From 0e8fd3398771da2f016d72830179507f3edda51b Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sat, 4 May 1996 07:50:46 +0000 Subject: Initial version imported to CVS (This used to be commit 291551d80711daab7b7581720bcd9a08d6096517) --- source3/smbd/chgpasswd.c | 376 ++++ source3/smbd/dir.c | 955 ++++++++++ source3/smbd/ipc.c | 2779 ++++++++++++++++++++++++++++++ source3/smbd/mangle.c | 610 +++++++ source3/smbd/message.c | 204 +++ source3/smbd/password.c | 1416 +++++++++++++++ source3/smbd/reply.c | 3210 ++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 4300 ++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/smbrun.c | 96 ++ source3/smbd/trans2.c | 1646 ++++++++++++++++++ source3/smbd/vt_mode.c | 496 ++++++ 11 files changed, 16088 insertions(+) create mode 100644 source3/smbd/chgpasswd.c create mode 100644 source3/smbd/dir.c create mode 100644 source3/smbd/ipc.c create mode 100644 source3/smbd/mangle.c create mode 100644 source3/smbd/message.c create mode 100644 source3/smbd/password.c create mode 100644 source3/smbd/reply.c create mode 100644 source3/smbd/server.c create mode 100644 source3/smbd/smbrun.c create mode 100644 source3/smbd/trans2.c create mode 100644 source3/smbd/vt_mode.c (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c new file mode 100644 index 0000000000..dc0514c1ed --- /dev/null +++ b/source3/smbd/chgpasswd.c @@ -0,0 +1,376 @@ +/* fork a child process to exec passwd and write to its +* tty to change a users password. This is running as the +* user who is attempting to change the password. +*/ + +/* + * This code was copied/borrowed and stolen from various sources. + * The primary source was the poppasswd.c from the authors of POPMail. This software + * was included as a client to change passwords using the 'passwd' program + * on the remote machine. + * + * This routine is called by set_user_password() in password.c only if ALLOW_PASSWORD_CHANGE + * is defined in the compiler directives located in the Makefile. + * + * This code has been hacked by Bob Nance (nance@niehs.nih.gov) and Evan Patterson + * (patters2@niehs.nih.gov) at the National Institute of Environmental Health Sciences + * and rights to modify, distribute or incorporate this change to the CAP suite or + * using it for any other reason are granted, so long as this disclaimer is left intact. + */ + +/* + This code was hacked considerably for inclusion in Samba, primarily + by Andrew.Tridgell@anu.edu.au. The biggest change was the addition + of the "password chat" option, which allows the easy runtime + specification of the expected sequence of events to change a + password. + */ + +#include "includes.h" +#include "loadparm.h" + +extern int DEBUGLEVEL; + +#ifdef ALLOW_CHANGE_PASSWORD + +#define MINPASSWDLENGTH 5 +#define BUFSIZE 512 + +static int findpty(char **slave) +{ + int master; +#ifdef SVR4 + extern char *ptsname(); +#else + static char line[12] = "/dev/ptyXX"; + void *dirp; + char *dpname; +#endif + +#ifdef SVR4 + if ((master = open("/dev/ptmx", O_RDWR)) >= 1) { + grantpt(master); + unlockpt(master); + *slave = ptsname(master); + return (master); + } +#else + dirp = OpenDir("/dev"); + if (!dirp) return(-1); + while ((dpname = ReadDirName(dirp)) != NULL) { + if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { + line[8] = dpname[3]; + line[9] = dpname[4]; + if ((master = open(line, O_RDWR)) >= 0) { + line[5] = 't'; + *slave = line; + CloseDir(dirp); + return (master); + } + } + } + CloseDir(dirp); +#endif + return (-1); +} + +static int dochild(int master,char *slavedev, char *name, char *passwordprogram) +{ + int slave; + struct termios stermios; + struct passwd *pass = Get_Pwnam(name,True); + int gid = pass->pw_gid; + int uid = pass->pw_uid; + +#ifdef USE_SETRES + setresuid(0,0,0); +#else + setuid(0); +#endif + + /* Start new session - gets rid of controlling terminal. */ + if (setsid() < 0) { + DEBUG(3,("Weirdness, couldn't let go of controlling terminal\n")); + return(False); + } + + /* Open slave pty and acquire as new controlling terminal. */ + if ((slave = open(slavedev, O_RDWR)) < 0) { + DEBUG(3,("More weirdness, could not open %s\n", + slavedev)); + return(False); + } +#ifdef SVR4 + ioctl(slave, I_PUSH, "ptem"); + ioctl(slave, I_PUSH, "ldterm"); +#else + if (ioctl(slave,TIOCSCTTY,0) <0) { + DEBUG(3,("Error in ioctl call for slave pty\n")); + /* return(False); */ + } +#endif + + /* Close master. */ + close(master); + + /* Make slave stdin/out/err of child. */ + + if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) { + DEBUG(3,("Could not re-direct stdin\n")); + return(False); + } + if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) { + DEBUG(3,("Could not re-direct stdout\n")); + return(False); + } + if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) { + DEBUG(3,("Could not re-direct stderr\n")); + return(False); + } + if (slave > 2) close(slave); + + /* Set proper terminal attributes - no echo, canonical input processing, + no map NL to CR/NL on output. */ + + if (tcgetattr(0, &stermios) < 0) { + DEBUG(3,("could not read default terminal attributes on pty\n")); + return(False); + } + stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); + stermios.c_lflag |= ICANON; + stermios.c_oflag &= ~(ONLCR); + if (tcsetattr(0, TCSANOW, &stermios) < 0) { + DEBUG(3,("could not set attributes of pty\n")); + return(False); + } + + /* make us completely into the right uid */ +#ifdef USE_SETRES + setresgid(0,0,0); + setresuid(0,0,0); + setresgid(gid,gid,gid); + setresuid(uid,uid,uid); +#else + setuid(0); + seteuid(0); + setgid(gid); + setegid(gid); + setuid(uid); + seteuid(uid); +#endif + + /* execl() password-change application */ + if (execl("/bin/sh","sh","-c",passwordprogram,NULL) < 0) { + DEBUG(3,("Bad status returned from %s\n",passwordprogram)); + return(False); + } + return(True); +} + +static int expect(int master,char *expected,char *buf) +{ + int n, m; + + n = 0; + buf[0] = 0; + while (1) { + if (n >= BUFSIZE-1) { + return False; + } + + /* allow 4 seconds for some output to appear */ + m = read_with_timeout(master, buf+n, 1, BUFSIZE-1-n, 4000, True); + if (m < 0) + return False; + + n += m; + buf[n] = 0; + + { + pstring s1,s2; + strcpy(s1,buf); + strcpy(s2,expected); + if (do_match(s1, s2, False)) + return(True); + } + } +} + +static void pwd_sub(char *buf) +{ + string_sub(buf,"\\n","\n"); + string_sub(buf,"\\r","\r"); + string_sub(buf,"\\s"," "); + string_sub(buf,"\\t","\t"); +} + +static void writestring(int fd,char *s) +{ + int l; + + l = strlen (s); + write (fd, s, l); +} + + +static int talktochild(int master, char *chatsequence) +{ + char buf[BUFSIZE]; + int count=0; + char *ptr=chatsequence; + fstring chatbuf; + + *buf = 0; + sleep(1); + + while (next_token(&ptr,chatbuf,NULL)) { + BOOL ok=True; + count++; + pwd_sub(chatbuf); + if (!strequal(chatbuf,".")) + ok = expect(master,chatbuf,buf); + +#if DEBUG_PASSWORD + DEBUG(100,("chatbuf=[%s] responsebuf=[%s]\n",chatbuf,buf)); +#endif + + if (!ok) { + DEBUG(3,("response %d incorrect\n",count)); + return(False); + } + + if (!next_token(&ptr,chatbuf,NULL)) break; + pwd_sub(chatbuf); + if (!strequal(chatbuf,".")) + writestring(master,chatbuf); + +#if DEBUG_PASSWORD + DEBUG(100,("sendbuf=[%s]\n",chatbuf)); +#endif + } + + if (count<1) return(False); + + return (True); +} + + +BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence) +{ + char *slavedev; + int master; + pid_t pid, wpid; + int wstat; + BOOL chstat; + + /* allocate a pseudo-terminal device */ + if ((master = findpty (&slavedev)) < 0) { + DEBUG(3,("Cannot Allocate pty for password change: %s",name)); + return(False); + } + + if ((pid = fork()) < 0) { + DEBUG(3,("Cannot fork() child for password change: %s",name)); + return(False); + } + + /* we now have a pty */ + if (pid > 0){ /* This is the parent process */ + if ((chstat = talktochild(master, chatsequence)) == False) { + DEBUG(3,("Child failed to change password: %s\n",name)); + kill(pid, SIGKILL); /* be sure to end this process */ + return(False); + } + if ((wpid = waitpid(pid, &wstat, 0)) < 0) { + DEBUG(3,("The process is no longer waiting!\n\n")); + return(False); + } + if (pid != wpid) { + DEBUG(3,("We were waiting for the wrong process ID\n")); + return(False); + } + if (WIFEXITED(wstat) == 0) { + DEBUG(3,("The process exited while we were waiting\n")); + return(False); + } + if (WEXITSTATUS(wstat) != 0) { + DEBUG(3,("The status of the process exiting was %d\n", wstat)); + return(False); + } + + } else { + /* CHILD */ + + /* make sure it doesn't freeze */ + alarm(20); + + DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,getuid(),getgid())); + chstat = dochild(master, slavedev, name, passwordprogram); + } + DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); + return (chstat); +} + + +BOOL chgpasswd(char *name,char *oldpass,char *newpass) +{ + pstring passwordprogram; + pstring chatsequence; + + strlower(name); + DEBUG(3,("Password change for user: %s\n",name)); + +#if DEBUG_PASSWORD + DEBUG(100,("Passwords: old=%s new=%s\n",oldpass,newpass)); +#endif + + /* Take the passed information and test it for minimum criteria */ + /* Minimum password length */ + if (strlen(newpass) < MINPASSWDLENGTH) /* too short, must be at least MINPASSWDLENGTH */ + { + DEBUG(2,("Password Change: %s, New password is shorter than MINPASSWDLENGTH\n",name)); + return (False); /* inform the user */ + } + + /* Password is same as old password */ + if (strcmp(oldpass,newpass) == 0) /* don't allow same password */ + { + DEBUG(2,("Password Change: %s, New password is same as old\n",name)); /* log the attempt */ + return (False); /* inform the user */ + } + +#if (defined(PASSWD_PROGRAM) && defined(PASSWD_CHAT)) + strcpy(passwordprogram,PASSWD_PROGRAM); + strcpy(chatsequence,PASSWD_CHAT); +#else + strcpy(passwordprogram,lp_passwd_program()); + strcpy(chatsequence,lp_passwd_chat()); +#endif + + if (!*chatsequence) { + DEBUG(2,("Null chat sequence - no password changing\n")); + return(False); + } + + if (!*passwordprogram) { + DEBUG(2,("Null password program - no password changing\n")); + return(False); + } + + string_sub(passwordprogram,"%u",name); + string_sub(passwordprogram,"%o",oldpass); + string_sub(passwordprogram,"%n",newpass); + + string_sub(chatsequence,"%u",name); + string_sub(chatsequence,"%o",oldpass); + string_sub(chatsequence,"%n",newpass); + return(chat_with_program(passwordprogram,name,chatsequence)); +} + +#else +BOOL chgpasswd(char *name,char *oldpass,char *newpass) +{ + DEBUG(0,("Password changing not compiled in (user=%s)\n",name)); + return(False); +} +#endif diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c new file mode 100644 index 0000000000..ac6f918b9d --- /dev/null +++ b/source3/smbd/dir.c @@ -0,0 +1,955 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Directory handling routines + 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[]; + +/* + This module implements directory related functions for Samba. +*/ + + + +uint32 dircounter = 0; + + +#define NUMDIRPTRS 256 + + +static struct dptr_struct +{ + int pid; + int cnum; + uint32 lastused; + void *ptr; + BOOL valid; + BOOL finished; + BOOL expect_close; + char *wcard; /* Field only used for lanman2 trans2_findfirst/next searches */ + uint16 attr; /* Field only used for lanman2 trans2_findfirst/next searches */ + char *path; +} +dirptrs[NUMDIRPTRS]; + + +static int dptrs_open = 0; + +/**************************************************************************** +initialise the dir array +****************************************************************************/ +void init_dptrs(void) +{ + static BOOL dptrs_init=False; + int i; + + if (dptrs_init) return; + for (i=0;i= MAXDIR) + dptr_idleoldest(); + DEBUG(4,("Reopening dptr key %d\n",key)); + if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path))) + dptrs_open++; + } + return(dirptrs[key].ptr); + } + return(NULL); +} + +/**************************************************************************** +get the dir path for a dir index +****************************************************************************/ +char *dptr_path(int key) +{ + if (dirptrs[key].valid) + return(dirptrs[key].path); + return(NULL); +} + +/**************************************************************************** +get the dir wcard for a dir index (lanman2 specific) +****************************************************************************/ +char *dptr_wcard(int key) +{ + if (dirptrs[key].valid) + return(dirptrs[key].wcard); + return(NULL); +} + +/**************************************************************************** +set the dir wcard for a dir index (lanman2 specific) +Returns 0 on ok, 1 on fail. +****************************************************************************/ +BOOL dptr_set_wcard(int key, char *wcard) +{ + if (dirptrs[key].valid) { + dirptrs[key].wcard = wcard; + return True; + } + return False; +} + +/**************************************************************************** +set the dir attrib for a dir index (lanman2 specific) +Returns 0 on ok, 1 on fail. +****************************************************************************/ +BOOL dptr_set_attr(int key, uint16 attr) +{ + if (dirptrs[key].valid) { + dirptrs[key].attr = attr; + return True; + } + return False; +} + +/**************************************************************************** +get the dir attrib for a dir index (lanman2 specific) +****************************************************************************/ +uint16 dptr_attr(int key) +{ + if (dirptrs[key].valid) + return(dirptrs[key].attr); + return(0); +} + +/**************************************************************************** +close a dptr +****************************************************************************/ +void dptr_close(int key) +{ + if (dirptrs[key].valid) { + DEBUG(4,("closing dptr key %d\n",key)); + if (dirptrs[key].ptr) { + CloseDir(dirptrs[key].ptr); + dptrs_open--; + } + /* Lanman 2 specific code */ + if (dirptrs[key].wcard) + free(dirptrs[key].wcard); + dirptrs[key].valid = False; + string_set(&dirptrs[key].path,""); + } +} + +/**************************************************************************** +close all dptrs for a cnum +****************************************************************************/ +void dptr_closecnum(int cnum) +{ + int i; + for (i=0;i= MAXDIR) + dptr_idleoldest(); + + for (i=0;ipos = dirp->numentries = dirp->mallocsize = 0; + dirp->data = dirp->current = NULL; + + while ((n = readdirname(p))) { + int l = strlen(n)+1; + if (used + l > dirp->mallocsize) { + int s = MAX(used+l,used+2000); + char *r; + r = (char *)Realloc(dirp->data,s); + if (!r) { + DEBUG(0,("Out of memory in OpenDir\n")); + break; + } + dirp->data = r; + dirp->mallocsize = s; + dirp->current = dirp->data; + } + strcpy(dirp->data+used,n); + used += l; + dirp->numentries++; + } + + closedir(p); + return((void *)dirp); +} + + +/******************************************************************* +close a directory +********************************************************************/ +void CloseDir(void *p) +{ + Dir *dirp = (Dir *)p; + if (!dirp) return; + if (dirp->data) free(dirp->data); + free(dirp); +} + +/******************************************************************* +read from a directory +********************************************************************/ +char *ReadDirName(void *p) +{ + char *ret; + Dir *dirp = (Dir *)p; + + if (!dirp || !dirp->current || dirp->pos >= dirp->numentries) return(NULL); + + ret = dirp->current; + dirp->current = skip_string(dirp->current,1); + dirp->pos++; + + return(ret); +} + + +/******************************************************************* +seek a dir +********************************************************************/ +BOOL SeekDir(void *p,int pos) +{ + Dir *dirp = (Dir *)p; + + if (!dirp) return(False); + + if (pos < dirp->pos) { + dirp->current = dirp->data; + dirp->pos = 0; + } + + while (dirp->pos < pos && ReadDirName(p)) ; + + return(dirp->pos == pos); +} + +/******************************************************************* +tell a dir position +********************************************************************/ +int TellDir(void *p) +{ + Dir *dirp = (Dir *)p; + + if (!dirp) return(-1); + + return(dirp->pos); +} + + +static int dir_cache_size = 0; +static struct dir_cache { + struct dir_cache *next; + struct dir_cache *prev; + char *path; + char *name; + char *dname; + int snum; +} *dir_cache = NULL; + +/******************************************************************* +add an entry to the directory cache +********************************************************************/ +void DirCacheAdd(char *path,char *name,char *dname,int snum) +{ + struct dir_cache *entry = (struct dir_cache *)malloc(sizeof(*entry)); + if (!entry) return; + entry->path = strdup(path); + entry->name = strdup(name); + entry->dname = strdup(dname); + entry->snum = snum; + if (!entry->path || !entry->name || !entry->dname) return; + + entry->next = dir_cache; + entry->prev = NULL; + if (entry->next) entry->next->prev = entry; + dir_cache = entry; + + DEBUG(4,("Added dir cache entry %s %s -> %s\n",path,name,dname)); + + if (dir_cache_size == DIRCACHESIZE) { + for (entry=dir_cache; entry->next; entry=entry->next) ; + free(entry->path); + free(entry->name); + free(entry->dname); + if (entry->prev) entry->prev->next = entry->next; + free(entry); + } else { + dir_cache_size++; + } +} + + +/******************************************************************* +check for an entry in the directory cache +********************************************************************/ +char *DirCacheCheck(char *path,char *name,int snum) +{ + struct dir_cache *entry; + + for (entry=dir_cache; entry; entry=entry->next) { + if (entry->snum == snum && + strcmp(path,entry->path) == 0 && + strcmp(name,entry->name) == 0) { + DEBUG(4,("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); + return(entry->dname); + } + } + + return(NULL); +} + +/******************************************************************* +flush entries in the dir_cache +********************************************************************/ +void DirCacheFlush(int snum) +{ + struct dir_cache *entry,*next; + + for (entry=dir_cache; entry; entry=next) { + if (entry->snum == snum) { + free(entry->path); + free(entry->dname); + free(entry->name); + next = entry->next; + if (entry->prev) entry->prev->next = entry->next; + if (entry->next) entry->next->prev = entry->prev; + if (dir_cache == entry) dir_cache = entry->next; + free(entry); + } else { + next = entry->next; + } + } +} + + +#ifdef REPLACE_GETWD +/* This is getcwd.c from bash. It is needed in Interactive UNIX. To + * add support for another OS you need to determine which of the + * conditional compilation macros you need to define. All the options + * are defined for Interactive UNIX. + */ +#ifdef ISC +#define HAVE_UNISTD_H +#define USGr3 +#define USG +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (__STDC__) +# define CONST const +# define PTR void * +#else /* !__STDC__ */ +# define CONST +# define PTR char * +#endif /* !__STDC__ */ + +#if !defined (PATH_MAX) +# if defined (MAXPATHLEN) +# define PATH_MAX MAXPATHLEN +# else /* !MAXPATHLEN */ +# define PATH_MAX 1024 +# endif /* !MAXPATHLEN */ +#endif /* !PATH_MAX */ + +#if defined (_POSIX_VERSION) || defined (USGr3) || defined (HAVE_DIRENT_H) +# if !defined (HAVE_DIRENT) +# define HAVE_DIRENT +# endif /* !HAVE_DIRENT */ +#endif /* _POSIX_VERSION || USGr3 || HAVE_DIRENT_H */ + +#if defined (HAVE_DIRENT) +# define D_NAMLEN(d) (strlen ((d)->d_name)) +#else +# define D_NAMLEN(d) ((d)->d_namlen) +#endif /* ! (_POSIX_VERSION || USGr3) */ + +#if defined (USG) || defined (USGr3) +# define d_fileno d_ino +#endif + +#if !defined (alloca) +extern char *alloca (); +#endif /* alloca */ + +/* Get the pathname of the current working directory, + and put it in SIZE bytes of BUF. Returns NULL if the + directory couldn't be determined or SIZE was too small. + If successful, returns BUF. In GNU, if BUF is NULL, + an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE <= 0, in which case it is as + big as necessary. */ +#if defined (__STDC__) +char * +getcwd (char *buf, size_t size) +#else /* !__STDC__ */ +char * +getcwd (buf, size) + char *buf; + int size; +#endif /* !__STDC__ */ +{ + static CONST char dots[] + = "../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../.."; + CONST char *dotp, *dotlist; + size_t dotsize; + dev_t rootdev, thisdev; + ino_t rootino, thisino; + char path[PATH_MAX + 1]; + register char *pathp; + char *pathbuf; + size_t pathsize; + struct stat st; + + if (buf != NULL && size == 0) + { + errno = EINVAL; + return ((char *)NULL); + } + + pathsize = sizeof (path); + pathp = &path[pathsize]; + *--pathp = '\0'; + pathbuf = path; + + if (stat (".", &st) < 0) + return ((char *)NULL); + thisdev = st.st_dev; + thisino = st.st_ino; + + if (stat ("/", &st) < 0) + return ((char *)NULL); + rootdev = st.st_dev; + rootino = st.st_ino; + + dotsize = sizeof (dots) - 1; + dotp = &dots[sizeof (dots)]; + dotlist = dots; + while (!(thisdev == rootdev && thisino == rootino)) + { + register DIR *dirstream; + register struct dirent *d; + dev_t dotdev; + ino_t dotino; + char mount_point; + int namlen; + + /* Look at the parent directory. */ + if (dotp == dotlist) + { + /* My, what a deep directory tree you have, Grandma. */ + char *new; + if (dotlist == dots) + { + new = malloc (dotsize * 2 + 1); + if (new == NULL) + goto lose; + memcpy (new, dots, dotsize); + } + else + { + new = realloc ((PTR) dotlist, dotsize * 2 + 1); + if (new == NULL) + goto lose; + } + memcpy (&new[dotsize], new, dotsize); + dotp = &new[dotsize]; + dotsize *= 2; + new[dotsize] = '\0'; + dotlist = new; + } + + dotp -= 3; + + /* Figure out if this directory is a mount point. */ + if (stat (dotp, &st) < 0) + goto lose; + dotdev = st.st_dev; + dotino = st.st_ino; + mount_point = dotdev != thisdev; + + /* Search for the last directory. */ + dirstream = opendir(dotp); + if (dirstream == NULL) + goto lose; + while ((d = (struct dirent *)readdir(dirstream)) != NULL) + { + if (d->d_name[0] == '.' && + (d->d_name[1] == '\0' || + (d->d_name[1] == '.' && d->d_name[2] == '\0'))) + continue; + if (mount_point || d->d_fileno == thisino) + { + char *name; + + namlen = D_NAMLEN(d); + name = (char *) + alloca (dotlist + dotsize - dotp + 1 + namlen + 1); + memcpy (name, dotp, dotlist + dotsize - dotp); + name[dotlist + dotsize - dotp] = '/'; + memcpy (&name[dotlist + dotsize - dotp + 1], + d->d_name, namlen + 1); + if (lstat (name, &st) < 0) + { + int save = errno; + closedir(dirstream); + errno = save; + goto lose; + } + if (st.st_dev == thisdev && st.st_ino == thisino) + break; + } + } + if (d == NULL) + { + int save = errno; + closedir(dirstream); + errno = save; + goto lose; + } + else + { + size_t space; + + while ((space = pathp - pathbuf) <= namlen) + { + char *new; + + if (pathbuf == path) + { + new = malloc (pathsize * 2); + if (!new) + goto lose; + } + else + { + new = realloc ((PTR) pathbuf, (pathsize * 2)); + if (!new) + goto lose; + pathp = new + space; + } + (void) memcpy (new + pathsize + space, pathp, pathsize - space); + pathp = new + pathsize + space; + pathbuf = new; + pathsize *= 2; + } + + pathp -= namlen; + (void) memcpy (pathp, d->d_name, namlen); + *--pathp = '/'; + closedir(dirstream); + } + + thisdev = dotdev; + thisino = dotino; + } + + if (pathp == &path[sizeof(path) - 1]) + *--pathp = '/'; + + if (dotlist != dots) + free ((PTR) dotlist); + + { + size_t len = pathbuf + pathsize - pathp; + if (buf == NULL) + { + if (len < (size_t) size) + len = size; + buf = (char *) malloc (len); + if (buf == NULL) + goto lose2; + } + else if ((size_t) size < len) + { + errno = ERANGE; + goto lose2; + } + (void) memcpy((PTR) buf, (PTR) pathp, len); + } + + if (pathbuf != path) + free (pathbuf); + + return (buf); + + lose: + if ((dotlist != dots) && dotlist) + { + int e = errno; + free ((PTR) dotlist); + errno = e; + } + + lose2: + if ((pathbuf != path) && pathbuf) + { + int e = errno; + free ((PTR) pathbuf); + errno = e; + } + return ((char *)NULL); +} +#endif diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c new file mode 100644 index 0000000000..8852e57e8b --- /dev/null +++ b/source3/smbd/ipc.c @@ -0,0 +1,2779 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Inter-process communication and named pipe 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. + */ +/* + This file handles the named pipe and mailslot calls + in the SMBtrans protocol + */ + +#include "includes.h" +#include "loadparm.h" +#include "pcap.h" + +#ifdef CHECK_TYPES +#undef CHECK_TYPES +#endif +#define CHECK_TYPES 0 + +extern int DEBUGLEVEL; +extern int maxxmit; +extern files_struct Files[]; +extern connection_struct Connections[]; + +extern fstring local_machine; + +#define NERR_Success 0 +#define NERR_badpass 86 +#define NERR_notsupported 50 + +#define NERR_BASE (2100) +#define NERR_BufTooSmall (NERR_BASE+23) +#define NERR_JobNotFound (NERR_BASE+51) +#define NERR_DestNotFound (NERR_BASE+52) +#define ERROR_INVALID_LEVEL 124 +#define ERROR_MORE_DATA 234 + +#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024)) + +#define ACCESS_READ 0x01 +#define ACCESS_WRITE 0x02 +#define ACCESS_CREATE 0x04 + +#define SHPWLEN 8 /* share password length */ +#define NNLEN 12 /* 8.3 net name length */ +#define SNLEN 15 /* service name length */ +#define QNLEN 12 /* queue name maximum length */ + +extern int Client; + +static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) +{ + pstring buf; + int l; + + if (!src || !dst || !n || !(*dst)) return(0); + + StrnCpy(buf,src,sizeof(buf)/2); + string_sub(buf,"%S",lp_servicename(snum)); + standard_sub(cnum,buf); + StrnCpy(*dst,buf,*n); + l = strlen(*dst) + 1; + (*dst) += l; + (*n) -= l; + return l; +} + +static int CopyAndAdvance(char** dst, char* src, int* n) +{ + int l; + if (!src || !dst || !n || !(*dst)) return(0); + StrnCpy(*dst,src,*n); + l = strlen(*dst) + 1; + (*dst) += l; + (*n) -= l; + return l; +} + +static int StrlenExpanded(int cnum, int snum, char* s) +{ + pstring buf; + if (!s) return(0); + StrnCpy(buf,s,sizeof(buf)/2); + string_sub(buf,"%S",lp_servicename(snum)); + standard_sub(cnum,buf); + return strlen(buf) + 1; +} + +static char* Expand(int cnum, int snum, char* s) +{ + static pstring buf; + if (!s) return(NULL); + StrnCpy(buf,s,sizeof(buf)/2); + string_sub(buf,"%S",lp_servicename(snum)); + standard_sub(cnum,buf); + return &buf[0]; +} + +/******************************************************************* + check a API string for validity when we only need to check the prefix + ******************************************************************/ +static BOOL prefix_ok(char *str,char *prefix) +{ + return(strncmp(str,prefix,strlen(prefix)) == 0); +} + + +/**************************************************************************** + send a trans reply + ****************************************************************************/ +static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, + int ldata,int lparam,int lsetup) +{ + int i; + int this_ldata,this_lparam; + int tot_data=0,tot_param=0; + int align; + + this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */ + this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam)); + + align = (this_lparam%4); + + set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); + if (this_lparam) + memcpy(smb_buf(outbuf),param,this_lparam); + if (this_ldata) + memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata); + + SSVAL(outbuf,smb_vwv0,lparam); + SSVAL(outbuf,smb_vwv1,ldata); + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); + SSVAL(outbuf,smb_vwv5,0); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,0); + SSVAL(outbuf,smb_vwv9,lsetup); + for (i=0;ibuflen; + int i; + + if (!p->format || !p->base) return(False); + + i = count * getlen(p->format); + if (p->subformat) i += subcount * getlen(p->subformat); + p->structbuf = p->base; + p->neededlen = 0; + p->usedlen = 0; + p->subcount = 0; + p->curpos = p->format; + if (i > n) { + i = n = 0; + p->errcode = NERR_BufTooSmall; + } + + p->errcode = NERR_Success; + p->buflen = i; + n -= i; + p->stringbuf = p->base + i; + p->stringlen = n; + return(p->errcode == NERR_Success); +} + +#ifdef __STDC__ +static int package(struct pack_desc* p, ...) +{ +#else +static int package(va_alist) +va_dcl +{ + struct pack_desc* p; +#endif + va_list args; + int needed=0, stringneeded; + char* str=NULL; + int is_string=0, stringused; + int32 temp; + +#ifdef __STDC__ + va_start(args,p); +#else + va_start(args); + p = va_arg(args,struct pack_desc *); +#endif + + if (!*p->curpos) { + if (!p->subcount) + p->curpos = p->format; + else { + p->curpos = p->subformat; + p->subcount--; + } + } +#if CHECK_TYPES + str = va_arg(args,char*); + if (strncmp(str,p->curpos,strlen(str)) != 0) { + DEBUG(2,("type error in package: %s instead of %*s\n",str, + strlen(str),p->curpos)); + va_end(args); +#if AJT + ajt_panic(); +#endif + return 0; + } +#endif + stringneeded = -1; + + if (!p->curpos) return(0); + + switch( *p->curpos++ ) { + case 'W': /* word (2 byte) */ + needed = 2; + temp = va_arg(args,int); + if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); + break; + case 'N': /* count of substructures (word) at end */ + needed = 2; + p->subcount = va_arg(args,int); + if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount); + break; + case 'D': /* double word (4 byte) */ + needed = 4; + temp = va_arg(args,int); + if (p->buflen >= needed) SIVAL(p->structbuf,0,temp); + break; + case 'B': /* byte (with optional counter) */ + needed = get_counter(&p->curpos); + { + char *s = va_arg(args,char*); + if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed); + } + break; + case 'z': /* offset to zero terminated string (4 byte) */ + str = va_arg(args,char*); + stringneeded = (str ? strlen(str)+1 : 0); + is_string = 1; + break; + case 'l': /* offset to user data (4 byte) */ + str = va_arg(args,char*); + stringneeded = va_arg(args,int); + is_string = 0; + break; + case 'b': /* offset to data (with counter) (4 byte) */ + str = va_arg(args,char*); + stringneeded = get_counter(&p->curpos); + is_string = 0; + break; + } + va_end(args); + if (stringneeded >= 0) { + needed = 4; + if (p->buflen >= needed) { + stringused = stringneeded; + if (stringused > p->stringlen) { + stringused = (is_string ? p->stringlen : 0); + if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA; + } + if (!stringused) + SIVAL(p->structbuf,0,0); + else { + SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); + memcpy(p->stringbuf,str?str:"",stringused); + if (is_string) p->stringbuf[stringused-1] = '\0'; + p->stringbuf += stringused; + p->stringlen -= stringused; + p->usedlen += stringused; + } + } + p->neededlen += stringneeded; + } + p->neededlen += needed; + if (p->buflen >= needed) { + p->structbuf += needed; + p->buflen -= needed; + p->usedlen += needed; + } + else { + if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall; + } + return 1; +} + +#if CHECK_TYPES +#define PACK(desc,t,v) package(desc,t,v,0,0,0,0) +#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0) +#else +#define PACK(desc,t,v) package(desc,v) +#define PACKl(desc,t,v,l) package(desc,v,l) +#endif + +static void PACKI(struct pack_desc* desc,char *t,int v) +{ + PACK(desc,t,v); +} + +static void PACKS(struct pack_desc* desc,char *t,char *v) +{ + PACK(desc,t,v); +} + +static void PackDriverData(struct pack_desc* desc) +{ + char drivdata[4+4+32]; + SIVAL(drivdata,0,sizeof drivdata); /* cb */ + SIVAL(drivdata,4,1000); /* lVersion */ + memset(drivdata+8,0,32); /* szDeviceName */ + strcpy(drivdata+8,"NULL"); + PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ +} + +static int check_printq_info(struct pack_desc* desc, + int uLevel, const char* id1, const char* id2) +{ + desc->subformat = NULL; + switch( uLevel ) { + case 0: + desc->format = "B13"; + break; + case 1: + desc->format = "B13BWWWzzzzzWW"; + break; + case 2: + desc->format = "B13BWWWzzzzzWN"; + desc->subformat = "WB21BB16B10zWWzDDz"; + break; + case 3: + desc->format = "zWWWWzzzzWWzzl"; + break; + case 4: + desc->format = "zWWWWzzzzWNzzl"; + desc->subformat = "WWzWWDDzz"; + break; + case 5: + desc->format = "z"; + break; + default: return False; + } + if (strcmp(desc->format,id1) != 0) return False; + if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False; + return True; +} + +static void fill_printjob_info(int cnum, int snum, int uLevel, + struct pack_desc* desc, + print_queue_struct* queue, int n) +{ + time_t t = queue->time; + + /* the client expects localtime */ + t += GMT_TO_LOCAL*TimeDiff(t); + + PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */ + if (uLevel == 1) { + PACKS(desc,"B21",queue->user); /* szUserName */ + PACKS(desc,"B",""); /* pad */ + PACKS(desc,"B16",""); /* szNotifyName */ + PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ + PACKS(desc,"z",""); /* pszParms */ + PACKI(desc,"W",n+1); /* uPosition */ + PACKI(desc,"W",queue->status); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",queue->time); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z",queue->file); /* pszComment */ + } + if (uLevel == 2 || uLevel == 3) { + PACKI(desc,"W",queue->priority); /* uPriority */ + PACKS(desc,"z",queue->user); /* pszUserName */ + PACKI(desc,"W",n+1); /* uPosition */ + PACKI(desc,"W",queue->status); /* fsStatus */ + PACKI(desc,"D",queue->time); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z","Samba"); /* pszComment */ + PACKS(desc,"z",queue->file); /* pszDocument */ + if (uLevel == 3) { + PACKS(desc,"z",""); /* pszNotifyName */ + PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ + PACKS(desc,"z",""); /* pszParms */ + PACKS(desc,"z",""); /* pszStatus */ + PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ + PACKS(desc,"z","lpd"); /* pszQProcName */ + PACKS(desc,"z",""); /* pszQProcParms */ + PACKS(desc,"z","NULL"); /* pszDriverName */ + PackDriverData(desc); /* pDriverData */ + PACKS(desc,"z",""); /* pszPrinterName */ + } + } +} + +static void fill_printq_info(int cnum, int snum, int uLevel, + struct pack_desc* desc, + int count, print_queue_struct* queue, + print_status_struct* status) +{ + if (uLevel < 3) { + PACKS(desc,"B13",SERVICE(snum)); + } else { + PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum))); + } + if (uLevel == 1 || uLevel == 2) { + PACKS(desc,"B",""); /* alignment */ + PACKI(desc,"W",5); /* priority */ + PACKI(desc,"W",0); /* start time */ + PACKI(desc,"W",0); /* until time */ + PACKS(desc,"z",""); /* pSepFile */ + PACKS(desc,"z","lpd"); /* pPrProc */ + PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ + PACKS(desc,"z",""); /* pParms */ + if (snum < 0) { + PACKS(desc,"z","UNKNOWN PRINTER"); + PACKI(desc,"W",LPSTAT_ERROR); + } + else if (!status || !status->message[0]) { + PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); + PACKI(desc,"W",LPSTAT_OK); /* status */ + } else { + PACKS(desc,"z",status->message); + PACKI(desc,"W",status->status); /* status */ + } + PACKI(desc,(uLevel == 1 ? "W" : "N"),count); + } + if (uLevel == 3 || uLevel == 4) { + PACKI(desc,"W",5); /* uPriority */ + PACKI(desc,"W",0); /* uStarttime */ + PACKI(desc,"W",0); /* uUntiltime */ + PACKI(desc,"W",5); /* pad1 */ + PACKS(desc,"z",""); /* pszSepFile */ + PACKS(desc,"z","lpd"); /* pszPrProc */ + PACKS(desc,"z",""); /* pszParms */ + if (!status || !status->message[0]) { + PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */ + PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ + } else { + PACKS(desc,"z",status->message); /* pszComment */ + PACKI(desc,"W",status->status); /* fsStatus */ + } + PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ + PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ + PACKS(desc,"z","NULL"); /* pszDriverName */ + PackDriverData(desc); /* pDriverData */ + } + if (uLevel == 2 || uLevel == 4) { + int i; + for (i=0;i gave %d entries\n",SERVICE(snum),count)); +} + +static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char *QueueName = p; + int uLevel,cbBuf; + int count=0; + int snum; + char* str3; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + + bzero(&status,sizeof(status)); + bzero(&desc,sizeof(desc)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + cbBuf = SVAL(p,2); + str3 = p + 4; + + if ((p = strchr(QueueName,'%'))) *p = 0; + + DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName)); + + /* check it's a supported varient */ + if (!prefix_ok(str1,"zWrLh")) return False; + if (!check_printq_info(&desc,uLevel,str2,str3)) return False; + + snum = lp_servicenumber(QueueName); + if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { + int pnum = lp_servicenumber(PRINTERS_NAME); + if (pnum >= 0) { + lp_add_printer(QueueName,pnum); + snum = lp_servicenumber(QueueName); + } + } + + if (snum < 0 || !VALID_SNUM(snum)) return(False); + + count = get_printqueue(snum,cnum,&queue,&status); + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,count)) { + desc.subcount = count; + fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status); + } + + *rdata_len = desc.usedlen; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); + + if (queue) free(queue); + + return(True); +} + + +/**************************************************************************** + view list of all print jobs on all queues + ****************************************************************************/ +static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data, + int mdrcnt, int mprcnt, + char **rdata, char** rparam, + int *rdata_len, int *rparam_len) +{ + char *param_format = param+2; + char *output_format1 = skip_string(param_format,1); + char *p = skip_string(output_format1,1); + int uLevel = SVAL(p,0); + char *output_format2 = p + 4; + int services = lp_numservices(); + int i, n; + struct pack_desc desc; + print_queue_struct **queue = NULL; + print_status_struct *status = NULL; + int* subcntarr = NULL; + int queuecnt, subcnt=0, succnt=0; + + bzero(&desc,sizeof(desc)); + + DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); + + if (prefix_ok(param_format,"WrLeh")) return False; + if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) + return False; + queuecnt = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) + queuecnt++; + if (uLevel > 0) { + queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*)); + memset(queue,0,queuecnt*sizeof(print_queue_struct*)); + status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct)); + memset(status,0,queuecnt*sizeof(print_status_struct)); + subcntarr = (int*)malloc(queuecnt*sizeof(int)); + subcnt = 0; + n = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]); + subcnt += subcntarr[n]; + n++; + } + } + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,queuecnt,subcnt)) { + n = 0; + succnt = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); + n++; + if (desc.errcode == NERR_Success) succnt = n; + } + } + + if (subcntarr) free(subcntarr); + + *rdata_len = desc.usedlen; + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,queuecnt); + + for (i = 0; i < queuecnt; i++) { + if (queue && queue[i]) free(queue[i]); + } + + if (queue) free(queue); + if (status) free(status); + + return True; +} + +/**************************************************************************** + get info level for a server list query + ****************************************************************************/ +static BOOL check_server_info(int uLevel, char* id) +{ + switch( uLevel ) { + case 0: + if (strcmp(id,"B16") != 0) return False; + break; + case 1: + if (strcmp(id,"B16BBDz") != 0) return False; + break; + default: + return False; + } + return True; +} + +/* used for server information: client, nameserv and ipc */ +struct srv_info_struct +{ + fstring name; + uint32 type; + fstring comment; + fstring domain; /* used ONLY in ipc.c NOT namework.c */ + BOOL server_added; /* used ONLY in ipc.c NOT namework.c */ +}; + +/******************************************************************* + filter out unwanted server info + ******************************************************************/ +static BOOL filter_server_info(struct srv_info_struct *server, + char *domain) +{ + 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); + } + } + 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) +{ + FILE *f; + pstring fname; + int count=0; + int alloced=0; + pstring line; + + strcpy(fname,lp_lockdir()); + trim_string(fname,NULL,"/"); + strcat(fname,"/"); + strcat(fname,SERVER_LIST); + + f = fopen(fname,"r"); + + if (!f) { + DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno))); + return(0); + } + if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM; + + while (!feof(f)) + { + fstring stype; + struct srv_info_struct *s; + char *ptr = line; + *ptr = 0; + + fgets(line,sizeof(line)-1,f); + if (!*line) continue; + + if (count == alloced) { + alloced += 10; + (*servers) = (struct srv_info_struct *) + Realloc(*servers,sizeof(**servers)*alloced); + if (!(*servers)) return(0); + 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 */ + strcpy(s->domain,my_workgroup()); + } + + if (sscanf(stype,"%X",&s->type) != 1) continue; + + /* 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++; + } + + fclose(f); + return(count); +} + +/******************************************************************* + fill in a server info structure + ******************************************************************/ +static int fill_srv_info(struct srv_info_struct *service, + int uLevel, char **buf, int *buflen, + char **stringbuf, int *stringspace, char *baseaddr) +{ + int struct_len; + char* p; + char* p2; + int l2; + int len; + + switch (uLevel) { + case 0: struct_len = 16; break; + case 1: struct_len = 26; break; + default: return -1; + } + + if (!buf) + { + len = 0; + switch (uLevel) + { + case 1: + len = strlen(service->comment)+1; + break; + } + + if (buflen) *buflen = struct_len; + if (stringspace) *stringspace = len; + return struct_len + len; + } + + len = struct_len; + p = *buf; + if (*buflen < struct_len) return -1; + if (stringbuf) + { + p2 = *stringbuf; + l2 = *stringspace; + } + else + { + p2 = p + struct_len; + l2 = *buflen - struct_len; + } + if (!baseaddr) baseaddr = p; + + switch (uLevel) + { + case 0: + StrnCpy(p,service->name,15); + break; + + case 1: + StrnCpy(p,service->name,15); + SIVAL(p,18,service->type); + SIVAL(p,22,PTR_DIFF(p2,baseaddr)); + len += CopyAndAdvance(&p2,service->comment,&l2); + break; + } + + if (stringbuf) + { + *buf = p + struct_len; + *buflen -= struct_len; + *stringbuf = p2; + *stringspace = l2; + } + else + { + *buf = p2; + *buflen -= len; + } + return len; +} + + +/**************************************************************************** + view list of servers available (or possibly domains). The info is + extracted from lists saved by nmbd on the local host + ****************************************************************************/ +static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + uint32 servertype = IVAL(p,4); + char *p2; + int data_len, fixed_len, string_len; + int f_len, s_len; + struct srv_info_struct *servers=NULL; + int counted=0,total=0; + int i; + fstring domain; + BOOL domain_request = (servertype & SV_TYPE_DOMAIN_ENUM) && + !(servertype == SV_TYPE_ALL); + + domain[0] = 0; + p += 8; + + if (!prefix_ok(str1,"WrLehD")) return False; + if (!check_server_info(uLevel,str2)) return False; + + DEBUG(4, ("server request level: %s\n", str2)); + + 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 */ + } + else if (strcmp(str1, "WrLehDz") == 0) + { + /* asking for a specific workgroup */ + 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()); + } + } + + data_len = fixed_len = string_len = 0; + + for (i=0;i 0) len += StrlenExpanded(cnum,snum,lp_comment(snum)); + if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; + if (buflen) *buflen = struct_len; + if (stringspace) *stringspace = len; + return struct_len + len; + } + + len = struct_len; + p = *buf; + if ((*buflen) < struct_len) return -1; + if (stringbuf) + { + p2 = *stringbuf; + l2 = *stringspace; + } + else + { + p2 = p + struct_len; + l2 = (*buflen) - struct_len; + } + if (!baseaddr) baseaddr = p; + + StrnCpy(p,lp_servicename(snum),13); + + if (uLevel > 0) + { + int type; + CVAL(p,13) = 0; + type = STYPE_DISKTREE; + if (lp_print_ok(snum)) type = STYPE_PRINTQ; + if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; + SSVAL(p,14,type); /* device type */ + SIVAL(p,16,PTR_DIFF(p2,baseaddr)); + len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2); + } + + if (uLevel > 1) + { + SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ + SSVALS(p,22,-1); /* max uses */ + SSVAL(p,24,1); /* current uses */ + SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ + len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); + memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ + } + + if (uLevel > 2) + { + memset(p+40,0,SHPWLEN+2); + SSVAL(p,50,0); + SIVAL(p,52,0); + SSVAL(p,56,0); + SSVAL(p,58,0); + SIVAL(p,60,0); + SSVAL(p,64,0); + SSVAL(p,66,0); + } + + if (stringbuf) + { + (*buf) = p + struct_len; + (*buflen) -= struct_len; + (*stringbuf) = p2; + (*stringspace) = l2; + } + else + { + (*buf) = p2; + (*buflen) -= len; + } + return len; +} + +static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *netname = skip_string(str2,1); + char *p = skip_string(netname,1); + int uLevel = SVAL(p,0); + int snum = find_service(netname); + + if (snum < 0) return False; + + /* check it's a supported varient */ + if (!prefix_ok(str1,"zWrLh")) return False; + if (!check_share_info(uLevel,str2)) return False; + + *rdata = REALLOC(*rdata,mdrcnt); + p = *rdata; + *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0); + if (*rdata_len < 0) return False; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + + return(True); +} + +/**************************************************************************** + view list of shares available + ****************************************************************************/ +static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + char *p2; + int count=lp_numservices(); + int total=0,counted=0; + int i; + int data_len, fixed_len, string_len; + int f_len, s_len; + + if (!prefix_ok(str1,"WrLeh")) return False; + if (!check_share_info(uLevel,str2)) return False; + + data_len = fixed_len = string_len = 0; + for (i=0;itm_hour; + CVAL(p,9) = t->tm_min; + CVAL(p,10) = t->tm_sec; + CVAL(p,11) = 0; /* hundredths of seconds */ + SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */ + SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ + CVAL(p,16) = t->tm_mday; + CVAL(p,17) = t->tm_mon + 1; + SSVAL(p,18,1900+t->tm_year); + CVAL(p,20) = t->tm_wday; + } + + + return(True); +} + +/**************************************************************************** + set the user password + ****************************************************************************/ +static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *p = skip_string(param+2,2); + fstring user; + fstring pass1,pass2; + + strcpy(user,p); + + p = skip_string(p,1); + + StrnCpy(pass1,p,16); + StrnCpy(pass2,p+16,16); + + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + DEBUG(3,("Set password for <%s>\n",user)); + + if (!password_ok(user,pass1,strlen(pass1),NULL,False) || + !chgpasswd(user,pass1,pass2)) + SSVAL(*rparam,0,NERR_badpass); + + bzero(pass1,sizeof(fstring)); + bzero(pass2,sizeof(fstring)); + + return(True); +} + +/**************************************************************************** + delete a print job + Form: <> + ****************************************************************************/ +static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + int function = SVAL(param,0); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded + by the print queue api */ + int snum = (SVAL(p,0)>>8); + int i, count; + + + /* check it's a supported varient */ + if (!(strcsequal(str1,"W") && strcsequal(str2,""))) + return(False); + + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_Success); + + if (snum >= 0 && VALID_SNUM(snum)) + { + print_queue_struct *queue=NULL; + lpq_reset(snum); + count = get_printqueue(snum,cnum,&queue,NULL); + + for (i=0;i= 0) { + lp_add_printer(QueueName,pnum); + snum = lp_servicenumber(QueueName); + } + } + + if (snum >= 0 && VALID_SNUM(snum)) { + print_queue_struct *queue=NULL; + int i, count; + lpq_reset(snum); + + count = get_printqueue(snum,cnum,&queue,NULL); + for (i = 0; i < count; i++) + del_printqueue(cnum,snum,queue[i].job); + + if (queue) free(queue); + } + + DEBUG(3,("Print queue purge, queue=%s\n",QueueName)); + + return(True); +} + + +/**************************************************************************** + set the property of a print job (undocumented?) + ? function = 0xb -> set name of print job + ? function = 0x6 -> move print job up/down + Form: + or +****************************************************************************/ +static int check_printjob_info(struct pack_desc* desc, + int uLevel, char* id) +{ + desc->subformat = NULL; + switch( uLevel ) { + case 0: desc->format = "W"; break; + case 1: desc->format = "WB21BB16B10zWWzDDz"; break; + case 2: desc->format = "WWzWWDDzz"; break; + case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; + default: return False; + } + if (strcmp(desc->format,id) != 0) return False; + return True; +} + +static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + struct pack_desc desc; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded + by the print queue api */ + int snum = (SVAL(p,0)>>8); + int uLevel = SVAL(p,2); + int function = SVAL(p,4); /* what is this ?? */ + int i; + char *s = data; + + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + /* check it's a supported varient */ + if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2))) + return(False); + + switch (function) { + case 0x6: /* change job place in the queue, data gives the new place */ + if (snum >= 0 && VALID_SNUM(snum)) + { + print_queue_struct *queue=NULL; + int count; + + lpq_reset(snum); + count = get_printqueue(snum,cnum,&queue,NULL); + for (i=0;i place ) /* move up */; + } +#endif + desc.errcode=NERR_notsupported; /* not yet supported */ + if (queue) free(queue); + } + } + else desc.errcode=NERR_JobNotFound; + break; + case 0xb: /* change print job name, data gives the name */ + /* jobid, snum should be zero */ + if (isalpha(*s)) + { + pstring name; + int l = 0; + while (l<64 && *s) + { + if (isalnum(*s) || strchr("-._",*s)) + name[l++] = *s; + s++; + } + name[l] = 0; + + DEBUG(3,("Setting print name to %s\n",name)); + + for (i=0;i 0) + { + struct srv_info_struct *servers=NULL; + int i,count; + pstring comment; + uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION| + SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE; + + strcpy(comment,lp_serverstring()); + + if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) { + for (i=0;i 1) + { + return False; /* not yet implemented */ + } + + *rdata_len = PTR_DIFF(p2,*rdata); + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + + return(True); +} + + +/**************************************************************************** + get info about the server + ****************************************************************************/ +static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char *p2; + extern pstring sesssetup_user; + int level = SVAL(p,0); + + DEBUG(4,("NetWkstaGetInfo level %d\n",level)); + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + + /* check it's a supported varient */ + if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) + return(False); + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + p2 = p + 22; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + strcpy(p2,local_machine); + p2 = skip_string(p2,1); + p += 4; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + strcpy(p2,sesssetup_user); + p2 = skip_string(p2,1); + p += 4; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + strcpy(p2,my_workgroup()); + p2 = skip_string(p2,1); + p += 4; + + SCVAL(p,0,2); /* major version?? */ + SCVAL(p,1,1); /* minor version?? */ + p += 2; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + strcpy(p2,my_workgroup()); /* login domain?? */ + p2 = skip_string(p2,1); + p += 4; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + strcpy(p2,""); + p2 = skip_string(p2,1); + p += 4; + + *rdata_len = PTR_DIFF(p2,*rdata); + + SSVAL(*rparam,4,*rdata_len); + + return(True); +} + + +/**************************************************************************** + get info about a user + ****************************************************************************/ + +#define USER_PRIV_GUEST 0 +#define USER_PRIV_USER 1 +#define USER_PRIV_ADMIN 2 + +static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *UserName = skip_string(str2,1); + char *p = skip_string(UserName,1); + int uLevel = SVAL(p,0); + char *p2; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLh") != 0) return False; + switch( uLevel ) { + case 0: p2 = "B21"; break; + case 1: p2 = "B21BB16DWzzWz"; break; + case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; + case 10: p2 = "B21Bzzz"; break; + case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break; + default: return False; + } + if (strcmp(p2,str2) != 0) return False; + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + p2 = p + 86; + + memset(p,0,21); + strcpy(p,UserName); + if (uLevel > 0) { + SCVAL(p,21,0); + *p2 = 0; + if (uLevel >= 10) { + SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */ + strcpy(p2,""); + p2 = skip_string(p2,1); + } + if (uLevel == 11) { /* modelled after NTAS 3.51 reply */ + SSVAL(p,34,USER_PRIV_USER); /* user privilege */ + SIVAL(p,36,0); /* auth flags */ + SIVALS(p,40,-1); /* password age */ + SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */ + strcpy(p2,"\\\\%L\\HOMES"); + standard_sub_basic(p2); + p2 = skip_string(p2,1); + SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,52,0); /* last logon */ + SIVAL(p,56,0); /* last logoff */ + SSVALS(p,60,-1); /* bad pw counts */ + SSVALS(p,62,-1); /* num logons */ + SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */ + strcpy(p2,"\\\\*"); + p2 = skip_string(p2,1); + SSVAL(p,68,0); /* country code */ + + SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */ + strcpy(p2,""); + p2 = skip_string(p2,1); + + SIVALS(p,74,-1); /* max storage */ + SSVAL(p,78,168); /* units per week */ + SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */ + memset(p2,-1,21); + SCVAL(p2,21,0); /* fix zero termination */ + p2 = skip_string(p2,1); + + SSVAL(p,84,0); /* code page */ + } + if (uLevel == 1 || uLevel == 2) { + memset(p+22,' ',16); /* password */ + SIVALS(p,38,-1); /* password age */ + SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */ + SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ + strcpy(p2,"\\\\%L\\HOMES"); + standard_sub_basic(p2); + p2 = skip_string(p2,1); + SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ + *p2++ = 0; + SSVAL(p,52,0); /* flags */ + SIVAL(p,54,0); /* script_path */ + if (uLevel == 2) { + SIVAL(p,60,0); /* auth_flags */ + SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,68,0); /* urs_comment */ + SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,76,0); /* workstations */ + SIVAL(p,80,0); /* last_logon */ + SIVAL(p,84,0); /* last_logoff */ + SIVALS(p,88,-1); /* acct_expires */ + SIVALS(p,92,-1); /* max_storage */ + SSVAL(p,96,168); /* units_per_week */ + SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */ + memset(p2,-1,21); + p2 += 21; + SSVALS(p,102,-1); /* bad_pw_count */ + SSVALS(p,104,-1); /* num_logons */ + SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ + strcpy(p2,"\\\\%L"); + standard_sub_basic(p2); + p2 = skip_string(p2,1); + SSVAL(p,110,49); /* country_code */ + SSVAL(p,112,860); /* code page */ + } + } + } + + *rdata_len = PTR_DIFF(p2,*rdata); + + SSVAL(*rparam,4,*rdata_len); /* is this right?? */ + + return(True); +} + + +/******************************************************************* + get groups that a user is a member of + ******************************************************************/ +static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *UserName = skip_string(str2,1); + char *p = skip_string(UserName,1); + int uLevel = SVAL(p,0); + char *p2; + int count=0; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLeh") != 0) return False; + switch( uLevel ) { + case 0: p2 = "B21"; break; + default: return False; + } + if (strcmp(p2,str2) != 0) return False; + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + + /* XXXX we need a real SAM database some day */ + strcpy(p,"Users"); p += 21; count++; + strcpy(p,"Domain Users"); p += 21; count++; + strcpy(p,"Guests"); p += 21; count++; + strcpy(p,"Domain Guests"); p += 21; count++; + + *rdata_len = PTR_DIFF(p,*rdata); + + SSVAL(*rparam,4,count); /* is this right?? */ + SSVAL(*rparam,6,count); /* is this right?? */ + + return(True); +} + + +static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + struct pack_desc desc; + char* name; + + uLevel = SVAL(p,0); + name = p + 2; + + bzero(&desc,sizeof(desc)); + + DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); + + /* check it's a supported varient */ + if (strcmp(str1,"OOWb54WrLh") != 0) return False; + if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False; + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.subformat = NULL; + desc.format = str2; + + + + if (init_package(&desc,1,0)) { + PACKI(&desc,"W",0); /* code */ + PACKS(&desc,"B21",name); /* eff. name */ + PACKS(&desc,"B",""); /* pad */ + PACKI(&desc,"W", + Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + PACKI(&desc,"D",0); /* auth flags XXX */ + PACKI(&desc,"W",0); /* num logons */ + PACKI(&desc,"W",0); /* bad pw count */ + PACKI(&desc,"D",-1); /* last logon */ + PACKI(&desc,"D",-1); /* last logoff */ + PACKI(&desc,"D",-1); /* logoff time */ + PACKI(&desc,"D",-1); /* kickoff time */ + PACKI(&desc,"D",0); /* password age */ + PACKI(&desc,"D",0); /* password can change */ + PACKI(&desc,"D",-1); /* password must change */ + { + fstring mypath; + strcpy(mypath,"\\\\"); + strcat(mypath,local_machine); + strupper(mypath); + PACKS(&desc,"z",mypath); /* computer */ + } + PACKS(&desc,"z",my_workgroup());/* domain */ + PACKS(&desc,"z",lp_logon_script()); /* script path */ + PACKI(&desc,"D",0); /* reserved */ + } + + *rdata_len = desc.usedlen; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); + return(True); +} + + +/**************************************************************************** + api_WAccessGetUserPerms + ****************************************************************************/ +static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *user = skip_string(str2,1); + char *resource = skip_string(user,1); + + DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); + + /* check it's a supported varient */ + if (strcmp(str1,"zzh") != 0) return False; + if (strcmp(str2,"") != 0) return False; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,0); /* errorcode */ + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,0x7f); /* permission flags */ + + return(True); +} + +/**************************************************************************** + api_WPrintJobEnumerate + ****************************************************************************/ +static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uJobId = SVAL(p,0); + int uLevel,cbBuf; + int count; + int i; + int snum; + int job; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + + uLevel = SVAL(p,2); + cbBuf = SVAL(p,4); + + bzero(&desc,sizeof(desc)); + bzero(&status,sizeof(status)); + + DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId)); + + /* check it's a supported varient */ + if (strcmp(str1,"WWrLh") != 0) return False; + if (!check_printjob_info(&desc,uLevel,str2)) return False; + + snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/ + job = uJobId & 0xFF; + + if (snum < 0 || !VALID_SNUM(snum)) return(False); + + count = get_printqueue(snum,cnum,&queue,&status); + for (i = 0; i < count; i++) { + if ((queue[i].job % 0xFF) == job) break; + } + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,1,0)) { + if (i < count) { + fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); + *rdata_len = desc.usedlen; + } + else { + desc.errcode = NERR_JobNotFound; + *rdata_len = 0; + } + } + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + if (queue) free(queue); + + DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char* name = p; + int uLevel,cbBuf; + int count; + int i, succnt=0; + int snum; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + + bzero(&desc,sizeof(desc)); + bzero(&status,sizeof(status)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + cbBuf = SVAL(p,2); + + DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLeh") != 0) return False; + if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */ + if (!check_printjob_info(&desc,uLevel,str2)) return False; + + snum = lp_servicenumber(name); + if (snum < 0 && pcap_printername_ok(name,NULL)) { + int pnum = lp_servicenumber(PRINTERS_NAME); + if (pnum >= 0) { + lp_add_printer(name,pnum); + snum = lp_servicenumber(name); + } + } + + if (snum < 0 || !VALID_SNUM(snum)) return(False); + + count = get_printqueue(snum,cnum,&queue,&status); + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,count,0)) { + succnt = 0; + for (i = 0; i < count; i++) { + fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); + if (desc.errcode == NERR_Success) succnt = i+1; + } + } + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,count); + + if (queue) free(queue); + + DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); + return(True); +} + +static int check_printdest_info(struct pack_desc* desc, + int uLevel, char* id) +{ + desc->subformat = NULL; + switch( uLevel ) { + case 0: desc->format = "B9"; break; + case 1: desc->format = "B9B21WWzW"; break; + case 2: desc->format = "z"; break; + case 3: desc->format = "zzzWWzzzWW"; break; + default: return False; + } + if (strcmp(desc->format,id) != 0) return False; + return True; +} + +static void fill_printdest_info(int cnum, int snum, int uLevel, + struct pack_desc* desc) +{ + char buf[100]; + strcpy(buf,SERVICE(snum)); + strupper(buf); + if (uLevel <= 1) { + PACKS(desc,"B9",buf); /* szName */ + if (uLevel == 1) { + PACKS(desc,"B21",""); /* szUserName */ + PACKI(desc,"W",0); /* uJobId */ + PACKI(desc,"W",0); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"W",0); /* time */ + } + } + if (uLevel == 2 || uLevel == 3) { + PACKS(desc,"z",buf); /* pszPrinterName */ + if (uLevel == 3) { + PACKS(desc,"z",""); /* pszUserName */ + PACKS(desc,"z",""); /* pszLogAddr */ + PACKI(desc,"W",0); /* uJobId */ + PACKI(desc,"W",0); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKS(desc,"z",""); /* pszComment */ + PACKS(desc,"z","NULL"); /* pszDrivers */ + PACKI(desc,"W",0); /* time */ + PACKI(desc,"W",0); /* pad1 */ + } + } +} + +static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char* PrinterName = p; + int uLevel,cbBuf; + struct pack_desc desc; + int snum; + + bzero(&desc,sizeof(desc)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + cbBuf = SVAL(p,2); + + DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLh") != 0) return False; + if (!check_printdest_info(&desc,uLevel,str2)) return False; + + snum = lp_servicenumber(PrinterName); + if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) { + int pnum = lp_servicenumber(PRINTERS_NAME); + if (pnum >= 0) { + lp_add_printer(PrinterName,pnum); + snum = lp_servicenumber(PrinterName); + } + } + + if (snum < 0) { + *rdata_len = 0; + desc.errcode = NERR_DestNotFound; + desc.neededlen = 0; + } + else { + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,0)) { + fill_printdest_info(cnum,snum,uLevel,&desc); + } + *rdata_len = desc.usedlen; + } + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel,cbBuf; + int queuecnt; + int i, n, succnt=0; + struct pack_desc desc; + int services = lp_numservices(); + + bzero(&desc,sizeof(desc)); + + uLevel = SVAL(p,0); + cbBuf = SVAL(p,2); + + DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (!check_printdest_info(&desc,uLevel,str2)) return False; + + queuecnt = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) + queuecnt++; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,queuecnt,0)) { + succnt = 0; + n = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + fill_printdest_info(cnum,i,uLevel,&desc); + n++; + if (desc.errcode == NERR_Success) succnt = n; + } + } + } + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,queuecnt); + + DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel,cbBuf; + int succnt; + struct pack_desc desc; + + bzero(&desc,sizeof(desc)); + + uLevel = SVAL(p,0); + cbBuf = SVAL(p,2); + + DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (uLevel != 0 || strcmp(str2,"B41") != 0) return False; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B41","NULL"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); + + DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel,cbBuf; + int succnt; + struct pack_desc desc; + + bzero(&desc,sizeof(desc)); + + uLevel = SVAL(p,0); + cbBuf = SVAL(p,2); + + DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B13","lpd"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); + + DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel,cbBuf; + int succnt; + struct pack_desc desc; + + bzero(&desc,sizeof(desc)); + + uLevel = SVAL(p,0); + cbBuf = SVAL(p,2); + + DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + bzero(&desc,sizeof(desc)); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B13","lp0"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); + + DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); + return(True); +} + +/**************************************************************************** + the buffer was too small + ****************************************************************************/ +static BOOL api_TooSmall(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + *rparam_len = MIN(*rparam_len,mprcnt); + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_BufTooSmall); + + DEBUG(3,("Supplied buffer too small in API command\n")); + + return(True); +} + + +/**************************************************************************** + the request is not supported + ****************************************************************************/ +static BOOL api_Unsupported(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_notsupported); + SSVAL(*rparam,2,0); /* converter word */ + + DEBUG(3,("Unsupported API command\n")); + + return(True); +} + + + + +struct +{ + char *name; + int id; + BOOL (*fn)(); + int flags; +} api_commands[] = { + {"RNetShareEnum", 0, api_RNetShareEnum,0}, + {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, + {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, + {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, + {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, + {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, + {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, + {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, + {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, + {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, + {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, + {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0}, + {"RDosPrintJobResume",83, api_RDosPrintJobDel,0}, + {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, + {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, + {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, + {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0}, + {"NetServerEnum", 104, api_RNetServerEnum,0}, + {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, + {"SetUserPassword", 115, api_SetUserPassword,0}, + {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0}, + {"PrintJobInfo", 147, api_PrintJobInfo,0}, + {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0}, + {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0}, + {"WPrintPortEnum", 207, api_WPrintPortEnum,0}, + {NULL, -1, api_Unsupported,0}}; + + +/**************************************************************************** + handle remote api calls + ****************************************************************************/ +static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params, + int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +{ + int api_command = SVAL(params,0); + char *rdata = NULL; + char *rparam = NULL; + int rdata_len = 0; + int rparam_len = 0; + BOOL reply=False; + int i; + + DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", + api_command,params+2,skip_string(params+2,1), + tdscnt,tpscnt,mdrcnt,mprcnt)); + + for (i=0;api_commands[i].name;i++) + if (api_commands[i].id == api_command && api_commands[i].fn) + { + DEBUG(3,("Doing %s\n",api_commands[i].name)); + break; + } + + rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); + rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); + + reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + + if (rdata_len > mdrcnt || + rparam_len > mprcnt) + { + reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } + + + /* if we get False back then it's actually unsupported */ + if (!reply) + api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + + + /* now send the reply */ + send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); + + if (rdata) + free(rdata); + if (rparam) + free(rparam); + + return(-1); +} + +/**************************************************************************** + handle named pipe commands + ****************************************************************************/ +static int named_pipe(int cnum,int uid, char *outbuf,char *name, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt, + int msrcnt,int mdrcnt,int mprcnt) +{ + + if (strequal(name,"LANMAN")) + return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); + + DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n", + name,(int)setup[0],(int)setup[1])); + + return(0); +} + + +/**************************************************************************** + reply to a SMBtrans + ****************************************************************************/ +int reply_trans(char *inbuf,char *outbuf) +{ + fstring name; + + char *data=NULL,*params=NULL; + uint16 *setup=NULL; + + int outsize = 0; + int cnum = SVAL(inbuf,smb_tid); + int uid = SVAL(inbuf,smb_uid); + + int tpscnt = SVAL(inbuf,smb_vwv0); + int tdscnt = SVAL(inbuf,smb_vwv1); + int mprcnt = SVAL(inbuf,smb_vwv2); + int mdrcnt = SVAL(inbuf,smb_vwv3); + int msrcnt = CVAL(inbuf,smb_vwv4); + BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); + BOOL one_way = BITSETW(inbuf+smb_vwv5,1); + int pscnt = SVAL(inbuf,smb_vwv9); + int psoff = SVAL(inbuf,smb_vwv10); + int dscnt = SVAL(inbuf,smb_vwv11); + int dsoff = SVAL(inbuf,smb_vwv12); + int suwcnt = CVAL(inbuf,smb_vwv13); + + StrnCpy(name,smb_buf(inbuf),sizeof(name)-1); + + if (tdscnt) + { + data = (char *)malloc(tdscnt); + memcpy(data,smb_base(inbuf)+dsoff,dscnt); + } + if (tpscnt) + { + params = (char *)malloc(tpscnt); + memcpy(params,smb_base(inbuf)+psoff,pscnt); + } + + if (suwcnt) + { + int i; + setup = (uint16 *)malloc(suwcnt*sizeof(setup[0])); + for (i=0;i data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt)); + + + if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) + outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, + suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); + + + if (data) free(data); + if (params) free(params); + if (setup) free(setup); + + if (close_on_completion) + close_cnum(cnum,uid); + + if (one_way) + return(-1); + + if (outsize == 0) + return(ERROR(ERRSRV,ERRnosupport)); + + return(outsize); +} + + diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c new file mode 100644 index 0000000000..8f1490c528 --- /dev/null +++ b/source3/smbd/mangle.c @@ -0,0 +1,610 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Name mangling + 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 int case_default; +extern BOOL case_mangle; + +/**************************************************************************** +provide a checksum on a string +****************************************************************************/ +int str_checksum(char *s) +{ + int res = 0; + int c; + int i=0; + while (*s) + { + c = *s; + res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); + s++; i++; + } + return(res); +} + +/**************************************************************************** +return True if a name is a special msdos reserved name +****************************************************************************/ +static BOOL is_reserved_msdos(char *fname) +{ + char upperFname[13]; + char *p; + + StrnCpy (upperFname, fname, 12); + + /* lpt1.txt and con.txt etc are also illegal */ + p=strchr(upperFname,'.'); + if (p) + *p='\0'; + strupper (upperFname); + if ((strcmp(upperFname,"CLOCK$") == 0) || + (strcmp(upperFname,"CON") == 0) || + (strcmp(upperFname,"AUX") == 0) || + (strcmp(upperFname,"COM1") == 0) || + (strcmp(upperFname,"COM2") == 0) || + (strcmp(upperFname,"COM3") == 0) || + (strcmp(upperFname,"COM4") == 0) || + (strcmp(upperFname,"LPT1") == 0) || + (strcmp(upperFname,"LPT2") == 0) || + (strcmp(upperFname,"LPT3") == 0) || + (strcmp(upperFname,"NUL") == 0) || + (strcmp(upperFname,"PRN") == 0)) + return (True) ; + + return (False); +} + + + +/**************************************************************************** +return True if a name is in 8.3 dos format +****************************************************************************/ +BOOL is_8_3(char *fname) +{ + int len; + char *dot_pos; + char *slash_pos = strrchr(fname,'/'); + int l; + + if (slash_pos) fname = slash_pos+1; + len = strlen(fname); + + dot_pos = strchr(fname,'.'); + + DEBUG(5,("checking %s for 8.3\n",fname)); + + if (case_mangle) + switch (case_default) + { + case CASE_LOWER: + if (strhasupper(fname)) return(False); + break; + case CASE_UPPER: + if (strhaslower(fname)) return(False); + break; + } + + /* can't be longer than 12 chars */ + if (len == 0 || len > 12) + return(False); + + /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ + if (is_reserved_msdos(fname)) + return(False); + + /* can't contain invalid dos chars */ + /* Windows use the ANSI charset. + But filenames are translated in the PC charset. + This Translation may be more or less relaxed depending + the Windows application. */ + + /* %%% A nice improvment to name mangling would be to translate + filename to ANSI charset on the smb server host */ + + { + char *p = fname; +#ifdef KANJI + dot_pos = 0; + while (*p) + { + if (is_shift_jis (*p)) { + p += 2; + } else if (is_kana (*p)) { + p ++; + } else { + if (*p == '.' && !dot_pos) + dot_pos = (char *) p; + if (!isdoschar(*p)) + return(False); + p++; + } + } +#else + while (*p) + { + if (!isdoschar(*p)) + return(False); + p++; + } +#endif /* KANJI */ + } + + /* no dot and less than 9 means OK */ + if (!dot_pos) + return(len <= 8); + + l = PTR_DIFF(dot_pos,fname); + + /* base must be at least 1 char except special cases . and .. */ + if (l == 0) + return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0); + + /* base can't be greater than 8 */ + if (l > 8) + return(False); + + if (lp_strip_dot() && + len - l == 1 && + !strchr(dot_pos+1,'.')) + { + *dot_pos = 0; + return(True); + } + + /* extension must be between 1 and 3 */ + if ( (len - l < 2 ) || (len - l > 4) ) + return(False); + + /* extension can't have a dot */ + if (strchr(dot_pos+1,'.')) + return(False); + + /* must be in 8.3 format */ + return(True); +} + + + +/* +keep a stack of name mangling results - just +so file moves and copies have a chance of working +*/ +fstring *mangled_stack = NULL; +int mangled_stack_size = 0; +int mangled_stack_len = 0; + +/**************************************************************************** +create the mangled stack +****************************************************************************/ +void create_mangled_stack(int size) +{ + if (mangled_stack) + { + free(mangled_stack); + mangled_stack_size = 0; + mangled_stack_len = 0; + } + if (size > 0) + mangled_stack = (fstring *)malloc(sizeof(fstring)*size); + if (mangled_stack) mangled_stack_size = size; +} + +/**************************************************************************** +push a mangled name onto the stack +****************************************************************************/ +static void push_mangled_name(char *s) +{ + int i; + char *p; + + if (!mangled_stack) + return; + + for (i=0;iuid = -1; + vuser->gid = -1; + vuser->user_ngroups = 0; + if(vuser->user_groups && + (vuser->user_groups != (gid_t *)vuser->user_igroups)) + free(vuser->user_groups); + vuser->user_groups = NULL; + if(vuser->user_igroups) + free(vuser->user_igroups); + vuser->user_igroups = NULL; + } +} + + +/**************************************************************************** +return a validated username +****************************************************************************/ +char *validated_username(int vuid) +{ + return(validated_users[vuid].name); +} + +/**************************************************************************** +register a uid/name pair as being valid and that a valid password +has been given. +****************************************************************************/ +void register_uid(int uid,int gid, char *name,BOOL guest) +{ + user_struct *vuser; + + if (valid_uid(uid) >= 0) + return; + validated_users = (user_struct *)Realloc(validated_users, + sizeof(user_struct)* + (num_validated_users+1)); + + if (!validated_users) + { + DEBUG(0,("Failed to realloc users struct!\n")); + return; + } + + vuser = &validated_users[num_validated_users]; + vuser->uid = uid; + vuser->gid = gid; + vuser->guest = guest; + strcpy(vuser->name,name); + + vuser->user_ngroups = 0; + vuser->user_groups = NULL; + vuser->user_igroups = NULL; + + /* Find all the groups this uid is in and store them. + Used by become_user() */ + setup_groups(name,uid,gid, + &vuser->user_ngroups, + &vuser->user_igroups, + &vuser->user_groups); + + DEBUG(3,("uid %d registered to name %s\n",uid,name)); + + num_validated_users++; +} + + +/**************************************************************************** +add a name to the session users list +****************************************************************************/ +void add_session_user(char *user) +{ + fstring suser; + StrnCpy(suser,user,sizeof(suser)-1); + + if (!Get_Pwnam(suser,True)) return; + + if (suser && *suser && !in_list(suser,session_users,False)) + { + if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) + DEBUG(1,("Too many session users??\n")); + else + { + strcat(session_users," "); + strcat(session_users,suser); + } + } +} + + +#ifdef NO_GETSPNAM +/* a fake shadow password routine which just fills a fake spwd struct + * with the sp_pwdp field. (sreiz@aie.nl) + */ +static struct spwd *getspnam(char *username) /* fake shadow password routine */ +{ + FILE *f; + char line[1024]; + static char pw[20]; + static struct spwd static_spwd; + + static_spwd.sp_pwdp=0; + if (!(f=fopen("/etc/master.passwd", "r"))) + return 0; + while (fgets(line, 1024, f)) { + if (!strncmp(line, username, strlen(username)) && + line[strlen(username)]==':') { /* found entry */ + char *p, *q; + + p=line+strlen(username)+1; + if ((q=strchr(p, ':'))) { + *q=0; + if (q-p+1>20) + break; + strcpy(pw, p); + static_spwd.sp_pwdp=pw; + } + break; + } + } + fclose(f); + if (static_spwd.sp_pwdp) + return &static_spwd; + return 0; +} +#endif + + +#ifdef OSF1_ENH_SEC +/**************************************************************************** +an enhanced crypt for OSF1 +****************************************************************************/ +static char *osf1_bigcrypt(char *password,char *salt1) +{ + static char result[AUTH_MAX_PASSWD_LENGTH] = ""; + char *p1; + char *p2=password; + char salt[3]; + int i; + int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS; + if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS) + parts++; + + StrnCpy(salt,salt1,2); + StrnCpy(result,salt1,2); + + for (i=0; iufld.fd_slogin = tz; + mypasswd->ufld.fd_nlogins = 0; + + putprpwnam(user,mypasswd); + + DEBUG(3,("Update protected database for Account %s after succesful connection\n",user)); + } + else + { + mypasswd->ufld.fd_ulogin = tz; + mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1; + if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries ) + { + mypasswd->uflg.fg_lock = 0; + DEBUG(3,("Account is disabled -- see Account Administrator.\n")); + } + putprpwnam ( user , mypasswd ); + DEBUG(3,("Update protected database for Account %s after refusing connection\n",user)); + } +#else + DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result))); +#endif +} + + +#ifdef AFS_AUTH +/******************************************************************* +check on AFS authentication +********************************************************************/ +static BOOL afs_auth(char *this_user,char *password) +{ + long password_expires = 0; + char *reason; + + /* For versions of AFS prior to 3.3, this routine has few arguments, */ + /* but since I can't find the old documentation... :-) */ + setpag(); + if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG, + this_user, + (char *) 0, /* instance */ + (char *) 0, /* cell */ + password, + 0, /* lifetime, default */ + &password_expires, /*days 'til it expires */ + 0, /* spare 2 */ + &reason) == 0) + return(True); + return(False); +} +#endif + + +#ifdef DFS_AUTH + +sec_login_handle_t my_dce_sec_context; +int dcelogin_atmost_once = 0; + +/******************************************************************* +check on a DCE/DFS authentication +********************************************************************/ +static BOOL dfs_auth(char *this_user,char *password) +{ + error_status_t err; + int err2; + int prterr; + boolean32 password_reset; + sec_passwd_rec_t my_dce_password; + sec_login_auth_src_t auth_src = sec_login_auth_src_network; + unsigned char dce_errstr[dce_c_error_string_len]; + + /* + * We only go for a DCE login context if the given password + * matches that stored in the local password file.. + * Assumes local passwd file is kept in sync w/ DCE RGY! + */ + + if (!strcmp((char *)crypt(password,this_salt),this_crypted) || + dcelogin_atmost_once) + return(False); + + if (sec_login_setup_identity( + (unsigned char *)this_user, + sec_login_no_flags, + &my_dce_sec_context, + &err) == 0) + { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE Setup Identity for %s failed: %s\n", + this_user,dce_errstr)); + return(False); + } + + my_dce_password.version_number = sec_passwd_c_version_none; + my_dce_password.pepper = NULL; + my_dce_password.key.key_type = sec_passwd_plain; + my_dce_password.key.tagged_union.plain = (idl_char *)password; + + if (sec_login_valid_and_cert_ident(my_dce_sec_context, + &my_dce_password, + &password_reset, + &auth_src, + &err) == 0 ) + { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n", + this_user,dce_errstr)); + + return(False); + } + + sec_login_set_context(my_dce_sec_context, &err); + if (err != error_status_ok ) + { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n", + this_user,dce_errstr)); + sec_login_purge_context(my_dce_sec_context, &err); + return(False); + } + else + { + DEBUG(0,("DCE login succeeded for principal %s on pid %d\n", + this_user, getpid())); + } + + dcelogin_atmost_once = 1; + return (True); +} + +void dfs_unlogin(void) +{ + error_status_t err; + int err2; + unsigned char dce_errstr[dce_c_error_string_len]; + + sec_login_purge_context(my_dce_sec_context, &err); + if (err != error_status_ok ) + { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE purge login context failed for server instance %d: %s\n", + getpid(), dce_errstr)); + } +} + +#endif + + +#ifdef LINUX_BIGCRYPT +/**************************************************************************** +an enhanced crypt for Linux to handle password longer than 8 characters +****************************************************************************/ +static int linux_bigcrypt(char *password,char *salt1, char *crypted) +{ +#define LINUX_PASSWORD_SEG_CHARS 8 + char salt[3]; + int i; + + StrnCpy(salt,salt1,2); + crypted +=2; + + for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { + char * p = crypt(password,salt) + 2; + if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) + return(0); + password += LINUX_PASSWORD_SEG_CHARS; + crypted += strlen(p); + } + + return(1); +} +#endif + + +/**************************************************************************** +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 BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N) +{ + int len = strlen(s); + int i; + +#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); + if (string_combinations2(s,i+1,fn,N-1)) + return(True); + s[i] = c; + } + return(False); +} + +/**************************************************************************** +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 BOOL string_combinations(char *s,BOOL (*fn)(),int N) +{ + int n; + for (n=1;n<=N;n++) + if (string_combinations2(s,0,fn,n)) return(True); + return(False); +} + + + +/**************************************************************************** +core of password checking routine +****************************************************************************/ +BOOL password_check(char *password) +{ +#ifdef AFS_AUTH + if (afs_auth(this_user,password)) return(True); +#endif + +#ifdef DFS_AUTH + if (dfs_auth(this_user,password)) return(True); +#endif + +#ifdef PWDAUTH + if (pwdauth(this_user,password) == 0) + return(True); +#endif + +#ifdef OSF1_ENH_SEC + return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0); +#endif + +#ifdef ULTRIX_AUTH + return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0); +#endif + +#ifdef LINUX_BIGCRYPT + return(linux_bigcrypt(password,this_salt,this_crypted)); +#endif + +#ifdef NO_CRYPT + DEBUG(1,("Warning - no crypt available\n")); + return(False); +#else + return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0); +#endif +} + +#ifdef SMB_PASSWD +/**************************************************************************** +core of smb password checking routine. +****************************************************************************/ +BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8) +{ + /* Finish the encryption of part_passwd. */ + unsigned char p21[21]; + unsigned char p24[24]; + + if(part_passwd == NULL) + DEBUG(10,("No password set - allowing access\n")); + /* No password set - always true ! */ + if(part_passwd == NULL) + return 1; + + memset(p21,'\0',21); + memcpy(p21,part_passwd,16); + E_P24(p21, c8, p24); +#if DEBUG_PASSWORD + { + int i; + DEBUG(100,("Part password (P16) was |")); + for(i = 0; i < 16; i++) + DEBUG(100,("%X ", (unsigned char)part_passwd[i])); + DEBUG(100,("|\n")); + DEBUG(100,("Password from client was |")); + for(i = 0; i < 24; i++) + DEBUG(100,("%X ", (unsigned char)password[i])); + DEBUG(100,("|\n")); + DEBUG(100,("Given challenge was |")); + for(i = 0; i < 8; i++) + DEBUG(100,("%X ", (unsigned char)c8[i])); + DEBUG(100,("|\n")); + DEBUG(100,("Value from encryption was |")); + for(i = 0; i < 24; i++) + DEBUG(100,("%X ", (unsigned char)p24[i])); + DEBUG(100,("|\n")); + } +#endif + return (memcmp(p24, password, 24) == 0); +} +#endif + +/**************************************************************************** +check if a username/password is OK +****************************************************************************/ +BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password) +{ + pstring pass2; + int level = lp_passwordlevel(); + struct passwd *pass; +#ifdef SMB_PASSWD + char challenge[8]; + struct smb_passwd *smb_pass; + BOOL challenge_done = False; +#endif + + if (password) password[pwlen] = 0; + +#ifdef SMB_PASSWD + if (pwlen == 24) + challenge_done = last_challenge(challenge); +#endif + +#if DEBUG_PASSWORD +#ifdef SMB_PASSWD + if (challenge_done) + { + int i; + DEBUG(100,("checking user=[%s] pass=[",user)); + for( i = 0; i < 24; i++) + DEBUG(100,("%0x ", (unsigned char)password[i])); + DEBUG(100,("]\n")); + } + else +#endif + DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); +#endif + + if (!password) + return(False); + + if (((!*password) || (!pwlen)) && !lp_null_passwords()) + return(False); + + if (pwd && !user) + { + pass = (struct passwd *) pwd; + user = pass->pw_name; + } + else + pass = Get_Pwnam(user,True); + +#ifdef SMB_PASSWD + + DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); + + if((pwlen == 24) && challenge_done) + { + DEBUG(4,("Checking SMB password for user %s (l=24)\n",user)); + + if (!pass) + { + DEBUG(3,("Couldn't find user %s\n",user)); + return(False); + } + + smb_pass = get_smbpwnam(user); + if(!smb_pass) + { + DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); + return(False); + } + + /* Ensure the uid's match */ + if(smb_pass->smb_userid != pass->pw_uid) + { + DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); + return(False); + } + + if(Protocol >= PROTOCOL_NT1 && is_nt_password) + { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + if(smb_pass->smb_nt_passwd != NULL) + { + DEBUG(4,("Checking NT MD4 password\n")); + if(smb_password_check(password, smb_pass->smb_nt_passwd, challenge)) + { + update_protected_database(user,True); + return(True); + } + DEBUG(4,("NT MD4 password check failed\n")); + return (False); + } + } + + /* Try against the lanman password */ + + if(smb_password_check(password, smb_pass->smb_passwd, challenge)) + { + update_protected_database(user,True); + return(True); + } + + DEBUG(3,("Error smb_password_check failed\n")); + } +#endif + + DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); + + if (!pass) + { + DEBUG(3,("Couldn't find user %s\n",user)); + return(False); + } + +#ifdef SHADOW_PWD + { + struct spwd *spass; + + /* many shadow systems require you to be root to get the password, + in most cases this should already be the case when this + function is called, except perhaps for IPC password changing + requests */ + + spass = getspnam(pass->pw_name); + if (spass && spass->sp_pwdp) + pass->pw_passwd = spass->sp_pwdp; + } +#endif + +#ifdef SecureWare + { + struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); + if (pr_pw && pr_pw->ufld.fd_encrypt) + pass->pw_passwd = pr_pw->ufld.fd_encrypt; + } +#endif + +#ifdef HPUX_10_TRUSTED + { + struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); + if (pr_pw && pr_pw->ufld.fd_encrypt) + pass->pw_passwd = pr_pw->ufld.fd_encrypt; + } +#endif + +#ifdef OSF1_ENH_SEC + { + struct pr_passwd *mypasswd; + DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user)); + mypasswd = getprpwnam (user); + if ( mypasswd ) + { + strcpy(pass->pw_name,mypasswd->ufld.fd_name); + strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt); + } + else + { + DEBUG(5,("No entry for user %s in protected database !\n",user)); + return(False); + } + } +#endif + +#ifdef ULTRIX_AUTH + { + AUTHORIZATION *ap = getauthuid( pass->pw_uid ); + if (ap) + { + strcpy( pass->pw_passwd, ap->a_password ); + endauthent(); + } + } +#endif + + /* extract relevant info */ + strcpy(this_user,pass->pw_name); + strcpy(this_salt,pass->pw_passwd); + strcpy(this_crypted,pass->pw_passwd); + + if (!*this_crypted) { + if (!lp_null_passwords()) { + DEBUG(2,("Disallowing access to %s due to null password\n",this_user)); + return(False); + } +#ifndef PWDAUTH + if (!*password) { + DEBUG(3,("Allowing access to %s with null password\n",this_user)); + return(True); + } +#endif + } + + /* try it as it came to us */ + if (password_check(password)) + { + update_protected_database(user,True); + return(True); + } + + /* if the password was given to us with mixed case then we don't + need to proceed as we know it hasn't been case modified by the + client */ + if (strhasupper(password) && strhaslower(password)) + return(False); + + /* make a copy of it */ + StrnCpy(pass2,password,sizeof(pstring)-1); + + /* try all lowercase */ + strlower(password); + if (password_check(password)) + { + update_protected_database(user,True); + return(True); + } + + /* give up? */ + if(level < 1) + { + update_protected_database(user,False); + + /* restore it */ + strcpy(password,pass2); + + return(False); + } + + /* last chance - all combinations of up to level chars upper! */ + strlower(password); + + if (string_combinations(password,password_check,level)) + { + update_protected_database(user,True); + return(True); + } + + update_protected_database(user,False); + + /* restore it */ + strcpy(password,pass2); + + return(False); +} + + + +/**************************************************************************** +check if a username is valid +****************************************************************************/ +BOOL user_ok(char *user,int snum) +{ + pstring valid, invalid; + BOOL ret; + + StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)); + StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)); + + string_sub(valid,"%S",lp_servicename(snum)); + string_sub(invalid,"%S",lp_servicename(snum)); + + ret = !user_in_list(user,invalid); + + if (ret && valid && *valid) + ret = user_in_list(user,valid); + + if (ret && lp_onlyuser(snum)) { + char *user_list = lp_username(snum); + string_sub(user_list,"%S",lp_servicename(snum)); + ret = user_in_list(user,user_list); + } + + return(ret); +} + + + + +/**************************************************************************** +validate a group username entry. Return the username or NULL +****************************************************************************/ +static char *validate_group(char *group,char *password,int pwlen,int snum) +{ +#ifdef NETGROUP + { + char *host, *user, *domain; + setnetgrent(group); + while (getnetgrent(&host, &user, &domain)) { + if (user) { + if (user_ok(user, snum) && + password_ok(user,password,pwlen,NULL,False)) { + endnetgrent(); + return(user); + } + } + } + endnetgrent(); + } +#endif + +#if HAVE_GETGRNAM + { + struct group *gptr = (struct group *)getgrnam(group); + char **member; + if (gptr) + { + member = gptr->gr_mem; + while (member && *member) + { + static fstring name; + strcpy(name,*member); + if (user_ok(name,snum) && + password_ok(name,password,pwlen,NULL,False)) + return(&name[0]); + member++; + } +#ifdef GROUP_CHECK_PWENT + { + struct passwd *pwd; + static fstring tm; + + setpwent (); + while (pwd = getpwent ()) { + if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { + /* This Entry have PASSWORD and same GID then check pwd */ + if (password_ok(NULL, password, pwlen, pwd,False)) { + strcpy(tm, pwd->pw_name); + endpwent (); + return tm; + } + } + } + endpwent (); + } +#endif /* GROUP_CHECK_PWENT */ + } + } +#endif + return(NULL); +} + + + +/**************************************************************************** +check for authority to login to a service with a given username/password +****************************************************************************/ +BOOL authorise_login(int snum,char *user,char *password, int pwlen, + BOOL *guest,BOOL *force,int vuid) +{ + BOOL ok = False; + + *guest = False; + +#if DEBUG_PASSWORD + DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password)); +#endif + + /* there are several possabilities: + 1) login as the given user with given password + 2) login as a previously registered username with the given password + 3) login as a session list username with the given password + 4) login as a previously validated user/password pair + 5) login as the "user =" user with given password + 6) login as the "user =" user with no password (guest connection) + 7) login as guest user with no password + + if the service is guest_only then steps 1 to 5 are skipped + */ + + if (GUEST_ONLY(snum)) *force = True; + + if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) + { + + /* check the given username and password */ + if (!ok && (*user) && user_ok(user,snum)) { + ok = password_ok(user,password, pwlen, NULL, False); + if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); + } + + /* check for a previously registered guest username */ + if (!ok && (vuid >= 0) && validated_users[vuid].guest) { + if (user_ok(validated_users[vuid].name,snum) && + password_ok(validated_users[vuid].name, password, pwlen, NULL, False)) { + strcpy(user, validated_users[vuid].name); + validated_users[vuid].guest = False; + DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); + ok = True; + } + } + + + /* now check the list of session users */ + if (!ok) + { + char *auser; + char *user_list = strdup(session_users); + if (!user_list) return(False); + + for (auser=strtok(user_list,LIST_SEP); + !ok && auser; + auser = strtok(NULL,LIST_SEP)) + { + fstring user2; + strcpy(user2,auser); + if (!user_ok(user2,snum)) continue; + + if (password_ok(user2,password, pwlen, NULL, False)) { + ok = True; + strcpy(user,user2); + DEBUG(3,("ACCEPTED: session list username and given password ok\n")); + } + } + free(user_list); + } + + /* check for a previously validated username/password pair */ + if (!ok && !lp_revalidate(snum) && + (vuid >= 0) && !validated_users[vuid].guest && + user_ok(validated_users[vuid].name,snum)) { + strcpy(user,validated_users[vuid].name); + *guest = False; + DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); + ok = True; + } + + /* check for a rhosts entry */ + if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) { + ok = True; + DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n")); + } + + /* check the user= fields and the given password */ + if (!ok && lp_username(snum)) { + char *auser; + pstring user_list; + StrnCpy(user_list,lp_username(snum),sizeof(pstring)); + + string_sub(user_list,"%S",lp_servicename(snum)); + + for (auser=strtok(user_list,LIST_SEP); + auser && !ok; + auser = strtok(NULL,LIST_SEP)) + { + if (*auser == '@') + { + auser = validate_group(auser+1,password,pwlen,snum); + if (auser) + { + ok = True; + strcpy(user,auser); + DEBUG(3,("ACCEPTED: group username and given password ok\n")); + } + } + else + { + fstring user2; + strcpy(user2,auser); + if (user_ok(user2,snum) && + password_ok(user2,password,pwlen,NULL, False)) + { + ok = True; + strcpy(user,user2); + DEBUG(3,("ACCEPTED: user list username and given password ok\n")); + } + } + } + } + } /* not guest only */ + + /* check for a normal guest connection */ + if (!ok && GUEST_OK(snum)) + { + fstring guestname; + StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); + if (Get_Pwnam(guestname,True)) + { + strcpy(user,guestname); + ok = True; + DEBUG(3,("ACCEPTED: guest account and guest ok\n")); + } + else + DEBUG(0,("Invalid guest account %s??\n",guestname)); + *guest = True; + *force = True; + } + + if (ok && !user_ok(user,snum)) + { + DEBUG(0,("rejected invalid user %s\n",user)); + ok = False; + } + + return(ok); +} + + +/**************************************************************************** +read the a hosts.equiv or .rhosts file and check if it +allows this user from this machine +****************************************************************************/ +static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) +{ + pstring buf; + int plus_allowed = 1; + char *file_host; + char *file_user; + FILE *fp = fopen(equiv_file, "r"); + DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); + if (! fp) return False; + while(fgets(buf, sizeof(buf), fp)) + { + trim_string(buf," "," "); + + if (buf[0] != '#' && buf[0] != '\n') + { + BOOL is_group = False; + int plus = 1; + char *bp = buf; + if (strcmp(buf, "NO_PLUS\n") == 0) + { + DEBUG(6, ("check_user_equiv NO_PLUS\n")); + plus_allowed = 0; + } + else { + if (buf[0] == '+') + { + bp++; + if (*bp == '\n' && plus_allowed) + { + /* a bare plus means everbody allowed */ + DEBUG(6, ("check_user_equiv everybody allowed\n")); + fclose(fp); + return True; + } + } + else if (buf[0] == '-') + { + bp++; + plus = 0; + } + if (*bp == '@') + { + is_group = True; + bp++; + } + file_host = strtok(bp, " \t\n"); + file_user = strtok(NULL, " \t\n"); + DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user)); + if (file_host && *file_host) + { + BOOL host_ok = False; + +#ifdef NETGROUP + /* THIS IS UNTESTED!! */ + if (is_group) + { + static char *mydomain = NULL; + if (!mydomain) + yp_get_default_domain(&mydomain); + if (mydomain && innetgr(remote,file_host,user,mydomain)) + host_ok = True; + } +#else + if (is_group) + { + DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n")); + continue; + } +#endif + + /* is it this host */ + /* the fact that remote has come from a call of gethostbyaddr + * means that it may have the fully qualified domain name + * so we could look up the file version to get it into + * a canonical form, but I would rather just type it + * in full in the equiv file + */ + if (!host_ok && !is_group && strequal(remote, file_host)) + host_ok = True; + + if (!host_ok) + continue; + + /* is it this user */ + if (file_user == 0 || strequal(user, file_user)) + { + fclose(fp); + DEBUG(5, ("check_user_equiv matched %s%s %s\n", + (plus ? "+" : "-"), file_host, + (file_user ? file_user : ""))); + return (plus ? True : False); + } + } + } + } + } + fclose(fp); + return False; +} + + +/**************************************************************************** +check for a possible hosts equiv or rhosts entry for the user +****************************************************************************/ +BOOL check_hosts_equiv(char *user) +{ + char *fname = NULL; + pstring rhostsfile; + struct passwd *pass = Get_Pwnam(user,True); + + extern struct from_host Client_info; + extern int Client; + + if (!pass) + return(False); + + fromhost(Client,&Client_info); + + fname = lp_hosts_equiv(); + + /* note: don't allow hosts.equiv on root */ + if (fname && *fname && (pass->pw_uid != 0)) + { + if (check_user_equiv(user,Client_info.name,fname)) + return(True); + } + + if (lp_use_rhosts()) + { + char *home = get_home_dir(user); + if (home) + { + sprintf(rhostsfile, "%s/.rhosts", home); + if (check_user_equiv(user,Client_info.name,rhostsfile)) + return(True); + } + } + + return(False); +} + + +static int password_client = -1; +static fstring pserver; + +/**************************************************************************** +attempted support for server level security +****************************************************************************/ +BOOL server_cryptkey(char *buf) +{ + pstring inbuf,outbuf; + fstring pass_protocol; + extern fstring remote_machine; + char *p; + int len; + fstring desthost; + struct in_addr dest_ip; + extern struct in_addr myip; + int port = 139; + BOOL ret; + + if (password_client >= 0) + close(password_client); + password_client = -1; + + if (Protocol < PROTOCOL_NT1) { + strcpy(pass_protocol,"LM1.2X002"); + } else { + strcpy(pass_protocol,"NT LM 0.12"); + } + + bzero(inbuf,sizeof(inbuf)); + bzero(outbuf,sizeof(outbuf)); + + for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { + strcpy(desthost,p); + standard_sub_basic(desthost); + strupper(desthost); + + dest_ip = *interpret_addr2(desthost); + if (zero_ip(dest_ip)) { + DEBUG(1,("Can't resolve address for %s\n",p)); + continue; + } + + if (memcmp(&dest_ip,&myip,sizeof(dest_ip)) == 0) { + DEBUG(1,("Password server loop - disabling password server %s\n",p)); + continue; + } + + password_client = open_socket_out(SOCK_STREAM, &dest_ip, port); + if (password_client >= 0) { + DEBUG(3,("connected to password server %s\n",p)); + StrnCpy(pserver,p,sizeof(pserver)-1); + break; + } + } + + if (password_client < 0) { + DEBUG(1,("password server not available\n")); + return(False); + } + + + /* send a session request (RFC 8002) */ + + /* put in the destination name */ + len = 4; + p = outbuf+len; + name_mangle(desthost,p,' '); + len += name_len(p); + + /* and my name */ + p = outbuf+len; + name_mangle(remote_machine,p,' '); + len += name_len(p); + + _smb_setlen(outbuf,len); + CVAL(outbuf,0) = 0x81; + + send_smb(password_client,outbuf); + receive_smb(password_client,inbuf,5000); + + if (CVAL(inbuf,0) != 0x82) { + DEBUG(1,("%s rejected the session\n",pserver)); + close(password_client); password_client = -1; + return(False); + } + + DEBUG(3,("got session\n")); + + bzero(outbuf,smb_size); + + /* setup the protocol string */ + set_message(outbuf,0,strlen(pass_protocol)+2,True); + p = smb_buf(outbuf); + *p++ = 2; + strcpy(p,pass_protocol); + + CVAL(outbuf,smb_com) = SMBnegprot; + CVAL(outbuf,smb_flg) = 0x8; + SSVAL(outbuf,smb_flg2,0x1); + + send_smb(password_client,outbuf); + ret = receive_smb(password_client,inbuf,5000); + + if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) { + DEBUG(1,("%s rejected the protocol\n",pserver)); + close(password_client); password_client= -1; + return(False); + } + + if (!(CVAL(inbuf,smb_vwv1) & 1)) { + DEBUG(1,("%s isn't in user level security mode\n",pserver)); + close(password_client); password_client= -1; + return(False); + } + + memcpy(buf,inbuf,smb_len(inbuf)+4); + + DEBUG(3,("password server OK\n")); + + return(True); +} + +/**************************************************************************** +attempted support for server level security +****************************************************************************/ +BOOL server_validate(char *buf) +{ + pstring inbuf,outbuf; + BOOL ret; + + if (password_client < 0) { + DEBUG(1,("%s not connected\n",pserver)); + return(False); + } + + bzero(inbuf,sizeof(inbuf)); + memcpy(outbuf,buf,sizeof(outbuf)); + + /* send a session setup command */ + CVAL(outbuf,smb_flg) = 0x8; + SSVAL(outbuf,smb_flg2,0x1); + CVAL(outbuf,smb_vwv0) = 0xFF; + + set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False); + + SCVAL(inbuf,smb_rcls,1); + + send_smb(password_client,outbuf); + ret = receive_smb(password_client,inbuf,5000); + + if (!ret || CVAL(inbuf,smb_rcls) != 0) { + DEBUG(1,("password server %s rejected the password\n",pserver)); + return(False); + } + + /* if logged in as guest then reject */ + if ((SVAL(inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n",pserver)); + return(False); + } + + DEBUG(3,("password server %s accepted the password\n",pserver)); + +#ifndef KEEP_PASSWORD_SERVER_OPEN + close(password_client); password_client= -1; +#endif + + return(True); +} + + diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c new file mode 100644 index 0000000000..b7b51775bb --- /dev/null +++ b/source3/smbd/reply.c @@ -0,0 +1,3210 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Main SMB reply routines + 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. +*/ +/* + This file handles most of the reply_ calls that the server + makes to handle specific protocols +*/ + + +#include "includes.h" +#include "loadparm.h" +#include "trans2.h" + +/* look in server.c for some explanation of these variables */ +extern int Protocol; +extern int DEBUGLEVEL; +extern int chain_size; +extern int maxxmit; +extern int chain_fnum; +extern char magic_char; +extern connection_struct Connections[]; +extern files_struct Files[]; +extern BOOL case_sensitive; +extern pstring sesssetup_user; +extern int Client; + +/* this macro should always be used to extract an fnum (smb_fid) from +a packet to ensure chaining works correctly */ +#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) + + +/**************************************************************************** + reply to an special message +****************************************************************************/ +int reply_special(char *inbuf,char *outbuf) +{ + int outsize = 4; + int msg_type = CVAL(inbuf,0); + int msg_flags = CVAL(inbuf,1); + pstring name1,name2; + extern fstring remote_machine; + extern fstring local_machine; + char *p; + + *name1 = *name2 = 0; + + smb_setlen(outbuf,0); + + switch (msg_type) + { + case 0x81: /* session request */ + CVAL(outbuf,0) = 0x82; + CVAL(outbuf,3) = 0; + if (name_len(inbuf+4) > 50) + { + DEBUG(0,("Invalid name length in session request\n")); + return(0); + } + name_extract(inbuf,4,name1); + name_extract(inbuf,4 + name_len(inbuf + 4),name2); + DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2)); + + strcpy(remote_machine,name2); + trim_string(remote_machine," "," "); + p = strchr(remote_machine,' '); + strlower(remote_machine); + if (p) *p = 0; + + strcpy(local_machine,name1); + trim_string(local_machine," "," "); + p = strchr(local_machine,' '); + strlower(local_machine); + if (p) *p = 0; + + add_session_user(remote_machine); + + reload_services(True); + reopen_logs(); + + break; + case 0x85: /* session keepalive */ + default: + return(0); + } + + DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags)); + + return(outsize); +} + + +/******************************************************************* +work out what error to give to a failed connection +********************************************************************/ +static int connection_error(char *inbuf,char *outbuf,int connection_num) +{ + switch (connection_num) + { + case -8: + return(ERROR(ERRSRV,ERRnoresource)); + case -7: + return(ERROR(ERRSRV,ERRbaduid)); + case -6: + return(ERROR(ERRSRV,ERRinvdevice)); + case -5: + return(ERROR(ERRSRV,ERRinvnetname)); + case -4: + return(ERROR(ERRSRV,ERRaccess)); + case -3: + return(ERROR(ERRDOS,ERRnoipc)); + case -2: + return(ERROR(ERRSRV,ERRinvnetname)); + } + return(ERROR(ERRSRV,ERRbadpw)); +} + + +/**************************************************************************** + reply to a tcon +****************************************************************************/ +int reply_tcon(char *inbuf,char *outbuf) +{ + pstring service; + pstring user; + pstring password; + pstring dev; + int connection_num; + int outsize = 0; + int uid = SVAL(inbuf,smb_uid); + int vuid; + int pwlen; + + *service = *user = *password = *dev = 0; + + vuid = valid_uid(uid); + + parse_connect(inbuf,service,user,password,&pwlen,dev); + + connection_num = make_connection(service,user,password,pwlen,dev,vuid); + + if (connection_num < 0) + return(connection_error(inbuf,outbuf,connection_num)); + + outsize = set_message(outbuf,2,0,True); + SSVAL(outbuf,smb_vwv0,maxxmit); + SSVAL(outbuf,smb_vwv1,connection_num); + SSVAL(outbuf,smb_tid,connection_num); + + DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); + + return(outsize); +} + + +/**************************************************************************** + reply to a tcon and X +****************************************************************************/ +int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + pstring service; + pstring user; + pstring password; + pstring devicename; + int connection_num; + int outsize = 0; + int uid = SVAL(inbuf,smb_uid); + int vuid; + int smb_com2 = SVAL(inbuf,smb_vwv0); + int smb_off2 = SVAL(inbuf,smb_vwv1); + int passlen = SVAL(inbuf,smb_vwv3); + + *service = *user = *password = *devicename = 0; + + /* we might have to close an old one */ + if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) + close_cnum(SVAL(inbuf,smb_tid),uid); + + vuid = valid_uid(uid); + + { + char *path; + char *p; + memcpy(password,smb_buf(inbuf),passlen); + password[passlen]=0; + path = smb_buf(inbuf) + passlen; + DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen)); + strcpy(service,path+2); + p = strchr(service,'\\'); + if (!p) + return(ERROR(ERRSRV,ERRinvnetname)); + *p = 0; + strcpy(service,p+1); + p = strchr(service,'%'); + if (p) + { + *p++ = 0; + strcpy(user,p); + } + StrnCpy(devicename,path + strlen(path) + 1,6); + DEBUG(4,("Got device type %s\n",devicename)); + } + + connection_num = make_connection(service,user,password,passlen,devicename,vuid); + + if (connection_num < 0) + return(connection_error(inbuf,outbuf,connection_num)); + + outsize = set_message(outbuf,2,strlen(devicename)+1,True); + + DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); + + /* set the incoming and outgoing tid to the just created one */ + SSVAL(inbuf,smb_tid,connection_num); + SSVAL(outbuf,smb_tid,connection_num); + + CVAL(outbuf,smb_vwv0) = smb_com2; + SSVAL(outbuf,smb_vwv1,(chain_size + outsize)-4); + + strcpy(smb_buf(outbuf),devicename); + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + return(outsize); +} + + +/**************************************************************************** + reply to an unknown type +****************************************************************************/ +int reply_unknown(char *inbuf,char *outbuf) +{ + int cnum; + int type; + cnum = SVAL(inbuf,smb_tid); + type = CVAL(inbuf,smb_com); + + DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n", + timestring(), + smb_fn_name(type), + cnum,type,type)); + + return(ERROR(ERRSRV,ERRunknownsmb)); +} + + +/**************************************************************************** + reply to an ioctl +****************************************************************************/ +int reply_ioctl(char *inbuf,char *outbuf) +{ + DEBUG(3,("ignoring ioctl\n")); + + return(ERROR(ERRSRV,ERRnosupport)); +} + + +/**************************************************************************** +reply to a session setup command +****************************************************************************/ +int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + int outsize = 0; + int sess_uid; + int gid; + int smb_com2; + int smb_off2; + int smb_bufsize; + int smb_mpxmax; + int smb_vc_num; + uint32 smb_sesskey; + int smb_apasslen; + pstring smb_apasswd; + int smb_ntpasslen = 0; + pstring smb_ntpasswd; + BOOL valid_nt_password = False; + pstring user; + BOOL guest=False; + + *smb_apasswd = 0; + + sess_uid = SVAL(inbuf,smb_uid); + smb_com2 = CVAL(inbuf,smb_vwv0); + smb_off2 = SVAL(inbuf,smb_vwv1); + smb_bufsize = SVAL(inbuf,smb_vwv2); + smb_mpxmax = SVAL(inbuf,smb_vwv3); + smb_vc_num = SVAL(inbuf,smb_vwv4); + smb_sesskey = IVAL(inbuf,smb_vwv5); + + if (Protocol < PROTOCOL_NT1) { + smb_apasslen = SVAL(inbuf,smb_vwv7); + memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); + StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1); + } else { + uint16 passlen1 = SVAL(inbuf,smb_vwv7); + uint16 passlen2 = SVAL(inbuf,smb_vwv8); + BOOL doencrypt = SMBENCRYPT(); + char *p = smb_buf(inbuf); + if (passlen1 > 256) passlen1 = 0; + if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird + lengths sometimes */ + if(doencrypt) { + /* Save the lanman2 password and the NT md4 password. */ + smb_apasslen = passlen1; + memcpy(smb_apasswd,p,smb_apasslen); + smb_ntpasslen = passlen2; + memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); + } else { + /* for Win95 */ + if (passlen1 > passlen2) { + smb_apasslen = passlen1; + StrnCpy(smb_apasswd,p,smb_apasslen); + } else { + smb_apasslen = passlen2; + StrnCpy(smb_apasswd,p + passlen1,smb_apasslen); + } + } + if (passlen2 == 1) { + /* apparently NT sometimes sets passlen2 to 1 when it means 0. This + tries to work around that problem */ + passlen2 = 0; + } + p += passlen1 + passlen2; + strcpy(user,p); p = skip_string(p,1); + DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", + p,skip_string(p,1),skip_string(p,2))); + } + + + DEBUG(3,("sesssetupX:name=[%s]\n",user)); + + if (!*user) + strcpy(user,lp_guestaccount(-1)); + + strlower(user); + + strcpy(sesssetup_user,user); + + reload_services(True); + + add_session_user(user); + + + if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) && + !check_hosts_equiv(user)) + { + + if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) + guest = True; + + /* now check if it's a valid username/password */ + /* If an NT password was supplied try and validate with that + first. This is superior as the passwords are mixed case 128 length unicode */ + if(smb_ntpasslen && !guest) + { + if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True)) + DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); + else + valid_nt_password = True; + } + if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False)) + { + if (lp_security() >= SEC_USER) { +#if (GUEST_SESSSETUP == 0) + return(ERROR(ERRSRV,ERRbadpw)); +#endif +#if (GUEST_SESSSETUP == 1) + if (Get_Pwnam(user,True)) + return(ERROR(ERRSRV,ERRbadpw)); +#endif + } + if (*smb_apasswd || !Get_Pwnam(user,True)) + strcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } + } + + if (!Get_Pwnam(user,True)) { + DEBUG(3,("No such user %s - using guest account\n",user)); + strcpy(user,lp_guestaccount(-1)); + guest = True; + } + + if (!strequal(user,lp_guestaccount(-1)) && + lp_servicenumber(user) < 0) + { + int homes = lp_servicenumber(HOMES_NAME); + char *home = get_home_dir(user); + if (homes >= 0 && home) + lp_add_home(user,homes,home); + } + + + /* it's ok - setup a reply */ + if (Protocol < PROTOCOL_NT1) { + outsize = set_message(outbuf,3,0,True); + } else { + char *p; + outsize = set_message(outbuf,3,3,True); + p = smb_buf(outbuf); + strcpy(p,"Unix"); p = skip_string(p,1); + strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1); + strcpy(p,my_workgroup()); p = skip_string(p,1); + outsize = set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + /* perhaps grab OS version here?? */ + } + + /* Set the correct uid in the outgoing and incoming packets + We will use this on future requests to determine which + user we should become. + */ + { + struct passwd *pw = Get_Pwnam(user,False); + if (!pw) { + DEBUG(1,("Username %s is invalid on this system\n",user)); + return(ERROR(ERRSRV,ERRbadpw)); + } + gid = pw->pw_gid; + SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid); + SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid); + } + + CVAL(outbuf,smb_vwv0) = smb_com2; + SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); + + if (guest) + SSVAL(outbuf,smb_vwv2,1); + + /* register the name and uid as being validated, so further connections + to a uid can get through without a password, on the same VC */ + register_uid(SVAL(inbuf,smb_uid),gid,user,guest); + + maxxmit = MIN(maxxmit,smb_bufsize); + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + return(outsize); +} + + +/**************************************************************************** + reply to a chkpth +****************************************************************************/ +int reply_chkpth(char *inbuf,char *outbuf) +{ + int outsize = 0; + int cnum,mode; + pstring name; + BOOL ok = False; + + cnum = SVAL(inbuf,smb_tid); + + strcpy(name,smb_buf(inbuf) + 1); + unix_convert(name,cnum); + + mode = SVAL(inbuf,smb_vwv0); + + if (check_name(name,cnum)) + ok = directory_exist(name,NULL); + + if (!ok) + return(ERROR(ERRDOS,ERRbadpath)); + + outsize = set_message(outbuf,0,0,True); + + DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode)); + + return(outsize); +} + + +/**************************************************************************** + reply to a getatr +****************************************************************************/ +int reply_getatr(char *inbuf,char *outbuf) +{ + pstring fname; + int cnum; + int outsize = 0; + struct stat sbuf; + BOOL ok = False; + int mode=0; + uint32 size=0; + time_t mtime=0; + + cnum = SVAL(inbuf,smb_tid); + + strcpy(fname,smb_buf(inbuf) + 1); + unix_convert(fname,cnum); + + /* dos smetimes asks for a stat of "" - it returns a "hidden directory" + under WfWg - weird! */ + if (! (*fname)) + { + mode = aHIDDEN | aDIR; + if (!CAN_WRITE(cnum)) mode |= aRONLY; + size = 0; + mtime = 0; + ok = True; + } + else + if (check_name(fname,cnum)) + { + if (sys_stat(fname,&sbuf) == 0) + { + mode = dos_mode(cnum,fname,&sbuf); + size = sbuf.st_size; + mtime = sbuf.st_mtime; + if (mode & aDIR) + size = 0; + ok = True; + } + else + DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); + } + + if (!ok) + return(UNIXERROR(ERRDOS,ERRbadfile)); + + outsize = set_message(outbuf,10,0,True); + + SSVAL(outbuf,smb_vwv0,mode); + put_dos_date3(outbuf,smb_vwv1,mtime); + SIVAL(outbuf,smb_vwv3,size); + + if (Protocol >= PROTOCOL_NT1) { + char *p = strrchr(fname,'/'); + uint16 flg2 = SVAL(outbuf,smb_flg2); + if (!p) p = fname; + if (!is_8_3(fname)) + SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + } + + DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size)); + + return(outsize); +} + + +/**************************************************************************** + reply to a setatr +****************************************************************************/ +int reply_setatr(char *inbuf,char *outbuf) +{ + pstring fname; + int cnum; + int outsize = 0; + BOOL ok=False; + int mode; + time_t mtime; + + cnum = SVAL(inbuf,smb_tid); + + strcpy(fname,smb_buf(inbuf) + 1); + unix_convert(fname,cnum); + + mode = SVAL(inbuf,smb_vwv0); + mtime = make_unix_date3(inbuf+smb_vwv1); + + if (directory_exist(fname,NULL)) + mode |= aDIR; + if (check_name(fname,cnum)) + ok = (dos_chmod(cnum,fname,mode,NULL) == 0); + if (ok) + ok = set_filetime(fname,mtime); + + if (!ok) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize = set_message(outbuf,0,0,True); + + DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode)); + + return(outsize); +} + + +/**************************************************************************** + reply to a dskattr +****************************************************************************/ +int reply_dskattr(char *inbuf,char *outbuf) +{ + int cnum; + int outsize = 0; + int dfree,dsize,bsize; + + cnum = SVAL(inbuf,smb_tid); + + sys_disk_free(".",&bsize,&dfree,&dsize); + + outsize = set_message(outbuf,5,0,True); + + SSVAL(outbuf,smb_vwv0,dsize); + SSVAL(outbuf,smb_vwv1,bsize/512); + SSVAL(outbuf,smb_vwv2,512); + SSVAL(outbuf,smb_vwv3,dfree); + + DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree)); + + return(outsize); +} + + +/**************************************************************************** + reply to a search + Can be called from SMBsearch, SMBffirst or SMBfunique. +****************************************************************************/ +int reply_search(char *inbuf,char *outbuf) +{ + pstring mask; + pstring directory; + pstring fname; + int size,mode; + time_t date; + int dirtype; + int cnum; + int outsize = 0; + int numentries = 0; + BOOL finished = False; + int maxentries; + int i; + char *p; + BOOL ok = False; + int status_len; + char *path; + char status[21]; + int dptr_num= -1; + BOOL check_descend = False; + BOOL expect_close = False; + BOOL can_open = True; + + *mask = *directory = *fname = 0; + + /* If we were called as SMBffirst then we must expect close. */ + if(CVAL(inbuf,smb_com) == SMBffirst) + expect_close = True; + + cnum = SVAL(inbuf,smb_tid); + + outsize = set_message(outbuf,1,3,True); + maxentries = SVAL(inbuf,smb_vwv0); + dirtype = SVAL(inbuf,smb_vwv1); + path = smb_buf(inbuf) + 1; + status_len = SVAL(smb_buf(inbuf),3 + strlen(path)); + + + /* dirtype &= ~aDIR; */ + + DEBUG(5,("path=%s status_len=%d\n",path,status_len)); + + + if (status_len == 0) + { + pstring dir2; + + strcpy(directory,smb_buf(inbuf)+1); + strcpy(dir2,smb_buf(inbuf)+1); + unix_convert(directory,cnum); + unix_format(dir2); + + if (!check_name(directory,cnum)) + can_open = False; + + p = strrchr(dir2,'/'); + if (p == NULL) + {strcpy(mask,dir2);*dir2 = 0;} + else + {*p = 0;strcpy(mask,p+1);} + + p = strrchr(directory,'/'); + if (!p) + *directory = 0; + else + *p = 0; + + if (strlen(directory) == 0) + strcpy(directory,"./"); + bzero(status,21); + CVAL(status,0) = dirtype; + } + else + { + memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); + memcpy(mask,status+1,11); + mask[11] = 0; + dirtype = CVAL(status,0) & 0x1F; + Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num); + if (!Connections[cnum].dirptr) + goto SearchEmpty; + string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); + if (!case_sensitive) + strnorm(mask); + } + + /* turn strings of spaces into a . */ + { + trim_string(mask,NULL," "); + if ((p = strrchr(mask,' '))) + { + fstring ext; + strcpy(ext,p+1); + *p = 0; + trim_string(mask,NULL," "); + strcat(mask,"."); + strcat(mask,ext); + } + } + + { + for (p=mask; *p; p++) + { + if (*p != '?' && *p != '*' && !isdoschar(*p)) + { + DEBUG(5,("Invalid char [%c] in search mask?\n",*p)); + *p = '?'; + } + } + } + + if (!strchr(mask,'.') && strlen(mask)>8) + { + fstring tmp; + strcpy(tmp,&mask[8]); + mask[8] = '.'; + mask[9] = 0; + strcat(mask,tmp); + } + + DEBUG(5,("mask=%s directory=%s\n",mask,directory)); + + if (can_open) + { + p = smb_buf(outbuf) + 3; + + ok = True; + + if (status_len == 0) + { + dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid)); + if (dptr_num < 0) + return(ERROR(ERRDOS,ERRnofids)); + } + + DEBUG(4,("dptr_num is %d\n",dptr_num)); + + if (ok) + { + if ((dirtype&0x1F) == aVOLID) + { + memcpy(p,status,21); + make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0); + dptr_fill(p+12,dptr_num); + if (dptr_zero(p+12) && (status_len==0)) + numentries = 1; + else + numentries = 0; + p += DIR_STRUCT_SIZE; + } + else + { + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); + if (in_list(Connections[cnum].dirpath, + lp_dontdescend(SNUM(cnum)),True)) + check_descend = True; + + for (i=numentries;(i= 0 && CVAL(inbuf,smb_com) == SMBfunique) + dptr_close(dptr_num); + + SSVAL(outbuf,smb_vwv0,numentries); + SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); + CVAL(smb_buf(outbuf),0) = 5; + SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); + + if (Protocol >= PROTOCOL_NT1) { + uint16 flg2 = SVAL(outbuf,smb_flg2); + SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + } + + outsize += DIR_STRUCT_SIZE*numentries; + smb_setlen(outbuf,outsize - 4); + + if ((! *directory) && dptr_path(dptr_num)) + sprintf(directory,"(%s)",dptr_path(dptr_num)); + + DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n", + timestring(), + smb_fn_name(CVAL(inbuf,smb_com)), + mask,directory,cnum,dirtype,numentries,maxentries)); + + return(outsize); +} + + +/**************************************************************************** + reply to a fclose (stop directory search) +****************************************************************************/ +int reply_fclose(char *inbuf,char *outbuf) +{ + int cnum; + int outsize = 0; + int status_len; + char *path; + char status[21]; + int dptr_num= -1; + + cnum = SVAL(inbuf,smb_tid); + + outsize = set_message(outbuf,1,0,True); + path = smb_buf(inbuf) + 1; + status_len = SVAL(smb_buf(inbuf),3 + strlen(path)); + + + if (status_len == 0) + return(ERROR(ERRSRV,ERRsrverror)); + + memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); + + if(dptr_fetch(status+12,&dptr_num)) { + /* Close the dptr - we know it's gone */ + dptr_close(dptr_num); + } + + SSVAL(outbuf,smb_vwv0,0); + + DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum)); + + return(outsize); +} + + +/**************************************************************************** + reply to an open +****************************************************************************/ +int reply_open(char *inbuf,char *outbuf) +{ + pstring fname; + int cnum; + int fnum = -1; + int outsize = 0; + int fmode=0; + int share_mode; + int size = 0; + time_t mtime=0; + int unixmode; + int rmode=0; + struct stat sbuf; + + cnum = SVAL(inbuf,smb_tid); + + share_mode = SVAL(inbuf,smb_vwv0); + + strcpy(fname,smb_buf(inbuf)+1); + unix_convert(fname,cnum); + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + + if (!check_name(fname,cnum)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + unixmode = unix_mode(cnum,aARCH); + + open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL); + + if (!Files[fnum].open) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if (fstat(Files[fnum].fd,&sbuf) != 0) { + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + mtime = sbuf.st_mtime; + + if (fmode & aDIR) { + DEBUG(3,("attempt to open a directory %s\n",fname)); + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + outsize = set_message(outbuf,7,0,True); + SSVAL(outbuf,smb_vwv0,fnum); + SSVAL(outbuf,smb_vwv1,fmode); + put_dos_date3(outbuf,smb_vwv2,mtime); + SIVAL(outbuf,smb_vwv4,size); + SSVAL(outbuf,smb_vwv6,rmode); + + return(outsize); +} + + +/**************************************************************************** + reply to an open and X +****************************************************************************/ +int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + pstring fname; + int cnum = SVAL(inbuf,smb_tid); + int fnum = -1; + int outsize = 0; + int openmode = 0; + int smb_com2 = CVAL(inbuf,smb_vwv0); + int smb_off2 = SVAL(inbuf,smb_vwv1); + int smb_mode = SVAL(inbuf,smb_vwv3); + int smb_attr = SVAL(inbuf,smb_vwv5); +#if 0 + int open_flags = SVAL(inbuf,smb_vwv2); + int smb_sattr = SVAL(inbuf,smb_vwv4); + uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); +#endif + int smb_ofun = SVAL(inbuf,smb_vwv8); + int unixmode; + int size=0,fmode=0,mtime=0,rmode=0; + struct stat sbuf; + int smb_action = 0; + + /* XXXX we need to handle passed times, sattr and flags */ + + strcpy(fname,smb_buf(inbuf)); + unix_convert(fname,cnum); + + /* now add create and trunc bits */ + if (smb_ofun & 0x10) + openmode |= O_CREAT; + if ((smb_ofun & 0x3) == 2) + openmode |= O_TRUNC; + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + + if (!check_name(fname,cnum)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + unixmode = unix_mode(cnum,smb_attr | aARCH); + + open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, + &rmode,&smb_action); + + if (!Files[fnum].open) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if (fstat(Files[fnum].fd,&sbuf) != 0) { + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + mtime = sbuf.st_mtime; + if (fmode & aDIR) { + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + outsize = set_message(outbuf,15,0,True); + CVAL(outbuf,smb_vwv0) = smb_com2; + SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); + SSVAL(outbuf,smb_vwv2,fnum); + SSVAL(outbuf,smb_vwv3,fmode); + put_dos_date3(outbuf,smb_vwv4,mtime); + SIVAL(outbuf,smb_vwv6,size); + SSVAL(outbuf,smb_vwv8,rmode); + SSVAL(outbuf,smb_vwv11,smb_action); + + chain_fnum = fnum; + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + chain_fnum = -1; + + return(outsize); +} + + +/**************************************************************************** + reply to a SMBulogoffX +****************************************************************************/ +int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) +{ + int outsize = 0; + int smb_com2 = CVAL(inbuf,smb_vwv0); + int smb_off2 = SVAL(inbuf,smb_vwv1); + int uid = SVAL(inbuf,smb_uid); + + invalidate_uid(uid); + + outsize = set_message(outbuf,2,0,True); + CVAL(outbuf,smb_vwv0) = smb_com2; + SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); + + DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid)); + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + + return(outsize); +} + + +/**************************************************************************** + reply to a mknew +****************************************************************************/ +int reply_mknew(char *inbuf,char *outbuf) +{ + pstring fname; + int cnum,com; + int fnum = -1; + int outsize = 0; + int createmode; + mode_t unixmode; + + com = SVAL(inbuf,smb_com); + cnum = SVAL(inbuf,smb_tid); + + createmode = SVAL(inbuf,smb_vwv0); + strcpy(fname,smb_buf(inbuf)+1); + unix_convert(fname,cnum); + + if (createmode & aVOLID) + { + DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); + } + + unixmode = unix_mode(cnum,createmode); + + if (com == SMBmknew && file_exist(fname,NULL)) + return(ERROR(ERRDOS,ERRfilexists)); + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + + if (!check_name(fname,cnum)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode); + + if (!Files[fnum].open) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,fnum); + + DEBUG(2,("new file %s\n",fname)); + DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd,fnum,cnum,createmode,unixmode)); + + return(outsize); +} + + +/**************************************************************************** + reply to a create temporary file +****************************************************************************/ +int reply_ctemp(char *inbuf,char *outbuf) +{ + pstring fname; + pstring fname2; + int cnum; + int fnum = -1; + int outsize = 0; + int createmode; + mode_t unixmode; + + cnum = SVAL(inbuf,smb_tid); + createmode = SVAL(inbuf,smb_vwv0); + sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1); + unix_convert(fname,cnum); + + unixmode = unix_mode(cnum,createmode); + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + + if (!check_name(fname,cnum)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + strcpy(fname2,(char *)mktemp(fname)); + + open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode); + + if (!Files[fnum].open) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize = set_message(outbuf,1,2 + strlen(fname2),True); + SSVAL(outbuf,smb_vwv0,fnum); + CVAL(smb_buf(outbuf),0) = 4; + strcpy(smb_buf(outbuf) + 1,fname2); + + DEBUG(2,("created temp file %s\n",fname2)); + DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd,fnum,cnum,createmode,unixmode)); + + return(outsize); +} + + +/******************************************************************* +check if a user is allowed to delete a file +********************************************************************/ +static BOOL can_delete(char *fname,int cnum,int dirtype) +{ + struct stat sbuf; + int fmode; + + if (!CAN_WRITE(cnum)) return(False); + + if (sys_lstat(fname,&sbuf) != 0) return(False); + fmode = dos_mode(cnum,fname,&sbuf); + if (fmode & aDIR) return(False); + if (fmode & aRONLY) return(False); + if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) + return(False); + if (!check_file_sharing(cnum,fname)) return(False); + return(True); +} + +/**************************************************************************** + reply to a unlink +****************************************************************************/ +int reply_unlink(char *inbuf,char *outbuf) +{ + int outsize = 0; + pstring name; + int cnum; + int dirtype; + pstring directory; + pstring mask; + char *p; + int count=0; + int error = ERRnoaccess; + BOOL has_wild; + BOOL exists=False; + + *directory = *mask = 0; + + cnum = SVAL(inbuf,smb_tid); + dirtype = SVAL(inbuf,smb_vwv0); + + strcpy(name,smb_buf(inbuf) + 1); + + DEBUG(3,("reply_unlink : %s\n",name)); + + unix_convert(name,cnum); + + p = strrchr(name,'/'); + if (!p) { + strcpy(directory,"./"); + strcpy(mask,name); + } else { + *p = 0; + strcpy(directory,name); + strcpy(mask,p+1); + } + + if (is_mangled(mask)) + check_mangled_stack(mask); + + has_wild = strchr(mask,'*') || strchr(mask,'?'); + + if (!has_wild) { + strcat(directory,"/"); + strcat(directory,mask); + if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++; + if (!count) exists = file_exist(directory,NULL); + } else { + void *dirptr = NULL; + char *dname; + + if (check_name(directory,cnum)) + dirptr = OpenDir(directory); + + if (dirptr) + { + error = ERRbadfile; + + if (strequal(mask,"????????.???")) + strcpy(mask,"*"); + + while ((dname = ReadDirName(dirptr))) + { + pstring fname; + strcpy(fname,dname); + + if(!mask_match(fname, mask, case_sensitive, False)) continue; + + error = ERRnoaccess; + sprintf(fname,"%s/%s",directory,dname); + if (!can_delete(fname,cnum,dirtype)) continue; + if (!sys_unlink(fname)) count++; + DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); + } + CloseDir(dirptr); + } + } + + if (count == 0) { + if (exists) + return(ERROR(ERRDOS,error)); + else + return(UNIXERROR(ERRDOS,error)); + } + + outsize = set_message(outbuf,0,0,True); + + return(outsize); +} + + +/**************************************************************************** + reply to a readbraw (core+ protocol) +****************************************************************************/ +int reply_readbraw(char *inbuf, char *outbuf) +{ + int cnum,maxcount,mincount,fnum; + int nread = 0; + int startpos; + char *header = outbuf; + int ret=0; + int fd; + char *fname; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + startpos = IVAL(inbuf,smb_vwv1); + maxcount = SVAL(inbuf,smb_vwv3); + mincount = SVAL(inbuf,smb_vwv4); + + /* ensure we don't overrun the packet size */ + maxcount = MIN(65535,maxcount); + maxcount = MAX(mincount,maxcount); + + if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read) + { + DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); + _smb_setlen(header,0); + transfer_file(0,Client,0,header,4,0); + return(-1); + } + else + { + fd = Files[fnum].fd; + fname = Files[fnum].name; + } + + + if (!is_locked(fnum,cnum,maxcount,startpos)) + { + int size = Files[fnum].size; + int sizeneeded = startpos + maxcount; + + if (size < sizeneeded) { + struct stat st; + if (fstat(Files[fnum].fd,&st) == 0) + size = st.st_size; + if (!Files[fnum].can_write) + Files[fnum].size = size; + } + + nread = MIN(maxcount,size - startpos); + } + + if (nread < mincount) + nread = 0; + + DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n", + timestring(), + fnum,cnum,startpos, + maxcount,mincount,nread)); + +#if UNSAFE_READRAW + { + int predict=0; + _smb_setlen(header,nread); + + if (!Files[fnum].can_write) + predict = read_predict(fd,startpos,header+4,NULL,nread); + + if ((nread-predict) > 0) + seek_file(fnum,startpos + predict); + + ret = transfer_file(fd,Client,nread-predict,header,4+predict, + startpos+predict); + } + + if (ret != nread+4) + DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n", + fname,startpos,nread,ret)); + +#else + ret = read_file(fnum,header+4,startpos,nread,nread,-1,False); + if (ret < mincount) ret = 0; + + _smb_setlen(header,ret); + transfer_file(0,Client,0,header,4+ret,0); +#endif + + DEBUG(5,("readbraw finished\n")); + return -1; +} + + +/**************************************************************************** + reply to a lockread (core+ protocol) +****************************************************************************/ +int reply_lockread(char *inbuf,char *outbuf) +{ + int cnum,fnum; + int nread = -1; + char *data; + int outsize = 0; + uint32 startpos, numtoread; + int eclass; + uint32 ecode; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_READ(fnum); + CHECK_ERROR(fnum); + + numtoread = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + + outsize = set_message(outbuf,5,3,True); + numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + data = smb_buf(outbuf) + 3; + + if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode)) + return (ERROR(eclass,ecode)); + + nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False); + + if (nread < 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize += nread; + SSVAL(outbuf,smb_vwv0,nread); + SSVAL(outbuf,smb_vwv5,nread+3); + SSVAL(smb_buf(outbuf),1,nread); + + DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread)); + + return(outsize); +} + + +/**************************************************************************** + reply to a read +****************************************************************************/ +int reply_read(char *inbuf,char *outbuf) +{ + int cnum,numtoread,fnum; + int nread = 0; + char *data; + int startpos; + int outsize = 0; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_READ(fnum); + CHECK_ERROR(fnum); + + numtoread = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + + outsize = set_message(outbuf,5,3,True); + numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + data = smb_buf(outbuf) + 3; + + if (is_locked(fnum,cnum,numtoread,startpos)) + return(ERROR(ERRDOS,ERRlock)); + + if (numtoread > 0) + nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False); + + if (nread < 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize += nread; + SSVAL(outbuf,smb_vwv0,nread); + SSVAL(outbuf,smb_vwv5,nread+3); + CVAL(smb_buf(outbuf),0) = 1; + SSVAL(smb_buf(outbuf),1,nread); + + DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread)); + + return(outsize); +} + + +/**************************************************************************** + reply to a read and X +****************************************************************************/ +int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + int smb_com2 = CVAL(inbuf,smb_vwv0); + int smb_off2 = SVAL(inbuf,smb_vwv1); + int fnum = GETFNUM(inbuf,smb_vwv2); + uint32 smb_offs = IVAL(inbuf,smb_vwv3); + int smb_maxcnt = SVAL(inbuf,smb_vwv5); + int smb_mincnt = SVAL(inbuf,smb_vwv6); + int cnum; + int nread = -1; + char *data; + int outsize = 0; + BOOL ok = False; + + cnum = SVAL(inbuf,smb_tid); + + CHECK_FNUM(fnum,cnum); + CHECK_READ(fnum); + CHECK_ERROR(fnum); + + outsize = set_message(outbuf,12,0,True); + data = smb_buf(outbuf); + + if (is_locked(fnum,cnum,smb_maxcnt,smb_offs)) + return(ERROR(ERRDOS,ERRlock)); + nread = read_file(fnum,data,smb_offs,smb_maxcnt,smb_maxcnt,-1,False); + ok = True; + + if (nread < 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize += nread; + CVAL(outbuf,smb_vwv0) = smb_com2; + SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4); + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf) + chain_size); + SSVAL(smb_buf(outbuf),-2,nread); + + DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d com2=%d off2=%d\n", + timestring(),fnum,cnum, + smb_mincnt,smb_maxcnt,nread,smb_com2,smb_off2)); + + chain_fnum = fnum; + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + chain_fnum = -1; + + return(outsize); +} + + +/**************************************************************************** + reply to a writebraw (core+ or LANMAN1.0 protocol) +****************************************************************************/ +int reply_writebraw(char *inbuf,char *outbuf) +{ + int nwritten=0; + int total_written=0; + int numtowrite=0; + int cnum,fnum; + int outsize = 0; + long startpos; + char *data=NULL; + BOOL write_through; + int tcount; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + tcount = IVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv3); + write_through = BITSETW(inbuf+smb_vwv7,0); + + /* We have to deal with slightly different formats depending + on whether we are using the core+ or lanman1.0 protocol */ + if(Protocol <= PROTOCOL_COREPLUS) { + numtowrite = SVAL(smb_buf(inbuf),-2); + data = smb_buf(inbuf); + } else { + numtowrite = SVAL(inbuf,smb_vwv10); + data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11); + } + + /* force the error type */ + CVAL(inbuf,smb_com) = SMBwritec; + CVAL(outbuf,smb_com) = SMBwritec; + + if (is_locked(fnum,cnum,tcount,startpos)) + return(ERROR(ERRDOS,ERRlock)); + + if (seek_file(fnum,startpos) != startpos) + DEBUG(0,("couldn't seek to %d in writebraw\n",startpos)); + + if (numtowrite>0) + nwritten = write_file(fnum,data,numtowrite); + + DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n", + timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through)); + + if (nwritten < numtowrite) + return(UNIXERROR(ERRHRD,ERRdiskfull)); + + total_written = nwritten; + + /* Return a message to the redirector to tell it + to send more bytes */ + CVAL(outbuf,smb_com) = SMBwritebraw; + SSVALS(outbuf,smb_vwv0,-1); + outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); + send_smb(Client,outbuf); + + /* Now read the raw data into the buffer and write it */ + if(read_smb_length(Client,inbuf,0) == -1) { + exit_server("secondary writebraw failed"); + } + + /* Even though this is not an smb message, smb_len + returns the generic length of an smb message */ + numtowrite = smb_len(inbuf); + + if (tcount > nwritten+numtowrite) { + DEBUG(3,("Client overestimated the write %d %d %d\n", + tcount,nwritten,numtowrite)); + } + + nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0, + startpos+nwritten); + total_written += nwritten; + + /* Set up outbuf to return the correct return */ + outsize = set_message(outbuf,1,0,True); + CVAL(outbuf,smb_com) = SMBwritec; + SSVAL(outbuf,smb_vwv0,total_written); + + if (nwritten < numtowrite) { + CVAL(outbuf,smb_rcls) = ERRHRD; + SSVAL(outbuf,smb_err,ERRdiskfull); + } + + if (lp_syncalways(SNUM(cnum)) || write_through) + sync_file(fnum); + + DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n", + timestring(),fnum,cnum,startpos,numtowrite,total_written)); + + /* we won't return a status if write through is not selected - this + follows what WfWg does */ + if (!write_through && total_written==tcount) + return(-1); + + return(outsize); +} + + +/**************************************************************************** + reply to a writeunlock (core+) +****************************************************************************/ +int reply_writeunlock(char *inbuf,char *outbuf) +{ + int cnum,fnum; + int nwritten = -1; + int outsize = 0; + char *data; + uint32 numtowrite,startpos; + int eclass; + uint32 ecode; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + numtowrite = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + data = smb_buf(inbuf) + 3; + + if (is_locked(fnum,cnum,numtowrite,startpos)) + return(ERROR(ERRDOS,ERRlock)); + + seek_file(fnum,startpos); + + /* The special X/Open SMB protocol handling of + zero length writes is *NOT* done for + this call */ + if(numtowrite == 0) + nwritten = 0; + else + nwritten = write_file(fnum,data,numtowrite); + + if (lp_syncalways(SNUM(cnum))) + sync_file(fnum); + + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode)) + return(ERROR(eclass,ecode)); + + outsize = set_message(outbuf,1,0,True); + + SSVAL(outbuf,smb_vwv0,nwritten); + + DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n", + timestring(),fnum,cnum,numtowrite,nwritten)); + + return(outsize); +} + + +/**************************************************************************** + reply to a write +****************************************************************************/ +int reply_write(char *inbuf,char *outbuf,int dum1,int dum2) +{ + int cnum,numtowrite,fnum; + int nwritten = -1; + int outsize = 0; + int startpos; + char *data; + + dum1 = dum2 = 0; + + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + numtowrite = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + data = smb_buf(inbuf) + 3; + + if (is_locked(fnum,cnum,numtowrite,startpos)) + return(ERROR(ERRDOS,ERRlock)); + + seek_file(fnum,startpos); + + /* X/Open SMB protocol says that if smb_vwv1 is + zero then the file size should be extended or + truncated to the size given in smb_vwv[2-3] */ + if(numtowrite == 0) + nwritten = set_filelen(Files[fnum].fd, startpos); + else + nwritten = write_file(fnum,data,numtowrite); + + if (lp_syncalways(SNUM(cnum))) + sync_file(fnum); + + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize = set_message(outbuf,1,0,True); + + SSVAL(outbuf,smb_vwv0,nwritten); + + if (nwritten < numtowrite) { + CVAL(outbuf,smb_rcls) = ERRHRD; + SSVAL(outbuf,smb_err,ERRdiskfull); + } + + DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten)); + + return(outsize); +} + + +/**************************************************************************** + reply to a write and X +****************************************************************************/ +int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + int smb_com2 = CVAL(inbuf,smb_vwv0); + int smb_off2 = SVAL(inbuf,smb_vwv1); + int fnum = GETFNUM(inbuf,smb_vwv2); + uint32 smb_offs = IVAL(inbuf,smb_vwv3); + int smb_dsize = SVAL(inbuf,smb_vwv10); + int smb_doff = SVAL(inbuf,smb_vwv11); + BOOL write_through = BITSETW(inbuf+smb_vwv7,0); + int cnum; + int nwritten = -1; + int outsize = 0; + char *data; + + cnum = SVAL(inbuf,smb_tid); + + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + data = smb_base(inbuf) + smb_doff; + + if (is_locked(fnum,cnum,smb_dsize,smb_offs)) + return(ERROR(ERRDOS,ERRlock)); + + seek_file(fnum,smb_offs); + + /* X/Open SMB protocol says that, unlike SMBwrite + if the length is zero then NO truncation is + done, just a write of zero. To truncate a file, + use SMBwrite. */ + if(smb_dsize == 0) + nwritten = 0; + else + nwritten = write_file(fnum,data,smb_dsize); + + if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize = set_message(outbuf,6,0,True); + + CVAL(outbuf,smb_vwv0) = smb_com2; + SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4); + SSVAL(outbuf,smb_vwv2,nwritten); + + if (nwritten < smb_dsize) { + CVAL(outbuf,smb_rcls) = ERRHRD; + SSVAL(outbuf,smb_err,ERRdiskfull); + } + + DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten)); + + chain_fnum = fnum; + + if (lp_syncalways(SNUM(cnum)) || write_through) + sync_file(fnum); + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + chain_fnum = -1; + + return(outsize); +} + + +/**************************************************************************** + reply to a lseek +****************************************************************************/ +int reply_lseek(char *inbuf,char *outbuf) +{ + int cnum,fnum; + uint32 startpos; + int32 res= -1; + int mode,umode; + int outsize = 0; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + mode = SVAL(inbuf,smb_vwv1) & 3; + startpos = IVAL(inbuf,smb_vwv2); + + switch (mode & 3) + { + case 0: umode = SEEK_SET; break; + case 1: umode = SEEK_CUR; break; + case 2: umode = SEEK_END; break; + default: + umode = SEEK_SET; break; + } + + res = lseek(Files[fnum].fd,startpos,umode); + Files[fnum].pos = res; + + outsize = set_message(outbuf,2,0,True); + SIVALS(outbuf,smb_vwv0,res); + + DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode)); + + return(outsize); +} + + +/**************************************************************************** + reply to a flush +****************************************************************************/ +int reply_flush(char *inbuf,char *outbuf) +{ + int cnum, fnum; + int outsize = set_message(outbuf,0,0,True); + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + if (fnum != 0xFFFF) { + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + } + + if (fnum == 0xFFFF) + { + int i; + for (i=0;iwr_errclass; + err = Files[fnum].wbmpx_ptr->wr_error; + } + + mtime = make_unix_date3(inbuf+smb_vwv1); + + close_file(fnum); + + /* try and set the date */ + set_filetime(Files[fnum].name,mtime); + + /* We have a cached error */ + if(eclass || err) + return(ERROR(eclass,err)); + + DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", + timestring(),Files[fnum].fd,fnum,cnum, + Connections[cnum].num_files_open)); + + return(outsize); +} + + +/**************************************************************************** + reply to a writeclose (Core+ protocol) +****************************************************************************/ +int reply_writeclose(char *inbuf,char *outbuf) +{ + int cnum,numtowrite,fnum; + int nwritten = -1; + int outsize = 0; + int startpos; + char *data; + time_t mtime; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + numtowrite = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + mtime = make_unix_date3(inbuf+smb_vwv4); + data = smb_buf(inbuf) + 1; + + if (is_locked(fnum,cnum,numtowrite,startpos)) + return(ERROR(ERRDOS,ERRlock)); + + seek_file(fnum,startpos); + + nwritten = write_file(fnum,data,numtowrite); + + close_file(fnum); + + set_filetime(Files[fnum].name,mtime); + + DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", + timestring(),fnum,cnum,numtowrite,nwritten, + Connections[cnum].num_files_open)); + + if (nwritten <= 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize = set_message(outbuf,1,0,True); + + SSVAL(outbuf,smb_vwv0,nwritten); + return(outsize); +} + + +/**************************************************************************** + reply to a lock +****************************************************************************/ +int reply_lock(char *inbuf,char *outbuf) +{ + int fnum,cnum; + int outsize = set_message(outbuf,0,0,True); + uint32 count,offset; + int eclass; + uint32 ecode; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + count = IVAL(inbuf,smb_vwv1); + offset = IVAL(inbuf,smb_vwv3); + + DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count)); + + if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode)) + return (ERROR(eclass,ecode)); + + return(outsize); +} + + +/**************************************************************************** + reply to a unlock +****************************************************************************/ +int reply_unlock(char *inbuf,char *outbuf) +{ + int fnum,cnum; + int outsize = set_message(outbuf,0,0,True); + uint32 count,offset; + int eclass; + uint32 ecode; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + count = IVAL(inbuf,smb_vwv1); + offset = IVAL(inbuf,smb_vwv3); + + if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode)) + return (ERROR(eclass,ecode)); + + DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count)); + + return(outsize); +} + + +/**************************************************************************** + reply to a tdis +****************************************************************************/ +int reply_tdis(char *inbuf,char *outbuf) +{ + int cnum, uid; + int outsize = set_message(outbuf,0,0,True); + + cnum = SVAL(inbuf,smb_tid); + uid = SVAL(inbuf,smb_uid); + + Connections[cnum].used = False; + + close_cnum(cnum,uid); + + DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum)); + + return outsize; +} + + + +/**************************************************************************** + reply to a echo +****************************************************************************/ +int reply_echo(char *inbuf,char *outbuf) +{ + int cnum; + int smb_reverb = SVAL(inbuf,smb_vwv0); + int seq_num; + int data_len = smb_buflen(inbuf); + int outsize = set_message(outbuf,1,data_len,True); + + cnum = SVAL(inbuf,smb_tid); + + if (cnum != 0xFFFF && !OPEN_CNUM(cnum)) + { + DEBUG(4,("Invalid cnum in echo (%d)\n",cnum)); + return(ERROR(ERRSRV,ERRinvnid)); + } + + /* copy any incoming data back out */ + if (data_len > 0) + memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len); + + if (smb_reverb > 100) + { + DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb)); + smb_reverb = 100; + } + + for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) + { + SSVAL(outbuf,smb_vwv0,seq_num); + + smb_setlen(outbuf,outsize - 4); + + send_smb(Client,outbuf); + } + + DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum)); + + return -1; +} + + +/**************************************************************************** + reply to a printopen +****************************************************************************/ +int reply_printopen(char *inbuf,char *outbuf) +{ + pstring fname; + pstring fname2; + int cnum; + int fnum = -1; + int outsize = 0; + + *fname = *fname2 = 0; + + cnum = SVAL(inbuf,smb_tid); + + if (!CAN_PRINT(cnum)) + return(ERROR(ERRDOS,ERRnoaccess)); + + { + pstring s; + char *p; + StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1); + p = s; + while (*p) + { + if (!(isalnum(*p) || strchr("._-",*p))) + *p = 'X'; + p++; + } + + if (strlen(s) > 10) s[10] = 0; + + sprintf(fname,"%s.XXXXXX",s); + } + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + + strcpy(fname2,(char *)mktemp(fname)); + + if (!check_name(fname2,cnum)) + return(ERROR(ERRDOS,ERRnoaccess)); + + open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC, + unix_mode(cnum,0)); + + if (!Files[fnum].open) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + /* force it to be a print file */ + Files[fnum].print_file = True; + + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,fnum); + + DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum)); + + return(outsize); +} + + +/**************************************************************************** + reply to a printclose +****************************************************************************/ +int reply_printclose(char *inbuf,char *outbuf) +{ + int fnum,cnum; + int outsize = set_message(outbuf,0,0,True); + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + if (!CAN_PRINT(cnum)) + return(ERROR(ERRDOS,ERRnoaccess)); + + close_file(fnum); + + DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum)); + + return(outsize); +} + + +/**************************************************************************** + reply to a printqueue +****************************************************************************/ +int reply_printqueue(char *inbuf,char *outbuf) +{ + int cnum, uid; + int outsize = set_message(outbuf,2,3,True); + int max_count = SVAL(inbuf,smb_vwv0); + int start_index = SVAL(inbuf,smb_vwv1); + + cnum = SVAL(inbuf,smb_tid); + uid = SVAL(inbuf,smb_uid); + +/* allow checking the queue for anyone */ +#if 0 + if (!CAN_PRINT(cnum)) + return(ERROR(ERRDOS,ERRnoaccess)); +#endif + + SSVAL(outbuf,smb_vwv0,0); + SSVAL(outbuf,smb_vwv1,0); + CVAL(smb_buf(outbuf),0) = 1; + SSVAL(smb_buf(outbuf),1,0); + + DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n", + timestring(),cnum,start_index,max_count)); + + if (!OPEN_CNUM(cnum) || !Connections[cnum].printer) + { + int i; + cnum = -1; + + for (i=0;i0?start_index:start_index+max_count+1); + int i; + + if (first >= count) + num_to_get = 0; + else + num_to_get = MIN(num_to_get,count-first); + + + for (i=first;i 0) + { + outsize = set_message(outbuf,2,28*count+3,False); + SSVAL(outbuf,smb_vwv0,count); + SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); + CVAL(smb_buf(outbuf),0) = 1; + SSVAL(smb_buf(outbuf),1,28*count); + } + + if (queue) free(queue); + + DEBUG(3,("%d entries returned in queue\n",count)); + } + + return(outsize); +} + + +/**************************************************************************** + reply to a printwrite +****************************************************************************/ +int reply_printwrite(char *inbuf,char *outbuf) +{ + int cnum,numtowrite,fnum; + int outsize = set_message(outbuf,0,0,True); + char *data; + + cnum = SVAL(inbuf,smb_tid); + + if (!CAN_PRINT(cnum)) + return(ERROR(ERRDOS,ERRnoaccess)); + + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + numtowrite = SVAL(smb_buf(inbuf),1); + data = smb_buf(inbuf) + 3; + + if (write_file(fnum,data,numtowrite) != numtowrite) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite)); + + return(outsize); +} + + +/**************************************************************************** + reply to a mkdir +****************************************************************************/ +int reply_mkdir(char *inbuf,char *outbuf) +{ + pstring directory; + int cnum; + int outsize,ret= -1; + + strcpy(directory,smb_buf(inbuf) + 1); + cnum = SVAL(inbuf,smb_tid); + unix_convert(directory,cnum); + + if (check_name(directory,cnum)) + ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); + + if (ret < 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + outsize = set_message(outbuf,0,0,True); + + DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret)); + + return(outsize); +} + + +/**************************************************************************** + reply to a rmdir +****************************************************************************/ +int reply_rmdir(char *inbuf,char *outbuf) +{ + pstring directory; + int cnum; + int outsize = 0; + BOOL ok = False; + + cnum = SVAL(inbuf,smb_tid); + strcpy(directory,smb_buf(inbuf) + 1); + unix_convert(directory,cnum); + + if (check_name(directory,cnum)) + { + dptr_closepath(directory,SVAL(inbuf,smb_pid)); + ok = (sys_rmdir(directory) == 0); + if (!ok) + DEBUG(3,("couldn't remove directory %s : %s\n", + directory,strerror(errno))); + } + + if (!ok) + return(UNIXERROR(ERRDOS,ERRbadpath)); + + outsize = set_message(outbuf,0,0,True); + + DEBUG(3,("%s rmdir %s\n",timestring(),directory)); + + return(outsize); +} + + +/******************************************************************* +resolve wildcards in a filename rename +********************************************************************/ +static BOOL resolve_wildcards(char *name1,char *name2) +{ + fstring root1,root2; + fstring ext1,ext2; + char *p,*p2; + + name1 = strrchr(name1,'/'); + name2 = strrchr(name2,'/'); + + if (!name1 || !name2) return(False); + + strcpy(root1,name1); + strcpy(root2,name2); + p = strrchr(root1,'.'); + if (p) { + *p = 0; + strcpy(ext1,p+1); + } else { + strcpy(ext1,""); + } + p = strrchr(root2,'.'); + if (p) { + *p = 0; + strcpy(ext2,p+1); + } else { + strcpy(ext2,""); + } + + p = root1; + p2 = root2; + while (*p2) { + if (*p2 == '?') { + *p2 = *p; + p2++; + } else { + p2++; + } + if (*p) p++; + } + + p = ext1; + p2 = ext2; + while (*p2) { + if (*p2 == '?') { + *p2 = *p; + p2++; + } else { + p2++; + } + if (*p) p++; + } + + strcpy(name2,root2); + if (ext2[0]) { + strcat(name2,"."); + strcat(name2,ext2); + } + + return(True); +} + +/******************************************************************* +check if a user is allowed to rename a file +********************************************************************/ +static BOOL can_rename(char *fname,int cnum) +{ + struct stat sbuf; + + if (!CAN_WRITE(cnum)) return(False); + + if (sys_lstat(fname,&sbuf) != 0) return(False); + if (!check_file_sharing(cnum,fname)) return(False); + + return(True); +} + +/**************************************************************************** + reply to a mv +****************************************************************************/ +int reply_mv(char *inbuf,char *outbuf) +{ + int outsize = 0; + pstring name; + int cnum; + pstring directory; + pstring mask,newname; + char *p; + int count=0; + int error = ERRnoaccess; + BOOL has_wild; + BOOL exists=False; + + *directory = *mask = 0; + + cnum = SVAL(inbuf,smb_tid); + + strcpy(name,smb_buf(inbuf) + 1); + strcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); + + DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); + + unix_convert(name,cnum); + unix_convert(newname,cnum); + + p = strrchr(name,'/'); + if (!p) { + strcpy(directory,"./"); + strcpy(mask,name); + } else { + *p = 0; + strcpy(directory,name); + strcpy(mask,p+1); + } + + if (is_mangled(mask)) + check_mangled_stack(mask); + + has_wild = strchr(mask,'*') || strchr(mask,'?'); + + if (!has_wild) { + strcat(directory,"/"); + strcat(directory,mask); + if (resolve_wildcards(directory,newname) && + can_rename(directory,cnum) && + !file_exist(newname,NULL) && + !sys_rename(directory,newname)) count++; + if (!count) exists = file_exist(directory,NULL); + if (!count && exists && file_exist(newname,NULL)) { + exists = True; + error = 183; + } + } else { + void *dirptr = NULL; + char *dname; + pstring destname; + + if (check_name(directory,cnum)) + dirptr = OpenDir(directory); + + if (dirptr) + { + error = ERRbadfile; + + if (strequal(mask,"????????.???")) + strcpy(mask,"*"); + + while ((dname = ReadDirName(dirptr))) + { + pstring fname; + strcpy(fname,dname); + + if(!mask_match(fname, mask, case_sensitive, False)) continue; + + error = ERRnoaccess; + sprintf(fname,"%s/%s",directory,dname); + if (!can_rename(fname,cnum)) continue; + strcpy(destname,newname); + + if (!resolve_wildcards(fname,destname)) continue; + + if (file_exist(destname,NULL)) { + error = 183; + continue; + } + if (!sys_rename(fname,destname)) count++; + DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname)); + } + CloseDir(dirptr); + } + } + + if (count == 0) { + if (exists) + return(ERROR(ERRDOS,error)); + else + return(UNIXERROR(ERRDOS,error)); + } + + outsize = set_message(outbuf,0,0,True); + + return(outsize); +} + +/******************************************************************* + copy a file as part of a reply_copy + ******************************************************************/ +static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, + int count,BOOL target_is_directory) +{ + int Access,action; + struct stat st; + int ret=0; + int fnum1,fnum2; + pstring dest; + + strcpy(dest,dest1); + if (target_is_directory) { + char *p = strrchr(src,'/'); + if (p) + p++; + else + p = src; + strcat(dest,"/"); + strcat(dest,p); + } + + if (!file_exist(src,&st)) return(False); + + fnum1 = find_free_file(); + if (fnum1<0) return(False); + open_file_shared(fnum1,cnum,src,(DENY_NONE<<4), + 1,0,&Access,&action); + + if (!Files[fnum1].open) return(False); + + if (!target_is_directory && count) + ofun = 1; + + fnum2 = find_free_file(); + if (fnum2<0) { + close_file(fnum1); + return(False); + } + open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, + ofun,st.st_mode,&Access,&action); + + if (!Files[fnum2].open) { + close_file(fnum1); + return(False); + } + + if ((ofun&3) == 1) { + lseek(Files[fnum2].fd,0,SEEK_END); + } + + if (st.st_size) + ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0); + + close_file(fnum1); + close_file(fnum2); + + return(ret == st.st_size); +} + + + +/**************************************************************************** + reply to a file copy. + ****************************************************************************/ +int reply_copy(char *inbuf,char *outbuf) +{ + int outsize = 0; + pstring name; + int cnum; + pstring directory; + pstring mask,newname; + char *p; + int count=0; + int error = ERRnoaccess; + BOOL has_wild; + BOOL exists=False; + int tid2 = SVAL(inbuf,smb_vwv0); + int ofun = SVAL(inbuf,smb_vwv1); + int flags = SVAL(inbuf,smb_vwv2); + BOOL target_is_directory=False; + + *directory = *mask = 0; + + cnum = SVAL(inbuf,smb_tid); + + strcpy(name,smb_buf(inbuf)); + strcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); + + DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); + + if (tid2 != cnum) { + /* can't currently handle inter share copies XXXX */ + DEBUG(3,("Rejecting inter-share copy\n")); + return(ERROR(ERRSRV,ERRinvdevice)); + } + + unix_convert(name,cnum); + unix_convert(newname,cnum); + + target_is_directory = directory_exist(newname,NULL); + + if ((flags&1) && target_is_directory) { + return(ERROR(ERRDOS,ERRbadfile)); + } + + if ((flags&2) && !target_is_directory) { + return(ERROR(ERRDOS,ERRbadpath)); + } + + if ((flags&(1<<5)) && directory_exist(name,NULL)) { + /* wants a tree copy! XXXX */ + DEBUG(3,("Rejecting tree copy\n")); + return(ERROR(ERRSRV,ERRerror)); + } + + p = strrchr(name,'/'); + if (!p) { + strcpy(directory,"./"); + strcpy(mask,name); + } else { + *p = 0; + strcpy(directory,name); + strcpy(mask,p+1); + } + + if (is_mangled(mask)) + check_mangled_stack(mask); + + has_wild = strchr(mask,'*') || strchr(mask,'?'); + + if (!has_wild) { + strcat(directory,"/"); + strcat(directory,mask); + if (resolve_wildcards(directory,newname) && + copy_file(directory,newname,cnum,ofun, + count,target_is_directory)) count++; + if (!count) exists = file_exist(directory,NULL); + } else { + void *dirptr = NULL; + char *dname; + pstring destname; + + if (check_name(directory,cnum)) + dirptr = OpenDir(directory); + + if (dirptr) + { + error = ERRbadfile; + + if (strequal(mask,"????????.???")) + strcpy(mask,"*"); + + while ((dname = ReadDirName(dirptr))) + { + pstring fname; + strcpy(fname,dname); + + if(!mask_match(fname, mask, case_sensitive, False)) continue; + + error = ERRnoaccess; + sprintf(fname,"%s/%s",directory,dname); + strcpy(destname,newname); + if (resolve_wildcards(fname,destname) && + copy_file(directory,newname,cnum,ofun, + count,target_is_directory)) count++; + DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); + } + CloseDir(dirptr); + } + } + + if (count == 0) { + if (exists) + return(ERROR(ERRDOS,error)); + else + return(UNIXERROR(ERRDOS,error)); + } + + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,count); + + return(outsize); +} + + + +/**************************************************************************** + reply to a setdir +****************************************************************************/ +int reply_setdir(char *inbuf,char *outbuf) +{ + int cnum,snum; + int outsize = 0; + BOOL ok = False; + pstring newdir; + + cnum = SVAL(inbuf,smb_tid); + + snum = Connections[cnum].service; + if (!CAN_SETDIR(snum)) + return(ERROR(ERRDOS,ERRnoaccess)); + + strcpy(newdir,smb_buf(inbuf) + 1); + strlower(newdir); + + if (strlen(newdir) == 0) + ok = True; + else + { + ok = directory_exist(newdir,NULL); + if (ok) + string_set(&Connections[cnum].connectpath,newdir); + } + + if (!ok) + return(ERROR(ERRDOS,ERRbadpath)); + + outsize = set_message(outbuf,0,0,True); + CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh); + + DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum)); + + return(outsize); +} + + +/**************************************************************************** + reply to a lockingX request +****************************************************************************/ +int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) +{ + int smb_com2 = CVAL(inbuf,smb_vwv0); + int smb_off2 = SVAL(inbuf,smb_vwv1); + int fnum = GETFNUM(inbuf,smb_vwv2); + uint16 locktype = SVAL(inbuf,smb_vwv3); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint16 num_locks = SVAL(inbuf,smb_vwv7); + uint32 count, offset; + + int cnum; + int i; + char *data; + uint32 ecode=0, dummy2; + int outsize, eclass=0, dummy1; + + cnum = SVAL(inbuf,smb_tid); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + data = smb_buf(inbuf); + /* Data now points at the beginning of the list + of smb_unlkrng structs */ + for(i = 0; i < (int)num_ulocks; i++) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode)) + return ERROR(eclass,ecode); + } + + /* Now do any requested locks */ + data += 10*num_ulocks; + /* Data now points at the beginning of the list + of smb_lkrng structs */ + for(i = 0; i < (int)num_locks; i++) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode)) + break; + } + + /* If any of the above locks failed, then we must unlock + all of the previous locks (X/Open spec). */ + if(i != num_locks && num_locks != 0) { + for(; i >= 0; i--) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2); + } + return ERROR(eclass,ecode); + } + + outsize = set_message(outbuf,2,0,True); + + CVAL(outbuf,smb_vwv0) = smb_com2; + SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4); + + DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", + timestring(),fnum,cnum,locktype,num_locks,num_ulocks)); + + chain_fnum = fnum; + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + chain_fnum = -1; + + return(outsize); +} + + +/**************************************************************************** + reply to a SMBreadbmpx (read block multiplex) request +****************************************************************************/ +int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) +{ + int cnum,fnum; + int nread = -1; + int total_read; + char *data; + int32 startpos; + int outsize, mincount, maxcount; + int max_per_packet; + int tcount; + int pad; + + /* this function doesn't seem to work - disable by default */ + if (!lp_readbmpx()) + return(ERROR(ERRSRV,ERRuseSTD)); + + outsize = set_message(outbuf,8,0,True); + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_READ(fnum); + CHECK_ERROR(fnum); + + startpos = IVAL(inbuf,smb_vwv1); + maxcount = SVAL(inbuf,smb_vwv3); + mincount = SVAL(inbuf,smb_vwv4); + + data = smb_buf(outbuf); + pad = ((int)data)%4; + if (pad) pad = 4 - pad; + data += pad; + + max_per_packet = bufsize-(outsize+pad); + tcount = maxcount; + total_read = 0; + + if (is_locked(fnum,cnum,maxcount,startpos)) + return(ERROR(ERRDOS,ERRlock)); + + do + { + int N = MIN(max_per_packet,tcount-total_read); + + nread = read_file(fnum,data,startpos,N,N,-1,False); + + if (nread <= 0) nread = 0; + + if (nread < N) + tcount = total_read + nread; + + set_message(outbuf,8,nread,False); + SIVAL(outbuf,smb_vwv0,startpos); + SSVAL(outbuf,smb_vwv2,tcount); + SSVAL(outbuf,smb_vwv6,nread); + SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); + + send_smb(Client,outbuf); + + total_read += nread; + startpos += nread; + } + while (total_read < tcount); + + return(-1); +} + + +/**************************************************************************** + reply to a SMBwritebmpx (write block multiplex primary) request +****************************************************************************/ +int reply_writebmpx(char *inbuf,char *outbuf) +{ + int cnum,numtowrite,fnum; + int nwritten = -1; + int outsize = 0; + int32 startpos; + int tcount, write_through, smb_doff; + char *data; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + tcount = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv3); + write_through = BITSETW(inbuf+smb_vwv7,0); + numtowrite = SVAL(inbuf,smb_vwv10); + smb_doff = SVAL(inbuf,smb_vwv11); + + data = smb_base(inbuf) + smb_doff; + + /* If this fails we need to send an SMBwriteC response, + not an SMBwritebmpx - set this up now so we don't forget */ + CVAL(outbuf,smb_com) = SMBwritec; + + if (is_locked(fnum,cnum,tcount,startpos)) + return(ERROR(ERRDOS,ERRlock)); + + seek_file(fnum,startpos); + nwritten = write_file(fnum,data,numtowrite); + + if(lp_syncalways(SNUM(cnum)) || write_through) + sync_file(fnum); + + if(nwritten < numtowrite) + return(UNIXERROR(ERRHRD,ERRdiskfull)); + + /* If the maximum to be written to this file + is greater than what we just wrote then set + up a secondary struct to be attached to this + fd, we will use this to cache error messages etc. */ + if(tcount > nwritten) + { + write_bmpx_struct *wbms; + if(Files[fnum].wbmpx_ptr != NULL) + wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */ + else + wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); + if(!wbms) + { + DEBUG(0,("Out of memory in reply_readmpx\n")); + return(ERROR(ERRSRV,ERRnoresource)); + } + wbms->wr_mode = write_through; + wbms->wr_discard = False; /* No errors yet */ + wbms->wr_total_written = nwritten; + wbms->wr_errclass = 0; + wbms->wr_error = 0; + Files[fnum].wbmpx_ptr = wbms; + } + + /* We are returning successfully, set the message type back to + SMBwritebmpx */ + CVAL(outbuf,smb_com) = SMBwriteBmpx; + + outsize = set_message(outbuf,1,0,True); + + SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ + + DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n", + timestring(),fnum,cnum,numtowrite,nwritten)); + + if (write_through && tcount==nwritten) { + /* we need to send both a primary and a secondary response */ + smb_setlen(outbuf,outsize - 4); + send_smb(Client,outbuf); + + /* now the secondary */ + outsize = set_message(outbuf,1,0,True); + CVAL(outbuf,smb_com) = SMBwritec; + SSVAL(outbuf,smb_vwv0,nwritten); + } + + return(outsize); +} + + +/**************************************************************************** + reply to a SMBwritebs (write block multiplex secondary) request +****************************************************************************/ +int reply_writebs(char *inbuf,char *outbuf) +{ + int cnum,numtowrite,fnum; + int nwritten = -1; + int outsize = 0; + int32 startpos; + int tcount, write_through, smb_doff; + char *data; + write_bmpx_struct *wbms; + BOOL send_response = False; + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + CHECK_FNUM(fnum,cnum); + CHECK_WRITE(fnum); + + tcount = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + numtowrite = SVAL(inbuf,smb_vwv6); + smb_doff = SVAL(inbuf,smb_vwv7); + + data = smb_base(inbuf) + smb_doff; + + /* We need to send an SMBwriteC response, not an SMBwritebs */ + CVAL(outbuf,smb_com) = SMBwritec; + + /* This fd should have an auxiliary struct attached, + check that it does */ + wbms = Files[fnum].wbmpx_ptr; + if(!wbms) return(-1); + + /* If write through is set we can return errors, else we must + cache them */ + write_through = wbms->wr_mode; + + /* Check for an earlier error */ + if(wbms->wr_discard) + return -1; /* Just discard the packet */ + + seek_file(fnum,startpos); + nwritten = write_file(fnum,data,numtowrite); + + if(lp_syncalways(SNUM(cnum)) || write_through) + sync_file(fnum); + + if (nwritten < numtowrite) + { + if(write_through) { + /* We are returning an error - we can delete the aux struct */ + if (wbms) free((char *)wbms); + Files[fnum].wbmpx_ptr = NULL; + return(ERROR(ERRHRD,ERRdiskfull)); + } + return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); + } + + /* Increment the total written, if this matches tcount + we can discard the auxiliary struct (hurrah !) and return a writeC */ + wbms->wr_total_written += nwritten; + if(wbms->wr_total_written >= tcount) + { + if (write_through) { + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); + send_response = True; + } + + free((char *)wbms); + Files[fnum].wbmpx_ptr = NULL; + } + + if(send_response) + return(outsize); + + return(-1); +} + + +/**************************************************************************** + reply to a SMBsetattrE +****************************************************************************/ +int reply_setattrE(char *inbuf,char *outbuf) +{ + int cnum,fnum; + struct utimbuf unix_times; + int outsize = 0; + + outsize = set_message(outbuf,0,0,True); + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + /* Convert the DOS times into unix times. Ignore create + time as UNIX can't set this. + */ + unix_times.actime = make_unix_date2(inbuf+smb_vwv3); + unix_times.modtime = make_unix_date2(inbuf+smb_vwv5); + + /* Set the date on this file */ + if(sys_utime(Files[fnum].name, &unix_times)) + return(ERROR(ERRDOS,ERRnoaccess)); + + DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum)); + + return(outsize); +} + + +/**************************************************************************** + reply to a SMBgetattrE +****************************************************************************/ +int reply_getattrE(char *inbuf,char *outbuf) +{ + int cnum,fnum; + struct stat sbuf; + int outsize = 0; + int mode; + + outsize = set_message(outbuf,11,0,True); + + cnum = SVAL(inbuf,smb_tid); + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + /* Do an fstat on this file */ + if(fstat(Files[fnum].fd, &sbuf)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + mode = dos_mode(cnum,Files[fnum].name,&sbuf); + + /* Convert the times into dos times. Set create + date to be last modify date as UNIX doesn't save + this */ + put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime); + put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); + put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); + if (mode & aDIR) + { + SIVAL(outbuf,smb_vwv6,0); + SIVAL(outbuf,smb_vwv8,0); + } + else + { + SIVAL(outbuf,smb_vwv6,sbuf.st_size); + SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024)); + } + SSVAL(outbuf,smb_vwv10, mode); + + DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum)); + + return(outsize); +} + + + + + diff --git a/source3/smbd/server.c b/source3/smbd/server.c new file mode 100644 index 0000000000..5d8facef33 --- /dev/null +++ b/source3/smbd/server.c @@ -0,0 +1,4300 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Main SMB server routines + 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" +#include "pcap.h" +#include "trans2.h" +#include "reply.h" + +pstring servicesf = CONFIGFILE; +pstring OriginalDir ="/"; +extern pstring debugf; +extern pstring sesssetup_user; + +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; + +/* a useful macro to debug the last message processed */ +#define LAST_MESSAGE() smb_fn_name(last_message) + +extern pstring scope; +extern int DEBUGLEVEL; +extern int case_default; +extern BOOL case_sensitive; +extern BOOL case_preserve; +extern BOOL use_mangled_map; +extern BOOL short_case_preserve; +extern BOOL case_mangle; +extern time_t smb_last_time; + +extern pstring user_socket_options; + +connection_struct Connections[MAX_CONNECTIONS]; +files_struct Files[MAX_OPEN_FILES]; + +extern int Protocol; + +int maxxmit = BUFFER_SIZE; + +int chain_size = 0; + +/* a fnum to use when chaining */ +int chain_fnum = -1; + +/* number of open connections */ +static int num_connections_open = 0; + +extern fstring remote_machine; + + +/* these can be set by some functions to override the error codes */ +int unix_ERR_class=SUCCESS; +int unix_ERR_code=0; + + +extern int extra_time_offset; + +extern pstring myhostname; +extern struct in_addr myip; + + +static int find_free_connection(int hash); + +#ifdef SMB_PASSWD +extern void generate_next_challenge(char *challenge); +extern void set_challenge(char *challenge); +#endif + +/* for readability... */ +#define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0) +#define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0) +#define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0) +#define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0) +#define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0) + + + +/**************************************************************************** + change a dos mode to a unix mode + base permission for files: + everybody gets read bit set + dos readonly is represented in unix by removing everyone's write bit + dos archive is represented in unix by the user's execute bit + dos system is represented in unix by the group's execute bit + dos hidden is represented in unix by the other's execute bit + base permission for directories: + dos directory is represented in unix by unix's dir bit and the exec bit +****************************************************************************/ +mode_t unix_mode(int cnum,int dosmode) +{ + mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); + + if ( !IS_DOS_READONLY(dosmode) ) + result |= (S_IWUSR | S_IWGRP | S_IWOTH); + + if (IS_DOS_DIR(dosmode)) + result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); + + if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode)) + result |= S_IXUSR; + + if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode)) + result |= S_IXGRP; + + if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode)) + result |= S_IXOTH; + + result &= CREATE_MODE(cnum); + return(result); +} + + +/**************************************************************************** + change a unix mode to a dos mode +****************************************************************************/ +int dos_mode(int cnum,char *path,struct stat *sbuf) +{ + int result = 0; + +#if OLD_DOS_MODE + if (!CAN_WRITE(cnum) || !((sbuf->st_mode & S_IWOTH) || + Connections[cnum].admin_user || + ((sbuf->st_mode & S_IWUSR) && + Connections[cnum].uid==sbuf->st_uid) || + ((sbuf->st_mode & S_IWGRP) && + in_group(sbuf->st_gid,Connections[cnum].gid, + Connections[cnum].ngroups, + Connections[cnum].igroups)))) + result |= aRONLY; +#else + if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) { + if (!((sbuf->st_mode & S_IWOTH) || + Connections[cnum].admin_user || + ((sbuf->st_mode & S_IWUSR) && Connections[cnum].uid==sbuf->st_uid) || + ((sbuf->st_mode & S_IWGRP) && + in_group(sbuf->st_gid,Connections[cnum].gid, + Connections[cnum].ngroups,Connections[cnum].igroups)))) + result |= aRONLY; + } else { + if ((sbuf->st_mode & S_IWUSR) == 0) + result |= aRONLY; + } +#endif + + if ((sbuf->st_mode & S_IXUSR) != 0) + result |= aARCH; + + if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0)) + result |= aSYSTEM; + + if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0)) + result |= aHIDDEN; + + if (S_ISDIR(sbuf->st_mode)) + result = aDIR | (result & aRONLY); + +#if LINKS_READ_ONLY + if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) + result |= aRONLY; +#endif + + /* hide files with a name starting with a . */ + if (lp_hide_dot_files(SNUM(cnum))) + { + char *p = strrchr(path,'/'); + if (p) + p++; + else + p = path; + + if (p[0] == '.' && p[1] != '.' && p[1] != 0) + result |= aHIDDEN; + } + + return(result); +} + + +/******************************************************************* +chmod a file - but preserve some bits +********************************************************************/ +int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) +{ + struct stat st1; + int mask=0; + int tmp; + int unixmode; + + if (!st) { + st = &st1; + if (sys_stat(fname,st)) return(-1); + } + + if (S_ISDIR(st->st_mode)) dosmode |= aDIR; + + if (dos_mode(cnum,fname,st) == dosmode) return(0); + + unixmode = unix_mode(cnum,dosmode); + + /* preserve the s bits */ + mask |= (S_ISUID | S_ISGID); + + /* preserve the t bit */ +#ifdef S_ISVTX + mask |= S_ISVTX; +#endif + + /* possibly preserve the x bits */ + if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR; + if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP; + if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH; + + unixmode |= (st->st_mode & mask); + + /* if we previously had any r bits set then leave them alone */ + if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { + unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH); + unixmode |= tmp; + } + + /* if we previously had any w bits set then leave them alone + if the new mode is not rdonly */ + if (!IS_DOS_READONLY(dosmode) && + (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) { + unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); + unixmode |= tmp; + } + + return(chmod(fname,unixmode)); +} + + +/**************************************************************************** +check if two filenames are equal + +this needs to be careful about whether we are case sensitive +****************************************************************************/ +static BOOL fname_equal(char *name1, char *name2) +{ + int l1 = strlen(name1); + int l2 = strlen(name2); + + /* handle filenames ending in a single dot */ + if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot()) + { + BOOL ret; + name1[l1-1] = 0; + ret = fname_equal(name1,name2); + name1[l1-1] = '.'; + return(ret); + } + + if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot()) + { + BOOL ret; + name2[l2-1] = 0; + ret = fname_equal(name1,name2); + name2[l2-1] = '.'; + return(ret); + } + + /* now normal filename handling */ + if (case_sensitive) + return(strcmp(name1,name2) == 0); + + return(strequal(name1,name2)); +} + + +/**************************************************************************** +mangle the 2nd name and check if it is then equal to the first name +****************************************************************************/ +static BOOL mangled_equal(char *name1, char *name2) +{ + pstring tmpname; + + if (is_8_3(name2)) + return(False); + + strcpy(tmpname,name2); + mangle_name_83(tmpname); + + return(strequal(name1,tmpname)); +} + + +/**************************************************************************** +scan a directory to find a filename, matching without case sensitivity + +If the name looks like a mangled name then try via the mangling functions +****************************************************************************/ +static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) +{ + void *cur_dir; + char *dname; + BOOL mangled; + fstring name2; + + mangled = is_mangled(name); + + /* handle null paths */ + if (*path == 0) + path = "."; + + if (docache && (dname = DirCacheCheck(path,name,snum))) { + strcpy(name, dname); + return(True); + } + + if (mangled) + check_mangled_stack(name); + + /* open the directory */ + if (!(cur_dir = OpenDir(path))) + { + DEBUG(3,("scan dir didn't open dir [%s]\n",path)); + return(False); + } + + /* now scan for matching names */ + while ((dname = ReadDirName(cur_dir))) + { + if (*dname == '.' && + (strequal(dname,".") || strequal(dname,".."))) + continue; + + strcpy(name2,dname); + if (!name_map_mangle(name2,False,snum)) continue; + + if ((mangled && mangled_equal(name,name2)) + || fname_equal(name, name2)) + { + /* we've found the file, change it's name and return */ + if (docache) DirCacheAdd(path,name,dname,snum); + strcpy(name, dname); + CloseDir(cur_dir); + return(True); + } + } + + CloseDir(cur_dir); + return(False); +} + +/**************************************************************************** +This routine is called to convert names from the dos namespace to unix +namespace. It needs to handle any case conversions, mangling, format +changes etc. + +We assume that we have already done a chdir() to the right "root" directory +for this service. + +The function will return False if some part of the name except for the last +part cannot be resolved +****************************************************************************/ +BOOL unix_convert(char *name,int cnum) +{ + struct stat st; + char *start, *end; + pstring dirpath; + + *dirpath = 0; + + /* convert to basic unix format - removing \ chars and cleaning it up */ + unix_format(name); + unix_clean_name(name); + + if (!case_sensitive && + (!case_preserve || (is_8_3(name) && !short_case_preserve))) + strnorm(name); + + /* names must be relative to the root of the service - trim any leading /. + also trim trailing /'s */ + trim_string(name,"/","/"); + + /* check if it's a printer file */ + if (Connections[cnum].printer) + { + if ((! *name) || strchr(name,'/') || !is_8_3(name)) + { + fstring name2; + sprintf(name2,"%.6s.XXXXXX",remote_machine); + strcpy(name,(char *)mktemp(name2)); + } + return(True); + } + + /* stat the name - if it exists then we are all done! */ + if (sys_stat(name,&st) == 0) + return(True); + + DEBUG(5,("unix_convert(%s,%d)\n",name,cnum)); + + /* a special case - if we don't have any mangling chars and are case + sensitive then searching won't help */ + if (case_sensitive && !is_mangled(name) && + !lp_strip_dot() && !use_mangled_map) + return(False); + + /* now we need to recursively match the name against the real + directory structure */ + + start = name; + while (strncmp(start,"./",2) == 0) + start += 2; + + /* now match each part of the path name separately, trying the names + as is first, then trying to scan the directory for matching names */ + for (;start;start = (end?end+1:(char *)NULL)) + { + /* pinpoint the end of this section of the filename */ + end = strchr(start, '/'); + + /* chop the name at this point */ + if (end) *end = 0; + + /* check if the name exists up to this point */ + if (sys_stat(name, &st) == 0) + { + /* it exists. it must either be a directory or this must be + the last part of the path for it to be OK */ + if (end && !(st.st_mode & S_IFDIR)) + { + /* an intermediate part of the name isn't a directory */ + DEBUG(5,("Not a dir %s\n",start)); + *end = '/'; + return(False); + } + } + else + { + pstring rest; + + *rest = 0; + + /* remember the rest of the pathname so it can be restored + later */ + if (end) strcpy(rest,end+1); + + + /* try to find this part of the path in the directory */ + if (strchr(start,'?') || strchr(start,'*') || + !scan_directory(dirpath, start, SNUM(cnum), end?True:False)) + { + if (end) + { + /* an intermediate part of the name can't be found */ + DEBUG(5,("Intermediate not found %s\n",start)); + *end = '/'; + return(False); + } + + /* just the last part of the name doesn't exist */ + /* we may need to strupper() or strlower() it in case + this conversion is being used for file creation + purposes */ + /* if the filename is of mixed case then don't normalise it */ + if (!case_preserve && + (!strhasupper(start) || !strhaslower(start))) + strnorm(start); + + /* check on the mangled stack to see if we can recover the + base of the filename */ + if (is_mangled(start)) + check_mangled_stack(start); + + DEBUG(5,("New file %s\n",start)); + return(True); + } + + /* restore the rest of the string */ + if (end) + { + strcpy(start+strlen(start)+1,rest); + end = start + strlen(start); + } + } + + /* add to the dirpath that we have resolved so far */ + if (*dirpath) strcat(dirpath,"/"); + strcat(dirpath,start); + + /* restore the / that we wiped out earlier */ + if (end) *end = '/'; + } + + /* the name has been resolved */ + DEBUG(5,("conversion finished %s\n",name)); + return(True); +} + + + + +#ifdef QUOTAS +#ifdef LINUX +/**************************************************************************** +try to get the disk space from disk quotas (LINUX version) +****************************************************************************/ +/* +If you didn't make the symlink to the quota package, too bad :( +*/ +#include "quota/quotactl.c" +#include "quota/hasquota.c" +static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t euser_id; + struct dqblk D; + struct stat S; + dev_t devno ; + struct mntent *mnt; + FILE *fp; + int found ; + int qcmd, fd ; + char *qfpathname; + + /* find the block device file */ + + if ( stat(path, &S) == -1 ) + return(False) ; + + devno = S.st_dev ; + + fp = setmntent(MOUNTED,"r"); + found = False ; + + while ((mnt = getmntent(fp)) != (struct mntent *) 0) { + if ( stat(mnt->mnt_dir,&S) == -1 ) + continue ; + if (S.st_dev == devno) { + found = True ; + break ; + } + } + endmntent(fp) ; + + if ( ! found ) + return(False) ; + + qcmd = QCMD(Q_GETQUOTA, USRQUOTA); + + if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA)) + return(False) ; + + if (!hasquota(mnt, USRQUOTA, &qfpathname)) + return(False) ; + + euser_id = geteuid(); + seteuid(0); + + if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) { + if ((fd = open(qfpathname, O_RDONLY)) < 0) { + seteuid(euser_id); + return(False); + } + lseek(fd, (long) dqoff(euser_id), L_SET); + switch (read(fd, &D, sizeof(struct dqblk))) { + case 0:/* EOF */ + memset((caddr_t)&D, 0, sizeof(struct dqblk)); + break; + case sizeof(struct dqblk): /* OK */ + break; + default: /* ERROR */ + close(fd); + seteuid(euser_id); + return(False); + } + } + seteuid(euser_id); + *bsize=1024; + + if (D.dqb_bsoftlimit==0) + return(False); + if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit)) + { + *dfree = 0; + *dsize = D.dqb_curblocks; + } + else { + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + } + return (True); +} +#else +#ifndef CRAY +/**************************************************************************** +try to get the disk space from disk quotas +****************************************************************************/ +static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t user_id, euser_id; + int r; + char dev_disk[256]; + struct dqblk D; + struct stat S; + /* find the block device file */ + if ((stat(path, &S)<0) || + (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); + + euser_id = geteuid(); + +#ifdef USE_SETRES + /* for HPUX, real uid must be same as euid to execute quotactl for euid */ + user_id = getuid(); + setresuid(euser_id,-1,-1); +#endif + r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); + #ifdef USE_SETRES + if (setresuid(user_id,-1,-1)) + DEBUG(5,("Unable to reset uid to %d\n", user_id)); + #endif + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = 1024; + if (r) + { + if (errno == EDQUOT) + { + *dfree =0; + *dsize =D.dqb_curblocks; + return (True); + } + else return(False); + } + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curfiles>D.dqb_fsoftlimit)) + { + *dfree = 0; + *dsize = D.dqb_curblocks; + } + else { + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + } + return (True); +} +#else +/**************************************************************************** +try to get the disk space from disk quotas (CRAY VERSION) +****************************************************************************/ +static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + struct mntent *mnt; + FILE *fd; + struct stat sbuf; + dev_t devno ; + static dev_t devno_cached = 0 ; + static char name[MNTMAXSTR] ; + struct q_request request ; + struct qf_header header ; + static int quota_default = 0 ; + int found ; + + if ( stat(path,&sbuf) == -1 ) + return(False) ; + + devno = sbuf.st_dev ; + + if ( devno != devno_cached ) { + + devno_cached = devno ; + + if ((fd = setmntent(KMTAB)) == NULL) + return(False) ; + + found = False ; + + while ((mnt = getmntent(fd)) != NULL) { + + if ( stat(mnt->mnt_dir,&sbuf) == -1 ) + continue ; + + if (sbuf.st_dev == devno) { + + found = True ; + break ; + + } + + } + + strcpy(name,mnt->mnt_dir) ; + endmntent(fd) ; + + if ( ! found ) + return(False) ; + } + + request.qf_magic = QF_MAGIC ; + request.qf_entry.id = geteuid() ; + + if (quotactl(name, Q_GETQUOTA, &request) == -1) + return(False) ; + + if ( ! request.user ) + return(False) ; + + if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) { + + if ( ! quota_default ) { + + if ( quotactl(name, Q_GETHEADER, &header) == -1 ) + return(False) ; + else + quota_default = header.user_h.def_fq ; + } + + *dfree = quota_default ; + + }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) { + + *dfree = 0 ; + + }else{ + + *dfree = request.qf_entry.user_q.f_quota ; + + } + + *dsize = request.qf_entry.user_q.f_use ; + + if ( *dfree ) + *dfree -= *dsize ; + + if ( *dfree < 0 ) + *dfree = 0 ; + + *bsize = 4096 ; /* Cray blocksize */ + + return(True) ; + +} +#endif /* CRAY */ +#endif /* LINUX */ +#endif /* QUOTAS */ + + +/**************************************************************************** +normalise for DOS usage +****************************************************************************/ +static void disk_norm(int *bsize,int *dfree,int *dsize) +{ + /* check if the disk is beyond the max disk size */ + int maxdisksize = lp_maxdisksize(); + if (maxdisksize) { + /* convert to blocks - and don't overflow */ + maxdisksize = ((maxdisksize*1024)/(*bsize))*1024; + if (*dsize > maxdisksize) *dsize = maxdisksize; + if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop + applications getting + div by 0 errors */ + } + + while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) + { + *dfree /= 2; + *dsize /= 2; + *bsize *= 2; + if (*bsize > WORDMAX ) + { + *bsize = WORDMAX; + if (*dsize > WORDMAX) + *dsize = WORDMAX; + if (*dfree > WORDMAX) + *dfree = WORDMAX; + break; + } + } +} + +/**************************************************************************** + return number of 1K blocks available on a path and total number +****************************************************************************/ +int disk_free(char *path,int *bsize,int *dfree,int *dsize) +{ + char *df_command = lp_dfree_command(); +#ifndef NO_STATFS +#ifdef USE_STATVFS + struct statvfs fs; +#else +#ifdef ULTRIX + struct fs_data fs; +#else + struct statfs fs; +#endif +#endif +#endif + +#ifdef QUOTAS + if (disk_quotas(path, bsize, dfree, dsize)) + { + disk_norm(bsize,dfree,dsize); + return(((*bsize)/1024)*(*dfree)); + } +#endif + + + /* possibly use system() to get the result */ + if (df_command && *df_command) + { + int ret; + pstring syscmd; + pstring outfile; + + sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid()); + sprintf(syscmd,"%s %s",df_command,path); + standard_sub_basic(syscmd); + + ret = smbrun(syscmd,outfile); + DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); + + { + FILE *f = fopen(outfile,"r"); + *dsize = 0; + *dfree = 0; + *bsize = 1024; + if (f) + { + fscanf(f,"%d %d %d",dsize,dfree,bsize); + fclose(f); + } + else + DEBUG(0,("Can't open %s\n",outfile)); + } + + unlink(outfile); + disk_norm(bsize,dfree,dsize); + return(((*bsize)/1024)*(*dfree)); + } + +#ifdef NO_STATFS + DEBUG(1,("Warning - no statfs function\n")); + return(1); +#else +#ifdef STATFS4 + if (statfs(path,&fs,sizeof(fs),0) != 0) +#else +#ifdef USE_STATVFS + if (statvfs(path, &fs)) +#else +#ifdef STATFS3 + if (statfs(path,&fs,sizeof(fs)) == -1) +#else + if (statfs(path,&fs) == -1) +#endif /* STATFS3 */ +#endif /* USE_STATVFS */ +#endif /* STATFS4 */ + { + DEBUG(3,("dfree call failed code errno=%d\n",errno)); + *bsize = 1024; + *dfree = 1; + *dsize = 1; + return(((*bsize)/1024)*(*dfree)); + } + +#ifdef ULTRIX + *bsize = 1024; + *dfree = fs.fd_req.bfree; + *dsize = fs.fd_req.btot; +#else +#ifdef USE_STATVFS + *bsize = fs.f_frsize; +#else +#ifdef USE_F_FSIZE + /* eg: osf1 has f_fsize = fundamental filesystem block size, + f_bsize = optimal transfer block size (MX: 94-04-19) */ + *bsize = fs.f_fsize; +#else + *bsize = fs.f_bsize; +#endif /* STATFS3 */ +#endif /* USE_STATVFS */ + +#ifdef STATFS4 + *dfree = fs.f_bfree; +#else + *dfree = fs.f_bavail; +#endif /* STATFS4 */ + *dsize = fs.f_blocks; +#endif /* ULTRIX */ + +#if defined(SCO) || defined(ISC) || defined(MIPS) + *bsize = 512; +#endif + +/* handle rediculous bsize values - some OSes are broken */ +if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; + + disk_norm(bsize,dfree,dsize); + + if (*bsize < 256) + *bsize = 512; + if ((*dsize)<1) + { + DEBUG(0,("dfree seems to be broken on your system\n")); + *dsize = 20*1024*1024/(*bsize); + *dfree = MAX(1,*dfree); + } + return(((*bsize)/1024)*(*dfree)); +#endif +} + + +/**************************************************************************** +wrap it to get filenames right +****************************************************************************/ +int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize) +{ + return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize)); +} + + + +/**************************************************************************** +check a filename - possibly caling reducename + +This is called by every routine before it allows an operation on a filename. +It does any final confirmation necessary to ensure that the filename is +a valid one for the user to access. +****************************************************************************/ +BOOL check_name(char *name,int cnum) +{ + BOOL ret; + + errno = 0; + + ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum))); + if (!ret) + DEBUG(5,("check_name on %s failed\n",name)); + + return(ret); +} + +/**************************************************************************** +check a filename - possibly caling reducename +****************************************************************************/ +static void check_for_pipe(char *fname) +{ + /* special case of pipe opens */ + char s[10]; + StrnCpy(s,fname,9); + strlower(s); + if (strstr(s,"pipe/")) + { + DEBUG(3,("Rejecting named pipe open for %s\n",fname)); + unix_ERR_class = ERRSRV; + unix_ERR_code = ERRaccess; + } +} + + +/**************************************************************************** +open a file +****************************************************************************/ +void open_file(int fnum,int cnum,char *fname1,int flags,int mode) +{ + pstring fname; + + Files[fnum].open = False; + Files[fnum].fd = -1; + errno = EPERM; + + strcpy(fname,fname1); + + /* check permissions */ + if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer) + { + DEBUG(3,("Permission denied opening %s\n",fname)); + check_for_pipe(fname); + return; + } + + /* this handles a bug in Win95 - it doesn't say to create the file when it + should */ + if (Connections[cnum].printer) + flags |= O_CREAT; + +/* + if (flags == O_WRONLY) + DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); +*/ + +#if UTIME_WORKAROUND + /* XXXX - is this OK?? */ + /* this works around a utime bug but can cause other problems */ + if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND)) + sys_unlink(fname); +#endif + + + Files[fnum].fd = sys_open(fname,flags,mode); + + if ((Files[fnum].fd>=0) && + Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) { + pstring dname; + int dum1,dum2,dum3; + char *p; + strcpy(dname,fname); + p = strrchr(dname,'/'); + if (p) *p = 0; + if (sys_disk_free(dname,&dum1,&dum2,&dum3) < + lp_minprintspace(SNUM(cnum))) { + close(Files[fnum].fd); + Files[fnum].fd = -1; + sys_unlink(fname); + errno = ENOSPC; + return; + } + } + + + /* Fix for files ending in '.' */ + if((Files[fnum].fd == -1) && (errno == ENOENT) && + (strchr(fname,'.')==NULL)) + { + strcat(fname,"."); + Files[fnum].fd = sys_open(fname,flags,mode); + } + +#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) + if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG)) + { + int max_len; + char *p = strrchr(fname, '/'); + + if (p == fname) /* name is "/xxx" */ + { + max_len = pathconf("/", _PC_NAME_MAX); + p++; + } + else if ((p == NULL) || (p == fname)) + { + p = fname; + max_len = pathconf(".", _PC_NAME_MAX); + } + else + { + *p = '\0'; + max_len = pathconf(fname, _PC_NAME_MAX); + *p = '/'; + p++; + } + if (strlen(p) > max_len) + { + char tmp = p[max_len]; + + p[max_len] = '\0'; + if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1) + p[max_len] = tmp; + } + } +#endif + + if (Files[fnum].fd < 0) + { + DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", + fname,strerror(errno),flags)); + check_for_pipe(fname); + return; + } + + if (Files[fnum].fd >= 0) + { + struct stat st; + Connections[cnum].num_files_open++; + fstat(Files[fnum].fd,&st); + Files[fnum].mode = st.st_mode; + Files[fnum].open_time = time(NULL); + Files[fnum].size = 0; + Files[fnum].pos = -1; + Files[fnum].open = True; + Files[fnum].mmap_ptr = NULL; + Files[fnum].mmap_size = 0; + Files[fnum].can_lock = True; + Files[fnum].can_read = ((flags & O_WRONLY)==0); + Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + Files[fnum].share_mode = 0; + Files[fnum].share_pending = False; + Files[fnum].print_file = Connections[cnum].printer; + Files[fnum].modified = False; + Files[fnum].cnum = cnum; + string_set(&Files[fnum].name,fname); + Files[fnum].wbmpx_ptr = NULL; + + /* + * If the printer is marked as postscript output a leading + * file identifier to ensure the file is treated as a raw + * postscript file. + * This has a similar effect as CtrlD=0 in WIN.INI file. + * tim@fsg.com 09/06/94 + */ + if (Files[fnum].print_file && POSTSCRIPT(cnum) && + Files[fnum].can_write) + { + DEBUG(3,("Writing postscript line\n")); + write_file(fnum,"%!\n",3); + } + + DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", + timestring(),Connections[cnum].user,fname, + BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write), + Connections[cnum].num_files_open,fnum)); + + } + +#if USE_MMAP + /* mmap it if read-only */ + if (!Files[fnum].can_write) + { + Files[fnum].mmap_size = file_size(fname); + Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size, + PROT_READ,MAP_SHARED,Files[fnum].fd,0); + + if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr) + { + DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); + Files[fnum].mmap_ptr = NULL; + } + } +#endif +} + +/******************************************************************* +sync a file +********************************************************************/ +void sync_file(int fnum) +{ +#ifndef NO_FSYNC + fsync(Files[fnum].fd); +#endif +} + +/**************************************************************************** +run a file if it is a magic script +****************************************************************************/ +static void check_magic(int fnum,int cnum) +{ + if (!*lp_magicscript(SNUM(cnum))) + return; + + DEBUG(5,("checking magic for %s\n",Files[fnum].name)); + + { + char *p; + if (!(p = strrchr(Files[fnum].name,'/'))) + p = Files[fnum].name; + else + p++; + + if (!strequal(lp_magicscript(SNUM(cnum)),p)) + return; + } + + { + int ret; + pstring magic_output; + pstring fname; + strcpy(fname,Files[fnum].name); + + if (*lp_magicoutput(SNUM(cnum))) + strcpy(magic_output,lp_magicoutput(SNUM(cnum))); + else + sprintf(magic_output,"%s.out",fname); + + chmod(fname,0755); + ret = smbrun(fname,magic_output); + DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); + unlink(fname); + } +} + + +/**************************************************************************** +close a file - possibly invalidating the read prediction +****************************************************************************/ +void close_file(int fnum) +{ + int cnum = Files[fnum].cnum; + invalidate_read_prediction(Files[fnum].fd); + Files[fnum].open = False; + Connections[cnum].num_files_open--; + if(Files[fnum].wbmpx_ptr) + { + free((char *)Files[fnum].wbmpx_ptr); + Files[fnum].wbmpx_ptr = NULL; + } + +#if USE_MMAP + if(Files[fnum].mmap_ptr) + { + munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size); + Files[fnum].mmap_ptr = NULL; + } +#endif + + if (lp_share_modes(SNUM(cnum))) + del_share_mode(fnum); + + if (Files[fnum].modified) { + struct stat st; + if (fstat(Files[fnum].fd,&st) == 0) { + int dosmode = dos_mode(cnum,Files[fnum].name,&st); + if (!IS_DOS_ARCHIVE(dosmode)) { + dos_chmod(cnum,Files[fnum].name,dosmode | aARCH,&st); + } + } + } + + close(Files[fnum].fd); + + /* NT uses smbclose to start a print - weird */ + if (Files[fnum].print_file) + print_file(fnum); + + /* check for magic scripts */ + check_magic(fnum,cnum); + + DEBUG(2,("%s %s closed file %s (numopen=%d)\n", + timestring(),Connections[cnum].user,Files[fnum].name, + Connections[cnum].num_files_open)); +} + +enum {AFAIL,AREAD,AWRITE,AALL}; + +/******************************************************************* +reproduce the share mode access table +********************************************************************/ +static int access_table(int new_deny,int old_deny,int old_mode, + int share_pid,char *fname) +{ + if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); + + if (new_deny == DENY_DOS || old_deny == DENY_DOS) { + if (old_deny == new_deny && share_pid == getpid()) + return(AALL); + + if (old_mode == 0) return(AREAD); + + /* the new smbpub.zip spec says that if the file extension is + .com, .dll, .exe or .sym then allow the open. I will force + it to read-only as this seems sensible although the spec is + a little unclear on this. */ + if ((fname = strrchr(fname,'.'))) { + if (strequal(fname,".com") || + strequal(fname,".dll") || + strequal(fname,".exe") || + strequal(fname,".sym")) + return(AREAD); + } + + return(AFAIL); + } + + switch (new_deny) + { + case DENY_WRITE: + if (old_deny==DENY_WRITE && old_mode==0) return(AREAD); + if (old_deny==DENY_READ && old_mode==0) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==0) return(AALL); + return(AFAIL); + case DENY_READ: + if (old_deny==DENY_WRITE && old_mode==1) return(AREAD); + if (old_deny==DENY_READ && old_mode==1) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==1) return(AALL); + return(AFAIL); + case DENY_NONE: + if (old_deny==DENY_WRITE) return(AREAD); + if (old_deny==DENY_READ) return(AWRITE); + if (old_deny==DENY_NONE) return(AALL); + return(AFAIL); + } + return(AFAIL); +} + +/******************************************************************* +check if the share mode on a file allows it to be deleted or unlinked +return True if sharing doesn't prevent the operation +********************************************************************/ +BOOL check_file_sharing(int cnum,char *fname) +{ + int pid=0; + int share_mode = get_share_mode_byname(cnum,fname,&pid); + + if (!pid || !share_mode) return(True); + + if (share_mode == DENY_DOS) + return(pid == getpid()); + + /* XXXX exactly what share mode combinations should be allowed for + deleting/renaming? */ + return(False); +} + +/**************************************************************************** + C. Hoch 11/22/95 + Helper for open_file_shared. + Truncate a file after checking locking; close file if locked. + **************************************************************************/ +static void truncate_unless_locked(int fnum, int cnum) +{ + if (Files[fnum].can_write){ + if (is_locked(fnum,cnum,0x3FFFFFFF,0)){ + close_file(fnum); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRlock; + } + else + ftruncate(Files[fnum].fd,0); + } +} + + +/**************************************************************************** +open a file with a share mode +****************************************************************************/ +void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, + int mode,int *Access,int *action) +{ + int flags=0; + int flags2=0; + int deny_mode = (share_mode>>4)&7; + struct stat sbuf; + BOOL file_existed = file_exist(fname,&sbuf); + BOOL fcbopen = False; + int share_pid=0; + + Files[fnum].open = False; + Files[fnum].fd = -1; + + /* this is for OS/2 EAs - try and say we don't support them */ + if (strstr(fname,".+,;=[].")) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; + return; + } + + if ((ofun & 0x3) == 0 && file_existed) { + errno = EEXIST; + return; + } + + if (ofun & 0x10) + flags2 |= O_CREAT; + if ((ofun & 0x3) == 2) + flags2 |= O_TRUNC; + + /* note that we ignore the append flag as + append does not mean the same thing under dos and unix */ + + switch (share_mode&0xF) + { + case 1: + flags = O_WRONLY; + break; + case 0xF: + fcbopen = True; + flags = O_RDWR; + break; + case 2: + flags = O_RDWR; + break; + default: + flags = O_RDONLY; + break; + } + + if (flags != O_RDONLY && file_existed && + (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) { + if (!fcbopen) { + errno = EACCES; + return; + } + flags = O_RDONLY; + } + + if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { + DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); + errno = EINVAL; + return; + } + + if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; + + if (lp_share_modes(SNUM(cnum))) { + int old_share=0; + + if (file_existed) + old_share = get_share_mode(cnum,&sbuf,&share_pid); + + if (share_pid) { + /* someone else has a share lock on it, check to see + if we can too */ + int old_open_mode = old_share&0xF; + int old_deny_mode = (old_share>>4)&7; + + if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) { + DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n", + deny_mode,old_deny_mode,old_open_mode,fname)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + + { + int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, + share_pid,fname); + + if ((access_allowed == AFAIL) || + (access_allowed == AREAD && flags == O_WRONLY) || + (access_allowed == AWRITE && flags == O_RDONLY)) { + DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", + deny_mode,old_deny_mode,old_open_mode, + share_pid,fname, + access_allowed)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + + if (access_allowed == AREAD) + flags = O_RDONLY; + + if (access_allowed == AWRITE) + flags = O_WRONLY; + } + } + } + + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", + flags,flags2,mode)); + + open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode); + if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) { + flags = O_RDONLY; + open_file(fnum,cnum,fname,flags,mode); + } + + if (Files[fnum].open) { + int open_mode=0; + switch (flags) { + case O_RDONLY: + open_mode = 0; + break; + case O_RDWR: + open_mode = 2; + break; + case O_WRONLY: + open_mode = 1; + break; + } + + Files[fnum].share_mode = (deny_mode<<4) | open_mode; + Files[fnum].share_pending = True; + + if (Access) { + (*Access) = open_mode; + } + + if (action) { + if (file_existed && !(flags2 & O_TRUNC)) *action = 1; + if (!file_existed) *action = 2; + if (file_existed && (flags2 & O_TRUNC)) *action = 3; + } + + if (!share_pid) + share_mode_pending = True; + + if ((flags2&O_TRUNC) && file_existed) + truncate_unless_locked(fnum,cnum); + } +} + + + +/******************************************************************* +check for files that we should now set our share modes on +********************************************************************/ +static void check_share_modes(void) +{ + int i; + for (i=0;i 0) + { + memcpy(data,Files[fnum].mmap_ptr+pos,num); + data += num; + pos += num; + maxcnt -= num; + mincnt = MAX(mincnt-num,0); + ret += num; + } + } +#endif + + if (maxcnt <= 0) + return(ret); + + if (seek_file(fnum,pos) != pos) + { + DEBUG(3,("Failed to seek to %d\n",pos)); + return(ret); + } + + if (maxcnt > 0) + ret += read_with_timeout(Files[fnum].fd, + data, + mincnt, + maxcnt, + timeout, + exact); + + return(ret); +} + + +/**************************************************************************** +write to a file +****************************************************************************/ +int write_file(int fnum,char *data,int n) +{ + if (!Files[fnum].can_write) { + errno = EPERM; + return(0); + } + + Files[fnum].modified = True; + + return(write_data(Files[fnum].fd,data,n)); +} + + +static int old_umask = 022; + +/**************************************************************************** +load parameters specific to a connection/service +****************************************************************************/ +BOOL become_service(int cnum,BOOL do_chdir) +{ + extern char magic_char; + static int last_cnum = -1; + int snum; + + if (!OPEN_CNUM(cnum)) + { + last_cnum = -1; + return(False); + } + + Connections[cnum].lastused = smb_last_time; + + snum = SNUM(cnum); + + if (do_chdir && + ChDir(Connections[cnum].connectpath) != 0 && + ChDir(Connections[cnum].origpath) != 0) + { + DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(), + Connections[cnum].connectpath,cnum)); + return(False); + } + + if (cnum == last_cnum) + return(True); + + last_cnum = cnum; + + case_default = lp_defaultcase(snum); + case_preserve = lp_preservecase(snum); + short_case_preserve = lp_shortpreservecase(snum); + case_mangle = lp_casemangle(snum); + case_sensitive = lp_casesensitive(snum); + magic_char = lp_magicchar(snum); + use_mangled_map = (*lp_mangled_map(snum) ? True:False); + return(True); +} + + +/**************************************************************************** + 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;iuid) 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 +****************************************************************************/ +int find_service(char *service) +{ + int iService; + + string_sub(service,"\\","/"); + + iService = lp_servicenumber(service); + + /* now handle the special case of a home directory */ + if (iService < 0) + { + char *phome_dir = get_home_dir(service); + DEBUG(3,("checking for home directory %s gave %s\n",service, + phome_dir?phome_dir:"(NULL)")); + if (phome_dir) + { + int iHomeService; + if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) + { + lp_add_home(service,iHomeService,phome_dir); + iService = lp_servicenumber(service); + } + } + } + + /* If we still don't have a service, attempt to add it as a printer. */ + if (iService < 0) + { + int iPrinterService; + + if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) + { + char *pszTemp; + + DEBUG(3,("checking whether %s is a valid printer name...\n", service)); + pszTemp = PRINTCAP; + if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) + { + DEBUG(3,("%s is a valid printer name\n", service)); + DEBUG(3,("adding %s as a printer service\n", service)); + lp_add_printer(service,iPrinterService); + iService = lp_servicenumber(service); + if (iService < 0) + DEBUG(0,("failed to add %s as a printer service!\n", service)); + } + else + DEBUG(3,("%s is not a valid printer name\n", service)); + } + } + + /* just possibly it's a default service? */ + if (iService < 0) + { + char *defservice = lp_defaultservice(); + if (defservice && *defservice && !strequal(defservice,service)) { + iService = find_service(defservice); + if (iService >= 0) { + string_sub(service,"_","/"); + iService = lp_add_service(service,iService); + } + } + } + + if (iService >= 0) + if (!VALID_SNUM(iService)) + { + DEBUG(0,("Invalid snum %d for %s\n",iService,service)); + iService = -1; + } + + if (iService < 0) + DEBUG(3,("find_service() failed to find service %s\n", service)); + + return (iService); +} + + +/**************************************************************************** + create an error packet from a cached error. +****************************************************************************/ +int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line) +{ + write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr; + + int32 eclass = wbmpx->wr_errclass; + int32 err = wbmpx->wr_error; + + /* We can now delete the auxiliary struct */ + free((char *)wbmpx); + Files[fnum].wbmpx_ptr = NULL; + return error_packet(inbuf,outbuf,eclass,err,line); +} + + +struct +{ + int unixerror; + int smbclass; + int smbcode; +} unix_smb_errmap[] = +{ + {EPERM,ERRDOS,ERRnoaccess}, + {EACCES,ERRDOS,ERRnoaccess}, + {ENOENT,ERRDOS,ERRbadfile}, + {EIO,ERRHRD,ERRgeneral}, + {EBADF,ERRSRV,ERRsrverror}, + {EINVAL,ERRSRV,ERRsrverror}, + {EEXIST,ERRDOS,ERRfilexists}, + {ENFILE,ERRDOS,ERRnofids}, + {EMFILE,ERRDOS,ERRnofids}, + {ENOSPC,ERRHRD,ERRdiskfull}, +#ifdef EDQUOT + {EDQUOT,ERRHRD,ERRdiskfull}, +#endif +#ifdef ENOTEMPTY + {ENOTEMPTY,ERRDOS,ERRnoaccess}, +#endif +#ifdef EXDEV + {EXDEV,ERRDOS,ERRdiffdevice}, +#endif + {EROFS,ERRHRD,ERRnowrite}, + {0,0,0} +}; + + +/**************************************************************************** + create an error packet from errno +****************************************************************************/ +int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line) +{ + int eclass=def_class; + int ecode=def_code; + int i=0; + + if (unix_ERR_class != SUCCESS) + { + eclass = unix_ERR_class; + ecode = unix_ERR_code; + unix_ERR_class = SUCCESS; + unix_ERR_code = 0; + } + else + { + while (unix_smb_errmap[i].smbclass != 0) + { + if (unix_smb_errmap[i].unixerror == errno) + { + eclass = unix_smb_errmap[i].smbclass; + ecode = unix_smb_errmap[i].smbcode; + break; + } + i++; + } + } + + return(error_packet(inbuf,outbuf,eclass,ecode,line)); +} + + +/**************************************************************************** + create an error packet. Normally called using the ERROR() macro +****************************************************************************/ +int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line) +{ + int outsize = set_message(outbuf,0,0,True); + int cmd; + cmd = CVAL(inbuf,smb_com); + + CVAL(outbuf,smb_rcls) = error_class; + SSVAL(outbuf,smb_err,error_code); + + DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + timestring(), + line, + (int)CVAL(inbuf,smb_com), + smb_fn_name(CVAL(inbuf,smb_com)), + error_class, + error_code)); + + if (errno != 0) + DEBUG(3,("error string = %s\n",strerror(errno))); + + return(outsize); +} + + +#ifndef SIGCLD_IGNORE +/**************************************************************************** +this prevents zombie child processes +****************************************************************************/ +static int sig_cld() +{ + static int depth = 0; + if (depth != 0) + { + DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n")); + depth=0; + return(0); + } + depth++; + + BlockSignals(True); + DEBUG(5,("got SIGCLD\n")); + +#ifdef USE_WAITPID + while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0); +#endif + + /* Stop zombies */ + /* Stevens, Adv. Unix Prog. says that on system V you must call + wait before reinstalling the signal handler, because the kernel + calls the handler from within the signal-call when there is a + child that has exited. This would lead to an infinite recursion + if done vice versa. */ + +#ifndef DONT_REINSTALL_SIG +#ifdef SIGCLD_IGNORE + signal(SIGCLD, SIG_IGN); +#else + signal(SIGCLD, SIGNAL_CAST sig_cld); +#endif +#endif + +#ifndef USE_WAITPID + while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0); +#endif + depth--; + BlockSignals(False); + return 0; +} +#endif + +/**************************************************************************** + this is called when the client exits abruptly + **************************************************************************/ +static int sig_pipe() +{ + exit_server("Got sigpipe\n"); + return(0); +} + +/**************************************************************************** + open the socket communication +****************************************************************************/ +static BOOL open_sockets(BOOL is_daemon,int port) +{ + extern int Client; + + if (is_daemon) + { + int s; + struct sockaddr addr; + int in_addrlen = sizeof(addr); + + /* Stop zombies */ +#ifdef SIGCLD_IGNORE + signal(SIGCLD, SIG_IGN); +#else + signal(SIGCLD, SIGNAL_CAST sig_cld); +#endif + + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0); + if (s == -1) + return(False); + + /* ready to listen */ + if (listen(s, 5) == -1) + { + DEBUG(0,("listen: %s",strerror(errno))); + close(s); + return False; + } + + /* now accept incoming connections - forking a new process + for each incoming connection */ + DEBUG(2,("waiting for a connection\n")); + while (1) + { + Client = accept(s,&addr,&in_addrlen); + + if (Client == -1 && errno == EINTR) + continue; + + if (Client == -1) + { + DEBUG(0,("accept: %s",strerror(errno))); + return False; + } + +#ifdef NO_FORK_DEBUG +#ifndef NO_SIGNAL_TEST + signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGCLD, SIGNAL_CAST SIG_DFL); +#endif + return True; +#else + if (Client != -1 && fork()==0) + { +#ifndef NO_SIGNAL_TEST + signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGCLD, SIGNAL_CAST SIG_DFL); +#endif + /* close our standard file descriptors */ + close_low_fds(); + + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + + return True; + } + close(Client); /* The parent doesn't need this socket */ +#endif + } + } + else + { + /* We will abort gracefully when the client or remote system + goes away */ +#ifndef NO_SIGNAL_TEST + signal(SIGPIPE, SIGNAL_CAST sig_pipe); +#endif + Client = dup(0); + + /* close our standard file descriptors */ + close_low_fds(); + + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + } + + return True; +} + + +/**************************************************************************** +check if a snum is in use +****************************************************************************/ +BOOL snum_used(int snum) +{ + int i; + for (i=0;i 16000 || uid < 0 || uid > 16000) + DEBUG(0,("This is probably a problem with the account %s\n",user)); + } + } + else + { + int i,ngroups; + int *igroups; + gid_t grp = 0; + ngroups = getgroups(0,&grp); + if (ngroups <= 0) + ngroups = 32; + igroups = (int *)malloc(sizeof(int)*ngroups); + for (i=0;i 0) + { + /* does getgroups return ints or gid_t ?? */ + static BOOL groups_use_ints = True; + + if (groups_use_ints && + ngroups == 1 && + SVAL(igroups,2) == 0x4242) + groups_use_ints = False; + + for (i=0;groups_use_ints && iread_only = lp_readonly(snum); + + { + pstring list; + StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); + string_sub(list,"%S",service); + + if (user_in_list(user,list)) + pcon->read_only = True; + + StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); + string_sub(list,"%S",service); + + if (user_in_list(user,list)) + pcon->read_only = False; + } + + /* admin user check */ + if (user_in_list(user,lp_admin_users(snum)) && + !pcon->read_only) + { + pcon->admin_user = True; + DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); + } + else + pcon->admin_user = False; + + pcon->force_user = force; + pcon->uid = pass->pw_uid; + pcon->gid = pass->pw_gid; + pcon->num_files_open = 0; + pcon->lastused = time(NULL); + pcon->service = snum; + pcon->used = True; + pcon->printer = (strncmp(dev,"LPT",3) == 0); + pcon->ipc = (strncmp(dev,"IPC",3) == 0); + pcon->dirptr = NULL; + string_set(&pcon->dirpath,""); + string_set(&pcon->user,user); + +#if HAVE_GETGRNAM + if (*lp_force_group(snum)) + { + struct group *gptr = (struct group *)getgrnam(lp_force_group(snum)); + if (gptr) + { + pcon->gid = gptr->gr_gid; + DEBUG(3,("Forced group %s\n",lp_force_group(snum))); + } + else + DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum))); + } +#endif + + if (*lp_force_user(snum)) + { + struct passwd *pass2; + fstring fuser; + strcpy(fuser,lp_force_user(snum)); + pass2 = (struct passwd *)Get_Pwnam(fuser,True); + if (pass2) + { + pcon->uid = pass2->pw_uid; + string_set(&pcon->user,fuser); + strcpy(user,fuser); + pcon->force_user = True; + DEBUG(3,("Forced user %s\n",fuser)); + } + else + DEBUG(1,("Couldn't find user %s\n",fuser)); + } + + { + pstring s; + strcpy(s,lp_pathname(snum)); + standard_sub(cnum,s); + string_set(&pcon->connectpath,s); + DEBUG(3,("Connect path is %s\n",s)); + } + + /* groups stuff added by ih */ + pcon->ngroups = 0; + pcon->groups = NULL; + + if (!IS_IPC(cnum)) + { + /* Find all the groups this uid is in and store them. Used by become_user() */ + setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); + + /* check number of connections */ + if (!claim_connection(cnum, + lp_servicename(SNUM(cnum)), + lp_max_connections(SNUM(cnum)),False)) + { + DEBUG(1,("too many connections - rejected\n")); + return(-8); + } + + if (lp_status(SNUM(cnum))) + claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection); + + first_connection = False; + } /* IS_IPC */ + + pcon->open = True; + + /* execute any "root preexec = " line */ + if (*lp_rootpreexec(SNUM(cnum))) + { + pstring cmd; + strcpy(cmd,lp_rootpreexec(SNUM(cnum))); + standard_sub(cnum,cmd); + DEBUG(5,("cmd=%s\n",cmd)); + smbrun(cmd,NULL); + } + + if (!become_user(cnum,pcon->uid)) + { + DEBUG(0,("Can't become connected user!\n")); + pcon->open = False; + if (!IS_IPC(cnum)) { + yield_connection(cnum, + lp_servicename(SNUM(cnum)), + lp_max_connections(SNUM(cnum))); + if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); + } + return(-1); + } + + if (ChDir(pcon->connectpath) != 0) + { + DEBUG(0,("Can't change directory to %s\n",pcon->connectpath)); + pcon->open = False; + unbecome_user(); + if (!IS_IPC(cnum)) { + yield_connection(cnum, + lp_servicename(SNUM(cnum)), + lp_max_connections(SNUM(cnum))); + if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); + } + return(-5); + } + + string_set(&pcon->origpath,pcon->connectpath); + +#if SOFTLINK_OPTIMISATION + /* resolve any soft links early */ + { + pstring s; + strcpy(s,pcon->connectpath); + GetWd(s); + string_set(&pcon->connectpath,s); + ChDir(pcon->connectpath); + } +#endif + + num_connections_open++; + add_session_user(user); + + /* execute any "preexec = " line */ + if (*lp_preexec(SNUM(cnum))) + { + pstring cmd; + strcpy(cmd,lp_preexec(SNUM(cnum))); + standard_sub(cnum,cmd); + smbrun(cmd,NULL); + } + + /* we've finished with the sensitive stuff */ + unbecome_user(); + + { + extern struct from_host Client_info; + DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n", + timestring(), + Client_info.name,Client_info.addr, + lp_servicename(SNUM(cnum)),user, + pcon->uid, + pcon->gid, + (int)getpid())); + } + + return(cnum); +} + + +/**************************************************************************** + find first available file slot +****************************************************************************/ +int find_free_file(void ) +{ + int i; + for (i=1;i=SEC_USER) secword |= 1; + if (doencrypt) secword |= 2; + + set_message(outbuf,13,doencrypt?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); +#ifdef SMB_PASSWD + /* Create a token value and add it to the outgoing packet. */ + if (doencrypt) + generate_next_challenge(smb_buf(outbuf)); +#endif + + Protocol = PROTOCOL_LANMAN1; + + if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { + DEBUG(3,("using password server validation\n")); +#ifdef SMB_PASSWD + if (doencrypt) set_challenge(smb_buf(outbuf)); +#endif + } + + CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + SSVAL(outbuf,smb_vwv2,maxxmit); + SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ + SSVAL(outbuf,smb_vwv4,1); + SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support + readbraw writebraw (possibly) */ + SIVAL(outbuf,smb_vwv6,getpid()); + SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); + + put_dos_date(outbuf,smb_vwv8,t); + + return (smb_len(outbuf)+4); +} + + +/**************************************************************************** +reply for the lanman 2.0 protocol +****************************************************************************/ +int reply_lanman2(char *outbuf) +{ + int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); + int secword=0; + BOOL doencrypt = SMBENCRYPT(); + time_t t = time(NULL); + + if (lp_security()>=SEC_USER) secword |= 1; + if (doencrypt) secword |= 2; + + set_message(outbuf,13,doencrypt?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); +#ifdef SMB_PASSWD + /* Create a token value and add it to the outgoing packet. */ + if (doencrypt) + generate_next_challenge(smb_buf(outbuf)); +#endif + + SIVAL(outbuf,smb_vwv6,getpid()); + + Protocol = PROTOCOL_LANMAN2; + + if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { + DEBUG(3,("using password server validation\n")); +#ifdef SMB_PASSWD + if (doencrypt) set_challenge(smb_buf(outbuf)); +#endif + } + + CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + SSVAL(outbuf,smb_vwv2,maxxmit); + SSVAL(outbuf,smb_vwv3,lp_maxmux()); + SSVAL(outbuf,smb_vwv4,1); + SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ + SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); + put_dos_date(outbuf,smb_vwv8,t); + + return (smb_len(outbuf)+4); +} + +/**************************************************************************** +reply for the nt protocol +****************************************************************************/ +int reply_nt1(char *outbuf) +{ + int capabilities=0x300; /* has dual names + lock_and_read */ + int secword=0; + BOOL doencrypt = SMBENCRYPT(); + + if (lp_security()>=SEC_USER) secword |= 1; + if (doencrypt) secword |= 2; + + set_message(outbuf,17,doencrypt?8:0,True); + CVAL(outbuf,smb_vwv1) = secword; +#ifdef SMB_PASSWD + /* Create a token value and add it to the outgoing packet. */ + if (doencrypt) { + generate_next_challenge(smb_buf(outbuf)); + /* Tell the nt machine how long the challenge is. */ + SSVALS(outbuf,smb_vwv16+1,8); + } +#endif + + SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ + + Protocol = PROTOCOL_NT1; + + if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { + DEBUG(3,("using password server validation\n")); +#ifdef SMB_PASSWD + if (doencrypt) set_challenge(smb_buf(outbuf)); +#endif + } + + if (lp_readraw() && lp_writeraw()) + capabilities |= 1; + + SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ + SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ + SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */ + SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */ + SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ + put_long_date(outbuf+smb_vwv11+1,time(NULL)); + SSVALS(outbuf,smb_vwv15+1,TimeDiff(time(NULL))/60); + + return (smb_len(outbuf)+4); +} + + +/* these are the protocol lists used for auto architecture detection: + +WinNT 3.51: +protocol [PC NETWORK PROGRAM 1.0] +protocol [XENIX CORE] +protocol [MICROSOFT NETWORKS 1.03] +protocol [LANMAN1.0] +protocol [Windows for Workgroups 3.1a] +protocol [LM1.2X002] +protocol [LANMAN2.1] +protocol [NT LM 0.12] + +Win95: +protocol [PC NETWORK PROGRAM 1.0] +protocol [XENIX CORE] +protocol [MICROSOFT NETWORKS 1.03] +protocol [LANMAN1.0] +protocol [Windows for Workgroups 3.1a] +protocol [LM1.2X002] +protocol [LANMAN2.1] +protocol [NT LM 0.12] + +OS/2: +protocol [PC NETWORK PROGRAM 1.0] +protocol [XENIX CORE] +protocol [LANMAN1.0] +protocol [LM1.2X002] +protocol [LANMAN2.1] +*/ + +/* + * Modified to recognize the architecture of the remote machine better. + * + * This appears to be the matrix of which protocol is used by which + * MS product. + Protocol WfWg Win95 WinNT OS/2 + PC NETWORK PROGRAM 1.0 1 1 1 1 + XENIX CORE 2 2 + MICROSOFT NETWORKS 3.0 2 2 + DOS LM1.2X002 3 3 + MICROSOFT NETWORKS 1.03 3 + DOS LANMAN2.1 4 4 + LANMAN1.0 4 3 + Windows for Workgroups 3.1a 5 5 5 + LM1.2X002 6 4 + LANMAN2.1 7 5 + NT LM 0.12 6 8 + * + * tim@fsg.com 09/29/95 + */ + +#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */ +#define ARCH_WIN95 0x2 +#define ARCH_OS2 0xC /* Again OS/2 is like NT */ +#define ARCH_WINNT 0x8 +#define ARCH_SAMBA 0x10 + +#define ARCH_ALL 0x1F + +/* List of supported protocols, most desired first */ +struct { + char *proto_name; + char *short_name; + int (*proto_reply_fn)(char *); + int protocol_level; +} supported_protocols[] = { + {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, + {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, + {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, + {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, + {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS}, + {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE}, + {NULL,NULL}, +}; + + +/**************************************************************************** + reply to a negprot +****************************************************************************/ +static int reply_negprot(char *inbuf,char *outbuf) +{ + extern fstring remote_arch; + int outsize = set_message(outbuf,1,0,True); + int Index=0; + int choice= -1; + int protocol; + char *p; + int bcc = SVAL(smb_buf(inbuf),-2); + int arch = ARCH_ALL; + + p = smb_buf(inbuf)+1; + while (p < (smb_buf(inbuf) + bcc)) + { + Index++; + DEBUG(3,("Requested protocol [%s]\n",p)); + if (strcsequal(p,"Windows for Workgroups 3.1a")) + arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT ); + else if (strcsequal(p,"DOS LM1.2X002")) + arch &= ( ARCH_WFWG | ARCH_WIN95 ); + else if (strcsequal(p,"DOS LANMAN2.1")) + arch &= ( ARCH_WFWG | ARCH_WIN95 ); + else if (strcsequal(p,"NT LM 0.12")) + arch &= ( ARCH_WIN95 | ARCH_WINNT ); + else if (strcsequal(p,"LANMAN2.1")) + arch &= ( ARCH_WINNT | ARCH_OS2 ); + else if (strcsequal(p,"LM1.2X002")) + arch &= ( ARCH_WINNT | ARCH_OS2 ); + else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) + arch &= ARCH_WINNT; + else if (strcsequal(p,"XENIX CORE")) + arch &= ( ARCH_WINNT | ARCH_OS2 ); + else if (strcsequal(p,"Samba")) { + arch = ARCH_SAMBA; + break; + } + + p += strlen(p) + 2; + } + + switch ( arch ) { + case ARCH_SAMBA: + strcpy(remote_arch,"Samba"); + break; + case ARCH_WFWG: + strcpy(remote_arch,"WfWg"); + break; + case ARCH_WIN95: + strcpy(remote_arch,"Win95"); + break; + case ARCH_WINNT: + strcpy(remote_arch,"WinNT"); + break; + case ARCH_OS2: + strcpy(remote_arch,"OS2"); + break; + default: + strcpy(remote_arch,"UNKNOWN"); + break; + } + + /* possibly reload - change of architecture */ + reload_services(True); + + /* a special case to stop password server loops */ + if (Index == 1 && strequal(remote_machine,myhostname) && + lp_security()==SEC_SERVER) + exit_server("Password server loop!"); + + /* Check for protocols, most desirable first */ + for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) + { + p = smb_buf(inbuf)+1; + Index = 0; + if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level) + while (p < (smb_buf(inbuf) + bcc)) + { + if (strequal(p,supported_protocols[protocol].proto_name)) + choice = Index; + Index++; + p += strlen(p) + 2; + } + if(choice != -1) + break; + } + + SSVAL(outbuf,smb_vwv0,choice); + if(choice != -1) { + extern fstring remote_proto; + strcpy(remote_proto,supported_protocols[protocol].short_name); + reload_services(True); + outsize = supported_protocols[protocol].proto_reply_fn(outbuf); + DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); + } + else { + DEBUG(0,("No protocol supported !\n")); + } + SSVAL(outbuf,smb_vwv0,choice); + + DEBUG(5,("%s negprot index=%d\n",timestring(),choice)); + + return(outsize); +} + + +/**************************************************************************** + parse a connect packet +****************************************************************************/ +void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev) +{ + char *p = smb_buf(buf) + 1; + char *p2; + + DEBUG(4,("parsing connect string %s\n",p)); + + p2 = strrchr(p,'\\'); + if (p2 == NULL) + strcpy(service,p); + else + strcpy(service,p2+1); + + p += strlen(p) + 2; + + strcpy(password,p); + *pwlen = strlen(password); + + p += strlen(p) + 2; + + strcpy(dev,p); + + *user = 0; + p = strchr(service,'%'); + if (p != NULL) + { + *p = 0; + strcpy(user,p+1); + } +} + + +/**************************************************************************** +close all open files for a connection +****************************************************************************/ +static void close_open_files(int cnum) +{ + int i; + for (i=0;i=total_recs || + fseek(f,i*sizeof(crec),SEEK_SET) != 0 || + fread(&crec,sizeof(crec),1,f) != 1) + { + if (foundi < 0) foundi = i; + break; + } + + if (Clear && crec.pid && !process_exists(crec.pid)) + { + fseek(f,i*sizeof(crec),SEEK_SET); + bzero((void *)&crec,sizeof(crec)); + fwrite(&crec,sizeof(crec),1,f); + if (foundi < 0) foundi = i; + continue; + } + if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) + { + foundi=i; + if (!Clear) break; + } + } + + if (foundi < 0) + { + DEBUG(3,("no free locks in %s\n",fname)); + fclose(f); + return(False); + } + + /* fill in the crec */ + bzero((void *)&crec,sizeof(crec)); + crec.magic = 0x280267; + crec.pid = getpid(); + crec.cnum = cnum; + crec.uid = Connections[cnum].uid; + crec.gid = Connections[cnum].gid; + StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1); + crec.start = time(NULL); + + { + extern struct from_host Client_info; + StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1); + StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1); + } + + /* make our mark */ + if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 || + fwrite(&crec,sizeof(crec),1,f) != 1) + { + fclose(f); + return(False); + } + + fclose(f); + return(True); +} + +#if DUMP_CORE +/******************************************************************* +prepare to dump a core file - carefully! +********************************************************************/ +static BOOL dump_core(void) +{ + char *p; + pstring dname; + strcpy(dname,debugf); + if ((p=strrchr(dname,'/'))) *p=0; + strcat(dname,"/corefiles"); + mkdir(dname,0700); + sys_chown(dname,getuid(),getgid()); + chmod(dname,0700); + if (chdir(dname)) return(False); + umask(~(0700)); + +#ifndef NO_GETRLIMIT +#ifdef RLIMIT_CORE + { + struct rlimit rlp; + getrlimit(RLIMIT_CORE, &rlp); + rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur); + setrlimit(RLIMIT_CORE, &rlp); + getrlimit(RLIMIT_CORE, &rlp); + DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max)); + } +#endif +#endif + + + DEBUG(0,("Dumping core in %s\n",dname)); + return(True); +} +#endif + +/**************************************************************************** +exit the server +****************************************************************************/ +void exit_server(char *reason) +{ + static int firsttime=1; + int i; + + if (!firsttime) exit(0); + firsttime = 0; + + unbecome_user(); + DEBUG(2,("Closing connections\n")); + for (i=0;i 4) + smb_setlen(outbuf,outsize - 4); + return(outsize); +} + + +/**************************************************************************** + process commands from the client +****************************************************************************/ +void process(void ) +{ + static int trans_num = 0; + int nread; + extern struct from_host Client_info; + extern int Client; + + fromhost(Client,&Client_info); + + InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if ((InBuffer == NULL) || (OutBuffer == NULL)) + return; + + InBuffer += SMB_ALIGNMENT; + OutBuffer += SMB_ALIGNMENT; + +#if PRIME_NMBD + DEBUG(3,("priming nmbd\n")); + { + struct in_addr ip; + ip = *interpret_addr2("localhost"); + if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1"); + *OutBuffer = 0; + send_one_packet(OutBuffer,1,ip,137,SOCK_DGRAM); + } +#endif + + last_user.cnum = -1; + + while (True) + { + int32 len; + int msg_type; + int msg_flags; + int type; + int deadtime = lp_deadtime()*60; + int counter; + int last_keepalive=0; + + if (deadtime <= 0) + deadtime = DEFAULT_SMBD_TIMEOUT; + + if (lp_readprediction()) + do_read_prediction(); + + { + extern pstring share_del_pending; + if (*share_del_pending) { + unbecome_user(); + if (!unlink(share_del_pending)) + DEBUG(3,("Share file deleted %s\n",share_del_pending)); + else + DEBUG(2,("Share del failed of %s\n",share_del_pending)); + share_del_pending[0] = 0; + } + } + + if (share_mode_pending) { + unbecome_user(); + check_share_modes(); + share_mode_pending=False; + } + + errno = 0; + + for (counter=SMBD_SELECT_LOOP; + !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); + counter += SMBD_SELECT_LOOP) + { + int i; + time_t t; + BOOL allidle = True; + extern int keepalive; + + /* check for socket failure */ + if (errno == EBADF) { + DEBUG(3,("%s Bad file descriptor - exiting\n",timestring())); + return; + } + + t = time(NULL); + + /* become root again if waiting */ + unbecome_user(); + + /* check for smb.conf reload */ + if (!(counter%SMBD_RELOAD_CHECK)) + reload_services(True); + + /* check the share modes every 10 secs */ + if (!(counter%SHARE_MODES_CHECK)) + check_share_modes(); + + /* clean the share modes every 5 minutes */ + if (!(counter%SHARE_MODES_CLEAN)) + clean_share_files(); + + /* automatic timeout if all connections are closed */ + if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) { + DEBUG(2,("%s Closing idle connection\n",timestring())); + return; + } + + if (keepalive && (counter-last_keepalive)>keepalive) { + if (!send_keepalive(Client)) { + DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); + return; + } + last_keepalive = counter; + } + + /* check for connection timeouts */ + for (i=0;iDPTR_IDLE_TIMEOUT) + dptr_idlecnum(i); + + if (Connections[i].num_files_open > 0 || + (t-Connections[i].lastused)0) { + DEBUG(2,("%s Closing idle connection 2\n",timestring())); + return; + } + } + + msg_type = CVAL(InBuffer,0); + msg_flags = CVAL(InBuffer,1); + type = CVAL(InBuffer,smb_com); + + len = smb_len(InBuffer); + + DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); + + nread = len + 4; + + DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + +#ifdef WITH_VTP + if(trans_num == 1 && VT_Check(InBuffer)) { + VT_Process(); + return; + } +#endif + + + if (msg_type == 0) + show_msg(InBuffer); + + nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit); + + if(nread > 0) { + if (CVAL(OutBuffer,0) == 0) + show_msg(OutBuffer); + + if (nread != smb_len(OutBuffer) + 4) + { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, + smb_len(OutBuffer))); + } + else + send_smb(Client,OutBuffer); + } + trans_num++; + } +} + + +/**************************************************************************** + initialise connect, service and file structs +****************************************************************************/ +static void init_structs(void ) +{ + int i; + get_myname(myhostname,&myip); + + for (i=0;i 1 && (*argv[1] != '-')) + { + argv++; + argc--; + } + + while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF) + switch (opt) + { + case 'O': + strcpy(user_socket_options,optarg); + break; + case 'i': + strcpy(scope,optarg); + break; + case 'P': + { + extern BOOL passive; + passive = True; + } + break; + case 's': + strcpy(servicesf,optarg); + break; + case 'l': + strcpy(debugf,optarg); + break; + case 'a': + { + extern BOOL append_log; + append_log = !append_log; + } + break; + case 'D': + is_daemon = True; + break; + case 'd': + if (*optarg == 'A') + DEBUGLEVEL = 10000; + else + DEBUGLEVEL = atoi(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + break; + default: + usage(argv[0]); + exit(1); + } + + reopen_logs(); + + 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 + { + struct rlimit rlp; + getrlimit(RLIMIT_NOFILE, &rlp); + rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES; + setrlimit(RLIMIT_NOFILE, &rlp); + getrlimit(RLIMIT_NOFILE, &rlp); + DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur)); + } +#endif +#endif + + + DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", + getuid(),getgid(),geteuid(),getegid())); + + if (sizeof(uint16) < 2 || sizeof(uint32) < 4) + { + DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); + exit(1); + } + + init_structs(); + + if (!reload_services(False)) + return(-1); + +#ifndef NO_SIGNAL_TEST + signal(SIGHUP,SIGNAL_CAST sig_hup); +#endif + + DEBUG(3,("%s loaded services\n",timestring())); + + if (!is_daemon && !is_a_socket(0)) + { + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + is_daemon = True; + } + + if (is_daemon) + { + DEBUG(3,("%s becoming a daemon\n",timestring())); + become_daemon(); + } + + if (open_sockets(is_daemon,port)) + { + /* possibly reload the services file. */ + reload_services(True); + + maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE); + + if (*lp_rootdir()) + { + if (sys_chroot(lp_rootdir()) == 0) + DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); + } + + process(); + close_sockets(); + } + exit_server("normal exit"); + return(0); +} + + diff --git a/source3/smbd/smbrun.c b/source3/smbd/smbrun.c new file mode 100644 index 0000000000..df12ae1f85 --- /dev/null +++ b/source3/smbd/smbrun.c @@ -0,0 +1,96 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + external program running routine + 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" + + +/******************************************************************* +close the low 3 fd's and open dev/null in their place +********************************************************************/ +static void close_fds(void) +{ + int fd; + int i; + close(0); close(1); close(2); + /* 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); + if (fd != i) return; + } +} + + +/* +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 +*/ +int main(int argc,char *argv[]) +{ + close_fds(); + + if (getuid() != geteuid()) + { + int uid,gid; + + if (getuid() == 0) + uid = geteuid(); + else + uid = getuid(); + + if (getgid() == 0) + gid = getegid(); + else + gid = getgid(); + +#ifdef USE_SETRES + setresgid(0,0,0); + setresuid(0,0,0); + setresgid(gid,gid,gid); + setresuid(uid,uid,uid); +#else + setuid(0); + seteuid(0); + setgid(gid); + setegid(gid); + setuid(uid); + seteuid(uid); +#endif + + if (getuid() != uid) + return(3); + } + + if (geteuid() != getuid()) + return(1); + + if (argc < 2) + return(2); + + /* this is to make sure that the system() call doesn't run forever */ + alarm(30); + + return(system(argv[1])); +} diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c new file mode 100644 index 0000000000..9d02123cf8 --- /dev/null +++ b/source3/smbd/trans2.c @@ -0,0 +1,1646 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB transaction2 handling + Copyright (C) Jeremy Allison 1994 + + Extensively modified by Andrew Tridgell, 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" +#include "trans2.h" + +extern int DEBUGLEVEL; +extern int Protocol; +extern connection_struct Connections[]; +extern files_struct Files[]; +extern BOOL case_sensitive; +extern int Client; + +/**************************************************************************** + Send the required number of replies back. + We assume all fields other than the data fields are + set correctly for the type of call. + HACK ! Always assumes smb_setup field is zero. +****************************************************************************/ +static int send_trans2_replies(char *outbuf, int bufsize, char *params, + int paramsize, char *pdata, int datasize) +{ + /* As we are using a protocol > LANMAN1 then the maxxmit + variable must have been set in the sessetupX call. + This takes precedence over the max_xmit field in the + global struct. These different max_xmit variables should + be merged as this is now too confusing */ + + extern int maxxmit; + int data_to_send = datasize; + int params_to_send = paramsize; + int useable_space; + char *pp = params; + char *pd = pdata; + int params_sent_thistime, data_sent_thistime, total_sent_thistime; + int alignment_offset = 1; + + /* Initially set the wcnt area to be 10 - this is true for all + trans2 replies */ + set_message(outbuf,10,0,True); + + /* If there genuinely are no parameters or data to send just send + the empty packet */ + if(params_to_send == 0 && data_to_send == 0) + { + send_smb(Client,outbuf); + return 0; + } + + /* Space is bufsize minus Netbios over TCP header minus SMB header */ + /* The + 1 is to align the param and data bytes on an even byte + boundary. NT 4.0 Beta needs this to work correctly. */ + useable_space = bufsize - ((smb_buf(outbuf)+alignment_offset) - outbuf); + useable_space = MIN(useable_space, maxxmit); /* XXX is this needed? correct? */ + + while( params_to_send || data_to_send) + { + /* Calculate whether we will totally or partially fill this packet */ + total_sent_thistime = params_to_send + data_to_send + alignment_offset; + total_sent_thistime = MIN(total_sent_thistime, useable_space); + + set_message(outbuf, 10, total_sent_thistime, True); + + /* Set total params and data to be sent */ + SSVAL(outbuf,smb_tprcnt,paramsize); + SSVAL(outbuf,smb_tdrcnt,datasize); + + /* Calculate how many parameters and data we can fit into + this packet. Parameters get precedence */ + + params_sent_thistime = MIN(params_to_send,useable_space); + data_sent_thistime = useable_space - params_sent_thistime; + data_sent_thistime = MIN(data_sent_thistime,data_to_send); + + SSVAL(outbuf,smb_prcnt, params_sent_thistime); + if(params_sent_thistime == 0) + { + SSVAL(outbuf,smb_proff,0); + SSVAL(outbuf,smb_prdisp,0); + } else { + /* smb_proff is the offset from the start of the SMB header to the + parameter bytes, however the first 4 bytes of outbuf are + the Netbios over TCP header. Thus use smb_base() to subtract + them from the calculation */ + SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + /* Absolute displacement of param bytes sent in this packet */ + SSVAL(outbuf,smb_prdisp,pp - params); + } + + SSVAL(outbuf,smb_drcnt, data_sent_thistime); + if(data_sent_thistime == 0) + { + SSVAL(outbuf,smb_droff,0); + SSVAL(outbuf,smb_drdisp, 0); + } else { + /* The offset of the data bytes is the offset of the + parameter bytes plus the number of parameters being sent this time */ + SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - + smb_base(outbuf)) + params_sent_thistime); + SSVAL(outbuf,smb_drdisp, pd - pdata); + } + + /* Copy the param bytes into the packet */ + if(params_sent_thistime) + memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + /* Copy in the data bytes */ + if(data_sent_thistime) + memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime,pd,data_sent_thistime); + + DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", + params_sent_thistime, data_sent_thistime, useable_space)); + DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", + params_to_send, data_to_send, paramsize, datasize)); + + /* Send the packet */ + send_smb(Client,outbuf); + + pp += params_sent_thistime; + pd += data_sent_thistime; + + params_to_send -= params_sent_thistime; + data_to_send -= data_sent_thistime; + + /* Sanity check */ + if(params_to_send < 0 || data_to_send < 0) + { + DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!", + params_to_send, data_to_send)); + return -1; + } + } + + return 0; +} + + +/**************************************************************************** + reply to a TRANSACT2_OPEN +****************************************************************************/ +static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, + char **pparams, char **ppdata) +{ + char *params = *pparams; + int16 open_mode = SVAL(params, 2); + int16 open_attr = SVAL(params,6); +#if 0 + BOOL return_additional_info = BITSETW(params,0); + int16 open_sattr = SVAL(params, 4); + time_t open_time = make_unix_date3(params+8); +#endif + int16 open_ofun = SVAL(params,12); + int32 open_size = IVAL(params,14); + char *pname = ¶ms[28]; + int16 namelen = strlen(pname)+1; + + pstring fname; + int fnum = -1; + int unixmode; + int size=0,fmode=0,mtime=0,rmode; + int32 inode = 0; + struct stat sbuf; + int smb_action = 0; + + StrnCpy(fname,pname,namelen); + + DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n", + fname,cnum,open_mode, open_attr, open_ofun, open_size)); + + /* XXXX we need to handle passed times, sattr and flags */ + + unix_convert(fname,cnum); + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + + if (!check_name(fname,cnum)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + unixmode = unix_mode(cnum,open_attr | aARCH); + + + open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, + &rmode,&smb_action); + + if (!Files[fnum].open) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if (fstat(Files[fnum].fd,&sbuf) != 0) { + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + mtime = sbuf.st_mtime; + inode = sbuf.st_ino; + if (fmode & aDIR) { + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* Realloc the size of parameters and data we will return */ + params = *pparams = Realloc(*pparams, 28); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + bzero(params,28); + SSVAL(params,0,fnum); + SSVAL(params,2,fmode); + put_dos_date2(params,4, mtime); + SIVAL(params,8, size); + SSVAL(params,12,rmode); + + SSVAL(params,18,smb_action); + SIVAL(params,20,inode); + + /* Send the required number of replies */ + send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0); + + return -1; +} + +/**************************************************************************** + get a level dependent lanman2 dir entry. +****************************************************************************/ +static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level, + int requires_resume_key, + BOOL dont_descend,char **ppdata, + char *base_data, int space_remaining, + BOOL *out_of_space, + int *last_name_off) +{ + char *dname; + BOOL found = False; + struct stat sbuf; + pstring mask; + pstring pathreal; + pstring fname; + BOOL matched; + char *p, *pdata = *ppdata; + int reskey=0, prev_dirpos=0; + int mode=0; + uint32 size=0,len; + uint32 mdate=0, adate=0, cdate=0; + char *name_ptr; + BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") || + strequal(Connections[cnum].dirpath,".") || + strequal(Connections[cnum].dirpath,"/")); + BOOL was_8_3; + + *fname = 0; + *out_of_space = False; + + if (!Connections[cnum].dirptr) + return(False); + + p = strrchr(path_mask,'/'); + if(p != NULL) + { + if(p[1] == '\0') + strcpy(mask,"*.*"); + else + strcpy(mask, p+1); + } + else + strcpy(mask, path_mask); + + while (!found) + { + /* Needed if we run out of space */ + prev_dirpos = TellDir(Connections[cnum].dirptr); + dname = ReadDirName(Connections[cnum].dirptr); + + reskey = TellDir(Connections[cnum].dirptr); + + DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", + Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); + + if (!dname) + return(False); + + matched = False; + + strcpy(fname,dname); + + if(mask_match(fname, mask, case_sensitive, True)) + { + BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); + if (dont_descend && !isdots) + continue; + + if (isrootdir && isdots) + continue; + + strcpy(pathreal,Connections[cnum].dirpath); + strcat(pathreal,"/"); + strcat(pathreal,fname); + if (sys_stat(pathreal,&sbuf) != 0) + { + DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); + continue; + } + + mode = dos_mode(cnum,pathreal,&sbuf); + + if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) + { + DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); + continue; + } + size = sbuf.st_size; + mdate = sbuf.st_mtime; + adate = sbuf.st_atime; + cdate = sbuf.st_ctime; + if(mode & aDIR) + size = 0; + + DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); + + found = True; + } + } + + +#ifndef KANJI + unix2dos_format(fname, True); +#endif + + p = pdata; + name_ptr = p; + + name_map_mangle(fname,False,SNUM(cnum)); + + switch (info_level) + { + case 1: + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + put_dos_date2(p,l1_fdateCreation,cdate); + put_dos_date2(p,l1_fdateLastAccess,adate); + put_dos_date2(p,l1_fdateLastWrite,mdate); + SIVAL(p,l1_cbFile,size); + SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024)); + SSVAL(p,l1_attrFile,mode); + SCVAL(p,l1_cchName,strlen(fname)); + strcpy(p + l1_achName, fname); + name_ptr = p + l1_achName; + p += l1_achName + strlen(fname) + 1; + break; + + case 2: + /* info_level 2 */ + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + put_dos_date2(p,l2_fdateCreation,cdate); + put_dos_date2(p,l2_fdateLastAccess,adate); + put_dos_date2(p,l2_fdateLastWrite,mdate); + SIVAL(p,l2_cbFile,size); + SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024)); + SSVAL(p,l2_attrFile,mode); + SIVAL(p,l2_cbList,0); /* No extended attributes */ + SCVAL(p,l2_cchName,strlen(fname)); + strcpy(p + l2_achName, fname); + name_ptr = p + l2_achName; + p += l2_achName + strlen(fname) + 1; + break; + + case 3: + SIVAL(p,0,reskey); + put_dos_date2(p,4,cdate); + put_dos_date2(p,8,adate); + put_dos_date2(p,12,mdate); + SIVAL(p,16,size); + SIVAL(p,20,ROUNDUP(size,1024)); + SSVAL(p,24,mode); + SIVAL(p,26,4); + CVAL(p,30) = strlen(fname); + strcpy(p+31, fname); + name_ptr = p+31; + p += 31 + strlen(fname) + 1; + break; + + case 4: + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + SIVAL(p,0,33+strlen(fname)+1); + put_dos_date2(p,4,cdate); + put_dos_date2(p,8,adate); + put_dos_date2(p,12,mdate); + SIVAL(p,16,size); + SIVAL(p,20,ROUNDUP(size,1024)); + SSVAL(p,24,mode); + CVAL(p,32) = strlen(fname); + strcpy(p + 33, fname); + name_ptr = p+33; + p += 33 + strlen(fname) + 1; + break; + + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + was_8_3 = is_8_3(fname); + len = 94+strlen(fname); + len = (len + 3) & ~3; + SIVAL(p,0,len); p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); p += 8; + SIVAL(p,0,mode); p += 4; + SIVAL(p,0,strlen(fname)); p += 4; + SIVAL(p,0,0); p += 4; + if (!was_8_3) { +#ifndef KANJI + strcpy(p+2,unix2dos_format(fname,False)); +#else + strcpy(p+2,fname); +#endif + if (!name_map_mangle(p+2,True,SNUM(cnum))) + (p+2)[12] = 0; + } else + *(p+2) = 0; + strupper(p+2); + SSVAL(p,0,strlen(p+2)); + p += 2 + 24; + /* name_ptr = p; */ + strcpy(p,fname); p += strlen(p); + p = pdata + len; + break; + + case SMB_FIND_FILE_DIRECTORY_INFO: + len = 64+strlen(fname); + len = (len + 3) & ~3; + SIVAL(p,0,len); p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); p += 8; + SIVAL(p,0,mode); p += 4; + SIVAL(p,0,strlen(fname)); p += 4; + strcpy(p,fname); + p = pdata + len; + break; + + + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + len = 68+strlen(fname); + len = (len + 3) & ~3; + SIVAL(p,0,len); p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); p += 8; + SIVAL(p,0,mode); p += 4; + SIVAL(p,0,strlen(fname)); p += 4; + SIVAL(p,0,0); p += 4; + strcpy(p,fname); + p = pdata + len; + break; + + case SMB_FIND_FILE_NAMES_INFO: + len = 12+strlen(fname); + len = (len + 3) & ~3; + SIVAL(p,0,len); p += 4; + SIVAL(p,0,reskey); p += 4; + SIVAL(p,0,strlen(fname)); p += 4; + strcpy(p,fname); + p = pdata + len; + break; + + default: + return(False); + } + + + if (PTR_DIFF(p,pdata) > space_remaining) { + /* Move the dirptr back to prev_dirpos */ + SeekDir(Connections[cnum].dirptr, prev_dirpos); + *out_of_space = True; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } + + /* Setup the last_filename pointer, as an offset from base_data */ + *last_name_off = PTR_DIFF(name_ptr,base_data); + /* Advance the data pointer to the next slot */ + *ppdata = p; + return(found); +} + +/**************************************************************************** + reply to a TRANS2_FINDFIRST +****************************************************************************/ +static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum, + char **pparams, char **ppdata) +{ + /* We must be careful here that we don't return more than the + allowed number of data bytes. If this means returning fewer than + maxentries then so be it. We assume that the redirector has + enough room for the fixed number of parameter bytes it has + requested. */ + uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt); + char *params = *pparams; + char *pdata = *ppdata; + int dirtype = SVAL(params,0); + int maxentries = SVAL(params,2); + BOOL close_after_first = BITSETW(params+4,0); + BOOL close_if_end = BITSETW(params+4,1); + BOOL requires_resume_key = BITSETW(params+4,2); + int info_level = SVAL(params,6); + pstring directory; + pstring mask; + char *p, *wcard; + int last_name_off=0; + int dptr_num = -1; + int numentries = 0; + int i; + BOOL finished = False; + BOOL dont_descend = False; + BOOL out_of_space = False; + int space_remaining; + + *directory = *mask = 0; + + DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", + dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, + info_level, max_data_bytes)); + + switch (info_level) + { + case 1: + case 2: + case 3: + case 4: + case SMB_FIND_FILE_DIRECTORY_INFO: + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + case SMB_FIND_FILE_NAMES_INFO: + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + break; + default: + return(ERROR(ERRDOS,ERRunknownlevel)); + } + + strcpy(directory, params + 12); /* Complete directory path with + wildcard mask appended */ + + DEBUG(5,("path=%s\n",directory)); + + unix_convert(directory,cnum); + if(!check_name(directory,cnum)) { + return(ERROR(ERRDOS,ERRbadpath)); + } + + p = strrchr(directory,'/'); + if(p == NULL) { + strcpy(mask,directory); + strcpy(directory,"./"); + } else { + strcpy(mask,p+1); + *p = 0; + } + + DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); + + pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024); + if(!*ppdata) + return(ERROR(ERRDOS,ERRnomem)); + bzero(pdata,max_data_bytes); + + /* Realloc the params space */ + params = *pparams = Realloc(*pparams, 10); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid)); + if (dptr_num < 0) + return(ERROR(ERRDOS,ERRbadpath)); + + /* convert the formatted masks */ + { + p = mask; + while (*p) { + if (*p == '<') *p = '*'; + if (*p == '>') *p = '?'; + if (*p == '"') *p = '.'; + p++; + } + } + + /* a special case for 16 bit apps */ + if (strequal(mask,"????????.???")) strcpy(mask,"*"); + + /* handle broken clients that send us old 8.3 format */ + string_sub(mask,"????????","*"); + string_sub(mask,".???",".*"); + + /* Save the wildcard match and attribs we are using on this directory - + needed as lanman2 assumes these are being saved between calls */ + + if(!(wcard = strdup(mask))) { + dptr_close(dptr_num); + return(ERROR(ERRDOS,ERRnomem)); + } + + dptr_set_wcard(dptr_num, wcard); + dptr_set_attr(dptr_num, dirtype); + + DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype)); + + /* We don't need to check for VOL here as this is returned by + a different TRANS2 call. */ + + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", + Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); + if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive)) + dont_descend = True; + + p = pdata; + space_remaining = max_data_bytes; + out_of_space = False; + + for (i=0;(i 0) + { + out_of_space = True; + finished = False; + } + else + { + finished = + !get_lanman2_dir_entry(cnum,mask,dirtype,info_level, + requires_resume_key,dont_descend, + &p,pdata,space_remaining, &out_of_space, + &last_name_off); + } + + if (finished && out_of_space) + finished = False; + + if (!finished && !out_of_space) + numentries++; + space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + } + + /* Check if we can close the dirptr */ + if(close_after_first || (finished && close_if_end)) + { + dptr_close(dptr_num); + DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); + dptr_num = -1; + } + + /* At this point pdata points to numentries directory entries. */ + + /* Set up the return parameter block */ + SSVAL(params,0,dptr_num); + SSVAL(params,2,numentries); + SSVAL(params,4,finished); + SSVAL(params,6,0); /* Never an EA error */ + SSVAL(params,8,last_name_off); + + send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); + + if ((! *directory) && dptr_path(dptr_num)) + sprintf(directory,"(%s)",dptr_path(dptr_num)); + + DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", + timestring(), + smb_fn_name(CVAL(inbuf,smb_com)), + mask,directory,cnum,dirtype,numentries)); + + return(-1); +} + + +/**************************************************************************** + reply to a TRANS2_FINDNEXT +****************************************************************************/ +static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize, + int cnum, char **pparams, char **ppdata) +{ + /* We must be careful here that we don't return more than the + allowed number of data bytes. If this means returning fewer than + maxentries then so be it. We assume that the redirector has + enough room for the fixed number of parameter bytes it has + requested. */ + int max_data_bytes = SVAL(inbuf, smb_mdrcnt); + char *params = *pparams; + char *pdata = *ppdata; + int16 dptr_num = SVAL(params,0); + int maxentries = SVAL(params,2); + uint16 info_level = SVAL(params,4); + uint32 resume_key = IVAL(params,6); + BOOL close_after_request = BITSETW(params+10,0); + BOOL close_if_end = BITSETW(params+10,1); + BOOL requires_resume_key = BITSETW(params+10,2); + BOOL continue_bit = BITSETW(params+10,3); + pstring mask; + pstring directory; + char *p; + uint16 dirtype; + int numentries = 0; + int i, last_name_off=0; + BOOL finished = False; + BOOL dont_descend = False; + BOOL out_of_space = False; + int space_remaining; + + *mask = *directory = 0; + + DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d continue=%d level = %d\n", + dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, + requires_resume_key, resume_key, continue_bit, info_level)); + + switch (info_level) + { + case 1: + case 2: + case 3: + case 4: + case SMB_FIND_FILE_DIRECTORY_INFO: + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + case SMB_FIND_FILE_NAMES_INFO: + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + break; + default: + return(ERROR(ERRDOS,ERRunknownlevel)); + } + + pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024); + if(!*ppdata) + return(ERROR(ERRDOS,ERRnomem)); + bzero(pdata,max_data_bytes); + + /* Realloc the params space */ + params = *pparams = Realloc(*pparams, 6*SIZEOFWORD); + if(!params) + return(ERROR(ERRDOS,ERRnomem)); + + /* Check that the dptr is valid */ + if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num))) + return(ERROR(ERRDOS,ERRnofiles)); + + string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); + + /* Get the wildcard mask from the dptr */ + if((p = dptr_wcard(dptr_num))== NULL) { + DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); + return (ERROR(ERRDOS,ERRnofiles)); + } + strcpy(mask, p); + strcpy(directory,Connections[cnum].dirpath); + + /* Get the attr mask from the dptr */ + dirtype = dptr_attr(dptr_num); + + DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n", + dptr_num, mask, dirtype, + Connections[cnum].dirptr, + TellDir(Connections[cnum].dirptr))); + + /* We don't need to check for VOL here as this is returned by + a different TRANS2 call. */ + + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); + if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive)) + dont_descend = True; + + p = pdata; + space_remaining = max_data_bytes; + out_of_space = False; + + /* If we have a resume key - seek to the correct position. */ + if(requires_resume_key && !continue_bit) + SeekDir(Connections[cnum].dirptr, resume_key); + + for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) + { + /* this is a heuristic to avoid seeking the dirptr except when + absolutely necessary. It allows for a filename of about 40 chars */ + if (space_remaining < DIRLEN_GUESS && numentries > 0) + { + out_of_space = True; + finished = False; + } + else + { + finished = + !get_lanman2_dir_entry(cnum,mask,dirtype,info_level, + requires_resume_key,dont_descend, + &p,pdata,space_remaining, &out_of_space, + &last_name_off); + } + + if (finished && out_of_space) + finished = False; + + if (!finished && !out_of_space) + numentries++; + space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + } + + /* Check if we can close the dirptr */ + if(close_after_request || (finished && close_if_end)) + { + dptr_close(dptr_num); /* This frees up the saved mask */ + DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); + dptr_num = -1; + } + + + /* Set up the return parameter block */ + SSVAL(params,0,numentries); + SSVAL(params,2,finished); + SSVAL(params,4,0); /* Never an EA error */ + SSVAL(params,6,last_name_off); + + send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); + + if ((! *directory) && dptr_path(dptr_num)) + sprintf(directory,"(%s)",dptr_path(dptr_num)); + + DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", + timestring(), + smb_fn_name(CVAL(inbuf,smb_com)), + mask,directory,cnum,dirtype,numentries)); + + return(-1); +} + +/**************************************************************************** + reply to a TRANS2_QFSINFO (query filesystem info) +****************************************************************************/ +static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize, + int cnum, char **pparams, char **ppdata) +{ + char *pdata = *ppdata; + char *params = *pparams; + uint16 info_level = SVAL(params,0); + int data_len; + struct stat st; + char *vname = volume_label(SNUM(cnum)); + + DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level)); + + if(sys_stat(".",&st)!=0) { + DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); + return (ERROR(ERRSRV,ERRinvdevice)); + } + + pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024); + + switch (info_level) + { + case 1: + { + int dfree,dsize,bsize; + data_len = 18; + sys_disk_free(".",&bsize,&dfree,&dsize); + SIVAL(pdata,l1_idFileSystem,st.st_dev); + SIVAL(pdata,l1_cSectorUnit,bsize/512); + SIVAL(pdata,l1_cUnit,dsize); + SIVAL(pdata,l1_cUnitAvail,dfree); + SSVAL(pdata,l1_cbSector,512); + DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n", + bsize, st.st_dev, bsize/512, dsize, dfree, 512)); + break; + } + case 2: + { + /* Return volume name */ + int volname_len = MIN(strlen(vname),11); + data_len = l2_vol_szVolLabel + volname_len + 1; + put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime); + SCVAL(pdata,l2_vol_cch,volname_len); + StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); + DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len, + pdata+l2_vol_szVolLabel)); + break; + } + case SMB_QUERY_FS_ATTRIBUTE_INFO: + data_len = 12 + 2*strlen(FSTYPE_STRING); + SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ + SIVAL(pdata,4,128); /* Max filename component length */ + SIVAL(pdata,8,2*strlen(FSTYPE_STRING)); + PutUniCode(pdata+12,FSTYPE_STRING); + break; + case SMB_QUERY_FS_LABEL_INFO: + data_len = 4 + strlen(vname); + SIVAL(pdata,0,strlen(vname)); + strcpy(pdata+4,vname); + break; + case SMB_QUERY_FS_VOLUME_INFO: + data_len = 17 + strlen(vname); + SIVAL(pdata,12,strlen(vname)); + strcpy(pdata+17,vname); + break; + case SMB_QUERY_FS_SIZE_INFO: + { + int dfree,dsize,bsize; + data_len = 24; + sys_disk_free(".",&bsize,&dfree,&dsize); + SIVAL(pdata,0,dsize); + SIVAL(pdata,8,dfree); + SIVAL(pdata,16,bsize/512); + SIVAL(pdata,20,512); + } + break; + case SMB_QUERY_FS_DEVICE_INFO: + data_len = 8; + SIVAL(pdata,0,0); /* dev type */ + SIVAL(pdata,4,0); /* characteristics */ + break; + default: + return(ERROR(ERRDOS,ERRunknownlevel)); + } + + + send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len); + + DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level)); + + return -1; +} + +/**************************************************************************** + reply to a TRANS2_SETFSINFO (set filesystem info) +****************************************************************************/ +static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize, + int cnum, char **pparams, char **ppdata) +{ + /* Just say yes we did it - there is nothing that + can be set here so it doesn't matter. */ + int outsize; + DEBUG(3,("call_trans2setfsinfo\n")); + + if (!CAN_WRITE(cnum)) + return(ERROR(ERRSRV,ERRaccess)); + + outsize = set_message(outbuf,10,0,True); + + return outsize; +} + +/**************************************************************************** + reply to a TRANS2_QFILEINFO (query file info by fileid) +****************************************************************************/ +static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, + int bufsize,int cnum, + char **pparams,char **ppdata, + int total_data) +{ + char *params = *pparams; + char *pdata = *ppdata; + uint16 tran_call = SVAL(inbuf, smb_setup0); + uint16 info_level; + int mode=0; + int size=0; + unsigned int data_size; + struct stat sbuf; + pstring fname1; + char *fname; + char *p; + int l,pos; + + + if (tran_call == TRANSACT2_QFILEINFO) { + int16 fnum = SVAL(params,0); + info_level = SVAL(params,2); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + fname = Files[fnum].name; + if (fstat(Files[fnum].fd,&sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + pos = lseek(Files[fnum].fd,0,SEEK_CUR); + } else { + /* qpathinfo */ + info_level = SVAL(params,0); + fname = &fname1[0]; + strcpy(fname,¶ms[6]); + unix_convert(fname,cnum); + if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + pos = 0; + } + + + DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", + fname,info_level,tran_call,total_data)); + + p = strrchr(fname,'/'); + if (!p) + p = fname; + else + p++; + l = strlen(p); + mode = dos_mode(cnum,fname,&sbuf); + size = sbuf.st_size; + if (mode & aDIR) size = 0; + + params = *pparams = Realloc(*pparams,2); bzero(params,2); + data_size = 1024; + pdata = *ppdata = Realloc(*ppdata, data_size); + + if (total_data > 0 && IVAL(pdata,0) == total_data) { + /* uggh, EAs for OS2 */ + DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); +#if 0 + SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); +#else + return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); +#endif + } + + bzero(pdata,data_size); + + switch (info_level) + { + case 1: + case 2: + data_size = (info_level==1?22:26); + put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); + put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); + put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); + SIVAL(pdata,l1_cbFile,size); + SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); + SSVAL(pdata,l1_attrFile,mode); + SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ + break; + + case 3: + data_size = 24; + put_dos_date2(pdata,0,sbuf.st_ctime); + put_dos_date2(pdata,4,sbuf.st_atime); + put_dos_date2(pdata,8,sbuf.st_mtime); + SIVAL(pdata,12,size); + SIVAL(pdata,16,ROUNDUP(size,1024)); + SIVAL(pdata,20,mode); + break; + + case 4: + data_size = 4; + SIVAL(pdata,0,data_size); + break; + + case 6: + return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */ + + case SMB_QUERY_FILE_BASIC_INFO: + data_size = 36; + put_long_date(pdata,sbuf.st_ctime); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); + put_long_date(pdata+24,sbuf.st_mtime); + SIVAL(pdata,32,mode); + break; + + case SMB_QUERY_FILE_STANDARD_INFO: + data_size = 22; + SIVAL(pdata,0,size); + SIVAL(pdata,8,size); + SIVAL(pdata,16,sbuf.st_nlink); + CVAL(pdata,20) = 0; + CVAL(pdata,21) = (mode&aDIR)?1:0; + break; + + case SMB_QUERY_FILE_EA_INFO: + data_size = 4; + break; + + case SMB_QUERY_FILE_NAME_INFO: + case SMB_QUERY_FILE_ALT_NAME_INFO: + data_size = 4 + l; + SIVAL(pdata,0,l); + strcpy(pdata+4,fname); + break; + case SMB_QUERY_FILE_ALLOCATION_INFO: + case SMB_QUERY_FILE_END_OF_FILEINFO: + data_size = 8; + SIVAL(pdata,0,size); + break; + + case SMB_QUERY_FILE_ALL_INFO: + put_long_date(pdata,sbuf.st_ctime); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); + put_long_date(pdata+24,sbuf.st_mtime); + SIVAL(pdata,32,mode); + pdata += 40; + SIVAL(pdata,0,size); + SIVAL(pdata,8,size); + SIVAL(pdata,16,sbuf.st_nlink); + CVAL(pdata,20) = 0; + CVAL(pdata,21) = (mode&aDIR)?1:0; + pdata += 24; + pdata += 8; /* index number */ + pdata += 4; /* EA info */ + if (mode & aRONLY) + SIVAL(pdata,0,0xA9); + else + SIVAL(pdata,0,0xd01BF); + pdata += 4; + SIVAL(pdata,0,pos); /* current offset */ + pdata += 8; + SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ + pdata += 4; + pdata += 4; /* alignment */ + SIVAL(pdata,0,l); + strcpy(pdata+4,fname); + pdata += 4 + l; + data_size = PTR_DIFF(pdata,(*ppdata)); + break; + + case SMB_QUERY_FILE_STREAM_INFO: + data_size = 24 + l; + SIVAL(pdata,0,pos); + SIVAL(pdata,4,size); + SIVAL(pdata,12,size); + SIVAL(pdata,20,l); + strcpy(pdata+24,fname); + break; + default: + return(ERROR(ERRDOS,ERRunknownlevel)); + } + + send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size); + + return(-1); +} + +/**************************************************************************** + reply to a TRANS2_SETFILEINFO (set file info by fileid) +****************************************************************************/ +static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, + int bufsize, int cnum, char **pparams, + char **ppdata, int total_data) +{ + char *params = *pparams; + char *pdata = *ppdata; + uint16 tran_call = SVAL(inbuf, smb_setup0); + uint16 info_level; + int mode=0; + int size=0; + struct utimbuf tvs; + struct stat st; + pstring fname1; + char *fname; + int fd = -1; + + if (!CAN_WRITE(cnum)) + return(ERROR(ERRSRV,ERRaccess)); + + if (tran_call == TRANSACT2_SETFILEINFO) { + int16 fnum = SVAL(params,0); + info_level = SVAL(params,2); + + CHECK_FNUM(fnum,cnum); + CHECK_ERROR(fnum); + + fname = Files[fnum].name; + fd = Files[fnum].fd; + + if(fstat(fd,&st)!=0) { + DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); + return(ERROR(ERRDOS,ERRbadpath)); + } + } else { + /* set path info */ + info_level = SVAL(params,0); + fname = fname1; + strcpy(fname,¶ms[6]); + unix_convert(fname,cnum); + if(!check_name(fname, cnum)) + return(ERROR(ERRDOS,ERRbadpath)); + + if(sys_stat(fname,&st)!=0) { + DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); + return(ERROR(ERRDOS,ERRbadpath)); + } + } + + DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", + tran_call,fname,info_level,total_data)); + + /* Realloc the parameter and data sizes */ + params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + size = st.st_size; + tvs.modtime = st.st_mtime; + tvs.actime = st.st_atime; + mode = dos_mode(cnum,fname,&st); + + if (total_data > 0 && IVAL(pdata,0) == total_data) { + /* uggh, EAs for OS2 */ + DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); + SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED); + + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + + return(-1); + } + + switch (info_level) + { + case 1: + tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); + tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); + mode = SVAL(pdata,l1_attrFile); + size = IVAL(pdata,l1_cbFile); + break; + + case 2: + tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); + tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); + mode = SVAL(pdata,l1_attrFile); + size = IVAL(pdata,l1_cbFile); + break; + + case 3: + tvs.actime = make_unix_date2(pdata+8); + tvs.modtime = make_unix_date2(pdata+12); + size = IVAL(pdata,16); + mode = IVAL(pdata,24); + break; + + case 4: + tvs.actime = make_unix_date2(pdata+8); + tvs.modtime = make_unix_date2(pdata+12); + size = IVAL(pdata,16); + mode = IVAL(pdata,24); + break; + + case SMB_SET_FILE_BASIC_INFO: + pdata += 8; /* create time */ + tvs.actime = interpret_long_date(pdata); pdata += 8; + tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8)); + pdata += 16; + mode = IVAL(pdata,0); + break; + + case SMB_SET_FILE_END_OF_FILE_INFO: + if (IVAL(pdata,4) != 0) /* more than 32 bits? */ + return(ERROR(ERRDOS,ERRunknownlevel)); + size = IVAL(pdata,0); + break; + + case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */ + case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */ + default: + return(ERROR(ERRDOS,ERRunknownlevel)); + } + + + if (!tvs.actime) tvs.actime = st.st_atime; + if (!tvs.modtime) tvs.modtime = st.st_mtime; + if (!size) size = st.st_size; + + /* Try and set the times, size and mode of this file - if they are different + from the current values */ + if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { + if(sys_utime(fname, &tvs)!=0) + return(ERROR(ERRDOS,ERRnoaccess)); + } + if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) { + DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); + return(ERROR(ERRDOS,ERRnoaccess)); + } + if(size != st.st_size) { + if (fd == -1) { + fd = sys_open(fname,O_RDWR,0); + if (fd == -1) + return(ERROR(ERRDOS,ERRbadpath)); + set_filelen(fd, size); + close(fd); + } else { + set_filelen(fd, size); + } + } + + SSVAL(params,0,0); + + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + + return(-1); +} + +/**************************************************************************** + reply to a TRANS2_MKDIR (make directory with extended attributes). +****************************************************************************/ +static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, + int cnum, char **pparams, char **ppdata) +{ + char *params = *pparams; + pstring directory; + int ret = -1; + + if (!CAN_WRITE(cnum)) + return(ERROR(ERRSRV,ERRaccess)); + + strcpy(directory, ¶ms[4]); + + DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); + + unix_convert(directory,cnum); + if (check_name(directory,cnum)) + ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); + + if(ret < 0) + { + DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* Realloc the parameter and data sizes */ + params = *pparams = Realloc(*pparams,2); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + SSVAL(params,0,0); + + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + + return(-1); +} + +/**************************************************************************** + reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes) + We don't actually do this - we just send a null response. +****************************************************************************/ +static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize, + int cnum, char **pparams, char **ppdata) +{ + static uint16 fnf_handle = 257; + char *params = *pparams; + uint16 info_level = SVAL(params,4); + + DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level)); + + switch (info_level) + { + case 1: + case 2: + break; + default: + return(ERROR(ERRDOS,ERRunknownlevel)); + } + + /* Realloc the parameter and data sizes */ + params = *pparams = Realloc(*pparams,6); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + SSVAL(params,0,fnf_handle); + SSVAL(params,2,0); /* No changes */ + SSVAL(params,4,0); /* No EA errors */ + + fnf_handle++; + + if(fnf_handle == 0) + fnf_handle = 257; + + send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0); + + return(-1); +} + +/**************************************************************************** + reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for + changes). Currently this does nothing. +****************************************************************************/ +static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize, + int cnum, char **pparams, char **ppdata) +{ + char *params = *pparams; + + DEBUG(3,("call_trans2findnotifynext\n")); + + /* Realloc the parameter and data sizes */ + params = *pparams = Realloc(*pparams,4); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + SSVAL(params,0,0); /* No changes */ + SSVAL(params,2,0); /* No EA errors */ + + send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0); + + return(-1); +} + +/**************************************************************************** + reply to a SMBfindclose (stop trans2 directory search) +****************************************************************************/ +int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize) +{ + int cnum; + int outsize = 0; + uint16 dptr_num=SVAL(inbuf,smb_vwv0); + + cnum = SVAL(inbuf,smb_tid); + + DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num)); + + dptr_close(dptr_num); + + outsize = set_message(outbuf,0,0,True); + + DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num)); + + return(outsize); +} + +/**************************************************************************** + reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search) +****************************************************************************/ +int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize) +{ + int cnum; + int outsize = 0; + int dptr_num= -1; + + cnum = SVAL(inbuf,smb_tid); + dptr_num = SVAL(inbuf,smb_vwv0); + + DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num)); + + /* We never give out valid handles for a + findnotifyfirst - so any dptr_num is ok here. + Just ignore it. */ + + outsize = set_message(outbuf,0,0,True); + + DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num)); + + return(outsize); +} + + +/**************************************************************************** + reply to a SMBtranss2 - just ignore it! +****************************************************************************/ +int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize) +{ + DEBUG(4,("Ignoring transs2 of length %d\n",length)); + return(-1); +} + +/**************************************************************************** + reply to a SMBtrans2 +****************************************************************************/ +int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) +{ + int outsize = 0; + int cnum = SVAL(inbuf,smb_tid); + unsigned int total_params = SVAL(inbuf, smb_tpscnt); + unsigned int total_data =SVAL(inbuf, smb_tdscnt); +#if 0 + unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt); + unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt); + unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt); + BOOL close_tid = BITSETW(inbuf+smb_flags,0); + BOOL no_final_response = BITSETW(inbuf+smb_flags,1); + int32 timeout = IVALS(inbuf,smb_timeout); +#endif + unsigned int suwcnt = SVAL(inbuf, smb_suwcnt); + unsigned int tran_call = SVAL(inbuf, smb_setup0); + char *params = NULL, *data = NULL; + int num_params, num_params_sofar, num_data, num_data_sofar; + + outsize = set_message(outbuf,0,0,True); + + /* All trans2 messages we handle have smb_sucnt == 1 - ensure this + is so as a sanity check */ + if(suwcnt != 1 ) + { + DEBUG(2,("Invalid smb_sucnt in trans2 call\n")); + return(ERROR(ERRSRV,ERRerror)); + } + + /* Allocate the space for the maximum needed parameters and data */ + if (total_params > 0) + params = (char *)malloc(total_params); + if (total_data > 0) + data = (char *)malloc(total_data); + + if ((total_params && !params) || (total_data && !data)) + { + DEBUG(2,("Out of memory in reply_trans2\n")); + return(ERROR(ERRDOS,ERRnomem)); + } + + /* Copy the param and data bytes sent with this request into + the params buffer */ + num_params = num_params_sofar = SVAL(inbuf,smb_pscnt); + num_data = num_data_sofar = SVAL(inbuf, smb_dscnt); + + memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); + memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); + + if(num_data_sofar < total_data || num_params_sofar < total_params) + { + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + send_smb(Client,outbuf); + + while( num_data_sofar < total_data || num_params_sofar < total_params) + { + receive_smb(Client,inbuf, 0); + + /* Ensure this is still a trans2 packet (sanity check) */ + if(CVAL(inbuf, smb_com) != SMBtranss2) + { + outsize = set_message(outbuf,0,0,True); + DEBUG(2,("Invalid secondary trans2 packet\n")); + free(params); + free(data); + return(ERROR(ERRSRV,ERRerror)); + } + + /* Revise total_params and total_data in case they have changed downwards */ + total_params = SVAL(inbuf, smb_tpscnt); + total_data = SVAL(inbuf, smb_tdscnt); + num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt)); + num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt)); + memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], + smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params); + memcpy( &data[SVAL(inbuf, smb_sdsdisp)], + smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data); + } + } + + if (Protocol >= PROTOCOL_NT1) { + uint16 flg2 = SVAL(outbuf,smb_flg2); + SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + } + + /* Now we must call the relevant TRANS2 function */ + switch(tran_call) + { + case TRANSACT2_OPEN: + outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data); + break; + case TRANSACT2_FINDFIRST: + outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data); + break; + case TRANSACT2_FINDNEXT: + outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); + break; + case TRANSACT2_QFSINFO: + outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); + break; + case TRANSACT2_SETFSINFO: + outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); + break; + case TRANSACT2_QPATHINFO: + case TRANSACT2_QFILEINFO: + outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data); + break; + case TRANSACT2_SETPATHINFO: + case TRANSACT2_SETFILEINFO: + outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data); + break; + case TRANSACT2_FINDNOTIFYFIRST: + outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); + break; + case TRANSACT2_FINDNOTIFYNEXT: + outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); + break; + case TRANSACT2_MKDIR: + outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); + break; + default: + /* Error in request */ + DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call)); + if(params) + free(params); + if(data) + free(data); + return (ERROR(ERRSRV,ERRerror)); + } + + /* As we do not know how many data packets will need to be + returned here the various call_trans2xxxx calls + must send their own. Thus a call_trans2xxx routine only + returns a value other than -1 when it wants to send + an error packet. + */ + + if(params) + free(params); + if(data) + free(data); + return outsize; /* If a correct response was needed the call_trans2xxx + calls have already sent it. If outsize != -1 then it is + returning an error packet. */ +} diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c new file mode 100644 index 0000000000..83b62a38ac --- /dev/null +++ b/source3/smbd/vt_mode.c @@ -0,0 +1,496 @@ +/* vt_mode.c */ +/* +support vtp-sessions + +written by Christian A. Lademann +*/ + +/* +02.05.95:cal:ported to samba-1.9.13 +*/ + +#define __vt_mode_c__ + + +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ + +#include "includes.h" +#include "vt_mode.h" +#include + +#ifdef SCO + extern char *strdup(); +#endif + +extern int Client; + +#ifdef LINUX +# define HAS_VTY +#endif + +#ifdef SCO +# define HAS_PTY +# define HAS_VTY + +# include +#endif + +extern int DEBUGLEVEL; +extern char *InBuffer, *OutBuffer; +extern int done_become_user; + +char master_name [64], slave_name [64]; +int master, slave, i, o, e; + +int ms_type = MS_NONE, + ms_poll = 0; + + +/* +VT_Check: test incoming packet for "vtp" or "iVT1\0" +*/ +int VT_Check(buffer) +char *buffer; +{ + DEBUG(3,("Checking packet: <%10s...>\n", buffer+4)); + if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5)) + return(1); + else + return(0); +} + + +/* +VT_Start_utmp: prepare /etc/utmp for /bin/login +*/ +VT_Start_utmp() +{ + struct utmp u, *v; + char *tt; + + + setutent(); + + strcpy(u.ut_line, VT_Line); + + if((v = getutline(&u)) == NULL) { + if(strncmp(VT_Line, "tty", 3) == 0) + tt = VT_Line + 3; + else if(strlen(VT_Line) > 4) + tt = VT_Line + strlen(VT_Line) - 4; + else + tt = VT_Line; + + strcpy(u.ut_id, tt); + u.ut_time = time((time_t*)0); + } + + strcpy(u.ut_user, "LOGIN"); + strcpy(u.ut_line, VT_Line); + u.ut_pid = getpid(); + u.ut_type = LOGIN_PROCESS; + pututline(&u); + + endutent(); + + return(0); +} + + +/* +VT_Stop_utmp: prepare /etc/utmp for other processes +*/ +VT_Stop_utmp() +{ + struct utmp u, *v; + + + if(VT_Line != NULL) { + setutent(); + + strcpy(u.ut_line, VT_Line); + + if((v = getutline(&u)) != NULL) { + strcpy(v->ut_user, ""); + v->ut_type = DEAD_PROCESS; + v->ut_time = time((time_t*)0); + pututline(v); + } + + endutent(); + } + + return(0); +} + + +/* +VT_AtExit: Things to do when the program exits +*/ +void VT_AtExit() +{ + if(VT_ChildPID > 0) { + kill(VT_ChildPID, SIGHUP); + (void)wait(NULL); + } + + VT_Stop_utmp(); +} + + +/* +VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died +*/ +void VT_SigCLD(sig) +int sig; +{ + if(wait(NULL) == VT_ChildPID) + VT_ChildDied = True; + else + signal(SIGCLD, VT_SigCLD); +} + + +/* +VT_SigEXIT: signalhandler for signals that cause the process to exit +*/ +void VT_SigEXIT(sig) +int sig; +{ + VT_AtExit(); + + exit(1); +} + + +/* +VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK +*/ +int VT_Start() +{ + char OutBuf [64], *X, *Y; + + + ms_type = MS_NONE; + master = slave = -1; + +#ifdef HAS_VTY +#ifdef LINUX +# define MASTER_TMPL "/dev/pty " +# define SLAVE_TMPL "/dev/tty " +# define LETTER1 "pqrs" +# define POS1 8 +# define LETTER2 "0123456789abcdef" +# define POS2 9 +#endif + +#ifdef SCO +# define MASTER_TMPL "/dev/ptyp_ " +# define SLAVE_TMPL "/dev/ttyp_ " +# define LETTER1 "0123456" +# define POS1 10 +# define LETTER2 "0123456789abcdef" +# define POS2 11 +#endif + + if(ms_poll == MS_VTY || ms_poll == 0) { + strcpy(master_name, MASTER_TMPL); + strcpy(slave_name, SLAVE_TMPL); + + for(X = LETTER1; *X && master < 0; X++) + for(Y = LETTER2; *Y && master < 0; Y++) { + master_name [POS1] = *X; + master_name [POS2] = *Y; + if((master = open(master_name, O_RDWR)) >= 0) { + slave_name [POS1] = *X; + slave_name [POS2] = *Y; + if((slave = open(slave_name, O_RDWR)) < 0) + close(master); + } + } + + if(master >= 0 && slave >= 0) + ms_type = MS_VTY; + } + +# undef MASTER_TMPL +# undef SLAVE_TMPL +# undef LETTER1 +# undef LETTER2 +# undef POS1 +# undef POS2 +#endif + + +#ifdef HAS_PTY +#ifdef SCO +# define MASTER_TMPL "/dev/ptyp%d" +# define SLAVE_TMPL "/dev/ttyp%d" +# define MIN_I 0 +# define MAX_I 63 +#endif + + if(ms_poll == MS_PTY || ms_poll == 0) { + int i; + + for(i = MIN_I; i <= MAX_I && master < 0; i++) { + sprintf(master_name, MASTER_TMPL, i); + if((master = open(master_name, O_RDWR)) >= 0) { + sprintf(slave_name, SLAVE_TMPL, i); + if((slave = open(slave_name, O_RDWR)) < 0) + close(master); + } + } + + if(master >= 0 && slave >= 0) + ms_type = MS_PTY; + } + +# undef MASTER_TMPL +# undef SLAVE_TMPL +# undef MIN_I +# undef MAX_I +#endif + + + if(! ms_type) + return(-1); + + VT_Line = strdup(strrchr(slave_name, '/') + 1); + + switch((VT_ChildPID = fork())) { + case -1: + return(-1); + break; + + case 0: +#ifdef SCO + setsid(); +#endif + close(0); + close(1); + close(2); + + i = open(slave_name, O_RDWR); + o = open(slave_name, O_RDWR); + e = open(slave_name, O_RDWR); + +#ifdef LINUX + setsid(); + if (ioctl(slave, TIOCSCTTY, (char *)NULL) == -1) + exit(1); +#endif +#ifdef SCO + tcsetpgrp(0, getpid()); +#endif + + VT_Start_utmp(); + + system("stty sane"); + execlp("/bin/login", "login", "-c", (char*)0); + exit(1); + break; + + default: + VT_Mode = True; + VT_Status = VT_OPEN; + VT_ChildDied = False; + VT_Fd = master; + + signal(SIGCLD, VT_SigCLD); + + signal(SIGHUP, VT_SigEXIT); + signal(SIGTERM, VT_SigEXIT); + signal(SIGINT, VT_SigEXIT); + signal(SIGQUIT, VT_SigEXIT); + + memset(OutBuf, 0, sizeof(OutBuf)); + OutBuf [4] = 0x06; + _smb_setlen(OutBuf, 1); + + send_smb(Client,OutBuf); + + return(0); + break; + } +} + + +/* +VT_Output: transport data from socket to pty +*/ +int VT_Output(Buffer) +char *Buffer; +{ + int i, len, nb; + + + if(VT_Status != VT_OPEN) + return(-1); + + len = smb_len(Buffer); + + nb = write(VT_Fd, Buffer + 4, len); + + return((nb == len) ? 0 : -1); +} + + +/* +VT_Input: transport data from pty to socket +*/ +int VT_Input(Buffer, Size) +char *Buffer; +int Size; +{ + int len; + + + if(VT_Status != VT_OPEN) + return(-1); + + memset(Buffer, 0, Size); + len = read(VT_Fd, Buffer + 4, MIN(VT_MAXREAD, Size)); + + _smb_setlen(Buffer, len); + + return(len + 4); +} + + +/* +VT_Process: main loop while in vt-mode +*/ +void VT_Process() +{ + static int trans_num = 0; + extern int Client; + int nread; + + + VT_Start(); + + atexit(VT_AtExit); + + while (True) { + int32 len; + int msg_type; + int msg_flags; + int counter; + int last_keepalive=0; + struct fd_set si; + struct timeval to, *top; + int n, ret, t; + + + errno = 0; + t = SMBD_SELECT_LOOP*1000; + + + FD_ZERO(&si); + FD_SET(Client, &si); + + FD_SET(VT_Fd, &si); + + if(t >= 0) { + to.tv_sec = t / 1000; + to.tv_usec = t - (to.tv_sec * 1000); + + top = &to; + } else + top = NULL; + + if(VT_ChildDied) + goto leave_VT_Process; + + n = select(MAX(VT_Fd, Client) + 1, &si, NULL, NULL, top); + + if(VT_ChildDied) + goto leave_VT_Process; + + if(n == 0) { + int i; + time_t t; + BOOL allidle = True; + extern int keepalive; + + counter += SMBD_SELECT_LOOP; + + t = time(NULL); + + if (keepalive && (counter-last_keepalive)>keepalive) { + if (!send_keepalive(Client)) + goto leave_VT_Process; + last_keepalive = counter; + } + } else if(n > 0) { + counter = 0; + + if(FD_ISSET(VT_Fd, &si)) { + /* got input from vt */ + nread = VT_Input(OutBuffer, MIN(BUFFER_SIZE,lp_maxxmit())); + + if(nread > 0) + send_smb(Client,OutBuffer); + } + + if(FD_ISSET(Client, &si)) { + /* got input from socket */ + + if(receive_smb(Client,InBuffer, 0)) { + msg_type = CVAL(InBuffer,0); + msg_flags = CVAL(InBuffer,1); + + len = smb_len(InBuffer); + + DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); + + nread = len + 4; + + DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + + if(msg_type == 0) + VT_Output(InBuffer); + else { + nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit())); + + if(nread > 0) { + if (nread != smb_len(OutBuffer) + 4) { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, + smb_len(OutBuffer))); + } else + send_smb(Client,OutBuffer); + } + } + } else + if(errno == EBADF) + goto leave_VT_Process; + } + } + + trans_num++; + } + + leave_VT_Process: +/* + if(VT_ChildPID > 0) + kill(VT_ChildPID, SIGHUP); + + VT_Stop_utmp(VT_Line); + return; +*/ + close_sockets(); + exit(0); +} -- cgit From 6bbd0d7b69ea9e27b1020833227aca196e14a75d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 May 1996 10:43:29 +0000 Subject: use the new issafe() macro instead of isalnum() and strchr() (This used to be commit 79c65e66f8034d21b6c90fcdbd76601657f3c447) --- source3/smbd/ipc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8852e57e8b..34210f2db7 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1551,8 +1551,7 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data, int l = 0; while (l<64 && *s) { - if (isalnum(*s) || strchr("-._",*s)) - name[l++] = *s; + if (issafe(*s)) name[l++] = *s; s++; } name[l] = 0; -- cgit From 089c5b2165003c7e668e1529929815871f16dc5a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 May 1996 10:44:49 +0000 Subject: move the dot_pos calculation down a bit (This used to be commit 45e2ffdc9c4334565e51c550b3a19a9bbb7037ef) --- source3/smbd/mangle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 8f1490c528..a43e7f6245 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -90,8 +90,6 @@ BOOL is_8_3(char *fname) if (slash_pos) fname = slash_pos+1; len = strlen(fname); - dot_pos = strchr(fname,'.'); - DEBUG(5,("checking %s for 8.3\n",fname)); if (case_mangle) @@ -122,6 +120,8 @@ BOOL is_8_3(char *fname) /* %%% A nice improvment to name mangling would be to translate filename to ANSI charset on the smb server host */ + dot_pos = strchr(fname,'.'); + { char *p = fname; #ifdef KANJI -- cgit From 03aeb8af5d97c1be6122ea90d53fa386e22c3046 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 May 1996 10:45:50 +0000 Subject: fix a netgroup bug (innetgr() was being called with the args in the wrong order!) (This used to be commit 4419093d336bad30b194b959231fed04cbc8a1cf) --- source3/smbd/password.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 87c1fef94c..863032df87 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1153,13 +1153,12 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) BOOL host_ok = False; #ifdef NETGROUP - /* THIS IS UNTESTED!! */ if (is_group) { static char *mydomain = NULL; if (!mydomain) yp_get_default_domain(&mydomain); - if (mydomain && innetgr(remote,file_host,user,mydomain)) + if (mydomain && innetgr(file_host,remote,user,mydomain)) host_ok = True; } #else -- cgit From b2a31c9e8118519b13c3625f6d1b46042bcb9501 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 May 1996 10:48:19 +0000 Subject: - use issafe() - map the archive bit in a more robust manner. We now set it when we first write to the file after opening it. (This used to be commit d20627b378e41546f00e5aabc86a71889ebc236a) --- source3/smbd/server.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5d8facef33..605e98be0f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -257,7 +257,7 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); unixmode |= tmp; } - + return(chmod(fname,unixmode)); } @@ -410,8 +410,12 @@ BOOL unix_convert(char *name,int cnum) { if ((! *name) || strchr(name,'/') || !is_8_3(name)) { + char *s; fstring name2; sprintf(name2,"%.6s.XXXXXX",remote_machine); + /* sanitise the name */ + for (s=name2 ; *s ; s++) + if (!issafe(*s)) *s = '_'; strcpy(name,(char *)mktemp(name2)); } return(True); @@ -1227,16 +1231,6 @@ void close_file(int fnum) if (lp_share_modes(SNUM(cnum))) del_share_mode(fnum); - if (Files[fnum].modified) { - struct stat st; - if (fstat(Files[fnum].fd,&st) == 0) { - int dosmode = dos_mode(cnum,Files[fnum].name,&st); - if (!IS_DOS_ARCHIVE(dosmode)) { - dos_chmod(cnum,Files[fnum].name,dosmode | aARCH,&st); - } - } - } - close(Files[fnum].fd); /* NT uses smbclose to start a print - weird */ @@ -1609,7 +1603,16 @@ int write_file(int fnum,char *data,int n) return(0); } - Files[fnum].modified = True; + if (!Files[fnum].modified) { + struct stat st; + Files[fnum].modified = True; + if (fstat(Files[fnum].fd,&st) == 0) { + int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st); + if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) { + dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st); + } + } + } return(write_data(Files[fnum].fd,data,n)); } -- cgit From 52fc872aec226258aa88c6676625ce2485257678 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 May 1996 03:04:19 +0000 Subject: - close the listening socket in the child process when running as a daemon - exit with a non-zero exit code if open_sockets() fails (This used to be commit 83866f3c84bd53a68f4937dddf4903eee7a00aaf) --- source3/smbd/server.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 605e98be0f..c77a5ca8a7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2225,6 +2225,9 @@ static BOOL open_sockets(BOOL is_daemon,int port) signal(SIGPIPE, SIGNAL_CAST sig_pipe); signal(SIGCLD, SIGNAL_CAST SIG_DFL); #endif + /* close the listening socket */ + close(s); + /* close our standard file descriptors */ close_low_fds(); @@ -4280,22 +4283,23 @@ int main(int argc,char *argv[]) become_daemon(); } - if (open_sockets(is_daemon,port)) - { - /* possibly reload the services file. */ - reload_services(True); + if (!open_sockets(is_daemon,port)) + exit(1); - maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE); + /* possibly reload the services file. */ + reload_services(True); - if (*lp_rootdir()) - { - if (sys_chroot(lp_rootdir()) == 0) - DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); - } + maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE); - process(); - close_sockets(); + if (*lp_rootdir()) + { + if (sys_chroot(lp_rootdir()) == 0) + DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); } + + process(); + close_sockets(); + exit_server("normal exit"); return(0); } -- cgit From 341a401b4802b2759092819ab5e50fe237a406d9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 May 1996 11:23:23 +0000 Subject: handle being passed a dptr of -1 to mean "close all open dir handles". Looks like OS/2 does this. It caused a core dump. (This used to be commit 4b2579daae0a9d78780476694fd395d97445e197) --- source3/smbd/dir.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ac6f918b9d..214b28dad0 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -186,6 +186,19 @@ close a dptr ****************************************************************************/ void dptr_close(int key) { + /* OS/2 seems to use -1 to indicate "close all directories" */ + if (key == -1) { + int i; + for (i=0;i= NUMDIRPTRS) { + DEBUG(3,("Invalid key %d given to dptr_close\n",key)); + return; + } + if (dirptrs[key].valid) { DEBUG(4,("closing dptr key %d\n",key)); if (dirptrs[key].ptr) { -- cgit From 11f7553c7495ecae3e918d8329107174c2ce0149 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 May 1996 11:25:07 +0000 Subject: turn on KEEP_PASSWORD_SERVER_OPEN by default (This used to be commit d2676cdd0b44fc4fc825118e510bac2c3f1e40d9) --- source3/smbd/password.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 863032df87..fcfe1b4a2c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1241,7 +1241,7 @@ BOOL check_hosts_equiv(char *user) } -static int password_client = -1; +int password_client = -1; static fstring pserver; /**************************************************************************** @@ -1405,7 +1405,7 @@ BOOL server_validate(char *buf) DEBUG(3,("password server %s accepted the password\n",pserver)); -#ifndef KEEP_PASSWORD_SERVER_OPEN +#if !KEEP_PASSWORD_SERVER_OPEN close(password_client); password_client= -1; #endif -- cgit From 04af2822099948279095acc4bc38f5dd4576c7c9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 May 1996 11:25:33 +0000 Subject: move quotas support out of server.c (This used to be commit 1ed5645a5d150de4e5e788c2389aa3cbe70a8faf) --- source3/smbd/quotas.c | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 source3/smbd/quotas.c (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c new file mode 100644 index 0000000000..32c9fc35d3 --- /dev/null +++ b/source3/smbd/quotas.c @@ -0,0 +1,330 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + support for quotas + 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" + + +#ifdef QUOTAS + +#ifdef LINUX +/**************************************************************************** +try to get the disk space from disk quotas (LINUX version) +****************************************************************************/ +/* +If you didn't make the symlink to the quota package, too bad :( +*/ +#include "quota/quotactl.c" +#include "quota/hasquota.c" +static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t euser_id; + struct dqblk D; + struct stat S; + dev_t devno ; + struct mntent *mnt; + FILE *fp; + int found ; + int qcmd, fd ; + char *qfpathname; + + /* find the block device file */ + + if ( stat(path, &S) == -1 ) + return(False) ; + + devno = S.st_dev ; + + fp = setmntent(MOUNTED,"r"); + found = False ; + + while ((mnt = getmntent(fp)) != (struct mntent *) 0) { + if ( stat(mnt->mnt_dir,&S) == -1 ) + continue ; + if (S.st_dev == devno) { + found = True ; + break ; + } + } + endmntent(fp) ; + + if ( ! found ) + return(False) ; + + qcmd = QCMD(Q_GETQUOTA, USRQUOTA); + + if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA)) + return(False) ; + + if (!hasquota(mnt, USRQUOTA, &qfpathname)) + return(False) ; + + euser_id = geteuid(); + seteuid(0); + + if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) { + if ((fd = open(qfpathname, O_RDONLY)) < 0) { + seteuid(euser_id); + return(False); + } + lseek(fd, (long) dqoff(euser_id), L_SET); + switch (read(fd, &D, sizeof(struct dqblk))) { + case 0:/* EOF */ + memset((caddr_t)&D, 0, sizeof(struct dqblk)); + break; + case sizeof(struct dqblk): /* OK */ + break; + default: /* ERROR */ + close(fd); + seteuid(euser_id); + return(False); + } + } + seteuid(euser_id); + *bsize=1024; + + if (D.dqb_bsoftlimit==0) + return(False); + if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit)) + { + *dfree = 0; + *dsize = D.dqb_curblocks; + } + else { + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + } + return (True); +} + +#elif defined(CRAY) +/**************************************************************************** +try to get the disk space from disk quotas (CRAY VERSION) +****************************************************************************/ +static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + struct mntent *mnt; + FILE *fd; + struct stat sbuf; + dev_t devno ; + static dev_t devno_cached = 0 ; + static char name[MNTMAXSTR] ; + struct q_request request ; + struct qf_header header ; + static int quota_default = 0 ; + int found ; + + if ( stat(path,&sbuf) == -1 ) + return(False) ; + + devno = sbuf.st_dev ; + + if ( devno != devno_cached ) { + + devno_cached = devno ; + + if ((fd = setmntent(KMTAB)) == NULL) + return(False) ; + + found = False ; + + while ((mnt = getmntent(fd)) != NULL) { + + if ( stat(mnt->mnt_dir,&sbuf) == -1 ) + continue ; + + if (sbuf.st_dev == devno) { + + found = True ; + break ; + + } + + } + + strcpy(name,mnt->mnt_dir) ; + endmntent(fd) ; + + if ( ! found ) + return(False) ; + } + + request.qf_magic = QF_MAGIC ; + request.qf_entry.id = geteuid() ; + + if (quotactl(name, Q_GETQUOTA, &request) == -1) + return(False) ; + + if ( ! request.user ) + return(False) ; + + if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) { + + if ( ! quota_default ) { + + if ( quotactl(name, Q_GETHEADER, &header) == -1 ) + return(False) ; + else + quota_default = header.user_h.def_fq ; + } + + *dfree = quota_default ; + + }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) { + + *dfree = 0 ; + + }else{ + + *dfree = request.qf_entry.user_q.f_quota ; + + } + + *dsize = request.qf_entry.user_q.f_use ; + + if ( *dfree ) + *dfree -= *dsize ; + + if ( *dfree < 0 ) + *dfree = 0 ; + + *bsize = 4096 ; /* Cray blocksize */ + + return(True) ; + +} + + +#elif defined(SUNOS5) + +#include +#include + +/**************************************************************************** +try to get the disk space from disk quotas (solaris 2 version) +****************************************************************************/ +/* Quota code by Peter Urbanec (amiga@cse.unsw.edu.au) */ +static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t user_id, euser_id; + int r; + struct dqblk D; + struct quotctl command; + int file; + + if((file=open(path, O_RDONLY))<0) return(False); + + euser_id = geteuid(); + user_id = getuid(); + + setuid(0); /* Solaris seems to want to give info only to super-user */ + seteuid(0); + + command.op = Q_GETQUOTA; + command.uid = euser_id; + command.addr = (caddr_t) &D; + + if(ioctl(file, Q_QUOTACTL, &command)<0) + { + close(file); + DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); + return(False); + } + close(file); + + setuid(user_id); /* Restore the original UID status */ + seteuid(euser_id); + + /* Use softlimit to determine disk space. A user exceeding the quota is told + * that there's no space left. Writes might actually work for a bit if the + * hardlimit is set higher than softlimit. Effectively the disk becomes + * made of rubber latex and begins to expand to accommodate the user :-) + */ + + *bsize = 512; + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + if(*dfree < 0) + { + *dfree = 0; + *dsize = D.dqb_curblocks; + } + +DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n", + path,*bsize,*dfree,*dsize)); + + return(True); +} + +#else + +/**************************************************************************** +try to get the disk space from disk quotas - default version +****************************************************************************/ +static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t user_id, euser_id; + int r; + char dev_disk[256]; + struct dqblk D; + struct stat S; + /* find the block device file */ + if ((stat(path, &S)<0) || + (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); + + euser_id = geteuid(); + +#ifdef USE_SETRES + /* for HPUX, real uid must be same as euid to execute quotactl for euid */ + user_id = getuid(); + setresuid(euser_id,-1,-1); +#endif + r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); + #ifdef USE_SETRES + if (setresuid(user_id,-1,-1)) + DEBUG(5,("Unable to reset uid to %d\n", user_id)); + #endif + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = 1024; + if (r) + { + if (errno == EDQUOT) + { + *dfree =0; + *dsize =D.dqb_curblocks; + return (True); + } + else return(False); + } + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curfiles>D.dqb_fsoftlimit)) + { + *dfree = 0; + *dsize = D.dqb_curblocks; + } + else { + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + } + return (True); +} + +#endif +#endif -- cgit From 90d21da1b957a865bb2505bcde804a3cc8713bd8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 May 1996 11:26:58 +0000 Subject: - fix a bug hanlding very log filenames - move quotas support to separate file - send keepalives to password server (This used to be commit f81295c7b4346759ac522ba610438a68204f1858) --- source3/smbd/server.c | 254 ++------------------------------------------------ 1 file changed, 7 insertions(+), 247 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c77a5ca8a7..1d02477073 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -326,7 +326,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) void *cur_dir; char *dname; BOOL mangled; - fstring name2; + pstring name2; mangled = is_mangled(name); @@ -526,251 +526,6 @@ BOOL unix_convert(char *name,int cnum) } - - -#ifdef QUOTAS -#ifdef LINUX -/**************************************************************************** -try to get the disk space from disk quotas (LINUX version) -****************************************************************************/ -/* -If you didn't make the symlink to the quota package, too bad :( -*/ -#include "quota/quotactl.c" -#include "quota/hasquota.c" -static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - uid_t euser_id; - struct dqblk D; - struct stat S; - dev_t devno ; - struct mntent *mnt; - FILE *fp; - int found ; - int qcmd, fd ; - char *qfpathname; - - /* find the block device file */ - - if ( stat(path, &S) == -1 ) - return(False) ; - - devno = S.st_dev ; - - fp = setmntent(MOUNTED,"r"); - found = False ; - - while ((mnt = getmntent(fp)) != (struct mntent *) 0) { - if ( stat(mnt->mnt_dir,&S) == -1 ) - continue ; - if (S.st_dev == devno) { - found = True ; - break ; - } - } - endmntent(fp) ; - - if ( ! found ) - return(False) ; - - qcmd = QCMD(Q_GETQUOTA, USRQUOTA); - - if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA)) - return(False) ; - - if (!hasquota(mnt, USRQUOTA, &qfpathname)) - return(False) ; - - euser_id = geteuid(); - seteuid(0); - - if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) { - if ((fd = open(qfpathname, O_RDONLY)) < 0) { - seteuid(euser_id); - return(False); - } - lseek(fd, (long) dqoff(euser_id), L_SET); - switch (read(fd, &D, sizeof(struct dqblk))) { - case 0:/* EOF */ - memset((caddr_t)&D, 0, sizeof(struct dqblk)); - break; - case sizeof(struct dqblk): /* OK */ - break; - default: /* ERROR */ - close(fd); - seteuid(euser_id); - return(False); - } - } - seteuid(euser_id); - *bsize=1024; - - if (D.dqb_bsoftlimit==0) - return(False); - if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit)) - { - *dfree = 0; - *dsize = D.dqb_curblocks; - } - else { - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - *dsize = D.dqb_bsoftlimit; - } - return (True); -} -#else -#ifndef CRAY -/**************************************************************************** -try to get the disk space from disk quotas -****************************************************************************/ -static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - uid_t user_id, euser_id; - int r; - char dev_disk[256]; - struct dqblk D; - struct stat S; - /* find the block device file */ - if ((stat(path, &S)<0) || - (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); - - euser_id = geteuid(); - -#ifdef USE_SETRES - /* for HPUX, real uid must be same as euid to execute quotactl for euid */ - user_id = getuid(); - setresuid(euser_id,-1,-1); -#endif - r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); - #ifdef USE_SETRES - if (setresuid(user_id,-1,-1)) - DEBUG(5,("Unable to reset uid to %d\n", user_id)); - #endif - /* Use softlimit to determine disk space, except when it has been exceeded */ - *bsize = 1024; - if (r) - { - if (errno == EDQUOT) - { - *dfree =0; - *dsize =D.dqb_curblocks; - return (True); - } - else return(False); - } - /* Use softlimit to determine disk space, except when it has been exceeded */ - if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curfiles>D.dqb_fsoftlimit)) - { - *dfree = 0; - *dsize = D.dqb_curblocks; - } - else { - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - *dsize = D.dqb_bsoftlimit; - } - return (True); -} -#else -/**************************************************************************** -try to get the disk space from disk quotas (CRAY VERSION) -****************************************************************************/ -static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - struct mntent *mnt; - FILE *fd; - struct stat sbuf; - dev_t devno ; - static dev_t devno_cached = 0 ; - static char name[MNTMAXSTR] ; - struct q_request request ; - struct qf_header header ; - static int quota_default = 0 ; - int found ; - - if ( stat(path,&sbuf) == -1 ) - return(False) ; - - devno = sbuf.st_dev ; - - if ( devno != devno_cached ) { - - devno_cached = devno ; - - if ((fd = setmntent(KMTAB)) == NULL) - return(False) ; - - found = False ; - - while ((mnt = getmntent(fd)) != NULL) { - - if ( stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - - if (sbuf.st_dev == devno) { - - found = True ; - break ; - - } - - } - - strcpy(name,mnt->mnt_dir) ; - endmntent(fd) ; - - if ( ! found ) - return(False) ; - } - - request.qf_magic = QF_MAGIC ; - request.qf_entry.id = geteuid() ; - - if (quotactl(name, Q_GETQUOTA, &request) == -1) - return(False) ; - - if ( ! request.user ) - return(False) ; - - if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) { - - if ( ! quota_default ) { - - if ( quotactl(name, Q_GETHEADER, &header) == -1 ) - return(False) ; - else - quota_default = header.user_h.def_fq ; - } - - *dfree = quota_default ; - - }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) { - - *dfree = 0 ; - - }else{ - - *dfree = request.qf_entry.user_q.f_quota ; - - } - - *dsize = request.qf_entry.user_q.f_use ; - - if ( *dfree ) - *dfree -= *dsize ; - - if ( *dfree < 0 ) - *dfree = 0 ; - - *bsize = 4096 ; /* Cray blocksize */ - - return(True) ; - -} -#endif /* CRAY */ -#endif /* LINUX */ -#endif /* QUOTAS */ - - /**************************************************************************** normalise for DOS usage ****************************************************************************/ @@ -3995,10 +3750,15 @@ void process(void ) } if (keepalive && (counter-last_keepalive)>keepalive) { + extern int password_client; if (!send_keepalive(Client)) { DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); return; - } + } + /* also send a keepalive to the password server if its still + connected */ + if (password_client != -1) + send_keepalive(password_client); last_keepalive = counter; } -- cgit From 2ef2593c92573d8cf042b0163cb9526335d661ff Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 May 1996 11:35:09 +0000 Subject: made dptr_num signed to handle -1 from OS/2 (This used to be commit d2c5ab135ca7ee6366f5f8733440318a724a4378) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9d02123cf8..f158aae357 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1444,7 +1444,7 @@ int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize) { int cnum; int outsize = 0; - uint16 dptr_num=SVAL(inbuf,smb_vwv0); + int16 dptr_num=SSVAL(inbuf,smb_vwv0); cnum = SVAL(inbuf,smb_tid); -- cgit From 1956d1349441d8d5694df6dda67528bec4b1c10e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 May 1996 07:47:47 +0000 Subject: cleanups to make thinsg compile cleanly (This used to be commit 39fbeb04ae938594c380d97ebe67c012fa0dd51a) --- source3/smbd/password.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fcfe1b4a2c..6031daf5f1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -52,7 +52,7 @@ void generate_next_challenge(char *challenge) v2 = (counter++) * getpid() + tval.tv_usec; SIVAL(challenge,0,v1); SIVAL(challenge,4,v2); - E1(challenge,"SAMBA",saved_challenge); + E1(challenge,"SAMBA",(char *)saved_challenge); memcpy(challenge,saved_challenge,8); challenge_sent = True; } @@ -684,7 +684,9 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL if(smb_pass->smb_nt_passwd != NULL) { DEBUG(4,("Checking NT MD4 password\n")); - if(smb_password_check(password, smb_pass->smb_nt_passwd, challenge)) + if(smb_password_check(password, + smb_pass->smb_nt_passwd, + (char *)challenge)) { update_protected_database(user,True); return(True); @@ -696,11 +698,12 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL /* Try against the lanman password */ - if(smb_password_check(password, smb_pass->smb_passwd, challenge)) - { - update_protected_database(user,True); - return(True); - } + if (smb_password_check(password, + smb_pass->smb_passwd, + (char *)challenge)) { + update_protected_database(user,True); + return(True); + } DEBUG(3,("Error smb_password_check failed\n")); } -- cgit From debd5b6ae9e4b308398d1d0a305ed4357ff6e1a5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 May 1996 07:49:50 +0000 Subject: fixed a typo (This used to be commit 654c242045a70b600488a765eb46b6f79e484de9) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f158aae357..045d461184 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1444,7 +1444,7 @@ int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize) { int cnum; int outsize = 0; - int16 dptr_num=SSVAL(inbuf,smb_vwv0); + int16 dptr_num=SVALS(inbuf,smb_vwv0); cnum = SVAL(inbuf,smb_tid); -- cgit From ec520018094a441017a539136e8f561900dd1318 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 May 1996 07:54:01 +0000 Subject: handle errors from receive_smb better, and print error string (This used to be commit 7814eca4b22f909e75c3321d9a157c2228198c5c) --- source3/smbd/server.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1d02477073..00f8c9e0fd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2394,7 +2394,8 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de if (ChDir(pcon->connectpath) != 0) { - DEBUG(0,("Can't change directory to %s\n",pcon->connectpath)); + DEBUG(0,("Can't change directory to %s (%s)\n", + pcon->connectpath,strerror(errno))); pcon->open = False; unbecome_user(); if (!IS_IPC(cnum)) { @@ -3721,8 +3722,8 @@ void process(void ) extern int keepalive; /* check for socket failure */ - if (errno == EBADF) { - DEBUG(3,("%s Bad file descriptor - exiting\n",timestring())); + if (errno) { + DEBUG(3,("receive_smb error (%s) exiting\n",strerror(errno))); return; } -- cgit From 1b87ef2440898e73f438f8816c8c3da5af6e7d66 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 May 1996 03:16:17 +0000 Subject: - added an entry on WinDD to samba.faq - added a sample smb.conf from Thoralf.Freitag@remserv.rz.fhtw-berlin.de - print the errno when you get a can't change directory error - added installscripts.sh from James_K._Foote.PARC@xerox.com (This used to be commit 48c6b86d4c580d62ef46132dc04ce2b1d14e21e8) --- source3/smbd/server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 00f8c9e0fd..5ef92777b2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2626,6 +2626,7 @@ int reply_nt1(char *outbuf) int capabilities=0x300; /* has dual names + lock_and_read */ int secword=0; BOOL doencrypt = SMBENCRYPT(); + time_t t = time(NULL); if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; @@ -2660,8 +2661,8 @@ int reply_nt1(char *outbuf) SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */ SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */ SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ - put_long_date(outbuf+smb_vwv11+1,time(NULL)); - SSVALS(outbuf,smb_vwv15+1,TimeDiff(time(NULL))/60); + put_long_date(outbuf+smb_vwv11+1,t); + SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); return (smb_len(outbuf)+4); } -- cgit From d8cf90d37f751f0614609bdf67aab875533b97de Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 May 1996 06:09:42 +0000 Subject: comment out the code that tries to handle the NT bug where the 2nd passlen is wrong. The fix is worse than the problem :-) (This used to be commit 51e22c931078e0b612dbc9e20dc143c3aebf7eb5) --- source3/smbd/reply.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b7b51775bb..b5fa86a8d7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -334,11 +334,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) StrnCpy(smb_apasswd,p + passlen1,smb_apasslen); } } +#if NT_WORKAROUND if (passlen2 == 1) { /* apparently NT sometimes sets passlen2 to 1 when it means 0. This tries to work around that problem */ passlen2 = 0; } +#endif p += passlen1 + passlen2; strcpy(user,p); p = skip_string(p,1); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", -- cgit From 58734631b4233ec08b7a262587e400792f31f185 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 May 1996 15:13:29 +0000 Subject: Lots of changes! - add faq info on NT printer handling - add "delete readonly" option to help rcs users - add stuff to man pages on new printer options - add "proxy name resolution" option - add "command string" -c option to smbclient (thanks Ken) - split time functions into time.c - rearrange the quotas stuff a bit and fix some bugs - complete rehash of the time handling code thanks to Paul Eggert - fix nmblookup output a bit - add plp print queue parsing from Bertrand Wallrich (This used to be commit 635b56f19c817527c52e9bbde31faa6a8a47777b) --- source3/smbd/ipc.c | 8 +++---- source3/smbd/password.c | 6 ++---- source3/smbd/quotas.c | 55 +++++++++++++++++++++++++++++++++++++------------ source3/smbd/reply.c | 4 +++- source3/smbd/server.c | 2 ++ 5 files changed, 53 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 34210f2db7..3b2c55dc46 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -467,7 +467,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, time_t t = queue->time; /* the client expects localtime */ - t += GMT_TO_LOCAL*TimeDiff(t); + t -= TimeDiff(t); PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */ if (uLevel == 1) { @@ -479,7 +479,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, PACKI(desc,"W",n+1); /* uPosition */ PACKI(desc,"W",queue->status); /* fsStatus */ PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",queue->time); /* ulSubmitted */ + PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z",queue->file); /* pszComment */ } @@ -488,7 +488,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, PACKS(desc,"z",queue->user); /* pszUserName */ PACKI(desc,"W",n+1); /* uPosition */ PACKI(desc,"W",queue->status); /* fsStatus */ - PACKI(desc,"D",queue->time); /* ulSubmitted */ + PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z","Samba"); /* pszComment */ PACKS(desc,"z",queue->file); /* pszDocument */ @@ -1289,7 +1289,7 @@ static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data, /* the client expects to get localtime, not GMT, in this bit (I think, this needs testing) */ - t = LocalTime(&unixdate,GMT_TO_LOCAL); + t = LocalTime(&unixdate); SIVAL(p,4,0); /* msecs ? */ CVAL(p,8) = t->tm_hour; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6031daf5f1..b8111fc739 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -287,15 +287,13 @@ static void update_protected_database( char *user, BOOL result) #ifdef OSF1_ENH_SEC struct pr_passwd *mypasswd; time_t starttime; - long tz; mypasswd = getprpwnam (user); starttime = time (NULL); - tz = mktime ( localtime ( &starttime ) ); if (result) { - mypasswd->ufld.fd_slogin = tz; + mypasswd->ufld.fd_slogin = starttime; mypasswd->ufld.fd_nlogins = 0; putprpwnam(user,mypasswd); @@ -304,7 +302,7 @@ static void update_protected_database( char *user, BOOL result) } else { - mypasswd->ufld.fd_ulogin = tz; + mypasswd->ufld.fd_ulogin = starttime; mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1; if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries ) { diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 32c9fc35d3..81f2dcaab5 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -1,3 +1,4 @@ +#ifdef QUOTAS /* Unix SMB/Netbios implementation. Version 1.9. @@ -19,12 +20,28 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "includes.h" +/* + * This is one of the most system dependent parts of Samba, and its + * done a litle differently. Each system has its own way of doing + * things :-( + */ + +#include "includes.h" -#ifdef QUOTAS #ifdef LINUX + +#ifdef __KERNEL__ +# undef __KERNEL__ +# include +# define __KERNEL__ +#else +# include +#endif + +#include + /**************************************************************************** try to get the disk space from disk quotas (LINUX version) ****************************************************************************/ @@ -115,6 +132,10 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #elif defined(CRAY) + +#include +#include + /**************************************************************************** try to get the disk space from disk quotas (CRAY VERSION) ****************************************************************************/ @@ -214,6 +235,7 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #elif defined(SUNOS5) +#include #include #include @@ -228,30 +250,33 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) struct dqblk D; struct quotctl command; int file; + int ret; if((file=open(path, O_RDONLY))<0) return(False); euser_id = geteuid(); user_id = getuid(); - setuid(0); /* Solaris seems to want to give info only to super-user */ - seteuid(0); - command.op = Q_GETQUOTA; command.uid = euser_id; command.addr = (caddr_t) &D; - if(ioctl(file, Q_QUOTACTL, &command)<0) - { - close(file); - DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); - return(False); - } - close(file); + setuid(0); /* Solaris seems to want to give info only to super-user */ + seteuid(0); + + ret = ioctl(file, Q_QUOTACTL, &command); setuid(user_id); /* Restore the original UID status */ seteuid(euser_id); + if (ret < 0) { + close(file); + DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); + return(False); + } + close(file); + + /* Use softlimit to determine disk space. A user exceeding the quota is told * that there's no space left. Writes might actually work for a bit if the * hardlimit is set higher than softlimit. Effectively the disk becomes @@ -275,6 +300,9 @@ DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n" #else +#include +#include + /**************************************************************************** try to get the disk space from disk quotas - default version ****************************************************************************/ @@ -327,4 +355,5 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #endif -#endif +#endif /* QUOTAS */ + diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b5fa86a8d7..68376baaf3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1181,7 +1181,9 @@ static BOOL can_delete(char *fname,int cnum,int dirtype) if (sys_lstat(fname,&sbuf) != 0) return(False); fmode = dos_mode(cnum,fname,&sbuf); if (fmode & aDIR) return(False); - if (fmode & aRONLY) return(False); + if (!lp_delete_readonly(SNUM(cnum))) { + if (fmode & aRONLY) return(False); + } if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return(False); if (!check_file_sharing(cnum,fname)) return(False); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5ef92777b2..3140d3ff84 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2456,6 +2456,8 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de int find_free_file(void ) { int i; + /* we start at 1 here for an obscure reason I can't now remember, + but I think is important :-) */ for (i=1;i Date: Sat, 1 Jun 1996 15:25:30 +0000 Subject: - 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) --- source3/smbd/ipc.c | 217 ++++++++++++++++++------------ source3/smbd/server.c | 287 +-------------------------------------- source3/smbd/smbrun.c | 71 +++++----- source3/smbd/uid.c | 364 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 536 insertions(+), 403 deletions(-) create mode 100644 source3/smbd/uid.c (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3b2c55dc46..25979d72f5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -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;iname, 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 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;iuid) 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 { diff --git a/source3/smbd/smbrun.c b/source3/smbd/smbrun.c index df12ae1f85..6c9ba52b8b 100644 --- a/source3/smbd/smbrun.c +++ b/source3/smbd/smbrun.c @@ -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/source3/smbd/uid.c b/source3/smbd/uid.c new file mode 100644 index 0000000000..f287c733c4 --- /dev/null +++ b/source3/smbd/uid.c @@ -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;iuid) 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); +} + + -- cgit From a2c1623827406667a4f2f058c24f1d971f6627f8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Jun 1996 06:42:03 +0000 Subject: 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 0d8dcfa13c527ec2c8aca39ba49c09e4e694b26c) --- source3/smbd/password.c | 2 +- source3/smbd/reply.c | 8 ++++---- source3/smbd/server.c | 29 +++++++++----------------- source3/smbd/smbrun.c | 2 +- source3/smbd/trans2.c | 20 +++++++++--------- source3/smbd/uid.c | 54 +++++++++++++++++++++++-------------------------- source3/smbd/vt_mode.c | 26 +++++++++--------------- 7 files changed, 60 insertions(+), 81 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b8111fc739..31d9191271 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1258,7 +1258,7 @@ BOOL server_cryptkey(char *buf) fstring desthost; struct in_addr dest_ip; extern struct in_addr myip; - int port = 139; + int port = SMB_PORT; BOOL ret; if (password_client >= 0) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 68376baaf3..4472e120aa 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1928,11 +1928,11 @@ int reply_close(char *inbuf,char *outbuf) mtime = make_unix_date3(inbuf+smb_vwv1); - close_file(fnum); - /* try and set the date */ set_filetime(Files[fnum].name,mtime); + close_file(fnum); + /* We have a cached error */ if(eclass || err) return(ERROR(eclass,err)); @@ -1976,10 +1976,10 @@ int reply_writeclose(char *inbuf,char *outbuf) nwritten = write_file(fnum,data,numtowrite); - close_file(fnum); - set_filetime(Files[fnum].name,mtime); + close_file(fnum); + DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", timestring(),fnum,cnum,numtowrite,nwritten, Connections[cnum].num_files_open)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b8e3cba61c..a8e1dad838 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -139,31 +139,20 @@ mode_t unix_mode(int cnum,int dosmode) int dos_mode(int cnum,char *path,struct stat *sbuf) { int result = 0; + extern struct current_user current_user; -#if OLD_DOS_MODE - if (!CAN_WRITE(cnum) || !((sbuf->st_mode & S_IWOTH) || - Connections[cnum].admin_user || - ((sbuf->st_mode & S_IWUSR) && - Connections[cnum].uid==sbuf->st_uid) || - ((sbuf->st_mode & S_IWGRP) && - in_group(sbuf->st_gid,Connections[cnum].gid, - Connections[cnum].ngroups, - Connections[cnum].igroups)))) - result |= aRONLY; -#else if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) { if (!((sbuf->st_mode & S_IWOTH) || Connections[cnum].admin_user || - ((sbuf->st_mode & S_IWUSR) && Connections[cnum].uid==sbuf->st_uid) || + ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) || ((sbuf->st_mode & S_IWGRP) && - in_group(sbuf->st_gid,Connections[cnum].gid, - Connections[cnum].ngroups,Connections[cnum].igroups)))) + in_group(sbuf->st_gid,current_user.gid, + current_user.ngroups,current_user.igroups)))) result |= aRONLY; } else { if ((sbuf->st_mode & S_IWUSR) == 0) result |= aRONLY; } -#endif if ((sbuf->st_mode & S_IXUSR) != 0) result |= aARCH; @@ -3383,7 +3372,7 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) /**************************************************************************** process commands from the client ****************************************************************************/ -void process(void ) +static void process(void) { static int trans_num = 0; int nread; @@ -3407,7 +3396,7 @@ void process(void ) ip = *interpret_addr2("localhost"); if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1"); *OutBuffer = 0; - send_one_packet(OutBuffer,1,ip,137,SOCK_DGRAM); + send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM); } #endif @@ -3592,7 +3581,7 @@ static void init_structs(void ) /**************************************************************************** usage on the program ****************************************************************************/ -void usage(char *pname) +static void usage(char *pname) { DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); @@ -3612,12 +3601,12 @@ void usage(char *pname) /**************************************************************************** main program ****************************************************************************/ -int main(int argc,char *argv[]) + int main(int argc,char *argv[]) { extern BOOL append_log; /* shall I run as a daemon */ BOOL is_daemon = False; - int port = 139; + int port = SMB_PORT; int opt; extern char *optarg; diff --git a/source3/smbd/smbrun.c b/source3/smbd/smbrun.c index 6c9ba52b8b..dcd5379bc1 100644 --- a/source3/smbd/smbrun.c +++ b/source3/smbd/smbrun.c @@ -46,7 +46,7 @@ as non root from a program which is switching between root and non-root It takes 3 arguments as uid,gid,command and runs command after becoming a non-root user */ -int main(int argc,char *argv[]) + int main(int argc,char *argv[]) { int uid,gid; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 045d461184..36dd5eba3e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -264,7 +264,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l int mode=0; uint32 size=0,len; uint32 mdate=0, adate=0, cdate=0; - char *name_ptr; + char *nameptr; BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") || strequal(Connections[cnum].dirpath,".") || strequal(Connections[cnum].dirpath,"/")); @@ -349,7 +349,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l #endif p = pdata; - name_ptr = p; + nameptr = p; name_map_mangle(fname,False,SNUM(cnum)); @@ -368,7 +368,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SSVAL(p,l1_attrFile,mode); SCVAL(p,l1_cchName,strlen(fname)); strcpy(p + l1_achName, fname); - name_ptr = p + l1_achName; + nameptr = p + l1_achName; p += l1_achName + strlen(fname) + 1; break; @@ -387,7 +387,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,l2_cbList,0); /* No extended attributes */ SCVAL(p,l2_cchName,strlen(fname)); strcpy(p + l2_achName, fname); - name_ptr = p + l2_achName; + nameptr = p + l2_achName; p += l2_achName + strlen(fname) + 1; break; @@ -402,7 +402,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,26,4); CVAL(p,30) = strlen(fname); strcpy(p+31, fname); - name_ptr = p+31; + nameptr = p+31; p += 31 + strlen(fname) + 1; break; @@ -420,7 +420,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SSVAL(p,24,mode); CVAL(p,32) = strlen(fname); strcpy(p + 33, fname); - name_ptr = p+33; + nameptr = p+33; p += 33 + strlen(fname) + 1; break; @@ -452,7 +452,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l strupper(p+2); SSVAL(p,0,strlen(p+2)); p += 2 + 24; - /* name_ptr = p; */ + /* nameptr = p; */ strcpy(p,fname); p += strlen(p); p = pdata + len; break; @@ -517,7 +517,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l } /* Setup the last_filename pointer, as an offset from base_data */ - *last_name_off = PTR_DIFF(name_ptr,base_data); + *last_name_off = PTR_DIFF(nameptr,base_data); /* Advance the data pointer to the next slot */ *ppdata = p; return(found); @@ -1004,7 +1004,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, if (tran_call == TRANSACT2_QFILEINFO) { - int16 fnum = SVAL(params,0); + int16 fnum = SVALS(params,0); info_level = SVAL(params,2); CHECK_FNUM(fnum,cnum); @@ -1198,7 +1198,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, return(ERROR(ERRSRV,ERRaccess)); if (tran_call == TRANSACT2_SETFILEINFO) { - int16 fnum = SVAL(params,0); + int16 fnum = SVALS(params,0); info_level = SVAL(params,2); CHECK_FNUM(fnum,cnum); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index f287c733c4..625303350a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -30,23 +30,18 @@ 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; +/* what user is current? */ +struct current_user current_user; /**************************************************************************** initialise the uid routines ****************************************************************************/ void init_uid(void) { - initial_uid = current_uid = geteuid(); - initial_gid = current_gid = getegid(); + initial_uid = current_user.uid = geteuid(); + initial_gid = current_user.gid = getegid(); if (initial_gid != 0 && initial_uid == 0) { @@ -61,7 +56,7 @@ void init_uid(void) initial_uid = geteuid(); initial_gid = getegid(); - last_user.cnum = -1; + current_user.cnum = -1; GetWd(OriginalDir); } @@ -111,7 +106,7 @@ static BOOL become_uid(int uid) return(False); } - current_uid = uid; + current_user.uid = uid; return(True); } @@ -140,7 +135,7 @@ static BOOL become_gid(int gid) return(False); } - current_gid = gid; + current_user.gid = gid; return(True); } @@ -174,7 +169,7 @@ BOOL become_guest(void) if (!ret) DEBUG(1,("Failed to become guest. Invalid guest account?\n")); - last_user.cnum = -2; + current_user.cnum = -2; return(ret); } @@ -208,10 +203,9 @@ BOOL become_user(int cnum, int uid) int new_umask; user_struct *vuser; int snum,gid; - int ngroups; - gid_t *groups; + int id = uid; - if (last_user.cnum == cnum && last_user.uid == uid) { + if (current_user.cnum == cnum && current_user.id == id) { DEBUG(4,("Skipping become_user - already user\n")); return(True); } @@ -231,8 +225,9 @@ BOOL become_user(int cnum, int uid) !check_user_ok(cnum,vuser,snum)) { uid = Connections[cnum].uid; gid = Connections[cnum].gid; - groups = Connections[cnum].groups; - ngroups = Connections[cnum].ngroups; + 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)); @@ -243,8 +238,9 @@ BOOL become_user(int cnum, int uid) gid = vuser->gid; else gid = Connections[cnum].gid; - groups = vuser->user_groups; - ngroups = vuser->user_ngroups; + current_user.groups = vuser->user_groups; + current_user.igroups = vuser->user_igroups; + current_user.ngroups = vuser->user_ngroups; } if (initial_uid == 0) @@ -254,8 +250,8 @@ BOOL become_user(int cnum, int uid) #ifndef NO_SETGROUPS if (!IS_IPC(cnum)) { /* groups stuff added by ih/wreu */ - if (ngroups > 0) - if (setgroups(ngroups,groups)<0) + if (current_user.ngroups > 0) + if (setgroups(current_user.ngroups,current_user.groups)<0) DEBUG(0,("setgroups call failed!\n")); } #endif @@ -267,8 +263,8 @@ BOOL become_user(int cnum, int uid) new_umask = 0777 & ~CREATE_MODE(cnum); old_umask = umask(new_umask); - last_user.cnum = cnum; - last_user.uid = uid; + 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)); @@ -281,7 +277,7 @@ BOOL become_user(int cnum, int uid) ****************************************************************************/ BOOL unbecome_user(void ) { - if (last_user.cnum == -1) + if (current_user.cnum == -1) return(False); ChDir(OriginalDir); @@ -320,8 +316,8 @@ BOOL unbecome_user(void ) } #endif - current_uid = initial_uid; - current_gid = initial_gid; + current_user.uid = initial_uid; + current_user.gid = initial_gid; if (ChDir(OriginalDir) != 0) DEBUG(0,("%s chdir(%s) failed in unbecome_user\n", @@ -330,7 +326,7 @@ BOOL unbecome_user(void ) DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); - last_user.cnum = -1; + current_user.cnum = -1; return(True); } @@ -352,7 +348,7 @@ int smbrun(char *cmd,char *outfile) } sprintf(syscmd,"%s %d %d \"(%s 2>&1) > %s\"", - path,current_uid,current_gid,cmd, + path,current_user.uid,current_user.gid,cmd, outfile?outfile:"/dev/null"); DEBUG(5,("smbrun - running %s ",syscmd)); diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c index 83b62a38ac..0a4d50c217 100644 --- a/source3/smbd/vt_mode.c +++ b/source3/smbd/vt_mode.c @@ -60,8 +60,7 @@ int ms_type = MS_NONE, /* VT_Check: test incoming packet for "vtp" or "iVT1\0" */ -int VT_Check(buffer) -char *buffer; +int VT_Check(char *buffer) { DEBUG(3,("Checking packet: <%10s...>\n", buffer+4)); if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5)) @@ -74,7 +73,7 @@ char *buffer; /* VT_Start_utmp: prepare /etc/utmp for /bin/login */ -VT_Start_utmp() +int VT_Start_utmp(void) { struct utmp u, *v; char *tt; @@ -111,7 +110,7 @@ VT_Start_utmp() /* VT_Stop_utmp: prepare /etc/utmp for other processes */ -VT_Stop_utmp() +int VT_Stop_utmp(void) { struct utmp u, *v; @@ -138,7 +137,7 @@ VT_Stop_utmp() /* VT_AtExit: Things to do when the program exits */ -void VT_AtExit() +void VT_AtExit(void) { if(VT_ChildPID > 0) { kill(VT_ChildPID, SIGHUP); @@ -152,8 +151,7 @@ void VT_AtExit() /* VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died */ -void VT_SigCLD(sig) -int sig; +void VT_SigCLD(int sig) { if(wait(NULL) == VT_ChildPID) VT_ChildDied = True; @@ -165,8 +163,7 @@ int sig; /* VT_SigEXIT: signalhandler for signals that cause the process to exit */ -void VT_SigEXIT(sig) -int sig; +void VT_SigEXIT(int sig) { VT_AtExit(); @@ -177,7 +174,7 @@ int sig; /* VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK */ -int VT_Start() +int VT_Start(void) { char OutBuf [64], *X, *Y; @@ -330,8 +327,7 @@ int VT_Start() /* VT_Output: transport data from socket to pty */ -int VT_Output(Buffer) -char *Buffer; +int VT_Output(char *Buffer) { int i, len, nb; @@ -350,9 +346,7 @@ char *Buffer; /* VT_Input: transport data from pty to socket */ -int VT_Input(Buffer, Size) -char *Buffer; -int Size; +int VT_Input(char *Buffer,int Size) { int len; @@ -372,7 +366,7 @@ int Size; /* VT_Process: main loop while in vt-mode */ -void VT_Process() +void VT_Process(void) { static int trans_num = 0; extern int Client; -- cgit From 5607ff396c375976e440f9c955a313ddd58e3bbd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Jun 1996 06:53:43 +0000 Subject: add dummy quotas fn fix typo in reply to backup lists (This used to be commit bc4a2994377ab078d3d1a900f79fda9dfe4d0e6a) --- source3/smbd/quotas.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 81f2dcaab5..d5be15264e 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -355,5 +355,9 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #endif + +#else +/* this keeps fussy compilers happy */ + void quotas_dummy(void) {} #endif /* QUOTAS */ -- cgit From e38afbf38210b8cf30c5b13dc5ea96a6dda433f7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Jun 1996 15:16:09 +0000 Subject: - changed some debug levels in clientutil.c - added dir_check_ftype() to clean up the file type checking a bit - added check for libc version >= 5 for setfsuid() for Linux - moved the AM_MASTER() and related macros to nameserv.h - added proper defines for the various netbios announce types - don't call the announce_backup() code, as I'm pretty sure its wrong it sent ANN_GetBackupListReq packets as broadcasts, they are supposed to be used only by clients to the master browser to find a list of available backup servers to remote a netserverenum to, I don't think nmbd should ever send one. - fixed a bug in the browse list writing - minor debug cleanups - put in the code to discard our own broadcasts (it won't work for multi-homed hosts though) - changed ELECTION_VERSION to 1 so we can be beaten by a NT 3.51 server by lowering the os level. - only do sync_browse_lists() if we are the master browser, otherwise we'll cause network overload - don't call tell_become_backup() as it appears to be badly broken, it should only be used when the machine being told has its MAINTAIN_LIST to to auto. Not calling it does no great harm anyway - fix a nasty bug where becomebackup was confused with reset browser! - make setbuffer() not get caught by the auto protototypes (This used to be commit cfbad9b08242962f41595273de08a7293fe432b1) --- source3/smbd/dir.c | 20 +++++++++++++++----- source3/smbd/trans2.c | 10 +++++----- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 214b28dad0..32f2eb5e7d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -411,6 +411,16 @@ void *dptr_fetch_lanman2(char *params,int dptr_num) return(p); } +/**************************************************************************** +check a filetype for being valid +****************************************************************************/ +BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype) +{ + if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) + return False; + return True; +} + /**************************************************************************** get a directory entry ****************************************************************************/ @@ -474,11 +484,11 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo *mode = dos_mode(cnum,pathreal,&sbuf); - if (((*mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) - { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); - continue; - } + if (!dir_check_ftype(cnum,*mode,&sbuf,dirtype)) { + DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); + continue; + } + *size = sbuf.st_size; *date = sbuf.st_mtime; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 36dd5eba3e..60e9ae2b29 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -325,11 +325,11 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l mode = dos_mode(cnum,pathreal,&sbuf); - if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) - { - DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); - continue; - } + if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) { + DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); + continue; + } + size = sbuf.st_size; mdate = sbuf.st_mtime; adate = sbuf.st_atime; -- cgit From f6655e8a385181bdbff0e7ac7f6a8dcbce60360b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Jun 1996 15:44:24 +0000 Subject: - remove some incorrect prototypes from server.c - formatting cleanup in check_master_browser() - removed unused code from nameserv.c (This used to be commit ed3ef2e47d5039077993c6addaf44dce2bb1e780) --- source3/smbd/server.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a8e1dad838..206d89423f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -84,11 +84,6 @@ extern struct in_addr myip; static int find_free_connection(int hash); -#ifdef SMB_PASSWD -extern void generate_next_challenge(char *challenge); -extern void set_challenge(char *challenge); -#endif - /* for readability... */ #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0) #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0) -- cgit From b9ae225b28f4707609e6436dad4be7ebdd7e181f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Jun 1996 11:43:09 +0000 Subject: - added interface.c and removed all the references to myip, bcast_ip and Netmask, instead replacing them with calls to routines in interface.c - got rid of old MAXINT define - added code to ensure we only return one entry for each name in the ipc enum routines - added new_only option to add_netbios_entry() to prevent overwriting of important names - minor time handling fixup (This used to be commit 7ed71b73ae745da099072eee36fc2700d1d91407) --- source3/smbd/ipc.c | 63 +++++++++++++++++++++++++++++++++---------------- source3/smbd/password.c | 4 +--- source3/smbd/server.c | 6 ++--- 3 files changed, 47 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 25979d72f5..916b0fb88e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -808,7 +808,8 @@ static BOOL filter_server_info(struct srv_info_struct *server, number of entries ******************************************************************/ static int get_server_info(uint32 servertype, - struct srv_info_struct **servers, BOOL domains, char *domain) + struct srv_info_struct **servers, BOOL domains, + char *domain) { FILE *f; pstring fname; @@ -831,7 +832,7 @@ static int get_server_info(uint32 servertype, /* 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))); + DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains))); while (!feof(f)) { @@ -861,10 +862,16 @@ static int get_server_info(uint32 servertype, strcpy(s->domain,my_workgroup()); } - if (sscanf(stype,"%X",&s->type) != 1) { DEBUG(4,("r:host file ")); ok = False; } + 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)) { DEBUG(4,("r:serv type ")); ok = False; } + if (!(servertype & s->type)) { + DEBUG(4,("r:serv type ")); + ok = False; + } if ((servertype == ~SV_TYPE_DOMAIN_ENUM) && (s->type & SV_TYPE_DOMAIN_ENUM)) @@ -902,6 +909,7 @@ static int get_server_info(uint32 servertype, return(count); } + /******************************************************************* fill in a server info structure ******************************************************************/ @@ -981,6 +989,11 @@ static int fill_srv_info(struct srv_info_struct *service, } +static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) +{ + return(strcmp(s1->name,s2->name)); +} + /**************************************************************************** view list of servers available (or possibly domains). The info is extracted from lists saved by nmbd on the local host @@ -1038,23 +1051,30 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, data_len = fixed_len = string_len = 0; + qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); + { + char *lastname=NULL; + for (i=0;iname, s->type, s->comment, s->domain)); - - if (data_len <= buf_len) + if (filter_server_info(s,domains,domain, + local_request|domain_request)) + { + if (lastname && strequal(lastname,s->name)) continue; + lastname = s->name; + 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; } - } + } } } @@ -1068,18 +1088,21 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, s_len = string_len; { + char *lastname=NULL; int count2 = counted; 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--; + struct srv_info_struct *s = &servers[i]; + if (filter_server_info(s,domains,domain,local_request|domain_request)) + { + if (lastname && strequal(lastname,s->name)) continue; + lastname = s->name; + 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--; + } } - } } *rparam_len = 8; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 31d9191271..c2fe8a4f0d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -43,7 +43,6 @@ Get the next challenge value - no repeats. ********************************************************************/ void generate_next_challenge(char *challenge) { - extern void E1(char *,char *,char *); static int counter = 0; struct timeval tval; int v1,v2; @@ -1257,7 +1256,6 @@ BOOL server_cryptkey(char *buf) int len; fstring desthost; struct in_addr dest_ip; - extern struct in_addr myip; int port = SMB_PORT; BOOL ret; @@ -1285,7 +1283,7 @@ BOOL server_cryptkey(char *buf) continue; } - if (memcmp(&dest_ip,&myip,sizeof(dest_ip)) == 0) { + if (ismyip(dest_ip)) { DEBUG(1,("Password server loop - disabling password server %s\n",p)); continue; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 206d89423f..25464d861c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -79,8 +79,6 @@ int unix_ERR_code=0; extern int extra_time_offset; extern pstring myhostname; -extern struct in_addr myip; - static int find_free_connection(int hash); @@ -1778,6 +1776,8 @@ BOOL reload_services(BOOL test) reopen_logs(); + load_interfaces(); + { extern int Client; if (Client != -1) { @@ -3550,7 +3550,7 @@ static void process(void) static void init_structs(void ) { int i; - get_myname(myhostname,&myip); + get_myname(myhostname,NULL); for (i=0;i Date: Fri, 7 Jun 1996 03:34:22 +0000 Subject: - added predict.c, moving the routines from util.c - added iface_count() and iface_n_ip() routines so its easy to loop over the local interface list - made readsize a normal loadparm global - check for null w in add_domain_entry() - set the deathtime to time()-1 for doamin entries with servertype==0 This allows servers that are shutting down to be removed - add the 0x1c name at startup if we are a WINS server. Previously we added it only if we were a master - loop over interfaces in add_my_domains(), so people don't have to have a lmhosts file to get lp_workgroup() on all interfaces - set add to True for find_workgroupstruct() in nmbsync, and check for null return - remove some ugly "errno = EBADF" bits. they just confused things. (This used to be commit 88b191b48836eeb7937f25b37d0bdd4a2276e5a7) --- source3/smbd/predict.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 source3/smbd/predict.c (limited to 'source3/smbd') diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c new file mode 100644 index 0000000000..8df381b367 --- /dev/null +++ b/source3/smbd/predict.c @@ -0,0 +1,146 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + file read prediction routines + 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; + + +/* variables used by the read prediction module */ +static int rp_fd = -1; +static int rp_offset = 0; +static int rp_length = 0; +static int rp_alloced = 0; +static int rp_predict_fd = -1; +static int rp_predict_offset = 0; +static int rp_predict_length = 0; +static int rp_timeout = 5; +static time_t rp_time = 0; +static char *rp_buffer = NULL; +static BOOL predict_skip=False; +time_t smb_last_time=(time_t)0; + +/**************************************************************************** +handle read prediction on a file +****************************************************************************/ +int read_predict(int fd,int offset,char *buf,char **ptr,int num) +{ + int ret = 0; + int possible = rp_length - (offset - rp_offset); + + possible = MIN(possible,num); + + /* give data if possible */ + if (fd == rp_fd && + offset >= rp_offset && + possible>0 && + smb_last_time-rp_time < rp_timeout) + { + ret = possible; + if (buf) + memcpy(buf,rp_buffer + (offset-rp_offset),possible); + else + *ptr = rp_buffer + (offset-rp_offset); + DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); + } + + if (ret == num) { + predict_skip = True; + } else { + predict_skip = False; + + /* prepare the next prediction */ + rp_predict_fd = fd; + rp_predict_offset = offset + num; + rp_predict_length = num; + } + + if (ret < 0) ret = 0; + + return(ret); +} + +/**************************************************************************** +pre-read some data +****************************************************************************/ +void do_read_prediction() +{ + static int readsize = 0; + + if (predict_skip) return; + + if (rp_predict_fd == -1) + return; + + rp_fd = rp_predict_fd; + rp_offset = rp_predict_offset; + rp_length = 0; + + rp_predict_fd = -1; + + if (readsize == 0) { + readsize = lp_readsize(); + readsize = MAX(readsize,1024); + } + + rp_predict_length = MIN(rp_predict_length,2*readsize); + rp_predict_length = MAX(rp_predict_length,1024); + rp_offset = (rp_offset/1024)*1024; + rp_predict_length = (rp_predict_length/1024)*1024; + + if (rp_predict_length > rp_alloced) + { + rp_buffer = Realloc(rp_buffer,rp_predict_length); + rp_alloced = rp_predict_length; + if (!rp_buffer) + { + DEBUG(0,("can't allocate read-prediction buffer\n")); + rp_predict_fd = -1; + rp_fd = -1; + rp_alloced = 0; + return; + } + } + + if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { + rp_fd = -1; + rp_predict_fd = -1; + return; + } + + rp_length = read(rp_fd,rp_buffer,rp_predict_length); + rp_time = time(NULL); + if (rp_length < 0) + rp_length = 0; +} + +/**************************************************************************** +invalidate read-prediction on a fd +****************************************************************************/ +void invalidate_read_prediction(int fd) +{ + if (rp_fd == fd) + rp_fd = -1; + if (rp_predict_fd == fd) + rp_predict_fd = -1; +} + -- cgit From 4eba893b02334953b0f1bc082dcba6f930f9ff80 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 8 Jun 1996 04:33:37 +0000 Subject: - added comments to byteorder.h explaining how it works. - fixed problem with installscripts if srcdir is not set - fixed ptr init bug in interface.c - changed default lookup type in nmblookup to match nbtstat under NT - new quotas fixes for sunos and solaris (This used to be commit e775576f026d282473256aeac6fef65a85acd98e) --- source3/smbd/quotas.c | 108 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index d5be15264e..4216aa1199 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -29,6 +29,7 @@ #include "includes.h" +extern int DEBUGLEVEL; #ifdef LINUX @@ -50,7 +51,7 @@ If you didn't make the symlink to the quota package, too bad :( */ #include "quota/quotactl.c" #include "quota/hasquota.c" -static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { uid_t euser_id; struct dqblk D; @@ -139,7 +140,7 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) /**************************************************************************** try to get the disk space from disk quotas (CRAY VERSION) ****************************************************************************/ -static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { struct mntent *mnt; FILE *fd; @@ -233,48 +234,119 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } -#elif defined(SUNOS5) +#elif defined(SUNOS5) || defined(SUNOS4) -#include #include +#if defined(SUNOS5) #include +#include +#else /* defined(SUNOS4) */ +#include +#include +#endif /**************************************************************************** try to get the disk space from disk quotas (solaris 2 version) ****************************************************************************/ /* Quota code by Peter Urbanec (amiga@cse.unsw.edu.au) */ -static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { uid_t user_id, euser_id; - int r; + int ret; struct dqblk D; +#if defined(SUNOS5) struct quotctl command; int file; - int ret; - - if((file=open(path, O_RDONLY))<0) return(False); + struct mnttab mnt; + static char name[MNT_LINE_MAX] ; +#else + struct mntent *mnt; + static char name[MNTMAXSTR] ; +#endif + FILE *fd; + struct stat sbuf; + dev_t devno ; + static dev_t devno_cached = 0 ; + int found ; + + if ( stat(path,&sbuf) == -1 ) + return(False) ; + + devno = sbuf.st_dev ; +DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno)); + if ( devno != devno_cached ) { + devno_cached = devno ; +#if defined(SUNOS5) + if ((fd = fopen(MNTTAB, "r")) == NULL) + return(False) ; + + found = False ; + while (getmntent(fd, &mnt) == 0) { + if ( stat(mnt.mnt_mountp,&sbuf) == -1 ) + continue ; +DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt.mnt_mountp,sbuf.st_dev)); + if (sbuf.st_dev == devno) { + found = True ; + break ; + } + } + + strcpy(name,mnt.mnt_mountp) ; + strcat(name,"/quotas") ; + fclose(fd) ; +#else + if ((fd = setmntent(MOUNTED, "r")) == NULL) + return(False) ; + + found = False ; + while ((mnt = getmntent(fd)) != NULL) { + if ( stat(mnt->mnt_dir,&sbuf) == -1 ) + continue ; +DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); + if (sbuf.st_dev == devno) { + found = True ; + break ; + } + } + + strcpy(name,mnt->mnt_fsname) ; + endmntent(fd) ; +#endif + + if ( ! found ) + return(False) ; + } euser_id = geteuid(); user_id = getuid(); - command.op = Q_GETQUOTA; - command.uid = euser_id; - command.addr = (caddr_t) &D; - setuid(0); /* Solaris seems to want to give info only to super-user */ seteuid(0); +#if defined(SUNOS5) +DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); + if((file=open(name, O_RDONLY))<0) { + setuid(user_id); /* Restore the original UID status */ + seteuid(euser_id); + return(False); + } + command.op = Q_GETQUOTA; + command.uid = euser_id; + command.addr = (caddr_t) &D; ret = ioctl(file, Q_QUOTACTL, &command); + close(file); +#else +DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); + ret = quotactl(Q_GETQUOTA, name, euser_id, &D); +#endif setuid(user_id); /* Restore the original UID status */ seteuid(euser_id); if (ret < 0) { - close(file); DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); return(False); } - close(file); /* Use softlimit to determine disk space. A user exceeding the quota is told @@ -283,6 +355,8 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) * made of rubber latex and begins to expand to accommodate the user :-) */ + if (D.dqb_bsoftlimit==0) + return(False); *bsize = 512; *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; *dsize = D.dqb_bsoftlimit; @@ -306,7 +380,7 @@ DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n" /**************************************************************************** try to get the disk space from disk quotas - default version ****************************************************************************/ -static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { uid_t user_id, euser_id; int r; @@ -341,6 +415,8 @@ static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } else return(False); } + if (D.dqb_bsoftlimit==0) + return(False); /* Use softlimit to determine disk space, except when it has been exceeded */ if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curfiles>D.dqb_fsoftlimit)) { -- cgit From 7e3b4a1c0df1434eb3d02f93c736ce065f9898d8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Jun 1996 04:38:24 +0000 Subject: got rid of a lot of redundent header files as we now globally generate prototypes automatically using "make proto". This is much less prone to error than the old method of manually adding prototypes (This used to be commit b551dc98f7cc194a5fc2e67a4ebae7fd67a01bbc) --- source3/smbd/chgpasswd.c | 1 - source3/smbd/dir.c | 1 - source3/smbd/ipc.c | 2 -- source3/smbd/mangle.c | 1 - source3/smbd/message.c | 1 - source3/smbd/password.c | 1 - source3/smbd/predict.c | 1 - source3/smbd/quotas.c | 12 +++++++----- source3/smbd/reply.c | 1 - source3/smbd/server.c | 3 --- source3/smbd/trans2.c | 1 - source3/smbd/uid.c | 1 - 12 files changed, 7 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index dc0514c1ed..809ac4d224 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -27,7 +27,6 @@ */ #include "includes.h" -#include "loadparm.h" extern int DEBUGLEVEL; diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 32f2eb5e7d..55a5983468 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "loadparm.h" extern int DEBUGLEVEL; extern connection_struct Connections[]; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 916b0fb88e..594e067ddd 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -24,8 +24,6 @@ */ #include "includes.h" -#include "loadparm.h" -#include "pcap.h" #ifdef CHECK_TYPES #undef CHECK_TYPES diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index a43e7f6245..cf1ece558c 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "loadparm.h" extern int DEBUGLEVEL; extern int case_default; diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 6a96b4c7a9..b26a6605ed 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -25,7 +25,6 @@ #include "includes.h" -#include "loadparm.h" /* look in server.c for some explanation of these variables */ extern int DEBUGLEVEL; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c2fe8a4f0d..ae548b8266 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "loadparm.h" extern int DEBUGLEVEL; extern int Protocol; diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 8df381b367..7f1692931c 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "loadparm.h" extern int DEBUGLEVEL; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 4216aa1199..6ba20faa6c 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -273,7 +273,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) return(False) ; devno = sbuf.st_dev ; -DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno)); + DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno)); if ( devno != devno_cached ) { devno_cached = devno ; #if defined(SUNOS5) @@ -284,7 +284,8 @@ DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno)); while (getmntent(fd, &mnt) == 0) { if ( stat(mnt.mnt_mountp,&sbuf) == -1 ) continue ; -DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt.mnt_mountp,sbuf.st_dev)); + DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", + mnt.mnt_mountp,sbuf.st_dev)); if (sbuf.st_dev == devno) { found = True ; break ; @@ -302,7 +303,8 @@ DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt.mnt_mountp,sbuf.st_dev)); while ((mnt = getmntent(fd)) != NULL) { if ( stat(mnt->mnt_dir,&sbuf) == -1 ) continue ; -DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); + DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", + mnt->mnt_dir,sbuf.st_dev)); if (sbuf.st_dev == devno) { found = True ; break ; @@ -324,7 +326,7 @@ DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); seteuid(0); #if defined(SUNOS5) -DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); + DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); if((file=open(name, O_RDONLY))<0) { setuid(user_id); /* Restore the original UID status */ seteuid(euser_id); @@ -336,7 +338,7 @@ DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); ret = ioctl(file, Q_QUOTACTL, &command); close(file); #else -DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); + DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4472e120aa..43703982ec 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -25,7 +25,6 @@ #include "includes.h" -#include "loadparm.h" #include "trans2.h" /* look in server.c for some explanation of these variables */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 25464d861c..ecc8e4ce9c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -20,10 +20,7 @@ */ #include "includes.h" -#include "loadparm.h" -#include "pcap.h" #include "trans2.h" -#include "reply.h" pstring servicesf = CONFIGFILE; extern pstring debugf; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 60e9ae2b29..0b113a2ed0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -22,7 +22,6 @@ */ #include "includes.h" -#include "loadparm.h" #include "trans2.h" extern int DEBUGLEVEL; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 625303350a..555cd457e7 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "loadparm.h" extern int DEBUGLEVEL; -- cgit From a521fe8a274c8a043cf77641dd4160fdef803533 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Jun 1996 05:16:19 +0000 Subject: a cleanup of the receive_smb() usage, adding timeouts in some places also added paranoid code in the main process() loop of smbd to detect when smbd is looping uselessly. This should stop the "smbd is chewing lots of cpu" reports (This used to be commit 8e9dce34d50d673cb50531f0c4c7672ce2522cef) --- source3/smbd/ipc.c | 11 +++++------ source3/smbd/password.c | 5 +++-- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 21 +++++++++++++++++++++ source3/smbd/trans2.c | 6 ++---- 5 files changed, 32 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 594e067ddd..415c939bf3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2790,12 +2790,9 @@ int reply_trans(char *inbuf,char *outbuf) while (pscnt < tpscnt || dscnt < tdscnt) { int pcnt,poff,dcnt,doff,pdisp,ddisp; - - receive_smb(Client,inbuf, 0); - show_msg(inbuf); - - /* Ensure this is still a trans packet (sanity check) */ - if(CVAL(inbuf, smb_com) != SMBtrans) + + if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) || + CVAL(inbuf, smb_com) != SMBtrans) { DEBUG(2,("Invalid secondary trans2 packet\n")); if (params) free(params); @@ -2803,6 +2800,8 @@ int reply_trans(char *inbuf,char *outbuf) if (setup) free(setup); return(ERROR(ERRSRV,ERRerror)); } + + show_msg(inbuf); tpscnt = SVAL(inbuf,smb_vwv0); tdscnt = SVAL(inbuf,smb_vwv1); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ae548b8266..a5f597682f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1318,9 +1318,10 @@ BOOL server_cryptkey(char *buf) CVAL(outbuf,0) = 0x81; send_smb(password_client,outbuf); - receive_smb(password_client,inbuf,5000); + - if (CVAL(inbuf,0) != 0x82) { + if (!receive_smb(password_client,inbuf,5000) || + CVAL(inbuf,0) != 0x82) { DEBUG(1,("%s rejected the session\n",pserver)); close(password_client); password_client = -1; return(False); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 43703982ec..4cfa001ec2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1590,7 +1590,7 @@ int reply_writebraw(char *inbuf,char *outbuf) send_smb(Client,outbuf); /* Now read the raw data into the buffer and write it */ - if(read_smb_length(Client,inbuf,0) == -1) { + if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) { exit_server("secondary writebraw failed"); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ecc8e4ce9c..3ececed393 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3445,6 +3445,27 @@ static void process(void) t = time(NULL); + { + /* the following bit of code was added to combat smbd + looping chewing lots of CPU time. It should never + actually be needed, but it seems that some systems + don't set error correctly, which is used to distinguish + a select() timeout from a read error + + we exit if receive_smb() returns false 3 times in one second. + */ + static int error_count=0; + static time_t error_time=0; + if (error_count==0) { + error_time = t; + } else if (error_time != t) { + error_count = 0; + } else if (error_count++ > 2) { + exit_server("looping in process()\n"); + } + } + + /* become root again if waiting */ unbecome_user(); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0b113a2ed0..321dabc72c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1554,10 +1554,8 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) while( num_data_sofar < total_data || num_params_sofar < total_params) { - receive_smb(Client,inbuf, 0); - - /* Ensure this is still a trans2 packet (sanity check) */ - if(CVAL(inbuf, smb_com) != SMBtranss2) + if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) || + CVAL(inbuf, smb_com) != SMBtranss2) { outsize = set_message(outbuf,0,0,True); DEBUG(2,("Invalid secondary trans2 packet\n")); -- cgit From 601281a43bb84f62485929a974c44b69f5c19884 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 1 Jul 1996 18:54:02 +0000 Subject: patch to fix NetServerEnum with multiple workgroup lists kindly supplied. it works for him. needs testing. (This used to be commit 546c49080707c0cbaa6bfc928102d52826867592) --- source3/smbd/ipc.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 415c939bf3..c5c87ea07f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -747,32 +747,45 @@ struct srv_info_struct /******************************************************************* filter out unwanted server info + This function returns True if the entry is wanted. ******************************************************************/ static BOOL filter_server_info(struct srv_info_struct *server, BOOL domains, char *domain, uint32 request) { + /* If no domain was specified, */ if (*domain == 0) { + /* If entry's domain matches this server's domain, + accept this entry. */ if (strequal(lp_workgroup(), server->domain)) { return True; } + + /* If specific domain requested, reject this entry. */ else if (domains) { DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain)); return False; } + + /* If the request was for a list of domain enumerators, + we don't care what domain this entry is in as long + as it is a domain enumerator. */ 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; } - return True; + DEBUG(4,("wrong domain: %8x: %s %s\n",server->type,server->name,server->domain)); + return False; } + + /* If a domain name was specified, */ else { + /* If this entry is in the requested domain, */ if (strequal(domain, server->domain)) { /* @@ -792,11 +805,15 @@ static BOOL filter_server_info(struct srv_info_struct *server, return True; } + + /* If the user didn't pick a domain, + (I don't think this can happen.) */ else if (!domains) { DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain)); return False; } + return True; } } @@ -871,6 +888,7 @@ static int get_server_info(uint32 servertype, ok = False; } + /* If all server, reject DOMIAN_ENUM entries? */ if ((servertype == ~SV_TYPE_DOMAIN_ENUM) && (s->type & SV_TYPE_DOMAIN_ENUM)) { @@ -878,6 +896,8 @@ static int get_server_info(uint32 servertype, ok = False; } + /* If a domain is specified, reject all except the + domain enumerators for the specified domain. */ if (domains && !(domain && *domain && strequal(domain, s->domain))) { if (!(s->type & SV_TYPE_DOMAIN_ENUM)) @@ -1035,11 +1055,13 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, if (strcmp(str1, "WrLehDO") == 0) { domains = False; + DEBUG(4, ("all domains\n")); } else if (strcmp(str1, "WrLehDz") == 0) { domains = True; StrnCpy(domain, p, sizeof(fstring)-1); + DEBUG(4, ("domains must match \"%s\"\n", domains)); } if (lp_browse_list()) @@ -1051,6 +1073,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); + /* A dry run */ { char *lastname=NULL; @@ -1085,6 +1108,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, f_len = fixed_len; s_len = string_len; + /* the real thing */ { char *lastname=NULL; int count2 = counted; -- cgit From 07fcf2df0349d5e1294c92de8d982b62d11175a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Jul 1996 01:58:27 +0000 Subject: - moved the protocol defs in the client to keep sill C compilers happy - added change for cnum range in reply_tdis() (This used to be commit 609c3a5e1e3a8d9ba380a802ab3ecf6f47093846) --- source3/smbd/reply.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4cfa001ec2..13cc8efe5d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2062,6 +2062,11 @@ int reply_tdis(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); uid = SVAL(inbuf,smb_uid); + if (!OPEN_CNUM(cnum)) { + DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum)); + return(ERROR(ERRSRV,ERRinvnid)); + } + Connections[cnum].used = False; close_cnum(cnum,uid); -- cgit From 7812ff08135318e74f5c286fe4773de8d1423969 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 4 Jul 1996 19:19:26 +0000 Subject: modified become_master() to a state-based system. becoming a master is now performed in stages: wait for each NetBIOS name to be successfully registered before proceeding to the next stage. tied implicit name registration and release (broadcast method) to the same piece of code as explicit method (via WINS server). created special_browser_name() function that checks __MSBROWSE__ name: this name is ignored by WINS servers apparently. fixed likely incompatibility between refresh_my_names() and add_my_names(). (netbios entries were unlikely to be refreshed). NOTE: none of these changes have been tested. at all. lkcl (This used to be commit 7719fb06524a66ce5e3f30f3152ddb1e200c97f3) --- source3/smbd/ipc.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c5c87ea07f..415c939bf3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -747,45 +747,32 @@ struct srv_info_struct /******************************************************************* filter out unwanted server info - This function returns True if the entry is wanted. ******************************************************************/ static BOOL filter_server_info(struct srv_info_struct *server, BOOL domains, char *domain, uint32 request) { - /* If no domain was specified, */ if (*domain == 0) { - /* If entry's domain matches this server's domain, - accept this entry. */ if (strequal(lp_workgroup(), server->domain)) { return True; } - - /* If specific domain requested, reject this entry. */ else if (domains) { DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain)); return False; } - - /* If the request was for a list of domain enumerators, - we don't care what domain this entry is in as long - as it is a domain enumerator. */ else if ((request & SV_TYPE_DOMAIN_ENUM) && (server->type & SV_TYPE_DOMAIN_ENUM)) { - return True; + DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain)); + return False; } - DEBUG(4,("wrong domain: %8x: %s %s\n",server->type,server->name,server->domain)); - return False; + return True; } - - /* If a domain name was specified, */ else { - /* If this entry is in the requested domain, */ if (strequal(domain, server->domain)) { /* @@ -805,15 +792,11 @@ static BOOL filter_server_info(struct srv_info_struct *server, return True; } - - /* If the user didn't pick a domain, - (I don't think this can happen.) */ else if (!domains) { DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain)); return False; } - return True; } } @@ -888,7 +871,6 @@ static int get_server_info(uint32 servertype, ok = False; } - /* If all server, reject DOMIAN_ENUM entries? */ if ((servertype == ~SV_TYPE_DOMAIN_ENUM) && (s->type & SV_TYPE_DOMAIN_ENUM)) { @@ -896,8 +878,6 @@ static int get_server_info(uint32 servertype, ok = False; } - /* If a domain is specified, reject all except the - domain enumerators for the specified domain. */ if (domains && !(domain && *domain && strequal(domain, s->domain))) { if (!(s->type & SV_TYPE_DOMAIN_ENUM)) @@ -1055,13 +1035,11 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, if (strcmp(str1, "WrLehDO") == 0) { domains = False; - DEBUG(4, ("all domains\n")); } else if (strcmp(str1, "WrLehDz") == 0) { domains = True; StrnCpy(domain, p, sizeof(fstring)-1); - DEBUG(4, ("domains must match \"%s\"\n", domains)); } if (lp_browse_list()) @@ -1073,7 +1051,6 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); - /* A dry run */ { char *lastname=NULL; @@ -1108,7 +1085,6 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, f_len = fixed_len; s_len = string_len; - /* the real thing */ { char *lastname=NULL; int count2 = counted; -- cgit From e5a0619c2839d45b00446c3af3f30599f3f3c5fa Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 10 Jul 1996 18:48:49 +0000 Subject: updated docs to match code mods from last two or three updates. done some more commenting of code to match docs. sorted some bugs. ipc BOOL domains was uninitialised. lkcl (This used to be commit cb43ce7bc08fa43a6ce49e0937f13afec5dce67b) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 415c939bf3..0f00e3ec21 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1013,7 +1013,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, int counted=0,total=0; int i; fstring domain; - BOOL domains; + BOOL domains = False; BOOL domain_request; BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY; -- cgit From 25b30c08dce8c04b7b98c02ac1de61d7aa76798f Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 17 Jul 1996 18:33:36 +0000 Subject: lots of changes to nmbd lkcl (This used to be commit 45d3b2644733333c657c48a69719fec72881f7df) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0f00e3ec21..415c939bf3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1013,7 +1013,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, int counted=0,total=0; int i; fstring domain; - BOOL domains = False; + BOOL domains; BOOL domain_request; BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY; -- cgit From 2b4b7b4e1adbd2aac9aab89b28df82fc145a6d87 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Jul 1996 15:47:30 +0000 Subject: fix a bug that we've had for a long time where we don't handle EOF properly from clients, and end up looping like mad. At least I _hope_ this is fixed. (This used to be commit a7c7d7afe2ef81f4a74584ce9b71e54442f7e484) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/reply.c | 10 +++++----- source3/smbd/server.c | 44 +++++++++++++++++++++----------------------- 3 files changed, 27 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 809ac4d224..54b49edf13 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -178,7 +178,7 @@ static int expect(int master,char *expected,char *buf) } /* allow 4 seconds for some output to appear */ - m = read_with_timeout(master, buf+n, 1, BUFSIZE-1-n, 4000, True); + m = read_with_timeout(master, buf+n, 1, BUFSIZE-1-n, 4000); if (m < 0) return False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 13cc8efe5d..d463b305c9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1363,7 +1363,7 @@ int reply_readbraw(char *inbuf, char *outbuf) fname,startpos,nread,ret)); #else - ret = read_file(fnum,header+4,startpos,nread,nread,-1,False); + ret = read_file(fnum,header+4,startpos,nread); if (ret < mincount) ret = 0; _smb_setlen(header,ret); @@ -1405,7 +1405,7 @@ int reply_lockread(char *inbuf,char *outbuf) if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode)) return (ERROR(eclass,ecode)); - nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False); + nread = read_file(fnum,data,startpos,numtoread); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1450,7 +1450,7 @@ int reply_read(char *inbuf,char *outbuf) return(ERROR(ERRDOS,ERRlock)); if (numtoread > 0) - nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False); + nread = read_file(fnum,data,startpos,numtoread); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1495,7 +1495,7 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (is_locked(fnum,cnum,smb_maxcnt,smb_offs)) return(ERROR(ERRDOS,ERRlock)); - nread = read_file(fnum,data,smb_offs,smb_maxcnt,smb_maxcnt,-1,False); + nread = read_file(fnum,data,smb_offs,smb_maxcnt); ok = True; if (nread < 0) @@ -2934,7 +2934,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) { int N = MIN(max_per_packet,tcount-total_read); - nread = read_file(fnum,data,startpos,N,N,-1,False); + nread = read_file(fnum,data,startpos,N); if (nread <= 0) nread = 0; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3ececed393..e582ea735a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -48,6 +48,8 @@ extern BOOL short_case_preserve; extern BOOL case_mangle; extern time_t smb_last_time; +extern int smb_read_error; + extern pstring user_socket_options; connection_struct Connections[MAX_CONNECTIONS]; @@ -1263,41 +1265,35 @@ int seek_file(int fnum,int pos) /**************************************************************************** read from a file ****************************************************************************/ -int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact) +int read_file(int fnum,char *data,int pos,int n) { - int ret=0; + int ret=0,readret; if (!Files[fnum].can_write) { - ret = read_predict(Files[fnum].fd, - pos, - data, - NULL, - maxcnt); + ret = read_predict(Files[fnum].fd,pos,data,NULL,n); data += ret; - maxcnt -= ret; - mincnt = MAX(mincnt-ret,0); + n -= ret; pos += ret; } #if USE_MMAP if (Files[fnum].mmap_ptr) { - int num = MIN(maxcnt,Files[fnum].mmap_size-pos); + int num = MIN(n,Files[fnum].mmap_size-pos); if (num > 0) { memcpy(data,Files[fnum].mmap_ptr+pos,num); data += num; pos += num; - maxcnt -= num; - mincnt = MAX(mincnt-num,0); + n -= num; ret += num; } } #endif - if (maxcnt <= 0) + if (n <= 0) return(ret); if (seek_file(fnum,pos) != pos) @@ -1306,13 +1302,10 @@ int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL return(ret); } - if (maxcnt > 0) - ret += read_with_timeout(Files[fnum].fd, - data, - mincnt, - maxcnt, - timeout, - exact); + if (n > 0) { + readret = read(Files[fnum].fd,data,n); + if (readret > 0) ret += readret; + } return(ret); } @@ -3437,9 +3430,14 @@ static void process(void) BOOL allidle = True; extern int keepalive; - /* check for socket failure */ - if (errno) { - DEBUG(3,("receive_smb error (%s) exiting\n",strerror(errno))); + if (smb_read_error == READ_EOF) { + DEBUG(3,("end of file from client\n")); + return; + } + + if (smb_read_error == READ_ERROR) { + DEBUG(3,("receive_smb error (%s) exiting\n", + strerror(errno))); return; } -- cgit From 02b98a8965a60a7c3394835ff01074fc88ffbb89 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 9 Aug 1996 18:05:34 +0000 Subject: applying login updates from jim@oxfordcc.co.uk, sent in by lewis2@server.uwindsor.ca. rest of this patch to follow. bug in interface.c - uninitialised pointer. nmbd has 0x20 as well as 0x0 NetBIOS name when lmhosts entry is added. lkcl (This used to be commit 2b9475cc5fda4b272f19c4f168d3f00363c8042b) --- source3/smbd/ipc.c | 22 ++++++++++++++-------- source3/smbd/server.c | 4 ++-- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 415c939bf3..f4f1807922 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -59,6 +59,9 @@ extern fstring local_machine; #define SNLEN 15 /* service name length */ #define QNLEN 12 /* queue name maximum length */ +#define MAJOR_VERSION 2 +#define MINOR_VERSION 0 + extern int Client; static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) @@ -1406,14 +1409,16 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data, *rdata_len = 0; - SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,0,NERR_badpass); SSVAL(*rparam,2,0); /* converter word */ DEBUG(3,("Set password for <%s>\n",user)); - if (!password_ok(user,pass1,strlen(pass1),NULL,False) || - !chgpasswd(user,pass1,pass2)) - SSVAL(*rparam,0,NERR_badpass); + if (password_ok(user,pass1,strlen(pass1),NULL,False) && + chgpasswd(user,pass1,pass2)) + { + SSVAL(*rparam,0,NERR_Success); + } bzero(pass1,sizeof(fstring)); bzero(pass2,sizeof(fstring)); @@ -1740,9 +1745,10 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, } if (servers) free(servers); - SCVAL(p,0,2); /* version_major */ - SCVAL(p,1,0); /* version_minor */ + SCVAL(p,0,MAJOR_VERSION); + SCVAL(p,1,MINOR_VERSION); SIVAL(p,2,servertype); + if (mdrcnt == struct_len) { SIVAL(p,6,0); } else { @@ -1817,8 +1823,8 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data, p2 = skip_string(p2,1); p += 4; - SCVAL(p,0,2); /* major version?? */ - SCVAL(p,1,1); /* minor version?? */ + SCVAL(p,0,MAJOR_VERSION); + SCVAL(p,1,MINOR_VERSION); p += 2; SIVAL(p,0,PTR_DIFF(p2,*rdata)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e582ea735a..d15ca9336e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3454,11 +3454,11 @@ static void process(void) */ static int error_count=0; static time_t error_time=0; - if (error_count==0) { + if (error_count++==0) { error_time = t; } else if (error_time != t) { error_count = 0; - } else if (error_count++ > 2) { + } else if (error_count > 2) { exit_server("looping in process()\n"); } } -- cgit From 396311075cc808278e6dd8469e3ac7eb7e7498c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Aug 1996 08:57:55 +0000 Subject: - sequent-ptx support from bressler@iftccu.ca.boeing.com (Rick Bressler) - machten support from Trevor Strohman (trev@figment.tenon.com) - added qinfo command to client as part of drag-and-drop printer support for win95 from David Chappell He also added the "printer driver" option - use sigblock() on more systems and use sigsetmask(0) instead of sigunblock() as its more portable. This beats a problem with zombies on heavilily loaded systems. - added internals.doc written by David Chappell into the source tree - get rid of PRINT_COMMAND options from local.h as they are no longer relevent - new kanji code from Fujita - don't set the recursion_available flag on queries in nmbd - fix a potential bug with pointer subtraction in printing.c - got rid of error_count code as the real fix (the EOF problem) is now in (This used to be commit aa6f8b04d125b5bc00f267abf72b800228aabf7d) --- source3/smbd/ipc.c | 16 +++++++-------- source3/smbd/mangle.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 23 +--------------------- 3 files changed, 63 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f4f1807922..0a54936cd0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -190,12 +190,6 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, } } - - -/**************************************************************************** - get a print queue - ****************************************************************************/ - struct pack_desc { char* format; /* formatstring for structure */ char* subformat; /* subformat for structure */ @@ -419,6 +413,11 @@ static void PACKS(struct pack_desc* desc,char *t,char *v) PACK(desc,t,v); } + +/**************************************************************************** + get a print queue + ****************************************************************************/ + static void PackDriverData(struct pack_desc* desc) { char drivdata[4+4+32]; @@ -546,7 +545,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, PACKI(desc,"W",0); /* uUntiltime */ PACKI(desc,"W",5); /* pad1 */ PACKS(desc,"z",""); /* pszSepFile */ - PACKS(desc,"z","lpd"); /* pszPrProc */ + PACKS(desc,"z","WinPrint"); /* pszPrProc */ PACKS(desc,"z",""); /* pszParms */ if (!status || !status->message[0]) { PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */ @@ -557,7 +556,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, } PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - PACKS(desc,"z","NULL"); /* pszDriverName */ + PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ PackDriverData(desc); /* pDriverData */ } if (uLevel == 2 || uLevel == 4) { @@ -594,6 +593,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data, cbBuf = SVAL(p,2); str3 = p + 4; + /* remove any trailing username */ if ((p = strchr(QueueName,'%'))) *p = 0; DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName)); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index cf1ece558c..177a34c975 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -509,9 +509,36 @@ void mangle_name_83(char *s) *p++ = 0; while (*p && extlen < 3) { +#ifdef KANJI + if (is_shift_jis (*p)) + { + if (extlen < 2) + { + extension[extlen++] = p[0]; + extension[extlen++] = p[1]; + } + else + { + extension[extlen++] = base36 (((unsigned char) *p) % 36); + } + p += 2; + } + else if (is_kana (*p)) + { + extension[extlen++] = p[0]; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') + extension[extlen++] = p[0]; + p++; + } +#else if (isdoschar(*p) && *p != '.') extension[extlen++] = *p; p++; +#endif /* KANJI */ } extension[extlen] = 0; } @@ -521,9 +548,36 @@ void mangle_name_83(char *s) while (*p && baselen < 5) { +#ifdef KANJI + if (is_shift_jis (*p)) + { + if (baselen < 4) + { + base[baselen++] = p[0]; + base[baselen++] = p[1]; + } + else + { + base[baselen++] = base36 (((unsigned char) *p) % 36); + } + p += 2; + } + else if (is_kana (*p)) + { + base[baselen++] = p[0]; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') + base[baselen++] = p[0]; + p++; + } +#else if (isdoschar(*p) && *p != '.') base[baselen++] = *p; p++; +#endif /* KANJI */ } base[baselen] = 0; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d15ca9336e..334edf77d0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -230,7 +230,7 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) unixmode |= tmp; } - return(chmod(fname,unixmode)); + return(sys_chmod(fname,unixmode)); } @@ -3443,27 +3443,6 @@ static void process(void) t = time(NULL); - { - /* the following bit of code was added to combat smbd - looping chewing lots of CPU time. It should never - actually be needed, but it seems that some systems - don't set error correctly, which is used to distinguish - a select() timeout from a read error - - we exit if receive_smb() returns false 3 times in one second. - */ - static int error_count=0; - static time_t error_time=0; - if (error_count++==0) { - error_time = t; - } else if (error_time != t) { - error_count = 0; - } else if (error_count > 2) { - exit_server("looping in process()\n"); - } - } - - /* become root again if waiting */ unbecome_user(); -- cgit From cd41e6629e3e401f1a181564ca41798c263802bc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Aug 1996 12:35:28 +0000 Subject: minor cleanups (This used to be commit f1dc2b93179ace36407bbb25c2c34c78087714bd) --- source3/smbd/smbrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/smbrun.c b/source3/smbd/smbrun.c index dcd5379bc1..d547c796e0 100644 --- a/source3/smbd/smbrun.c +++ b/source3/smbd/smbrun.c @@ -41,7 +41,7 @@ static void close_fds(void) /* -This is a wrapper around the system call to allow commands to run correctly +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 3 arguments as uid,gid,command and runs command after -- cgit From 6475a9157464b132decbae2aee0f001a364c0dbe Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Aug 1996 15:01:09 +0000 Subject: fixed an obvious bug that meant that DosPrintQEnum could never work. Now we'll see if it works after this fix ... (This used to be commit 9735d7e8e2978ce17a001d7d5766faf382ff5788) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0a54936cd0..5b3939e98c 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -663,7 +663,7 @@ static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data, DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); - if (prefix_ok(param_format,"WrLeh")) return False; + if (!prefix_ok(param_format,"WrLeh")) return False; if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) return False; queuecnt = 0; -- cgit From 47673b32ed4a907b380b70d5f4f366ba8be301d2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Aug 1996 15:11:34 +0000 Subject: - added FAST_SHARE_MODES code - added some named pipe code from Jim (This used to be commit c94866e9e44ea1eb72da06bc65ef1c032ae8e0c9) --- source3/smbd/ipc.c | 108 ++++++++++++++- source3/smbd/pipes.c | 363 ++++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/reply.c | 18 ++- source3/smbd/server.c | 23 +++- 4 files changed, 500 insertions(+), 12 deletions(-) create mode 100644 source3/smbd/pipes.c (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 5b3939e98c..39b8f3f089 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -59,11 +59,21 @@ extern fstring local_machine; #define SNLEN 15 /* service name length */ #define QNLEN 12 /* queue name maximum length */ -#define MAJOR_VERSION 2 +#define MAJOR_VERSION 4 #define MINOR_VERSION 0 extern int Client; +static BOOL api_Unsupported(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); +static BOOL api_TooSmall(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); + + static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) { pstring buf; @@ -1906,7 +1916,8 @@ static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data, p2 = skip_string(p2,1); } if (uLevel == 11) { /* modelled after NTAS 3.51 reply */ - SSVAL(p,34,USER_PRIV_USER); /* user privilege */ + SSVAL(p,34, + Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,36,0); /* auth flags */ SIVALS(p,40,-1); /* password age */ SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */ @@ -1941,7 +1952,8 @@ static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data, if (uLevel == 1 || uLevel == 2) { memset(p+22,' ',16); /* password */ SIVALS(p,38,-1); /* password age */ - SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */ + SSVAL(p,42, + Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ strcpy(p2,"\\\\%L\\HOMES"); standard_sub_basic(p2); @@ -2577,6 +2589,92 @@ static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data, return(True); } + +struct +{ + char * name; + char * pipename; + int subcommand; + BOOL (*fn) (); +} api_fd_commands [] = + { + { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, + { NULL, NULL, -1, api_Unsupported } + }; + +/**************************************************************************** + handle remote api calls delivered to a named pipe already opened. + ****************************************************************************/ +static int api_fd_reply(int cnum,int uid,char *outbuf, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +{ + char *rdata = NULL; + char *rparam = NULL; + int rdata_len = 0; + int rparam_len = 0; + BOOL reply=False; + int i; + int fd; + int subcommand; + + /* First find out the name of this file. */ + if (suwcnt != 2) + { + DEBUG(0,("Unexpected named pipe transaction.\n")); + return(-1); + } + + /* Get the file handle and hence the file name. */ + fd = setup[1]; + subcommand = setup[0]; + + DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name)); + DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", + tdscnt,tpscnt,mdrcnt,mprcnt)); + + for (i=0;api_fd_commands[i].name;i++) + if (strequal(api_fd_commands[i].pipename, Files[fd].name) && + api_fd_commands[i].subcommand == subcommand && + api_fd_commands[i].fn) + { + DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); + break; + } + + rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); + rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); + + reply = api_fd_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + if (rdata_len > mdrcnt || + rparam_len > mprcnt) + { + reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } + + + /* if we get False back then it's actually unsupported */ + if (!reply) + api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + /* now send the reply */ + send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); + + if (rdata) + free(rdata); + if (rparam) + free(rparam); + + return(-1); +} + + + /**************************************************************************** the buffer was too small ****************************************************************************/ @@ -2727,6 +2825,10 @@ static int named_pipe(int cnum,int uid, char *outbuf,char *name, if (strequal(name,"LANMAN")) return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); +if (strlen(name) < 1) + return(api_fd_reply(cnum,uid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt)); + + DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n", name,(int)setup[0],(int)setup[1])); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c new file mode 100644 index 0000000000..724f58e1e2 --- /dev/null +++ b/source3/smbd/pipes.c @@ -0,0 +1,363 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Pipe SMB reply routines + 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. +*/ +/* + This file handles reply_ calls on named pipes that the server + makes to handle specific protocols +*/ + + +#include "includes.h" +#include "trans2.h" + +#define PIPE "\\PIPE\\" +#define PIPELEN strlen(PIPE) + +#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024)) + +/* look in server.c for some explanation of these variables */ +extern int Protocol; +extern int DEBUGLEVEL; +extern int chain_size; +extern int maxxmit; +extern int chain_fnum; +extern char magic_char; +extern connection_struct Connections[]; +extern files_struct Files[]; +extern BOOL case_sensitive; +extern pstring sesssetup_user; +extern int Client; + +/* this macro should always be used to extract an fnum (smb_fid) from +a packet to ensure chaining works correctly */ +#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) + +char * known_pipes [] = +{ + "lsarpc", + NULL +}; + +/**************************************************************************** + reply to an open and X on a named pipe + + In fact what we do is to open a regular file with the same name in + /tmp. This can then be closed as normal. Reading and writing won't + make much sense, but will do *something*. The real reason for this + support is to be able to do transactions on them (well, on lsarpc + for domain login purposes...). + + This code is basically stolen from reply_open_and_X with some + wrinkles to handle pipes. +****************************************************************************/ +int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + pstring fname; + int cnum = SVAL(inbuf,smb_tid); + int fnum = -1; + int outsize = 0; + int smb_com2 = CVAL(inbuf,smb_vwv0); + int smb_off2 = SVAL(inbuf,smb_vwv1); + int smb_mode = SVAL(inbuf,smb_vwv3); + int smb_attr = SVAL(inbuf,smb_vwv5); +#if 0 + int open_flags = SVAL(inbuf,smb_vwv2); + int smb_sattr = SVAL(inbuf,smb_vwv4); + uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); +#endif + int smb_ofun = SVAL(inbuf,smb_vwv8); + int unixmode; + int size=0,fmode=0,mtime=0,rmode=0; + struct stat sbuf; + int smb_action = 0; + int i; + + /* XXXX we need to handle passed times, sattr and flags */ + strcpy(fname,smb_buf(inbuf)); + + /* If the name doesn't start \PIPE\ then this is directed */ + /* at a mailslot or something we really, really don't understand, */ + /* not just something we really don't understand. */ + if ( strncmp(fname,PIPE,PIPELEN) != 0 ) + return(ERROR(ERRSRV,ERRaccess)); + + DEBUG(4,("Opening pipe %s.\n", fname)); + + /* Strip \PIPE\ off the name. */ + strcpy(fname,smb_buf(inbuf) + PIPELEN); + + /* See if it is one we want to handle. */ + for( i = 0; known_pipes[i] ; i++ ) + if( strcmp(fname,known_pipes[i]) == 0 ) + break; + + if ( known_pipes[i] == NULL ) + return(ERROR(ERRSRV,ERRaccess)); + + /* Known pipes arrive with DIR attribs. Remove it so a regular file */ + /* can be opened and add it in after the open. */ + DEBUG(3,("Known pipe %s opening.\n",fname)); + smb_attr &= ~aDIR; + Connections[cnum].read_only = 0; + smb_ofun |= 0x10; /* Add Create it not exists flag */ + + unix_convert(fname,cnum); + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + + if (!check_name(fname,cnum)) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + unixmode = unix_mode(cnum,smb_attr); + + open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, + &rmode,&smb_action); + + if (!Files[fnum].open) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if (fstat(Files[fnum].fd,&sbuf) != 0) { + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + mtime = sbuf.st_mtime; + if (fmode & aDIR) { + close_file(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* Prepare the reply */ + outsize = set_message(outbuf,15,0,True); + CVAL(outbuf,smb_vwv0) = smb_com2; + + /* Put things back the way they were. */ + Connections[cnum].read_only = 1; + + /* Mark the opened file as an existing named pipe in message mode. */ + SSVAL(outbuf,smb_vwv9,2); + SSVAL(outbuf,smb_vwv10,0xc700); + if (rmode == 2) + { + DEBUG(4,("Resetting open result to open from create.\n")); + rmode = 1; + } + + SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); + SSVAL(outbuf,smb_vwv2,fnum); + SSVAL(outbuf,smb_vwv3,fmode); + put_dos_date3(outbuf,smb_vwv4,mtime); + SIVAL(outbuf,smb_vwv6,size); + SSVAL(outbuf,smb_vwv8,rmode); + SSVAL(outbuf,smb_vwv11,smb_action); + + chain_fnum = fnum; + + if (smb_com2 != 0xFF) + outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, + outbuf,outbuf+outsize, + length,bufsize); + + chain_fnum = -1; + + DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n", + fname, fnum, Files[fnum].name)); + + return(outsize); +} + + +/**************************************************************************** + api_LsarpcSNPHS + + SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here, + so just blithely return True. This is really only for NT domain stuff, + we we're only handling that - don't assume Samba now does complete + named pipe handling. +****************************************************************************/ +BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 id; + + id = param[0] + (param[1] << 8); + DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id)); + return(True); +} + + +/**************************************************************************** + api_LsarpcTNP + + TransactNamedPipe on \PIPE\lsarpc. +****************************************************************************/ +static void LsarpcTNP1(char *data,char **rdata, int *rdata_len) +{ + uint32 dword1, dword2; + char pname[] = "\\PIPE\\lsass"; + + /* All kinds of mysterious numbers here */ + *rdata_len = 68; + *rdata = REALLOC(*rdata,*rdata_len); + + dword1 = IVAL(data,0xC); + dword2 = IVAL(data,0x10); + + SIVAL(*rdata,0,0xc0005); + SIVAL(*rdata,4,0x10); + SIVAL(*rdata,8,0x44); + SIVAL(*rdata,0xC,dword1); + + SIVAL(*rdata,0x10,dword2); + SIVAL(*rdata,0x14,0x15); + SSVAL(*rdata,0x18,sizeof(pname)); + strcpy(*rdata + 0x1a,pname); + SIVAL(*rdata,0x28,1); + memcpy(*rdata + 0x30, data + 0x34, 0x14); +} + +static void LsarpcTNP2(char *data,char **rdata, int *rdata_len) +{ + uint32 dword1; + + /* All kinds of mysterious numbers here */ + *rdata_len = 48; + *rdata = REALLOC(*rdata,*rdata_len); + + dword1 = IVAL(data,0xC); + + SIVAL(*rdata,0,0x03020005); + SIVAL(*rdata,4,0x10); + SIVAL(*rdata,8,0x30); + SIVAL(*rdata,0xC,dword1); + SIVAL(*rdata,0x10,0x18); + SIVAL(*rdata,0x1c,0x44332211); + SIVAL(*rdata,0x20,0x88776655); + SIVAL(*rdata,0x24,0xCCBBAA99); + SIVAL(*rdata,0x28,0x11FFEEDD); +} + +static void LsarpcTNP3(char *data,char **rdata, int *rdata_len) +{ + uint32 dword1; + uint16 word1; + char * workgroup = lp_workgroup(); + int wglen = strlen(workgroup); + int i; + + /* All kinds of mysterious numbers here */ + *rdata_len = 90 + 2 * wglen; + *rdata = REALLOC(*rdata,*rdata_len); + + dword1 = IVAL(data,0xC); + word1 = SVAL(data,0x2C); + + SIVAL(*rdata,0,0x03020005); + SIVAL(*rdata,4,0x10); + SIVAL(*rdata,8,0x60); + SIVAL(*rdata,0xC,dword1); + SIVAL(*rdata,0x10,0x48); + SSVAL(*rdata,0x18,0x5988); /* This changes */ + SSVAL(*rdata,0x1A,0x15); + SSVAL(*rdata,0x1C,word1); + SSVAL(*rdata,0x20,6); + SSVAL(*rdata,0x22,8); + SSVAL(*rdata,0x24,0x8E8); /* So does this */ + SSVAL(*rdata,0x26,0x15); + SSVAL(*rdata,0x28,0x4D48); /* And this */ + SSVAL(*rdata,0x2A,0x15); + SIVAL(*rdata,0x2C,4); + SIVAL(*rdata,0x34,wglen); + for ( i = 0 ; i < wglen ; i++ ) + (*rdata)[0x38 + i * 2] = workgroup[i]; + + /* Now fill in the rest */ + i = 0x38 + wglen * 2; + SSVAL(*rdata,i,0x648); + SIVAL(*rdata,i+2,4); + SIVAL(*rdata,i+6,0x401); + SSVAL(*rdata,i+0xC,0x500); + SIVAL(*rdata,i+0xE,0x15); + SIVAL(*rdata,i+0x12,0x2372FE1); + SIVAL(*rdata,i+0x16,0x7E831BEF); + SIVAL(*rdata,i+0x1A,0x4B454B2); +} + +static void LsarpcTNP4(char *data,char **rdata, int *rdata_len) +{ + uint32 dword1; + + /* All kinds of mysterious numbers here */ + *rdata_len = 48; + *rdata = REALLOC(*rdata,*rdata_len); + + dword1 = IVAL(data,0xC); + + SIVAL(*rdata,0,0x03020005); + SIVAL(*rdata,4,0x10); + SIVAL(*rdata,8,0x30); + SIVAL(*rdata,0xC,dword1); + SIVAL(*rdata,0x10,0x18); +} + + +BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint32 id,id2; + + id = IVAL(data,0); + + DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id)); + switch (id) + { + case 0xb0005: + LsarpcTNP1(data,rdata,rdata_len); + break; + + case 0x03000005: + id2 = IVAL(data,8); + DEBUG(4,("\t- Suboperation %lx\n",id2)); + switch (id2 & 0xF) + { + case 8: + LsarpcTNP2(data,rdata,rdata_len); + break; + + case 0xC: + LsarpcTNP4(data,rdata,rdata_len); + break; + + case 0xE: + LsarpcTNP3(data,rdata,rdata_len); + break; + } + break; + } + return(True); +} diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d463b305c9..a97c8c9c9c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -294,6 +294,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL valid_nt_password = False; pstring user; BOOL guest=False; + BOOL computer_id=False; *smb_apasswd = 0; @@ -349,6 +350,15 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(3,("sesssetupX:name=[%s]\n",user)); + /* If name ends in $ then I think it's asking about whether a */ + /* computer with that name (minus the $) has access. For now */ + /* say yes to everything ending in $. */ + if (user[strlen(user) - 1] == '$') { + computer_id = True; + user[strlen(user) - 1] = '\0'; + } + + if (!*user) strcpy(user,lp_guestaccount(-1)); @@ -380,7 +390,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False)) { - if (lp_security() >= SEC_USER) { + if (!computer_id && lp_security() >= SEC_USER) { #if (GUEST_SESSSETUP == 0) return(ERROR(ERRSRV,ERRbadpw)); #endif @@ -444,7 +454,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) CVAL(outbuf,smb_vwv0) = smb_com2; SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); - if (guest) + if (guest && !computer_id) SSVAL(outbuf,smb_vwv2,1); /* register the name and uid as being validated, so further connections @@ -980,6 +990,10 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) struct stat sbuf; int smb_action = 0; + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(cnum)) + return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize); + /* XXXX we need to handle passed times, sattr and flags */ strcpy(fname,smb_buf(inbuf)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 334edf77d0..170062a531 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1584,7 +1584,7 @@ static int sig_cld() } depth++; - BlockSignals(True); + BlockSignals(True,SIGCLD); DEBUG(5,("got SIGCLD\n")); #ifdef USE_WAITPID @@ -1610,7 +1610,7 @@ static int sig_cld() while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0); #endif depth--; - BlockSignals(False); + BlockSignals(False,SIGCLD); return 0; } #endif @@ -1791,13 +1791,13 @@ this prevents zombie child processes ****************************************************************************/ static int sig_hup() { - BlockSignals(True); + BlockSignals(True,SIGHUP); DEBUG(0,("Got SIGHUP\n")); reload_services(False); #ifndef DONT_REINSTALL_SIG signal(SIGHUP,SIGNAL_CAST sig_hup); #endif - BlockSignals(False); + BlockSignals(False,SIGHUP); return(0); } @@ -3011,7 +3011,7 @@ struct smb_message_struct {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE}, {SMBread,"SMBread",reply_read,AS_USER}, {SMBwrite,"SMBwrite",reply_write,AS_USER}, - {SMBclose,"SMBclose",reply_close,AS_USER}, + {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER}, @@ -3054,7 +3054,7 @@ struct smb_message_struct {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE}, {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE}, - {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER}, + {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC}, {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER}, {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER}, {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, @@ -3456,7 +3456,7 @@ static void process(void) /* clean the share modes every 5 minutes */ if (!(counter%SHARE_MODES_CLEAN)) - clean_share_files(); + clean_share_modes(); /* automatic timeout if all connections are closed */ if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) { @@ -3744,6 +3744,11 @@ static void usage(char *pname) if (!open_sockets(is_daemon,port)) exit(1); +#ifdef FAST_SHARE_MODES + if (!start_share_mode_mgmt()) + exit(1); +#endif + /* possibly reload the services file. */ reload_services(True); @@ -3758,6 +3763,10 @@ static void usage(char *pname) process(); close_sockets(); +#ifdef FAST_SHARE_MODES + stop_share_mode_mgmt(); +#endif + exit_server("normal exit"); return(0); } -- cgit From 28177ca73bdbe3f8fb17a608db3df1a39e0e37a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 17 Aug 1996 11:37:44 +0000 Subject: - added support for Amiga-unix (based on BSD I think) - changed the order of PROGS and SPROGS in Makefile (SPROGS first) - another 64 bit cleanup (for INADDR_NONE) - added paranoia code in DirCacheAdd() to detect looping - fixed important DirCache flush bug - rewrote the NetServerEnum code after I found it could return servers from multiple workgroups at once, and this could cause browsing havoc. Now a null workgroup query is equivalent to a query for the servers primary workgroup - got rid of my_workgroup() - got rid of "workgroup = *" comment in Makefile. We no longer support a workgroup of *, users must set the workgroup explicitly - the wins.dat file was being stored in a different format to what it was being loaded in - this could cause havoc. fixed. - uppercase our netbios name and the workgroup name at startup - if accept fails in main loop when running as a daemon then continue, don't just exit! - don't use ./ on smbclient in smbtar - better code to detect if a process exists (This used to be commit ec3d53963064b50ff33e8eff47812aac82f164ba) --- source3/smbd/dir.c | 9 +++- source3/smbd/ipc.c | 145 ++++++++++++-------------------------------------- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 +- 4 files changed, 44 insertions(+), 114 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 55a5983468..42bd54c270 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -631,6 +631,7 @@ add an entry to the directory cache ********************************************************************/ void DirCacheAdd(char *path,char *name,char *dname,int snum) { + int count; struct dir_cache *entry = (struct dir_cache *)malloc(sizeof(*entry)); if (!entry) return; entry->path = strdup(path); @@ -647,7 +648,12 @@ void DirCacheAdd(char *path,char *name,char *dname,int snum) DEBUG(4,("Added dir cache entry %s %s -> %s\n",path,name,dname)); if (dir_cache_size == DIRCACHESIZE) { - for (entry=dir_cache; entry->next; entry=entry->next) ; + for (entry=dir_cache, count=1; + entry->next && count < dir_cache_size; + entry=entry->next, count++) ; + if (entry->next || count != dir_cache_size) { + DEBUG(0,("DirCache bug - please report\n")); + } free(entry->path); free(entry->name); free(entry->dname); @@ -695,6 +701,7 @@ void DirCacheFlush(int snum) if (entry->next) entry->next->prev = entry->prev; if (dir_cache == entry) dir_cache = entry->next; free(entry); + dir_cache_size--; } else { next = entry->next; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 39b8f3f089..78a9807769 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -748,78 +748,22 @@ static BOOL check_server_info(int uLevel, char* id) return True; } -/* used for server information: client, nameserv and ipc */ struct srv_info_struct { fstring name; uint32 type; fstring comment; - fstring domain; /* used ONLY in ipc.c NOT namework.c */ - BOOL server_added; /* used ONLY in ipc.c NOT namework.c */ + fstring domain; + BOOL server_added; }; -/******************************************************************* - filter out unwanted server info - ******************************************************************/ -static BOOL filter_server_info(struct srv_info_struct *server, - BOOL domains, - char *domain, uint32 request) -{ - 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; - } -} /******************************************************************* 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, BOOL domains, + struct srv_info_struct **servers, char *domain) { FILE *f; @@ -843,7 +787,7 @@ static int get_server_info(uint32 servertype, /* 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))); + DEBUG(4,("Servertype search: %8x\n",servertype)); while (!feof(f)) { @@ -870,7 +814,7 @@ static int get_server_info(uint32 servertype, if (!next_token(&ptr,s->comment, NULL)) continue; if (!next_token(&ptr,s->domain , NULL)) { /* this allows us to cope with an old nmbd */ - strcpy(s->domain,my_workgroup()); + strcpy(s->domain,lp_workgroup()); } if (sscanf(stype,"%X",&s->type) != 1) { @@ -884,20 +828,16 @@ static int get_server_info(uint32 servertype, ok = False; } - if ((servertype == ~SV_TYPE_DOMAIN_ENUM) && + if ((servertype & SV_TYPE_DOMAIN_ENUM) != (s->type & SV_TYPE_DOMAIN_ENUM)) { - DEBUG(4,("s:all x dom ")); + DEBUG(4,("s: dom mismatch ")); ok = False; } - if (domains && !(domain && *domain && strequal(domain, s->domain))) + if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) { - if (!(s->type & SV_TYPE_DOMAIN_ENUM)) - { - DEBUG(4,("r:dom enum ")); - ok = False; - } + ok = False; } if (ok) @@ -905,7 +845,6 @@ static int get_server_info(uint32 servertype, 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++; } @@ -1026,16 +965,13 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, int counted=0,total=0; int i; fstring domain; - 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_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); - domain[0] = 0; p += 8; if (!prefix_ok(str1,"WrLehD")) return False; @@ -1045,20 +981,14 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request))); DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); - if (strcmp(str1, "WrLehDO") == 0) - { - domains = False; - } - else if (strcmp(str1, "WrLehDz") == 0) - { - domains = True; + if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); + } else { + StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); } if (lp_browse_list()) - { - total = get_server_info(servertype,&servers,domains,domain); - } + total = get_server_info(servertype,&servers,domain); data_len = fixed_len = string_len = 0; @@ -1070,21 +1000,17 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, for (i=0;iname)) continue; + lastname = s->name; + 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) { - if (lastname && strequal(lastname,s->name)) continue; - lastname = s->name; - 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; - } + counted++; + fixed_len += f_len; + string_len += s_len; } } } @@ -1104,15 +1030,12 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, 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)) - { - if (lastname && strequal(lastname,s->name)) continue; - lastname = s->name; - 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--; - } + if (lastname && strequal(lastname,s->name)) continue; + lastname = s->name; + 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--; } } @@ -1746,7 +1669,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,False,NULL))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;i Date: Sat, 17 Aug 1996 14:27:12 +0000 Subject: - made FAST_SHARE_MODES standard for Linux - you can now press enter after a password prompt with "smbclient -L hostname" and it will use a blank username and password, the same as if you used -U% - changed the wins.dat store code to not go via a string variable (just use fprintf instead) - removed a "unsigned long" that luke put back in, changing it to uint32 to keep 64 bit machines happy. Naughtly luke! - allow guest non-connnected print queue listings so ms client 3 can work (This used to be commit 917160dee69bbc198985b6f3232ca2dcda809d8a) --- source3/smbd/server.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3889440975..403b41e86b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3026,7 +3026,7 @@ struct smb_message_struct {SMBctemp,"SMBctemp",reply_ctemp,AS_USER}, {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER}, {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER}, - {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER}, + {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST}, {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER}, {SMBlock,"SMBlock",reply_lock,AS_USER}, {SMBunlock,"SMBunlock",reply_unlock,AS_USER}, @@ -3159,8 +3159,17 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize unbecome_user(); /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(cnum,uid)) - return(ERROR(ERRSRV,ERRinvnid)); + if ((flags & AS_USER) && !become_user(cnum,uid)) { + if (flags & AS_GUEST) + flags &= ~AS_USER; + else + return(ERROR(ERRSRV,ERRinvnid)); + } + /* this code is to work around a bug is MS client 3 without + introducing a security hole - it needs to be able to do + print queue checks as guest if it isn't logged in properly */ + if (flags & AS_USER) + flags &= ~AS_GUEST; /* does it need write permission? */ if ((flags & NEED_WRITE) && !CAN_WRITE(cnum)) @@ -3744,7 +3753,7 @@ static void usage(char *pname) if (!open_sockets(is_daemon,port)) exit(1); -#ifdef FAST_SHARE_MODES +#if FAST_SHARE_MODES if (!start_share_mode_mgmt()) exit(1); #endif @@ -3763,7 +3772,7 @@ static void usage(char *pname) process(); close_sockets(); -#ifdef FAST_SHARE_MODES +#if FAST_SHARE_MODES stop_share_mode_mgmt(); #endif -- cgit From 0c33046a0aa0461a5e932dd7b0b6e38ab9708867 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 19 Aug 1996 11:17:29 +0000 Subject: - added "netbios name" option in smb.conf to make controlling the name that samba uses possible - added "socket address" option to allow virtual SMB servers (on systems with IP aliasing line Linux) - disabled FAST_SHARE_MODES by default in Linux as older Linux boxes can't do shared writeable mappings. We really need autoconf ... - added new option types in loadparm so a string type can be specified ot be uppercase only, this is used for the workgroup and netbios name options - auto-create the lock directory if it doesn't exist in shared mem startup - get rid of announce_backup() - change a few comments in nmbd code - rewrote the chaining code completely. Hopefully it will handle any depth chains now. - added LPRng support (This used to be commit e9eac6cd49c352349580ddb13d720cb201aecc48) --- source3/smbd/pipes.c | 17 +----- source3/smbd/reply.c | 125 +++++++--------------------------------- source3/smbd/server.c | 154 ++++++++++++++++++++++++-------------------------- 3 files changed, 96 insertions(+), 200 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 724f58e1e2..ffa46083c3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -35,7 +35,6 @@ /* look in server.c for some explanation of these variables */ extern int Protocol; extern int DEBUGLEVEL; -extern int chain_size; extern int maxxmit; extern int chain_fnum; extern char magic_char; @@ -72,9 +71,6 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring fname; int cnum = SVAL(inbuf,smb_tid); int fnum = -1; - int outsize = 0; - int smb_com2 = CVAL(inbuf,smb_vwv0); - int smb_off2 = SVAL(inbuf,smb_vwv1); int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); #if 0 @@ -149,8 +145,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) } /* Prepare the reply */ - outsize = set_message(outbuf,15,0,True); - CVAL(outbuf,smb_vwv0) = smb_com2; + set_message(outbuf,15,0,True); /* Put things back the way they were. */ Connections[cnum].read_only = 1; @@ -164,7 +159,6 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) rmode = 1; } - SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); SSVAL(outbuf,smb_vwv2,fnum); SSVAL(outbuf,smb_vwv3,fmode); put_dos_date3(outbuf,smb_vwv4,mtime); @@ -174,17 +168,10 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) chain_fnum = fnum; - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - chain_fnum = -1; - DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n", fname, fnum, Files[fnum].name)); - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3c2e91d5f5..a84a9af0c1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -30,7 +30,6 @@ /* look in server.c for some explanation of these variables */ extern int Protocol; extern int DEBUGLEVEL; -extern int chain_size; extern int maxxmit; extern int chain_fnum; extern char magic_char; @@ -178,11 +177,8 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring password; pstring devicename; int connection_num; - int outsize = 0; int uid = SVAL(inbuf,smb_uid); int vuid; - int smb_com2 = SVAL(inbuf,smb_vwv0); - int smb_off2 = SVAL(inbuf,smb_vwv1); int passlen = SVAL(inbuf,smb_vwv3); *service = *user = *password = *devicename = 0; @@ -221,7 +217,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (connection_num < 0) return(connection_error(inbuf,outbuf,connection_num)); - outsize = set_message(outbuf,2,strlen(devicename)+1,True); + set_message(outbuf,2,strlen(devicename)+1,True); DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); @@ -229,17 +225,9 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(inbuf,smb_tid,connection_num); SSVAL(outbuf,smb_tid,connection_num); - CVAL(outbuf,smb_vwv0) = smb_com2; - SSVAL(outbuf,smb_vwv1,(chain_size + outsize)-4); - strcpy(smb_buf(outbuf),devicename); - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -278,11 +266,8 @@ reply to a session setup command ****************************************************************************/ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - int outsize = 0; int sess_uid; int gid; - int smb_com2; - int smb_off2; int smb_bufsize; int smb_mpxmax; int smb_vc_num; @@ -299,8 +284,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) *smb_apasswd = 0; sess_uid = SVAL(inbuf,smb_uid); - smb_com2 = CVAL(inbuf,smb_vwv0); - smb_off2 = SVAL(inbuf,smb_vwv1); smb_bufsize = SVAL(inbuf,smb_vwv2); smb_mpxmax = SVAL(inbuf,smb_vwv3); smb_vc_num = SVAL(inbuf,smb_vwv4); @@ -424,15 +407,15 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* it's ok - setup a reply */ if (Protocol < PROTOCOL_NT1) { - outsize = set_message(outbuf,3,0,True); + set_message(outbuf,3,0,True); } else { char *p; - outsize = set_message(outbuf,3,3,True); + set_message(outbuf,3,3,True); p = smb_buf(outbuf); strcpy(p,"Unix"); p = skip_string(p,1); strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1); strcpy(p,lp_workgroup()); p = skip_string(p,1); - outsize = set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); /* perhaps grab OS version here?? */ } @@ -451,9 +434,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid); } - CVAL(outbuf,smb_vwv0) = smb_com2; - SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); - if (guest && !computer_id) SSVAL(outbuf,smb_vwv2,1); @@ -463,12 +443,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) maxxmit = MIN(maxxmit,smb_bufsize); - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -973,10 +948,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring fname; int cnum = SVAL(inbuf,smb_tid); int fnum = -1; - int outsize = 0; int openmode = 0; - int smb_com2 = CVAL(inbuf,smb_vwv0); - int smb_off2 = SVAL(inbuf,smb_vwv1); int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); #if 0 @@ -1033,9 +1005,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRDOS,ERRnoaccess)); } - outsize = set_message(outbuf,15,0,True); - CVAL(outbuf,smb_vwv0) = smb_com2; - SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); + set_message(outbuf,15,0,True); SSVAL(outbuf,smb_vwv2,fnum); SSVAL(outbuf,smb_vwv3,fmode); put_dos_date3(outbuf,smb_vwv4,mtime); @@ -1045,14 +1015,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) chain_fnum = fnum; - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - chain_fnum = -1; - - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1061,26 +1024,15 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) ****************************************************************************/ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) { - int outsize = 0; - int smb_com2 = CVAL(inbuf,smb_vwv0); - int smb_off2 = SVAL(inbuf,smb_vwv1); int uid = SVAL(inbuf,smb_uid); invalidate_uid(uid); - outsize = set_message(outbuf,2,0,True); - CVAL(outbuf,smb_vwv0) = smb_com2; - SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4); + set_message(outbuf,2,0,True); DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid)); - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1486,8 +1438,6 @@ int reply_read(char *inbuf,char *outbuf) ****************************************************************************/ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - int smb_com2 = CVAL(inbuf,smb_vwv0); - int smb_off2 = SVAL(inbuf,smb_vwv1); int fnum = GETFNUM(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_maxcnt = SVAL(inbuf,smb_vwv5); @@ -1495,7 +1445,6 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) int cnum; int nread = -1; char *data; - int outsize = 0; BOOL ok = False; cnum = SVAL(inbuf,smb_tid); @@ -1504,7 +1453,7 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) CHECK_READ(fnum); CHECK_ERROR(fnum); - outsize = set_message(outbuf,12,0,True); + set_message(outbuf,12,0,True); data = smb_buf(outbuf); if (is_locked(fnum,cnum,smb_maxcnt,smb_offs)) @@ -1515,27 +1464,17 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); - outsize += nread; - CVAL(outbuf,smb_vwv0) = smb_com2; - SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4); SSVAL(outbuf,smb_vwv5,nread); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf) + chain_size); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d com2=%d off2=%d\n", + DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n", timestring(),fnum,cnum, - smb_mincnt,smb_maxcnt,nread,smb_com2,smb_off2)); + smb_mincnt,smb_maxcnt,nread)); chain_fnum = fnum; - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - chain_fnum = -1; - - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1767,8 +1706,6 @@ int reply_write(char *inbuf,char *outbuf,int dum1,int dum2) ****************************************************************************/ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - int smb_com2 = CVAL(inbuf,smb_vwv0); - int smb_off2 = SVAL(inbuf,smb_vwv1); int fnum = GETFNUM(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_dsize = SVAL(inbuf,smb_vwv10); @@ -1776,7 +1713,6 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL write_through = BITSETW(inbuf+smb_vwv7,0); int cnum; int nwritten = -1; - int outsize = 0; char *data; cnum = SVAL(inbuf,smb_tid); @@ -1804,10 +1740,8 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - outsize = set_message(outbuf,6,0,True); + set_message(outbuf,6,0,True); - CVAL(outbuf,smb_vwv0) = smb_com2; - SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4); SSVAL(outbuf,smb_vwv2,nwritten); if (nwritten < smb_dsize) { @@ -1822,14 +1756,7 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (lp_syncalways(SNUM(cnum)) || write_through) sync_file(fnum); - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - chain_fnum = -1; - - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2828,8 +2755,6 @@ int reply_setdir(char *inbuf,char *outbuf) ****************************************************************************/ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) { - int smb_com2 = CVAL(inbuf,smb_vwv0); - int smb_off2 = SVAL(inbuf,smb_vwv1); int fnum = GETFNUM(inbuf,smb_vwv2); uint16 locktype = SVAL(inbuf,smb_vwv3); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); @@ -2840,7 +2765,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) int i; char *data; uint32 ecode=0, dummy2; - int outsize, eclass=0, dummy1; + int eclass=0, dummy1; cnum = SVAL(inbuf,smb_tid); @@ -2879,24 +2804,14 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) return ERROR(eclass,ecode); } - outsize = set_message(outbuf,2,0,True); - - CVAL(outbuf,smb_vwv0) = smb_com2; - SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4); + set_message(outbuf,2,0,True); DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", timestring(),fnum,cnum,locktype,num_locks,num_ulocks)); chain_fnum = fnum; - if (smb_com2 != 0xFF) - outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4, - outbuf,outbuf+outsize, - length,bufsize); - - chain_fnum = -1; - - return(outsize); + return chain_reply(inbuf,outbuf,length,bufsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 403b41e86b..c377684536 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -59,8 +59,6 @@ extern int Protocol; int maxxmit = BUFFER_SIZE; -int chain_size = 0; - /* a fnum to use when chaining */ int chain_fnum = -1; @@ -1645,7 +1643,7 @@ static BOOL open_sockets(BOOL is_daemon,int port) #endif /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0); + s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address())); if (s == -1) return(False); @@ -3221,103 +3219,97 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /**************************************************************************** -construct a chained reply and add it to the already made reply - -inbuf points to the original message start. -inbuf2 points to the smb_wct part of the secondary message -type is the type of the secondary message -outbuf points to the original outbuffer -outbuf2 points to the smb_wct field of the new outbuffer -size is the total length of the incoming message (from inbuf1) -bufsize is the total buffer size - -return how many bytes were added to the response -****************************************************************************/ -int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize) -{ - int outsize = 0; - char *ibuf,*obuf; - static BOOL in_chain = False; - static char *last_outbuf=NULL; - BOOL was_inchain = in_chain; - int insize_remaining; - static int insize_deleted; - - - chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct; - if (was_inchain) - outbuf = last_outbuf; - else - insize_deleted = 0; - + construct a chained reply and add it to the already made reply + **************************************************************************/ +int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) +{ + static char *orig_inbuf; + static char *orig_outbuf; + int smb_com2 = CVAL(inbuf,smb_vwv0); + unsigned smb_off2 = SVAL(inbuf,smb_vwv1); + char *inbuf2, *outbuf2; + int outsize2; + char inbuf_saved[smb_wct]; + char outbuf_saved[smb_wct]; + extern int chain_size; + int wct = CVAL(outbuf,smb_wct); + int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); + + /* maybe its not chained */ + if (smb_com2 == 0xFF) { + CVAL(outbuf,smb_vwv0) = 0xFF; + return outsize; + } - insize_deleted = 0; - inbuf2 -= insize_deleted; - insize_remaining = size - PTR_DIFF(inbuf2,inbuf); - insize_deleted += size - (insize_remaining + smb_wct); + if (chain_size == 0) { + /* this is the first part of the chain */ + orig_inbuf = inbuf; + orig_outbuf = outbuf; + } - in_chain = True; - last_outbuf = outbuf; + /* we need to tell the client where the next part of the reply will be */ + SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); + CVAL(outbuf,smb_vwv0) = smb_com2; + /* remember how much the caller added to the chain, only counting stuff + after the parameter words */ + chain_size += outsize - smb_wct; - /* allocate some space for the in and out buffers of the chained message */ - ibuf = (char *)malloc(size + SAFETY_MARGIN); - obuf = (char *)malloc(bufsize + SAFETY_MARGIN); + /* work out pointers into the original packets. The + headers on these need to be filled in */ + inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; + outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; - if (!ibuf || !obuf) - { - DEBUG(0,("Out of memory in chain reply\n")); - return(ERROR(ERRSRV,ERRnoresource)); - } + /* save the data which will be overwritten by the new headers */ + memcpy(inbuf_saved,inbuf2,smb_wct); + memcpy(outbuf_saved,outbuf2,smb_wct); - ibuf += SMB_ALIGNMENT; - obuf += SMB_ALIGNMENT; + /* give the new packet the same header as the first part of the SMB */ + memcpy(inbuf2,orig_inbuf,smb_wct); /* create the in buffer */ - memcpy(ibuf,inbuf,smb_wct); - memcpy(ibuf+smb_wct,inbuf2,insize_remaining); - CVAL(ibuf,smb_com) = type; + CVAL(outbuf2,smb_com) = smb_com2; /* create the out buffer */ - bzero(obuf,smb_size); - - set_message(obuf,0,0,True); - CVAL(obuf,smb_com) = CVAL(ibuf,smb_com); + bzero(outbuf2,smb_size); + set_message(outbuf2,0,0,True); + CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com); - memcpy(obuf+4,ibuf+4,4); - CVAL(obuf,smb_rcls) = SUCCESS; - CVAL(obuf,smb_reh) = 0; - CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(obuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(obuf,smb_err,SUCCESS); - SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid)); + memcpy(outbuf2+4,inbuf2+4,4); + CVAL(outbuf2,smb_rcls) = SUCCESS; + CVAL(outbuf2,smb_reh) = 0; + CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set + means a reply */ + SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf2,smb_err,SUCCESS); + SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid)); + SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid)); + SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid)); + SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid)); DEBUG(3,("Chained message\n")); - show_msg(ibuf); + show_msg(inbuf2); /* process the request */ - outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining, - bufsize-chain_size); + outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, + bufsize-chain_size); /* copy the new reply header over the old one, but preserve the smb_com field */ - memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1)); - - /* and copy the data from the reply to the right spot */ - memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct); - - /* free the allocated buffers */ - if (ibuf) free(ibuf-SMB_ALIGNMENT); - if (obuf) free(obuf-SMB_ALIGNMENT); + smb_com2 = CVAL(orig_outbuf,smb_com); + memmove(orig_outbuf,outbuf2,smb_wct); + CVAL(orig_outbuf,smb_com) = smb_com2; - in_chain = was_inchain; + /* restore the saved data, being careful not to overwrite any + data from the reply header */ + memcpy(inbuf2,inbuf_saved,smb_wct); + { + int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); + if (ofs < 0) ofs = 0; + memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); + } - /* return how much extra has been added to the packet */ - return(outsize - smb_wct); + return(outsize2 + chain_size); } @@ -3330,10 +3322,12 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) int type = CVAL(inbuf,smb_com); int outsize = 0; int msg_type = CVAL(inbuf,0); + extern int chain_size; smb_last_time = time(NULL); chain_size = 0; + chain_fnum = -1; bzero(outbuf,smb_size); -- cgit From 241ecbe741287be9a03623d3282a2ec1432dbf2a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 19 Aug 1996 13:54:58 +0000 Subject: fix a bug in the new chaining code (This used to be commit 50ed940451e9d009f19e735074f8fcdb503f5c25) --- source3/smbd/server.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c377684536..1fb6358794 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3225,7 +3225,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) { static char *orig_inbuf; static char *orig_outbuf; - int smb_com2 = CVAL(inbuf,smb_vwv0); + int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); unsigned smb_off2 = SVAL(inbuf,smb_vwv1); char *inbuf2, *outbuf2; int outsize2; @@ -3260,15 +3260,18 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; + /* remember the original command type */ + smb_com1 = CVAL(orig_outbuf,smb_com); + /* save the data which will be overwritten by the new headers */ memcpy(inbuf_saved,inbuf2,smb_wct); memcpy(outbuf_saved,outbuf2,smb_wct); /* give the new packet the same header as the first part of the SMB */ - memcpy(inbuf2,orig_inbuf,smb_wct); + memmove(inbuf2,orig_inbuf,smb_wct); /* create the in buffer */ - CVAL(outbuf2,smb_com) = smb_com2; + CVAL(inbuf2,smb_com) = smb_com2; /* create the out buffer */ bzero(outbuf2,smb_size); @@ -3296,9 +3299,8 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* copy the new reply header over the old one, but preserve the smb_com field */ - smb_com2 = CVAL(orig_outbuf,smb_com); memmove(orig_outbuf,outbuf2,smb_wct); - CVAL(orig_outbuf,smb_com) = smb_com2; + CVAL(orig_outbuf,smb_com) = smb_com1; /* restore the saved data, being careful not to overwrite any data from the reply header */ @@ -3309,7 +3311,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); } - return(outsize2 + chain_size); + return outsize2; } @@ -3351,6 +3353,8 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) outsize = switch_message(type,inbuf,outbuf,size,bufsize); + outsize += chain_size; + if(outsize > 4) smb_setlen(outbuf,outsize - 4); return(outsize); -- cgit From 748d65a4ac898708dc7d2fd6f2bdee41489fee86 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 Aug 1996 15:45:16 +0000 Subject: - fix a bug in NetServerEnum where counted and total were not counted correctly if there were multiple instances of a name. This led to the infamous "not enough memory" error when browsing (but this isn't the only cause of that message) - fix a triple-chaining bug which affected OpenX following a TconX - fix a serious nmbd bug that meant nmdb would answer packets that it wasn't supposed to, causing havoc with browse lists. - never time out SELF packets. This is an interim fix until I find out why nmbd thought they should be timed out. (This used to be commit 2960c3908c2c3b01a1f2b77def60350018d298e1) --- source3/smbd/ipc.c | 14 ++++++++------ source3/smbd/reply.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/server.c | 45 +++++---------------------------------------- 3 files changed, 57 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 78a9807769..9da7c993dd 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -963,7 +963,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, int f_len, s_len; struct srv_info_struct *servers=NULL; int counted=0,total=0; - int i; + int i,missed; fstring domain; BOOL domain_request; BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY; @@ -991,6 +991,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, total = get_server_info(servertype,&servers,domain); data_len = fixed_len = string_len = 0; + missed = 0; qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); @@ -1006,12 +1007,13 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", s->name, s->type, s->comment, s->domain)); - if (data_len <= buf_len) - { + if (data_len <= buf_len) { counted++; fixed_len += f_len; string_len += s_len; - } + } else { + missed++; + } } } @@ -1044,12 +1046,12 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,total); + SSVAL(*rparam,6,counted+missed); if (servers) free(servers); DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", - domain,uLevel,counted,total)); + domain,uLevel,counted,counted+missed)); return(True); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a84a9af0c1..7241aadac0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -130,6 +130,44 @@ static int connection_error(char *inbuf,char *outbuf,int connection_num) } + +/**************************************************************************** + parse a share descriptor string +****************************************************************************/ +static void parse_connect(char *p,char *service,char *user, + char *password,int *pwlen,char *dev) +{ + char *p2; + + DEBUG(4,("parsing connect string %s\n",p)); + + p2 = strrchr(p,'\\'); + if (p2 == NULL) + strcpy(service,p); + else + strcpy(service,p2+1); + + p += strlen(p) + 2; + + strcpy(password,p); + *pwlen = strlen(password); + + p += strlen(p) + 2; + + strcpy(dev,p); + + *user = 0; + p = strchr(service,'%'); + if (p != NULL) + { + *p = 0; + strcpy(user,p+1); + } +} + + + + /**************************************************************************** reply to a tcon ****************************************************************************/ @@ -149,7 +187,7 @@ int reply_tcon(char *inbuf,char *outbuf) vuid = valid_uid(uid); - parse_connect(inbuf,service,user,password,&pwlen,dev); + parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); connection_num = make_connection(service,user,password,pwlen,dev,vuid); @@ -1210,6 +1248,11 @@ int reply_unlink(char *inbuf,char *outbuf) if (check_name(directory,cnum)) dirptr = OpenDir(directory); + /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then + the pattern matches against the long name, otherwise the short name + We don't implement this yet XXXX + */ + if (dirptr) { error = ERRbadfile; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1fb6358794..683d63e7aa 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2563,41 +2563,6 @@ static int reply_negprot(char *inbuf,char *outbuf) } -/**************************************************************************** - parse a connect packet -****************************************************************************/ -void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev) -{ - char *p = smb_buf(buf) + 1; - char *p2; - - DEBUG(4,("parsing connect string %s\n",p)); - - p2 = strrchr(p,'\\'); - if (p2 == NULL) - strcpy(service,p); - else - strcpy(service,p2+1); - - p += strlen(p) + 2; - - strcpy(password,p); - *pwlen = strlen(password); - - p += strlen(p) + 2; - - strcpy(dev,p); - - *user = 0; - p = strchr(service,'%'); - if (p != NULL) - { - *p = 0; - strcpy(user,p+1); - } -} - - /**************************************************************************** close all open files for a connection ****************************************************************************/ @@ -3261,14 +3226,14 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; /* remember the original command type */ - smb_com1 = CVAL(orig_outbuf,smb_com); + smb_com1 = CVAL(orig_inbuf,smb_com); /* save the data which will be overwritten by the new headers */ memcpy(inbuf_saved,inbuf2,smb_wct); memcpy(outbuf_saved,outbuf2,smb_wct); - /* give the new packet the same header as the first part of the SMB */ - memmove(inbuf2,orig_inbuf,smb_wct); + /* give the new packet the same header as the last part of the SMB */ + memmove(inbuf2,inbuf,smb_wct); /* create the in buffer */ CVAL(inbuf2,smb_com) = smb_com2; @@ -3297,8 +3262,8 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, bufsize-chain_size); - /* copy the new reply header over the old one, but preserve - the smb_com field */ + /* copy the new reply and request headers over the old ones, but + preserve the smb_com field */ memmove(orig_outbuf,outbuf2,smb_wct); CVAL(orig_outbuf,smb_com) = smb_com1; -- cgit From b5a64bb74056fad43afedcb05d29000618170ef4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 Aug 1996 06:09:00 +0000 Subject: - new handling of ST_TYPE bits, they are now consolidated much more in DFLT_SERVER_TYPE in nameserv.h - got rid of a lot of spurious domain controller stuff. Samba is not a domain controller yet, but it can be a domain master. We were claiming to be a domain controller in some packets which may have caused problems - don't do preferred master startups on the WINS pseudo-net - don't do election requests on the WINS pseudo-net - fix a nasty bug in become_non_master() which wiped out the bits in remove_type before using them. The result was that samba didn't like losing its master status. - changed the logic in the election packet handling to enable us to become a non-master whenever we receive a winning election frame, even if we aren't expecting it - get another packet from the socket in nmbd when we reject one of our own packets, this stops us from going into the packet reading code too often and makes nmbd much snappier - always remove a name immediately when we try to release it, don't wait for the lack of response from the network, otherwise we will end up replying to name that we don't really own. We still send the dereg packets, we just don't wait for them to time out. (This used to be commit eb84f2f342375439d94481a0ccf47c9593544e32) --- source3/smbd/ipc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9da7c993dd..87df699e29 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1666,8 +1666,7 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, struct srv_info_struct *servers=NULL; int i,count; pstring comment; - uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION| - SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE; + uint32 servertype=DFLT_SERVER_TYPE; strcpy(comment,lp_serverstring()); -- cgit From da0761ac0dfd8eab9d889abcf37ace79aae04ebd Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 21 Aug 1996 08:11:03 +0000 Subject: JHT ==> Upgraded Samba to Windows NT Server version 4.1 Just to keep ahead of the pack. Note: Really only done to differntiate our version ID from existing SMB Servers. (This used to be commit 6636c7b5b8e8a4ccf7f39450011ed864049a7cd1) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 87df699e29..920284fc9f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -60,7 +60,7 @@ extern fstring local_machine; #define QNLEN 12 /* queue name maximum length */ #define MAJOR_VERSION 4 -#define MINOR_VERSION 0 +#define MINOR_VERSION 1 extern int Client; -- cgit From a782ffb5edfb7759f756032be918e3e939a458bc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 Aug 1996 12:36:01 +0000 Subject: handle sigpipe better for server security (This used to be commit d87fdb3ee95b6640d5deef823f22e8d98350ca33) --- source3/smbd/server.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 683d63e7aa..0e0a524f16 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1618,6 +1618,20 @@ static int sig_cld() **************************************************************************/ static int sig_pipe() { + extern int password_client; + BlockSignals(True,SIGPIPE); + + if (password_client != -1) { + DEBUG(3,("lost connection to password server\n")); + close(password_client); + password_client = -1; +#ifndef DONT_REINSTALL_SIG + signal(SIGPIPE, SIGNAL_CAST sig_pipe); +#endif + BlockSignals(False,SIGPIPE); + return 0; + } + exit_server("Got sigpipe\n"); return(0); } -- cgit From 3d088fd65e3e49949dfd98b464ad6e08f6115099 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 Aug 1996 14:15:09 +0000 Subject: - fix a bug handling readraw packets that caused the timeout to be 30 milliseconds instead of 30 seconds as was intended. Thanks to Paul Nelson for finding this bug. (This used to be commit 78f62c83be5df6b66aa0b5e83b2d290f97ce53c2) --- source3/smbd/ipc.c | 2 +- source3/smbd/trans2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 920284fc9f..dd9b9661ae 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2823,7 +2823,7 @@ int reply_trans(char *inbuf,char *outbuf) { int pcnt,poff,dcnt,doff,pdisp,ddisp; - if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) || + if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || CVAL(inbuf, smb_com) != SMBtrans) { DEBUG(2,("Invalid secondary trans2 packet\n")); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 321dabc72c..9b5419010e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1554,7 +1554,7 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) while( num_data_sofar < total_data || num_params_sofar < total_params) { - if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) || + if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || CVAL(inbuf, smb_com) != SMBtranss2) { outsize = set_message(outbuf,0,0,True); -- cgit From 9155889092ac9ff476d950a0c1b624ebad3cdad6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Aug 1996 06:32:03 +0000 Subject: - add timeouts to connect() for password server connections. This makes multiple password servers practical. (This used to be commit 5c3e8326cc45d3cbd076475e445ce461a2bf7560) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a5f597682f..fd3ff4fd17 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1287,7 +1287,7 @@ BOOL server_cryptkey(char *buf) continue; } - password_client = open_socket_out(SOCK_STREAM, &dest_ip, port); + password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); if (password_client >= 0) { DEBUG(3,("connected to password server %s\n",p)); StrnCpy(pserver,p,sizeof(pserver)-1); -- cgit From 5945be9718b8ea56c8dde99729c0ec0e56080fee Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 23 Aug 1996 10:17:30 +0000 Subject: - fixed bugs in nmb response packet checking. - added multiple workgroup code - samba can register under different (unique) NetBIOS aliases, one per workgroup it joins. lkcl (This used to be commit f24e341e7e4d8726b98d3a0f83b24f61817fe536) --- source3/smbd/ipc.c | 38 +++++++++++++++++++++++++++++++++++--- source3/smbd/server.c | 2 ++ 2 files changed, 37 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index dd9b9661ae..916d7e3cc4 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -983,8 +983,26 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); - } else { - StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); + } + else + { + /* a server will connect to us under one of samba's NetBIOS + name aliases, and by not giving us a domain name it + assumes we know which domain it's talking about. + do a look-up for the workgroup name against the name + the host connected to us as. + */ + + char *work_alias; + char host_alias[16]; + + StrnCpy(host_alias, local_machine, 15); + work_alias = conf_alias_to_workgroup(host_alias); /* look-up */ + + DEBUG(4,("host alias: %s work_alias: %s\n", + host_alias, work_alias)); + if (work_alias) + StrnCpy(domain, work_alias, sizeof(fstring)-1); } if (lp_browse_list()) @@ -1668,9 +1686,23 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, pstring comment; uint32 servertype=DFLT_SERVER_TYPE; + char *work_alias; + char host_alias[16]; + char domain[16]; + + StrnCpy(host_alias, local_machine, 15); + work_alias = conf_alias_to_workgroup(host_alias); /* look-up */ + + DEBUG(4,("host alias: %s work_alias: %s\n", + host_alias, work_alias)); + if (work_alias) + StrnCpy(domain, work_alias, sizeof(fstring)-1); + else + *domain = 0; + strcpy(comment,lp_serverstring()); - if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,domain))>0) { for (i=0;i Date: Sat, 24 Aug 1996 01:32:51 +0000 Subject: fixed dircahe bug (This used to be commit 050f941e21aeb57ab47ac9d29fb4acfceab45087) --- source3/smbd/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 42bd54c270..f2e672987e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -649,9 +649,9 @@ void DirCacheAdd(char *path,char *name,char *dname,int snum) if (dir_cache_size == DIRCACHESIZE) { for (entry=dir_cache, count=1; - entry->next && count < dir_cache_size; + entry->next && count < dir_cache_size + 1; entry=entry->next, count++) ; - if (entry->next || count != dir_cache_size) { + if (entry->next || count != dir_cache_size + 1) { DEBUG(0,("DirCache bug - please report\n")); } free(entry->path); -- cgit From 9ad5a3fe36ac2b32bcb7a50c608ec586629f2125 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sat, 24 Aug 1996 01:41:46 +0000 Subject: removed all of lukes recent changes. I need to do a p2 release but can't test the multi group changes. I also found that some of lukes changes wiped out some recent bug fixes. Is your CVS tree ok luke? (This used to be commit 8b7fe224bce64803d55ae279fa61ef3ebbbb0241) --- source3/smbd/ipc.c | 38 +++----------------------------------- source3/smbd/server.c | 2 -- 2 files changed, 3 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 916d7e3cc4..dd9b9661ae 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -983,26 +983,8 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); - } - else - { - /* a server will connect to us under one of samba's NetBIOS - name aliases, and by not giving us a domain name it - assumes we know which domain it's talking about. - do a look-up for the workgroup name against the name - the host connected to us as. - */ - - char *work_alias; - char host_alias[16]; - - StrnCpy(host_alias, local_machine, 15); - work_alias = conf_alias_to_workgroup(host_alias); /* look-up */ - - DEBUG(4,("host alias: %s work_alias: %s\n", - host_alias, work_alias)); - if (work_alias) - StrnCpy(domain, work_alias, sizeof(fstring)-1); + } else { + StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); } if (lp_browse_list()) @@ -1686,23 +1668,9 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, pstring comment; uint32 servertype=DFLT_SERVER_TYPE; - char *work_alias; - char host_alias[16]; - char domain[16]; - - StrnCpy(host_alias, local_machine, 15); - work_alias = conf_alias_to_workgroup(host_alias); /* look-up */ - - DEBUG(4,("host alias: %s work_alias: %s\n", - host_alias, work_alias)); - if (work_alias) - StrnCpy(domain, work_alias, sizeof(fstring)-1); - else - *domain = 0; - strcpy(comment,lp_serverstring()); - if ((count=get_server_info(SV_TYPE_ALL,&servers,domain))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;i Date: Sat, 24 Aug 1996 01:46:47 +0000 Subject: added debug info (This used to be commit 4a988021a2aceaa5fc0d4e5ba2802392a7141ad8) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f2e672987e..73c4afd77e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -652,7 +652,7 @@ void DirCacheAdd(char *path,char *name,char *dname,int snum) entry->next && count < dir_cache_size + 1; entry=entry->next, count++) ; if (entry->next || count != dir_cache_size + 1) { - DEBUG(0,("DirCache bug - please report\n")); + DEBUG(0,("DirCache bug - please report %d %d\n",dir_cache_size,count)); } free(entry->path); free(entry->name); -- cgit From 11d9539d755d5c5accb4481577781b8b7bfeda50 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Oct 1996 14:06:17 +0000 Subject: - accept either NT or lanman passwords in tconX (This used to be commit b6c1c60d72e1625ca172b8f8eb07078413611468) --- source3/smbd/password.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fd3ff4fd17..41dfd838ed 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -597,7 +597,7 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha /**************************************************************************** check if a username/password is OK ****************************************************************************/ -BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password) +BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) { pstring pass2; int level = lp_passwordlevel(); @@ -672,7 +672,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL return(False); } - if(Protocol >= PROTOCOL_NT1 && is_nt_password) + if(Protocol >= PROTOCOL_NT1) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). @@ -688,7 +688,6 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL return(True); } DEBUG(4,("NT MD4 password check failed\n")); - return (False); } } @@ -888,7 +887,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL,False)) { + password_ok(user,password,pwlen,NULL)) { endnetgrent(); return(user); } @@ -910,7 +909,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; strcpy(name,*member); if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL,False)) + password_ok(name,password,pwlen,NULL)) return(&name[0]); member++; } @@ -923,7 +922,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (pwd = getpwent ()) { if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { /* This Entry have PASSWORD and same GID then check pwd */ - if (password_ok(NULL, password, pwlen, pwd,False)) { + if (password_ok(NULL, password, pwlen, pwd)) { strcpy(tm, pwd->pw_name); endpwent (); return tm; @@ -974,14 +973,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL, False); + ok = password_ok(user,password, pwlen, NULL); if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); } /* check for a previously registered guest username */ if (!ok && (vuid >= 0) && validated_users[vuid].guest) { if (user_ok(validated_users[vuid].name,snum) && - password_ok(validated_users[vuid].name, password, pwlen, NULL, False)) { + password_ok(validated_users[vuid].name, password, pwlen, NULL)) { strcpy(user, validated_users[vuid].name); validated_users[vuid].guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); @@ -1005,7 +1004,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, strcpy(user2,auser); if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL, False)) { + if (password_ok(user2,password, pwlen, NULL)) { ok = True; strcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); @@ -1057,7 +1056,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstring user2; strcpy(user2,auser); if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL, False)) + password_ok(user2,password,pwlen,NULL)) { ok = True; strcpy(user,user2); -- cgit From 5a2f52b79e28530c454cb488a44588147640f061 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Oct 1996 14:09:22 +0000 Subject: - a huge pile of changes from Luke which implement the browse.conf stuff and also fix a pile of nmbd bugs. Unfortunately I found it very hard to disentangle the new features from the bug fixes so I am putting in the new code. I hope this is the last big pile of changes to the 1.9.16 series! (This used to be commit 20b6203dac4bbb43e4e7bea0b214496d76d679d9) --- source3/smbd/ipc.c | 61 +++++++++++++++++++++++++++++++++++++++++---------- source3/smbd/pipes.c | 17 +++++++++++--- source3/smbd/reply.c | 16 ++++++++++---- source3/smbd/server.c | 2 ++ 4 files changed, 77 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index dd9b9661ae..580aa446b6 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -439,7 +439,7 @@ static void PackDriverData(struct pack_desc* desc) } static int check_printq_info(struct pack_desc* desc, - int uLevel, const char* id1, const char* id2) + int uLevel, char *id1, const char* id2) { desc->subformat = NULL; switch( uLevel ) { @@ -812,10 +812,7 @@ static int get_server_info(uint32 servertype, 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 cope with an old nmbd */ - strcpy(s->domain,lp_workgroup()); - } + if (!next_token(&ptr,s->domain , NULL)) continue; if (sscanf(stype,"%X",&s->type) != 1) { DEBUG(4,("r:host file ")); @@ -983,8 +980,22 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); - } else { - StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); + } + else + { + /* a server will connect to us under one of samba's NetBIOS + name aliases, and by not giving us a domain name it + assumes we know which domain it's talking about. + do a look-up for the workgroup name against the name + the host connected to us as. + */ + + char *work_alias; + + work_alias = conf_alias_to_workgroup(local_machine); /* look-up */ + + if (work_alias) + StrnCpy(domain, work_alias, sizeof(fstring)-1); } if (lp_browse_list()) @@ -1349,7 +1360,7 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data, DEBUG(3,("Set password for <%s>\n",user)); - if (password_ok(user,pass1,strlen(pass1),NULL,False) && + if (password_ok(user,pass1,strlen(pass1),NULL) && chgpasswd(user,pass1,pass2)) { SSVAL(*rparam,0,NERR_Success); @@ -1668,9 +1679,19 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, pstring comment; uint32 servertype=DFLT_SERVER_TYPE; + char *work_alias; + char domain[16]; + + work_alias = conf_alias_to_workgroup(local_machine); /* look-up */ + + if (work_alias) + StrnCpy(domain, work_alias, sizeof(fstring)-1); + else + *domain = 0; + strcpy(comment,lp_serverstring()); - if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,domain))>0) { for (i=0;i= SEC_USER) { #if (GUEST_SESSSETUP == 0) @@ -452,7 +460,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) p = smb_buf(outbuf); strcpy(p,"Unix"); p = skip_string(p,1); strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1); - strcpy(p,lp_workgroup()); p = skip_string(p,1); + strcpy(p,domain); p = skip_string(p,1); set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); /* perhaps grab OS version here?? */ } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0e0a524f16..4aaab4c087 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3746,6 +3746,8 @@ static void usage(char *pname) DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); } + read_smbbrowse_conf(myhostname); + process(); close_sockets(); -- cgit From afd08462ad5ff6b3c4bf621e39c55853a608175e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Oct 1996 15:41:30 +0000 Subject: backout all the changes to nmbd. The 1.9.16 tree is now back to 1.9.16p2 as far as nmbd is concerned apart from a small change that fixes the announce type in two places. (This used to be commit 45e66a69d320024877c8b13f12b21bf895e04410) --- source3/smbd/ipc.c | 57 +++++++++------------------------------------------ source3/smbd/pipes.c | 17 +++------------ source3/smbd/reply.c | 12 ++--------- source3/smbd/server.c | 2 -- 4 files changed, 15 insertions(+), 73 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 580aa446b6..8e81134de5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -812,7 +812,10 @@ static int get_server_info(uint32 servertype, 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)) continue; + if (!next_token(&ptr,s->domain , NULL)) { + /* this allows us to cope with an old nmbd */ + strcpy(s->domain,lp_workgroup()); + } if (sscanf(stype,"%X",&s->type) != 1) { DEBUG(4,("r:host file ")); @@ -980,22 +983,8 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); - } - else - { - /* a server will connect to us under one of samba's NetBIOS - name aliases, and by not giving us a domain name it - assumes we know which domain it's talking about. - do a look-up for the workgroup name against the name - the host connected to us as. - */ - - char *work_alias; - - work_alias = conf_alias_to_workgroup(local_machine); /* look-up */ - - if (work_alias) - StrnCpy(domain, work_alias, sizeof(fstring)-1); + } else { + StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); } if (lp_browse_list()) @@ -1679,19 +1668,9 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, pstring comment; uint32 servertype=DFLT_SERVER_TYPE; - char *work_alias; - char domain[16]; - - work_alias = conf_alias_to_workgroup(local_machine); /* look-up */ - - if (work_alias) - StrnCpy(domain, work_alias, sizeof(fstring)-1); - else - *domain = 0; - strcpy(comment,lp_serverstring()); - if ((count=get_server_info(SV_TYPE_ALL,&servers,domain))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;i Date: Wed, 2 Oct 1996 16:16:16 +0000 Subject: - fix the EALREADY bug so connections to slow hosts with smbclient get through - add workarounds to handle the win95 and WinNT bugs in handling password lengths in sessionsetup (This used to be commit 671b3a3a770c824ae77fcb83dc551054a880edad) --- source3/smbd/reply.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b6c2313bf4..6cf1b031e8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -335,10 +335,8 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); BOOL doencrypt = SMBENCRYPT(); - char *p = smb_buf(inbuf); - if (passlen1 > 256) passlen1 = 0; - if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird - lengths sometimes */ + char *p = smb_buf(inbuf); + if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; @@ -346,26 +344,33 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) smb_ntpasslen = passlen2; memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); } else { - /* for Win95 */ - if (passlen1 > passlen2) { - smb_apasslen = passlen1; - StrnCpy(smb_apasswd,p,smb_apasslen); - } else { - smb_apasslen = passlen2; - StrnCpy(smb_apasswd,p + passlen1,smb_apasslen); + /* both Win95 and WinNT stuff up the password lengths for + non-encrypting systems. Uggh. + + if passlen1==24 its a win95 system, and its setting the + password length incorrectly. Luckily it still works with the + default code because Win95 will null terminate the password + anyway + + if passlen1>0 and passlen2>0 then its a NT box and its + setting passlen2 to some random value which really stuffs + things up. we need to fix that one. */ + if (passlen1 > 0 && passlen2 > 0) { + passlen2 = 0; } + /* we use the first password that they gave */ + smb_apasslen = passlen1; + StrnCpy(smb_apasswd,p,smb_apasslen); } -#if NT_WORKAROUND - if (passlen2 == 1) { - /* apparently NT sometimes sets passlen2 to 1 when it means 0. This - tries to work around that problem */ - passlen2 = 0; - } -#endif + p += passlen1 + passlen2; strcpy(user,p); p = skip_string(p,1); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", p,skip_string(p,1),skip_string(p,2))); + + /* now work around the Win95 bug */ + if(!doencrypt && smb_apasslen==24) + smb_apasslen = strlen(smb_apasswd); } -- cgit From e23f2b9cef8428bda51b413642d9720ba5c590d5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 4 Oct 1996 09:31:07 +0000 Subject: - changed the umask handling. We now set the umask to 0 and explicitly set the mode on all created files. I think this is a better policy. - change the debug levels on some items - fix a charset handling bug which affected foreign and extended charset users - no longer switch back to the original directory when idle, instead switch to / as the original directory may not be readable by ordinary users. - fix some bugs where the create mode of files was not being explicitly set (it was relying on the umask and using fopen). Not a big bug as it only affected obscure commands like the messaging ops. - got rid of the lock code in the lpq cache as its no longer needed - rewrote smbrun to be faster and to remove the security hole. We now don't actually need a external smbrun binary, its all done by smbd. - add a more explicit warning about uids and gids of -1 or 65535 (This used to be commit 5aa735c940ccdb6acae5f28449d484181c912e49) --- source3/smbd/message.c | 28 +++++----- source3/smbd/server.c | 18 +++--- source3/smbd/uid.c | 146 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 152 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index b26a6605ed..22523aad3b 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -42,8 +42,8 @@ static void msg_deliver(void) { pstring s; fstring name; - FILE *f; int i; + int fd; if (! (*lp_msg_command())) { @@ -56,21 +56,19 @@ static void msg_deliver(void) sprintf(s,"/tmp/msg.XXXXXX"); strcpy(name,(char *)mktemp(s)); - f = fopen(name,"w"); - if (!f) - { - DEBUG(1,("can't open message file %s\n",name)); - return; - } + fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); + if (fd == -1) { + DEBUG(1,("can't open message file %s\n",name)); + return; + } - for (i=0;iuid)) @@ -2149,7 +2149,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pstring cmd; strcpy(cmd,lp_preexec(SNUM(cnum))); standard_sub(cnum,cmd); - smbrun(cmd,NULL); + smbrun(cmd,NULL,False); } /* we've finished with the sensitive stuff */ @@ -2629,7 +2629,7 @@ void close_cnum(int cnum, int uid) pstring cmd; strcpy(cmd,lp_postexec(SNUM(cnum))); standard_sub(cnum,cmd); - smbrun(cmd,NULL); + smbrun(cmd,NULL,False); unbecome_user(); } @@ -2640,7 +2640,7 @@ void close_cnum(int cnum, int uid) pstring cmd; strcpy(cmd,lp_rootpostexec(SNUM(cnum))); standard_sub(cnum,cmd); - smbrun(cmd,NULL); + smbrun(cmd,NULL,False); } Connections[cnum].open = False; @@ -2764,8 +2764,10 @@ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) if (!file_exist(fname,NULL)) { + int oldmask = umask(022); f = fopen(fname,"w"); if (f) fclose(f); + umask(oldmask); } total_recs = file_size(fname) / sizeof(crec); @@ -3617,7 +3619,9 @@ static void usage(char *pname) fault_setup(exit_server); - umask(0777 & ~DEF_CREATE_MASK); + /* we want total control over the permissions on created files, + so set our umask to 0 */ + umask(0); init_uid(); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 555cd457e7..7274c18478 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -27,9 +27,6 @@ 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; @@ -57,7 +54,7 @@ void init_uid(void) current_user.cnum = -1; - GetWd(OriginalDir); + ChDir(IDLE_DIR); } @@ -69,6 +66,10 @@ static BOOL become_uid(int uid) if (initial_uid != 0) return(True); + if (uid == -1 || uid == 65535) { + DEBUG(1,("WARNING: using uid %d is a security risk\n",uid)); + } + #ifdef AIX { /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */ @@ -118,6 +119,10 @@ static BOOL become_gid(int gid) { if (initial_uid != 0) return(True); + + if (gid == -1 || gid == 65535) { + DEBUG(1,("WARNING: using gid %d is a security risk\n",gid)); + } #ifdef USE_SETRES if (setresgid(-1,gid,-1) != 0) @@ -199,7 +204,6 @@ static BOOL check_user_ok(int cnum,user_struct *vuser,int snum) ****************************************************************************/ BOOL become_user(int cnum, int uid) { - int new_umask; user_struct *vuser; int snum,gid; int id = uid; @@ -259,14 +263,11 @@ BOOL become_user(int cnum, int 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)); + DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", + getuid(),geteuid(),getgid(),getegid())); return(True); } @@ -279,9 +280,7 @@ BOOL unbecome_user(void ) if (current_user.cnum == -1) return(False); - ChDir(OriginalDir); - - umask(old_umask); + ChDir(IDLE_DIR); if (initial_uid == 0) { @@ -318,9 +317,9 @@ BOOL unbecome_user(void ) current_user.uid = initial_uid; current_user.gid = initial_gid; - if (ChDir(OriginalDir) != 0) + if (ChDir(IDLE_DIR) != 0) DEBUG(0,("%s chdir(%s) failed in unbecome_user\n", - timestring(),OriginalDir)); + timestring(),IDLE_DIR)); DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); @@ -332,14 +331,69 @@ BOOL unbecome_user(void ) /**************************************************************************** -run a command via system() using smbrun, being careful about uid/gid handling +This is a utility function of smbrun(). It must be called only from +the child as it may leave the caller in a privilaged state. ****************************************************************************/ -int smbrun(char *cmd,char *outfile) +static BOOL setup_stdout_file(char *outfile,BOOL shared) +{ + int fd; + mode_t mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH; + + close(1); + + if (shared) { + /* become root - unprivilaged users can't delete these files */ +#ifdef USE_SETRES + setresgid(0,0,0); + setresuid(0,0,0); +#else + setuid(0); + seteuid(0); +#endif + } + + /* now create the file with O_EXCL set */ + unlink(outfile); + fd = open(outfile,O_RDWR|O_CREAT|O_TRUNC|O_EXCL,mode); + + if (fd == -1) return False; + + if (fd != 1) { + if (dup2(fd,1) != 0) { + DEBUG(2,("Failed to create stdout file descriptor\n")); + close(fd); + return False; + } + close(fd); + } + return True; +} + + +/**************************************************************************** +run a command being careful about uid/gid handling and putting the output in +outfile (or discard it if outfile is NULL). + +if shared is True then ensure the file will be writeable by all users +but created such that its owned by root. This overcomes a security hole. + +if shared is not set then open the file with O_EXCL set +****************************************************************************/ +int smbrun(char *cmd,char *outfile,BOOL shared) { + int fd,pid; + int uid = current_user.uid; + int gid = current_user.gid; + +#if USE_SYSTEM int ret; pstring syscmd; char *path = lp_smbrun(); + /* in the old method we use system() to execute smbrun which then + executes the command (using system() again!). This involves lots + of shell launches and is very slow. It also suffers from a + potential security hole */ if (!file_exist(path,NULL)) { DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",path)); @@ -347,13 +401,69 @@ int smbrun(char *cmd,char *outfile) } sprintf(syscmd,"%s %d %d \"(%s 2>&1) > %s\"", - path,current_user.uid,current_user.gid,cmd, + path,uid,gid,cmd, outfile?outfile:"/dev/null"); DEBUG(5,("smbrun - running %s ",syscmd)); ret = system(syscmd); DEBUG(5,("gave %d\n",ret)); return(ret); +#else + /* in this newer method we will exec /bin/sh with the correct + arguments, after first setting stdout to point at the file */ + + if ((pid=fork())) { + int status=0; + /* the parent just waits for the child to exit */ + if (waitpid(pid,&status,0) != pid) { + DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno))); + return -1; + } + return status; + } + + + /* we are in the child. we exec /bin/sh to do the work for us. we + don't directly exec the command we want because it may be a + pipeline or anything else the config file specifies */ + + /* point our stdout at the file we want output to go into */ + if (outfile && !setup_stdout_file(outfile,shared)) { + exit(80); + } + + /* 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 USE_SETRES + setresgid(0,0,0); + setresuid(0,0,0); + setresgid(gid,gid,gid); + setresuid(uid,uid,uid); +#else + setuid(0); + seteuid(0); + setgid(gid); + setegid(gid); + setuid(uid); + seteuid(uid); +#endif + + if (getuid() != uid || geteuid() != uid || + getgid() != gid || getegid() != gid) { + /* we failed to lose our privilages - do not execute the command */ + exit(81); /* we can't print stuff at this stage, instead use exit codes + for debugging */ + } + + /* close all other file descriptors, leaving only 0, 1 and 2. 0 and + 2 point to /dev/null from the startup code */ + for (fd=3;fd<256;fd++) close(fd); + + execl("/bin/sh","sh","-c",cmd,NULL); + + /* not reached */ + exit(82); +#endif } -- cgit From 38087ccb4071bfff29801026e2bf5c47565305b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Oct 1996 02:54:37 +0000 Subject: - use workgroup from smb.conf in smbclient - change debug level on clitar stuff - define MAP_FILE if not defined - ensure we never set authoritative on queries in nmbd - fake a positive response to SMBioctl, apparently this is needed for some WfWg printer drivers - deny file access for non-fcbopen queries when (access_allowed == AREAD && flags == O_RDWR) - add sys_waitpid() (This used to be commit 61e3116e573637d6b5a878eeb8db72831e3c5bd1) --- source3/smbd/reply.c | 7 ++++++- source3/smbd/server.c | 3 ++- source3/smbd/uid.c | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6cf1b031e8..63c0a7027e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -294,8 +294,13 @@ int reply_unknown(char *inbuf,char *outbuf) int reply_ioctl(char *inbuf,char *outbuf) { DEBUG(3,("ignoring ioctl\n")); - +#if 1 + /* we just say it succeeds and hope its all OK. + some day it would be nice to interpret them individually */ + return set_message(outbuf,1,0,True); +#else return(ERROR(ERRSRV,ERRnosupport)); +#endif } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a710aef69b..9ad7840465 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1158,6 +1158,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, share_pid,fname); if ((access_allowed == AFAIL) || + (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) || (access_allowed == AREAD && flags == O_WRONLY) || (access_allowed == AWRITE && flags == O_RDONLY)) { DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", @@ -1586,7 +1587,7 @@ static int sig_cld() DEBUG(5,("got SIGCLD\n")); #ifdef USE_WAITPID - while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0); + while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0); #endif /* Stop zombies */ diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 7274c18478..9312a447a0 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -415,7 +415,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared) if ((pid=fork())) { int status=0; /* the parent just waits for the child to exit */ - if (waitpid(pid,&status,0) != pid) { + if (sys_waitpid(pid,&status,0) != pid) { DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno))); return -1; } -- cgit From e5893bdfbef0ac16772199d7ec6fac7d3e4f8431 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Oct 1996 10:41:13 +0000 Subject: I have fixed quite a few important bugs in this commit. Luke, can you take special note of the bug fixes to nmbd so you can propogate them to your new code. - rewrote the code that used to use fromhost(). We now call gethostbyaddr() only if necessary and a maximum of once per connection. Calling gethostbyaddr() causes problems on some systems so avoiding it if possible is a good thing :-) - added the "fake oplocks" option. See the docs in smb.conf(5) and Speed.txt - fixed a serious bug in nmbd where it would try a DNS lookup on FIND_SELF queries. This caused a lot of unnecessary (and incorrect) DNS lookups to happen. FIND_SELF queries should only go to the internal name tables. - don't set FIND_SELF for name queries if we are a wins proxy, as we are supposed to be answering queries for other hosts. - fixed a bug in nmbd which had "if (search | FIND_LOCAL)" instead of "if (search & FIND_LOCAL)". Luke, this was in nameservreply.c - the above 3 bugs together meant that DNS queries were being cached, but the cache wasn't being used, so every query was going to DNS, no wonder nmbd has been chewing so much CPU time! Another side effect was that queries on names in lmhosts weren't being answered for bcast queries with "wins proxy" set. - ignore the maxxmit for seconday session setups (see CIFS spec) - close user opened files in a uLogoffX for user level security (see CIFS spec) - added uid into the files struct to support the above change (This used to be commit ea472b7217b7693627a13a7b1e428a0a6a3d8755) --- source3/smbd/password.c | 9 ++------- source3/smbd/reply.c | 33 ++++++++++++++++++++++++++++++++- source3/smbd/server.c | 22 ++++++++-------------- source3/smbd/trans2.c | 5 +++++ 4 files changed, 47 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 41dfd838ed..d17bb86be4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1207,20 +1207,15 @@ BOOL check_hosts_equiv(char *user) pstring rhostsfile; struct passwd *pass = Get_Pwnam(user,True); - extern struct from_host Client_info; - extern int Client; - if (!pass) return(False); - fromhost(Client,&Client_info); - fname = lp_hosts_equiv(); /* note: don't allow hosts.equiv on root */ if (fname && *fname && (pass->pw_uid != 0)) { - if (check_user_equiv(user,Client_info.name,fname)) + if (check_user_equiv(user,client_name(),fname)) return(True); } @@ -1230,7 +1225,7 @@ BOOL check_hosts_equiv(char *user) if (home) { sprintf(rhostsfile, "%s/.rhosts", home); - if (check_user_equiv(user,Client_info.name,rhostsfile)) + if (check_user_equiv(user,client_name(),rhostsfile)) return(True); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 63c0a7027e..7b8f4a502f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -323,6 +323,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring user; BOOL guest=False; BOOL computer_id=False; + static BOOL done_sesssetup = False; *smb_apasswd = 0; @@ -489,7 +490,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) to a uid can get through without a password, on the same VC */ register_uid(SVAL(inbuf,smb_uid),gid,user,guest); - maxxmit = MIN(maxxmit,smb_bufsize); + if (!done_sesssetup) + maxxmit = MIN(maxxmit,smb_bufsize); + + done_sesssetup = True; return chain_reply(inbuf,outbuf,length,bufsize); } @@ -983,6 +987,10 @@ int reply_open(char *inbuf,char *outbuf) put_dos_date3(outbuf,smb_vwv2,mtime); SIVAL(outbuf,smb_vwv4,size); SSVAL(outbuf,smb_vwv6,rmode); + + if (lp_fake_oplocks(SNUM(cnum))) { + CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); + } return(outsize); } @@ -999,6 +1007,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) int openmode = 0; int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); + BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1); #if 0 int open_flags = SVAL(inbuf,smb_vwv2); int smb_sattr = SVAL(inbuf,smb_vwv4); @@ -1053,6 +1062,10 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRDOS,ERRnoaccess)); } + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + smb_action |= (1<<15); + } + set_message(outbuf,15,0,True); SSVAL(outbuf,smb_vwv2,fnum); SSVAL(outbuf,smb_vwv3,fmode); @@ -1076,6 +1089,16 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) invalidate_uid(uid); + /* in user level security we are supposed to close any files + open by this user */ + if (lp_security() != SEC_SHARE) { + int i; + for (i=0;iuid, pcon->gid, @@ -2597,8 +2599,6 @@ close a cnum ****************************************************************************/ void close_cnum(int cnum, int uid) { - extern struct from_host Client_info; - DirCacheFlush(SNUM(cnum)); unbecome_user(); @@ -2611,7 +2611,7 @@ void close_cnum(int cnum, int uid) DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n", timestring(), - Client_info.name,Client_info.addr, + remote_machine,client_addr(), lp_servicename(SNUM(cnum)))); yield_connection(cnum, @@ -2825,11 +2825,8 @@ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1); crec.start = time(NULL); - { - extern struct from_host Client_info; - StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1); - StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1); - } + StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); + StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1); /* make our mark */ if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 || @@ -2977,7 +2974,7 @@ struct smb_message_struct {SMBecho,"SMBecho",reply_echo,0}, {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, - {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, + {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, AS_USER}, {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, @@ -3350,11 +3347,8 @@ static void process(void) { static int trans_num = 0; int nread; - extern struct from_host Client_info; extern int Client; - fromhost(Client,&Client_info); - InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if ((InBuffer == NULL) || (OutBuffer == NULL)) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9b5419010e..53af9acbf5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -163,6 +163,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, char *params = *pparams; int16 open_mode = SVAL(params, 2); int16 open_attr = SVAL(params,6); + BOOL oplock_request = BITSETW(params,1); #if 0 BOOL return_additional_info = BITSETW(params,0); int16 open_sattr = SVAL(params, 4); @@ -232,6 +233,10 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, SIVAL(params,8, size); SSVAL(params,12,rmode); + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + smb_action |= (1<<15); + } + SSVAL(params,18,smb_action); SIVAL(params,20,inode); -- cgit From f3c79936d7fc21d3257432962b23764ca00b0cbb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Oct 1996 13:13:31 +0000 Subject: - replace the base36 function with one that works on more systems (compiler bugs were the problem) - minor password cleanups (catch WfWG bug where it sets the password to a space instead of a NULL) - fix printing problem for kanji users - minor cleanups (This used to be commit 92566ecc315c29da6e9aaa67ddae33e64f5bcc67) --- source3/smbd/mangle.c | 9 +++------ source3/smbd/reply.c | 32 ++++++++++++++++++++++++-------- source3/smbd/server.c | 2 +- 3 files changed, 28 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 177a34c975..6d98d9e39c 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -383,13 +383,10 @@ BOOL is_mangled(char *s) /**************************************************************************** return a base 36 character. v must be from 0 to 35. ****************************************************************************/ -static char base36(int v) +static char base36(unsigned int v) { - v = v % 36; - if (v < 10) - return('0'+v); - else /* needed to work around a DEC C compiler bug */ - return('A' + (v-10)); + static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + return basechars[v % 36]; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7b8f4a502f..89b07f1b9e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -181,7 +181,7 @@ int reply_tcon(char *inbuf,char *outbuf) int outsize = 0; int uid = SVAL(inbuf,smb_uid); int vuid; - int pwlen; + int pwlen=0; *service = *user = *password = *dev = 0; @@ -218,6 +218,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) int uid = SVAL(inbuf,smb_uid); int vuid; int passlen = SVAL(inbuf,smb_vwv3); + BOOL doencrypt = SMBENCRYPT(); *service = *user = *password = *devicename = 0; @@ -231,8 +232,15 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) char *path; char *p; memcpy(password,smb_buf(inbuf),passlen); - password[passlen]=0; + password[passlen]=0; path = smb_buf(inbuf) + passlen; + + if (!doencrypt || passlen != 24) { + if (strequal(password," ")) + *password = 0; + passlen = strlen(password); + } + DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen)); strcpy(service,path+2); p = strchr(service,'\\'); @@ -315,7 +323,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) int smb_mpxmax; int smb_vc_num; uint32 smb_sesskey; - int smb_apasslen; + int smb_apasslen = 0; pstring smb_apasswd; int smb_ntpasslen = 0; pstring smb_ntpasswd; @@ -343,6 +351,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL doencrypt = SMBENCRYPT(); char *p = smb_buf(inbuf); + if (passlen1 != 24 && passlen2 != 24) + doencrypt = False; + if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; @@ -366,17 +377,22 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } /* we use the first password that they gave */ smb_apasslen = passlen1; - StrnCpy(smb_apasswd,p,smb_apasslen); + StrnCpy(smb_apasswd,p,smb_apasslen); + + /* trim the password */ + smb_apasslen = strlen(smb_apasswd); + + /* wfwg sometimes uses a space instead of a null */ + if (strequal(smb_apasswd," ")) { + smb_apasslen = 0; + *smb_apasswd = 0; + } } p += passlen1 + passlen2; strcpy(user,p); p = skip_string(p,1); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", p,skip_string(p,1),skip_string(p,2))); - - /* now work around the Win95 bug */ - if(!doencrypt && smb_apasslen==24) - smb_apasslen = strlen(smb_apasswd); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e0e9838a74..5db62426ca 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -841,7 +841,7 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode) Files[fnum].print_file = Connections[cnum].printer; Files[fnum].modified = False; Files[fnum].cnum = cnum; - string_set(&Files[fnum].name,fname); + string_set(&Files[fnum].name,dos_to_unix(fname,False)); Files[fnum].wbmpx_ptr = NULL; /* -- cgit From dfa2b456c743a643080d3a2eb0d9db62503141f5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 7 Oct 1996 11:06:34 +0000 Subject: - continue when failing to load config file in nmblookup and smbclient - fix important bug in nmbd where it set the return code for a negative name response to 0 (which means success!) (This used to be commit bfa816cc8f30d9a629b4fe9f71bf0707aa6c4502) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 89b07f1b9e..48a0732617 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -302,7 +302,7 @@ int reply_unknown(char *inbuf,char *outbuf) int reply_ioctl(char *inbuf,char *outbuf) { DEBUG(3,("ignoring ioctl\n")); -#if 1 +#if 0 /* we just say it succeeds and hope its all OK. some day it would be nice to interpret them individually */ return set_message(outbuf,1,0,True); -- cgit From ec85f2e53d18a818440cf716ad6b6892594cae85 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 7 Oct 1996 15:04:48 +0000 Subject: - revert to old idle dir code (marty pointed out a problem with the new code) - handle server level security in the new "detect NT password length stuffups" code (This used to be commit 7c135d499409d4ddedb978f681559dae90ac4288) --- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 3 +++ source3/smbd/uid.c | 10 ++++++---- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 48a0732617..a37c1901be 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -372,7 +372,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if passlen1>0 and passlen2>0 then its a NT box and its setting passlen2 to some random value which really stuffs things up. we need to fix that one. */ - if (passlen1 > 0 && passlen2 > 0) { + if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24) { passlen2 = 0; } /* we use the first password that they gave */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5db62426ca..2dc78e0176 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -67,6 +67,7 @@ static int num_connections_open = 0; extern fstring remote_machine; +pstring OriginalDir; /* these can be set by some functions to override the error codes */ int unix_ERR_class=SUCCESS; @@ -3618,6 +3619,8 @@ static void usage(char *pname) so set our umask to 0 */ umask(0); + GetWd(OriginalDir); + init_uid(); /* this is for people who can't start the program correctly */ diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 9312a447a0..f7005b53cf 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -31,6 +31,8 @@ static int initial_gid; /* what user is current? */ struct current_user current_user; +extern pstring OriginalDir; + /**************************************************************************** initialise the uid routines ****************************************************************************/ @@ -54,7 +56,7 @@ void init_uid(void) current_user.cnum = -1; - ChDir(IDLE_DIR); + ChDir(OriginalDir); } @@ -280,7 +282,7 @@ BOOL unbecome_user(void ) if (current_user.cnum == -1) return(False); - ChDir(IDLE_DIR); + ChDir(OriginalDir); if (initial_uid == 0) { @@ -317,9 +319,9 @@ BOOL unbecome_user(void ) current_user.uid = initial_uid; current_user.gid = initial_gid; - if (ChDir(IDLE_DIR) != 0) + if (ChDir(OriginalDir) != 0) DEBUG(0,("%s chdir(%s) failed in unbecome_user\n", - timestring(),IDLE_DIR)); + timestring(),OriginalDir)); DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); -- cgit From 6dc1fe06c141ba7e32ee85caa3652f0b24896378 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 9 Oct 1996 15:08:29 +0000 Subject: - correctly handle non-encrypted share mode session-setup. We were losing the username due to the recent "handle broken password lengths" patch. (This used to be commit b006cd6f911c045488bcdab260b03fd98cb08145) --- source3/smbd/reply.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a37c1901be..3d125a1186 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -332,6 +332,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL guest=False; BOOL computer_id=False; static BOOL done_sesssetup = False; + BOOL doencrypt = SMBENCRYPT(); *smb_apasswd = 0; @@ -345,10 +346,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) smb_apasslen = SVAL(inbuf,smb_vwv7); memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1); + + if (lp_security() != SEC_SERVER && !doencrypt) + smb_apasslen = strlen(smb_apasswd); } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); - BOOL doencrypt = SMBENCRYPT(); char *p = smb_buf(inbuf); if (passlen1 != 24 && passlen2 != 24) @@ -369,10 +372,11 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) default code because Win95 will null terminate the password anyway - if passlen1>0 and passlen2>0 then its a NT box and its + if passlen1>0 and passlen2>0 then maybe its a NT box and its setting passlen2 to some random value which really stuffs things up. we need to fix that one. */ - if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24) { + if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && + passlen2 != 1) { passlen2 = 0; } /* we use the first password that they gave */ -- cgit From dc0d4d2efbd27c8acac9d8a87248a0ee07003acc Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 23 Oct 1996 19:12:47 +0000 Subject: Jeremy Removed AS_USER requirement for SMBulogoff. A valid TID (cnum) is not given for this call, which become_user needs if it is not to return an error. This fixes a specific case with NT4.0 which stops users attaching to a Samba server using a different account to the one they are logged in under. (This used to be commit c65a2cdd830bcda396ad6a0bd51a9b80c9d26a67) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2dc78e0176..c5a7a7ca02 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2975,7 +2975,7 @@ struct smb_message_struct {SMBecho,"SMBecho",reply_echo,0}, {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, - {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, AS_USER}, + {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, -- cgit From 08d00eb68ee93eaead0f3bbaabc3d89540e0818e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 24 Oct 1996 00:09:08 +0000 Subject: - added support for TMPDIR env variable - fixed fault.c for linux 2.1 - put back in the FIND_SELF failing code - cleaned up casts in encryption (This used to be commit 3af04f1580b2569c0a4f2549bf6352c7a25afa0d) --- source3/smbd/message.c | 2 +- source3/smbd/server.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 22523aad3b..2ef5b246c4 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -53,7 +53,7 @@ static void msg_deliver(void) } /* put it in a temporary file */ - sprintf(s,"/tmp/msg.XXXXXX"); + sprintf(s,"%s/msg.XXXXXX",tmpdir()); strcpy(name,(char *)mktemp(s)); fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c5a7a7ca02..8a6bef1525 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -564,7 +564,7 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) pstring syscmd; pstring outfile; - sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid()); + sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid()); sprintf(syscmd,"%s %s",df_command,path); standard_sub_basic(syscmd); -- cgit From 9bc6d7f4d638780c25f7eec8be2474537ed6dedc Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 25 Oct 1996 20:10:53 +0000 Subject: Changed definitions of prototypes to take uint16 vuid's not int uid's. Part of the change for Samba to return an index+offset into the registered users table rather than a raw unix uid. Added casts to required prototypes for function pointers in tables. jra@cygnus.com (This used to be commit ec2a3a1cf2220f6aace004d1808352f8e62a5616) --- source3/smbd/ipc.c | 138 ++++++++++++++++++++++++++--------------------------- 1 file changed, 69 insertions(+), 69 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8e81134de5..be500cb40d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -64,11 +64,11 @@ extern fstring local_machine; extern int Client; -static BOOL api_Unsupported(int cnum,int uid, char *param,char *data, +static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); -static BOOL api_TooSmall(int cnum,int uid, char *param,char *data, +static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); @@ -578,7 +578,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count)); } -static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data, +static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -651,7 +651,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data, /**************************************************************************** view list of all print jobs on all queues ****************************************************************************/ -static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data, +static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data, int mdrcnt, int mprcnt, char **rdata, char** rparam, int *rdata_len, int *rparam_len) @@ -948,7 +948,7 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) view list of servers available (or possibly domains). The info is extracted from lists saved by nmbd on the local host ****************************************************************************/ -static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, +static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) { @@ -1175,7 +1175,7 @@ static int fill_share_info(int cnum, int snum, int uLevel, return len; } -static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data, +static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1210,7 +1210,7 @@ static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data, /**************************************************************************** view list of shares available ****************************************************************************/ -static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data, +static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1274,7 +1274,7 @@ static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data, /**************************************************************************** get the time of day info ****************************************************************************/ -static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data, +static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1323,7 +1323,7 @@ static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data, /**************************************************************************** set the user password ****************************************************************************/ -static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data, +static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1365,7 +1365,7 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data, delete a print job Form: <> ****************************************************************************/ -static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data, +static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1427,7 +1427,7 @@ static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data, return(True); } -static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1498,7 +1498,7 @@ static int check_printjob_info(struct pack_desc* desc, return True; } -static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data, +static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1579,7 +1579,7 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data, GetWd(wd); unbecome_user(); - if (!become_user(Files[i].cnum,uid) || + if (!become_user(Files[i].cnum,vuid) || !become_service(Files[i].cnum,True)) break; @@ -1605,7 +1605,7 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data, /**************************************************************************** get info about the server ****************************************************************************/ -static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, +static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1712,7 +1712,7 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, /**************************************************************************** get info about the server ****************************************************************************/ -static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data, +static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1787,7 +1787,7 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data, #define USER_PRIV_USER 1 #define USER_PRIV_ADMIN 2 -static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data, +static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1927,7 +1927,7 @@ static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data, /******************************************************************* get groups that a user is a member of ******************************************************************/ -static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data, +static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1974,7 +1974,7 @@ static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data, } -static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data, +static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2047,7 +2047,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data, /**************************************************************************** api_WAccessGetUserPerms ****************************************************************************/ -static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data, +static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2075,7 +2075,7 @@ static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data, /**************************************************************************** api_WPrintJobEnumerate ****************************************************************************/ -static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2141,7 +2141,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data, return(True); } -static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2258,7 +2258,7 @@ static void fill_printdest_info(int cnum, int snum, int uLevel, } } -static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2317,7 +2317,7 @@ static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data, return(True); } -static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2375,7 +2375,7 @@ static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data, return(True); } -static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2420,7 +2420,7 @@ static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data, return(True); } -static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2466,7 +2466,7 @@ static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data, return(True); } -static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data, +static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2524,13 +2524,13 @@ struct { { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, - { NULL, NULL, -1, api_Unsupported } + { NULL, NULL, -1, (BOOL (*)())api_Unsupported } }; /**************************************************************************** handle remote api calls delivered to a named pipe already opened. ****************************************************************************/ -static int api_fd_reply(int cnum,int uid,char *outbuf, +static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, uint16 *setup,char *data,char *params, int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { @@ -2570,20 +2570,20 @@ static int api_fd_reply(int cnum,int uid,char *outbuf, rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - reply = api_fd_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt, + reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); if (rdata_len > mdrcnt || rparam_len > mprcnt) { - reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt, + reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); } /* if we get False back then it's actually unsupported */ if (!reply) - api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt, + api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); /* now send the reply */ @@ -2602,7 +2602,7 @@ static int api_fd_reply(int cnum,int uid,char *outbuf, /**************************************************************************** the buffer was too small ****************************************************************************/ -static BOOL api_TooSmall(int cnum,int uid, char *param,char *data, +static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2623,7 +2623,7 @@ static BOOL api_TooSmall(int cnum,int uid, char *param,char *data, /**************************************************************************** the request is not supported ****************************************************************************/ -static BOOL api_Unsupported(int cnum,int uid, char *param,char *data, +static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2651,38 +2651,38 @@ struct BOOL (*fn)(); int flags; } api_commands[] = { - {"RNetShareEnum", 0, api_RNetShareEnum,0}, - {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, - {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, - {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, - {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, - {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, - {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, - {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, - {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, - {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, - {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, - {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0}, - {"RDosPrintJobResume",83, api_RDosPrintJobDel,0}, - {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, - {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, - {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, - {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0}, - {"NetServerEnum", 104, api_RNetServerEnum,0}, - {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, - {"SetUserPassword", 115, api_SetUserPassword,0}, - {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0}, - {"PrintJobInfo", 147, api_PrintJobInfo,0}, - {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0}, - {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0}, - {"WPrintPortEnum", 207, api_WPrintPortEnum,0}, - {NULL, -1, api_Unsupported,0}}; + {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0}, + {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0}, + {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0}, + {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0}, + {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0}, + {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0}, + {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0}, + {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0}, + {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0}, + {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0}, + {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0}, + {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0}, + {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0}, + {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0}, + {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0}, + {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0}, + {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0}, + {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0}, + {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0}, + {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0}, + {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0}, + {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0}, + {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0}, + {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0}, + {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0}, + {NULL, -1, (BOOL (*)())api_Unsupported,0}}; /**************************************************************************** handle remote api calls ****************************************************************************/ -static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params, +static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { int api_command = SVAL(params,0); @@ -2707,21 +2707,21 @@ static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params, rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt, + reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); if (rdata_len > mdrcnt || rparam_len > mprcnt) { - reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt, + reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); } /* if we get False back then it's actually unsupported */ if (!reply) - api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt, + api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); @@ -2740,17 +2740,17 @@ static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params, /**************************************************************************** handle named pipe commands ****************************************************************************/ -static int named_pipe(int cnum,int uid, char *outbuf,char *name, +static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, uint16 *setup,char *data,char *params, int suwcnt,int tdscnt,int tpscnt, int msrcnt,int mdrcnt,int mprcnt) { if (strequal(name,"LANMAN")) - return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); + return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); if (strlen(name) < 1) - return(api_fd_reply(cnum,uid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt)); + return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt)); DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n", @@ -2772,7 +2772,7 @@ int reply_trans(char *inbuf,char *outbuf) int outsize = 0; int cnum = SVAL(inbuf,smb_tid); - int uid = SVAL(inbuf,smb_uid); + uint16 vuid = SVAL(inbuf,smb_uid); int tpscnt = SVAL(inbuf,smb_vwv0); int tdscnt = SVAL(inbuf,smb_vwv1); @@ -2860,7 +2860,7 @@ int reply_trans(char *inbuf,char *outbuf) if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) - outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, + outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); @@ -2869,7 +2869,7 @@ int reply_trans(char *inbuf,char *outbuf) if (setup) free(setup); if (close_on_completion) - close_cnum(cnum,uid); + close_cnum(cnum,vuid); if (one_way) return(-1); -- cgit From 8c5c55fea5656df4fcc241c1f989674cf1b54f9e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 25 Oct 1996 20:18:28 +0000 Subject: Core of the changes for returning smb_uid's. smb_uid's are now returned as an index plus offset into the valudated_users table. The offset (100) is added so that an smb_uid of zero becomes an invalid value. All access into the validated_users table are done by removing the offset and indexing into the table. Out of ranges return NULL. Causes accesses into the validated_users table to be more consistant and controlled. This change made due to the fact that the uid field is only 16 bits in the smb header and we need for this not to be a unix user id (which can ge 32 bits). jra@cygnus.com (This used to be commit ac265eff85a043e139b259e400fbbc444a94c97c) --- source3/smbd/password.c | 117 +++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 60 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index d17bb86be4..4f9f91d76d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -80,32 +80,18 @@ BOOL last_challenge(char *challenge) static user_struct *validated_users = NULL; static int num_validated_users = 0; -/**************************************************************************** -check if a uid has been validated, and return an index if it has. -1 if not -****************************************************************************/ -int valid_uid(int uid) -{ - int i; - if (uid == -1) return(-1); - - for (i=0;i= (uint16)num_validated_users) || + (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1)) return NULL; return &validated_users[vuid]; } @@ -113,56 +99,65 @@ user_struct *get_valid_user_struct(int uid) /**************************************************************************** invalidate a uid ****************************************************************************/ -void invalidate_uid(int uid) +void invalidate_vuid(uint16 vuid) { - int i; - for (i=0;iuid = -1; - vuser->gid = -1; - vuser->user_ngroups = 0; - if(vuser->user_groups && - (vuser->user_groups != (gid_t *)vuser->user_igroups)) - free(vuser->user_groups); - vuser->user_groups = NULL; - if(vuser->user_igroups) - free(vuser->user_igroups); - vuser->user_igroups = NULL; - } + user_struct *vuser = get_valid_user_struct(vuid); + if(vuser == 0) + return; + + vuser->uid = -1; + vuser->gid = -1; + vuser->user_ngroups = 0; + if(vuser->user_groups && + (vuser->user_groups != (gid_t *)vuser->user_igroups)) + free(vuser->user_groups); + vuser->user_groups = NULL; + if(vuser->user_igroups) + free(vuser->user_igroups); + vuser->user_igroups = NULL; } /**************************************************************************** return a validated username ****************************************************************************/ -char *validated_username(int vuid) +char *validated_username(uint16 vuid) { - return(validated_users[vuid].name); + user_struct *vuser = get_valid_user_struct(vuid); + if(vuser == 0) + return 0; + return(vuser->name); } /**************************************************************************** register a uid/name pair as being valid and that a valid password -has been given. +has been given. vuid is biased by an offset. This allows us to +tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -void register_uid(int uid,int gid, char *name,BOOL guest) +uint16 register_vuid(int uid,int gid, char *name,BOOL guest) { user_struct *vuser; - if (valid_uid(uid) >= 0) - return; - validated_users = (user_struct *)Realloc(validated_users, - sizeof(user_struct)* - (num_validated_users+1)); + int i; + for(i = 0; i < num_validated_users; i++) { + vuser = &validated_users[i]; + if( vuser->uid == uid ) + return i; /* User already validated */ + } + validated_users = (user_struct *)Realloc(validated_users, + sizeof(user_struct)* + (num_validated_users+1)); + if (!validated_users) { DEBUG(0,("Failed to realloc users struct!\n")); - return; + return UID_FIELD_INVALID; } vuser = &validated_users[num_validated_users]; + num_validated_users++; + vuser->uid = uid; vuser->gid = gid; vuser->guest = guest; @@ -180,8 +175,8 @@ void register_uid(int uid,int gid, char *name,BOOL guest) &vuser->user_groups); DEBUG(3,("uid %d registered to name %s\n",uid,name)); - - num_validated_users++; + + return (uint16)((num_validated_users - 1) + VUID_OFFSET); } @@ -944,7 +939,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) check for authority to login to a service with a given username/password ****************************************************************************/ BOOL authorise_login(int snum,char *user,char *password, int pwlen, - BOOL *guest,BOOL *force,int vuid) + BOOL *guest,BOOL *force,uint16 vuid) { BOOL ok = False; @@ -971,6 +966,8 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) { + user_struct *vuser = get_valid_user_struct(vuid); + /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { ok = password_ok(user,password, pwlen, NULL); @@ -978,11 +975,11 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, } /* check for a previously registered guest username */ - if (!ok && (vuid >= 0) && validated_users[vuid].guest) { - if (user_ok(validated_users[vuid].name,snum) && - password_ok(validated_users[vuid].name, password, pwlen, NULL)) { - strcpy(user, validated_users[vuid].name); - validated_users[vuid].guest = False; + if (!ok && (vuser != 0) && vuser->guest) { + if (user_ok(vuser->name,snum) && + password_ok(vuser->name, password, pwlen, NULL)) { + strcpy(user, vuser->name); + vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); ok = True; } @@ -1015,9 +1012,9 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check for a previously validated username/password pair */ if (!ok && !lp_revalidate(snum) && - (vuid >= 0) && !validated_users[vuid].guest && - user_ok(validated_users[vuid].name,snum)) { - strcpy(user,validated_users[vuid].name); + (vuser != 0) && !vuser->guest && + user_ok(vuser->name,snum)) { + strcpy(user,vuser->name); *guest = False; DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); ok = True; -- cgit From 2afda919632519da8ceaa39d114430638f3b6872 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 25 Oct 1996 20:30:22 +0000 Subject: Modified all references to uid to vuid. jra@cygnus.com (This used to be commit a2b07e5562dda87b42d9447c0b29a7815bd3178d) --- source3/smbd/reply.c | 55 +++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3d125a1186..4ba438f190 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -179,14 +179,11 @@ int reply_tcon(char *inbuf,char *outbuf) pstring dev; int connection_num; int outsize = 0; - int uid = SVAL(inbuf,smb_uid); - int vuid; + uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; *service = *user = *password = *dev = 0; - vuid = valid_uid(uid); - parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); connection_num = make_connection(service,user,password,pwlen,dev,vuid); @@ -215,8 +212,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring password; pstring devicename; int connection_num; - int uid = SVAL(inbuf,smb_uid); - int vuid; + uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); BOOL doencrypt = SMBENCRYPT(); @@ -224,9 +220,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) - close_cnum(SVAL(inbuf,smb_tid),uid); - - vuid = valid_uid(uid); + close_cnum(SVAL(inbuf,smb_tid),vuid); { char *path; @@ -317,8 +311,9 @@ reply to a session setup command ****************************************************************************/ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - int sess_uid; + uint16 sess_vuid; int gid; + int uid; int smb_bufsize; int smb_mpxmax; int smb_vc_num; @@ -336,7 +331,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) *smb_apasswd = 0; - sess_uid = SVAL(inbuf,smb_uid); smb_bufsize = SVAL(inbuf,smb_vwv2); smb_mpxmax = SVAL(inbuf,smb_vwv3); smb_vc_num = SVAL(inbuf,smb_vwv4); @@ -499,8 +493,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRSRV,ERRbadpw)); } gid = pw->pw_gid; - SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid); - SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid); + uid = pw->pw_uid; } if (guest && !computer_id) @@ -508,8 +501,11 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - register_uid(SVAL(inbuf,smb_uid),gid,user,guest); + sess_vuid = register_vuid(uid,gid,user,guest); + SSVAL(outbuf,smb_uid,sess_vuid); + SSVAL(inbuf,smb_uid,sess_vuid); + if (!done_sesssetup) maxxmit = MIN(maxxmit,smb_bufsize); @@ -1105,23 +1101,28 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) ****************************************************************************/ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) { - int uid = SVAL(inbuf,smb_uid); + uint16 vuid = SVAL(inbuf,smb_uid); + user_struct *vuser = get_valid_user_struct(vuid); - invalidate_uid(uid); + if(vuser == 0) { + DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); + } /* in user level security we are supposed to close any files open by this user */ - if (lp_security() != SEC_SHARE) { + if ((vuser != 0) && (lp_security() != SEC_SHARE)) { int i; for (i=0;iuid && Files[i].open) { close_file(i); } } + invalidate_vuid(vuid); + set_message(outbuf,2,0,True); - DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid)); + DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid)); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2101,11 +2102,12 @@ int reply_unlock(char *inbuf,char *outbuf) ****************************************************************************/ int reply_tdis(char *inbuf,char *outbuf) { - int cnum, uid; + int cnum; int outsize = set_message(outbuf,0,0,True); - + uint16 vuid; + cnum = SVAL(inbuf,smb_tid); - uid = SVAL(inbuf,smb_uid); + vuid = SVAL(inbuf,smb_uid); if (!OPEN_CNUM(cnum)) { DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum)); @@ -2114,7 +2116,7 @@ int reply_tdis(char *inbuf,char *outbuf) Connections[cnum].used = False; - close_cnum(cnum,uid); + close_cnum(cnum,vuid); DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum)); @@ -2259,13 +2261,14 @@ int reply_printclose(char *inbuf,char *outbuf) ****************************************************************************/ int reply_printqueue(char *inbuf,char *outbuf) { - int cnum, uid; + int cnum; int outsize = set_message(outbuf,2,3,True); int max_count = SVAL(inbuf,smb_vwv0); int start_index = SVAL(inbuf,smb_vwv1); + uint16 vuid; cnum = SVAL(inbuf,smb_tid); - uid = SVAL(inbuf,smb_uid); + vuid = SVAL(inbuf,smb_uid); /* allow checking the queue for anyone */ #if 0 @@ -2301,7 +2304,7 @@ int reply_printqueue(char *inbuf,char *outbuf) DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum)); } - if (!become_user(cnum,uid)) + if (!become_user(cnum,vuid)) return(ERROR(ERRSRV,ERRinvnid)); { -- cgit From ddc18f418382755106cadf91110e1bc5e6223346 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 25 Oct 1996 20:42:46 +0000 Subject: Modified all references to smb_uid to be vuid's. jra@cygnus.com (This used to be commit 5056672a3ad579fa900411534d7548a6fabc729f) --- source3/smbd/server.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8a6bef1525..adea09f18f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1895,7 +1895,7 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups, /**************************************************************************** make a connection to a service ****************************************************************************/ -int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid) +int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid) { int cnum; int snum; @@ -2015,6 +2015,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->admin_user = False; pcon->force_user = force; + pcon->vuid = vuid; pcon->uid = pass->pw_uid; pcon->gid = pass->pw_gid; pcon->num_files_open = 0; @@ -2103,7 +2104,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de smbrun(cmd,NULL,False); } - if (!become_user(cnum,pcon->uid)) + if (!become_user(cnum,pcon->vuid)) { DEBUG(0,("Can't become connected user!\n")); pcon->open = False; @@ -2598,7 +2599,7 @@ static void close_open_files(int cnum) /**************************************************************************** close a cnum ****************************************************************************/ -void close_cnum(int cnum, int uid) +void close_cnum(int cnum, uint16 vuid) { DirCacheFlush(SNUM(cnum)); @@ -2626,7 +2627,7 @@ void close_cnum(int cnum, int uid) dptr_closecnum(cnum); /* execute any "postexec = " line */ - if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid)) + if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid)) { pstring cmd; strcpy(cmd,lp_postexec(SNUM(cnum))); @@ -3130,14 +3131,14 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { int cnum = SVAL(inbuf,smb_tid); int flags = smb_messages[match].flags; - int uid = SVAL(inbuf,smb_uid); + uint16 session_tag = SVAL(inbuf,smb_uid); /* does this protocol need to be run as root? */ if (!(flags & AS_USER)) unbecome_user(); /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(cnum,uid)) { + if ((flags & AS_USER) && !become_user(cnum,session_tag)) { if (flags & AS_GUEST) flags &= ~AS_USER; else -- cgit From 697e46373c8fa7b07234f6611c93cf25fe9733ed Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 25 Oct 1996 20:50:31 +0000 Subject: Changed become_user to take a vuid as second arg. Consistent with other changes to make smb_uid an index+offset into the validated_users table. jra@cygnus.com (This used to be commit 89675f8ae8f136fb587690b137f4413607d30c14) --- source3/smbd/uid.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index f7005b53cf..4fa0ed89da 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -204,13 +204,13 @@ static BOOL check_user_ok(int cnum,user_struct *vuser,int snum) /**************************************************************************** become the user of a connection number ****************************************************************************/ -BOOL become_user(int cnum, int uid) +BOOL become_user(int cnum, uint16 vuid) { - user_struct *vuser; + user_struct *vuser = get_valid_user_struct(vuid); int snum,gid; - int id = uid; + int uid; - if (current_user.cnum == cnum && current_user.id == id) { + if (current_user.cnum == cnum && vuser != 0 && current_user.id == vuser->uid) { DEBUG(4,("Skipping become_user - already user\n")); return(True); } @@ -226,7 +226,7 @@ BOOL become_user(int cnum, int uid) if (Connections[cnum].force_user || lp_security() == SEC_SHARE || - !(vuser = get_valid_user_struct(uid)) || + !(vuser) || (vuser->guest) || !check_user_ok(cnum,vuser,snum)) { uid = Connections[cnum].uid; gid = Connections[cnum].gid; @@ -235,7 +235,7 @@ BOOL become_user(int cnum, int uid) current_user.ngroups = Connections[cnum].ngroups; } else { if (!vuser) { - DEBUG(2,("Invalid vuid used %d\n",uid)); + DEBUG(2,("Invalid vuid used %d\n",vuid)); return(False); } uid = vuser->uid; @@ -266,7 +266,7 @@ BOOL become_user(int cnum, int uid) } current_user.cnum = cnum; - current_user.id = id; + current_user.id = uid; DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); -- cgit From 7da995a1dd352712f1b5d8ad2545408281265b0f Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sat, 9 Nov 1996 01:56:20 +0000 Subject: Set num_validated_users to zero if Realloc fails. (This used to be commit 57121e609e927d16389793c7969f5fb944c7669d) --- source3/smbd/password.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 4f9f91d76d..9b06e0dcb5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -152,6 +152,7 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) if (!validated_users) { DEBUG(0,("Failed to realloc users struct!\n")); + num_validated_users = 0; return UID_FIELD_INVALID; } -- cgit From b02557f80e80e6fc270f253ba139ee8e4903a459 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 3 Dec 1996 19:05:27 +0000 Subject: Added Volkers fix for bundary condition. Needed as word alignment wasn't being taken into account in space calculations. (This used to be commit 2fd77d66c0e93b381466e40bd34680468ac8ec77) --- source3/smbd/trans2.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 53af9acbf5..3b4cdeb1c6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -68,16 +68,19 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, } /* Space is bufsize minus Netbios over TCP header minus SMB header */ - /* The + 1 is to align the param and data bytes on an even byte + /* The alignment_offset is to align the param and data bytes on an even byte boundary. NT 4.0 Beta needs this to work correctly. */ useable_space = bufsize - ((smb_buf(outbuf)+alignment_offset) - outbuf); - useable_space = MIN(useable_space, maxxmit); /* XXX is this needed? correct? */ + /* useable_space can never be more than maxxmit minus the + alignment offset. */ + useable_space = MIN(useable_space, maxxmit - alignment_offset); while( params_to_send || data_to_send) { /* Calculate whether we will totally or partially fill this packet */ total_sent_thistime = params_to_send + data_to_send + alignment_offset; - total_sent_thistime = MIN(total_sent_thistime, useable_space); + /* We can never send more than maxxmit */ + total_sent_thistime = MIN(total_sent_thistime, maxxmit); set_message(outbuf, 10, total_sent_thistime, True); -- cgit From b719173ecb7eeff518d27952c523a64bcbcf0fb2 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 10 Dec 1996 17:49:11 +0000 Subject: Added in veto files parameter create by Whistle. jra@cygnus.com (This used to be commit d5659df9c23822766501397b8fbbffbce6842ea7) --- source3/smbd/dir.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 73c4afd77e..f3c1ae020e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -533,6 +533,9 @@ void *OpenDir(char *name) while ((n = readdirname(p))) { int l = strlen(n)+1; + /* If it's a vetoed file, pretend it doesn't even exist */ + if(is_vetoed_name(n)) + continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; -- cgit From 53a9501444e3e00797e464ad4550db3e99921c87 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 10 Dec 1996 17:58:11 +0000 Subject: Fixed quota support for FreeBsd. jra@cygnus.com (This used to be commit d1009c53517c3cfc536cb6436a702441c27be448) --- source3/smbd/quotas.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 6ba20faa6c..3e22e26ba3 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -376,8 +376,12 @@ DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n" #else +#ifdef __FreeBSD__ +#include +#else #include #include +#endif /**************************************************************************** try to get the disk space from disk quotas - default version @@ -389,9 +393,11 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) char dev_disk[256]; struct dqblk D; struct stat S; +#ifndef __FreeBSD__ /* find the block device file */ if ((stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); +#endif euser_id = geteuid(); @@ -399,12 +405,17 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) /* for HPUX, real uid must be same as euid to execute quotactl for euid */ user_id = getuid(); setresuid(euser_id,-1,-1); -#endif r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); - #ifdef USE_SETRES if (setresuid(user_id,-1,-1)) DEBUG(5,("Unable to reset uid to %d\n", user_id)); +#else +#if defined(__FreeBSD__) + r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); +#else + r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); #endif +#endif + /* Use softlimit to determine disk space, except when it has been exceeded */ *bsize = 1024; if (r) @@ -420,8 +431,11 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) if (D.dqb_bsoftlimit==0) return(False); /* Use softlimit to determine disk space, except when it has been exceeded */ - if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curfiles>D.dqb_fsoftlimit)) - { + if ((D.dqb_curblocks>D.dqb_bsoftlimit) +#if !defined(__FreeBSD__) +||(D.dqb_curfiles>D.dqb_fsoftlimit)) +#endif + ) { *dfree = 0; *dsize = D.dqb_curblocks; } -- cgit From d68e27a3bc08e9b0d44d6fe863a45a4830102ed3 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 10 Dec 1996 18:00:22 +0000 Subject: Added -f lockfile support. jra@cygnus.com (This used to be commit 84024a3df37df48865d6a53fbba0716d62819743) --- source3/smbd/server.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index adea09f18f..29360c40b3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -30,6 +30,9 @@ char *InBuffer = NULL; char *OutBuffer = NULL; char *last_inbuf = NULL; +int am_parent = 1; +int atexit_set = 0; + BOOL share_mode_pending = False; /* the last message the was processed */ @@ -87,7 +90,20 @@ static int find_free_connection(int hash); #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0) #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0) - +/**************************************************************************** + when exiting, take the whole family +****************************************************************************/ +void *dflt_sig(void) +{ + exit_server("caught signal"); +} +/**************************************************************************** + Send a SIGTERM to our process group. +*****************************************************************************/ +void killkids(void) +{ + if(am_parent) kill(0,SIGTERM); +} /**************************************************************************** change a dos mode to a unix mode @@ -685,6 +701,12 @@ BOOL check_name(char *name,int cnum) errno = 0; + if( is_vetoed_path(name)) + { + DEBUG(5,("file path name %s vetoed\n",name)); + return(0); + } + ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum))); if (!ret) DEBUG(5,("check_name on %s failed\n",name)); @@ -1673,6 +1695,9 @@ static BOOL open_sockets(BOOL is_daemon,int port) return False; } + if(atexit_set == 0) + atexit(&killkids); + /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); @@ -1707,6 +1732,7 @@ static BOOL open_sockets(BOOL is_daemon,int port) /* close our standard file descriptors */ close_low_fds(); + am_parent = 0; set_socket_options(Client,"SO_KEEPALIVE"); set_socket_options(Client,user_socket_options); @@ -3584,6 +3610,7 @@ static void usage(char *pname) int port = SMB_PORT; int opt; extern char *optarg; + char pidFile[100] = { 0 }; #ifdef NEED_AUTH_PARAMETERS set_auth_parameters(argc,argv); @@ -3615,6 +3642,7 @@ static void usage(char *pname) #endif fault_setup(exit_server); + signal(SIGTERM , SIGNAL_CAST dflt_sig); /* we want total control over the permissions on created files, so set our umask to 0 */ @@ -3631,9 +3659,12 @@ static void usage(char *pname) argc--; } - while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF) + while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF) switch (opt) { + case 'f': + strncpy(pidFile, optarg, sizeof(pidFile)); + break; case 'O': strcpy(user_socket_options,optarg); break; @@ -3730,6 +3761,31 @@ static void usage(char *pname) become_daemon(); } + if (*pidFile) + { + int fd; + char buf[20]; + + if ((fd = open(pidFile, + O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) + { + DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno))); + exit(1); + } + if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False) + { + DEBUG(0,("ERROR: smbd is already running\n")); + exit(1); + } + sprintf(buf, "%u\n", (unsigned int) getpid()); + if (write(fd, buf, strlen(buf)) < 0) + { + DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno))); + exit(1); + } + /* Leave pid file open & locked for the duration... */ + } + if (!open_sockets(is_daemon,port)) exit(1); -- cgit From d613892674d40962880356ac4915d7321ae2573a Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 2 Jan 1997 04:04:49 +0000 Subject: JHT ==> Added extensions for PAM (Pluggable Authentication Module) support for Linux and other little beasties that use PAM. Source: ftp.redhat.com/pub/Incoming/samba-1.9.16p9.src.rpm Originally from RedHat modifications to samba-1.9.15p8 (This used to be commit 79145bad569c71a7485b40a74e91eb93b52d6392) --- source3/smbd/password.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9b06e0dcb5..8c1a1026cc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -312,6 +312,103 @@ static void update_protected_database( char *user, BOOL result) } +#ifdef USE_PAM +/******************************************************************* +check on PAM authentication +********************************************************************/ + +/* We first need some helper functions */ +#include +/* Static variables used to communicate between the conversation function + * and the server_login function + */ +static char *PAM_username; +static char *PAM_password; + +/* PAM conversation function + * Here we assume (for now, at least) that echo on means login name, and + * echo off means password. + */ +static int PAM_conv (int num_msg, + const struct pam_message **msg, + struct pam_response **resp, + void *appdata_ptr) { + int count = 0, replies = 0; + struct pam_response *reply = NULL; + int size = sizeof(struct pam_response); + + #define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \ + if (!reply) return PAM_CONV_ERR; \ + size += sizeof(struct pam_response) + #define COPY_STRING(s) (s) ? strdup(s) : NULL + + for (count = 0; count < num_msg; count++) { + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + GET_MEM; + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies++].resp = COPY_STRING(PAM_username); + /* PAM frees resp */ + break; + case PAM_PROMPT_ECHO_OFF: + GET_MEM; + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies++].resp = COPY_STRING(PAM_password); + /* PAM frees resp */ + break; + case PAM_TEXT_INFO: + /* ignore it... */ + break; + case PAM_ERROR_MSG: + default: + /* Must be an error of some sort... */ + free (reply); + return PAM_CONV_ERR; + } + } + if (reply) *resp = reply; + return PAM_SUCCESS; +} +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + + +static BOOL pam_auth(char *this_user,char *password) +{ + pam_handle_t *pamh; + int pam_error; + + /* Now use PAM to do authentication. For now, we won't worry about + * session logging, only authentication. Bail out if there are any + * errors. Since this is a limited protocol, and an even more limited + * function within a server speaking this protocol, we can't be as + * verbose as would otherwise make sense. + * Query: should we be using PAM_SILENT to shut PAM up? + */ + #define PAM_BAIL if (pam_error != PAM_SUCCESS) { \ + pam_end(pamh, 0); return False; \ + } + PAM_password = password; + PAM_username = this_user; + pam_error = pam_start("samba", this_user, &PAM_conversation, &pamh); + PAM_BAIL; + pam_error = pam_authenticate(pamh, 0); + PAM_BAIL; + /* It is not clear to me that account management is the right thing + * to do, but it is not clear that it isn't, either. This can be + * removed if no account management should be done. Alternately, + * put a pam_allow.so entry in /etc/pam.conf for account handling. */ + pam_error = pam_acct_mgmt(pamh, 0); + PAM_BAIL; + pam_end(pamh, PAM_SUCCESS); + /* If this point is reached, the user has been authenticated. */ + return(True); +} +#endif + + #ifdef AFS_AUTH /******************************************************************* check on AFS authentication @@ -513,6 +610,11 @@ core of password checking routine ****************************************************************************/ BOOL password_check(char *password) { + +#ifdef USE_PAM + if (pam_auth(this_user,password)) return(True); +#endif + #ifdef AFS_AUTH if (afs_auth(this_user,password)) return(True); #endif -- cgit From 8bc7d6bebd4fcf8c95cb6d58da14404a5e46de91 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 9 Jan 1997 18:02:17 +0000 Subject: Makefile: Changes to split Solaris into Solaris2.3 and previous, and 2.4 and after from Paul Eggert. Makefile: Added AMIGA changes from Rask Ingemann Lambertsen . charset.c: Patch for Western European Languages from Josef Hinteregger charset.h: Patch for Western European Languages from Josef Hinteregger clitar.c: Patch to re-sync after read fail from (lost contributor name, sorry). includes.h: Patch for AMIGA from Rask Ingemann Lambertsen includes.h: Patch for SunOS atexit by Jeremy (jra@cygnus.com) interface.c: Patch for AMIGA from Rask Ingemann Lambertsen kanji.h: Patch for Western European Languages from Josef Hinteregger locking.c: Patch to fix file locking from Jeremy (jra@cygnus.com) locking.c: Patch to add granularity of lock files to usec by Jeremy (jra@cygnus.com) pipes.c: Patch to fix file locking from Jeremy (jra@cygnus.com) proto.h: Patch to fix file locking from Jeremy (jra@cygnus.com) reply.c: Patch to fix file locking from Jeremy (jra@cygnus.com) server.c: Patch to fix file locking from Jeremy (jra@cygnus.com) server.c: Patch for FAST_SHARE_MODE fix from (lost contributor name, sorry). smb.h: Patch to fix file locking from Jeremy (jra@cygnus.com) smb.h: Patch to add granularity of lock files to usec by Jeremy (jra@cygnus.com) status.c: Patch to fix file locking from Jeremy (jra@cygnus.com) statuc.c: Patch to add granularity of lock files to usec by Jeremy (jra@cygnus.com) system.c: Patch for Western European Languages from Josef Hinteregger trans2.c: Patch to fix file locking from Jeremy (jra@cygnus.com) trans2.c: Patch to fix volume name reported to Win95 from Jeremy (jra@cygnus.com) util.c: Patch for Western European Languages from Josef Hinteregger util.c: Patch to fix client_name from continuously returning UNKNOWN (from various contributors). version.h: Update to 1.9.16p10. (This used to be commit 03d28fa32eb094affa33133ebe2602fdb70f6361) --- source3/smbd/pipes.c | 2 +- source3/smbd/reply.c | 40 ++--- source3/smbd/server.c | 412 +++++++++++++++++++++++++++++++++++++++++--------- source3/smbd/trans2.c | 24 ++- 4 files changed, 368 insertions(+), 110 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index ffa46083c3..cb498a6195 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -131,7 +131,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); - if (fstat(Files[fnum].fd,&sbuf) != 0) { + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4ba438f190..812618b2c7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -982,7 +982,7 @@ int reply_open(char *inbuf,char *outbuf) if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); - if (fstat(Files[fnum].fd,&sbuf) != 0) { + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1065,7 +1065,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); - if (fstat(Files[fnum].fd,&sbuf) != 0) { + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1164,7 +1164,7 @@ int reply_mknew(char *inbuf,char *outbuf) if (!check_name(fname,cnum)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode); + open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1177,7 +1177,7 @@ int reply_mknew(char *inbuf,char *outbuf) } DEBUG(2,("new file %s\n",fname)); - DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd,fnum,cnum,createmode,unixmode)); + DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); return(outsize); } @@ -1212,7 +1212,7 @@ int reply_ctemp(char *inbuf,char *outbuf) strcpy(fname2,(char *)mktemp(fname)); - open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode); + open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1227,7 +1227,7 @@ int reply_ctemp(char *inbuf,char *outbuf) } DEBUG(2,("created temp file %s\n",fname2)); - DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd,fnum,cnum,createmode,unixmode)); + DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); return(outsize); } @@ -1385,7 +1385,7 @@ int reply_readbraw(char *inbuf, char *outbuf) } else { - fd = Files[fnum].fd; + fd = Files[fnum].fd_ptr->fd; fname = Files[fnum].name; } @@ -1397,7 +1397,7 @@ int reply_readbraw(char *inbuf, char *outbuf) if (size < sizeneeded) { struct stat st; - if (fstat(Files[fnum].fd,&st) == 0) + if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) size = st.st_size; if (!Files[fnum].can_write) Files[fnum].size = size; @@ -1661,7 +1661,7 @@ int reply_writebraw(char *inbuf,char *outbuf) tcount,nwritten,numtowrite)); } - nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0, + nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0, startpos+nwritten); total_written += nwritten; @@ -1781,7 +1781,7 @@ int reply_write(char *inbuf,char *outbuf,int dum1,int dum2) zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) - nwritten = set_filelen(Files[fnum].fd, startpos); + nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos); else nwritten = write_file(fnum,data,numtowrite); @@ -1894,7 +1894,7 @@ int reply_lseek(char *inbuf,char *outbuf) umode = SEEK_SET; break; } - res = lseek(Files[fnum].fd,startpos,umode); + res = lseek(Files[fnum].fd_ptr->fd,startpos,umode); Files[fnum].pos = res; outsize = set_message(outbuf,2,0,True); @@ -1983,7 +1983,7 @@ int reply_close(char *inbuf,char *outbuf) return(ERROR(eclass,err)); DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - timestring(),Files[fnum].fd,fnum,cnum, + timestring(),Files[fnum].fd_ptr->fd,fnum,cnum, Connections[cnum].num_files_open)); return(outsize); @@ -2059,7 +2059,7 @@ int reply_lock(char *inbuf,char *outbuf) count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); - DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count)); + DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); @@ -2091,7 +2091,7 @@ int reply_unlock(char *inbuf,char *outbuf) if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); - DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count)); + DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); return(outsize); } @@ -2214,7 +2214,7 @@ int reply_printopen(char *inbuf,char *outbuf) return(ERROR(ERRDOS,ERRnoaccess)); open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC, - unix_mode(cnum,0)); + unix_mode(cnum,0), 0); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2225,7 +2225,7 @@ int reply_printopen(char *inbuf,char *outbuf) outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); - DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum)); + DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum)); return(outsize); } @@ -2250,7 +2250,7 @@ int reply_printclose(char *inbuf,char *outbuf) close_file(fnum); - DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum)); + DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); return(outsize); } @@ -2678,11 +2678,11 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, } if ((ofun&3) == 1) { - lseek(Files[fnum2].fd,0,SEEK_END); + lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END); } if (st.st_size) - ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0); + ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); close_file(fnum1); close_file(fnum2); @@ -3220,7 +3220,7 @@ int reply_getattrE(char *inbuf,char *outbuf) CHECK_ERROR(fnum); /* Do an fstat on this file */ - if(fstat(Files[fnum].fd, &sbuf)) + if(fstat(Files[fnum].fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(cnum,Files[fnum].name,&sbuf); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 29360c40b3..75e7279e6d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -58,6 +58,13 @@ extern pstring user_socket_options; connection_struct Connections[MAX_CONNECTIONS]; files_struct Files[MAX_OPEN_FILES]; +/* + * Indirection for file fd's. Needed as POSIX locking + * is based on file/process, not fd/process. + */ +file_fd_struct FileFd[MAX_OPEN_FILES]; +int max_file_fd_used = 0; + extern int Protocol; int maxxmit = BUFFER_SIZE; @@ -731,17 +738,182 @@ static void check_for_pipe(char *fname) } } +/**************************************************************************** +fd support routines - attempt to do a sys_open +****************************************************************************/ + +int fd_attempt_open(char *fname, int flags, int mode) +{ + int fd = sys_open(fname,flags,mode); + + /* Fix for files ending in '.' */ + if((fd == -1) && (errno == ENOENT) && + (strchr(fname,'.')==NULL)) + { + strcat(fname,"."); + fd = sys_open(fname,flags,mode); + } + +#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) + if ((fd == -1) && (errno == ENAMETOOLONG)) + { + int max_len; + char *p = strrchr(fname, '/'); + + if (p == fname) /* name is "/xxx" */ + { + max_len = pathconf("/", _PC_NAME_MAX); + p++; + } + else if ((p == NULL) || (p == fname)) + { + p = fname; + max_len = pathconf(".", _PC_NAME_MAX); + } + else + { + *p = '\0'; + max_len = pathconf(fname, _PC_NAME_MAX); + *p = '/'; + p++; + } + if (strlen(p) > max_len) + { + char tmp = p[max_len]; + + p[max_len] = '\0'; + if ((fd = sys_open(fname,flags,mode)) == -1) + p[max_len] = tmp; + } + } +#endif + return fd; +} + +/**************************************************************************** +fd support routines - attempt to find an already open file by dev +and inode - increments the ref_count of the returned file_fd_struct *. +****************************************************************************/ +file_fd_struct *fd_get_already_open(struct stat *sbuf) +{ + int i; + file_fd_struct *fd_ptr; + + if(sbuf == 0) + return 0; + + for(i = 0; i <= max_file_fd_used; i++) { + fd_ptr = &FileFd[i]; + if((fd_ptr->ref_count > 0) && + (((int32)sbuf->st_dev) == fd_ptr->dev) && + (((int32)sbuf->st_ino) == fd_ptr->inode)) { + fd_ptr->ref_count++; + DEBUG(3, + ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n", + i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count)); + return fd_ptr; + } + } + return 0; +} + +/**************************************************************************** +fd support routines - attempt to find a empty slot in the FileFd array. +Increments the ref_count of the returned entry. +****************************************************************************/ +file_fd_struct *fd_get_new() +{ + int i; + file_fd_struct *fd_ptr; + + for(i = 0; i < MAX_OPEN_FILES; i++) { + fd_ptr = &FileFd[i]; + if(fd_ptr->ref_count == 0) { + fd_ptr->dev = (int32)-1; + fd_ptr->inode = (int32)-1; + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; + fd_ptr->ref_count++; + /* Increment max used counter if neccessary, cuts down + on search time when re-using */ + if(i > max_file_fd_used) + max_file_fd_used = i; + DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n", + i, fd_ptr->dev, fd_ptr->inode)); + return fd_ptr; + } + } + DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\ +n")); + return 0; +} + +/**************************************************************************** +fd support routines - attempt to re-open an already open fd as O_RDWR. +Save the already open fd (we cannot close due to POSIX file locking braindamage. +****************************************************************************/ + +void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) +{ + int fd = sys_open( fname, O_RDWR, mode); + + if(fd == -1) + return; + + if(fd_ptr->real_open_flags == O_RDONLY) + fd_ptr->fd_readonly = fd_ptr->fd; + if(fd_ptr->real_open_flags == O_WRONLY) + fd_ptr->fd_writeonly = fd_ptr->fd; + + fd_ptr->fd = fd; + fd_ptr->real_open_flags = O_RDWR; +} + +/**************************************************************************** +fd support routines - attempt to close the file referenced by this fd. +Decrements the ref_count and returns it. +****************************************************************************/ +int fd_attempt_close(file_fd_struct *fd_ptr) +{ + DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", + fd_ptr - &FileFd[0], + fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, + fd_ptr->real_open_flags, + fd_ptr->ref_count)); + if(fd_ptr->ref_count > 0) { + fd_ptr->ref_count--; + if(fd_ptr->ref_count == 0) { + if(fd_ptr->fd != -1) + close(fd_ptr->fd); + if(fd_ptr->fd_readonly != -1) + close(fd_ptr->fd_readonly); + if(fd_ptr->fd_writeonly != -1) + close(fd_ptr->fd_writeonly); + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; + fd_ptr->dev = -1; + fd_ptr->inode = -1; + } + } + return fd_ptr->ref_count; +} /**************************************************************************** open a file ****************************************************************************/ -void open_file(int fnum,int cnum,char *fname1,int flags,int mode) +void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) { extern struct current_user current_user; pstring fname; + struct stat statbuf; + file_fd_struct *fd_ptr; Files[fnum].open = False; - Files[fnum].fd = -1; + Files[fnum].fd_ptr = 0; errno = EPERM; strcpy(fname,fname1); @@ -771,10 +943,104 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode) sys_unlink(fname); #endif + /* + * Ensure we have a valid struct stat so we can search the + * open fd table. + */ + if(sbuf == 0) { + if(stat(fname, &statbuf) < 0) { + if(errno != ENOENT) { + DEBUG(3,("Error doing stat on file %s (%s)\n", + fname,strerror(errno))); + + check_for_pipe(fname); + return; + } + sbuf = 0; + } else { + sbuf = &statbuf; + } + } - Files[fnum].fd = sys_open(fname,flags,mode); + /* + * Check to see if we have this file already + * open. If we do, just use the already open fd and increment the + * reference count (fd_get_already_open increments the ref_count). + */ + if((fd_ptr = fd_get_already_open(sbuf))!= 0) { + + int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); + + /* File was already open. */ + if((flags & O_CREAT) && (flags & O_EXCL)) { + fd_ptr->ref_count--; + errno = EEXIST; + return; + } + + /* + * If not opened O_RDWR try + * and do that here - a chmod may have been done + * between the last open and now. + */ + if(fd_ptr->real_open_flags != O_RDWR) + fd_attempt_reopen(fname, mode, fd_ptr); + + /* + * Ensure that if we wanted write access + * it has been opened for write, and if we wanted read it + * was open for read. + */ + if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) || + ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) || + ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { + DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", + fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); + check_for_pipe(fname); + fd_ptr->ref_count--; + return; + } + + /* + * If O_TRUNC was set, ensure we truncate the file. + * open_file_shared explicitly clears this flag before + * calling open_file, so we can safely do this here. + */ + if(flags & O_TRUNC) + ftruncate(fd_ptr->fd, 0); + + } else { + int open_flags; + /* We need to allocate a new file_fd_struct (this increments the + ref_count). */ + if((fd_ptr = fd_get_new()) == 0) + return; + /* + * Whatever the requested flags, attempt read/write access, + * as we don't know what flags future file opens may require. + * If this fails, try again with the required flags. + * Even if we open read/write when only read access was + * requested the setting of the can_write flag in + * the file_struct will protect us from errant + * write requests. We never need to worry about O_APPEND + * as this is not set anywhere in Samba. + */ + fd_ptr->real_open_flags = O_RDWR; + /* Set the flags as needed without the read/write modes. */ + open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); + fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); + if((fd_ptr->fd == -1) && (errno == EACCES)) { + if(flags & O_WRONLY) { + fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode); + fd_ptr->real_open_flags = O_WRONLY; + } else { + fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode); + fd_ptr->real_open_flags = O_RDONLY; + } + } + } - if ((Files[fnum].fd>=0) && + if ((fd_ptr->fd >=0) && Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) { pstring dname; int dum1,dum2,dum3; @@ -784,72 +1050,47 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode) if (p) *p = 0; if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(cnum))) { - close(Files[fnum].fd); - Files[fnum].fd = -1; - sys_unlink(fname); + fd_attempt_close(fd_ptr); + Files[fnum].fd_ptr = 0; + if(fd_ptr->ref_count == 0) + sys_unlink(fname); errno = ENOSPC; return; } } - - /* Fix for files ending in '.' */ - if((Files[fnum].fd == -1) && (errno == ENOENT) && - (strchr(fname,'.')==NULL)) - { - strcat(fname,"."); - Files[fnum].fd = sys_open(fname,flags,mode); - } - -#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) - if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG)) - { - int max_len; - char *p = strrchr(fname, '/'); - - if (p == fname) /* name is "/xxx" */ - { - max_len = pathconf("/", _PC_NAME_MAX); - p++; - } - else if ((p == NULL) || (p == fname)) - { - p = fname; - max_len = pathconf(".", _PC_NAME_MAX); - } - else - { - *p = '\0'; - max_len = pathconf(fname, _PC_NAME_MAX); - *p = '/'; - p++; - } - if (strlen(p) > max_len) - { - char tmp = p[max_len]; - - p[max_len] = '\0'; - if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1) - p[max_len] = tmp; - } - } -#endif - - if (Files[fnum].fd < 0) + if (fd_ptr->fd < 0) { DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); + /* Ensure the ref_count is decremented. */ + fd_attempt_close(fd_ptr); check_for_pipe(fname); return; } - if (Files[fnum].fd >= 0) + if (fd_ptr->fd >= 0) { - struct stat st; + if(sbuf == 0) { + /* Do the fstat */ + if(fstat(fd_ptr->fd, &statbuf) == -1) { + /* Error - backout !! */ + DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", + fd_ptr->fd, fname,strerror(errno))); + /* Ensure the ref_count is decremented. */ + fd_attempt_close(fd_ptr); + return; + } + sbuf = &statbuf; + } + /* Set the correct entries in fd_ptr. */ + fd_ptr->dev = (int32)sbuf->st_dev; + fd_ptr->inode = (int32)sbuf->st_ino; + + Files[fnum].fd_ptr = fd_ptr; Connections[cnum].num_files_open++; - fstat(Files[fnum].fd,&st); - Files[fnum].mode = st.st_mode; - Files[fnum].open_time = time(NULL); + Files[fnum].mode = sbuf->st_mode; + GetTimeOfDay(&Files[fnum].open_time); Files[fnum].uid = current_user.id; Files[fnum].size = 0; Files[fnum].pos = -1; @@ -911,7 +1152,7 @@ sync a file void sync_file(int fnum) { #ifndef NO_FSYNC - fsync(Files[fnum].fd); + fsync(Files[fnum].fd_ptr->fd); #endif } @@ -961,7 +1202,7 @@ close a file - possibly invalidating the read prediction void close_file(int fnum) { int cnum = Files[fnum].cnum; - invalidate_read_prediction(Files[fnum].fd); + invalidate_read_prediction(Files[fnum].fd_ptr->fd); Files[fnum].open = False; Connections[cnum].num_files_open--; if(Files[fnum].wbmpx_ptr) @@ -981,7 +1222,7 @@ void close_file(int fnum) if (lp_share_modes(SNUM(cnum))) del_share_mode(fnum); - close(Files[fnum].fd); + fd_attempt_close(Files[fnum].fd_ptr); /* NT uses smbclose to start a print - weird */ if (Files[fnum].print_file) @@ -1081,7 +1322,7 @@ static void truncate_unless_locked(int fnum, int cnum) unix_ERR_code = ERRlock; } else - ftruncate(Files[fnum].fd,0); + ftruncate(Files[fnum].fd_ptr->fd,0); } } @@ -1101,7 +1342,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int share_pid=0; Files[fnum].open = False; - Files[fnum].fd = -1; + Files[fnum].fd_ptr = 0; /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) { @@ -1208,10 +1449,10 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,mode)); - open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode); + open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,&sbuf); if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) { flags = O_RDONLY; - open_file(fnum,cnum,fname,flags,mode); + open_file(fnum,cnum,fname,flags,mode,&sbuf); } if (Files[fnum].open) { @@ -1282,7 +1523,7 @@ int seek_file(int fnum,int pos) if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum)) offset = 3; - Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset; + Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset; return(Files[fnum].pos); } @@ -1295,7 +1536,7 @@ int read_file(int fnum,char *data,int pos,int n) if (!Files[fnum].can_write) { - ret = read_predict(Files[fnum].fd,pos,data,NULL,n); + ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n); data += ret; n -= ret; @@ -1327,7 +1568,7 @@ int read_file(int fnum,char *data,int pos,int n) } if (n > 0) { - readret = read(Files[fnum].fd,data,n); + readret = read(Files[fnum].fd_ptr->fd,data,n); if (readret > 0) ret += readret; } @@ -1348,7 +1589,7 @@ int write_file(int fnum,char *data,int n) if (!Files[fnum].modified) { struct stat st; Files[fnum].modified = True; - if (fstat(Files[fnum].fd,&st) == 0) { + if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) { int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st); if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) { dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st); @@ -1356,7 +1597,7 @@ int write_file(int fnum,char *data,int n) } } - return(write_data(Files[fnum].fd,data,n)); + return(write_data(Files[fnum].fd_ptr->fd,data,n)); } @@ -2057,14 +2298,21 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de #if HAVE_GETGRNAM if (*lp_force_group(snum)) { - struct group *gptr = (struct group *)getgrnam(lp_force_group(snum)); + struct group *gptr; + pstring gname; + + StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1); + /* default service may be a group name */ + string_sub(gname,"%S",service); + gptr = (struct group *)getgrnam(gname); + if (gptr) { pcon->gid = gptr->gr_gid; - DEBUG(3,("Forced group %s\n",lp_force_group(snum))); + DEBUG(3,("Forced group %s\n",gname)); } else - DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum))); + DEBUG(1,("Couldn't find group %s\n",gname)); } #endif @@ -2936,6 +3184,11 @@ void exit_server(char *reason) if (dump_core()) return; #endif } + +#if FAST_SHARE_MODES + stop_share_mode_mgmt(); +#endif + DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:"")); exit(0); } @@ -3574,6 +3827,19 @@ static void init_structs(void ) { Files[i].open = False; string_init(&Files[i].name,""); + + } + + for (i=0;iref_count = 0; + fd_ptr->dev = (int32)-1; + fd_ptr->inode = (int32)-1; + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; } init_dptrs(); @@ -3808,10 +4074,6 @@ static void usage(char *pname) process(); close_sockets(); -#if FAST_SHARE_MODES - stop_share_mode_mgmt(); -#endif - exit_server("normal exit"); return(0); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3b4cdeb1c6..b2bee17eea 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -210,7 +210,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); - if (fstat(Files[fnum].fd,&sbuf) != 0) { + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -351,9 +351,6 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l } -#ifndef KANJI - unix2dos_format(fname, True); -#endif p = pdata; nameptr = p; @@ -447,11 +444,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { -#ifndef KANJI - strcpy(p+2,unix2dos_format(fname,False)); -#else strcpy(p+2,fname); -#endif if (!name_map_mangle(p+2,True,SNUM(cnum))) (p+2)[12] = 0; } else @@ -937,9 +930,12 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize strcpy(pdata+4,vname); break; case SMB_QUERY_FS_VOLUME_INFO: - data_len = 17 + strlen(vname); - SIVAL(pdata,12,strlen(vname)); - strcpy(pdata+17,vname); + data_len = 18 + 2*strlen(vname); + SIVAL(pdata,12,2*strlen(vname)); + PutUniCode(pdata+18,vname); + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), + vname)); + break; break; case SMB_QUERY_FS_SIZE_INFO: { @@ -1018,11 +1014,11 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - if (fstat(Files[fnum].fd,&sbuf) != 0) { + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = lseek(Files[fnum].fd,0,SEEK_CUR); + pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR); } else { /* qpathinfo */ info_level = SVAL(params,0); @@ -1212,7 +1208,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - fd = Files[fnum].fd; + fd = Files[fnum].fd_ptr->fd; if(fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); -- cgit From 586c6276ec78c9ee276e3d01ba017db14c30e0ce Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 13 Jan 1997 19:41:08 +0000 Subject: Added an extra parameter for unix_convert. If present this is the last component of the modified pathname before modification. This is needed due to an exceptional condition in reply_mv when the filesystem is case preserving, but not case sensitive and the user wants to change the case of a filename. Code for this is also added to reply.c Jeremy (jra@cygnus.com). (This used to be commit cdafa35f9dba6eb0073700e3a214348c432a3e84) --- source3/smbd/pipes.c | 2 +- source3/smbd/reply.c | 73 ++++++++++++++++++++++++++++++++++++++++----------- source3/smbd/server.c | 26 +++++++++++++++--- source3/smbd/trans2.c | 10 +++---- 4 files changed, 87 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index cb498a6195..efa6a68b9d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -114,7 +114,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) Connections[cnum].read_only = 0; smb_ofun |= 0x10; /* Add Create it not exists flag */ - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); fnum = find_free_file(); if (fnum < 0) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 812618b2c7..3698787ba4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -36,6 +36,7 @@ extern char magic_char; extern connection_struct Connections[]; extern files_struct Files[]; extern BOOL case_sensitive; +extern BOOL case_preserve; extern pstring sesssetup_user; extern int Client; @@ -528,7 +529,7 @@ int reply_chkpth(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); strcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,cnum); + unix_convert(name,cnum,0); mode = SVAL(inbuf,smb_vwv0); @@ -563,7 +564,7 @@ int reply_getatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); strcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ @@ -629,7 +630,7 @@ int reply_setatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); strcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); @@ -732,7 +733,7 @@ int reply_search(char *inbuf,char *outbuf) strcpy(directory,smb_buf(inbuf)+1); strcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,cnum); + unix_convert(directory,cnum,0); unix_format(dir2); if (!check_name(directory,cnum)) @@ -966,7 +967,7 @@ int reply_open(char *inbuf,char *outbuf) share_mode = SVAL(inbuf,smb_vwv0); strcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); fnum = find_free_file(); if (fnum < 0) @@ -1042,7 +1043,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* XXXX we need to handle passed times, sattr and flags */ strcpy(fname,smb_buf(inbuf)); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); /* now add create and trunc bits */ if (smb_ofun & 0x10) @@ -1145,7 +1146,7 @@ int reply_mknew(char *inbuf,char *outbuf) createmode = SVAL(inbuf,smb_vwv0); strcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); if (createmode & aVOLID) { @@ -1199,7 +1200,7 @@ int reply_ctemp(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); unixmode = unix_mode(cnum,createmode); @@ -1281,7 +1282,7 @@ int reply_unlink(char *inbuf,char *outbuf) DEBUG(3,("reply_unlink : %s\n",name)); - unix_convert(name,cnum); + unix_convert(name,cnum,0); p = strrchr(name,'/'); if (!p) { @@ -2393,7 +2394,7 @@ int reply_mkdir(char *inbuf,char *outbuf) strcpy(directory,smb_buf(inbuf) + 1); cnum = SVAL(inbuf,smb_tid); - unix_convert(directory,cnum); + unix_convert(directory,cnum,0); if (check_name(directory,cnum)) ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); @@ -2421,7 +2422,7 @@ int reply_rmdir(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); strcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,cnum); + unix_convert(directory,cnum,0); if (check_name(directory,cnum)) { @@ -2532,6 +2533,7 @@ int reply_mv(char *inbuf,char *outbuf) int cnum; pstring directory; pstring mask,newname; + pstring newname_last_component; char *p; int count=0; int error = ERRnoaccess; @@ -2547,8 +2549,8 @@ int reply_mv(char *inbuf,char *outbuf) DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - unix_convert(name,cnum); - unix_convert(newname,cnum); + unix_convert(name,cnum,0); + unix_convert(newname,cnum,newname_last_component); p = strrchr(name,'/'); if (!p) { @@ -2558,6 +2560,7 @@ int reply_mv(char *inbuf,char *outbuf) *p = 0; strcpy(directory,name); strcpy(mask,p+1); + *p = '/'; /* Replace needed for exceptional test below. */ } if (is_mangled(mask)) @@ -2568,10 +2571,50 @@ int reply_mv(char *inbuf,char *outbuf) if (!has_wild) { strcat(directory,"/"); strcat(directory,mask); + + DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, name = %s, newname = %s, newname_last_component = %s\n", case_sensitive, case_preserve, name, newname, newname_last_component)); + + /* + * Check for special case with case preserving and not + * case sensitive, if name and newname are identical, + * and the old last component differs from the original + * last component only by case, then we should allow + * the rename (user is trying to change the case of the + * filename). + */ + if((case_sensitive == False) && (case_preserve == True) && + strcsequal(name, newname)) { + pstring newname_modified_last_component; + + /* + * Get the last component of the modified name. + */ + p = strrchr(newname,'/'); + if (!p) + strcpy(newname_modified_last_component,name); + else + strcpy(newname_modified_last_component,p+1); + + if(strcsequal(newname_modified_last_component, + newname_last_component) == False) { + /* + * Replace the modified last component with + * the original. + */ + if(p) + strcpy(p+1, newname_last_component); + else + strcpy(newname, newname_last_component); + } + } + if (resolve_wildcards(directory,newname) && can_rename(directory,cnum) && !file_exist(newname,NULL) && !sys_rename(directory,newname)) count++; + + DEBUG(3,("reply_mv : doing rename on %s -> %s\n",directory,newname)); + if (!count) exists = file_exist(directory,NULL); if (!count && exists && file_exist(newname,NULL)) { exists = True; @@ -2727,8 +2770,8 @@ int reply_copy(char *inbuf,char *outbuf) return(ERROR(ERRSRV,ERRinvdevice)); } - unix_convert(name,cnum); - unix_convert(newname,cnum); + unix_convert(name,cnum,0); + unix_convert(newname,cnum,0); target_is_directory = directory_exist(newname,NULL); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 75e7279e6d..623a3fb2bd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -378,14 +378,21 @@ for this service. The function will return False if some part of the name except for the last part cannot be resolved + +If the saved_last_component != 0, then the unmodified last component +of the pathname is returned there. This is used in an exceptional +case in reply_mv (so far). If saved_last_component == 0 then nothing +is returned there. ****************************************************************************/ -BOOL unix_convert(char *name,int cnum) +BOOL unix_convert(char *name,int cnum,pstring saved_last_component) { struct stat st; char *start, *end; pstring dirpath; *dirpath = 0; + if(saved_last_component) + *saved_last_component = 0; /* convert to basic unix format - removing \ chars and cleaning it up */ unix_format(name); @@ -415,6 +422,17 @@ BOOL unix_convert(char *name,int cnum) return(True); } + /* + * Ensure saved_last_component is valid even if file exists. + */ + if(saved_last_component) { + end = strrchr(name, '/'); + if(end) + strcpy(saved_last_component, end + 1); + else + strcpy(saved_last_component, name); + } + /* stat the name - if it exists then we are all done! */ if (sys_stat(name,&st) == 0) return(True); @@ -442,7 +460,10 @@ BOOL unix_convert(char *name,int cnum) end = strchr(start, '/'); /* chop the name at this point */ - if (end) *end = 0; + if (end) *end = 0; + + if(saved_last_component != 0) + strcpy(saved_last_component, end ? end + 1 : start); /* check if the name exists up to this point */ if (sys_stat(name, &st) == 0) @@ -467,7 +488,6 @@ BOOL unix_convert(char *name,int cnum) later */ if (end) strcpy(rest,end+1); - /* try to find this part of the path in the directory */ if (strchr(start,'?') || strchr(start,'*') || !scan_directory(dirpath, start, SNUM(cnum), end?True:False)) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b2bee17eea..94c4f26359 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -192,7 +192,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); fnum = find_free_file(); if (fnum < 0) @@ -581,7 +581,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,cnum); + unix_convert(directory,cnum,0); if(!check_name(directory,cnum)) { return(ERROR(ERRDOS,ERRbadpath)); } @@ -1024,7 +1024,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, info_level = SVAL(params,0); fname = &fname1[0]; strcpy(fname,¶ms[6]); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadpath)); @@ -1219,7 +1219,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, info_level = SVAL(params,0); fname = fname1; strcpy(fname,¶ms[6]); - unix_convert(fname,cnum); + unix_convert(fname,cnum,0); if(!check_name(fname, cnum)) return(ERROR(ERRDOS,ERRbadpath)); @@ -1353,7 +1353,7 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,cnum); + unix_convert(directory,cnum,0); if (check_name(directory,cnum)) ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); -- cgit From 869f24e0b1915ec8d3e14f8850417474200e687e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 15 Jan 1997 01:53:25 +0000 Subject: locking.c proto.h shmem.c smb.h status.c : Changed shm_ prefixes to smb_shm_ prefixes as shm_ is a POSIX.4 prefix. Updated fd code in FAST_SHARE_MODE code to work with new fd indirection. quotas.c: Fixed #ifdef not on position zero. Jeremy. (jra@cygnus.com). (This used to be commit c9a9d56642cc34369a42f48a28116e466240d303) --- source3/smbd/quotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 3e22e26ba3..aec349dfd1 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -413,7 +413,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); #else r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); - #endif +#endif #endif /* Use softlimit to determine disk space, except when it has been exceeded */ -- cgit From 691632e555274853dbefccf4accc6f5ee5e42e27 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 23 Jan 1997 19:39:57 +0000 Subject: Added fix for file descriptor re-use failing when file_exists is false. Jeremy (jra@cygnus.com). (This used to be commit b587f18247537577764a1e28169bf6307ff292e9) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 623a3fb2bd..2d47816ff7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1469,10 +1469,10 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,mode)); - open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,&sbuf); + open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) { flags = O_RDONLY; - open_file(fnum,cnum,fname,flags,mode,&sbuf); + open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 ); } if (Files[fnum].open) { -- cgit From 2831c627740c80d4ea1187058b249e1d5b5e5c58 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 2 Feb 1997 16:03:51 +0000 Subject: line 1960 - call to atexit - address of higher order function killkids not needed (address already specified). lkcl (This used to be commit c5ab2eb71afd2961dfb61da30984a8b0fc88e754) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2d47816ff7..6ab6c76c4a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1957,7 +1957,7 @@ static BOOL open_sockets(BOOL is_daemon,int port) } if(atexit_set == 0) - atexit(&killkids); + atexit(killkids); /* now accept incoming connections - forking a new process for each incoming connection */ -- cgit From 98bf10bc5df6eb1c3b71d51cc60ef4bf25f57d97 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 2 Feb 1997 18:12:36 +0000 Subject: util.c: StrCaseCmp and StrnCaseCmp terminated incorrectly, giving false answers when a string was partially identical. this issue is still outstanding, and needs to be investigated further. loadparm.c: added lp_logon_path() parameter. ipc.c: in NetUserGetInfo, lp_logon_path() can be returned instead of always specifying \\SAMBA_SERVER\HOMES (which may not necessarily exist). it is now possible to specify lp_logon_path() as \\ARBITRARY_SERVER\%U, just like NT server can. the default is \\SAMBA_SERVER\HOMES, just like it used to be. lkcl (This used to be commit d5b6ad7cb87d6b1a9342f027ac4f57ffdb54b4f3) --- source3/smbd/ipc.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index be500cb40d..1bb1322b5d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1845,8 +1845,15 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SIVAL(p,36,0); /* auth flags */ SIVALS(p,40,-1); /* password age */ SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */ - strcpy(p2,"\\\\%L\\HOMES"); - standard_sub_basic(p2); + if (*lp_logon_path()) + { + strcpy(p2,lp_logon_path()); + } + else + { + strcpy(p2,"\\\\%L\\HOMES"); + standard_sub_basic(p2); + } p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */ strcpy(p2,""); @@ -1879,8 +1886,15 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SSVAL(p,42, Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - strcpy(p2,"\\\\%L\\HOMES"); - standard_sub_basic(p2); + if (*lp_logon_path()) + { + strcpy(p2,lp_logon_path()); + } + else + { + strcpy(p2,"\\\\%L\\HOMES"); + standard_sub_basic(p2); + } p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; -- cgit From 30ae26ba426eefef3928e699c46f01eb56f49fa8 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 3 Feb 1997 19:40:15 +0000 Subject: Fixed bug with NT and large directories. jra@cygnus.com (This used to be commit f0aa5e3ff05053224cffc8243237e7675e8b413b) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 94c4f26359..2df28e9264 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -79,8 +79,8 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, { /* Calculate whether we will totally or partially fill this packet */ total_sent_thistime = params_to_send + data_to_send + alignment_offset; - /* We can never send more than maxxmit */ - total_sent_thistime = MIN(total_sent_thistime, maxxmit); + /* We can never send more than useable_space */ + total_sent_thistime = MIN(total_sent_thistime, useable_space); set_message(outbuf, 10, total_sent_thistime, True); -- cgit From f24c04fc77370aae1bddb18955fab3b0e8161ad7 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 3 Feb 1997 19:48:56 +0000 Subject: Fixed up problems with CDROM filesystems (return EROFS) and also compile issue with USE_MMAP code. jra@cygnus.com (This used to be commit 8e9fe58991c32817142aa2a6caec1df0c4fa4b08) --- source3/smbd/server.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6ab6c76c4a..0146776bbc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1049,7 +1049,15 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s /* Set the flags as needed without the read/write modes. */ open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); + /* + * On some systems opening a file for R/W access on a read only + * filesystems sets errno to EROFS. + */ +#ifdef EROFS + if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) { +#else /* No EROFS */ if((fd_ptr->fd == -1) && (errno == EACCES)) { +#endif /* EROFS */ if(flags & O_WRONLY) { fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode); fd_ptr->real_open_flags = O_WRONLY; @@ -1155,7 +1163,7 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s { Files[fnum].mmap_size = file_size(fname); Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size, - PROT_READ,MAP_SHARED,Files[fnum].fd,0); + PROT_READ,MAP_SHARED,Files[fnum]->fd_ptr.fd,0); if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr) { -- cgit From 1fe69a7dd9311e211f05ebba45ec574ded35ca89 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 4 Feb 1997 01:21:52 +0000 Subject: Fixed my stupid typo in earlier fix. jra@cygnus.com (This used to be commit e9a8ccb36bc94e161fdf85c1de8310937710c92f) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0146776bbc..5ff60c6c6c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1163,7 +1163,7 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s { Files[fnum].mmap_size = file_size(fname); Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size, - PROT_READ,MAP_SHARED,Files[fnum]->fd_ptr.fd,0); + PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0); if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr) { -- cgit From cc55a88ddc9c08cc669da731e9f7aafc379680ee Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 4 Feb 1997 10:35:38 +0000 Subject: JHT ===> Fixed potential PAM Security hole and second chance syndrome spurious warning message "Warning - no crypt available" (This used to be commit dc559428b85474ff4d80f37f421365a3910a8861) --- source3/smbd/password.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8c1a1026cc..3ccc1e4cfd 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -612,7 +612,16 @@ BOOL password_check(char *password) { #ifdef USE_PAM +/* This falls through if the password check fails + - if NO_CRYPT is defined this causes an error msg + saying Warning - no crypt available + - if NO_CRYPT is NOT defined this is a potential security hole + as it may authenticate via the crypt call when PAM + settings say it should fail. if (pam_auth(this_user,password)) return(True); +Hence we make a direct return to avoid a second chance!!! +*/ + return (pam_auth(this_user,password)); #endif #ifdef AFS_AUTH -- cgit From 8839603f03b624e80f86395261d513bc7eb79189 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 10 Feb 1997 13:54:29 +0000 Subject: JHT ===> William Yost patches integrated to fix leading path on 8.3 filename problem. Problem conditions: case sensitive = no default case = lower mangle case = yes preserve case = yes short preserve case = yes Problem: Win95 still writes upper case file names. Patches supplied have been incorporated into mangle.c and server.c but needs YOSTW to be defined for it to take effect. Action: ======= If we are happy with the patch, delete old code in mangle.c, then remove all YOSTW #ifdefs. (This used to be commit 84fc674c89e8999f284b59888dfa2cdc47438e88) --- source3/smbd/mangle.c | 5 +++++ source3/smbd/server.c | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 6d98d9e39c..c0baa65982 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -92,6 +92,7 @@ BOOL is_8_3(char *fname) DEBUG(5,("checking %s for 8.3\n",fname)); if (case_mangle) +#ifndef YOSTW switch (case_default) { case CASE_LOWER: @@ -101,6 +102,10 @@ BOOL is_8_3(char *fname) if (strhaslower(fname)) return(False); break; } +#endif +#ifdef YOSTW + if (strhasupper(fname) && strhaslower(fname)) return(False); +#endif /* can't be longer than 12 chars */ if (len == 0 || len > 12) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5ff60c6c6c..6f4da9b779 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -389,6 +389,9 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) struct stat st; char *start, *end; pstring dirpath; +#ifdef YOSTW + char szName[132], *p; +#endif *dirpath = 0; if(saved_last_component) @@ -398,6 +401,23 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) unix_format(name); unix_clean_name(name); +#ifdef YOSTW + /* Remove leading path specifications to check for 8_3 name */ + if ( strncmp( name, "./",2) == 0 ) { + strcpy( szName, name+2 ); + } + else { + strcpy( szName, name ); + } + p = strrchr( szName, '/' ); + if ( p != NULL ) { + p++; + } + else { + p = szName; + } +#endif + if (!case_sensitive && (!case_preserve || (is_8_3(name) && !short_case_preserve))) strnorm(name); -- cgit From c6311f4e0a17472f4ea7e6c15ad8fc41c71270c0 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 10 Feb 1997 19:27:27 +0000 Subject: Removed YOST code. Removal of leading ./ chars should be done in unix_clean_name in util.c jra@cygnus.com (This used to be commit f9f1085c7db673f602f9de07670a9bbf3205410f) --- source3/smbd/server.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6f4da9b779..5ff60c6c6c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -389,9 +389,6 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) struct stat st; char *start, *end; pstring dirpath; -#ifdef YOSTW - char szName[132], *p; -#endif *dirpath = 0; if(saved_last_component) @@ -401,23 +398,6 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) unix_format(name); unix_clean_name(name); -#ifdef YOSTW - /* Remove leading path specifications to check for 8_3 name */ - if ( strncmp( name, "./",2) == 0 ) { - strcpy( szName, name+2 ); - } - else { - strcpy( szName, name ); - } - p = strrchr( szName, '/' ); - if ( p != NULL ) { - p++; - } - else { - p = szName; - } -#endif - if (!case_sensitive && (!case_preserve || (is_8_3(name) && !short_case_preserve))) strnorm(name); -- cgit From 8bd0dbb1af535466018b7ae3e4f7f042d493e145 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 11 Feb 1997 22:53:29 +0000 Subject: Replaced YOST code with more functionally equivalent code that changes a bit less. Also added fix to tricky reply_mv case. jra@cygnus.com (This used to be commit f22ac13b1423186d463c9fc5b3588a3dcbd7bc1c) --- source3/smbd/mangle.c | 11 +++-------- source3/smbd/reply.c | 6 ++++-- source3/smbd/server.c | 34 +++++++++++++++++----------------- source3/smbd/trans2.c | 2 +- 4 files changed, 25 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index c0baa65982..5fdf31b7a4 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -79,7 +79,7 @@ static BOOL is_reserved_msdos(char *fname) /**************************************************************************** return True if a name is in 8.3 dos format ****************************************************************************/ -BOOL is_8_3(char *fname) +BOOL is_8_3(char *fname, BOOL check_case) { int len; char *dot_pos; @@ -91,8 +91,7 @@ BOOL is_8_3(char *fname) DEBUG(5,("checking %s for 8.3\n",fname)); - if (case_mangle) -#ifndef YOSTW + if (check_case && case_mangle) switch (case_default) { case CASE_LOWER: @@ -102,10 +101,6 @@ BOOL is_8_3(char *fname) if (strhaslower(fname)) return(False); break; } -#endif -#ifdef YOSTW - if (strhasupper(fname) && strhaslower(fname)) return(False); -#endif /* can't be longer than 12 chars */ if (len == 0 || len > 12) @@ -652,7 +647,7 @@ BOOL name_map_mangle(char *OutName,BOOL need83,int snum) } /* check if it's already in 8.3 format */ - if (need83 && !is_8_3(OutName)) { + if (need83 && !is_8_3(OutName, True)) { if (!lp_manglednames(snum)) return(False); /* mangle it into 8.3 */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3698787ba4..46c385b85e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -37,6 +37,7 @@ extern connection_struct Connections[]; extern files_struct Files[]; extern BOOL case_sensitive; extern BOOL case_preserve; +extern BOOL short_case_preserve; extern pstring sesssetup_user; extern int Client; @@ -605,7 +606,7 @@ int reply_getatr(char *inbuf,char *outbuf) char *p = strrchr(fname,'/'); uint16 flg2 = SVAL(outbuf,smb_flg2); if (!p) p = fname; - if (!is_8_3(fname)) + if (!is_8_3(fname, True)) SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ } @@ -2582,7 +2583,8 @@ int reply_mv(char *inbuf,char *outbuf) * the rename (user is trying to change the case of the * filename). */ - if((case_sensitive == False) && (case_preserve == True) && + if((case_sensitive == False) && ((case_preserve == True) || + ((short_case_preserve == True) && is_8_3(name, True))) && strcsequal(name, newname)) { pstring newname_modified_last_component; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5ff60c6c6c..4f3ee0fd0b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -300,7 +300,7 @@ static BOOL mangled_equal(char *name1, char *name2) { pstring tmpname; - if (is_8_3(name2)) + if (is_8_3(name2, True)) return(False); strcpy(tmpname,name2); @@ -398,18 +398,29 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) unix_format(name); unix_clean_name(name); - if (!case_sensitive && - (!case_preserve || (is_8_3(name) && !short_case_preserve))) - strnorm(name); - /* names must be relative to the root of the service - trim any leading /. also trim trailing /'s */ trim_string(name,"/","/"); + /* + * Ensure saved_last_component is valid even if file exists. + */ + if(saved_last_component) { + end = strrchr(name, '/'); + if(end) + strcpy(saved_last_component, end + 1); + else + strcpy(saved_last_component, name); + } + + if (!case_sensitive && + (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) + strnorm(name); + /* check if it's a printer file */ if (Connections[cnum].printer) { - if ((! *name) || strchr(name,'/') || !is_8_3(name)) + if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) { char *s; fstring name2; @@ -422,17 +433,6 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) return(True); } - /* - * Ensure saved_last_component is valid even if file exists. - */ - if(saved_last_component) { - end = strrchr(name, '/'); - if(end) - strcpy(saved_last_component, end + 1); - else - strcpy(saved_last_component, name); - } - /* stat the name - if it exists then we are all done! */ if (sys_stat(name,&st) == 0) return(True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2df28e9264..d489978ab8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -429,7 +429,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - was_8_3 = is_8_3(fname); + was_8_3 = is_8_3(fname, True); len = 94+strlen(fname); len = (len + 3) & ~3; SIVAL(p,0,len); p += 4; -- cgit From e9a4f896bda4e102630522024a371ad0eb10a6a7 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 18 Feb 1997 17:20:14 +0000 Subject: Fixed problem with renaming folder on top level share. jra@cygnus.com (This used to be commit 7ba1cff9341b4094fddf1e2e529b1e5b79aea675) --- source3/smbd/reply.c | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 46c385b85e..5dbd39f746 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2553,9 +2553,18 @@ int reply_mv(char *inbuf,char *outbuf) unix_convert(name,cnum,0); unix_convert(newname,cnum,newname_last_component); + /* + * Split the old name into directory and last component + * strings. Note that unix_convert may have stripped off a + * leading ./ from both name and newname if the rename is + * at the root of the share. We need to make sure either both + * name and newname contain a / character or neither of them do + * as this is checked in resolve_wildcards(). + */ + p = strrchr(name,'/'); if (!p) { - strcpy(directory,"./"); + strcpy(directory,"."); strcpy(mask,name); } else { *p = 0; @@ -2570,32 +2579,45 @@ int reply_mv(char *inbuf,char *outbuf) has_wild = strchr(mask,'*') || strchr(mask,'?'); if (!has_wild) { + BOOL is_short_name = is_8_3(name, True); + + /* Add a terminating '/' to the directory name. */ strcat(directory,"/"); strcat(directory,mask); - DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, name = %s, newname = %s, newname_last_component = %s\n", case_sensitive, case_preserve, name, newname, newname_last_component)); + /* Ensure newname contains a '/' also */ + if(strrchr(newname,'/') == 0) { + pstring tmpstr; + + strcpy(tmpstr, "./"); + strcat(tmpstr, newname); + strcpy(newname, tmpstr); + } + + DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", + case_sensitive, case_preserve, short_case_preserve, directory, + newname, newname_last_component, is_short_name)); /* * Check for special case with case preserving and not - * case sensitive, if name and newname are identical, + * case sensitive, if directory and newname are identical, * and the old last component differs from the original * last component only by case, then we should allow * the rename (user is trying to change the case of the * filename). */ - if((case_sensitive == False) && ((case_preserve == True) || - ((short_case_preserve == True) && is_8_3(name, True))) && - strcsequal(name, newname)) { + if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) || + ((short_case_preserve == True) && (is_short_name == True))) && + strcsequal(directory, newname)) { pstring newname_modified_last_component; /* * Get the last component of the modified name. + * Note that we guarantee that newname contains a '/' + * character above. */ p = strrchr(newname,'/'); - if (!p) - strcpy(newname_modified_last_component,name); - else - strcpy(newname_modified_last_component,p+1); + strcpy(newname_modified_last_component,p+1); if(strcsequal(newname_modified_last_component, newname_last_component) == False) { @@ -2603,10 +2625,7 @@ int reply_mv(char *inbuf,char *outbuf) * Replace the modified last component with * the original. */ - if(p) - strcpy(p+1, newname_last_component); - else - strcpy(newname, newname_last_component); + strcpy(p+1, newname_last_component); } } @@ -2615,7 +2634,8 @@ int reply_mv(char *inbuf,char *outbuf) !file_exist(newname,NULL) && !sys_rename(directory,newname)) count++; - DEBUG(3,("reply_mv : doing rename on %s -> %s\n",directory,newname)); + DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", + directory,newname)); if (!count) exists = file_exist(directory,NULL); if (!count && exists && file_exist(newname,NULL)) { -- cgit From df42b0a7bcdaae96035ecb1d434a66735358fd95 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 23 Feb 1997 05:18:09 +0000 Subject: Makefile: Added cleandir target. chgpasswd.c: Added patch from Roland Haag to allow password changes to be done more than once. loadparm.c: Added entries for the "directory mode/directory mask parameters". Changed default file mode to 644. proto.h: Added sys_gethostbyname. server.c: Added directory mode changes. system.c: Added sys_gethostbyname. trans2.c: Added NT_FILE_ATTRIBUTE_NORMAL patch from Roger Orr trans2.h: Defined NT_FILE_ATTRIBUTE_NORMAL for above patch. util.c: Changes calls to gethostbyname to sys_gethostbyname. jra@cygnus.com (This used to be commit d8d8a7ee00971fca7a8d079bfb547af107df35a4) --- source3/smbd/chgpasswd.c | 8 ++++++-- source3/smbd/server.c | 20 +++++++++++--------- source3/smbd/trans2.c | 9 ++++++--- 3 files changed, 23 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 54b49edf13..883ad5214a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -41,7 +41,7 @@ static int findpty(char **slave) #ifdef SVR4 extern char *ptsname(); #else - static char line[12] = "/dev/ptyXX"; + static char line[12]; void *dirp; char *dpname; #endif @@ -54,13 +54,17 @@ static int findpty(char **slave) return (master); } #else + strcpy( line, "/dev/ptyXX" ); + dirp = OpenDir("/dev"); if (!dirp) return(-1); while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { + DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); line[8] = dpname[3]; line[9] = dpname[4]; if ((master = open(line, O_RDWR)) >= 0) { + DEBUG(3,("pty: opened %s\n", line ) ); line[5] = 't'; *slave = line; CloseDir(dirp); @@ -280,7 +284,7 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence) kill(pid, SIGKILL); /* be sure to end this process */ return(False); } - if ((wpid = waitpid(pid, &wstat, 0)) < 0) { + if ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { DEBUG(3,("The process is no longer waiting!\n\n")); return(False); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4f3ee0fd0b..09c8fccb5c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -130,19 +130,21 @@ mode_t unix_mode(int cnum,int dosmode) if ( !IS_DOS_READONLY(dosmode) ) result |= (S_IWUSR | S_IWGRP | S_IWOTH); - if (IS_DOS_DIR(dosmode)) + if (IS_DOS_DIR(dosmode)) { result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); - - if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode)) - result |= S_IXUSR; + result &= (lp_dir_mode(SNUM(cnum)) | 0700); + } else { + if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode)) + result |= S_IXUSR; - if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode)) - result |= S_IXGRP; + if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode)) + result |= S_IXGRP; - if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode)) - result |= S_IXOTH; + if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode)) + result |= S_IXOTH; - result &= CREATE_MODE(cnum); + result &= CREATE_MODE(cnum); + } return(result); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d489978ab8..ab2fe88536 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -276,6 +276,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l strequal(Connections[cnum].dirpath,".") || strequal(Connections[cnum].dirpath,"/")); BOOL was_8_3; + int nt_extmode; /* Used for NT connections instead of mode */ *fname = 0; *out_of_space = False; @@ -357,6 +358,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l name_map_mangle(fname,False,SNUM(cnum)); + nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL; + switch (info_level) { case 1: @@ -440,7 +443,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l put_long_date(p,mdate); p += 8; SIVAL(p,0,size); p += 8; SIVAL(p,0,size); p += 8; - SIVAL(p,0,mode); p += 4; + SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { @@ -468,7 +471,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l put_long_date(p,mdate); p += 8; SIVAL(p,0,size); p += 8; SIVAL(p,0,size); p += 8; - SIVAL(p,0,mode); p += 4; + SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; strcpy(p,fname); p = pdata + len; @@ -486,7 +489,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l put_long_date(p,mdate); p += 8; SIVAL(p,0,size); p += 8; SIVAL(p,0,size); p += 8; - SIVAL(p,0,mode); p += 4; + SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; strcpy(p,fname); -- cgit From da0a56a278232bad50ea0dd05de3b06299d66234 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 28 Feb 1997 20:39:36 +0000 Subject: Split maxxmit parameter into two : max_send (auto configured by the connecting client, as per CIFS4) and max_recv, which can be configured as the old maxxmit was. Fixes problems with NT directory listings when maxxmit is set very small. jra@cygnus.com (This used to be commit c2d5d1040a933987a0c39545bb5bf8e2fc400a87) --- source3/smbd/ipc.c | 10 +++++----- source3/smbd/pipes.c | 1 - source3/smbd/reply.c | 9 ++++++--- source3/smbd/server.c | 20 +++++++++++++++----- source3/smbd/trans2.c | 8 ++++---- 5 files changed, 30 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1bb1322b5d..ccb2f3dd52 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -31,7 +31,7 @@ #define CHECK_TYPES 0 extern int DEBUGLEVEL; -extern int maxxmit; +extern int max_send; extern files_struct Files[]; extern connection_struct Connections[]; @@ -142,8 +142,8 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, int tot_data=0,tot_param=0; int align; - this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam)); + this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ + this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); align = (this_lparam%4); @@ -173,8 +173,8 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, while (tot_data < ldata || tot_param < lparam) { - this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */ - this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam)); + this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */ + this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam)); align = (this_lparam%4); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index efa6a68b9d..06f3aeb0fb 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -35,7 +35,6 @@ /* look in server.c for some explanation of these variables */ extern int Protocol; extern int DEBUGLEVEL; -extern int maxxmit; extern int chain_fnum; extern char magic_char; extern connection_struct Connections[]; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5dbd39f746..f532d613b4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -30,7 +30,8 @@ /* look in server.c for some explanation of these variables */ extern int Protocol; extern int DEBUGLEVEL; -extern int maxxmit; +extern int max_send; +extern int max_recv; extern int chain_fnum; extern char magic_char; extern connection_struct Connections[]; @@ -194,7 +195,7 @@ int reply_tcon(char *inbuf,char *outbuf) return(connection_error(inbuf,outbuf,connection_num)); outsize = set_message(outbuf,2,0,True); - SSVAL(outbuf,smb_vwv0,maxxmit); + SSVAL(outbuf,smb_vwv0,max_recv); SSVAL(outbuf,smb_vwv1,connection_num); SSVAL(outbuf,smb_tid,connection_num); @@ -509,7 +510,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(inbuf,smb_uid,sess_vuid); if (!done_sesssetup) - maxxmit = MIN(maxxmit,smb_bufsize); + max_send = MIN(max_send,smb_bufsize); + + DEBUG(0,(" Client requested max send size of %d\n", max_send)); done_sesssetup = True; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 09c8fccb5c..1abcb8089f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -67,7 +67,17 @@ int max_file_fd_used = 0; extern int Protocol; -int maxxmit = BUFFER_SIZE; +/* + * Size of data we can send to client. Set + * by the client for all protocols above CORE. + * Set by us for CORE protocol. + */ +int max_send = BUFFER_SIZE; +/* + * Size of the data we can receive. Set by us. + * Can be modified by the max xmit parameter. + */ +int max_recv = BUFFER_SIZE; /* a fnum to use when chaining */ int chain_fnum = -1; @@ -2592,7 +2602,7 @@ int reply_lanman1(char *outbuf) } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_vwv2,maxxmit); + SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ SSVAL(outbuf,smb_vwv4,1); SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support @@ -2639,7 +2649,7 @@ int reply_lanman2(char *outbuf) } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_vwv2,maxxmit); + SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); SSVAL(outbuf,smb_vwv4,1); SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ @@ -3813,7 +3823,7 @@ static void process(void) if (msg_type == 0) show_msg(InBuffer); - nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit); + nread = construct_reply(InBuffer,OutBuffer,nread,max_send); if(nread > 0) { if (CVAL(OutBuffer,0) == 0) @@ -4093,7 +4103,7 @@ static void usage(char *pname) /* possibly reload the services file. */ reload_services(True); - maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE); + max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); if (*lp_rootdir()) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ab2fe88536..2c0d5903e6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -40,13 +40,13 @@ extern int Client; static int send_trans2_replies(char *outbuf, int bufsize, char *params, int paramsize, char *pdata, int datasize) { - /* As we are using a protocol > LANMAN1 then the maxxmit + /* As we are using a protocol > LANMAN1 then the max_send variable must have been set in the sessetupX call. This takes precedence over the max_xmit field in the global struct. These different max_xmit variables should be merged as this is now too confusing */ - extern int maxxmit; + extern int max_send; int data_to_send = datasize; int params_to_send = paramsize; int useable_space; @@ -71,9 +71,9 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, /* The alignment_offset is to align the param and data bytes on an even byte boundary. NT 4.0 Beta needs this to work correctly. */ useable_space = bufsize - ((smb_buf(outbuf)+alignment_offset) - outbuf); - /* useable_space can never be more than maxxmit minus the + /* useable_space can never be more than max_send minus the alignment offset. */ - useable_space = MIN(useable_space, maxxmit - alignment_offset); + useable_space = MIN(useable_space, max_send - alignment_offset); while( params_to_send || data_to_send) { -- cgit From 3e2f9c3dee3895b44a367ec1b1b2d9b1b3b00e7c Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 7 Mar 1997 17:24:22 +0000 Subject: quotas.c: Fixed typo in #ifdef'ed compile. ufc.c: Added pre-declaration of _ufc_doit(). jra@cygnus.com (This used to be commit 7c690e020ffae9a56c678ae46ae87283a1aa92fe) --- source3/smbd/quotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index aec349dfd1..05b40ada0f 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -433,7 +433,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) /* Use softlimit to determine disk space, except when it has been exceeded */ if ((D.dqb_curblocks>D.dqb_bsoftlimit) #if !defined(__FreeBSD__) -||(D.dqb_curfiles>D.dqb_fsoftlimit)) +||(D.dqb_curfiles>D.dqb_fsoftlimit) #endif ) { *dfree = 0; -- cgit From b581d0324098f12a5bcb1941e698339a84e44a93 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 9 Mar 1997 14:58:22 +0000 Subject: 1) updated ipc.c NetUserGetInfo - load \\%L\%U instead of \\%L\HOMES because the share must be browseable by a w95 client 2) send_mailslot_reply - unique or group datagram argument added. 3) netlogon.c - rewrote response packet to do the right thing for w95. 4) server.c reply_nt1() - added OEMDomainstring to the end. 5) (deep breath) reworked the nmbd-browsing code a little bit. i discovered two months ago that becoming a primary domain controller (and domain master browser) is done independently of becoming a backup domain controller (logon server) is done independently of becoming a local master browser. therefore, three sets of state-machines (instead of just one) are in place - each of which is responsible for taking samba through the required stages to become: a logon server; a domain master browser; and a local master browser. each of these three things can occur independently on each interface, _including_ the wins pseudo-interface. the only slight caveat is that the wins pseudo-interface, by virtue of _not_ being a broadcast interface, does _not_ register as a local master browser with the wins server, as this doesn't make sense. lkcl (This used to be commit 88c6a00c3c1b430307f512986185b5ed7aea7181) --- source3/smbd/ipc.c | 472 ++++++++++++++++++++++++++++++++++---------------- source3/smbd/server.c | 57 ++++-- 2 files changed, 369 insertions(+), 160 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ccb2f3dd52..9f8369912c 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1,3 +1,4 @@ + /* Unix SMB/Netbios implementation. Version 1.9. @@ -1672,7 +1673,8 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;i 0) { - SCVAL(p,21,0); - *p2 = 0; - if (uLevel >= 10) { - SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */ - strcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */ - strcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,""); - p2 = skip_string(p2,1); - } - if (uLevel == 11) { /* modelled after NTAS 3.51 reply */ - SSVAL(p,34, - Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - SIVAL(p,36,0); /* auth flags */ - SIVALS(p,40,-1); /* password age */ - SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { - strcpy(p2,"\\\\%L\\HOMES"); - standard_sub_basic(p2); - } - p2 = skip_string(p2,1); - SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */ - strcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,52,0); /* last logon */ - SIVAL(p,56,0); /* last logoff */ - SSVALS(p,60,-1); /* bad pw counts */ - SSVALS(p,62,-1); /* num logons */ - SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */ - strcpy(p2,"\\\\*"); - p2 = skip_string(p2,1); - SSVAL(p,68,0); /* country code */ - - SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */ - strcpy(p2,""); - p2 = skip_string(p2,1); - - SIVALS(p,74,-1); /* max storage */ - SSVAL(p,78,168); /* units per week */ - SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */ - memset(p2,-1,21); - SCVAL(p2,21,0); /* fix zero termination */ - p2 = skip_string(p2,1); - - SSVAL(p,84,0); /* code page */ - } - if (uLevel == 1 || uLevel == 2) { - memset(p+22,' ',16); /* password */ - SIVALS(p,38,-1); /* password age */ - SSVAL(p,42, - Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { - strcpy(p2,"\\\\%L\\HOMES"); - standard_sub_basic(p2); - } - p2 = skip_string(p2,1); - SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ - *p2++ = 0; - SSVAL(p,52,0); /* flags */ - SIVAL(p,54,0); /* script_path */ - if (uLevel == 2) { - SIVAL(p,60,0); /* auth_flags */ - SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,68,0); /* urs_comment */ - SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ - strcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,76,0); /* workstations */ - SIVAL(p,80,0); /* last_logon */ - SIVAL(p,84,0); /* last_logoff */ - SIVALS(p,88,-1); /* acct_expires */ - SIVALS(p,92,-1); /* max_storage */ - SSVAL(p,96,168); /* units_per_week */ - SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */ - memset(p2,-1,21); - p2 += 21; - SSVALS(p,102,-1); /* bad_pw_count */ - SSVALS(p,104,-1); /* num_logons */ - SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ - strcpy(p2,"\\\\%L"); - standard_sub_basic(p2); - p2 = skip_string(p2,1); - SSVAL(p,110,49); /* country_code */ - SSVAL(p,112,860); /* code page */ - } - } - } + if (uLevel > 0) + { + SCVAL(p,usri11_pad,0); /* padding - 1 byte */ + *p2 = 0; + } + if (uLevel >= 10) + { + SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ + strcpy(p2,"Comment"); + p2 = skip_string(p2,1); + + SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ + strcpy(p2,"UserComment"); + p2 = skip_string(p2,1); + + /* EEK! the cifsrap.txt doesn't have this in!!!! */ + SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ +#if 0 + strcpy(p2,"FullName"); +#endif + strcpy(p2,UserName); /* suggest copying the user name, for now... */ + p2 = skip_string(p2,1); + } + if (uLevel == 11) /* modelled after NTAS 3.51 reply */ + { + SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ + SIVALS(p,usri11_password_age,0xffffffff); /* password age */ + SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ + if (*lp_logon_path()) + { + strcpy(p2,lp_logon_path()); + } + else + { + strcpy(p2,"\\\\%L\\%U"); + } + standard_sub_basic(p2); + p2 = skip_string(p2,1); + SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,usri11_last_logon,0); /* last logon */ + SIVAL(p,usri11_last_logoff,0); /* last logoff */ + SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */ + SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */ + SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ + strcpy(p2,"\\\\*"); + p2 = skip_string(p2,1); + SSVAL(p,usri11_country_code,0); /* country code */ + + SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ + strcpy(p2,""); + p2 = skip_string(p2,1); + + SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */ + SSVAL(p,usri11_units_per_week,168); /* units per week */ + SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */ + + /* a simple way to get logon hours at all times. */ + memset(p2,0xff,21); + SCVAL(p2,21,0); /* fix zero termination */ + p2 = skip_string(p2,1); + + SSVAL(p,usri11_code_page,0); /* code page */ + } + if (uLevel == 1 || uLevel == 2) + { + memset(p+22,' ',16); /* password */ + SIVALS(p,38,-1); /* password age */ + SSVAL(p,42, + Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ + if (*lp_logon_path()) + { + strcpy(p2,lp_logon_path()); + } + else + { + strcpy(p2,"\\\\%L\\%U"); + } + standard_sub_basic(p2); + p2 = skip_string(p2,1); + SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ + *p2++ = 0; + SSVAL(p,52,0); /* flags */ + SIVAL(p,54,0); /* script_path */ + if (uLevel == 2) + { + SIVAL(p,60,0); /* auth_flags */ + SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,68,0); /* urs_comment */ + SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ + strcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,76,0); /* workstations */ + SIVAL(p,80,0); /* last_logon */ + SIVAL(p,84,0); /* last_logoff */ + SIVALS(p,88,-1); /* acct_expires */ + SIVALS(p,92,-1); /* max_storage */ + SSVAL(p,96,168); /* units_per_week */ + SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */ + memset(p2,-1,21); + p2 += 21; + SSVALS(p,102,-1); /* bad_pw_count */ + SSVALS(p,104,-1); /* num_logons */ + SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ + strcpy(p2,"\\\\%L"); + standard_sub_basic(p2); + p2 = skip_string(p2,1); + SSVAL(p,110,49); /* country_code */ + SSVAL(p,112,860); /* code page */ + } + } - *rdata_len = PTR_DIFF(p2,*rdata); + *rdata_len = PTR_DIFF(p2,*rdata); - SSVAL(*rparam,4,*rdata_len); /* is this right?? */ + SSVAL(*rparam,4,*rdata_len); /* is this right?? */ - return(True); + return(True); } - /******************************************************************* get groups that a user is a member of ******************************************************************/ @@ -2016,9 +2193,8 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, desc.subformat = NULL; desc.format = str2; - - - if (init_package(&desc,1,0)) { + if (init_package(&desc,1,0)) + { PACKI(&desc,"W",0); /* code */ PACKS(&desc,"B21",name); /* eff. name */ PACKS(&desc,"B",""); /* pad */ @@ -2027,7 +2203,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, PACKI(&desc,"D",0); /* auth flags XXX */ PACKI(&desc,"W",0); /* num logons */ PACKI(&desc,"W",0); /* bad pw count */ - PACKI(&desc,"D",-1); /* last logon */ + PACKI(&desc,"D",0); /* last logon */ PACKI(&desc,"D",-1); /* last logoff */ PACKI(&desc,"D",-1); /* logoff time */ PACKI(&desc,"D",-1); /* kickoff time */ @@ -2043,7 +2219,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, } PACKS(&desc,"z",lp_workgroup());/* domain */ PACKS(&desc,"z",lp_logon_script()); /* script path */ - PACKI(&desc,"D",0); /* reserved */ + PACKI(&desc,"D",0x00000000); /* reserved */ } *rdata_len = desc.usedlen; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1abcb8089f..57611553cc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2659,32 +2659,67 @@ int reply_lanman2(char *outbuf) return (smb_len(outbuf)+4); } + /**************************************************************************** reply for the nt protocol ****************************************************************************/ int reply_nt1(char *outbuf) { - int capabilities=0x300; /* has dual names + lock_and_read */ + /* dual names + lock_and_read + nt SMBs + remote API calls */ + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ; +/* + other valid capabilities which we may support at some time... + CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; + CAP_LARGE_FILES|CAP_LARGE_READX| + CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; + */ + int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); + int data_len; + int encrypt_len; + char challenge_len = 8; + + if (lp_readraw() && lp_writeraw()) + { + capabilities |= CAP_RAW_MODE; + } if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; - set_message(outbuf,17,doencrypt?8:0,True); + /* decide where (if) to put the encryption challenge, and + follow it with the OEM'd domain name + */ + encrypt_len = doencrypt?challenge_len:0; +#if UNICODE + data_len = encrypt_len + 2*(strlen(lp_workgroup())+1); +#else + data_len = encrypt_len + strlen(lp_workgroup()) + 1; +#endif + + set_message(outbuf,17,data_len,True); + +#if UNICODE + /* put the OEM'd domain name */ + PutUniCode(smb_buf(outbuf)+encrypt_len,lp_workgroup()); +#else + strcpy(smb_buf(outbuf)+encrypt_len, lp_workgroup()); +#endif + CVAL(outbuf,smb_vwv1) = secword; #ifdef SMB_PASSWD /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) { + if (doencrypt) + { generate_next_challenge(smb_buf(outbuf)); + /* Tell the nt machine how long the challenge is. */ - SSVALS(outbuf,smb_vwv16+1,8); + SSVALS(outbuf,smb_vwv16+1,challenge_len); } #endif - SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ - Protocol = PROTOCOL_NT1; if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { @@ -2694,21 +2729,19 @@ int reply_nt1(char *outbuf) #endif } - if (lp_readraw() && lp_writeraw()) - capabilities |= 1; - SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ - SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */ - SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */ + SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ + SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */ + SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ put_long_date(outbuf+smb_vwv11+1,t); SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); + SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */ return (smb_len(outbuf)+4); } - /* these are the protocol lists used for auto architecture detection: WinNT 3.51: -- cgit From aaba4712c8dbf61043d9fe6e1d6773bbd835e3b2 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sat, 15 Mar 1997 14:47:00 +0000 Subject: JHT ===> Moved MAJOR_VERSION and MINOR_VERSION defines to smb.h Made version info consistent in ipc.c and nameannounce.c Added define for BROWSER_ELECTION_VALUE and BROWSER_CONSTANT (see do_announce_host() in nameannounce.c). Sniffing with the latest bloodhound I found that the byte range occupied by the BROWSER_ELECTION_VALUE is interpreted depending on the type of announcement being made. In a Local_Master_Announcement it is BROWSER_ELECTION_VALUE but in both Workgroup_Announcement and Host_Announcement this is seen as Comment_String_Pointer. What does this mean? We need to know? (This used to be commit 86b0018cc7e246910a9a621b2bf379f782506a08) --- source3/smbd/ipc.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9f8369912c..3a2df56b3e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -60,9 +60,6 @@ extern fstring local_machine; #define SNLEN 15 /* service name length */ #define QNLEN 12 /* queue name maximum length */ -#define MAJOR_VERSION 4 -#define MINOR_VERSION 1 - extern int Client; static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, -- cgit From 121c81e3d68f1748f114a2530a9eb67f7f658fda Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 7 May 1997 17:56:46 +0000 Subject: added automount home directory support. contributed by simeon@bangor.co.uk and a mini bug-fix by rob.nacarrato@sheridanc.on.ca reads in an entry from the auto.home file for the user when they log in, and mounts their home directory as the default path for the [homes] service. i might add this as to the %substitution system, so that you can specify subdirectories for the user profiles, mainly. lkcl (This used to be commit 0bb6acc358243c49e19de9d5cc95f5124ac11b7c) --- source3/smbd/ipc.c | 32 +++++++++++++++++++--------- source3/smbd/password.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3a2df56b3e..9a80a8d062 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1947,6 +1947,7 @@ There is no auxiliary data in the response. #define AF_OP_SERVER 2 #define AF_OP_ACCOUNTS 3 + static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1959,10 +1960,17 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, int uLevel = SVAL(p,0); char *p2; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + /* get NIS home of a previously validated user - simeon */ + user_struct *vuser = get_valid_user_struct(vuid); + DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); + #if (defined(NETGROUP) && defined(AUTOMOUNT)) + DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); + #endif - /* check it's a supported varient */ + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + + /* check it's a supported variant */ if (strcmp(str1,"zWrLh") != 0) return False; switch( uLevel ) { @@ -2005,12 +2013,10 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ -#if 0 - strcpy(p2,"FullName"); -#endif - strcpy(p2,UserName); /* suggest copying the user name, for now... */ + strcpy(p2,vuser->real_name); /* simeon */ p2 = skip_string(p2,1); } + if (uLevel == 11) /* modelled after NTAS 3.51 reply */ { SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); @@ -2023,7 +2029,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, } else { +#if (defined(NETGROUP) && defined(AUTOMOUNT)) + strcpy(p2, vuser->home_share); +#else strcpy(p2,"\\\\%L\\%U"); +#endif } standard_sub_basic(p2); p2 = skip_string(p2,1); @@ -2067,7 +2077,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, } else { +#if (defined(NETGROUP) && defined(AUTOMOUNT)) + strcpy(p2, vuser->home_share); +#else strcpy(p2,"\\\\%L\\%U"); +#endif } standard_sub_basic(p2); p2 = skip_string(p2,1); @@ -2079,7 +2093,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strcpy(p2,""); + strcpy(p2,vuser->real_name); /* simeon */ p2 = skip_string(p2,1); SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ @@ -3066,5 +3080,3 @@ int reply_trans(char *inbuf,char *outbuf) return(outsize); } - - diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3ccc1e4cfd..2c24913c86 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,6 +21,10 @@ #include "includes.h" +#if (defined(NETGROUP) && defined (AUTOMOUNT)) +#include "rpcsvc/ypclnt.h" +#endif + extern int DEBUGLEVEL; extern int Protocol; @@ -138,6 +142,17 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) { user_struct *vuser; +#if (defined(NETGROUP) && defined (AUTOMOUNT)) + int nis_error; /* returned by yp all functions */ + char *nis_result; /* yp_match inits this */ + int nis_result_len; /* and set this */ + char *nis_domain; /* yp_get_default_domain inits this */ + char *nis_map = (char *)lp_nis_home_map_name(); + int home_server_len; +#endif + struct passwd *pwfile; /* for getting real name from passwd file */ + int real_name_len; + int i; for(i = 0; i < num_validated_users; i++) { vuser = &validated_users[i]; @@ -177,6 +192,46 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) DEBUG(3,("uid %d registered to name %s\n",uid,name)); +#if (defined(NETGROUP) && defined (AUTOMOUNT)) + vuser->home_share = NULL; + DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n")); + vuser->home_share = Realloc(vuser->home_share, 32); + strcpy(vuser->home_share,"\\\\%L\\HOMES"); + + if (nis_error = yp_get_default_domain(&nis_domain)) + DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); + DEBUG(3, ("NIS Domain: %s\n", nis_domain)); + + if (nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), + &nis_result, &nis_result_len)) + DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); + if (!nis_error && lp_nis_home_map()) { + home_server_len = strcspn(nis_result,":"); + DEBUG(3, ("NIS lookup succeeded\n\tHome server length: %d\n",home_server_len)); + vuser->home_share = (char *)Realloc(vuser->home_share, home_server_len+12); + DEBUG(3, ("\tAllocated %d bytes for HOMESHR\n",home_server_len+12 )); + strcpy(vuser->home_share,"\\\\"); + strncat(vuser->home_share, nis_result, home_server_len); + strcat(vuser->home_share,"\\homes"); + DEBUG(2,("\tUser = %s\n\tUID = %d\n\tNIS result = %s\n\tHOMESHR = %s\n", + vuser->name, vuser->uid, nis_result, vuser->home_share)); + } +#endif + + vuser->real_name = NULL; + DEBUG(3, ("Clearing default real name\n")); + vuser->real_name = Realloc(vuser->real_name, 15); + strcpy(vuser->real_name, "\0"); + if (lp_unix_realname()) { + pwfile=getpwnam(vuser->name); + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); + real_name_len = strcspn(pwfile->pw_gecos, ","); + DEBUG(3, ("Real name length: %d\n", real_name_len)); + vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1); + strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len); + vuser->real_name[real_name_len]='\0'; + } + return (uint16)((num_validated_users - 1) + VUID_OFFSET); } -- cgit From 0f1f0ceb9519368188f695e18e2341ccfd1b2d15 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 8 May 1997 01:14:17 +0000 Subject: '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. (This used to be commit cf23a155a1315f50d488794a2caf88402bf3e3e6) --- source3/smbd/dir.c | 2 +- source3/smbd/ipc.c | 2 +- source3/smbd/mangle.c | 2 +- source3/smbd/message.c | 2 +- source3/smbd/password.c | 2 +- source3/smbd/pipes.c | 2 +- source3/smbd/predict.c | 2 +- source3/smbd/quotas.c | 2 +- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/smbrun.c | 2 +- source3/smbd/trans2.c | 2 +- source3/smbd/uid.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f3c1ae020e..2437b8b17e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Directory handling routines - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9a80a8d062..1f1ac8600a 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3,7 +3,7 @@ Unix SMB/Netbios implementation. Version 1.9. Inter-process communication and named pipe handling - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 5fdf31b7a4..96e787b07f 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Name mangling - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 2ef5b246c4..93a2d9d850 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. SMB messaging - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2c24913c86..7885fd1bbc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Password and authentication handling - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 06f3aeb0fb..634d7af7f4 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Pipe SMB reply routines - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 7f1692931c..691d8fbb4e 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. file read prediction routines - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 05b40ada0f..eba76d4c74 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -3,7 +3,7 @@ Unix SMB/Netbios implementation. Version 1.9. support for quotas - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f532d613b4..bb75211deb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Main SMB reply routines - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 57611553cc..0f72efc478 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Main SMB server routines - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/smbrun.c b/source3/smbd/smbrun.c index d547c796e0..42ce7f60ad 100644 --- a/source3/smbd/smbrun.c +++ b/source3/smbd/smbrun.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. external program running routine - Copyright (C) Andrew Tridgell 1992-1995 + 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 diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2c0d5903e6..38c7031b66 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994 + Copyright (C) Jeremy Allison 1994-1997 Extensively modified by Andrew Tridgell, 1995 diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 4fa0ed89da..e2c5f590b7 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. uid/user handling - Copyright (C) Andrew Tridgell 1992-1995 + 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 -- cgit From aa864415c5183c948fe9ae221023d40265c38013 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 20 May 1997 00:32:51 +0000 Subject: dir.c: Fixed double slash issue. includes.h: Changed to ifdef FAST_SHARE_MODES. ipc.c: Changed lp_workgroup() to myworkgroup. loadparm.c: Added new shared mem parameters. Added Luke's fix. locking.c: Rewrite to do share modes better (both fast and slow modes). nameannounce.c: Changed lp_workgroup() to myworkgroup. Added Luke's fix. nameconf.c: Changed lp_workgroup() to myworkgroup. namedbname.c: Improved debug. namedbserver.c: Changed lp_workgroup() to myworkgroup. namedbsubnet.c: Added Luke's fix - rewritten somewhat. namedbwork.c: Changed lp_workgroup() to myworkgroup. nameelect.c: Added Luke's fix - rewritten somewhat. nameresp.c: Stoped shadowing global. nameserv.c: Added Luke's fix - Improved debug. nameservreply.c: Improved debug. namework.c: Changed lp_workgroup() to myworkgroup. nmbd.c: Added Luke's fix - Changed lp_workgroup() to myworkgroup. pipes.c: Changed lp_workgroup() to myworkgroup. proto.h: Added Luke's fix, added smb_shm_ proto's. reply.c: Changed lp_workgroup() to myworkgroup. server.c: Rewrite to do share modes better (both fast and slow modes). shmem.c: Rewrite to do share modes better (both fast and slow modes). smb.h: Rewrite to do share modes better (both fast and slow modes). status.c: Rewrite to do share modes better (both fast and slow modes). trans2.c: Fixed double slash issue. util.c: Tidied up, created myworkgroup. Jeremy Allison (jallison@whistle.com). (This used to be commit 2a1711eaaf08bb6776770cd3c96b3010f431a677) --- source3/smbd/dir.c | 7 +- source3/smbd/ipc.c | 13 +-- source3/smbd/pipes.c | 3 +- source3/smbd/reply.c | 3 +- source3/smbd/server.c | 288 +++++++++++++++++++++++++++++--------------------- source3/smbd/trans2.c | 4 +- 6 files changed, 186 insertions(+), 132 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 2437b8b17e..bc099dd1e8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -433,6 +433,7 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo BOOL isrootdir; pstring filename; BOOL matched; + BOOL needslash; *path = *pathreal = *filename = 0; @@ -440,6 +441,9 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo strequal(Connections[cnum].dirpath,".") || strequal(Connections[cnum].dirpath,"/")); + needslash = + ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/'); + if (!Connections[cnum].dirptr) return(False); @@ -467,7 +471,8 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo strcpy(fname,filename); *path = 0; strcpy(path,Connections[cnum].dirpath); - strcat(path,"/"); + if(needslash) + strcat(path,"/"); strcpy(pathreal,path); strcat(path,fname); strcat(pathreal,dname); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1f1ac8600a..8b9fb485ae 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -37,6 +37,7 @@ extern files_struct Files[]; extern connection_struct Connections[]; extern fstring local_machine; +extern fstring myworkgroup; #define NERR_Success 0 #define NERR_badpass 86 @@ -812,7 +813,7 @@ static int get_server_info(uint32 servertype, if (!next_token(&ptr,s->comment, NULL)) continue; if (!next_token(&ptr,s->domain , NULL)) { /* this allows us to cope with an old nmbd */ - strcpy(s->domain,lp_workgroup()); + strcpy(s->domain,myworkgroup); } if (sscanf(stype,"%X",&s->type) != 1) { @@ -982,7 +983,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); } else { - StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); + StrnCpy(domain, myworkgroup, sizeof(fstring)-1); } if (lp_browse_list()) @@ -1668,7 +1669,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, strcpy(comment,lp_serverstring()); - if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) { for (i=0;iref_count > 0) && - (((int32)sbuf->st_dev) == fd_ptr->dev) && - (((int32)sbuf->st_ino) == fd_ptr->inode)) { + (((uint32)sbuf->st_dev) == fd_ptr->dev) && + (((uint32)sbuf->st_ino) == fd_ptr->inode)) { fd_ptr->ref_count++; DEBUG(3, ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n", @@ -861,8 +861,8 @@ file_fd_struct *fd_get_new() for(i = 0; i < MAX_OPEN_FILES; i++) { fd_ptr = &FileFd[i]; if(fd_ptr->ref_count == 0) { - fd_ptr->dev = (int32)-1; - fd_ptr->inode = (int32)-1; + fd_ptr->dev = (uint32)-1; + fd_ptr->inode = (uint32)-1; fd_ptr->fd = -1; fd_ptr->fd_readonly = -1; fd_ptr->fd_writeonly = -1; @@ -927,8 +927,8 @@ int fd_attempt_close(file_fd_struct *fd_ptr) fd_ptr->fd_readonly = -1; fd_ptr->fd_writeonly = -1; fd_ptr->real_open_flags = -1; - fd_ptr->dev = -1; - fd_ptr->inode = -1; + fd_ptr->dev = (uint32)-1; + fd_ptr->inode = (uint32)-1; } } return fd_ptr->ref_count; @@ -1124,8 +1124,8 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s sbuf = &statbuf; } /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = (int32)sbuf->st_dev; - fd_ptr->inode = (int32)sbuf->st_ino; + fd_ptr->dev = (uint32)sbuf->st_dev; + fd_ptr->inode = (uint32)sbuf->st_ino; Files[fnum].fd_ptr = fd_ptr; Connections[cnum].num_files_open++; @@ -1141,7 +1141,6 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s Files[fnum].can_read = ((flags & O_WRONLY)==0); Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0); Files[fnum].share_mode = 0; - Files[fnum].share_pending = False; Files[fnum].print_file = Connections[cnum].printer; Files[fnum].modified = False; Files[fnum].cnum = cnum; @@ -1241,38 +1240,49 @@ close a file - possibly invalidating the read prediction ****************************************************************************/ void close_file(int fnum) { - int cnum = Files[fnum].cnum; - invalidate_read_prediction(Files[fnum].fd_ptr->fd); - Files[fnum].open = False; + files_struct *fs_p = &Files[fnum]; + int cnum = fs_p->cnum; + uint32 dev = fs_p->fd_ptr->dev; + uint32 inode = fs_p->fd_ptr->inode; + share_lock_token token; + + invalidate_read_prediction(fs_p->fd_ptr->fd); + fs_p->open = False; Connections[cnum].num_files_open--; - if(Files[fnum].wbmpx_ptr) + if(fs_p->wbmpx_ptr) { - free((char *)Files[fnum].wbmpx_ptr); - Files[fnum].wbmpx_ptr = NULL; + free((char *)fs_p->wbmpx_ptr); + fs_p->wbmpx_ptr = NULL; } #if USE_MMAP - if(Files[fnum].mmap_ptr) + if(fs_p->mmap_ptr) { - munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size); - Files[fnum].mmap_ptr = NULL; + munmap(fs_p->mmap_ptr,fs_p->mmap_size); + fs_p->mmap_ptr = NULL; } #endif if (lp_share_modes(SNUM(cnum))) - del_share_mode(fnum); + { + lock_share_entry( cnum, dev, inode, &token); + del_share_mode(token, fnum); + } + + fd_attempt_close(fs_p->fd_ptr); - fd_attempt_close(Files[fnum].fd_ptr); + if (lp_share_modes(SNUM(cnum))) + unlock_share_entry( cnum, dev, inode, token); /* NT uses smbclose to start a print - weird */ - if (Files[fnum].print_file) + if (fs_p->print_file) print_file(fnum); /* check for magic scripts */ check_magic(fnum,cnum); DEBUG(2,("%s %s closed file %s (numopen=%d)\n", - timestring(),Connections[cnum].user,Files[fnum].name, + timestring(),Connections[cnum].user,fs_p->name, Connections[cnum].num_files_open)); } @@ -1334,17 +1344,44 @@ return True if sharing doesn't prevent the operation ********************************************************************/ BOOL check_file_sharing(int cnum,char *fname) { - int pid=0; - int share_mode = get_share_mode_byname(cnum,fname,&pid); + int i; + int ret = False; + min_share_mode_entry *old_shares = 0; + int num_share_modes; + struct stat sbuf; + share_lock_token token; + int pid = getpid(); - if (!pid || !share_mode) return(True); - - if (share_mode == DENY_DOS) - return(pid == getpid()); + if(!lp_share_modes(SNUM(cnum))) + return True; + + if (stat(fname,&sbuf) == -1) return(True); + + lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token); + num_share_modes = get_share_modes(cnum, token, + (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares); + + for( i = 0; i < num_share_modes; i++) + { + if (old_shares[i].share_mode != DENY_DOS) + goto free_and_exit; + + if(old_shares[i].pid != pid); + goto free_and_exit; + } /* XXXX exactly what share mode combinations should be allowed for deleting/renaming? */ - return(False); + /* If we got here then either there were no share modes or + all share modes were DENY_DOS and the pid == getpid() */ + ret = True; + +free_and_exit: + + unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token); + if(old_shares != NULL) + free((char *)old_shares); + return(ret); } /**************************************************************************** @@ -1373,25 +1410,31 @@ open a file with a share mode void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int mode,int *Access,int *action) { + files_struct *fs_p = &Files[fnum]; int flags=0; int flags2=0; int deny_mode = (share_mode>>4)&7; struct stat sbuf; BOOL file_existed = file_exist(fname,&sbuf); + BOOL share_locked = False; BOOL fcbopen = False; - int share_pid=0; + share_lock_token token; + uint32 dev = 0; + uint32 inode = 0; - Files[fnum].open = False; - Files[fnum].fd_ptr = 0; + fs_p->open = False; + fs_p->fd_ptr = 0; /* this is for OS/2 EAs - try and say we don't support them */ - if (strstr(fname,".+,;=[].")) { + if (strstr(fname,".+,;=[].")) + { unix_ERR_class = ERRDOS; unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; return; } - if ((ofun & 0x3) == 0 && file_existed) { + if ((ofun & 0x3) == 0 && file_existed) + { errno = EEXIST; return; } @@ -1405,7 +1448,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, append does not mean the same thing under dos and unix */ switch (share_mode&0xF) - { + { case 1: flags = O_WRONLY; break; @@ -1419,18 +1462,21 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, default: flags = O_RDONLY; break; - } + } if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) { - if (!fcbopen) { + (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) + { + if (!fcbopen) + { errno = EACCES; return; } flags = O_RDONLY; } - if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { + if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) + { DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); errno = EINVAL; return; @@ -1438,21 +1484,36 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; - if (lp_share_modes(SNUM(cnum))) { - int old_share=0; + if (lp_share_modes(SNUM(cnum))) + { + int num_shares = 0; + int i; + min_share_mode_entry *old_shares = 0; + if (file_existed) - old_share = get_share_mode(cnum,&sbuf,&share_pid); + { + dev = (uint32)sbuf.st_dev; + inode = (uint32)sbuf.st_ino; + lock_share_entry(cnum, dev, inode, &token); + share_locked = True; + num_shares = get_share_modes(cnum, token, dev, inode, &old_shares); + } - if (share_pid) { + for(i = 0; i < num_shares; i++) + { /* someone else has a share lock on it, check to see if we can too */ - int old_open_mode = old_share&0xF; - int old_deny_mode = (old_share>>4)&7; + int old_open_mode = old_shares[i].share_mode &0xF; + int old_deny_mode = (old_shares[i].share_mode >>4)&7; - if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) { + if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) + { DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n", deny_mode,old_deny_mode,old_open_mode,fname)); + free((char *)old_shares); + if(share_locked) + unlock_share_entry(cnum, dev, inode, token); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -1461,21 +1522,25 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share_pid,fname); + old_shares[i].pid,fname); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) || (access_allowed == AREAD && flags == O_WRONLY) || - (access_allowed == AWRITE && flags == O_RDONLY)) { + (access_allowed == AWRITE && flags == O_RDONLY)) + { DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", deny_mode,old_deny_mode,old_open_mode, - share_pid,fname, + old_shares[i].pid,fname, access_allowed)); + free((char *)old_shares); + if(share_locked) + unlock_share_entry(cnum, dev, inode, token); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; return; - } + } if (access_allowed == AREAD) flags = O_RDONLY; @@ -1484,76 +1549,69 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, flags = O_WRONLY; } } + if(old_shares != 0) + free((char *)old_shares); } DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,mode)); open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); - if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) { + if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen) + { flags = O_RDONLY; open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 ); } - if (Files[fnum].open) { + if (fs_p->open) + { int open_mode=0; - switch (flags) { - case O_RDONLY: - open_mode = 0; - break; - case O_RDWR: - open_mode = 2; - break; - case O_WRONLY: - open_mode = 1; - break; + + if((share_locked == False) && lp_share_modes(SNUM(cnum))) + { + /* We created the file - thus we must now lock the share entry before creating it. */ + dev = fs_p->fd_ptr->dev; + inode = fs_p->fd_ptr->inode; + lock_share_entry(cnum, dev, inode, &token); + share_locked = True; } - Files[fnum].share_mode = (deny_mode<<4) | open_mode; - Files[fnum].share_pending = True; + switch (flags) + { + case O_RDONLY: + open_mode = 0; + break; + case O_RDWR: + open_mode = 2; + break; + case O_WRONLY: + open_mode = 1; + break; + } + + fs_p->share_mode = (deny_mode<<4) | open_mode; - if (Access) { + if (Access) (*Access) = open_mode; - } - - if (action) { + + if (action) + { if (file_existed && !(flags2 & O_TRUNC)) *action = 1; if (!file_existed) *action = 2; if (file_existed && (flags2 & O_TRUNC)) *action = 3; } - if (!share_pid) - share_mode_pending = True; - if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fnum,cnum); - } -} - + if (lp_share_modes(SNUM(cnum))) + set_share_mode(token, fnum); + } -/******************************************************************* -check for files that we should now set our share modes on -********************************************************************/ -static void check_share_modes(void) -{ - int i; - for (i=0;i= IDLE_CLOSED_TIMEOUT) { @@ -4082,6 +4124,8 @@ static void usage(char *pname) if (!reload_services(False)) return(-1); + strcpy(myworkgroup, lp_workgroup()); + #ifndef NO_SIGNAL_TEST signal(SIGHUP,SIGNAL_CAST sig_hup); #endif @@ -4128,10 +4172,10 @@ static void usage(char *pname) if (!open_sockets(is_daemon,port)) exit(1); -#if FAST_SHARE_MODES +#ifdef FAST_SHARE_MODES if (!start_share_mode_mgmt()) exit(1); -#endif +#endif /* FAST_SHARE_MODES */ /* possibly reload the services file. */ reload_services(True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 38c7031b66..1d9977c66e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -277,6 +277,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l strequal(Connections[cnum].dirpath,"/")); BOOL was_8_3; int nt_extmode; /* Used for NT connections instead of mode */ + BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/'); *fname = 0; *out_of_space = False; @@ -323,7 +324,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l continue; strcpy(pathreal,Connections[cnum].dirpath); - strcat(pathreal,"/"); + if(needslash) + strcat(pathreal,"/"); strcat(pathreal,fname); if (sys_stat(pathreal,&sbuf) != 0) { -- cgit From 71e5f97555a454d81274a937af59b76fe8207925 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 21 May 1997 01:09:51 +0000 Subject: Added fix from Paul Nelson @ Thursby - smb_mid field could be corrupted if security = server. jallison@whistle.com (This used to be commit 52da1897ce4428f5e2a6c0306aecb8109b43ebd8) --- source3/smbd/server.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index fe0868b34a..65e620c7f0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2638,6 +2638,11 @@ int reply_lanman1(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); + /* We need to save and restore this as it can be destroyed + if we call another server if security=server + Thanks to Paul Nelson @ Thursby for pointing this out. + */ + uint16 mid = SVAL(outbuf, smb_mid); if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; @@ -2660,6 +2665,7 @@ int reply_lanman1(char *outbuf) } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ SSVAL(outbuf,smb_vwv4,1); @@ -2683,6 +2689,11 @@ int reply_lanman2(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); + /* We need to save and restore this as it can be destroyed + if we call another server if security=server + Thanks to Paul Nelson @ Thursby for pointing this out. + */ + uint16 mid = SVAL(outbuf, smb_mid); if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; @@ -2707,6 +2718,7 @@ int reply_lanman2(char *outbuf) } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); SSVAL(outbuf,smb_vwv4,1); @@ -2738,6 +2750,11 @@ int reply_nt1(char *outbuf) int data_len; int encrypt_len; char challenge_len = 8; + /* We need to save and restore this as it can be destroyed + if we call another server if security=server + Thanks to Paul Nelson @ Thursby for pointing this out. + */ + uint16 mid = SVAL(outbuf, smb_mid); if (lp_readraw() && lp_writeraw()) { @@ -2787,6 +2804,7 @@ int reply_nt1(char *outbuf) #endif } + SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ -- cgit From ccf4314fe73fb035f6941f00ce952ba3a308c2da Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 27 May 1997 20:28:45 +0000 Subject: loadparm.c: Ensure printer services cannot be read only and don't use share mode locking. locking.c: Changed aborts to returns so not so drastic on PANIC errors. proto.h: Removed definition of open_file as this is now never externally called. reply.c: Changed reply_mknew, reply_ctemp, reply_printopen to go through open_file_shared. server.c: Modified open_file_shared to be more robust and be useful for printer & temp files. Removed truncate option from open_file (now all truncates are done in open_file_shared). util.c: Added EAGAIN to errors checked in open_socket_out(). version.h: Updated to 1.9.17alpha2. jallison@whistle.com (This used to be commit d8471909b79fd591be2b789485b65d2e636d4745) --- source3/smbd/reply.c | 30 +++++++++++++++++++++--------- source3/smbd/server.c | 31 +++++++++++++++++-------------- 2 files changed, 38 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 639c386c2f..530ce84895 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1135,7 +1135,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** - reply to a mknew + reply to a mknew or a create ****************************************************************************/ int reply_mknew(char *inbuf,char *outbuf) { @@ -1145,7 +1145,8 @@ int reply_mknew(char *inbuf,char *outbuf) int outsize = 0; int createmode; mode_t unixmode; - + int ofun = 0; + com = SVAL(inbuf,smb_com); cnum = SVAL(inbuf,smb_tid); @@ -1160,9 +1161,6 @@ int reply_mknew(char *inbuf,char *outbuf) unixmode = unix_mode(cnum,createmode); - if (com == SMBmknew && file_exist(fname,NULL)) - return(ERROR(ERRDOS,ERRfilexists)); - fnum = find_free_file(); if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); @@ -1170,7 +1168,19 @@ int reply_mknew(char *inbuf,char *outbuf) if (!check_name(fname,cnum)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0); + if(com == SMBmknew) + { + /* We should fail if file exists. */ + ofun = 0x10; + } + else + { + /* SMBcreate - Create if file doesn't exist, truncate if it does. */ + ofun = 0x12; + } + + /* Open file in dos compatibility share mode. */ + open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1218,7 +1228,9 @@ int reply_ctemp(char *inbuf,char *outbuf) strcpy(fname2,(char *)mktemp(fname)); - open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0); + /* Open file in dos compatibility share mode. */ + /* We should fail if file exists. */ + open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2219,8 +2231,8 @@ int reply_printopen(char *inbuf,char *outbuf) if (!check_name(fname2,cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC, - unix_mode(cnum,0), 0); + /* Open for exclusive use, write only. */ + open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 65e620c7f0..4ae139fc58 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -937,7 +937,7 @@ int fd_attempt_close(file_fd_struct *fd_ptr) /**************************************************************************** open a file ****************************************************************************/ -void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) +static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) { extern struct current_user current_user; pstring fname; @@ -1033,14 +1033,6 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s return; } - /* - * If O_TRUNC was set, ensure we truncate the file. - * open_file_shared explicitly clears this flag before - * calling open_file, so we can safely do this here. - */ - if(flags & O_TRUNC) - ftruncate(fd_ptr->fd, 0); - } else { int open_flags; /* We need to allocate a new file_fd_struct (this increments the @@ -1389,11 +1381,19 @@ free_and_exit: Helper for open_file_shared. Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(int fnum, int cnum) +static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, + BOOL *share_locked) { if (Files[fnum].can_write){ if (is_locked(fnum,cnum,0x3FFFFFFF,0)){ + /* If share modes are in force for this connection we + have the share entry locked. Unlock it before closing. */ + if (*share_locked && lp_share_modes(SNUM(cnum))) + unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, + Files[fnum].fd_ptr->inode, token); close_file(fnum); + /* Share mode no longer locked. */ + *share_locked = False; errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; @@ -1600,12 +1600,15 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (!file_existed) *action = 2; if (file_existed && (flags2 & O_TRUNC)) *action = 3; } - - if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fnum,cnum); - + /* We must create the share mode entry before truncate as + truncate can fail due to locking and have to close the + file (which expects the share_mode_entry to be there). + */ if (lp_share_modes(SNUM(cnum))) set_share_mode(token, fnum); + + if ((flags2&O_TRUNC) && file_existed) + truncate_unless_locked(fnum,cnum,token,&share_locked); } if (share_locked && lp_share_modes(SNUM(cnum))) -- cgit From 3ab97ebe6db1a5a4a0573c7c8482c94876bbce9a Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 30 May 1997 20:40:48 +0000 Subject: charcnv.c: Fixed silly bugs detected on IRIX. client.c: Fixed silly bugs detected on IRIX. namedbname.c: Stopped 1d names from being registered in WINS db. namedbsubnet.c: Only register 1e names on broadcast subnet. nameelect.c: Changed add_my_name entries. Forced host announces if we have less than 10 servers listed. Fixed registering 1b domain name issues. namepacket.c: Added error message when dgram discarded. nameserv.c: Added notion of 'direct' names that are not registered on the network. Needed to get around bugs in earlier nmbd handling of DOMAIN(1b) names. nameservreply.c:Tidied up debug message. nameservresp.c: Added response_name_query_domain() code. Deals with re-registering DOMAIN(1b) name. nmbd.c: Fixed silly bugs detected on IRIX. nmblib.c: Added paranoia debugs. proto.h: Updated remove_name_entry(), add_my_name_entry(). server.c: Fixed silly bugs detected on IRIX. trans2.c: Fixed silly bugs detected on IRIX. uid.c: Fixed silly bugs detected on IRIX. version.h: Updated to alpha3. Jeremy (jallison@whistle.com). (This used to be commit f08222bd8b86a061c52d22015f946a4737eb47fd) --- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 1 - source3/smbd/uid.c | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4ae139fc58..51710b7b77 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1358,7 +1358,7 @@ BOOL check_file_sharing(int cnum,char *fname) if (old_shares[i].share_mode != DENY_DOS) goto free_and_exit; - if(old_shares[i].pid != pid); + if(old_shares[i].pid != pid) goto free_and_exit; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1d9977c66e..1f727c4ecd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -941,7 +941,6 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), vname)); break; - break; case SMB_QUERY_FS_SIZE_INFO: { int dfree,dsize,bsize; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index e2c5f590b7..7a903e0551 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -466,6 +466,5 @@ int smbrun(char *cmd,char *outfile,BOOL shared) /* not reached */ exit(82); #endif + return 1; } - - -- cgit From 548196362bf5f81de823a075e86bb9ac10e6b14b Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 6 Jun 1997 16:14:17 +0000 Subject: loadparm.c: Made explicit max packet now ignored. namedbwork.c: Don't announce potential browser if local master = False. nameelect.c: Raise debug level of comment to 2. proto.h: Added reset_globals_after_fork(). server.c: Call reset_globals_after_fork() after forking child. util.c: Added reset_globals_after_fork() - should stop problems with % substitutions in children. (This used to be commit 77be0f710cc96441d966ab7b026a0d591b01ffb0) --- source3/smbd/server.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 51710b7b77..299ae07aa3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2065,6 +2065,7 @@ static BOOL open_sockets(BOOL is_daemon,int port) #else if (Client != -1 && fork()==0) { + /* Child code ... */ #ifndef NO_SIGNAL_TEST signal(SIGPIPE, SIGNAL_CAST sig_pipe); signal(SIGCLD, SIGNAL_CAST SIG_DFL); @@ -2079,6 +2080,11 @@ static BOOL open_sockets(BOOL is_daemon,int port) set_socket_options(Client,"SO_KEEPALIVE"); set_socket_options(Client,user_socket_options); + /* Reset global variables in util.c so that + client substitutions will be done correctly + in the process. + */ + reset_globals_after_fork(); return True; } close(Client); /* The parent doesn't need this socket */ @@ -3119,7 +3125,7 @@ BOOL yield_connection(int cnum,char *name,int max_connections) f = fopen(fname,"r+"); if (!f) { - DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno))); + DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno))); return(False); } -- cgit From c6e63aa896a10656f6205828e744b722fc72f8ac Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 11 Jun 1997 01:03:06 +0000 Subject: Makefile: Added quoata changes for Linux from Thorvald Natvig Makefile.RPM: Added quoata changes for Linux from Thorvald Natvig charset.c: Large changes to add multiple client code pages. charset.h: Changed charset_initialise() proto. client.c: Fixed message sending bug. Changed charset_initialise(). ipc.c: Fixed #ifdef compile problems. loadparm.c: Added "client code page" option. nmbd.c: Changed charset_initialise(). Fixed lmhosts read. nmblookup.c: Changed charset_initialise(). proto.h: Added lp_client_code_page(void). quotas.c: Added quoata changes for Linux from Thorvald Natvig reply.c: Changed debug level. Made SMBecho ignore tid. server.c: Changed charset_initialise(). smb.h: Added DEFAULT_CLIENT_CODE_PAGE as 850. smbpasswd.c: Changed charset_initialise(). status.c: Changed charset_initialise(). testparm.c: Changed charset_initialise(). testprns.c: Changed charset_initialise(). Jeremy Allison (jallison@whistle.com) (This used to be commit 957025bace1bcff34d21a6caeca498e85abccb23) --- source3/smbd/ipc.c | 4 +-- source3/smbd/quotas.c | 94 +++++++++++++++++++++++---------------------------- source3/smbd/reply.c | 8 ++++- source3/smbd/server.c | 4 ++- 4 files changed, 54 insertions(+), 56 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8b9fb485ae..6b3953e6c8 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1964,9 +1964,9 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /* get NIS home of a previously validated user - simeon */ user_struct *vuser = get_valid_user_struct(vuid); DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); - #if (defined(NETGROUP) && defined(AUTOMOUNT)) +#if (defined(NETGROUP) && defined(AUTOMOUNT)) DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); - #endif +#endif *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index eba76d4c74..a1d29bcd12 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -33,47 +33,43 @@ extern int DEBUGLEVEL; #ifdef LINUX -#ifdef __KERNEL__ -# undef __KERNEL__ -# include -# define __KERNEL__ -#else -# include -#endif +#include +#include +#include #include +#include + +_syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr); /**************************************************************************** try to get the disk space from disk quotas (LINUX version) ****************************************************************************/ -/* -If you didn't make the symlink to the quota package, too bad :( -*/ -#include "quota/quotactl.c" -#include "quota/hasquota.c" + BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { uid_t euser_id; + int r; + char dev_disk[256]; struct dqblk D; struct stat S; - dev_t devno ; - struct mntent *mnt; FILE *fp; - int found ; - int qcmd, fd ; - char *qfpathname; + struct mntent *mnt; + int devno; + int found; /* find the block device file */ - if ( stat(path, &S) == -1 ) + if ( stat(path, &S) == -1 ) { return(False) ; + } devno = S.st_dev ; fp = setmntent(MOUNTED,"r"); found = False ; - while ((mnt = getmntent(fp)) != (struct mntent *) 0) { + while ((mnt = getmntent(fp))) { if ( stat(mnt->mnt_dir,&S) == -1 ) continue ; if (S.st_dev == devno) { @@ -83,48 +79,42 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } endmntent(fp) ; - if ( ! found ) - return(False) ; - - qcmd = QCMD(Q_GETQUOTA, USRQUOTA); - - if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA)) - return(False) ; - - if (!hasquota(mnt, USRQUOTA, &qfpathname)) - return(False) ; - - euser_id = geteuid(); - seteuid(0); - - if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) { - if ((fd = open(qfpathname, O_RDONLY)) < 0) { - seteuid(euser_id); + if (!found) { return(False); } - lseek(fd, (long) dqoff(euser_id), L_SET); - switch (read(fd, &D, sizeof(struct dqblk))) { - case 0:/* EOF */ - memset((caddr_t)&D, 0, sizeof(struct dqblk)); - break; - case sizeof(struct dqblk): /* OK */ - break; - default: /* ERROR */ - close(fd); + + euser_id=geteuid(); + seteuid(0); + r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D); seteuid(euser_id); - return(False); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = 1024; + if (r) + { + if (errno == EDQUOT) + { + *dfree =0; + *dsize =D.dqb_curblocks; + return (True); } + else return(False); } - seteuid(euser_id); - *bsize=1024; - - if (D.dqb_bsoftlimit==0) - return(False); - if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit)) + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) || + (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) || + (D.dqb_isoftlimit && D.dqb_curinodes>=D.dqb_isoftlimit) || + (D.dqb_ihardlimit && D.dqb_curinodes>=D.dqb_ihardlimit) + ) { *dfree = 0; *dsize = D.dqb_curblocks; } + else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0) + { + return(False); + } else { *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; *dsize = D.dqb_bsoftlimit; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 530ce84895..8af4536c19 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -513,7 +513,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); - DEBUG(0,(" Client requested max send size of %d\n", max_send)); + DEBUG(1,(" Client requested max send size of %d\n", max_send)); done_sesssetup = True; @@ -2156,11 +2156,17 @@ int reply_echo(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); + /* According to the latest CIFS spec we shouldn't + care what the TID is. + */ + +#if 0 if (cnum != 0xFFFF && !OPEN_CNUM(cnum)) { DEBUG(4,("Invalid cnum in echo (%d)\n",cnum)); return(ERROR(ERRSRV,ERRinvnid)); } +#endif /* copy any incoming data back out */ if (data_len > 0) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 299ae07aa3..a44745496b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4036,7 +4036,7 @@ static void usage(char *pname) setup_logging(argv[0],False); - charset_initialise(); + charset_initialise(-1); /* make absolutely sure we run as root - to handle cases whre people are crazy enough to have it setuid */ @@ -4151,6 +4151,8 @@ static void usage(char *pname) if (!reload_services(False)) return(-1); + charset_initialise(lp_client_code_page()); + strcpy(myworkgroup, lp_workgroup()); #ifndef NO_SIGNAL_TEST -- cgit From 2a33e58d18f400a05aeef00ba27f2b3c12ac315c Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 16 Jun 1997 20:49:15 +0000 Subject: charset.c: Dropped debug message to level 6. loadparm.c: Added "time server" parameter. nameserv.h: Added "time server" parameter. proto.h: Added lp_time_server(). server.c: Removed incorrect | 0700 - this was a whistle specific change. Jeremy (jallison@whistle.com). (This used to be commit 54dcca1240ec0a7f107f8a77e0893855015f9d29) --- source3/smbd/server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a44745496b..c808eac06a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -141,8 +141,10 @@ mode_t unix_mode(int cnum,int dosmode) result |= (S_IWUSR | S_IWGRP | S_IWOTH); if (IS_DOS_DIR(dosmode)) { + /* We never make directories read only for the owner as under DOS a user + can always create a file in a read-only directory. */ result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); - result &= (lp_dir_mode(SNUM(cnum)) | 0700); + result &= lp_dir_mode(SNUM(cnum)); } else { if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode)) result |= S_IXUSR; -- cgit From 16c87e9198ab645df15209370288fefbd832f81e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 18 Jun 1997 01:04:57 +0000 Subject: Fixed *really* stupid bug in register_vuid - only a problem on multi-user NT systems. Jeremy (jallison@whistle.com) (This used to be commit 6ca5c8ca3294cde56e28558bcb02c144225903d8) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 7885fd1bbc..803418c97e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -157,7 +157,7 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) for(i = 0; i < num_validated_users; i++) { vuser = &validated_users[i]; if( vuser->uid == uid ) - return i; /* User already validated */ + return (uint16)(i + VUID_OFFSET); /* User already validated */ } validated_users = (user_struct *)Realloc(validated_users, -- cgit From 434d26acfe3bea62217b5ceaafc8b7b9cbe6e914 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 19 Jun 1997 00:18:23 +0000 Subject: loadparm.c: Added "force create mode" and "force directory mode" params. proto.h: Added lp_force_create_mode() and lp_force_dir_mode(). server.c: Fixed application of mode bits to be regular across files and directories. smb.h: Removed unused CREATE_MODE macro. Jeremy (jallison@whistle.com) (This used to be commit 2c928212500e1de27550d9fccb0939fd2e450515) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/server.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c808eac06a..203bdb8da8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -130,8 +130,12 @@ void killkids(void) dos archive is represented in unix by the user's execute bit dos system is represented in unix by the group's execute bit dos hidden is represented in unix by the other's execute bit + Then apply create mask, + then add force bits. base permission for directories: dos directory is represented in unix by unix's dir bit and the exec bit + Then apply create mask, + then add force bits. ****************************************************************************/ mode_t unix_mode(int cnum,int dosmode) { @@ -144,7 +148,10 @@ mode_t unix_mode(int cnum,int dosmode) /* We never make directories read only for the owner as under DOS a user can always create a file in a read-only directory. */ result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); + /* Apply directory mask */ result &= lp_dir_mode(SNUM(cnum)); + /* Add in force bits */ + result |= lp_force_dir_mode(SNUM(cnum)); } else { if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode)) result |= S_IXUSR; @@ -155,7 +162,10 @@ mode_t unix_mode(int cnum,int dosmode) if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode)) result |= S_IXOTH; - result &= CREATE_MODE(cnum); + /* Apply mode mask */ + result &= lp_create_mode(SNUM(cnum)); + /* Add in force bits */ + result |= lp_force_create_mode(SNUM(cnum)); } return(result); } -- cgit From 9e37076f2b8514a010008db44def4355e52379c2 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 27 Jun 1997 00:26:59 +0000 Subject: shmem.c: Changed debug to higher level uid.c: Stop smbrun from deleting device files. util.c: Added EAGAIN to known error list. Jeremy (jallison@whistle.com) (This used to be commit c07db8d8e7e4a421501a08efe999e9ccd7337855) --- source3/smbd/uid.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 7a903e0551..0cf1c217a9 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -339,7 +339,9 @@ the child as it may leave the caller in a privilaged state. static BOOL setup_stdout_file(char *outfile,BOOL shared) { int fd; + struct stat st; mode_t mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH; + int flags = O_RDWR|O_CREAT|O_TRUNC|O_EXCL; close(1); @@ -354,9 +356,15 @@ static BOOL setup_stdout_file(char *outfile,BOOL shared) #endif } - /* now create the file with O_EXCL set */ - unlink(outfile); - fd = open(outfile,O_RDWR|O_CREAT|O_TRUNC|O_EXCL,mode); + if(stat(outfile, &st) == 0) { + /* Check we're not deleting a device file. */ + if(st.st_mode & S_IFREG) + unlink(outfile); + else + flags = O_RDWR; + } + /* now create the file */ + fd = open(outfile,flags,mode); if (fd == -1) return False; -- cgit From fb1429c1970bc123e191f0cb7cc764faf4b86998 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 1 Jul 1997 01:19:13 +0000 Subject: client.c: New print queue query code from Jeff C. Foster " ipc.c: Added code for returning restricted lists of servers. loadparm.c: Changed default for force create mode to 000. Changed default maxmux to 50 to comply with NT. locking.c: Fixed silly crash bug with slow share mode code. nameannounce.c: Added code for returning restricted lists of servers. namedbserver.c: Added code for returning restricted lists of servers. nameelect.c: Added code for returning restricted lists of servers. namework.c: Added code for returning restricted lists of servers. nmbsync.c: Added code for returning restricted lists of servers. server.c: Added quota fix Albrecht Gebhardt smb.h: Added define for COPYBUF_SIZE. system.c: Rename across filesystems Patch from Warren Birnbaum util.c: Minor fix for warning. (This used to be commit 1c6e433caa22813a699c9766847886eb59755f8b) --- source3/smbd/ipc.c | 17 ++++++++++- source3/smbd/server.c | 83 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 77 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6b3953e6c8..7922e41623 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -770,6 +770,7 @@ static int get_server_info(uint32 servertype, int count=0; int alloced=0; pstring line; + BOOL local_list_only; strcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); @@ -784,7 +785,10 @@ static int get_server_info(uint32 servertype, } /* request for everything is code for request all servers */ - if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM; + if (servertype == SV_TYPE_ALL) + servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + + local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); DEBUG(4,("Servertype search: %8x\n",servertype)); @@ -821,6 +825,14 @@ static int get_server_info(uint32 servertype, ok = False; } + /* Filter the servers/domains we return based on what was asked for. */ + + /* Check to see if we are being asked for a local list only. */ + if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) { + DEBUG(4,("r: local list only")); + ok = False; + } + /* doesn't match up: don't want it */ if (!(servertype & s->type)) { DEBUG(4,("r:serv type ")); @@ -839,6 +851,9 @@ static int get_server_info(uint32 servertype, ok = False; } + /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ + s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; + if (ok) { DEBUG(4,("**SV** %20s %8x %25s %15s\n", diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 203bdb8da8..8c40734ce4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -603,6 +603,14 @@ static void disk_norm(int *bsize,int *dfree,int *dsize) int disk_free(char *path,int *bsize,int *dfree,int *dsize) { char *df_command = lp_dfree_command(); + int dfree_retval; +#ifdef QUOTAS + int dfreeq_retval; + int dfreeq = 0; + int bsizeq = *bsize; + int dsizeq = *dsize; +#endif + #ifndef NO_STATFS #ifdef USE_STATVFS struct statvfs fs; @@ -615,15 +623,6 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) #endif #endif -#ifdef QUOTAS - if (disk_quotas(path, bsize, dfree, dsize)) - { - disk_norm(bsize,dfree,dsize); - return(((*bsize)/1024)*(*dfree)); - } -#endif - - /* possibly use system() to get the result */ if (df_command && *df_command) { @@ -639,22 +638,42 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); { - FILE *f = fopen(outfile,"r"); - *dsize = 0; - *dfree = 0; - *bsize = 1024; - if (f) - { - fscanf(f,"%d %d %d",dsize,dfree,bsize); - fclose(f); - } - else - DEBUG(0,("Can't open %s\n",outfile)); + FILE *f = fopen(outfile,"r"); + *dsize = 0; + *dfree = 0; + *bsize = 1024; + if (f) + { + fscanf(f,"%d %d %d",dsize,dfree,bsize); + fclose(f); + } + else + DEBUG(0,("Can't open %s\n",outfile)); } unlink(outfile); disk_norm(bsize,dfree,dsize); - return(((*bsize)/1024)*(*dfree)); + dfree_retval = ((*bsize)/1024)*(*dfree); +#ifdef QUOTAS + /* Ensure we return the min value between the users quota and + what's free on the disk. Thanks to Albrecht Gebhardt + for this fix. + */ + if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq)) + { + disk_norm(&bsizeq, &dfreeq, &dsizeq); + dfreeq_retval = ((bsizeq)/1024)*(dfreeq); + dfree_retval = ( dfree_retval < dfreeq_retval ) ? + dfree_retval : dfreeq_retval ; + /* maybe dfree and dfreeq are calculated using different bsizes + so convert dfree from bsize into bsizeq */ + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; + *bsize = bsizeq; + *dsize = dsizeq; + } +#endif + return(dfree_retval); } #ifdef NO_STATFS @@ -724,7 +743,27 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; *dsize = 20*1024*1024/(*bsize); *dfree = MAX(1,*dfree); } - return(((*bsize)/1024)*(*dfree)); + dfree_retval = ((*bsize)/1024)*(*dfree); +#ifdef QUOTAS + /* Ensure we return the min value between the users quota and + what's free on the disk. Thanks to Albrecht Gebhardt + for this fix. + */ + if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq)) + { + disk_norm(&bsizeq, &dfreeq, &dsizeq); + dfreeq_retval = ((bsizeq)/1024)*(dfreeq); + dfree_retval = ( dfree_retval < dfreeq_retval ) ? + dfree_retval : dfreeq_retval ; + /* maybe dfree and dfreeq are calculated using different bsizes + so convert dfree from bsize into bsizeq */ + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; + *bsize = bsizeq; + *dsize = dsizeq; + } +#endif + return(dfree_retval); #endif } -- cgit From 738d29667f9cd1ce312ec011f5e37ce584d7173d Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 1 Jul 1997 19:02:43 +0000 Subject: added "hide files" option. lkcl (This used to be commit 6e594ce0e5a3af5e7311380d18ff0d19ba9698a7) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8c40734ce4..30cf9cb016 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -222,6 +222,11 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aHIDDEN; } + if (is_hidden_path(path)) + { + result |= aHIDDEN; + } + return(result); } -- cgit From ce9baa3bac6eba5f7a468557572f342d3ba918ec Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 1 Jul 1997 19:42:42 +0000 Subject: made "hide files" and "veto files" into per-service parameter sections, instead of just [global]. this makes it easier to decide whether to remove the "hide dot files" per-service parameter, and supercede it with a default "hide files" value of ".*". lkcl (This used to be commit f3ee4620ea7b93e4a00e77f9d787a118fd11ccaa) --- source3/smbd/dir.c | 22 +++++++++++----------- source3/smbd/server.c | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index bc099dd1e8..f674c92804 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -108,7 +108,7 @@ static void dptr_idleoldest(void) /**************************************************************************** get the dir ptr for a dir index ****************************************************************************/ -static void *dptr_get(int key,uint32 lastused) +static void *dptr_get(int cnum, int key,uint32 lastused) { if (dirptrs[key].valid) { if (lastused) dirptrs[key].lastused = lastused; @@ -116,7 +116,7 @@ static void *dptr_get(int key,uint32 lastused) if (dptrs_open >= MAXDIR) dptr_idleoldest(); DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path))) + if ((dirptrs[key].ptr = OpenDir(cnum, dirptrs[key].path))) dptrs_open++; } return(dirptrs[key].ptr); @@ -259,7 +259,7 @@ static BOOL start_dir(int cnum,char *directory) if (! *directory) directory = "."; - Connections[cnum].dirptr = OpenDir(directory); + Connections[cnum].dirptr = OpenDir(cnum, directory); if (Connections[cnum].dirptr) { dptrs_open++; string_set(&Connections[cnum].dirpath,directory); @@ -345,10 +345,10 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid) /**************************************************************************** fill the 5 byte server reserved dptr field ****************************************************************************/ -BOOL dptr_fill(char *buf1,unsigned int key) +BOOL dptr_fill(int cnum, char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_get(key,0); + void *p = dptr_get(cnum, key,0); uint32 offset; if (!p) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -373,10 +373,10 @@ BOOL dptr_zero(char *buf) /**************************************************************************** fetch the dir ptr and seek it given the 5 byte server field ****************************************************************************/ -void *dptr_fetch(char *buf,int *num) +void *dptr_fetch(int cnum, char *buf,int *num) { unsigned int key = *(unsigned char *)buf; - void *p = dptr_get(key,dircounter++); + void *p = dptr_get(cnum, key,dircounter++); uint32 offset; if (!p) { DEBUG(3,("fetched null dirptr %d\n",key)); @@ -393,9 +393,9 @@ void *dptr_fetch(char *buf,int *num) /**************************************************************************** fetch the dir ptr and seek it given the lanman2 parameter block ****************************************************************************/ -void *dptr_fetch_lanman2(char *params,int dptr_num) +void *dptr_fetch_lanman2(int cnum, char *params,int dptr_num) { - void *p = dptr_get(dptr_num,dircounter++); + void *p = dptr_get(cnum, dptr_num,dircounter++); uint32 resume_key = SVAL(params,6); BOOL uses_resume_key = BITSETW(params+10,2); BOOL continue_bit = BITSETW(params+10,3); @@ -520,7 +520,7 @@ typedef struct /******************************************************************* open a directory ********************************************************************/ -void *OpenDir(char *name) +void *OpenDir(int cnum, char *name) { Dir *dirp; char *n; @@ -539,7 +539,7 @@ void *OpenDir(char *name) while ((n = readdirname(p))) { int l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ - if(is_vetoed_name(n)) + if(is_vetoed_name(cnum, n)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 30cf9cb016..5af77d0ac4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -222,7 +222,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aHIDDEN; } - if (is_hidden_path(path)) + if (is_hidden_path(SNUM(cnum), path)) { result |= aHIDDEN; } @@ -366,7 +366,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) check_mangled_stack(name); /* open the directory */ - if (!(cur_dir = OpenDir(path))) + if (!(cur_dir = OpenDir(snum, path))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); @@ -796,7 +796,7 @@ BOOL check_name(char *name,int cnum) errno = 0; - if( is_vetoed_path(name)) + if( is_vetoed_path(SNUM(cnum), name)) { DEBUG(5,("file path name %s vetoed\n",name)); return(0); -- cgit From 1599e41ec42998fdf05a3b22c3f3a93f8b4832ed Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 1 Jul 1997 20:50:57 +0000 Subject: Rolled back Lukes changes. Not quite ready for prime time. Jeremy (jallison@whistle.com) (This used to be commit ed04ec7ab8b8e73b5442bdef03d5a3c994247b4e) --- source3/smbd/dir.c | 22 +++++++++++----------- source3/smbd/server.c | 9 ++------- 2 files changed, 13 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f674c92804..bc099dd1e8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -108,7 +108,7 @@ static void dptr_idleoldest(void) /**************************************************************************** get the dir ptr for a dir index ****************************************************************************/ -static void *dptr_get(int cnum, int key,uint32 lastused) +static void *dptr_get(int key,uint32 lastused) { if (dirptrs[key].valid) { if (lastused) dirptrs[key].lastused = lastused; @@ -116,7 +116,7 @@ static void *dptr_get(int cnum, int key,uint32 lastused) if (dptrs_open >= MAXDIR) dptr_idleoldest(); DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dirptrs[key].ptr = OpenDir(cnum, dirptrs[key].path))) + if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path))) dptrs_open++; } return(dirptrs[key].ptr); @@ -259,7 +259,7 @@ static BOOL start_dir(int cnum,char *directory) if (! *directory) directory = "."; - Connections[cnum].dirptr = OpenDir(cnum, directory); + Connections[cnum].dirptr = OpenDir(directory); if (Connections[cnum].dirptr) { dptrs_open++; string_set(&Connections[cnum].dirpath,directory); @@ -345,10 +345,10 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid) /**************************************************************************** fill the 5 byte server reserved dptr field ****************************************************************************/ -BOOL dptr_fill(int cnum, char *buf1,unsigned int key) +BOOL dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_get(cnum, key,0); + void *p = dptr_get(key,0); uint32 offset; if (!p) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -373,10 +373,10 @@ BOOL dptr_zero(char *buf) /**************************************************************************** fetch the dir ptr and seek it given the 5 byte server field ****************************************************************************/ -void *dptr_fetch(int cnum, char *buf,int *num) +void *dptr_fetch(char *buf,int *num) { unsigned int key = *(unsigned char *)buf; - void *p = dptr_get(cnum, key,dircounter++); + void *p = dptr_get(key,dircounter++); uint32 offset; if (!p) { DEBUG(3,("fetched null dirptr %d\n",key)); @@ -393,9 +393,9 @@ void *dptr_fetch(int cnum, char *buf,int *num) /**************************************************************************** fetch the dir ptr and seek it given the lanman2 parameter block ****************************************************************************/ -void *dptr_fetch_lanman2(int cnum, char *params,int dptr_num) +void *dptr_fetch_lanman2(char *params,int dptr_num) { - void *p = dptr_get(cnum, dptr_num,dircounter++); + void *p = dptr_get(dptr_num,dircounter++); uint32 resume_key = SVAL(params,6); BOOL uses_resume_key = BITSETW(params+10,2); BOOL continue_bit = BITSETW(params+10,3); @@ -520,7 +520,7 @@ typedef struct /******************************************************************* open a directory ********************************************************************/ -void *OpenDir(int cnum, char *name) +void *OpenDir(char *name) { Dir *dirp; char *n; @@ -539,7 +539,7 @@ void *OpenDir(int cnum, char *name) while ((n = readdirname(p))) { int l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ - if(is_vetoed_name(cnum, n)) + if(is_vetoed_name(n)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5af77d0ac4..8c40734ce4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -222,11 +222,6 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aHIDDEN; } - if (is_hidden_path(SNUM(cnum), path)) - { - result |= aHIDDEN; - } - return(result); } @@ -366,7 +361,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) check_mangled_stack(name); /* open the directory */ - if (!(cur_dir = OpenDir(snum, path))) + if (!(cur_dir = OpenDir(path))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); @@ -796,7 +791,7 @@ BOOL check_name(char *name,int cnum) errno = 0; - if( is_vetoed_path(SNUM(cnum), name)) + if( is_vetoed_path(name)) { DEBUG(5,("file path name %s vetoed\n",name)); return(0); -- cgit From 594f8a43610e0407f6842f76c8d80e180e7daed4 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 2 Jul 1997 01:19:41 +0000 Subject: Fixed compile warnings for FreeBsd & Linux. Jeremy (jallison@whistle.com). (This used to be commit 93352e1aae9a1af7036cf56da820356cefe3698b) --- source3/smbd/quotas.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index a1d29bcd12..e6a6f61568 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -50,7 +50,6 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { uid_t euser_id; int r; - char dev_disk[256]; struct dqblk D; struct stat S; FILE *fp; @@ -378,12 +377,12 @@ try to get the disk space from disk quotas - default version ****************************************************************************/ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { - uid_t user_id, euser_id; + uid_t euser_id; int r; - char dev_disk[256]; struct dqblk D; - struct stat S; #ifndef __FreeBSD__ + char dev_disk[256]; + struct stat S; /* find the block device file */ if ((stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); @@ -392,12 +391,16 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) euser_id = geteuid(); #ifdef USE_SETRES - /* for HPUX, real uid must be same as euid to execute quotactl for euid */ - user_id = getuid(); - setresuid(euser_id,-1,-1); - r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); - if (setresuid(user_id,-1,-1)) - DEBUG(5,("Unable to reset uid to %d\n", user_id)); + { + uid_t user_id; + + /* for HPUX, real uid must be same as euid to execute quotactl for euid */ + user_id = getuid(); + setresuid(euser_id,-1,-1); + r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); + if (setresuid(user_id,-1,-1)) + DEBUG(5,("Unable to reset uid to %d\n", user_id)); + } #else #if defined(__FreeBSD__) r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); -- cgit From fc3901122d51b76b5dd5d6a798dace35760590ad Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 3 Jul 1997 17:19:46 +0000 Subject: Fixes for UnixWare 2.x with shadow passwords from Warren Young . (This used to be commit 885b42b44752249c85bb924c9ceefa5b710225da) --- source3/smbd/password.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 803418c97e..2ba09f5ad9 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -887,6 +887,15 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) if (spass && spass->sp_pwdp) pass->pw_passwd = spass->sp_pwdp; } +#elif defined(IA_UINFO) + { + /* Need to get password with SVR4.2's ia_ functions instead of + get{sp,pw}ent functions. Required by UnixWare 2.x, tested on + version 2.1. (tangent@cyberport.com) */ + uinfo_t uinfo; + if (ia_openinfo(pass->pw_name, &uinfo) != -1) + ia_get_logpwd(uinfo, &(pass->pw_passwd)); + } #endif #ifdef SecureWare -- cgit From f6384eca672565bf820f86721de5cf25a5e5e9fe Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 3 Jul 1997 19:44:06 +0000 Subject: Fix for deleting directories that contain only veto files. Needed for interoperability with netatalk volumes. Jeremy (jallison@whistle.com) (This used to be commit e72a8513bccf77177f6fb6002057fee608947a32) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/dir.c | 8 +++--- source3/smbd/reply.c | 74 +++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/server.c | 2 +- 4 files changed, 76 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 883ad5214a..e0dd7fc0ae 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -56,7 +56,7 @@ static int findpty(char **slave) #else strcpy( line, "/dev/ptyXX" ); - dirp = OpenDir("/dev"); + dirp = OpenDir("/dev", True); if (!dirp) return(-1); while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index bc099dd1e8..1d0228864c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -116,7 +116,7 @@ static void *dptr_get(int key,uint32 lastused) if (dptrs_open >= MAXDIR) dptr_idleoldest(); DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path))) + if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path, True))) dptrs_open++; } return(dirptrs[key].ptr); @@ -259,7 +259,7 @@ static BOOL start_dir(int cnum,char *directory) if (! *directory) directory = "."; - Connections[cnum].dirptr = OpenDir(directory); + Connections[cnum].dirptr = OpenDir(directory, True); if (Connections[cnum].dirptr) { dptrs_open++; string_set(&Connections[cnum].dirpath,directory); @@ -520,7 +520,7 @@ typedef struct /******************************************************************* open a directory ********************************************************************/ -void *OpenDir(char *name) +void *OpenDir(char *name, BOOL use_veto) { Dir *dirp; char *n; @@ -539,7 +539,7 @@ void *OpenDir(char *name) while ((n = readdirname(p))) { int l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ - if(is_vetoed_name(n)) + if(use_veto && is_vetoed_name(n)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8af4536c19..5f030d5372 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1326,7 +1326,7 @@ int reply_unlink(char *inbuf,char *outbuf) char *dname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory); + dirptr = OpenDir(directory, True); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -2449,10 +2449,76 @@ int reply_rmdir(char *inbuf,char *outbuf) if (check_name(directory,cnum)) { + dptr_closepath(directory,SVAL(inbuf,smb_pid)); ok = (sys_rmdir(directory) == 0); + if(!ok && (errno == ENOTEMPTY) && lp_veto_files()) + { + /* Check to see if the only thing in this directory are + vetoed files/directories. If so then delete them and + retry. If we fail to delete any of them (and we *don't* + do a recursive delete) then fail the rmdir. */ + BOOL all_veto_files = True; + char *dname; + void *dirptr = OpenDir(directory, False); + + if(dirptr != NULL) + { + int dirpos = TellDir(dirptr); + while ((dname = ReadDirName(dirptr))) + { + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + if(!is_vetoed_name(dname)) + { + all_veto_files = False; + break; + } + } + if(all_veto_files) + { + SeekDir(dirptr,dirpos); + while ((dname = ReadDirName(dirptr))) + { + pstring fullname; + struct stat st; + + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + + /* Construct the full name. */ + if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) + { + errno = ENOMEM; + break; + } + strcpy(fullname, directory); + strcat(fullname, "/"); + strcat(fullname, dname); + + if(sys_lstat(fullname, &st) != 0) + break; + if(st.st_mode & S_IFDIR) + { + if(sys_rmdir(fullname) != 0) + break; + } + else if(sys_unlink(fullname) != 0) + break; + } + CloseDir(dirptr); + /* Retry the rmdir */ + ok = (sys_rmdir(directory) == 0); + } + else + CloseDir(dirptr); + } + else + errno = ENOTEMPTY; + } + if (!ok) - DEBUG(3,("couldn't remove directory %s : %s\n", + DEBUG(3,("couldn't remove directory %s : %s\n", directory,strerror(errno))); } @@ -2670,7 +2736,7 @@ int reply_mv(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory); + dirptr = OpenDir(directory, True); if (dirptr) { @@ -2861,7 +2927,7 @@ int reply_copy(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory); + dirptr = OpenDir(directory, True); if (dirptr) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8c40734ce4..30d8ce3d2a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -361,7 +361,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) check_mangled_stack(name); /* open the directory */ - if (!(cur_dir = OpenDir(path))) + if (!(cur_dir = OpenDir(path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); -- cgit From 1fe89d0b716ccd9fca4abe4daf89df063b38f4b3 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 6 Jul 1997 13:48:10 +0000 Subject: added, tested and debugged new "hide files" option. lkcl (This used to be commit 60af320a436c3a26230fd7ac71856e67ef64e819) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/dir.c | 28 +++++++++++++++------------- source3/smbd/reply.c | 14 +++++++------- source3/smbd/server.c | 21 +++++++++++++++++++-- source3/smbd/trans2.c | 2 +- 5 files changed, 43 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e0dd7fc0ae..79ea66253d 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -56,7 +56,7 @@ static int findpty(char **slave) #else strcpy( line, "/dev/ptyXX" ); - dirp = OpenDir("/dev", True); + dirp = OpenDir(-1, "/dev", True); if (!dirp) return(-1); while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 1d0228864c..2a219e0281 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -108,7 +108,7 @@ static void dptr_idleoldest(void) /**************************************************************************** get the dir ptr for a dir index ****************************************************************************/ -static void *dptr_get(int key,uint32 lastused) +static void *dptr_get(int snum, int key,uint32 lastused) { if (dirptrs[key].valid) { if (lastused) dirptrs[key].lastused = lastused; @@ -116,7 +116,7 @@ static void *dptr_get(int key,uint32 lastused) if (dptrs_open >= MAXDIR) dptr_idleoldest(); DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path, True))) + if ((dirptrs[key].ptr = OpenDir(snum, dirptrs[key].path, True))) dptrs_open++; } return(dirptrs[key].ptr); @@ -259,7 +259,7 @@ static BOOL start_dir(int cnum,char *directory) if (! *directory) directory = "."; - Connections[cnum].dirptr = OpenDir(directory, True); + Connections[cnum].dirptr = OpenDir(SNUM(cnum), directory, True); if (Connections[cnum].dirptr) { dptrs_open++; string_set(&Connections[cnum].dirpath,directory); @@ -345,10 +345,10 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid) /**************************************************************************** fill the 5 byte server reserved dptr field ****************************************************************************/ -BOOL dptr_fill(char *buf1,unsigned int key) +BOOL dptr_fill(int snum, char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_get(key,0); + void *p = dptr_get(snum, key,0); uint32 offset; if (!p) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -373,10 +373,10 @@ BOOL dptr_zero(char *buf) /**************************************************************************** fetch the dir ptr and seek it given the 5 byte server field ****************************************************************************/ -void *dptr_fetch(char *buf,int *num) +void *dptr_fetch(int snum, char *buf,int *num) { unsigned int key = *(unsigned char *)buf; - void *p = dptr_get(key,dircounter++); + void *p = dptr_get(snum, key,dircounter++); uint32 offset; if (!p) { DEBUG(3,("fetched null dirptr %d\n",key)); @@ -393,9 +393,9 @@ void *dptr_fetch(char *buf,int *num) /**************************************************************************** fetch the dir ptr and seek it given the lanman2 parameter block ****************************************************************************/ -void *dptr_fetch_lanman2(char *params,int dptr_num) +void *dptr_fetch_lanman2(int snum, char *params,int dptr_num) { - void *p = dptr_get(dptr_num,dircounter++); + void *p = dptr_get(snum, dptr_num,dircounter++); uint32 resume_key = SVAL(params,6); BOOL uses_resume_key = BITSETW(params+10,2); BOOL continue_bit = BITSETW(params+10,3); @@ -520,7 +520,7 @@ typedef struct /******************************************************************* open a directory ********************************************************************/ -void *OpenDir(char *name, BOOL use_veto) +void *OpenDir(int snum, char *name, BOOL use_veto) { Dir *dirp; char *n; @@ -536,11 +536,13 @@ void *OpenDir(char *name, BOOL use_veto) dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; - while ((n = readdirname(p))) { + while ((n = readdirname(p))) + { int l = strlen(n)+1; + /* If it's a vetoed file, pretend it doesn't even exist */ - if(use_veto && is_vetoed_name(n)) - continue; + if (use_veto && is_vetoed_name(snum, n)) continue; + if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5f030d5372..af980943ca 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -767,7 +767,7 @@ int reply_search(char *inbuf,char *outbuf) memcpy(mask,status+1,11); mask[11] = 0; dirtype = CVAL(status,0) & 0x1F; - Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num); + Connections[cnum].dirptr = dptr_fetch(SNUM(cnum), status+12,&dptr_num); if (!Connections[cnum].dirptr) goto SearchEmpty; string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); @@ -832,7 +832,7 @@ int reply_search(char *inbuf,char *outbuf) { memcpy(p,status,21); make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0); - dptr_fill(p+12,dptr_num); + dptr_fill(SNUM(cnum), p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; else @@ -854,7 +854,7 @@ int reply_search(char *inbuf,char *outbuf) { memcpy(p,status,21); make_dir_struct(p,mask,fname,size,mode,date); - dptr_fill(p+12,dptr_num); + dptr_fill(SNUM(cnum), p+12,dptr_num); numentries++; } p += DIR_STRUCT_SIZE; @@ -937,7 +937,7 @@ int reply_fclose(char *inbuf,char *outbuf) memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); - if(dptr_fetch(status+12,&dptr_num)) { + if(dptr_fetch(SNUM(cnum), status+12,&dptr_num)) { /* Close the dptr - we know it's gone */ dptr_close(dptr_num); } @@ -1326,7 +1326,7 @@ int reply_unlink(char *inbuf,char *outbuf) char *dname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory, True); + dirptr = OpenDir(SNUM(cnum), directory, True); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -2736,7 +2736,7 @@ int reply_mv(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory, True); + dirptr = OpenDir(SNUM(cnum), directory, True); if (dirptr) { @@ -2927,7 +2927,7 @@ int reply_copy(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(directory, True); + dirptr = OpenDir(SNUM(cnum), directory, True); if (dirptr) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 30d8ce3d2a..0361c5aa46 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -179,6 +179,8 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) int result = 0; extern struct current_user current_user; + DEBUG(5,("dos_mode: %d %s\n", cnum, path)); + if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) { if (!((sbuf->st_mode & S_IWOTH) || Connections[cnum].admin_user || @@ -222,6 +224,21 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aHIDDEN; } + if (is_hidden_path(SNUM(cnum), path)) + { + result |= aHIDDEN; + } + + DEBUG(5,("dos_mode returning ")); + + if (result & aHIDDEN) DEBUG(5, ("h")); + if (result & aRONLY ) DEBUG(5, ("r")); + if (result & aSYSTEM) DEBUG(5, ("s")); + if (result & aDIR ) DEBUG(5, ("d")); + if (result & aARCH ) DEBUG(5, ("a")); + + DEBUG(5,("\n")); + return(result); } @@ -361,7 +378,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) check_mangled_stack(name); /* open the directory */ - if (!(cur_dir = OpenDir(path, True))) + if (!(cur_dir = OpenDir(snum, path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); @@ -791,7 +808,7 @@ BOOL check_name(char *name,int cnum) errno = 0; - if( is_vetoed_path(name)) + if( is_vetoed_name(SNUM(cnum), name)) { DEBUG(5,("file path name %s vetoed\n",name)); return(0); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1f727c4ecd..6f8fe5121a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -782,7 +782,7 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz return(ERROR(ERRDOS,ERRnomem)); /* Check that the dptr is valid */ - if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num))) + if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(SNUM(cnum), params, dptr_num))) return(ERROR(ERRDOS,ERRnofiles)); string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); -- cgit From bc4d8cb3068425c0f4b84020b856d80fba7ce81f Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 6 Jul 1997 14:07:00 +0000 Subject: missed one OpenDir() and two is_vetoed_name() calls, both of which take a service number as a parameter, in the rmdir code, when doing a recompile. lkcl (This used to be commit e095e339e62471a0b172918d2d3213f8a34b2108) --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index af980943ca..8f650cb994 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2452,7 +2452,7 @@ int reply_rmdir(char *inbuf,char *outbuf) dptr_closepath(directory,SVAL(inbuf,smb_pid)); ok = (sys_rmdir(directory) == 0); - if(!ok && (errno == ENOTEMPTY) && lp_veto_files()) + if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum))) { /* Check to see if the only thing in this directory are vetoed files/directories. If so then delete them and @@ -2460,7 +2460,7 @@ int reply_rmdir(char *inbuf,char *outbuf) do a recursive delete) then fail the rmdir. */ BOOL all_veto_files = True; char *dname; - void *dirptr = OpenDir(directory, False); + void *dirptr = OpenDir(SNUM(cnum), directory, False); if(dirptr != NULL) { @@ -2469,7 +2469,7 @@ int reply_rmdir(char *inbuf,char *outbuf) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; - if(!is_vetoed_name(dname)) + if(!is_vetoed_name(SNUM(cnum), dname)) { all_veto_files = False; break; -- cgit From 25eae02948b40667495fbb021dd130180180a05e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 8 Jul 1997 16:54:44 +0000 Subject: Makefile: Added AIX targets from Ole Holm Nielsen chgpasswd.c: Added Samba/GPL notice (for obvious reasons). clitar.c: Updated Copyright date to include 1997 (for obvious reasons). getsmbpass.c: Updated Copyright date to include 1997 (for obvious reasons). includes.h: Added stropts for solaris. loadparm.c: Changed comment for hide files option. nameconf.c: Updated Copyright date to include 1997 (for obvious reasons). nmbd.c: Updated Copyright date to include 1997 (for obvious reasons). pcap.c: Updated Copyright date to include 1997 (for obvious reasons). proto.h: Re-added accidentaly deleted smb_shm_ calls. quotas.c: Added AIX quota patch from Ole Holm Nielsen server.c: Optimization on calling is_hidden_path. Updated Copyrights. smb.h: Changed DEFAULT_FILES_TO_HIDE from "*/.*" to ".*". smbpass.c: Updated Copyright date to include 1997 (for obvious reasons). ufc.c: Updated Copyright date to include 1997 (for obvious reasons). util.c: Added last component code to is_in_path(). Jeremy (jallison@whistle.com) (This used to be commit 9385ae1005f13c8ed51f1319e3949b5c8571e62d) --- source3/smbd/chgpasswd.c | 43 ++++++++++++++++++++++++++++++++----------- source3/smbd/quotas.c | 23 +++++++++++++++++------ source3/smbd/server.c | 6 ++++-- 3 files changed, 53 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 79ea66253d..6063f2aac8 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1,3 +1,24 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Samba utility functions + 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. +*/ + /* fork a child process to exec passwd and write to its * tty to change a users password. This is running as the * user who is attempting to change the password. @@ -38,22 +59,22 @@ extern int DEBUGLEVEL; static int findpty(char **slave) { int master; -#ifdef SVR4 +#if defined(SVR4) || defined(SUNOS5) extern char *ptsname(); -#else +#else /* defined(SVR4) || defined(SUNOS5) */ static char line[12]; void *dirp; char *dpname; -#endif +#endif /* defined(SVR4) || defined(SUNOS5) */ -#ifdef SVR4 +#if defined(SVR4) || defined(SUNOS5) if ((master = open("/dev/ptmx", O_RDWR)) >= 1) { grantpt(master); unlockpt(master); *slave = ptsname(master); return (master); } -#else +#else /* defined(SVR4) || defined(SUNOS5) */ strcpy( line, "/dev/ptyXX" ); dirp = OpenDir(-1, "/dev", True); @@ -73,7 +94,7 @@ static int findpty(char **slave) } } CloseDir(dirp); -#endif +#endif /* defined(SVR4) || defined(SUNOS5) */ return (-1); } @@ -87,9 +108,9 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram) #ifdef USE_SETRES setresuid(0,0,0); -#else +#else /* USE_SETRES */ setuid(0); -#endif +#endif /* USE_SETRES */ /* Start new session - gets rid of controlling terminal. */ if (setsid() < 0) { @@ -103,15 +124,15 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram) slavedev)); return(False); } -#ifdef SVR4 +#if defined(SVR4) || defined(SUNOS5) ioctl(slave, I_PUSH, "ptem"); ioctl(slave, I_PUSH, "ldterm"); -#else +#else /* defined(SVR4) || defined(SUNOS5) */ if (ioctl(slave,TIOCSCTTY,0) <0) { DEBUG(3,("Error in ioctl call for slave pty\n")); /* return(False); */ } -#endif +#endif /* defined(SVR4) || defined(SUNOS5) */ /* Close master. */ close(master); diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index e6a6f61568..262eea3100 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -367,7 +367,14 @@ DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n" #ifdef __FreeBSD__ #include -#else +#elif AIX +/* AIX quota patch from Ole Holm Nielsen */ +#include +/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */ +#define dqb_curfiles dqb_curinodes +#define dqb_fhardlimit dqb_ihardlimit +#define dqb_fsoftlimit dqb_isoftlimit +#else /* !__FreeBSD__ && !AIX */ #include #include #endif @@ -380,7 +387,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) uid_t euser_id; int r; struct dqblk D; -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(AIX) char dev_disk[256]; struct stat S; /* find the block device file */ @@ -401,13 +408,17 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) if (setresuid(user_id,-1,-1)) DEBUG(5,("Unable to reset uid to %d\n", user_id)); } -#else +#else /* USE_SETRES */ #if defined(__FreeBSD__) r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); -#else +#elif defined(AIX) + /* AIX has both USER and GROUP quotas: + Get the USER quota (ohnielse@fysik.dtu.dk) */ + r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); +#else /* !__FreeBSD__ && !AIX */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); -#endif -#endif +#endif /* !__FreeBSD__ && !AIX */ +#endif /* USE_SETRES */ /* Use softlimit to determine disk space, except when it has been exceeded */ *bsize = 1024; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0361c5aa46..768c7c71bc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -224,7 +224,9 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aHIDDEN; } - if (is_hidden_path(SNUM(cnum), path)) + /* Optimization : Only call is_hidden_path if it's not already + hidden. */ + if (!(result & aHIDDEN) && is_hidden_path(SNUM(cnum), path)) { result |= aHIDDEN; } @@ -4189,7 +4191,7 @@ static void usage(char *pname) reopen_logs(); DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION)); - DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n")); + DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n")); #ifndef NO_GETRLIMIT #ifdef RLIMIT_NOFILE -- cgit From cec799512da39b880a80449952a30c255d7eb972 Mon Sep 17 00:00:00 2001 From: John Terpstra Date: Wed, 9 Jul 1997 11:04:45 +0000 Subject: JHT ==> Added copyright notations for my works. This is regretably needed! (This used to be commit c80111cdf54218f23b230dc91bd6d814e6a4afcc) --- source3/smbd/ipc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7922e41623..17bdd3ca66 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1,9 +1,11 @@ - /* Unix SMB/Netbios implementation. Version 1.9. Inter-process communication and named pipe handling Copyright (C) Andrew Tridgell 1992-1997 + + SMB Version handling + Copyright (C) John H Terpstra 1995-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 -- cgit From 792771ecc954892e85f7715136a4d70221f90d85 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 11 Jul 1997 00:54:45 +0000 Subject: interface.c: Fix for AIX4.x finding interfaces. server.c: Subtle fix for filenames containing ':'. Jeremy (jallison@whistle.com) (This used to be commit ee9f57bab25e5ee07fb2d384b8c416576401a6ab) --- source3/smbd/server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 768c7c71bc..528e4769ea 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -397,7 +397,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) if (!name_map_mangle(name2,False,snum)) continue; if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, name2)) + || fname_equal(name, dname)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,snum); @@ -2102,7 +2102,7 @@ static BOOL open_sockets(BOOL is_daemon,int port) /* ready to listen */ if (listen(s, 5) == -1) { - DEBUG(0,("listen: %s",strerror(errno))); + DEBUG(0,("listen: %s\n",strerror(errno))); close(s); return False; } @@ -2122,7 +2122,7 @@ static BOOL open_sockets(BOOL is_daemon,int port) if (Client == -1) { - DEBUG(0,("accept: %s",strerror(errno))); + DEBUG(0,("accept: %s\n",strerror(errno))); continue; } -- cgit From 9a8c54f51bb53dd21c364009f0110936140a1eea Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sat, 12 Jul 1997 14:41:26 +0000 Subject: trans2 query file/path info - unix change times being reported as dos create times. now reports unix modified times as dos create times: the alternative is to report zero (unknown create time). w95 reports the info level 0x101 (smb query file basic) as data size 40 bytes not 36. put 40 bytes data instead. put in comments into trans2 set file/path info, showing which is the create time, which is the mod time. lkcl (This used to be commit ff455e405998a1a01320ffc21c81587cd34e9853) --- source3/smbd/trans2.c | 129 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6f8fe5121a..d0d3352ec4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -343,7 +343,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l size = sbuf.st_size; mdate = sbuf.st_mtime; adate = sbuf.st_atime; - cdate = sbuf.st_ctime; + cdate = sbuf.st_mtime; if(mode & aDIR) size = 0; @@ -915,10 +915,10 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize /* Return volume name */ int volname_len = MIN(strlen(vname),11); data_len = l2_vol_szVolLabel + volname_len + 1; - put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime); + put_dos_date2(pdata,l2_vol_fdateCreation,st.st_mtime); SCVAL(pdata,l2_vol_cch,volname_len); StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); - DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len, + DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_mtime, volname_len, pdata+l2_vol_szVolLabel)); break; } @@ -1070,21 +1070,21 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, switch (info_level) { - case 1: - case 2: + case SMB_INFO_STANDARD: + case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); - put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); + put_dos_date2(pdata,l1_fdateCreation,sbuf.st_mtime); /* create = mod */ + put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */ + put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,size); SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); SSVAL(pdata,l1_attrFile,mode); SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ break; - case 3: + case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; - put_dos_date2(pdata,0,sbuf.st_ctime); + put_dos_date2(pdata,0,sbuf.st_mtime); /* create time = mod time */ put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,size); @@ -1092,7 +1092,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, SIVAL(pdata,20,mode); break; - case 4: + case SMB_INFO_QUERY_ALL_EAS: data_size = 4; SIVAL(pdata,0,data_size); break; @@ -1101,12 +1101,20 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */ case SMB_QUERY_FILE_BASIC_INFO: - data_size = 36; - put_long_date(pdata,sbuf.st_ctime); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); - put_long_date(pdata+24,sbuf.st_mtime); + data_size = 40; /* w95 returns 40 bytes not 36. */ + put_long_date(pdata,sbuf.st_mtime); /* create time = mod time */ + put_long_date(pdata+8,sbuf.st_atime); /* access time */ + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_ctime); /* change time */ SIVAL(pdata,32,mode); + + DEBUG(5,("SMB_QFBI - ")); + DEBUG(5,("create: %s ", ctime(&sbuf.st_mtime))); + DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); + DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); + DEBUG(5,("change: %s ", ctime(&sbuf.st_ctime))); + DEBUG(5,("mode: %x\n", mode)); + break; case SMB_QUERY_FILE_STANDARD_INFO: @@ -1135,10 +1143,10 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, break; case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,sbuf.st_ctime); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); - put_long_date(pdata+24,sbuf.st_mtime); + put_long_date(pdata,sbuf.st_mtime); /* create time = mod time */ + put_long_date(pdata+8,sbuf.st_atime); /* access time */ + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_ctime); /* change time */ SIVAL(pdata,32,mode); pdata += 40; SIVAL(pdata,0,size); @@ -1257,29 +1265,33 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, } switch (info_level) + { + case SMB_INFO_STANDARD: + case SMB_INFO_QUERY_EA_SIZE: { - case 1: + /* access time */ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); - tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - mode = SVAL(pdata,l1_attrFile); - size = IVAL(pdata,l1_cbFile); - break; - case 2: - tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); + /* write time */ tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); + mode = SVAL(pdata,l1_attrFile); size = IVAL(pdata,l1_cbFile); break; + } - case 3: + /* XXXX um, i don't think this is right. + it's also not in the cifs6.txt spec. + */ + case SMB_INFO_QUERY_EAS_FROM_LIST: tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); size = IVAL(pdata,16); mode = IVAL(pdata,24); break; - case 4: + /* XXXX nor this. not in cifs6.txt, either. */ + case SMB_INFO_QUERY_ALL_EAS: tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); size = IVAL(pdata,16); @@ -1287,48 +1299,79 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, break; case SMB_SET_FILE_BASIC_INFO: - pdata += 8; /* create time */ - tvs.actime = interpret_long_date(pdata); pdata += 8; - tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8)); - pdata += 16; - mode = IVAL(pdata,0); + { + /* create time */ + + /* access time */ + tvs.actime = interpret_long_date(pdata+8); + + /* write time + changed time, combined. */ + tvs.modtime=MAX(interpret_long_date(pdata+16), + interpret_long_date(pdata+24)); + + /* attributes */ + mode = IVAL(pdata,32); break; + } case SMB_SET_FILE_END_OF_FILE_INFO: + { if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return(ERROR(ERRDOS,ERRunknownlevel)); + return(ERROR(ERRDOS,ERRunknownlevel)); size = IVAL(pdata,0); break; + } case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */ case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */ default: + { return(ERROR(ERRDOS,ERRunknownlevel)); } + } + DEBUG(3,("actime: %s " , ctime(&tvs.actime))); + DEBUG(3,("modtime: %s ", ctime(&tvs.modtime))); + DEBUG(3,("size: %x " , size)); + DEBUG(3,("mode: %x\n" , mode)); + /* get some defaults (no modifications) if any info is zero. */ if (!tvs.actime) tvs.actime = st.st_atime; if (!tvs.modtime) tvs.modtime = st.st_mtime; if (!size) size = st.st_size; - /* Try and set the times, size and mode of this file - if they are different - from the current values */ - if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { + /* Try and set the times, size and mode of this file - + if they are different from the current values + */ + if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) + { if(sys_utime(fname, &tvs)!=0) + { return(ERROR(ERRDOS,ERRnoaccess)); + } } - if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) { + + /* check the mode isn't different, before changing it */ + if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL)) + { DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); return(ERROR(ERRDOS,ERRnoaccess)); } - if(size != st.st_size) { - if (fd == -1) { + + if(size != st.st_size) + { + if (fd == -1) + { fd = sys_open(fname,O_RDWR,0); if (fd == -1) - return(ERROR(ERRDOS,ERRbadpath)); + { + return(ERROR(ERRDOS,ERRbadpath)); + } set_filelen(fd, size); close(fd); - } else { + } + else + { set_filelen(fd, size); } } -- cgit From 136732a6f4cda86b4e28908afb3ad4893439c1ca Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 13 Jul 1997 14:05:01 +0000 Subject: counter loop % usage only worked if counters were an exact multiple of SMBD_LOOP time. used >= instead. lkcl (This used to be commit c881dff3bfaa370b5eb4324217796d186572a9e3) --- source3/smbd/server.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 528e4769ea..83bb09b11f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3886,6 +3886,9 @@ static void process(void) int deadtime = lp_deadtime()*60; int counter; int last_keepalive=0; + int service_load_counter = 0; + int share_check_counter = 0; + int share_clean_counter = 0; if (deadtime <= 0) deadtime = DEFAULT_SMBD_TIMEOUT; @@ -3904,6 +3907,14 @@ static void process(void) BOOL allidle = True; extern int keepalive; + if (counter > 365 * 3600) /* big number of seconds. */ + { + counter = 0; + share_check_counter = 0; + share_clean_counter = 0; + service_load_counter = 0; + } + if (smb_read_error == READ_EOF) { DEBUG(3,("end of file from client\n")); return; @@ -3921,17 +3932,31 @@ static void process(void) unbecome_user(); /* check for smb.conf reload */ - if (!(counter%SMBD_RELOAD_CHECK)) + if (counter >= service_load_counter + SMBD_RELOAD_CHECK) + { + service_load_counter = counter; + + /* remove all unused services. reduce some of that memory overhead. */ + lp_killunused(snum_used); + + /* reload services, if files have changed. */ reload_services(True); + } #if 0 /* JRA */ /* check the share modes every 10 secs */ - if (!(counter%SHARE_MODES_CHECK)) + if (counter >= share_check_counter + SHARE_MODES_CHECK) + { + share_check_counter = counter; check_share_modes(); + } /* clean the share modes every 5 minutes */ - if (!(counter%SHARE_MODES_CLEAN)) + if (counter >= share_clean_counter + SHARE_MODES_CLEAN) + { + share_clean_counter = counter; clean_share_modes(); + } #endif /* JRA */ /* automatic timeout if all connections are closed */ -- cgit From 0776dea81fbf353669714a5e3ff6d62ff6303ed6 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 14 Jul 1997 19:45:34 +0000 Subject: local.h: Removed ununsed SHARE_MODES_XXX defines. Upped SMBD_RELOAD_CHECK from 10 to 60. server.c: Removed unused code (was If 0'ed out). trans2.c: Backed out Luke's ctime->mtime change. I don't think it is correct. Left the other fixes, though. util.c: Changed veto/hide files separator back to '/'. Jeremy (jallison@whistle.com) (This used to be commit b47121624c8824d3e1d8992cb950ebad52ba5c58) --- source3/smbd/server.c | 20 -------------------- source3/smbd/trans2.c | 34 +++++++++++++++++----------------- 2 files changed, 17 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 83bb09b11f..41f23ed02f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3887,8 +3887,6 @@ static void process(void) int counter; int last_keepalive=0; int service_load_counter = 0; - int share_check_counter = 0; - int share_clean_counter = 0; if (deadtime <= 0) deadtime = DEFAULT_SMBD_TIMEOUT; @@ -3910,8 +3908,6 @@ static void process(void) if (counter > 365 * 3600) /* big number of seconds. */ { counter = 0; - share_check_counter = 0; - share_clean_counter = 0; service_load_counter = 0; } @@ -3943,22 +3939,6 @@ static void process(void) reload_services(True); } -#if 0 /* JRA */ - /* check the share modes every 10 secs */ - if (counter >= share_check_counter + SHARE_MODES_CHECK) - { - share_check_counter = counter; - check_share_modes(); - } - - /* clean the share modes every 5 minutes */ - if (counter >= share_clean_counter + SHARE_MODES_CLEAN) - { - share_clean_counter = counter; - clean_share_modes(); - } -#endif /* JRA */ - /* automatic timeout if all connections are closed */ if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) { DEBUG(2,("%s Closing idle connection\n",timestring())); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d0d3352ec4..1b199f01ba 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -343,7 +343,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l size = sbuf.st_size; mdate = sbuf.st_mtime; adate = sbuf.st_atime; - cdate = sbuf.st_mtime; + cdate = sbuf.st_ctime; if(mode & aDIR) size = 0; @@ -915,10 +915,10 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize /* Return volume name */ int volname_len = MIN(strlen(vname),11); data_len = l2_vol_szVolLabel + volname_len + 1; - put_dos_date2(pdata,l2_vol_fdateCreation,st.st_mtime); + put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime); SCVAL(pdata,l2_vol_cch,volname_len); StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); - DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_mtime, volname_len, + DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len, pdata+l2_vol_szVolLabel)); break; } @@ -1073,7 +1073,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,sbuf.st_mtime); /* create = mod */ + put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */ put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */ put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,size); @@ -1084,7 +1084,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; - put_dos_date2(pdata,0,sbuf.st_mtime); /* create time = mod time */ + put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */ put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,size); @@ -1101,18 +1101,18 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */ case SMB_QUERY_FILE_BASIC_INFO: - data_size = 40; /* w95 returns 40 bytes not 36. */ - put_long_date(pdata,sbuf.st_mtime); /* create time = mod time */ + data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ + put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */ put_long_date(pdata+8,sbuf.st_atime); /* access time */ put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_ctime); /* change time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); DEBUG(5,("SMB_QFBI - ")); - DEBUG(5,("create: %s ", ctime(&sbuf.st_mtime))); + DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime))); DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); - DEBUG(5,("change: %s ", ctime(&sbuf.st_ctime))); + DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("mode: %x\n", mode)); break; @@ -1143,10 +1143,10 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, break; case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,sbuf.st_mtime); /* create time = mod time */ + put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */ put_long_date(pdata+8,sbuf.st_atime); /* access time */ put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_ctime); /* change time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); pdata += 40; SIVAL(pdata,0,size); @@ -1300,7 +1300,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_SET_FILE_BASIC_INFO: { - /* create time */ + /* Ignore create time at offset pdata. */ /* access time */ tvs.actime = interpret_long_date(pdata+8); @@ -1330,10 +1330,10 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, } } - DEBUG(3,("actime: %s " , ctime(&tvs.actime))); - DEBUG(3,("modtime: %s ", ctime(&tvs.modtime))); - DEBUG(3,("size: %x " , size)); - DEBUG(3,("mode: %x\n" , mode)); + DEBUG(6,("actime: %s " , ctime(&tvs.actime))); + DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); + DEBUG(6,("size: %x " , size)); + DEBUG(6,("mode: %x\n" , mode)); /* get some defaults (no modifications) if any info is zero. */ if (!tvs.actime) tvs.actime = st.st_atime; -- cgit From 8b904f4ecc7b6bd6558d40fda4184112bbb10366 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 17 Jul 1997 20:11:58 +0000 Subject: Makefile: Added krb5 option from Nathan Neulinger includes.h: Added krb5 option from Nathan Neulinger , added SGI5 fix. password.c: Added krb5 option from Nathan Neulinger quotas.c: Added inode quote fix. reply.c: removed redundent code. server.c: Changed error debug to 0, removed redundent check. util.c: Added close_low_fd() to become_daemon - fix for rsh from Johnathan Knight. Jeremy (jallison@whistle.com) (This used to be commit 256afb764828b0a6dad5529d62501bc9ea2807ee) --- source3/smbd/password.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/quotas.c | 2 +- source3/smbd/reply.c | 7 ---- source3/smbd/server.c | 4 +-- 4 files changed, 89 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2ba09f5ad9..e00028d87e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -585,6 +585,86 @@ void dfs_unlogin(void) #endif +#ifdef KRB5_AUTH +/******************************************************************* +check on Kerberos authentication +********************************************************************/ +static BOOL krb5_auth(char *this_user,char *password) +{ + krb5_data tgtname = { + 0, + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME + }; + krb5_context kcontext; + krb5_principal kprinc; + krb5_principal server; + krb5_creds kcreds; + int options = 0; + krb5_address **addrs = (krb5_address **)0; + krb5_preauthtype *preauth = NULL; + krb5_keytab keytab = NULL; + krb5_timestamp now; + krb5_ccache ccache = NULL; + int retval; + char *name; + + if ( retval=krb5_init_context(&kcontext)) + { + return(False); + } + + if ( retval = krb5_timeofday(kcontext, &now) ) + { + return(False); + } + + if ( retval = krb5_cc_default(kcontext, &ccache) ) + { + return(False); + } + + if ( retval = krb5_parse_name(kcontext, this_user, &kprinc) ) + { + return(False); + } + + memset((char *)&kcreds, 0, sizeof(kcreds)); + + kcreds.client = kprinc; + + if ((retval = krb5_build_principal_ext(kcontext, &server, + krb5_princ_realm(kcontext, kprinc)->length, + krb5_princ_realm(kcontext, kprinc)->data, + tgtname.length, + tgtname.data, + krb5_princ_realm(kcontext, kprinc)->length, + krb5_princ_realm(kcontext, kprinc)->data, + 0))) + { + return(False); + } + + kcreds.server = server; + + retval = krb5_get_in_tkt_with_password(kcontext, + options, + addrs, + NULL, + preauth, + password, + 0, + &kcreds, + 0); + + if ( retval ) + { + return(False); + } + + return(True); +} +#endif /* KRB5_AUTH */ #ifdef LINUX_BIGCRYPT /**************************************************************************** @@ -687,6 +767,10 @@ Hence we make a direct return to avoid a second chance!!! if (dfs_auth(this_user,password)) return(True); #endif +#ifdef KRB5_AUTH + if (krb5_auth(this_user,password)) return(True); +#endif + #ifdef PWDAUTH if (pwdauth(this_user,password) == 0) return(True); @@ -1318,7 +1402,8 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) } file_host = strtok(bp, " \t\n"); file_user = strtok(NULL, " \t\n"); - DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user)); + DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", + file_user ? file_user : "(null)" )); if (file_host && *file_host) { BOOL host_ok = False; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 262eea3100..8cbe46d9e1 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -437,7 +437,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) /* Use softlimit to determine disk space, except when it has been exceeded */ if ((D.dqb_curblocks>D.dqb_bsoftlimit) #if !defined(__FreeBSD__) -||(D.dqb_curfiles>D.dqb_fsoftlimit) +||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0)) #endif ) { *dfree = 0; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8f650cb994..315c7fbb51 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1026,7 +1026,6 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring fname; int cnum = SVAL(inbuf,smb_tid); int fnum = -1; - int openmode = 0; int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1); @@ -1050,12 +1049,6 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) strcpy(fname,smb_buf(inbuf)); unix_convert(fname,cnum,0); - /* now add create and trunc bits */ - if (smb_ofun & 0x10) - openmode |= O_CREAT; - if ((smb_ofun & 0x3) == 2) - openmode |= O_TRUNC; - fnum = find_free_file(); if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 41f23ed02f..2969624215 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1577,9 +1577,9 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int old_open_mode = old_shares[i].share_mode &0xF; int old_deny_mode = (old_shares[i].share_mode >>4)&7; - if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) + if (old_deny_mode > 4 || old_open_mode > 2) { - DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n", + DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", deny_mode,old_deny_mode,old_open_mode,fname)); free((char *)old_shares); if(share_locked) -- cgit From 612111c7a1a048d19e24b5e2e4d426247d320d1e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 18 Jul 1997 20:21:32 +0000 Subject: charset.c: Split charset_initialise() into 2 - a charset_initialise() and a codepage_initialise(). Fixes problem with initialising dos map twice. charset.h: Changes to support charset changes. client.c: Changes to support charset changes. loadparm.c: follow symlinks parameter from David Clerc nmbd.c: Changes to support charset changes. nmblookup.c:Changes to support charset changes. proto.h: Changes to support charset changes. reply.c: Don't call security=server with no user/no password guest. Fix from Stefaan A Eeckels server.c: follow symlinks code from David Clerc smbpasswd.c:Changes to support charset changes. status.c: Changes to support charset changes. testparm.c: Changes to support charset changes. testprns.c: Changes to support charset changes. uid.c: Fixed log message with no \n. Jeremy (jallison@whistle.com) (This used to be commit 2a28a6e5e461aca7fe6c19cd01d287010056cffb) --- source3/smbd/reply.c | 20 ++++++++++++-------- source3/smbd/server.c | 20 ++++++++++++++++++-- source3/smbd/uid.c | 2 +- 3 files changed, 31 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 315c7fbb51..5869588664 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -409,8 +409,14 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } + /* If no username is sent use the guest account */ if (!*user) - strcpy(user,lp_guestaccount(-1)); + { + strcpy(user,lp_guestaccount(-1)); + /* If no user and no password then set guest flag. */ + if( *smb_apasswd == 0) + guest = True; + } strlower(user); @@ -421,24 +427,22 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) add_session_user(user); - if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) && + if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) && !check_hosts_equiv(user)) { - if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) - guest = True; - /* now check if it's a valid username/password */ /* If an NT password was supplied try and validate with that - first. This is superior as the passwords are mixed case 128 length unicode */ - if(smb_ntpasslen && !guest) + first. This is superior as the passwords are mixed case + 128 length unicode */ + if(smb_ntpasslen) { if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); else valid_nt_password = True; } - if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) + if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) { if (!computer_id && lp_security() >= SEC_USER) { #if (GUEST_SESSSETUP == 0) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2969624215..5f5404bcc2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -817,6 +817,22 @@ BOOL check_name(char *name,int cnum) } ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum))); + + /* Check if we are allowing users to follow symlinks */ + /* Patch from David Clerc + University of Geneva */ + + if (!lp_symlinks(SNUM(cnum))) + { + struct stat statbuf; + if ( (sys_lstat(name,&statbuf) != -1) && + (S_ISLNK(statbuf.st_mode)) ) + { + DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); + ret=0; + } + } + if (!ret) DEBUG(5,("check_name on %s failed\n",name)); @@ -4111,7 +4127,7 @@ static void usage(char *pname) setup_logging(argv[0],False); - charset_initialise(-1); + charset_initialise(); /* make absolutely sure we run as root - to handle cases whre people are crazy enough to have it setuid */ @@ -4226,7 +4242,7 @@ static void usage(char *pname) if (!reload_services(False)) return(-1); - charset_initialise(lp_client_code_page()); + codepage_initialise(lp_client_code_page()); strcpy(myworkgroup, lp_workgroup()); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 0cf1c217a9..cdc4e474c6 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -83,7 +83,7 @@ static BOOL become_uid(int uid) &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)")); + DEBUG(1,("Can't set uid (AIX3)\n")); } #endif -- cgit From 0cdc68332df6beaa47307f730fda793bf295ef96 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 22 Jul 1997 18:35:44 +0000 Subject: Removed lp_killunused() call from server main loop. This WAS A MAJOR BUG THAT CAN CAUSE IPC$ to be removed !!!!! Not sure how this one got introduced (but I have my suspicions :-). lp_killunused() MUST ONLY BE CALLED from reload_services(). Jeremy (jallison@whistle.com) (This used to be commit 937f0fbf87c4b66a947215ee13a69d1e19e4ff77) --- source3/smbd/server.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5f5404bcc2..3c5cd6bea7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3948,9 +3948,6 @@ static void process(void) { service_load_counter = counter; - /* remove all unused services. reduce some of that memory overhead. */ - lp_killunused(snum_used); - /* reload services, if files have changed. */ reload_services(True); } -- cgit From a3de6a813ed058255f1e9b2da2aa181f5becc51f Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 22 Jul 1997 19:04:40 +0000 Subject: charset.c: Fixed signed/unsigned issues. password.c: Fixed problem with MS-Exchange services. Jeremy (jallison@whistle.com) (This used to be commit e723dd3deec00a91568c5aa546374409ce7ba379) --- source3/smbd/password.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e00028d87e..eb837c2584 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -153,12 +153,26 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) struct passwd *pwfile; /* for getting real name from passwd file */ int real_name_len; +#if 0 + /* + * After observing MS-Exchange services writing to a Samba share + * I belive this code is incorrect. Each service does it's own + * sessionsetup_and_X for the same user, and as each service shuts + * down, it does a user_logoff_and_X. As we are consolidating multiple + * sessionsetup_and_X's onto the same vuid here, when the first service + * shuts down, it invalidates all the open files for the other services. + * Hence I am removing this code and forcing each sessionsetup_and_X + * to get a new vuid. + * Jeremy Allison. (jallison@whistle.com). + */ + int i; for(i = 0; i < num_validated_users; i++) { vuser = &validated_users[i]; if( vuser->uid == uid ) return (uint16)(i + VUID_OFFSET); /* User already validated */ } +#endif validated_users = (user_struct *)Realloc(validated_users, sizeof(user_struct)* -- cgit From 15ae50ca5203bc4c04567e400ba041a4d1757b2b Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 24 Jul 1997 17:25:11 +0000 Subject: Makefile: Added UNIXWARE 2.x with shadow passwords from fja@extratech.com client.c: Made prompt appear at debug level 0. Fixed strcasecmp redefinition. Caused client to use set_blocking rather than making fcntl calls itself. dir.c: Removed redundent snum parameters. includes.h: Added SCO fixes. loadparm.c: Made default 'files to hide' a null string. nmbd.c: Removed O_NONBLOCK from pid file open for platforms that dont have it. proto.h: Changed snum to cnum where needed. Changed is_xx_path to is_in_path (now called via MACRO). quotas.c: Swapped setuid/seteuid calls when restoring uid. reply.c: Removed redundent snum parameters. server.c: Changed snum to cnum where needed. Setup new veto_list, hide_list namelists. Added standard_sub changes from Stefaan A Eeckels and Paul Rippin shmem.c: Changed cast for sizeof to be int before negating. smb.h: Added new veto_list, hide_list entries to connections. Added IS_PRINT, IS_HIDDEN_PATH, IS_VETO_PATH macros. trans2.c: Removed redundent snum parameters. util.c: Added standard_sub_basic changes from Stefaan A Eeckels and Paul Rippin Fixed up veto/hidden path processing so the paths are pres-parsed and checked for wildcards (for speed). Jeremy (jallison@whistle.com) (This used to be commit 9afa36f7874cfd527aa6ef1e7965c1d35d46ab1f) --- source3/smbd/dir.c | 32 +++++++++++++------------ source3/smbd/quotas.c | 4 ++-- source3/smbd/reply.c | 20 ++++++++-------- source3/smbd/server.c | 65 ++++++++++++++++++++++++++++++++++----------------- source3/smbd/trans2.c | 2 +- 5 files changed, 73 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 2a219e0281..5bd5b1d573 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -108,18 +108,20 @@ static void dptr_idleoldest(void) /**************************************************************************** get the dir ptr for a dir index ****************************************************************************/ -static void *dptr_get(int snum, int key,uint32 lastused) +static void *dptr_get(int key,uint32 lastused) { - if (dirptrs[key].valid) { - if (lastused) dirptrs[key].lastused = lastused; - if (!dirptrs[key].ptr) { + struct dptr_struct *dp = &dirptrs[key]; + + if (dp->valid) { + if (lastused) dp->lastused = lastused; + if (!dp->ptr) { if (dptrs_open >= MAXDIR) dptr_idleoldest(); DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dirptrs[key].ptr = OpenDir(snum, dirptrs[key].path, True))) + if ((dp->ptr = OpenDir(dp->cnum, dp->path, True))) dptrs_open++; } - return(dirptrs[key].ptr); + return(dp->ptr); } return(NULL); } @@ -259,7 +261,7 @@ static BOOL start_dir(int cnum,char *directory) if (! *directory) directory = "."; - Connections[cnum].dirptr = OpenDir(SNUM(cnum), directory, True); + Connections[cnum].dirptr = OpenDir(cnum, directory, True); if (Connections[cnum].dirptr) { dptrs_open++; string_set(&Connections[cnum].dirpath,directory); @@ -345,10 +347,10 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid) /**************************************************************************** fill the 5 byte server reserved dptr field ****************************************************************************/ -BOOL dptr_fill(int snum, char *buf1,unsigned int key) +BOOL dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_get(snum, key,0); + void *p = dptr_get(key,0); uint32 offset; if (!p) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -373,10 +375,10 @@ BOOL dptr_zero(char *buf) /**************************************************************************** fetch the dir ptr and seek it given the 5 byte server field ****************************************************************************/ -void *dptr_fetch(int snum, char *buf,int *num) +void *dptr_fetch(char *buf,int *num) { unsigned int key = *(unsigned char *)buf; - void *p = dptr_get(snum, key,dircounter++); + void *p = dptr_get(key,dircounter++); uint32 offset; if (!p) { DEBUG(3,("fetched null dirptr %d\n",key)); @@ -393,9 +395,9 @@ void *dptr_fetch(int snum, char *buf,int *num) /**************************************************************************** fetch the dir ptr and seek it given the lanman2 parameter block ****************************************************************************/ -void *dptr_fetch_lanman2(int snum, char *params,int dptr_num) +void *dptr_fetch_lanman2(char *params,int dptr_num) { - void *p = dptr_get(snum, dptr_num,dircounter++); + void *p = dptr_get(dptr_num,dircounter++); uint32 resume_key = SVAL(params,6); BOOL uses_resume_key = BITSETW(params+10,2); BOOL continue_bit = BITSETW(params+10,3); @@ -520,7 +522,7 @@ typedef struct /******************************************************************* open a directory ********************************************************************/ -void *OpenDir(int snum, char *name, BOOL use_veto) +void *OpenDir(int cnum, char *name, BOOL use_veto) { Dir *dirp; char *n; @@ -541,7 +543,7 @@ void *OpenDir(int snum, char *name, BOOL use_veto) int l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ - if (use_veto && is_vetoed_name(snum, n)) continue; + if (use_veto && IS_VETO_PATH(cnum, n)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 8cbe46d9e1..883c2c050d 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -331,8 +331,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - setuid(user_id); /* Restore the original UID status */ - seteuid(euser_id); + seteuid(euser_id); /* Restore the original uid status. */ + setuid(user_id); if (ret < 0) { DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5869588664..374a01b665 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -771,7 +771,7 @@ int reply_search(char *inbuf,char *outbuf) memcpy(mask,status+1,11); mask[11] = 0; dirtype = CVAL(status,0) & 0x1F; - Connections[cnum].dirptr = dptr_fetch(SNUM(cnum), status+12,&dptr_num); + Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num); if (!Connections[cnum].dirptr) goto SearchEmpty; string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); @@ -836,7 +836,7 @@ int reply_search(char *inbuf,char *outbuf) { memcpy(p,status,21); make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0); - dptr_fill(SNUM(cnum), p+12,dptr_num); + dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; else @@ -858,7 +858,7 @@ int reply_search(char *inbuf,char *outbuf) { memcpy(p,status,21); make_dir_struct(p,mask,fname,size,mode,date); - dptr_fill(SNUM(cnum), p+12,dptr_num); + dptr_fill(p+12,dptr_num); numentries++; } p += DIR_STRUCT_SIZE; @@ -941,7 +941,7 @@ int reply_fclose(char *inbuf,char *outbuf) memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); - if(dptr_fetch(SNUM(cnum), status+12,&dptr_num)) { + if(dptr_fetch(status+12,&dptr_num)) { /* Close the dptr - we know it's gone */ dptr_close(dptr_num); } @@ -1323,7 +1323,7 @@ int reply_unlink(char *inbuf,char *outbuf) char *dname; if (check_name(directory,cnum)) - dirptr = OpenDir(SNUM(cnum), directory, True); + dirptr = OpenDir(cnum, directory, True); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -2457,7 +2457,7 @@ int reply_rmdir(char *inbuf,char *outbuf) do a recursive delete) then fail the rmdir. */ BOOL all_veto_files = True; char *dname; - void *dirptr = OpenDir(SNUM(cnum), directory, False); + void *dirptr = OpenDir(cnum, directory, False); if(dirptr != NULL) { @@ -2466,7 +2466,7 @@ int reply_rmdir(char *inbuf,char *outbuf) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; - if(!is_vetoed_name(SNUM(cnum), dname)) + if(!IS_VETO_PATH(cnum, dname)) { all_veto_files = False; break; @@ -2733,7 +2733,7 @@ int reply_mv(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(SNUM(cnum), directory, True); + dirptr = OpenDir(cnum, directory, True); if (dirptr) { @@ -2924,7 +2924,7 @@ int reply_copy(char *inbuf,char *outbuf) pstring destname; if (check_name(directory,cnum)) - dirptr = OpenDir(SNUM(cnum), directory, True); + dirptr = OpenDir(cnum, directory, True); if (dirptr) { @@ -3105,7 +3105,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) mincount = SVAL(inbuf,smb_vwv4); data = smb_buf(outbuf); - pad = ((int)data)%4; + pad = ((long)data)%4; if (pad) pad = 4 - pad; data += pad; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3c5cd6bea7..30a3027de9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -226,7 +226,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) /* Optimization : Only call is_hidden_path if it's not already hidden. */ - if (!(result & aHIDDEN) && is_hidden_path(SNUM(cnum), path)) + if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path)) { result |= aHIDDEN; } @@ -358,7 +358,7 @@ scan a directory to find a filename, matching without case sensitivity If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) +static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) { void *cur_dir; char *dname; @@ -371,7 +371,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) if (*path == 0) path = "."; - if (docache && (dname = DirCacheCheck(path,name,snum))) { + if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) { strcpy(name, dname); return(True); } @@ -380,7 +380,7 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) check_mangled_stack(name); /* open the directory */ - if (!(cur_dir = OpenDir(snum, path, True))) + if (!(cur_dir = OpenDir(cnum, path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); @@ -394,13 +394,13 @@ static BOOL scan_directory(char *path, char *name,int snum,BOOL docache) continue; strcpy(name2,dname); - if (!name_map_mangle(name2,False,snum)) continue; + if (!name_map_mangle(name2,False,SNUM(cnum))) continue; if ((mangled && mangled_equal(name,name2)) || fname_equal(name, dname)) { /* we've found the file, change it's name and return */ - if (docache) DirCacheAdd(path,name,dname,snum); + if (docache) DirCacheAdd(path,name,dname,SNUM(cnum)); strcpy(name, dname); CloseDir(cur_dir); return(True); @@ -533,7 +533,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) /* try to find this part of the path in the directory */ if (strchr(start,'?') || strchr(start,'*') || - !scan_directory(dirpath, start, SNUM(cnum), end?True:False)) + !scan_directory(dirpath, start, cnum, end?True:False)) { if (end) { @@ -810,7 +810,7 @@ BOOL check_name(char *name,int cnum) errno = 0; - if( is_vetoed_name(SNUM(cnum), name)) + if( IS_VETO_PATH(cnum, name)) { DEBUG(5,("file path name %s vetoed\n",name)); return(0); @@ -2485,6 +2485,8 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->printer = (strncmp(dev,"LPT",3) == 0); pcon->ipc = (strncmp(dev,"IPC",3) == 0); pcon->dirptr = NULL; + pcon->veto_list = NULL; + pcon->hide_list = NULL; string_set(&pcon->dirpath,""); string_set(&pcon->user,user); @@ -2627,6 +2629,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de /* we've finished with the sensitive stuff */ unbecome_user(); + /* Add veto/hide lists */ + if (!IS_IPC(cnum) && !IS_PRINT(cnum)) + { + set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum))); + set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum))); + } + { DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n", timestring(), @@ -3176,6 +3185,9 @@ void close_cnum(int cnum, uint16 vuid) Connections[cnum].ngroups = 0; } + free_namearray(Connections[cnum].veto_list); + free_namearray(Connections[cnum].hide_list); + string_set(&Connections[cnum].user,""); string_set(&Connections[cnum].dirpath,""); string_set(&Connections[cnum].connectpath,""); @@ -3440,22 +3452,28 @@ void exit_server(char *reason) /**************************************************************************** do some standard substitutions in a string ****************************************************************************/ -void standard_sub(int cnum,char *s) +void standard_sub(int cnum,char *string) { - if (!strchr(s,'%')) return; - - if (VALID_CNUM(cnum)) - { - string_sub(s,"%S",lp_servicename(Connections[cnum].service)); - string_sub(s,"%P",Connections[cnum].connectpath); - string_sub(s,"%u",Connections[cnum].user); - if (strstr(s,"%H")) { - char *home = get_home_dir(Connections[cnum].user); - if (home) string_sub(s,"%H",home); + if (VALID_CNUM(cnum)) { + char *p, *s, *home; + + for ( s=string ; (p=strchr(s, '%')) != NULL ; s=p ) { + switch (*(p+1)) { + case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL) + string_sub(p,"%H",home); + else + p += 2; + break; + case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break; + case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break; + case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break; + case 'u' : string_sub(p,"%u",Connections[cnum].user); break; + case '\0' : p++; break; /* don't run off the end of the string */ + default : p+=2; break; } - string_sub(s,"%g",gidtoname(Connections[cnum].gid)); } - standard_sub_basic(s); + } + standard_sub_basic(string); } /* @@ -4267,7 +4285,10 @@ static void usage(char *pname) char buf[20]; if ((fd = open(pidFile, - O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) +#ifdef O_NONBLOCK + O_NONBLOCK | +#endif + O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) { DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno))); exit(1); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1b199f01ba..11a2a50ffe 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -782,7 +782,7 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz return(ERROR(ERRDOS,ERRnomem)); /* Check that the dptr is valid */ - if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(SNUM(cnum), params, dptr_num))) + if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num))) return(ERROR(ERRDOS,ERRnofiles)); string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); -- cgit From 834518eddd66c926b8aac7aa2b7024639417d6a2 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Thu, 24 Jul 1997 22:42:16 +0000 Subject: loadparm.c: Changed default create mask to 755 to support MAP_ARCHIVE. server.c: Added check for MAP_ARCHIVE before we set archive bit. Jeremy (jallison@whistle.com) (This used to be commit d21a166277776f6750b7bcc3c4f9073cce17eacb) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 30a3027de9..1b961ab7c7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -194,7 +194,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aRONLY; } - if ((sbuf->st_mode & S_IXUSR) != 0) + if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0)) result |= aARCH; if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0)) -- cgit From 7314126d9e1d84997d818166f27e2076d55ff04e Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 28 Jul 1997 18:59:57 +0000 Subject: client.c: Added amanda fixes. clitar.c: Added amanda fixes. nameannounce.c: Removed redundent code. nameelect.c: Removed redundent code. nameserv.h: Removed redundent code. nameservresp.c: Removed redundent code. namework.c: Removed redundent code. password.c: Prevented crash if getpwnam fails. Jeremy (jallison@whistle.com) (This used to be commit 760fe30353de66e8e6571f8ff4ec1064261b5428) --- source3/smbd/password.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index eb837c2584..23c29104e3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -237,13 +237,15 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) vuser->real_name = Realloc(vuser->real_name, 15); strcpy(vuser->real_name, "\0"); if (lp_unix_realname()) { - pwfile=getpwnam(vuser->name); - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); - real_name_len = strcspn(pwfile->pw_gecos, ","); - DEBUG(3, ("Real name length: %d\n", real_name_len)); - vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1); - strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len); - vuser->real_name[real_name_len]='\0'; + if((pwfile=getpwnam(vuser->name))!= NULL) + { + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); + real_name_len = strcspn(pwfile->pw_gecos, ","); + DEBUG(3, ("Real name length: %d\n", real_name_len)); + vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1); + strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len); + vuser->real_name[real_name_len]='\0'; + } } return (uint16)((num_validated_users - 1) + VUID_OFFSET); -- cgit From 75bbf35a8626ea30ac31546d0ceb9e2801ab7eae Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 30 Jul 1997 19:17:51 +0000 Subject: client.c: Minor change to cast parameters for DEC unix. clientutil.c: Minor change to cast parameters for DEC unix. ipc.c: Fixes to parameterise the stuff John wants. loadparm.c: Fixes to parameterise the stuff John wants. nameannounce.c: Fixes to parameterise the stuff John wants. namedbwork.c: Fixes to parameterise the stuff John wants. nameserv.h: Fixes to parameterise the stuff John wants. proto.h: Fixes to parameterise the stuff John wants. smb.h: Fixes to parameterise the stuff John wants. util.c: tidy. Jeremy (jallison@whistle.com) (This used to be commit 9fbca2594ba775450d5dca13cbce257b4362ca66) --- source3/smbd/ipc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 17bdd3ca66..89dd9f511b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1682,7 +1682,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, struct srv_info_struct *servers=NULL; int i,count; pstring comment; - uint32 servertype=DFLT_SERVER_TYPE; + uint32 servertype= lp_default_server_announce(); strcpy(comment,lp_serverstring()); @@ -1696,8 +1696,8 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, } if (servers) free(servers); - SCVAL(p,0,MAJOR_VERSION); - SCVAL(p,1,MINOR_VERSION); + SCVAL(p,0,lp_major_announce_version()); + SCVAL(p,1,lp_minor_announce_version()); SIVAL(p,2,servertype); if (mdrcnt == struct_len) { @@ -1777,8 +1777,8 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data, p2 = skip_string(p2,1); p += 4; - SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */ - SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */ + SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ + SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */ p += 2; SIVAL(p,0,PTR_DIFF(p2,*rdata)); -- cgit From b5114b41f574c5a5341e07d6f16877a48c6b874d Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 5 Aug 1997 01:31:55 +0000 Subject: Makefile: Added IRIX 6 target. loadparm.c: Fixed stupid static warnings with set_default_server_announce_type. password.c: Fixed char -> uchar cast warnings. nameservreply.c: Fixed group fade out code. Jeremy (jallison@whistle.com) (This used to be commit a2dd5c5a551547e83c707e63c0696c7724035501) --- source3/smbd/password.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 23c29104e3..67f32d376c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -54,7 +54,7 @@ void generate_next_challenge(char *challenge) v2 = (counter++) * getpid() + tval.tv_usec; SIVAL(challenge,0,v1); SIVAL(challenge,4,v2); - E1(challenge,"SAMBA",(char *)saved_challenge); + E1((uchar *)challenge,(uchar *)"SAMBA",(uchar *)saved_challenge); memcpy(challenge,saved_challenge,8); challenge_sent = True; } @@ -944,7 +944,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) DEBUG(4,("Checking NT MD4 password\n")); if(smb_password_check(password, smb_pass->smb_nt_passwd, - (char *)challenge)) + (unsigned char *)challenge)) { update_protected_database(user,True); return(True); @@ -957,7 +957,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) if (smb_password_check(password, smb_pass->smb_passwd, - (char *)challenge)) { + (unsigned char *)challenge)) { update_protected_database(user,True); return(True); } -- cgit From 9170cfd4b6455a235e7600e7988f34d77693e7ed Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Mon, 11 Aug 1997 18:06:44 +0000 Subject: spelling. lkcl (This used to be commit 7e326450cf5aeee704df9fb5e298b0fc353dfb8b) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 67f32d376c..2740304cc4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1225,7 +1225,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password)); #endif - /* there are several possabilities: + /* there are several possibilities: 1) login as the given user with given password 2) login as a previously registered username with the given password 3) login as a session list username with the given password -- cgit From b65fdef1ba6a9a0a27da724a8324a6f2804759cf Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 13 Aug 1997 20:16:32 +0000 Subject: includes.h: Fixed S_IFLNK for old DEC ultrix. ipc.c: Finally :-) fixed responses to NetServerEnum2 when SV_TYPE_ALL given. Jeremy (jallison@whistle.com) (This used to be commit 1dc37c83506a434840a04c49e423cd9d2223fab4) --- source3/smbd/ipc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 89dd9f511b..d6d2f289aa 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -982,11 +982,17 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, int i,missed; fstring domain; BOOL domain_request; - BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY; + BOOL local_request; - if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM; + /* If someone sets all the bits they don't really mean to set + DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the + known servers. */ + + if (servertype == SV_TYPE_ALL) + servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); + local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0); p += 8; -- cgit From ea4c7557dd7048ba7a266d28de9e43fe0e282a52 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sun, 17 Aug 1997 21:03:12 +0000 Subject: connecting to IPC$ goes under the guest account. the IPC$ share should be treated no differently than any other share (for any security setting: user, server or share). this will clear up a bug where, when clients connect to the IPC$ share, this used to be done under the guest account. the standard_sub_basic() macros will substitute the _guest_ account for %U, causing the samba server to look different from when the client then connects to any other share. lkcl (This used to be commit 38526569608f6eb5f098efee7013037873d140bf) --- source3/smbd/server.c | 41 +++++++++++++++++++---------------------- source3/smbd/uid.c | 2 -- 2 files changed, 19 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1b961ab7c7..35774c0a43 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2541,25 +2541,22 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->ngroups = 0; pcon->groups = NULL; - if (!IS_IPC(cnum)) - { - /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); + /* Find all the groups this uid is in and store them. Used by become_user() */ + setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); - /* check number of connections */ - if (!claim_connection(cnum, + /* check number of connections */ + if (!claim_connection(cnum, lp_servicename(SNUM(cnum)), lp_max_connections(SNUM(cnum)),False)) - { - DEBUG(1,("too many connections - rejected\n")); - return(-8); - } + { + DEBUG(1,("too many connections - rejected\n")); + return(-8); + } - if (lp_status(SNUM(cnum))) - claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection); + if (lp_status(SNUM(cnum))) + claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection); - first_connection = False; - } /* IS_IPC */ + first_connection = False; pcon->open = True; @@ -2577,13 +2574,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { DEBUG(0,("Can't become connected user!\n")); pcon->open = False; - if (!IS_IPC(cnum)) { - yield_connection(cnum, + yield_connection(cnum, lp_servicename(SNUM(cnum)), lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); + if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); + { + return(-1); } - return(-1); } if (ChDir(pcon->connectpath) != 0) @@ -2592,13 +2589,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->connectpath,strerror(errno))); pcon->open = False; unbecome_user(); - if (!IS_IPC(cnum)) { - yield_connection(cnum, + yield_connection(cnum, lp_servicename(SNUM(cnum)), lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); + if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); + { + return(-5); } - return(-5); } string_set(&pcon->origpath,pcon->connectpath); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index cdc4e474c6..4ffdb0923e 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -253,12 +253,10 @@ BOOL become_user(int cnum, uint16 vuid) 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)) -- cgit From e9269c67a59ffa741123cb2ce3ab8dfb97136dec Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 19 Aug 1997 19:22:26 +0000 Subject: Makefile: Changed for HPUX10 tidyup. includes.h: Changed for HPUX10 tidyup. ipc.c: Fixed bug where getting local server list from NT browsers would fail. nmbsync.c: Fixed bug where getting local server list from NT browsers would fail. proto.h: Changed for crash bug on SCO with USE_MMAP. quotas.c: Added OSF quotas (patch from Bret Giddings ). Rolled back solaris uid change - I think it was wrong. reply.c: Changed for crash bug on SCO with USE_MMAP. server.c: Removed Lukes changes. Changed for crash bug on SCO with USE_MMAP. smb.h: Changed for crash bug on SCO with USE_MMAP. smbpasswd.c:Fixed crash bug with Lukes changes. uid.c: Removed Lukes changes. util.c: Fixed I18N bug with extended char filenames and widelinks = no. Jeremy (jallison@whistle.com) (This used to be commit bf1c79f7fd7f9beec4f9f4e58337cadceeb1cb38) --- source3/smbd/ipc.c | 9 +++++++++ source3/smbd/quotas.c | 45 ++++++++++++++++++++++++++++++++++++++++-- source3/smbd/reply.c | 10 +++++----- source3/smbd/server.c | 54 +++++++++++++++++++++++++++------------------------ source3/smbd/uid.c | 2 ++ 5 files changed, 88 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index d6d2f289aa..e21021c0ac 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -991,6 +991,15 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set + any other bit (they may just set this bit on it's own) they + want all the locally seen servers. However this bit can be + set on its own so set the requested servers to be + ALL - DOMAIN_ENUM. */ + + if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) + servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); + domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0); diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 883c2c050d..d19d386e27 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -331,8 +331,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - seteuid(euser_id); /* Restore the original uid status. */ - setuid(user_id); + setuid(user_id); /* Restore the original uid status. */ + seteuid(euser_id); if (ret < 0) { DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); @@ -363,6 +363,47 @@ DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n" return(True); } + +#elif defined(OSF1) +#include + +/**************************************************************************** +try to get the disk space from disk quotas - OFS1 version +****************************************************************************/ +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t user_id, euser_id; + int r; + struct dqblk D; + struct stat S; + + euser_id = geteuid(); + user_id = getuid(); + + setreuid(euser_id, euser_id); + r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D); + if (setreuid(user_id, euser_id) == -1) + DEBUG(5,("Unable to reset uid to %d\n", user_id)); + + *bsize = DEV_BSIZE; + + if (r) + return(False); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + + if (D.dqb_bsoftlimit==0) + return(False); + + if ((D.dqb_curblocks>D.dqb_bsoftlimit)) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else { + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + } + return (True); +} #else #ifdef __FreeBSD__ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 374a01b665..0216b58c34 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1374,7 +1374,7 @@ int reply_readbraw(char *inbuf, char *outbuf) { int cnum,maxcount,mincount,fnum; int nread = 0; - int startpos; + uint32 startpos; char *header = outbuf; int ret=0; int fd; @@ -1418,7 +1418,7 @@ int reply_readbraw(char *inbuf, char *outbuf) Files[fnum].size = size; } - nread = MIN(maxcount,size - startpos); + nread = MIN(maxcount,(int)(size - startpos)); } if (nread < mincount) @@ -1515,7 +1515,7 @@ int reply_read(char *inbuf,char *outbuf) int cnum,numtoread,fnum; int nread = 0; char *data; - int startpos; + uint32 startpos; int outsize = 0; cnum = SVAL(inbuf,smb_tid); @@ -3081,7 +3081,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) int nread = -1; int total_read; char *data; - int32 startpos; + uint32 startpos; int outsize, mincount, maxcount; int max_per_packet; int tcount; @@ -3152,7 +3152,7 @@ int reply_writebmpx(char *inbuf,char *outbuf) int cnum,numtowrite,fnum; int nwritten = -1; int outsize = 0; - int32 startpos; + uint32 startpos; int tcount, write_through, smb_doff; char *data; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 35774c0a43..3d5b75794b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1704,20 +1704,21 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, /**************************************************************************** seek a file. Try to avoid the seek if possible ****************************************************************************/ -int seek_file(int fnum,int pos) +int seek_file(int fnum,uint32 pos) { - int offset = 0; + uint32 offset = 0; if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum)) offset = 3; - Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset; + Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) + - offset); return(Files[fnum].pos); } /**************************************************************************** read from a file ****************************************************************************/ -int read_file(int fnum,char *data,int pos,int n) +int read_file(int fnum,char *data,uint32 pos,int n) { int ret=0,readret; @@ -1733,7 +1734,7 @@ int read_file(int fnum,char *data,int pos,int n) #if USE_MMAP if (Files[fnum].mmap_ptr) { - int num = MIN(n,Files[fnum].mmap_size-pos); + int num = MIN(n,(int)(Files[fnum].mmap_size-pos)); if (num > 0) { memcpy(data,Files[fnum].mmap_ptr+pos,num); @@ -2541,22 +2542,25 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->ngroups = 0; pcon->groups = NULL; - /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); + if (!IS_IPC(cnum)) + { + /* Find all the groups this uid is in and store them. Used by become_user() */ + setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); - /* check number of connections */ - if (!claim_connection(cnum, + /* check number of connections */ + if (!claim_connection(cnum, lp_servicename(SNUM(cnum)), lp_max_connections(SNUM(cnum)),False)) - { - DEBUG(1,("too many connections - rejected\n")); - return(-8); - } + { + DEBUG(1,("too many connections - rejected\n")); + return(-8); + } - if (lp_status(SNUM(cnum))) - claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection); + if (lp_status(SNUM(cnum))) + claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection); - first_connection = False; + first_connection = False; + } /* IS_IPC */ pcon->open = True; @@ -2574,13 +2578,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { DEBUG(0,("Can't become connected user!\n")); pcon->open = False; - yield_connection(cnum, + if (!IS_IPC(cnum)) { + yield_connection(cnum, lp_servicename(SNUM(cnum)), lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - { - return(-1); + if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); } + return(-1); } if (ChDir(pcon->connectpath) != 0) @@ -2589,13 +2593,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->connectpath,strerror(errno))); pcon->open = False; unbecome_user(); - yield_connection(cnum, + if (!IS_IPC(cnum)) { + yield_connection(cnum, lp_servicename(SNUM(cnum)), lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - { - return(-5); + if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); } + return(-5); } string_set(&pcon->origpath,pcon->connectpath); @@ -3420,7 +3424,7 @@ void exit_server(char *reason) DEBUG(2,("Closing connections\n")); for (i=0;i 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)) -- cgit From c76dc7c2963d1205cf46849df6b6f0edbf63692d Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 20 Aug 1997 01:22:05 +0000 Subject: Fix suggested by "Christian Groessler" dir.c: Cause dptr_create to return -2 when failing on unix error. reply.c: Use UNIXERROR in more cases. server.c: Add ENOTDIR mapping to error table. trans2.c: Correctly determine UNIX error on dptr_create. Jeremy (jallison@whistle.com) (This used to be commit de38a0b34fcd65fa3024300f978aa30eb86d854f) --- source3/smbd/dir.c | 2 +- source3/smbd/reply.c | 8 ++++++-- source3/smbd/server.c | 1 + source3/smbd/trans2.c | 6 +++++- 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5bd5b1d573..06ee6ae8ed 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -282,7 +282,7 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid) int oldi; if (!start_dir(cnum,path)) - return(-1); + return(-2); /* Code to say use a unix error return code. */ if (dptrs_open >= MAXDIR) dptr_idleoldest(); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0216b58c34..f630e71e25 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -546,7 +546,7 @@ int reply_chkpth(char *inbuf,char *outbuf) ok = directory_exist(name,NULL); if (!ok) - return(ERROR(ERRDOS,ERRbadpath)); + return(UNIXERROR(ERRDOS,ERRbadpath)); outsize = set_message(outbuf,0,0,True); @@ -825,7 +825,11 @@ int reply_search(char *inbuf,char *outbuf) { dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid)); if (dptr_num < 0) - return(ERROR(ERRDOS,ERRnofids)); + { + if(dptr_num == -2) + return (UNIXERROR(ERRDOS,ERRnofids)); + return(ERROR(ERRDOS,ERRnofids)); + } } DEBUG(4,("dptr_num is %d\n",dptr_num)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3d5b75794b..93d05ffab6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1940,6 +1940,7 @@ struct {EPERM,ERRDOS,ERRnoaccess}, {EACCES,ERRDOS,ERRnoaccess}, {ENOENT,ERRDOS,ERRbadfile}, + {ENOTDIR,ERRDOS,ERRbadpath}, {EIO,ERRHRD,ERRgeneral}, {EBADF,ERRSRV,ERRsrverror}, {EINVAL,ERRSRV,ERRsrverror}, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 11a2a50ffe..e7fd6824ab 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -614,7 +614,11 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid)); if (dptr_num < 0) - return(ERROR(ERRDOS,ERRbadpath)); + { + if(dptr_num == -2) + return (UNIXERROR(ERRDOS,ERRbadpath)); + return(ERROR(ERRDOS,ERRbadpath)); + } /* convert the formatted masks */ { -- cgit From 46dbd8c06009ad9e64251ae844fb16f2a30f5ab7 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 20 Aug 1997 20:32:23 +0000 Subject: Changes to allow Samba to return the same error code as Windows NT. Takes care of the cases where a Windows program is parsing a pathname component by component and expects 2 different errors. ERRbadpath - if a component in the path doesn't exist. ERRbaddirectory - if a component in the path exists but is not a directory. Extra error code added to smb.h to support this. Code based on suggestions from "Christian Groessler" . Jeremy (jallison@whistle.com) (This used to be commit 28b3c6db8a81b41b448a4f3cd98e9cd2c4b5fb2e) --- source3/smbd/pipes.c | 11 ++- source3/smbd/reply.c | 239 ++++++++++++++++++++++++++++++++++++++++---------- source3/smbd/server.c | 25 +++++- source3/smbd/trans2.c | 70 +++++++++++++-- 4 files changed, 285 insertions(+), 60 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index a294ee4f49..afab7e1d91 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -84,6 +84,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) struct stat sbuf; int smb_action = 0; int i; + BOOL bad_path = False; /* XXXX we need to handle passed times, sattr and flags */ strcpy(fname,smb_buf(inbuf)); @@ -114,7 +115,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) Connections[cnum].read_only = 0; smb_ofun |= 0x10; /* Add Create it not exists flag */ - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); if (fnum < 0) @@ -129,7 +130,15 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) &rmode,&smb_action); if (!Files[fnum].open) + { + /* Change the error code if bad_path was set. */ + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f630e71e25..cadd63e045 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -534,11 +534,12 @@ int reply_chkpth(char *inbuf,char *outbuf) int cnum,mode; pstring name; BOOL ok = False; - + BOOL bad_path = False; + cnum = SVAL(inbuf,smb_tid); strcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,cnum,0); + unix_convert(name,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); @@ -546,8 +547,20 @@ int reply_chkpth(char *inbuf,char *outbuf) ok = directory_exist(name,NULL); if (!ok) + { + /* We special case this - as when a Windows machine + is parsing a path is steps through the components + one at a time - if a component fails it expects + ERRbadpath, not ERRbadfile. + */ + if(errno == ENOENT) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRbadpath)); - + } + outsize = set_message(outbuf,0,0,True); DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode)); @@ -569,11 +582,12 @@ int reply_getatr(char *inbuf,char *outbuf) int mode=0; uint32 size=0; time_t mtime=0; - + BOOL bad_path = False; + cnum = SVAL(inbuf,smb_tid); strcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ @@ -587,23 +601,31 @@ int reply_getatr(char *inbuf,char *outbuf) } else if (check_name(fname,cnum)) + { + if (sys_stat(fname,&sbuf) == 0) { - if (sys_stat(fname,&sbuf) == 0) - { - mode = dos_mode(cnum,fname,&sbuf); - size = sbuf.st_size; - mtime = sbuf.st_mtime; - if (mode & aDIR) - size = 0; - ok = True; - } - else - DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); + mode = dos_mode(cnum,fname,&sbuf); + size = sbuf.st_size; + mtime = sbuf.st_mtime; + if (mode & aDIR) + size = 0; + ok = True; + } + else + DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); } if (!ok) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadfile)); - + } + outsize = set_message(outbuf,10,0,True); SSVAL(outbuf,smb_vwv0,mode); @@ -635,11 +657,12 @@ int reply_setatr(char *inbuf,char *outbuf) BOOL ok=False; int mode; time_t mtime; - + BOOL bad_path = False; + cnum = SVAL(inbuf,smb_tid); strcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); @@ -652,8 +675,16 @@ int reply_setatr(char *inbuf,char *outbuf) ok = set_filetime(fname,mtime); if (!ok) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRnoaccess)); - + } + outsize = set_message(outbuf,0,0,True); DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode)); @@ -715,6 +746,7 @@ int reply_search(char *inbuf,char *outbuf) BOOL check_descend = False; BOOL expect_close = False; BOOL can_open = True; + BOOL bad_path = False; *mask = *directory = *fname = 0; @@ -742,26 +774,32 @@ int reply_search(char *inbuf,char *outbuf) strcpy(directory,smb_buf(inbuf)+1); strcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,cnum,0); + unix_convert(directory,cnum,0,&bad_path); unix_format(dir2); if (!check_name(directory,cnum)) - can_open = False; + can_open = False; p = strrchr(dir2,'/'); if (p == NULL) - {strcpy(mask,dir2);*dir2 = 0;} + { + strcpy(mask,dir2); + *dir2 = 0; + } else - {*p = 0;strcpy(mask,p+1);} + { + *p = 0; + strcpy(mask,p+1); + } p = strrchr(directory,'/'); if (!p) - *directory = 0; + *directory = 0; else - *p = 0; + *p = 0; if (strlen(directory) == 0) - strcpy(directory,"./"); + strcpy(directory,"./"); bzero(status,21); CVAL(status,0) = dirtype; } @@ -827,7 +865,14 @@ int reply_search(char *inbuf,char *outbuf) if (dptr_num < 0) { if(dptr_num == -2) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return (UNIXERROR(ERRDOS,ERRnofids)); + } return(ERROR(ERRDOS,ERRnofids)); } } @@ -974,27 +1019,42 @@ int reply_open(char *inbuf,char *outbuf) int unixmode; int rmode=0; struct stat sbuf; - + BOOL bad_path = False; + cnum = SVAL(inbuf,smb_tid); share_mode = SVAL(inbuf,smb_vwv0); strcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); if (!check_name(fname,cnum)) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); - + } + unixmode = unix_mode(cnum,aARCH); open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL); if (!Files[fnum].open) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); @@ -1047,6 +1107,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) int size=0,fmode=0,mtime=0,rmode=0; struct stat sbuf; int smb_action = 0; + BOOL bad_path = False; /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(cnum)) @@ -1055,14 +1116,21 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* XXXX we need to handle passed times, sattr and flags */ strcpy(fname,smb_buf(inbuf)); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); if (!check_name(fname,cnum)) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } unixmode = unix_mode(cnum,smb_attr | aARCH); @@ -1070,7 +1138,14 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) &rmode,&smb_action); if (!Files[fnum].open) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); @@ -1147,13 +1222,14 @@ int reply_mknew(char *inbuf,char *outbuf) int createmode; mode_t unixmode; int ofun = 0; + BOOL bad_path = False; com = SVAL(inbuf,smb_com); cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); strcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); if (createmode & aVOLID) { @@ -1167,7 +1243,14 @@ int reply_mknew(char *inbuf,char *outbuf) return(ERROR(ERRSRV,ERRnofids)); if (!check_name(fname,cnum)) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } if(com == SMBmknew) { @@ -1184,8 +1267,15 @@ int reply_mknew(char *inbuf,char *outbuf) open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL); if (!Files[fnum].open) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); - + } + outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); @@ -1212,11 +1302,12 @@ int reply_ctemp(char *inbuf,char *outbuf) int outsize = 0; int createmode; mode_t unixmode; - + BOOL bad_path = False; + cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); unixmode = unix_mode(cnum,createmode); @@ -1225,7 +1316,14 @@ int reply_ctemp(char *inbuf,char *outbuf) return(ERROR(ERRSRV,ERRnofids)); if (!check_name(fname,cnum)) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } strcpy(fname2,(char *)mktemp(fname)); @@ -1234,7 +1332,14 @@ int reply_ctemp(char *inbuf,char *outbuf) open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL); if (!Files[fnum].open) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } outsize = set_message(outbuf,1,2 + strlen(fname2),True); SSVAL(outbuf,smb_vwv0,fnum); @@ -1290,6 +1395,7 @@ int reply_unlink(char *inbuf,char *outbuf) int error = ERRnoaccess; BOOL has_wild; BOOL exists=False; + BOOL bad_path = False; *directory = *mask = 0; @@ -1300,7 +1406,7 @@ int reply_unlink(char *inbuf,char *outbuf) DEBUG(3,("reply_unlink : %s\n",name)); - unix_convert(name,cnum,0); + unix_convert(name,cnum,0,&bad_path); p = strrchr(name,'/'); if (!p) { @@ -1362,7 +1468,14 @@ int reply_unlink(char *inbuf,char *outbuf) if (exists) return(ERROR(ERRDOS,error)); else + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,error)); + } } outsize = set_message(outbuf,0,0,True); @@ -2415,17 +2528,25 @@ int reply_mkdir(char *inbuf,char *outbuf) pstring directory; int cnum; int outsize,ret= -1; - + BOOL bad_path = False; + strcpy(directory,smb_buf(inbuf) + 1); cnum = SVAL(inbuf,smb_tid); - unix_convert(directory,cnum,0); + unix_convert(directory,cnum,0,&bad_path); if (check_name(directory,cnum)) ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); if (ret < 0) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); - + } + outsize = set_message(outbuf,0,0,True); DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret)); @@ -2443,10 +2564,11 @@ int reply_rmdir(char *inbuf,char *outbuf) int cnum; int outsize = 0; BOOL ok = False; - + BOOL bad_path = False; + cnum = SVAL(inbuf,smb_tid); strcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,cnum,0); + unix_convert(directory,cnum,0,&bad_path); if (check_name(directory,cnum)) { @@ -2524,8 +2646,15 @@ int reply_rmdir(char *inbuf,char *outbuf) } if (!ok) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRbadpath)); - + } + outsize = set_message(outbuf,0,0,True); DEBUG(3,("%s rmdir %s\n",timestring(),directory)); @@ -2629,6 +2758,8 @@ int reply_mv(char *inbuf,char *outbuf) int error = ERRnoaccess; BOOL has_wild; BOOL exists=False; + BOOL bad_path1 = False; + BOOL bad_path2 = False; *directory = *mask = 0; @@ -2639,8 +2770,8 @@ int reply_mv(char *inbuf,char *outbuf) DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - unix_convert(name,cnum,0); - unix_convert(newname,cnum,newname_last_component); + unix_convert(name,cnum,0,&bad_path1); + unix_convert(newname,cnum,newname_last_component,&bad_path2); /* * Split the old name into directory and last component @@ -2775,7 +2906,14 @@ int reply_mv(char *inbuf,char *outbuf) if (exists) return(ERROR(ERRDOS,error)); else + { + if((errno == ENOENT) && (bad_path1 || bad_path2)) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,error)); + } } outsize = set_message(outbuf,0,0,True); @@ -2865,6 +3003,8 @@ int reply_copy(char *inbuf,char *outbuf) int ofun = SVAL(inbuf,smb_vwv1); int flags = SVAL(inbuf,smb_vwv2); BOOL target_is_directory=False; + BOOL bad_path1 = False; + BOOL bad_path2 = False; *directory = *mask = 0; @@ -2881,8 +3021,8 @@ int reply_copy(char *inbuf,char *outbuf) return(ERROR(ERRSRV,ERRinvdevice)); } - unix_convert(name,cnum,0); - unix_convert(newname,cnum,0); + unix_convert(name,cnum,0,&bad_path1); + unix_convert(newname,cnum,0,&bad_path2); target_is_directory = directory_exist(newname,NULL); @@ -2960,7 +3100,14 @@ int reply_copy(char *inbuf,char *outbuf) if (exists) return(ERROR(ERRDOS,error)); else + { + if((errno == ENOENT) && (bad_path1 || bad_path2)) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,error)); + } } outsize = set_message(outbuf,1,0,True); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 93d05ffab6..aaf62fdcad 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -426,14 +426,22 @@ If the saved_last_component != 0, then the unmodified last component of the pathname is returned there. This is used in an exceptional case in reply_mv (so far). If saved_last_component == 0 then nothing is returned there. + +The bad_path arg is set to True if the filename walk failed. This is +used to pick the correct error code to return between ENOENT and ENOTDIR +as Windows applications depend on ERRbadpath being returned if a component +of a pathname does not exist. ****************************************************************************/ -BOOL unix_convert(char *name,int cnum,pstring saved_last_component) +BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path) { struct stat st; char *start, *end; pstring dirpath; + int saved_errno; *dirpath = 0; + *bad_path = False; + if(saved_last_component) *saved_last_component = 0; @@ -480,12 +488,14 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) if (sys_stat(name,&st) == 0) return(True); + saved_errno = errno; + DEBUG(5,("unix_convert(%s,%d)\n",name,cnum)); /* a special case - if we don't have any mangling chars and are case sensitive then searching won't help */ if (case_sensitive && !is_mangled(name) && - !lp_strip_dot() && !use_mangled_map) + !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) return(False); /* now we need to recursively match the name against the real @@ -506,7 +516,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) if (end) *end = 0; if(saved_last_component != 0) - strcpy(saved_last_component, end ? end + 1 : start); + strcpy(saved_last_component, end ? end + 1 : start); /* check if the name exists up to this point */ if (sys_stat(name, &st) == 0) @@ -540,6 +550,13 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component) /* an intermediate part of the name can't be found */ DEBUG(5,("Intermediate not found %s\n",start)); *end = '/'; + /* We need to return the fact that the intermediate + name resolution failed. This is used to return an + error of ERRbadpath rather than ERRbadfile. Some + Windows applications depend on the difference between + these two errors. + */ + *bad_path = True; return(False); } @@ -1940,7 +1957,7 @@ struct {EPERM,ERRDOS,ERRnoaccess}, {EACCES,ERRDOS,ERRnoaccess}, {ENOENT,ERRDOS,ERRbadfile}, - {ENOTDIR,ERRDOS,ERRbadpath}, + {ENOTDIR,ERRDOS,ERRbaddirectory}, {EIO,ERRHRD,ERRgeneral}, {EBADF,ERRSRV,ERRsrverror}, {EINVAL,ERRSRV,ERRsrverror}, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e7fd6824ab..9a48fb3ded 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -184,6 +184,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, int32 inode = 0; struct stat sbuf; int smb_action = 0; + BOOL bad_path = False; StrnCpy(fname,pname,namelen); @@ -192,14 +193,21 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); if (!check_name(fname,cnum)) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } unixmode = unix_mode(cnum,open_attr | aARCH); @@ -208,7 +216,14 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, &rmode,&smb_action); if (!Files[fnum].open) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { close_file(fnum); @@ -559,6 +574,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum BOOL dont_descend = False; BOOL out_of_space = False; int space_remaining; + BOOL bad_path = False; *directory = *mask = 0; @@ -586,8 +602,13 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,cnum,0); + unix_convert(directory,cnum,0,&bad_path); if(!check_name(directory,cnum)) { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(ERROR(ERRDOS,ERRbadpath)); } @@ -616,7 +637,14 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum if (dptr_num < 0) { if(dptr_num == -2) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return (UNIXERROR(ERRDOS,ERRbadpath)); + } return(ERROR(ERRDOS,ERRbadpath)); } @@ -1012,7 +1040,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, char *fname; char *p; int l,pos; - + BOOL bad_path = False; if (tran_call == TRANSACT2_QFILEINFO) { int16 fnum = SVALS(params,0); @@ -1032,9 +1060,14 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, info_level = SVAL(params,0); fname = &fname1[0]; strcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRbadpath)); } pos = 0; @@ -1212,6 +1245,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, pstring fname1; char *fname; int fd = -1; + BOOL bad_path = False; if (!CAN_WRITE(cnum)) return(ERROR(ERRSRV,ERRaccess)); @@ -1235,13 +1269,25 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, info_level = SVAL(params,0); fname = fname1; strcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0); + unix_convert(fname,cnum,0,&bad_path); if(!check_name(fname, cnum)) - return(ERROR(ERRDOS,ERRbadpath)); - + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + if(sys_stat(fname,&st)!=0) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRbadpath)); + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); } } @@ -1396,6 +1442,7 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, char *params = *pparams; pstring directory; int ret = -1; + BOOL bad_path = False; if (!CAN_WRITE(cnum)) return(ERROR(ERRSRV,ERRaccess)); @@ -1404,13 +1451,18 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,cnum,0); + unix_convert(directory,cnum,0,&bad_path); if (check_name(directory,cnum)) ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); if(ret < 0) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); } -- cgit From 41bbc5e21fbac555b26bd751dd93d09969715199 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 26 Aug 1997 01:28:27 +0000 Subject: smb.h: Added error code used for OS2 WPS. trans2.c: Added OS2 WPS fix - but ifdefed out for now. Will turn on after 1.9.17 release. Jeremy (jallison@whistle.com) (This used to be commit 9d5d347686ca1c8a25088b882dcc5065b6d9c564) --- source3/smbd/trans2.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9a48fb3ded..8052924059 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1094,13 +1094,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); -#if 0 - SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - return(-1); -#else return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); -#endif } bzero(pdata,data_size); @@ -1307,11 +1301,11 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED); - - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - - return(-1); +#ifdef OS2_WPS_FIX /* This may become the main code stream in a later release */ + return(ERROR(ERRDOS,ERRcannotopen)); +#else /* OS2_WPS_FIX */ + return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); +#endif /* OS2_WPS_FIX */ } switch (info_level) -- cgit From 38dc53828e6e9a3ba9589c722fba40a4df167d75 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 27 Aug 1997 19:27:25 +0000 Subject: doing that irritating compiler clash warning with the protos for standard_sub and standard_sub_basic. again. lkcl (This used to be commit b60ef755cf594ee9751660467709ea4f7a669a2c) --- source3/smbd/server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index aaf62fdcad..4259bda958 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3471,12 +3471,12 @@ void exit_server(char *reason) /**************************************************************************** do some standard substitutions in a string ****************************************************************************/ -void standard_sub(int cnum,char *string) +void standard_sub(int cnum,char *str) { if (VALID_CNUM(cnum)) { char *p, *s, *home; - for ( s=string ; (p=strchr(s, '%')) != NULL ; s=p ) { + for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) { switch (*(p+1)) { case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL) string_sub(p,"%H",home); @@ -3492,7 +3492,7 @@ void standard_sub(int cnum,char *string) } } } - standard_sub_basic(string); + standard_sub_basic(str); } /* -- cgit From 45f998293034f399ebf8c76ff41c8b9b55b86776 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Aug 1997 18:59:52 +0000 Subject: mangle.c: Fixed bug that caused string to run off the end of the mangled map. server.c: Changed comparison from dname to name2 - seems correct - don't know why I changed it originally. hmmmmm. trans2.c: Made lanman2 code more similar to scan_directory(). I should make the trans2 code call scan_dir as they are so similar. Jeremy(jallison@whistle.com). (This used to be commit 3909576849025ed21e5282abc892ae7582ee0275) --- source3/smbd/mangle.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 96e787b07f..a08402a85e 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -414,9 +414,9 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) while (*start) { while ((*start) && (*start != '(')) start++; - start++; /* Skip the ( */ if (!*start) continue; /* Always check for the end. */ + start++; /* Skip the ( */ end = start; /* Search for the ' ' or a ')' */ DEBUG(5,("Start of first in pair '%s'\n", start)); while ((*end) && !((*end == ' ') || (*end == ')'))) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4259bda958..93724a9861 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -397,7 +397,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) if (!name_map_mangle(name2,False,SNUM(cnum))) continue; if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, dname)) + || fname_equal(name, name2)) /* name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra) */ { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(cnum)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8052924059..28bff08843 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -329,7 +329,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l strcpy(fname,dname); - if(mask_match(fname, mask, case_sensitive, True)) + if(name_map_mangle(fname,False,SNUM(cnum)) && + mask_match(fname, mask, case_sensitive, True)) { BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); if (dont_descend && !isdots) @@ -341,7 +342,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l strcpy(pathreal,Connections[cnum].dirpath); if(needslash) strcat(pathreal,"/"); - strcat(pathreal,fname); + strcat(pathreal,dname); if (sys_stat(pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); @@ -368,13 +369,9 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l } } - - p = pdata; nameptr = p; - name_map_mangle(fname,False,SNUM(cnum)); - nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL; switch (info_level) -- cgit From d95652780ac67b41b935511cd6dbdf94b3de371e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Aug 1997 22:54:41 +0000 Subject: Oops. Reversed mangled map change made in error. Testing found this one. Jeremy (jallison@whistle.com) (This used to be commit adf98469fc3f0969676bd454cfd143f8ef03ce48) --- source3/smbd/trans2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 28bff08843..0ef7327d2e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -329,8 +329,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l strcpy(fname,dname); - if(name_map_mangle(fname,False,SNUM(cnum)) && - mask_match(fname, mask, case_sensitive, True)) + if(mask_match(fname, mask, case_sensitive, True)) { BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); if (dont_descend && !isdots) @@ -369,6 +368,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l } } + name_map_mangle(fname,False,SNUM(cnum)); + p = pdata; nameptr = p; -- cgit From f434139087ea45ed1eb578267843943b0f04c94c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 31 Aug 1997 02:18:59 +0000 Subject: fixed a bug in the printjob encoding/decoding. We weren't doing it for the print_ functions in reply.c, with the effect that you couldn't cancel print jobs from smbclient or from older dos clients. we now use a couple of utility functions printjob_encode() and printjob_decode() rather than sticking the bitops inline in each place. also fixed a bunch of places that used foo%0xFF rather than foo&0xFF Note that this isn't really me doing the commit, it can't be as I'm working on my thesis ... (This used to be commit 3556763be3acbf01c967ee9717943dd44163fb9f) --- source3/smbd/ipc.c | 25 +++++++++++-------------- source3/smbd/reply.c | 2 +- 2 files changed, 12 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e21021c0ac..55e293d7ff 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -480,7 +480,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, /* the client expects localtime */ t -= TimeDiff(t); - PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */ + PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */ if (uLevel == 1) { PACKS(desc,"B21",queue->user); /* szUserName */ PACKS(desc,"B",""); /* pad */ @@ -1405,11 +1405,10 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded - by the print queue api */ - int snum = (SVAL(p,0)>>8); + int jobid, snum; int i, count; + printjob_decode(SVAL(p,0), &snum, &jobid); /* check it's a supported varient */ if (!(strcsequal(str1,"W") && strcsequal(str2,""))) @@ -1429,7 +1428,7 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, count = get_printqueue(snum,cnum,&queue,NULL); for (i=0;i>8); + int jobid, snum; int uLevel = SVAL(p,2); int function = SVAL(p,4); /* what is this ?? */ int i; char *s = data; + + printjob_decode(SVAL(p,0), &snum, &jobid); *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); @@ -1565,7 +1564,7 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, lpq_reset(snum); count = get_printqueue(snum,cnum,&queue,NULL); for (i=0;i> 8; /*## valid serice number??*/ - job = uJobId & 0xFF; + printjob_decode(SVAL(p,0), &snum, &job); if (snum < 0 || !VALID_SNUM(snum)) return(False); count = get_printqueue(snum,cnum,&queue,&status); for (i = 0; i < count; i++) { - if ((queue[i].job % 0xFF) == job) break; + if ((queue[i].job & 0xFF) == job) break; } if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cadd63e045..4616ea14ed 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2463,7 +2463,7 @@ int reply_printqueue(char *inbuf,char *outbuf) { put_dos_date2(p,0,queue[i].time); CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3); - SSVAL(p,5,queue[i].job); + SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job)); SIVAL(p,7,queue[i].size); CVAL(p,11) = 0; StrnCpy(p+12,queue[i].user,16); -- cgit From 3fc24dc9ed330d73aedbe2017cdfa5b5657e69cc Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 31 Aug 1997 14:14:22 +0000 Subject: added word count 3 support into reply_tcon_and_X (see cifs6.txt). the only thing i couldn't do was get the chaining word count to point to the end of the smb reply, for the next and_X (not that there is one). (This used to be commit 54f11999d2113f2e88144ed63e23dd82b32e14a6) --- source3/smbd/reply.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4616ea14ed..8e304a77df 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -261,7 +261,29 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (connection_num < 0) return(connection_error(inbuf,outbuf,connection_num)); - set_message(outbuf,2,strlen(devicename)+1,True); + if (Protocol < PROTOCOL_NT1) + { + set_message(outbuf,2,strlen(devicename)+1,True); + strcpy(smb_buf(outbuf),devicename); + } + else + { + char *fsname = "NTFS"; + int devlen = strlen(devicename)+1; + int fslen = strlen(fsname)+1; + int len = devlen + fslen + 1; + + char *p; + set_message(outbuf,3,3,True); + + p = smb_buf(outbuf); + strcpy(p,devicename); p = skip_string(p,1); /* device name */ + strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ + + set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + + SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */ + } DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); @@ -269,8 +291,6 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(inbuf,smb_tid,connection_num); SSVAL(outbuf,smb_tid,connection_num); - strcpy(smb_buf(outbuf),devicename); - return chain_reply(inbuf,outbuf,length,bufsize); } -- cgit From e1e4b37ac785da3829f4326722c34a473a17ade5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Sep 1997 22:21:38 +0000 Subject: reply.c: Removed unused variables. Caught by gcc -Wall -Werror server.c: Fix for old DOS clients not understanding ERRbaddirectory - map to ERRbadpath. util.c: Fix for systems with no LOG_DAEMON facility. Jeremy (jallison@whistle.com) (This used to be commit dadb1ffb4ca5222c0b62d785cd714d65cae328e8) --- source3/smbd/reply.c | 5 +---- source3/smbd/server.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8e304a77df..58b509ecec 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -269,11 +269,8 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) else { char *fsname = "NTFS"; - int devlen = strlen(devicename)+1; - int fslen = strlen(fsname)+1; - int len = devlen + fslen + 1; - char *p; + set_message(outbuf,3,3,True); p = smb_buf(outbuf); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 93724a9861..50f3214919 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1978,6 +1978,18 @@ struct {0,0,0} }; +/* Mapping for old clients. */ + +struct +{ + int new_smb_error; + int old_smb_error; + int protocol_level; +} old_client_errmap[] = +{ + {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1}, + {0,0,0} +}; /**************************************************************************** create an error packet from errno @@ -1998,17 +2010,30 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int else { while (unix_smb_errmap[i].smbclass != 0) - { - if (unix_smb_errmap[i].unixerror == errno) + { + if (unix_smb_errmap[i].unixerror == errno) { eclass = unix_smb_errmap[i].smbclass; ecode = unix_smb_errmap[i].smbcode; break; } i++; - } + } } + /* Make sure we don't return error codes that old + clients don't understand. */ + + for(i = 0; old_client_errmap[i].new_smb_error != 0; i++) + { + if((Protocol < old_client_errmap[i].protocol_level) && + (old_client_errmap[i].new_smb_error == ecode)) + { + ecode = old_client_errmap[i].old_smb_error; + break; + } + } + return(error_packet(inbuf,outbuf,eclass,ecode,line)); } -- cgit From 82290216ad827c9f8f74ffd3aa6a37dca28174e1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 Sep 1997 20:15:40 +0000 Subject: nameannounce.c nameresp.c nameserv.c nameservreply.c proto.h : Removed broadcast and recurse parameters in the queue_netbios_pkt_wins() call - they are not needed as they should always be 'false' and 'true' respectively. Also fixed a bug with secure name registration (WINS server code). server.c: Finally fixed problem with error 267 being returned to Win95. It is needed by NT. This is a horrid fix and I would appreciate a better one :-). Jeremy (jallison@whistle.com) (This used to be commit fa1305d1894a28331ba80d9de038ebf31ba902d6) --- source3/smbd/server.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 50f3214919..a65ffdd81c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1985,9 +1985,10 @@ struct int new_smb_error; int old_smb_error; int protocol_level; + char *valid_remote_arch; } old_client_errmap[] = { - {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1}, + {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, "WinNT"}, {0,0,0} }; @@ -1996,6 +1997,7 @@ struct ****************************************************************************/ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line) { + extern fstring remote_arch; int eclass=def_class; int ecode=def_code; int i=0; @@ -2024,9 +2026,19 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int /* Make sure we don't return error codes that old clients don't understand. */ + /* JRA - unfortunately, WinNT needs some error codes + for apps to work correctly, Win95 will break if + these error codes are returned. But they both + negotiate the *same* protocol. So we need to use + the revolting 'remote_arch' string to tie break. + + There must be a better way of doing this... + */ + for(i = 0; old_client_errmap[i].new_smb_error != 0; i++) { - if((Protocol < old_client_errmap[i].protocol_level) && + if(((Protocol < old_client_errmap[i].protocol_level) || + !strcsequal( old_client_errmap[i].valid_remote_arch, remote_arch)) && (old_client_errmap[i].new_smb_error == ecode)) { ecode = old_client_errmap[i].old_smb_error; -- cgit From f5302af621d91536a72b437ae2b80f9dedb46920 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Sep 1997 20:26:07 +0000 Subject: Fixed up determination of client type for PROTOCOL_NT1. Uses client capabilities bits in session_setup_and_X to decide. Made remote_arch an enum as well as a string, for easier use. Jeremy (jallison@whistle.com) (This used to be commit 99080705a2d0adcb25e1eecbe517a2fac2779baa) --- source3/smbd/reply.c | 16 ++++++++++++++++ source3/smbd/server.c | 22 ++++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 58b509ecec..773063131a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -367,8 +367,24 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); + uint32 client_caps = IVAL(inbuf,smb_vwv11); + enum remote_arch_types ra_type = get_remote_arch(); + char *p = smb_buf(inbuf); + /* client_caps is used as final determination if client is NT or Win95. + This is needed to return the correct error codes in some + circumstances. + */ + + if(ra_type == RA_WINNT || ra_type == RA_WIN95) + { + if(client_caps & (CAP_NT_SMBS | CAP_STATUS32)) + set_remote_arch( RA_WINNT); + else + set_remote_arch( RA_WIN95); + } + if (passlen1 != 24 && passlen2 != 24) doencrypt = False; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a65ffdd81c..e2fe14b0b8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1985,10 +1985,10 @@ struct int new_smb_error; int old_smb_error; int protocol_level; - char *valid_remote_arch; + enum remote_arch_types valid_ra_type; } old_client_errmap[] = { - {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, "WinNT"}, + {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, RA_WINNT}, {0,0,0} }; @@ -1997,7 +1997,6 @@ struct ****************************************************************************/ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line) { - extern fstring remote_arch; int eclass=def_class; int ecode=def_code; int i=0; @@ -2030,7 +2029,7 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int for apps to work correctly, Win95 will break if these error codes are returned. But they both negotiate the *same* protocol. So we need to use - the revolting 'remote_arch' string to tie break. + the revolting 'remote_arch' enum to tie break. There must be a better way of doing this... */ @@ -2038,7 +2037,7 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int for(i = 0; old_client_errmap[i].new_smb_error != 0; i++) { if(((Protocol < old_client_errmap[i].protocol_level) || - !strcsequal( old_client_errmap[i].valid_remote_arch, remote_arch)) && + (old_client_errmap[i].valid_ra_type != get_remote_arch())) && (old_client_errmap[i].new_smb_error == ecode)) { ecode = old_client_errmap[i].old_smb_error; @@ -3062,7 +3061,6 @@ struct { ****************************************************************************/ static int reply_negprot(char *inbuf,char *outbuf) { - extern fstring remote_arch; int outsize = set_message(outbuf,1,0,True); int Index=0; int choice= -1; @@ -3102,22 +3100,22 @@ static int reply_negprot(char *inbuf,char *outbuf) switch ( arch ) { case ARCH_SAMBA: - strcpy(remote_arch,"Samba"); + set_remote_arch(RA_SAMBA); break; case ARCH_WFWG: - strcpy(remote_arch,"WfWg"); + set_remote_arch(RA_WFWG); break; case ARCH_WIN95: - strcpy(remote_arch,"Win95"); + set_remote_arch(RA_WIN95); break; case ARCH_WINNT: - strcpy(remote_arch,"WinNT"); + set_remote_arch(RA_WINNT); break; case ARCH_OS2: - strcpy(remote_arch,"OS2"); + set_remote_arch(RA_OS2); break; default: - strcpy(remote_arch,"UNKNOWN"); + set_remote_arch(RA_UNKNOWN); break; } -- cgit From ab68ac375ee5c175366123617887a725498efddc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Sep 1997 21:23:27 +0000 Subject: Fix from Frank Varnavas . We cannot use the same name as the client to the NT password server, as NT will drop client connections if the same client name connects twice. Instead, synthesize a name from our pid. and the remote machine name. Jeremy (jallison@whistle.com) (This used to be commit ebf9487a9a68c4d786449490627ee919622e6dbf) --- source3/smbd/password.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2740304cc4..ed79d658a6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1576,11 +1576,25 @@ BOOL server_cryptkey(char *buf) p = outbuf+len; name_mangle(desthost,p,' '); len += name_len(p); + p = outbuf+len; /* and my name */ - p = outbuf+len; - name_mangle(remote_machine,p,' '); - len += name_len(p); + /* Fix from Frank Varnavas . + We cannot use the same name as the client to + the NT password server, as NT will drop client + connections if the same client name connects + twice. Instead, synthesize a name from our pid. + and the remote machine name. + */ + { + char buf[32]; /* create name as PIDname */ + sprintf(buf,"%d", getpid()); + strncpy(&buf[strlen(buf)], remote_machine, 31 - strlen(buf)); + buf[31] = '\0'; + DEBUG(1,("negprot w/password server as %s\n",buf)); + name_mangle(buf,p,' '); + len += name_len(p); + } _smb_setlen(outbuf,len); CVAL(outbuf,0) = 0x81; -- cgit From e7e49a6e6a1e7d5b1bc64563f29e7cebd5d8e01f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 1997 21:32:32 +0000 Subject: client.c: Made sure myhostname was initialised before substitutions. status.c: Made sure myhostname was initialised before substitutions. server.c trans2.c: Moved OS/2 WPS fix. Jeremy (jallison@whistle.com) (This used to be commit 8a12b6a4f0feec712f5c4e02e21198c455b060ae) --- source3/smbd/server.c | 6 ++++++ source3/smbd/trans2.c | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e2fe14b0b8..d4407269f0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1532,7 +1532,13 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (strstr(fname,".+,;=[].")) { unix_ERR_class = ERRDOS; + /* OS/2 Workplace shell fix may be main code stream in a later release. */ +#ifdef OS2_WPS_FIX + unix_ERR_code = ERRcannotopen; +#else /* OS2_WPS_FIX */ unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; +#endif /* OS2_WPS_FIX */ + return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0ef7327d2e..19c1158658 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1299,11 +1299,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); -#ifdef OS2_WPS_FIX /* This may become the main code stream in a later release */ - return(ERROR(ERRDOS,ERRcannotopen)); -#else /* OS2_WPS_FIX */ return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); -#endif /* OS2_WPS_FIX */ } switch (info_level) -- cgit From 30416c0b8a0f54f6cc1179c2e00860eaf5f58401 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Sep 1997 20:17:32 +0000 Subject: charcnv.c client.c clitar.c kanji.c kanji.h loadparm.c mangle.c smb.h util.c: Big merge to allow KANJI support to be in the main binary without explicitly compiling with it. locking.c: Fix for smbstatus not being able to read files. namepacket.c: Removed unneccesary debug statement. trans2.c: Added Luke's proposed fix (ifdefed out until further testing). nmblookup.c: Fixed bug where query fails and status is done on bogus IP. Jeremy (jallison@whistle.com) (This used to be commit 9196255022ae8c51b527412747b324819bea2c13) --- source3/smbd/mangle.c | 205 +++++++++++++++++++++++++++----------------------- source3/smbd/trans2.c | 8 ++ 2 files changed, 117 insertions(+), 96 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index a08402a85e..3f753cf855 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -123,30 +123,34 @@ BOOL is_8_3(char *fname, BOOL check_case) { char *p = fname; -#ifdef KANJI - dot_pos = 0; - while (*p) + if(lp_client_code_page() == KANJI_CODEPAGE) + { + dot_pos = 0; + while (*p) { - if (is_shift_jis (*p)) { - p += 2; - } else if (is_kana (*p)) { - p ++; - } else { - if (*p == '.' && !dot_pos) - dot_pos = (char *) p; - if (!isdoschar(*p)) - return(False); - p++; - } - } -#else - while (*p) + if (is_shift_jis (*p)) + p += 2; + else if (is_kana (*p)) + p ++; + else + { + if (*p == '.' && !dot_pos) + dot_pos = (char *) p; + if (!isdoschar(*p)) + return(False); + p++; + } + } + } + else + { + while (*p) { - if (!isdoschar(*p)) - return(False); - p++; + if (!isdoschar(*p)) + return(False); + p++; } -#endif /* KANJI */ + } } /* no dot and less than 9 means OK */ @@ -498,84 +502,90 @@ void mangle_name_83(char *s) DEBUG(5,("Mangling name %s to ",s)); if (p) - { - if (p == s) - strcpy(extension,"___"); - else + { + if (p == s) + strcpy(extension,"___"); + else { *p++ = 0; while (*p && extlen < 3) - { -#ifdef KANJI - if (is_shift_jis (*p)) - { - if (extlen < 2) - { - extension[extlen++] = p[0]; - extension[extlen++] = p[1]; - } - else - { - extension[extlen++] = base36 (((unsigned char) *p) % 36); - } - p += 2; - } - else if (is_kana (*p)) - { - extension[extlen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') - extension[extlen++] = p[0]; - p++; - } -#else - if (isdoschar(*p) && *p != '.') - extension[extlen++] = *p; - p++; -#endif /* KANJI */ - } + { + if(lp_client_code_page() == KANJI_CODEPAGE) + { + if (is_shift_jis (*p)) + { + if (extlen < 2) + { + extension[extlen++] = p[0]; + extension[extlen++] = p[1]; + } + else + { + extension[extlen++] = base36 (((unsigned char) *p) % 36); + } + p += 2; + } + else if (is_kana (*p)) + { + extension[extlen++] = p[0]; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') + extension[extlen++] = p[0]; + p++; + } + } + else + { + if (isdoschar(*p) && *p != '.') + extension[extlen++] = *p; + p++; + } + } extension[extlen] = 0; - } } + } p = s; while (*p && baselen < 5) + { + if(lp_client_code_page() == KANJI_CODEPAGE) { -#ifdef KANJI if (is_shift_jis (*p)) - { - if (baselen < 4) - { - base[baselen++] = p[0]; - base[baselen++] = p[1]; - } - else - { + { + if (baselen < 4) + { + base[baselen++] = p[0]; + base[baselen++] = p[1]; + } + else + { base[baselen++] = base36 (((unsigned char) *p) % 36); - } - p += 2; - } + } + p += 2; + } else if (is_kana (*p)) - { - base[baselen++] = p[0]; - p++; - } + { + base[baselen++] = p[0]; + p++; + } else - { - if (isdoschar (*p) && *p != '.') - base[baselen++] = p[0]; - p++; - } -#else + { + if (isdoschar (*p) && *p != '.') + base[baselen++] = p[0]; + p++; + } + } + else + { if (isdoschar(*p) && *p != '.') - base[baselen++] = *p; + base[baselen++] = *p; p++; -#endif /* KANJI */ } + } base[baselen] = 0; csum = csum % (36*36); @@ -601,7 +611,8 @@ static BOOL illegal_name(char *name) static BOOL initialised=False; unsigned char *s; - if (!initialised) { + if (!initialised) + { char *ill = "*\\/?<>|\":{}"; initialised = True; @@ -610,21 +621,23 @@ static BOOL illegal_name(char *name) illegal[*s] = True; } -#ifdef KANJI - for (s = (unsigned char *)name; *s;) { - if (is_shift_jis (*s)) { - s += 2; - } else if (illegal[*s]) { - return(True); - } else { - s++; + if(lp_client_code_page() == KANJI_CODEPAGE) + { + for (s = (unsigned char *)name; *s;) { + if (is_shift_jis (*s)) { + s += 2; + } else if (illegal[*s]) { + return(True); + } else { + s++; + } } } -#else - for (s = (unsigned char *)name;*s;s++) - if (illegal[*s]) return(True); -#endif - + else + { + for (s = (unsigned char *)name;*s;s++) + if (illegal[*s]) return(True); + } return(False); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 19c1158658..c8e726d36e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1347,6 +1347,14 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, tvs.modtime=MAX(interpret_long_date(pdata+16), interpret_long_date(pdata+24)); +#if 0 /* Needs more testing... */ + /* Test from Luke to prevent Win95 from + setting incorrect values here. + */ + if (tvs.actime < tvs.modtime) + return(ERROR(ERRDOS,ERRnoaccess)); +#endif /* Needs more testing... */ + /* attributes */ mode = IVAL(pdata,32); break; -- cgit From 34695928331e74a44389815cab941a3e673c84ee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Sep 1997 16:29:36 +0000 Subject: Added fix that means if connecting user sends guest account with no password they are seen as guest. Previous patch broke this. Jeremy (jallison@whistle.com) (This used to be commit 9a55c49626f65627b26417795891260bb2afcc27) --- source3/smbd/reply.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 773063131a..228d8ad669 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -268,7 +268,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { - char *fsname = "NTFS"; + char *fsname = "SAMBA"; char *p; set_message(outbuf,3,3,True); @@ -459,6 +459,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) add_session_user(user); + /* Check if the given username was the guest user with no password. + We need to do this check after add_session_user() as that + call can potentially change the username (via map_user). + */ + + if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) + guest = True; if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) && !check_hosts_equiv(user)) -- cgit From 33a003de4056532be0c9a199d4857b9da1b18034 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 14 Sep 1997 16:37:18 +0000 Subject: This commit does 3 main things: 1) put the encryption code in by default, with no #ifdef. It is still disabled by default so you need to add "encrypt passwords = yes" in smb.conf but at least all binaries will have it. 2) cleanup the kanji code so it compiles with no warnings 3) get rid of lots of uses of ugly non-portable C code. The main offender being things like "register" but also remove uses of the "const" keyword as there are compilers out there that don't support it and even those that do often complain about its usage. Users don't like warnings :-( There is still some work to do. We need to replace the md4 code with our own implementation. The current code (from rfc1186) is PD but is not very portable. The new RFC (rfc1320) is more portable but adds copyright restrictions. I'll do a from-scratch MD4 soon. We also need to test that what I've implemented is portable. It should be, but I'm too tired right now to test it on anything other than intel linux. (This used to be commit db917c62c14315afe6f0745a8097c1bca25cbf07) --- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 31 +++++++++---------------------- source3/smbd/server.c | 12 ------------ 3 files changed, 10 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 55e293d7ff..794bc7bb8e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -440,7 +440,7 @@ static void PackDriverData(struct pack_desc* desc) } static int check_printq_info(struct pack_desc* desc, - int uLevel, char *id1, const char* id2) + int uLevel, char *id1, char *id2) { desc->subformat = NULL; switch( uLevel ) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ed79d658a6..abecb46dcd 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -36,7 +36,6 @@ static char this_user[100]=""; static char this_salt[100]=""; static char this_crypted[100]=""; -#ifdef SMB_PASSWD /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; static BOOL challenge_sent=False; @@ -78,7 +77,6 @@ BOOL last_challenge(char *challenge) memcpy(challenge,saved_challenge,8); return(True); } -#endif /* this holds info on user ids that are already validated for this VC */ static user_struct *validated_users = NULL; @@ -401,7 +399,7 @@ static char *PAM_password; * echo off means password. */ static int PAM_conv (int num_msg, - const struct pam_message **msg, + struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int count = 0, replies = 0; @@ -812,7 +810,6 @@ Hence we make a direct return to avoid a second chance!!! #endif } -#ifdef SMB_PASSWD /**************************************************************************** core of smb password checking routine. ****************************************************************************/ @@ -854,7 +851,6 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha #endif return (memcmp(p24, password, 24) == 0); } -#endif /**************************************************************************** check if a username/password is OK @@ -864,21 +860,16 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) pstring pass2; int level = lp_passwordlevel(); struct passwd *pass; -#ifdef SMB_PASSWD char challenge[8]; struct smb_passwd *smb_pass; BOOL challenge_done = False; -#endif if (password) password[pwlen] = 0; -#ifdef SMB_PASSWD if (pwlen == 24) challenge_done = last_challenge(challenge); -#endif #if DEBUG_PASSWORD -#ifdef SMB_PASSWD if (challenge_done) { int i; @@ -886,10 +877,9 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) for( i = 0; i < 24; i++) DEBUG(100,("%0x ", (unsigned char)password[i])); DEBUG(100,("]\n")); + } else { + DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); } - else -#endif - DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); #endif if (!password) @@ -906,8 +896,6 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) else pass = Get_Pwnam(user,True); -#ifdef SMB_PASSWD - DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); if((pwlen == 24) && challenge_done) @@ -964,7 +952,6 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) DEBUG(3,("Error smb_password_check failed\n")); } -#endif DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); @@ -1587,12 +1574,12 @@ BOOL server_cryptkey(char *buf) and the remote machine name. */ { - char buf[32]; /* create name as PIDname */ - sprintf(buf,"%d", getpid()); - strncpy(&buf[strlen(buf)], remote_machine, 31 - strlen(buf)); - buf[31] = '\0'; - DEBUG(1,("negprot w/password server as %s\n",buf)); - name_mangle(buf,p,' '); + char buf2[32]; /* create name as PIDname */ + sprintf(buf2,"%d", getpid()); + strncpy(&buf2[strlen(buf2)], remote_machine, 31 - strlen(buf2)); + buf2[31] = '\0'; + DEBUG(1,("negprot w/password server as %s\n",buf2)); + name_mangle(buf2,p,' '); len += name_len(p); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d4407269f0..8560d5239d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2814,19 +2814,15 @@ int reply_lanman1(char *outbuf) set_message(outbuf,13,doencrypt?8:0,True); SSVAL(outbuf,smb_vwv1,secword); -#ifdef SMB_PASSWD /* Create a token value and add it to the outgoing packet. */ if (doencrypt) generate_next_challenge(smb_buf(outbuf)); -#endif Protocol = PROTOCOL_LANMAN1; if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { DEBUG(3,("using password server validation\n")); -#ifdef SMB_PASSWD if (doencrypt) set_challenge(smb_buf(outbuf)); -#endif } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ @@ -2865,11 +2861,9 @@ int reply_lanman2(char *outbuf) set_message(outbuf,13,doencrypt?8:0,True); SSVAL(outbuf,smb_vwv1,secword); -#ifdef SMB_PASSWD /* Create a token value and add it to the outgoing packet. */ if (doencrypt) generate_next_challenge(smb_buf(outbuf)); -#endif SIVAL(outbuf,smb_vwv6,getpid()); @@ -2877,9 +2871,7 @@ int reply_lanman2(char *outbuf) if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { DEBUG(3,("using password server validation\n")); -#ifdef SMB_PASSWD if (doencrypt) set_challenge(smb_buf(outbuf)); -#endif } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ @@ -2949,7 +2941,6 @@ int reply_nt1(char *outbuf) #endif CVAL(outbuf,smb_vwv1) = secword; -#ifdef SMB_PASSWD /* Create a token value and add it to the outgoing packet. */ if (doencrypt) { @@ -2958,15 +2949,12 @@ int reply_nt1(char *outbuf) /* Tell the nt machine how long the challenge is. */ SSVALS(outbuf,smb_vwv16+1,challenge_len); } -#endif Protocol = PROTOCOL_NT1; if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { DEBUG(3,("using password server validation\n")); -#ifdef SMB_PASSWD if (doencrypt) set_challenge(smb_buf(outbuf)); -#endif } SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ -- cgit From 57c2578cb2b7e02acc6c04d07adc11a77c40aa9c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Sep 1997 04:41:16 +0000 Subject: - change generate_challenge() to use md4 instead of des - move routines about a bit between smbencrypt.c and smbdes.c. Ensure that there is no entry point for normal DES operation - add the following comment: This code is NOT a complete DES implementation. It implements only the minimum necessary for SMB authentication, as used by all SMB products (including every copy of Microsoft Windows95 ever sold) In particular, it can only do a unchained forward DES pass. This means it is not possible to use this code for encryption/decryption of data, instead it is only useful as a "hash" algorithm. There is no entry point into this code that allows normal DES operation. I believe this means that this code does not come under ITAR regulations but this is NOT a legal opinion. If you are concerned about the applicability of ITAR regulations to this code then you should confirm it for yourself (and maybe let me know if you come up with a different answer to the one above) (This used to be commit 35b92e725f351c9a9f2846a6b55f71c234f187c7) --- source3/smbd/password.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index abecb46dcd..7b581d1289 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -45,17 +45,24 @@ Get the next challenge value - no repeats. ********************************************************************/ void generate_next_challenge(char *challenge) { - static int counter = 0; - struct timeval tval; - int v1,v2; - GetTimeOfDay(&tval); - v1 = (counter++) + getpid() + tval.tv_sec; - v2 = (counter++) * getpid() + tval.tv_usec; - SIVAL(challenge,0,v1); - SIVAL(challenge,4,v2); - E1((uchar *)challenge,(uchar *)"SAMBA",(uchar *)saved_challenge); - memcpy(challenge,saved_challenge,8); - challenge_sent = True; + unsigned char buf[16]; + static int counter = 0; + struct timeval tval; + int v1,v2; + + /* get a sort-of random number */ + GetTimeOfDay(&tval); + v1 = (counter++) + getpid() + tval.tv_sec; + v2 = (counter++) * getpid() + tval.tv_usec; + SIVAL(challenge,0,v1); + SIVAL(challenge,4,v2); + + /* mash it up with md4 */ + mdfour(buf, challenge, 8); + + memcpy(saved_challenge, buf, 8); + memcpy(challenge,buf,8); + challenge_sent = True; } /******************************************************************* -- cgit From cda707f9176c2bb433b5cc4968a9617005f8dc00 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Sep 1997 08:26:33 +0000 Subject: add a cast (This used to be commit e712c6ed61abeae5ec2acf99f109ad81e7a19978) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 7b581d1289..35f73eab2d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -58,7 +58,7 @@ void generate_next_challenge(char *challenge) SIVAL(challenge,4,v2); /* mash it up with md4 */ - mdfour(buf, challenge, 8); + mdfour(buf, (unsigned char *)challenge, 8); memcpy(saved_challenge, buf, 8); memcpy(challenge,buf,8); -- cgit From 1590983eb0849130962cb0a08198cf8ad3d49380 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Sep 1997 01:29:53 +0000 Subject: Added 'delete veto files' paremeter. Ugly - but the only way to allow Samba client users to delete directories containing Mac metafile information (.AppleDouble directories). Needed for clean integration with netatalk. Jeremy (jallison@whistle.com) (This used to be commit 29c6c037dc62e44784e9d127d1e7ef3dd1506733) --- source3/smbd/reply.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 228d8ad669..cb0e5d7628 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2594,6 +2594,66 @@ int reply_mkdir(char *inbuf,char *outbuf) return(outsize); } +/**************************************************************************** +Static function used by reply_rmdir to delete an entire directory +tree recursively. +****************************************************************************/ +static BOOL recursive_rmdir(char *directory) +{ + char *dname = NULL; + BOOL ret = False; + void *dirptr = OpenDir(-1, directory, False); + + if(dirptr == NULL) + return True; + + while((dname = ReadDirName(dirptr))) + { + pstring fullname; + struct stat st; + + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + + /* Construct the full name. */ + if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) + { + errno = ENOMEM; + ret = True; + break; + } + strcpy(fullname, directory); + strcat(fullname, "/"); + strcat(fullname, dname); + + if(sys_lstat(fullname, &st) != 0) + { + ret = True; + break; + } + + if(st.st_mode & S_IFDIR) + { + if(recursive_rmdir(fullname)!=0) + { + ret = True; + break; + } + if(sys_rmdir(fullname) != 0) + { + ret = True; + break; + } + } + else if(sys_unlink(fullname) != 0) + { + ret = True; + break; + } + } + CloseDir(dirptr); + return ret; +} /**************************************************************************** reply to a rmdir @@ -2662,10 +2722,15 @@ int reply_rmdir(char *inbuf,char *outbuf) if(sys_lstat(fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) + { + if(lp_recursive_veto_delete(SNUM(cnum))) { - if(sys_rmdir(fullname) != 0) + if(recursive_rmdir(fullname) != 0) break; } + if(sys_rmdir(fullname) != 0) + break; + } else if(sys_unlink(fullname) != 0) break; } -- cgit From a8064b0f00f78d04d7e1969ebfbd01fbc55943c6 Mon Sep 17 00:00:00 2001 From: John Terpstra Date: Wed, 17 Sep 1997 13:53:59 +0000 Subject: JHT ===> Changed behaviour of logon script processing so that all macros can be used in the logon script parameter definition in the smb.conf Globals section. This fixes a problem reported by Jacco de Leeuw where OS/2 does not see the %u variable. Jacco suggested using %U but we really do want the user for the netlogon share session. If this does not do the trick - well we eat our hat! Yeh! (This used to be commit a7716b2e70606e447094509116455ea53fe8bf64) --- source3/smbd/ipc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 794bc7bb8e..ced3a2009d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2219,6 +2219,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, int uLevel; struct pack_desc desc; char* name; + char* logon_script; uLevel = SVAL(p,0); name = p + 2; @@ -2261,7 +2262,14 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, PACKS(&desc,"z",mypath); /* computer */ } PACKS(&desc,"z",myworkgroup);/* domain */ - PACKS(&desc,"z",lp_logon_script()); /* script path */ + +/* JHT - By calling lp_logon_script() and standard_sub() we have */ +/* made sure all macros are fully substituted and available */ + logon_script = lp_logon_script(); + standard_sub( cnum, logon_script ); + PACKS(&desc,"z", logon_script); /* script path */ +/* End of JHT mods */ + PACKI(&desc,"D",0x00000000); /* reserved */ } -- cgit From 570a5becfcf1202d1277af8b149d50ca70315b74 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Sep 1997 07:05:43 +0000 Subject: added some debug stuff (This used to be commit 95184fd1ecdf5eea9c42d748db848210b7e863d3) --- source3/smbd/reply.c | 115 ++++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cb0e5d7628..09c4e29416 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -53,58 +53,71 @@ a packet to ensure chaining works correctly */ ****************************************************************************/ int reply_special(char *inbuf,char *outbuf) { - int outsize = 4; - int msg_type = CVAL(inbuf,0); - int msg_flags = CVAL(inbuf,1); - pstring name1,name2; - extern fstring remote_machine; - extern fstring local_machine; - char *p; - - *name1 = *name2 = 0; - - smb_setlen(outbuf,0); - - switch (msg_type) - { - case 0x81: /* session request */ - CVAL(outbuf,0) = 0x82; - CVAL(outbuf,3) = 0; - if (name_len(inbuf+4) > 50) - { - DEBUG(0,("Invalid name length in session request\n")); - return(0); + int outsize = 4; + int msg_type = CVAL(inbuf,0); + int msg_flags = CVAL(inbuf,1); + pstring name1,name2; + extern fstring remote_machine; + extern fstring local_machine; + char *p; + + *name1 = *name2 = 0; + + smb_setlen(outbuf,0); + + switch (msg_type) { + case 0x81: /* session request */ + CVAL(outbuf,0) = 0x82; + CVAL(outbuf,3) = 0; + if (name_len(inbuf+4) > 50) { + DEBUG(0,("Invalid name length in session request\n")); + return(0); + } + name_extract(inbuf,4,name1); + name_extract(inbuf,4 + name_len(inbuf + 4),name2); + DEBUG(2,("netbios connect: name1=%s name2=%s\n", + name1,name2)); + + strcpy(remote_machine,name2); + trim_string(remote_machine," "," "); + p = strchr(remote_machine,' '); + strlower(remote_machine); + if (p) *p = 0; + + strcpy(local_machine,name1); + trim_string(local_machine," "," "); + p = strchr(local_machine,' '); + strlower(local_machine); + if (p) *p = 0; + + add_session_user(remote_machine); + + reload_services(True); + reopen_logs(); + + break; + + case 0x89: /* session keepalive request + (some old clients produce this?) */ + CVAL(outbuf,0) = 0x85; + CVAL(outbuf,3) = 0; + break; + + case 0x82: /* positive session response */ + case 0x83: /* negative session response */ + case 0x84: /* retarget session response */ + DEBUG(0,("Unexpected session response\n")); + break; + + case 0x85: /* session keepalive */ + default: + return(0); } - name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); - DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2)); - - strcpy(remote_machine,name2); - trim_string(remote_machine," "," "); - p = strchr(remote_machine,' '); - strlower(remote_machine); - if (p) *p = 0; - - strcpy(local_machine,name1); - trim_string(local_machine," "," "); - p = strchr(local_machine,' '); - strlower(local_machine); - if (p) *p = 0; - - add_session_user(remote_machine); - - reload_services(True); - reopen_logs(); - - break; - case 0x85: /* session keepalive */ - default: - return(0); - } - - DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags)); - - return(outsize); + + DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n", + timestring(),msg_type,msg_flags)); + + return(outsize); } -- cgit From 81eb442e88e8231b8e9c556c1ee393e99269af78 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Sep 1997 19:19:06 +0000 Subject: Checkin to sync up oplock development code so that NT domain development code won't diverge. Makefile: Fixed make proto (again). Added GLIBC2 fixes for Linux. includes.h: Added GLIBC2 fixes for Linux. proto.h: Much tidier. quotas.c: OSF/1 quota fix. reply.c: Fix from Ray Frush for zero NT timestamps. server.c util.c: First oplock checkin - nowhere near finished so bracketed with #ifdef USE_OPLOCKS. Done to make sync with NT domain code easier. Jeremy (jallison@whistle.com) (This used to be commit 7dce7d84473beb5663b14a8ab32781970819c19d) --- source3/smbd/quotas.c | 20 +++- source3/smbd/reply.c | 22 ++++- source3/smbd/server.c | 268 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 219 insertions(+), 91 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index d19d386e27..d4f746c9e3 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -373,22 +373,34 @@ try to get the disk space from disk quotas - OFS1 version BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { uid_t user_id, euser_id; - int r; + int r, save_errno; struct dqblk D; struct stat S; euser_id = geteuid(); user_id = getuid(); - setreuid(euser_id, euser_id); + setreuid(euser_id, -1); r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D); - if (setreuid(user_id, euser_id) == -1) + if (r) + save_errno = errno; + + if (setreuid(user_id, -1) == -1) DEBUG(5,("Unable to reset uid to %d\n", user_id)); *bsize = DEV_BSIZE; if (r) - return(False); + { + if (save_errno == EDQUOT) // disk quota exceeded + { + *dfree = 0; + *dsize = D.dqb_curblocks; + return (True); + } + else + return (False); + } /* Use softlimit to determine disk space, except when it has been exceeded */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 09c4e29416..8117685637 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3610,11 +3610,31 @@ int reply_setattrE(char *inbuf,char *outbuf) unix_times.actime = make_unix_date2(inbuf+smb_vwv3); unix_times.modtime = make_unix_date2(inbuf+smb_vwv5); + /* + * Patch from Ray Frush + * Sometimes times are sent as zero - ignore them. + */ + + if ((unix_times.actime == 0) && (unix_times.modtime == 0)) + { + /* Ignore request */ + DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \ +not setting timestamps of 0\n", + timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); + return(outsize); + } + else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) + { + /* set modify time = to access time if modify time was 0 */ + unix_times.modtime = unix_times.actime; + } + /* Set the date on this file */ if(sys_utime(Files[fnum].name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum)); + DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", + timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); return(outsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8560d5239d..110d31b302 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -84,6 +84,12 @@ int chain_fnum = -1; /* number of open connections */ static int num_connections_open = 0; +#ifdef USE_OPLOCKS +/* Oplock ipc UDP socket. */ +int oplock_sock = -1; +int oplock_port = -1; +#endif /* USE_OPLOCKS */ + extern fstring remote_machine; pstring OriginalDir; @@ -2257,6 +2263,64 @@ static BOOL open_sockets(BOOL is_daemon,int port) return True; } +#ifdef USE_OPLOCKS +/**************************************************************************** + open the oplock IPC socket communication +****************************************************************************/ +static BOOL open_oplock_ipc() +{ + struct sockaddr_in sock_name; + int name_len = sizeof(sock_name); + + DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); + + /* Open a lookback UDP socket on a random port. */ + oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0,interpret_addr("127.0.0.1")); + if (oplock_sock == -1) + return(False); + + /* Find out the transient UDP port we have been allocated. */ + if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &name_len)<0) + { + DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", + strerror(errno))); + close(oplock_sock); + oplock_sock = -1; + return False; + } + oplock_port = ntohs(sock_name.sin_port); + + return True; +} + +/**************************************************************************** + process an oplock break message. +****************************************************************************/ +static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) +{ + int32 msg_len; + int16 port; + struct in_addr from; + char *msg_start; + + msg_len = IVAL(buffer,0); + port = SVAL(buffer,4); + memcpy((char *)&from, &buffer[6], sizeof(struct in_addr)); + + msg_start = &buffer[6 + sizeof(struct in_addr)]; + + /* Validate message length. */ + if(msg_len > (buf_size - (6 + sizeof(struct in_addr)))) + { + DEBUG(0,("process_local_message: invalid msg_len (%d) max can be %d\n", + msg_len, buf_size - (6 + sizeof(struct in_addr)))); + return False; + } + + /* Validate message from address (must be localhost). */ + return True; +} +#endif /* USE_OPLOCKS */ /**************************************************************************** check if a snum is in use @@ -3960,32 +4024,40 @@ static void process(void) #endif while (True) + { + int32 len; + int msg_type; + int msg_flags; + int type; + int deadtime = lp_deadtime()*60; + int counter; + int last_keepalive=0; + int service_load_counter = 0; +#ifdef USE_OPLOCKS + BOOL got_smb = False; +#endif /* USE_OPLOCKS */ + + if (deadtime <= 0) + deadtime = DEFAULT_SMBD_TIMEOUT; + + if (lp_readprediction()) + do_read_prediction(); + + errno = 0; + + for (counter=SMBD_SELECT_LOOP; +#ifdef USE_OPLOCKS + !receive_message_or_smb(Client,oplock_sock, + InBuffer,SMBD_SELECT_LOOP*1000,&got_smb); +#else /* USE_OPLOCKS */ + !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); +#endif /* USE_OPLOCKS */ + counter += SMBD_SELECT_LOOP) { - int32 len; - int msg_type; - int msg_flags; - int type; - int deadtime = lp_deadtime()*60; - int counter; - int last_keepalive=0; - int service_load_counter = 0; - - if (deadtime <= 0) - deadtime = DEFAULT_SMBD_TIMEOUT; - - if (lp_readprediction()) - do_read_prediction(); - - errno = 0; - - for (counter=SMBD_SELECT_LOOP; - !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); - counter += SMBD_SELECT_LOOP) - { - int i; - time_t t; - BOOL allidle = True; - extern int keepalive; + int i; + time_t t; + BOOL allidle = True; + extern int keepalive; if (counter > 365 * 3600) /* big number of seconds. */ { @@ -3993,69 +4065,79 @@ static void process(void) service_load_counter = 0; } - if (smb_read_error == READ_EOF) { - DEBUG(3,("end of file from client\n")); - return; - } + if (smb_read_error == READ_EOF) + { + DEBUG(3,("end of file from client\n")); + return; + } - if (smb_read_error == READ_ERROR) { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return; - } + if (smb_read_error == READ_ERROR) + { + DEBUG(3,("receive_smb error (%s) exiting\n", + strerror(errno))); + return; + } - t = time(NULL); + t = time(NULL); - /* become root again if waiting */ - unbecome_user(); + /* become root again if waiting */ + unbecome_user(); - /* check for smb.conf reload */ - if (counter >= service_load_counter + SMBD_RELOAD_CHECK) + /* check for smb.conf reload */ + if (counter >= service_load_counter + SMBD_RELOAD_CHECK) { service_load_counter = counter; /* reload services, if files have changed. */ - reload_services(True); + reload_services(True); } - /* automatic timeout if all connections are closed */ - if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) { - DEBUG(2,("%s Closing idle connection\n",timestring())); - return; - } + /* automatic timeout if all connections are closed */ + if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) + { + DEBUG(2,("%s Closing idle connection\n",timestring())); + return; + } - if (keepalive && (counter-last_keepalive)>keepalive) { - extern int password_client; - if (!send_keepalive(Client)) { - DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); - return; - } - /* also send a keepalive to the password server if its still - connected */ - if (password_client != -1) - send_keepalive(password_client); - last_keepalive = counter; - } + if (keepalive && (counter-last_keepalive)>keepalive) + { + extern int password_client; + if (!send_keepalive(Client)) + { + DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); + return; + } + /* also send a keepalive to the password server if its still + connected */ + if (password_client != -1) + send_keepalive(password_client); + last_keepalive = counter; + } - /* check for connection timeouts */ - for (i=0;iDPTR_IDLE_TIMEOUT) - dptr_idlecnum(i); - - if (Connections[i].num_files_open > 0 || - (t-Connections[i].lastused)0) { - DEBUG(2,("%s Closing idle connection 2\n",timestring())); - return; - } - } + /* check for connection timeouts */ + for (i=0;iDPTR_IDLE_TIMEOUT) + dptr_idlecnum(i); + + if (Connections[i].num_files_open > 0 || + (t-Connections[i].lastused)0) + { + DEBUG(2,("%s Closing idle connection 2\n",timestring())); + return; + } + } +#ifdef USE_OPLOCKS + if(got_smb) + { +#endif /* USE_OPLOCKS */ msg_type = CVAL(InBuffer,0); msg_flags = CVAL(InBuffer,1); type = CVAL(InBuffer,smb_com); @@ -4069,7 +4151,8 @@ static void process(void) DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); #ifdef WITH_VTP - if(trans_num == 1 && VT_Check(InBuffer)) { + if(trans_num == 1 && VT_Check(InBuffer)) + { VT_Process(); return; } @@ -4077,25 +4160,32 @@ static void process(void) if (msg_type == 0) - show_msg(InBuffer); + show_msg(InBuffer); nread = construct_reply(InBuffer,OutBuffer,nread,max_send); - if(nread > 0) { + if(nread > 0) + { if (CVAL(OutBuffer,0) == 0) - show_msg(OutBuffer); + show_msg(OutBuffer); if (nread != smb_len(OutBuffer) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, - smb_len(OutBuffer))); - } - else - send_smb(Client,OutBuffer); + { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(OutBuffer))); + } + else + send_smb(Client,OutBuffer); } trans_num++; +#ifdef USE_OPLOCKS + } + else + { + process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); } +#endif /* USE_OPLOCKS */ + } } @@ -4374,6 +4464,12 @@ static void usage(char *pname) DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); } +#ifdef USE_OPLOCKS + /* Setup the oplock IPC socket. */ + if(!open_oplock_ipc()) + exit(1); +#endif /* USE_OPLOCKS */ + process(); close_sockets(); -- cgit From 6dd6b1383c0ed10c0897dea44f247befc15b03cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 Sep 1997 00:25:44 +0000 Subject: Makefile: Removed earlier errors. includes.h: Added INADDR_LOOPBACK define. locking.c: More code to support oplocks. proto.h: Updated. server.c: More code to support oplocks. Moved processing of an SMB out of process() into a separate function so it is easier to call from an oplock break. smb.h: Added oplock fields. Jeremy (jallison@whistle.com) (This used to be commit f46dbaf08eb8e06a7545d2c19dce9e2dda9dcc78) --- source3/smbd/server.c | 123 ++++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 58 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 110d31b302..3b24ba5ce9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -87,7 +87,7 @@ static int num_connections_open = 0; #ifdef USE_OPLOCKS /* Oplock ipc UDP socket. */ int oplock_sock = -1; -int oplock_port = -1; +uint16 oplock_port = 0; #endif /* USE_OPLOCKS */ extern fstring remote_machine; @@ -1720,7 +1720,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, file (which expects the share_mode_entry to be there). */ if (lp_share_modes(SNUM(cnum))) - set_share_mode(token, fnum); + set_share_mode(token, fnum, 0); if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fnum,cnum,token,&share_locked); @@ -2275,9 +2275,13 @@ static BOOL open_oplock_ipc() DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0,interpret_addr("127.0.0.1")); + oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK)); if (oplock_sock == -1) + { + DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ +address %x. Error was %s\n", INADDR_LOOPBACK, strerror(errno))); return(False); + } /* Find out the transient UDP port we have been allocated. */ if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &name_len)<0) @@ -2299,13 +2303,13 @@ static BOOL open_oplock_ipc() static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) { int32 msg_len; - int16 port; - struct in_addr from; + int16 from_port; + struct in_addr from_addr; char *msg_start; msg_len = IVAL(buffer,0); - port = SVAL(buffer,4); - memcpy((char *)&from, &buffer[6], sizeof(struct in_addr)); + from_port = SVAL(buffer,4); + memcpy((char *)&from_addr, &buffer[6], sizeof(struct in_addr)); msg_start = &buffer[6 + sizeof(struct in_addr)]; @@ -2318,6 +2322,13 @@ static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) } /* Validate message from address (must be localhost). */ + if(from_addr.s_addr != htonl(INADDR_LOOPBACK)) + { + DEBUG(0,("process_local_message: invalid from address \ +(was %x should be 127.0.0.1\n", from_addr.s_addr)); + return False; + } + return True; } #endif /* USE_OPLOCKS */ @@ -3994,14 +4005,57 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) return(outsize); } +/**************************************************************************** + process an smb from the client - split out from the process() code so + it can be used by the oplock break code. +****************************************************************************/ + +static void process_smb(char *InBuffer, char *OutBuffer) +{ + extern int Client; + static int trans_num = 0; + + int msg_type = CVAL(InBuffer,0); + int32 len = smb_len(InBuffer); + int nread = len + 4; + + DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); + DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + +#ifdef WITH_VTP + if(trans_num == 1 && VT_Check(InBuffer)) + { + VT_Process(); + return; + } +#endif + + if (msg_type == 0) + show_msg(InBuffer); + + nread = construct_reply(InBuffer,OutBuffer,nread,max_send); + + if(nread > 0) + { + if (CVAL(OutBuffer,0) == 0) + show_msg(OutBuffer); + + if (nread != smb_len(OutBuffer) + 4) + { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(OutBuffer))); + } + else + send_smb(Client,OutBuffer); + } + trans_num++; +} /**************************************************************************** process commands from the client ****************************************************************************/ static void process(void) { - static int trans_num = 0; - int nread; extern int Client; InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); @@ -4025,10 +4079,6 @@ static void process(void) while (True) { - int32 len; - int msg_type; - int msg_flags; - int type; int deadtime = lp_deadtime()*60; int counter; int last_keepalive=0; @@ -4048,7 +4098,7 @@ static void process(void) for (counter=SMBD_SELECT_LOOP; #ifdef USE_OPLOCKS !receive_message_or_smb(Client,oplock_sock, - InBuffer,SMBD_SELECT_LOOP*1000,&got_smb); + InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); #else /* USE_OPLOCKS */ !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); #endif /* USE_OPLOCKS */ @@ -4136,54 +4186,11 @@ static void process(void) #ifdef USE_OPLOCKS if(got_smb) - { #endif /* USE_OPLOCKS */ - msg_type = CVAL(InBuffer,0); - msg_flags = CVAL(InBuffer,1); - type = CVAL(InBuffer,smb_com); - - len = smb_len(InBuffer); - - DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); - - nread = len + 4; - - DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); - -#ifdef WITH_VTP - if(trans_num == 1 && VT_Check(InBuffer)) - { - VT_Process(); - return; - } -#endif - - - if (msg_type == 0) - show_msg(InBuffer); - - nread = construct_reply(InBuffer,OutBuffer,nread,max_send); - - if(nread > 0) - { - if (CVAL(OutBuffer,0) == 0) - show_msg(OutBuffer); - - if (nread != smb_len(OutBuffer) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(OutBuffer))); - } - else - send_smb(Client,OutBuffer); - } - trans_num++; + process_smb(InBuffer, OutBuffer); #ifdef USE_OPLOCKS - } else - { process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); - } #endif /* USE_OPLOCKS */ } } -- cgit From cef59090bb2fd3f8a9efd1a453cb90264b891d58 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 1997 18:55:29 +0000 Subject: Adding Andrews buffer overflow fixes into the main branch. Jeremy (jallison@whistle.com) (This used to be commit e7eb1f044d3101679dc7a118820ea5efe0cd837c) --- source3/smbd/chgpasswd.c | 12 ++-- source3/smbd/dir.c | 2 +- source3/smbd/ipc.c | 29 +++++--- source3/smbd/mangle.c | 8 +-- source3/smbd/message.c | 14 ++-- source3/smbd/pipes.c | 4 +- source3/smbd/reply.c | 175 +++++++++++++++++++++++++++-------------------- source3/smbd/server.c | 36 +++++----- source3/smbd/trans2.c | 28 +++++--- source3/smbd/vt_mode.c | 12 ++-- 10 files changed, 181 insertions(+), 139 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 6063f2aac8..bed81138b2 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -212,8 +212,8 @@ static int expect(int master,char *expected,char *buf) { pstring s1,s2; - strcpy(s1,buf); - strcpy(s2,expected); + pstrcpy(s1,buf); + pstrcpy(s2,expected); if (do_match(s1, s2, False)) return(True); } @@ -364,11 +364,11 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass) } #if (defined(PASSWD_PROGRAM) && defined(PASSWD_CHAT)) - strcpy(passwordprogram,PASSWD_PROGRAM); - strcpy(chatsequence,PASSWD_CHAT); + pstrcpy(passwordprogram,PASSWD_PROGRAM); + pstrcpy(chatsequence,PASSWD_CHAT); #else - strcpy(passwordprogram,lp_passwd_program()); - strcpy(chatsequence,lp_passwd_chat()); + pstrcpy(passwordprogram,lp_passwd_program()); + pstrcpy(chatsequence,lp_passwd_chat()); #endif if (!*chatsequence) { diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 06ee6ae8ed..567bc14424 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -461,7 +461,7 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo matched = False; - strcpy(filename,dname); + pstrcpy(filename,dname); if ((strcmp(filename,mask) == 0) || (name_map_mangle(filename,True,SNUM(cnum)) && diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ced3a2009d..b9355c4ec0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -774,7 +774,7 @@ static int get_server_info(uint32 servertype, pstring line; BOOL local_list_only; - strcpy(fname,lp_lockdir()); + pstrcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); strcat(fname,"/"); strcat(fname,SERVER_LIST); @@ -1363,7 +1363,7 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, fstring user; fstring pass1,pass2; - strcpy(user,p); + fstrcpy(user,p); p = skip_string(p,1); @@ -1698,14 +1698,14 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, pstring comment; uint32 servertype= lp_default_server_announce(); - strcpy(comment,lp_serverstring()); + pstrcpy(comment,lp_serverstring()); if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) { for (i=0;i 0) { @@ -2043,9 +2043,9 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, strcpy(p2,"UserComment"); p2 = skip_string(p2,1); - /* EEK! the cifsrap.txt doesn't have this in!!!! */ + /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,vuser->real_name); /* simeon */ p2 = skip_string(p2,1); } @@ -2062,7 +2062,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, else { #if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); + strcpy(p2, vuser->home_share); #else strcpy(p2,"\\\\%L\\%U"); #endif @@ -2469,7 +2469,8 @@ static void fill_printdest_info(int cnum, int snum, int uLevel, struct pack_desc* desc) { char buf[100]; - strcpy(buf,SERVICE(snum)); + strncpy(buf,SERVICE(snum),sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; strupper(buf); if (uLevel <= 1) { PACKS(desc,"B9",buf); /* szName */ @@ -3026,7 +3027,11 @@ int reply_trans(char *inbuf,char *outbuf) int dsoff = SVAL(inbuf,smb_vwv12); int suwcnt = CVAL(inbuf,smb_vwv13); - StrnCpy(name,smb_buf(inbuf),sizeof(name)-1); + fstrcpy(name,smb_buf(inbuf)); + + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters\n"); + } if (tdscnt) { @@ -3088,6 +3093,10 @@ int reply_trans(char *inbuf,char *outbuf) pscnt += pcnt; dscnt += dcnt; + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters\n"); + } + if (pcnt) memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); if (dcnt) diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 3f753cf855..b0a45ffb47 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -273,7 +273,7 @@ BOOL check_mangled_stack(char *s) } if (check_extension && !strchr(mangled_stack[i],'.')) { - strcpy(tmpname,mangled_stack[i]); + pstrcpy(tmpname,mangled_stack[i]); strcat(tmpname,extension); mangle_name_83(tmpname); if (strequal(tmpname,s)) @@ -307,7 +307,7 @@ static char *map_filename(char *s, /* This is null terminated */ pstring pat; StrnCpy(pat, pattern, len); /* Get pattern into a proper string! */ - strcpy(matching_bit,""); /* Match but no star gets this. */ + pstrcpy(matching_bit,""); /* Match but no star gets this. */ pp = pat; /* Initialise the pointers. */ sp = s; if ((len == 1) && (*pattern == '*')) { @@ -446,7 +446,7 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) continue; /* Always check for the end. */ } if (*end == '*') { - strcpy(np, match_string); + pstrcpy(np, match_string); np += strlen(match_string); end++; /* Skip the '*' */ while ((*end) /* Not the end of string. */ @@ -460,7 +460,7 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) } *np++ = '\0'; /* NULL terminate it. */ DEBUG(5,("End of second in pair '%s'\n", end)); - strcpy(s, new_string); /* Substitute with the new name. */ + pstrcpy(s, new_string); /* Substitute with the new name. */ DEBUG(5,("s is now '%s'\n", s)); } start = end; /* Skip a bit which cannot be wanted */ diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 93a2d9d850..64253932ab 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -54,7 +54,7 @@ static void msg_deliver(void) /* put it in a temporary file */ sprintf(s,"%s/msg.XXXXXX",tmpdir()); - strcpy(name,(char *)mktemp(s)); + fstrcpy(name,(char *)mktemp(s)); fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); if (fd == -1) { @@ -74,7 +74,7 @@ static void msg_deliver(void) /* run the command */ if (*lp_msg_command()) { - strcpy(s,lp_msg_command()); + pstrcpy(s,lp_msg_command()); string_sub(s,"%s",name); string_sub(s,"%f",msgfrom); string_sub(s,"%t",msgto); @@ -108,8 +108,8 @@ int reply_sends(char *inbuf,char *outbuf) dest = skip_string(orig,1)+1; msg = skip_string(dest,1)+1; - strcpy(msgfrom,orig); - strcpy(msgto,dest); + fstrcpy(msgfrom,orig); + fstrcpy(msgto,dest); len = SVAL(msg,0); len = MIN(len,1600-msgpos); @@ -143,10 +143,10 @@ int reply_sendstrt(char *inbuf,char *outbuf) orig = smb_buf(inbuf)+1; dest = skip_string(orig,1)+1; - strcpy(msgfrom,orig); - strcpy(msgto,dest); + fstrcpy(msgfrom,orig); + fstrcpy(msgto,dest); - DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),orig,dest)); + DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),msgfrom,msgto)); return(outsize); } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index afab7e1d91..feb8d91a5b 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -87,7 +87,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL bad_path = False; /* XXXX we need to handle passed times, sattr and flags */ - strcpy(fname,smb_buf(inbuf)); + pstrcpy(fname,smb_buf(inbuf)); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ @@ -98,7 +98,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(4,("Opening pipe %s.\n", fname)); /* Strip \PIPE\ off the name. */ - strcpy(fname,smb_buf(inbuf) + PIPELEN); + pstrcpy(fname,smb_buf(inbuf) + PIPELEN); /* See if it is one we want to handle. */ for( i = 0; known_pipes[i] ; i++ ) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8117685637..c1422bbcf6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -48,6 +48,18 @@ a packet to ensure chaining works correctly */ #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) +/**************************************************************************** +report a possible attack via the password buffer overflow bug +****************************************************************************/ +static void overflow_attack(int len) +{ + DEBUG(0,("ERROR: Invalid password length %d\n", len)); + DEBUG(0,("you're machine may be under attack by a user exploiting an old bug\n")); + DEBUG(0,("Attack was from IP=%s\n", client_addr())); + exit_server("possible attack"); +} + + /**************************************************************************** reply to an special message ****************************************************************************/ @@ -66,36 +78,36 @@ int reply_special(char *inbuf,char *outbuf) smb_setlen(outbuf,0); switch (msg_type) { - case 0x81: /* session request */ - CVAL(outbuf,0) = 0x82; - CVAL(outbuf,3) = 0; - if (name_len(inbuf+4) > 50) { - DEBUG(0,("Invalid name length in session request\n")); - return(0); - } - name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); + case 0x81: /* session request */ + CVAL(outbuf,0) = 0x82; + CVAL(outbuf,3) = 0; + if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { + DEBUG(0,("Invalid name length in session request\n")); + return(0); + } + name_extract(inbuf,4,name1); + name_extract(inbuf,4 + name_len(inbuf + 4),name2); DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - - strcpy(remote_machine,name2); - trim_string(remote_machine," "," "); - p = strchr(remote_machine,' '); - strlower(remote_machine); - if (p) *p = 0; - - strcpy(local_machine,name1); - trim_string(local_machine," "," "); - p = strchr(local_machine,' '); - strlower(local_machine); - if (p) *p = 0; - - add_session_user(remote_machine); - - reload_services(True); - reopen_logs(); - - break; + + fstrcpy(remote_machine,name2); + trim_string(remote_machine," "," "); + p = strchr(remote_machine,' '); + strlower(remote_machine); + if (p) *p = 0; + + fstrcpy(local_machine,name1); + trim_string(local_machine," "," "); + p = strchr(local_machine,' '); + strlower(local_machine); + if (p) *p = 0; + + add_session_user(remote_machine); + + reload_services(True); + reopen_logs(); + + break; case 0x89: /* session keepalive request (some old clients produce this?) */ @@ -160,25 +172,25 @@ static void parse_connect(char *p,char *service,char *user, p2 = strrchr(p,'\\'); if (p2 == NULL) - strcpy(service,p); + fstrcpy(service,p); else - strcpy(service,p2+1); + fstrcpy(service,p2+1); p += strlen(p) + 2; - strcpy(password,p); + fstrcpy(password,p); *pwlen = strlen(password); p += strlen(p) + 2; - strcpy(dev,p); + fstrcpy(dev,p); *user = 0; p = strchr(service,'%'); if (p != NULL) { *p = 0; - strcpy(user,p+1); + fstrcpy(user,p+1); } } @@ -238,6 +250,10 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) close_cnum(SVAL(inbuf,smb_tid),vuid); + + if (passlen > MAX_PASSWORD_LENGTH) { + overflow_attack(passlen); + } { char *path; @@ -252,18 +268,17 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) passlen = strlen(password); } - DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen)); - strcpy(service,path+2); + fstrcpy(service,path+2); p = strchr(service,'\\'); if (!p) return(ERROR(ERRSRV,ERRinvnetname)); *p = 0; - strcpy(service,p+1); + fstrcpy(service,p+1); p = strchr(service,'%'); if (p) { *p++ = 0; - strcpy(user,p); + fstrcpy(user,p); } StrnCpy(devicename,path + strlen(path) + 1,6); DEBUG(4,("Got device type %s\n",devicename)); @@ -372,11 +387,15 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); + if (smb_apasslen > MAX_PASSWORD_LENGTH) + overflow_attack(smb_apasslen); + memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1); + pstrcpy(user,smb_buf(inbuf)+smb_apasslen); - if (lp_security() != SEC_SERVER && !doencrypt) - smb_apasslen = strlen(smb_apasswd); + if (lp_security() != SEC_SERVER && !doencrypt) { + smb_apasslen = strlen(smb_apasswd); + } } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); @@ -401,6 +420,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 != 24 && passlen2 != 24) doencrypt = False; + if (passlen1 > MAX_PASSWORD_LENGTH) { + overflow_attack(passlen1); + } + + passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); + passlen2 = MIN(passlen2, MAX_PASSWORD_LENGTH); + if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; @@ -438,7 +464,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } p += passlen1 + passlen2; - strcpy(user,p); p = skip_string(p,1); + fstrcpy(user,p); p = skip_string(p,1); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", p,skip_string(p,1),skip_string(p,2))); } @@ -591,7 +617,7 @@ int reply_chkpth(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf) + 1); + pstrcpy(name,smb_buf(inbuf) + 1); unix_convert(name,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); @@ -639,7 +665,7 @@ int reply_getatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(fname,smb_buf(inbuf) + 1); + pstrcpy(fname,smb_buf(inbuf) + 1); unix_convert(fname,cnum,0,&bad_path); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" @@ -714,7 +740,7 @@ int reply_setatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(fname,smb_buf(inbuf) + 1); + pstrcpy(fname,smb_buf(inbuf) + 1); unix_convert(fname,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); @@ -825,8 +851,8 @@ int reply_search(char *inbuf,char *outbuf) { pstring dir2; - strcpy(directory,smb_buf(inbuf)+1); - strcpy(dir2,smb_buf(inbuf)+1); + pstrcpy(directory,smb_buf(inbuf)+1); + pstrcpy(dir2,smb_buf(inbuf)+1); unix_convert(directory,cnum,0,&bad_path); unix_format(dir2); @@ -842,7 +868,7 @@ int reply_search(char *inbuf,char *outbuf) else { *p = 0; - strcpy(mask,p+1); + pstrcpy(mask,p+1); } p = strrchr(directory,'/'); @@ -876,7 +902,7 @@ int reply_search(char *inbuf,char *outbuf) if ((p = strrchr(mask,' '))) { fstring ext; - strcpy(ext,p+1); + fstrcpy(ext,p+1); *p = 0; trim_string(mask,NULL," "); strcat(mask,"."); @@ -898,7 +924,7 @@ int reply_search(char *inbuf,char *outbuf) if (!strchr(mask,'.') && strlen(mask)>8) { fstring tmp; - strcpy(tmp,&mask[8]); + fstrcpy(tmp,&mask[8]); mask[8] = '.'; mask[9] = 0; strcat(mask,tmp); @@ -1078,7 +1104,7 @@ int reply_open(char *inbuf,char *outbuf) share_mode = SVAL(inbuf,smb_vwv0); - strcpy(fname,smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -1168,7 +1194,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* XXXX we need to handle passed times, sattr and flags */ - strcpy(fname,smb_buf(inbuf)); + pstrcpy(fname,smb_buf(inbuf)); unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -1281,7 +1307,7 @@ int reply_mknew(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); - strcpy(fname,smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,cnum,0,&bad_path); if (createmode & aVOLID) @@ -1359,7 +1385,8 @@ int reply_ctemp(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); - sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); + strcat(fname,"/TMXXXXXX"); unix_convert(fname,cnum,0,&bad_path); unixmode = unix_mode(cnum,createmode); @@ -1455,7 +1482,7 @@ int reply_unlink(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); dirtype = SVAL(inbuf,smb_vwv0); - strcpy(name,smb_buf(inbuf) + 1); + pstrcpy(name,smb_buf(inbuf) + 1); DEBUG(3,("reply_unlink : %s\n",name)); @@ -1503,7 +1530,7 @@ int reply_unlink(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; @@ -2381,7 +2408,7 @@ int reply_printopen(char *inbuf,char *outbuf) { pstring s; char *p; - StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1); + pstrcpy(s,smb_buf(inbuf)+1); p = s; while (*p) { @@ -2583,7 +2610,7 @@ int reply_mkdir(char *inbuf,char *outbuf) int outsize,ret= -1; BOOL bad_path = False; - strcpy(directory,smb_buf(inbuf) + 1); + pstrcpy(directory,smb_buf(inbuf) + 1); cnum = SVAL(inbuf,smb_tid); unix_convert(directory,cnum,0,&bad_path); @@ -2680,7 +2707,7 @@ int reply_rmdir(char *inbuf,char *outbuf) BOOL bad_path = False; cnum = SVAL(inbuf,smb_tid); - strcpy(directory,smb_buf(inbuf) + 1); + pstrcpy(directory,smb_buf(inbuf) + 1); unix_convert(directory,cnum,0,&bad_path); if (check_name(directory,cnum)) @@ -2728,7 +2755,7 @@ int reply_rmdir(char *inbuf,char *outbuf) errno = ENOMEM; break; } - strcpy(fullname, directory); + pstrcpy(fullname, directory); strcat(fullname, "/"); strcat(fullname, dname); @@ -2795,21 +2822,21 @@ static BOOL resolve_wildcards(char *name1,char *name2) if (!name1 || !name2) return(False); - strcpy(root1,name1); - strcpy(root2,name2); + fstrcpy(root1,name1); + fstrcpy(root2,name2); p = strrchr(root1,'.'); if (p) { *p = 0; - strcpy(ext1,p+1); + fstrcpy(ext1,p+1); } else { - strcpy(ext1,""); + fstrcpy(ext1,""); } p = strrchr(root2,'.'); if (p) { *p = 0; - strcpy(ext2,p+1); + fstrcpy(ext2,p+1); } else { - strcpy(ext2,""); + fstrcpy(ext2,""); } p = root1; @@ -2883,8 +2910,8 @@ int reply_mv(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf) + 1); - strcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); + pstrcpy(name,smb_buf(inbuf) + 1); + pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); @@ -2998,14 +3025,14 @@ int reply_mv(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; error = ERRnoaccess; sprintf(fname,"%s/%s",directory,dname); if (!can_rename(fname,cnum)) continue; - strcpy(destname,newname); + pstrcpy(destname,newname); if (!resolve_wildcards(fname,destname)) continue; @@ -3051,7 +3078,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, int fnum1,fnum2; pstring dest; - strcpy(dest,dest1); + pstrcpy(dest,dest1); if (target_is_directory) { char *p = strrchr(src,'/'); if (p) @@ -3128,8 +3155,8 @@ int reply_copy(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf)); - strcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); + pstrcpy(name,smb_buf(inbuf)); + pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); @@ -3198,7 +3225,7 @@ int reply_copy(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; @@ -3252,7 +3279,7 @@ int reply_setdir(char *inbuf,char *outbuf) if (!CAN_SETDIR(snum)) return(ERROR(ERRDOS,ERRnoaccess)); - strcpy(newdir,smb_buf(inbuf) + 1); + pstrcpy(newdir,smb_buf(inbuf) + 1); strlower(newdir); if (strlen(newdir) == 0) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3b24ba5ce9..22c8448dde 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -399,7 +399,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) (strequal(dname,".") || strequal(dname,".."))) continue; - strcpy(name2,dname); + pstrcpy(name2,dname); if (!name_map_mangle(name2,False,SNUM(cnum))) continue; if ((mangled && mangled_equal(name,name2)) @@ -545,7 +545,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa /* remember the rest of the pathname so it can be restored later */ - if (end) strcpy(rest,end+1); + if (end) pstrcpy(rest,end+1); /* try to find this part of the path in the directory */ if (strchr(start,'?') || strchr(start,'*') || @@ -1057,7 +1057,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct Files[fnum].fd_ptr = 0; errno = EPERM; - strcpy(fname,fname1); + pstrcpy(fname,fname1); /* check permissions */ if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer) @@ -1186,7 +1186,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct pstring dname; int dum1,dum2,dum3; char *p; - strcpy(dname,fname); + pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; if (sys_disk_free(dname,&dum1,&dum2,&dum3) < @@ -1321,10 +1321,10 @@ static void check_magic(int fnum,int cnum) int ret; pstring magic_output; pstring fname; - strcpy(fname,Files[fnum].name); + pstrcpy(fname,Files[fnum].name); if (*lp_magicoutput(SNUM(cnum))) - strcpy(magic_output,lp_magicoutput(SNUM(cnum))); + pstrcpy(magic_output,lp_magicoutput(SNUM(cnum))); else sprintf(magic_output,"%s.out",fname); @@ -2355,10 +2355,10 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; - strcpy(fname,lp_configfile()); + pstrcpy(fname,lp_configfile()); if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { - strcpy(servicesf,fname); + pstrcpy(servicesf,fname); test = False; } } @@ -2651,13 +2651,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { struct passwd *pass2; fstring fuser; - strcpy(fuser,lp_force_user(snum)); + fstrcpy(fuser,lp_force_user(snum)); pass2 = (struct passwd *)Get_Pwnam(fuser,True); if (pass2) { pcon->uid = pass2->pw_uid; string_set(&pcon->user,fuser); - strcpy(user,fuser); + fstrcpy(user,fuser); pcon->force_user = True; DEBUG(3,("Forced user %s\n",fuser)); } @@ -2667,7 +2667,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring s; - strcpy(s,lp_pathname(snum)); + pstrcpy(s,lp_pathname(snum)); standard_sub(cnum,s); string_set(&pcon->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); @@ -2703,7 +2703,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de if (*lp_rootpreexec(SNUM(cnum))) { pstring cmd; - strcpy(cmd,lp_rootpreexec(SNUM(cnum))); + pstrcpy(cmd,lp_rootpreexec(SNUM(cnum))); standard_sub(cnum,cmd); DEBUG(5,("cmd=%s\n",cmd)); smbrun(cmd,NULL,False); @@ -2743,7 +2743,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de /* resolve any soft links early */ { pstring s; - strcpy(s,pcon->connectpath); + pstrcpy(s,pcon->connectpath); GetWd(s); string_set(&pcon->connectpath,s); ChDir(pcon->connectpath); @@ -2757,7 +2757,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de if (*lp_preexec(SNUM(cnum))) { pstring cmd; - strcpy(cmd,lp_preexec(SNUM(cnum))); + pstrcpy(cmd,lp_preexec(SNUM(cnum))); standard_sub(cnum,cmd); smbrun(cmd,NULL,False); } @@ -3216,7 +3216,7 @@ static int reply_negprot(char *inbuf,char *outbuf) SSVAL(outbuf,smb_vwv0,choice); if(choice != -1) { extern fstring remote_proto; - strcpy(remote_proto,supported_protocols[protocol].short_name); + fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(True); outsize = supported_protocols[protocol].proto_reply_fn(outbuf); DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); @@ -3335,7 +3335,7 @@ BOOL yield_connection(int cnum,char *name,int max_connections) bzero(&crec,sizeof(crec)); - strcpy(fname,lp_lockdir()); + pstrcpy(fname,lp_lockdir()); standard_sub(cnum,fname); trim_string(fname,"","/"); @@ -3407,7 +3407,7 @@ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections)); - strcpy(fname,lp_lockdir()); + pstrcpy(fname,lp_lockdir()); standard_sub(cnum,fname); trim_string(fname,"","/"); @@ -3503,7 +3503,7 @@ static BOOL dump_core(void) { char *p; pstring dname; - strcpy(dname,debugf); + pstrcpy(dname,debugf); if ((p=strrchr(dname,'/'))) *p=0; strcat(dname,"/corefiles"); mkdir(dname,0700); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c8e726d36e..59e9ef21b0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -306,10 +306,10 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l if(p[1] == '\0') strcpy(mask,"*.*"); else - strcpy(mask, p+1); + pstrcpy(mask, p+1); } else - strcpy(mask, path_mask); + pstrcpy(mask, path_mask); while (!found) { @@ -327,7 +327,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l matched = False; - strcpy(fname,dname); + pstrcpy(fname,dname); if(mask_match(fname, mask, case_sensitive, True)) { @@ -338,7 +338,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l if (isrootdir && isdots) continue; - strcpy(pathreal,Connections[cnum].dirpath); + pstrcpy(pathreal,Connections[cnum].dirpath); if(needslash) strcat(pathreal,"/"); strcat(pathreal,dname); @@ -595,7 +595,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum return(ERROR(ERRDOS,ERRunknownlevel)); } - strcpy(directory, params + 12); /* Complete directory path with + pstrcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */ DEBUG(5,("path=%s\n",directory)); @@ -1057,7 +1057,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, /* qpathinfo */ info_level = SVAL(params,0); fname = &fname1[0]; - strcpy(fname,¶ms[6]); + pstrcpy(fname,¶ms[6]); unix_convert(fname,cnum,0,&bad_path); if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); @@ -1163,7 +1163,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_ALT_NAME_INFO: data_size = 4 + l; SIVAL(pdata,0,l); - strcpy(pdata+4,fname); + pstrcpy(pdata+4,fname); break; case SMB_QUERY_FILE_ALLOCATION_INFO: case SMB_QUERY_FILE_END_OF_FILEINFO: @@ -1197,7 +1197,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, pdata += 4; pdata += 4; /* alignment */ SIVAL(pdata,0,l); - strcpy(pdata+4,fname); + pstrcpy(pdata+4,fname); pdata += 4 + l; data_size = PTR_DIFF(pdata,(*ppdata)); break; @@ -1208,7 +1208,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, SIVAL(pdata,4,size); SIVAL(pdata,12,size); SIVAL(pdata,20,l); - strcpy(pdata+24,fname); + pstrcpy(pdata+24,fname); break; default: return(ERROR(ERRDOS,ERRunknownlevel)); @@ -1260,7 +1260,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, /* set path info */ info_level = SVAL(params,0); fname = fname1; - strcpy(fname,¶ms[6]); + pstrcpy(fname,¶ms[6]); unix_convert(fname,cnum,0,&bad_path); if(!check_name(fname, cnum)) { @@ -1443,7 +1443,7 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, if (!CAN_WRITE(cnum)) return(ERROR(ERRSRV,ERRaccess)); - strcpy(directory, ¶ms[4]); + pstrcpy(directory, ¶ms[4]); DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); @@ -1645,6 +1645,9 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) num_params = num_params_sofar = SVAL(inbuf,smb_pscnt); num_data = num_data_sofar = SVAL(inbuf, smb_dscnt); + if (num_params > total_params || num_data > total_data) + exit_server("invalid params in reply_trans2"); + memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); @@ -1672,6 +1675,9 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) total_data = SVAL(inbuf, smb_tdscnt); num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt)); num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt)); + if (num_params_sofar > total_params || num_data_sofar > total_data) + exit_server("data overflow in trans2"); + memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params); memcpy( &data[SVAL(inbuf, smb_sdsdisp)], diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c index 0a4d50c217..07558274a5 100644 --- a/source3/smbd/vt_mode.c +++ b/source3/smbd/vt_mode.c @@ -81,7 +81,7 @@ int VT_Start_utmp(void) setutent(); - strcpy(u.ut_line, VT_Line); + fstrcpy(u.ut_line, VT_Line); if((v = getutline(&u)) == NULL) { if(strncmp(VT_Line, "tty", 3) == 0) @@ -91,12 +91,12 @@ int VT_Start_utmp(void) else tt = VT_Line; - strcpy(u.ut_id, tt); + fstrcpy(u.ut_id, tt); u.ut_time = time((time_t*)0); } - strcpy(u.ut_user, "LOGIN"); - strcpy(u.ut_line, VT_Line); + fstrcpy(u.ut_user, "LOGIN"); + fstrcpy(u.ut_line, VT_Line); u.ut_pid = getpid(); u.ut_type = LOGIN_PROCESS; pututline(&u); @@ -118,10 +118,10 @@ int VT_Stop_utmp(void) if(VT_Line != NULL) { setutent(); - strcpy(u.ut_line, VT_Line); + fstrcpy(u.ut_line, VT_Line); if((v = getutline(&u)) != NULL) { - strcpy(v->ut_user, ""); + fstrcpy(v->ut_user, ""); v->ut_type = DEAD_PROCESS; v->ut_time = time((time_t*)0); pututline(v); -- cgit From dff16872ca39c007d32d114af82d3ccd97f9d47a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 1997 19:26:56 +0000 Subject: Syncing up current oplock work in progress. #ifdef'ed out so should have no effect on other work. Jeremy (jallison@whistle.com) (This used to be commit 7e3d4c8b21f63a06d32605d230129e36883ad08c) --- source3/smbd/pipes.c | 2 +- source3/smbd/reply.c | 79 ++++++++++++------ source3/smbd/server.c | 227 +++++++++++++++++++++++++++++++------------------- source3/smbd/trans2.c | 6 +- 4 files changed, 195 insertions(+), 119 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index feb8d91a5b..a465e91145 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -127,7 +127,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) unixmode = unix_mode(cnum,smb_attr); open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - &rmode,&smb_action); + 0, &rmode,&smb_action); if (!Files[fnum].open) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c1422bbcf6..94839c227a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1099,6 +1099,8 @@ int reply_open(char *inbuf,char *outbuf) int rmode=0; struct stat sbuf; BOOL bad_path = False; + files_struct *fsp; + int oplock_request = CORE_OPLOCK_REQUEST(inbuf); cnum = SVAL(inbuf,smb_tid); @@ -1123,9 +1125,12 @@ int reply_open(char *inbuf,char *outbuf) unixmode = unix_mode(cnum,aARCH); - open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL); + open_file_shared(fnum,cnum,fname,share_mode,3,unixmode, + oplock_request,&rmode,NULL); - if (!Files[fnum].open) + fsp = &Files[fnum]; + + if (!fsp->open) { if((errno == ENOENT) && bad_path) { @@ -1135,7 +1140,7 @@ int reply_open(char *inbuf,char *outbuf) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1157,10 +1162,12 @@ int reply_open(char *inbuf,char *outbuf) SIVAL(outbuf,smb_vwv4,size); SSVAL(outbuf,smb_vwv6,rmode); - if (lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + fsp->granted_oplock = True; } + if(fsp->granted_oplock) + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; return(outsize); } @@ -1175,7 +1182,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) int fnum = -1; int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); - BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1); + BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); #if 0 int open_flags = SVAL(inbuf,smb_vwv2); int smb_sattr = SVAL(inbuf,smb_vwv4); @@ -1187,6 +1194,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) struct stat sbuf; int smb_action = 0; BOOL bad_path = False; + files_struct *fsp; /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(cnum)) @@ -1214,9 +1222,11 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unixmode = unix_mode(cnum,smb_attr | aARCH); open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - &rmode,&smb_action); + oplock_request, &rmode,&smb_action); - if (!Files[fnum].open) + fsp = &Files[fnum]; + + if (!fsp->open) { if((errno == ENOENT) && bad_path) { @@ -1226,7 +1236,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1240,9 +1250,12 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= (1<<15); + fsp->granted_oplock = True; } + if(fsp->granted_oplock) + smb_action |= EXTENDED_OPLOCK_GRANTED; + set_message(outbuf,15,0,True); SSVAL(outbuf,smb_vwv2,fnum); SSVAL(outbuf,smb_vwv3,fmode); @@ -1302,6 +1315,8 @@ int reply_mknew(char *inbuf,char *outbuf) mode_t unixmode; int ofun = 0; BOOL bad_path = False; + files_struct *fsp; + int oplock_request = CORE_OPLOCK_REQUEST(inbuf); com = SVAL(inbuf,smb_com); cnum = SVAL(inbuf,smb_tid); @@ -1343,9 +1358,12 @@ int reply_mknew(char *inbuf,char *outbuf) } /* Open file in dos compatibility share mode. */ - open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL); + open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, + oplock_request, NULL, NULL); - if (!Files[fnum].open) + fsp = &Files[fnum]; + + if (!fsp->open) { if((errno == ENOENT) && bad_path) { @@ -1358,10 +1376,13 @@ int reply_mknew(char *inbuf,char *outbuf) outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); - if (lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + fsp->granted_oplock = True; } - + + if(fsp->granted_oplock) + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + DEBUG(2,("new file %s\n",fname)); DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); @@ -1382,6 +1403,8 @@ int reply_ctemp(char *inbuf,char *outbuf) int createmode; mode_t unixmode; BOOL bad_path = False; + files_struct *fsp; + int oplock_request = CORE_OPLOCK_REQUEST(inbuf); cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); @@ -1409,9 +1432,12 @@ int reply_ctemp(char *inbuf,char *outbuf) /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL); + open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, + oplock_request, NULL, NULL); - if (!Files[fnum].open) + fsp = &Files[fnum]; + + if (!fsp->open) { if((errno == ENOENT) && bad_path) { @@ -1426,10 +1452,13 @@ int reply_ctemp(char *inbuf,char *outbuf) CVAL(smb_buf(outbuf),0) = 4; strcpy(smb_buf(outbuf) + 1,fname2); - if (lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + fsp->granted_oplock = True; } + if(fsp->granted_oplock) + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + DEBUG(2,("created temp file %s\n",fname2)); DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); @@ -2432,7 +2461,8 @@ int reply_printopen(char *inbuf,char *outbuf) return(ERROR(ERRDOS,ERRnoaccess)); /* Open for exclusive use, write only. */ - open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL); + open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), + 0, NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -3094,7 +3124,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, fnum1 = find_free_file(); if (fnum1<0) return(False); open_file_shared(fnum1,cnum,src,(DENY_NONE<<4), - 1,0,&Access,&action); + 1,0,0,&Access,&action); if (!Files[fnum1].open) return(False); @@ -3107,7 +3137,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, return(False); } open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, - ofun,st.st_mode,&Access,&action); + ofun,st.st_mode,0,&Access,&action); if (!Files[fnum2].open) { close_file(fnum1); @@ -3713,8 +3743,3 @@ int reply_getattrE(char *inbuf,char *outbuf) return(outsize); } - - - - - diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 22c8448dde..d2ad803c9c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -88,6 +88,8 @@ static int num_connections_open = 0; /* Oplock ipc UDP socket. */ int oplock_sock = -1; uint16 oplock_port = 0; +/* Current number of oplocks we have outstanding. */ +uint32 oplocks_open = 0; #endif /* USE_OPLOCKS */ extern fstring remote_machine; @@ -1052,9 +1054,10 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct pstring fname; struct stat statbuf; file_fd_struct *fd_ptr; + files_struct *fsp = &Files[fnum]; - Files[fnum].open = False; - Files[fnum].fd_ptr = 0; + fsp->open = False; + fsp->fd_ptr = 0; errno = EPERM; pstrcpy(fname,fname1); @@ -1192,7 +1195,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(cnum))) { fd_attempt_close(fd_ptr); - Files[fnum].fd_ptr = 0; + fsp->fd_ptr = 0; if(fd_ptr->ref_count == 0) sys_unlink(fname); errno = ENOSPC; @@ -1228,25 +1231,26 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fd_ptr->dev = (uint32)sbuf->st_dev; fd_ptr->inode = (uint32)sbuf->st_ino; - Files[fnum].fd_ptr = fd_ptr; + fsp->fd_ptr = fd_ptr; Connections[cnum].num_files_open++; - Files[fnum].mode = sbuf->st_mode; - GetTimeOfDay(&Files[fnum].open_time); - Files[fnum].uid = current_user.id; - Files[fnum].size = 0; - Files[fnum].pos = -1; - Files[fnum].open = True; - Files[fnum].mmap_ptr = NULL; - Files[fnum].mmap_size = 0; - Files[fnum].can_lock = True; - Files[fnum].can_read = ((flags & O_WRONLY)==0); - Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - Files[fnum].share_mode = 0; - Files[fnum].print_file = Connections[cnum].printer; - Files[fnum].modified = False; - Files[fnum].cnum = cnum; - string_set(&Files[fnum].name,dos_to_unix(fname,False)); - Files[fnum].wbmpx_ptr = NULL; + fsp->mode = sbuf->st_mode; + GetTimeOfDay(&fsp->open_time); + fsp->uid = current_user.id; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + fsp->can_lock = True; + fsp->can_read = ((flags & O_WRONLY)==0); + fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + fsp->share_mode = 0; + fsp->print_file = Connections[cnum].printer; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->cnum = cnum; + string_set(&fsp->name,dos_to_unix(fname,False)); + fsp->wbmpx_ptr = NULL; /* * If the printer is marked as postscript output a leading @@ -1255,8 +1259,8 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct * This has a similar effect as CtrlD=0 in WIN.INI file. * tim@fsg.com 09/06/94 */ - if (Files[fnum].print_file && POSTSCRIPT(cnum) && - Files[fnum].can_write) + if (fsp->print_file && POSTSCRIPT(cnum) && + fsp->can_write) { DEBUG(3,("Writing postscript line\n")); write_file(fnum,"%!\n",3); @@ -1264,23 +1268,23 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", timestring(),Connections[cnum].user,fname, - BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write), + BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write), Connections[cnum].num_files_open,fnum)); } #if USE_MMAP /* mmap it if read-only */ - if (!Files[fnum].can_write) + if (!fsp->can_write) { - Files[fnum].mmap_size = file_size(fname); - Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size, - PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0); + fsp->mmap_size = file_size(fname); + fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, + PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); - if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr) + if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); - Files[fnum].mmap_ptr = NULL; + fsp->mmap_ptr = NULL; } } #endif @@ -1512,12 +1516,52 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, } } +/**************************************************************************** +check if we can open a file with a share mode +****************************************************************************/ +int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, + BOOL fcbopen, int *flags) +{ + int old_open_mode = share->share_mode &0xF; + int old_deny_mode = (share->share_mode >>4)&7; + + if (old_deny_mode > 4 || old_open_mode > 2) + { + DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", + deny_mode,old_deny_mode,old_open_mode,fname)); + return False; + } + + { + int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, + share->pid,fname); + + if ((access_allowed == AFAIL) || + (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || + (access_allowed == AREAD && *flags == O_WRONLY) || + (access_allowed == AWRITE && *flags == O_RDONLY)) + { + DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", + deny_mode,old_deny_mode,old_open_mode, + share->pid,fname, access_allowed)); + return False; + } + + if (access_allowed == AREAD) + *flags = O_RDONLY; + + if (access_allowed == AWRITE) + *flags = O_WRONLY; + + } + return True; +} /**************************************************************************** open a file with a share mode ****************************************************************************/ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, - int mode,int *Access,int *action) + int mode,int oplock_request, int *Access,int *action) { files_struct *fs_p = &Files[fnum]; int flags=0; @@ -1605,7 +1649,6 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int i; min_share_mode_entry *old_shares = 0; - if (file_existed) { dev = (uint32)sbuf.st_dev; @@ -1615,55 +1658,61 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, num_shares = get_share_modes(cnum, token, dev, inode, &old_shares); } - for(i = 0; i < num_shares; i++) - { - /* someone else has a share lock on it, check to see - if we can too */ - int old_open_mode = old_shares[i].share_mode &0xF; - int old_deny_mode = (old_shares[i].share_mode >>4)&7; + /* + * Check if the share modes will give us access. + */ - if (old_deny_mode > 4 || old_open_mode > 2) - { - DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", - deny_mode,old_deny_mode,old_open_mode,fname)); - free((char *)old_shares); - if(share_locked) - unlock_share_entry(cnum, dev, inode, token); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } + if(share_locked && (num_shares != 0)) + { + BOOL broke_oplock; + do { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - old_shares[i].pid,fname); - - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) || - (access_allowed == AREAD && flags == O_WRONLY) || - (access_allowed == AWRITE && flags == O_RDONLY)) + broke_oplock = False; + for(i = 0; i < num_shares; i++) { - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", - deny_mode,old_deny_mode,old_open_mode, - old_shares[i].pid,fname, - access_allowed)); - free((char *)old_shares); - if(share_locked) + /* someone else has a share lock on it, check to see + if we can too */ + if(check_share_mode(&old_shares[i], deny_mode, fname, fcbopen, &flags) == False) + { + free((char *)old_shares); unlock_share_entry(cnum, dev, inode, token); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } +#ifdef USE_OPLOCKS + /* + * The share modes would give us access. Check if someone + * has an oplock on this file. If so we must break it before + * continuing. + */ + if(old_shares[i].op_type != 0) + { + /* Oplock break.... */ + unlock_share_entry(cnum, dev, inode, token); +#if 0 /* Work in progress..... */ + if(break_oplock()) + { + free((char *)old_shares); + /* Error condition here... */ + } + lock_share_entry(cnum, dev, inode, &token); + broke_oplock = True; + break; +#endif + } +#endif /* USE_OPLOCKS */ } - - if (access_allowed == AREAD) - flags = O_RDONLY; - - if (access_allowed == AWRITE) - flags = O_WRONLY; - } + if(broke_oplock) + { + free((char *)old_shares); + num_shares = get_share_modes(cnum, token, dev, inode, &old_shares); + } + } while(broke_oplock); } + if(old_shares != 0) free((char *)old_shares); } @@ -1720,7 +1769,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, file (which expects the share_mode_entry to be there). */ if (lp_share_modes(SNUM(cnum))) - set_share_mode(token, fnum, 0); + set_share_mode(token, fnum, 0, 0); if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fnum,cnum,token,&share_locked); @@ -2279,7 +2328,8 @@ static BOOL open_oplock_ipc() if (oplock_sock == -1) { DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %x. Error was %s\n", INADDR_LOOPBACK, strerror(errno))); +address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); + oplock_port = 0; return(False); } @@ -2290,6 +2340,7 @@ address %x. Error was %s\n", INADDR_LOOPBACK, strerror(errno))); strerror(errno))); close(oplock_sock); oplock_sock = -1; + oplock_port = 0; return False; } oplock_port = ntohs(sock_name.sin_port); @@ -2324,7 +2375,7 @@ static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) /* Validate message from address (must be localhost). */ if(from_addr.s_addr != htonl(INADDR_LOOPBACK)) { - DEBUG(0,("process_local_message: invalid from address \ + DEBUG(0,("process_local_message: invalid 'from' address \ (was %x should be 127.0.0.1\n", from_addr.s_addr)); return False; } @@ -4010,20 +4061,20 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) it can be used by the oplock break code. ****************************************************************************/ -static void process_smb(char *InBuffer, char *OutBuffer) +static void process_smb(char *inbuf, char *outbuf) { extern int Client; static int trans_num = 0; - int msg_type = CVAL(InBuffer,0); - int32 len = smb_len(InBuffer); + int msg_type = CVAL(inbuf,0); + int32 len = smb_len(outbuf); int nread = len + 4; DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); #ifdef WITH_VTP - if(trans_num == 1 && VT_Check(InBuffer)) + if(trans_num == 1 && VT_Check(inbuf)) { VT_Process(); return; @@ -4031,22 +4082,22 @@ static void process_smb(char *InBuffer, char *OutBuffer) #endif if (msg_type == 0) - show_msg(InBuffer); + show_msg(inbuf); - nread = construct_reply(InBuffer,OutBuffer,nread,max_send); + nread = construct_reply(inbuf,outbuf,nread,max_send); if(nread > 0) { - if (CVAL(OutBuffer,0) == 0) - show_msg(OutBuffer); + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); - if (nread != smb_len(OutBuffer) + 4) + if (nread != smb_len(outbuf) + 4) { DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(OutBuffer))); + nread, smb_len(outbuf))); } else - send_smb(Client,OutBuffer); + send_smb(Client,outbuf); } trans_num++; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 59e9ef21b0..8ab024ded2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -166,7 +166,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, char *params = *pparams; int16 open_mode = SVAL(params, 2); int16 open_attr = SVAL(params,6); - BOOL oplock_request = BITSETW(params,1); + BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1)); #if 0 BOOL return_additional_info = BITSETW(params,0); int16 open_sattr = SVAL(params, 4); @@ -213,7 +213,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, - &rmode,&smb_action); + oplock_request, &rmode,&smb_action); if (!Files[fnum].open) { @@ -252,7 +252,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, SSVAL(params,12,rmode); if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= (1<<15); + smb_action |= EXTENDED_OPLOCK_GRANTED; } SSVAL(params,18,smb_action); -- cgit From a5af479e5d4e93aaf8b1effdbd9057d2a9b85aea Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 1997 19:40:12 +0000 Subject: Fixed you're -> your text that some pedant complained about :-). Jeremy (jallison@whistle.com). (This used to be commit b11833f1bdecf1c3c3e5bc7494741605cba92a1e) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 94839c227a..c1c42be801 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -54,7 +54,7 @@ report a possible attack via the password buffer overflow bug static void overflow_attack(int len) { DEBUG(0,("ERROR: Invalid password length %d\n", len)); - DEBUG(0,("you're machine may be under attack by a user exploiting an old bug\n")); + DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); DEBUG(0,("Attack was from IP=%s\n", client_addr())); exit_server("possible attack"); } -- cgit From a0cd12e221af54e00aa7dd971c080881da8b32ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Sep 1997 02:38:19 +0000 Subject: dir.c: more pstrcpys. local.h: Add OPLOCK_BREAK_TIMEOUT. password.c: Fix for paranoia password server security bug. proto.h: Updated. reply.c: Oplock changes. server.c: Massive oplock changes - nearly there.... smb.h: oplock definitions. util.c: Add local message processing queues for oplocks. Jeremy (jallison@whistle.com) (This used to be commit 92f1553db2cdf6f32881eb984a87050cf3e4760b) --- source3/smbd/dir.c | 6 +- source3/smbd/password.c | 45 +++-- source3/smbd/reply.c | 11 +- source3/smbd/server.c | 456 ++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 421 insertions(+), 97 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 567bc14424..316b58818f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -470,12 +470,12 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) continue; - strcpy(fname,filename); + pstrcpy(fname,filename); *path = 0; - strcpy(path,Connections[cnum].dirpath); + pstrcpy(path,Connections[cnum].dirpath); if(needslash) strcat(path,"/"); - strcpy(pathreal,path); + pstrcpy(pathreal,path); strcat(path,fname); strcat(pathreal,dname); if (sys_stat(pathreal,&sbuf) != 0) diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 35f73eab2d..f4d94791cf 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1504,13 +1504,14 @@ BOOL check_hosts_equiv(char *user) int password_client = -1; static fstring pserver; +static char *secserver_inbuf = NULL; /**************************************************************************** attempted support for server level security ****************************************************************************/ BOOL server_cryptkey(char *buf) { - pstring inbuf,outbuf; + pstring outbuf; fstring pass_protocol; extern fstring remote_machine; char *p; @@ -1519,6 +1520,14 @@ BOOL server_cryptkey(char *buf) struct in_addr dest_ip; int port = SMB_PORT; BOOL ret; + + if(secserver_inbuf == NULL) { + secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if(secserver_inbuf == NULL) { + DEBUG(0,("server_cryptkey: malloc fail for input buffer.\n")); + return False; + } + } if (password_client >= 0) close(password_client); @@ -1530,7 +1539,7 @@ BOOL server_cryptkey(char *buf) strcpy(pass_protocol,"NT LM 0.12"); } - bzero(inbuf,sizeof(inbuf)); + bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); bzero(outbuf,sizeof(outbuf)); for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { @@ -1596,8 +1605,8 @@ BOOL server_cryptkey(char *buf) send_smb(password_client,outbuf); - if (!receive_smb(password_client,inbuf,5000) || - CVAL(inbuf,0) != 0x82) { + if (!receive_smb(password_client,secserver_inbuf,5000) || + CVAL(secserver_inbuf,0) != 0x82) { DEBUG(1,("%s rejected the session\n",pserver)); close(password_client); password_client = -1; return(False); @@ -1618,21 +1627,21 @@ BOOL server_cryptkey(char *buf) SSVAL(outbuf,smb_flg2,0x1); send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); + ret = receive_smb(password_client,secserver_inbuf,5000); - if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) { + if (!ret || CVAL(secserver_inbuf,smb_rcls) || SVAL(secserver_inbuf,smb_vwv0)) { DEBUG(1,("%s rejected the protocol\n",pserver)); close(password_client); password_client= -1; return(False); } - if (!(CVAL(inbuf,smb_vwv1) & 1)) { + if (!(CVAL(secserver_inbuf,smb_vwv1) & 1)) { DEBUG(1,("%s isn't in user level security mode\n",pserver)); close(password_client); password_client= -1; return(False); } - memcpy(buf,inbuf,smb_len(inbuf)+4); + memcpy(buf,secserver_inbuf,smb_len(secserver_inbuf)+4); DEBUG(3,("password server OK\n")); @@ -1644,15 +1653,23 @@ attempted support for server level security ****************************************************************************/ BOOL server_validate(char *buf) { - pstring inbuf,outbuf; + pstring outbuf; BOOL ret; + if(secserver_inbuf == NULL) { + secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if(secserver_inbuf == NULL) { + DEBUG(0,("server_validate: malloc fail for input buffer.\n")); + return False; + } + } + if (password_client < 0) { DEBUG(1,("%s not connected\n",pserver)); return(False); } - bzero(inbuf,sizeof(inbuf)); + bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); memcpy(outbuf,buf,sizeof(outbuf)); /* send a session setup command */ @@ -1662,18 +1679,18 @@ BOOL server_validate(char *buf) set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False); - SCVAL(inbuf,smb_rcls,1); + SCVAL(secserver_inbuf,smb_rcls,1); send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); + ret = receive_smb(password_client,secserver_inbuf,5000); - if (!ret || CVAL(inbuf,smb_rcls) != 0) { + if (!ret || CVAL(secserver_inbuf,smb_rcls) != 0) { DEBUG(1,("password server %s rejected the password\n",pserver)); return(False); } /* if logged in as guest then reject */ - if ((SVAL(inbuf,smb_vwv2) & 1) != 0) { + if ((SVAL(secserver_inbuf,smb_vwv2) & 1) != 0) { DEBUG(1,("password server %s gave us guest only\n",pserver)); return(False); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c1c42be801..8987e7c0c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -42,6 +42,7 @@ extern BOOL short_case_preserve; extern pstring sesssetup_user; extern fstring myworkgroup; extern int Client; +extern int global_oplock_break; /* this macro should always be used to extract an fnum (smb_fid) from a packet to ensure chaining works correctly */ @@ -388,7 +389,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); if (smb_apasslen > MAX_PASSWORD_LENGTH) + { overflow_attack(smb_apasslen); + } memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); pstrcpy(user,smb_buf(inbuf)+smb_apasslen); @@ -1163,7 +1166,7 @@ int reply_open(char *inbuf,char *outbuf) SSVAL(outbuf,smb_vwv6,rmode); if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - fsp->granted_oplock = True; + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } if(fsp->granted_oplock) @@ -1250,7 +1253,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - fsp->granted_oplock = True; + smb_action |= EXTENDED_OPLOCK_GRANTED; } if(fsp->granted_oplock) @@ -1377,7 +1380,7 @@ int reply_mknew(char *inbuf,char *outbuf) SSVAL(outbuf,smb_vwv0,fnum); if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - fsp->granted_oplock = True; + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } if(fsp->granted_oplock) @@ -1453,7 +1456,7 @@ int reply_ctemp(char *inbuf,char *outbuf) strcpy(smb_buf(outbuf) + 1,fname2); if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - fsp->granted_oplock = True; + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } if(fsp->granted_oplock) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d2ad803c9c..708a2c272b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -89,9 +89,11 @@ static int num_connections_open = 0; int oplock_sock = -1; uint16 oplock_port = 0; /* Current number of oplocks we have outstanding. */ -uint32 oplocks_open = 0; +uint32 global_oplocks_open = 0; #endif /* USE_OPLOCKS */ +BOOL global_oplock_break = False; + extern fstring remote_machine; pstring OriginalDir; @@ -1355,17 +1357,17 @@ void close_file(int fnum) fs_p->open = False; Connections[cnum].num_files_open--; if(fs_p->wbmpx_ptr) - { - free((char *)fs_p->wbmpx_ptr); - fs_p->wbmpx_ptr = NULL; - } + { + free((char *)fs_p->wbmpx_ptr); + fs_p->wbmpx_ptr = NULL; + } #if USE_MMAP if(fs_p->mmap_ptr) - { - munmap(fs_p->mmap_ptr,fs_p->mmap_size); - fs_p->mmap_ptr = NULL; - } + { + munmap(fs_p->mmap_ptr,fs_p->mmap_size); + fs_p->mmap_ptr = NULL; + } #endif if (lp_share_modes(SNUM(cnum))) @@ -1668,12 +1670,15 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, do { + broke_oplock = False; for(i = 0; i < num_shares; i++) { + min_share_mode_entry *share_entry = &old_shares[i]; + /* someone else has a share lock on it, check to see if we can too */ - if(check_share_mode(&old_shares[i], deny_mode, fname, fcbopen, &flags) == False) + if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) { free((char *)old_shares); unlock_share_entry(cnum, dev, inode, token); @@ -1688,23 +1693,31 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, * has an oplock on this file. If so we must break it before * continuing. */ - if(old_shares[i].op_type != 0) + if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) { + + DEBUG(5,("open file shared: breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); + /* Oplock break.... */ unlock_share_entry(cnum, dev, inode, token); -#if 0 /* Work in progress..... */ - if(break_oplock()) + if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); - /* Error condition here... */ + DEBUG(0,("open file shared: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; } lock_share_entry(cnum, dev, inode, &token); broke_oplock = True; break; -#endif } #endif /* USE_OPLOCKS */ - } + } /* end for */ + if(broke_oplock) { free((char *)old_shares); @@ -2312,6 +2325,52 @@ static BOOL open_sockets(BOOL is_daemon,int port) return True; } +/**************************************************************************** + process an smb from the client - split out from the process() code so + it can be used by the oplock break code. +****************************************************************************/ + +static void process_smb(char *inbuf, char *outbuf) +{ + extern int Client; + static int trans_num = 0; + + int msg_type = CVAL(inbuf,0); + int32 len = smb_len(outbuf); + int nread = len + 4; + + DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); + DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + +#ifdef WITH_VTP + if(trans_num == 1 && VT_Check(inbuf)) + { + VT_Process(); + return; + } +#endif + + if (msg_type == 0) + show_msg(inbuf); + + nread = construct_reply(inbuf,outbuf,nread,max_send); + + if(nread > 0) + { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); + + if (nread != smb_len(outbuf) + 4) + { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(outbuf))); + } + else + send_smb(Client,outbuf); + } + trans_num++; +} + #ifdef USE_OPLOCKS /**************************************************************************** open the oplock IPC socket communication @@ -2355,33 +2414,324 @@ static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) { int32 msg_len; int16 from_port; - struct in_addr from_addr; char *msg_start; - msg_len = IVAL(buffer,0); - from_port = SVAL(buffer,4); - memcpy((char *)&from_addr, &buffer[6], sizeof(struct in_addr)); + msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET); + from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET); + + msg_start = &buffer[UDP_CMD_HEADER_LEN]; + + DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", + msg_len, from_port)); + + /* Switch on message command - currently OPLOCK_BREAK_CMD is the + only valid request. */ + + switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET)) + { + case OPLOCK_BREAK_CMD: + /* Ensure that the msg length is correct. */ + if(msg_len != OPLOCK_BREAK_MSG_LEN) + { + DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \ +should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); + return False; + } + { + uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + struct sockaddr_in toaddr; + + DEBUG(5,("process_local_message: oplock break request from \ +pid %d, dev %d, inode %d\n", remotepid, dev, inode)); + + /* + * If we have no record of any currently open oplocks, + * it's not an error, as a close command may have + * just been issued on the file that was oplocked. + * Just return success in this case. + */ + + if(global_oplocks_open != 0) + { + if(oplock_break(dev, inode) == False) + { + DEBUG(0,("process_local_message: oplock break failed - \ +not returning udp message.\n")); + return False; + } + } + else + { + DEBUG(3,("process_local_message: oplock break requested with no outstanding \ +oplocks. Returning success.\n")); + } + + /* Send the message back after OR'ing in the 'REPLY' bit. */ + SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); + + bzero((char *)&toaddr,sizeof(toaddr)); + toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + toaddr.sin_port = htons(from_port); + toaddr.sin_family = AF_INET; + + if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) + { + DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", + remotepid, strerror(errno))); + return False; + } + } + break; + default: + DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", + (unsigned int)SVAL(msg_start,0))); + return False; + } + return True; +} + +/**************************************************************************** + Process an oplock break directly. +****************************************************************************/ +BOOL oplock_break(uint32 dev, uint32 inode) +{ + extern int Client; + static char *inbuf = NULL; + static char *outbuf = NULL; + files_struct *fsp = NULL; + int fnum; + + if(inbuf == NULL) + { + inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if(inbuf == NULL) { + DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); + return False; + } + outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if(outbuf == NULL) { + DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); + free(inbuf); + inbuf = NULL; + return False; + } + } + + /* We need to search the file open table for the + entry containing this dev and inode, and ensure + we have an oplock on it. */ + for( fnum = 0; fnum < MAX_OPEN_FILES; fnum++) + { + if(OPEN_FNUM(fnum)) + { + fsp = &Files[fnum]; + if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode)) + break; + } + } + + if(fsp == NULL) + { + /* The file could have been closed in the meantime - return success. */ + DEBUG(3,("oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ +allowing break to succeed.\n", dev, inode, fnum)); + return True; + } + + /* Ensure we have an oplock on the file */ + + /* Question - can a client asynchronously break an oplock ? Would it + ever do so ? If so this test is invalid for external smbd oplock + breaks and we should return True in these cases (JRA). + */ + + if(!fsp->granted_oplock) + { + DEBUG(0,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock.\n", + fsp->name, fnum, dev, inode)); + return False; + } + + /* Now comes the horrid part. We must send an oplock break to the client, + and then process incoming messages until we get a close or oplock release. + */ + + /* Prepare the SMBlockingX message. */ + bzero(outbuf,smb_size); + set_message(outbuf,8,0,True); + + SCVAL(outbuf,smb_com,SMBlockingX); + SSVAL(outbuf,smb_tid,fsp->cnum); + SSVAL(outbuf,smb_pid,0xFFFF); + SSVAL(outbuf,smb_uid,0); + SSVAL(outbuf,smb_mid,0xFFFF); + SCVAL(outbuf,smb_vwv0,0xFF); + SSVAL(outbuf,smb_vwv2,fnum); + SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); + /* Change this when we have level II oplocks. */ + SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE); + + send_smb(Client, outbuf); + + global_oplock_break = True; + + /* Process incoming messages. */ + while(global_oplock_break && OPEN_FNUM(fnum)) + { + if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) + { + if (smb_read_error == READ_EOF) + { + DEBUG(3,("oplock_break: end of file from client\n")); + return False; + } + + if (smb_read_error == READ_ERROR) + { + DEBUG(3,("oplock_break: receive_smb error (%s)\n", + strerror(errno))); + return False; + } + } + process_smb(inbuf, outbuf); + } + + return True; +} + +/**************************************************************************** +Send an oplock break message to another smbd process. If the oplock is held +by the local smbd then call the oplock break function directly. +****************************************************************************/ - msg_start = &buffer[6 + sizeof(struct in_addr)]; +BOOL request_oplock_break(min_share_mode_entry *share_entry, + uint32 dev, uint32 inode) +{ + char op_break_msg[OPLOCK_BREAK_MSG_LEN]; + struct sockaddr_in addr_out; + int pid = getpid(); + + if(pid == share_entry->pid) + { + /* We are breaking our own oplock, make sure it's us. */ + if(share_entry->op_port != oplock_port) + { + DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %x, port = %d \ +should be %d\n", pid, share_entry->op_port, oplock_port)); + return False; + } + /* Call oplock break direct. */ + return oplock_break(dev, inode); + } + + /* We need to send a OPLOCK_BREAK_CMD message to the + port in the share mode entry. */ - /* Validate message length. */ - if(msg_len > (buf_size - (6 + sizeof(struct in_addr)))) + SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); + SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); + SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); + SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); + + /* set the address and port */ + bzero((char *)&addr_out,sizeof(addr_out)); + addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_out.sin_port = htons( share_entry->op_port ); + addr_out.sin_family = AF_INET; + + DEBUG(3,("request_oplock_break: sending a oplock break message to pid %d on port %d \ +for dev = %x, inode = %x\n", share_entry->pid, share_entry->op_port, dev, inode)); + + if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, + (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - DEBUG(0,("process_local_message: invalid msg_len (%d) max can be %d\n", - msg_len, buf_size - (6 + sizeof(struct in_addr)))); + DEBUG(0,("request_oplock_break: failed when sending a oplock break message \ +to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", + share_entry->pid, share_entry->op_port, dev, inode, + strerror(errno))); return False; } - /* Validate message from address (must be localhost). */ - if(from_addr.s_addr != htonl(INADDR_LOOPBACK)) + /* + * Now we must await the oplock broken message coming back + * from the target smbd process. Timeout if it fails to + * return in OPLOCK_BREAK_TIMEOUT seconds. + * While we get messages that aren't ours, loop. + */ + + while(1) { - DEBUG(0,("process_local_message: invalid 'from' address \ -(was %x should be 127.0.0.1\n", from_addr.s_addr)); - return False; + char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; + int32 reply_msg_len; + int16 reply_from_port; + char *reply_msg_start; + + if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), + OPLOCK_BREAK_TIMEOUT * 1000) == False) + { + if(smb_read_error == READ_TIMEOUT) + DEBUG(0,("request_oplock_break: no response received to oplock break request to \ +pid %d on port %d for dev = %x, inode = %x\n", share_entry->pid, + share_entry->op_port, dev, inode)); + else + DEBUG(0,("request_oplock_break: error in response received to oplock break request to \ +pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid, + share_entry->op_port, dev, inode, strerror(errno))); + return False; + } + + /* + * If the response we got was not an answer to our message, but + * was a completely different request, push it onto the pending + * udp message stack so that we can deal with it in the main loop. + * It may be another oplock break request to us. + */ + + /* + * Local note from JRA. There exists the possibility of a denial + * of service attack here by allowing non-root processes running + * on a local machine sending many of these pending messages to + * a smbd port. Currently I'm not sure how to restrict the messages + * I will queue (although I could add a limit to the queue) to + * those received by root processes only. There should be a + * way to make this bulletproof.... + */ + + reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET); + reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET); + + reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN]; + + if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) + { + /* Ignore it. */ + DEBUG(0,("request_oplock_break: invalid message length received. Ignoring\n")); + continue; + } + + if(((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) == 0) || + (reply_from_port != share_entry->op_port) || + (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], + &op_break_msg[OPLOCK_BREAK_PID_OFFSET], + OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0)) + { + DEBUG(3,("request_oplock_break: received other message whilst awaiting \ +oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", + share_entry->pid, share_entry->op_port, dev, inode)); + if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) + return False; + } + + break; } + DEBUG(3,("request_oplock_break: broke oplock.\n")); + return True; } + #endif /* USE_OPLOCKS */ /**************************************************************************** @@ -4056,52 +4406,6 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) return(outsize); } -/**************************************************************************** - process an smb from the client - split out from the process() code so - it can be used by the oplock break code. -****************************************************************************/ - -static void process_smb(char *inbuf, char *outbuf) -{ - extern int Client; - static int trans_num = 0; - - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(outbuf); - int nread = len + 4; - - DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); - DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); - -#ifdef WITH_VTP - if(trans_num == 1 && VT_Check(inbuf)) - { - VT_Process(); - return; - } -#endif - - if (msg_type == 0) - show_msg(inbuf); - - nread = construct_reply(inbuf,outbuf,nread,max_send); - - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); - - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - send_smb(Client,outbuf); - } - trans_num++; -} - /**************************************************************************** process commands from the client ****************************************************************************/ -- cgit From 5864551aef50295addd1c8aa690a52870f70626d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Oct 1997 23:32:22 +0000 Subject: OPLOCK CHECK-IN - oplocks are now *OPERATIONAL* !!!! Yipeee. At least as far as I can check in a short time :-). local.h: Changed OPLOCK_BREAK_TIMEOUT to 30 seconds. locking.c: Big changes to delete oplocks on a share mode entry. proto.h: updated. reply.c: Added oplock break code in lockingX reply & readbraw reply. server.c: Add batch oplock code. Force server shutdown if client fails to respond to oplock break. smb.h: Fix silly slow share mode oplock define bug. status.c: Add oplock status info. Jeremy (jallison@whistle.com) (This used to be commit 4c83d37239f15f855fc10f01d7b4bf4217fb9eda) --- source3/smbd/reply.c | 57 ++++++++++++++- source3/smbd/server.c | 199 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 226 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8987e7c0c2..1a896aa02a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1254,10 +1254,13 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { smb_action |= EXTENDED_OPLOCK_GRANTED; + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } - if(fsp->granted_oplock) + if(fsp->granted_oplock) { smb_action |= EXTENDED_OPLOCK_GRANTED; + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + } set_message(outbuf,15,0,True); SSVAL(outbuf,smb_vwv2,fnum); @@ -1609,6 +1612,22 @@ int reply_readbraw(char *inbuf, char *outbuf) int fd; char *fname; +#ifdef USE_OPLOCKS + /* + * Special check if an oplock break has been issued + * and the readraw request croses on the wire, we must + * return a zero length response here. + */ + + if(global_oplock_break) + { + _smb_setlen(header,0); + transfer_file(0,Client,0,header,4,0); + DEBUG(5,("readbraw - oplock break finished\n")); + return -1; + } +#endif + cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); @@ -3342,7 +3361,10 @@ int reply_setdir(char *inbuf,char *outbuf) int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) { int fnum = GETFNUM(inbuf,smb_vwv2); - uint16 locktype = SVAL(inbuf,smb_vwv3); + unsigned char locktype = CVAL(inbuf,smb_vwv3); +#if 0 + unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); +#endif /* USE_OPLOCKS */ uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -3359,6 +3381,35 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) CHECK_ERROR(fnum); data = smb_buf(inbuf); + +#ifdef USE_OPLOCKS + /* Check if this is an oplock break on a file + we have granted an oplock on. + */ + if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) && + (num_ulocks == 0) && (num_locks == 0) && + (CVAL(inbuf,smb_vwv0) == 0xFF)) + { + DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", + fnum)); + /* + * Make sure we have granted an oplock on this file. + */ + if(!Files[fnum].granted_oplock) + { + DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ +oplock granted on this file.\n", fnum)); + return ERROR(ERRDOS,ERRlock); + } + + /* Just clear the granted flag and return. oplock_break() + will handle changing the share_mode_entry. */ + + Files[fnum].granted_oplock = 0; + return -1; + } +#endif /* USE_OPLOCKS */ + /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { @@ -3393,7 +3444,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,2,0,True); DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", - timestring(),fnum,cnum,locktype,num_locks,num_ulocks)); + timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks)); chain_fnum = fnum; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 708a2c272b..5f59af1bf1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1458,23 +1458,74 @@ BOOL check_file_sharing(int cnum,char *fname) struct stat sbuf; share_lock_token token; int pid = getpid(); + uint32 dev, inode; if(!lp_share_modes(SNUM(cnum))) return True; if (stat(fname,&sbuf) == -1) return(True); - lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token); - num_share_modes = get_share_modes(cnum, token, - (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares); + dev = (uint32)sbuf.st_dev; + inode = (uint32)sbuf.st_ino; - for( i = 0; i < num_share_modes; i++) + lock_share_entry(cnum, dev, inode, &token); + num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + + /* + * Check if the share modes will give us access. + */ + + if(num_share_modes != 0) { - if (old_shares[i].share_mode != DENY_DOS) - goto free_and_exit; + BOOL broke_oplock; + + do + { + + broke_oplock = False; + for(i = 0; i < num_share_modes; i++) + { + min_share_mode_entry *share_entry = &old_shares[i]; + + /* someone else has a share lock on it, check to see + if we can too */ + if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) + goto free_and_exit; + +#ifdef USE_OPLOCKS + /* + * The share modes would give us access. Check if someone + * has an oplock on this file. If so we must break it before + * continuing. + */ + if(share_entry->op_type & BATCH_OPLOCK) + { + + DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - if(old_shares[i].pid != pid) - goto free_and_exit; + /* Oplock break.... */ + unlock_share_entry(cnum, dev, inode, token); + if(request_oplock_break(share_entry, dev, inode) == False) + { + free((char *)old_shares); + DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); + return False; + } + lock_share_entry(cnum, dev, inode, &token); + broke_oplock = True; + break; + } +#endif /* USE_OPLOCKS */ + } /* end for */ + + if(broke_oplock) + { + free((char *)old_shares); + num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + } + } while(broke_oplock); } /* XXXX exactly what share mode combinations should be allowed for @@ -1485,7 +1536,7 @@ BOOL check_file_sharing(int cnum,char *fname) free_and_exit: - unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token); + unlock_share_entry(cnum, dev, inode, token); if(old_shares != NULL) free((char *)old_shares); return(ret); @@ -1576,6 +1627,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, share_lock_token token; uint32 dev = 0; uint32 inode = 0; + int num_share_modes = 0; fs_p->open = False; fs_p->fd_ptr = 0; @@ -1647,7 +1699,6 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (lp_share_modes(SNUM(cnum))) { - int num_shares = 0; int i; min_share_mode_entry *old_shares = 0; @@ -1657,14 +1708,14 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, inode = (uint32)sbuf.st_ino; lock_share_entry(cnum, dev, inode, &token); share_locked = True; - num_shares = get_share_modes(cnum, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); } /* * Check if the share modes will give us access. */ - if(share_locked && (num_shares != 0)) + if(share_locked && (num_share_modes != 0)) { BOOL broke_oplock; @@ -1672,7 +1723,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { broke_oplock = False; - for(i = 0; i < num_shares; i++) + for(i = 0; i < num_share_modes; i++) { min_share_mode_entry *share_entry = &old_shares[i]; @@ -1696,7 +1747,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) { - DEBUG(5,("open file shared: breaking oplock (%x) on file %s, \ + DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); /* Oplock break.... */ @@ -1704,7 +1755,7 @@ dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); - DEBUG(0,("open file shared: FAILED when breaking oplock (%x) on file %s, \ + DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); errno = EACCES; unix_ERR_class = ERRDOS; @@ -1721,7 +1772,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if(broke_oplock) { free((char *)old_shares); - num_shares = get_share_modes(cnum, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); } } while(broke_oplock); } @@ -1782,7 +1833,27 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); file (which expects the share_mode_entry to be there). */ if (lp_share_modes(SNUM(cnum))) - set_share_mode(token, fnum, 0, 0); + { + uint16 port = 0; +#ifdef USE_OPLOCKS + /* JRA. Currently this only services Exlcusive and batch + oplocks (no other opens on this file). This needs to + be extended to level II oplocks (multiple reader + oplocks). */ + + if(oplock_request && (num_share_modes == 0)) + { + fs_p->granted_oplock = True; + global_oplocks_open++; + port = oplock_port; + + DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ +dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); + } + +#endif /* USE_OPLOCKS */ + set_share_mode(token, fnum, port, oplock_request); + } if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fnum,cnum,token,&share_locked); @@ -2444,7 +2515,7 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); struct sockaddr_in toaddr; DEBUG(5,("process_local_message: oplock break request from \ -pid %d, dev %d, inode %d\n", remotepid, dev, inode)); +pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); /* * If we have no record of any currently open oplocks, @@ -2483,6 +2554,11 @@ oplocks. Returning success.\n")); remotepid, strerror(errno))); return False; } + + DEBUG(5,("process_local_message: oplock break reply sent to \ +pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, + from_port, dev, inode)); + } break; default: @@ -2503,6 +2579,9 @@ BOOL oplock_break(uint32 dev, uint32 inode) static char *outbuf = NULL; files_struct *fsp = NULL; int fnum; + share_lock_token token; + time_t start_time; + BOOL shutdown_server = False; if(inbuf == NULL) { @@ -2579,24 +2658,90 @@ allowing break to succeed.\n", dev, inode, fnum)); global_oplock_break = True; /* Process incoming messages. */ - while(global_oplock_break && OPEN_FNUM(fnum)) + + /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT + seconds we should just die.... */ + + start_time = time(NULL); + + while(OPEN_FNUM(fnum) && fsp->granted_oplock) { if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) { + /* + * Die if we got an error. + */ + if (smb_read_error == READ_EOF) - { - DEBUG(3,("oplock_break: end of file from client\n")); - return False; - } + DEBUG(0,("oplock_break: end of file from client\n")); if (smb_read_error == READ_ERROR) - { - DEBUG(3,("oplock_break: receive_smb error (%s)\n", + DEBUG(0,("oplock_break: receive_smb error (%s)\n", strerror(errno))); - return False; - } + + if (smb_read_error == READ_TIMEOUT) + DEBUG(0,("oplock_break: receive_smb timed out after %d seconds.\n", + OPLOCK_BREAK_TIMEOUT)); + + DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ +inode = %x).\n", fsp->name, fnum, dev, inode)); + shutdown_server = True; + break; } process_smb(inbuf, outbuf); + + /* We only need this in case a readraw crossed on the wire. */ + global_oplock_break = False; + + /* + * Die if we go over the time limit. + */ + + if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) + { + DEBUG(0,("oplock_break: no break received from client within \ +%d seconds.\n", OPLOCK_BREAK_TIMEOUT)); + DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ +inode = %x).\n", fsp->name, fnum, dev, inode)); + shutdown_server = True; + break; + } + } + + /* + * If the client did not respond we must die. + */ + + if(shutdown_server) + { + DEBUG(0,("oplock_break: client failure in break - shutting down this smbd.\n")); + close_sockets(); + close(oplock_sock); + exit_server("oplock break failure"); + } + + if(OPEN_FNUM(fnum)) + { + /* Remove the oplock flag from the sharemode. */ + lock_share_entry(fsp->cnum, dev, inode, &token); + if(remove_share_oplock( fnum, token)==False) + { + DEBUG(0,("oplock_break: failed to remove share oplock for fnum %d, \ +dev = %x, inode = %x\n", fnum, dev, inode)); + unlock_share_entry(fsp->cnum, dev, inode, token); + return False; + } + unlock_share_entry(fsp->cnum, dev, inode, token); + } + + global_oplocks_open--; + + /* Santity check - remove this later. JRA */ + if(global_oplocks_open < 0) + { + DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", + global_oplocks_open)); + abort(); } return True; -- cgit From c557bb0517c3d1ad908f906a60b43bd604289f88 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 1997 00:57:59 +0000 Subject: Fixed problem with oplock_type being set with no port. Jeremy (jallison@whistle.com) (This used to be commit 90484db0bfe25a096def627f94be24f3fa243375) --- source3/smbd/server.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5f59af1bf1..5477230943 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1849,8 +1849,16 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); - } + } + else + { + port = 0; + oplock_request = 0; + } +#else /* USE_OPLOCKS */ + oplock_request = 0; + port = 0; #endif /* USE_OPLOCKS */ set_share_mode(token, fnum, port, oplock_request); } @@ -2764,7 +2772,7 @@ BOOL request_oplock_break(min_share_mode_entry *share_entry, /* We are breaking our own oplock, make sure it's us. */ if(share_entry->op_port != oplock_port) { - DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %x, port = %d \ + DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ should be %d\n", pid, share_entry->op_port, oplock_port)); return False; } -- cgit From c9cf77a6bb245145dce3cd96ff4267fe226a1019 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 1997 02:36:11 +0000 Subject: Modified some debug messages, moved from 5 -> 8. Jeremy (jallison@whistle.com) (This used to be commit cb83c74a6ccfc44721af65b75625a949782c758a) --- source3/smbd/server.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5477230943..b9bdbaa655 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -189,7 +189,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) int result = 0; extern struct current_user current_user; - DEBUG(5,("dos_mode: %d %s\n", cnum, path)); + DEBUG(8,("dos_mode: %d %s\n", cnum, path)); if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) { if (!((sbuf->st_mode & S_IWOTH) || @@ -241,15 +241,15 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aHIDDEN; } - DEBUG(5,("dos_mode returning ")); + DEBUG(8,("dos_mode returning ")); - if (result & aHIDDEN) DEBUG(5, ("h")); - if (result & aRONLY ) DEBUG(5, ("r")); - if (result & aSYSTEM) DEBUG(5, ("s")); - if (result & aDIR ) DEBUG(5, ("d")); - if (result & aARCH ) DEBUG(5, ("a")); + if (result & aHIDDEN) DEBUG(8, ("h")); + if (result & aRONLY ) DEBUG(8, ("r")); + if (result & aSYSTEM) DEBUG(8, ("s")); + if (result & aDIR ) DEBUG(8, ("d")); + if (result & aARCH ) DEBUG(8, ("a")); - DEBUG(5,("\n")); + DEBUG(8,("\n")); return(result); } -- cgit From 85097a7c177977c3e0cb9b2ad41642dba5f917ac Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Oct 1997 03:14:32 +0000 Subject: change the semantics of hosts allow/hosts deny so that a global setting applies to all shares regardless of any settings on other shares. This allows us to immediately drop a connection if it does not come from a allowed host, without even parsing the first SMB packet. The next time we get a nasty security hole we can offer people the option of just setting their hosts allow line. If we drop a connection in this way we generate a "Not listening for calling name" response and then exit. add a per share "oplocks" option in smb.conf. I think its important to be able to disable oplocks on a per-share basis as there are occasions then they are definately not wanted, for example when sharing data between a windows box and a unix application. This also allows us to tell people "try disabling oplocks" when diagnosing problems. fix a bug in process_smb(). It was taking the length of the packet from outbuf, not inbuf (this bug was introduced with the oplocks code). Jeremy, I assume this wasn't deliberate? (This used to be commit 44bc9f239aa0b3cdf6cf9ad8d3911e397eba7335) --- source3/smbd/server.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b9bdbaa655..7b04d228c3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1841,7 +1841,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); be extended to level II oplocks (multiple reader oplocks). */ - if(oplock_request && (num_share_modes == 0)) + if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum))) { fs_p->granted_oplock = True; global_oplocks_open++; @@ -2412,12 +2412,27 @@ static BOOL open_sockets(BOOL is_daemon,int port) static void process_smb(char *inbuf, char *outbuf) { extern int Client; - static int trans_num = 0; - + static int trans_num; int msg_type = CVAL(inbuf,0); - int32 len = smb_len(outbuf); + int32 len = smb_len(inbuf); int nread = len + 4; + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (!check_access(-1)) { + /* send a negative session response "not listining on calling + name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG(1,("%s Connection denied from %s\n", + timestring(),client_addr())); + send_smb(Client,buf); + exit_server("connection denied"); + } + } + DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); -- cgit From fbd5dded7dd027faa549f854b45f47b72af47528 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 1997 03:26:07 +0000 Subject: Added debug message for oplock_break(). Jeremy (jallison@whistle.com) (This used to be commit 4f29dfbc791f1f08c8c44a6fbdd0bc31892455dd) --- source3/smbd/server.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7b04d228c3..a3214e16cb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -89,7 +89,7 @@ static int num_connections_open = 0; int oplock_sock = -1; uint16 oplock_port = 0; /* Current number of oplocks we have outstanding. */ -uint32 global_oplocks_open = 0; +int32 global_oplocks_open = 0; #endif /* USE_OPLOCKS */ BOOL global_oplock_break = False; @@ -2606,6 +2606,9 @@ BOOL oplock_break(uint32 dev, uint32 inode) time_t start_time; BOOL shutdown_server = False; + DEBUG(5,("oplock_break: called for dev = %x, inode = %x. Current \ +global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); + if(inbuf == NULL) { inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); @@ -2767,6 +2770,9 @@ dev = %x, inode = %x\n", fnum, dev, inode)); abort(); } + DEBUG(5,("oplock_break: returning success for dev = %x, inode = %x. Current \ +global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); + return True; } -- cgit From a69125bae97619580134dfd38f1952f37b2bbcec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Oct 1997 14:11:34 +0000 Subject: change a debug level in reply.c change from ERRbaddirectory to ERRbadpath for ENOTDIR errors. This reverts to the old Samba code. I've done quite a bit of testing against NT4 and have yet to get it to produce the ERRbaddirectory error code. Producing ERRbaddirectory made a visual basic application that was sent to me not run. This might explain some of the "it doesn't work any more" complaints we've got about 1.9.17. Jeremy, can you remember how you got NT to produce ERRbaddirectory? There might be some specific circumstances we need to cover. (This used to be commit 1ed901ddffef48cdce87017bab0fd613e6ca8637) --- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1a896aa02a..aa3f43a813 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -599,7 +599,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); - DEBUG(1,(" Client requested max send size of %d\n", max_send)); + DEBUG(6,("Client requested max send size of %d\n", max_send)); done_sesssetup = True; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a3214e16cb..19cc5b9abb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2110,7 +2110,7 @@ struct {EPERM,ERRDOS,ERRnoaccess}, {EACCES,ERRDOS,ERRnoaccess}, {ENOENT,ERRDOS,ERRbadfile}, - {ENOTDIR,ERRDOS,ERRbaddirectory}, + {ENOTDIR,ERRDOS,ERRbadpath}, {EIO,ERRHRD,ERRgeneral}, {EBADF,ERRSRV,ERRsrverror}, {EINVAL,ERRSRV,ERRsrverror}, -- cgit From 4438d7b57e459e091017fcbe18547a8b69be4d80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 1997 03:15:24 +0000 Subject: proto.h: Updated. server.c: Updated after netbench observation. Oplocks must be broken *before* share modes are checked, not after. Netbench seems to be working now. smb.h: Added offsets for oplock break time fields. trans2.c: Upped debug messages. util.c: Upped debug messages. Jeremy (jallison@whistle.com) (This used to be commit bc4b70c566ed5fa926441fb64a0f756a6137d8d0) --- source3/smbd/server.c | 74 ++++++++++++++++++++++++++++++++------------------- source3/smbd/trans2.c | 2 +- 2 files changed, 47 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 19cc5b9abb..d7620a5804 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1404,7 +1404,8 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - if (old_deny == new_deny && share_pid == getpid()) + int pid = getpid(); + if (old_deny == new_deny && share_pid == pid) return(AALL); if (old_mode == 0) return(AREAD); @@ -1487,16 +1488,12 @@ BOOL check_file_sharing(int cnum,char *fname) { min_share_mode_entry *share_entry = &old_shares[i]; - /* someone else has a share lock on it, check to see - if we can too */ - if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) - goto free_and_exit; - #ifdef USE_OPLOCKS /* - * The share modes would give us access. Check if someone - * has an oplock on this file. If so we must break it before - * continuing. + * Break oplocks before checking share modes. See comment in + * open_file_shared for details. + * Check if someone has an oplock on this file. If so we must + * break it before continuing. */ if(share_entry->op_type & BATCH_OPLOCK) { @@ -1518,6 +1515,12 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); break; } #endif /* USE_OPLOCKS */ + + /* someone else has a share lock on it, check to see + if we can too */ + if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) + goto free_and_exit; + } /* end for */ if(broke_oplock) @@ -1727,22 +1730,13 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { min_share_mode_entry *share_entry = &old_shares[i]; - /* someone else has a share lock on it, check to see - if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) - { - free((char *)old_shares); - unlock_share_entry(cnum, dev, inode, token); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } #ifdef USE_OPLOCKS /* - * The share modes would give us access. Check if someone - * has an oplock on this file. If so we must break it before - * continuing. + * By observation of NetBench, oplocks are broken *before* share + * modes are checked. This allows a file to be closed by the client + * if the share mode would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so we must break + * it before continuing. */ if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) { @@ -1767,6 +1761,19 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); break; } #endif /* USE_OPLOCKS */ + + /* someone else has a share lock on it, check to see + if we can too */ + if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) + { + free((char *)old_shares); + unlock_share_entry(cnum, dev, inode, token); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + } /* end for */ if(broke_oplock) @@ -2428,7 +2435,7 @@ static void process_smb(char *inbuf, char *outbuf) static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG(1,("%s Connection denied from %s\n", timestring(),client_addr())); - send_smb(Client,buf); + send_smb(Client,(char *)buf); exit_server("connection denied"); } } @@ -2535,8 +2542,12 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + struct timeval tval; struct sockaddr_in toaddr; + tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); + tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); + DEBUG(5,("process_local_message: oplock break request from \ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); @@ -2549,7 +2560,7 @@ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); if(global_oplocks_open != 0) { - if(oplock_break(dev, inode) == False) + if(oplock_break(dev, inode, &tval) == False) { DEBUG(0,("process_local_message: oplock break failed - \ not returning udp message.\n")); @@ -2595,7 +2606,7 @@ pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, /**************************************************************************** Process an oplock break directly. ****************************************************************************/ -BOOL oplock_break(uint32 dev, uint32 inode) +BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { extern int Client; static char *inbuf = NULL; @@ -2633,7 +2644,9 @@ global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); if(OPEN_FNUM(fnum)) { fsp = &Files[fnum]; - if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode)) + if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) && + (fsp->open_time.tv_sec == tval->tv_sec) && + (fsp->open_time.tv_usec == tval->tv_usec)) break; } } @@ -2797,8 +2810,11 @@ BOOL request_oplock_break(min_share_mode_entry *share_entry, should be %d\n", pid, share_entry->op_port, oplock_port)); return False; } + + DEBUG(5,("request_oplock_break: breaking our own oplock\n")); + /* Call oplock break direct. */ - return oplock_break(dev, inode); + return oplock_break(dev, inode, &share_entry->time); } /* We need to send a OPLOCK_BREAK_CMD message to the @@ -2808,6 +2824,8 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); + SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); + SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); /* set the address and port */ bzero((char *)&addr_out,sizeof(addr_out)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8ab024ded2..56f153f12f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -319,7 +319,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l reskey = TellDir(Connections[cnum].dirptr); - DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", + DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); if (!dname) -- cgit From 2534e0688ba703423c9d18b3296b00c097aa351d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Oct 1997 03:34:19 +0000 Subject: add "static" to a couple of functions that are only used locally. set granted_oplock=False at the start of open_file(). This is paranoia. (This used to be commit c7f09ffd4a00ef7266e3f54536ee6aaca9335fb8) --- source3/smbd/server.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d7620a5804..9af1a88062 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -886,8 +886,7 @@ static void check_for_pipe(char *fname) /**************************************************************************** fd support routines - attempt to do a sys_open ****************************************************************************/ - -int fd_attempt_open(char *fname, int flags, int mode) +static int fd_attempt_open(char *fname, int flags, int mode) { int fd = sys_open(fname,flags,mode); @@ -939,7 +938,7 @@ int fd_attempt_open(char *fname, int flags, int mode) fd support routines - attempt to find an already open file by dev and inode - increments the ref_count of the returned file_fd_struct *. ****************************************************************************/ -file_fd_struct *fd_get_already_open(struct stat *sbuf) +static file_fd_struct *fd_get_already_open(struct stat *sbuf) { int i; file_fd_struct *fd_ptr; @@ -966,7 +965,7 @@ file_fd_struct *fd_get_already_open(struct stat *sbuf) fd support routines - attempt to find a empty slot in the FileFd array. Increments the ref_count of the returned entry. ****************************************************************************/ -file_fd_struct *fd_get_new() +static file_fd_struct *fd_get_new() { int i; file_fd_struct *fd_ptr; @@ -999,8 +998,7 @@ n")); fd support routines - attempt to re-open an already open fd as O_RDWR. Save the already open fd (we cannot close due to POSIX file locking braindamage. ****************************************************************************/ - -void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) +static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) { int fd = sys_open( fname, O_RDWR, mode); @@ -1020,7 +1018,7 @@ void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ -int fd_attempt_close(file_fd_struct *fd_ptr) +static int fd_attempt_close(file_fd_struct *fd_ptr) { DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", fd_ptr - &FileFd[0], @@ -1060,6 +1058,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fsp->open = False; fsp->fd_ptr = 0; + fsp->granted_oplock = False; errno = EPERM; pstrcpy(fname,fname1); -- cgit From 2f7b04061e61df7dcc1029b71fe12ca4dfca5f10 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Oct 1997 20:36:06 +0000 Subject: locking.c: Fixed incorrect parameter count in debug statements. May explain solaris crashes. reply.c: Added NT specific error code. Put oplock break code in correct place in reply_lockingX. server.c: Removed unneeded error mapping stuff. Fixed race condition in oplock code. trans2.c: Added NT specific error code. util.c: Added paranoia check in interpret_addr. Some core dumps reported here. Upped fcntl debug levels. Andrew. Please check the NT specific error code handling (search for the string "/* Ugly - NT specific hack - but needed (JRA) */", this makes NT and 95 clients behave correctly here - please check your Visual Basic apps with this code. Jeremy (jallison@whistle.com). (This used to be commit 97ee4a5f69bd9cfbbc8710a1a04d80db0ee40104) --- source3/smbd/reply.c | 34 +++++++++++++++++++---- source3/smbd/server.c | 74 ++++++++++++--------------------------------------- source3/smbd/trans2.c | 17 ++++++++++++ 3 files changed, 63 insertions(+), 62 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index aa3f43a813..a8f674183c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -640,6 +640,15 @@ int reply_chkpth(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + + /* Ugly - NT specific hack - but needed (JRA) */ + if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && + (get_remote_arch() == RA_WINNT)) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbaddirectory; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -3390,22 +3399,37 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) (num_ulocks == 0) && (num_locks == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF)) { + share_lock_token token; + files_struct *fsp = &Files[fnum]; + uint32 dev = fsp->fd_ptr->dev; + uint32 inode = fsp->fd_ptr->inode; + DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", fnum)); /* * Make sure we have granted an oplock on this file. */ - if(!Files[fnum].granted_oplock) + if(!fsp->granted_oplock) { DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ -oplock granted on this file.\n", fnum)); +no oplock granted on this file.\n", fnum)); return ERROR(ERRDOS,ERRlock); } - /* Just clear the granted flag and return. oplock_break() - will handle changing the share_mode_entry. */ + /* Remove the oplock flag from the sharemode. */ + lock_share_entry(fsp->cnum, dev, inode, &token); + if(remove_share_oplock( fnum, token)==False) + { + DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ +dev = %x, inode = %x\n", fnum, dev, inode)); + unlock_share_entry(fsp->cnum, dev, inode, token); + return -1; + } + unlock_share_entry(fsp->cnum, dev, inode, token); + + /* Clear the granted flag and return. */ - Files[fnum].granted_oplock = 0; + fsp->granted_oplock = False; return -1; } #endif /* USE_OPLOCKS */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9af1a88062..52869505c0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2137,20 +2137,6 @@ struct {0,0,0} }; -/* Mapping for old clients. */ - -struct -{ - int new_smb_error; - int old_smb_error; - int protocol_level; - enum remote_arch_types valid_ra_type; -} old_client_errmap[] = -{ - {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, RA_WINNT}, - {0,0,0} -}; - /**************************************************************************** create an error packet from errno ****************************************************************************/ @@ -2181,29 +2167,6 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int } } - /* Make sure we don't return error codes that old - clients don't understand. */ - - /* JRA - unfortunately, WinNT needs some error codes - for apps to work correctly, Win95 will break if - these error codes are returned. But they both - negotiate the *same* protocol. So we need to use - the revolting 'remote_arch' enum to tie break. - - There must be a better way of doing this... - */ - - for(i = 0; old_client_errmap[i].new_smb_error != 0; i++) - { - if(((Protocol < old_client_errmap[i].protocol_level) || - (old_client_errmap[i].valid_ra_type != get_remote_arch())) && - (old_client_errmap[i].new_smb_error == ecode)) - { - ecode = old_client_errmap[i].old_smb_error; - break; - } - } - return(error_packet(inbuf,outbuf,eclass,ecode,line)); } @@ -2612,7 +2575,6 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) static char *outbuf = NULL; files_struct *fsp = NULL; int fnum; - share_lock_token token; time_t start_time; BOOL shutdown_server = False; @@ -2660,16 +2622,19 @@ allowing break to succeed.\n", dev, inode, fnum)); /* Ensure we have an oplock on the file */ - /* Question - can a client asynchronously break an oplock ? Would it - ever do so ? If so this test is invalid for external smbd oplock - breaks and we should return True in these cases (JRA). + /* There is a potential race condition in that an oplock could + have been broken due to another udp request, and yet there are + still oplock break messages being sent in the udp message + queue for this file. So return true if we don't have an oplock, + as we may have just freed it. But this is an unusual case so + we should log a message at low debug priority (1). */ if(!fsp->granted_oplock) { - DEBUG(0,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock.\n", - fsp->name, fnum, dev, inode)); - return False; + DEBUG(1,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ +Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode)); + return True; } /* Now comes the horrid part. We must send an oplock break to the client, @@ -2729,7 +2694,8 @@ inode = %x).\n", fsp->name, fnum, dev, inode)); process_smb(inbuf, outbuf); /* We only need this in case a readraw crossed on the wire. */ - global_oplock_break = False; + if(global_oplock_break) + global_oplock_break = False; /* * Die if we go over the time limit. @@ -2760,16 +2726,10 @@ inode = %x).\n", fsp->name, fnum, dev, inode)); if(OPEN_FNUM(fnum)) { - /* Remove the oplock flag from the sharemode. */ - lock_share_entry(fsp->cnum, dev, inode, &token); - if(remove_share_oplock( fnum, token)==False) - { - DEBUG(0,("oplock_break: failed to remove share oplock for fnum %d, \ -dev = %x, inode = %x\n", fnum, dev, inode)); - unlock_share_entry(fsp->cnum, dev, inode, token); - return False; - } - unlock_share_entry(fsp->cnum, dev, inode, token); + /* The lockingX reply will have removed the oplock flag + from the sharemode. */ + /* Paranoia.... */ + fsp->granted_oplock = False; } global_oplocks_open--; @@ -2782,8 +2742,8 @@ dev = %x, inode = %x\n", fnum, dev, inode)); abort(); } - DEBUG(5,("oplock_break: returning success for dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); + DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ +global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open)); return True; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 56f153f12f..7f46604cce 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -607,6 +607,15 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + + /* Ugly - NT specific hack - but needed (JRA) */ + if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && + (get_remote_arch() == RA_WINNT)) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbaddirectory; + } + return(ERROR(ERRDOS,ERRbadpath)); } @@ -641,6 +650,14 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + + /* Ugly - NT specific hack - but needed (JRA) */ + if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && + (get_remote_arch() == RA_WINNT)) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbaddirectory; + } return (UNIXERROR(ERRDOS,ERRbadpath)); } return(ERROR(ERRDOS,ERRbadpath)); -- cgit From 3c5998e29be2ce035d71b211aa992e38b5cf7904 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 4 Oct 1997 00:23:57 +0000 Subject: Race condition with multiple oplock break requests happens more often than you might think (reproduced here with 4 clients and netbench :-). Raising debug log level for report from 1 to 3. Jeremy (jallison@whistle.com) (This used to be commit 23eeab7aa2e9c935e1f48ce3449544c03c1c899f) --- source3/smbd/server.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 52869505c0..b250572a1f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2626,13 +2626,12 @@ allowing break to succeed.\n", dev, inode, fnum)); have been broken due to another udp request, and yet there are still oplock break messages being sent in the udp message queue for this file. So return true if we don't have an oplock, - as we may have just freed it. But this is an unusual case so - we should log a message at low debug priority (1). + as we may have just freed it. */ if(!fsp->granted_oplock) { - DEBUG(1,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ + DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode)); return True; } -- cgit From 5059fbf44f5b427f93081d1090f4f2c818b01478 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Oct 1997 05:24:02 +0000 Subject: fix some "shadows global" errors. (This used to be commit 25b7ada3587d1fe68164a2339d7f0fbcecf18e53) --- source3/smbd/server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b250572a1f..826b17121f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2441,7 +2441,7 @@ static void process_smb(char *inbuf, char *outbuf) static BOOL open_oplock_ipc() { struct sockaddr_in sock_name; - int name_len = sizeof(sock_name); + int len = sizeof(sock_name); DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); @@ -2456,7 +2456,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); } /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &name_len)<0) + if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) { DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", strerror(errno))); @@ -2473,7 +2473,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); /**************************************************************************** process an oplock break message. ****************************************************************************/ -static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) +static BOOL process_local_message(int sock, char *buffer, int buf_size) { int32 msg_len; int16 from_port; @@ -2543,7 +2543,7 @@ oplocks. Returning success.\n")); toaddr.sin_port = htons(from_port); toaddr.sin_family = AF_INET; - if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", -- cgit From 2e92be3aaf01c574d32d1a10e1359888638b68bc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 1997 17:52:25 +0000 Subject: client.c: Changed shadowed variable. locking.c: Removed USE_OPLOCKS - now the default. params.c: Removed unused variable. proto.h: Updated. reply.c: Removed USE_OPLOCKS - now the default. server.c: Removed USE_OPLOCKS - now the default. smb.h: Removed USE_OPLOCKS - now the default. smbparse.c: Changed shadowed variable. status.c: Removed USE_OPLOCKS - now the default. util.c: Removed USE_OPLOCKS - now the default. Jeremy (jallison@whistle.com) (This used to be commit b93509846d6291771787af457500eec8984ee6bd) --- source3/smbd/reply.c | 6 +----- source3/smbd/server.c | 26 -------------------------- 2 files changed, 1 insertion(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a8f674183c..fa641931eb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1621,7 +1621,6 @@ int reply_readbraw(char *inbuf, char *outbuf) int fd; char *fname; -#ifdef USE_OPLOCKS /* * Special check if an oplock break has been issued * and the readraw request croses on the wire, we must @@ -1635,7 +1634,6 @@ int reply_readbraw(char *inbuf, char *outbuf) DEBUG(5,("readbraw - oplock break finished\n")); return -1; } -#endif cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); @@ -3373,7 +3371,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) unsigned char locktype = CVAL(inbuf,smb_vwv3); #if 0 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); -#endif /* USE_OPLOCKS */ +#endif uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -3391,7 +3389,6 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) data = smb_buf(inbuf); -#ifdef USE_OPLOCKS /* Check if this is an oplock break on a file we have granted an oplock on. */ @@ -3432,7 +3429,6 @@ dev = %x, inode = %x\n", fnum, dev, inode)); fsp->granted_oplock = False; return -1; } -#endif /* USE_OPLOCKS */ /* Data now points at the beginning of the list of smb_unlkrng structs */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 826b17121f..4f5b01ba91 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -84,13 +84,11 @@ int chain_fnum = -1; /* number of open connections */ static int num_connections_open = 0; -#ifdef USE_OPLOCKS /* Oplock ipc UDP socket. */ int oplock_sock = -1; uint16 oplock_port = 0; /* Current number of oplocks we have outstanding. */ int32 global_oplocks_open = 0; -#endif /* USE_OPLOCKS */ BOOL global_oplock_break = False; @@ -1487,7 +1485,6 @@ BOOL check_file_sharing(int cnum,char *fname) { min_share_mode_entry *share_entry = &old_shares[i]; -#ifdef USE_OPLOCKS /* * Break oplocks before checking share modes. See comment in * open_file_shared for details. @@ -1513,7 +1510,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); broke_oplock = True; break; } -#endif /* USE_OPLOCKS */ /* someone else has a share lock on it, check to see if we can too */ @@ -1729,7 +1725,6 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { min_share_mode_entry *share_entry = &old_shares[i]; -#ifdef USE_OPLOCKS /* * By observation of NetBench, oplocks are broken *before* share * modes are checked. This allows a file to be closed by the client @@ -1759,7 +1754,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); broke_oplock = True; break; } -#endif /* USE_OPLOCKS */ /* someone else has a share lock on it, check to see if we can too */ @@ -1841,7 +1835,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if (lp_share_modes(SNUM(cnum))) { uint16 port = 0; -#ifdef USE_OPLOCKS /* JRA. Currently this only services Exlcusive and batch oplocks (no other opens on this file). This needs to be extended to level II oplocks (multiple reader @@ -1862,10 +1855,6 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); port = 0; oplock_request = 0; } -#else /* USE_OPLOCKS */ - oplock_request = 0; - port = 0; -#endif /* USE_OPLOCKS */ set_share_mode(token, fnum, port, oplock_request); } @@ -2434,7 +2423,6 @@ static void process_smb(char *inbuf, char *outbuf) trans_num++; } -#ifdef USE_OPLOCKS /**************************************************************************** open the oplock IPC socket communication ****************************************************************************/ @@ -2882,8 +2870,6 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", return True; } -#endif /* USE_OPLOCKS */ - /**************************************************************************** check if a snum is in use ****************************************************************************/ @@ -4588,9 +4574,7 @@ static void process(void) int counter; int last_keepalive=0; int service_load_counter = 0; -#ifdef USE_OPLOCKS BOOL got_smb = False; -#endif /* USE_OPLOCKS */ if (deadtime <= 0) deadtime = DEFAULT_SMBD_TIMEOUT; @@ -4601,12 +4585,8 @@ static void process(void) errno = 0; for (counter=SMBD_SELECT_LOOP; -#ifdef USE_OPLOCKS !receive_message_or_smb(Client,oplock_sock, InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); -#else /* USE_OPLOCKS */ - !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); -#endif /* USE_OPLOCKS */ counter += SMBD_SELECT_LOOP) { int i; @@ -4689,14 +4669,10 @@ static void process(void) } } -#ifdef USE_OPLOCKS if(got_smb) -#endif /* USE_OPLOCKS */ process_smb(InBuffer, OutBuffer); -#ifdef USE_OPLOCKS else process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); -#endif /* USE_OPLOCKS */ } } @@ -4976,11 +4952,9 @@ static void usage(char *pname) DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); } -#ifdef USE_OPLOCKS /* Setup the oplock IPC socket. */ if(!open_oplock_ipc()) exit(1); -#endif /* USE_OPLOCKS */ process(); close_sockets(); -- cgit From a3b7bdd7b997fd6d41b8b96676eb58471112d931 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 7 Oct 1997 14:58:07 +0000 Subject: pipes.c: some routines to create LSA RPC packets. none of them are used. lsaparse.c: smbparse.c: smb.h: more tidy-up. (This used to be commit b37e21273e81b875876e8e8ddf6804714044ffd8) --- source3/smbd/pipes.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 237 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index a465e91145..0fb8a89c9e 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -2,7 +2,9 @@ Unix SMB/Netbios implementation. Version 1.9. Pipe SMB reply routines - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1997, + Paul Ashton 1997, + Luke Kenneth Casson Leighton 1996-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 @@ -51,6 +53,9 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { "lsarpc", +#if 0 + "NETLOGON", +#endif NULL }; @@ -357,3 +362,234 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, } return(True); } + +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + +/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ +/* identauth >= 2^32 can be detected because it will be specified in hex */ +static void init_dom_sid(DOM_SID *sid, char *domsid) +{ + int identauth; + char *p; + + DEBUG(4,("netlogon domain SID: %s\n", domsid)); + + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + sid->sid_no = atoi(p); + + /* identauth in decimal should be < 2^32 */ + /* identauth in hex should be >= 2^32 */ + identauth = atoi(strtok(0,"-")); + + DEBUG(4,("netlogon rev %d\n", sid->sid_no)); + DEBUG(4,("netlogon %s ia %d\n", p, identauth)); + + sid->id_auth[0] = 0; + sid->id_auth[1] = 0; + sid->id_auth[2] = (identauth & 0xff000000) >> 24; + sid->id_auth[3] = (identauth & 0x00ff0000) >> 16; + sid->id_auth[4] = (identauth & 0x0000ff00) >> 8; + sid->id_auth[5] = (identauth & 0x000000ff); + + sid->num_auths = 0; + + while ((p = strtok(0, "-")) != NULL) + { + sid->sub_auths[sid->num_auths++] = atoi(p); + } +} + +static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) +{ + if (hdr == NULL) return; + + hdr->major = 5; /* RPC version 5 */ + hdr->minor = 0; /* minor version 0 */ + hdr->pkt_type = 2; /* RPC response packet */ + hdr->frag = 3; /* first frag + last frag */ + hdr->pack_type = 1; /* packed data representation */ + hdr->frag_len = data_len; /* fragment length, fill in later */ + hdr->auth_len = 0; /* authentication length */ + hdr->call_id = call_id; /* call identifier - match incoming RPC */ + hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */ + hdr->context_id = 0; /* presentation context identifier */ + hdr->cancel_count = 0; /* cancel count */ + hdr->reserved = 0; /* reserved */ +} + +static void init_rpc_reply(char *inbuf, char *q, char *base, int data_len) +{ + uint32 callid = RIVAL(inbuf, 12); + RPC_HDR hdr; + + create_rpc_reply(&hdr, callid, data_len); + smb_io_rpc_hdr(False, &hdr, q, base, 4); +} + +static int lsa_reply_open_policy(char *q, char *base) +{ + char *start = q; + LSA_R_OPEN_POL r_o; + + /* set up the LSA QUERY INFO response */ + bzero(&(r_o.pol.data), POL_HND_SIZE); + r_o.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_open_pol(False, &r_o, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_unistr2(UNISTR2 *str, char *buf, int len, char terminate) +{ + /* set up string lengths. add one if string is not null-terminated */ + str->uni_max_len = len + (terminate != 0 ? 1 : 0); + str->undoc = 0; + str->uni_str_len = len; + + /* store the string (null-terminated copy) */ + PutUniCode((char *)str->buffer, buf); + + /* overwrite the last character: some strings are terminated with 4 not 0 */ + str->buffer[len] = (uint16)terminate; +} + +static void init_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) +{ + int domlen = strlen(dom_name); + + d_q->uni_dom_max_len = domlen * 2; + d_q->padding = 0; + d_q->uni_dom_str_len = domlen * 2; + + d_q->buffer_dom_name = 0; /* domain buffer pointer */ + d_q->buffer_dom_sid = 0; /* domain sid pointer */ + + /* NOT null-terminated: 4-terminated instead! */ + init_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); + + init_dom_sid(&(d_q->dom_sid), dom_sid); +} + +static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, + char *dom_name, char *dom_sid) +{ + char *start = q; + LSA_R_QUERY_INFO r_q; + + /* set up the LSA QUERY INFO response */ + + r_q.undoc_buffer = 1; /* not null */ + r_q.info_class = q_q->info_class; + + init_dom_query(&r_q.dom.id5, dom_name, dom_sid); + + r_q.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_query(False, &r_q, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) +{ + memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); + r_c->status = status; +} + +#if 0 + char chal[8]; + /* PAXX: set these to random values */ + for (int i = 0; i < 8; i+++) + { + chal[i] = 0xA5; + } +#endif + +static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, + char chal[8]) +{ + char *start = q; + LSA_R_REQ_CHAL r_c; + + /* set up the LSA REQUEST CHALLENGE response */ + + init_lsa_r_req_chal(&r_c, chal, 0); + + /* store the response in the SMB stream */ + q = lsa_io_r_req_chal(False, &r_c, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) +{ + memcpy(cred->data, resp_cred, sizeof(cred->data)); +} + +static void init_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, + char resp_cred[8], NEG_FLAGS *flgs, int status) +{ + init_lsa_chal(&(r_a->srv_chal), resp_cred); + memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs)); + r_a->status = status; +} + +static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, + char resp_cred[8], int status) +{ + char *start = q; + LSA_R_AUTH_2 r_a; + + /* set up the LSA AUTH 2 response */ + + init_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); + + /* store the response in the SMB stream */ + q = lsa_io_r_auth_2(False, &r_a, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) +{ + init_lsa_chal(&(cred->challenge), srv_chal); + cred->timestamp = srv_time; +} + + +static void init_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, + char srv_chal[8], UTIME srv_time, int status) +{ + init_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); + r_a->status = status; +} + +static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, + char srv_cred[8], UTIME srv_time, + int status) +{ + char *start = q; + LSA_R_SRV_PWSET r_s; + + /* set up the LSA Server Password Set response */ + init_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); + + /* store the response in the SMB stream */ + q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + -- cgit From 577ae65ca562ec05849a2e9e79689d00e0a0bcf2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 7 Oct 1997 18:18:10 +0000 Subject: pipes.c: more static unused functions in pipes.c for the LSA RPC stream. smb.h: corrections and altercations over the documentation lsaparse.c: reflecting alterations in LSA structures... (This used to be commit bef12478d212a950578843d6d4dece1f153bfd25) --- source3/smbd/pipes.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 182 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 0fb8a89c9e..95b69ef4d9 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -28,6 +28,7 @@ #include "includes.h" #include "trans2.h" +#include "nterr.h" #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) @@ -371,7 +372,7 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ /* identauth >= 2^32 can be detected because it will be specified in hex */ -static void init_dom_sid(DOM_SID *sid, char *domsid) +static void make_dom_sid(DOM_SID *sid, char *domsid) { int identauth; char *p; @@ -422,7 +423,7 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->reserved = 0; /* reserved */ } -static void init_rpc_reply(char *inbuf, char *q, char *base, int data_len) +static void make_rpc_reply(char *inbuf, char *q, char *base, int data_len) { uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; @@ -447,7 +448,14 @@ static int lsa_reply_open_policy(char *q, char *base) return q - start; } -static void init_unistr2(UNISTR2 *str, char *buf, int len, char terminate) +static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) +{ + hdr->uni_max_len = max_len; + hdr->uni_str_len = len; + hdr->undoc = terminate; +} + +static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) { /* set up string lengths. add one if string is not null-terminated */ str->uni_max_len = len + (terminate != 0 ? 1 : 0); @@ -461,7 +469,7 @@ static void init_unistr2(UNISTR2 *str, char *buf, int len, char terminate) str->buffer[len] = (uint16)terminate; } -static void init_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) +static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) { int domlen = strlen(dom_name); @@ -473,9 +481,9 @@ static void init_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) d_q->buffer_dom_sid = 0; /* domain sid pointer */ /* NOT null-terminated: 4-terminated instead! */ - init_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); + make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); - init_dom_sid(&(d_q->dom_sid), dom_sid); + make_dom_sid(&(d_q->dom_sid), dom_sid); } static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, @@ -489,7 +497,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, r_q.undoc_buffer = 1; /* not null */ r_q.info_class = q_q->info_class; - init_dom_query(&r_q.dom.id5, dom_name, dom_sid); + make_dom_query(&r_q.dom.id5, dom_name, dom_sid); r_q.status = 0x0; @@ -500,7 +508,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, return q - start; } -static void init_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) +static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) { memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); r_c->status = status; @@ -523,7 +531,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, /* set up the LSA REQUEST CHALLENGE response */ - init_lsa_r_req_chal(&r_c, chal, 0); + make_lsa_r_req_chal(&r_c, chal, 0); /* store the response in the SMB stream */ q = lsa_io_r_req_chal(False, &r_c, q, base, 4); @@ -532,15 +540,15 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, return q - start; } -static void init_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) +static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) { memcpy(cred->data, resp_cred, sizeof(cred->data)); } -static void init_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, +static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, char resp_cred[8], NEG_FLAGS *flgs, int status) { - init_lsa_chal(&(r_a->srv_chal), resp_cred); + make_lsa_chal(&(r_a->srv_chal), resp_cred); memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs)); r_a->status = status; } @@ -553,7 +561,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, /* set up the LSA AUTH 2 response */ - init_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); + make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); /* store the response in the SMB stream */ q = lsa_io_r_auth_2(False, &r_a, q, base, 4); @@ -562,17 +570,17 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, return q - start; } -static void init_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) +static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) { - init_lsa_chal(&(cred->challenge), srv_chal); + make_lsa_chal(&(cred->challenge), srv_chal); cred->timestamp = srv_time; } -static void init_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, +static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, char srv_chal[8], UTIME srv_time, int status) { - init_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); + make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); r_a->status = status; } @@ -584,7 +592,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ - init_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); + make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); /* store the response in the SMB stream */ q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); @@ -593,3 +601,159 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, return q - start; } +static void make_lsa_user_info(LSA_USER_INFO *usr, + + NTTIME *logon_time, + NTTIME *logoff_time, + NTTIME *kickoff_time, + NTTIME *pass_last_set_time, + NTTIME *pass_can_change_time, + NTTIME *pass_must_change_time, + + char *user_name, + char *full_name, + char *logon_script, + char *profile_path, + char *home_dir, + char *dir_drive, + + uint16 logon_count, + uint16 bad_pw_count, + + uint32 user_id, + uint32 group_id, + uint32 num_groups, + DOM_GID *gids, + uint32 user_flgs, + + char sess_key[16], + + char *logon_srv, + char *logon_dom, + + char *dom_sid, + char *other_sids) /* space-delimited set of SIDs */ +{ + /* only cope with one "other" sid, right now. */ + /* need to count the number of space-delimited sids */ + int i; + int num_other_sids = other_sids != NULL ? 1 : 0; + + int len_user_name = strlen(user_name ); + int len_full_name = strlen(full_name ); + int len_logon_script = strlen(logon_script); + int len_profile_path = strlen(profile_path); + int len_home_dir = strlen(home_dir ); + int len_dir_drive = strlen(dir_drive ); + + int len_logon_srv = strlen(logon_srv); + int len_logon_dom = strlen(logon_dom); + + usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */ + + usr->logon_time = *logon_time; + usr->logoff_time = *logoff_time; + usr->kickoff_time = *kickoff_time; + usr->pass_last_set_time = *pass_last_set_time; + usr->pass_can_change_time = *pass_can_change_time; + usr->pass_must_change_time = *pass_must_change_time; + + make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4); + make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4); + make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4); + make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4); + make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4); + make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4); + + usr->logon_count = logon_count; + usr->bad_pw_count = bad_pw_count; + + usr->user_id = user_id; + usr->group_id = group_id; + usr->num_groups = num_groups; + usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */ + usr->user_flgs = user_flgs; + + if (sess_key != NULL) + { + memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key)); + } + else + { + bzero(usr->sess_key, sizeof(usr->sess_key)); + } + + make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4); + make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4); + + usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ + + bzero(usr->padding, sizeof(usr->padding)); + + usr->num_other_sids = num_other_sids; + usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; + + make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0); + make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0); + make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0); + make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0); + make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0); + make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0); + + usr->num_groups2 = num_groups; + for (i = 0; i < num_groups; i++) + { + usr->gids[i] = gids[i]; + } + + make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0); + make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0); + + make_dom_sid(&(usr->dom_sid), dom_sid); + make_dom_sid(&(usr->other_sids[0]), other_sids); +} + + +static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, + char srv_cred[8], UTIME srv_time, + LSA_USER_INFO *user_info) +{ + char *start = q; + LSA_R_SAM_LOGON r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + + /* store the user information, if there is any. */ + r_s.user = user_info; + r_s.buffer_user = user_info != NULL ? 1 : 0; + r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); + + /* store the response in the SMB stream */ + q = lsa_io_r_sam_logon(False, &r_s, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + + +static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, + char srv_cred[8], UTIME srv_time, + uint32 status) +{ + char *start = q; + LSA_R_SAM_LOGOFF r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + + r_s.status = status; + + /* store the response in the SMB stream */ + q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} -- cgit From fb27bc139f8d321e50471c595b65b277ee114801 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Oct 1997 18:46:19 +0000 Subject: locking.c: Added fix for race condition in slow share mode code. lsaparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. pipes.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. server.c: Fixed last known oplock race condition. smb.h: Re-removed USE_OPLOCK defines - someone checked in an old version. smbparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. Jeremy (jallison@whistle.com) (This used to be commit 1e1366ddc5542283a37debdf830ca139bbade1b0) --- source3/smbd/pipes.c | 4 ++++ source3/smbd/server.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 95b69ef4d9..ffa64a4e80 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -364,6 +364,8 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } +#if 0 /* HAVING TO DO THIS TO GET THINGS TO COMPILE - LUKE PLEASE CHECK THIS !!! */ + /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -757,3 +759,5 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* return length of SMB data stored */ return q - start; } + +#endif /* LUKE PLEASE CHECK THIS !! */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4f5b01ba91..92c219c71b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2455,6 +2455,9 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); } oplock_port = ntohs(sock_name.sin_port); + DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", + getpid(), oplock_port)); + return True; } @@ -2545,6 +2548,31 @@ pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, } break; + /* + * Keep this as a debug case - eventually we can remove it. + */ + case 0x8001: + DEBUG(0,("process_local_message: Received unsolicited break \ +reply - dumping info.\n")); + + if(msg_len != OPLOCK_BREAK_MSG_LEN) + { + DEBUG(0,("process_local_message: ubr: incorrect length for reply \ +(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); + return False; + } + + { + uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + + DEBUG(0,("process_local_message: unsolicited oplock break reply from \ +pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); + + } + return False; + default: DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", (unsigned int)SVAL(msg_start,0))); @@ -2860,6 +2888,7 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", share_entry->pid, share_entry->op_port, dev, inode)); if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) return False; + continue; } break; -- cgit From b0bdb42bd12905f5a6990b1cdc5d33fc4a3063a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Oct 1997 00:21:39 +0000 Subject: ipc.c: Added ERROR_MORE_DATA error if client buffer too small. server.c: Allow admin_user on read only shares. I think this is safe but it needs looking at. Jeremy (jallison@whistle.com) (This used to be commit cc50955a2760f1de7e80b91408a7c0806f6eb44c) --- source3/smbd/ipc.c | 2 +- source3/smbd/server.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b9355c4ec0..6da9562c9f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1074,7 +1074,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA)); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); SSVAL(*rparam,6,counted+missed); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 92c219c71b..290181fb9e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3167,8 +3167,17 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de } /* admin user check */ - if (user_in_list(user,lp_admin_users(snum)) && - !pcon->read_only) + + /* JRA - original code denied admin user if the share was + marked read_only. Changed as I don't think this is needed, + but old code left in case there is a problem here. + */ + if (user_in_list(user,lp_admin_users(snum)) +#if 0 + && !pcon->read_only) +#else + ) +#endif { pcon->admin_user = True; DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); -- cgit From 827aa6bc6ad8e73a9100c2ae4cad3f0da8a29a58 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 8 Oct 1997 11:47:46 +0000 Subject: updating lsaparse.c and smbparse.c in line with changes to pipes.c and smb.h from yesterday. (This used to be commit 0b7049fae25957851a7f33d2bd500d8ecefc1ad5) --- source3/smbd/pipes.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index ffa64a4e80..95b69ef4d9 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -364,8 +364,6 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } -#if 0 /* HAVING TO DO THIS TO GET THINGS TO COMPILE - LUKE PLEASE CHECK THIS !!! */ - /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -759,5 +757,3 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* return length of SMB data stored */ return q - start; } - -#endif /* LUKE PLEASE CHECK THIS !! */ -- cgit From 8871297885050911aaa802c4e90e282c44e49b84 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 8 Oct 1997 17:12:07 +0000 Subject: loadparm.c proto.h: added lp_domainsid() lsaparse.c smb.h: debugging structures and parsing functions pipes.c: finally got to the functions that will go into the RPC switch statement. (This used to be commit d15aed8a9c58a7cc90befaee2d5a2752708f9327) --- source3/smbd/pipes.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 95b69ef4d9..06b785bd87 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -423,13 +423,13 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->reserved = 0; /* reserved */ } -static void make_rpc_reply(char *inbuf, char *q, char *base, int data_len) +static void make_rpc_reply(char *inbuf, char *q, int data_len) { uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; create_rpc_reply(&hdr, callid, data_len); - smb_io_rpc_hdr(False, &hdr, q, base, 4); + smb_io_rpc_hdr(False, &hdr, q, q, 4); } static int lsa_reply_open_policy(char *q, char *base) @@ -455,6 +455,18 @@ static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) hdr->undoc = terminate; } +static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate) +{ + make_uni_hdr(&(hdr->unihdr), max_len, len, terminate); + hdr->undoc_buffer = len > 0 ? 1 : 0; +} + +static void make_unistr(UNISTR *str, char *buf) +{ + /* store the string (null-terminated copy) */ + PutUniCode((char *)(str->buffer), buf); +} + static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) { /* set up string lengths. add one if string is not null-terminated */ @@ -469,6 +481,16 @@ static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) str->buffer[len] = (uint16)terminate; } +static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) +{ + int len_sid_str = strlen(sid_str); + + sid2->type = 0x5; + sid2->undoc = 0; + make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0); + make_unistr (&(sid2->str), sid_str); +} + static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) { int domlen = strlen(dom_name); @@ -508,6 +530,79 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, return q - start; } +/* pretty much hard-coded choice of "other" sids, unfortunately... */ +static void make_dom_ref(DOM_R_REF *ref, + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int len_dom_name = strlen(dom_name); + int len_other_sid1 = strlen(other_sid1); + int len_other_sid2 = strlen(other_sid2); + int len_other_sid3 = strlen(other_sid3); + + ref->undoc_buffer = 1; + ref->num_ref_doms_1 = 4; + ref->buffer_dom_name = 1; + ref->max_entries = 32; + ref->num_ref_doms_2 = 4; + + make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); + make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); + + if (dom_name != NULL) + { + make_unistr(&(ref->uni_dom_name), dom_name); + } + + make_dom_sid(&(ref->ref_dom[0]), dom_sid ); + make_dom_sid(&(ref->ref_dom[1]), other_sid1); + make_dom_sid(&(ref->ref_dom[2]), other_sid2); + make_dom_sid(&(ref->ref_dom[3]), other_sid3); +} + +static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, + int num_entries, char *dom_sids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]); + } + + r_l->num_entries3 = num_entries; +} + +static int lsa_reply_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, char *q, char *base, + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + char *start = q; + LSA_R_LOOKUP_SIDS r_l; + + /* set up the LSA Lookup SIDs response */ + make_reply_lookup_sids(&r_l, 0, NULL, /* q_l->num_entries, q_l->dom_sids, */ + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) { memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); @@ -757,3 +852,44 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* return length of SMB data stored */ return q - start; } + + +static void api_lsa_open_policy( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + /* we might actually want to decode the query, but it's not necessary */ + /* lsa_io_q_open_policy(...); */ + + /* return a 20 byte policy handle */ + reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} + +static void api_lsa_query_info( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + LSA_Q_QUERY_INFO q_i; + pstring dom_name; + pstring dom_sid; + + /* grab the info class and policy handle */ + lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, + dom_name, dom_sid); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} -- cgit From b2707324245d7143f4ac0056526044aed3881f3e Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 8 Oct 1997 18:36:34 +0000 Subject: added api_lsa_lookup_sids() function (This used to be commit 35dd48740d8f733e7725813322b094b4679b31c5) --- source3/smbd/pipes.c | 1074 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1071 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 06b785bd87..88cf0b2d71 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -370,6 +370,29 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, fragment length. I've decided to do it based on operation number :-) */ +/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ +char *dom_sid_to_string(DOM_SID *sid) +{ + static pstring sidstr; + char subauth[16]; + int i; + uint32 ia = (sid->id_auth[0]) + + (sid->id_auth[1] << 8 ) + + (sid->id_auth[2] << 16) + + (sid->id_auth[3] << 24); + + sprintf(sidstr, "S-%d-%d", sid->sid_no, ia); + + for (i = 0; i < sid->num_auths; i++) + { + sprintf(subauth, "-%d", sid->sub_auths[i]); + strcat(sidstr, subauth); + } + + DEBUG(5,("dom_sid_to_string returning %s\n", sidstr)); + return sidstr; +} + /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ /* identauth >= 2^32 can be detected because it will be specified in hex */ static void make_dom_sid(DOM_SID *sid, char *domsid) @@ -563,7 +586,7 @@ static void make_dom_ref(DOM_R_REF *ref, } static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, - int num_entries, char *dom_sids[MAX_LOOKUP_SIDS], + int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { @@ -584,7 +607,8 @@ static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, r_l->num_entries3 = num_entries; } -static int lsa_reply_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, char *q, char *base, +static int lsa_reply_lookup_sids(char *q, char *base, + int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { @@ -592,7 +616,7 @@ static int lsa_reply_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, char *q, char *base, LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ - make_reply_lookup_sids(&r_l, 0, NULL, /* q_l->num_entries, q_l->dom_sids, */ + make_reply_lookup_sids(&r_l, num_entries, dom_sids, dom_name, dom_sid, other_sid1, other_sid2, other_sid3); r_l.status = 0x0; @@ -893,3 +917,1047 @@ static void api_lsa_query_info( char *param, char *data, make_rpc_reply(data, *rdata, reply_len); *rdata_len = reply_len + 0x18; } + +static void api_lsa_lookup_sids( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + int i; + LSA_Q_LOOKUP_SIDS q_l; + pstring dom_name; + pstring dom_sid; + fstring dom_sids[MAX_LOOKUP_SIDS]; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* convert received SIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i]))); + } + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, + q_l.num_entries, dom_sids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} + + +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + +BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + uint32 nentries; + char *policyhandle; + #define MAXSIDS 64 + uchar *sids[MAXSIDS]; /* for lookup SID */ + int nsids; + int nnames; + #define MAXNAMES 64 + uchar *names[MAXNAMES]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAOPENPOLICY: + DEBUG(1,("LSAOPENPOLICY\n")); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + DEBUG(4,("netlogon data %lx\n", data)); + q = *rdata + 0x18; + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + /* return a 20 byte policy handle */ + /* here's a pretty handle:- */ + qSIVAL(time(NULL)); + qSIVAL(0x810a792f); + qSIVAL(0x11d107d5); + qSIVAL(time(NULL)); + qSIVAL(0x6cbcf800); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + break; + + case LSAQUERYINFOPOLICY: + DEBUG(1,("LSAQUERYINFOPOLICY\n")); + dump_data(1,data,128); + infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ + q = *rdata + 0x18; + qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose + value is ignored */ + qSSVAL(infoclass); + domainname = lp_workgroup(); + domlen = strlen(domainname); + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + + switch (infoclass) + { + case 5: + case 3: + default: + qSSVAL(0); /* 2 undocumented bytes */ + qSSVAL(domlen*2); + qSSVAL(domlen*2); /* unicode domain len and maxlen */ + qSIVAL(4); /* domain buffer pointer */ + qSIVAL(2); /* domain sid pointer */ + qunistr(domainname); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + } + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAENUMTRUSTDOM: + DEBUG(1,("LSAENUMTRUSTDOM\n")); + q = *rdata + 0x18; + qSIVAL(0); /* enumeration context */ + qSIVAL(0); /* entries read */ + qSIVAL(0); /* trust information */ + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + break; + + case LSACLOSE: + DEBUG(1,("LSACLOSE\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAOPENSECRET: + DEBUG(1,("LSAOPENSECRET\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + break; + + case LSALOOKUPSIDS: + DEBUG(1,("LSAOPENSECRET\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupsid entries %d\n",nentries)); + q += (2+nentries) * 4; /* skip bufptrs */ + /* now we have nentries sids of the form: + uint32 Subauthority count (SAC) + char Revision + char Subaurity count again + char[6] Identifier authority + [uint32 subauthority] * SAC + */ + for (nsids = 0; nsids < nentries; nsids++) + { + DEBUG(4,("lookupsid q in %lx\n",q)); + sids[nsids] = q; + DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); + q += 4+1+1+6+IVAL(q,0)*4; + DEBUG(4,("lookupsid q %lx\n",q)); + } + /* There's 16 bytes of something after all of that, don't know + what it is though - incorrectly documented */ + + DEBUG(4,("lookupsid line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use ?! */ + qSSVAL(0); /* undocumented */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + qunihdr(sidtostring(sids[i])); + DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qunistr(sidtostring(sids[i])); + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSALOOKUPNAMES: + DEBUG(1,("LSALOOKUPNAMES\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ + qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); + qSIVAL(nametorid(names[i])); + DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + default: + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + } + return(True); +} + +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAREQCHAL: + DEBUG(1,("LSAREQCHAL\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ + q = skip_unicode_string(logonsrv,1) + 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr(logonsrv), + unistr(unicomp))); + + dcauth[cnum].chal[0] = IVAL(q, 0); + dcauth[cnum].chal[1] = IVAL(q, 4); + dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ + dcauth[cnum].cred[1] = IVAL(q, 4); + +DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); + + /* PAXX: set these to random values */ + dcauth[cnum].svrchal[0] = 0x11111111; + dcauth[cnum].svrchal[1] = 0x22222222; + dcauth[cnum].svrcred[0] = 0x11111111; + dcauth[cnum].svrcred[1] = 0x22222222; + strcpy(machacct,unistr(unicomp)); + strcat(machacct, "$"); + smb_pass = get_smbpwnam(machacct); + if(smb_pass) + memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); + DEBUG(1,("pass %s %s\n", machacct, foo)); + setsesskey(cnum); + q = *rdata + 0x18; + qSIVAL(dcauth[cnum].svrchal[0]); + qSIVAL(dcauth[cnum].svrchal[1]); + +DEBUG(1,("NL: server challenge %08x %08x\n", + dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAAUTH2: + DEBUG(1,("LSAAUTH2\n")); + dump_data(1,q,128); + q = data + 0x18; + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + dump_data(1,unicomp,32); + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + q = align4(q, data); + negflags = qIVAL; + DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), + rcvcred[0], rcvcred[1], negflags)); + +DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", + rcvcred[0], rcvcred[1], negflags)); + + checkcred(cnum, rcvcred[0], rcvcred[1], 0); + q = *rdata + 0x18; + makecred(cnum, 0, q); + q += 8; + + qSIVAL(negflags); + /* update stored client credentials */ + dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; + dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + + case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } + + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); + } + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) + { + /* put the extra sids: PAXX: TODO */ + } + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; + default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); + default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + } + return(True); +} + +void initrpcreply(char *inbuf, char *q) +{ + uint32 callid; + + qSCVAL(5); /* RPC version 5 */ + qSCVAL(0); /* minor version 0 */ + qSCVAL(2); /* RPC response packet */ + qSCVAL(3); /* first frag + last frag */ + qRSIVAL(0x10000000); /* packed data representation */ + qRSSVAL(0); /* fragment length, fill in later */ + qSSVAL(0); /* authentication length */ + callid = RIVAL(inbuf,12); + qRSIVAL(callid); /* call identifier - match incoming RPC */ + qSIVAL(0x18); /* allocation hint (no idea) */ + qSSVAL(0); /* presentation context identifier */ + qSCVAL(0); /* cancel count */ + qSCVAL(0); /* reserved */ +} + +endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) +{ + SSVAL(q, 8, datalen + 4); + SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ + SIVAL(q, datalen, rtnval); + *rlen = datalen + 4; + {int fd; fd = open("/tmp/rpc", O_RDWR);write(fd,q,datalen+4);} +} + +void setsesskey(int cnum) +{ + uint32 sum[2]; + char netsum[8]; + char netsesskey[8]; + char icv[8]; + + sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; + sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; + SIVAL(netsum,0,sum[0]); + SIVAL(netsum,4,sum[1]); + E1(dcauth[cnum].md4pw,netsum,icv); + E1(dcauth[cnum].md4pw+9,icv,netsesskey); + dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); + dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); + +DEBUG(1,("NL: session key %08x %08x\n", + dcauth[cnum].sesskey[0], + dcauth[cnum].sesskey[1])); +} + +void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char calccred[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].cred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + if (IVAL(calccred,0) != cred0 || + IVAL(calccred,4) != cred1) + { + DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); + /* PAXX: do something about it! */ + } else + DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); +} + +void makecred(int cnum, uint32 time, char *calccred) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", + dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], + IVAL(calccred, 0), IVAL(calccred, 4))); +} + + +struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) +{ + static struct uinfo u; + static pstring fullnm; + static pstring ascuser; + extern pstring myname; + static pstring stme; + static pstring stdom; + struct smb_passwd *smb_pass; + + strcpy(ascuser,unistr(user)); + ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ + DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); + + smb_pass = get_smbpwnam(ascuser); + if(!smb_pass) + return 0; + DEBUG(1,("GETU %d\n", __LINE__)); + if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { + DEBUG(1,("pass mismatch:\n")); + dump_data(1,ntowfpass,16); + dump_data(1,smb_pass->smb_nt_passwd,16); + return 0; + } + + DEBUG(1,("GETU %d\n", __LINE__)); + u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; + u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; + u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; + u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; + u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.effectivename = ascuser; + strcpy(fullnm, "Full name of "); + strcat(fullnm, ascuser); + DEBUG(1,("GETU %d\n", __LINE__)); + u.fullname = fullnm; + u.logonscript = "foologin.cmd"; + u.profilepath = "prof"; + u.homedirectory = "foohomes"; + DEBUG(1,("GETU %d\n", __LINE__)); + u.homedirectorydrive = "a:"; + u.logoncount = 7; + u.badpwcount = 8; + u.uid = 778; + DEBUG(1,("GETU %d\n", __LINE__)); + u.gid = 998; + u.ngroups = 2; + u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); + u.groups[0].gid = 776; + DEBUG(1,("GETU %d\n", __LINE__)); + u.groups[0].attr = 0x7; + u.groups[1].gid = 776; + u.groups[1].attr = 0x7; + u.userflags = 0x20; + u.logonserver = stme; + get_myname(myname,NULL); + strcpy(stme, myname); + strupper(stme); + DEBUG(1,("LS %s\n", u.logonserver)); + u.logondomain = stdom; + strcpy(stdom, lp_workgroup()); + strupper(stdom); + DEBUG(1,("DOM %s\n", u.logondomain)); + u.nsids = 0; + u.sids = 0; + DEBUG(1,("GETU %d\n", __LINE__)); + return &u; +}; + +int +nametorid(char *uniuser) +{ + if (!strncmp(unistr(uniuser+12),"ashtonp",7)) + return 2000; + if (!strncmp(unistr(uniuser+12),"user1",5)) + return 1; + if (!strncmp(unistr(uniuser+12),"user2",5)) + return 10; + if (!strncmp(unistr(uniuser+12),"user3",5)) + return 100; + return 3000; +} + +#endif /* NTDOMAIN */ -- cgit From 74113cd60ecceaf73fce83e84dbcd58b498f2cb1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Oct 1997 20:34:13 +0000 Subject: Makefile: Split definitions for SGI4,5,6. includes.h: Split definitions for SGI4,5,6. pipes.c: Moved Luke's #ifdef to remove warnings. quotas.c: Two changes for FreeBSD and SGI. server.c: Quota changes for large filesystems. Jeremy (jallison@whistle.com) (This used to be commit b8ff5543b9fa45095caa9f24aeb22a1dcc1cd308) --- source3/smbd/pipes.c | 2 +- source3/smbd/quotas.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/server.c | 20 ++++++- 3 files changed, 165 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 88cf0b2d71..870dc16fdd 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -364,6 +364,7 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } +#ifdef UNDEFINED_NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -953,7 +954,6 @@ static void api_lsa_lookup_sids( char *param, char *data, } -#ifdef UNDEFINED_NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index d4f746c9e3..8810bcd909 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -416,10 +416,132 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } return (True); } + +#elif defined (SGI6) +/**************************************************************************** +try to get the disk space from disk quotas (IRIX 6.2 version) +****************************************************************************/ + +#include +#include + +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t euser_id; + int r; + struct dqblk D; + struct fs_disk_quota F; + struct stat S; + FILE *fp; + struct mntent *mnt; + int devno; + int found; + + /* find the block device file */ + + if ( stat(path, &S) == -1 ) { + return(False) ; + } + + devno = S.st_dev ; + + fp = setmntent(MOUNTED,"r"); + found = False ; + + while ((mnt = getmntent(fp))) { + if ( stat(mnt->mnt_dir,&S) == -1 ) + continue ; + if (S.st_dev == devno) { + found = True ; + break ; + } + } + endmntent(fp) ; + + if (!found) { + return(False); + } + + euser_id=geteuid(); + seteuid(0); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + + *bsize = 512; + + if ( 0 == strcmp ( mnt->mnt_type, "efs" )) + { + r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); + + if (r==-1) + return(False); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) || + (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) || + (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) || + (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit) + ) + { + *dfree = 0; + *dsize = D.dqb_curblocks; + } + else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0) + { + return(False); + } + else + { + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + } + + } + else if ( 0 == strcmp ( mnt->mnt_type, "xfs" )) + { + r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); + + if (r==-1) + return(False); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) || + (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) || + (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) || + (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit) + ) + { + /* + * Fixme!: these are __uint64_t, this may truncate values + */ + *dfree = 0; + *dsize = (int) F.d_bcount; + } + else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) + { + return(False); + } + else + { + *dfree = (int)(F.d_blk_softlimit - F.d_bcount); + *dsize = (int)F.d_blk_softlimit; + } + + } + else + return(False); + + return (True); + +} + #else #ifdef __FreeBSD__ #include +#include #elif AIX /* AIX quota patch from Ole Holm Nielsen */ #include @@ -463,7 +585,25 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #else /* USE_SETRES */ #if defined(__FreeBSD__) - r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); + { + /* FreeBSD patches from Marty Moll */ + uid_t user_id; + gid_t egrp_id; + + /* Need to be root to get quotas in FreeBSD */ + user_id = getuid(); + egrp_id = getegid(); + setuid(0); + seteuid(0); + r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); + + /* As FreeBSD has group quotas, if getting the user + quota fails, try getting the group instead. */ + if (r) + r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); + setuid(user_id); + seteuid(euser_id); + } #elif defined(AIX) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ @@ -474,7 +614,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #endif /* USE_SETRES */ /* Use softlimit to determine disk space, except when it has been exceeded */ +#if defined(__FreeBSD__) + *bsize = DEV_BSIZE; +#else /* !__FreeBSD__ */ *bsize = 1024; +#endif /*!__FreeBSD__ */ + if (r) { if (errno == EDQUOT) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 290181fb9e..2b906a7641 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -711,7 +711,15 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; @@ -801,7 +809,15 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; -- cgit From f40427291e176028f45482209d863019428abc8b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 8 Oct 1997 21:36:42 +0000 Subject: added a dummy function (space in front so make proto doesn't pick it up) to call the unused static functions in pipes.c. avoids need to move #if UNDEFINED_NTDOMAIN about, to stop compiler warnings while code is being developed, but might be released as-is. (This used to be commit d7f41e3815babce58fa9901f076c2918666abaf9) --- source3/smbd/pipes.c | 1028 +------------------------------------------------- 1 file changed, 20 insertions(+), 1008 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 870dc16fdd..bedf847cc4 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -364,7 +364,6 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } -#ifdef UNDEFINED_NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -953,1011 +952,24 @@ static void api_lsa_lookup_sids( char *param, char *data, *rdata_len = reply_len + 0x18; } - -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - -BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - uint32 nentries; - char *policyhandle; - #define MAXSIDS 64 - uchar *sids[MAXSIDS]; /* for lookup SID */ - int nsids; - int nnames; - #define MAXNAMES 64 - uchar *names[MAXNAMES]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAOPENPOLICY: - DEBUG(1,("LSAOPENPOLICY\n")); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - DEBUG(4,("netlogon data %lx\n", data)); - q = *rdata + 0x18; - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - /* return a 20 byte policy handle */ - /* here's a pretty handle:- */ - qSIVAL(time(NULL)); - qSIVAL(0x810a792f); - qSIVAL(0x11d107d5); - qSIVAL(time(NULL)); - qSIVAL(0x6cbcf800); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - break; - - case LSAQUERYINFOPOLICY: - DEBUG(1,("LSAQUERYINFOPOLICY\n")); - dump_data(1,data,128); - infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ - q = *rdata + 0x18; - qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose - value is ignored */ - qSSVAL(infoclass); - domainname = lp_workgroup(); - domlen = strlen(domainname); - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - - switch (infoclass) - { - case 5: - case 3: - default: - qSSVAL(0); /* 2 undocumented bytes */ - qSSVAL(domlen*2); - qSSVAL(domlen*2); /* unicode domain len and maxlen */ - qSIVAL(4); /* domain buffer pointer */ - qSIVAL(2); /* domain sid pointer */ - qunistr(domainname); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - } - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAENUMTRUSTDOM: - DEBUG(1,("LSAENUMTRUSTDOM\n")); - q = *rdata + 0x18; - qSIVAL(0); /* enumeration context */ - qSIVAL(0); /* entries read */ - qSIVAL(0); /* trust information */ - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - break; - - case LSACLOSE: - DEBUG(1,("LSACLOSE\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAOPENSECRET: - DEBUG(1,("LSAOPENSECRET\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - break; - - case LSALOOKUPSIDS: - DEBUG(1,("LSAOPENSECRET\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupsid entries %d\n",nentries)); - q += (2+nentries) * 4; /* skip bufptrs */ - /* now we have nentries sids of the form: - uint32 Subauthority count (SAC) - char Revision - char Subaurity count again - char[6] Identifier authority - [uint32 subauthority] * SAC - */ - for (nsids = 0; nsids < nentries; nsids++) - { - DEBUG(4,("lookupsid q in %lx\n",q)); - sids[nsids] = q; - DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); - q += 4+1+1+6+IVAL(q,0)*4; - DEBUG(4,("lookupsid q %lx\n",q)); - } - /* There's 16 bytes of something after all of that, don't know - what it is though - incorrectly documented */ - - DEBUG(4,("lookupsid line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use ?! */ - qSSVAL(0); /* undocumented */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunihdr(sidtostring(sids[i])); - DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qunistr(sidtostring(sids[i])); - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSALOOKUPNAMES: - DEBUG(1,("LSALOOKUPNAMES\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) - { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ - } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ - qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); - qSIVAL(nametorid(names[i])); - DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - default: - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); - } - return(True); -} - -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAREQCHAL: - DEBUG(1,("LSAREQCHAL\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ - q = skip_unicode_string(logonsrv,1) + 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr(logonsrv), - unistr(unicomp))); - - dcauth[cnum].chal[0] = IVAL(q, 0); - dcauth[cnum].chal[1] = IVAL(q, 4); - dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ - dcauth[cnum].cred[1] = IVAL(q, 4); - -DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); - - /* PAXX: set these to random values */ - dcauth[cnum].svrchal[0] = 0x11111111; - dcauth[cnum].svrchal[1] = 0x22222222; - dcauth[cnum].svrcred[0] = 0x11111111; - dcauth[cnum].svrcred[1] = 0x22222222; - strcpy(machacct,unistr(unicomp)); - strcat(machacct, "$"); - smb_pass = get_smbpwnam(machacct); - if(smb_pass) - memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); - DEBUG(1,("pass %s %s\n", machacct, foo)); - setsesskey(cnum); - q = *rdata + 0x18; - qSIVAL(dcauth[cnum].svrchal[0]); - qSIVAL(dcauth[cnum].svrchal[1]); - -DEBUG(1,("NL: server challenge %08x %08x\n", - dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAAUTH2: - DEBUG(1,("LSAAUTH2\n")); - dump_data(1,q,128); - q = data + 0x18; - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - dump_data(1,unicomp,32); - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - q = align4(q, data); - negflags = qIVAL; - DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), - rcvcred[0], rcvcred[1], negflags)); - -DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", - rcvcred[0], rcvcred[1], negflags)); - - checkcred(cnum, rcvcred[0], rcvcred[1], 0); - q = *rdata + 0x18; - makecred(cnum, 0, q); - q += 8; - - qSIVAL(negflags); - /* update stored client credentials */ - dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; - dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - - case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; - default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); - default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - } - return(True); +/* space in front of this function so that make proto doesn't pick it up */ + void _dummy_function(void) +{ + UTIME t; + lsa_reply_req_chal(NULL, NULL, NULL, NULL); + lsa_reply_auth_2(NULL, NULL, NULL, NULL, 0); + lsa_reply_srv_pwset(NULL, NULL, NULL, NULL, t, 0); + make_lsa_user_info(NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + 0, 0, + 0, 0, 0, NULL, 0, + NULL, + NULL, NULL, + NULL, NULL); + lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL); + lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); + api_lsa_open_policy(NULL,NULL,NULL,NULL); + api_lsa_query_info(NULL,NULL,NULL,NULL); + api_lsa_lookup_sids(NULL,NULL,NULL,NULL); } - -void initrpcreply(char *inbuf, char *q) -{ - uint32 callid; - - qSCVAL(5); /* RPC version 5 */ - qSCVAL(0); /* minor version 0 */ - qSCVAL(2); /* RPC response packet */ - qSCVAL(3); /* first frag + last frag */ - qRSIVAL(0x10000000); /* packed data representation */ - qRSSVAL(0); /* fragment length, fill in later */ - qSSVAL(0); /* authentication length */ - callid = RIVAL(inbuf,12); - qRSIVAL(callid); /* call identifier - match incoming RPC */ - qSIVAL(0x18); /* allocation hint (no idea) */ - qSSVAL(0); /* presentation context identifier */ - qSCVAL(0); /* cancel count */ - qSCVAL(0); /* reserved */ -} - -endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) -{ - SSVAL(q, 8, datalen + 4); - SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ - SIVAL(q, datalen, rtnval); - *rlen = datalen + 4; - {int fd; fd = open("/tmp/rpc", O_RDWR);write(fd,q,datalen+4);} -} - -void setsesskey(int cnum) -{ - uint32 sum[2]; - char netsum[8]; - char netsesskey[8]; - char icv[8]; - - sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; - sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; - SIVAL(netsum,0,sum[0]); - SIVAL(netsum,4,sum[1]); - E1(dcauth[cnum].md4pw,netsum,icv); - E1(dcauth[cnum].md4pw+9,icv,netsesskey); - dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); - dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); - -DEBUG(1,("NL: session key %08x %08x\n", - dcauth[cnum].sesskey[0], - dcauth[cnum].sesskey[1])); -} - -void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char calccred[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].cred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - if (IVAL(calccred,0) != cred0 || - IVAL(calccred,4) != cred1) - { - DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); - /* PAXX: do something about it! */ - } else - DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); -} - -void makecred(int cnum, uint32 time, char *calccred) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", - dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], - IVAL(calccred, 0), IVAL(calccred, 4))); -} - - -struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) -{ - static struct uinfo u; - static pstring fullnm; - static pstring ascuser; - extern pstring myname; - static pstring stme; - static pstring stdom; - struct smb_passwd *smb_pass; - - strcpy(ascuser,unistr(user)); - ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ - DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); - - smb_pass = get_smbpwnam(ascuser); - if(!smb_pass) - return 0; - DEBUG(1,("GETU %d\n", __LINE__)); - if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { - DEBUG(1,("pass mismatch:\n")); - dump_data(1,ntowfpass,16); - dump_data(1,smb_pass->smb_nt_passwd,16); - return 0; - } - - DEBUG(1,("GETU %d\n", __LINE__)); - u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; - u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; - u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; - u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; - u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.effectivename = ascuser; - strcpy(fullnm, "Full name of "); - strcat(fullnm, ascuser); - DEBUG(1,("GETU %d\n", __LINE__)); - u.fullname = fullnm; - u.logonscript = "foologin.cmd"; - u.profilepath = "prof"; - u.homedirectory = "foohomes"; - DEBUG(1,("GETU %d\n", __LINE__)); - u.homedirectorydrive = "a:"; - u.logoncount = 7; - u.badpwcount = 8; - u.uid = 778; - DEBUG(1,("GETU %d\n", __LINE__)); - u.gid = 998; - u.ngroups = 2; - u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); - u.groups[0].gid = 776; - DEBUG(1,("GETU %d\n", __LINE__)); - u.groups[0].attr = 0x7; - u.groups[1].gid = 776; - u.groups[1].attr = 0x7; - u.userflags = 0x20; - u.logonserver = stme; - get_myname(myname,NULL); - strcpy(stme, myname); - strupper(stme); - DEBUG(1,("LS %s\n", u.logonserver)); - u.logondomain = stdom; - strcpy(stdom, lp_workgroup()); - strupper(stdom); - DEBUG(1,("DOM %s\n", u.logondomain)); - u.nsids = 0; - u.sids = 0; - DEBUG(1,("GETU %d\n", __LINE__)); - return &u; -}; - -int -nametorid(char *uniuser) -{ - if (!strncmp(unistr(uniuser+12),"ashtonp",7)) - return 2000; - if (!strncmp(unistr(uniuser+12),"user1",5)) - return 1; - if (!strncmp(unistr(uniuser+12),"user2",5)) - return 10; - if (!strncmp(unistr(uniuser+12),"user3",5)) - return 100; - return 3000; -} - -#endif /* NTDOMAIN */ -- cgit From 10424272bebb7867d85b70ebe9aebef85fd5efe0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Oct 1997 22:23:47 +0000 Subject: Put in fix for read-prediction extending files bug. Hard to test, can't get read-prediction to happen :-). Jeremy (jallison@whistle.com) (This used to be commit fa69b3dda47d56e0c3ce1f4f284eac89d4b4bf56) --- source3/smbd/predict.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 691d8fbb4e..7d6b2498f5 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -53,24 +53,37 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num) offset >= rp_offset && possible>0 && smb_last_time-rp_time < rp_timeout) - { - ret = possible; - if (buf) - memcpy(buf,rp_buffer + (offset-rp_offset),possible); - else - *ptr = rp_buffer + (offset-rp_offset); - DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); - } + { + ret = possible; + if (buf) + memcpy(buf,rp_buffer + (offset-rp_offset),possible); + else + *ptr = rp_buffer + (offset-rp_offset); + DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); + } if (ret == num) { predict_skip = True; } else { - predict_skip = False; + struct stat rp_stat; + + /* Find the end of the file - ensure we don't + read predict beyond it. */ + if(fstat(fd,&rp_stat) < 0) + { + DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); + predict_skip = True; + } + else + { + predict_skip = False; - /* prepare the next prediction */ - rp_predict_fd = fd; - rp_predict_offset = offset + num; - rp_predict_length = num; + /* prepare the next prediction */ + rp_predict_fd = fd; + /* Make sure we don't seek beyond the end of the file. */ + rp_predict_offset = MIN((offset + num),rp_stat.st_size); + rp_predict_length = num; + } } if (ret < 0) ret = 0; -- cgit From e5494e2c093fecd4b493ab925f7c7d30b79bc98d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 9 Oct 1997 06:36:04 +0000 Subject: bracket some macros change MAX_PASSWORD_LENGTH to MAX_PASS_LEN to prevent conflict on some systems add #ifdef around soft link dependent code (for systems that don't have soft links) (This used to be commit e10ba4b97a219e87b62d32834bf15ed2e323ed2e) --- source3/smbd/reply.c | 10 +++++----- source3/smbd/server.c | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fa641931eb..2a3679553c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -252,7 +252,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) close_cnum(SVAL(inbuf,smb_tid),vuid); - if (passlen > MAX_PASSWORD_LENGTH) { + if (passlen > MAX_PASS_LEN) { overflow_attack(passlen); } @@ -388,7 +388,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASSWORD_LENGTH) + if (smb_apasslen > MAX_PASS_LEN) { overflow_attack(smb_apasslen); } @@ -423,12 +423,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 != 24 && passlen2 != 24) doencrypt = False; - if (passlen1 > MAX_PASSWORD_LENGTH) { + if (passlen1 > MAX_PASS_LEN) { overflow_attack(passlen1); } - passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); - passlen2 = MIN(passlen2, MAX_PASSWORD_LENGTH); + passlen1 = MIN(passlen1, MAX_PASS_LEN); + passlen2 = MIN(passlen2, MAX_PASS_LEN); if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2b906a7641..e4d433c06f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -214,9 +214,11 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) if (S_ISDIR(sbuf->st_mode)) result = aDIR | (result & aRONLY); +#ifdef S_ISLNK #if LINKS_READ_ONLY if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) result |= aRONLY; +#endif #endif /* hide files with a name starting with a . */ @@ -863,6 +865,7 @@ BOOL check_name(char *name,int cnum) /* Patch from David Clerc University of Geneva */ +#ifdef S_ISLNK if (!lp_symlinks(SNUM(cnum))) { struct stat statbuf; @@ -873,6 +876,7 @@ BOOL check_name(char *name,int cnum) ret=0; } } +#endif if (!ret) DEBUG(5,("check_name on %s failed\n",name)); -- cgit From ad54a5671405374b6308929154c6922bc6a7d0d7 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 9 Oct 1997 14:40:46 +0000 Subject: credentials.c: use UTIME structure (defined and commented in smb.h to be time, secs, since 01jan1970) pipes.c: another sub-function. util.c: added char *unistr2(uint16 *buff) function. same as unistr except it takes uint16* instead of char*. smbparse.c smb.h: more structure sorting. proto.h: the usual. (This used to be commit 72a86f514f0c92b69499718e63f5dd73ebece56e) --- source3/smbd/pipes.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 189 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index bedf847cc4..13cdff262d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -370,6 +370,20 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, fragment length. I've decided to do it based on operation number :-) */ +/* RID username mapping function. just for fun, it maps to the unix uid */ +static uint32 name_to_rid(char *user_name) +{ + struct passwd *pw = Get_Pwnam(user_name, False); + if (!pw) + { + DEBUG(1,("Username %s is invalid on this system\n", user_name)); + return (uint32)(-1); + } + + return (uint32)(pw->pw_uid); +} + + /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ char *dom_sid_to_string(DOM_SID *sid) { @@ -504,6 +518,14 @@ static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) str->buffer[len] = (uint16)terminate; } +static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) +{ + rid2->type = 0x5; + rid2->undoc = 0x5; + rid2->rid = rid; + rid2->rid_idx = 0; +} + static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) { int len_sid_str = strlen(sid_str); @@ -585,6 +607,28 @@ static void make_dom_ref(DOM_R_REF *ref, make_dom_sid(&(ref->ref_dom[3]), other_sid3); } +static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); + } + + r_l->num_entries3 = num_entries; +} + static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], char *dom_name, char *dom_sid, @@ -627,6 +671,26 @@ static int lsa_reply_lookup_sids(char *q, char *base, return q - start; } +static int lsa_reply_lookup_rids(char *q, char *base, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + char *start = q; + LSA_R_LOOKUP_RIDS r_l; + + /* set up the LSA Lookup RIDs response */ + make_reply_lookup_rids(&r_l, num_entries, dom_rids, + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) { memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); @@ -952,6 +1016,129 @@ static void api_lsa_lookup_sids( char *param, char *data, *rdata_len = reply_len + 0x18; } +static void api_lsa_lookup_names( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + int i; + LSA_Q_LOOKUP_RIDS q_l; + pstring dom_name; + pstring dom_sid; + uint32 dom_rids[MAX_LOOKUP_SIDS]; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* convert received RIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + char *user_name = unistr2(q_l.lookup_name[i].str.buffer); + dom_rids[i] = name_to_rid(user_name); + } + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, + q_l.num_entries, dom_rids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} + +#if 0 + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { +qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { +qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ +qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); +qSIVAL(name_to_rid(names[i])); + DEBUG(4,("lookupnames name_to_rid %d\n",name_to_rid(names[i]))); +qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + +#endif + + /* space in front of this function so that make proto doesn't pick it up */ void _dummy_function(void) { @@ -971,5 +1158,6 @@ static void api_lsa_lookup_sids( char *param, char *data, lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); api_lsa_open_policy(NULL,NULL,NULL,NULL); api_lsa_query_info(NULL,NULL,NULL,NULL); - api_lsa_lookup_sids(NULL,NULL,NULL,NULL); + api_lsa_lookup_sids (NULL,NULL,NULL,NULL); + api_lsa_lookup_names(NULL,NULL,NULL,NULL); } -- cgit From 5a3ea52d4a567a341c8f2243783afdb392991ea2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 9 Oct 1997 15:48:40 +0000 Subject: pipes.c: added api_ntlsarpcTNP() function. hooray! smb.h: added LSA #defines needed by above function. (This used to be commit 5437f666987918516032cf8a5dada107e5d14d25) --- source3/smbd/pipes.c | 1175 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 1093 insertions(+), 82 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 13cdff262d..4dd7aa3e30 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -3,8 +3,8 @@ Version 1.9. Pipe SMB reply routines Copyright (C) Andrew Tridgell 1992-1997, - Paul Ashton 1997, - Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Paul Ashton 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 @@ -370,6 +370,36 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, fragment length. I've decided to do it based on operation number :-) */ +/* this function is due to be replaced */ +static void initrpcreply(char *inbuf, char *q) +{ + uint32 callid; + + SCVAL(q, 0, 5); q++; /* RPC version 5 */ + SCVAL(q, 0, 0); q++; /* minor version 0 */ + SCVAL(q, 0, 2); q++; /* RPC response packet */ + SCVAL(q, 0, 3); q++; /* first frag + last frag */ + RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */ + RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */ + SSVAL(q, 0, 0); q += 2; /* authentication length */ + callid = RIVAL(inbuf, 12); + RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */ + SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */ + SSVAL(q, 0, 0); q += 2; /* presentation context identifier */ + SCVAL(q, 0, 0); q++; /* cancel count */ + SCVAL(q, 0, 0); q++; /* reserved */ +} + +/* this function is due to be replaced */ +static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) +{ + SSVAL(q, 8, datalen + 4); + SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ + SIVAL(q, datalen, rtnval); + *rlen = datalen + 4; + { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); } +} + /* RID username mapping function. just for fun, it maps to the unix uid */ static uint32 name_to_rid(char *user_name) { @@ -1051,94 +1081,1079 @@ static void api_lsa_lookup_names( char *param, char *data, *rdata_len = reply_len + 0x18; } -#if 0 - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) +BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum = SVAL(data,22); + + int pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + switch (opnum) + { + case LSA_OPENPOLICY: + { + DEBUG(3,("LSA_OPENPOLICY\n")); + api_lsa_open_policy(param, data, rdata, rdata_len); + break; + } + + case LSA_QUERYINFOPOLICY: + { + DEBUG(3,("LSA_QUERYINFOPOLICY\n")); + + api_lsa_query_info(param, data, rdata, rdata_len); + break; + } + + case LSA_ENUMTRUSTDOM: + { + char *q = *rdata + 0x18; + + DEBUG(3,("LSA_ENUMTRUSTDOM\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); /* enumeration context */ + SIVAL(q, 0, 4); /* entries read */ + SIVAL(q, 0, 8); /* trust information */ + + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + + break; + } + + case LSA_CLOSE: + { + char *q = *rdata + 0x18; + + DEBUG(3,("LSA_CLOSE\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); + SIVAL(q, 0, 4); + SIVAL(q, 0, 8); + SIVAL(q, 0, 12); + SIVAL(q, 0, 16); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + + break; + } + + case LSA_OPENSECRET: + { + char *q = *rdata + 0x18; + DEBUG(3,("LSA_OPENSECRET\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); + SIVAL(q, 0, 4); + SIVAL(q, 0, 8); + SIVAL(q, 0, 12); + SIVAL(q, 0, 16); + + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + + break; + } + + case LSA_LOOKUPSIDS: + { + DEBUG(3,("LSA_OPENSECRET\n")); + api_lsa_lookup_sids(param, data, rdata, rdata_len); + break; + } + + case LSA_LOOKUPNAMES: + { + DEBUG(3,("LSA_LOOKUPNAMES\n")); + api_lsa_lookup_names(param, data, rdata, rdata_len); + break; + } + + default: + { + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + break; + } + } + return True; +} + + +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + + BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + uchar rc4key[16]; + uchar ntowfpass[16]; + uint32 nentries; + char *policyhandle; + #define MAXSIDS 64 + uchar *sids[MAXSIDS]; /* for lookup SID */ + int nsids; + #define MAXNAMES 64 + uchar *names[MAXNAMES]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) { -qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); + case LSAOPENPOLICY: + DEBUG(1,("LSAOPENPOLICY\n")); + char *q = *rdata + 0x18; + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + /* return a 20 byte policy handle */ + /* here's a pretty handle:- */ + qSIVAL(time(NULL)); + qSIVAL(0x810a792f); + qSIVAL(0x11d107d5); + qSIVAL(time(NULL)); + qSIVAL(0x6cbcf800); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + break; + + case LSAQUERYINFOPOLICY: + DEBUG(1,("LSAQUERYINFOPOLICY\n")); + dump_data(1,data,128); + infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ + q = *rdata + 0x18; + qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose + value is ignored */ + qSSVAL(infoclass); + domainname = lp_workgroup(); + domlen = strlen(domainname); + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + + switch (infoclass) + { + case 5: + case 3: + default: + qSSVAL(0); /* 2 undocumented bytes */ + qSSVAL(domlen*2); + qSSVAL(domlen*2); /* unicode domain len and maxlen */ + qSIVAL(4); /* domain buffer pointer */ + qSIVAL(2); /* domain sid pointer */ + qunistr(domainname); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + } + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAENUMTRUSTDOM: + DEBUG(1,("LSAENUMTRUSTDOM\n")); + q = *rdata + 0x18; + qSIVAL(0); /* enumeration context */ + qSIVAL(0); /* entries read */ + qSIVAL(0); /* trust information */ + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + break; + + case LSACLOSE: + DEBUG(1,("LSACLOSE\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); + case LSAOPENSECRET: + DEBUG(1,("LSAOPENSECRET\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + break; + + case LSALOOKUPSIDS: + DEBUG(1,("LSAOPENSECRET\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupsid entries %d\n",nentries)); + q += (2+nentries) * 4; /* skip bufptrs */ + /* now we have nentries sids of the form: + uint32 Subauthority count (SAC) + char Revision + char Subaurity count again + char[6] Identifier authority + [uint32 subauthority] * SAC + */ + for (nsids = 0; nsids < nentries; nsids++) + { + DEBUG(4,("lookupsid q in %lx\n",q)); + sids[nsids] = q; + DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); + q += 4+1+1+6+IVAL(q,0)*4; + DEBUG(4,("lookupsid q %lx\n",q)); + } + /* There's 16 bytes of something after all of that, don't know + what it is though - incorrectly documented */ + + DEBUG(4,("lookupsid line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use ?! */ + qSSVAL(0); /* undocumented */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + qunihdr(sidtostring(sids[i])); + DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qunistr(sidtostring(sids[i])); + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSALOOKUPNAMES: + DEBUG(1,("LSALOOKUPNAMES\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ + qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); + qSIVAL(nametorid(names[i])); + DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + default: + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + } + return(True); +} + + BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ { -qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ -qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); -qSIVAL(name_to_rid(names[i])); - DEBUG(4,("lookupnames name_to_rid %d\n",name_to_rid(names[i]))); -qSIVAL(0); /* domain index out of above reference domains */ + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; -#endif + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAREQCHAL: + DEBUG(1,("LSAREQCHAL\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ + q = skip_unicode_string(logonsrv,1) + 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr(logonsrv), + unistr(unicomp))); + + dcauth[cnum].chal[0] = IVAL(q, 0); + dcauth[cnum].chal[1] = IVAL(q, 4); + dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ + dcauth[cnum].cred[1] = IVAL(q, 4); + +DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); + + /* PAXX: set these to random values */ + dcauth[cnum].svrchal[0] = 0x11111111; + dcauth[cnum].svrchal[1] = 0x22222222; + dcauth[cnum].svrcred[0] = 0x11111111; + dcauth[cnum].svrcred[1] = 0x22222222; + strcpy(machacct,unistr(unicomp)); + strcat(machacct, "$"); + smb_pass = get_smbpwnam(machacct); + if(smb_pass) + memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); + DEBUG(1,("pass %s %s\n", machacct, foo)); + setsesskey(cnum); + q = *rdata + 0x18; + qSIVAL(dcauth[cnum].svrchal[0]); + qSIVAL(dcauth[cnum].svrchal[1]); + +DEBUG(1,("NL: server challenge %08x %08x\n", + dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAAUTH2: + DEBUG(1,("LSAAUTH2\n")); + dump_data(1,q,128); + q = data + 0x18; + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + dump_data(1,unicomp,32); + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + q = align4(q, data); + negflags = qIVAL; + DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), + rcvcred[0], rcvcred[1], negflags)); + +DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", + rcvcred[0], rcvcred[1], negflags)); + + checkcred(cnum, rcvcred[0], rcvcred[1], 0); + q = *rdata + 0x18; + makecred(cnum, 0, q); + q += 8; + + qSIVAL(negflags); + /* update stored client credentials */ + dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; + dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + + case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } + + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); + } + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) + { + /* put the extra sids: PAXX: TODO */ + } + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; + default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); + default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + } + return(True); +} + +static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char calccred[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].cred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + if (IVAL(calccred,0) != cred0 || + IVAL(calccred,4) != cred1) + { + DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); + /* PAXX: do something about it! */ + } else + DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); +} + +static void makecred(int cnum, uint32 time, char *calccred) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", + dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], + IVAL(calccred, 0), IVAL(calccred, 4))); +} + +static void setsesskey(int cnum) +{ + uint32 sum[2]; + char netsum[8]; + char netsesskey[8]; + char icv[8]; + + sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; + sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; + SIVAL(netsum,0,sum[0]); + SIVAL(netsum,4,sum[1]); + E1(dcauth[cnum].md4pw,netsum,icv); + E1(dcauth[cnum].md4pw+9,icv,netsesskey); + dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); + dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); + +DEBUG(1,("NL: session key %08x %08x\n", + dcauth[cnum].sesskey[0], + dcauth[cnum].sesskey[1])); +} + +static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) +{ + static struct uinfo u; + static pstring fullnm; + static pstring ascuser; + extern pstring myname; + static pstring stme; + static pstring stdom; + struct smb_passwd *smb_pass; + + strcpy(ascuser,unistr(user)); + ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ + DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); + + smb_pass = get_smbpwnam(ascuser); + if(!smb_pass) + return 0; + DEBUG(1,("GETU %d\n", __LINE__)); + if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { + DEBUG(1,("pass mismatch:\n")); + dump_data(1,ntowfpass,16); + dump_data(1,smb_pass->smb_nt_passwd,16); + return 0; + } + + DEBUG(1,("GETU %d\n", __LINE__)); + u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; + u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; + u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; + u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; + u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.effectivename = ascuser; + strcpy(fullnm, "Full name of "); + strcat(fullnm, ascuser); + DEBUG(1,("GETU %d\n", __LINE__)); + u.fullname = fullnm; + u.logonscript = "foologin.cmd"; + u.profilepath = "prof"; + u.homedirectory = "foohomes"; + DEBUG(1,("GETU %d\n", __LINE__)); + u.homedirectorydrive = "a:"; + u.logoncount = 7; + u.badpwcount = 8; + u.uid = 778; + DEBUG(1,("GETU %d\n", __LINE__)); + u.gid = 998; + u.ngroups = 2; + u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); + u.groups[0].gid = 776; + DEBUG(1,("GETU %d\n", __LINE__)); + u.groups[0].attr = 0x7; + u.groups[1].gid = 776; + u.groups[1].attr = 0x7; + u.userflags = 0x20; + u.logonserver = stme; + get_myname(myname,NULL); + strcpy(stme, myname); + strupper(stme); + DEBUG(1,("LS %s\n", u.logonserver)); + u.logondomain = stdom; + strcpy(stdom, lp_workgroup()); + strupper(stdom); + DEBUG(1,("DOM %s\n", u.logondomain)); + u.nsids = 0; + u.sids = 0; + DEBUG(1,("GETU %d\n", __LINE__)); + return &u; +}; +#endif /* NTDOMAIN */ /* space in front of this function so that make proto doesn't pick it up */ void _dummy_function(void) { @@ -1156,8 +2171,4 @@ qSIVAL(0); /* domain index out of above reference domains */ NULL, NULL); lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL); lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); - api_lsa_open_policy(NULL,NULL,NULL,NULL); - api_lsa_query_info(NULL,NULL,NULL,NULL); - api_lsa_lookup_sids (NULL,NULL,NULL,NULL); - api_lsa_lookup_names(NULL,NULL,NULL,NULL); } -- cgit From 3dd03e4bb7af903eae162648bbf51da04fa68200 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 9 Oct 1997 16:14:53 +0000 Subject: added #ifdef NTDOMAIN. added call to api_ntLsarpc instead of api_Lsarpc in ipc.c iff NTDOMAIN is defined. (This used to be commit 7bc4c4c27bf18ce3f632d230dc919ea341b5abb0) --- source3/smbd/ipc.c | 4 + source3/smbd/pipes.c | 984 +-------------------------------------------------- 2 files changed, 7 insertions(+), 981 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6da9562c9f..28cdb22889 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2763,7 +2763,11 @@ struct } api_fd_commands [] = { { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, +#ifdef NTDOMAIN + { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, +#else { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, +#endif { NULL, NULL, -1, (BOOL (*)())api_Unsupported } }; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 4dd7aa3e30..6937412e29 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -54,7 +54,7 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { "lsarpc", -#if 0 +#if NTDOMAIN "NETLOGON", #endif NULL @@ -364,6 +364,8 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } + +#ifdef NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -1191,984 +1193,4 @@ BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, return True; } - -#ifdef UNDEFINED_NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - - BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - uchar rc4key[16]; - uchar ntowfpass[16]; - uint32 nentries; - char *policyhandle; - #define MAXSIDS 64 - uchar *sids[MAXSIDS]; /* for lookup SID */ - int nsids; - #define MAXNAMES 64 - uchar *names[MAXNAMES]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAOPENPOLICY: - DEBUG(1,("LSAOPENPOLICY\n")); - char *q = *rdata + 0x18; - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - /* return a 20 byte policy handle */ - /* here's a pretty handle:- */ - qSIVAL(time(NULL)); - qSIVAL(0x810a792f); - qSIVAL(0x11d107d5); - qSIVAL(time(NULL)); - qSIVAL(0x6cbcf800); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - break; - - case LSAQUERYINFOPOLICY: - DEBUG(1,("LSAQUERYINFOPOLICY\n")); - dump_data(1,data,128); - infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ - q = *rdata + 0x18; - qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose - value is ignored */ - qSSVAL(infoclass); - domainname = lp_workgroup(); - domlen = strlen(domainname); - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - - switch (infoclass) - { - case 5: - case 3: - default: - qSSVAL(0); /* 2 undocumented bytes */ - qSSVAL(domlen*2); - qSSVAL(domlen*2); /* unicode domain len and maxlen */ - qSIVAL(4); /* domain buffer pointer */ - qSIVAL(2); /* domain sid pointer */ - qunistr(domainname); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - } - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAENUMTRUSTDOM: - DEBUG(1,("LSAENUMTRUSTDOM\n")); - q = *rdata + 0x18; - qSIVAL(0); /* enumeration context */ - qSIVAL(0); /* entries read */ - qSIVAL(0); /* trust information */ - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - break; - - case LSACLOSE: - DEBUG(1,("LSACLOSE\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAOPENSECRET: - DEBUG(1,("LSAOPENSECRET\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - break; - - case LSALOOKUPSIDS: - DEBUG(1,("LSAOPENSECRET\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupsid entries %d\n",nentries)); - q += (2+nentries) * 4; /* skip bufptrs */ - /* now we have nentries sids of the form: - uint32 Subauthority count (SAC) - char Revision - char Subaurity count again - char[6] Identifier authority - [uint32 subauthority] * SAC - */ - for (nsids = 0; nsids < nentries; nsids++) - { - DEBUG(4,("lookupsid q in %lx\n",q)); - sids[nsids] = q; - DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); - q += 4+1+1+6+IVAL(q,0)*4; - DEBUG(4,("lookupsid q %lx\n",q)); - } - /* There's 16 bytes of something after all of that, don't know - what it is though - incorrectly documented */ - - DEBUG(4,("lookupsid line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use ?! */ - qSSVAL(0); /* undocumented */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunihdr(sidtostring(sids[i])); - DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qunistr(sidtostring(sids[i])); - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSALOOKUPNAMES: - DEBUG(1,("LSALOOKUPNAMES\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) - { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ - } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ - qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); - qSIVAL(nametorid(names[i])); - DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - default: - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); - } - return(True); -} - - BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAREQCHAL: - DEBUG(1,("LSAREQCHAL\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ - q = skip_unicode_string(logonsrv,1) + 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr(logonsrv), - unistr(unicomp))); - - dcauth[cnum].chal[0] = IVAL(q, 0); - dcauth[cnum].chal[1] = IVAL(q, 4); - dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ - dcauth[cnum].cred[1] = IVAL(q, 4); - -DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); - - /* PAXX: set these to random values */ - dcauth[cnum].svrchal[0] = 0x11111111; - dcauth[cnum].svrchal[1] = 0x22222222; - dcauth[cnum].svrcred[0] = 0x11111111; - dcauth[cnum].svrcred[1] = 0x22222222; - strcpy(machacct,unistr(unicomp)); - strcat(machacct, "$"); - smb_pass = get_smbpwnam(machacct); - if(smb_pass) - memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); - DEBUG(1,("pass %s %s\n", machacct, foo)); - setsesskey(cnum); - q = *rdata + 0x18; - qSIVAL(dcauth[cnum].svrchal[0]); - qSIVAL(dcauth[cnum].svrchal[1]); - -DEBUG(1,("NL: server challenge %08x %08x\n", - dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAAUTH2: - DEBUG(1,("LSAAUTH2\n")); - dump_data(1,q,128); - q = data + 0x18; - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - dump_data(1,unicomp,32); - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - q = align4(q, data); - negflags = qIVAL; - DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), - rcvcred[0], rcvcred[1], negflags)); - -DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", - rcvcred[0], rcvcred[1], negflags)); - - checkcred(cnum, rcvcred[0], rcvcred[1], 0); - q = *rdata + 0x18; - makecred(cnum, 0, q); - q += 8; - - qSIVAL(negflags); - /* update stored client credentials */ - dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; - dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - - case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; - default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); - default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - } - return(True); -} - -static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char calccred[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].cred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - if (IVAL(calccred,0) != cred0 || - IVAL(calccred,4) != cred1) - { - DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); - /* PAXX: do something about it! */ - } else - DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); -} - -static void makecred(int cnum, uint32 time, char *calccred) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", - dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], - IVAL(calccred, 0), IVAL(calccred, 4))); -} - -static void setsesskey(int cnum) -{ - uint32 sum[2]; - char netsum[8]; - char netsesskey[8]; - char icv[8]; - - sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; - sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; - SIVAL(netsum,0,sum[0]); - SIVAL(netsum,4,sum[1]); - E1(dcauth[cnum].md4pw,netsum,icv); - E1(dcauth[cnum].md4pw+9,icv,netsesskey); - dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); - dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); - -DEBUG(1,("NL: session key %08x %08x\n", - dcauth[cnum].sesskey[0], - dcauth[cnum].sesskey[1])); -} - -static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) -{ - static struct uinfo u; - static pstring fullnm; - static pstring ascuser; - extern pstring myname; - static pstring stme; - static pstring stdom; - struct smb_passwd *smb_pass; - - strcpy(ascuser,unistr(user)); - ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ - DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); - - smb_pass = get_smbpwnam(ascuser); - if(!smb_pass) - return 0; - DEBUG(1,("GETU %d\n", __LINE__)); - if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { - DEBUG(1,("pass mismatch:\n")); - dump_data(1,ntowfpass,16); - dump_data(1,smb_pass->smb_nt_passwd,16); - return 0; - } - - DEBUG(1,("GETU %d\n", __LINE__)); - u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; - u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; - u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; - u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; - u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.effectivename = ascuser; - strcpy(fullnm, "Full name of "); - strcat(fullnm, ascuser); - DEBUG(1,("GETU %d\n", __LINE__)); - u.fullname = fullnm; - u.logonscript = "foologin.cmd"; - u.profilepath = "prof"; - u.homedirectory = "foohomes"; - DEBUG(1,("GETU %d\n", __LINE__)); - u.homedirectorydrive = "a:"; - u.logoncount = 7; - u.badpwcount = 8; - u.uid = 778; - DEBUG(1,("GETU %d\n", __LINE__)); - u.gid = 998; - u.ngroups = 2; - u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); - u.groups[0].gid = 776; - DEBUG(1,("GETU %d\n", __LINE__)); - u.groups[0].attr = 0x7; - u.groups[1].gid = 776; - u.groups[1].attr = 0x7; - u.userflags = 0x20; - u.logonserver = stme; - get_myname(myname,NULL); - strcpy(stme, myname); - strupper(stme); - DEBUG(1,("LS %s\n", u.logonserver)); - u.logondomain = stdom; - strcpy(stdom, lp_workgroup()); - strupper(stdom); - DEBUG(1,("DOM %s\n", u.logondomain)); - u.nsids = 0; - u.sids = 0; - DEBUG(1,("GETU %d\n", __LINE__)); - return &u; -}; - - #endif /* NTDOMAIN */ -/* space in front of this function so that make proto doesn't pick it up */ - void _dummy_function(void) -{ - UTIME t; - lsa_reply_req_chal(NULL, NULL, NULL, NULL); - lsa_reply_auth_2(NULL, NULL, NULL, NULL, 0); - lsa_reply_srv_pwset(NULL, NULL, NULL, NULL, t, 0); - make_lsa_user_info(NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - 0, 0, - 0, 0, 0, NULL, 0, - NULL, - NULL, NULL, - NULL, NULL); - lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL); - lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); -} -- cgit From f3f44f7dbbc360733da329ef55bb0353ae0a8443 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Oct 1997 18:40:52 +0000 Subject: local.h: Fix spelling mistake :-). namedbsubnet.c: Stop registering 1x name unless we can be a local master. reply.c: Remove ERRbaddirectory code. server.c: Remove abort() - use exit_server() instead. trans2.c: Remove ERRbaddirectory code. Jeremy (jallison@whistle.com) (This used to be commit 76247228896d39312ba896fa229076be3271e2e4) --- source3/smbd/reply.c | 4 +++- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 9 +++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2a3679553c..baccb76291 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -641,13 +641,15 @@ int reply_chkpth(char *inbuf,char *outbuf) unix_ERR_code = ERRbadpath; } - /* Ugly - NT specific hack - but needed (JRA) */ +#if 0 + /* Ugly - NT specific hack - maybe not needed ? (JRA) */ if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbaddirectory; } +#endif return(UNIXERROR(ERRDOS,ERRbadpath)); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e4d433c06f..d387b7375b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2774,7 +2774,7 @@ inode = %x).\n", fsp->name, fnum, dev, inode)); { DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", global_oplocks_open)); - abort(); + exit_server("oplock_break: global_oplocks_open < 0"); } DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7f46604cce..092a069a6e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -608,13 +608,15 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_code = ERRbadpath; } - /* Ugly - NT specific hack - but needed (JRA) */ +#if 0 + /* Ugly - NT specific hack - maybe not needed ? (JRA) */ if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbaddirectory; } +#endif return(ERROR(ERRDOS,ERRbadpath)); } @@ -651,13 +653,16 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_code = ERRbadpath; } - /* Ugly - NT specific hack - but needed (JRA) */ +#if 0 + /* Ugly - NT specific hack - maybe not needed ? (JRA) */ if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbaddirectory; } +#endif + return (UNIXERROR(ERRDOS,ERRbadpath)); } return(ERROR(ERRDOS,ERRbadpath)); -- cgit From 805749baab4e79fbdb9897f22b2c801d9dd9efc2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Oct 1997 01:32:26 +0000 Subject: nmblookup.c: Added -A ability to do status on ip address. smb.h: Added defines we will need for NT SMB calls. trans2.c: Fixed SMB_QUERY_FILE_ALT_NAME_INFO return - this is only for short name returns (and only used when you negotiate NT SMB calls to boot !). Jeremy (jallison@whistle.com) (This used to be commit 53915bd160eda8c099482ddcef74d1d7606e752b) --- source3/smbd/trans2.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 092a069a6e..a56df9cb9c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1181,12 +1181,32 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, data_size = 4; break; - case SMB_QUERY_FILE_NAME_INFO: + /* Get the 8.3 name - used if NT SMB was negotiated. */ case SMB_QUERY_FILE_ALT_NAME_INFO: + { + pstring short_name; + pstrcpy(short_name,fname); + /* Mangle if not already 8.3 */ + if(!is_8_3(short_name, True)) + { + if(!name_map_mangle(short_name,True,SNUM(cnum))) + *short_name = '\0'; + } + strncpy(pdata + 4,short_name,12); + (pdata + 4)[12] = 0; + strupper(pdata + 4); + l = strlen(pdata + 4); + data_size = 4 + l; + SIVAL(pdata,0,l); + } + break; + + case SMB_QUERY_FILE_NAME_INFO: data_size = 4 + l; SIVAL(pdata,0,l); pstrcpy(pdata+4,fname); break; + case SMB_QUERY_FILE_ALLOCATION_INFO: case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; -- cgit From c5e739febe5ab3bcc5d147fe791c788ec72531a3 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 10 Oct 1997 14:48:05 +0000 Subject: Makefile: added credentials.c to smbd credentials.c: using credential structures instead of char* password.c uid.c server.c: added sid and attr to user_struct. smbdes.c: smbhash and str_to_key make public instead of private. pipes.c smb.h: lsa structures, sub-functions. proto.h: usual. (This used to be commit 87a0a944855a673d693d934e446bdc231b1c7f02) --- source3/smbd/password.c | 97 +++-- source3/smbd/pipes.c | 1063 ++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/server.c | 22 +- source3/smbd/uid.c | 15 +- 4 files changed, 1126 insertions(+), 71 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f4d94791cf..af9be289c7 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -96,10 +96,10 @@ tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ user_struct *get_valid_user_struct(uint16 vuid) { - if(vuid == UID_FIELD_INVALID) + if (vuid == UID_FIELD_INVALID) return NULL; vuid -= VUID_OFFSET; - if((vuid >= (uint16)num_validated_users) || + if ((vuid >= (uint16)num_validated_users) || (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1)) return NULL; return &validated_users[vuid]; @@ -111,19 +111,28 @@ invalidate a uid void invalidate_vuid(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); - if(vuser == 0) - return; + + if (vuser == NULL) return; vuser->uid = -1; vuser->gid = -1; - vuser->user_ngroups = 0; - if(vuser->user_groups && - (vuser->user_groups != (gid_t *)vuser->user_igroups)) - free(vuser->user_groups); - vuser->user_groups = NULL; - if(vuser->user_igroups) - free(vuser->user_igroups); - vuser->user_igroups = NULL; + + vuser->n_sids = 0; + + /* same number of igroups as groups as attrs */ + vuser->n_groups = 0; + + if (vuser->groups && (vuser->groups != (gid_t *)vuser->igroups)) + free(vuser->groups); + + if (vuser->igroups) free(vuser->igroups); + if (vuser->attrs ) free(vuser->attrs); + if (vuser->sids ) free(vuser->sids); + + vuser->attrs = NULL; + vuser->sids = NULL; + vuser->igroups = NULL; + vuser->groups = NULL; } @@ -133,7 +142,7 @@ return a validated username char *validated_username(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); - if(vuser == 0) + if (vuser == NULL) return 0; return(vuser->name); } @@ -156,12 +165,11 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) int home_server_len; #endif struct passwd *pwfile; /* for getting real name from passwd file */ - int real_name_len; #if 0 /* * After observing MS-Exchange services writing to a Samba share - * I belive this code is incorrect. Each service does it's own + * I belive this code is incorrect. Each service does its own * sessionsetup_and_X for the same user, and as each service shuts * down, it does a user_logoff_and_X. As we are consolidating multiple * sessionsetup_and_X's onto the same vuid here, when the first service @@ -174,7 +182,7 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) int i; for(i = 0; i < num_validated_users; i++) { vuser = &validated_users[i]; - if( vuser->uid == uid ) + if ( vuser->uid == uid ) return (uint16)(i + VUID_OFFSET); /* User already validated */ } #endif @@ -198,16 +206,21 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) vuser->guest = guest; strcpy(vuser->name,name); - vuser->user_ngroups = 0; - vuser->user_groups = NULL; - vuser->user_igroups = NULL; + vuser->n_sids = 0; + vuser->sids = NULL; + + vuser->n_groups = 0; + vuser->groups = NULL; + vuser->igroups = NULL; + vuser->attrs = NULL; /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(name,uid,gid, - &vuser->user_ngroups, - &vuser->user_igroups, - &vuser->user_groups); + &vuser->n_groups, + &vuser->igroups, + &vuser->groups, + &vuser->attrs); DEBUG(3,("uid %d registered to name %s\n",uid,name)); @@ -215,14 +228,14 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) vuser->home_share = NULL; DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n")); vuser->home_share = Realloc(vuser->home_share, 32); - strcpy(vuser->home_share,"\\\\%L\\HOMES"); + strcpy(vuser->home_share,"\\\\%L\\%U"); - if (nis_error = yp_get_default_domain(&nis_domain)) + if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); DEBUG(3, ("NIS Domain: %s\n", nis_domain)); - if (nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), - &nis_result, &nis_result_len)) + if ((nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), + &nis_result, &nis_result_len)) != 0) DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); if (!nis_error && lp_nis_home_map()) { home_server_len = strcspn(nis_result,":"); @@ -237,19 +250,13 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) } #endif - vuser->real_name = NULL; DEBUG(3, ("Clearing default real name\n")); - vuser->real_name = Realloc(vuser->real_name, 15); - strcpy(vuser->real_name, "\0"); + fstrcpy(vuser->real_name, "\0"); if (lp_unix_realname()) { - if((pwfile=getpwnam(vuser->name))!= NULL) + if ((pwfile=getpwnam(vuser->name))!= NULL) { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); - real_name_len = strcspn(pwfile->pw_gecos, ","); - DEBUG(3, ("Real name length: %d\n", real_name_len)); - vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1); - strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len); - vuser->real_name[real_name_len]='\0'; + fstrcpy(vuser->real_name, pwfile->pw_gecos); } } @@ -702,7 +709,7 @@ static int linux_bigcrypt(char *password,char *salt1, char *crypted) for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { char * p = crypt(password,salt) + 2; - if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) + if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) return(0); password += LINUX_PASSWORD_SEG_CHARS; crypted += strlen(p); @@ -826,10 +833,10 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha unsigned char p21[21]; unsigned char p24[24]; - if(part_passwd == NULL) + if (part_passwd == NULL) DEBUG(10,("No password set - allowing access\n")); /* No password set - always true ! */ - if(part_passwd == NULL) + if (part_passwd == NULL) return 1; memset(p21,'\0',21); @@ -905,7 +912,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); - if((pwlen == 24) && challenge_done) + if ((pwlen == 24) && challenge_done) { DEBUG(4,("Checking SMB password for user %s (l=24)\n",user)); @@ -916,28 +923,28 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) } smb_pass = get_smbpwnam(user); - if(!smb_pass) + if (!smb_pass) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); } /* Ensure the uid's match */ - if(smb_pass->smb_userid != pass->pw_uid) + if (smb_pass->smb_userid != pass->pw_uid) { DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); } - if(Protocol >= PROTOCOL_NT1) + if (Protocol >= PROTOCOL_NT1) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - if(smb_pass->smb_nt_passwd != NULL) + if (smb_pass->smb_nt_passwd != NULL) { DEBUG(4,("Checking NT MD4 password\n")); - if(smb_password_check(password, + if (smb_password_check(password, smb_pass->smb_nt_passwd, (unsigned char *)challenge)) { @@ -1080,7 +1087,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) } /* give up? */ - if(level < 1) + if (level < 1) { update_protected_database(user,False); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 6937412e29..5a6da643d9 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -492,13 +492,13 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->reserved = 0; /* reserved */ } -static void make_rpc_reply(char *inbuf, char *q, int data_len) +static int make_rpc_reply(char *inbuf, char *q, int data_len) { uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; create_rpc_reply(&hdr, callid, data_len); - smb_io_rpc_hdr(False, &hdr, q, q, 4); + return smb_io_rpc_hdr(False, &hdr, q, q, 4) - q; } static int lsa_reply_open_policy(char *q, char *base) @@ -723,30 +723,22 @@ static int lsa_reply_lookup_rids(char *q, char *base, return q - start; } -static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) +static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, + DOM_CHAL *srv_chal, int status) { - memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data)); r_c->status = status; } -#if 0 - char chal[8]; - /* PAXX: set these to random values */ - for (int i = 0; i < 8; i+++) - { - chal[i] = 0xA5; - } -#endif - static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, - char chal[8]) + DOM_CHAL *srv_chal) { char *start = q; LSA_R_REQ_CHAL r_c; /* set up the LSA REQUEST CHALLENGE response */ - make_lsa_r_req_chal(&r_c, chal, 0); + make_lsa_r_req_chal(&r_c, srv_chal, 0); /* store the response in the SMB stream */ q = lsa_io_r_req_chal(False, &r_c, q, base, 4); @@ -1083,7 +1075,7 @@ static void api_lsa_lookup_names( char *param, char *data, *rdata_len = reply_len + 0x18; } -BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, +BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1193,4 +1185,1043 @@ BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, return True; } +static void api_lsa_req_chal( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + int i; + LSA_Q_REQ_CHAL q_r; + + fstring mach_acct; + struct smb_passwd *smb_pass; + + /* grab the challenge... */ + lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); + + fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr2(q_r.uni_logon_srv .buffer), + mach_acct)); + + strcat(mach_acct, "$"); + + smb_pass = get_smbpwnam(mach_acct); + if (smb_pass != NULL) + { + memcpy(vuser->dc.md4pw, smb_pass->smb_nt_passwd, sizeof(vuser->dc.md4pw)); + } + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", mach_acct)); + } + + { + char foo[16]; + for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", vuser->dc.md4pw[i]); + DEBUG(1,("pass %s %s\n", mach_acct, foo)); + } + + /* from client / server challenges and md4 password, generate sess key */ + cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal), + vuser->dc.md4pw, vuser->dc.sess_key); + + /* copy the client credentials for later use */ + memcpy(vuser->dc.srv_chal.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + memcpy(vuser->dc.srv_cred.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + + /* create a server challenge for the client */ + /* PAXX: set these to random values. */ + /* lkcl: paul, you mentioned that it doesn't really matter much */ + for (i = 0; i < 8; i++) + { + vuser->dc.srv_chal.data[i] = 0xA5; + } + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18, + &(vuser->dc.srv_chal)); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; +} + +void no_fn(uint uid) +{ + user_struct *vuser = get_valid_user_struct(uid); + DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); +#if defined(NETGROUP) && defined(AUTOMOUNT) + DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); +#endif +} + +#endif /* NTDOMAIN */ + +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + + BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + uchar rc4key[16]; + uchar ntowfpass[16]; + uint32 nentries; + char *policyhandle; + #define MAXSIDS 64 + uchar *sids[MAXSIDS]; /* for lookup SID */ + int nsids; + #define MAXNAMES 64 + uchar *names[MAXNAMES]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAOPENPOLICY: + DEBUG(1,("LSAOPENPOLICY\n")); + char *q = *rdata + 0x18; + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + /* return a 20 byte policy handle */ + /* here's a pretty handle:- */ + qSIVAL(time(NULL)); + qSIVAL(0x810a792f); + qSIVAL(0x11d107d5); + qSIVAL(time(NULL)); + qSIVAL(0x6cbcf800); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + break; + + case LSAQUERYINFOPOLICY: + DEBUG(1,("LSAQUERYINFOPOLICY\n")); + dump_data(1,data,128); + infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ + q = *rdata + 0x18; + qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose + value is ignored */ + qSSVAL(infoclass); + domainname = lp_workgroup(); + domlen = strlen(domainname); + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + + switch (infoclass) + { + case 5: + case 3: + default: + qSSVAL(0); /* 2 undocumented bytes */ + qSSVAL(domlen*2); + qSSVAL(domlen*2); /* unicode domain len and maxlen */ + qSIVAL(4); /* domain buffer pointer */ + qSIVAL(2); /* domain sid pointer */ + qunistr(domainname); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + } + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAENUMTRUSTDOM: + DEBUG(1,("LSAENUMTRUSTDOM\n")); + q = *rdata + 0x18; + qSIVAL(0); /* enumeration context */ + qSIVAL(0); /* entries read */ + qSIVAL(0); /* trust information */ + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + break; + + case LSACLOSE: + DEBUG(1,("LSACLOSE\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAOPENSECRET: + DEBUG(1,("LSAOPENSECRET\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + break; + + case LSALOOKUPSIDS: + DEBUG(1,("LSAOPENSECRET\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupsid entries %d\n",nentries)); + q += (2+nentries) * 4; /* skip bufptrs */ + /* now we have nentries sids of the form: + uint32 Subauthority count (SAC) + char Revision + char Subaurity count again + char[6] Identifier authority + [uint32 subauthority] * SAC + */ + for (nsids = 0; nsids < nentries; nsids++) + { + DEBUG(4,("lookupsid q in %lx\n",q)); + sids[nsids] = q; + DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); + q += 4+1+1+6+IVAL(q,0)*4; + DEBUG(4,("lookupsid q %lx\n",q)); + } + /* There's 16 bytes of something after all of that, don't know + what it is though - incorrectly documented */ + + DEBUG(4,("lookupsid line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use ?! */ + qSSVAL(0); /* undocumented */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + qunihdr(sidtostring(sids[i])); + DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qunistr(sidtostring(sids[i])); + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSALOOKUPNAMES: + DEBUG(1,("LSALOOKUPNAMES\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ + qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); + qSIVAL(nametorid(names[i])); + DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + default: + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + } + return(True); +} + + BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAREQCHAL: + DEBUG(1,("LSAREQCHAL\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ + q = skip_unicode_string(logonsrv,1) + 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr(logonsrv), + unistr(unicomp))); + + dcauth[cnum].chal[0] = IVAL(q, 0); + dcauth[cnum].chal[1] = IVAL(q, 4); + dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ + dcauth[cnum].cred[1] = IVAL(q, 4); + +DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); + + /* PAXX: set these to random values */ + dcauth[cnum].svrchal[0] = 0x11111111; + dcauth[cnum].svrchal[1] = 0x22222222; + dcauth[cnum].svrcred[0] = 0x11111111; + dcauth[cnum].svrcred[1] = 0x22222222; + strcpy(machacct,unistr(unicomp)); + strcat(machacct, "$"); + smb_pass = get_smbpwnam(machacct); + if(smb_pass) + memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); + DEBUG(1,("pass %s %s\n", machacct, foo)); + setsesskey(cnum); + q = *rdata + 0x18; + qSIVAL(dcauth[cnum].svrchal[0]); + qSIVAL(dcauth[cnum].svrchal[1]); + +DEBUG(1,("NL: server challenge %08x %08x\n", + dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAAUTH2: + DEBUG(1,("LSAAUTH2\n")); + dump_data(1,q,128); + q = data + 0x18; + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + dump_data(1,unicomp,32); + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + q = align4(q, data); + negflags = qIVAL; + DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), + rcvcred[0], rcvcred[1], negflags)); + +DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", + rcvcred[0], rcvcred[1], negflags)); + + checkcred(cnum, rcvcred[0], rcvcred[1], 0); + q = *rdata + 0x18; + makecred(cnum, 0, q); + q += 8; + + qSIVAL(negflags); + /* update stored client credentials */ + dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; + dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + + case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } + + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); + } + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) + { + /* put the extra sids: PAXX: TODO */ + } + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; + default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); + default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + } + return(True); +} + +static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char calccred[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].cred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + if (IVAL(calccred,0) != cred0 || + IVAL(calccred,4) != cred1) + { + DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); + /* PAXX: do something about it! */ + } else + DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); +} + +static void makecred(int cnum, uint32 time, char *calccred) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", + dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], + IVAL(calccred, 0), IVAL(calccred, 4))); +} + +static void setsesskey(int cnum) +{ + uint32 sum[2]; + char netsum[8]; + char netsesskey[8]; + char icv[8]; + + sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; + sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; + SIVAL(netsum,0,sum[0]); + SIVAL(netsum,4,sum[1]); + E1(dcauth[cnum].md4pw,netsum,icv); + E1(dcauth[cnum].md4pw+9,icv,netsesskey); + dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); + dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); + +DEBUG(1,("NL: session key %08x %08x\n", + dcauth[cnum].sesskey[0], + dcauth[cnum].sesskey[1])); +} + +static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) +{ + static struct uinfo u; + static pstring fullnm; + static pstring ascuser; + extern pstring myname; + static pstring stme; + static pstring stdom; + struct smb_passwd *smb_pass; + + strcpy(ascuser,unistr(user)); + ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ + DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); + + smb_pass = get_smbpwnam(ascuser); + if(!smb_pass) + return 0; + DEBUG(1,("GETU %d\n", __LINE__)); + if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { + DEBUG(1,("pass mismatch:\n")); + dump_data(1,ntowfpass,16); + dump_data(1,smb_pass->smb_nt_passwd,16); + return 0; + } + + DEBUG(1,("GETU %d\n", __LINE__)); + u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; + u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; + u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; + u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; + u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.effectivename = ascuser; + strcpy(fullnm, "Full name of "); + strcat(fullnm, ascuser); + DEBUG(1,("GETU %d\n", __LINE__)); + u.fullname = fullnm; + u.logonscript = "foologin.cmd"; + u.profilepath = "prof"; + u.homedirectory = "foohomes"; + DEBUG(1,("GETU %d\n", __LINE__)); + u.homedirectorydrive = "a:"; + u.logoncount = 7; + u.badpwcount = 8; + u.uid = 778; + DEBUG(1,("GETU %d\n", __LINE__)); + u.gid = 998; + u.ngroups = 2; + u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); + u.groups[0].gid = 776; + DEBUG(1,("GETU %d\n", __LINE__)); + u.groups[0].attr = 0x7; + u.groups[1].gid = 776; + u.groups[1].attr = 0x7; + u.userflags = 0x20; + u.logonserver = stme; + get_myname(myname,NULL); + strcpy(stme, myname); + strupper(stme); + DEBUG(1,("LS %s\n", u.logonserver)); + u.logondomain = stdom; + strcpy(stdom, lp_workgroup()); + strupper(stdom); + DEBUG(1,("DOM %s\n", u.logondomain)); + u.nsids = 0; + u.sids = 0; + DEBUG(1,("GETU %d\n", __LINE__)); + return &u; +}; + + #endif /* NTDOMAIN */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d387b7375b..1c31f69389 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3003,7 +3003,8 @@ static int sig_hup() Setup the groups a user belongs to. ****************************************************************************/ int setup_groups(char *user, int uid, int gid, int *p_ngroups, - int **p_igroups, gid_t **p_groups) + int **p_igroups, gid_t **p_groups, + int **p_attrs) { if (-1 == initgroups(user,gid)) { @@ -3018,19 +3019,25 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups, { int i,ngroups; int *igroups; + int *attrs; gid_t grp = 0; ngroups = getgroups(0,&grp); if (ngroups <= 0) ngroups = 32; igroups = (int *)malloc(sizeof(int)*ngroups); + attrs = (int *)malloc(sizeof(int)*ngroups); for (i=0;ingroups = 0; + pcon->igroups = NULL; pcon->groups = NULL; + pcon->attrs = NULL; if (!IS_IPC(cnum)) { /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); + setup_groups(pcon->user,pcon->uid,pcon->gid, + &pcon->ngroups,&pcon->igroups,&pcon->groups,&pcon->attrs); /* check number of connections */ if (!claim_connection(cnum, diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index cdc4e474c6..78614a5b5c 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -227,13 +227,17 @@ BOOL become_user(int cnum, uint16 vuid) if (Connections[cnum].force_user || lp_security() == SEC_SHARE || !(vuser) || (vuser->guest) || - !check_user_ok(cnum,vuser,snum)) { + !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 { + current_user.attrs = vuser->attrs; + } + else + { if (!vuser) { DEBUG(2,("Invalid vuid used %d\n",vuid)); return(False); @@ -243,9 +247,10 @@ BOOL become_user(int cnum, uint16 vuid) 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; + current_user.ngroups = vuser->n_groups; + current_user.groups = vuser->groups; + current_user.igroups = vuser->igroups; + current_user.attrs = vuser->attrs; } if (initial_uid == 0) -- cgit From b94ddf082d73249e3ad1590ee24a5c9c33a15e94 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 10 Oct 1997 16:40:23 +0000 Subject: ipc.c : #if NTDOMAIN call to api_netlogRPC #endif lsaparse.c : renamed lsa_io_q_auth2 to lsa_io_q_auth_2. pipes.c : added api_lsa_reply_auth_2() and api_netlogRPC. proto.h : the usual. (This used to be commit e2e1979b6215080593728942d414a273505877df) --- source3/smbd/ipc.c | 2 + source3/smbd/pipes.c | 1366 +++++++++++++++----------------------------------- 2 files changed, 395 insertions(+), 973 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 28cdb22889..6b255dd405 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2765,6 +2765,8 @@ struct { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, #ifdef NTDOMAIN { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, + { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP }, + { "SetNmdPpHndState", "NETLOGON", 1, api_netlogrpcTNP }, #else { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, #endif diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 5a6da643d9..24f15ba7fd 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -753,15 +753,15 @@ static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, - char resp_cred[8], NEG_FLAGS *flgs, int status) + DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) { - make_lsa_chal(&(r_a->srv_chal), resp_cred); - memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs)); + memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); + memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs)); r_a->status = status; } static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, - char resp_cred[8], int status) + DOM_CHAL *resp_cred, int status) { char *start = q; LSA_R_AUTH_2 r_a; @@ -1185,63 +1185,67 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, return True; } -static void api_lsa_req_chal( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) +static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) { - int reply_len; - + struct smb_passwd *smb_pass = get_smbpwnam(mach_acct); int i; - LSA_Q_REQ_CHAL q_r; - - fstring mach_acct; - struct smb_passwd *smb_pass; - - /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); - fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr2(q_r.uni_logon_srv .buffer), - mach_acct)); - - strcat(mach_acct, "$"); - - smb_pass = get_smbpwnam(mach_acct); if (smb_pass != NULL) { - memcpy(vuser->dc.md4pw, smb_pass->smb_nt_passwd, sizeof(vuser->dc.md4pw)); + memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); } else { /* No such machine account. Should error out here, but we'll print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", mach_acct)); + DEBUG(1,("No account in domain for %s\n", mach_acct)); + return False; } { char foo[16]; - for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", vuser->dc.md4pw[i]); - DEBUG(1,("pass %s %s\n", mach_acct, foo)); + for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]); + DEBUG(4,("pass %s %s\n", mach_acct, foo)); } /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal), - vuser->dc.md4pw, vuser->dc.sess_key); + cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), + dc->md4pw, dc->sess_key); /* copy the client credentials for later use */ - memcpy(vuser->dc.srv_chal.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); - memcpy(vuser->dc.srv_cred.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + memcpy(dc->srv_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); + memcpy(dc->srv_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); /* create a server challenge for the client */ /* PAXX: set these to random values. */ /* lkcl: paul, you mentioned that it doesn't really matter much */ for (i = 0; i < 8; i++) { - vuser->dc.srv_chal.data[i] = 0xA5; + dc->srv_chal.data[i] = 0xA5; } + return True; +} + +static void api_lsa_req_chal( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + LSA_Q_REQ_CHAL q_r; + + fstring mach_acct; + + /* grab the challenge... */ + lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); + + fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); + + strcat(mach_acct, "$"); + + update_dcinfo(&(vuser->dc), &(q_r.clnt_chal), mach_acct); + /* construct reply. return status is always 0x0 */ reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18, &(vuser->dc.srv_chal)); @@ -1252,976 +1256,392 @@ static void api_lsa_req_chal( user_struct *vuser, *rdata_len = reply_len; } -void no_fn(uint uid) +static void api_lsa_auth_2( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) { - user_struct *vuser = get_valid_user_struct(uid); - DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if defined(NETGROUP) && defined(AUTOMOUNT) - DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif -} + int reply_len; + LSA_Q_AUTH_2 q_a; -#endif /* NTDOMAIN */ + DOM_CHAL srv_chal; + UTIME srv_time; + + srv_time.time = 0; + + /* grab the challenge... */ + lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4); + + /* check that the client credentials are valid */ + cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, + &(vuser->dc.srv_cred), srv_time); + + /* create server credentials for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &srv_chal); + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18, + &srv_chal, 0x0); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; +} -#ifdef UNDEFINED_NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - uchar rc4key[16]; - uchar ntowfpass[16]; - uint32 nentries; - char *policyhandle; - #define MAXSIDS 64 - uchar *sids[MAXSIDS]; /* for lookup SID */ - int nsids; - #define MAXNAMES 64 - uchar *names[MAXNAMES]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } + uint16 opnum = SVAL(data,22); + int pkttype = CVAL(data, 2); - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAOPENPOLICY: - DEBUG(1,("LSAOPENPOLICY\n")); - char *q = *rdata + 0x18; - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - /* return a 20 byte policy handle */ - /* here's a pretty handle:- */ - qSIVAL(time(NULL)); - qSIVAL(0x810a792f); - qSIVAL(0x11d107d5); - qSIVAL(time(NULL)); - qSIVAL(0x6cbcf800); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - break; - - case LSAQUERYINFOPOLICY: - DEBUG(1,("LSAQUERYINFOPOLICY\n")); - dump_data(1,data,128); - infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ - q = *rdata + 0x18; - qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose - value is ignored */ - qSSVAL(infoclass); - domainname = lp_workgroup(); - domlen = strlen(domainname); - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - - switch (infoclass) - { - case 5: - case 3: - default: - qSSVAL(0); /* 2 undocumented bytes */ - qSSVAL(domlen*2); - qSSVAL(domlen*2); /* unicode domain len and maxlen */ - qSIVAL(4); /* domain buffer pointer */ - qSIVAL(2); /* domain sid pointer */ - qunistr(domainname); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - } - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAENUMTRUSTDOM: - DEBUG(1,("LSAENUMTRUSTDOM\n")); - q = *rdata + 0x18; - qSIVAL(0); /* enumeration context */ - qSIVAL(0); /* entries read */ - qSIVAL(0); /* trust information */ - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - break; - - case LSACLOSE: - DEBUG(1,("LSACLOSE\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; + user_struct *vuser = get_valid_user_struct(uid); - case LSAOPENSECRET: - DEBUG(1,("LSAOPENSECRET\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - break; + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } - case LSALOOKUPSIDS: - DEBUG(1,("LSAOPENSECRET\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupsid entries %d\n",nentries)); - q += (2+nentries) * 4; /* skip bufptrs */ - /* now we have nentries sids of the form: - uint32 Subauthority count (SAC) - char Revision - char Subaurity count again - char[6] Identifier authority - [uint32 subauthority] * SAC - */ - for (nsids = 0; nsids < nentries; nsids++) - { - DEBUG(4,("lookupsid q in %lx\n",q)); - sids[nsids] = q; - DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); - q += 4+1+1+6+IVAL(q,0)*4; - DEBUG(4,("lookupsid q %lx\n",q)); - } - /* There's 16 bytes of something after all of that, don't know - what it is though - incorrectly documented */ - - DEBUG(4,("lookupsid line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); + if (vuser == NULL) return False; - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); +#if defined(NETGROUP) && defined(AUTOMOUNT) + DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); +#endif - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + switch (opnum) + { + case LSA_REQCHAL: + { + DEBUG(3,("LSA_REQCHAL\n")); + api_lsa_req_chal(vuser, param, data, rdata, rdata_len); + break; + } - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use ?! */ - qSSVAL(0); /* undocumented */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunihdr(sidtostring(sids[i])); - DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qunistr(sidtostring(sids[i])); - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; + case LSA_AUTH2: + { + DEBUG(3,("LSA_AUTH2\n")); + api_lsa_auth_2(vuser, param, data, rdata, rdata_len); + break; + } - case LSALOOKUPNAMES: - DEBUG(1,("LSALOOKUPNAMES\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) - { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ - } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); + default: + { + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + break; + } + } - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); + return True; +} - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ +#if 0 - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ - qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); - qSIVAL(nametorid(names[i])); - DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; +case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + +case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } - default: - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); } - return(True); -} - - BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; + /* put the extra sids: PAXX: TODO */ } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); +DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); +DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); +DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) { - case LSAREQCHAL: - DEBUG(1,("LSAREQCHAL\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ - q = skip_unicode_string(logonsrv,1) + 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr(logonsrv), - unistr(unicomp))); - - dcauth[cnum].chal[0] = IVAL(q, 0); - dcauth[cnum].chal[1] = IVAL(q, 4); - dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ - dcauth[cnum].cred[1] = IVAL(q, 4); - -DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); - - /* PAXX: set these to random values */ - dcauth[cnum].svrchal[0] = 0x11111111; - dcauth[cnum].svrchal[1] = 0x22222222; - dcauth[cnum].svrcred[0] = 0x11111111; - dcauth[cnum].svrcred[1] = 0x22222222; - strcpy(machacct,unistr(unicomp)); - strcat(machacct, "$"); - smb_pass = get_smbpwnam(machacct); - if(smb_pass) - memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); - DEBUG(1,("pass %s %s\n", machacct, foo)); - setsesskey(cnum); - q = *rdata + 0x18; - qSIVAL(dcauth[cnum].svrchal[0]); - qSIVAL(dcauth[cnum].svrchal[1]); - -DEBUG(1,("NL: server challenge %08x %08x\n", - dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAAUTH2: - DEBUG(1,("LSAAUTH2\n")); - dump_data(1,q,128); - q = data + 0x18; - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - dump_data(1,unicomp,32); - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - q = align4(q, data); - negflags = qIVAL; - DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), - rcvcred[0], rcvcred[1], negflags)); - -DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", - rcvcred[0], rcvcred[1], negflags)); - - checkcred(cnum, rcvcred[0], rcvcred[1], 0); - q = *rdata + 0x18; - makecred(cnum, 0, q); - q += 8; - - qSIVAL(negflags); - /* update stored client credentials */ - dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; - dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - - case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; - default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); - default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + qSIVAL(subauths[i]); } - return(True); -} - -static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char calccred[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].cred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - if (IVAL(calccred,0) != cred0 || - IVAL(calccred,4) != cred1) - { - DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); - /* PAXX: do something about it! */ - } else - DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); -} + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + +case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) +q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) +q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; +default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); +default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); -static void makecred(int cnum, uint32 time, char *calccred) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", - dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], - IVAL(calccred, 0), IVAL(calccred, 4))); -} +#endif /* 0 */ -static void setsesskey(int cnum) +void no_fn(uint uid) { - uint32 sum[2]; - char netsum[8]; - char netsesskey[8]; - char icv[8]; - - sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; - sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; - SIVAL(netsum,0,sum[0]); - SIVAL(netsum,4,sum[1]); - E1(dcauth[cnum].md4pw,netsum,icv); - E1(dcauth[cnum].md4pw+9,icv,netsesskey); - dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); - dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); - -DEBUG(1,("NL: session key %08x %08x\n", - dcauth[cnum].sesskey[0], - dcauth[cnum].sesskey[1])); } -static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) -{ - static struct uinfo u; - static pstring fullnm; - static pstring ascuser; - extern pstring myname; - static pstring stme; - static pstring stdom; - struct smb_passwd *smb_pass; - - strcpy(ascuser,unistr(user)); - ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ - DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); - - smb_pass = get_smbpwnam(ascuser); - if(!smb_pass) - return 0; - DEBUG(1,("GETU %d\n", __LINE__)); - if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { - DEBUG(1,("pass mismatch:\n")); - dump_data(1,ntowfpass,16); - dump_data(1,smb_pass->smb_nt_passwd,16); - return 0; - } - - DEBUG(1,("GETU %d\n", __LINE__)); - u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; - u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; - u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; - u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; - u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.effectivename = ascuser; - strcpy(fullnm, "Full name of "); - strcat(fullnm, ascuser); - DEBUG(1,("GETU %d\n", __LINE__)); - u.fullname = fullnm; - u.logonscript = "foologin.cmd"; - u.profilepath = "prof"; - u.homedirectory = "foohomes"; - DEBUG(1,("GETU %d\n", __LINE__)); - u.homedirectorydrive = "a:"; - u.logoncount = 7; - u.badpwcount = 8; - u.uid = 778; - DEBUG(1,("GETU %d\n", __LINE__)); - u.gid = 998; - u.ngroups = 2; - u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); - u.groups[0].gid = 776; - DEBUG(1,("GETU %d\n", __LINE__)); - u.groups[0].attr = 0x7; - u.groups[1].gid = 776; - u.groups[1].attr = 0x7; - u.userflags = 0x20; - u.logonserver = stme; - get_myname(myname,NULL); - strcpy(stme, myname); - strupper(stme); - DEBUG(1,("LS %s\n", u.logonserver)); - u.logondomain = stdom; - strcpy(stdom, lp_workgroup()); - strupper(stdom); - DEBUG(1,("DOM %s\n", u.logondomain)); - u.nsids = 0; - u.sids = 0; - DEBUG(1,("GETU %d\n", __LINE__)); - return &u; -}; +#endif /* NTDOMAIN */ +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ #endif /* NTDOMAIN */ -- cgit From 7f296a8f905cc40972ed249567e5d985c0ce3825 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 10 Oct 1997 18:03:30 +0000 Subject: added lsa_reply_srv_pwset() (This used to be commit 0d043cfef289ee82287bb6014a164ba83ca87f30) --- source3/smbd/pipes.c | 162 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 96 insertions(+), 66 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 24f15ba7fd..0a94be0aa0 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -747,11 +747,6 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, return q - start; } -static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) -{ - memcpy(cred->data, resp_cred, sizeof(cred->data)); -} - static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) { @@ -777,22 +772,22 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, return q - start; } -static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) +static void make_lsa_dom_chal(DOM_CRED *cred, DOM_CHAL *srv_chal, UTIME srv_time) { - make_lsa_chal(&(cred->challenge), srv_chal); + memcpy(cred->challenge.data, srv_chal->data, sizeof(srv_chal->data)); cred->timestamp = srv_time; } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, - char srv_chal[8], UTIME srv_time, int status) + DOM_CHAL *srv_chal, UTIME srv_time, int status) { make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); r_a->status = status; } static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, + DOM_CHAL *srv_cred, UTIME srv_time, int status) { char *start = q; @@ -922,7 +917,7 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, + DOM_CHAL *srv_cred, UTIME srv_time, LSA_USER_INFO *user_info) { char *start = q; @@ -946,7 +941,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, + DOM_CHAL *srv_cred, UTIME srv_time, uint32 status) { char *start = q; @@ -1276,9 +1271,9 @@ static void api_lsa_auth_2( user_struct *vuser, &(vuser->dc.srv_cred), srv_time); /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &srv_chal); + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); - /* construct reply. return status is always 0x0 */ + /* construct reply. */ reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18, &srv_chal, 0x0); @@ -1289,6 +1284,87 @@ static void api_lsa_auth_2( user_struct *vuser, } +static void api_lsa_srv_pwset( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + LSA_Q_SRV_PWSET q_a; + + DOM_CHAL srv_chal; + UTIME srv_time; + UTIME new_clnt_time; + + srv_time.time = 0; + + /* grab the challenge... */ + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + + /* check that the client credentials are valid */ + cred_assert(&(q_a.clnt_id.cred.challenge), vuser->dc.sess_key, + &(vuser->dc.srv_cred), srv_time); + + new_clnt_time.time = q_a.clnt_id.cred.timestamp.time + 1; + + /* create server credentials for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, &srv_chal); + + *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); + + /* construct reply. always indicate failure. nt keeps going... */ + reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18, + &srv_chal, srv_time, + NT_STATUS_WRONG_PASSWORD|0xC000000); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; +} + +#if 0 +case LSASRVPWSET: + DEBUG(1,("LSASRVPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; +#endif + + BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1331,6 +1407,13 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, break; } + case LSA_SRVPWSET: + { + DEBUG(3,("LSA_SRVPWSET\n")); + api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); + break; + } + default: { DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); @@ -1344,46 +1427,6 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, #if 0 -case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - case LSASAMLOGON: DEBUG(1,("LSASAMLOGON\n")); dump_data(1,data,128); @@ -1631,17 +1674,4 @@ default: #endif /* 0 */ -void no_fn(uint uid) -{ -} - -#endif /* NTDOMAIN */ - -#ifdef UNDEFINED_NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - #endif /* NTDOMAIN */ -- cgit From 422c54ff38c338e213c57f5b882bea8cf8c14b98 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 10 Oct 1997 19:48:51 +0000 Subject: added api_lsa_sam_logon() and api_sam_logoff(). that's it. lots of run-time debugging, now. (This used to be commit 75f32987d8599d10b294dc4e0c0160eecda7296b) --- source3/smbd/pipes.c | 386 ++++++++++++++++++++++++++++----------------------- 1 file changed, 216 insertions(+), 170 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 0a94be0aa0..e6c29fadf6 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -772,29 +772,21 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, return q - start; } -static void make_lsa_dom_chal(DOM_CRED *cred, DOM_CHAL *srv_chal, UTIME srv_time) -{ - memcpy(cred->challenge.data, srv_chal->data, sizeof(srv_chal->data)); - cred->timestamp = srv_time; -} - - static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, - DOM_CHAL *srv_chal, UTIME srv_time, int status) + DOM_CRED *srv_cred, int status) { - make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); + memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred)); r_a->status = status; } static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, - DOM_CHAL *srv_cred, UTIME srv_time, - int status) + DOM_CRED *srv_cred, int status) { char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ - make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); + make_lsa_r_srv_pwset(&r_s, srv_cred, status); /* store the response in the SMB stream */ q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); @@ -917,15 +909,14 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, - DOM_CHAL *srv_cred, UTIME srv_time, - LSA_USER_INFO *user_info) + DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); /* store the user information, if there is any. */ r_s.user = user_info; @@ -941,7 +932,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, - DOM_CHAL *srv_cred, UTIME srv_time, + DOM_CRED *srv_cred, uint32 status) { char *start = q; @@ -949,7 +940,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* XXXX maybe we want to say 'no', reject the client's credentials */ r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); r_s.status = status; @@ -1284,36 +1275,52 @@ static void api_lsa_auth_2( user_struct *vuser, } -static void api_lsa_srv_pwset( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) +static BOOL deal_with_credentials(user_struct *vuser, + DOM_CRED *clnt_cred, DOM_CRED *srv_cred) { - int reply_len; - LSA_Q_SRV_PWSET q_a; - - DOM_CHAL srv_chal; - UTIME srv_time; UTIME new_clnt_time; - srv_time.time = 0; - - /* grab the challenge... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + /* doesn't matter that server time is 0 */ + srv_cred->timestamp.time = 0; /* check that the client credentials are valid */ - cred_assert(&(q_a.clnt_id.cred.challenge), vuser->dc.sess_key, - &(vuser->dc.srv_cred), srv_time); + if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, + &(vuser->dc.srv_cred), clnt_cred->timestamp)) + { + return False; + } - new_clnt_time.time = q_a.clnt_id.cred.timestamp.time + 1; + /* increment client time by one second */ + new_clnt_time.time = clnt_cred->timestamp.time + 1; /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, &srv_chal); + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, + &(srv_cred->challenge)); + /* update the client and server credentials, for use next time... */ *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); + return True; +} + +static void api_lsa_srv_pwset( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + LSA_Q_SRV_PWSET q_a; + + DOM_CRED srv_cred; + + /* grab the challenge and encrypted password ... */ + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); + /* construct reply. always indicate failure. nt keeps going... */ reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18, - &srv_chal, srv_time, + &srv_cred, NT_STATUS_WRONG_PASSWORD|0xC000000); /* construct header, now that we know the reply length */ @@ -1322,111 +1329,133 @@ static void api_lsa_srv_pwset( user_struct *vuser, *rdata_len = reply_len; } -#if 0 -case LSASRVPWSET: - DEBUG(1,("LSASRVPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); +static void api_lsa_sam_logoff( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + LSA_Q_SAM_LOGOFF q_l; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; + DOM_CRED srv_cred; + + /* grab the challenge... */ + lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4); - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + /* construct reply. always indicate success */ + reply_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata + 0x18, + &srv_cred, + 0x0); - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; -#endif + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len; +} -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) + +static void api_lsa_sam_logon( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) { - uint16 opnum = SVAL(data,22); - int pkttype = CVAL(data, 2); + int reply_len; + LSA_Q_SAM_LOGON q_l; + LSA_USER_INFO usr_info; + LSA_USER_INFO *p_usr_info = NULL; - user_struct *vuser = get_valid_user_struct(uid); + DOM_CRED srv_creds; - if (pkttype == 0x0b) /* RPC BIND */ + lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4); + + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); + + if (vuser != NULL) { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } + NTTIME dummy_time; + pstring logon_script; + pstring profile_path; + pstring home_dir; + pstring home_drive; + pstring my_name; + pstring my_workgroup; + pstring dom_sid; + pstring username; + extern pstring myname; + + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; + + get_myname(myname, NULL); + + pstrcpy(logon_script, lp_logon_script()); + pstrcpy(profile_path, lp_logon_path ()); + pstrcpy(dom_sid , lp_domainsid ()); + pstrcpy(my_workgroup, lp_workgroup ()); + + pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer)); + pstrcpy(my_name , myname ); + strupper(my_name); + + pstrcpy(home_drive , "a:" ); + +#if (defined(NETGROUP) && defined(AUTOMOUNT)) + pstrcpy(home_dir , vuser->home_share); +#else + pstrcpy(home_dir , "\\\\%L\\%U"); + standard_sub_basic(home_dir); +#endif - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + p_usr_info = &usr_info; - if (vuser == NULL) return False; + make_lsa_user_info(p_usr_info, - DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if defined(NETGROUP) && defined(AUTOMOUNT) - DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ - switch (opnum) - { - case LSA_REQCHAL: - { - DEBUG(3,("LSA_REQCHAL\n")); - api_lsa_req_chal(vuser, param, data, rdata, rdata_len); - break; - } + username, /* user_name */ + vuser->real_name, /* full_name */ + logon_script, /* logon_script */ + profile_path, /* profile_path */ + home_dir, /* home_dir */ + home_drive, /* dir_drive */ - case LSA_AUTH2: - { - DEBUG(3,("LSA_AUTH2\n")); - api_lsa_auth_2(vuser, param, data, rdata, rdata_len); - break; - } + 0, /* logon_count */ + 0, /* bad_pw_count */ - case LSA_SRVPWSET: - { - DEBUG(3,("LSA_SRVPWSET\n")); - api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); - break; - } + vuser->uid, /* uint32 user_id */ + vuser->gid, /* uint32 group_id */ + 0, /* uint32 num_groups */ + NULL, /* DOM_GID *gids */ + 0x20, /* uint32 user_flgs */ - default: - { - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - break; - } + NULL, /* char sess_key[16] */ + + my_name, /* char *logon_srv */ + my_workgroup, /* char *logon_dom */ + + dom_sid, /* char *dom_sid */ + NULL); /* char *other_sids */ } - return True; + reply_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata + 0x18, + &srv_creds, p_usr_info); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; } #if 0 - case LSASAMLOGON: DEBUG(1,("LSASAMLOGON\n")); dump_data(1,data,128); @@ -1616,62 +1645,79 @@ DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); break; +#endif -case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) -q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) -q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; -default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); -default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum = SVAL(data,22); + int pkttype = CVAL(data, 2); + + user_struct *vuser = get_valid_user_struct(uid); + + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } -#endif /* 0 */ + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + + if (vuser == NULL) return False; + + DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); +#if defined(NETGROUP) && defined(AUTOMOUNT) + DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); +#endif + + switch (opnum) + { + case LSA_REQCHAL: + { + DEBUG(3,("LSA_REQCHAL\n")); + api_lsa_req_chal(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_AUTH2: + { + DEBUG(3,("LSA_AUTH2\n")); + api_lsa_auth_2(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_SRVPWSET: + { + DEBUG(3,("LSA_SRVPWSET\n")); + api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_SAMLOGON: + { + DEBUG(3,("LSA_SAMLOGON\n")); + api_lsa_sam_logon(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_SAMLOGOFF: + { + DEBUG(3,("LSA_SAMLOGOFF\n")); + api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len); + break; + } + + default: + { + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + break; + } + } + + return True; +} #endif /* NTDOMAIN */ -- cgit From b6dd030b45e9dfadb9856a04c256228e7862fdda Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 12 Oct 1997 03:48:47 +0000 Subject: remove { and } from the list of illegal characters in filenames. The CIFS3 spec does not list them as illegal. This allows things like the control panel icon to be placed on a Samba drive. (This used to be commit d2ac9e6fb6e76778154c58217237251d7bb0e98c) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index b0a45ffb47..829e307a85 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -613,7 +613,7 @@ static BOOL illegal_name(char *name) if (!initialised) { - char *ill = "*\\/?<>|\":{}"; + char *ill = "*\\/?<>|\":"; initialised = True; bzero((char *)illegal,256); -- cgit From a26037ac7c1ac218863f9d674dcf85293eb2f085 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Oct 1997 11:46:42 +0000 Subject: added debugging macros (suitable eventually for use in tcpdump, hopefully) (This used to be commit 946d73cf838976b905550288cac3aea7c43959f6) --- source3/smbd/pipes.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index e6c29fadf6..3bfee3e3cf 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -503,15 +503,20 @@ static int make_rpc_reply(char *inbuf, char *q, int data_len) static int lsa_reply_open_policy(char *q, char *base) { + int i; char *start = q; LSA_R_OPEN_POL r_o; /* set up the LSA QUERY INFO response */ - bzero(&(r_o.pol.data), POL_HND_SIZE); + /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ + for (i = 0; i < POL_HND_SIZE; i++) + { + r_o.pol.data[i] = i; + } r_o.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_open_pol(False, &r_o, q, base, 4); + q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -601,7 +606,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, r_q.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_query(False, &r_q, q, base, 4); + q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -697,7 +702,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, r_l.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4); + q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -717,7 +722,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, r_l.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4); + q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -741,7 +746,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, make_lsa_r_req_chal(&r_c, srv_chal, 0); /* store the response in the SMB stream */ - q = lsa_io_r_req_chal(False, &r_c, q, base, 4); + q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -766,7 +771,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); /* store the response in the SMB stream */ - q = lsa_io_r_auth_2(False, &r_a, q, base, 4); + q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -789,7 +794,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, make_lsa_r_srv_pwset(&r_s, srv_cred, status); /* store the response in the SMB stream */ - q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); + q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -924,7 +929,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); /* store the response in the SMB stream */ - q = lsa_io_r_sam_logon(False, &r_s, q, base, 4); + q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -945,7 +950,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, r_s.status = status; /* store the response in the SMB stream */ - q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4); + q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -978,7 +983,7 @@ static void api_lsa_query_info( char *param, char *data, pstring dom_sid; /* grab the info class and policy handle */ - lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4); + lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1004,7 +1009,7 @@ static void api_lsa_lookup_sids( char *param, char *data, fstring dom_sids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1038,7 +1043,7 @@ static void api_lsa_lookup_names( char *param, char *data, uint32 dom_rids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1224,7 +1229,7 @@ static void api_lsa_req_chal( user_struct *vuser, fstring mach_acct; /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); + lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4, 0); fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); @@ -1255,7 +1260,7 @@ static void api_lsa_auth_2( user_struct *vuser, srv_time.time = 0; /* grab the challenge... */ - lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4); + lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4, 0); /* check that the client credentials are valid */ cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, @@ -1313,7 +1318,7 @@ static void api_lsa_srv_pwset( user_struct *vuser, DOM_CRED srv_cred; /* grab the challenge and encrypted password ... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); @@ -1340,7 +1345,7 @@ static void api_lsa_sam_logoff( user_struct *vuser, DOM_CRED srv_cred; /* grab the challenge... */ - lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); @@ -1368,7 +1373,7 @@ static void api_lsa_sam_logon( user_struct *vuser, DOM_CRED srv_creds; - lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); @@ -1655,7 +1660,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, uint16 opnum = SVAL(data,22); int pkttype = CVAL(data, 2); - user_struct *vuser = get_valid_user_struct(uid); + user_struct *vuser; if (pkttype == 0x0b) /* RPC BIND */ { @@ -1666,7 +1671,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - if (vuser == NULL) return False; + if ((vuser = get_valid_user_struct(uid)) == NULL) return False; DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); #if defined(NETGROUP) && defined(AUTOMOUNT) -- cgit From 60575a888aebec898fdaf0f6c0c8269607b2571f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Oct 1997 14:17:55 +0000 Subject: ipc.c: debugging info. found that data = NULL because of short packet length indicated from the ntlsaRPC pipe _royally_ stuffs NT's packet handling. maybe this should go down as a service denial bug to the ntbugtraq list. pipes.c lsaparse.c smbparse.c : added more debug stuff. added length of header to data_len in MSRPC fragment_length field (0x18 bytes short) which caused the above bug from NT 4.0. oops. (This used to be commit a6f8de6815e0b85bb23b302980730501ac0b87e5) --- source3/smbd/ipc.c | 33 ++++++++++++++----------- source3/smbd/pipes.c | 69 +++++++++++++++++++++++++--------------------------- 2 files changed, 52 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6b255dd405..b314d41679 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2801,30 +2801,35 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, subcommand = setup[0]; DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name)); - DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - tdscnt,tpscnt,mdrcnt,mprcnt)); + DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", + tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); for (i=0;api_fd_commands[i].name;i++) + { if (strequal(api_fd_commands[i].pipename, Files[fd].name) && - api_fd_commands[i].subcommand == subcommand && - api_fd_commands[i].fn) - { - DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); - break; - } + api_fd_commands[i].subcommand == subcommand && + api_fd_commands[i].fn) + { + DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); + break; + } + } - rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); + rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024); rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); + DEBUG(10,("calling api_fd_command\n")); + reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); - if (rdata_len > mdrcnt || - rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, + DEBUG(10,("called api_fd_command\n")); + + if (rdata_len > mdrcnt || rparam_len > mprcnt) + { + reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); - } + } /* if we get False back then it's actually unsupported */ diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 3bfee3e3cf..820f596572 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -482,7 +482,7 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->minor = 0; /* minor version 0 */ hdr->pkt_type = 2; /* RPC response packet */ hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 1; /* packed data representation */ + hdr->pack_type = 0x10; /* packed data representation */ hdr->frag_len = data_len; /* fragment length, fill in later */ hdr->auth_len = 0; /* authentication length */ hdr->call_id = call_id; /* call identifier - match incoming RPC */ @@ -507,11 +507,18 @@ static int lsa_reply_open_policy(char *q, char *base) char *start = q; LSA_R_OPEN_POL r_o; + static char handle[20] = + { 0x00, 0x00, 0x00, 0x00, + 0x2f, 0x79, 0x0a, 0x81, + 0xd5, 0x17, 0xd1, 0x11, + 0x80, 0xaf, 0x96, 0xcd, + 0x50, 0xf8, 0xbc, 0x6c + }; /* set up the LSA QUERY INFO response */ /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ for (i = 0; i < POL_HND_SIZE; i++) { - r_o.pol.data[i] = i; + r_o.pol.data[i] = handle[i]; } r_o.status = 0x0; @@ -960,24 +967,16 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, static void api_lsa_open_policy( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - /* we might actually want to decode the query, but it's not necessary */ /* lsa_io_q_open_policy(...); */ - /* return a 20 byte policy handle */ - reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; + /* construct a 20 byte policy handle. return length*/ + *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); } -static void api_lsa_query_info( char *param, char *data, +static int api_lsa_query_info( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - LSA_Q_QUERY_INFO q_i; pstring dom_name; pstring dom_sid; @@ -989,19 +988,13 @@ static void api_lsa_query_info( char *param, char *data, pstrcpy(dom_sid , lp_domainsid()); /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, + return lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, dom_name, dom_sid); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_sids( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_SIDS q_l; pstring dom_name; @@ -1021,21 +1014,15 @@ static void api_lsa_lookup_sids( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, q_l.num_entries, dom_sids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_names( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_RIDS q_l; pstring dom_name; @@ -1056,14 +1043,10 @@ static void api_lsa_lookup_names( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, q_l.num_entries, dom_rids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, @@ -1088,6 +1071,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENPOLICY\n")); api_lsa_open_policy(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1096,6 +1081,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, DEBUG(3,("LSA_QUERYINFOPOLICY\n")); api_lsa_query_info(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1157,6 +1144,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENSECRET\n")); api_lsa_lookup_sids(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1164,6 +1153,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_LOOKUPNAMES\n")); api_lsa_lookup_names(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1657,11 +1648,17 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - uint16 opnum = SVAL(data,22); - int pkttype = CVAL(data, 2); - + uint16 opnum; + char pkttype; user_struct *vuser; + DEBUG(5,("api_netlogrpcTNP data:%x\n", data)); + + if (data == NULL) return False; + + opnum = SVAL(data,22); + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ { DEBUG(4,("netlogon rpc bind %x\n",pkttype)); @@ -1669,7 +1666,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, return True; } - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + DEBUG(4,("netlogon TransactNamedPipe op %x\n", opnum)); if ((vuser = get_valid_user_struct(uid)) == NULL) return False; -- cgit From 78f6bc4eba9f6d68c31b1c7e35243a1b81619b0d Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Oct 1997 17:07:35 +0000 Subject: updated rpc header reply: callid wrong; alloc hint a uint32 not a uint16. still doesn't get rid of the netlogon trans2 request with zero data. (This used to be commit 0cf67955f09d99c452bfc3fdde00dcea98e21db1) --- source3/smbd/pipes.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 820f596572..4f1d015216 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -53,10 +53,11 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { - "lsarpc", #if NTDOMAIN "NETLOGON", + "srvsvc", #endif + "lsarpc", NULL }; @@ -494,17 +495,18 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) static int make_rpc_reply(char *inbuf, char *q, int data_len) { - uint32 callid = RIVAL(inbuf, 12); + uint32 callid = IVAL(inbuf, 12); RPC_HDR hdr; + DEBUG(5,("make_rpc_reply. callid: %x\n", callid)); + create_rpc_reply(&hdr, callid, data_len); - return smb_io_rpc_hdr(False, &hdr, q, q, 4) - q; + return PTR_DIFF(smb_io_rpc_hdr(False, &hdr, q, q, 4), q); } static int lsa_reply_open_policy(char *q, char *base) { int i; - char *start = q; LSA_R_OPEN_POL r_o; static char handle[20] = @@ -526,7 +528,7 @@ static int lsa_reply_open_policy(char *q, char *base) q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) @@ -600,7 +602,6 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, char *dom_name, char *dom_sid) { - char *start = q; LSA_R_QUERY_INFO r_q; /* set up the LSA QUERY INFO response */ @@ -616,7 +617,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } /* pretty much hard-coded choice of "other" sids, unfortunately... */ @@ -700,7 +701,6 @@ static int lsa_reply_lookup_sids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ @@ -712,7 +712,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static int lsa_reply_lookup_rids(char *q, char *base, @@ -720,7 +720,6 @@ static int lsa_reply_lookup_rids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_RIDS r_l; /* set up the LSA Lookup RIDs response */ @@ -732,7 +731,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, @@ -745,7 +744,6 @@ static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DOM_CHAL *srv_chal) { - char *start = q; LSA_R_REQ_CHAL r_c; /* set up the LSA REQUEST CHALLENGE response */ @@ -756,7 +754,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, @@ -770,7 +768,6 @@ static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, DOM_CHAL *resp_cred, int status) { - char *start = q; LSA_R_AUTH_2 r_a; /* set up the LSA AUTH 2 response */ @@ -781,7 +778,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, @@ -794,7 +791,6 @@ static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, DOM_CRED *srv_cred, int status) { - char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ @@ -804,7 +800,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_user_info(LSA_USER_INFO *usr, @@ -923,7 +919,6 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { - char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -939,7 +934,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } @@ -947,7 +942,6 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, DOM_CRED *srv_cred, uint32 status) { - char *start = q; LSA_R_SAM_LOGOFF r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -960,7 +954,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } -- cgit From db20ab9bbdcc8fbfa81883c2d0c952386820de4c Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Oct 1997 19:02:55 +0000 Subject: getting somewhere. ipc.c : removed srvsvc pipe reference: have to do that. pipes.c lsaparse.c smbparse.c : more debugging info. looks a bit like netmon output. (This used to be commit e02aa88e25ae6d4da7953aaff04ff2ae9a656d05) --- source3/smbd/ipc.c | 7 ++-- source3/smbd/pipes.c | 109 ++++++++++++++++++++++++++++----------------------- 2 files changed, 65 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b314d41679..468d34e157 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2762,13 +2762,14 @@ struct BOOL (*fn) (); } api_fd_commands [] = { - { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, #ifdef NTDOMAIN + { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "SetNmdPpHndState", "NETLOGON", 1, api_LsarpcSNPHS }, { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP }, - { "SetNmdPpHndState", "NETLOGON", 1, api_netlogrpcTNP }, #else - { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, + { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP }, #endif { NULL, NULL, -1, (BOOL (*)())api_Unsupported } }; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 4f1d015216..eb8215b7a3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -53,11 +53,10 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { + "lsarpc", #if NTDOMAIN "NETLOGON", - "srvsvc", #endif - "lsarpc", NULL }; @@ -483,7 +482,7 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->minor = 0; /* minor version 0 */ hdr->pkt_type = 2; /* RPC response packet */ hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 0x10; /* packed data representation */ + hdr->pack_type = 1; /* packed data representation */ hdr->frag_len = data_len; /* fragment length, fill in later */ hdr->auth_len = 0; /* authentication length */ hdr->call_id = call_id; /* call identifier - match incoming RPC */ @@ -495,32 +494,24 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) static int make_rpc_reply(char *inbuf, char *q, int data_len) { - uint32 callid = IVAL(inbuf, 12); + uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; - DEBUG(5,("make_rpc_reply. callid: %x\n", callid)); - create_rpc_reply(&hdr, callid, data_len); - return PTR_DIFF(smb_io_rpc_hdr(False, &hdr, q, q, 4), q); + return smb_io_rpc_hdr(False, &hdr, q, q, 4, 0) - q; } static int lsa_reply_open_policy(char *q, char *base) { int i; + char *start = q; LSA_R_OPEN_POL r_o; - static char handle[20] = - { 0x00, 0x00, 0x00, 0x00, - 0x2f, 0x79, 0x0a, 0x81, - 0xd5, 0x17, 0xd1, 0x11, - 0x80, 0xaf, 0x96, 0xcd, - 0x50, 0xf8, 0xbc, 0x6c - }; /* set up the LSA QUERY INFO response */ /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ for (i = 0; i < POL_HND_SIZE; i++) { - r_o.pol.data[i] = handle[i]; + r_o.pol.data[i] = i; } r_o.status = 0x0; @@ -528,7 +519,7 @@ static int lsa_reply_open_policy(char *q, char *base) q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) @@ -602,6 +593,7 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, char *dom_name, char *dom_sid) { + char *start = q; LSA_R_QUERY_INFO r_q; /* set up the LSA QUERY INFO response */ @@ -617,7 +609,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } /* pretty much hard-coded choice of "other" sids, unfortunately... */ @@ -701,6 +693,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { + char *start = q; LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ @@ -712,7 +705,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static int lsa_reply_lookup_rids(char *q, char *base, @@ -720,6 +713,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { + char *start = q; LSA_R_LOOKUP_RIDS r_l; /* set up the LSA Lookup RIDs response */ @@ -731,7 +725,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, @@ -739,11 +733,16 @@ static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, { memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data)); r_c->status = status; + + DEBUG(5,("make_lsa_r_req_chal srv_chal: %lx %lx\n", + *(uint32*)(&((r_c->srv_chal.data[0]))), + *(uint32*)(&((r_c->srv_chal.data[4]))) )); } static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DOM_CHAL *srv_chal) { + char *start = q; LSA_R_REQ_CHAL r_c; /* set up the LSA REQUEST CHALLENGE response */ @@ -754,7 +753,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, @@ -768,6 +767,7 @@ static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, DOM_CHAL *resp_cred, int status) { + char *start = q; LSA_R_AUTH_2 r_a; /* set up the LSA AUTH 2 response */ @@ -778,7 +778,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, @@ -791,6 +791,7 @@ static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, DOM_CRED *srv_cred, int status) { + char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ @@ -800,7 +801,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_user_info(LSA_USER_INFO *usr, @@ -919,6 +920,7 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { + char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -934,7 +936,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } @@ -942,6 +944,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, DOM_CRED *srv_cred, uint32 status) { + char *start = q; LSA_R_SAM_LOGOFF r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -954,23 +957,31 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void api_lsa_open_policy( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + /* we might actually want to decode the query, but it's not necessary */ /* lsa_io_q_open_policy(...); */ - /* construct a 20 byte policy handle. return length*/ - *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); + /* return a 20 byte policy handle */ + reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } -static int api_lsa_query_info( char *param, char *data, +static void api_lsa_query_info( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + LSA_Q_QUERY_INFO q_i; pstring dom_name; pstring dom_sid; @@ -982,13 +993,19 @@ static int api_lsa_query_info( char *param, char *data, pstrcpy(dom_sid , lp_domainsid()); /* construct reply. return status is always 0x0 */ - return lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, + reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, dom_name, dom_sid); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_sids( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + int i; LSA_Q_LOOKUP_SIDS q_l; pstring dom_name; @@ -1008,15 +1025,21 @@ static void api_lsa_lookup_sids( char *param, char *data, } /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, + reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, q_l.num_entries, dom_sids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_names( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + int i; LSA_Q_LOOKUP_RIDS q_l; pstring dom_name; @@ -1037,10 +1060,14 @@ static void api_lsa_lookup_names( char *param, char *data, } /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, + reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, q_l.num_entries, dom_rids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, @@ -1065,8 +1092,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENPOLICY\n")); api_lsa_open_policy(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1075,8 +1100,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, DEBUG(3,("LSA_QUERYINFOPOLICY\n")); api_lsa_query_info(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1138,8 +1161,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENSECRET\n")); api_lsa_lookup_sids(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1147,8 +1168,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_LOOKUPNAMES\n")); api_lsa_lookup_names(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1642,16 +1661,10 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - uint16 opnum; - char pkttype; - user_struct *vuser; - - DEBUG(5,("api_netlogrpcTNP data:%x\n", data)); - - if (data == NULL) return False; + uint16 opnum = SVAL(data,22); + int pkttype = CVAL(data, 2); - opnum = SVAL(data,22); - pkttype = CVAL(data, 2); + user_struct *vuser; if (pkttype == 0x0b) /* RPC BIND */ { @@ -1660,7 +1673,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, return True; } - DEBUG(4,("netlogon TransactNamedPipe op %x\n", opnum)); + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); if ((vuser = get_valid_user_struct(uid)) == NULL) return False; -- cgit From 2259e56a947104b19a1196154af4e43ab15e4b7c Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 13 Oct 1997 12:21:56 +0000 Subject: byteorder.h : debugging output wasn't (still isn't) perfect. credentials.c lsaparse.c smbparse.c : added DEBUG strings. pipes.c : lost some changes, to do with setup of RPC headers. arg. (This used to be commit 9fdd697d17b68293bb95fd68f44c24f0f5b97f5f) --- source3/smbd/pipes.c | 346 ++++++++------------------------------------------- 1 file changed, 54 insertions(+), 292 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index eb8215b7a3..173b3cdd06 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -504,7 +504,6 @@ static int make_rpc_reply(char *inbuf, char *q, int data_len) static int lsa_reply_open_policy(char *q, char *base) { int i; - char *start = q; LSA_R_OPEN_POL r_o; /* set up the LSA QUERY INFO response */ @@ -519,7 +518,7 @@ static int lsa_reply_open_policy(char *q, char *base) q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) @@ -593,7 +592,6 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, char *dom_name, char *dom_sid) { - char *start = q; LSA_R_QUERY_INFO r_q; /* set up the LSA QUERY INFO response */ @@ -609,7 +607,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } /* pretty much hard-coded choice of "other" sids, unfortunately... */ @@ -693,7 +691,6 @@ static int lsa_reply_lookup_sids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ @@ -705,7 +702,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static int lsa_reply_lookup_rids(char *q, char *base, @@ -713,7 +710,6 @@ static int lsa_reply_lookup_rids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_RIDS r_l; /* set up the LSA Lookup RIDs response */ @@ -725,35 +721,35 @@ static int lsa_reply_lookup_rids(char *q, char *base, q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, DOM_CHAL *srv_chal, int status) { - memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data)); + DEBUG(6,("make_lsa_r_req_chal: %d\n", __LINE__)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); r_c->status = status; - - DEBUG(5,("make_lsa_r_req_chal srv_chal: %lx %lx\n", - *(uint32*)(&((r_c->srv_chal.data[0]))), - *(uint32*)(&((r_c->srv_chal.data[4]))) )); } static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DOM_CHAL *srv_chal) { - char *start = q; LSA_R_REQ_CHAL r_c; - /* set up the LSA REQUEST CHALLENGE response */ + DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); + /* set up the LSA REQUEST CHALLENGE response */ make_lsa_r_req_chal(&r_c, srv_chal, 0); /* store the response in the SMB stream */ q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); + DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); + /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, @@ -767,7 +763,6 @@ static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, DOM_CHAL *resp_cred, int status) { - char *start = q; LSA_R_AUTH_2 r_a; /* set up the LSA AUTH 2 response */ @@ -778,7 +773,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, @@ -791,7 +786,6 @@ static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, DOM_CRED *srv_cred, int status) { - char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ @@ -801,7 +795,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_user_info(LSA_USER_INFO *usr, @@ -920,7 +914,6 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { - char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -936,7 +929,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } @@ -944,7 +937,6 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, DOM_CRED *srv_cred, uint32 status) { - char *start = q; LSA_R_SAM_LOGOFF r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -957,55 +949,41 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void api_lsa_open_policy( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - /* we might actually want to decode the query, but it's not necessary */ /* lsa_io_q_open_policy(...); */ /* return a 20 byte policy handle */ - reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; + *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); } static void api_lsa_query_info( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - LSA_Q_QUERY_INFO q_i; pstring dom_name; pstring dom_sid; /* grab the info class and policy handle */ - lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, dom_name, dom_sid); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_sids( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_SIDS q_l; pstring dom_name; @@ -1013,7 +991,7 @@ static void api_lsa_lookup_sids( char *param, char *data, fstring dom_sids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1025,21 +1003,15 @@ static void api_lsa_lookup_sids( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, q_l.num_entries, dom_sids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_names( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_RIDS q_l; pstring dom_name; @@ -1047,7 +1019,7 @@ static void api_lsa_lookup_names( char *param, char *data, uint32 dom_rids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1060,14 +1032,10 @@ static void api_lsa_lookup_names( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, q_l.num_entries, dom_rids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, @@ -1092,6 +1060,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENPOLICY\n")); api_lsa_open_policy(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1100,6 +1069,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, DEBUG(3,("LSA_QUERYINFOPOLICY\n")); api_lsa_query_info(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1161,6 +1131,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENSECRET\n")); api_lsa_lookup_sids(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1168,6 +1139,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_LOOKUPNAMES\n")); api_lsa_lookup_names(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1180,11 +1152,16 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, return True; } -static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) +static BOOL update_dcinfo(int cnum, uint16 vuid, + struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) { - struct smb_passwd *smb_pass = get_smbpwnam(mach_acct); + struct smb_passwd *smb_pass; int i; + unbecome_user(); + smb_pass = get_smbpwnam(mach_acct); + become_user(cnum, vuid); + if (smb_pass != NULL) { memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); @@ -1219,43 +1196,39 @@ static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acc dc->srv_chal.data[i] = 0xA5; } + DEBUG(6,("update_dcinfo: %d\n", __LINE__)); + return True; } -static void api_lsa_req_chal( user_struct *vuser, +static void api_lsa_req_chal( int cnum, uint16 vuid, + user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - LSA_Q_REQ_CHAL q_r; fstring mach_acct; /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_req_chal(True, &q_r, data + 0x18, data, 4, 0); fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); strcat(mach_acct, "$"); - update_dcinfo(&(vuser->dc), &(q_r.clnt_chal), mach_acct); + update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, &(vuser->dc.srv_chal)); - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } static void api_lsa_auth_2( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_AUTH_2 q_a; DOM_CHAL srv_chal; @@ -1264,7 +1237,7 @@ static void api_lsa_auth_2( user_struct *vuser, srv_time.time = 0; /* grab the challenge... */ - lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_auth_2(True, &q_a, data + 0x18, data, 4, 0); /* check that the client credentials are valid */ cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, @@ -1274,13 +1247,8 @@ static void api_lsa_auth_2( user_struct *vuser, cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); /* construct reply. */ - reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, &srv_chal, 0x0); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } @@ -1316,26 +1284,20 @@ static void api_lsa_srv_pwset( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_SRV_PWSET q_a; DOM_CRED srv_cred; /* grab the challenge and encrypted password ... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); /* construct reply. always indicate failure. nt keeps going... */ - reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata, &srv_cred, NT_STATUS_WRONG_PASSWORD|0xC000000); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } @@ -1343,26 +1305,20 @@ static void api_lsa_sam_logoff( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_SAM_LOGOFF q_l; DOM_CRED srv_cred; /* grab the challenge... */ - lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); /* construct reply. always indicate success */ - reply_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata, &srv_cred, 0x0); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } @@ -1370,14 +1326,13 @@ static void api_lsa_sam_logon( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_SAM_LOGON q_l; LSA_USER_INFO usr_info; LSA_USER_INFO *p_usr_info = NULL; DOM_CRED srv_creds; - lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_sam_logon(True, &q_l, data + 0x18, data, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); @@ -1454,208 +1409,11 @@ static void api_lsa_sam_logon( user_struct *vuser, NULL); /* char *other_sids */ } - reply_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata, &srv_creds, p_usr_info); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } -#if 0 -case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); -DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); -DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); -DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; -#endif - BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1687,7 +1445,8 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, case LSA_REQCHAL: { DEBUG(3,("LSA_REQCHAL\n")); - api_lsa_req_chal(vuser, param, data, rdata, rdata_len); + api_lsa_req_chal(cnum, uid, vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1695,6 +1454,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_AUTH2\n")); api_lsa_auth_2(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1702,6 +1462,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_SRVPWSET\n")); api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1709,6 +1470,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_SAMLOGON\n")); api_lsa_sam_logon(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } -- cgit From 081dcc7e8b7c6a336a1fe5e46b90d6cbb9b1a3d2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 13 Oct 1997 12:55:07 +0000 Subject: checked in a file with a compile error. oops! (This used to be commit 28d96c7e6de19a28346d406ccc6fc8b00305903b) --- source3/smbd/pipes.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 173b3cdd06..772e49f41d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -739,7 +739,6 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); - memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); /* set up the LSA REQUEST CHALLENGE response */ make_lsa_r_req_chal(&r_c, srv_chal, 0); -- cgit From 2225fe13766ae07a44e27cc4a1fb665cf5afc804 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 13 Oct 1997 13:35:37 +0000 Subject: debug info added (This used to be commit a3f96555b47265b8cd4d1f735af58375e2591d56) --- source3/smbd/pipes.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 772e49f41d..59592a04ae 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -1164,6 +1164,8 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, if (smb_pass != NULL) { memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); + DEBUG(5,("dc->md4pw(%d) :", sizeof(dc->md4pw))); + dump_data(5, dc->md4pw, 16); } else { @@ -1218,6 +1220,8 @@ static void api_lsa_req_chal( int cnum, uint16 vuid, update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); + DEBUG(6,("api_lsa_req_chal: %d\n", __LINE__)); + /* construct reply. return status is always 0x0 */ *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, &(vuser->dc.srv_chal)); -- cgit From fcc885e0169ac6418cca9e6030863a225dee6adf Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 13 Oct 1997 14:19:17 +0000 Subject: debugging... no idea what i'm doing. (This used to be commit d7a9a02e0a9e1e791810c24bcfcbd39a6bd7dac5) --- source3/smbd/pipes.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 59592a04ae..74bde7493d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -1181,13 +1181,9 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, DEBUG(4,("pass %s %s\n", mach_acct, foo)); } - /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), - dc->md4pw, dc->sess_key); - - /* copy the client credentials for later use */ - memcpy(dc->srv_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); - memcpy(dc->srv_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); + /* copy the client credentials */ + memcpy(dc->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); + memcpy(dc->clnt_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); /* create a server challenge for the client */ /* PAXX: set these to random values. */ @@ -1197,6 +1193,10 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, dc->srv_chal.data[i] = 0xA5; } + /* from client / server challenges and md4 password, generate sess key */ + cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), + dc->md4pw, dc->sess_key); + DEBUG(6,("update_dcinfo: %d\n", __LINE__)); return True; @@ -1218,9 +1218,10 @@ static void api_lsa_req_chal( int cnum, uint16 vuid, strcat(mach_acct, "$"); - update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); + DEBUG(6,("q_r.clnt_chal.data(%d) :", sizeof(q_r.clnt_chal.data))); + dump_data(6, q_r.clnt_chal.data, 8); - DEBUG(6,("api_lsa_req_chal: %d\n", __LINE__)); + update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); /* construct reply. return status is always 0x0 */ *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, -- cgit From 1035aa9c73bd26e0b01781e6b9b8af51b2013a25 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 13 Oct 1997 15:55:54 +0000 Subject: split pipes.c down into util, netlog and ntlsa. (This used to be commit 8fe02c239d70497af449ed0cdf1a32de10021ba1) --- source3/smbd/pipes.c | 1136 +------------------------------------------------- 1 file changed, 1 insertion(+), 1135 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 74bde7493d..91ca69c022 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -28,7 +28,6 @@ #include "includes.h" #include "trans2.h" -#include "nterr.h" #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) @@ -216,7 +215,7 @@ BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, TransactNamedPipe on \PIPE\lsarpc. ****************************************************************************/ -static void LsarpcTNP1(char *data,char **rdata, int *rdata_len) +void LsarpcTNP1(char *data,char **rdata, int *rdata_len) { uint32 dword1, dword2; char pname[] = "\\PIPE\\lsass"; @@ -363,1136 +362,3 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, } return(True); } - - -#ifdef NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - -/* this function is due to be replaced */ -static void initrpcreply(char *inbuf, char *q) -{ - uint32 callid; - - SCVAL(q, 0, 5); q++; /* RPC version 5 */ - SCVAL(q, 0, 0); q++; /* minor version 0 */ - SCVAL(q, 0, 2); q++; /* RPC response packet */ - SCVAL(q, 0, 3); q++; /* first frag + last frag */ - RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */ - RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */ - SSVAL(q, 0, 0); q += 2; /* authentication length */ - callid = RIVAL(inbuf, 12); - RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */ - SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */ - SSVAL(q, 0, 0); q += 2; /* presentation context identifier */ - SCVAL(q, 0, 0); q++; /* cancel count */ - SCVAL(q, 0, 0); q++; /* reserved */ -} - -/* this function is due to be replaced */ -static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) -{ - SSVAL(q, 8, datalen + 4); - SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ - SIVAL(q, datalen, rtnval); - *rlen = datalen + 4; - { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); } -} - -/* RID username mapping function. just for fun, it maps to the unix uid */ -static uint32 name_to_rid(char *user_name) -{ - struct passwd *pw = Get_Pwnam(user_name, False); - if (!pw) - { - DEBUG(1,("Username %s is invalid on this system\n", user_name)); - return (uint32)(-1); - } - - return (uint32)(pw->pw_uid); -} - - -/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ -char *dom_sid_to_string(DOM_SID *sid) -{ - static pstring sidstr; - char subauth[16]; - int i; - uint32 ia = (sid->id_auth[0]) + - (sid->id_auth[1] << 8 ) + - (sid->id_auth[2] << 16) + - (sid->id_auth[3] << 24); - - sprintf(sidstr, "S-%d-%d", sid->sid_no, ia); - - for (i = 0; i < sid->num_auths; i++) - { - sprintf(subauth, "-%d", sid->sub_auths[i]); - strcat(sidstr, subauth); - } - - DEBUG(5,("dom_sid_to_string returning %s\n", sidstr)); - return sidstr; -} - -/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ -/* identauth >= 2^32 can be detected because it will be specified in hex */ -static void make_dom_sid(DOM_SID *sid, char *domsid) -{ - int identauth; - char *p; - - DEBUG(4,("netlogon domain SID: %s\n", domsid)); - - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - sid->sid_no = atoi(p); - - /* identauth in decimal should be < 2^32 */ - /* identauth in hex should be >= 2^32 */ - identauth = atoi(strtok(0,"-")); - - DEBUG(4,("netlogon rev %d\n", sid->sid_no)); - DEBUG(4,("netlogon %s ia %d\n", p, identauth)); - - sid->id_auth[0] = 0; - sid->id_auth[1] = 0; - sid->id_auth[2] = (identauth & 0xff000000) >> 24; - sid->id_auth[3] = (identauth & 0x00ff0000) >> 16; - sid->id_auth[4] = (identauth & 0x0000ff00) >> 8; - sid->id_auth[5] = (identauth & 0x000000ff); - - sid->num_auths = 0; - - while ((p = strtok(0, "-")) != NULL) - { - sid->sub_auths[sid->num_auths++] = atoi(p); - } -} - -static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) -{ - if (hdr == NULL) return; - - hdr->major = 5; /* RPC version 5 */ - hdr->minor = 0; /* minor version 0 */ - hdr->pkt_type = 2; /* RPC response packet */ - hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 1; /* packed data representation */ - hdr->frag_len = data_len; /* fragment length, fill in later */ - hdr->auth_len = 0; /* authentication length */ - hdr->call_id = call_id; /* call identifier - match incoming RPC */ - hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */ - hdr->context_id = 0; /* presentation context identifier */ - hdr->cancel_count = 0; /* cancel count */ - hdr->reserved = 0; /* reserved */ -} - -static int make_rpc_reply(char *inbuf, char *q, int data_len) -{ - uint32 callid = RIVAL(inbuf, 12); - RPC_HDR hdr; - - create_rpc_reply(&hdr, callid, data_len); - return smb_io_rpc_hdr(False, &hdr, q, q, 4, 0) - q; -} - -static int lsa_reply_open_policy(char *q, char *base) -{ - int i; - LSA_R_OPEN_POL r_o; - - /* set up the LSA QUERY INFO response */ - /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ - for (i = 0; i < POL_HND_SIZE; i++) - { - r_o.pol.data[i] = i; - } - r_o.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) -{ - hdr->uni_max_len = max_len; - hdr->uni_str_len = len; - hdr->undoc = terminate; -} - -static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate) -{ - make_uni_hdr(&(hdr->unihdr), max_len, len, terminate); - hdr->undoc_buffer = len > 0 ? 1 : 0; -} - -static void make_unistr(UNISTR *str, char *buf) -{ - /* store the string (null-terminated copy) */ - PutUniCode((char *)(str->buffer), buf); -} - -static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) -{ - /* set up string lengths. add one if string is not null-terminated */ - str->uni_max_len = len + (terminate != 0 ? 1 : 0); - str->undoc = 0; - str->uni_str_len = len; - - /* store the string (null-terminated copy) */ - PutUniCode((char *)str->buffer, buf); - - /* overwrite the last character: some strings are terminated with 4 not 0 */ - str->buffer[len] = (uint16)terminate; -} - -static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) -{ - rid2->type = 0x5; - rid2->undoc = 0x5; - rid2->rid = rid; - rid2->rid_idx = 0; -} - -static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) -{ - int len_sid_str = strlen(sid_str); - - sid2->type = 0x5; - sid2->undoc = 0; - make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0); - make_unistr (&(sid2->str), sid_str); -} - -static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) -{ - int domlen = strlen(dom_name); - - d_q->uni_dom_max_len = domlen * 2; - d_q->padding = 0; - d_q->uni_dom_str_len = domlen * 2; - - d_q->buffer_dom_name = 0; /* domain buffer pointer */ - d_q->buffer_dom_sid = 0; /* domain sid pointer */ - - /* NOT null-terminated: 4-terminated instead! */ - make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); - - make_dom_sid(&(d_q->dom_sid), dom_sid); -} - -static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, - char *dom_name, char *dom_sid) -{ - LSA_R_QUERY_INFO r_q; - - /* set up the LSA QUERY INFO response */ - - r_q.undoc_buffer = 1; /* not null */ - r_q.info_class = q_q->info_class; - - make_dom_query(&r_q.dom.id5, dom_name, dom_sid); - - r_q.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_query(False, &r_q, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -/* pretty much hard-coded choice of "other" sids, unfortunately... */ -static void make_dom_ref(DOM_R_REF *ref, - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int len_dom_name = strlen(dom_name); - int len_other_sid1 = strlen(other_sid1); - int len_other_sid2 = strlen(other_sid2); - int len_other_sid3 = strlen(other_sid3); - - ref->undoc_buffer = 1; - ref->num_ref_doms_1 = 4; - ref->buffer_dom_name = 1; - ref->max_entries = 32; - ref->num_ref_doms_2 = 4; - - make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); - make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); - make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); - make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); - - if (dom_name != NULL) - { - make_unistr(&(ref->uni_dom_name), dom_name); - } - - make_dom_sid(&(ref->ref_dom[0]), dom_sid ); - make_dom_sid(&(ref->ref_dom[1]), other_sid1); - make_dom_sid(&(ref->ref_dom[2]), other_sid2); - make_dom_sid(&(ref->ref_dom[3]), other_sid3); -} - -static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, - int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int i; - - make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, - other_sid1, other_sid2, other_sid3); - - r_l->num_entries = num_entries; - r_l->undoc_buffer = 1; - r_l->num_entries2 = num_entries; - - for (i = 0; i < num_entries; i++) - { - make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); - } - - r_l->num_entries3 = num_entries; -} - -static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, - int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int i; - - make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, - other_sid1, other_sid2, other_sid3); - - r_l->num_entries = num_entries; - r_l->undoc_buffer = 1; - r_l->num_entries2 = num_entries; - - for (i = 0; i < num_entries; i++) - { - make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]); - } - - r_l->num_entries3 = num_entries; -} - -static int lsa_reply_lookup_sids(char *q, char *base, - int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - LSA_R_LOOKUP_SIDS r_l; - - /* set up the LSA Lookup SIDs response */ - make_reply_lookup_sids(&r_l, num_entries, dom_sids, - dom_name, dom_sid, other_sid1, other_sid2, other_sid3); - r_l.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static int lsa_reply_lookup_rids(char *q, char *base, - int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - LSA_R_LOOKUP_RIDS r_l; - - /* set up the LSA Lookup RIDs response */ - make_reply_lookup_rids(&r_l, num_entries, dom_rids, - dom_name, dom_sid, other_sid1, other_sid2, other_sid3); - r_l.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, - DOM_CHAL *srv_chal, int status) -{ - DEBUG(6,("make_lsa_r_req_chal: %d\n", __LINE__)); - memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); - r_c->status = status; -} - -static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, - DOM_CHAL *srv_chal) -{ - LSA_R_REQ_CHAL r_c; - - DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); - - /* set up the LSA REQUEST CHALLENGE response */ - make_lsa_r_req_chal(&r_c, srv_chal, 0); - - /* store the response in the SMB stream */ - q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); - - DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, - DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) -{ - memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); - memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs)); - r_a->status = status; -} - -static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, - DOM_CHAL *resp_cred, int status) -{ - LSA_R_AUTH_2 r_a; - - /* set up the LSA AUTH 2 response */ - - make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); - - /* store the response in the SMB stream */ - q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, - DOM_CRED *srv_cred, int status) -{ - memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred)); - r_a->status = status; -} - -static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, - DOM_CRED *srv_cred, int status) -{ - LSA_R_SRV_PWSET r_s; - - /* set up the LSA Server Password Set response */ - make_lsa_r_srv_pwset(&r_s, srv_cred, status); - - /* store the response in the SMB stream */ - q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_user_info(LSA_USER_INFO *usr, - - NTTIME *logon_time, - NTTIME *logoff_time, - NTTIME *kickoff_time, - NTTIME *pass_last_set_time, - NTTIME *pass_can_change_time, - NTTIME *pass_must_change_time, - - char *user_name, - char *full_name, - char *logon_script, - char *profile_path, - char *home_dir, - char *dir_drive, - - uint16 logon_count, - uint16 bad_pw_count, - - uint32 user_id, - uint32 group_id, - uint32 num_groups, - DOM_GID *gids, - uint32 user_flgs, - - char sess_key[16], - - char *logon_srv, - char *logon_dom, - - char *dom_sid, - char *other_sids) /* space-delimited set of SIDs */ -{ - /* only cope with one "other" sid, right now. */ - /* need to count the number of space-delimited sids */ - int i; - int num_other_sids = other_sids != NULL ? 1 : 0; - - int len_user_name = strlen(user_name ); - int len_full_name = strlen(full_name ); - int len_logon_script = strlen(logon_script); - int len_profile_path = strlen(profile_path); - int len_home_dir = strlen(home_dir ); - int len_dir_drive = strlen(dir_drive ); - - int len_logon_srv = strlen(logon_srv); - int len_logon_dom = strlen(logon_dom); - - usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */ - - usr->logon_time = *logon_time; - usr->logoff_time = *logoff_time; - usr->kickoff_time = *kickoff_time; - usr->pass_last_set_time = *pass_last_set_time; - usr->pass_can_change_time = *pass_can_change_time; - usr->pass_must_change_time = *pass_must_change_time; - - make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4); - make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4); - make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4); - make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4); - make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4); - make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4); - - usr->logon_count = logon_count; - usr->bad_pw_count = bad_pw_count; - - usr->user_id = user_id; - usr->group_id = group_id; - usr->num_groups = num_groups; - usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */ - usr->user_flgs = user_flgs; - - if (sess_key != NULL) - { - memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key)); - } - else - { - bzero(usr->sess_key, sizeof(usr->sess_key)); - } - - make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4); - make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4); - - usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ - - bzero(usr->padding, sizeof(usr->padding)); - - usr->num_other_sids = num_other_sids; - usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; - - make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0); - make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0); - make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0); - make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0); - make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0); - make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0); - - usr->num_groups2 = num_groups; - for (i = 0; i < num_groups; i++) - { - usr->gids[i] = gids[i]; - } - - make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0); - make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0); - - make_dom_sid(&(usr->dom_sid), dom_sid); - make_dom_sid(&(usr->other_sids[0]), other_sids); -} - - -static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, - DOM_CRED *srv_cred, LSA_USER_INFO *user_info) -{ - LSA_R_SAM_LOGON r_s; - - /* XXXX maybe we want to say 'no', reject the client's credentials */ - r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); - - /* store the user information, if there is any. */ - r_s.user = user_info; - r_s.buffer_user = user_info != NULL ? 1 : 0; - r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); - - /* store the response in the SMB stream */ - q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - - -static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, - DOM_CRED *srv_cred, - uint32 status) -{ - LSA_R_SAM_LOGOFF r_s; - - /* XXXX maybe we want to say 'no', reject the client's credentials */ - r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); - - r_s.status = status; - - /* store the response in the SMB stream */ - q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - - -static void api_lsa_open_policy( char *param, char *data, - char **rdata, int *rdata_len ) -{ - /* we might actually want to decode the query, but it's not necessary */ - /* lsa_io_q_open_policy(...); */ - - /* return a 20 byte policy handle */ - *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); -} - -static void api_lsa_query_info( char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_QUERY_INFO q_i; - pstring dom_name; - pstring dom_sid; - - /* grab the info class and policy handle */ - lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, - dom_name, dom_sid); -} - -static void api_lsa_lookup_sids( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int i; - LSA_Q_LOOKUP_SIDS q_l; - pstring dom_name; - pstring dom_sid; - fstring dom_sids[MAX_LOOKUP_SIDS]; - - /* grab the info class and policy handle */ - lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* convert received SIDs to strings, so we can do them. */ - for (i = 0; i < q_l.num_entries; i++) - { - fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i]))); - } - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, - q_l.num_entries, dom_sids, /* text-converted SIDs */ - dom_name, dom_sid, /* domain name, domain SID */ - "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ -} - -static void api_lsa_lookup_names( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int i; - LSA_Q_LOOKUP_RIDS q_l; - pstring dom_name; - pstring dom_sid; - uint32 dom_rids[MAX_LOOKUP_SIDS]; - - /* grab the info class and policy handle */ - lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* convert received RIDs to strings, so we can do them. */ - for (i = 0; i < q_l.num_entries; i++) - { - char *user_name = unistr2(q_l.lookup_name[i].str.buffer); - dom_rids[i] = name_to_rid(user_name); - } - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, - q_l.num_entries, dom_rids, /* text-converted SIDs */ - dom_name, dom_sid, /* domain name, domain SID */ - "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ -} - -BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum = SVAL(data,22); - - int pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - switch (opnum) - { - case LSA_OPENPOLICY: - { - DEBUG(3,("LSA_OPENPOLICY\n")); - api_lsa_open_policy(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_QUERYINFOPOLICY: - { - DEBUG(3,("LSA_QUERYINFOPOLICY\n")); - - api_lsa_query_info(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_ENUMTRUSTDOM: - { - char *q = *rdata + 0x18; - - DEBUG(3,("LSA_ENUMTRUSTDOM\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); /* enumeration context */ - SIVAL(q, 0, 4); /* entries read */ - SIVAL(q, 0, 8); /* trust information */ - - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - - break; - } - - case LSA_CLOSE: - { - char *q = *rdata + 0x18; - - DEBUG(3,("LSA_CLOSE\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); - SIVAL(q, 0, 4); - SIVAL(q, 0, 8); - SIVAL(q, 0, 12); - SIVAL(q, 0, 16); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - - break; - } - - case LSA_OPENSECRET: - { - char *q = *rdata + 0x18; - DEBUG(3,("LSA_OPENSECRET\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); - SIVAL(q, 0, 4); - SIVAL(q, 0, 8); - SIVAL(q, 0, 12); - SIVAL(q, 0, 16); - - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - - break; - } - - case LSA_LOOKUPSIDS: - { - DEBUG(3,("LSA_OPENSECRET\n")); - api_lsa_lookup_sids(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_LOOKUPNAMES: - { - DEBUG(3,("LSA_LOOKUPNAMES\n")); - api_lsa_lookup_names(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - default: - { - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); - break; - } - } - return True; -} - -static BOOL update_dcinfo(int cnum, uint16 vuid, - struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) -{ - struct smb_passwd *smb_pass; - int i; - - unbecome_user(); - smb_pass = get_smbpwnam(mach_acct); - become_user(cnum, vuid); - - if (smb_pass != NULL) - { - memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); - DEBUG(5,("dc->md4pw(%d) :", sizeof(dc->md4pw))); - dump_data(5, dc->md4pw, 16); - } - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain for %s\n", mach_acct)); - return False; - } - - { - char foo[16]; - for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]); - DEBUG(4,("pass %s %s\n", mach_acct, foo)); - } - - /* copy the client credentials */ - memcpy(dc->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); - memcpy(dc->clnt_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); - - /* create a server challenge for the client */ - /* PAXX: set these to random values. */ - /* lkcl: paul, you mentioned that it doesn't really matter much */ - for (i = 0; i < 8; i++) - { - dc->srv_chal.data[i] = 0xA5; - } - - /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), - dc->md4pw, dc->sess_key); - - DEBUG(6,("update_dcinfo: %d\n", __LINE__)); - - return True; -} - -static void api_lsa_req_chal( int cnum, uint16 vuid, - user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_REQ_CHAL q_r; - - fstring mach_acct; - - /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data, 4, 0); - - fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); - - strcat(mach_acct, "$"); - - DEBUG(6,("q_r.clnt_chal.data(%d) :", sizeof(q_r.clnt_chal.data))); - dump_data(6, q_r.clnt_chal.data, 8); - - update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, - &(vuser->dc.srv_chal)); - -} - -static void api_lsa_auth_2( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_AUTH_2 q_a; - - DOM_CHAL srv_chal; - UTIME srv_time; - - srv_time.time = 0; - - /* grab the challenge... */ - lsa_io_q_auth_2(True, &q_a, data + 0x18, data, 4, 0); - - /* check that the client credentials are valid */ - cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, - &(vuser->dc.srv_cred), srv_time); - - /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); - - /* construct reply. */ - *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, - &srv_chal, 0x0); -} - - -static BOOL deal_with_credentials(user_struct *vuser, - DOM_CRED *clnt_cred, DOM_CRED *srv_cred) -{ - UTIME new_clnt_time; - - /* doesn't matter that server time is 0 */ - srv_cred->timestamp.time = 0; - - /* check that the client credentials are valid */ - if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, - &(vuser->dc.srv_cred), clnt_cred->timestamp)) - { - return False; - } - - /* increment client time by one second */ - new_clnt_time.time = clnt_cred->timestamp.time + 1; - - /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, - &(srv_cred->challenge)); - - /* update the client and server credentials, for use next time... */ - *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); - - return True; -} - -static void api_lsa_srv_pwset( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_SRV_PWSET q_a; - - DOM_CRED srv_cred; - - /* grab the challenge and encrypted password ... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data, 4, 0); - - /* checks and updates credentials. creates reply credentials */ - deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); - - /* construct reply. always indicate failure. nt keeps going... */ - *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata, - &srv_cred, - NT_STATUS_WRONG_PASSWORD|0xC000000); -} - - -static void api_lsa_sam_logoff( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_SAM_LOGOFF q_l; - - DOM_CRED srv_cred; - - /* grab the challenge... */ - lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data, 4, 0); - - /* checks and updates credentials. creates reply credentials */ - deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); - - /* construct reply. always indicate success */ - *rdata_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata, - &srv_cred, - 0x0); -} - - -static void api_lsa_sam_logon( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_SAM_LOGON q_l; - LSA_USER_INFO usr_info; - LSA_USER_INFO *p_usr_info = NULL; - - DOM_CRED srv_creds; - - lsa_io_q_sam_logon(True, &q_l, data + 0x18, data, 4, 0); - - /* checks and updates credentials. creates reply credentials */ - deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); - - if (vuser != NULL) - { - NTTIME dummy_time; - pstring logon_script; - pstring profile_path; - pstring home_dir; - pstring home_drive; - pstring my_name; - pstring my_workgroup; - pstring dom_sid; - pstring username; - extern pstring myname; - - dummy_time.low = 0xffffffff; - dummy_time.high = 0x7fffffff; - - get_myname(myname, NULL); - - pstrcpy(logon_script, lp_logon_script()); - pstrcpy(profile_path, lp_logon_path ()); - pstrcpy(dom_sid , lp_domainsid ()); - pstrcpy(my_workgroup, lp_workgroup ()); - - pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer)); - pstrcpy(my_name , myname ); - strupper(my_name); - - pstrcpy(home_drive , "a:" ); - -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - pstrcpy(home_dir , vuser->home_share); -#else - pstrcpy(home_dir , "\\\\%L\\%U"); - standard_sub_basic(home_dir); -#endif - - p_usr_info = &usr_info; - - make_lsa_user_info(p_usr_info, - - &dummy_time, /* logon_time */ - &dummy_time, /* logoff_time */ - &dummy_time, /* kickoff_time */ - &dummy_time, /* pass_last_set_time */ - &dummy_time, /* pass_can_change_time */ - &dummy_time, /* pass_must_change_time */ - - username, /* user_name */ - vuser->real_name, /* full_name */ - logon_script, /* logon_script */ - profile_path, /* profile_path */ - home_dir, /* home_dir */ - home_drive, /* dir_drive */ - - 0, /* logon_count */ - 0, /* bad_pw_count */ - - vuser->uid, /* uint32 user_id */ - vuser->gid, /* uint32 group_id */ - 0, /* uint32 num_groups */ - NULL, /* DOM_GID *gids */ - 0x20, /* uint32 user_flgs */ - - NULL, /* char sess_key[16] */ - - my_name, /* char *logon_srv */ - my_workgroup, /* char *logon_dom */ - - dom_sid, /* char *dom_sid */ - NULL); /* char *other_sids */ - } - - *rdata_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata, - &srv_creds, p_usr_info); -} - - -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum = SVAL(data,22); - int pkttype = CVAL(data, 2); - - user_struct *vuser; - - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - - if ((vuser = get_valid_user_struct(uid)) == NULL) return False; - - DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if defined(NETGROUP) && defined(AUTOMOUNT) - DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif - - switch (opnum) - { - case LSA_REQCHAL: - { - DEBUG(3,("LSA_REQCHAL\n")); - api_lsa_req_chal(cnum, uid, vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_AUTH2: - { - DEBUG(3,("LSA_AUTH2\n")); - api_lsa_auth_2(vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_SRVPWSET: - { - DEBUG(3,("LSA_SRVPWSET\n")); - api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_SAMLOGON: - { - DEBUG(3,("LSA_SAMLOGON\n")); - api_lsa_sam_logon(vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_SAMLOGOFF: - { - DEBUG(3,("LSA_SAMLOGOFF\n")); - api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len); - break; - } - - default: - { - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - break; - } - } - - return True; -} - -#endif /* NTDOMAIN */ -- cgit From 91e56c7b7b5b1a72dc00b468204c007820d3460e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 15 Oct 1997 04:04:38 +0000 Subject: force the salt to be a maximum of 2 characters long in calls to crypt() This might solve some password problems, particulary on HPUX (This used to be commit 45f4ae4327a8836cad22bbf64f1effba6a6eb7f5) --- source3/smbd/password.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index af9be289c7..1b1bd34bcc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1047,6 +1047,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) /* extract relevant info */ strcpy(this_user,pass->pw_name); strcpy(this_salt,pass->pw_passwd); + this_salt[2] = 0; strcpy(this_crypted,pass->pw_passwd); if (!*this_crypted) { -- cgit From df4afea583a8b53aca46e15dcc75bba1af731f9f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 15 Oct 1997 16:51:03 +0000 Subject: added srvsvc basic pipe, straight from paul's code. does NETSHAREENUM and NETSERVERGETINFO. (This used to be commit 96b17b829fc787c15cd366eca604c09d68b5b900) --- source3/smbd/ipc.c | 2 ++ source3/smbd/pipes.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 468d34e157..c29e8656b1 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2764,8 +2764,10 @@ struct { #ifdef NTDOMAIN { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "SetNmdPpHndState", "srvsvc", 1, api_LsarpcSNPHS }, { "SetNmdPpHndState", "NETLOGON", 1, api_LsarpcSNPHS }, { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, + { "TransactNmPipe", "srvsvc", 0x26, api_srvsvcTNP }, { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP }, #else { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 91ca69c022..bf53fa84bc 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -55,6 +55,7 @@ char * known_pipes [] = "lsarpc", #if NTDOMAIN "NETLOGON", + "srvsvc", #endif NULL }; @@ -362,3 +363,84 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, } return(True); } + +BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + int pkttype; + extern pstring myname; + char *servername; + uint32 level; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("srvsvc rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("srvsvc TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("srvsvc LINE %d\n",__LINE__)); + get_myname(myname,NULL); + switch (opnum) + { + case NETSHAREENUM: + q = data + 0x18; + servername = q + 16; + q = skip_unicode_string(servername,1); + if (strlen(unistr(servername)) % 2 == 0) + q += 2; + level = IVAL(q, 0); q += 4; + /* ignore the rest for the moment */ + q = *rdata + 0x18; + SIVAL(q, 0, level); q += 4; + SIVAL(q, 0, 1); q += 4; /* switch value */ + SIVAL(q, 0, 2); q += 4; + SIVAL(q, 0, 2); q += 4; /* number of entries */ + SIVAL(q, 0, 2); q += 4; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + case NETSERVERGETINFO: + { + UNISTR2 uni_str; + q = data + 0x18; + servername = q + 16; + q = skip_unicode_string(servername,1); + if (strlen(unistr(servername)) % 2 == 0) + q += 2; + level = IVAL(q, 0); q += 4; + /* ignore the rest for the moment */ + q = *rdata + 0x18; + SIVAL(q, 0, 101); q += 4; /* switch value */ + SIVAL(q, 0, 2); q += 4; /* bufptr */ + SIVAL(q, 0, 0x1f4); q += 4; /* platform id */ + SIVAL(q, 0, 2); q += 4; /* bufptr for name */ + SIVAL(q, 0, 5); q += 4; /* major version */ + SIVAL(q, 0, 4); q += 4; /* minor version == 5.4 */ + SIVAL(q, 0, 0x4100B); q += 4; /* type */ + SIVAL(q, 0, 2); q += 4; /* comment */ + make_unistr2(&uni_str, myname, strlen(myname)); + q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); + + make_unistr2(&uni_str, lp_serverstring(), strlen(lp_serverstring())); + q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); + + q = align_offset(q, *rdata, 4); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + } + default: + DEBUG(4, ("srvsvc, unknown code: %lx\n", opnum)); + } + return(True); +} + -- cgit From d83845241381fb6ff86890d1d43c3d3bf6522a2b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 15 Oct 1997 19:16:38 +0000 Subject: smb.h smbparse.c pipenetlog.c : whoops, the SAM Logon structure was wrong. updated this, and cifsntdomain.txt. more debug info in pipenetlog.c. the crash is somewhere around deal_with_credentials(). byteorder.h : put in uint8, uint16 and uint32 typecasts around debug info, because sign extending was resulting in ffffffe8 being displayed instead of e8. credentials.c : some debugging info, because i'm tracking a coredump. without gdb. nothing like making things difficult. reply.c : whoops, missed this (important) bit from paul's code, which tells the NT workstation that the MACHINE$ entry doesn't already exist, and we're going to create a default entry with a password "machine" right now. proto.h: the usual. (This used to be commit ed606bc7d4e6fb1091e527ea70a3e950d50a1db4) --- source3/smbd/reply.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index baccb76291..dffb6f05bd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -479,8 +479,31 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ if (user[strlen(user) - 1] == '$') { - computer_id = True; + struct smb_passwd *smb_pass; /* To check if machine account exists */ +#ifdef NTDOMAIN +/* + PAXX: Ack. We don't want to do this. The workstation trust account + with a $ on the end should exist in the local password database + or be mapped to something generic, but not modified. For NT + domain support we must reject this used in certain circumstances + with a code to indicate to the client that it is an invalid use + of a workstation trust account. NTWKS needs this error to join + a domain. This may be the source of future bugs if we cannot + be sure whether to reject this or not. +*/ + smb_pass = get_smbpwnam(user); + if(smb_pass) + { + /* PAXX: This is the NO LOGON workstation trust account stuff */ + DEBUG(4,("Rejecting workstation trust account %s",user)); + SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ + CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ + return(ERROR(0x99,0xc000)); /* 0x99 NT error, 0xc00 */ + } + computer_id = True; +#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */ user[strlen(user) - 1] = '\0'; +#endif } -- cgit From 359d42c08d012b3e1c1bc6ac1071f8add706ba35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Oct 1997 21:53:59 +0000 Subject: ipc.c: Adding Andrews become_root code to the main branch. locking.c: Adding Andrews become_root code to the main branch. pipes.c: Fixing the close_file issue. proto.h: The usual. reply.c: Move smb_pass into NTDOMAIN defined code. Fixing the close_file issue. server.c: Fixing the close_file issue. trans2.c: Fixing the close_file issue. uid.c: Adding Andrews become_root code to the main branch. Jeremy (jallison@whistle.com) (This used to be commit 16fd4337f79ce33f91050c96c4a566221c5d9126) --- source3/smbd/ipc.c | 4 +++ source3/smbd/pipes.c | 4 +-- source3/smbd/reply.c | 26 +++++++++--------- source3/smbd/server.c | 16 +++++++---- source3/smbd/trans2.c | 4 +-- source3/smbd/uid.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 106 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c29e8656b1..142f139d26 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1602,6 +1602,8 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, DEBUG(3,("Setting print name to %s\n",name)); + become_root(True); + for (i=0;ifd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -155,7 +155,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dffb6f05bd..56288df073 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -479,8 +479,8 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ if (user[strlen(user) - 1] == '$') { - struct smb_passwd *smb_pass; /* To check if machine account exists */ #ifdef NTDOMAIN + struct smb_passwd *smb_pass; /* To check if machine account exists */ /* PAXX: Ack. We don't want to do this. The workstation trust account with a $ on the end should exist in the local password database @@ -1178,7 +1178,7 @@ int reply_open(char *inbuf,char *outbuf) } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1188,7 +1188,7 @@ int reply_open(char *inbuf,char *outbuf) if (fmode & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1274,7 +1274,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1282,7 +1282,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1328,7 +1328,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) int i; for (i=0;iuid && Files[i].open) { - close_file(i); + close_file(i,False); } } @@ -2271,7 +2271,7 @@ int reply_close(char *inbuf,char *outbuf) /* try and set the date */ set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum,True); /* We have a cached error */ if(eclass || err) @@ -2318,7 +2318,7 @@ int reply_writeclose(char *inbuf,char *outbuf) set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum,True); DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", timestring(),fnum,cnum,numtowrite,nwritten, @@ -2550,7 +2550,7 @@ int reply_printclose(char *inbuf,char *outbuf) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - close_file(fnum); + close_file(fnum,True); DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); @@ -3187,14 +3187,14 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, fnum2 = find_free_file(); if (fnum2<0) { - close_file(fnum1); + close_file(fnum1,False); return(False); } open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, ofun,st.st_mode,0,&Access,&action); if (!Files[fnum2].open) { - close_file(fnum1); + close_file(fnum1,False); return(False); } @@ -3205,8 +3205,8 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, if (st.st_size) ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); - close_file(fnum1); - close_file(fnum2); + close_file(fnum1,False); + close_file(fnum2,False); return(ret == st.st_size); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1c31f69389..be24ad7781 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1361,8 +1361,13 @@ static void check_magic(int fnum,int cnum) /**************************************************************************** close a file - possibly invalidating the read prediction + +If normal_close is 1 then this came from a normal SMBclose (or equivalent) +operation otherwise it came as the result of some other operation such as +the closing of the connection. In the latter case printing and +magic scripts are not run ****************************************************************************/ -void close_file(int fnum) +void close_file(int fnum, BOOL normal_close) { files_struct *fs_p = &Files[fnum]; int cnum = fs_p->cnum; @@ -1399,11 +1404,12 @@ void close_file(int fnum) unlock_share_entry( cnum, dev, inode, token); /* NT uses smbclose to start a print - weird */ - if (fs_p->print_file) + if (normal_close && fs_p->print_file) print_file(fnum); /* check for magic scripts */ - check_magic(fnum,cnum); + if (normal_close) + check_magic(fnum,cnum); DEBUG(2,("%s %s closed file %s (numopen=%d)\n", timestring(),Connections[cnum].user,fs_p->name, @@ -1575,7 +1581,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, if (*share_locked && lp_share_modes(SNUM(cnum))) unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, Files[fnum].fd_ptr->inode, token); - close_file(fnum); + close_file(fnum,False); /* Share mode no longer locked. */ *share_locked = False; errno = EACCES; @@ -3847,7 +3853,7 @@ static void close_open_files(int cnum) int i; for (i=0;ifd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -235,7 +235,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 78614a5b5c..42ade7e4da 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -481,3 +481,77 @@ int smbrun(char *cmd,char *outfile,BOOL shared) #endif return 1; } + +static struct current_user current_user_saved; +static int become_root_depth; +static pstring become_root_dir; + +/**************************************************************************** +This is used when we need to do a privilaged operation (such as mucking +with share mode files) and temporarily need root access to do it. This +call should always be paired with an unbecome_root() call immediately +after the operation + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void become_root(BOOL save_dir) +{ + if (become_root_depth) { + DEBUG(0,("ERROR: become root depth is non zero\n")); + } + if (save_dir) + GetWd(become_root_dir); + + current_user_saved = current_user; + become_root_depth = 1; + + become_gid(0); + become_uid(0); +} + +/**************************************************************************** +When the privilaged operation is over call this + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void unbecome_root(BOOL restore_dir) +{ + if (become_root_depth != 1) { + DEBUG(0,("ERROR: unbecome root depth is %d\n", + become_root_depth)); + } + + /* we might have done a become_user() while running as root, + if we have then become root again in order to become + non root! */ + if (current_user.uid != 0) { + become_uid(0); + } + + /* restore our gid first */ + if (!become_gid(current_user_saved.gid)) { + DEBUG(0,("ERROR: Failed to restore gid\n")); + exit_server("Failed to restore gid"); + } + +#ifndef NO_SETGROUPS + if (current_user_saved.ngroups > 0) { + if (setgroups(current_user_saved.ngroups, + current_user_saved.groups)<0) + DEBUG(0,("ERROR: setgroups call failed!\n")); + } +#endif + + /* now restore our uid */ + if (!become_uid(current_user_saved.uid)) { + DEBUG(0,("ERROR: Failed to restore uid\n")); + exit_server("Failed to restore uid"); + } + + if (restore_dir) + ChDir(become_root_dir); + + current_user = current_user_saved; + + become_root_depth = 0; +} -- cgit From 50147ca41c12694b9658c15ddf4b2d8b4e1d4746 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Thu, 16 Oct 1997 01:03:18 +0000 Subject: Made changes to the dir cache functions: - They now use the ubi_dLinkList linked list code. This is not a big gain, I suppose. It would be significant if there were lots of doubly-linked lists in the code and I replaced them all. The only other advantage is that the code is more modular, which appeals to my own sense of order, if no one elses. :-} - I allocate space for the entry structure and the strings in one go, instead of using malloc() and separate strdup() calls. This should be more efficient, and allows for a single call to free() to free the whole thing. These are very minor changes, but they do serve to make me more familiar with the code overall. (This used to be commit 1dafef88871338f06dbcbbb67ce3bbbb460d7bb6) --- source3/smbd/dir.c | 204 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 83 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 316b58818f..d69ccfe1c1 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -628,97 +628,135 @@ int TellDir(void *p) } -static int dir_cache_size = 0; -static struct dir_cache { - struct dir_cache *next; - struct dir_cache *prev; - char *path; - char *name; - char *dname; - int snum; -} *dir_cache = NULL; +/* -------------------------------------------------------------------------- ** + * This section manages a global directory cache. + * (It should probably be split into a separate module. crh) + * -------------------------------------------------------------------------- ** + */ -/******************************************************************* -add an entry to the directory cache -********************************************************************/ -void DirCacheAdd(char *path,char *name,char *dname,int snum) -{ - int count; - struct dir_cache *entry = (struct dir_cache *)malloc(sizeof(*entry)); - if (!entry) return; - entry->path = strdup(path); - entry->name = strdup(name); - entry->dname = strdup(dname); - entry->snum = snum; - if (!entry->path || !entry->name || !entry->dname) return; - - entry->next = dir_cache; - entry->prev = NULL; - if (entry->next) entry->next->prev = entry; - dir_cache = entry; - - DEBUG(4,("Added dir cache entry %s %s -> %s\n",path,name,dname)); - - if (dir_cache_size == DIRCACHESIZE) { - for (entry=dir_cache, count=1; - entry->next && count < dir_cache_size + 1; - entry=entry->next, count++) ; - if (entry->next || count != dir_cache_size + 1) { - DEBUG(0,("DirCache bug - please report %d %d\n",dir_cache_size,count)); - } - free(entry->path); - free(entry->name); - free(entry->dname); - if (entry->prev) entry->prev->next = entry->next; - free(entry); - } else { - dir_cache_size++; - } -} +#include "ubi_dLinkList.h" +typedef struct + { + ubi_dlNode node; + char *path; + char *name; + char *dname; + int snum; + } dir_cache_entry; + +static ubi_dlList dir_cache[1] = { { NULL, NULL, 0 } }; + +void DirCacheAdd( char *path, char *name, char *dname, int snum ) + /* ------------------------------------------------------------------------ ** + * Add an entry to the directory cache. + * + * Input: path - + * name - + * dname - + * snum - + * + * Output: None. + * + * ------------------------------------------------------------------------ ** + */ + { + int pathlen; + int namelen; + dir_cache_entry *entry; + + /* Allocate the structure & string space in one go so that it can be freed + * in one call to free(). + */ + pathlen = strlen( path ) +1; /* Bytes required to store path (with nul). */ + namelen = strlen( name ) +1; /* Bytes required to store name (with nul). */ + entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry ) + + pathlen + + namelen + + strlen( dname ) +1 ); + if( NULL == entry ) /* Not adding to the cache is not fatal, */ + return; /* so just return as if nothing happened. */ + + /* Set pointers correctly and load values. */ + entry->path = strcpy( (char *)&entry[1], path); + entry->name = strcpy( &(entry->path[pathlen]), name); + entry->dname = strcpy( &(entry->name[namelen]), dname); + entry->snum = snum; + + /* Add the new entry to the linked list. */ + (void)ubi_dlAddHead( dir_cache, entry ); + DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) ); + + /* Free excess cache entries. */ + while( DIRCACHESIZE < dir_cache->count ) + free( ubi_dlRemTail( dir_cache ) ); + + } /* DirCacheAdd */ + + +char *DirCacheCheck( char *path, char *name, int snum ) + /* ------------------------------------------------------------------------ ** + * Search for an entry to the directory cache. + * + * Input: path - + * name - + * snum - + * + * Output: The dname string of the located entry, or NULL if the entry was + * not found. + * + * Notes: This uses a linear search, which is is okay because of + * the small size of the cache. Use a splay tree or hash + * for large caches. + * + * ------------------------------------------------------------------------ ** + */ + { + dir_cache_entry *entry; -/******************************************************************* -check for an entry in the directory cache -********************************************************************/ -char *DirCacheCheck(char *path,char *name,int snum) -{ - struct dir_cache *entry; - - for (entry=dir_cache; entry; entry=entry->next) { - if (entry->snum == snum && - strcmp(path,entry->path) == 0 && - strcmp(name,entry->name) == 0) { - DEBUG(4,("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); - return(entry->dname); + for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); + NULL != entry; + entry = (dir_cache_entry *)ubi_dlNext( entry ) ) + { + if( entry->snum == snum + && 0 == strcmp( name, entry->name ) + && 0 == strcmp( path, entry->path ) ) + { + DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); + return( entry->dname ); + } } - } return(NULL); -} + } /* DirCacheCheck */ + +void DirCacheFlush( int snum ) + /* ------------------------------------------------------------------------ ** + * Remove all cache entries which have an snum that matches the input. + * + * Input: snum - + * + * Output: None. + * + * ------------------------------------------------------------------------ ** + */ + { + dir_cache_entry *entry; + ubi_dlNodePtr next; -/******************************************************************* -flush entries in the dir_cache -********************************************************************/ -void DirCacheFlush(int snum) -{ - struct dir_cache *entry,*next; - - for (entry=dir_cache; entry; entry=next) { - if (entry->snum == snum) { - free(entry->path); - free(entry->dname); - free(entry->name); - next = entry->next; - if (entry->prev) entry->prev->next = entry->next; - if (entry->next) entry->next->prev = entry->prev; - if (dir_cache == entry) dir_cache = entry->next; - free(entry); - dir_cache_size--; - } else { - next = entry->next; + for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); NULL != entry; ) + { + next = ubi_dlNext( entry ); + if( entry->snum == snum ) + free( ubi_dlRemThis( dir_cache, entry ) ); + entry = (dir_cache_entry *)next; } - } -} + } /* DirCacheFlush */ + +/* -------------------------------------------------------------------------- ** + * End of the section that manages the global directory cache. + * -------------------------------------------------------------------------- ** + */ #ifdef REPLACE_GETWD -- cgit From b676826bec7cef3a1c324e0e655588195e80c1c5 Mon Sep 17 00:00:00 2001 From: John Terpstra Date: Thu, 16 Oct 1997 05:33:24 +0000 Subject: Added Michael Johnsons' PAM modifications This patch has been checked over. JHT (This used to be commit c84a043f89ccba001597962cd03e2f2a634c4b08) --- source3/smbd/password.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1b1bd34bcc..9f4f0abcae 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -416,33 +416,33 @@ static int PAM_conv (int num_msg, struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { - int count = 0, replies = 0; + int replies = 0; struct pam_response *reply = NULL; - int size = sizeof(struct pam_response); - #define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \ - if (!reply) return PAM_CONV_ERR; \ - size += sizeof(struct pam_response) #define COPY_STRING(s) (s) ? strdup(s) : NULL - for (count = 0; count < num_msg; count++) { - switch (msg[count]->msg_style) { + reply = malloc(sizeof(struct pam_response) * num_msg); + if (!reply) return PAM_CONV_ERR; + + for (replies = 0; replies < num_msg; replies++) { + switch (msg[replies]->msg_style) { case PAM_PROMPT_ECHO_ON: - GET_MEM; reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_username); + reply[replies].resp = COPY_STRING(PAM_username); /* PAM frees resp */ break; case PAM_PROMPT_ECHO_OFF: - GET_MEM; reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_password); + reply[replies].resp = COPY_STRING(PAM_password); /* PAM frees resp */ break; case PAM_TEXT_INFO: + /* fall through */ + case PAM_ERROR_MSG: /* ignore it... */ + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; break; - case PAM_ERROR_MSG: default: /* Must be an error of some sort... */ free (reply); -- cgit From 10087a663bfda233d3e18137f469f0cc7e769a0a Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Fri, 17 Oct 1997 21:06:20 +0000 Subject: Simply moved the #include for ubi_dLinkList.h from within dir.c to includes.h. More consistent with current practice. (This used to be commit cb51c860b352fb9d07fb3298d0317274ba6c9925) --- source3/smbd/dir.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index d69ccfe1c1..c12305499a 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -634,8 +634,6 @@ int TellDir(void *p) * -------------------------------------------------------------------------- ** */ -#include "ubi_dLinkList.h" - typedef struct { ubi_dlNode node; -- cgit From 0225c88104f8966b6ca1b6ed0485f4753aee4bef Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 18 Oct 1997 15:01:01 +0000 Subject: put the NT_STATUS_ALLOTTED_SPACE_EXCEEDED error in instead of 0x99. whatever that means. (This used to be commit ce54f3a7a965b0a9f888dc45d6f4633609d5ca08) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 56288df073..c5b7c50071 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -26,6 +26,7 @@ #include "includes.h" #include "trans2.h" +#include "nterr.h" /* look in server.c for some explanation of these variables */ extern int Protocol; @@ -498,7 +499,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(4,("Rejecting workstation trust account %s",user)); SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(0x99,0xc000)); /* 0x99 NT error, 0xc00 */ + return(ERROR(NT_STATUS_ALLOTTED_SPACE_EXCEEDED, 0xc000)); /* 0x99 NT error, 0xc00 */ } computer_id = True; #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */ -- cgit From 30ed3b5c77505a835eea9e8d2ff9c6df4395b11e Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 19 Oct 1997 12:24:23 +0000 Subject: pipes.c pipesrvsvc.c : moved stub srvsvc pipe function into separate file, in preparation for further work. (This used to be commit 2f2d18cc9474e1b40765a67242659be7c63a9936) --- source3/smbd/pipes.c | 80 ---------------------------------------------------- 1 file changed, 80 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 8c7e6c69c5..12e54d2bca 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -364,83 +364,3 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } -BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - int pkttype; - extern pstring myname; - char *servername; - uint32 level; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("srvsvc rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("srvsvc TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("srvsvc LINE %d\n",__LINE__)); - get_myname(myname,NULL); - switch (opnum) - { - case NETSHAREENUM: - q = data + 0x18; - servername = q + 16; - q = skip_unicode_string(servername,1); - if (strlen(unistr(servername)) % 2 == 0) - q += 2; - level = IVAL(q, 0); q += 4; - /* ignore the rest for the moment */ - q = *rdata + 0x18; - SIVAL(q, 0, level); q += 4; - SIVAL(q, 0, 1); q += 4; /* switch value */ - SIVAL(q, 0, 2); q += 4; - SIVAL(q, 0, 2); q += 4; /* number of entries */ - SIVAL(q, 0, 2); q += 4; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - case NETSERVERGETINFO: - { - UNISTR2 uni_str; - q = data + 0x18; - servername = q + 16; - q = skip_unicode_string(servername,1); - if (strlen(unistr(servername)) % 2 == 0) - q += 2; - level = IVAL(q, 0); q += 4; - /* ignore the rest for the moment */ - q = *rdata + 0x18; - SIVAL(q, 0, 101); q += 4; /* switch value */ - SIVAL(q, 0, 2); q += 4; /* bufptr */ - SIVAL(q, 0, 0x1f4); q += 4; /* platform id */ - SIVAL(q, 0, 2); q += 4; /* bufptr for name */ - SIVAL(q, 0, 5); q += 4; /* major version */ - SIVAL(q, 0, 4); q += 4; /* minor version == 5.4 */ - SIVAL(q, 0, 0x4100B); q += 4; /* type */ - SIVAL(q, 0, 2); q += 4; /* comment */ - make_unistr2(&uni_str, myname, strlen(myname)); - q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); - - make_unistr2(&uni_str, lp_serverstring(), strlen(lp_serverstring())); - q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); - - q = align_offset(q, *rdata, 4); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - } - default: - DEBUG(4, ("srvsvc, unknown code: %lx\n", opnum)); - } - return(True); -} - -- cgit From f4b4b3e6e35916dc5e280542f5f914e40b25dd21 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Oct 1997 02:50:12 +0000 Subject: casting cleanups (This used to be commit ab849a97821c9e1f199eea8ea2ec477687bed947) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9f4f0abcae..2da8a8f936 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1657,7 +1657,7 @@ BOOL server_cryptkey(char *buf) } /**************************************************************************** -attempted support for server level security +support for server level security ****************************************************************************/ BOOL server_validate(char *buf) { -- cgit From 3e670e4057321911c6674b8abe3c0bdcd684fd09 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Oct 1997 08:46:00 +0000 Subject: a major share modes reorganisation. The shares modes code is now split into separate files. The shared memory implementation is in locking_shm.c. The slow implementation is in locking_slow.c It is all controlled by a struct share_ops structure that has function pointers to the implementation of all the functions needed by a share modes implementation. An initialisation function sets up this structure. This will make adding new implementations easy and clean. This also allowed me to get rid of the ugly code in smbstatus. Now status.c links to the locking code and calls methods in share_ops. I also renamed some things and generally organised things in a much cleaner fashion. Defines and structures specific to each implementation have been moved to the appropriate file and out of smb.h. (This used to be commit 65ab9adaa0d356b8041ed8a507ea52117f2a284e) --- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c5b7c50071..7576ee323b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3422,7 +3422,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) (num_ulocks == 0) && (num_locks == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF)) { - share_lock_token token; + int token; files_struct *fsp = &Files[fnum]; uint32 dev = fsp->fd_ptr->dev; uint32 inode = fsp->fd_ptr->inode; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index be24ad7781..7d9638f01e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1373,7 +1373,7 @@ void close_file(int fnum, BOOL normal_close) int cnum = fs_p->cnum; uint32 dev = fs_p->fd_ptr->dev; uint32 inode = fs_p->fd_ptr->inode; - share_lock_token token; + int token; invalidate_read_prediction(fs_p->fd_ptr->fd); fs_p->open = False; @@ -1477,10 +1477,10 @@ BOOL check_file_sharing(int cnum,char *fname) { int i; int ret = False; - min_share_mode_entry *old_shares = 0; + share_mode_entry *old_shares = 0; int num_share_modes; struct stat sbuf; - share_lock_token token; + int token; int pid = getpid(); uint32 dev, inode; @@ -1509,7 +1509,7 @@ BOOL check_file_sharing(int cnum,char *fname) broke_oplock = False; for(i = 0; i < num_share_modes; i++) { - min_share_mode_entry *share_entry = &old_shares[i]; + share_mode_entry *share_entry = &old_shares[i]; /* * Break oplocks before checking share modes. See comment in @@ -1571,8 +1571,8 @@ free_and_exit: Helper for open_file_shared. Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, - BOOL *share_locked) +static void truncate_unless_locked(int fnum, int cnum, int token, + BOOL *share_locked) { if (Files[fnum].can_write){ if (is_locked(fnum,cnum,0x3FFFFFFF,0)){ @@ -1596,7 +1596,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, /**************************************************************************** check if we can open a file with a share mode ****************************************************************************/ -int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, +int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags) { int old_open_mode = share->share_mode &0xF; @@ -1648,7 +1648,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, BOOL file_existed = file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; - share_lock_token token; + int token; uint32 dev = 0; uint32 inode = 0; int num_share_modes = 0; @@ -1724,7 +1724,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (lp_share_modes(SNUM(cnum))) { int i; - min_share_mode_entry *old_shares = 0; + share_mode_entry *old_shares = 0; if (file_existed) { @@ -1749,7 +1749,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, broke_oplock = False; for(i = 0; i < num_share_modes; i++) { - min_share_mode_entry *share_entry = &old_shares[i]; + share_mode_entry *share_entry = &old_shares[i]; /* * By observation of NetBench, oplocks are broken *before* share @@ -2794,7 +2794,7 @@ Send an oplock break message to another smbd process. If the oplock is held by the local smbd then call the oplock break function directly. ****************************************************************************/ -BOOL request_oplock_break(min_share_mode_entry *share_entry, +BOOL request_oplock_break(share_mode_entry *share_entry, uint32 dev, uint32 inode) { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; @@ -4177,9 +4177,7 @@ void exit_server(char *reason) #endif } -#ifdef FAST_SHARE_MODES - stop_share_mode_mgmt(); -#endif /* FAST_SHARE_MODES */ + locking_end(); DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:"")); exit(0); @@ -5012,10 +5010,8 @@ static void usage(char *pname) if (!open_sockets(is_daemon,port)) exit(1); -#ifdef FAST_SHARE_MODES - if (!start_share_mode_mgmt()) + if (!locking_init()) exit(1); -#endif /* FAST_SHARE_MODES */ /* possibly reload the services file. */ reload_services(True); -- cgit From 423a7c417136af3f6d09b3c1763336dd0a401d4f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 20 Oct 1997 12:10:58 +0000 Subject: util.c password.c : added automount_server() function which, if -DAUTOMOUNT is in use, returns the server name of the NIS auto.map entry. otherwise, it returns local_server. added use of automount_server() for a new substitution %N for NIS home server. this defaults, via automount_server(), to the same functionality as %L if -DAUTOMOUNT is not used. removed vuser->home_share. moved code that grabbed the servername into the separate function automount_server(). loadparm.c : created "logon drive" (default of "") created "logon home" (default of "\\%N\%U") changed default of "logon path" from NULL to "\\%N\%U\profile". ipc.c pipenetlog.c : use lp_logon_drive(), lp_logon_home() and lp_logon_path() in their now easier-to-use form (don't have to check if *lp_logon_path() and manually substitute a default of \\%L\%U and do a standard_sub_basic() on the result, because the default automatically does this. (This used to be commit c6c28a4c3c9010ff9d5eac4bad091189a786d5a0) --- source3/smbd/ipc.c | 31 ++----------------------------- source3/smbd/password.c | 35 ----------------------------------- 2 files changed, 2 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 142f139d26..466781c58c 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1999,9 +1999,6 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /* get NIS home of a previously validated user - simeon */ user_struct *vuser = get_valid_user_struct(vuid); DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); @@ -2059,19 +2056,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,0xffffffff); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); -#else - strcpy(p2,"\\\\%L\\%U"); -#endif - } - standard_sub_basic(p2); + strcpy(p2, lp_logon_path()); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ strcpy(p2,""); @@ -2107,19 +2092,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SSVAL(p,42, Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); -#else - strcpy(p2,"\\\\%L\\%U"); -#endif - } - standard_sub_basic(p2); + strcpy(p2,lp_logon_path()); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2da8a8f936..311ef47679 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -155,15 +155,6 @@ tell random client vuid's (normally zero) from valid vuids. uint16 register_vuid(int uid,int gid, char *name,BOOL guest) { user_struct *vuser; - -#if (defined(NETGROUP) && defined (AUTOMOUNT)) - int nis_error; /* returned by yp all functions */ - char *nis_result; /* yp_match inits this */ - int nis_result_len; /* and set this */ - char *nis_domain; /* yp_get_default_domain inits this */ - char *nis_map = (char *)lp_nis_home_map_name(); - int home_server_len; -#endif struct passwd *pwfile; /* for getting real name from passwd file */ #if 0 @@ -224,32 +215,6 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) DEBUG(3,("uid %d registered to name %s\n",uid,name)); -#if (defined(NETGROUP) && defined (AUTOMOUNT)) - vuser->home_share = NULL; - DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n")); - vuser->home_share = Realloc(vuser->home_share, 32); - strcpy(vuser->home_share,"\\\\%L\\%U"); - - if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) - DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); - DEBUG(3, ("NIS Domain: %s\n", nis_domain)); - - if ((nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), - &nis_result, &nis_result_len)) != 0) - DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); - if (!nis_error && lp_nis_home_map()) { - home_server_len = strcspn(nis_result,":"); - DEBUG(3, ("NIS lookup succeeded\n\tHome server length: %d\n",home_server_len)); - vuser->home_share = (char *)Realloc(vuser->home_share, home_server_len+12); - DEBUG(3, ("\tAllocated %d bytes for HOMESHR\n",home_server_len+12 )); - strcpy(vuser->home_share,"\\\\"); - strncat(vuser->home_share, nis_result, home_server_len); - strcat(vuser->home_share,"\\homes"); - DEBUG(2,("\tUser = %s\n\tUID = %d\n\tNIS result = %s\n\tHOMESHR = %s\n", - vuser->name, vuser->uid, nis_result, vuser->home_share)); - } -#endif - DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->real_name, "\0"); if (lp_unix_realname()) { -- cgit From 79f4fb52c1ed56fd843f81b4eb0cdd2991d4d0f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Oct 1997 18:52:04 +0000 Subject: loadparm.c: Changed 'interfaces only' parameter to 'bind interfaces only'. Added 'dos filetimes' parameter for UTIME fix. locking_shm.c: Fixed typo (sorry Andrew :-). namepacket.c: Changed lp_interfaces_only() to lp_bind_interfaces_only(). proto.h: The usual. reply.c: Made filetime calls use new file_utime call (wrapper for sys_utime). server.c: Made filetime calls use new file_utime call (wrapper for sys_utime). system.c: Added Andrew's sanity checks to times in sys_utime(). time.c: Moved set_filetime() to server.c. Made null_mtime() global. trans2.c: Made filetime calls use new file_utime call (wrapper for sys_utime). Jeremy (jallison@whistle.com) (This used to be commit 41a1d81c112a82ad2ae1b3c4ee81051f133ce1ed) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/reply.c | 8 +++--- source3/smbd/server.c | 72 +++++++++++++++++++++++++++++++++++++++++++++------ source3/smbd/trans2.c | 2 +- 3 files changed, 69 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7576ee323b..424c7d8183 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -789,7 +789,7 @@ int reply_setatr(char *inbuf,char *outbuf) if (check_name(fname,cnum)) ok = (dos_chmod(cnum,fname,mode,NULL) == 0); if (ok) - ok = set_filetime(fname,mtime); + ok = set_filetime(cnum,fname,mtime); if (!ok) { @@ -2270,7 +2270,7 @@ int reply_close(char *inbuf,char *outbuf) mtime = make_unix_date3(inbuf+smb_vwv1); /* try and set the date */ - set_filetime(Files[fnum].name,mtime); + set_filetime(cnum, Files[fnum].name,mtime); close_file(fnum,True); @@ -2317,7 +2317,7 @@ int reply_writeclose(char *inbuf,char *outbuf) nwritten = write_file(fnum,data,numtowrite); - set_filetime(Files[fnum].name,mtime); + set_filetime(cnum, Files[fnum].name,mtime); close_file(fnum,True); @@ -3787,7 +3787,7 @@ not setting timestamps of 0\n", } /* Set the date on this file */ - if(sys_utime(Files[fnum].name, &unix_times)) + if(file_utime(cnum, Files[fnum].name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7d9638f01e..7639c5940b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -254,7 +254,6 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) return(result); } - /******************************************************************* chmod a file - but preserve some bits ********************************************************************/ @@ -308,6 +307,70 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) return(sys_chmod(fname,unixmode)); } +/******************************************************************* +Wrapper around sys_utime that possibly allows DOS semantics rather +than POSIX. +*******************************************************************/ + +int file_utime(int cnum, char *fname, struct utimbuf *times) +{ + extern struct current_user current_user; + struct stat sb; + int ret = -1; + + if(sys_utime(fname, times) == 0) + return 0; + + if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum))) + return -1; + + /* We have permission (given by the Samba admin) to + break POSIX semantics and allow a user to change + the time on a file they don't own but can write to + (as DOS does). + */ + + if(sys_stat(fname,&sb) != 0) + return -1; + + /* Check if we have write access. */ + if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) + { + if (((sb.st_mode & S_IWOTH) || + Connections[cnum].admin_user || + ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || + ((sb.st_mode & S_IWGRP) && + in_group(sb.st_gid,current_user.gid, + current_user.ngroups,current_user.igroups)))) + { + /* We are allowed to become root and change the filetime. */ + become_root(False); + ret = sys_utime(fname, times); + unbecome_root(False); + } + } + + return ret; +} + +/******************************************************************* +Change a filetime - possibly allowing DOS semantics. +*******************************************************************/ + +BOOL set_filetime(int cnum, char *fname, time_t mtime) +{ + struct utimbuf times; + + if (null_mtime(mtime)) return(True); + + times.modtime = times.actime = mtime; + + if (file_utime(cnum, fname, ×)) { + DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); + } + + return(True); +} /**************************************************************************** check if two filenames are equal @@ -1099,13 +1162,6 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); */ -#if UTIME_WORKAROUND - /* XXXX - is this OK?? */ - /* this works around a utime bug but can cause other problems */ - if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND)) - sys_unlink(fname); -#endif - /* * Ensure we have a valid struct stat so we can search the * open fd table. diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e484b3b2e1..6a7fc292fa 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1433,7 +1433,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, */ if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { - if(sys_utime(fname, &tvs)!=0) + if(file_utime(cnum, fname, &tvs)!=0) { return(ERROR(ERRDOS,ERRnoaccess)); } -- cgit From ea92c8d3f1acb87426e0fa21568cfce433d9c838 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Oct 1997 09:09:55 +0000 Subject: add some debug info (This used to be commit b22fa0d7e3d1158112e03f93a22232e719fe6003) --- source3/smbd/ipc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 466781c58c..4f6c85de9f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2002,6 +2002,8 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); + + DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); /* check it's a supported variant */ if (strcmp(str1,"zWrLh") != 0) return False; -- cgit From 0891bb6a910841455162876be09a92107cd9df00 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Oct 1997 09:34:33 +0000 Subject: rewrote the password server code using the new clientgen.c client interface The new code uses a source netbios name equal to the Samba servers name, not the client name. It also uses NetWkstaUserLogon to do a full network logon. This means it will honour the servers logon restrictions (such as login times etc). (This used to be commit 11de90f972f6d83974425e80014f54e15d495413) --- source3/smbd/password.c | 275 +++++++++++++++++++----------------------------- source3/smbd/reply.c | 11 +- source3/smbd/server.c | 158 +++++++++++++--------------- 3 files changed, 191 insertions(+), 253 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 311ef47679..24ee52ed69 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1475,206 +1475,143 @@ BOOL check_hosts_equiv(char *user) } -int password_client = -1; -static fstring pserver; -static char *secserver_inbuf = NULL; +static struct cli_state cli; /**************************************************************************** -attempted support for server level security +return the client state structure ****************************************************************************/ -BOOL server_cryptkey(char *buf) +struct cli_state *server_client(void) { - pstring outbuf; - fstring pass_protocol; - extern fstring remote_machine; - char *p; - int len; - fstring desthost; - struct in_addr dest_ip; - int port = SMB_PORT; - BOOL ret; - - if(secserver_inbuf == NULL) { - secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(secserver_inbuf == NULL) { - DEBUG(0,("server_cryptkey: malloc fail for input buffer.\n")); - return False; - } - } - - if (password_client >= 0) - close(password_client); - password_client = -1; - - if (Protocol < PROTOCOL_NT1) { - strcpy(pass_protocol,"LM1.2X002"); - } else { - strcpy(pass_protocol,"NT LM 0.12"); - } - - bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); - bzero(outbuf,sizeof(outbuf)); - - for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { - strcpy(desthost,p); - standard_sub_basic(desthost); - strupper(desthost); - - dest_ip = *interpret_addr2(desthost); - if (zero_ip(dest_ip)) { - DEBUG(1,("Can't resolve address for %s\n",p)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",p)); - continue; - } - - password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); - if (password_client >= 0) { - DEBUG(3,("connected to password server %s\n",p)); - StrnCpy(pserver,p,sizeof(pserver)-1); - break; - } - } - - if (password_client < 0) { - DEBUG(1,("password server not available\n")); - return(False); - } - - - /* send a session request (RFC 8002) */ - - /* put in the destination name */ - len = 4; - p = outbuf+len; - name_mangle(desthost,p,' '); - len += name_len(p); - p = outbuf+len; - - /* and my name */ - /* Fix from Frank Varnavas . - We cannot use the same name as the client to - the NT password server, as NT will drop client - connections if the same client name connects - twice. Instead, synthesize a name from our pid. - and the remote machine name. - */ - { - char buf2[32]; /* create name as PIDname */ - sprintf(buf2,"%d", getpid()); - strncpy(&buf2[strlen(buf2)], remote_machine, 31 - strlen(buf2)); - buf2[31] = '\0'; - DEBUG(1,("negprot w/password server as %s\n",buf2)); - name_mangle(buf2,p,' '); - len += name_len(p); - } - - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(password_client,outbuf); - - - if (!receive_smb(password_client,secserver_inbuf,5000) || - CVAL(secserver_inbuf,0) != 0x82) { - DEBUG(1,("%s rejected the session\n",pserver)); - close(password_client); password_client = -1; - return(False); - } + return &cli; +} - DEBUG(3,("got session\n")); +/**************************************************************************** +support for server level security +****************************************************************************/ +struct cli_state *server_cryptkey(void) +{ + fstring desthost; + struct in_addr dest_ip; + extern fstring local_machine; + char *p; + + if (!cli_initialise(&cli)) + return NULL; + + for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { + fstrcpy(desthost,p); + standard_sub_basic(desthost); + strupper(desthost); + + dest_ip = *interpret_addr2(desthost); + if (zero_ip(dest_ip)) { + DEBUG(1,("Can't resolve address for %s\n",p)); + continue; + } - bzero(outbuf,smb_size); + if (ismyip(dest_ip)) { + DEBUG(1,("Password server loop - disabling password server %s\n",p)); + continue; + } - /* setup the protocol string */ - set_message(outbuf,0,strlen(pass_protocol)+2,True); - p = smb_buf(outbuf); - *p++ = 2; - strcpy(p,pass_protocol); + if (cli_connect(&cli, desthost, &dest_ip)) { + DEBUG(3,("connected to password server %s\n",p)); + break; + } + } - CVAL(outbuf,smb_com) = SMBnegprot; - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); + if (!p) { + DEBUG(1,("password server not available\n")); + cli_shutdown(&cli); + return NULL; + } - send_smb(password_client,outbuf); - ret = receive_smb(password_client,secserver_inbuf,5000); + if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { + DEBUG(1,("%s rejected the session\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - if (!ret || CVAL(secserver_inbuf,smb_rcls) || SVAL(secserver_inbuf,smb_vwv0)) { - DEBUG(1,("%s rejected the protocol\n",pserver)); - close(password_client); password_client= -1; - return(False); - } + DEBUG(3,("got session\n")); - if (!(CVAL(secserver_inbuf,smb_vwv1) & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",pserver)); - close(password_client); password_client= -1; - return(False); - } + if (!cli_negprot(&cli)) { + DEBUG(1,("%s rejected the negprot\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - memcpy(buf,secserver_inbuf,smb_len(secserver_inbuf)+4); + if (cli.protocol < PROTOCOL_LANMAN2 || + !(cli.sec_mode & 1)) { + DEBUG(1,("%s isn't in user level security mode\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - DEBUG(3,("password server OK\n")); + DEBUG(3,("password server OK\n")); - return(True); + return &cli; } /**************************************************************************** -support for server level security +validate a password with the password server ****************************************************************************/ -BOOL server_validate(char *buf) +BOOL server_validate(char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen) { - pstring outbuf; - BOOL ret; + extern fstring local_machine; + fstring share; - if(secserver_inbuf == NULL) { - secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(secserver_inbuf == NULL) { - DEBUG(0,("server_validate: malloc fail for input buffer.\n")); - return False; - } - } + if (!cli.initialised) { + DEBUG(1,("password server %s is not connected\n", cli.desthost)); + return(False); + } - if (password_client < 0) { - DEBUG(1,("%s not connected\n",pserver)); - return(False); - } + if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", cli.desthost)); + return False; + } - bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); - memcpy(outbuf,buf,sizeof(outbuf)); + /* if logged in as guest then reject */ + if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); + return(False); + } - /* send a session setup command */ - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); - CVAL(outbuf,smb_vwv0) = 0xFF; - set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False); + sprintf(share,"\\\\%s\\IPC$", cli.desthost); - SCVAL(secserver_inbuf,smb_rcls,1); + if (!cli_send_tconX(&cli, share, "IPC", "", 1)) { + DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); + return False; + } - send_smb(password_client,outbuf); - ret = receive_smb(password_client,secserver_inbuf,5000); - if (!ret || CVAL(secserver_inbuf,smb_rcls) != 0) { - DEBUG(1,("password server %s rejected the password\n",pserver)); - return(False); - } + if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { + DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); + cli_tdis(&cli); + return False; + } - /* if logged in as guest then reject */ - if ((SVAL(secserver_inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n",pserver)); - return(False); - } + if (cli.privilages == 0) { + DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); + cli_tdis(&cli); + return False; + } + + if (!strequal(cli.eff_name, user)) { + DEBUG(1,("password server %s gave different username %s\n", + cli.desthost, + cli.eff_name)); + cli_tdis(&cli); + return False; + } - DEBUG(3,("password server %s accepted the password\n",pserver)); + DEBUG(3,("password server %s accepted the password\n", cli.desthost)); -#if !KEEP_PASSWORD_SERVER_OPEN - close(password_client); password_client= -1; -#endif + cli_tdis(&cli); - return(True); + return(True); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 424c7d8183..3643b6eed0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -379,8 +379,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL computer_id=False; static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); + char *domain = ""; *smb_apasswd = 0; + *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); smb_mpxmax = SVAL(inbuf,smb_vwv3); @@ -469,8 +471,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) p += passlen1 + passlen2; fstrcpy(user,p); p = skip_string(p,1); + domain = p; + DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - p,skip_string(p,1),skip_string(p,2))); + domain,skip_string(p,1),skip_string(p,2))); } @@ -533,7 +537,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) guest = True; - if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) && + if (!guest && !(lp_security() == SEC_SERVER && + server_validate(user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && !check_hosts_equiv(user)) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7639c5940b..f6a43a536d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2320,22 +2320,21 @@ static int sig_cld() **************************************************************************/ static int sig_pipe() { - extern int password_client; - BlockSignals(True,SIGPIPE); + struct cli_state *cli; + BlockSignals(True,SIGPIPE); - if (password_client != -1) { - DEBUG(3,("lost connection to password server\n")); - close(password_client); - password_client = -1; + if ((cli = server_client()) && cli->initialised) { + DEBUG(3,("lost connection to password server\n")); + cli_shutdown(cli); #ifndef DONT_REINSTALL_SIG - signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGPIPE, SIGNAL_CAST sig_pipe); #endif - BlockSignals(False,SIGPIPE); - return 0; - } + BlockSignals(False,SIGPIPE); + return 0; + } - exit_server("Got sigpipe\n"); - return(0); + exit_server("Got sigpipe\n"); + return(0); } /**************************************************************************** @@ -3564,11 +3563,6 @@ int reply_lanman1(char *outbuf) Protocol = PROTOCOL_LANMAN1; - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); - if (doencrypt) set_challenge(smb_buf(outbuf)); - } - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv2,max_recv); @@ -3594,32 +3588,42 @@ int reply_lanman2(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); + struct cli_state *cli = NULL; + char cryptkey[8]; + char crypt_len = 0; + + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } + + if (cli) { + DEBUG(3,("using password server validation\n")); + doencrypt = ((cli->sec_mode & 2) != 0); + } if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; - set_message(outbuf,13,doencrypt?8:0,True); + if (doencrypt) { + crypt_len = 8; + if (!cli) { + generate_next_challenge(cryptkey); + } else { + memcpy(cryptkey, cli->cryptkey, 8); + set_challenge(cli->cryptkey); + } + } + + set_message(outbuf,13,crypt_len,True); SSVAL(outbuf,smb_vwv1,secword); - /* Create a token value and add it to the outgoing packet. */ if (doencrypt) - generate_next_challenge(smb_buf(outbuf)); + memcpy(smb_buf(outbuf), cryptkey, 8); SIVAL(outbuf,smb_vwv6,getpid()); Protocol = PROTOCOL_LANMAN2; - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); - if (doencrypt) set_challenge(smb_buf(outbuf)); - } - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); SSVAL(outbuf,smb_vwv4,1); @@ -3641,67 +3645,58 @@ int reply_nt1(char *outbuf) /* other valid capabilities which we may support at some time... CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; - CAP_LARGE_FILES|CAP_LARGE_READX| - CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; + CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; */ int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); int data_len; - int encrypt_len; - char challenge_len = 8; - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); + struct cli_state *cli = NULL; + char cryptkey[8]; + char crypt_len = 0; - if (lp_readraw() && lp_writeraw()) - { - capabilities |= CAP_RAW_MODE; + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); } - if (lp_security()>=SEC_USER) secword |= 1; + if (cli) { + DEBUG(3,("using password server validation\n")); + doencrypt = ((cli->sec_mode & 2) != 0); + } + + if (doencrypt) { + crypt_len = 8; + if (!cli) { + generate_next_challenge(cryptkey); + } else { + memcpy(cryptkey, cli->cryptkey, 8); + set_challenge(cli->cryptkey); + } + } + + if (lp_readraw() && lp_writeraw()) { + capabilities |= CAP_RAW_MODE; + } + + if (lp_security() >= SEC_USER) secword |= 1; if (doencrypt) secword |= 2; /* decide where (if) to put the encryption challenge, and follow it with the OEM'd domain name */ - encrypt_len = doencrypt?challenge_len:0; -#if UNICODE - data_len = encrypt_len + 2*(strlen(myworkgroup)+1); -#else - data_len = encrypt_len + strlen(myworkgroup) + 1; -#endif + data_len = crypt_len + strlen(myworkgroup) + 1; set_message(outbuf,17,data_len,True); - -#if UNICODE - /* put the OEM'd domain name */ - PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup); -#else - strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup); -#endif + strcpy(smb_buf(outbuf)+crypt_len, myworkgroup); CVAL(outbuf,smb_vwv1) = secword; - /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) - { - generate_next_challenge(smb_buf(outbuf)); - - /* Tell the nt machine how long the challenge is. */ - SSVALS(outbuf,smb_vwv16+1,challenge_len); - } + SSVALS(outbuf,smb_vwv16+1,crypt_len); + if (doencrypt) + memcpy(smb_buf(outbuf), cryptkey, 8); Protocol = PROTOCOL_NT1; - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); - if (doencrypt) set_challenge(smb_buf(outbuf)); - } - - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ @@ -4766,17 +4761,16 @@ static void process(void) if (keepalive && (counter-last_keepalive)>keepalive) { - extern int password_client; - if (!send_keepalive(Client)) - { - DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); - return; - } - /* also send a keepalive to the password server if its still - connected */ - if (password_client != -1) - send_keepalive(password_client); - last_keepalive = counter; + struct cli_state *cli = server_client(); + if (!send_keepalive(Client)) { + DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); + return; + } + /* also send a keepalive to the password server if its still + connected */ + if (cli && cli->initialised) + send_keepalive(cli->fd); + last_keepalive = counter; } /* check for connection timeouts */ -- cgit From 0aa3935917e325afcb72fdab7a95e99bcfb074cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Oct 1997 11:54:57 +0000 Subject: fix the order of become_uid() and become_gid() in become_root(). This was a harmless bug but left log entries code cleanup in reply_lanman2() (This used to be commit 8e90e1ef276c4cc362e32985c2845fc4c5108273) --- source3/smbd/server.c | 9 +-------- source3/smbd/uid.c | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f6a43a536d..6fe89b8e95 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3546,11 +3546,6 @@ int reply_lanman1(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; @@ -3564,7 +3559,6 @@ int reply_lanman1(char *outbuf) Protocol = PROTOCOL_LANMAN1; CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ SSVAL(outbuf,smb_vwv4,1); @@ -3616,11 +3610,10 @@ int reply_lanman2(char *outbuf) set_message(outbuf,13,crypt_len,True); SSVAL(outbuf,smb_vwv1,secword); + SIVAL(outbuf,smb_vwv6,getpid()); if (doencrypt) memcpy(smb_buf(outbuf), cryptkey, 8); - SIVAL(outbuf,smb_vwv6,getpid()); - Protocol = PROTOCOL_LANMAN2; CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 42ade7e4da..28bf4b421a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -505,8 +505,8 @@ void become_root(BOOL save_dir) current_user_saved = current_user; become_root_depth = 1; - become_gid(0); become_uid(0); + become_gid(0); } /**************************************************************************** -- cgit From 8f13fb0bdcb77d44091fa5bb4ab60fd1ac5650c6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Oct 1997 12:55:49 +0000 Subject: don't check lp_alternate_permissions() in the new utime workaround code. lp_alternate_permissions() is intended only to affect the display of file permissions, not what you can actually do with the files. (This used to be commit 454802d5922bf2b2c6df1f084e183611937ee5fb) --- source3/smbd/server.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6fe89b8e95..28364d9c0c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -334,20 +334,18 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) return -1; /* Check if we have write access. */ - if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) - { - if (((sb.st_mode & S_IWOTH) || - Connections[cnum].admin_user || - ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || - ((sb.st_mode & S_IWGRP) && - in_group(sb.st_gid,current_user.gid, - current_user.ngroups,current_user.igroups)))) - { - /* We are allowed to become root and change the filetime. */ - become_root(False); - ret = sys_utime(fname, times); - unbecome_root(False); - } + if (CAN_WRITE(cnum)) { + if (((sb.st_mode & S_IWOTH) || + Connections[cnum].admin_user || + ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || + ((sb.st_mode & S_IWGRP) && + in_group(sb.st_gid,current_user.gid, + current_user.ngroups,current_user.igroups)))) { + /* We are allowed to become root and change the filetime. */ + become_root(False); + ret = sys_utime(fname, times); + unbecome_root(False); + } } return ret; -- cgit From bb9ca7fd648d8a507ade0f15ac84251eb13a8f02 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Oct 1997 13:03:46 +0000 Subject: check for EPERM or EACCESS in file_utime() (This used to be commit afd7592ffd74fbc77f4b177b007291df95f418ef) --- source3/smbd/server.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 28364d9c0c..5f925df687 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -318,10 +318,15 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) struct stat sb; int ret = -1; + errno = 0; + if(sys_utime(fname, times) == 0) return 0; - if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum))) + if((errno != EPERM) && (errno != EACCESS)) + return -1; + + if(!lp_dos_filetimes(SNUM(cnum))) return -1; /* We have permission (given by the Samba admin) to -- cgit From 0083afc90e928f2fa55be3936d51474bb97daf2e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Oct 1997 13:15:20 +0000 Subject: damn, I spelt EACCES wrong. actually it's wrong in the linux man page for utime ... (This used to be commit 267b56de10a20c25faee69cf4b6b6c02887ebe9c) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5f925df687..42b2a506cc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -323,7 +323,7 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) if(sys_utime(fname, times) == 0) return 0; - if((errno != EPERM) && (errno != EACCESS)) + if((errno != EPERM) && (errno != EACCES)) return -1; if(!lp_dos_filetimes(SNUM(cnum))) -- cgit From efe9b26a7b08cc9ea02cad32a847f71773a6edc4 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 21 Oct 1997 18:25:14 +0000 Subject: loadparm.c : added "domain admin users" parameter added "domain guest users" parameter these two complement the "domain groups" parameter. the "domain groups" parameter should be for your own groups, and well-known aliases. util.c : added ability to do "domain groups = power_users admin_users backup_ops" which are well-known RID aliases, not well-known RID groups. pipenetlog.c : combine the "domain admin users"; "domain guest users" and "domain groups" parameters to give an array of RID groups to include in the SAM Logon response. ipc.c smb.h : moved REALLOC() into smb.h added RID #defines. proto.h: usual. (This used to be commit f2554f231d1f59f30224adcc02b2b3ca4c24e0dd) --- source3/smbd/ipc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 4f6c85de9f..efae39889d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -52,8 +52,6 @@ extern fstring myworkgroup; #define ERROR_INVALID_LEVEL 124 #define ERROR_MORE_DATA 234 -#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024)) - #define ACCESS_READ 0x01 #define ACCESS_WRITE 0x02 #define ACCESS_CREATE 0x04 -- cgit From 79b314447bdcda65cffdd3dd495932c417b545f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 1997 18:27:55 +0000 Subject: chgpasswd.c: includes.h: SCO changes. server.c: Added code in open_sockets to allow 'bind interfaces only' to work as documented. Jeremy (jallison@whistle.com) (This used to be commit 46ac5928d9069af1dc60e9724f38e228dd578937) --- source3/smbd/chgpasswd.c | 6 +- source3/smbd/server.c | 220 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 153 insertions(+), 73 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index bed81138b2..17401410ce 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -124,15 +124,15 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram) slavedev)); return(False); } -#if defined(SVR4) || defined(SUNOS5) +#if defined(SVR4) || defined(SUNOS5) || defined(SCO) ioctl(slave, I_PUSH, "ptem"); ioctl(slave, I_PUSH, "ldterm"); -#else /* defined(SVR4) || defined(SUNOS5) */ +#else /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */ if (ioctl(slave,TIOCSCTTY,0) <0) { DEBUG(3,("Error in ioctl call for slave pty\n")); /* return(False); */ } -#endif /* defined(SVR4) || defined(SUNOS5) */ +#endif /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */ /* Close master. */ close(master); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 42b2a506cc..68f2dca27c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2348,100 +2348,180 @@ static BOOL open_sockets(BOOL is_daemon,int port) extern int Client; if (is_daemon) - { - int s; - struct sockaddr addr; - int in_addrlen = sizeof(addr); - - /* Stop zombies */ + { + int num_interfaces = iface_count(); + int fd_listenset[FD_SETSIZE]; + fd_set listen_set; + int s; + int i; + + /* Stop zombies */ #ifdef SIGCLD_IGNORE - signal(SIGCLD, SIG_IGN); + signal(SIGCLD, SIG_IGN); #else - signal(SIGCLD, SIGNAL_CAST sig_cld); + signal(SIGCLD, SIGNAL_CAST sig_cld); #endif + if(atexit_set == 0) + atexit(killkids); + + FD_ZERO(&listen_set); + + if(lp_interfaces() && lp_bind_interfaces_only()) + { + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + + if(num_interfaces > FD_SETSIZE) + { + DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ +max can be %d\n", num_interfaces, FD_SETSIZE)); + return False; + } + + /* Now open a listen socket for each of the interfaces. */ + for(i = 0; i < num_interfaces; i++) + { + struct in_addr *ifip = iface_n_ip(i); + + if(ifip == NULL) + { + DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); + continue; + } + s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr); + if(s == -1) + return False; + /* ready to listen */ + if (listen(s, 5) == -1) + { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } + FD_SET(s,&listen_set); + } + } + else + { + /* Just bind to 0.0.0.0 - accept connections from anywhere. */ + num_interfaces = 1; + /* open an incoming socket */ s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address())); if (s == -1) - return(False); + return(False); /* ready to listen */ if (listen(s, 5) == -1) - { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; - } - - if(atexit_set == 0) - atexit(killkids); + { + DEBUG(0,("open_sockets: listen: %s\n",strerror(errno))); + close(s); + return False; + } - /* now accept incoming connections - forking a new process - for each incoming connection */ - DEBUG(2,("waiting for a connection\n")); - while (1) - { - Client = accept(s,&addr,&in_addrlen); + fd_listenset[0] = s; + FD_SET(s,&listen_set); + } - if (Client == -1 && errno == EINTR) - continue; + /* now accept incoming connections - forking a new process + for each incoming connection */ + DEBUG(2,("waiting for a connection\n")); + while (1) + { + fd_set lfds; + int num; - if (Client == -1) - { - DEBUG(0,("accept: %s\n",strerror(errno))); - continue; - } + memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); + + num = sys_select(&lfds,NULL); + + if (num == -1 && errno == EINTR) + continue; + + /* Find the sockets that are read-ready - accept on these. */ + for( ; num > 0; num--) + { + struct sockaddr addr; + int in_addrlen = sizeof(addr); + + s = -1; + for(i = 0; i < num_interfaces; i++) + { + if(FD_ISSET(fd_listenset[i],&lfds)) + { + s = fd_listenset[i]; + break; + } + } + + Client = accept(s,&addr,&in_addrlen); + + if (Client == -1 && errno == EINTR) + continue; + + if (Client == -1) + { + DEBUG(0,("open_sockets: accept: %s\n",strerror(errno))); + continue; + } #ifdef NO_FORK_DEBUG +#ifndef NO_SIGNAL_TEST + signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGCLD, SIGNAL_CAST SIG_DFL); +#endif /* NO_SIGNAL_TEST */ + return True; +#else /* NO_FORK_DEBUG */ + if (Client != -1 && fork()==0) + { + /* Child code ... */ + #ifndef NO_SIGNAL_TEST signal(SIGPIPE, SIGNAL_CAST sig_pipe); signal(SIGCLD, SIGNAL_CAST SIG_DFL); -#endif - return True; -#else - if (Client != -1 && fork()==0) - { - /* Child code ... */ -#ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); - signal(SIGCLD, SIGNAL_CAST SIG_DFL); -#endif - /* close the listening socket */ - close(s); - - /* close our standard file descriptors */ - close_low_fds(); - am_parent = 0; +#endif /* NO_SIGNAL_TEST */ + /* close the listening socket(s) */ + for(i = 0; i < num_interfaces; i++) + close(fd_listenset[i]); + + /* close our standard file descriptors */ + close_low_fds(); + am_parent = 0; - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - - /* Reset global variables in util.c so that - client substitutions will be done correctly - in the process. - */ - reset_globals_after_fork(); - return True; - } - close(Client); /* The parent doesn't need this socket */ -#endif - } - } + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + + /* Reset global variables in util.c so that + client substitutions will be done correctly + in the process. + */ + reset_globals_after_fork(); + return True; + } + close(Client); /* The parent doesn't need this socket */ +#endif /NO_FORK_DEBUG */ + } /* end for num */ + } /* end while 1 */ + } /* end if is_daemon */ else - { - /* We will abort gracefully when the client or remote system - goes away */ + { + /* Started from inetd. fd 0 is the socket. */ + /* We will abort gracefully when the client or remote system + goes away */ #ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGPIPE, SIGNAL_CAST sig_pipe); #endif - Client = dup(0); + Client = dup(0); - /* close our standard file descriptors */ - close_low_fds(); + /* close our standard file descriptors */ + close_low_fds(); - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - } + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + } return True; } -- cgit From 325738bd277648135815c99165fc8b72d1b1859c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 1997 22:51:21 +0000 Subject: WHATSNEW.txt: Updated for alpha3. server.c: int16 -> uint16 fix for port comparisons in oplock code. Needed for Solaris. version.h: Updated to alpha3. Jeremy (jallison@whistle.com) (This used to be commit 2d9645e99ba30a5cce4372ff80d1bd26c516ac34) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 68f2dca27c..d67247481f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2631,7 +2631,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); static BOOL process_local_message(int sock, char *buffer, int buf_size) { int32 msg_len; - int16 from_port; + uint16 from_port; char *msg_start; msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET); @@ -2995,7 +2995,7 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", { char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; int32 reply_msg_len; - int16 reply_from_port; + uint16 reply_from_port; char *reply_msg_start; if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), -- cgit From d38aba33afefc5791c1a672f5786bf2d8da8dda8 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 22 Oct 1997 18:37:43 +0000 Subject: client.c : send to \PIPE\ not \PIPE\NETLOGON. ipc.c : fstring name not being bzero'd caused problems when calling named_pipe(). (This used to be commit 2393c49b0509b8ce021f0acfba135219cd753cf9) --- source3/smbd/ipc.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index efae39889d..01502573fc 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2769,6 +2769,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, int fd; int subcommand; + DEBUG(5,("api_fd_reply\n")); /* First find out the name of this file. */ if (suwcnt != 2) { @@ -2976,18 +2977,24 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, int suwcnt,int tdscnt,int tpscnt, int msrcnt,int mdrcnt,int mprcnt) { + DEBUG(3,("named pipe command on <%s> name\n")); - if (strequal(name,"LANMAN")) - return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); + if (strequal(name,"LANMAN")) + { + return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt); + } -if (strlen(name) < 1) - return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt)); + if (strlen(name) < 1) + { + return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); + } + if (setup) + { + DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1])); + } - DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n", - name,(int)setup[0],(int)setup[1])); - - return(0); + return 0; } @@ -3018,6 +3025,7 @@ int reply_trans(char *inbuf,char *outbuf) int dsoff = SVAL(inbuf,smb_vwv12); int suwcnt = CVAL(inbuf,smb_vwv13); + bzero(name, sizeof(name)); fstrcpy(name,smb_buf(inbuf)); if (dscnt > tdscnt || pscnt > tpscnt) { @@ -3096,11 +3104,18 @@ int reply_trans(char *inbuf,char *outbuf) DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt)); - if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) + { + DEBUG(5,("calling named_pipe\n")); outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); + } + else + { + DEBUG(3,("invalid pipe name\n")); + outsize = 0; + } if (data) free(data); -- cgit From 203c93e9221bfa71a00165f251695cafb92f035b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 23 Oct 1997 16:17:07 +0000 Subject: general sorting out, from crashes generated by do_lsa_req_chal() in client.c trying to set up the data parameters etc and not understanding what's going on. in api_netlogTNP, added smb_io_rpc_hdr() call to decode the header received (and in this instance, generated by do_lsa_req_chal()). and then noticed that it's two bytes out. but i don't know how to do "byte parameters" and it's not the same format as the LSA_REQCHAL received from nt workstations. agh! (This used to be commit 0cc8ce43e1d54b44237bb525f4cf6b77e7ca3ced) --- source3/smbd/ipc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 01502573fc..ebfa564f6e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2781,7 +2781,8 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, fd = setup[1]; subcommand = setup[0]; - DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name)); + DEBUG(3,("Got API command %d on pipe %s (fd %x)", + subcommand,Files[fd].name, fd)); DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); -- cgit From abb255cfe674a39c6a42f5083af9c5facdbcca05 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Oct 1997 22:30:57 +0000 Subject: Big change to make nmbd code more readable/understandable. Main change is removal of find_name_search() confusion. This has been replaced with find_name_on_subnet() which makes it explicit what is being searched. Also changed wins_subnet to be wins_client_subnet in preparation for splitting the wins subnet into client and server pieces. This is a big nmbd change and I'd appreciate any bug reports. Specific changes follow : asyncdns.c: Removed wins entry from add_netbios_entry(). This is now explicit in the subnet_record parameter. interface.c: iface_bcast(), iface_nmask(), iface_ip() return the default interface if none can be found. Made this behavior explicit - some code in nmbd incorrectly depended upon this (reply_name_status() for instance). nameannounce.c: find_name_search changes to find_name_on_subnet. namebrowse.c: wins_subnet renamed to wins_client_subnet. namedbname.c: find_name_search removed. find_name_on_subnet added. add_netbios_entry - wins parameter removed. namedbsubnet.c: find_req_subnet removed - not explicit enough. nameelect.c: wins_subnet renamed to wins_client_subnet. namepacket.c: listening() simplified. nameresp.c: wins_subnet renamed to wins_client_subnet. nameserv.c: find_name_search moved to find_name_on_subnet. nameserv.h: FIND_XXX -> changed to FIND_SELF_NAME, FIND_ANY_NAME. nameservreply.c: find_name_search moved to find_name_on_subnet. Debug entries changed. nameservresp.c: wins_subnet renamed to wins_client_subnet. namework.c: wins_subnet renamed to wins_client_subnet. nmbd.c: wins parameter removed from add_netbios_entry. nmbsync: wins_subnet renamed to wins_client_subnet. proto.h: The usual. server.c: remove accepted fd from fd_set. Jeremy (jallison@whistle.com) (This used to be commit 2c97b33fc0b5ef181dbf51a50cb61074935165bf) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d67247481f..20c1a1c1b7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2453,6 +2453,8 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); if(FD_ISSET(fd_listenset[i],&lfds)) { s = fd_listenset[i]; + /* Clear this so we don't look at it again. */ + FD_CLR(fd_listenset[i],&lfds); break; } } -- cgit From a12f04753348e6d52df1f9a2359794deacfc9007 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 24 Oct 1997 13:15:34 +0000 Subject: nterr.c : added a structure that wraps nt errors as strings and enums, so we can do a smb_nt_error() function. Makefile ntclient.c : added ntclient.c, broken out nt domain stuff into a separate file. getting fed up of compile-times and size of client.c. fixed the do_lsa_req_chal() function. made it read the response, and return the challenge credentials received from the server. next stop: do_lsa_auth_2(). client.c : removed nt domain logon functions into a separate file. pipenetlog.c pipentlsa.c pipesrvsvc.c smbparse.c : i'd broken the offsets of the RPC_HDR while trying to sort out the nt client code. fixed it again. added some robustness stuff. util.c : the unistrn2() function was null-terminating the string at one character too many. (This used to be commit 39cec7f698c4461aee05cfbb213879fbd486117d) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ebfa564f6e..61b282fd42 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2978,7 +2978,7 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, int suwcnt,int tdscnt,int tpscnt, int msrcnt,int mdrcnt,int mprcnt) { - DEBUG(3,("named pipe command on <%s> name\n")); + DEBUG(3,("named pipe command on <%s> name\n", name)); if (strequal(name,"LANMAN")) { -- cgit From 390c1f3c4d3136b454fa5eb8681fa9ca34eaacc2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 25 Oct 1997 10:58:18 +0000 Subject: Makefile : adding bits for new nt domain code byteorder.h : trying to get macros right, and not to crash on SUNOS5... client.c : added #ifdef NTDOMAIN, and created do_nt_login() function. don't want to have to recompile client.c unless absolutely necessary. credentials.c : moved deal_with_creds() [possibly inappropriately] into credentials.c ipc.c reply.c server.c uid.c : attempting to make (un)become_root() functions calleable from smbclient. this is a little tricky: smbclient might have to be another setuid root program, immediately setuid'ing to non-root, so that we can reset-uid to root to get at the smbpasswd file. or, have a secure pipe mechanism to smbd to grab smbpasswd entries. or the like. smbdes.c smbencrypt.c : created a function to generate lm and nt owf hashes. lsaparse.c ntclient.c smbparse.c : added nt client LSA_AUTH2 code. it works, too! pipenetlog.c pipentlsa.c pipesrvsvc.c : simplification. code-shuffling. getting that damn offset right for the opcode in RPC_HDR. smb.h : changed dcinfo xxx_creds to DOM_CRED structures instead of DOM_CHAL. we might need to store the server times as well. proto.h : the usual. (This used to be commit 82436a3d99d4bdce249ce9ff27fd2ca4b2447e07) --- source3/smbd/ipc.c | 5 +++-- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 8 ++++---- source3/smbd/uid.c | 44 +++++++++++++++++++++----------------------- 4 files changed, 29 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 61b282fd42..9c9c183a14 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1606,11 +1606,12 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, if (Files[i].open && Files[i].print_file) { pstring wd; + int fcnum = Files[i].cnum; GetWd(wd); unbecome_user(); - if (!become_user(Files[i].cnum,vuid) || - !become_service(Files[i].cnum,True)) + if (!become_user(&Connections[fcnum], fcnum,vuid) || + !become_service(fcnum,True)) break; if (sys_rename(Files[i].name,name) == 0) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3643b6eed0..22c22ccc55 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2614,7 +2614,7 @@ int reply_printqueue(char *inbuf,char *outbuf) DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum)); } - if (!become_user(cnum,vuid)) + if (!become_user(&Connections[cnum], cnum, vuid)) return(ERROR(ERRSRV,ERRinvnid)); { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 20c1a1c1b7..9b428df44c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -94,7 +94,7 @@ BOOL global_oplock_break = False; extern fstring remote_machine; -pstring OriginalDir; +extern pstring OriginalDir; /* these can be set by some functions to override the error codes */ int unix_ERR_class=SUCCESS; @@ -3462,7 +3462,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de smbrun(cmd,NULL,False); } - if (!become_user(cnum,pcon->vuid)) + if (!become_user(&Connections[cnum], cnum,pcon->vuid)) { DEBUG(0,("Can't become connected user!\n")); pcon->open = False; @@ -4019,7 +4019,7 @@ void close_cnum(int cnum, uint16 vuid) dptr_closecnum(cnum); /* execute any "postexec = " line */ - if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid)) + if (*lp_postexec(SNUM(cnum)) && become_user(&Connections[cnum], cnum,vuid)) { pstring cmd; strcpy(cmd,lp_postexec(SNUM(cnum))); @@ -4542,7 +4542,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize unbecome_user(); /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(cnum,session_tag)) { + if ((flags & AS_USER) && !become_user(&Connections[cnum], cnum,session_tag)) { if (flags & AS_GUEST) flags &= ~AS_USER; else diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 28bf4b421a..645d078979 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -23,15 +23,13 @@ extern int DEBUGLEVEL; -extern connection_struct Connections[]; - static int initial_uid; static int initial_gid; /* what user is current? */ struct current_user current_user; -extern pstring OriginalDir; +pstring OriginalDir; /**************************************************************************** initialise the uid routines @@ -183,19 +181,19 @@ BOOL become_guest(void) /******************************************************************* check if a username is OK ********************************************************************/ -static BOOL check_user_ok(int cnum,user_struct *vuser,int snum) +static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { int i; - for (i=0;iuid) return(True); + for (i=0;iuid_cache.entries;i++) + if (conn->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; + i = conn->uid_cache.entries % UID_CACHE_SIZE; + conn->uid_cache.list[i] = vuser->uid; - if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE) - Connections[cnum].uid_cache.entries++; + if (conn->uid_cache.entries < UID_CACHE_SIZE) + conn->uid_cache.entries++; return(True); } @@ -204,7 +202,7 @@ static BOOL check_user_ok(int cnum,user_struct *vuser,int snum) /**************************************************************************** become the user of a connection number ****************************************************************************/ -BOOL become_user(int cnum, uint16 vuid) +BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum,gid; @@ -217,23 +215,23 @@ BOOL become_user(int cnum, uint16 vuid) unbecome_user(); - if (!OPEN_CNUM(cnum)) { + if (!(VALID_CNUM(cnum) && conn->open)) { DEBUG(2,("Connection %d not open\n",cnum)); return(False); } - snum = Connections[cnum].service; + snum = conn->service; - if (Connections[cnum].force_user || + if (conn->force_user || lp_security() == SEC_SHARE || !(vuser) || (vuser->guest) || - !check_user_ok(cnum,vuser,snum)) + !check_user_ok(conn, 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; + uid = conn->uid; + gid = conn->gid; + current_user.groups = conn->groups; + current_user.igroups = conn->igroups; + current_user.ngroups = conn->ngroups; current_user.attrs = vuser->attrs; } else @@ -246,7 +244,7 @@ BOOL become_user(int cnum, uint16 vuid) if(!*lp_force_group(snum)) gid = vuser->gid; else - gid = Connections[cnum].gid; + gid = conn->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; current_user.igroups = vuser->igroups; @@ -258,7 +256,7 @@ BOOL become_user(int cnum, uint16 vuid) if (!become_gid(gid)) return(False); #ifndef NO_SETGROUPS - if (!IS_IPC(cnum)) { + if (!(VALID_CNUM(cnum) && conn->ipc)) { /* groups stuff added by ih/wreu */ if (current_user.ngroups > 0) if (setgroups(current_user.ngroups,current_user.groups)<0) @@ -266,7 +264,7 @@ BOOL become_user(int cnum, uint16 vuid) } #endif - if (!Connections[cnum].admin_user && !become_uid(uid)) + if (!conn->admin_user && !become_uid(uid)) return(False); } -- cgit From 8047228db4d3545da13d87d7b370a38ed0b4c4bb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Oct 1997 12:02:34 +0000 Subject: Fixed 2 oplock bugs: 1) the oplock macros in smb.h used | where they should have used &. This means that smbd thought that all clients were always requesting oplocks. This would have _really_ confused smbclient and smbfs when they started receiving async oplock break requests when they don't even know what an oplock is! 2) an oplock break request from a client can be embedded in a normal lockingX request, and will be if the client has batched any lock requests internally. The smbd code assumed that all oplock break requests had num_locks==num_ulocks==0 which is not true. The only thing special about a oplock break request with num_locks==num_ulocks==0 is that no reply is sent. Otherwise it is processed as a normal locking request in addition to the oplock break processing. These two fixes get the MS mail system in Win98 working on a Samba 1.9.18 network drive. Andrew (This used to be commit ed71534df56d0296280dbde1859597fb42002088) --- source3/smbd/reply.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 22c22ccc55..f437ea564d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3425,9 +3425,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) /* Check if this is an oplock break on a file we have granted an oplock on. */ - if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) && - (num_ulocks == 0) && (num_locks == 0) && - (CVAL(inbuf,smb_vwv0) == 0xFF)) + if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { int token; files_struct *fsp = &Files[fnum]; @@ -3448,19 +3446,21 @@ no oplock granted on this file.\n", fnum)); /* Remove the oplock flag from the sharemode. */ lock_share_entry(fsp->cnum, dev, inode, &token); - if(remove_share_oplock( fnum, token)==False) - { - DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ -dev = %x, inode = %x\n", fnum, dev, inode)); - unlock_share_entry(fsp->cnum, dev, inode, token); - return -1; - } - unlock_share_entry(fsp->cnum, dev, inode, token); + if(remove_share_oplock( fnum, token)==False) { + DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ +dev = %x, inode = %x\n", + fnum, dev, inode)); + unlock_share_entry(fsp->cnum, dev, inode, token); + } else { + unlock_share_entry(fsp->cnum, dev, inode, token); - /* Clear the granted flag and return. */ + /* Clear the granted flag and return. */ + fsp->granted_oplock = False; + } - fsp->granted_oplock = False; - return -1; + /* if this is a pure oplock break request then don't send a reply */ + if (num_locks == 0 && num_ulocks == 0) + return -1; } /* Data now points at the beginning of the list -- cgit From 464dc5433641566abeeabd07f46ab569c986a3b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Oct 1997 13:38:07 +0000 Subject: also disable read prediction in 1.9.18 (This used to be commit 0f15558efb26b7215540a588dfe8733e9346d407) --- source3/smbd/predict.c | 6 +++++- source3/smbd/reply.c | 2 ++ source3/smbd/server.c | 9 ++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 7d6b2498f5..f5f0a2102e 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -23,6 +23,7 @@ extern int DEBUGLEVEL; +#if USE_READ_PREDICTION /* variables used by the read prediction module */ static int rp_fd = -1; @@ -36,7 +37,7 @@ static int rp_timeout = 5; static time_t rp_time = 0; static char *rp_buffer = NULL; static BOOL predict_skip=False; -time_t smb_last_time=(time_t)0; +extern time_t smb_last_time; /**************************************************************************** handle read prediction on a file @@ -156,3 +157,6 @@ void invalidate_read_prediction(int fd) rp_predict_fd = -1; } +#else + void read_prediction_dummy(void) ; +#endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f437ea564d..9e261a1bd5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1722,8 +1722,10 @@ int reply_readbraw(char *inbuf, char *outbuf) int predict=0; _smb_setlen(header,nread); +#if USE_READ_PREDICTION if (!Files[fnum].can_write) predict = read_predict(fd,startpos,header+4,NULL,nread); +#endif if ((nread-predict) > 0) seek_file(fnum,startpos + predict); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9b428df44c..88f7497ee5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -48,7 +48,7 @@ extern BOOL case_preserve; extern BOOL use_mangled_map; extern BOOL short_case_preserve; extern BOOL case_mangle; -extern time_t smb_last_time; +time_t smb_last_time=(time_t)0; extern int smb_read_error; @@ -1434,7 +1434,10 @@ void close_file(int fnum, BOOL normal_close) uint32 inode = fs_p->fd_ptr->inode; int token; +#if USE_READ_PREDICTION invalidate_read_prediction(fs_p->fd_ptr->fd); +#endif + fs_p->open = False; Connections[cnum].num_files_open--; if(fs_p->wbmpx_ptr) @@ -1972,6 +1975,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) { int ret=0,readret; +#if USE_READ_PREDICTION if (!Files[fnum].can_write) { ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n); @@ -1980,6 +1984,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) n -= ret; pos += ret; } +#endif #if USE_MMAP if (Files[fnum].mmap_ptr) @@ -4782,8 +4787,10 @@ static void process(void) if (deadtime <= 0) deadtime = DEFAULT_SMBD_TIMEOUT; +#if USE_READ_PREDICTION if (lp_readprediction()) do_read_prediction(); +#endif errno = 0; -- cgit From 71d648cdb431ecf984196a7e480208a94fcdf390 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Oct 1997 14:27:17 +0000 Subject: change the default file permissions on the SHARE_MEM_FILE* to 0644. smbstatus now gets only read permission on the share files and does no locking. also get rid of some unnecessary umask(0) calls. smbd always runs with umask(0) (This used to be commit c6ac10170dbba57dfebc54c50d79cb29d13bb442) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 88f7497ee5..93042e119b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5145,7 +5145,7 @@ static void usage(char *pname) if (!open_sockets(is_daemon,port)) exit(1); - if (!locking_init()) + if (!locking_init(0)) exit(1); /* possibly reload the services file. */ -- cgit From f868196c1db2e4559960a1ded81afad7dd873beb Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 27 Oct 1997 16:14:29 +0000 Subject: checks against file handle in api_fd_reply(). i don't know what error message should be returned, so i just let it fall through to sending an "api_unsupported" (This used to be commit 85d132da6756da0904fe894ea617b84e38e610ff) --- source3/smbd/ipc.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9c9c183a14..0354b4ecbe 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2765,10 +2765,13 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, char *rparam = NULL; int rdata_len = 0; int rparam_len = 0; - BOOL reply=False; + + BOOL reply = False; + int i; int fd; int subcommand; + pstring pipe_name; DEBUG(5,("api_fd_reply\n")); /* First find out the name of this file. */ @@ -2781,19 +2784,28 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, /* Get the file handle and hence the file name. */ fd = setup[1]; subcommand = setup[0]; - + if (fd >= 0 && fd < MAX_OPEN_FILES) + { + pstrcpy(pipe_name, Files[fd].name); + } + else + { + pipe_name[0] = 0; + DEBUG(1,("api_fd_reply: INVALID FILE HANDLE: %x\n", fd)); + } + DEBUG(3,("Got API command %d on pipe %s (fd %x)", - subcommand,Files[fd].name, fd)); + subcommand, pipe_name, fd)); DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); - for (i=0;api_fd_commands[i].name;i++) + for (i = 0; api_fd_commands[i].name; i++) { - if (strequal(api_fd_commands[i].pipename, Files[fd].name) && + if (strequal(api_fd_commands[i].pipename, pipe_name) && api_fd_commands[i].subcommand == subcommand && api_fd_commands[i].fn) { - DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); + DEBUG(3,("Doing %s\n", api_fd_commands[i].name)); break; } } -- cgit From 7c20ee083f6820a4c8776cefae3e0477f79ea934 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Oct 1997 06:07:07 +0000 Subject: refuse pathworks type R connect (patch from Stephen Tweedie) (This used to be commit c63fee2b282c8b53f87e63995384602b66a805a6) --- source3/smbd/reply.c | 63 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9e261a1bd5..9484f3b85f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -74,42 +74,57 @@ int reply_special(char *inbuf,char *outbuf) extern fstring remote_machine; extern fstring local_machine; char *p; + int len; + char name_type = 0; *name1 = *name2 = 0; smb_setlen(outbuf,0); switch (msg_type) { - case 0x81: /* session request */ - CVAL(outbuf,0) = 0x82; - CVAL(outbuf,3) = 0; - if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { - DEBUG(0,("Invalid name length in session request\n")); - return(0); - } - name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); + case 0x81: /* session request */ + CVAL(outbuf,0) = 0x82; + CVAL(outbuf,3) = 0; + if (name_len(inbuf+4) > 50 || + name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { + DEBUG(0,("Invalid name length in session request\n")); + return(0); + } + name_extract(inbuf,4,name1); + name_extract(inbuf,4 + name_len(inbuf + 4),name2); DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - fstrcpy(remote_machine,name2); - trim_string(remote_machine," "," "); - p = strchr(remote_machine,' '); - strlower(remote_machine); - if (p) *p = 0; - - fstrcpy(local_machine,name1); - trim_string(local_machine," "," "); - p = strchr(local_machine,' '); - strlower(local_machine); - if (p) *p = 0; + fstrcpy(remote_machine,name2); + trim_string(remote_machine," "," "); + p = strchr(remote_machine,' '); + strlower(remote_machine); + if (p) *p = 0; + + fstrcpy(local_machine,name1); + trim_string(local_machine," "," "); + len = strlen(local_machine); + if (len == 16) { + name_type = local_machine[15]; + local_machine[15] = 0; + } + p = strchr(local_machine,' '); + strlower(local_machine); + if (p) *p = 0; + + if (name_type == 'R') { + /* We are being asked for a pathworks session --- + no thanks! */ + CVAL(outbuf, 0) = 0x83; + break; + } - add_session_user(remote_machine); + add_session_user(remote_machine); - reload_services(True); - reopen_logs(); + reload_services(True); + reopen_logs(); - break; + break; case 0x89: /* session keepalive request (some old clients produce this?) */ -- cgit From 8f0316bdbcba996d40ac152a9ac076a18b5dd7ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Oct 1997 19:32:59 +0000 Subject: Adding Windows 95 printer driver code donated by Jean-Francois.Micouleau@utc.fr. New program, make_printerdef, plus two new parameters : [global] "printer driver file" [local] "printer driver location" Jeremy. (This used to be commit 9a5b42e6b3e7a35d56f81e9428fc747246e2fc5c) --- source3/smbd/ipc.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0354b4ecbe..65f85719ae 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -462,6 +462,10 @@ static int check_printq_info(struct pack_desc* desc, case 5: desc->format = "z"; break; + case 52: + desc->format = "WzzzzzzzzN"; + desc->subformat = "z"; + break; default: return False; } if (strcmp(desc->format,id1) != 0) return False; @@ -521,11 +525,18 @@ static void fill_printq_info(int cnum, int snum, int uLevel, int count, print_queue_struct* queue, print_status_struct* status) { - if (uLevel < 3) { - PACKS(desc,"B13",SERVICE(snum)); - } else { - PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum))); + switch (uLevel) { + case 1: + case 2: + PACKS(desc,"B13",SERVICE(snum)); + break; + case 3: + case 4: + case 5: + PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum))); + break; } + if (uLevel == 1 || uLevel == 2) { PACKS(desc,"B",""); /* alignment */ PACKI(desc,"W",5); /* priority */ @@ -573,10 +584,119 @@ static void fill_printq_info(int cnum, int snum, int uLevel, for (i=0;i gave %d entries\n",SERVICE(snum),count)); } +/* This function returns the number of file for a given driver */ +int get_printerdrivernumber(int snum) +{ + int i=0,ok=0; + pstring tok; + char *p,*q; + FILE *f; + pstring fname; + + strcpy(fname,lp_driverfile()); + + DEBUG(4,("In get_printerdrivernumber: %s\n",fname)); + f=fopen(fname,"r"); + if (!f) { + DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno))); + return(0); + } + + p=(char *)malloc(8192*sizeof(char)); + q=p; /* need it to free memory because p change ! */ + + /* lookup the long printer driver name in the file description */ + while (!feof(f) && !ok) + { + fgets(p,8191,f); + next_token(&p,tok,":"); + if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1; + } + + if (ok) { + /* skip 2 fields */ + next_token(&p,tok,":"); /* short name */ + next_token(&p,tok,":"); /* driver name */ + /* count the number of files */ + while (next_token(&p,tok,",")) + i++; + } + fclose(f); + free(q); + + return(i); +} + static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -622,7 +742,14 @@ static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data, if (snum < 0 || !VALID_SNUM(snum)) return(False); - count = get_printqueue(snum,cnum,&queue,&status); + if (uLevel==52) + { + count = get_printerdrivernumber(snum); + DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); + } + else + count = get_printqueue(snum,cnum,&queue,&status); + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; -- cgit From fe0a702322bdf3c76a517e2fd7e92a05219c49dd Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 29 Oct 1997 00:04:14 +0000 Subject: byteorder.h : added mode for printing debug array data as chars not uint8/16/32s. only really useful for (uint8) strings or (uint16) unicode strings lsaparse.c smbparse.c smb.h : rpc bind and rpc bind ack structures and parsing and creation functions. ipc.c pipes.c pipenetlog.c pipentlsa.c pipesrvsvc.c : using rpc bind / bind ack parsing routines instead of incorrect use of api_LsarpcTNP1 function. ntclient.c : creation of do_rpc_bind() function. THAT'S IT, FOLKS! (This used to be commit 21c89e2f17c51939fd6b53dddbe3072419eb0db2) --- source3/smbd/ipc.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- source3/smbd/pipes.c | 2 +- 2 files changed, 44 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 65f85719ae..b7939f2461 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2893,7 +2893,8 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, int rdata_len = 0; int rparam_len = 0; - BOOL reply = False; + BOOL reply = False; + BOOL bind_req = False; int i; int fd; @@ -2940,12 +2941,49 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024); rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - DEBUG(10,("calling api_fd_command\n")); +#ifdef NTDOMAIN + if (api_fd_commands[i].subcommand != -1) + { + RPC_HDR hdr; + char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0); + + if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND)))) + { + RPC_HDR_RB hdr_rb; + + char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0); + + if ((bind_req = (p != NULL))) + { + RPC_HDR_BA hdr_ba; + make_rpc_hdr_ba(&hdr_ba, + hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid, + api_fd_commands[i].pipename, + 0x1, 0x0, 0x0, + &(hdr_rb.transfer)); + + p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0); + + rdata_len = PTR_DIFF(p, rdata); + + make_rpc_hdr(&hdr, RPC_BINDACK, hdr.call_id, rdata_len); - reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, + p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0); + + reply = (p != NULL); + } + } + } +#endif + + if (!bind_req) + { + DEBUG(10,("calling api_fd_command\n")); + + reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); - - DEBUG(10,("called api_fd_command\n")); + DEBUG(10,("called api_fd_command\n")); + } if (rdata_len > mdrcnt || rparam_len > mprcnt) { diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 12e54d2bca..901d7e682a 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -216,7 +216,7 @@ BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, TransactNamedPipe on \PIPE\lsarpc. ****************************************************************************/ -void LsarpcTNP1(char *data,char **rdata, int *rdata_len) +static void LsarpcTNP1(char *data,char **rdata, int *rdata_len) { uint32 dword1, dword2; char pname[] = "\\PIPE\\lsass"; -- cgit From b925b3d20c8e85c7b65a0ad599248443ae12905c Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 29 Oct 1997 01:05:46 +0000 Subject: added frag field to make_rpc_hdr() function (This used to be commit 6b0e51929495582bc48a4d5fba24aa7c1f7caaf6) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b7939f2461..aa1d2d5c4f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2966,7 +2966,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, rdata_len = PTR_DIFF(p, rdata); - make_rpc_hdr(&hdr, RPC_BINDACK, hdr.call_id, rdata_len); + make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len); p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0); -- cgit From 0db5b8fdc97d24bdfadefb9b043df614644c578a Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 29 Oct 1997 14:34:17 +0000 Subject: ipc.c : bind ack should contain \PIPE\pipename not just pipename. ntclientpipe.c : sanity in bind ack: pipe name checks; transfer syntax checks; reason checks. (This used to be commit c2e2197e9d87795bda0198247c7bb132fe586fc1) --- source3/smbd/ipc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index aa1d2d5c4f..c2cfc15a21 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2945,20 +2945,31 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, if (api_fd_commands[i].subcommand != -1) { RPC_HDR hdr; + + /* process the rpc header */ char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0); + /* bind request received */ if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND)))) { RPC_HDR_RB hdr_rb; + /* decode the bind request */ char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0); if ((bind_req = (p != NULL))) { RPC_HDR_BA hdr_ba; + fstring ack_pipe_name; + + /* name has to be \PIPE\xxxxx */ + strcpy(ack_pipe_name, "\\PIPE\\"); + strcat(ack_pipe_name, api_fd_commands[i].pipename); + + /* make a bind acknowledgement */ make_rpc_hdr_ba(&hdr_ba, hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid, - api_fd_commands[i].pipename, + ack_pipe_name, 0x1, 0x0, 0x0, &(hdr_rb.transfer)); -- cgit From 520878fd1f440a7313cedb4827bdc81454d94d20 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 29 Oct 1997 19:05:34 +0000 Subject: ipc.c ntclientpipe.c: response to Bind Acknowledgment needs a lookup table for the PIPE string (secondary address in RPC_HDR_BA structure). smbparse.c util.c : interesting problem, i think caused by us typecasting a uint16* buffer to char*. found on a SPARC. (This used to be commit 420408ee83902faa6cf871f26e93ad5efb483727) --- source3/smbd/ipc.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c2cfc15a21..088ecfbddd 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2862,23 +2862,27 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data, struct { char * name; - char * pipename; + char * pipe_clnt_name; +#ifdef NTDOMAIN + char * pipe_srv_name; +#endif int subcommand; BOOL (*fn) (); } api_fd_commands [] = { #ifdef NTDOMAIN - { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, - { "SetNmdPpHndState", "srvsvc", 1, api_LsarpcSNPHS }, - { "SetNmdPpHndState", "NETLOGON", 1, api_LsarpcSNPHS }, - { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, - { "TransactNmPipe", "srvsvc", 0x26, api_srvsvcTNP }, - { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP }, + { "SetNmdPpHndState", "lsarpc", "lsass", 1, api_LsarpcSNPHS }, + { "SetNmdPpHndState", "srvsvc", "lsass", 1, api_LsarpcSNPHS }, + { "SetNmdPpHndState", "NETLOGON", "NETLOGON", 1, api_LsarpcSNPHS }, + { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP }, + { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP }, + { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP }, + { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported } #else { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP }, -#endif { NULL, NULL, -1, (BOOL (*)())api_Unsupported } +#endif }; /**************************************************************************** @@ -2929,7 +2933,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, for (i = 0; api_fd_commands[i].name; i++) { - if (strequal(api_fd_commands[i].pipename, pipe_name) && + if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) && api_fd_commands[i].subcommand == subcommand && api_fd_commands[i].fn) { @@ -2964,7 +2968,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, /* name has to be \PIPE\xxxxx */ strcpy(ack_pipe_name, "\\PIPE\\"); - strcat(ack_pipe_name, api_fd_commands[i].pipename); + strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name); /* make a bind acknowledgement */ make_rpc_hdr_ba(&hdr_ba, -- cgit From 1337b6170376ea690994e18ebb67137d6ab001e8 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 29 Oct 1997 20:08:09 +0000 Subject: zero data parameter being passed to smb_io_rpc_hdr(), which couldn't cope. (This used to be commit c0137cd8fe1362beef9ce879cc558869bdf2edfa) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 088ecfbddd..0d57b1ecfe 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2946,7 +2946,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); #ifdef NTDOMAIN - if (api_fd_commands[i].subcommand != -1) + if (data != NULL && api_fd_commands[i].subcommand != -1) { RPC_HDR hdr; -- cgit From a275e5d4e16142a9924f8b97980f364a80df3b64 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 30 Oct 1997 01:05:13 +0000 Subject: removed mechanism that created actual files NETLOGON, lsarpc and the like, which are pipes on the IPC$ connection. created mechanism to record pipe names in a separate pipes_struct. it is planned to expand this, to return sensible things like interface structures, and policy handles (RPC_IFACE and LSA_POL_HND). and the like. (This used to be commit 33cce5fac0e2f818a19a6c4e6a797ef44f3b5c75) --- source3/smbd/ipc.c | 15 ++--- source3/smbd/pipes.c | 171 ++++++++++++++++++++++++++++++--------------------- source3/smbd/reply.c | 5 ++ 3 files changed, 111 insertions(+), 80 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0d57b1ecfe..b525f06046 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2903,7 +2903,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, int i; int fd; int subcommand; - pstring pipe_name; + char *pipe_name; DEBUG(5,("api_fd_reply\n")); /* First find out the name of this file. */ @@ -2916,14 +2916,11 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, /* Get the file handle and hence the file name. */ fd = setup[1]; subcommand = setup[0]; - if (fd >= 0 && fd < MAX_OPEN_FILES) - { - pstrcpy(pipe_name, Files[fd].name); - } - else + pipe_name = get_pipe_name(fd); + + if (pipe_name == NULL) { - pipe_name[0] = 0; - DEBUG(1,("api_fd_reply: INVALID FILE HANDLE: %x\n", fd)); + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd)); } DEBUG(3,("Got API command %d on pipe %s (fd %x)", @@ -2946,7 +2943,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); #ifdef NTDOMAIN - if (data != NULL && api_fd_commands[i].subcommand != -1) + if (data != NULL && api_fd_commands[i].subcommand == 0x26) { RPC_HDR hdr; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 901d7e682a..990b25cb0a 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -37,18 +37,34 @@ /* look in server.c for some explanation of these variables */ extern int Protocol; extern int DEBUGLEVEL; -extern int chain_fnum; extern char magic_char; -extern connection_struct Connections[]; -extern files_struct Files[]; +static int chain_pnum = -1; extern BOOL case_sensitive; extern pstring sesssetup_user; extern int Client; extern fstring myworkgroup; -/* this macro should always be used to extract an fnum (smb_fid) from -a packet to ensure chaining works correctly */ -#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) +#ifndef MAX_OPEN_PIPES +#define MAX_OPEN_PIPES 50 +#endif + +static struct +{ + int cnum; + BOOL open; + fstring name; + +} Pipes[MAX_OPEN_PIPES]; + +#define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES)) +#define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && Pipes[pnum].open) +#define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum) + +#define CHECK_PNUM(pnum,c) if (!PNUM_OK(pnum,c)) \ + return(ERROR(ERRDOS,ERRbadfid)) +/* this macro should always be used to extract an pnum (smb_fid) from + a packet to ensure chaining works correctly */ +#define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where)) char * known_pipes [] = { @@ -61,13 +77,50 @@ char * known_pipes [] = }; /**************************************************************************** - reply to an open and X on a named pipe + find first available file slot +****************************************************************************/ +static int find_free_pipe(void ) +{ + int i; + /* we start at 1 here for an obscure reason I can't now remember, + but I think is important :-) */ + for (i = 1; i < MAX_OPEN_PIPES; i++) + if (!Pipes[i].open) + return(i); - In fact what we do is to open a regular file with the same name in - /tmp. This can then be closed as normal. Reading and writing won't - make much sense, but will do *something*. The real reason for this - support is to be able to do transactions on them (well, on lsarpc - for domain login purposes...). + DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n")); + + return(-1); +} + +/**************************************************************************** + gets the name of a pipe +****************************************************************************/ +char *get_pipe_name(int pnum) +{ + DEBUG(6,("get_pipe_name: ")); + + if (VALID_PNUM(pnum - 0x800)) + { + DEBUG(6,("name: %s cnum: %d open: %s ", + Pipes[pnum - 0x800].name, + Pipes[pnum - 0x800].cnum, + BOOLSTR(Pipes[pnum - 0x800].open))); + } + if (OPEN_PNUM(pnum - 0x800)) + { + DEBUG(6,("OK\n")); + return Pipes[pnum - 0x800].name; + } + else + { + DEBUG(6,("NOT\n")); + return NULL; + } +} + +/**************************************************************************** + reply to an open and X on a named pipe This code is basically stolen from reply_open_and_X with some wrinkles to handle pipes. @@ -76,21 +129,10 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; int cnum = SVAL(inbuf,smb_tid); - int fnum = -1; - int smb_mode = SVAL(inbuf,smb_vwv3); - int smb_attr = SVAL(inbuf,smb_vwv5); -#if 0 - int open_flags = SVAL(inbuf,smb_vwv2); - int smb_sattr = SVAL(inbuf,smb_vwv4); - uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); -#endif + int pnum = -1; int smb_ofun = SVAL(inbuf,smb_vwv8); - int unixmode; int size=0,fmode=0,mtime=0,rmode=0; - struct stat sbuf; - int smb_action = 0; int i; - BOOL bad_path = False; /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); @@ -117,79 +159,66 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); - smb_attr &= ~aDIR; - Connections[cnum].read_only = 0; smb_ofun |= 0x10; /* Add Create it not exists flag */ - unix_convert(fname,cnum,0,&bad_path); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - unixmode = unix_mode(cnum,smb_attr); - - open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - 0, &rmode,&smb_action); - - if (!Files[fnum].open) - { - /* Change the error code if bad_path was set. */ - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); - return(ERROR(ERRDOS,ERRnoaccess)); - } + pnum = find_free_pipe(); + if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); - size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - mtime = sbuf.st_mtime; - if (fmode & aDIR) { - close_file(fnum,False); - return(ERROR(ERRDOS,ERRnoaccess)); - } + Pipes[pnum].open = True; + Pipes[pnum].cnum = cnum; + fstrcpy(Pipes[pnum].name, fname); /* Prepare the reply */ set_message(outbuf,15,0,True); - /* Put things back the way they were. */ - Connections[cnum].read_only = 1; - /* Mark the opened file as an existing named pipe in message mode. */ SSVAL(outbuf,smb_vwv9,2); SSVAL(outbuf,smb_vwv10,0xc700); + if (rmode == 2) { DEBUG(4,("Resetting open result to open from create.\n")); rmode = 1; } - SSVAL(outbuf,smb_vwv2,fnum); + SSVAL(outbuf,smb_vwv2, pnum + 0x800); /* mark file handle up into high range */ SSVAL(outbuf,smb_vwv3,fmode); put_dos_date3(outbuf,smb_vwv4,mtime); SIVAL(outbuf,smb_vwv6,size); SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,smb_action); - - chain_fnum = fnum; + SSVAL(outbuf,smb_vwv11,0); - DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n", - fname, fnum, Files[fnum].name)); + DEBUG(4,("Opened pipe %s with handle %x name %s.\n", + fname, pnum + 0x800, Pipes[pnum].name)); + chain_pnum = pnum; + return chain_reply(inbuf,outbuf,length,bufsize); } +/**************************************************************************** + reply to a close +****************************************************************************/ +int reply_pipe_close(char *inbuf,char *outbuf) +{ + int pnum = GETPNUM(inbuf,smb_vwv0); + int cnum = SVAL(inbuf,smb_tid); + int outsize = set_message(outbuf,0,0,True); + + /* mapping is 0x800 up... */ + + CHECK_PNUM(pnum-0x800,cnum); + + DEBUG(3,("%s Closed pipe name %s pnum=%d cnum=%d\n", + timestring(),Pipes[pnum-0x800].name, pnum,cnum)); + + Pipes[pnum-0x800].open = False; + + return(outsize); +} + + /**************************************************************************** api_LsarpcSNPHS diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9484f3b85f..46425861d4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2283,7 +2283,12 @@ int reply_close(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); + /* If it's an IPC, pass off to the pipe handler. */ + if (IS_IPC(cnum)) + return reply_pipe_close(inbuf,outbuf); + fnum = GETFNUM(inbuf,smb_vwv0); + CHECK_FNUM(fnum,cnum); if(HAS_CACHED_ERROR(fnum)) { -- cgit From 739a730637b8320dce85c12686a4d4647990824d Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 30 Oct 1997 17:08:42 +0000 Subject: Makefile: simply adding pipes.o to SMBDOBJ3. rpc_pipes/pipe_hnd.c : created pipe handles module. pipes.c server.c : use of pipe_hnd functions in SMBopenX and SMBclose, on the IPC$ pipe. (This used to be commit ada256b5e3b9fb0db988e3be7d47943e7c19b3fb) --- source3/smbd/ipc.c | 2 +- source3/smbd/pipes.c | 80 ++------------------------------------------------- source3/smbd/server.c | 3 ++ 3 files changed, 7 insertions(+), 78 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b525f06046..a42baea80a 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2916,7 +2916,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, /* Get the file handle and hence the file name. */ fd = setup[1]; subcommand = setup[0]; - pipe_name = get_pipe_name(fd); + pipe_name = get_rpc_pipe_hnd_name(fd); if (pipe_name == NULL) { diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 990b25cb0a..ff93041fbc 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -38,30 +38,15 @@ extern int Protocol; extern int DEBUGLEVEL; extern char magic_char; -static int chain_pnum = -1; extern BOOL case_sensitive; extern pstring sesssetup_user; extern int Client; extern fstring myworkgroup; -#ifndef MAX_OPEN_PIPES -#define MAX_OPEN_PIPES 50 -#endif - -static struct -{ - int cnum; - BOOL open; - fstring name; - -} Pipes[MAX_OPEN_PIPES]; - #define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES)) #define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && Pipes[pnum].open) #define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum) -#define CHECK_PNUM(pnum,c) if (!PNUM_OK(pnum,c)) \ - return(ERROR(ERRDOS,ERRbadfid)) /* this macro should always be used to extract an pnum (smb_fid) from a packet to ensure chaining works correctly */ #define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where)) @@ -76,49 +61,6 @@ char * known_pipes [] = NULL }; -/**************************************************************************** - find first available file slot -****************************************************************************/ -static int find_free_pipe(void ) -{ - int i; - /* we start at 1 here for an obscure reason I can't now remember, - but I think is important :-) */ - for (i = 1; i < MAX_OPEN_PIPES; i++) - if (!Pipes[i].open) - return(i); - - DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n")); - - return(-1); -} - -/**************************************************************************** - gets the name of a pipe -****************************************************************************/ -char *get_pipe_name(int pnum) -{ - DEBUG(6,("get_pipe_name: ")); - - if (VALID_PNUM(pnum - 0x800)) - { - DEBUG(6,("name: %s cnum: %d open: %s ", - Pipes[pnum - 0x800].name, - Pipes[pnum - 0x800].cnum, - BOOLSTR(Pipes[pnum - 0x800].open))); - } - if (OPEN_PNUM(pnum - 0x800)) - { - DEBUG(6,("OK\n")); - return Pipes[pnum - 0x800].name; - } - else - { - DEBUG(6,("NOT\n")); - return NULL; - } -} - /**************************************************************************** reply to an open and X on a named pipe @@ -161,13 +103,9 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(3,("Known pipe %s opening.\n",fname)); smb_ofun |= 0x10; /* Add Create it not exists flag */ - pnum = find_free_pipe(); + pnum = open_rpc_pipe_hnd(fname, cnum); if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); - Pipes[pnum].open = True; - Pipes[pnum].cnum = cnum; - fstrcpy(Pipes[pnum].name, fname); - /* Prepare the reply */ set_message(outbuf,15,0,True); @@ -188,11 +126,6 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,0); - DEBUG(4,("Opened pipe %s with handle %x name %s.\n", - fname, pnum + 0x800, Pipes[pnum].name)); - - chain_pnum = pnum; - return chain_reply(inbuf,outbuf,length,bufsize); } @@ -202,18 +135,11 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) ****************************************************************************/ int reply_pipe_close(char *inbuf,char *outbuf) { - int pnum = GETPNUM(inbuf,smb_vwv0); + int pnum = get_rpc_pipe_num(inbuf,smb_vwv0); int cnum = SVAL(inbuf,smb_tid); int outsize = set_message(outbuf,0,0,True); - /* mapping is 0x800 up... */ - - CHECK_PNUM(pnum-0x800,cnum); - - DEBUG(3,("%s Closed pipe name %s pnum=%d cnum=%d\n", - timestring(),Pipes[pnum-0x800].name, pnum,cnum)); - - Pipes[pnum-0x800].open = False; + if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid)); return(outsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 93042e119b..3867240241 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4925,6 +4925,9 @@ static void init_structs(void ) fd_ptr->real_open_flags = -1; } + /* for RPC pipes */ + init_rpc_pipe_hnd(); + init_dptrs(); } -- cgit From 55e2dc7c6f4378adfdcbd166b2680096a3e4a5a4 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 30 Oct 1997 21:51:15 +0000 Subject: storing pipe name state (from set named pipe handle state call) in the pipes array. (This used to be commit 5335d5cdc4659f4676958f0399e2de29a117c133) --- source3/smbd/ipc.c | 24 ++++++++++++++---------- source3/smbd/pipes.c | 15 ++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a42baea80a..1943129ba6 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2871,15 +2871,11 @@ struct } api_fd_commands [] = { #ifdef NTDOMAIN - { "SetNmdPpHndState", "lsarpc", "lsass", 1, api_LsarpcSNPHS }, - { "SetNmdPpHndState", "srvsvc", "lsass", 1, api_LsarpcSNPHS }, - { "SetNmdPpHndState", "NETLOGON", "NETLOGON", 1, api_LsarpcSNPHS }, { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP }, { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP }, { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP }, { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported } #else - { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP }, { NULL, NULL, -1, (BOOL (*)())api_Unsupported } #endif @@ -2899,6 +2895,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, BOOL reply = False; BOOL bind_req = False; + BOOL set_nphs = False; int i; int fd; @@ -2943,6 +2940,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); #ifdef NTDOMAIN + /* RPC Pipe command 0x26. */ if (data != NULL && api_fd_commands[i].subcommand == 0x26) { RPC_HDR hdr; @@ -2988,7 +2986,14 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, } #endif - if (!bind_req) + /* Set Named Pipe Handle state */ + if (subcommand == 0x1) + { + set_nphs = True; + reply = api_LsarpcSNPHS(fd, cnum, params); + } + + if (!bind_req && !set_nphs) { DEBUG(10,("calling api_fd_command\n")); @@ -3003,19 +3008,18 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, &rdata,&rparam,&rdata_len,&rparam_len); } - /* if we get False back then it's actually unsupported */ if (!reply) + { api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); + } /* now send the reply */ send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); - if (rdata) - free(rdata); - if (rparam) - free(rparam); + if (rdata ) free(rdata ); + if (rparam) free(rparam); return(-1); } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index ff93041fbc..4a2e185cb4 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -148,21 +148,18 @@ int reply_pipe_close(char *inbuf,char *outbuf) /**************************************************************************** api_LsarpcSNPHS - SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here, - so just blithely return True. This is really only for NT domain stuff, - we we're only handling that - don't assume Samba now does complete - named pipe handling. + SetNamedPipeHandleState on \PIPE\lsarpc. ****************************************************************************/ -BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param) { uint16 id; + if (!param) return False; + id = param[0] + (param[1] << 8); DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id)); - return(True); + + return set_rpc_pipe_hnd_state(pnum, cnum, id); } -- cgit From 03deca0070b3c7004963938b973519e9c56f2f5c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Nov 1997 07:22:18 +0000 Subject: re-initialise the timezone on each new connection. This means you don't need to restart smbd after a DST change. (This used to be commit 2a50d5d5ed4ca7d2b546d7337ec88c527ec82689) --- source3/smbd/server.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3867240241..095bc00e08 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4776,6 +4776,9 @@ static void process(void) } #endif + /* re-initialise the timezone */ + TimeInit(); + while (True) { int deadtime = lp_deadtime()*60; -- cgit From 224c40a52335bf1afc7662183900e143307aa5be Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Nov 1997 13:22:16 +0000 Subject: a simple SMB torture tester. This will allow us to evaluate locking techniques more accurately. (This used to be commit 054e3b2ae3a8cfb98fde72becef9b05de34d2ba7) --- source3/smbd/password.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 24ee52ed69..b759f68430 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1560,7 +1560,6 @@ BOOL server_validate(char *user, char *domain, char *ntpass, int ntpasslen) { extern fstring local_machine; - fstring share; if (!cli.initialised) { DEBUG(1,("password server %s is not connected\n", cli.desthost)); @@ -1579,9 +1578,7 @@ BOOL server_validate(char *user, char *domain, } - sprintf(share,"\\\\%s\\IPC$", cli.desthost); - - if (!cli_send_tconX(&cli, share, "IPC", "", 1)) { + if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); return False; } -- cgit From b26623bc3a8ff5191763c83564453e77edee836a Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 2 Nov 1997 20:35:20 +0000 Subject: Christian Lademann's contribution: new capabilities in smb.conf. '<' and '|' characters indicate read file and execute command respectively, and feed the output into the parameter (!!!). '<$' and '|$' means run standard_sub_basic() on them. this is going to be fun to document in smb.conf.5.... also, Christian created a new "online" service parameter. services can be taken "off-line".... (This used to be commit 15f44d28916cdc1432bffdbb999c7cf7efd8fb86) --- source3/smbd/reply.c | 4 +++- source3/smbd/server.c | 23 ++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 46425861d4..116542ba34 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1023,7 +1023,9 @@ int reply_search(char *inbuf,char *outbuf) if ((dirtype&0x1F) == aVOLID) { memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0); + mode = aVOLID; + if(!CAN_WRITE(cnum)) mode |= aRONLY; + make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,mode,0); dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 095bc00e08..25d24eab53 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4356,6 +4356,7 @@ force write permissions on print services. #define TIME_INIT (1<<2) #define CAN_IPC (1<<3) #define AS_GUEST (1<<5) +#define DONT_CHECK_ONLINE (1<<6) /* @@ -4377,15 +4378,15 @@ struct smb_message_struct /* CORE PROTOCOL */ - {SMBnegprot,"SMBnegprot",reply_negprot,0}, - {SMBtcon,"SMBtcon",reply_tcon,0}, - {SMBtdis,"SMBtdis",reply_tdis,0}, - {SMBexit,"SMBexit",reply_exit,0}, - {SMBioctl,"SMBioctl",reply_ioctl,0}, - {SMBecho,"SMBecho",reply_echo,0}, - {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, - {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, - {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ + {SMBnegprot,"SMBnegprot",reply_negprot,DONT_CHECK_ONLINE}, + {SMBtcon,"SMBtcon",reply_tcon,DONT_CHECK_ONLINE}, + {SMBtdis,"SMBtdis",reply_tdis,DONT_CHECK_ONLINE}, + {SMBexit,"SMBexit",reply_exit,DONT_CHECK_ONLINE}, + {SMBioctl,"SMBioctl",reply_ioctl,DONT_CHECK_ONLINE}, + {SMBecho,"SMBecho",reply_echo,DONT_CHECK_ONLINE}, + {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,DONT_CHECK_ONLINE}, + {SMBtconX,"SMBtconX",reply_tcon_and_X,DONT_CHECK_ONLINE}, + {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, DONT_CHECK_ONLINE}, /* ulogoff doesn't give a valid TID */ {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, @@ -4575,6 +4576,10 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1))) return(ERROR(ERRSRV,ERRaccess)); + /* is this service online? */ + if (! (flags & DONT_CHECK_ONLINE) && ! lp_online(SNUM(cnum))) + return(ERROR(ERRHRD,ERRnotready)); + last_inbuf = inbuf; outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize); -- cgit From cdc6099647f7a48a8e31f9dfc331fe82dd66acdf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Nov 1997 19:24:45 +0000 Subject: Rolling back the files loadparm.c : to equivalent to version 1.67 reply.c : to equivalent to version 1.69 server.c : to equivalent to version 1.122 util.c : to equivalent to version 1.98 to remove the incorrect changes. proto.h: The usual. rpc_pipes/smbparse.c : Backeting stuff that SHOULD NOT BE IN THE none-NTDOMAIN build ! Jeremy. (This used to be commit 6064c9d80fd9fcc3ceec528494ba5e2591610098) --- source3/smbd/reply.c | 4 +--- source3/smbd/server.c | 23 +++++++++-------------- 2 files changed, 10 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 116542ba34..46425861d4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1023,9 +1023,7 @@ int reply_search(char *inbuf,char *outbuf) if ((dirtype&0x1F) == aVOLID) { memcpy(p,status,21); - mode = aVOLID; - if(!CAN_WRITE(cnum)) mode |= aRONLY; - make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,mode,0); + make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0); dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 25d24eab53..095bc00e08 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4356,7 +4356,6 @@ force write permissions on print services. #define TIME_INIT (1<<2) #define CAN_IPC (1<<3) #define AS_GUEST (1<<5) -#define DONT_CHECK_ONLINE (1<<6) /* @@ -4378,15 +4377,15 @@ struct smb_message_struct /* CORE PROTOCOL */ - {SMBnegprot,"SMBnegprot",reply_negprot,DONT_CHECK_ONLINE}, - {SMBtcon,"SMBtcon",reply_tcon,DONT_CHECK_ONLINE}, - {SMBtdis,"SMBtdis",reply_tdis,DONT_CHECK_ONLINE}, - {SMBexit,"SMBexit",reply_exit,DONT_CHECK_ONLINE}, - {SMBioctl,"SMBioctl",reply_ioctl,DONT_CHECK_ONLINE}, - {SMBecho,"SMBecho",reply_echo,DONT_CHECK_ONLINE}, - {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,DONT_CHECK_ONLINE}, - {SMBtconX,"SMBtconX",reply_tcon_and_X,DONT_CHECK_ONLINE}, - {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, DONT_CHECK_ONLINE}, /* ulogoff doesn't give a valid TID */ + {SMBnegprot,"SMBnegprot",reply_negprot,0}, + {SMBtcon,"SMBtcon",reply_tcon,0}, + {SMBtdis,"SMBtdis",reply_tdis,0}, + {SMBexit,"SMBexit",reply_exit,0}, + {SMBioctl,"SMBioctl",reply_ioctl,0}, + {SMBecho,"SMBecho",reply_echo,0}, + {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, + {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, + {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, @@ -4576,10 +4575,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1))) return(ERROR(ERRSRV,ERRaccess)); - /* is this service online? */ - if (! (flags & DONT_CHECK_ONLINE) && ! lp_online(SNUM(cnum))) - return(ERROR(ERRHRD,ERRnotready)); - last_inbuf = inbuf; outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize); -- cgit From ec35f1c1cc363b84867fea49f6b2b5e3c0b9b889 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Nov 1997 19:11:16 +0000 Subject: local.h: Added OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR. proto.h: The usual. server.c: Added timestring() messages to oplock logs. Added fix to allow file open processing to continue is an oplock break message times out. Jeremy. (This used to be commit c45369217169fac261b32db71469c007db4b4a03) --- source3/smbd/server.c | 80 +++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 095bc00e08..3c128872e6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2765,8 +2765,8 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) time_t start_time; BOOL shutdown_server = False; - DEBUG(5,("oplock_break: called for dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); + DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \ +global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); if(inbuf == NULL) { @@ -2802,8 +2802,8 @@ global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); if(fsp == NULL) { /* The file could have been closed in the meantime - return success. */ - DEBUG(3,("oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ -allowing break to succeed.\n", dev, inode, fnum)); + DEBUG(3,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ +allowing break to succeed.\n", timestring(), dev, inode, fnum)); return True; } @@ -2818,8 +2818,8 @@ allowing break to succeed.\n", dev, inode, fnum)); if(!fsp->granted_oplock) { - DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ -Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode)); + DEBUG(3,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ +Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode)); return True; } @@ -2862,18 +2862,18 @@ Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode)); */ if (smb_read_error == READ_EOF) - DEBUG(0,("oplock_break: end of file from client\n")); + DEBUG(0,("%s oplock_break: end of file from client\n", timestring())); if (smb_read_error == READ_ERROR) - DEBUG(0,("oplock_break: receive_smb error (%s)\n", - strerror(errno))); + DEBUG(0,("%s oplock_break: receive_smb error (%s)\n", + timestring(), strerror(errno))); if (smb_read_error == READ_TIMEOUT) - DEBUG(0,("oplock_break: receive_smb timed out after %d seconds.\n", - OPLOCK_BREAK_TIMEOUT)); + DEBUG(0,("%s oplock_break: receive_smb timed out after %d seconds.\n", + timestring(), OPLOCK_BREAK_TIMEOUT)); - DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", fsp->name, fnum, dev, inode)); + DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \ +inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); shutdown_server = True; break; } @@ -2889,10 +2889,10 @@ inode = %x).\n", fsp->name, fnum, dev, inode)); if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) { - DEBUG(0,("oplock_break: no break received from client within \ -%d seconds.\n", OPLOCK_BREAK_TIMEOUT)); - DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", fsp->name, fnum, dev, inode)); + DEBUG(0,("%s oplock_break: no break received from client within \ +%d seconds.\n", timestring(), OPLOCK_BREAK_TIMEOUT)); + DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \ +inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); shutdown_server = True; break; } @@ -2904,7 +2904,8 @@ inode = %x).\n", fsp->name, fnum, dev, inode)); if(shutdown_server) { - DEBUG(0,("oplock_break: client failure in break - shutting down this smbd.\n")); + DEBUG(0,("%s oplock_break: client failure in break - shutting down this smbd.\n", + timestring())); close_sockets(); close(oplock_sock); exit_server("oplock break failure"); @@ -2928,8 +2929,8 @@ inode = %x).\n", fsp->name, fnum, dev, inode)); exit_server("oplock_break: global_oplocks_open < 0"); } - DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open)); + DEBUG(3,("%s oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ +global_oplocks_open = %d\n", timestring(), fnum, dev, inode, global_oplocks_open)); return True; } @@ -2978,15 +2979,15 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); addr_out.sin_port = htons( share_entry->op_port ); addr_out.sin_family = AF_INET; - DEBUG(3,("request_oplock_break: sending a oplock break message to pid %d on port %d \ -for dev = %x, inode = %x\n", share_entry->pid, share_entry->op_port, dev, inode)); + DEBUG(3,("%s request_oplock_break: sending a oplock break message to pid %d on port %d \ +for dev = %x, inode = %x\n", timestring(), share_entry->pid, share_entry->op_port, dev, inode)); if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - DEBUG(0,("request_oplock_break: failed when sending a oplock break message \ + DEBUG(0,("%s request_oplock_break: failed when sending a oplock break message \ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", - share_entry->pid, share_entry->op_port, dev, inode, + timestring(), share_entry->pid, share_entry->op_port, dev, inode, strerror(errno))); return False; } @@ -2994,7 +2995,7 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", /* * Now we must await the oplock broken message coming back * from the target smbd process. Timeout if it fails to - * return in OPLOCK_BREAK_TIMEOUT seconds. + * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. * While we get messages that aren't ours, loop. */ @@ -3006,15 +3007,25 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", char *reply_msg_start; if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), - OPLOCK_BREAK_TIMEOUT * 1000) == False) + (OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) * 1000) == False) { if(smb_read_error == READ_TIMEOUT) - DEBUG(0,("request_oplock_break: no response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x\n", share_entry->pid, + { + DEBUG(0,("%s request_oplock_break: no response received to oplock break request to \ +pid %d on port %d for dev = %x, inode = %x\n", timestring(), share_entry->pid, share_entry->op_port, dev, inode)); + /* + * This is a hack to make handling of failing clients more robust. + * If a oplock break response message is not received in the timeout + * period we may assume that the smbd servicing that client holding + * the oplock has died and the client changes were lost anyway, so + * we should continue to try and open the file. + */ + break; + } else - DEBUG(0,("request_oplock_break: error in response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid, + DEBUG(0,("%s request_oplock_break: error in response received to oplock break request to \ +pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, share_entry->pid, share_entry->op_port, dev, inode, strerror(errno))); return False; } @@ -3044,7 +3055,8 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) { /* Ignore it. */ - DEBUG(0,("request_oplock_break: invalid message length received. Ignoring\n")); + DEBUG(0,("%s request_oplock_break: invalid message length received. Ignoring\n", + timestring())); continue; } @@ -3054,9 +3066,9 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid &op_break_msg[OPLOCK_BREAK_PID_OFFSET], OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0)) { - DEBUG(3,("request_oplock_break: received other message whilst awaiting \ + DEBUG(3,("%s request_oplock_break: received other message whilst awaiting \ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", - share_entry->pid, share_entry->op_port, dev, inode)); + timestring(), share_entry->pid, share_entry->op_port, dev, inode)); if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) return False; continue; @@ -3065,7 +3077,7 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", break; } - DEBUG(3,("request_oplock_break: broke oplock.\n")); + DEBUG(3,("%s request_oplock_break: broke oplock.\n", timestring())); return True; } -- cgit From bd529d7a83c35be233baca09bc79aa911ad443ce Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 6 Nov 1997 23:03:58 +0000 Subject: following a cvs error, i am rewriting this monster-commit. with bad grace. Modified Files: --------------- Makefile: adding extra files ipc.c : send_trans_reply() - alignment issue. this makes the alignment the same as that in NT. this should be looked at by people who understand the SMB stuff better than i. api_fd_commands[] - added samr and wkssvc pipes. loadparm.c : lp_domain_controller() changed to mean "samba is a domain controller". it's a "yes/no" parameter, now. no, it isn't used _anywhere_. namedbwork.c nameelect.c : if "domain controller = yes" then add SV_TYPE_DOMAIN_CTRL to the host _and_ workgroup announcements. yes, you must do both: nt does. namelogon.c : important NETLOGON bug in SAMLOGON request parsing, which may be the source of some people's problems with logging on to the Samba PDC. password.c : get_smbpwnam() renamed to get_smbpwd_entry(). pipes.c : added samr and wkssvc pipes. proto.h : usual. can we actually _remove_ proto.h from the cvs tree, and have it as one of the Makefile dependencies, or something? reply.c : get_smbpwnam() renamed to get_smbpwd_entry() - also changed response error code when logging in from a WORKSTATION$ account. yes, paul is right: we need to know when to return the right error code, and why. server.c : added call to reset_chain_pnum(). #ifdef NTDOMAIN added call to init_lsa_policy_hnd() #endif. jeremy, you'd be proud: i did a compile without NTDOMAIN, and caught a link error for this function. smb.h : defines and structures for samr and wkssvc pipes. smbpass.c : modified get_smbpwnam() to get_smbpwd_entry() and it now takes two arguments. one for the name; if this is null, it looks up by smb_userid instead. oh, by the way, smb_userids are actually domain relative ids (RIDs). concatenate a RID with the domain SID, and you have an internet globally unique way of identifying a user. we're using RIDs in the wrong way.... added mod_smbpwnam() function. this was based on code in smbpasswd.c rpc_pipes/lsaparse.c : added enum trusted domain parsing. this is incomplete: i need a packet trace to write it properly. rpc_pipes/pipe_hnd.c : added reset_chain_pnum() function. rpc_pipes/pipenetlog.c : get_smbpwnam() function renamed to get_smbpwd_entry(). arcfour() issues. removed capability of get_md4pw() function to automatically add workstation accounts. this should either be done using smbpasswd -add MACHINE$, or by using \PIPE\samr. rpc_pipes/pipe_util.c : create_pol_hnd() - creates a unique LSA Policy Handle. overkill function: uses a 64 bit sequence number; current unix time and the smbd pid. rpc_pipes/smbparse.c : arcfour() issues. smb_io_unistr2() should advance by uni_str_len not uni_max_len. smb_io_smb_hdr_rb() - request bind uses uint16 for the context id, and uint8 for the num_syntaxes. oops, i put these both as uint32s. Added Files: ------------ rpc_pipes/lsa_hnd.c : on the samr pipe, allocate and associate an LSA Policy Handle with a SID. you receive queries with the LSA Policy Handle, and have to turn this back into a SID in order to answer the query... rpc_pipes/pipesamr.c rpc_pipes/samrparse.c \PIPE\samr processing. samr i presume is the SAM Replication pipe. rpc_pipes/pipewkssvc.c rpc_pipes/wksparse.c \PIPE\wkssvc processing. the Workstation Service pipe? holy cow. (This used to be commit 1bd084b3e690eb26a1006d616075e53d711ecd2f) --- source3/smbd/ipc.c | 4 +++- source3/smbd/password.c | 3 ++- source3/smbd/pipes.c | 4 ++++ source3/smbd/reply.c | 14 +++++++++----- source3/smbd/server.c | 6 ++++++ 5 files changed, 24 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1943129ba6..ce14ccd9bc 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -144,7 +144,7 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); - align = (this_lparam%4); + align = (this_lparam%4)+1; set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); if (this_lparam) @@ -2872,7 +2872,9 @@ struct { #ifdef NTDOMAIN { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP }, + { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP }, { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP }, + { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP }, { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP }, { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported } #else diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b759f68430..185fc68f5a 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -887,7 +887,8 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } - smb_pass = get_smbpwnam(user); + /* non-null username indicates search by username not smb userid */ + smb_pass = get_smbpwd_entry(user, 0); if (!smb_pass) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 4a2e185cb4..e2f704e6af 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -57,6 +57,8 @@ char * known_pipes [] = #if NTDOMAIN "NETLOGON", "srvsvc", + "wkssvc", + "samr", #endif NULL }; @@ -139,6 +141,8 @@ int reply_pipe_close(char *inbuf,char *outbuf) int cnum = SVAL(inbuf,smb_tid); int outsize = set_message(outbuf,0,0,True); + DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum)); + if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid)); return(outsize); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 46425861d4..e8d79b098c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -498,7 +498,8 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* If name ends in $ then I think it's asking about whether a */ /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ - if (user[strlen(user) - 1] == '$') { + if (user[strlen(user) - 1] == '$') + { #ifdef NTDOMAIN struct smb_passwd *smb_pass; /* To check if machine account exists */ /* @@ -511,15 +512,18 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) a domain. This may be the source of future bugs if we cannot be sure whether to reject this or not. */ - smb_pass = get_smbpwnam(user); - if(smb_pass) + /* non-null user name indicates search by username not by smb userid */ + smb_pass = get_smbpwd_entry(user, 0); + + if (!smb_pass) { /* PAXX: This is the NO LOGON workstation trust account stuff */ - DEBUG(4,("Rejecting workstation trust account %s",user)); + DEBUG(4,("No Workstation trust account %s",user)); SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_ALLOTTED_SPACE_EXCEEDED, 0xc000)); /* 0x99 NT error, 0xc00 */ + return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* 0x109 NT error, 0xc000 */ } + computer_id = True; #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */ user[strlen(user) - 1] = '\0'; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3c128872e6..e4e5872035 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4732,6 +4732,7 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) chain_size = 0; chain_fnum = -1; + reset_chain_pnum(); bzero(outbuf,smb_size); @@ -4943,6 +4944,11 @@ static void init_structs(void ) /* for RPC pipes */ init_rpc_pipe_hnd(); +#ifdef NTDOMAIN + /* for LSA handles */ + init_lsa_policy_hnd(); +#endif + init_dptrs(); } -- cgit From 36e5b646d9d6f40b44a9c851c5f8caa499eb2237 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Nov 1997 23:34:51 +0000 Subject: ipc.c: Changing back arbitrary alignment change until I know *why* luke changed it. proto.h: The usual. uid.c: Fix crash bug when attaching with smbclient -mCORE. A vuid pointer was being used when it was null. Jeremy. (This used to be commit ff94f97cf2b0f62cbbddbfd3d126df7f4d649334) --- source3/smbd/ipc.c | 2 +- source3/smbd/uid.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ce14ccd9bc..604cf24d8f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -144,7 +144,7 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); - align = (this_lparam%4)+1; + align = (this_lparam%4); set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); if (this_lparam) diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 645d078979..b36fa4df06 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -232,7 +232,7 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) current_user.groups = conn->groups; current_user.igroups = conn->igroups; current_user.ngroups = conn->ngroups; - current_user.attrs = vuser->attrs; + current_user.attrs = conn->attrs; } else { -- cgit From f9bbcb3fb3effdeb9f9f42de77bbde9f2789efdc Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Fri, 7 Nov 1997 03:06:24 +0000 Subject: Modified Files: mangle.c server.c proto.h mangle.c I am planning to replace the mangled_stack array with a proper stack, but found many style inconsistencies (no, really). As you might expect, I have standardized on my own preferences. ;) I also found a potential problem in create_mangled_stack (which I've renamed as reset_mangled_stack). If the stack size were passed into the function as 0 or less, there was the possibility that the array would have been freed twice. I doubt that this ever happens, but I don't like to leave holes. Of course, the fix will be irrelevent once I replace the array with a linked-list-based stack. server.c Changed the call to create_mangled_stack() to a call to reset_mangled_stack(). proto.h Regenerated to match the above changes. (A real comment! How unusual!) (This used to be commit 34d1b3e4fa7a1158f3a3c5c47adf0417c7144095) --- source3/smbd/mangle.c | 557 ++++++++++++++++++++++++++++---------------------- source3/smbd/server.c | 2 +- 2 files changed, 317 insertions(+), 242 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 829e307a85..bf26475715 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -26,27 +26,33 @@ extern int case_default; extern BOOL case_mangle; /**************************************************************************** -provide a checksum on a string -****************************************************************************/ + * Provide a checksum on a string + * + * Input: s - the nul-terminated character string for which the checksum + * will be calculated. + * Output: The checksum value calculated for s. + * + ****************************************************************************/ int str_checksum(char *s) -{ + { int res = 0; int c; int i=0; - while (*s) + + while( *s ) { - c = *s; - res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); - s++; i++; + c = *s; + res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); + s++; i++; } return(res); -} + } /* str_checksum */ /**************************************************************************** return True if a name is a special msdos reserved name ****************************************************************************/ static BOOL is_reserved_msdos(char *fname) -{ + { char upperFname[13]; char *p; @@ -72,7 +78,7 @@ static BOOL is_reserved_msdos(char *fname) return (True) ; return (False); -} + } /* is_reserved_msdos */ @@ -80,34 +86,37 @@ static BOOL is_reserved_msdos(char *fname) return True if a name is in 8.3 dos format ****************************************************************************/ BOOL is_8_3(char *fname, BOOL check_case) -{ + { int len; char *dot_pos; char *slash_pos = strrchr(fname,'/'); int l; - if (slash_pos) fname = slash_pos+1; + if( slash_pos ) + fname = slash_pos+1; len = strlen(fname); DEBUG(5,("checking %s for 8.3\n",fname)); - if (check_case && case_mangle) + if( check_case && case_mangle ) + { switch (case_default) { case CASE_LOWER: - if (strhasupper(fname)) return(False); - break; + if (strhasupper(fname)) return(False); + break; case CASE_UPPER: - if (strhaslower(fname)) return(False); - break; + if (strhaslower(fname)) return(False); + break; } + } /* can't be longer than 12 chars */ - if (len == 0 || len > 12) + if( len == 0 || len > 12 ) return(False); /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ - if (is_reserved_msdos(fname)) + if( is_reserved_msdos(fname) ) return(False); /* can't contain invalid dos chars */ @@ -121,184 +130,218 @@ BOOL is_8_3(char *fname, BOOL check_case) dot_pos = strchr(fname,'.'); - { + { char *p = fname; + if(lp_client_code_page() == KANJI_CODEPAGE) - { + { dot_pos = 0; while (*p) - { + { if (is_shift_jis (*p)) p += 2; else if (is_kana (*p)) p ++; else - { + { if (*p == '.' && !dot_pos) dot_pos = (char *) p; if (!isdoschar(*p)) return(False); p++; + } } - } - } + } else - { - while (*p) { + while (*p) + { if (!isdoschar(*p)) return(False); p++; - } + } + } } - } /* no dot and less than 9 means OK */ if (!dot_pos) return(len <= 8); - + l = PTR_DIFF(dot_pos,fname); /* base must be at least 1 char except special cases . and .. */ - if (l == 0) + if( l == 0 ) return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0); /* base can't be greater than 8 */ - if (l > 8) + if( l > 8 ) return(False); - if (lp_strip_dot() && + if( lp_strip_dot() && len - l == 1 && - !strchr(dot_pos+1,'.')) + !strchr(dot_pos+1,'.') ) { - *dot_pos = 0; - return(True); + *dot_pos = 0; + return(True); } /* extension must be between 1 and 3 */ - if ( (len - l < 2 ) || (len - l > 4) ) + if( (len - l < 2 ) || (len - l > 4) ) return(False); /* extension can't have a dot */ - if (strchr(dot_pos+1,'.')) + if( strchr(dot_pos+1,'.') ) return(False); /* must be in 8.3 format */ return(True); -} + } /* is_8_3 */ + +/* -------------------------------------------------------------------------- ** + * This section creates and maintains a stack of name mangling results. + * The original comments read: "keep a stack of name mangling results - just + * so file moves and copies have a chance of working" (whatever that means). + * + * There are three functions to manage the stack: + * reset_mangled_stack() - + * push_mangled_name() - + * check_mangled_stack() - + */ - - -/* -keep a stack of name mangling results - just -so file moves and copies have a chance of working -*/ fstring *mangled_stack = NULL; int mangled_stack_size = 0; int mangled_stack_len = 0; /**************************************************************************** -create the mangled stack -****************************************************************************/ -void create_mangled_stack(int size) -{ - if (mangled_stack) + * create the mangled stack CRH + ****************************************************************************/ +void reset_mangled_stack( int size ) + { + if( mangled_stack ) + { + free(mangled_stack); + mangled_stack_size = 0; + mangled_stack_len = 0; + } + + if( size > 0 ) { - free(mangled_stack); - mangled_stack_size = 0; - mangled_stack_len = 0; + mangled_stack = (fstring *)malloc( sizeof(fstring) * size ); + if( mangled_stack ) + mangled_stack_size = size; } - if (size > 0) - mangled_stack = (fstring *)malloc(sizeof(fstring)*size); - if (mangled_stack) mangled_stack_size = size; -} + else + mangled_stack = NULL; + } /* create_mangled_stack */ /**************************************************************************** -push a mangled name onto the stack -****************************************************************************/ + * push a mangled name onto the stack CRH + ****************************************************************************/ static void push_mangled_name(char *s) -{ + { int i; char *p; - if (!mangled_stack) + /* If the stack doesn't exist... Fail. */ + if( !mangled_stack ) return; - for (i=0;i is already on the stack, move it to the top. */ + for( i=0; i wasn't already there, add it to the top of the stack. */ + memmove( mangled_stack[1], mangled_stack[0], + sizeof(fstring) * MIN(mangled_stack_len, mangled_stack_size-1) ); + strcpy( mangled_stack[0], s ); + mangled_stack_len = MIN( mangled_stack_size, mangled_stack_len+1 ); + + /* Hmmm... + * Find the last dot '.' in the name, + * if there are any upper case characters past the last dot + * and there are no more than three characters past the last dot + * then terminate the name *at* the last dot. + */ + p = strrchr( mangled_stack[0], '.' ); + if( p && (!strhasupper(p+1)) && (strlen(p+1) < (size_t)4) ) *p = 0; - mangled_stack_len = MIN(mangled_stack_size,mangled_stack_len+1); -} + + } /* push_mangled_name */ /**************************************************************************** -check for a name on the mangled name stack -****************************************************************************/ + * check for a name on the mangled name stack CRH + ****************************************************************************/ BOOL check_mangled_stack(char *s) -{ + { int i; pstring tmpname; char extension[5]; - char *p = strrchr(s,'.'); + char *p = strrchr( s, '.' ); BOOL check_extension = False; extension[0] = 0; - if (!mangled_stack) return(False); + /* If the stack doesn't exist, fail. */ + if( !mangled_stack ) + return(False); - if (p) + /* If there is a file extension, then we need to play with it, too. */ + if( p ) { - check_extension = True; - StrnCpy(extension,p,4); - strlower(extension); /* XXXXXXX */ + check_extension = True; + StrnCpy( extension, p, 4 ); + strlower( extension ); /* XXXXXXX */ } - for (i=0;i Date: Fri, 7 Nov 1997 03:28:43 +0000 Subject: ipc.c : added a #define around the alignment thing: it's a way to stop NetMonitor from decoding your packets!!!! proto.h : usual. reply.c : added what i believe to be the correct error messages for getting correct domain joining. smb.h : some guesses at good names of the SAMR_XXXX functions. sorting out the SAMR_LOOKUP_RIDS function. this is *not* the same as the LSA_LOOKUP_RIDS function, unless paul accidentally put it on the ntlsa pipe by mistake, instead of the samr pipe :-) rpc_pipes/lsa_hnd.c rpc_pipes/pipe_hnd.c : moved creation and allocation of unique policy handles into this module. rpc_pipes/pipesamr.c rpc_pipes/samrparse.c rpc_pipes/smbparse.c : SAMR_LOOKUP_RIDS is beginning to look _suspiciously_ like the LSA_LOOKUP_RIDS function. but i know that there are subtle discrepancies. (This used to be commit 6bc07b0b4193e28b13a675fece8d9d6b365a7eb0) --- source3/smbd/ipc.c | 5 +++++ source3/smbd/reply.c | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 604cf24d8f..741290d2a2 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -144,7 +144,12 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); +#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING + /* if you don't want Net Monitor to decode your packets, do this!!! */ + align = ((this_lparam+1)%4); +#else align = (this_lparam%4); +#endif set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); if (this_lparam) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e8d79b098c..78dad6f02f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -516,12 +516,21 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) smb_pass = get_smbpwd_entry(user, 0); if (!smb_pass) + { + /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */ + DEBUG(4,("Workstation trust account %s doesn't exist.",user)); + SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ + CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ + return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */ + } + else { /* PAXX: This is the NO LOGON workstation trust account stuff */ + /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */ DEBUG(4,("No Workstation trust account %s",user)); SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* 0x109 NT error, 0xc000 */ + return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */ } computer_id = True; -- cgit From e357d9106895b165bfa3f8331b9f186004c9a6cd Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 9 Nov 1997 17:30:10 +0000 Subject: attempting to mark up 32 bit error codes, needed for NT domains. separated out smb server-mode password validation into a separate file. added called and calling netbios names to client gen state: referenced section in rfc1002.txt. created workstation trust account checking code in ntclient.c there might be a bug in reply_session_setup_andX. i indented and added { } around single-line if statements: the lm password checking code now doesn't look right (around the GUEST_SESSSETUP bits). *no code semantics have been changed by the indentation process*. (This used to be commit f27966957fa7f16d337a4a58719239d036deab4c) --- source3/smbd/password.c | 140 +----------------------------------------------- source3/smbd/reply.c | 89 +++++++++++++++++------------- source3/smbd/server.c | 93 +++++++++++++++++++------------- 3 files changed, 110 insertions(+), 212 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 185fc68f5a..7dd2133406 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,7 +21,7 @@ #include "includes.h" -#if (defined(NETGROUP) && defined (AUTOMOUNT)) +#ifdef NETGROUP #include "rpcsvc/ypclnt.h" #endif @@ -1475,141 +1475,3 @@ BOOL check_hosts_equiv(char *user) return(False); } - -static struct cli_state cli; - -/**************************************************************************** -return the client state structure -****************************************************************************/ -struct cli_state *server_client(void) -{ - return &cli; -} - -/**************************************************************************** -support for server level security -****************************************************************************/ -struct cli_state *server_cryptkey(void) -{ - fstring desthost; - struct in_addr dest_ip; - extern fstring local_machine; - char *p; - - if (!cli_initialise(&cli)) - return NULL; - - for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { - fstrcpy(desthost,p); - standard_sub_basic(desthost); - strupper(desthost); - - dest_ip = *interpret_addr2(desthost); - if (zero_ip(dest_ip)) { - DEBUG(1,("Can't resolve address for %s\n",p)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",p)); - continue; - } - - if (cli_connect(&cli, desthost, &dest_ip)) { - DEBUG(3,("connected to password server %s\n",p)); - break; - } - } - - if (!p) { - DEBUG(1,("password server not available\n")); - cli_shutdown(&cli); - return NULL; - } - - if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { - DEBUG(1,("%s rejected the session\n",desthost)); - cli_shutdown(&cli); - return NULL; - } - - DEBUG(3,("got session\n")); - - if (!cli_negprot(&cli)) { - DEBUG(1,("%s rejected the negprot\n",desthost)); - cli_shutdown(&cli); - return NULL; - } - - if (cli.protocol < PROTOCOL_LANMAN2 || - !(cli.sec_mode & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",desthost)); - cli_shutdown(&cli); - return NULL; - } - - DEBUG(3,("password server OK\n")); - - return &cli; -} - -/**************************************************************************** -validate a password with the password server -****************************************************************************/ -BOOL server_validate(char *user, char *domain, - char *pass, int passlen, - char *ntpass, int ntpasslen) -{ - extern fstring local_machine; - - if (!cli.initialised) { - DEBUG(1,("password server %s is not connected\n", cli.desthost)); - return(False); - } - - if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { - DEBUG(1,("password server %s rejected the password\n", cli.desthost)); - return False; - } - - /* if logged in as guest then reject */ - if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); - return(False); - } - - - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { - DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); - return False; - } - - - if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { - DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); - cli_tdis(&cli); - return False; - } - - if (cli.privilages == 0) { - DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); - cli_tdis(&cli); - return False; - } - - if (!strequal(cli.eff_name, user)) { - DEBUG(1,("password server %s gave different username %s\n", - cli.desthost, - cli.eff_name)); - cli_tdis(&cli); - return False; - } - - DEBUG(3,("password server %s accepted the password\n", cli.desthost)); - - cli_tdis(&cli); - - return(True); -} - - diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 78dad6f02f..532fc583c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -395,6 +395,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; + struct cli_state *pwd_srv = NULL; *smb_apasswd = 0; *smb_ntpasswd = 0; @@ -518,19 +519,17 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!smb_pass) { /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */ - DEBUG(4,("Workstation trust account %s doesn't exist.",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */ + DEBUG(4,("Workstation trust account %s doesn't exist\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */ + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); /* decimal 109; critical NT error */ } else { /* PAXX: This is the NO LOGON workstation trust account stuff */ /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */ - DEBUG(4,("No Workstation trust account %s",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */ + DEBUG(4,("No Workstation trust account %s\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */ + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); /* decimal 409; critical NT error */ } computer_id = True; @@ -563,43 +562,59 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) */ if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) + { guest = True; + } - if (!guest && !(lp_security() == SEC_SERVER && - server_validate(user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen)) && - !check_hosts_equiv(user)) - { - - /* now check if it's a valid username/password */ - /* If an NT password was supplied try and validate with that - first. This is superior as the passwords are mixed case - 128 length unicode */ - if(smb_ntpasslen) - { - if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) - DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); - else - valid_nt_password = True; - } - if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) + if (!guest && !(lp_security() == SEC_SERVER && + ((pwd_srv = pwd_server_connection()) != NULL) && + server_validate(pwd_srv, user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && + !check_hosts_equiv(user)) { - if (!computer_id && lp_security() >= SEC_USER) { + + /* now check if it's a valid username/password */ + /* If an NT password was supplied try and validate with that + first. This is superior as the passwords are mixed case + 128 length unicode */ + + if (smb_ntpasslen) + { + /* check the NT password, if there is one. */ + if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) + { + DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); + } + else + { + valid_nt_password = True; + } + } + + /* check the LM password instead */ + if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) + { + if (!computer_id && lp_security() >= SEC_USER) + { #if (GUEST_SESSSETUP == 0) - return(ERROR(ERRSRV,ERRbadpw)); + return(ERROR(ERRSRV,ERRbadpw)); #endif #if (GUEST_SESSSETUP == 1) - if (Get_Pwnam(user,True)) - return(ERROR(ERRSRV,ERRbadpw)); + if (Get_Pwnam(user,True)) + return(ERROR(ERRSRV,ERRbadpw)); #endif - } - if (*smb_apasswd || !Get_Pwnam(user,True)) - strcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; + } + + /* no lm or nt password specified: username doesn't exist. allow guest access */ + if (*smb_apasswd || !Get_Pwnam(user,True)) + { + strcpy(user, lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } + } } - } if (!Get_Pwnam(user,True)) { DEBUG(3,("No such user %s - using guest account\n",user)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 908cf984b8..a42b4deea2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -25,6 +25,7 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; extern pstring sesssetup_user; +extern pstring local_machine; extern fstring myworkgroup; char *InBuffer = NULL; @@ -114,6 +115,21 @@ static int find_free_connection(int hash); #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0) #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0) +/* use this to validate user against a password server. "security = server" */ +static struct cli_state pwd_srv; + +/**************************************************************************** + for use in reply.c, to access the password server connection. +****************************************************************************/ +struct cli_state *pwd_server_connection(void) +{ + if (pwd_srv.initialised) + { + return &pwd_srv; + } + return NULL; +} + /**************************************************************************** when exiting, take the whole family ****************************************************************************/ @@ -2257,21 +2273,30 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int { int outsize = set_message(outbuf,0,0,True); int cmd; - cmd = CVAL(inbuf,smb_com); - - CVAL(outbuf,smb_rcls) = error_class; - SSVAL(outbuf,smb_err,error_code); + int flgs2; + cmd = CVAL(inbuf,smb_com); + flgs2 = SVAL(outbuf,smb_flg2); - DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - timestring(), - line, - (int)CVAL(inbuf,smb_com), - smb_fn_name(CVAL(inbuf,smb_com)), - error_class, - error_code)); + if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) + { + SIVAL(outbuf,smb_rcls,error_code); + + DEBUG(3,("%s 32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", + timestring(), line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf))); + } + else + { + CVAL(outbuf,smb_rcls) = error_class; + SSVAL(outbuf,smb_err,error_code); + DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + timestring(), line, cmd, smb_fn_name(cmd), error_class, error_code)); + } + if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); + { + DEBUG(3,("error string = %s\n", strerror(errno))); + } return(outsize); } @@ -2328,12 +2353,13 @@ static int sig_cld() **************************************************************************/ static int sig_pipe() { - struct cli_state *cli; BlockSignals(True,SIGPIPE); - if ((cli = server_client()) && cli->initialised) { + if (pwd_srv.initialised) + { DEBUG(3,("lost connection to password server\n")); - cli_shutdown(cli); + cli_shutdown(&pwd_srv); + #ifndef DONT_REINSTALL_SIG signal(SIGPIPE, SIGNAL_CAST sig_pipe); #endif @@ -3684,29 +3710,27 @@ int reply_lanman2(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); - struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { + if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine)) + { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + doencrypt = ((pwd_srv.sec_mode & 2) != 0); } if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; - if (doencrypt) { + if (doencrypt) + { crypt_len = 8; - if (!cli) { + if (pwd_srv.initialised) + { generate_next_challenge(cryptkey); } else { - memcpy(cryptkey, cli->cryptkey, 8); - set_challenge(cli->cryptkey); + memcpy(cryptkey, pwd_srv.cryptkey, 8); + set_challenge(pwd_srv.cryptkey); } } @@ -3751,16 +3775,14 @@ int reply_nt1(char *outbuf) char cryptkey[8]; char crypt_len = 0; - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { + if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine)) + { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + doencrypt = ((pwd_srv.sec_mode & 2) != 0); } - if (doencrypt) { + if (doencrypt) + { crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); @@ -4862,15 +4884,14 @@ static void process(void) if (keepalive && (counter-last_keepalive)>keepalive) { - struct cli_state *cli = server_client(); if (!send_keepalive(Client)) { DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); return; } /* also send a keepalive to the password server if its still connected */ - if (cli && cli->initialised) - send_keepalive(cli->fd); + if (pwd_srv.initialised) + send_keepalive(pwd_srv.fd); last_keepalive = counter; } -- cgit From 77aec4ae6307c0ad0b843bbf23d64ccb1aaf7476 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Nov 1997 19:23:17 +0000 Subject: Rolled back tree state to 11:59pm 8th November 1997 EST to remove problems. Jeremy (This used to be commit 4a36ac236c2ad634f05efcd0179875d09988614a) --- source3/smbd/password.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/reply.c | 89 +++++++++++++----------------- source3/smbd/server.c | 93 +++++++++++++------------------- 3 files changed, 212 insertions(+), 110 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 7dd2133406..185fc68f5a 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,7 +21,7 @@ #include "includes.h" -#ifdef NETGROUP +#if (defined(NETGROUP) && defined (AUTOMOUNT)) #include "rpcsvc/ypclnt.h" #endif @@ -1475,3 +1475,141 @@ BOOL check_hosts_equiv(char *user) return(False); } + +static struct cli_state cli; + +/**************************************************************************** +return the client state structure +****************************************************************************/ +struct cli_state *server_client(void) +{ + return &cli; +} + +/**************************************************************************** +support for server level security +****************************************************************************/ +struct cli_state *server_cryptkey(void) +{ + fstring desthost; + struct in_addr dest_ip; + extern fstring local_machine; + char *p; + + if (!cli_initialise(&cli)) + return NULL; + + for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { + fstrcpy(desthost,p); + standard_sub_basic(desthost); + strupper(desthost); + + dest_ip = *interpret_addr2(desthost); + if (zero_ip(dest_ip)) { + DEBUG(1,("Can't resolve address for %s\n",p)); + continue; + } + + if (ismyip(dest_ip)) { + DEBUG(1,("Password server loop - disabling password server %s\n",p)); + continue; + } + + if (cli_connect(&cli, desthost, &dest_ip)) { + DEBUG(3,("connected to password server %s\n",p)); + break; + } + } + + if (!p) { + DEBUG(1,("password server not available\n")); + cli_shutdown(&cli); + return NULL; + } + + if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { + DEBUG(1,("%s rejected the session\n",desthost)); + cli_shutdown(&cli); + return NULL; + } + + DEBUG(3,("got session\n")); + + if (!cli_negprot(&cli)) { + DEBUG(1,("%s rejected the negprot\n",desthost)); + cli_shutdown(&cli); + return NULL; + } + + if (cli.protocol < PROTOCOL_LANMAN2 || + !(cli.sec_mode & 1)) { + DEBUG(1,("%s isn't in user level security mode\n",desthost)); + cli_shutdown(&cli); + return NULL; + } + + DEBUG(3,("password server OK\n")); + + return &cli; +} + +/**************************************************************************** +validate a password with the password server +****************************************************************************/ +BOOL server_validate(char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen) +{ + extern fstring local_machine; + + if (!cli.initialised) { + DEBUG(1,("password server %s is not connected\n", cli.desthost)); + return(False); + } + + if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", cli.desthost)); + return False; + } + + /* if logged in as guest then reject */ + if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); + return(False); + } + + + if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { + DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); + return False; + } + + + if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { + DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); + cli_tdis(&cli); + return False; + } + + if (cli.privilages == 0) { + DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); + cli_tdis(&cli); + return False; + } + + if (!strequal(cli.eff_name, user)) { + DEBUG(1,("password server %s gave different username %s\n", + cli.desthost, + cli.eff_name)); + cli_tdis(&cli); + return False; + } + + DEBUG(3,("password server %s accepted the password\n", cli.desthost)); + + cli_tdis(&cli); + + return(True); +} + + diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 532fc583c2..78dad6f02f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -395,7 +395,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; - struct cli_state *pwd_srv = NULL; *smb_apasswd = 0; *smb_ntpasswd = 0; @@ -519,17 +518,19 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!smb_pass) { /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */ - DEBUG(4,("Workstation trust account %s doesn't exist\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */ - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); /* decimal 109; critical NT error */ + DEBUG(4,("Workstation trust account %s doesn't exist.",user)); + SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ + CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ + return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */ } else { /* PAXX: This is the NO LOGON workstation trust account stuff */ /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */ - DEBUG(4,("No Workstation trust account %s\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */ - return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); /* decimal 409; critical NT error */ + DEBUG(4,("No Workstation trust account %s",user)); + SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ + CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ + return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */ } computer_id = True; @@ -562,59 +563,43 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) */ if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) - { guest = True; - } - - if (!guest && !(lp_security() == SEC_SERVER && - ((pwd_srv = pwd_server_connection()) != NULL) && - server_validate(pwd_srv, user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen)) && - !check_hosts_equiv(user)) - { - /* now check if it's a valid username/password */ - /* If an NT password was supplied try and validate with that - first. This is superior as the passwords are mixed case - 128 length unicode */ + if (!guest && !(lp_security() == SEC_SERVER && + server_validate(user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && + !check_hosts_equiv(user)) + { - if (smb_ntpasslen) - { - /* check the NT password, if there is one. */ - if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) - { - DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); - } - else - { - valid_nt_password = True; - } - } - - /* check the LM password instead */ - if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) - { - if (!computer_id && lp_security() >= SEC_USER) - { + /* now check if it's a valid username/password */ + /* If an NT password was supplied try and validate with that + first. This is superior as the passwords are mixed case + 128 length unicode */ + if(smb_ntpasslen) + { + if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) + DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); + else + valid_nt_password = True; + } + if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) + { + if (!computer_id && lp_security() >= SEC_USER) { #if (GUEST_SESSSETUP == 0) - return(ERROR(ERRSRV,ERRbadpw)); + return(ERROR(ERRSRV,ERRbadpw)); #endif #if (GUEST_SESSSETUP == 1) - if (Get_Pwnam(user,True)) - return(ERROR(ERRSRV,ERRbadpw)); + if (Get_Pwnam(user,True)) + return(ERROR(ERRSRV,ERRbadpw)); #endif - } - - /* no lm or nt password specified: username doesn't exist. allow guest access */ - if (*smb_apasswd || !Get_Pwnam(user,True)) - { - strcpy(user, lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } - } + } + if (*smb_apasswd || !Get_Pwnam(user,True)) + strcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; } + } if (!Get_Pwnam(user,True)) { DEBUG(3,("No such user %s - using guest account\n",user)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a42b4deea2..908cf984b8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -25,7 +25,6 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; extern pstring sesssetup_user; -extern pstring local_machine; extern fstring myworkgroup; char *InBuffer = NULL; @@ -115,21 +114,6 @@ static int find_free_connection(int hash); #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0) #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0) -/* use this to validate user against a password server. "security = server" */ -static struct cli_state pwd_srv; - -/**************************************************************************** - for use in reply.c, to access the password server connection. -****************************************************************************/ -struct cli_state *pwd_server_connection(void) -{ - if (pwd_srv.initialised) - { - return &pwd_srv; - } - return NULL; -} - /**************************************************************************** when exiting, take the whole family ****************************************************************************/ @@ -2273,30 +2257,21 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int { int outsize = set_message(outbuf,0,0,True); int cmd; - int flgs2; - cmd = CVAL(inbuf,smb_com); - flgs2 = SVAL(outbuf,smb_flg2); + cmd = CVAL(inbuf,smb_com); - if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) - { - SIVAL(outbuf,smb_rcls,error_code); - - DEBUG(3,("%s 32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", - timestring(), line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf))); - } - else - { - CVAL(outbuf,smb_rcls) = error_class; - SSVAL(outbuf,smb_err,error_code); - - DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - timestring(), line, cmd, smb_fn_name(cmd), error_class, error_code)); - } + CVAL(outbuf,smb_rcls) = error_class; + SSVAL(outbuf,smb_err,error_code); + DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + timestring(), + line, + (int)CVAL(inbuf,smb_com), + smb_fn_name(CVAL(inbuf,smb_com)), + error_class, + error_code)); + if (errno != 0) - { - DEBUG(3,("error string = %s\n", strerror(errno))); - } + DEBUG(3,("error string = %s\n",strerror(errno))); return(outsize); } @@ -2353,13 +2328,12 @@ static int sig_cld() **************************************************************************/ static int sig_pipe() { + struct cli_state *cli; BlockSignals(True,SIGPIPE); - if (pwd_srv.initialised) - { + if ((cli = server_client()) && cli->initialised) { DEBUG(3,("lost connection to password server\n")); - cli_shutdown(&pwd_srv); - + cli_shutdown(cli); #ifndef DONT_REINSTALL_SIG signal(SIGPIPE, SIGNAL_CAST sig_pipe); #endif @@ -3710,27 +3684,29 @@ int reply_lanman2(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); + struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; - if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine)) - { + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } + + if (cli) { DEBUG(3,("using password server validation\n")); - doencrypt = ((pwd_srv.sec_mode & 2) != 0); + doencrypt = ((cli->sec_mode & 2) != 0); } if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; - if (doencrypt) - { + if (doencrypt) { crypt_len = 8; - if (pwd_srv.initialised) - { + if (!cli) { generate_next_challenge(cryptkey); } else { - memcpy(cryptkey, pwd_srv.cryptkey, 8); - set_challenge(pwd_srv.cryptkey); + memcpy(cryptkey, cli->cryptkey, 8); + set_challenge(cli->cryptkey); } } @@ -3775,14 +3751,16 @@ int reply_nt1(char *outbuf) char cryptkey[8]; char crypt_len = 0; - if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine)) - { + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } + + if (cli) { DEBUG(3,("using password server validation\n")); - doencrypt = ((pwd_srv.sec_mode & 2) != 0); + doencrypt = ((cli->sec_mode & 2) != 0); } - if (doencrypt) - { + if (doencrypt) { crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); @@ -4884,14 +4862,15 @@ static void process(void) if (keepalive && (counter-last_keepalive)>keepalive) { + struct cli_state *cli = server_client(); if (!send_keepalive(Client)) { DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); return; } /* also send a keepalive to the password server if its still connected */ - if (pwd_srv.initialised) - send_keepalive(pwd_srv.fd); + if (cli && cli->initialised) + send_keepalive(cli->fd); last_keepalive = counter; } -- cgit From 5c3f9f4e2c7ab8e2190e2089dccfa01d1fd44f5e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Nov 1997 00:48:42 +0000 Subject: auto-create the locks directory on startup (This used to be commit a0ab8fe54c27d9f25266c5abfd60458827500dfd) --- source3/smbd/server.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 908cf984b8..278087b60a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5138,6 +5138,10 @@ static void usage(char *pname) become_daemon(); } + if (!directory_exist(lp_lockdir(), NULL)) { + mkdir(lp_lockdir(), 0755); + } + if (*pidFile) { int fd; -- cgit From daa618991028862ba2c2d91fd4a83eeace46cd6a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Nov 1997 01:19:32 +0000 Subject: Left global_oplock_break set while request to break oplock is outstanding to client. Done to allay Andrews' fears about readbraw crossing on the wire :-). Jeremy. (This used to be commit 2fe8a730d9eeadca22ed1424014181e193ce3d52) --- source3/smbd/server.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 278087b60a..e3328690b0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2844,6 +2844,7 @@ Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, in send_smb(Client, outbuf); + /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; /* Process incoming messages. */ @@ -2879,10 +2880,6 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); } process_smb(inbuf, outbuf); - /* We only need this in case a readraw crossed on the wire. */ - if(global_oplock_break) - global_oplock_break = False; - /* * Die if we go over the time limit. */ @@ -2898,6 +2895,10 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); } } + /* We need this in case a readraw crossed on the wire. */ + if(global_oplock_break) + global_oplock_break = False; + /* * If the client did not respond we must die. */ -- cgit From 9f804556c4d0bb68f9b7acaf2b679bc0a02ea8f9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Nov 1997 19:16:38 +0000 Subject: loadparm.c : Added "veto oplock files" parameter. make_printerdef.c: Fixed warning. quotas.c: Fixed irix root errors. server.c: Fixed oplock reference count bug. smb.h: Added IS_VETO_OPLOCK_PATH(). Jeremy. (This used to be commit c28487df63e29bc0f8d2ece876a07a2a076d4c73) --- source3/smbd/quotas.c | 7 +++++++ source3/smbd/server.c | 16 +++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 8810bcd909..562d8fd5db 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -473,6 +473,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); + seteuid(euser_id); /* Restore the original uid status. */ + if (r==-1) return(False); @@ -502,6 +504,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); + seteuid(euser_id); /* Restore the original uid status. */ + if (r==-1) return(False); @@ -531,7 +535,10 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } else + { + seteuid(euser_id); /* Restore the original uid status. */ return(False); + } return (True); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e3328690b0..d51c43c2f7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1473,6 +1473,9 @@ void close_file(int fnum, BOOL normal_close) if (normal_close) check_magic(fnum,cnum); + if(fs_p->granted_oplock == True) + global_oplocks_open--; + DEBUG(2,("%s %s closed file %s (numopen=%d)\n", timestring(),Connections[cnum].user,fs_p->name, Connections[cnum].num_files_open)); @@ -1680,9 +1683,9 @@ int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, (access_allowed == AREAD && *flags == O_WRONLY) || (access_allowed == AWRITE && *flags == O_RDONLY)) { - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", + DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", deny_mode,old_deny_mode,old_open_mode, - share->pid,fname, access_allowed)); + share->pid,fname, fcbopen, *flags, access_allowed)); return False; } @@ -1928,7 +1931,8 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); be extended to level II oplocks (multiple reader oplocks). */ - if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum))) + if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum)) && + !IS_VETO_OPLOCK_PATH(cnum,fname)) { fs_p->granted_oplock = True; global_oplocks_open++; @@ -2918,9 +2922,8 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); from the sharemode. */ /* Paranoia.... */ fsp->granted_oplock = False; - } - global_oplocks_open--; + } /* Santity check - remove this later. JRA */ if(global_oplocks_open < 0) @@ -3391,6 +3394,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->dirptr = NULL; pcon->veto_list = NULL; pcon->hide_list = NULL; + pcon->veto_oplock_list = NULL; string_set(&pcon->dirpath,""); string_set(&pcon->user,user); @@ -3541,6 +3545,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum))); set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum))); + set_namearray( &pcon->veto_oplock_list, lp_veto_oplocks(SNUM(cnum))); } { @@ -4070,6 +4075,7 @@ void close_cnum(int cnum, uint16 vuid) free_namearray(Connections[cnum].veto_list); free_namearray(Connections[cnum].hide_list); + free_namearray(Connections[cnum].veto_oplock_list); string_set(&Connections[cnum].user,""); string_set(&Connections[cnum].dirpath,""); -- cgit From 689ed3481d491e247fac8fb57a0bd78bfa216c2a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Nov 1997 23:30:49 +0000 Subject: ipc.c: Changed reply_trans to use receive_next_smb() to cope with local message processing. reply.c: Added check to reply_lockingX for chain after oplock break. server.c: Added receive_next_smb(). trans2.c: Changed reply_trans2 to use receive_next_smb() to cope with local message processing. (This used to be commit f4ae644e13f2c4479dfc94c77c0a8295edf54086) --- source3/smbd/ipc.c | 16 ++++++++++++---- source3/smbd/reply.c | 9 ++++++++- source3/smbd/server.c | 26 ++++++++++++++++++++++++++ source3/smbd/trans2.c | 16 +++++++++++++--- 4 files changed, 59 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 741290d2a2..c862ff3b38 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -62,6 +62,8 @@ extern fstring myworkgroup; #define QNLEN 12 /* queue name maximum length */ extern int Client; +extern int oplock_sock; +extern int smb_read_error; static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, @@ -3203,7 +3205,7 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, /**************************************************************************** reply to a SMBtrans ****************************************************************************/ -int reply_trans(char *inbuf,char *outbuf) +int reply_trans(char *inbuf,char *outbuf, int size, int bufsize) { fstring name; @@ -3266,12 +3268,18 @@ int reply_trans(char *inbuf,char *outbuf) /* receive the rest of the trans packet */ while (pscnt < tpscnt || dscnt < tdscnt) { + BOOL ret; int pcnt,poff,dcnt,doff,pdisp,ddisp; - if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || - CVAL(inbuf, smb_com) != SMBtrans) + ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT); + + if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) { - DEBUG(2,("Invalid secondary trans2 packet\n")); + if(ret) + DEBUG(0,("reply_trans: Invalid secondary trans packet\n")); + else + DEBUG(0,("reply_trans: %s in getting secondary trans response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); if (params) free(params); if (data) free(data); if (setup) free(setup); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 78dad6f02f..0d5f016613 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3495,7 +3495,14 @@ dev = %x, inode = %x\n", /* if this is a pure oplock break request then don't send a reply */ if (num_locks == 0 && num_ulocks == 0) - return -1; + { + /* Sanity check - ensure a pure oplock break is not a + chained request. */ + if(CVAL(inbuf,smb_vwv0) != 0xff) + DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", + (unsigned int)CVAL(inbuf,smb_vwv0) )); + return -1; + } } /* Data now points at the beginning of the list diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d51c43c2f7..3f4f6c7034 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3086,6 +3086,32 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", return True; } +/**************************************************************************** +Get the next SMB packet, doing the local message processing automatically. +****************************************************************************/ + +BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout) +{ + BOOL got_smb = False; + BOOL ret; + + do + { + ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize, + timeout,&got_smb); + + if(ret && !got_smb) + { + /* Deal with oplock break requests from other smbd's. */ + process_local_message(oplock_sock, inbuf, bufsize); + continue; + } + } + while(ret && !got_smb); + + return ret; +} + /**************************************************************************** check if a snum is in use ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6a7fc292fa..0ca678b768 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -30,6 +30,8 @@ extern connection_struct Connections[]; extern files_struct Files[]; extern BOOL case_sensitive; extern int Client; +extern int oplock_sock; +extern int smb_read_error; /**************************************************************************** Send the required number of replies back. @@ -1702,11 +1704,19 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) while( num_data_sofar < total_data || num_params_sofar < total_params) { - if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || - CVAL(inbuf, smb_com) != SMBtranss2) + BOOL ret; + + ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize, + SMB_SECONDARY_WAIT); + + if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) { outsize = set_message(outbuf,0,0,True); - DEBUG(2,("Invalid secondary trans2 packet\n")); + if(ret) + DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n")); + else + DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); free(params); free(data); return(ERROR(ERRSRV,ERRerror)); -- cgit From 31e8936b9a416aad109e6f63f4c90ac596116510 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Nov 1997 01:36:36 +0000 Subject: added some debug lines to the rename code (This used to be commit ee3042eefb47bbdbefc83ab3f0f407c7dea4d8a0) --- source3/smbd/reply.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0d5f016613..2c646d99f5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3158,14 +3158,23 @@ int reply_mv(char *inbuf,char *outbuf) error = ERRnoaccess; sprintf(fname,"%s/%s",directory,dname); - if (!can_rename(fname,cnum)) continue; + if (!can_rename(fname,cnum)) { + DEBUG(6,("rename %s refused\n", fname)); + continue; + } pstrcpy(destname,newname); - if (!resolve_wildcards(fname,destname)) continue; + if (!resolve_wildcards(fname,destname)) { + DEBUG(6,("resolve_wildcards %s %s failed\n", + fname, destname)); + continue; + } if (file_exist(destname,NULL)) { - error = 183; - continue; + DEBUG(6,("file_exist %s\n", + destname)); + error = 183; + continue; } if (!sys_rename(fname,destname)) count++; DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname)); -- cgit From f822c17d35921817e19ce0d879788125f361d4b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 Nov 1997 03:30:24 +0000 Subject: fixed a very nasty oplock bug. We could send oplock break requests on files that aren't open if the file happened to close while the oplock was in transit. We would end up sending a oplock break request on another random file (actually the open file that happened to have the highest fnum). Then we wouldn't get a response, so smbd would keep sending and would actually flood the net with an infinite number of oplock break requests! (This used to be commit 0da20e0aecbf3e59bdc649c489a18832403dc9b2) --- source3/smbd/server.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3f4f6c7034..8a52ddef69 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2795,11 +2795,12 @@ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); { if(OPEN_FNUM(fnum)) { - fsp = &Files[fnum]; if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) && (fsp->open_time.tv_sec == tval->tv_sec) && - (fsp->open_time.tv_usec == tval->tv_usec)) - break; + (fsp->open_time.tv_usec == tval->tv_usec)) { + fsp = &Files[fnum]; + break; + } } } -- cgit From bca5c727af0251c79db63a44f48bfdcc73915806 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 Nov 1997 03:39:04 +0000 Subject: there was a bug in my oplock bugfix :-) It's fixed properly now :-) (This used to be commit a6a04b5c6cd35e4b5f4dd4522775961e6315c658) --- source3/smbd/server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8a52ddef69..536e89bf18 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2795,9 +2795,9 @@ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); { if(OPEN_FNUM(fnum)) { - if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) && - (fsp->open_time.tv_sec == tval->tv_sec) && - (fsp->open_time.tv_usec == tval->tv_usec)) { + if((Files[fnum].fd_ptr->dev == dev) && (Files[fnum].fd_ptr->inode == inode) && + (Files[fnum].open_time.tv_sec == tval->tv_sec) && + (Files[fnum].open_time.tv_usec == tval->tv_usec)) { fsp = &Files[fnum]; break; } -- cgit From cf9d07cc7d41627a59ea3bec5ba2b9eebb894ab5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 29 Nov 1997 02:40:31 +0000 Subject: added a sent_oplock_break element to Files[] as a paranoia check so we can't sent a oplock break twice on the same file. changed some debug levels in the oplock code to level 0 so we can track down a bug zero the returned Files[] entry in find_free_file() don't try to overcome client bugs in the handling of non-encrypted passwords if in server level security mode added paranoid null termination of password buffers slight change to my ajt_panic() routine (This used to be commit e360c79c9cec681c4609783019749773d3e79386) --- source3/smbd/reply.c | 10 ++++++---- source3/smbd/server.c | 24 ++++++++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2c646d99f5..ec94ab0552 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -260,7 +260,6 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) int connection_num; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); - BOOL doencrypt = SMBENCRYPT(); *service = *user = *password = *devicename = 0; @@ -279,7 +278,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) password[passlen]=0; path = smb_buf(inbuf) + passlen; - if (!doencrypt || passlen != 24) { + if (passlen != 24) { if (strequal(password," ")) *password = 0; passlen = strlen(password); @@ -412,9 +411,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); + smb_apasswd[smb_apasslen] = 0; pstrcpy(user,smb_buf(inbuf)+smb_apasslen); - if (lp_security() != SEC_SERVER && !doencrypt) { + if (!doencrypt && (lp_security() != SEC_SERVER)) { smb_apasslen = strlen(smb_apasswd); } } else { @@ -448,12 +448,14 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) passlen1 = MIN(passlen1, MAX_PASS_LEN); passlen2 = MIN(passlen2, MAX_PASS_LEN); - if(doencrypt) { + if(doencrypt || (lp_security() == SEC_SERVER)) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; memcpy(smb_apasswd,p,smb_apasslen); + smb_apasswd[smb_apasslen] = 0; smb_ntpasslen = passlen2; memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); + smb_ntpasswd[smb_ntpasslen] = 0; } else { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 536e89bf18..77c8fc319f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1935,6 +1935,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); !IS_VETO_OPLOCK_PATH(cnum,fname)) { fs_p->granted_oplock = True; + fs_p->sent_oplock_break = False; global_oplocks_open++; port = oplock_port; @@ -2807,7 +2808,7 @@ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); if(fsp == NULL) { /* The file could have been closed in the meantime - return success. */ - DEBUG(3,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ + DEBUG(0,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ allowing break to succeed.\n", timestring(), dev, inode, fnum)); return True; } @@ -2823,11 +2824,19 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum)); if(!fsp->granted_oplock) { - DEBUG(3,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ -Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode)); + DEBUG(0,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode)); return True; } + /* mark the oplock break as sent - we don't want to send twice! */ + if (fsp->sent_oplock_break) + { + DEBUG(0,("%s ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode)); + return True; + } + + fsp->sent_oplock_break = True; + /* Now comes the horrid part. We must send an oplock break to the client, and then process incoming messages until we get a close or oplock release. */ @@ -2923,7 +2932,7 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); from the sharemode. */ /* Paranoia.... */ fsp->granted_oplock = False; - global_oplocks_open--; + global_oplocks_open--; } /* Santity check - remove this later. JRA */ @@ -3599,8 +3608,11 @@ int find_free_file(void ) /* we start at 1 here for an obscure reason I can't now remember, but I think is important :-) */ for (i=1;i Date: Sat, 29 Nov 1997 13:29:13 +0000 Subject: use -1 not 0xffffffff in SIVALS() macros use the same process_exists() code on all systems (it's probably faster anyway) (This used to be commit 901b95aa77ac1ecc45823c23fb4e1d9da8dc8318) --- source3/smbd/ipc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c862ff3b38..50ad831eb3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2189,7 +2189,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, { SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ - SIVALS(p,usri11_password_age,0xffffffff); /* password age */ + SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ strcpy(p2, lp_logon_path()); p2 = skip_string(p2,1); @@ -2198,8 +2198,8 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, p2 = skip_string(p2,1); SIVAL(p,usri11_last_logon,0); /* last logon */ SIVAL(p,usri11_last_logoff,0); /* last logoff */ - SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */ - SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */ + SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ + SSVALS(p,usri11_num_logons,-1); /* num logons */ SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ strcpy(p2,"\\\\*"); p2 = skip_string(p2,1); @@ -2209,7 +2209,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, strcpy(p2,""); p2 = skip_string(p2,1); - SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */ + SIVALS(p,usri11_max_storage,-1); /* max storage */ SSVAL(p,usri11_units_per_week,168); /* units per week */ SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */ -- cgit From 15a6097263d4d5179b0eed43ede74fd65a83e090 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 30 Nov 1997 02:58:34 +0000 Subject: clientgen.c: Added cli_mv() (used in a recent torture test). reply.c: Changed reply_open_and_X to split out the oplock request bits from core and extended and if an oplock was granted only set the corresponding bit on reply. server.c: Added code to dynamically allocate i/o buffers in oplock_break (prevents recursion problems) , also made reset of sent_oplock_break explicit. Jeremy. (This used to be commit 16e55ee2b8be9a4210d8cf87691cdf42373759d2) --- source3/smbd/reply.c | 28 ++++++++++++++++++++++---- source3/smbd/server.c | 54 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 58 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec94ab0552..06b96b13d9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1257,7 +1257,11 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) int fnum = -1; int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); - BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); + /* Breakout the oplock request bits so we can set the + reply bits separately. */ + BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); + BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); + BOOL oplock_request = ex_oplock_request | core_oplock_request; #if 0 int open_flags = SVAL(inbuf,smb_vwv2); int smb_sattr = SVAL(inbuf,smb_vwv4); @@ -1324,13 +1328,29 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRDOS,ERRnoaccess)); } - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + /* If the caller set the extended oplock request bit + and we granted one (by whatever means) - set the + correct bit for extended oplock reply. + */ + + if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) { smb_action |= EXTENDED_OPLOCK_GRANTED; - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } - if(fsp->granted_oplock) { + if(ex_oplock_request && fsp->granted_oplock) { smb_action |= EXTENDED_OPLOCK_GRANTED; + } + + /* If the caller set the core oplock request bit + and we granted one (by whatever means) - set the + correct bit for core oplock reply. + */ + + if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) { + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + } + + if(core_oplock_request && fsp->granted_oplock) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 77c8fc319f..9ca4ab5b78 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1326,6 +1326,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fsp->print_file = Connections[cnum].printer; fsp->modified = False; fsp->granted_oplock = False; + fsp->sent_oplock_break = False; fsp->cnum = cnum; string_set(&fsp->name,dos_to_unix(fname,False)); fsp->wbmpx_ptr = NULL; @@ -1476,6 +1477,8 @@ void close_file(int fnum, BOOL normal_close) if(fs_p->granted_oplock == True) global_oplocks_open--; + fs_p->sent_oplock_break = False; + DEBUG(2,("%s %s closed file %s (numopen=%d)\n", timestring(),Connections[cnum].user,fs_p->name, Connections[cnum].num_files_open)); @@ -2773,22 +2776,6 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); - if(inbuf == NULL) - { - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(inbuf == NULL) { - DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); - return False; - } - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(outbuf == NULL) { - DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - free(inbuf); - inbuf = NULL; - return False; - } - } - /* We need to search the file open table for the entry containing this dev and inode, and ensure we have an oplock on it. */ @@ -2831,16 +2818,35 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum)); /* mark the oplock break as sent - we don't want to send twice! */ if (fsp->sent_oplock_break) { - DEBUG(0,("%s ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode)); - return True; - } + DEBUG(0,("%s oplock_break: ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode)); - fsp->sent_oplock_break = True; + /* We have to fail the open here as we cannot send another oplock break on this + file whilst we are awaiting a response from the client - neither can we + allow another open to succeed while we are waiting for the client. */ + return False; + } /* Now comes the horrid part. We must send an oplock break to the client, and then process incoming messages until we get a close or oplock release. + At this point we know we need a new inbuf/outbuf buffer pair. + We cannot use these staticaly as we may recurse into here due to + messages crossing on the wire. */ + if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + { + DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); + return False; + } + + if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + { + DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); + free(inbuf); + inbuf = NULL; + return False; + } + /* Prepare the SMBlockingX message. */ bzero(outbuf,smb_size); set_message(outbuf,8,0,True); @@ -2858,6 +2864,9 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum)); send_smb(Client, outbuf); + /* Remember we just sent an oplock break on this file. */ + fsp->sent_oplock_break = True; + /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; @@ -2909,6 +2918,10 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); } } + /* Free the buffers we've been using to recurse. */ + free(inbuf); + free(outbuf); + /* We need this in case a readraw crossed on the wire. */ if(global_oplock_break) global_oplock_break = False; @@ -2932,6 +2945,7 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); from the sharemode. */ /* Paranoia.... */ fsp->granted_oplock = False; + fsp->sent_oplock_break = False; global_oplocks_open--; } -- cgit From c4aaa6bc3f7e8bd823f7279c78583384e7617d93 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Dec 1997 19:00:18 +0000 Subject: asyncdns.c: Removed warning when compiling with -DSYNC_DNS. nameelect.c: Tidied up settings of work->ServerType when unbecoming things. nmbd.c: Fixed pidFile warning. server.c: Fixed pidFile warning. Jeremy. (This used to be commit 94d53dcac5d06e48be5cea9d54625da795f62d20) --- source3/smbd/server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9ca4ab5b78..d707699e33 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5043,7 +5043,9 @@ static void usage(char *pname) int port = SMB_PORT; int opt; extern char *optarg; - char pidFile[100] = { 0 }; + char pidFile[100]; + + *pidFile = '\0'; #ifdef NEED_AUTH_PARAMETERS set_auth_parameters(argc,argv); -- cgit From 7097597fd64353f023fae28124bae20e74fd18ed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Dec 1997 23:27:40 +0000 Subject: HPUX trusted systems need to use bigcrypt() not crypt() (This used to be commit 979eaf9e9c4dd58f1371597585d4cd64841febd0) --- source3/smbd/password.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 185fc68f5a..2176d5dafa 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -781,6 +781,10 @@ Hence we make a direct return to avoid a second chance!!! return(linux_bigcrypt(password,this_salt,this_crypted)); #endif +#ifdef HPUX_10_TRUSTED + return(bigcrypt(password,this_salt,this_crypted)); +#endif + #ifdef NO_CRYPT DEBUG(1,("Warning - no crypt available\n")); return(False); -- cgit From a53d7c11649e61b74b23bd6127283f2c7a3d63b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Dec 1997 23:29:57 +0000 Subject: changing the comment in find_new_file() to say why a base of 1 is used (This used to be commit 2b0f3fd14908411472be032ad09144cb71c55479) --- source3/smbd/server.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d707699e33..1ddb3204d3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3619,8 +3619,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de int find_free_file(void ) { int i; - /* we start at 1 here for an obscure reason I can't now remember, - but I think is important :-) */ + /* returning a file handle of 0 is a bad idea - so we start at 1 */ for (i=1;i Date: Wed, 3 Dec 1997 03:43:05 +0000 Subject: allow users to disable the NetWkstaUserLogon call in server level security by changing a setting in local.h or adding it to their Makefile. See comment in local.h (This used to be commit cc10fdf7583ec644850445ad96afd8b22b71e86f) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2176d5dafa..1c72f0cfa6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1589,6 +1589,7 @@ BOOL server_validate(char *user, char *domain, } +#if USE_NETWKSTAUSERLOGON if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); cli_tdis(&cli); @@ -1608,6 +1609,7 @@ BOOL server_validate(char *user, char *domain, cli_tdis(&cli); return False; } +#endif DEBUG(3,("password server %s accepted the password\n", cli.desthost)); -- cgit From 87df23458eac4e4a81673442db49467a65102b15 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Dec 1997 03:57:29 +0000 Subject: allow local_machine and remote_machine (%L and %m macros) to contain spaces (This used to be commit 93f0619e049d1598db0c3022aeccf33910b0550f) --- source3/smbd/reply.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 06b96b13d9..c903c7a1fd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -73,7 +73,6 @@ int reply_special(char *inbuf,char *outbuf) pstring name1,name2; extern fstring remote_machine; extern fstring local_machine; - char *p; int len; char name_type = 0; @@ -96,21 +95,18 @@ int reply_special(char *inbuf,char *outbuf) name1,name2)); fstrcpy(remote_machine,name2); + remote_machine[15] = 0; trim_string(remote_machine," "," "); - p = strchr(remote_machine,' '); strlower(remote_machine); - if (p) *p = 0; fstrcpy(local_machine,name1); - trim_string(local_machine," "," "); len = strlen(local_machine); if (len == 16) { name_type = local_machine[15]; local_machine[15] = 0; } - p = strchr(local_machine,' '); + trim_string(local_machine," "," "); strlower(local_machine); - if (p) *p = 0; if (name_type == 'R') { /* We are being asked for a pathworks session --- -- cgit From 164c9db4de87ea851a631f1c9d431e0a4525802e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Dec 1997 09:10:01 +0000 Subject: Fixed bug reported by Gert-Jan Vons with doing a dir /s into a unix directory ending in a ':'. Jeremy. (This used to be commit 273978b7d72955efcc0e0d9e87438b45f51c163d) --- source3/smbd/server.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1ddb3204d3..15258e02ea 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -452,8 +452,20 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) return(True); } +#if 0 + /* + * This code I believe is incorrect - and commenting it out + * is the correct fix for the bug mentioned below in the + * comment 'name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra)'. + * The incoming name can be mangled, and if we de-mangle it + * here it will not compare correctly against the filename (name2) + * read from the directory and then mangled by the name_map_mangle() + * call. We need to mangle both names or neither. + * (JRA). + */ if (mangled) check_mangled_stack(name); +#endif /* open the directory */ if (!(cur_dir = OpenDir(cnum, path, True))) -- cgit From 662eaecee6b36a0bbaf3524ac50aca47ec437923 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 14 Dec 1997 18:45:51 +0000 Subject: give out file handles differently on each new connection because of a common bug in MS clients where they try to reuse a file descriptor from an earlier smb connection. This code increases the chance that the errant client will get an error rather than causing corruption (This used to be commit 677d7a5a13728d8207dd2e7092c98d026d2d4f3c) --- source3/smbd/server.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 15258e02ea..bf66e1ca4b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3630,16 +3630,35 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de ****************************************************************************/ int find_free_file(void ) { - int i; - /* returning a file handle of 0 is a bad idea - so we start at 1 */ - for (i=1;i Date: Sat, 20 Dec 1997 05:25:37 +0000 Subject: trans2.c: Forced trans2_findfirst to behave as NT does in error returns. util.c: Applied fix from Branko Cibej where StrnCaseCmp tests one character too many. Jeremy. (This used to be commit cb771b2667070cff8d6cf86998a11ba2e4977690) --- source3/smbd/trans2.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0ca678b768..ce4a450050 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -646,29 +646,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid)); if (dptr_num < 0) - { - if(dptr_num == -2) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - -#if 0 - /* Ugly - NT specific hack - maybe not needed ? (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } -#endif - - return (UNIXERROR(ERRDOS,ERRbadpath)); - } - return(ERROR(ERRDOS,ERRbadpath)); - } + return(ERROR(ERRDOS,ERRbadfile)); /* convert the formatted masks */ { @@ -748,6 +726,14 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum dptr_num = -1; } + /* + * If there are no matching entries we must return ERRDOS/ERRbadfile - + * from observation of NT. + */ + + if(numentries == 0) + return(ERROR(ERRDOS,ERRbadfile)); + /* At this point pdata points to numentries directory entries. */ /* Set up the return parameter block */ -- cgit From d57c055478a34b9c4a0fc7ba90d20f510d0df797 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 20 Dec 1997 10:52:00 +0000 Subject: loadparm.c: Added fix for veto oplock files bug from Charles Hoch server.c, util.c: Added fix for oplock break requests blocking due to server being blocked in read call. Bug found by Charles Hoch . Jeremy. (This used to be commit 209f894fdbcfbf7a7952b6228342b86e088a9582) --- source3/smbd/server.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bf66e1ca4b..76a9fb272a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2595,6 +2595,8 @@ static void process_smb(char *inbuf, char *outbuf) if (msg_type == 0) show_msg(inbuf); + else if(msg_type == 0x85) + return; /* Keepalive packet. */ nread = construct_reply(inbuf,outbuf,nread,max_send); @@ -3142,6 +3144,13 @@ BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int tim process_local_message(oplock_sock, inbuf, bufsize); continue; } + + if(ret && (CVAL(inbuf,0) == 0x85)) + { + /* Keepalive packet. */ + got_smb = False; + } + } while(ret && !got_smb); -- cgit From d1e796d8577a666e5ef14f9bb462c080300dca3e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Dec 1997 07:15:59 +0000 Subject: Fixes to compile under OpenBSD from "Todd T. Fries" Jeremy. (This used to be commit 3c9292505914e2119fa7b1973c9fbbe1742262b2) --- source3/smbd/quotas.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 562d8fd5db..8333fa7cf2 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -546,7 +546,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #else -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__OpenBSD__) #include #include #elif AIX @@ -556,7 +556,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #define dqb_curfiles dqb_curinodes #define dqb_fhardlimit dqb_ihardlimit #define dqb_fsoftlimit dqb_isoftlimit -#else /* !__FreeBSD__ && !AIX */ +#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ #include #include #endif @@ -569,7 +569,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) uid_t euser_id; int r; struct dqblk D; -#if !defined(__FreeBSD__) && !defined(AIX) +#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) char dev_disk[256]; struct stat S; /* find the block device file */ @@ -591,7 +591,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) DEBUG(5,("Unable to reset uid to %d\n", user_id)); } #else /* USE_SETRES */ -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) { /* FreeBSD patches from Marty Moll */ uid_t user_id; @@ -615,17 +615,17 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); -#else /* !__FreeBSD__ && !AIX */ +#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); -#endif /* !__FreeBSD__ && !AIX */ +#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ #endif /* USE_SETRES */ /* Use softlimit to determine disk space, except when it has been exceeded */ -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) *bsize = DEV_BSIZE; -#else /* !__FreeBSD__ */ +#else /* !__FreeBSD__ && !__OpenBSD__ */ *bsize = 1024; -#endif /*!__FreeBSD__ */ +#endif /*!__FreeBSD__ && !__OpenBSD__ */ if (r) { @@ -641,7 +641,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) return(False); /* Use softlimit to determine disk space, except when it has been exceeded */ if ((D.dqb_curblocks>D.dqb_bsoftlimit) -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0)) #endif ) { -- cgit From d4979e7727ef94de469e66b74a9bee6f9742d4c0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Dec 1997 11:30:58 +0000 Subject: Fixed security bug when 'force user' and 'user only' are set. Reported by Brian McCauley . Jeremy. (This used to be commit 00067800a25d6f5fe11e833a01d5a7a1e76dcc11) --- source3/smbd/uid.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b36fa4df06..46a2de4f17 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -222,10 +222,13 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) snum = conn->service; + if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) + return False; + if (conn->force_user || lp_security() == SEC_SHARE || - !(vuser) || (vuser->guest) || - !check_user_ok(conn, vuser, snum)) + !(vuser) || (vuser->guest) + ) { uid = conn->uid; gid = conn->gid; -- cgit From 08bd3b8cc0ed557e8fa9769c053b456ba0fa457e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Dec 1997 13:21:36 +0000 Subject: Fixed nastly little bug where client was sending open_and_X call with smb_mode (smb_vwv[3]) of 0x20 == DENY_WRITE + read-only-open. and smb_ofun (smb_vwv[8]) of 0x11 == Create if not exist plus append on a read-only share. This was mapped into the strange unix flags of (O_RDONLY|O_CREAT) - essentially O_CREAT as O_RDONLY == 0. We were checking the unix flags directly against O_RDONLY instead of masking off the open mode flag bits before doing the comparison, so this open was being refused even though it was valid on a read-only share. Also ensured that the O_CREAT bit was masked out of the flags bit if the open was done on a read-only share (as doing a unix open( filename, O_RDONLY|O_CREAT, xxx) will create a zero length file if the user had permission to write into the directory - which should be denied on a read-only share. Thanks to Mark Peek @ Whistle for giving me this test case. Jeremy. (This used to be commit eae921ac632c8297836b85e909903da0602eac0e) --- source3/smbd/server.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 76a9fb272a..5e5f129959 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1151,6 +1151,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct struct stat statbuf; file_fd_struct *fd_ptr; files_struct *fsp = &Files[fnum]; + int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); fsp->open = False; fsp->fd_ptr = 0; @@ -1160,12 +1161,32 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct pstrcpy(fname,fname1); /* check permissions */ - if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer) - { + + /* + * This code was changed after seeing a client open request + * containing the open mode of (DENY_WRITE/read-only) with + * the 'create if not exist' bit set. The previous code + * would fail to open the file read only on a read-only share + * as it was checking the flags parameter directly against O_RDONLY, + * this was failing as the flags parameter was set to O_RDONLY|O_CREAT. + * JRA. + */ + + if (!CAN_WRITE(cnum) && !Connections[cnum].printer) { + /* It's a read-only share - fail if we wanted to write. */ + if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); check_for_pipe(fname); return; } + else if(flags & O_CREAT) { + /* We don't want to write - but we must make sure that O_CREAT + doesn't create the file if we have write access into the + directory. + */ + flags &= ~O_CREAT; + } + } /* this handles a bug in Win95 - it doesn't say to create the file when it should */ @@ -1203,8 +1224,6 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct */ if((fd_ptr = fd_get_already_open(sbuf))!= 0) { - int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); - /* File was already open. */ if((flags & O_CREAT) && (flags & O_EXCL)) { fd_ptr->ref_count--; -- cgit From aef2c5d69956c72f8b0bd2285283e8879ed8603d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Dec 1997 09:30:56 +0000 Subject: Added SIGUSR1/SIGUSR2 handling. Sending nmbd/smbd a SIGUSR1 will raise the debug level by one (capped at 10) sending a SIGUSR2 will lower it (lower limit at zero). Jeremy. (This used to be commit 6a3cb6f4b46129e4d799a24d34cdb9460ed8910f) --- source3/smbd/server.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5e5f129959..5eb360bbe7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5243,7 +5243,18 @@ static void usage(char *pname) #ifndef NO_SIGNAL_TEST signal(SIGHUP,SIGNAL_CAST sig_hup); #endif - + + /* Setup the signals that allow the debug log level + to by dynamically changed. */ + +#if defined(SIGUSR1) + signal( SIGUSR1, SIGNAL_CAST sig_usr1 ); +#endif /* SIGUSR1 */ + +#if defined(SIGUSR2) + signal( SIGUSR2, SIGNAL_CAST sig_usr2 ); +#endif /* SIGUSR2 */ + DEBUG(3,("%s loaded services\n",timestring())); if (!is_daemon && !is_a_socket(0)) -- cgit From 0a5073e985847acac11979771bdc04308a903107 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 1 Jan 1998 13:55:28 +0000 Subject: fixes to make_printerdef.c to generate a correct printers.def file changes to ipc.c to use new printers.def file (This used to be commit 52e275c4ccc1b7f0c2ef8d12d28065898a1c89c9) --- source3/smbd/ipc.c | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 50ad831eb3..af1c928ba2 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -594,7 +594,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, if (uLevel==52) { int i,ok=0; - pstring tok,driver,short_name; + pstring tok,driver,datafile, langmon, helpfile, datatype; char *p,*q; FILE *f; pstring fname; @@ -621,33 +621,58 @@ static void fill_printq_info(int cnum, int snum, int uLevel, fclose(f); - next_token(&p,short_name,":"); - next_token(&p,driver,":"); + next_token(&p,driver,":"); /* driver file name */ + next_token(&p,datafile,":"); /* data file name */ +/* + * for the next tokens - which may be empty - I have to check for empty + * tokens first because the next_token function will skip all empty + * token fields + */ + if (*p == ':') { + *helpfile = '\0'; + p++; + }else + next_token(&p,helpfile,":"); /* help file */ + if (*p == ':') { + *langmon = '\0'; + p++; + }else + next_token(&p,langmon,":"); /* language monitor */ + + next_token(&p,datatype,":"); /* default data type */ PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ + PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ if (ok) { - PACKS(desc,"z",driver); /* Driver Name */ - PACKS(desc,"z",short_name); /* short printer name */ + PACKS(desc,"z",driver); /* Driverfile Name */ + PACKS(desc,"z",datafile); /* Datafile name */ + PACKS(desc,"z",langmon); /* language monitor */ DEBUG(3,("Driver:%s:\n",driver)); - DEBUG(3,("short name:%s:\n",short_name)); + DEBUG(3,("Data File:%s:\n",datafile)); + DEBUG(3,("Language Monitor:%s:\n",langmon)); } else { PACKS(desc,"z",""); PACKS(desc,"z",""); + PACKS(desc,"z",""); } - PACKS(desc,"z",""); PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ - PACKS(desc,"z","EMF"); - PACKS(desc,"z",""); - if (ok) + if (ok) { + PACKS(desc,"z",datatype); /* default data type */ + PACKS(desc,"z",helpfile); /* helpfile name */ PACKS(desc,"z",driver); /* driver name */ - else + DEBUG(3,("Data Type:%s:\n",datatype)); + DEBUG(3,("Help File:%s:\n",helpfile)); + } + else { + PACKS(desc,"z","RAW"); PACKS(desc,"z",""); + PACKS(desc,"z",""); + } PACKI(desc,"N",count); /* number of files to copy */ for (i=0;i Date: Fri, 2 Jan 1998 13:33:20 +0000 Subject: fix printer driver rpc to prevent core dumps. (This used to be commit 0c82d139e3eb20a00016df30f33835ab5150ecea) --- source3/smbd/ipc.c | 138 ++++++++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 65 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index af1c928ba2..994e0b293b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -594,16 +594,17 @@ static void fill_printq_info(int cnum, int snum, int uLevel, if (uLevel==52) { int i,ok=0; - pstring tok,driver,datafile, langmon, helpfile, datatype; + pstring tok,driver,datafile,langmon,helpfile,datatype; char *p,*q; FILE *f; pstring fname; strcpy(fname,lp_driverfile()); - f=fopen(fname,"r"); if (!f) { - DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno))); + DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno))); + desc->errcode=NERR_notsupported; + return; } p=(char *)malloc(8192*sizeof(char)); @@ -613,80 +614,80 @@ static void fill_printq_info(int cnum, int snum, int uLevel, /* lookup the long printer driver name in the file description */ while (f && !feof(f) && !ok) { + p = q; /* reset string pointer */ fgets(p,8191,f); p[strlen(p)-1]='\0'; - next_token(&p,tok,":"); - if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1; + if (next_token(&p,tok,":") && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + ok=1; } - fclose(f); - next_token(&p,driver,":"); /* driver file name */ - next_token(&p,datafile,":"); /* data file name */ -/* - * for the next tokens - which may be empty - I have to check for empty - * tokens first because the next_token function will skip all empty - * token fields - */ - if (*p == ':') { - *helpfile = '\0'; - p++; - }else - next_token(&p,helpfile,":"); /* help file */ - if (*p == ':') { - *langmon = '\0'; - p++; - }else - next_token(&p,langmon,":"); /* language monitor */ - - next_token(&p,datatype,":"); /* default data type */ - - PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ + /* driver file name */ + if (ok && !next_token(&p,driver,":")) ok = 0; + /* data file name */ + if (ok && !next_token(&p,datafile,":")) ok = 0; + /* + * for the next tokens - which may be empty - I have to check for empty + * tokens first because the next_token function will skip all empty + * token fields + */ + if (ok) { + /* help file */ + if (*p == ':') { + *helpfile = '\0'; + p++; + } else if (!next_token(&p,helpfile,":")) ok = 0; + } - if (ok) - { + if (ok) { + /* language monitor */ + if (*p == ':') { + *langmon = '\0'; + p++; + } else if (!next_token(&p,langmon,":")) ok = 0; + } + + /* default data type */ + if (ok && !next_token(&p,datatype,":")) ok = 0; + + if (ok) { + PACKI(desc,"W",0x0400); /* don't know */ + PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ PACKS(desc,"z",driver); /* Driverfile Name */ PACKS(desc,"z",datafile); /* Datafile name */ PACKS(desc,"z",langmon); /* language monitor */ + PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ + PACKS(desc,"z",datatype); /* default data type */ + PACKS(desc,"z",helpfile); /* helpfile name */ + PACKS(desc,"z",driver); /* driver name */ DEBUG(3,("Driver:%s:\n",driver)); DEBUG(3,("Data File:%s:\n",datafile)); DEBUG(3,("Language Monitor:%s:\n",langmon)); - } - else - { - PACKS(desc,"z",""); - PACKS(desc,"z",""); - PACKS(desc,"z",""); - } - - PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ - if (ok) { - PACKS(desc,"z",datatype); /* default data type */ - PACKS(desc,"z",helpfile); /* helpfile name */ - PACKS(desc,"z",driver); /* driver name */ DEBUG(3,("Data Type:%s:\n",datatype)); DEBUG(3,("Help File:%s:\n",helpfile)); - } - else { - PACKS(desc,"z","RAW"); - PACKS(desc,"z",""); - PACKS(desc,"z",""); - } - PACKI(desc,"N",count); /* number of files to copy */ - for (i=0;i gave %d entries\n", + SERVICE(snum),count)); + } else { + DEBUG(3,("fill_printq_info: Can't supply driver files\n")); + desc->errcode=NERR_notsupported; } free(q); } - - DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count)); } -/* This function returns the number of file for a given driver */ +/* This function returns the number of files for a given driver */ int get_printerdrivernumber(int snum) { int i=0,ok=0; @@ -700,7 +701,7 @@ int get_printerdrivernumber(int snum) DEBUG(4,("In get_printerdrivernumber: %s\n",fname)); f=fopen(fname,"r"); if (!f) { - DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno))); + DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno))); return(0); } @@ -710,20 +711,27 @@ int get_printerdrivernumber(int snum) /* lookup the long printer driver name in the file description */ while (!feof(f) && !ok) { + p = q; /* reset string pointer */ fgets(p,8191,f); - next_token(&p,tok,":"); - if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1; + if (next_token(&p,tok,":") && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + ok=1; } + fclose(f); if (ok) { - /* skip 2 fields */ - next_token(&p,tok,":"); /* short name */ - next_token(&p,tok,":"); /* driver name */ + /* skip 5 fields */ + i = 5; + while (*p && i) { + if (*p++ == ':') i--; + } + if (!*p || i) + return(0); + /* count the number of files */ while (next_token(&p,tok,",")) i++; } - fclose(f); free(q); return(i); -- cgit From 6e2acebc778ee8507b1631968c78459e30a4163e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Jan 1998 08:29:15 +0000 Subject: Ensure that if we are in share mode security that the smb_uid field is invalid. Jeremy. (This used to be commit a689ca1ce5c3ffdc753dce329f51a8ede0592f29) --- source3/smbd/server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5eb360bbe7..93d2a9756d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4670,7 +4670,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { int cnum = SVAL(inbuf,smb_tid); int flags = smb_messages[match].flags; - uint16 session_tag = SVAL(inbuf,smb_uid); + /* In share mode security we must ignore the vuid. */ + uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); /* does this protocol need to be run as root? */ if (!(flags & AS_USER)) -- cgit From 10f844c988cf426d2309d5bd73bedec182dd03d3 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Thu, 8 Jan 1998 03:04:55 +0000 Subject: Fixed an apparent typo: 2551c2551 < #endif /NO_FORK_DEBUG */ --- > #endif /* NO_FORK_DEBUG */ Chris -)----- (This used to be commit 954fc7e0d01443f4bfc7157f2dcba2187f6700ec) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 93d2a9756d..29a0d462f3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2548,7 +2548,7 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); return True; } close(Client); /* The parent doesn't need this socket */ -#endif /NO_FORK_DEBUG */ +#endif /* NO_FORK_DEBUG */ } /* end for num */ } /* end while 1 */ } /* end if is_daemon */ -- cgit From 5c6525003c4070f4fdbb4513601bee7abc6d8bf5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Jan 1998 08:11:15 +0000 Subject: ipc.c: Fixed problem where we were not returning 'buffer too small' when NT sends up a mdrcnt of zero. Jeremy. (This used to be commit 2a75519b8592948b2f35ecca040bd3f88bf89be5) --- source3/smbd/ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 994e0b293b..ee2aec8c22 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -283,8 +283,8 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount) i = n = 0; p->errcode = NERR_BufTooSmall; } - - p->errcode = NERR_Success; + else + p->errcode = NERR_Success; p->buflen = i; n -= i; p->stringbuf = p->base + i; -- cgit From 0e7be4859732283602732ac6a2110712221dc442 Mon Sep 17 00:00:00 2001 From: John Terpstra Date: Sat, 10 Jan 1998 11:42:29 +0000 Subject: Following discussions with Cristian Gafton (Red Hat) we have decided to make PAM silent about it's actions. This reduced error logging for EVERY password validation request. Refer to password.c PAM section for further info. Fiels Affected: password.c (This used to be commit 7a1a8042dd005e26e610a16eaaa693f119b874c7) --- source3/smbd/password.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1c72f0cfa6..c2b916a0af 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -442,13 +442,19 @@ static BOOL pam_auth(char *this_user,char *password) PAM_username = this_user; pam_error = pam_start("samba", this_user, &PAM_conversation, &pamh); PAM_BAIL; - pam_error = pam_authenticate(pamh, 0); +/* Setting PAM_SILENT stops generation of error messages to syslog + * to enable debugging on Red Hat Linux set: + * /etc/pam.d/samba: + * auth required /lib/security/pam_pwdb.so nullok shadow audit + * _OR_ change PAM_SILENT to 0 to force detailed reporting (logging) + */ + pam_error = pam_authenticate(pamh, PAM_SILENT); PAM_BAIL; /* It is not clear to me that account management is the right thing * to do, but it is not clear that it isn't, either. This can be * removed if no account management should be done. Alternately, * put a pam_allow.so entry in /etc/pam.conf for account handling. */ - pam_error = pam_acct_mgmt(pamh, 0); + pam_error = pam_acct_mgmt(pamh, PAM_SILENT); PAM_BAIL; pam_end(pamh, PAM_SUCCESS); /* If this point is reached, the user has been authenticated. */ -- cgit From b13a8bdb40facf632c98f2087e48837c775be400 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Jan 1998 23:28:39 +0000 Subject: *** empty log message *** (This used to be commit a307b5155594a12ca978190cc9dec52e203e0fd3) --- source3/smbd/server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 29a0d462f3..fb03577435 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2799,8 +2799,8 @@ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { extern int Client; - static char *inbuf = NULL; - static char *outbuf = NULL; + char *inbuf = NULL; + char *outbuf = NULL; files_struct *fsp = NULL; int fnum; time_t start_time; @@ -5124,7 +5124,7 @@ static void usage(char *pname) charset_initialise(); - /* make absolutely sure we run as root - to handle cases whre people + /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ #ifdef USE_SETRES setresuid(0,0,0); -- cgit From 385e40c5dc079e04ef89fb7c158a01c1d1a77c58 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Jan 1998 23:59:11 +0000 Subject: *** empty log message *** (This used to be commit 440535a0c755cfb55ced8fe537e2251d6a30714f) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index fb03577435..a83e865f9e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3671,9 +3671,13 @@ int find_free_file(void ) if (first_file == 0) first_file = 1; } + if (first_file == MAX_OPEN_FILES) + first_file = 0; + for (i=first_file;i Date: Mon, 12 Jan 1998 00:20:10 +0000 Subject: *** empty log message *** (This used to be commit 7b031586ca33a381eb0e27f3557f43c2550df5f8) --- source3/smbd/reply.c | 26 +++++++++++++++++++++----- source3/smbd/server.c | 16 ++++++++++------ source3/smbd/trans2.c | 2 ++ 3 files changed, 33 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c903c7a1fd..7194f3b144 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1191,6 +1191,7 @@ int reply_open(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1208,6 +1209,7 @@ int reply_open(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1291,6 +1293,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1308,6 +1311,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1437,6 +1441,7 @@ int reply_mknew(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1464,6 +1469,7 @@ int reply_mknew(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1519,6 +1525,7 @@ int reply_ctemp(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1538,6 +1545,7 @@ int reply_ctemp(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + Files[fnum].reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2572,15 +2580,19 @@ int reply_printopen(char *inbuf,char *outbuf) strcpy(fname2,(char *)mktemp(fname)); - if (!check_name(fname2,cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); + if (!check_name(fname2,cnum)) { + Files[fnum].reserved = False; + return(ERROR(ERRDOS,ERRnoaccess)); + } /* Open for exclusive use, write only. */ open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), 0, NULL, NULL); - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if (!Files[fnum].open) { + Files[fnum].reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } /* force it to be a print file */ Files[fnum].print_file = True; @@ -3250,7 +3262,10 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, open_file_shared(fnum1,cnum,src,(DENY_NONE<<4), 1,0,0,&Access,&action); - if (!Files[fnum1].open) return(False); + if (!Files[fnum1].open) { + Files[fnum1].reserved = False; + return(False); + } if (!target_is_directory && count) ofun = 1; @@ -3265,6 +3280,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, if (!Files[fnum2].open) { close_file(fnum1,False); + Files[fnum2].reserved = False; return(False); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a83e865f9e..3c40e9800f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1466,6 +1466,8 @@ void close_file(int fnum, BOOL normal_close) uint32 inode = fs_p->fd_ptr->inode; int token; + Files[fnum].reserved = False; + #if USE_READ_PREDICTION invalidate_read_prediction(fs_p->fd_ptr->fd); #endif @@ -3671,21 +3673,23 @@ int find_free_file(void ) if (first_file == 0) first_file = 1; } - if (first_file == MAX_OPEN_FILES) - first_file = 0; + if (first_file >= MAX_OPEN_FILES) + first_file = 1; for (i=first_file;i Date: Thu, 15 Jan 1998 04:57:54 +0000 Subject: reply.c: Added timestamp to attack warning. server.c: Fixed security=share problem where the vuid was still being looked at. Jeremy. (This used to be commit ab8d615fe2004c3ca93dd2978ba988ea89d7fd74) --- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7194f3b144..b1caee10a2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -55,7 +55,7 @@ report a possible attack via the password buffer overflow bug ****************************************************************************/ static void overflow_attack(int len) { - DEBUG(0,("ERROR: Invalid password length %d\n", len)); + DEBUG(0,("%s: ERROR: Invalid password length %d\n", timestring(), len)); DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); DEBUG(0,("Attack was from IP=%s\n", client_addr())); exit_server("possible attack"); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3c40e9800f..aaf446bdf5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4681,6 +4681,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize int flags = smb_messages[match].flags; /* In share mode security we must ignore the vuid. */ uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); + /* Ensure this value is replaced in the incoming packet. */ + SSVAL(inbuf,smb_uid,session_tag); /* does this protocol need to be run as root? */ if (!(flags & AS_USER)) -- cgit From 4f9674d1c85f2e7293874477ae0da15fee1538c7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jan 1998 08:58:00 +0000 Subject: reply.c: server.c: Test fix for NT worstation SMBmv oplock bug. smbdes.c: Addition of 'forward' parameter in preparation of allowing password change. Jeremy. (This used to be commit 0b0b1fb122a52e67a8fdc77d013ad0b3bbb90d19) --- source3/smbd/reply.c | 4 ++-- source3/smbd/server.c | 44 ++++++++++++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b1caee10a2..847f6e68f2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1586,7 +1586,7 @@ static BOOL can_delete(char *fname,int cnum,int dirtype) } if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return(False); - if (!check_file_sharing(cnum,fname)) return(False); + if (!check_file_sharing(cnum,fname,False)) return(False); return(True); } @@ -3039,7 +3039,7 @@ static BOOL can_rename(char *fname,int cnum) if (!CAN_WRITE(cnum)) return(False); if (sys_lstat(fname,&sbuf) != 0) return(False); - if (!check_file_sharing(cnum,fname)) return(False); + if (!check_file_sharing(cnum,fname,True)) return(False); return(True); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index aaf446bdf5..bf635fc27a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1574,7 +1574,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if the share mode on a file allows it to be deleted or unlinked return True if sharing doesn't prevent the operation ********************************************************************/ -BOOL check_file_sharing(int cnum,char *fname) +BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) { int i; int ret = False; @@ -1621,21 +1621,41 @@ BOOL check_file_sharing(int cnum,char *fname) if(share_entry->op_type & BATCH_OPLOCK) { - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ + /* + * It appears that the NT redirector may have a bug, in that + * it tries to do an SMBmv on a file that it has open with a + * batch oplock, and then fails to respond to the oplock break + * request. This only seems to occur when the client is doing an + * SMBmv to the smbd it is using - thus we try and detect this + * condition by checking if the file being moved is open and oplocked by + * this smbd process, and then not sending the oplock break in this + * special case. If the file was open with a deny mode that + * prevents the move the SMBmv will fail anyway with a share + * violation error. JRA. + */ + if(rename_op && (share_entry->pid == pid)) + { + DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ +batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); + } + else + { + DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ + /* Oplock break.... */ + unlock_share_entry(cnum, dev, inode, token); + if(request_oplock_break(share_entry, dev, inode) == False) + { + free((char *)old_shares); + DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - return False; + return False; + } + lock_share_entry(cnum, dev, inode, &token); + broke_oplock = True; + break; } - lock_share_entry(cnum, dev, inode, &token); - broke_oplock = True; - break; } /* someone else has a share lock on it, check to see -- cgit From 1ea8ceac458501719a055700902d456304c4ee0a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 Jan 1998 07:08:21 +0000 Subject: charcnv.c: Added codepage 866 support onto the file system. Patch from Max Khon . chgpasswd.c: Allow old RAP change password to work with encrypted passwords. Samba can now allow Windows 95/NT clients to securely change the Lanman password ! (But not the NT hash - that gets lost). ipc.c: smbdes.c: smbpass.c: Support for the above. server.c: #ifdef'ed out fix for NT redirector bug. util.c: Fix NIS bug with server name. Jeremy. (This used to be commit cd9fad92d0316e5a0007ba3c5668906dc2f011f1) --- source3/smbd/chgpasswd.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/ipc.c | 30 ++++++++++++++--- source3/smbd/server.c | 7 ++++ 3 files changed, 116 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 17401410ce..1502cd1219 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -398,3 +398,86 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass) return(False); } #endif + +/*********************************************************** + Code to check the lanman hashed password. +************************************************************/ + +BOOL check_lanman_password(char *user, unsigned char *pass1, + unsigned char *pass2, struct smb_passwd **psmbpw) +{ + unsigned char unenc_new_pw[16]; + unsigned char unenc_old_pw[16]; + struct smb_passwd *smbpw; + + *psmbpw = NULL; + + become_root(0); + smbpw = get_smbpwd_entry(user, 0); + unbecome_root(0); + + if(smbpw == NULL) + { + DEBUG(0,("check_lanman_password: get_smbpwd_entry returned NULL\n")); + return False; + } + + if(smbpw->smb_passwd == NULL) + { + DEBUG(0,("check_lanman_password: no lanman password !\n")); + return False; + } + + /* Get the new lanman hash. */ + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + + /* Use this to get the old lanman hash. */ + D_P16(unenc_new_pw, pass1, unenc_old_pw); + + /* Check that the two old passwords match. */ + if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + { + DEBUG(0,("check_lanman_password: old password doens't match.\n")); + return False; + } + + *psmbpw = smbpw; + return True; +} + +/*********************************************************** + Code to change the lanman hashed password. + It nulls out the NT hashed password as it will + no longer be valid. +************************************************************/ + +BOOL change_lanman_password(struct smb_passwd *smbpw, char *pass1, char *pass2) +{ + char unenc_new_pw[16]; + BOOL ret; + + if(smbpw == NULL) + { + DEBUG(0,("change_lanman_password: get_smbpwd_entry returned NULL\n")); + return False; + } + + if(smbpw->smb_passwd == NULL) + { + DEBUG(0,("change_lanman_password: no lanman password !\n")); + return False; + } + + /* Get the new lanman hash. */ + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + + smbpw->smb_passwd = unenc_new_pw; + smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ + + /* Now write it into the file. */ + become_root(0); + ret = mod_smbpwd_entry(smbpw); + unbecome_root(0); + + return ret; +} diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ee2aec8c22..e3db823a9d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1141,7 +1141,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, uint32 servertype = IVAL(p,4); char *p2; int data_len, fixed_len, string_len; - int f_len, s_len; + int f_len = 0, s_len = 0; struct srv_info_struct *servers=NULL; int counted=0,total=0; int i,missed; @@ -1421,7 +1421,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, int total=0,counted=0; int i; int data_len, fixed_len, string_len; - int f_len, s_len; + int f_len = 0, s_len = 0; if (!prefix_ok(str1,"WrLeh")) return False; if (!check_share_info(uLevel,str2)) return False; @@ -1532,8 +1532,8 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, p = skip_string(p,1); - StrnCpy(pass1,p,16); - StrnCpy(pass2,p+16,16); + memcpy(pass1,p,16); + memcpy(pass2,p+16,16); *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); @@ -1545,12 +1545,34 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, DEBUG(3,("Set password for <%s>\n",user)); + /* + * Attempt the plaintext password change first. + * Older versions of Windows seem to do this. + */ + if (password_ok(user,pass1,strlen(pass1),NULL) && chgpasswd(user,pass1,pass2)) { SSVAL(*rparam,0,NERR_Success); } + /* + * If the plaintext change failed, attempt + * the encrypted. NT will generate this + * after trying the samr method. + */ + + if(SVAL(*rparam,0) != NERR_Success) + { + struct smb_passwd *smbpw = NULL; + + if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &smbpw) && + change_lanman_password(smbpw,(unsigned char *)pass1,(unsigned char *)pass2)) + { + SSVAL(*rparam,0,NERR_Success); + } + } + bzero(pass1,sizeof(fstring)); bzero(pass2,sizeof(fstring)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bf635fc27a..751039070f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1637,6 +1637,13 @@ BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) { DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); +#if 0 + /* + * This next line is a test that allows the deny-mode + * processing to be skipped. JRA. + */ + continue; +#endif } else { -- cgit From 118213c059501d384be9a6dcaf02d13a681bedc3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Jan 1998 09:25:05 +0000 Subject: printing.c: Bug fix for lpng reporting. server.c: Large fix for oplock deadlock bug. util.c: Fix for oplock deadlock bug. Jeremy. (This used to be commit 4cae830ab3a942b2f2868173a492d02f6332651d) --- source3/smbd/server.c | 106 +++++++++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 751039070f..b5408a2903 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2963,6 +2963,16 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); shutdown_server = True; break; } + + /* + * There are certain SMB requests that we shouldn't allow + * to recurse. opens, renames and deletes are the obvious + * ones. This is handled in the switch_message() function. + * If global_oplock_break is set they will push the packet onto + * the pending smb queue and return -1 (no reply). + * JRA. + */ + process_smb(inbuf, outbuf); /* @@ -3036,6 +3046,8 @@ BOOL request_oplock_break(share_mode_entry *share_entry, char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; int pid = getpid(); + time_t start_time; + int time_left; if(pid == share_entry->pid) { @@ -3089,7 +3101,10 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", * While we get messages that aren't ours, loop. */ - while(1) + start_time = time(NULL); + time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR; + + while(time_left >= 0) { char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; int32 reply_msg_len; @@ -3097,7 +3112,7 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", char *reply_msg_start; if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), - (OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) * 1000) == False) + time_left ? time_left * 1000 : 1) == False) { if(smb_read_error == READ_TIMEOUT) { @@ -3120,23 +3135,6 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, shar return False; } - /* - * If the response we got was not an answer to our message, but - * was a completely different request, push it onto the pending - * udp message stack so that we can deal with it in the main loop. - * It may be another oplock break request to us. - */ - - /* - * Local note from JRA. There exists the possibility of a denial - * of service attack here by allowing non-root processes running - * on a local machine sending many of these pending messages to - * a smbd port. Currently I'm not sure how to restrict the messages - * I will queue (although I could add a limit to the queue) to - * those received by root processes only. There should be a - * way to make this bulletproof.... - */ - reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET); reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET); @@ -3150,21 +3148,37 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, shar continue; } - if(((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) == 0) || - (reply_from_port != share_entry->op_port) || + /* + * Test to see if this is the reply we are awaiting. + */ + + if((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) && + (reply_from_port == share_entry->op_port) && (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], &op_break_msg[OPLOCK_BREAK_PID_OFFSET], - OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0)) + OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) { - DEBUG(3,("%s request_oplock_break: received other message whilst awaiting \ -oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", - timestring(), share_entry->pid, share_entry->op_port, dev, inode)); - if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) - return False; - continue; + /* + * This is the reply we've been waiting for. + */ + break; } + else + { + /* + * This is another message - probably a break request. + * Process it to prevent potential deadlock. + * Note that the code in switch_message() prevents + * us from recursing into here as any SMB requests + * we might process that would cause another oplock + * break request to be made will be queued. + * JRA. + */ - break; + process_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply)); + } + + time_left -= (time(NULL) - start_time); } DEBUG(3,("%s request_oplock_break: broke oplock.\n", timestring())); @@ -4522,7 +4536,7 @@ force write permissions on print services. #define TIME_INIT (1<<2) #define CAN_IPC (1<<3) #define AS_GUEST (1<<5) - +#define QUEUE_IN_OPLOCK (1<<6) /* define a list of possible SMB messages and their corresponding @@ -4556,20 +4570,20 @@ struct smb_message_struct {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, {SMBsearch,"SMBsearch",reply_search,AS_USER}, - {SMBopen,"SMBopen",reply_open,AS_USER}, + {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK }, /* note that SMBmknew and SMBcreate are deliberately overloaded */ {SMBcreate,"SMBcreate",reply_mknew,AS_USER}, {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, - {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE}, + {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, {SMBread,"SMBread",reply_read,AS_USER}, {SMBwrite,"SMBwrite",reply_write,AS_USER}, {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER}, - {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE}, + {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, /* this is a Pathworks specific call, allowing the changing of the root path */ @@ -4577,8 +4591,8 @@ struct smb_message_struct {SMBlseek,"SMBlseek",reply_lseek,AS_USER}, {SMBflush,"SMBflush",reply_flush,AS_USER}, - {SMBctemp,"SMBctemp",reply_ctemp,AS_USER}, - {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER}, + {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, + {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK }, {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER}, {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST}, {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER}, @@ -4605,10 +4619,10 @@ struct smb_message_struct {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC}, {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC}, {SMBioctls,"SMBioctls",NULL,AS_USER}, - {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE}, - {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE}, + {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, + {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, - {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC}, + {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER}, {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER}, {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, @@ -4620,7 +4634,7 @@ struct smb_message_struct /* LANMAN2.0 PROTOCOL FOLLOWS */ {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER}, + {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK }, {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, /* messaging routines */ @@ -4702,6 +4716,20 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize else { DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid)); + + if(global_oplock_break && (smb_messages[match].flags & QUEUE_IN_OPLOCK)) + { + /* + * Queue this message as we are the process of an oplock break. + */ + + DEBUG(2,("%s: switch_message: queueing message due to being in oplock break state.\n", + timestring() )); + + push_smb_message( inbuf, size); + return -1; + } + if (smb_messages[match].fn) { int cnum = SVAL(inbuf,smb_tid); -- cgit From 55f400bd84f26027f5ec9b7fa06b22895de7557c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Jan 1998 13:27:43 +0000 Subject: This is *not* a big change (although it looks like one). This is merely updating the Copyright statements from 1997 to 1998. It's a once a year thing :-). NO OTHER CHANGES WERE MADE. Jeremy. (This used to be commit b9c16977231efb274e08856f7f3f4408dad6d96c) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/dir.c | 2 +- source3/smbd/ipc.c | 4 ++-- source3/smbd/mangle.c | 2 +- source3/smbd/message.c | 2 +- source3/smbd/password.c | 2 +- source3/smbd/pipes.c | 6 +++--- source3/smbd/predict.c | 2 +- source3/smbd/quotas.c | 2 +- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/smbrun.c | 2 +- source3/smbd/trans2.c | 2 +- source3/smbd/uid.c | 2 +- source3/smbd/vt_mode.c | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 1502cd1219..b516ec8ac8 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Samba utility functions - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index c12305499a..d751653263 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Directory handling routines - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e3db823a9d..048dab8b3e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2,10 +2,10 @@ Unix SMB/Netbios implementation. Version 1.9. Inter-process communication and named pipe handling - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 SMB Version handling - Copyright (C) John H Terpstra 1995-1997 + Copyright (C) John H Terpstra 1995-1998 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 diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index bf26475715..7b6a563511 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Name mangling - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 64253932ab..8c3f6f6630 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. SMB messaging - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c2b916a0af..567b8f54f2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Password and authentication handling - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index e2f704e6af..b5f9700f33 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -2,9 +2,9 @@ Unix SMB/Netbios implementation. Version 1.9. Pipe SMB reply routines - Copyright (C) Andrew Tridgell 1992-1997, - Copyright (C) Luke Kenneth Casson Leighton 1996-1997. - Copyright (C) Paul Ashton 1997. + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Luke Kenneth Casson Leighton 1996-1998 + Copyright (C) Paul Ashton 1997-1998. 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 diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index f5f0a2102e..862ba97f7e 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. file read prediction routines - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 8333fa7cf2..0a366e5ee6 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -3,7 +3,7 @@ Unix SMB/Netbios implementation. Version 1.9. support for quotas - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 847f6e68f2..746c79db21 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Main SMB reply routines - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b5408a2903..447a9a5469 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Main SMB server routines - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/smbrun.c b/source3/smbd/smbrun.c index 42ce7f60ad..1b1802c95f 100644 --- a/source3/smbd/smbrun.c +++ b/source3/smbd/smbrun.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. external program running routine - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b52169a66b..56843e0423 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-1997 + Copyright (C) Jeremy Allison 1994-1998 Extensively modified by Andrew Tridgell, 1995 diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 46a2de4f17..176f6ca240 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. uid/user handling - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1998 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 diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c index 07558274a5..dcb6ce831d 100644 --- a/source3/smbd/vt_mode.c +++ b/source3/smbd/vt_mode.c @@ -2,7 +2,7 @@ /* support vtp-sessions -written by Christian A. Lademann +(C) written by Christian A. Lademann */ /* -- cgit From 66c668a6d308662dd02ea359551fb6d3867d12ca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Jan 1998 05:22:19 +0000 Subject: nmbd.c, server.c: Added #ifndef MEM_MAN around code that sets the SIGUSR1 and SIGUSR2 signals. This allows the MEM_MAN code to be compiled in and the memory debug feature to be used with SIGUSR1. Jeremy. (This used to be commit 43ef7e3cb5bb971ff6ddf8230b08995e55b7c6e1) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 447a9a5469..01d379ebb3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5314,6 +5314,10 @@ static void usage(char *pname) /* Setup the signals that allow the debug log level to by dynamically changed. */ + /* If we are using the malloc debug code we can't use + SIGUSR1 and SIGUSR2 to do debug level changes. */ + +#ifndef MEM_MAN #if defined(SIGUSR1) signal( SIGUSR1, SIGNAL_CAST sig_usr1 ); #endif /* SIGUSR1 */ @@ -5321,6 +5325,7 @@ static void usage(char *pname) #if defined(SIGUSR2) signal( SIGUSR2, SIGNAL_CAST sig_usr2 ); #endif /* SIGUSR2 */ +#endif /* MEM_MAN */ DEBUG(3,("%s loaded services\n",timestring())); -- cgit From a215c98602c0849819a50de6b13f8c41824ef08a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Jan 1998 13:52:17 +0000 Subject: Changed code that truncates salt after 2 characters so that it becomes HPUX specific. This fixes a bug with FreeBSD md5 crypt implementation that needs all of the password characters. It seems better to make this an HPUX specific thing. Jeremy. (This used to be commit 91a2b746d3fac261d4be3bd7afa3d5bb601b3d27) --- source3/smbd/password.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 567b8f54f2..0f8705d4be 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1023,7 +1023,10 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) /* extract relevant info */ strcpy(this_user,pass->pw_name); strcpy(this_salt,pass->pw_passwd); +#ifdef HPUX + /* The crypt on HPUX won't work with more than 2 salt characters. */ this_salt[2] = 0; +#endif /* HPUX */ strcpy(this_crypted,pass->pw_passwd); if (!*this_crypted) { -- cgit From 4f650dab6f867bda2beeeda71b2b97e75834853f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 24 Jan 1998 08:49:21 +0000 Subject: Added get_create_time() function to time.c. This gets the minimum timestamp associated with a file. reply.c and trans2.c then return this as the create time. Designed to fix problems with VC++ and others. Jeremy. (This used to be commit e3d5f6196d6eff707c78941696a368216e2a7410) --- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 746c79db21..4703dea475 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3916,7 +3916,7 @@ int reply_getattrE(char *inbuf,char *outbuf) /* Convert the times into dos times. Set create date to be last modify date as UNIX doesn't save this */ - put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime); + put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf)); put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 56843e0423..eb8356cc53 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -362,7 +362,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l size = sbuf.st_size; mdate = sbuf.st_mtime; adate = sbuf.st_atime; - cdate = sbuf.st_ctime; + cdate = get_create_time(&sbuf); if(mode & aDIR) size = 0; @@ -1114,7 +1114,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */ + put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf)); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */ put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,size); @@ -1125,7 +1125,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; - put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */ + put_dos_date2(pdata,0,get_create_time(&sbuf)); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,size); @@ -1143,14 +1143,17 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_BASIC_INFO: data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ - put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */ + put_long_date(pdata,get_create_time(&sbuf)); put_long_date(pdata+8,sbuf.st_atime); /* access time */ put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); DEBUG(5,("SMB_QFBI - ")); - DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime))); + { + time_t create_time = get_create_time(&sbuf); + DEBUG(5,("create: %s ", ctime(&create_time))); + } DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); @@ -1204,7 +1207,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, break; case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */ + put_long_date(pdata,get_create_time(&sbuf)); put_long_date(pdata+8,sbuf.st_atime); /* access time */ put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ -- cgit From db5e1e646c9616db5a3f5fe224153176cd556c01 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 25 Jan 1998 15:36:11 +0000 Subject: always align both the parameter and data bytes on a 4 byte boundary in trans2 responses. I'm not at all convinced this was causing problems, because observations of Win95 show that it produces totally non-aligned paramater bytes and 2 byte aligned data bytes. We were previously always producing 2 byte aligned data and parameter bytes so we already had "better" alignment than Win95. lets hope no clients rely on servers producing unaligned data or parameters! (This used to be commit 68ad11a7352824fea46ecbe67a3827a7ba3bcbab) --- source3/smbd/trans2.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index eb8356cc53..139ded57b2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -55,7 +55,8 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, char *pp = params; char *pd = pdata; int params_sent_thistime, data_sent_thistime, total_sent_thistime; - int alignment_offset = 1; + int alignment_offset = 3; + int data_alignment_offset = 0; /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */ @@ -69,18 +70,28 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, return 0; } + /* when sending params and data ensure that both are nicely aligned */ + if ((params_to_send % 4) != 0) + data_alignment_offset = 4 - (params_to_send % 4); + /* Space is bufsize minus Netbios over TCP header minus SMB header */ - /* The alignment_offset is to align the param and data bytes on an even byte + /* The alignment_offset is to align the param bytes on an even byte boundary. NT 4.0 Beta needs this to work correctly. */ - useable_space = bufsize - ((smb_buf(outbuf)+alignment_offset) - outbuf); + useable_space = bufsize - ((smb_buf(outbuf)+ + alignment_offset+data_alignment_offset) - + outbuf); + /* useable_space can never be more than max_send minus the alignment offset. */ - useable_space = MIN(useable_space, max_send - alignment_offset); + useable_space = MIN(useable_space, + max_send - (alignment_offset+data_alignment_offset)); + - while( params_to_send || data_to_send) + while (params_to_send || data_to_send) { /* Calculate whether we will totally or partially fill this packet */ - total_sent_thistime = params_to_send + data_to_send + alignment_offset; + total_sent_thistime = params_to_send + data_to_send + + alignment_offset + data_alignment_offset; /* We can never send more than useable_space */ total_sent_thistime = MIN(total_sent_thistime, useable_space); @@ -121,7 +132,8 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, /* The offset of the data bytes is the offset of the parameter bytes plus the number of parameters being sent this time */ SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - - smb_base(outbuf)) + params_sent_thistime); + smb_base(outbuf)) + + params_sent_thistime + data_alignment_offset); SSVAL(outbuf,smb_drdisp, pd - pdata); } @@ -130,7 +142,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); /* Copy in the data bytes */ if(data_sent_thistime) - memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime,pd,data_sent_thistime); + memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+data_alignment_offset,pd,data_sent_thistime); DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", params_sent_thistime, data_sent_thistime, useable_space)); -- cgit From e525e29487dcc5e3e5a504dfae5d83def25f58e6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Jan 1998 13:11:58 +0000 Subject: Fix from Charles Hoch (hoch@hpl.hp.com). Whne there is no data to send, setting the data alignment to a 4 byte boundary causes a few extra bytes to be sent. This seems to cause the NT redirector to *sometimes* fail. Jeremy. (This used to be commit f6ee3263dac960772024bf9009ad0ddce6d8f289) --- source3/smbd/trans2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 139ded57b2..a9e15f65c4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -70,8 +70,10 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, return 0; } - /* when sending params and data ensure that both are nicely aligned */ - if ((params_to_send % 4) != 0) + /* When sending params and data ensure that both are nicely aligned */ + /* Only do this alignment when there is also data to send - else + can cause NT redirector problems. */ + if (((params_to_send % 4) != 0) && (data_to_send != 0)) data_alignment_offset = 4 - (params_to_send % 4); /* Space is bufsize minus Netbios over TCP header minus SMB header */ -- cgit From 89652787c3894c7a79345a2ea67a4de741a0f760 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Jan 1998 08:25:46 +0000 Subject: Makefile: Fix for OSF1 typo. asyncdns.c: Fixes that went into 1.9.18p2 - allow unclocking of sigterm. chgpasswd.c: char -> unsigned char fixes. includes.h: AIX fix to get prototype for inet_ntoa. local.h: Tune size of shared memory based on MAX_OPEN_FILES. nmbd_mynames.c: Fix for nmbd repeated refresh bug. nmbd_responserecordsdb.c: Fix for nmbd repeated refresh bug. nmbd_winsserver.c: Fix for multi-homed registration optimisation. smb.h: Moved default shared memory size to local.h Jeremy. (This used to be commit fa5466805685d461564054d7d9947948fc56ae93) --- source3/smbd/chgpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index b516ec8ac8..80c7a43750 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -451,9 +451,9 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, no longer be valid. ************************************************************/ -BOOL change_lanman_password(struct smb_passwd *smbpw, char *pass1, char *pass2) +BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2) { - char unenc_new_pw[16]; + unsigned char unenc_new_pw[16]; BOOL ret; if(smbpw == NULL) -- cgit From 2bce7ae59d15122a150def0459ee0b4fdc787313 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 31 Jan 1998 14:31:08 +0000 Subject: server.c: Added fix where, if all the file entries are being used, smbd tries to break an oplock to make room for another file entry. This works well with Windows 95 that seems to keep batch oplocks around for an arbitrarily long time. Also changed rlimit code to ask for MAX_OPEN_FILES + 10 (if allowed) as many systems use file descriptors for directory handles also. Jeremy. (This used to be commit 1544d5a0f889d42696656fb18d2da1c1f8626b2b) --- source3/smbd/server.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 01d379ebb3..3a12513454 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3695,6 +3695,31 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de return(cnum); } +/**************************************************************************** + Attempt to break an oplock on a file (if oplocked). + Returns True if the file was closed as a result of + the oplock break, False otherwise. + Used as a last ditch attempt to free a space in the + file table when we have run out. +****************************************************************************/ + +static BOOL attempt_close_oplocked_file(files_struct *fp) +{ + + DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fp->name)); + + if (fp->open && fp->granted_oplock && !fp->sent_oplock_break) { + + /* Try and break the oplock. */ + file_fd_struct *fsp = fp->fd_ptr; + if(oplock_break( fsp->dev, fsp->inode, &fp->open_time)) { + if(!fp->open) /* Did the oplock break close the file ? */ + return True; + } + } + + return False; +} /**************************************************************************** find first available file slot @@ -3734,6 +3759,32 @@ int find_free_file(void ) return(i); } + /* + * Before we give up, go through the open files + * and see if there are any files opened with a + * batch oplock. If so break the oplock and then + * re-use that entry (if it becomes closed). + * This may help as NT/95 clients tend to keep + * files batch oplocked for quite a long time + * after they have finished with them. + */ + for (i=first_file;irlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES; + /* + * Set the fd limit to be MAX_OPEN_FILES + 10 to account for the + * extra fd we need to read directories, as well as the log files + * and standard handles etc. + */ + rlp.rlim_cur = (MAX_OPEN_FILES+10>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES+10; setrlimit(RLIMIT_NOFILE, &rlp); getrlimit(RLIMIT_NOFILE, &rlp); DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur)); -- cgit From 5546e28e69b1a43dbb48e024e233d8ebf7fa667a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 7 Feb 1998 12:15:20 +0000 Subject: A small raft of changes, I will sync up with 1.9.18 also. chgpasswd.c: Fixed typo in debug message. includes.h: Fix include for aix. kanji.c: Added cap_to_sj as inverse of sj_to_cap. loadparm.c: local.h: password.c: Added code for "networkstation user login" parameter. - patch from Rob Nielsen . printing.c: Added further aix printing fixes. reply.c: Changed access time fetch to a function. trans2.c: Changed access time fetch to a function. time.c: Changed access time fetch to a function. server.c: Made NT redirector workaround final. util.c: Added debug for write_socket failing. Jeremy. (This used to be commit a031404623c22d62f8de035be2239f609af08112) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/password.c | 61 +++++++++++++++++++++++++++++++----------------- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 8 ++++--- source3/smbd/trans2.c | 13 ++++++----- 5 files changed, 53 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 80c7a43750..fb795e973e 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -437,7 +437,7 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, /* Check that the two old passwords match. */ if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { - DEBUG(0,("check_lanman_password: old password doens't match.\n")); + DEBUG(0,("check_lanman_password: old password doesn't match.\n")); return False; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0f8705d4be..607d01d2cf 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -514,9 +514,14 @@ static BOOL dfs_auth(char *this_user,char *password) * Assumes local passwd file is kept in sync w/ DCE RGY! */ - if (!strcmp((char *)crypt(password,this_salt),this_crypted) || - dcelogin_atmost_once) - return(False); + /* Fix for original (broken) code from Brett Wooldridge */ + if (dce_login_atmost_once) + return (False); + /* This can be ifdefed as the DCE check below is stricter... */ +#ifndef NO_CRYPT + if ( strcmp((char *)crypt(password,this_salt),this_crypted) ) + return (False); +#endif if (sec_login_setup_identity( (unsigned char *)this_user, @@ -1597,28 +1602,40 @@ BOOL server_validate(char *user, char *domain, return False; } + /* + * This patch from Rob Nielsen makes doing + * the NetWksaUserLogon a dynamic, rather than compile-time + * parameter, defaulting to on. This is somewhat dangerous + * as it allows people to turn off this neccessary check, + * but so many people have had problems with this that I + * think it is a neccessary change. JRA. + */ + + if (lp_net_wksta_user_logon()) { + DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", cli.desthost)); + if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { + DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); + cli_tdis(&cli); + return False; + } -#if USE_NETWKSTAUSERLOGON - if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { - DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); - cli_tdis(&cli); - return False; - } - - if (cli.privilages == 0) { - DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); - cli_tdis(&cli); - return False; - } + if (cli.privilages == 0) { + DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); + cli_tdis(&cli); + return False; + } - if (!strequal(cli.eff_name, user)) { - DEBUG(1,("password server %s gave different username %s\n", - cli.desthost, - cli.eff_name)); - cli_tdis(&cli); - return False; + if (!strequal(cli.eff_name, user)) { + DEBUG(1,("password server %s gave different username %s\n", + cli.desthost, + cli.eff_name)); + cli_tdis(&cli); + return False; + } } -#endif + else { + DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", cli.desthost)); + } DEBUG(3,("password server %s accepted the password\n", cli.desthost)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4703dea475..db494d07db 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3917,7 +3917,7 @@ int reply_getattrE(char *inbuf,char *outbuf) date to be last modify date as UNIX doesn't save this */ put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf)); - put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); + put_dos_date2(outbuf,smb_vwv2,get_access_time(&sbuf)); put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3a12513454..94360a4c37 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1637,13 +1637,15 @@ BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) { DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); -#if 0 /* * This next line is a test that allows the deny-mode - * processing to be skipped. JRA. + * processing to be skipped. This seems to be needed as + * NT insists on the rename succeeding (in Office 9x no less !). + * This should be removed as soon as (a) MS fix the redirector + * bug or (b) NT SMB support in Samba makes NT not issue the + * call (as is my fervent hope). JRA. */ continue; -#endif } else { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a9e15f65c4..825dd0a25e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -375,7 +375,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l size = sbuf.st_size; mdate = sbuf.st_mtime; - adate = sbuf.st_atime; + adate = get_access_time(&sbuf); cdate = get_create_time(&sbuf); if(mode & aDIR) size = 0; @@ -1129,7 +1129,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf)); - put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */ + put_dos_date2(pdata,l1_fdateLastAccess,get_access_time(&sbuf)); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,size); SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); @@ -1140,7 +1140,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; put_dos_date2(pdata,0,get_create_time(&sbuf)); - put_dos_date2(pdata,4,sbuf.st_atime); + put_dos_date2(pdata,4,get_access_time(&sbuf)); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,size); SIVAL(pdata,16,ROUNDUP(size,1024)); @@ -1158,7 +1158,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_BASIC_INFO: data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ put_long_date(pdata,get_create_time(&sbuf)); - put_long_date(pdata+8,sbuf.st_atime); /* access time */ + put_long_date(pdata+8,get_access_time(&sbuf)); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); @@ -1167,8 +1167,9 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, { time_t create_time = get_create_time(&sbuf); DEBUG(5,("create: %s ", ctime(&create_time))); + create_time = get_access_time(&sbuf); + DEBUG(5,("access: %s ", ctime(&create_time))); } - DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("mode: %x\n", mode)); @@ -1222,7 +1223,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_ALL_INFO: put_long_date(pdata,get_create_time(&sbuf)); - put_long_date(pdata+8,sbuf.st_atime); /* access time */ + put_long_date(pdata+8,get_access_time(&sbuf)); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); -- cgit From 99e11e171e40703271ad2a7934708cee66b0bb82 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Feb 1998 11:07:14 +0000 Subject: Makefile: Added AIX 3.2.5. loadparm.c: Added "win95 bug compatibility" parameter. local.h: Replaced MAX_OPEN_FILES back to 100 from 10 (oops). reply.c: Fixed ulogoff check against uid - changed to vuid. server.c: Changed file struct save of uid - changed to vuid. smb.h: Changed id in struct current_user to vuid. Changed file struct uid to vuid. time.c: Added "win95 bug compatibility" atime -> mtime return. trans2.c: Added "win95 bug compatibility" fixes. uid.c: Changed id in struct current_user to vuid - added checks to set/reset it. util.c: Added code to expand environment variables. version.h : still at 1.9.18 (head branch doesn't matter too much at present). Jeremy. (This used to be commit adc903bcf59ad1664babd7f1d43675d3a75bfbc9) --- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 30 +++++++++++++++++++++++++----- source3/smbd/uid.c | 8 ++++++-- 4 files changed, 33 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index db494d07db..93bb679289 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1385,7 +1385,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) if ((vuser != 0) && (lp_security() != SEC_SHARE)) { int i; for (i=0;iuid && Files[i].open) { + if ((Files[i].vuid == vuid) && Files[i].open) { close_file(i,False); } } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 94360a4c37..0a6a05fdbf 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1344,7 +1344,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct Connections[cnum].num_files_open++; fsp->mode = sbuf->st_mode; GetTimeOfDay(&fsp->open_time); - fsp->uid = current_user.id; + fsp->vuid = current_user.vuid; fsp->size = 0; fsp->pos = -1; fsp->open = True; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 825dd0a25e..2b5d5785fa 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -32,6 +32,7 @@ extern BOOL case_sensitive; extern int Client; extern int oplock_sock; extern int smb_read_error; +extern fstring local_machine; /**************************************************************************** Send the required number of replies back. @@ -940,7 +941,8 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize int data_len; struct stat st; char *vname = volume_label(SNUM(cnum)); - + int snum = SNUM(cnum); + DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level)); if(sys_stat(".",&st)!=0) { @@ -971,7 +973,11 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize /* Return volume name */ int volname_len = MIN(strlen(vname),11); data_len = l2_vol_szVolLabel + volname_len + 1; - put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime); + /* + * Add volume serial number - hash of a combination of + * the called hostname and the service name. + */ + SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) ); SCVAL(pdata,l2_vol_cch,volname_len); StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len, @@ -992,6 +998,11 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize break; case SMB_QUERY_FS_VOLUME_INFO: data_len = 18 + 2*strlen(vname); + /* + * Add volume serial number - hash of a combination of + * the called hostname and the service name. + */ + SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) ); SIVAL(pdata,12,2*strlen(vname)); PutUniCode(pdata+18,vname); DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), @@ -1128,9 +1139,18 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf)); - put_dos_date2(pdata,l1_fdateLastAccess,get_access_time(&sbuf)); - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ + if( lp_win95_bug_compatibility()) + { + put_dos_date(pdata,l1_fdateCreation,get_create_time(&sbuf)); + put_dos_date(pdata,l1_fdateLastAccess,get_access_time(&sbuf)); + put_dos_date(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ + } + else + { + put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf)); + put_dos_date2(pdata,l1_fdateLastAccess,get_access_time(&sbuf)); + put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ + } SIVAL(pdata,l1_cbFile,size); SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); SSVAL(pdata,l1_attrFile,mode); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 176f6ca240..14b0000f59 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -53,6 +53,7 @@ void init_uid(void) initial_gid = getegid(); current_user.cnum = -1; + current_user.vuid = UID_FIELD_INVALID; ChDir(OriginalDir); } @@ -174,6 +175,7 @@ BOOL become_guest(void) DEBUG(1,("Failed to become guest. Invalid guest account?\n")); current_user.cnum = -2; + current_user.vuid = UID_FIELD_INVALID; return(ret); } @@ -208,7 +210,8 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) int snum,gid; int uid; - if (current_user.cnum == cnum && vuser != 0 && current_user.id == vuser->uid) { + if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) && + (current_user.uid == vuser->uid)) { DEBUG(4,("Skipping become_user - already user\n")); return(True); } @@ -272,7 +275,7 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) } current_user.cnum = cnum; - current_user.id = uid; + current_user.vuid = vuid; DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); @@ -333,6 +336,7 @@ BOOL unbecome_user(void ) getuid(),geteuid(),getgid(),getegid())); current_user.cnum = -1; + current_user.vuid = UID_FIELD_INVALID; return(True); } -- cgit From c04291ae995b65935ef9581bfd95eebaf4354c1d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Feb 1998 14:57:55 +0000 Subject: make the initial logfile names consistent. This should mean that smbd starts with log.smb and nmbd starts with log.nmb. It also gets rid of the "log." when using the log.%m construct as %m expands to smb before a client connects. (This used to be commit b7712a0a6d0afeef6239d5af61cba677eebb247b) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0a6a05fdbf..c2880b0e89 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5239,6 +5239,8 @@ static void usage(char *pname) strcpy(debugf,SMBLOGFILE); + strcpy(remote_machine, "smb"); + setup_logging(argv[0],False); charset_initialise(); -- cgit From 2beada804a238534628398f62fe4ed9e8d2c3efd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Feb 1998 07:11:58 +0000 Subject: Ding-dong the witch is dead, the witch is dead...... This is the checkin that fixes the infamous Visual C++ 'file has changed' bug. I feel *SO* good about that :-). charset.c: Added (void) to fix Herb's fussy compiler. loadparm.c: Removed "win95 bug compatibility" (didn't like it much anyway :-). Added "dos filetime resolution" instead. reply.c: Added the 2 second timestamp resolution fix that the song above is about. time.c: Removed unneeded get_access_time() function. trans2.c : Removed unneeded "win95 bug compatibility" code. Jeremy. (This used to be commit 10d628e4aeaecc573de27e251fec7b91844cba40) --- source3/smbd/reply.c | 17 +++++++++++++---- source3/smbd/trans2.c | 26 ++++++++------------------ 2 files changed, 21 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 93bb679289..38380180f9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -779,7 +779,10 @@ int reply_getatr(char *inbuf,char *outbuf) outsize = set_message(outbuf,10,0,True); SSVAL(outbuf,smb_vwv0,mode); - put_dos_date3(outbuf,smb_vwv1,mtime); + if(lp_dos_filetime_resolution(SNUM(cnum)) ) + put_dos_date3(outbuf,smb_vwv1,mtime & ~1); + else + put_dos_date3(outbuf,smb_vwv1,mtime); SIVAL(outbuf,smb_vwv3,size); if (Protocol >= PROTOCOL_NT1) { @@ -1231,7 +1234,10 @@ int reply_open(char *inbuf,char *outbuf) outsize = set_message(outbuf,7,0,True); SSVAL(outbuf,smb_vwv0,fnum); SSVAL(outbuf,smb_vwv1,fmode); - put_dos_date3(outbuf,smb_vwv2,mtime); + if(lp_dos_filetime_resolution(SNUM(cnum)) ) + put_dos_date3(outbuf,smb_vwv2,mtime & ~1); + else + put_dos_date3(outbuf,smb_vwv2,mtime); SIVAL(outbuf,smb_vwv4,size); SSVAL(outbuf,smb_vwv6,rmode); @@ -1357,7 +1363,10 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,15,0,True); SSVAL(outbuf,smb_vwv2,fnum); SSVAL(outbuf,smb_vwv3,fmode); - put_dos_date3(outbuf,smb_vwv4,mtime); + if(lp_dos_filetime_resolution(SNUM(cnum)) ) + put_dos_date3(outbuf,smb_vwv4,mtime & ~1); + else + put_dos_date3(outbuf,smb_vwv4,mtime); SIVAL(outbuf,smb_vwv6,size); SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,smb_action); @@ -3917,7 +3926,7 @@ int reply_getattrE(char *inbuf,char *outbuf) date to be last modify date as UNIX doesn't save this */ put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf)); - put_dos_date2(outbuf,smb_vwv2,get_access_time(&sbuf)); + put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2b5d5785fa..6eda891e32 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -376,7 +376,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l size = sbuf.st_size; mdate = sbuf.st_mtime; - adate = get_access_time(&sbuf); + adate = sbuf.st_atime; cdate = get_create_time(&sbuf); if(mode & aDIR) size = 0; @@ -1139,18 +1139,9 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - if( lp_win95_bug_compatibility()) - { - put_dos_date(pdata,l1_fdateCreation,get_create_time(&sbuf)); - put_dos_date(pdata,l1_fdateLastAccess,get_access_time(&sbuf)); - put_dos_date(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - } - else - { - put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf)); - put_dos_date2(pdata,l1_fdateLastAccess,get_access_time(&sbuf)); - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - } + put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf)); + put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); + put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,size); SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); SSVAL(pdata,l1_attrFile,mode); @@ -1160,7 +1151,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; put_dos_date2(pdata,0,get_create_time(&sbuf)); - put_dos_date2(pdata,4,get_access_time(&sbuf)); + put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,size); SIVAL(pdata,16,ROUNDUP(size,1024)); @@ -1178,7 +1169,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_BASIC_INFO: data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ put_long_date(pdata,get_create_time(&sbuf)); - put_long_date(pdata+8,get_access_time(&sbuf)); + put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); @@ -1187,9 +1178,8 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, { time_t create_time = get_create_time(&sbuf); DEBUG(5,("create: %s ", ctime(&create_time))); - create_time = get_access_time(&sbuf); - DEBUG(5,("access: %s ", ctime(&create_time))); } + DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("mode: %x\n", mode)); @@ -1243,7 +1233,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_ALL_INFO: put_long_date(pdata,get_create_time(&sbuf)); - put_long_date(pdata+8,get_access_time(&sbuf)); + put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); -- cgit From c16d4aec00230983973be3b827d1209f5db65d9c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Feb 1998 19:48:01 +0000 Subject: nmbd_packets.c: nmbd_subnetdb.c: Patch from Andrey Alekseyev to fix the fact that retransmit_or_expire_response_records() wasn't looking at the WINS subnet. server.c: Patch from jkf@soton.ac.uk to add %p (NIS server path) substitution. smbpass.c: Fix to stop parsing failing on non-valid lines. trans2.c: Fix for volume serial number code. util.c: Patch from jkf@soton.ac.uk to add %p (NIS server path) substitution. Fix for warnings under RH5. gcc 2.8. Jeremy. (This used to be commit e58ab3bbe6e939ba678ad5482e58e0191c8dcbcb) --- source3/smbd/server.c | 9 +++++++++ source3/smbd/trans2.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c2880b0e89..9c25a21000 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4569,6 +4569,15 @@ void standard_sub(int cnum,char *str) case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break; case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break; case 'u' : string_sub(p,"%u",Connections[cnum].user); 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 username. + * The %p (NIS server path) code is 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(Connections[cnum].service))); break; case '\0' : p++; break; /* don't run off the end of the string */ default : p+=2; break; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6eda891e32..893f1adc66 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -977,7 +977,7 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize * Add volume serial number - hash of a combination of * the called hostname and the service name. */ - SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) ); + SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); SCVAL(pdata,l2_vol_cch,volname_len); StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len, @@ -1002,7 +1002,7 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize * Add volume serial number - hash of a combination of * the called hostname and the service name. */ - SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) ); + SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); SIVAL(pdata,12,2*strlen(vname)); PutUniCode(pdata+18,vname); DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), -- cgit From de3badf479eb08c19d4abc0625488effc79dc1fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Feb 1998 19:53:55 +0000 Subject: Fix for NT redirector bug where deltree fails if the resume key indexes are changed between directory scans. This fix does what NT4.x SP3 does in that it stops using resume keys and returns zero instead. We now use the filename in findnext to continue the search in the correct place (as NT does). Jeremy. (This used to be commit b813fb22c4c1b0ee48667e99e82434d20266bbf2) --- source3/smbd/dir.c | 9 ++---- source3/smbd/trans2.c | 78 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index d751653263..a34406cc65 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -393,21 +393,16 @@ void *dptr_fetch(char *buf,int *num) } /**************************************************************************** -fetch the dir ptr and seek it given the lanman2 parameter block +fetch the dir ptr. ****************************************************************************/ -void *dptr_fetch_lanman2(char *params,int dptr_num) +void *dptr_fetch_lanman2(int dptr_num) { void *p = dptr_get(dptr_num,dircounter++); - uint32 resume_key = SVAL(params,6); - BOOL uses_resume_key = BITSETW(params+10,2); - BOOL continue_bit = BITSETW(params+10,3); if (!p) { DEBUG(3,("fetched null dirptr %d\n",dptr_num)); return(NULL); } - if(uses_resume_key && !continue_bit) - SeekDir(p,resume_key); DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); return(p); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 893f1adc66..35272ae3d9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -301,7 +301,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l pstring fname; BOOL matched; char *p, *pdata = *ppdata; - int reskey=0, prev_dirpos=0; + uint32 reskey=0; + int prev_dirpos=0; int mode=0; uint32 size=0,len; uint32 mdate=0, adate=0, cdate=0; @@ -336,7 +337,14 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l prev_dirpos = TellDir(Connections[cnum].dirptr); dname = ReadDirName(Connections[cnum].dirptr); - reskey = TellDir(Connections[cnum].dirptr); + /* + * Due to bugs in NT client redirectors we are not using + * resume keys any more - set them to zero. + * Check out the related comments in findfirst/findnext. + * JRA. + */ + + reskey = 0; DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); @@ -796,6 +804,7 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz BOOL close_if_end = BITSETW(params+10,1); BOOL requires_resume_key = BITSETW(params+10,2); BOOL continue_bit = BITSETW(params+10,3); + pstring resume_name; pstring mask; pstring directory; char *p; @@ -807,11 +816,15 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz BOOL out_of_space = False; int space_remaining; - *mask = *directory = 0; + *mask = *directory = *resume_name = 0; + + pstrcpy( resume_name, params+12); - DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d continue=%d level = %d\n", + DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \ +close_after_request=%d, close_if_end = %d requires_resume_key = %d \ +resume_key = %d resume name = %s continue=%d level = %d\n", dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, - requires_resume_key, resume_key, continue_bit, info_level)); + requires_resume_key, resume_key, resume_name, continue_bit, info_level)); switch (info_level) { @@ -839,7 +852,7 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz return(ERROR(ERRDOS,ERRnomem)); /* Check that the dptr is valid */ - if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num))) + if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(dptr_num))) return(ERROR(ERRDOS,ERRnofiles)); string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); @@ -871,9 +884,56 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz space_remaining = max_data_bytes; out_of_space = False; - /* If we have a resume key - seek to the correct position. */ - if(requires_resume_key && !continue_bit) - SeekDir(Connections[cnum].dirptr, resume_key); + /* + * Seek to the correct position. We no longer use the resume key but + * depend on the last file name instead. + */ + if(requires_resume_key && *resume_name && !continue_bit) + { + /* + * Fix for NT redirector problem triggered by resume key indexes + * changing between directory scans. We now return a resume key of 0 + * and instead look for the filename to continue from (also given + * to us by NT/95/smbfs/smbclient). If no other scans have been done between the + * findfirst/findnext (as is usual) then the directory pointer + * should already be at the correct place. Check this by scanning + * backwards looking for an exact (ie. case sensitive) filename match. + * If we get to the beginning of the directory and haven't found it then scan + * forwards again looking for a match. JRA. + */ + + int current_pos, start_pos; + char *dname; + void *dirptr = Connections[cnum].dirptr; + start_pos = TellDir(dirptr); + for(current_pos = start_pos; current_pos >= 0; current_pos--) + { + SeekDir(dirptr, current_pos); + dname = ReadDirName(dirptr); + if(dname && strcsequal( resume_name, dname)) + { + SeekDir(dirptr, current_pos+1); + break; + } + } + + /* + * Scan forward from start if not found going backwards. + */ + + if(current_pos < 0) + { + SeekDir(dirptr, start_pos); + for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) + { + if(strcsequal( resume_name, dname)) + { + SeekDir(dirptr, current_pos+1); + break; + } + } /* end for */ + } /* end if current_pos */ + } /* end if requires_resume_key && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { -- cgit From 45dab9f06594777e96be5f4556e6bb386f68f309 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Feb 1998 22:58:21 +0000 Subject: Makefile, password.c, includes.h: Added KRB4 patches from Johan Hedin nmbd_packets.c: Patch for aliased interfaces from Daniel Haun . Jeremy. (This used to be commit 60f6302b1972e49159bf6e1a838e691268e4399c) --- source3/smbd/password.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 607d01d2cf..1911515404 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -670,6 +670,32 @@ static BOOL krb5_auth(char *this_user,char *password) } #endif /* KRB5_AUTH */ +#ifdef KRB4_AUTH +/******************************************************************* +check on Kerberos authentication +********************************************************************/ +static BOOL krb4_auth(char *this_user,char *password) +{ + char realm[REALM_SZ]; + char tkfile[MAXPATHLEN]; + + if (krb_get_lrealm(realm, 1) != KSUCCESS) + (void) strncpy(realm, KRB_REALM, sizeof (realm)); + + (void) sprintf(tkfile, "/tmp/samba_tkt_%d", getpid()); + + krb_set_tkt_string(tkfile); + if (krb_verify_user(this_user, "", realm, + password, 0, + "rmcd") == KSUCCESS) { + unlink(tkfile); + return 1; + } + unlink(tkfile); + return 0; +} +#endif /* KRB4_AUTH */ + #ifdef LINUX_BIGCRYPT /**************************************************************************** an enhanced crypt for Linux to handle password longer than 8 characters @@ -775,6 +801,10 @@ Hence we make a direct return to avoid a second chance!!! if (krb5_auth(this_user,password)) return(True); #endif +#ifdef KRB4_AUTH + if (krb4_auth(this_user,password)) return(True); +#endif + #ifdef PWDAUTH if (pwdauth(this_user,password) == 0) return(True); -- cgit From b7fb6c6b38784d25c9c85e9b27b08e30111dbd0c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Mar 1998 20:19:14 +0000 Subject: Change the multibyte character set support so that Kanji support is one case of multibyte character support, rather than being a specific case in single byte character support. This allows us to add Big5 Chinese support (code page 950) and Korean Hangul support (code page 949) at very little cost. Also allows us to easily add future multibyte code pages. Makefile: Added codepages 949, 950 as we now support more multibyte codepages. asyncdns.c: Fixed problem with child being re-spawned when parent killed. charcnv.c charset.c client.c clitar.c kanji.c kanji.h smb.h util.c loadparm.c: Generic multibyte codepage support (adding Big5 Chinese and Korean Hangul). nmbd.c: Fixed problem with child being re-spawned when parent killed. mangle.c: Modified str_checksum so that first 15 characters have more effect on outcome. This helps with short name mangling as most 'long' names are still shorter than 15 chars (bug was foobar_mng and foobar_sum would hash to the same value, with the modified code they hash differently. Jeremy. (This used to be commit 299016338cfb47f0c585875ef9b468121fcee97d) --- source3/smbd/mangle.c | 136 ++++++++++++++++++-------------------------------- source3/smbd/trans2.c | 5 ++ 2 files changed, 53 insertions(+), 88 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 7b6a563511..d0d5ada247 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -42,7 +42,7 @@ int str_checksum(char *s) while( *s ) { c = *s; - res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); + res ^= (c << (15-(i%15))) ^ (c >> (i % 15)); s++; i++; } return(res); @@ -130,38 +130,25 @@ BOOL is_8_3(char *fname, BOOL check_case) dot_pos = strchr(fname,'.'); - { + { char *p = fname; + int skip; - if(lp_client_code_page() == KANJI_CODEPAGE) - { - dot_pos = 0; - while (*p) - { - if (is_shift_jis (*p)) - p += 2; - else if (is_kana (*p)) - p ++; - else - { - if (*p == '.' && !dot_pos) - dot_pos = (char *) p; - if (!isdoschar(*p)) - return(False); - p++; - } - } - } - else + dot_pos = 0; + while (*p) + { + if((skip = skip_multibyte_char( *p )) != 0) + p += skip; + else { - while (*p) - { + if (*p == '.' && !dot_pos) + dot_pos = (char *) p; if (!isdoschar(*p)) return(False); p++; - } } } + } /* no dot and less than 9 means OK */ if (!dot_pos) @@ -542,6 +529,7 @@ void mangle_name_83(char *s) char base[9]; int baselen = 0; int extlen = 0; + int skip; extension[0]=0; base[0]=0; @@ -572,40 +560,29 @@ void mangle_name_83(char *s) *p++ = 0; while (*p && extlen < 3) { - if(lp_client_code_page() == KANJI_CODEPAGE) + skip = skip_multibyte_char(*p); + if (skip == 2) { - if (is_shift_jis (*p)) + if (extlen < 2) { - if (extlen < 2) - { - extension[extlen++] = p[0]; - extension[extlen++] = p[1]; - } - else - { - extension[extlen++] = base36 (((unsigned char) *p) % 36); - } - p += 2; + extension[extlen++] = p[0]; + extension[extlen++] = p[1]; } - else + else { - if( is_kana (*p) ) - { - extension[extlen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') - extension[extlen++] = p[0]; - p++; - } + extension[extlen++] = base36 (((unsigned char) *p) % 36); } + p += 2; } - else + else if( skip == 1 ) { - if (isdoschar(*p) && *p != '.') - extension[extlen++] = *p; + extension[extlen++] = p[0]; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') + extension[extlen++] = p[0]; p++; } } @@ -617,9 +594,8 @@ void mangle_name_83(char *s) while (*p && baselen < 5) { - if(lp_client_code_page() == KANJI_CODEPAGE) - { - if (is_shift_jis (*p)) + skip = skip_multibyte_char(*p); + if (skip == 2) { if (baselen < 4) { @@ -632,27 +608,17 @@ void mangle_name_83(char *s) } p += 2; } - else + else if( skip == 1) { - if( is_kana (*p) ) - { + base[baselen++] = p[0]; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') base[baselen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') - base[baselen++] = p[0]; - p++; - } + p++; } - } - else - { - if (isdoschar(*p) && *p != '.') - base[baselen++] = *p; - p++; - } } base[baselen] = 0; @@ -679,6 +645,7 @@ static BOOL illegal_name(char *name) static unsigned char illegal[256]; static BOOL initialised=False; unsigned char *s; + int skip; if( !initialised ) { @@ -690,26 +657,19 @@ static BOOL illegal_name(char *name) illegal[*s] = True; } - if(lp_client_code_page() == KANJI_CODEPAGE) + for (s = (unsigned char *)name; *s;) { - for (s = (unsigned char *)name; *s;) + skip = skip_multibyte_char( *s ); + if (skip != 0) + s += skip; + else { - if (is_shift_jis (*s)) - s += 2; + if (illegal[*s]) + return(True); else - { - if (illegal[*s]) - return(True); - else - s++; - } + s++; } } - else - { - for (s = (unsigned char *)name;*s;s++) - if (illegal[*s]) return(True); - } return(False); } /* illegal_name */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 35272ae3d9..3cd6c138c8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -908,11 +908,14 @@ resume_key = %d resume name = %s continue=%d level = %d\n", start_pos = TellDir(dirptr); for(current_pos = start_pos; current_pos >= 0; current_pos--) { + DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos)); + SeekDir(dirptr, current_pos); dname = ReadDirName(dirptr); if(dname && strcsequal( resume_name, dname)) { SeekDir(dirptr, current_pos+1); + DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); break; } } @@ -923,12 +926,14 @@ resume_key = %d resume name = %s continue=%d level = %d\n", if(current_pos < 0) { + DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos)); SeekDir(dirptr, start_pos); for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) { if(strcsequal( resume_name, dname)) { SeekDir(dirptr, current_pos+1); + DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); break; } } /* end for */ -- cgit From 3fb9f9db569e0fe02777e1e7805f20e668309cfe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Mar 1998 01:50:47 +0000 Subject: Adding Korean and Traditional Chinese codepage support. Jeremy. (This used to be commit 2df47cf1bb3428fbaa8dcf45ec114ec3aaafae57) --- source3/smbd/password.c | 2 +- source3/smbd/server.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1911515404..a51e5f639f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -515,7 +515,7 @@ static BOOL dfs_auth(char *this_user,char *password) */ /* Fix for original (broken) code from Brett Wooldridge */ - if (dce_login_atmost_once) + if (dcelogin_atmost_once) return (False); /* This can be ifdefed as the DCE check below is stricter... */ #ifndef NO_CRYPT diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9c25a21000..e6807bdf31 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -54,6 +54,10 @@ extern int smb_read_error; extern pstring user_socket_options; +#ifdef DFS_AUTH +extern int dcelogin_atmost_once; +#endif /* DFS_AUTH */ + connection_struct Connections[MAX_CONNECTIONS]; files_struct Files[MAX_OPEN_FILES]; -- cgit From f3eeb2f1fa528b0d952d2519f719d30f4a2489fa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Mar 1998 22:24:07 +0000 Subject: Removed broken change I made to mangle.c (ooops. Andrew's original algorithm was correct). Finally (I think) fixed the mangled directory stack issue in scan_directory() correctly. Mangled & non-mangled names are now being checked correctly. Hurrah to Ulrik Dickow who helped isolate this one. Jeremy. (This used to be commit 37f5f7b557aa59c7eba4a9f2f2f323d7cec62fc7) --- source3/smbd/mangle.c | 2 +- source3/smbd/server.c | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index d0d5ada247..8aa53bc35a 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -42,7 +42,7 @@ int str_checksum(char *s) while( *s ) { c = *s; - res ^= (c << (15-(i%15))) ^ (c >> (i % 15)); + res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); s++; i++; } return(res); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e6807bdf31..e290027d0a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -456,11 +456,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) return(True); } -#if 0 - /* - * This code I believe is incorrect - and commenting it out - * is the correct fix for the bug mentioned below in the - * comment 'name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra)'. + /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) * read from the directory and then mangled by the name_map_mangle() @@ -468,8 +464,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) * (JRA). */ if (mangled) - check_mangled_stack(name); -#endif + mangled = !check_mangled_stack(name); /* open the directory */ if (!(cur_dir = OpenDir(cnum, path, True))) @@ -489,7 +484,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) if (!name_map_mangle(name2,False,SNUM(cnum))) continue; if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, name2)) /* name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra) */ + || fname_equal(name, name2)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(cnum)); -- cgit From fdeea341ed1bae670382e45eb731db1b5838ad21 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Mar 1998 21:11:04 +0000 Subject: "For I have laboured mightily on Luke's code, and hath broken all I saw" - the book of Jeremy, chapter 1 :-). So here is the mega-merge of the NTDOM branch server code. It doesn't include the new client side pieces, we'll look at that later. This should give the same functionality, server wise, as the NTDOM branch does, only merged into the main branch. Any fixes to domain controler functionality should be added to the main branch, not the NTDOM branch. This code compiles without warnings on gcc2.8, but will need further testing before we are sure all the working functionality of the NTDOM server branch has been correctly carried over. I hereby declare the server side of the NTDOM branch dead (and all who sail in her :-). Jeremy. (This used to be commit 118ba4d77a33248e762a2cf843fb7cbc906ee6e7) --- source3/smbd/chgpasswd.c | 12 + source3/smbd/ipc.c | 669 ++++++++++++++++++++++++++++++++--------------- source3/smbd/password.c | 103 ++++++-- source3/smbd/pipes.c | 242 ++++------------- source3/smbd/reply.c | 116 +++++--- source3/smbd/server.c | 4 +- 6 files changed, 676 insertions(+), 470 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fb795e973e..c83ff1911c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -422,6 +422,12 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, return False; } + if(smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + return False; + } + if(smbpw->smb_passwd == NULL) { DEBUG(0,("check_lanman_password: no lanman password !\n")); @@ -462,6 +468,12 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi return False; } + if(smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); + return False; + } + if(smbpw->smb_passwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 048dab8b3e..bbeeb21e96 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -27,6 +27,7 @@ */ #include "includes.h" +#include "nterr.h" #ifdef CHECK_TYPES #undef CHECK_TYPES @@ -131,79 +132,128 @@ static BOOL prefix_ok(char *str,char *prefix) return(strncmp(str,prefix,strlen(prefix)) == 0); } +/******************************************************************* + copies parameters and data, as needed, into the smb buffer + + *both* the data and params sections should be aligned. this + is fudged in the rpc pipes by + at present, only the data section is. this may be a possible + cause of some of the ipc problems being experienced. lkcl26dec97 + + ******************************************************************/ +static void copy_trans_params_and_data(char *outbuf, int align, + struct mem_buf *rparam, struct mem_buf *rdata, + int param_offset, int data_offset, + int param_len, int data_len) +{ + char *copy_into = smb_buf(outbuf); + + DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", + param_offset, param_offset + param_len, + data_offset , data_offset + data_len)); + + if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len); + copy_into += param_len + align; + if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len); +} /**************************************************************************** send a trans reply ****************************************************************************/ -static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup) +static void send_trans_reply(char *outbuf, + struct mem_buf *rdata, + struct mem_buf *rparam, + uint16 *setup, int lsetup, int max_data_ret) { - int i; - int this_ldata,this_lparam; - int tot_data=0,tot_param=0; - int align; + int i; + int this_ldata,this_lparam; + int tot_data=0,tot_param=0; + int align; + + int ldata = rdata ? mem_buf_len(rdata ) : 0; + int lparam = rparam ? mem_buf_len(rparam) : 0; - this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); + BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False; + + if (buffer_too_large) + { + DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret)); + ldata = max_data_ret; + } + + this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ + this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING - /* if you don't want Net Monitor to decode your packets, do this!!! */ - align = ((this_lparam+1)%4); + /* if you don't want Net Monitor to decode your packets, do this!!! */ + align = ((this_lparam+1)%4); #else - align = (this_lparam%4); + align = (this_lparam%4); #endif - set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); - if (this_lparam) - memcpy(smb_buf(outbuf),param,this_lparam); - if (this_ldata) - memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata); - - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,lsetup); - for (i=0;iuid, vuser->name)); + if(vuser != NULL) + DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); @@ -2236,7 +2322,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); } @@ -2292,7 +2378,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ @@ -2920,175 +3006,331 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data, return(True); } - -struct +struct api_cmd { - char * name; char * pipe_clnt_name; -#ifdef NTDOMAIN char * pipe_srv_name; -#endif - int subcommand; - BOOL (*fn) (); -} api_fd_commands [] = - { -#ifdef NTDOMAIN - { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP }, - { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP }, - { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP }, - { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP }, - { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP }, - { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported } -#else - { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP }, - { NULL, NULL, -1, (BOOL (*)())api_Unsupported } -#endif - }; + BOOL (*fn) (pipes_struct *, prs_struct *); +}; -/**************************************************************************** - handle remote api calls delivered to a named pipe already opened. - ****************************************************************************/ -static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +static struct api_cmd api_fd_commands[] = { - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; + { "lsarpc", "lsass", api_ntlsa_rpc }, + { "samr", "lsass", api_samr_rpc }, + { "srvsvc", "ntsvcs", api_srvsvc_rpc }, + { "wkssvc", "ntsvcs", api_wkssvc_rpc }, + { "NETLOGON", "lsass", api_netlog_rpc }, + { "winreg", "winreg", api_reg_rpc }, + { NULL, NULL, NULL } +}; - BOOL reply = False; - BOOL bind_req = False; - BOOL set_nphs = False; +static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) +{ + BOOL ntlmssp_auth = False; + fstring ack_pipe_name; + int i = 0; - int i; - int fd; - int subcommand; - char *pipe_name; - - DEBUG(5,("api_fd_reply\n")); - /* First find out the name of this file. */ - if (suwcnt != 2) - { - DEBUG(0,("Unexpected named pipe transaction.\n")); - return(-1); - } - - /* Get the file handle and hence the file name. */ - fd = setup[1]; - subcommand = setup[0]; - pipe_name = get_rpc_pipe_hnd_name(fd); + DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); - if (pipe_name == NULL) - { - DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd)); - } + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) + { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) + { + DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", + api_fd_commands[i].pipe_clnt_name, + api_fd_commands[i].pipe_srv_name)); + fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name); + break; + } + } - DEBUG(3,("Got API command %d on pipe %s (fd %x)", - subcommand, pipe_name, fd)); - DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", - tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); - - for (i = 0; api_fd_commands[i].name; i++) - { - if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) && - api_fd_commands[i].subcommand == subcommand && - api_fd_commands[i].fn) - { - DEBUG(3,("Doing %s\n", api_fd_commands[i].name)); - break; - } - } - - rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024); - rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - -#ifdef NTDOMAIN - /* RPC Pipe command 0x26. */ - if (data != NULL && api_fd_commands[i].subcommand == 0x26) - { - RPC_HDR hdr; + if (api_fd_commands[i].fn == NULL) return False; - /* process the rpc header */ - char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0); - - /* bind request received */ - if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND)))) - { - RPC_HDR_RB hdr_rb; + /* decode the bind request */ + smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0); - /* decode the bind request */ - char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0); + if (pd->offset == 0) return False; - if ((bind_req = (p != NULL))) - { - RPC_HDR_BA hdr_ba; - fstring ack_pipe_name; + if (p->hdr.auth_len != 0) + { + /* decode the authentication verifier */ + smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0); - /* name has to be \PIPE\xxxxx */ - strcpy(ack_pipe_name, "\\PIPE\\"); - strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name); + if (pd->offset == 0) return False; - /* make a bind acknowledgement */ - make_rpc_hdr_ba(&hdr_ba, - hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid, - ack_pipe_name, - 0x1, 0x0, 0x0, - &(hdr_rb.transfer)); + /* ignore the version number for now */ + ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP"); + } - p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0); + /* name has to be \PIPE\xxxxx */ + strcpy(ack_pipe_name, "\\PIPE\\"); + strcat(ack_pipe_name, p->pipe_srv_name); - rdata_len = PTR_DIFF(p, rdata); + DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); - make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len); + prs_init(&(p->rdata), 1024, 4, 0, False); + prs_init(&(p->rhdr ), 0x10, 4, 0, False); + prs_init(&(p->rauth), 1024, 4, 0, False); - p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0); - - reply = (p != NULL); - } - } - } -#endif + /***/ + /*** do the bind ack first ***/ + /***/ - /* Set Named Pipe Handle state */ - if (subcommand == 0x1) - { - set_nphs = True; - reply = api_LsarpcSNPHS(fd, cnum, params); - } + make_rpc_hdr_ba(&p->hdr_ba, + p->hdr_rb.bba.max_tsize, + p->hdr_rb.bba.max_rsize, + p->hdr_rb.bba.assoc_gid, + ack_pipe_name, + 0x1, 0x0, 0x0, + &(p->hdr_rb.transfer)); - if (!bind_req && !set_nphs) - { - DEBUG(10,("calling api_fd_command\n")); + smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0); + mem_realloc_data(p->rdata.data, p->rdata.offset); - reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - DEBUG(10,("called api_fd_command\n")); - } + /***/ + /*** now the authentication ***/ + /***/ - if (rdata_len > mdrcnt || rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - /* if we get False back then it's actually unsupported */ - if (!reply) - { - api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); - - if (rdata ) free(rdata ); - if (rparam) free(rparam); - - return(-1); + if (ntlmssp_auth) + { + uint8 data[16]; + bzero(data, sizeof(data)); /* first 8 bytes are non-zero */ + + make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp, + 0x0a, 0x06, 0, + "NTLMSSP", 2, + 0x00000000, 0x0000b2b3, 0x000082b1, + data); + smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0); + mem_realloc_data(p->rauth.data, p->rauth.offset); + } + + /***/ + /*** then do the header, now we know the length ***/ + /***/ + + make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, + p->rdata.offset + p->rauth.offset, + p->rauth.offset); + + smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0); + mem_realloc_data(p->rhdr.data, p->rdata.offset); + + /***/ + /*** link rpc header, bind acknowledgment and authentication responses ***/ + /***/ + + p->rhdr.data->offset.start = 0; + p->rhdr.data->offset.end = p->rhdr.offset; + p->rhdr.data->next = p->rdata.data; + + if (ntlmssp_auth) + { + p->rdata.data->offset.start = p->rhdr.offset; + p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; + p->rdata.data->next = p->rauth.data; + + p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset; + p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset; + p->rauth.data->next = NULL; + } + else + { + p->rdata.data->offset.start = p->rhdr.offset; + p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; + p->rdata.data->next = NULL; + } + + return True; } +static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd) +{ + int i = 0; + + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) + { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) + { + DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name)); + return api_fd_commands[i].fn(p, pd); + } + } + return False; +} +static BOOL api_dce_rpc_command(char *outbuf, + pipes_struct *p, + prs_struct *pd) +{ + BOOL reply = False; + if (pd->data == NULL) return False; + + /* process the rpc header */ + smb_io_rpc_hdr("", &p->hdr, pd, 0); + + if (pd->offset == 0) return False; + + switch (p->hdr.pkt_type) + { + case RPC_BIND : + { + reply = api_pipe_bind_req(p, pd); + break; + } + case RPC_REQUEST: + { + reply = api_pipe_request (p, pd); + break; + } + } + + if (reply) + { + /* now send the reply */ + send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len); + + if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len) + { + /* all of data was sent: no need to wait for SMBreadX calls */ + mem_free_data(p->rhdr .data); + mem_free_data(p->rdata.data); + } + } + + return reply; +} + +/**************************************************************************** + SetNamedPipeHandleState +****************************************************************************/ +static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) +{ + uint16 id; + + if (!param) return False; + + id = param[0] + (param[1] << 8); + DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id)); + + if (set_rpc_pipe_hnd_state(p, id)) + { + /* now send the reply */ + send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len); + + return True; + } + return False; +} + + +/**************************************************************************** + when no reply is generated, indicate unsupported. + ****************************************************************************/ +static BOOL api_no_reply(char *outbuf, int max_rdata_len) +{ + struct mem_buf rparam; + + mem_init(&rparam, 0); + mem_alloc_data(&rparam, 4); + + rparam.offset.start = 0; + rparam.offset.end = 4; + + /* unsupported */ + SSVAL(rparam.data,0,NERR_notsupported); + SSVAL(rparam.data,2,0); /* converter word */ + + DEBUG(3,("Unsupported API fd command\n")); + + /* now send the reply */ + send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len); + + mem_free_data(&rparam); + + return(-1); +} + +/**************************************************************************** + handle remote api calls delivered to a named pipe already opened. + ****************************************************************************/ +static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +{ + BOOL reply = False; + + int pnum; + int subcommand; + pipes_struct *p = NULL; + prs_struct pd; + struct mem_buf data_buf; + + DEBUG(5,("api_fd_reply\n")); + + /* fake up a data buffer from the api_fd_reply data parameters */ + mem_create(&data_buf, data, tdscnt, 0, False); + data_buf.offset.start = 0; + data_buf.offset.end = tdscnt; + + /* fake up a parsing structure */ + pd.data = &data_buf; + pd.align = 4; + pd.io = True; + pd.offset = 0; + + /* First find out the name of this file. */ + if (suwcnt != 2) + { + DEBUG(0,("Unexpected named pipe transaction.\n")); + return(-1); + } + + /* Get the file handle and hence the file name. */ + pnum = setup[1]; + subcommand = setup[0]; + get_rpc_pipe(pnum, &p); + + if (p != NULL) + { + DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", + subcommand, p->name, pnum)); + DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", + tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); + + /* record maximum data length that can be transmitted in an SMBtrans */ + p->max_rdata_len = mdrcnt; + + switch (subcommand) + { + case 0x26: + { + /* dce/rpc command */ + reply = api_dce_rpc_command(outbuf, p, &pd); + break; + } + case 0x01: + { + /* Set Named Pipe Handle state */ + reply = api_SNPHS(outbuf, p, params); + break; + } + } + } + else + { + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); + } + + if (!reply) + { + return api_no_reply(outbuf, mdrcnt); + } + return -1; +} /**************************************************************************** the buffer was too small @@ -3145,6 +3387,7 @@ struct {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0}, {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0}, {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0}, + {"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0}, {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0}, {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0}, {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0}, @@ -3177,6 +3420,8 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { int api_command = SVAL(params,0); + struct mem_buf rdata_buf; + struct mem_buf rparam_buf; char *rdata = NULL; char *rparam = NULL; int rdata_len = 0; @@ -3216,14 +3461,20 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, &rdata,&rparam,&rdata_len,&rparam_len); + mem_create(&rdata_buf , rdata , rdata_len , 0, False); + mem_create(&rparam_buf, rparam, rparam_len, 0, False); + + rdata_buf.offset.start = 0; + rdata_buf.offset.end = rdata_len; + + rparam_buf.offset.start = 0; + rparam_buf.offset.end = rparam_len; /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); + send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0); - if (rdata) - free(rdata); - if (rparam) - free(rparam); + if (rdata ) free(rdata); + if (rparam) free(rparam); return(-1); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a51e5f639f..b422dda36c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -876,6 +876,68 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha return (memcmp(p24, password, 24) == 0); } +/**************************************************************************** + Do a specific test for an smb password being correct, given a smb_password and + the lanman and NT responses. +****************************************************************************/ + +BOOL smb_password_ok(struct smb_passwd *smb_pass, + uchar lm_pass[24], uchar nt_pass[24]) +{ + uchar challenge[8]; + + if (!lm_pass || !smb_pass) return(False); + + if(smb_pass->acct_ctrl & ACB_DISABLED) + { + DEBUG(3,("smb_password_ok: account for user %s was disabled.\n", smb_pass->smb_name)); + return(False); + } + + if (!last_challenge(challenge)) + { + DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); + return False; + } + + DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n", smb_pass->smb_name)); + + if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) + { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_password_check(nt_pass, smb_pass->smb_nt_passwd, challenge)) + { + DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); + return(True); + } + DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); + } + + /* Try against the lanman password. smb_pass->smb_passwd == NULL means + no password, allow access. */ + + DEBUG(4,("Checking LM MD4 password\n")); + + if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ)) + { + DEBUG(4,("smb_password_ok: no password required for user %s\n", smb_pass->smb_name)); + return True; + } + + if((smb_pass->smb_passwd != NULL) && smb_password_check(lm_pass, smb_pass->smb_passwd, challenge)) + { + DEBUG(4,("smb_password_ok: LM MD4 password check succeeded\n")); + return(True); + } + + DEBUG(4,("smb_password_ok: LM MD4 password check failed\n")); + + return False; +} + /**************************************************************************** check if a username/password is OK ****************************************************************************/ @@ -940,6 +1002,13 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } + /* Quit if the account was disabled. */ + if(smb_pass->acct_ctrl & ACB_DISABLED) + { + DEBUG(3,("password_ok: account for user %s was disabled.\n", user)); + return(False); + } + /* Ensure the uid's match */ if (smb_pass->smb_userid != pass->pw_uid) { @@ -947,35 +1016,13 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } - if (Protocol >= PROTOCOL_NT1) - { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - if (smb_pass->smb_nt_passwd != NULL) - { - DEBUG(4,("Checking NT MD4 password\n")); - if (smb_password_check(password, - smb_pass->smb_nt_passwd, - (unsigned char *)challenge)) - { - update_protected_database(user,True); - return(True); - } - DEBUG(4,("NT MD4 password check failed\n")); - } - } - - /* Try against the lanman password */ - - if (smb_password_check(password, - smb_pass->smb_passwd, - (unsigned char *)challenge)) { - update_protected_database(user,True); - return(True); - } + if(smb_password_ok( smb_pass, password, password)) + { + update_protected_database(user,True); + return(True); + } - DEBUG(3,("Error smb_password_check failed\n")); + DEBUG(3,("Error smb_password_check failed\n")); } DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index b5f9700f33..4d425cc2c0 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -51,17 +51,7 @@ extern fstring myworkgroup; a packet to ensure chaining works correctly */ #define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where)) -char * known_pipes [] = -{ - "lsarpc", -#if NTDOMAIN - "NETLOGON", - "srvsvc", - "wkssvc", - "samr", -#endif - NULL -}; +extern struct pipe_id_info pipe_names[]; /**************************************************************************** reply to an open and X on a named pipe @@ -72,7 +62,8 @@ char * known_pipes [] = int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; - int cnum = SVAL(inbuf,smb_tid); + uint16 cnum = SVAL(inbuf, smb_tid); + uint16 vuid = SVAL(inbuf, smb_uid); int pnum = -1; int smb_ofun = SVAL(inbuf,smb_vwv8); int size=0,fmode=0,mtime=0,rmode=0; @@ -89,23 +80,23 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(4,("Opening pipe %s.\n", fname)); - /* Strip \PIPE\ off the name. */ - pstrcpy(fname,smb_buf(inbuf) + PIPELEN); - /* See if it is one we want to handle. */ - for( i = 0; known_pipes[i] ; i++ ) - if( strcmp(fname,known_pipes[i]) == 0 ) + for( i = 0; pipe_names[i].client_pipe ; i++ ) + if( strcmp(fname,pipe_names[i].client_pipe) == 0 ) break; - if ( known_pipes[i] == NULL ) + if ( pipe_names[i].client_pipe == NULL ) return(ERROR(ERRSRV,ERRaccess)); + /* Strip \PIPE\ off the name. */ + pstrcpy(fname,smb_buf(inbuf) + PIPELEN); + /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); smb_ofun |= 0x10; /* Add Create it not exists flag */ - pnum = open_rpc_pipe_hnd(fname, cnum); + pnum = open_rpc_pipe_hnd(fname, cnum, vuid); if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); /* Prepare the reply */ @@ -133,190 +124,65 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** - reply to a close -****************************************************************************/ -int reply_pipe_close(char *inbuf,char *outbuf) -{ - int pnum = get_rpc_pipe_num(inbuf,smb_vwv0); - int cnum = SVAL(inbuf,smb_tid); - int outsize = set_message(outbuf,0,0,True); - - DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum)); - - if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid)); - - return(outsize); -} - - -/**************************************************************************** - api_LsarpcSNPHS + reply to a read and X - SetNamedPipeHandleState on \PIPE\lsarpc. + This code is basically stolen from reply_read_and_X with some + wrinkles to handle pipes. ****************************************************************************/ -BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param) +int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - uint16 id; + int pnum = get_rpc_pipe_num(inbuf,smb_vwv2); + uint32 smb_offs = IVAL(inbuf,smb_vwv3); + int smb_maxcnt = SVAL(inbuf,smb_vwv5); + int smb_mincnt = SVAL(inbuf,smb_vwv6); + int cnum; + int nread = -1; + char *data; + BOOL ok = False; - if (!param) return False; + cnum = SVAL(inbuf,smb_tid); - id = param[0] + (param[1] << 8); - DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id)); - - return set_rpc_pipe_hnd_state(pnum, cnum, id); -} - - -/**************************************************************************** - api_LsarpcTNP - - TransactNamedPipe on \PIPE\lsarpc. -****************************************************************************/ -static void LsarpcTNP1(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1, dword2; - char pname[] = "\\PIPE\\lsass"; +/* + CHECK_FNUM(fnum,cnum); + CHECK_READ(fnum); + CHECK_ERROR(fnum); +*/ - /* All kinds of mysterious numbers here */ - *rdata_len = 68; - *rdata = REALLOC(*rdata,*rdata_len); + set_message(outbuf,12,0,True); + data = smb_buf(outbuf); - dword1 = IVAL(data,0xC); - dword2 = IVAL(data,0x10); + nread = read_pipe(pnum, data, smb_offs, smb_maxcnt); - SIVAL(*rdata,0,0xc0005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x44); - SIVAL(*rdata,0xC,dword1); + ok = True; - SIVAL(*rdata,0x10,dword2); - SIVAL(*rdata,0x14,0x15); - SSVAL(*rdata,0x18,sizeof(pname)); - strcpy(*rdata + 0x1a,pname); - SIVAL(*rdata,0x28,1); - memcpy(*rdata + 0x30, data + 0x34, 0x14); -} - -static void LsarpcTNP2(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - - /* All kinds of mysterious numbers here */ - *rdata_len = 48; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x30); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x18); - SIVAL(*rdata,0x1c,0x44332211); - SIVAL(*rdata,0x20,0x88776655); - SIVAL(*rdata,0x24,0xCCBBAA99); - SIVAL(*rdata,0x28,0x11FFEEDD); -} - -static void LsarpcTNP3(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - uint16 word1; - char * workgroup = myworkgroup; - int wglen = strlen(workgroup); - int i; - - /* All kinds of mysterious numbers here */ - *rdata_len = 90 + 2 * wglen; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - word1 = SVAL(data,0x2C); - - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x60); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x48); - SSVAL(*rdata,0x18,0x5988); /* This changes */ - SSVAL(*rdata,0x1A,0x15); - SSVAL(*rdata,0x1C,word1); - SSVAL(*rdata,0x20,6); - SSVAL(*rdata,0x22,8); - SSVAL(*rdata,0x24,0x8E8); /* So does this */ - SSVAL(*rdata,0x26,0x15); - SSVAL(*rdata,0x28,0x4D48); /* And this */ - SSVAL(*rdata,0x2A,0x15); - SIVAL(*rdata,0x2C,4); - SIVAL(*rdata,0x34,wglen); - for ( i = 0 ; i < wglen ; i++ ) - (*rdata)[0x38 + i * 2] = workgroup[i]; - - /* Now fill in the rest */ - i = 0x38 + wglen * 2; - SSVAL(*rdata,i,0x648); - SIVAL(*rdata,i+2,4); - SIVAL(*rdata,i+6,0x401); - SSVAL(*rdata,i+0xC,0x500); - SIVAL(*rdata,i+0xE,0x15); - SIVAL(*rdata,i+0x12,0x2372FE1); - SIVAL(*rdata,i+0x16,0x7E831BEF); - SIVAL(*rdata,i+0x1A,0x4B454B2); -} - -static void LsarpcTNP4(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - - /* All kinds of mysterious numbers here */ - *rdata_len = 48; - *rdata = REALLOC(*rdata,*rdata_len); + if (nread < 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(smb_buf(outbuf),-2,nread); + + DEBUG(3,("%s readX pnum=%04x cnum=%d min=%d max=%d nread=%d\n", + timestring(),pnum,cnum, + smb_mincnt,smb_maxcnt,nread)); - dword1 = IVAL(data,0xC); + set_chain_pnum(pnum); - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x30); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x18); + return chain_reply(inbuf,outbuf,length,bufsize); } - - -BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +/**************************************************************************** + reply to a close +****************************************************************************/ +int reply_pipe_close(char *inbuf,char *outbuf) { - uint32 id,id2; + int pnum = get_rpc_pipe_num(inbuf,smb_vwv0); + int cnum = SVAL(inbuf,smb_tid); + int outsize = set_message(outbuf,0,0,True); - id = IVAL(data,0); + DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum)); - DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id)); - switch (id) - { - case 0xb0005: - LsarpcTNP1(data,rdata,rdata_len); - break; + if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid)); - case 0x03000005: - id2 = IVAL(data,8); - DEBUG(4,("\t- Suboperation %lx\n",id2)); - switch (id2 & 0xF) - { - case 8: - LsarpcTNP2(data,rdata,rdata_len); - break; - - case 0xC: - LsarpcTNP4(data,rdata,rdata_len); - break; - - case 0xE: - LsarpcTNP3(data,rdata,rdata_len); - break; - } - break; - } - return(True); + return(outsize); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 38380180f9..74cfd797c3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -366,6 +366,74 @@ int reply_ioctl(char *inbuf,char *outbuf) #endif } +/**************************************************************************** + always return an error: it's just a matter of which one... + ****************************************************************************/ +static int session_trust_account(char *inbuf, char *outbuf, char *user, + char *smb_passwd, int smb_passlen, + char *smb_nt_passwd, int smb_nt_passlen) +{ + struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ + if (lp_security() == SEC_USER) + { + smb_trust_acct = get_smbpwd_entry(user, 0); + } + else + { + DEBUG(3,("Trust account %s only supported with security = user\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } + + if (smb_trust_acct == NULL) + { + /* lkclXXXX: workstation entry doesn't exist */ + DEBUG(4,("Trust account %s user doesn't exist\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER)); + } + else + { + if ((smb_passlen != 24) || (smb_nt_passlen != 24)) + { + DEBUG(4,("Trust account %s - password length wrong.\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } + + if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd)) + { + DEBUG(4,("Trust Account %s - password failed\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } + + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST)) + { + DEBUG(4,("Domain trust account %s denied by server\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); + } + + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST)) + { + DEBUG(4,("Server trust account %s denied by server\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); + } + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST)) + { + DEBUG(4,("Wksta trust account %s denied by server\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); + } + } + + /* don't know what to do: indicate logon failure */ + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); +} + /**************************************************************************** reply to a session setup command @@ -386,7 +454,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL valid_nt_password = False; pstring user; BOOL guest=False; - BOOL computer_id=False; static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; @@ -496,48 +563,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* If name ends in $ then I think it's asking about whether a */ /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ - if (user[strlen(user) - 1] == '$') + if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) { -#ifdef NTDOMAIN - struct smb_passwd *smb_pass; /* To check if machine account exists */ -/* - PAXX: Ack. We don't want to do this. The workstation trust account - with a $ on the end should exist in the local password database - or be mapped to something generic, but not modified. For NT - domain support we must reject this used in certain circumstances - with a code to indicate to the client that it is an invalid use - of a workstation trust account. NTWKS needs this error to join - a domain. This may be the source of future bugs if we cannot - be sure whether to reject this or not. -*/ - /* non-null user name indicates search by username not by smb userid */ - smb_pass = get_smbpwd_entry(user, 0); - - if (!smb_pass) - { - /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */ - DEBUG(4,("Workstation trust account %s doesn't exist.",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */ - } - else - { - /* PAXX: This is the NO LOGON workstation trust account stuff */ - /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */ - DEBUG(4,("No Workstation trust account %s",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */ - } - - computer_id = True; -#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */ - user[strlen(user) - 1] = '\0'; -#endif + return session_trust_account(inbuf, outbuf, user, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen); } - /* If no username is sent use the guest account */ if (!*user) { @@ -583,7 +615,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) { - if (!computer_id && lp_security() >= SEC_USER) { + if (lp_security() >= SEC_USER) { #if (GUEST_SESSSETUP == 0) return(ERROR(ERRSRV,ERRbadpw)); #endif @@ -643,7 +675,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) uid = pw->pw_uid; } - if (guest && !computer_id) + if (guest) SSVAL(outbuf,smb_vwv2,1); /* register the name and uid as being validated, so further connections diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e290027d0a..774e5c10b9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3955,7 +3955,7 @@ reply for the nt protocol int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ; + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS; /* other valid capabilities which we may support at some time... CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; @@ -5190,10 +5190,8 @@ static void init_structs(void ) /* for RPC pipes */ init_rpc_pipe_hnd(); -#ifdef NTDOMAIN /* for LSA handles */ init_lsa_policy_hnd(); -#endif init_dptrs(); } -- cgit From e13f143ec6c46a1a540339d0a48940c6312ae8d9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Mar 1998 23:20:26 +0000 Subject: Missed fixes in NTDOM branch for doing readX via pipe IPC$. Allows long share lists to be browsed. Browsing *into* a long share name still fails, though. (Luke - you may need to look into this). Jeremy. (This used to be commit 5299d1b49f2bfd6cf84a687548904206f4a18a41) --- source3/smbd/reply.c | 4 ++++ source3/smbd/server.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 74cfd797c3..1415d95522 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1954,6 +1954,10 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) cnum = SVAL(inbuf,smb_tid); + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(cnum)) + return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); + CHECK_FNUM(fnum,cnum); CHECK_READ(fnum); CHECK_ERROR(fnum); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 774e5c10b9..86b76454e4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4684,7 +4684,7 @@ struct smb_message_struct {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, - {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER}, + {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER}, {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, -- cgit From 930230181d6b5972156bf4da8880fd2424838071 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Mar 1998 02:14:29 +0000 Subject: report the max size of raw reads as 65536 not 65535 (this now matches what Win95 reports) (This used to be commit a4c6884f43233d57a5f6465f67c4657dd061ae43) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 86b76454e4..7bce748878 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4014,7 +4014,7 @@ int reply_nt1(char *outbuf) SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ - SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */ + SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ put_long_date(outbuf+smb_vwv11+1,t); -- cgit From 4389fba6c3c77a1f1ff7c3c8c85ab483acba77f9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Mar 1998 02:15:32 +0000 Subject: use FSTYPE_STRING not "SAMBA" for filesystem type (This used to be commit df62c80e1d04059905b8a3c5bf9073ba91331e99) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1415d95522..83a4293fad 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -308,7 +308,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { - char *fsname = "SAMBA"; + char *fsname = FSTYPE_STRING; char *p; set_message(outbuf,3,3,True); -- cgit From 2e68682069ff72096f341b2fd3079aadf7c70a2f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Mar 1998 02:43:46 +0000 Subject: move setup_groups() into password.c so that swat can link without including server.o (This used to be commit 67bb8835c76e3efc43de55493971fe2402c0d709) --- source3/smbd/password.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 83 ----------------------------------------------- 2 files changed, 86 insertions(+), 83 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b422dda36c..212d931e87 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -147,6 +147,92 @@ char *validated_username(uint16 vuid) return(vuser->name); } + +/**************************************************************************** +Setup the groups a user belongs to. +****************************************************************************/ +int setup_groups(char *user, int uid, int gid, int *p_ngroups, + int **p_igroups, gid_t **p_groups, + int **p_attrs) +{ + 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)); + } + } + else + { + int i,ngroups; + int *igroups; + int *attrs; + gid_t grp = 0; + ngroups = getgroups(0,&grp); + if (ngroups <= 0) + ngroups = 32; + igroups = (int *)malloc(sizeof(int)*ngroups); + attrs = (int *)malloc(sizeof(int)*ngroups); + for (i=0;i 0) + { + /* does getgroups return ints or gid_t ?? */ + static BOOL groups_use_ints = True; + + if (groups_use_ints && + ngroups == 1 && + SVAL(igroups,2) == 0x4242) + groups_use_ints = False; + + for (i=0;groups_use_ints && i 16000 || uid < 0 || uid > 16000) - DEBUG(0,("This is probably a problem with the account %s\n",user)); - } - } - else - { - int i,ngroups; - int *igroups; - int *attrs; - gid_t grp = 0; - ngroups = getgroups(0,&grp); - if (ngroups <= 0) - ngroups = 32; - igroups = (int *)malloc(sizeof(int)*ngroups); - attrs = (int *)malloc(sizeof(int)*ngroups); - for (i=0;i 0) - { - /* does getgroups return ints or gid_t ?? */ - static BOOL groups_use_ints = True; - - if (groups_use_ints && - ngroups == 1 && - SVAL(igroups,2) == 0x4242) - groups_use_ints = False; - - for (i=0;groups_use_ints && i Date: Sat, 14 Mar 1998 08:27:41 +0000 Subject: another makeover of loadparm to support new stuff in swat and testparm. In particular I added: - ability to optionally save default values of all parameters when calling lp_load(). This can then be used to save only non-default parameters in lp_dump(). This makes the saved smb.conf (and viewed parameters in testparm) much shorter - ability to not load ipc share in lp_load() - separators in parm_table[] so parameters can be grouped logically. - flag to mark parameters that are local but which should be also viewed as global as far as parameters editing is concerned (This used to be commit f9af35da26e58fb0b644b5f0169f1c212230047a) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3c54f388fe..b42ebd6c0f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3257,7 +3257,7 @@ BOOL reload_services(BOOL test) lp_killunused(snum_used); - ret = lp_load(servicesf,False); + ret = lp_load(servicesf,False,False,True); /* perhaps the config filename is now set */ if (!test) -- cgit From c063e9ec3e90508e846dd51e22a643c74c02f7c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 14 Mar 1998 12:57:58 +0000 Subject: added the ability to start/stop the server from SWAT. I needed to modify the way the pidfile is handled in nmbd and smbd to do this. Jeremy, you may wish to look at what I've done as it probably breaks the Whistle use of pidfiles. In particular I've removed the -f option and instead smbd and nmbd always create a pidfile in the lock directory. (This used to be commit 20bb22d61b986d2036c681fc33db60f2b2b3c1c7) --- source3/smbd/server.c | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b42ebd6c0f..ca4a95f59d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5144,9 +5144,6 @@ static void usage(char *pname) int port = SMB_PORT; int opt; extern char *optarg; - char pidFile[100]; - - *pidFile = '\0'; #ifdef NEED_AUTH_PARAMETERS set_auth_parameters(argc,argv); @@ -5200,9 +5197,6 @@ static void usage(char *pname) while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF) switch (opt) { - case 'f': - strncpy(pidFile, optarg, sizeof(pidFile)); - break; case 'O': strcpy(user_socket_options,optarg); break; @@ -5328,33 +5322,9 @@ static void usage(char *pname) mkdir(lp_lockdir(), 0755); } - if (*pidFile) - { - int fd; - char buf[20]; - - if ((fd = open(pidFile, -#ifdef O_NONBLOCK - O_NONBLOCK | -#endif - O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) - { - DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno))); - exit(1); - } - if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False) - { - DEBUG(0,("ERROR: smbd is already running\n")); - exit(1); - } - sprintf(buf, "%u\n", (unsigned int) getpid()); - if (write(fd, buf, strlen(buf)) < 0) - { - DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno))); - exit(1); - } - /* Leave pid file open & locked for the duration... */ - } + if (is_daemon) { + pidfile_create("smbd"); + } if (!open_sockets(is_daemon,port)) exit(1); -- cgit From d360320618fe3a7f53ac1f05ee3ac54323a03c82 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 15 Mar 1998 02:37:52 +0000 Subject: - added the ability to kill off individual connections from SWAT (from the status page) - split the claim_connection() code into its own file - fixed the claim_connection() code to lock the file when manipulating it - always claim a null connection at startup - fixed a bug in the pidfile code (This used to be commit abd4a17e21d12be3d1747e94ceb1915abaf135e3) --- source3/smbd/connection.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 186 ++------------------------------------ 2 files changed, 226 insertions(+), 181 deletions(-) create mode 100644 source3/smbd/connection.c (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c new file mode 100644 index 0000000000..610afbc3e5 --- /dev/null +++ b/source3/smbd/connection.c @@ -0,0 +1,221 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + connection claim routines + Copyright (C) Andrew Tridgell 1998 + + 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 connection_struct Connections[MAX_CONNECTIONS]; +extern fstring remote_machine; + +extern int DEBUGLEVEL; + +/**************************************************************************** +simple routines to do connection counting +****************************************************************************/ +BOOL yield_connection(int cnum,char *name,int max_connections) +{ + struct connect_record crec; + pstring fname; + int fd; + int mypid = getpid(); + int i; + + DEBUG(3,("Yielding connection to %d %s\n",cnum,name)); + + if (max_connections <= 0) + return(True); + + bzero(&crec,sizeof(crec)); + + pstrcpy(fname,lp_lockdir()); + trim_string(fname,"","/"); + + strcat(fname,"/"); + strcat(fname,name); + strcat(fname,".LCK"); + + fd = open(fname,O_RDWR); + if (fd == -1) { + DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno))); + return(False); + } + + if (fcntl_lock(fd,F_SETLKW,0,1,F_WRLCK)==False) { + DEBUG(0,("ERROR: can't get lock on %s\n", fname)); + return False; + } + + /* find the right spot */ + for (i=0;i=total_recs || + lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || + read(fd,&crec,sizeof(crec)) != sizeof(crec)) { + if (foundi < 0) foundi = i; + break; + } + + if (Clear && crec.pid && !process_exists(crec.pid)) { + lseek(fd,i*sizeof(crec),SEEK_SET); + bzero((void *)&crec,sizeof(crec)); + write(fd, &crec,sizeof(crec)); + if (foundi < 0) foundi = i; + continue; + } + if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) { + foundi=i; + if (!Clear) break; + } + } + + if (foundi < 0) { + DEBUG(3,("no free locks in %s\n",fname)); + if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + DEBUG(0,("ERROR: can't release lock on %s\n", fname)); + } + close(fd); + return(False); + } + + /* fill in the crec */ + bzero((void *)&crec,sizeof(crec)); + crec.magic = 0x280267; + crec.pid = getpid(); + crec.cnum = cnum; + if (cnum != -1) { + crec.uid = Connections[cnum].uid; + crec.gid = Connections[cnum].gid; + StrnCpy(crec.name,lp_servicename(SNUM(cnum)),sizeof(crec.name)-1); + } + crec.start = time(NULL); + + StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); + StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1); + + /* make our mark */ + if (lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) || + write(fd, &crec,sizeof(crec)) != sizeof(crec)) { + if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + DEBUG(0,("ERROR: can't release lock on %s\n", fname)); + } + close(fd); + return(False); + } + + if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + DEBUG(0,("ERROR: can't release lock on %s\n", fname)); + } + + close(fd); + return(True); +} diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ca4a95f59d..64b293336b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3312,7 +3312,6 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de connection_struct *pcon; BOOL guest = False; BOOL force = False; - static BOOL first_connection = True; strlower(service); @@ -3518,9 +3517,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de } if (lp_status(SNUM(cnum))) - claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection); - - first_connection = False; + claim_connection(cnum,"STATUS.",MAXSTATUS,False); } /* IS_IPC */ pcon->open = True; @@ -4213,183 +4210,6 @@ void close_cnum(int cnum, uint16 vuid) } -/**************************************************************************** -simple routines to do connection counting -****************************************************************************/ -BOOL yield_connection(int cnum,char *name,int max_connections) -{ - struct connect_record crec; - pstring fname; - FILE *f; - int mypid = getpid(); - int i; - - DEBUG(3,("Yielding connection to %d %s\n",cnum,name)); - - if (max_connections <= 0) - return(True); - - bzero(&crec,sizeof(crec)); - - pstrcpy(fname,lp_lockdir()); - standard_sub(cnum,fname); - trim_string(fname,"","/"); - - strcat(fname,"/"); - strcat(fname,name); - strcat(fname,".LCK"); - - f = fopen(fname,"r+"); - if (!f) - { - DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno))); - return(False); - } - - fseek(f,0,SEEK_SET); - - /* find a free spot */ - for (i=0;i=total_recs || - fseek(f,i*sizeof(crec),SEEK_SET) != 0 || - fread(&crec,sizeof(crec),1,f) != 1) - { - if (foundi < 0) foundi = i; - break; - } - - if (Clear && crec.pid && !process_exists(crec.pid)) - { - fseek(f,i*sizeof(crec),SEEK_SET); - bzero((void *)&crec,sizeof(crec)); - fwrite(&crec,sizeof(crec),1,f); - if (foundi < 0) foundi = i; - continue; - } - if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) - { - foundi=i; - if (!Clear) break; - } - } - - if (foundi < 0) - { - DEBUG(3,("no free locks in %s\n",fname)); - fclose(f); - return(False); - } - - /* fill in the crec */ - bzero((void *)&crec,sizeof(crec)); - crec.magic = 0x280267; - crec.pid = getpid(); - crec.cnum = cnum; - crec.uid = Connections[cnum].uid; - crec.gid = Connections[cnum].gid; - StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1); - crec.start = time(NULL); - - StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); - StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1); - - /* make our mark */ - if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 || - fwrite(&crec,sizeof(crec),1,f) != 1) - { - fclose(f); - return(False); - } - - fclose(f); - return(True); -} #if DUMP_CORE /******************************************************************* @@ -5347,6 +5167,10 @@ static void usage(char *pname) if(!open_oplock_ipc()) exit(1); + if (lp_status(-1)) { + claim_connection(-1,"STATUS.",MAXSTATUS,True); + } + process(); close_sockets(); -- cgit From 86f5105fbca56ab07f8a33e892fe656672600388 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 15 Mar 1998 03:06:50 +0000 Subject: - claim the null connection after the session request to mak sure we have the netbios name - fix another kill connection bug (This used to be commit c634b799874795d42dae28fb4440ea452dc89b1b) --- source3/smbd/reply.c | 4 ++++ source3/smbd/server.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 83a4293fad..b0550bba57 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -120,6 +120,10 @@ int reply_special(char *inbuf,char *outbuf) reload_services(True); reopen_logs(); + if (lp_status(-1)) { + claim_connection(-1,"STATUS.",MAXSTATUS,True); + } + break; case 0x89: /* session keepalive request diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 64b293336b..248a2cee5f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5167,10 +5167,6 @@ static void usage(char *pname) if(!open_oplock_ipc()) exit(1); - if (lp_status(-1)) { - claim_connection(-1,"STATUS.",MAXSTATUS,True); - } - process(); close_sockets(); -- cgit From 90cdd717f8352a3b3eacdc154dfb1f9ff2fabeaf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Mar 1998 18:31:09 +0000 Subject: includes.h: Addition of NetBSD 1.3 fix, fix for HPUX 9.x, 10.x zombie problem. password.c: Fix for Thursby to stop Dave clients failing in share mode security (this was their bug - they were interpreting the uid field in share mode which is explicitly denied by the spec but it's easier for us to fix it than them :-). Jeremy. (This used to be commit 39372d9e20803d32c0c5b87226a72b007978baad) --- source3/smbd/password.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 212d931e87..c0e89100ea 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -243,6 +243,10 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ + /* Ensure no vuid gets registered in share level security. */ + if(lp_security() == SEC_SHARE) + return UID_FIELD_INVALID; + #if 0 /* * After observing MS-Exchange services writing to a Samba share -- cgit From c54af0f8b20e3f93c59da6a817920e1de6c4a870 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Mar 1998 20:59:47 +0000 Subject: Adding the same change as was added to 1.9.18 branch to add the "name resolve order" parameter. source/Makefile: Re-ordered link for name resolve order code. source/clientgen.c: source/clientutil.c: Added calls to resolve_name(). source/includes.h: Added HPUX zombie fix. source/loadparm.c: Added new name resolve order parameter. source/namequery.c: Re-wrote to include parsing of lmhosts file, new resolve_name() function requested by John. source/nmbd.c: Tell resolve_name not to do WINS lookups if we are the WINS server. source/nmbd_lmhosts.c: Call lmhosts parsing functions in namequery.c source/password.c: Call resolve_name() to lookup security=server name. source/reply.c: source/time.c: source/trans2.c: "fake directory create times" fix from Jim Hague - hague@research.canon.com.au. source/util.c: Removed isalnum() test in Get_Hostname() that seems to cause problems on many systems. Jeremy. (This used to be commit 7f118970da7c43eaddcf92dc056d3e849f1e7d5c) --- source3/smbd/password.c | 9 ++++----- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 12 ++++++------ 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c0e89100ea..bb0aacac7e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1689,11 +1689,10 @@ struct cli_state *server_cryptkey(void) standard_sub_basic(desthost); strupper(desthost); - dest_ip = *interpret_addr2(desthost); - if (zero_ip(dest_ip)) { - DEBUG(1,("Can't resolve address for %s\n",p)); - continue; - } + if(!resolve_name( desthost, &dest_ip)) { + DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",p)); + continue; + } if (ismyip(dest_ip)) { DEBUG(1,("Password server loop - disabling password server %s\n",p)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b0550bba57..4d163d70a0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3965,7 +3965,7 @@ int reply_getattrE(char *inbuf,char *outbuf) /* Convert the times into dos times. Set create date to be last modify date as UNIX doesn't save this */ - put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf)); + put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3cd6c138c8..165df56af5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -385,7 +385,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l size = sbuf.st_size; mdate = sbuf.st_mtime; adate = sbuf.st_atime; - cdate = get_create_time(&sbuf); + cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))); if(mode & aDIR) size = 0; @@ -1204,7 +1204,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf)); + put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,size); @@ -1215,7 +1215,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; - put_dos_date2(pdata,0,get_create_time(&sbuf)); + put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,size); @@ -1233,7 +1233,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_BASIC_INFO: data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ - put_long_date(pdata,get_create_time(&sbuf)); + put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ @@ -1241,7 +1241,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, DEBUG(5,("SMB_QFBI - ")); { - time_t create_time = get_create_time(&sbuf); + time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))); DEBUG(5,("create: %s ", ctime(&create_time))); } DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); @@ -1297,7 +1297,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, break; case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,get_create_time(&sbuf)); + put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ -- cgit From f996885676f041437430bfd5843a3000611b0923 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 17 Mar 1998 12:31:43 +0000 Subject: this isn't a big commit, it just looks like it :-) I needed the client_name() and client_addr() functions in swat so I could tell who was connecting from where. The problem was that these functions didn't take a file descriptor parameter they just used the global "Client". So I needed to change all calls to pass a parameter ... lots of files. (This used to be commit a776058900a727591bd7b69debdaa25c0e31d693) --- source3/smbd/connection.c | 3 ++- source3/smbd/password.c | 22 +++++++++++----------- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 8 +++++--- 4 files changed, 19 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 610afbc3e5..5cf8b800f2 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -115,6 +115,7 @@ simple routines to do connection counting ****************************************************************************/ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) { + extern int Client; struct connect_record crec; pstring fname; int fd=-1; @@ -200,7 +201,7 @@ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) crec.start = time(NULL); StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); - StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1); + StrnCpy(crec.addr,client_addr(Client),sizeof(crec.addr)-1); /* make our mark */ if (lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) || diff --git a/source3/smbd/password.c b/source3/smbd/password.c index bb0aacac7e..ffa75d7d0b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1640,21 +1640,21 @@ BOOL check_hosts_equiv(char *user) fname = lp_hosts_equiv(); /* note: don't allow hosts.equiv on root */ - if (fname && *fname && (pass->pw_uid != 0)) - { - if (check_user_equiv(user,client_name(),fname)) - return(True); - } + if (fname && *fname && (pass->pw_uid != 0)) { + extern int Client; + if (check_user_equiv(user,client_name(Client),fname)) + return(True); + } if (lp_use_rhosts()) { char *home = get_home_dir(user); - if (home) - { - sprintf(rhostsfile, "%s/.rhosts", home); - if (check_user_equiv(user,client_name(),rhostsfile)) - return(True); - } + if (home) { + extern int Client; + sprintf(rhostsfile, "%s/.rhosts", home); + if (check_user_equiv(user,client_name(Client),rhostsfile)) + return(True); + } } return(False); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4d163d70a0..8afda69b32 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -57,7 +57,7 @@ static void overflow_attack(int len) { DEBUG(0,("%s: ERROR: Invalid password length %d\n", timestring(), len)); DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); - DEBUG(0,("Attack was from IP=%s\n", client_addr())); + DEBUG(0,("Attack was from IP=%s\n", client_addr(Client))); exit_server("possible attack"); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 248a2cee5f..f51342d0e5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2625,7 +2625,7 @@ static void process_smb(char *inbuf, char *outbuf) name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG(1,("%s Connection denied from %s\n", - timestring(),client_addr())); + timestring(),client_addr(Client))); send_smb(Client,(char *)buf); exit_server("connection denied"); } @@ -3597,10 +3597,11 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de } { + extern int Client; DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n", timestring(), remote_machine, - client_addr(), + client_addr(Client), lp_servicename(SNUM(cnum)),user, pcon->uid, pcon->gid, @@ -4143,6 +4144,7 @@ close a cnum ****************************************************************************/ void close_cnum(int cnum, uint16 vuid) { + extern int Client; DirCacheFlush(SNUM(cnum)); unbecome_user(); @@ -4155,7 +4157,7 @@ void close_cnum(int cnum, uint16 vuid) DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n", timestring(), - remote_machine,client_addr(), + remote_machine,client_addr(Client), lp_servicename(SNUM(cnum)))); yield_connection(cnum, -- cgit From da050244c305c1e03e2f3fb2ac02f6bc93ad47ca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Mar 1998 19:07:53 +0000 Subject: Added SamOEMChangePassword functionality. Jeremy. (This used to be commit e02e3bcbbd4333113dde7bef47763fb229148007) --- source3/smbd/chgpasswd.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/ipc.c | 60 +++++++++++++++++++++++++ 2 files changed, 174 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index c83ff1911c..57d81ad756 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -493,3 +493,117 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi return ret; } + +/*********************************************************** + Code to check the OEM hashed password. +************************************************************/ + +BOOL check_oem_password(char *user, unsigned char *data, + struct smb_passwd **psmbpw, char *new_passwd, + int new_passwd_size) +{ + struct smb_passwd *smbpw = NULL; + int new_pw_len; + fstring upper_case_new_passwd; + unsigned char new_p16[16]; + unsigned char unenc_old_pw[16]; + + become_root(0); + *psmbpw = smbpw = get_smbpwd_entry(user, 0); + unbecome_root(0); + + if(smbpw == NULL) + { + DEBUG(0,("check_oem_password: get_smbpwd_entry returned NULL\n")); + return False; + } + + if(smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + return False; + } + + if(smbpw->smb_passwd == NULL) + { + DEBUG(0,("check_oem_password: no lanman password !\n")); + return False; + } + + /* + * Call the hash function to get the new password. + */ + SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd); + + /* + * The length of the new password is in the last 4 bytes of + * the data buffer. + */ + new_pw_len = IVAL(data,512); + if(new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { + DEBUG(0,("check_oem_password: incorrect password length.\n")); + return False; + } + + memcpy(new_passwd, &data[512-new_pw_len], new_pw_len); + new_passwd[new_pw_len] = '\0'; + + /* + * To ensure we got the correct new password, hash it and + * use it as a key to test the passed old password. + */ + + memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd)); + fstrcpy(upper_case_new_passwd, new_passwd); + strupper(upper_case_new_passwd); + + E_P16((uchar *)upper_case_new_passwd, new_p16); + + /* + * Now use new_p16 as the key to see if the old + * password matches. + */ + D_P16(new_p16, &data[516], unenc_old_pw); + + if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { + DEBUG(0,("check_oem_password: old password doesn't match.\n")); + return False; + } + + memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd)); + + return True; +} + +/*********************************************************** + Code to change the oem password. Changes both the lanman + and NT hashes. +************************************************************/ + +BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd) +{ + int ret; + fstring upper_case_new_passwd; + unsigned char new_nt_p16[16]; + unsigned char new_p16[16]; + + fstrcpy(upper_case_new_passwd, new_passwd); + strupper(upper_case_new_passwd); + + E_P16((uchar *)upper_case_new_passwd, new_p16); + + smbpw->smb_passwd = new_p16; + + E_md4hash((uchar *) new_passwd, new_nt_p16); + smbpw->smb_nt_passwd = new_nt_p16; + + /* Now write it into the file. */ + become_root(0); + ret = mod_smbpwd_entry(smbpw); + unbecome_root(0); + + memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd)); + memset(new_passwd, '\0', strlen(new_passwd)); + + return ret; +} diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index bbeeb21e96..89b3e36f52 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1662,6 +1662,65 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, return(True); } +/**************************************************************************** + Set the user password (SamOEM version - gets plaintext). +****************************************************************************/ + +static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + fstring user; + fstring new_passwd; + struct smb_passwd *smbpw = NULL; + char *p = param + 2; + + *rparam_len = 2; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_badpass); + + /* + * Check the parameter definition is correct. + */ + if(!strequal(param + 2, "zsT")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2)); + return False; + } + p = skip_string(p, 1); + + if(!strequal(p, "B516B16")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p)); + return False; + } + p = skip_string(p,1); + + fstrcpy(user,p); + p = skip_string(p,1); + + if(check_oem_password( user, data, &smbpw, new_passwd, sizeof(new_passwd)) == False) { + return True; + } + + /* + * At this point we have the new case-sensitive plaintext + * password in the fstring new_passwd. If we wanted to synchronise + * with UNIX passwords we would call a UNIX password changing + * function here. However it would have to be done as root + * as the plaintext of the old users password is not + * available. JRA. + */ + + if(change_oem_password( smbpw, new_passwd)) { + SSVAL(*rparam,0,NERR_Success); + } + + return(True); +} + /**************************************************************************** delete a print job Form: <> @@ -3410,6 +3469,7 @@ struct {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0}, {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0}, {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0}, + {"SamOEMChangePassword", 214, (BOOL (*)())api_SamOEMChangePassword,0}, {NULL, -1, (BOOL (*)())api_Unsupported,0}}; -- cgit From 7abbf368f908cacdb2978e33069e49755e54faa8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Mar 1998 20:06:47 +0000 Subject: Adding the same changes to HEAD as were added to BRANCH_1_9_18. Changed smbpasswd to be client-server for a normal user, rather than accessing the private/smbpasswd file directly (it still accesses this file directly when run as root, so root can add users/change a users password without knowing the old password). A shakeout of this change is that smbpasswd can now be used to change a users password on a remote NT machine (yep - you heard that one right - we can now change a NT password from UNIX !!!!!). Jeremy. (This used to be commit 20770b6f1c25288e90d3e0d215afa7f0809ce124) --- source3/smbd/chgpasswd.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 57d81ad756..779845d37a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -408,6 +408,7 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, { unsigned char unenc_new_pw[16]; unsigned char unenc_old_pw[16]; + unsigned char null_pw[16]; struct smb_passwd *smbpw; *psmbpw = NULL; @@ -428,8 +429,13 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, return False; } - if(smbpw->smb_passwd == NULL) + if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { + unsigned char no_pw[14]; + memset(no_pw, '\0', 14); + E_P16((uchar *)no_pw, (uchar *)null_pw); + smbpw->smb_passwd = null_pw; + } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("check_lanman_password: no lanman password !\n")); return False; } @@ -460,6 +466,7 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2) { unsigned char unenc_new_pw[16]; + unsigned char null_pw[16]; BOOL ret; if(smbpw == NULL) @@ -474,8 +481,13 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi return False; } - if(smbpw->smb_passwd == NULL) + if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { + unsigned char no_pw[14]; + memset(no_pw, '\0', 14); + E_P16((uchar *)no_pw, (uchar *)null_pw); + smbpw->smb_passwd = null_pw; + } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); return False; } @@ -507,6 +519,7 @@ BOOL check_oem_password(char *user, unsigned char *data, fstring upper_case_new_passwd; unsigned char new_p16[16]; unsigned char unenc_old_pw[16]; + unsigned char null_pw[16]; become_root(0); *psmbpw = smbpw = get_smbpwd_entry(user, 0); @@ -524,8 +537,13 @@ BOOL check_oem_password(char *user, unsigned char *data, return False; } - if(smbpw->smb_passwd == NULL) + if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { + unsigned char no_pw[14]; + memset(no_pw, '\0', 14); + E_P16((uchar *)no_pw, (uchar *)null_pw); + smbpw->smb_passwd = null_pw; + } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } @@ -533,7 +551,7 @@ BOOL check_oem_password(char *user, unsigned char *data, /* * Call the hash function to get the new password. */ - SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd); + SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd, True); /* * The length of the new password is in the last 4 bytes of @@ -541,7 +559,7 @@ BOOL check_oem_password(char *user, unsigned char *data, */ new_pw_len = IVAL(data,512); if(new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { - DEBUG(0,("check_oem_password: incorrect password length.\n")); + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } @@ -587,6 +605,7 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd) unsigned char new_nt_p16[16]; unsigned char new_p16[16]; + memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd)); fstrcpy(upper_case_new_passwd, new_passwd); strupper(upper_case_new_passwd); -- cgit From 4269286835ab3b6c5e23dcd369960ec94b5075f9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Mar 1998 21:44:30 +0000 Subject: Finally made OS/2 WP fix the default. Jeremy. (This used to be commit 7cc7a65dec917071d5df04b711acaf8824f13dd6) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f51342d0e5..08cf013920 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1790,7 +1790,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { unix_ERR_class = ERRDOS; /* OS/2 Workplace shell fix may be main code stream in a later release. */ -#ifdef OS2_WPS_FIX +#if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ unix_ERR_code = ERRcannotopen; #else /* OS2_WPS_FIX */ unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; -- cgit From 5d7c8375e4ffb017ef0f9eed7e619e533b3e8d12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Mar 1998 00:37:53 +0000 Subject: clientgen.c ipc.c smbpasswd.c: Fixes for warnings (from Herb). quotas.c: Linux quota fix. util.c: Ensure smb_read_error is zero in all calls that can set it. lib/rpc/include/rpc_misc.h lib/rpc/include/rpc_netlogon.h lib/rpc/parse/parse_misc.c lib/rpc/parse/parse_net.c lib/rpc/server/srv_netlog.c : Modify Luke's code to call SamOEMhash(). Jeremy. (This used to be commit 7f749708383b8b36c3f23a5fbc5cbdf39bc8e555) --- source3/smbd/ipc.c | 3 ++- source3/smbd/quotas.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 89b3e36f52..4798188454 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1701,7 +1701,8 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat fstrcpy(user,p); p = skip_string(p,1); - if(check_oem_password( user, data, &smbpw, new_passwd, sizeof(new_passwd)) == False) { + if(check_oem_password( user, (unsigned char *)data, &smbpw, + new_passwd, (int)sizeof(new_passwd)) == False) { return True; } diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 0a366e5ee6..df85f79b9b 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -115,6 +115,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) return(False); } else { + if (D.dqb_bsoftlimit == 0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; *dsize = D.dqb_bsoftlimit; } -- cgit From f52bb48748cf330d8d9a9c6350f53e84e4adaece Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Mar 1998 02:39:26 +0000 Subject: Fix for client generated core-dump bug where offset to readraw was so large that when used with -DUSE_MMAP it caused the unsigned subtraction to wrap aound and become positive - thus causing a silly memcpy offset. Thanks to "Michael St. Laurent" for giving me the core dump that allowed me to track this one down. Jeremy. (This used to be commit c9e066037ab222472085c4a0ecc8a39b337ad2aa) --- source3/smbd/server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 08cf013920..39580d008d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2058,7 +2058,8 @@ int read_file(int fnum,char *data,uint32 pos,int n) #if USE_MMAP if (Files[fnum].mmap_ptr) { - int num = MIN(n,(int)(Files[fnum].mmap_size-pos)); + int num = (Files[fnum].mmap_size > pos) ? (Files[fnum].mmap_size - pos) : -1; + num = MIN(n,num); if (num > 0) { memcpy(data,Files[fnum].mmap_ptr+pos,num); -- cgit From a4156f9b50c81fe40823cd8e32ec990690d3884c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Mar 1998 19:59:14 +0000 Subject: chgpasswd.c, ipc.c, loadparm.c: Added boolean "unix password sync" parameter which allows the new change password code to change the unix password also. Defaults to OFF. includes.h: Added termios.h to FreeBSD to allow password changing. namequery.c: Fixed missing name parameters to debug statements. Jeremy. (This used to be commit 4ac50c0f0aa5af084ddad89b1f9baf6c2c1ddcb8) --- source3/smbd/chgpasswd.c | 74 ++++++++++++++++++++++++++++++++++++------------ source3/smbd/ipc.c | 5 +++- 2 files changed, 60 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 779845d37a..ae1fd1a675 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -98,14 +98,22 @@ static int findpty(char **slave) return (-1); } -static int dochild(int master,char *slavedev, char *name, char *passwordprogram) +static int dochild(int master,char *slavedev, char *name, char *passwordprogram, BOOL as_root) { int slave; struct termios stermios; struct passwd *pass = Get_Pwnam(name,True); - int gid = pass->pw_gid; - int uid = pass->pw_uid; + int gid; + int uid; + if(pass == NULL) { + DEBUG(0,("dochild: user name %s doesn't exist in the UNIX password database.\n", + name)); + return False; + } + + gid = pass->pw_gid; + uid = pass->pw_uid; #ifdef USE_SETRES setresuid(0,0,0); #else /* USE_SETRES */ @@ -169,19 +177,21 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram) } /* make us completely into the right uid */ + if(!as_root) { #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); + setresgid(gid,gid,gid); + setresuid(uid,uid,uid); #else - setuid(0); - seteuid(0); - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); + setuid(0); + seteuid(0); + setgid(gid); + setegid(gid); + setuid(uid); + seteuid(uid); #endif + } /* execl() password-change application */ if (execl("/bin/sh","sh","-c",passwordprogram,NULL) < 0) { @@ -279,7 +289,7 @@ static int talktochild(int master, char *chatsequence) } -BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence) +BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root) { char *slavedev; int master; @@ -328,18 +338,25 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence) /* make sure it doesn't freeze */ alarm(20); + if(as_root) + become_root(False); DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,getuid(),getgid())); - chstat = dochild(master, slavedev, name, passwordprogram); + chstat = dochild(master, slavedev, name, passwordprogram, as_root); + + if(as_root) + unbecome_root(False); } DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); return (chstat); } -BOOL chgpasswd(char *name,char *oldpass,char *newpass) +BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; + int i; + int len; strlower(name); DEBUG(3,("Password change for user: %s\n",name)); @@ -381,6 +398,27 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass) return(False); } + /* + * Check the old and new passwords don't contain any control + * characters. + */ + + len = strlen(oldpass); + for(i = 0; i < len; i++) { + if(iscntrl(oldpass[i])) { + DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n")); + return False; + } + } + + len = strlen(newpass); + for(i = 0; i < len; i++) { + if(iscntrl(newpass[i])) { + DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n")); + return False; + } + } + string_sub(passwordprogram,"%u",name); string_sub(passwordprogram,"%o",oldpass); string_sub(passwordprogram,"%n",newpass); @@ -388,11 +426,11 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass) string_sub(chatsequence,"%u",name); string_sub(chatsequence,"%o",oldpass); string_sub(chatsequence,"%n",newpass); - return(chat_with_program(passwordprogram,name,chatsequence)); + return(chat_with_program(passwordprogram,name,chatsequence, as_root)); } #else -BOOL chgpasswd(char *name,char *oldpass,char *newpass) +BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) { DEBUG(0,("Password changing not compiled in (user=%s)\n",name)); return(False); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 4798188454..f38a76d74a 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1634,7 +1634,7 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, */ if (password_ok(user,pass1,strlen(pass1),NULL) && - chgpasswd(user,pass1,pass2)) + chgpasswd(user,pass1,pass2,False)) { SSVAL(*rparam,0,NERR_Success); } @@ -1714,6 +1714,9 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat * as the plaintext of the old users password is not * available. JRA. */ + + if(lp_unix_password_sync()) + chgpasswd(user,"", new_passwd, True); if(change_oem_password( smbpw, new_passwd)) { SSVAL(*rparam,0,NERR_Success); -- cgit From 6f1fc787de485b4899d9145a2225c22cf26c27a2 Mon Sep 17 00:00:00 2001 From: John Terpstra Date: Sun, 29 Mar 1998 05:34:03 +0000 Subject: Added remote machine and address to debug message in make_connection() function. contributor: (This used to be commit 7775b0f2aa43ee58f1a4f13004451235cfa157ef) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 39580d008d..7d9ca802e4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3325,7 +3325,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de return(-3); } - DEBUG(0,("%s couldn't find service %s\n",timestring(),service)); + DEBUG(0,("%s %s (%s) couldn't find service %s\n",timestring(),remote_machine,client_addr(),service)); return(-2); } -- cgit From 2a0b0873e3bd41ae961bffd3d6b59f8299ba2838 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Mar 1998 22:45:10 +0000 Subject: Fixed compile-time error introduced by log message change. Added support for 32bit error messages needed for NTDOM code (was in NTDOM branch, somehow missed during the merge). Jeremy. (This used to be commit 188fb28d7be5d466c86a7464f951d08941d0021f) --- source3/smbd/server.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7d9ca802e4..ca4326f14e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2326,13 +2326,21 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line) { int outsize = set_message(outbuf,0,0,True); - int cmd; - cmd = CVAL(inbuf,smb_com); - - CVAL(outbuf,smb_rcls) = error_class; - SSVAL(outbuf,smb_err,error_code); - - DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + int cmd = CVAL(inbuf,smb_com); + int flgs2 = SVAL(outbuf,smb_flg2); + + if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) + { + SIVAL(outbuf,smb_rcls,error_code); + + DEBUG(3,("%s 32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", + timestring(), line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf))); + } + else + { + CVAL(outbuf,smb_rcls) = error_class; + SSVAL(outbuf,smb_err,error_code); + DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", timestring(), line, (int)CVAL(inbuf,smb_com), @@ -2340,6 +2348,8 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int error_class, error_code)); + } + if (errno != 0) DEBUG(3,("error string = %s\n",strerror(errno))); @@ -3319,13 +3329,14 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de snum = find_service(service); if (snum < 0) { + extern int Client; if (strequal(service,"IPC$")) { DEBUG(3,("%s refusing IPC connection\n",timestring())); return(-3); } - DEBUG(0,("%s %s (%s) couldn't find service %s\n",timestring(),remote_machine,client_addr(),service)); + DEBUG(0,("%s %s (%s) couldn't find service %s\n",timestring(),remote_machine,client_addr(Client),service)); return(-2); } -- cgit From 10fe54befa10b283269001fdf779b9938c9a3a2c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 31 Mar 1998 20:55:14 +0000 Subject: includes.h: Added semaphore fix for HPUX10.x server.c trans2.c: Added oplock deadlock bug fix. lib/rpc/server/srv_netlog.c: Made code that changes machine account password the default. Jeremy. (This used to be commit 3b56fbc11e9d1cb7d4930d9782238c2610cac30d) --- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ca4326f14e..8166021fc2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4446,7 +4446,7 @@ struct smb_message_struct /* LANMAN2.0 PROTOCOL FOLLOWS */ {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK }, + {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER }, {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, /* messaging routines */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 165df56af5..75cf18785c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -33,6 +33,7 @@ extern int Client; extern int oplock_sock; extern int smb_read_error; extern fstring local_machine; +extern int global_oplock_break; /**************************************************************************** Send the required number of replies back. @@ -1743,6 +1744,19 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) char *params = NULL, *data = NULL; int num_params, num_params_sofar, num_data, num_data_sofar; + if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) + { + /* + * Queue this open message as we are the process of an oplock break. + */ + + DEBUG(2,("%s: reply_trans2: queueing message trans2open due to being in oplock break state.\n", + timestring() )); + + push_smb_message( inbuf, length); + return -1; + } + outsize = set_message(outbuf,0,0,True); /* All trans2 messages we handle have smb_sucnt == 1 - ensure this -- cgit From 724cab4d08d631c0afaac5e77356ca5336562eb0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Apr 1998 18:14:56 +0000 Subject: loadparm.c: Cause IPC$ comment to be evaluated at runtime, rather than load time (patch from "Marty Leisner" . server.c: Patch from Josef Hinteregger - string could be overwritten when find_service() called recursively. Jeremy. (This used to be commit cf15b3bd74a262e7af3d739a83ef7b43df4935e5) --- source3/smbd/server.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8166021fc2..d0b0304430 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2214,8 +2214,16 @@ int find_service(char *service) /* just possibly it's a default service? */ if (iService < 0) { - char *defservice = lp_defaultservice(); - if (defservice && *defservice && !strequal(defservice,service)) { + char *pdefservice = lp_defaultservice(); + if (pdefservice && *pdefservice && !strequal(pdefservice,service)) { + /* + * We need to do a local copy here as lp_defaultservice() + * returns one of the rotating lp_string buffers that + * could get overwritten by the recursive find_service() call + * below. Fix from Josef Hinteregger . + */ + pstring defservice; + pstrcpy(defservice, pdefservice); iService = find_service(defservice); if (iService >= 0) { string_sub(service,"_","/"); -- cgit From 1af95effe96284c30c0f3f1782677e8f1873ceca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Apr 1998 19:12:22 +0000 Subject: Fix to stop Windows 95 spinning on print queue requests when it gets an error message it doesn't understand. Jeremy. (This used to be commit 838e2fe2f76b20f34309c2322e3bd60817fef1fd) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f38a76d74a..6d0a8d55dd 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -456,7 +456,7 @@ va_dcl p->usedlen += needed; } else { - if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall; + if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA; } return 1; } -- cgit From d1cc06083dff66519d2a2418d7cce9916131a6da Mon Sep 17 00:00:00 2001 From: John Terpstra Date: Thu, 9 Apr 1998 14:13:20 +0000 Subject: Added const cast to struct args to get rid of compile time warning. (This used to be commit 5d956abb4f4ed22671dfb1c7cb51489ab280463f) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ffa75d7d0b..be032c5c38 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -468,7 +468,7 @@ static char *PAM_password; * echo off means password. */ static int PAM_conv (int num_msg, - struct pam_message **msg, + const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int replies = 0; -- cgit From af80d8e98f2f74939d680c6abc21e3f40b927f31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Apr 1998 20:48:48 +0000 Subject: Makefile, loadparm.c, server.c, smb.h, util.c: Patch from stn@techfak.uni-kiel.de (Stefan Nehlsen) to get homes from the NIS+ map. smbpasswd.c: Tidy up of cli_state structure. Jeremy. (This used to be commit fc2295e0f5729585fdb3ee47edb290851d4071c5) --- source3/smbd/server.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d0b0304430..01f9006a42 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -101,7 +101,7 @@ extern fstring remote_machine; extern pstring OriginalDir; /* these can be set by some functions to override the error codes */ -int unix_ERR_class=SUCCESS; +int unix_ERR_class=SMB_SUCCESS; int unix_ERR_code=0; @@ -2303,11 +2303,11 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int int ecode=def_code; int i=0; - if (unix_ERR_class != SUCCESS) + if (unix_ERR_class != SMB_SUCCESS) { eclass = unix_ERR_class; ecode = unix_ERR_code; - unix_ERR_class = SUCCESS; + unix_ERR_class = SMB_SUCCESS; unix_ERR_code = 0; } else @@ -4686,12 +4686,12 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com); memcpy(outbuf2+4,inbuf2+4,4); - CVAL(outbuf2,smb_rcls) = SUCCESS; + CVAL(outbuf2,smb_rcls) = SMB_SUCCESS; CVAL(outbuf2,smb_reh) = 0; CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set means a reply */ SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf2,smb_err,SUCCESS); + SSVAL(outbuf2,smb_err,SMB_SUCCESS); SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid)); SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid)); SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid)); @@ -4748,12 +4748,12 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) set_message(outbuf,0,0,True); memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SUCCESS; + CVAL(outbuf,smb_rcls) = SMB_SUCCESS; CVAL(outbuf,smb_reh) = 0; CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set means a reply */ SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf,smb_err,SUCCESS); + SSVAL(outbuf,smb_err,SMB_SUCCESS); SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); -- cgit From 31ae9c7013be791717f6e77794ce8c8fc1c1c16c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Apr 1998 01:19:18 +0000 Subject: Fix for [homes] problem with security=share. We were still relying on a valid vuid to get the connecting username - this is *never* true (anymore) with security=share. Jeremy. (This used to be commit 5d6f63a7e665ee19bd4508b2b40d497e9851b248) --- source3/smbd/server.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 01f9006a42..1d3c2e144c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3353,11 +3353,25 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de if (*user && Get_Pwnam(user,True)) return(make_connection(user,user,password,pwlen,dev,vuid)); - if (validated_username(vuid)) - { - strcpy(user,validated_username(vuid)); - return(make_connection(user,user,password,pwlen,dev,vuid)); - } + if(lp_security() != SEC_SHARE) + { + if (validated_username(vuid)) + { + strcpy(user,validated_username(vuid)); + return(make_connection(user,user,password,pwlen,dev,vuid)); + } + } + else + { + /* + * Security = share. Try with sesssetup_user as the username. + */ + if(*sesssetup_user) + { + strcpy(user,sesssetup_user); + return(make_connection(user,user,password,pwlen,dev,vuid)); + } + } } if (!lp_snum_ok(snum) || !check_access(snum)) { -- cgit From e300c0346ff92035ff9568b55b34469193e29769 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Apr 1998 18:21:16 +0000 Subject: includes.h: Moved HPUX undefine of SEMMSL to where it actually does something. ipc.c: Added Luke's debug statement. locking_slow.c: Added FTRUNCATE_NEEDS_ROOT code for broken systems that need it (not sure what these are yet). membuffer.c ntdomain.h proto.h lib/rpc/include/rpc_dce.h lib/rpc/include/rpc_srvsvc.h lib/rpc/parse/parse_prs.c lib/rpc/parse/parse_rpc.c lib/rpc/server/srv_pipe_hnd.c lib/rpc/server/srv_util.c: Re-merge of Luke's NTDOM changes 'cos he's a lazy git with carpel tunnel syndrome :-). Jeremy. (This used to be commit 52e3966fbcf7b5fbdbc7cbe9ac0b453ab5bf3217) --- source3/smbd/ipc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6d0a8d55dd..62951219bf 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3367,6 +3367,9 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, /* record maximum data length that can be transmitted in an SMBtrans */ p->max_rdata_len = mdrcnt; + DEBUG(10,("api_fd_reply: p:%p max_rdata_len: %d\n", + p, p->max_rdata_len)); + switch (subcommand) { case 0x26: -- cgit From 77da897307806830ecf36f0e4de41cf51d826e79 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 12 Apr 1998 02:52:13 +0000 Subject: support O_SYNC at open time in files (previously we only supported it on individual writes) (This used to be commit ce017a233ba5c68e340e0d31634f9bd93118b20a) --- source3/smbd/server.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1d3c2e144c..b86098f493 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1829,6 +1829,10 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, flags = O_RDONLY; break; } + + if (share_mode&(1<<14)) { + flags2 |= O_SYNC; + } if (flags != O_RDONLY && file_existed && (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) -- cgit From e40b24249bf7aec81737e16081548bf99fa8cc76 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Apr 1998 11:12:44 +0000 Subject: fixed a memory leak in close_file(). Each time a file was opened we leaked memory equal to the length of the filename. (This used to be commit 30a347de74f7f8e2646b1853a9e5914320cee58d) --- source3/smbd/server.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b86098f493..e0652d35c8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1514,6 +1514,13 @@ void close_file(int fnum, BOOL normal_close) DEBUG(2,("%s %s closed file %s (numopen=%d)\n", timestring(),Connections[cnum].user,fs_p->name, Connections[cnum].num_files_open)); + + if (fs_p->name) { + string_free(&fs_p->name); + } + + /* we will catch bugs faster by zeroing this structure */ + memset(fs_p, 0, sizeof(*fs_p)); } enum {AFAIL,AREAD,AWRITE,AALL}; @@ -4949,7 +4956,6 @@ static void init_structs(void ) { Files[i].open = False; string_init(&Files[i].name,""); - } for (i=0;i Date: Mon, 13 Apr 1998 19:24:06 +0000 Subject: Changes to allow Samba to be compiled with -Wstrict-prototypes with gcc. (Not a big change although it looks like it :-). Jeremy. (This used to be commit cd2613c57261456485fe4eeecfda209ada70de8e) --- source3/smbd/ipc.c | 58 +++++++++++++++++----------------- source3/smbd/message.c | 8 ++--- source3/smbd/password.c | 4 +-- source3/smbd/predict.c | 2 +- source3/smbd/reply.c | 83 ++++++++++++++++++++++++------------------------- source3/smbd/server.c | 16 +++++----- 6 files changed, 84 insertions(+), 87 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 62951219bf..e4ddcbec69 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3447,37 +3447,37 @@ struct { char *name; int id; - BOOL (*fn)(); + BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *); int flags; } api_commands[] = { - {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0}, - {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0}, - {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0}, - {"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0}, - {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0}, - {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0}, - {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0}, - {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0}, - {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0}, - {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0}, - {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0}, - {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0}, - {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0}, - {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0}, - {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0}, - {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0}, - {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0}, - {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0}, - {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0}, - {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0}, - {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0}, - {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0}, - {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0}, - {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0}, - {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0}, - {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0}, - {"SamOEMChangePassword", 214, (BOOL (*)())api_SamOEMChangePassword,0}, - {NULL, -1, (BOOL (*)())api_Unsupported,0}}; + {"RNetShareEnum", 0, api_RNetShareEnum,0}, + {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, + {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, + {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0}, + {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, + {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, + {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, + {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, + {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, + {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, + {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, + {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, + {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0}, + {"RDosPrintJobResume",83, api_RDosPrintJobDel,0}, + {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, + {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, + {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, + {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0}, + {"NetServerEnum", 104, api_RNetServerEnum,0}, + {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, + {"SetUserPassword", 115, api_SetUserPassword,0}, + {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0}, + {"PrintJobInfo", 147, api_PrintJobInfo,0}, + {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0}, + {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0}, + {"WPrintPortEnum", 207, api_WPrintPortEnum,0}, + {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0}, + {NULL, -1, api_Unsupported,0}}; /**************************************************************************** diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 8c3f6f6630..24477f31ff 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -90,7 +90,7 @@ static void msg_deliver(void) /**************************************************************************** reply to a sends ****************************************************************************/ -int reply_sends(char *inbuf,char *outbuf) +int reply_sends(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int len; char *orig,*dest,*msg; @@ -128,7 +128,7 @@ int reply_sends(char *inbuf,char *outbuf) /**************************************************************************** reply to a sendstrt ****************************************************************************/ -int reply_sendstrt(char *inbuf,char *outbuf) +int reply_sendstrt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { char *orig,*dest; int outsize = 0; @@ -155,7 +155,7 @@ int reply_sendstrt(char *inbuf,char *outbuf) /**************************************************************************** reply to a sendtxt ****************************************************************************/ -int reply_sendtxt(char *inbuf,char *outbuf) +int reply_sendtxt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int len; int outsize = 0; @@ -183,7 +183,7 @@ int reply_sendtxt(char *inbuf,char *outbuf) /**************************************************************************** reply to a sendend ****************************************************************************/ -int reply_sendend(char *inbuf,char *outbuf) +int reply_sendend(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index be032c5c38..74ebeb1617 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -819,7 +819,7 @@ 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 BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N) +static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(char *),int N) { int len = strlen(s); int i; @@ -850,7 +850,7 @@ 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 BOOL string_combinations(char *s,BOOL (*fn)(),int N) +static BOOL string_combinations(char *s,BOOL (*fn)(char *),int N) { int n; for (n=1;n<=N;n++) diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 862ba97f7e..6f6a4ca655 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -95,7 +95,7 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num) /**************************************************************************** pre-read some data ****************************************************************************/ -void do_read_prediction() +void do_read_prediction(void) { static int readsize = 0; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8afda69b32..d4ee8223ad 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -217,7 +217,7 @@ static void parse_connect(char *p,char *service,char *user, /**************************************************************************** reply to a tcon ****************************************************************************/ -int reply_tcon(char *inbuf,char *outbuf) +int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring service; pstring user; @@ -358,7 +358,7 @@ int reply_unknown(char *inbuf,char *outbuf) /**************************************************************************** reply to an ioctl ****************************************************************************/ -int reply_ioctl(char *inbuf,char *outbuf) +int reply_ioctl(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { DEBUG(3,("ignoring ioctl\n")); #if 0 @@ -703,7 +703,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a chkpth ****************************************************************************/ -int reply_chkpth(char *inbuf,char *outbuf) +int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; int cnum,mode; @@ -758,7 +758,7 @@ int reply_chkpth(char *inbuf,char *outbuf) /**************************************************************************** reply to a getatr ****************************************************************************/ -int reply_getatr(char *inbuf,char *outbuf) +int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; int cnum; @@ -838,7 +838,7 @@ int reply_getatr(char *inbuf,char *outbuf) /**************************************************************************** reply to a setatr ****************************************************************************/ -int reply_setatr(char *inbuf,char *outbuf) +int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; int cnum; @@ -885,7 +885,7 @@ int reply_setatr(char *inbuf,char *outbuf) /**************************************************************************** reply to a dskattr ****************************************************************************/ -int reply_dskattr(char *inbuf,char *outbuf) +int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum; int outsize = 0; @@ -912,7 +912,7 @@ int reply_dskattr(char *inbuf,char *outbuf) reply to a search Can be called from SMBsearch, SMBffirst or SMBfunique. ****************************************************************************/ -int reply_search(char *inbuf,char *outbuf) +int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring mask; pstring directory; @@ -1158,7 +1158,7 @@ int reply_search(char *inbuf,char *outbuf) /**************************************************************************** reply to a fclose (stop directory search) ****************************************************************************/ -int reply_fclose(char *inbuf,char *outbuf) +int reply_fclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum; int outsize = 0; @@ -1195,7 +1195,7 @@ int reply_fclose(char *inbuf,char *outbuf) /**************************************************************************** reply to an open ****************************************************************************/ -int reply_open(char *inbuf,char *outbuf) +int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; int cnum; @@ -1448,7 +1448,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a mknew or a create ****************************************************************************/ -int reply_mknew(char *inbuf,char *outbuf) +int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; int cnum,com; @@ -1538,7 +1538,7 @@ int reply_mknew(char *inbuf,char *outbuf) /**************************************************************************** reply to a create temporary file ****************************************************************************/ -int reply_ctemp(char *inbuf,char *outbuf) +int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; pstring fname2; @@ -1638,7 +1638,7 @@ static BOOL can_delete(char *fname,int cnum,int dirtype) /**************************************************************************** reply to a unlink ****************************************************************************/ -int reply_unlink(char *inbuf,char *outbuf) +int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; pstring name; @@ -1743,7 +1743,7 @@ int reply_unlink(char *inbuf,char *outbuf) /**************************************************************************** reply to a readbraw (core+ protocol) ****************************************************************************/ -int reply_readbraw(char *inbuf, char *outbuf) +int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { int cnum,maxcount,mincount,fnum; int nread = 0; @@ -1853,7 +1853,7 @@ int reply_readbraw(char *inbuf, char *outbuf) /**************************************************************************** reply to a lockread (core+ protocol) ****************************************************************************/ -int reply_lockread(char *inbuf,char *outbuf) +int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) { int cnum,fnum; int nread = -1; @@ -1899,7 +1899,7 @@ int reply_lockread(char *inbuf,char *outbuf) /**************************************************************************** reply to a read ****************************************************************************/ -int reply_read(char *inbuf,char *outbuf) +int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,numtoread,fnum; int nread = 0; @@ -1994,7 +1994,7 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a writebraw (core+ or LANMAN1.0 protocol) ****************************************************************************/ -int reply_writebraw(char *inbuf,char *outbuf) +int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int nwritten=0; int total_written=0; @@ -2101,7 +2101,7 @@ int reply_writebraw(char *inbuf,char *outbuf) /**************************************************************************** reply to a writeunlock (core+) ****************************************************************************/ -int reply_writeunlock(char *inbuf,char *outbuf) +int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,fnum; int nwritten = -1; @@ -2158,7 +2158,7 @@ int reply_writeunlock(char *inbuf,char *outbuf) /**************************************************************************** reply to a write ****************************************************************************/ -int reply_write(char *inbuf,char *outbuf,int dum1,int dum2) +int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) { int cnum,numtowrite,fnum; int nwritten = -1; @@ -2166,9 +2166,6 @@ int reply_write(char *inbuf,char *outbuf,int dum1,int dum2) int startpos; char *data; - dum1 = dum2 = 0; - - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); @@ -2276,7 +2273,7 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a lseek ****************************************************************************/ -int reply_lseek(char *inbuf,char *outbuf) +int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,fnum; uint32 startpos; @@ -2317,7 +2314,7 @@ int reply_lseek(char *inbuf,char *outbuf) /**************************************************************************** reply to a flush ****************************************************************************/ -int reply_flush(char *inbuf,char *outbuf) +int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum, fnum; int outsize = set_message(outbuf,0,0,True); @@ -2348,7 +2345,7 @@ int reply_flush(char *inbuf,char *outbuf) /**************************************************************************** reply to a exit ****************************************************************************/ -int reply_exit(char *inbuf,char *outbuf) +int reply_exit(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); DEBUG(3,("%s exit\n",timestring())); @@ -2360,7 +2357,7 @@ int reply_exit(char *inbuf,char *outbuf) /**************************************************************************** reply to a close ****************************************************************************/ -int reply_close(char *inbuf,char *outbuf) +int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int fnum,cnum; int outsize = 0; @@ -2406,7 +2403,7 @@ int reply_close(char *inbuf,char *outbuf) /**************************************************************************** reply to a writeclose (Core+ protocol) ****************************************************************************/ -int reply_writeclose(char *inbuf,char *outbuf) +int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,numtowrite,fnum; int nwritten = -1; @@ -2455,7 +2452,7 @@ int reply_writeclose(char *inbuf,char *outbuf) /**************************************************************************** reply to a lock ****************************************************************************/ -int reply_lock(char *inbuf,char *outbuf) +int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int fnum,cnum; int outsize = set_message(outbuf,0,0,True); @@ -2484,7 +2481,7 @@ int reply_lock(char *inbuf,char *outbuf) /**************************************************************************** reply to a unlock ****************************************************************************/ -int reply_unlock(char *inbuf,char *outbuf) +int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int fnum,cnum; int outsize = set_message(outbuf,0,0,True); @@ -2513,7 +2510,7 @@ int reply_unlock(char *inbuf,char *outbuf) /**************************************************************************** reply to a tdis ****************************************************************************/ -int reply_tdis(char *inbuf,char *outbuf) +int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum; int outsize = set_message(outbuf,0,0,True); @@ -2541,7 +2538,7 @@ int reply_tdis(char *inbuf,char *outbuf) /**************************************************************************** reply to a echo ****************************************************************************/ -int reply_echo(char *inbuf,char *outbuf) +int reply_echo(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum; int smb_reverb = SVAL(inbuf,smb_vwv0); @@ -2591,7 +2588,7 @@ int reply_echo(char *inbuf,char *outbuf) /**************************************************************************** reply to a printopen ****************************************************************************/ -int reply_printopen(char *inbuf,char *outbuf) +int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; pstring fname2; @@ -2658,7 +2655,7 @@ int reply_printopen(char *inbuf,char *outbuf) /**************************************************************************** reply to a printclose ****************************************************************************/ -int reply_printclose(char *inbuf,char *outbuf) +int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int fnum,cnum; int outsize = set_message(outbuf,0,0,True); @@ -2683,7 +2680,7 @@ int reply_printclose(char *inbuf,char *outbuf) /**************************************************************************** reply to a printqueue ****************************************************************************/ -int reply_printqueue(char *inbuf,char *outbuf) +int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum; int outsize = set_message(outbuf,2,3,True); @@ -2777,7 +2774,7 @@ int reply_printqueue(char *inbuf,char *outbuf) /**************************************************************************** reply to a printwrite ****************************************************************************/ -int reply_printwrite(char *inbuf,char *outbuf) +int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,numtowrite,fnum; int outsize = set_message(outbuf,0,0,True); @@ -2809,7 +2806,7 @@ int reply_printwrite(char *inbuf,char *outbuf) /**************************************************************************** reply to a mkdir ****************************************************************************/ -int reply_mkdir(char *inbuf,char *outbuf) +int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring directory; int cnum; @@ -2904,7 +2901,7 @@ static BOOL recursive_rmdir(char *directory) /**************************************************************************** reply to a rmdir ****************************************************************************/ -int reply_rmdir(char *inbuf,char *outbuf) +int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring directory; int cnum; @@ -3096,7 +3093,7 @@ static BOOL can_rename(char *fname,int cnum) /**************************************************************************** reply to a mv ****************************************************************************/ -int reply_mv(char *inbuf,char *outbuf) +int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; pstring name; @@ -3351,7 +3348,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, /**************************************************************************** reply to a file copy. ****************************************************************************/ -int reply_copy(char *inbuf,char *outbuf) +int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; pstring name; @@ -3485,7 +3482,7 @@ int reply_copy(char *inbuf,char *outbuf) /**************************************************************************** reply to a setdir ****************************************************************************/ -int reply_setdir(char *inbuf,char *outbuf) +int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,snum; int outsize = 0; @@ -3714,7 +3711,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a SMBwritebmpx (write block multiplex primary) request ****************************************************************************/ -int reply_writebmpx(char *inbuf,char *outbuf) +int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,numtowrite,fnum; int nwritten = -1; @@ -3807,7 +3804,7 @@ int reply_writebmpx(char *inbuf,char *outbuf) /**************************************************************************** reply to a SMBwritebs (write block multiplex secondary) request ****************************************************************************/ -int reply_writebs(char *inbuf,char *outbuf) +int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,numtowrite,fnum; int nwritten = -1; @@ -3888,7 +3885,7 @@ int reply_writebs(char *inbuf,char *outbuf) /**************************************************************************** reply to a SMBsetattrE ****************************************************************************/ -int reply_setattrE(char *inbuf,char *outbuf) +int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,fnum; struct utimbuf unix_times; @@ -3941,7 +3938,7 @@ not setting timestamps of 0\n", /**************************************************************************** reply to a SMBgetattrE ****************************************************************************/ -int reply_getattrE(char *inbuf,char *outbuf) +int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int cnum,fnum; struct stat sbuf; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e0652d35c8..7216ae79bb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1060,7 +1060,7 @@ static file_fd_struct *fd_get_already_open(struct stat *sbuf) fd support routines - attempt to find a empty slot in the FileFd array. Increments the ref_count of the returned entry. ****************************************************************************/ -static file_fd_struct *fd_get_new() +static file_fd_struct *fd_get_new(void) { int i; file_fd_struct *fd_ptr; @@ -2380,7 +2380,7 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int /**************************************************************************** this prevents zombie child processes ****************************************************************************/ -static int sig_cld() +static int sig_cld(void) { static int depth = 0; if (depth != 0) @@ -2425,7 +2425,7 @@ static int sig_cld() /**************************************************************************** this is called when the client exits abruptly **************************************************************************/ -static int sig_pipe() +static int sig_pipe(void) { struct cli_state *cli; BlockSignals(True,SIGPIPE); @@ -2698,7 +2698,7 @@ static void process_smb(char *inbuf, char *outbuf) /**************************************************************************** open the oplock IPC socket communication ****************************************************************************/ -static BOOL open_oplock_ipc() +static BOOL open_oplock_ipc(void) { struct sockaddr_in sock_name; int len = sizeof(sock_name); @@ -3318,7 +3318,7 @@ BOOL reload_services(BOOL test) /**************************************************************************** this prevents zombie child processes ****************************************************************************/ -static int sig_hup() +static int sig_hup(void) { BlockSignals(True,SIGHUP); DEBUG(0,("Got SIGHUP\n")); @@ -4066,7 +4066,7 @@ struct { /**************************************************************************** reply to a negprot ****************************************************************************/ -static int reply_negprot(char *inbuf,char *outbuf) +static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(outbuf,1,0,True); int Index=0; @@ -4392,7 +4392,7 @@ struct smb_message_struct { int code; char *name; - int (*fn)(); + int (*fn)(char *, char *, int, int); int flags; #if PROFILING unsigned long time; @@ -5042,7 +5042,7 @@ static void usage(char *pname) seteuid(0); #endif - fault_setup(exit_server); + fault_setup((void (*)(void *))exit_server); signal(SIGTERM , SIGNAL_CAST dflt_sig); /* we want total control over the permissions on created files, -- cgit From d5e040247e180664bd32a0d7d8dd905f46cbdb47 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Mon, 13 Apr 1998 22:45:52 +0000 Subject: Changes include: proto.h: The unusual. ;) reply.c: I changes some function names, and updated reply.c to match. See mangle.c below for more. server.c: Changed function names and parameters in file mangle.c, so changed server.c calls to match. See mangle.c below for more. mangle.c: I replaced the caching mechanism used for caching reverse mangled name maps. The old method was a large array of 256-byte strings. Movement in the stack (including push and pop) was done by memcpy()ing whole chunks of memory around. The new system uses the ubi_Cache module which, in turn, uses a splay tree. Entries are dynamically allocated using a minimum amount of memory. Searches are non-linear, which should speed things up a bit, too. Overall, this should save memory and be faster. Other changes: I streamlined the is_mangled() test and made other speed enhancements including replacing some static functions with macros. Added comments, etc. Note: Per an E'mail conversation with Andrew, the 'mangled stack' parameter in smb.conf doesn't do anything anymore. The cache is now set for 16K bytes maximum memory usage. The mangle stack parameter is silently ignored. This can easily be changed, but I'd rather introduce a 'mangled cache memory' parameter and remove 'mangled stack'. Remaining problems: While testing the module, I noticed that something is calling name_map_mangle() twice. The result is that names which contain illegal characters are getting mangled twice. Also, the entire module works by overwriting the input string. This has a variety of nasty side effects. Summary: There's a lot still to be done, but the changes I have in place *should* work in exactly the same way (except for the mangle stack parameter). The rest of the bugs and other issues are separate. Chris -)----- (This used to be commit 8759bec11ba483b2292b0e513b85c98ed5e3e2d4) --- source3/smbd/mangle.c | 1103 +++++++++++++++++++++++++++++++------------------ source3/smbd/reply.c | 6 +- source3/smbd/server.c | 6 +- 3 files changed, 700 insertions(+), 415 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 8aa53bc35a..f4e39ef982 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -19,39 +19,159 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* -------------------------------------------------------------------------- ** + * Notable problems... + * + * March/April 1998 CRH + * - Many of the functions in this module overwrite string buffers passed to + * them. This causes a variety of problems and is, generally speaking, + * dangerous and scarry. See the kludge notes in name_map_mangle() + * below. + * - It seems that something is calling name_map_mangle() twice. The + * first call is probably some sort of test. Names which contain + * illegal characters are being doubly mangled. I'm not sure, but + * I'm guessing the problem is in server.c. + * + * -------------------------------------------------------------------------- ** + */ + +/* -------------------------------------------------------------------------- ** + * History... + * + * March/April 1998 CRH + * Updated a bit. Rewrote is_mangled() to be a bit more selective. + * Rewrote the mangled name cache. Added comments here and there. + * &c. + * -------------------------------------------------------------------------- ** + */ + #include "includes.h" +#include "ubiqx/ubi_Cache.h" -extern int DEBUGLEVEL; -extern int case_default; -extern BOOL case_mangle; -/**************************************************************************** - * Provide a checksum on a string +/* -------------------------------------------------------------------------- ** + * External Variables... + */ + +extern int DEBUGLEVEL; /* Global debug level. */ +extern int case_default; /* Are conforming 8.3 names all upper or lower? */ +extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ + +/* -------------------------------------------------------------------------- ** + * Other stuff... * - * Input: s - the nul-terminated character string for which the checksum - * will be calculated. - * Output: The checksum value calculated for s. + * magic_char - This is the magic char used for mangling. It's + * global. There is a call to lp_magicchar() in server.c + * that is used to override the initial value. + * + * basechars - The set of 36 characters used for name mangling. This + * is static (scope is this file only). + * + * base36() - Macro used to select a character from basechars (i.e., + * base36(n) will return the nth digit, modulo 36). + * + * chartest - array 0..255. The index range is the set of all possible + * values of a byte. For each byte value, the content is a + * two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK, + * below. + * + * ct_initialized - False until the chartest array has been initialized via + * a call to init_chartest(). + * + * BASECHAR_MASK - Masks the upper nibble of a one-byte value. + * + * ILLEGAL_MASK - Masks the lower nibble of a one-byte value. + * + * isbasecahr() - Given a character, check the chartest array to see + * if that character is in the basechars set. This is + * faster than using strchr(). * - ****************************************************************************/ -int str_checksum(char *s) + * isillegal() - Given a character, check the chartest array to see + * if that character is in the illegal characters set. + * This is faster than using strchr(). + * + * mangled_cache - Cache header used for storing mangled -> original + * reverse maps. + * + * mc_initialized - False until the mangled_cache structure has been + * initialized via a call to reset_mangled_cache(). + * + * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the + * cache. A value of 0 indicates "infinite". + * + * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the + * cache. When the cache was kept as an array of 256 + * byte strings, the default cache size was 50 entries. + * This required a fixed 12.5Kbytes of memory. The + * mangled stack parameter is no longer used (though + * this might change). We're now using a fixed 16Kbyte + * maximum cache size. This will probably be much more + * than 50 entries. + */ + +char magic_char = '~'; + +static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +static unsigned char chartest[256] = { 0 }; +static BOOL ct_initialized = False; + +#define base36(V) ((char)(basechars[(V) % 36])) +#define BASECHAR_MASK 0xf0 +#define ILLEGAL_MASK 0x0f +#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) +#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) + +static ubi_cacheRoot mangled_cache[1] = { 0 }; +static BOOL mc_initialized = False; +#define MANGLED_CACHE_MAX_ENTRIES 0 +#define MANGLED_CACHE_MAX_MEMORY 16384 + + +/* -------------------------------------------------------------------------- ** + * Functions... + */ + +/* ************************************************************************** ** + * Initialize the static character test array. + * + * Input: none + * + * Output: none + * + * Notes: This function changes (loads) the contents of the + * array. The scope of is this file. + * + * ************************************************************************** ** + */ +static void init_chartest( void ) { - int res = 0; - int c; - int i=0; + char *illegalchars = "*\\/?<>|\":"; + unsigned char *s; + + bzero( (char *)chartest, 256 ); - while( *s ) - { - c = *s; - res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); - s++; i++; - } - return(res); - } /* str_checksum */ + for( s = (unsigned char *)illegalchars; *s; s++ ) + chartest[*s] = ILLEGAL_MASK; + + for( s = (unsigned char *)basechars; *s; s++ ) + chartest[*s] |= BASECHAR_MASK; -/**************************************************************************** -return True if a name is a special msdos reserved name -****************************************************************************/ -static BOOL is_reserved_msdos(char *fname) + ct_initialized = True; + } /* init_chartest */ + +/* ************************************************************************** ** + * Return True if a name is a special msdos reserved name. + * + * Input: fname - String containing the name to be tested. + * + * Output: True, if the name matches one of the list of reserved names. + * + * Notes: This is a static function called by is_8_3(), below. + * + * ************************************************************************** ** + */ +static BOOL is_reserved_msdos( char *fname ) { char upperFname[13]; char *p; @@ -59,67 +179,186 @@ static BOOL is_reserved_msdos(char *fname) StrnCpy (upperFname, fname, 12); /* lpt1.txt and con.txt etc are also illegal */ - p=strchr(upperFname,'.'); - if (p) - *p='\0'; - strupper (upperFname); - if ((strcmp(upperFname,"CLOCK$") == 0) || - (strcmp(upperFname,"CON") == 0) || - (strcmp(upperFname,"AUX") == 0) || - (strcmp(upperFname,"COM1") == 0) || - (strcmp(upperFname,"COM2") == 0) || - (strcmp(upperFname,"COM3") == 0) || - (strcmp(upperFname,"COM4") == 0) || - (strcmp(upperFname,"LPT1") == 0) || - (strcmp(upperFname,"LPT2") == 0) || - (strcmp(upperFname,"LPT3") == 0) || - (strcmp(upperFname,"NUL") == 0) || - (strcmp(upperFname,"PRN") == 0)) - return (True) ; - - return (False); + p = strchr(upperFname,'.'); + if( p ) + *p = '\0'; + + strupper( upperFname ); + p = upperFname + 1; + switch( upperFname[0] ) + { + case 'A': + if( 0 == strcmp( p, "UX" ) ) + return( True ); + break; + case 'C': + if( (0 == strcmp( p, "LOCK$" )) + || (0 == strcmp( p, "ON" )) + || (0 == strcmp( p, "OM1" )) + || (0 == strcmp( p, "OM2" )) + || (0 == strcmp( p, "OM3" )) + || (0 == strcmp( p, "OM4" )) + ) + return( True ); + break; + case 'L': + if( (0 == strcmp( p, "PT1" )) + || (0 == strcmp( p, "PT2" )) + || (0 == strcmp( p, "PT3" )) + ) + return( True ); + break; + case 'N': + if( 0 == strcmp( p, "UL" ) ) + return( True ); + break; + case 'P': + if( 0 == strcmp( p, "RN" ) ) + return( True ); + break; + } + + return( False ); } /* is_reserved_msdos */ +/* ************************************************************************** ** + * Determine whether or not a given name contains illegal characters, even + * long names. + * + * Input: name - The name to be tested. + * + * Output: True if an illegal character was found in , else False. + * + * Notes: This is used to test a name on the host system, long or short, + * for characters that would be illegal on most client systems, + * particularly DOS and Windows systems. Unix and AmigaOS, for + * example, allow a filenames which contain such oddities as + * quotes ("). If a name is found which does contain an illegal + * character, it is mangled even if it conforms to the 8.3 + * format. + * + * ************************************************************************** ** + */ +static BOOL is_illegal_name( char *name ) + { + unsigned char *s; + int skip; + + if( !name ) + return( True ); + + if( !ct_initialized ) + init_chartest(); + + s = (unsigned char *)name; + while( *s ) + { + skip = skip_multibyte_char( *s ); + if( skip != 0 ) + { + s += skip; + } + else + { + if( isillegal( *s ) ) + return( True ); + else + s++; + } + } + + return( False ); + } /* is_illegal_name */ + +/* ************************************************************************** ** + * Return True if the name *could be* a mangled name. + * + * Input: s - A file name. + * + * Output: True if the name matches the pattern described below in the + * notes, else False. + * + * Notes: The input name is *not* tested for 8.3 compliance. This must be + * done separately. This function returns true if the name contains + * a magic character followed by excactly two characters from the + * basechars list (above), which in turn are followed either by the + * nul (end of string) byte or a dot (extension). + * + * ************************************************************************** ** + */ +BOOL is_mangled( char *s ) + { + char *magic; + + if( !ct_initialized ) + init_chartest(); + magic = strchr( s, magic_char ); + while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ + { + if( ('.' == magic[3] || !(magic[3])) /* Ends with '.' or nul? */ + && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ + && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ + return( True ); /* If all above, then true, */ + magic = strchr( magic+1, magic_char ); /* else seek next magic. */ + } + return( False ); + } /* is_mangled */ -/**************************************************************************** -return True if a name is in 8.3 dos format -****************************************************************************/ -BOOL is_8_3(char *fname, BOOL check_case) +/* ************************************************************************** ** + * Return True if the name is a valid DOS name in 8.3 DOS format. + * + * Input: fname - File name to be checked. + * check_case - If True, and if case_mangle is True, then the + * name will be checked to see if all characters + * are the correct case. See case_mangle and + * case_default above. + * + * Output: True if the name is a valid DOS name, else FALSE. + * + * ************************************************************************** ** + */ +BOOL is_8_3( char *fname, BOOL check_case ) { - int len; + int len; + int l; + int skip; + char *p; char *dot_pos; - char *slash_pos = strrchr(fname,'/'); - int l; + char *slash_pos = strrchr( fname, '/' ); + /* If there is a directory path, skip it. */ if( slash_pos ) - fname = slash_pos+1; - len = strlen(fname); + fname = slash_pos + 1; + len = strlen( fname ); + + DEBUG( 5, ( "Checking %s for 8.3\n", fname ) ); - DEBUG(5,("checking %s for 8.3\n",fname)); + /* Can't be 0 chars or longer than 12 chars */ + if( (len == 0) || (len > 12) ) + return( False ); + /* Mustn't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ + if( is_reserved_msdos( fname ) ) + return( False ); + + /* Check that all characters are the correct case, if asked to do so. */ if( check_case && case_mangle ) { - switch (case_default) + switch( case_default ) { case CASE_LOWER: - if (strhasupper(fname)) return(False); + if( strhasupper( fname ) ) + return(False); break; case CASE_UPPER: - if (strhaslower(fname)) return(False); + if( strhaslower( fname ) ) + return(False); break; } } - /* can't be longer than 12 chars */ - if( len == 0 || len > 12 ) - return(False); - - /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ - if( is_reserved_msdos(fname) ) - return(False); - - /* can't contain invalid dos chars */ + /* Can't contain invalid dos chars */ /* Windows use the ANSI charset. But filenames are translated in the PC charset. This Translation may be more or less relaxed depending @@ -128,203 +367,283 @@ BOOL is_8_3(char *fname, BOOL check_case) /* %%% A nice improvment to name mangling would be to translate filename to ANSI charset on the smb server host */ - dot_pos = strchr(fname,'.'); - - { - char *p = fname; - int skip; - - dot_pos = 0; - while (*p) + p = fname; + dot_pos = NULL; + while( *p ) { - if((skip = skip_multibyte_char( *p )) != 0) - p += skip; - else + if( (skip = skip_multibyte_char( *p )) != 0 ) + p += skip; + else { - if (*p == '.' && !dot_pos) - dot_pos = (char *) p; - if (!isdoschar(*p)) - return(False); - p++; + if( *p == '.' && !dot_pos ) + dot_pos = (char *)p; + else + if( !isdoschar( *p ) ) + return( False ); + p++; } } - } /* no dot and less than 9 means OK */ - if (!dot_pos) - return(len <= 8); + if( !dot_pos ) + return( len <= 8 ); - l = PTR_DIFF(dot_pos,fname); + l = PTR_DIFF( dot_pos, fname ); /* base must be at least 1 char except special cases . and .. */ if( l == 0 ) - return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0); + return( 0 == strcmp( fname, "." ) || 0 == strcmp( fname, ".." ) ); /* base can't be greater than 8 */ if( l > 8 ) - return(False); + return( False ); - if( lp_strip_dot() && - len - l == 1 && - !strchr(dot_pos+1,'.') ) + /* see smb.conf(5) for a description of the 'strip dot' parameter. */ + if( lp_strip_dot() + && len - l == 1 + && !strchr( dot_pos + 1, '.' ) ) { *dot_pos = 0; - return(True); + return( True ); } /* extension must be between 1 and 3 */ if( (len - l < 2 ) || (len - l > 4) ) - return(False); + return( False ); - /* extension can't have a dot */ - if( strchr(dot_pos+1,'.') ) - return(False); + /* extensions may not have a dot */ + if( strchr( dot_pos+1, '.' ) ) + return( False ); /* must be in 8.3 format */ - return(True); + return( True ); } /* is_8_3 */ -/* -------------------------------------------------------------------------- ** - * This section creates and maintains a stack of name mangling results. - * The original comments read: "keep a stack of name mangling results - just - * so file moves and copies have a chance of working" (whatever that means). - * - * There are three functions to manage the stack: - * reset_mangled_stack() - - * push_mangled_name() - - * check_mangled_stack() - +/* ************************************************************************** ** + * Provide a checksum on a string + * + * Input: s - the nul-terminated character string for which the checksum + * will be calculated. + * + * Output: The checksum value calculated for s. + * + * ************************************************************************** ** */ - -fstring *mangled_stack = NULL; -int mangled_stack_size = 0; -int mangled_stack_len = 0; - -/**************************************************************************** - * create the mangled stack CRH - ****************************************************************************/ -void reset_mangled_stack( int size ) +int str_checksum( char *s ) { - if( mangled_stack ) + int res = 0; + int c; + int i=0; + + while( *s ) { - free(mangled_stack); - mangled_stack_size = 0; - mangled_stack_len = 0; + c = *s; + res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); + s++; + i++; } + return(res); + } /* str_checksum */ + +/* ************************************************************************** ** + * Compare two cache keys and return a value indicating their ordinal + * relationship. + * + * Input: ItemPtr - Pointer to a comparison key. In this case, this will + * be a mangled name string. + * NodePtr - Pointer to a node in the cache. The node structure + * will be followed in memory by a mangled name string. + * + * Output: A signed integer, as follows: + * (x < 0) <==> Key1 less than Key2 + * (x == 0) <==> Key1 equals Key2 + * (x > 0) <==> Key1 greater than Key2 + * + * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for + * more info. + * + * ************************************************************************** ** + */ +static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) + { + char *Key1 = (char *)ItemPtr; + char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); + + return( StrCaseCmp( Key1, Key2 ) ); + } /* cache_compare */ - if( size > 0 ) +/* ************************************************************************** ** + * Initializes or clears the mangled cache. + * + * Input: none. + * Output: none. + * + * Notes: There is a section below that is commented out. It shows how + * one might use lp_ calls to set the maximum memory and entry size + * of the cache. You might also want to remove the constants used + * in ubi_cacheInit() and replace them with lp_ calls. If so, then + * the calls to ubi_cacheSetMax*() would be moved into the else + * clause. Another option would be to pass in the max_entries and + * max_memory values as parameters. crh 09-Apr-1998. + * + * ************************************************************************** ** + */ +void reset_mangled_cache( void ) + { + if( !mc_initialized ) { - mangled_stack = (fstring *)malloc( sizeof(fstring) * size ); - if( mangled_stack ) - mangled_stack_size = size; + (void)ubi_cacheInit( mangled_cache, + cache_compare, + (ubi_trKillNodeRtn)free, + MANGLED_CACHE_MAX_ENTRIES, + MANGLED_CACHE_MAX_MEMORY ); + mc_initialized = True; } else - mangled_stack = NULL; - } /* create_mangled_stack */ + { + (void)ubi_cacheClear( mangled_cache ); + } -/**************************************************************************** - * push a mangled name onto the stack CRH - ****************************************************************************/ -static void push_mangled_name(char *s) - { - int i; - char *p; + /* + (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); + (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); + */ + } /* reset_mangled_cache */ - /* If the stack doesn't exist... Fail. */ - if( !mangled_stack ) + +/* ************************************************************************** ** + * Add a mangled name into the cache. + * + * Notes: If the mangled cache has not been initialized, then the + * function will simply fail. It could initialize the cache, + * but that's not the way it was done before I changed the + * cache mechanism, so I'm sticking with the old method. + * + * If the extension of the raw name maps directly to the + * extension of the mangled name, then we'll store both names + * *without* extensions. That way, we can provide consistant + * reverse mangling for all names that match. The test here is + * a bit more careful than the one done in earlier versions of + * mangle.c: + * + * - the extension must exist on the raw name, + * - it must be all lower case + * - it must match the mangled extension (to prove that no + * mangling occurred). + * + * crh 07-Apr-1998 + * + * ************************************************************************** ** + */ +static void cache_mangled_name( char *mangled_name, char *raw_name ) + { + ubi_cacheEntryPtr new_entry; + char *s1; + char *s2; + int mangled_len; + int raw_len; + int i; + + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) return; - /* If name is already on the stack, move it to the top. */ - for( i=0; i wasn't already there, add it to the top of the stack. */ - memmove( mangled_stack[1], mangled_stack[0], - sizeof(fstring) * MIN(mangled_stack_len, mangled_stack_size-1) ); - strcpy( mangled_stack[0], s ); - mangled_stack_len = MIN( mangled_stack_size, mangled_stack_len+1 ); - - /* Hmmm... - * Find the last dot '.' in the name, - * if there are any upper case characters past the last dot - * and there are no more than three characters past the last dot - * then terminate the name *at* the last dot. - */ - p = strrchr( mangled_stack[0], '.' ); - if( p && (!strhasupper(p+1)) && (strlen(p+1) < (size_t)4) ) - *p = 0; + /* Allocate a new cache entry. If the allcoation fails, just return. */ + i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; + new_entry = malloc( i ); + if( !new_entry ) + return; - } /* push_mangled_name */ + /* Fill the new cache entry, and add it to the cache. */ + s1 = (char *)(new_entry + 1); + s2 = (char *)&(s1[mangled_len + 1]); + (void)StrnCpy( s1, mangled_name, mangled_len ); + (void)StrnCpy( s2, raw_name, raw_len ); + ubi_cachePut( mangled_cache, i, new_entry, s1 ); + } /* cache_mangled_name */ -/**************************************************************************** - * check for a name on the mangled name stack CRH - ****************************************************************************/ -BOOL check_mangled_stack(char *s) +/* ************************************************************************** ** + * Check for a name on the mangled name stack + * + * Input: s - Input *and* output string buffer. + * + * Output: True if the name was found in the cache, else False. + * + * Notes: If a reverse map is found, the function will overwrite the string + * space indicated by the input pointer . This is frightening. + * It should be rewritten to return NULL if the long name was not + * found, and a pointer to the long name if it was found. + * + * ************************************************************************** ** + */ +BOOL check_mangled_cache( char *s ) { - int i; - pstring tmpname; - char extension[5]; - char *p = strrchr( s, '.' ); - BOOL check_extension = False; - - extension[0] = 0; + ubi_cacheEntryPtr FoundPtr; + char *ext_start = NULL; + char *found_name; - /* If the stack doesn't exist, fail. */ - if( !mangled_stack ) - return(False); + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) + return( False ); - /* If there is a file extension, then we need to play with it, too. */ - if( p ) - { - check_extension = True; - StrnCpy( extension, p, 4 ); - strlower( extension ); /* XXXXXXX */ - } + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - for( i=0; i [%s]\n", OutName) ); + return( True ); } /* name_map_mangle */ + +/* ========================================================================== */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d4ee8223ad..7807bf8369 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1675,7 +1675,7 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } if (is_mangled(mask)) - check_mangled_stack(mask); + check_mangled_cache( mask ); has_wild = strchr(mask,'*') || strchr(mask,'?'); @@ -3142,7 +3142,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } if (is_mangled(mask)) - check_mangled_stack(mask); + check_mangled_cache( mask ); has_wild = strchr(mask,'*') || strchr(mask,'?'); @@ -3412,7 +3412,7 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } if (is_mangled(mask)) - check_mangled_stack(mask); + check_mangled_cache( mask ); has_wild = strchr(mask,'*') || strchr(mask,'?'); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7216ae79bb..c4db553659 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -464,7 +464,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) * (JRA). */ if (mangled) - mangled = !check_mangled_stack(name); + mangled = !check_mangled_cache( name ); /* open the directory */ if (!(cur_dir = OpenDir(cnum, path, True))) @@ -659,7 +659,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa /* check on the mangled stack to see if we can recover the base of the filename */ if (is_mangled(start)) - check_mangled_stack(start); + check_mangled_cache( start ); DEBUG(5,("New file %s\n",start)); return(True); @@ -3305,7 +3305,7 @@ BOOL reload_services(BOOL test) } } - reset_mangled_stack( lp_mangledstack() ); + reset_mangled_cache(); /* this forces service parameters to be flushed */ become_service(-1,True); -- cgit From 3f5d0ae6b28ad1f9847ccb44da644d6a9b072d20 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Apr 1998 23:27:22 +0000 Subject: Fixed aggregate initializer problem for gcc. Jeremy. (This used to be commit e74428e4287cbc1557cc79d4930371cfaf3256d4) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index f4e39ef982..3953da54ea 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -122,7 +122,7 @@ static BOOL ct_initialized = False; #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) #define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) -static ubi_cacheRoot mangled_cache[1] = { 0 }; +static ubi_cacheRoot mangled_cache[1] = { { { 0 }, 0, 0, 0, 0, 0, 0} }; static BOOL mc_initialized = False; #define MANGLED_CACHE_MAX_ENTRIES 0 #define MANGLED_CACHE_MAX_MEMORY 16384 -- cgit From 2a53d6f7077de596265a3e73e79827392054142c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Apr 1998 00:41:59 +0000 Subject: Modified interfaces to getting smb password entries from get_smbpwd_entry (now an internal function to smbpass.c) to a more UNIX-like : getsmbpwnam() - get entry by name. getsmbpwuid() - get entry by uid. Changed the type returned by the smbpasswd enumeration functions to be a void * so that people don't come to depend on it being a FILE *. These abstractions should make it much easier to replace the smbpasswd file with a better backend in future. Other files changed are to match the above changes. Jeremy. (This used to be commit 1161cfb7f2b0d5a6d3e2b524a14a6f325ce70efb) --- source3/smbd/chgpasswd.c | 10 +++++----- source3/smbd/password.c | 4 ++-- source3/smbd/reply.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index ae1fd1a675..7494d0162d 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -452,12 +452,12 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, *psmbpw = NULL; become_root(0); - smbpw = get_smbpwd_entry(user, 0); + smbpw = getsmbpwnam(user); unbecome_root(0); if(smbpw == NULL) { - DEBUG(0,("check_lanman_password: get_smbpwd_entry returned NULL\n")); + DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n")); return False; } @@ -509,7 +509,7 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi if(smbpw == NULL) { - DEBUG(0,("change_lanman_password: get_smbpwd_entry returned NULL\n")); + DEBUG(0,("change_lanman_password: no smb password entry.\n")); return False; } @@ -560,12 +560,12 @@ BOOL check_oem_password(char *user, unsigned char *data, unsigned char null_pw[16]; become_root(0); - *psmbpw = smbpw = get_smbpwd_entry(user, 0); + *psmbpw = smbpw = getsmbpwnam(user); unbecome_root(0); if(smbpw == NULL) { - DEBUG(0,("check_oem_password: get_smbpwd_entry returned NULL\n")); + DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); return False; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 74ebeb1617..bbd9f8b849 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1084,8 +1084,8 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } - /* non-null username indicates search by username not smb userid */ - smb_pass = get_smbpwd_entry(user, 0); + smb_pass = getsmbpwnam(user); + if (!smb_pass) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7807bf8369..eaf3fe9920 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -380,7 +380,7 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ if (lp_security() == SEC_USER) { - smb_trust_acct = get_smbpwd_entry(user, 0); + smb_trust_acct = getsmbpwnam(user); } else { -- cgit From 041a292c439189206f1c35de94893dd51a1fda33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Apr 1998 20:00:41 +0000 Subject: ipc.c: Fix for printer queue spinning with Win95. nmbd.c: Fix for always overwriting log despite append setting. smb.h: Addition of last time password changed entry to account info. smbpass.c: Changes to support last time changed field in smbpasswd file. smbpasswd.c: Changes to support last time changed field in smbpasswd file. util.c: Fix for always overwriting log despite append setting. Jeremy. (This used to be commit eb4fe9ecdf539209efab07dc992447ea7370cf93) --- source3/smbd/ipc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e4ddcbec69..7cf4d6f5b8 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -330,8 +330,9 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount) p->subcount = 0; p->curpos = p->format; if (i > n) { + p->neededlen = i; i = n = 0; - p->errcode = NERR_BufTooSmall; + p->errcode = ERROR_MORE_DATA; } else p->errcode = NERR_Success; -- cgit From 7b9a53b68079231fc0c65ee4a265de297031a161 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Apr 1998 19:23:10 +0000 Subject: reply.c: Fix bugs where debug statements were accessing the fd_ptr struct internals after Andrews' code had memset it to zero (this was causing core dumps). charcnv.c: Fixes for ISO8859-2 from Petr Hubeny . Jeremy. (This used to be commit df8783ca76d543d200c743f515a185cfea2880df) --- source3/smbd/reply.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eaf3fe9920..2c4800b1c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2386,16 +2386,16 @@ int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /* try and set the date */ set_filetime(cnum, Files[fnum].name,mtime); + DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", + timestring(),Files[fnum].fd_ptr->fd,fnum,cnum, + Connections[cnum].num_files_open)); + close_file(fnum,True); /* We have a cached error */ if(eclass || err) return(ERROR(eclass,err)); - DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - timestring(),Files[fnum].fd_ptr->fd,fnum,cnum, - Connections[cnum].num_files_open)); - return(outsize); } @@ -2669,10 +2669,10 @@ int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - close_file(fnum,True); - DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); + close_file(fnum,True); + return(outsize); } -- cgit From efb71742ca8ff9ec3211c5b3cf5d311fdceecd1c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Apr 1998 22:43:54 +0000 Subject: Makefile: Added genrand.o clientgen.c: Changed to fill change password buffer with random stuff. password.c: Changed to get challenge from genrand.c server.c: Added #ifdef around O_SYNC. version.h: Changed to 1.9.19prealpha. genrand.c: New code to generate (hopefully) good random numbers for use in crypto challenges/session keys etc. PLEASE REVIEW THIS CODE AND SUGGEST IMPROVEMENTS !!!!!! Jeremy. (This used to be commit 608e98546392fd0aac9b33f4feac43615dbb4405) --- source3/smbd/password.c | 10 ++++++++++ source3/smbd/server.c | 2 ++ 2 files changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index bbd9f8b849..fe3ac5c765 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -45,6 +45,12 @@ Get the next challenge value - no repeats. ********************************************************************/ void generate_next_challenge(char *challenge) { +#if 0 + /* + * Leave this ifdef'd out while we test + * the new crypto random number generator. + * JRA. + */ unsigned char buf[16]; static int counter = 0; struct timeval tval; @@ -59,7 +65,11 @@ void generate_next_challenge(char *challenge) /* mash it up with md4 */ mdfour(buf, (unsigned char *)challenge, 8); +#else + unsigned char buf[8]; + generate_random_buffer(buf,8,False); +#endif memcpy(saved_challenge, buf, 8); memcpy(challenge,buf,8); challenge_sent = True; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c4db553659..4a3edeb871 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1837,9 +1837,11 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, break; } +#if defined(O_SYNC) if (share_mode&(1<<14)) { flags2 |= O_SYNC; } +#endif /* O_SYNC */ if (flags != O_RDONLY && file_existed && (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) -- cgit From 6babe8da07b6a803d15deed70dd7e6aaae93ed4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Apr 1998 23:07:28 +0000 Subject: Added 'passwd chat debug' parameter to allow admins to debug their Samba passwd chat scripts. Jeremy. (This used to be commit 5a995f4f75ffb0d55d6ceaa63a1209d230001991) --- source3/smbd/chgpasswd.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 7494d0162d..92bdb1adf0 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -264,9 +264,8 @@ static int talktochild(int master, char *chatsequence) if (!strequal(chatbuf,".")) ok = expect(master,chatbuf,buf); -#if DEBUG_PASSWORD - DEBUG(100,("chatbuf=[%s] responsebuf=[%s]\n",chatbuf,buf)); -#endif + if(lp_passwd_chat_debug()) + DEBUG(100,("talktochild: chatbuf=[%s] responsebuf=[%s]\n",chatbuf,buf)); if (!ok) { DEBUG(3,("response %d incorrect\n",count)); @@ -278,9 +277,8 @@ static int talktochild(int master, char *chatsequence) if (!strequal(chatbuf,".")) writestring(master,chatbuf); -#if DEBUG_PASSWORD - DEBUG(100,("sendbuf=[%s]\n",chatbuf)); -#endif + if(lp_passwd_chat_debug()) + DEBUG(100,("talktochild: sendbuf=[%s]\n",chatbuf)); } if (count<1) return(False); -- cgit From 2dee1ed38867504d067d593c62734ecff0eca77c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Apr 1998 02:23:24 +0000 Subject: clientgen.c: Added cli_ulogoff() call. password.c: Added call to cli_ulogoff on successfull sessionsetup. Jeremy. (This used to be commit 77882f002b2a8203aad419e485fc885303d999a0) --- source3/smbd/password.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fe3ac5c765..b4d728d0c2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1816,6 +1816,7 @@ BOOL server_validate(char *user, char *domain, DEBUG(3,("password server %s accepted the password\n", cli.desthost)); cli_tdis(&cli); + cli_ulogoff(&cli); return(True); } -- cgit From c41f6c8fdf20ead45658f93ab4d42cb97545f10d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Apr 1998 02:27:12 +0000 Subject: Added cli_ulogoff() calls to all the exit code paths in security=server. Jeremy. (This used to be commit 78d87a5bfdfc6d3f4428591d30294fe7d05d0f91) --- source3/smbd/password.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b4d728d0c2..b69b58f54e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1769,12 +1769,14 @@ BOOL server_validate(char *user, char *domain, /* if logged in as guest then reject */ if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); + cli_ulogoff(&cli); return(False); } if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); + cli_ulogoff(&cli); return False; } @@ -1792,12 +1794,14 @@ BOOL server_validate(char *user, char *domain, if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); cli_tdis(&cli); + cli_ulogoff(&cli); return False; } if (cli.privilages == 0) { DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); cli_tdis(&cli); + cli_ulogoff(&cli); return False; } @@ -1806,6 +1810,7 @@ BOOL server_validate(char *user, char *domain, cli.desthost, cli.eff_name)); cli_tdis(&cli); + cli_ulogoff(&cli); return False; } } -- cgit From 76d3bc36a5ce13d2a7bd08f9c18b2cfd0ab0210f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 21 Apr 1998 02:36:37 +0000 Subject: put server-side long dce/rpc code in main branch. (This used to be commit 2e1a08b28c1c0c9ea988a09067cd149926f25c69) --- source3/smbd/ipc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7cf4d6f5b8..74ae115217 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3255,9 +3255,9 @@ static BOOL api_dce_rpc_command(char *outbuf, if (reply) { /* now send the reply */ - send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len); + send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset); - if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len) + if (mem_buf_len(p->rhdr.data) <= p->file_offset) { /* all of data was sent: no need to wait for SMBreadX calls */ mem_free_data(p->rhdr .data); @@ -3283,7 +3283,7 @@ static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len); + send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset); return True; } @@ -3366,10 +3366,10 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); /* record maximum data length that can be transmitted in an SMBtrans */ - p->max_rdata_len = mdrcnt; + p->file_offset = mdrcnt; - DEBUG(10,("api_fd_reply: p:%p max_rdata_len: %d\n", - p, p->max_rdata_len)); + DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n", + p, p->file_offset)); switch (subcommand) { -- cgit From 8584c6bd6621eefb49aff69581caf28e38b4ceda Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Apr 1998 00:56:38 +0000 Subject: genrand.c: Improved generation of random values, more secure. loadparm.c: Started add of 'security=domain' code. password.c: Fix for security=server NT bugs. reply.c: Started add of 'security=domain' code. server.c: Started add of 'security=domain' code. smb.h: Started add of 'security=domain' code. Jeremy. (This used to be commit e6bda112ebe0d41f54c4249b5c2e1f24011347e1) --- source3/smbd/password.c | 39 ++++++++++++++++++++++++++++++++++++--- source3/smbd/reply.c | 12 +++++++++++- source3/smbd/server.c | 4 ++++ 3 files changed, 51 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b69b58f54e..c347f2de0d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1755,12 +1755,48 @@ BOOL server_validate(char *user, char *domain, char *ntpass, int ntpasslen) { extern fstring local_machine; + static unsigned char badpass[24]; if (!cli.initialised) { DEBUG(1,("password server %s is not connected\n", cli.desthost)); return(False); } + if(badpass[0] == 0) { + memset(badpass, 0x1f, sizeof(badpass)); + } + + if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) { + /* Very unlikely, our random bad password is the same as the users + password. */ + memset(badpass, badpass[0]+1, sizeof(badpass)); + } + + /* + * Attempt a session setup with a totally incorrect password. + * If this succeeds with the guest bit *NOT* set then the password + * server is broken and is not correctly setting the guest bit. We + * need to detect this as some versions of NT4.x are broken. JRA. + */ + + if (cli_session_setup(&cli, user, badpass, sizeof(badpass), badpass, sizeof(badpass), + domain)) { + if ((SVAL(cli.inbuf,smb_vwv2) & 1) == 0) { + DEBUG(0,("server_validate: password server %s allows users as non-guest \ +with a bad password.\n", cli.desthost)); + DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ +use this machine as the password server.\n")); + cli_ulogoff(&cli); + return False; + } + cli_ulogoff(&cli); + } + + /* + * Now we know the password server will correctly set the guest bit, or is + * not guest enabled, we can try with the real password. + */ + if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { DEBUG(1,("password server %s rejected the password\n", cli.desthost)); return False; @@ -1773,7 +1809,6 @@ BOOL server_validate(char *user, char *domain, return(False); } - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); cli_ulogoff(&cli); @@ -1825,5 +1860,3 @@ BOOL server_validate(char *user, char *domain, return(True); } - - diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2c4800b1c2..2f3b3660fc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -515,7 +515,11 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) passlen1 = MIN(passlen1, MAX_PASS_LEN); passlen2 = MIN(passlen2, MAX_PASS_LEN); - if(doencrypt || (lp_security() == SEC_SERVER)) { +#ifdef DOMAIN_CLIENT + if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { +#else /* DOMAIN_CLIENT */ + if(doencrypt || lp_security() == SEC_SERVER) { +#endif /* DOMAIN_CLIENT */ /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; memcpy(smb_apasswd,p,smb_apasslen); @@ -603,6 +607,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) server_validate(user, domain, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen)) && +#ifdef DOMAIN_CLIENT + !(lp_security() == SEC_DOMAIN && + domain_client_validate(user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && +#endif /* DOMAIN_CLIENT */ !check_hosts_equiv(user)) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4a3edeb871..81fe5c9306 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4133,7 +4133,11 @@ static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz /* a special case to stop password server loops */ if (Index == 1 && strequal(remote_machine,myhostname) && +#ifdef DOMAIN_CLIENT + (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN)) +#else /* DOMAIN_CLIENT */ lp_security()==SEC_SERVER) +#endif /* DOMAIN_CLIENT */ exit_server("Password server loop!"); /* Check for protocols, most desirable first */ -- cgit From a85f5bc268a1c13334b86ac3a44a026359c09371 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Apr 1998 18:54:57 +0000 Subject: genrand.c: Changed SMB_PASSWD_FILE to lp_smb_passwd_file(). password.c: Started the initial code for domain_client_validate(). All bracketed with #ifdef DOMAIN_CLIENT for now. reply.c: Call to domain_client_validate(). All bracketed with #ifdef DOMAIN_CLIENT for now. smbpass.c: New code to get/set machine passwords. Tidied up nesting of lock calls. Jeremy. (This used to be commit 89fe059a6816f32d2cc5c4c04c4089b60590e7e6) --- source3/smbd/password.c | 73 ++++++++++++++++++++++++++++++++ source3/smbd/reply.c | 109 ++++++++++++++++++++++++------------------------ 2 files changed, 128 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c347f2de0d..04a1795e7f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -31,6 +31,8 @@ extern int Protocol; /* users from session setup */ static pstring session_users=""; +extern pstring myname; + /* these are kept here to keep the string_combinations function simple */ static char this_user[100]=""; static char this_salt[100]=""; @@ -1860,3 +1862,74 @@ use this machine as the password server.\n")); return(True); } + +#ifdef DOMAIN_CLIENT +BOOL domain_client_validate( char *user, char *domain, + char *smb_apasswd, int smb_apasslen, + char *smb_ntpasswd, int smb_ntpasslen) +{ + unsigned char local_lm_hash[21]; + unsigned char local_nt_hash[21]; + unsigned char local_challenge[8]; + unsigned char local_lm_response[24]; + unsigned char local_nt_reponse[24]; + BOOL encrypted = True; + + /* + * Check that the requested domain is not our own machine name. + * If it is, we should never check the PDC here, we use our own local + * password file. + */ + + if(strequal( domain, myname)) { + DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); + return False; + } + + /* + * Next, check that the passwords given were encrypted. + */ + + if(smb_apasslen != 24 || smb_ntpasslen != 24) { + + /* + * Not encrypted - do so. + */ + + DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); + encrypted = False; + memset(local_lm_hash, '\0', sizeof(local_lm_hash)); + E_P16((uchar *) smb_apasswd, local_lm_hash); + memset(local_nt_hash, '\0', sizeof(local_nt_hash)); + E_md4hash((uchar *) smb_ntpasswd, local_nt_hash); + generate_random_buffer( local_challenge, 8, False); + E_P24(local_lm_hash, local_challenge, local_lm_response); + E_P24(local_nt_hash, local_challenge, local_nt_reponse); + smb_apasslen = 24; + smb_ntpasslen = 24; + smb_apasswd = (char *)local_lm_response; + smb_ntpasswd = (char *)local_nt_reponse; + } else { + + /* + * Encrypted - get the challenge we sent for these + * responses. + */ + + if (!last_challenge(local_challenge)) { + DEBUG(0,("domain_client_validate: no challenge done - password failed\n")); + return False; + } + } + + /* + * At this point, smb_apasswd points to the lanman response to + * the challenge in local_challenge, and smb_ntpasswd points to + * the NT response to the challenge in local_challenge. Ship + * these over the secure channel to a domain controller and + * see if they were valid. + */ + + return False; +} +#endif /* DOMAIN_CLIENT */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2f3b3660fc..4472aa16e6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -377,65 +377,66 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, char *smb_passwd, int smb_passlen, char *smb_nt_passwd, int smb_nt_passlen) { - struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ - if (lp_security() == SEC_USER) - { - smb_trust_acct = getsmbpwnam(user); - } - else - { - DEBUG(3,("Trust account %s only supported with security = user\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); - } + struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ + if (lp_security() == SEC_USER) + { + smb_trust_acct = getsmbpwnam(user); + } + else + { + DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } - if (smb_trust_acct == NULL) - { - /* lkclXXXX: workstation entry doesn't exist */ - DEBUG(4,("Trust account %s user doesn't exist\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER)); - } - else - { - if ((smb_passlen != 24) || (smb_nt_passlen != 24)) - { - DEBUG(4,("Trust account %s - password length wrong.\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); - } + if (smb_trust_acct == NULL) + { + /* lkclXXXX: workstation entry doesn't exist */ + DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER)); + } + else + { + if ((smb_passlen != 24) || (smb_nt_passlen != 24)) + { + DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } - if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd)) - { - DEBUG(4,("Trust Account %s - password failed\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); - } + if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd)) + { + DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST)) - { - DEBUG(4,("Domain trust account %s denied by server\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); - } + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST)) + { + DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); + } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST)) - { - DEBUG(4,("Server trust account %s denied by server\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); - } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST)) - { - DEBUG(4,("Wksta trust account %s denied by server\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); - } - } + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST)) + { + DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); + } + + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST)) + { + DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); + } + } - /* don't know what to do: indicate logon failure */ - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + /* don't know what to do: indicate logon failure */ + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } -- cgit From 002a47de8e0cf03c79cedbed2db52f391001f459 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Apr 1998 20:12:17 +0000 Subject: clientgen.c: Added rap error codes to cli_error, moved from smbpasswd.c password.c: Changed global cli -> pw_cli, removed strtok (bad strtok, bad :-) use in security=server, started to extend security=domain code. smbpasswd.c: Removed rap error code functions. Jeremy. (This used to be commit 0f00b8fce1a5cad7f8c212568fa33f09986e5bd6) --- source3/smbd/password.c | 215 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 161 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 04a1795e7f..d627edf1cd 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1673,14 +1673,14 @@ BOOL check_hosts_equiv(char *user) } -static struct cli_state cli; +static struct cli_state pw_cli; /**************************************************************************** return the client state structure ****************************************************************************/ struct cli_state *server_client(void) { - return &cli; + return &pw_cli; } /**************************************************************************** @@ -1692,61 +1692,63 @@ struct cli_state *server_cryptkey(void) struct in_addr dest_ip; extern fstring local_machine; char *p; + BOOL connected_ok = False; - if (!cli_initialise(&cli)) + if (!cli_initialise(&pw_cli)) return NULL; - - for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { - fstrcpy(desthost,p); + + p = lp_passwordserver(); + while(p && next_token( &p, desthost, LIST_SEP)) { standard_sub_basic(desthost); strupper(desthost); if(!resolve_name( desthost, &dest_ip)) { - DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",p)); + DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); continue; } if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",p)); + DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); continue; } - if (cli_connect(&cli, desthost, &dest_ip)) { - DEBUG(3,("connected to password server %s\n",p)); + if (cli_connect(&pw_cli, desthost, &dest_ip)) { + DEBUG(3,("connected to password server %s\n",desthost)); + connected_ok = True; break; } } - if (!p) { - DEBUG(1,("password server not available\n")); - cli_shutdown(&cli); + if (!connected_ok) { + DEBUG(0,("password server not available\n")); + cli_shutdown(&pw_cli); return NULL; } - if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { + if (!cli_session_request(&pw_cli, desthost, 0x20, local_machine)) { DEBUG(1,("%s rejected the session\n",desthost)); - cli_shutdown(&cli); + cli_shutdown(&pw_cli); return NULL; } DEBUG(3,("got session\n")); - if (!cli_negprot(&cli)) { + if (!cli_negprot(&pw_cli)) { DEBUG(1,("%s rejected the negprot\n",desthost)); - cli_shutdown(&cli); + cli_shutdown(&pw_cli); return NULL; } - if (cli.protocol < PROTOCOL_LANMAN2 || - !(cli.sec_mode & 1)) { + if (pw_cli.protocol < PROTOCOL_LANMAN2 || + !(pw_cli.sec_mode & 1)) { DEBUG(1,("%s isn't in user level security mode\n",desthost)); - cli_shutdown(&cli); + cli_shutdown(&pw_cli); return NULL; } DEBUG(3,("password server OK\n")); - return &cli; + return &pw_cli; } /**************************************************************************** @@ -1759,8 +1761,8 @@ BOOL server_validate(char *user, char *domain, extern fstring local_machine; static unsigned char badpass[24]; - if (!cli.initialised) { - DEBUG(1,("password server %s is not connected\n", cli.desthost)); + if (!pw_cli.initialised) { + DEBUG(1,("password server %s is not connected\n", pw_cli.desthost)); return(False); } @@ -1781,17 +1783,17 @@ BOOL server_validate(char *user, char *domain, * need to detect this as some versions of NT4.x are broken. JRA. */ - if (cli_session_setup(&cli, user, badpass, sizeof(badpass), badpass, sizeof(badpass), + if (cli_session_setup(&pw_cli, user, badpass, sizeof(badpass), badpass, sizeof(badpass), domain)) { - if ((SVAL(cli.inbuf,smb_vwv2) & 1) == 0) { + if ((SVAL(pw_cli.inbuf,smb_vwv2) & 1) == 0) { DEBUG(0,("server_validate: password server %s allows users as non-guest \ -with a bad password.\n", cli.desthost)); +with a bad password.\n", pw_cli.desthost)); DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ use this machine as the password server.\n")); - cli_ulogoff(&cli); + cli_ulogoff(&pw_cli); return False; } - cli_ulogoff(&cli); + cli_ulogoff(&pw_cli); } /* @@ -1799,21 +1801,21 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { - DEBUG(1,("password server %s rejected the password\n", cli.desthost)); + if (!cli_session_setup(&pw_cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", pw_cli.desthost)); return False; } /* if logged in as guest then reject */ - if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); - cli_ulogoff(&cli); + if ((SVAL(pw_cli.inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", pw_cli.desthost)); + cli_ulogoff(&pw_cli); return(False); } - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { - DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); - cli_ulogoff(&cli); + if (!cli_send_tconX(&pw_cli, "IPC$", "IPC", "", 1)) { + DEBUG(1,("password server %s refused IPC$ connect\n", pw_cli.desthost)); + cli_ulogoff(&pw_cli); return False; } @@ -1827,43 +1829,48 @@ use this machine as the password server.\n")); */ if (lp_net_wksta_user_logon()) { - DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", cli.desthost)); - if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { - DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); - cli_tdis(&cli); - cli_ulogoff(&cli); + DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", pw_cli.desthost)); + if (!cli_NetWkstaUserLogon(&pw_cli,user,local_machine)) { + DEBUG(1,("password server %s failed NetWkstaUserLogon\n", pw_cli.desthost)); + cli_tdis(&pw_cli); + cli_ulogoff(&pw_cli); return False; } - if (cli.privilages == 0) { - DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); - cli_tdis(&cli); - cli_ulogoff(&cli); + if (pw_cli.privilages == 0) { + DEBUG(1,("password server %s gave guest privilages\n", pw_cli.desthost)); + cli_tdis(&pw_cli); + cli_ulogoff(&pw_cli); return False; } - if (!strequal(cli.eff_name, user)) { + if (!strequal(pw_cli.eff_name, user)) { DEBUG(1,("password server %s gave different username %s\n", - cli.desthost, - cli.eff_name)); - cli_tdis(&cli); - cli_ulogoff(&cli); + pw_cli.desthost, + pw_cli.eff_name)); + cli_tdis(&pw_cli); + cli_ulogoff(&pw_cli); return False; } } else { - DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", cli.desthost)); + DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", pw_cli.desthost)); } - DEBUG(3,("password server %s accepted the password\n", cli.desthost)); + DEBUG(3,("password server %s accepted the password\n", pw_cli.desthost)); - cli_tdis(&cli); - cli_ulogoff(&cli); + cli_tdis(&pw_cli); + cli_ulogoff(&pw_cli); return(True); } #ifdef DOMAIN_CLIENT +/*********************************************************************** + Do the same as security=server, but using NT Domain calls and a session + key from the machine password. +************************************************************************/ + BOOL domain_client_validate( char *user, char *domain, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) @@ -1874,6 +1881,11 @@ BOOL domain_client_validate( char *user, char *domain, unsigned char local_lm_response[24]; unsigned char local_nt_reponse[24]; BOOL encrypted = True; + fstring remote_machine; + char *p; + struct in_addr dest_ip; + struct cli_state cli; + BOOL connected_ok = False; /* * Check that the requested domain is not our own machine name. @@ -1930,6 +1942,101 @@ BOOL domain_client_validate( char *user, char *domain, * see if they were valid. */ + /* + * Treat each name in the 'password server =' line as a potential + * PDC/BDC. Contact each in turn and try and authenticate. + */ + + p = lp_passwordserver(); + while(p && next_token( &p, remote_machine, LIST_SEP)) { + + standard_sub_basic(remote_machine); + strupper(remote_machine); + + if(!resolve_name( remote_machine, &dest_ip)) { + DEBUG(1,("domain_client_validate: Can't resolve address for %s\n", remote_machine)); + continue; + } + + if (ismyip(dest_ip)) { + DEBUG(1,("domain_client_validate: Password server loop - not using password server %s\n",remote_machine)); + continue; + } + + memset(&cli, '\0', sizeof(struct cli_state)); + + if (!cli_connect(&cli, remote_machine, &dest_ip)) { + DEBUG(0,("domain_client_validate: unable to connect to SMB server on \ +machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) )); + continue; + } + + if (!cli_session_request(&cli, remote_machine, 0x20, myname)) { + DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \ +Error was : %s.\n", remote_machine, cli_errstr(&cli) )); + cli_shutdown(&cli); + continue; + } + + cli.protocol = PROTOCOL_NT1; + + if (!cli_negprot(&cli)) { + DEBUG(0,("domain_client_validate: machine %s rejected the negotiate protocol. \ +Error was : %s.\n", remote_machine, cli_errstr(&cli) )); + cli_shutdown(&cli); + continue; + } + + if (cli.protocol != PROTOCOL_NT1) { + DEBUG(0,("domain_client_validate: machine %s didn't negotiate NT protocol.\n", + remote_machine)); + cli_shutdown(&cli); + continue; + } + + /* + * Do an anonymous session setup. + */ + + if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) { + DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \ +Error was : %s.\n", remote_machine, cli_errstr(&cli) )); + cli_shutdown(&cli); + continue; + } + + if (!(cli.sec_mode & 1)) { + DEBUG(1,("domain_client_validate: machine %s isn't in user level security mode\n", + remote_machine)); + cli_shutdown(&cli); + continue; + } + + if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { + DEBUG(0,("domain_client_validate: machine %s rejected the tconX on the IPC$ share. \ +Error was : %s.\n", remote_machine, cli_errstr(&cli) )); + cli_shutdown(&cli); + continue; + } + + /* + * We have an anonymous connection to IPC$. + */ + connected_ok = True; + break; + } + + if (!connected_ok) { + DEBUG(0,("domain_client_validate: Domain password server not available.\n")); + cli_shutdown(&cli); + return False; + } + + /* + * Ok - we have an anonymous connection to the IPC$ share. + * Now start the NT Domain stuff :-). + */ + return False; } #endif /* DOMAIN_CLIENT */ -- cgit From 30675f81f60bab24f47758baab8316d4467709ef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Apr 1998 22:59:19 +0000 Subject: Makefile: Added nterr.c into the mix. clientgen.c: Added nt_error as an entry in the struct client_state. password.c: Open the netlogon pipe. smb.h: Added nt_error as an entry in the struct client_state. lib/rpc/parse/parse_net.c: Added comments on net logon. lib/rpc/server/srv_netlog.c: Added comments on net logon. Jeremy. (This used to be commit 899a9f0dce50c73e03c8da2ebe920957491c8ad7) --- source3/smbd/password.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index d627edf1cd..11ffe4afd1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1886,6 +1886,7 @@ BOOL domain_client_validate( char *user, char *domain, struct in_addr dest_ip; struct cli_state cli; BOOL connected_ok = False; + int fnum; /* * Check that the requested domain is not our own machine name. @@ -2037,6 +2038,18 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); * Now start the NT Domain stuff :-). */ + /* + * First, open the pipe to \PIPE\NETLOGON. + */ + + if((fnum = cli_open(&cli, PIPE_NETLOGON, O_CREAT, DENY_NONE)) == -1) { + DEBUG(0,("domain_client_validate: cli_open on %s on machine %s failed. Error was :%s.\n", + PIPE_NETLOGON, remote_machine, cli_errstr(&cli))); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } + return False; } #endif /* DOMAIN_CLIENT */ -- cgit From e7ac86607c80912e55ac7179b100cea22749c16f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Apr 1998 01:12:08 +0000 Subject: This looks like a big change but really isn't. It is changing the global variables "myname" and "myworkgroup" to "global_myname" and "global_myworkgroup" respectively. This is to make it very explicit when we are messing with a global (don't ask - it makes the domain client code much clearer :-). Jeremy. (This used to be commit 866406bfe399cf757c8275093dacd5ce4843afa0) --- source3/smbd/ipc.c | 14 +++++++------- source3/smbd/password.c | 27 +++++++++++++-------------- source3/smbd/pipes.c | 1 - source3/smbd/reply.c | 4 ++-- source3/smbd/server.c | 8 ++++---- 5 files changed, 26 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 74ae115217..e3dcda9004 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -40,7 +40,7 @@ extern files_struct Files[]; extern connection_struct Connections[]; extern fstring local_machine; -extern fstring myworkgroup; +extern fstring global_myworkgroup; #define NERR_Success 0 #define NERR_badpass 86 @@ -1035,7 +1035,7 @@ static int get_server_info(uint32 servertype, if (!next_token(&ptr,s->comment, NULL)) continue; if (!next_token(&ptr,s->domain , NULL)) { /* this allows us to cope with an old nmbd */ - strcpy(s->domain,myworkgroup); + strcpy(s->domain,global_myworkgroup); } if (sscanf(stype,"%X",&s->type) != 1) { @@ -1231,7 +1231,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); } else { - StrnCpy(domain, myworkgroup, sizeof(fstring)-1); + StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1); } if (lp_browse_list()) @@ -2039,7 +2039,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, pstrcpy(comment,lp_serverstring()); - if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) { for (i=0;i= 0) && ((pnum) < MAX_OPEN_PIPES)) #define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && Pipes[pnum].open) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4472aa16e6..fe1de65be3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -41,7 +41,7 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; extern pstring sesssetup_user; -extern fstring myworkgroup; +extern fstring global_myworkgroup; extern int Client; extern int global_oplock_break; @@ -671,7 +671,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) p = smb_buf(outbuf); strcpy(p,"Unix"); p = skip_string(p,1); strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1); - strcpy(p,myworkgroup); p = skip_string(p,1); + strcpy(p,global_myworkgroup); p = skip_string(p,1); set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); /* perhaps grab OS version here?? */ } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 81fe5c9306..167911e497 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -25,7 +25,7 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; extern pstring sesssetup_user; -extern fstring myworkgroup; +extern fstring global_myworkgroup; char *InBuffer = NULL; char *OutBuffer = NULL; @@ -3961,10 +3961,10 @@ int reply_nt1(char *outbuf) /* decide where (if) to put the encryption challenge, and follow it with the OEM'd domain name */ - data_len = crypt_len + strlen(myworkgroup) + 1; + data_len = crypt_len + strlen(global_myworkgroup) + 1; set_message(outbuf,17,data_len,True); - strcpy(smb_buf(outbuf)+crypt_len, myworkgroup); + strcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); CVAL(outbuf,smb_vwv1) = secword; SSVALS(outbuf,smb_vwv16+1,crypt_len); @@ -5154,7 +5154,7 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); - strcpy(myworkgroup, lp_workgroup()); + strcpy(global_myworkgroup, lp_workgroup()); #ifndef NO_SIGNAL_TEST signal(SIGHUP,SIGNAL_CAST sig_hup); -- cgit From d3832506b2583130c4f4ba4b3edeabca987b7cbb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Apr 1998 00:02:57 +0000 Subject: This is the checkin that adds the security=domain functionality. WARNING - so far this has only been tested against a Samba PDC (still waiting for IS to add me the machine accounts :-). Still missing is the code in smbpasswd that will add a machine account password and change it on the domain controller, but this is not hard, and I will check it in soon. Jeremy. (This used to be commit 17b94a7084621b3f0106dd4d3386f05cdfc56d19) --- source3/smbd/password.c | 97 +++++++++++++++++++++++++++++++++++++++---------- source3/smbd/reply.c | 6 --- source3/smbd/server.c | 4 -- 3 files changed, 78 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0e9ec620b1..21424592f1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -32,6 +32,7 @@ extern int Protocol; static pstring session_users=""; extern pstring global_myname; +extern fstring global_myworkgroup; /* these are kept here to keep the string_combinations function simple */ static char this_user[100]=""; @@ -1865,7 +1866,6 @@ use this machine as the password server.\n")); return(True); } -#ifdef DOMAIN_CLIENT /*********************************************************************** Do the same as security=server, but using NT Domain calls and a session key from the machine password. @@ -1875,17 +1875,20 @@ BOOL domain_client_validate( char *user, char *domain, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { - unsigned char local_lm_hash[21]; - unsigned char local_nt_hash[21]; unsigned char local_challenge[8]; unsigned char local_lm_response[24]; unsigned char local_nt_reponse[24]; - BOOL encrypted = True; + unsigned char machine_passwd[16]; + time_t lct; fstring remote_machine; char *p; struct in_addr dest_ip; + NET_ID_INFO_CTR ctr; + NET_USER_INFO_3 info3; struct cli_state cli; + uint32 smb_uid_low; BOOL connected_ok = False; + void *vp; /* * Check that the requested domain is not our own machine name. @@ -1909,14 +1912,9 @@ BOOL domain_client_validate( char *user, char *domain, */ DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); - encrypted = False; - memset(local_lm_hash, '\0', sizeof(local_lm_hash)); - E_P16((uchar *) smb_apasswd, local_lm_hash); - memset(local_nt_hash, '\0', sizeof(local_nt_hash)); - E_md4hash((uchar *) smb_ntpasswd, local_nt_hash); generate_random_buffer( local_challenge, 8, False); - E_P24(local_lm_hash, local_challenge, local_lm_response); - E_P24(local_nt_hash, local_challenge, local_nt_reponse); + SMBencrypt( smb_apasswd, local_challenge, local_lm_response); + SMBNTencrypt( smb_ntpasswd, local_challenge, local_nt_reponse); smb_apasslen = 24; smb_ntpasslen = 24; smb_apasswd = (char *)local_lm_response; @@ -1934,6 +1932,29 @@ BOOL domain_client_validate( char *user, char *domain, } } + /* + * Get the machine account password. + */ + if((vp = machine_password_lock( global_myworkgroup, global_myname, False)) == NULL) { + DEBUG(0,("domain_client_validate: unable to open the machine account password file for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + return False; + } + + if(get_machine_account_password( vp, machine_passwd, &lct) == False) { + DEBUG(0,("domain_client_validate: unable to read the machine account password for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + machine_password_unlock(vp); + return False; + } + + machine_password_unlock(vp); + + /* + * Here we should check the last change time to see if the machine + * password needs changing..... TODO... JRA. + */ + /* * At this point, smb_apasswd points to the lanman response to * the challenge in local_challenge, and smb_ntpasswd points to @@ -1942,6 +1963,12 @@ BOOL domain_client_validate( char *user, char *domain, * see if they were valid. */ + memset(&cli, '\0', sizeof(struct cli_state)); + if(cli_initialise(&cli) == False) { + DEBUG(0,("domain_client_validate: unable to initialize client connection.\n")); + return False; + } + /* * Treat each name in the 'password server =' line as a potential * PDC/BDC. Contact each in turn and try and authenticate. @@ -1963,8 +1990,6 @@ BOOL domain_client_validate( char *user, char *domain, continue; } - memset(&cli, '\0', sizeof(struct cli_state)); - if (!cli_connect(&cli, remote_machine, &dest_ip)) { DEBUG(0,("domain_client_validate: unable to connect to SMB server on \ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) )); @@ -2032,7 +2057,6 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); return False; } -#if 0 /* for now... JRA */ /* * Ok - we have an anonymous connection to the IPC$ share. * Now start the NT Domain stuff :-). @@ -2041,14 +2065,49 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); if(cli_nt_session_open(&cli, PIPE_NETLOGON, False) == False) { DEBUG(0,("domain_client_validate: unable to open the domain client session to \ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); - cli_close(&cli, fnum); + cli_close(&cli, cli.nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); return False; } - if(cli_nt_setup_creds(&cli,) HERE -#endif - return False; + if(cli_nt_setup_creds(&cli, machine_passwd) == False) { + DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ +%s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); + cli_close(&cli, cli.nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } + + /* We really don't care what LUID we give the user. */ + generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); + + if(cli_nt_login_network(&cli, domain, user, smb_uid_low, local_challenge, + smb_apasswd, smb_ntpasswd, &ctr, &info3) == False) { + DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ +%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); + cli_close(&cli, cli.nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } + + /* + * Here, if we really want it, we have lots of info about the user in info3. + */ + + if(cli_nt_logoff(&cli, &ctr) == False) { + DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ +%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); + cli_close(&cli, cli.nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } + + cli_close(&cli, cli.nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return True; } -#endif /* DOMAIN_CLIENT */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fe1de65be3..a8a0c2f98c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -516,11 +516,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) passlen1 = MIN(passlen1, MAX_PASS_LEN); passlen2 = MIN(passlen2, MAX_PASS_LEN); -#ifdef DOMAIN_CLIENT if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { -#else /* DOMAIN_CLIENT */ - if(doencrypt || lp_security() == SEC_SERVER) { -#endif /* DOMAIN_CLIENT */ /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; memcpy(smb_apasswd,p,smb_apasslen); @@ -608,12 +604,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) server_validate(user, domain, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen)) && -#ifdef DOMAIN_CLIENT !(lp_security() == SEC_DOMAIN && domain_client_validate(user, domain, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen)) && -#endif /* DOMAIN_CLIENT */ !check_hosts_equiv(user)) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 167911e497..ac18bb4038 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4133,11 +4133,7 @@ static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz /* a special case to stop password server loops */ if (Index == 1 && strequal(remote_machine,myhostname) && -#ifdef DOMAIN_CLIENT (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN)) -#else /* DOMAIN_CLIENT */ - lp_security()==SEC_SERVER) -#endif /* DOMAIN_CLIENT */ exit_server("Password server loop!"); /* Check for protocols, most desirable first */ -- cgit From a8e7f804ca86c4ae91d6d4429f9fe264947b54f9 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 29 Apr 1998 11:00:12 +0000 Subject: password.c: added become_root / unbecome_root around the get machine account password. smbpass.c: cleaning up code. - turning if (BOOL_expr == False) into if (BOOL_expr) what if you test if (BOOL_expr == True) and someone defines True to be -1 on one system and 1 on another? or if you get inconsistent return results between developers - removed if ((FILE*) == 0) and made this if ((FILE*) == NULL) - cannot assume that NULL is zero integer. plus there are typecast issues to deal with - removed return (ret == 0) ? True : False and made this return ret == 0 rely on the compiler to return correct BOOL value: not all developers will return True or False #defines: stick with BOOL test (non-zero). - removed if (ret == False) replaced with if (!ret) - bug where instead of if (sizeof(pstring)-len-len-6 < 0) it had a boolean test if (pstring-len-len-6). - removed "." after debugging of filenames: the "." - a fullstop - looked like it was part of the filename, making things difficult to sort out. still to be resolved: the global_myname isn't set up, such that the machine account password file is named "TEST3..mac". (This used to be commit 315e26c23abf7137684bf084c825ad241076132e) --- source3/smbd/password.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 21424592f1..f2ab29001e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1932,6 +1932,8 @@ BOOL domain_client_validate( char *user, char *domain, } } + become_root(False); + /* * Get the machine account password. */ @@ -1950,6 +1952,8 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); machine_password_unlock(vp); + unbecome_root(False); + /* * Here we should check the last change time to see if the machine * password needs changing..... TODO... JRA. -- cgit From e305c2c9e2e657974d34d1d58a8f9372921fdae2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Apr 1998 19:22:01 +0000 Subject: clientgen.c: Fixed null session setup bug. password.c: Stopped cli_nt_logout call (we don't have it correct yet). Added Luke object-orientation fix :-). smb.h: Added clnt_name_slash to cli_state. lib/rpc/client/cli_login.c: Changed global_myname to clnt_name_slash where needed. lib/rpc/client/cli_netlogon.c: Fixed debug messages, don't check creds on error. lib/rpc/client/cli_pipe.c: Fixed debug messages, Added Luke object-orientation fix. lib/rpc/parse/parse_misc.c: Fixed STRING2 linearization bug that was adding 1. Jeremy. (This used to be commit c6c22df20196cb7f0ae84b1a1dd202a87adb8d4e) --- source3/smbd/password.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f2ab29001e..180c51f4ea 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -2069,7 +2069,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); if(cli_nt_session_open(&cli, PIPE_NETLOGON, False) == False) { DEBUG(0,("domain_client_validate: unable to open the domain client session to \ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); - cli_close(&cli, cli.nt_pipe_fnum); + cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); return False; @@ -2078,7 +2078,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); if(cli_nt_setup_creds(&cli, machine_passwd) == False) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); - cli_close(&cli, cli.nt_pipe_fnum); + cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); return False; @@ -2091,7 +2091,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); smb_apasswd, smb_ntpasswd, &ctr, &info3) == False) { DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ %s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); - cli_close(&cli, cli.nt_pipe_fnum); + cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); return False; @@ -2101,16 +2101,24 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); * Here, if we really want it, we have lots of info about the user in info3. */ +#if 0 + /* + * We don't actually need to do this - plus it fails currently with + * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to + * send here. JRA. + */ + if(cli_nt_logoff(&cli, &ctr) == False) { DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ %s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); - cli_close(&cli, cli.nt_pipe_fnum); + cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); return False; } +#endif /* 0 */ - cli_close(&cli, cli.nt_pipe_fnum); + cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); return True; -- cgit From 90177708aaf5bf17d689979701b5f0156b8a2fa4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Apr 1998 22:27:26 +0000 Subject: Makefile: Added files to smbpasswd.c. loadparm.c: Patch from tim@quiknet.com for static string problems. server.c: Setup global_myname. smbpass.c: Fix up locking. Add machine_password_delete() call. smbpasswd.c: Added provisional code to add to a domain. lib/rpc/client/cli_login.c: Fixed incorrect cred_hash3 call when setting machine password. lib/rpc/server/srv_netlog.c: Fixed incorrect cred_hash3 call when setting machine password. Jeremy. (This used to be commit 6a7164233e3bf9d6bb57c44a53204068e454ae5c) --- source3/smbd/server.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ac18bb4038..83293a5787 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -26,6 +26,7 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; extern pstring sesssetup_user; extern fstring global_myworkgroup; +extern pstring global_myname; char *InBuffer = NULL; char *OutBuffer = NULL; @@ -4942,6 +4943,21 @@ static void init_structs(void ) int i; get_myname(myhostname,NULL); + /* + * Set the machine NETBIOS name if not already + * set from the config file. + */ + + if (!*global_myname) + { + char *p; + fstrcpy( global_myname, myhostname ); + p = strchr( global_myname, '.' ); + if (p) + *p = 0; + } + strupper( global_myname ); + for (i=0;i Date: Thu, 30 Apr 1998 01:39:22 +0000 Subject: Added patch from Bruce Tenison to allow encrypted passwords to be stored over time, allowing a smbpasswd file migration. Adds new parameter "update encrypted". Will also add to 1.9.18 branch. Docs update to follow. Jeremy. (This used to be commit 5d3e874d780d595415cc27a7f5945fc2e694c3ac) --- source3/smbd/chgpasswd.c | 8 +++++--- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 92bdb1adf0..4bdfaec453 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -536,7 +536,7 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi /* Now write it into the file. */ become_root(0); - ret = mod_smbpwd_entry(smbpw); + ret = mod_smbpwd_entry(smbpw,False); unbecome_root(0); return ret; @@ -632,9 +632,11 @@ BOOL check_oem_password(char *user, unsigned char *data, /*********************************************************** Code to change the oem password. Changes both the lanman and NT hashes. + override = False, normal + override = True, override XXXXXXXXXX'd password ************************************************************/ -BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd) +BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) { int ret; fstring upper_case_new_passwd; @@ -654,7 +656,7 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd) /* Now write it into the file. */ become_root(0); - ret = mod_smbpwd_entry(smbpw); + ret = mod_smbpwd_entry(smbpw,override); unbecome_root(0); memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd)); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e3dcda9004..2f9cc00dc9 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1719,7 +1719,7 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat if(lp_unix_password_sync()) chgpasswd(user,"", new_passwd, True); - if(change_oem_password( smbpw, new_passwd)) { + if(change_oem_password( smbpw, new_passwd, False)) { SSVAL(*rparam,0,NERR_Success); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 180c51f4ea..57e7775b71 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -423,6 +423,31 @@ static char *osf1_bigcrypt(char *password,char *salt1) } #endif +/**************************************************************************** +update the encrypted smbpasswd file from the plaintext username and password +*****************************************************************************/ +BOOL update_smbpassword_file( char *user, fstring password) +{ + struct smb_passwd *smbpw; + BOOL ret; + + become_root(0); + smbpw = getsmbpwnam(user); + unbecome_root(0); + + if(smbpw == NULL) + { + DEBUG(0,("update_smbpassword_file: getsmbpwnam returned NULL\n")); + return False; + } + + /* Here, the flag is one, because we want to ignore the XXXXXXX'd out password */ + ret = change_oem_password( smbpw, password, True); + if (ret == False) + DEBUG(3,("update_smbpasswd_file: change_oem_password returned False\n")); + + return ret; +} /**************************************************************************** update the enhanced security database. Only relevant for OSF1 at the moment. @@ -1051,6 +1076,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) struct passwd *pass; char challenge[8]; struct smb_passwd *smb_pass; + BOOL update_encrypted = lp_update_encrypted(); BOOL challenge_done = False; if (password) password[pwlen] = 0; @@ -1231,6 +1257,8 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) if (password_check(password)) { update_protected_database(user,True); + if (update_encrypted) + update_smbpassword_file(user,password); return(True); } @@ -1248,6 +1276,8 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) if (password_check(password)) { update_protected_database(user,True); + if (update_encrypted) + update_smbpassword_file(user,password); return(True); } @@ -1268,6 +1298,8 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) if (string_combinations(password,password_check,level)) { update_protected_database(user,True); + if (update_encrypted) + update_smbpassword_file(user,password); return(True); } -- cgit From 19f76f391b97b405879fd8574e711a6d59e4e60c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 May 1998 19:24:32 +0000 Subject: genrand.c: SGI compile warning fix. ipc.c: Fix for duplicate printer names being long. loadparm.c: Set bNetWkstaUserLogon to false by default - new code in password.c protects us. nmbd_logonnames.c: nmbd_namequery.c: nmbd_namerelease.c: Debug messages fix. password.c: SGI compile warning fix, fix for tcon() with bNetWkstaUserLogon call. reply.c: SGI compile warning fix. server.c Debug messages fix. smbpass.c: Fix for incorrect pointer. Jeremy. (This used to be commit 567d3f838988cafab4770fce1cf68b73085e6c71) --- source3/smbd/ipc.c | 1 + source3/smbd/password.c | 29 +++++++++++++++-------------- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 3 +-- 4 files changed, 18 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 2f9cc00dc9..3bdff29621 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -669,6 +669,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, fgets(p,8191,f); p[strlen(p)-1]='\0'; if (next_token(&p,tok,":") && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) ok=1; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 57e7775b71..5127539466 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -91,7 +91,7 @@ BOOL set_challenge(char *challenge) /******************************************************************* get the last challenge sent ********************************************************************/ -BOOL last_challenge(char *challenge) +BOOL last_challenge(unsigned char *challenge) { if (!challenge_sent) return(False); memcpy(challenge,saved_challenge,8); @@ -1036,7 +1036,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_password_check(nt_pass, smb_pass->smb_nt_passwd, challenge)) + if (smb_password_check(nt_pass, (uchar *)smb_pass->smb_nt_passwd, challenge)) { DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); return(True); @@ -1055,7 +1055,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, return True; } - if((smb_pass->smb_passwd != NULL) && smb_password_check(lm_pass, smb_pass->smb_passwd, challenge)) + if((smb_pass->smb_passwd != NULL) && smb_password_check(lm_pass, (uchar *)smb_pass->smb_passwd, challenge)) { DEBUG(4,("smb_password_ok: LM MD4 password check succeeded\n")); return(True); @@ -1074,7 +1074,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) pstring pass2; int level = lp_passwordlevel(); struct passwd *pass; - char challenge[8]; + uchar challenge[8]; struct smb_passwd *smb_pass; BOOL update_encrypted = lp_update_encrypted(); BOOL challenge_done = False; @@ -1846,12 +1846,6 @@ use this machine as the password server.\n")); return(False); } - if (!cli_send_tconX(&pw_cli, "IPC$", "IPC", "", 1)) { - DEBUG(1,("password server %s refused IPC$ connect\n", pw_cli.desthost)); - cli_ulogoff(&pw_cli); - return False; - } - /* * This patch from Rob Nielsen makes doing * the NetWksaUserLogon a dynamic, rather than compile-time @@ -1863,28 +1857,36 @@ use this machine as the password server.\n")); if (lp_net_wksta_user_logon()) { DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", pw_cli.desthost)); + + if (!cli_send_tconX(&pw_cli, "IPC$", "IPC", "", 1)) { + DEBUG(0,("password server %s refused IPC$ connect\n", pw_cli.desthost)); + cli_ulogoff(&pw_cli); + return False; + } + if (!cli_NetWkstaUserLogon(&pw_cli,user,local_machine)) { - DEBUG(1,("password server %s failed NetWkstaUserLogon\n", pw_cli.desthost)); + DEBUG(0,("password server %s failed NetWkstaUserLogon\n", pw_cli.desthost)); cli_tdis(&pw_cli); cli_ulogoff(&pw_cli); return False; } if (pw_cli.privilages == 0) { - DEBUG(1,("password server %s gave guest privilages\n", pw_cli.desthost)); + DEBUG(0,("password server %s gave guest privilages\n", pw_cli.desthost)); cli_tdis(&pw_cli); cli_ulogoff(&pw_cli); return False; } if (!strequal(pw_cli.eff_name, user)) { - DEBUG(1,("password server %s gave different username %s\n", + DEBUG(0,("password server %s gave different username %s\n", pw_cli.desthost, pw_cli.eff_name)); cli_tdis(&pw_cli); cli_ulogoff(&pw_cli); return False; } + cli_tdis(&pw_cli); } else { DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", pw_cli.desthost)); @@ -1892,7 +1894,6 @@ use this machine as the password server.\n")); DEBUG(3,("password server %s accepted the password\n", pw_cli.desthost)); - cli_tdis(&pw_cli); cli_ulogoff(&pw_cli); return(True); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a8a0c2f98c..3a0d4a9bee 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -405,7 +405,7 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd)) + if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 83293a5787..b6d2b82705 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1085,8 +1085,7 @@ static file_fd_struct *fd_get_new(void) return fd_ptr; } } - DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\ -n")); + DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\n")); return 0; } -- cgit From a2bddb20ed078c3e1b9cb60a7420b3d107898f52 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 May 1998 01:34:51 +0000 Subject: Fixes for the %U and %G problems people have reported. Essentially, multiple session_setup_and_X's may be done to an smbd. As there is only one global variable containing the requested connection name (sessionsetup_user), then any subsequent sessionsetups overwrite this name (causing %U and %G to get the wrong name). This is particularly common when an NT client does a null session setup to get a browse list after the user has connected, but before a share has been mounted. These changes store the requested_name in the vuid structure (so this only really works for user level and above security) and copies this name back into the global variable before the standard_sub call. Jeremy. (This used to be commit b5187ad6a3b3af9fbbeee8bced0ab16b41e9825b) --- source3/smbd/ipc.c | 10 +++++----- source3/smbd/message.c | 2 +- source3/smbd/password.c | 9 +++++---- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 17 +++++++++++------ source3/smbd/uid.c | 8 +++++++- 6 files changed, 30 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3bdff29621..13a8d1347f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -85,7 +85,7 @@ static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) StrnCpy(buf,src,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); + standard_sub(cnum,buf,UID_FIELD_INVALID); StrnCpy(*dst,buf,*n); l = strlen(*dst) + 1; (*dst) += l; @@ -110,7 +110,7 @@ static int StrlenExpanded(int cnum, int snum, char* s) if (!s) return(0); StrnCpy(buf,s,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); + standard_sub(cnum,buf,UID_FIELD_INVALID); return strlen(buf) + 1; } @@ -120,7 +120,7 @@ static char* Expand(int cnum, int snum, char* s) if (!s) return(NULL); StrnCpy(buf,s,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); + standard_sub(cnum,buf,UID_FIELD_INVALID); return &buf[0]; } @@ -2058,7 +2058,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, SIVAL(p,6,0); } else { SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub(cnum,comment); + standard_sub(cnum,comment,vuid); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); p2 = skip_string(p2,1); } @@ -2584,7 +2584,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, /* JHT - By calling lp_logon_script() and standard_sub() we have */ /* made sure all macros are fully substituted and available */ logon_script = lp_logon_script(); - standard_sub( cnum, logon_script ); + standard_sub( cnum, logon_script, vuid ); PACKS(&desc,"z", logon_script); /* script path */ /* End of JHT mods */ diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 24477f31ff..9fb506edd0 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -78,7 +78,7 @@ static void msg_deliver(void) string_sub(s,"%s",name); string_sub(s,"%f",msgfrom); string_sub(s,"%t",msgto); - standard_sub(-1,s); + standard_sub(-1,s,UID_FIELD_INVALID); smbrun(s,NULL,False); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 5127539466..53ed8c85f1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -251,7 +251,7 @@ register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -uint16 register_vuid(int uid,int gid, char *name,BOOL guest) +uint16 register_vuid(int uid,int gid, char *unix_name, char *requested_name, BOOL guest) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -298,7 +298,8 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) vuser->uid = uid; vuser->gid = gid; vuser->guest = guest; - strcpy(vuser->name,name); + fstrcpy(vuser->name,unix_name); + fstrcpy(vuser->requested_name,requested_name); vuser->n_sids = 0; vuser->sids = NULL; @@ -310,13 +311,13 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(name,uid,gid, + setup_groups(unix_name,uid,gid, &vuser->n_groups, &vuser->igroups, &vuser->groups, &vuser->attrs); - DEBUG(3,("uid %d registered to name %s\n",uid,name)); + DEBUG(3,("uid %d registered to name %s\n",uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->real_name, "\0"); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3a0d4a9bee..50b977d49f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -689,7 +689,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,guest); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b6d2b82705..29ee8c9fc5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3537,7 +3537,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring s; pstrcpy(s,lp_pathname(snum)); - standard_sub(cnum,s); + standard_sub(cnum,s,vuid); string_set(&pcon->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); } @@ -3574,7 +3574,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring cmd; pstrcpy(cmd,lp_rootpreexec(SNUM(cnum))); - standard_sub(cnum,cmd); + standard_sub(cnum,cmd,vuid); DEBUG(5,("cmd=%s\n",cmd)); smbrun(cmd,NULL,False); } @@ -3628,7 +3628,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(cnum))); - standard_sub(cnum,cmd); + standard_sub(cnum,cmd,vuid); smbrun(cmd,NULL,False); } @@ -4222,7 +4222,7 @@ void close_cnum(int cnum, uint16 vuid) { pstring cmd; strcpy(cmd,lp_postexec(SNUM(cnum))); - standard_sub(cnum,cmd); + standard_sub(cnum,cmd,vuid); smbrun(cmd,NULL,False); unbecome_user(); } @@ -4233,7 +4233,7 @@ void close_cnum(int cnum, uint16 vuid) { pstring cmd; strcpy(cmd,lp_rootpostexec(SNUM(cnum))); - standard_sub(cnum,cmd); + standard_sub(cnum,cmd,vuid); smbrun(cmd,NULL,False); } @@ -4338,8 +4338,10 @@ void exit_server(char *reason) /**************************************************************************** do some standard substitutions in a string ****************************************************************************/ -void standard_sub(int cnum,char *str) +void standard_sub(int cnum,char *str,uint16 vuid) { + user_struct *vuser = get_valid_user_struct(vuid); + if (VALID_CNUM(cnum)) { char *p, *s, *home; @@ -4368,6 +4370,9 @@ void standard_sub(int cnum,char *str) } } } + if(vuser != NULL) + pstrcpy( sesssetup_user, vuser->requested_name); + standard_sub_basic(str); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 14b0000f59..c01fa1b052 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -28,6 +28,7 @@ static int initial_gid; /* what user is current? */ struct current_user current_user; +extern pstring sesssetup_user; pstring OriginalDir; @@ -276,7 +277,12 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) current_user.cnum = cnum; current_user.vuid = vuid; - + + /* Ensure sesssetup_user is set correctly if we are using + user security. */ + if(vuser != NULL) + pstrcpy( sesssetup_user, vuser->requested_name); + DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); -- cgit From b54509045d7186fc0526d91bcf429659cba8be1d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 May 1998 18:14:02 +0000 Subject: loadparm.c: Added #ifdef USE_LDAP around ldap code. server.c: Moved %U, %G and %N into standard_sub() from standard_sub_basic() as only smbd knows about usernames. Also fixes problem with calling standard_sub_basic() from loadparm.c. smbpass.c: Partial tidyup of machine_password_lock() code - not finished yet. util.c: Moved %U, %G and %N into standard_sub() from standard_sub_basic() as only smbd knows about usernames. Also fixes problem with calling standard_sub_basic() from loadparm.c. lib/rpc/server/srv_ldap_helpers.c: Added #ifdef USE_LDAP around ldap code. lib/rpc/server/srv_samr.c: Added #ifdef USE_LDAP around ldap code. Jeremy. (This used to be commit 446b98ca071170fc950bad86ad96b58308a5b75c) --- source3/smbd/server.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 29ee8c9fc5..6f5527714d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4340,10 +4340,14 @@ do some standard substitutions in a string ****************************************************************************/ void standard_sub(int cnum,char *str,uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); - if (VALID_CNUM(cnum)) { char *p, *s, *home; + struct passwd *pass; + char *username = sesssetup_user; + user_struct *vuser = get_valid_user_struct(vuid); + + if(vuser != NULL) + pstrcpy( sesssetup_user, vuser->requested_name); for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) { switch (*(p+1)) { @@ -4355,24 +4359,29 @@ void standard_sub(int cnum,char *str,uint16 vuid) case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break; case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break; case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break; + case 'G' : + { + if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL) + string_sub(p,"%G",gidtoname(pass->pw_gid)); + else + p += 2; + break; + } case 'u' : string_sub(p,"%u",Connections[cnum].user); break; + case 'U' : string_sub(p,"%U", username); 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 username. * The %p (NIS server path) code is here as it is used * instead of the default "path =" string in [homes] and so * needs the service name, not the username. */ + case 'N' : string_sub(p,"%N", automount_server(username)); break; case 'p' : string_sub(p,"%p",automount_path(lp_servicename(Connections[cnum].service))); break; case '\0' : p++; break; /* don't run off the end of the string */ default : p+=2; break; } } } - if(vuser != NULL) - pstrcpy( sesssetup_user, vuser->requested_name); - standard_sub_basic(str); } -- cgit From 346abceb277e3354214599cc3c0f9bac6d44dfc8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 May 1998 18:45:57 +0000 Subject: smbpass.c: Fixed machine_passwd_lock() problems. password.c: Fixed machine_passwd_lock() problems. lib/rpc/server/srv_ldap_helpers.c: Oops - broke proto.h with dummy function. Fixed now. Jeremy. (This used to be commit d28427f21fff49da6b38c24625e3e2dae49a9713) --- source3/smbd/password.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 53ed8c85f1..1056269490 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1922,7 +1922,6 @@ BOOL domain_client_validate( char *user, char *domain, struct cli_state cli; uint32 smb_uid_low; BOOL connected_ok = False; - void *vp; /* * Check that the requested domain is not our own machine name. @@ -1971,20 +1970,20 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password. */ - if((vp = machine_password_lock( global_myworkgroup, global_myname, False)) == NULL) { + if(!machine_password_lock( global_myworkgroup, global_myname, False)) { DEBUG(0,("domain_client_validate: unable to open the machine account password file for \ machine %s in domain %s.\n", global_myname, global_myworkgroup )); return False; } - if(get_machine_account_password( vp, machine_passwd, &lct) == False) { + if(get_machine_account_password( machine_passwd, &lct) == False) { DEBUG(0,("domain_client_validate: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname, global_myworkgroup )); - machine_password_unlock(vp); + machine_password_unlock(); return False; } - machine_password_unlock(vp); + machine_password_unlock(); unbecome_root(False); -- cgit From 10a610cbc4acf89845b1878cdd0e5b193bc24455 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Wed, 6 May 1998 19:22:45 +0000 Subject: Andrew redefines the free() function to do some memory management testing. He also suggested that some systems may implement free() as a macro (but I think he was looking for an excuse ;). Anyway, I've added a function to mangle.c that calls free(). Chris -)----- (This used to be commit 95f7b03285c42e8f5573690939b79afc7e686908) --- source3/smbd/mangle.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 3953da54ea..eb267faab3 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -472,6 +472,24 @@ static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) return( StrCaseCmp( Key1, Key2 ) ); } /* cache_compare */ +/* ************************************************************************** ** + * Free a cache entry. + * + * Input: WarrenZevon - Pointer to the entry that is to be returned to + * Nirvana. + * Output: none. + * + * Notes: This function gets around the possibility that the standard + * free() function may be implemented as a macro, or other evil + * subversions (oh, so much fun). + * + * ************************************************************************** ** + */ +static void cache_free_entry( ubi_trNodePtr WarrenZevon ) + { + free( WarrenZevon ); + } /* cache_free_entry */ + /* ************************************************************************** ** * Initializes or clears the mangled cache. * @@ -494,7 +512,7 @@ void reset_mangled_cache( void ) { (void)ubi_cacheInit( mangled_cache, cache_compare, - (ubi_trKillNodeRtn)free, + cache_free_entry, MANGLED_CACHE_MAX_ENTRIES, MANGLED_CACHE_MAX_MEMORY ); mc_initialized = True; -- cgit From d8d9f7723337c267a8740750fe19a6387cfbb1f6 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 7 May 1998 18:19:05 +0000 Subject: created "passdb.c" which is an interface point to (at present) either smbpasswd or ldap passwd, at compile-time (-DUSE_LDAP). _none_ of the functions in ldap.c or smbpass.c should be called directly: only those in passdb.c should be used. -DUSE_LDAP is unlikely to compile at the moment. (This used to be commit 57b01ad4ffb14ebd600d4e66602b54ed987f6106) --- source3/smbd/chgpasswd.c | 78 ++++++++++++++++++++++++------------------------ source3/smbd/ipc.c | 12 ++++---- source3/smbd/password.c | 12 ++++---- source3/smbd/reply.c | 14 ++++----- 4 files changed, 58 insertions(+), 58 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 4bdfaec453..e466455aeb 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -440,56 +440,56 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) ************************************************************/ BOOL check_lanman_password(char *user, unsigned char *pass1, - unsigned char *pass2, struct smb_passwd **psmbpw) + unsigned char *pass2, struct smb_passwd **psampw) { unsigned char unenc_new_pw[16]; unsigned char unenc_old_pw[16]; unsigned char null_pw[16]; - struct smb_passwd *smbpw; + struct smb_passwd *sampw; - *psmbpw = NULL; + *psampw = NULL; become_root(0); - smbpw = getsmbpwnam(user); + sampw = getsampwnam(user); unbecome_root(0); - if(smbpw == NULL) + if(sampw == NULL) { - DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n")); + DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); return False; } - if(smbpw->acct_ctrl & ACB_DISABLED) + if(sampw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } - if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + if((sampw->smb_passwd == NULL) && (sampw->acct_ctrl & ACB_PWNOTREQ)) { unsigned char no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); - smbpw->smb_passwd = null_pw; - } else if (smbpw->smb_passwd == NULL) { + sampw->smb_passwd = null_pw; + } else if (sampw->smb_passwd == NULL) { DEBUG(0,("check_lanman_password: no lanman password !\n")); return False; } /* Get the new lanman hash. */ - D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + D_P16(sampw->smb_passwd, pass2, unenc_new_pw); /* Use this to get the old lanman hash. */ D_P16(unenc_new_pw, pass1, unenc_old_pw); /* Check that the two old passwords match. */ - if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + if(memcmp(sampw->smb_passwd, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); return False; } - *psmbpw = smbpw; + *psampw = sampw; return True; } @@ -499,44 +499,44 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, no longer be valid. ************************************************************/ -BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2) +BOOL change_lanman_password(struct smb_passwd *sampw, unsigned char *pass1, unsigned char *pass2) { unsigned char unenc_new_pw[16]; unsigned char null_pw[16]; BOOL ret; - if(smbpw == NULL) + if(sampw == NULL) { DEBUG(0,("change_lanman_password: no smb password entry.\n")); return False; } - if(smbpw->acct_ctrl & ACB_DISABLED) + if(sampw->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); + DEBUG(0,("change_lanman_password: account %s disabled.\n", sampw->smb_name)); return False; } - if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + if((sampw->smb_passwd == NULL) && (sampw->acct_ctrl & ACB_PWNOTREQ)) { unsigned char no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); - smbpw->smb_passwd = null_pw; - } else if (smbpw->smb_passwd == NULL) { + sampw->smb_passwd = null_pw; + } else if (sampw->smb_passwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); return False; } /* Get the new lanman hash. */ - D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + D_P16(sampw->smb_passwd, pass2, unenc_new_pw); - smbpw->smb_passwd = unenc_new_pw; - smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ + sampw->smb_passwd = unenc_new_pw; + sampw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ /* Now write it into the file. */ become_root(0); - ret = mod_smbpwd_entry(smbpw,False); + ret = mod_sampwd_entry(sampw,False); unbecome_root(0); return ret; @@ -547,10 +547,10 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi ************************************************************/ BOOL check_oem_password(char *user, unsigned char *data, - struct smb_passwd **psmbpw, char *new_passwd, + struct smb_passwd **psampw, char *new_passwd, int new_passwd_size) { - struct smb_passwd *smbpw = NULL; + struct smb_passwd *sampw = NULL; int new_pw_len; fstring upper_case_new_passwd; unsigned char new_p16[16]; @@ -558,28 +558,28 @@ BOOL check_oem_password(char *user, unsigned char *data, unsigned char null_pw[16]; become_root(0); - *psmbpw = smbpw = getsmbpwnam(user); + *psampw = sampw = getsampwnam(user); unbecome_root(0); - if(smbpw == NULL) + if(sampw == NULL) { - DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); + DEBUG(0,("check_oem_password: getsampwnam returned NULL\n")); return False; } - if(smbpw->acct_ctrl & ACB_DISABLED) + if(sampw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } - if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + if((sampw->smb_passwd == NULL) && (sampw->acct_ctrl & ACB_PWNOTREQ)) { unsigned char no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); - smbpw->smb_passwd = null_pw; - } else if (smbpw->smb_passwd == NULL) { + sampw->smb_passwd = null_pw; + } else if (sampw->smb_passwd == NULL) { DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } @@ -587,7 +587,7 @@ BOOL check_oem_password(char *user, unsigned char *data, /* * Call the hash function to get the new password. */ - SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd, True); + SamOEMhash( (unsigned char *)data, (unsigned char *)sampw->smb_passwd, True); /* * The length of the new password is in the last 4 bytes of @@ -619,7 +619,7 @@ BOOL check_oem_password(char *user, unsigned char *data, */ D_P16(new_p16, &data[516], unenc_old_pw); - if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { + if(memcmp(sampw->smb_passwd, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old password doesn't match.\n")); return False; } @@ -636,7 +636,7 @@ BOOL check_oem_password(char *user, unsigned char *data, override = True, override XXXXXXXXXX'd password ************************************************************/ -BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) +BOOL change_oem_password(struct smb_passwd *sampw, char *new_passwd, BOOL override) { int ret; fstring upper_case_new_passwd; @@ -649,14 +649,14 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL overri E_P16((uchar *)upper_case_new_passwd, new_p16); - smbpw->smb_passwd = new_p16; + sampw->smb_passwd = new_p16; E_md4hash((uchar *) new_passwd, new_nt_p16); - smbpw->smb_nt_passwd = new_nt_p16; + sampw->smb_nt_passwd = new_nt_p16; /* Now write it into the file. */ become_root(0); - ret = mod_smbpwd_entry(smbpw,override); + ret = mod_sampwd_entry(sampw,override); unbecome_root(0); memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd)); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 13a8d1347f..48c0277165 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1649,10 +1649,10 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, if(SVAL(*rparam,0) != NERR_Success) { - struct smb_passwd *smbpw = NULL; + struct smb_passwd *sampw = NULL; - if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &smbpw) && - change_lanman_password(smbpw,(unsigned char *)pass1,(unsigned char *)pass2)) + if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) && + change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2)) { SSVAL(*rparam,0,NERR_Success); } @@ -1675,7 +1675,7 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat { fstring user; fstring new_passwd; - struct smb_passwd *smbpw = NULL; + struct smb_passwd *sampw = NULL; char *p = param + 2; *rparam_len = 2; @@ -1703,7 +1703,7 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat fstrcpy(user,p); p = skip_string(p,1); - if(check_oem_password( user, (unsigned char *)data, &smbpw, + if(check_oem_password( user, (unsigned char *)data, &sampw, new_passwd, (int)sizeof(new_passwd)) == False) { return True; } @@ -1720,7 +1720,7 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat if(lp_unix_password_sync()) chgpasswd(user,"", new_passwd, True); - if(change_oem_password( smbpw, new_passwd, False)) { + if(change_oem_password( sampw, new_passwd, False)) { SSVAL(*rparam,0,NERR_Success); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1056269490..82e3a024e1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -429,21 +429,21 @@ update the encrypted smbpasswd file from the plaintext username and password *****************************************************************************/ BOOL update_smbpassword_file( char *user, fstring password) { - struct smb_passwd *smbpw; + struct smb_passwd *sampw; BOOL ret; become_root(0); - smbpw = getsmbpwnam(user); + sampw = getsampwnam(user); unbecome_root(0); - if(smbpw == NULL) + if(sampw == NULL) { - DEBUG(0,("update_smbpassword_file: getsmbpwnam returned NULL\n")); + DEBUG(0,("update_smbpassword_file: getsampwnam returned NULL\n")); return False; } /* Here, the flag is one, because we want to ignore the XXXXXXX'd out password */ - ret = change_oem_password( smbpw, password, True); + ret = change_oem_password( sampw, password, True); if (ret == False) DEBUG(3,("update_smbpasswd_file: change_oem_password returned False\n")); @@ -1124,7 +1124,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } - smb_pass = getsmbpwnam(user); + smb_pass = getsampwnam(user); if (!smb_pass) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 50b977d49f..1567e52777 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -377,10 +377,10 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, char *smb_passwd, int smb_passlen, char *smb_nt_passwd, int smb_nt_passlen) { - struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ + struct smb_passwd *sam_trust_acct = NULL; /* check if trust account exists */ if (lp_security() == SEC_USER) { - smb_trust_acct = getsmbpwnam(user); + sam_trust_acct = getsampwnam(user); } else { @@ -389,7 +389,7 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (smb_trust_acct == NULL) + if (sam_trust_acct == NULL) { /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); @@ -405,28 +405,28 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) + if (!smb_password_ok(sam_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST)) + if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_DOMTRUST)) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST)) + if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_SVRTRUST)) { DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST)) + if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_WSTRUST)) { DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); -- cgit From 01df1ed95f880a671ead7bc92b3bcff01a2e2dc0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 May 1998 19:04:14 +0000 Subject: This should (hopefully :-) be the final fix for the %U %G substitution problem.... smbpass.c: Removed Luke's dire warning - as some of the functions in here *need* to be called externally :-). Jeremy. (This used to be commit 1fd8d12ca414066acec71b33eb8a13e16c2acd3a) --- source3/smbd/ipc.c | 10 +++++----- source3/smbd/message.c | 2 +- source3/smbd/server.c | 50 ++++++++++++++++++++++++++++---------------------- source3/smbd/uid.c | 6 ------ 4 files changed, 34 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 48c0277165..8be9c10a13 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -85,7 +85,7 @@ static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) StrnCpy(buf,src,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf,UID_FIELD_INVALID); + standard_sub(cnum,buf); StrnCpy(*dst,buf,*n); l = strlen(*dst) + 1; (*dst) += l; @@ -110,7 +110,7 @@ static int StrlenExpanded(int cnum, int snum, char* s) if (!s) return(0); StrnCpy(buf,s,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf,UID_FIELD_INVALID); + standard_sub(cnum,buf); return strlen(buf) + 1; } @@ -120,7 +120,7 @@ static char* Expand(int cnum, int snum, char* s) if (!s) return(NULL); StrnCpy(buf,s,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf,UID_FIELD_INVALID); + standard_sub(cnum,buf); return &buf[0]; } @@ -2058,7 +2058,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, SIVAL(p,6,0); } else { SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub(cnum,comment,vuid); + standard_sub(cnum,comment); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); p2 = skip_string(p2,1); } @@ -2584,7 +2584,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, /* JHT - By calling lp_logon_script() and standard_sub() we have */ /* made sure all macros are fully substituted and available */ logon_script = lp_logon_script(); - standard_sub( cnum, logon_script, vuid ); + standard_sub( cnum, logon_script ); PACKS(&desc,"z", logon_script); /* script path */ /* End of JHT mods */ diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 9fb506edd0..24477f31ff 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -78,7 +78,7 @@ static void msg_deliver(void) string_sub(s,"%s",name); string_sub(s,"%f",msgfrom); string_sub(s,"%t",msgto); - standard_sub(-1,s,UID_FIELD_INVALID); + standard_sub(-1,s); smbrun(s,NULL,False); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6f5527714d..e4c00c141f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3537,7 +3537,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring s; pstrcpy(s,lp_pathname(snum)); - standard_sub(cnum,s,vuid); + standard_sub(cnum,s); string_set(&pcon->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); } @@ -3574,7 +3574,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring cmd; pstrcpy(cmd,lp_rootpreexec(SNUM(cnum))); - standard_sub(cnum,cmd,vuid); + standard_sub(cnum,cmd); DEBUG(5,("cmd=%s\n",cmd)); smbrun(cmd,NULL,False); } @@ -3628,7 +3628,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(cnum))); - standard_sub(cnum,cmd,vuid); + standard_sub(cnum,cmd); smbrun(cmd,NULL,False); } @@ -4222,7 +4222,7 @@ void close_cnum(int cnum, uint16 vuid) { pstring cmd; strcpy(cmd,lp_postexec(SNUM(cnum))); - standard_sub(cnum,cmd,vuid); + standard_sub(cnum,cmd); smbrun(cmd,NULL,False); unbecome_user(); } @@ -4233,7 +4233,7 @@ void close_cnum(int cnum, uint16 vuid) { pstring cmd; strcpy(cmd,lp_rootpostexec(SNUM(cnum))); - standard_sub(cnum,cmd,vuid); + standard_sub(cnum,cmd); smbrun(cmd,NULL,False); } @@ -4338,16 +4338,10 @@ void exit_server(char *reason) /**************************************************************************** do some standard substitutions in a string ****************************************************************************/ -void standard_sub(int cnum,char *str,uint16 vuid) +void standard_sub(int cnum,char *str) { if (VALID_CNUM(cnum)) { char *p, *s, *home; - struct passwd *pass; - char *username = sesssetup_user; - user_struct *vuser = get_valid_user_struct(vuid); - - if(vuser != NULL) - pstrcpy( sesssetup_user, vuser->requested_name); for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) { switch (*(p+1)) { @@ -4359,23 +4353,15 @@ void standard_sub(int cnum,char *str,uint16 vuid) case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break; case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break; case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break; - case 'G' : - { - if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL) - string_sub(p,"%G",gidtoname(pass->pw_gid)); - else - p += 2; - break; - } case 'u' : string_sub(p,"%u",Connections[cnum].user); break; - case 'U' : string_sub(p,"%U", username); 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 username. * The %p (NIS server path) code is here as it is used * instead of the default "path =" string in [homes] and so * needs the service name, not the username. */ - case 'N' : string_sub(p,"%N", automount_server(username)); break; case 'p' : string_sub(p,"%p",automount_path(lp_servicename(Connections[cnum].service))); break; case '\0' : p++; break; /* don't run off the end of the string */ default : p+=2; break; @@ -4595,11 +4581,31 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { int cnum = SVAL(inbuf,smb_tid); int flags = smb_messages[match].flags; + static uint16 last_session_tag = UID_FIELD_INVALID; /* In share mode security we must ignore the vuid. */ uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); /* Ensure this value is replaced in the incoming packet. */ SSVAL(inbuf,smb_uid,session_tag); + /* + * Ensure the correct username is in sesssetup_user. + * This is a really ugly bugfix for problems with + * multiple session_setup_and_X's being done and + * allowing %U and %G substitutions to work correctly. + * There is a reason this code is done here, don't + * move it unless you know what you're doing... :-). + * JRA. + */ + if(session_tag != last_session_tag ) { + user_struct *vuser = NULL; + + last_session_tag = session_tag; + if(session_tag != UID_FIELD_INVALID) + vuser = get_valid_user_struct(session_tag); + if(vuser != NULL) + pstrcpy( sesssetup_user, vuser->requested_name); + } + /* does this protocol need to be run as root? */ if (!(flags & AS_USER)) unbecome_user(); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c01fa1b052..a8e340e46f 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -28,7 +28,6 @@ static int initial_gid; /* what user is current? */ struct current_user current_user; -extern pstring sesssetup_user; pstring OriginalDir; @@ -278,11 +277,6 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) current_user.cnum = cnum; current_user.vuid = vuid; - /* Ensure sesssetup_user is set correctly if we are using - user security. */ - if(vuser != NULL) - pstrcpy( sesssetup_user, vuser->requested_name); - DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); -- cgit From 4cc7a1b0ef893941446c5f03b9372966a453cb6a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 May 1998 01:22:16 +0000 Subject: Initial cut at the code that will do NT SMB calls. Not linked in, not compiled yet, just checked in for safe keeping :-). Jeremy. (This used to be commit 74565f0039be8ab02a501accad5e671e80733314) --- source3/smbd/nttrans.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 source3/smbd/nttrans.c (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c new file mode 100644 index 0000000000..0a861bf9c6 --- /dev/null +++ b/source3/smbd/nttrans.c @@ -0,0 +1,225 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB NT transaction handling + Copyright (C) Jeremy Allison 1994-1998 + + 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; +extern int Protocol; +extern connection_struct Connections[]; +extern files_struct Files[]; +extern int Client; +extern int oplock_sock; +extern int smb_read_error; +extern int global_oplock_break; + +/**************************************************************************** + reply to an unsolicited SMBNTtranss - just ignore it! +****************************************************************************/ + +int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize) +{ + DEBUG(4,("Ignoring nttranss of length %d\n",length)); + return(-1); +} + +/**************************************************************************** + reply to a SMBNTtrans +****************************************************************************/ + +int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) +{ + int outsize = 0; + int cnum = SVAL(inbuf,smb_tid); +#if 0 + uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); + uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount); + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); +#endif + uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); + uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount); + uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount); + uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset); + uint32 data_count = IVAL(inbuf,smb_nt_DataCount); + uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset); + uint16 setup_count = SVAL(inbuf,smb_nt_SetupCount); + uint16 function_code = SVAL( inbuf, smb_nt_Function); + char *params = NULL, *data = NULL, *setup = NULL; + uint32 num_params_sofar, num_data_sofar; + + if(global_oplock_break && (function_code == NT_TRANSACT_CREATE)) { + /* + * Queue this open message as we are the process of an oplock break. + */ + + DEBUG(2,("%s: reply_nttrans: queueing message NT_TRANSACT_CREATE \ +due to being in oplock break state.\n", timestring() )); + + push_smb_message( inbuf, length); + return -1; + } + + outsize = set_message(outbuf,0,0,True); + + /* + * All nttrans messages we handle have smb_wcnt == 19 + setup_count. + * Ensure this is so as a sanity check. + */ + + if(CVAL(inbuf, smb_wcnt) != 19 + setup_count) { + DEBUG(2,("Invalid smb_wcnt in trans2 call\n")); + return(ERROR(ERRSRV,ERRerror)); + } + + /* Allocate the space for the setup, the maximum needed parameters and data */ + + if(setup_count > 0) + setup = (char *)malloc(setup_count); + if (total_parameter_count > 0) + params = (char *)malloc(total_parameter_count); + if (total_data_count > 0) + data = (char *)malloc(total_data_count); + + if ((total_parameter_count && !params) || (total_data_count && !data) || + (setup_count && !setup)) { + DEBUG(0,("reply_nttrans : Out of memory\n")); + return(ERROR(ERRDOS,ERRnomem)); + } + + /* Copy the param and data bytes sent with this request into + the params buffer */ + num_params_sofar = parameter_count; + num_data_sofar = data_count; + + if (parameter_count > total_parameter_count || data_count > total_data_count) + exit_server("reply_nttrans: invalid sizes in packet.\n"); + + if(setup) + memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); + if(params) + memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); + if(data) + memcpy( data, smb_base(inbuf) + data_offset, data_count); + + if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + send_smb(Client,outbuf); + + while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { + BOOL ret; + + ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize, + SMB_SECONDARY_WAIT); + + if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) { + outsize = set_message(outbuf,0,0,True); + if(ret) + DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n")); + else + DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); + if(params) + free(params); + if(data) + free(data); + if(setup) + free(setup); + return(ERROR(ERRSRV,ERRerror)); + } + + /* Revise total_params and total_data in case they have changed downwards */ + total_parameter_count = SIVAL(inbuf, smb_nts_TotalParameterCount); + total_data_count = SIVAL(inbuf, smb_nts_TotalDataCount); + num_params_sofar += (parameter_count = SIVAL(inbuf,smb_nts_ParameterCount)); + num_data_sofar += ( data_count = SIVAL(inbuf, smb_nts_DataCount)); + if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) + exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n"); + + memcpy( ¶ms[ SIVAL(inbuf, smb_nts_ParameterDisplacement)], + smb_base(inbuf) + SVAL(inbuf, smb_nts_ParameterOffset), parameter_count); + memcpy( &data[SVAL(inbuf, smb_nts_DataDisplacement)], + smb_base(inbuf)+ SVAL(inbuf, smb_nts_DataOffset), data_count); + } + } + + if (Protocol >= PROTOCOL_NT1) { + uint16 flg2 = SVAL(outbuf,smb_flg2); + SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + } + + /* Now we must call the relevant TRANS2 function */ + switch(function_code) + { + case NT_TRANSACT_CREATE: + outsize = call_nt_transact_create(inbuf, outbuf, bufsize, cnum, + &setup, ¶ms, &data); + break; + case NT_TRANSACT_IOCTL: + outsize = call_nt_transact_ioctl(inbuf, outbuf, bufsize, cnum, + &setup, ¶ms, &data); + break; + case NT_TRANSACT_SET_SECURITY_DESC: + outsize = call_nt_transact_set_security_desc(inbuf, outbuf, length, bufsize, cnum, + &setup, ¶ms, &data); + break; + case NT_TRANSACT_NOTIFY_CHANGE: + outsize = call_nt_transact_notify_change(inbuf, outbuf, length, bufsize, cnum, + &setup, ¶ms, &data); + break; + case NT_TRANSACT_RENAME: + outsize = call_nt_transact_rename(inbuf, outbuf, length, bufsize, cnum, + &setup, ¶ms, &data); + break; + case NT_TRANSACT_QUERY_SECURITY_DESC: + outsize = call_nt_transact_query_security_desc(inbuf, outbuf, length, bufsize, cnum, + &setup, ¶ms, &data, total_data); + break; + default: + /* Error in request */ + DEBUG(0,("reply_nttrans: %s Unknown request %d in nttrans call\n",timestring(), + tran_call)); + if(setup) + free(setup); + if(params) + free(params); + if(data) + free(data); + return (ERROR(ERRSRV,ERRerror)); + } + + /* As we do not know how many data packets will need to be + returned here the various call_nt_transact_xxxx calls + must send their own. Thus a call_nt_transact_xxxx routine only + returns a value other than -1 when it wants to send + an error packet. + */ + + if(setup) + free(setup); + if(params) + free(params); + if(data) + free(data); + return outsize; /* If a correct response was needed the call_nt_transact_xxxx + calls have already sent it. If outsize != -1 then it is + returning an error packet. */ +} -- cgit From 9273102ea54d010043e6fdfaf1c61116eb93562e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 May 1998 01:23:11 +0000 Subject: smb.h: Supporting defines for NT trans calls. trans2.c: Paranoia bugfixes added when studying nttrans.c. Jeremy. (This used to be commit 94e70edef91c71703a7ebcdaf2b5a2bdce940a69) --- source3/smbd/trans2.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 75cf18785c..af70064ef4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1787,8 +1787,10 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) if (num_params > total_params || num_data > total_data) exit_server("invalid params in reply_trans2"); - memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); - memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); + if(params) + memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); + if(data) + memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); if(num_data_sofar < total_data || num_params_sofar < total_params) { @@ -1812,8 +1814,10 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) else DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - free(params); - free(data); + if(params) + free(params); + if(data) + free(data); return(ERROR(ERRSRV,ERRerror)); } -- cgit From 9f57f01b144b030274cc5d116b864b3c27f251ef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 May 1998 16:59:30 +0000 Subject: clitar.c: #ifdef'ed out all the bits that were giving 'defined but not used' messages. nttrans.c: More updates. smb.h: Removed stuff that didn't belong in the smb_passwd struct. Persuaded Luke to use a new structure. web/swat.c: Fixed gcc complaints about shadowing global 'string'. Jeremy. (This used to be commit 61c1dbb9785ed1e6fe40f93c7cc65024884df6f5) --- source3/smbd/nttrans.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0a861bf9c6..73f6786a04 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -30,6 +30,20 @@ extern int oplock_sock; extern int smb_read_error; extern int global_oplock_break; +static char *known_nt_pipes[] = { + "\\LANMAN", + "\\srvsvc", + "\\samr", + "\\wkssvc", + "\\NETLOGON", + "\\ntlsa", + "\\ntsvcs", + "\\lsass", + "\\lsarpc", + NULL +}; + + /**************************************************************************** reply to an unsolicited SMBNTtranss - just ignore it! ****************************************************************************/ @@ -166,9 +180,8 @@ due to being in oplock break state.\n", timestring() )); SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ } - /* Now we must call the relevant TRANS2 function */ - switch(function_code) - { + /* Now we must call the relevant NT_TRANS function */ + switch(function_code) { case NT_TRANSACT_CREATE: outsize = call_nt_transact_create(inbuf, outbuf, bufsize, cnum, &setup, ¶ms, &data); @@ -204,7 +217,7 @@ due to being in oplock break state.\n", timestring() )); if(data) free(data); return (ERROR(ERRSRV,ERRerror)); - } + } /* As we do not know how many data packets will need to be returned here the various call_nt_transact_xxxx calls -- cgit From 839e47c5a62fb42d3e0b2e083ad23243e9cec566 Mon Sep 17 00:00:00 2001 From: John Terpstra Date: Sun, 10 May 1998 06:20:27 +0000 Subject: Updated OSF1_ENH_SEC mode password handling. This now tries Enhanced passwords first and if this fails trys Basic mode (ie: Unix /etc/passwd) authentication. This only happens when OSF1_ENH_SEC is defined at compilation. (This used to be commit 29462c8d7a241eb462b1583170a0b5f16096ea3f) --- source3/smbd/password.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 82e3a024e1..8dfae21ad1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -940,7 +940,14 @@ Hence we make a direct return to avoid a second chance!!! #endif #ifdef OSF1_ENH_SEC - return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0); + { + BOOL ret = (strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0); + if(!ret) { + DEBUG(2,("password_check: OSF1_ENH_SEC failed. Trying normal crypt.\n")); + ret = (strcmp((char *)crypt(password,this_salt),this_crypted) == 0); + } + return ret; + } #endif #ifdef ULTRIX_AUTH -- cgit From 3dfc0c847240ac7e12c39f4ed9c31a888949ade1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 May 1998 06:38:36 +0000 Subject: changed to use slprintf() instead of sprintf() just about everywhere. I've implemented slprintf() as a bounds checked sprintf() using mprotect() and a non-writeable page. This should prevent any sprintf based security holes. (This used to be commit ee09e9dadb69aaba5a751dd20ccc6d587d841bd6) --- source3/smbd/message.c | 2 +- source3/smbd/password.c | 14 +++++++------- source3/smbd/reply.c | 10 +++++----- source3/smbd/server.c | 8 ++++---- source3/smbd/trans2.c | 4 ++-- source3/smbd/uid.c | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 24477f31ff..b368c4d031 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -53,7 +53,7 @@ static void msg_deliver(void) } /* put it in a temporary file */ - sprintf(s,"%s/msg.XXXXXX",tmpdir()); + slprintf(s,sizeof(s)-1, "%s/msg.XXXXXX",tmpdir()); fstrcpy(name,(char *)mktemp(s)); fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8dfae21ad1..67de0523e8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1044,7 +1044,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_password_check(nt_pass, (uchar *)smb_pass->smb_nt_passwd, challenge)) + if (smb_password_check((char *)nt_pass, (uchar *)smb_pass->smb_nt_passwd, challenge)) { DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); return(True); @@ -1063,7 +1063,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, return True; } - if((smb_pass->smb_passwd != NULL) && smb_password_check(lm_pass, (uchar *)smb_pass->smb_passwd, challenge)) + if((smb_pass->smb_passwd != NULL) && smb_password_check((char *)lm_pass, (uchar *)smb_pass->smb_passwd, challenge)) { DEBUG(4,("smb_password_ok: LM MD4 password check succeeded\n")); return(True); @@ -1153,7 +1153,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } - if(smb_password_ok( smb_pass, password, password)) + if(smb_password_ok( smb_pass, (unsigned char *)password,(uchar *)password)) { update_protected_database(user,True); return(True); @@ -1704,7 +1704,7 @@ BOOL check_hosts_equiv(char *user) char *home = get_home_dir(user); if (home) { extern int Client; - sprintf(rhostsfile, "%s/.rhosts", home); + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); if (check_user_equiv(user,client_name(Client),rhostsfile)) return(True); } @@ -1953,8 +1953,8 @@ BOOL domain_client_validate( char *user, char *domain, DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); generate_random_buffer( local_challenge, 8, False); - SMBencrypt( smb_apasswd, local_challenge, local_lm_response); - SMBNTencrypt( smb_ntpasswd, local_challenge, local_nt_reponse); + SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); + SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_reponse); smb_apasslen = 24; smb_ntpasslen = 24; smb_apasswd = (char *)local_lm_response; @@ -2127,7 +2127,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); /* We really don't care what LUID we give the user. */ generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - if(cli_nt_login_network(&cli, domain, user, smb_uid_low, local_challenge, + if(cli_nt_login_network(&cli, domain, user, smb_uid_low, (char *)local_challenge, smb_apasswd, smb_ntpasswd, &ctr, &info3) == False) { DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ %s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1567e52777..b8270495fd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1149,7 +1149,7 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) smb_setlen(outbuf,outsize - 4); if ((! *directory) && dptr_path(dptr_num)) - sprintf(directory,"(%s)",dptr_path(dptr_num)); + slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n", timestring(), @@ -1716,7 +1716,7 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(!mask_match(fname, mask, case_sensitive, False)) continue; error = ERRnoaccess; - sprintf(fname,"%s/%s",directory,dname); + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,cnum,dirtype)) continue; if (!sys_unlink(fname)) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); @@ -2622,7 +2622,7 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (strlen(s) > 10) s[10] = 0; - sprintf(fname,"%s.XXXXXX",s); + slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s); } fnum = find_free_file(); @@ -3238,7 +3238,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(!mask_match(fname, mask, case_sensitive, False)) continue; error = ERRnoaccess; - sprintf(fname,"%s/%s",directory,dname); + slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); if (!can_rename(fname,cnum)) { DEBUG(6,("rename %s refused\n", fname)); continue; @@ -3451,7 +3451,7 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(!mask_match(fname, mask, case_sensitive, False)) continue; error = ERRnoaccess; - sprintf(fname,"%s/%s",directory,dname); + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); strcpy(destname,newname); if (resolve_wildcards(fname,destname) && copy_file(directory,newname,cnum,ofun, diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e4c00c141f..7788b142e0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -563,7 +563,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa { char *s; fstring name2; - sprintf(name2,"%.6s.XXXXXX",remote_machine); + slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); /* sanitise the name */ for (s=name2 ; *s ; s++) if (!issafe(*s)) *s = '_'; @@ -754,8 +754,8 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) pstring syscmd; pstring outfile; - sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid()); - sprintf(syscmd,"%s %s",df_command,path); + slprintf(outfile,sizeof(outfile)-1, "%s/dfree.smb.%d",tmpdir(),(int)getpid()); + slprintf(syscmd,sizeof(syscmd)-1,"%s %s",df_command,path); standard_sub_basic(syscmd); ret = smbrun(syscmd,outfile,False); @@ -1439,7 +1439,7 @@ static void check_magic(int fnum,int cnum) if (*lp_magicoutput(SNUM(cnum))) pstrcpy(magic_output,lp_magicoutput(SNUM(cnum))); else - sprintf(magic_output,"%s.out",fname); + slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); chmod(fname,0755); ret = smbrun(fname,magic_output,False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index af70064ef4..fb45efcc0b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -772,7 +772,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); if ((! *directory) && dptr_path(dptr_num)) - sprintf(directory,"(%s)",dptr_path(dptr_num)); + slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", timestring(), @@ -985,7 +985,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); if ((! *directory) && dptr_path(dptr_num)) - sprintf(directory,"(%s)",dptr_path(dptr_num)); + slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", timestring(), diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index a8e340e46f..749248ac86 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -420,7 +420,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared) return(1); } - sprintf(syscmd,"%s %d %d \"(%s 2>&1) > %s\"", + slprintf(syscmd,sizeof(syscmd)-1,"%s %d %d \"(%s 2>&1) > %s\"", path,uid,gid,cmd, outfile?outfile:"/dev/null"); -- cgit From f004d84f683673b7cb167320e3e78a3fcefdfd07 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 11 May 1998 15:56:01 +0000 Subject: ldap back-end database development Makefile: created PASSBD_OBJ group includes.h: added #ifdef USE_LDAP to #include headers ldap.c: - renamed "_machine" to "_trust" everywhere. - added sam_passwd support routines - removed get_ldappwd_entry function: replaced with get_sampwd_entry - removed getldappwnam/uid: replaced with getsampwnam/uid - other messing about bits which are probably going to annoy the hell out of jean-francois (sorry!) mkproto.awk: - added stuff to wrap ldap.c protos with #ifdef USE_LDAP - added uid_t and gid_t return results to the prototype generation passdb.c: - created getsam21pwent, add_sam21pwd_entry, mod_sam21pwd_entry. - modified getsampwnam/uid and created getsam21pwnam/rid functions to replace the local get_smbpwd_entry() and get_ldappwd_entry() functions, which jeremy didn't like anyway because they were dual-purpose. - added utility routines which are or may be useful to all the password database routines. password.c: - renamed "machine_" to "trust_" everywhere. smbpass.c: - removed get_smbpwd_entry function: replaced it with get_sampwd_entry functions in passdb.c - moved code that decoded acct_ctrl into passdb.c - moved encode_acct_ctrl into passdb.c - removed getsmbpwnam/uid: replaced with getsampwnam/uid - renamed "machine_" to "trust_" everywhere. smbpasswd.c: - renamed "machine_" to "trust_" everywhere. util.c: - moved gethexpwd function into passdb.c lib/rpc/server/srv_util.c: - moved user_rid_to_uid, group_rid_to_rid etc etc into passdb.c (This used to be commit 673ab50c4c2c25db355d90efde3a6bfbb4d8369e) --- source3/smbd/password.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 67de0523e8..327bfba371 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1919,7 +1919,7 @@ BOOL domain_client_validate( char *user, char *domain, unsigned char local_challenge[8]; unsigned char local_lm_response[24]; unsigned char local_nt_reponse[24]; - unsigned char machine_passwd[16]; + unsigned char trust_passwd[16]; time_t lct; fstring remote_machine; char *p; @@ -1977,20 +1977,20 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password. */ - if(!machine_password_lock( global_myworkgroup, global_myname, False)) { + if(!trust_password_lock( global_myworkgroup, global_myname, False)) { DEBUG(0,("domain_client_validate: unable to open the machine account password file for \ machine %s in domain %s.\n", global_myname, global_myworkgroup )); return False; } - if(get_machine_account_password( machine_passwd, &lct) == False) { + if(get_trust_account_password( trust_passwd, &lct) == False) { DEBUG(0,("domain_client_validate: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname, global_myworkgroup )); - machine_password_unlock(); + trust_password_unlock(); return False; } - machine_password_unlock(); + trust_password_unlock(); unbecome_root(False); @@ -2115,7 +2115,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); return False; } - if(cli_nt_setup_creds(&cli, machine_passwd) == False) { + if(cli_nt_setup_creds(&cli, trust_passwd) == False) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); cli_nt_session_close(&cli); -- cgit From 05eb22f77c21f8027e64b0caddefa4d9f030f95f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 May 1998 17:53:37 +0000 Subject: reply.c: Added code to not overwrite sesssetup_user when in share level security and null session setup done. smbpasswd.c: Fix from Gerald Carter to fix incorrect use of pointer. Jeremy. (This used to be commit 69ace0760986a6e892cd5b25ca85930b65e38c45) --- source3/smbd/reply.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b8270495fd..c927e09425 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -586,7 +586,14 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) strlower(user); - strcpy(sesssetup_user,user); + /* + * In share level security, only overwrite sesssetup_use if + * it's a non null-session share. Helps keep %U and %G + * working. + */ + + if((lp_security() != SEC_SHARE) || *user) + strcpy(sesssetup_user,user); reload_services(True); -- cgit From f888868f46a5418bac9ab528497136c152895305 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 May 1998 00:55:32 +0000 Subject: This is a security audit change of the main source. It removed all ocurrences of the following functions : sprintf strcpy strcat The replacements are slprintf, safe_strcpy and safe_strcat. It should not be possible to use code in Samba that uses sprintf, strcpy or strcat, only the safe_equivalents. Once Andrew has fixed the slprintf implementation then this code will be moved back to the 1.9.18 code stream. Jeremy. (This used to be commit 2d774454005f0b54e5684cf618da7060594dfcbb) --- source3/smbd/chgpasswd.c | 4 +- source3/smbd/connection.c | 12 ++--- source3/smbd/dir.c | 14 +++--- source3/smbd/ipc.c | 60 ++++++++++++------------- source3/smbd/mangle.c | 16 +++---- source3/smbd/password.c | 50 ++++++++++----------- source3/smbd/quotas.c | 14 +++--- source3/smbd/reply.c | 112 +++++++++++++++++++++++----------------------- source3/smbd/server.c | 56 +++++++++++------------ source3/smbd/trans2.c | 38 ++++++++-------- source3/smbd/vt_mode.c | 10 ++--- 11 files changed, 193 insertions(+), 193 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e466455aeb..d900b54c1f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -62,7 +62,7 @@ static int findpty(char **slave) #if defined(SVR4) || defined(SUNOS5) extern char *ptsname(); #else /* defined(SVR4) || defined(SUNOS5) */ - static char line[12]; + static fstring line; void *dirp; char *dpname; #endif /* defined(SVR4) || defined(SUNOS5) */ @@ -75,7 +75,7 @@ static int findpty(char **slave) return (master); } #else /* defined(SVR4) || defined(SUNOS5) */ - strcpy( line, "/dev/ptyXX" ); + fstrcpy( line, "/dev/ptyXX" ); dirp = OpenDir(-1, "/dev", True); if (!dirp) return(-1); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5cf8b800f2..64b3f153cf 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -48,9 +48,9 @@ BOOL yield_connection(int cnum,char *name,int max_connections) pstrcpy(fname,lp_lockdir()); trim_string(fname,"","/"); - strcat(fname,"/"); - strcat(fname,name); - strcat(fname,".LCK"); + pstrcat(fname,"/"); + pstrcat(fname,name); + pstrcat(fname,".LCK"); fd = open(fname,O_RDWR); if (fd == -1) { @@ -133,9 +133,9 @@ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) if (!directory_exist(fname,NULL)) mkdir(fname,0755); - strcat(fname,"/"); - strcat(fname,name); - strcat(fname,".LCK"); + pstrcat(fname,"/"); + pstrcat(fname,name); + pstrcat(fname,".LCK"); if (!file_exist(fname,NULL)) { fd = open(fname,O_RDWR|O_CREAT|O_EXCL, 0644); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index a34406cc65..37fcd05743 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -469,10 +469,10 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo *path = 0; pstrcpy(path,Connections[cnum].dirpath); if(needslash) - strcat(path,"/"); + pstrcat(path,"/"); pstrcpy(pathreal,path); - strcat(path,fname); - strcat(pathreal,dname); + pstrcat(path,fname); + pstrcat(pathreal,dname); if (sys_stat(pathreal,&sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]\n",path)); @@ -552,7 +552,7 @@ void *OpenDir(int cnum, char *name, BOOL use_veto) dirp->mallocsize = s; dirp->current = dirp->data; } - strcpy(dirp->data+used,n); + pstrcpy(dirp->data+used,n); used += l; dirp->numentries++; } @@ -671,9 +671,9 @@ void DirCacheAdd( char *path, char *name, char *dname, int snum ) return; /* so just return as if nothing happened. */ /* Set pointers correctly and load values. */ - entry->path = strcpy( (char *)&entry[1], path); - entry->name = strcpy( &(entry->path[pathlen]), name); - entry->dname = strcpy( &(entry->name[namelen]), dname); + entry->path = pstrcpy( (char *)&entry[1], path); + entry->name = pstrcpy( &(entry->path[pathlen]), name); + entry->dname = pstrcpy( &(entry->name[namelen]), dname); entry->snum = snum; /* Add the new entry to the linked list. */ diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8be9c10a13..7b82894c7f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -491,7 +491,7 @@ static void PackDriverData(struct pack_desc* desc) SIVAL(drivdata,0,sizeof drivdata); /* cb */ SIVAL(drivdata,4,1000); /* lVersion */ memset(drivdata+8,0,32); /* szDeviceName */ - strcpy(drivdata+8,"NULL"); + pstrcpy(drivdata+8,"NULL"); PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ } @@ -650,7 +650,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, FILE *f; pstring fname; - strcpy(fname,lp_driverfile()); + pstrcpy(fname,lp_driverfile()); f=fopen(fname,"r"); if (!f) { DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno))); @@ -748,7 +748,7 @@ int get_printerdrivernumber(int snum) FILE *f; pstring fname; - strcpy(fname,lp_driverfile()); + pstrcpy(fname,lp_driverfile()); DEBUG(4,("In get_printerdrivernumber: %s\n",fname)); f=fopen(fname,"r"); @@ -993,8 +993,8 @@ static int get_server_info(uint32 servertype, pstrcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,SERVER_LIST); + pstrcat(fname,"/"); + pstrcat(fname,SERVER_LIST); f = fopen(fname,"r"); @@ -1036,7 +1036,7 @@ static int get_server_info(uint32 servertype, if (!next_token(&ptr,s->comment, NULL)) continue; if (!next_token(&ptr,s->domain , NULL)) { /* this allows us to cope with an old nmbd */ - strcpy(s->domain,global_myworkgroup); + pstrcpy(s->domain,global_myworkgroup); } if (sscanf(stype,"%X",&s->type) != 1) { @@ -2115,18 +2115,18 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data, SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ - strcpy(p2,local_machine); + pstrcpy(p2,local_machine); strupper(p2); p2 = skip_string(p2,1); p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,sesssetup_user); + pstrcpy(p2,sesssetup_user); p2 = skip_string(p2,1); p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ - strcpy(p2,global_myworkgroup); + pstrcpy(p2,global_myworkgroup); strupper(p2); p2 = skip_string(p2,1); p += 4; @@ -2136,12 +2136,12 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data, p += 2; SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,global_myworkgroup); /* don't know. login domain?? */ + pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */ p2 = skip_string(p2,1); p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ - strcpy(p2,""); + pstrcpy(p2,""); p2 = skip_string(p2,1); p += 4; @@ -2378,16 +2378,16 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, if (uLevel >= 10) { SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ - strcpy(p2,"Comment"); + pstrcpy(p2,"Comment"); p2 = skip_string(p2,1); SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ - strcpy(p2,"UserComment"); + pstrcpy(p2,"UserComment"); p2 = skip_string(p2,1); /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); + pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); } @@ -2397,22 +2397,22 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - strcpy(p2, lp_logon_path()); + pstrcpy(p2, lp_logon_path()); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ - strcpy(p2,""); + pstrcpy(p2,""); p2 = skip_string(p2,1); SIVAL(p,usri11_last_logon,0); /* last logon */ SIVAL(p,usri11_last_logoff,0); /* last logoff */ SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ SSVALS(p,usri11_num_logons,-1); /* num logons */ SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ - strcpy(p2,"\\\\*"); + pstrcpy(p2,"\\\\*"); p2 = skip_string(p2,1); SSVAL(p,usri11_country_code,0); /* country code */ SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ - strcpy(p2,""); + pstrcpy(p2,""); p2 = skip_string(p2,1); SIVALS(p,usri11_max_storage,-1); /* max storage */ @@ -2433,7 +2433,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SSVAL(p,42, Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - strcpy(p2,lp_logon_path()); + pstrcpy(p2,lp_logon_path()); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; @@ -2443,11 +2443,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); + pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ - strcpy(p2,""); + pstrcpy(p2,""); p2 = skip_string(p2,1); SIVAL(p,76,0); /* workstations */ SIVAL(p,80,0); /* last_logon */ @@ -2461,7 +2461,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SSVALS(p,102,-1); /* bad_pw_count */ SSVALS(p,104,-1); /* num_logons */ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ - strcpy(p2,"\\\\%L"); + pstrcpy(p2,"\\\\%L"); standard_sub_basic(p2); p2 = skip_string(p2,1); SSVAL(p,110,49); /* country_code */ @@ -2512,10 +2512,10 @@ static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data, p = *rdata; /* XXXX we need a real SAM database some day */ - strcpy(p,"Users"); p += 21; count++; - strcpy(p,"Domain Users"); p += 21; count++; - strcpy(p,"Guests"); p += 21; count++; - strcpy(p,"Domain Guests"); p += 21; count++; + pstrcpy(p,"Users"); p += 21; count++; + pstrcpy(p,"Domain Users"); p += 21; count++; + pstrcpy(p,"Guests"); p += 21; count++; + pstrcpy(p,"Domain Guests"); p += 21; count++; *rdata_len = PTR_DIFF(p,*rdata); @@ -2574,8 +2574,8 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, PACKI(&desc,"D",-1); /* password must change */ { fstring mypath; - strcpy(mypath,"\\\\"); - strcat(mypath,local_machine); + fstrcpy(mypath,"\\\\"); + fstrcat(mypath,local_machine); strupper(mypath); PACKS(&desc,"z",mypath); /* computer */ } @@ -3129,8 +3129,8 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) } /* name has to be \PIPE\xxxxx */ - strcpy(ack_pipe_name, "\\PIPE\\"); - strcat(ack_pipe_name, p->pipe_srv_name); + fstrcpy(ack_pipe_name, "\\PIPE\\"); + fstrcat(ack_pipe_name, p->pipe_srv_name); DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index eb267faab3..e822894600 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -648,9 +648,9 @@ BOOL check_mangled_cache( char *s ) DEBUG( 3, ("Found %s on mangled stack ", s) ); - (void)strcpy( s, found_name ); + (void)pstrcpy( s, found_name ); if( ext_start ) - (void)strcat( s, ext_start ); + (void)pstrcat( s, ext_start ); DEBUG( 3, ("as %s\n", s) ); @@ -830,7 +830,7 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) * * ************************************************************************** ** */ -void mangle_name_83( char *s ) +void mangle_name_83( char *s, int s_len ) { int csum = str_checksum(s); char *p; @@ -863,7 +863,7 @@ void mangle_name_83( char *s ) if( p ) { if( p == s ) - strcpy( extension, "___" ); + safe_strcpy( extension, "___", 3 ); else { *p++ = 0; @@ -933,13 +933,13 @@ void mangle_name_83( char *s ) csum = csum % (36*36); - (void)sprintf( s, "%s%c%c%c", + (void)slprintf( s, s_len - 1, "%s%c%c%c", base, magic_char, base36( csum/36 ), base36( csum ) ); if( *extension ) { - (void)strcat( s, "." ); - (void)strcat( s, extension ); + (void)pstrcat( s, "." ); + (void)pstrcat( s, extension ); } DEBUG( 5, ( "%s\n", s ) ); @@ -996,7 +996,7 @@ BOOL name_map_mangle( char *OutName, BOOL need83, int snum ) /* mangle it into 8.3 */ tmp = strdup( OutName ); - mangle_name_83( OutName ); + mangle_name_83( OutName, strlen(tmp) ); if( tmp ) { cache_mangled_name( OutName, tmp ); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 327bfba371..3040775e03 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -349,8 +349,8 @@ void add_session_user(char *user) DEBUG(1,("Too many session users??\n")); else { - strcat(session_users," "); - strcat(session_users,suser); + pstrcat(session_users," "); + pstrcat(session_users,suser); } } } @@ -364,7 +364,7 @@ static struct spwd *getspnam(char *username) /* fake shadow password routine */ { FILE *f; char line[1024]; - static char pw[20]; + static fstring pw; static struct spwd static_spwd; static_spwd.sp_pwdp=0; @@ -380,7 +380,7 @@ static struct spwd *getspnam(char *username) /* fake shadow password routine */ *q=0; if (q-p+1>20) break; - strcpy(pw, p); + fstrcpy(pw, p); static_spwd.sp_pwdp=pw; } break; @@ -415,7 +415,7 @@ static char *osf1_bigcrypt(char *password,char *salt1) for (i=0; ipw_name,mypasswd->ufld.fd_name); - strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt); + fstrcpy(pass->pw_name,mypasswd->ufld.fd_name); + fstrcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt); } else { @@ -1233,20 +1233,20 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) AUTHORIZATION *ap = getauthuid( pass->pw_uid ); if (ap) { - strcpy( pass->pw_passwd, ap->a_password ); + fstrcpy( pass->pw_passwd, ap->a_password ); endauthent(); } } #endif /* extract relevant info */ - strcpy(this_user,pass->pw_name); - strcpy(this_salt,pass->pw_passwd); + fstrcpy(this_user,pass->pw_name); + fstrcpy(this_salt,pass->pw_passwd); #ifdef HPUX /* The crypt on HPUX won't work with more than 2 salt characters. */ this_salt[2] = 0; #endif /* HPUX */ - strcpy(this_crypted,pass->pw_passwd); + fstrcpy(this_crypted,pass->pw_passwd); if (!*this_crypted) { if (!lp_null_passwords()) { @@ -1295,7 +1295,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) update_protected_database(user,False); /* restore it */ - strcpy(password,pass2); + fstrcpy(password,pass2); return(False); } @@ -1314,7 +1314,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) update_protected_database(user,False); /* restore it */ - strcpy(password,pass2); + fstrcpy(password,pass2); return(False); } @@ -1384,7 +1384,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (member && *member) { static fstring name; - strcpy(name,*member); + fstrcpy(name,*member); if (user_ok(name,snum) && password_ok(name,password,pwlen,NULL)) return(&name[0]); @@ -1400,7 +1400,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { /* This Entry have PASSWORD and same GID then check pwd */ if (password_ok(NULL, password, pwlen, pwd)) { - strcpy(tm, pwd->pw_name); + fstrcpy(tm, pwd->pw_name); endpwent (); return tm; } @@ -1460,7 +1460,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->name,snum) && password_ok(vuser->name, password, pwlen, NULL)) { - strcpy(user, vuser->name); + fstrcpy(user, vuser->name); vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); ok = True; @@ -1480,12 +1480,12 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, auser = strtok(NULL,LIST_SEP)) { fstring user2; - strcpy(user2,auser); + fstrcpy(user2,auser); if (!user_ok(user2,snum)) continue; if (password_ok(user2,password, pwlen, NULL)) { ok = True; - strcpy(user,user2); + fstrcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); } } @@ -1496,7 +1496,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!ok && !lp_revalidate(snum) && (vuser != 0) && !vuser->guest && user_ok(vuser->name,snum)) { - strcpy(user,vuser->name); + fstrcpy(user,vuser->name); *guest = False; DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); ok = True; @@ -1526,19 +1526,19 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (auser) { ok = True; - strcpy(user,auser); + fstrcpy(user,auser); DEBUG(3,("ACCEPTED: group username and given password ok\n")); } } else { fstring user2; - strcpy(user2,auser); + fstrcpy(user2,auser); if (user_ok(user2,snum) && password_ok(user2,password,pwlen,NULL)) { ok = True; - strcpy(user,user2); + fstrcpy(user,user2); DEBUG(3,("ACCEPTED: user list username and given password ok\n")); } } @@ -1553,7 +1553,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); if (Get_Pwnam(guestname,True)) { - strcpy(user,guestname); + fstrcpy(user,guestname); ok = True; DEBUG(3,("ACCEPTED: guest account and guest ok\n")); } diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index df85f79b9b..ee08e48e65 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -138,7 +138,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) struct stat sbuf; dev_t devno ; static dev_t devno_cached = 0 ; - static char name[MNTMAXSTR] ; + static pstring name; struct q_request request ; struct qf_header header ; static int quota_default = 0 ; @@ -172,7 +172,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } - strcpy(name,mnt->mnt_dir) ; + pstrcpy(name,mnt->mnt_dir) ; endmntent(fd) ; if ( ! found ) @@ -249,10 +249,10 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) struct quotctl command; int file; struct mnttab mnt; - static char name[MNT_LINE_MAX] ; + static pstring name; #else struct mntent *mnt; - static char name[MNTMAXSTR] ; + static pstring name; #endif FILE *fd; struct stat sbuf; @@ -283,8 +283,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } } - strcpy(name,mnt.mnt_mountp) ; - strcat(name,"/quotas") ; + pstrcpy(name,mnt.mnt_mountp) ; + pstrcat(name,"/quotas") ; fclose(fd) ; #else if ((fd = setmntent(MOUNTED, "r")) == NULL) @@ -302,7 +302,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } } - strcpy(name,mnt->mnt_fsname) ; + pstrcpy(name,mnt->mnt_fsname) ; endmntent(fd) ; #endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c927e09425..21a20b0712 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -308,7 +308,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { set_message(outbuf,2,strlen(devicename)+1,True); - strcpy(smb_buf(outbuf),devicename); + pstrcpy(smb_buf(outbuf),devicename); } else { @@ -318,8 +318,8 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,3,3,True); p = smb_buf(outbuf); - strcpy(p,devicename); p = skip_string(p,1); /* device name */ - strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ + pstrcpy(p,devicename); p = skip_string(p,1); /* device name */ + pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); @@ -578,7 +578,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* If no username is sent use the guest account */ if (!*user) { - strcpy(user,lp_guestaccount(-1)); + pstrcpy(user,lp_guestaccount(-1)); /* If no user and no password then set guest flag. */ if( *smb_apasswd == 0) guest = True; @@ -593,7 +593,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) */ if((lp_security() != SEC_SHARE) || *user) - strcpy(sesssetup_user,user); + pstrcpy(sesssetup_user,user); reload_services(True); @@ -641,7 +641,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) #endif } if (*smb_apasswd || !Get_Pwnam(user,True)) - strcpy(user,lp_guestaccount(-1)); + pstrcpy(user,lp_guestaccount(-1)); DEBUG(3,("Registered username %s for guest access\n",user)); guest = True; } @@ -649,7 +649,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!Get_Pwnam(user,True)) { DEBUG(3,("No such user %s - using guest account\n",user)); - strcpy(user,lp_guestaccount(-1)); + pstrcpy(user,lp_guestaccount(-1)); guest = True; } @@ -670,9 +670,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) char *p; set_message(outbuf,3,3,True); p = smb_buf(outbuf); - strcpy(p,"Unix"); p = skip_string(p,1); - strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1); - strcpy(p,global_myworkgroup); p = skip_string(p,1); + pstrcpy(p,"Unix"); p = skip_string(p,1); + pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1); + pstrcpy(p,global_myworkgroup); p = skip_string(p,1); set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); /* perhaps grab OS version here?? */ } @@ -984,7 +984,7 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) p = strrchr(dir2,'/'); if (p == NULL) { - strcpy(mask,dir2); + pstrcpy(mask,dir2); *dir2 = 0; } else @@ -1000,7 +1000,7 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) *p = 0; if (strlen(directory) == 0) - strcpy(directory,"./"); + pstrcpy(directory,"./"); bzero(status,21); CVAL(status,0) = dirtype; } @@ -1027,8 +1027,8 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) fstrcpy(ext,p+1); *p = 0; trim_string(mask,NULL," "); - strcat(mask,"."); - strcat(mask,ext); + pstrcat(mask,"."); + pstrcat(mask,ext); } } @@ -1049,7 +1049,7 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) fstrcpy(tmp,&mask[8]); mask[8] = '.'; mask[9] = 0; - strcat(mask,tmp); + pstrcat(mask,tmp); } DEBUG(5,("mask=%s directory=%s\n",mask,directory)); @@ -1566,7 +1566,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - strcat(fname,"/TMXXXXXX"); + pstrcat(fname,"/TMXXXXXX"); unix_convert(fname,cnum,0,&bad_path); unixmode = unix_mode(cnum,createmode); @@ -1586,7 +1586,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - strcpy(fname2,(char *)mktemp(fname)); + pstrcpy(fname2,(char *)mktemp(fname)); /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ @@ -1609,7 +1609,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,1,2 + strlen(fname2),True); SSVAL(outbuf,smb_vwv0,fnum); CVAL(smb_buf(outbuf),0) = 4; - strcpy(smb_buf(outbuf) + 1,fname2); + pstrcpy(smb_buf(outbuf) + 1,fname2); if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; @@ -1678,12 +1678,12 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) p = strrchr(name,'/'); if (!p) { - strcpy(directory,"./"); - strcpy(mask,name); + pstrcpy(directory,"./"); + pstrcpy(mask,name); } else { *p = 0; - strcpy(directory,name); - strcpy(mask,p+1); + pstrcpy(directory,name); + pstrcpy(mask,p+1); } if (is_mangled(mask)) @@ -1692,8 +1692,8 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) has_wild = strchr(mask,'*') || strchr(mask,'?'); if (!has_wild) { - strcat(directory,"/"); - strcat(directory,mask); + pstrcat(directory,"/"); + pstrcat(directory,mask); if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++; if (!count) exists = file_exist(directory,NULL); } else { @@ -1713,7 +1713,7 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) error = ERRbadfile; if (strequal(mask,"????????.???")) - strcpy(mask,"*"); + pstrcpy(mask,"*"); while ((dname = ReadDirName(dirptr))) { @@ -2636,7 +2636,7 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); - strcpy(fname2,(char *)mktemp(fname)); + pstrcpy(fname2,(char *)mktemp(fname)); if (!check_name(fname2,cnum)) { Files[fnum].reserved = False; @@ -2877,9 +2877,9 @@ static BOOL recursive_rmdir(char *directory) ret = True; break; } - strcpy(fullname, directory); - strcat(fullname, "/"); - strcat(fullname, dname); + pstrcpy(fullname, directory); + pstrcat(fullname, "/"); + pstrcat(fullname, dname); if(sys_lstat(fullname, &st) != 0) { @@ -2971,8 +2971,8 @@ int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) break; } pstrcpy(fullname, directory); - strcat(fullname, "/"); - strcat(fullname, dname); + pstrcat(fullname, "/"); + pstrcat(fullname, dname); if(sys_lstat(fullname, &st) != 0) break; @@ -3078,10 +3078,10 @@ static BOOL resolve_wildcards(char *name1,char *name2) if (*p) p++; } - strcpy(name2,root2); + pstrcpy(name2,root2); if (ext2[0]) { - strcat(name2,"."); - strcat(name2,ext2); + pstrcat(name2,"."); + pstrcat(name2,ext2); } return(True); @@ -3144,12 +3144,12 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) p = strrchr(name,'/'); if (!p) { - strcpy(directory,"."); - strcpy(mask,name); + pstrcpy(directory,"."); + pstrcpy(mask,name); } else { *p = 0; - strcpy(directory,name); - strcpy(mask,p+1); + pstrcpy(directory,name); + pstrcpy(mask,p+1); *p = '/'; /* Replace needed for exceptional test below. */ } @@ -3162,16 +3162,16 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) BOOL is_short_name = is_8_3(name, True); /* Add a terminating '/' to the directory name. */ - strcat(directory,"/"); - strcat(directory,mask); + pstrcat(directory,"/"); + pstrcat(directory,mask); /* Ensure newname contains a '/' also */ if(strrchr(newname,'/') == 0) { pstring tmpstr; - strcpy(tmpstr, "./"); - strcat(tmpstr, newname); - strcpy(newname, tmpstr); + pstrcpy(tmpstr, "./"); + pstrcat(tmpstr, newname); + pstrcpy(newname, tmpstr); } DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", @@ -3197,7 +3197,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) * character above. */ p = strrchr(newname,'/'); - strcpy(newname_modified_last_component,p+1); + pstrcpy(newname_modified_last_component,p+1); if(strcsequal(newname_modified_last_component, newname_last_component) == False) { @@ -3205,7 +3205,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) * Replace the modified last component with * the original. */ - strcpy(p+1, newname_last_component); + pstrcpy(p+1, newname_last_component); } } @@ -3235,7 +3235,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) error = ERRbadfile; if (strequal(mask,"????????.???")) - strcpy(mask,"*"); + pstrcpy(mask,"*"); while ((dname = ReadDirName(dirptr))) { @@ -3309,8 +3309,8 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, p++; else p = src; - strcat(dest,"/"); - strcat(dest,p); + pstrcat(dest,"/"); + pstrcat(dest,p); } if (!file_exist(src,&st)) return(False); @@ -3415,12 +3415,12 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) p = strrchr(name,'/'); if (!p) { - strcpy(directory,"./"); - strcpy(mask,name); + pstrcpy(directory,"./"); + pstrcpy(mask,name); } else { *p = 0; - strcpy(directory,name); - strcpy(mask,p+1); + pstrcpy(directory,name); + pstrcpy(mask,p+1); } if (is_mangled(mask)) @@ -3429,8 +3429,8 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) has_wild = strchr(mask,'*') || strchr(mask,'?'); if (!has_wild) { - strcat(directory,"/"); - strcat(directory,mask); + pstrcat(directory,"/"); + pstrcat(directory,mask); if (resolve_wildcards(directory,newname) && copy_file(directory,newname,cnum,ofun, count,target_is_directory)) count++; @@ -3448,7 +3448,7 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) error = ERRbadfile; if (strequal(mask,"????????.???")) - strcpy(mask,"*"); + pstrcpy(mask,"*"); while ((dname = ReadDirName(dirptr))) { @@ -3459,7 +3459,7 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - strcpy(destname,newname); + pstrcpy(destname,newname); if (resolve_wildcards(fname,destname) && copy_file(directory,newname,cnum,ofun, count,target_is_directory)) count++; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7788b142e0..540f9f799f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -427,8 +427,8 @@ static BOOL mangled_equal(char *name1, char *name2) if (is_8_3(name2, True)) return(False); - strcpy(tmpname,name2); - mangle_name_83(tmpname); + pstrcpy(tmpname,name2); + mangle_name_83(tmpname,sizeof(tmpname)); return(strequal(name1,tmpname)); } @@ -453,7 +453,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) path = "."; if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) { - strcpy(name, dname); + pstrcpy(name, dname); return(True); } @@ -489,7 +489,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(cnum)); - strcpy(name, dname); + pstrcpy(name, dname); CloseDir(cur_dir); return(True); } @@ -547,9 +547,9 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa if(saved_last_component) { end = strrchr(name, '/'); if(end) - strcpy(saved_last_component, end + 1); + pstrcpy(saved_last_component, end + 1); else - strcpy(saved_last_component, name); + pstrcpy(saved_last_component, name); } if (!case_sensitive && @@ -567,7 +567,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa /* sanitise the name */ for (s=name2 ; *s ; s++) if (!issafe(*s)) *s = '_'; - strcpy(name,(char *)mktemp(name2)); + pstrcpy(name,(char *)mktemp(name2)); } return(True); } @@ -604,7 +604,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa if (end) *end = 0; if(saved_last_component != 0) - strcpy(saved_last_component, end ? end + 1 : start); + pstrcpy(saved_last_component, end ? end + 1 : start); /* check if the name exists up to this point */ if (sys_stat(name, &st) == 0) @@ -669,14 +669,14 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa /* restore the rest of the string */ if (end) { - strcpy(start+strlen(start)+1,rest); + pstrcpy(start+strlen(start)+1,rest); end = start + strlen(start); } } /* add to the dirpath that we have resolved so far */ - if (*dirpath) strcat(dirpath,"/"); - strcat(dirpath,start); + if (*dirpath) pstrcat(dirpath,"/"); + pstrcat(dirpath,start); /* restore the / that we wiped out earlier */ if (end) *end = '/'; @@ -990,7 +990,7 @@ static int fd_attempt_open(char *fname, int flags, int mode) if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { - strcat(fname,"."); + pstrcat(fname,"."); fd = sys_open(fname,flags,mode); } @@ -3370,7 +3370,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { if (validated_username(vuid)) { - strcpy(user,validated_username(vuid)); + pstrcpy(user,validated_username(vuid)); return(make_connection(user,user,password,pwlen,dev,vuid)); } } @@ -3381,7 +3381,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de */ if(*sesssetup_user) { - strcpy(user,sesssetup_user); + pstrcpy(user,sesssetup_user); return(make_connection(user,user,password,pwlen,dev,vuid)); } } @@ -3393,14 +3393,14 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de /* you can only connect to the IPC$ service as an ipc device */ if (strequal(service,"IPC$")) - strcpy(dev,"IPC"); + pstrcpy(dev,"IPC"); if (*dev == '?' || !*dev) { if (lp_print_ok(snum)) - strcpy(dev,"LPT1:"); + pstrcpy(dev,"LPT1:"); else - strcpy(dev,"A:"); + pstrcpy(dev,"A:"); } /* if the request is as a printer and you can't print then refuse */ @@ -3964,7 +3964,7 @@ int reply_nt1(char *outbuf) data_len = crypt_len + strlen(global_myworkgroup) + 1; set_message(outbuf,17,data_len,True); - strcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); + pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); CVAL(outbuf,smb_vwv1) = secword; SSVALS(outbuf,smb_vwv16+1,crypt_len); @@ -4221,7 +4221,7 @@ void close_cnum(int cnum, uint16 vuid) if (*lp_postexec(SNUM(cnum)) && become_user(&Connections[cnum], cnum,vuid)) { pstring cmd; - strcpy(cmd,lp_postexec(SNUM(cnum))); + pstrcpy(cmd,lp_postexec(SNUM(cnum))); standard_sub(cnum,cmd); smbrun(cmd,NULL,False); unbecome_user(); @@ -4232,7 +4232,7 @@ void close_cnum(int cnum, uint16 vuid) if (*lp_rootpostexec(SNUM(cnum))) { pstring cmd; - strcpy(cmd,lp_rootpostexec(SNUM(cnum))); + pstrcpy(cmd,lp_rootpostexec(SNUM(cnum))); standard_sub(cnum,cmd); smbrun(cmd,NULL,False); } @@ -4270,7 +4270,7 @@ static BOOL dump_core(void) pstring dname; pstrcpy(dname,debugf); if ((p=strrchr(dname,'/'))) *p=0; - strcat(dname,"/corefiles"); + pstrcat(dname,"/corefiles"); mkdir(dname,0700); sys_chown(dname,getuid(),getgid()); chmod(dname,0700); @@ -5060,9 +5060,9 @@ static void usage(char *pname) TimeInit(); - strcpy(debugf,SMBLOGFILE); + pstrcpy(debugf,SMBLOGFILE); - strcpy(remote_machine, "smb"); + pstrcpy(remote_machine, "smb"); setup_logging(argv[0],False); @@ -5101,10 +5101,10 @@ static void usage(char *pname) switch (opt) { case 'O': - strcpy(user_socket_options,optarg); + pstrcpy(user_socket_options,optarg); break; case 'i': - strcpy(scope,optarg); + pstrcpy(scope,optarg); break; case 'P': { @@ -5113,10 +5113,10 @@ static void usage(char *pname) } break; case 's': - strcpy(servicesf,optarg); + pstrcpy(servicesf,optarg); break; case 'l': - strcpy(debugf,optarg); + pstrcpy(debugf,optarg); break; case 'a': { @@ -5185,7 +5185,7 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); - strcpy(global_myworkgroup, lp_workgroup()); + pstrcpy(global_myworkgroup, lp_workgroup()); #ifndef NO_SIGNAL_TEST signal(SIGHUP,SIGNAL_CAST sig_hup); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fb45efcc0b..db44dc984d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -325,7 +325,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l if(p != NULL) { if(p[1] == '\0') - strcpy(mask,"*.*"); + pstrcpy(mask,"*.*"); else pstrcpy(mask, p+1); } @@ -368,8 +368,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l pstrcpy(pathreal,Connections[cnum].dirpath); if(needslash) - strcat(pathreal,"/"); - strcat(pathreal,dname); + pstrcat(pathreal,"/"); + pstrcat(pathreal,dname); if (sys_stat(pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); @@ -417,7 +417,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024)); SSVAL(p,l1_attrFile,mode); SCVAL(p,l1_cchName,strlen(fname)); - strcpy(p + l1_achName, fname); + pstrcpy(p + l1_achName, fname); nameptr = p + l1_achName; p += l1_achName + strlen(fname) + 1; break; @@ -436,7 +436,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SSVAL(p,l2_attrFile,mode); SIVAL(p,l2_cbList,0); /* No extended attributes */ SCVAL(p,l2_cchName,strlen(fname)); - strcpy(p + l2_achName, fname); + pstrcpy(p + l2_achName, fname); nameptr = p + l2_achName; p += l2_achName + strlen(fname) + 1; break; @@ -451,7 +451,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SSVAL(p,24,mode); SIVAL(p,26,4); CVAL(p,30) = strlen(fname); - strcpy(p+31, fname); + pstrcpy(p+31, fname); nameptr = p+31; p += 31 + strlen(fname) + 1; break; @@ -469,7 +469,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,20,ROUNDUP(size,1024)); SSVAL(p,24,mode); CVAL(p,32) = strlen(fname); - strcpy(p + 33, fname); + pstrcpy(p + 33, fname); nameptr = p+33; p += 33 + strlen(fname) + 1; break; @@ -490,7 +490,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { - strcpy(p+2,fname); + pstrcpy(p+2,fname); if (!name_map_mangle(p+2,True,SNUM(cnum))) (p+2)[12] = 0; } else @@ -499,7 +499,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SSVAL(p,0,strlen(p+2)); p += 2 + 24; /* nameptr = p; */ - strcpy(p,fname); p += strlen(p); + pstrcpy(p,fname); p += strlen(p); p = pdata + len; break; @@ -516,7 +516,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,0,size); p += 8; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; - strcpy(p,fname); + pstrcpy(p,fname); p = pdata + len; break; @@ -535,7 +535,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; - strcpy(p,fname); + pstrcpy(p,fname); p = pdata + len; break; @@ -545,7 +545,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,0,len); p += 4; SIVAL(p,0,reskey); p += 4; SIVAL(p,0,strlen(fname)); p += 4; - strcpy(p,fname); + pstrcpy(p,fname); p = pdata + len; break; @@ -651,10 +651,10 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum p = strrchr(directory,'/'); if(p == NULL) { - strcpy(mask,directory); - strcpy(directory,"./"); + pstrcpy(mask,directory); + pstrcpy(directory,"./"); } else { - strcpy(mask,p+1); + pstrcpy(mask,p+1); *p = 0; } @@ -686,7 +686,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum } /* a special case for 16 bit apps */ - if (strequal(mask,"????????.???")) strcpy(mask,"*"); + if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); /* handle broken clients that send us old 8.3 format */ string_sub(mask,"????????","*"); @@ -863,8 +863,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); return (ERROR(ERRDOS,ERRnofiles)); } - strcpy(mask, p); - strcpy(directory,Connections[cnum].dirpath); + pstrcpy(mask, p); + pstrcpy(directory,Connections[cnum].dirpath); /* Get the attr mask from the dptr */ dirtype = dptr_attr(dptr_num); @@ -1060,7 +1060,7 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize case SMB_QUERY_FS_LABEL_INFO: data_len = 4 + strlen(vname); SIVAL(pdata,0,strlen(vname)); - strcpy(pdata+4,vname); + pstrcpy(pdata+4,vname); break; case SMB_QUERY_FS_VOLUME_INFO: data_len = 18 + 2*strlen(vname); diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c index dcb6ce831d..19f8259464 100644 --- a/source3/smbd/vt_mode.c +++ b/source3/smbd/vt_mode.c @@ -50,7 +50,7 @@ extern int DEBUGLEVEL; extern char *InBuffer, *OutBuffer; extern int done_become_user; -char master_name [64], slave_name [64]; +fstring master_name, slave_name; int master, slave, i, o, e; int ms_type = MS_NONE, @@ -202,8 +202,8 @@ int VT_Start(void) #endif if(ms_poll == MS_VTY || ms_poll == 0) { - strcpy(master_name, MASTER_TMPL); - strcpy(slave_name, SLAVE_TMPL); + fstrcpy(master_name, MASTER_TMPL); + fstrcpy(slave_name, SLAVE_TMPL); for(X = LETTER1; *X && master < 0; X++) for(Y = LETTER2; *Y && master < 0; Y++) { @@ -242,9 +242,9 @@ int VT_Start(void) int i; for(i = MIN_I; i <= MAX_I && master < 0; i++) { - sprintf(master_name, MASTER_TMPL, i); + slprintf(master_name, sizeof(fstring) - 1, MASTER_TMPL, i); if((master = open(master_name, O_RDWR)) >= 0) { - sprintf(slave_name, SLAVE_TMPL, i); + slprintf(slave_name, sizeof(fstring) - 1, SLAVE_TMPL, i); if((slave = open(slave_name, O_RDWR)) < 0) close(master); } -- cgit From a4276507e43487f47445eab11d4ac1b080b3270e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 May 1998 01:30:40 +0000 Subject: chgpasswd.c: Added comments to #ifdefs ipc.c: Caused samba password changing not to be done if UNIX password changing requested and not successful. util.c: Added string_to_sid() and sid_to_string() functions. lib/rpc/client/cli_samr.c: lib/rpc/include/rpc_misc.h: lib/rpc/parse/parse_lsa.c: lib/rpc/parse/parse_misc.c: lib/rpc/parse/parse_net.c: lib/rpc/parse/parse_samr.c: lib/rpc/server/srv_lsa.c: lib/rpc/server/srv_lsa_hnd.c: lib/rpc/server/srv_netlog.c: lib/rpc/server/srv_samr.c: lib/rpc/server/srv_util.c: Changes so that instead of passing SIDs around as char *, they are converted to DOM_SID at the earliest opportunity, and passed around as that. Also added dynamic memory allocation of group sids. Preparing to auto-generate machine sid. Jeremy. (This used to be commit 134d6fa79c1b6b9505a2c84ba9bfb91dd3be76e5) --- source3/smbd/chgpasswd.c | 4 ++-- source3/smbd/ipc.c | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d900b54c1f..ece3107257 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -427,13 +427,13 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) return(chat_with_program(passwordprogram,name,chatsequence, as_root)); } -#else +#else /* ALLOW_CHANGE_PASSWORD */ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) { DEBUG(0,("Password changing not compiled in (user=%s)\n",name)); return(False); } -#endif +#endif /* ALLOW_CHANGE_PASSWORD */ /*********************************************************** Code to check the lanman hashed password. diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7b82894c7f..132fdb30ef 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1677,6 +1677,7 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat fstring new_passwd; struct smb_passwd *sampw = NULL; char *p = param + 2; + int ret = True; *rparam_len = 2; *rparam = REALLOC(*rparam,*rparam_len); @@ -1718,9 +1719,9 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat */ if(lp_unix_password_sync()) - chgpasswd(user,"", new_passwd, True); + ret = chgpasswd(user,"", new_passwd, True); - if(change_oem_password( sampw, new_passwd, False)) { + if(ret && change_oem_password( sampw, new_passwd, False)) { SSVAL(*rparam,0,NERR_Success); } -- cgit From bce6d410130982af6ca58dc9a0d297b5f80e6c6c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 May 1998 03:20:42 +0000 Subject: namequery.c: Fixed SGI IRIX 5.x compiler problem. server.c: Added MACHINE.SID file generation - use lp_domain_sid() be default. smbpass.c: Exposed do_file_lock() as I now use it in server.c Jeremy. (This used to be commit 5bf17840ac7d65d08dd3fdfe8b789010488f6808) --- source3/smbd/server.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 191 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 540f9f799f..f277bea421 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -59,6 +59,12 @@ extern pstring user_socket_options; extern int dcelogin_atmost_once; #endif /* DFS_AUTH */ +/* + * This is set on startup - it defines the SID for this + * machine. +*/ +DOM_SID global_machine_sid; + connection_struct Connections[MAX_CONNECTIONS]; files_struct Files[MAX_OPEN_FILES]; @@ -135,6 +141,185 @@ void killkids(void) if(am_parent) kill(0,SIGTERM); } +/**************************************************************************** + Read the machine SID from a file. +****************************************************************************/ + +static BOOL read_sid_from_file(int fd, char *sid_file) +{ + fstring fline; + + if(read(fd, &fline, sizeof(fline) -1 ) < 0) { + DEBUG(0,("read_sid_from_file: unable to read file %s. Error was %s\n", + sid_file, strerror(errno) )); + return False; + } + + /* + * Convert to the machine SID. + */ + + fline[sizeof(fline)-1] = '\0'; + if(!string_to_sid( &global_machine_sid, fline)) { + DEBUG(0,("read_sid_from_file: unable to generate machine SID.\n")); + return False; + } + + return True; +} + +/**************************************************************************** + Generate the global machine sid. Look for the MACHINE.SID file first, if + not found then look in smb.conf and use it to create the MACHINE.SID file. +****************************************************************************/ + +static BOOL generate_machine_sid(void) +{ + int fd; + char *p; + pstring sid_file; + fstring sid_string; + struct stat st; + uchar raw_sid_data[12]; + + pstrcpy(sid_file, lp_smb_passwd_file()); + p = strrchr(sid_file, '/'); + if(p != NULL) + *++p = '\0'; + + pstrcat(sid_file, "MACHINE.SID"); + + if((fd = open( sid_file, O_RDWR | O_CREAT, 0644)) < 0 ) { + DEBUG(0,("generate_machine_sid: unable to open or create file %s. Error was %s\n", + sid_file, strerror(errno) )); + return False; + } + + /* + * Check if the file contains data. + */ + + if(fstat( fd, &st) < 0) { + DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + if(st.st_size > 0) { + /* + * We have a valid SID - read it. + */ + if(!read_sid_from_file( fd, sid_file)) { + DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + close(fd); + return True; + } + + /* + * The file contains no data - we may need to generate our + * own sid. Try the lp_domain_sid() first. + */ + + if(*lp_domain_sid()) + fstrcpy( sid_string, lp_domain_sid()); + else { + /* + * Generate the new sid data & turn it into a string. + */ + int i; + generate_random_buffer( raw_sid_data, 12, True); + + fstrcpy( sid_string, "S-1-5-21"); + for( i = 0; i < 3; i++) { + fstring tmp_string; + slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4)); + fstrcat( sid_string, tmp_string); + } + } + + fstrcat(sid_string, "\n"); + + /* + * Ensure our new SID is valid. + */ + + if(!string_to_sid( &global_machine_sid, sid_string)) { + DEBUG(0,("generate_machine_sid: unable to generate machine SID.\n")); + return False; + } + + /* + * Do an exclusive blocking lock on the file. + */ + + if(!do_file_lock( fd, 60, F_WRLCK)) { + DEBUG(0,("generate_machine_sid: unable to lock file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + /* + * At this point we have a blocking lock on the SID + * file - check if in the meantime someone else wrote + * SID data into the file. If so - they were here first, + * use their data. + */ + + if(fstat( fd, &st) < 0) { + DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + if(st.st_size > 0) { + /* + * We have a valid SID - read it. + */ + if(!read_sid_from_file( fd, sid_file)) { + DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + close(fd); + return True; + } + + /* + * The file is still empty and we have an exlusive lock on it. + * Write out out SID data into the file. + */ + + if(fchmod(fd, 0644) < 0) { + DEBUG(0,("generate_machine_sid: unable to set correct permissions on file %s. \ +Error was %s\n", sid_file, strerror(errno) )); + close(fd); + return False; + } + + if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) { + DEBUG(0,("generate_machine_sid: unable to write file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + /* + * Unlock & exit. + */ + + do_file_lock( fd, 60, F_UNLCK); + close(fd); + return True; +} + /**************************************************************************** change a dos mode to a unix mode base permission for files: @@ -5187,6 +5372,12 @@ static void usage(char *pname) pstrcpy(global_myworkgroup, lp_workgroup()); + if(!generate_machine_sid()) + { + DEBUG(0,("ERROR: Samba cannot get a machine SID.\n")); + exit(1); + } + #ifndef NO_SIGNAL_TEST signal(SIGHUP,SIGNAL_CAST sig_hup); #endif @@ -5256,5 +5447,3 @@ static void usage(char *pname) exit_server("normal exit"); return(0); } - - -- cgit From f8a4273407f2983bb05a76e914d4f532bbd5004e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 May 1998 21:10:49 +0000 Subject: passdb.c server.c: Moved generate_machine_sid() into passdb.c for Jean-Francois (who might want an LDAP version). Changed locking to free exclusive lock as soon as possible to prevent contention. lib/rpc/parse/parse_samr.c lib/rpc/server/srv_samr.c: Changed last SID-as-string manipulation function to use DOM_SID structure. Jeremy. (This used to be commit 3b8f5aef57b4f37265c0403385053085f0df6f18) --- source3/smbd/server.c | 183 +------------------------------------------------- 1 file changed, 2 insertions(+), 181 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f277bea421..9821b305bc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -62,8 +62,8 @@ extern int dcelogin_atmost_once; /* * This is set on startup - it defines the SID for this * machine. -*/ -DOM_SID global_machine_sid; + */ +extern DOM_SID global_machine_sid; connection_struct Connections[MAX_CONNECTIONS]; files_struct Files[MAX_OPEN_FILES]; @@ -141,185 +141,6 @@ void killkids(void) if(am_parent) kill(0,SIGTERM); } -/**************************************************************************** - Read the machine SID from a file. -****************************************************************************/ - -static BOOL read_sid_from_file(int fd, char *sid_file) -{ - fstring fline; - - if(read(fd, &fline, sizeof(fline) -1 ) < 0) { - DEBUG(0,("read_sid_from_file: unable to read file %s. Error was %s\n", - sid_file, strerror(errno) )); - return False; - } - - /* - * Convert to the machine SID. - */ - - fline[sizeof(fline)-1] = '\0'; - if(!string_to_sid( &global_machine_sid, fline)) { - DEBUG(0,("read_sid_from_file: unable to generate machine SID.\n")); - return False; - } - - return True; -} - -/**************************************************************************** - Generate the global machine sid. Look for the MACHINE.SID file first, if - not found then look in smb.conf and use it to create the MACHINE.SID file. -****************************************************************************/ - -static BOOL generate_machine_sid(void) -{ - int fd; - char *p; - pstring sid_file; - fstring sid_string; - struct stat st; - uchar raw_sid_data[12]; - - pstrcpy(sid_file, lp_smb_passwd_file()); - p = strrchr(sid_file, '/'); - if(p != NULL) - *++p = '\0'; - - pstrcat(sid_file, "MACHINE.SID"); - - if((fd = open( sid_file, O_RDWR | O_CREAT, 0644)) < 0 ) { - DEBUG(0,("generate_machine_sid: unable to open or create file %s. Error was %s\n", - sid_file, strerror(errno) )); - return False; - } - - /* - * Check if the file contains data. - */ - - if(fstat( fd, &st) < 0) { - DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - if(st.st_size > 0) { - /* - * We have a valid SID - read it. - */ - if(!read_sid_from_file( fd, sid_file)) { - DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - close(fd); - return True; - } - - /* - * The file contains no data - we may need to generate our - * own sid. Try the lp_domain_sid() first. - */ - - if(*lp_domain_sid()) - fstrcpy( sid_string, lp_domain_sid()); - else { - /* - * Generate the new sid data & turn it into a string. - */ - int i; - generate_random_buffer( raw_sid_data, 12, True); - - fstrcpy( sid_string, "S-1-5-21"); - for( i = 0; i < 3; i++) { - fstring tmp_string; - slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4)); - fstrcat( sid_string, tmp_string); - } - } - - fstrcat(sid_string, "\n"); - - /* - * Ensure our new SID is valid. - */ - - if(!string_to_sid( &global_machine_sid, sid_string)) { - DEBUG(0,("generate_machine_sid: unable to generate machine SID.\n")); - return False; - } - - /* - * Do an exclusive blocking lock on the file. - */ - - if(!do_file_lock( fd, 60, F_WRLCK)) { - DEBUG(0,("generate_machine_sid: unable to lock file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - /* - * At this point we have a blocking lock on the SID - * file - check if in the meantime someone else wrote - * SID data into the file. If so - they were here first, - * use their data. - */ - - if(fstat( fd, &st) < 0) { - DEBUG(0,("generate_machine_sid: unable to stat file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - if(st.st_size > 0) { - /* - * We have a valid SID - read it. - */ - if(!read_sid_from_file( fd, sid_file)) { - DEBUG(0,("generate_machine_sid: unable to read file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - close(fd); - return True; - } - - /* - * The file is still empty and we have an exlusive lock on it. - * Write out out SID data into the file. - */ - - if(fchmod(fd, 0644) < 0) { - DEBUG(0,("generate_machine_sid: unable to set correct permissions on file %s. \ -Error was %s\n", sid_file, strerror(errno) )); - close(fd); - return False; - } - - if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) { - DEBUG(0,("generate_machine_sid: unable to write file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - /* - * Unlock & exit. - */ - - do_file_lock( fd, 60, F_UNLCK); - close(fd); - return True; -} - /**************************************************************************** change a dos mode to a unix mode base permission for files: -- cgit From 646ab2b0a773592a5973ce78fecfb24b39aa2506 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 18 May 1998 14:17:47 +0000 Subject: resolving compilation errors (This used to be commit dea0c06eec44a7c2860f97d8f23584d30e482e0a) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9821b305bc..a35c3a2fdc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5193,7 +5193,7 @@ static void usage(char *pname) pstrcpy(global_myworkgroup, lp_workgroup()); - if(!generate_machine_sid()) + if(!pdb_generate_machine_sid()) { DEBUG(0,("ERROR: Samba cannot get a machine SID.\n")); exit(1); -- cgit From ffab54750f0eec202895670dd9293ee4aa3eb475 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 May 1998 21:30:57 +0000 Subject: chgpasswd.c: Changed back to getsmb... from getsam... ldap.c: Stoped dummy_function being prototyped. loadparm.c: Fixed slprintf sizes. nisppass.c: Fixed safe_strcpy sizes. nmbd_processlogon.c: Changed back to getsmb... from getsam... nttrans.c: Just a dump of new code. passdb.c: Moved stuff around a lot - stopped any lookups by rid. This needs to be indirected through a function table (soon). password.c: Changed back to getsmb... from getsam... reply.c: Changed back to getsmb... from getsam... slprintf.c: Fixed prototype problems. smb.h: Fixed prototype problems. smbpass.c: Changed to getsmbfile.... smbpasswd.c: Changed back to getsmb... from getsam... lib/rpc/server/srv_netlog.c: Changed back to getsmb... from getsam... lib/rpc/server/srv_samr.c: Fixed rid lookup - use uid or gid lookup. lib/rpc/server/srv_util.c: Changed back to getsmb... from getsam... Jeremy. (This used to be commit 7d332b2493d2089d09521250fc9b72d8953307c0) --- source3/smbd/chgpasswd.c | 78 ++++++++++++++--------------- source3/smbd/nttrans.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/password.c | 12 ++--- source3/smbd/reply.c | 14 +++--- 4 files changed, 179 insertions(+), 52 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index ece3107257..e8f3abc4f1 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -440,56 +440,56 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) ************************************************************/ BOOL check_lanman_password(char *user, unsigned char *pass1, - unsigned char *pass2, struct smb_passwd **psampw) + unsigned char *pass2, struct smb_passwd **psmbpw) { unsigned char unenc_new_pw[16]; unsigned char unenc_old_pw[16]; unsigned char null_pw[16]; - struct smb_passwd *sampw; + struct smb_passwd *smbpw; - *psampw = NULL; + *psmbpw = NULL; become_root(0); - sampw = getsampwnam(user); + smbpw = getsmbpwnam(user); unbecome_root(0); - if(sampw == NULL) + if(smbpw == NULL) { - DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); + DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n")); return False; } - if(sampw->acct_ctrl & ACB_DISABLED) + if(smbpw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } - if((sampw->smb_passwd == NULL) && (sampw->acct_ctrl & ACB_PWNOTREQ)) + if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { unsigned char no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); - sampw->smb_passwd = null_pw; - } else if (sampw->smb_passwd == NULL) { + smbpw->smb_passwd = null_pw; + } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("check_lanman_password: no lanman password !\n")); return False; } /* Get the new lanman hash. */ - D_P16(sampw->smb_passwd, pass2, unenc_new_pw); + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); /* Use this to get the old lanman hash. */ D_P16(unenc_new_pw, pass1, unenc_old_pw); /* Check that the two old passwords match. */ - if(memcmp(sampw->smb_passwd, unenc_old_pw, 16)) + if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); return False; } - *psampw = sampw; + *psmbpw = smbpw; return True; } @@ -499,44 +499,44 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, no longer be valid. ************************************************************/ -BOOL change_lanman_password(struct smb_passwd *sampw, unsigned char *pass1, unsigned char *pass2) +BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2) { unsigned char unenc_new_pw[16]; unsigned char null_pw[16]; BOOL ret; - if(sampw == NULL) + if(smbpw == NULL) { DEBUG(0,("change_lanman_password: no smb password entry.\n")); return False; } - if(sampw->acct_ctrl & ACB_DISABLED) + if(smbpw->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("change_lanman_password: account %s disabled.\n", sampw->smb_name)); + DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); return False; } - if((sampw->smb_passwd == NULL) && (sampw->acct_ctrl & ACB_PWNOTREQ)) + if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { unsigned char no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); - sampw->smb_passwd = null_pw; - } else if (sampw->smb_passwd == NULL) { + smbpw->smb_passwd = null_pw; + } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); return False; } /* Get the new lanman hash. */ - D_P16(sampw->smb_passwd, pass2, unenc_new_pw); + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); - sampw->smb_passwd = unenc_new_pw; - sampw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ + smbpw->smb_passwd = unenc_new_pw; + smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ /* Now write it into the file. */ become_root(0); - ret = mod_sampwd_entry(sampw,False); + ret = mod_smbpwd_entry(smbpw,False); unbecome_root(0); return ret; @@ -547,10 +547,10 @@ BOOL change_lanman_password(struct smb_passwd *sampw, unsigned char *pass1, unsi ************************************************************/ BOOL check_oem_password(char *user, unsigned char *data, - struct smb_passwd **psampw, char *new_passwd, + struct smb_passwd **psmbpw, char *new_passwd, int new_passwd_size) { - struct smb_passwd *sampw = NULL; + struct smb_passwd *smbpw = NULL; int new_pw_len; fstring upper_case_new_passwd; unsigned char new_p16[16]; @@ -558,28 +558,28 @@ BOOL check_oem_password(char *user, unsigned char *data, unsigned char null_pw[16]; become_root(0); - *psampw = sampw = getsampwnam(user); + *psmbpw = smbpw = getsmbpwnam(user); unbecome_root(0); - if(sampw == NULL) + if(smbpw == NULL) { - DEBUG(0,("check_oem_password: getsampwnam returned NULL\n")); + DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); return False; } - if(sampw->acct_ctrl & ACB_DISABLED) + if(smbpw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } - if((sampw->smb_passwd == NULL) && (sampw->acct_ctrl & ACB_PWNOTREQ)) + if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { unsigned char no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); - sampw->smb_passwd = null_pw; - } else if (sampw->smb_passwd == NULL) { + smbpw->smb_passwd = null_pw; + } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } @@ -587,7 +587,7 @@ BOOL check_oem_password(char *user, unsigned char *data, /* * Call the hash function to get the new password. */ - SamOEMhash( (unsigned char *)data, (unsigned char *)sampw->smb_passwd, True); + SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd, True); /* * The length of the new password is in the last 4 bytes of @@ -619,7 +619,7 @@ BOOL check_oem_password(char *user, unsigned char *data, */ D_P16(new_p16, &data[516], unenc_old_pw); - if(memcmp(sampw->smb_passwd, unenc_old_pw, 16)) { + if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old password doesn't match.\n")); return False; } @@ -636,7 +636,7 @@ BOOL check_oem_password(char *user, unsigned char *data, override = True, override XXXXXXXXXX'd password ************************************************************/ -BOOL change_oem_password(struct smb_passwd *sampw, char *new_passwd, BOOL override) +BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) { int ret; fstring upper_case_new_passwd; @@ -649,14 +649,14 @@ BOOL change_oem_password(struct smb_passwd *sampw, char *new_passwd, BOOL overri E_P16((uchar *)upper_case_new_passwd, new_p16); - sampw->smb_passwd = new_p16; + smbpw->smb_passwd = new_p16; E_md4hash((uchar *) new_passwd, new_nt_p16); - sampw->smb_nt_passwd = new_nt_p16; + smbpw->smb_nt_passwd = new_nt_p16; /* Now write it into the file. */ become_root(0); - ret = mod_sampwd_entry(sampw,override); + ret = mod_smbpwd_entry(smbpw,override); unbecome_root(0); memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd)); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 73f6786a04..81aa578daf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -43,6 +43,133 @@ static char *known_nt_pipes[] = { NULL }; +/**************************************************************************** + reply to an NT create and X call. +****************************************************************************/ + +THIS IS JUST CRIBBED FROM REPLY.C AT PRESENT AND IS A WORK +IN PROGRESS. JRA. + +int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + pstring fname; + int cnum = SVAL(inbuf,smb_tid); + int fnum = -1; + int smb_mode = SVAL(inbuf,smb_vwv3); + int smb_attr = SVAL(inbuf,smb_vwv5); + /* Breakout the oplock request bits so we can set the + reply bits separately. */ + BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); + BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); + BOOL oplock_request = ex_oplock_request | core_oplock_request; +#if 0 + int open_flags = SVAL(inbuf,smb_vwv2); + int smb_sattr = SVAL(inbuf,smb_vwv4); + uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); +#endif + int smb_ofun = SVAL(inbuf,smb_vwv8); + int unixmode; + int size=0,fmode=0,mtime=0,rmode=0; + struct stat sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp; + + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(cnum)) + return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize); + + /* XXXX we need to handle passed times, sattr and flags */ + + pstrcpy(fname,smb_buf(inbuf)); + unix_convert(fname,cnum,0,&bad_path); + + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); + if (!check_name(fname,cnum)) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + unixmode = unix_mode(cnum,smb_attr | aARCH); + + open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, + oplock_request, &rmode,&smb_action); + + fsp = &Files[fnum]; + + if (!fsp->open) + { + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + mtime = sbuf.st_mtime; + if (fmode & aDIR) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* If the caller set the extended oplock request bit + and we granted one (by whatever means) - set the + correct bit for extended oplock reply. + */ + + if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) { + smb_action |= EXTENDED_OPLOCK_GRANTED; + } + + if(ex_oplock_request && fsp->granted_oplock) { + smb_action |= EXTENDED_OPLOCK_GRANTED; + } + + /* If the caller set the core oplock request bit + and we granted one (by whatever means) - set the + correct bit for core oplock reply. + */ + + if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) { + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + } + + if(core_oplock_request && fsp->granted_oplock) { + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + } + + set_message(outbuf,15,0,True); + SSVAL(outbuf,smb_vwv2,fnum); + SSVAL(outbuf,smb_vwv3,fmode); + if(lp_dos_filetime_resolution(SNUM(cnum)) ) + put_dos_date3(outbuf,smb_vwv4,mtime & ~1); + else + put_dos_date3(outbuf,smb_vwv4,mtime); + SIVAL(outbuf,smb_vwv6,size); + SSVAL(outbuf,smb_vwv8,rmode); + SSVAL(outbuf,smb_vwv11,smb_action); + + chain_fnum = fnum; + + return chain_reply(inbuf,outbuf,length,bufsize); +} /**************************************************************************** reply to an unsolicited SMBNTtranss - just ignore it! diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3040775e03..a8d9ece557 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -429,21 +429,21 @@ update the encrypted smbpasswd file from the plaintext username and password *****************************************************************************/ BOOL update_smbpassword_file( char *user, fstring password) { - struct smb_passwd *sampw; + struct smb_passwd *smbpw; BOOL ret; become_root(0); - sampw = getsampwnam(user); + smbpw = getsmbpwnam(user); unbecome_root(0); - if(sampw == NULL) + if(smbpw == NULL) { - DEBUG(0,("update_smbpassword_file: getsampwnam returned NULL\n")); + DEBUG(0,("update_smbpassword_file: getsmbpwnam returned NULL\n")); return False; } /* Here, the flag is one, because we want to ignore the XXXXXXX'd out password */ - ret = change_oem_password( sampw, password, True); + ret = change_oem_password( smbpw, password, True); if (ret == False) DEBUG(3,("update_smbpasswd_file: change_oem_password returned False\n")); @@ -1131,7 +1131,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } - smb_pass = getsampwnam(user); + smb_pass = getsmbpwnam(user); if (!smb_pass) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 21a20b0712..4cde83cefe 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -377,10 +377,10 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, char *smb_passwd, int smb_passlen, char *smb_nt_passwd, int smb_nt_passlen) { - struct smb_passwd *sam_trust_acct = NULL; /* check if trust account exists */ + struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ if (lp_security() == SEC_USER) { - sam_trust_acct = getsampwnam(user); + smb_trust_acct = getsmbpwnam(user); } else { @@ -389,7 +389,7 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (sam_trust_acct == NULL) + if (smb_trust_acct == NULL) { /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); @@ -405,28 +405,28 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(sam_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) + if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_DOMTRUST)) + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST)) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); } - if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_SVRTRUST)) + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST)) { DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); } - if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_WSTRUST)) + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST)) { DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); -- cgit From 118827376f8ccedb455e81b7d2b3bff029cde457 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 May 1998 23:57:28 +0000 Subject: Abstracted all the crappy password interfaces through an indirect function table, selectable at compile time. This should make the code that implements all the password functions much cleaner, as it's now very clear exactly what a particular password database needs to provide to Samba. Jeremy. (This used to be commit 27ca536ad974242524c12f7100e419d9e7f9647f) --- source3/smbd/server.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a35c3a2fdc..2b2ebb5304 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -5247,6 +5247,9 @@ static void usage(char *pname) if (!locking_init(0)) exit(1); + if(!initialize_password_db()) + exit(1); + /* possibly reload the services file. */ reload_services(True); -- cgit From bff8dd86eeaa12c393e1fc70d230538c13801865 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 May 1998 02:01:21 +0000 Subject: Fixed Samba's wildcard algorithm to be *exactly* the same as NT. You do not want to know how this code works :-). Jeremy (This used to be commit 7adbd2dfc1eda0e147b7ab4b5ff5e71f173794af) --- source3/smbd/trans2.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index db44dc984d..372ab58b65 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -678,7 +678,16 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum { p = mask; while (*p) { - if (*p == '<') *p = '*'; + if (*p == '<') { + pstring expnd; + if(p[1] != '"') { + pstrcpy( expnd, p+1 ); + *p++ = '*'; + *p = '.'; + safe_strcpy( p+1, expnd, p - mask - 1); + } else + *p = '*'; + } if (*p == '>') *p = '?'; if (*p == '"') *p = '.'; p++; -- cgit From fd4d5ab75da1e7703919b66ad174e98d94574701 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 May 1998 02:07:57 +0000 Subject: Minor tweak for wcard compatibility paranoia. Jeremy. (This used to be commit 5d8ef7d0f1ecb358c841f382fc48e6eccbe8e171) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 372ab58b65..84d9b1cc17 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -680,7 +680,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum while (*p) { if (*p == '<') { pstring expnd; - if(p[1] != '"') { + if(p[1] != '"' && p[1] != '.') { pstrcpy( expnd, p+1 ); *p++ = '*'; *p = '.'; -- cgit From 67850c4574c739c61702eb18389ae4a592018037 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 May 1998 04:20:31 +0000 Subject: Fixed incorrect last arg to safe_strcpy in new wildcard code. Jeremy. (This used to be commit 67007d98b9daf5cccf049cb836dbb989516eb0ce) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 84d9b1cc17..4c06377bda 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -684,7 +684,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum pstrcpy( expnd, p+1 ); *p++ = '*'; *p = '.'; - safe_strcpy( p+1, expnd, p - mask - 1); + safe_strcpy( p+1, expnd, sizeof(mask) - (p - mask) - 2); } else *p = '*'; } -- cgit From 35c65576f71bb95f1bda5909c3a3cf32665a0dd4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 May 1998 23:50:16 +0000 Subject: printing.c: Fixed overflow by one problem in LPRng. reply.c: Fixed password length modifiers to always be done is none-encrypted mode used. This fixes Samba for people who are using non-encrypted passwords with security=server. Jeremy. (This used to be commit 720b565349e3467bd81d6d863b9ac54237edd3cf) --- source3/smbd/reply.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4cde83cefe..5ed30a7e8f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -516,6 +516,23 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) passlen1 = MIN(passlen1, MAX_PASS_LEN); passlen2 = MIN(passlen2, MAX_PASS_LEN); + if(!doencrypt) { + /* both Win95 and WinNT stuff up the password lengths for + non-encrypting systems. Uggh. + + if passlen1==24 its a win95 system, and its setting the + password length incorrectly. Luckily it still works with the + default code because Win95 will null terminate the password + anyway + + if passlen1>0 and passlen2>0 then maybe its a NT box and its + setting passlen2 to some random value which really stuffs + things up. we need to fix that one. */ + + if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1) + passlen2 = 0; + } + if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; @@ -525,21 +542,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); smb_ntpasswd[smb_ntpasslen] = 0; } else { - /* both Win95 and WinNT stuff up the password lengths for - non-encrypting systems. Uggh. - - if passlen1==24 its a win95 system, and its setting the - password length incorrectly. Luckily it still works with the - default code because Win95 will null terminate the password - anyway - - if passlen1>0 and passlen2>0 then maybe its a NT box and its - setting passlen2 to some random value which really stuffs - things up. we need to fix that one. */ - if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && - passlen2 != 1) { - passlen2 = 0; - } /* we use the first password that they gave */ smb_apasslen = passlen1; StrnCpy(smb_apasswd,p,smb_apasslen); -- cgit From bfa013908f2b0e3c8c9bed4c6f5c6ec9ee0931cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 May 1998 23:59:04 +0000 Subject: Fixed 'revalidate' parameter so it's only considered in security=share mode. Jeremy. (This used to be commit 7727f09ea9055053ed1d3e2af1069ddae245efb4) --- source3/smbd/password.c | 58 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a8d9ece557..0f2efcc1da 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1469,38 +1469,38 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* now check the list of session users */ - if (!ok) - { - char *auser; - char *user_list = strdup(session_users); - if (!user_list) return(False); + if (!ok) + { + char *auser; + char *user_list = strdup(session_users); + if (!user_list) return(False); - for (auser=strtok(user_list,LIST_SEP); - !ok && auser; - auser = strtok(NULL,LIST_SEP)) - { - fstring user2; - fstrcpy(user2,auser); - if (!user_ok(user2,snum)) continue; + for (auser=strtok(user_list,LIST_SEP); + !ok && auser; + auser = strtok(NULL,LIST_SEP)) + { + fstring user2; + fstrcpy(user2,auser); + if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL)) { - ok = True; - fstrcpy(user,user2); - DEBUG(3,("ACCEPTED: session list username and given password ok\n")); - } - } - free(user_list); - } - - /* check for a previously validated username/password pair */ - if (!ok && !lp_revalidate(snum) && - (vuser != 0) && !vuser->guest && - user_ok(vuser->name,snum)) { - fstrcpy(user,vuser->name); - *guest = False; - DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); - ok = True; + if (password_ok(user2,password, pwlen, NULL)) { + ok = True; + fstrcpy(user,user2); + DEBUG(3,("ACCEPTED: session list username and given password ok\n")); + } } + free(user_list); + } + + /* check for a previously validated username/password pair */ + if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) && + (vuser != 0) && !vuser->guest && + user_ok(vuser->name,snum)) { + fstrcpy(user,vuser->name); + *guest = False; + DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); + ok = True; + } /* check for a rhosts entry */ if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) { -- cgit From 6580fa6b5ce023a6bb7ce8aa9b8ab4b5c524f08b Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Fri, 22 May 1998 05:16:27 +0000 Subject: Removed all ubiqx includes from includes.h. So far, this was only a problem for dir.h, which I've fixed. Andrew did not add includes.h to the ubiqx headers, which is good because it would cause internal conflicts within the ubiqx tree modules. It's also bad because the definitions and includes that are part of includes.h are now in the ubiqx C files, but not in the header files. So, if includes.h were to redefine int, for example, the new definition would be in the ubiqx C files, but not in the headers. So, until Andrew and I can work something out that we both agree upon, there are three basic rules: 1) Don't include includes.h in the ubiqx headers. Problems may arise. 2) The ubiqx headers must follow includes.h in any Samba module that uses them. This can and should all be worked out. We just have to talk about it. Chris -)----- (This used to be commit 2b6be7084df4ddfca3a1ab7b73304007c5f9d0aa) --- source3/smbd/dir.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 37fcd05743..59ee23bbe8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "ubiqx/ubi_dLinkList.h" extern int DEBUGLEVEL; extern connection_struct Connections[]; -- cgit From cfc43a5a2fe65cccd9902bc28441da6c8d29f6a0 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Fri, 22 May 1998 07:46:39 +0000 Subject: I've put the ubiqx headers back into includes.h, and removed them from dir.c & mangle.c. This was possible after I checked the tree code to make sure that the tree code did not reference functions by macro name. Also, note that the AVL module has been removed to prevent conflict with the SplayTree macro defines. Chris -)----- (This used to be commit a1f4c8567c3c5264cbfa99867fa894cafab7da81) --- source3/smbd/dir.c | 1 - source3/smbd/mangle.c | 1 - 2 files changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 59ee23bbe8..37fcd05743 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "ubiqx/ubi_dLinkList.h" extern int DEBUGLEVEL; extern connection_struct Connections[]; diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index e822894600..33fc729a7f 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -46,7 +46,6 @@ */ #include "includes.h" -#include "ubiqx/ubi_Cache.h" /* -------------------------------------------------------------------------- ** -- cgit From 1d16f750515bcf49e0dc87394479dc56e7192538 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 May 1998 19:37:31 +0000 Subject: smb.h: More NT SMB stuff (just defines). smbpass.c: Do *NOT* make this function static. It breaks the compile on gcc util.c: Getting closer to MS wildcard semantics. A trailing '*' matches any trailing dot-separated components. trans2.c: Removed hacks that change multiple '?' -> '*' as this breaks things now. trans2.h: Removed NT_FILE_ATTRIBUTE_NORMAL - now FILE_ATTRIBUTE_NORMAL is defined in smb.h. Jeremy. (This used to be commit 42a65511068cd9006350c80bbed2f346f3f01cb0) --- source3/smbd/trans2.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4c06377bda..4fefb4b39c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -401,7 +401,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l p = pdata; nameptr = p; - nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL; + nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) { @@ -693,13 +693,21 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum p++; } } - + +#if 0 /* JRA */ + /* + * Now we have a working mask_match in util.c, I believe + * we no longer need these hacks (in fact they break + * things). JRA. + */ + /* a special case for 16 bit apps */ if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); /* handle broken clients that send us old 8.3 format */ string_sub(mask,"????????","*"); string_sub(mask,".???",".*"); +#endif /* JRA */ /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ -- cgit From 9bd7e1e8870da87ea6f3c9e78933beeb08b65a0c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 May 1998 00:30:52 +0000 Subject: loadparm.c: Added machine password timeout parameter - set to 7 days be default. password.c: Added code to tell server.c when machine password needs changing. server.c: Change machine password in idle cycles if it needs it. smbpassfile.c: Fixed up length calculations for machine password file. smbpasswd.c: Moved domain joining code/machine password changing code. lib/rpc/client/cli_netlogon.c: And this is where it now lives. Jeremy. (This used to be commit b8fedca6191de96159df0d1d17082d82e8e44773) --- source3/smbd/password.c | 9 +++++---- source3/smbd/server.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0f2efcc1da..48fd7cbe24 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -28,6 +28,8 @@ extern int DEBUGLEVEL; extern int Protocol; +BOOL global_machine_pasword_needs_changing; + /* users from session setup */ static pstring session_users=""; @@ -1972,8 +1974,6 @@ BOOL domain_client_validate( char *user, char *domain, } } - become_root(False); - /* * Get the machine account password. */ @@ -1992,13 +1992,14 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); trust_password_unlock(); - unbecome_root(False); - /* * Here we should check the last change time to see if the machine * password needs changing..... TODO... JRA. */ + if(time(NULL) > lct + lp_machine_password_timeout()) + global_machine_pasword_needs_changing = True; + /* * At this point, smb_apasswd points to the lanman response to * the challenge in local_challenge, and smb_ntpasswd points to diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2b2ebb5304..408d5cd068 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -50,6 +50,7 @@ extern BOOL use_mangled_map; extern BOOL short_case_preserve; extern BOOL case_mangle; time_t smb_last_time=(time_t)0; +extern BOOL global_machine_pasword_needs_changing; extern int smb_read_error; @@ -4950,6 +4951,52 @@ static void process(void) DEBUG(2,("%s Closing idle connection 2\n",timestring())); return; } + + if(global_machine_pasword_needs_changing) + { + unsigned char trust_passwd_hash[16]; + time_t lct; + pstring remote_machine_list; + + /* + * We're in domain level security, and the code that + * read the machine password flagged that the machine + * password needs changing. + */ + + /* + * First, open the machine password file with an exclusive lock. + */ + + if(!trust_password_lock( global_myworkgroup, global_myname, True)) { + DEBUG(0,("process: unable to open the machine account password file for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + continue; + } + + if(!get_trust_account_password( trust_passwd_hash, &lct)) { + DEBUG(0,("process: unable to read the machine account password for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + trust_password_unlock(); + continue; + } + + /* + * Make sure someone else hasn't already done this. + */ + + if(t < lct + lp_machine_password_timeout()) { + trust_password_unlock(); + global_machine_pasword_needs_changing = False; + continue; + } + + pstrcpy(remote_machine_list, lp_passwordserver()); + + change_trust_account_password( global_myworkgroup, remote_machine_list); + trust_password_unlock(); + global_machine_pasword_needs_changing = False; + } } if(got_smb) -- cgit From c435955b02c7fc227b9475ff73c62e080d34a1af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 Jun 1998 01:04:45 +0000 Subject: ipc.c: Fix bug where we don't return the correct error code when client gives a too-small buffer for share info. Fix from Gil Kloepfer smb.h: server.c: Fix for a nastly little security problem with multi-user Windows NT servers and Samba where the contents of the open-file cache can end up being served out to users who shouldn't have access. This is some *seriously* ugly code. Jeremy. (This used to be commit 05c85df3c7da982085615e5a1db6c71e164db4f5) --- source3/smbd/ipc.c | 21 ++-- source3/smbd/server.c | 340 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 270 insertions(+), 91 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 132fdb30ef..8def6d4908 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1504,6 +1504,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, char *p2; int count=lp_numservices(); int total=0,counted=0; + BOOL missed = False; int i; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; @@ -1514,16 +1515,18 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, data_len = fixed_len = string_len = 0; for (i=0;iuid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) + return; + fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u; +} + +/**************************************************************************** +Remove a uid_t that currently has this file open. This is an optimization only +used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + int i; + for(i = 0; i < fd_ptr->uid_cache_count; i++) + if(fd_ptr->uid_users_cache[i] == u) { + if(i < (fd_ptr->uid_cache_count-1)) + memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1], + sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) ); + fd_ptr->uid_cache_count--; + } + return; +} + +/**************************************************************************** +Check if a uid_t that currently has this file open is present. This is an +optimization only used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + int i; + for(i = 0; i < fd_ptr->uid_cache_count; i++) + if(fd_ptr->uid_users_cache[i] == u) + return True; + return False; +} + /**************************************************************************** fd support routines - attempt to find an already open file by dev and inode - increments the ref_count of the returned file_fd_struct *. @@ -1070,6 +1111,7 @@ Increments the ref_count of the returned entry. ****************************************************************************/ static file_fd_struct *fd_get_new(void) { + extern struct current_user current_user; int i; file_fd_struct *fd_ptr; @@ -1082,9 +1124,11 @@ static file_fd_struct *fd_get_new(void) fd_ptr->fd_readonly = -1; fd_ptr->fd_writeonly = -1; fd_ptr->real_open_flags = -1; + fd_ptr->uid_cache_count = 0; + fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); fd_ptr->ref_count++; /* Increment max used counter if neccessary, cuts down - on search time when re-using */ + on search time when re-using */ if(i > max_file_fd_used) max_file_fd_used = i; DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n", @@ -1122,31 +1166,106 @@ Decrements the ref_count and returns it. ****************************************************************************/ static int fd_attempt_close(file_fd_struct *fd_ptr) { + extern struct current_user current_user; + DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", - fd_ptr - &FileFd[0], - fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, - fd_ptr->real_open_flags, - fd_ptr->ref_count)); + fd_ptr - &FileFd[0], + fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, + fd_ptr->real_open_flags, + fd_ptr->ref_count)); if(fd_ptr->ref_count > 0) { fd_ptr->ref_count--; if(fd_ptr->ref_count == 0) { if(fd_ptr->fd != -1) close(fd_ptr->fd); if(fd_ptr->fd_readonly != -1) - close(fd_ptr->fd_readonly); + close(fd_ptr->fd_readonly); if(fd_ptr->fd_writeonly != -1) - close(fd_ptr->fd_writeonly); + close(fd_ptr->fd_writeonly); fd_ptr->fd = -1; fd_ptr->fd_readonly = -1; fd_ptr->fd_writeonly = -1; fd_ptr->real_open_flags = -1; fd_ptr->dev = (uint32)-1; fd_ptr->inode = (uint32)-1; - } + fd_ptr->uid_cache_count = 0; + } else + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); } return fd_ptr->ref_count; } +/**************************************************************************** +fd support routines - check that current user has permissions +to open this file. Used when uid not found in optimization cache. +This is really ugly code, as due to POSIX locking braindamage we must +fork and then attempt to open the file, and return success or failure +via an exit code. +****************************************************************************/ +static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) +{ + pid_t child_pid; + + if((child_pid = fork()) < 0) { + DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); + return False; + } + + if(child_pid) { + /* + * Parent. + */ + pid_t wpid; + int status_code; + if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { + DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n")); + return(False); + } + + if (child_pid != wpid) { + DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); + return(False); + } +#if defined(WIFEXITED) && defined(WEXITSTATUS) + if (WIFEXITED(status_code) == 0) { + DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n")); + return(False); + } + if (WEXITSTATUS(status_code) != 0) { + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); + return(False); + } +#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */ + if(status_code != 0) { + DEBUG(9,("check_access_allowed_for_current_user: The status of the process e +xiting was %d. Returning access denied.\n", status_code)); + return(False); + } +#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */ + + /* + * Success - the child could open the file. + */ + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code)); + return True; + } else { + /* + * Child. + */ + int fd; + DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode )); + if((fd = fd_attempt_open( fname, accmode, 0)) < 0) { + /* Access denied. */ + _exit(EACCES); + } + close(fd); + DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); + _exit(0); + } + + return False; +} + /**************************************************************************** open a file ****************************************************************************/ @@ -1229,14 +1348,41 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct * reference count (fd_get_already_open increments the ref_count). */ if((fd_ptr = fd_get_already_open(sbuf))!= 0) { + /* + * File was already open. + */ - /* File was already open. */ + /* + * Check it wasn't open for exclusive use. + */ if((flags & O_CREAT) && (flags & O_EXCL)) { fd_ptr->ref_count--; errno = EEXIST; return; } + /* + * Ensure that the user attempting to open + * this file has permissions to do so, if + * the user who originally opened the file wasn't + * the same as the current user. + */ + + if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { + if(!check_access_allowed_for_current_user( fname, accmode )) { + /* Error - permission denied. */ + DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", + fname, flags, accmode)); + /* Ensure the ref_count is decremented. */ + fd_ptr->ref_count--; + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + errno = EACCES; + return; + } + } + + fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + /* * If not opened O_RDWR try * and do that here - a chmod may have been done @@ -1256,6 +1402,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); check_for_pipe(fname); + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); fd_ptr->ref_count--; return; } @@ -1293,7 +1440,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode); fd_ptr->real_open_flags = O_WRONLY; } else { - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode); + fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode); fd_ptr->real_open_flags = O_RDONLY; } } @@ -1319,90 +1466,91 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct } if (fd_ptr->fd < 0) - { - DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", - fname,strerror(errno),flags)); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); - check_for_pipe(fname); - return; - } + { + DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", + fname,strerror(errno),flags)); + /* Ensure the ref_count is decremented. */ + fd_attempt_close(fd_ptr); + check_for_pipe(fname); + return; + } if (fd_ptr->fd >= 0) - { - if(sbuf == 0) { - /* Do the fstat */ - if(fstat(fd_ptr->fd, &statbuf) == -1) { - /* Error - backout !! */ - DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", - fd_ptr->fd, fname,strerror(errno))); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); - return; - } - sbuf = &statbuf; + { + if(sbuf == 0) { + /* Do the fstat */ + if(fstat(fd_ptr->fd, &statbuf) == -1) { + /* Error - backout !! */ + DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", + fd_ptr->fd, fname,strerror(errno))); + /* Ensure the ref_count is decremented. */ + fd_attempt_close(fd_ptr); + return; } - /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = (uint32)sbuf->st_dev; - fd_ptr->inode = (uint32)sbuf->st_ino; - - fsp->fd_ptr = fd_ptr; - Connections[cnum].num_files_open++; - fsp->mode = sbuf->st_mode; - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; - fsp->size = 0; - fsp->pos = -1; - fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; - fsp->can_lock = True; - fsp->can_read = ((flags & O_WRONLY)==0); - fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - fsp->share_mode = 0; - fsp->print_file = Connections[cnum].printer; - fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; - fsp->cnum = cnum; - string_set(&fsp->name,dos_to_unix(fname,False)); - fsp->wbmpx_ptr = NULL; + sbuf = &statbuf; + } - /* - * If the printer is marked as postscript output a leading - * file identifier to ensure the file is treated as a raw - * postscript file. - * This has a similar effect as CtrlD=0 in WIN.INI file. - * tim@fsg.com 09/06/94 - */ - if (fsp->print_file && POSTSCRIPT(cnum) && - fsp->can_write) - { - DEBUG(3,("Writing postscript line\n")); - write_file(fnum,"%!\n",3); - } - - DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", - timestring(),Connections[cnum].user,fname, - BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write), - Connections[cnum].num_files_open,fnum)); + /* Set the correct entries in fd_ptr. */ + fd_ptr->dev = (uint32)sbuf->st_dev; + fd_ptr->inode = (uint32)sbuf->st_ino; + + fsp->fd_ptr = fd_ptr; + Connections[cnum].num_files_open++; + fsp->mode = sbuf->st_mode; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + fsp->can_lock = True; + fsp->can_read = ((flags & O_WRONLY)==0); + fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + fsp->share_mode = 0; + fsp->print_file = Connections[cnum].printer; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + fsp->cnum = cnum; + string_set(&fsp->name,dos_to_unix(fname,False)); + fsp->wbmpx_ptr = NULL; + /* + * If the printer is marked as postscript output a leading + * file identifier to ensure the file is treated as a raw + * postscript file. + * This has a similar effect as CtrlD=0 in WIN.INI file. + * tim@fsg.com 09/06/94 + */ + if (fsp->print_file && POSTSCRIPT(cnum) && fsp->can_write) + { + DEBUG(3,("Writing postscript line\n")); + write_file(fnum,"%!\n",3); } + + DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", + timestring(), + *sesssetup_user ? sesssetup_user : Connections[cnum].user,fname, + BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write), + Connections[cnum].num_files_open,fnum)); + + } #if USE_MMAP /* mmap it if read-only */ if (!fsp->can_write) - { - fsp->mmap_size = file_size(fname); - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + { + fsp->mmap_size = file_size(fname); + fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, + PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); - if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) - { - DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); - fsp->mmap_ptr = NULL; - } + if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) + { + DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); + fsp->mmap_ptr = NULL; } + } #endif } @@ -2867,6 +3015,7 @@ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); ****************************************************************************/ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { + extern struct current_user current_user; extern int Client; char *inbuf = NULL; char *outbuf = NULL; @@ -2874,6 +3023,9 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) int fnum; time_t start_time; BOOL shutdown_server = False; + int saved_cnum; + int saved_vuid; + pstring saved_dir; DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); @@ -2979,6 +3131,15 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum)); start_time = time(NULL); + /* + * Save the information we need to re-become the + * user, then unbecome the user whilst we're doing this. + */ + saved_cnum = fsp->cnum; + saved_vuid = current_user.vuid; + GetWd(saved_dir); + unbecome_user(); + while(OPEN_FNUM(fnum) && fsp->granted_oplock) { if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) @@ -3030,6 +3191,21 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); } } + /* + * Go back to being the user who requested the oplock + * break. + */ + if(!become_user(&Connections[saved_cnum], saved_cnum, saved_vuid)) + { + DEBUG(0,("%s oplock_break: unable to re-become user ! Shutting down server\n", + timestring())); + close_sockets(); + close(oplock_sock); + exit_server("unable to re-become user"); + } + /* Including the directory. */ + ChDir(saved_dir); + /* Free the buffers we've been using to recurse. */ free(inbuf); free(outbuf); -- cgit From 28029c73b75538cd2903965664c6bcc3f22d7230 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Jun 1998 18:49:13 +0000 Subject: client.c: Allowed client to proceed even if it gets error 234 (more data available) when scanning server/workgroup/share lists. ipc.c: Removed redundent definition of ERROR_MORE_DATA (234) we already have ERRmoredata in smb.h Jeremy. (This used to be commit ae3510e9fb309be343e245d8460c1ceb8164077b) --- source3/smbd/ipc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8def6d4908..a9e0bec3ed 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -51,7 +51,6 @@ extern fstring global_myworkgroup; #define NERR_JobNotFound (NERR_BASE+51) #define NERR_DestNotFound (NERR_BASE+52) #define ERROR_INVALID_LEVEL 124 -#define ERROR_MORE_DATA 234 #define ACCESS_READ 0x01 #define ACCESS_WRITE 0x02 @@ -332,7 +331,7 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount) if (i > n) { p->neededlen = i; i = n = 0; - p->errcode = ERROR_MORE_DATA; + p->errcode = ERRmoredata; } else p->errcode = NERR_Success; @@ -435,7 +434,7 @@ va_dcl stringused = stringneeded; if (stringused > p->stringlen) { stringused = (is_string ? p->stringlen : 0); - if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA; + if (p->errcode == NERR_Success) p->errcode = ERRmoredata; } if (!stringused) SIVAL(p->structbuf,0,0); @@ -457,7 +456,7 @@ va_dcl p->usedlen += needed; } else { - if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA; + if (p->errcode == NERR_Success) p->errcode = ERRmoredata; } return 1; } @@ -1291,7 +1290,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA)); + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); SSVAL(*rparam,6,counted+missed); @@ -1542,7 +1541,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,missed ? ERROR_MORE_DATA : NERR_Success); + SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); SSVAL(*rparam,6,total); -- cgit From 72bf410b6e9b85f8fbff7f6175661829bef35f62 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Jun 1998 19:45:13 +0000 Subject: De-coupled the mapping of a Windows to UNIX username from the Get_Pwnam username case conversion wrapper. It is now (very) explicit where we are mapping between an incoming Windows username, and when we are doing a UNIX password entry lookup, which may change the case of the given username. This makes things *much* clearer (IMHO:-) and will ease the adding of the 'groupname map' parameter, and the addition of the special 'jeremy' mode for Samba where unix users will not be needed. (We must think of a better name for it :-). Jeremy. (This used to be commit fb6ed81844e7cb6049749e43ac9b4adfaf4ca2de) --- source3/smbd/ipc.c | 26 ++++++++++++++++++++++++++ source3/smbd/reply.c | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a9e0bec3ed..f92e376575 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1632,6 +1632,18 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, DEBUG(3,("Set password for <%s>\n",user)); + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); + /* * Attempt the plaintext password change first. * Older versions of Windows seem to do this. @@ -1706,6 +1718,20 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat fstrcpy(user,p); p = skip_string(p,1); + DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); + if(check_oem_password( user, (unsigned char *)data, &sampw, new_passwd, (int)sizeof(new_passwd)) == False) { return True; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5ed30a7e8f..c9b0c6852d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -232,6 +232,18 @@ int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); + connection_num = make_connection(service,user,password,pwlen,dev,vuid); if (connection_num < 0) @@ -300,6 +312,18 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(4,("Got device type %s\n",devicename)); } + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); + connection_num = make_connection(service,user,password,passlen,devicename,vuid); if (connection_num < 0) @@ -599,11 +623,22 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) reload_services(True); + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); + add_session_user(user); - /* Check if the given username was the guest user with no password. - We need to do this check after add_session_user() as that - call can potentially change the username (via map_user). + /* + * Check if the given username was the guest user with no password. */ if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) -- cgit From cd3de05fb53852cd0951cf7c9bc44ea0fbd66276 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Jun 1998 23:15:42 +0000 Subject: Minor changes as I've now discovered gcc -pedantic-errors. This does the signed/unsigned warnings I've been missing. Jeremy (This used to be commit 6d94e67624d1f2c08ac2e1c0eea23facd1e618f2) --- source3/smbd/server.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 59fd45f75e..ba7a0a18f1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1237,8 +1237,7 @@ static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) } #else /* defined(WIFEXITED) && defined(WEXITSTATUS) */ if(status_code != 0) { - DEBUG(9,("check_access_allowed_for_current_user: The status of the process e -xiting was %d. Returning access denied.\n", status_code)); + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); return(False); } #endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */ -- cgit From 9a735eb7e25d8bf6c5be7775d89436034ea6be8a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Jun 1998 03:08:23 +0000 Subject: ipc.c: map_username is now a BOOL function. reply.c: map_username is now a BOOL function. server.c: Added capability to do map_username on service names when looking for a home directory. That's what the original code would do. lib/rpc/server/srv_util.c: Changed domain_ to builtin_ for BUILTIN aliases. username.c: Work in progress on groupname map parameter. Jeremy (This used to be commit fa95fae5eed95aff64f0a01825477610a101bbc7) --- source3/smbd/ipc.c | 4 +-- source3/smbd/reply.c | 6 ++--- source3/smbd/server.c | 70 ++++++++++++++++++++++++++++++--------------------- 3 files changed, 47 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f92e376575..9c48951e35 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1637,7 +1637,7 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, * function. */ - map_username(user); + (void)map_username(user); /* * Do any UNIX username case mangling. @@ -1725,7 +1725,7 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat * function. */ - map_username(user); + (void)map_username(user); /* * Do any UNIX username case mangling. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c9b0c6852d..a9db0b3840 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -237,7 +237,7 @@ int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) * function. */ - map_username(user); + (void)map_username(user); /* * Do any UNIX username case mangling. @@ -317,7 +317,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) * function. */ - map_username(user); + (void)map_username(user); /* * Do any UNIX username case mangling. @@ -628,7 +628,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) * function. */ - map_username(user); + (void)map_username(user); /* * Do any UNIX username case mangling. diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ba7a0a18f1..25ec11abaa 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2340,16 +2340,28 @@ int find_service(char *service) if (iService < 0) { char *phome_dir = get_home_dir(service); + + if(!phome_dir) + { + /* + * Try mapping the servicename, it may + * be a Windows to unix mapped user name. + */ + if(map_username(service)) + phome_dir = get_home_dir(service); + } + DEBUG(3,("checking for home directory %s gave %s\n",service, - phome_dir?phome_dir:"(NULL)")); + phome_dir?phome_dir:"(NULL)")); + if (phome_dir) { - int iHomeService; - if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) - { - lp_add_home(service,iHomeService,phome_dir); - iService = lp_servicenumber(service); - } + int iHomeService; + if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) + { + lp_add_home(service,iHomeService,phome_dir); + iService = lp_servicenumber(service); + } } } @@ -2380,34 +2392,36 @@ int find_service(char *service) /* just possibly it's a default service? */ if (iService < 0) + { + char *pdefservice = lp_defaultservice(); + if (pdefservice && *pdefservice && !strequal(pdefservice,service)) { - char *pdefservice = lp_defaultservice(); - if (pdefservice && *pdefservice && !strequal(pdefservice,service)) { - /* - * We need to do a local copy here as lp_defaultservice() - * returns one of the rotating lp_string buffers that - * could get overwritten by the recursive find_service() call - * below. Fix from Josef Hinteregger . - */ - pstring defservice; - pstrcpy(defservice, pdefservice); - iService = find_service(defservice); - if (iService >= 0) { - string_sub(service,"_","/"); - iService = lp_add_service(service,iService); - } + /* + * We need to do a local copy here as lp_defaultservice() + * returns one of the rotating lp_string buffers that + * could get overwritten by the recursive find_service() call + * below. Fix from Josef Hinteregger . + */ + pstring defservice; + pstrcpy(defservice, pdefservice); + iService = find_service(defservice); + if (iService >= 0) + { + string_sub(service,"_","/"); + iService = lp_add_service(service,iService); } } + } if (iService >= 0) - if (!VALID_SNUM(iService)) - { - DEBUG(0,("Invalid snum %d for %s\n",iService,service)); - iService = -1; - } + if (!VALID_SNUM(iService)) + { + DEBUG(0,("Invalid snum %d for %s\n",iService,service)); + iService = -1; + } if (iService < 0) - DEBUG(3,("find_service() failed to find service %s\n", service)); + DEBUG(3,("find_service() failed to find service %s\n", service)); return (iService); } -- cgit From a32ad6733bfdd0e6b2603df665544f10813f645f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jun 1998 03:00:06 +0000 Subject: Groupname mapping code now lives here. Jeremy. (This used to be commit a70b929ec7b38855b7d09378536620c3f221cbe8) --- source3/smbd/groupname.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 source3/smbd/groupname.c (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c new file mode 100644 index 0000000000..4cfd3e98f5 --- /dev/null +++ b/source3/smbd/groupname.c @@ -0,0 +1,204 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Groupname handling + Copyright (C) Jeremy Allison 1998. + + 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; +extern DOM_SID global_machine_sid; + + +/************************************************************************** + Groupname map functionality. The code loads a groupname map file and + (currently) loads it into a linked list. This is slow and memory + hungry, but can be changed into a more efficient storage format + if the demands on it become excessive. +***************************************************************************/ + +typedef struct groupname_map { + ubi_slNode next; + + char *windows_name; + DOM_SID windows_sid; + char *unix_name; + gid_t unix_gid; +} groupname_map_entry; + +static ubi_slList groupname_map_list; + +/************************************************************************** + Delete all the entries in the groupname map list. +***************************************************************************/ + +static void delete_groupname_map_list(void) +{ + groupname_map_entry *gmep; + + while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) { + if(gmep->windows_name) + free(gmep->windows_name); + if(gmep->unix_name) + free(gmep->unix_name); + free((char *)gmep); + } +} + +/************************************************************************** + Load a groupname map file. Sets last accessed timestamp. +***************************************************************************/ + +void load_groupname_map(void) +{ + static time_t groupmap_file_last_modified = (time_t)0; + static BOOL initialized = False; + char *groupname_map_file = lp_groupname_map(); + struct stat st; + FILE *fp; + char *s; + pstring buf; + groupname_map_entry *new_ep; + + if(!initialized) { + ubi_slInitList( &groupname_map_list ); + initialized = True; + } + + if (!*groupname_map_file) + return; + + if(stat(groupname_map_file, &st) != 0) { + DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n", + groupname_map_file, strerror(errno) )); + return; + } + + /* + * Check if file has changed. + */ + if( st.st_mtime <= groupmap_file_last_modified) + return; + + groupmap_file_last_modified = st.st_mtime; + + /* + * Load the file. + */ + + fp = fopen(groupname_map_file,"r"); + if (!fp) { + DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n", + groupname_map_file, strerror(errno))); + return; + } + + /* + * Throw away any previous list. + */ + delete_groupname_map_list(); + + DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file)); + + while((s=fgets_slash(buf,sizeof(buf),fp))!=NULL) { + pstring unixname; + pstring windows_name; + struct group *gptr; + DOM_SID tmp_sid; + + DEBUG(10,("load_groupname_map: Read line |%s|\n", s)); + + if (!*s || strchr("#;",*s)) + continue; + + if(!next_token(&s,unixname, "\t\n\r=")) + continue; + + if(!next_token(&s,windows_name, "\t\n\r=")) + continue; + + trim_string(unixname, " ", " "); + trim_string(windows_name, " ", " "); + + if (!*windows_name) + continue; + + if(!*unixname) + continue; + + DEBUG(5,("load_groupname_map: unixname = %s, windowsname = %s.\n", + unixname, windows_name)); + + /* + * Attempt to get the unix gid_t for this name. + */ + + if((gptr = (struct group *)getgrnam(unixname)) == NULL) { + DEBUG(0,("load_groupname_map: getgrnam for group %s failed.\ +Error was %s.\n", unixname, strerror(errno) )); + continue; + } + + /* + * Now map to an NT SID. + */ + + if(!lookup_wellknown_sid_from_name(windows_name, &tmp_sid)) { + /* + * It's not a well known name, convert the UNIX gid_t + * to a rid within this domain SID. + */ + tmp_sid = global_machine_sid; + tmp_sid.sub_auths[tmp_sid.num_auths++] = + pdb_gid_to_group_rid((gid_t)gptr->gr_gid); + } + + /* + * Create the list entry and add it onto the list. + */ + + if((new_ep = (groupname_map_entry *)malloc( sizeof(groupname_map_entry) ))== NULL) { + DEBUG(0,("load_groupname_map: malloc fail for groupname_map_entry.\n")); + fclose(fp); + return; + } + + new_ep->unix_gid = gptr->gr_gid; + new_ep->windows_sid = tmp_sid; + new_ep->windows_name = strdup( windows_name ); + new_ep->unix_name = strdup( unixname ); + + if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) { + DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n")); + fclose(fp); + if(new_ep->windows_name != NULL) + free(new_ep->windows_name); + if(new_ep->unix_name != NULL) + free(new_ep->unix_name); + free((char *)new_ep); + return; + } + memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) ); + + ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep); + } + + DEBUG(10,("load_groupname_map: Added %d entries to groupname map.\n", + ubi_slCount( &groupname_map_list ) )); + + fclose(fp); +} -- cgit From 5b5eb35c91ec400a25f6e6cf3eec421bd9560d50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jun 1998 03:04:00 +0000 Subject: Makefile: Added ubi_sLinkList.o as the groupname.o file needs it. Added groupname.o includes.h: Added ubi_sLinkList.h include. loadparm.c: Added groupname map parameter. password.c: Fix HPUX big_crypt. username.c: New user_in_list() code. Moved groupname map code to groupname.c lib/rpc/server/srv_util.c: Added lookup_wellknown_sid_from_name(). New groupname map stuff. Note that nothing currently uses this but at compiles ok. Jeremy. (This used to be commit beef636a4d772457816ef068c62ea965d07131f6) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 48fd7cbe24..277e3a592e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -961,7 +961,7 @@ Hence we make a direct return to avoid a second chance!!! #endif #ifdef HPUX_10_TRUSTED - return(bigcrypt(password,this_salt,this_crypted)); + return(strcmp(bigcrypt(password,this_salt),this_crypted) == 0); #endif #ifdef NO_CRYPT -- cgit From 644fbaaf9ba38a5f3d60f27f7110e755b20d31e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Jun 1998 18:19:54 +0000 Subject: Makefile: smbumount.c: Added fixes to compile under Linux. includes.h: Added SunOS 4.x QSORT_CAST fix. reply.c: Fixed user name mapping function for security=server, security=domain. Jeremy. (This used to be commit 21ca6bfb3ba3927efaf7eeff4325976d41489be2) --- source3/smbd/reply.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a9db0b3840..9177b3cde1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -482,6 +482,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring smb_ntpasswd; BOOL valid_nt_password = False; pstring user; + pstring orig_user; BOOL guest=False; static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); @@ -623,6 +624,14 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) reload_services(True); + /* + * Save the username before mapping. We will use + * the original username sent to us for security=server + * and security=domain checking. + */ + + pstrcpy( orig_user, user); + /* * Pass the user through the NT -> unix user mapping * function. @@ -645,14 +654,17 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) guest = True; if (!guest && !(lp_security() == SEC_SERVER && - server_validate(user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen)) && - !(lp_security() == SEC_DOMAIN && - domain_client_validate(user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen)) && - !check_hosts_equiv(user)) + /* Check with orig_user for security=server and + security=domain. */ + server_validate(orig_user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && + !(lp_security() == SEC_DOMAIN && + domain_client_validate(orig_user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && + !check_hosts_equiv(user) + ) { /* now check if it's a valid username/password */ -- cgit From 7ed5a181ac836f2f88e1525723dd6197ca3a9084 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Jun 1998 22:02:14 +0000 Subject: client.c: Made -L do a null-session share unless -U user is specified. clientutil.c: Fixed NT session to add NT password. groupname.c: Added lookup function. Jeremy. (This used to be commit 8216363e83fcdccfade70f983830b56b7e6546a4) --- source3/smbd/groupname.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 4cfd3e98f5..33ce3adbfe 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -202,3 +202,37 @@ Error was %s.\n", unixname, strerror(errno) )); fclose(fp); } + +/*********************************************************** + Lookup a SID entry by gid_t. +************************************************************/ + +void map_gid_to_sid( gid_t gid, DOM_SID *psid) +{ + groupname_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_groupname_map(); + + for( gmep = (groupname_map_entry *)ubi_slFirst( &groupname_map_list); + gmep; gmep = (groupname_map_entry *)ubi_slNext( gmep )) { + + if( gmep->unix_gid == gid) { + *psid = gmep->windows_sid; + DEBUG(7,("map_gid_to_sid: Mapping unix group %s to windows group %s.\n", + gmep->unix_name, gmep->windows_name )); + return; + } + } + + /* + * If there's no map, convert the UNIX gid_t + * to a rid within this domain SID. + */ + *psid = global_machine_sid; + psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid); + + return; +} -- cgit From cb757820f5452d192ce3b1eeb4f19a17ee93c3fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Jun 1998 01:35:52 +0000 Subject: Added SSL support from Christian Starkjohann This patch may not yet compile with -DUSE_SSL enabled, further Makefile changes may be needed. But it was important to get this code in place before I go off to USENIX. Jeremy. (This used to be commit 31e768369fdc61e07c59630c86c62239f3d3f3f7) --- source3/smbd/server.c | 25 +++++ source3/smbd/ssl.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 source3/smbd/ssl.c (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 25ec11abaa..45a63a544a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2810,6 +2810,10 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); static void process_smb(char *inbuf, char *outbuf) { extern int Client; +#ifdef USE_SSL + extern BOOL sslEnabled; /* don't use function for performance reasons */ + static int sslConnected = 0; +#endif /* USE_SSL */ static int trans_num; int msg_type = CVAL(inbuf,0); int32 len = smb_len(inbuf); @@ -2834,6 +2838,18 @@ static void process_smb(char *inbuf, char *outbuf) DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); +#ifdef USE_SSL + if(sslEnabled && !sslConnected){ + sslConnected = sslutil_negotiate_ssl(Client, msg_type); + if(sslConnected < 0){ /* an error occured */ + exit_server("SSL negotiation failed"); + }else if(sslConnected){ + trans_num++; + return; + } + } +#endif /* USE_SSL */ + #ifdef WITH_VTP if(trans_num == 1 && VT_Check(inbuf)) { @@ -5425,6 +5441,15 @@ static void usage(char *pname) if (!reload_services(False)) return(-1); +#ifdef USE_SSL + { + extern BOOL sslEnabled; + sslEnabled = lp_ssl_enabled(); + if(sslEnabled) + sslutil_init(True); + } +#endif /* USE_SSL */ + codepage_initialise(lp_client_code_page()); pstrcpy(global_myworkgroup, lp_workgroup()); diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c new file mode 100644 index 0000000000..1bb89f05b1 --- /dev/null +++ b/source3/smbd/ssl.c @@ -0,0 +1,266 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SSLeay utility functions + Copyright (C) Christian Starkjohann 1998 + + 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. +*/ + +#ifdef USE_SSL /* should always be defined if this module is compiled */ + +#include "includes.h" +#include +#include + +BOOL sslEnabled; +SSL *ssl = NULL; +int sslFd = -1; +static SSL_CTX *sslContext = NULL; +extern int DEBUGLEVEL; + +static int ssl_verify_cb(int ok, X509_STORE_CTX *ctx) +{ +char buffer[256]; + + X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), + buffer, sizeof(buffer)); + if(ok){ + DEBUG(0, ("SSL: Certificate OK: %s\n", buffer)); + }else{ + switch (ctx->error){ + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + DEBUG(0, ("SSL: Cert error: CA not known: %s\n", buffer)); + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + DEBUG(0, ("SSL: Cert error: Cert not yet valid: %s\n", buffer)); + break; + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + DEBUG(0, ("SSL: Cert error: illegal \'not before\' field: %s\n", + buffer)); + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + DEBUG(0, ("SSL: Cert error: Cert expired: %s\n", buffer)); + break; + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + DEBUG(0, ("SSL: Cert error: invalid \'not after\' field: %s\n", + buffer)); + break; + default: + DEBUG(0, ("SSL: Cert error: unknown error %d in %s\n", ctx->error, + buffer)); + break; + } + } + return ok; +} + +static RSA *ssl_temp_rsa_cb(SSL *ssl, int export) +{ +static RSA *rsa = NULL; + + if(rsa == NULL) + rsa = RSA_generate_key(512, RSA_F4, NULL, NULL); + return rsa; +} + +/* This is called before we fork. It should ask the user for the pass phrase + * if necessary. Error output can still go to stderr because the process + * has a terminal. + */ +int sslutil_init(int isServer) +{ +int err; +char *certfile, *keyfile, *ciphers, *cacertDir, *cacertFile; + + SSL_load_error_strings(); + SSLeay_add_ssl_algorithms(); + switch(lp_ssl_version()){ + case SMB_SSL_V2: sslContext = SSL_CTX_new(SSLv2_method()); break; + case SMB_SSL_V3: sslContext = SSL_CTX_new(SSLv3_method()); break; + default: + case SMB_SSL_V23: sslContext = SSL_CTX_new(SSLv23_method()); break; + case SMB_SSL_TLS1: sslContext = SSL_CTX_new(TLSv1_method()); break; + } + if(sslContext == NULL){ + err = ERR_get_error(); + fprintf(stderr, "SSL: Error allocating context: %s\n", + ERR_error_string(err, NULL)); + exit(1); + } + if(lp_ssl_compatibility()){ + SSL_CTX_set_options(sslContext, SSL_OP_ALL); + } + certfile = isServer ? lp_ssl_cert() : lp_ssl_client_cert(); + if((certfile == NULL || *certfile == 0) && isServer){ + fprintf(stderr, "SSL: No cert file specified in config file!\n"); + fprintf(stderr, "The server MUST have a certificate!\n"); + exit(1); + } + keyfile = isServer ? lp_ssl_privkey() : lp_ssl_client_privkey(); + if(keyfile == NULL || *keyfile == 0) + keyfile = certfile; + if(certfile != NULL && *certfile != 0){ + if(!SSL_CTX_use_certificate_file(sslContext, certfile, SSL_FILETYPE_PEM)){ + err = ERR_get_error(); + fprintf(stderr, "SSL: error reading certificate from file %s: %s\n", + certfile, ERR_error_string(err, NULL)); + exit(1); + } + if(!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)){ + err = ERR_get_error(); + fprintf(stderr, "SSL: error reading private key from file %s: %s\n", + keyfile, ERR_error_string(err, NULL)); + exit(1); + } + if(!SSL_CTX_check_private_key(sslContext)){ + err = ERR_get_error(); + fprintf(stderr, "SSL: Private key does not match public key in cert!\n"); + exit(1); + } + } + cacertDir = lp_ssl_cacertdir(); + cacertFile = lp_ssl_cacertfile(); + if(cacertDir != NULL && *cacertDir == 0) + cacertDir = NULL; + if(cacertFile != NULL && *cacertFile == 0) + cacertFile = NULL; + if(!SSL_CTX_load_verify_locations(sslContext, cacertFile, cacertDir)){ + err = ERR_get_error(); + fprintf(stderr, "SSL: Error error setting CA cert locations: %s\n", + ERR_error_string(err, NULL)); + fprintf(stderr, "trying default locations.\n"); + cacertFile = cacertDir = NULL; + if(!SSL_CTX_set_default_verify_paths(sslContext)){ + err = ERR_get_error(); + fprintf(stderr, "SSL: Error error setting default CA cert location: %s\n", + ERR_error_string(err, NULL)); + exit(1); + } + } + SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb); + if((ciphers = lp_ssl_ciphers()) != NULL && *ciphers != 0) + SSL_CTX_set_cipher_list(sslContext, ciphers); + if((isServer && lp_ssl_reqClientCert()) || (!isServer && lp_ssl_reqServerCert())){ + SSL_CTX_set_verify(sslContext, + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); + }else{ + SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, ssl_verify_cb); + } +#if 1 /* don't know what this is good for, but s_server in SSLeay does it, too */ + if(isServer){ + SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(certfile)); + } +#endif + return 0; +} + +int sslutil_accept(int fd) +{ +int err; + + if(ssl != NULL){ + DEBUG(0, ("SSL: internal error: more than one SSL connection (server)\n")); + return -1; + } + if((ssl = SSL_new(sslContext)) == NULL){ + err = ERR_get_error(); + DEBUG(0, ("SSL: Error allocating handle: %s\n", + ERR_error_string(err, NULL))); + return -1; + } + SSL_set_fd(ssl, fd); + sslFd = fd; + if(SSL_accept(ssl) <= 0){ + err = ERR_get_error(); + DEBUG(0, ("SSL: Error accepting on socket: %s\n", + ERR_error_string(err, NULL))); + return -1; + } + DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl))); + return 0; +} + +int sslutil_fd_is_ssl(int fd) +{ + return fd == sslFd; +} + +int sslutil_connect(int fd) +{ +int err; + + if(ssl != NULL){ + DEBUG(0, ("SSL: internal error: more than one SSL connection (client)\n")); + return -1; + } + if((ssl = SSL_new(sslContext)) == NULL){ + err = ERR_get_error(); + DEBUG(0, ("SSL: Error allocating handle: %s\n", + ERR_error_string(err, NULL))); + return -1; + } + SSL_set_fd(ssl, fd); + sslFd = fd; + if(SSL_connect(ssl) <= 0){ + err = ERR_get_error(); + DEBUG(0, ("SSL: Error conencting socket: %s\n", + ERR_error_string(err, NULL))); + return -1; + } + DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl))); + return 0; +} + +int sslutil_disconnect(int fd) +{ + if(fd == sslFd && ssl != NULL){ + SSL_free(ssl); + ssl = NULL; + sslFd = -1; + } + return 0; +} + +int sslutil_negotiate_ssl(int fd, int msg_type) +{ +unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; +char *reqHosts, *resignHosts; + + reqHosts = lp_ssl_hosts(); + resignHosts = lp_ssl_hosts_resign(); + if(!allow_access(resignHosts, reqHosts, client_name(fd), client_addr(fd))){ + sslEnabled = False; + return 0; + } + if(msg_type != 0x81){ /* first packet must be a session request */ + DEBUG(0, ("%s Client %s did not use session setup; access denied\n", + timestring(), client_addr(fd))); + send_smb(fd, (char *)buf); + return -1; + } + buf[4] = 0x8e; /* negative session response: use SSL */ + send_smb(fd, (char *)buf); + if(sslutil_accept(fd) != 0){ + DEBUG(0, ("%s Client %s failed SSL negotiation!\n", + timestring(), client_addr(fd))); + return -1; + } + return 1; +} + +#else /* USE_SSL */ + void ssl_dummy(void) {;} /* So some compilers don't complain. */ +#endif /* USE_SSL */ -- cgit From 1829528d1fb2b87c726341aaf8d69d1190f83d6b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jun 1998 21:19:40 +0000 Subject: nttrans.c: More code towards NT protocol. smb.h: More code towards NT protocol. time.c: Fix for sco bug. Jeremy. (This used to be commit e53f4396ead540bcf9ecd18f3253e49216404a1b) --- source3/smbd/nttrans.c | 104 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 81aa578daf..9d6f0d4021 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -55,19 +55,20 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) pstring fname; int cnum = SVAL(inbuf,smb_tid); int fnum = -1; - int smb_mode = SVAL(inbuf,smb_vwv3); + uint32 flags = SIVAL(inbuf,smb_ntcreate_Flags); + uint32 desired_access = SIVAL(inbuf,smb_ntcreate_DesiredAccess); + uint32 file_attributes = SIVAL(inbuf,smb_ntcreate_FileAttributes); + uint32 share_access = SIVAL(inbuf,smb_ntcreate_ShareAccess); + uint32 create_disposition = SIVAL(inbuf,smb_ntcreate_CreateDisposition); + + int smb_ofun; + int smb_open_mode; int smb_attr = SVAL(inbuf,smb_vwv5); /* Breakout the oplock request bits so we can set the reply bits separately. */ - BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); + BOOL ex_oplock_request = flags & BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); BOOL oplock_request = ex_oplock_request | core_oplock_request; -#if 0 - int open_flags = SVAL(inbuf,smb_vwv2); - int smb_sattr = SVAL(inbuf,smb_vwv4); - uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); -#endif - int smb_ofun = SVAL(inbuf,smb_vwv8); int unixmode; int size=0,fmode=0,mtime=0,rmode=0; struct stat sbuf; @@ -77,10 +78,87 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(cnum)) - return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize); - - /* XXXX we need to handle passed times, sattr and flags */ - + return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize); + + /* If it's a request for a directory open, fail it. */ + if(flags & OPEN_DIRECTORY) + return(ERROR(ERRSRV,ERRfilespecs)); + + /* + * We need to construct the open_and_X ofun value from the + * NT values, as that's what our code is structured to accept. + */ + + switch( create_disposition ) { + case CREATE_NEW: + /* create if not exist, fail if exist */ + smb_ofun = 0x10; + break; + case CREATE_ALWAYS: + /* create if not exist, trunc if exist */ + smb_ofun = 0x12; + break; + case OPEN_EXISTING: + /* fail if not exist, open if exists */ + smb_ofun = 0x1; + break; + case OPEN_ALWAYS: + /* create if not exist, open if exists */ + smb_ofun = 0x11; + break; + case TRUNCATE_EXISTING: + /* fail if not exist, truncate if exists */ + smb_ofun = 0x2; + break; + default: + DEBUG(0,("reply_ntcreate_and_X: Incorrect value for create_disposition = %d\n", + create_disposition )); + return(ERROR(ERRDOS,ERRbadaccess)); + } + + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ + + switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) { + case FILE_READ_DATA: + smb_open_mode = 0; + break; + case FILE_WRITE_DATA: + smb_open_mode = 1; + break; + case FILE_READ_DATA|FILE_WRITE_DATA: + smb_open_mode = 2; + break; + default: + DEBUG(0,("reply_ntcreate_and_X: Incorrect value for desired_access = %x\n", + desired_access)); + return(ERROR(ERRDOS,ERRbadaccess)); + } + + /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */ + switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) { + case FILE_SHARE_READ: + smb_open_mode |= (DENY_WRITE<<4); + break; + case FILE_SHARE_WRITE: + smb_open_mode |= (DENY_READ<<4); + break; + case (FILE_SHARE_READ|FILE_SHARE_WRITE): + smb_open_mode |= (DENY_NONE<<4); + break; + case FILE_SHARE_NONE: + smb_open_mode |= (DENY_ALL<<4); + break; + } + + /* + * Handle a O_SYNC request. + */ + if(file_attributes & FILE_FLAG_WRITE_THROUGH) + smb_open_mode |= (1<<14); + pstrcpy(fname,smb_buf(inbuf)); unix_convert(fname,cnum,0,&bad_path); @@ -100,7 +178,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) unixmode = unix_mode(cnum,smb_attr | aARCH); - open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); fsp = &Files[fnum]; -- cgit From 139a34157eba50f70c86f2dd07fb384a7cbaf9cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Jul 1998 21:49:49 +0000 Subject: includes.h: AIX fix. nttrans.c: More NT SMB work. smb.h: More NT SMB defines. trans2.c: Change call response as I now have docs on what the flags mean. #ifdef it with JRATEST until I'm sure it's ok though. Jeremy. (This used to be commit ce2503fddd7ef9eed89e1a63fd834f13432a9cd6) --- source3/smbd/nttrans.c | 133 ++++++++++++++++++++++++++++++++++++++----------- source3/smbd/trans2.c | 4 ++ 2 files changed, 109 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9d6f0d4021..1cde27a9ff 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -29,6 +29,9 @@ extern int Client; extern int oplock_sock; extern int smb_read_error; extern int global_oplock_break; +extern BOOL case_sensitive; +extern BOOL case_preserve; +extern BOOL short_case_preserve; static char *known_nt_pipes[] = { "\\LANMAN", @@ -43,12 +46,46 @@ static char *known_nt_pipes[] = { NULL }; +static BOOL saved_case_sensitive; +static BOOL saved_case_preserve; +static BOOL saved_short_case_preserve; + /**************************************************************************** - reply to an NT create and X call. + Save case semantics. +****************************************************************************/ + +static void set_posix_case_semantics(uint32 file_attributes) +{ + if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) + return; + + saved_case_sensitive = case_sensitive; + saved_case_preserve = case_preserve; + saved_short_case_preserve = short_case_preserve; + + /* Set to POSIX. */ + case_sensitive = True; + case_preserve = True; + short_case_preserve = True; +} + +/**************************************************************************** + Restore case semantics. ****************************************************************************/ -THIS IS JUST CRIBBED FROM REPLY.C AT PRESENT AND IS A WORK -IN PROGRESS. JRA. +static void restore_case_semantics(uint32 file_attributes) +{ + if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) + return; + + case_sensitive = saved_case_sensitive; + case_preserve = saved_case_preserve; + short_case_preserve = saved_short_case_preserve; +} + +/**************************************************************************** + reply to an NT create and X call. +****************************************************************************/ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) { @@ -60,29 +97,29 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) uint32 file_attributes = SIVAL(inbuf,smb_ntcreate_FileAttributes); uint32 share_access = SIVAL(inbuf,smb_ntcreate_ShareAccess); uint32 create_disposition = SIVAL(inbuf,smb_ntcreate_CreateDisposition); - + uint32 fname_len = MIN(((uint32)SSVAL(inbuf,smb_ntcreate_NameLength)), + ((uint32)sizeof(fname)-1)); int smb_ofun; int smb_open_mode; - int smb_attr = SVAL(inbuf,smb_vwv5); + int smb_attr = file_attributes & SAMBA_ATTRIBUTES_MASK; /* Breakout the oplock request bits so we can set the reply bits separately. */ - BOOL ex_oplock_request = flags & - BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); - BOOL oplock_request = ex_oplock_request | core_oplock_request; + int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); int unixmode; int size=0,fmode=0,mtime=0,rmode=0; struct stat sbuf; int smb_action = 0; BOOL bad_path = False; files_struct *fsp; - + char *p = NULL; + /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(cnum)) return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize); /* If it's a request for a directory open, fail it. */ if(flags & OPEN_DIRECTORY) - return(ERROR(ERRSRV,ERRfilespecs)); + return(ERROR(ERRDOS,ERRnoaccess)); /* * We need to construct the open_and_X ofun value from the @@ -159,12 +196,22 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) if(file_attributes & FILE_FLAG_WRITE_THROUGH) smb_open_mode |= (1<<14); - pstrcpy(fname,smb_buf(inbuf)); + /* + * Check if POSIX semantics are wanted. + */ + + set_posix_case_semantics(file_attributes); + + StrnCpy(fname,smb_buf(inbuf),fname_len); unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); if (fnum < 0) + { + restore_case_semantics(file_attributes); return(ERROR(ERRSRV,ERRnofids)); + } + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -173,6 +220,9 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_code = ERRbadpath; } Files[fnum].reserved = False; + + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -191,11 +241,17 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_code = ERRbadpath; } Files[fnum].reserved = False; + + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); + + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); } @@ -204,6 +260,9 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) mtime = sbuf.st_mtime; if (fmode & aDIR) { close_file(fnum,False); + + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); } @@ -212,29 +271,45 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) correct bit for extended oplock reply. */ - if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) { + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { smb_action |= EXTENDED_OPLOCK_GRANTED; } - if(ex_oplock_request && fsp->granted_oplock) { + if(oplock_request && fsp->granted_oplock) { smb_action |= EXTENDED_OPLOCK_GRANTED; } - /* If the caller set the core oplock request bit - and we granted one (by whatever means) - set the - correct bit for core oplock reply. - */ - - if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } - - if(core_oplock_request && fsp->granted_oplock) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } + set_message(outbuf,34,0,True); + + p = outbuf + smb_vwv2; + + SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? ); + p++; + SSVAL(p,0,fnum); + p += 2; + SIVAL(p,0,smb_action); + p += 4; - set_message(outbuf,15,0,True); - SSVAL(outbuf,smb_vwv2,fnum); + CreationTime + p += 8; + LastAccessTime; + p += 8; + LastWriteTime; + p += 8; + ChangeTime; + p += 8; + FileAttributes; + p += 4; + AllocationSize; + p += 8; + EndOfFile; + p += 8; + SSVAL(p,0,0); /* File Type */ + p += 2; + SSVAL(p,0,0); /* Device State */ + p += 1; + SCVAL(p,0,0); /* Not Directory. */ + SSVAL(outbuf,smb_vwv3,fmode); if(lp_dos_filetime_resolution(SNUM(cnum)) ) put_dos_date3(outbuf,smb_vwv4,mtime & ~1); @@ -246,8 +321,10 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) chain_fnum = fnum; + restore_case_semantics(file_attributes); + return chain_reply(inbuf,outbuf,length,bufsize); -} +} /**************************************************************************** reply to an unsolicited SMBNTtranss - just ignore it! diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4fefb4b39c..6cf7dd3949 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1069,7 +1069,11 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize } case SMB_QUERY_FS_ATTRIBUTE_INFO: data_len = 12 + 2*strlen(FSTYPE_STRING); +#if 1 /* JRATEST */ + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */ +#else /* JRATEST */ SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ +#endif /* JRATEST */ SIVAL(pdata,4,128); /* Max filename component length */ SIVAL(pdata,8,2*strlen(FSTYPE_STRING)); PutUniCode(pdata+12,FSTYPE_STRING); -- cgit From 3daefed54e221b397f1eff43d2a83a61c4500fb1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jul 1998 18:49:08 +0000 Subject: chgpasswd.c: Fix from Peter Debus for Digital UNIX password change core dump bug. nmbd_subnetdb.c: Make namelist_entry_compare() static. nttrans.c: More NT SMB stuff. Jeremy. (This used to be commit 1925a29c6b355b8358ee99e5b876b6376aa7d628) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/nttrans.c | 93 +++++++++++++++++++++++++++--------------------- 2 files changed, 53 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e8f3abc4f1..204a4480e9 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -77,7 +77,7 @@ static int findpty(char **slave) #else /* defined(SVR4) || defined(SUNOS5) */ fstrcpy( line, "/dev/ptyXX" ); - dirp = OpenDir(-1, "/dev", True); + dirp = OpenDir(-1, "/dev", False); if (!dirp) return(-1); while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1cde27a9ff..f6b5704681 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -23,6 +23,7 @@ extern int DEBUGLEVEL; extern int Protocol; +extern int chain_fnum; extern connection_struct Connections[]; extern files_struct Files[]; extern int Client; @@ -46,6 +47,10 @@ static char *known_nt_pipes[] = { NULL }; +/**************************************************************************** + Save case statics. +****************************************************************************/ + static BOOL saved_case_sensitive; static BOOL saved_case_preserve; static BOOL saved_short_case_preserve; @@ -106,7 +111,8 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) reply bits separately. */ int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); int unixmode; - int size=0,fmode=0,mtime=0,rmode=0; + int fmode=0,mtime=0,rmode=0; + off_t file_size = 0; struct stat sbuf; int smb_action = 0; BOOL bad_path = False; @@ -206,16 +212,13 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); - if (fnum < 0) - { + if (fnum < 0) { restore_case_semantics(file_attributes); return(ERROR(ERRSRV,ERRnofids)); } - if (!check_name(fname,cnum)) - { - if((errno == ENOENT) && bad_path) - { + if (!check_name(fname,cnum)) { + if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } @@ -229,14 +232,12 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) unixmode = unix_mode(cnum,smb_attr | aARCH); open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request, &rmode,&smb_action); + oplock_request,&rmode,&smb_action); fsp = &Files[fnum]; - if (!fsp->open) - { - if((errno == ENOENT) && bad_path) - { + if (!fsp->open) { + if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } @@ -283,42 +284,32 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) p = outbuf + smb_vwv2; - SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? ); + /* + * Currently as we don't support level II oplocks we just report + * exclusive & batch here. + */ + + SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 3 : 0)); p++; SSVAL(p,0,fnum); p += 2; SIVAL(p,0,smb_action); p += 4; - - CreationTime - p += 8; - LastAccessTime; - p += 8; - LastWriteTime; + + /* Create time. */ + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); p += 8; - ChangeTime; + put_long_date(p,sbuf.st_atime); /* access time */ p += 8; - FileAttributes; - p += 4; - AllocationSize; + put_long_date(p,sbuf.st_mtime); /* write time */ p += 8; - EndOfFile; + put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; - SSVAL(p,0,0); /* File Type */ - p += 2; - SSVAL(p,0,0); /* Device State */ - p += 1; - SCVAL(p,0,0); /* Not Directory. */ - - SSVAL(outbuf,smb_vwv3,fmode); - if(lp_dos_filetime_resolution(SNUM(cnum)) ) - put_dos_date3(outbuf,smb_vwv4,mtime & ~1); - else - put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,size); - SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,smb_action); - + SIVAL(p,0,fmode); /* File Attributes. */ + p += 12; + SIVAL(p,0, size & 0xFFFFFFFF); + SIVAL(p,4, (size >> 32)); + chain_fnum = fnum; restore_case_semantics(file_attributes); @@ -326,6 +317,26 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) return chain_reply(inbuf,outbuf,length,bufsize); } +/**************************************************************************** + reply to a NT_TRANSACT_CREATE call (needs to process SD's). +****************************************************************************/ + +static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int cnum, + char **setup, char **params, char **data) +{ + char *params = *pparams; + uint32 flags = SIVAL(params,0); + uint32 desired_access = + uint32 file_attributes = SIVAL(inbuf,smb_ntcreate_FileAttributes); + uint32 share_access = SIVAL(inbuf,smb_ntcreate_ShareAccess); + uint32 create_disposition = SIVAL(inbuf,smb_ntcreate_CreateDisposition); + uint32 fname_len = MIN(((uint32)SSVAL(inbuf,smb_ntcreate_NameLength)), + ((uint32)sizeof(fname)-1)); + int smb_ofun; + int smb_open_mode; + int smb_attr = file_attributes & SAMBA_ATTRIBUTES_MASK; +} + /**************************************************************************** reply to an unsolicited SMBNTtranss - just ignore it! ****************************************************************************/ @@ -344,11 +355,11 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) { int outsize = 0; int cnum = SVAL(inbuf,smb_tid); -#if 0 +#if 0 /* Not used. */ uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount); uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); -#endif +#endif /* Not used. */ uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount); uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount); -- cgit From 6491a956ef0b6a54b28887521f75e2f54f18a6d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jul 1998 22:23:56 +0000 Subject: nttrans.c: More NT SMB stuff. shmem_sysv.c: Fix for shared memory problems on several systems, Second and subsequent use of shmget should use zero as the size. Fix from Veselin Terzic Jeremy. (This used to be commit 1cd94b24592ca31ffae671acfd83b0d42b212cab) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f6b5704681..5327502fd3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -106,7 +106,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) ((uint32)sizeof(fname)-1)); int smb_ofun; int smb_open_mode; - int smb_attr = file_attributes & SAMBA_ATTRIBUTES_MASK; + int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); @@ -334,7 +334,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int c ((uint32)sizeof(fname)-1)); int smb_ofun; int smb_open_mode; - int smb_attr = file_attributes & SAMBA_ATTRIBUTES_MASK; + int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); } /**************************************************************************** -- cgit From 7a2b695bcbf80f192eea8db09a3f30c2cf75412d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Jul 1998 22:48:21 +0000 Subject: password.c: Fixes to allow Win95 clients to have lm encrypted passwords recognised. lib/rpc/client/cli_login.c: Fix debug comment. lib/rpc/parse/parse_misc.c: Fix for passing null pointers. lib/rpc/parse/parse_net.c: Send correct password lengths when called from Win95. Jeremy. (This used to be commit ad1848b35521b3d478ea3226db818a1edef78254) --- source3/smbd/password.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 277e3a592e..1924a32780 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1947,7 +1947,8 @@ BOOL domain_client_validate( char *user, char *domain, * Next, check that the passwords given were encrypted. */ - if(smb_apasslen != 24 || smb_ntpasslen != 24) { + if(((smb_apasslen != 24) && (smb_apasslen != 0)) || + ((smb_ntpasslen != 24) && (smb_ntpasslen != 0))) { /* * Not encrypted - do so. @@ -2129,7 +2130,9 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); if(cli_nt_login_network(&cli, domain, user, smb_uid_low, (char *)local_challenge, - smb_apasswd, smb_ntpasswd, &ctr, &info3) == False) { + ((smb_apasslen != 0) ? smb_apasswd : NULL), + ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), + &ctr, &info3) == False) { DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ %s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); cli_nt_session_close(&cli); -- cgit From 8c1199c2c7067cdf59d5f22622a6fcf571b12c5f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jul 1998 01:42:05 +0000 Subject: Implementing more NT SMB functionality. Jeremy. (This used to be commit d34c91126049b7d3094455d407aa99a6d0452304) --- source3/smbd/nttrans.c | 414 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 332 insertions(+), 82 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5327502fd3..c890153781 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -89,80 +89,41 @@ static void restore_case_semantics(uint32 file_attributes) } /**************************************************************************** - reply to an NT create and X call. + Utility function to map create disposition. ****************************************************************************/ -int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) -{ - pstring fname; - int cnum = SVAL(inbuf,smb_tid); - int fnum = -1; - uint32 flags = SIVAL(inbuf,smb_ntcreate_Flags); - uint32 desired_access = SIVAL(inbuf,smb_ntcreate_DesiredAccess); - uint32 file_attributes = SIVAL(inbuf,smb_ntcreate_FileAttributes); - uint32 share_access = SIVAL(inbuf,smb_ntcreate_ShareAccess); - uint32 create_disposition = SIVAL(inbuf,smb_ntcreate_CreateDisposition); - uint32 fname_len = MIN(((uint32)SSVAL(inbuf,smb_ntcreate_NameLength)), - ((uint32)sizeof(fname)-1)); - int smb_ofun; - int smb_open_mode; - int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); - /* Breakout the oplock request bits so we can set the - reply bits separately. */ - int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); - int unixmode; - int fmode=0,mtime=0,rmode=0; - off_t file_size = 0; - struct stat sbuf; - int smb_action = 0; - BOOL bad_path = False; - files_struct *fsp; - char *p = NULL; - - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(cnum)) - return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize); - - /* If it's a request for a directory open, fail it. */ - if(flags & OPEN_DIRECTORY) - return(ERROR(ERRDOS,ERRnoaccess)); - - /* - * We need to construct the open_and_X ofun value from the - * NT values, as that's what our code is structured to accept. - */ - +static int map_create_disposition( uint32 create_disposition) +{ switch( create_disposition ) { case CREATE_NEW: /* create if not exist, fail if exist */ - smb_ofun = 0x10; - break; + return 0x10; case CREATE_ALWAYS: /* create if not exist, trunc if exist */ - smb_ofun = 0x12; - break; + return 0x12; case OPEN_EXISTING: /* fail if not exist, open if exists */ - smb_ofun = 0x1; - break; + return 0x1; case OPEN_ALWAYS: /* create if not exist, open if exists */ - smb_ofun = 0x11; - break; + return 0x11; case TRUNCATE_EXISTING: /* fail if not exist, truncate if exists */ - smb_ofun = 0x2; - break; + return 0x2; default: - DEBUG(0,("reply_ntcreate_and_X: Incorrect value for create_disposition = %d\n", + DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n", create_disposition )); - return(ERROR(ERRDOS,ERRbadaccess)); + return -1; } +} - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ +/**************************************************************************** + Utility function to map share modes. +****************************************************************************/ + +static int map_share_mode( uint32 desired_access, uint32 share_access) +{ + int smb_open_mode; switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) { case FILE_READ_DATA: @@ -175,9 +136,9 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) smb_open_mode = 2; break; default: - DEBUG(0,("reply_ntcreate_and_X: Incorrect value for desired_access = %x\n", + DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n", desired_access)); - return(ERROR(ERRDOS,ERRbadaccess)); + return -1; } /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */ @@ -202,6 +163,121 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) if(file_attributes & FILE_FLAG_WRITE_THROUGH) smb_open_mode |= (1<<14); + return smb_open_mode; +} + +/**************************************************************************** + Reply to an NT create and X call on a pipe. +****************************************************************************/ + +static int nt_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + pstring fname; + int cnum = SVAL(inbuf,smb_tid); + int pnum = -1; + uint16 vuid = SVAL(inbuf, smb_uid); + uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); + uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); + uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); + uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); + uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); + uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), + ((uint32)sizeof(fname)-1)); + int smb_ofun; + int smb_open_mode; + int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); + int unixmode; + int fmode=0,mtime=0,rmode=0; + off_t file_size = 0; + struct stat sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp; + char *p = NULL; + + StrnCpy(fname,smb_buf(inbuf),fname_len); + + DEBUG(4,("nt_open_pipe_and_X: Opening pipe %s.\n", fname)); + + /* See if it is one we want to handle. */ + for( i = 0; known_nt_pipes[i]; i++ ) + if( strequal(fname,known_nt_pipes[i])) + break; + + if ( known_nt_pipes[i] == NULL ) + return(ERROR(ERRSRV,ERRaccess)); + + /* Strip \\ off the name. */ + p = &fname[1]; + + /* Known pipes arrive with DIR attribs. Remove it so a regular file */ + /* can be opened and add it in after the open. */ + DEBUG(3,("nt_open_pipe_and_X: Known pipe %s opening.\n",p)); + + if((smb_ofun = map_create_disposition( create_disposition )) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + smb_ofun |= 0x10; /* Add Create it not exists flag */ + + pnum = open_rpc_pipe_hnd(p, cnum, vuid); + if (pnum < 0) + return(ERROR(ERRSRV,ERRnofids)); +} + +/**************************************************************************** + Reply to an NT create and X call. +****************************************************************************/ + +int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + pstring fname; + int cnum = SVAL(inbuf,smb_tid); + int fnum = -1; + uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); + uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); + uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); + uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); + uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); + uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), + ((uint32)sizeof(fname)-1)); + int smb_ofun; + int smb_open_mode; + int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); + /* Breakout the oplock request bits so we can set the + reply bits separately. */ + int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); + int unixmode; + int fmode=0,mtime=0,rmode=0; + off_t file_size = 0; + struct stat sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp; + char *p = NULL; + + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(cnum)) + return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize); + + /* If it's a request for a directory open, fail it. */ + if(flags & OPEN_DIRECTORY) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * We need to construct the open_and_X ofun value from the + * NT values, as that's what our code is structured to accept. + */ + + if((smb_ofun = map_create_disposition( create_disposition )) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ + + if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + /* * Check if POSIX semantics are wanted. */ @@ -256,14 +332,13 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRDOS,ERRnoaccess)); } + restore_case_semantics(file_attributes); + size = sbuf.st_size; fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { close_file(fnum,False); - - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); } @@ -312,33 +387,141 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) chain_fnum = fnum; - restore_case_semantics(file_attributes); - return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** - reply to a NT_TRANSACT_CREATE call (needs to process SD's). + Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int cnum, char **setup, char **params, char **data) { + pstring fname; + int fnum = -1; char *params = *pparams; - uint32 flags = SIVAL(params,0); - uint32 desired_access = - uint32 file_attributes = SIVAL(inbuf,smb_ntcreate_FileAttributes); - uint32 share_access = SIVAL(inbuf,smb_ntcreate_ShareAccess); - uint32 create_disposition = SIVAL(inbuf,smb_ntcreate_CreateDisposition); - uint32 fname_len = MIN(((uint32)SSVAL(inbuf,smb_ntcreate_NameLength)), + uint32 flags = IVAL(params,0); + uint32 desired_access = IVAL(params,8); + uint32 file_attributes = IVAL(params,20); + uint32 share_access = IVAL(params,24); + uint32 create_disposition = IVAL(params,28); + uint32 fname_len = MIN(((uint32)IVAL(params,44)), ((uint32)sizeof(fname)-1)); int smb_ofun; int smb_open_mode; int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); + + /* If it's a request for a directory open, fail it. */ + if(flags & OPEN_DIRECTORY) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * We need to construct the open_and_X ofun value from the + * NT values, as that's what our code is structured to accept. + */ + + if((smb_ofun = map_create_disposition( create_disposition )) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ + + if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + + /* + * Check if POSIX semantics are wanted. + */ + + set_posix_case_semantics(file_attributes); + + StrnCpy(fname,params+53,fname_len); + unix_convert(fname,cnum,0,&bad_path); + + fnum = find_free_file(); + if (fnum < 0) { + restore_case_semantics(file_attributes); + return(ERROR(ERRSRV,ERRnofids)); + } + + if (!check_name(fname,cnum)) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; + + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + unixmode = unix_mode(cnum,smb_attr | aARCH); + + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); + + fsp = &Files[fnum]; + + if (!fsp->open) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; + + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); + + restore_case_semantics(file_attributes); + + return(ERROR(ERRDOS,ERRnoaccess)); + } + + restore_case_semantics(file_attributes); + + size = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + mtime = sbuf.st_mtime; + if (fmode & aDIR) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* If the caller set the extended oplock request bit + and we granted one (by whatever means) - set the + correct bit for extended oplock reply. + */ + + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + smb_action |= EXTENDED_OPLOCK_GRANTED; + } + + if(oplock_request && fsp->granted_oplock) { + smb_action |= EXTENDED_OPLOCK_GRANTED; + } + } /**************************************************************************** - reply to an unsolicited SMBNTtranss - just ignore it! + Reply to a NT CANCEL request - just ignore it. +****************************************************************************/ + +int reply_ntcancel(char *inbuf,char *outbuf,int length,int bufsize) +{ + DEBUG(4,("Ignoring ntcancel of length %d\n",length)); + return(-1); +} + +/**************************************************************************** + Reply to an unsolicited SMBNTtranss - just ignore it! ****************************************************************************/ int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize) @@ -348,7 +531,74 @@ int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize) } /**************************************************************************** - reply to a SMBNTtrans + Reply to an NT transact rename command. +****************************************************************************/ + +static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int cnum, + char **setup, char **params, char **data) +{ + char *params = *pparams; + pstring fname; + int fnum = SVAL(params, 0); + uint16 rename_flags = SVAL(params,2); + uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); + uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)), + ((uint32)sizeof(fname)-1)); + + StrnCpy(fname,params+4,fname_len); + unix_convert(fname,cnum,0,&bad_path); + +} + +/**************************************************************************** + Reply to a notify change - we should never get this (for now) as we + don't allow a directory to be opened. +****************************************************************************/ + +static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int bufsize, int cnum, + char **setup, char **params, char **data) +{ + DEBUG(0,("call_nt_transact_notify_change: Should not be called !\n")); + return(ERROR(ERRSRV,ERRnosupport)); +} + +/**************************************************************************** + Reply to query a security descriptor - currently this is not implemented (it + is planned to be though). +****************************************************************************/ + +static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum, + char **setup, char **params, char **data) +{ + DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n")); + return(ERROR(ERRSRV,ERRnosupport)); +} + +/**************************************************************************** + Reply to set a security descriptor - currently this is not implemented (it + is planned to be though). +****************************************************************************/ + +static int call_nt_transact_set_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum, + char **setup, char **params, char **data) +{ + DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n")); + return(ERROR(ERRSRV,ERRnosupport)); +} + +/**************************************************************************** + Reply to IOCTL - not implemented - no plans. +****************************************************************************/ + +static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int bufsize, int cnum, + char **setup, char **params, char **data) +{ + DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); + return(ERROR(ERRSRV,ERRnosupport)); +} + +/**************************************************************************** + Reply to a SMBNTtrans. ****************************************************************************/ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) @@ -366,7 +616,7 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset); uint32 data_count = IVAL(inbuf,smb_nt_DataCount); uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset); - uint16 setup_count = SVAL(inbuf,smb_nt_SetupCount); + uint16 setup_count = CVAL(inbuf,smb_nt_SetupCount); uint16 function_code = SVAL( inbuf, smb_nt_Function); char *params = NULL, *data = NULL, *setup = NULL; uint32 num_params_sofar, num_data_sofar; @@ -454,17 +704,17 @@ due to being in oplock break state.\n", timestring() )); } /* Revise total_params and total_data in case they have changed downwards */ - total_parameter_count = SIVAL(inbuf, smb_nts_TotalParameterCount); - total_data_count = SIVAL(inbuf, smb_nts_TotalDataCount); - num_params_sofar += (parameter_count = SIVAL(inbuf,smb_nts_ParameterCount)); - num_data_sofar += ( data_count = SIVAL(inbuf, smb_nts_DataCount)); + total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); + total_data_count = IVAL(inbuf, smb_nts_TotalDataCount); + num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount)); + num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount)); if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n"); - memcpy( ¶ms[ SIVAL(inbuf, smb_nts_ParameterDisplacement)], - smb_base(inbuf) + SVAL(inbuf, smb_nts_ParameterOffset), parameter_count); - memcpy( &data[SVAL(inbuf, smb_nts_DataDisplacement)], - smb_base(inbuf)+ SVAL(inbuf, smb_nts_DataOffset), data_count); + memcpy( ¶ms[ IVAL(inbuf, smb_nts_ParameterDisplacement)], + smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count); + memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)], + smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count); } } -- cgit From ddf62bbbdb12e45d0fec5dab3dcd8030d2aa4680 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Jul 1998 00:41:32 +0000 Subject: NT SMB trans reply code. Jeremy. (This used to be commit 556254d72517c8a5bf70cafaf443df1675fe64d9) --- source3/smbd/nttrans.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/trans2.c | 150 +++++++++++++++++----------------- 2 files changed, 291 insertions(+), 74 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c890153781..bc7a504d1d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -47,6 +47,189 @@ static char *known_nt_pipes[] = { NULL }; +/**************************************************************************** + Send the required number of replies back. + We assume all fields other than the data fields are + set correctly for the type of call. + HACK ! Always assumes smb_setup field is zero. +****************************************************************************/ +static int send_nt_replies(char *outbuf, int bufsize, char *params, + int paramsize, char *pdata, int datasize) +{ + extern int max_send; + int data_to_send = datasize; + int params_to_send = paramsize; + int useable_space; + char *pp = params; + char *pd = pdata; + int params_sent_thistime, data_sent_thistime, total_sent_thistime; + int alignment_offset = 3; + int data_alignment_offset = 0; + + /* + * Initially set the wcnt area to be 18 - this is true for all + * transNT replies. + */ + + set_message(outbuf,18,0,True); + + /* + * If there genuinely are no parameters or data to send just send + * the empty packet. + */ + + if(params_to_send == 0 && data_to_send == 0) { + send_smb(Client,outbuf); + return 0; + } + + /* + * When sending params and data ensure that both are nicely aligned. + * Only do this alignment when there is also data to send - else + * can cause NT redirector problems. + */ + + if (((params_to_send % 4) != 0) && (data_to_send != 0)) + data_alignment_offset = 4 - (params_to_send % 4); + + /* + * Space is bufsize minus Netbios over TCP header minus SMB header. + * The alignment_offset is to align the param bytes on a four byte + * boundary (2 bytes for data len, one byte pad). + * NT needs this to work correctly. + */ + + useable_space = bufsize - ((smb_buf(outbuf)+ + alignment_offset+data_alignment_offset) - + outbuf); + + /* + * useable_space can never be more than max_send minus the + * alignment offset. + */ + + useable_space = MIN(useable_space, + max_send - (alignment_offset+data_alignment_offset)); + + + while (params_to_send || data_to_send) { + + /* + * Calculate whether we will totally or partially fill this packet. + */ + + total_sent_thistime = params_to_send + data_to_send + + alignment_offset + data_alignment_offset; + + /* + * We can never send more than useable_space. + */ + + total_sent_thistime = MIN(total_sent_thistime, useable_space); + + set_message(outbuf, 18, total_sent_thistime, True); + + /* + * Set total params and data to be sent. + */ + + SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize); + SIVAL(outbuf,smb_ntr_TotalDataCount,datasize); + + /* + * Calculate how many parameters and data we can fit into + * this packet. Parameters get precedence. + */ + + params_sent_thistime = MIN(params_to_send,useable_space); + data_sent_thistime = useable_space - params_sent_thistime; + data_sent_thistime = MIN(data_sent_thistime,data_to_send); + + SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime); + + if(params_sent_thistime == 0) { + SIVAL(outbuf,smb_ntr_ParameterOffset,0); + SIVAL(outbuf,smb_ntr_ParameterDisplacement,0); + } else { + /* + * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the + * parameter bytes, however the first 4 bytes of outbuf are + * the Netbios over TCP header. Thus use smb_base() to subtract + * them from the calculation. + */ + + SIVAL(outbuf,smb_ntr_ParameterOffset, + ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + /* + * Absolute displacement of param bytes sent in this packet. + */ + + SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params); + } + + /* + * Deal with the data portion. + */ + + SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime); + + if(data_sent_thistime == 0) { + SIVAL(outbuf,smb_ntr_DataOffset,0); + SIVAL(outbuf,smb_ntr_DataDisplacement, 0); + } else { + /* + * The offset of the data bytes is the offset of the + * parameter bytes plus the number of parameters being sent this time. + */ + + SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) - + smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); + SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata); + } + + /* + * Copy the param bytes into the packet. + */ + + if(params_sent_thistime) + memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + + /* + * Copy in the data bytes + */ + + if(data_sent_thistime) + memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ + data_alignment_offset,pd,data_sent_thistime); + + DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", + params_sent_thistime, data_sent_thistime, useable_space)); + DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", + params_to_send, data_to_send, paramsize, datasize)); + + /* Send the packet */ + send_smb(Client,outbuf); + + pp += params_sent_thistime; + pd += data_sent_thistime; + + params_to_send -= params_sent_thistime; + data_to_send -= data_sent_thistime; + + /* + * Sanity check + */ + + if(params_to_send < 0 || data_to_send < 0) { + DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!", + params_to_send, data_to_send)); + return -1; + } + } + + return 0; +} + /**************************************************************************** Save case statics. ****************************************************************************/ @@ -216,7 +399,7 @@ static int nt_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) if((smb_ofun = map_create_disposition( create_disposition )) == -1) return(ERROR(ERRDOS,ERRbadaccess)); - smb_ofun |= 0x10; /* Add Create it not exists flag */ + smb_ofun |= 0x10; /* Add Create if not exists flag */ pnum = open_rpc_pipe_hnd(p, cnum, vuid); if (pnum < 0) @@ -508,6 +691,36 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int c smb_action |= EXTENDED_OPLOCK_GRANTED; } + /* Realloc the size of parameters and data we will return */ + params = *pparams = Realloc(*pparams, 69); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + p = params; + SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 3 : 0)); + p += 2; + SSVAL(p,0,fnum); + p += 2; + SIVAL(p,0,smb_action); + p += 8; + /* Create time. */ + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fmode); /* File Attributes. */ + p += 12; + SIVAL(p,0, size & 0xFFFFFFFF); + SIVAL(p,4, (size >> 32)); + + /* Send the required number of replies */ + send_nt_replies(outbuf, bufsize, params, 69, *ppdata, 0); + + return -1; } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6cf7dd3949..3ea9cb201f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -67,109 +67,113 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, /* If there genuinely are no parameters or data to send just send the empty packet */ if(params_to_send == 0 && data_to_send == 0) - { - send_smb(Client,outbuf); - return 0; - } + { + send_smb(Client,outbuf); + return 0; + } /* When sending params and data ensure that both are nicely aligned */ /* Only do this alignment when there is also data to send - else can cause NT redirector problems. */ if (((params_to_send % 4) != 0) && (data_to_send != 0)) - data_alignment_offset = 4 - (params_to_send % 4); + data_alignment_offset = 4 - (params_to_send % 4); /* Space is bufsize minus Netbios over TCP header minus SMB header */ /* The alignment_offset is to align the param bytes on an even byte boundary. NT 4.0 Beta needs this to work correctly. */ useable_space = bufsize - ((smb_buf(outbuf)+ - alignment_offset+data_alignment_offset) - - outbuf); + alignment_offset+data_alignment_offset) - + outbuf); /* useable_space can never be more than max_send minus the alignment offset. */ useable_space = MIN(useable_space, - max_send - (alignment_offset+data_alignment_offset)); + max_send - (alignment_offset+data_alignment_offset)); while (params_to_send || data_to_send) - { - /* Calculate whether we will totally or partially fill this packet */ - total_sent_thistime = params_to_send + data_to_send + - alignment_offset + data_alignment_offset; - /* We can never send more than useable_space */ - total_sent_thistime = MIN(total_sent_thistime, useable_space); + { + /* Calculate whether we will totally or partially fill this packet */ + total_sent_thistime = params_to_send + data_to_send + + alignment_offset + data_alignment_offset; + /* We can never send more than useable_space */ + total_sent_thistime = MIN(total_sent_thistime, useable_space); - set_message(outbuf, 10, total_sent_thistime, True); + set_message(outbuf, 10, total_sent_thistime, True); - /* Set total params and data to be sent */ - SSVAL(outbuf,smb_tprcnt,paramsize); - SSVAL(outbuf,smb_tdrcnt,datasize); + /* Set total params and data to be sent */ + SSVAL(outbuf,smb_tprcnt,paramsize); + SSVAL(outbuf,smb_tdrcnt,datasize); - /* Calculate how many parameters and data we can fit into - this packet. Parameters get precedence */ + /* Calculate how many parameters and data we can fit into + this packet. Parameters get precedence */ - params_sent_thistime = MIN(params_to_send,useable_space); - data_sent_thistime = useable_space - params_sent_thistime; - data_sent_thistime = MIN(data_sent_thistime,data_to_send); + params_sent_thistime = MIN(params_to_send,useable_space); + data_sent_thistime = useable_space - params_sent_thistime; + data_sent_thistime = MIN(data_sent_thistime,data_to_send); - SSVAL(outbuf,smb_prcnt, params_sent_thistime); - if(params_sent_thistime == 0) - { - SSVAL(outbuf,smb_proff,0); - SSVAL(outbuf,smb_prdisp,0); - } else { - /* smb_proff is the offset from the start of the SMB header to the - parameter bytes, however the first 4 bytes of outbuf are - the Netbios over TCP header. Thus use smb_base() to subtract - them from the calculation */ - SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); - /* Absolute displacement of param bytes sent in this packet */ - SSVAL(outbuf,smb_prdisp,pp - params); - } + SSVAL(outbuf,smb_prcnt, params_sent_thistime); + if(params_sent_thistime == 0) + { + SSVAL(outbuf,smb_proff,0); + SSVAL(outbuf,smb_prdisp,0); + } + else + { + /* smb_proff is the offset from the start of the SMB header to the + parameter bytes, however the first 4 bytes of outbuf are + the Netbios over TCP header. Thus use smb_base() to subtract + them from the calculation */ + SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + /* Absolute displacement of param bytes sent in this packet */ + SSVAL(outbuf,smb_prdisp,pp - params); + } - SSVAL(outbuf,smb_drcnt, data_sent_thistime); - if(data_sent_thistime == 0) - { - SSVAL(outbuf,smb_droff,0); - SSVAL(outbuf,smb_drdisp, 0); - } else { - /* The offset of the data bytes is the offset of the - parameter bytes plus the number of parameters being sent this time */ - SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - - smb_base(outbuf)) + - params_sent_thistime + data_alignment_offset); - SSVAL(outbuf,smb_drdisp, pd - pdata); - } + SSVAL(outbuf,smb_drcnt, data_sent_thistime); + if(data_sent_thistime == 0) + { + SSVAL(outbuf,smb_droff,0); + SSVAL(outbuf,smb_drdisp, 0); + } + else + { + /* The offset of the data bytes is the offset of the + parameter bytes plus the number of parameters being sent this time */ + SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - + smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); + SSVAL(outbuf,smb_drdisp, pd - pdata); + } - /* Copy the param bytes into the packet */ - if(params_sent_thistime) - memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); - /* Copy in the data bytes */ - if(data_sent_thistime) - memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+data_alignment_offset,pd,data_sent_thistime); + /* Copy the param bytes into the packet */ + if(params_sent_thistime) + memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + /* Copy in the data bytes */ + if(data_sent_thistime) + memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ + data_alignment_offset,pd,data_sent_thistime); - DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", - params_sent_thistime, data_sent_thistime, useable_space)); - DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", - params_to_send, data_to_send, paramsize, datasize)); + DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", + params_sent_thistime, data_sent_thistime, useable_space)); + DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", + params_to_send, data_to_send, paramsize, datasize)); - /* Send the packet */ - send_smb(Client,outbuf); + /* Send the packet */ + send_smb(Client,outbuf); - pp += params_sent_thistime; - pd += data_sent_thistime; + pp += params_sent_thistime; + pd += data_sent_thistime; - params_to_send -= params_sent_thistime; - data_to_send -= data_sent_thistime; + params_to_send -= params_sent_thistime; + data_to_send -= data_sent_thistime; - /* Sanity check */ - if(params_to_send < 0 || data_to_send < 0) - { - DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!", - params_to_send, data_to_send)); - return -1; - } + /* Sanity check */ + if(params_to_send < 0 || data_to_send < 0) + { + DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!", + params_to_send, data_to_send)); + return -1; } + } return 0; } -- cgit From 86de50535f66c8ad51374b19fedb0377060ac8ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Jul 1998 19:13:01 +0000 Subject: New version of the DFS_AUTH code from Karsten Muuss Jeremy. (This used to be commit cf7402c5325afd1f9a737facf285cb905702adb2) --- source3/smbd/password.c | 281 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 242 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1924a32780..e160580e5f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -623,6 +623,19 @@ static BOOL afs_auth(char *this_user,char *password) #ifdef DFS_AUTH +/***************************************************************** + This new version of the DFS_AUTH code was donated by Karsten Muuss + . It fixes the following problems with the + old code : + + - Server credentials may expire + - Client credential cache files have wrong owner + - purge_context() function is called with invalid argument + + This new code was modified to ensure that on exit the uid/gid is + still root, and the original directory is restored. JRA. +******************************************************************/ + sec_login_handle_t my_dce_sec_context; int dcelogin_atmost_once = 0; @@ -634,70 +647,261 @@ static BOOL dfs_auth(char *this_user,char *password) error_status_t err; int err2; int prterr; + signed32 expire_time, current_time; boolean32 password_reset; - sec_passwd_rec_t my_dce_password; + struct passwd *pw; + sec_passwd_rec_t passwd_rec; sec_login_auth_src_t auth_src = sec_login_auth_src_network; unsigned char dce_errstr[dce_c_error_string_len]; + if (dcelogin_atmost_once) return(False); + +#ifndef NO_CRYPT /* * We only go for a DCE login context if the given password * matches that stored in the local password file.. * Assumes local passwd file is kept in sync w/ DCE RGY! */ - /* Fix for original (broken) code from Brett Wooldridge */ - if (dcelogin_atmost_once) - return (False); - /* This can be ifdefed as the DCE check below is stricter... */ -#ifndef NO_CRYPT if ( strcmp((char *)crypt(password,this_salt),this_crypted) ) - return (False); + return(False); #endif - if (sec_login_setup_identity( - (unsigned char *)this_user, - sec_login_no_flags, - &my_dce_sec_context, - &err) == 0) + sec_login_get_current_context(&my_dce_sec_context, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't get current context. %s\n", dce_errstr)); + + return(False); + } + + sec_login_certify_identity(my_dce_sec_context, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't get current context. %s\n", dce_errstr)); + + return(False); + } + + sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't get expiration. %s\n", dce_errstr)); + + return(False); + } + + time(¤t_time); + + if (expire_time < (current_time + 60)) { + struct passwd *pw; + sec_passwd_rec_t *key; + + sec_login_get_pwent(my_dce_sec_context, + (sec_login_passwd_t*)&pw, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); + + return(False); + } + + sec_login_refresh_identity(my_dce_sec_context, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't refresh identity. %s\n", dce_errstr)); + + return(False); + } + + sec_key_mgmt_get_key(rpc_c_authn_dce_secret, NULL, + (unsigned char *)pw->pw_name, + sec_c_key_version_none, + (void**)&key, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't get key for %s. %s\n", pw->pw_name, dce_errstr)); + + return(False); + } + + sec_login_valid_and_cert_ident(my_dce_sec_context, key, + &password_reset, &auth_src, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't validate and certify identity for %s. %s\n", + pw->pw_name, dce_errstr)); + } + + sec_key_mgmt_free_key(key, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't free key.\n", dce_errstr)); + } + } + + if (sec_login_setup_identity((unsigned char *)this_user, + sec_login_no_flags, + &my_dce_sec_context, + &err) == 0) + { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0,("DCE Setup Identity for %s failed: %s\n", - this_user,dce_errstr)); + this_user,dce_errstr)); return(False); } - my_dce_password.version_number = sec_passwd_c_version_none; - my_dce_password.pepper = NULL; - my_dce_password.key.key_type = sec_passwd_plain; - my_dce_password.key.tagged_union.plain = (idl_char *)password; - - if (sec_login_valid_and_cert_ident(my_dce_sec_context, - &my_dce_password, - &password_reset, - &auth_src, - &err) == 0 ) - { + sec_login_get_pwent(my_dce_sec_context, + (sec_login_passwd_t*)&pw, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); + + return(False); + } + + sec_login_purge_context(&my_dce_sec_context, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't purge context. %s\n", dce_errstr)); + + return(False); + } + + /* + * NB. I'd like to change these to call something like become_user() + * instead but currently we don't have a connection + * context to become the correct user. This is already + * fairly platform specific code however, so I think + * this should be ok. I have added code to go + * back to being root on error though. JRA. + */ + + if (setregid(-1, pw->pw_gid) != 0) { + DEBUG(0,("Can't set egid to %d (%s)\n", pw->pw_gid, strerror(errno))); + return False; + } + + if (setreuid(-1, pw->pw_uid) != 0) { + setgid(0); + DEBUG(0,("Can't set euid to %d (%s)\n", pw->pw_uid, strerror(errno))); + return False; + } + + if (sec_login_setup_identity((unsigned char *)this_user, + sec_login_no_flags, + &my_dce_sec_context, + &err) == 0) + + { dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n", - this_user,dce_errstr)); - + /* Go back to root, JRA. */ + setuid(0); + setgid(0); + DEBUG(0,("DCE Setup Identity for %s failed: %s\n", + this_user,dce_errstr)); return(False); } + sec_login_get_pwent(my_dce_sec_context, + (sec_login_passwd_t*)&pw, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + /* Go back to root, JRA. */ + setuid(0); + setgid(0); + DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); + + return(False); + } + + passwd_rec.version_number = sec_passwd_c_version_none; + passwd_rec.pepper = NULL; + passwd_rec.key.key_type = sec_passwd_plain; + passwd_rec.key.tagged_union.plain = (idl_char *)password; + + sec_login_validate_identity(my_dce_sec_context, + &passwd_rec, &password_reset, + &auth_src, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + /* Go back to root, JRA. */ + setuid(0); + setgid(0); + DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n", + this_user,dce_errstr)); + + return(False); + } + + sec_login_certify_identity(my_dce_sec_context, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + /* Go back to root, JRA. */ + setuid(0); + setgid(0); + DEBUG(0,("DCE certify identity failed: %s\n", dce_errstr)); + + return(False); + } + + if (auth_src != sec_login_auth_src_network) { + DEBUG(0,("DCE context has no network credentials.\n")); + } + sec_login_set_context(my_dce_sec_context, &err); - if (err != error_status_ok ) - { + if (err != error_status_ok ) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n", - this_user,dce_errstr)); - sec_login_purge_context(my_dce_sec_context, &err); + this_user,dce_errstr)); + + sec_login_purge_context(&my_dce_sec_context, &err); + /* Go back to root, JRA. */ + setuid(0); + setgid(0); return(False); } - else - { - DEBUG(0,("DCE login succeeded for principal %s on pid %d\n", - this_user, getpid())); - } + + sec_login_get_pwent(my_dce_sec_context, + (sec_login_passwd_t*)&pw, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); + + /* Go back to root, JRA. */ + setuid(0); + setgid(0); + return(False); + } + + DEBUG(0,("DCE login succeeded for principal %s on pid %d\n", + this_user, getpid())); + + DEBUG(3,("DCE principal: %s\n" + " uid: %d\n" + " gid: %d\n", + pw->pw_name, pw->pw_uid, pw->pw_gid)); + DEBUG(3,(" info: %s\n" + " dir: %s\n" + " shell: %s\n", + pw->pw_gecos, pw->pw_dir, pw->pw_shell)); + + sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); + if (err != error_status_ok ) { + dce_error_inq_text(err, dce_errstr, &err2); + /* Go back to root, JRA. */ + setuid(0); + setgid(0); + DEBUG(0,("DCE can't get expiration. %s\n", dce_errstr)); + + return(False); + } + + setuid(0); + setgid(0); + + DEBUG(0,("DCE context expires: %s",asctime(localtime(&expire_time)))); dcelogin_atmost_once = 1; return (True); @@ -709,15 +913,14 @@ void dfs_unlogin(void) int err2; unsigned char dce_errstr[dce_c_error_string_len]; - sec_login_purge_context(my_dce_sec_context, &err); + sec_login_purge_context(&my_dce_sec_context, &err); if (err != error_status_ok ) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0,("DCE purge login context failed for server instance %d: %s\n", - getpid(), dce_errstr)); + getpid(), dce_errstr)); } } - #endif #ifdef KRB5_AUTH -- cgit From 769269c384f49533e335969cff0f740f8148b6ff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Jul 1998 22:01:51 +0000 Subject: Needed fix to SIGHUP handling donated by branko.cibej@hermes.si (I can't believe we've had that bug so long :-). Jeremy. (This used to be commit 4d26757776af2aaba9cdaf4c956fab29bfde1599) --- source3/smbd/server.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 45a63a544a..300e8d28e8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3484,15 +3484,15 @@ BOOL reload_services(BOOL test) BOOL ret; if (lp_loaded()) + { + pstring fname; + pstrcpy(fname,lp_configfile()); + if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { - pstring fname; - pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) - { - pstrcpy(servicesf,fname); - test = False; - } + pstrcpy(servicesf,fname); + test = False; } + } reopen_logs(); @@ -3532,11 +3532,20 @@ BOOL reload_services(BOOL test) /**************************************************************************** this prevents zombie child processes ****************************************************************************/ +static BOOL reload_after_sighup = False; + static int sig_hup(void) { BlockSignals(True,SIGHUP); DEBUG(0,("Got SIGHUP\n")); - reload_services(False); + + /* + * Fix from here. + * We used to reload in the signal handler - this + * is a *BIG* no-no. + */ + + reload_after_sighup = True; #ifndef DONT_REINSTALL_SIG signal(SIGHUP,SIGNAL_CAST sig_hup); #endif @@ -5117,6 +5126,18 @@ static void process(void) reload_services(True); } + /* + * If reload_after_sighup == True then we got a SIGHUP + * and are being asked to reload. Fix from + */ + + if (reload_after_sighup) + { + DEBUG(0,("Reloading services after SIGHUP\n")); + reload_services(False); + reload_after_sighup = False; + } + /* automatic timeout if all connections are closed */ if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) { -- cgit From ddb7b8a3d6cb03a36ab23816b76c7b0c16c0ab37 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Jul 1998 01:13:16 +0000 Subject: AIX patch from Michael Wojcik adding detail to the AIX specific (and undocumented) setpriv and setuidx calls. Jeremy. (This used to be commit 7a8d0a4ed4e07090bfe776b5544712274d2426e4) --- source3/smbd/uid.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 749248ac86..358de86875 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -74,15 +74,124 @@ static BOOL become_uid(int uid) #ifdef AIX { /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */ + /* MWW: This is all undocumented, of course. There's a patch to WU-ftpd + in the AIX FAQ which does the setpriv, then sets the gid stuff, then + sets uid. Since Samba separates setting the gid and setting the uid, + I've duplicated the setpriv code in become_gid. I've also made the + requisite changes to become_gid to match the WU-ftpd patch. + + I believe we'll still get errors in the Samba logs. This setpriv + call is supposed to disable "trapdooring" on AIX - ie. normally + once a seteuid / setegid is done, the effective ID can't be set back + to what it was before. See the comments in become_root / unbecome_root. + I *think* that we may have to do something additional here to prevent + the "Can't set uid (AIX3)" messages, though - possibly change the + values of priv.pv_priv to keep the SET_PROC_DAC privilege, and + possibly SET_OBJ_DAC and SET_OBJ_STAT as well. + + The pv_priv array is two longwords, and the constants in sys/priv.h + have values between 1 and 64, according to the comments in priv.h. + This strongly suggests a bit vector - but does BYPASS_DAC_WRITE + (#define'd to 1) mean 1<<0 or 1<<1? Unfortunately, nothing's + defined to 0 or 64, which would be a dead giveaway. Also, what's the + fullword-boundary endianness? That is, is pv_priv[0] the high or + the low 32 bits? Fortunately, the values used by "su" (see below) + don't make much sense if pv_priv[0] is the high bits. Also, based + on analysis of the values used by su, I concluded that, for example, + BYPASS_DAC_READ (defined to 2) is bit "2" counting from 1 - ie. + if (pv_priv[0] & (1 << (BYPASS_DAC_READ - 1))) then BYPASS_DAC_READ + is on. That's a bit odd, but it makes more sense than if the + privilege constants are meant to be taken as exponents of 2. + + For analysis, I ran "su" as root under dbx, and stopped in setpriv. + The first argument to setpriv can be examined using + + print $r3 (eg. "0x30009" = PRIV_SET|PRIV_MAXIMUM|PRIV_EFFECTIV) + + the contents of the pv_priv array can be examined using + + ($r4)/2X + + Here's what su does: + + setpriv(PRIV_SET | PRIV_INHERITED | PRIV_BEQUEATH, {0,0}) + setpriv(PRIV_SET | PRIV_EFFECTIVE | PRIV_MAXIMUM, + {0x02800006, 0x00040000}) + 0x02800006 = SET_PROC_AUDIT | SET_PROC_ENV | + BYPASS_DAC_EXEC | BYPASS_DAC_READ + 0x00040000 = TPATH_CONFIG + setpriv(PRIV_SET | PRIV_EFFECTIVE, {0, 0}) + + Analysis: + + Reduce inherited privileges to none, so the child doesn't inherit + anything special. + Change su's privileges so it can execute the shell even if someone + has goofed up the permissions to it or to directories on the + search path; so it can set the process auditing characteristics + and privileged environment (stuff in /etc/security/environ with + the sysenv attribute); and so that it can set the trusted path + characteristics for this login. + Zap those privileges back off when we don't need them any more. + + I'm guessing we want to keep SET_PROC_DAC in the current priv set, + but not in the inherited one. That is, set PRIV_INHERITED and + PRIV_BEQUEATH to 0. We also probably want to set PRIV_MAXIMUM and + PRIV_EFFECTIVE to only the privs we need, which at this point would + appear to be just SET_PROC_DAC. *Note*: setting PRIV_MAXIMUM + with any of the privilege sets higher than what you're trying to + set the maximum to will produce an EINVAL. For example, if we + try to set PRIV_MAXIMUM to SET_PROC_DAC *before* we reduce + PRIV_INHERITED and PRIV_BEQUEATH, it won't work. Zero out the + inherited privileges first. + + Some experimentation with simple programs confirms that if we're + running with an EUID of 0 we can switch our UID/EUID back and + forth with setuidx - *unless* we call setpriv({0,0}, ...) first. + In other words, by default root has SET_PROC_DAT set, but we can + remove it from our privilege set. This is what we want to do for + child processes, I believe. + + Also, calling setpriv(PRIV_SUB|PRIV_EFFECTIVE,...) with pv_priv[0] + set to SET_PROC_DAC (1 << (SET_PROC_DAC - 1)) will prevent an + EUID-root process from switching its EUID back with setuidx. + + In other words, setuidx on AIX is *not* trapdoor. setuid is + trapdoor. We need a non-trapdoor setuid function, but we don't + want processes we fork to have access to it. Thus we use setuidx + but first we disable it for our children. + + Note, however, that we can only increase our privileges (as we + do in the first call to setpriv) if we're EUID-root. If we + started out as root, and then switched to a non-root user ID, + that's OK; we've already set them. Just don't try to set them + again. + + Also, I suspect that after using setpriv / setuidx / etc. here in + the AIX-specific code we DON'T want to fall through to the code that + calls setuid, etc. However, I haven't noticed any more problems with + the code the way it is here. + */ + 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) + if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_BEQUEATH, + &priv, sizeof(priv_t)) < 0) { + DEBUG(1, ("Can't set child privileges (AIX3): %s\n", strerror(errno))); + } + + priv.pv_priv[0] = (1 << (SET_PROC_DAC - 1)); + if (setpriv(PRIV_SET|PRIV_EFFECTIVE|PRIV_MAXIMUM, + &priv, sizeof(priv_t)) < 0) { + DEBUG(1, ("Can't set own privileges (AIX3): %s\n", strerror(errno))); + } + + if (setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 || + seteuid((uid_t)uid) < 0) { DEBUG(1,("Can't set uid (AIX3)\n")); + } } #endif @@ -125,6 +234,24 @@ static BOOL become_gid(int gid) DEBUG(1,("WARNING: using gid %d is a security risk\n",gid)); } +#ifdef AIX + { + /* MWW: See comment above in become_uid. */ + 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) { + DEBUG(1, ("Can't set privilege (AIX3)\n")); + } + if (setgidx(ID_REAL|ID_EFFECTIVE, (gid_t)gid) < 0 || + setegid((gid_t)gid) < 0) { + DEBUG(1,("Can't set gid (AIX3)\n")); + } + } +#endif + #ifdef USE_SETRES if (setresgid(-1,gid,-1) != 0) #elif defined(USE_SETFS) @@ -169,6 +296,10 @@ BOOL become_guest(void) pass = Get_Pwnam(lp_guestaccount(-1),True); if (!pass) return(False); +#ifdef AIX + /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before setting IDs */ + initgroups(pass->pw_name, (gid_t)pass->pw_gid); +#endif ret = become_id(pass->pw_uid,pass->pw_gid); if (!ret) -- cgit From 1e4b0268aa3b5021b72c17d54c846e575952e625 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Jul 1998 20:03:09 +0000 Subject: Fix for bug PR#8294 reported by - the Files array was storing the 'dos_to_unix' translated name, rather than the untranslated name. This could case problems when the name was run through dos_to_unix again. Jeremy. (This used to be commit 5f4be1498f7c907a539fe9b5998dfbcaa9e20e20) --- source3/smbd/server.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 300e8d28e8..e167941ccb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1512,7 +1512,14 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fsp->granted_oplock = False; fsp->sent_oplock_break = False; fsp->cnum = cnum; - string_set(&fsp->name,dos_to_unix(fname,False)); + /* + * Note that the file name here is the *untranslated* name + * ie. it is still in the DOS codepage sent from the client. + * All use of this filename will pass though the sys_xxxx + * functions which will do the dos_to_unix translation before + * mapping into a UNIX filename. JRA. + */ + string_set(&fsp->name,fname); fsp->wbmpx_ptr = NULL; /* -- cgit From 5ffb30858f3b9181c90e50f6a3d791e017be3f7e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 11 Jul 1998 00:28:34 +0000 Subject: nttrans.c: More NT SMB stuff. reply.c: Broke out the internals of reply_mv so that they may be called externally from the NT transact rename. server.c: Changed stat calls to sys_stat - found in code review of bugfix. Jeremy. (This used to be commit fb19dad88edfd7a5c7257a15afc9253fb41f4b99) --- source3/smbd/nttrans.c | 18 ++++--- source3/smbd/reply.c | 142 +++++++++++++++++++++++++++---------------------- source3/smbd/server.c | 19 +++++-- 3 files changed, 103 insertions(+), 76 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bc7a504d1d..c452e945c7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -48,11 +48,12 @@ static char *known_nt_pipes[] = { }; /**************************************************************************** - Send the required number of replies back. - We assume all fields other than the data fields are - set correctly for the type of call. - HACK ! Always assumes smb_setup field is zero. + Send the required number of replies back. + We assume all fields other than the data fields are + set correctly for the type of call. + HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ + static int send_nt_replies(char *outbuf, int bufsize, char *params, int paramsize, char *pdata, int datasize) { @@ -751,16 +752,17 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int c char **setup, char **params, char **data) { char *params = *pparams; - pstring fname; + pstring new_name; + pstring old_name; int fnum = SVAL(params, 0); uint16 rename_flags = SVAL(params,2); uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)), ((uint32)sizeof(fname)-1)); - StrnCpy(fname,params+4,fname_len); - unix_convert(fname,cnum,0,&bad_path); - + StrnCpy(new_name,params+4,fname_len); + unix_convert(new_name,cnum,0,&bad_path); + } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9177b3cde1..ec3ad84c9a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3152,33 +3152,28 @@ static BOOL can_rename(char *fname,int cnum) } /**************************************************************************** - reply to a mv + The guts of the rename command, split out so it may be called by the NT SMB + code. ****************************************************************************/ -int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int rename_internals(char *inbuf, char *outbuf, char *name, char *newname) { - int outsize = 0; - pstring name; int cnum; pstring directory; - pstring mask,newname; + pstring mask; pstring newname_last_component; char *p; - int count=0; - int error = ERRnoaccess; BOOL has_wild; - BOOL exists=False; BOOL bad_path1 = False; BOOL bad_path2 = False; + int count=0; + int error = ERRnoaccess; + BOOL exists=False; + + cnum = SVAL(inbuf,smb_tid); *directory = *mask = 0; - cnum = SVAL(inbuf,smb_tid); - - pstrcpy(name,smb_buf(inbuf) + 1); - pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); - - DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - unix_convert(name,cnum,0,&bad_path1); unix_convert(newname,cnum,newname_last_component,&bad_path2); @@ -3223,7 +3218,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) pstrcpy(newname, tmpstr); } - DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", + DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", case_sensitive, case_preserve, short_case_preserve, directory, newname, newname_last_component, is_short_name)); @@ -3249,21 +3244,22 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) pstrcpy(newname_modified_last_component,p+1); if(strcsequal(newname_modified_last_component, - newname_last_component) == False) { - /* - * Replace the modified last component with - * the original. - */ + newname_last_component) == False) { + /* + * Replace the modified last component with + * the original. + */ pstrcpy(p+1, newname_last_component); } } if (resolve_wildcards(directory,newname) && - can_rename(directory,cnum) && - !file_exist(newname,NULL) && - !sys_rename(directory,newname)) count++; + can_rename(directory,cnum) && + !file_exist(newname,NULL) && + !sys_rename(directory,newname)) + count++; - DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", + DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); if (!count) exists = file_exist(directory,NULL); @@ -3279,62 +3275,78 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (check_name(directory,cnum)) dirptr = OpenDir(cnum, directory, True); - if (dirptr) - { - error = ERRbadfile; + if (dirptr) { + error = ERRbadfile; - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr))) - { - pstring fname; - pstrcpy(fname,dname); + while ((dname = ReadDirName(dirptr))) { + pstring fname; + pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) continue; - - error = ERRnoaccess; - slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); - if (!can_rename(fname,cnum)) { - DEBUG(6,("rename %s refused\n", fname)); - continue; - } - pstrcpy(destname,newname); + if(!mask_match(fname, mask, case_sensitive, False)) + continue; + + error = ERRnoaccess; + slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); + if (!can_rename(fname,cnum)) { + DEBUG(6,("rename %s refused\n", fname)); + continue; + } + pstrcpy(destname,newname); - if (!resolve_wildcards(fname,destname)) { - DEBUG(6,("resolve_wildcards %s %s failed\n", - fname, destname)); - continue; - } + if (!resolve_wildcards(fname,destname)) { + DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname)); + continue; + } - if (file_exist(destname,NULL)) { - DEBUG(6,("file_exist %s\n", - destname)); - error = 183; - continue; - } - if (!sys_rename(fname,destname)) count++; - DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname)); - } - CloseDir(dirptr); + if (file_exist(destname,NULL)) { + DEBUG(6,("file_exist %s\n", destname)); + error = 183; + continue; + } + if (!sys_rename(fname,destname)) + count++; + DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } + CloseDir(dirptr); + } } - + if (count == 0) { if (exists) return(ERROR(ERRDOS,error)); - else - { - if((errno == ENOENT) && (bad_path1 || bad_path2)) - { + else { + if((errno == ENOENT) && (bad_path1 || bad_path2)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } return(UNIXERROR(ERRDOS,error)); } } - - outsize = set_message(outbuf,0,0,True); + + return 0; +} + +/**************************************************************************** + Reply to a mv. +****************************************************************************/ + +int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +{ + int outsize = 0; + pstring name; + pstring newname; + + pstrcpy(name,smb_buf(inbuf) + 1); + pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); + + DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); + + outsize = rename_internals(inbuf, outbuf, name, newname); + if(outsize == 0) + outsize = set_message(outbuf,0,0,True); return(outsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e167941ccb..374c41c1f5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1327,7 +1327,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct * open fd table. */ if(sbuf == 0) { - if(stat(fname, &statbuf) < 0) { + if(sys_stat(fname, &statbuf) < 0) { if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); @@ -1755,7 +1755,7 @@ BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) if(!lp_share_modes(SNUM(cnum))) return True; - if (stat(fname,&sbuf) == -1) return(True); + if (sys_stat(fname,&sbuf) == -1) return(True); dev = (uint32)sbuf.st_dev; inode = (uint32)sbuf.st_ino; @@ -4145,7 +4145,12 @@ reply for the nt protocol int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS; + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS +#ifdef HAVE_NT_SMBS + |CAP_NT_SMBS +#endif /* HAVE_NT_SMBS */ + ; + /* other valid capabilities which we may support at some time... CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; @@ -4712,6 +4717,14 @@ struct smb_message_struct {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER }, {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, +#ifdef HAVE_NT_SMBS + /* NT PROTOCOL FOLLOWS */ + {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, + {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, + {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, + {SMBntcancel, "SMBntcancel", reply_ntcancel, AS_USER }, +#endif /* HAVE_NT_SMBS */ + /* messaging routines */ {SMBsends,"SMBsends",reply_sends,AS_GUEST}, {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST}, -- cgit From ebad4278b72289f10ce7afa72a137f5e3e998b01 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 11 Jul 1998 01:25:02 +0000 Subject: nntrans.c: Fully implemented transact rename. reply.c: Added NT specific rename if exists flag to rename_internals(). smb.h: Added NT rename flag. Jeremy. (This used to be commit b398f7daf58459db6e8d3496502abeb634ac2183) --- source3/smbd/nttrans.c | 19 ++++++++++++++++--- source3/smbd/reply.c | 27 ++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c452e945c7..fa47bc7a17 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -469,6 +469,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_posix_case_semantics(file_attributes); StrnCpy(fname,smb_buf(inbuf),fname_len); + fname[fname_len] = '\0'; unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -622,6 +623,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int c set_posix_case_semantics(file_attributes); StrnCpy(fname,params+53,fname_len); + fname[fname_len] = '\0'; unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -753,16 +755,27 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int c { char *params = *pparams; pstring new_name; - pstring old_name; int fnum = SVAL(params, 0); - uint16 rename_flags = SVAL(params,2); + BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)), ((uint32)sizeof(fname)-1)); + int outsize = 0; + CHECK_FNUM(fnum, cnum); StrnCpy(new_name,params+4,fname_len); - unix_convert(new_name,cnum,0,&bad_path); + new_name[fname_len] = '\0'; + + outsize = rename_internals(inbuf, outbuf, Files[fnum].name, newname, replace_if_exists); + if(outsize == 0) { + /* + * Rename was successful. + */ + send_nt_replies(outbuf, bufsize, NULL, 0, NULL, 0); + outsize = -1; + } + return(outsize); } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec3ad84c9a..cb659e3ef9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3156,7 +3156,7 @@ static BOOL can_rename(char *fname,int cnum) code. ****************************************************************************/ -int rename_internals(char *inbuf, char *outbuf, char *name, char *newname) +int rename_internals(char *inbuf, char *outbuf, char *name, char *newname, BOOL replace_if_exists) { int cnum; pstring directory; @@ -3203,6 +3203,9 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname) has_wild = strchr(mask,'*') || strchr(mask,'?'); if (!has_wild) { + /* + * No wildcards - just process the one file. + */ BOOL is_short_name = is_8_3(name, True); /* Add a terminating '/' to the directory name. */ @@ -3253,6 +3256,18 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname) } } + if(replace_if_exists) { + /* + * NT SMB specific flag - we must remove a target + * file with the same name before continuing. + */ + if(resolve_wildcards(directory,newname) && + can_rename(directory,cnum) && + file_exist(newname,NULL)) { + sys_unlink(newname); + } + } + if (resolve_wildcards(directory,newname) && can_rename(directory,cnum) && !file_exist(newname,NULL) && @@ -3268,6 +3283,9 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname) error = 183; } } else { + /* + * Wildcards - process each file that matches. + */ void *dirptr = NULL; char *dname; pstring destname; @@ -3301,11 +3319,14 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname) continue; } - if (file_exist(destname,NULL)) { + if (replace_if_exists && file_exist(destname,NULL)) { + sys_unlink(destname); + } else if(file_exist(destname,NULL)) { DEBUG(6,("file_exist %s\n", destname)); error = 183; continue; } + if (!sys_rename(fname,destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); @@ -3344,7 +3365,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - outsize = rename_internals(inbuf, outbuf, name, newname); + outsize = rename_internals(inbuf, outbuf, name, newname, False); if(outsize == 0) outsize = set_message(outbuf,0,0,True); -- cgit From 59d07445b61e26321e3a1770c13756ac5948aabb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Jul 1998 21:23:59 +0000 Subject: loadparm.c: With apologies to Charlton Heston and Pierre Boule. "You damn fools, you finally did it". Changed default security mode to be security=user. Yes this is a big (although small in code) change. It's something we've been discussing for a while, to finally wean people off the legacy security=share mode which is *never* what you want. Jeremy. nmbd_incomingrequests.c: Bug fix for nmbd core dumps caused by overrun. Found by . nttrans.c: More NT smb stuff. reply.c: Unlink will overwrite an existing file. Well you learn something new about POSIX every day. :-). server.c: Tidyup unreadable code. smbpasswd.c: Code to allow -U remote_username to allow ordinary users to change remote passwords if their NT username is different from their UNIX username. Patch from . Jeremy. (This used to be commit 4eccb47cfb3c8907a6558b6ea9a02b0184458e34) --- source3/smbd/nttrans.c | 3 +- source3/smbd/reply.c | 26 ++++---- source3/smbd/server.c | 176 ++++++++++++++++++++++++------------------------- 3 files changed, 102 insertions(+), 103 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fa47bc7a17..65f2b0274e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -766,7 +766,8 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int c StrnCpy(new_name,params+4,fname_len); new_name[fname_len] = '\0'; - outsize = rename_internals(inbuf, outbuf, Files[fnum].name, newname, replace_if_exists); + outsize = rename_internals(inbuf, outbuf, Files[fnum].name, + newname, replace_if_exists); if(outsize == 0) { /* * Rename was successful. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cb659e3ef9..07b72738c5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3258,21 +3258,21 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname, BOOL if(replace_if_exists) { /* - * NT SMB specific flag - we must remove a target - * file with the same name before continuing. + * NT SMB specific flag - rename can overwrite + * file with the same name so don't check for + * file_exist(). */ if(resolve_wildcards(directory,newname) && can_rename(directory,cnum) && - file_exist(newname,NULL)) { - sys_unlink(newname); - } - } - - if (resolve_wildcards(directory,newname) && - can_rename(directory,cnum) && - !file_exist(newname,NULL) && !sys_rename(directory,newname)) - count++; + count++; + } else { + if (resolve_wildcards(directory,newname) && + can_rename(directory,cnum) && + !file_exist(newname,NULL) && + !sys_rename(directory,newname)) + count++; + } DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); @@ -3319,9 +3319,7 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname, BOOL continue; } - if (replace_if_exists && file_exist(destname,NULL)) { - sys_unlink(destname); - } else if(file_exist(destname,NULL)) { + if (!replace_if_exists && file_exist(destname,NULL)) { DEBUG(6,("file_exist %s\n", destname)); error = 183; continue; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 374c41c1f5..154f8ed93e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4787,126 +4787,126 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* make sure this is an SMB packet */ if (strncmp(smb_base(inbuf),"\377SMB",4) != 0) - { - DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf))); - return(-1); - } + { + DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf))); + return(-1); + } for (match=0;matchrequested_name); - } + /* + * Ensure the correct username is in sesssetup_user. + * This is a really ugly bugfix for problems with + * multiple session_setup_and_X's being done and + * allowing %U and %G substitutions to work correctly. + * There is a reason this code is done here, don't + * move it unless you know what you're doing... :-). + * JRA. + */ + if(session_tag != last_session_tag ) { + user_struct *vuser = NULL; + + last_session_tag = session_tag; + if(session_tag != UID_FIELD_INVALID) + vuser = get_valid_user_struct(session_tag); + if(vuser != NULL) + pstrcpy( sesssetup_user, vuser->requested_name); + } - /* does this protocol need to be run as root? */ - if (!(flags & AS_USER)) - unbecome_user(); + /* does this protocol need to be run as root? */ + if (!(flags & AS_USER)) + unbecome_user(); - /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(&Connections[cnum], cnum,session_tag)) { - if (flags & AS_GUEST) - flags &= ~AS_USER; - else - return(ERROR(ERRSRV,ERRinvnid)); - } - /* this code is to work around a bug is MS client 3 without - introducing a security hole - it needs to be able to do - print queue checks as guest if it isn't logged in properly */ - if (flags & AS_USER) - flags &= ~AS_GUEST; + /* does this protocol need to be run as the connected user? */ + if ((flags & AS_USER) && !become_user(&Connections[cnum], cnum,session_tag)) { + if (flags & AS_GUEST) + flags &= ~AS_USER; + else + return(ERROR(ERRSRV,ERRinvnid)); + } + /* this code is to work around a bug is MS client 3 without + introducing a security hole - it needs to be able to do + print queue checks as guest if it isn't logged in properly */ + if (flags & AS_USER) + flags &= ~AS_GUEST; - /* does it need write permission? */ - if ((flags & NEED_WRITE) && !CAN_WRITE(cnum)) - return(ERROR(ERRSRV,ERRaccess)); + /* does it need write permission? */ + if ((flags & NEED_WRITE) && !CAN_WRITE(cnum)) + return(ERROR(ERRSRV,ERRaccess)); - /* ipc services are limited */ - if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC)) - return(ERROR(ERRSRV,ERRaccess)); + /* ipc services are limited */ + if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC)) + return(ERROR(ERRSRV,ERRaccess)); - /* load service specific parameters */ - if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False)) - return(ERROR(ERRSRV,ERRaccess)); + /* load service specific parameters */ + if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False)) + return(ERROR(ERRSRV,ERRaccess)); - /* does this protocol need to be run as guest? */ - if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1))) - return(ERROR(ERRSRV,ERRaccess)); + /* does this protocol need to be run as guest? */ + if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1))) + return(ERROR(ERRSRV,ERRaccess)); - last_inbuf = inbuf; + last_inbuf = inbuf; - outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize); - } - else - { - outsize = reply_unknown(inbuf,outbuf); - } + outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize); + } + else + { + outsize = reply_unknown(inbuf,outbuf); } + } #if PROFILING GetTimeOfDay(&msg_end_time); if (!(smb_messages[match].flags & TIME_INIT)) - { - smb_messages[match].time = 0; - smb_messages[match].flags |= TIME_INIT; - } + { + smb_messages[match].time = 0; + smb_messages[match].flags |= TIME_INIT; + } { unsigned long this_time = (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 + - (msg_end_time.tv_usec - msg_start_time.tv_usec); + (msg_end_time.tv_usec - msg_start_time.tv_usec); smb_messages[match].time += this_time; total_time += this_time; } DEBUG(2,("TIME %s %d usecs %g pct\n", - smb_fn_name(type),smb_messages[match].time, - (100.0*smb_messages[match].time) / total_time)); + smb_fn_name(type),smb_messages[match].time, + (100.0*smb_messages[match].time) / total_time)); #endif return(outsize); -- cgit From f1cd3cb54c6495db2a91c473f91c78d24622d98e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Jul 1998 00:06:29 +0000 Subject: Makefile: Added CC=gcc to DGUX on Intel. Comment from ross@filmworks.com. ipc.c: loadparm.c: printing.c: Added code from to implement print queue pausing. New parameters are "queuepause command" and "queueresume command". util.c: Added fix for mount options in autmount map. lib/rpc/include/rpc_misc.h: Removed duplicate pipe names for Jean-Francois. Jeremy. (This used to be commit 559a9bf2bbdeae3e76ba9178779cd3a9537c4e91) --- source3/smbd/ipc.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9c48951e35..cbacca3b83 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1821,11 +1821,15 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, return(True); } +/**************************************************************************** + Purge a print queue - or pause or resume it. + ****************************************************************************/ static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { + int function = SVAL(param,0); char *str1 = param+2; char *str2 = skip_string(str1,1); char *QueueName = skip_string(str2,1); @@ -1853,19 +1857,30 @@ static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data, } if (snum >= 0 && VALID_SNUM(snum)) { - print_queue_struct *queue=NULL; - int i, count; lpq_reset(snum); - count = get_printqueue(snum,cnum,&queue,NULL); - for (i = 0; i < count; i++) - del_printqueue(cnum,snum,queue[i].job); - - if (queue) free(queue); + switch (function) { + case 74: /* Pause queue */ + case 75: /* Resume queue */ + status_printqueue(cnum,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK)); + DEBUG(3,("Print queue %s, queue=%s\n", + (function==74?"pause":"resume"),QueueName)); + break; + case 103: /* Purge */ + { + print_queue_struct *queue=NULL; + int i, count; + count = get_printqueue(snum,cnum,&queue,NULL); + for (i = 0; i < count; i++) + del_printqueue(cnum,snum,queue[i].job); + + if (queue) free(queue); + DEBUG(3,("Print queue purge, queue=%s\n",QueueName)); + break; + } + } } - DEBUG(3,("Print queue purge, queue=%s\n",QueueName)); - return(True); } @@ -3490,6 +3505,8 @@ struct {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, + {"WPrintQueuePause", 74, api_WPrintQueuePurge,0}, + {"WPrintQueueResume", 75, api_WPrintQueuePurge,0}, {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, -- cgit From dc44d77c7fd3427b1313e8ee2d7929fb7778148f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Jul 1998 22:46:06 +0000 Subject: Makefile: Added nttrans.o includes.h: Added termios.h for AIX. nttrans.c: Working NT SMB calls ! pipes.c: Use strequal instead of strcmp. server.c: Use #defines rather than numbers. smb.h: Updated NT SMB #defines. Jeremy. (This used to be commit 3e5cada9885059e9926eb6a56d350c4b1b53d245) --- source3/smbd/nttrans.c | 488 ++++++++++++++++++++++++++++--------------------- source3/smbd/pipes.c | 2 +- source3/smbd/server.c | 6 +- 3 files changed, 283 insertions(+), 213 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 65f2b0274e..541b482926 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -279,19 +279,20 @@ static void restore_case_semantics(uint32 file_attributes) static int map_create_disposition( uint32 create_disposition) { switch( create_disposition ) { - case CREATE_NEW: + case FILE_CREATE: /* create if not exist, fail if exist */ return 0x10; - case CREATE_ALWAYS: + case FILE_SUPERSEDE: + case FILE_OVERWRITE_IF: /* create if not exist, trunc if exist */ return 0x12; - case OPEN_EXISTING: + case FILE_OPEN: /* fail if not exist, open if exists */ return 0x1; - case OPEN_ALWAYS: + case FILE_OPEN_IF: /* create if not exist, open if exists */ return 0x11; - case TRUNCATE_EXISTING: + case FILE_OVERWRITE: /* fail if not exist, truncate if exists */ return 0x2; default: @@ -305,7 +306,7 @@ static int map_create_disposition( uint32 create_disposition) Utility function to map share modes. ****************************************************************************/ -static int map_share_mode( uint32 desired_access, uint32 share_access) +static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode; @@ -354,34 +355,14 @@ static int map_share_mode( uint32 desired_access, uint32 share_access) Reply to an NT create and X call on a pipe. ****************************************************************************/ -static int nt_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) +static int nt_open_pipe(char *fname, char *inbuf, char *outbuf, int *ppnum) { - pstring fname; int cnum = SVAL(inbuf,smb_tid); int pnum = -1; uint16 vuid = SVAL(inbuf, smb_uid); - uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); - uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); - uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); - uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); - uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); - uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), - ((uint32)sizeof(fname)-1)); - int smb_ofun; - int smb_open_mode; - int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); - int unixmode; - int fmode=0,mtime=0,rmode=0; - off_t file_size = 0; - struct stat sbuf; - int smb_action = 0; - BOOL bad_path = False; - files_struct *fsp; - char *p = NULL; + int i; - StrnCpy(fname,smb_buf(inbuf),fname_len); - - DEBUG(4,("nt_open_pipe_and_X: Opening pipe %s.\n", fname)); + DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); /* See if it is one we want to handle. */ for( i = 0; known_nt_pipes[i]; i++ ) @@ -392,19 +373,16 @@ static int nt_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRSRV,ERRaccess)); /* Strip \\ off the name. */ - p = &fname[1]; + fname++; - /* Known pipes arrive with DIR attribs. Remove it so a regular file */ - /* can be opened and add it in after the open. */ - DEBUG(3,("nt_open_pipe_and_X: Known pipe %s opening.\n",p)); + DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); - if((smb_ofun = map_create_disposition( create_disposition )) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); - smb_ofun |= 0x10; /* Add Create if not exists flag */ - - pnum = open_rpc_pipe_hnd(p, cnum, vuid); + pnum = open_rpc_pipe_hnd(fname, cnum, vuid); if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); + + *ppnum = pnum + 0x800; /* Mark file handle up into high range. */ + return 0; } /**************************************************************************** @@ -428,20 +406,16 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); /* Breakout the oplock request bits so we can set the reply bits separately. */ - int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); + int oplock_request = 0; int unixmode; int fmode=0,mtime=0,rmode=0; - off_t file_size = 0; + off_t file_len = 0; struct stat sbuf; int smb_action = 0; BOOL bad_path = False; files_struct *fsp; char *p = NULL; - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(cnum)) - return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize); - /* If it's a request for a directory open, fail it. */ if(flags & OPEN_DIRECTORY) return(ERROR(ERRDOS,ERRnoaccess)); @@ -459,87 +433,108 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) * and the share access. */ - if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1) + if((smb_open_mode = map_share_mode( desired_access, share_access, file_attributes)) == -1) return(ERROR(ERRDOS,ERRbadaccess)); /* - * Check if POSIX semantics are wanted. + * Get the file name. */ - - set_posix_case_semantics(file_attributes); - StrnCpy(fname,smb_buf(inbuf),fname_len); fname[fname_len] = '\0'; - unix_convert(fname,cnum,0,&bad_path); - - fnum = find_free_file(); - if (fnum < 0) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); - } - if (!check_name(fname,cnum)) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; + /* If it's an IPC, use the pipe handler. */ + if (IS_IPC(cnum)) { + int ret = nt_open_pipe(fname, inbuf, outbuf, &fnum); + if(ret != 0) + return ret; + smb_action = FILE_WAS_OPENED; + } else { + + /* + * Ordinary file. + */ + + /* + * Check if POSIX semantics are wanted. + */ + + set_posix_case_semantics(file_attributes); + + unix_convert(fname,cnum,0,&bad_path); + + fnum = find_free_file(); + if (fnum < 0) { + restore_case_semantics(file_attributes); + return(ERROR(ERRSRV,ERRnofids)); } - Files[fnum].reserved = False; - restore_case_semantics(file_attributes); + if (!check_name(fname,cnum)) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - unixmode = unix_mode(cnum,smb_attr | aARCH); + unixmode = unix_mode(cnum,smb_attr | aARCH); - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); - fsp = &Files[fnum]; + fsp = &Files[fnum]; - if (!fsp->open) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - Files[fnum].reserved = False; + if (!fsp->open) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; - restore_case_semantics(file_attributes); + restore_case_semantics(file_attributes); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); - restore_case_semantics(file_attributes); + restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } + return(ERROR(ERRDOS,ERRnoaccess)); + } - restore_case_semantics(file_attributes); + restore_case_semantics(file_attributes); - size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - mtime = sbuf.st_mtime; - if (fmode & aDIR) { - close_file(fnum,False); - return(ERROR(ERRDOS,ERRnoaccess)); - } + file_len = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + if(fmode == 0) + fmode = FILE_ATTRIBUTE_NORMAL; + mtime = sbuf.st_mtime; + if (fmode & aDIR) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } - /* If the caller set the extended oplock request bit - and we granted one (by whatever means) - set the - correct bit for extended oplock reply. - */ + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - } - - if(oplock_request && fsp->granted_oplock) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - } + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) + smb_action |= EXTENDED_OPLOCK_GRANTED; + if(oplock_request && fsp->granted_oplock) + smb_action |= EXTENDED_OPLOCK_GRANTED; + } + set_message(outbuf,34,0,True); p = outbuf + smb_vwv2; @@ -549,26 +544,46 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) * exclusive & batch here. */ - SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 3 : 0)); + SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); p++; SSVAL(p,0,fnum); p += 2; SIVAL(p,0,smb_action); p += 4; - /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); - p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ - p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ - p += 12; - SIVAL(p,0, size & 0xFFFFFFFF); - SIVAL(p,4, (size >> 32)); + if (IS_IPC(cnum)) { + /* + * Deal with pipe return. + */ + p += 32; + SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ + p += 20; + /* File type. */ + SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); + /* Device state. */ + SSVAL(p,2, 0x5FF); /* ? */ + } else { + /* + * Deal with file return. + */ + /* Create time. */ + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fmode); /* File Attributes. */ + p += 12; + if(sizeof(off_t) == 8) { + SIVAL(p,0, file_len & 0xFFFFFFFF); + SIVAL(p,4, file_len >> 32); + } else { + SIVAL(p,0,file_len); + } + } chain_fnum = fnum; @@ -579,12 +594,13 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ -static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int cnum, - char **setup, char **params, char **data) +static int call_nt_transact_create(char *inbuf, char *outbuf, int length, + int bufsize, int cnum, + char **ppsetup, char **ppparams, char **ppdata) { pstring fname; int fnum = -1; - char *params = *pparams; + char *params = *ppparams; uint32 flags = IVAL(params,0); uint32 desired_access = IVAL(params,8); uint32 file_attributes = IVAL(params,20); @@ -595,6 +611,17 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int c int smb_ofun; int smb_open_mode; int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); + /* Breakout the oplock request bits so we can set the + reply bits separately. */ + int oplock_request = 0; + int unixmode; + int fmode=0,mtime=0,rmode=0; + off_t file_len = 0; + struct stat sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp; + char *p = NULL; /* If it's a request for a directory open, fail it. */ if(flags & OPEN_DIRECTORY) @@ -613,112 +640,150 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int c * and the share access. */ - if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1) + if((smb_open_mode = map_share_mode( desired_access, share_access, file_attributes)) == -1) return(ERROR(ERRDOS,ERRbadaccess)); /* - * Check if POSIX semantics are wanted. + * Get the file name. */ - set_posix_case_semantics(file_attributes); - StrnCpy(fname,params+53,fname_len); fname[fname_len] = '\0'; - unix_convert(fname,cnum,0,&bad_path); - - fnum = find_free_file(); - if (fnum < 0) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); - } - if (!check_name(fname,cnum)) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; + /* If it's an IPC, use the pipe handler. */ + if (IS_IPC(cnum)) { + int ret = nt_open_pipe(fname, inbuf, outbuf, &fnum); + if(ret != 0) + return ret; + smb_action = FILE_WAS_OPENED; + } else { + /* + * Check if POSIX semantics are wanted. + */ + + set_posix_case_semantics(file_attributes); + + unix_convert(fname,cnum,0,&bad_path); + + fnum = find_free_file(); + if (fnum < 0) { + restore_case_semantics(file_attributes); + return(ERROR(ERRSRV,ERRnofids)); } - Files[fnum].reserved = False; - restore_case_semantics(file_attributes); + if (!check_name(fname,cnum)) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - unixmode = unix_mode(cnum,smb_attr | aARCH); + unixmode = unix_mode(cnum,smb_attr | aARCH); - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); - fsp = &Files[fnum]; + fsp = &Files[fnum]; - if (!fsp->open) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - Files[fnum].reserved = False; + if (!fsp->open) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; - restore_case_semantics(file_attributes); + restore_case_semantics(file_attributes); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); - restore_case_semantics(file_attributes); + restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } + return(ERROR(ERRDOS,ERRnoaccess)); + } - restore_case_semantics(file_attributes); + restore_case_semantics(file_attributes); - size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - mtime = sbuf.st_mtime; - if (fmode & aDIR) { - close_file(fnum,False); - return(ERROR(ERRDOS,ERRnoaccess)); - } + file_len = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + if(fmode == 0) + fmode = FILE_ATTRIBUTE_NORMAL; + mtime = sbuf.st_mtime; + if (fmode & aDIR) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } - /* If the caller set the extended oplock request bit - and we granted one (by whatever means) - set the - correct bit for extended oplock reply. - */ + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - } + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) + smb_action |= EXTENDED_OPLOCK_GRANTED; - if(oplock_request && fsp->granted_oplock) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - } + if(oplock_request && fsp->granted_oplock) + smb_action |= EXTENDED_OPLOCK_GRANTED; + } /* Realloc the size of parameters and data we will return */ - params = *pparams = Realloc(*pparams, 69); + params = *ppparams = Realloc(*ppparams, 69); if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); p = params; - SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 3 : 0)); + SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); p += 2; SSVAL(p,0,fnum); p += 2; SIVAL(p,0,smb_action); p += 8; - /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); - p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ - p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ - p += 12; - SIVAL(p,0, size & 0xFFFFFFFF); - SIVAL(p,4, (size >> 32)); + + if (IS_IPC(cnum)) { + /* + * Deal with pipe return. + */ + p += 32; + SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ + p += 20; + /* File type. */ + SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); + /* Device state. */ + SSVAL(p,2, 0x5FF); /* ? */ + } else { + /* + * Deal with file return. + */ + /* Create time. */ + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fmode); /* File Attributes. */ + p += 12; + if(sizeof(off_t) == 8) { + SIVAL(p,0, file_len & 0xFFFFFFFF); + SIVAL(p,4, (file_len >> 32)); + } else { + SIVAL(p,0,file_len); + } + } /* Send the required number of replies */ send_nt_replies(outbuf, bufsize, params, 69, *ppdata, 0); @@ -750,16 +815,16 @@ int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize) Reply to an NT transact rename command. ****************************************************************************/ -static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int cnum, - char **setup, char **params, char **data) +static int call_nt_transact_rename(char *inbuf, char *outbuf, int length, + int bufsize, int cnum, + char **ppsetup, char **ppparams, char **ppdata) { - char *params = *pparams; + char *params = *ppparams; pstring new_name; int fnum = SVAL(params, 0); BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; - uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)), - ((uint32)sizeof(fname)-1)); + ((uint32)sizeof(new_name)-1)); int outsize = 0; CHECK_FNUM(fnum, cnum); @@ -767,7 +832,7 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int c new_name[fname_len] = '\0'; outsize = rename_internals(inbuf, outbuf, Files[fnum].name, - newname, replace_if_exists); + new_name, replace_if_exists); if(outsize == 0) { /* * Rename was successful. @@ -784,8 +849,9 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int c don't allow a directory to be opened. ****************************************************************************/ -static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int bufsize, int cnum, - char **setup, char **params, char **data) +static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, + int bufsize, int cnum, + char **ppsetup, char **ppparams, char **ppdata) { DEBUG(0,("call_nt_transact_notify_change: Should not be called !\n")); return(ERROR(ERRSRV,ERRnosupport)); @@ -796,8 +862,9 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int bufsize is planned to be though). ****************************************************************************/ -static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum, - char **setup, char **params, char **data) +static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int length, + int bufsize, int cnum, + char **ppsetup, char **ppparams, char **ppdata) { DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n")); return(ERROR(ERRSRV,ERRnosupport)); @@ -808,8 +875,9 @@ static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int b is planned to be though). ****************************************************************************/ -static int call_nt_transact_set_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum, - char **setup, char **params, char **data) +static int call_nt_transact_set_security_desc(char *inbuf, char *outbuf, int length, + int bufsize, int cnum, + char **ppsetup, char **ppparams, char **ppdata) { DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n")); return(ERROR(ERRSRV,ERRnosupport)); @@ -819,8 +887,9 @@ static int call_nt_transact_set_security_desc(char *inbuf, char *outbuf, int buf Reply to IOCTL - not implemented - no plans. ****************************************************************************/ -static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int bufsize, int cnum, - char **setup, char **params, char **data) +static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int length, + int bufsize, int cnum, + char **ppsetup, char **ppparams, char **ppdata) { DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); return(ERROR(ERRSRV,ERRnosupport)); @@ -865,12 +934,13 @@ due to being in oplock break state.\n", timestring() )); outsize = set_message(outbuf,0,0,True); /* - * All nttrans messages we handle have smb_wcnt == 19 + setup_count. + * All nttrans messages we handle have smb_wct == 19 + setup_count. * Ensure this is so as a sanity check. */ - if(CVAL(inbuf, smb_wcnt) != 19 + setup_count) { - DEBUG(2,("Invalid smb_wcnt in trans2 call\n")); + if(CVAL(inbuf, smb_wct) != 19 + setup_count) { + DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", + CVAL(inbuf, smb_wct), 19 + setup_count)); return(ERROR(ERRSRV,ERRerror)); } @@ -955,11 +1025,11 @@ due to being in oplock break state.\n", timestring() )); /* Now we must call the relevant NT_TRANS function */ switch(function_code) { case NT_TRANSACT_CREATE: - outsize = call_nt_transact_create(inbuf, outbuf, bufsize, cnum, + outsize = call_nt_transact_create(inbuf, outbuf, length, bufsize, cnum, &setup, ¶ms, &data); break; case NT_TRANSACT_IOCTL: - outsize = call_nt_transact_ioctl(inbuf, outbuf, bufsize, cnum, + outsize = call_nt_transact_ioctl(inbuf, outbuf, length, bufsize, cnum, &setup, ¶ms, &data); break; case NT_TRANSACT_SET_SECURITY_DESC: @@ -976,12 +1046,12 @@ due to being in oplock break state.\n", timestring() )); break; case NT_TRANSACT_QUERY_SECURITY_DESC: outsize = call_nt_transact_query_security_desc(inbuf, outbuf, length, bufsize, cnum, - &setup, ¶ms, &data, total_data); + &setup, ¶ms, &data); break; default: /* Error in request */ DEBUG(0,("reply_nttrans: %s Unknown request %d in nttrans call\n",timestring(), - tran_call)); + function_code)); if(setup) free(setup); if(params) diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index fa11060ade..f0c5c3ba7f 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -81,7 +81,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* See if it is one we want to handle. */ for( i = 0; pipe_names[i].client_pipe ; i++ ) - if( strcmp(fname,pipe_names[i].client_pipe) == 0 ) + if( strequal(fname,pipe_names[i].client_pipe) ) break; if ( pipe_names[i].client_pipe == NULL ) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 154f8ed93e..a236e2e6ec 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2153,9 +2153,9 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if (action) { - if (file_existed && !(flags2 & O_TRUNC)) *action = 1; - if (!file_existed) *action = 2; - if (file_existed && (flags2 & O_TRUNC)) *action = 3; + if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED; + if (!file_existed) *action = FILE_WAS_CREATED; + if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN; } /* We must create the share mode entry before truncate as truncate can fail due to locking and have to close the -- cgit From b61b50ac2c42968a499d1c048fa5ee89e321f8a0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Jul 1998 00:47:16 +0000 Subject: local.h: Added NTFS define if HAVE_NT_SMBS is defined. nttrans.c: Fixed issue with access DELETE on renaming files. Jeremy. (This used to be commit 0fcf167af898a9c7a20fddc0d95c887477a22ed1) --- source3/smbd/nttrans.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 541b482926..45334e88e5 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -308,7 +308,7 @@ static int map_create_disposition( uint32 create_disposition) static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 file_attributes) { - int smb_open_mode; + int smb_open_mode = -1; switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) { case FILE_READ_DATA: @@ -320,10 +320,16 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi case FILE_READ_DATA|FILE_WRITE_DATA: smb_open_mode = 2; break; - default: - DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n", + } + + if (smb_open_mode == -1) { + if(desired_access & DELETE_ACCESS) + smb_open_mode = 2; + else { + DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n", desired_access)); - return -1; + return -1; + } } /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */ -- cgit From 18067a7f0c7153d5298ab1e6530ace4f25f926e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Jul 1998 01:38:08 +0000 Subject: nttrans.c: Added FILE_EXECUTE to required permissions checked. trans2.c: Fixed up the SMB_QUERY_FILE_ALT_NAME_INFO code, now I've got an NT client to generate it. It uses unicode without bothering to check the unicode bit of course, but now we can execute 16 bit exe's on a WinNT client from a long filename directory (hurrah). Jeremy. (This used to be commit 6c31be7d3ffff6a40bbbac6de53663fa707ac859) --- source3/smbd/nttrans.c | 2 ++ source3/smbd/trans2.c | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 45334e88e5..8f7f40b4f9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -325,6 +325,8 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi if (smb_open_mode == -1) { if(desired_access & DELETE_ACCESS) smb_open_mode = 2; + else if( desired_access & FILE_EXECUTE) + smb_open_mode = 0; else { DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n", desired_access)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3ea9cb201f..a0aa65601f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1073,11 +1073,10 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize } case SMB_QUERY_FS_ATTRIBUTE_INFO: data_len = 12 + 2*strlen(FSTYPE_STRING); -#if 1 /* JRATEST */ SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */ -#else /* JRATEST */ +#if 0 /* Old code. JRA. */ SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ -#endif /* JRATEST */ +#endif /* Old code. */ SIVAL(pdata,4,128); /* Max filename component length */ SIVAL(pdata,8,2*strlen(FSTYPE_STRING)); PutUniCode(pdata+12,FSTYPE_STRING); @@ -1147,8 +1146,10 @@ static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsi } /**************************************************************************** - reply to a TRANS2_QFILEINFO (query file info by fileid) + Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by + file name or file id). ****************************************************************************/ + static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, int bufsize,int cnum, char **pparams,char **ppdata, @@ -1294,19 +1295,18 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_ALT_NAME_INFO: { pstring short_name; - pstrcpy(short_name,fname); + pstrcpy(short_name,p); /* Mangle if not already 8.3 */ if(!is_8_3(short_name, True)) { if(!name_map_mangle(short_name,True,SNUM(cnum))) *short_name = '\0'; } - strncpy(pdata + 4,short_name,12); - (pdata + 4)[12] = 0; - strupper(pdata + 4); - l = strlen(pdata + 4); - data_size = 4 + l; - SIVAL(pdata,0,l); + strupper(short_name); + l = strlen(short_name); + PutUniCode(pdata + 4, short_name); + data_size = 4 + (2*l); + SIVAL(pdata,0,2*l); } break; -- cgit From 471087c9d28a4058efc16f98784cb179ffc1e4c4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Jul 1998 22:21:24 +0000 Subject: Code added to fix the renaming of a directory under NT SMB calls. local.h: Changed MAXDIR to MAX_OPEN_DIRECTORIES - shmem size also tuned by this. dir.c: Use MAX_OPEN_DIRECTORIES. nttrans.c: Allow opening of a directory to succeed. Doesn't actually open a file descriptor but takes a files_struct slot marked as an fd. reply.c: Changed to close any outstanding is_directory files. reply_close changed to understand directory files. server.c: Added open_directory(), close_directory() calls. smb.h: Added is_directory to files_struct. Changed OPEN_FNUM to check that target is !is_directory (this prevents the normal file calls from processing a directory files_struct. Jeremy. (This used to be commit e01ce693f47e75e277f3440d46e32b0bd866b550) --- source3/smbd/dir.c | 4 +- source3/smbd/nttrans.c | 81 +++++++++++++++++++++++--------- source3/smbd/reply.c | 55 ++++++++++++++++------ source3/smbd/server.c | 125 ++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 204 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 37fcd05743..8296a90fa1 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -115,7 +115,7 @@ static void *dptr_get(int key,uint32 lastused) if (dp->valid) { if (lastused) dp->lastused = lastused; if (!dp->ptr) { - if (dptrs_open >= MAXDIR) + if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); DEBUG(4,("Reopening dptr key %d\n",key)); if ((dp->ptr = OpenDir(dp->cnum, dp->path, True))) @@ -284,7 +284,7 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid) if (!start_dir(cnum,path)) return(-2); /* Code to say use a unix error return code. */ - if (dptrs_open >= MAXDIR) + if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); for (i=0;ireserved = False; restore_case_semantics(file_attributes); @@ -493,39 +495,72 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + /* + * NB. We have a potential bug here. If we cause an oplock + * break to ourselves, then we could end up processing filename + * related SMB requests whilst we await the oplock break + * response. As we may have changed the filename case + * semantics to be POSIX-like, this could mean a filename + * request could fail when it should succeed. This is a + * rare condition, but eventually we must arrange to restore + * the correct case semantics before issuing an oplock break + * request to our client. JRA. + */ + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); - fsp = &Files[fnum]; - - if (!fsp->open) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - Files[fnum].reserved = False; + restore_case_semantics(file_attributes); - restore_case_semantics(file_attributes); + if (!fsp->open) { + /* + * We cheat here. The only case we care about is a directory + * rename, where the NT client will attempt to open the source + * directory for DELETE access. Note that when the NT client + * does this it does *not* set the directory bit in the + * request packet. This is translated into a read/write open + * request. POSIX states that any open for write request on a directory + * will generate an EISDIR error, so we can catch this here and open + * a pseudo handle that is flagged as a directory. JRA. + */ - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if(errno == EISDIR) { + oplock_request = 0; + open_directory(fnum, cnum, fname, &smb_action); + + if(!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); - - restore_case_semantics(file_attributes); - - return(ERROR(ERRDOS,ERRnoaccess)); - } + if(fsp->is_directory) { + if(stat(fsp->name, &sbuf) != 0) { + close_directory(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } else { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } - restore_case_semantics(file_attributes); - file_len = sbuf.st_size; fmode = dos_mode(cnum,fname,&sbuf); if(fmode == 0) fmode = FILE_ATTRIBUTE_NORMAL; mtime = sbuf.st_mtime; - if (fmode & aDIR) { + if (!fsp->is_directory && (fmode & aDIR)) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -591,10 +626,12 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { SIVAL(p,0,file_len); } + p += 12; + SCVAL(p,0,fsp->is_directory ? 1 : 0); } chain_fnum = fnum; - + return chain_reply(inbuf,outbuf,length,bufsize); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 07b72738c5..a0d1775b21 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1490,10 +1490,15 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) open by this user */ if ((vuser != 0) && (lp_security() != SEC_SHARE)) { int i; - for (i=0;ivuid == vuid) && fsp->open) { + if(!fsp->is_directory) + close_file(i,False); + else + close_directory(i); } + } } invalidate_vuid(vuid); @@ -2416,14 +2421,16 @@ int reply_exit(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** - reply to a close + Reply to a close - has to deal with closing a directory opened by NT SMB's. ****************************************************************************/ + int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int fnum,cnum; int outsize = 0; time_t mtime; int32 eclass = 0, err = 0; + files_struct *fsp = NULL; outsize = set_message(outbuf,0,0,True); @@ -2435,23 +2442,43 @@ int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + /* + * We can only use CHECK_FNUM if we know it's not a directory. + */ + + if(!(VALID_FNUM(fnum) && Files[fnum].open && Files[fnum].is_directory)) + CHECK_FNUM(fnum,cnum); + + fsp = &Files[fnum]; if(HAS_CACHED_ERROR(fnum)) { - eclass = Files[fnum].wbmpx_ptr->wr_errclass; - err = Files[fnum].wbmpx_ptr->wr_error; + eclass = fsp->wbmpx_ptr->wr_errclass; + err = fsp->wbmpx_ptr->wr_error; } - mtime = make_unix_date3(inbuf+smb_vwv1); + if(fsp->is_directory) { + /* + * Special case - close NT SMB directory + * handle. + */ + DEBUG(3,("%s close directory fnum=%d cnum=%d\n", + timestring(), fnum, cnum )); + close_directory(fnum); + } else { + /* + * Close ordinary file. + */ + mtime = make_unix_date3(inbuf+smb_vwv1); - /* try and set the date */ - set_filetime(cnum, Files[fnum].name,mtime); + /* try and set the date */ + set_filetime(cnum, fsp->name,mtime); - DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - timestring(),Files[fnum].fd_ptr->fd,fnum,cnum, - Connections[cnum].num_files_open)); + DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", + timestring(),fsp->fd_ptr->fd,fnum,cnum, + Connections[cnum].num_files_open)); - close_file(fnum,True); + close_file(fnum,True); + } /* We have a cached error */ if(eclass || err) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a236e2e6ec..cabf2d44b1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1511,6 +1511,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fsp->modified = False; fsp->granted_oplock = False; fsp->sent_oplock_break = False; + fsp->is_directory = False; fsp->cnum = cnum; /* * Note that the file name here is the *untranslated* name @@ -1609,15 +1610,43 @@ static void check_magic(int fnum,int cnum) } } +/**************************************************************************** + Common code to close a file or a directory. +****************************************************************************/ + +static void close_filestruct(files_struct *fs_p) +{ + int cnum = fs_p->cnum; + + fs_p->reserved = False; + fs_p->open = False; + fs_p->is_directory = False; + + Connections[cnum].num_files_open--; + if(fs_p->wbmpx_ptr) + { + free((char *)fs_p->wbmpx_ptr); + fs_p->wbmpx_ptr = NULL; + } + +#if USE_MMAP + if(fs_p->mmap_ptr) + { + munmap(fs_p->mmap_ptr,fs_p->mmap_size); + fs_p->mmap_ptr = NULL; + } +#endif +} /**************************************************************************** -close a file - possibly invalidating the read prediction + Close a file - possibly invalidating the read prediction. -If normal_close is 1 then this came from a normal SMBclose (or equivalent) -operation otherwise it came as the result of some other operation such as -the closing of the connection. In the latter case printing and -magic scripts are not run + If normal_close is 1 then this came from a normal SMBclose (or equivalent) + operation otherwise it came as the result of some other operation such as + the closing of the connection. In the latter case printing and + magic scripts are not run. ****************************************************************************/ + void close_file(int fnum, BOOL normal_close) { files_struct *fs_p = &Files[fnum]; @@ -1626,28 +1655,12 @@ void close_file(int fnum, BOOL normal_close) uint32 inode = fs_p->fd_ptr->inode; int token; - Files[fnum].reserved = False; + close_filestruct(fs_p); #if USE_READ_PREDICTION invalidate_read_prediction(fs_p->fd_ptr->fd); #endif - fs_p->open = False; - Connections[cnum].num_files_open--; - if(fs_p->wbmpx_ptr) - { - free((char *)fs_p->wbmpx_ptr); - fs_p->wbmpx_ptr = NULL; - } - -#if USE_MMAP - if(fs_p->mmap_ptr) - { - munmap(fs_p->mmap_ptr,fs_p->mmap_size); - fs_p->mmap_ptr = NULL; - } -#endif - if (lp_share_modes(SNUM(cnum))) { lock_share_entry( cnum, dev, inode, &token); @@ -1684,6 +1697,69 @@ void close_file(int fnum, BOOL normal_close) memset(fs_p, 0, sizeof(*fs_p)); } +/**************************************************************************** + Close a directory opened by an NT SMB call. +****************************************************************************/ + +void close_directory(int fnum) +{ + files_struct *fs_p = &Files[fnum]; + + /* + * Do the code common to files and directories. + */ + close_filestruct(fs_p); + + if (fs_p->name) { + string_free(&fs_p->name); + } + + /* we will catch bugs faster by zeroing this structure */ + memset(fs_p, 0, sizeof(*fs_p)); +} + +/**************************************************************************** + Open a directory from an NT SMB call. +****************************************************************************/ + +void open_directory(int fnum,int cnum,char *fname, int *action) +{ + extern struct current_user current_user; + files_struct *fsp = &Files[fnum]; + + fsp->fd_ptr = NULL; + Connections[cnum].num_files_open++; + fsp->mode = 0; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + fsp->can_lock = True; + fsp->can_read = False; + fsp->can_write = False; + fsp->share_mode = 0; + fsp->print_file = False; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + fsp->is_directory = True; + fsp->cnum = cnum; + /* + * Note that the file name here is the *untranslated* name + * ie. it is still in the DOS codepage sent from the client. + * All use of this filename will pass though the sys_xxxx + * functions which will do the dos_to_unix translation before + * mapping into a UNIX filename. JRA. + */ + string_set(&fsp->name,fname); + fsp->wbmpx_ptr = NULL; + + *action = FILE_WAS_OPENED; +} + enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* @@ -4413,7 +4489,10 @@ static void close_open_files(int cnum) int i; for (i=0;i Date: Fri, 17 Jul 1998 22:22:48 +0000 Subject: Forgot to increase size of files_struct by MAX_OPEN_DIRECTORIES in previous checkin. Jeremy. (This used to be commit 7dfaca5d370ccb472d85416c623692ae7ec2176f) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index cabf2d44b1..98f65ce6e9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -67,7 +67,7 @@ extern int dcelogin_atmost_once; extern DOM_SID global_machine_sid; connection_struct Connections[MAX_CONNECTIONS]; -files_struct Files[MAX_OPEN_FILES]; +files_struct Files[MAX_OPEN_FILES+MAX_OPEN_DIRECTORIES]; /* * Indirection for file fd's. Needed as POSIX locking -- cgit From 781c9e50820e3bc2b11e15bbff2f16b6ad74f26a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Jul 1998 01:31:59 +0000 Subject: includes.h: Added feature type USE_GRANTPT for pty code. chgpasswd.c: Updated to use USE_GRANTPT feature definition. Jeremy. (This used to be commit 953c5dbbae8c1370e5988619746b508f26cb0390) --- source3/smbd/chgpasswd.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 204a4480e9..894762b707 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -59,22 +59,24 @@ extern int DEBUGLEVEL; static int findpty(char **slave) { int master; +#if defined(USE_GRANTPT) #if defined(SVR4) || defined(SUNOS5) extern char *ptsname(); -#else /* defined(SVR4) || defined(SUNOS5) */ +#endif /* defined(SVR4) || defined(SUNOS5) */ +#else /* USE_GRANTPT */ static fstring line; void *dirp; char *dpname; -#endif /* defined(SVR4) || defined(SUNOS5) */ +#endif /* USE_GRANTPT */ -#if defined(SVR4) || defined(SUNOS5) +#if defined(USE_GRANTPT) if ((master = open("/dev/ptmx", O_RDWR)) >= 1) { grantpt(master); unlockpt(master); *slave = ptsname(master); return (master); } -#else /* defined(SVR4) || defined(SUNOS5) */ +#else /* USE_GRANTPT */ fstrcpy( line, "/dev/ptyXX" ); dirp = OpenDir(-1, "/dev", False); @@ -94,7 +96,7 @@ static int findpty(char **slave) } } CloseDir(dirp); -#endif /* defined(SVR4) || defined(SUNOS5) */ +#endif /* USE_GRANTPT */ return (-1); } @@ -136,10 +138,12 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, ioctl(slave, I_PUSH, "ptem"); ioctl(slave, I_PUSH, "ldterm"); #else /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */ +#if defined(TIOCSCTTY) if (ioctl(slave,TIOCSCTTY,0) <0) { DEBUG(3,("Error in ioctl call for slave pty\n")); /* return(False); */ } +#endif /* defined(TIOCSCTTY) */ #endif /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */ /* Close master. */ -- cgit From f5866fd4ba8da9acde87c7f9da8f1a242540e287 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Jul 1998 13:59:19 +0000 Subject: Fixed bug found by Richard Sharpe. After increasing files_struct size by MAX_OPEN_DIRECTORIES for nttrans I forgot to update the code that enumerates the array. Created new MAX_FNUMS in local.h, changed all code that iterates through the files_struct array to use this. (sorry Richard). Jeremy. (This used to be commit 339b10222269d71c7a493cc08b7b1bfd35fd55fc) --- source3/smbd/ipc.c | 2 +- source3/smbd/reply.c | 4 ++-- source3/smbd/server.c | 18 +++++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index cbacca3b83..8b06fc91a3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1983,7 +1983,7 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, become_root(True); - for (i=0;ivuid == vuid) && fsp->open) { if(!fsp->is_directory) @@ -2396,7 +2396,7 @@ int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum == 0xFFFF) { int i; - for (i=0;i= MAX_OPEN_FILES) + if (first_file >= MAX_FNUMS) first_file = 1; - for (i=first_file;i Date: Thu, 23 Jul 1998 00:10:26 +0000 Subject: locking.c: Added lock type to is_locked() and do_lock() as the code in reply_lockingX wasn't taking account of the difference between read and write locks ! How did this ever work :-) ! reply.c: server.c: Add lock type to is_locked() and do_lock(). util.c: Also added code from klausr@ITAP.Physik.Uni-Stuttgart.De to fix problem with log files growing too large if an smbd writes less than 100 debug messages. Jeremy. (This used to be commit 80080abf772a470d5f0f4dcd4a75fb2a09a9fb2a) --- source3/smbd/nttrans.c | 12 ++++++------ source3/smbd/reply.c | 27 ++++++++++++++------------- source3/smbd/server.c | 16 +++++++++++++++- 3 files changed, 35 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 672e2c0802..9b6cfe1621 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -620,12 +620,12 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 12; - if(sizeof(off_t) == 8) { +#if OFF_T_IS_64_BITS SIVAL(p,0, file_len & 0xFFFFFFFF); SIVAL(p,4, file_len >> 32); - } else { +#else /* OFF_T_IS_64_BITS */ SIVAL(p,0,file_len); - } +#endif /* OFF_T_IS_64_BITS */ p += 12; SCVAL(p,0,fsp->is_directory ? 1 : 0); } @@ -822,12 +822,12 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 12; - if(sizeof(off_t) == 8) { +#if OFF_T_IS_64_BITS SIVAL(p,0, file_len & 0xFFFFFFFF); SIVAL(p,4, (file_len >> 32)); - } else { +#else /* OFF_T_IS_64_BITS */ SIVAL(p,0,file_len); - } +#endif /* OFF_T_IS_64_BITS */ } /* Send the required number of replies */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f6fd2ccd90..35189883e2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1858,7 +1858,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) } - if (!is_locked(fnum,cnum,maxcount,startpos)) + if (!is_locked(fnum,cnum,maxcount,startpos, F_RDLCK)) { int size = Files[fnum].size; int sizeneeded = startpos + maxcount; @@ -1943,7 +1943,7 @@ int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode)) + if(!do_lock( fnum, cnum, numtoread, startpos, F_RDLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); nread = read_file(fnum,data,startpos,numtoread); @@ -1987,7 +1987,7 @@ int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if (is_locked(fnum,cnum,numtoread,startpos)) + if (is_locked(fnum,cnum,numtoread,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); if (numtoread > 0) @@ -2035,7 +2035,7 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,12,0,True); data = smb_buf(outbuf); - if (is_locked(fnum,cnum,smb_maxcnt,smb_offs)) + if (is_locked(fnum,cnum,smb_maxcnt,smb_offs, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); nread = read_file(fnum,data,smb_offs,smb_maxcnt); ok = True; @@ -2097,7 +2097,7 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(inbuf,smb_com) = SMBwritec; CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fnum,cnum,tcount,startpos)) + if (is_locked(fnum,cnum,tcount,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); if (seek_file(fnum,startpos) != startpos) @@ -2188,7 +2188,7 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fnum,cnum,numtowrite,startpos)) + if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,startpos); @@ -2243,7 +2243,7 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fnum,cnum,numtowrite,startpos)) + if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,startpos); @@ -2299,7 +2299,7 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) data = smb_base(inbuf) + smb_doff; - if (is_locked(fnum,cnum,smb_dsize,smb_offs)) + if (is_locked(fnum,cnum,smb_dsize,smb_offs, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,smb_offs); @@ -2512,7 +2512,7 @@ int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (is_locked(fnum,cnum,numtowrite,startpos)) + if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,startpos); @@ -2559,7 +2559,7 @@ int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); - if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode)) + if(!do_lock( fnum, cnum, count, offset, F_WRLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); return(outsize); @@ -3729,7 +3729,8 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_locks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode)) + if(!do_lock(fnum,cnum,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + &eclass, &ecode)) break; } @@ -3796,7 +3797,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) tcount = maxcount; total_read = 0; - if (is_locked(fnum,cnum,maxcount,startpos)) + if (is_locked(fnum,cnum,maxcount,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); do @@ -3858,7 +3859,7 @@ int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) not an SMBwritebmpx - set this up now so we don't forget */ CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fnum,cnum,tcount,startpos)) + if (is_locked(fnum,cnum,tcount,startpos,F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,startpos); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9df2ed37bb..62ee75db0a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1948,7 +1948,7 @@ static void truncate_unless_locked(int fnum, int cnum, int token, BOOL *share_locked) { if (Files[fnum].can_write){ - if (is_locked(fnum,cnum,0x3FFFFFFF,0)){ + if (is_locked(fnum,cnum,0x3FFFFFFF,0,F_WRLCK)){ /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(cnum))) @@ -2861,6 +2861,20 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); return True; } close(Client); /* The parent doesn't need this socket */ + + /* + * Force parent to check log size after spawning child. + * Fix from klausr@ITAP.Physik.Uni-Stuttgart.De. + * The parent smbd will log to logserver.smb. + * It writes only two messages for each child + * started/finished. But each child writes, say, 50 messages also in + * logserver.smb, begining with the debug_count of the parent, before the + * child opens its own log file logserver.client. In a worst case + * scenario the size of logserver.smb would be checked after about + * 50*50=2500 messages (ca. 100kb). + */ + force_check_log_size(); + #endif /* NO_FORK_DEBUG */ } /* end for num */ } /* end while 1 */ -- cgit From 48a378f0674de0bdd3ee7d2147862179d55e4e56 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Fri, 24 Jul 1998 07:43:13 +0000 Subject: Changed the definition of the linked list header used in the directory cache so that it uses the new ubi_dlNewList() macro in ubi_dLinkList.h. (This used to be commit 16f0ad0c913e2d5b0198409485c56ad4809ca077) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 8296a90fa1..ceb9ae7633 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -638,7 +638,7 @@ typedef struct int snum; } dir_cache_entry; -static ubi_dlList dir_cache[1] = { { NULL, NULL, 0 } }; +static ubi_dlNewList( dir_cache ); void DirCacheAdd( char *path, char *name, char *dname, int snum ) /* ------------------------------------------------------------------------ ** -- cgit From 0fa2fde675da991096afc9abf896602d7a3803ab Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Sat, 25 Jul 1998 15:18:07 +0000 Subject: Noticed that I was using the strlen() of a string that I had strdup()'d before testing that the strdup() worked. Fixed. (This used to be commit 899d0d5de5dd9d080d5c4cb94874d4f939427d1b) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 33fc729a7f..f33b8ac2e6 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -995,7 +995,7 @@ BOOL name_map_mangle( char *OutName, BOOL need83, int snum ) /* mangle it into 8.3 */ tmp = strdup( OutName ); - mangle_name_83( OutName, strlen(tmp) ); + mangle_name_83( OutName, strlen(OutName) ); if( tmp ) { cache_mangled_name( OutName, tmp ); -- cgit From 1aa138922e5c0e4925ff5cbfcdb4e7cad367b31b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Jul 1998 18:50:45 +0000 Subject: chgpasswd.c: Fixed up debug calls to stop crashes if ptsname failed. local.h: Kept FSTYPE_STRING as Samba for now. nmbd_browsesync.c: Added bugfix from Matt Chapman mattyc@cyberdude.com - lmb_browserlist is now a struct ubi_dlList not a struct browse_cache_record *. server.c: smb.h: uid.c: password.c: Removed attrs code - it is not used anywhere. Jeremy (This used to be commit ef1af7fe6d5c58ae57b8e4efff0729e1a315da43) --- source3/smbd/chgpasswd.c | 17 +++++++++++++---- source3/smbd/password.c | 17 +++-------------- source3/smbd/server.c | 11 ++--------- source3/smbd/uid.c | 2 -- 4 files changed, 18 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 894762b707..560d989b47 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -74,7 +74,13 @@ static int findpty(char **slave) grantpt(master); unlockpt(master); *slave = ptsname(master); - return (master); + if(*slave == NULL) { + DEBUG(0,("findpty: Unable to create master/slave pty pair.\n")); + return -1; + } else { + DEBUG(10, ("findpty: Allocated slave pty %s\n", *slave)); + return (master); + } } #else /* USE_GRANTPT */ fstrcpy( line, "/dev/ptyXX" ); @@ -197,6 +203,8 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, #endif } + DEBUG(10, ("Invoking '%s' as password change program.\n", passwordprogram)); + /* execl() password-change application */ if (execl("/bin/sh","sh","-c",passwordprogram,NULL) < 0) { DEBUG(3,("Bad status returned from %s\n",passwordprogram)); @@ -297,7 +305,7 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL int master; pid_t pid, wpid; int wstat; - BOOL chstat; + BOOL chstat = False; /* allocate a pseudo-terminal device */ if ((master = findpty (&slavedev)) < 0) { @@ -315,7 +323,6 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL if ((chstat = talktochild(master, chatsequence)) == False) { DEBUG(3,("Child failed to change password: %s\n",name)); kill(pid, SIGKILL); /* be sure to end this process */ - return(False); } if ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { DEBUG(3,("The process is no longer waiting!\n\n")); @@ -348,7 +355,9 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL if(as_root) unbecome_root(False); } - DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); + + if(chstat) + DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); return (chstat); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e160580e5f..711729f86d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -134,17 +134,15 @@ void invalidate_vuid(uint16 vuid) vuser->n_sids = 0; - /* same number of igroups as groups as attrs */ + /* same number of igroups as groups */ vuser->n_groups = 0; if (vuser->groups && (vuser->groups != (gid_t *)vuser->igroups)) free(vuser->groups); if (vuser->igroups) free(vuser->igroups); - if (vuser->attrs ) free(vuser->attrs); if (vuser->sids ) free(vuser->sids); - vuser->attrs = NULL; vuser->sids = NULL; vuser->igroups = NULL; vuser->groups = NULL; @@ -167,8 +165,7 @@ char *validated_username(uint16 vuid) Setup the groups a user belongs to. ****************************************************************************/ int setup_groups(char *user, int uid, int gid, int *p_ngroups, - int **p_igroups, gid_t **p_groups, - int **p_attrs) + int **p_igroups, gid_t **p_groups) { if (-1 == initgroups(user,gid)) { @@ -183,25 +180,19 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups, { int i,ngroups; int *igroups; - int *attrs; gid_t grp = 0; ngroups = getgroups(0,&grp); if (ngroups <= 0) ngroups = 32; igroups = (int *)malloc(sizeof(int)*ngroups); - attrs = (int *)malloc(sizeof(int)*ngroups); for (i=0;in_groups = 0; vuser->groups = NULL; vuser->igroups = NULL; - vuser->attrs = NULL; /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(unix_name,uid,gid, &vuser->n_groups, &vuser->igroups, - &vuser->groups, - &vuser->attrs); + &vuser->groups); DEBUG(3,("uid %d registered to name %s\n",uid,unix_name)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 62ee75db0a..49ce759945 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3864,13 +3864,12 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de pcon->ngroups = 0; pcon->igroups = NULL; pcon->groups = NULL; - pcon->attrs = NULL; if (!IS_IPC(cnum)) { /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(pcon->user,pcon->uid,pcon->gid, - &pcon->ngroups,&pcon->igroups,&pcon->groups,&pcon->attrs); + &pcon->ngroups,&pcon->igroups,&pcon->groups); /* check number of connections */ if (!claim_connection(cnum, @@ -4235,11 +4234,7 @@ reply for the nt protocol int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS -#ifdef HAVE_NT_SMBS - |CAP_NT_SMBS -#endif /* HAVE_NT_SMBS */ - ; + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS |CAP_NT_SMBS; /* other valid capabilities which we may support at some time... @@ -4810,13 +4805,11 @@ struct smb_message_struct {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER }, {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, -#ifdef HAVE_NT_SMBS /* NT PROTOCOL FOLLOWS */ {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, {SMBntcancel, "SMBntcancel", reply_ntcancel, AS_USER }, -#endif /* HAVE_NT_SMBS */ /* messaging routines */ {SMBsends,"SMBsends",reply_sends,AS_GUEST}, diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 358de86875..2a75b660b5 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -369,7 +369,6 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) current_user.groups = conn->groups; current_user.igroups = conn->igroups; current_user.ngroups = conn->ngroups; - current_user.attrs = conn->attrs; } else { @@ -385,7 +384,6 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; current_user.igroups = vuser->igroups; - current_user.attrs = vuser->attrs; } if (initial_uid == 0) -- cgit From 7abcd0521e36425bf7c3dc90929c00ed49e9ab07 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jul 1998 18:15:31 +0000 Subject: loadparm.c: Added strict sync parameter. locking.c: Added code to deal with real open mode of file. reply.c: Added strict sync parameter. server.c: Added strict sync parameter. Fixed open modes. Jeremy. (This used to be commit ed57b603b5c9333d588e62d774ad2be67e43ffd9) --- source3/smbd/reply.c | 16 ++++++++-------- source3/smbd/server.c | 14 ++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 35189883e2..c9daf14b4b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2150,7 +2150,7 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); + sync_file(cnum,fnum); DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n", timestring(),fnum,cnum,startpos,numtowrite,total_written)); @@ -2202,7 +2202,7 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) nwritten = write_file(fnum,data,numtowrite); if (lp_syncalways(SNUM(cnum))) - sync_file(fnum); + sync_file(cnum,fnum); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2257,7 +2257,7 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) nwritten = write_file(fnum,data,numtowrite); if (lp_syncalways(SNUM(cnum))) - sync_file(fnum); + sync_file(cnum,fnum); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2330,7 +2330,7 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) chain_fnum = fnum; if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); + sync_file(cnum,fnum); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2398,10 +2398,10 @@ int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int i; for (i=0;ifd == -1) && (errno == EACCES)) { #endif /* EROFS */ - if(flags & O_WRONLY) { - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode); - fd_ptr->real_open_flags = O_WRONLY; - } else { - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode); - fd_ptr->real_open_flags = O_RDONLY; + if(accmode != O_RDWR) { + fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); + fd_ptr->real_open_flags = accmode; } } } @@ -1564,10 +1561,11 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct /******************************************************************* sync a file ********************************************************************/ -void sync_file(int fnum) +void sync_file(int cnum, int fnum) { #ifndef NO_FSYNC - fsync(Files[fnum].fd_ptr->fd); + if(lp_strict_sync(SNUM(cnum))) + fsync(Files[fnum].fd_ptr->fd); #endif } -- cgit From c48b3fce6be6d5d952cbcda0ddae223dda5a576f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Jul 1998 00:27:23 +0000 Subject: locking.c: Print messages when we downgrade a lock. reply.c: Do the same mask expansion we do in trans2.c - needed for Win98. trans2.c: Make the mask expansion into a function call now we have to do it twice. Jeremy. (This used to be commit 7b3a9d6285cc0d1967155a68845e28c6296ecc67) --- source3/smbd/reply.c | 3 +++ source3/smbd/trans2.c | 48 +++++++++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c9daf14b4b..f05ba2eee6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1081,6 +1081,9 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } } + /* Convert the formatted mask. (This code lives in trans2.c) */ + mask_convert(mask); + { for (p=mask; *p; p++) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a0aa65601f..2fcab32afb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -573,6 +573,33 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l return(found); } +/**************************************************************************** + Convert the directory masks formated for the wire. +****************************************************************************/ + +void mask_convert( char *mask) +{ + /* + * We know mask is a pstring. + */ + char *p = mask; + while (*p) { + if (*p == '<') { + pstring expnd; + if(p[1] != '"' && p[1] != '.') { + pstrcpy( expnd, p+1 ); + *p++ = '*'; + *p = '.'; + safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2); + } else + *p = '*'; + } + if (*p == '>') *p = '?'; + if (*p == '"') *p = '.'; + p++; + } +} + /**************************************************************************** reply to a TRANS2_FINDFIRST ****************************************************************************/ @@ -678,25 +705,8 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum if (dptr_num < 0) return(ERROR(ERRDOS,ERRbadfile)); - /* convert the formatted masks */ - { - p = mask; - while (*p) { - if (*p == '<') { - pstring expnd; - if(p[1] != '"' && p[1] != '.') { - pstrcpy( expnd, p+1 ); - *p++ = '*'; - *p = '.'; - safe_strcpy( p+1, expnd, sizeof(mask) - (p - mask) - 2); - } else - *p = '*'; - } - if (*p == '>') *p = '?'; - if (*p == '"') *p = '.'; - p++; - } - } + /* Convert the formatted mask. */ + mask_convert(mask); #if 0 /* JRA */ /* -- cgit From 64578c0589a3a741f81fb55c16eeb882128da00b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Jul 1998 03:08:05 +0000 Subject: merge from the autoconf2 branch to the main branch (This used to be commit 3bda7ac417107a7b01d91805ca71c4330657ed21) --- source3/smbd/chgpasswd.c | 58 +++---- source3/smbd/dfree.c | 231 +++++++++++++++++++++++++++ source3/smbd/dir.c | 301 ++--------------------------------- source3/smbd/ipc.c | 4 +- source3/smbd/password.c | 107 ++++--------- source3/smbd/quotas.c | 6 +- source3/smbd/server.c | 403 +++++++---------------------------------------- source3/smbd/smbrun.c | 9 +- source3/smbd/ssl.c | 6 +- source3/smbd/uid.c | 279 +++++++++----------------------- source3/smbd/vt_mode.c | 12 +- 11 files changed, 440 insertions(+), 976 deletions(-) create mode 100644 source3/smbd/dfree.c (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 560d989b47..af6746a699 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -51,25 +51,20 @@ extern int DEBUGLEVEL; -#ifdef ALLOW_CHANGE_PASSWORD - +#if ALLOW_CHANGE_PASSWORD #define MINPASSWDLENGTH 5 #define BUFSIZE 512 static int findpty(char **slave) { int master; -#if defined(USE_GRANTPT) -#if defined(SVR4) || defined(SUNOS5) - extern char *ptsname(); -#endif /* defined(SVR4) || defined(SUNOS5) */ -#else /* USE_GRANTPT */ +#ifndef HAVE_GRANTPT static fstring line; void *dirp; char *dpname; -#endif /* USE_GRANTPT */ +#endif /* !HAVE_GRANTPT */ -#if defined(USE_GRANTPT) +#if defined(HAVE_GRANTPT) if ((master = open("/dev/ptmx", O_RDWR)) >= 1) { grantpt(master); unlockpt(master); @@ -82,7 +77,7 @@ static int findpty(char **slave) return (master); } } -#else /* USE_GRANTPT */ +#else /* HAVE_GRANTPT */ fstrcpy( line, "/dev/ptyXX" ); dirp = OpenDir(-1, "/dev", False); @@ -102,7 +97,7 @@ static int findpty(char **slave) } } CloseDir(dirp); -#endif /* USE_GRANTPT */ +#endif /* HAVE_GRANTPT */ return (-1); } @@ -122,11 +117,11 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, gid = pass->pw_gid; uid = pass->pw_uid; -#ifdef USE_SETRES +#ifdef HAVE_SETRESUID setresuid(0,0,0); -#else /* USE_SETRES */ +#else setuid(0); -#endif /* USE_SETRES */ +#endif /* Start new session - gets rid of controlling terminal. */ if (setsid() < 0) { @@ -140,17 +135,15 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, slavedev)); return(False); } -#if defined(SVR4) || defined(SUNOS5) || defined(SCO) +#ifdef I_PUSH ioctl(slave, I_PUSH, "ptem"); ioctl(slave, I_PUSH, "ldterm"); -#else /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */ -#if defined(TIOCSCTTY) +#elif defined(TIOCSCTTY) if (ioctl(slave,TIOCSCTTY,0) <0) { DEBUG(3,("Error in ioctl call for slave pty\n")); /* return(False); */ } -#endif /* defined(TIOCSCTTY) */ -#endif /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */ +#endif /* Close master. */ close(master); @@ -188,18 +181,18 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, /* make us completely into the right uid */ if(!as_root) { -#ifdef USE_SETRES - setresgid(0,0,0); - setresuid(0,0,0); - setresgid(gid,gid,gid); - setresuid(uid,uid,uid); +#ifdef HAVE_SETRESUID + setresgid(0,0,0); + setresuid(0,0,0); + setresgid(gid,gid,gid); + setresuid(uid,uid,uid); #else - setuid(0); - seteuid(0); - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); + setuid(0); + seteuid(0); + setgid(gid); + setegid(gid); + setuid(uid); + seteuid(uid); #endif } @@ -391,13 +384,8 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) return (False); /* inform the user */ } -#if (defined(PASSWD_PROGRAM) && defined(PASSWD_CHAT)) - pstrcpy(passwordprogram,PASSWD_PROGRAM); - pstrcpy(chatsequence,PASSWD_CHAT); -#else pstrcpy(passwordprogram,lp_passwd_program()); pstrcpy(chatsequence,lp_passwd_chat()); -#endif if (!*chatsequence) { DEBUG(2,("Null chat sequence - no password changing\n")); diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c new file mode 100644 index 0000000000..799ff6a24c --- /dev/null +++ b/source3/smbd/dfree.c @@ -0,0 +1,231 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + functions to calculate the free disk space + Copyright (C) Andrew Tridgell 1998 + + 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; + +/**************************************************************************** +normalise for DOS usage +****************************************************************************/ +static void disk_norm(int *bsize,int *dfree,int *dsize) +{ + /* check if the disk is beyond the max disk size */ + int maxdisksize = lp_maxdisksize(); + if (maxdisksize) { + /* convert to blocks - and don't overflow */ + maxdisksize = ((maxdisksize*1024)/(*bsize))*1024; + if (*dsize > maxdisksize) *dsize = maxdisksize; + if (*dfree > maxdisksize) *dfree = maxdisksize-1; + /* the -1 should stop applications getting div by 0 + errors */ + } + + while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) { + *dfree /= 2; + *dsize /= 2; + *bsize *= 2; + if (*bsize > WORDMAX) { + *bsize = WORDMAX; + if (*dsize > WORDMAX) + *dsize = WORDMAX; + if (*dfree > WORDMAX) + *dfree = WORDMAX; + break; + } + } +} + + +/* Return the number of TOSIZE-byte blocks used by + BLOCKS FROMSIZE-byte blocks, rounding away from zero. + TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */ +static int adjust_blocks(int blocks, int fromsize, int tosize) +{ + if (tosize <= 0 || fromsize <= 0) { + return -1; + } + + if (fromsize == tosize) /* e.g., from 512 to 512 */ + return blocks; + else if (fromsize > tosize) /* e.g., from 2048 to 512 */ + return blocks * (fromsize / tosize); + else /* e.g., from 256 to 512 */ + return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize); +} + +/* this does all of the system specific guff to get the free disk space. + It is derived from code in the GNU fileutils package, but has been + considerably mangled for use here + + results are returned in *dfree and *dsize, in 512 byte units +*/ +static int fsusage(const char *path, int *dfree, int *dsize) +{ +#ifdef STAT_STATFS3_OSF1 +#define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512) + struct statfs fsd; + + if (statfs (path, &fsd, sizeof (struct statfs)) != 0) + return -1; +#endif /* STAT_STATFS3_OSF1 */ + +#ifdef STAT_STATFS2_FS_DATA /* Ultrix */ +#define CONVERT_BLOCKS(B) adjust_blocks ((B), 1024, 512) + struct fs_data fsd; + + if (statfs (path, &fsd) != 1) + return -1; + + (*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot); + (*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen); +#endif /* STAT_STATFS2_FS_DATA */ + +#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ +#define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512) + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; + +#ifdef STATFS_TRUNCATES_BLOCK_COUNTS + /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the + struct statfs are truncated to 2GB. These conditions detect that + truncation, presumably without botching the 4.1.1 case, in which + the values are not truncated. The correct counts are stored in + undocumented spare fields. */ + if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) { + fsd.f_blocks = fsd.f_spare[0]; + fsd.f_bfree = fsd.f_spare[1]; + fsd.f_bavail = fsd.f_spare[2]; + } +#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ +#endif /* STAT_STATFS2_BSIZE */ + + +#ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ +#define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512) + + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; +#endif /* STAT_STATFS2_FSIZE */ + +#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ +# if _AIX || defined(_CRAY) +# define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512) +# ifdef _CRAY +# define f_bavail f_bfree +# endif +# else +# define CONVERT_BLOCKS(B) (B) +# ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ +# ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ +# define f_bavail f_bfree +# endif +# endif +# endif + + struct statfs fsd; + + if (statfs (path, &fsd, sizeof fsd, 0) < 0) + return -1; + /* Empirically, the block counts on most SVR3 and SVR3-derived + systems seem to always be in terms of 512-byte blocks, + no matter what value f_bsize has. */ + +#endif /* STAT_STATFS4 */ + +#ifdef STAT_STATVFS /* SVR4 */ +# define CONVERT_BLOCKS(B) \ + adjust_blocks ((B), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512) + + struct statvfs fsd; + + if (statvfs (path, &fsd) < 0) + return -1; + /* f_frsize isn't guaranteed to be supported. */ + +#endif /* STAT_STATVFS */ + +#ifndef CONVERT_BLOCKS + /* we don't have any dfree code! */ + return -1; +#else +#if !defined(STAT_STATFS2_FS_DATA) + /* !Ultrix */ + (*dsize) = CONVERT_BLOCKS (fsd.f_blocks); + (*dfree) = CONVERT_BLOCKS (fsd.f_bavail); +#endif /* not STAT_STATFS2_FS_DATA */ +#endif + + return 0; +} + +/**************************************************************************** + return number of 1K blocks available on a path and total number +****************************************************************************/ +static int disk_free(char *path,int *bsize,int *dfree,int *dsize) +{ + int dfree_retval; + + (*dfree) = (*dsize) = 0; + (*bsize) = 512; + + fsusage(path, dfree, dsize); + + if (*bsize < 256) { + *bsize = 512; + } + + if ((*dsize)<1) { + static int done; + if (!done) { + DEBUG(0,("WARNING: dfree is broken on this system\n")); + done=1; + } + *dsize = 20*1024*1024/(*bsize); + *dfree = MAX(1,*dfree); + } + + disk_norm(bsize,dfree,dsize); + + if ((*bsize) < 1024) { + dfree_retval = (*dfree)/(1024/(*bsize)); + } else { + dfree_retval = ((*bsize)/1024)*(*dfree); + } + + return(dfree_retval); +} + + +/**************************************************************************** +wrap it to get filenames right +****************************************************************************/ +int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize) +{ + return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize)); +} + + diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ceb9ae7633..44e0556f20 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -30,7 +30,7 @@ extern connection_struct Connections[]; -uint32 dircounter = 0; +static uint32 dircounter = 0; #define NUMDIRPTRS 256 @@ -723,7 +723,7 @@ char *DirCacheCheck( char *path, char *name, int snum ) return(NULL); } /* DirCacheCheck */ -void DirCacheFlush( int snum ) +void DirCacheFlush(int snum) /* ------------------------------------------------------------------------ ** * Remove all cache entries which have an snum that matches the input. * @@ -733,18 +733,18 @@ void DirCacheFlush( int snum ) * * ------------------------------------------------------------------------ ** */ - { - dir_cache_entry *entry; - ubi_dlNodePtr next; - - for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); NULL != entry; ) - { - next = ubi_dlNext( entry ); - if( entry->snum == snum ) - free( ubi_dlRemThis( dir_cache, entry ) ); - entry = (dir_cache_entry *)next; - } - } /* DirCacheFlush */ +{ + dir_cache_entry *entry; + ubi_dlNodePtr next; + + for(entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); + NULL != entry; ) { + next = ubi_dlNext( entry ); + if( entry->snum == snum ) + free( ubi_dlRemThis( dir_cache, entry ) ); + entry = (dir_cache_entry *)next; + } +} /* DirCacheFlush */ /* -------------------------------------------------------------------------- ** * End of the section that manages the global directory cache. @@ -752,276 +752,3 @@ void DirCacheFlush( int snum ) */ -#ifdef REPLACE_GETWD -/* This is getcwd.c from bash. It is needed in Interactive UNIX. To - * add support for another OS you need to determine which of the - * conditional compilation macros you need to define. All the options - * are defined for Interactive UNIX. - */ -#ifdef ISC -#define HAVE_UNISTD_H -#define USGr3 -#define USG -#endif - -#if defined (HAVE_UNISTD_H) -# include -#endif - -#if defined (__STDC__) -# define CONST const -# define PTR void * -#else /* !__STDC__ */ -# define CONST -# define PTR char * -#endif /* !__STDC__ */ - -#if !defined (PATH_MAX) -# if defined (MAXPATHLEN) -# define PATH_MAX MAXPATHLEN -# else /* !MAXPATHLEN */ -# define PATH_MAX 1024 -# endif /* !MAXPATHLEN */ -#endif /* !PATH_MAX */ - -#if defined (_POSIX_VERSION) || defined (USGr3) || defined (HAVE_DIRENT_H) -# if !defined (HAVE_DIRENT) -# define HAVE_DIRENT -# endif /* !HAVE_DIRENT */ -#endif /* _POSIX_VERSION || USGr3 || HAVE_DIRENT_H */ - -#if defined (HAVE_DIRENT) -# define D_NAMLEN(d) (strlen ((d)->d_name)) -#else -# define D_NAMLEN(d) ((d)->d_namlen) -#endif /* ! (_POSIX_VERSION || USGr3) */ - -#if defined (USG) || defined (USGr3) -# define d_fileno d_ino -#endif - -#if !defined (alloca) -extern char *alloca (); -#endif /* alloca */ - -/* Get the pathname of the current working directory, - and put it in SIZE bytes of BUF. Returns NULL if the - directory couldn't be determined or SIZE was too small. - If successful, returns BUF. In GNU, if BUF is NULL, - an array is allocated with `malloc'; the array is SIZE - bytes long, unless SIZE <= 0, in which case it is as - big as necessary. */ -#if defined (__STDC__) -char * -getcwd (char *buf, size_t size) -#else /* !__STDC__ */ -char * -getcwd (buf, size) - char *buf; - int size; -#endif /* !__STDC__ */ -{ - static CONST char dots[] - = "../../../../../../../../../../../../../../../../../../../../../../../\ -../../../../../../../../../../../../../../../../../../../../../../../../../../\ -../../../../../../../../../../../../../../../../../../../../../../../../../.."; - CONST char *dotp, *dotlist; - size_t dotsize; - dev_t rootdev, thisdev; - ino_t rootino, thisino; - char path[PATH_MAX + 1]; - register char *pathp; - char *pathbuf; - size_t pathsize; - struct stat st; - - if (buf != NULL && size == 0) - { - errno = EINVAL; - return ((char *)NULL); - } - - pathsize = sizeof (path); - pathp = &path[pathsize]; - *--pathp = '\0'; - pathbuf = path; - - if (stat (".", &st) < 0) - return ((char *)NULL); - thisdev = st.st_dev; - thisino = st.st_ino; - - if (stat ("/", &st) < 0) - return ((char *)NULL); - rootdev = st.st_dev; - rootino = st.st_ino; - - dotsize = sizeof (dots) - 1; - dotp = &dots[sizeof (dots)]; - dotlist = dots; - while (!(thisdev == rootdev && thisino == rootino)) - { - register DIR *dirstream; - register struct dirent *d; - dev_t dotdev; - ino_t dotino; - char mount_point; - int namlen; - - /* Look at the parent directory. */ - if (dotp == dotlist) - { - /* My, what a deep directory tree you have, Grandma. */ - char *new; - if (dotlist == dots) - { - new = malloc (dotsize * 2 + 1); - if (new == NULL) - goto lose; - memcpy (new, dots, dotsize); - } - else - { - new = realloc ((PTR) dotlist, dotsize * 2 + 1); - if (new == NULL) - goto lose; - } - memcpy (&new[dotsize], new, dotsize); - dotp = &new[dotsize]; - dotsize *= 2; - new[dotsize] = '\0'; - dotlist = new; - } - - dotp -= 3; - - /* Figure out if this directory is a mount point. */ - if (stat (dotp, &st) < 0) - goto lose; - dotdev = st.st_dev; - dotino = st.st_ino; - mount_point = dotdev != thisdev; - - /* Search for the last directory. */ - dirstream = opendir(dotp); - if (dirstream == NULL) - goto lose; - while ((d = (struct dirent *)readdir(dirstream)) != NULL) - { - if (d->d_name[0] == '.' && - (d->d_name[1] == '\0' || - (d->d_name[1] == '.' && d->d_name[2] == '\0'))) - continue; - if (mount_point || d->d_fileno == thisino) - { - char *name; - - namlen = D_NAMLEN(d); - name = (char *) - alloca (dotlist + dotsize - dotp + 1 + namlen + 1); - memcpy (name, dotp, dotlist + dotsize - dotp); - name[dotlist + dotsize - dotp] = '/'; - memcpy (&name[dotlist + dotsize - dotp + 1], - d->d_name, namlen + 1); - if (lstat (name, &st) < 0) - { - int save = errno; - closedir(dirstream); - errno = save; - goto lose; - } - if (st.st_dev == thisdev && st.st_ino == thisino) - break; - } - } - if (d == NULL) - { - int save = errno; - closedir(dirstream); - errno = save; - goto lose; - } - else - { - size_t space; - - while ((space = pathp - pathbuf) <= namlen) - { - char *new; - - if (pathbuf == path) - { - new = malloc (pathsize * 2); - if (!new) - goto lose; - } - else - { - new = realloc ((PTR) pathbuf, (pathsize * 2)); - if (!new) - goto lose; - pathp = new + space; - } - (void) memcpy (new + pathsize + space, pathp, pathsize - space); - pathp = new + pathsize + space; - pathbuf = new; - pathsize *= 2; - } - - pathp -= namlen; - (void) memcpy (pathp, d->d_name, namlen); - *--pathp = '/'; - closedir(dirstream); - } - - thisdev = dotdev; - thisino = dotino; - } - - if (pathp == &path[sizeof(path) - 1]) - *--pathp = '/'; - - if (dotlist != dots) - free ((PTR) dotlist); - - { - size_t len = pathbuf + pathsize - pathp; - if (buf == NULL) - { - if (len < (size_t) size) - len = size; - buf = (char *) malloc (len); - if (buf == NULL) - goto lose2; - } - else if ((size_t) size < len) - { - errno = ERANGE; - goto lose2; - } - (void) memcpy((PTR) buf, (PTR) pathp, len); - } - - if (pathbuf != path) - free (pathbuf); - - return (buf); - - lose: - if ((dotlist != dots) && dotlist) - { - int e = errno; - free ((PTR) dotlist); - errno = e; - } - - lose2: - if ((pathbuf != path) && pathbuf) - { - int e = errno; - free ((PTR) pathbuf); - errno = e; - } - return ((char *)NULL); -} -#endif diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8b06fc91a3..adc3fcdcb5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -342,7 +342,7 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount) return(p->errcode == NERR_Success); } -#ifdef __STDC__ +#ifdef HAVE_STDARG_H static int package(struct pack_desc* p, ...) { #else @@ -357,7 +357,7 @@ va_dcl int is_string=0, stringused; int32 temp; -#ifdef __STDC__ +#ifdef HAVE_STDARG_H va_start(args,p); #else va_start(args); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 711729f86d..aae398dbda 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,7 +21,7 @@ #include "includes.h" -#if (defined(NETGROUP) && defined (AUTOMOUNT)) +#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) #include "rpcsvc/ypclnt.h" #endif @@ -347,44 +347,6 @@ void add_session_user(char *user) } -#ifdef NO_GETSPNAM -/* a fake shadow password routine which just fills a fake spwd struct - * with the sp_pwdp field. (sreiz@aie.nl) - */ -static struct spwd *getspnam(char *username) /* fake shadow password routine */ -{ - FILE *f; - char line[1024]; - static fstring pw; - static struct spwd static_spwd; - - static_spwd.sp_pwdp=0; - if (!(f=fopen("/etc/master.passwd", "r"))) - return 0; - while (fgets(line, 1024, f)) { - if (!strncmp(line, username, strlen(username)) && - line[strlen(username)]==':') { /* found entry */ - char *p, *q; - - p=line+strlen(username)+1; - if ((q=strchr(p, ':'))) { - *q=0; - if (q-p+1>20) - break; - fstrcpy(pw, p); - static_spwd.sp_pwdp=pw; - } - break; - } - } - fclose(f); - if (static_spwd.sp_pwdp) - return &static_spwd; - return 0; -} -#endif - - #ifdef OSF1_ENH_SEC /**************************************************************************** an enhanced crypt for OSF1 @@ -480,7 +442,7 @@ static void update_protected_database( char *user, BOOL result) } -#ifdef USE_PAM +#ifdef HAVE_PAM /******************************************************************* check on PAM authentication ********************************************************************/ @@ -583,7 +545,7 @@ static BOOL pam_auth(char *this_user,char *password) #endif -#ifdef AFS_AUTH +#ifdef WITH_AFS /******************************************************************* check on AFS authentication ********************************************************************/ @@ -610,7 +572,7 @@ static BOOL afs_auth(char *this_user,char *password) #endif -#ifdef DFS_AUTH +#ifdef WITH_DFS /***************************************************************** This new version of the DFS_AUTH code was donated by Karsten Muuss @@ -645,7 +607,7 @@ static BOOL dfs_auth(char *this_user,char *password) if (dcelogin_atmost_once) return(False); -#ifndef NO_CRYPT +#ifdef HAVE_CRYPT /* * We only go for a DCE login context if the given password * matches that stored in the local password file.. @@ -1099,24 +1061,24 @@ core of password checking routine BOOL password_check(char *password) { -#ifdef USE_PAM +#ifdef HAVE_PAM /* This falls through if the password check fails - - if NO_CRYPT is defined this causes an error msg + - if HAVE_CRYPT is not defined this causes an error msg saying Warning - no crypt available - - if NO_CRYPT is NOT defined this is a potential security hole + - if HAVE_CRYPT is defined this is a potential security hole as it may authenticate via the crypt call when PAM settings say it should fail. - if (pam_auth(this_user,password)) return(True); -Hence we make a direct return to avoid a second chance!!! + if (pam_auth(this_user,password)) return(True); + Hence we make a direct return to avoid a second chance!!! */ return (pam_auth(this_user,password)); #endif -#ifdef AFS_AUTH +#ifdef WITH_AFS if (afs_auth(this_user,password)) return(True); #endif -#ifdef DFS_AUTH +#ifdef WITH_DFS if (dfs_auth(this_user,password)) return(True); #endif @@ -1128,11 +1090,6 @@ Hence we make a direct return to avoid a second chance!!! if (krb4_auth(this_user,password)) return(True); #endif -#ifdef PWDAUTH - if (pwdauth(this_user,password) == 0) - return(True); -#endif - #ifdef OSF1_ENH_SEC { BOOL ret = (strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0); @@ -1152,11 +1109,11 @@ Hence we make a direct return to avoid a second chance!!! return(linux_bigcrypt(password,this_salt,this_crypted)); #endif -#ifdef HPUX_10_TRUSTED +#ifdef HAVE_BIGCRYPT return(strcmp(bigcrypt(password,this_salt),this_crypted) == 0); #endif -#ifdef NO_CRYPT +#ifndef HAVE_CRYPT DEBUG(1,("Warning - no crypt available\n")); return(False); #else @@ -1364,7 +1321,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } -#ifdef SHADOW_PWD +#ifdef HAVE_GETSPNAM { struct spwd *spass; @@ -1388,15 +1345,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) } #endif -#ifdef SecureWare - { - struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); - if (pr_pw && pr_pw->ufld.fd_encrypt) - pass->pw_passwd = pr_pw->ufld.fd_encrypt; - } -#endif - -#ifdef HPUX_10_TRUSTED +#ifdef HAVE_GETPRPWNAM { struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); if (pr_pw && pr_pw->ufld.fd_encrypt) @@ -1436,23 +1385,21 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) /* extract relevant info */ fstrcpy(this_user,pass->pw_name); fstrcpy(this_salt,pass->pw_passwd); -#ifdef HPUX - /* The crypt on HPUX won't work with more than 2 salt characters. */ + /* crypt on some platforms (HPUX in particular) + won't work with more than 2 salt characters. */ this_salt[2] = 0; -#endif /* HPUX */ + fstrcpy(this_crypted,pass->pw_passwd); if (!*this_crypted) { if (!lp_null_passwords()) { - DEBUG(2,("Disallowing access to %s due to null password\n",this_user)); - return(False); + DEBUG(2,("Disallowing access to %s due to null password\n",this_user)); + return(False); } -#ifndef PWDAUTH if (!*password) { - DEBUG(3,("Allowing access to %s with null password\n",this_user)); - return(True); + DEBUG(3,("Allowing access to %s with null password\n",this_user)); + return(True); } -#endif } /* try it as it came to us */ @@ -1551,7 +1498,7 @@ validate a group username entry. Return the username or NULL ****************************************************************************/ static char *validate_group(char *group,char *password,int pwlen,int snum) { -#ifdef NETGROUP +#ifdef HAVE_NETGROUP { char *host, *user, *domain; setnetgrent(group); @@ -1568,7 +1515,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) } #endif -#if HAVE_GETGRNAM +#ifdef HAVE_GETGRNAM { struct group *gptr = (struct group *)getgrnam(group); char **member; @@ -1824,7 +1771,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) { BOOL host_ok = False; -#ifdef NETGROUP +#ifdef HAVE_NETGROUP if (is_group) { static char *mydomain = NULL; @@ -1836,7 +1783,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) #else if (is_group) { - DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n")); + DEBUG(1,("Netgroups not configured\n")); continue; } #endif diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index ee08e48e65..dbdbd49921 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -581,7 +581,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) euser_id = geteuid(); -#ifdef USE_SETRES +#ifdef HPUX { uid_t user_id; @@ -592,7 +592,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) if (setresuid(user_id,-1,-1)) DEBUG(5,("Unable to reset uid to %d\n", user_id)); } -#else /* USE_SETRES */ +#else #if defined(__FreeBSD__) || defined(__OpenBSD__) { /* FreeBSD patches from Marty Moll */ @@ -620,7 +620,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ -#endif /* USE_SETRES */ +#endif /* HAVE_SETRES */ /* Use softlimit to determine disk space, except when it has been exceeded */ #if defined(__FreeBSD__) || defined(__OpenBSD__) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 151a6d7ded..3469e45732 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -33,7 +33,6 @@ char *OutBuffer = NULL; char *last_inbuf = NULL; int am_parent = 1; -int atexit_set = 0; /* the last message the was processed */ int last_message = -1; @@ -56,9 +55,9 @@ extern int smb_read_error; extern pstring user_socket_options; -#ifdef DFS_AUTH +#ifdef WITH_DFS extern int dcelogin_atmost_once; -#endif /* DFS_AUTH */ +#endif /* WITH_DFS */ /* * This is set on startup - it defines the SID for this @@ -695,236 +694,6 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa } -/**************************************************************************** -normalise for DOS usage -****************************************************************************/ -static void disk_norm(int *bsize,int *dfree,int *dsize) -{ - /* check if the disk is beyond the max disk size */ - int maxdisksize = lp_maxdisksize(); - if (maxdisksize) { - /* convert to blocks - and don't overflow */ - maxdisksize = ((maxdisksize*1024)/(*bsize))*1024; - if (*dsize > maxdisksize) *dsize = maxdisksize; - if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop - applications getting - div by 0 errors */ - } - - while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) - { - *dfree /= 2; - *dsize /= 2; - *bsize *= 2; - if (*bsize > WORDMAX ) - { - *bsize = WORDMAX; - if (*dsize > WORDMAX) - *dsize = WORDMAX; - if (*dfree > WORDMAX) - *dfree = WORDMAX; - break; - } - } -} - -/**************************************************************************** - return number of 1K blocks available on a path and total number -****************************************************************************/ -int disk_free(char *path,int *bsize,int *dfree,int *dsize) -{ - char *df_command = lp_dfree_command(); - int dfree_retval; -#ifdef QUOTAS - int dfreeq_retval; - int dfreeq = 0; - int bsizeq = *bsize; - int dsizeq = *dsize; -#endif - -#ifndef NO_STATFS -#ifdef USE_STATVFS - struct statvfs fs; -#else -#ifdef ULTRIX - struct fs_data fs; -#else - struct statfs fs; -#endif -#endif -#endif - - /* possibly use system() to get the result */ - if (df_command && *df_command) - { - int ret; - pstring syscmd; - pstring outfile; - - slprintf(outfile,sizeof(outfile)-1, "%s/dfree.smb.%d",tmpdir(),(int)getpid()); - slprintf(syscmd,sizeof(syscmd)-1,"%s %s",df_command,path); - standard_sub_basic(syscmd); - - ret = smbrun(syscmd,outfile,False); - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - - { - FILE *f = fopen(outfile,"r"); - *dsize = 0; - *dfree = 0; - *bsize = 1024; - if (f) - { - fscanf(f,"%d %d %d",dsize,dfree,bsize); - fclose(f); - } - else - DEBUG(0,("Can't open %s\n",outfile)); - } - - unlink(outfile); - disk_norm(bsize,dfree,dsize); - dfree_retval = ((*bsize)/1024)*(*dfree); -#ifdef QUOTAS - /* Ensure we return the min value between the users quota and - what's free on the disk. Thanks to Albrecht Gebhardt - for this fix. - */ - if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq)) - { - disk_norm(&bsizeq, &dfreeq, &dsizeq); - dfreeq_retval = ((bsizeq)/1024)*(dfreeq); - dfree_retval = ( dfree_retval < dfreeq_retval ) ? - dfree_retval : dfreeq_retval ; - /* maybe dfree and dfreeq are calculated using different bsizes - so convert dfree from bsize into bsizeq */ - /* avoid overflows due to multiplication, so do not: - *dfree = ((*dfree) * (*bsize)) / (bsizeq); - bsize and bsizeq are powers of 2 so its better to - to divide them getting a multiplication or division factor - for dfree. Rene Nieuwenhuizen (07-10-1997) */ - if (*bsize >= bsizeq) - *dfree = *dfree * (*bsize / bsizeq); - else - *dfree = *dfree / (bsizeq / *bsize); - *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; - *bsize = bsizeq; - *dsize = dsizeq; - } -#endif - return(dfree_retval); - } - -#ifdef NO_STATFS - DEBUG(1,("Warning - no statfs function\n")); - return(1); -#else -#ifdef STATFS4 - if (statfs(path,&fs,sizeof(fs),0) != 0) -#else -#ifdef USE_STATVFS - if (statvfs(path, &fs)) -#else -#ifdef STATFS3 - if (statfs(path,&fs,sizeof(fs)) == -1) -#else - if (statfs(path,&fs) == -1) -#endif /* STATFS3 */ -#endif /* USE_STATVFS */ -#endif /* STATFS4 */ - { - DEBUG(3,("dfree call failed code errno=%d\n",errno)); - *bsize = 1024; - *dfree = 1; - *dsize = 1; - return(((*bsize)/1024)*(*dfree)); - } - -#ifdef ULTRIX - *bsize = 1024; - *dfree = fs.fd_req.bfree; - *dsize = fs.fd_req.btot; -#else -#ifdef USE_STATVFS - *bsize = fs.f_frsize; -#else -#ifdef USE_F_FSIZE - /* eg: osf1 has f_fsize = fundamental filesystem block size, - f_bsize = optimal transfer block size (MX: 94-04-19) */ - *bsize = fs.f_fsize; -#else - *bsize = fs.f_bsize; -#endif /* STATFS3 */ -#endif /* USE_STATVFS */ - -#ifdef STATFS4 - *dfree = fs.f_bfree; -#else - *dfree = fs.f_bavail; -#endif /* STATFS4 */ - *dsize = fs.f_blocks; -#endif /* ULTRIX */ - -#if defined(SCO) || defined(ISC) || defined(MIPS) - *bsize = 512; -#endif - -/* handle rediculous bsize values - some OSes are broken */ -if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; - - disk_norm(bsize,dfree,dsize); - - if (*bsize < 256) - *bsize = 512; - if ((*dsize)<1) - { - DEBUG(0,("dfree seems to be broken on your system\n")); - *dsize = 20*1024*1024/(*bsize); - *dfree = MAX(1,*dfree); - } - dfree_retval = ((*bsize)/1024)*(*dfree); -#ifdef QUOTAS - /* Ensure we return the min value between the users quota and - what's free on the disk. Thanks to Albrecht Gebhardt - for this fix. - */ - if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq)) - { - disk_norm(&bsizeq, &dfreeq, &dsizeq); - dfreeq_retval = ((bsizeq)/1024)*(dfreeq); - dfree_retval = ( dfree_retval < dfreeq_retval ) ? - dfree_retval : dfreeq_retval ; - /* maybe dfree and dfreeq are calculated using different bsizes - so convert dfree from bsize into bsizeq */ - /* avoid overflows due to multiplication, so do not: - *dfree = ((*dfree) * (*bsize)) / (bsizeq); - bsize and bsizeq are powers of 2 so its better to - to divide them getting a multiplication or division factor - for dfree. Rene Nieuwenhuizen (07-10-1997) */ - if (*bsize >= bsizeq) - *dfree = *dfree * (*bsize / bsizeq); - else - *dfree = *dfree / (bsizeq / *bsize); - *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; - *bsize = bsizeq; - *dsize = dsizeq; - } -#endif - return(dfree_retval); -#endif -} - - -/**************************************************************************** -wrap it to get filenames right -****************************************************************************/ -int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize) -{ - return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize)); -} - - - /**************************************************************************** check a filename - possibly caling reducename @@ -1541,7 +1310,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct } -#if USE_MMAP +#if WITH_MMAP /* mmap it if read-only */ if (!fsp->can_write) { @@ -1563,9 +1332,9 @@ sync a file ********************************************************************/ void sync_file(int cnum, int fnum) { -#ifndef NO_FSYNC - if(lp_strict_sync(SNUM(cnum))) - fsync(Files[fnum].fd_ptr->fd); +#ifdef HAVE_FSYNC + if(lp_strict_sync(SNUM(cnum))) + fsync(Files[fnum].fd_ptr->fd); #endif } @@ -1627,7 +1396,7 @@ static void close_filestruct(files_struct *fs_p) fs_p->wbmpx_ptr = NULL; } -#if USE_MMAP +#if WITH_MMAP if(fs_p->mmap_ptr) { munmap(fs_p->mmap_ptr,fs_p->mmap_size); @@ -2303,7 +2072,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) } #endif -#if USE_MMAP +#if WITH_MMAP if (Files[fnum].mmap_ptr) { int num = (Files[fnum].mmap_size > pos) ? (Files[fnum].mmap_size - pos) : -1; @@ -2627,52 +2396,6 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int } -#ifndef SIGCLD_IGNORE -/**************************************************************************** -this prevents zombie child processes -****************************************************************************/ -static int sig_cld(void) -{ - static int depth = 0; - if (depth != 0) - { - DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n")); - depth=0; - return(0); - } - depth++; - - BlockSignals(True,SIGCLD); - DEBUG(5,("got SIGCLD\n")); - -#ifdef USE_WAITPID - while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0); -#endif - - /* Stop zombies */ - /* Stevens, Adv. Unix Prog. says that on system V you must call - wait before reinstalling the signal handler, because the kernel - calls the handler from within the signal-call when there is a - child that has exited. This would lead to an infinite recursion - if done vice versa. */ - -#ifndef DONT_REINSTALL_SIG -#ifdef SIGCLD_IGNORE - signal(SIGCLD, SIG_IGN); -#else - signal(SIGCLD, SIGNAL_CAST sig_cld); -#endif -#endif - -#ifndef USE_WAITPID - while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0); -#endif - depth--; - BlockSignals(False,SIGCLD); - return 0; -} -#endif - /**************************************************************************** this is called when the client exits abruptly **************************************************************************/ @@ -2684,9 +2407,6 @@ static int sig_pipe(void) if ((cli = server_client()) && cli->initialised) { DEBUG(3,("lost connection to password server\n")); cli_shutdown(cli); -#ifndef DONT_REINSTALL_SIG - signal(SIGPIPE, SIGNAL_CAST sig_pipe); -#endif BlockSignals(False,SIGPIPE); return 0; } @@ -2710,15 +2430,17 @@ static BOOL open_sockets(BOOL is_daemon,int port) int s; int i; - /* Stop zombies */ -#ifdef SIGCLD_IGNORE - signal(SIGCLD, SIG_IGN); -#else - signal(SIGCLD, SIGNAL_CAST sig_cld); +#ifdef HAVE_ATEXIT + static int atexit_set; + if(atexit_set == 0) { + atexit_set=1; + atexit(killkids); + } #endif - if(atexit_set == 0) - atexit(killkids); + /* Stop zombies */ + CatchChild(); + FD_ZERO(&listen_set); @@ -2825,21 +2547,12 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); continue; } -#ifdef NO_FORK_DEBUG -#ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); - signal(SIGCLD, SIGNAL_CAST SIG_DFL); -#endif /* NO_SIGNAL_TEST */ - return True; -#else /* NO_FORK_DEBUG */ if (Client != -1 && fork()==0) { /* Child code ... */ -#ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); - signal(SIGCLD, SIGNAL_CAST SIG_DFL); -#endif /* NO_SIGNAL_TEST */ + CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); + /* close the listening socket(s) */ for(i = 0; i < num_interfaces; i++) close(fd_listenset[i]); @@ -2860,20 +2573,19 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); } close(Client); /* The parent doesn't need this socket */ - /* - * Force parent to check log size after spawning child. - * Fix from klausr@ITAP.Physik.Uni-Stuttgart.De. - * The parent smbd will log to logserver.smb. - * It writes only two messages for each child - * started/finished. But each child writes, say, 50 messages also in - * logserver.smb, begining with the debug_count of the parent, before the - * child opens its own log file logserver.client. In a worst case - * scenario the size of logserver.smb would be checked after about - * 50*50=2500 messages (ca. 100kb). - */ - force_check_log_size(); - -#endif /* NO_FORK_DEBUG */ + /* + * Force parent to check log size after spawning child. + * Fix from klausr@ITAP.Physik.Uni-Stuttgart.De. + * The parent smbd will log to logserver.smb. + * It writes only two messages for each child + * started/finished. But each child writes, say, 50 messages also in + * logserver.smb, begining with the debug_count of the parent, before the + * child opens its own log file logserver.client. In a worst case + * scenario the size of logserver.smb would be checked after about + * 50*50=2500 messages (ca. 100kb). + */ + force_check_log_size(); + } /* end for num */ } /* end while 1 */ } /* end if is_daemon */ @@ -2882,9 +2594,7 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ -#ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); -#endif + CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); Client = dup(0); /* close our standard file descriptors */ @@ -2905,10 +2615,10 @@ max can be %d\n", num_interfaces, FD_SETSIZE)); static void process_smb(char *inbuf, char *outbuf) { extern int Client; -#ifdef USE_SSL +#ifdef WITH_SSL extern BOOL sslEnabled; /* don't use function for performance reasons */ static int sslConnected = 0; -#endif /* USE_SSL */ +#endif /* WITH_SSL */ static int trans_num; int msg_type = CVAL(inbuf,0); int32 len = smb_len(inbuf); @@ -2933,7 +2643,7 @@ static void process_smb(char *inbuf, char *outbuf) DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); -#ifdef USE_SSL +#ifdef WITH_SSL if(sslEnabled && !sslConnected){ sslConnected = sslutil_negotiate_ssl(Client, msg_type); if(sslConnected < 0){ /* an error occured */ @@ -2943,7 +2653,7 @@ static void process_smb(char *inbuf, char *outbuf) return; } } -#endif /* USE_SSL */ +#endif /* WITH_SSL */ #ifdef WITH_VTP if(trans_num == 1 && VT_Check(inbuf)) @@ -3641,9 +3351,6 @@ static int sig_hup(void) */ reload_after_sighup = True; -#ifndef DONT_REINSTALL_SIG - signal(SIGHUP,SIGNAL_CAST sig_hup); -#endif BlockSignals(False,SIGHUP); return(0); } @@ -3811,7 +3518,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de string_set(&pcon->dirpath,""); string_set(&pcon->user,user); -#if HAVE_GETGRNAM +#ifdef HAVE_GETGRNAM if (*lp_force_group(snum)) { struct group *gptr; @@ -4596,7 +4303,7 @@ static BOOL dump_core(void) if (chdir(dname)) return(False); umask(~(0700)); -#ifndef NO_GETRLIMIT +#ifdef HAVE_GETRLIMIT #ifdef RLIMIT_CORE { struct rlimit rlp; @@ -4631,7 +4338,7 @@ void exit_server(char *reason) for (i=0;i @@ -261,6 +261,6 @@ char *reqHosts, *resignHosts; return 1; } -#else /* USE_SSL */ +#else /* WITH_SSL */ void ssl_dummy(void) {;} /* So some compilers don't complain. */ -#endif /* USE_SSL */ +#endif /* WITH_SSL */ diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 2a75b660b5..a8e0bf0d03 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -36,26 +36,25 @@ initialise the uid routines ****************************************************************************/ void init_uid(void) { - initial_uid = current_user.uid = geteuid(); - initial_gid = current_user.gid = getegid(); + 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); + if (initial_gid != 0 && initial_uid == 0) { +#ifdef HAVE_SETRESUID + setresgid(0,0,0); #else - setgid(0); - setegid(0); + setgid(0); + setegid(0); #endif - } - - initial_uid = geteuid(); - initial_gid = getegid(); + } - current_user.cnum = -1; - current_user.vuid = UID_FIELD_INVALID; + initial_uid = geteuid(); + initial_gid = getegid(); - ChDir(OriginalDir); + current_user.cnum = -1; + current_user.vuid = UID_FIELD_INVALID; + + ChDir(OriginalDir); } @@ -64,141 +63,33 @@ void init_uid(void) ****************************************************************************/ static BOOL become_uid(int uid) { - if (initial_uid != 0) - return(True); - - if (uid == -1 || uid == 65535) { - DEBUG(1,("WARNING: using uid %d is a security risk\n",uid)); - } - -#ifdef AIX - { - /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */ - /* MWW: This is all undocumented, of course. There's a patch to WU-ftpd - in the AIX FAQ which does the setpriv, then sets the gid stuff, then - sets uid. Since Samba separates setting the gid and setting the uid, - I've duplicated the setpriv code in become_gid. I've also made the - requisite changes to become_gid to match the WU-ftpd patch. - - I believe we'll still get errors in the Samba logs. This setpriv - call is supposed to disable "trapdooring" on AIX - ie. normally - once a seteuid / setegid is done, the effective ID can't be set back - to what it was before. See the comments in become_root / unbecome_root. - I *think* that we may have to do something additional here to prevent - the "Can't set uid (AIX3)" messages, though - possibly change the - values of priv.pv_priv to keep the SET_PROC_DAC privilege, and - possibly SET_OBJ_DAC and SET_OBJ_STAT as well. - - The pv_priv array is two longwords, and the constants in sys/priv.h - have values between 1 and 64, according to the comments in priv.h. - This strongly suggests a bit vector - but does BYPASS_DAC_WRITE - (#define'd to 1) mean 1<<0 or 1<<1? Unfortunately, nothing's - defined to 0 or 64, which would be a dead giveaway. Also, what's the - fullword-boundary endianness? That is, is pv_priv[0] the high or - the low 32 bits? Fortunately, the values used by "su" (see below) - don't make much sense if pv_priv[0] is the high bits. Also, based - on analysis of the values used by su, I concluded that, for example, - BYPASS_DAC_READ (defined to 2) is bit "2" counting from 1 - ie. - if (pv_priv[0] & (1 << (BYPASS_DAC_READ - 1))) then BYPASS_DAC_READ - is on. That's a bit odd, but it makes more sense than if the - privilege constants are meant to be taken as exponents of 2. - - For analysis, I ran "su" as root under dbx, and stopped in setpriv. - The first argument to setpriv can be examined using - - print $r3 (eg. "0x30009" = PRIV_SET|PRIV_MAXIMUM|PRIV_EFFECTIV) - - the contents of the pv_priv array can be examined using - - ($r4)/2X - - Here's what su does: - - setpriv(PRIV_SET | PRIV_INHERITED | PRIV_BEQUEATH, {0,0}) - setpriv(PRIV_SET | PRIV_EFFECTIVE | PRIV_MAXIMUM, - {0x02800006, 0x00040000}) - 0x02800006 = SET_PROC_AUDIT | SET_PROC_ENV | - BYPASS_DAC_EXEC | BYPASS_DAC_READ - 0x00040000 = TPATH_CONFIG - setpriv(PRIV_SET | PRIV_EFFECTIVE, {0, 0}) - - Analysis: - - Reduce inherited privileges to none, so the child doesn't inherit - anything special. - Change su's privileges so it can execute the shell even if someone - has goofed up the permissions to it or to directories on the - search path; so it can set the process auditing characteristics - and privileged environment (stuff in /etc/security/environ with - the sysenv attribute); and so that it can set the trusted path - characteristics for this login. - Zap those privileges back off when we don't need them any more. - - I'm guessing we want to keep SET_PROC_DAC in the current priv set, - but not in the inherited one. That is, set PRIV_INHERITED and - PRIV_BEQUEATH to 0. We also probably want to set PRIV_MAXIMUM and - PRIV_EFFECTIVE to only the privs we need, which at this point would - appear to be just SET_PROC_DAC. *Note*: setting PRIV_MAXIMUM - with any of the privilege sets higher than what you're trying to - set the maximum to will produce an EINVAL. For example, if we - try to set PRIV_MAXIMUM to SET_PROC_DAC *before* we reduce - PRIV_INHERITED and PRIV_BEQUEATH, it won't work. Zero out the - inherited privileges first. - - Some experimentation with simple programs confirms that if we're - running with an EUID of 0 we can switch our UID/EUID back and - forth with setuidx - *unless* we call setpriv({0,0}, ...) first. - In other words, by default root has SET_PROC_DAT set, but we can - remove it from our privilege set. This is what we want to do for - child processes, I believe. - - Also, calling setpriv(PRIV_SUB|PRIV_EFFECTIVE,...) with pv_priv[0] - set to SET_PROC_DAC (1 << (SET_PROC_DAC - 1)) will prevent an - EUID-root process from switching its EUID back with setuidx. - - In other words, setuidx on AIX is *not* trapdoor. setuid is - trapdoor. We need a non-trapdoor setuid function, but we don't - want processes we fork to have access to it. Thus we use setuidx - but first we disable it for our children. - - Note, however, that we can only increase our privileges (as we - do in the first call to setpriv) if we're EUID-root. If we - started out as root, and then switched to a non-root user ID, - that's OK; we've already set them. Just don't try to set them - again. - - Also, I suspect that after using setpriv / setuidx / etc. here in - the AIX-specific code we DON'T want to fall through to the code that - calls setuid, etc. However, I haven't noticed any more problems with - the code the way it is here. - */ - - priv_t priv; - - priv.pv_priv[0] = 0; - priv.pv_priv[1] = 0; - if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_BEQUEATH, - &priv, sizeof(priv_t)) < 0) { - DEBUG(1, ("Can't set child privileges (AIX3): %s\n", strerror(errno))); - } - - priv.pv_priv[0] = (1 << (SET_PROC_DAC - 1)); - if (setpriv(PRIV_SET|PRIV_EFFECTIVE|PRIV_MAXIMUM, - &priv, sizeof(priv_t)) < 0) { - DEBUG(1, ("Can't set own privileges (AIX3): %s\n", strerror(errno))); - } + if (initial_uid != 0) { + return(True); + } + + if (uid == -1 || uid == 65535) { + static int done; + if (!done) { + DEBUG(1,("WARNING: using uid %d is a security risk\n", + uid)); + done=1; + } + } - if (setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 || - seteuid((uid_t)uid) < 0) { - DEBUG(1,("Can't set uid (AIX3)\n")); - } - } +#ifdef HAVE_TRAPDOOR_UID +#ifdef HAVE_SETUIDX + /* AIX3 has setuidx which is NOT a trapoor function (tridge) */ + if (setuidx(ID_EFFECTIVE, (uid_t)uid) != 0) { + if (seteuid((uid_t)uid) != 0) { + DEBUG(1,("Can't set uid (setuidx)\n")); + return False; + } + } +#endif #endif -#ifdef USE_SETRES - if (setresuid(-1,uid,-1) != 0) -#elif defined(USE_SETFS) - if (setfsuid(uid) != 0) +#ifdef HAVE_SETRESUID + if (setresuid(-1,uid,-1) != 0) #else if ((seteuid(uid) != 0) && (setuid(uid) != 0)) @@ -206,19 +97,20 @@ static BOOL become_uid(int uid) { 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")); + 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); - } + 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; + current_user.uid = uid; - return(True); + return(True); } @@ -234,36 +126,17 @@ static BOOL become_gid(int gid) DEBUG(1,("WARNING: using gid %d is a security risk\n",gid)); } -#ifdef AIX - { - /* MWW: See comment above in become_uid. */ - 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) { - DEBUG(1, ("Can't set privilege (AIX3)\n")); - } - if (setgidx(ID_REAL|ID_EFFECTIVE, (gid_t)gid) < 0 || - setegid((gid_t)gid) < 0) { - DEBUG(1,("Can't set gid (AIX3)\n")); - } - } -#endif - -#ifdef USE_SETRES +#ifdef HAVE_SETRESUID 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")); + if (gid > 32000) { + DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); + } return(False); } @@ -278,7 +151,7 @@ static BOOL become_gid(int gid) ****************************************************************************/ static BOOL become_id(int uid,int gid) { - return(become_gid(gid) && become_uid(uid)); + return(become_gid(gid) && become_uid(uid)); } /**************************************************************************** @@ -300,10 +173,12 @@ BOOL become_guest(void) /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before setting IDs */ initgroups(pass->pw_name, (gid_t)pass->pw_gid); #endif + ret = become_id(pass->pw_uid,pass->pw_gid); - if (!ret) + if (!ret) { DEBUG(1,("Failed to become guest. Invalid guest account?\n")); + } current_user.cnum = -2; current_user.vuid = UID_FIELD_INVALID; @@ -390,7 +265,7 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) { if (!become_gid(gid)) return(False); -#ifndef NO_SETGROUPS +#ifdef HAVE_SETGROUPS if (!(VALID_CNUM(cnum) && conn->ipc)) { /* groups stuff added by ih/wreu */ if (current_user.ngroups > 0) @@ -424,34 +299,30 @@ BOOL unbecome_user(void ) if (initial_uid == 0) { -#ifdef USE_SETRES +#ifdef HAVE_SETRESUID 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(); - } + 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; @@ -485,13 +356,13 @@ static BOOL setup_stdout_file(char *outfile,BOOL shared) close(1); if (shared) { - /* become root - unprivilaged users can't delete these files */ -#ifdef USE_SETRES - setresgid(0,0,0); - setresuid(0,0,0); + /* become root - unprivilaged users can't delete these files */ +#ifdef HAVE_SETRESUID + setresgid(0,0,0); + setresuid(0,0,0); #else - setuid(0); - seteuid(0); + setuid(0); + seteuid(0); #endif } @@ -534,7 +405,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared) int uid = current_user.uid; int gid = current_user.gid; -#if USE_SYSTEM +#ifndef HAVE_EXECL int ret; pstring syscmd; char *path = lp_smbrun(); @@ -583,7 +454,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared) /* 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 USE_SETRES +#ifdef HAVE_SETRESUID setresgid(0,0,0); setresuid(0,0,0); setresgid(gid,gid,gid); @@ -668,7 +539,7 @@ void unbecome_root(BOOL restore_dir) exit_server("Failed to restore gid"); } -#ifndef NO_SETGROUPS +#ifdef HAVE_SETGROUPS if (current_user_saved.ngroups > 0) { if (setgroups(current_user_saved.ngroups, current_user_saved.groups)<0) diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c index 19f8259464..6e95bac3c2 100644 --- a/source3/smbd/vt_mode.c +++ b/source3/smbd/vt_mode.c @@ -156,7 +156,7 @@ void VT_SigCLD(int sig) if(wait(NULL) == VT_ChildPID) VT_ChildDied = True; else - signal(SIGCLD, VT_SigCLD); + CatchSignal(SIGCLD, VT_SigCLD); } @@ -305,12 +305,12 @@ int VT_Start(void) VT_ChildDied = False; VT_Fd = master; - signal(SIGCLD, VT_SigCLD); + CatchSignal(SIGCLD, VT_SigCLD); - signal(SIGHUP, VT_SigEXIT); - signal(SIGTERM, VT_SigEXIT); - signal(SIGINT, VT_SigEXIT); - signal(SIGQUIT, VT_SigEXIT); + CatchSignal(SIGHUP, VT_SigEXIT); + CatchSignal(SIGTERM, VT_SigEXIT); + CatchSignal(SIGINT, VT_SigEXIT); + CatchSignal(SIGQUIT, VT_SigEXIT); memset(OutBuf, 0, sizeof(OutBuf)); OutBuf [4] = 0x06; -- cgit From fb08c34cf3950f994701a9c98c89670f6346f7ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Jul 1998 05:05:36 +0000 Subject: get rid of the runtime test for broken getgroups() and add a compile time test instead. This also allows us to get rid of the igroups element of a couple of structures. (This used to be commit 8b25fe734166b76ceebf8d9543c706ebe0fddc96) --- source3/smbd/password.c | 108 +++++++++++++++--------------------------------- source3/smbd/server.c | 12 ++---- source3/smbd/uid.c | 2 - 3 files changed, 37 insertions(+), 85 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index aae398dbda..0f8e33940f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -137,14 +137,11 @@ void invalidate_vuid(uint16 vuid) /* same number of igroups as groups */ vuser->n_groups = 0; - if (vuser->groups && (vuser->groups != (gid_t *)vuser->igroups)) - free(vuser->groups); + if (vuser->groups) free(vuser->groups); - if (vuser->igroups) free(vuser->igroups); - if (vuser->sids ) free(vuser->sids); + if (vuser->sids) free(vuser->sids); vuser->sids = NULL; - vuser->igroups = NULL; vuser->groups = NULL; } @@ -164,78 +161,41 @@ char *validated_username(uint16 vuid) /**************************************************************************** Setup the groups a user belongs to. ****************************************************************************/ -int setup_groups(char *user, int uid, int gid, int *p_ngroups, - int **p_igroups, gid_t **p_groups) +int setup_groups(char *user, int uid, int gid, int *p_ngroups, GID_T **p_groups) { - 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)); + int i,ngroups; + GID_T *groups; + GID_T grp = 0; + + 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; } - } - else - { - int i,ngroups; - int *igroups; - gid_t grp = 0; - ngroups = getgroups(0,&grp); - if (ngroups <= 0) - ngroups = 32; - igroups = (int *)malloc(sizeof(int)*ngroups); - for (i=0;i 0) - { - /* does getgroups return ints or gid_t ?? */ - static BOOL groups_use_ints = True; - if (groups_use_ints && - ngroups == 1 && - SVAL(igroups,2) == 0x4242) - groups_use_ints = False; - - for (i=0;groups_use_ints && in_groups = 0; vuser->groups = NULL; - vuser->igroups = NULL; /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(unix_name,uid,gid, &vuser->n_groups, - &vuser->igroups, &vuser->groups); DEBUG(3,("uid %d registered to name %s\n",uid,unix_name)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3469e45732..8eee0209b6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -206,7 +206,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) || ((sbuf->st_mode & S_IWGRP) && in_group(sbuf->st_gid,current_user.gid, - current_user.ngroups,current_user.igroups)))) + current_user.ngroups,current_user.groups)))) result |= aRONLY; } else { if ((sbuf->st_mode & S_IWUSR) == 0) @@ -356,7 +356,7 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || ((sb.st_mode & S_IWGRP) && in_group(sb.st_gid,current_user.gid, - current_user.ngroups,current_user.igroups)))) { + current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(False); ret = sys_utime(fname, times); @@ -3567,14 +3567,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de /* groups stuff added by ih */ pcon->ngroups = 0; - pcon->igroups = NULL; pcon->groups = NULL; if (!IS_IPC(cnum)) { /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(pcon->user,pcon->uid,pcon->gid, - &pcon->ngroups,&pcon->igroups,&pcon->groups); + &pcon->ngroups,&pcon->groups); /* check number of connections */ if (!claim_connection(cnum, @@ -4267,11 +4266,8 @@ void close_cnum(int cnum, uint16 vuid) num_connections_open--; if (Connections[cnum].ngroups && Connections[cnum].groups) { - if (Connections[cnum].igroups != (int *)Connections[cnum].groups) - free(Connections[cnum].groups); - free(Connections[cnum].igroups); + free(Connections[cnum].groups); Connections[cnum].groups = NULL; - Connections[cnum].igroups = NULL; Connections[cnum].ngroups = 0; } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index a8e0bf0d03..173fdaca03 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -242,7 +242,6 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) uid = conn->uid; gid = conn->gid; current_user.groups = conn->groups; - current_user.igroups = conn->igroups; current_user.ngroups = conn->ngroups; } else @@ -258,7 +257,6 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) gid = conn->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; - current_user.igroups = vuser->igroups; } if (initial_uid == 0) -- cgit From 7284bb5ca049a682097bb25afcf25d40f1ac5479 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Jul 1998 21:18:57 +0000 Subject: Makefile.in: Moved UBIQX stuff into UTILOBJ. loadparm.c: Added "ole locking compatibility" option (default "true"). locking.c: Changes to implement union in files_struct. locking_shm.c: Changes to implement union in files_struct. nttrans.c: Made opening a directory explicit (we have to). Added create directory code for nttrans. reply.c: Changes to implement union in files_struct. server.c: Changes to implement union in files_struct. Added create directory code. trans2.c: Changes to implement union in files_struct. smb.h: Changes to implement union in files_struct. util.c: Changed linked list code to UNIQX linked list. This will make the other lists I need to implement for ChangeNotify and blocking locks easier. Jeremy. (This used to be commit 3a5eea850bb256b39cff8ace1e4fb4e0c1f5472b) --- source3/smbd/nttrans.c | 220 ++++++++++++++++++++++++++++++------------------- source3/smbd/reply.c | 140 +++++++++++++++++-------------- source3/smbd/server.c | 169 +++++++++++++++++++++++-------------- source3/smbd/trans2.c | 20 +++-- 4 files changed, 332 insertions(+), 217 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9b6cfe1621..4e857c183c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -424,10 +424,6 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) files_struct *fsp; char *p = NULL; - /* If it's a request for a directory open, fail it. */ - if(flags & OPEN_DIRECTORY) - return(ERROR(ERRDOS,ERRnoaccess)); - /* * We need to construct the open_and_X ofun value from the * NT values, as that's what our code is structured to accept. @@ -459,7 +455,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { /* - * Ordinary file. + * Ordinary file or directory. */ /* @@ -495,66 +491,95 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - /* - * NB. We have a potential bug here. If we cause an oplock - * break to ourselves, then we could end up processing filename - * related SMB requests whilst we await the oplock break - * response. As we may have changed the filename case - * semantics to be POSIX-like, this could mean a filename - * request could fail when it should succeed. This is a - * rare condition, but eventually we must arrange to restore - * the correct case semantics before issuing an oplock break - * request to our client. JRA. + /* + * If it's a request for a directory open, deal with it separately. */ - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + if(flags & OPEN_DIRECTORY) { + oplock_request = 0; - restore_case_semantics(file_attributes); + open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); + + restore_case_semantics(file_attributes); + + if(!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + + /* + * Ordinary file case. + */ - if (!fsp->open) { /* - * We cheat here. The only case we care about is a directory - * rename, where the NT client will attempt to open the source - * directory for DELETE access. Note that when the NT client - * does this it does *not* set the directory bit in the - * request packet. This is translated into a read/write open - * request. POSIX states that any open for write request on a directory - * will generate an EISDIR error, so we can catch this here and open - * a pseudo handle that is flagged as a directory. JRA. + * NB. We have a potential bug here. If we cause an oplock + * break to ourselves, then we could end up processing filename + * related SMB requests whilst we await the oplock break + * response. As we may have changed the filename case + * semantics to be POSIX-like, this could mean a filename + * request could fail when it should succeed. This is a + * rare condition, but eventually we must arrange to restore + * the correct case semantics before issuing an oplock break + * request to our client. JRA. */ - if(errno == EISDIR) { - oplock_request = 0; - open_directory(fnum, cnum, fname, &smb_action); + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); + + if (!fsp->open) { + /* + * We cheat here. The only case we care about is a directory + * rename, where the NT client will attempt to open the source + * directory for DELETE access. Note that when the NT client + * does this it does *not* set the directory bit in the + * request packet. This is translated into a read/write open + * request. POSIX states that any open for write request on a directory + * will generate an EISDIR error, so we can catch this here and open + * a pseudo handle that is flagged as a directory. JRA. + */ + + if(errno == EISDIR) { + oplock_request = 0; + + open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); + + if(!fsp->open) { + fsp->reserved = False; + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } - if(!fsp->open) { fsp->reserved = False; + + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - } else { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - - fsp->reserved = False; - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } + } + } if(fsp->is_directory) { - if(stat(fsp->name, &sbuf) != 0) { + if(sys_stat(fsp->name, &sbuf) != 0) { close_directory(fnum); + restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); + restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } + restore_case_semantics(file_attributes); + file_len = sbuf.st_size; fmode = dos_mode(cnum,fname,&sbuf); if(fmode == 0) @@ -668,10 +693,6 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, files_struct *fsp; char *p = NULL; - /* If it's a request for a directory open, fail it. */ - if(flags & OPEN_DIRECTORY) - return(ERROR(ERRDOS,ERRnoaccess)); - /* * We need to construct the open_and_X ofun value from the * NT values, as that's what our code is structured to accept. @@ -733,56 +754,85 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + /* + * If it's a request for a directory open, deal with it separately. + */ - fsp = &Files[fnum]; - - if (!fsp->open) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; + if(flags & OPEN_DIRECTORY) { + + oplock_request = 0; + + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ + + open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); + + if(!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - Files[fnum].reserved = False; + } else { - restore_case_semantics(file_attributes); + /* + * Ordinary file case. + */ - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); - restore_case_semantics(file_attributes); + fsp = &Files[fnum]; + + if (!fsp->open) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; - return(ERROR(ERRDOS,ERRnoaccess)); - } + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - restore_case_semantics(file_attributes); + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); - file_len = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - if(fmode == 0) - fmode = FILE_ATTRIBUTE_NORMAL; - mtime = sbuf.st_mtime; - if (fmode & aDIR) { - close_file(fnum,False); - return(ERROR(ERRDOS,ERRnoaccess)); - } + restore_case_semantics(file_attributes); + + return(ERROR(ERRDOS,ERRnoaccess)); + } - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ + file_len = sbuf.st_size; + fmode = dos_mode(cnum,fname,&sbuf); + if(fmode == 0) + fmode = FILE_ATTRIBUTE_NORMAL; + mtime = sbuf.st_mtime; + + if (fmode & aDIR) { + close_file(fnum,False); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) - smb_action |= EXTENDED_OPLOCK_GRANTED; + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) + smb_action |= EXTENDED_OPLOCK_GRANTED; - if(oplock_request && fsp->granted_oplock) - smb_action |= EXTENDED_OPLOCK_GRANTED; + if(oplock_request && fsp->granted_oplock) + smb_action |= EXTENDED_OPLOCK_GRANTED; + } } + restore_case_semantics(file_attributes); + /* Realloc the size of parameters and data we will return */ params = *ppparams = Realloc(*ppparams, 69); if(params == NULL) @@ -972,7 +1022,7 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(2,("%s: reply_nttrans: queueing message NT_TRANSACT_CREATE \ due to being in oplock break state.\n", timestring() )); - push_smb_message( inbuf, length); + push_oplock_pending_smb_message( inbuf, length); return -1; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f05ba2eee6..2845d5650a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1287,6 +1287,8 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1294,7 +1296,7 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1303,8 +1305,6 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname,share_mode,3,unixmode, oplock_request,&rmode,NULL); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1312,11 +1312,11 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1392,6 +1392,8 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1399,7 +1401,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1408,8 +1410,6 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1417,11 +1417,11 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1548,6 +1548,8 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1555,7 +1557,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1574,8 +1576,6 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, oplock_request, NULL, NULL); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1583,7 +1583,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1598,7 +1598,8 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG(2,("new file %s\n",fname)); - DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); + DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", + timestring(),fname,fsp->f_u.fd_ptr->fd,fnum,cnum,createmode,unixmode)); return(outsize); } @@ -1632,6 +1633,8 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1639,7 +1642,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1650,8 +1653,6 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, oplock_request, NULL, NULL); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1659,7 +1660,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1676,7 +1677,8 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG(2,("created temp file %s\n",fname2)); - DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); + DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", + timestring(),fname2,fsp->f_u.fd_ptr->fd,fnum,cnum,createmode,unixmode)); return(outsize); } @@ -1821,6 +1823,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) int ret=0; int fd; char *fname; + files_struct *fsp; /* * Special check if an oplock break has been issued @@ -1848,35 +1851,37 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) maxcount = MAX(mincount,maxcount); if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read) - { - DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); - _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); - return(-1); - } + { + DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); + _smb_setlen(header,0); + transfer_file(0,Client,0,header,4,0); + return(-1); + } else - { - fd = Files[fnum].fd_ptr->fd; - fname = Files[fnum].name; - } + { + fsp = &Files[fnum]; + + fd = fsp->f_u.fd_ptr->fd; + fname = fsp->name; + } if (!is_locked(fnum,cnum,maxcount,startpos, F_RDLCK)) - { - int size = Files[fnum].size; - int sizeneeded = startpos + maxcount; + { + int size = fsp->size; + int sizeneeded = startpos + maxcount; - if (size < sizeneeded) { - struct stat st; - if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) - size = st.st_size; - if (!Files[fnum].can_write) - Files[fnum].size = size; - } - - nread = MIN(maxcount,(int)(size - startpos)); + if (size < sizeneeded) { + struct stat st; + if (fstat(fsp->f_u.fd_ptr->fd,&st) == 0) + size = st.st_size; + if (!fsp->can_write) + fsp->size = size; } + nread = MIN(maxcount,(int)(size - startpos)); + } + if (nread < mincount) nread = 0; @@ -1891,7 +1896,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) _smb_setlen(header,nread); #if USE_READ_PREDICTION - if (!Files[fnum].can_write) + if (!fsp->can_write) predict = read_predict(fd,startpos,header+4,NULL,nread); #endif @@ -2138,7 +2143,7 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) tcount,nwritten,numtowrite)); } - nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0, + nwritten = transfer_file(Client,Files[fnum].f_u.fd_ptr->fd,numtowrite,NULL,0, startpos+nwritten); total_written += nwritten; @@ -2255,7 +2260,7 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) - nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos); + nwritten = set_filelen(Files[fnum].f_u.fd_ptr->fd, startpos); else nwritten = write_file(fnum,data,numtowrite); @@ -2349,7 +2354,8 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int32 res= -1; int mode,umode; int outsize = 0; - + files_struct *fsp; + cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); @@ -2367,9 +2373,11 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) default: umode = SEEK_SET; break; } + + fsp = &Files[fnum]; - res = lseek(Files[fnum].fd_ptr->fd,startpos,umode); - Files[fnum].pos = res; + res = lseek(fsp->f_u.fd_ptr->fd,startpos,umode); + fsp->pos = res; outsize = set_message(outbuf,2,0,True); SIVALS(outbuf,smb_vwv0,res); @@ -2477,7 +2485,7 @@ int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) set_filetime(cnum, fsp->name,mtime); DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - timestring(),fsp->fd_ptr->fd,fnum,cnum, + timestring(),fsp->f_u.fd_ptr->fd,fnum,cnum, Connections[cnum].num_files_open)); close_file(fnum,True); @@ -2560,7 +2568,8 @@ int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); - DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); + DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", + timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum,offset,count)); if(!do_lock( fnum, cnum, count, offset, F_WRLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); @@ -2592,7 +2601,8 @@ int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); - DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); + DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", + timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum,offset,count)); return(outsize); } @@ -2686,6 +2696,7 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int cnum; int fnum = -1; int outsize = 0; + files_struct *fsp; *fname = *fname2 = 0; @@ -2715,10 +2726,12 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + pstrcpy(fname2,(char *)mktemp(fname)); if (!check_name(fname2,cnum)) { - Files[fnum].reserved = False; + fsp->reserved = False; return(ERROR(ERRDOS,ERRnoaccess)); } @@ -2726,18 +2739,19 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), 0, NULL, NULL); - if (!Files[fnum].open) { - Files[fnum].reserved = False; + if (!fsp->open) { + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } /* force it to be a print file */ - Files[fnum].print_file = True; + fsp->print_file = True; outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); - DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum)); + DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n", + timestring(),fname2,fsp->f_u.fd_ptr->fd,fnum,cnum)); return(outsize); } @@ -2760,7 +2774,8 @@ int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); + DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n", + timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum)); close_file(fnum,True); @@ -3453,11 +3468,12 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, } if ((ofun&3) == 1) { - lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END); + lseek(Files[fnum2].f_u.fd_ptr->fd,0,SEEK_END); } if (st.st_size) - ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); + ret = transfer_file(Files[fnum1].f_u.fd_ptr->fd, + Files[fnum2].f_u.fd_ptr->fd,st.st_size,NULL,0,0); close_file(fnum1,False); close_file(fnum2,False); @@ -3675,8 +3691,8 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) { int token; files_struct *fsp = &Files[fnum]; - uint32 dev = fsp->fd_ptr->dev; - uint32 inode = fsp->fd_ptr->inode; + uint32 dev = fsp->f_u.fd_ptr->dev; + uint32 inode = fsp->f_u.fd_ptr->inode; DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", fnum)); @@ -4077,7 +4093,7 @@ int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CHECK_ERROR(fnum); /* Do an fstat on this file */ - if(fstat(Files[fnum].fd_ptr->fd, &sbuf)) + if(fstat(Files[fnum].f_u.fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(cnum,Files[fnum].name,&sbuf); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8eee0209b6..056611a886 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1047,7 +1047,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); fsp->open = False; - fsp->fd_ptr = 0; + fsp->f_u.fd_ptr = 0; fsp->granted_oplock = False; errno = EPERM; @@ -1222,7 +1222,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(cnum))) { fd_attempt_close(fd_ptr); - fsp->fd_ptr = 0; + fsp->f_u.fd_ptr = 0; if(fd_ptr->ref_count == 0) sys_unlink(fname); errno = ENOSPC; @@ -1259,7 +1259,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fd_ptr->dev = (uint32)sbuf->st_dev; fd_ptr->inode = (uint32)sbuf->st_ino; - fsp->fd_ptr = fd_ptr; + fsp->f_u.fd_ptr = fd_ptr; Connections[cnum].num_files_open++; fsp->mode = sbuf->st_mode; GetTimeOfDay(&fsp->open_time); @@ -1316,7 +1316,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct { fsp->mmap_size = file_size(fname); fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + PROT_READ,MAP_SHARED,fsp->f_u.fd_ptr->fd,0); if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { @@ -1334,7 +1334,7 @@ void sync_file(int cnum, int fnum) { #ifdef HAVE_FSYNC if(lp_strict_sync(SNUM(cnum))) - fsync(Files[fnum].fd_ptr->fd); + fsync(Files[fnum].f_u.fd_ptr->fd); #endif } @@ -1381,26 +1381,26 @@ static void check_magic(int fnum,int cnum) Common code to close a file or a directory. ****************************************************************************/ -static void close_filestruct(files_struct *fs_p) +static void close_filestruct(files_struct *fsp) { - int cnum = fs_p->cnum; + int cnum = fsp->cnum; - fs_p->reserved = False; - fs_p->open = False; - fs_p->is_directory = False; + fsp->reserved = False; + fsp->open = False; + fsp->is_directory = False; Connections[cnum].num_files_open--; - if(fs_p->wbmpx_ptr) + if(fsp->wbmpx_ptr) { - free((char *)fs_p->wbmpx_ptr); - fs_p->wbmpx_ptr = NULL; + free((char *)fsp->wbmpx_ptr); + fsp->wbmpx_ptr = NULL; } #if WITH_MMAP - if(fs_p->mmap_ptr) + if(fsp->mmap_ptr) { - munmap(fs_p->mmap_ptr,fs_p->mmap_size); - fs_p->mmap_ptr = NULL; + munmap(fsp->mmap_ptr,fsp->mmap_size); + fsp->mmap_ptr = NULL; } #endif } @@ -1418,14 +1418,14 @@ void close_file(int fnum, BOOL normal_close) { files_struct *fs_p = &Files[fnum]; int cnum = fs_p->cnum; - uint32 dev = fs_p->fd_ptr->dev; - uint32 inode = fs_p->fd_ptr->inode; + uint32 dev = fs_p->f_u.fd_ptr->dev; + uint32 inode = fs_p->f_u.fd_ptr->inode; int token; close_filestruct(fs_p); #if USE_READ_PREDICTION - invalidate_read_prediction(fs_p->fd_ptr->fd); + invalidate_read_prediction(fs_p->f_u.fd_ptr->fd); #endif if (lp_share_modes(SNUM(cnum))) @@ -1434,7 +1434,7 @@ void close_file(int fnum, BOOL normal_close) del_share_mode(token, fnum); } - fd_attempt_close(fs_p->fd_ptr); + fd_attempt_close(fs_p->f_u.fd_ptr); if (lp_share_modes(SNUM(cnum))) unlock_share_entry( cnum, dev, inode, token); @@ -1470,31 +1470,74 @@ void close_file(int fnum, BOOL normal_close) void close_directory(int fnum) { - files_struct *fs_p = &Files[fnum]; + files_struct *fsp = &Files[fnum]; + + /* TODO - walk the list of pending + change notify requests and free + any pertaining to this fnum. */ /* * Do the code common to files and directories. */ - close_filestruct(fs_p); + close_filestruct(fsp); - if (fs_p->name) { - string_free(&fs_p->name); - } + if (fsp->name) + string_free(&fsp->name); + + if (fsp->f_u.dir_ptr) + free((char *)fsp->f_u.dir_ptr); /* we will catch bugs faster by zeroing this structure */ - memset(fs_p, 0, sizeof(*fs_p)); + memset(fsp, 0, sizeof(*fsp)); } /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ -void open_directory(int fnum,int cnum,char *fname, int *action) +int open_directory(int fnum,int cnum,char *fname, int smb_ofun, int unixmode, int *action) { extern struct current_user current_user; files_struct *fsp = &Files[fnum]; + struct stat st; + + if (smb_ofun & 0x10) { + /* + * Create the directory. + */ + + if(sys_mkdir(fname, unixmode) < 0) { + DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + *action = FILE_WAS_CREATED; + + } else { + + /* + * Check that it *was* a directory. + */ + + if(sys_stat(fname, &st) < 0) { + DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + if(!S_ISDIR(st.st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + return -1; + } + *action = FILE_WAS_OPENED; + } - fsp->fd_ptr = NULL; + /* + * Setup the files_struct for it. + */ + + fsp->f_u.dir_ptr = NULL; Connections[cnum].num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); @@ -1524,7 +1567,7 @@ void open_directory(int fnum,int cnum,char *fname, int *action) string_set(&fsp->name,fname); fsp->wbmpx_ptr = NULL; - *action = FILE_WAS_OPENED; + return 0; } enum {AFAIL,AREAD,AWRITE,AALL}; @@ -1719,8 +1762,8 @@ static void truncate_unless_locked(int fnum, int cnum, int token, /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, - Files[fnum].fd_ptr->inode, token); + unlock_share_entry( cnum, Files[fnum].f_u.fd_ptr->dev, + Files[fnum].f_u.fd_ptr->inode, token); close_file(fnum,False); /* Share mode no longer locked. */ *share_locked = False; @@ -1729,7 +1772,7 @@ static void truncate_unless_locked(int fnum, int cnum, int token, unix_ERR_code = ERRlock; } else - ftruncate(Files[fnum].fd_ptr->fd,0); + ftruncate(Files[fnum].f_u.fd_ptr->fd,0); } } @@ -1794,7 +1837,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int num_share_modes = 0; fs_p->open = False; - fs_p->fd_ptr = 0; + fs_p->f_u.fd_ptr = 0; /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) @@ -1970,8 +2013,8 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if((share_locked == False) && lp_share_modes(SNUM(cnum))) { /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; + dev = fs_p->f_u.fd_ptr->dev; + inode = fs_p->f_u.fd_ptr->inode; lock_share_entry(cnum, dev, inode, &token); share_locked = True; } @@ -2046,12 +2089,13 @@ seek a file. Try to avoid the seek if possible int seek_file(int fnum,uint32 pos) { uint32 offset = 0; - if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum)) + files_struct *fsp = &Files[fnum]; + + if (fsp->print_file && POSTSCRIPT(fsp->cnum)) offset = 3; - Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - - offset); - return(Files[fnum].pos); + fsp->pos = (int)(lseek(fsp->f_u.fd_ptr->fd,pos+offset,SEEK_SET) - offset); + return(fsp->pos); } /**************************************************************************** @@ -2060,11 +2104,12 @@ read from a file int read_file(int fnum,char *data,uint32 pos,int n) { int ret=0,readret; + files_struct *fsp = &Files[fnum]; #if USE_READ_PREDICTION - if (!Files[fnum].can_write) + if (!fsp->can_write) { - ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n); + ret = read_predict(fsp->f_u.fd_ptr->fd,pos,data,NULL,n); data += ret; n -= ret; @@ -2073,13 +2118,13 @@ int read_file(int fnum,char *data,uint32 pos,int n) #endif #if WITH_MMAP - if (Files[fnum].mmap_ptr) + if (fsp->mmap_ptr) { - int num = (Files[fnum].mmap_size > pos) ? (Files[fnum].mmap_size - pos) : -1; + int num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; num = MIN(n,num); if (num > 0) { - memcpy(data,Files[fnum].mmap_ptr+pos,num); + memcpy(data,fsp->mmap_ptr+pos,num); data += num; pos += num; n -= num; @@ -2098,7 +2143,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) } if (n > 0) { - readret = read(Files[fnum].fd_ptr->fd,data,n); + readret = read(fsp->f_u.fd_ptr->fd,data,n); if (readret > 0) ret += readret; } @@ -2111,23 +2156,25 @@ write to a file ****************************************************************************/ int write_file(int fnum,char *data,int n) { - if (!Files[fnum].can_write) { + files_struct *fsp = &Files[fnum]; + + if (!fsp->can_write) { errno = EPERM; return(0); } - if (!Files[fnum].modified) { + if (!fsp->modified) { struct stat st; - Files[fnum].modified = True; - if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) { - int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st); - if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) { - dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st); + fsp->modified = True; + if (fstat(fsp->f_u.fd_ptr->fd,&st) == 0) { + int dosmode = dos_mode(fsp->cnum,fsp->name,&st); + if (MAP_ARCHIVE(fsp->cnum) && !IS_DOS_ARCHIVE(dosmode)) { + dos_chmod(fsp->cnum,fsp->name,dosmode | aARCH,&st); } } } - return(write_data(Files[fnum].fd_ptr->fd,data,n)); + return(write_data(fsp->f_u.fd_ptr->fd,data,n)); } @@ -2871,7 +2918,7 @@ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); { if(OPEN_FNUM(fnum)) { - if((Files[fnum].fd_ptr->dev == dev) && (Files[fnum].fd_ptr->inode == inode) && + if((Files[fnum].f_u.fd_ptr->dev == dev) && (Files[fnum].f_u.fd_ptr->inode == inode) && (Files[fnum].open_time.tv_sec == tval->tv_sec) && (Files[fnum].open_time.tv_usec == tval->tv_usec)) { fsp = &Files[fnum]; @@ -3687,17 +3734,17 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de file table when we have run out. ****************************************************************************/ -static BOOL attempt_close_oplocked_file(files_struct *fp) +static BOOL attempt_close_oplocked_file(files_struct *fsp) { - DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fp->name)); + DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->name)); - if (fp->open && fp->granted_oplock && !fp->sent_oplock_break) { + if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) { /* Try and break the oplock. */ - file_fd_struct *fsp = fp->fd_ptr; - if(oplock_break( fsp->dev, fsp->inode, &fp->open_time)) { - if(!fp->open) /* Did the oplock break close the file ? */ + file_fd_struct *fd_ptr = fsp->f_u.fd_ptr; + if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time)) { + if(!fsp->open) /* Did the oplock break close the file ? */ return True; } } @@ -4601,7 +4648,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize DEBUG(2,("%s: switch_message: queueing message due to being in oplock break state.\n", timestring() )); - push_smb_message( inbuf, size); + push_oplock_pending_smb_message( inbuf, size); return -1; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2fcab32afb..08f6803005 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -207,6 +207,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, struct stat sbuf; int smb_action = 0; BOOL bad_path = False; + files_struct *fsp; StrnCpy(fname,pname,namelen); @@ -221,6 +222,8 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -228,28 +231,27 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } unixmode = unix_mode(cnum,open_attr | aARCH); - open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); - if (!Files[fnum].open) + if (!fsp->open) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1187,11 +1189,11 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + if (fstat(Files[fnum].f_u.fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR); + pos = lseek(Files[fnum].f_u.fd_ptr->fd,0,SEEK_CUR); } else { /* qpathinfo */ info_level = SVAL(params,0); @@ -1411,7 +1413,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - fd = Files[fnum].fd_ptr->fd; + fd = Files[fnum].f_u.fd_ptr->fd; if(fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); @@ -1788,7 +1790,7 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(2,("%s: reply_trans2: queueing message trans2open due to being in oplock break state.\n", timestring() )); - push_smb_message( inbuf, length); + push_oplock_pending_smb_message( inbuf, length); return -1; } -- cgit From 28900ea26ff1c8d41328bba30206db7fe91e2184 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Fri, 31 Jul 1998 22:39:15 +0000 Subject: As per a Andrew's message, I went through and removed the timestring() timestamps from several DEBUG messages. The timestamps are redundant now that DEBUG() provides them automatically. There are still a few more files to do, but I've got to get home for dinner. Chris -)----- (This used to be commit 60286ccecaa6028d687e6406755016455e3b3a26) --- source3/smbd/message.c | 8 +- source3/smbd/nttrans.c | 8 +- source3/smbd/pipes.c | 5 +- source3/smbd/reply.c | 218 ++++++++++++++++++++++---------------------- source3/smbd/server.c | 239 ++++++++++++++++++++++++++++--------------------- source3/smbd/ssl.c | 7 +- source3/smbd/trans2.c | 27 +++--- source3/smbd/uid.c | 3 +- source3/smbd/vt_mode.c | 2 +- 9 files changed, 280 insertions(+), 237 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index b368c4d031..44ae272bdd 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -117,7 +117,7 @@ int reply_sends(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) memcpy(&msgbuf[msgpos],msg+2,len); msgpos += len; - DEBUG(3,("%s SMBsends (from %s to %s)\n",timestring(),orig,dest)); + DEBUG( 3, ( "SMBsends (from %s to %s)\n", orig, dest ) ); msg_deliver(); @@ -146,7 +146,7 @@ int reply_sendstrt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) fstrcpy(msgfrom,orig); fstrcpy(msgto,dest); - DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),msgfrom,msgto)); + DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); return(outsize); } @@ -174,7 +174,7 @@ int reply_sendtxt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) memcpy(&msgbuf[msgpos],msg+2,len); msgpos += len; - DEBUG(3,("%s SMBsendtxt\n",timestring())); + DEBUG( 3, ( "SMBsendtxt\n" ) ); return(outsize); } @@ -192,7 +192,7 @@ int reply_sendend(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,0,0,True); - DEBUG(3,("%s SMBsendend\n",timestring())); + DEBUG( 3, ( "%s SMBsendend\n" ) ); msg_deliver(); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4e857c183c..d845076f36 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1019,8 +1019,8 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) * Queue this open message as we are the process of an oplock break. */ - DEBUG(2,("%s: reply_nttrans: queueing message NT_TRANSACT_CREATE \ -due to being in oplock break state.\n", timestring() )); + DEBUG( 2, ( "reply_nttrans: queueing message NT_TRANSACT_CREATE " ) ); + DEBUGADD( 2, ( "due to being in oplock break state.\n" ) ); push_oplock_pending_smb_message( inbuf, length); return -1; @@ -1145,8 +1145,8 @@ due to being in oplock break state.\n", timestring() )); break; default: /* Error in request */ - DEBUG(0,("reply_nttrans: %s Unknown request %d in nttrans call\n",timestring(), - function_code)); + DEBUG( 0, ( "reply_nttrans: Unknown request %d in nttrans call\n", + function_code ) ); if(setup) free(setup); if(params) diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index f0c5c3ba7f..34884aa6d3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -161,9 +161,8 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - DEBUG(3,("%s readX pnum=%04x cnum=%d min=%d max=%d nread=%d\n", - timestring(),pnum,cnum, - smb_mincnt,smb_maxcnt,nread)); + DEBUG( 3, ( "readX pnum=%04x cnum=%d min=%d max=%d nread=%d\n", + pnum, cnum, smb_mincnt, smb_maxcnt, nread ) ); set_chain_pnum(pnum); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2845d5650a..71544c1b19 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -55,9 +55,13 @@ report a possible attack via the password buffer overflow bug ****************************************************************************/ static void overflow_attack(int len) { - DEBUG(0,("%s: ERROR: Invalid password length %d\n", timestring(), len)); - DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); - DEBUG(0,("Attack was from IP=%s\n", client_addr(Client))); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "ERROR: Invalid password length %d.\n", len ); + dbgtext( "Your machine may be under attack by someone " ); + dbgtext( "attempting to exploit an old bug.\n" ); + dbgtext( "Attack was from IP = %s.\n", client_addr(Client) ); + } exit_server("possible attack"); } @@ -143,8 +147,8 @@ int reply_special(char *inbuf,char *outbuf) return(0); } - DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n", - timestring(),msg_type,msg_flags)); + DEBUG( 5, ( "init msg_type=0x%x msg_flags=0x%x\n", + msg_type, msg_flags ) ); return(outsize); } @@ -254,7 +258,7 @@ int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_vwv1,connection_num); SSVAL(outbuf,smb_tid,connection_num); - DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); + DEBUG(3,("tcon service=%s user=%s cnum=%d\n", service, user, connection_num)); return(outsize); } @@ -350,7 +354,8 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */ } - DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); + DEBUG( 3, ( "tconX service=%s user=%s cnum=%d\n", + service, user, connection_num ) ); /* set the incoming and outgoing tid to the just created one */ SSVAL(inbuf,smb_tid,connection_num); @@ -370,10 +375,8 @@ int reply_unknown(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); type = CVAL(inbuf,smb_com); - DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n", - timestring(), - smb_fn_name(type), - cnum,type,type)); + DEBUG(0,("unknown command type (%s): cnum=%d type=%d (0x%X)\n", + smb_fn_name(type), cnum, type, type)); return(ERROR(ERRSRV,ERRunknownsmb)); } @@ -807,11 +810,11 @@ int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) return(UNIXERROR(ERRDOS,ERRbadpath)); } - + outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode)); - + + DEBUG( 3, ( "chkpth %s cnum=%d mode=%d\n", name, cnum, mode ) ); + return(outsize); } @@ -890,7 +893,7 @@ int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ } - DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size)); + DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, size ) ); return(outsize); } @@ -937,7 +940,7 @@ int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,0,0,True); - DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode)); + DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); return(outsize); } @@ -962,9 +965,9 @@ int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_vwv1,bsize/512); SSVAL(outbuf,smb_vwv2,512); SSVAL(outbuf,smb_vwv3,dfree); - - DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree)); - + + DEBUG( 3, ( "dskattr cnum=%d dfree=%d\n", cnum, dfree ) ); + return(outsize); } @@ -1210,10 +1213,9 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if ((! *directory) && dptr_path(dptr_num)) slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n", - timestring(), + DEBUG( 4, ( "%s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n", smb_fn_name(CVAL(inbuf,smb_com)), - mask,directory,cnum,dirtype,numentries,maxentries)); + mask, directory, cnum, dirtype, numentries, maxentries ) ); return(outsize); } @@ -1250,7 +1252,7 @@ int reply_fclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_vwv0,0); - DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum)); + DEBUG( 3, ( "%s search close cnum=%d\n", cnum ) ); return(outsize); } @@ -1508,7 +1510,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,2,0,True); - DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid)); + DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1597,10 +1599,10 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(fsp->granted_oplock) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - DEBUG(2,("new file %s\n",fname)); - DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", - timestring(),fname,fsp->f_u.fd_ptr->fd,fnum,cnum,createmode,unixmode)); - + DEBUG( 2, ( "new file %s\n", fname ) ); + DEBUG( 3, ( "mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", + fname, fsp->f_u.fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); + return(outsize); } @@ -1676,10 +1678,10 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(fsp->granted_oplock) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - DEBUG(2,("created temp file %s\n",fname2)); - DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", - timestring(),fname2,fsp->f_u.fd_ptr->fd,fnum,cnum,createmode,unixmode)); - + DEBUG( 2, ( "created temp file %s\n", fname2 ) ); + DEBUG( 3, ( "ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", + fname2, fsp->f_u.fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); + return(outsize); } @@ -1885,10 +1887,9 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) if (nread < mincount) nread = 0; - DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n", - timestring(), - fnum,cnum,startpos, - maxcount,mincount,nread)); + DEBUG( 3, ( "readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n", + fnum, cnum, startpos, + maxcount, mincount, nread ) ); #if UNSAFE_READRAW { @@ -1955,17 +1956,18 @@ int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) return (ERROR(eclass,ecode)); nread = read_file(fnum,data,startpos,numtoread); - + if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); - + outsize += nread; SSVAL(outbuf,smb_vwv0,nread); SSVAL(outbuf,smb_vwv5,nread+3); SSVAL(smb_buf(outbuf),1,nread); - - DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread)); - + + DEBUG( 3, ( "lockread fnum=%d cnum=%d num=%d nread=%d\n", + fnum, cnum, numtoread, nread ) ); + return(outsize); } @@ -2010,8 +2012,9 @@ int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(smb_buf(outbuf),0) = 1; SSVAL(smb_buf(outbuf),1,nread); - DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread)); - + DEBUG( 3, ( "read fnum=%d cnum=%d num=%d nread=%d\n", + fnum, cnum, numtoread, nread ) ); + return(outsize); } @@ -2055,9 +2058,9 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n", - timestring(),fnum,cnum, - smb_mincnt,smb_maxcnt,nread)); + DEBUG( 3, ( "readX fnum=%d cnum=%d min=%d max=%d nread=%d\n", + fnum, cnum, + smb_mincnt, smb_maxcnt, nread ) ); chain_fnum = fnum; @@ -2114,8 +2117,8 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (numtowrite>0) nwritten = write_file(fnum,data,numtowrite); - DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n", - timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through)); + DEBUG( 3, ( "writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n", + fnum, cnum, startpos, numtowrite, nwritten, write_through ) ); if (nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -2160,8 +2163,8 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (lp_syncalways(SNUM(cnum)) || write_through) sync_file(cnum,fnum); - DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n", - timestring(),fnum,cnum,startpos,numtowrite,total_written)); + DEBUG( 3, ( "writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n", + fnum, cnum, startpos, numtowrite, total_written ) ); /* we won't return a status if write through is not selected - this follows what WfWg does */ @@ -2222,9 +2225,9 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_vwv0,nwritten); - DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n", - timestring(),fnum,cnum,numtowrite,nwritten)); - + DEBUG( 3, ( "writeunlock fnum=%d cnum=%d num=%d wrote=%d\n", + fnum, cnum, numtowrite, nwritten ) ); + return(outsize); } @@ -2279,8 +2282,9 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) SSVAL(outbuf,smb_err,ERRdiskfull); } - DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten)); - + DEBUG( 3, ( "%s write fnum=%d cnum=%d num=%d wrote=%d\n", + fnum, cnum, numtowrite, nwritten ) ); + return(outsize); } @@ -2333,7 +2337,8 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_err,ERRdiskfull); } - DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten)); + DEBUG( 3, ( "%s writeX fnum=%d cnum=%d num=%d wrote=%d\n", + fnum, cnum, smb_dsize, nwritten ) ); chain_fnum = fnum; @@ -2382,8 +2387,9 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,2,0,True); SIVALS(outbuf,smb_vwv0,res); - DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode)); - + DEBUG( 3, ( "lseek fnum=%d cnum=%d ofs=%d mode=%d\n", + fnum, cnum, startpos, mode ) ); + return(outsize); } @@ -2414,7 +2420,7 @@ int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) else sync_file(cnum,fnum); - DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum)); + DEBUG( 3, ( "flush fnum=%d\n", fnum ) ); return(outsize); } @@ -2425,8 +2431,8 @@ int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int reply_exit(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); - DEBUG(3,("%s exit\n",timestring())); - + DEBUG( 3, ( "exit\n" ) ); + return(outsize); } @@ -2472,9 +2478,9 @@ int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) * Special case - close NT SMB directory * handle. */ - DEBUG(3,("%s close directory fnum=%d cnum=%d\n", - timestring(), fnum, cnum )); - close_directory(fnum); + DEBUG( 3, ( "close directory fnum=%d cnum=%d\n", + fnum, cnum ) ); + close_directory( fnum ); } else { /* * Close ordinary file. @@ -2484,9 +2490,9 @@ int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /* try and set the date */ set_filetime(cnum, fsp->name,mtime); - DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - timestring(),fsp->f_u.fd_ptr->fd,fnum,cnum, - Connections[cnum].num_files_open)); + DEBUG( 3, ( "close fd=%d fnum=%d cnum=%d (numopen=%d)\n", + fsp->f_u.fd_ptr->fd, fnum, cnum, + Connections[cnum].num_files_open ) ); close_file(fnum,True); } @@ -2534,9 +2540,9 @@ int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) close_file(fnum,True); - DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", - timestring(),fnum,cnum,numtowrite,nwritten, - Connections[cnum].num_files_open)); + DEBUG( 3, ( "writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", + fnum, cnum, numtowrite, nwritten, + Connections[cnum].num_files_open ) ); if (nwritten <= 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2568,12 +2574,12 @@ int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); - DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", - timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum,offset,count)); + DEBUG( 3, ("lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", + Files[fnum].f_u.fd_ptr->fd, fnum, cnum, offset, count ) ); if(!do_lock( fnum, cnum, count, offset, F_WRLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); - + return(outsize); } @@ -2601,8 +2607,8 @@ int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); - DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", - timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum,offset,count)); + DEBUG( 3, ( "unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", + Files[fnum].f_u.fd_ptr->fd, fnum, cnum, offset, count ) ); return(outsize); } @@ -2629,7 +2635,7 @@ int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) close_cnum(cnum,vuid); - DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum)); + DEBUG( 3, ( "tdis cnum=%d\n", cnum ) ); return outsize; } @@ -2680,7 +2686,7 @@ int reply_echo(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) send_smb(Client,outbuf); } - DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum)); + DEBUG( 3, ( "echo %d times cnum=%d\n", smb_reverb, cnum ) ); return -1; } @@ -2750,9 +2756,9 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); - DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n", - timestring(),fname2,fsp->f_u.fd_ptr->fd,fnum,cnum)); - + DEBUG( 3, ("openprint %s fd=%d fnum=%d cnum=%d\n", + fname2, fsp->f_u.fd_ptr->fd, fnum, cnum ) ); + return(outsize); } @@ -2774,8 +2780,8 @@ int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n", - timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum)); + DEBUG( 3, ( "printclose fd=%d fnum=%d cnum=%d\n", + Files[fnum].f_u.fd_ptr->fd,fnum,cnum)); close_file(fnum,True); @@ -2808,8 +2814,8 @@ int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(smb_buf(outbuf),0) = 1; SSVAL(smb_buf(outbuf),1,0); - DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n", - timestring(),cnum,start_index,max_count)); + DEBUG( 3, ( "printqueue cnum=%d start_index=%d max_count=%d\n", + cnum, start_index, max_count ) ); if (!OPEN_CNUM(cnum) || !Connections[cnum].printer) { @@ -2903,7 +2909,7 @@ int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (write_file(fnum,data,numtowrite) != numtowrite) return(UNIXERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite)); + DEBUG( 3, ( "printwrite fnum=%d cnum=%d num=%d\n", fnum, cnum, numtowrite ) ); return(outsize); } @@ -2935,11 +2941,11 @@ int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } return(UNIXERROR(ERRDOS,ERRnoaccess)); } - + outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret)); - + + DEBUG( 3, ( "mkdir %s cnum=%d ret=%d\n", directory, cnum, ret ) ); + return(outsize); } @@ -3111,7 +3117,7 @@ int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,0,0,True); - DEBUG(3,("%s rmdir %s\n",timestring(),directory)); + DEBUG( 3, ( "rmdir %s\n", directory ) ); return(outsize); } @@ -3650,9 +3656,9 @@ int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,0,0,True); CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh); - - DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum)); - + + DEBUG( 3, ( "setdir %s cnum=%d\n", newdir, cnum ) ); + return(outsize); } @@ -3766,8 +3772,8 @@ dev = %x, inode = %x\n", set_message(outbuf,2,0,True); - DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", - timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks)); + DEBUG( 3, ( "lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", + fnum, cnum, (unsigned int)locktype, num_locks, num_ulocks ) ); chain_fnum = fnum; @@ -3922,9 +3928,9 @@ int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ - DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n", - timestring(),fnum,cnum,numtowrite,nwritten)); - + DEBUG( 3, ( "writebmpx fnum=%d cnum=%d num=%d wrote=%d\n", + fnum, cnum, numtowrite, nwritten ) ); + if (write_through && tcount==nwritten) { /* we need to send both a primary and a secondary response */ smb_setlen(outbuf,outsize - 4); @@ -4052,9 +4058,11 @@ int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if ((unix_times.actime == 0) && (unix_times.modtime == 0)) { /* Ignore request */ - DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \ -not setting timestamps of 0\n", - timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); + if( DEBUGLVL( 3 ) ) + { + dbgtext( "reply_setattrE fnum=%d cnum=%d ", fnum, cnum ); + dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); + } return(outsize); } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) @@ -4067,8 +4075,8 @@ not setting timestamps of 0\n", if(file_utime(cnum, Files[fnum].name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", - timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); + DEBUG( 3, ( "reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", + fnum, cnum, unix_times.actime, unix_times.modtime ) ); return(outsize); } @@ -4116,7 +4124,7 @@ int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } SSVAL(outbuf,smb_vwv10, mode); - DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum)); + DEBUG( 3, ( "reply_getattrE fnum=%d cnum=%d\n", fnum, cnum ) ); return(outsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 056611a886..2fc6bd2007 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1302,11 +1302,10 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct write_file(fnum,"%!\n",3); } - DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", - timestring(), + DEBUG( 2, ( "%s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", *sesssetup_user ? sesssetup_user : Connections[cnum].user,fname, - BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write), - Connections[cnum].num_files_open,fnum)); + BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), + Connections[cnum].num_files_open,fnum ) ); } @@ -1452,9 +1451,9 @@ void close_file(int fnum, BOOL normal_close) fs_p->sent_oplock_break = False; - DEBUG(2,("%s %s closed file %s (numopen=%d)\n", - timestring(),Connections[cnum].user,fs_p->name, - Connections[cnum].num_files_open)); + DEBUG( 2, ( "%s closed file %s (numopen=%d)\n", + Connections[cnum].user,fs_p->name, + Connections[cnum].num_files_open ) ); if (fs_p->name) { string_free(&fs_p->name); @@ -2201,8 +2200,8 @@ BOOL become_service(int cnum,BOOL do_chdir) ChDir(Connections[cnum].connectpath) != 0 && ChDir(Connections[cnum].origpath) != 0) { - DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(), - Connections[cnum].connectpath,cnum)); + DEBUG( 0, ( "chdir (%s) failed cnum=%d\n", + Connections[cnum].connectpath, cnum ) ); return(False); } @@ -2419,20 +2418,19 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int { SIVAL(outbuf,smb_rcls,error_code); - DEBUG(3,("%s 32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", - timestring(), line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf))); + DEBUG( 3, ( "32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", + line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf) ) ); } else { CVAL(outbuf,smb_rcls) = error_class; SSVAL(outbuf,smb_err,error_code); - DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - timestring(), - line, - (int)CVAL(inbuf,smb_com), - smb_fn_name(CVAL(inbuf,smb_com)), - error_class, - error_code)); + DEBUG( 3, ( "error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + line, + (int)CVAL(inbuf,smb_com), + smb_fn_name(CVAL(inbuf,smb_com)), + error_class, + error_code ) ); } @@ -2680,15 +2678,15 @@ static void process_smb(char *inbuf, char *outbuf) /* send a negative session response "not listining on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG(1,("%s Connection denied from %s\n", - timestring(),client_addr(Client))); + DEBUG( 1, ( "Connection denied from %s\n", + client_addr(Client) ) ); send_smb(Client,(char *)buf); exit_server("connection denied"); } } - DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); - DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); #ifdef WITH_SSL if(sslEnabled && !sslConnected){ @@ -2908,8 +2906,11 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) int saved_vuid; pstring saved_dir; - DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); + if( DEBUGLVL( 3 ) ) + { + dbgtext( "oplock_break: called for dev = %x, inode = %x.\n", dev, inode ); + dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); + } /* We need to search the file open table for the entry containing this dev and inode, and ensure @@ -2930,8 +2931,12 @@ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); if(fsp == NULL) { /* The file could have been closed in the meantime - return success. */ - DEBUG(0,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ -allowing break to succeed.\n", timestring(), dev, inode, fnum)); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: cannot find open file with " ); + dbgtext( "dev = %x, inode = %x (fnum = %d) ", dev, inode, fnum ); + dbgtext( "allowing break to succeed.\n" ); + } return True; } @@ -2946,18 +2951,30 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum)); if(!fsp->granted_oplock) { - DEBUG(0,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode)); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: file %s (fnum = %d, ", fsp->name, fnum ); + dbgtext( "dev = %x, inode = %x) has no oplock.\n", dev, inode ); + dbgtext( "Allowing break to succeed regardless.\n" ); + } return True; } /* mark the oplock break as sent - we don't want to send twice! */ if (fsp->sent_oplock_break) { - DEBUG(0,("%s oplock_break: ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode)); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); + dbgtext( "file %s (fnum = %d, ", fsp->name, fnum ); + dbgtext( "dev = %x, inode = %x)\n", dev, inode ); + } - /* We have to fail the open here as we cannot send another oplock break on this - file whilst we are awaiting a response from the client - neither can we - allow another open to succeed while we are waiting for the client. */ + /* We have to fail the open here as we cannot send another oplock break on + this file whilst we are awaiting a response from the client - neither + can we allow another open to succeed while we are waiting for the + client. + */ return False; } @@ -3030,18 +3047,17 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum)); */ if (smb_read_error == READ_EOF) - DEBUG(0,("%s oplock_break: end of file from client\n", timestring())); + DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); if (smb_read_error == READ_ERROR) - DEBUG(0,("%s oplock_break: receive_smb error (%s)\n", - timestring(), strerror(errno))); + DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); if (smb_read_error == READ_TIMEOUT) - DEBUG(0,("%s oplock_break: receive_smb timed out after %d seconds.\n", - timestring(), OPLOCK_BREAK_TIMEOUT)); + DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", + OPLOCK_BREAK_TIMEOUT ) ); - DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); + DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->name ) ); + DEBUGADD( 0, ( "(fnum = %d, dev = %x, inode = %x).\n", fnum, dev, inode)); shutdown_server = True; break; } @@ -3063,10 +3079,13 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) { - DEBUG(0,("%s oplock_break: no break received from client within \ -%d seconds.\n", timestring(), OPLOCK_BREAK_TIMEOUT)); - DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: no break received from client " ); + dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); + dbgtext( "oplock_break failed for file %s ", fsp->name ); + dbgtext( "(fnum = %d, dev = %x, inode = %x).\n", fnum, dev, inode ); + } shutdown_server = True; break; } @@ -3078,8 +3097,8 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); */ if(!become_user(&Connections[saved_cnum], saved_cnum, saved_vuid)) { - DEBUG(0,("%s oplock_break: unable to re-become user ! Shutting down server\n", - timestring())); + DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); + DEBUGADD( 0, ( "Shutting down server\n" ) ); close_sockets(); close(oplock_sock); exit_server("unable to re-become user"); @@ -3101,8 +3120,8 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); if(shutdown_server) { - DEBUG(0,("%s oplock_break: client failure in break - shutting down this smbd.\n", - timestring())); + DEBUG( 0, ( "oplock_break: client failure in break - " ) ); + DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); close_sockets(); close(oplock_sock); exit_server("oplock break failure"); @@ -3126,8 +3145,12 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode)); exit_server("oplock_break: global_oplocks_open < 0"); } - DEBUG(3,("%s oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", timestring(), fnum, dev, inode, global_oplocks_open)); + if( DEBUGLVL( 3 ) ) + { + dbgtext( "oplock_break: returning success for " ); + dbgtext( "fnum = %d, dev = %x, inode = %x.\n", fnum, dev, inode ); + dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); + } return True; } @@ -3178,16 +3201,24 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); addr_out.sin_port = htons( share_entry->op_port ); addr_out.sin_family = AF_INET; - DEBUG(3,("%s request_oplock_break: sending a oplock break message to pid %d on port %d \ -for dev = %x, inode = %x\n", timestring(), share_entry->pid, share_entry->op_port, dev, inode)); + if( DEBUGLVL( 3 ) ) + { + dbgtext( "request_oplock_break: sending a oplock break message to " ); + dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x\n", dev, inode ); + } if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - DEBUG(0,("%s request_oplock_break: failed when sending a oplock break message \ -to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", - timestring(), share_entry->pid, share_entry->op_port, dev, inode, - strerror(errno))); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "request_oplock_break: failed when sending a oplock " ); + dbgtext( "break message to pid %d ", share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); + dbgtext( "Error was %s\n", strerror(errno) ); + } return False; } @@ -3213,9 +3244,13 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", { if(smb_read_error == READ_TIMEOUT) { - DEBUG(0,("%s request_oplock_break: no response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x\n", timestring(), share_entry->pid, - share_entry->op_port, dev, inode)); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "request_oplock_break: no response received to oplock " ); + dbgtext( "break request to pid %d ", share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x\n", dev, inode ); + } /* * This is a hack to make handling of failing clients more robust. * If a oplock break response message is not received in the timeout @@ -3226,9 +3261,14 @@ pid %d on port %d for dev = %x, inode = %x\n", timestring(), share_entry->pid, break; } else - DEBUG(0,("%s request_oplock_break: error in response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, share_entry->pid, - share_entry->op_port, dev, inode, strerror(errno))); + if( DEBUGLVL( 0 ) ) + { + dbgtext( "request_oplock_break: error in response received " ); + dbgtext( "to oplock break request to pid %d ", share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); + dbgtext( "Error was (%s).\n", strerror(errno) ); + } return False; } @@ -3240,8 +3280,8 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, shar if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) { /* Ignore it. */ - DEBUG(0,("%s request_oplock_break: invalid message length received. Ignoring\n", - timestring())); + DEBUG( 0, ( "request_oplock_break: invalid message length received." ) ); + DEBUGADD( 0, ( " Ignoring.\n" ) ); continue; } @@ -3278,7 +3318,7 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, shar time_left -= (time(NULL) - start_time); } - DEBUG(3,("%s request_oplock_break: broke oplock.\n", timestring())); + DEBUG( 3, ( "%s request_oplock_break: broke oplock.\n" ) ); return True; } @@ -3422,12 +3462,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { extern int Client; if (strequal(service,"IPC$")) - { - DEBUG(3,("%s refusing IPC connection\n",timestring())); - return(-3); + { + DEBUG( 3, ( "refusing IPC connection\n" ) ); + return( -3 ); } - DEBUG(0,("%s %s (%s) couldn't find service %s\n",timestring(),remote_machine,client_addr(Client),service)); + DEBUG( 0, ( "%s (%s) couldn't find service %s\n", + remote_machine, client_addr(Client), service ) ); return(-2); } @@ -3489,14 +3530,14 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de /* shall we let them in? */ if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { - DEBUG(2,("%s invalid username/password for %s\n",timestring(),service)); + DEBUG( 2, ( "Invalid username/password for %s\n", service ) ); return(-1); } - cnum = find_free_connection(str_checksum(service) + str_checksum(user)); + cnum = find_free_connection( str_checksum(service) + str_checksum(user) ); if (cnum < 0) { - DEBUG(0,("%s couldn't find free connection\n",timestring())); + DEBUG( 0, ( "Couldn't find free connection.\n" ) ); return(-1); } @@ -3508,7 +3549,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de if (pass == NULL) { - DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); + DEBUG( 0, ( "Couldn't find account %s\n", user ) ); return(-7); } @@ -3711,17 +3752,16 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de set_namearray( &pcon->veto_oplock_list, lp_veto_oplocks(SNUM(cnum))); } - { + if( DEBUGLVL( IS_IPC(cnum) ? 3 : 1 ) ) + { extern int Client; - DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n", - timestring(), - remote_machine, - client_addr(Client), - lp_servicename(SNUM(cnum)),user, - pcon->uid, - pcon->gid, - (int)getpid())); - } + + dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); + dbgtext( "connect to service %s ", lp_servicename(SNUM(cnum)) ); + dbgtext( "as user %s ", user ); + dbgtext( "(uid=%d, gid=%d) ", pcon->uid, pcon->gid ); + dbgtext( "(pid %d)\n", (int)getpid() ); + } return(cnum); } @@ -4235,7 +4275,7 @@ static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz } SSVAL(outbuf,smb_vwv0,choice); - DEBUG(5,("%s negprot index=%d\n",timestring(),choice)); + DEBUG( 5, ( "negprot index=%d\n", choice ) ); return(outsize); } @@ -4274,10 +4314,9 @@ void close_cnum(int cnum, uint16 vuid) return; } - DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n", - timestring(), - remote_machine,client_addr(Client), - lp_servicename(SNUM(cnum)))); + DEBUG( IS_IPC(cnum)?3:1, ( "%s (%s) closed connection to service %s\n", + remote_machine,client_addr(Client), + lp_servicename(SNUM(cnum)) ) ); yield_connection(cnum, lp_servicename(SNUM(cnum)), @@ -4400,7 +4439,7 @@ void exit_server(char *reason) locking_end(); - DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:"")); + DEBUG( 3, ( "Server exit (%s)\n", (reason ? reason : "") ) ); exit(0); } @@ -4645,10 +4684,10 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize * Queue this message as we are the process of an oplock break. */ - DEBUG(2,("%s: switch_message: queueing message due to being in oplock break state.\n", - timestring() )); + DEBUG( 2, ( "switch_message: queueing message due to being in " ) ); + DEBUGADD( 2, ( "oplock break state.\n" ) ); - push_oplock_pending_smb_message( inbuf, size); + push_oplock_pending_smb_message( inbuf, size ); return -1; } @@ -4995,15 +5034,15 @@ static void process(void) /* automatic timeout if all connections are closed */ if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) { - DEBUG(2,("%s Closing idle connection\n",timestring())); + DEBUG( 2, ( "Closing idle connection\n" ) ); return; } if (keepalive && (counter-last_keepalive)>keepalive) { struct cli_state *cli = server_client(); - if (!send_keepalive(Client)) { - DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); + if (!send_keepalive(Client)) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); return; } /* also send a keepalive to the password server if its still @@ -5028,7 +5067,7 @@ static void process(void) if (allidle && num_connections_open>0) { - DEBUG(2,("%s Closing idle connection 2\n",timestring())); + DEBUG( 2, ( "Closing idle connection 2.\n" ) ); return; } @@ -5281,8 +5320,8 @@ static void usage(char *pname) reopen_logs(); - DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION)); - DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n")); + DEBUG( 1, ( "smbd version %s started.\n", VERSION ) ); + DEBUGADD( 1, ( "Copyright Andrew Tridgell 1992-1997\n" ) ); #ifdef HAVE_GETRLIMIT #ifdef RLIMIT_NOFILE @@ -5353,7 +5392,7 @@ static void usage(char *pname) #endif /* SIGUSR2 */ #endif /* MEM_MAN */ - DEBUG(3,("%s loaded services\n",timestring())); + DEBUG( 3, ( "loaded services\n" ) ); if (!is_daemon && !is_a_socket(0)) { @@ -5363,7 +5402,7 @@ static void usage(char *pname) if (is_daemon) { - DEBUG(3,("%s becoming a daemon\n",timestring())); + DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(); } @@ -5392,11 +5431,11 @@ static void usage(char *pname) if (*lp_rootdir()) { if (sys_chroot(lp_rootdir()) == 0) - DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); + DEBUG( 2, ( "Changed root to %s\n", lp_rootdir() ) ); } /* Setup the oplock IPC socket. */ - if(!open_oplock_ipc()) + if( !open_oplock_ipc() ) exit(1); process(); diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index 68b45016b8..27bb8f3a52 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -246,16 +246,15 @@ char *reqHosts, *resignHosts; return 0; } if(msg_type != 0x81){ /* first packet must be a session request */ - DEBUG(0, ("%s Client %s did not use session setup; access denied\n", - timestring(), client_addr(fd))); + DEBUG( 0, ( "Client %s did not use session setup; access denied\n", + client_addr(fd) ) ); send_smb(fd, (char *)buf); return -1; } buf[4] = 0x8e; /* negative session response: use SSL */ send_smb(fd, (char *)buf); if(sslutil_accept(fd) != 0){ - DEBUG(0, ("%s Client %s failed SSL negotiation!\n", - timestring(), client_addr(fd))); + DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr(fd) ) ); return -1; } return 1; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 08f6803005..7f34187bd6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -807,10 +807,9 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", - timestring(), - smb_fn_name(CVAL(inbuf,smb_com)), - mask,directory,cnum,dirtype,numentries)); + DEBUG( 4, ( "%s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", + smb_fn_name(CVAL(inbuf,smb_com)), + mask, directory, cnum, dirtype, numentries ) ); return(-1); } @@ -1020,10 +1019,9 @@ resume_key = %d resume name = %s continue=%d level = %d\n", if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", - timestring(), - smb_fn_name(CVAL(inbuf,smb_com)), - mask,directory,cnum,dirtype,numentries)); + DEBUG( 3, ( "%s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", + smb_fn_name(CVAL(inbuf,smb_com)), + mask, directory, cnum, dirtype, numentries ) ); return(-1); } @@ -1133,7 +1131,8 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len); - DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level)); + DEBUG( 4, ( "%s info_level = %d\n", + smb_fn_name(CVAL(inbuf,smb_com)), info_level) ); return -1; } @@ -1719,7 +1718,7 @@ int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize) outsize = set_message(outbuf,0,0,True); - DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num)); + DEBUG( 3, ( "SMBfindclose cnum=%d, dptr_num = %d\n", cnum, dptr_num ) ); return(outsize); } @@ -1744,7 +1743,7 @@ int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize) outsize = set_message(outbuf,0,0,True); - DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num)); + DEBUG( 3, ( "SMB_findnclose cnum=%d, dptr_num = %d\n", cnum, dptr_num ) ); return(outsize); } @@ -1787,8 +1786,8 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) * Queue this open message as we are the process of an oplock break. */ - DEBUG(2,("%s: reply_trans2: queueing message trans2open due to being in oplock break state.\n", - timestring() )); + DEBUG( 2, ( "reply_trans2: queueing message trans2open due to being " ) ); + DEBUGADD( 2, ( "in oplock break state.\n" ) ); push_oplock_pending_smb_message( inbuf, length); return -1; @@ -1915,7 +1914,7 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) break; default: /* Error in request */ - DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call)); + DEBUG( 2, ( "Unknown request %d in trans2 call\n", tran_call ) ); if(params) free(params); if(data) diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 173fdaca03..82ff7ee7ce 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -327,8 +327,7 @@ BOOL unbecome_user(void ) current_user.gid = initial_gid; if (ChDir(OriginalDir) != 0) - DEBUG(0,("%s chdir(%s) failed in unbecome_user\n", - timestring(),OriginalDir)); + DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c index 6e95bac3c2..64272ed8da 100644 --- a/source3/smbd/vt_mode.c +++ b/source3/smbd/vt_mode.c @@ -452,7 +452,7 @@ void VT_Process(void) nread = len + 4; - DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + DEBUG( 3, ("Transaction %d of length %d\n", trans_num, nread ) ); if(msg_type == 0) VT_Output(InBuffer); -- cgit From 7448091da6ee11709b8e5117ff6810515567f88a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Aug 1998 19:07:55 +0000 Subject: First implementation of ChangeNotify - this version only checks for changes in the directory modify timestamps. A better version will look at the requested client flags, and create a hash that represents the current state of the directory, and check against this instead. debug.c: Added lp_timestamp_logs() function. loadparm.c: Added "change notify timeout" in seconds (default 60) - this is the scan rate for a directory. Added ""timestamp logs" boolean - default True. Turns off log timestamps (so I can read them :-). nttrans.c: ChangeNotify implementation. server.c: ChangeNotify implementation. shmem_sysv.c: Added exits on shmem errors (without them smbd can core dump if some calls fail). smb.h: Added ChangeNotify flags for future use. util.c: Tidied up typedef. Jeremy. (This used to be commit a0748c3f53974483680ebe2ea4f556ece8d7fa43) --- source3/smbd/nttrans.c | 304 +++++++++++++++++++++++++++++++++++++++++++++---- source3/smbd/server.c | 13 ++- 2 files changed, 297 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d845076f36..4ee271cd6b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -657,6 +657,9 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) chain_fnum = fnum; + DEBUG(5,("reply_ntcreate_and_X: open fnum = %d, name = %s\n", + fnum, fsp->name )); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -737,12 +740,14 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, return(ERROR(ERRSRV,ERRnofids)); } + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; restore_case_semantics(file_attributes); @@ -783,14 +788,12 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; restore_case_semantics(file_attributes); @@ -887,12 +890,22 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, } /**************************************************************************** - Reply to a NT CANCEL request - just ignore it. + Reply to a NT CANCEL request. ****************************************************************************/ int reply_ntcancel(char *inbuf,char *outbuf,int length,int bufsize) { - DEBUG(4,("Ignoring ntcancel of length %d\n",length)); + /* + * Go through and cancel any pending change notifies. + * TODO: When we add blocking locks we will add cancel + * for them here too. + */ + + int mid = SVAL(inbuf,smb_mid); + remove_pending_change_notify_requests_by_mid(mid); + + DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); + return(-1); } @@ -933,6 +946,10 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int length, * Rename was successful. */ send_nt_replies(outbuf, bufsize, NULL, 0, NULL, 0); + + DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", + Files[fnum].name, new_name)); + outsize = -1; } @@ -940,7 +957,175 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int length, } /**************************************************************************** - Reply to a notify change - we should never get this (for now) as we + This is the structure to queue to implement NT change + notify. It consists of smb_size bytes stored from the + transact command (to keep the mid, tid etc around). + Plus the fid to examine and the time to check next. +*****************************************************************************/ + +typedef struct { + ubi_slNode msg_next; + int fnum; + int cnum; + time_t next_check_time; + char request_buf[smb_size]; +} change_notify_buf; + +static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_queue, 0}; + +/**************************************************************************** + Setup the common parts of the return packet and send it. + Code stolen from construct_reply() in server.c +*****************************************************************************/ + +static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) +{ + extern int Client; + char outbuf[smb_size]; + + bzero(outbuf,smb_size); + + CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); + set_message(outbuf,0,0,True); + + memcpy(outbuf+4,inbuf+4,4); + CVAL(outbuf,smb_rcls) = SMB_SUCCESS; + CVAL(outbuf,smb_reh) = 0; + CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set + means a reply */ + SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf,smb_err,SMB_SUCCESS); + SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); + SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); + SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); + SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); + + ERROR(error_class,error_code); + send_smb(Client,outbuf); +} + +/**************************************************************************** + Delete entries by fnum from the change notify pending queue. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_fid(int fnum) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + if(cnbp->fnum == fnum) { + ubi_slRemNext( &change_notify_queue, prev); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Delete entries by mid from the change notify pending queue. Always send reply. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_mid(int mid) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + if(SVAL(cnbp->request_buf,smb_mid) == mid) { + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + ubi_slRemNext( &change_notify_queue, prev); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Process the change notify queue. Note that this is only called as root. +*****************************************************************************/ + +void process_pending_change_notify_queue(time_t t) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + if(cnbp == NULL) + return; + + if(cnbp->next_check_time >= t) + return; + + /* + * It's time to check. Go through the queue and see if + * the timestamps changed. + */ + + while((cnbp != NULL) && (cnbp->next_check_time <= t)) { + struct stat st; + int fnum = cnbp->fnum; + int cnum = cnbp->cnum; + files_struct *fsp = &Files[fnum]; + uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(cnbp->request_buf,smb_uid); + + if(!become_user(&Connections[cnum],cnum,vuid)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + ubi_slRemNext( &change_notify_queue, prev); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + if(sys_stat(fsp->name, &st) < 0) { + DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \ +Error was %s.\n", fsp->name, strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + ubi_slRemNext( &change_notify_queue, prev); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + if(fsp->f_u.dir_ptr->modify_time != st.st_mtime || + fsp->f_u.dir_ptr->status_time != st.st_ctime) { + /* + * Remove the entry and return a change notify to the client. + */ + DEBUG(5,("process_pending_change_notify_queue: directory fnum = %d, name = %s changed\n", + fnum, fsp->name )); + change_notify_reply_packet(cnbp->request_buf,ERRDOS,ERROR_NOTIFY_ENUM_DIR); + ubi_slRemNext( &change_notify_queue, prev); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + unbecome_user(); + + /* + * Move to the next in the list. + */ + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Reply to a notify change - queue the request and don't allow a directory to be opened. ****************************************************************************/ @@ -948,10 +1133,83 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, int bufsize, int cnum, char **ppsetup, char **ppparams, char **ppdata) { +#if 0 DEBUG(0,("call_nt_transact_notify_change: Should not be called !\n")); return(ERROR(ERRSRV,ERRnosupport)); +#else /* Under development. */ + char *setup = *ppsetup; + files_struct *fsp; + int fnum = -1; + change_notify_buf *cnbp; + struct stat st; + + fnum = SVAL(setup,4); + + DEBUG(0,("call_nt_transact_notify_change: fnum = %d.\n", fnum)); + + if(!VALID_FNUM(fnum)) + return(ERROR(ERRDOS,ERRbadfid)); + + fsp = &Files[fnum]; + + if((!fsp->open) || (!fsp->is_directory) || (cnum != fsp->cnum)) + return(ERROR(ERRDOS,ERRbadfid)); + + /* + * Setup the current directory information in the + * directory entry in the files_struct. We will use + * this to check against when the timer expires. + */ + + if(sys_stat(fsp->name, &st) < 0) { + DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \ + Error was %s\n", fnum, fsp->name, strerror(errno) )); + return -1; + } + + if(fsp->f_u.dir_ptr == NULL) { + if((fsp->f_u.dir_ptr = (dir_status_struct *)malloc(sizeof(dir_status_struct))) == NULL) { + DEBUG(0,("call_nt_transact_notify_change: Malloc fail !\n" )); + return -1; + } + } + + fsp->f_u.dir_ptr->modify_time = st.st_mtime; + fsp->f_u.dir_ptr->status_time = st.st_ctime; + + /* + * Now queue an entry on the notify change stack. We timestamp + * the entry we are adding so that we know when to scan next. + * We only need to save smb_size bytes from this incoming packet + * as we will always by returning a 'read the directory yourself' + * error. + */ + + if((cnbp = (change_notify_buf *)malloc(sizeof(change_notify_buf))) == NULL) { + DEBUG(0,("call_nt_transact_notify_change: Malloc fail (2) !\n" )); + return -1; + } + + memcpy(cnbp->request_buf, inbuf, smb_size); + cnbp->fnum = fnum; + cnbp->cnum = cnum; + cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); + + /* + * Adding to the tail enables us to check only + * the head when scanning for change, as this entry + * is forced to have the first timeout expiration. + */ + + ubi_slAddTail(&change_notify_queue, cnbp); + + DEBUG(3,("call_nt_transact_notify_change: notify change called on directory fid=%d, name = %s\n", + fnum, fsp->name )); + + return -1; +#endif } - + /**************************************************************************** Reply to query a security descriptor - currently this is not implemented (it is planned to be though). @@ -996,7 +1254,7 @@ static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int length, int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) { - int outsize = 0; + int outsize = 0; int cnum = SVAL(inbuf,smb_tid); #if 0 /* Not used. */ uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); @@ -1009,7 +1267,7 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset); uint32 data_count = IVAL(inbuf,smb_nt_DataCount); uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset); - uint16 setup_count = CVAL(inbuf,smb_nt_SetupCount); + uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */ uint16 function_code = SVAL( inbuf, smb_nt_Function); char *params = NULL, *data = NULL, *setup = NULL; uint32 num_params_sofar, num_data_sofar; @@ -1019,8 +1277,8 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) * Queue this open message as we are the process of an oplock break. */ - DEBUG( 2, ( "reply_nttrans: queueing message NT_TRANSACT_CREATE " ) ); - DEBUGADD( 2, ( "due to being in oplock break state.\n" ) ); + DEBUG(2,("reply_nttrans: queueing message NT_TRANSACT_CREATE \ +due to being in oplock break state.\n" )); push_oplock_pending_smb_message( inbuf, length); return -1; @@ -1033,9 +1291,9 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) * Ensure this is so as a sanity check. */ - if(CVAL(inbuf, smb_wct) != 19 + setup_count) { + if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) { DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", - CVAL(inbuf, smb_wct), 19 + setup_count)); + CVAL(inbuf, smb_wct), 19 + (setup_count/2))); return(ERROR(ERRSRV,ERRerror)); } @@ -1062,12 +1320,21 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) if (parameter_count > total_parameter_count || data_count > total_data_count) exit_server("reply_nttrans: invalid sizes in packet.\n"); - if(setup) + if(setup) { memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); - if(params) + DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count)); + dump_data(10, setup, setup_count); + } + if(params) { memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); - if(data) + DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count)); + dump_data(10, params, parameter_count); + } + if(data) { memcpy( data, smb_base(inbuf) + data_offset, data_count); + DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); + dump_data(10, data, data_count); + } if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { /* We need to send an interim response then receive the rest @@ -1145,8 +1412,7 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) break; default: /* Error in request */ - DEBUG( 0, ( "reply_nttrans: Unknown request %d in nttrans call\n", - function_code ) ); + DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); if(setup) free(setup); if(params) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2fc6bd2007..97a1a79239 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1475,6 +1475,8 @@ void close_directory(int fnum) change notify requests and free any pertaining to this fnum. */ + remove_pending_change_notify_requests_by_fid(fnum); + /* * Do the code common to files and directories. */ @@ -1532,6 +1534,9 @@ int open_directory(int fnum,int cnum,char *fname, int smb_ofun, int unixmode, in *action = FILE_WAS_OPENED; } + DEBUG(5,("open_directory: opening directory %s, fnum = %d\n", + fname, fnum )); + /* * Setup the files_struct for it. */ @@ -4029,7 +4034,7 @@ int reply_nt1(char *outbuf) /* other valid capabilities which we may support at some time... - CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; + CAP_LARGE_FILES| CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; */ @@ -5116,6 +5121,12 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); trust_password_unlock(); global_machine_pasword_needs_changing = False; } + + /* + * Check to see if we have any change notifies + * outstanding on the queue. + */ + process_pending_change_notify_queue(t); } if(got_smb) -- cgit From c0c057c0dfc43c47b2d340e26026136cf001ff0a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Aug 1998 01:01:26 +0000 Subject: loadparm.c: Added "debug timestamp" synonym for Chris. nttrans.c: Moved common code into function in server.c Removed left over debug level 0. server.c: Moved common code into function in server.c Jeremy. (This used to be commit 34ef55b7228155cef40cbdfcdc1fe623c1037bd6) --- source3/smbd/nttrans.c | 25 ++----------------------- source3/smbd/reply.c | 2 ++ source3/smbd/server.c | 40 ++++++++++++++++++++++++---------------- 3 files changed, 28 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4ee271cd6b..a30da8e6e0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -975,7 +975,6 @@ static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_qu /**************************************************************************** Setup the common parts of the return packet and send it. - Code stolen from construct_reply() in server.c *****************************************************************************/ static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) @@ -983,22 +982,7 @@ static void change_notify_reply_packet(char *inbuf, int error_class, uint32 erro extern int Client; char outbuf[smb_size]; - bzero(outbuf,smb_size); - - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); - set_message(outbuf,0,0,True); - - memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf,smb_reh) = 0; - CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf,smb_err,SMB_SUCCESS); - SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); + construct_reply_common(inbuf, outbuf); ERROR(error_class,error_code); send_smb(Client,outbuf); @@ -1133,10 +1117,6 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, int bufsize, int cnum, char **ppsetup, char **ppparams, char **ppdata) { -#if 0 - DEBUG(0,("call_nt_transact_notify_change: Should not be called !\n")); - return(ERROR(ERRSRV,ERRnosupport)); -#else /* Under development. */ char *setup = *ppsetup; files_struct *fsp; int fnum = -1; @@ -1145,7 +1125,7 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, fnum = SVAL(setup,4); - DEBUG(0,("call_nt_transact_notify_change: fnum = %d.\n", fnum)); + DEBUG(3,("call_nt_transact_notify_change: fnum = %d.\n", fnum)); if(!VALID_FNUM(fnum)) return(ERROR(ERRDOS,ERRbadfid)); @@ -1207,7 +1187,6 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, fnum, fsp->name )); return -1; -#endif } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 71544c1b19..2e6ceb93aa 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -82,6 +82,8 @@ int reply_special(char *inbuf,char *outbuf) *name1 = *name2 = 0; + bzero(outbuf,smb_size); + smb_setlen(outbuf,0); switch (msg_type) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 97a1a79239..97c54cde04 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4888,6 +4888,29 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) } +/**************************************************************************** + Helper function for contruct_reply. +****************************************************************************/ + +void construct_reply_common(char *inbuf,char *outbuf) +{ + bzero(outbuf,smb_size); + + CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); + set_message(outbuf,0,0,True); + + memcpy(outbuf+4,inbuf+4,4); + CVAL(outbuf,smb_rcls) = SMB_SUCCESS; + CVAL(outbuf,smb_reh) = 0; + CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set + means a reply */ + SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf,smb_err,SMB_SUCCESS); + SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); + SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); + SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); + SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); +} /**************************************************************************** construct a reply to the incoming packet @@ -4905,25 +4928,10 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) chain_fnum = -1; reset_chain_pnum(); - bzero(outbuf,smb_size); - if (msg_type != 0) return(reply_special(inbuf,outbuf)); - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); - set_message(outbuf,0,0,True); - - memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf,smb_reh) = 0; - CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf,smb_err,SMB_SUCCESS); - SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); + construct_reply_common(inbuf, outbuf); outsize = switch_message(type,inbuf,outbuf,size,bufsize); -- cgit From 3aeadef40b92d031036a50042bbf8fbe60d0954a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Aug 1998 23:45:34 +0000 Subject: nttrans.c: Fix change_notify. Queue processing code wasn't changing to the correct directory before doing the stat. Doh ! uid.c: Fix for performance in security=share mode. Invalid vuid meant that in security=share mode Samba was always doing the become_user/ undebome_user pairs for *every* smb. This code fixes it, but tridge should review for security implications. Jeremy. (This used to be commit c3663379fdcec487feea2e5d848ee012ee6c6baf) --- source3/smbd/nttrans.c | 59 +++++++++++++++++++++++++++++++++++--------------- source3/smbd/uid.c | 13 ++++++++++- 2 files changed, 54 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a30da8e6e0..1f724a4bfb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1071,6 +1071,19 @@ void process_pending_change_notify_queue(time_t t) continue; } + if(!become_service(cnum,True)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to become service cnum=%d. \ +Error was %s.\n", cnum, strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + ubi_slRemNext( &change_notify_queue, prev); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + if(sys_stat(fsp->name, &st) < 0) { DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \ Error was %s.\n", fsp->name, strerror(errno) )); @@ -1135,27 +1148,39 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, if((!fsp->open) || (!fsp->is_directory) || (cnum != fsp->cnum)) return(ERROR(ERRDOS,ERRbadfid)); - /* - * Setup the current directory information in the - * directory entry in the files_struct. We will use - * this to check against when the timer expires. - */ - - if(sys_stat(fsp->name, &st) < 0) { - DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \ - Error was %s\n", fnum, fsp->name, strerror(errno) )); - return -1; - } - if(fsp->f_u.dir_ptr == NULL) { + + /* + * No currently stored directory info - we must + * generate it here. + */ + if((fsp->f_u.dir_ptr = (dir_status_struct *)malloc(sizeof(dir_status_struct))) == NULL) { DEBUG(0,("call_nt_transact_notify_change: Malloc fail !\n" )); return -1; } - } - fsp->f_u.dir_ptr->modify_time = st.st_mtime; - fsp->f_u.dir_ptr->status_time = st.st_ctime; + /* + * Setup the current directory information in the + * directory entry in the files_struct. We will use + * this to check against when the timer expires. + * NB. We only do this if there is no current directory + * information in the directory struct - as when we start + * monitoring file size etc. this information will start + * becoming increasingly expensive to maintain, so we won't + * want to re-generate it for every ChangeNofity call. + */ + + if(sys_stat(fsp->name, &st) < 0) { + DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \ +Error was %s\n", fnum, fsp->name, strerror(errno) )); + return -1; + } + + fsp->f_u.dir_ptr->modify_time = st.st_mtime; + fsp->f_u.dir_ptr->status_time = st.st_ctime; + + } /* * Now queue an entry on the notify change stack. We timestamp @@ -1183,8 +1208,8 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, ubi_slAddTail(&change_notify_queue, cnbp); - DEBUG(3,("call_nt_transact_notify_change: notify change called on directory fid=%d, name = %s\n", - fnum, fsp->name )); + DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ +fid=%d, name = %s\n", fnum, fsp->name )); return -1; } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 82ff7ee7ce..9e669c301b 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -216,7 +216,18 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) int snum,gid; int uid; - if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) && + /* + * We need a separate check in security=share mode due to vuid + * always being UID_FIELD_INVALID. If we don't do this then + * in share mode security we are *always* changing uid's between + * SMB's - this hurts performance - Badly. + */ + + if((lp_security() == SEC_SHARE) && (current_user.cnum == cnum) && + (current_user.uid == conn->uid)) { + DEBUG(4,("Skipping become_user - already user\n")); + return(True); + } else if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) && (current_user.uid == vuser->uid)) { DEBUG(4,("Skipping become_user - already user\n")); return(True); -- cgit From a4b872451e5195063d657bff8763227e9f82b4b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Aug 1998 22:17:51 +0000 Subject: Fixed memory leak when freeing ChangeNotify structures. Jeremy. (This used to be commit 996c5ac97a8d1443bc8abc59b9a10ff3aeb77389) --- source3/smbd/nttrans.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1f724a4bfb..b4873efea0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -999,7 +999,7 @@ void remove_pending_change_notify_requests_by_fid(int fnum) while(cnbp != NULL) { if(cnbp->fnum == fnum) { - ubi_slRemNext( &change_notify_queue, prev); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; } @@ -1021,7 +1021,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) while(cnbp != NULL) { if(SVAL(cnbp->request_buf,smb_mid) == mid) { change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - ubi_slRemNext( &change_notify_queue, prev); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; } @@ -1066,7 +1066,7 @@ void process_pending_change_notify_queue(time_t t) * Remove the entry and return an error to the client. */ change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - ubi_slRemNext( &change_notify_queue, prev); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; } @@ -1078,7 +1078,7 @@ Error was %s.\n", cnum, strerror(errno) )); * Remove the entry and return an error to the client. */ change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - ubi_slRemNext( &change_notify_queue, prev); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); unbecome_user(); continue; @@ -1091,7 +1091,7 @@ Error was %s.\n", fsp->name, strerror(errno) )); * Remove the entry and return an error to the client. */ change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - ubi_slRemNext( &change_notify_queue, prev); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); unbecome_user(); continue; @@ -1105,7 +1105,7 @@ Error was %s.\n", fsp->name, strerror(errno) )); DEBUG(5,("process_pending_change_notify_queue: directory fnum = %d, name = %s changed\n", fnum, fsp->name )); change_notify_reply_packet(cnbp->request_buf,ERRDOS,ERROR_NOTIFY_ENUM_DIR); - ubi_slRemNext( &change_notify_queue, prev); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); unbecome_user(); continue; -- cgit From 27ff18a184556f1e157de7c2789f39e3e70a40fc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Aug 1998 11:24:15 +0000 Subject: these dummy files are needed for autoconf processing (This used to be commit be762dc3de6c1ef768790522dfe93007a61ce5d7) --- source3/smbd/dummy.in | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 source3/smbd/dummy.in (limited to 'source3/smbd') diff --git a/source3/smbd/dummy.in b/source3/smbd/dummy.in new file mode 100644 index 0000000000..e69de29bb2 -- cgit From 87bcd5502c105921b48f9654d1c4f6d14ed9e9f6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Aug 1998 11:25:49 +0000 Subject: added ignore rules for the dummy files (This used to be commit 687f76a17d6d3ebd33b4d9a848deef56f3c1f56a) --- source3/smbd/.cvsignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 source3/smbd/.cvsignore (limited to 'source3/smbd') diff --git a/source3/smbd/.cvsignore b/source3/smbd/.cvsignore new file mode 100644 index 0000000000..421376db9e --- /dev/null +++ b/source3/smbd/.cvsignore @@ -0,0 +1 @@ +dummy -- cgit From 35f815d2786ec1bd99676f62ff5e636e81809e51 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Aug 1998 13:25:34 +0000 Subject: this gets smbd compiling and linking correctly with the new layout. (This used to be commit d08fa39cec5c71a9034dbf4241fc7e195f1bbaa5) --- source3/smbd/ipc.c | 24 +-- source3/smbd/nttrans.c | 11 +- source3/smbd/smbrun.c | 92 ---------- source3/smbd/vt_mode.c | 490 ------------------------------------------------- 4 files changed, 18 insertions(+), 599 deletions(-) delete mode 100644 source3/smbd/smbrun.c delete mode 100644 source3/smbd/vt_mode.c (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index adc3fcdcb5..f1467a7f8a 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3694,18 +3694,18 @@ int reply_trans(char *inbuf,char *outbuf, int size, int bufsize) ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT); - if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) - { - if(ret) - DEBUG(0,("reply_trans: Invalid secondary trans packet\n")); - else - DEBUG(0,("reply_trans: %s in getting secondary trans response.\n", - (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - if (params) free(params); - if (data) free(data); - if (setup) free(setup); - return(ERROR(ERRSRV,ERRerror)); - } + if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) { + if(ret) { + DEBUG(0,("reply_trans: Invalid secondary trans packet\n")); + } else { + DEBUG(0,("reply_trans: %s in getting secondary trans response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); + } + if (params) free(params); + if (data) free(data); + if (setup) free(setup); + return(ERROR(ERRSRV,ERRerror)); + } show_msg(inbuf); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b4873efea0..c6782cd45f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1354,11 +1354,12 @@ due to being in oplock break state.\n" )); if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) { outsize = set_message(outbuf,0,0,True); - if(ret) - DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n")); - else - DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", - (smb_read_error == READ_ERROR) ? "error" : "timeout" )); + if(ret) { + DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n")); + } else { + DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); + } if(params) free(params); if(data) diff --git a/source3/smbd/smbrun.c b/source3/smbd/smbrun.c deleted file mode 100644 index 2a94ac3235..0000000000 --- a/source3/smbd/smbrun.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - external program running routine - Copyright (C) Andrew Tridgell 1992-1998 - - 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" - - -/******************************************************************* -close the low 3 fd's and open dev/null in their place -********************************************************************/ -static void close_fds(void) -{ - int fd; - int i; - close(0); close(1); close(2); - /* 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); - if (fd != i) return; - } -} - - -/* -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 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 (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 HAVE_SETRESUID - setresgid(0,0,0); - setresuid(0,0,0); -#else - setuid(0); - seteuid(0); -#endif - -#ifdef HAVE_SETRESUID - 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(4); - - /* this is to make sure that the system() call doesn't run forever */ - alarm(30); - - return(system(argv[3])); -} diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c deleted file mode 100644 index 64272ed8da..0000000000 --- a/source3/smbd/vt_mode.c +++ /dev/null @@ -1,490 +0,0 @@ -/* vt_mode.c */ -/* -support vtp-sessions - -(C) written by Christian A. Lademann -*/ - -/* -02.05.95:cal:ported to samba-1.9.13 -*/ - -#define __vt_mode_c__ - - -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -#include "includes.h" -#include "vt_mode.h" -#include - -#ifdef SCO - extern char *strdup(); -#endif - -extern int Client; - -#ifdef LINUX -# define HAS_VTY -#endif - -#ifdef SCO -# define HAS_PTY -# define HAS_VTY - -# include -#endif - -extern int DEBUGLEVEL; -extern char *InBuffer, *OutBuffer; -extern int done_become_user; - -fstring master_name, slave_name; -int master, slave, i, o, e; - -int ms_type = MS_NONE, - ms_poll = 0; - - -/* -VT_Check: test incoming packet for "vtp" or "iVT1\0" -*/ -int VT_Check(char *buffer) -{ - DEBUG(3,("Checking packet: <%10s...>\n", buffer+4)); - if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5)) - return(1); - else - return(0); -} - - -/* -VT_Start_utmp: prepare /etc/utmp for /bin/login -*/ -int VT_Start_utmp(void) -{ - struct utmp u, *v; - char *tt; - - - setutent(); - - fstrcpy(u.ut_line, VT_Line); - - if((v = getutline(&u)) == NULL) { - if(strncmp(VT_Line, "tty", 3) == 0) - tt = VT_Line + 3; - else if(strlen(VT_Line) > 4) - tt = VT_Line + strlen(VT_Line) - 4; - else - tt = VT_Line; - - fstrcpy(u.ut_id, tt); - u.ut_time = time((time_t*)0); - } - - fstrcpy(u.ut_user, "LOGIN"); - fstrcpy(u.ut_line, VT_Line); - u.ut_pid = getpid(); - u.ut_type = LOGIN_PROCESS; - pututline(&u); - - endutent(); - - return(0); -} - - -/* -VT_Stop_utmp: prepare /etc/utmp for other processes -*/ -int VT_Stop_utmp(void) -{ - struct utmp u, *v; - - - if(VT_Line != NULL) { - setutent(); - - fstrcpy(u.ut_line, VT_Line); - - if((v = getutline(&u)) != NULL) { - fstrcpy(v->ut_user, ""); - v->ut_type = DEAD_PROCESS; - v->ut_time = time((time_t*)0); - pututline(v); - } - - endutent(); - } - - return(0); -} - - -/* -VT_AtExit: Things to do when the program exits -*/ -void VT_AtExit(void) -{ - if(VT_ChildPID > 0) { - kill(VT_ChildPID, SIGHUP); - (void)wait(NULL); - } - - VT_Stop_utmp(); -} - - -/* -VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died -*/ -void VT_SigCLD(int sig) -{ - if(wait(NULL) == VT_ChildPID) - VT_ChildDied = True; - else - CatchSignal(SIGCLD, VT_SigCLD); -} - - -/* -VT_SigEXIT: signalhandler for signals that cause the process to exit -*/ -void VT_SigEXIT(int sig) -{ - VT_AtExit(); - - exit(1); -} - - -/* -VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK -*/ -int VT_Start(void) -{ - char OutBuf [64], *X, *Y; - - - ms_type = MS_NONE; - master = slave = -1; - -#ifdef HAS_VTY -#ifdef LINUX -# define MASTER_TMPL "/dev/pty " -# define SLAVE_TMPL "/dev/tty " -# define LETTER1 "pqrs" -# define POS1 8 -# define LETTER2 "0123456789abcdef" -# define POS2 9 -#endif - -#ifdef SCO -# define MASTER_TMPL "/dev/ptyp_ " -# define SLAVE_TMPL "/dev/ttyp_ " -# define LETTER1 "0123456" -# define POS1 10 -# define LETTER2 "0123456789abcdef" -# define POS2 11 -#endif - - if(ms_poll == MS_VTY || ms_poll == 0) { - fstrcpy(master_name, MASTER_TMPL); - fstrcpy(slave_name, SLAVE_TMPL); - - for(X = LETTER1; *X && master < 0; X++) - for(Y = LETTER2; *Y && master < 0; Y++) { - master_name [POS1] = *X; - master_name [POS2] = *Y; - if((master = open(master_name, O_RDWR)) >= 0) { - slave_name [POS1] = *X; - slave_name [POS2] = *Y; - if((slave = open(slave_name, O_RDWR)) < 0) - close(master); - } - } - - if(master >= 0 && slave >= 0) - ms_type = MS_VTY; - } - -# undef MASTER_TMPL -# undef SLAVE_TMPL -# undef LETTER1 -# undef LETTER2 -# undef POS1 -# undef POS2 -#endif - - -#ifdef HAS_PTY -#ifdef SCO -# define MASTER_TMPL "/dev/ptyp%d" -# define SLAVE_TMPL "/dev/ttyp%d" -# define MIN_I 0 -# define MAX_I 63 -#endif - - if(ms_poll == MS_PTY || ms_poll == 0) { - int i; - - for(i = MIN_I; i <= MAX_I && master < 0; i++) { - slprintf(master_name, sizeof(fstring) - 1, MASTER_TMPL, i); - if((master = open(master_name, O_RDWR)) >= 0) { - slprintf(slave_name, sizeof(fstring) - 1, SLAVE_TMPL, i); - if((slave = open(slave_name, O_RDWR)) < 0) - close(master); - } - } - - if(master >= 0 && slave >= 0) - ms_type = MS_PTY; - } - -# undef MASTER_TMPL -# undef SLAVE_TMPL -# undef MIN_I -# undef MAX_I -#endif - - - if(! ms_type) - return(-1); - - VT_Line = strdup(strrchr(slave_name, '/') + 1); - - switch((VT_ChildPID = fork())) { - case -1: - return(-1); - break; - - case 0: -#ifdef SCO - setsid(); -#endif - close(0); - close(1); - close(2); - - i = open(slave_name, O_RDWR); - o = open(slave_name, O_RDWR); - e = open(slave_name, O_RDWR); - -#ifdef LINUX - setsid(); - if (ioctl(slave, TIOCSCTTY, (char *)NULL) == -1) - exit(1); -#endif -#ifdef SCO - tcsetpgrp(0, getpid()); -#endif - - VT_Start_utmp(); - - system("stty sane"); - execlp("/bin/login", "login", "-c", (char*)0); - exit(1); - break; - - default: - VT_Mode = True; - VT_Status = VT_OPEN; - VT_ChildDied = False; - VT_Fd = master; - - CatchSignal(SIGCLD, VT_SigCLD); - - CatchSignal(SIGHUP, VT_SigEXIT); - CatchSignal(SIGTERM, VT_SigEXIT); - CatchSignal(SIGINT, VT_SigEXIT); - CatchSignal(SIGQUIT, VT_SigEXIT); - - memset(OutBuf, 0, sizeof(OutBuf)); - OutBuf [4] = 0x06; - _smb_setlen(OutBuf, 1); - - send_smb(Client,OutBuf); - - return(0); - break; - } -} - - -/* -VT_Output: transport data from socket to pty -*/ -int VT_Output(char *Buffer) -{ - int i, len, nb; - - - if(VT_Status != VT_OPEN) - return(-1); - - len = smb_len(Buffer); - - nb = write(VT_Fd, Buffer + 4, len); - - return((nb == len) ? 0 : -1); -} - - -/* -VT_Input: transport data from pty to socket -*/ -int VT_Input(char *Buffer,int Size) -{ - int len; - - - if(VT_Status != VT_OPEN) - return(-1); - - memset(Buffer, 0, Size); - len = read(VT_Fd, Buffer + 4, MIN(VT_MAXREAD, Size)); - - _smb_setlen(Buffer, len); - - return(len + 4); -} - - -/* -VT_Process: main loop while in vt-mode -*/ -void VT_Process(void) -{ - static int trans_num = 0; - extern int Client; - int nread; - - - VT_Start(); - - atexit(VT_AtExit); - - while (True) { - int32 len; - int msg_type; - int msg_flags; - int counter; - int last_keepalive=0; - struct fd_set si; - struct timeval to, *top; - int n, ret, t; - - - errno = 0; - t = SMBD_SELECT_LOOP*1000; - - - FD_ZERO(&si); - FD_SET(Client, &si); - - FD_SET(VT_Fd, &si); - - if(t >= 0) { - to.tv_sec = t / 1000; - to.tv_usec = t - (to.tv_sec * 1000); - - top = &to; - } else - top = NULL; - - if(VT_ChildDied) - goto leave_VT_Process; - - n = select(MAX(VT_Fd, Client) + 1, &si, NULL, NULL, top); - - if(VT_ChildDied) - goto leave_VT_Process; - - if(n == 0) { - int i; - time_t t; - BOOL allidle = True; - extern int keepalive; - - counter += SMBD_SELECT_LOOP; - - t = time(NULL); - - if (keepalive && (counter-last_keepalive)>keepalive) { - if (!send_keepalive(Client)) - goto leave_VT_Process; - last_keepalive = counter; - } - } else if(n > 0) { - counter = 0; - - if(FD_ISSET(VT_Fd, &si)) { - /* got input from vt */ - nread = VT_Input(OutBuffer, MIN(BUFFER_SIZE,lp_maxxmit())); - - if(nread > 0) - send_smb(Client,OutBuffer); - } - - if(FD_ISSET(Client, &si)) { - /* got input from socket */ - - if(receive_smb(Client,InBuffer, 0)) { - msg_type = CVAL(InBuffer,0); - msg_flags = CVAL(InBuffer,1); - - len = smb_len(InBuffer); - - DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); - - nread = len + 4; - - DEBUG( 3, ("Transaction %d of length %d\n", trans_num, nread ) ); - - if(msg_type == 0) - VT_Output(InBuffer); - else { - nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit())); - - if(nread > 0) { - if (nread != smb_len(OutBuffer) + 4) { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, - smb_len(OutBuffer))); - } else - send_smb(Client,OutBuffer); - } - } - } else - if(errno == EBADF) - goto leave_VT_Process; - } - } - - trans_num++; - } - - leave_VT_Process: -/* - if(VT_ChildPID > 0) - kill(VT_ChildPID, SIGHUP); - - VT_Stop_utmp(VT_Line); - return; -*/ - close_sockets(); - exit(0); -} -- cgit From fa88efbbacbbe74b72ddb9e316265de2aab31260 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Aug 1998 07:04:53 +0000 Subject: split the system password checking routines out of smbd/password.c and into passdb/pass_check.c. This means SWAT no longer needs to link to smbd/password.c (This used to be commit 90d93889d722670cbb517017531264630af759bf) --- source3/smbd/password.c | 1182 ++++++----------------------------------------- source3/smbd/server.c | 3 +- 2 files changed, 143 insertions(+), 1042 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0f8e33940f..055c53d009 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -36,11 +36,6 @@ static pstring session_users=""; extern pstring global_myname; extern fstring global_myworkgroup; -/* these are kept here to keep the string_combinations function simple */ -static char this_user[100]=""; -static char this_salt[100]=""; -static char this_crypted[100]=""; - /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; static BOOL challenge_sent=False; @@ -305,779 +300,36 @@ void add_session_user(char *user) } -#ifdef OSF1_ENH_SEC -/**************************************************************************** -an enhanced crypt for OSF1 -****************************************************************************/ -static char *osf1_bigcrypt(char *password,char *salt1) -{ - static char result[AUTH_MAX_PASSWD_LENGTH] = ""; - char *p1; - char *p2=password; - char salt[3]; - int i; - int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS; - if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS) - parts++; - - StrnCpy(salt,salt1,2); - StrnCpy(result,salt1,2); - - for (i=0; iufld.fd_slogin = starttime; - mypasswd->ufld.fd_nlogins = 0; - - putprpwnam(user,mypasswd); - - DEBUG(3,("Update protected database for Account %s after succesful connection\n",user)); - } - else - { - mypasswd->ufld.fd_ulogin = starttime; - mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1; - if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries ) - { - mypasswd->uflg.fg_lock = 0; - DEBUG(3,("Account is disabled -- see Account Administrator.\n")); - } - putprpwnam ( user , mypasswd ); - DEBUG(3,("Update protected database for Account %s after refusing connection\n",user)); - } -#else - DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result))); -#endif -} - - -#ifdef HAVE_PAM -/******************************************************************* -check on PAM authentication -********************************************************************/ - -/* We first need some helper functions */ -#include -/* Static variables used to communicate between the conversation function - * and the server_login function - */ -static char *PAM_username; -static char *PAM_password; - -/* PAM conversation function - * Here we assume (for now, at least) that echo on means login name, and - * echo off means password. - */ -static int PAM_conv (int num_msg, - const struct pam_message **msg, - struct pam_response **resp, - void *appdata_ptr) { - int replies = 0; - struct pam_response *reply = NULL; - - #define COPY_STRING(s) (s) ? strdup(s) : NULL - - reply = malloc(sizeof(struct pam_response) * num_msg); - if (!reply) return PAM_CONV_ERR; - - for (replies = 0; replies < num_msg; replies++) { - switch (msg[replies]->msg_style) { - case PAM_PROMPT_ECHO_ON: - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = COPY_STRING(PAM_username); - /* PAM frees resp */ - break; - case PAM_PROMPT_ECHO_OFF: - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = COPY_STRING(PAM_password); - /* PAM frees resp */ - break; - case PAM_TEXT_INFO: - /* fall through */ - case PAM_ERROR_MSG: - /* ignore it... */ - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = NULL; - break; - default: - /* Must be an error of some sort... */ - free (reply); - return PAM_CONV_ERR; - } - } - if (reply) *resp = reply; - return PAM_SUCCESS; -} -static struct pam_conv PAM_conversation = { - &PAM_conv, - NULL -}; - - -static BOOL pam_auth(char *this_user,char *password) +BOOL update_smbpassword_file(char *user, char *password) { - pam_handle_t *pamh; - int pam_error; - - /* Now use PAM to do authentication. For now, we won't worry about - * session logging, only authentication. Bail out if there are any - * errors. Since this is a limited protocol, and an even more limited - * function within a server speaking this protocol, we can't be as - * verbose as would otherwise make sense. - * Query: should we be using PAM_SILENT to shut PAM up? - */ - #define PAM_BAIL if (pam_error != PAM_SUCCESS) { \ - pam_end(pamh, 0); return False; \ - } - PAM_password = password; - PAM_username = this_user; - pam_error = pam_start("samba", this_user, &PAM_conversation, &pamh); - PAM_BAIL; -/* Setting PAM_SILENT stops generation of error messages to syslog - * to enable debugging on Red Hat Linux set: - * /etc/pam.d/samba: - * auth required /lib/security/pam_pwdb.so nullok shadow audit - * _OR_ change PAM_SILENT to 0 to force detailed reporting (logging) - */ - pam_error = pam_authenticate(pamh, PAM_SILENT); - PAM_BAIL; - /* It is not clear to me that account management is the right thing - * to do, but it is not clear that it isn't, either. This can be - * removed if no account management should be done. Alternately, - * put a pam_allow.so entry in /etc/pam.conf for account handling. */ - pam_error = pam_acct_mgmt(pamh, PAM_SILENT); - PAM_BAIL; - pam_end(pamh, PAM_SUCCESS); - /* If this point is reached, the user has been authenticated. */ - return(True); -} -#endif - - -#ifdef WITH_AFS -/******************************************************************* -check on AFS authentication -********************************************************************/ -static BOOL afs_auth(char *this_user,char *password) -{ - long password_expires = 0; - char *reason; - - /* For versions of AFS prior to 3.3, this routine has few arguments, */ - /* but since I can't find the old documentation... :-) */ - setpag(); - if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG, - this_user, - (char *) 0, /* instance */ - (char *) 0, /* cell */ - password, - 0, /* lifetime, default */ - &password_expires, /*days 'til it expires */ - 0, /* spare 2 */ - &reason) == 0) - return(True); - return(False); -} -#endif - - -#ifdef WITH_DFS - -/***************************************************************** - This new version of the DFS_AUTH code was donated by Karsten Muuss - . It fixes the following problems with the - old code : - - - Server credentials may expire - - Client credential cache files have wrong owner - - purge_context() function is called with invalid argument - - This new code was modified to ensure that on exit the uid/gid is - still root, and the original directory is restored. JRA. -******************************************************************/ - -sec_login_handle_t my_dce_sec_context; -int dcelogin_atmost_once = 0; - -/******************************************************************* -check on a DCE/DFS authentication -********************************************************************/ -static BOOL dfs_auth(char *this_user,char *password) -{ - error_status_t err; - int err2; - int prterr; - signed32 expire_time, current_time; - boolean32 password_reset; - struct passwd *pw; - sec_passwd_rec_t passwd_rec; - sec_login_auth_src_t auth_src = sec_login_auth_src_network; - unsigned char dce_errstr[dce_c_error_string_len]; - - if (dcelogin_atmost_once) return(False); - -#ifdef HAVE_CRYPT - /* - * We only go for a DCE login context if the given password - * matches that stored in the local password file.. - * Assumes local passwd file is kept in sync w/ DCE RGY! - */ - - if ( strcmp((char *)crypt(password,this_salt),this_crypted) ) - return(False); -#endif - - sec_login_get_current_context(&my_dce_sec_context, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't get current context. %s\n", dce_errstr)); - - return(False); - } - - sec_login_certify_identity(my_dce_sec_context, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't get current context. %s\n", dce_errstr)); - - return(False); - } - - sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't get expiration. %s\n", dce_errstr)); - - return(False); - } - - time(¤t_time); - - if (expire_time < (current_time + 60)) { - struct passwd *pw; - sec_passwd_rec_t *key; - - sec_login_get_pwent(my_dce_sec_context, - (sec_login_passwd_t*)&pw, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); - - return(False); - } - - sec_login_refresh_identity(my_dce_sec_context, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't refresh identity. %s\n", dce_errstr)); - - return(False); - } - - sec_key_mgmt_get_key(rpc_c_authn_dce_secret, NULL, - (unsigned char *)pw->pw_name, - sec_c_key_version_none, - (void**)&key, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't get key for %s. %s\n", pw->pw_name, dce_errstr)); - - return(False); - } - - sec_login_valid_and_cert_ident(my_dce_sec_context, key, - &password_reset, &auth_src, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't validate and certify identity for %s. %s\n", - pw->pw_name, dce_errstr)); - } - - sec_key_mgmt_free_key(key, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't free key.\n", dce_errstr)); - } - } - - if (sec_login_setup_identity((unsigned char *)this_user, - sec_login_no_flags, - &my_dce_sec_context, - &err) == 0) - - { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE Setup Identity for %s failed: %s\n", - this_user,dce_errstr)); - return(False); - } - - sec_login_get_pwent(my_dce_sec_context, - (sec_login_passwd_t*)&pw, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); - - return(False); - } - - sec_login_purge_context(&my_dce_sec_context, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't purge context. %s\n", dce_errstr)); - - return(False); - } - - /* - * NB. I'd like to change these to call something like become_user() - * instead but currently we don't have a connection - * context to become the correct user. This is already - * fairly platform specific code however, so I think - * this should be ok. I have added code to go - * back to being root on error though. JRA. - */ - - if (setregid(-1, pw->pw_gid) != 0) { - DEBUG(0,("Can't set egid to %d (%s)\n", pw->pw_gid, strerror(errno))); - return False; - } - - if (setreuid(-1, pw->pw_uid) != 0) { - setgid(0); - DEBUG(0,("Can't set euid to %d (%s)\n", pw->pw_uid, strerror(errno))); - return False; - } - - if (sec_login_setup_identity((unsigned char *)this_user, - sec_login_no_flags, - &my_dce_sec_context, - &err) == 0) - - { - dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - DEBUG(0,("DCE Setup Identity for %s failed: %s\n", - this_user,dce_errstr)); - return(False); - } - - sec_login_get_pwent(my_dce_sec_context, - (sec_login_passwd_t*)&pw, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); - - return(False); - } - - passwd_rec.version_number = sec_passwd_c_version_none; - passwd_rec.pepper = NULL; - passwd_rec.key.key_type = sec_passwd_plain; - passwd_rec.key.tagged_union.plain = (idl_char *)password; - - sec_login_validate_identity(my_dce_sec_context, - &passwd_rec, &password_reset, - &auth_src, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n", - this_user,dce_errstr)); - - return(False); - } - - sec_login_certify_identity(my_dce_sec_context, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - DEBUG(0,("DCE certify identity failed: %s\n", dce_errstr)); - - return(False); - } - - if (auth_src != sec_login_auth_src_network) { - DEBUG(0,("DCE context has no network credentials.\n")); - } - - sec_login_set_context(my_dce_sec_context, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n", - this_user,dce_errstr)); - - sec_login_purge_context(&my_dce_sec_context, &err); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - return(False); - } - - sec_login_get_pwent(my_dce_sec_context, - (sec_login_passwd_t*)&pw, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); - - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - return(False); - } - - DEBUG(0,("DCE login succeeded for principal %s on pid %d\n", - this_user, getpid())); - - DEBUG(3,("DCE principal: %s\n" - " uid: %d\n" - " gid: %d\n", - pw->pw_name, pw->pw_uid, pw->pw_gid)); - DEBUG(3,(" info: %s\n" - " dir: %s\n" - " shell: %s\n", - pw->pw_gecos, pw->pw_dir, pw->pw_shell)); - - sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); - if (err != error_status_ok ) { - dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - DEBUG(0,("DCE can't get expiration. %s\n", dce_errstr)); - - return(False); - } - - setuid(0); - setgid(0); - - DEBUG(0,("DCE context expires: %s",asctime(localtime(&expire_time)))); - - dcelogin_atmost_once = 1; - return (True); -} - -void dfs_unlogin(void) -{ - error_status_t err; - int err2; - unsigned char dce_errstr[dce_c_error_string_len]; - - sec_login_purge_context(&my_dce_sec_context, &err); - if (err != error_status_ok ) - { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE purge login context failed for server instance %d: %s\n", - getpid(), dce_errstr)); - } -} -#endif - -#ifdef KRB5_AUTH -/******************************************************************* -check on Kerberos authentication -********************************************************************/ -static BOOL krb5_auth(char *this_user,char *password) -{ - krb5_data tgtname = { - 0, - KRB5_TGS_NAME_SIZE, - KRB5_TGS_NAME - }; - krb5_context kcontext; - krb5_principal kprinc; - krb5_principal server; - krb5_creds kcreds; - int options = 0; - krb5_address **addrs = (krb5_address **)0; - krb5_preauthtype *preauth = NULL; - krb5_keytab keytab = NULL; - krb5_timestamp now; - krb5_ccache ccache = NULL; - int retval; - char *name; - - if ( retval=krb5_init_context(&kcontext)) - { - return(False); - } - - if ( retval = krb5_timeofday(kcontext, &now) ) - { - return(False); - } - - if ( retval = krb5_cc_default(kcontext, &ccache) ) - { - return(False); - } + struct smb_passwd *smbpw; + BOOL ret; - if ( retval = krb5_parse_name(kcontext, this_user, &kprinc) ) - { - return(False); - } - - memset((char *)&kcreds, 0, sizeof(kcreds)); - - kcreds.client = kprinc; + become_root(0); + smbpw = getsmbpwnam(user); + unbecome_root(0); - if ((retval = krb5_build_principal_ext(kcontext, &server, - krb5_princ_realm(kcontext, kprinc)->length, - krb5_princ_realm(kcontext, kprinc)->data, - tgtname.length, - tgtname.data, - krb5_princ_realm(kcontext, kprinc)->length, - krb5_princ_realm(kcontext, kprinc)->data, - 0))) - { - return(False); + if(smbpw == NULL) { + DEBUG(0,("getsmbpwnam returned NULL\n")); + return False; } - - kcreds.server = server; - - retval = krb5_get_in_tkt_with_password(kcontext, - options, - addrs, - NULL, - preauth, - password, - 0, - &kcreds, - 0); - - if ( retval ) - { - return(False); + + /* Here, the flag is one, because we want to ignore the + XXXXXXX'd out password */ + ret = change_oem_password( smbpw, password, True); + if (ret == False) { + DEBUG(3,("change_oem_password returned False\n")); } - return(True); -} -#endif /* KRB5_AUTH */ - -#ifdef KRB4_AUTH -/******************************************************************* -check on Kerberos authentication -********************************************************************/ -static BOOL krb4_auth(char *this_user,char *password) -{ - char realm[REALM_SZ]; - char tkfile[MAXPATHLEN]; - - if (krb_get_lrealm(realm, 1) != KSUCCESS) - (void) safe_strcpy(realm, KRB_REALM, sizeof (realm) - 1); - - (void) slprintf(tkfile, sizeof(tkfile) - 1, "/tmp/samba_tkt_%d", getpid()); - - krb_set_tkt_string(tkfile); - if (krb_verify_user(this_user, "", realm, - password, 0, - "rmcd") == KSUCCESS) { - unlink(tkfile); - return 1; - } - unlink(tkfile); - return 0; -} -#endif /* KRB4_AUTH */ - -#ifdef LINUX_BIGCRYPT -/**************************************************************************** -an enhanced crypt for Linux to handle password longer than 8 characters -****************************************************************************/ -static int linux_bigcrypt(char *password,char *salt1, char *crypted) -{ -#define LINUX_PASSWORD_SEG_CHARS 8 - char salt[3]; - int i; - - StrnCpy(salt,salt1,2); - crypted +=2; - - for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { - char * p = crypt(password,salt) + 2; - if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) - return(0); - password += LINUX_PASSWORD_SEG_CHARS; - crypted += strlen(p); - } - - return(1); + return ret; } -#endif - - -/**************************************************************************** -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 BOOL string_combinations2(char *s,int offset,BOOL (*fn)(char *),int N) -{ - int len = strlen(s); - int i; - -#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); - if (string_combinations2(s,i+1,fn,N-1)) - return(True); - s[i] = c; - } - return(False); -} - -/**************************************************************************** -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 BOOL string_combinations(char *s,BOOL (*fn)(char *),int N) -{ - int n; - for (n=1;n<=N;n++) - if (string_combinations2(s,0,fn,n)) return(True); - return(False); -} - - - -/**************************************************************************** -core of password checking routine -****************************************************************************/ -BOOL password_check(char *password) -{ - -#ifdef HAVE_PAM -/* This falls through if the password check fails - - if HAVE_CRYPT is not defined this causes an error msg - saying Warning - no crypt available - - if HAVE_CRYPT is defined this is a potential security hole - as it may authenticate via the crypt call when PAM - settings say it should fail. - if (pam_auth(this_user,password)) return(True); - Hence we make a direct return to avoid a second chance!!! -*/ - return (pam_auth(this_user,password)); -#endif - -#ifdef WITH_AFS - if (afs_auth(this_user,password)) return(True); -#endif -#ifdef WITH_DFS - if (dfs_auth(this_user,password)) return(True); -#endif -#ifdef KRB5_AUTH - if (krb5_auth(this_user,password)) return(True); -#endif -#ifdef KRB4_AUTH - if (krb4_auth(this_user,password)) return(True); -#endif -#ifdef OSF1_ENH_SEC - { - BOOL ret = (strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0); - if(!ret) { - DEBUG(2,("password_check: OSF1_ENH_SEC failed. Trying normal crypt.\n")); - ret = (strcmp((char *)crypt(password,this_salt),this_crypted) == 0); - } - return ret; - } -#endif - -#ifdef ULTRIX_AUTH - return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0); -#endif - -#ifdef LINUX_BIGCRYPT - return(linux_bigcrypt(password,this_salt,this_crypted)); -#endif - -#ifdef HAVE_BIGCRYPT - return(strcmp(bigcrypt(password,this_salt),this_crypted) == 0); -#endif - -#ifndef HAVE_CRYPT - DEBUG(1,("Warning - no crypt available\n")); - return(False); -#else - return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0); -#endif -} /**************************************************************************** core of smb password checking routine. @@ -1125,327 +377,175 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ - BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar lm_pass[24], uchar nt_pass[24]) { - uchar challenge[8]; + uchar challenge[8]; - if (!lm_pass || !smb_pass) return(False); + if (!lm_pass || !smb_pass) return(False); - if(smb_pass->acct_ctrl & ACB_DISABLED) - { - DEBUG(3,("smb_password_ok: account for user %s was disabled.\n", smb_pass->smb_name)); - return(False); - } - - if (!last_challenge(challenge)) - { - DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); - return False; - } + if(smb_pass->acct_ctrl & ACB_DISABLED) { + DEBUG(3,("account for user %s was disabled.\n", + smb_pass->smb_name)); + return(False); + } - DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n", smb_pass->smb_name)); + if (!last_challenge(challenge)) { + DEBUG(1,("no challenge done - password failed\n")); + return False; + } - if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) - { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_password_check((char *)nt_pass, (uchar *)smb_pass->smb_nt_passwd, challenge)) - { - DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); - return(True); - } - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); - } + DEBUG(4,("Checking SMB password for user %s\n", + smb_pass->smb_name)); + + if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_password_check((char *)nt_pass, + (uchar *)smb_pass->smb_nt_passwd, + challenge)) { + DEBUG(4,("NT MD4 password check succeeded\n")); + return(True); + } + DEBUG(4,("NT MD4 password check failed\n")); + } - /* Try against the lanman password. smb_pass->smb_passwd == NULL means - no password, allow access. */ + /* Try against the lanman password. smb_pass->smb_passwd == NULL means + no password, allow access. */ - DEBUG(4,("Checking LM MD4 password\n")); + DEBUG(4,("Checking LM MD4 password\n")); - if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ)) - { - DEBUG(4,("smb_password_ok: no password required for user %s\n", smb_pass->smb_name)); - return True; - } + if((smb_pass->smb_passwd == NULL) && + (smb_pass->acct_ctrl & ACB_PWNOTREQ)) { + DEBUG(4,("no password required for user %s\n", + smb_pass->smb_name)); + return True; + } - if((smb_pass->smb_passwd != NULL) && smb_password_check((char *)lm_pass, (uchar *)smb_pass->smb_passwd, challenge)) - { - DEBUG(4,("smb_password_ok: LM MD4 password check succeeded\n")); - return(True); - } + if((smb_pass->smb_passwd != NULL) && + smb_password_check((char *)lm_pass, + (uchar *)smb_pass->smb_passwd, challenge)) { + DEBUG(4,("LM MD4 password check succeeded\n")); + return(True); + } - DEBUG(4,("smb_password_ok: LM MD4 password check failed\n")); + DEBUG(4,("LM MD4 password check failed\n")); - return False; + return False; } + /**************************************************************************** -check if a username/password is OK +check if a username/password is OK assuming the password is a 24 byte +SMB hash +return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) +static BOOL pass_check_smb(char *user,char *password, struct passwd *pwd) { - pstring pass2; - int level = lp_passwordlevel(); - struct passwd *pass; - uchar challenge[8]; - struct smb_passwd *smb_pass; - BOOL update_encrypted = lp_update_encrypted(); - BOOL challenge_done = False; + struct passwd *pass; + uchar challenge[8]; + struct smb_passwd *smb_pass; + BOOL challenge_done; - if (password) password[pwlen] = 0; - - if (pwlen == 24) - challenge_done = last_challenge(challenge); - -#if DEBUG_PASSWORD - if (challenge_done) - { - int i; - DEBUG(100,("checking user=[%s] pass=[",user)); - for( i = 0; i < 24; i++) - DEBUG(100,("%0x ", (unsigned char)password[i])); - DEBUG(100,("]\n")); - } else { - DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); - } -#endif - - if (!password) - return(False); - - if (((!*password) || (!pwlen)) && !lp_null_passwords()) - return(False); - - if (pwd && !user) - { - pass = (struct passwd *) pwd; - user = pass->pw_name; - } - else - pass = Get_Pwnam(user,True); - - DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); + if (!password) { + return(False); + } - if ((pwlen == 24) && challenge_done) - { - DEBUG(4,("Checking SMB password for user %s (l=24)\n",user)); + challenge_done = last_challenge(challenge); - if (!pass) - { - DEBUG(3,("Couldn't find user %s\n",user)); - return(False); + if (!challenge_done) { + DEBUG(0,("Error: challenge not done for user=%s\n", user)); + return False; } - smb_pass = getsmbpwnam(user); + if (pwd && !user) { + pass = (struct passwd *) pwd; + user = pass->pw_name; + } else { + pass = Get_Pwnam(user,True); + } - if (!smb_pass) - { - DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); - return(False); + if (!pass) { + DEBUG(3,("Couldn't find user %s\n",user)); + return(False); } - /* Quit if the account was disabled. */ - if(smb_pass->acct_ctrl & ACB_DISABLED) - { - DEBUG(3,("password_ok: account for user %s was disabled.\n", user)); - return(False); - } + smb_pass = getsmbpwnam(user); - /* Ensure the uid's match */ - if (smb_pass->smb_userid != pass->pw_uid) - { - DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); - return(False); + if (!smb_pass) { + DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); + return(False); } - if(smb_password_ok( smb_pass, (unsigned char *)password,(uchar *)password)) - { - update_protected_database(user,True); - return(True); + /* Quit if the account was disabled. */ + if(smb_pass->acct_ctrl & ACB_DISABLED) { + DEBUG(3,("account for user %s was disabled.\n", user)); + return(False); } - DEBUG(3,("Error smb_password_check failed\n")); - } - - DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); - - if (!pass) - { - DEBUG(3,("Couldn't find user %s\n",user)); - return(False); - } - -#ifdef HAVE_GETSPNAM - { - struct spwd *spass; - - /* many shadow systems require you to be root to get the password, - in most cases this should already be the case when this - function is called, except perhaps for IPC password changing - requests */ - - spass = getspnam(pass->pw_name); - if (spass && spass->sp_pwdp) - pass->pw_passwd = spass->sp_pwdp; - } -#elif defined(IA_UINFO) - { - /* Need to get password with SVR4.2's ia_ functions instead of - get{sp,pw}ent functions. Required by UnixWare 2.x, tested on - version 2.1. (tangent@cyberport.com) */ - uinfo_t uinfo; - if (ia_openinfo(pass->pw_name, &uinfo) != -1) - ia_get_logpwd(uinfo, &(pass->pw_passwd)); - } -#endif - -#ifdef HAVE_GETPRPWNAM - { - struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); - if (pr_pw && pr_pw->ufld.fd_encrypt) - pass->pw_passwd = pr_pw->ufld.fd_encrypt; - } -#endif - -#ifdef OSF1_ENH_SEC - { - struct pr_passwd *mypasswd; - DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user)); - mypasswd = getprpwnam (user); - if ( mypasswd ) - { - fstrcpy(pass->pw_name,mypasswd->ufld.fd_name); - fstrcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt); - } - else - { - DEBUG(5,("No entry for user %s in protected database !\n",user)); - return(False); - } - } -#endif - -#ifdef ULTRIX_AUTH - { - AUTHORIZATION *ap = getauthuid( pass->pw_uid ); - if (ap) - { - fstrcpy( pass->pw_passwd, ap->a_password ); - endauthent(); - } - } -#endif - - /* extract relevant info */ - fstrcpy(this_user,pass->pw_name); - fstrcpy(this_salt,pass->pw_passwd); - /* crypt on some platforms (HPUX in particular) - won't work with more than 2 salt characters. */ - this_salt[2] = 0; - - fstrcpy(this_crypted,pass->pw_passwd); - - if (!*this_crypted) { - if (!lp_null_passwords()) { - DEBUG(2,("Disallowing access to %s due to null password\n",this_user)); - return(False); - } - if (!*password) { - DEBUG(3,("Allowing access to %s with null password\n",this_user)); - return(True); - } - } - - /* try it as it came to us */ - if (password_check(password)) - { - update_protected_database(user,True); - if (update_encrypted) - update_smbpassword_file(user,password); - return(True); - } - - /* if the password was given to us with mixed case then we don't - need to proceed as we know it hasn't been case modified by the - client */ - if (strhasupper(password) && strhaslower(password)) - return(False); - - /* make a copy of it */ - StrnCpy(pass2,password,sizeof(pstring)-1); - - /* try all lowercase */ - strlower(password); - if (password_check(password)) - { - update_protected_database(user,True); - if (update_encrypted) - update_smbpassword_file(user,password); - return(True); - } - - /* give up? */ - if (level < 1) - { - update_protected_database(user,False); - - /* restore it */ - fstrcpy(password,pass2); - - return(False); - } - - /* last chance - all combinations of up to level chars upper! */ - strlower(password); - - if (string_combinations(password,password_check,level)) - { - update_protected_database(user,True); - if (update_encrypted) - update_smbpassword_file(user,password); - return(True); - } + /* Ensure the uid's match */ + if (smb_pass->smb_userid != pass->pw_uid) { + DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); + return(False); + } - update_protected_database(user,False); - - /* restore it */ - fstrcpy(password,pass2); - - return(False); + if (smb_password_ok(smb_pass, + (unsigned char *)password, + (uchar *)password)) { + return(True); + } + + DEBUG(3,("Error smb_password_check failed\n")); + return False; } - +/**************************************************************************** +check if a username/password pair is OK either via the system password +database or the encrypted SMB password database +return True if the password is correct, False otherwise +****************************************************************************/ +BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) +{ + if (pwlen == 24) { + /* if it is 24 bytes long then assume it is an encrypted + password */ + return pass_check_smb(user, password, pwd); + } + + return pass_check(user, password, pwlen, pwd, + lp_update_encrypted() ? + update_smbpassword_file : NULL); +} /**************************************************************************** check if a username is valid ****************************************************************************/ BOOL user_ok(char *user,int snum) { - pstring valid, invalid; - BOOL ret; - - StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)); - StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)); + pstring valid, invalid; + BOOL ret; - string_sub(valid,"%S",lp_servicename(snum)); - string_sub(invalid,"%S",lp_servicename(snum)); + StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)); + StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)); - ret = !user_in_list(user,invalid); - - if (ret && valid && *valid) - ret = user_in_list(user,valid); + string_sub(valid,"%S",lp_servicename(snum)); + string_sub(invalid,"%S",lp_servicename(snum)); + + ret = !user_in_list(user,invalid); + + if (ret && valid && *valid) { + ret = user_in_list(user,valid); + } - if (ret && lp_onlyuser(snum)) { - char *user_list = lp_username(snum); - string_sub(user_list,"%S",lp_servicename(snum)); - ret = user_in_list(user,user_list); - } + if (ret && lp_onlyuser(snum)) { + char *user_list = lp_username(snum); + string_sub(user_list,"%S",lp_servicename(snum)); + ret = user_in_list(user,user_list); + } - return(ret); + return(ret); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 97c54cde04..8f9349f3fc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4426,8 +4426,9 @@ void exit_server(char *reason) if (Connections[i].open) close_cnum(i,(uint16)-1); #ifdef WITH_DFS - if (dcelogin_atmost_once) + if (dcelogin_atmost_once) { dfs_unlogin(); + } #endif if (!reason) { int oldlevel = DEBUGLEVEL; -- cgit From 670c6addc322e69b86975fc4024c88a885b63d9f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Aug 1998 07:29:57 +0000 Subject: moved access.c into lib/ from smbd/ as it is needed by testparm. I modified it not to need any smbd specific structures and instead pass things from smbd. (This used to be commit 162141d3b3fcf53fbc6a1f18702df85c2b7f1781) --- source3/smbd/server.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8f9349f3fc..47fb175d8e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2679,7 +2679,7 @@ static void process_smb(char *inbuf, char *outbuf) deny parameters before doing any parsing of the packet passed to us by the client. This prevents attacks on our parsing code from hosts not in the hosts allow list */ - if (!check_access(-1)) { + if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) { /* send a negative session response "not listining on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; @@ -3459,6 +3459,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de connection_struct *pcon; BOOL guest = False; BOOL force = False; + extern int Client; strlower(service); @@ -3503,7 +3504,8 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de } } - if (!lp_snum_ok(snum) || !check_access(snum)) { + if (!lp_snum_ok(snum) || + !check_access(Client, lp_hostsallow(snum), lp_hostsdeny(snum))) { return(-4); } @@ -4649,6 +4651,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize static int num_smb_messages = sizeof(smb_messages) / sizeof(struct smb_message_struct); int match; + extern int Client; #if PROFILING struct timeval msg_start_time; @@ -4756,8 +4759,11 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(ERROR(ERRSRV,ERRaccess)); /* does this protocol need to be run as guest? */ - if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1))) + if ((flags & AS_GUEST) && + (!become_guest() || + !check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1)))) { return(ERROR(ERRSRV,ERRaccess)); + } last_inbuf = inbuf; -- cgit From 17fb3a2304d3f9eaa314c90b476d153b5f333f31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Aug 1998 20:12:53 +0000 Subject: Makefile.in: Fixed make clean bug with CVS directory in bin/. include/smb.h: Fixed bugs in Debug macro's with SGI compiler. smbd/trans2.c: Fixed bug reported by Zoltan Palmai PR#8903 where get_lanman2_dir_entry() could return a mangled name as a resume key and call_trans2findnext() wasn't doing the same. Jeremy. (This used to be commit 9d010e721c27af1d9498fd1e147993ba8ac8b41e) --- source3/smbd/trans2.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7f34187bd6..84cd99c91f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -945,6 +945,16 @@ resume_key = %d resume name = %s continue=%d level = %d\n", SeekDir(dirptr, current_pos); dname = ReadDirName(dirptr); + + /* + * Remember, name_map_mangle is called by + * get_lanman2_dir_entry(), so the resume name + * could be mangled. Ensure we do the same + * here. + */ + + name_map_mangle( dname, False, SNUM(cnum)); + if(dname && strcsequal( resume_name, dname)) { SeekDir(dirptr, current_pos+1); @@ -963,6 +973,15 @@ resume_key = %d resume name = %s continue=%d level = %d\n", SeekDir(dirptr, start_pos); for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) { + /* + * Remember, name_map_mangle is called by + * get_lanman2_dir_entry(), so the resume name + * could be mangled. Ensure we do the same + * here. + */ + + name_map_mangle( dname, False, SNUM(cnum)); + if(strcsequal( resume_name, dname)) { SeekDir(dirptr, current_pos+1); -- cgit From 9042aa41c3c54e8dce600338cd4b796b65aaf066 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Aug 1998 02:13:01 +0000 Subject: Makefile.in: Added CHECK target back in (at Herb's request). Added manpath in (although we don't currently use it). client/client.c: Added John Blair's fixes for "put -". include/nterr.h: Added NT_STATUS_NOTIFY_ENUM_DIR error code. smbd/nttrans.c: Added in devious fix for one-shot NT change notify bug. Jeremy. (This used to be commit 4ac3091e57e9ab234b3c051333ba521a92defa99) --- source3/smbd/nttrans.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c6782cd45f..143bfc9a8b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "nterr.h" extern int DEBUGLEVEL; extern int Protocol; @@ -984,6 +985,17 @@ static void change_notify_reply_packet(char *inbuf, int error_class, uint32 erro construct_reply_common(inbuf, outbuf); + /* + * If we're returning a 'too much in the directory changed' we need to + * set this is an NT error status flags. If we don't then the (probably + * untested) code in the NT redirector has a bug in that it doesn't re-issue + * the change notify.... Ah - I *love* it when I get so deeply into this I + * can even determine how MS failed to test stuff and why.... :-). JRA. + */ + + if(error_class == 0 && error_code == NT_STATUS_NOTIFY_ENUM_DIR) + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + ERROR(error_class,error_code); send_smb(Client,outbuf); } @@ -1104,7 +1116,7 @@ Error was %s.\n", fsp->name, strerror(errno) )); */ DEBUG(5,("process_pending_change_notify_queue: directory fnum = %d, name = %s changed\n", fnum, fsp->name )); - change_notify_reply_packet(cnbp->request_buf,ERRDOS,ERROR_NOTIFY_ENUM_DIR); + change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); unbecome_user(); -- cgit From b1778b6b57401d78fb4352992fde54706af6b75f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Aug 1998 23:28:35 +0000 Subject: include/smb.h: Removed dir_ptr. Not needed. locking/locking.c: First cut a blocking lock code. #ifdef'ed out for now. locking/locking_shm.c: Removed dir_ptr. Not needed. smbd/nttrans.c: More work on ChangeNotify - return is not an error and needs to be handled as a nttrans with zero params. Removed dir_ptr. Not needed. smbd/reply.c: smbd/server.c: smbd/trans2.c: Removed dir_ptr. Not needed. Hmmm. At the moment smbclient is broken - doesn't issue prompt correctly. This needs looking at. Jeremy. (This used to be commit ddfbcc05815621d3c463f92faed047f126412342) --- source3/smbd/nttrans.c | 72 ++++++++++++++++++++++---------------------------- source3/smbd/reply.c | 55 +++++++++++++++++++++++--------------- source3/smbd/server.c | 53 ++++++++++++++++++------------------- source3/smbd/trans2.c | 8 +++--- 4 files changed, 95 insertions(+), 93 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 143bfc9a8b..8709b9c646 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -572,7 +572,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -801,7 +801,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); restore_case_semantics(file_attributes); @@ -969,6 +969,8 @@ typedef struct { int fnum; int cnum; time_t next_check_time; + time_t modify_time; /* Info from the directory we're monitoring. */ + time_t status_time; /* Info from the directory we're monitoring. */ char request_buf[smb_size]; } change_notify_buf; @@ -981,8 +983,9 @@ static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_qu static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) { extern int Client; - char outbuf[smb_size]; + char outbuf[smb_size+38]; + memset(outbuf, '\0', sizeof(outbuf)); construct_reply_common(inbuf, outbuf); /* @@ -993,10 +996,17 @@ static void change_notify_reply_packet(char *inbuf, int error_class, uint32 erro * can even determine how MS failed to test stuff and why.... :-). JRA. */ - if(error_class == 0 && error_code == NT_STATUS_NOTIFY_ENUM_DIR) + if(error_class == 0) /* NT Error. */ SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); ERROR(error_class,error_code); + + /* + * Seems NT needs a transact command with an error code + * in it. This is a longer packet than a simple error. + */ + set_message(outbuf,18,0,False); + send_smb(Client,outbuf); } @@ -1032,7 +1042,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) while(cnbp != NULL) { if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_CANCELLED); free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; @@ -1109,8 +1119,8 @@ Error was %s.\n", fsp->name, strerror(errno) )); continue; } - if(fsp->f_u.dir_ptr->modify_time != st.st_mtime || - fsp->f_u.dir_ptr->status_time != st.st_ctime) { + if(cnbp->modify_time != st.st_mtime || + cnbp->status_time != st.st_ctime) { /* * Remove the entry and return a change notify to the client. */ @@ -1160,40 +1170,6 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, if((!fsp->open) || (!fsp->is_directory) || (cnum != fsp->cnum)) return(ERROR(ERRDOS,ERRbadfid)); - if(fsp->f_u.dir_ptr == NULL) { - - /* - * No currently stored directory info - we must - * generate it here. - */ - - if((fsp->f_u.dir_ptr = (dir_status_struct *)malloc(sizeof(dir_status_struct))) == NULL) { - DEBUG(0,("call_nt_transact_notify_change: Malloc fail !\n" )); - return -1; - } - - /* - * Setup the current directory information in the - * directory entry in the files_struct. We will use - * this to check against when the timer expires. - * NB. We only do this if there is no current directory - * information in the directory struct - as when we start - * monitoring file size etc. this information will start - * becoming increasingly expensive to maintain, so we won't - * want to re-generate it for every ChangeNofity call. - */ - - if(sys_stat(fsp->name, &st) < 0) { - DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \ -Error was %s\n", fnum, fsp->name, strerror(errno) )); - return -1; - } - - fsp->f_u.dir_ptr->modify_time = st.st_mtime; - fsp->f_u.dir_ptr->status_time = st.st_ctime; - - } - /* * Now queue an entry on the notify change stack. We timestamp * the entry we are adding so that we know when to scan next. @@ -1207,9 +1183,23 @@ Error was %s\n", fnum, fsp->name, strerror(errno) )); return -1; } + /* + * Store the current timestamp on the directory we are monitoring. + */ + + if(sys_stat(fsp->name, &st) < 0) { + DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \ +Error was %s\n", fnum, fsp->name, strerror(errno) )); + free((char *)cnbp); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fnum = fnum; cnbp->cnum = cnum; + cnbp->modify_time = st.st_mtime; + cnbp->status_time = st.st_ctime; + cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2e6ceb93aa..b0509bf3d5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1320,7 +1320,7 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1425,7 +1425,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1603,7 +1603,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) DEBUG( 2, ( "new file %s\n", fname ) ); DEBUG( 3, ( "mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", - fname, fsp->f_u.fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); + fname, fsp->fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); return(outsize); } @@ -1682,7 +1682,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) DEBUG( 2, ( "created temp file %s\n", fname2 ) ); DEBUG( 3, ( "ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", - fname2, fsp->f_u.fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); + fname2, fsp->fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); return(outsize); } @@ -1865,7 +1865,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { fsp = &Files[fnum]; - fd = fsp->f_u.fd_ptr->fd; + fd = fsp->fd_ptr->fd; fname = fsp->name; } @@ -1877,7 +1877,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) if (size < sizeneeded) { struct stat st; - if (fstat(fsp->f_u.fd_ptr->fd,&st) == 0) + if (fstat(fsp->fd_ptr->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -2148,7 +2148,7 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) tcount,nwritten,numtowrite)); } - nwritten = transfer_file(Client,Files[fnum].f_u.fd_ptr->fd,numtowrite,NULL,0, + nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0, startpos+nwritten); total_written += nwritten; @@ -2265,7 +2265,7 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) - nwritten = set_filelen(Files[fnum].f_u.fd_ptr->fd, startpos); + nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos); else nwritten = write_file(fnum,data,numtowrite); @@ -2383,7 +2383,7 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) fsp = &Files[fnum]; - res = lseek(fsp->f_u.fd_ptr->fd,startpos,umode); + res = lseek(fsp->fd_ptr->fd,startpos,umode); fsp->pos = res; outsize = set_message(outbuf,2,0,True); @@ -2493,7 +2493,7 @@ int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) set_filetime(cnum, fsp->name,mtime); DEBUG( 3, ( "close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - fsp->f_u.fd_ptr->fd, fnum, cnum, + fsp->fd_ptr->fd, fnum, cnum, Connections[cnum].num_files_open ) ); close_file(fnum,True); @@ -2577,7 +2577,7 @@ int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) offset = IVAL(inbuf,smb_vwv3); DEBUG( 3, ("lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", - Files[fnum].f_u.fd_ptr->fd, fnum, cnum, offset, count ) ); + Files[fnum].fd_ptr->fd, fnum, cnum, offset, count ) ); if(!do_lock( fnum, cnum, count, offset, F_WRLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); @@ -2610,7 +2610,7 @@ int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) return (ERROR(eclass,ecode)); DEBUG( 3, ( "unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", - Files[fnum].f_u.fd_ptr->fd, fnum, cnum, offset, count ) ); + Files[fnum].fd_ptr->fd, fnum, cnum, offset, count ) ); return(outsize); } @@ -2759,7 +2759,7 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_vwv0,fnum); DEBUG( 3, ("openprint %s fd=%d fnum=%d cnum=%d\n", - fname2, fsp->f_u.fd_ptr->fd, fnum, cnum ) ); + fname2, fsp->fd_ptr->fd, fnum, cnum ) ); return(outsize); } @@ -2783,7 +2783,7 @@ int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) return(ERROR(ERRDOS,ERRnoaccess)); DEBUG( 3, ( "printclose fd=%d fnum=%d cnum=%d\n", - Files[fnum].f_u.fd_ptr->fd,fnum,cnum)); + Files[fnum].fd_ptr->fd,fnum,cnum)); close_file(fnum,True); @@ -3476,12 +3476,12 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, } if ((ofun&3) == 1) { - lseek(Files[fnum2].f_u.fd_ptr->fd,0,SEEK_END); + lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END); } if (st.st_size) - ret = transfer_file(Files[fnum1].f_u.fd_ptr->fd, - Files[fnum2].f_u.fd_ptr->fd,st.st_size,NULL,0,0); + ret = transfer_file(Files[fnum1].fd_ptr->fd, + Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); close_file(fnum1,False); close_file(fnum2,False); @@ -3678,7 +3678,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; - + int32 lock_timeout = IVAL(inbuf,smb_vwv4); int cnum; int i; char *data; @@ -3699,8 +3699,8 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) { int token; files_struct *fsp = &Files[fnum]; - uint32 dev = fsp->f_u.fd_ptr->dev; - uint32 inode = fsp->f_u.fd_ptr->inode; + uint32 dev = fsp->fd_ptr->dev; + uint32 inode = fsp->fd_ptr->inode; DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", fnum)); @@ -3749,6 +3749,9 @@ dev = %x, inode = %x\n", return ERROR(eclass,ecode); } + /* Setup the timeout in seconds. */ + lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000); + /* Now do any requested locks */ data += 10*num_ulocks; /* Data now points at the beginning of the list @@ -3758,6 +3761,16 @@ dev = %x, inode = %x\n", offset = IVAL(data,SMB_LKOFF_OFFSET(i)); if(!do_lock(fnum,cnum,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) +#if 0 /* JRATEST - blocking lock code. */ + if((ecode == ERRlock) && (lock_timeout != 0)) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) + return -1; +#endif /* JRATEST */ break; } @@ -4103,7 +4116,7 @@ int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CHECK_ERROR(fnum); /* Do an fstat on this file */ - if(fstat(Files[fnum].f_u.fd_ptr->fd, &sbuf)) + if(fstat(Files[fnum].fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(cnum,Files[fnum].name,&sbuf); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 47fb175d8e..143b45e9ef 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1047,7 +1047,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); fsp->open = False; - fsp->f_u.fd_ptr = 0; + fsp->fd_ptr = 0; fsp->granted_oplock = False; errno = EPERM; @@ -1222,7 +1222,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(cnum))) { fd_attempt_close(fd_ptr); - fsp->f_u.fd_ptr = 0; + fsp->fd_ptr = 0; if(fd_ptr->ref_count == 0) sys_unlink(fname); errno = ENOSPC; @@ -1259,7 +1259,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fd_ptr->dev = (uint32)sbuf->st_dev; fd_ptr->inode = (uint32)sbuf->st_ino; - fsp->f_u.fd_ptr = fd_ptr; + fsp->fd_ptr = fd_ptr; Connections[cnum].num_files_open++; fsp->mode = sbuf->st_mode; GetTimeOfDay(&fsp->open_time); @@ -1315,7 +1315,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct { fsp->mmap_size = file_size(fname); fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->f_u.fd_ptr->fd,0); + PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { @@ -1333,7 +1333,7 @@ void sync_file(int cnum, int fnum) { #ifdef HAVE_FSYNC if(lp_strict_sync(SNUM(cnum))) - fsync(Files[fnum].f_u.fd_ptr->fd); + fsync(Files[fnum].fd_ptr->fd); #endif } @@ -1417,14 +1417,14 @@ void close_file(int fnum, BOOL normal_close) { files_struct *fs_p = &Files[fnum]; int cnum = fs_p->cnum; - uint32 dev = fs_p->f_u.fd_ptr->dev; - uint32 inode = fs_p->f_u.fd_ptr->inode; + uint32 dev = fs_p->fd_ptr->dev; + uint32 inode = fs_p->fd_ptr->inode; int token; close_filestruct(fs_p); #if USE_READ_PREDICTION - invalidate_read_prediction(fs_p->f_u.fd_ptr->fd); + invalidate_read_prediction(fs_p->fd_ptr->fd); #endif if (lp_share_modes(SNUM(cnum))) @@ -1433,7 +1433,7 @@ void close_file(int fnum, BOOL normal_close) del_share_mode(token, fnum); } - fd_attempt_close(fs_p->f_u.fd_ptr); + fd_attempt_close(fs_p->fd_ptr); if (lp_share_modes(SNUM(cnum))) unlock_share_entry( cnum, dev, inode, token); @@ -1485,9 +1485,6 @@ void close_directory(int fnum) if (fsp->name) string_free(&fsp->name); - if (fsp->f_u.dir_ptr) - free((char *)fsp->f_u.dir_ptr); - /* we will catch bugs faster by zeroing this structure */ memset(fsp, 0, sizeof(*fsp)); } @@ -1541,7 +1538,7 @@ int open_directory(int fnum,int cnum,char *fname, int smb_ofun, int unixmode, in * Setup the files_struct for it. */ - fsp->f_u.dir_ptr = NULL; + fsp->fd_ptr = NULL; Connections[cnum].num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); @@ -1761,13 +1758,15 @@ free_and_exit: static void truncate_unless_locked(int fnum, int cnum, int token, BOOL *share_locked) { - if (Files[fnum].can_write){ + files_struct *fsp = &Files[fnum]; + + if (fsp->can_write){ if (is_locked(fnum,cnum,0x3FFFFFFF,0,F_WRLCK)){ /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, Files[fnum].f_u.fd_ptr->dev, - Files[fnum].f_u.fd_ptr->inode, token); + unlock_share_entry( cnum, fsp->fd_ptr->dev, + fsp->fd_ptr->inode, token); close_file(fnum,False); /* Share mode no longer locked. */ *share_locked = False; @@ -1776,7 +1775,7 @@ static void truncate_unless_locked(int fnum, int cnum, int token, unix_ERR_code = ERRlock; } else - ftruncate(Files[fnum].f_u.fd_ptr->fd,0); + ftruncate(fsp->fd_ptr->fd,0); } } @@ -1841,7 +1840,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int num_share_modes = 0; fs_p->open = False; - fs_p->f_u.fd_ptr = 0; + fs_p->fd_ptr = 0; /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) @@ -2017,8 +2016,8 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if((share_locked == False) && lp_share_modes(SNUM(cnum))) { /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fs_p->f_u.fd_ptr->dev; - inode = fs_p->f_u.fd_ptr->inode; + dev = fs_p->fd_ptr->dev; + inode = fs_p->fd_ptr->inode; lock_share_entry(cnum, dev, inode, &token); share_locked = True; } @@ -2098,7 +2097,7 @@ int seek_file(int fnum,uint32 pos) if (fsp->print_file && POSTSCRIPT(fsp->cnum)) offset = 3; - fsp->pos = (int)(lseek(fsp->f_u.fd_ptr->fd,pos+offset,SEEK_SET) - offset); + fsp->pos = (int)(lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); return(fsp->pos); } @@ -2113,7 +2112,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) #if USE_READ_PREDICTION if (!fsp->can_write) { - ret = read_predict(fsp->f_u.fd_ptr->fd,pos,data,NULL,n); + ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); data += ret; n -= ret; @@ -2147,7 +2146,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) } if (n > 0) { - readret = read(fsp->f_u.fd_ptr->fd,data,n); + readret = read(fsp->fd_ptr->fd,data,n); if (readret > 0) ret += readret; } @@ -2170,7 +2169,7 @@ int write_file(int fnum,char *data,int n) if (!fsp->modified) { struct stat st; fsp->modified = True; - if (fstat(fsp->f_u.fd_ptr->fd,&st) == 0) { + if (fstat(fsp->fd_ptr->fd,&st) == 0) { int dosmode = dos_mode(fsp->cnum,fsp->name,&st); if (MAP_ARCHIVE(fsp->cnum) && !IS_DOS_ARCHIVE(dosmode)) { dos_chmod(fsp->cnum,fsp->name,dosmode | aARCH,&st); @@ -2178,7 +2177,7 @@ int write_file(int fnum,char *data,int n) } } - return(write_data(fsp->f_u.fd_ptr->fd,data,n)); + return(write_data(fsp->fd_ptr->fd,data,n)); } @@ -2924,7 +2923,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { if(OPEN_FNUM(fnum)) { - if((Files[fnum].f_u.fd_ptr->dev == dev) && (Files[fnum].f_u.fd_ptr->inode == inode) && + if((Files[fnum].fd_ptr->dev == dev) && (Files[fnum].fd_ptr->inode == inode) && (Files[fnum].open_time.tv_sec == tval->tv_sec) && (Files[fnum].open_time.tv_usec == tval->tv_usec)) { fsp = &Files[fnum]; @@ -3789,7 +3788,7 @@ static BOOL attempt_close_oplocked_file(files_struct *fsp) if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) { /* Try and break the oplock. */ - file_fd_struct *fd_ptr = fsp->f_u.fd_ptr; + file_fd_struct *fd_ptr = fsp->fd_ptr; if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time)) { if(!fsp->open) /* Did the oplock break close the file ? */ return True; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 84cd99c91f..fc119307cd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -251,7 +251,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1207,11 +1207,11 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - if (fstat(Files[fnum].f_u.fd_ptr->fd,&sbuf) != 0) { + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = lseek(Files[fnum].f_u.fd_ptr->fd,0,SEEK_CUR); + pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR); } else { /* qpathinfo */ info_level = SVAL(params,0); @@ -1431,7 +1431,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - fd = Files[fnum].f_u.fd_ptr->fd; + fd = Files[fnum].fd_ptr->fd; if(fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); -- cgit From b067f0e2b921a7ac221d47a91d408526935363b2 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Thu, 13 Aug 1998 00:01:02 +0000 Subject: Debug output formatting change. I'm trying to combine log lines that really should be together. Chris -)----- (This used to be commit 8880fc58fa61edfd5a83cc75ef627b430b8a4437) --- source3/smbd/password.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 055c53d009..118251ffd6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -184,11 +184,11 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups, GID_T **p_groups) (*p_groups) = groups; - DEBUG(3,("%s is in %d groups\n",user,ngroups)); - for (i=0;i Date: Fri, 14 Aug 1998 17:38:29 +0000 Subject: this is the bug change to using connection_struct* instead of cnum. Connections[] is now a local array in server.c I might have broken something with this change. In particular the oplock code is suspect and some .dll files aren't being oplocked when I expected them to be. I'll look at it after I've got some sleep. (This used to be commit c7ee025ead4a85b6fa44a832047b878451845fb6) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/connection.c | 24 +- source3/smbd/dir.c | 128 ++-- source3/smbd/groupname.c | 4 +- source3/smbd/ipc.c | 460 ++++++------ source3/smbd/mangle.c | 25 - source3/smbd/message.c | 16 +- source3/smbd/nttrans.c | 717 +++++++++--------- source3/smbd/pipes.c | 20 +- source3/smbd/reply.c | 1785 +++++++++++++++++++++------------------------ source3/smbd/server.c | 1501 ++++++++++++++++++------------------- source3/smbd/trans2.c | 609 ++++++++-------- source3/smbd/uid.c | 303 ++------ 13 files changed, 2648 insertions(+), 2946 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index af6746a699..6594c5f48c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -80,7 +80,7 @@ static int findpty(char **slave) #else /* HAVE_GRANTPT */ fstrcpy( line, "/dev/ptyXX" ); - dirp = OpenDir(-1, "/dev", False); + dirp = OpenDir(NULL, "/dev", False); if (!dirp) return(-1); while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 64b3f153cf..342a5f43bc 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -22,7 +22,6 @@ #include "includes.h" -extern connection_struct Connections[MAX_CONNECTIONS]; extern fstring remote_machine; extern int DEBUGLEVEL; @@ -30,7 +29,7 @@ extern int DEBUGLEVEL; /**************************************************************************** simple routines to do connection counting ****************************************************************************/ -BOOL yield_connection(int cnum,char *name,int max_connections) +BOOL yield_connection(connection_struct *conn,char *name,int max_connections) { struct connect_record crec; pstring fname; @@ -38,7 +37,7 @@ BOOL yield_connection(int cnum,char *name,int max_connections) int mypid = getpid(); int i; - DEBUG(3,("Yielding connection to %d %s\n",cnum,name)); + DEBUG(3,("Yielding connection to %s\n",name)); if (max_connections <= 0) return(True); @@ -73,11 +72,11 @@ BOOL yield_connection(int cnum,char *name,int max_connections) close(fd); return(False); } - if (crec.pid == mypid && crec.cnum == cnum) + if (crec.pid == mypid && crec.cnum == conn->cnum) break; } - if (crec.pid != mypid || crec.cnum != cnum) { + if (crec.pid != mypid || crec.cnum != conn->cnum) { if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); } @@ -113,7 +112,7 @@ BOOL yield_connection(int cnum,char *name,int max_connections) /**************************************************************************** simple routines to do connection counting ****************************************************************************/ -BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) +BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear) { extern int Client; struct connect_record crec; @@ -192,11 +191,14 @@ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) bzero((void *)&crec,sizeof(crec)); crec.magic = 0x280267; crec.pid = getpid(); - crec.cnum = cnum; - if (cnum != -1) { - crec.uid = Connections[cnum].uid; - crec.gid = Connections[cnum].gid; - StrnCpy(crec.name,lp_servicename(SNUM(cnum)),sizeof(crec.name)-1); + if (conn) { + crec.cnum = conn->cnum; + crec.uid = conn->uid; + crec.gid = conn->gid; + StrnCpy(crec.name, + lp_servicename(SNUM(conn)),sizeof(crec.name)-1); + } else { + crec.cnum = -1; } crec.start = time(NULL); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 44e0556f20..42ed68f713 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -22,7 +22,6 @@ #include "includes.h" extern int DEBUGLEVEL; -extern connection_struct Connections[]; /* This module implements directory related functions for Samba. @@ -36,18 +35,17 @@ static uint32 dircounter = 0; #define NUMDIRPTRS 256 -static struct dptr_struct -{ - int pid; - int cnum; - uint32 lastused; - void *ptr; - BOOL valid; - BOOL finished; - BOOL expect_close; - char *wcard; /* Field only used for lanman2 trans2_findfirst/next searches */ - uint16 attr; /* Field only used for lanman2 trans2_findfirst/next searches */ - char *path; +static struct dptr_struct { + int pid; + connection_struct *conn; + uint32 lastused; + void *ptr; + BOOL valid; + BOOL finished; + BOOL expect_close; + char *wcard; /* Field only used for trans2_ searches */ + uint16 attr; /* Field only used for trans2_ searches */ + char *path; } dirptrs[NUMDIRPTRS]; @@ -110,20 +108,20 @@ get the dir ptr for a dir index ****************************************************************************/ static void *dptr_get(int key,uint32 lastused) { - struct dptr_struct *dp = &dirptrs[key]; - - if (dp->valid) { - if (lastused) dp->lastused = lastused; - if (!dp->ptr) { - if (dptrs_open >= MAX_OPEN_DIRECTORIES) - dptr_idleoldest(); - DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dp->ptr = OpenDir(dp->cnum, dp->path, True))) - dptrs_open++; - } - return(dp->ptr); - } - return(NULL); + struct dptr_struct *dp = &dirptrs[key]; + + if (dp->valid) { + if (lastused) dp->lastused = lastused; + if (!dp->ptr) { + if (dptrs_open >= MAX_OPEN_DIRECTORIES) + dptr_idleoldest(); + DEBUG(4,("Reopening dptr key %d\n",key)); + if ((dp->ptr = OpenDir(dp->conn, dp->path, True))) + dptrs_open++; + } + return(dp->ptr); + } + return(NULL); } /**************************************************************************** @@ -217,22 +215,22 @@ void dptr_close(int key) /**************************************************************************** close all dptrs for a cnum ****************************************************************************/ -void dptr_closecnum(int cnum) +void dptr_closecnum(connection_struct *conn) { int i; for (i=0;idirptr = OpenDir(conn, directory, True); + if (conn->dirptr) { + dptrs_open++; + string_set(&conn->dirpath,directory); + return(True); + } - return(False); + return(False); } /**************************************************************************** create a new dir ptr ****************************************************************************/ -int dptr_create(int cnum,char *path, BOOL expect_close,int pid) +int dptr_create(connection_struct *conn,char *path, BOOL expect_close,int pid) { int i; uint32 old; int oldi; - if (!start_dir(cnum,path)) + if (!start_dir(conn,path)) return(-2); /* Code to say use a unix error return code. */ if (dptrs_open >= MAX_OPEN_DIRECTORIES) @@ -325,11 +323,11 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid) if (dirptrs[i].valid) dptr_close(i); - dirptrs[i].ptr = Connections[cnum].dirptr; + dirptrs[i].ptr = conn->dirptr; string_set(&dirptrs[i].path,path); dirptrs[i].lastused = dircounter++; dirptrs[i].finished = False; - dirptrs[i].cnum = cnum; + dirptrs[i].conn = conn; dirptrs[i].pid = pid; dirptrs[i].expect_close = expect_close; dirptrs[i].wcard = NULL; /* Only used in lanman2 searches */ @@ -357,7 +355,7 @@ BOOL dptr_fill(char *buf1,unsigned int key) return(False); } offset = TellDir(p); - DEBUG(6,("fill on key %d dirptr 0x%x now at %d\n",key,p,offset)); + DEBUG(6,("fill on key %d dirptr 0x%x now at %d\n",key,(unsigned)p,offset)); buf[0] = key; SIVAL(buf,1,offset | DPTR_MASK); return(True); @@ -410,7 +408,7 @@ void *dptr_fetch_lanman2(int dptr_num) /**************************************************************************** check a filetype for being valid ****************************************************************************/ -BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype) +BOOL dir_check_ftype(connection_struct *conn,int mode,struct stat *st,int dirtype) { if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) return False; @@ -420,7 +418,7 @@ BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype) /**************************************************************************** get a directory entry ****************************************************************************/ -BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend) +BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend) { char *dname; BOOL found = False; @@ -434,22 +432,22 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo *path = *pathreal = *filename = 0; - isrootdir = (strequal(Connections[cnum].dirpath,"./") || - strequal(Connections[cnum].dirpath,".") || - strequal(Connections[cnum].dirpath,"/")); + isrootdir = (strequal(conn->dirpath,"./") || + strequal(conn->dirpath,".") || + strequal(conn->dirpath,"/")); needslash = - ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/'); + ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - if (!Connections[cnum].dirptr) + if (!conn->dirptr) return(False); while (!found) { - dname = ReadDirName(Connections[cnum].dirptr); + dname = ReadDirName(conn->dirptr); DEBUG(6,("readdir on dirptr 0x%x now at offset %d\n", - Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); + (unsigned)conn->dirptr,TellDir(conn->dirptr))); if (dname == NULL) return(False); @@ -459,7 +457,7 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo pstrcpy(filename,dname); if ((strcmp(filename,mask) == 0) || - (name_map_mangle(filename,True,SNUM(cnum)) && + (name_map_mangle(filename,True,SNUM(conn)) && mask_match(filename,mask,False,False))) { if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) @@ -467,7 +465,7 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo pstrcpy(fname,filename); *path = 0; - pstrcpy(path,Connections[cnum].dirpath); + pstrcpy(path,conn->dirpath); if(needslash) pstrcat(path,"/"); pstrcpy(pathreal,path); @@ -483,9 +481,9 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo !strequal(fname,".") && !strequal(fname,"..")) continue; - *mode = dos_mode(cnum,pathreal,&sbuf); + *mode = dos_mode(conn,pathreal,&sbuf); - if (!dir_check_ftype(cnum,*mode,&sbuf,dirtype)) { + if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) { DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); continue; } @@ -517,7 +515,7 @@ typedef struct /******************************************************************* open a directory ********************************************************************/ -void *OpenDir(int cnum, char *name, BOOL use_veto) +void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; @@ -538,7 +536,7 @@ void *OpenDir(int cnum, char *name, BOOL use_veto) int l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ - if (use_veto && IS_VETO_PATH(cnum, n)) continue; + if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 33ce3adbfe..689fdbbbd9 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -197,8 +197,8 @@ Error was %s.\n", unixname, strerror(errno) )); ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep); } - DEBUG(10,("load_groupname_map: Added %d entries to groupname map.\n", - ubi_slCount( &groupname_map_list ) )); + DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n", + ubi_slCount(&groupname_map_list))); fclose(fp); } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f1467a7f8a..a72b442735 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -37,7 +37,6 @@ extern int DEBUGLEVEL; extern int max_send; extern files_struct Files[]; -extern connection_struct Connections[]; extern fstring local_machine; extern fstring global_myworkgroup; @@ -65,31 +64,32 @@ extern int Client; extern int oplock_sock; extern int smb_read_error; -static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); -static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); -static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) +static int CopyExpanded(connection_struct *conn, + int snum, char** dst, char* src, int* n) { - pstring buf; - int l; + pstring buf; + int l; - if (!src || !dst || !n || !(*dst)) return(0); + if (!src || !dst || !n || !(*dst)) return(0); - StrnCpy(buf,src,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - StrnCpy(*dst,buf,*n); - l = strlen(*dst) + 1; - (*dst) += l; - (*n) -= l; - return l; + StrnCpy(buf,src,sizeof(buf)/2); + string_sub(buf,"%S",lp_servicename(snum)); + standard_sub(conn,buf); + StrnCpy(*dst,buf,*n); + l = strlen(*dst) + 1; + (*dst) += l; + (*n) -= l; + return l; } static int CopyAndAdvance(char** dst, char* src, int* n) @@ -103,24 +103,24 @@ static int CopyAndAdvance(char** dst, char* src, int* n) return l; } -static int StrlenExpanded(int cnum, int snum, char* s) +static int StrlenExpanded(connection_struct *conn, int snum, char* s) { - pstring buf; - if (!s) return(0); - StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - return strlen(buf) + 1; + pstring buf; + if (!s) return(0); + StrnCpy(buf,s,sizeof(buf)/2); + string_sub(buf,"%S",lp_servicename(snum)); + standard_sub(conn,buf); + return strlen(buf) + 1; } -static char* Expand(int cnum, int snum, char* s) +static char* Expand(connection_struct *conn, int snum, char* s) { - static pstring buf; - if (!s) return(NULL); - StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - return &buf[0]; + static pstring buf; + if (!s) return(NULL); + StrnCpy(buf,s,sizeof(buf)/2); + string_sub(buf,"%S",lp_servicename(snum)); + standard_sub(conn,buf); + return &buf[0]; } /******************************************************************* @@ -530,7 +530,7 @@ static int check_printq_info(struct pack_desc* desc, return True; } -static void fill_printjob_info(int cnum, int snum, int uLevel, +static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, struct pack_desc* desc, print_queue_struct* queue, int n) { @@ -577,7 +577,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, } } -static void fill_printq_info(int cnum, int snum, int uLevel, +static void fill_printq_info(connection_struct *conn, int snum, int uLevel, struct pack_desc* desc, int count, print_queue_struct* queue, print_status_struct* status) @@ -590,7 +590,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, case 3: case 4: case 5: - PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum))); + PACKS(desc,"z",Expand(conn,snum,SERVICE(snum))); break; } @@ -608,7 +608,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, PACKI(desc,"W",LPSTAT_ERROR); } else if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); + PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); PACKI(desc,"W",LPSTAT_OK); /* status */ } else { PACKS(desc,"z",status->message); @@ -625,7 +625,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, PACKS(desc,"z","WinPrint"); /* pszPrProc */ PACKS(desc,"z",""); /* pszParms */ if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */ + PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */ PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ } else { PACKS(desc,"z",status->message); /* pszComment */ @@ -639,7 +639,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, if (uLevel == 2 || uLevel == 4) { int i; for (i=0;i 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; if (init_package(&desc,1,count)) { desc.subcount = count; - fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status); + fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); } *rdata_len = desc.usedlen; @@ -868,7 +869,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data, /**************************************************************************** view list of all print jobs on all queues ****************************************************************************/ -static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data, +static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data, int mdrcnt, int mprcnt, char **rdata, char** rparam, int *rdata_len, int *rparam_len) @@ -907,7 +908,7 @@ static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data, n = 0; for (i = 0; i < services; i++) if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]); + subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]); subcnt += subcntarr[n]; n++; } @@ -921,7 +922,7 @@ static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data, succnt = 0; for (i = 0; i < services; i++) if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); + fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); n++; if (desc.errcode == NERR_Success) succnt = n; } @@ -1180,7 +1181,7 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) view list of servers available (or possibly domains). The info is extracted from lists saved by nmbd on the local host ****************************************************************************/ -static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, +static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) { @@ -1306,7 +1307,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, /**************************************************************************** command 0x34 - suspected of being a "Lookup Names" stub api ****************************************************************************/ -static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data, +static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) { @@ -1360,7 +1361,7 @@ static BOOL check_share_info(int uLevel, char* id) return True; } -static int fill_share_info(int cnum, int snum, int uLevel, +static int fill_share_info(connection_struct *conn, int snum, int uLevel, char** buf, int* buflen, char** stringbuf, int* stringspace, char* baseaddr) { @@ -1382,7 +1383,7 @@ static int fill_share_info(int cnum, int snum, int uLevel, if (!buf) { len = 0; - if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum)); + if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum)); if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; if (buflen) *buflen = struct_len; if (stringspace) *stringspace = len; @@ -1415,7 +1416,7 @@ static int fill_share_info(int cnum, int snum, int uLevel, if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; SSVAL(p,14,type); /* device type */ SIVAL(p,16,PTR_DIFF(p2,baseaddr)); - len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2); + len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); } if (uLevel > 1) @@ -1455,7 +1456,7 @@ static int fill_share_info(int cnum, int snum, int uLevel, return len; } -static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1475,7 +1476,7 @@ static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data, *rdata = REALLOC(*rdata,mdrcnt); p = *rdata; - *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0); + *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); if (*rdata_len < 0) return False; *rparam_len = 6; @@ -1490,7 +1491,7 @@ static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data, /**************************************************************************** view list of shares available ****************************************************************************/ -static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1516,7 +1517,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, if (lp_browseable(i) && lp_snum_ok(i)) { total++; - data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0); + data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0); if (data_len <= buf_len) { counted++; @@ -1536,7 +1537,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, s_len = string_len; for (i = 0; i < count;i++) if (lp_browseable(i) && lp_snum_ok(i)) - if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0) + if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0) break; *rparam_len = 8; @@ -1557,7 +1558,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, /**************************************************************************** get the time of day info ****************************************************************************/ -static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1606,7 +1607,7 @@ static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data, /**************************************************************************** set the user password ****************************************************************************/ -static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1682,7 +1683,7 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, Set the user password (SamOEM version - gets plaintext). ****************************************************************************/ -static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1760,7 +1761,7 @@ static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *dat delete a print job Form: <> ****************************************************************************/ -static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1789,7 +1790,7 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, { print_queue_struct *queue=NULL; lpq_reset(snum); - count = get_printqueue(snum,cnum,&queue,NULL); + count = get_printqueue(snum,conn,&queue,NULL); for (i=0;iadmin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ @@ -2475,7 +2477,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, memset(p+22,' ',16); /* password */ SIVALS(p,38,-1); /* password age */ SSVAL(p,42, - Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ pstrcpy(p2,lp_logon_path()); p2 = skip_string(p2,1); @@ -2523,7 +2525,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /******************************************************************* get groups that a user is a member of ******************************************************************/ -static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2570,7 +2572,7 @@ static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data, } -static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2605,7 +2607,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, PACKS(&desc,"B21",name); /* eff. name */ PACKS(&desc,"B",""); /* pad */ PACKI(&desc,"W", - Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); PACKI(&desc,"D",0); /* auth flags XXX */ PACKI(&desc,"W",0); /* num logons */ PACKI(&desc,"W",0); /* bad pw count */ @@ -2628,7 +2630,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, /* JHT - By calling lp_logon_script() and standard_sub() we have */ /* made sure all macros are fully substituted and available */ logon_script = lp_logon_script(); - standard_sub( cnum, logon_script ); + standard_sub( conn, logon_script ); PACKS(&desc,"z", logon_script); /* script path */ /* End of JHT mods */ @@ -2650,7 +2652,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, /**************************************************************************** api_WAccessGetUserPerms ****************************************************************************/ -static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2678,7 +2680,7 @@ static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data /**************************************************************************** api_WPrintJobEnumerate ****************************************************************************/ -static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2711,7 +2713,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data, if (snum < 0 || !VALID_SNUM(snum)) return(False); - count = get_printqueue(snum,cnum,&queue,&status); + count = get_printqueue(snum,conn,&queue,&status); for (i = 0; i < count; i++) { if ((queue[i].job & 0xFF) == job) break; } @@ -2721,7 +2723,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data, if (init_package(&desc,1,0)) { if (i < count) { - fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); *rdata_len = desc.usedlen; } else { @@ -2742,7 +2744,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data, return(True); } -static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2784,7 +2786,7 @@ static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data, if (snum < 0 || !VALID_SNUM(snum)) return(False); - count = get_printqueue(snum,cnum,&queue,&status); + count = get_printqueue(snum,conn,&queue,&status); if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; @@ -2792,7 +2794,7 @@ static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data, if (init_package(&desc,count,0)) { succnt = 0; for (i = 0; i < count; i++) { - fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); if (desc.errcode == NERR_Success) succnt = i+1; } } @@ -2827,7 +2829,7 @@ static int check_printdest_info(struct pack_desc* desc, return True; } -static void fill_printdest_info(int cnum, int snum, int uLevel, +static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, struct pack_desc* desc) { char buf[100]; @@ -2860,7 +2862,7 @@ static void fill_printdest_info(int cnum, int snum, int uLevel, } } -static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2904,7 +2906,7 @@ static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data, desc.base = *rdata; desc.buflen = mdrcnt; if (init_package(&desc,1,0)) { - fill_printdest_info(cnum,snum,uLevel,&desc); + fill_printdest_info(conn,snum,uLevel,&desc); } *rdata_len = desc.usedlen; } @@ -2919,7 +2921,7 @@ static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data, return(True); } -static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -2957,7 +2959,7 @@ static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data, n = 0; for (i = 0; i < services; i++) { if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printdest_info(cnum,i,uLevel,&desc); + fill_printdest_info(conn,i,uLevel,&desc); n++; if (desc.errcode == NERR_Success) succnt = n; } @@ -2977,7 +2979,7 @@ static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data, return(True); } -static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -3022,7 +3024,7 @@ static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data, return(True); } -static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -3068,7 +3070,7 @@ static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data, return(True); } -static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -3366,7 +3368,7 @@ static BOOL api_no_reply(char *outbuf, int max_rdata_len) /**************************************************************************** handle remote api calls delivered to a named pipe already opened. ****************************************************************************/ -static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, +static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, uint16 *setup,char *data,char *params, int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { @@ -3407,8 +3409,6 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, { DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum)); - DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", - tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); /* record maximum data length that can be transmitted in an SMBtrans */ p->file_offset = mdrcnt; @@ -3447,7 +3447,7 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, /**************************************************************************** the buffer was too small ****************************************************************************/ -static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -3468,7 +3468,7 @@ static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data, /**************************************************************************** the request is not supported ****************************************************************************/ -static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, +static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -3493,7 +3493,8 @@ struct { char *name; int id; - BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *); + BOOL (*fn)(connection_struct *,uint16,char *,char *, + int,int,char **,char **,int *,int *); int flags; } api_commands[] = { {"RNetShareEnum", 0, api_RNetShareEnum,0}, @@ -3531,7 +3532,7 @@ struct /**************************************************************************** handle remote api calls ****************************************************************************/ -static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, +static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { int api_command = SVAL(params,0); @@ -3558,21 +3559,21 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, + reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); if (rdata_len > mdrcnt || rparam_len > mprcnt) { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, + reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); } /* if we get False back then it's actually unsupported */ if (!reply) - api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, + api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); @@ -3597,7 +3598,7 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, /**************************************************************************** handle named pipe commands ****************************************************************************/ -static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, +static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name, uint16 *setup,char *data,char *params, int suwcnt,int tdscnt,int tpscnt, int msrcnt,int mdrcnt,int mprcnt) @@ -3606,12 +3607,12 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, if (strequal(name,"LANMAN")) { - return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt); + return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt); } if (strlen(name) < 1) { - return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); + return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); } if (setup) @@ -3626,141 +3627,132 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, /**************************************************************************** reply to a SMBtrans ****************************************************************************/ -int reply_trans(char *inbuf,char *outbuf, int size, int bufsize) -{ - fstring name; - - char *data=NULL,*params=NULL; - uint16 *setup=NULL; - - int outsize = 0; - int cnum = SVAL(inbuf,smb_tid); - uint16 vuid = SVAL(inbuf,smb_uid); - - int tpscnt = SVAL(inbuf,smb_vwv0); - int tdscnt = SVAL(inbuf,smb_vwv1); - int mprcnt = SVAL(inbuf,smb_vwv2); - int mdrcnt = SVAL(inbuf,smb_vwv3); - int msrcnt = CVAL(inbuf,smb_vwv4); - BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); - BOOL one_way = BITSETW(inbuf+smb_vwv5,1); - int pscnt = SVAL(inbuf,smb_vwv9); - int psoff = SVAL(inbuf,smb_vwv10); - int dscnt = SVAL(inbuf,smb_vwv11); - int dsoff = SVAL(inbuf,smb_vwv12); - int suwcnt = CVAL(inbuf,smb_vwv13); - - bzero(name, sizeof(name)); - fstrcpy(name,smb_buf(inbuf)); - - if (dscnt > tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters\n"); - } +int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize) +{ + fstring name; + + char *data=NULL,*params=NULL; + uint16 *setup=NULL; + int outsize = 0; + uint16 vuid = SVAL(inbuf,smb_uid); + int tpscnt = SVAL(inbuf,smb_vwv0); + int tdscnt = SVAL(inbuf,smb_vwv1); + int mprcnt = SVAL(inbuf,smb_vwv2); + int mdrcnt = SVAL(inbuf,smb_vwv3); + int msrcnt = CVAL(inbuf,smb_vwv4); + BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); + BOOL one_way = BITSETW(inbuf+smb_vwv5,1); + int pscnt = SVAL(inbuf,smb_vwv9); + int psoff = SVAL(inbuf,smb_vwv10); + int dscnt = SVAL(inbuf,smb_vwv11); + int dsoff = SVAL(inbuf,smb_vwv12); + int suwcnt = CVAL(inbuf,smb_vwv13); + + bzero(name, sizeof(name)); + fstrcpy(name,smb_buf(inbuf)); + + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters\n"); + } - if (tdscnt) - { - data = (char *)malloc(tdscnt); - memcpy(data,smb_base(inbuf)+dsoff,dscnt); - } - if (tpscnt) - { - params = (char *)malloc(tpscnt); - memcpy(params,smb_base(inbuf)+psoff,pscnt); - } + if (tdscnt) { + data = (char *)malloc(tdscnt); + memcpy(data,smb_base(inbuf)+dsoff,dscnt); + } - if (suwcnt) - { - int i; - setup = (uint16 *)malloc(suwcnt*sizeof(setup[0])); - for (i=0;i tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters\n"); - } - - if (pcnt) - memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); - if (dcnt) - memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); - } - - - DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt)); - - if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) - { - DEBUG(5,("calling named_pipe\n")); - outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, - suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); - } - else - { - DEBUG(3,("invalid pipe name\n")); - outsize = 0; - } - - - if (data) free(data); - if (params) free(params); - if (setup) free(setup); - - if (close_on_completion) - close_cnum(cnum,vuid); + tpscnt = SVAL(inbuf,smb_vwv0); + tdscnt = SVAL(inbuf,smb_vwv1); + + pcnt = SVAL(inbuf,smb_vwv2); + poff = SVAL(inbuf,smb_vwv3); + pdisp = SVAL(inbuf,smb_vwv4); + + dcnt = SVAL(inbuf,smb_vwv5); + doff = SVAL(inbuf,smb_vwv6); + ddisp = SVAL(inbuf,smb_vwv7); + + pscnt += pcnt; + dscnt += dcnt; + + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters\n"); + } + + if (pcnt) + memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); + if (dcnt) + memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); + } + + + DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n", + name,tdscnt,tpscnt,suwcnt)); + + if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) { + DEBUG(5,("calling named_pipe\n")); + outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, + suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); + } else { + DEBUG(3,("invalid pipe name\n")); + outsize = 0; + } - if (one_way) - return(-1); - - if (outsize == 0) - return(ERROR(ERRSRV,ERRnosupport)); + + if (data) free(data); + if (params) free(params); + if (setup) free(setup); + + if (close_on_completion) + close_cnum(conn,vuid); - return(outsize); + if (one_way) + return(-1); + + if (outsize == 0) + return(ERROR(ERRSRV,ERRnosupport)); + + return(outsize); } diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index f33b8ac2e6..0703a4a74e 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -418,31 +418,6 @@ BOOL is_8_3( char *fname, BOOL check_case ) return( True ); } /* is_8_3 */ -/* ************************************************************************** ** - * Provide a checksum on a string - * - * Input: s - the nul-terminated character string for which the checksum - * will be calculated. - * - * Output: The checksum value calculated for s. - * - * ************************************************************************** ** - */ -int str_checksum( char *s ) - { - int res = 0; - int c; - int i=0; - - while( *s ) - { - c = *s; - res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); - s++; - i++; - } - return(res); - } /* str_checksum */ /* ************************************************************************** ** * Compare two cache keys and return a value indicating their ordinal diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 44ae272bdd..001fc652b2 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -78,7 +78,7 @@ static void msg_deliver(void) string_sub(s,"%s",name); string_sub(s,"%f",msgfrom); string_sub(s,"%t",msgto); - standard_sub(-1,s); + standard_sub_basic(s); smbrun(s,NULL,False); } @@ -90,7 +90,8 @@ static void msg_deliver(void) /**************************************************************************** reply to a sends ****************************************************************************/ -int reply_sends(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_sends(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int len; char *orig,*dest,*msg; @@ -128,7 +129,8 @@ int reply_sends(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a sendstrt ****************************************************************************/ -int reply_sendstrt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_sendstrt(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { char *orig,*dest; int outsize = 0; @@ -155,7 +157,8 @@ int reply_sendstrt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a sendtxt ****************************************************************************/ -int reply_sendtxt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_sendtxt(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int len; int outsize = 0; @@ -183,7 +186,8 @@ int reply_sendtxt(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a sendend ****************************************************************************/ -int reply_sendend(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_sendend(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; @@ -192,7 +196,7 @@ int reply_sendend(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "%s SMBsendend\n" ) ); + DEBUG(3,("SMBsendend\n")); msg_deliver(); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8709b9c646..bff61b6736 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -25,7 +25,6 @@ extern int DEBUGLEVEL; extern int Protocol; extern int chain_fnum; -extern connection_struct Connections[]; extern files_struct Files[]; extern int Client; extern int oplock_sock; @@ -363,10 +362,9 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi /**************************************************************************** Reply to an NT create and X call on a pipe. ****************************************************************************/ - -static int nt_open_pipe(char *fname, char *inbuf, char *outbuf, int *ppnum) +static int nt_open_pipe(char *fname, connection_struct *conn, + char *inbuf, char *outbuf, int *ppnum) { - int cnum = SVAL(inbuf,smb_tid); int pnum = -1; uint16 vuid = SVAL(inbuf, smb_uid); int i; @@ -386,7 +384,7 @@ static int nt_open_pipe(char *fname, char *inbuf, char *outbuf, int *ppnum) DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); - pnum = open_rpc_pipe_hnd(fname, cnum, vuid); + pnum = open_rpc_pipe_hnd(fname, conn, vuid); if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); @@ -397,280 +395,291 @@ static int nt_open_pipe(char *fname, char *inbuf, char *outbuf, int *ppnum) /**************************************************************************** Reply to an NT create and X call. ****************************************************************************/ - -int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) +int reply_ntcreate_and_X(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { - pstring fname; - int cnum = SVAL(inbuf,smb_tid); - int fnum = -1; - uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); - uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); - uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); - uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); - uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); - uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), - ((uint32)sizeof(fname)-1)); - int smb_ofun; - int smb_open_mode; - int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); - /* Breakout the oplock request bits so we can set the - reply bits separately. */ - int oplock_request = 0; - int unixmode; - int fmode=0,mtime=0,rmode=0; - off_t file_len = 0; - struct stat sbuf; - int smb_action = 0; - BOOL bad_path = False; - files_struct *fsp; - char *p = NULL; - - /* - * We need to construct the open_and_X ofun value from the - * NT values, as that's what our code is structured to accept. - */ - - if((smb_ofun = map_create_disposition( create_disposition )) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); - - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ - - if((smb_open_mode = map_share_mode( desired_access, share_access, file_attributes)) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); - - /* - * Get the file name. - */ - StrnCpy(fname,smb_buf(inbuf),fname_len); - fname[fname_len] = '\0'; - - /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(cnum)) { - int ret = nt_open_pipe(fname, inbuf, outbuf, &fnum); - if(ret != 0) - return ret; - smb_action = FILE_WAS_OPENED; - } else { - - /* - * Ordinary file or directory. - */ - - /* - * Check if POSIX semantics are wanted. - */ - - set_posix_case_semantics(file_attributes); - - unix_convert(fname,cnum,0,&bad_path); - - fnum = find_free_file(); - if (fnum < 0) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); - } - - fsp = &Files[fnum]; - - if (!check_name(fname,cnum)) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - fsp->reserved = False; - - restore_case_semantics(file_attributes); - - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - unixmode = unix_mode(cnum,smb_attr | aARCH); - - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - - /* - * If it's a request for a directory open, deal with it separately. - */ - - if(flags & OPEN_DIRECTORY) { - oplock_request = 0; - - open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); - - restore_case_semantics(file_attributes); - - if(!fsp->open) { - fsp->reserved = False; - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } else { - - /* - * Ordinary file case. - */ - - /* - * NB. We have a potential bug here. If we cause an oplock - * break to ourselves, then we could end up processing filename - * related SMB requests whilst we await the oplock break - * response. As we may have changed the filename case - * semantics to be POSIX-like, this could mean a filename - * request could fail when it should succeed. This is a - * rare condition, but eventually we must arrange to restore - * the correct case semantics before issuing an oplock break - * request to our client. JRA. - */ - - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); - - if (!fsp->open) { - /* - * We cheat here. The only case we care about is a directory - * rename, where the NT client will attempt to open the source - * directory for DELETE access. Note that when the NT client - * does this it does *not* set the directory bit in the - * request packet. This is translated into a read/write open - * request. POSIX states that any open for write request on a directory - * will generate an EISDIR error, so we can catch this here and open - * a pseudo handle that is flagged as a directory. JRA. - */ - - if(errno == EISDIR) { - oplock_request = 0; - - open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); - - if(!fsp->open) { - fsp->reserved = False; - restore_case_semantics(file_attributes); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } else { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - - fsp->reserved = False; - - restore_case_semantics(file_attributes); + pstring fname; + int fnum = -1; + uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); + uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); + uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); + uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); + uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); + uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), + ((uint32)sizeof(fname)-1)); + int smb_ofun; + int smb_open_mode; + int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); + /* Breakout the oplock request bits so we can set the + reply bits separately. */ + int oplock_request = 0; + int unixmode; + int fmode=0,mtime=0,rmode=0; + off_t file_len = 0; + struct stat sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp=NULL; + char *p = NULL; + + /* + * We need to construct the open_and_X ofun value from the + * NT values, as that's what our code is structured to accept. + */ + + if((smb_ofun = map_create_disposition( create_disposition )) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ + + if((smb_open_mode = map_share_mode(desired_access, + share_access, + file_attributes)) == -1) { + return(ERROR(ERRDOS,ERRbadaccess)); + } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } - } - - if(fsp->is_directory) { - if(sys_stat(fsp->name, &sbuf) != 0) { - close_directory(fnum); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } else { - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } - - restore_case_semantics(file_attributes); - - file_len = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - if(fmode == 0) - fmode = FILE_ATTRIBUTE_NORMAL; - mtime = sbuf.st_mtime; - if (!fsp->is_directory && (fmode & aDIR)) { - close_file(fnum,False); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ + /* + * Get the file name. + */ + StrnCpy(fname,smb_buf(inbuf),fname_len); + fname[fname_len] = '\0'; + + /* If it's an IPC, use the pipe handler. */ + if (IS_IPC(conn)) { + int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &fnum); + if(ret != 0) + return ret; + smb_action = FILE_WAS_OPENED; + } else { + + /* + * Ordinary file or directory. + */ + + /* + * Check if POSIX semantics are wanted. + */ + + set_posix_case_semantics(file_attributes); + + unix_convert(fname,conn,0,&bad_path); + + fnum = find_free_file(); + if (fnum < 0) { + restore_case_semantics(file_attributes); + return(ERROR(ERRSRV,ERRnofids)); + } + + fsp = &Files[fnum]; + + if (!check_name(fname,conn)) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + fsp->reserved = False; + + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + unixmode = unix_mode(conn,smb_attr | aARCH); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) - smb_action |= EXTENDED_OPLOCK_GRANTED; - - if(oplock_request && fsp->granted_oplock) - smb_action |= EXTENDED_OPLOCK_GRANTED; - } - - set_message(outbuf,34,0,True); - - p = outbuf + smb_vwv2; - - /* - * Currently as we don't support level II oplocks we just report - * exclusive & batch here. - */ - - SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); - p++; - SSVAL(p,0,fnum); - p += 2; - SIVAL(p,0,smb_action); - p += 4; - - if (IS_IPC(cnum)) { - /* - * Deal with pipe return. - */ - p += 32; - SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ - p += 20; - /* File type. */ - SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); - /* Device state. */ - SSVAL(p,2, 0x5FF); /* ? */ - } else { - /* - * Deal with file return. - */ - /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); - p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ - p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ - p += 12; + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + + /* + * If it's a request for a directory open, deal with it separately. + */ + + if(flags & OPEN_DIRECTORY) { + oplock_request = 0; + + open_directory(fnum, conn, fname, smb_ofun, + unixmode, &smb_action); + + restore_case_semantics(file_attributes); + + if(!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + /* + * Ordinary file case. + */ + + /* NB. We have a potential bug here. If we + * cause an oplock break to ourselves, then we + * could end up processing filename related + * SMB requests whilst we await the oplock + * break response. As we may have changed the + * filename case semantics to be POSIX-like, + * this could mean a filename request could + * fail when it should succeed. This is a rare + * condition, but eventually we must arrange + * to restore the correct case semantics + * before issuing an oplock break request to + * our client. JRA. */ + + open_file_shared(fnum,conn,fname,smb_open_mode, + smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); + + if (!fsp->open) { + /* We cheat here. The only case we + * care about is a directory rename, + * where the NT client will attempt to + * open the source directory for + * DELETE access. Note that when the + * NT client does this it does *not* + * set the directory bit in the * + * request packet. This is translated + * into a read/write open * + * request. POSIX states that any open + * for write request on a directory * + * will generate an EISDIR error, so + * we can catch this here and open * a + * pseudo handle that is flagged as a + * directory. JRA. */ + + if(errno == EISDIR) { + oplock_request = 0; + + open_directory(fnum, conn, fname, smb_ofun, unixmode, &smb_action); + + if(!fsp->open) { + fsp->reserved = False; + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + + fsp->reserved = False; + + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } + } + + if(fsp->is_directory) { + if(sys_stat(fsp->fsp_name, &sbuf) != 0) { + close_directory(fnum); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } else { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } + + restore_case_semantics(file_attributes); + + file_len = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + if(fmode == 0) + fmode = FILE_ATTRIBUTE_NORMAL; + mtime = sbuf.st_mtime; + if (!fsp->is_directory && (fmode & aDIR)) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) + smb_action |= EXTENDED_OPLOCK_GRANTED; + + if(oplock_request && fsp->granted_oplock) + smb_action |= EXTENDED_OPLOCK_GRANTED; + } + + set_message(outbuf,34,0,True); + + p = outbuf + smb_vwv2; + + /* + * Currently as we don't support level II oplocks we just report + * exclusive & batch here. + */ + + SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); + p++; + SSVAL(p,0,fnum); + p += 2; + SIVAL(p,0,smb_action); + p += 4; + + if (IS_IPC(conn)) { + /* + * Deal with pipe return. + */ + p += 32; + SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ + p += 20; + /* File type. */ + SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); + /* Device state. */ + SSVAL(p,2, 0x5FF); /* ? */ + } else { + /* + * Deal with file return. + */ + /* Create time. */ + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fmode); /* File Attributes. */ + p += 12; #if OFF_T_IS_64_BITS - SIVAL(p,0, file_len & 0xFFFFFFFF); - SIVAL(p,4, file_len >> 32); + SIVAL(p,0, file_len & 0xFFFFFFFF); + SIVAL(p,4, file_len >> 32); #else /* OFF_T_IS_64_BITS */ - SIVAL(p,0,file_len); + SIVAL(p,0,file_len); #endif /* OFF_T_IS_64_BITS */ - p += 12; - SCVAL(p,0,fsp->is_directory ? 1 : 0); - } - - chain_fnum = fnum; + p += 12; + SCVAL(p,0,fsp->is_directory ? 1 : 0); + } + + chain_fnum = fnum; - DEBUG(5,("reply_ntcreate_and_X: open fnum = %d, name = %s\n", - fnum, fsp->name )); + + DEBUG(5,("reply_ntcreate_and_X: open fnum = %d, name = %s\n", + fnum, fsp?fsp->fsp_name:"NULL")); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ - -static int call_nt_transact_create(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, - char **ppsetup, char **ppparams, char **ppdata) +static int call_nt_transact_create(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, + char **ppsetup, char **ppparams, + char **ppdata) { pstring fname; int fnum = -1; @@ -721,8 +730,8 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, fname[fname_len] = '\0'; /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(cnum)) { - int ret = nt_open_pipe(fname, inbuf, outbuf, &fnum); + if (IS_IPC(conn)) { + int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &fnum); if(ret != 0) return ret; smb_action = FILE_WAS_OPENED; @@ -733,7 +742,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, set_posix_case_semantics(file_attributes); - unix_convert(fname,cnum,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); fnum = find_free_file(); if (fnum < 0) { @@ -743,7 +752,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, fsp = &Files[fnum]; - if (!check_name(fname,cnum)) { + if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; @@ -755,7 +764,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(cnum,smb_attr | aARCH); + unixmode = unix_mode(conn,smb_attr | aARCH); oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; @@ -774,7 +783,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, * CreateDirectory() call. */ - open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); + open_directory(fnum, conn, fname, smb_ofun, unixmode, &smb_action); if(!fsp->open) { fsp->reserved = False; @@ -786,7 +795,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, * Ordinary file case. */ - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + open_file_shared(fnum,conn,fname,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp->open) { @@ -810,7 +819,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, } file_len = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); + fmode = dos_mode(conn,fname,&sbuf); if(fmode == 0) fmode = FILE_ATTRIBUTE_NORMAL; mtime = sbuf.st_mtime; @@ -827,7 +836,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, * correct bit for extended oplock reply. */ - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) smb_action |= EXTENDED_OPLOCK_GRANTED; if(oplock_request && fsp->granted_oplock) @@ -850,7 +859,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, SIVAL(p,0,smb_action); p += 8; - if (IS_IPC(cnum)) { + if (IS_IPC(conn)) { /* * Deal with pipe return. */ @@ -866,7 +875,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, * Deal with file return. */ /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); p += 8; put_long_date(p,sbuf.st_atime); /* access time */ p += 8; @@ -893,39 +902,39 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, /**************************************************************************** Reply to a NT CANCEL request. ****************************************************************************/ - -int reply_ntcancel(char *inbuf,char *outbuf,int length,int bufsize) +int reply_ntcancel(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { - /* - * Go through and cancel any pending change notifies. - * TODO: When we add blocking locks we will add cancel - * for them here too. - */ - - int mid = SVAL(inbuf,smb_mid); - remove_pending_change_notify_requests_by_mid(mid); - - DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); - - return(-1); + /* + * Go through and cancel any pending change notifies. + * TODO: When we add blocking locks we will add cancel + * for them here too. + */ + + int mid = SVAL(inbuf,smb_mid); + remove_pending_change_notify_requests_by_mid(mid); + + DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); + + return(-1); } /**************************************************************************** Reply to an unsolicited SMBNTtranss - just ignore it! ****************************************************************************/ - -int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize) +int reply_nttranss(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { - DEBUG(4,("Ignoring nttranss of length %d\n",length)); - return(-1); + DEBUG(4,("Ignoring nttranss of length %d\n",length)); + return(-1); } /**************************************************************************** Reply to an NT transact rename command. ****************************************************************************/ - -static int call_nt_transact_rename(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, +static int call_nt_transact_rename(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, char **ppsetup, char **ppparams, char **ppdata) { char *params = *ppparams; @@ -936,11 +945,11 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int length, ((uint32)sizeof(new_name)-1)); int outsize = 0; - CHECK_FNUM(fnum, cnum); + CHECK_FNUM(fnum, conn); StrnCpy(new_name,params+4,fname_len); new_name[fname_len] = '\0'; - outsize = rename_internals(inbuf, outbuf, Files[fnum].name, + outsize = rename_internals(conn, inbuf, outbuf, Files[fnum].fsp_name, new_name, replace_if_exists); if(outsize == 0) { /* @@ -949,7 +958,7 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int length, send_nt_replies(outbuf, bufsize, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", - Files[fnum].name, new_name)); + Files[fnum].fsp_name, new_name)); outsize = -1; } @@ -967,7 +976,7 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int length, typedef struct { ubi_slNode msg_next; int fnum; - int cnum; + connection_struct *conn; time_t next_check_time; time_t modify_time; /* Info from the directory we're monitoring. */ time_t status_time; /* Info from the directory we're monitoring. */ @@ -1076,12 +1085,12 @@ void process_pending_change_notify_queue(time_t t) while((cnbp != NULL) && (cnbp->next_check_time <= t)) { struct stat st; int fnum = cnbp->fnum; - int cnum = cnbp->cnum; + connection_struct *conn = cnbp->conn; files_struct *fsp = &Files[fnum]; uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if(!become_user(&Connections[cnum],cnum,vuid)) { + if(!become_user(conn,vuid)) { DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", vuid )); /* @@ -1093,9 +1102,8 @@ void process_pending_change_notify_queue(time_t t) continue; } - if(!become_service(cnum,True)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to become service cnum=%d. \ -Error was %s.\n", cnum, strerror(errno) )); + if(!become_service(conn,True)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to become service Error was %s.\n", strerror(errno) )); /* * Remove the entry and return an error to the client. */ @@ -1106,9 +1114,9 @@ Error was %s.\n", cnum, strerror(errno) )); continue; } - if(sys_stat(fsp->name, &st) < 0) { + if(sys_stat(fsp->fsp_name, &st) < 0) { DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \ -Error was %s.\n", fsp->name, strerror(errno) )); +Error was %s.\n", fsp->fsp_name, strerror(errno) )); /* * Remove the entry and return an error to the client. */ @@ -1125,7 +1133,7 @@ Error was %s.\n", fsp->name, strerror(errno) )); * Remove the entry and return a change notify to the client. */ DEBUG(5,("process_pending_change_notify_queue: directory fnum = %d, name = %s changed\n", - fnum, fsp->name )); + fnum, fsp->fsp_name )); change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); @@ -1147,10 +1155,11 @@ Error was %s.\n", fsp->name, strerror(errno) )); Reply to a notify change - queue the request and don't allow a directory to be opened. ****************************************************************************/ - -static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, - char **ppsetup, char **ppparams, char **ppdata) +static int call_nt_transact_notify_change(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, + char **ppsetup, + char **ppparams, char **ppdata) { char *setup = *ppsetup; files_struct *fsp; @@ -1167,7 +1176,7 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, fsp = &Files[fnum]; - if((!fsp->open) || (!fsp->is_directory) || (cnum != fsp->cnum)) + if((!fsp->open) || (!fsp->is_directory) || (conn != fsp->conn)) return(ERROR(ERRDOS,ERRbadfid)); /* @@ -1187,16 +1196,16 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length, * Store the current timestamp on the directory we are monitoring. */ - if(sys_stat(fsp->name, &st) < 0) { + if(sys_stat(fsp->fsp_name, &st) < 0) { DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \ -Error was %s\n", fnum, fsp->name, strerror(errno) )); +Error was %s\n", fnum, fsp->fsp_name, strerror(errno) )); free((char *)cnbp); return(UNIXERROR(ERRDOS,ERRbadfid)); } memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fnum = fnum; - cnbp->cnum = cnum; + cnbp->conn = conn; cnbp->modify_time = st.st_mtime; cnbp->status_time = st.st_ctime; @@ -1211,7 +1220,7 @@ Error was %s\n", fnum, fsp->name, strerror(errno) )); ubi_slAddTail(&change_notify_queue, cnbp); DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ -fid=%d, name = %s\n", fnum, fsp->name )); +fid=%d, name = %s\n", fnum, fsp->fsp_name )); return -1; } @@ -1220,9 +1229,10 @@ fid=%d, name = %s\n", fnum, fsp->name )); Reply to query a security descriptor - currently this is not implemented (it is planned to be though). ****************************************************************************/ - -static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, +static int call_nt_transact_query_security_desc(connection_struct *conn, + char *inbuf, char *outbuf, + int length, + int bufsize, char **ppsetup, char **ppparams, char **ppdata) { DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n")); @@ -1233,21 +1243,23 @@ static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int l Reply to set a security descriptor - currently this is not implemented (it is planned to be though). ****************************************************************************/ - -static int call_nt_transact_set_security_desc(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, - char **ppsetup, char **ppparams, char **ppdata) +static int call_nt_transact_set_security_desc(connection_struct *conn, + char *inbuf, char *outbuf, + int length, + int bufsize, + char **ppsetup, + char **ppparams, char **ppdata) { - DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n")); - return(ERROR(ERRSRV,ERRnosupport)); + DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n")); + return(ERROR(ERRSRV,ERRnosupport)); } /**************************************************************************** Reply to IOCTL - not implemented - no plans. ****************************************************************************/ - -static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, +static int call_nt_transact_ioctl(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, char **ppsetup, char **ppparams, char **ppdata) { DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); @@ -1257,11 +1269,10 @@ static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int length, /**************************************************************************** Reply to a SMBNTtrans. ****************************************************************************/ - -int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) +int reply_nttrans(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { int outsize = 0; - int cnum = SVAL(inbuf,smb_tid); #if 0 /* Not used. */ uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount); @@ -1394,39 +1405,45 @@ due to being in oplock break state.\n" )); /* Now we must call the relevant NT_TRANS function */ switch(function_code) { case NT_TRANSACT_CREATE: - outsize = call_nt_transact_create(inbuf, outbuf, length, bufsize, cnum, + outsize = call_nt_transact_create(conn, inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); break; case NT_TRANSACT_IOCTL: - outsize = call_nt_transact_ioctl(inbuf, outbuf, length, bufsize, cnum, + outsize = call_nt_transact_ioctl(conn, + inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); break; case NT_TRANSACT_SET_SECURITY_DESC: - outsize = call_nt_transact_set_security_desc(inbuf, outbuf, length, bufsize, cnum, + outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, + length, bufsize, &setup, ¶ms, &data); break; case NT_TRANSACT_NOTIFY_CHANGE: - outsize = call_nt_transact_notify_change(inbuf, outbuf, length, bufsize, cnum, + outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, + length, bufsize, &setup, ¶ms, &data); break; case NT_TRANSACT_RENAME: - outsize = call_nt_transact_rename(inbuf, outbuf, length, bufsize, cnum, + outsize = call_nt_transact_rename(conn, inbuf, outbuf, length, + bufsize, &setup, ¶ms, &data); break; + case NT_TRANSACT_QUERY_SECURITY_DESC: - outsize = call_nt_transact_query_security_desc(inbuf, outbuf, length, bufsize, cnum, + outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, + length, bufsize, &setup, ¶ms, &data); break; - default: - /* Error in request */ - DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); - if(setup) - free(setup); - if(params) - free(params); - if(data) - free(data); - return (ERROR(ERRSRV,ERRerror)); + default: + /* Error in request */ + DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); + if(setup) + free(setup); + if(params) + free(params); + if(data) + free(data); + return (ERROR(ERRSRV,ERRerror)); } /* As we do not know how many data packets will need to be diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 34884aa6d3..2a51e83946 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -58,10 +58,10 @@ extern struct pipe_id_info pipe_names[]; This code is basically stolen from reply_open_and_X with some wrinkles to handle pipes. ****************************************************************************/ -int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) +int reply_open_pipe_and_X(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; - uint16 cnum = SVAL(inbuf, smb_tid); uint16 vuid = SVAL(inbuf, smb_uid); int pnum = -1; int smb_ofun = SVAL(inbuf,smb_vwv8); @@ -95,7 +95,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(3,("Known pipe %s opening.\n",fname)); smb_ofun |= 0x10; /* Add Create it not exists flag */ - pnum = open_rpc_pipe_hnd(fname, cnum, vuid); + pnum = open_rpc_pipe_hnd(fname, conn, vuid); if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); /* Prepare the reply */ @@ -134,13 +134,10 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); - int cnum; int nread = -1; char *data; BOOL ok = False; - cnum = SVAL(inbuf,smb_tid); - /* CHECK_FNUM(fnum,cnum); CHECK_READ(fnum); @@ -161,8 +158,8 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - DEBUG( 3, ( "readX pnum=%04x cnum=%d min=%d max=%d nread=%d\n", - pnum, cnum, smb_mincnt, smb_maxcnt, nread ) ); + DEBUG(3,("readX pnum=%04x min=%d max=%d nread=%d\n", + pnum, smb_mincnt, smb_maxcnt, nread)); set_chain_pnum(pnum); @@ -171,15 +168,14 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a close ****************************************************************************/ -int reply_pipe_close(char *inbuf,char *outbuf) +int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) { int pnum = get_rpc_pipe_num(inbuf,smb_vwv0); - int cnum = SVAL(inbuf,smb_tid); int outsize = set_message(outbuf,0,0,True); - DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum)); + DEBUG(5,("reply_pipe_close: pnum:%x\n", pnum)); - if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid)); + if (!close_rpc_pipe_hnd(pnum, conn)) return(ERROR(ERRDOS,ERRbadfid)); return(outsize); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b0509bf3d5..66d1dd2839 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -35,7 +35,6 @@ extern int max_send; extern int max_recv; extern int chain_fnum; extern char magic_char; -extern connection_struct Connections[]; extern files_struct Files[]; extern BOOL case_sensitive; extern BOOL case_preserve; @@ -82,7 +81,7 @@ int reply_special(char *inbuf,char *outbuf) *name1 = *name2 = 0; - bzero(outbuf,smb_size); + bzero(outbuf,smb_size); smb_setlen(outbuf,0); @@ -127,7 +126,7 @@ int reply_special(char *inbuf,char *outbuf) reopen_logs(); if (lp_status(-1)) { - claim_connection(-1,"STATUS.",MAXSTATUS,True); + claim_connection(NULL,"STATUS.",MAXSTATUS,True); } break; @@ -149,8 +148,8 @@ int reply_special(char *inbuf,char *outbuf) return(0); } - DEBUG( 5, ( "init msg_type=0x%x msg_flags=0x%x\n", - msg_type, msg_flags ) ); + DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n", + msg_type, msg_flags)); return(outsize); } @@ -159,26 +158,13 @@ int reply_special(char *inbuf,char *outbuf) /******************************************************************* work out what error to give to a failed connection ********************************************************************/ -static int connection_error(char *inbuf,char *outbuf,int connection_num) +static int connection_error(char *inbuf,char *outbuf,int ecode) { - switch (connection_num) - { - case -8: - return(ERROR(ERRSRV,ERRnoresource)); - case -7: - return(ERROR(ERRSRV,ERRbaduid)); - case -6: - return(ERROR(ERRSRV,ERRinvdevice)); - case -5: - return(ERROR(ERRSRV,ERRinvnetname)); - case -4: - return(ERROR(ERRSRV,ERRaccess)); - case -3: - return(ERROR(ERRDOS,ERRnoipc)); - case -2: - return(ERROR(ERRSRV,ERRinvnetname)); - } - return(ERROR(ERRSRV,ERRbadpw)); + if (ecode == ERRnoipc) { + return(ERROR(ERRDOS,ERRnoipc)); + } + + return(ERROR(ERRSRV,ecode)); } @@ -223,147 +209,145 @@ static void parse_connect(char *p,char *service,char *user, /**************************************************************************** reply to a tcon ****************************************************************************/ -int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_tcon(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring service; - pstring user; - pstring password; - pstring dev; - int connection_num; - int outsize = 0; - uint16 vuid = SVAL(inbuf,smb_uid); - int pwlen=0; - - *service = *user = *password = *dev = 0; - - parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ + pstring service; + pstring user; + pstring password; + pstring dev; + int outsize = 0; + uint16 vuid = SVAL(inbuf,smb_uid); + int pwlen=0; + int ecode = -1; + + *service = *user = *password = *dev = 0; + + parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ - (void)map_username(user); + (void)map_username(user); - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); - connection_num = make_connection(service,user,password,pwlen,dev,vuid); + conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode); - if (connection_num < 0) - return(connection_error(inbuf,outbuf,connection_num)); + if (!conn) { + return(connection_error(inbuf,outbuf,ecode)); + } - outsize = set_message(outbuf,2,0,True); - SSVAL(outbuf,smb_vwv0,max_recv); - SSVAL(outbuf,smb_vwv1,connection_num); - SSVAL(outbuf,smb_tid,connection_num); + outsize = set_message(outbuf,2,0,True); + SSVAL(outbuf,smb_vwv0,max_recv); + SSVAL(outbuf,smb_vwv1,conn->cnum); + SSVAL(outbuf,smb_tid,conn->cnum); - DEBUG(3,("tcon service=%s user=%s cnum=%d\n", service, user, connection_num)); + DEBUG(3,("tcon service=%s user=%s cnum=%d\n", + service, user, conn->cnum)); - return(outsize); + return(outsize); } /**************************************************************************** reply to a tcon and X ****************************************************************************/ -int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) +int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - pstring service; - pstring user; - pstring password; - pstring devicename; - int connection_num; - uint16 vuid = SVAL(inbuf,smb_uid); - int passlen = SVAL(inbuf,smb_vwv3); - - *service = *user = *password = *devicename = 0; - - /* we might have to close an old one */ - if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) - close_cnum(SVAL(inbuf,smb_tid),vuid); - - if (passlen > MAX_PASS_LEN) { - overflow_attack(passlen); - } - - { - char *path; - char *p; - memcpy(password,smb_buf(inbuf),passlen); - password[passlen]=0; - path = smb_buf(inbuf) + passlen; - - if (passlen != 24) { - if (strequal(password," ")) - *password = 0; - passlen = strlen(password); - } - - fstrcpy(service,path+2); - p = strchr(service,'\\'); - if (!p) - return(ERROR(ERRSRV,ERRinvnetname)); - *p = 0; - fstrcpy(service,p+1); - p = strchr(service,'%'); - if (p) - { - *p++ = 0; - fstrcpy(user,p); - } - StrnCpy(devicename,path + strlen(path) + 1,6); - DEBUG(4,("Got device type %s\n",devicename)); - } - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); + pstring service; + pstring user; + pstring password; + pstring devicename; + int ecode = -1; + uint16 vuid = SVAL(inbuf,smb_uid); + int passlen = SVAL(inbuf,smb_vwv3); + char *path; + char *p; + + *service = *user = *password = *devicename = 0; - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); + /* we might have to close an old one */ + if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { + close_cnum(conn,vuid); + } - connection_num = make_connection(service,user,password,passlen,devicename,vuid); + if (passlen > MAX_PASS_LEN) { + overflow_attack(passlen); + } - if (connection_num < 0) - return(connection_error(inbuf,outbuf,connection_num)); + memcpy(password,smb_buf(inbuf),passlen); + password[passlen]=0; + path = smb_buf(inbuf) + passlen; - if (Protocol < PROTOCOL_NT1) - { - set_message(outbuf,2,strlen(devicename)+1,True); - pstrcpy(smb_buf(outbuf),devicename); - } - else - { - char *fsname = FSTYPE_STRING; - char *p; + if (passlen != 24) { + if (strequal(password," ")) + *password = 0; + passlen = strlen(password); + } + + fstrcpy(service,path+2); + p = strchr(service,'\\'); + if (!p) + return(ERROR(ERRSRV,ERRinvnetname)); + *p = 0; + fstrcpy(service,p+1); + p = strchr(service,'%'); + if (p) { + *p++ = 0; + fstrcpy(user,p); + } + StrnCpy(devicename,path + strlen(path) + 1,6); + DEBUG(4,("Got device type %s\n",devicename)); - set_message(outbuf,3,3,True); + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam(user, True); + + conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode); + + if (!conn) + return(connection_error(inbuf,outbuf,ecode)); - p = smb_buf(outbuf); - pstrcpy(p,devicename); p = skip_string(p,1); /* device name */ - pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ + if (Protocol < PROTOCOL_NT1) { + set_message(outbuf,2,strlen(devicename)+1,True); + pstrcpy(smb_buf(outbuf),devicename); + } else { + char *fsname = FSTYPE_STRING; + char *p; - set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + set_message(outbuf,3,3,True); - SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */ - } + p = smb_buf(outbuf); + pstrcpy(p,devicename); p = skip_string(p,1); /* device name */ + pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ + + set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + + SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */ + } - DEBUG( 3, ( "tconX service=%s user=%s cnum=%d\n", - service, user, connection_num ) ); + DEBUG(3,("tconX service=%s user=%s\n", + service, user)); - /* set the incoming and outgoing tid to the just created one */ - SSVAL(inbuf,smb_tid,connection_num); - SSVAL(outbuf,smb_tid,connection_num); + /* set the incoming and outgoing tid to the just created one */ + SSVAL(inbuf,smb_tid,conn->cnum); + SSVAL(outbuf,smb_tid,conn->cnum); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -372,37 +356,36 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) ****************************************************************************/ int reply_unknown(char *inbuf,char *outbuf) { - int cnum; - int type; - cnum = SVAL(inbuf,smb_tid); - type = CVAL(inbuf,smb_com); + int type; + type = CVAL(inbuf,smb_com); - DEBUG(0,("unknown command type (%s): cnum=%d type=%d (0x%X)\n", - smb_fn_name(type), cnum, type, type)); + DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n", + smb_fn_name(type), type, type)); - return(ERROR(ERRSRV,ERRunknownsmb)); + return(ERROR(ERRSRV,ERRunknownsmb)); } /**************************************************************************** reply to an ioctl ****************************************************************************/ -int reply_ioctl(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_ioctl(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - DEBUG(3,("ignoring ioctl\n")); + DEBUG(3,("ignoring ioctl\n")); #if 0 - /* we just say it succeeds and hope its all OK. - some day it would be nice to interpret them individually */ - return set_message(outbuf,1,0,True); + /* we just say it succeeds and hope its all OK. + some day it would be nice to interpret them individually */ + return set_message(outbuf,1,0,True); #else - return(ERROR(ERRSRV,ERRnosupport)); + return(ERROR(ERRSRV,ERRnosupport)); #endif } /**************************************************************************** always return an error: it's just a matter of which one... ****************************************************************************/ -static int session_trust_account(char *inbuf, char *outbuf, char *user, +static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user, char *smb_passwd, int smb_passlen, char *smb_nt_passwd, int smb_nt_passlen) { @@ -472,7 +455,7 @@ static int session_trust_account(char *inbuf, char *outbuf, char *user, /**************************************************************************** reply to a session setup command ****************************************************************************/ -int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) +int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 sess_vuid; int gid; @@ -602,7 +585,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* say yes to everything ending in $. */ if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) { - return session_trust_account(inbuf, outbuf, user, + return session_trust_account(conn, inbuf, outbuf, user, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen); } @@ -769,22 +752,20 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a chkpth ****************************************************************************/ -int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; - int cnum,mode; + int mode; pstring name; BOOL ok = False; BOOL bad_path = False; - cnum = SVAL(inbuf,smb_tid); - pstrcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,cnum,0,&bad_path); + unix_convert(name,conn,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); - if (check_name(name,cnum)) + if (check_name(name,conn)) ok = directory_exist(name,NULL); if (!ok) @@ -815,7 +796,7 @@ int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "chkpth %s cnum=%d mode=%d\n", name, cnum, mode ) ); + DEBUG(3,("chkpth %s mode=%d\n", name, mode)); return(outsize); } @@ -824,10 +805,9 @@ int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a getatr ****************************************************************************/ -int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; - int cnum; int outsize = 0; struct stat sbuf; BOOL ok = False; @@ -836,27 +816,25 @@ int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) time_t mtime=0; BOOL bad_path = False; - cnum = SVAL(inbuf,smb_tid); - pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (! (*fname)) { mode = aHIDDEN | aDIR; - if (!CAN_WRITE(cnum)) mode |= aRONLY; + if (!CAN_WRITE(conn)) mode |= aRONLY; size = 0; mtime = 0; ok = True; } else - if (check_name(fname,cnum)) + if (check_name(fname,conn)) { if (sys_stat(fname,&sbuf) == 0) { - mode = dos_mode(cnum,fname,&sbuf); + mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; mtime = sbuf.st_mtime; if (mode & aDIR) @@ -881,7 +859,7 @@ int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,10,0,True); SSVAL(outbuf,smb_vwv0,mode); - if(lp_dos_filetime_resolution(SNUM(cnum)) ) + if(lp_dos_filetime_resolution(SNUM(conn)) ) put_dos_date3(outbuf,smb_vwv1,mtime & ~1); else put_dos_date3(outbuf,smb_vwv1,mtime); @@ -904,30 +882,27 @@ int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a setatr ****************************************************************************/ -int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; - int cnum; int outsize = 0; BOOL ok=False; int mode; time_t mtime; BOOL bad_path = False; - cnum = SVAL(inbuf,smb_tid); - pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); if (directory_exist(fname,NULL)) mode |= aDIR; - if (check_name(fname,cnum)) - ok = (dos_chmod(cnum,fname,mode,NULL) == 0); + if (check_name(fname,conn)) + ok = (dos_chmod(conn,fname,mode,NULL) == 0); if (ok) - ok = set_filetime(cnum,fname,mtime); + ok = set_filetime(conn,fname,mtime); if (!ok) { @@ -951,14 +926,11 @@ int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a dskattr ****************************************************************************/ -int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum; int outsize = 0; int dfree,dsize,bsize; - cnum = SVAL(inbuf,smb_tid); - sys_disk_free(".",&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -968,7 +940,7 @@ int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_vwv2,512); SSVAL(outbuf,smb_vwv3,dfree); - DEBUG( 3, ( "dskattr cnum=%d dfree=%d\n", cnum, dfree ) ); + DEBUG(3,("dskattr dfree=%d\n", dfree)); return(outsize); } @@ -978,7 +950,7 @@ int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) reply to a search Can be called from SMBsearch, SMBffirst or SMBfunique. ****************************************************************************/ -int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring mask; pstring directory; @@ -986,7 +958,6 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int size,mode; time_t date; int dirtype; - int cnum; int outsize = 0; int numentries = 0; BOOL finished = False; @@ -1009,8 +980,6 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(CVAL(inbuf,smb_com) == SMBffirst) expect_close = True; - cnum = SVAL(inbuf,smb_tid); - outsize = set_message(outbuf,1,3,True); maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); @@ -1029,10 +998,10 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) pstrcpy(directory,smb_buf(inbuf)+1); pstrcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,cnum,0,&bad_path); + unix_convert(directory,conn,0,&bad_path); unix_format(dir2); - if (!check_name(directory,cnum)) + if (!check_name(directory,conn)) can_open = False; p = strrchr(dir2,'/'); @@ -1064,10 +1033,10 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) memcpy(mask,status+1,11); mask[11] = 0; dirtype = CVAL(status,0) & 0x1F; - Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num); - if (!Connections[cnum].dirptr) + conn->dirptr = dptr_fetch(status+12,&dptr_num); + if (!conn->dirptr) goto SearchEmpty; - string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); + string_set(&conn->dirpath,dptr_path(dptr_num)); if (!case_sensitive) strnorm(mask); } @@ -1119,7 +1088,7 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (status_len == 0) { - dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid)); + dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid)); if (dptr_num < 0) { if(dptr_num == -2) @@ -1142,7 +1111,7 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if ((dirtype&0x1F) == aVOLID) { memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0); + make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; @@ -1152,15 +1121,16 @@ int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } else { - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); - if (in_list(Connections[cnum].dirpath, - lp_dontdescend(SNUM(cnum)),True)) + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", + conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath, + lp_dontdescend(SNUM(conn)),True)) check_descend = True; for (i=numentries;(iopen) @@ -1326,7 +1290,7 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); + fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { @@ -1338,14 +1302,14 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,7,0,True); SSVAL(outbuf,smb_vwv0,fnum); SSVAL(outbuf,smb_vwv1,fmode); - if(lp_dos_filetime_resolution(SNUM(cnum)) ) + if(lp_dos_filetime_resolution(SNUM(conn)) ) put_dos_date3(outbuf,smb_vwv2,mtime & ~1); else put_dos_date3(outbuf,smb_vwv2,mtime); SIVAL(outbuf,smb_vwv4,size); SSVAL(outbuf,smb_vwv6,rmode); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } @@ -1358,10 +1322,9 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to an open and X ****************************************************************************/ -int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) +int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; - int cnum = SVAL(inbuf,smb_tid); int fnum = -1; int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); @@ -1384,13 +1347,13 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) files_struct *fsp; /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(cnum)) - return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize); + if (IS_IPC(conn)) + return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); - unix_convert(fname,cnum,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); fnum = find_free_file(); if (fnum < 0) @@ -1398,7 +1361,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) fsp = &Files[fnum]; - if (!check_name(fname,cnum)) + if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) { @@ -1409,9 +1372,9 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(cnum,smb_attr | aARCH); + unixmode = unix_mode(conn,smb_attr | aARCH); - open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, + open_file_shared(fnum,conn,fname,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp->open) @@ -1431,7 +1394,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) } size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); + fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { close_file(fnum,False); @@ -1443,7 +1406,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) correct bit for extended oplock reply. */ - if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) { + if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) { smb_action |= EXTENDED_OPLOCK_GRANTED; } @@ -1456,7 +1419,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) correct bit for core oplock reply. */ - if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) { + if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } @@ -1467,7 +1430,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,15,0,True); SSVAL(outbuf,smb_vwv2,fnum); SSVAL(outbuf,smb_vwv3,fmode); - if(lp_dos_filetime_resolution(SNUM(cnum)) ) + if(lp_dos_filetime_resolution(SNUM(conn)) ) put_dos_date3(outbuf,smb_vwv4,mtime & ~1); else put_dos_date3(outbuf,smb_vwv4,mtime); @@ -1484,7 +1447,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a SMBulogoffX ****************************************************************************/ -int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) +int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 vuid = SVAL(inbuf,smb_uid); user_struct *vuser = get_valid_user_struct(vuid); @@ -1521,10 +1484,10 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a mknew or a create ****************************************************************************/ -int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; - int cnum,com; + int com; int fnum = -1; int outsize = 0; int createmode; @@ -1535,18 +1498,17 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int oplock_request = CORE_OPLOCK_REQUEST(inbuf); com = SVAL(inbuf,smb_com); - cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); if (createmode & aVOLID) { DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); } - unixmode = unix_mode(cnum,createmode); + unixmode = unix_mode(conn,createmode); fnum = find_free_file(); if (fnum < 0) @@ -1554,7 +1516,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) fsp = &Files[fnum]; - if (!check_name(fname,cnum)) + if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) { @@ -1577,7 +1539,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } /* Open file in dos compatibility share mode. */ - open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, + open_file_shared(fnum,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, oplock_request, NULL, NULL); if (!fsp->open) @@ -1594,7 +1556,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } @@ -1602,8 +1564,8 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG( 2, ( "new file %s\n", fname ) ); - DEBUG( 3, ( "mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", - fname, fsp->fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); + DEBUG( 3, ( "mknew %s fd=%d fnum=%d dmode=%d umode=%o\n", + fname, fsp->fd_ptr->fd, fnum, createmode, unixmode ) ); return(outsize); } @@ -1612,11 +1574,10 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a create temporary file ****************************************************************************/ -int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; pstring fname2; - int cnum; int fnum = -1; int outsize = 0; int createmode; @@ -1625,13 +1586,12 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); - unix_convert(fname,cnum,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); - unixmode = unix_mode(cnum,createmode); + unixmode = unix_mode(conn,createmode); fnum = find_free_file(); if (fnum < 0) @@ -1639,7 +1599,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) fsp = &Files[fnum]; - if (!check_name(fname,cnum)) + if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) { @@ -1654,7 +1614,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, + open_file_shared(fnum,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, oplock_request, NULL, NULL); if (!fsp->open) @@ -1673,7 +1633,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(smb_buf(outbuf),0) = 4; pstrcpy(smb_buf(outbuf) + 1,fname2); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } @@ -1681,8 +1641,8 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG( 2, ( "created temp file %s\n", fname2 ) ); - DEBUG( 3, ( "ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", - fname2, fsp->fd_ptr->fd, fnum, cnum, createmode, unixmode ) ); + DEBUG( 3, ( "ctemp %s fd=%d fnum=%d dmode=%d umode=%o\n", + fname2, fsp->fd_ptr->fd, fnum, createmode, unixmode ) ); return(outsize); } @@ -1691,33 +1651,32 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /******************************************************************* check if a user is allowed to delete a file ********************************************************************/ -static BOOL can_delete(char *fname,int cnum,int dirtype) +static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) { struct stat sbuf; int fmode; - if (!CAN_WRITE(cnum)) return(False); + if (!CAN_WRITE(conn)) return(False); if (sys_lstat(fname,&sbuf) != 0) return(False); - fmode = dos_mode(cnum,fname,&sbuf); + fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); - if (!lp_delete_readonly(SNUM(cnum))) { + if (!lp_delete_readonly(SNUM(conn))) { if (fmode & aRONLY) return(False); } if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return(False); - if (!check_file_sharing(cnum,fname,False)) return(False); + if (!check_file_sharing(conn,fname,False)) return(False); return(True); } /**************************************************************************** reply to a unlink ****************************************************************************/ -int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; pstring name; - int cnum; int dirtype; pstring directory; pstring mask; @@ -1730,14 +1689,13 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) *directory = *mask = 0; - cnum = SVAL(inbuf,smb_tid); dirtype = SVAL(inbuf,smb_vwv0); pstrcpy(name,smb_buf(inbuf) + 1); DEBUG(3,("reply_unlink : %s\n",name)); - unix_convert(name,cnum,0,&bad_path); + unix_convert(name,conn,0,&bad_path); p = strrchr(name,'/'); if (!p) { @@ -1757,14 +1715,14 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++; + if (can_delete(directory,conn,dirtype) && !sys_unlink(directory)) count++; if (!count) exists = file_exist(directory,NULL); } else { void *dirptr = NULL; char *dname; - if (check_name(directory,cnum)) - dirptr = OpenDir(cnum, directory, True); + if (check_name(directory,conn)) + dirptr = OpenDir(conn, directory, True); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -1787,7 +1745,7 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - if (!can_delete(fname,cnum,dirtype)) continue; + if (!can_delete(fname,conn,dirtype)) continue; if (!sys_unlink(fname)) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); } @@ -1818,9 +1776,9 @@ int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a readbraw (core+ protocol) ****************************************************************************/ -int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) +int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { - int cnum,maxcount,mincount,fnum; + int maxcount,mincount,fnum; int nread = 0; uint32 startpos; char *header = outbuf; @@ -1843,7 +1801,6 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) return -1; } - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); startpos = IVAL(inbuf,smb_vwv1); @@ -1854,7 +1811,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) maxcount = MIN(65535,maxcount); maxcount = MAX(mincount,maxcount); - if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read) + if (!FNUM_OK(fnum,conn) || !Files[fnum].can_read) { DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); _smb_setlen(header,0); @@ -1866,11 +1823,11 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) fsp = &Files[fnum]; fd = fsp->fd_ptr->fd; - fname = fsp->name; + fname = fsp->fsp_name; } - if (!is_locked(fnum,cnum,maxcount,startpos, F_RDLCK)) + if (!is_locked(fnum,conn,maxcount,startpos, F_RDLCK)) { int size = fsp->size; int sizeneeded = startpos + maxcount; @@ -1889,8 +1846,8 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) if (nread < mincount) nread = 0; - DEBUG( 3, ( "readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n", - fnum, cnum, startpos, + DEBUG( 3, ( "readbraw fnum=%d start=%d max=%d min=%d nread=%d\n", + fnum, startpos, maxcount, mincount, nread ) ); #if UNSAFE_READRAW @@ -1930,9 +1887,9 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a lockread (core+ protocol) ****************************************************************************/ -int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) +int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) { - int cnum,fnum; + int fnum; int nread = -1; char *data; int outsize = 0; @@ -1940,10 +1897,9 @@ int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) int eclass; uint32 ecode; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_READ(fnum); CHECK_ERROR(fnum); @@ -1954,7 +1910,7 @@ int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fnum, cnum, numtoread, startpos, F_RDLCK, &eclass, &ecode)) + if(!do_lock( fnum, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); nread = read_file(fnum,data,startpos,numtoread); @@ -1967,8 +1923,8 @@ int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) SSVAL(outbuf,smb_vwv5,nread+3); SSVAL(smb_buf(outbuf),1,nread); - DEBUG( 3, ( "lockread fnum=%d cnum=%d num=%d nread=%d\n", - fnum, cnum, numtoread, nread ) ); + DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n", + fnum, numtoread, nread ) ); return(outsize); } @@ -1977,18 +1933,17 @@ int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) /**************************************************************************** reply to a read ****************************************************************************/ -int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,numtoread,fnum; + int numtoread,fnum; int nread = 0; char *data; uint32 startpos; int outsize = 0; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_READ(fnum); CHECK_ERROR(fnum); @@ -1999,7 +1954,7 @@ int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if (is_locked(fnum,cnum,numtoread,startpos, F_RDLCK)) + if (is_locked(fnum,conn,numtoread,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); if (numtoread > 0) @@ -2014,8 +1969,8 @@ int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(smb_buf(outbuf),0) = 1; SSVAL(smb_buf(outbuf),1,nread); - DEBUG( 3, ( "read fnum=%d cnum=%d num=%d nread=%d\n", - fnum, cnum, numtoread, nread ) ); + DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", + fnum, numtoread, nread ) ); return(outsize); } @@ -2024,31 +1979,28 @@ int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a read and X ****************************************************************************/ -int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) +int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { int fnum = GETFNUM(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); - int cnum; int nread = -1; char *data; BOOL ok = False; - cnum = SVAL(inbuf,smb_tid); - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(cnum)) + if (IS_IPC(conn)) return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_READ(fnum); CHECK_ERROR(fnum); set_message(outbuf,12,0,True); data = smb_buf(outbuf); - if (is_locked(fnum,cnum,smb_maxcnt,smb_offs, F_RDLCK)) + if (is_locked(fnum,conn,smb_maxcnt,smb_offs, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); nread = read_file(fnum,data,smb_offs,smb_maxcnt); ok = True; @@ -2060,9 +2012,8 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - DEBUG( 3, ( "readX fnum=%d cnum=%d min=%d max=%d nread=%d\n", - fnum, cnum, - smb_mincnt, smb_maxcnt, nread ) ); + DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n", + fnum, smb_mincnt, smb_maxcnt, nread ) ); chain_fnum = fnum; @@ -2073,22 +2024,21 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a writebraw (core+ or LANMAN1.0 protocol) ****************************************************************************/ -int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int nwritten=0; int total_written=0; int numtowrite=0; - int cnum,fnum; + int fnum; int outsize = 0; long startpos; char *data=NULL; BOOL write_through; int tcount; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_WRITE(fnum); CHECK_ERROR(fnum); @@ -2110,17 +2060,17 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(inbuf,smb_com) = SMBwritec; CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fnum,cnum,tcount,startpos, F_WRLCK)) + if (is_locked(fnum,conn,tcount,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); if (seek_file(fnum,startpos) != startpos) - DEBUG(0,("couldn't seek to %d in writebraw\n",startpos)); + DEBUG(0,("couldn't seek to %ld in writebraw\n",startpos)); if (numtowrite>0) nwritten = write_file(fnum,data,numtowrite); - DEBUG( 3, ( "writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n", - fnum, cnum, startpos, numtowrite, nwritten, write_through ) ); + DEBUG(3,("writebraw1 fnum=%d start=%ld num=%d wrote=%d sync=%d\n", + fnum, startpos, numtowrite, nwritten, write_through)); if (nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -2162,11 +2112,11 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVAL(outbuf,smb_err,ERRdiskfull); } - if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(cnum,fnum); + if (lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fnum); - DEBUG( 3, ( "writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n", - fnum, cnum, startpos, numtowrite, total_written ) ); + DEBUG(3,("writebraw2 fnum=%d start=%ld num=%d wrote=%d\n", + fnum, startpos, numtowrite, total_written)); /* we won't return a status if write through is not selected - this follows what WfWg does */ @@ -2180,9 +2130,9 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a writeunlock (core+) ****************************************************************************/ -int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,fnum; + int fnum; int nwritten = -1; int outsize = 0; char *data; @@ -2190,10 +2140,9 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int eclass; uint32 ecode; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_WRITE(fnum); CHECK_ERROR(fnum); @@ -2201,7 +2150,7 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK)) + if (is_locked(fnum,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,startpos); @@ -2214,21 +2163,21 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) else nwritten = write_file(fnum,data,numtowrite); - if (lp_syncalways(SNUM(cnum))) - sync_file(cnum,fnum); + if (lp_syncalways(SNUM(conn))) + sync_file(conn,fnum); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode)) + if(!do_unlock(fnum, conn, numtowrite, startpos, &eclass, &ecode)) return(ERROR(eclass,ecode)); outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); - DEBUG( 3, ( "writeunlock fnum=%d cnum=%d num=%d wrote=%d\n", - fnum, cnum, numtowrite, nwritten ) ); + DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n", + fnum, numtowrite, nwritten ) ); return(outsize); } @@ -2237,18 +2186,17 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a write ****************************************************************************/ -int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) +int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize) { - int cnum,numtowrite,fnum; + int numtowrite,fnum; int nwritten = -1; int outsize = 0; int startpos; char *data; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_WRITE(fnum); CHECK_ERROR(fnum); @@ -2256,7 +2204,7 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK)) + if (is_locked(fnum,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,startpos); @@ -2269,8 +2217,8 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) else nwritten = write_file(fnum,data,numtowrite); - if (lp_syncalways(SNUM(cnum))) - sync_file(cnum,fnum); + if (lp_syncalways(SNUM(conn))) + sync_file(conn,fnum); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2284,8 +2232,8 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) SSVAL(outbuf,smb_err,ERRdiskfull); } - DEBUG( 3, ( "%s write fnum=%d cnum=%d num=%d wrote=%d\n", - fnum, cnum, numtowrite, nwritten ) ); + DEBUG(3,("write fnum=%d num=%d wrote=%d\n", + fnum, numtowrite, nwritten)); return(outsize); } @@ -2294,26 +2242,23 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) /**************************************************************************** reply to a write and X ****************************************************************************/ -int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) +int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { int fnum = GETFNUM(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_dsize = SVAL(inbuf,smb_vwv10); int smb_doff = SVAL(inbuf,smb_vwv11); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); - int cnum; int nwritten = -1; char *data; - cnum = SVAL(inbuf,smb_tid); - - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_WRITE(fnum); CHECK_ERROR(fnum); data = smb_base(inbuf) + smb_doff; - if (is_locked(fnum,cnum,smb_dsize,smb_offs, F_WRLCK)) + if (is_locked(fnum,conn,smb_dsize,smb_offs, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,smb_offs); @@ -2339,13 +2284,13 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_err,ERRdiskfull); } - DEBUG( 3, ( "%s writeX fnum=%d cnum=%d num=%d wrote=%d\n", - fnum, cnum, smb_dsize, nwritten ) ); + DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", + fnum, smb_dsize, nwritten)); chain_fnum = fnum; - if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(cnum,fnum); + if (lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fnum); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2354,19 +2299,18 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a lseek ****************************************************************************/ -int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,fnum; + int fnum; uint32 startpos; int32 res= -1; int mode,umode; int outsize = 0; files_struct *fsp; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); mode = SVAL(inbuf,smb_vwv1) & 3; @@ -2389,8 +2333,8 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,2,0,True); SIVALS(outbuf,smb_vwv0,res); - DEBUG( 3, ( "lseek fnum=%d cnum=%d ofs=%d mode=%d\n", - fnum, cnum, startpos, mode ) ); + DEBUG(3,("lseek fnum=%d ofs=%d mode=%d\n", + fnum, startpos, mode)); return(outsize); } @@ -2399,28 +2343,28 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a flush ****************************************************************************/ -int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum, fnum; + int fnum; int outsize = set_message(outbuf,0,0,True); - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); if (fnum != 0xFFFF) { - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); } - if (fnum == 0xFFFF) - { - int i; - for (i=0;iwbmpx_ptr->wr_errclass; - err = fsp->wbmpx_ptr->wr_error; - } - - if(fsp->is_directory) { - /* - * Special case - close NT SMB directory - * handle. - */ - DEBUG( 3, ( "close directory fnum=%d cnum=%d\n", - fnum, cnum ) ); - close_directory( fnum ); - } else { - /* - * Close ordinary file. - */ - mtime = make_unix_date3(inbuf+smb_vwv1); + if(HAS_CACHED_ERROR(fnum)) { + eclass = fsp->wbmpx_ptr->wr_errclass; + err = fsp->wbmpx_ptr->wr_error; + } - /* try and set the date */ - set_filetime(cnum, fsp->name,mtime); + if(fsp->is_directory) { + /* + * Special case - close NT SMB directory + * handle. + */ + DEBUG(3,("close directory fnum=%d\n", fnum)); + close_directory(fnum); + } else { + /* + * Close ordinary file. + */ + mtime = make_unix_date3(inbuf+smb_vwv1); + + /* try and set the date */ + set_filetime(conn, fsp->fsp_name,mtime); - DEBUG( 3, ( "close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - fsp->fd_ptr->fd, fnum, cnum, - Connections[cnum].num_files_open ) ); + DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", + fsp->fd_ptr->fd, fnum, + conn->num_files_open)); - close_file(fnum,True); - } + close_file(fnum,True); + } - /* We have a cached error */ - if(eclass || err) - return(ERROR(eclass,err)); + /* We have a cached error */ + if(eclass || err) + return(ERROR(eclass,err)); - return(outsize); + return(outsize); } /**************************************************************************** reply to a writeclose (Core+ protocol) ****************************************************************************/ -int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_writeclose(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,numtowrite,fnum; - int nwritten = -1; - int outsize = 0; - int startpos; - char *data; - time_t mtime; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - mtime = make_unix_date3(inbuf+smb_vwv4); - data = smb_buf(inbuf) + 1; - - if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK)) - return(ERROR(ERRDOS,ERRlock)); + int numtowrite,fnum; + int nwritten = -1; + int outsize = 0; + int startpos; + char *data; + time_t mtime; + + fnum = GETFNUM(inbuf,smb_vwv0); + + CHECK_FNUM(fnum,conn); + CHECK_WRITE(fnum); + CHECK_ERROR(fnum); + + numtowrite = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + mtime = make_unix_date3(inbuf+smb_vwv4); + data = smb_buf(inbuf) + 1; + + if (is_locked(fnum,conn,numtowrite,startpos, F_WRLCK)) + return(ERROR(ERRDOS,ERRlock)); - seek_file(fnum,startpos); + seek_file(fnum,startpos); - nwritten = write_file(fnum,data,numtowrite); + nwritten = write_file(fnum,data,numtowrite); - set_filetime(cnum, Files[fnum].name,mtime); + set_filetime(conn, Files[fnum].fsp_name,mtime); - close_file(fnum,True); + close_file(fnum,True); - DEBUG( 3, ( "writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", - fnum, cnum, numtowrite, nwritten, - Connections[cnum].num_files_open ) ); + DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n", + fnum, numtowrite, nwritten, + conn->num_files_open)); - if (nwritten <= 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if (nwritten <= 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); - outsize = set_message(outbuf,1,0,True); + outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,nwritten); - return(outsize); + SSVAL(outbuf,smb_vwv0,nwritten); + return(outsize); } /**************************************************************************** reply to a lock ****************************************************************************/ -int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_lock(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum,cnum; - int outsize = set_message(outbuf,0,0,True); - uint32 count,offset; - int eclass; - uint32 ecode; + int fnum; + int outsize = set_message(outbuf,0,0,True); + uint32 count,offset; + int eclass; + uint32 ecode; - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); + fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); + CHECK_FNUM(fnum,conn); + CHECK_ERROR(fnum); - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); + count = IVAL(inbuf,smb_vwv1); + offset = IVAL(inbuf,smb_vwv3); - DEBUG( 3, ("lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", - Files[fnum].fd_ptr->fd, fnum, cnum, offset, count ) ); + DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n", + Files[fnum].fd_ptr->fd, fnum, offset, count)); - if(!do_lock( fnum, cnum, count, offset, F_WRLCK, &eclass, &ecode)) - return (ERROR(eclass,ecode)); + if (!do_lock(fnum, conn, count, offset, F_WRLCK, &eclass, &ecode)) + return (ERROR(eclass,ecode)); - return(outsize); + return(outsize); } /**************************************************************************** reply to a unlock ****************************************************************************/ -int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum,cnum; + int fnum; int outsize = set_message(outbuf,0,0,True); uint32 count,offset; int eclass; uint32 ecode; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); - if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode)) + if(!do_unlock(fnum, conn, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); - DEBUG( 3, ( "unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", - Files[fnum].fd_ptr->fd, fnum, cnum, offset, count ) ); + DEBUG( 3, ( "unlock fd=%d fnum=%d ofs=%d cnt=%d\n", + Files[fnum].fd_ptr->fd, fnum, offset, count ) ); return(outsize); } @@ -2619,27 +2561,24 @@ int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a tdis ****************************************************************************/ -int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_tdis(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum; - int outsize = set_message(outbuf,0,0,True); - uint16 vuid; + int outsize = set_message(outbuf,0,0,True); + uint16 vuid; - cnum = SVAL(inbuf,smb_tid); - vuid = SVAL(inbuf,smb_uid); + vuid = SVAL(inbuf,smb_uid); - if (!OPEN_CNUM(cnum)) { - DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum)); - return(ERROR(ERRSRV,ERRinvnid)); - } + if (!conn) { + DEBUG(4,("Invalid connection in tdis\n")); + return(ERROR(ERRSRV,ERRinvnid)); + } - Connections[cnum].used = False; + conn->used = False; - close_cnum(cnum,vuid); + close_cnum(conn,vuid); - DEBUG( 3, ( "tdis cnum=%d\n", cnum ) ); - - return outsize; + return outsize; } @@ -2647,261 +2586,217 @@ int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a echo ****************************************************************************/ -int reply_echo(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_echo(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum; - int smb_reverb = SVAL(inbuf,smb_vwv0); - int seq_num; - int data_len = smb_buflen(inbuf); - int outsize = set_message(outbuf,1,data_len,True); - - cnum = SVAL(inbuf,smb_tid); - - /* According to the latest CIFS spec we shouldn't - care what the TID is. - */ - -#if 0 - if (cnum != 0xFFFF && !OPEN_CNUM(cnum)) - { - DEBUG(4,("Invalid cnum in echo (%d)\n",cnum)); - return(ERROR(ERRSRV,ERRinvnid)); - } -#endif + int smb_reverb = SVAL(inbuf,smb_vwv0); + int seq_num; + int data_len = smb_buflen(inbuf); + int outsize = set_message(outbuf,1,data_len,True); + + /* copy any incoming data back out */ + if (data_len > 0) + memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len); - /* copy any incoming data back out */ - if (data_len > 0) - memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len); + if (smb_reverb > 100) { + DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb)); + smb_reverb = 100; + } - if (smb_reverb > 100) - { - DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb)); - smb_reverb = 100; - } + for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) { + SSVAL(outbuf,smb_vwv0,seq_num); - for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) - { - SSVAL(outbuf,smb_vwv0,seq_num); + smb_setlen(outbuf,outsize - 4); - smb_setlen(outbuf,outsize - 4); - - send_smb(Client,outbuf); - } + send_smb(Client,outbuf); + } - DEBUG( 3, ( "echo %d times cnum=%d\n", smb_reverb, cnum ) ); + DEBUG(3,("echo %d times\n", smb_reverb)); - return -1; + return -1; } /**************************************************************************** reply to a printopen ****************************************************************************/ -int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_printopen(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring fname; - pstring fname2; - int cnum; - int fnum = -1; - int outsize = 0; - files_struct *fsp; - - *fname = *fname2 = 0; - - cnum = SVAL(inbuf,smb_tid); - - if (!CAN_PRINT(cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); - - { - pstring s; - char *p; - pstrcpy(s,smb_buf(inbuf)+1); - p = s; - while (*p) - { - if (!(isalnum(*p) || strchr("._-",*p))) - *p = 'X'; - p++; - } + pstring fname; + pstring fname2; + int fnum = -1; + int outsize = 0; + files_struct *fsp; + + *fname = *fname2 = 0; + + if (!CAN_PRINT(conn)) + return(ERROR(ERRDOS,ERRnoaccess)); - if (strlen(s) > 10) s[10] = 0; + { + pstring s; + char *p; + pstrcpy(s,smb_buf(inbuf)+1); + p = s; + while (*p) { + if (!(isalnum(*p) || strchr("._-",*p))) + *p = 'X'; + p++; + } - slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s); - } + if (strlen(s) > 10) s[10] = 0; - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); + slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s); + } - fsp = &Files[fnum]; + fnum = find_free_file(); + if (fnum < 0) + return(ERROR(ERRSRV,ERRnofids)); - pstrcpy(fname2,(char *)mktemp(fname)); + fsp = &Files[fnum]; + + pstrcpy(fname2,(char *)mktemp(fname)); - if (!check_name(fname2,cnum)) { - fsp->reserved = False; - return(ERROR(ERRDOS,ERRnoaccess)); - } + if (!check_name(fname2,conn)) { + fsp->reserved = False; + return(ERROR(ERRDOS,ERRnoaccess)); + } - /* Open for exclusive use, write only. */ - open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), - 0, NULL, NULL); + /* Open for exclusive use, write only. */ + open_file_shared(fnum,conn,fname2, + (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0), + 0, NULL, NULL); - if (!fsp->open) { - fsp->reserved = False; - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if (!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - /* force it to be a print file */ - fsp->print_file = True; + /* force it to be a print file */ + fsp->print_file = True; - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fnum); + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,fnum); - DEBUG( 3, ("openprint %s fd=%d fnum=%d cnum=%d\n", - fname2, fsp->fd_ptr->fd, fnum, cnum ) ); + DEBUG(3,("openprint %s fd=%d fnum=%d\n", + fname2, fsp->fd_ptr->fd, fnum)); - return(outsize); + return(outsize); } /**************************************************************************** reply to a printclose ****************************************************************************/ -int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_printclose(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum,cnum; - int outsize = set_message(outbuf,0,0,True); + int fnum; + int outsize = set_message(outbuf,0,0,True); - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); + fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); + CHECK_FNUM(fnum,conn); + CHECK_ERROR(fnum); - if (!CAN_PRINT(cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); + if (!CAN_PRINT(conn)) + return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG( 3, ( "printclose fd=%d fnum=%d cnum=%d\n", - Files[fnum].fd_ptr->fd,fnum,cnum)); + DEBUG(3,("printclose fd=%d fnum=%d\n", + Files[fnum].fd_ptr->fd,fnum)); - close_file(fnum,True); + close_file(fnum,True); - return(outsize); + return(outsize); } /**************************************************************************** reply to a printqueue ****************************************************************************/ -int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_printqueue(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum; - int outsize = set_message(outbuf,2,3,True); - int max_count = SVAL(inbuf,smb_vwv0); - int start_index = SVAL(inbuf,smb_vwv1); - uint16 vuid; - - cnum = SVAL(inbuf,smb_tid); - vuid = SVAL(inbuf,smb_uid); - -/* allow checking the queue for anyone */ -#if 0 - if (!CAN_PRINT(cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); -#endif - - SSVAL(outbuf,smb_vwv0,0); - SSVAL(outbuf,smb_vwv1,0); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,0); + int outsize = set_message(outbuf,2,3,True); + int max_count = SVAL(inbuf,smb_vwv0); + int start_index = SVAL(inbuf,smb_vwv1); + uint16 vuid; + + vuid = SVAL(inbuf,smb_uid); + + /* we used to allow the client to get the cnum wrong, but that + is really quite gross and only worked when there was only + one printer - I think we should now only accept it if they + get it right (tridge) */ + if (!CAN_PRINT(conn)) + return(ERROR(ERRDOS,ERRnoaccess)); + + SSVAL(outbuf,smb_vwv0,0); + SSVAL(outbuf,smb_vwv1,0); + CVAL(smb_buf(outbuf),0) = 1; + SSVAL(smb_buf(outbuf),1,0); - DEBUG( 3, ( "printqueue cnum=%d start_index=%d max_count=%d\n", - cnum, start_index, max_count ) ); - - if (!OPEN_CNUM(cnum) || !Connections[cnum].printer) - { - int i; - cnum = -1; - - for (i=0;i0?start_index:start_index+max_count+1); - int i; + DEBUG(3,("printqueue start_index=%d max_count=%d\n", + start_index, max_count)); - if (first >= count) - num_to_get = 0; - else - num_to_get = MIN(num_to_get,count-first); + { + print_queue_struct *queue = NULL; + char *p = smb_buf(outbuf) + 3; + int count = get_printqueue(SNUM(conn), conn,&queue,NULL); + int num_to_get = ABS(max_count); + int first = (max_count>0?start_index:start_index+max_count+1); + int i; + + if (first >= count) + num_to_get = 0; + else + num_to_get = MIN(num_to_get,count-first); - for (i=first;i 0) - { - outsize = set_message(outbuf,2,28*count+3,False); - SSVAL(outbuf,smb_vwv0,count); - SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,28*count); - } + if (count > 0) { + outsize = set_message(outbuf,2,28*count+3,False); + SSVAL(outbuf,smb_vwv0,count); + SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); + CVAL(smb_buf(outbuf),0) = 1; + SSVAL(smb_buf(outbuf),1,28*count); + } - if (queue) free(queue); + if (queue) free(queue); - DEBUG(3,("%d entries returned in queue\n",count)); - } + DEBUG(3,("%d entries returned in queue\n",count)); + } - return(outsize); + return(outsize); } /**************************************************************************** reply to a printwrite ****************************************************************************/ -int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,numtowrite,fnum; + int numtowrite,fnum; int outsize = set_message(outbuf,0,0,True); char *data; - cnum = SVAL(inbuf,smb_tid); - - if (!CAN_PRINT(cnum)) + if (!CAN_PRINT(conn)) return(ERROR(ERRDOS,ERRnoaccess)); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_WRITE(fnum); CHECK_ERROR(fnum); @@ -2911,7 +2806,7 @@ int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (write_file(fnum,data,numtowrite) != numtowrite) return(UNIXERROR(ERRDOS,ERRnoaccess)); - DEBUG( 3, ( "printwrite fnum=%d cnum=%d num=%d\n", fnum, cnum, numtowrite ) ); + DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fnum, numtowrite ) ); return(outsize); } @@ -2920,19 +2815,17 @@ int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a mkdir ****************************************************************************/ -int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring directory; - int cnum; int outsize,ret= -1; BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - cnum = SVAL(inbuf,smb_tid); - unix_convert(directory,cnum,0,&bad_path); + unix_convert(directory,conn,0,&bad_path); - if (check_name(directory,cnum)) - ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); + if (check_name(directory, conn)) + ret = sys_mkdir(directory,unix_mode(conn,aDIR)); if (ret < 0) { @@ -2946,7 +2839,7 @@ int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "mkdir %s cnum=%d ret=%d\n", directory, cnum, ret ) ); + DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) ); return(outsize); } @@ -2959,7 +2852,7 @@ static BOOL recursive_rmdir(char *directory) { char *dname = NULL; BOOL ret = False; - void *dirptr = OpenDir(-1, directory, False); + void *dirptr = OpenDir(NULL, directory, False); if(dirptr == NULL) return True; @@ -3015,24 +2908,22 @@ static BOOL recursive_rmdir(char *directory) /**************************************************************************** reply to a rmdir ****************************************************************************/ -int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring directory; - int cnum; int outsize = 0; BOOL ok = False; BOOL bad_path = False; - cnum = SVAL(inbuf,smb_tid); pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,cnum,0,&bad_path); + unix_convert(directory,conn, NULL,&bad_path); - if (check_name(directory,cnum)) + if (check_name(directory,conn)) { dptr_closepath(directory,SVAL(inbuf,smb_pid)); ok = (sys_rmdir(directory) == 0); - if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum))) + if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn))) { /* Check to see if the only thing in this directory are vetoed files/directories. If so then delete them and @@ -3040,7 +2931,7 @@ int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) do a recursive delete) then fail the rmdir. */ BOOL all_veto_files = True; char *dname; - void *dirptr = OpenDir(cnum, directory, False); + void *dirptr = OpenDir(conn, directory, False); if(dirptr != NULL) { @@ -3049,7 +2940,7 @@ int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; - if(!IS_VETO_PATH(cnum, dname)) + if(!IS_VETO_PATH(conn, dname)) { all_veto_files = False; break; @@ -3080,7 +2971,7 @@ int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) break; if(st.st_mode & S_IFDIR) { - if(lp_recursive_veto_delete(SNUM(cnum))) + if(lp_recursive_veto_delete(SNUM(conn))) { if(recursive_rmdir(fullname) != 0) break; @@ -3192,14 +3083,14 @@ static BOOL resolve_wildcards(char *name1,char *name2) /******************************************************************* check if a user is allowed to rename a file ********************************************************************/ -static BOOL can_rename(char *fname,int cnum) +static BOOL can_rename(char *fname,connection_struct *conn) { struct stat sbuf; - if (!CAN_WRITE(cnum)) return(False); + if (!CAN_WRITE(conn)) return(False); if (sys_lstat(fname,&sbuf) != 0) return(False); - if (!check_file_sharing(cnum,fname,True)) return(False); + if (!check_file_sharing(conn,fname,True)) return(False); return(True); } @@ -3208,204 +3099,205 @@ static BOOL can_rename(char *fname,int cnum) The guts of the rename command, split out so it may be called by the NT SMB code. ****************************************************************************/ - -int rename_internals(char *inbuf, char *outbuf, char *name, char *newname, BOOL replace_if_exists) +int rename_internals(connection_struct *conn, + char *inbuf, char *outbuf, char *name, + char *newname, BOOL replace_if_exists) { - int cnum; - pstring directory; - pstring mask; - pstring newname_last_component; - char *p; - BOOL has_wild; - BOOL bad_path1 = False; - BOOL bad_path2 = False; - int count=0; - int error = ERRnoaccess; - BOOL exists=False; - - cnum = SVAL(inbuf,smb_tid); - - *directory = *mask = 0; - - unix_convert(name,cnum,0,&bad_path1); - unix_convert(newname,cnum,newname_last_component,&bad_path2); - - /* - * Split the old name into directory and last component - * strings. Note that unix_convert may have stripped off a - * leading ./ from both name and newname if the rename is - * at the root of the share. We need to make sure either both - * name and newname contain a / character or neither of them do - * as this is checked in resolve_wildcards(). - */ - - p = strrchr(name,'/'); - if (!p) { - pstrcpy(directory,"."); - pstrcpy(mask,name); - } else { - *p = 0; - pstrcpy(directory,name); - pstrcpy(mask,p+1); - *p = '/'; /* Replace needed for exceptional test below. */ - } - - if (is_mangled(mask)) - check_mangled_cache( mask ); - - has_wild = strchr(mask,'*') || strchr(mask,'?'); - - if (!has_wild) { - /* - * No wildcards - just process the one file. - */ - BOOL is_short_name = is_8_3(name, True); - - /* Add a terminating '/' to the directory name. */ - pstrcat(directory,"/"); - pstrcat(directory,mask); + pstring directory; + pstring mask; + pstring newname_last_component; + char *p; + BOOL has_wild; + BOOL bad_path1 = False; + BOOL bad_path2 = False; + int count=0; + int error = ERRnoaccess; + BOOL exists=False; + + *directory = *mask = 0; + + unix_convert(name,conn,0,&bad_path1); + unix_convert(newname,conn,newname_last_component,&bad_path2); + + /* + * Split the old name into directory and last component + * strings. Note that unix_convert may have stripped off a + * leading ./ from both name and newname if the rename is + * at the root of the share. We need to make sure either both + * name and newname contain a / character or neither of them do + * as this is checked in resolve_wildcards(). + */ + + p = strrchr(name,'/'); + if (!p) { + pstrcpy(directory,"."); + pstrcpy(mask,name); + } else { + *p = 0; + pstrcpy(directory,name); + pstrcpy(mask,p+1); + *p = '/'; /* Replace needed for exceptional test below. */ + } - /* Ensure newname contains a '/' also */ - if(strrchr(newname,'/') == 0) { - pstring tmpstr; + if (is_mangled(mask)) + check_mangled_cache( mask ); - pstrcpy(tmpstr, "./"); - pstrcat(tmpstr, newname); - pstrcpy(newname, tmpstr); - } - - DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", - case_sensitive, case_preserve, short_case_preserve, directory, - newname, newname_last_component, is_short_name)); + has_wild = strchr(mask,'*') || strchr(mask,'?'); - /* - * Check for special case with case preserving and not - * case sensitive, if directory and newname are identical, - * and the old last component differs from the original - * last component only by case, then we should allow - * the rename (user is trying to change the case of the - * filename). - */ - if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) || - ((short_case_preserve == True) && (is_short_name == True))) && - strcsequal(directory, newname)) { - pstring newname_modified_last_component; - - /* - * Get the last component of the modified name. - * Note that we guarantee that newname contains a '/' - * character above. - */ - p = strrchr(newname,'/'); - pstrcpy(newname_modified_last_component,p+1); + if (!has_wild) { + /* + * No wildcards - just process the one file. + */ + BOOL is_short_name = is_8_3(name, True); - if(strcsequal(newname_modified_last_component, - newname_last_component) == False) { - /* - * Replace the modified last component with - * the original. - */ - pstrcpy(p+1, newname_last_component); - } - } - - if(replace_if_exists) { - /* - * NT SMB specific flag - rename can overwrite - * file with the same name so don't check for - * file_exist(). - */ - if(resolve_wildcards(directory,newname) && - can_rename(directory,cnum) && - !sys_rename(directory,newname)) - count++; - } else { - if (resolve_wildcards(directory,newname) && - can_rename(directory,cnum) && - !file_exist(newname,NULL) && - !sys_rename(directory,newname)) - count++; - } + /* Add a terminating '/' to the directory name. */ + pstrcat(directory,"/"); + pstrcat(directory,mask); + + /* Ensure newname contains a '/' also */ + if(strrchr(newname,'/') == 0) { + pstring tmpstr; + + pstrcpy(tmpstr, "./"); + pstrcat(tmpstr, newname); + pstrcpy(newname, tmpstr); + } + + DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", + case_sensitive, case_preserve, short_case_preserve, directory, + newname, newname_last_component, is_short_name)); + + /* + * Check for special case with case preserving and not + * case sensitive, if directory and newname are identical, + * and the old last component differs from the original + * last component only by case, then we should allow + * the rename (user is trying to change the case of the + * filename). + */ + if((case_sensitive == False) && + (((case_preserve == True) && + (is_short_name == False)) || + ((short_case_preserve == True) && + (is_short_name == True))) && + strcsequal(directory, newname)) { + pstring newname_modified_last_component; + + /* + * Get the last component of the modified name. + * Note that we guarantee that newname contains a '/' + * character above. + */ + p = strrchr(newname,'/'); + pstrcpy(newname_modified_last_component,p+1); + + if(strcsequal(newname_modified_last_component, + newname_last_component) == False) { + /* + * Replace the modified last component with + * the original. + */ + pstrcpy(p+1, newname_last_component); + } + } + + if(replace_if_exists) { + /* + * NT SMB specific flag - rename can overwrite + * file with the same name so don't check for + * file_exist(). + */ + if(resolve_wildcards(directory,newname) && + can_rename(directory,conn) && + !sys_rename(directory,newname)) + count++; + } else { + if (resolve_wildcards(directory,newname) && + can_rename(directory,conn) && + !file_exist(newname,NULL) && + !sys_rename(directory,newname)) + count++; + } - DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", + DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); - - if (!count) exists = file_exist(directory,NULL); - if (!count && exists && file_exist(newname,NULL)) { - exists = True; - error = 183; - } - } else { - /* - * Wildcards - process each file that matches. - */ - void *dirptr = NULL; - char *dname; - pstring destname; - - if (check_name(directory,cnum)) - dirptr = OpenDir(cnum, directory, True); - - if (dirptr) { - error = ERRbadfile; - - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - - while ((dname = ReadDirName(dirptr))) { - pstring fname; - pstrcpy(fname,dname); - - if(!mask_match(fname, mask, case_sensitive, False)) - continue; - - error = ERRnoaccess; - slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); - if (!can_rename(fname,cnum)) { - DEBUG(6,("rename %s refused\n", fname)); - continue; - } - pstrcpy(destname,newname); - - if (!resolve_wildcards(fname,destname)) { - DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname)); - continue; - } - - if (!replace_if_exists && file_exist(destname,NULL)) { - DEBUG(6,("file_exist %s\n", destname)); - error = 183; - continue; - } - - if (!sys_rename(fname,destname)) - count++; - DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); - } - CloseDir(dirptr); - } - } - - if (count == 0) { - if (exists) - return(ERROR(ERRDOS,error)); - else { - if((errno == ENOENT) && (bad_path1 || bad_path2)) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,error)); - } - } - - return 0; + + if (!count) exists = file_exist(directory,NULL); + if (!count && exists && file_exist(newname,NULL)) { + exists = True; + error = 183; + } + } else { + /* + * Wildcards - process each file that matches. + */ + void *dirptr = NULL; + char *dname; + pstring destname; + + if (check_name(directory,conn)) + dirptr = OpenDir(conn, directory, True); + + if (dirptr) { + error = ERRbadfile; + + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + + while ((dname = ReadDirName(dirptr))) { + pstring fname; + pstrcpy(fname,dname); + + if(!mask_match(fname, mask, case_sensitive, False)) + continue; + + error = ERRnoaccess; + slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); + if (!can_rename(fname,conn)) { + DEBUG(6,("rename %s refused\n", fname)); + continue; + } + pstrcpy(destname,newname); + + if (!resolve_wildcards(fname,destname)) { + DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname)); + continue; + } + + if (!replace_if_exists && file_exist(destname,NULL)) { + DEBUG(6,("file_exist %s\n", destname)); + error = 183; + continue; + } + + if (!sys_rename(fname,destname)) + count++; + DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); + } + CloseDir(dirptr); + } + } + + if (count == 0) { + if (exists) + return(ERROR(ERRDOS,error)); + else { + if((errno == ENOENT) && (bad_path1 || bad_path2)) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,error)); + } + } + + return 0; } /**************************************************************************** Reply to a mv. ****************************************************************************/ -int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; pstring name; @@ -3416,7 +3308,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - outsize = rename_internals(inbuf, outbuf, name, newname, False); + outsize = rename_internals(conn, inbuf, outbuf, name, newname, False); if(outsize == 0) outsize = set_message(outbuf,0,0,True); @@ -3426,7 +3318,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /******************************************************************* copy a file as part of a reply_copy ******************************************************************/ -static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, +static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory) { int Access,action; @@ -3450,7 +3342,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, fnum1 = find_free_file(); if (fnum1<0) return(False); - open_file_shared(fnum1,cnum,src,(DENY_NONE<<4), + open_file_shared(fnum1,conn,src,(DENY_NONE<<4), 1,0,0,&Access,&action); if (!Files[fnum1].open) { @@ -3466,7 +3358,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, close_file(fnum1,False); return(False); } - open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, + open_file_shared(fnum2,conn,dest,(DENY_NONE<<4)|1, ofun,st.st_mode,0,&Access,&action); if (!Files[fnum2].open) { @@ -3494,11 +3386,10 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, /**************************************************************************** reply to a file copy. ****************************************************************************/ -int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; pstring name; - int cnum; pstring directory; pstring mask,newname; char *p; @@ -3515,21 +3406,19 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) *directory = *mask = 0; - cnum = SVAL(inbuf,smb_tid); - pstrcpy(name,smb_buf(inbuf)); pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); - if (tid2 != cnum) { + if (tid2 != conn->cnum) { /* can't currently handle inter share copies XXXX */ DEBUG(3,("Rejecting inter-share copy\n")); return(ERROR(ERRSRV,ERRinvdevice)); } - unix_convert(name,cnum,0,&bad_path1); - unix_convert(newname,cnum,0,&bad_path2); + unix_convert(name,conn,0,&bad_path1); + unix_convert(newname,conn,0,&bad_path2); target_is_directory = directory_exist(newname,NULL); @@ -3566,7 +3455,7 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) pstrcat(directory,"/"); pstrcat(directory,mask); if (resolve_wildcards(directory,newname) && - copy_file(directory,newname,cnum,ofun, + copy_file(directory,newname,conn,ofun, count,target_is_directory)) count++; if (!count) exists = file_exist(directory,NULL); } else { @@ -3574,8 +3463,8 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) char *dname; pstring destname; - if (check_name(directory,cnum)) - dirptr = OpenDir(cnum, directory, True); + if (check_name(directory,conn)) + dirptr = OpenDir(conn, directory, True); if (dirptr) { @@ -3595,7 +3484,7 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); pstrcpy(destname,newname); if (resolve_wildcards(fname,destname) && - copy_file(directory,newname,cnum,ofun, + copy_file(directory,newname,conn,ofun, count,target_is_directory)) count++; DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); } @@ -3628,38 +3517,36 @@ int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a setdir ****************************************************************************/ -int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,snum; + int snum; int outsize = 0; BOOL ok = False; pstring newdir; - cnum = SVAL(inbuf,smb_tid); - - snum = Connections[cnum].service; + snum = SNUM(conn); if (!CAN_SETDIR(snum)) return(ERROR(ERRDOS,ERRnoaccess)); pstrcpy(newdir,smb_buf(inbuf) + 1); strlower(newdir); - if (strlen(newdir) == 0) - ok = True; - else - { - ok = directory_exist(newdir,NULL); - if (ok) - string_set(&Connections[cnum].connectpath,newdir); - } + if (strlen(newdir) == 0) { + ok = True; + } else { + ok = directory_exist(newdir,NULL); + if (ok) { + string_set(&conn->connectpath,newdir); + } + } if (!ok) - return(ERROR(ERRDOS,ERRbadpath)); + return(ERROR(ERRDOS,ERRbadpath)); outsize = set_message(outbuf,0,0,True); CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh); - - DEBUG( 3, ( "setdir %s cnum=%d\n", newdir, cnum ) ); + + DEBUG(3,("setdir %s\n", newdir)); return(outsize); } @@ -3668,7 +3555,7 @@ int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a lockingX request ****************************************************************************/ -int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) +int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { int fnum = GETFNUM(inbuf,smb_vwv2); unsigned char locktype = CVAL(inbuf,smb_vwv3); @@ -3679,15 +3566,12 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; int32 lock_timeout = IVAL(inbuf,smb_vwv4); - int cnum; int i; char *data; uint32 ecode=0, dummy2; int eclass=0, dummy1; - cnum = SVAL(inbuf,smb_tid); - - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); data = smb_buf(inbuf); @@ -3715,14 +3599,14 @@ no oplock granted on this file.\n", fnum)); } /* Remove the oplock flag from the sharemode. */ - lock_share_entry(fsp->cnum, dev, inode, &token); + lock_share_entry(fsp->conn, dev, inode, &token); if(remove_share_oplock( fnum, token)==False) { DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ dev = %x, inode = %x\n", fnum, dev, inode)); - unlock_share_entry(fsp->cnum, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode, token); } else { - unlock_share_entry(fsp->cnum, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode, token); /* Clear the granted flag and return. */ fsp->granted_oplock = False; @@ -3745,7 +3629,7 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_ulocks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode)) + if(!do_unlock(fnum,conn,count,offset,&eclass, &ecode)) return ERROR(eclass,ecode); } @@ -3759,7 +3643,7 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_locks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - if(!do_lock(fnum,cnum,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + if(!do_lock(fnum,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) #if 0 /* JRATEST - blocking lock code. */ if((ecode == ERRlock) && (lock_timeout != 0)) { @@ -3780,15 +3664,15 @@ dev = %x, inode = %x\n", for(; i >= 0; i--) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2); + do_unlock(fnum,conn,count,offset,&dummy1,&dummy2); } return ERROR(eclass,ecode); } set_message(outbuf,2,0,True); - DEBUG( 3, ( "lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", - fnum, cnum, (unsigned int)locktype, num_locks, num_ulocks ) ); + DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", + fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); chain_fnum = fnum; @@ -3799,9 +3683,9 @@ dev = %x, inode = %x\n", /**************************************************************************** reply to a SMBreadbmpx (read block multiplex) request ****************************************************************************/ -int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) +int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - int cnum,fnum; + int fnum; int nread = -1; int total_read; char *data; @@ -3817,10 +3701,9 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) outsize = set_message(outbuf,8,0,True); - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_READ(fnum); CHECK_ERROR(fnum); @@ -3837,7 +3720,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) tcount = maxcount; total_read = 0; - if (is_locked(fnum,cnum,maxcount,startpos, F_RDLCK)) + if (is_locked(fnum,conn,maxcount,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); do @@ -3871,19 +3754,18 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** reply to a SMBwritebmpx (write block multiplex primary) request ****************************************************************************/ -int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,numtowrite,fnum; + int numtowrite,fnum; int nwritten = -1; int outsize = 0; uint32 startpos; int tcount, write_through, smb_doff; char *data; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_WRITE(fnum); CHECK_ERROR(fnum); @@ -3899,14 +3781,14 @@ int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) not an SMBwritebmpx - set this up now so we don't forget */ CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fnum,cnum,tcount,startpos,F_WRLCK)) + if (is_locked(fnum,conn,tcount,startpos,F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); seek_file(fnum,startpos); nwritten = write_file(fnum,data,numtowrite); - if(lp_syncalways(SNUM(cnum)) || write_through) - sync_file(cnum,fnum); + if(lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fnum); if(nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -3943,8 +3825,8 @@ int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ - DEBUG( 3, ( "writebmpx fnum=%d cnum=%d num=%d wrote=%d\n", - fnum, cnum, numtowrite, nwritten ) ); + DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n", + fnum, numtowrite, nwritten ) ); if (write_through && tcount==nwritten) { /* we need to send both a primary and a secondary response */ @@ -3964,9 +3846,9 @@ int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a SMBwritebs (write block multiplex secondary) request ****************************************************************************/ -int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,numtowrite,fnum; + int numtowrite,fnum; int nwritten = -1; int outsize = 0; int32 startpos; @@ -3975,9 +3857,8 @@ int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) write_bmpx_struct *wbms; BOOL send_response = False; - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_WRITE(fnum); tcount = SVAL(inbuf,smb_vwv1); @@ -4006,8 +3887,8 @@ int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) seek_file(fnum,startpos); nwritten = write_file(fnum,data,numtowrite); - if(lp_syncalways(SNUM(cnum)) || write_through) - sync_file(cnum,fnum); + if(lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fnum); if (nwritten < numtowrite) { @@ -4045,18 +3926,17 @@ int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a SMBsetattrE ****************************************************************************/ -int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,fnum; + int fnum; struct utimbuf unix_times; int outsize = 0; outsize = set_message(outbuf,0,0,True); - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); /* Convert the DOS times into unix times. Ignore create @@ -4075,7 +3955,7 @@ int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /* Ignore request */ if( DEBUGLVL( 3 ) ) { - dbgtext( "reply_setattrE fnum=%d cnum=%d ", fnum, cnum ); + dbgtext( "reply_setattrE fnum=%d ", fnum); dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); } return(outsize); @@ -4087,11 +3967,11 @@ int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } /* Set the date on this file */ - if(file_utime(cnum, Files[fnum].name, &unix_times)) + if(file_utime(conn, Files[fnum].fsp_name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG( 3, ( "reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", - fnum, cnum, unix_times.actime, unix_times.modtime ) ); + DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", + fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); return(outsize); } @@ -4100,31 +3980,30 @@ int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) /**************************************************************************** reply to a SMBgetattrE ****************************************************************************/ -int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int cnum,fnum; + int fnum; struct stat sbuf; int outsize = 0; int mode; outsize = set_message(outbuf,11,0,True); - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); /* Do an fstat on this file */ if(fstat(Files[fnum].fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - mode = dos_mode(cnum,Files[fnum].name,&sbuf); + mode = dos_mode(conn,Files[fnum].fsp_name,&sbuf); /* Convert the times into dos times. Set create date to be last modify date as UNIX doesn't save this */ - put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) @@ -4139,7 +4018,7 @@ int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } SSVAL(outbuf,smb_vwv10, mode); - DEBUG( 3, ( "reply_getattrE fnum=%d cnum=%d\n", fnum, cnum ) ); + DEBUG( 3, ( "reply_getattrE fnum=%d\n", fnum)); return(outsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 143b45e9ef..9c7bafd9dd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -65,7 +65,7 @@ extern int dcelogin_atmost_once; */ extern DOM_SID global_machine_sid; -connection_struct Connections[MAX_CONNECTIONS]; +static connection_struct Connections[MAX_CONNECTIONS]; files_struct Files[MAX_FNUMS]; /* @@ -116,8 +116,6 @@ extern int extra_time_offset; extern pstring myhostname; -static int find_free_connection(int hash); - /* for readability... */ #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0) #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0) @@ -156,7 +154,7 @@ void killkids(void) Then apply create mask, then add force bits. ****************************************************************************/ -mode_t unix_mode(int cnum,int dosmode) +mode_t unix_mode(connection_struct *conn,int dosmode) { mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); @@ -168,23 +166,23 @@ mode_t unix_mode(int cnum,int dosmode) can always create a file in a read-only directory. */ result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); /* Apply directory mask */ - result &= lp_dir_mode(SNUM(cnum)); + result &= lp_dir_mode(SNUM(conn)); /* Add in force bits */ - result |= lp_force_dir_mode(SNUM(cnum)); + result |= lp_force_dir_mode(SNUM(conn)); } else { - if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode)) + if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode)) result |= S_IXUSR; - if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode)) + if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode)) result |= S_IXGRP; - if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode)) + if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode)) result |= S_IXOTH; /* Apply mode mask */ - result &= lp_create_mode(SNUM(cnum)); + result &= lp_create_mode(SNUM(conn)); /* Add in force bits */ - result |= lp_force_create_mode(SNUM(cnum)); + result |= lp_force_create_mode(SNUM(conn)); } return(result); } @@ -193,16 +191,16 @@ mode_t unix_mode(int cnum,int dosmode) /**************************************************************************** change a unix mode to a dos mode ****************************************************************************/ -int dos_mode(int cnum,char *path,struct stat *sbuf) +int dos_mode(connection_struct *conn,char *path,struct stat *sbuf) { int result = 0; extern struct current_user current_user; - DEBUG(8,("dos_mode: %d %s\n", cnum, path)); + DEBUG(8,("dos_mode: %s\n", path)); - if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) { + if (CAN_WRITE(conn) && !lp_alternate_permissions(SNUM(conn))) { if (!((sbuf->st_mode & S_IWOTH) || - Connections[cnum].admin_user || + conn->admin_user || ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) || ((sbuf->st_mode & S_IWGRP) && in_group(sbuf->st_gid,current_user.gid, @@ -213,13 +211,13 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aRONLY; } - if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0)) + if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) result |= aARCH; - if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0)) + if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) result |= aSYSTEM; - if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0)) + if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) result |= aHIDDEN; if (S_ISDIR(sbuf->st_mode)) @@ -233,7 +231,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) #endif /* hide files with a name starting with a . */ - if (lp_hide_dot_files(SNUM(cnum))) + if (lp_hide_dot_files(SNUM(conn))) { char *p = strrchr(path,'/'); if (p) @@ -247,7 +245,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) /* Optimization : Only call is_hidden_path if it's not already hidden. */ - if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path)) + if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { result |= aHIDDEN; } @@ -268,7 +266,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) /******************************************************************* chmod a file - but preserve some bits ********************************************************************/ -int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) +int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st) { struct stat st1; int mask=0; @@ -282,9 +280,9 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) if (S_ISDIR(st->st_mode)) dosmode |= aDIR; - if (dos_mode(cnum,fname,st) == dosmode) return(0); + if (dos_mode(conn,fname,st) == dosmode) return(0); - unixmode = unix_mode(cnum,dosmode); + unixmode = unix_mode(conn,dosmode); /* preserve the s bits */ mask |= (S_ISUID | S_ISGID); @@ -295,9 +293,9 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) #endif /* possibly preserve the x bits */ - if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR; - if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP; - if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH; + if (!MAP_ARCHIVE(conn)) mask |= S_IXUSR; + if (!MAP_SYSTEM(conn)) mask |= S_IXGRP; + if (!MAP_HIDDEN(conn)) mask |= S_IXOTH; unixmode |= (st->st_mode & mask); @@ -323,7 +321,7 @@ Wrapper around sys_utime that possibly allows DOS semantics rather than POSIX. *******************************************************************/ -int file_utime(int cnum, char *fname, struct utimbuf *times) +int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) { extern struct current_user current_user; struct stat sb; @@ -337,7 +335,7 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) if((errno != EPERM) && (errno != EACCES)) return -1; - if(!lp_dos_filetimes(SNUM(cnum))) + if(!lp_dos_filetimes(SNUM(conn))) return -1; /* We have permission (given by the Samba admin) to @@ -350,9 +348,9 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) return -1; /* Check if we have write access. */ - if (CAN_WRITE(cnum)) { + if (CAN_WRITE(conn)) { if (((sb.st_mode & S_IWOTH) || - Connections[cnum].admin_user || + conn->admin_user || ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || ((sb.st_mode & S_IWGRP) && in_group(sb.st_gid,current_user.gid, @@ -371,7 +369,7 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -BOOL set_filetime(int cnum, char *fname, time_t mtime) +BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) { struct utimbuf times; @@ -379,7 +377,7 @@ BOOL set_filetime(int cnum, char *fname, time_t mtime) times.modtime = times.actime = mtime; - if (file_utime(cnum, fname, ×)) { + if (file_utime(conn, fname, ×)) { DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); } @@ -445,7 +443,7 @@ scan a directory to find a filename, matching without case sensitivity If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) +static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) { void *cur_dir; char *dname; @@ -458,7 +456,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) if (*path == 0) path = "."; - if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) { + if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { pstrcpy(name, dname); return(True); } @@ -474,7 +472,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) mangled = !check_mangled_cache( name ); /* open the directory */ - if (!(cur_dir = OpenDir(cnum, path, True))) + if (!(cur_dir = OpenDir(conn, path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); @@ -488,13 +486,13 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) continue; pstrcpy(name2,dname); - if (!name_map_mangle(name2,False,SNUM(cnum))) continue; + if (!name_map_mangle(name2,False,SNUM(conn))) continue; if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) { /* we've found the file, change it's name and return */ - if (docache) DirCacheAdd(path,name,dname,SNUM(cnum)); + if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); pstrcpy(name, dname); CloseDir(cur_dir); return(True); @@ -526,7 +524,7 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ -BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path) +BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) { struct stat st; char *start, *end; @@ -563,7 +561,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa strnorm(name); /* check if it's a printer file */ - if (Connections[cnum].printer) + if (conn->printer) { if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) { @@ -584,7 +582,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa saved_errno = errno; - DEBUG(5,("unix_convert(%s,%d)\n",name,cnum)); + DEBUG(5,("unix_convert(%s)\n",name)); /* a special case - if we don't have any mangling chars and are case sensitive then searching won't help */ @@ -637,7 +635,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa /* try to find this part of the path in the directory */ if (strchr(start,'?') || strchr(start,'*') || - !scan_directory(dirpath, start, cnum, end?True:False)) + !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { @@ -701,26 +699,25 @@ This is called by every routine before it allows an operation on a filename. It does any final confirmation necessary to ensure that the filename is a valid one for the user to access. ****************************************************************************/ -BOOL check_name(char *name,int cnum) +BOOL check_name(char *name,connection_struct *conn) { BOOL ret; errno = 0; - if( IS_VETO_PATH(cnum, name)) - { - DEBUG(5,("file path name %s vetoed\n",name)); - return(0); - } + if (IS_VETO_PATH(conn, name)) { + DEBUG(5,("file path name %s vetoed\n",name)); + return(0); + } - ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum))); + ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn))); /* Check if we are allowing users to follow symlinks */ /* Patch from David Clerc University of Geneva */ #ifdef S_ISLNK - if (!lp_symlinks(SNUM(cnum))) + if (!lp_symlinks(SNUM(conn))) { struct stat statbuf; if ( (sys_lstat(name,&statbuf) != -1) && @@ -1037,7 +1034,8 @@ static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) /**************************************************************************** open a file ****************************************************************************/ -static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) +static void open_file(int fnum,connection_struct *conn, + char *fname1,int flags,int mode, struct stat *sbuf) { extern struct current_user current_user; pstring fname; @@ -1065,14 +1063,13 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct * JRA. */ - if (!CAN_WRITE(cnum) && !Connections[cnum].printer) { + if (conn->read_only && !conn->printer) { /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); check_for_pipe(fname); return; - } - else if(flags & O_CREAT) { + } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that O_CREAT doesn't create the file if we have write access into the directory. @@ -1083,8 +1080,9 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct /* this handles a bug in Win95 - it doesn't say to create the file when it should */ - if (Connections[cnum].printer) - flags |= O_CREAT; + if (conn->printer) { + flags |= O_CREAT; + } /* if (flags == O_WRONLY) @@ -1212,7 +1210,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct } if ((fd_ptr->fd >=0) && - Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) { + conn->printer && lp_minprintspace(SNUM(conn))) { pstring dname; int dum1,dum2,dum3; char *p; @@ -1220,7 +1218,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct p = strrchr(dname,'/'); if (p) *p = 0; if (sys_disk_free(dname,&dum1,&dum2,&dum3) < - lp_minprintspace(SNUM(cnum))) { + lp_minprintspace(SNUM(conn))) { fd_attempt_close(fd_ptr); fsp->fd_ptr = 0; if(fd_ptr->ref_count == 0) @@ -1260,7 +1258,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fd_ptr->inode = (uint32)sbuf->st_ino; fsp->fd_ptr = fd_ptr; - Connections[cnum].num_files_open++; + conn->num_files_open++; fsp->mode = sbuf->st_mode; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; @@ -1273,12 +1271,12 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); fsp->share_mode = 0; - fsp->print_file = Connections[cnum].printer; + fsp->print_file = conn->printer; fsp->modified = False; fsp->granted_oplock = False; fsp->sent_oplock_break = False; fsp->is_directory = False; - fsp->cnum = cnum; + fsp->conn = conn; /* * Note that the file name here is the *untranslated* name * ie. it is still in the DOS codepage sent from the client. @@ -1286,7 +1284,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct * functions which will do the dos_to_unix translation before * mapping into a UNIX filename. JRA. */ - string_set(&fsp->name,fname); + string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; /* @@ -1296,32 +1294,30 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct * This has a similar effect as CtrlD=0 in WIN.INI file. * tim@fsg.com 09/06/94 */ - if (fsp->print_file && POSTSCRIPT(cnum) && fsp->can_write) - { - DEBUG(3,("Writing postscript line\n")); - write_file(fnum,"%!\n",3); + if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { + DEBUG(3,("Writing postscript line\n")); + write_file(fnum,"%!\n",3); } - DEBUG( 2, ( "%s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", - *sesssetup_user ? sesssetup_user : Connections[cnum].user,fname, - BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), - Connections[cnum].num_files_open,fnum ) ); + DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", + *sesssetup_user ? sesssetup_user : conn->user,fname, + BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), + conn->num_files_open,fnum)); } #if WITH_MMAP /* mmap it if read-only */ - if (!fsp->can_write) - { - fsp->mmap_size = file_size(fname); - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); - - if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) - { - DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); - fsp->mmap_ptr = NULL; - } + if (!fsp->can_write) { + fsp->mmap_size = file_size(fname); + fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, + PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + + if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { + DEBUG(3,("Failed to mmap() %s - %s\n", + fname,strerror(errno))); + fsp->mmap_ptr = NULL; + } } #endif } @@ -1329,10 +1325,10 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct /******************************************************************* sync a file ********************************************************************/ -void sync_file(int cnum, int fnum) +void sync_file(connection_struct *conn, int fnum) { #ifdef HAVE_FSYNC - if(lp_strict_sync(SNUM(cnum))) + if(lp_strict_sync(SNUM(conn))) fsync(Files[fnum].fd_ptr->fd); #endif } @@ -1340,21 +1336,21 @@ void sync_file(int cnum, int fnum) /**************************************************************************** run a file if it is a magic script ****************************************************************************/ -static void check_magic(int fnum,int cnum) +static void check_magic(int fnum,connection_struct *conn) { - if (!*lp_magicscript(SNUM(cnum))) + if (!*lp_magicscript(SNUM(conn))) return; - DEBUG(5,("checking magic for %s\n",Files[fnum].name)); + DEBUG(5,("checking magic for %s\n",Files[fnum].fsp_name)); { char *p; - if (!(p = strrchr(Files[fnum].name,'/'))) - p = Files[fnum].name; + if (!(p = strrchr(Files[fnum].fsp_name,'/'))) + p = Files[fnum].fsp_name; else p++; - if (!strequal(lp_magicscript(SNUM(cnum)),p)) + if (!strequal(lp_magicscript(SNUM(conn)),p)) return; } @@ -1362,10 +1358,10 @@ static void check_magic(int fnum,int cnum) int ret; pstring magic_output; pstring fname; - pstrcpy(fname,Files[fnum].name); + pstrcpy(fname,Files[fnum].fsp_name); - if (*lp_magicoutput(SNUM(cnum))) - pstrcpy(magic_output,lp_magicoutput(SNUM(cnum))); + if (*lp_magicoutput(SNUM(conn))) + pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); else slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); @@ -1379,28 +1375,25 @@ static void check_magic(int fnum,int cnum) /**************************************************************************** Common code to close a file or a directory. ****************************************************************************/ - static void close_filestruct(files_struct *fsp) { - int cnum = fsp->cnum; + connection_struct *conn = fsp->conn; - fsp->reserved = False; - fsp->open = False; - fsp->is_directory = False; + fsp->reserved = False; + fsp->open = False; + fsp->is_directory = False; - Connections[cnum].num_files_open--; - if(fsp->wbmpx_ptr) - { - free((char *)fsp->wbmpx_ptr); - fsp->wbmpx_ptr = NULL; - } + conn->num_files_open--; + if(fsp->wbmpx_ptr) { + free((char *)fsp->wbmpx_ptr); + fsp->wbmpx_ptr = NULL; + } #if WITH_MMAP - if(fsp->mmap_ptr) - { - munmap(fsp->mmap_ptr,fsp->mmap_size); - fsp->mmap_ptr = NULL; - } + if(fsp->mmap_ptr) { + munmap(fsp->mmap_ptr,fsp->mmap_size); + fsp->mmap_ptr = NULL; + } #endif } @@ -1412,55 +1405,54 @@ static void close_filestruct(files_struct *fsp) the closing of the connection. In the latter case printing and magic scripts are not run. ****************************************************************************/ - void close_file(int fnum, BOOL normal_close) { - files_struct *fs_p = &Files[fnum]; - int cnum = fs_p->cnum; - uint32 dev = fs_p->fd_ptr->dev; - uint32 inode = fs_p->fd_ptr->inode; - int token; + files_struct *fs_p = &Files[fnum]; + uint32 dev = fs_p->fd_ptr->dev; + uint32 inode = fs_p->fd_ptr->inode; + int token; + connection_struct *conn = fs_p->conn; - close_filestruct(fs_p); + close_filestruct(fs_p); #if USE_READ_PREDICTION - invalidate_read_prediction(fs_p->fd_ptr->fd); + invalidate_read_prediction(fs_p->fd_ptr->fd); #endif - if (lp_share_modes(SNUM(cnum))) - { - lock_share_entry( cnum, dev, inode, &token); - del_share_mode(token, fnum); - } + if (lp_share_modes(SNUM(conn))) { + lock_share_entry(conn, dev, inode, &token); + del_share_mode(token, fnum); + } - fd_attempt_close(fs_p->fd_ptr); + fd_attempt_close(fs_p->fd_ptr); - if (lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, dev, inode, token); + if (lp_share_modes(SNUM(conn))) + unlock_share_entry(conn, dev, inode, token); - /* NT uses smbclose to start a print - weird */ - if (normal_close && fs_p->print_file) - print_file(fnum); + /* NT uses smbclose to start a print - weird */ + if (normal_close && fs_p->print_file) + print_file(conn, fs_p); - /* check for magic scripts */ - if (normal_close) - check_magic(fnum,cnum); + /* check for magic scripts */ + if (normal_close) { + check_magic(fnum,conn); + } - if(fs_p->granted_oplock == True) - global_oplocks_open--; + if(fs_p->granted_oplock == True) + global_oplocks_open--; - fs_p->sent_oplock_break = False; + fs_p->sent_oplock_break = False; - DEBUG( 2, ( "%s closed file %s (numopen=%d)\n", - Connections[cnum].user,fs_p->name, - Connections[cnum].num_files_open ) ); + DEBUG(2,("%s closed file %s (numopen=%d)\n", + conn->user,fs_p->fsp_name, + conn->num_files_open)); - if (fs_p->name) { - string_free(&fs_p->name); - } + if (fs_p->fsp_name) { + string_free(&fs_p->fsp_name); + } - /* we will catch bugs faster by zeroing this structure */ - memset(fs_p, 0, sizeof(*fs_p)); + /* we will catch bugs faster by zeroing this structure */ + memset(fs_p, 0, sizeof(*fs_p)); } /**************************************************************************** @@ -1482,8 +1474,8 @@ void close_directory(int fnum) */ close_filestruct(fsp); - if (fsp->name) - string_free(&fsp->name); + if (fsp->fsp_name) + string_free(&fsp->fsp_name); /* we will catch bugs faster by zeroing this structure */ memset(fsp, 0, sizeof(*fsp)); @@ -1492,83 +1484,81 @@ void close_directory(int fnum) /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ - -int open_directory(int fnum,int cnum,char *fname, int smb_ofun, int unixmode, int *action) +int open_directory(int fnum,connection_struct *conn, + char *fname, int smb_ofun, int unixmode, int *action) { - extern struct current_user current_user; - files_struct *fsp = &Files[fnum]; - struct stat st; - - if (smb_ofun & 0x10) { - /* - * Create the directory. - */ - - if(sys_mkdir(fname, unixmode) < 0) { - DEBUG(0,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); - return -1; - } - - *action = FILE_WAS_CREATED; - - } else { - - /* - * Check that it *was* a directory. - */ - - if(sys_stat(fname, &st) < 0) { - DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", - fname, strerror(errno) )); - return -1; - } + extern struct current_user current_user; + files_struct *fsp = &Files[fnum]; + struct stat st; + + if (smb_ofun & 0x10) { + /* + * Create the directory. + */ + + if(sys_mkdir(fname, unixmode) < 0) { + DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } - if(!S_ISDIR(st.st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - return -1; - } - *action = FILE_WAS_OPENED; - } + *action = FILE_WAS_CREATED; + } else { + /* + * Check that it *was* a directory. + */ - DEBUG(5,("open_directory: opening directory %s, fnum = %d\n", - fname, fnum )); + if(sys_stat(fname, &st) < 0) { + DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } - /* - * Setup the files_struct for it. - */ + if(!S_ISDIR(st.st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + return -1; + } + *action = FILE_WAS_OPENED; + } + + DEBUG(5,("open_directory: opening directory %s, fnum = %d\n", + fname, fnum )); - fsp->fd_ptr = NULL; - Connections[cnum].num_files_open++; - fsp->mode = 0; - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; - fsp->size = 0; - fsp->pos = -1; - fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; - fsp->can_lock = True; - fsp->can_read = False; - fsp->can_write = False; - fsp->share_mode = 0; - fsp->print_file = False; - fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; - fsp->is_directory = True; - fsp->cnum = cnum; - /* - * Note that the file name here is the *untranslated* name - * ie. it is still in the DOS codepage sent from the client. - * All use of this filename will pass though the sys_xxxx - * functions which will do the dos_to_unix translation before - * mapping into a UNIX filename. JRA. - */ - string_set(&fsp->name,fname); - fsp->wbmpx_ptr = NULL; + /* + * Setup the files_struct for it. + */ + + fsp->fd_ptr = NULL; + conn->num_files_open++; + fsp->mode = 0; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + fsp->can_lock = True; + fsp->can_read = False; + fsp->can_write = False; + fsp->share_mode = 0; + fsp->print_file = False; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + fsp->is_directory = True; + fsp->conn = conn; + /* + * Note that the file name here is the *untranslated* name + * ie. it is still in the DOS codepage sent from the client. + * All use of this filename will pass though the sys_xxxx + * functions which will do the dos_to_unix translation before + * mapping into a UNIX filename. JRA. + */ + string_set(&fsp->fsp_name,fname); + fsp->wbmpx_ptr = NULL; - return 0; + return 0; } enum {AFAIL,AREAD,AWRITE,AALL}; @@ -1628,7 +1618,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if the share mode on a file allows it to be deleted or unlinked return True if sharing doesn't prevent the operation ********************************************************************/ -BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) +BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) { int i; int ret = False; @@ -1639,7 +1629,7 @@ BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) int pid = getpid(); uint32 dev, inode; - if(!lp_share_modes(SNUM(cnum))) + if(!lp_share_modes(SNUM(conn))) return True; if (sys_stat(fname,&sbuf) == -1) return(True); @@ -1647,8 +1637,8 @@ BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) dev = (uint32)sbuf.st_dev; inode = (uint32)sbuf.st_ino; - lock_share_entry(cnum, dev, inode, &token); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + lock_share_entry(conn, dev, inode, &token); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); /* * Check if the share modes will give us access. @@ -1707,7 +1697,7 @@ batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); + unlock_share_entry(conn, dev, inode, token); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); @@ -1715,7 +1705,7 @@ dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); return False; } - lock_share_entry(cnum, dev, inode, &token); + lock_share_entry(conn, dev, inode, &token); broke_oplock = True; break; } @@ -1731,7 +1721,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if(broke_oplock) { free((char *)old_shares); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); } } while(broke_oplock); } @@ -1744,7 +1734,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); free_and_exit: - unlock_share_entry(cnum, dev, inode, token); + unlock_share_entry(conn, dev, inode, token); if(old_shares != NULL) free((char *)old_shares); return(ret); @@ -1755,17 +1745,17 @@ free_and_exit: Helper for open_file_shared. Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(int fnum, int cnum, int token, +static void truncate_unless_locked(int fnum, connection_struct *conn, int token, BOOL *share_locked) { files_struct *fsp = &Files[fnum]; if (fsp->can_write){ - if (is_locked(fnum,cnum,0x3FFFFFFF,0,F_WRLCK)){ + if (is_locked(fnum,conn,0x3FFFFFFF,0,F_WRLCK)){ /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ - if (*share_locked && lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, fsp->fd_ptr->dev, + if (*share_locked && lp_share_modes(SNUM(conn))) + unlock_share_entry( conn, fsp->fd_ptr->dev, fsp->fd_ptr->inode, token); close_file(fnum,False); /* Share mode no longer locked. */ @@ -1823,7 +1813,7 @@ int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, /**************************************************************************** open a file with a share mode ****************************************************************************/ -void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, +void open_file_shared(int fnum,connection_struct *conn,char *fname,int share_mode,int ofun, int mode,int oplock_request, int *Access,int *action) { files_struct *fs_p = &Files[fnum]; @@ -1894,7 +1884,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, #endif /* O_SYNC */ if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) + (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) { if (!fcbopen) { @@ -1913,7 +1903,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; - if (lp_share_modes(SNUM(cnum))) + if (lp_share_modes(SNUM(conn))) { int i; share_mode_entry *old_shares = 0; @@ -1922,9 +1912,9 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { dev = (uint32)sbuf.st_dev; inode = (uint32)sbuf.st_ino; - lock_share_entry(cnum, dev, inode, &token); + lock_share_entry(conn, dev, inode, &token); share_locked = True; - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); } /* @@ -1957,7 +1947,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); + unlock_share_entry(conn, dev, inode, token); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); @@ -1968,7 +1958,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); unix_ERR_code = ERRbadshare; return; } - lock_share_entry(cnum, dev, inode, &token); + lock_share_entry(conn, dev, inode, &token); broke_oplock = True; break; } @@ -1978,7 +1968,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) { free((char *)old_shares); - unlock_share_entry(cnum, dev, inode, token); + unlock_share_entry(conn, dev, inode, token); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -1990,7 +1980,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if(broke_oplock) { free((char *)old_shares); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); } } while(broke_oplock); } @@ -2002,23 +1992,23 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,mode)); - open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); + open_file(fnum,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen) { flags = O_RDONLY; - open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 ); + open_file(fnum,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); } if (fs_p->open) { int open_mode=0; - if((share_locked == False) && lp_share_modes(SNUM(cnum))) + if((share_locked == False) && lp_share_modes(SNUM(conn))) { /* We created the file - thus we must now lock the share entry before creating it. */ dev = fs_p->fd_ptr->dev; inode = fs_p->fd_ptr->inode; - lock_share_entry(cnum, dev, inode, &token); + lock_share_entry(conn, dev, inode, &token); share_locked = True; } @@ -2050,7 +2040,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); truncate can fail due to locking and have to close the file (which expects the share_mode_entry to be there). */ - if (lp_share_modes(SNUM(cnum))) + if (lp_share_modes(SNUM(conn))) { uint16 port = 0; /* JRA. Currently this only services Exlcusive and batch @@ -2058,8 +2048,8 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); be extended to level II oplocks (multiple reader oplocks). */ - if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum)) && - !IS_VETO_OPLOCK_PATH(cnum,fname)) + if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && + !IS_VETO_OPLOCK_PATH(conn,fname)) { fs_p->granted_oplock = True; fs_p->sent_oplock_break = False; @@ -2079,11 +2069,11 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); } if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fnum,cnum,token,&share_locked); + truncate_unless_locked(fnum,conn,token,&share_locked); } - if (share_locked && lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, dev, inode, token); + if (share_locked && lp_share_modes(SNUM(conn))) + unlock_share_entry( conn, dev, inode, token); } /**************************************************************************** @@ -2094,7 +2084,7 @@ int seek_file(int fnum,uint32 pos) uint32 offset = 0; files_struct *fsp = &Files[fnum]; - if (fsp->print_file && POSTSCRIPT(fsp->cnum)) + if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; fsp->pos = (int)(lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); @@ -2170,9 +2160,9 @@ int write_file(int fnum,char *data,int n) struct stat st; fsp->modified = True; if (fstat(fsp->fd_ptr->fd,&st) == 0) { - int dosmode = dos_mode(fsp->cnum,fsp->name,&st); - if (MAP_ARCHIVE(fsp->cnum) && !IS_DOS_ARCHIVE(dosmode)) { - dos_chmod(fsp->cnum,fsp->name,dosmode | aARCH,&st); + int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); + if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { + dos_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); } } } @@ -2184,44 +2174,42 @@ int write_file(int fnum,char *data,int n) /**************************************************************************** load parameters specific to a connection/service ****************************************************************************/ -BOOL become_service(int cnum,BOOL do_chdir) +BOOL become_service(connection_struct *conn,BOOL do_chdir) { - extern char magic_char; - static int last_cnum = -1; - int snum; + extern char magic_char; + static connection_struct *last_conn; + int snum; - if (!OPEN_CNUM(cnum)) - { - last_cnum = -1; - return(False); - } + if (!conn || !conn->open) { + last_conn = NULL; + return(False); + } - Connections[cnum].lastused = smb_last_time; + conn->lastused = smb_last_time; - snum = SNUM(cnum); + snum = SNUM(conn); - if (do_chdir && - ChDir(Connections[cnum].connectpath) != 0 && - ChDir(Connections[cnum].origpath) != 0) - { - DEBUG( 0, ( "chdir (%s) failed cnum=%d\n", - Connections[cnum].connectpath, cnum ) ); - return(False); - } + if (do_chdir && + ChDir(conn->connectpath) != 0 && + ChDir(conn->origpath) != 0) { + DEBUG(0,("chdir (%s) failed\n", + conn->connectpath)); + return(False); + } - if (cnum == last_cnum) - return(True); + if (conn == last_conn) + return(True); - last_cnum = cnum; + last_conn = conn; - case_default = lp_defaultcase(snum); - case_preserve = lp_preservecase(snum); - short_case_preserve = lp_shortpreservecase(snum); - case_mangle = lp_casemangle(snum); - case_sensitive = lp_casesensitive(snum); - magic_char = lp_magicchar(snum); - use_mangled_map = (*lp_mangled_map(snum) ? True:False); - return(True); + case_default = lp_defaultcase(snum); + case_preserve = lp_preservecase(snum); + short_case_preserve = lp_shortpreservecase(snum); + case_mangle = lp_casemangle(snum); + case_sensitive = lp_casesensitive(snum); + magic_char = lp_magicchar(snum); + use_mangled_map = (*lp_mangled_map(snum) ? True:False); + return(True); } @@ -2906,7 +2894,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) int fnum; time_t start_time; BOOL shutdown_server = False; - int saved_cnum; + connection_struct *saved_conn; int saved_vuid; pstring saved_dir; @@ -2957,7 +2945,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { if( DEBUGLVL( 0 ) ) { - dbgtext( "oplock_break: file %s (fnum = %d, ", fsp->name, fnum ); + dbgtext( "oplock_break: file %s (fnum = %d, ", fsp->fsp_name, fnum ); dbgtext( "dev = %x, inode = %x) has no oplock.\n", dev, inode ); dbgtext( "Allowing break to succeed regardless.\n" ); } @@ -2970,7 +2958,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) if( DEBUGLVL( 0 ) ) { dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); - dbgtext( "file %s (fnum = %d, ", fsp->name, fnum ); + dbgtext( "file %s (fnum = %d, ", fsp->fsp_name, fnum ); dbgtext( "dev = %x, inode = %x)\n", dev, inode ); } @@ -3008,7 +2996,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) set_message(outbuf,8,0,True); SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->cnum); + SSVAL(outbuf,smb_tid,fsp->conn->cnum); SSVAL(outbuf,smb_pid,0xFFFF); SSVAL(outbuf,smb_uid,0); SSVAL(outbuf,smb_mid,0xFFFF); @@ -3037,7 +3025,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) * Save the information we need to re-become the * user, then unbecome the user whilst we're doing this. */ - saved_cnum = fsp->cnum; + saved_conn = fsp->conn; saved_vuid = current_user.vuid; GetWd(saved_dir); unbecome_user(); @@ -3060,7 +3048,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); - DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->name ) ); + DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) ); DEBUGADD( 0, ( "(fnum = %d, dev = %x, inode = %x).\n", fnum, dev, inode)); shutdown_server = True; break; @@ -3087,7 +3075,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { dbgtext( "oplock_break: no break received from client " ); dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); - dbgtext( "oplock_break failed for file %s ", fsp->name ); + dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); dbgtext( "(fnum = %d, dev = %x, inode = %x).\n", fnum, dev, inode ); } shutdown_server = True; @@ -3099,7 +3087,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) * Go back to being the user who requested the oplock * break. */ - if(!become_user(&Connections[saved_cnum], saved_cnum, saved_vuid)) + if(!become_user(saved_conn, saved_vuid)) { DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); DEBUGADD( 0, ( "Shutting down server\n" ) ); @@ -3322,7 +3310,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); time_left -= (time(NULL) - start_time); } - DEBUG( 3, ( "%s request_oplock_break: broke oplock.\n" ) ); + DEBUG(3,("request_oplock_break: broke oplock.\n")); return True; } @@ -3365,11 +3353,13 @@ check if a snum is in use ****************************************************************************/ BOOL snum_used(int snum) { - int i; - for (i=0;iread_only = lp_readonly(snum); + /* add it as a possible user name */ + add_session_user(service); - { - pstring list; - StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); + /* shall we let them in? */ + if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { + DEBUG( 2, ( "Invalid username/password for %s\n", service ) ); + *ecode = ERRbadpw; + return NULL; + } + + conn = find_free_connection(str_checksum(service) + str_checksum(user)); + if (!conn) { + DEBUG(0,("Couldn't find free connection.\n")); + *ecode = ERRnoresource; + return NULL; + } - if (user_in_list(user,list)) - pcon->read_only = True; + /* find out some info about the user */ + pass = Get_Pwnam(user,True); - StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); + if (pass == NULL) { + DEBUG(0,( "Couldn't find account %s\n",user)); + *ecode = ERRbaduid; + return NULL; + } - if (user_in_list(user,list)) - pcon->read_only = False; - } + conn->read_only = lp_readonly(snum); - /* admin user check */ + { + pstring list; + StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); + string_sub(list,"%S",service); + + if (user_in_list(user,list)) + conn->read_only = True; + + StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); + string_sub(list,"%S",service); + + if (user_in_list(user,list)) + conn->read_only = False; + } - /* JRA - original code denied admin user if the share was - marked read_only. Changed as I don't think this is needed, - but old code left in case there is a problem here. - */ - if (user_in_list(user,lp_admin_users(snum)) + /* admin user check */ + + /* JRA - original code denied admin user if the share was + marked read_only. Changed as I don't think this is needed, + but old code left in case there is a problem here. + */ + if (user_in_list(user,lp_admin_users(snum)) #if 0 - && !pcon->read_only) -#else - ) + && !conn->read_only #endif - { - pcon->admin_user = True; - DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); - } - else - pcon->admin_user = False; + ) { + conn->admin_user = True; + DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); + } else { + conn->admin_user = False; + } - pcon->force_user = force; - pcon->vuid = vuid; - pcon->uid = pass->pw_uid; - pcon->gid = pass->pw_gid; - pcon->num_files_open = 0; - pcon->lastused = time(NULL); - pcon->service = snum; - pcon->used = True; - pcon->printer = (strncmp(dev,"LPT",3) == 0); - pcon->ipc = (strncmp(dev,"IPC",3) == 0); - pcon->dirptr = NULL; - pcon->veto_list = NULL; - pcon->hide_list = NULL; - pcon->veto_oplock_list = NULL; - string_set(&pcon->dirpath,""); - string_set(&pcon->user,user); - + conn->force_user = force; + conn->vuid = vuid; + conn->uid = pass->pw_uid; + conn->gid = pass->pw_gid; + conn->num_files_open = 0; + conn->lastused = time(NULL); + conn->service = snum; + conn->used = True; + conn->printer = (strncmp(dev,"LPT",3) == 0); + conn->ipc = (strncmp(dev,"IPC",3) == 0); + conn->dirptr = NULL; + conn->veto_list = NULL; + conn->hide_list = NULL; + conn->veto_oplock_list = NULL; + string_set(&conn->dirpath,""); + string_set(&conn->user,user); + #ifdef HAVE_GETGRNAM - if (*lp_force_group(snum)) - { - struct group *gptr; - pstring gname; - - StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1); - /* default service may be a group name */ - string_sub(gname,"%S",service); - gptr = (struct group *)getgrnam(gname); - - if (gptr) - { - pcon->gid = gptr->gr_gid; - DEBUG(3,("Forced group %s\n",gname)); + if (*lp_force_group(snum)) { + struct group *gptr; + pstring gname; + + StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1); + /* default service may be a group name */ + string_sub(gname,"%S",service); + gptr = (struct group *)getgrnam(gname); + + if (gptr) { + conn->gid = gptr->gr_gid; + DEBUG(3,("Forced group %s\n",gname)); + } else { + DEBUG(1,("Couldn't find group %s\n",gname)); + } } - else - DEBUG(1,("Couldn't find group %s\n",gname)); - } #endif - - if (*lp_force_user(snum)) - { - struct passwd *pass2; - fstring fuser; - fstrcpy(fuser,lp_force_user(snum)); - pass2 = (struct passwd *)Get_Pwnam(fuser,True); - if (pass2) - { - pcon->uid = pass2->pw_uid; - string_set(&pcon->user,fuser); - fstrcpy(user,fuser); - pcon->force_user = True; - DEBUG(3,("Forced user %s\n",fuser)); + + if (*lp_force_user(snum)) { + struct passwd *pass2; + fstring fuser; + fstrcpy(fuser,lp_force_user(snum)); + pass2 = (struct passwd *)Get_Pwnam(fuser,True); + if (pass2) { + conn->uid = pass2->pw_uid; + string_set(&conn->user,fuser); + fstrcpy(user,fuser); + conn->force_user = True; + DEBUG(3,("Forced user %s\n",fuser)); + } else { + DEBUG(1,("Couldn't find user %s\n",fuser)); + } } - else - DEBUG(1,("Couldn't find user %s\n",fuser)); - } - { - pstring s; - pstrcpy(s,lp_pathname(snum)); - standard_sub(cnum,s); - string_set(&pcon->connectpath,s); - DEBUG(3,("Connect path is %s\n",s)); - } - - /* groups stuff added by ih */ - pcon->ngroups = 0; - pcon->groups = NULL; - - if (!IS_IPC(cnum)) - { - /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(pcon->user,pcon->uid,pcon->gid, - &pcon->ngroups,&pcon->groups); - - /* check number of connections */ - if (!claim_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum)),False)) { - DEBUG(1,("too many connections - rejected\n")); - return(-8); - } - - if (lp_status(SNUM(cnum))) - claim_connection(cnum,"STATUS.",MAXSTATUS,False); - } /* IS_IPC */ - - pcon->open = True; - - /* execute any "root preexec = " line */ - if (*lp_rootpreexec(SNUM(cnum))) - { - pstring cmd; - pstrcpy(cmd,lp_rootpreexec(SNUM(cnum))); - standard_sub(cnum,cmd); - DEBUG(5,("cmd=%s\n",cmd)); - smbrun(cmd,NULL,False); - } - - if (!become_user(&Connections[cnum], cnum,pcon->vuid)) - { - DEBUG(0,("Can't become connected user!\n")); - pcon->open = False; - if (!IS_IPC(cnum)) { - yield_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - } - return(-1); - } - - if (ChDir(pcon->connectpath) != 0) - { - DEBUG(0,("Can't change directory to %s (%s)\n", - pcon->connectpath,strerror(errno))); - pcon->open = False; - unbecome_user(); - if (!IS_IPC(cnum)) { - yield_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - } - return(-5); - } - - string_set(&pcon->origpath,pcon->connectpath); + pstring s; + pstrcpy(s,lp_pathname(snum)); + standard_sub(conn,s); + string_set(&conn->connectpath,s); + DEBUG(3,("Connect path is %s\n",s)); + } + /* groups stuff added by ih */ + conn->ngroups = 0; + conn->groups = NULL; + + if (!IS_IPC(conn)) { + /* Find all the groups this uid is in and + store them. Used by become_user() */ + setup_groups(conn->user,conn->uid,conn->gid, + &conn->ngroups,&conn->groups); + + /* check number of connections */ + if (!claim_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn)), + False)) { + DEBUG(1,("too many connections - rejected\n")); + *ecode = ERRnoresource; + return NULL; + } + + if (lp_status(SNUM(conn))) + claim_connection(conn,"STATUS.", + MAXSTATUS,False); + } /* IS_IPC */ + + conn->open = True; + + /* execute any "root preexec = " line */ + if (*lp_rootpreexec(SNUM(conn))) { + pstring cmd; + pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); + standard_sub(conn,cmd); + DEBUG(5,("cmd=%s\n",cmd)); + smbrun(cmd,NULL,False); + } + + if (!become_user(conn, conn->vuid)) { + DEBUG(0,("Can't become connected user!\n")); + conn->open = False; + if (!IS_IPC(conn)) { + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); + if (lp_status(SNUM(conn))) { + yield_connection(conn,"STATUS.",MAXSTATUS); + } + } + *ecode = ERRbadpw; + return NULL; + } + + if (ChDir(conn->connectpath) != 0) { + DEBUG(0,("Can't change directory to %s (%s)\n", + conn->connectpath,strerror(errno))); + conn->open = False; + unbecome_user(); + if (!IS_IPC(conn)) { + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); + if (lp_status(SNUM(conn))) + yield_connection(conn,"STATUS.",MAXSTATUS); + } + *ecode = ERRinvnetname; + return NULL; + } + + string_set(&conn->origpath,conn->connectpath); + #if SOFTLINK_OPTIMISATION - /* resolve any soft links early */ - { - pstring s; - pstrcpy(s,pcon->connectpath); - GetWd(s); - string_set(&pcon->connectpath,s); - ChDir(pcon->connectpath); - } + /* resolve any soft links early */ + { + pstring s; + pstrcpy(s,conn->connectpath); + GetWd(s); + string_set(&conn->connectpath,s); + ChDir(conn->connectpath); + } #endif - - num_connections_open++; - add_session_user(user); - - /* execute any "preexec = " line */ - if (*lp_preexec(SNUM(cnum))) - { - pstring cmd; - pstrcpy(cmd,lp_preexec(SNUM(cnum))); - standard_sub(cnum,cmd); - smbrun(cmd,NULL,False); - } - - /* we've finished with the sensitive stuff */ - unbecome_user(); - - /* Add veto/hide lists */ - if (!IS_IPC(cnum) && !IS_PRINT(cnum)) - { - set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum))); - set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum))); - set_namearray( &pcon->veto_oplock_list, lp_veto_oplocks(SNUM(cnum))); - } - - if( DEBUGLVL( IS_IPC(cnum) ? 3 : 1 ) ) - { - extern int Client; - - dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); - dbgtext( "connect to service %s ", lp_servicename(SNUM(cnum)) ); - dbgtext( "as user %s ", user ); - dbgtext( "(uid=%d, gid=%d) ", pcon->uid, pcon->gid ); - dbgtext( "(pid %d)\n", (int)getpid() ); - } - - return(cnum); + + num_connections_open++; + add_session_user(user); + + /* execute any "preexec = " line */ + if (*lp_preexec(SNUM(conn))) { + pstring cmd; + pstrcpy(cmd,lp_preexec(SNUM(conn))); + standard_sub(conn,cmd); + smbrun(cmd,NULL,False); + } + + /* we've finished with the sensitive stuff */ + unbecome_user(); + + /* Add veto/hide lists */ + if (!IS_IPC(conn) && !IS_PRINT(conn)) { + set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn))); + set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn))); + set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn))); + } + + if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { + extern int Client; + + dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); + dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); + dbgtext( "as user %s ", user ); + dbgtext( "(uid=%d, gid=%d) ", conn->uid, conn->gid ); + dbgtext( "(pid %d)\n", (int)getpid() ); + } + + return(conn); } /**************************************************************************** @@ -3783,7 +3797,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de static BOOL attempt_close_oplocked_file(files_struct *fsp) { - DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->name)); + DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) { @@ -3867,41 +3881,6 @@ int find_free_file(void ) return(-1); } -/**************************************************************************** - find first available connection slot, starting from a random position. -The randomisation stops problems with the server dieing and clients -thinking the server is still available. -****************************************************************************/ -static int find_free_connection(int hash ) -{ - int i; - BOOL used=False; - hash = (hash % (MAX_CONNECTIONS-2))+1; - - again: - - for (i=hash+1;i!=hash;) - { - if (!Connections[i].open && Connections[i].used == used) - { - DEBUG(3,("found free connection number %d\n",i)); - return(i); - } - i++; - if (i == MAX_CONNECTIONS) - i = 1; - } - - if (!used) - { - used = !used; - goto again; - } - - DEBUG(1,("ERROR! Out of connection structures\n")); - return(-1); -} - /**************************************************************************** reply for the core protocol @@ -4183,7 +4162,9 @@ struct { /**************************************************************************** reply to a negprot ****************************************************************************/ -static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +static int reply_negprot(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, + int dum_buffsize) { int outsize = set_message(outbuf,1,0,True); int Index=0; @@ -4290,11 +4271,11 @@ static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz /**************************************************************************** close all open files for a connection ****************************************************************************/ -static void close_open_files(int cnum) +static void close_open_files(connection_struct *conn) { int i; for (i=0;iopen) { + DEBUG(0,("cnum not open\n")); + return; + } - DEBUG( IS_IPC(cnum)?3:1, ( "%s (%s) closed connection to service %s\n", - remote_machine,client_addr(Client), - lp_servicename(SNUM(cnum)) ) ); + DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", + remote_machine,client_addr(Client), + lp_servicename(SNUM(conn)))); - yield_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum))); + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(cnum))) - yield_connection(cnum,"STATUS.",MAXSTATUS); + if (lp_status(SNUM(conn))) + yield_connection(conn,"STATUS.",MAXSTATUS); - close_open_files(cnum); - dptr_closecnum(cnum); + close_open_files(conn); + dptr_closecnum(conn); - /* execute any "postexec = " line */ - if (*lp_postexec(SNUM(cnum)) && become_user(&Connections[cnum], cnum,vuid)) - { - pstring cmd; - pstrcpy(cmd,lp_postexec(SNUM(cnum))); - standard_sub(cnum,cmd); - smbrun(cmd,NULL,False); - unbecome_user(); - } - - unbecome_user(); - /* execute any "root postexec = " line */ - if (*lp_rootpostexec(SNUM(cnum))) - { - pstring cmd; - pstrcpy(cmd,lp_rootpostexec(SNUM(cnum))); - standard_sub(cnum,cmd); - smbrun(cmd,NULL,False); - } - - Connections[cnum].open = False; - num_connections_open--; - if (Connections[cnum].ngroups && Connections[cnum].groups) - { - free(Connections[cnum].groups); - Connections[cnum].groups = NULL; - Connections[cnum].ngroups = 0; - } + /* execute any "postexec = " line */ + if (*lp_postexec(SNUM(conn)) && + become_user(conn, vuid)) { + pstring cmd; + pstrcpy(cmd,lp_postexec(SNUM(conn))); + standard_sub(conn,cmd); + smbrun(cmd,NULL,False); + unbecome_user(); + } - free_namearray(Connections[cnum].veto_list); - free_namearray(Connections[cnum].hide_list); - free_namearray(Connections[cnum].veto_oplock_list); + unbecome_user(); + /* execute any "root postexec = " line */ + if (*lp_rootpostexec(SNUM(conn))) { + pstring cmd; + pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); + standard_sub(conn,cmd); + smbrun(cmd,NULL,False); + } + + conn->open = False; + num_connections_open--; + if (conn->ngroups && conn->groups) { + free(conn->groups); + conn->groups = NULL; + conn->ngroups = 0; + } - string_set(&Connections[cnum].user,""); - string_set(&Connections[cnum].dirpath,""); - string_set(&Connections[cnum].connectpath,""); + free_namearray(conn->veto_list); + free_namearray(conn->hide_list); + free_namearray(conn->veto_oplock_list); + + string_set(&conn->user,""); + string_set(&conn->dirpath,""); + string_set(&conn->connectpath,""); } @@ -4406,6 +4384,7 @@ static BOOL dump_core(void) DEBUG(0,("Dumping core in %s\n",dname)); + abort(); return(True); } #endif @@ -4425,7 +4404,7 @@ void exit_server(char *reason) DEBUG(2,("Closing connections\n")); for (i=0;iDPTR_IDLE_TIMEOUT) - dptr_idlecnum(i); - - if (Connections[i].num_files_open > 0 || - (t-Connections[i].lastused)DPTR_IDLE_TIMEOUT) + dptr_idlecnum(&Connections[i]); + + if (Connections[i].num_files_open > 0 || + (t-Connections[i].lastused)0) - { - DEBUG( 2, ( "Closing idle connection 2.\n" ) ); - return; + if (allidle && num_connections_open>0) { + DEBUG(2,("Closing idle connection 2.\n")); + return; } if(global_machine_pasword_needs_changing) @@ -5189,7 +5140,7 @@ static void init_structs(void ) for (i=0;i LANMAN1 then the max_send variable must have been set in the sessetupX call. @@ -182,8 +181,9 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, /**************************************************************************** reply to a TRANSACT2_OPEN ****************************************************************************/ -static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, - char **pparams, char **ppdata) +static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, + int bufsize, + char **pparams, char **ppdata) { char *params = *pparams; int16 open_mode = SVAL(params, 2); @@ -211,12 +211,12 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, StrnCpy(fname,pname,namelen); - DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n", - fname,cnum,open_mode, open_attr, open_ofun, open_size)); + DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", + fname,open_mode, open_attr, open_ofun, open_size)); /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,cnum,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); fnum = find_free_file(); if (fnum < 0) @@ -224,7 +224,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, fsp = &Files[fnum]; - if (!check_name(fname,cnum)) + if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) { @@ -235,9 +235,9 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(cnum,open_attr | aARCH); + unixmode = unix_mode(conn,open_attr | aARCH); - open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, + open_file_shared(fnum,conn,fname,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp->open) @@ -257,7 +257,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, } size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); + fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { @@ -277,7 +277,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, SIVAL(params,8, size); SSVAL(params,12,rmode); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { smb_action |= EXTENDED_OPLOCK_GRANTED; } @@ -293,7 +293,8 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, /**************************************************************************** get a level dependent lanman2 dir entry. ****************************************************************************/ -static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level, +static int get_lanman2_dir_entry(connection_struct *conn, + char *path_mask,int dirtype,int info_level, int requires_resume_key, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, @@ -314,17 +315,17 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l uint32 size=0,len; uint32 mdate=0, adate=0, cdate=0; char *nameptr; - BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") || - strequal(Connections[cnum].dirpath,".") || - strequal(Connections[cnum].dirpath,"/")); + BOOL isrootdir = (strequal(conn->dirpath,"./") || + strequal(conn->dirpath,".") || + strequal(conn->dirpath,"/")); BOOL was_8_3; int nt_extmode; /* Used for NT connections instead of mode */ - BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/'); + BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); *fname = 0; *out_of_space = False; - if (!Connections[cnum].dirptr) + if (!conn->dirptr) return(False); p = strrchr(path_mask,'/'); @@ -341,8 +342,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l while (!found) { /* Needed if we run out of space */ - prev_dirpos = TellDir(Connections[cnum].dirptr); - dname = ReadDirName(Connections[cnum].dirptr); + prev_dirpos = TellDir(conn->dirptr); + dname = ReadDirName(conn->dirptr); /* * Due to bugs in NT client redirectors we are not using @@ -354,7 +355,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l reskey = 0; DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", - Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); + (unsigned)conn->dirptr,TellDir(conn->dirptr))); if (!dname) return(False); @@ -372,7 +373,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l if (isrootdir && isdots) continue; - pstrcpy(pathreal,Connections[cnum].dirpath); + pstrcpy(pathreal,conn->dirpath); if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); @@ -382,9 +383,9 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l continue; } - mode = dos_mode(cnum,pathreal,&sbuf); + mode = dos_mode(conn,pathreal,&sbuf); - if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) { + if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) { DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); continue; } @@ -392,7 +393,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l size = sbuf.st_size; mdate = sbuf.st_mtime; adate = sbuf.st_atime; - cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))); + cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); if(mode & aDIR) size = 0; @@ -402,7 +403,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l } } - name_map_mangle(fname,False,SNUM(cnum)); + name_map_mangle(fname,False,SNUM(conn)); p = pdata; nameptr = p; @@ -497,7 +498,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l SIVAL(p,0,0); p += 4; if (!was_8_3) { pstrcpy(p+2,fname); - if (!name_map_mangle(p+2,True,SNUM(cnum))) + if (!name_map_mangle(p+2,True,SNUM(conn))) (p+2)[12] = 0; } else *(p+2) = 0; @@ -562,7 +563,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l if (PTR_DIFF(p,pdata) > space_remaining) { /* Move the dirptr back to prev_dirpos */ - SeekDir(Connections[cnum].dirptr, prev_dirpos); + SeekDir(conn->dirptr, prev_dirpos); *out_of_space = True; DEBUG(9,("get_lanman2_dir_entry: out of space\n")); return False; /* Not finished - just out of space */ @@ -605,8 +606,9 @@ void mask_convert( char *mask) /**************************************************************************** reply to a TRANS2_FINDFIRST ****************************************************************************/ -static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum, - char **pparams, char **ppdata) +static int call_trans2findfirst(connection_struct *conn, + char *inbuf, char *outbuf, int bufsize, + char **pparams, char **ppdata) { /* We must be careful here that we don't return more than the allowed number of data bytes. If this means returning fewer than @@ -661,8 +663,8 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,cnum,0,&bad_path); - if(!check_name(directory,cnum)) { + unix_convert(directory,conn,0,&bad_path); + if(!check_name(directory,conn)) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; @@ -703,7 +705,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); - dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid)); + dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid)); if (dptr_num < 0) return(ERROR(ERRDOS,ERRbadfile)); @@ -742,8 +744,8 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum a different TRANS2 call. */ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); - if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive)) + conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) dont_descend = True; p = pdata; @@ -763,7 +765,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum else { finished = - !get_lanman2_dir_entry(cnum,mask,dirtype,info_level, + !get_lanman2_dir_entry(conn,mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &last_name_off); @@ -807,9 +809,9 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG( 4, ( "%s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", + DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", smb_fn_name(CVAL(inbuf,smb_com)), - mask, directory, cnum, dirtype, numentries ) ); + mask, directory, dirtype, numentries ) ); return(-1); } @@ -818,8 +820,10 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum /**************************************************************************** reply to a TRANS2_FINDNEXT ****************************************************************************/ -static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) +static int call_trans2findnext(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, + char **pparams, char **ppdata) { /* We must be careful here that we don't return more than the allowed number of data bytes. If this means returning fewer than @@ -885,10 +889,10 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return(ERROR(ERRDOS,ERRnomem)); /* Check that the dptr is valid */ - if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(dptr_num))) + if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) return(ERROR(ERRDOS,ERRnofiles)); - string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); + string_set(&conn->dirpath,dptr_path(dptr_num)); /* Get the wildcard mask from the dptr */ if((p = dptr_wcard(dptr_num))== NULL) { @@ -896,21 +900,21 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return (ERROR(ERRDOS,ERRnofiles)); } pstrcpy(mask, p); - pstrcpy(directory,Connections[cnum].dirpath); + pstrcpy(directory,conn->dirpath); /* Get the attr mask from the dptr */ dirtype = dptr_attr(dptr_num); DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n", dptr_num, mask, dirtype, - Connections[cnum].dirptr, - TellDir(Connections[cnum].dirptr))); + (unsigned)conn->dirptr, + TellDir(conn->dirptr))); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); - if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive)) + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) dont_descend = True; p = pdata; @@ -937,7 +941,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", int current_pos, start_pos; char *dname; - void *dirptr = Connections[cnum].dirptr; + void *dirptr = conn->dirptr; start_pos = TellDir(dirptr); for(current_pos = start_pos; current_pos >= 0; current_pos--) { @@ -953,7 +957,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * here. */ - name_map_mangle( dname, False, SNUM(cnum)); + name_map_mangle( dname, False, SNUM(conn)); if(dname && strcsequal( resume_name, dname)) { @@ -980,7 +984,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * here. */ - name_map_mangle( dname, False, SNUM(cnum)); + name_map_mangle( dname, False, SNUM(conn)); if(strcsequal( resume_name, dname)) { @@ -1004,7 +1008,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", else { finished = - !get_lanman2_dir_entry(cnum,mask,dirtype,info_level, + !get_lanman2_dir_entry(conn,mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &last_name_off); @@ -1038,9 +1042,9 @@ resume_key = %d resume name = %s continue=%d level = %d\n", if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG( 3, ( "%s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", + DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", smb_fn_name(CVAL(inbuf,smb_com)), - mask, directory, cnum, dirtype, numentries ) ); + mask, directory, dirtype, numentries ) ); return(-1); } @@ -1048,18 +1052,20 @@ resume_key = %d resume name = %s continue=%d level = %d\n", /**************************************************************************** reply to a TRANS2_QFSINFO (query filesystem info) ****************************************************************************/ -static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) +static int call_trans2qfsinfo(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, + char **pparams, char **ppdata) { char *pdata = *ppdata; char *params = *pparams; uint16 info_level = SVAL(params,0); int data_len; struct stat st; - char *vname = volume_label(SNUM(cnum)); - int snum = SNUM(cnum); + char *vname = volume_label(SNUM(conn)); + int snum = SNUM(conn); - DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level)); + DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); if(sys_stat(".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); @@ -1081,7 +1087,7 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize SIVAL(pdata,l1_cUnitAvail,dfree); SSVAL(pdata,l1_cbSector,512); DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n", - bsize, st.st_dev, bsize/512, dsize, dfree, 512)); + bsize, (unsigned)st.st_dev, bsize/512, dsize, dfree, 512)); break; } case 2: @@ -1096,7 +1102,8 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); SCVAL(pdata,l2_vol_cch,volname_len); StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); - DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len, + DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", + (unsigned)st.st_ctime, volname_len, pdata+l2_vol_szVolLabel)); break; } @@ -1159,15 +1166,17 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize /**************************************************************************** reply to a TRANS2_SETFSINFO (set filesystem info) ****************************************************************************/ -static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) +static int call_trans2setfsinfo(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, + char **pparams, char **ppdata) { /* Just say yes we did it - there is nothing that can be set here so it doesn't matter. */ int outsize; DEBUG(3,("call_trans2setfsinfo\n")); - if (!CAN_WRITE(cnum)) + if (!CAN_WRITE(conn)) return(ERROR(ERRSRV,ERRaccess)); outsize = set_message(outbuf,10,0,True); @@ -1180,8 +1189,9 @@ static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsi file name or file id). ****************************************************************************/ -static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, - int bufsize,int cnum, +static int call_trans2qfilepathinfo(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, char **pparams,char **ppdata, int total_data) { @@ -1203,10 +1213,10 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, int16 fnum = SVALS(params,0); info_level = SVAL(params,2); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); - fname = Files[fnum].name; + fname = Files[fnum].fsp_name; if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); @@ -1217,8 +1227,8 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, info_level = SVAL(params,0); fname = &fname1[0]; pstrcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0,&bad_path); - if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { + unix_convert(fname,conn,0,&bad_path); + if (!check_name(fname,conn) || sys_stat(fname,&sbuf)) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1240,7 +1250,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, else p++; l = strlen(p); - mode = dos_mode(cnum,fname,&sbuf); + mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; if (mode & aDIR) size = 0; @@ -1261,7 +1271,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,size); @@ -1272,7 +1282,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; - put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,size); @@ -1290,7 +1300,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_BASIC_INFO: data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ - put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ @@ -1298,7 +1308,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, DEBUG(5,("SMB_QFBI - ")); { - time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))); + time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); DEBUG(5,("create: %s ", ctime(&create_time))); } DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); @@ -1329,7 +1339,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, /* Mangle if not already 8.3 */ if(!is_8_3(short_name, True)) { - if(!name_map_mangle(short_name,True,SNUM(cnum))) + if(!name_map_mangle(short_name,True,SNUM(conn))) *short_name = '\0'; } strupper(short_name); @@ -1353,7 +1363,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, break; case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)))); + put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ @@ -1403,8 +1413,9 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, /**************************************************************************** reply to a TRANS2_SETFILEINFO (set file info by fileid) ****************************************************************************/ -static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, char **pparams, +static int call_trans2setfilepathinfo(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, char **pparams, char **ppdata, int total_data) { char *params = *pparams; @@ -1420,17 +1431,17 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, int fd = -1; BOOL bad_path = False; - if (!CAN_WRITE(cnum)) + if (!CAN_WRITE(conn)) return(ERROR(ERRSRV,ERRaccess)); if (tran_call == TRANSACT2_SETFILEINFO) { int16 fnum = SVALS(params,0); info_level = SVAL(params,2); - CHECK_FNUM(fnum,cnum); + CHECK_FNUM(fnum,conn); CHECK_ERROR(fnum); - fname = Files[fnum].name; + fname = Files[fnum].fsp_name; fd = Files[fnum].fd_ptr->fd; if(fstat(fd,&st)!=0) { @@ -1442,8 +1453,8 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, info_level = SVAL(params,0); fname = fname1; pstrcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0,&bad_path); - if(!check_name(fname, cnum)) + unix_convert(fname,conn,0,&bad_path); + if(!check_name(fname, conn)) { if((errno == ENOENT) && bad_path) { @@ -1475,7 +1486,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, size = st.st_size; tvs.modtime = st.st_mtime; tvs.actime = st.st_atime; - mode = dos_mode(cnum,fname,&st); + mode = dos_mode(conn,fname,&st); if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ @@ -1572,14 +1583,14 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, */ if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { - if(file_utime(cnum, fname, &tvs)!=0) + if(file_utime(conn, fname, &tvs)!=0) { return(ERROR(ERRDOS,ERRnoaccess)); } } /* check the mode isn't different, before changing it */ - if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL)) + if (mode != dos_mode(conn, fname, &st) && dos_chmod(conn, fname, mode, NULL)) { DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1613,24 +1624,25 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, /**************************************************************************** reply to a TRANS2_MKDIR (make directory with extended attributes). ****************************************************************************/ -static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) +static int call_trans2mkdir(connection_struct *conn, + char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, char **ppdata) { char *params = *pparams; pstring directory; int ret = -1; BOOL bad_path = False; - if (!CAN_WRITE(cnum)) + if (!CAN_WRITE(conn)) return(ERROR(ERRSRV,ERRaccess)); pstrcpy(directory, ¶ms[4]); DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,cnum,0,&bad_path); - if (check_name(directory,cnum)) - ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); + unix_convert(directory,conn,0,&bad_path); + if (check_name(directory,conn)) + ret = sys_mkdir(directory,unix_mode(conn,aDIR)); if(ret < 0) { @@ -1659,8 +1671,10 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes) We don't actually do this - we just send a null response. ****************************************************************************/ -static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) +static int call_trans2findnotifyfirst(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, + char **pparams, char **ppdata) { static uint16 fnf_handle = 257; char *params = *pparams; @@ -1700,8 +1714,10 @@ static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for changes). Currently this does nothing. ****************************************************************************/ -static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) +static int call_trans2findnotifynext(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, + char **pparams, char **ppdata) { char *params = *pparams; @@ -1723,236 +1739,255 @@ static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int /**************************************************************************** reply to a SMBfindclose (stop trans2 directory search) ****************************************************************************/ -int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize) +int reply_findclose(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { - int cnum; - int outsize = 0; - int16 dptr_num=SVALS(inbuf,smb_vwv0); + int outsize = 0; + int16 dptr_num=SVALS(inbuf,smb_vwv0); - cnum = SVAL(inbuf,smb_tid); + DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num)); - DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num)); + dptr_close(dptr_num); - dptr_close(dptr_num); + outsize = set_message(outbuf,0,0,True); - outsize = set_message(outbuf,0,0,True); + DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num)); - DEBUG( 3, ( "SMBfindclose cnum=%d, dptr_num = %d\n", cnum, dptr_num ) ); - - return(outsize); + return(outsize); } /**************************************************************************** reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search) ****************************************************************************/ -int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize) +int reply_findnclose(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { - int cnum; - int outsize = 0; - int dptr_num= -1; - - cnum = SVAL(inbuf,smb_tid); - dptr_num = SVAL(inbuf,smb_vwv0); + int outsize = 0; + int dptr_num= -1; + + dptr_num = SVAL(inbuf,smb_vwv0); - DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num)); + DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num)); - /* We never give out valid handles for a - findnotifyfirst - so any dptr_num is ok here. - Just ignore it. */ + /* We never give out valid handles for a + findnotifyfirst - so any dptr_num is ok here. + Just ignore it. */ - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "SMB_findnclose cnum=%d, dptr_num = %d\n", cnum, dptr_num ) ); + DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num)); - return(outsize); + return(outsize); } /**************************************************************************** reply to a SMBtranss2 - just ignore it! ****************************************************************************/ -int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize) +int reply_transs2(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { - DEBUG(4,("Ignoring transs2 of length %d\n",length)); - return(-1); + DEBUG(4,("Ignoring transs2 of length %d\n",length)); + return(-1); } /**************************************************************************** reply to a SMBtrans2 ****************************************************************************/ -int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) +int reply_trans2(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) { - int outsize = 0; - int cnum = SVAL(inbuf,smb_tid); - unsigned int total_params = SVAL(inbuf, smb_tpscnt); - unsigned int total_data =SVAL(inbuf, smb_tdscnt); + int outsize = 0; + unsigned int total_params = SVAL(inbuf, smb_tpscnt); + unsigned int total_data =SVAL(inbuf, smb_tdscnt); #if 0 - unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt); - unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt); - unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt); - BOOL close_tid = BITSETW(inbuf+smb_flags,0); - BOOL no_final_response = BITSETW(inbuf+smb_flags,1); - int32 timeout = IVALS(inbuf,smb_timeout); + unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt); + unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt); + unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt); + BOOL close_tid = BITSETW(inbuf+smb_flags,0); + BOOL no_final_response = BITSETW(inbuf+smb_flags,1); + int32 timeout = IVALS(inbuf,smb_timeout); #endif - unsigned int suwcnt = SVAL(inbuf, smb_suwcnt); - unsigned int tran_call = SVAL(inbuf, smb_setup0); - char *params = NULL, *data = NULL; - int num_params, num_params_sofar, num_data, num_data_sofar; - - if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) - { - /* - * Queue this open message as we are the process of an oplock break. - */ - - DEBUG( 2, ( "reply_trans2: queueing message trans2open due to being " ) ); - DEBUGADD( 2, ( "in oplock break state.\n" ) ); + unsigned int suwcnt = SVAL(inbuf, smb_suwcnt); + unsigned int tran_call = SVAL(inbuf, smb_setup0); + char *params = NULL, *data = NULL; + int num_params, num_params_sofar, num_data, num_data_sofar; - push_oplock_pending_smb_message( inbuf, length); - return -1; - } + if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) { + /* Queue this open message as we are the process of an + * oplock break. */ - outsize = set_message(outbuf,0,0,True); + DEBUG(2,("reply_trans2: queueing message trans2open due to being ")); + DEBUGADD(2,( "in oplock break state.\n")); - /* All trans2 messages we handle have smb_sucnt == 1 - ensure this - is so as a sanity check */ - if(suwcnt != 1 ) - { - DEBUG(2,("Invalid smb_sucnt in trans2 call\n")); - return(ERROR(ERRSRV,ERRerror)); - } + push_oplock_pending_smb_message(inbuf, length); + return -1; + } + + outsize = set_message(outbuf,0,0,True); + + /* All trans2 messages we handle have smb_sucnt == 1 - ensure this + is so as a sanity check */ + if (suwcnt != 1) { + DEBUG(2,("Invalid smb_sucnt in trans2 call\n")); + return(ERROR(ERRSRV,ERRerror)); + } - /* Allocate the space for the maximum needed parameters and data */ - if (total_params > 0) - params = (char *)malloc(total_params); - if (total_data > 0) - data = (char *)malloc(total_data); + /* Allocate the space for the maximum needed parameters and data */ + if (total_params > 0) + params = (char *)malloc(total_params); + if (total_data > 0) + data = (char *)malloc(total_data); - if ((total_params && !params) || (total_data && !data)) - { - DEBUG(2,("Out of memory in reply_trans2\n")); - return(ERROR(ERRDOS,ERRnomem)); - } - - /* Copy the param and data bytes sent with this request into - the params buffer */ - num_params = num_params_sofar = SVAL(inbuf,smb_pscnt); - num_data = num_data_sofar = SVAL(inbuf, smb_dscnt); - - if (num_params > total_params || num_data > total_data) - exit_server("invalid params in reply_trans2"); - - if(params) - memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); - if(data) - memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); - - if(num_data_sofar < total_data || num_params_sofar < total_params) - { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - send_smb(Client,outbuf); - - while( num_data_sofar < total_data || num_params_sofar < total_params) - { - BOOL ret; - - ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize, - SMB_SECONDARY_WAIT); + if ((total_params && !params) || (total_data && !data)) { + DEBUG(2,("Out of memory in reply_trans2\n")); + return(ERROR(ERRDOS,ERRnomem)); + } - if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) - { - outsize = set_message(outbuf,0,0,True); - if(ret) - DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n")); - else - DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", - (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - if(params) - free(params); - if(data) - free(data); - return(ERROR(ERRSRV,ERRerror)); - } + /* Copy the param and data bytes sent with this request into + the params buffer */ + num_params = num_params_sofar = SVAL(inbuf,smb_pscnt); + num_data = num_data_sofar = SVAL(inbuf, smb_dscnt); + + if (num_params > total_params || num_data > total_data) + exit_server("invalid params in reply_trans2"); + + if(params) + memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); + if(data) + memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); + + if(num_data_sofar < total_data || num_params_sofar < total_params) { + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + send_smb(Client,outbuf); + + while (num_data_sofar < total_data || + num_params_sofar < total_params) { + BOOL ret; + + ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize, + SMB_SECONDARY_WAIT); + + if ((ret && + (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) { + outsize = set_message(outbuf,0,0,True); + if(ret) + DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n")); + else + DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); + if(params) + free(params); + if(data) + free(data); + return(ERROR(ERRSRV,ERRerror)); + } - /* Revise total_params and total_data in case they have changed downwards */ - total_params = SVAL(inbuf, smb_tpscnt); - total_data = SVAL(inbuf, smb_tdscnt); - num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt)); - num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt)); - if (num_params_sofar > total_params || num_data_sofar > total_data) - exit_server("data overflow in trans2"); - - memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], - smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params); - memcpy( &data[SVAL(inbuf, smb_sdsdisp)], - smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data); + /* Revise total_params and total_data in case + they have changed downwards */ + total_params = SVAL(inbuf, smb_tpscnt); + total_data = SVAL(inbuf, smb_tdscnt); + num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt)); + num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt)); + if (num_params_sofar > total_params || num_data_sofar > total_data) + exit_server("data overflow in trans2"); + + memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], + smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params); + memcpy( &data[SVAL(inbuf, smb_sdsdisp)], + smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data); + } + } + + if (Protocol >= PROTOCOL_NT1) { + uint16 flg2 = SVAL(outbuf,smb_flg2); + SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ } - } - - if (Protocol >= PROTOCOL_NT1) { - uint16 flg2 = SVAL(outbuf,smb_flg2); - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ - } - - /* Now we must call the relevant TRANS2 function */ - switch(tran_call) - { - case TRANSACT2_OPEN: - outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_FINDFIRST: - outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_FINDNEXT: - outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_QFSINFO: - outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_SETFSINFO: - outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_QPATHINFO: - case TRANSACT2_QFILEINFO: - outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data); - break; - case TRANSACT2_SETPATHINFO: - case TRANSACT2_SETFILEINFO: - outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data); - break; - case TRANSACT2_FINDNOTIFYFIRST: - outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_FINDNOTIFYNEXT: - outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_MKDIR: - outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - default: - /* Error in request */ - DEBUG( 2, ( "Unknown request %d in trans2 call\n", tran_call ) ); - if(params) - free(params); - if(data) - free(data); - return (ERROR(ERRSRV,ERRerror)); - } - /* As we do not know how many data packets will need to be - returned here the various call_trans2xxxx calls - must send their own. Thus a call_trans2xxx routine only - returns a value other than -1 when it wants to send - an error packet. - */ - - if(params) - free(params); - if(data) - free(data); - return outsize; /* If a correct response was needed the call_trans2xxx - calls have already sent it. If outsize != -1 then it is - returning an error packet. */ + /* Now we must call the relevant TRANS2 function */ + switch(tran_call) { + case TRANSACT2_OPEN: + outsize = call_trans2open(conn, + inbuf, outbuf, bufsize, + ¶ms, &data); + break; + + case TRANSACT2_FINDFIRST: + outsize = call_trans2findfirst(conn, inbuf, outbuf, + bufsize, ¶ms, &data); + break; + + case TRANSACT2_FINDNEXT: + outsize = call_trans2findnext(conn, inbuf, outbuf, + length, bufsize, + ¶ms, &data); + break; + + case TRANSACT2_QFSINFO: + outsize = call_trans2qfsinfo(conn, inbuf, outbuf, + length, bufsize, ¶ms, + &data); + break; + + case TRANSACT2_SETFSINFO: + outsize = call_trans2setfsinfo(conn, inbuf, outbuf, + length, bufsize, + ¶ms, &data); + break; + + case TRANSACT2_QPATHINFO: + case TRANSACT2_QFILEINFO: + outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, + length, bufsize, + ¶ms, &data, total_data); + break; + case TRANSACT2_SETPATHINFO: + case TRANSACT2_SETFILEINFO: + outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, + length, bufsize, + ¶ms, &data, + total_data); + break; + + case TRANSACT2_FINDNOTIFYFIRST: + outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, + length, bufsize, + ¶ms, &data); + break; + + case TRANSACT2_FINDNOTIFYNEXT: + outsize = call_trans2findnotifynext(conn, inbuf, outbuf, + length, bufsize, + ¶ms, &data); + break; + case TRANSACT2_MKDIR: + outsize = call_trans2mkdir(conn, inbuf, outbuf, length, + bufsize, ¶ms, &data); + break; + default: + /* Error in request */ + DEBUG(2,("Unknown request %d in trans2 call\n", tran_call)); + if(params) + free(params); + if(data) + free(data); + return (ERROR(ERRSRV,ERRerror)); + } + + /* As we do not know how many data packets will need to be + returned here the various call_trans2xxxx calls + must send their own. Thus a call_trans2xxx routine only + returns a value other than -1 when it wants to send + an error packet. + */ + + if(params) + free(params); + if(data) + free(data); + return outsize; /* If a correct response was needed the + call_trans2xxx calls have already sent + it. If outsize != -1 then it is returning */ } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 9e669c301b..1276eeaaac 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -27,7 +27,7 @@ static int initial_uid; static int initial_gid; /* what user is current? */ -struct current_user current_user; +extern struct current_user current_user; pstring OriginalDir; @@ -51,7 +51,7 @@ void init_uid(void) initial_uid = geteuid(); initial_gid = getegid(); - current_user.cnum = -1; + current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; ChDir(OriginalDir); @@ -180,7 +180,7 @@ BOOL become_guest(void) DEBUG(1,("Failed to become guest. Invalid guest account?\n")); } - current_user.cnum = -2; + current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; return(ret); @@ -210,90 +210,89 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) /**************************************************************************** become the user of a connection number ****************************************************************************/ -BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) +BOOL become_user(connection_struct *conn, uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); - int snum,gid; - int uid; - - /* - * We need a separate check in security=share mode due to vuid - * always being UID_FIELD_INVALID. If we don't do this then - * in share mode security we are *always* changing uid's between - * SMB's - this hurts performance - Badly. - */ - - if((lp_security() == SEC_SHARE) && (current_user.cnum == cnum) && - (current_user.uid == conn->uid)) { - DEBUG(4,("Skipping become_user - already user\n")); - return(True); - } else if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) && - (current_user.uid == vuser->uid)) { - DEBUG(4,("Skipping become_user - already user\n")); - return(True); - } - - unbecome_user(); - - if (!(VALID_CNUM(cnum) && conn->open)) { - DEBUG(2,("Connection %d not open\n",cnum)); - return(False); - } - - snum = conn->service; + user_struct *vuser = get_valid_user_struct(vuid); + int snum,gid; + int uid; + + /* + * We need a separate check in security=share mode due to vuid + * always being UID_FIELD_INVALID. If we don't do this then + * in share mode security we are *always* changing uid's between + * SMB's - this hurts performance - Badly. + */ + + if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && + (current_user.uid == conn->uid)) { + DEBUG(4,("Skipping become_user - already user\n")); + return(True); + } else if ((current_user.conn == conn) && + (vuser != 0) && (current_user.vuid == vuid) && + (current_user.uid == vuser->uid)) { + DEBUG(4,("Skipping become_user - already user\n")); + return(True); + } - if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) - return False; + unbecome_user(); - if (conn->force_user || - lp_security() == SEC_SHARE || - !(vuser) || (vuser->guest) - ) - { - uid = conn->uid; - gid = conn->gid; - current_user.groups = conn->groups; - current_user.ngroups = conn->ngroups; - } - else - { - if (!vuser) { - DEBUG(2,("Invalid vuid used %d\n",vuid)); - return(False); - } - uid = vuser->uid; - if(!*lp_force_group(snum)) - gid = vuser->gid; - else - gid = conn->gid; - current_user.ngroups = vuser->n_groups; - current_user.groups = vuser->groups; - } + if (!(conn && conn->open)) { + DEBUG(2,("Connection not open\n")); + return(False); + } - if (initial_uid == 0) - { - if (!become_gid(gid)) return(False); + snum = SNUM(conn); + + if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) + return False; + + if (conn->force_user || + lp_security() == SEC_SHARE || + !(vuser) || (vuser->guest)) { + uid = conn->uid; + gid = conn->gid; + current_user.groups = conn->groups; + current_user.ngroups = conn->ngroups; + } else { + if (!vuser) { + DEBUG(2,("Invalid vuid used %d\n",vuid)); + return(False); + } + uid = vuser->uid; + if(!*lp_force_group(snum)) { + gid = vuser->gid; + } else { + gid = conn->gid; + } + current_user.ngroups = vuser->n_groups; + current_user.groups = vuser->groups; + } + + if (initial_uid == 0) { + if (!become_gid(gid)) return(False); #ifdef HAVE_SETGROUPS - if (!(VALID_CNUM(cnum) && conn->ipc)) { - /* 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")); - } + if (!(conn && conn->ipc)) { + /* 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 (!conn->admin_user && !become_uid(uid)) - return(False); - } - - current_user.cnum = cnum; - current_user.vuid = vuid; + if (!conn->admin_user && !become_uid(uid)) + return(False); + } + + current_user.conn = conn; + current_user.vuid = vuid; - DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", - getuid(),geteuid(),getgid(),getegid())); + DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", + getuid(),geteuid(),getgid(),getegid())); - return(True); + return(True); } /**************************************************************************** @@ -301,7 +300,7 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) ****************************************************************************/ BOOL unbecome_user(void ) { - if (current_user.cnum == -1) + if (!current_user.conn) return(False); ChDir(OriginalDir); @@ -343,158 +342,12 @@ BOOL unbecome_user(void ) DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", getuid(),geteuid(),getgid(),getegid())); - current_user.cnum = -1; + current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; return(True); } - -/**************************************************************************** -This is a utility function of smbrun(). It must be called only from -the child as it may leave the caller in a privilaged state. -****************************************************************************/ -static BOOL setup_stdout_file(char *outfile,BOOL shared) -{ - int fd; - struct stat st; - mode_t mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH; - int flags = O_RDWR|O_CREAT|O_TRUNC|O_EXCL; - - close(1); - - if (shared) { - /* become root - unprivilaged users can't delete these files */ -#ifdef HAVE_SETRESUID - setresgid(0,0,0); - setresuid(0,0,0); -#else - setuid(0); - seteuid(0); -#endif - } - - if(stat(outfile, &st) == 0) { - /* Check we're not deleting a device file. */ - if(st.st_mode & S_IFREG) - unlink(outfile); - else - flags = O_RDWR; - } - /* now create the file */ - fd = open(outfile,flags,mode); - - if (fd == -1) return False; - - if (fd != 1) { - if (dup2(fd,1) != 0) { - DEBUG(2,("Failed to create stdout file descriptor\n")); - close(fd); - return False; - } - close(fd); - } - return True; -} - - -/**************************************************************************** -run a command being careful about uid/gid handling and putting the output in -outfile (or discard it if outfile is NULL). - -if shared is True then ensure the file will be writeable by all users -but created such that its owned by root. This overcomes a security hole. - -if shared is not set then open the file with O_EXCL set -****************************************************************************/ -int smbrun(char *cmd,char *outfile,BOOL shared) -{ - int fd,pid; - int uid = current_user.uid; - int gid = current_user.gid; - -#ifndef HAVE_EXECL - int ret; - pstring syscmd; - char *path = lp_smbrun(); - - /* in the old method we use system() to execute smbrun which then - executes the command (using system() again!). This involves lots - of shell launches and is very slow. It also suffers from a - potential security hole */ - if (!file_exist(path,NULL)) - { - DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",path)); - return(1); - } - - slprintf(syscmd,sizeof(syscmd)-1,"%s %d %d \"(%s 2>&1) > %s\"", - path,uid,gid,cmd, - outfile?outfile:"/dev/null"); - - DEBUG(5,("smbrun - running %s ",syscmd)); - ret = system(syscmd); - DEBUG(5,("gave %d\n",ret)); - return(ret); -#else - /* in this newer method we will exec /bin/sh with the correct - arguments, after first setting stdout to point at the file */ - - if ((pid=fork())) { - int status=0; - /* the parent just waits for the child to exit */ - if (sys_waitpid(pid,&status,0) != pid) { - DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno))); - return -1; - } - return status; - } - - - /* we are in the child. we exec /bin/sh to do the work for us. we - don't directly exec the command we want because it may be a - pipeline or anything else the config file specifies */ - - /* point our stdout at the file we want output to go into */ - if (outfile && !setup_stdout_file(outfile,shared)) { - exit(80); - } - - /* 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 - setresgid(0,0,0); - setresuid(0,0,0); - setresgid(gid,gid,gid); - setresuid(uid,uid,uid); -#else - setuid(0); - seteuid(0); - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); -#endif - - if (getuid() != uid || geteuid() != uid || - getgid() != gid || getegid() != gid) { - /* we failed to lose our privilages - do not execute the command */ - exit(81); /* we can't print stuff at this stage, instead use exit codes - for debugging */ - } - - /* close all other file descriptors, leaving only 0, 1 and 2. 0 and - 2 point to /dev/null from the startup code */ - for (fd=3;fd<256;fd++) close(fd); - - execl("/bin/sh","sh","-c",cmd,NULL); - - /* not reached */ - exit(82); -#endif - return 1; -} - static struct current_user current_user_saved; static int become_root_depth; static pstring become_root_dir; -- cgit From e13aeea928dd89373cfaf3916c96f853c1227884 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Aug 1998 01:19:26 +0000 Subject: configure: Changes for extra headers. configure.in: Source for header changes. client/clitar.c: Fixed isXXX macros & debugs for gcc pedantic compile. include/config.h.in: Added MEMSET, BZERO, MEMORY, RPCSVC_YPCLNT, STRINGS headers. include/includes.h: Headers for the above. include/smb.h: Made SIGNAL_CAST POSIX by default void (*)(int). lib/access.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/charset.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/debug.c: Fixed signal functs. lib/kanji.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/smbrun.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/util.c: Fixed isXXX macros & debugs for gcc pedantic compile. libsmb/namequery.c: Fixed isXXX macros & debugs for gcc pedantic compile. locking/shmem.c: Fixed isXXX macros & debugs for gcc pedantic compile. locking/shmem_sysv.c: Fixed error messages in sysV stuff. nmbd/asyncdns.c: Fixed signal functs. nmbd/nmbd.c: Fixed isXXX macros & debugs for gcc pedantic compile. passdb/passdb.c: Fixed isXXX macros & debugs for gcc pedantic compile. passdb/smbpassfile.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/chgpasswd.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/ipc.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/nttrans.c: Fixed fsp code path. smbd/password.c: fixed HAVE_YP_GET_DEFAULT_DOMAIN problem. smbd/printing.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/reply.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/server.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/trans2.c: Fixed core dump bug. smbd/uid.c: Fixed isXXX macros & debugs for gcc pedantic compile. Jeremy. (This used to be commit 1b9cbcd02e575dc0a95fa589f720df30a4acc46b) --- source3/smbd/chgpasswd.c | 6 +++--- source3/smbd/ipc.c | 4 ++-- source3/smbd/nttrans.c | 3 ++- source3/smbd/password.c | 2 +- source3/smbd/reply.c | 7 +++---- source3/smbd/server.c | 16 +++++++--------- source3/smbd/trans2.c | 10 ++++++---- source3/smbd/uid.c | 8 ++++---- 8 files changed, 28 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 6594c5f48c..bd7d28b11f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -342,7 +342,7 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL if(as_root) become_root(False); - DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,getuid(),getgid())); + DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid())); chstat = dochild(master, slavedev, name, passwordprogram, as_root); if(as_root) @@ -404,7 +404,7 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) len = strlen(oldpass); for(i = 0; i < len; i++) { - if(iscntrl(oldpass[i])) { + if(iscntrl((int)oldpass[i])) { DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n")); return False; } @@ -412,7 +412,7 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) len = strlen(newpass); for(i = 0; i < len; i++) { - if(iscntrl(newpass[i])) { + if(iscntrl((int)newpass[i])) { DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n")); return False; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a72b442735..63495f0479 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -274,7 +274,7 @@ static int get_counter(char** p) { int i, n; if (!p || !(*p)) return(1); - if (!isdigit(**p)) return 1; + if (!isdigit((int)**p)) return 1; for (n = 0;;) { i = **p; if (isdigit(i)) @@ -1969,7 +1969,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha break; case 0xb: /* change print job name, data gives the name */ /* jobid, snum should be zero */ - if (isalpha(*s)) + if (isalpha((int)*s)) { pstring name; int l = 0; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bff61b6736..94ecbfea49 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -452,6 +452,7 @@ int reply_ntcreate_and_X(connection_struct *conn, int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &fnum); if(ret != 0) return ret; + fsp = &Files[fnum]; smb_action = FILE_WAS_OPENED; } else { @@ -667,7 +668,7 @@ int reply_ntcreate_and_X(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X: open fnum = %d, name = %s\n", - fnum, fsp?fsp->fsp_name:"NULL")); + fnum, fsp->fsp_name)); return chain_reply(inbuf,outbuf,length,bufsize); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 118251ffd6..121ebb7f00 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -829,7 +829,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) { BOOL host_ok = False; -#ifdef HAVE_NETGROUP +#if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN) if (is_group) { static char *mydomain = NULL; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 66d1dd2839..626d2e9617 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -327,7 +327,6 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt pstrcpy(smb_buf(outbuf),devicename); } else { char *fsname = FSTYPE_STRING; - char *p; set_message(outbuf,3,3,True); @@ -1565,7 +1564,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 2, ( "new file %s\n", fname ) ); DEBUG( 3, ( "mknew %s fd=%d fnum=%d dmode=%d umode=%o\n", - fname, fsp->fd_ptr->fd, fnum, createmode, unixmode ) ); + fname, fsp->fd_ptr->fd, fnum, createmode, (int)unixmode ) ); return(outsize); } @@ -1642,7 +1641,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 2, ( "created temp file %s\n", fname2 ) ); DEBUG( 3, ( "ctemp %s fd=%d fnum=%d dmode=%d umode=%o\n", - fname2, fsp->fd_ptr->fd, fnum, createmode, unixmode ) ); + fname2, fsp->fd_ptr->fd, fnum, createmode, (int)unixmode ) ); return(outsize); } @@ -2640,7 +2639,7 @@ int reply_printopen(connection_struct *conn, pstrcpy(s,smb_buf(inbuf)+1); p = s; while (*p) { - if (!(isalnum(*p) || strchr("._-",*p))) + if (!(isalnum((int)*p) || strchr("._-",*p))) *p = 'X'; p++; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9c7bafd9dd..ba93ceaa16 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2436,7 +2436,7 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int /**************************************************************************** this is called when the client exits abruptly **************************************************************************/ -static int sig_pipe(void) +static void sig_pipe(int sig) { struct cli_state *cli; BlockSignals(True,SIGPIPE); @@ -2445,11 +2445,10 @@ static int sig_pipe(void) DEBUG(3,("lost connection to password server\n")); cli_shutdown(cli); BlockSignals(False,SIGPIPE); - return 0; + return; } exit_server("Got sigpipe\n"); - return(0); } /**************************************************************************** @@ -2756,7 +2755,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); oplock_port = ntohs(sock_name.sin_port); DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", - getpid(), oplock_port)); + (int)getpid(), oplock_port)); return True; } @@ -3420,7 +3419,7 @@ this prevents zombie child processes ****************************************************************************/ static BOOL reload_after_sighup = False; -static int sig_hup(void) +static void sig_hup(int sig) { BlockSignals(True,SIGHUP); DEBUG(0,("Got SIGHUP\n")); @@ -3433,7 +3432,6 @@ static int sig_hup(void) reload_after_sighup = True; BlockSignals(False,SIGHUP); - return(0); } /**************************************************************************** @@ -4377,7 +4375,7 @@ static BOOL dump_core(void) rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur); setrlimit(RLIMIT_CORE, &rlp); getrlimit(RLIMIT_CORE, &rlp); - DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max)); + DEBUG(3,("Core limits now %d %d\n",(int)rlp.rlim_cur,(int)rlp.rlim_max)); } #endif #endif @@ -5312,14 +5310,14 @@ static void usage(char *pname) rlp.rlim_cur = (MAX_OPEN_FILES+10>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES+10; setrlimit(RLIMIT_NOFILE, &rlp); getrlimit(RLIMIT_NOFILE, &rlp); - DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur)); + DEBUG(3,("Maximum number of open files per session is %d\n",(int)rlp.rlim_cur)); } #endif #endif DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", - getuid(),getgid(),geteuid(),getegid())); + (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 07f0316c22..992d8cd616 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -940,7 +940,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", */ int current_pos, start_pos; - char *dname; + char *dname = NULL; void *dirptr = conn->dirptr; start_pos = TellDir(dirptr); for(current_pos = start_pos; current_pos >= 0; current_pos--) @@ -957,7 +957,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * here. */ - name_map_mangle( dname, False, SNUM(conn)); + if(dname != NULL) + name_map_mangle( dname, False, SNUM(conn)); if(dname && strcsequal( resume_name, dname)) { @@ -984,9 +985,10 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * here. */ - name_map_mangle( dname, False, SNUM(conn)); + if(dname != NULL) + name_map_mangle( dname, False, SNUM(conn)); - if(strcsequal( resume_name, dname)) + if(dname && strcsequal( resume_name, dname)) { SeekDir(dirptr, current_pos+1); DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 1276eeaaac..08a3952b3a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -96,7 +96,7 @@ static BOOL become_uid(int uid) #endif { DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n", - uid,getuid(), geteuid())); + uid,(int)getuid(), (int)geteuid())); if (uid > 32000) { DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n")); } @@ -133,7 +133,7 @@ static BOOL become_gid(int gid) #endif { DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n", - gid,getgid(),getegid())); + gid,(int)getgid(),(int)getegid())); if (gid > 32000) { DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); } @@ -290,7 +290,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) current_user.vuid = vuid; DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", - getuid(),geteuid(),getgid(),getegid())); + (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); return(True); } @@ -340,7 +340,7 @@ BOOL unbecome_user(void ) DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", - getuid(),geteuid(),getgid(),getegid())); + (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; -- cgit From 127655cc888ac40332d4e8e5b94aab03f5120aae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 15 Aug 1998 07:27:34 +0000 Subject: this checkin gets rid of the global Files[] array and makes it local in files.c it should now be faily easy to expand the default MAX_OPEN_FILES to many thousands. (This used to be commit b088c804f98908eb02f05ab2f2e8a61691a0a582) --- source3/smbd/files.c | 321 +++++++++++++++++++++++++++ source3/smbd/ipc.c | 174 ++++++++------- source3/smbd/nttrans.c | 123 +++++------ source3/smbd/pipes.c | 13 +- source3/smbd/reply.c | 572 +++++++++++++++++++++---------------------------- source3/smbd/server.c | 378 +++++++------------------------- source3/smbd/trans2.c | 45 ++-- 7 files changed, 820 insertions(+), 806 deletions(-) create mode 100644 source3/smbd/files.c (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c new file mode 100644 index 0000000000..a37d190f01 --- /dev/null +++ b/source3/smbd/files.c @@ -0,0 +1,321 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Files[] structure handling + Copyright (C) Andrew Tridgell 1998 + + 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; + +#define MAX_OPEN_FILES 100 + +#define MAX_FNUMS (MAX_OPEN_FILES+MAX_OPEN_DIRECTORIES) +#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_FNUMS)) + +static files_struct Files[MAX_FNUMS]; + +/* + * Indirection for file fd's. Needed as POSIX locking + * is based on file/process, not fd/process. + */ +static file_fd_struct FileFd[MAX_OPEN_FILES]; +static int max_file_fd_used = 0; + + +/**************************************************************************** + find first available file slot +****************************************************************************/ +files_struct *find_free_file(void ) +{ + int i; + static int first_file; + + /* we want to give out file handles differently on each new + connection because of a common bug in MS clients where they try to + reuse a file descriptor from an earlier smb connection. This code + increases the chance that the errant client will get an error rather + than causing corruption */ + if (first_file == 0) { + first_file = (getpid() ^ (int)time(NULL)) % MAX_FNUMS; + if (first_file == 0) first_file = 1; + } + + if (first_file >= MAX_FNUMS) + first_file = 1; + + for (i=first_file;iref_count > 0) && + (((uint32)sbuf->st_dev) == fd_ptr->dev) && + (((uint32)sbuf->st_ino) == fd_ptr->inode)) { + fd_ptr->ref_count++; + DEBUG(3, + ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n", + i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count)); + return fd_ptr; + } + } + return 0; +} + +/**************************************************************************** +fd support routines - attempt to find a empty slot in the FileFd array. +Increments the ref_count of the returned entry. +****************************************************************************/ +file_fd_struct *fd_get_new(void) +{ + extern struct current_user current_user; + int i; + file_fd_struct *fd_ptr; + + for(i = 0; i < MAX_OPEN_FILES; i++) { + fd_ptr = &FileFd[i]; + if(fd_ptr->ref_count == 0) { + fd_ptr->dev = (uint32)-1; + fd_ptr->inode = (uint32)-1; + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; + fd_ptr->uid_cache_count = 0; + fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + fd_ptr->ref_count++; + /* Increment max used counter if neccessary, cuts down + on search time when re-using */ + if(i > max_file_fd_used) + max_file_fd_used = i; + DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n", + i, fd_ptr->dev, fd_ptr->inode)); + return fd_ptr; + } + } + DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\n")); + return 0; +} + + +/**************************************************************************** +close all open files for a connection +****************************************************************************/ +void file_close_conn(connection_struct *conn) +{ + int i; + for (i=0;irlp.rlim_max)? + rlp.rlim_max:MAX_FNUMS+10; + setrlimit(RLIMIT_NOFILE, &rlp); + getrlimit(RLIMIT_NOFILE, &rlp); + DEBUG(3,("Maximum number of open files per session is %d\n", + (int)rlp.rlim_cur)); + } +#endif +#endif + + + + for (i=0;iref_count = 0; + fd_ptr->dev = (int32)-1; + fd_ptr->inode = (int32)-1; + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; + } +} + +/**************************************************************************** +find a fsp given a fnum +****************************************************************************/ +files_struct *file_fsp(int fnum) +{ + if (!VALID_FNUM(fnum)) return NULL; + return &Files[fnum]; +} + + +/**************************************************************************** +close files open by a specified vuid +****************************************************************************/ +void file_close_user(int vuid) +{ + int i; + for (i=0;ivuid == vuid) && fsp->open) { + if(!fsp->is_directory) + close_file(fsp,False); + else + close_directory(fsp); + } + } +} + + +/**************************************************************************** +find a fsp given a device, inode and timevalue +****************************************************************************/ +files_struct *file_find_dit(int dev, int inode, struct timeval *tval) +{ + int i; + for (i=0;iopen && + fsp->fd_ptr->dev == dev && + fsp->fd_ptr->inode == inode && + fsp->open_time.tv_sec == tval->tv_sec && + fsp->open_time.tv_usec == tval->tv_usec) { + return fsp; + } + } + return NULL; +} + +/**************************************************************************** +find a fsp that is open for printing +****************************************************************************/ +files_struct *file_find_print(void) +{ + int i; + + for (i=0;iopen && fsp->print_file) { + return fsp; + } + } + return NULL; +} + + +/**************************************************************************** +sync open files on a connection +****************************************************************************/ +void file_sync_all(connection_struct *conn) +{ + int i; + for (i=0;iopen && conn == fsp->conn) { + sync_file(conn,fsp); + } + } +} + + +void file_free(files_struct *fsp) +{ + memset(fsp, 0, sizeof(*fsp)); +} diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 63495f0479..ae225956a2 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -36,7 +36,6 @@ extern int DEBUGLEVEL; extern int max_send; -extern files_struct Files[]; extern fstring local_machine; extern fstring global_myworkgroup; @@ -1913,108 +1912,105 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - struct pack_desc desc; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int jobid, snum; - int uLevel = SVAL(p,2); - int function = SVAL(p,4); /* what is this ?? */ - int i; - char *s = data; + struct pack_desc desc; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int jobid, snum; + int uLevel = SVAL(p,2); + int function = SVAL(p,4); /* what is this ?? */ + int i; + char *s = data; + files_struct *fsp; - printjob_decode(SVAL(p,0), &snum, &jobid); + printjob_decode(SVAL(p,0), &snum, &jobid); - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; - - /* check it's a supported varient */ - if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2))) - return(False); + *rdata_len = 0; + + /* check it's a supported varient */ + if ((strcmp(str1,"WWsTP")) || + (!check_printjob_info(&desc,uLevel,str2))) + return(False); - switch (function) { - case 0x6: /* change job place in the queue, data gives the new place */ - if (snum >= 0 && VALID_SNUM(snum)) - { - print_queue_struct *queue=NULL; - int count; + switch (function) { + case 0x6: /* change job place in the queue, + data gives the new place */ + if (snum >= 0 && VALID_SNUM(snum)) { + print_queue_struct *queue=NULL; + int count; - lpq_reset(snum); - count = get_printqueue(snum,conn,&queue,NULL); - for (i=0;i place ) /* move up */; - } + { + int place= SVAL(data,0); + /* we currently have no way of + doing this. Can any unix do it? */ + if (i < place) /* move down */; + else if (i > place ) /* move up */; + } #endif - desc.errcode=NERR_notsupported; /* not yet supported */ - if (queue) free(queue); - } - } - else desc.errcode=NERR_JobNotFound; - break; - case 0xb: /* change print job name, data gives the name */ - /* jobid, snum should be zero */ - if (isalpha((int)*s)) - { - pstring name; - int l = 0; - while (l<64 && *s) - { - if (issafe(*s)) name[l++] = *s; - s++; - } - name[l] = 0; + desc.errcode=NERR_notsupported; /* not yet + supported */ + if (queue) free(queue); + } + } else { + desc.errcode=NERR_JobNotFound; + } + break; + + case 0xb: /* change print job name, data gives the name */ + /* jobid, snum should be zero */ + if (isalpha((int)*s)) { + pstring name; + int l = 0; + while (l<64 && *s) { + if (issafe(*s)) name[l++] = *s; + s++; + } + name[l] = 0; - DEBUG(3,("Setting print name to %s\n",name)); + DEBUG(3,("Setting print name to %s\n",name)); - become_root(True); - - for (i=0;iconn; + unbecome_user(); - if (!become_user(fconn,vuid) || - !become_service(fconn,True)) - break; + if (!become_user(fconn,vuid) || + !become_service(fconn,True)) + break; - if (sys_rename(Files[i].fsp_name,name) == 0) { - string_set(&Files[i].fsp_name,name); - } - break; - } + if (sys_rename(fsp->fsp_name,name) == 0) { + string_set(&fsp->fsp_name,name); + } + break; + } + } + desc.errcode=NERR_Success; + break; - unbecome_root(True); - } - desc.errcode=NERR_Success; - - break; - default: /* not implemented */ - return False; - } + default: /* not implemented */ + return False; + } - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); /* converter word */ - - return(True); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); /* converter word */ + + return(True); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 94ecbfea49..d396b05a62 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -24,8 +24,7 @@ extern int DEBUGLEVEL; extern int Protocol; -extern int chain_fnum; -extern files_struct Files[]; +extern files_struct *chain_fsp; extern int Client; extern int oplock_sock; extern int smb_read_error; @@ -388,7 +387,8 @@ static int nt_open_pipe(char *fname, connection_struct *conn, if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); - *ppnum = pnum + 0x800; /* Mark file handle up into high range. */ + *ppnum = pnum + PIPE_HANDLE_OFFSET; /* Mark file handle up into high + range. */ return 0; } @@ -399,7 +399,6 @@ int reply_ntcreate_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; - int fnum = -1; uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); @@ -413,7 +412,7 @@ int reply_ntcreate_and_X(connection_struct *conn, /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - int unixmode; + int unixmode, pnum = -1; int fmode=0,mtime=0,rmode=0; off_t file_len = 0; struct stat sbuf; @@ -449,10 +448,9 @@ int reply_ntcreate_and_X(connection_struct *conn, /* If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { - int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &fnum); + int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) return ret; - fsp = &Files[fnum]; smb_action = FILE_WAS_OPENED; } else { @@ -468,20 +466,18 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_convert(fname,conn,0,&bad_path); - fnum = find_free_file(); - if (fnum < 0) { + fsp = find_free_file(); + if (!fsp) { restore_case_semantics(file_attributes); return(ERROR(ERRSRV,ERRnofids)); } - fsp = &Files[fnum]; - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); restore_case_semantics(file_attributes); @@ -500,13 +496,13 @@ int reply_ntcreate_and_X(connection_struct *conn, if(flags & OPEN_DIRECTORY) { oplock_request = 0; - open_directory(fnum, conn, fname, smb_ofun, + open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); if(!fsp->open) { - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { @@ -527,7 +523,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - open_file_shared(fnum,conn,fname,smb_open_mode, + open_file_shared(fsp,conn,fname,smb_open_mode, smb_ofun,unixmode, oplock_request,&rmode,&smb_action); @@ -551,10 +547,10 @@ int reply_ntcreate_and_X(connection_struct *conn, if(errno == EISDIR) { oplock_request = 0; - open_directory(fnum, conn, fname, smb_ofun, unixmode, &smb_action); + open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); if(!fsp->open) { - fsp->reserved = False; + file_free(fsp); restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -564,7 +560,7 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); restore_case_semantics(file_attributes); @@ -575,13 +571,13 @@ int reply_ntcreate_and_X(connection_struct *conn, if(fsp->is_directory) { if(sys_stat(fsp->fsp_name, &sbuf) != 0) { - close_directory(fnum); + close_directory(fsp); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -595,7 +591,7 @@ int reply_ntcreate_and_X(connection_struct *conn, fmode = FILE_ATTRIBUTE_NORMAL; mtime = sbuf.st_mtime; if (!fsp->is_directory && (fmode & aDIR)) { - close_file(fnum,False); + close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -623,7 +619,11 @@ int reply_ntcreate_and_X(connection_struct *conn, SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); p++; - SSVAL(p,0,fnum); + if (IS_IPC(conn)) { + SSVAL(p,0,pnum); + } else { + SSVAL(p,0,fsp->fnum); + } p += 2; SIVAL(p,0,smb_action); p += 4; @@ -664,11 +664,10 @@ int reply_ntcreate_and_X(connection_struct *conn, SCVAL(p,0,fsp->is_directory ? 1 : 0); } - chain_fnum = fnum; + chain_fsp = fsp; - - DEBUG(5,("reply_ntcreate_and_X: open fnum = %d, name = %s\n", - fnum, fsp->fsp_name)); + DEBUG(5,("reply_ntcreate_and_X: open name = %s\n", + fsp->fsp_name)); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -683,7 +682,6 @@ static int call_nt_transact_create(connection_struct *conn, char **ppdata) { pstring fname; - int fnum = -1; char *params = *ppparams; uint32 flags = IVAL(params,0); uint32 desired_access = IVAL(params,8); @@ -698,7 +696,7 @@ static int call_nt_transact_create(connection_struct *conn, /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - int unixmode; + int unixmode, pnum = -1; int fmode=0,mtime=0,rmode=0; off_t file_len = 0; struct stat sbuf; @@ -732,7 +730,7 @@ static int call_nt_transact_create(connection_struct *conn, /* If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { - int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &fnum); + int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) return ret; smb_action = FILE_WAS_OPENED; @@ -745,14 +743,12 @@ static int call_nt_transact_create(connection_struct *conn, unix_convert(fname,conn,0,&bad_path); - fnum = find_free_file(); - if (fnum < 0) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); + fsp = find_free_file(); + if (!fsp) { + restore_case_semantics(file_attributes); + return(ERROR(ERRSRV,ERRnofids)); } - fsp = &Files[fnum]; - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; @@ -784,10 +780,10 @@ static int call_nt_transact_create(connection_struct *conn, * CreateDirectory() call. */ - open_directory(fnum, conn, fname, smb_ofun, unixmode, &smb_action); + open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); if(!fsp->open) { - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { @@ -796,7 +792,7 @@ static int call_nt_transact_create(connection_struct *conn, * Ordinary file case. */ - open_file_shared(fnum,conn,fname,smb_open_mode,smb_ofun,unixmode, + open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp->open) { @@ -804,7 +800,7 @@ static int call_nt_transact_create(connection_struct *conn, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); restore_case_semantics(file_attributes); @@ -812,7 +808,7 @@ static int call_nt_transact_create(connection_struct *conn, } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + close_file(fsp,False); restore_case_semantics(file_attributes); @@ -826,7 +822,7 @@ static int call_nt_transact_create(connection_struct *conn, mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum,False); + close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -855,7 +851,11 @@ static int call_nt_transact_create(connection_struct *conn, p = params; SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); p += 2; - SSVAL(p,0,fnum); + if (IS_IPC(conn)) { + SSVAL(p,0,pnum); + } else { + SSVAL(p,0,fsp->fnum); + } p += 2; SIVAL(p,0,smb_action); p += 8; @@ -940,17 +940,17 @@ static int call_nt_transact_rename(connection_struct *conn, { char *params = *ppparams; pstring new_name; - int fnum = SVAL(params, 0); + files_struct *fsp = GETFSP(params, 0); BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)), ((uint32)sizeof(new_name)-1)); int outsize = 0; - CHECK_FNUM(fnum, conn); + CHECK_FSP(fsp, conn); StrnCpy(new_name,params+4,fname_len); new_name[fname_len] = '\0'; - outsize = rename_internals(conn, inbuf, outbuf, Files[fnum].fsp_name, + outsize = rename_internals(conn, inbuf, outbuf, fsp->fsp_name, new_name, replace_if_exists); if(outsize == 0) { /* @@ -959,7 +959,7 @@ static int call_nt_transact_rename(connection_struct *conn, send_nt_replies(outbuf, bufsize, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", - Files[fnum].fsp_name, new_name)); + fsp->fsp_name, new_name)); outsize = -1; } @@ -976,7 +976,7 @@ static int call_nt_transact_rename(connection_struct *conn, typedef struct { ubi_slNode msg_next; - int fnum; + files_struct *fsp; connection_struct *conn; time_t next_check_time; time_t modify_time; /* Info from the directory we're monitoring. */ @@ -1023,14 +1023,13 @@ static void change_notify_reply_packet(char *inbuf, int error_class, uint32 erro /**************************************************************************** Delete entries by fnum from the change notify pending queue. *****************************************************************************/ - -void remove_pending_change_notify_requests_by_fid(int fnum) +void remove_pending_change_notify_requests_by_fid(files_struct *fsp) { change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); change_notify_buf *prev = NULL; while(cnbp != NULL) { - if(cnbp->fnum == fnum) { + if(cnbp->fsp == fsp) { free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; @@ -1085,9 +1084,8 @@ void process_pending_change_notify_queue(time_t t) while((cnbp != NULL) && (cnbp->next_check_time <= t)) { struct stat st; - int fnum = cnbp->fnum; + files_struct *fsp = cnbp->fsp; connection_struct *conn = cnbp->conn; - files_struct *fsp = &Files[fnum]; uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); @@ -1133,8 +1131,8 @@ Error was %s.\n", fsp->fsp_name, strerror(errno) )); /* * Remove the entry and return a change notify to the client. */ - DEBUG(5,("process_pending_change_notify_queue: directory fnum = %d, name = %s changed\n", - fnum, fsp->fsp_name )); + DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed\n", + fsp->fsp_name )); change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); @@ -1164,19 +1162,16 @@ static int call_nt_transact_notify_change(connection_struct *conn, { char *setup = *ppsetup; files_struct *fsp; - int fnum = -1; change_notify_buf *cnbp; struct stat st; - fnum = SVAL(setup,4); + fsp = GETFSP(setup,4); - DEBUG(3,("call_nt_transact_notify_change: fnum = %d.\n", fnum)); + DEBUG(3,("call_nt_transact_notify_change\n")); - if(!VALID_FNUM(fnum)) + if(!fsp) return(ERROR(ERRDOS,ERRbadfid)); - fsp = &Files[fnum]; - if((!fsp->open) || (!fsp->is_directory) || (conn != fsp->conn)) return(ERROR(ERRDOS,ERRbadfid)); @@ -1198,14 +1193,14 @@ static int call_nt_transact_notify_change(connection_struct *conn, */ if(sys_stat(fsp->fsp_name, &st) < 0) { - DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \ -Error was %s\n", fnum, fsp->fsp_name, strerror(errno) )); + DEBUG(0,("call_nt_transact_notify_change: Unable to stat name = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); free((char *)cnbp); return(UNIXERROR(ERRDOS,ERRbadfid)); } memcpy(cnbp->request_buf, inbuf, smb_size); - cnbp->fnum = fnum; + cnbp->fsp = fsp; cnbp->conn = conn; cnbp->modify_time = st.st_mtime; cnbp->status_time = st.st_ctime; @@ -1221,7 +1216,7 @@ Error was %s\n", fnum, fsp->fsp_name, strerror(errno) )); ubi_slAddTail(&change_notify_queue, cnbp); DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ -fid=%d, name = %s\n", fnum, fsp->fsp_name )); +name = %s\n", fsp->fsp_name )); return -1; } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 2a51e83946..9ec77c08ca 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -44,7 +44,6 @@ extern int Client; #define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES)) #define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && Pipes[pnum].open) -#define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum) /* this macro should always be used to extract an pnum (smb_fid) from a packet to ensure chaining works correctly */ @@ -84,7 +83,7 @@ int reply_open_pipe_and_X(connection_struct *conn, if( strequal(fname,pipe_names[i].client_pipe) ) break; - if ( pipe_names[i].client_pipe == NULL ) + if (pipe_names[i].client_pipe == NULL) return(ERROR(ERRSRV,ERRaccess)); /* Strip \PIPE\ off the name. */ @@ -111,7 +110,9 @@ int reply_open_pipe_and_X(connection_struct *conn, rmode = 1; } - SSVAL(outbuf,smb_vwv2, pnum + 0x800); /* mark file handle up into high range */ + SSVAL(outbuf,smb_vwv2, pnum + PIPE_HANDLE_OFFSET); /* mark file + handle up into + high range */ SSVAL(outbuf,smb_vwv3,fmode); put_dos_date3(outbuf,smb_vwv4,mtime); SIVAL(outbuf,smb_vwv6,size); @@ -138,12 +139,6 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) char *data; BOOL ok = False; -/* - CHECK_FNUM(fnum,cnum); - CHECK_READ(fnum); - CHECK_ERROR(fnum); -*/ - set_message(outbuf,12,0,True); data = smb_buf(outbuf); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 626d2e9617..e9a25ea79a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -33,9 +33,8 @@ extern int Protocol; extern int DEBUGLEVEL; extern int max_send; extern int max_recv; -extern int chain_fnum; +extern files_struct *chain_fsp; extern char magic_char; -extern files_struct Files[]; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; @@ -44,11 +43,6 @@ extern fstring global_myworkgroup; extern int Client; extern int global_oplock_break; -/* this macro should always be used to extract an fnum (smb_fid) from -a packet to ensure chaining works correctly */ -#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) - - /**************************************************************************** report a possible attack via the password buffer overflow bug ****************************************************************************/ @@ -1232,7 +1226,6 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; - int fnum = -1; int outsize = 0; int fmode=0; int share_mode; @@ -1250,12 +1243,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,conn,0,&bad_path); - fnum = find_free_file(); - if (fnum < 0) + fsp = find_free_file(); + if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - fsp = &Files[fnum]; - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) @@ -1263,13 +1254,13 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } unixmode = unix_mode(conn,aARCH); - open_file_shared(fnum,conn,fname,share_mode,3,unixmode, + open_file_shared(fsp,conn,fname,share_mode,3,unixmode, oplock_request,&rmode,NULL); if (!fsp->open) @@ -1279,12 +1270,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1294,12 +1285,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (fmode & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fnum,False); + close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } outsize = set_message(outbuf,7,0,True); - SSVAL(outbuf,smb_vwv0,fnum); + SSVAL(outbuf,smb_vwv0,fsp->fnum); SSVAL(outbuf,smb_vwv1,fmode); if(lp_dos_filetime_resolution(SNUM(conn)) ) put_dos_date3(outbuf,smb_vwv2,mtime & ~1); @@ -1324,7 +1315,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; - int fnum = -1; int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); /* Breakout the oplock request bits so we can set the @@ -1354,12 +1344,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt pstrcpy(fname,smb_buf(inbuf)); unix_convert(fname,conn,0,&bad_path); - fnum = find_free_file(); - if (fnum < 0) + fsp = find_free_file(); + if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - fsp = &Files[fnum]; - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) @@ -1367,13 +1355,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } unixmode = unix_mode(conn,smb_attr | aARCH); - open_file_shared(fnum,conn,fname,smb_mode,smb_ofun,unixmode, + open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp->open) @@ -1383,12 +1371,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1396,7 +1384,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum,False); + close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1427,7 +1415,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } set_message(outbuf,15,0,True); - SSVAL(outbuf,smb_vwv2,fnum); + SSVAL(outbuf,smb_vwv2,fsp->fnum); SSVAL(outbuf,smb_vwv3,fmode); if(lp_dos_filetime_resolution(SNUM(conn)) ) put_dos_date3(outbuf,smb_vwv4,mtime & ~1); @@ -1437,7 +1425,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,smb_action); - chain_fnum = fnum; + chain_fsp = fsp; return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1458,16 +1446,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, /* in user level security we are supposed to close any files open by this user */ if ((vuser != 0) && (lp_security() != SEC_SHARE)) { - int i; - for (i=0;ivuid == vuid) && fsp->open) { - if(!fsp->is_directory) - close_file(i,False); - else - close_directory(i); - } - } + file_close_user(vuid); } invalidate_vuid(vuid); @@ -1487,7 +1466,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring fname; int com; - int fnum = -1; int outsize = 0; int createmode; mode_t unixmode; @@ -1509,12 +1487,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,createmode); - fnum = find_free_file(); - if (fnum < 0) + fsp = find_free_file(); + if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - fsp = &Files[fnum]; - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) @@ -1522,7 +1498,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1538,7 +1514,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file in dos compatibility share mode. */ - open_file_shared(fnum,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, + open_file_shared(fsp,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, oplock_request, NULL, NULL); if (!fsp->open) @@ -1548,12 +1524,12 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fnum); + SSVAL(outbuf,smb_vwv0,fsp->fnum); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; @@ -1563,8 +1539,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG( 2, ( "new file %s\n", fname ) ); - DEBUG( 3, ( "mknew %s fd=%d fnum=%d dmode=%d umode=%o\n", - fname, fsp->fd_ptr->fd, fnum, createmode, (int)unixmode ) ); + DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", + fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) ); return(outsize); } @@ -1577,7 +1553,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring fname; pstring fname2; - int fnum = -1; int outsize = 0; int createmode; mode_t unixmode; @@ -1592,12 +1567,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,createmode); - fnum = find_free_file(); - if (fnum < 0) + fsp = find_free_file(); + if (fsp) return(ERROR(ERRSRV,ERRnofids)); - fsp = &Files[fnum]; - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) @@ -1605,7 +1578,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1613,7 +1586,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fnum,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, + open_file_shared(fsp,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, oplock_request, NULL, NULL); if (!fsp->open) @@ -1623,12 +1596,12 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } outsize = set_message(outbuf,1,2 + strlen(fname2),True); - SSVAL(outbuf,smb_vwv0,fnum); + SSVAL(outbuf,smb_vwv0,fsp->fnum); CVAL(smb_buf(outbuf),0) = 4; pstrcpy(smb_buf(outbuf) + 1,fname2); @@ -1640,8 +1613,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG( 2, ( "created temp file %s\n", fname2 ) ); - DEBUG( 3, ( "ctemp %s fd=%d fnum=%d dmode=%d umode=%o\n", - fname2, fsp->fd_ptr->fd, fnum, createmode, (int)unixmode ) ); + DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", + fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) ); return(outsize); } @@ -1777,7 +1750,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ****************************************************************************/ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { - int maxcount,mincount,fnum; + int maxcount,mincount; int nread = 0; uint32 startpos; char *header = outbuf; @@ -1800,7 +1773,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s return -1; } - fnum = GETFNUM(inbuf,smb_vwv0); + fsp = GETFSP(inbuf,smb_vwv0); startpos = IVAL(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); @@ -1810,23 +1783,18 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s maxcount = MIN(65535,maxcount); maxcount = MAX(mincount,maxcount); - if (!FNUM_OK(fnum,conn) || !Files[fnum].can_read) - { - DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); - _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); - return(-1); - } - else - { - fsp = &Files[fnum]; - - fd = fsp->fd_ptr->fd; - fname = fsp->fsp_name; + if (!FNUM_OK(fsp,conn) || !fsp->can_read) { + DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum)); + _smb_setlen(header,0); + transfer_file(0,Client,0,header,4,0); + return(-1); + } else { + fd = fsp->fd_ptr->fd; + fname = fsp->fsp_name; } - if (!is_locked(fnum,conn,maxcount,startpos, F_RDLCK)) + if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) { int size = fsp->size; int sizeneeded = startpos + maxcount; @@ -1846,7 +1814,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s nread = 0; DEBUG( 3, ( "readbraw fnum=%d start=%d max=%d min=%d nread=%d\n", - fnum, startpos, + fsp->fnum, startpos, maxcount, mincount, nread ) ); #if UNSAFE_READRAW @@ -1860,7 +1828,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #endif if ((nread-predict) > 0) - seek_file(fnum,startpos + predict); + seek_file(fsp,startpos + predict); ret = transfer_file(fd,Client,nread-predict,header,4+predict, startpos+predict); @@ -1871,7 +1839,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s fname,startpos,nread,ret)); #else - ret = read_file(fnum,header+4,startpos,nread); + ret = read_file(fsp,header+4,startpos,nread); if (ret < mincount) ret = 0; _smb_setlen(header,ret); @@ -1888,19 +1856,17 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s ****************************************************************************/ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) { - int fnum; int nread = -1; char *data; int outsize = 0; uint32 startpos, numtoread; int eclass; uint32 ecode; - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_READ(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); + CHECK_ERROR(fsp); numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -1909,10 +1875,10 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_si numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fnum, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) + if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); - nread = read_file(fnum,data,startpos,numtoread); + nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1923,7 +1889,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_si SSVAL(smb_buf(outbuf),1,nread); DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n", - fnum, numtoread, nread ) ); + fsp->fnum, numtoread, nread ) ); return(outsize); } @@ -1934,17 +1900,16 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_si ****************************************************************************/ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtoread,fnum; + int numtoread; int nread = 0; char *data; uint32 startpos; int outsize = 0; - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_READ(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); + CHECK_ERROR(fsp); numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -1953,11 +1918,11 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if (is_locked(fnum,conn,numtoread,startpos, F_RDLCK)) + if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); if (numtoread > 0) - nread = read_file(fnum,data,startpos,numtoread); + nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1969,7 +1934,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(smb_buf(outbuf),1,nread); DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", - fnum, numtoread, nread ) ); + fsp->fnum, numtoread, nread ) ); return(outsize); } @@ -1980,7 +1945,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, ****************************************************************************/ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - int fnum = GETFNUM(inbuf,smb_vwv2); + files_struct *fsp = GETFSP(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); @@ -1992,16 +1957,16 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (IS_IPC(conn)) return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); - CHECK_FNUM(fnum,conn); - CHECK_READ(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); + CHECK_ERROR(fsp); set_message(outbuf,12,0,True); data = smb_buf(outbuf); - if (is_locked(fnum,conn,smb_maxcnt,smb_offs, F_RDLCK)) + if (is_locked(fsp,conn,smb_maxcnt,smb_offs, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); - nread = read_file(fnum,data,smb_offs,smb_maxcnt); + nread = read_file(fsp,data,smb_offs,smb_maxcnt); ok = True; if (nread < 0) @@ -2012,9 +1977,9 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SSVAL(smb_buf(outbuf),-2,nread); DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n", - fnum, smb_mincnt, smb_maxcnt, nread ) ); + fsp->fnum, smb_mincnt, smb_maxcnt, nread ) ); - chain_fnum = fnum; + chain_fsp = fsp; return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2028,18 +1993,16 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s int nwritten=0; int total_written=0; int numtowrite=0; - int fnum; int outsize = 0; long startpos; char *data=NULL; BOOL write_through; int tcount; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); tcount = IVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv3); @@ -2059,17 +2022,17 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s CVAL(inbuf,smb_com) = SMBwritec; CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fnum,conn,tcount,startpos, F_WRLCK)) + if (is_locked(fsp,conn,tcount,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - if (seek_file(fnum,startpos) != startpos) + if (seek_file(fsp,startpos) != startpos) DEBUG(0,("couldn't seek to %ld in writebraw\n",startpos)); if (numtowrite>0) - nwritten = write_file(fnum,data,numtowrite); + nwritten = write_file(fsp,data,numtowrite); DEBUG(3,("writebraw1 fnum=%d start=%ld num=%d wrote=%d sync=%d\n", - fnum, startpos, numtowrite, nwritten, write_through)); + fsp->fnum, startpos, numtowrite, nwritten, write_through)); if (nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -2097,7 +2060,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s tcount,nwritten,numtowrite)); } - nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0, + nwritten = transfer_file(Client,fsp->fd_ptr->fd,numtowrite,NULL,0, startpos+nwritten); total_written += nwritten; @@ -2112,10 +2075,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s } if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fnum); + sync_file(conn,fsp); DEBUG(3,("writebraw2 fnum=%d start=%ld num=%d wrote=%d\n", - fnum, startpos, numtowrite, total_written)); + fsp->fnum, startpos, numtowrite, total_written)); /* we won't return a status if write through is not selected - this follows what WfWg does */ @@ -2131,28 +2094,26 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s ****************************************************************************/ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; int nwritten = -1; int outsize = 0; char *data; uint32 numtowrite,startpos; int eclass; uint32 ecode; - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fnum,conn,numtowrite,startpos, F_WRLCK)) + if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fnum,startpos); + seek_file(fsp,startpos); /* The special X/Open SMB protocol handling of zero length writes is *NOT* done for @@ -2160,15 +2121,15 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum if(numtowrite == 0) nwritten = 0; else - nwritten = write_file(fnum,data,numtowrite); + nwritten = write_file(fsp,data,numtowrite); if (lp_syncalways(SNUM(conn))) - sync_file(conn,fnum); + sync_file(conn,fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - if(!do_unlock(fnum, conn, numtowrite, startpos, &eclass, &ecode)) + if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode)) return(ERROR(eclass,ecode)); outsize = set_message(outbuf,1,0,True); @@ -2176,7 +2137,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum SSVAL(outbuf,smb_vwv0,nwritten); DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n", - fnum, numtowrite, nwritten ) ); + fsp->fnum, numtowrite, nwritten ) ); return(outsize); } @@ -2187,37 +2148,36 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum ****************************************************************************/ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize) { - int numtowrite,fnum; + int numtowrite; int nwritten = -1; int outsize = 0; int startpos; char *data; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fnum,conn,numtowrite,startpos, F_WRLCK)) + if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fnum,startpos); + seek_file(fsp,startpos); /* X/Open SMB protocol says that if smb_vwv1 is zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) - nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos); + nwritten = set_filelen(fsp->fd_ptr->fd, startpos); else - nwritten = write_file(fnum,data,numtowrite); + nwritten = write_file(fsp,data,numtowrite); if (lp_syncalways(SNUM(conn))) - sync_file(conn,fnum); + sync_file(conn,fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2232,7 +2192,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i } DEBUG(3,("write fnum=%d num=%d wrote=%d\n", - fnum, numtowrite, nwritten)); + fsp->fnum, numtowrite, nwritten)); return(outsize); } @@ -2243,7 +2203,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i ****************************************************************************/ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - int fnum = GETFNUM(inbuf,smb_vwv2); + files_struct *fsp = GETFSP(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_dsize = SVAL(inbuf,smb_vwv10); int smb_doff = SVAL(inbuf,smb_vwv11); @@ -2251,16 +2211,16 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng int nwritten = -1; char *data; - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); data = smb_base(inbuf) + smb_doff; - if (is_locked(fnum,conn,smb_dsize,smb_offs, F_WRLCK)) + if (is_locked(fsp,conn,smb_dsize,smb_offs, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fnum,smb_offs); + seek_file(fsp,smb_offs); /* X/Open SMB protocol says that, unlike SMBwrite if the length is zero then NO truncation is @@ -2269,7 +2229,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if(smb_dsize == 0) nwritten = 0; else - nwritten = write_file(fnum,data,smb_dsize); + nwritten = write_file(fsp,data,smb_dsize); if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2284,12 +2244,12 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng } DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", - fnum, smb_dsize, nwritten)); + fsp->fnum, smb_dsize, nwritten)); - chain_fnum = fnum; + chain_fsp = fsp; if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fnum); + sync_file(conn,fsp); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2300,17 +2260,14 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng ****************************************************************************/ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; uint32 startpos; int32 res= -1; int mode,umode; int outsize = 0; - files_struct *fsp; - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); mode = SVAL(inbuf,smb_vwv1) & 3; startpos = IVAL(inbuf,smb_vwv2); @@ -2324,8 +2281,6 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, umode = SEEK_SET; break; } - fsp = &Files[fnum]; - res = lseek(fsp->fd_ptr->fd,startpos,umode); fsp->pos = res; @@ -2333,7 +2288,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SIVALS(outbuf,smb_vwv0,res); DEBUG(3,("lseek fnum=%d ofs=%d mode=%d\n", - fnum, startpos, mode)); + fsp->fnum, startpos, mode)); return(outsize); } @@ -2344,28 +2299,21 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, ****************************************************************************/ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; int outsize = set_message(outbuf,0,0,True); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - fnum = GETFNUM(inbuf,smb_vwv0); - - if (fnum != 0xFFFF) { - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + if (fsp) { + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); } - if (fnum == 0xFFFF) { - int i; - for (i=0;iopen && fsp->is_directory)) + CHECK_FSP(fsp,conn); - fsp = &Files[fnum]; - - if(HAS_CACHED_ERROR(fnum)) { + if(HAS_CACHED_ERROR(fsp)) { eclass = fsp->wbmpx_ptr->wr_errclass; err = fsp->wbmpx_ptr->wr_error; } @@ -2423,8 +2368,8 @@ int reply_close(connection_struct *conn, * Special case - close NT SMB directory * handle. */ - DEBUG(3,("close directory fnum=%d\n", fnum)); - close_directory(fnum); + DEBUG(3,("close directory fnum=%d\n", fsp->fnum)); + close_directory(fsp); } else { /* * Close ordinary file. @@ -2435,10 +2380,10 @@ int reply_close(connection_struct *conn, set_filetime(conn, fsp->fsp_name,mtime); DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", - fsp->fd_ptr->fd, fnum, + fsp->fd_ptr->fd, fsp->fnum, conn->num_files_open)); - close_file(fnum,True); + close_file(fsp,True); } /* We have a cached error */ @@ -2455,37 +2400,36 @@ int reply_close(connection_struct *conn, int reply_writeclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite,fnum; + int numtowrite; int nwritten = -1; int outsize = 0; int startpos; char *data; time_t mtime; - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (is_locked(fnum,conn,numtowrite,startpos, F_WRLCK)) + if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fnum,startpos); + seek_file(fsp,startpos); - nwritten = write_file(fnum,data,numtowrite); + nwritten = write_file(fsp,data,numtowrite); - set_filetime(conn, Files[fnum].fsp_name,mtime); + set_filetime(conn, fsp->fsp_name,mtime); - close_file(fnum,True); + close_file(fsp,True); DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n", - fnum, numtowrite, nwritten, + fsp->fnum, numtowrite, nwritten, conn->num_files_open)); if (nwritten <= 0) @@ -2504,24 +2448,22 @@ int reply_writeclose(connection_struct *conn, int reply_lock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; int outsize = set_message(outbuf,0,0,True); uint32 count,offset; int eclass; uint32 ecode; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n", - Files[fnum].fd_ptr->fd, fnum, offset, count)); + fsp->fd_ptr->fd, fsp->fnum, offset, count)); - if (!do_lock(fnum, conn, count, offset, F_WRLCK, &eclass, &ecode)) + if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); return(outsize); @@ -2533,25 +2475,23 @@ int reply_lock(connection_struct *conn, ****************************************************************************/ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; int outsize = set_message(outbuf,0,0,True); uint32 count,offset; int eclass; uint32 ecode; - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); - if(!do_unlock(fnum, conn, count, offset, &eclass, &ecode)) + if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); DEBUG( 3, ( "unlock fd=%d fnum=%d ofs=%d cnt=%d\n", - Files[fnum].fd_ptr->fd, fnum, offset, count ) ); + fsp->fd_ptr->fd, fsp->fnum, offset, count ) ); return(outsize); } @@ -2624,7 +2564,6 @@ int reply_printopen(connection_struct *conn, { pstring fname; pstring fname2; - int fnum = -1; int outsize = 0; files_struct *fsp; @@ -2649,26 +2588,24 @@ int reply_printopen(connection_struct *conn, slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s); } - fnum = find_free_file(); - if (fnum < 0) + fsp = find_free_file(); + if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - - fsp = &Files[fnum]; pstrcpy(fname2,(char *)mktemp(fname)); if (!check_name(fname2,conn)) { - fsp->reserved = False; + file_free(fsp); return(ERROR(ERRDOS,ERRnoaccess)); } /* Open for exclusive use, write only. */ - open_file_shared(fnum,conn,fname2, + open_file_shared(fsp,conn,fname2, (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0), 0, NULL, NULL); if (!fsp->open) { - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2676,10 +2613,10 @@ int reply_printopen(connection_struct *conn, fsp->print_file = True; outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fnum); + SSVAL(outbuf,smb_vwv0,fsp->fnum); DEBUG(3,("openprint %s fd=%d fnum=%d\n", - fname2, fsp->fd_ptr->fd, fnum)); + fname2, fsp->fd_ptr->fd, fsp->fnum)); return(outsize); } @@ -2691,21 +2628,19 @@ int reply_printopen(connection_struct *conn, int reply_printclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; int outsize = set_message(outbuf,0,0,True); - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); if (!CAN_PRINT(conn)) return(ERROR(ERRDOS,ERRnoaccess)); DEBUG(3,("printclose fd=%d fnum=%d\n", - Files[fnum].fd_ptr->fd,fnum)); + fsp->fd_ptr->fd,fsp->fnum)); - close_file(fnum,True); + close_file(fsp,True); return(outsize); } @@ -2786,26 +2721,25 @@ int reply_printqueue(connection_struct *conn, ****************************************************************************/ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite,fnum; + int numtowrite; int outsize = set_message(outbuf,0,0,True); char *data; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); if (!CAN_PRINT(conn)) return(ERROR(ERRDOS,ERRnoaccess)); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); numtowrite = SVAL(smb_buf(inbuf),1); data = smb_buf(inbuf) + 3; - if (write_file(fnum,data,numtowrite) != numtowrite) + if (write_file(fsp,data,numtowrite) != numtowrite) return(UNIXERROR(ERRDOS,ERRnoaccess)); - DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fnum, numtowrite ) ); + DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); return(outsize); } @@ -3323,7 +3257,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int Access,action; struct stat st; int ret=0; - int fnum1,fnum2; + files_struct *fsp1,*fsp2; pstring dest; pstrcpy(dest,dest1); @@ -3339,43 +3273,43 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!file_exist(src,&st)) return(False); - fnum1 = find_free_file(); - if (fnum1<0) return(False); - open_file_shared(fnum1,conn,src,(DENY_NONE<<4), + fsp1 = find_free_file(); + if (!fsp1) return(False); + open_file_shared(fsp1,conn,src,(DENY_NONE<<4), 1,0,0,&Access,&action); - if (!Files[fnum1].open) { - Files[fnum1].reserved = False; + if (!fsp1->open) { + fsp1->reserved = False; return(False); } if (!target_is_directory && count) ofun = 1; - fnum2 = find_free_file(); - if (fnum2<0) { - close_file(fnum1,False); - return(False); + fsp2 = find_free_file(); + if (!fsp2) { + close_file(fsp1,False); + return(False); } - open_file_shared(fnum2,conn,dest,(DENY_NONE<<4)|1, + open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1, ofun,st.st_mode,0,&Access,&action); - if (!Files[fnum2].open) { - close_file(fnum1,False); - Files[fnum2].reserved = False; + if (!fsp2->open) { + close_file(fsp1,False); + fsp2->reserved = False; return(False); } if ((ofun&3) == 1) { - lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END); + lseek(fsp2->fd_ptr->fd,0,SEEK_END); } if (st.st_size) - ret = transfer_file(Files[fnum1].fd_ptr->fd, - Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); + ret = transfer_file(fsp1->fd_ptr->fd, + fsp2->fd_ptr->fd,st.st_size,NULL,0,0); - close_file(fnum1,False); - close_file(fnum2,False); + close_file(fsp1,False); + close_file(fsp2,False); return(ret == st.st_size); } @@ -3556,7 +3490,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ****************************************************************************/ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - int fnum = GETFNUM(inbuf,smb_vwv2); + files_struct *fsp = GETFSP(inbuf,smb_vwv2); unsigned char locktype = CVAL(inbuf,smb_vwv3); #if 0 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); @@ -3570,8 +3504,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, uint32 ecode=0, dummy2; int eclass=0, dummy1; - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); data = smb_buf(inbuf); @@ -3581,28 +3515,27 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { int token; - files_struct *fsp = &Files[fnum]; uint32 dev = fsp->fd_ptr->dev; uint32 inode = fsp->fd_ptr->inode; DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", - fnum)); + fsp->fnum)); /* * Make sure we have granted an oplock on this file. */ if(!fsp->granted_oplock) { DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ -no oplock granted on this file.\n", fnum)); +no oplock granted on this file.\n", fsp->fnum)); return ERROR(ERRDOS,ERRlock); } /* Remove the oplock flag from the sharemode. */ lock_share_entry(fsp->conn, dev, inode, &token); - if(remove_share_oplock( fnum, token)==False) { + if(remove_share_oplock(fsp, token)==False) { DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ dev = %x, inode = %x\n", - fnum, dev, inode)); + fsp->fnum, dev, inode)); unlock_share_entry(fsp->conn, dev, inode, token); } else { unlock_share_entry(fsp->conn, dev, inode, token); @@ -3628,7 +3561,7 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_ulocks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - if(!do_unlock(fnum,conn,count,offset,&eclass, &ecode)) + if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode)) return ERROR(eclass,ecode); } @@ -3642,7 +3575,7 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_locks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - if(!do_lock(fnum,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) #if 0 /* JRATEST - blocking lock code. */ if((ecode == ERRlock) && (lock_timeout != 0)) { @@ -3663,7 +3596,7 @@ dev = %x, inode = %x\n", for(; i >= 0; i--) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - do_unlock(fnum,conn,count,offset,&dummy1,&dummy2); + do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } return ERROR(eclass,ecode); } @@ -3671,9 +3604,9 @@ dev = %x, inode = %x\n", set_message(outbuf,2,0,True); DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", - fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); + fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); - chain_fnum = fnum; + chain_fsp = fsp; return chain_reply(inbuf,outbuf,length,bufsize); } @@ -3684,7 +3617,6 @@ dev = %x, inode = %x\n", ****************************************************************************/ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - int fnum; int nread = -1; int total_read; char *data; @@ -3693,6 +3625,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, int max_per_packet; int tcount; int pad; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); /* this function doesn't seem to work - disable by default */ if (!lp_readbmpx()) @@ -3700,11 +3633,9 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, outsize = set_message(outbuf,8,0,True); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,conn); - CHECK_READ(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); + CHECK_ERROR(fsp); startpos = IVAL(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); @@ -3719,14 +3650,14 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fnum,conn,maxcount,startpos, F_RDLCK)) + if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); do { int N = MIN(max_per_packet,tcount-total_read); - nread = read_file(fnum,data,startpos,N); + nread = read_file(fsp,data,startpos,N); if (nread <= 0) nread = 0; @@ -3755,18 +3686,17 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, ****************************************************************************/ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite,fnum; + int numtowrite; int nwritten = -1; int outsize = 0; uint32 startpos; int tcount, write_through, smb_doff; char *data; - - fnum = GETFNUM(inbuf,smb_vwv0); + files_struct *fsp = GETFSP(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); tcount = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv3); @@ -3780,14 +3710,14 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s not an SMBwritebmpx - set this up now so we don't forget */ CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fnum,conn,tcount,startpos,F_WRLCK)) + if (is_locked(fsp,conn,tcount,startpos,F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fnum,startpos); - nwritten = write_file(fnum,data,numtowrite); + seek_file(fsp,startpos); + nwritten = write_file(fsp,data,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fnum); + sync_file(conn,fsp); if(nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -3799,8 +3729,8 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if(tcount > nwritten) { write_bmpx_struct *wbms; - if(Files[fnum].wbmpx_ptr != NULL) - wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */ + if(fsp->wbmpx_ptr != NULL) + wbms = fsp->wbmpx_ptr; /* Use an existing struct */ else wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); if(!wbms) @@ -3813,7 +3743,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s wbms->wr_total_written = nwritten; wbms->wr_errclass = 0; wbms->wr_error = 0; - Files[fnum].wbmpx_ptr = wbms; + fsp->wbmpx_ptr = wbms; } /* We are returning successfully, set the message type back to @@ -3825,7 +3755,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n", - fnum, numtowrite, nwritten ) ); + fsp->fnum, numtowrite, nwritten ) ); if (write_through && tcount==nwritten) { /* we need to send both a primary and a secondary response */ @@ -3847,18 +3777,18 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s ****************************************************************************/ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite,fnum; + int numtowrite; int nwritten = -1; int outsize = 0; int32 startpos; int tcount, write_through, smb_doff; char *data; write_bmpx_struct *wbms; - BOOL send_response = False; - - fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,conn); - CHECK_WRITE(fnum); + BOOL send_response = False; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); + + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); tcount = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -3872,7 +3802,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz /* This fd should have an auxiliary struct attached, check that it does */ - wbms = Files[fnum].wbmpx_ptr; + wbms = fsp->wbmpx_ptr; if(!wbms) return(-1); /* If write through is set we can return errors, else we must @@ -3883,18 +3813,18 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz if(wbms->wr_discard) return -1; /* Just discard the packet */ - seek_file(fnum,startpos); - nwritten = write_file(fnum,data,numtowrite); + seek_file(fsp,startpos); + nwritten = write_file(fsp,data,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fnum); + sync_file(conn,fsp); if (nwritten < numtowrite) { if(write_through) { /* We are returning an error - we can delete the aux struct */ if (wbms) free((char *)wbms); - Files[fnum].wbmpx_ptr = NULL; + fsp->wbmpx_ptr = NULL; return(ERROR(ERRHRD,ERRdiskfull)); } return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); @@ -3912,7 +3842,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz } free((char *)wbms); - Files[fnum].wbmpx_ptr = NULL; + fsp->wbmpx_ptr = NULL; } if(send_response) @@ -3927,16 +3857,14 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz ****************************************************************************/ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; struct utimbuf unix_times; int outsize = 0; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); outsize = set_message(outbuf,0,0,True); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); /* Convert the DOS times into unix times. Ignore create time as UNIX can't set this. @@ -3954,7 +3882,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si /* Ignore request */ if( DEBUGLVL( 3 ) ) { - dbgtext( "reply_setattrE fnum=%d ", fnum); + dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); } return(outsize); @@ -3966,11 +3894,11 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si } /* Set the date on this file */ - if(file_utime(conn, Files[fnum].fsp_name, &unix_times)) + if(file_utime(conn, fsp->fsp_name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", - fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); + fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); return(outsize); } @@ -3981,23 +3909,21 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si ****************************************************************************/ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int fnum; struct stat sbuf; int outsize = 0; int mode; + files_struct *fsp = GETFSP(inbuf,smb_vwv0); outsize = set_message(outbuf,11,0,True); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); /* Do an fstat on this file */ - if(fstat(Files[fnum].fd_ptr->fd, &sbuf)) + if(fstat(fsp->fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - mode = dos_mode(conn,Files[fnum].fsp_name,&sbuf); + mode = dos_mode(conn,fsp->fsp_name,&sbuf); /* Convert the times into dos times. Set create date to be last modify date as UNIX doesn't save @@ -4017,7 +3943,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si } SSVAL(outbuf,smb_vwv10, mode); - DEBUG( 3, ( "reply_getattrE fnum=%d\n", fnum)); + DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum)); return(outsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ba93ceaa16..8b656ab264 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -66,14 +66,6 @@ extern int dcelogin_atmost_once; extern DOM_SID global_machine_sid; static connection_struct Connections[MAX_CONNECTIONS]; -files_struct Files[MAX_FNUMS]; - -/* - * Indirection for file fd's. Needed as POSIX locking - * is based on file/process, not fd/process. - */ -file_fd_struct FileFd[MAX_OPEN_FILES]; -int max_file_fd_used = 0; extern int Protocol; @@ -89,8 +81,8 @@ int max_send = BUFFER_SIZE; */ int max_recv = BUFFER_SIZE; -/* a fnum to use when chaining */ -int chain_fnum = -1; +/* a fsp to use when chaining */ +files_struct *chain_fsp = NULL; /* number of open connections */ static int num_connections_open = 0; @@ -807,7 +799,7 @@ static int fd_attempt_open(char *fname, int flags, int mode) Cache a uid_t currently with this file open. This is an optimization only used when multiple sessionsetup's have been done to one smbd. ****************************************************************************/ -static void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) +void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) { if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) return; @@ -844,67 +836,6 @@ static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) return False; } -/**************************************************************************** -fd support routines - attempt to find an already open file by dev -and inode - increments the ref_count of the returned file_fd_struct *. -****************************************************************************/ -static file_fd_struct *fd_get_already_open(struct stat *sbuf) -{ - int i; - file_fd_struct *fd_ptr; - - if(sbuf == 0) - return 0; - - for(i = 0; i <= max_file_fd_used; i++) { - fd_ptr = &FileFd[i]; - if((fd_ptr->ref_count > 0) && - (((uint32)sbuf->st_dev) == fd_ptr->dev) && - (((uint32)sbuf->st_ino) == fd_ptr->inode)) { - fd_ptr->ref_count++; - DEBUG(3, - ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n", - i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count)); - return fd_ptr; - } - } - return 0; -} - -/**************************************************************************** -fd support routines - attempt to find a empty slot in the FileFd array. -Increments the ref_count of the returned entry. -****************************************************************************/ -static file_fd_struct *fd_get_new(void) -{ - extern struct current_user current_user; - int i; - file_fd_struct *fd_ptr; - - for(i = 0; i < MAX_OPEN_FILES; i++) { - fd_ptr = &FileFd[i]; - if(fd_ptr->ref_count == 0) { - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_ptr->uid_cache_count = 0; - fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); - fd_ptr->ref_count++; - /* Increment max used counter if neccessary, cuts down - on search time when re-using */ - if(i > max_file_fd_used) - max_file_fd_used = i; - DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n", - i, fd_ptr->dev, fd_ptr->inode)); - return fd_ptr; - } - } - DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\n")); - return 0; -} /**************************************************************************** fd support routines - attempt to re-open an already open fd as O_RDWR. @@ -934,8 +865,7 @@ static int fd_attempt_close(file_fd_struct *fd_ptr) { extern struct current_user current_user; - DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", - fd_ptr - &FileFd[0], + DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, fd_ptr->real_open_flags, fd_ptr->ref_count)); @@ -1034,14 +964,13 @@ static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) /**************************************************************************** open a file ****************************************************************************/ -static void open_file(int fnum,connection_struct *conn, +static void open_file(files_struct *fsp,connection_struct *conn, char *fname1,int flags,int mode, struct stat *sbuf) { extern struct current_user current_user; pstring fname; struct stat statbuf; file_fd_struct *fd_ptr; - files_struct *fsp = &Files[fnum]; int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); fsp->open = False; @@ -1296,13 +1225,13 @@ static void open_file(int fnum,connection_struct *conn, */ if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { DEBUG(3,("Writing postscript line\n")); - write_file(fnum,"%!\n",3); + write_file(fsp,"%!\n",3); } - DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", + DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", *sesssetup_user ? sesssetup_user : conn->user,fname, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), - conn->num_files_open,fnum)); + conn->num_files_open)); } @@ -1325,28 +1254,28 @@ static void open_file(int fnum,connection_struct *conn, /******************************************************************* sync a file ********************************************************************/ -void sync_file(connection_struct *conn, int fnum) +void sync_file(connection_struct *conn, files_struct *fsp) { #ifdef HAVE_FSYNC if(lp_strict_sync(SNUM(conn))) - fsync(Files[fnum].fd_ptr->fd); + fsync(fsp->fd_ptr->fd); #endif } /**************************************************************************** run a file if it is a magic script ****************************************************************************/ -static void check_magic(int fnum,connection_struct *conn) +static void check_magic(files_struct *fsp,connection_struct *conn) { if (!*lp_magicscript(SNUM(conn))) return; - DEBUG(5,("checking magic for %s\n",Files[fnum].fsp_name)); + DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); { char *p; - if (!(p = strrchr(Files[fnum].fsp_name,'/'))) - p = Files[fnum].fsp_name; + if (!(p = strrchr(fsp->fsp_name,'/'))) + p = fsp->fsp_name; else p++; @@ -1358,7 +1287,7 @@ static void check_magic(int fnum,connection_struct *conn) int ret; pstring magic_output; pstring fname; - pstrcpy(fname,Files[fnum].fsp_name); + pstrcpy(fname,fsp->fsp_name); if (*lp_magicoutput(SNUM(conn))) pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); @@ -1379,7 +1308,7 @@ static void close_filestruct(files_struct *fsp) { connection_struct *conn = fsp->conn; - fsp->reserved = False; + file_free(fsp); fsp->open = False; fsp->is_directory = False; @@ -1405,69 +1334,66 @@ static void close_filestruct(files_struct *fsp) the closing of the connection. In the latter case printing and magic scripts are not run. ****************************************************************************/ -void close_file(int fnum, BOOL normal_close) +void close_file(files_struct *fsp, BOOL normal_close) { - files_struct *fs_p = &Files[fnum]; - uint32 dev = fs_p->fd_ptr->dev; - uint32 inode = fs_p->fd_ptr->inode; + uint32 dev = fsp->fd_ptr->dev; + uint32 inode = fsp->fd_ptr->inode; int token; - connection_struct *conn = fs_p->conn; + connection_struct *conn = fsp->conn; - close_filestruct(fs_p); + close_filestruct(fsp); #if USE_READ_PREDICTION - invalidate_read_prediction(fs_p->fd_ptr->fd); + invalidate_read_prediction(fsp->fd_ptr->fd); #endif if (lp_share_modes(SNUM(conn))) { lock_share_entry(conn, dev, inode, &token); - del_share_mode(token, fnum); + del_share_mode(token, fsp); } - fd_attempt_close(fs_p->fd_ptr); + fd_attempt_close(fsp->fd_ptr); if (lp_share_modes(SNUM(conn))) unlock_share_entry(conn, dev, inode, token); /* NT uses smbclose to start a print - weird */ - if (normal_close && fs_p->print_file) - print_file(conn, fs_p); + if (normal_close && fsp->print_file) + print_file(conn, fsp); /* check for magic scripts */ if (normal_close) { - check_magic(fnum,conn); + check_magic(fsp,conn); } - if(fs_p->granted_oplock == True) + if(fsp->granted_oplock == True) global_oplocks_open--; - fs_p->sent_oplock_break = False; + fsp->sent_oplock_break = False; DEBUG(2,("%s closed file %s (numopen=%d)\n", - conn->user,fs_p->fsp_name, + conn->user,fsp->fsp_name, conn->num_files_open)); - if (fs_p->fsp_name) { - string_free(&fs_p->fsp_name); + if (fsp->fsp_name) { + string_free(&fsp->fsp_name); } - /* we will catch bugs faster by zeroing this structure */ - memset(fs_p, 0, sizeof(*fs_p)); + file_free(fsp); } /**************************************************************************** Close a directory opened by an NT SMB call. ****************************************************************************/ -void close_directory(int fnum) +void close_directory(files_struct *fsp) { - files_struct *fsp = &Files[fnum]; /* TODO - walk the list of pending change notify requests and free - any pertaining to this fnum. */ + any pertaining to this fsp. */ - remove_pending_change_notify_requests_by_fid(fnum); + remove_pending_change_notify_requests_by_fid(fsp); /* * Do the code common to files and directories. @@ -1477,18 +1403,16 @@ void close_directory(int fnum) if (fsp->fsp_name) string_free(&fsp->fsp_name); - /* we will catch bugs faster by zeroing this structure */ - memset(fsp, 0, sizeof(*fsp)); + file_free(fsp); } /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ -int open_directory(int fnum,connection_struct *conn, +int open_directory(files_struct *fsp,connection_struct *conn, char *fname, int smb_ofun, int unixmode, int *action) { extern struct current_user current_user; - files_struct *fsp = &Files[fnum]; struct stat st; if (smb_ofun & 0x10) { @@ -1521,8 +1445,8 @@ int open_directory(int fnum,connection_struct *conn, *action = FILE_WAS_OPENED; } - DEBUG(5,("open_directory: opening directory %s, fnum = %d\n", - fname, fnum )); + DEBUG(5,("open_directory: opening directory %s\n", + fname)); /* * Setup the files_struct for it. @@ -1745,19 +1669,17 @@ free_and_exit: Helper for open_file_shared. Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(int fnum, connection_struct *conn, int token, +static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, BOOL *share_locked) { - files_struct *fsp = &Files[fnum]; - if (fsp->can_write){ - if (is_locked(fnum,conn,0x3FFFFFFF,0,F_WRLCK)){ + if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){ /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(conn))) unlock_share_entry( conn, fsp->fd_ptr->dev, fsp->fd_ptr->inode, token); - close_file(fnum,False); + close_file(fsp,False); /* Share mode no longer locked. */ *share_locked = False; errno = EACCES; @@ -1813,10 +1735,9 @@ int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, /**************************************************************************** open a file with a share mode ****************************************************************************/ -void open_file_shared(int fnum,connection_struct *conn,char *fname,int share_mode,int ofun, +void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, int mode,int oplock_request, int *Access,int *action) { - files_struct *fs_p = &Files[fnum]; int flags=0; int flags2=0; int deny_mode = (share_mode>>4)&7; @@ -1829,8 +1750,8 @@ void open_file_shared(int fnum,connection_struct *conn,char *fname,int share_mod uint32 inode = 0; int num_share_modes = 0; - fs_p->open = False; - fs_p->fd_ptr = 0; + fsp->open = False; + fsp->fd_ptr = 0; /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) @@ -1992,22 +1913,22 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,mode)); - open_file(fnum,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); - if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen) + open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); + if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen) { flags = O_RDONLY; - open_file(fnum,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); + open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); } - if (fs_p->open) + if (fsp->open) { int open_mode=0; if((share_locked == False) && lp_share_modes(SNUM(conn))) { /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; + dev = fsp->fd_ptr->dev; + inode = fsp->fd_ptr->inode; lock_share_entry(conn, dev, inode, &token); share_locked = True; } @@ -2025,7 +1946,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); break; } - fs_p->share_mode = (deny_mode<<4) | open_mode; + fsp->share_mode = (deny_mode<<4) | open_mode; if (Access) (*Access) = open_mode; @@ -2051,8 +1972,8 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && !IS_VETO_OPLOCK_PATH(conn,fname)) { - fs_p->granted_oplock = True; - fs_p->sent_oplock_break = False; + fsp->granted_oplock = True; + fsp->sent_oplock_break = False; global_oplocks_open++; port = oplock_port; @@ -2065,11 +1986,11 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); port = 0; oplock_request = 0; } - set_share_mode(token, fnum, port, oplock_request); + set_share_mode(token, fsp, port, oplock_request); } if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fnum,conn,token,&share_locked); + truncate_unless_locked(fsp,conn,token,&share_locked); } if (share_locked && lp_share_modes(SNUM(conn))) @@ -2079,10 +2000,9 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); /**************************************************************************** seek a file. Try to avoid the seek if possible ****************************************************************************/ -int seek_file(int fnum,uint32 pos) +int seek_file(files_struct *fsp,uint32 pos) { uint32 offset = 0; - files_struct *fsp = &Files[fnum]; if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; @@ -2094,10 +2014,9 @@ int seek_file(int fnum,uint32 pos) /**************************************************************************** read from a file ****************************************************************************/ -int read_file(int fnum,char *data,uint32 pos,int n) +int read_file(files_struct *fsp,char *data,uint32 pos,int n) { int ret=0,readret; - files_struct *fsp = &Files[fnum]; #if USE_READ_PREDICTION if (!fsp->can_write) @@ -2129,7 +2048,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) if (n <= 0) return(ret); - if (seek_file(fnum,pos) != pos) + if (seek_file(fsp,pos) != pos) { DEBUG(3,("Failed to seek to %d\n",pos)); return(ret); @@ -2147,9 +2066,8 @@ int read_file(int fnum,char *data,uint32 pos,int n) /**************************************************************************** write to a file ****************************************************************************/ -int write_file(int fnum,char *data,int n) +int write_file(files_struct *fsp,char *data,int n) { - files_struct *fsp = &Files[fnum]; if (!fsp->can_write) { errno = EPERM; @@ -2318,16 +2236,16 @@ int find_service(char *service) /**************************************************************************** create an error packet from a cached error. ****************************************************************************/ -int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line) +int cached_error_packet(char *inbuf,char *outbuf,files_struct *fsp,int line) { - write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr; + write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; int32 eclass = wbmpx->wr_errclass; int32 err = wbmpx->wr_error; /* We can now delete the auxiliary struct */ free((char *)wbmpx); - Files[fnum].wbmpx_ptr = NULL; + fsp->wbmpx_ptr = NULL; return error_packet(inbuf,outbuf,eclass,err,line); } @@ -2890,7 +2808,6 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) char *inbuf = NULL; char *outbuf = NULL; files_struct *fsp = NULL; - int fnum; time_t start_time; BOOL shutdown_server = False; connection_struct *saved_conn; @@ -2906,18 +2823,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) /* We need to search the file open table for the entry containing this dev and inode, and ensure we have an oplock on it. */ - for( fnum = 0; fnum < MAX_FNUMS; fnum++) - { - if(OPEN_FNUM(fnum)) - { - if((Files[fnum].fd_ptr->dev == dev) && (Files[fnum].fd_ptr->inode == inode) && - (Files[fnum].open_time.tv_sec == tval->tv_sec) && - (Files[fnum].open_time.tv_usec == tval->tv_usec)) { - fsp = &Files[fnum]; - break; - } - } - } + fsp = file_find_dit(dev, inode, tval); if(fsp == NULL) { @@ -2925,7 +2831,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) if( DEBUGLVL( 0 ) ) { dbgtext( "oplock_break: cannot find open file with " ); - dbgtext( "dev = %x, inode = %x (fnum = %d) ", dev, inode, fnum ); + dbgtext( "dev = %x, inode = %x ", dev, inode); dbgtext( "allowing break to succeed.\n" ); } return True; @@ -2944,8 +2850,8 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { if( DEBUGLVL( 0 ) ) { - dbgtext( "oplock_break: file %s (fnum = %d, ", fsp->fsp_name, fnum ); - dbgtext( "dev = %x, inode = %x) has no oplock.\n", dev, inode ); + dbgtext( "oplock_break: file %s ", fsp->fsp_name ); + dbgtext( "(dev = %x, inode = %x) has no oplock.\n", dev, inode ); dbgtext( "Allowing break to succeed regardless.\n" ); } return True; @@ -2957,8 +2863,8 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) if( DEBUGLVL( 0 ) ) { dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); - dbgtext( "file %s (fnum = %d, ", fsp->fsp_name, fnum ); - dbgtext( "dev = %x, inode = %x)\n", dev, inode ); + dbgtext( "file %s ", fsp->fsp_name); + dbgtext( "(dev = %x, inode = %x)\n", dev, inode ); } /* We have to fail the open here as we cannot send another oplock break on @@ -3000,7 +2906,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) SSVAL(outbuf,smb_uid,0); SSVAL(outbuf,smb_mid,0xFFFF); SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fnum); + SSVAL(outbuf,smb_vwv2,fsp->fnum); SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); /* Change this when we have level II oplocks. */ SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE); @@ -3029,7 +2935,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) GetWd(saved_dir); unbecome_user(); - while(OPEN_FNUM(fnum) && fsp->granted_oplock) + while(OPEN_FSP(fsp) && fsp->granted_oplock) { if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) { @@ -3048,7 +2954,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) OPLOCK_BREAK_TIMEOUT ) ); DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) ); - DEBUGADD( 0, ( "(fnum = %d, dev = %x, inode = %x).\n", fnum, dev, inode)); + DEBUGADD( 0, ( "(dev = %x, inode = %x).\n", dev, inode)); shutdown_server = True; break; } @@ -3075,7 +2981,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) dbgtext( "oplock_break: no break received from client " ); dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); - dbgtext( "(fnum = %d, dev = %x, inode = %x).\n", fnum, dev, inode ); + dbgtext( "(dev = %x, inode = %x).\n", dev, inode ); } shutdown_server = True; break; @@ -3118,7 +3024,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) exit_server("oplock break failure"); } - if(OPEN_FNUM(fnum)) + if(OPEN_FSP(fsp)) { /* The lockingX reply will have removed the oplock flag from the sharemode. */ @@ -3139,7 +3045,7 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) if( DEBUGLVL( 3 ) ) { dbgtext( "oplock_break: returning success for " ); - dbgtext( "fnum = %d, dev = %x, inode = %x.\n", fnum, dev, inode ); + dbgtext( "dev = %x, inode = %x.\n", dev, inode ); dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); } @@ -3791,8 +3697,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int Used as a last ditch attempt to free a space in the file table when we have run out. ****************************************************************************/ - -static BOOL attempt_close_oplocked_file(files_struct *fsp) +BOOL attempt_close_oplocked_file(files_struct *fsp) { DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); @@ -3810,75 +3715,6 @@ static BOOL attempt_close_oplocked_file(files_struct *fsp) return False; } -/**************************************************************************** - find first available file slot -****************************************************************************/ -int find_free_file(void ) -{ - int i; - static int first_file; - - /* we want to give out file handles differently on each new - connection because of a common bug in MS clients where they try to - reuse a file descriptor from an earlier smb connection. This code - increases the chance that the errant client will get an error rather - than causing corruption */ - if (first_file == 0) { - first_file = (getpid() ^ (int)time(NULL)) % MAX_FNUMS; - if (first_file == 0) first_file = 1; - } - - if (first_file >= MAX_FNUMS) - first_file = 1; - - for (i=first_file;iref_count = 0; - fd_ptr->dev = (int32)-1; - fd_ptr->inode = (int32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - } + file_init(); /* for RPC pipes */ init_rpc_pipe_hnd(); @@ -5297,25 +5100,6 @@ static void usage(char *pname) DEBUG( 1, ( "smbd version %s started.\n", VERSION ) ); DEBUGADD( 1, ( "Copyright Andrew Tridgell 1992-1997\n" ) ); -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_NOFILE - { - struct rlimit rlp; - getrlimit(RLIMIT_NOFILE, &rlp); - /* - * Set the fd limit to be MAX_OPEN_FILES + 10 to account for the - * extra fd we need to read directories, as well as the log files - * and standard handles etc. - */ - rlp.rlim_cur = (MAX_OPEN_FILES+10>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES+10; - setrlimit(RLIMIT_NOFILE, &rlp); - getrlimit(RLIMIT_NOFILE, &rlp); - DEBUG(3,("Maximum number of open files per session is %d\n",(int)rlp.rlim_cur)); - } -#endif -#endif - - DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 992d8cd616..67db3aeb2a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -26,13 +26,13 @@ extern int DEBUGLEVEL; extern int Protocol; -extern files_struct Files[]; extern BOOL case_sensitive; extern int Client; extern int oplock_sock; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; +extern files_struct *chain_fsp; /**************************************************************************** Send the required number of replies back. @@ -200,7 +200,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int16 namelen = strlen(pname)+1; pstring fname; - int fnum = -1; int unixmode; int size=0,fmode=0,mtime=0,rmode; int32 inode = 0; @@ -218,12 +217,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unix_convert(fname,conn,0,&bad_path); - fnum = find_free_file(); - if (fnum < 0) + fsp = find_free_file(); + if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - fsp = &Files[fnum]; - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) @@ -231,13 +228,13 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } unixmode = unix_mode(conn,open_attr | aARCH); - open_file_shared(fnum,conn,fname,open_mode,open_ofun,unixmode, + open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp->open) @@ -247,12 +244,12 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -261,7 +258,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { - close_file(fnum,False); + close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -271,7 +268,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(ERROR(ERRDOS,ERRnomem)); bzero(params,28); - SSVAL(params,0,fnum); + SSVAL(params,0,fsp->fnum); SSVAL(params,2,fmode); put_dos_date2(params,4, mtime); SIVAL(params,8, size); @@ -1212,18 +1209,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, BOOL bad_path = False; if (tran_call == TRANSACT2_QFILEINFO) { - int16 fnum = SVALS(params,0); + files_struct *fsp = GETFSP(params,0); info_level = SVAL(params,2); - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); - fname = Files[fnum].fsp_name; - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); + fname = fsp->fsp_name; + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR); + pos = lseek(fsp->fd_ptr->fd,0,SEEK_CUR); } else { /* qpathinfo */ info_level = SVAL(params,0); @@ -1437,14 +1434,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(ERROR(ERRSRV,ERRaccess)); if (tran_call == TRANSACT2_SETFILEINFO) { - int16 fnum = SVALS(params,0); + files_struct *fsp = GETFSP(params,0); info_level = SVAL(params,2); - CHECK_FNUM(fnum,conn); - CHECK_ERROR(fnum); + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); - fname = Files[fnum].fsp_name; - fd = Files[fnum].fd_ptr->fd; + fname = fsp->fsp_name; + fd = fsp->fd_ptr->fd; if(fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); -- cgit From 6a6e8958ad86d61395d9ad47a0c2bef732d07b13 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Aug 1998 02:32:55 +0000 Subject: changed find_free_file() to file_new(). (This used to be commit 3daee29636dcb2d99a0e7c08179a098befae00dc) --- source3/smbd/files.c | 2 +- source3/smbd/nttrans.c | 4 ++-- source3/smbd/reply.c | 14 +++++++------- source3/smbd/trans2.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index a37d190f01..04aff67a15 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -41,7 +41,7 @@ static int max_file_fd_used = 0; /**************************************************************************** find first available file slot ****************************************************************************/ -files_struct *find_free_file(void ) +files_struct *file_new(void ) { int i; static int first_file; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d396b05a62..0e76bf30b2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -466,7 +466,7 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_convert(fname,conn,0,&bad_path); - fsp = find_free_file(); + fsp = file_new(); if (!fsp) { restore_case_semantics(file_attributes); return(ERROR(ERRSRV,ERRnofids)); @@ -743,7 +743,7 @@ static int call_nt_transact_create(connection_struct *conn, unix_convert(fname,conn,0,&bad_path); - fsp = find_free_file(); + fsp = file_new(); if (!fsp) { restore_case_semantics(file_attributes); return(ERROR(ERRSRV,ERRnofids)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e9a25ea79a..340602d3a5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1243,7 +1243,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,conn,0,&bad_path); - fsp = find_free_file(); + fsp = file_new(); if (!fsp) return(ERROR(ERRSRV,ERRnofids)); @@ -1344,7 +1344,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt pstrcpy(fname,smb_buf(inbuf)); unix_convert(fname,conn,0,&bad_path); - fsp = find_free_file(); + fsp = file_new(); if (!fsp) return(ERROR(ERRSRV,ERRnofids)); @@ -1487,7 +1487,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,createmode); - fsp = find_free_file(); + fsp = file_new(); if (!fsp) return(ERROR(ERRSRV,ERRnofids)); @@ -1567,7 +1567,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,createmode); - fsp = find_free_file(); + fsp = file_new(); if (fsp) return(ERROR(ERRSRV,ERRnofids)); @@ -2588,7 +2588,7 @@ int reply_printopen(connection_struct *conn, slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s); } - fsp = find_free_file(); + fsp = file_new(); if (!fsp) return(ERROR(ERRSRV,ERRnofids)); @@ -3273,7 +3273,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!file_exist(src,&st)) return(False); - fsp1 = find_free_file(); + fsp1 = file_new(); if (!fsp1) return(False); open_file_shared(fsp1,conn,src,(DENY_NONE<<4), 1,0,0,&Access,&action); @@ -3286,7 +3286,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!target_is_directory && count) ofun = 1; - fsp2 = find_free_file(); + fsp2 = file_new(); if (!fsp2) { close_file(fsp1,False); return(False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 67db3aeb2a..72ad7ec12b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -217,7 +217,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unix_convert(fname,conn,0,&bad_path); - fsp = find_free_file(); + fsp = file_new(); if (!fsp) return(ERROR(ERRSRV,ERRnofids)); -- cgit From a7acf10566af549eb71e7a421397c8073d55e0f6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Aug 1998 03:04:06 +0000 Subject: server.c: fixed a bug in close_file() with the new files.c handling code bitmap.c: added bitmap hanlding code in preparation for increasing the default max open files to several thousand (This used to be commit f573a65b67e7a57586fec57845598e49b157ee0a) --- source3/smbd/server.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8b656ab264..e9aa2d0278 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1308,7 +1308,7 @@ static void close_filestruct(files_struct *fsp) { connection_struct *conn = fsp->conn; - file_free(fsp); + fsp->reserved = False; fsp->open = False; fsp->is_directory = False; @@ -1388,22 +1388,21 @@ void close_file(files_struct *fsp, BOOL normal_close) void close_directory(files_struct *fsp) { + /* TODO - walk the list of pending + change notify requests and free + any pertaining to this fsp. */ - /* TODO - walk the list of pending - change notify requests and free - any pertaining to this fsp. */ + remove_pending_change_notify_requests_by_fid(fsp); - remove_pending_change_notify_requests_by_fid(fsp); - - /* - * Do the code common to files and directories. - */ - close_filestruct(fsp); - - if (fsp->fsp_name) - string_free(&fsp->fsp_name); - - file_free(fsp); + /* + * Do the code common to files and directories. + */ + close_filestruct(fsp); + + if (fsp->fsp_name) + string_free(&fsp->fsp_name); + + file_free(fsp); } /**************************************************************************** -- cgit From 739d0b1ddc58bbb792c3eebe8c545602a4fae438 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Aug 1998 04:08:47 +0000 Subject: got rid of the Files[] array completely (previously I'd just made it private to files.c) It now is a doubly linked list with a bitmap for allocated file numbers. Similarly for the fd_ptr code. I also changed the default maximum number of open files to 4096. The static cost is 1 bit per file. It all seems to work, and it passes the "does Sue scream" test, but if you see weird behaviour then please investigate. With the volume of new code that has gone in there are bound to be one or two bugs lurking. note that you must do a "make clean" before building this as many data structures have changed in size. (This used to be commit 79755ce97004b787d7e83a8d18fc4c7c003b7231) --- source3/smbd/files.c | 353 +++++++++++++++++++++++++++++-------------------- source3/smbd/nttrans.c | 2 +- source3/smbd/reply.c | 4 +- source3/smbd/server.c | 4 +- 4 files changed, 212 insertions(+), 151 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 04aff67a15..66fbaebeb0 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -23,20 +23,23 @@ extern int DEBUGLEVEL; -#define MAX_OPEN_FILES 100 +/* the only restriction is that this must be less than PIPE_HANDLE_OFFSET */ +#define MAX_FNUMS 4096 -#define MAX_FNUMS (MAX_OPEN_FILES+MAX_OPEN_DIRECTORIES) #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_FNUMS)) -static files_struct Files[MAX_FNUMS]; +static struct bitmap *file_bmap; +static struct bitmap *fd_bmap; + +static files_struct *Files; /* * Indirection for file fd's. Needed as POSIX locking * is based on file/process, not fd/process. */ -static file_fd_struct FileFd[MAX_OPEN_FILES]; -static int max_file_fd_used = 0; +static file_fd_struct *FileFd; +static int files_used, fd_ptr_used; /**************************************************************************** find first available file slot @@ -45,6 +48,7 @@ files_struct *file_new(void ) { int i; static int first_file; + files_struct *fsp; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to @@ -56,59 +60,55 @@ files_struct *file_new(void ) if (first_file == 0) first_file = 1; } - if (first_file >= MAX_FNUMS) + if (first_file >= MAX_FNUMS) { first_file = 1; + } - for (i=first_file;inext) { + if (attempt_close_oplocked_file(fsp)) { + return file_new(); + } } - /* returning a file handle of 0 is a bad idea - so we start at 1 */ - for (i=1;ifnum = i; + string_init(&fsp->fsp_name,""); + + bitmap_set(file_bmap, i); + files_used++; + + /* hook into the front of the list */ + if (!Files) { + Files = fsp; + } else { + Files->prev = fsp; + fsp->next = Files; + Files = fsp; + } + + DEBUG(5,("allocated file structure %d (%d used)\n", + i, files_used)); + + return fsp; } @@ -119,60 +119,74 @@ and inode - increments the ref_count of the returned file_fd_struct *. ****************************************************************************/ file_fd_struct *fd_get_already_open(struct stat *sbuf) { - int i; - file_fd_struct *fd_ptr; - - if(sbuf == 0) - return 0; - - for(i = 0; i <= max_file_fd_used; i++) { - fd_ptr = &FileFd[i]; - if((fd_ptr->ref_count > 0) && - (((uint32)sbuf->st_dev) == fd_ptr->dev) && - (((uint32)sbuf->st_ino) == fd_ptr->inode)) { - fd_ptr->ref_count++; - DEBUG(3, - ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n", - i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count)); - return fd_ptr; - } - } - return 0; + file_fd_struct *fd_ptr; + + if(!sbuf) return NULL; + + for (fd_ptr=FileFd;fd_ptr;fd_ptr=fd_ptr->next) { + if ((fd_ptr->ref_count > 0) && + (((uint32)sbuf->st_dev) == fd_ptr->dev) && + (((uint32)sbuf->st_ino) == fd_ptr->inode)) { + fd_ptr->ref_count++; + DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %x, ref_count = %d\n", + fd_ptr->dev, fd_ptr->inode, + fd_ptr->ref_count)); + return fd_ptr; + } + } + + return NULL; } + + /**************************************************************************** fd support routines - attempt to find a empty slot in the FileFd array. Increments the ref_count of the returned entry. ****************************************************************************/ file_fd_struct *fd_get_new(void) { - extern struct current_user current_user; - int i; - file_fd_struct *fd_ptr; - - for(i = 0; i < MAX_OPEN_FILES; i++) { - fd_ptr = &FileFd[i]; - if(fd_ptr->ref_count == 0) { - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_ptr->uid_cache_count = 0; - fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); - fd_ptr->ref_count++; - /* Increment max used counter if neccessary, cuts down - on search time when re-using */ - if(i > max_file_fd_used) - max_file_fd_used = i; - DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n", - i, fd_ptr->dev, fd_ptr->inode)); - return fd_ptr; - } - } - DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\n")); - return 0; + extern struct current_user current_user; + int i; + file_fd_struct *fd_ptr; + + i = bitmap_find(fd_bmap, 1); + if (i == -1) { + DEBUG(0,("ERROR! Out of file_fd structures\n")); + return NULL; + } + + fd_ptr = (file_fd_struct *)malloc(sizeof(*fd_ptr)); + if (!fd_ptr) return NULL; + + memset(fd_ptr, 0, sizeof(*fd_ptr)); + + fd_ptr->fdnum = i; + fd_ptr->dev = (uint32)-1; + fd_ptr->inode = (uint32)-1; + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; + fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + fd_ptr->ref_count++; + + bitmap_set(fd_bmap, i); + fd_ptr_used++; + + /* hook into the front of the list */ + if (!FileFd) { + FileFd = fd_ptr; + } else { + FileFd->prev = fd_ptr; + fd_ptr->next = FileFd; + FileFd = fd_ptr; + } + + DEBUG(5,("allocated fd_ptr structure %d (%d used)\n", + i, fd_ptr_used)); + + return fd_ptr; } @@ -181,14 +195,16 @@ close all open files for a connection ****************************************************************************/ void file_close_conn(connection_struct *conn) { - int i; - for (i=0;inext) { + if (fsp->conn == conn && fsp->open) { + if (fsp->is_directory) + close_directory(fsp); + else + close_file(fsp,False); + } + } } /**************************************************************************** @@ -196,10 +212,14 @@ initialise file structures ****************************************************************************/ void file_init(void) { - int i; + file_bmap = bitmap_allocate(MAX_FNUMS); + fd_bmap = bitmap_allocate(MAX_FNUMS); + + if (!file_bmap || !fd_bmap) { + exit_server("out of memory in file_init"); + } -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_NOFILE +#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)) { struct rlimit rlp; getrlimit(RLIMIT_NOFILE, &rlp); @@ -215,34 +235,23 @@ void file_init(void) (int)rlp.rlim_cur)); } #endif -#endif - - - - for (i=0;iref_count = 0; - fd_ptr->dev = (int32)-1; - fd_ptr->inode = (int32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - } } + /**************************************************************************** find a fsp given a fnum ****************************************************************************/ files_struct *file_fsp(int fnum) { + files_struct *fsp; + if (!VALID_FNUM(fnum)) return NULL; - return &Files[fnum]; + + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->fnum == fnum) return fsp; + } + + return NULL; } @@ -251,9 +260,9 @@ close files open by a specified vuid ****************************************************************************/ void file_close_user(int vuid) { - int i; - for (i=0;inext) { if ((fsp->vuid == vuid) && fsp->open) { if(!fsp->is_directory) close_file(fsp,False); @@ -269,9 +278,9 @@ find a fsp given a device, inode and timevalue ****************************************************************************/ files_struct *file_find_dit(int dev, int inode, struct timeval *tval) { - int i; - for (i=0;inext) { if (fsp->open && fsp->fd_ptr->dev == dev && fsp->fd_ptr->inode == inode && @@ -279,22 +288,21 @@ files_struct *file_find_dit(int dev, int inode, struct timeval *tval) fsp->open_time.tv_usec == tval->tv_usec) { return fsp; } - } + } + return NULL; } + /**************************************************************************** find a fsp that is open for printing ****************************************************************************/ files_struct *file_find_print(void) { - int i; + files_struct *fsp; - for (i=0;iopen && fsp->print_file) { - return fsp; - } + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->open && fsp->print_file) return fsp; } return NULL; } @@ -305,9 +313,9 @@ sync open files on a connection ****************************************************************************/ void file_sync_all(connection_struct *conn) { - int i; - for (i=0;inext) { if (fsp->open && conn == fsp->conn) { sync_file(conn,fsp); } @@ -315,7 +323,60 @@ void file_sync_all(connection_struct *conn) } +/**************************************************************************** +free up a fd_ptr +****************************************************************************/ +static void fd_ptr_free(file_fd_struct *fd_ptr) +{ + if (fd_ptr == FileFd) { + FileFd = fd_ptr->next; + if (FileFd) FileFd->prev = NULL; + } else { + fd_ptr->prev->next = fd_ptr->next; + if (fd_ptr->next) fd_ptr->next->prev = fd_ptr->prev; + } + + bitmap_clear(fd_bmap, fd_ptr->fdnum); + fd_ptr_used--; + + DEBUG(5,("freed fd_ptr structure %d (%d used)\n", + fd_ptr->fdnum, fd_ptr_used)); + + /* paranoia */ + memset(fd_ptr, 0, sizeof(*fd_ptr)); + + free(fd_ptr); +} + + +/**************************************************************************** +free up a fsp +****************************************************************************/ void file_free(files_struct *fsp) { + if (fsp == Files) { + Files = fsp->next; + if (Files) Files->prev = NULL; + } else { + fsp->prev->next = fsp->next; + if (fsp->next) fsp->next->prev = fsp->prev; + } + + string_free(&fsp->fsp_name); + + if (fsp->fd_ptr && fsp->fd_ptr->ref_count == 0) { + fd_ptr_free(fsp->fd_ptr); + } + + bitmap_clear(file_bmap, fsp->fnum); + files_used--; + + DEBUG(5,("freed files structure %d (%d used)\n", + fsp->fnum, files_used)); + + /* this is paranoia, just in case someone tries to reuse the + information */ memset(fsp, 0, sizeof(*fsp)); + + free(fsp); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0e76bf30b2..4778e3a66b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -754,7 +754,7 @@ static int call_nt_transact_create(connection_struct *conn, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - fsp->reserved = False; + file_free(fsp); restore_case_semantics(file_attributes); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 340602d3a5..e62c0bd576 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3279,7 +3279,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, 1,0,0,&Access,&action); if (!fsp1->open) { - fsp1->reserved = False; + file_free(fsp1); return(False); } @@ -3296,7 +3296,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!fsp2->open) { close_file(fsp1,False); - fsp2->reserved = False; + file_free(fsp2); return(False); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e9aa2d0278..1ae402b902 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -885,8 +885,9 @@ static int fd_attempt_close(file_fd_struct *fd_ptr) fd_ptr->dev = (uint32)-1; fd_ptr->inode = (uint32)-1; fd_ptr->uid_cache_count = 0; - } else + } else { fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + } } return fd_ptr->ref_count; } @@ -1308,7 +1309,6 @@ static void close_filestruct(files_struct *fsp) { connection_struct *conn = fsp->conn; - fsp->reserved = False; fsp->open = False; fsp->is_directory = False; -- cgit From b590b27b45725993335c6c1f110bf1a9bb56513b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Aug 1998 06:20:18 +0000 Subject: - some tidying up in files.c - handle null fsp in DEBUG() at end of reply_ntcreate_and_X(). Jeremy, can you fix this properly? - get snum right in print queue code in ipc.c (it was broken by my connections_struct changes). (This used to be commit b3dd3785751db2d5d0a80ffac9c3df01c9909891) --- source3/smbd/files.c | 6 +++--- source3/smbd/ipc.c | 13 ++++++------- source3/smbd/nttrans.c | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 66fbaebeb0..8f1cefbbb6 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -223,9 +223,9 @@ void file_init(void) { struct rlimit rlp; getrlimit(RLIMIT_NOFILE, &rlp); - /* Set the fd limit to be MAX_OPEN_FILES + 10 to - * account for the extra fd we need to read - * directories, as well as the log files and standard + /* Set the fd limit to be MAX_FNUMS + 10 to + * account for the extra fd we need + * as well as the log files and standard * handles etc. */ rlp.rlim_cur = (MAX_FNUMS+10>rlp.rlim_max)? rlp.rlim_max:MAX_FNUMS+10; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ae225956a2..be7fb8d8e3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -833,20 +833,19 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, if (snum < 0 || !VALID_SNUM(snum)) return(False); - if (uLevel==52) - { - count = get_printerdrivernumber(snum); - DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); + if (uLevel==52) { + count = get_printerdrivernumber(snum); + DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); } else { - count = get_printqueue(SNUM(conn), conn,&queue,&status); + count = get_printqueue(snum, conn,&queue,&status); } if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; if (init_package(&desc,1,count)) { - desc.subcount = count; - fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); + desc.subcount = count; + fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); } *rdata_len = desc.usedlen; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4778e3a66b..9bfdddf704 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -667,7 +667,7 @@ int reply_ntcreate_and_X(connection_struct *conn, chain_fsp = fsp; DEBUG(5,("reply_ntcreate_and_X: open name = %s\n", - fsp->fsp_name)); + fsp?fsp->fsp_name:"NULL")); return chain_reply(inbuf,outbuf,length,bufsize); } -- cgit From f2d538a105a61ce6d2852700fc328e15ac158827 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 03:06:20 +0000 Subject: some cleanups from the conversion of Pipes[] to a linked list. I also removed most cases where a pnum is used and substituted a pipes_struct*. in files.c I added a offset of 0x1000 to all file handles on the wire. This makes it much less likely that bad parsing will give us the wrong field. (This used to be commit 8bc2627ff28d340db65bfa017daca2dc291d5ef7) --- source3/smbd/files.c | 19 +++--- source3/smbd/ipc.c | 2 +- source3/smbd/nttrans.c | 43 ++++++------ source3/smbd/pipes.c | 182 ++++++++++++++++++++++--------------------------- source3/smbd/server.c | 2 +- 5 files changed, 114 insertions(+), 134 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 8f1cefbbb6..bc3ea880bf 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -28,6 +28,8 @@ extern int DEBUGLEVEL; #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_FNUMS)) +#define FILE_HANDLE_OFFSET 0x1000 + static struct bitmap *file_bmap; static struct bitmap *fd_bmap; @@ -57,11 +59,6 @@ files_struct *file_new(void ) than causing corruption */ if (first_file == 0) { first_file = (getpid() ^ (int)time(NULL)) % MAX_FNUMS; - if (first_file == 0) first_file = 1; - } - - if (first_file >= MAX_FNUMS) { - first_file = 1; } i = bitmap_find(file_bmap, first_file); @@ -89,12 +86,14 @@ files_struct *file_new(void ) if (!fsp) return NULL; memset(fsp, 0, sizeof(*fsp)); - first_file = i+1; - fsp->fnum = i; - string_init(&fsp->fsp_name,""); + + first_file = (i+1) % MAX_FNUMS; bitmap_set(file_bmap, i); files_used++; + + fsp->fnum = i + FILE_HANDLE_OFFSET; + string_init(&fsp->fsp_name,""); /* hook into the front of the list */ if (!Files) { @@ -245,8 +244,6 @@ files_struct *file_fsp(int fnum) { files_struct *fsp; - if (!VALID_FNUM(fnum)) return NULL; - for (fsp=Files;fsp;fsp=fsp->next) { if (fsp->fnum == fnum) return fsp; } @@ -368,7 +365,7 @@ void file_free(files_struct *fsp) fd_ptr_free(fsp->fd_ptr); } - bitmap_clear(file_bmap, fsp->fnum); + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; DEBUG(5,("freed files structure %d (%d used)\n", diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index be7fb8d8e3..1a6fb3366a 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3398,7 +3398,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, /* Get the file handle and hence the file name. */ pnum = setup[1]; subcommand = setup[0]; - get_rpc_pipe(pnum, &p); + p = get_rpc_pipe(pnum); if (p != NULL) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9bfdddf704..31bfac25c8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -364,32 +364,33 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi static int nt_open_pipe(char *fname, connection_struct *conn, char *inbuf, char *outbuf, int *ppnum) { - int pnum = -1; - uint16 vuid = SVAL(inbuf, smb_uid); - int i; + pipes_struct *p = NULL; - DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); + uint16 vuid = SVAL(inbuf, smb_uid); + int i; + + DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); - /* See if it is one we want to handle. */ - for( i = 0; known_nt_pipes[i]; i++ ) - if( strequal(fname,known_nt_pipes[i])) - break; + /* See if it is one we want to handle. */ + for( i = 0; known_nt_pipes[i]; i++ ) + if( strequal(fname,known_nt_pipes[i])) + break; - if ( known_nt_pipes[i] == NULL ) - return(ERROR(ERRSRV,ERRaccess)); + if ( known_nt_pipes[i] == NULL ) + return(ERROR(ERRSRV,ERRaccess)); - /* Strip \\ off the name. */ - fname++; + /* Strip \\ off the name. */ + fname++; - DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); + DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); - pnum = open_rpc_pipe_hnd(fname, conn, vuid); - if (pnum < 0) - return(ERROR(ERRSRV,ERRnofids)); + p = open_rpc_pipe_p(fname, conn, vuid); + if (!p) + return(ERROR(ERRSRV,ERRnofids)); - *ppnum = pnum + PIPE_HANDLE_OFFSET; /* Mark file handle up into high - range. */ - return 0; + *ppnum = p->pnum; + + return 0; } /**************************************************************************** @@ -1258,8 +1259,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); - return(ERROR(ERRSRV,ERRnosupport)); + DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); + return(ERROR(ERRSRV,ERRnosupport)); } /**************************************************************************** diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 9ec77c08ca..84e31894a3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -32,22 +32,7 @@ #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) -#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024)) - -/* look in server.c for some explanation of these variables */ -extern int Protocol; extern int DEBUGLEVEL; -extern char magic_char; -extern BOOL case_sensitive; -extern pstring sesssetup_user; -extern int Client; - -#define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES)) -#define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && Pipes[pnum].open) - -/* this macro should always be used to extract an pnum (smb_fid) from - a packet to ensure chaining works correctly */ -#define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where)) extern struct pipe_id_info pipe_names[]; @@ -60,66 +45,63 @@ extern struct pipe_id_info pipe_names[]; int reply_open_pipe_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - pstring fname; - uint16 vuid = SVAL(inbuf, smb_uid); - int pnum = -1; - int smb_ofun = SVAL(inbuf,smb_vwv8); - int size=0,fmode=0,mtime=0,rmode=0; - int i; - - /* XXXX we need to handle passed times, sattr and flags */ - pstrcpy(fname,smb_buf(inbuf)); - - /* If the name doesn't start \PIPE\ then this is directed */ - /* at a mailslot or something we really, really don't understand, */ - /* not just something we really don't understand. */ - if ( strncmp(fname,PIPE,PIPELEN) != 0 ) - return(ERROR(ERRSRV,ERRaccess)); - - DEBUG(4,("Opening pipe %s.\n", fname)); - - /* See if it is one we want to handle. */ - for( i = 0; pipe_names[i].client_pipe ; i++ ) - if( strequal(fname,pipe_names[i].client_pipe) ) - break; - - if (pipe_names[i].client_pipe == NULL) - return(ERROR(ERRSRV,ERRaccess)); - - /* Strip \PIPE\ off the name. */ - pstrcpy(fname,smb_buf(inbuf) + PIPELEN); - - /* Known pipes arrive with DIR attribs. Remove it so a regular file */ - /* can be opened and add it in after the open. */ - DEBUG(3,("Known pipe %s opening.\n",fname)); - smb_ofun |= 0x10; /* Add Create it not exists flag */ - - pnum = open_rpc_pipe_hnd(fname, conn, vuid); - if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); - - /* Prepare the reply */ - set_message(outbuf,15,0,True); - - /* Mark the opened file as an existing named pipe in message mode. */ - SSVAL(outbuf,smb_vwv9,2); - SSVAL(outbuf,smb_vwv10,0xc700); - - if (rmode == 2) - { - DEBUG(4,("Resetting open result to open from create.\n")); - rmode = 1; - } - - SSVAL(outbuf,smb_vwv2, pnum + PIPE_HANDLE_OFFSET); /* mark file - handle up into - high range */ - SSVAL(outbuf,smb_vwv3,fmode); - put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,size); - SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,0); - - return chain_reply(inbuf,outbuf,length,bufsize); + pstring fname; + uint16 vuid = SVAL(inbuf, smb_uid); + pipes_struct *p; + int smb_ofun = SVAL(inbuf,smb_vwv8); + int size=0,fmode=0,mtime=0,rmode=0; + int i; + + /* XXXX we need to handle passed times, sattr and flags */ + pstrcpy(fname,smb_buf(inbuf)); + + /* If the name doesn't start \PIPE\ then this is directed */ + /* at a mailslot or something we really, really don't understand, */ + /* not just something we really don't understand. */ + if ( strncmp(fname,PIPE,PIPELEN) != 0 ) + return(ERROR(ERRSRV,ERRaccess)); + + DEBUG(4,("Opening pipe %s.\n", fname)); + + /* See if it is one we want to handle. */ + for( i = 0; pipe_names[i].client_pipe ; i++ ) + if( strequal(fname,pipe_names[i].client_pipe) ) + break; + + if (pipe_names[i].client_pipe == NULL) + return(ERROR(ERRSRV,ERRaccess)); + + /* Strip \PIPE\ off the name. */ + pstrcpy(fname,smb_buf(inbuf) + PIPELEN); + + /* Known pipes arrive with DIR attribs. Remove it so a regular file */ + /* can be opened and add it in after the open. */ + DEBUG(3,("Known pipe %s opening.\n",fname)); + smb_ofun |= 0x10; /* Add Create it not exists flag */ + + p = open_rpc_pipe_p(fname, conn, vuid); + if (!p) return(ERROR(ERRSRV,ERRnofids)); + + /* Prepare the reply */ + set_message(outbuf,15,0,True); + + /* Mark the opened file as an existing named pipe in message mode. */ + SSVAL(outbuf,smb_vwv9,2); + SSVAL(outbuf,smb_vwv10,0xc700); + + if (rmode == 2) { + DEBUG(4,("Resetting open result to open from create.\n")); + rmode = 1; + } + + SSVAL(outbuf,smb_vwv2, p->pnum); + SSVAL(outbuf,smb_vwv3,fmode); + put_dos_date3(outbuf,smb_vwv4,mtime); + SIVAL(outbuf,smb_vwv6,size); + SSVAL(outbuf,smb_vwv8,rmode); + SSVAL(outbuf,smb_vwv11,0); + + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -131,47 +113,47 @@ int reply_open_pipe_and_X(connection_struct *conn, ****************************************************************************/ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - int pnum = get_rpc_pipe_num(inbuf,smb_vwv2); - uint32 smb_offs = IVAL(inbuf,smb_vwv3); - int smb_maxcnt = SVAL(inbuf,smb_vwv5); - int smb_mincnt = SVAL(inbuf,smb_vwv6); - int nread = -1; - char *data; - BOOL ok = False; + pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); + uint32 smb_offs = IVAL(inbuf,smb_vwv3); + int smb_maxcnt = SVAL(inbuf,smb_vwv5); + int smb_mincnt = SVAL(inbuf,smb_vwv6); + int nread = -1; + char *data; + BOOL ok = False; - set_message(outbuf,12,0,True); - data = smb_buf(outbuf); + set_message(outbuf,12,0,True); + data = smb_buf(outbuf); - nread = read_pipe(pnum, data, smb_offs, smb_maxcnt); + nread = read_pipe(p, data, smb_offs, smb_maxcnt); - ok = True; + ok = True; - if (nread < 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if (nread < 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); - SSVAL(outbuf,smb_vwv5,nread); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); - SSVAL(smb_buf(outbuf),-2,nread); + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(smb_buf(outbuf),-2,nread); - DEBUG(3,("readX pnum=%04x min=%d max=%d nread=%d\n", - pnum, smb_mincnt, smb_maxcnt, nread)); + DEBUG(3,("readX pnum=%04x min=%d max=%d nread=%d\n", + p->pnum, smb_mincnt, smb_maxcnt, nread)); - set_chain_pnum(pnum); + set_chain_p(p); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** reply to a close ****************************************************************************/ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) { - int pnum = get_rpc_pipe_num(inbuf,smb_vwv0); - int outsize = set_message(outbuf,0,0,True); + pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); + int outsize = set_message(outbuf,0,0,True); - DEBUG(5,("reply_pipe_close: pnum:%x\n", pnum)); + DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum)); - if (!close_rpc_pipe_hnd(pnum, conn)) return(ERROR(ERRDOS,ERRbadfid)); + if (!close_rpc_pipe_hnd(p, conn)) return(ERROR(ERRDOS,ERRbadfid)); - return(outsize); + return(outsize); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1ae402b902..e6117000a4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4700,7 +4700,7 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) chain_size = 0; chain_fsp = NULL; - reset_chain_pnum(); + reset_chain_p(); if (msg_type != 0) return(reply_special(inbuf,outbuf)); -- cgit From 8978aae69699ccab76fdf95037948b1cc7e7c286 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 03:52:05 +0000 Subject: much cleaner chain pointer handling for both files and pipes. the chain pointer is now stored as a static and is set whenever a handle is created or extracted. This also makes the code less error prone. (This used to be commit 068a862982bea726e8d7b1b4065d510b9840a272) --- source3/smbd/files.c | 55 ++++++++++++++++++++++++++++++++++++-------------- source3/smbd/nttrans.c | 7 ++----- source3/smbd/pipes.c | 2 -- source3/smbd/reply.c | 53 ++++++++++++++++++++---------------------------- source3/smbd/server.c | 5 +---- source3/smbd/trans2.c | 5 ++--- 6 files changed, 67 insertions(+), 60 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index bc3ea880bf..e66e53e6ed 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -35,6 +35,10 @@ static struct bitmap *fd_bmap; static files_struct *Files; +/* a fsp to use when chaining */ +static files_struct *chain_fsp = NULL; + + /* * Indirection for file fd's. Needed as POSIX locking * is based on file/process, not fd/process. @@ -106,6 +110,8 @@ files_struct *file_new(void ) DEBUG(5,("allocated file structure %d (%d used)\n", i, files_used)); + + chain_fsp = fsp; return fsp; } @@ -237,21 +243,6 @@ void file_init(void) } -/**************************************************************************** -find a fsp given a fnum -****************************************************************************/ -files_struct *file_fsp(int fnum) -{ - files_struct *fsp; - - for (fsp=Files;fsp;fsp=fsp->next) { - if (fsp->fnum == fnum) return fsp; - } - - return NULL; -} - - /**************************************************************************** close files open by a specified vuid ****************************************************************************/ @@ -375,5 +366,39 @@ void file_free(files_struct *fsp) information */ memset(fsp, 0, sizeof(*fsp)); + if (fsp == chain_fsp) chain_fsp = NULL; + free(fsp); } + + +/**************************************************************************** +get a fsp from a packet given the offset of a 16 bit fnum +****************************************************************************/ +files_struct *file_fsp(char *buf, int where) +{ + int fnum; + files_struct *fsp; + + if (chain_fsp) return chain_fsp; + + fnum = SVAL(buf, where); + + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->fnum == fnum) { + chain_fsp = fsp; + return fsp; + } + } + + return NULL; +} + + +/**************************************************************************** +reset the chained fsp - done at the start of a packet reply +****************************************************************************/ +void file_chain_reset(void) +{ + chain_fsp = NULL; +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 31bfac25c8..89efd7ccd7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -24,7 +24,6 @@ extern int DEBUGLEVEL; extern int Protocol; -extern files_struct *chain_fsp; extern int Client; extern int oplock_sock; extern int smb_read_error; @@ -665,8 +664,6 @@ int reply_ntcreate_and_X(connection_struct *conn, SCVAL(p,0,fsp->is_directory ? 1 : 0); } - chain_fsp = fsp; - DEBUG(5,("reply_ntcreate_and_X: open name = %s\n", fsp?fsp->fsp_name:"NULL")); @@ -941,7 +938,7 @@ static int call_nt_transact_rename(connection_struct *conn, { char *params = *ppparams; pstring new_name; - files_struct *fsp = GETFSP(params, 0); + files_struct *fsp = file_fsp(params, 0); BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)), ((uint32)sizeof(new_name)-1)); @@ -1166,7 +1163,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, change_notify_buf *cnbp; struct stat st; - fsp = GETFSP(setup,4); + fsp = file_fsp(setup,4); DEBUG(3,("call_nt_transact_notify_change\n")); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 84e31894a3..fed5c2bd17 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -138,8 +138,6 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(3,("readX pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); - set_chain_p(p); - return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e62c0bd576..6b91d9d152 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -33,7 +33,6 @@ extern int Protocol; extern int DEBUGLEVEL; extern int max_send; extern int max_recv; -extern files_struct *chain_fsp; extern char magic_char; extern BOOL case_sensitive; extern BOOL case_preserve; @@ -1425,8 +1424,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,smb_action); - chain_fsp = fsp; - return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1773,7 +1770,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s return -1; } - fsp = GETFSP(inbuf,smb_vwv0); + fsp = file_fsp(inbuf,smb_vwv0); startpos = IVAL(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); @@ -1862,7 +1859,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_si uint32 startpos, numtoread; int eclass; uint32 ecode; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_READ(fsp); @@ -1905,7 +1902,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, char *data; uint32 startpos; int outsize = 0; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_READ(fsp); @@ -1945,7 +1942,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, ****************************************************************************/ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = GETFSP(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); @@ -1979,8 +1976,6 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n", fsp->fnum, smb_mincnt, smb_maxcnt, nread ) ); - chain_fsp = fsp; - return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1998,7 +1993,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s char *data=NULL; BOOL write_through; int tcount; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2100,7 +2095,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum uint32 numtowrite,startpos; int eclass; uint32 ecode; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2153,7 +2148,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i int outsize = 0; int startpos; char *data; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2203,7 +2198,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i ****************************************************************************/ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = GETFSP(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_dsize = SVAL(inbuf,smb_vwv10); int smb_doff = SVAL(inbuf,smb_vwv11); @@ -2246,8 +2241,6 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", fsp->fnum, smb_dsize, nwritten)); - chain_fsp = fsp; - if (lp_syncalways(SNUM(conn)) || write_through) sync_file(conn,fsp); @@ -2264,7 +2257,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int32 res= -1; int mode,umode; int outsize = 0; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2300,7 +2293,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); if (fsp) { CHECK_FSP(fsp,conn); @@ -2349,7 +2342,7 @@ int reply_close(connection_struct *conn, return reply_pipe_close(conn, inbuf,outbuf); } - fsp = GETFSP(inbuf,smb_vwv0); + fsp = file_fsp(inbuf,smb_vwv0); /* * We can only use CHECK_FSP if we know it's not a directory. @@ -2406,7 +2399,7 @@ int reply_writeclose(connection_struct *conn, int startpos; char *data; time_t mtime; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2452,7 +2445,7 @@ int reply_lock(connection_struct *conn, uint32 count,offset; int eclass; uint32 ecode; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2479,7 +2472,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size uint32 count,offset; int eclass; uint32 ecode; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2629,7 +2622,7 @@ int reply_printclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2724,7 +2717,7 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ int numtowrite; int outsize = set_message(outbuf,0,0,True); char *data; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); if (!CAN_PRINT(conn)) return(ERROR(ERRDOS,ERRnoaccess)); @@ -3490,7 +3483,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ****************************************************************************/ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = GETFSP(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); unsigned char locktype = CVAL(inbuf,smb_vwv3); #if 0 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); @@ -3606,8 +3599,6 @@ dev = %x, inode = %x\n", DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); - chain_fsp = fsp; - return chain_reply(inbuf,outbuf,length,bufsize); } @@ -3625,7 +3616,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, int max_per_packet; int tcount; int pad; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); /* this function doesn't seem to work - disable by default */ if (!lp_readbmpx()) @@ -3692,7 +3683,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s uint32 startpos; int tcount, write_through, smb_doff; char *data; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -3785,7 +3776,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz char *data; write_bmpx_struct *wbms; BOOL send_response = False; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -3859,7 +3850,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si { struct utimbuf unix_times; int outsize = 0; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); outsize = set_message(outbuf,0,0,True); @@ -3912,7 +3903,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si struct stat sbuf; int outsize = 0; int mode; - files_struct *fsp = GETFSP(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); outsize = set_message(outbuf,11,0,True); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e6117000a4..f160b590dc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -81,9 +81,6 @@ int max_send = BUFFER_SIZE; */ int max_recv = BUFFER_SIZE; -/* a fsp to use when chaining */ -files_struct *chain_fsp = NULL; - /* number of open connections */ static int num_connections_open = 0; @@ -4699,7 +4696,7 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) smb_last_time = time(NULL); chain_size = 0; - chain_fsp = NULL; + file_chain_reset(); reset_chain_p(); if (msg_type != 0) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 72ad7ec12b..2789282771 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -32,7 +32,6 @@ extern int oplock_sock; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; -extern files_struct *chain_fsp; /**************************************************************************** Send the required number of replies back. @@ -1209,7 +1208,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, BOOL bad_path = False; if (tran_call == TRANSACT2_QFILEINFO) { - files_struct *fsp = GETFSP(params,0); + files_struct *fsp = file_fsp(params,0); info_level = SVAL(params,2); CHECK_FSP(fsp,conn); @@ -1434,7 +1433,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(ERROR(ERRSRV,ERRaccess)); if (tran_call == TRANSACT2_SETFILEINFO) { - files_struct *fsp = GETFSP(params,0); + files_struct *fsp = file_fsp(params,0); info_level = SVAL(params,2); CHECK_FSP(fsp,conn); -- cgit From 983dc71c9844675ad364f3ea59ddd04b87857b55 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 06:13:32 +0000 Subject: moved connection_struct handling code into smbd/conn.c and changed it to a linked list with bitmap format. (This used to be commit b7aaab1b6b2d2f72b2bb7c11f5c7bf081a6093d9) --- source3/smbd/conn.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/files.c | 20 +++--- source3/smbd/server.c | 137 +++++------------------------------ source3/smbd/uid.c | 2 +- 4 files changed, 227 insertions(+), 128 deletions(-) create mode 100644 source3/smbd/conn.c (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c new file mode 100644 index 0000000000..b110e8d082 --- /dev/null +++ b/source3/smbd/conn.c @@ -0,0 +1,196 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Manage connections_struct structures + Copyright (C) Andrew Tridgell 1998 + + 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; + +/* set these to define the limits of the server. NOTE These are on a + per-client basis. Thus any one machine can't connect to more than + MAX_CONNECTIONS services, but any number of machines may connect at + one time. */ +#define MAX_CONNECTIONS 128 + +static connection_struct *Connections; + +/* number of open connections */ +static struct bitmap *bmap; +static int num_open; + +/**************************************************************************** +init the conn structures +****************************************************************************/ +void conn_init(void) +{ + bmap = bitmap_allocate(MAX_CONNECTIONS); +} + +/**************************************************************************** +return the number of open connections +****************************************************************************/ +int conn_num_open(void) +{ + return num_open; +} + + +/**************************************************************************** +check if a snum is in use +****************************************************************************/ +BOOL conn_snum_used(int snum) +{ + connection_struct *conn; + for (conn=Connections;conn;conn=conn->next) { + if (conn->service == snum) { + return(True); + } + } + return(False); +} + + +/**************************************************************************** +find a conn given a cnum +****************************************************************************/ +connection_struct *conn_find(int cnum) +{ + connection_struct *conn; + + for (conn=Connections;conn;conn=conn->next) { + if (conn->cnum == cnum) return conn; + } + + return NULL; +} + + +/**************************************************************************** + find first available connection slot, starting from a random position. +The randomisation stops problems with the server dieing and clients +thinking the server is still available. +****************************************************************************/ +connection_struct *conn_new(void) +{ + connection_struct *conn; + int i; + + i = bitmap_find(bmap, 1); + + if (i == -1) { + DEBUG(1,("ERROR! Out of connection structures\n")); + return NULL; + } + + conn = (connection_struct *)malloc(sizeof(*conn)); + if (!conn) return NULL; + + memset(conn, 0, sizeof(*conn)); + conn->cnum = i; + + bitmap_set(bmap, i); + + num_open++; + + string_init(&conn->user,""); + string_init(&conn->dirpath,""); + string_init(&conn->connectpath,""); + string_init(&conn->origpath,""); + + /* hook into the front of the list */ + if (!Connections) { + Connections = conn; + } else { + Connections->prev = conn; + conn->next = Connections; + Connections = conn; + } + + return conn; +} + +/**************************************************************************** +close all conn structures +****************************************************************************/ +void conn_close_all(void) +{ + connection_struct *conn, *next; + for (conn=Connections;conn;conn=next) { + next=conn->next; + close_cnum(conn, (uint16)-1); + } +} + +/**************************************************************************** +idle inactive connections +****************************************************************************/ +BOOL conn_idle_all(time_t t, int deadtime) +{ + BOOL allidle = True; + connection_struct *conn, *next; + + for (conn=Connections;conn;conn=next) { + next=conn->next; + /* close dirptrs on connections that are idle */ + if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) + dptr_idlecnum(conn); + + if (conn->num_files_open > 0 || + (t-conn->lastused)next; + if (Connections) Connections->prev = NULL; + } else { + conn->prev->next = conn->next; + if (conn->next) conn->next->prev = conn->prev; + } + + if (conn->ngroups && conn->groups) { + free(conn->groups); + conn->groups = NULL; + conn->ngroups = 0; + } + + free_namearray(conn->veto_list); + free_namearray(conn->hide_list); + free_namearray(conn->veto_oplock_list); + + string_free(&conn->user); + string_free(&conn->dirpath); + string_free(&conn->connectpath); + string_free(&conn->origpath); + + bitmap_clear(bmap, conn->cnum); + num_open--; + + memset(conn, 0, sizeof(*conn)); + free(conn); +} diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e66e53e6ed..7bd5501de5 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -54,7 +54,7 @@ files_struct *file_new(void ) { int i; static int first_file; - files_struct *fsp; + files_struct *fsp, *next; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to @@ -76,7 +76,8 @@ files_struct *file_new(void ) * files batch oplocked for quite a long time * after they have finished with them. */ - for (fsp=Files;fsp;fsp=fsp->next) { + for (fsp=Files;fsp;fsp=next) { + next=fsp->next; if (attempt_close_oplocked_file(fsp)) { return file_new(); } @@ -200,9 +201,10 @@ close all open files for a connection ****************************************************************************/ void file_close_conn(connection_struct *conn) { - files_struct *fsp; + files_struct *fsp, *next; - for (fsp=Files;fsp;fsp=fsp->next) { + for (fsp=Files;fsp;fsp=next) { + next = fsp->next; if (fsp->conn == conn && fsp->open) { if (fsp->is_directory) close_directory(fsp); @@ -248,9 +250,10 @@ close files open by a specified vuid ****************************************************************************/ void file_close_user(int vuid) { - files_struct *fsp; + files_struct *fsp, *next; - for (fsp=Files;fsp;fsp=fsp->next) { + for (fsp=Files;fsp;fsp=next) { + next=fsp->next; if ((fsp->vuid == vuid) && fsp->open) { if(!fsp->is_directory) close_file(fsp,False); @@ -301,9 +304,10 @@ sync open files on a connection ****************************************************************************/ void file_sync_all(connection_struct *conn) { - files_struct *fsp; + files_struct *fsp, *next; - for (fsp=Files;fsp;fsp=fsp->next) { + for (fsp=Files;fsp;fsp=next) { + next=fsp->next; if (fsp->open && conn == fsp->conn) { sync_file(conn,fsp); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f160b590dc..a293075741 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -65,8 +65,6 @@ extern int dcelogin_atmost_once; */ extern DOM_SID global_machine_sid; -static connection_struct Connections[MAX_CONNECTIONS]; - extern int Protocol; /* @@ -81,9 +79,6 @@ int max_send = BUFFER_SIZE; */ int max_recv = BUFFER_SIZE; -/* number of open connections */ -static int num_connections_open = 0; - /* Oplock ipc UDP socket. */ int oplock_sock = -1; uint16 oplock_port = 0; @@ -2094,7 +2089,7 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir) static connection_struct *last_conn; int snum; - if (!conn || !conn->open) { + if (!conn) { last_conn = NULL; return(False); } @@ -3249,20 +3244,6 @@ BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int tim return ret; } -/**************************************************************************** -check if a snum is in use -****************************************************************************/ -BOOL snum_used(int snum) -{ - int i; - for (i=0;iopen = True; - /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { pstring cmd; @@ -3610,7 +3556,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!become_user(conn, conn->vuid)) { DEBUG(0,("Can't become connected user!\n")); - conn->open = False; if (!IS_IPC(conn)) { yield_connection(conn, lp_servicename(SNUM(conn)), @@ -3619,6 +3564,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int yield_connection(conn,"STATUS.",MAXSTATUS); } } + conn_free(conn); *ecode = ERRbadpw; return NULL; } @@ -3626,7 +3572,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (ChDir(conn->connectpath) != 0) { DEBUG(0,("Can't change directory to %s (%s)\n", conn->connectpath,strerror(errno))); - conn->open = False; unbecome_user(); if (!IS_IPC(conn)) { yield_connection(conn, @@ -3635,6 +3580,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (lp_status(SNUM(conn))) yield_connection(conn,"STATUS.",MAXSTATUS); } + conn_free(conn); *ecode = ERRinvnetname; return NULL; } @@ -3652,7 +3598,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int } #endif - num_connections_open++; add_session_user(user); /* execute any "preexec = " line */ @@ -4108,11 +4053,6 @@ void close_cnum(connection_struct *conn, uint16 vuid) unbecome_user(); - if (!conn->open) { - DEBUG(0,("cnum not open\n")); - return; - } - DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", remote_machine,client_addr(Client), lp_servicename(SNUM(conn)))); @@ -4146,21 +4086,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) smbrun(cmd,NULL,False); } - conn->open = False; - num_connections_open--; - if (conn->ngroups && conn->groups) { - free(conn->groups); - conn->groups = NULL; - conn->ngroups = 0; - } - - free_namearray(conn->veto_list); - free_namearray(conn->hide_list); - free_namearray(conn->veto_oplock_list); - - string_set(&conn->user,""); - string_set(&conn->dirpath,""); - string_set(&conn->connectpath,""); + conn_free(conn); } @@ -4208,16 +4134,15 @@ exit the server void exit_server(char *reason) { static int firsttime=1; - int i; if (!firsttime) exit(0); firsttime = 0; unbecome_user(); DEBUG(2,("Closing connections\n")); - for (i=0;i= IDLE_CLOSED_TIMEOUT) + if (conn_num_open()==0 && counter >= IDLE_CLOSED_TIMEOUT) { DEBUG( 2, ( "Closing idle connection\n" ) ); return; @@ -4837,19 +4757,9 @@ static void process(void) } /* check for connection timeouts */ - for (i=0;iDPTR_IDLE_TIMEOUT) - dptr_idlecnum(&Connections[i]); - - if (Connections[i].num_files_open > 0 || - (t-Connections[i].lastused)0) { + if (allidle && conn_num_open()>0) { DEBUG(2,("Closing idle connection 2.\n")); return; } @@ -4920,7 +4830,6 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); ****************************************************************************/ static void init_structs(void ) { - int i; get_myname(myhostname,NULL); /* @@ -4938,17 +4847,7 @@ static void init_structs(void ) } strupper( global_myname ); - for (i=0;iopen)) { + if (!conn) { DEBUG(2,("Connection not open\n")); return(False); } -- cgit From 72ed7049d88e5296ebec362189e62a384385ad34 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 06:47:53 +0000 Subject: added some optimisation for the case where the number of open files is very large. files.c now promotes a files_struct to the top of the list if it is used when it is more than 10 elements from the top. also moved common linked list code for the 5 sets of linked lists that I've created over the past few days into dlinklist.h (I've explained to Chris why I didn't use the ubiqx code) (This used to be commit 1eb9ae2996b5a243a147f485e7e353d54f820852) --- source3/smbd/conn.c | 27 ++++++++++----------------- source3/smbd/files.c | 47 ++++++++++++++--------------------------------- 2 files changed, 24 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index b110e8d082..2afbfb7d7e 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -72,10 +72,16 @@ find a conn given a cnum ****************************************************************************/ connection_struct *conn_find(int cnum) { + int count=0; connection_struct *conn; - for (conn=Connections;conn;conn=conn->next) { - if (conn->cnum == cnum) return conn; + for (conn=Connections;conn;conn=conn->next,count++) { + if (conn->cnum == cnum) { + if (count > 10) { + DLIST_PROMOTE(Connections, conn); + } + return conn; + } } return NULL; @@ -114,14 +120,7 @@ connection_struct *conn_new(void) string_init(&conn->connectpath,""); string_init(&conn->origpath,""); - /* hook into the front of the list */ - if (!Connections) { - Connections = conn; - } else { - Connections->prev = conn; - conn->next = Connections; - Connections = conn; - } + DLIST_ADD(Connections, conn); return conn; } @@ -165,13 +164,7 @@ free a conn structure ****************************************************************************/ void conn_free(connection_struct *conn) { - if (conn == Connections) { - Connections = conn->next; - if (Connections) Connections->prev = NULL; - } else { - conn->prev->next = conn->next; - if (conn->next) conn->next->prev = conn->prev; - } + DLIST_REMOVE(Connections, conn); if (conn->ngroups && conn->groups) { free(conn->groups); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 7bd5501de5..fa1b8f3bac 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -100,14 +100,7 @@ files_struct *file_new(void ) fsp->fnum = i + FILE_HANDLE_OFFSET; string_init(&fsp->fsp_name,""); - /* hook into the front of the list */ - if (!Files) { - Files = fsp; - } else { - Files->prev = fsp; - fsp->next = Files; - Files = fsp; - } + DLIST_ADD(Files, fsp); DEBUG(5,("allocated file structure %d (%d used)\n", i, files_used)); @@ -180,14 +173,7 @@ file_fd_struct *fd_get_new(void) bitmap_set(fd_bmap, i); fd_ptr_used++; - /* hook into the front of the list */ - if (!FileFd) { - FileFd = fd_ptr; - } else { - FileFd->prev = fd_ptr; - fd_ptr->next = FileFd; - FileFd = fd_ptr; - } + DLIST_ADD(FileFd, fd_ptr); DEBUG(5,("allocated fd_ptr structure %d (%d used)\n", i, fd_ptr_used)); @@ -269,14 +255,18 @@ find a fsp given a device, inode and timevalue ****************************************************************************/ files_struct *file_find_dit(int dev, int inode, struct timeval *tval) { + int count=0; files_struct *fsp; - for (fsp=Files;fsp;fsp=fsp->next) { + for (fsp=Files;fsp;fsp=fsp->next,count++) { if (fsp->open && fsp->fd_ptr->dev == dev && fsp->fd_ptr->inode == inode && fsp->open_time.tv_sec == tval->tv_sec && fsp->open_time.tv_usec == tval->tv_usec) { + if (count > 10) { + DLIST_PROMOTE(Files, fsp); + } return fsp; } } @@ -320,13 +310,7 @@ free up a fd_ptr ****************************************************************************/ static void fd_ptr_free(file_fd_struct *fd_ptr) { - if (fd_ptr == FileFd) { - FileFd = fd_ptr->next; - if (FileFd) FileFd->prev = NULL; - } else { - fd_ptr->prev->next = fd_ptr->next; - if (fd_ptr->next) fd_ptr->next->prev = fd_ptr->prev; - } + DLIST_REMOVE(FileFd, fd_ptr); bitmap_clear(fd_bmap, fd_ptr->fdnum); fd_ptr_used--; @@ -346,13 +330,7 @@ free up a fsp ****************************************************************************/ void file_free(files_struct *fsp) { - if (fsp == Files) { - Files = fsp->next; - if (Files) Files->prev = NULL; - } else { - fsp->prev->next = fsp->next; - if (fsp->next) fsp->next->prev = fsp->prev; - } + DLIST_REMOVE(Files, fsp); string_free(&fsp->fsp_name); @@ -381,16 +359,19 @@ get a fsp from a packet given the offset of a 16 bit fnum ****************************************************************************/ files_struct *file_fsp(char *buf, int where) { - int fnum; + int fnum, count=0; files_struct *fsp; if (chain_fsp) return chain_fsp; fnum = SVAL(buf, where); - for (fsp=Files;fsp;fsp=fsp->next) { + for (fsp=Files;fsp;fsp=fsp->next, count++) { if (fsp->fnum == fnum) { chain_fsp = fsp; + if (count > 10) { + DLIST_PROMOTE(Files, fsp); + } return fsp; } } -- cgit From 4c5c26b1ef4be862fc2037dd5fcc120cb35bacca Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 07:15:54 +0000 Subject: now that we have no global arrays we can start to split up the monster server.c without breaking things. this splits off netprot.c and fileio.c for negprot and read/write/seek handling respectively. (This used to be commit b3d7014643ec9f2eef6e6f598f5b9db1fe2f930d) --- source3/smbd/fileio.c | 117 ++++++++++++ source3/smbd/negprot.c | 415 ++++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 485 ------------------------------------------------- 3 files changed, 532 insertions(+), 485 deletions(-) create mode 100644 source3/smbd/fileio.c create mode 100644 source3/smbd/negprot.c (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c new file mode 100644 index 0000000000..edf87f3e7b --- /dev/null +++ b/source3/smbd/fileio.c @@ -0,0 +1,117 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + read/write to a files_struct + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + + +/**************************************************************************** +seek a file. Try to avoid the seek if possible +****************************************************************************/ +int seek_file(files_struct *fsp,uint32 pos) +{ + uint32 offset = 0; + + if (fsp->print_file && lp_postscript(fsp->conn->service)) + offset = 3; + + fsp->pos = (int)(lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); + return(fsp->pos); +} + +/**************************************************************************** +read from a file +****************************************************************************/ +int read_file(files_struct *fsp,char *data,uint32 pos,int n) +{ + int ret=0,readret; + +#if USE_READ_PREDICTION + if (!fsp->can_write) + { + ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); + + data += ret; + n -= ret; + pos += ret; + } +#endif + +#if WITH_MMAP + if (fsp->mmap_ptr) + { + int num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; + num = MIN(n,num); + if (num > 0) + { + memcpy(data,fsp->mmap_ptr+pos,num); + data += num; + pos += num; + n -= num; + ret += num; + } + } +#endif + + if (n <= 0) + return(ret); + + if (seek_file(fsp,pos) != pos) + { + DEBUG(3,("Failed to seek to %d\n",pos)); + return(ret); + } + + if (n > 0) { + readret = read(fsp->fd_ptr->fd,data,n); + if (readret > 0) ret += readret; + } + + return(ret); +} + + +/**************************************************************************** +write to a file +****************************************************************************/ +int write_file(files_struct *fsp,char *data,int n) +{ + + if (!fsp->can_write) { + errno = EPERM; + return(0); + } + + if (!fsp->modified) { + struct stat st; + fsp->modified = True; + if (fstat(fsp->fd_ptr->fd,&st) == 0) { + int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); + if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { + dos_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); + } + } + } + + return(write_data(fsp->fd_ptr->fd,data,n)); +} + diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c new file mode 100644 index 0000000000..8e996cac21 --- /dev/null +++ b/source3/smbd/negprot.c @@ -0,0 +1,415 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + negprot reply code + Copyright (C) Andrew Tridgell 1992-1998 + + 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; +extern int Protocol; +extern int max_recv; +extern fstring global_myworkgroup; +extern fstring remote_machine; +extern pstring myhostname; + +/**************************************************************************** +reply for the core protocol +****************************************************************************/ +static int reply_corep(char *outbuf) +{ + int outsize = set_message(outbuf,1,0,True); + + Protocol = PROTOCOL_CORE; + + return outsize; +} + + +/**************************************************************************** +reply for the coreplus protocol +****************************************************************************/ +static int reply_coreplus(char *outbuf) +{ + int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); + int outsize = set_message(outbuf,13,0,True); + SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support + readbraw and writebraw (possibly) */ + CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */ + + Protocol = PROTOCOL_COREPLUS; + + return outsize; +} + + +/**************************************************************************** +reply for the lanman 1.0 protocol +****************************************************************************/ +static int reply_lanman1(char *outbuf) +{ + int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); + int secword=0; + BOOL doencrypt = SMBENCRYPT(); + time_t t = time(NULL); + + if (lp_security()>=SEC_USER) secword |= 1; + if (doencrypt) secword |= 2; + + set_message(outbuf,13,doencrypt?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); + /* Create a token value and add it to the outgoing packet. */ + if (doencrypt) + generate_next_challenge(smb_buf(outbuf)); + + Protocol = PROTOCOL_LANMAN1; + + CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + SSVAL(outbuf,smb_vwv2,max_recv); + SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ + SSVAL(outbuf,smb_vwv4,1); + SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support + readbraw writebraw (possibly) */ + SIVAL(outbuf,smb_vwv6,getpid()); + SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); + + put_dos_date(outbuf,smb_vwv8,t); + + return (smb_len(outbuf)+4); +} + + +/**************************************************************************** +reply for the lanman 2.0 protocol +****************************************************************************/ +static int reply_lanman2(char *outbuf) +{ + int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); + int secword=0; + BOOL doencrypt = SMBENCRYPT(); + time_t t = time(NULL); + struct cli_state *cli = NULL; + char cryptkey[8]; + char crypt_len = 0; + + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } + + if (cli) { + DEBUG(3,("using password server validation\n")); + doencrypt = ((cli->sec_mode & 2) != 0); + } + + if (lp_security()>=SEC_USER) secword |= 1; + if (doencrypt) secword |= 2; + + if (doencrypt) { + crypt_len = 8; + if (!cli) { + generate_next_challenge(cryptkey); + } else { + memcpy(cryptkey, cli->cryptkey, 8); + set_challenge(cli->cryptkey); + } + } + + set_message(outbuf,13,crypt_len,True); + SSVAL(outbuf,smb_vwv1,secword); + SIVAL(outbuf,smb_vwv6,getpid()); + if (doencrypt) + memcpy(smb_buf(outbuf), cryptkey, 8); + + Protocol = PROTOCOL_LANMAN2; + + CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + SSVAL(outbuf,smb_vwv2,max_recv); + SSVAL(outbuf,smb_vwv3,lp_maxmux()); + SSVAL(outbuf,smb_vwv4,1); + SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ + SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); + put_dos_date(outbuf,smb_vwv8,t); + + return (smb_len(outbuf)+4); +} + + +/**************************************************************************** +reply for the nt protocol +****************************************************************************/ +static int reply_nt1(char *outbuf) +{ + /* dual names + lock_and_read + nt SMBs + remote API calls */ + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS |CAP_NT_SMBS; + +/* + other valid capabilities which we may support at some time... + CAP_LARGE_FILES| + CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; + */ + + int secword=0; + BOOL doencrypt = SMBENCRYPT(); + time_t t = time(NULL); + int data_len; + struct cli_state *cli = NULL; + char cryptkey[8]; + char crypt_len = 0; + + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } + + if (cli) { + DEBUG(3,("using password server validation\n")); + doencrypt = ((cli->sec_mode & 2) != 0); + } + + if (doencrypt) { + crypt_len = 8; + if (!cli) { + generate_next_challenge(cryptkey); + } else { + memcpy(cryptkey, cli->cryptkey, 8); + set_challenge(cli->cryptkey); + } + } + + if (lp_readraw() && lp_writeraw()) { + capabilities |= CAP_RAW_MODE; + } + + if (lp_security() >= SEC_USER) secword |= 1; + if (doencrypt) secword |= 2; + + /* decide where (if) to put the encryption challenge, and + follow it with the OEM'd domain name + */ + data_len = crypt_len + strlen(global_myworkgroup) + 1; + + set_message(outbuf,17,data_len,True); + pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); + + CVAL(outbuf,smb_vwv1) = secword; + SSVALS(outbuf,smb_vwv16+1,crypt_len); + if (doencrypt) + memcpy(smb_buf(outbuf), cryptkey, 8); + + Protocol = PROTOCOL_NT1; + + SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ + SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ + SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ + SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ + SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ + SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ + put_long_date(outbuf+smb_vwv11+1,t); + SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); + SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */ + + return (smb_len(outbuf)+4); +} + +/* these are the protocol lists used for auto architecture detection: + +WinNT 3.51: +protocol [PC NETWORK PROGRAM 1.0] +protocol [XENIX CORE] +protocol [MICROSOFT NETWORKS 1.03] +protocol [LANMAN1.0] +protocol [Windows for Workgroups 3.1a] +protocol [LM1.2X002] +protocol [LANMAN2.1] +protocol [NT LM 0.12] + +Win95: +protocol [PC NETWORK PROGRAM 1.0] +protocol [XENIX CORE] +protocol [MICROSOFT NETWORKS 1.03] +protocol [LANMAN1.0] +protocol [Windows for Workgroups 3.1a] +protocol [LM1.2X002] +protocol [LANMAN2.1] +protocol [NT LM 0.12] + +OS/2: +protocol [PC NETWORK PROGRAM 1.0] +protocol [XENIX CORE] +protocol [LANMAN1.0] +protocol [LM1.2X002] +protocol [LANMAN2.1] +*/ + +/* + * Modified to recognize the architecture of the remote machine better. + * + * This appears to be the matrix of which protocol is used by which + * MS product. + Protocol WfWg Win95 WinNT OS/2 + PC NETWORK PROGRAM 1.0 1 1 1 1 + XENIX CORE 2 2 + MICROSOFT NETWORKS 3.0 2 2 + DOS LM1.2X002 3 3 + MICROSOFT NETWORKS 1.03 3 + DOS LANMAN2.1 4 4 + LANMAN1.0 4 3 + Windows for Workgroups 3.1a 5 5 5 + LM1.2X002 6 4 + LANMAN2.1 7 5 + NT LM 0.12 6 8 + * + * tim@fsg.com 09/29/95 + */ + +#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */ +#define ARCH_WIN95 0x2 +#define ARCH_OS2 0xC /* Again OS/2 is like NT */ +#define ARCH_WINNT 0x8 +#define ARCH_SAMBA 0x10 + +#define ARCH_ALL 0x1F + +/* List of supported protocols, most desired first */ +static struct { + char *proto_name; + char *short_name; + int (*proto_reply_fn)(char *); + int protocol_level; +} supported_protocols[] = { + {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, + {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, + {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, + {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, + {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS}, + {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE}, + {NULL,NULL}, +}; + + +/**************************************************************************** + reply to a negprot +****************************************************************************/ +int reply_negprot(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, + int dum_buffsize) +{ + int outsize = set_message(outbuf,1,0,True); + int Index=0; + int choice= -1; + int protocol; + char *p; + int bcc = SVAL(smb_buf(inbuf),-2); + int arch = ARCH_ALL; + + p = smb_buf(inbuf)+1; + while (p < (smb_buf(inbuf) + bcc)) + { + Index++; + DEBUG(3,("Requested protocol [%s]\n",p)); + if (strcsequal(p,"Windows for Workgroups 3.1a")) + arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT ); + else if (strcsequal(p,"DOS LM1.2X002")) + arch &= ( ARCH_WFWG | ARCH_WIN95 ); + else if (strcsequal(p,"DOS LANMAN2.1")) + arch &= ( ARCH_WFWG | ARCH_WIN95 ); + else if (strcsequal(p,"NT LM 0.12")) + arch &= ( ARCH_WIN95 | ARCH_WINNT ); + else if (strcsequal(p,"LANMAN2.1")) + arch &= ( ARCH_WINNT | ARCH_OS2 ); + else if (strcsequal(p,"LM1.2X002")) + arch &= ( ARCH_WINNT | ARCH_OS2 ); + else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) + arch &= ARCH_WINNT; + else if (strcsequal(p,"XENIX CORE")) + arch &= ( ARCH_WINNT | ARCH_OS2 ); + else if (strcsequal(p,"Samba")) { + arch = ARCH_SAMBA; + break; + } + + p += strlen(p) + 2; + } + + switch ( arch ) { + case ARCH_SAMBA: + set_remote_arch(RA_SAMBA); + break; + case ARCH_WFWG: + set_remote_arch(RA_WFWG); + break; + case ARCH_WIN95: + set_remote_arch(RA_WIN95); + break; + case ARCH_WINNT: + set_remote_arch(RA_WINNT); + break; + case ARCH_OS2: + set_remote_arch(RA_OS2); + break; + default: + set_remote_arch(RA_UNKNOWN); + break; + } + + /* possibly reload - change of architecture */ + reload_services(True); + + /* a special case to stop password server loops */ + if (Index == 1 && strequal(remote_machine,myhostname) && + (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN)) + exit_server("Password server loop!"); + + /* Check for protocols, most desirable first */ + for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) + { + p = smb_buf(inbuf)+1; + Index = 0; + if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level) + while (p < (smb_buf(inbuf) + bcc)) + { + if (strequal(p,supported_protocols[protocol].proto_name)) + choice = Index; + Index++; + p += strlen(p) + 2; + } + if(choice != -1) + break; + } + + SSVAL(outbuf,smb_vwv0,choice); + if(choice != -1) { + extern fstring remote_proto; + fstrcpy(remote_proto,supported_protocols[protocol].short_name); + reload_services(True); + outsize = supported_protocols[protocol].proto_reply_fn(outbuf); + DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); + } + else { + DEBUG(0,("No protocol supported !\n")); + } + SSVAL(outbuf,smb_vwv0,choice); + + DEBUG( 5, ( "negprot index=%d\n", choice ) ); + + return(outsize); +} + diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a293075741..ccb830637d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -65,8 +65,6 @@ extern int dcelogin_atmost_once; */ extern DOM_SID global_machine_sid; -extern int Protocol; - /* * Size of data we can send to client. Set * by the client for all protocols above CORE. @@ -100,13 +98,6 @@ extern int extra_time_offset; extern pstring myhostname; -/* for readability... */ -#define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0) -#define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0) -#define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0) -#define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0) -#define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0) - /**************************************************************************** when exiting, take the whole family ****************************************************************************/ @@ -1988,97 +1979,6 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); unlock_share_entry( conn, dev, inode, token); } -/**************************************************************************** -seek a file. Try to avoid the seek if possible -****************************************************************************/ -int seek_file(files_struct *fsp,uint32 pos) -{ - uint32 offset = 0; - - if (fsp->print_file && lp_postscript(fsp->conn->service)) - offset = 3; - - fsp->pos = (int)(lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); - return(fsp->pos); -} - -/**************************************************************************** -read from a file -****************************************************************************/ -int read_file(files_struct *fsp,char *data,uint32 pos,int n) -{ - int ret=0,readret; - -#if USE_READ_PREDICTION - if (!fsp->can_write) - { - ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); - - data += ret; - n -= ret; - pos += ret; - } -#endif - -#if WITH_MMAP - if (fsp->mmap_ptr) - { - int num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; - num = MIN(n,num); - if (num > 0) - { - memcpy(data,fsp->mmap_ptr+pos,num); - data += num; - pos += num; - n -= num; - ret += num; - } - } -#endif - - if (n <= 0) - return(ret); - - if (seek_file(fsp,pos) != pos) - { - DEBUG(3,("Failed to seek to %d\n",pos)); - return(ret); - } - - if (n > 0) { - readret = read(fsp->fd_ptr->fd,data,n); - if (readret > 0) ret += readret; - } - - return(ret); -} - - -/**************************************************************************** -write to a file -****************************************************************************/ -int write_file(files_struct *fsp,char *data,int n) -{ - - if (!fsp->can_write) { - errno = EPERM; - return(0); - } - - if (!fsp->modified) { - struct stat st; - fsp->modified = True; - if (fstat(fsp->fd_ptr->fd,&st) == 0) { - int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); - if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { - dos_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); - } - } - } - - return(write_data(fsp->fd_ptr->fd,data,n)); -} - /**************************************************************************** load parameters specific to a connection/service @@ -3657,391 +3557,6 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) } -/**************************************************************************** -reply for the core protocol -****************************************************************************/ -int reply_corep(char *outbuf) -{ - int outsize = set_message(outbuf,1,0,True); - - Protocol = PROTOCOL_CORE; - - return outsize; -} - - -/**************************************************************************** -reply for the coreplus protocol -****************************************************************************/ -int reply_coreplus(char *outbuf) -{ - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int outsize = set_message(outbuf,13,0,True); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support - readbraw and writebraw (possibly) */ - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */ - - Protocol = PROTOCOL_COREPLUS; - - return outsize; -} - - -/**************************************************************************** -reply for the lanman 1.0 protocol -****************************************************************************/ -int reply_lanman1(char *outbuf) -{ - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int secword=0; - BOOL doencrypt = SMBENCRYPT(); - time_t t = time(NULL); - - if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; - - set_message(outbuf,13,doencrypt?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); - /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) - generate_next_challenge(smb_buf(outbuf)); - - Protocol = PROTOCOL_LANMAN1; - - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support - readbraw writebraw (possibly) */ - SIVAL(outbuf,smb_vwv6,getpid()); - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); - - put_dos_date(outbuf,smb_vwv8,t); - - return (smb_len(outbuf)+4); -} - - -/**************************************************************************** -reply for the lanman 2.0 protocol -****************************************************************************/ -int reply_lanman2(char *outbuf) -{ - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int secword=0; - BOOL doencrypt = SMBENCRYPT(); - time_t t = time(NULL); - struct cli_state *cli = NULL; - char cryptkey[8]; - char crypt_len = 0; - - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { - DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); - } - - if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; - - if (doencrypt) { - crypt_len = 8; - if (!cli) { - generate_next_challenge(cryptkey); - } else { - memcpy(cryptkey, cli->cryptkey, 8); - set_challenge(cli->cryptkey); - } - } - - set_message(outbuf,13,crypt_len,True); - SSVAL(outbuf,smb_vwv1,secword); - SIVAL(outbuf,smb_vwv6,getpid()); - if (doencrypt) - memcpy(smb_buf(outbuf), cryptkey, 8); - - Protocol = PROTOCOL_LANMAN2; - - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); - put_dos_date(outbuf,smb_vwv8,t); - - return (smb_len(outbuf)+4); -} - - -/**************************************************************************** -reply for the nt protocol -****************************************************************************/ -int reply_nt1(char *outbuf) -{ - /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS |CAP_NT_SMBS; - -/* - other valid capabilities which we may support at some time... - CAP_LARGE_FILES| - CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; - */ - - int secword=0; - BOOL doencrypt = SMBENCRYPT(); - time_t t = time(NULL); - int data_len; - struct cli_state *cli = NULL; - char cryptkey[8]; - char crypt_len = 0; - - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { - DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); - } - - if (doencrypt) { - crypt_len = 8; - if (!cli) { - generate_next_challenge(cryptkey); - } else { - memcpy(cryptkey, cli->cryptkey, 8); - set_challenge(cli->cryptkey); - } - } - - if (lp_readraw() && lp_writeraw()) { - capabilities |= CAP_RAW_MODE; - } - - if (lp_security() >= SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; - - /* decide where (if) to put the encryption challenge, and - follow it with the OEM'd domain name - */ - data_len = crypt_len + strlen(global_myworkgroup) + 1; - - set_message(outbuf,17,data_len,True); - pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); - - CVAL(outbuf,smb_vwv1) = secword; - SSVALS(outbuf,smb_vwv16+1,crypt_len); - if (doencrypt) - memcpy(smb_buf(outbuf), cryptkey, 8); - - Protocol = PROTOCOL_NT1; - - SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ - SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ - SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ - SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ - SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ - SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ - put_long_date(outbuf+smb_vwv11+1,t); - SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); - SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */ - - return (smb_len(outbuf)+4); -} - -/* these are the protocol lists used for auto architecture detection: - -WinNT 3.51: -protocol [PC NETWORK PROGRAM 1.0] -protocol [XENIX CORE] -protocol [MICROSOFT NETWORKS 1.03] -protocol [LANMAN1.0] -protocol [Windows for Workgroups 3.1a] -protocol [LM1.2X002] -protocol [LANMAN2.1] -protocol [NT LM 0.12] - -Win95: -protocol [PC NETWORK PROGRAM 1.0] -protocol [XENIX CORE] -protocol [MICROSOFT NETWORKS 1.03] -protocol [LANMAN1.0] -protocol [Windows for Workgroups 3.1a] -protocol [LM1.2X002] -protocol [LANMAN2.1] -protocol [NT LM 0.12] - -OS/2: -protocol [PC NETWORK PROGRAM 1.0] -protocol [XENIX CORE] -protocol [LANMAN1.0] -protocol [LM1.2X002] -protocol [LANMAN2.1] -*/ - -/* - * Modified to recognize the architecture of the remote machine better. - * - * This appears to be the matrix of which protocol is used by which - * MS product. - Protocol WfWg Win95 WinNT OS/2 - PC NETWORK PROGRAM 1.0 1 1 1 1 - XENIX CORE 2 2 - MICROSOFT NETWORKS 3.0 2 2 - DOS LM1.2X002 3 3 - MICROSOFT NETWORKS 1.03 3 - DOS LANMAN2.1 4 4 - LANMAN1.0 4 3 - Windows for Workgroups 3.1a 5 5 5 - LM1.2X002 6 4 - LANMAN2.1 7 5 - NT LM 0.12 6 8 - * - * tim@fsg.com 09/29/95 - */ - -#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */ -#define ARCH_WIN95 0x2 -#define ARCH_OS2 0xC /* Again OS/2 is like NT */ -#define ARCH_WINNT 0x8 -#define ARCH_SAMBA 0x10 - -#define ARCH_ALL 0x1F - -/* List of supported protocols, most desired first */ -struct { - char *proto_name; - char *short_name; - int (*proto_reply_fn)(char *); - int protocol_level; -} supported_protocols[] = { - {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, - {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, - {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, - {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, - {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS}, - {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE}, - {NULL,NULL}, -}; - - -/**************************************************************************** - reply to a negprot -****************************************************************************/ -static int reply_negprot(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, - int dum_buffsize) -{ - int outsize = set_message(outbuf,1,0,True); - int Index=0; - int choice= -1; - int protocol; - char *p; - int bcc = SVAL(smb_buf(inbuf),-2); - int arch = ARCH_ALL; - - p = smb_buf(inbuf)+1; - while (p < (smb_buf(inbuf) + bcc)) - { - Index++; - DEBUG(3,("Requested protocol [%s]\n",p)); - if (strcsequal(p,"Windows for Workgroups 3.1a")) - arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT ); - else if (strcsequal(p,"DOS LM1.2X002")) - arch &= ( ARCH_WFWG | ARCH_WIN95 ); - else if (strcsequal(p,"DOS LANMAN2.1")) - arch &= ( ARCH_WFWG | ARCH_WIN95 ); - else if (strcsequal(p,"NT LM 0.12")) - arch &= ( ARCH_WIN95 | ARCH_WINNT ); - else if (strcsequal(p,"LANMAN2.1")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); - else if (strcsequal(p,"LM1.2X002")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); - else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) - arch &= ARCH_WINNT; - else if (strcsequal(p,"XENIX CORE")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); - else if (strcsequal(p,"Samba")) { - arch = ARCH_SAMBA; - break; - } - - p += strlen(p) + 2; - } - - switch ( arch ) { - case ARCH_SAMBA: - set_remote_arch(RA_SAMBA); - break; - case ARCH_WFWG: - set_remote_arch(RA_WFWG); - break; - case ARCH_WIN95: - set_remote_arch(RA_WIN95); - break; - case ARCH_WINNT: - set_remote_arch(RA_WINNT); - break; - case ARCH_OS2: - set_remote_arch(RA_OS2); - break; - default: - set_remote_arch(RA_UNKNOWN); - break; - } - - /* possibly reload - change of architecture */ - reload_services(True); - - /* a special case to stop password server loops */ - if (Index == 1 && strequal(remote_machine,myhostname) && - (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN)) - exit_server("Password server loop!"); - - /* Check for protocols, most desirable first */ - for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) - { - p = smb_buf(inbuf)+1; - Index = 0; - if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level) - while (p < (smb_buf(inbuf) + bcc)) - { - if (strequal(p,supported_protocols[protocol].proto_name)) - choice = Index; - Index++; - p += strlen(p) + 2; - } - if(choice != -1) - break; - } - - SSVAL(outbuf,smb_vwv0,choice); - if(choice != -1) { - extern fstring remote_proto; - fstrcpy(remote_proto,supported_protocols[protocol].short_name); - reload_services(True); - outsize = supported_protocols[protocol].proto_reply_fn(outbuf); - DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); - } - else { - DEBUG(0,("No protocol supported !\n")); - } - SSVAL(outbuf,smb_vwv0,choice); - - DEBUG( 5, ( "negprot index=%d\n", choice ) ); - - return(outsize); -} - /**************************************************************************** close a cnum -- cgit From 0922615405838af7430ef39490ee578711866320 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 07:40:06 +0000 Subject: more splitting of server.c created dosmode.c and filename.c (This used to be commit 534a90ca44641417c21f6ed6d4b94b1de60f808d) --- source3/smbd/dosmode.c | 202 +++++++++++++++++ source3/smbd/fileio.c | 12 + source3/smbd/filename.c | 380 ++++++++++++++++++++++++++++++++ source3/smbd/server.c | 573 ++---------------------------------------------- 4 files changed, 610 insertions(+), 557 deletions(-) create mode 100644 source3/smbd/dosmode.c create mode 100644 source3/smbd/filename.c (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c new file mode 100644 index 0000000000..c1af18d80b --- /dev/null +++ b/source3/smbd/dosmode.c @@ -0,0 +1,202 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + dos mode handling functions + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + +/**************************************************************************** + change a dos mode to a unix mode + base permission for files: + everybody gets read bit set + dos readonly is represented in unix by removing everyone's write bit + dos archive is represented in unix by the user's execute bit + dos system is represented in unix by the group's execute bit + dos hidden is represented in unix by the other's execute bit + Then apply create mask, + then add force bits. + base permission for directories: + dos directory is represented in unix by unix's dir bit and the exec bit + Then apply create mask, + then add force bits. +****************************************************************************/ +mode_t unix_mode(connection_struct *conn,int dosmode) +{ + mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); + + if ( !IS_DOS_READONLY(dosmode) ) + result |= (S_IWUSR | S_IWGRP | S_IWOTH); + + if (IS_DOS_DIR(dosmode)) { + /* We never make directories read only for the owner as under DOS a user + can always create a file in a read-only directory. */ + result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); + /* Apply directory mask */ + result &= lp_dir_mode(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_dir_mode(SNUM(conn)); + } else { + if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode)) + result |= S_IXUSR; + + if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode)) + result |= S_IXGRP; + + if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode)) + result |= S_IXOTH; + + /* Apply mode mask */ + result &= lp_create_mode(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_create_mode(SNUM(conn)); + } + return(result); +} + + +/**************************************************************************** + change a unix mode to a dos mode +****************************************************************************/ +int dos_mode(connection_struct *conn,char *path,struct stat *sbuf) +{ + int result = 0; + extern struct current_user current_user; + + DEBUG(8,("dos_mode: %s\n", path)); + + if (CAN_WRITE(conn) && !lp_alternate_permissions(SNUM(conn))) { + if (!((sbuf->st_mode & S_IWOTH) || + conn->admin_user || + ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) || + ((sbuf->st_mode & S_IWGRP) && + in_group(sbuf->st_gid,current_user.gid, + current_user.ngroups,current_user.groups)))) + result |= aRONLY; + } else { + if ((sbuf->st_mode & S_IWUSR) == 0) + result |= aRONLY; + } + + if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) + result |= aARCH; + + if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) + result |= aSYSTEM; + + if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) + result |= aHIDDEN; + + if (S_ISDIR(sbuf->st_mode)) + result = aDIR | (result & aRONLY); + +#ifdef S_ISLNK +#if LINKS_READ_ONLY + if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) + result |= aRONLY; +#endif +#endif + + /* hide files with a name starting with a . */ + if (lp_hide_dot_files(SNUM(conn))) + { + char *p = strrchr(path,'/'); + if (p) + p++; + else + p = path; + + if (p[0] == '.' && p[1] != '.' && p[1] != 0) + result |= aHIDDEN; + } + + /* Optimization : Only call is_hidden_path if it's not already + hidden. */ + if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) + { + result |= aHIDDEN; + } + + DEBUG(8,("dos_mode returning ")); + + if (result & aHIDDEN) DEBUG(8, ("h")); + if (result & aRONLY ) DEBUG(8, ("r")); + if (result & aSYSTEM) DEBUG(8, ("s")); + if (result & aDIR ) DEBUG(8, ("d")); + if (result & aARCH ) DEBUG(8, ("a")); + + DEBUG(8,("\n")); + + return(result); +} + +/******************************************************************* +chmod a file - but preserve some bits +********************************************************************/ +int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st) +{ + struct stat st1; + int mask=0; + int tmp; + int unixmode; + + if (!st) { + st = &st1; + if (sys_stat(fname,st)) return(-1); + } + + if (S_ISDIR(st->st_mode)) dosmode |= aDIR; + + if (dos_mode(conn,fname,st) == dosmode) return(0); + + unixmode = unix_mode(conn,dosmode); + + /* preserve the s bits */ + mask |= (S_ISUID | S_ISGID); + + /* preserve the t bit */ +#ifdef S_ISVTX + mask |= S_ISVTX; +#endif + + /* possibly preserve the x bits */ + if (!MAP_ARCHIVE(conn)) mask |= S_IXUSR; + if (!MAP_SYSTEM(conn)) mask |= S_IXGRP; + if (!MAP_HIDDEN(conn)) mask |= S_IXOTH; + + unixmode |= (st->st_mode & mask); + + /* if we previously had any r bits set then leave them alone */ + if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { + unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH); + unixmode |= tmp; + } + + /* if we previously had any w bits set then leave them alone + if the new mode is not rdonly */ + if (!IS_DOS_READONLY(dosmode) && + (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) { + unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); + unixmode |= tmp; + } + + return(sys_chmod(fname,unixmode)); +} + diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index edf87f3e7b..971d309ff9 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -115,3 +115,15 @@ int write_file(files_struct *fsp,char *data,int n) return(write_data(fsp->fd_ptr->fd,data,n)); } + +/******************************************************************* +sync a file +********************************************************************/ +void sync_file(connection_struct *conn, files_struct *fsp) +{ +#ifdef HAVE_FSYNC + if(lp_strict_sync(SNUM(conn))) + fsync(fsp->fd_ptr->fd); +#endif +} + diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c new file mode 100644 index 0000000000..a6a9e7e7f0 --- /dev/null +++ b/source3/smbd/filename.c @@ -0,0 +1,380 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + filename handling routines + Copyright (C) Andrew Tridgell 1992-1998 + + 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; +extern BOOL case_sensitive; +extern BOOL case_preserve; +extern BOOL short_case_preserve; +extern fstring remote_machine; +extern BOOL use_mangled_map; + +/**************************************************************************** +check if two filenames are equal + +this needs to be careful about whether we are case sensitive +****************************************************************************/ +BOOL fname_equal(char *name1, char *name2) +{ + int l1 = strlen(name1); + int l2 = strlen(name2); + + /* handle filenames ending in a single dot */ + if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot()) + { + BOOL ret; + name1[l1-1] = 0; + ret = fname_equal(name1,name2); + name1[l1-1] = '.'; + return(ret); + } + + if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot()) + { + BOOL ret; + name2[l2-1] = 0; + ret = fname_equal(name1,name2); + name2[l2-1] = '.'; + return(ret); + } + + /* now normal filename handling */ + if (case_sensitive) + return(strcmp(name1,name2) == 0); + + return(strequal(name1,name2)); +} + + +/**************************************************************************** +mangle the 2nd name and check if it is then equal to the first name +****************************************************************************/ +BOOL mangled_equal(char *name1, char *name2) +{ + pstring tmpname; + + if (is_8_3(name2, True)) + return(False); + + pstrcpy(tmpname,name2); + mangle_name_83(tmpname,sizeof(tmpname)); + + return(strequal(name1,tmpname)); +} + +/**************************************************************************** +This routine is called to convert names from the dos namespace to unix +namespace. It needs to handle any case conversions, mangling, format +changes etc. + +We assume that we have already done a chdir() to the right "root" directory +for this service. + +The function will return False if some part of the name except for the last +part cannot be resolved + +If the saved_last_component != 0, then the unmodified last component +of the pathname is returned there. This is used in an exceptional +case in reply_mv (so far). If saved_last_component == 0 then nothing +is returned there. + +The bad_path arg is set to True if the filename walk failed. This is +used to pick the correct error code to return between ENOENT and ENOTDIR +as Windows applications depend on ERRbadpath being returned if a component +of a pathname does not exist. +****************************************************************************/ +BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) +{ + struct stat st; + char *start, *end; + pstring dirpath; + int saved_errno; + + *dirpath = 0; + *bad_path = False; + + if(saved_last_component) + *saved_last_component = 0; + + /* convert to basic unix format - removing \ chars and cleaning it up */ + unix_format(name); + unix_clean_name(name); + + /* names must be relative to the root of the service - trim any leading /. + also trim trailing /'s */ + trim_string(name,"/","/"); + + /* + * Ensure saved_last_component is valid even if file exists. + */ + if(saved_last_component) { + end = strrchr(name, '/'); + if(end) + pstrcpy(saved_last_component, end + 1); + else + pstrcpy(saved_last_component, name); + } + + if (!case_sensitive && + (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) + strnorm(name); + + /* check if it's a printer file */ + if (conn->printer) + { + if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) + { + char *s; + fstring name2; + slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); + /* sanitise the name */ + for (s=name2 ; *s ; s++) + if (!issafe(*s)) *s = '_'; + pstrcpy(name,(char *)mktemp(name2)); + } + return(True); + } + + /* stat the name - if it exists then we are all done! */ + if (sys_stat(name,&st) == 0) + return(True); + + saved_errno = errno; + + DEBUG(5,("unix_convert(%s)\n",name)); + + /* a special case - if we don't have any mangling chars and are case + sensitive then searching won't help */ + if (case_sensitive && !is_mangled(name) && + !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) + return(False); + + /* now we need to recursively match the name against the real + directory structure */ + + start = name; + while (strncmp(start,"./",2) == 0) + start += 2; + + /* now match each part of the path name separately, trying the names + as is first, then trying to scan the directory for matching names */ + for (;start;start = (end?end+1:(char *)NULL)) + { + /* pinpoint the end of this section of the filename */ + end = strchr(start, '/'); + + /* chop the name at this point */ + if (end) *end = 0; + + if(saved_last_component != 0) + pstrcpy(saved_last_component, end ? end + 1 : start); + + /* check if the name exists up to this point */ + if (sys_stat(name, &st) == 0) + { + /* it exists. it must either be a directory or this must be + the last part of the path for it to be OK */ + if (end && !(st.st_mode & S_IFDIR)) + { + /* an intermediate part of the name isn't a directory */ + DEBUG(5,("Not a dir %s\n",start)); + *end = '/'; + return(False); + } + } + else + { + pstring rest; + + *rest = 0; + + /* remember the rest of the pathname so it can be restored + later */ + if (end) pstrcpy(rest,end+1); + + /* try to find this part of the path in the directory */ + if (strchr(start,'?') || strchr(start,'*') || + !scan_directory(dirpath, start, conn, end?True:False)) + { + if (end) + { + /* an intermediate part of the name can't be found */ + DEBUG(5,("Intermediate not found %s\n",start)); + *end = '/'; + /* We need to return the fact that the intermediate + name resolution failed. This is used to return an + error of ERRbadpath rather than ERRbadfile. Some + Windows applications depend on the difference between + these two errors. + */ + *bad_path = True; + return(False); + } + + /* just the last part of the name doesn't exist */ + /* we may need to strupper() or strlower() it in case + this conversion is being used for file creation + purposes */ + /* if the filename is of mixed case then don't normalise it */ + if (!case_preserve && + (!strhasupper(start) || !strhaslower(start))) + strnorm(start); + + /* check on the mangled stack to see if we can recover the + base of the filename */ + if (is_mangled(start)) + check_mangled_cache( start ); + + DEBUG(5,("New file %s\n",start)); + return(True); + } + + /* restore the rest of the string */ + if (end) + { + pstrcpy(start+strlen(start)+1,rest); + end = start + strlen(start); + } + } + + /* add to the dirpath that we have resolved so far */ + if (*dirpath) pstrcat(dirpath,"/"); + pstrcat(dirpath,start); + + /* restore the / that we wiped out earlier */ + if (end) *end = '/'; + } + + /* the name has been resolved */ + DEBUG(5,("conversion finished %s\n",name)); + return(True); +} + + +/**************************************************************************** +check a filename - possibly caling reducename + +This is called by every routine before it allows an operation on a filename. +It does any final confirmation necessary to ensure that the filename is +a valid one for the user to access. +****************************************************************************/ +BOOL check_name(char *name,connection_struct *conn) +{ + BOOL ret; + + errno = 0; + + if (IS_VETO_PATH(conn, name)) { + DEBUG(5,("file path name %s vetoed\n",name)); + return(0); + } + + ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn))); + + /* Check if we are allowing users to follow symlinks */ + /* Patch from David Clerc + University of Geneva */ + +#ifdef S_ISLNK + if (!lp_symlinks(SNUM(conn))) + { + struct stat statbuf; + if ( (sys_lstat(name,&statbuf) != -1) && + (S_ISLNK(statbuf.st_mode)) ) + { + DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); + ret=0; + } + } +#endif + + if (!ret) + DEBUG(5,("check_name on %s failed\n",name)); + + return(ret); +} + + +/**************************************************************************** +scan a directory to find a filename, matching without case sensitivity + +If the name looks like a mangled name then try via the mangling functions +****************************************************************************/ +BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) +{ + void *cur_dir; + char *dname; + BOOL mangled; + pstring name2; + + mangled = is_mangled(name); + + /* handle null paths */ + if (*path == 0) + path = "."; + + if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { + pstrcpy(name, dname); + return(True); + } + + /* + * The incoming name can be mangled, and if we de-mangle it + * here it will not compare correctly against the filename (name2) + * read from the directory and then mangled by the name_map_mangle() + * call. We need to mangle both names or neither. + * (JRA). + */ + if (mangled) + mangled = !check_mangled_cache( name ); + + /* open the directory */ + if (!(cur_dir = OpenDir(conn, path, True))) + { + DEBUG(3,("scan dir didn't open dir [%s]\n",path)); + return(False); + } + + /* now scan for matching names */ + while ((dname = ReadDirName(cur_dir))) + { + if (*dname == '.' && + (strequal(dname,".") || strequal(dname,".."))) + continue; + + pstrcpy(name2,dname); + if (!name_map_mangle(name2,False,SNUM(conn))) continue; + + if ((mangled && mangled_equal(name,name2)) + || fname_equal(name, name2)) + { + /* we've found the file, change it's name and return */ + if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); + pstrcpy(name, dname); + CloseDir(cur_dir); + return(True); + } + } + + CloseDir(cur_dir); + return(False); +} diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ccb830637d..d81d80047b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -114,188 +114,10 @@ void killkids(void) if(am_parent) kill(0,SIGTERM); } -/**************************************************************************** - change a dos mode to a unix mode - base permission for files: - everybody gets read bit set - dos readonly is represented in unix by removing everyone's write bit - dos archive is represented in unix by the user's execute bit - dos system is represented in unix by the group's execute bit - dos hidden is represented in unix by the other's execute bit - Then apply create mask, - then add force bits. - base permission for directories: - dos directory is represented in unix by unix's dir bit and the exec bit - Then apply create mask, - then add force bits. -****************************************************************************/ -mode_t unix_mode(connection_struct *conn,int dosmode) -{ - mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); - - if ( !IS_DOS_READONLY(dosmode) ) - result |= (S_IWUSR | S_IWGRP | S_IWOTH); - - if (IS_DOS_DIR(dosmode)) { - /* We never make directories read only for the owner as under DOS a user - can always create a file in a read-only directory. */ - result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); - /* Apply directory mask */ - result &= lp_dir_mode(SNUM(conn)); - /* Add in force bits */ - result |= lp_force_dir_mode(SNUM(conn)); - } else { - if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode)) - result |= S_IXUSR; - - if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode)) - result |= S_IXGRP; - - if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode)) - result |= S_IXOTH; - - /* Apply mode mask */ - result &= lp_create_mode(SNUM(conn)); - /* Add in force bits */ - result |= lp_force_create_mode(SNUM(conn)); - } - return(result); -} - - -/**************************************************************************** - change a unix mode to a dos mode -****************************************************************************/ -int dos_mode(connection_struct *conn,char *path,struct stat *sbuf) -{ - int result = 0; - extern struct current_user current_user; - - DEBUG(8,("dos_mode: %s\n", path)); - - if (CAN_WRITE(conn) && !lp_alternate_permissions(SNUM(conn))) { - if (!((sbuf->st_mode & S_IWOTH) || - conn->admin_user || - ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) || - ((sbuf->st_mode & S_IWGRP) && - in_group(sbuf->st_gid,current_user.gid, - current_user.ngroups,current_user.groups)))) - result |= aRONLY; - } else { - if ((sbuf->st_mode & S_IWUSR) == 0) - result |= aRONLY; - } - - if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) - result |= aARCH; - - if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) - result |= aSYSTEM; - - if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) - result |= aHIDDEN; - - if (S_ISDIR(sbuf->st_mode)) - result = aDIR | (result & aRONLY); - -#ifdef S_ISLNK -#if LINKS_READ_ONLY - if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) - result |= aRONLY; -#endif -#endif - - /* hide files with a name starting with a . */ - if (lp_hide_dot_files(SNUM(conn))) - { - char *p = strrchr(path,'/'); - if (p) - p++; - else - p = path; - - if (p[0] == '.' && p[1] != '.' && p[1] != 0) - result |= aHIDDEN; - } - - /* Optimization : Only call is_hidden_path if it's not already - hidden. */ - if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) - { - result |= aHIDDEN; - } - - DEBUG(8,("dos_mode returning ")); - - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); - - DEBUG(8,("\n")); - - return(result); -} - -/******************************************************************* -chmod a file - but preserve some bits -********************************************************************/ -int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st) -{ - struct stat st1; - int mask=0; - int tmp; - int unixmode; - - if (!st) { - st = &st1; - if (sys_stat(fname,st)) return(-1); - } - - if (S_ISDIR(st->st_mode)) dosmode |= aDIR; - - if (dos_mode(conn,fname,st) == dosmode) return(0); - - unixmode = unix_mode(conn,dosmode); - - /* preserve the s bits */ - mask |= (S_ISUID | S_ISGID); - - /* preserve the t bit */ -#ifdef S_ISVTX - mask |= S_ISVTX; -#endif - - /* possibly preserve the x bits */ - if (!MAP_ARCHIVE(conn)) mask |= S_IXUSR; - if (!MAP_SYSTEM(conn)) mask |= S_IXGRP; - if (!MAP_HIDDEN(conn)) mask |= S_IXOTH; - - unixmode |= (st->st_mode & mask); - - /* if we previously had any r bits set then leave them alone */ - if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { - unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH); - unixmode |= tmp; - } - - /* if we previously had any w bits set then leave them alone - if the new mode is not rdonly */ - if (!IS_DOS_READONLY(dosmode) && - (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) { - unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); - unixmode |= tmp; - } - - return(sys_chmod(fname,unixmode)); -} - /******************************************************************* Wrapper around sys_utime that possibly allows DOS semantics rather than POSIX. *******************************************************************/ - int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) { extern struct current_user current_user; @@ -343,7 +165,6 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) /******************************************************************* Change a filetime - possibly allowing DOS semantics. *******************************************************************/ - BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) { struct utimbuf times; @@ -359,373 +180,6 @@ BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) return(True); } -/**************************************************************************** -check if two filenames are equal - -this needs to be careful about whether we are case sensitive -****************************************************************************/ -static BOOL fname_equal(char *name1, char *name2) -{ - int l1 = strlen(name1); - int l2 = strlen(name2); - - /* handle filenames ending in a single dot */ - if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name1[l1-1] = 0; - ret = fname_equal(name1,name2); - name1[l1-1] = '.'; - return(ret); - } - - if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name2[l2-1] = 0; - ret = fname_equal(name1,name2); - name2[l2-1] = '.'; - return(ret); - } - - /* now normal filename handling */ - if (case_sensitive) - return(strcmp(name1,name2) == 0); - - return(strequal(name1,name2)); -} - - -/**************************************************************************** -mangle the 2nd name and check if it is then equal to the first name -****************************************************************************/ -static BOOL mangled_equal(char *name1, char *name2) -{ - pstring tmpname; - - if (is_8_3(name2, True)) - return(False); - - pstrcpy(tmpname,name2); - mangle_name_83(tmpname,sizeof(tmpname)); - - return(strequal(name1,tmpname)); -} - - -/**************************************************************************** -scan a directory to find a filename, matching without case sensitivity - -If the name looks like a mangled name then try via the mangling functions -****************************************************************************/ -static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) -{ - void *cur_dir; - char *dname; - BOOL mangled; - pstring name2; - - mangled = is_mangled(name); - - /* handle null paths */ - if (*path == 0) - path = "."; - - if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { - pstrcpy(name, dname); - return(True); - } - - /* - * The incoming name can be mangled, and if we de-mangle it - * here it will not compare correctly against the filename (name2) - * read from the directory and then mangled by the name_map_mangle() - * call. We need to mangle both names or neither. - * (JRA). - */ - if (mangled) - mangled = !check_mangled_cache( name ); - - /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) - { - DEBUG(3,("scan dir didn't open dir [%s]\n",path)); - return(False); - } - - /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) - { - if (*dname == '.' && - (strequal(dname,".") || strequal(dname,".."))) - continue; - - pstrcpy(name2,dname); - if (!name_map_mangle(name2,False,SNUM(conn))) continue; - - if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, name2)) - { - /* we've found the file, change it's name and return */ - if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); - CloseDir(cur_dir); - return(True); - } - } - - CloseDir(cur_dir); - return(False); -} - -/**************************************************************************** -This routine is called to convert names from the dos namespace to unix -namespace. It needs to handle any case conversions, mangling, format -changes etc. - -We assume that we have already done a chdir() to the right "root" directory -for this service. - -The function will return False if some part of the name except for the last -part cannot be resolved - -If the saved_last_component != 0, then the unmodified last component -of the pathname is returned there. This is used in an exceptional -case in reply_mv (so far). If saved_last_component == 0 then nothing -is returned there. - -The bad_path arg is set to True if the filename walk failed. This is -used to pick the correct error code to return between ENOENT and ENOTDIR -as Windows applications depend on ERRbadpath being returned if a component -of a pathname does not exist. -****************************************************************************/ -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) -{ - struct stat st; - char *start, *end; - pstring dirpath; - int saved_errno; - - *dirpath = 0; - *bad_path = False; - - if(saved_last_component) - *saved_last_component = 0; - - /* convert to basic unix format - removing \ chars and cleaning it up */ - unix_format(name); - unix_clean_name(name); - - /* names must be relative to the root of the service - trim any leading /. - also trim trailing /'s */ - trim_string(name,"/","/"); - - /* - * Ensure saved_last_component is valid even if file exists. - */ - if(saved_last_component) { - end = strrchr(name, '/'); - if(end) - pstrcpy(saved_last_component, end + 1); - else - pstrcpy(saved_last_component, name); - } - - if (!case_sensitive && - (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) - strnorm(name); - - /* check if it's a printer file */ - if (conn->printer) - { - if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) - { - char *s; - fstring name2; - slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); - /* sanitise the name */ - for (s=name2 ; *s ; s++) - if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)mktemp(name2)); - } - return(True); - } - - /* stat the name - if it exists then we are all done! */ - if (sys_stat(name,&st) == 0) - return(True); - - saved_errno = errno; - - DEBUG(5,("unix_convert(%s)\n",name)); - - /* a special case - if we don't have any mangling chars and are case - sensitive then searching won't help */ - if (case_sensitive && !is_mangled(name) && - !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) - return(False); - - /* now we need to recursively match the name against the real - directory structure */ - - start = name; - while (strncmp(start,"./",2) == 0) - start += 2; - - /* now match each part of the path name separately, trying the names - as is first, then trying to scan the directory for matching names */ - for (;start;start = (end?end+1:(char *)NULL)) - { - /* pinpoint the end of this section of the filename */ - end = strchr(start, '/'); - - /* chop the name at this point */ - if (end) *end = 0; - - if(saved_last_component != 0) - pstrcpy(saved_last_component, end ? end + 1 : start); - - /* check if the name exists up to this point */ - if (sys_stat(name, &st) == 0) - { - /* it exists. it must either be a directory or this must be - the last part of the path for it to be OK */ - if (end && !(st.st_mode & S_IFDIR)) - { - /* an intermediate part of the name isn't a directory */ - DEBUG(5,("Not a dir %s\n",start)); - *end = '/'; - return(False); - } - } - else - { - pstring rest; - - *rest = 0; - - /* remember the rest of the pathname so it can be restored - later */ - if (end) pstrcpy(rest,end+1); - - /* try to find this part of the path in the directory */ - if (strchr(start,'?') || strchr(start,'*') || - !scan_directory(dirpath, start, conn, end?True:False)) - { - if (end) - { - /* an intermediate part of the name can't be found */ - DEBUG(5,("Intermediate not found %s\n",start)); - *end = '/'; - /* We need to return the fact that the intermediate - name resolution failed. This is used to return an - error of ERRbadpath rather than ERRbadfile. Some - Windows applications depend on the difference between - these two errors. - */ - *bad_path = True; - return(False); - } - - /* just the last part of the name doesn't exist */ - /* we may need to strupper() or strlower() it in case - this conversion is being used for file creation - purposes */ - /* if the filename is of mixed case then don't normalise it */ - if (!case_preserve && - (!strhasupper(start) || !strhaslower(start))) - strnorm(start); - - /* check on the mangled stack to see if we can recover the - base of the filename */ - if (is_mangled(start)) - check_mangled_cache( start ); - - DEBUG(5,("New file %s\n",start)); - return(True); - } - - /* restore the rest of the string */ - if (end) - { - pstrcpy(start+strlen(start)+1,rest); - end = start + strlen(start); - } - } - - /* add to the dirpath that we have resolved so far */ - if (*dirpath) pstrcat(dirpath,"/"); - pstrcat(dirpath,start); - - /* restore the / that we wiped out earlier */ - if (end) *end = '/'; - } - - /* the name has been resolved */ - DEBUG(5,("conversion finished %s\n",name)); - return(True); -} - - -/**************************************************************************** -check a filename - possibly caling reducename - -This is called by every routine before it allows an operation on a filename. -It does any final confirmation necessary to ensure that the filename is -a valid one for the user to access. -****************************************************************************/ -BOOL check_name(char *name,connection_struct *conn) -{ - BOOL ret; - - errno = 0; - - if (IS_VETO_PATH(conn, name)) { - DEBUG(5,("file path name %s vetoed\n",name)); - return(0); - } - - ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn))); - - /* Check if we are allowing users to follow symlinks */ - /* Patch from David Clerc - University of Geneva */ - -#ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) - { - struct stat statbuf; - if ( (sys_lstat(name,&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) - { - DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - ret=0; - } - } -#endif - - if (!ret) - DEBUG(5,("check_name on %s failed\n",name)); - - return(ret); -} - -/**************************************************************************** -check a filename - possibly caling reducename -****************************************************************************/ -static void check_for_pipe(char *fname) -{ - /* special case of pipe opens */ - char s[10]; - StrnCpy(s,fname,9); - strlower(s); - if (strstr(s,"pipe/")) - { - DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRaccess; - } -} /**************************************************************************** fd support routines - attempt to do a sys_open @@ -945,6 +399,22 @@ static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) return False; } +/**************************************************************************** +check a filename for the pipe string +****************************************************************************/ +static void check_for_pipe(char *fname) +{ + /* special case of pipe opens */ + char s[10]; + StrnCpy(s,fname,9); + strlower(s); + if (strstr(s,"pipe/")) { + DEBUG(3,("Rejecting named pipe open for %s\n",fname)); + unix_ERR_class = ERRSRV; + unix_ERR_code = ERRaccess; + } +} + /**************************************************************************** open a file ****************************************************************************/ @@ -1235,17 +705,6 @@ static void open_file(files_struct *fsp,connection_struct *conn, #endif } -/******************************************************************* -sync a file -********************************************************************/ -void sync_file(connection_struct *conn, files_struct *fsp) -{ -#ifdef HAVE_FSYNC - if(lp_strict_sync(SNUM(conn))) - fsync(fsp->fd_ptr->fd); -#endif -} - /**************************************************************************** run a file if it is a magic script ****************************************************************************/ -- cgit From c3effa8b599a6a0a2fe05487edc3a0d13e83d427 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 13:11:34 +0000 Subject: this completes the splitup of server.c. the splitup was done with an axe, not a scalpel, so there are some rough edges. I mostly wanted to get the general form right with fine tuning of what goes where to come later. Still, this is better than what we had before where server.c was a general repository for anything that didn't fit elsewhere. (This used to be commit a6d194886a4a5f7507fa37289ff96c1be56f14a6) --- source3/smbd/close.c | 170 +++ source3/smbd/dosmode.c | 68 + source3/smbd/error.c | 142 ++ source3/smbd/open.c | 1150 +++++++++++++++ source3/smbd/oplock.c | 639 +++++++++ source3/smbd/process.c | 810 +++++++++++ source3/smbd/server.c | 3714 +++--------------------------------------------- source3/smbd/service.c | 542 +++++++ 8 files changed, 3718 insertions(+), 3517 deletions(-) create mode 100644 source3/smbd/close.c create mode 100644 source3/smbd/error.c create mode 100644 source3/smbd/open.c create mode 100644 source3/smbd/oplock.c create mode 100644 source3/smbd/process.c create mode 100644 source3/smbd/service.c (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c new file mode 100644 index 0000000000..9bc0a89338 --- /dev/null +++ b/source3/smbd/close.c @@ -0,0 +1,170 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + file closing + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + +extern int32 global_oplocks_open; + + +/**************************************************************************** +run a file if it is a magic script +****************************************************************************/ +static void check_magic(files_struct *fsp,connection_struct *conn) +{ + if (!*lp_magicscript(SNUM(conn))) + return; + + DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); + + { + char *p; + if (!(p = strrchr(fsp->fsp_name,'/'))) + p = fsp->fsp_name; + else + p++; + + if (!strequal(lp_magicscript(SNUM(conn)),p)) + return; + } + + { + int ret; + pstring magic_output; + pstring fname; + pstrcpy(fname,fsp->fsp_name); + + if (*lp_magicoutput(SNUM(conn))) + pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); + else + slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); + + chmod(fname,0755); + ret = smbrun(fname,magic_output,False); + DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); + unlink(fname); + } +} + +/**************************************************************************** + Common code to close a file or a directory. +****************************************************************************/ +static void close_filestruct(files_struct *fsp) +{ + connection_struct *conn = fsp->conn; + + fsp->open = False; + fsp->is_directory = False; + + conn->num_files_open--; + if(fsp->wbmpx_ptr) { + free((char *)fsp->wbmpx_ptr); + fsp->wbmpx_ptr = NULL; + } + +#if WITH_MMAP + if(fsp->mmap_ptr) { + munmap(fsp->mmap_ptr,fsp->mmap_size); + fsp->mmap_ptr = NULL; + } +#endif +} + +/**************************************************************************** + Close a file - possibly invalidating the read prediction. + + If normal_close is 1 then this came from a normal SMBclose (or equivalent) + operation otherwise it came as the result of some other operation such as + the closing of the connection. In the latter case printing and + magic scripts are not run. +****************************************************************************/ +void close_file(files_struct *fsp, BOOL normal_close) +{ + uint32 dev = fsp->fd_ptr->dev; + uint32 inode = fsp->fd_ptr->inode; + int token; + connection_struct *conn = fsp->conn; + + close_filestruct(fsp); + +#if USE_READ_PREDICTION + invalidate_read_prediction(fsp->fd_ptr->fd); +#endif + + if (lp_share_modes(SNUM(conn))) { + lock_share_entry(conn, dev, inode, &token); + del_share_mode(token, fsp); + } + + fd_attempt_close(fsp->fd_ptr); + + if (lp_share_modes(SNUM(conn))) + unlock_share_entry(conn, dev, inode, token); + + /* NT uses smbclose to start a print - weird */ + if (normal_close && fsp->print_file) + print_file(conn, fsp); + + /* check for magic scripts */ + if (normal_close) { + check_magic(fsp,conn); + } + + if(fsp->granted_oplock == True) + global_oplocks_open--; + + fsp->sent_oplock_break = False; + + DEBUG(2,("%s closed file %s (numopen=%d)\n", + conn->user,fsp->fsp_name, + conn->num_files_open)); + + if (fsp->fsp_name) { + string_free(&fsp->fsp_name); + } + + file_free(fsp); +} + +/**************************************************************************** + Close a directory opened by an NT SMB call. +****************************************************************************/ + +void close_directory(files_struct *fsp) +{ + /* TODO - walk the list of pending + change notify requests and free + any pertaining to this fsp. */ + + remove_pending_change_notify_requests_by_fid(fsp); + + /* + * Do the code common to files and directories. + */ + close_filestruct(fsp); + + if (fsp->fsp_name) + string_free(&fsp->fsp_name); + + file_free(fsp); +} + diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index c1af18d80b..9db3e208b5 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -200,3 +200,71 @@ int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st) return(sys_chmod(fname,unixmode)); } + +/******************************************************************* +Wrapper around sys_utime that possibly allows DOS semantics rather +than POSIX. +*******************************************************************/ +int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) +{ + extern struct current_user current_user; + struct stat sb; + int ret = -1; + + errno = 0; + + if(sys_utime(fname, times) == 0) + return 0; + + if((errno != EPERM) && (errno != EACCES)) + return -1; + + if(!lp_dos_filetimes(SNUM(conn))) + return -1; + + /* We have permission (given by the Samba admin) to + break POSIX semantics and allow a user to change + the time on a file they don't own but can write to + (as DOS does). + */ + + if(sys_stat(fname,&sb) != 0) + return -1; + + /* Check if we have write access. */ + if (CAN_WRITE(conn)) { + if (((sb.st_mode & S_IWOTH) || + conn->admin_user || + ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || + ((sb.st_mode & S_IWGRP) && + in_group(sb.st_gid,current_user.gid, + current_user.ngroups,current_user.groups)))) { + /* We are allowed to become root and change the filetime. */ + become_root(False); + ret = sys_utime(fname, times); + unbecome_root(False); + } + } + + return ret; +} + +/******************************************************************* +Change a filetime - possibly allowing DOS semantics. +*******************************************************************/ +BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) +{ + struct utimbuf times; + + if (null_mtime(mtime)) return(True); + + times.modtime = times.actime = mtime; + + if (file_utime(conn, fname, ×)) { + DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); + } + + return(True); +} + + diff --git a/source3/smbd/error.c b/source3/smbd/error.c new file mode 100644 index 0000000000..ea23d8b28d --- /dev/null +++ b/source3/smbd/error.c @@ -0,0 +1,142 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + error packet handling + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + + +/**************************************************************************** + create an error packet from a cached error. +****************************************************************************/ +int cached_error_packet(char *inbuf,char *outbuf,files_struct *fsp,int line) +{ + write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; + + int32 eclass = wbmpx->wr_errclass; + int32 err = wbmpx->wr_error; + + /* We can now delete the auxiliary struct */ + free((char *)wbmpx); + fsp->wbmpx_ptr = NULL; + return error_packet(inbuf,outbuf,eclass,err,line); +} + + +struct +{ + int unixerror; + int smbclass; + int smbcode; +} unix_smb_errmap[] = +{ + {EPERM,ERRDOS,ERRnoaccess}, + {EACCES,ERRDOS,ERRnoaccess}, + {ENOENT,ERRDOS,ERRbadfile}, + {ENOTDIR,ERRDOS,ERRbadpath}, + {EIO,ERRHRD,ERRgeneral}, + {EBADF,ERRSRV,ERRsrverror}, + {EINVAL,ERRSRV,ERRsrverror}, + {EEXIST,ERRDOS,ERRfilexists}, + {ENFILE,ERRDOS,ERRnofids}, + {EMFILE,ERRDOS,ERRnofids}, + {ENOSPC,ERRHRD,ERRdiskfull}, +#ifdef EDQUOT + {EDQUOT,ERRHRD,ERRdiskfull}, +#endif +#ifdef ENOTEMPTY + {ENOTEMPTY,ERRDOS,ERRnoaccess}, +#endif +#ifdef EXDEV + {EXDEV,ERRDOS,ERRdiffdevice}, +#endif + {EROFS,ERRHRD,ERRnowrite}, + {0,0,0} +}; + +/**************************************************************************** + create an error packet from errno +****************************************************************************/ +int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line) +{ + int eclass=def_class; + int ecode=def_code; + int i=0; + + if (unix_ERR_class != SMB_SUCCESS) + { + eclass = unix_ERR_class; + ecode = unix_ERR_code; + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + } + else + { + while (unix_smb_errmap[i].smbclass != 0) + { + if (unix_smb_errmap[i].unixerror == errno) + { + eclass = unix_smb_errmap[i].smbclass; + ecode = unix_smb_errmap[i].smbcode; + break; + } + i++; + } + } + + return(error_packet(inbuf,outbuf,eclass,ecode,line)); +} + + +/**************************************************************************** + create an error packet. Normally called using the ERROR() macro +****************************************************************************/ +int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line) +{ + int outsize = set_message(outbuf,0,0,True); + int cmd = CVAL(inbuf,smb_com); + int flgs2 = SVAL(outbuf,smb_flg2); + + if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) + { + SIVAL(outbuf,smb_rcls,error_code); + + DEBUG( 3, ( "32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", + line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf) ) ); + } + else + { + CVAL(outbuf,smb_rcls) = error_class; + SSVAL(outbuf,smb_err,error_code); + DEBUG( 3, ( "error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + line, + (int)CVAL(inbuf,smb_com), + smb_fn_name(CVAL(inbuf,smb_com)), + error_class, + error_code ) ); + + } + + if (errno != 0) + DEBUG(3,("error string = %s\n",strerror(errno))); + + return(outsize); +} diff --git a/source3/smbd/open.c b/source3/smbd/open.c new file mode 100644 index 0000000000..311eac07e5 --- /dev/null +++ b/source3/smbd/open.c @@ -0,0 +1,1150 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + file opening and share modes + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + +extern pstring sesssetup_user; +extern int global_oplocks_open; +extern uint16 oplock_port; + + +/**************************************************************************** +fd support routines - attempt to do a sys_open +****************************************************************************/ +static int fd_attempt_open(char *fname, int flags, int mode) +{ + int fd = sys_open(fname,flags,mode); + + /* Fix for files ending in '.' */ + if((fd == -1) && (errno == ENOENT) && + (strchr(fname,'.')==NULL)) + { + pstrcat(fname,"."); + fd = sys_open(fname,flags,mode); + } + +#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) + if ((fd == -1) && (errno == ENAMETOOLONG)) + { + int max_len; + char *p = strrchr(fname, '/'); + + if (p == fname) /* name is "/xxx" */ + { + max_len = pathconf("/", _PC_NAME_MAX); + p++; + } + else if ((p == NULL) || (p == fname)) + { + p = fname; + max_len = pathconf(".", _PC_NAME_MAX); + } + else + { + *p = '\0'; + max_len = pathconf(fname, _PC_NAME_MAX); + *p = '/'; + p++; + } + if (strlen(p) > max_len) + { + char tmp = p[max_len]; + + p[max_len] = '\0'; + if ((fd = sys_open(fname,flags,mode)) == -1) + p[max_len] = tmp; + } + } +#endif + return fd; +} + +/**************************************************************************** +Cache a uid_t currently with this file open. This is an optimization only +used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) + return; + fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u; +} + +/**************************************************************************** +Remove a uid_t that currently has this file open. This is an optimization only +used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + int i; + for(i = 0; i < fd_ptr->uid_cache_count; i++) + if(fd_ptr->uid_users_cache[i] == u) { + if(i < (fd_ptr->uid_cache_count-1)) + memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1], + sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) ); + fd_ptr->uid_cache_count--; + } + return; +} + +/**************************************************************************** +Check if a uid_t that currently has this file open is present. This is an +optimization only used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + int i; + for(i = 0; i < fd_ptr->uid_cache_count; i++) + if(fd_ptr->uid_users_cache[i] == u) + return True; + return False; +} + + +/**************************************************************************** +fd support routines - attempt to re-open an already open fd as O_RDWR. +Save the already open fd (we cannot close due to POSIX file locking braindamage. +****************************************************************************/ +static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) +{ + int fd = sys_open( fname, O_RDWR, mode); + + if(fd == -1) + return; + + if(fd_ptr->real_open_flags == O_RDONLY) + fd_ptr->fd_readonly = fd_ptr->fd; + if(fd_ptr->real_open_flags == O_WRONLY) + fd_ptr->fd_writeonly = fd_ptr->fd; + + fd_ptr->fd = fd; + fd_ptr->real_open_flags = O_RDWR; +} + +/**************************************************************************** +fd support routines - attempt to close the file referenced by this fd. +Decrements the ref_count and returns it. +****************************************************************************/ +int fd_attempt_close(file_fd_struct *fd_ptr) +{ + extern struct current_user current_user; + + DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", + fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, + fd_ptr->real_open_flags, + fd_ptr->ref_count)); + if(fd_ptr->ref_count > 0) { + fd_ptr->ref_count--; + if(fd_ptr->ref_count == 0) { + if(fd_ptr->fd != -1) + close(fd_ptr->fd); + if(fd_ptr->fd_readonly != -1) + close(fd_ptr->fd_readonly); + if(fd_ptr->fd_writeonly != -1) + close(fd_ptr->fd_writeonly); + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; + fd_ptr->dev = (uint32)-1; + fd_ptr->inode = (uint32)-1; + fd_ptr->uid_cache_count = 0; + } else { + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + } + } + return fd_ptr->ref_count; +} + +/**************************************************************************** +fd support routines - check that current user has permissions +to open this file. Used when uid not found in optimization cache. +This is really ugly code, as due to POSIX locking braindamage we must +fork and then attempt to open the file, and return success or failure +via an exit code. +****************************************************************************/ +static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) +{ + pid_t child_pid; + + if((child_pid = fork()) < 0) { + DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); + return False; + } + + if(child_pid) { + /* + * Parent. + */ + pid_t wpid; + int status_code; + if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { + DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n")); + return(False); + } + + if (child_pid != wpid) { + DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); + return(False); + } +#if defined(WIFEXITED) && defined(WEXITSTATUS) + if (WIFEXITED(status_code) == 0) { + DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n")); + return(False); + } + if (WEXITSTATUS(status_code) != 0) { + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); + return(False); + } +#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */ + if(status_code != 0) { + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); + return(False); + } +#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */ + + /* + * Success - the child could open the file. + */ + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code)); + return True; + } else { + /* + * Child. + */ + int fd; + DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode )); + if((fd = fd_attempt_open( fname, accmode, 0)) < 0) { + /* Access denied. */ + _exit(EACCES); + } + close(fd); + DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); + _exit(0); + } + + return False; +} + +/**************************************************************************** +check a filename for the pipe string +****************************************************************************/ +static void check_for_pipe(char *fname) +{ + /* special case of pipe opens */ + char s[10]; + StrnCpy(s,fname,9); + strlower(s); + if (strstr(s,"pipe/")) { + DEBUG(3,("Rejecting named pipe open for %s\n",fname)); + unix_ERR_class = ERRSRV; + unix_ERR_code = ERRaccess; + } +} + +/**************************************************************************** +open a file +****************************************************************************/ +static void open_file(files_struct *fsp,connection_struct *conn, + char *fname1,int flags,int mode, struct stat *sbuf) +{ + extern struct current_user current_user; + pstring fname; + struct stat statbuf; + file_fd_struct *fd_ptr; + int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); + + fsp->open = False; + fsp->fd_ptr = 0; + fsp->granted_oplock = False; + errno = EPERM; + + pstrcpy(fname,fname1); + + /* check permissions */ + + /* + * This code was changed after seeing a client open request + * containing the open mode of (DENY_WRITE/read-only) with + * the 'create if not exist' bit set. The previous code + * would fail to open the file read only on a read-only share + * as it was checking the flags parameter directly against O_RDONLY, + * this was failing as the flags parameter was set to O_RDONLY|O_CREAT. + * JRA. + */ + + if (conn->read_only && !conn->printer) { + /* It's a read-only share - fail if we wanted to write. */ + if(accmode != O_RDONLY) { + DEBUG(3,("Permission denied opening %s\n",fname)); + check_for_pipe(fname); + return; + } else if(flags & O_CREAT) { + /* We don't want to write - but we must make sure that O_CREAT + doesn't create the file if we have write access into the + directory. + */ + flags &= ~O_CREAT; + } + } + + /* this handles a bug in Win95 - it doesn't say to create the file when it + should */ + if (conn->printer) { + flags |= O_CREAT; + } + +/* + if (flags == O_WRONLY) + DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); +*/ + + /* + * Ensure we have a valid struct stat so we can search the + * open fd table. + */ + if(sbuf == 0) { + if(sys_stat(fname, &statbuf) < 0) { + if(errno != ENOENT) { + DEBUG(3,("Error doing stat on file %s (%s)\n", + fname,strerror(errno))); + + check_for_pipe(fname); + return; + } + sbuf = 0; + } else { + sbuf = &statbuf; + } + } + + /* + * Check to see if we have this file already + * open. If we do, just use the already open fd and increment the + * reference count (fd_get_already_open increments the ref_count). + */ + if((fd_ptr = fd_get_already_open(sbuf))!= 0) { + /* + * File was already open. + */ + + /* + * Check it wasn't open for exclusive use. + */ + if((flags & O_CREAT) && (flags & O_EXCL)) { + fd_ptr->ref_count--; + errno = EEXIST; + return; + } + + /* + * Ensure that the user attempting to open + * this file has permissions to do so, if + * the user who originally opened the file wasn't + * the same as the current user. + */ + + if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { + if(!check_access_allowed_for_current_user( fname, accmode )) { + /* Error - permission denied. */ + DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", + fname, flags, accmode)); + /* Ensure the ref_count is decremented. */ + fd_ptr->ref_count--; + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + errno = EACCES; + return; + } + } + + fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + + /* + * If not opened O_RDWR try + * and do that here - a chmod may have been done + * between the last open and now. + */ + if(fd_ptr->real_open_flags != O_RDWR) + fd_attempt_reopen(fname, mode, fd_ptr); + + /* + * Ensure that if we wanted write access + * it has been opened for write, and if we wanted read it + * was open for read. + */ + if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) || + ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) || + ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { + DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", + fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); + check_for_pipe(fname); + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + fd_ptr->ref_count--; + return; + } + + } else { + int open_flags; + /* We need to allocate a new file_fd_struct (this increments the + ref_count). */ + if((fd_ptr = fd_get_new()) == 0) + return; + /* + * Whatever the requested flags, attempt read/write access, + * as we don't know what flags future file opens may require. + * If this fails, try again with the required flags. + * Even if we open read/write when only read access was + * requested the setting of the can_write flag in + * the file_struct will protect us from errant + * write requests. We never need to worry about O_APPEND + * as this is not set anywhere in Samba. + */ + fd_ptr->real_open_flags = O_RDWR; + /* Set the flags as needed without the read/write modes. */ + open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); + fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); + /* + * On some systems opening a file for R/W access on a read only + * filesystems sets errno to EROFS. + */ +#ifdef EROFS + if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) { +#else /* No EROFS */ + if((fd_ptr->fd == -1) && (errno == EACCES)) { +#endif /* EROFS */ + if(accmode != O_RDWR) { + fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); + fd_ptr->real_open_flags = accmode; + } + } + } + + if ((fd_ptr->fd >=0) && + conn->printer && lp_minprintspace(SNUM(conn))) { + pstring dname; + int dum1,dum2,dum3; + char *p; + pstrcpy(dname,fname); + p = strrchr(dname,'/'); + if (p) *p = 0; + if (sys_disk_free(dname,&dum1,&dum2,&dum3) < + lp_minprintspace(SNUM(conn))) { + fd_attempt_close(fd_ptr); + fsp->fd_ptr = 0; + if(fd_ptr->ref_count == 0) + sys_unlink(fname); + errno = ENOSPC; + return; + } + } + + if (fd_ptr->fd < 0) + { + DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", + fname,strerror(errno),flags)); + /* Ensure the ref_count is decremented. */ + fd_attempt_close(fd_ptr); + check_for_pipe(fname); + return; + } + + if (fd_ptr->fd >= 0) + { + if(sbuf == 0) { + /* Do the fstat */ + if(fstat(fd_ptr->fd, &statbuf) == -1) { + /* Error - backout !! */ + DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", + fd_ptr->fd, fname,strerror(errno))); + /* Ensure the ref_count is decremented. */ + fd_attempt_close(fd_ptr); + return; + } + sbuf = &statbuf; + } + + /* Set the correct entries in fd_ptr. */ + fd_ptr->dev = (uint32)sbuf->st_dev; + fd_ptr->inode = (uint32)sbuf->st_ino; + + fsp->fd_ptr = fd_ptr; + conn->num_files_open++; + fsp->mode = sbuf->st_mode; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + fsp->can_lock = True; + fsp->can_read = ((flags & O_WRONLY)==0); + fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + fsp->share_mode = 0; + fsp->print_file = conn->printer; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + fsp->is_directory = False; + fsp->conn = conn; + /* + * Note that the file name here is the *untranslated* name + * ie. it is still in the DOS codepage sent from the client. + * All use of this filename will pass though the sys_xxxx + * functions which will do the dos_to_unix translation before + * mapping into a UNIX filename. JRA. + */ + string_set(&fsp->fsp_name,fname); + fsp->wbmpx_ptr = NULL; + + /* + * If the printer is marked as postscript output a leading + * file identifier to ensure the file is treated as a raw + * postscript file. + * This has a similar effect as CtrlD=0 in WIN.INI file. + * tim@fsg.com 09/06/94 + */ + if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { + DEBUG(3,("Writing postscript line\n")); + write_file(fsp,"%!\n",3); + } + + DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", + *sesssetup_user ? sesssetup_user : conn->user,fname, + BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), + conn->num_files_open)); + + } + +#if WITH_MMAP + /* mmap it if read-only */ + if (!fsp->can_write) { + fsp->mmap_size = file_size(fname); + fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, + PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + + if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { + DEBUG(3,("Failed to mmap() %s - %s\n", + fname,strerror(errno))); + fsp->mmap_ptr = NULL; + } + } +#endif +} + + +/**************************************************************************** + C. Hoch 11/22/95 + Helper for open_file_shared. + Truncate a file after checking locking; close file if locked. + **************************************************************************/ +static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, + BOOL *share_locked) +{ + if (fsp->can_write){ + if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){ + /* If share modes are in force for this connection we + have the share entry locked. Unlock it before closing. */ + if (*share_locked && lp_share_modes(SNUM(conn))) + unlock_share_entry( conn, fsp->fd_ptr->dev, + fsp->fd_ptr->inode, token); + close_file(fsp,False); + /* Share mode no longer locked. */ + *share_locked = False; + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRlock; + } + else + ftruncate(fsp->fd_ptr->fd,0); + } +} + + + +/**************************************************************************** +open a file with a share mode +****************************************************************************/ +void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, + int mode,int oplock_request, int *Access,int *action) +{ + int flags=0; + int flags2=0; + int deny_mode = (share_mode>>4)&7; + struct stat sbuf; + BOOL file_existed = file_exist(fname,&sbuf); + BOOL share_locked = False; + BOOL fcbopen = False; + int token; + uint32 dev = 0; + uint32 inode = 0; + int num_share_modes = 0; + + fsp->open = False; + fsp->fd_ptr = 0; + + /* this is for OS/2 EAs - try and say we don't support them */ + if (strstr(fname,".+,;=[].")) + { + unix_ERR_class = ERRDOS; + /* OS/2 Workplace shell fix may be main code stream in a later release. */ +#if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ + unix_ERR_code = ERRcannotopen; +#else /* OS2_WPS_FIX */ + unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; +#endif /* OS2_WPS_FIX */ + + return; + } + + if ((ofun & 0x3) == 0 && file_existed) + { + errno = EEXIST; + return; + } + + if (ofun & 0x10) + flags2 |= O_CREAT; + if ((ofun & 0x3) == 2) + flags2 |= O_TRUNC; + + /* note that we ignore the append flag as + append does not mean the same thing under dos and unix */ + + switch (share_mode&0xF) + { + case 1: + flags = O_WRONLY; + break; + case 0xF: + fcbopen = True; + flags = O_RDWR; + break; + case 2: + flags = O_RDWR; + break; + default: + flags = O_RDONLY; + break; + } + +#if defined(O_SYNC) + if (share_mode&(1<<14)) { + flags2 |= O_SYNC; + } +#endif /* O_SYNC */ + + if (flags != O_RDONLY && file_existed && + (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) + { + if (!fcbopen) + { + errno = EACCES; + return; + } + flags = O_RDONLY; + } + + if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) + { + DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); + errno = EINVAL; + return; + } + + if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; + + if (lp_share_modes(SNUM(conn))) + { + int i; + share_mode_entry *old_shares = 0; + + if (file_existed) + { + dev = (uint32)sbuf.st_dev; + inode = (uint32)sbuf.st_ino; + lock_share_entry(conn, dev, inode, &token); + share_locked = True; + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + } + + /* + * Check if the share modes will give us access. + */ + + if(share_locked && (num_share_modes != 0)) + { + BOOL broke_oplock; + + do + { + + broke_oplock = False; + for(i = 0; i < num_share_modes; i++) + { + share_mode_entry *share_entry = &old_shares[i]; + + /* + * By observation of NetBench, oplocks are broken *before* share + * modes are checked. This allows a file to be closed by the client + * if the share mode would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so we must break + * it before continuing. + */ + if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) + { + + DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); + + /* Oplock break.... */ + unlock_share_entry(conn, dev, inode, token); + if(request_oplock_break(share_entry, dev, inode) == False) + { + free((char *)old_shares); + DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + lock_share_entry(conn, dev, inode, &token); + broke_oplock = True; + break; + } + + /* someone else has a share lock on it, check to see + if we can too */ + if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) + { + free((char *)old_shares); + unlock_share_entry(conn, dev, inode, token); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + + } /* end for */ + + if(broke_oplock) + { + free((char *)old_shares); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + } + } while(broke_oplock); + } + + if(old_shares != 0) + free((char *)old_shares); + } + + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", + flags,flags2,mode)); + + open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); + if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen) + { + flags = O_RDONLY; + open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); + } + + if (fsp->open) + { + int open_mode=0; + + if((share_locked == False) && lp_share_modes(SNUM(conn))) + { + /* We created the file - thus we must now lock the share entry before creating it. */ + dev = fsp->fd_ptr->dev; + inode = fsp->fd_ptr->inode; + lock_share_entry(conn, dev, inode, &token); + share_locked = True; + } + + switch (flags) + { + case O_RDONLY: + open_mode = 0; + break; + case O_RDWR: + open_mode = 2; + break; + case O_WRONLY: + open_mode = 1; + break; + } + + fsp->share_mode = (deny_mode<<4) | open_mode; + + if (Access) + (*Access) = open_mode; + + if (action) + { + if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED; + if (!file_existed) *action = FILE_WAS_CREATED; + if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN; + } + /* We must create the share mode entry before truncate as + truncate can fail due to locking and have to close the + file (which expects the share_mode_entry to be there). + */ + if (lp_share_modes(SNUM(conn))) + { + uint16 port = 0; + /* JRA. Currently this only services Exlcusive and batch + oplocks (no other opens on this file). This needs to + be extended to level II oplocks (multiple reader + oplocks). */ + + if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && + !IS_VETO_OPLOCK_PATH(conn,fname)) + { + fsp->granted_oplock = True; + fsp->sent_oplock_break = False; + global_oplocks_open++; + port = oplock_port; + + DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ +dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); + + } + else + { + port = 0; + oplock_request = 0; + } + set_share_mode(token, fsp, port, oplock_request); + } + + if ((flags2&O_TRUNC) && file_existed) + truncate_unless_locked(fsp,conn,token,&share_locked); + } + + if (share_locked && lp_share_modes(SNUM(conn))) + unlock_share_entry( conn, dev, inode, token); +} + + + +/**************************************************************************** + Open a directory from an NT SMB call. +****************************************************************************/ +int open_directory(files_struct *fsp,connection_struct *conn, + char *fname, int smb_ofun, int unixmode, int *action) +{ + extern struct current_user current_user; + struct stat st; + + if (smb_ofun & 0x10) { + /* + * Create the directory. + */ + + if(sys_mkdir(fname, unixmode) < 0) { + DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + *action = FILE_WAS_CREATED; + } else { + /* + * Check that it *was* a directory. + */ + + if(sys_stat(fname, &st) < 0) { + DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + if(!S_ISDIR(st.st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + return -1; + } + *action = FILE_WAS_OPENED; + } + + DEBUG(5,("open_directory: opening directory %s\n", + fname)); + + /* + * Setup the files_struct for it. + */ + + fsp->fd_ptr = NULL; + conn->num_files_open++; + fsp->mode = 0; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + fsp->can_lock = True; + fsp->can_read = False; + fsp->can_write = False; + fsp->share_mode = 0; + fsp->print_file = False; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + fsp->is_directory = True; + fsp->conn = conn; + /* + * Note that the file name here is the *untranslated* name + * ie. it is still in the DOS codepage sent from the client. + * All use of this filename will pass though the sys_xxxx + * functions which will do the dos_to_unix translation before + * mapping into a UNIX filename. JRA. + */ + string_set(&fsp->fsp_name,fname); + fsp->wbmpx_ptr = NULL; + + return 0; +} + +enum {AFAIL,AREAD,AWRITE,AALL}; + +/******************************************************************* +reproduce the share mode access table +********************************************************************/ +static int access_table(int new_deny,int old_deny,int old_mode, + int share_pid,char *fname) +{ + if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); + + if (new_deny == DENY_DOS || old_deny == DENY_DOS) { + int pid = getpid(); + if (old_deny == new_deny && share_pid == pid) + return(AALL); + + if (old_mode == 0) return(AREAD); + + /* the new smbpub.zip spec says that if the file extension is + .com, .dll, .exe or .sym then allow the open. I will force + it to read-only as this seems sensible although the spec is + a little unclear on this. */ + if ((fname = strrchr(fname,'.'))) { + if (strequal(fname,".com") || + strequal(fname,".dll") || + strequal(fname,".exe") || + strequal(fname,".sym")) + return(AREAD); + } + + return(AFAIL); + } + + switch (new_deny) + { + case DENY_WRITE: + if (old_deny==DENY_WRITE && old_mode==0) return(AREAD); + if (old_deny==DENY_READ && old_mode==0) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==0) return(AALL); + return(AFAIL); + case DENY_READ: + if (old_deny==DENY_WRITE && old_mode==1) return(AREAD); + if (old_deny==DENY_READ && old_mode==1) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==1) return(AALL); + return(AFAIL); + case DENY_NONE: + if (old_deny==DENY_WRITE) return(AREAD); + if (old_deny==DENY_READ) return(AWRITE); + if (old_deny==DENY_NONE) return(AALL); + return(AFAIL); + } + return(AFAIL); +} + +/******************************************************************* +check if the share mode on a file allows it to be deleted or unlinked +return True if sharing doesn't prevent the operation +********************************************************************/ +BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) +{ + int i; + int ret = False; + share_mode_entry *old_shares = 0; + int num_share_modes; + struct stat sbuf; + int token; + int pid = getpid(); + uint32 dev, inode; + + if(!lp_share_modes(SNUM(conn))) + return True; + + if (sys_stat(fname,&sbuf) == -1) return(True); + + dev = (uint32)sbuf.st_dev; + inode = (uint32)sbuf.st_ino; + + lock_share_entry(conn, dev, inode, &token); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + + /* + * Check if the share modes will give us access. + */ + + if(num_share_modes != 0) + { + BOOL broke_oplock; + + do + { + + broke_oplock = False; + for(i = 0; i < num_share_modes; i++) + { + share_mode_entry *share_entry = &old_shares[i]; + + /* + * Break oplocks before checking share modes. See comment in + * open_file_shared for details. + * Check if someone has an oplock on this file. If so we must + * break it before continuing. + */ + if(share_entry->op_type & BATCH_OPLOCK) + { + + /* + * It appears that the NT redirector may have a bug, in that + * it tries to do an SMBmv on a file that it has open with a + * batch oplock, and then fails to respond to the oplock break + * request. This only seems to occur when the client is doing an + * SMBmv to the smbd it is using - thus we try and detect this + * condition by checking if the file being moved is open and oplocked by + * this smbd process, and then not sending the oplock break in this + * special case. If the file was open with a deny mode that + * prevents the move the SMBmv will fail anyway with a share + * violation error. JRA. + */ + if(rename_op && (share_entry->pid == pid)) + { + DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ +batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); + /* + * This next line is a test that allows the deny-mode + * processing to be skipped. This seems to be needed as + * NT insists on the rename succeeding (in Office 9x no less !). + * This should be removed as soon as (a) MS fix the redirector + * bug or (b) NT SMB support in Samba makes NT not issue the + * call (as is my fervent hope). JRA. + */ + continue; + } + else + { + DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); + + /* Oplock break.... */ + unlock_share_entry(conn, dev, inode, token); + if(request_oplock_break(share_entry, dev, inode) == False) + { + free((char *)old_shares); + DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); + return False; + } + lock_share_entry(conn, dev, inode, &token); + broke_oplock = True; + break; + } + } + + /* someone else has a share lock on it, check to see + if we can too */ + if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) + goto free_and_exit; + + } /* end for */ + + if(broke_oplock) + { + free((char *)old_shares); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + } + } while(broke_oplock); + } + + /* XXXX exactly what share mode combinations should be allowed for + deleting/renaming? */ + /* If we got here then either there were no share modes or + all share modes were DENY_DOS and the pid == getpid() */ + ret = True; + +free_and_exit: + + unlock_share_entry(conn, dev, inode, token); + if(old_shares != NULL) + free((char *)old_shares); + return(ret); +} + +/**************************************************************************** +check if we can open a file with a share mode +****************************************************************************/ +int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, + BOOL fcbopen, int *flags) +{ + int old_open_mode = share->share_mode &0xF; + int old_deny_mode = (share->share_mode >>4)&7; + + if (old_deny_mode > 4 || old_open_mode > 2) + { + DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", + deny_mode,old_deny_mode,old_open_mode,fname)); + return False; + } + + { + int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, + share->pid,fname); + + if ((access_allowed == AFAIL) || + (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || + (access_allowed == AREAD && *flags == O_WRONLY) || + (access_allowed == AWRITE && *flags == O_RDONLY)) + { + DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", + deny_mode,old_deny_mode,old_open_mode, + share->pid,fname, fcbopen, *flags, access_allowed)); + return False; + } + + if (access_allowed == AREAD) + *flags = O_RDONLY; + + if (access_allowed == AWRITE) + *flags = O_WRONLY; + + } + return True; +} + diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c new file mode 100644 index 0000000000..1b49e2cfaf --- /dev/null +++ b/source3/smbd/oplock.c @@ -0,0 +1,639 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + oplock processing + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + +extern int oplock_sock; +extern uint16 oplock_port; +extern int32 global_oplocks_open; +extern int32 global_oplocks_open; +extern int global_oplock_break; +extern int smb_read_error; + + +/**************************************************************************** + open the oplock IPC socket communication +****************************************************************************/ +BOOL open_oplock_ipc(void) +{ + struct sockaddr_in sock_name; + int len = sizeof(sock_name); + + DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); + + /* Open a lookback UDP socket on a random port. */ + oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK)); + if (oplock_sock == -1) + { + DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ +address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); + oplock_port = 0; + return(False); + } + + /* Find out the transient UDP port we have been allocated. */ + if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) + { + DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", + strerror(errno))); + close(oplock_sock); + oplock_sock = -1; + oplock_port = 0; + return False; + } + oplock_port = ntohs(sock_name.sin_port); + + DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", + (int)getpid(), oplock_port)); + + return True; +} + +/**************************************************************************** + process an oplock break message. +****************************************************************************/ +BOOL process_local_message(int sock, char *buffer, int buf_size) +{ + int32 msg_len; + uint16 from_port; + char *msg_start; + + msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET); + from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET); + + msg_start = &buffer[UDP_CMD_HEADER_LEN]; + + DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", + msg_len, from_port)); + + /* Switch on message command - currently OPLOCK_BREAK_CMD is the + only valid request. */ + + switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET)) + { + case OPLOCK_BREAK_CMD: + /* Ensure that the msg length is correct. */ + if(msg_len != OPLOCK_BREAK_MSG_LEN) + { + DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \ +should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); + return False; + } + { + uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + struct timeval tval; + struct sockaddr_in toaddr; + + tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); + tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); + + DEBUG(5,("process_local_message: oplock break request from \ +pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); + + /* + * If we have no record of any currently open oplocks, + * it's not an error, as a close command may have + * just been issued on the file that was oplocked. + * Just return success in this case. + */ + + if(global_oplocks_open != 0) + { + if(oplock_break(dev, inode, &tval) == False) + { + DEBUG(0,("process_local_message: oplock break failed - \ +not returning udp message.\n")); + return False; + } + } + else + { + DEBUG(3,("process_local_message: oplock break requested with no outstanding \ +oplocks. Returning success.\n")); + } + + /* Send the message back after OR'ing in the 'REPLY' bit. */ + SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); + + bzero((char *)&toaddr,sizeof(toaddr)); + toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + toaddr.sin_port = htons(from_port); + toaddr.sin_family = AF_INET; + + if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) + { + DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", + remotepid, strerror(errno))); + return False; + } + + DEBUG(5,("process_local_message: oplock break reply sent to \ +pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, + from_port, dev, inode)); + + } + break; + /* + * Keep this as a debug case - eventually we can remove it. + */ + case 0x8001: + DEBUG(0,("process_local_message: Received unsolicited break \ +reply - dumping info.\n")); + + if(msg_len != OPLOCK_BREAK_MSG_LEN) + { + DEBUG(0,("process_local_message: ubr: incorrect length for reply \ +(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); + return False; + } + + { + uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + + DEBUG(0,("process_local_message: unsolicited oplock break reply from \ +pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); + + } + return False; + + default: + DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", + (unsigned int)SVAL(msg_start,0))); + return False; + } + return True; +} + +/**************************************************************************** + Process an oplock break directly. +****************************************************************************/ +BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) +{ + extern struct current_user current_user; + extern int Client; + char *inbuf = NULL; + char *outbuf = NULL; + files_struct *fsp = NULL; + time_t start_time; + BOOL shutdown_server = False; + connection_struct *saved_conn; + int saved_vuid; + pstring saved_dir; + + if( DEBUGLVL( 3 ) ) + { + dbgtext( "oplock_break: called for dev = %x, inode = %x.\n", dev, inode ); + dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); + } + + /* We need to search the file open table for the + entry containing this dev and inode, and ensure + we have an oplock on it. */ + fsp = file_find_dit(dev, inode, tval); + + if(fsp == NULL) + { + /* The file could have been closed in the meantime - return success. */ + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: cannot find open file with " ); + dbgtext( "dev = %x, inode = %x ", dev, inode); + dbgtext( "allowing break to succeed.\n" ); + } + return True; + } + + /* Ensure we have an oplock on the file */ + + /* There is a potential race condition in that an oplock could + have been broken due to another udp request, and yet there are + still oplock break messages being sent in the udp message + queue for this file. So return true if we don't have an oplock, + as we may have just freed it. + */ + + if(!fsp->granted_oplock) + { + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: file %s ", fsp->fsp_name ); + dbgtext( "(dev = %x, inode = %x) has no oplock.\n", dev, inode ); + dbgtext( "Allowing break to succeed regardless.\n" ); + } + return True; + } + + /* mark the oplock break as sent - we don't want to send twice! */ + if (fsp->sent_oplock_break) + { + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); + dbgtext( "file %s ", fsp->fsp_name); + dbgtext( "(dev = %x, inode = %x)\n", dev, inode ); + } + + /* We have to fail the open here as we cannot send another oplock break on + this file whilst we are awaiting a response from the client - neither + can we allow another open to succeed while we are waiting for the + client. + */ + return False; + } + + /* Now comes the horrid part. We must send an oplock break to the client, + and then process incoming messages until we get a close or oplock release. + At this point we know we need a new inbuf/outbuf buffer pair. + We cannot use these staticaly as we may recurse into here due to + messages crossing on the wire. + */ + + if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + { + DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); + return False; + } + + if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + { + DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); + free(inbuf); + inbuf = NULL; + return False; + } + + /* Prepare the SMBlockingX message. */ + bzero(outbuf,smb_size); + set_message(outbuf,8,0,True); + + SCVAL(outbuf,smb_com,SMBlockingX); + SSVAL(outbuf,smb_tid,fsp->conn->cnum); + SSVAL(outbuf,smb_pid,0xFFFF); + SSVAL(outbuf,smb_uid,0); + SSVAL(outbuf,smb_mid,0xFFFF); + SCVAL(outbuf,smb_vwv0,0xFF); + SSVAL(outbuf,smb_vwv2,fsp->fnum); + SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); + /* Change this when we have level II oplocks. */ + SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE); + + send_smb(Client, outbuf); + + /* Remember we just sent an oplock break on this file. */ + fsp->sent_oplock_break = True; + + /* We need this in case a readraw crosses on the wire. */ + global_oplock_break = True; + + /* Process incoming messages. */ + + /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT + seconds we should just die.... */ + + start_time = time(NULL); + + /* + * Save the information we need to re-become the + * user, then unbecome the user whilst we're doing this. + */ + saved_conn = fsp->conn; + saved_vuid = current_user.vuid; + GetWd(saved_dir); + unbecome_user(); + + while(OPEN_FSP(fsp) && fsp->granted_oplock) + { + if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) + { + /* + * Die if we got an error. + */ + + if (smb_read_error == READ_EOF) + DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); + + if (smb_read_error == READ_ERROR) + DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); + + if (smb_read_error == READ_TIMEOUT) + DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", + OPLOCK_BREAK_TIMEOUT ) ); + + DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) ); + DEBUGADD( 0, ( "(dev = %x, inode = %x).\n", dev, inode)); + shutdown_server = True; + break; + } + + /* + * There are certain SMB requests that we shouldn't allow + * to recurse. opens, renames and deletes are the obvious + * ones. This is handled in the switch_message() function. + * If global_oplock_break is set they will push the packet onto + * the pending smb queue and return -1 (no reply). + * JRA. + */ + + process_smb(inbuf, outbuf); + + /* + * Die if we go over the time limit. + */ + + if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) + { + if( DEBUGLVL( 0 ) ) + { + dbgtext( "oplock_break: no break received from client " ); + dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); + dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); + dbgtext( "(dev = %x, inode = %x).\n", dev, inode ); + } + shutdown_server = True; + break; + } + } + + /* + * Go back to being the user who requested the oplock + * break. + */ + if(!become_user(saved_conn, saved_vuid)) + { + DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); + DEBUGADD( 0, ( "Shutting down server\n" ) ); + close_sockets(); + close(oplock_sock); + exit_server("unable to re-become user"); + } + /* Including the directory. */ + ChDir(saved_dir); + + /* Free the buffers we've been using to recurse. */ + free(inbuf); + free(outbuf); + + /* We need this in case a readraw crossed on the wire. */ + if(global_oplock_break) + global_oplock_break = False; + + /* + * If the client did not respond we must die. + */ + + if(shutdown_server) + { + DEBUG( 0, ( "oplock_break: client failure in break - " ) ); + DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); + close_sockets(); + close(oplock_sock); + exit_server("oplock break failure"); + } + + if(OPEN_FSP(fsp)) + { + /* The lockingX reply will have removed the oplock flag + from the sharemode. */ + /* Paranoia.... */ + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + global_oplocks_open--; + } + + /* Santity check - remove this later. JRA */ + if(global_oplocks_open < 0) + { + DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", + global_oplocks_open)); + exit_server("oplock_break: global_oplocks_open < 0"); + } + + if( DEBUGLVL( 3 ) ) + { + dbgtext( "oplock_break: returning success for " ); + dbgtext( "dev = %x, inode = %x.\n", dev, inode ); + dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); + } + + return True; +} + +/**************************************************************************** +Send an oplock break message to another smbd process. If the oplock is held +by the local smbd then call the oplock break function directly. +****************************************************************************/ + +BOOL request_oplock_break(share_mode_entry *share_entry, + uint32 dev, uint32 inode) +{ + char op_break_msg[OPLOCK_BREAK_MSG_LEN]; + struct sockaddr_in addr_out; + int pid = getpid(); + time_t start_time; + int time_left; + + if(pid == share_entry->pid) + { + /* We are breaking our own oplock, make sure it's us. */ + if(share_entry->op_port != oplock_port) + { + DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ +should be %d\n", pid, share_entry->op_port, oplock_port)); + return False; + } + + DEBUG(5,("request_oplock_break: breaking our own oplock\n")); + + /* Call oplock break direct. */ + return oplock_break(dev, inode, &share_entry->time); + } + + /* We need to send a OPLOCK_BREAK_CMD message to the + port in the share mode entry. */ + + SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); + SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); + SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); + SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); + SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); + SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); + + /* set the address and port */ + bzero((char *)&addr_out,sizeof(addr_out)); + addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_out.sin_port = htons( share_entry->op_port ); + addr_out.sin_family = AF_INET; + + if( DEBUGLVL( 3 ) ) + { + dbgtext( "request_oplock_break: sending a oplock break message to " ); + dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x\n", dev, inode ); + } + + if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, + (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) + { + if( DEBUGLVL( 0 ) ) + { + dbgtext( "request_oplock_break: failed when sending a oplock " ); + dbgtext( "break message to pid %d ", share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); + dbgtext( "Error was %s\n", strerror(errno) ); + } + return False; + } + + /* + * Now we must await the oplock broken message coming back + * from the target smbd process. Timeout if it fails to + * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. + * While we get messages that aren't ours, loop. + */ + + start_time = time(NULL); + time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR; + + while(time_left >= 0) + { + char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; + int32 reply_msg_len; + uint16 reply_from_port; + char *reply_msg_start; + + if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), + time_left ? time_left * 1000 : 1) == False) + { + if(smb_read_error == READ_TIMEOUT) + { + if( DEBUGLVL( 0 ) ) + { + dbgtext( "request_oplock_break: no response received to oplock " ); + dbgtext( "break request to pid %d ", share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x\n", dev, inode ); + } + /* + * This is a hack to make handling of failing clients more robust. + * If a oplock break response message is not received in the timeout + * period we may assume that the smbd servicing that client holding + * the oplock has died and the client changes were lost anyway, so + * we should continue to try and open the file. + */ + break; + } + else + if( DEBUGLVL( 0 ) ) + { + dbgtext( "request_oplock_break: error in response received " ); + dbgtext( "to oplock break request to pid %d ", share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); + dbgtext( "Error was (%s).\n", strerror(errno) ); + } + return False; + } + + reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET); + reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET); + + reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN]; + + if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) + { + /* Ignore it. */ + DEBUG( 0, ( "request_oplock_break: invalid message length received." ) ); + DEBUGADD( 0, ( " Ignoring.\n" ) ); + continue; + } + + /* + * Test to see if this is the reply we are awaiting. + */ + + if((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) && + (reply_from_port == share_entry->op_port) && + (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], + &op_break_msg[OPLOCK_BREAK_PID_OFFSET], + OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) + { + /* + * This is the reply we've been waiting for. + */ + break; + } + else + { + /* + * This is another message - probably a break request. + * Process it to prevent potential deadlock. + * Note that the code in switch_message() prevents + * us from recursing into here as any SMB requests + * we might process that would cause another oplock + * break request to be made will be queued. + * JRA. + */ + + process_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply)); + } + + time_left -= (time(NULL) - start_time); + } + + DEBUG(3,("request_oplock_break: broke oplock.\n")); + + return True; +} + + +/**************************************************************************** + Attempt to break an oplock on a file (if oplocked). + Returns True if the file was closed as a result of + the oplock break, False otherwise. + Used as a last ditch attempt to free a space in the + file table when we have run out. +****************************************************************************/ +BOOL attempt_close_oplocked_file(files_struct *fsp) +{ + + DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); + + if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) { + + /* Try and break the oplock. */ + file_fd_struct *fd_ptr = fsp->fd_ptr; + if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time)) { + if(!fsp->open) /* Did the oplock break close the file ? */ + return True; + } + } + + return False; +} + diff --git a/source3/smbd/process.c b/source3/smbd/process.c new file mode 100644 index 0000000000..30abfdb894 --- /dev/null +++ b/source3/smbd/process.c @@ -0,0 +1,810 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + process incoming packets - main loop + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + +extern int last_message; +extern int global_oplock_break; +extern pstring sesssetup_user; +extern char *last_inbuf; +extern time_t smb_last_time; +extern char *InBuffer; +extern char *OutBuffer; +extern int oplock_sock; +extern int smb_read_error; +extern BOOL reload_after_sighup; +extern BOOL global_machine_pasword_needs_changing; +extern fstring global_myworkgroup; +extern pstring global_myname; +extern int max_send; + + +/**************************************************************************** +Get the next SMB packet, doing the local message processing automatically. +****************************************************************************/ +BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout) +{ + BOOL got_smb = False; + BOOL ret; + + do + { + ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize, + timeout,&got_smb); + + if(ret && !got_smb) + { + /* Deal with oplock break requests from other smbd's. */ + process_local_message(oplock_sock, inbuf, bufsize); + continue; + } + + if(ret && (CVAL(inbuf,0) == 0x85)) + { + /* Keepalive packet. */ + got_smb = False; + } + + } + while(ret && !got_smb); + + return ret; +} + + + +/**************************************************************************** + process an smb from the client - split out from the process() code so + it can be used by the oplock break code. +****************************************************************************/ +void process_smb(char *inbuf, char *outbuf) +{ + extern int Client; +#ifdef WITH_SSL + extern BOOL sslEnabled; /* don't use function for performance reasons */ + static int sslConnected = 0; +#endif /* WITH_SSL */ + static int trans_num; + int msg_type = CVAL(inbuf,0); + int32 len = smb_len(inbuf); + int nread = len + 4; + + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) { + /* send a negative session response "not listining on calling + name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG( 1, ( "Connection denied from %s\n", + client_addr(Client) ) ); + send_smb(Client,(char *)buf); + exit_server("connection denied"); + } + } + + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); + +#ifdef WITH_SSL + if(sslEnabled && !sslConnected){ + sslConnected = sslutil_negotiate_ssl(Client, msg_type); + if(sslConnected < 0){ /* an error occured */ + exit_server("SSL negotiation failed"); + }else if(sslConnected){ + trans_num++; + return; + } + } +#endif /* WITH_SSL */ + +#ifdef WITH_VTP + if(trans_num == 1 && VT_Check(inbuf)) + { + VT_Process(); + return; + } +#endif + + if (msg_type == 0) + show_msg(inbuf); + else if(msg_type == 0x85) + return; /* Keepalive packet. */ + + nread = construct_reply(inbuf,outbuf,nread,max_send); + + if(nread > 0) + { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); + + if (nread != smb_len(outbuf) + 4) + { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(outbuf))); + } + else + send_smb(Client,outbuf); + } + trans_num++; +} + + +/* +These flags determine some of the permissions required to do an operation + +Note that I don't set NEED_WRITE on some write operations because they +are used by some brain-dead clients when printing, and I don't want to +force write permissions on print services. +*/ +#define AS_USER (1<<0) +#define NEED_WRITE (1<<1) +#define TIME_INIT (1<<2) +#define CAN_IPC (1<<3) +#define AS_GUEST (1<<5) +#define QUEUE_IN_OPLOCK (1<<6) + +/* + define a list of possible SMB messages and their corresponding + functions. Any message that has a NULL function is unimplemented - + please feel free to contribute implementations! +*/ +struct smb_message_struct +{ + int code; + char *name; + int (*fn)(connection_struct *conn, char *, char *, int, int); + int flags; +#if PROFILING + unsigned long time; +#endif +} + smb_messages[] = { + + /* CORE PROTOCOL */ + + {SMBnegprot,"SMBnegprot",reply_negprot,0}, + {SMBtcon,"SMBtcon",reply_tcon,0}, + {SMBtdis,"SMBtdis",reply_tdis,0}, + {SMBexit,"SMBexit",reply_exit,0}, + {SMBioctl,"SMBioctl",reply_ioctl,0}, + {SMBecho,"SMBecho",reply_echo,0}, + {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, + {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, + {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ + {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, + {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, + {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, + {SMBsearch,"SMBsearch",reply_search,AS_USER}, + {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK }, + + /* note that SMBmknew and SMBcreate are deliberately overloaded */ + {SMBcreate,"SMBcreate",reply_mknew,AS_USER}, + {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, + + {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, + {SMBread,"SMBread",reply_read,AS_USER}, + {SMBwrite,"SMBwrite",reply_write,AS_USER}, + {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, + {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, + {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, + {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER}, + {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, + + /* this is a Pathworks specific call, allowing the + changing of the root path */ + {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, + + {SMBlseek,"SMBlseek",reply_lseek,AS_USER}, + {SMBflush,"SMBflush",reply_flush,AS_USER}, + {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, + {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK }, + {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER}, + {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER}, + {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER}, + {SMBlock,"SMBlock",reply_lock,AS_USER}, + {SMBunlock,"SMBunlock",reply_unlock,AS_USER}, + + /* CORE+ PROTOCOL FOLLOWS */ + + {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER}, + {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER}, + {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER}, + {SMBlockread,"SMBlockread",reply_lockread,AS_USER}, + {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER}, + + /* LANMAN1.0 PROTOCOL FOLLOWS */ + + {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER}, + {SMBreadBs,"SMBreadBs",NULL,AS_USER}, + {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER}, + {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER}, + {SMBwritec,"SMBwritec",NULL,AS_USER}, + {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE}, + {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER}, + {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC}, + {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC}, + {SMBioctls,"SMBioctls",NULL,AS_USER}, + {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, + {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, + + {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, + {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, + {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER}, + {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, + + {SMBffirst,"SMBffirst",reply_search,AS_USER}, + {SMBfunique,"SMBfunique",reply_search,AS_USER}, + {SMBfclose,"SMBfclose",reply_fclose,AS_USER}, + + /* LANMAN2.0 PROTOCOL FOLLOWS */ + {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, + {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, + {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER }, + {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, + + /* NT PROTOCOL FOLLOWS */ + {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, + {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, + {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, + {SMBntcancel, "SMBntcancel", reply_ntcancel, AS_USER }, + + /* messaging routines */ + {SMBsends,"SMBsends",reply_sends,AS_GUEST}, + {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST}, + {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST}, + {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST}, + + /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */ + + {SMBsendb,"SMBsendb",NULL,AS_GUEST}, + {SMBfwdname,"SMBfwdname",NULL,AS_GUEST}, + {SMBcancelf,"SMBcancelf",NULL,AS_GUEST}, + {SMBgetmac,"SMBgetmac",NULL,AS_GUEST} + }; + +/**************************************************************************** +return a string containing the function name of a SMB command +****************************************************************************/ +char *smb_fn_name(int type) +{ + static char *unknown_name = "SMBunknown"; + static int num_smb_messages = + sizeof(smb_messages) / sizeof(struct smb_message_struct); + int match; + + for (match=0;matchrequested_name); + } + + /* does this protocol need to be run as root? */ + if (!(flags & AS_USER)) + unbecome_user(); + + /* does this protocol need to be run as the connected user? */ + if ((flags & AS_USER) && !become_user(conn,session_tag)) { + if (flags & AS_GUEST) + flags &= ~AS_USER; + else + return(ERROR(ERRSRV,ERRinvnid)); + } + /* this code is to work around a bug is MS client 3 without + introducing a security hole - it needs to be able to do + print queue checks as guest if it isn't logged in properly */ + if (flags & AS_USER) + flags &= ~AS_GUEST; + + /* does it need write permission? */ + if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) + return(ERROR(ERRSRV,ERRaccess)); + + /* ipc services are limited */ + if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) { + return(ERROR(ERRSRV,ERRaccess)); + } + + /* load service specific parameters */ + if (conn && + !become_service(conn,(flags & AS_USER)?True:False)) { + return(ERROR(ERRSRV,ERRaccess)); + } + + /* does this protocol need to be run as guest? */ + if ((flags & AS_GUEST) && + (!become_guest() || + !check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1)))) { + return(ERROR(ERRSRV,ERRaccess)); + } + + last_inbuf = inbuf; + + outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize); + } + else + { + outsize = reply_unknown(inbuf,outbuf); + } + } + +#if PROFILING + GetTimeOfDay(&msg_end_time); + if (!(smb_messages[match].flags & TIME_INIT)) + { + smb_messages[match].time = 0; + smb_messages[match].flags |= TIME_INIT; + } + { + unsigned long this_time = + (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 + + (msg_end_time.tv_usec - msg_start_time.tv_usec); + smb_messages[match].time += this_time; + total_time += this_time; + } + DEBUG(2,("TIME %s %d usecs %g pct\n", + smb_fn_name(type),smb_messages[match].time, + (100.0*smb_messages[match].time) / total_time)); +#endif + + return(outsize); +} + + +/**************************************************************************** + construct a chained reply and add it to the already made reply + **************************************************************************/ +int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) +{ + static char *orig_inbuf; + static char *orig_outbuf; + int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); + unsigned smb_off2 = SVAL(inbuf,smb_vwv1); + char *inbuf2, *outbuf2; + int outsize2; + char inbuf_saved[smb_wct]; + char outbuf_saved[smb_wct]; + extern int chain_size; + int wct = CVAL(outbuf,smb_wct); + int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); + + /* maybe its not chained */ + if (smb_com2 == 0xFF) { + CVAL(outbuf,smb_vwv0) = 0xFF; + return outsize; + } + + if (chain_size == 0) { + /* this is the first part of the chain */ + orig_inbuf = inbuf; + orig_outbuf = outbuf; + } + + /* we need to tell the client where the next part of the reply will be */ + SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); + CVAL(outbuf,smb_vwv0) = smb_com2; + + /* remember how much the caller added to the chain, only counting stuff + after the parameter words */ + chain_size += outsize - smb_wct; + + /* work out pointers into the original packets. The + headers on these need to be filled in */ + inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; + outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; + + /* remember the original command type */ + smb_com1 = CVAL(orig_inbuf,smb_com); + + /* save the data which will be overwritten by the new headers */ + memcpy(inbuf_saved,inbuf2,smb_wct); + memcpy(outbuf_saved,outbuf2,smb_wct); + + /* give the new packet the same header as the last part of the SMB */ + memmove(inbuf2,inbuf,smb_wct); + + /* create the in buffer */ + CVAL(inbuf2,smb_com) = smb_com2; + + /* create the out buffer */ + bzero(outbuf2,smb_size); + set_message(outbuf2,0,0,True); + CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com); + + memcpy(outbuf2+4,inbuf2+4,4); + CVAL(outbuf2,smb_rcls) = SMB_SUCCESS; + CVAL(outbuf2,smb_reh) = 0; + CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set + means a reply */ + SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf2,smb_err,SMB_SUCCESS); + SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid)); + SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid)); + SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid)); + SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid)); + + DEBUG(3,("Chained message\n")); + show_msg(inbuf2); + + /* process the request */ + outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, + bufsize-chain_size); + + /* copy the new reply and request headers over the old ones, but + preserve the smb_com field */ + memmove(orig_outbuf,outbuf2,smb_wct); + CVAL(orig_outbuf,smb_com) = smb_com1; + + /* restore the saved data, being careful not to overwrite any + data from the reply header */ + memcpy(inbuf2,inbuf_saved,smb_wct); + { + int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); + if (ofs < 0) ofs = 0; + memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); + } + + return outsize2; +} + + +/**************************************************************************** + Helper function for contruct_reply. +****************************************************************************/ + +void construct_reply_common(char *inbuf,char *outbuf) +{ + bzero(outbuf,smb_size); + + CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); + set_message(outbuf,0,0,True); + + memcpy(outbuf+4,inbuf+4,4); + CVAL(outbuf,smb_rcls) = SMB_SUCCESS; + CVAL(outbuf,smb_reh) = 0; + CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set + means a reply */ + SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf,smb_err,SMB_SUCCESS); + SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); + SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); + SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); + SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); +} + +/**************************************************************************** + construct a reply to the incoming packet +****************************************************************************/ +int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) +{ + int type = CVAL(inbuf,smb_com); + int outsize = 0; + int msg_type = CVAL(inbuf,0); + extern int chain_size; + + smb_last_time = time(NULL); + + chain_size = 0; + file_chain_reset(); + reset_chain_p(); + + if (msg_type != 0) + return(reply_special(inbuf,outbuf)); + + construct_reply_common(inbuf, outbuf); + + outsize = switch_message(type,inbuf,outbuf,size,bufsize); + + outsize += chain_size; + + if(outsize > 4) + smb_setlen(outbuf,outsize - 4); + return(outsize); +} + +/**************************************************************************** + process commands from the client +****************************************************************************/ +void smbd_process(void) +{ + extern int Client; + + InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if ((InBuffer == NULL) || (OutBuffer == NULL)) + return; + + InBuffer += SMB_ALIGNMENT; + OutBuffer += SMB_ALIGNMENT; + +#if PRIME_NMBD + DEBUG(3,("priming nmbd\n")); + { + struct in_addr ip; + ip = *interpret_addr2("localhost"); + if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1"); + *OutBuffer = 0; + send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM); + } +#endif + + /* re-initialise the timezone */ + TimeInit(); + + while (True) + { + int deadtime = lp_deadtime()*60; + int counter; + int last_keepalive=0; + int service_load_counter = 0; + BOOL got_smb = False; + + if (deadtime <= 0) + deadtime = DEFAULT_SMBD_TIMEOUT; + +#if USE_READ_PREDICTION + if (lp_readprediction()) + do_read_prediction(); +#endif + + errno = 0; + + for (counter=SMBD_SELECT_LOOP; + !receive_message_or_smb(Client,oplock_sock, + InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); + counter += SMBD_SELECT_LOOP) + { + time_t t; + BOOL allidle = True; + extern int keepalive; + + if (counter > 365 * 3600) /* big number of seconds. */ + { + counter = 0; + service_load_counter = 0; + } + + if (smb_read_error == READ_EOF) + { + DEBUG(3,("end of file from client\n")); + return; + } + + if (smb_read_error == READ_ERROR) + { + DEBUG(3,("receive_smb error (%s) exiting\n", + strerror(errno))); + return; + } + + t = time(NULL); + + /* become root again if waiting */ + unbecome_user(); + + /* check for smb.conf reload */ + if (counter >= service_load_counter + SMBD_RELOAD_CHECK) + { + service_load_counter = counter; + + /* reload services, if files have changed. */ + reload_services(True); + } + + /* + * If reload_after_sighup == True then we got a SIGHUP + * and are being asked to reload. Fix from + */ + + if (reload_after_sighup) + { + DEBUG(0,("Reloading services after SIGHUP\n")); + reload_services(False); + reload_after_sighup = False; + } + + /* automatic timeout if all connections are closed */ + if (conn_num_open()==0 && counter >= IDLE_CLOSED_TIMEOUT) + { + DEBUG( 2, ( "Closing idle connection\n" ) ); + return; + } + + if (keepalive && (counter-last_keepalive)>keepalive) + { + struct cli_state *cli = server_client(); + if (!send_keepalive(Client)) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return; + } + /* also send a keepalive to the password server if its still + connected */ + if (cli && cli->initialised) + send_keepalive(cli->fd); + last_keepalive = counter; + } + + /* check for connection timeouts */ + allidle = conn_idle_all(t, deadtime); + + if (allidle && conn_num_open()>0) { + DEBUG(2,("Closing idle connection 2.\n")); + return; + } + + if(global_machine_pasword_needs_changing) + { + unsigned char trust_passwd_hash[16]; + time_t lct; + pstring remote_machine_list; + + /* + * We're in domain level security, and the code that + * read the machine password flagged that the machine + * password needs changing. + */ + + /* + * First, open the machine password file with an exclusive lock. + */ + + if(!trust_password_lock( global_myworkgroup, global_myname, True)) { + DEBUG(0,("process: unable to open the machine account password file for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + continue; + } + + if(!get_trust_account_password( trust_passwd_hash, &lct)) { + DEBUG(0,("process: unable to read the machine account password for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + trust_password_unlock(); + continue; + } + + /* + * Make sure someone else hasn't already done this. + */ + + if(t < lct + lp_machine_password_timeout()) { + trust_password_unlock(); + global_machine_pasword_needs_changing = False; + continue; + } + + pstrcpy(remote_machine_list, lp_passwordserver()); + + change_trust_account_password( global_myworkgroup, remote_machine_list); + trust_password_unlock(); + global_machine_pasword_needs_changing = False; + } + + /* + * Check to see if we have any change notifies + * outstanding on the queue. + */ + process_pending_change_notify_queue(t); + } + + if(got_smb) + process_smb(InBuffer, OutBuffer); + else + process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); + } +} diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d81d80047b..276f5a8075 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -114,2493 +114,216 @@ void killkids(void) if(am_parent) kill(0,SIGTERM); } -/******************************************************************* -Wrapper around sys_utime that possibly allows DOS semantics rather -than POSIX. -*******************************************************************/ -int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) -{ - extern struct current_user current_user; - struct stat sb; - int ret = -1; - - errno = 0; - - if(sys_utime(fname, times) == 0) - return 0; - - if((errno != EPERM) && (errno != EACCES)) - return -1; - - if(!lp_dos_filetimes(SNUM(conn))) - return -1; - - /* We have permission (given by the Samba admin) to - break POSIX semantics and allow a user to change - the time on a file they don't own but can write to - (as DOS does). - */ - - if(sys_stat(fname,&sb) != 0) - return -1; - - /* Check if we have write access. */ - if (CAN_WRITE(conn)) { - if (((sb.st_mode & S_IWOTH) || - conn->admin_user || - ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || - ((sb.st_mode & S_IWGRP) && - in_group(sb.st_gid,current_user.gid, - current_user.ngroups,current_user.groups)))) { - /* We are allowed to become root and change the filetime. */ - become_root(False); - ret = sys_utime(fname, times); - unbecome_root(False); - } - } - - return ret; -} - -/******************************************************************* -Change a filetime - possibly allowing DOS semantics. -*******************************************************************/ -BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) -{ - struct utimbuf times; - - if (null_mtime(mtime)) return(True); - - times.modtime = times.actime = mtime; - - if (file_utime(conn, fname, ×)) { - DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); - } - - return(True); -} - - -/**************************************************************************** -fd support routines - attempt to do a sys_open -****************************************************************************/ -static int fd_attempt_open(char *fname, int flags, int mode) -{ - int fd = sys_open(fname,flags,mode); - - /* Fix for files ending in '.' */ - if((fd == -1) && (errno == ENOENT) && - (strchr(fname,'.')==NULL)) - { - pstrcat(fname,"."); - fd = sys_open(fname,flags,mode); - } - -#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) - if ((fd == -1) && (errno == ENAMETOOLONG)) - { - int max_len; - char *p = strrchr(fname, '/'); - - if (p == fname) /* name is "/xxx" */ - { - max_len = pathconf("/", _PC_NAME_MAX); - p++; - } - else if ((p == NULL) || (p == fname)) - { - p = fname; - max_len = pathconf(".", _PC_NAME_MAX); - } - else - { - *p = '\0'; - max_len = pathconf(fname, _PC_NAME_MAX); - *p = '/'; - p++; - } - if (strlen(p) > max_len) - { - char tmp = p[max_len]; - - p[max_len] = '\0'; - if ((fd = sys_open(fname,flags,mode)) == -1) - p[max_len] = tmp; - } - } -#endif - return fd; -} - -/**************************************************************************** -Cache a uid_t currently with this file open. This is an optimization only -used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ -void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) - return; - fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u; -} - -/**************************************************************************** -Remove a uid_t that currently has this file open. This is an optimization only -used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ -static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - int i; - for(i = 0; i < fd_ptr->uid_cache_count; i++) - if(fd_ptr->uid_users_cache[i] == u) { - if(i < (fd_ptr->uid_cache_count-1)) - memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1], - sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) ); - fd_ptr->uid_cache_count--; - } - return; -} - -/**************************************************************************** -Check if a uid_t that currently has this file open is present. This is an -optimization only used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ -static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - int i; - for(i = 0; i < fd_ptr->uid_cache_count; i++) - if(fd_ptr->uid_users_cache[i] == u) - return True; - return False; -} - - -/**************************************************************************** -fd support routines - attempt to re-open an already open fd as O_RDWR. -Save the already open fd (we cannot close due to POSIX file locking braindamage. -****************************************************************************/ -static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) -{ - int fd = sys_open( fname, O_RDWR, mode); - - if(fd == -1) - return; - - if(fd_ptr->real_open_flags == O_RDONLY) - fd_ptr->fd_readonly = fd_ptr->fd; - if(fd_ptr->real_open_flags == O_WRONLY) - fd_ptr->fd_writeonly = fd_ptr->fd; - - fd_ptr->fd = fd; - fd_ptr->real_open_flags = O_RDWR; -} - -/**************************************************************************** -fd support routines - attempt to close the file referenced by this fd. -Decrements the ref_count and returns it. -****************************************************************************/ -static int fd_attempt_close(file_fd_struct *fd_ptr) -{ - extern struct current_user current_user; - - DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", - fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, - fd_ptr->real_open_flags, - fd_ptr->ref_count)); - if(fd_ptr->ref_count > 0) { - fd_ptr->ref_count--; - if(fd_ptr->ref_count == 0) { - if(fd_ptr->fd != -1) - close(fd_ptr->fd); - if(fd_ptr->fd_readonly != -1) - close(fd_ptr->fd_readonly); - if(fd_ptr->fd_writeonly != -1) - close(fd_ptr->fd_writeonly); - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; - fd_ptr->uid_cache_count = 0; - } else { - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - } - } - return fd_ptr->ref_count; -} - -/**************************************************************************** -fd support routines - check that current user has permissions -to open this file. Used when uid not found in optimization cache. -This is really ugly code, as due to POSIX locking braindamage we must -fork and then attempt to open the file, and return success or failure -via an exit code. -****************************************************************************/ -static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) -{ - pid_t child_pid; - - if((child_pid = fork()) < 0) { - DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); - return False; - } - - if(child_pid) { - /* - * Parent. - */ - pid_t wpid; - int status_code; - if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { - DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n")); - return(False); - } - - if (child_pid != wpid) { - DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); - return(False); - } -#if defined(WIFEXITED) && defined(WEXITSTATUS) - if (WIFEXITED(status_code) == 0) { - DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n")); - return(False); - } - if (WEXITSTATUS(status_code) != 0) { - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); - return(False); - } -#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */ - if(status_code != 0) { - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); - return(False); - } -#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */ - - /* - * Success - the child could open the file. - */ - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code)); - return True; - } else { - /* - * Child. - */ - int fd; - DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode )); - if((fd = fd_attempt_open( fname, accmode, 0)) < 0) { - /* Access denied. */ - _exit(EACCES); - } - close(fd); - DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); - _exit(0); - } - - return False; -} - -/**************************************************************************** -check a filename for the pipe string -****************************************************************************/ -static void check_for_pipe(char *fname) -{ - /* special case of pipe opens */ - char s[10]; - StrnCpy(s,fname,9); - strlower(s); - if (strstr(s,"pipe/")) { - DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRaccess; - } -} - -/**************************************************************************** -open a file -****************************************************************************/ -static void open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,int mode, struct stat *sbuf) -{ - extern struct current_user current_user; - pstring fname; - struct stat statbuf; - file_fd_struct *fd_ptr; - int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); - - fsp->open = False; - fsp->fd_ptr = 0; - fsp->granted_oplock = False; - errno = EPERM; - - pstrcpy(fname,fname1); - - /* check permissions */ - - /* - * This code was changed after seeing a client open request - * containing the open mode of (DENY_WRITE/read-only) with - * the 'create if not exist' bit set. The previous code - * would fail to open the file read only on a read-only share - * as it was checking the flags parameter directly against O_RDONLY, - * this was failing as the flags parameter was set to O_RDONLY|O_CREAT. - * JRA. - */ - - if (conn->read_only && !conn->printer) { - /* It's a read-only share - fail if we wanted to write. */ - if(accmode != O_RDONLY) { - DEBUG(3,("Permission denied opening %s\n",fname)); - check_for_pipe(fname); - return; - } else if(flags & O_CREAT) { - /* We don't want to write - but we must make sure that O_CREAT - doesn't create the file if we have write access into the - directory. - */ - flags &= ~O_CREAT; - } - } - - /* this handles a bug in Win95 - it doesn't say to create the file when it - should */ - if (conn->printer) { - flags |= O_CREAT; - } - -/* - if (flags == O_WRONLY) - DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); -*/ - - /* - * Ensure we have a valid struct stat so we can search the - * open fd table. - */ - if(sbuf == 0) { - if(sys_stat(fname, &statbuf) < 0) { - if(errno != ENOENT) { - DEBUG(3,("Error doing stat on file %s (%s)\n", - fname,strerror(errno))); - - check_for_pipe(fname); - return; - } - sbuf = 0; - } else { - sbuf = &statbuf; - } - } - - /* - * Check to see if we have this file already - * open. If we do, just use the already open fd and increment the - * reference count (fd_get_already_open increments the ref_count). - */ - if((fd_ptr = fd_get_already_open(sbuf))!= 0) { - /* - * File was already open. - */ - - /* - * Check it wasn't open for exclusive use. - */ - if((flags & O_CREAT) && (flags & O_EXCL)) { - fd_ptr->ref_count--; - errno = EEXIST; - return; - } - - /* - * Ensure that the user attempting to open - * this file has permissions to do so, if - * the user who originally opened the file wasn't - * the same as the current user. - */ - - if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { - if(!check_access_allowed_for_current_user( fname, accmode )) { - /* Error - permission denied. */ - DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", - fname, flags, accmode)); - /* Ensure the ref_count is decremented. */ - fd_ptr->ref_count--; - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - errno = EACCES; - return; - } - } - - fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); - - /* - * If not opened O_RDWR try - * and do that here - a chmod may have been done - * between the last open and now. - */ - if(fd_ptr->real_open_flags != O_RDWR) - fd_attempt_reopen(fname, mode, fd_ptr); - - /* - * Ensure that if we wanted write access - * it has been opened for write, and if we wanted read it - * was open for read. - */ - if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) || - ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) || - ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { - DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", - fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); - check_for_pipe(fname); - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - fd_ptr->ref_count--; - return; - } - - } else { - int open_flags; - /* We need to allocate a new file_fd_struct (this increments the - ref_count). */ - if((fd_ptr = fd_get_new()) == 0) - return; - /* - * Whatever the requested flags, attempt read/write access, - * as we don't know what flags future file opens may require. - * If this fails, try again with the required flags. - * Even if we open read/write when only read access was - * requested the setting of the can_write flag in - * the file_struct will protect us from errant - * write requests. We never need to worry about O_APPEND - * as this is not set anywhere in Samba. - */ - fd_ptr->real_open_flags = O_RDWR; - /* Set the flags as needed without the read/write modes. */ - open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); - /* - * On some systems opening a file for R/W access on a read only - * filesystems sets errno to EROFS. - */ -#ifdef EROFS - if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) { -#else /* No EROFS */ - if((fd_ptr->fd == -1) && (errno == EACCES)) { -#endif /* EROFS */ - if(accmode != O_RDWR) { - fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); - fd_ptr->real_open_flags = accmode; - } - } - } - - if ((fd_ptr->fd >=0) && - conn->printer && lp_minprintspace(SNUM(conn))) { - pstring dname; - int dum1,dum2,dum3; - char *p; - pstrcpy(dname,fname); - p = strrchr(dname,'/'); - if (p) *p = 0; - if (sys_disk_free(dname,&dum1,&dum2,&dum3) < - lp_minprintspace(SNUM(conn))) { - fd_attempt_close(fd_ptr); - fsp->fd_ptr = 0; - if(fd_ptr->ref_count == 0) - sys_unlink(fname); - errno = ENOSPC; - return; - } - } - - if (fd_ptr->fd < 0) - { - DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", - fname,strerror(errno),flags)); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); - check_for_pipe(fname); - return; - } - - if (fd_ptr->fd >= 0) - { - if(sbuf == 0) { - /* Do the fstat */ - if(fstat(fd_ptr->fd, &statbuf) == -1) { - /* Error - backout !! */ - DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", - fd_ptr->fd, fname,strerror(errno))); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); - return; - } - sbuf = &statbuf; - } - - /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = (uint32)sbuf->st_dev; - fd_ptr->inode = (uint32)sbuf->st_ino; - - fsp->fd_ptr = fd_ptr; - conn->num_files_open++; - fsp->mode = sbuf->st_mode; - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; - fsp->size = 0; - fsp->pos = -1; - fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; - fsp->can_lock = True; - fsp->can_read = ((flags & O_WRONLY)==0); - fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - fsp->share_mode = 0; - fsp->print_file = conn->printer; - fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; - fsp->is_directory = False; - fsp->conn = conn; - /* - * Note that the file name here is the *untranslated* name - * ie. it is still in the DOS codepage sent from the client. - * All use of this filename will pass though the sys_xxxx - * functions which will do the dos_to_unix translation before - * mapping into a UNIX filename. JRA. - */ - string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; - - /* - * If the printer is marked as postscript output a leading - * file identifier to ensure the file is treated as a raw - * postscript file. - * This has a similar effect as CtrlD=0 in WIN.INI file. - * tim@fsg.com 09/06/94 - */ - if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { - DEBUG(3,("Writing postscript line\n")); - write_file(fsp,"%!\n",3); - } - - DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *sesssetup_user ? sesssetup_user : conn->user,fname, - BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), - conn->num_files_open)); - - } - -#if WITH_MMAP - /* mmap it if read-only */ - if (!fsp->can_write) { - fsp->mmap_size = file_size(fname); - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); - - if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { - DEBUG(3,("Failed to mmap() %s - %s\n", - fname,strerror(errno))); - fsp->mmap_ptr = NULL; - } - } -#endif -} - -/**************************************************************************** -run a file if it is a magic script -****************************************************************************/ -static void check_magic(files_struct *fsp,connection_struct *conn) -{ - if (!*lp_magicscript(SNUM(conn))) - return; - - DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); - - { - char *p; - if (!(p = strrchr(fsp->fsp_name,'/'))) - p = fsp->fsp_name; - else - p++; - - if (!strequal(lp_magicscript(SNUM(conn)),p)) - return; - } - - { - int ret; - pstring magic_output; - pstring fname; - pstrcpy(fname,fsp->fsp_name); - - if (*lp_magicoutput(SNUM(conn))) - pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); - else - slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); - - chmod(fname,0755); - ret = smbrun(fname,magic_output,False); - DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); - unlink(fname); - } -} - -/**************************************************************************** - Common code to close a file or a directory. -****************************************************************************/ -static void close_filestruct(files_struct *fsp) -{ - connection_struct *conn = fsp->conn; - - fsp->open = False; - fsp->is_directory = False; - - conn->num_files_open--; - if(fsp->wbmpx_ptr) { - free((char *)fsp->wbmpx_ptr); - fsp->wbmpx_ptr = NULL; - } - -#if WITH_MMAP - if(fsp->mmap_ptr) { - munmap(fsp->mmap_ptr,fsp->mmap_size); - fsp->mmap_ptr = NULL; - } -#endif -} - -/**************************************************************************** - Close a file - possibly invalidating the read prediction. - - If normal_close is 1 then this came from a normal SMBclose (or equivalent) - operation otherwise it came as the result of some other operation such as - the closing of the connection. In the latter case printing and - magic scripts are not run. -****************************************************************************/ -void close_file(files_struct *fsp, BOOL normal_close) -{ - uint32 dev = fsp->fd_ptr->dev; - uint32 inode = fsp->fd_ptr->inode; - int token; - connection_struct *conn = fsp->conn; - - close_filestruct(fsp); - -#if USE_READ_PREDICTION - invalidate_read_prediction(fsp->fd_ptr->fd); -#endif - - if (lp_share_modes(SNUM(conn))) { - lock_share_entry(conn, dev, inode, &token); - del_share_mode(token, fsp); - } - - fd_attempt_close(fsp->fd_ptr); - - if (lp_share_modes(SNUM(conn))) - unlock_share_entry(conn, dev, inode, token); - - /* NT uses smbclose to start a print - weird */ - if (normal_close && fsp->print_file) - print_file(conn, fsp); - - /* check for magic scripts */ - if (normal_close) { - check_magic(fsp,conn); - } - - if(fsp->granted_oplock == True) - global_oplocks_open--; - - fsp->sent_oplock_break = False; - - DEBUG(2,("%s closed file %s (numopen=%d)\n", - conn->user,fsp->fsp_name, - conn->num_files_open)); - - if (fsp->fsp_name) { - string_free(&fsp->fsp_name); - } - - file_free(fsp); -} - -/**************************************************************************** - Close a directory opened by an NT SMB call. -****************************************************************************/ - -void close_directory(files_struct *fsp) -{ - /* TODO - walk the list of pending - change notify requests and free - any pertaining to this fsp. */ - - remove_pending_change_notify_requests_by_fid(fsp); - - /* - * Do the code common to files and directories. - */ - close_filestruct(fsp); - - if (fsp->fsp_name) - string_free(&fsp->fsp_name); - - file_free(fsp); -} - -/**************************************************************************** - Open a directory from an NT SMB call. -****************************************************************************/ -int open_directory(files_struct *fsp,connection_struct *conn, - char *fname, int smb_ofun, int unixmode, int *action) -{ - extern struct current_user current_user; - struct stat st; - - if (smb_ofun & 0x10) { - /* - * Create the directory. - */ - - if(sys_mkdir(fname, unixmode) < 0) { - DEBUG(0,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); - return -1; - } - - *action = FILE_WAS_CREATED; - } else { - /* - * Check that it *was* a directory. - */ - - if(sys_stat(fname, &st) < 0) { - DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", - fname, strerror(errno) )); - return -1; - } - - if(!S_ISDIR(st.st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - return -1; - } - *action = FILE_WAS_OPENED; - } - - DEBUG(5,("open_directory: opening directory %s\n", - fname)); - - /* - * Setup the files_struct for it. - */ - - fsp->fd_ptr = NULL; - conn->num_files_open++; - fsp->mode = 0; - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; - fsp->size = 0; - fsp->pos = -1; - fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; - fsp->can_lock = True; - fsp->can_read = False; - fsp->can_write = False; - fsp->share_mode = 0; - fsp->print_file = False; - fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; - fsp->is_directory = True; - fsp->conn = conn; - /* - * Note that the file name here is the *untranslated* name - * ie. it is still in the DOS codepage sent from the client. - * All use of this filename will pass though the sys_xxxx - * functions which will do the dos_to_unix translation before - * mapping into a UNIX filename. JRA. - */ - string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; - - return 0; -} - -enum {AFAIL,AREAD,AWRITE,AALL}; - -/******************************************************************* -reproduce the share mode access table -********************************************************************/ -static int access_table(int new_deny,int old_deny,int old_mode, - int share_pid,char *fname) -{ - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - int pid = getpid(); - if (old_deny == new_deny && share_pid == pid) - return(AALL); - - if (old_mode == 0) return(AREAD); - - /* the new smbpub.zip spec says that if the file extension is - .com, .dll, .exe or .sym then allow the open. I will force - it to read-only as this seems sensible although the spec is - a little unclear on this. */ - if ((fname = strrchr(fname,'.'))) { - if (strequal(fname,".com") || - strequal(fname,".dll") || - strequal(fname,".exe") || - strequal(fname,".sym")) - return(AREAD); - } - - return(AFAIL); - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==0) return(AREAD); - if (old_deny==DENY_READ && old_mode==0) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==0) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==1) return(AREAD); - if (old_deny==DENY_READ && old_mode==1) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==1) return(AALL); - return(AFAIL); - case DENY_NONE: - if (old_deny==DENY_WRITE) return(AREAD); - if (old_deny==DENY_READ) return(AWRITE); - if (old_deny==DENY_NONE) return(AALL); - return(AFAIL); - } - return(AFAIL); -} - -/******************************************************************* -check if the share mode on a file allows it to be deleted or unlinked -return True if sharing doesn't prevent the operation -********************************************************************/ -BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) -{ - int i; - int ret = False; - share_mode_entry *old_shares = 0; - int num_share_modes; - struct stat sbuf; - int token; - int pid = getpid(); - uint32 dev, inode; - - if(!lp_share_modes(SNUM(conn))) - return True; - - if (sys_stat(fname,&sbuf) == -1) return(True); - - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; - - lock_share_entry(conn, dev, inode, &token); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); - - /* - * Check if the share modes will give us access. - */ - - if(num_share_modes != 0) - { - BOOL broke_oplock; - - do - { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * Break oplocks before checking share modes. See comment in - * open_file_shared for details. - * Check if someone has an oplock on this file. If so we must - * break it before continuing. - */ - if(share_entry->op_type & BATCH_OPLOCK) - { - - /* - * It appears that the NT redirector may have a bug, in that - * it tries to do an SMBmv on a file that it has open with a - * batch oplock, and then fails to respond to the oplock break - * request. This only seems to occur when the client is doing an - * SMBmv to the smbd it is using - thus we try and detect this - * condition by checking if the file being moved is open and oplocked by - * this smbd process, and then not sending the oplock break in this - * special case. If the file was open with a deny mode that - * prevents the move the SMBmv will fail anyway with a share - * violation error. JRA. - */ - if(rename_op && (share_entry->pid == pid)) - { - DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ -batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); - /* - * This next line is a test that allows the deny-mode - * processing to be skipped. This seems to be needed as - * NT insists on the rename succeeding (in Office 9x no less !). - * This should be removed as soon as (a) MS fix the redirector - * bug or (b) NT SMB support in Samba makes NT not issue the - * call (as is my fervent hope). JRA. - */ - continue; - } - else - { - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - return False; - } - lock_share_entry(conn, dev, inode, &token); - broke_oplock = True; - break; - } - } - - /* someone else has a share lock on it, check to see - if we can too */ - if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) - goto free_and_exit; - - } /* end for */ - - if(broke_oplock) - { - free((char *)old_shares); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); - } - } while(broke_oplock); - } - - /* XXXX exactly what share mode combinations should be allowed for - deleting/renaming? */ - /* If we got here then either there were no share modes or - all share modes were DENY_DOS and the pid == getpid() */ - ret = True; - -free_and_exit: - - unlock_share_entry(conn, dev, inode, token); - if(old_shares != NULL) - free((char *)old_shares); - return(ret); -} - -/**************************************************************************** - C. Hoch 11/22/95 - Helper for open_file_shared. - Truncate a file after checking locking; close file if locked. - **************************************************************************/ -static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, - BOOL *share_locked) -{ - if (fsp->can_write){ - if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){ - /* If share modes are in force for this connection we - have the share entry locked. Unlock it before closing. */ - if (*share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, token); - close_file(fsp,False); - /* Share mode no longer locked. */ - *share_locked = False; - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRlock; - } - else - ftruncate(fsp->fd_ptr->fd,0); - } -} - -/**************************************************************************** -check if we can open a file with a share mode -****************************************************************************/ -int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, - BOOL fcbopen, int *flags) -{ - int old_open_mode = share->share_mode &0xF; - int old_deny_mode = (share->share_mode >>4)&7; - - if (old_deny_mode > 4 || old_open_mode > 2) - { - DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", - deny_mode,old_deny_mode,old_open_mode,fname)); - return False; - } - - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); - - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags == O_WRONLY) || - (access_allowed == AWRITE && *flags == O_RDONLY)) - { - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", - deny_mode,old_deny_mode,old_open_mode, - share->pid,fname, fcbopen, *flags, access_allowed)); - return False; - } - - if (access_allowed == AREAD) - *flags = O_RDONLY; - - if (access_allowed == AWRITE) - *flags = O_WRONLY; - - } - return True; -} - -/**************************************************************************** -open a file with a share mode -****************************************************************************/ -void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, - int mode,int oplock_request, int *Access,int *action) -{ - int flags=0; - int flags2=0; - int deny_mode = (share_mode>>4)&7; - struct stat sbuf; - BOOL file_existed = file_exist(fname,&sbuf); - BOOL share_locked = False; - BOOL fcbopen = False; - int token; - uint32 dev = 0; - uint32 inode = 0; - int num_share_modes = 0; - - fsp->open = False; - fsp->fd_ptr = 0; - - /* this is for OS/2 EAs - try and say we don't support them */ - if (strstr(fname,".+,;=[].")) - { - unix_ERR_class = ERRDOS; - /* OS/2 Workplace shell fix may be main code stream in a later release. */ -#if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ - unix_ERR_code = ERRcannotopen; -#else /* OS2_WPS_FIX */ - unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; -#endif /* OS2_WPS_FIX */ - - return; - } - - if ((ofun & 0x3) == 0 && file_existed) - { - errno = EEXIST; - return; - } - - if (ofun & 0x10) - flags2 |= O_CREAT; - if ((ofun & 0x3) == 2) - flags2 |= O_TRUNC; - - /* note that we ignore the append flag as - append does not mean the same thing under dos and unix */ - - switch (share_mode&0xF) - { - case 1: - flags = O_WRONLY; - break; - case 0xF: - fcbopen = True; - flags = O_RDWR; - break; - case 2: - flags = O_RDWR; - break; - default: - flags = O_RDONLY; - break; - } - -#if defined(O_SYNC) - if (share_mode&(1<<14)) { - flags2 |= O_SYNC; - } -#endif /* O_SYNC */ - - if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) - { - if (!fcbopen) - { - errno = EACCES; - return; - } - flags = O_RDONLY; - } - - if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) - { - DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - errno = EINVAL; - return; - } - - if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; - - if (lp_share_modes(SNUM(conn))) - { - int i; - share_mode_entry *old_shares = 0; - - if (file_existed) - { - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; - lock_share_entry(conn, dev, inode, &token); - share_locked = True; - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); - } - - /* - * Check if the share modes will give us access. - */ - - if(share_locked && (num_share_modes != 0)) - { - BOOL broke_oplock; - - do - { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * By observation of NetBench, oplocks are broken *before* share - * modes are checked. This allows a file to be closed by the client - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. - */ - if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) - { - - DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - lock_share_entry(conn, dev, inode, &token); - broke_oplock = True; - break; - } - - /* someone else has a share lock on it, check to see - if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) - { - free((char *)old_shares); - unlock_share_entry(conn, dev, inode, token); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - - } /* end for */ - - if(broke_oplock) - { - free((char *)old_shares); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); - } - } while(broke_oplock); - } - - if(old_shares != 0) - free((char *)old_shares); - } - - DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - flags,flags2,mode)); - - open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); - if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen) - { - flags = O_RDONLY; - open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); - } - - if (fsp->open) - { - int open_mode=0; - - if((share_locked == False) && lp_share_modes(SNUM(conn))) - { - /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fsp->fd_ptr->dev; - inode = fsp->fd_ptr->inode; - lock_share_entry(conn, dev, inode, &token); - share_locked = True; - } - - switch (flags) - { - case O_RDONLY: - open_mode = 0; - break; - case O_RDWR: - open_mode = 2; - break; - case O_WRONLY: - open_mode = 1; - break; - } - - fsp->share_mode = (deny_mode<<4) | open_mode; - - if (Access) - (*Access) = open_mode; - - if (action) - { - if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED; - if (!file_existed) *action = FILE_WAS_CREATED; - if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN; - } - /* We must create the share mode entry before truncate as - truncate can fail due to locking and have to close the - file (which expects the share_mode_entry to be there). - */ - if (lp_share_modes(SNUM(conn))) - { - uint16 port = 0; - /* JRA. Currently this only services Exlcusive and batch - oplocks (no other opens on this file). This needs to - be extended to level II oplocks (multiple reader - oplocks). */ - - if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && - !IS_VETO_OPLOCK_PATH(conn,fname)) - { - fsp->granted_oplock = True; - fsp->sent_oplock_break = False; - global_oplocks_open++; - port = oplock_port; - - DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); - - } - else - { - port = 0; - oplock_request = 0; - } - set_share_mode(token, fsp, port, oplock_request); - } - - if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fsp,conn,token,&share_locked); - } - - if (share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, dev, inode, token); -} - - -/**************************************************************************** -load parameters specific to a connection/service -****************************************************************************/ -BOOL become_service(connection_struct *conn,BOOL do_chdir) -{ - extern char magic_char; - static connection_struct *last_conn; - int snum; - - if (!conn) { - last_conn = NULL; - return(False); - } - - conn->lastused = smb_last_time; - - snum = SNUM(conn); - - if (do_chdir && - ChDir(conn->connectpath) != 0 && - ChDir(conn->origpath) != 0) { - DEBUG(0,("chdir (%s) failed\n", - conn->connectpath)); - return(False); - } - - if (conn == last_conn) - return(True); - - last_conn = conn; - - case_default = lp_defaultcase(snum); - case_preserve = lp_preservecase(snum); - short_case_preserve = lp_shortpreservecase(snum); - case_mangle = lp_casemangle(snum); - case_sensitive = lp_casesensitive(snum); - magic_char = lp_magicchar(snum); - use_mangled_map = (*lp_mangled_map(snum) ? True:False); - return(True); -} - - -/**************************************************************************** - find a service entry -****************************************************************************/ -int find_service(char *service) -{ - int iService; - - string_sub(service,"\\","/"); - - iService = lp_servicenumber(service); - - /* now handle the special case of a home directory */ - if (iService < 0) - { - char *phome_dir = get_home_dir(service); - - if(!phome_dir) - { - /* - * Try mapping the servicename, it may - * be a Windows to unix mapped user name. - */ - if(map_username(service)) - phome_dir = get_home_dir(service); - } - - DEBUG(3,("checking for home directory %s gave %s\n",service, - phome_dir?phome_dir:"(NULL)")); - - if (phome_dir) - { - int iHomeService; - if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) - { - lp_add_home(service,iHomeService,phome_dir); - iService = lp_servicenumber(service); - } - } - } - - /* If we still don't have a service, attempt to add it as a printer. */ - if (iService < 0) - { - int iPrinterService; - - if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) - { - char *pszTemp; - - DEBUG(3,("checking whether %s is a valid printer name...\n", service)); - pszTemp = PRINTCAP; - if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) - { - DEBUG(3,("%s is a valid printer name\n", service)); - DEBUG(3,("adding %s as a printer service\n", service)); - lp_add_printer(service,iPrinterService); - iService = lp_servicenumber(service); - if (iService < 0) - DEBUG(0,("failed to add %s as a printer service!\n", service)); - } - else - DEBUG(3,("%s is not a valid printer name\n", service)); - } - } - - /* just possibly it's a default service? */ - if (iService < 0) - { - char *pdefservice = lp_defaultservice(); - if (pdefservice && *pdefservice && !strequal(pdefservice,service)) - { - /* - * We need to do a local copy here as lp_defaultservice() - * returns one of the rotating lp_string buffers that - * could get overwritten by the recursive find_service() call - * below. Fix from Josef Hinteregger . - */ - pstring defservice; - pstrcpy(defservice, pdefservice); - iService = find_service(defservice); - if (iService >= 0) - { - string_sub(service,"_","/"); - iService = lp_add_service(service,iService); - } - } - } - - if (iService >= 0) - if (!VALID_SNUM(iService)) - { - DEBUG(0,("Invalid snum %d for %s\n",iService,service)); - iService = -1; - } - - if (iService < 0) - DEBUG(3,("find_service() failed to find service %s\n", service)); - - return (iService); -} - - -/**************************************************************************** - create an error packet from a cached error. -****************************************************************************/ -int cached_error_packet(char *inbuf,char *outbuf,files_struct *fsp,int line) -{ - write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; - - int32 eclass = wbmpx->wr_errclass; - int32 err = wbmpx->wr_error; - - /* We can now delete the auxiliary struct */ - free((char *)wbmpx); - fsp->wbmpx_ptr = NULL; - return error_packet(inbuf,outbuf,eclass,err,line); -} - - -struct -{ - int unixerror; - int smbclass; - int smbcode; -} unix_smb_errmap[] = -{ - {EPERM,ERRDOS,ERRnoaccess}, - {EACCES,ERRDOS,ERRnoaccess}, - {ENOENT,ERRDOS,ERRbadfile}, - {ENOTDIR,ERRDOS,ERRbadpath}, - {EIO,ERRHRD,ERRgeneral}, - {EBADF,ERRSRV,ERRsrverror}, - {EINVAL,ERRSRV,ERRsrverror}, - {EEXIST,ERRDOS,ERRfilexists}, - {ENFILE,ERRDOS,ERRnofids}, - {EMFILE,ERRDOS,ERRnofids}, - {ENOSPC,ERRHRD,ERRdiskfull}, -#ifdef EDQUOT - {EDQUOT,ERRHRD,ERRdiskfull}, -#endif -#ifdef ENOTEMPTY - {ENOTEMPTY,ERRDOS,ERRnoaccess}, -#endif -#ifdef EXDEV - {EXDEV,ERRDOS,ERRdiffdevice}, -#endif - {EROFS,ERRHRD,ERRnowrite}, - {0,0,0} -}; - -/**************************************************************************** - create an error packet from errno -****************************************************************************/ -int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line) -{ - int eclass=def_class; - int ecode=def_code; - int i=0; - - if (unix_ERR_class != SMB_SUCCESS) - { - eclass = unix_ERR_class; - ecode = unix_ERR_code; - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - } - else - { - while (unix_smb_errmap[i].smbclass != 0) - { - if (unix_smb_errmap[i].unixerror == errno) - { - eclass = unix_smb_errmap[i].smbclass; - ecode = unix_smb_errmap[i].smbcode; - break; - } - i++; - } - } - - return(error_packet(inbuf,outbuf,eclass,ecode,line)); -} - - -/**************************************************************************** - create an error packet. Normally called using the ERROR() macro -****************************************************************************/ -int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line) -{ - int outsize = set_message(outbuf,0,0,True); - int cmd = CVAL(inbuf,smb_com); - int flgs2 = SVAL(outbuf,smb_flg2); - - if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) - { - SIVAL(outbuf,smb_rcls,error_code); - - DEBUG( 3, ( "32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", - line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf) ) ); - } - else - { - CVAL(outbuf,smb_rcls) = error_class; - SSVAL(outbuf,smb_err,error_code); - DEBUG( 3, ( "error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - line, - (int)CVAL(inbuf,smb_com), - smb_fn_name(CVAL(inbuf,smb_com)), - error_class, - error_code ) ); - - } - - if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); - - return(outsize); -} - - -/**************************************************************************** - this is called when the client exits abruptly - **************************************************************************/ -static void sig_pipe(int sig) -{ - struct cli_state *cli; - BlockSignals(True,SIGPIPE); - - if ((cli = server_client()) && cli->initialised) { - DEBUG(3,("lost connection to password server\n")); - cli_shutdown(cli); - BlockSignals(False,SIGPIPE); - return; - } - - exit_server("Got sigpipe\n"); -} - -/**************************************************************************** - open the socket communication -****************************************************************************/ -static BOOL open_sockets(BOOL is_daemon,int port) -{ - extern int Client; - - if (is_daemon) - { - int num_interfaces = iface_count(); - int fd_listenset[FD_SETSIZE]; - fd_set listen_set; - int s; - int i; - -#ifdef HAVE_ATEXIT - static int atexit_set; - if(atexit_set == 0) { - atexit_set=1; - atexit(killkids); - } -#endif - - /* Stop zombies */ - CatchChild(); - - - FD_ZERO(&listen_set); - - if(lp_interfaces() && lp_bind_interfaces_only()) - { - /* We have been given an interfaces line, and been - told to only bind to those interfaces. Create a - socket per interface and bind to only these. - */ - - if(num_interfaces > FD_SETSIZE) - { - DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ -max can be %d\n", num_interfaces, FD_SETSIZE)); - return False; - } - - /* Now open a listen socket for each of the interfaces. */ - for(i = 0; i < num_interfaces; i++) - { - struct in_addr *ifip = iface_n_ip(i); - - if(ifip == NULL) - { - DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); - continue; - } - s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr); - if(s == -1) - return False; - /* ready to listen */ - if (listen(s, 5) == -1) - { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; - } - FD_SET(s,&listen_set); - } - } - else - { - /* Just bind to 0.0.0.0 - accept connections from anywhere. */ - num_interfaces = 1; - - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address())); - if (s == -1) - return(False); - - /* ready to listen */ - if (listen(s, 5) == -1) - { - DEBUG(0,("open_sockets: listen: %s\n",strerror(errno))); - close(s); - return False; - } - - fd_listenset[0] = s; - FD_SET(s,&listen_set); - } - - /* now accept incoming connections - forking a new process - for each incoming connection */ - DEBUG(2,("waiting for a connection\n")); - while (1) - { - fd_set lfds; - int num; - - memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - - num = sys_select(&lfds,NULL); - - if (num == -1 && errno == EINTR) - continue; - - /* Find the sockets that are read-ready - accept on these. */ - for( ; num > 0; num--) - { - struct sockaddr addr; - int in_addrlen = sizeof(addr); - - s = -1; - for(i = 0; i < num_interfaces; i++) - { - if(FD_ISSET(fd_listenset[i],&lfds)) - { - s = fd_listenset[i]; - /* Clear this so we don't look at it again. */ - FD_CLR(fd_listenset[i],&lfds); - break; - } - } - - Client = accept(s,&addr,&in_addrlen); - - if (Client == -1 && errno == EINTR) - continue; - - if (Client == -1) - { - DEBUG(0,("open_sockets: accept: %s\n",strerror(errno))); - continue; - } - - if (Client != -1 && fork()==0) - { - /* Child code ... */ - - CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); - - /* close the listening socket(s) */ - for(i = 0; i < num_interfaces; i++) - close(fd_listenset[i]); - - /* close our standard file descriptors */ - close_low_fds(); - am_parent = 0; - - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - - /* Reset global variables in util.c so that - client substitutions will be done correctly - in the process. - */ - reset_globals_after_fork(); - return True; - } - close(Client); /* The parent doesn't need this socket */ - - /* - * Force parent to check log size after spawning child. - * Fix from klausr@ITAP.Physik.Uni-Stuttgart.De. - * The parent smbd will log to logserver.smb. - * It writes only two messages for each child - * started/finished. But each child writes, say, 50 messages also in - * logserver.smb, begining with the debug_count of the parent, before the - * child opens its own log file logserver.client. In a worst case - * scenario the size of logserver.smb would be checked after about - * 50*50=2500 messages (ca. 100kb). - */ - force_check_log_size(); - - } /* end for num */ - } /* end while 1 */ - } /* end if is_daemon */ - else - { - /* Started from inetd. fd 0 is the socket. */ - /* We will abort gracefully when the client or remote system - goes away */ - CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); - Client = dup(0); - - /* close our standard file descriptors */ - close_low_fds(); - - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - } - - return True; -} - -/**************************************************************************** - process an smb from the client - split out from the process() code so - it can be used by the oplock break code. -****************************************************************************/ - -static void process_smb(char *inbuf, char *outbuf) -{ - extern int Client; -#ifdef WITH_SSL - extern BOOL sslEnabled; /* don't use function for performance reasons */ - static int sslConnected = 0; -#endif /* WITH_SSL */ - static int trans_num; - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; - - if (trans_num == 0) { - /* on the first packet, check the global hosts allow/ hosts - deny parameters before doing any parsing of the packet - passed to us by the client. This prevents attacks on our - parsing code from hosts not in the hosts allow list */ - if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) { - /* send a negative session response "not listining on calling - name" */ - static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG( 1, ( "Connection denied from %s\n", - client_addr(Client) ) ); - send_smb(Client,(char *)buf); - exit_server("connection denied"); - } - } - - DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); - DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); - -#ifdef WITH_SSL - if(sslEnabled && !sslConnected){ - sslConnected = sslutil_negotiate_ssl(Client, msg_type); - if(sslConnected < 0){ /* an error occured */ - exit_server("SSL negotiation failed"); - }else if(sslConnected){ - trans_num++; - return; - } - } -#endif /* WITH_SSL */ - -#ifdef WITH_VTP - if(trans_num == 1 && VT_Check(inbuf)) - { - VT_Process(); - return; - } -#endif - - if (msg_type == 0) - show_msg(inbuf); - else if(msg_type == 0x85) - return; /* Keepalive packet. */ - - nread = construct_reply(inbuf,outbuf,nread,max_send); - - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); - - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - send_smb(Client,outbuf); - } - trans_num++; -} - -/**************************************************************************** - open the oplock IPC socket communication -****************************************************************************/ -static BOOL open_oplock_ipc(void) -{ - struct sockaddr_in sock_name; - int len = sizeof(sock_name); - - DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); - - /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK)); - if (oplock_sock == -1) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); - oplock_port = 0; - return(False); - } - - /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", - strerror(errno))); - close(oplock_sock); - oplock_sock = -1; - oplock_port = 0; - return False; - } - oplock_port = ntohs(sock_name.sin_port); - DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", - (int)getpid(), oplock_port)); - - return True; -} /**************************************************************************** - process an oplock break message. -****************************************************************************/ -static BOOL process_local_message(int sock, char *buffer, int buf_size) + this is called when the client exits abruptly + **************************************************************************/ +static void sig_pipe(int sig) { - int32 msg_len; - uint16 from_port; - char *msg_start; - - msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET); - from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET); - - msg_start = &buffer[UDP_CMD_HEADER_LEN]; - - DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", - msg_len, from_port)); - - /* Switch on message command - currently OPLOCK_BREAK_CMD is the - only valid request. */ - - switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET)) - { - case OPLOCK_BREAK_CMD: - /* Ensure that the msg length is correct. */ - if(msg_len != OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); - return False; - } - { - uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); - struct timeval tval; - struct sockaddr_in toaddr; - - tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); - tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); - - DEBUG(5,("process_local_message: oplock break request from \ -pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); - - /* - * If we have no record of any currently open oplocks, - * it's not an error, as a close command may have - * just been issued on the file that was oplocked. - * Just return success in this case. - */ - - if(global_oplocks_open != 0) - { - if(oplock_break(dev, inode, &tval) == False) - { - DEBUG(0,("process_local_message: oplock break failed - \ -not returning udp message.\n")); - return False; - } - } - else - { - DEBUG(3,("process_local_message: oplock break requested with no outstanding \ -oplocks. Returning success.\n")); - } - - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); - - bzero((char *)&toaddr,sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; - - if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) - { - DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", - remotepid, strerror(errno))); - return False; - } - - DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, - from_port, dev, inode)); - - } - break; - /* - * Keep this as a debug case - eventually we can remove it. - */ - case 0x8001: - DEBUG(0,("process_local_message: Received unsolicited break \ -reply - dumping info.\n")); - - if(msg_len != OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: ubr: incorrect length for reply \ -(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); - return False; - } - - { - uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); - - DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); + struct cli_state *cli; + BlockSignals(True,SIGPIPE); - } - return False; + if ((cli = server_client()) && cli->initialised) { + DEBUG(3,("lost connection to password server\n")); + cli_shutdown(cli); + BlockSignals(False,SIGPIPE); + return; + } - default: - DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", - (unsigned int)SVAL(msg_start,0))); - return False; - } - return True; + exit_server("Got sigpipe\n"); } /**************************************************************************** - Process an oplock break directly. + open the socket communication ****************************************************************************/ -BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) +static BOOL open_sockets(BOOL is_daemon,int port) { - extern struct current_user current_user; extern int Client; - char *inbuf = NULL; - char *outbuf = NULL; - files_struct *fsp = NULL; - time_t start_time; - BOOL shutdown_server = False; - connection_struct *saved_conn; - int saved_vuid; - pstring saved_dir; - - if( DEBUGLVL( 3 ) ) - { - dbgtext( "oplock_break: called for dev = %x, inode = %x.\n", dev, inode ); - dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); - } - - /* We need to search the file open table for the - entry containing this dev and inode, and ensure - we have an oplock on it. */ - fsp = file_find_dit(dev, inode, tval); - - if(fsp == NULL) - { - /* The file could have been closed in the meantime - return success. */ - if( DEBUGLVL( 0 ) ) - { - dbgtext( "oplock_break: cannot find open file with " ); - dbgtext( "dev = %x, inode = %x ", dev, inode); - dbgtext( "allowing break to succeed.\n" ); - } - return True; - } - - /* Ensure we have an oplock on the file */ - - /* There is a potential race condition in that an oplock could - have been broken due to another udp request, and yet there are - still oplock break messages being sent in the udp message - queue for this file. So return true if we don't have an oplock, - as we may have just freed it. - */ - - if(!fsp->granted_oplock) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "oplock_break: file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %x) has no oplock.\n", dev, inode ); - dbgtext( "Allowing break to succeed regardless.\n" ); - } - return True; - } - - /* mark the oplock break as sent - we don't want to send twice! */ - if (fsp->sent_oplock_break) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); - dbgtext( "file %s ", fsp->fsp_name); - dbgtext( "(dev = %x, inode = %x)\n", dev, inode ); - } - - /* We have to fail the open here as we cannot send another oplock break on - this file whilst we are awaiting a response from the client - neither - can we allow another open to succeed while we are waiting for the - client. - */ - return False; - } - - /* Now comes the horrid part. We must send an oplock break to the client, - and then process incoming messages until we get a close or oplock release. - At this point we know we need a new inbuf/outbuf buffer pair. - We cannot use these staticaly as we may recurse into here due to - messages crossing on the wire. - */ - - if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) - { - DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); - return False; - } - - if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) - { - DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - free(inbuf); - inbuf = NULL; - return False; - } - - /* Prepare the SMBlockingX message. */ - bzero(outbuf,smb_size); - set_message(outbuf,8,0,True); - - SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->conn->cnum); - SSVAL(outbuf,smb_pid,0xFFFF); - SSVAL(outbuf,smb_uid,0); - SSVAL(outbuf,smb_mid,0xFFFF); - SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fsp->fnum); - SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); - /* Change this when we have level II oplocks. */ - SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE); - - send_smb(Client, outbuf); - - /* Remember we just sent an oplock break on this file. */ - fsp->sent_oplock_break = True; - - /* We need this in case a readraw crosses on the wire. */ - global_oplock_break = True; - - /* Process incoming messages. */ - - /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT - seconds we should just die.... */ - - start_time = time(NULL); - - /* - * Save the information we need to re-become the - * user, then unbecome the user whilst we're doing this. - */ - saved_conn = fsp->conn; - saved_vuid = current_user.vuid; - GetWd(saved_dir); - unbecome_user(); - - while(OPEN_FSP(fsp) && fsp->granted_oplock) - { - if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) - { - /* - * Die if we got an error. - */ - - if (smb_read_error == READ_EOF) - DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); - - if (smb_read_error == READ_ERROR) - DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); - - if (smb_read_error == READ_TIMEOUT) - DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", - OPLOCK_BREAK_TIMEOUT ) ); - - DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) ); - DEBUGADD( 0, ( "(dev = %x, inode = %x).\n", dev, inode)); - shutdown_server = True; - break; - } - - /* - * There are certain SMB requests that we shouldn't allow - * to recurse. opens, renames and deletes are the obvious - * ones. This is handled in the switch_message() function. - * If global_oplock_break is set they will push the packet onto - * the pending smb queue and return -1 (no reply). - * JRA. - */ - - process_smb(inbuf, outbuf); - - /* - * Die if we go over the time limit. - */ - - if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "oplock_break: no break received from client " ); - dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); - dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %x).\n", dev, inode ); - } - shutdown_server = True; - break; - } - } - - /* - * Go back to being the user who requested the oplock - * break. - */ - if(!become_user(saved_conn, saved_vuid)) - { - DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); - DEBUGADD( 0, ( "Shutting down server\n" ) ); - close_sockets(); - close(oplock_sock); - exit_server("unable to re-become user"); - } - /* Including the directory. */ - ChDir(saved_dir); - - /* Free the buffers we've been using to recurse. */ - free(inbuf); - free(outbuf); - - /* We need this in case a readraw crossed on the wire. */ - if(global_oplock_break) - global_oplock_break = False; - - /* - * If the client did not respond we must die. - */ - - if(shutdown_server) - { - DEBUG( 0, ( "oplock_break: client failure in break - " ) ); - DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); - close_sockets(); - close(oplock_sock); - exit_server("oplock break failure"); - } - - if(OPEN_FSP(fsp)) - { - /* The lockingX reply will have removed the oplock flag - from the sharemode. */ - /* Paranoia.... */ - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; - global_oplocks_open--; - } - /* Santity check - remove this later. JRA */ - if(global_oplocks_open < 0) + if (is_daemon) { - DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", - global_oplocks_open)); - exit_server("oplock_break: global_oplocks_open < 0"); - } + int num_interfaces = iface_count(); + int fd_listenset[FD_SETSIZE]; + fd_set listen_set; + int s; + int i; - if( DEBUGLVL( 3 ) ) - { - dbgtext( "oplock_break: returning success for " ); - dbgtext( "dev = %x, inode = %x.\n", dev, inode ); - dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); +#ifdef HAVE_ATEXIT + static int atexit_set; + if(atexit_set == 0) { + atexit_set=1; + atexit(killkids); } +#endif - return True; -} + /* Stop zombies */ + CatchChild(); -/**************************************************************************** -Send an oplock break message to another smbd process. If the oplock is held -by the local smbd then call the oplock break function directly. -****************************************************************************/ -BOOL request_oplock_break(share_mode_entry *share_entry, - uint32 dev, uint32 inode) -{ - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - int pid = getpid(); - time_t start_time; - int time_left; + FD_ZERO(&listen_set); - if(pid == share_entry->pid) - { - /* We are breaking our own oplock, make sure it's us. */ - if(share_entry->op_port != oplock_port) + if(lp_interfaces() && lp_bind_interfaces_only()) { - DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ -should be %d\n", pid, share_entry->op_port, oplock_port)); - return False; - } + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ - DEBUG(5,("request_oplock_break: breaking our own oplock\n")); + if(num_interfaces > FD_SETSIZE) + { + DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ +max can be %d\n", num_interfaces, FD_SETSIZE)); + return False; + } - /* Call oplock break direct. */ - return oplock_break(dev, inode, &share_entry->time); - } + /* Now open a listen socket for each of the interfaces. */ + for(i = 0; i < num_interfaces; i++) + { + struct in_addr *ifip = iface_n_ip(i); - /* We need to send a OPLOCK_BREAK_CMD message to the - port in the share mode entry. */ - - SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); - SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); - SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); - SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); - SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); - SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); - - /* set the address and port */ - bzero((char *)&addr_out,sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; - - if( DEBUGLVL( 3 ) ) - { - dbgtext( "request_oplock_break: sending a oplock break message to " ); - dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x\n", dev, inode ); + if(ifip == NULL) + { + DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); + continue; + } + s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr); + if(s == -1) + return False; + /* ready to listen */ + if (listen(s, 5) == -1) + { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } + FD_SET(s,&listen_set); + } } + else + { + /* Just bind to 0.0.0.0 - accept connections from anywhere. */ + num_interfaces = 1; - if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) - { - if( DEBUGLVL( 0 ) ) + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address())); + if (s == -1) + return(False); + + /* ready to listen */ + if (listen(s, 5) == -1) { - dbgtext( "request_oplock_break: failed when sending a oplock " ); - dbgtext( "break message to pid %d ", share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); - dbgtext( "Error was %s\n", strerror(errno) ); + DEBUG(0,("open_sockets: listen: %s\n",strerror(errno))); + close(s); + return False; } - return False; - } - /* - * Now we must await the oplock broken message coming back - * from the target smbd process. Timeout if it fails to - * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. - * While we get messages that aren't ours, loop. - */ + fd_listenset[0] = s; + FD_SET(s,&listen_set); + } - start_time = time(NULL); - time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR; + /* now accept incoming connections - forking a new process + for each incoming connection */ + DEBUG(2,("waiting for a connection\n")); + while (1) + { + fd_set lfds; + int num; - while(time_left >= 0) - { - char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; - int32 reply_msg_len; - uint16 reply_from_port; - char *reply_msg_start; + memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), - time_left ? time_left * 1000 : 1) == False) - { - if(smb_read_error == READ_TIMEOUT) + num = sys_select(&lfds,NULL); + + if (num == -1 && errno == EINTR) + continue; + + /* Find the sockets that are read-ready - accept on these. */ + for( ; num > 0; num--) { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "request_oplock_break: no response received to oplock " ); - dbgtext( "break request to pid %d ", share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x\n", dev, inode ); - } - /* - * This is a hack to make handling of failing clients more robust. - * If a oplock break response message is not received in the timeout - * period we may assume that the smbd servicing that client holding - * the oplock has died and the client changes were lost anyway, so - * we should continue to try and open the file. - */ - break; - } - else - if( DEBUGLVL( 0 ) ) + struct sockaddr addr; + int in_addrlen = sizeof(addr); + + s = -1; + for(i = 0; i < num_interfaces; i++) + { + if(FD_ISSET(fd_listenset[i],&lfds)) { - dbgtext( "request_oplock_break: error in response received " ); - dbgtext( "to oplock break request to pid %d ", share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); - dbgtext( "Error was (%s).\n", strerror(errno) ); + s = fd_listenset[i]; + /* Clear this so we don't look at it again. */ + FD_CLR(fd_listenset[i],&lfds); + break; } - return False; - } - - reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET); - reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET); - - reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN]; + } - if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) - { - /* Ignore it. */ - DEBUG( 0, ( "request_oplock_break: invalid message length received." ) ); - DEBUGADD( 0, ( " Ignoring.\n" ) ); - continue; - } + Client = accept(s,&addr,&in_addrlen); - /* - * Test to see if this is the reply we are awaiting. - */ + if (Client == -1 && errno == EINTR) + continue; - if((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) && - (reply_from_port == share_entry->op_port) && - (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], - &op_break_msg[OPLOCK_BREAK_PID_OFFSET], - OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) - { - /* - * This is the reply we've been waiting for. - */ - break; - } - else - { - /* - * This is another message - probably a break request. - * Process it to prevent potential deadlock. - * Note that the code in switch_message() prevents - * us from recursing into here as any SMB requests - * we might process that would cause another oplock - * break request to be made will be queued. - * JRA. - */ - - process_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply)); - } + if (Client == -1) + { + DEBUG(0,("open_sockets: accept: %s\n",strerror(errno))); + continue; + } - time_left -= (time(NULL) - start_time); - } + if (Client != -1 && fork()==0) + { + /* Child code ... */ - DEBUG(3,("request_oplock_break: broke oplock.\n")); + CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); - return True; -} + /* close the listening socket(s) */ + for(i = 0; i < num_interfaces; i++) + close(fd_listenset[i]); -/**************************************************************************** -Get the next SMB packet, doing the local message processing automatically. -****************************************************************************/ + /* close our standard file descriptors */ + close_low_fds(); + am_parent = 0; + + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); -BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout) -{ - BOOL got_smb = False; - BOOL ret; + /* Reset global variables in util.c so that + client substitutions will be done correctly + in the process. + */ + reset_globals_after_fork(); + return True; + } + close(Client); /* The parent doesn't need this socket */ - do + /* + * Force parent to check log size after spawning child. + * Fix from klausr@ITAP.Physik.Uni-Stuttgart.De. + * The parent smbd will log to logserver.smb. + * It writes only two messages for each child + * started/finished. But each child writes, say, 50 messages also in + * logserver.smb, begining with the debug_count of the parent, before the + * child opens its own log file logserver.client. In a worst case + * scenario the size of logserver.smb would be checked after about + * 50*50=2500 messages (ca. 100kb). + */ + force_check_log_size(); + + } /* end for num */ + } /* end while 1 */ + } /* end if is_daemon */ + else { - ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize, - timeout,&got_smb); - - if(ret && !got_smb) - { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(oplock_sock, inbuf, bufsize); - continue; - } + /* Started from inetd. fd 0 is the socket. */ + /* We will abort gracefully when the client or remote system + goes away */ + CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); + Client = dup(0); - if(ret && (CVAL(inbuf,0) == 0x85)) - { - /* Keepalive packet. */ - got_smb = False; - } + /* close our standard file descriptors */ + close_low_fds(); + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); } - while(ret && !got_smb); - return ret; + return True; } /**************************************************************************** @@ -2613,454 +336,67 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { - pstrcpy(servicesf,fname); - test = False; - } - } - - reopen_logs(); - - if (test && !lp_file_list_changed()) - return(True); - - lp_killunused(conn_snum_used); - - ret = lp_load(servicesf,False,False,True); - - load_printers(); - - /* perhaps the config filename is now set */ - if (!test) - reload_services(True); - - reopen_logs(); - - load_interfaces(); - - { - extern int Client; - if (Client != -1) { - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - } - } - - reset_mangled_cache(); - - /* this forces service parameters to be flushed */ - become_service(NULL,True); - - return(ret); -} - - - -/**************************************************************************** -this prevents zombie child processes -****************************************************************************/ -static BOOL reload_after_sighup = False; - -static void sig_hup(int sig) -{ - BlockSignals(True,SIGHUP); - DEBUG(0,("Got SIGHUP\n")); - - /* - * Fix from here. - * We used to reload in the signal handler - this - * is a *BIG* no-no. - */ - - reload_after_sighup = True; - BlockSignals(False,SIGHUP); -} - - -/**************************************************************************** - make a connection to a service -****************************************************************************/ -connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode) -{ - int snum; - struct passwd *pass = NULL; - BOOL guest = False; - BOOL force = False; - extern int Client; - connection_struct *conn; - - strlower(service); - - snum = find_service(service); - if (snum < 0) { - extern int Client; - if (strequal(service,"IPC$")) { - DEBUG(3,("refusing IPC connection\n")); - *ecode = ERRnoipc; - return NULL; - } - - DEBUG(0,("%s (%s) couldn't find service %s\n", - remote_machine, client_addr(Client), service)); - *ecode = ERRinvnetname; - return NULL; - } - - if (strequal(service,HOMES_NAME)) { - if (*user && Get_Pwnam(user,True)) - return(make_connection(user,user,password, - pwlen,dev,vuid,ecode)); - - if(lp_security() != SEC_SHARE) { - if (validated_username(vuid)) { - pstrcpy(user,validated_username(vuid)); - return(make_connection(user,user,password,pwlen,dev,vuid,ecode)); - } - } else { - /* Security = share. Try with sesssetup_user - * as the username. */ - if(*sesssetup_user) { - pstrcpy(user,sesssetup_user); - return(make_connection(user,user,password,pwlen,dev,vuid,ecode)); - } - } - } - - if (!lp_snum_ok(snum) || - !check_access(Client, - lp_hostsallow(snum), lp_hostsdeny(snum))) { - *ecode = ERRaccess; - return NULL; - } - - /* you can only connect to the IPC$ service as an ipc device */ - if (strequal(service,"IPC$")) - pstrcpy(dev,"IPC"); - - if (*dev == '?' || !*dev) { - if (lp_print_ok(snum)) { - pstrcpy(dev,"LPT1:"); - } else { - pstrcpy(dev,"A:"); + if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { + pstrcpy(servicesf,fname); + test = False; } } - /* if the request is as a printer and you can't print then refuse */ - strupper(dev); - if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { - DEBUG(1,("Attempt to connect to non-printer as a printer\n")); - *ecode = ERRinvdevice; - return NULL; - } - - /* lowercase the user name */ - strlower(user); - - /* add it as a possible user name */ - add_session_user(service); + reopen_logs(); - /* shall we let them in? */ - if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { - DEBUG( 2, ( "Invalid username/password for %s\n", service ) ); - *ecode = ERRbadpw; - return NULL; - } - - conn = conn_new(); - if (!conn) { - DEBUG(0,("Couldn't find free connection.\n")); - *ecode = ERRnoresource; - conn_free(conn); - return NULL; - } + if (test && !lp_file_list_changed()) + return(True); - /* find out some info about the user */ - pass = Get_Pwnam(user,True); + lp_killunused(conn_snum_used); - if (pass == NULL) { - DEBUG(0,( "Couldn't find account %s\n",user)); - *ecode = ERRbaduid; - conn_free(conn); - return NULL; - } + ret = lp_load(servicesf,False,False,True); - conn->read_only = lp_readonly(snum); + load_printers(); - { - pstring list; - StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); - - if (user_in_list(user,list)) - conn->read_only = True; - - StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); - - if (user_in_list(user,list)) - conn->read_only = False; - } + /* perhaps the config filename is now set */ + if (!test) + reload_services(True); - /* admin user check */ - - /* JRA - original code denied admin user if the share was - marked read_only. Changed as I don't think this is needed, - but old code left in case there is a problem here. - */ - if (user_in_list(user,lp_admin_users(snum)) -#if 0 - && !conn->read_only -#endif - ) { - conn->admin_user = True; - DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); - } else { - conn->admin_user = False; - } - - conn->force_user = force; - conn->vuid = vuid; - conn->uid = pass->pw_uid; - conn->gid = pass->pw_gid; - conn->num_files_open = 0; - conn->lastused = time(NULL); - conn->service = snum; - conn->used = True; - conn->printer = (strncmp(dev,"LPT",3) == 0); - conn->ipc = (strncmp(dev,"IPC",3) == 0); - conn->dirptr = NULL; - conn->veto_list = NULL; - conn->hide_list = NULL; - conn->veto_oplock_list = NULL; - string_set(&conn->dirpath,""); - string_set(&conn->user,user); - -#ifdef HAVE_GETGRNAM - if (*lp_force_group(snum)) { - struct group *gptr; - pstring gname; - - StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1); - /* default service may be a group name */ - string_sub(gname,"%S",service); - gptr = (struct group *)getgrnam(gname); - - if (gptr) { - conn->gid = gptr->gr_gid; - DEBUG(3,("Forced group %s\n",gname)); - } else { - DEBUG(1,("Couldn't find group %s\n",gname)); - } - } -#endif - - if (*lp_force_user(snum)) { - struct passwd *pass2; - fstring fuser; - fstrcpy(fuser,lp_force_user(snum)); - pass2 = (struct passwd *)Get_Pwnam(fuser,True); - if (pass2) { - conn->uid = pass2->pw_uid; - string_set(&conn->user,fuser); - fstrcpy(user,fuser); - conn->force_user = True; - DEBUG(3,("Forced user %s\n",fuser)); - } else { - DEBUG(1,("Couldn't find user %s\n",fuser)); - } - } + reopen_logs(); - { - pstring s; - pstrcpy(s,lp_pathname(snum)); - standard_sub(conn,s); - string_set(&conn->connectpath,s); - DEBUG(3,("Connect path is %s\n",s)); - } + load_interfaces(); - /* groups stuff added by ih */ - conn->ngroups = 0; - conn->groups = NULL; - - if (!IS_IPC(conn)) { - /* Find all the groups this uid is in and - store them. Used by become_user() */ - setup_groups(conn->user,conn->uid,conn->gid, - &conn->ngroups,&conn->groups); - - /* check number of connections */ - if (!claim_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn)), - False)) { - DEBUG(1,("too many connections - rejected\n")); - *ecode = ERRnoresource; - conn_free(conn); - return NULL; - } - - if (lp_status(SNUM(conn))) - claim_connection(conn,"STATUS.", - MAXSTATUS,False); - } /* IS_IPC */ - - /* execute any "root preexec = " line */ - if (*lp_rootpreexec(SNUM(conn))) { - pstring cmd; - pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); - standard_sub(conn,cmd); - DEBUG(5,("cmd=%s\n",cmd)); - smbrun(cmd,NULL,False); - } - - if (!become_user(conn, conn->vuid)) { - DEBUG(0,("Can't become connected user!\n")); - if (!IS_IPC(conn)) { - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(conn))) { - yield_connection(conn,"STATUS.",MAXSTATUS); - } - } - conn_free(conn); - *ecode = ERRbadpw; - return NULL; - } - - if (ChDir(conn->connectpath) != 0) { - DEBUG(0,("Can't change directory to %s (%s)\n", - conn->connectpath,strerror(errno))); - unbecome_user(); - if (!IS_IPC(conn)) { - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(conn))) - yield_connection(conn,"STATUS.",MAXSTATUS); - } - conn_free(conn); - *ecode = ERRinvnetname; - return NULL; - } - - string_set(&conn->origpath,conn->connectpath); - -#if SOFTLINK_OPTIMISATION - /* resolve any soft links early */ { - pstring s; - pstrcpy(s,conn->connectpath); - GetWd(s); - string_set(&conn->connectpath,s); - ChDir(conn->connectpath); - } -#endif - - add_session_user(user); - - /* execute any "preexec = " line */ - if (*lp_preexec(SNUM(conn))) { - pstring cmd; - pstrcpy(cmd,lp_preexec(SNUM(conn))); - standard_sub(conn,cmd); - smbrun(cmd,NULL,False); - } - - /* we've finished with the sensitive stuff */ - unbecome_user(); - - /* Add veto/hide lists */ - if (!IS_IPC(conn) && !IS_PRINT(conn)) { - set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn))); - set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn))); - set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn))); - } - - if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { extern int Client; - - dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); - dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); - dbgtext( "as user %s ", user ); - dbgtext( "(uid=%d, gid=%d) ", conn->uid, conn->gid ); - dbgtext( "(pid %d)\n", (int)getpid() ); + if (Client != -1) { + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + } } - - return(conn); -} - -/**************************************************************************** - Attempt to break an oplock on a file (if oplocked). - Returns True if the file was closed as a result of - the oplock break, False otherwise. - Used as a last ditch attempt to free a space in the - file table when we have run out. -****************************************************************************/ -BOOL attempt_close_oplocked_file(files_struct *fsp) -{ - DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - - if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) { + reset_mangled_cache(); - /* Try and break the oplock. */ - file_fd_struct *fd_ptr = fsp->fd_ptr; - if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time)) { - if(!fsp->open) /* Did the oplock break close the file ? */ - return True; - } - } + /* this forces service parameters to be flushed */ + become_service(NULL,True); - return False; + return(ret); } /**************************************************************************** -close a cnum +this prevents zombie child processes ****************************************************************************/ -void close_cnum(connection_struct *conn, uint16 vuid) -{ - extern int Client; - DirCacheFlush(SNUM(conn)); - - unbecome_user(); +BOOL reload_after_sighup = False; - DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", - remote_machine,client_addr(Client), - lp_servicename(SNUM(conn)))); - - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); - - if (lp_status(SNUM(conn))) - yield_connection(conn,"STATUS.",MAXSTATUS); - - file_close_conn(conn); - dptr_closecnum(conn); +static void sig_hup(int sig) +{ + BlockSignals(True,SIGHUP); + DEBUG(0,("Got SIGHUP\n")); - /* execute any "postexec = " line */ - if (*lp_postexec(SNUM(conn)) && - become_user(conn, vuid)) { - pstring cmd; - pstrcpy(cmd,lp_postexec(SNUM(conn))); - standard_sub(conn,cmd); - smbrun(cmd,NULL,False); - unbecome_user(); - } + /* + * Fix from here. + * We used to reload in the signal handler - this + * is a *BIG* no-no. + */ - unbecome_user(); - /* execute any "root postexec = " line */ - if (*lp_rootpostexec(SNUM(conn))) { - pstring cmd; - pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); - standard_sub(conn,cmd); - smbrun(cmd,NULL,False); - } - - conn_free(conn); + reload_after_sighup = True; + BlockSignals(False,SIGHUP); } @@ -3141,662 +477,6 @@ void exit_server(char *reason) exit(0); } -/* -These flags determine some of the permissions required to do an operation - -Note that I don't set NEED_WRITE on some write operations because they -are used by some brain-dead clients when printing, and I don't want to -force write permissions on print services. -*/ -#define AS_USER (1<<0) -#define NEED_WRITE (1<<1) -#define TIME_INIT (1<<2) -#define CAN_IPC (1<<3) -#define AS_GUEST (1<<5) -#define QUEUE_IN_OPLOCK (1<<6) - -/* - define a list of possible SMB messages and their corresponding - functions. Any message that has a NULL function is unimplemented - - please feel free to contribute implementations! -*/ -struct smb_message_struct -{ - int code; - char *name; - int (*fn)(connection_struct *conn, char *, char *, int, int); - int flags; -#if PROFILING - unsigned long time; -#endif -} - smb_messages[] = { - - /* CORE PROTOCOL */ - - {SMBnegprot,"SMBnegprot",reply_negprot,0}, - {SMBtcon,"SMBtcon",reply_tcon,0}, - {SMBtdis,"SMBtdis",reply_tdis,0}, - {SMBexit,"SMBexit",reply_exit,0}, - {SMBioctl,"SMBioctl",reply_ioctl,0}, - {SMBecho,"SMBecho",reply_echo,0}, - {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, - {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, - {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ - {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, - {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, - {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, - {SMBsearch,"SMBsearch",reply_search,AS_USER}, - {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK }, - - /* note that SMBmknew and SMBcreate are deliberately overloaded */ - {SMBcreate,"SMBcreate",reply_mknew,AS_USER}, - {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, - - {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, - {SMBread,"SMBread",reply_read,AS_USER}, - {SMBwrite,"SMBwrite",reply_write,AS_USER}, - {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, - {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, - {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, - {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER}, - {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, - - /* this is a Pathworks specific call, allowing the - changing of the root path */ - {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, - - {SMBlseek,"SMBlseek",reply_lseek,AS_USER}, - {SMBflush,"SMBflush",reply_flush,AS_USER}, - {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, - {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK }, - {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER}, - {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER}, - {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER}, - {SMBlock,"SMBlock",reply_lock,AS_USER}, - {SMBunlock,"SMBunlock",reply_unlock,AS_USER}, - - /* CORE+ PROTOCOL FOLLOWS */ - - {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER}, - {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER}, - {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER}, - {SMBlockread,"SMBlockread",reply_lockread,AS_USER}, - {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER}, - - /* LANMAN1.0 PROTOCOL FOLLOWS */ - - {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER}, - {SMBreadBs,"SMBreadBs",NULL,AS_USER}, - {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER}, - {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER}, - {SMBwritec,"SMBwritec",NULL,AS_USER}, - {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE}, - {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER}, - {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC}, - {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC}, - {SMBioctls,"SMBioctls",NULL,AS_USER}, - {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, - {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, - - {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, - {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, - {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER}, - {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, - - {SMBffirst,"SMBffirst",reply_search,AS_USER}, - {SMBfunique,"SMBfunique",reply_search,AS_USER}, - {SMBfclose,"SMBfclose",reply_fclose,AS_USER}, - - /* LANMAN2.0 PROTOCOL FOLLOWS */ - {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, - {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER }, - {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, - - /* NT PROTOCOL FOLLOWS */ - {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, - {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, - {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, - {SMBntcancel, "SMBntcancel", reply_ntcancel, AS_USER }, - - /* messaging routines */ - {SMBsends,"SMBsends",reply_sends,AS_GUEST}, - {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST}, - {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST}, - {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST}, - - /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */ - - {SMBsendb,"SMBsendb",NULL,AS_GUEST}, - {SMBfwdname,"SMBfwdname",NULL,AS_GUEST}, - {SMBcancelf,"SMBcancelf",NULL,AS_GUEST}, - {SMBgetmac,"SMBgetmac",NULL,AS_GUEST} - }; - -/**************************************************************************** -return a string containing the function name of a SMB command -****************************************************************************/ -char *smb_fn_name(int type) -{ - static char *unknown_name = "SMBunknown"; - static int num_smb_messages = - sizeof(smb_messages) / sizeof(struct smb_message_struct); - int match; - - for (match=0;matchrequested_name); - } - - /* does this protocol need to be run as root? */ - if (!(flags & AS_USER)) - unbecome_user(); - - /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(conn,session_tag)) { - if (flags & AS_GUEST) - flags &= ~AS_USER; - else - return(ERROR(ERRSRV,ERRinvnid)); - } - /* this code is to work around a bug is MS client 3 without - introducing a security hole - it needs to be able to do - print queue checks as guest if it isn't logged in properly */ - if (flags & AS_USER) - flags &= ~AS_GUEST; - - /* does it need write permission? */ - if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); - - /* ipc services are limited */ - if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) { - return(ERROR(ERRSRV,ERRaccess)); - } - - /* load service specific parameters */ - if (conn && - !become_service(conn,(flags & AS_USER)?True:False)) { - return(ERROR(ERRSRV,ERRaccess)); - } - - /* does this protocol need to be run as guest? */ - if ((flags & AS_GUEST) && - (!become_guest() || - !check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1)))) { - return(ERROR(ERRSRV,ERRaccess)); - } - - last_inbuf = inbuf; - - outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize); - } - else - { - outsize = reply_unknown(inbuf,outbuf); - } - } - -#if PROFILING - GetTimeOfDay(&msg_end_time); - if (!(smb_messages[match].flags & TIME_INIT)) - { - smb_messages[match].time = 0; - smb_messages[match].flags |= TIME_INIT; - } - { - unsigned long this_time = - (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 + - (msg_end_time.tv_usec - msg_start_time.tv_usec); - smb_messages[match].time += this_time; - total_time += this_time; - } - DEBUG(2,("TIME %s %d usecs %g pct\n", - smb_fn_name(type),smb_messages[match].time, - (100.0*smb_messages[match].time) / total_time)); -#endif - - return(outsize); -} - - -/**************************************************************************** - construct a chained reply and add it to the already made reply - **************************************************************************/ -int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) -{ - static char *orig_inbuf; - static char *orig_outbuf; - int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); - unsigned smb_off2 = SVAL(inbuf,smb_vwv1); - char *inbuf2, *outbuf2; - int outsize2; - char inbuf_saved[smb_wct]; - char outbuf_saved[smb_wct]; - extern int chain_size; - int wct = CVAL(outbuf,smb_wct); - int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); - - /* maybe its not chained */ - if (smb_com2 == 0xFF) { - CVAL(outbuf,smb_vwv0) = 0xFF; - return outsize; - } - - if (chain_size == 0) { - /* this is the first part of the chain */ - orig_inbuf = inbuf; - orig_outbuf = outbuf; - } - - /* we need to tell the client where the next part of the reply will be */ - SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - CVAL(outbuf,smb_vwv0) = smb_com2; - - /* remember how much the caller added to the chain, only counting stuff - after the parameter words */ - chain_size += outsize - smb_wct; - - /* work out pointers into the original packets. The - headers on these need to be filled in */ - inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; - outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; - - /* remember the original command type */ - smb_com1 = CVAL(orig_inbuf,smb_com); - - /* save the data which will be overwritten by the new headers */ - memcpy(inbuf_saved,inbuf2,smb_wct); - memcpy(outbuf_saved,outbuf2,smb_wct); - - /* give the new packet the same header as the last part of the SMB */ - memmove(inbuf2,inbuf,smb_wct); - - /* create the in buffer */ - CVAL(inbuf2,smb_com) = smb_com2; - - /* create the out buffer */ - bzero(outbuf2,smb_size); - set_message(outbuf2,0,0,True); - CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com); - - memcpy(outbuf2+4,inbuf2+4,4); - CVAL(outbuf2,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf2,smb_reh) = 0; - CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf2,smb_err,SMB_SUCCESS); - SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid)); - SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid)); - SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid)); - SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid)); - - DEBUG(3,("Chained message\n")); - show_msg(inbuf2); - - /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, - bufsize-chain_size); - - /* copy the new reply and request headers over the old ones, but - preserve the smb_com field */ - memmove(orig_outbuf,outbuf2,smb_wct); - CVAL(orig_outbuf,smb_com) = smb_com1; - - /* restore the saved data, being careful not to overwrite any - data from the reply header */ - memcpy(inbuf2,inbuf_saved,smb_wct); - { - int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) ofs = 0; - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); - } - - return outsize2; -} - - -/**************************************************************************** - Helper function for contruct_reply. -****************************************************************************/ - -void construct_reply_common(char *inbuf,char *outbuf) -{ - bzero(outbuf,smb_size); - - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); - set_message(outbuf,0,0,True); - - memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf,smb_reh) = 0; - CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf,smb_err,SMB_SUCCESS); - SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); -} - -/**************************************************************************** - construct a reply to the incoming packet -****************************************************************************/ -int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) -{ - int type = CVAL(inbuf,smb_com); - int outsize = 0; - int msg_type = CVAL(inbuf,0); - extern int chain_size; - - smb_last_time = time(NULL); - - chain_size = 0; - file_chain_reset(); - reset_chain_p(); - - if (msg_type != 0) - return(reply_special(inbuf,outbuf)); - - construct_reply_common(inbuf, outbuf); - - outsize = switch_message(type,inbuf,outbuf,size,bufsize); - - outsize += chain_size; - - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); - return(outsize); -} - -/**************************************************************************** - process commands from the client -****************************************************************************/ -static void process(void) -{ - extern int Client; - - InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if ((InBuffer == NULL) || (OutBuffer == NULL)) - return; - - InBuffer += SMB_ALIGNMENT; - OutBuffer += SMB_ALIGNMENT; - -#if PRIME_NMBD - DEBUG(3,("priming nmbd\n")); - { - struct in_addr ip; - ip = *interpret_addr2("localhost"); - if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1"); - *OutBuffer = 0; - send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM); - } -#endif - - /* re-initialise the timezone */ - TimeInit(); - - while (True) - { - int deadtime = lp_deadtime()*60; - int counter; - int last_keepalive=0; - int service_load_counter = 0; - BOOL got_smb = False; - - if (deadtime <= 0) - deadtime = DEFAULT_SMBD_TIMEOUT; - -#if USE_READ_PREDICTION - if (lp_readprediction()) - do_read_prediction(); -#endif - - errno = 0; - - for (counter=SMBD_SELECT_LOOP; - !receive_message_or_smb(Client,oplock_sock, - InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); - counter += SMBD_SELECT_LOOP) - { - time_t t; - BOOL allidle = True; - extern int keepalive; - - if (counter > 365 * 3600) /* big number of seconds. */ - { - counter = 0; - service_load_counter = 0; - } - - if (smb_read_error == READ_EOF) - { - DEBUG(3,("end of file from client\n")); - return; - } - - if (smb_read_error == READ_ERROR) - { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return; - } - - t = time(NULL); - - /* become root again if waiting */ - unbecome_user(); - - /* check for smb.conf reload */ - if (counter >= service_load_counter + SMBD_RELOAD_CHECK) - { - service_load_counter = counter; - - /* reload services, if files have changed. */ - reload_services(True); - } - - /* - * If reload_after_sighup == True then we got a SIGHUP - * and are being asked to reload. Fix from - */ - - if (reload_after_sighup) - { - DEBUG(0,("Reloading services after SIGHUP\n")); - reload_services(False); - reload_after_sighup = False; - } - - /* automatic timeout if all connections are closed */ - if (conn_num_open()==0 && counter >= IDLE_CLOSED_TIMEOUT) - { - DEBUG( 2, ( "Closing idle connection\n" ) ); - return; - } - - if (keepalive && (counter-last_keepalive)>keepalive) - { - struct cli_state *cli = server_client(); - if (!send_keepalive(Client)) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return; - } - /* also send a keepalive to the password server if its still - connected */ - if (cli && cli->initialised) - send_keepalive(cli->fd); - last_keepalive = counter; - } - - /* check for connection timeouts */ - allidle = conn_idle_all(t, deadtime); - - if (allidle && conn_num_open()>0) { - DEBUG(2,("Closing idle connection 2.\n")); - return; - } - - if(global_machine_pasword_needs_changing) - { - unsigned char trust_passwd_hash[16]; - time_t lct; - pstring remote_machine_list; - - /* - * We're in domain level security, and the code that - * read the machine password flagged that the machine - * password needs changing. - */ - - /* - * First, open the machine password file with an exclusive lock. - */ - - if(!trust_password_lock( global_myworkgroup, global_myname, True)) { - DEBUG(0,("process: unable to open the machine account password file for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - continue; - } - - if(!get_trust_account_password( trust_passwd_hash, &lct)) { - DEBUG(0,("process: unable to read the machine account password for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - trust_password_unlock(); - continue; - } - - /* - * Make sure someone else hasn't already done this. - */ - - if(t < lct + lp_machine_password_timeout()) { - trust_password_unlock(); - global_machine_pasword_needs_changing = False; - continue; - } - - pstrcpy(remote_machine_list, lp_passwordserver()); - - change_trust_account_password( global_myworkgroup, remote_machine_list); - trust_password_unlock(); - global_machine_pasword_needs_changing = False; - } - - /* - * Check to see if we have any change notifies - * outstanding on the queue. - */ - process_pending_change_notify_queue(t); - } - - if(got_smb) - process_smb(InBuffer, OutBuffer); - else - process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); - } -} /**************************************************************************** @@ -4065,7 +745,7 @@ static void usage(char *pname) if( !open_oplock_ipc() ) exit(1); - process(); + smbd_process(); close_sockets(); exit_server("normal exit"); diff --git a/source3/smbd/service.c b/source3/smbd/service.c new file mode 100644 index 0000000000..b0c74aa53e --- /dev/null +++ b/source3/smbd/service.c @@ -0,0 +1,542 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + service (connection) opening and closing + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + +extern time_t smb_last_time; +extern int case_default; +extern BOOL case_preserve; +extern BOOL short_case_preserve; +extern BOOL case_mangle; +extern BOOL case_sensitive; +extern BOOL use_mangled_map; +extern fstring remote_machine; +extern pstring sesssetup_user; +extern fstring remote_machine; + + +/**************************************************************************** +load parameters specific to a connection/service +****************************************************************************/ +BOOL become_service(connection_struct *conn,BOOL do_chdir) +{ + extern char magic_char; + static connection_struct *last_conn; + int snum; + + if (!conn) { + last_conn = NULL; + return(False); + } + + conn->lastused = smb_last_time; + + snum = SNUM(conn); + + if (do_chdir && + ChDir(conn->connectpath) != 0 && + ChDir(conn->origpath) != 0) { + DEBUG(0,("chdir (%s) failed\n", + conn->connectpath)); + return(False); + } + + if (conn == last_conn) + return(True); + + last_conn = conn; + + case_default = lp_defaultcase(snum); + case_preserve = lp_preservecase(snum); + short_case_preserve = lp_shortpreservecase(snum); + case_mangle = lp_casemangle(snum); + case_sensitive = lp_casesensitive(snum); + magic_char = lp_magicchar(snum); + use_mangled_map = (*lp_mangled_map(snum) ? True:False); + return(True); +} + + +/**************************************************************************** + find a service entry +****************************************************************************/ +int find_service(char *service) +{ + int iService; + + string_sub(service,"\\","/"); + + iService = lp_servicenumber(service); + + /* now handle the special case of a home directory */ + if (iService < 0) + { + char *phome_dir = get_home_dir(service); + + if(!phome_dir) + { + /* + * Try mapping the servicename, it may + * be a Windows to unix mapped user name. + */ + if(map_username(service)) + phome_dir = get_home_dir(service); + } + + DEBUG(3,("checking for home directory %s gave %s\n",service, + phome_dir?phome_dir:"(NULL)")); + + if (phome_dir) + { + int iHomeService; + if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) + { + lp_add_home(service,iHomeService,phome_dir); + iService = lp_servicenumber(service); + } + } + } + + /* If we still don't have a service, attempt to add it as a printer. */ + if (iService < 0) + { + int iPrinterService; + + if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) + { + char *pszTemp; + + DEBUG(3,("checking whether %s is a valid printer name...\n", service)); + pszTemp = PRINTCAP; + if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) + { + DEBUG(3,("%s is a valid printer name\n", service)); + DEBUG(3,("adding %s as a printer service\n", service)); + lp_add_printer(service,iPrinterService); + iService = lp_servicenumber(service); + if (iService < 0) + DEBUG(0,("failed to add %s as a printer service!\n", service)); + } + else + DEBUG(3,("%s is not a valid printer name\n", service)); + } + } + + /* just possibly it's a default service? */ + if (iService < 0) + { + char *pdefservice = lp_defaultservice(); + if (pdefservice && *pdefservice && !strequal(pdefservice,service)) + { + /* + * We need to do a local copy here as lp_defaultservice() + * returns one of the rotating lp_string buffers that + * could get overwritten by the recursive find_service() call + * below. Fix from Josef Hinteregger . + */ + pstring defservice; + pstrcpy(defservice, pdefservice); + iService = find_service(defservice); + if (iService >= 0) + { + string_sub(service,"_","/"); + iService = lp_add_service(service,iService); + } + } + } + + if (iService >= 0) + if (!VALID_SNUM(iService)) + { + DEBUG(0,("Invalid snum %d for %s\n",iService,service)); + iService = -1; + } + + if (iService < 0) + DEBUG(3,("find_service() failed to find service %s\n", service)); + + return (iService); +} + + +/**************************************************************************** + make a connection to a service +****************************************************************************/ +connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode) +{ + int snum; + struct passwd *pass = NULL; + BOOL guest = False; + BOOL force = False; + extern int Client; + connection_struct *conn; + + strlower(service); + + snum = find_service(service); + if (snum < 0) { + extern int Client; + if (strequal(service,"IPC$")) { + DEBUG(3,("refusing IPC connection\n")); + *ecode = ERRnoipc; + return NULL; + } + + DEBUG(0,("%s (%s) couldn't find service %s\n", + remote_machine, client_addr(Client), service)); + *ecode = ERRinvnetname; + return NULL; + } + + if (strequal(service,HOMES_NAME)) { + if (*user && Get_Pwnam(user,True)) + return(make_connection(user,user,password, + pwlen,dev,vuid,ecode)); + + if(lp_security() != SEC_SHARE) { + if (validated_username(vuid)) { + pstrcpy(user,validated_username(vuid)); + return(make_connection(user,user,password,pwlen,dev,vuid,ecode)); + } + } else { + /* Security = share. Try with sesssetup_user + * as the username. */ + if(*sesssetup_user) { + pstrcpy(user,sesssetup_user); + return(make_connection(user,user,password,pwlen,dev,vuid,ecode)); + } + } + } + + if (!lp_snum_ok(snum) || + !check_access(Client, + lp_hostsallow(snum), lp_hostsdeny(snum))) { + *ecode = ERRaccess; + return NULL; + } + + /* you can only connect to the IPC$ service as an ipc device */ + if (strequal(service,"IPC$")) + pstrcpy(dev,"IPC"); + + if (*dev == '?' || !*dev) { + if (lp_print_ok(snum)) { + pstrcpy(dev,"LPT1:"); + } else { + pstrcpy(dev,"A:"); + } + } + + /* if the request is as a printer and you can't print then refuse */ + strupper(dev); + if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { + DEBUG(1,("Attempt to connect to non-printer as a printer\n")); + *ecode = ERRinvdevice; + return NULL; + } + + /* lowercase the user name */ + strlower(user); + + /* add it as a possible user name */ + add_session_user(service); + + /* shall we let them in? */ + if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { + DEBUG( 2, ( "Invalid username/password for %s\n", service ) ); + *ecode = ERRbadpw; + return NULL; + } + + conn = conn_new(); + if (!conn) { + DEBUG(0,("Couldn't find free connection.\n")); + *ecode = ERRnoresource; + conn_free(conn); + return NULL; + } + + /* find out some info about the user */ + pass = Get_Pwnam(user,True); + + if (pass == NULL) { + DEBUG(0,( "Couldn't find account %s\n",user)); + *ecode = ERRbaduid; + conn_free(conn); + return NULL; + } + + conn->read_only = lp_readonly(snum); + + { + pstring list; + StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); + string_sub(list,"%S",service); + + if (user_in_list(user,list)) + conn->read_only = True; + + StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); + string_sub(list,"%S",service); + + if (user_in_list(user,list)) + conn->read_only = False; + } + + /* admin user check */ + + /* JRA - original code denied admin user if the share was + marked read_only. Changed as I don't think this is needed, + but old code left in case there is a problem here. + */ + if (user_in_list(user,lp_admin_users(snum)) +#if 0 + && !conn->read_only +#endif + ) { + conn->admin_user = True; + DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); + } else { + conn->admin_user = False; + } + + conn->force_user = force; + conn->vuid = vuid; + conn->uid = pass->pw_uid; + conn->gid = pass->pw_gid; + conn->num_files_open = 0; + conn->lastused = time(NULL); + conn->service = snum; + conn->used = True; + conn->printer = (strncmp(dev,"LPT",3) == 0); + conn->ipc = (strncmp(dev,"IPC",3) == 0); + conn->dirptr = NULL; + conn->veto_list = NULL; + conn->hide_list = NULL; + conn->veto_oplock_list = NULL; + string_set(&conn->dirpath,""); + string_set(&conn->user,user); + +#ifdef HAVE_GETGRNAM + if (*lp_force_group(snum)) { + struct group *gptr; + pstring gname; + + StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1); + /* default service may be a group name */ + string_sub(gname,"%S",service); + gptr = (struct group *)getgrnam(gname); + + if (gptr) { + conn->gid = gptr->gr_gid; + DEBUG(3,("Forced group %s\n",gname)); + } else { + DEBUG(1,("Couldn't find group %s\n",gname)); + } + } +#endif + + if (*lp_force_user(snum)) { + struct passwd *pass2; + fstring fuser; + fstrcpy(fuser,lp_force_user(snum)); + pass2 = (struct passwd *)Get_Pwnam(fuser,True); + if (pass2) { + conn->uid = pass2->pw_uid; + string_set(&conn->user,fuser); + fstrcpy(user,fuser); + conn->force_user = True; + DEBUG(3,("Forced user %s\n",fuser)); + } else { + DEBUG(1,("Couldn't find user %s\n",fuser)); + } + } + + { + pstring s; + pstrcpy(s,lp_pathname(snum)); + standard_sub(conn,s); + string_set(&conn->connectpath,s); + DEBUG(3,("Connect path is %s\n",s)); + } + + /* groups stuff added by ih */ + conn->ngroups = 0; + conn->groups = NULL; + + if (!IS_IPC(conn)) { + /* Find all the groups this uid is in and + store them. Used by become_user() */ + setup_groups(conn->user,conn->uid,conn->gid, + &conn->ngroups,&conn->groups); + + /* check number of connections */ + if (!claim_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn)), + False)) { + DEBUG(1,("too many connections - rejected\n")); + *ecode = ERRnoresource; + conn_free(conn); + return NULL; + } + + if (lp_status(SNUM(conn))) + claim_connection(conn,"STATUS.", + MAXSTATUS,False); + } /* IS_IPC */ + + /* execute any "root preexec = " line */ + if (*lp_rootpreexec(SNUM(conn))) { + pstring cmd; + pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); + standard_sub(conn,cmd); + DEBUG(5,("cmd=%s\n",cmd)); + smbrun(cmd,NULL,False); + } + + if (!become_user(conn, conn->vuid)) { + DEBUG(0,("Can't become connected user!\n")); + if (!IS_IPC(conn)) { + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); + if (lp_status(SNUM(conn))) { + yield_connection(conn,"STATUS.",MAXSTATUS); + } + } + conn_free(conn); + *ecode = ERRbadpw; + return NULL; + } + + if (ChDir(conn->connectpath) != 0) { + DEBUG(0,("Can't change directory to %s (%s)\n", + conn->connectpath,strerror(errno))); + unbecome_user(); + if (!IS_IPC(conn)) { + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); + if (lp_status(SNUM(conn))) + yield_connection(conn,"STATUS.",MAXSTATUS); + } + conn_free(conn); + *ecode = ERRinvnetname; + return NULL; + } + + string_set(&conn->origpath,conn->connectpath); + +#if SOFTLINK_OPTIMISATION + /* resolve any soft links early */ + { + pstring s; + pstrcpy(s,conn->connectpath); + GetWd(s); + string_set(&conn->connectpath,s); + ChDir(conn->connectpath); + } +#endif + + add_session_user(user); + + /* execute any "preexec = " line */ + if (*lp_preexec(SNUM(conn))) { + pstring cmd; + pstrcpy(cmd,lp_preexec(SNUM(conn))); + standard_sub(conn,cmd); + smbrun(cmd,NULL,False); + } + + /* we've finished with the sensitive stuff */ + unbecome_user(); + + /* Add veto/hide lists */ + if (!IS_IPC(conn) && !IS_PRINT(conn)) { + set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn))); + set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn))); + set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn))); + } + + if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { + extern int Client; + + dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); + dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); + dbgtext( "as user %s ", user ); + dbgtext( "(uid=%d, gid=%d) ", conn->uid, conn->gid ); + dbgtext( "(pid %d)\n", (int)getpid() ); + } + + return(conn); +} + + +/**************************************************************************** +close a cnum +****************************************************************************/ +void close_cnum(connection_struct *conn, uint16 vuid) +{ + extern int Client; + DirCacheFlush(SNUM(conn)); + + unbecome_user(); + + DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", + remote_machine,client_addr(Client), + lp_servicename(SNUM(conn)))); + + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); + + if (lp_status(SNUM(conn))) + yield_connection(conn,"STATUS.",MAXSTATUS); + + file_close_conn(conn); + dptr_closecnum(conn); + + /* execute any "postexec = " line */ + if (*lp_postexec(SNUM(conn)) && + become_user(conn, vuid)) { + pstring cmd; + pstrcpy(cmd,lp_postexec(SNUM(conn))); + standard_sub(conn,cmd); + smbrun(cmd,NULL,False); + unbecome_user(); + } + + unbecome_user(); + /* execute any "root postexec = " line */ + if (*lp_rootpostexec(SNUM(conn))) { + pstring cmd; + pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); + standard_sub(conn,cmd); + smbrun(cmd,NULL,False); + } + + conn_free(conn); +} + + -- cgit From dd2e202e5c8d6220e29becb48fde333fa5258794 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 13:44:05 +0000 Subject: move soem variables from server.c that don't belong there. (This used to be commit f92475aa3cb3ade576c39c02c7996c949c42082a) --- source3/smbd/error.c | 4 ++++ source3/smbd/oplock.c | 14 +++++++++----- source3/smbd/process.c | 18 +++++++++++++++++- source3/smbd/server.c | 45 --------------------------------------------- 4 files changed, 30 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index ea23d8b28d..d879f9a93c 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -23,6 +23,10 @@ extern int DEBUGLEVEL; +/* these can be set by some functions to override the error codes */ +int unix_ERR_class=SMB_SUCCESS; +int unix_ERR_code=0; + /**************************************************************************** create an error packet from a cached error. diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1b49e2cfaf..d47435a0ec 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -23,11 +23,15 @@ extern int DEBUGLEVEL; -extern int oplock_sock; -extern uint16 oplock_port; -extern int32 global_oplocks_open; -extern int32 global_oplocks_open; -extern int global_oplock_break; +/* Oplock ipc UDP socket. */ +int oplock_sock = -1; +uint16 oplock_port = 0; + +/* Current number of oplocks we have outstanding. */ +int32 global_oplocks_open = 0; +BOOL global_oplock_break = False; + + extern int smb_read_error; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 30abfdb894..acc89ae146 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -23,11 +23,24 @@ extern int DEBUGLEVEL; +time_t smb_last_time=(time_t)0; + +/* + * Size of data we can send to client. Set + * by the client for all protocols above CORE. + * Set by us for CORE protocol. + */ +int max_send = BUFFER_SIZE; +/* + * Size of the data we can receive. Set by us. + * Can be modified by the max xmit parameter. + */ +int max_recv = BUFFER_SIZE; + extern int last_message; extern int global_oplock_break; extern pstring sesssetup_user; extern char *last_inbuf; -extern time_t smb_last_time; extern char *InBuffer; extern char *OutBuffer; extern int oplock_sock; @@ -645,6 +658,9 @@ void smbd_process(void) } #endif + + max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); + /* re-initialise the timezone */ TimeInit(); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 276f5a8075..7c4bc20ccc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -24,7 +24,6 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; -extern pstring sesssetup_user; extern fstring global_myworkgroup; extern pstring global_myname; @@ -42,14 +41,6 @@ int last_message = -1; extern pstring scope; extern int DEBUGLEVEL; -extern int case_default; -extern BOOL case_sensitive; -extern BOOL case_preserve; -extern BOOL use_mangled_map; -extern BOOL short_case_preserve; -extern BOOL case_mangle; -time_t smb_last_time=(time_t)0; -extern BOOL global_machine_pasword_needs_changing; extern int smb_read_error; @@ -59,43 +50,9 @@ extern pstring user_socket_options; extern int dcelogin_atmost_once; #endif /* WITH_DFS */ -/* - * This is set on startup - it defines the SID for this - * machine. - */ -extern DOM_SID global_machine_sid; - -/* - * Size of data we can send to client. Set - * by the client for all protocols above CORE. - * Set by us for CORE protocol. - */ -int max_send = BUFFER_SIZE; -/* - * Size of the data we can receive. Set by us. - * Can be modified by the max xmit parameter. - */ -int max_recv = BUFFER_SIZE; - -/* Oplock ipc UDP socket. */ -int oplock_sock = -1; -uint16 oplock_port = 0; -/* Current number of oplocks we have outstanding. */ -int32 global_oplocks_open = 0; - -BOOL global_oplock_break = False; extern fstring remote_machine; - extern pstring OriginalDir; - -/* these can be set by some functions to override the error codes */ -int unix_ERR_class=SMB_SUCCESS; -int unix_ERR_code=0; - - -extern int extra_time_offset; - extern pstring myhostname; /**************************************************************************** @@ -733,8 +690,6 @@ static void usage(char *pname) /* possibly reload the services file. */ reload_services(True); - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); - if (*lp_rootdir()) { if (sys_chroot(lp_rootdir()) == 0) -- cgit From 28788ca46c06d00a472949fd3de7b64988925283 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 14:11:44 +0000 Subject: removed some of the rough edges from the splitup (This used to be commit 722312c326d54849e2552327fcd88ac77257ad2c) --- source3/smbd/process.c | 5 + source3/smbd/server.c | 886 +++++++++++++++++++++++++------------------------ 2 files changed, 456 insertions(+), 435 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index acc89ae146..756e010d9e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -25,6 +25,11 @@ extern int DEBUGLEVEL; time_t smb_last_time=(time_t)0; +char *InBuffer = NULL; +char *OutBuffer = NULL; +char *last_inbuf = NULL; + + /* * Size of data we can send to client. Set * by the client for all protocols above CORE. diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7c4bc20ccc..41a2a10d50 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -27,10 +27,6 @@ extern pstring debugf; extern fstring global_myworkgroup; extern pstring global_myname; -char *InBuffer = NULL; -char *OutBuffer = NULL; -char *last_inbuf = NULL; - int am_parent = 1; /* the last message the was processed */ @@ -42,8 +38,6 @@ int last_message = -1; extern pstring scope; extern int DEBUGLEVEL; -extern int smb_read_error; - extern pstring user_socket_options; #ifdef WITH_DFS @@ -58,17 +52,18 @@ extern pstring myhostname; /**************************************************************************** when exiting, take the whole family ****************************************************************************/ -void *dflt_sig(void) +void *dflt_sig(void) { - exit_server("caught signal"); - return 0; /* Keep -Wall happy :-) */ + exit_server("caught signal"); + return NULL; } + /**************************************************************************** Send a SIGTERM to our process group. *****************************************************************************/ void killkids(void) { - if(am_parent) kill(0,SIGTERM); + if(am_parent) kill(0,SIGTERM); } @@ -94,193 +89,205 @@ static void sig_pipe(int sig) /**************************************************************************** open the socket communication ****************************************************************************/ -static BOOL open_sockets(BOOL is_daemon,int port) +static BOOL open_sockets_inetd(void) { - extern int Client; + extern int Client; + + /* Started from inetd. fd 0 is the socket. */ + /* We will abort gracefully when the client or remote system + goes away */ + CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); + Client = dup(0); + + /* close our standard file descriptors */ + close_low_fds(); + + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + + return True; +} - if (is_daemon) - { - int num_interfaces = iface_count(); - int fd_listenset[FD_SETSIZE]; - fd_set listen_set; - int s; - int i; +/**************************************************************************** + open the socket communication +****************************************************************************/ +static BOOL open_sockets(BOOL is_daemon,int port) +{ + extern int Client; + int num_interfaces = iface_count(); + int fd_listenset[FD_SETSIZE]; + fd_set listen_set; + int s; + int i; + + if (!is_daemon) { + return open_sockets_inetd(); + } + + #ifdef HAVE_ATEXIT - static int atexit_set; - if(atexit_set == 0) { - atexit_set=1; - atexit(killkids); - } + { + static int atexit_set; + if(atexit_set == 0) { + atexit_set=1; + atexit(killkids); + } + } #endif - /* Stop zombies */ - CatchChild(); - - - FD_ZERO(&listen_set); - - if(lp_interfaces() && lp_bind_interfaces_only()) - { - /* We have been given an interfaces line, and been - told to only bind to those interfaces. Create a - socket per interface and bind to only these. - */ - - if(num_interfaces > FD_SETSIZE) - { - DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ -max can be %d\n", num_interfaces, FD_SETSIZE)); - return False; - } - - /* Now open a listen socket for each of the interfaces. */ - for(i = 0; i < num_interfaces; i++) - { - struct in_addr *ifip = iface_n_ip(i); - - if(ifip == NULL) - { - DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); - continue; - } - s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr); - if(s == -1) - return False; - /* ready to listen */ - if (listen(s, 5) == -1) - { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; - } - FD_SET(s,&listen_set); - } - } - else - { - /* Just bind to 0.0.0.0 - accept connections from anywhere. */ - num_interfaces = 1; - - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address())); - if (s == -1) - return(False); - - /* ready to listen */ - if (listen(s, 5) == -1) - { - DEBUG(0,("open_sockets: listen: %s\n",strerror(errno))); - close(s); - return False; - } - - fd_listenset[0] = s; - FD_SET(s,&listen_set); - } - - /* now accept incoming connections - forking a new process - for each incoming connection */ - DEBUG(2,("waiting for a connection\n")); - while (1) - { - fd_set lfds; - int num; - - memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - - num = sys_select(&lfds,NULL); - - if (num == -1 && errno == EINTR) - continue; - - /* Find the sockets that are read-ready - accept on these. */ - for( ; num > 0; num--) - { - struct sockaddr addr; - int in_addrlen = sizeof(addr); - - s = -1; - for(i = 0; i < num_interfaces; i++) - { - if(FD_ISSET(fd_listenset[i],&lfds)) - { - s = fd_listenset[i]; - /* Clear this so we don't look at it again. */ - FD_CLR(fd_listenset[i],&lfds); - break; - } - } - - Client = accept(s,&addr,&in_addrlen); - - if (Client == -1 && errno == EINTR) - continue; - - if (Client == -1) - { - DEBUG(0,("open_sockets: accept: %s\n",strerror(errno))); - continue; - } - - if (Client != -1 && fork()==0) - { - /* Child code ... */ - - CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); - - /* close the listening socket(s) */ - for(i = 0; i < num_interfaces; i++) - close(fd_listenset[i]); - - /* close our standard file descriptors */ - close_low_fds(); - am_parent = 0; - - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - - /* Reset global variables in util.c so that - client substitutions will be done correctly - in the process. - */ - reset_globals_after_fork(); - return True; - } - close(Client); /* The parent doesn't need this socket */ - - /* - * Force parent to check log size after spawning child. - * Fix from klausr@ITAP.Physik.Uni-Stuttgart.De. - * The parent smbd will log to logserver.smb. - * It writes only two messages for each child - * started/finished. But each child writes, say, 50 messages also in - * logserver.smb, begining with the debug_count of the parent, before the - * child opens its own log file logserver.client. In a worst case - * scenario the size of logserver.smb would be checked after about - * 50*50=2500 messages (ca. 100kb). - */ - force_check_log_size(); + /* Stop zombies */ + CatchChild(); + + + FD_ZERO(&listen_set); + + if(lp_interfaces() && lp_bind_interfaces_only()) { + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + + if(num_interfaces > FD_SETSIZE) { + DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ +max can be %d\n", + num_interfaces, FD_SETSIZE)); + return False; + } + + /* Now open a listen socket for each of the + interfaces. */ + for(i = 0; i < num_interfaces; i++) { + struct in_addr *ifip = iface_n_ip(i); + + if(ifip == NULL) { + DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); + continue; + } + s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr); + if(s == -1) + return False; + /* ready to listen */ + if (listen(s, 5) == -1) { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } + FD_SET(s,&listen_set); + } + } else { + /* Just bind to 0.0.0.0 - accept connections + from anywhere. */ + num_interfaces = 1; + + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address())); + if (s == -1) + return(False); + + /* ready to listen */ + if (listen(s, 5) == -1) { + DEBUG(0,("open_sockets: listen: %s\n", + strerror(errno))); + close(s); + return False; + } + + fd_listenset[0] = s; + FD_SET(s,&listen_set); + } + + /* now accept incoming connections - forking a new process + for each incoming connection */ + DEBUG(2,("waiting for a connection\n")); + while (1) { + fd_set lfds; + int num; + + memcpy((char *)&lfds, (char *)&listen_set, + sizeof(listen_set)); + + num = sys_select(&lfds,NULL); + + if (num == -1 && errno == EINTR) + continue; + + /* Find the sockets that are read-ready - + accept on these. */ + for( ; num > 0; num--) { + struct sockaddr addr; + int in_addrlen = sizeof(addr); + + s = -1; + for(i = 0; i < num_interfaces; i++) { + if(FD_ISSET(fd_listenset[i],&lfds)) { + s = fd_listenset[i]; + /* Clear this so we don't look + at it again. */ + FD_CLR(fd_listenset[i],&lfds); + break; + } + } + + Client = accept(s,&addr,&in_addrlen); + + if (Client == -1 && errno == EINTR) + continue; + + if (Client == -1) { + DEBUG(0,("open_sockets: accept: %s\n", + strerror(errno))); + continue; + } + + if (Client != -1 && fork()==0) { + /* Child code ... */ + + CatchSignal(SIGPIPE, + SIGNAL_CAST sig_pipe); + + /* close the listening socket(s) */ + for(i = 0; i < num_interfaces; i++) + close(fd_listenset[i]); + + /* close our standard file + descriptors */ + close_low_fds(); + am_parent = 0; + + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + + /* Reset global variables in util.c so + that client substitutions will be + done correctly in the process. */ + reset_globals_after_fork(); + return True; + } + /* The parent doesn't need this socket */ + close(Client); + + /* Force parent to check log size after + * spawning child. Fix from + * klausr@ITAP.Physik.Uni-Stuttgart.De. The + * parent smbd will log to logserver.smb. It + * writes only two messages for each child + * started/finished. But each child writes, + * say, 50 messages also in logserver.smb, + * begining with the debug_count of the + * parent, before the child opens its own log + * file logserver.client. In a worst case + * scenario the size of logserver.smb would be + * checked after about 50*50=2500 messages + * (ca. 100kb). + * */ + force_check_log_size(); - } /* end for num */ - } /* end while 1 */ - } /* end if is_daemon */ - else - { - /* Started from inetd. fd 0 is the socket. */ - /* We will abort gracefully when the client or remote system - goes away */ - CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); - Client = dup(0); - - /* close our standard file descriptors */ - close_low_fds(); - - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - } - - return True; + } /* end for num */ + } /* end while 1 */ + + return True; } /**************************************************************************** @@ -343,17 +350,17 @@ BOOL reload_after_sighup = False; static void sig_hup(int sig) { - BlockSignals(True,SIGHUP); - DEBUG(0,("Got SIGHUP\n")); + BlockSignals(True,SIGHUP); + DEBUG(0,("Got SIGHUP\n")); - /* - * Fix from here. - * We used to reload in the signal handler - this - * is a *BIG* no-no. - */ + /* + * Fix from here. + * We used to reload in the signal handler - this + * is a *BIG* no-no. + */ - reload_after_sighup = True; - BlockSignals(False,SIGHUP); + reload_after_sighup = True; + BlockSignals(False,SIGHUP); } @@ -364,74 +371,79 @@ prepare to dump a core file - carefully! ********************************************************************/ static BOOL dump_core(void) { - char *p; - pstring dname; - pstrcpy(dname,debugf); - if ((p=strrchr(dname,'/'))) *p=0; - pstrcat(dname,"/corefiles"); - mkdir(dname,0700); - sys_chown(dname,getuid(),getgid()); - chmod(dname,0700); - if (chdir(dname)) return(False); - umask(~(0700)); + char *p; + pstring dname; + pstrcpy(dname,debugf); + if ((p=strrchr(dname,'/'))) *p=0; + pstrcat(dname,"/corefiles"); + mkdir(dname,0700); + sys_chown(dname,getuid(),getgid()); + chmod(dname,0700); + if (chdir(dname)) return(False); + umask(~(0700)); #ifdef HAVE_GETRLIMIT #ifdef RLIMIT_CORE - { - struct rlimit rlp; - getrlimit(RLIMIT_CORE, &rlp); - rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur); - setrlimit(RLIMIT_CORE, &rlp); - getrlimit(RLIMIT_CORE, &rlp); - DEBUG(3,("Core limits now %d %d\n",(int)rlp.rlim_cur,(int)rlp.rlim_max)); - } + { + struct rlimit rlp; + getrlimit(RLIMIT_CORE, &rlp); + rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur); + setrlimit(RLIMIT_CORE, &rlp); + getrlimit(RLIMIT_CORE, &rlp); + DEBUG(3,("Core limits now %d %d\n", + (int)rlp.rlim_cur,(int)rlp.rlim_max)); + } #endif #endif - DEBUG(0,("Dumping core in %s\n",dname)); - abort(); - return(True); + DEBUG(0,("Dumping core in %s\n",dname)); + abort(); + return(True); } #endif + /**************************************************************************** exit the server ****************************************************************************/ void exit_server(char *reason) { - static int firsttime=1; + static int firsttime=1; + extern char *last_inbuf; - if (!firsttime) exit(0); - firsttime = 0; - unbecome_user(); - DEBUG(2,("Closing connections\n")); + if (!firsttime) exit(0); + firsttime = 0; - conn_close_all(); + unbecome_user(); + DEBUG(2,("Closing connections\n")); + + conn_close_all(); #ifdef WITH_DFS - if (dcelogin_atmost_once) { - dfs_unlogin(); - } + if (dcelogin_atmost_once) { + dfs_unlogin(); + } #endif - if (!reason) { - int oldlevel = DEBUGLEVEL; - DEBUGLEVEL = 10; - DEBUG(0,("Last message was %s\n",smb_fn_name(last_message))); - if (last_inbuf) - show_msg(last_inbuf); - DEBUGLEVEL = oldlevel; - DEBUG(0,("===============================================================\n")); + + if (!reason) { + int oldlevel = DEBUGLEVEL; + DEBUGLEVEL = 10; + DEBUG(0,("Last message was %s\n",smb_fn_name(last_message))); + if (last_inbuf) + show_msg(last_inbuf); + DEBUGLEVEL = oldlevel; + DEBUG(0,("===============================================================\n")); #if DUMP_CORE - if (dump_core()) return; + if (dump_core()) return; #endif - } + } - locking_end(); + locking_end(); - DEBUG( 3, ( "Server exit (%s)\n", (reason ? reason : "") ) ); - exit(0); + DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); + exit(0); } @@ -441,34 +453,34 @@ void exit_server(char *reason) ****************************************************************************/ static void init_structs(void ) { - get_myname(myhostname,NULL); + get_myname(myhostname,NULL); + + /* + * Set the machine NETBIOS name if not already + * set from the config file. + */ - /* - * Set the machine NETBIOS name if not already - * set from the config file. - */ + if (!*global_myname) { + char *p; + fstrcpy( global_myname, myhostname ); + p = strchr( global_myname, '.' ); + if (p) + *p = 0; + } - if (!*global_myname) - { - char *p; - fstrcpy( global_myname, myhostname ); - p = strchr( global_myname, '.' ); - if (p) - *p = 0; - } - strupper( global_myname ); + strupper( global_myname ); - conn_init(); + conn_init(); - file_init(); + file_init(); - /* for RPC pipes */ - init_rpc_pipe_hnd(); + /* for RPC pipes */ + init_rpc_pipe_hnd(); - /* for LSA handles */ - init_lsa_policy_hnd(); + /* for LSA handles */ + init_lsa_policy_hnd(); - init_dptrs(); + init_dptrs(); } /**************************************************************************** @@ -476,18 +488,18 @@ usage on the program ****************************************************************************/ static void usage(char *pname) { - DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); - - printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname); - printf("Version %s\n",VERSION); - printf("\t-D become a daemon\n"); - printf("\t-p port listen on the specified port\n"); - printf("\t-d debuglevel set the debuglevel\n"); - printf("\t-l log basename. Basename for log/debug files\n"); - printf("\t-s services file. Filename of services file\n"); - printf("\t-P passive only\n"); - printf("\t-a overwrite log file, don't append\n"); - printf("\n"); + DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); + + printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname); + printf("Version %s\n",VERSION); + printf("\t-D become a daemon\n"); + printf("\t-p port listen on the specified port\n"); + printf("\t-d debuglevel set the debuglevel\n"); + printf("\t-l log basename. Basename for log/debug files\n"); + printf("\t-s services file. Filename of services file\n"); + printf("\t-P passive only\n"); + printf("\t-a overwrite log file, don't append\n"); + printf("\n"); } @@ -496,213 +508,217 @@ static void usage(char *pname) ****************************************************************************/ int main(int argc,char *argv[]) { - extern BOOL append_log; - /* shall I run as a daemon */ - BOOL is_daemon = False; - int port = SMB_PORT; - int opt; - extern char *optarg; - + extern BOOL append_log; + /* shall I run as a daemon */ + BOOL is_daemon = False; + int port = SMB_PORT; + int opt; + extern char *optarg; + #ifdef HAVE_SET_AUTH_PARAMETERS - set_auth_parameters(argc,argv); + set_auth_parameters(argc,argv); #endif #ifdef HAVE_SETLUID - /* needed for SecureWare on SCO */ - setluid(0); + /* needed for SecureWare on SCO */ + setluid(0); #endif - append_log = True; + append_log = True; - TimeInit(); + TimeInit(); - pstrcpy(debugf,SMBLOGFILE); + pstrcpy(debugf,SMBLOGFILE); - pstrcpy(remote_machine, "smb"); + pstrcpy(remote_machine, "smb"); - setup_logging(argv[0],False); + setup_logging(argv[0],False); - charset_initialise(); + charset_initialise(); - /* make absolutely sure we run as root - to handle cases where people - are crazy enough to have it setuid */ + /* make absolutely sure we run as root - to handle cases where people + are crazy enough to have it setuid */ #ifdef HAVE_SETRESUID - setresuid(0,0,0); + setresuid(0,0,0); #else - setuid(0); - seteuid(0); - setuid(0); - seteuid(0); + setuid(0); + seteuid(0); + setuid(0); + seteuid(0); #endif - fault_setup((void (*)(void *))exit_server); - CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig); - - /* we want total control over the permissions on created files, - so set our umask to 0 */ - umask(0); - - GetWd(OriginalDir); - - init_uid(); - - /* this is for people who can't start the program correctly */ - while (argc > 1 && (*argv[1] != '-')) - { - argv++; - argc--; - } - - while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF) - switch (opt) - { - case 'O': - pstrcpy(user_socket_options,optarg); - break; - case 'i': - pstrcpy(scope,optarg); - break; - case 'P': - { - extern BOOL passive; - passive = True; - } - break; - case 's': - pstrcpy(servicesf,optarg); - break; - case 'l': - pstrcpy(debugf,optarg); - break; - case 'a': - { - extern BOOL append_log; - append_log = !append_log; + fault_setup((void (*)(void *))exit_server); + CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig); + + /* we want total control over the permissions on created files, + so set our umask to 0 */ + umask(0); + + GetWd(OriginalDir); + + init_uid(); + + /* this is for people who can't start the program correctly */ + while (argc > 1 && (*argv[1] != '-')) { + argv++; + argc--; } - break; - case 'D': - is_daemon = True; - break; - case 'd': - if (*optarg == 'A') - DEBUGLEVEL = 10000; - else - DEBUGLEVEL = atoi(optarg); - break; - case 'p': - port = atoi(optarg); - break; - case 'h': - usage(argv[0]); - exit(0); - break; - default: - usage(argv[0]); - exit(1); - } - reopen_logs(); + while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF) + switch (opt) { + case 'O': + pstrcpy(user_socket_options,optarg); + break; + + case 'i': + pstrcpy(scope,optarg); + break; + + case 'P': + { + extern BOOL passive; + passive = True; + } + break; + + case 's': + pstrcpy(servicesf,optarg); + break; + + case 'l': + pstrcpy(debugf,optarg); + break; + + case 'a': + { + extern BOOL append_log; + append_log = !append_log; + } + break; + + case 'D': + is_daemon = True; + break; + + case 'd': + if (*optarg == 'A') + DEBUGLEVEL = 10000; + else + DEBUGLEVEL = atoi(optarg); + break; + + case 'p': + port = atoi(optarg); + break; + + case 'h': + usage(argv[0]); + exit(0); + break; + + default: + usage(argv[0]); + exit(1); + } - DEBUG( 1, ( "smbd version %s started.\n", VERSION ) ); - DEBUGADD( 1, ( "Copyright Andrew Tridgell 1992-1997\n" ) ); + reopen_logs(); - DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", - (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); + DEBUG(1,( "smbd version %s started.\n", VERSION)); + DEBUGADD(1,( "Copyright Andrew Tridgell 1992-1997\n")); - if (sizeof(uint16) < 2 || sizeof(uint32) < 4) - { - DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); - exit(1); - } + DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", + (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); - init_structs(); + if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { + DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); + exit(1); + } - if (!reload_services(False)) - return(-1); + init_structs(); + + if (!reload_services(False)) + return(-1); #ifdef WITH_SSL - { - extern BOOL sslEnabled; - sslEnabled = lp_ssl_enabled(); - if(sslEnabled) - sslutil_init(True); - } + { + extern BOOL sslEnabled; + sslEnabled = lp_ssl_enabled(); + if(sslEnabled) + sslutil_init(True); + } #endif /* WITH_SSL */ - codepage_initialise(lp_client_code_page()); + codepage_initialise(lp_client_code_page()); - pstrcpy(global_myworkgroup, lp_workgroup()); + pstrcpy(global_myworkgroup, lp_workgroup()); - if(!pdb_generate_machine_sid()) { - DEBUG(0,("ERROR: Samba cannot get a machine SID.\n")); - exit(1); - } - - CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); + if(!pdb_generate_machine_sid()) { + DEBUG(0,("ERROR: Samba cannot get a machine SID.\n")); + exit(1); + } - /* Setup the signals that allow the debug log level - to by dynamically changed. */ + CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); + + /* Setup the signals that allow the debug log level + to by dynamically changed. */ - /* If we are using the malloc debug code we can't use - SIGUSR1 and SIGUSR2 to do debug level changes. */ - + /* If we are using the malloc debug code we can't use + SIGUSR1 and SIGUSR2 to do debug level changes. */ + #ifndef MEM_MAN #if defined(SIGUSR1) - CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 ); + CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 ); #endif /* SIGUSR1 */ #if defined(SIGUSR2) - CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 ); + CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 ); #endif /* SIGUSR2 */ #endif /* MEM_MAN */ - DEBUG( 3, ( "loaded services\n" ) ); + DEBUG(3,( "loaded services\n")); - if (!is_daemon && !is_a_socket(0)) - { - DEBUG(0,("standard input is not a socket, assuming -D option\n")); - is_daemon = True; - } - - if (is_daemon) - { - DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(); - } - - if (!directory_exist(lp_lockdir(), NULL)) { - mkdir(lp_lockdir(), 0755); - } + if (!is_daemon && !is_a_socket(0)) { + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + is_daemon = True; + } - if (is_daemon) { - pidfile_create("smbd"); - } + if (is_daemon) { + DEBUG( 3, ( "Becoming a daemon.\n" ) ); + become_daemon(); + } - if (!open_sockets(is_daemon,port)) - exit(1); + if (!directory_exist(lp_lockdir(), NULL)) { + mkdir(lp_lockdir(), 0755); + } - if (!locking_init(0)) - exit(1); + if (is_daemon) { + pidfile_create("smbd"); + } - if(!initialize_password_db()) - exit(1); + if (!open_sockets(is_daemon,port)) + exit(1); - /* possibly reload the services file. */ - reload_services(True); + if (!locking_init(0)) + exit(1); - if (*lp_rootdir()) - { - if (sys_chroot(lp_rootdir()) == 0) - DEBUG( 2, ( "Changed root to %s\n", lp_rootdir() ) ); - } + if(!initialize_password_db()) + exit(1); - /* Setup the oplock IPC socket. */ - if( !open_oplock_ipc() ) - exit(1); + /* possibly reload the services file. */ + reload_services(True); + + if (*lp_rootdir()) { + if (sys_chroot(lp_rootdir()) == 0) + DEBUG(2,("Changed root to %s\n", lp_rootdir())); + } - smbd_process(); - close_sockets(); + /* Setup the oplock IPC socket. */ + if( !open_oplock_ipc() ) + exit(1); - exit_server("normal exit"); - return(0); + smbd_process(); + close_sockets(); + + exit_server("normal exit"); + return(0); } -- cgit From b935fc086285e73203e5f3af80041489e893ee1a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Aug 1998 22:59:53 +0000 Subject: Fixed bug introduced by the recent changes where the chain_fnum could be overwritten in oplock processing code. Jeremy. (This used to be commit 908a583b48e37c5e869216f4dc92d4a587ff1238) --- source3/smbd/files.c | 20 ++- source3/smbd/nttrans.c | 339 ++++++++++++++++++++++++------------------------- source3/smbd/oplock.c | 5 + 3 files changed, 193 insertions(+), 171 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index fa1b8f3bac..4f87802119 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -37,7 +37,8 @@ static files_struct *Files; /* a fsp to use when chaining */ static files_struct *chain_fsp = NULL; - +/* a fsp to use to save when breaking an oplock. */ +static files_struct *oplock_save_chain_fsp = NULL; /* * Indirection for file fd's. Needed as POSIX locking @@ -387,3 +388,20 @@ void file_chain_reset(void) { chain_fsp = NULL; } + +/**************************************************************************** +Save the chained fsp - done when about to do an oplock break. +****************************************************************************/ + +void file_chain_save(void) +{ + oplock_save_chain_fsp = chain_fsp; +} + +/**************************************************************************** +Restore the chained fsp - done after an oplock break. +****************************************************************************/ +void file_chain_restore(void) +{ + chain_fsp = oplock_save_chain_fsp; +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 89efd7ccd7..61826fa0ee 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -447,166 +447,186 @@ int reply_ntcreate_and_X(connection_struct *conn, fname[fname_len] = '\0'; /* If it's an IPC, use the pipe handler. */ + if (IS_IPC(conn)) { + int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) return ret; - smb_action = FILE_WAS_OPENED; - } else { /* - * Ordinary file or directory. - */ + * Deal with pipe return. + */ + + set_message(outbuf,34,0,True); + + p = outbuf + smb_vwv2; + p++; + SSVAL(p,0,pnum); + p += 2; + SIVAL(p,0,FILE_WAS_OPENED); + p += 4; + p += 32; + SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ + p += 20; + /* File type. */ + SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); + /* Device state. */ + SSVAL(p,2, 0x5FF); /* ? */ + } + + /* + * Ordinary file or directory. + */ - /* - * Check if POSIX semantics are wanted. - */ + /* + * Check if POSIX semantics are wanted. + */ - set_posix_case_semantics(file_attributes); + set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path); - fsp = file_new(); - if (!fsp) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); + fsp = file_new(); + if (!fsp) { + restore_case_semantics(file_attributes); + return(ERROR(ERRSRV,ERRnofids)); + } + + if (!check_name(fname,conn)) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; } + file_free(fsp); - if (!check_name(fname,conn)) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - - restore_case_semantics(file_attributes); - - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - unixmode = unix_mode(conn,smb_attr | aARCH); + unixmode = unix_mode(conn,smb_attr | aARCH); - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - /* - * If it's a request for a directory open, deal with it separately. - */ + /* + * If it's a request for a directory open, deal with it separately. + */ - if(flags & OPEN_DIRECTORY) { - oplock_request = 0; - - open_directory(fsp, conn, fname, smb_ofun, - unixmode, &smb_action); + if(flags & OPEN_DIRECTORY) { + oplock_request = 0; + + open_directory(fsp, conn, fname, smb_ofun, + unixmode, &smb_action); - restore_case_semantics(file_attributes); + restore_case_semantics(file_attributes); - if(!fsp->open) { - file_free(fsp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } else { - /* - * Ordinary file case. - */ - - /* NB. We have a potential bug here. If we - * cause an oplock break to ourselves, then we - * could end up processing filename related - * SMB requests whilst we await the oplock - * break response. As we may have changed the - * filename case semantics to be POSIX-like, - * this could mean a filename request could - * fail when it should succeed. This is a rare - * condition, but eventually we must arrange - * to restore the correct case semantics - * before issuing an oplock break request to - * our client. JRA. */ - - open_file_shared(fsp,conn,fname,smb_open_mode, - smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); - - if (!fsp->open) { - /* We cheat here. The only case we - * care about is a directory rename, - * where the NT client will attempt to - * open the source directory for - * DELETE access. Note that when the - * NT client does this it does *not* - * set the directory bit in the * - * request packet. This is translated - * into a read/write open * - * request. POSIX states that any open - * for write request on a directory * - * will generate an EISDIR error, so - * we can catch this here and open * a - * pseudo handle that is flagged as a - * directory. JRA. */ - - if(errno == EISDIR) { - oplock_request = 0; - - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); - - if(!fsp->open) { - file_free(fsp); - restore_case_semantics(file_attributes); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } else { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - + if(!fsp->open) { + file_free(fsp); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + /* + * Ordinary file case. + */ + + /* NB. We have a potential bug here. If we + * cause an oplock break to ourselves, then we + * could end up processing filename related + * SMB requests whilst we await the oplock + * break response. As we may have changed the + * filename case semantics to be POSIX-like, + * this could mean a filename request could + * fail when it should succeed. This is a rare + * condition, but eventually we must arrange + * to restore the correct case semantics + * before issuing an oplock break request to + * our client. JRA. */ + + open_file_shared(fsp,conn,fname,smb_open_mode, + smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); + + if (!fsp->open) { + /* We cheat here. The only case we + * care about is a directory rename, + * where the NT client will attempt to + * open the source directory for + * DELETE access. Note that when the + * NT client does this it does *not* + * set the directory bit in the + * request packet. This is translated + * into a read/write open + * request. POSIX states that any open + * for write request on a directory + * will generate an EISDIR error, so + * we can catch this here and open a + * pseudo handle that is flagged as a + * directory. JRA. */ + + if(errno == EISDIR) { + oplock_request = 0; + + open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + + if(!fsp->open) { file_free(fsp); - restore_case_semantics(file_attributes); - return(UNIXERROR(ERRDOS,ERRnoaccess)); } - } - } - - if(fsp->is_directory) { - if(sys_stat(fsp->fsp_name, &sbuf) != 0) { - close_directory(fsp); + } else { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + + file_free(fsp); + restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - } else { - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fsp,False); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } - - restore_case_semantics(file_attributes); + } + } - file_len = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) - fmode = FILE_ATTRIBUTE_NORMAL; - mtime = sbuf.st_mtime; - if (!fsp->is_directory && (fmode & aDIR)) { + if(fsp->is_directory) { + if(sys_stat(fsp->fsp_name, &sbuf) != 0) { + close_directory(fsp); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } else { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); + restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } + } - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ - - if (oplock_request && lp_fake_oplocks(SNUM(conn))) - smb_action |= EXTENDED_OPLOCK_GRANTED; + restore_case_semantics(file_attributes); - if(oplock_request && fsp->granted_oplock) - smb_action |= EXTENDED_OPLOCK_GRANTED; - } + file_len = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + if(fmode == 0) + fmode = FILE_ATTRIBUTE_NORMAL; + mtime = sbuf.st_mtime; + if (!fsp->is_directory && (fmode & aDIR)) { + close_file(fsp,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) + smb_action |= EXTENDED_OPLOCK_GRANTED; + + if(oplock_request && fsp->granted_oplock) + smb_action |= EXTENDED_OPLOCK_GRANTED; set_message(outbuf,34,0,True); @@ -619,53 +639,32 @@ int reply_ntcreate_and_X(connection_struct *conn, SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); p++; - if (IS_IPC(conn)) { - SSVAL(p,0,pnum); - } else { - SSVAL(p,0,fsp->fnum); - } + SSVAL(p,0,fsp->fnum); p += 2; SIVAL(p,0,smb_action); p += 4; - if (IS_IPC(conn)) { - /* - * Deal with pipe return. - */ - p += 32; - SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ - p += 20; - /* File type. */ - SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); - /* Device state. */ - SSVAL(p,2, 0x5FF); /* ? */ - } else { - /* - * Deal with file return. - */ - /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); - p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ - p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ - p += 12; + /* Create time. */ + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fmode); /* File Attributes. */ + p += 12; #if OFF_T_IS_64_BITS - SIVAL(p,0, file_len & 0xFFFFFFFF); - SIVAL(p,4, file_len >> 32); + SIVAL(p,0, file_len & 0xFFFFFFFF); + SIVAL(p,4, file_len >> 32); #else /* OFF_T_IS_64_BITS */ - SIVAL(p,0,file_len); + SIVAL(p,0,file_len); #endif /* OFF_T_IS_64_BITS */ - p += 12; - SCVAL(p,0,fsp->is_directory ? 1 : 0); - } + p += 12; + SCVAL(p,0,fsp->is_directory ? 1 : 0); - DEBUG(5,("reply_ntcreate_and_X: open name = %s\n", - fsp?fsp->fsp_name:"NULL")); + DEBUG(5,("reply_ntcreate_and_X: open name = %s\n", fsp->fsp_name)); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -700,7 +699,7 @@ static int call_nt_transact_create(connection_struct *conn, struct stat sbuf; int smb_action = 0; BOOL bad_path = False; - files_struct *fsp; + files_struct *fsp = NULL; char *p = NULL; /* diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index d47435a0ec..d9df308a35 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -329,6 +329,8 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) saved_vuid = current_user.vuid; GetWd(saved_dir); unbecome_user(); + /* Save the chain fnum. */ + file_chain_save(); while(OPEN_FSP(fsp) && fsp->granted_oplock) { @@ -398,6 +400,9 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) /* Including the directory. */ ChDir(saved_dir); + /* Restore the chain fnum. */ + file_chain_restore(); + /* Free the buffers we've been using to recurse. */ free(inbuf); free(outbuf); -- cgit From 1e6837837ac402702ccadcbcfd853b8c673c783a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Aug 1998 23:39:59 +0000 Subject: smbd/nttrans.c: Fixed bug in split off pipe code. locking/locking.c: More blocking lock changes. Jeremy. (This used to be commit 2ca4fc95a4227645f1009a057d46b58508846a92) --- source3/smbd/nttrans.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 61826fa0ee..b5ed42fbb3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -473,6 +473,10 @@ int reply_ntcreate_and_X(connection_struct *conn, SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); /* Device state. */ SSVAL(p,2, 0x5FF); /* ? */ + + DEBUG(5,("reply_ntcreate_and_X: open pipe = %s\n", fname)); + + return chain_reply(inbuf,outbuf,length,bufsize); } /* -- cgit From 12de4034c72ea5054d716bf848c2b16bef7a4d89 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Aug 1998 01:49:34 +0000 Subject: Makefile.in: Moved blocking lock code into smbd/blocking.c for link purposes. include/includes.h: Added nterr.h. locking/locking.c: Moved blocking lock code into smbd/blocking.c for link purposes. smbd/close.c: Added blocking lock removal to file close. smbd/filename.c: Tidied up unix_convert() so I could read it (:-) in preparation for the stat_cache code. smbd/nttrans.c: Added WRITE_ATTRIBUTES check. smbd/reply.c: Fixed multibyte char problem in wildcard mask. Jeremy. (This used to be commit 148eaba3dadb1d0bd3ac3ef53da3d9811636e89a) --- source3/smbd/close.c | 6 +- source3/smbd/filename.c | 254 +++++++++++++++++++++++++++++------------------- source3/smbd/nttrans.c | 5 +- source3/smbd/reply.c | 28 ++++-- 4 files changed, 176 insertions(+), 117 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 9bc0a89338..b8063ca3f4 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -142,6 +142,8 @@ void close_file(files_struct *fsp, BOOL normal_close) string_free(&fsp->fsp_name); } + remove_pending_lock_requests_by_fid(fsp); + file_free(fsp); } @@ -151,10 +153,6 @@ void close_file(files_struct *fsp, BOOL normal_close) void close_directory(files_struct *fsp) { - /* TODO - walk the list of pending - change notify requests and free - any pertaining to this fsp. */ - remove_pending_change_notify_requests_by_fid(fsp); /* diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a6a9e7e7f0..ab5851fb5e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -102,6 +102,7 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ + BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) { struct stat st; @@ -115,17 +116,24 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(saved_last_component) *saved_last_component = 0; - /* convert to basic unix format - removing \ chars and cleaning it up */ + /* + * Convert to basic unix format - removing \ chars and cleaning it up. + */ + unix_format(name); unix_clean_name(name); - /* names must be relative to the root of the service - trim any leading /. - also trim trailing /'s */ + /* + * Names must be relative to the root of the service - trim any leading /. + * also trim trailing /'s. + */ + trim_string(name,"/","/"); /* * Ensure saved_last_component is valid even if file exists. */ + if(saved_last_component) { end = strrchr(name, '/'); if(end) @@ -138,23 +146,30 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) strnorm(name); - /* check if it's a printer file */ - if (conn->printer) - { - if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) - { - char *s; - fstring name2; - slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); - /* sanitise the name */ - for (s=name2 ; *s ; s++) - if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)mktemp(name2)); - } - return(True); - } + /* + * Check if it's a printer file. + */ + if (conn->printer) { + if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) { + char *s; + fstring name2; + slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); + + /* + * Sanitise the name. + */ + + for (s=name2 ; *s ; s++) + if (!issafe(*s)) *s = '_'; + pstrcpy(name,(char *)mktemp(name2)); + } + return(True); + } + + /* + * stat the name - if it exists then we are all done! + */ - /* stat the name - if it exists then we are all done! */ if (sys_stat(name,&st) == 0) return(True); @@ -162,109 +177,144 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, DEBUG(5,("unix_convert(%s)\n",name)); - /* a special case - if we don't have any mangling chars and are case - sensitive then searching won't help */ + /* + * A special case - if we don't have any mangling chars and are case + * sensitive then searching won't help. + */ + if (case_sensitive && !is_mangled(name) && !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) return(False); - /* now we need to recursively match the name against the real - directory structure */ + /* + * Now we need to recursively match the name against the real + * directory structure. + */ start = name; while (strncmp(start,"./",2) == 0) start += 2; - /* now match each part of the path name separately, trying the names - as is first, then trying to scan the directory for matching names */ - for (;start;start = (end?end+1:(char *)NULL)) - { - /* pinpoint the end of this section of the filename */ + /* + * Match each part of the path name separately, trying the names + * as is first, then trying to scan the directory for matching names. + */ + + for (;start;start = (end?end+1:(char *)NULL)) { + /* + * Pinpoint the end of this section of the filename. + */ end = strchr(start, '/'); - /* chop the name at this point */ - if (end) *end = 0; + /* + * Chop the name at this point. + */ + if (end) + *end = 0; if(saved_last_component != 0) pstrcpy(saved_last_component, end ? end + 1 : start); - /* check if the name exists up to this point */ - if (sys_stat(name, &st) == 0) - { - /* it exists. it must either be a directory or this must be - the last part of the path for it to be OK */ - if (end && !(st.st_mode & S_IFDIR)) - { - /* an intermediate part of the name isn't a directory */ - DEBUG(5,("Not a dir %s\n",start)); - *end = '/'; - return(False); - } - } - else - { - pstring rest; - - *rest = 0; - - /* remember the rest of the pathname so it can be restored - later */ - if (end) pstrcpy(rest,end+1); - - /* try to find this part of the path in the directory */ - if (strchr(start,'?') || strchr(start,'*') || - !scan_directory(dirpath, start, conn, end?True:False)) - { - if (end) - { - /* an intermediate part of the name can't be found */ - DEBUG(5,("Intermediate not found %s\n",start)); - *end = '/'; - /* We need to return the fact that the intermediate - name resolution failed. This is used to return an - error of ERRbadpath rather than ERRbadfile. Some - Windows applications depend on the difference between - these two errors. - */ - *bad_path = True; - return(False); - } + /* + * Check if the name exists up to this point. + */ + if (sys_stat(name, &st) == 0) { + /* + * It exists. it must either be a directory or this must be + * the last part of the path for it to be OK. + */ + if (end && !(st.st_mode & S_IFDIR)) { + /* + * An intermediate part of the name isn't a directory. + */ + DEBUG(5,("Not a dir %s\n",start)); + *end = '/'; + return(False); + } + } else { + pstring rest; + + *rest = 0; + + /* + * Remember the rest of the pathname so it can be restored + * later. + */ + + if (end) + pstrcpy(rest,end+1); + + /* + * Try to find this part of the path in the directory. + */ + if (strchr(start,'?') || strchr(start,'*') || + !scan_directory(dirpath, start, conn, end?True:False)) { + if (end) { + /* + * An intermediate part of the name can't be found. + */ + DEBUG(5,("Intermediate not found %s\n",start)); + *end = '/'; + + /* + * We need to return the fact that the intermediate + * name resolution failed. This is used to return an + * error of ERRbadpath rather than ERRbadfile. Some + * Windows applications depend on the difference between + * these two errors. + */ + *bad_path = True; + return(False); + } - /* just the last part of the name doesn't exist */ - /* we may need to strupper() or strlower() it in case - this conversion is being used for file creation - purposes */ - /* if the filename is of mixed case then don't normalise it */ - if (!case_preserve && - (!strhasupper(start) || !strhaslower(start))) - strnorm(start); - - /* check on the mangled stack to see if we can recover the - base of the filename */ - if (is_mangled(start)) - check_mangled_cache( start ); - - DEBUG(5,("New file %s\n",start)); - return(True); - } - - /* restore the rest of the string */ - if (end) - { - pstrcpy(start+strlen(start)+1,rest); - end = start + strlen(start); - } - } + /* + * Just the last part of the name doesn't exist. + * We may need to strupper() or strlower() it in case + * this conversion is being used for file creation + * purposes. If the filename is of mixed case then + * don't normalise it. + */ + + if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) + strnorm(start); + + /* + * check on the mangled stack to see if we can recover the + * base of the filename. + */ + + if (is_mangled(start)) + check_mangled_cache( start ); + + DEBUG(5,("New file %s\n",start)); + return(True); + } - /* add to the dirpath that we have resolved so far */ - if (*dirpath) pstrcat(dirpath,"/"); + /* + * Restore the rest of the string. + */ + if (end) { + pstrcpy(start+strlen(start)+1,rest); + end = start + strlen(start); + } + } /* end else */ + + /* + * Add to the dirpath that we have resolved so far. + */ + if (*dirpath) pstrcat(dirpath,"/"); pstrcat(dirpath,start); - /* restore the / that we wiped out earlier */ - if (end) *end = '/'; - } + /* + * Restore the / that we wiped out earlier. + */ + if (end) + *end = '/'; + } - /* the name has been resolved */ + /* + * The name has been resolved. + */ DEBUG(5,("conversion finished %s\n",name)); return(True); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b5ed42fbb3..9a9fc51d36 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -321,7 +321,7 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi } if (smb_open_mode == -1) { - if(desired_access & DELETE_ACCESS) + if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) smb_open_mode = 2; else if( desired_access & FILE_EXECUTE) smb_open_mode = 0; @@ -909,12 +909,11 @@ int reply_ntcancel(connection_struct *conn, { /* * Go through and cancel any pending change notifies. - * TODO: When we add blocking locks we will add cancel - * for them here too. */ int mid = SVAL(inbuf,smb_mid); remove_pending_change_notify_requests_by_mid(mid); + remove_pending_lock_requests_by_mid(mid); DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6b91d9d152..28fed8bc04 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1051,14 +1051,24 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mask_convert(mask); { - for (p=mask; *p; p++) + int skip; + p = mask; + while(*p) + { + if((skip = skip_multibyte_char( *p )) != 0 ) { - if (*p != '?' && *p != '*' && !isdoschar(*p)) - { - DEBUG(5,("Invalid char [%c] in search mask?\n",*p)); - *p = '?'; - } + p += skip; } + else + { + if (*p != '?' && *p != '*' && !isdoschar(*p)) + { + DEBUG(5,("Invalid char [%c] in search mask?\n",*p)); + *p = '?'; + } + p++; + } + } } if (!strchr(mask,'.') && strlen(mask)>8) @@ -3569,8 +3579,8 @@ dev = %x, inode = %x\n", count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), - &eclass, &ecode)) -#if 0 /* JRATEST - blocking lock code. */ + &eclass, &ecode)) { +#if 0 /* JRATEST */ if((ecode == ERRlock) && (lock_timeout != 0)) { /* * A blocking lock was requested. Package up @@ -3579,8 +3589,10 @@ dev = %x, inode = %x\n", */ if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) return -1; + } #endif /* JRATEST */ break; + } } /* If any of the above locks failed, then we must unlock -- cgit From 3f153e592b420ed79688b97559de9586a0f7b6fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Aug 1998 01:49:57 +0000 Subject: Blocking lock code split out... Jeremy. (This used to be commit 9cdb148ef56dc8f74891f5c6e9cae10142bd4c6e) --- source3/smbd/blocking.c | 375 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 source3/smbd/blocking.c (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c new file mode 100644 index 0000000000..294dafc405 --- /dev/null +++ b/source3/smbd/blocking.c @@ -0,0 +1,375 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Blocking Locking functions + Copyright (C) Jeremy Allison 1998 + + 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; +extern int Client; + +/**************************************************************************** + This is the structure to queue to implement blocking locks. + notify. It consists of the requesting SMB and the expiry time. +*****************************************************************************/ + +typedef struct { + ubi_slNode msg_next; + time_t expire_time; + int lock_num; + char *inbuf; + int length; +} blocking_lock_record; + +static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; + +/**************************************************************************** + Destructor for the above structure. +****************************************************************************/ + +static void free_blocking_lock_record(blocking_lock_record *blr) +{ + free(blr->inbuf); + free((char *)blr); +} + +/**************************************************************************** + Function to push a blocking lockingX request onto the lock queue. + NB. We can only get away with this as the CIFS spec only includes + SMB_COM_LOCKING_ANDX as a head SMB, ie. it is not one that is ever + generated as part of a chain. +****************************************************************************/ + +BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) +{ + blocking_lock_record *blr; + files_struct *fsp = file_fsp(inbuf,smb_vwv2); + + /* + * Now queue an entry on the blocking lock queue. We setup + * the expiration time here. + */ + + if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); + return False; + } + + if((blr->inbuf = (char *)malloc(length)) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); + free((char *)blr); + return False; + } + + memcpy(blr->inbuf, inbuf, length); + blr->length = length; + blr->lock_num = lock_num; + blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + + ubi_slAddTail(&blocking_lock_queue, blr); + + DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \ +for fnum = %d, name = %s\n", (int)blr->expire_time, fsp->fnum, fsp->fsp_name )); + + return True; +} + +/**************************************************************************** + Return a blocking lock success SMB. +*****************************************************************************/ + +static void blocking_lock_reply_success(blocking_lock_record *blr) +{ + extern int chain_size; + extern char *OutBuffer; + char *outbuf = OutBuffer; + int bufsize = BUFFER_SIZE; + char *inbuf = blr->inbuf; + int outsize = 0; + + construct_reply_common(inbuf, outbuf); + set_message(outbuf,2,0,True); + + /* + * As this message is a lockingX call we must handle + * any following chained message correctly. + * This is normally handled in construct_reply(), + * but as that calls switch_message, we can't use + * that here and must set up the chain info manually. + */ + + chain_size = 0; + + outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); + + outsize += chain_size; + + if(outsize > 4) + smb_setlen(outbuf,outsize - 4); + + send_smb(Client,outbuf); +} + +/**************************************************************************** + Return a lock fail error. Undo all the locks we have obtained first. +*****************************************************************************/ + +static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +{ + extern char *OutBuffer; + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + files_struct *fsp = file_fsp(inbuf,smb_vwv2); + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint32 count, offset; + char *data; + int i; + + data = smb_buf(inbuf) + 10*num_ulocks; + + /* + * Data now points at the beginning of the list + * of smb_lkrng structs. + */ + + for(i = blr->lock_num; i >= 0; i--) { + int dummy1; + uint32 dummy2; + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); + } + + construct_reply_common(inbuf, outbuf); + + if(eclass == 0) /* NT Error. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + + ERROR(eclass,ecode); + send_smb(Client,outbuf); +} + +/**************************************************************************** + Attempt to finish off getting all pending blocking locks. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL blocking_lock_record_process(blocking_lock_record *blr) +{ + char *inbuf = blr->inbuf; + unsigned char locktype = CVAL(inbuf,smb_vwv3); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint16 num_locks = SVAL(inbuf,smb_vwv7); + uint32 count, offset; + char *data; + int eclass=0; + uint32 ecode=0; + + data = smb_buf(inbuf) + 10*num_ulocks; + + /* + * Data now points at the beginning of the list + * of smb_lkrng structs. + */ + + for(; blr->lock_num < num_locks; blr->lock_num++) { + count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); + offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); + if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + &eclass, &ecode)) + break; + } + + if(blr->lock_num == num_locks) { + + /* + * Success - we got all the locks. + */ + + DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n", + fsp->fnum, (unsigned int)locktype, num_locks) ); + + blocking_lock_reply_success(blr); + return True; + + } else if((errno != EACCES) && (errno != EAGAIN)) { + + /* + * We have other than a "can't get lock" POSIX + * error. Free any locks we had and return an error. + * Return True so we get dequeued. + */ + + blocking_lock_reply_error(blr, eclass, ecode); + return True; + } + + /* + * Still can't get all the locks - keep waiting. + */ + + DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \ +Waiting....\n", blr->lock_num, num_locks, fsp->fnum)); + + return False; +} + +/**************************************************************************** + Delete entries by fnum from the blocking lock pending queue. +*****************************************************************************/ + +void remove_pending_lock_requests_by_fid(files_struct *fsp) +{ + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + while(blr != NULL) { + files_struct *req_fsp = file_fsp(blr->inbuf,smb_vwv2); + + if(req_fsp == fsp) { + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } +} + +/**************************************************************************** + Delete entries by mid from the blocking lock pending queue. Always send reply. +*****************************************************************************/ + +void remove_pending_lock_requests_by_mid(int mid) +{ + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + while(blr != NULL) { + if(SVAL(blr->inbuf,smb_mid) == mid) { + blocking_lock_reply_error(blr,0,NT_STATUS_CANCELLED); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } +} + +/**************************************************************************** + Process the blocking lock queue. Note that this is only called as root. +*****************************************************************************/ + +void process_blocking_lock_queue(time_t t) +{ + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + if(blr == NULL) + return; + + /* + * Go through the queue and see if we can get any of the locks. + */ + + while(blr != NULL) { + files_struct *fsp = NULL; + connection_struct *conn = NULL; + uint16 vuid; + + /* + * Ensure we don't have any old chain_fnum values + * sitting around.... + */ + file_chain_reset(); + + conn = conn_find(SVAL(blr->inbuf,smb_tid)); + fsp = file_fsp(blr->inbuf,smb_vwv2); + vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(blr->inbuf,smb_uid); + + DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", + fsp->fnum, fsp->fsp_name )); + + if((blr->expire_time != -1) && (blr->expire_time > t)) { + /* + * Lock expired - throw away all previously + * obtained locks and return lock error. + */ + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fsp->fnum, fsp->fsp_name )); + + blocking_lock_reply_error(blr,ERRSRV,ERRaccess); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + if(!become_user(conn,vuid)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,ERRSRV,ERRaccess); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + if(!become_service(conn,True)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,ERRSRV,ERRaccess); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + unbecome_user(); + continue; + } + + /* + * Go through the remaining locks and try and obtain them. + * The call returns True if all locks were obtained successfully + * and False if we still need to wait. + */ + + if(blocking_lock_record_process(blr)) { + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + unbecome_user(); + continue; + } + + unbecome_user(); + + /* + * Move to the next in the list. + */ + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } +} + -- cgit From dc76502cd8a950f6aff84ce4eedfd9d2b30d3dcc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 20 Aug 1998 19:28:37 +0000 Subject: Turning on blocking locking code. NB. Blocking lock requests that are not the head of an SMB request (ie. are part of a chain) will not be queued - this will be fixed when we move to the new chain code. In practice, this doesn't seem to cause much of a problem (in my admittedly limited testing) bug a debug level zero message will be placed in the log when this happens to help determine how real the problem is. smbd/locking.c: New debug messages. smbd/blocking.c: New blocking code - handles SMBlock, SMBlockread and SMBlockingX smbd/chgpasswd.c: Fix for master fd leak. smbd/files.c: Tidyup comment. smbd/nttrans.c: Added fnum to debug message. smbd/process.c: Made chain_reply() use construct_reply_common(). Added blocking lock queue processing into idle loop. smbd/reply.c: Added queue pushes for SMBlock, SMBlockread and SMBlockingX. Jeremy. (This used to be commit e1dd03ecda0bc6d7eaa31070c83774bb5679fd1b) --- source3/smbd/blocking.c | 284 +++++++++++++++++++++++++++++++++++++++++------ source3/smbd/chgpasswd.c | 4 + source3/smbd/files.c | 4 +- source3/smbd/nttrans.c | 2 +- source3/smbd/process.c | 72 ++++++------ source3/smbd/reply.c | 36 ++++-- 6 files changed, 316 insertions(+), 86 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 294dafc405..1aa80b2797 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -22,6 +22,8 @@ #include "includes.h" extern int DEBUGLEVEL; extern int Client; +extern int chain_size; +extern char *OutBuffer; /**************************************************************************** This is the structure to queue to implement blocking locks. @@ -30,6 +32,7 @@ extern int Client; typedef struct { ubi_slNode msg_next; + int com_type; time_t expire_time; int lock_num; char *inbuf; @@ -49,10 +52,16 @@ static void free_blocking_lock_record(blocking_lock_record *blr) } /**************************************************************************** - Function to push a blocking lockingX request onto the lock queue. - NB. We can only get away with this as the CIFS spec only includes - SMB_COM_LOCKING_ANDX as a head SMB, ie. it is not one that is ever - generated as part of a chain. + Determine if this is a secondary element of a chained SMB. + **************************************************************************/ + +static BOOL in_chained_smb(void) +{ + return (chain_size != 0); +} + +/**************************************************************************** + Function to push a blocking lock request onto the lock queue. ****************************************************************************/ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) @@ -60,6 +69,11 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int blocking_lock_record *blr; files_struct *fsp = file_fsp(inbuf,smb_vwv2); + if(in_chained_smb() ) { + DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); + return False; + } + /* * Now queue an entry on the blocking lock queue. We setup * the expiration time here. @@ -76,27 +90,38 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int return False; } + blr->com_type = CVAL(inbuf,smb_com); + blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + blr->lock_num = lock_num; memcpy(blr->inbuf, inbuf, length); blr->length = length; - blr->lock_num = lock_num; - blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; ubi_slAddTail(&blocking_lock_queue, blr); - DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \ -for fnum = %d, name = %s\n", (int)blr->expire_time, fsp->fnum, fsp->fsp_name )); + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d \ +for fnum = %d, name = %s\n", length, (int)blr->expire_time, fsp->fnum, fsp->fsp_name )); return True; } /**************************************************************************** - Return a blocking lock success SMB. + Return a smd with a given size. +*****************************************************************************/ + +static void send_blocking_reply(char *outbuf, int outsize) +{ + if(outsize > 4) + smb_setlen(outbuf,outsize - 4); + + send_smb(Client,outbuf); +} + +/**************************************************************************** + Return a lockingX success SMB. *****************************************************************************/ -static void blocking_lock_reply_success(blocking_lock_record *blr) +static void reply_lockingX_success(blocking_lock_record *blr) { - extern int chain_size; - extern char *OutBuffer; char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; @@ -113,26 +138,37 @@ static void blocking_lock_reply_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - chain_size = 0; - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); outsize += chain_size; - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); + send_blocking_reply(outbuf,outsize); +} + +/**************************************************************************** + Return a generic lock fail error blocking call. +*****************************************************************************/ + +static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, int32 ecode) +{ + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + construct_reply_common(inbuf, outbuf); + + if(eclass == 0) /* NT Error. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + ERROR(eclass,ecode); send_smb(Client,outbuf); } /**************************************************************************** - Return a lock fail error. Undo all the locks we have obtained first. + Return a lock fail error for a lockingX call. Undo all the locks we have + obtained first. *****************************************************************************/ -static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ecode) { - extern char *OutBuffer; - char *outbuf = OutBuffer; char *inbuf = blr->inbuf; files_struct *fsp = file_fsp(inbuf,smb_vwv2); connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); @@ -156,21 +192,159 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } + generic_blocking_lock_error(blr, eclass, ecode); +} + +/**************************************************************************** + Return a lock fail error. +*****************************************************************************/ + +static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +{ + switch(blr->com_type) { + case SMBlock: + generic_blocking_lock_error(blr, eclass, ecode); + break; + case SMBlockread: + generic_blocking_lock_error(blr, eclass, ecode); + break; + case SMBlockingX: + reply_lockingX_error(blr, eclass, ecode); + break; + default: + DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } +} + +/**************************************************************************** + Attempt to finish off getting all pending blocking locks for a lockread call. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL process_lockread(blocking_lock_record *blr) +{ + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + int nread = -1; + char *data; + int outsize = 0; + uint32 startpos, numtoread; + int eclass; + uint32 ecode; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + + numtoread = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + + numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + data = smb_buf(outbuf) + 3; + + if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) { + if((errno != EACCES) && (errno != EAGAIN)) { + /* + * We have other than a "can't get lock" POSIX + * error. Send an error. + * Return True so we get dequeued. + */ + + generic_blocking_lock_error(blr, eclass, ecode); + return True; + } + + /* + * Still waiting for lock.... + */ + + DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n", + fsp->fsp_name)); + return False; + } + + nread = read_file(fsp,data,startpos,numtoread); + + if (nread < 0) { + generic_blocking_lock_error(blr,ERRDOS,ERRnoaccess); + return True; + } + construct_reply_common(inbuf, outbuf); + outsize = set_message(outbuf,5,3,True); - if(eclass == 0) /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + outsize += nread; + SSVAL(outbuf,smb_vwv0,nread); + SSVAL(outbuf,smb_vwv5,nread+3); + SSVAL(smb_buf(outbuf),1,nread); - ERROR(eclass,ecode); - send_smb(Client,outbuf); + DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", + fsp->fsp_name, fsp->fnum, numtoread, nread ) ); + + send_blocking_reply(outbuf,outsize); + return True; } /**************************************************************************** - Attempt to finish off getting all pending blocking locks. + Attempt to finish off getting all pending blocking locks for a lock call. Returns True if we want to be removed from the list. *****************************************************************************/ -static BOOL blocking_lock_record_process(blocking_lock_record *blr) +static BOOL process_lock(blocking_lock_record *blr) +{ + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + int outsize; + uint32 count,offset; + int eclass; + uint32 ecode; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + + count = IVAL(inbuf,smb_vwv1); + offset = IVAL(inbuf,smb_vwv3); + + errno = 0; + if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { + if((errno != EACCES) && (errno != EAGAIN)) { + + /* + * We have other than a "can't get lock" POSIX + * error. Send an error. + * Return True so we get dequeued. + */ + + blocking_lock_reply_error(blr, eclass, ecode); + return True; + } + + /* + * Still can't get the lock - keep waiting. + */ + + DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n", + fsp->fsp_name)); + return False; + } + + /* + * Success - we got the lock. + */ + + DEBUG(3,("process_lock : file=%s fnum=%d ofs=%d cnt=%d\n", + fsp->fsp_name, fsp->fnum, (int)offset, (int)count)); + + construct_reply_common(inbuf, outbuf); + outsize = set_message(outbuf,0,0,True); + send_blocking_reply(outbuf,outsize); + return True; +} + +/**************************************************************************** + Attempt to finish off getting all pending blocking locks for a lockingX call. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL process_lockingX(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); @@ -193,6 +367,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) for(; blr->lock_num < num_locks; blr->lock_num++) { count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); + errno = 0; if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) break; @@ -204,10 +379,10 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) * Success - we got all the locks. */ - DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n", - fsp->fnum, (unsigned int)locktype, num_locks) ); + DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n", + fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) ); - blocking_lock_reply_success(blr); + reply_lockingX_success(blr); return True; } else if((errno != EACCES) && (errno != EAGAIN)) { @@ -226,12 +401,52 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) * Still can't get all the locks - keep waiting. */ - DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \ -Waiting....\n", blr->lock_num, num_locks, fsp->fnum)); + DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \ +Waiting....\n", blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum)); return False; } +/**************************************************************************** + Process a blocking lock SMB. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL blocking_lock_record_process(blocking_lock_record *blr) +{ + switch(blr->com_type) { + case SMBlock: + return process_lock(blr); + case SMBlockread: + return process_lockread(blr); + case SMBlockingX: + return process_lockingX(blr); + default: + DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return False; /* Keep compiler happy. */ +} + +/**************************************************************************** + Get the files_struct given a particular queued SMB. +*****************************************************************************/ + +static files_struct *get_fsp_from_blr(blocking_lock_record *blr) +{ + switch(blr->com_type) { + case SMBlock: + case SMBlockread: + return file_fsp(blr->inbuf,smb_vwv0); + case SMBlockingX: + return file_fsp(blr->inbuf,smb_vwv2); + default: + DEBUG(0,("get_fsp_from_blr: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return NULL; /* Keep compiler happy. */ +} + /**************************************************************************** Delete entries by fnum from the blocking lock pending queue. *****************************************************************************/ @@ -242,7 +457,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) blocking_lock_record *prev = NULL; while(blr != NULL) { - files_struct *req_fsp = file_fsp(blr->inbuf,smb_vwv2); + files_struct *req_fsp = get_fsp_from_blr(blr); if(req_fsp == fsp) { free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); @@ -294,18 +509,18 @@ void process_blocking_lock_queue(time_t t) */ while(blr != NULL) { - files_struct *fsp = NULL; connection_struct *conn = NULL; uint16 vuid; + files_struct *fsp = get_fsp_from_blr(blr); /* * Ensure we don't have any old chain_fnum values * sitting around.... */ + chain_size = 0; file_chain_reset(); conn = conn_find(SVAL(blr->inbuf,smb_tid)); - fsp = file_fsp(blr->inbuf,smb_vwv2); vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(blr->inbuf,smb_uid); @@ -372,4 +587,3 @@ void process_blocking_lock_queue(time_t t) blr = (blocking_lock_record *)ubi_slNext(blr); } } - diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index bd7d28b11f..ee6a2d14f4 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -308,6 +308,7 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL if ((pid = fork()) < 0) { DEBUG(3,("Cannot fork() child for password change: %s",name)); + close(master); return(False); } @@ -317,6 +318,9 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL DEBUG(3,("Child failed to change password: %s\n",name)); kill(pid, SIGKILL); /* be sure to end this process */ } + + close(master); + if ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { DEBUG(3,("The process is no longer waiting!\n\n")); return(False); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4f87802119..00de8dfffa 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -380,10 +380,10 @@ files_struct *file_fsp(char *buf, int where) return NULL; } - /**************************************************************************** -reset the chained fsp - done at the start of a packet reply + Reset the chained fsp - done at the start of a packet reply ****************************************************************************/ + void file_chain_reset(void) { chain_fsp = NULL; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9a9fc51d36..236f1e2d30 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -668,7 +668,7 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 12; SCVAL(p,0,fsp->is_directory ? 1 : 0); - DEBUG(5,("reply_ntcreate_and_X: open name = %s\n", fsp->fsp_name)); + DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); return chain_reply(inbuf,outbuf,length,bufsize); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 756e010d9e..5bf8cdb2b1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -29,7 +29,6 @@ char *InBuffer = NULL; char *OutBuffer = NULL; char *last_inbuf = NULL; - /* * Size of data we can send to client. Set * by the client for all protocols above CORE. @@ -485,6 +484,29 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(outsize); } +/**************************************************************************** + Helper function for contruct_reply. +****************************************************************************/ + +void construct_reply_common(char *inbuf,char *outbuf) +{ + bzero(outbuf,smb_size); + + set_message(outbuf,0,0,True); + CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); + + memcpy(outbuf+4,inbuf+4,4); + CVAL(outbuf,smb_rcls) = SMB_SUCCESS; + CVAL(outbuf,smb_reh) = 0; + CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set + means a reply */ + SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf,smb_err,SMB_SUCCESS); + SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); + SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); + SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); + SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); +} /**************************************************************************** construct a chained reply and add it to the already made reply @@ -542,21 +564,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) CVAL(inbuf2,smb_com) = smb_com2; /* create the out buffer */ - bzero(outbuf2,smb_size); - set_message(outbuf2,0,0,True); - CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com); - - memcpy(outbuf2+4,inbuf2+4,4); - CVAL(outbuf2,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf2,smb_reh) = 0; - CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf2,smb_err,SMB_SUCCESS); - SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid)); - SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid)); - SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid)); - SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid)); + construct_reply_common(inbuf2, outbuf2); DEBUG(3,("Chained message\n")); show_msg(inbuf2); @@ -582,34 +590,10 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) return outsize2; } - -/**************************************************************************** - Helper function for contruct_reply. -****************************************************************************/ - -void construct_reply_common(char *inbuf,char *outbuf) -{ - bzero(outbuf,smb_size); - - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); - set_message(outbuf,0,0,True); - - memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf,smb_reh) = 0; - CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf,smb_err,SMB_SUCCESS); - SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); -} - /**************************************************************************** construct a reply to the incoming packet ****************************************************************************/ + int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) { int type = CVAL(inbuf,smb_com); @@ -816,6 +800,12 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); global_machine_pasword_needs_changing = False; } + /* + * Check to see if we have any blocking locks + * outstanding on the queue. + */ + process_blocking_lock_queue(t); + /* * Check to see if we have any change notifies * outstanding on the queue. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 28fed8bc04..3e59e7dbd0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1861,7 +1861,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s /**************************************************************************** reply to a lockread (core+ protocol) ****************************************************************************/ -int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) +int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz) { int nread = -1; char *data; @@ -1882,8 +1882,18 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_si numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) + if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) { + if(ecode == ERRlock) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, -1, 0)) + return -1; + } return (ERROR(eclass,ecode)); + } nread = read_file(fsp,data,startpos,numtoread); @@ -2449,7 +2459,7 @@ int reply_writeclose(connection_struct *conn, reply to a lock ****************************************************************************/ int reply_lock(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + char *inbuf,char *outbuf, int length, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); uint32 count,offset; @@ -2466,8 +2476,18 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n", fsp->fd_ptr->fd, fsp->fnum, offset, count)); - if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) - return (ERROR(eclass,ecode)); + if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { + if(ecode == ERRlock) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, -1, 0)) + return -1; + } + return (ERROR(eclass,ecode)); + } return(outsize); } @@ -3564,6 +3584,8 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_ulocks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + DEBUG(10,("reply_lockingX: unlock start=%d, len=%d for file %s\n", + (int)offset, (int)count, fsp->fsp_name )); if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode)) return ERROR(eclass,ecode); } @@ -3578,9 +3600,10 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_locks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + DEBUG(10,("reply_lockingX: lock start=%d, len=%d for file %s\n", + (int)offset, (int)count, fsp->fsp_name )); if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) { -#if 0 /* JRATEST */ if((ecode == ERRlock) && (lock_timeout != 0)) { /* * A blocking lock was requested. Package up @@ -3590,7 +3613,6 @@ dev = %x, inode = %x\n", if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) return -1; } -#endif /* JRATEST */ break; } } -- cgit From 81b580fd2248221c61e3d4dac03862fb1fd8fde5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Aug 1998 01:30:29 +0000 Subject: Fixes for the problem in blocking locks with file_fsp returning the chain_fsp on close (if you don't know what this means, consider yourself lucky - this one took a day to track down :-). Jeremy. (This used to be commit 193cb5382464173e99a538867a266d793f0ceab5) --- source3/smbd/blocking.c | 69 ++++++++++++++++++++++++++++--------------------- source3/smbd/close.c | 4 +-- source3/smbd/nttrans.c | 10 ++++++- 3 files changed, 51 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 1aa80b2797..2241b7aa8d 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -33,6 +33,7 @@ extern char *OutBuffer; typedef struct { ubi_slNode msg_next; int com_type; + files_struct *fsp; time_t expire_time; int lock_num; char *inbuf; @@ -51,6 +52,25 @@ static void free_blocking_lock_record(blocking_lock_record *blr) free((char *)blr); } +/**************************************************************************** + Get the files_struct given a particular queued SMB. +*****************************************************************************/ + +static files_struct *get_fsp_from_pkt(char *inbuf) +{ + switch(CVAL(inbuf,smb_com)) { + case SMBlock: + case SMBlockread: + return file_fsp(inbuf,smb_vwv0); + case SMBlockingX: + return file_fsp(inbuf,smb_vwv2); + default: + DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return NULL; /* Keep compiler happy. */ +} + /**************************************************************************** Determine if this is a secondary element of a chained SMB. **************************************************************************/ @@ -67,7 +87,6 @@ static BOOL in_chained_smb(void) BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) { blocking_lock_record *blr; - files_struct *fsp = file_fsp(inbuf,smb_vwv2); if(in_chained_smb() ) { DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); @@ -91,6 +110,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int } blr->com_type = CVAL(inbuf,smb_com); + blr->fsp = get_fsp_from_pkt(inbuf); blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; blr->lock_num = lock_num; memcpy(blr->inbuf, inbuf, length); @@ -98,8 +118,10 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int ubi_slAddTail(&blocking_lock_queue, blr); + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d \ -for fnum = %d, name = %s\n", length, (int)blr->expire_time, fsp->fnum, fsp->fsp_name )); +for fnum = %d, name = %s\n", length, (int)blr->expire_time, + blr->fsp->fnum, blr->fsp->fsp_name )); return True; } @@ -170,7 +192,7 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, i static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ecode) { char *inbuf = blr->inbuf; - files_struct *fsp = file_fsp(inbuf,smb_vwv2); + files_struct *fsp = blr->fsp; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint32 count, offset; @@ -233,7 +255,7 @@ static BOOL process_lockread(blocking_lock_record *blr) int eclass; uint32 ecode; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = blr->fsp; numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -298,7 +320,7 @@ static BOOL process_lock(blocking_lock_record *blr) int eclass; uint32 ecode; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = blr->fsp; count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); @@ -348,7 +370,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); - files_struct *fsp = file_fsp(inbuf,smb_vwv2); + files_struct *fsp = blr->fsp; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); @@ -428,25 +450,6 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) return False; /* Keep compiler happy. */ } -/**************************************************************************** - Get the files_struct given a particular queued SMB. -*****************************************************************************/ - -static files_struct *get_fsp_from_blr(blocking_lock_record *blr) -{ - switch(blr->com_type) { - case SMBlock: - case SMBlockread: - return file_fsp(blr->inbuf,smb_vwv0); - case SMBlockingX: - return file_fsp(blr->inbuf,smb_vwv2); - default: - DEBUG(0,("get_fsp_from_blr: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return NULL; /* Keep compiler happy. */ -} - /**************************************************************************** Delete entries by fnum from the blocking lock pending queue. *****************************************************************************/ @@ -457,9 +460,11 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) blocking_lock_record *prev = NULL; while(blr != NULL) { - files_struct *req_fsp = get_fsp_from_blr(blr); + if(blr->fsp->fnum == fsp->fnum) { + + DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ +file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - if(req_fsp == fsp) { free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -481,6 +486,11 @@ void remove_pending_lock_requests_by_mid(int mid) while(blr != NULL) { if(SVAL(blr->inbuf,smb_mid) == mid) { + files_struct *fsp = blr->fsp; + + DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ +file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); + blocking_lock_reply_error(blr,0,NT_STATUS_CANCELLED); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); @@ -511,14 +521,15 @@ void process_blocking_lock_queue(time_t t) while(blr != NULL) { connection_struct *conn = NULL; uint16 vuid; - files_struct *fsp = get_fsp_from_blr(blr); + files_struct *fsp = NULL; /* - * Ensure we don't have any old chain_fnum values + * Ensure we don't have any old chain_fsp values * sitting around.... */ chain_size = 0; file_chain_reset(); + fsp = blr->fsp; conn = conn_find(SVAL(blr->inbuf,smb_tid)); vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : diff --git a/source3/smbd/close.c b/source3/smbd/close.c index b8063ca3f4..07b000d7ad 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -104,6 +104,8 @@ void close_file(files_struct *fsp, BOOL normal_close) int token; connection_struct *conn = fsp->conn; + remove_pending_lock_requests_by_fid(fsp); + close_filestruct(fsp); #if USE_READ_PREDICTION @@ -142,8 +144,6 @@ void close_file(files_struct *fsp, BOOL normal_close) string_free(&fsp->fsp_name); } - remove_pending_lock_requests_by_fid(fsp); - file_free(fsp); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 236f1e2d30..596d15c2c7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -28,6 +28,7 @@ extern int Client; extern int oplock_sock; extern int smb_read_error; extern int global_oplock_break; +extern int chain_size; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; @@ -1029,7 +1030,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp) change_notify_buf *prev = NULL; while(cnbp != NULL) { - if(cnbp->fsp == fsp) { + if(cnbp->fsp->fnum == fsp->fnum) { free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; @@ -1089,6 +1090,13 @@ void process_pending_change_notify_queue(time_t t) uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); + /* + * Ensure we don't have any old chain_fsp values + * sitting around.... + */ + chain_size = 0; + file_chain_reset(); + if(!become_user(conn,vuid)) { DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", vuid )); -- cgit From 60cf7ad5cf53534b72189e1cfa3495e804cc0efc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 21 Aug 1998 05:58:57 +0000 Subject: fixed a bug in trans2_qfilepathinfo() where we used the length of the basename of a file but the whole file name. silly error. (This used to be commit 6e00de7a1d3d5f9fa9bcc40db119fcb8602165c9) --- source3/smbd/trans2.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2789282771..190910bd97 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1251,6 +1251,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; if (mode & aDIR) size = 0; + + /* from now on we only want the part after the / */ + fname = p; params = *pparams = Realloc(*pparams,2); bzero(params,2); data_size = 1024; @@ -1399,6 +1402,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,20,l); pstrcpy(pdata+24,fname); break; + default: return(ERROR(ERRDOS,ERRunknownlevel)); } -- cgit From 038e3433d39337f736b7b69ac1e6212e9f8e5406 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 21 Aug 1998 11:37:40 +0000 Subject: added new smb.conf option "panic action". see my samba-technical explanation. (This used to be commit c6899df44c34088a4d2bf1edc840320b0ba7e32e) --- source3/smbd/ipc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1a6fb3366a..eb0abc37c0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -377,9 +377,7 @@ va_dcl DEBUG(2,("type error in package: %s instead of %*s\n",str, strlen(str),p->curpos)); va_end(args); -#if AJT - ajt_panic(); -#endif + smb_panic("invalid types in ipc"); return 0; } #endif -- cgit From 541cd2a2d9972f85d09779bf29bda0f7da051114 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 21 Aug 1998 14:31:43 +0000 Subject: don't attempt to answer QFILEINFO/SMB_QUERY_FILE_STREAM_INFO queries - if we do then NTws gets a BSOD. I checked and NT server refuses these queries too :) (This used to be commit d2fb7ee8f55dd1ff25fca46e18b02a05bc2b71ae) --- source3/smbd/trans2.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 190910bd97..1dfb488b9e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1394,6 +1394,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = PTR_DIFF(pdata,(*ppdata)); break; +#if 0 + /* NT4 server just returns "invalid query" to this - if we try to answer + it then NTws gets a BSOD! (tridge) */ case SMB_QUERY_FILE_STREAM_INFO: data_size = 24 + l; SIVAL(pdata,0,pos); @@ -1402,6 +1405,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,20,l); pstrcpy(pdata+24,fname); break; +#endif default: return(ERROR(ERRDOS,ERRunknownlevel)); -- cgit From 7fe3a42857792a70bdd729fefa2311b77ae86e7e Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Fri, 21 Aug 1998 17:21:55 +0000 Subject: nmbd and smbd had different behavior with respect to log files. nmbd would default to overwrite and smbd would default to append. Also, the -a option (actually a toggle, such that "-a -a" would set the default) was documented as append mode for nmbd, and *overwrite mode* for smbd. nmbd now defaults to append mode, to match smbd. The -a option now always means append, and I've added the -o option to both, meaning overwrite. Note that the change to nmbd's default behavior may confuse some people. I've not seen anything about 2.0.0 changes in the WHATSNEW.txt file. Where would I document a change like this? Chris -)----- (This used to be commit b1d374fb14b1fb92a84260f1dcc59a39a4b99a3d) --- source3/smbd/server.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 41a2a10d50..a08ff8184e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -490,7 +490,8 @@ static void usage(char *pname) { DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); - printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname); + printf("Usage: %s [-D] [-p port] [-d debuglevel] ", pname); + printf("[-l log basename] [-s services file]\n" ); printf("Version %s\n",VERSION); printf("\t-D become a daemon\n"); printf("\t-p port listen on the specified port\n"); @@ -498,7 +499,8 @@ static void usage(char *pname) printf("\t-l log basename. Basename for log/debug files\n"); printf("\t-s services file. Filename of services file\n"); printf("\t-P passive only\n"); - printf("\t-a overwrite log file, don't append\n"); + printf("\t-a append to log file (default)\n"); + printf("\t-o overwrite log file, don't append\n"); printf("\n"); } @@ -564,7 +566,7 @@ static void usage(char *pname) argc--; } - while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF) + while ( EOF != (opt = getopt(argc, argv, "O:i:l:s:d:Dp:h?Paof:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); @@ -590,10 +592,11 @@ static void usage(char *pname) break; case 'a': - { - extern BOOL append_log; - append_log = !append_log; - } + append_log = True; + break; + + case 'o': + append_log = False; break; case 'D': @@ -612,6 +615,7 @@ static void usage(char *pname) break; case 'h': + case '?': usage(argv[0]); exit(0); break; -- cgit From 3f3f47b0bd8d089120d267cfad1976db95cd8ebe Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 22 Aug 1998 02:54:21 +0000 Subject: added ASSERT() and ASSERT_ARRAY() macros and sprinkled them liberally in the rpc code. (This used to be commit e6ce1c5b5a9f29d8fcbbd23019186ff5c600e795) --- source3/smbd/ipc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index eb0abc37c0..46fb6a22ff 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -373,13 +373,7 @@ va_dcl } #if CHECK_TYPES str = va_arg(args,char*); - if (strncmp(str,p->curpos,strlen(str)) != 0) { - DEBUG(2,("type error in package: %s instead of %*s\n",str, - strlen(str),p->curpos)); - va_end(args); - smb_panic("invalid types in ipc"); - return 0; - } + ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); #endif stringneeded = -1; -- cgit From 8afc9c80ac11649f06e5517d819dbf201c941acb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Aug 1998 21:49:10 +0000 Subject: Changed ASSERT macros to SMB_ASSERT macros as some systems already have an ASSERT macro defined. Jeremy. (This used to be commit dbe6ad014a8b5dcbf17d7cd9865650c2e040d666) --- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 46fb6a22ff..70c2668d92 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -373,7 +373,7 @@ va_dcl } #if CHECK_TYPES str = va_arg(args,char*); - ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); + SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); #endif stringneeded = -1; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 121ebb7f00..ecc86f29ec 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1191,8 +1191,8 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); trust_password_unlock(); /* - * Here we should check the last change time to see if the machine - * password needs changing..... TODO... JRA. + * Here we check the last change time to see if the machine + * password needs changing. JRA. */ if(time(NULL) > lct + lp_machine_password_timeout()) -- cgit From 5ae06b99c06313d1465b03d5120e7fbf6a87b9e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Aug 1998 02:29:17 +0000 Subject: Added code to (correctly) ignore TRANSACT2_SETFILEINFO with SMB_SET_FILE_ALLOCATION_INFO. Office 97 expects this call to succeed when you tell it you do NT SMB calls. Jeremy. (This used to be commit 260e7e27401d863e9f580d4748c577334d9fc9d0) --- source3/smbd/open.c | 2 +- source3/smbd/trans2.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 311eac07e5..e54a456092 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -530,7 +530,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, } DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *sesssetup_user ? sesssetup_user : conn->user,fname, + *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1dfb488b9e..fe22a21ca1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1566,8 +1566,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + case SMB_SET_FILE_ALLOCATION_INFO: + break; /* We don't need to do anything for this call. */ + case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */ - case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */ default: { return(ERROR(ERRDOS,ERRunknownlevel)); -- cgit From 2c065107b149797e2a42a6c119f883d30be411eb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 25 Aug 1998 06:40:42 +0000 Subject: changed the default permissions code to do this: if ((sbuf->st_mode & S_IWUSR) == 0) result |= aRONLY; rather than the very complex user/group permissions checks we do currently. This is equivalent ot setting "alternate permissions = yes" in the old code. The change is motivated by three main reasons: 1) it's basically impossible to second guess whether a file is writeable without trying to open it for writing. ACLs, root squash etc just make it too hard. 2) setting it not RONLY if the owner can write is closer to what NT does (eg. look at a cdrom - files are not marked read only). 3) it prevents the silly problem of copying files from a read only share to a writeable share and then finding you can't write to them as windows preserves the RONLY flag. Lots of people get bitten by this when they drag a folder from a Samba drive. It also hurts some install programs. I have also added a new flag type for loadparm.c called FLAG_DEPRECATED which I've set for "alternate permissions". I'll soon add code to testparm to give a warning about deprecated options. (This used to be commit c4363a12fdc0be329ca2bfeb1d7b89bfe90031dc) --- source3/smbd/dosmode.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 9db3e208b5..da7fdfb973 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -78,22 +78,11 @@ mode_t unix_mode(connection_struct *conn,int dosmode) int dos_mode(connection_struct *conn,char *path,struct stat *sbuf) { int result = 0; - extern struct current_user current_user; DEBUG(8,("dos_mode: %s\n", path)); - if (CAN_WRITE(conn) && !lp_alternate_permissions(SNUM(conn))) { - if (!((sbuf->st_mode & S_IWOTH) || - conn->admin_user || - ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) || - ((sbuf->st_mode & S_IWGRP) && - in_group(sbuf->st_gid,current_user.gid, - current_user.ngroups,current_user.groups)))) - result |= aRONLY; - } else { - if ((sbuf->st_mode & S_IWUSR) == 0) + if ((sbuf->st_mode & S_IWUSR) == 0) result |= aRONLY; - } if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) result |= aARCH; -- cgit From 5e5e320d361afcb4d9503354b3912b4c7a672197 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Aug 1998 20:38:53 +0000 Subject: This is the stat cache code - seems to work fine (needs heavy NetBench testing though.... :-). Attempts to efficiently reduce the number of stat() calls Samba does. Jeremy. (This used to be commit d0e48a2d8072c3e77a57ac6a2fb5044c05f03b41) --- source3/smbd/filename.c | 290 +++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/nttrans.c | 4 +- source3/smbd/password.c | 4 - source3/smbd/process.c | 4 + source3/smbd/reply.c | 44 ++++---- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 14 +-- 7 files changed, 312 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ab5851fb5e..8ef2eef96a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -29,10 +29,10 @@ extern fstring remote_machine; extern BOOL use_mangled_map; /**************************************************************************** -check if two filenames are equal - -this needs to be careful about whether we are case sensitive + Check if two filenames are equal. + This needs to be careful about whether we are case sensitive. ****************************************************************************/ + BOOL fname_equal(char *name1, char *name2) { int l1 = strlen(name1); @@ -66,8 +66,9 @@ BOOL fname_equal(char *name1, char *name2) /**************************************************************************** -mangle the 2nd name and check if it is then equal to the first name + Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ + BOOL mangled_equal(char *name1, char *name2) { pstring tmpname; @@ -81,6 +82,215 @@ BOOL mangled_equal(char *name1, char *name2) return(strequal(name1,tmpname)); } +/**************************************************************************** + Stat cache code used in unix_convert. +*****************************************************************************/ + +static int global_stat_cache_lookups; +static int global_stat_cache_misses; +static int global_stat_cache_hits; + +/**************************************************************************** + Stat cache statistics code. +*****************************************************************************/ + +void print_stat_cache_statistics(void) +{ + double eff = ((double)global_stat_cache_lookups/100.0)*(double)global_stat_cache_hits; + + DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ +stat cache was %f%% effective.\n", global_stat_cache_lookups, + global_stat_cache_hits, global_stat_cache_misses, eff )); +} + +typedef struct { + ubi_dlNode link; + int name_len; + pstring orig_name; + pstring translated_name; +} stat_cache_entry; + +#define MAX_STAT_CACHE_SIZE 50 + +static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; + +/**************************************************************************** + Compare two names in the stat cache. +*****************************************************************************/ + +static BOOL stat_name_equal( char *s1, char *s2) +{ + return (case_sensitive ? (strcmp( s1, s2) == 0) : (StrCaseCmp(s1, s2) == 0)); +} + +/**************************************************************************** + Compare two names in the stat cache. +*****************************************************************************/ + +static BOOL stat_name_equal_len( char *s1, char *s2, int len) +{ + return (case_sensitive ? (strncmp( s1, s2, len) == 0) : + (StrnCaseCmp(s1, s2, len) == 0)); +} + +/**************************************************************************** + Add an entry into the stat cache. +*****************************************************************************/ + +static void stat_cache_add( char *full_orig_name, char *orig_translated_path) +{ + stat_cache_entry *scp; + pstring orig_name; + pstring translated_path; + int namelen = strlen(orig_translated_path); + + /* + * Don't cache trivial valid directory entries. + */ + if(strequal(full_orig_name, ".") || strequal(full_orig_name, "..")) + return; + + /* + * If we are in case insentive mode, we need to + * store names that need no translation - else, it + * would be a waste. + */ + + if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + return; + + /* + * Remove any trailing '/' characters from the + * translated path. + */ + + pstrcpy(translated_path, orig_translated_path); + if(translated_path[namelen-1] == '/') { + translated_path[namelen-1] = '\0'; + namelen--; + } + + /* + * We will only replace namelen characters + * of full_orig_name. + * StrnCpy always null terminates. + */ + + StrnCpy(orig_name, full_orig_name, namelen); + + /* + * Check this name doesn't exist in the cache before we + * add it. + */ + + for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; + scp = (stat_cache_entry *)ubi_dlNext( scp )) { + if(stat_name_equal( scp->orig_name, orig_name) && + (strcmp( scp->translated_name, translated_path) == 0)) { + /* + * Name does exist - promote it. + */ + if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != scp ) { + ubi_dlRemThis( &stat_cache, scp); + ubi_dlAddHead( &stat_cache, scp); + } + return; + } + } + + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry))) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + + pstrcpy(scp->orig_name, orig_name); + pstrcpy(scp->translated_name, translated_path); + scp->name_len = namelen; + + ubi_dlAddHead( &stat_cache, scp); + + DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name )); + + if(ubi_dlCount(&stat_cache) > MAX_STAT_CACHE_SIZE) { + scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache ); + free((char *)scp); + return; + } +} + +/**************************************************************************** + Look through the stat cache for an entry - promote it to the top if found. + Return True if we translated (and did a scuccessful stat on) the entire name. +*****************************************************************************/ + +static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, struct stat *pst) +{ + stat_cache_entry *scp; + stat_cache_entry *longest_hit = NULL; + int namelen = strlen(name); + + *start = name; + global_stat_cache_lookups++; + + /* + * Don't lookup trivial valid directory entries. + */ + if(strequal(name, ".") || strequal(name, "..")) { + global_stat_cache_misses++; + return False; + } + + for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; + scp = (stat_cache_entry *)ubi_dlNext( scp )) { + if(scp->name_len <= namelen) { + if(stat_name_equal_len(scp->orig_name, name, scp->name_len)) { + if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len)) + longest_hit = scp; + } + } + } + + if(longest_hit == NULL) { + DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name)); + global_stat_cache_misses++; + return False; + } + + global_stat_cache_hits++; + + DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n", + name, longest_hit->orig_name, longest_hit->translated_name )); + + /* + * longest_hit is the longest match we got in the list. + * Check it exists - if so, overwrite the original name + * and then promote it to the top. + */ + + if(sys_stat( longest_hit->translated_name, pst) != 0) { + /* + * Discard this entry. + */ + ubi_dlRemThis( &stat_cache, longest_hit); + free((char *)longest_hit); + return False; + } + + memcpy(name, longest_hit->translated_name, longest_hit->name_len); + if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) { + ubi_dlRemThis( &stat_cache, longest_hit); + ubi_dlAddHead( &stat_cache, longest_hit); + } + + *start = &name[longest_hit->name_len]; + if(**start == '/') + ++*start; + + StrnCpy( dirpath, longest_hit->translated_name, name - (*start)); + + return (namelen == longest_hit->name_len); +} + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -103,15 +313,21 @@ as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path) +BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, + BOOL *bad_path, struct stat *pst) { struct stat st; - char *start, *end; + char *start, *end, *orig_start; pstring dirpath; + pstring orig_path; int saved_errno; + BOOL component_was_mangled = False; + BOOL name_has_wildcard = False; *dirpath = 0; *bad_path = False; + if(pst) + memset( (char *)pst, '\0', sizeof(struct stat)); if(saved_last_component) *saved_last_component = 0; @@ -166,16 +382,34 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, return(True); } + start = name; + while (strncmp(start,"./",2) == 0) + start += 2; + + pstrcpy(orig_path, name); + + if(stat_cache_lookup( name, dirpath, &start, &st)) { + if(pst) + *pst = st; + return True; + } + /* * stat the name - if it exists then we are all done! */ - if (sys_stat(name,&st) == 0) + if (sys_stat(name,&st) == 0) { + stat_cache_add(orig_path, name); + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + if(pst) + *pst = st; return(True); + } saved_errno = errno; - DEBUG(5,("unix_convert(%s)\n",name)); + DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", + name, dirpath, start)); /* * A special case - if we don't have any mangling chars and are case @@ -186,21 +420,20 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) return(False); + if(strchr(start,'?') || strchr(start,'*')) + name_has_wildcard = True; + /* * Now we need to recursively match the name against the real * directory structure. */ - start = name; - while (strncmp(start,"./",2) == 0) - start += 2; - /* * Match each part of the path name separately, trying the names * as is first, then trying to scan the directory for matching names. */ - for (;start;start = (end?end+1:(char *)NULL)) { + for (orig_start = start; start ; start = (end?end+1:(char *)NULL)) { /* * Pinpoint the end of this section of the filename. */ @@ -231,6 +464,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *end = '/'; return(False); } + } else { pstring rest; @@ -247,6 +481,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Try to find this part of the path in the directory. */ + if (strchr(start,'?') || strchr(start,'*') || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { @@ -283,8 +518,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * base of the filename. */ - if (is_mangled(start)) + if (is_mangled(start)) { + component_was_mangled = True; check_mangled_cache( start ); + } DEBUG(5,("New file %s\n",start)); return(True); @@ -302,8 +539,18 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Add to the dirpath that we have resolved so far. */ - if (*dirpath) pstrcat(dirpath,"/"); - pstrcat(dirpath,start); + if (*dirpath) + pstrcat(dirpath,"/"); + + pstrcat(dirpath,start); + + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, dirpath); /* * Restore the / that we wiped out earlier. @@ -312,10 +559,19 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *end = '/'; } + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, name); + /* * The name has been resolved. */ - DEBUG(5,("conversion finished %s\n",name)); + + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); return(True); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 596d15c2c7..fbcc19e77d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -490,7 +490,7 @@ int reply_ntcreate_and_X(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) { @@ -743,7 +743,7 @@ static int call_nt_transact_create(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ecc86f29ec..4ee9e8705d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,10 +21,6 @@ #include "includes.h" -#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) -#include "rpcsvc/ypclnt.h" -#endif - extern int DEBUGLEVEL; extern int Protocol; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5bf8cdb2b1..63e51dc242 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -723,6 +723,10 @@ void smbd_process(void) DEBUG(0,("Reloading services after SIGHUP\n")); reload_services(False); reload_after_sighup = False; + /* + * Use this as an excuse to print some stats. + */ + print_stat_cache_statistics(); } /* automatic timeout if all connections are closed */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3e59e7dbd0..3052bd730c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -751,14 +751,19 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring name; BOOL ok = False; BOOL bad_path = False; + struct stat st; pstrcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,conn,0,&bad_path); + unix_convert(name,conn,0,&bad_path,&st); mode = SVAL(inbuf,smb_vwv0); - if (check_name(name,conn)) - ok = directory_exist(name,NULL); + if (check_name(name,conn)) { + if(VALID_STAT(st)) + ok = S_ISDIR(st.st_mode); + else + ok = directory_exist(name,NULL); + } if (!ok) { @@ -809,7 +814,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,&sbuf); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ @@ -824,7 +829,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size else if (check_name(fname,conn)) { - if (sys_stat(fname,&sbuf) == 0) + if (VALID_STAT(sbuf) || sys_stat(fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; @@ -881,15 +886,16 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok=False; int mode; time_t mtime; + struct stat st; BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,&st); mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (directory_exist(fname,NULL)) + if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL)) mode |= aDIR; if (check_name(fname,conn)) ok = (dos_chmod(conn,fname,mode,NULL) == 0); @@ -990,7 +996,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(directory,smb_buf(inbuf)+1); pstrcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,conn,0,&bad_path); + unix_convert(directory,conn,0,&bad_path,NULL); unix_format(dir2); if (!check_name(directory,conn)) @@ -1250,7 +1256,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) @@ -1351,7 +1357,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) @@ -1485,7 +1491,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,NULL); if (createmode & aVOLID) { @@ -1570,7 +1576,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,NULL); unixmode = unix_mode(conn,createmode); @@ -1674,7 +1680,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - unix_convert(name,conn,0,&bad_path); + unix_convert(name,conn,0,&bad_path,NULL); p = strrchr(name,'/'); if (!p) { @@ -2778,7 +2784,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,conn,0,&bad_path); + unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) ret = sys_mkdir(directory,unix_mode(conn,aDIR)); @@ -2872,7 +2878,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,conn, NULL,&bad_path); + unix_convert(directory,conn, NULL,&bad_path,NULL); if (check_name(directory,conn)) { @@ -3072,8 +3078,8 @@ int rename_internals(connection_struct *conn, *directory = *mask = 0; - unix_convert(name,conn,0,&bad_path1); - unix_convert(newname,conn,newname_last_component,&bad_path2); + unix_convert(name,conn,0,&bad_path1,NULL); + unix_convert(newname,conn,newname_last_component,&bad_path2,NULL); /* * Split the old name into directory and last component @@ -3373,8 +3379,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRSRV,ERRinvdevice)); } - unix_convert(name,conn,0,&bad_path1); - unix_convert(newname,conn,0,&bad_path2); + unix_convert(name,conn,0,&bad_path1,NULL); + unix_convert(newname,conn,0,&bad_path2,NULL); target_is_directory = directory_exist(newname,NULL); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a08ff8184e..4c38fb5f4b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -287,7 +287,7 @@ max can be %d\n", } /* end for num */ } /* end while 1 */ - return True; +/* NOTREACHED return True; */ } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fe22a21ca1..da11dbcb29 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -214,7 +214,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) @@ -659,7 +659,7 @@ static int call_trans2findfirst(connection_struct *conn, DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,conn,0,&bad_path); + unix_convert(directory,conn,0,&bad_path,NULL); if(!check_name(directory,conn)) { if((errno == ENOENT) && bad_path) { @@ -1225,8 +1225,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = &fname1[0]; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path); - if (!check_name(fname,conn) || sys_stat(fname,&sbuf)) { + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && sys_stat(fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1459,7 +1459,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = fname1; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path); + unix_convert(fname,conn,0,&bad_path,&st); if(!check_name(fname, conn)) { if((errno == ENOENT) && bad_path) @@ -1470,7 +1470,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(sys_stat(fname,&st)!=0) { + if(!VALID_STAT(st) && sys_stat(fname,&st)!=0) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1648,7 +1648,7 @@ static int call_trans2mkdir(connection_struct *conn, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,conn,0,&bad_path); + unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory,conn)) ret = sys_mkdir(directory,unix_mode(conn,aDIR)); -- cgit From d0cfc1f04192bd22ce750e076d81d8be64504adc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Aug 1998 20:51:12 +0000 Subject: Fixed stat cache statistics calculation. Oops. Jeremy. (This used to be commit d6a9087e7e626e6e07503dba38854b136fe70c23) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8ef2eef96a..de4fef5189 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -96,7 +96,7 @@ static int global_stat_cache_hits; void print_stat_cache_statistics(void) { - double eff = ((double)global_stat_cache_lookups/100.0)*(double)global_stat_cache_hits; + double eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ stat cache was %f%% effective.\n", global_stat_cache_lookups, -- cgit From 38142a1ebbe860778e26eaff68585726061c05e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Aug 1998 21:46:29 +0000 Subject: This checking fixes the statcache bug that stopped NetBench from running correctly. Added new parameter "stat cache size" - set to 50 by default. I now declare the statcache code officially "open" for business :-). It gets a hit rate of 97% with a NetBench run and seems to make using a case insensitive run as efficient as a case sensitive run. Also tidied up our sys_select usage - added a maxfd parameter and also added an implementation of select in terms of poll(), for systems where poll() is much faster. This is disabled by default. Jeremy. (This used to be commit 779b924ec1f6c81ff578d22295b20fece698d1fc) --- source3/smbd/filename.c | 20 ++++++++++++++------ source3/smbd/server.c | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index de4fef5189..9112828092 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -115,7 +115,8 @@ typedef struct { static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; /**************************************************************************** - Compare two names in the stat cache. + Compare two names in the stat cache - to check if we already have such an + entry. *****************************************************************************/ static BOOL stat_name_equal( char *s1, char *s2) @@ -124,13 +125,20 @@ static BOOL stat_name_equal( char *s1, char *s2) } /**************************************************************************** - Compare two names in the stat cache. + Compare a pathname to a name in the stat cache - of a given length. + Note - this code always checks that the next character in the pathname + is either a '/' character, or a '\0' character - to ensure we only + match *full* pathname components. *****************************************************************************/ -static BOOL stat_name_equal_len( char *s1, char *s2, int len) +static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) { - return (case_sensitive ? (strncmp( s1, s2, len) == 0) : - (StrnCaseCmp(s1, s2, len) == 0)); + BOOL matched = (case_sensitive ? (strncmp( stat_name, orig_name, len) == 0) : + (StrnCaseCmp(stat_name, orig_name, len) == 0)); + if(orig_name[len] != '/' && orig_name[len] != '\0') + return False; + + return matched; } /**************************************************************************** @@ -211,7 +219,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name )); - if(ubi_dlCount(&stat_cache) > MAX_STAT_CACHE_SIZE) { + if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) { scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache ); free((char *)scp); return; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4c38fb5f4b..1bc6cf273f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -208,7 +208,7 @@ max can be %d\n", memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select(&lfds,NULL); + num = sys_select(256,&lfds,NULL); if (num == -1 && errno == EINTR) continue; -- cgit From 61b5fd6f32e9ccb612df1354a3e3b3bed5f2b808 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 31 Aug 1998 03:11:42 +0000 Subject: bounds check next_token() to prevent possible buffer overflows (This used to be commit 3eade55dc7c842bdc50205c330802d211fae54d3) --- source3/smbd/chgpasswd.c | 4 ++-- source3/smbd/groupname.c | 4 ++-- source3/smbd/ipc.c | 26 +++++++++++++------------- source3/smbd/password.c | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index ee6a2d14f4..aebdde6d34 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -262,7 +262,7 @@ static int talktochild(int master, char *chatsequence) *buf = 0; sleep(1); - while (next_token(&ptr,chatbuf,NULL)) { + while (next_token(&ptr,chatbuf,NULL,sizeof(chatbuf))) { BOOL ok=True; count++; pwd_sub(chatbuf); @@ -277,7 +277,7 @@ static int talktochild(int master, char *chatsequence) return(False); } - if (!next_token(&ptr,chatbuf,NULL)) break; + if (!next_token(&ptr,chatbuf,NULL,sizeof(chatbuf))) break; pwd_sub(chatbuf); if (!strequal(chatbuf,".")) writestring(master,chatbuf); diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 689fdbbbd9..3183c5c83c 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -125,10 +125,10 @@ void load_groupname_map(void) if (!*s || strchr("#;",*s)) continue; - if(!next_token(&s,unixname, "\t\n\r=")) + if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) continue; - if(!next_token(&s,windows_name, "\t\n\r=")) + if(!next_token(&s,windows_name, "\t\n\r=", sizeof(windows_name))) continue; trim_string(unixname, " ", " "); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 70c2668d92..7c0a51f785 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -658,7 +658,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, p = q; /* reset string pointer */ fgets(p,8191,f); p[strlen(p)-1]='\0'; - if (next_token(&p,tok,":") && + if (next_token(&p,tok,":",sizeof(tok)) && (strlen(lp_printerdriver(snum)) == strlen(tok)) && (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) ok=1; @@ -666,9 +666,9 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, fclose(f); /* driver file name */ - if (ok && !next_token(&p,driver,":")) ok = 0; + if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0; /* data file name */ - if (ok && !next_token(&p,datafile,":")) ok = 0; + if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0; /* * for the next tokens - which may be empty - I have to check for empty * tokens first because the next_token function will skip all empty @@ -679,7 +679,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, if (*p == ':') { *helpfile = '\0'; p++; - } else if (!next_token(&p,helpfile,":")) ok = 0; + } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0; } if (ok) { @@ -687,11 +687,11 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, if (*p == ':') { *langmon = '\0'; p++; - } else if (!next_token(&p,langmon,":")) ok = 0; + } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0; } /* default data type */ - if (ok && !next_token(&p,datatype,":")) ok = 0; + if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0; if (ok) { PACKI(desc,"W",0x0400); /* don't know */ @@ -714,7 +714,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, /* no need to check return value here - it was already tested in * get_printerdrivernumber */ - next_token(&p,tok,","); + next_token(&p,tok,",",sizeof(tok)); PACKS(desc,"z",tok); /* driver files to copy */ DEBUG(3,("file:%s:\n",tok)); } @@ -755,7 +755,7 @@ int get_printerdrivernumber(int snum) { p = q; /* reset string pointer */ fgets(p,8191,f); - if (next_token(&p,tok,":") && + if (next_token(&p,tok,":",sizeof(tok)) && (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) ok=1; } @@ -771,7 +771,7 @@ int get_printerdrivernumber(int snum) return(0); /* count the number of files */ - while (next_token(&p,tok,",")) + while (next_token(&p,tok,",",sizeof(tok))) i++; } free(q); @@ -1021,10 +1021,10 @@ static int get_server_info(uint32 servertype, } s = &(*servers)[count]; - 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)) { + if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue; + if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue; + if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue; + if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) { /* this allows us to cope with an old nmbd */ pstrcpy(s->domain,global_myworkgroup); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 4ee9e8705d..dadbcad11e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -934,7 +934,7 @@ struct cli_state *server_cryptkey(void) return NULL; p = lp_passwordserver(); - while(p && next_token( &p, desthost, LIST_SEP)) { + while(p && next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { standard_sub_basic(desthost); strupper(desthost); @@ -1214,7 +1214,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); */ p = lp_passwordserver(); - while(p && next_token( &p, remote_machine, LIST_SEP)) { + while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { standard_sub_basic(remote_machine); strupper(remote_machine); -- cgit From 693480af8bb2d3e83566af9463ca427f47a879da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Aug 1998 20:20:54 +0000 Subject: configure.in, configure: include/config.h.in: Added stropts and poll. include/smb.h: Moved old typedefs of uint8 etc. into include/includes.h where all the other defines live (changed them from typedefs to defines). Other changes : changed from using uint32 to SMB_DEV_T and SMB_INO_T in preparation for moving to size independed (ie. 64 bit clean) device and inode access. Stat call wrapper comes next :-). Jeremy. (This used to be commit 3d9ec96de5e04e83abafe9c5d980bd39eee856ea) --- source3/smbd/close.c | 4 ++-- source3/smbd/files.c | 10 +++++----- source3/smbd/open.c | 23 ++++++++++++----------- source3/smbd/oplock.c | 25 +++++++++++++++++-------- source3/smbd/reply.c | 4 ++-- source3/smbd/trans2.c | 5 ++++- 6 files changed, 42 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 07b000d7ad..42b16bc7ac 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -99,8 +99,8 @@ static void close_filestruct(files_struct *fsp) ****************************************************************************/ void close_file(files_struct *fsp, BOOL normal_close) { - uint32 dev = fsp->fd_ptr->dev; - uint32 inode = fsp->fd_ptr->inode; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; int token; connection_struct *conn = fsp->conn; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 00de8dfffa..d098677fba 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -125,8 +125,8 @@ file_fd_struct *fd_get_already_open(struct stat *sbuf) for (fd_ptr=FileFd;fd_ptr;fd_ptr=fd_ptr->next) { if ((fd_ptr->ref_count > 0) && - (((uint32)sbuf->st_dev) == fd_ptr->dev) && - (((uint32)sbuf->st_ino) == fd_ptr->inode)) { + (sbuf->st_dev == fd_ptr->dev) && + (sbuf->st_ino == fd_ptr->inode)) { fd_ptr->ref_count++; DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %x, ref_count = %d\n", fd_ptr->dev, fd_ptr->inode, @@ -162,8 +162,8 @@ file_fd_struct *fd_get_new(void) memset(fd_ptr, 0, sizeof(*fd_ptr)); fd_ptr->fdnum = i; - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; + fd_ptr->dev = (SMB_DEV_T)-1; + fd_ptr->inode = (SMB_INO_T)-1; fd_ptr->fd = -1; fd_ptr->fd_readonly = -1; fd_ptr->fd_writeonly = -1; @@ -254,7 +254,7 @@ void file_close_user(int vuid) /**************************************************************************** find a fsp given a device, inode and timevalue ****************************************************************************/ -files_struct *file_find_dit(int dev, int inode, struct timeval *tval) +files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { int count=0; files_struct *fsp; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e54a456092..1a16a25c0a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -166,8 +166,8 @@ int fd_attempt_close(file_fd_struct *fd_ptr) fd_ptr->fd_readonly = -1; fd_ptr->fd_writeonly = -1; fd_ptr->real_open_flags = -1; - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; + fd_ptr->dev = (SMB_DEV_T)-1; + fd_ptr->inode = (SMB_INO_T)-1; fd_ptr->uid_cache_count = 0; } else { fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); @@ -484,8 +484,8 @@ static void open_file(files_struct *fsp,connection_struct *conn, } /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = (uint32)sbuf->st_dev; - fd_ptr->inode = (uint32)sbuf->st_ino; + fd_ptr->dev = sbuf->st_dev; + fd_ptr->inode = sbuf->st_ino; fsp->fd_ptr = fd_ptr; conn->num_files_open++; @@ -596,8 +596,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int BOOL share_locked = False; BOOL fcbopen = False; int token; - uint32 dev = 0; - uint32 inode = 0; + SMB_DEV_T dev = 0; + SMB_INO_T inode = 0; int num_share_modes = 0; fsp->open = False; @@ -681,8 +681,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int if (file_existed) { - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; + dev = sbuf.st_dev; + inode = sbuf.st_ino; lock_share_entry(conn, dev, inode, &token); share_locked = True; num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); @@ -994,15 +994,16 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) struct stat sbuf; int token; int pid = getpid(); - uint32 dev, inode; + SMB_DEV_T dev; + SMB_INO_T inode; if(!lp_share_modes(SNUM(conn))) return True; if (sys_stat(fname,&sbuf) == -1) return(True); - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; + dev = sbuf.st_dev; + inode = sbuf.st_ino; lock_share_entry(conn, dev, inode, &token); num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index d9df308a35..ab88b82953 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -105,8 +105,11 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); } { uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + /* + * Warning - this will need to be changed if SMB_DEV_T/SMB_INO_T <> 4 bytes. !! + */ + SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); struct timeval tval; struct sockaddr_in toaddr; @@ -176,8 +179,11 @@ reply - dumping info.\n")); { uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + /* + * Warning - this will need to be changed if SMB_DEV_T/SMB_INO_T <> 4 bytes. !! + */ + SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); DEBUG(0,("process_local_message: unsolicited oplock break reply from \ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); @@ -196,7 +202,7 @@ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); /**************************************************************************** Process an oplock break directly. ****************************************************************************/ -BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) +BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { extern struct current_user current_user; extern int Client; @@ -458,7 +464,7 @@ by the local smbd then call the oplock break function directly. ****************************************************************************/ BOOL request_oplock_break(share_mode_entry *share_entry, - uint32 dev, uint32 inode) + SMB_DEV_T dev, SMB_INO_T inode) { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; @@ -487,10 +493,13 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); - SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); - SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); + /* + * WARNING - this will need to be changed if SMB_DEV_T/SMB_INO_T <> 4 bytes. + */ + SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); + SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); /* set the address and port */ bzero((char *)&addr_out,sizeof(addr_out)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3052bd730c..e30c31776c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3544,8 +3544,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { int token; - uint32 dev = fsp->fd_ptr->dev; - uint32 inode = fsp->fd_ptr->inode; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", fsp->fnum)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index da11dbcb29..3a851cfa8b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -201,7 +201,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, pstring fname; int unixmode; int size=0,fmode=0,mtime=0,rmode; - int32 inode = 0; + SMB_INO_T inode = 0; struct stat sbuf; int smb_action = 0; BOOL bad_path = False; @@ -278,6 +278,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, } SSVAL(params,18,smb_action); + /* + * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes. + */ SIVAL(params,20,inode); /* Send the required number of replies */ -- cgit From a5f8955ccb875f8467a83c241abf2e58c2bb96f4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 1 Sep 1998 01:10:01 +0000 Subject: check that a valid pipe is passed before doing a pipe close. I made this change after getting a segv in reply_pipe_close(). The funny thing was that pipes_open was 1 and Pipes was NULL. That "can't happen" and suggests that we have a wild pointer somewhere. I suspect the rpc code, as I was playing with long share names (a share called "averylongusername") at the time and the logs show lots of srvsvc operations. I bet there is a buffer in the rpc code somewhere that is overflowing and trashing bits of the data segment. (This used to be commit 9fee8c2eb7bd05431cd9bcfbed3804c8ca1ee593) --- source3/smbd/pipes.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index fed5c2bd17..97df3abfc3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -121,6 +121,8 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) char *data; BOOL ok = False; + if (!p) return(ERROR(ERRDOS,ERRbadfid)); + set_message(outbuf,12,0,True); data = smb_buf(outbuf); @@ -148,6 +150,8 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); int outsize = set_message(outbuf,0,0,True); + if (!p) return(ERROR(ERRDOS,ERRbadfid)); + DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum)); if (!close_rpc_pipe_hnd(p, conn)) return(ERROR(ERRDOS,ERRbadfid)); -- cgit From 18556274139cc5a00593471bd745354d98a35303 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Sep 1998 20:11:54 +0000 Subject: More abstraction of file system data types, to move to a 64 bit file interface for the NT SMB's. Created a new define, SMB_STRUCT_STAT that currently is defined to be struct stat - this wil change to a user defined type containing 64 bit info when the correct wrappers are written for 64 bit stat(), fstat() and lstat() calls. Also changed all sys_xxxx() calls that were previously just wrappers to the same call prefixed by a dos_to_unix() call into dos_xxxx() calls. This makes it explicit when a pathname translation is being done, and when it is not. Now, all sys_xxx() calls are meant to be wrappers to mask OS differences, and not silently converting filenames on the fly. Jeremy. (This used to be commit 28aa182dbffaa4ffd86047e608400de4b26e80eb) --- source3/smbd/dir.c | 8 +++---- source3/smbd/dosmode.c | 20 ++++++++-------- source3/smbd/fileio.c | 4 ++-- source3/smbd/filename.c | 18 +++++++-------- source3/smbd/files.c | 2 +- source3/smbd/groupname.c | 2 +- source3/smbd/ipc.c | 2 +- source3/smbd/nttrans.c | 14 +++++------ source3/smbd/open.c | 30 ++++++++++++------------ source3/smbd/predict.c | 2 +- source3/smbd/quotas.c | 12 +++++----- source3/smbd/reply.c | 60 ++++++++++++++++++++++++------------------------ source3/smbd/trans2.c | 24 +++++++++---------- 13 files changed, 99 insertions(+), 99 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 42ed68f713..7c81b826d1 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -408,7 +408,7 @@ void *dptr_fetch_lanman2(int dptr_num) /**************************************************************************** check a filetype for being valid ****************************************************************************/ -BOOL dir_check_ftype(connection_struct *conn,int mode,struct stat *st,int dirtype) +BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype) { if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) return False; @@ -422,7 +422,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,in { char *dname; BOOL found = False; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; pstring path; pstring pathreal; BOOL isrootdir; @@ -471,7 +471,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,in pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (sys_stat(pathreal,&sbuf) != 0) + if (dos_stat(pathreal,&sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]\n",path)); continue; @@ -519,7 +519,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - void *p = sys_opendir(name); + void *p = dos_opendir(name); int used=0; if (!p) return(NULL); diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index da7fdfb973..1336e27281 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -75,7 +75,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode) /**************************************************************************** change a unix mode to a dos mode ****************************************************************************/ -int dos_mode(connection_struct *conn,char *path,struct stat *sbuf) +int dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) { int result = 0; @@ -139,16 +139,16 @@ int dos_mode(connection_struct *conn,char *path,struct stat *sbuf) /******************************************************************* chmod a file - but preserve some bits ********************************************************************/ -int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st) +int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *st) { - struct stat st1; + SMB_STRUCT_STAT st1; int mask=0; int tmp; int unixmode; if (!st) { st = &st1; - if (sys_stat(fname,st)) return(-1); + if (dos_stat(fname,st)) return(-1); } if (S_ISDIR(st->st_mode)) dosmode |= aDIR; @@ -186,23 +186,23 @@ int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st) unixmode |= tmp; } - return(sys_chmod(fname,unixmode)); + return(dos_chmod(fname,unixmode)); } /******************************************************************* -Wrapper around sys_utime that possibly allows DOS semantics rather +Wrapper around dos_utime that possibly allows DOS semantics rather than POSIX. *******************************************************************/ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) { extern struct current_user current_user; - struct stat sb; + SMB_STRUCT_STAT sb; int ret = -1; errno = 0; - if(sys_utime(fname, times) == 0) + if(dos_utime(fname, times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -217,7 +217,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(sys_stat(fname,&sb) != 0) + if(dos_stat(fname,&sb) != 0) return -1; /* Check if we have write access. */ @@ -230,7 +230,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(False); - ret = sys_utime(fname, times); + ret = dos_utime(fname, times); unbecome_root(False); } } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 971d309ff9..047c84f35f 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -102,12 +102,12 @@ int write_file(files_struct *fsp,char *data,int n) } if (!fsp->modified) { - struct stat st; + SMB_STRUCT_STAT st; fsp->modified = True; if (fstat(fsp->fd_ptr->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { - dos_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); + file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); } } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9112828092..3bc69210b9 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -231,7 +231,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, struct stat *pst) +static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -275,7 +275,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, struct s * and then promote it to the top. */ - if(sys_stat( longest_hit->translated_name, pst) != 0) { + if(dos_stat( longest_hit->translated_name, pst) != 0) { /* * Discard this entry. */ @@ -322,9 +322,9 @@ of a pathname does not exist. ****************************************************************************/ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, struct stat *pst) + BOOL *bad_path, SMB_STRUCT_STAT *pst) { - struct stat st; + SMB_STRUCT_STAT st; char *start, *end, *orig_start; pstring dirpath; pstring orig_path; @@ -335,7 +335,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *dirpath = 0; *bad_path = False; if(pst) - memset( (char *)pst, '\0', sizeof(struct stat)); + memset( (char *)pst, '\0', sizeof(SMB_STRUCT_STAT)); if(saved_last_component) *saved_last_component = 0; @@ -406,7 +406,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (sys_stat(name,&st) == 0) { + if (dos_stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -459,7 +459,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Check if the name exists up to this point. */ - if (sys_stat(name, &st) == 0) { + if (dos_stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -611,8 +611,8 @@ BOOL check_name(char *name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { - struct stat statbuf; - if ( (sys_lstat(name,&statbuf) != -1) && + SMB_STRUCT_STAT statbuf; + if ( (dos_lstat(name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d098677fba..341d9946ec 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -117,7 +117,7 @@ files_struct *file_new(void ) fd support routines - attempt to find an already open file by dev and inode - increments the ref_count of the returned file_fd_struct *. ****************************************************************************/ -file_fd_struct *fd_get_already_open(struct stat *sbuf) +file_fd_struct *fd_get_already_open(SMB_STRUCT_STAT *sbuf) { file_fd_struct *fd_ptr; diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 3183c5c83c..6616d0d157 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -68,7 +68,7 @@ void load_groupname_map(void) static time_t groupmap_file_last_modified = (time_t)0; static BOOL initialized = False; char *groupname_map_file = lp_groupname_map(); - struct stat st; + SMB_STRUCT_STAT st; FILE *fp; char *s; pstring buf; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7c0a51f785..e3b39e6eb2 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1985,7 +1985,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha !become_service(fconn,True)) break; - if (sys_rename(fsp->fsp_name,name) == 0) { + if (dos_rename(fsp->fsp_name,name) == 0) { string_set(&fsp->fsp_name,name); } break; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fbcc19e77d..9e507aa4d2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -416,7 +416,7 @@ int reply_ntcreate_and_X(connection_struct *conn, int unixmode, pnum = -1; int fmode=0,mtime=0,rmode=0; off_t file_len = 0; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; files_struct *fsp=NULL; @@ -596,7 +596,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } if(fsp->is_directory) { - if(sys_stat(fsp->fsp_name, &sbuf) != 0) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { close_directory(fsp); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -701,7 +701,7 @@ static int call_nt_transact_create(connection_struct *conn, int unixmode, pnum = -1; int fmode=0,mtime=0,rmode=0; off_t file_len = 0; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; files_struct *fsp = NULL; @@ -1084,7 +1084,7 @@ void process_pending_change_notify_queue(time_t t) */ while((cnbp != NULL) && (cnbp->next_check_time <= t)) { - struct stat st; + SMB_STRUCT_STAT st; files_struct *fsp = cnbp->fsp; connection_struct *conn = cnbp->conn; uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : @@ -1121,7 +1121,7 @@ void process_pending_change_notify_queue(time_t t) continue; } - if(sys_stat(fsp->fsp_name, &st) < 0) { + if(dos_stat(fsp->fsp_name, &st) < 0) { DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \ Error was %s.\n", fsp->fsp_name, strerror(errno) )); /* @@ -1171,7 +1171,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *setup = *ppsetup; files_struct *fsp; change_notify_buf *cnbp; - struct stat st; + SMB_STRUCT_STAT st; fsp = file_fsp(setup,4); @@ -1200,7 +1200,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, * Store the current timestamp on the directory we are monitoring. */ - if(sys_stat(fsp->fsp_name, &st) < 0) { + if(dos_stat(fsp->fsp_name, &st) < 0) { DEBUG(0,("call_nt_transact_notify_change: Unable to stat name = %s. \ Error was %s\n", fsp->fsp_name, strerror(errno) )); free((char *)cnbp); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1a16a25c0a..76e88c2e85 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -29,18 +29,18 @@ extern uint16 oplock_port; /**************************************************************************** -fd support routines - attempt to do a sys_open +fd support routines - attempt to do a dos_open ****************************************************************************/ static int fd_attempt_open(char *fname, int flags, int mode) { - int fd = sys_open(fname,flags,mode); + int fd = dos_open(fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = sys_open(fname,flags,mode); + fd = dos_open(fname,flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -71,7 +71,7 @@ static int fd_attempt_open(char *fname, int flags, int mode) char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = sys_open(fname,flags,mode)) == -1) + if ((fd = dos_open(fname,flags,mode)) == -1) p[max_len] = tmp; } } @@ -127,7 +127,7 @@ Save the already open fd (we cannot close due to POSIX file locking braindamage. ****************************************************************************/ static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) { - int fd = sys_open( fname, O_RDWR, mode); + int fd = dos_open( fname, O_RDWR, mode); if(fd == -1) return; @@ -266,11 +266,11 @@ static void check_for_pipe(char *fname) open a file ****************************************************************************/ static void open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,int mode, struct stat *sbuf) + char *fname1,int flags,int mode, SMB_STRUCT_STAT *sbuf) { extern struct current_user current_user; pstring fname; - struct stat statbuf; + SMB_STRUCT_STAT statbuf; file_fd_struct *fd_ptr; int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); @@ -324,7 +324,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * open fd table. */ if(sbuf == 0) { - if(sys_stat(fname, &statbuf) < 0) { + if(dos_stat(fname, &statbuf) < 0) { if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); @@ -452,7 +452,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fd_attempt_close(fd_ptr); fsp->fd_ptr = 0; if(fd_ptr->ref_count == 0) - sys_unlink(fname); + dos_unlink(fname); errno = ENOSPC; return; } @@ -591,7 +591,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int int flags=0; int flags2=0; int deny_mode = (share_mode>>4)&7; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; BOOL file_existed = file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; @@ -856,14 +856,14 @@ int open_directory(files_struct *fsp,connection_struct *conn, char *fname, int smb_ofun, int unixmode, int *action) { extern struct current_user current_user; - struct stat st; + SMB_STRUCT_STAT st; if (smb_ofun & 0x10) { /* * Create the directory. */ - if(sys_mkdir(fname, unixmode) < 0) { + if(dos_mkdir(fname, unixmode) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -875,7 +875,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Check that it *was* a directory. */ - if(sys_stat(fname, &st) < 0) { + if(dos_stat(fname, &st) < 0) { DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -991,7 +991,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) int ret = False; share_mode_entry *old_shares = 0; int num_share_modes; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int token; int pid = getpid(); SMB_DEV_T dev; @@ -1000,7 +1000,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) if(!lp_share_modes(SNUM(conn))) return True; - if (sys_stat(fname,&sbuf) == -1) return(True); + if (dos_stat(fname,&sbuf) == -1) return(True); dev = sbuf.st_dev; inode = sbuf.st_ino; diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 6f6a4ca655..6e423c8eff 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -66,7 +66,7 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num) if (ret == num) { predict_skip = True; } else { - struct stat rp_stat; + SMB_STRUCT_STAT rp_stat; /* Find the end of the file - ensure we don't read predict beyond it. */ diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index dbdbd49921..7f1cd5ce79 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -51,7 +51,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) uid_t euser_id; int r; struct dqblk D; - struct stat S; + SMB_STRUCT_STAT S; FILE *fp; struct mntent *mnt; int devno; @@ -135,7 +135,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { struct mntent *mnt; FILE *fd; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; dev_t devno ; static dev_t devno_cached = 0 ; static pstring name; @@ -255,7 +255,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) static pstring name; #endif FILE *fd; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; dev_t devno ; static dev_t devno_cached = 0 ; int found ; @@ -377,7 +377,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) uid_t user_id, euser_id; int r, save_errno; struct dqblk D; - struct stat S; + SMB_STRUCT_STAT S; euser_id = geteuid(); user_id = getuid(); @@ -433,7 +433,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) int r; struct dqblk D; struct fs_disk_quota F; - struct stat S; + SMB_STRUCT_STAT S; FILE *fp; struct mntent *mnt; int devno; @@ -573,7 +573,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) struct dqblk D; #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) char dev_disk[256]; - struct stat S; + SMB_STRUCT_STAT S; /* find the block device file */ if ((stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e30c31776c..a3164bd67d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -751,7 +751,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring name; BOOL ok = False; BOOL bad_path = False; - struct stat st; + SMB_STRUCT_STAT st; pstrcpy(name,smb_buf(inbuf) + 1); unix_convert(name,conn,0,&bad_path,&st); @@ -806,7 +806,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size { pstring fname; int outsize = 0; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; BOOL ok = False; int mode=0; uint32 size=0; @@ -829,7 +829,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size else if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || sys_stat(fname,&sbuf) == 0) + if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; @@ -886,7 +886,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok=False; int mode; time_t mtime; - struct stat st; + SMB_STRUCT_STAT st; BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); @@ -898,7 +898,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL)) mode |= aDIR; if (check_name(fname,conn)) - ok = (dos_chmod(conn,fname,mode,NULL) == 0); + ok = (file_chmod(conn,fname,mode,NULL) == 0); if (ok) ok = set_filetime(conn,fname,mtime); @@ -1248,7 +1248,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, time_t mtime=0; int unixmode; int rmode=0; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); @@ -1345,7 +1345,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int smb_ofun = SVAL(inbuf,smb_vwv8); int unixmode; int size=0,fmode=0,mtime=0,rmode=0; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; files_struct *fsp; @@ -1638,12 +1638,12 @@ check if a user is allowed to delete a file ********************************************************************/ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) { - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int fmode; if (!CAN_WRITE(conn)) return(False); - if (sys_lstat(fname,&sbuf) != 0) return(False); + if (dos_lstat(fname,&sbuf) != 0) return(False); fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); if (!lp_delete_readonly(SNUM(conn))) { @@ -1700,7 +1700,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (can_delete(directory,conn,dirtype) && !sys_unlink(directory)) count++; + if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++; if (!count) exists = file_exist(directory,NULL); } else { void *dirptr = NULL; @@ -1731,7 +1731,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; - if (!sys_unlink(fname)) count++; + if (!dos_unlink(fname)) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); } CloseDir(dirptr); @@ -1813,7 +1813,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s int sizeneeded = startpos + maxcount; if (size < sizeneeded) { - struct stat st; + SMB_STRUCT_STAT st; if (fstat(fsp->fd_ptr->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) @@ -2787,7 +2787,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) - ret = sys_mkdir(directory,unix_mode(conn,aDIR)); + ret = dos_mkdir(directory,unix_mode(conn,aDIR)); if (ret < 0) { @@ -2822,7 +2822,7 @@ static BOOL recursive_rmdir(char *directory) while((dname = ReadDirName(dirptr))) { pstring fullname; - struct stat st; + SMB_STRUCT_STAT st; if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; @@ -2838,7 +2838,7 @@ static BOOL recursive_rmdir(char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(sys_lstat(fullname, &st) != 0) + if(dos_lstat(fullname, &st) != 0) { ret = True; break; @@ -2851,13 +2851,13 @@ static BOOL recursive_rmdir(char *directory) ret = True; break; } - if(sys_rmdir(fullname) != 0) + if(dos_rmdir(fullname) != 0) { ret = True; break; } } - else if(sys_unlink(fullname) != 0) + else if(dos_unlink(fullname) != 0) { ret = True; break; @@ -2884,7 +2884,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { dptr_closepath(directory,SVAL(inbuf,smb_pid)); - ok = (sys_rmdir(directory) == 0); + ok = (dos_rmdir(directory) == 0); if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn))) { /* Check to see if the only thing in this directory are @@ -2914,7 +2914,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, while ((dname = ReadDirName(dirptr))) { pstring fullname; - struct stat st; + SMB_STRUCT_STAT st; if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; @@ -2929,7 +2929,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(sys_lstat(fullname, &st) != 0) + if(dos_lstat(fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) { @@ -2938,15 +2938,15 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if(recursive_rmdir(fullname) != 0) break; } - if(sys_rmdir(fullname) != 0) + if(dos_rmdir(fullname) != 0) break; } - else if(sys_unlink(fullname) != 0) + else if(dos_unlink(fullname) != 0) break; } CloseDir(dirptr); /* Retry the rmdir */ - ok = (sys_rmdir(directory) == 0); + ok = (dos_rmdir(directory) == 0); } else CloseDir(dirptr); @@ -3047,11 +3047,11 @@ check if a user is allowed to rename a file ********************************************************************/ static BOOL can_rename(char *fname,connection_struct *conn) { - struct stat sbuf; + SMB_STRUCT_STAT sbuf; if (!CAN_WRITE(conn)) return(False); - if (sys_lstat(fname,&sbuf) != 0) return(False); + if (dos_lstat(fname,&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); return(True); @@ -3171,13 +3171,13 @@ int rename_internals(connection_struct *conn, */ if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !sys_rename(directory,newname)) + !dos_rename(directory,newname)) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && !file_exist(newname,NULL) && - !sys_rename(directory,newname)) + !dos_rename(directory,newname)) count++; } @@ -3232,7 +3232,7 @@ int rename_internals(connection_struct *conn, continue; } - if (!sys_rename(fname,destname)) + if (!dos_rename(fname,destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3284,7 +3284,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory) { int Access,action; - struct stat st; + SMB_STRUCT_STAT st; int ret=0; files_struct *fsp1,*fsp2; pstring dest; @@ -3940,7 +3940,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si ****************************************************************************/ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int outsize = 0; int mode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3a851cfa8b..8871d568dd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -202,7 +202,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int unixmode; int size=0,fmode=0,mtime=0,rmode; SMB_INO_T inode = 0; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; files_struct *fsp; @@ -302,7 +302,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, { char *dname; BOOL found = False; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; pstring mask; pstring pathreal; pstring fname; @@ -376,7 +376,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (sys_stat(pathreal,&sbuf) != 0) + if (dos_stat(pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); continue; @@ -1062,13 +1062,13 @@ static int call_trans2qfsinfo(connection_struct *conn, char *params = *pparams; uint16 info_level = SVAL(params,0); int data_len; - struct stat st; + SMB_STRUCT_STAT st; char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(sys_stat(".",&st)!=0) { + if(dos_stat(".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return (ERROR(ERRSRV,ERRinvdevice)); } @@ -1203,7 +1203,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, int mode=0; int size=0; unsigned int data_size; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; pstring fname1; char *fname; char *p; @@ -1229,7 +1229,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname = &fname1[0]; pstrcpy(fname,¶ms[6]); unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && sys_stat(fname,&sbuf))) { + if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1434,7 +1434,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, int mode=0; int size=0; struct utimbuf tvs; - struct stat st; + SMB_STRUCT_STAT st; pstring fname1; char *fname; int fd = -1; @@ -1473,7 +1473,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(!VALID_STAT(st) && sys_stat(fname,&st)!=0) { + if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1601,7 +1601,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } /* check the mode isn't different, before changing it */ - if (mode != dos_mode(conn, fname, &st) && dos_chmod(conn, fname, mode, NULL)) + if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL)) { DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1611,7 +1611,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if (fd == -1) { - fd = sys_open(fname,O_RDWR,0); + fd = dos_open(fname,O_RDWR,0); if (fd == -1) { return(ERROR(ERRDOS,ERRbadpath)); @@ -1653,7 +1653,7 @@ static int call_trans2mkdir(connection_struct *conn, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory,conn)) - ret = sys_mkdir(directory,unix_mode(conn,aDIR)); + ret = dos_mkdir(directory,unix_mode(conn,aDIR)); if(ret < 0) { -- cgit From 148691b1c5e8e93b02762757345a54c82e6fdadc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Sep 1998 05:00:47 +0000 Subject: we are never interested in SIGPIPE so just ignore (block) it always. Don't even install a handler. (This used to be commit 72c383f4b7bcce5374632dc972df16ab0e2542b9) --- source3/smbd/server.c | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1bc6cf273f..dadf2018c8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -67,25 +67,6 @@ void killkids(void) } - -/**************************************************************************** - this is called when the client exits abruptly - **************************************************************************/ -static void sig_pipe(int sig) -{ - struct cli_state *cli; - BlockSignals(True,SIGPIPE); - - if ((cli = server_client()) && cli->initialised) { - DEBUG(3,("lost connection to password server\n")); - cli_shutdown(cli); - BlockSignals(False,SIGPIPE); - return; - } - - exit_server("Got sigpipe\n"); -} - /**************************************************************************** open the socket communication ****************************************************************************/ @@ -96,7 +77,6 @@ static BOOL open_sockets_inetd(void) /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ - CatchSignal(SIGPIPE, SIGNAL_CAST sig_pipe); Client = dup(0); /* close our standard file descriptors */ @@ -244,9 +224,6 @@ max can be %d\n", if (Client != -1 && fork()==0) { /* Child code ... */ - CatchSignal(SIGPIPE, - SIGNAL_CAST sig_pipe); - /* close the listening socket(s) */ for(i = 0; i < num_interfaces; i++) close(fd_listenset[i]); @@ -552,6 +529,9 @@ static void usage(char *pname) fault_setup((void (*)(void *))exit_server); CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig); + /* we are never interested in SIGPIPE */ + BlockSignals(True,SIGPIPE); + /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); -- cgit From 0067ea1b5a634db442ed8f89558dc4d43d9f3fe6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Sep 1998 17:23:41 +0000 Subject: Fix for PR#9497 - not waiting for child. Jeremy. (This used to be commit e817d836bba3aaf0f732d66bc5a4383a7f7005db) --- source3/smbd/chgpasswd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index aebdde6d34..c9478166c4 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -319,12 +319,14 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL kill(pid, SIGKILL); /* be sure to end this process */ } - close(master); - if ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { DEBUG(3,("The process is no longer waiting!\n\n")); + close(master); return(False); } + + close(master); + if (pid != wpid) { DEBUG(3,("We were waiting for the wrong process ID\n")); return(False); -- cgit From 0b5cc173099c7fd5ea4865ef4197739ec87e4c35 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Sep 1998 03:14:31 +0000 Subject: fixed a bug in the name mangling code. It implicitly assumed that mangling a name can't increase it's size which isn't true. (imagine a file called "L B" which mangles to "LB~XX") The symptoms were that users couldn't run batch files from short directory names that contained non 8.3 characters (such as spaces). (This used to be commit c319d8ea3f8b42bb3a8e501642971ed0bdb21583) --- source3/smbd/filename.c | 2 +- source3/smbd/mangle.c | 78 ++++++++++++++++++++++++------------------------- 2 files changed, 40 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3bc69210b9..656bb8997c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -77,7 +77,7 @@ BOOL mangled_equal(char *name1, char *name2) return(False); pstrcpy(tmpname,name2); - mangle_name_83(tmpname,sizeof(tmpname)); + mangle_name_83(tmpname); return(strequal(name1,tmpname)); } diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 0703a4a74e..0a3d3f54eb 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -799,12 +799,12 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) } } /* do_fwd_mangled_map */ -/* ************************************************************************** ** +/***************************************************************************** * do the actual mangling to 8.3 format - * - * ************************************************************************** ** + * the buffer must be able to hold 13 characters (including the null) + ***************************************************************************** */ -void mangle_name_83( char *s, int s_len ) +void mangle_name_83( char *s) { int csum = str_checksum(s); char *p; @@ -907,7 +907,7 @@ void mangle_name_83( char *s, int s_len ) csum = csum % (36*36); - (void)slprintf( s, s_len - 1, "%s%c%c%c", + (void)slprintf(s, 12, "%s%c%c%c", base, magic_char, base36( csum/36 ), base36( csum ) ); if( *extension ) @@ -917,12 +917,13 @@ void mangle_name_83( char *s, int s_len ) } DEBUG( 5, ( "%s\n", s ) ); + } /* mangle_name_83 */ -/* ************************************************************************** ** +/***************************************************************************** * Convert a filename to DOS format. Return True if successful. * - * Input: OutName - Source *and* destination buffer. + * Input: OutName - Source *and* destination buffer. * * NOTE that OutName must point to a memory space that * is at least 13 bytes in size! @@ -939,47 +940,46 @@ void mangle_name_83( char *s, int s_len ) * Output: Returns False only if the name wanted mangling but the share does * not have name mangling turned on. * - * ************************************************************************** ** + * **************************************************************************** */ -BOOL name_map_mangle( char *OutName, BOOL need83, int snum ) - { - DEBUG(5, - ("name_map_mangle( %s, %s, %d )\n", OutName, need83?"TRUE":"FALSE", snum) ); +BOOL name_map_mangle(char *OutName, BOOL need83, int snum) +{ + char *map; + DEBUG(5,("name_map_mangle( %s, %s, %d )\n", + OutName, need83?"TRUE":"FALSE", snum)); #ifdef MANGLE_LONG_FILENAMES - if( !need83 && is_illegal_name(OutName) ) - need83 = True; + if( !need83 && is_illegal_name(OutName) ) + need83 = True; #endif - /* apply any name mappings */ - { - char *map = lp_mangled_map( snum ); + /* apply any name mappings */ + map = lp_mangled_map(snum); - if( map && *map ) - do_fwd_mangled_map( OutName, map ); - } + if (map && *map) { + do_fwd_mangled_map( OutName, map ); + } - /* check if it's already in 8.3 format */ - if( need83 && !is_8_3( OutName, True ) ) - { - char *tmp; /* kludge -- mangle_name_83() overwrites the source string */ - /* but cache_mangled_name() needs both. crh 09-Apr-1998 */ + /* check if it's already in 8.3 format */ + if (need83 && !is_8_3(OutName, True)) { + char *tmp; - if( !lp_manglednames( snum ) ) - return( False ); + if (!lp_manglednames(snum)) { + return(False); + } - /* mangle it into 8.3 */ - tmp = strdup( OutName ); - mangle_name_83( OutName, strlen(OutName) ); - if( tmp ) - { - cache_mangled_name( OutName, tmp ); - free( tmp ); - } - } + /* mangle it into 8.3 */ + tmp = strdup(OutName); + mangle_name_83(OutName); - DEBUG( 5, ("name_map_mangle() ==> [%s]\n", OutName) ); - return( True ); - } /* name_map_mangle */ + if(tmp) { + cache_mangled_name(OutName, tmp); + free(tmp); + } + } + + DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName)); + return(True); +} /* name_map_mangle */ /* ========================================================================== */ -- cgit From 4acd373e5bbd615141ceb5fb3c4a588a5b4581d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Sep 1998 05:37:15 +0000 Subject: changed the SMBtrans reply code to align at the same alignment as observed from NT. We were aligning the data before but not the parameters. This aligns both. This change may break some other parts of ipc.c if we have relied on the alignment somewhere, so if you think this broke something then let me know. (This used to be commit d252d331015b7606618ba1422bb669da003da293) --- source3/smbd/ipc.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e3b39e6eb2..048afe35cd 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -144,7 +144,7 @@ static void copy_trans_params_and_data(char *outbuf, int align, int param_offset, int data_offset, int param_len, int data_len) { - char *copy_into = smb_buf(outbuf); + char *copy_into = smb_buf(outbuf)+1; DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", param_offset, param_offset + param_len, @@ -182,14 +182,9 @@ static void send_trans_reply(char *outbuf, this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); -#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING - /* if you don't want Net Monitor to decode your packets, do this!!! */ - align = ((this_lparam+1)%4); -#else - align = (this_lparam%4); -#endif + align = ((this_lparam)%4); - set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); + set_message(outbuf,10+lsetup,1+align+this_ldata+this_lparam,True); if (buffer_too_large) { @@ -206,10 +201,10 @@ static void send_trans_reply(char *outbuf, SSVAL(outbuf,smb_vwv0,lparam); SSVAL(outbuf,smb_vwv1,ldata); SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); SSVAL(outbuf,smb_vwv5,0); SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); SSVAL(outbuf,smb_vwv8,0); SSVAL(outbuf,smb_vwv9,lsetup); @@ -231,7 +226,7 @@ static void send_trans_reply(char *outbuf, align = (this_lparam%4); - set_message(outbuf,10,this_ldata+this_lparam+align,False); + set_message(outbuf,10,1+this_ldata+this_lparam+align,False); copy_trans_params_and_data(outbuf, align, rparam , rdata, @@ -239,10 +234,10 @@ static void send_trans_reply(char *outbuf, this_lparam, this_ldata); SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); SSVAL(outbuf,smb_vwv5,tot_param); SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); SSVAL(outbuf,smb_vwv8,tot_data); SSVAL(outbuf,smb_vwv9,0); -- cgit From 7bb86c1b132bce31a006ea9768a54db7a45fe1a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Sep 1998 18:40:31 +0000 Subject: Ok - this is the 64 bit widening check in. It changes the configure to check for stat64 and friends, and then changes much of Samba to use the data type SMB_OFF_T for file size information. stat/fstat/lstat/lseek/ftruncate have now become sys_stat etc. to hide the 64 bit calls if needed. Note that this still does not expose 64 bit functionality to the client, as the changes to the reply_xxx smb's are not yet done. This code change should make these changes possible. Still to do before full 64 bit-ness to the client: fcntl lock code. statfs code widening of dev_t and ino_t (now possible due to SMB_DEV_T and SMB_OFF_T types being in place). Let me know if wierd things happen after this check-in and I'll fix them :-). Jeremy. (This used to be commit 14500936c321d15995c963766aac67bf1f4e3824) --- source3/smbd/connection.c | 8 +- source3/smbd/dir.c | 3 +- source3/smbd/fileio.c | 8 +- source3/smbd/groupname.c | 2 +- source3/smbd/nttrans.c | 12 +-- source3/smbd/open.c | 4 +- source3/smbd/predict.c | 10 +-- source3/smbd/quotas.c | 32 ++++---- source3/smbd/reply.c | 54 +++++++------ source3/smbd/trans2.c | 201 ++++++++++++++++++++++++---------------------- 10 files changed, 172 insertions(+), 162 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 342a5f43bc..c3b6ba0199 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -88,7 +88,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) bzero((void *)&crec,sizeof(crec)); /* remove our mark */ - if (lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || + if (sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || write(fd, &crec,sizeof(crec)) != sizeof(crec)) { DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno))); if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { @@ -159,14 +159,14 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO /* find a free spot */ for (i=0;i=total_recs || - lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || + sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || read(fd,&crec,sizeof(crec)) != sizeof(crec)) { if (foundi < 0) foundi = i; break; } if (Clear && crec.pid && !process_exists(crec.pid)) { - lseek(fd,i*sizeof(crec),SEEK_SET); + sys_lseek(fd,i*sizeof(crec),SEEK_SET); bzero((void *)&crec,sizeof(crec)); write(fd, &crec,sizeof(crec)); if (foundi < 0) foundi = i; @@ -206,7 +206,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO StrnCpy(crec.addr,client_addr(Client),sizeof(crec.addr)-1); /* make our mark */ - if (lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) || + if (sys_lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) || write(fd, &crec,sizeof(crec)) != sizeof(crec)) { if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7c81b826d1..73db295548 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -418,7 +418,8 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int di /**************************************************************************** get a directory entry ****************************************************************************/ -BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend) +BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, + SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) { char *dname; BOOL found = False; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 047c84f35f..6d6edf9d37 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -27,14 +27,14 @@ extern int DEBUGLEVEL; /**************************************************************************** seek a file. Try to avoid the seek if possible ****************************************************************************/ -int seek_file(files_struct *fsp,uint32 pos) +SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { - uint32 offset = 0; + SMB_OFF_T offset = 0; if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; - fsp->pos = (int)(lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); + fsp->pos = (sys_lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); return(fsp->pos); } @@ -104,7 +104,7 @@ int write_file(files_struct *fsp,char *data,int n) if (!fsp->modified) { SMB_STRUCT_STAT st; fsp->modified = True; - if (fstat(fsp->fd_ptr->fd,&st) == 0) { + if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 6616d0d157..75af12a47a 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -82,7 +82,7 @@ void load_groupname_map(void) if (!*groupname_map_file) return; - if(stat(groupname_map_file, &st) != 0) { + if(sys_stat(groupname_map_file, &st) != 0) { DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n", groupname_map_file, strerror(errno) )); return; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9e507aa4d2..3fdee043dc 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -415,7 +415,7 @@ int reply_ntcreate_and_X(connection_struct *conn, int oplock_request = 0; int unixmode, pnum = -1; int fmode=0,mtime=0,rmode=0; - off_t file_len = 0; + SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; @@ -602,7 +602,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -660,12 +660,12 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 12; -#if OFF_T_IS_64_BITS +#ifdef LARGE_SMB_OFF_T SIVAL(p,0, file_len & 0xFFFFFFFF); SIVAL(p,4, file_len >> 32); -#else /* OFF_T_IS_64_BITS */ +#else /* LARGE_SMB_OFF_T */ SIVAL(p,0,file_len); -#endif /* OFF_T_IS_64_BITS */ +#endif /* LARGE_SMB_OFF_T */ p += 12; SCVAL(p,0,fsp->is_directory ? 1 : 0); @@ -809,7 +809,7 @@ static int call_nt_transact_create(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 76e88c2e85..395de66a88 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -472,7 +472,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, { if(sbuf == 0) { /* Do the fstat */ - if(fstat(fd_ptr->fd, &statbuf) == -1) { + if(sys_fstat(fd_ptr->fd, &statbuf) == -1) { /* Error - backout !! */ DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", fd_ptr->fd, fname,strerror(errno))); @@ -576,7 +576,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i unix_ERR_code = ERRlock; } else - ftruncate(fsp->fd_ptr->fd,0); + sys_ftruncate(fsp->fd_ptr->fd,0); } } diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 6e423c8eff..0deda0c0b6 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -27,11 +27,11 @@ extern int DEBUGLEVEL; /* variables used by the read prediction module */ static int rp_fd = -1; -static int rp_offset = 0; +static SMB_OFF_T rp_offset = 0; static int rp_length = 0; static int rp_alloced = 0; static int rp_predict_fd = -1; -static int rp_predict_offset = 0; +static SMB_OFF_T rp_predict_offset = 0; static int rp_predict_length = 0; static int rp_timeout = 5; static time_t rp_time = 0; @@ -42,7 +42,7 @@ extern time_t smb_last_time; /**************************************************************************** handle read prediction on a file ****************************************************************************/ -int read_predict(int fd,int offset,char *buf,char **ptr,int num) +int read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,int num) { int ret = 0; int possible = rp_length - (offset - rp_offset); @@ -70,7 +70,7 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num) /* Find the end of the file - ensure we don't read predict beyond it. */ - if(fstat(fd,&rp_stat) < 0) + if(sys_fstat(fd,&rp_stat) < 0) { DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); predict_skip = True; @@ -134,7 +134,7 @@ void do_read_prediction(void) } } - if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { + if (sys_lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { rp_fd = -1; rp_predict_fd = -1; return; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 7f1cd5ce79..b7a538e189 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -54,12 +54,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) SMB_STRUCT_STAT S; FILE *fp; struct mntent *mnt; - int devno; + SMB_DEV_T devno; int found; /* find the block device file */ - if ( stat(path, &S) == -1 ) { + if ( sys_stat(path, &S) == -1 ) { return(False) ; } @@ -69,7 +69,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) found = False ; while ((mnt = getmntent(fp))) { - if ( stat(mnt->mnt_dir,&S) == -1 ) + if ( sys_stat(mnt->mnt_dir,&S) == -1 ) continue ; if (S.st_dev == devno) { found = True ; @@ -136,15 +136,15 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) struct mntent *mnt; FILE *fd; SMB_STRUCT_STAT sbuf; - dev_t devno ; - static dev_t devno_cached = 0 ; + SMB_DEV_T devno ; + static SMB_DEV_T devno_cached = 0 ; static pstring name; struct q_request request ; struct qf_header header ; static int quota_default = 0 ; int found ; - if ( stat(path,&sbuf) == -1 ) + if ( sys_stat(path,&sbuf) == -1 ) return(False) ; devno = sbuf.st_dev ; @@ -160,7 +160,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) while ((mnt = getmntent(fd)) != NULL) { - if ( stat(mnt->mnt_dir,&sbuf) == -1 ) + if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) continue ; if (sbuf.st_dev == devno) { @@ -256,11 +256,11 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #endif FILE *fd; SMB_STRUCT_STAT sbuf; - dev_t devno ; - static dev_t devno_cached = 0 ; + SMB_DEV_T devno ; + static SMB_DEV_T devno_cached = 0 ; int found ; - if ( stat(path,&sbuf) == -1 ) + if ( sys_stat(path,&sbuf) == -1 ) return(False) ; devno = sbuf.st_dev ; @@ -273,7 +273,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) found = False ; while (getmntent(fd, &mnt) == 0) { - if ( stat(mnt.mnt_mountp,&sbuf) == -1 ) + if ( sys_stat(mnt.mnt_mountp,&sbuf) == -1 ) continue ; DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt.mnt_mountp,sbuf.st_dev)); @@ -292,7 +292,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) found = False ; while ((mnt = getmntent(fd)) != NULL) { - if ( stat(mnt->mnt_dir,&sbuf) == -1 ) + if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) continue ; DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); @@ -436,12 +436,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) SMB_STRUCT_STAT S; FILE *fp; struct mntent *mnt; - int devno; + SMB_DEV_T devno; int found; /* find the block device file */ - if ( stat(path, &S) == -1 ) { + if ( sys_stat(path, &S) == -1 ) { return(False) ; } @@ -451,7 +451,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) found = False ; while ((mnt = getmntent(fp))) { - if ( stat(mnt->mnt_dir,&S) == -1 ) + if ( sys_stat(mnt->mnt_dir,&S) == -1 ) continue ; if (S.st_dev == devno) { found = True ; @@ -575,7 +575,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) char dev_disk[256]; SMB_STRUCT_STAT S; /* find the block device file */ - if ((stat(path, &S)<0) || + if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); #endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a3164bd67d..3665518ae6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -809,7 +809,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT sbuf; BOOL ok = False; int mode=0; - uint32 size=0; + SMB_OFF_T size=0; time_t mtime=0; BOOL bad_path = False; @@ -860,7 +860,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size put_dos_date3(outbuf,smb_vwv1,mtime & ~1); else put_dos_date3(outbuf,smb_vwv1,mtime); - SIVAL(outbuf,smb_vwv3,size); + SIVAL(outbuf,smb_vwv3,(uint32)size); if (Protocol >= PROTOCOL_NT1) { char *p = strrchr(fname,'/'); @@ -870,7 +870,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ } - DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, size ) ); + DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); return(outsize); } @@ -953,7 +953,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring mask; pstring directory; pstring fname; - int size,mode; + SMB_OFF_T size; + int mode; time_t date; int dirtype; int outsize = 0; @@ -1244,7 +1245,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int outsize = 0; int fmode=0; int share_mode; - int size = 0; + SMB_OFF_T size = 0; time_t mtime=0; int unixmode; int rmode=0; @@ -1289,7 +1290,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1311,7 +1312,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, put_dos_date3(outbuf,smb_vwv2,mtime & ~1); else put_dos_date3(outbuf,smb_vwv2,mtime); - SIVAL(outbuf,smb_vwv4,size); + SIVAL(outbuf,smb_vwv4,(uint32)size); SSVAL(outbuf,smb_vwv6,rmode); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { @@ -1344,7 +1345,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt #endif int smb_ofun = SVAL(inbuf,smb_vwv8); int unixmode; - int size=0,fmode=0,mtime=0,rmode=0; + SMB_OFF_T size=0; + int fmode=0,mtime=0,rmode=0; SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; @@ -1390,7 +1392,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1436,7 +1438,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt put_dos_date3(outbuf,smb_vwv4,mtime & ~1); else put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,size); + SIVAL(outbuf,smb_vwv6,(uint32)size); SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,smb_action); @@ -1767,7 +1769,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s int nread = 0; uint32 startpos; char *header = outbuf; - int ret=0; + SMB_OFF_T ret=0; int fd; char *fname; files_struct *fsp; @@ -1781,7 +1783,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if(global_oplock_break) { _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); + transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); DEBUG(5,("readbraw - oplock break finished\n")); return -1; } @@ -1799,7 +1801,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (!FNUM_OK(fsp,conn) || !fsp->can_read) { DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum)); _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); + transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); return(-1); } else { fd = fsp->fd_ptr->fd; @@ -1809,12 +1811,12 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) { - int size = fsp->size; + SMB_OFF_T size = fsp->size; int sizeneeded = startpos + maxcount; if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (fstat(fsp->fd_ptr->fd,&st) == 0) + if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -1843,7 +1845,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if ((nread-predict) > 0) seek_file(fsp,startpos + predict); - ret = transfer_file(fd,Client,nread-predict,header,4+predict, + ret = transfer_file(fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } @@ -2081,7 +2083,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s tcount,nwritten,numtowrite)); } - nwritten = transfer_file(Client,fsp->fd_ptr->fd,numtowrite,NULL,0, + nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0, startpos+nwritten); total_written += nwritten; @@ -2193,7 +2195,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) - nwritten = set_filelen(fsp->fd_ptr->fd, startpos); + nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos); else nwritten = write_file(fsp,data,numtowrite); @@ -2280,7 +2282,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { uint32 startpos; - int32 res= -1; + SMB_OFF_T res= -1; int mode,umode; int outsize = 0; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -2292,19 +2294,19 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, startpos = IVAL(inbuf,smb_vwv2); switch (mode & 3) - { + { case 0: umode = SEEK_SET; break; case 1: umode = SEEK_CUR; break; case 2: umode = SEEK_END; break; default: umode = SEEK_SET; break; - } + } - res = lseek(fsp->fd_ptr->fd,startpos,umode); + res = sys_lseek(fsp->fd_ptr->fd,(SMB_OFF_T)startpos,umode); fsp->pos = res; outsize = set_message(outbuf,2,0,True); - SIVALS(outbuf,smb_vwv0,res); + SIVALS(outbuf,smb_vwv0,(uint32)res); DEBUG(3,("lseek fnum=%d ofs=%d mode=%d\n", fsp->fnum, startpos, mode)); @@ -3330,7 +3332,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - lseek(fsp2->fd_ptr->fd,0,SEEK_END); + sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END); } if (st.st_size) @@ -3951,7 +3953,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si CHECK_ERROR(fsp); /* Do an fstat on this file */ - if(fstat(fsp->fd_ptr->fd, &sbuf)) + if(sys_fstat(fsp->fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(conn,fsp->fsp_name,&sbuf); @@ -3969,7 +3971,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si } else { - SIVAL(outbuf,smb_vwv6,sbuf.st_size); + SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024)); } SSVAL(outbuf,smb_vwv10, mode); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8871d568dd..dd1aa8f48b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -200,7 +200,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, pstring fname; int unixmode; - int size=0,fmode=0,mtime=0,rmode; + SMB_OFF_T size=0; + int fmode=0,mtime=0,rmode; SMB_INO_T inode = 0; SMB_STRUCT_STAT sbuf; int smb_action = 0; @@ -247,7 +248,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -270,7 +271,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, SSVAL(params,0,fsp->fnum); SSVAL(params,2,fmode); put_dos_date2(params,4, mtime); - SIVAL(params,8, size); + SIVAL(params,8, (uint32)size); SSVAL(params,12,rmode); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { @@ -311,7 +312,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, uint32 reskey=0; int prev_dirpos=0; int mode=0; - uint32 size=0,len; + SMB_OFF_T size = 0; + uint32 len; uint32 mdate=0, adate=0, cdate=0; char *nameptr; BOOL isrootdir = (strequal(conn->dirpath,"./") || @@ -329,78 +331,78 @@ static int get_lanman2_dir_entry(connection_struct *conn, p = strrchr(path_mask,'/'); if(p != NULL) - { - if(p[1] == '\0') - pstrcpy(mask,"*.*"); - else - pstrcpy(mask, p+1); - } + { + if(p[1] == '\0') + pstrcpy(mask,"*.*"); + else + pstrcpy(mask, p+1); + } else pstrcpy(mask, path_mask); while (!found) - { - /* Needed if we run out of space */ - prev_dirpos = TellDir(conn->dirptr); - dname = ReadDirName(conn->dirptr); + { + /* Needed if we run out of space */ + prev_dirpos = TellDir(conn->dirptr); + dname = ReadDirName(conn->dirptr); - /* - * Due to bugs in NT client redirectors we are not using - * resume keys any more - set them to zero. - * Check out the related comments in findfirst/findnext. - * JRA. - */ + /* + * Due to bugs in NT client redirectors we are not using + * resume keys any more - set them to zero. + * Check out the related comments in findfirst/findnext. + * JRA. + */ - reskey = 0; + reskey = 0; - DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", - (unsigned)conn->dirptr,TellDir(conn->dirptr))); + DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", + (unsigned)conn->dirptr,TellDir(conn->dirptr))); - if (!dname) - return(False); + if (!dname) + return(False); - matched = False; + matched = False; - pstrcpy(fname,dname); + pstrcpy(fname,dname); - if(mask_match(fname, mask, case_sensitive, True)) - { - BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); - if (dont_descend && !isdots) - continue; + if(mask_match(fname, mask, case_sensitive, True)) + { + BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); + if (dont_descend && !isdots) + continue; - if (isrootdir && isdots) - continue; - - pstrcpy(pathreal,conn->dirpath); - if(needslash) - pstrcat(pathreal,"/"); - pstrcat(pathreal,dname); - if (dos_stat(pathreal,&sbuf) != 0) - { - DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); - continue; - } - - mode = dos_mode(conn,pathreal,&sbuf); - - if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); - continue; - } - - size = sbuf.st_size; - mdate = sbuf.st_mtime; - adate = sbuf.st_atime; - cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - if(mode & aDIR) - size = 0; - - DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); + if (isrootdir && isdots) + continue; + + pstrcpy(pathreal,conn->dirpath); + if(needslash) + pstrcat(pathreal,"/"); + pstrcat(pathreal,dname); + if (dos_stat(pathreal,&sbuf) != 0) + { + DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); + continue; + } + + mode = dos_mode(conn,pathreal,&sbuf); + + if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) { + DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); + continue; + } + + size = sbuf.st_size; + mdate = sbuf.st_mtime; + adate = sbuf.st_atime; + cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + if(mode & aDIR) + size = 0; + + DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); - found = True; - } + found = True; } + } name_map_mangle(fname,False,SNUM(conn)); @@ -410,7 +412,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) - { + { case 1: if(requires_resume_key) { SIVAL(p,0,reskey); @@ -419,7 +421,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,l1_fdateCreation,cdate); put_dos_date2(p,l1_fdateLastAccess,adate); put_dos_date2(p,l1_fdateLastWrite,mdate); - SIVAL(p,l1_cbFile,size); + SIVAL(p,l1_cbFile,(uint32)size); SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024)); SSVAL(p,l1_attrFile,mode); SCVAL(p,l1_cchName,strlen(fname)); @@ -437,7 +439,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,l2_fdateCreation,cdate); put_dos_date2(p,l2_fdateLastAccess,adate); put_dos_date2(p,l2_fdateLastWrite,mdate); - SIVAL(p,l2_cbFile,size); + SIVAL(p,l2_cbFile,(uint32)size); SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024)); SSVAL(p,l2_attrFile,mode); SIVAL(p,l2_cbList,0); /* No extended attributes */ @@ -452,7 +454,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,4,cdate); put_dos_date2(p,8,adate); put_dos_date2(p,12,mdate); - SIVAL(p,16,size); + SIVAL(p,16,(uint32)size); SIVAL(p,20,ROUNDUP(size,1024)); SSVAL(p,24,mode); SIVAL(p,26,4); @@ -471,7 +473,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,4,cdate); put_dos_date2(p,8,adate); put_dos_date2(p,12,mdate); - SIVAL(p,16,size); + SIVAL(p,16,(uint32)size); SIVAL(p,20,ROUNDUP(size,1024)); SSVAL(p,24,mode); CVAL(p,32) = strlen(fname); @@ -1076,20 +1078,20 @@ static int call_trans2qfsinfo(connection_struct *conn, pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024); switch (info_level) - { + { case 1: - { - int dfree,dsize,bsize; - data_len = 18; - sys_disk_free(".",&bsize,&dfree,&dsize); - SIVAL(pdata,l1_idFileSystem,st.st_dev); - SIVAL(pdata,l1_cSectorUnit,bsize/512); - SIVAL(pdata,l1_cUnit,dsize); - SIVAL(pdata,l1_cUnitAvail,dfree); - SSVAL(pdata,l1_cbSector,512); - DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n", + { + int dfree,dsize,bsize; + data_len = 18; + sys_disk_free(".",&bsize,&dfree,&dsize); + SIVAL(pdata,l1_idFileSystem,st.st_dev); + SIVAL(pdata,l1_cSectorUnit,bsize/512); + SIVAL(pdata,l1_cUnit,dsize); + SIVAL(pdata,l1_cUnitAvail,dfree); + SSVAL(pdata,l1_cbSector,512); + DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n", bsize, (unsigned)st.st_dev, bsize/512, dsize, dfree, 512)); - break; + break; } case 2: { @@ -1136,16 +1138,16 @@ static int call_trans2qfsinfo(connection_struct *conn, vname)); break; case SMB_QUERY_FS_SIZE_INFO: - { - int dfree,dsize,bsize; - data_len = 24; - sys_disk_free(".",&bsize,&dfree,&dsize); - SIVAL(pdata,0,dsize); - SIVAL(pdata,8,dfree); - SIVAL(pdata,16,bsize/512); - SIVAL(pdata,20,512); - } + { + int dfree,dsize,bsize; + data_len = 24; + sys_disk_free(".",&bsize,&dfree,&dsize); + SIVAL(pdata,0,dsize); + SIVAL(pdata,8,dfree); + SIVAL(pdata,16,bsize/512); + SIVAL(pdata,20,512); break; + } case SMB_QUERY_FS_DEVICE_INFO: data_len = 8; SIVAL(pdata,0,0); /* dev type */ @@ -1153,7 +1155,7 @@ static int call_trans2qfsinfo(connection_struct *conn, break; default: return(ERROR(ERRDOS,ERRunknownlevel)); - } + } send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len); @@ -1201,13 +1203,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; int mode=0; - int size=0; + SMB_OFF_T size=0; unsigned int data_size; SMB_STRUCT_STAT sbuf; pstring fname1; char *fname; char *p; - int l,pos; + int l; + SMB_OFF_T pos; BOOL bad_path = False; if (tran_call == TRANSACT2_QFILEINFO) { @@ -1218,11 +1221,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = lseek(fsp->fd_ptr->fd,0,SEEK_CUR); + pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR); } else { /* qpathinfo */ info_level = SVAL(params,0); @@ -1278,7 +1281,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - SIVAL(pdata,l1_cbFile,size); + SIVAL(pdata,l1_cbFile,(uint32)size); SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); SSVAL(pdata,l1_attrFile,mode); SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ @@ -1289,7 +1292,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); - SIVAL(pdata,12,size); + SIVAL(pdata,12,(uint32)size); SIVAL(pdata,16,ROUNDUP(size,1024)); SIVAL(pdata,20,mode); break; @@ -1432,7 +1435,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; int mode=0; - int size=0; + SMB_OFF_T size=0; struct utimbuf tvs; SMB_STRUCT_STAT st; pstring fname1; @@ -1453,7 +1456,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; fd = fsp->fd_ptr->fd; - if(fstat(fd,&st)!=0) { + if(sys_fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); return(ERROR(ERRDOS,ERRbadpath)); } @@ -1581,7 +1584,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); +#ifdef LARGE_SMB_OFF_T + DEBUG(6,("size: %.0f ", (double)size)); +#else /* LARGE_SMB_OFF_T */ DEBUG(6,("size: %x " , size)); +#endif /* LARGE_SMB_OFF_T */ DEBUG(6,("mode: %x\n" , mode)); /* get some defaults (no modifications) if any info is zero. */ -- cgit From 623a18db4b0f46c80c29e93a0ad0a2fcbfec71dc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Sep 1998 00:23:28 +0000 Subject: More 64 bit stuff - now the fcntl locks are 64 bit clean. Nearly at the stage where I can expose the 64-bit-ness to the NT clients.... Jeremy. (This used to be commit 422f1dd45074c0e28203aca5952e57bbe56676b6) --- source3/smbd/connection.c | 18 +++++++++--------- source3/smbd/open.c | 4 ++++ 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index c3b6ba0199..0170fa5497 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -57,7 +57,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) return(False); } - if (fcntl_lock(fd,F_SETLKW,0,1,F_WRLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) { DEBUG(0,("ERROR: can't get lock on %s\n", fname)); return False; } @@ -66,7 +66,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) for (i=0;icnum) { - if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); } close(fd); @@ -91,14 +91,14 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) if (sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || write(fd, &crec,sizeof(crec)) != sizeof(crec)) { DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno))); - if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); } close(fd); return(False); } - if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); } @@ -149,7 +149,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO return(False); } - if (fcntl_lock(fd,F_SETLKW,0,1,F_WRLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) { DEBUG(0,("ERROR: can't get lock on %s\n", fname)); return False; } @@ -180,7 +180,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO if (foundi < 0) { DEBUG(3,("no free locks in %s\n",fname)); - if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); } close(fd); @@ -208,14 +208,14 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO /* make our mark */ if (sys_lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) || write(fd, &crec,sizeof(crec)) != sizeof(crec)) { - if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); } close(fd); return(False); } - if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) { + if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { DEBUG(0,("ERROR: can't release lock on %s\n", fname)); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 395de66a88..f24d4ac962 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -562,7 +562,11 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i BOOL *share_locked) { if (fsp->can_write){ +#ifdef LARGE_SMB_OFF_T + if (is_locked(fsp,conn,0x3FFFFFFFFFFFFFFFLL,0,F_WRLCK)){ +#else if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){ +#endif /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(conn))) -- cgit From 83900f2b682c62f2b5620b29ecb710274990ac51 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Sep 1998 20:53:58 +0000 Subject: Modified dev_t and ino_t code to be 64 bit clean (including changes to oplock break message passing). I think that smbd/nmbd are now inode and offset size independent (at least for 32 bit and 64 bit systems). Now to expose all this new functionality to NT clients..... Jeremy. (This used to be commit 5910d07bbf45a34d3c901461f74704c029a79474) --- source3/smbd/files.c | 8 +++- source3/smbd/open.c | 61 +++++++++++++++++++++---- source3/smbd/oplock.c | 123 +++++++++++++++++++++++++++++++++++++++++--------- source3/smbd/reply.c | 10 +++- 4 files changed, 170 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 341d9946ec..163e4f0cf2 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -128,9 +128,15 @@ file_fd_struct *fd_get_already_open(SMB_STRUCT_STAT *sbuf) (sbuf->st_dev == fd_ptr->dev) && (sbuf->st_ino == fd_ptr->inode)) { fd_ptr->ref_count++; +#ifdef LARGE_SMB_INO_T + DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %.0f, ref_count = %d\n", + (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, + fd_ptr->ref_count)); +#else /* LARGE_SMB_INO_T */ DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %x, ref_count = %d\n", - fd_ptr->dev, fd_ptr->inode, + (unsigned int)fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count)); +#endif /* LARGE_SMB_INO_T */ return fd_ptr; } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f24d4ac962..45d919187f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -149,10 +149,18 @@ int fd_attempt_close(file_fd_struct *fd_ptr) { extern struct current_user current_user; - DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", - fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, +#ifdef LARGE_SMB_INO_T + DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n", + fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, fd_ptr->real_open_flags, fd_ptr->ref_count)); +#else /* LARGE_SMB_INO_T */ + DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %lx, open_flags = %d, ref_count = %d.\n", + fd_ptr->fd, (unsigned int)fd_ptr->dev, (unsigned long)fd_ptr->inode, + fd_ptr->real_open_flags, + fd_ptr->ref_count)); +#endif /* LARGE_SMB_INO_T */ + if(fd_ptr->ref_count > 0) { fd_ptr->ref_count--; if(fd_ptr->ref_count == 0) { @@ -718,16 +726,28 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) { +#ifdef LARGE_SMB_INO_T + DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); +dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ /* Oplock break.... */ unlock_share_entry(conn, dev, inode, token); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); + +#ifdef LARGE_SMB_INO_T + DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); +dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -831,8 +851,13 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); global_oplocks_open++; port = oplock_port; +#ifdef LARGE_SMB_INO_T + DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); +dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (double)inode)); +#endif /* LARGE_SMB_INO_T */ } else @@ -1051,8 +1076,15 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) */ if(rename_op && (share_entry->pid == pid)) { + +#ifdef LARGE_SMB_INO_T + DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ +batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ -batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); +batch oplocked file %s, dev = %x, inode = %lx\n", fname, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + /* * This next line is a test that allows the deny-mode * processing to be skipped. This seems to be needed as @@ -1065,16 +1097,29 @@ batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); } else { + +#ifdef LARGE_SMB_INO_T DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); +dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ +dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ /* Oplock break.... */ unlock_share_entry(conn, dev, inode, token); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); + +#ifdef LARGE_SMB_INO_T DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); +dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + return False; } lock_share_entry(conn, dev, inode, &token); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ab88b82953..52a574663c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -105,19 +105,30 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); } { uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); /* - * Warning - this will need to be changed if SMB_DEV_T/SMB_INO_T <> 4 bytes. !! + * Warning - beware of SMB_INO_T <> 4 bytes. !! */ - SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); +#ifdef LARGE_SMB_INO_T + SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4); + SMB_INO_T inode = inode_low | (inode_high << 32); +#else /* LARGE_SMB_INO_T */ SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); +#endif /* LARGE_SMB_INO_T */ struct timeval tval; struct sockaddr_in toaddr; tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); +#ifdef LARGE_SMB_INO_T DEBUG(5,("process_local_message: oplock break request from \ -pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); +pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUG(5,("process_local_message: oplock break request from \ +pid %d, port %d, dev = %x, inode = %lx\n", remotepid, from_port, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ /* * If we have no record of any currently open oplocks, @@ -157,9 +168,15 @@ oplocks. Returning success.\n")); return False; } +#ifdef LARGE_SMB_INO_T + DEBUG(5,("process_local_message: oplock break reply sent to \ +pid %d, port %d, for file dev = %x, inode = %.0f\n", + remotepid, from_port, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, - from_port, dev, inode)); +pid %d, port %d, for file dev = %x, inode = %lx\n", + remotepid, from_port, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ } break; @@ -179,14 +196,25 @@ reply - dumping info.\n")); { uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); /* - * Warning - this will need to be changed if SMB_DEV_T/SMB_INO_T <> 4 bytes. !! + * Warning - beware of SMB_INO_T <> 4 bytes. !! */ - SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); +#ifdef LARGE_SMB_INO_T + SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4); + SMB_INO_T inode = inode_low | (inode_high << 32); +#else /* LARGE_SMB_INO_T */ SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); +#endif /* LARGE_SMB_INO_T */ +#ifdef LARGE_SMB_INO_T + DEBUG(0,("process_local_message: unsolicited oplock break reply from \ +pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); +pid %d, port %d, dev = %x, inode = %lx\n", remotepid, from_port, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ } return False; @@ -217,7 +245,11 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break: called for dev = %x, inode = %x.\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "oplock_break: called for dev = %x, inode = %.0f.\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "oplock_break: called for dev = %x, inode = %lx.\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); } @@ -232,7 +264,11 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 0 ) ) { dbgtext( "oplock_break: cannot find open file with " ); - dbgtext( "dev = %x, inode = %x ", dev, inode); +#ifdef LARGE_SMB_INO_T + dbgtext( "dev = %x, inode = %.0f ", (unsigned int)dev, (double)inode); +#else /* LARGE_SMB_INO_T */ + dbgtext( "dev = %x, inode = %x ", (unsigned int)dev, (unsigned long)inode); +#endif /* LARGE_SMB_INO_T */ dbgtext( "allowing break to succeed.\n" ); } return True; @@ -252,7 +288,11 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 0 ) ) { dbgtext( "oplock_break: file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %x) has no oplock.\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "(dev = %x, inode = %.0f) has no oplock.\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "(dev = %x, inode = %lx) has no oplock.\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ dbgtext( "Allowing break to succeed regardless.\n" ); } return True; @@ -265,7 +305,11 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); dbgtext( "file %s ", fsp->fsp_name); - dbgtext( "(dev = %x, inode = %x)\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "(dev = %x, inode = %.0f)\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "(dev = %x, inode = %lx)\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ } /* We have to fail the open here as we cannot send another oplock break on @@ -357,7 +401,12 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) OPLOCK_BREAK_TIMEOUT ) ); DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) ); - DEBUGADD( 0, ( "(dev = %x, inode = %x).\n", dev, inode)); +#ifdef LARGE_SMB_INO_T + DEBUGADD( 0, ( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ + DEBUGADD( 0, ( "(dev = %x, inode = %lx).\n", (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + shutdown_server = True; break; } @@ -384,7 +433,12 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) dbgtext( "oplock_break: no break received from client " ); dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %x).\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "(dev = %x, inode = %lx).\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ + } shutdown_server = True; break; @@ -451,7 +505,11 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 3 ) ) { dbgtext( "oplock_break: returning success for " ); - dbgtext( "dev = %x, inode = %x.\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); } @@ -495,11 +553,16 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); + SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); /* - * WARNING - this will need to be changed if SMB_DEV_T/SMB_INO_T <> 4 bytes. + * WARNING - beware of SMB_INO_T <> 4 bytes. */ - SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); +#ifdef LARGE_SMB_INO_T + SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,(inode & 0xFFFFFFFFL)); + SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET+4,((inode >> 32) & 0xFFFFFFFFL)); +#else /* LARGE_SMB_INO_T */ SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); +#endif /* LARGE_SMB_INO_T */ /* set the address and port */ bzero((char *)&addr_out,sizeof(addr_out)); @@ -511,7 +574,12 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); { dbgtext( "request_oplock_break: sending a oplock break message to " ); dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ + } if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, @@ -522,7 +590,11 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); dbgtext( "request_oplock_break: failed when sending a oplock " ); dbgtext( "break message to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ dbgtext( "Error was %s\n", strerror(errno) ); } return False; @@ -555,7 +627,12 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); dbgtext( "request_oplock_break: no response received to oplock " ); dbgtext( "break request to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ + } /* * This is a hack to make handling of failing clients more robust. @@ -572,7 +649,11 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); dbgtext( "request_oplock_break: error in response received " ); dbgtext( "to oplock break request to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %x.\n", dev, inode ); +#ifdef LARGE_SMB_INO_T + dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); +#else /* LARGE_SMB_INO_T */ + dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); +#endif /* LARGE_SMB_INO_T */ dbgtext( "Error was (%s).\n", strerror(errno) ); } return False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3665518ae6..d7ab997010 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3564,9 +3564,15 @@ no oplock granted on this file.\n", fsp->fnum)); /* Remove the oplock flag from the sharemode. */ lock_share_entry(fsp->conn, dev, inode, &token); if(remove_share_oplock(fsp, token)==False) { + +#ifdef LARGE_SMB_INO_T + DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ +dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); +#else /* LARGE_SMB_INO_T */ DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ -dev = %x, inode = %x\n", - fsp->fnum, dev, inode)); +dev = %x, inode = %lx\n", fsp->fnum, (unsigned int)dev, (unsigned long)inode)); +#endif /* LARGE_SMB_INO_T */ + unlock_share_entry(fsp->conn, dev, inode, token); } else { unlock_share_entry(fsp->conn, dev, inode, token); -- cgit From 98f524bde4801bd0b013a6bc79c5552ef62b59f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 5 Sep 1998 03:14:40 +0000 Subject: Bugfix for leak in reference counted file struct. Added "nt smb support" parameter to allow NT SMB's to be turned off. Jeremy. (This used to be commit 63f65f5027d5022153fa2757b49c56829db1725b) --- source3/smbd/close.c | 3 ++- source3/smbd/files.c | 6 +++--- source3/smbd/negprot.c | 3 ++- source3/smbd/open.c | 16 ++++++---------- 4 files changed, 13 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 42b16bc7ac..e9606cdfbe 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -117,7 +117,8 @@ void close_file(files_struct *fsp, BOOL normal_close) del_share_mode(token, fsp); } - fd_attempt_close(fsp->fd_ptr); + if(fd_attempt_close(fsp->fd_ptr) == 0) + fsp->fd_ptr = NULL; if (lp_share_modes(SNUM(conn))) unlock_share_entry(conn, dev, inode, token); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 163e4f0cf2..0b72bcf0fa 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -133,8 +133,8 @@ file_fd_struct *fd_get_already_open(SMB_STRUCT_STAT *sbuf) (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, fd_ptr->ref_count)); #else /* LARGE_SMB_INO_T */ - DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %x, ref_count = %d\n", - (unsigned int)fd_ptr->dev, fd_ptr->inode, + DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %lx, ref_count = %d\n", + (unsigned int)fd_ptr->dev, (unsigned long)fd_ptr->inode, fd_ptr->ref_count)); #endif /* LARGE_SMB_INO_T */ return fd_ptr; @@ -315,7 +315,7 @@ void file_sync_all(connection_struct *conn) /**************************************************************************** free up a fd_ptr ****************************************************************************/ -static void fd_ptr_free(file_fd_struct *fd_ptr) +void fd_ptr_free(file_fd_struct *fd_ptr) { DLIST_REMOVE(FileFd, fd_ptr); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 8e996cac21..b1e8a65c94 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -156,7 +156,8 @@ reply for the nt protocol static int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS |CAP_NT_SMBS; + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS | + lp_nt_smb_support() ? CAP_NT_SMBS : 0; /* other valid capabilities which we may support at some time... diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 45d919187f..a72469f2b2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -170,13 +170,10 @@ int fd_attempt_close(file_fd_struct *fd_ptr) close(fd_ptr->fd_readonly); if(fd_ptr->fd_writeonly != -1) close(fd_ptr->fd_writeonly); - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_ptr->dev = (SMB_DEV_T)-1; - fd_ptr->inode = (SMB_INO_T)-1; - fd_ptr->uid_cache_count = 0; + /* + * Delete this fd_ptr. + */ + fd_ptr_free(fd_ptr); } else { fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); } @@ -457,10 +454,9 @@ static void open_file(files_struct *fsp,connection_struct *conn, if (p) *p = 0; if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(conn))) { - fd_attempt_close(fd_ptr); - fsp->fd_ptr = 0; - if(fd_ptr->ref_count == 0) + if(fd_attempt_close(fd_ptr) == 0) dos_unlink(fname); + fsp->fd_ptr = 0; errno = ENOSPC; return; } -- cgit From 766aa4ff5c6007669010d8c284de20111e633b25 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 5 Sep 1998 03:38:50 +0000 Subject: Fixed one more Debug problem with inode in non-64 bit case. Jeremy. (This used to be commit 94d63cc382ac0d8a523db98b93750225082b09b1) --- source3/smbd/oplock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 52a574663c..6e675b56ef 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -267,7 +267,7 @@ BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) #ifdef LARGE_SMB_INO_T dbgtext( "dev = %x, inode = %.0f ", (unsigned int)dev, (double)inode); #else /* LARGE_SMB_INO_T */ - dbgtext( "dev = %x, inode = %x ", (unsigned int)dev, (unsigned long)inode); + dbgtext( "dev = %x, inode = %lx ", (unsigned int)dev, (unsigned long)inode); #endif /* LARGE_SMB_INO_T */ dbgtext( "allowing break to succeed.\n" ); } -- cgit From e9ea36e4d2270bd7d32da12ef6d6e2299641582d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 05:07:05 +0000 Subject: tridge the destroyer returns! prompted by the interpret_security() dead code that Jean-Francois pointed out I added a make target "finddead" that finds potentially dead (ie. unused) code. It spat out 304 function names ... I went through these are deleted many of them, making others static (finddead also reports functions that are used only in the local file). in doing this I have almost certainly deleted some useful code. I may have even prevented compilation with some compile options. I apologise. I decided it was better to get rid of this code now and add back the one or two functions that are needed than to keep all this baggage. So, if I have done a bit too much "destroying" then let me know. Keep the swearing to a minimum :) One bit I didn't do is the ubibt code. Chris, can you look at that? Heaps of unused functions there. Can they be made static? (This used to be commit 2204475c87f3024ea8fd1fbd7385b2def617a46f) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/filename.c | 10 +- source3/smbd/files.c | 5 +- source3/smbd/ipc.c | 2 +- source3/smbd/nttrans.c | 4 +- source3/smbd/open.c | 190 ++++++++++++++++--------------- source3/smbd/oplock.c | 4 +- source3/smbd/password.c | 4 +- source3/smbd/process.c | 286 +++++++++++++++++++++-------------------------- source3/smbd/server.c | 4 +- source3/smbd/trans2.c | 2 +- 11 files changed, 247 insertions(+), 266 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index c9478166c4..68cbe9b35b 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -292,7 +292,7 @@ static int talktochild(int master, char *chatsequence) } -BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root) +static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root) { char *slavedev; int master; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 656bb8997c..115ff699c7 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -28,12 +28,13 @@ extern BOOL short_case_preserve; extern fstring remote_machine; extern BOOL use_mangled_map; +static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); + /**************************************************************************** Check if two filenames are equal. This needs to be careful about whether we are case sensitive. ****************************************************************************/ - -BOOL fname_equal(char *name1, char *name2) +static BOOL fname_equal(char *name1, char *name2) { int l1 = strlen(name1); int l2 = strlen(name2); @@ -68,8 +69,7 @@ BOOL fname_equal(char *name1, char *name2) /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ - -BOOL mangled_equal(char *name1, char *name2) +static BOOL mangled_equal(char *name1, char *name2) { pstring tmpname; @@ -633,7 +633,7 @@ scan a directory to find a filename, matching without case sensitivity If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) +static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) { void *cur_dir; char *dname; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 0b72bcf0fa..0fe6a4ebd1 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -133,8 +133,9 @@ file_fd_struct *fd_get_already_open(SMB_STRUCT_STAT *sbuf) (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, fd_ptr->ref_count)); #else /* LARGE_SMB_INO_T */ - DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %lx, ref_count = %d\n", - (unsigned int)fd_ptr->dev, (unsigned long)fd_ptr->inode, + DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %x, ref_count = %d\n", + (unsigned int)fd_ptr->dev, + (unsigned int)fd_ptr->inode, fd_ptr->ref_count)); #endif /* LARGE_SMB_INO_T */ return fd_ptr; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 048afe35cd..8f7b1a9e15 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -725,7 +725,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, } /* This function returns the number of files for a given driver */ -int get_printerdrivernumber(int snum) +static int get_printerdrivernumber(int snum) { int i=0,ok=0; pstring tok; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3fdee043dc..0f50145d7f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -33,6 +33,8 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; +static void remove_pending_change_notify_requests_by_mid(int mid); + static char *known_nt_pipes[] = { "\\LANMAN", "\\srvsvc", @@ -1045,7 +1047,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp) Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_mid(int mid) +static void remove_pending_change_notify_requests_by_mid(int mid) { change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); change_notify_buf *prev = NULL; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a72469f2b2..e6289b1cdb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -589,6 +589,102 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i } +enum {AFAIL,AREAD,AWRITE,AALL}; + +/******************************************************************* +reproduce the share mode access table +********************************************************************/ +static int access_table(int new_deny,int old_deny,int old_mode, + int share_pid,char *fname) +{ + if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); + + if (new_deny == DENY_DOS || old_deny == DENY_DOS) { + int pid = getpid(); + if (old_deny == new_deny && share_pid == pid) + return(AALL); + + if (old_mode == 0) return(AREAD); + + /* the new smbpub.zip spec says that if the file extension is + .com, .dll, .exe or .sym then allow the open. I will force + it to read-only as this seems sensible although the spec is + a little unclear on this. */ + if ((fname = strrchr(fname,'.'))) { + if (strequal(fname,".com") || + strequal(fname,".dll") || + strequal(fname,".exe") || + strequal(fname,".sym")) + return(AREAD); + } + + return(AFAIL); + } + + switch (new_deny) + { + case DENY_WRITE: + if (old_deny==DENY_WRITE && old_mode==0) return(AREAD); + if (old_deny==DENY_READ && old_mode==0) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==0) return(AALL); + return(AFAIL); + case DENY_READ: + if (old_deny==DENY_WRITE && old_mode==1) return(AREAD); + if (old_deny==DENY_READ && old_mode==1) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==1) return(AALL); + return(AFAIL); + case DENY_NONE: + if (old_deny==DENY_WRITE) return(AREAD); + if (old_deny==DENY_READ) return(AWRITE); + if (old_deny==DENY_NONE) return(AALL); + return(AFAIL); + } + return(AFAIL); +} + + +/**************************************************************************** +check if we can open a file with a share mode +****************************************************************************/ +static int check_share_mode( share_mode_entry *share, int deny_mode, + char *fname, + BOOL fcbopen, int *flags) +{ + int old_open_mode = share->share_mode &0xF; + int old_deny_mode = (share->share_mode >>4)&7; + + if (old_deny_mode > 4 || old_open_mode > 2) + { + DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", + deny_mode,old_deny_mode,old_open_mode,fname)); + return False; + } + + { + int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, + share->pid,fname); + + if ((access_allowed == AFAIL) || + (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || + (access_allowed == AREAD && *flags == O_WRONLY) || + (access_allowed == AWRITE && *flags == O_RDONLY)) + { + DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", + deny_mode,old_deny_mode,old_open_mode, + share->pid,fname, fcbopen, *flags, access_allowed)); + return False; + } + + if (access_allowed == AREAD) + *flags = O_RDONLY; + + if (access_allowed == AWRITE) + *flags = O_WRONLY; + + } + return True; +} + /**************************************************************************** open a file with a share mode @@ -852,7 +948,7 @@ dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsi dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); #else /* LARGE_SMB_INO_T */ DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (double)inode)); +dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (unsigned long)inode)); #endif /* LARGE_SMB_INO_T */ } @@ -953,58 +1049,6 @@ int open_directory(files_struct *fsp,connection_struct *conn, return 0; } -enum {AFAIL,AREAD,AWRITE,AALL}; - -/******************************************************************* -reproduce the share mode access table -********************************************************************/ -static int access_table(int new_deny,int old_deny,int old_mode, - int share_pid,char *fname) -{ - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - int pid = getpid(); - if (old_deny == new_deny && share_pid == pid) - return(AALL); - - if (old_mode == 0) return(AREAD); - - /* the new smbpub.zip spec says that if the file extension is - .com, .dll, .exe or .sym then allow the open. I will force - it to read-only as this seems sensible although the spec is - a little unclear on this. */ - if ((fname = strrchr(fname,'.'))) { - if (strequal(fname,".com") || - strequal(fname,".dll") || - strequal(fname,".exe") || - strequal(fname,".sym")) - return(AREAD); - } - - return(AFAIL); - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==0) return(AREAD); - if (old_deny==DENY_READ && old_mode==0) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==0) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==1) return(AREAD); - if (old_deny==DENY_READ && old_mode==1) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==1) return(AALL); - return(AFAIL); - case DENY_NONE: - if (old_deny==DENY_WRITE) return(AREAD); - if (old_deny==DENY_READ) return(AWRITE); - if (old_deny==DENY_NONE) return(AALL); - return(AFAIL); - } - return(AFAIL); -} /******************************************************************* check if the share mode on a file allows it to be deleted or unlinked @@ -1153,44 +1197,4 @@ free_and_exit: return(ret); } -/**************************************************************************** -check if we can open a file with a share mode -****************************************************************************/ -int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, - BOOL fcbopen, int *flags) -{ - int old_open_mode = share->share_mode &0xF; - int old_deny_mode = (share->share_mode >>4)&7; - - if (old_deny_mode > 4 || old_open_mode > 2) - { - DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", - deny_mode,old_deny_mode,old_open_mode,fname)); - return False; - } - - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); - - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags == O_WRONLY) || - (access_allowed == AWRITE && *flags == O_RDONLY)) - { - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", - deny_mode,old_deny_mode,old_open_mode, - share->pid,fname, fcbopen, *flags, access_allowed)); - return False; - } - - if (access_allowed == AREAD) - *flags = O_RDONLY; - - if (access_allowed == AWRITE) - *flags = O_WRONLY; - - } - return True; -} diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 6e675b56ef..dd882d08cc 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -34,6 +34,8 @@ BOOL global_oplock_break = False; extern int smb_read_error; +static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval); + /**************************************************************************** open the oplock IPC socket communication @@ -230,7 +232,7 @@ pid %d, port %d, dev = %x, inode = %lx\n", remotepid, from_port, (unsigned int)d /**************************************************************************** Process an oplock break directly. ****************************************************************************/ -BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) +static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { extern struct current_user current_user; extern int Client; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index dadbcad11e..684420f4c3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -84,7 +84,7 @@ BOOL set_challenge(char *challenge) /******************************************************************* get the last challenge sent ********************************************************************/ -BOOL last_challenge(unsigned char *challenge) +static BOOL last_challenge(unsigned char *challenge) { if (!challenge_sent) return(False); memcpy(challenge,saved_challenge,8); @@ -299,7 +299,7 @@ void add_session_user(char *user) /**************************************************************************** update the encrypted smbpasswd file from the plaintext username and password *****************************************************************************/ -BOOL update_smbpassword_file(char *user, char *password) +static BOOL update_smbpassword_file(char *user, char *password) { struct smb_passwd *smbpw; BOOL ret; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 63e51dc242..b72178013d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -89,86 +89,6 @@ BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int tim } - -/**************************************************************************** - process an smb from the client - split out from the process() code so - it can be used by the oplock break code. -****************************************************************************/ -void process_smb(char *inbuf, char *outbuf) -{ - extern int Client; -#ifdef WITH_SSL - extern BOOL sslEnabled; /* don't use function for performance reasons */ - static int sslConnected = 0; -#endif /* WITH_SSL */ - static int trans_num; - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; - - if (trans_num == 0) { - /* on the first packet, check the global hosts allow/ hosts - deny parameters before doing any parsing of the packet - passed to us by the client. This prevents attacks on our - parsing code from hosts not in the hosts allow list */ - if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) { - /* send a negative session response "not listining on calling - name" */ - static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG( 1, ( "Connection denied from %s\n", - client_addr(Client) ) ); - send_smb(Client,(char *)buf); - exit_server("connection denied"); - } - } - - DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); - DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); - -#ifdef WITH_SSL - if(sslEnabled && !sslConnected){ - sslConnected = sslutil_negotiate_ssl(Client, msg_type); - if(sslConnected < 0){ /* an error occured */ - exit_server("SSL negotiation failed"); - }else if(sslConnected){ - trans_num++; - return; - } - } -#endif /* WITH_SSL */ - -#ifdef WITH_VTP - if(trans_num == 1 && VT_Check(inbuf)) - { - VT_Process(); - return; - } -#endif - - if (msg_type == 0) - show_msg(inbuf); - else if(msg_type == 0x85) - return; /* Keepalive packet. */ - - nread = construct_reply(inbuf,outbuf,nread,max_send); - - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); - - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - send_smb(Client,outbuf); - } - trans_num++; -} - - /* These flags determine some of the permissions required to do an operation @@ -194,9 +114,6 @@ struct smb_message_struct char *name; int (*fn)(connection_struct *conn, char *, char *, int, int); int flags; -#if PROFILING - unsigned long time; -#endif } smb_messages[] = { @@ -302,26 +219,6 @@ struct smb_message_struct {SMBgetmac,"SMBgetmac",NULL,AS_GUEST} }; -/**************************************************************************** -return a string containing the function name of a SMB command -****************************************************************************/ -char *smb_fn_name(int type) -{ - static char *unknown_name = "SMBunknown"; - static int num_smb_messages = - sizeof(smb_messages) / sizeof(struct smb_message_struct); - int match; - - for (match=0;match 4) + smb_setlen(outbuf,outsize - 4); + return(outsize); +} + + +/**************************************************************************** + process an smb from the client - split out from the process() code so + it can be used by the oplock break code. +****************************************************************************/ +void process_smb(char *inbuf, char *outbuf) +{ + extern int Client; +#ifdef WITH_SSL + extern BOOL sslEnabled; /* don't use function for performance reasons */ + static int sslConnected = 0; +#endif /* WITH_SSL */ + static int trans_num; + int msg_type = CVAL(inbuf,0); + int32 len = smb_len(inbuf); + int nread = len + 4; + + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) { + /* send a negative session response "not listining on calling + name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG( 1, ( "Connection denied from %s\n", + client_addr(Client) ) ); + send_smb(Client,(char *)buf); + exit_server("connection denied"); + } } + + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); + +#ifdef WITH_SSL + if(sslEnabled && !sslConnected){ + sslConnected = sslutil_negotiate_ssl(Client, msg_type); + if(sslConnected < 0){ /* an error occured */ + exit_server("SSL negotiation failed"); + }else if(sslConnected){ + trans_num++; + return; + } + } +#endif /* WITH_SSL */ + +#ifdef WITH_VTP + if(trans_num == 1 && VT_Check(inbuf)) { - unsigned long this_time = - (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 + - (msg_end_time.tv_usec - msg_start_time.tv_usec); - smb_messages[match].time += this_time; - total_time += this_time; + VT_Process(); + return; } - DEBUG(2,("TIME %s %d usecs %g pct\n", - smb_fn_name(type),smb_messages[match].time, - (100.0*smb_messages[match].time) / total_time)); #endif - return(outsize); + if (msg_type == 0) + show_msg(inbuf); + else if(msg_type == 0x85) + return; /* Keepalive packet. */ + + nread = construct_reply(inbuf,outbuf,nread,max_send); + + if(nread > 0) + { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); + + if (nread != smb_len(outbuf) + 4) + { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(outbuf))); + } + else + send_smb(Client,outbuf); + } + trans_num++; +} + + + +/**************************************************************************** +return a string containing the function name of a SMB command +****************************************************************************/ +char *smb_fn_name(int type) +{ + static char *unknown_name = "SMBunknown"; + static int num_smb_messages = + sizeof(smb_messages) / sizeof(struct smb_message_struct); + int match; + + for (match=0;match 4) - smb_setlen(outbuf,outsize - 4); - return(outsize); -} - /**************************************************************************** process commands from the client ****************************************************************************/ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index dadf2018c8..5af62fd4a7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -52,7 +52,7 @@ extern pstring myhostname; /**************************************************************************** when exiting, take the whole family ****************************************************************************/ -void *dflt_sig(void) +static void *dflt_sig(void) { exit_server("caught signal"); return NULL; @@ -61,7 +61,7 @@ void *dflt_sig(void) /**************************************************************************** Send a SIGTERM to our process group. *****************************************************************************/ -void killkids(void) +static void killkids(void) { if(am_parent) kill(0,SIGTERM); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dd1aa8f48b..f0ed77bd97 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1587,7 +1587,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, #ifdef LARGE_SMB_OFF_T DEBUG(6,("size: %.0f ", (double)size)); #else /* LARGE_SMB_OFF_T */ - DEBUG(6,("size: %x " , size)); + DEBUG(6,("size: %x " , (int)size)); #endif /* LARGE_SMB_OFF_T */ DEBUG(6,("mode: %x\n" , mode)); -- cgit From 012e575e1336fbba70174d32c26ecab9ce5523ce Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 05:23:29 +0000 Subject: ahh, the joy of deleting large chunks of code that someone else has painstakingly put in :) This gets rid of most of the #ifdef LARGE_SMB_INO_T ifdefs around DEBUG() statements. We just use %.0f in all cases. Makes the code a bit easier to read :) (This used to be commit 41f0069afc02169932e04ff0039bb6328eaaf04d) --- source3/smbd/trans2.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f0ed77bd97..709b8daecd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1584,11 +1584,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); -#ifdef LARGE_SMB_OFF_T DEBUG(6,("size: %.0f ", (double)size)); -#else /* LARGE_SMB_OFF_T */ - DEBUG(6,("size: %x " , (int)size)); -#endif /* LARGE_SMB_OFF_T */ DEBUG(6,("mode: %x\n" , mode)); /* get some defaults (no modifications) if any info is zero. */ -- cgit From f6044c87c021342d68d614d59bc8dacd32d223b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 13:24:20 +0000 Subject: some cleanups to use ZERO_STRUCT() and friends (This used to be commit 7b154dc4313324dfad6cf0117b8ce246bf12bf16) --- source3/smbd/conn.c | 4 ++-- source3/smbd/filename.c | 5 +++-- source3/smbd/files.c | 8 ++++---- source3/smbd/password.c | 3 ++- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 2afbfb7d7e..5dc904bd91 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -108,7 +108,7 @@ connection_struct *conn_new(void) conn = (connection_struct *)malloc(sizeof(*conn)); if (!conn) return NULL; - memset(conn, 0, sizeof(*conn)); + ZERO_STRUCTP(conn); conn->cnum = i; bitmap_set(bmap, i); @@ -184,6 +184,6 @@ void conn_free(connection_struct *conn) bitmap_clear(bmap, conn->cnum); num_open--; - memset(conn, 0, sizeof(*conn)); + ZERO_STRUCTP(conn); free(conn); } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 115ff699c7..8b81d6df2a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -334,8 +334,9 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *dirpath = 0; *bad_path = False; - if(pst) - memset( (char *)pst, '\0', sizeof(SMB_STRUCT_STAT)); + if(pst) { + ZERO_STRUCTP(pst); + } if(saved_last_component) *saved_last_component = 0; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 0fe6a4ebd1..ed14b86e5f 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -91,7 +91,7 @@ files_struct *file_new(void ) fsp = (files_struct *)malloc(sizeof(*fsp)); if (!fsp) return NULL; - memset(fsp, 0, sizeof(*fsp)); + ZERO_STRUCTP(fsp); first_file = (i+1) % MAX_FNUMS; @@ -166,7 +166,7 @@ file_fd_struct *fd_get_new(void) fd_ptr = (file_fd_struct *)malloc(sizeof(*fd_ptr)); if (!fd_ptr) return NULL; - memset(fd_ptr, 0, sizeof(*fd_ptr)); + ZERO_STRUCTP(fd_ptr); fd_ptr->fdnum = i; fd_ptr->dev = (SMB_DEV_T)-1; @@ -327,7 +327,7 @@ void fd_ptr_free(file_fd_struct *fd_ptr) fd_ptr->fdnum, fd_ptr_used)); /* paranoia */ - memset(fd_ptr, 0, sizeof(*fd_ptr)); + ZERO_STRUCTP(fd_ptr); free(fd_ptr); } @@ -354,7 +354,7 @@ void file_free(files_struct *fsp) /* this is paranoia, just in case someone tries to reuse the information */ - memset(fsp, 0, sizeof(*fsp)); + ZERO_STRUCTP(fsp); if (fsp == chain_fsp) chain_fsp = NULL; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 684420f4c3..1d90af3066 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1202,7 +1202,8 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); * see if they were valid. */ - memset(&cli, '\0', sizeof(struct cli_state)); + ZERO_STRUCT(cli); + if(cli_initialise(&cli) == False) { DEBUG(0,("domain_client_validate: unable to initialize client connection.\n")); return False; -- cgit From fd33412fa0ebd7de6c8749caeb111bdf4390dd47 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 15:31:10 +0000 Subject: fixed a stat cache bug (the one found by Matthew Geier). The fix I used is a very conservative fix. I'll leave it up to Jeremy to put in a better fix. The problem was the detection of mangled names. (This used to be commit c96b5fde5ae12bd0d4d6bcff095cf090738c92a4) --- source3/smbd/filename.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8b81d6df2a..ee9ce3f835 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -331,6 +331,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, int saved_errno; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; + extern char magic_char; *dirpath = 0; *bad_path = False; @@ -432,6 +433,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(strchr(start,'?') || strchr(start,'*')) name_has_wildcard = True; + /* this is an extremely conservative test for mangled names. */ + if (strchr(start,magic_char)) + component_was_mangled = True; + /* * Now we need to recursively match the name against the real * directory structure. @@ -528,7 +533,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, */ if (is_mangled(start)) { - component_was_mangled = True; check_mangled_cache( start ); } -- cgit From 4fc5a74ffa491d52afc373abcdd4257a4f105aa4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 6 Sep 1998 01:37:14 +0000 Subject: add a "stat cache" boolean smb.conf option. (defaults to on) I think we need this so we can rule out stat cache bugs when dealing with bug reports. If we ask a user to disable the stat cache and the problem persists then we know it isn't a stat cache bug. The stat cache code is sufficiently complicated that it can be pretty hard to tell if it is causing problems or not. (This used to be commit c83f3775cd8a7aad13571926cdd5949a07538771) --- source3/smbd/filename.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ee9ce3f835..a88829de9d 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,7 +150,11 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) stat_cache_entry *scp; pstring orig_name; pstring translated_path; - int namelen = strlen(orig_translated_path); + int namelen; + + if (!lp_stat_cache()) return; + + namelen = strlen(orig_translated_path); /* * Don't cache trivial valid directory entries. @@ -235,8 +239,12 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; - int namelen = strlen(name); + int namelen; + + if (!lp_stat_cache()) return False; + namelen = strlen(name); + *start = name; global_stat_cache_lookups++; -- cgit From 519a6d5f0ed0d81cf739394c1c8c305f8ae43c87 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 7 Sep 1998 17:01:52 +0000 Subject: added 0x10 to the frag length in the "bind ack". (This used to be commit 46301b1d2161317f56049934a9e7b658447b2c76) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8f7b1a9e15..61d9aa8bdd 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3205,7 +3205,7 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, p->hdr.call_id, - p->rdata.offset + p->rauth.offset, + p->rdata.offset + p->rauth.offset + 0x10, p->rauth.offset); smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0); -- cgit From 6e0c276ec8b918165a19b3dfc86bc7bef6d1f706 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Sep 1998 19:21:04 +0000 Subject: Added back groupname map stuff removed by Andrew's "slash 'n' burn" tactics :-). Protected by #ifdef until used. Fixed bug in fd_attempt_close() where a pointer to potentially free'd memory was returned. I hate that. Added "blocking locks" as a per-share option for performance testing. Changed is_mangled() so it will return true if called with a pathname and any component of the pathname was mangled (it was already attempting to do this, but not checking for a '/' as end-of-mangle). This should be a better fix for the wierd stat cache bug Andrew identified. Jeremy. (This used to be commit 0de01f45980c7bc261248a9cead972a8d8cbd594) --- source3/smbd/filename.c | 14 ++++++++++++++ source3/smbd/groupname.c | 5 +++++ source3/smbd/mangle.c | 7 ++++--- source3/smbd/open.c | 49 +++++++++++++++++++++++------------------------- source3/smbd/reply.c | 6 +++--- 5 files changed, 49 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a88829de9d..0910e03ee3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -339,7 +339,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, int saved_errno; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; +#if 0 + /* Andrew's conservative code... JRA. */ extern char magic_char; +#endif *dirpath = 0; *bad_path = False; @@ -441,9 +444,20 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(strchr(start,'?') || strchr(start,'*')) name_has_wildcard = True; + /* + * is_mangled() was changed to look at an entire pathname, not + * just a component. JRA. + */ + + if(is_mangled(start)) + component_was_mangled = True; + +#if 0 + /* Keep Andrew's conservative code around, just in case. JRA. */ /* this is an extremely conservative test for mangled names. */ if (strchr(start,magic_char)) component_was_mangled = True; +#endif /* * Now we need to recursively match the name against the real diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 75af12a47a..29236e2ca5 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -19,6 +19,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef USING_GROUPNAME_MAP + #include "includes.h" extern int DEBUGLEVEL; extern DOM_SID global_machine_sid; @@ -236,3 +238,6 @@ void map_gid_to_sid( gid_t gid, DOM_SID *psid) return; } +#else /* USING_GROUPNAME_MAP */ + void load_groupname_map(void) {;} +#endif /* USING_GROUPNAME_MAP */ diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 0a3d3f54eb..f0d5a9d85c 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -272,7 +272,7 @@ static BOOL is_illegal_name( char *name ) /* ************************************************************************** ** * Return True if the name *could be* a mangled name. * - * Input: s - A file name. + * Input: s - A path name - in UNIX pathname format. * * Output: True if the name matches the pattern described below in the * notes, else False. @@ -281,7 +281,8 @@ static BOOL is_illegal_name( char *name ) * done separately. This function returns true if the name contains * a magic character followed by excactly two characters from the * basechars list (above), which in turn are followed either by the - * nul (end of string) byte or a dot (extension). + * nul (end of string) byte or a dot (extension) or by a '/' (end of + * a directory name). * * ************************************************************************** ** */ @@ -295,7 +296,7 @@ BOOL is_mangled( char *s ) magic = strchr( s, magic_char ); while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ { - if( ('.' == magic[3] || !(magic[3])) /* Ends with '.' or nul? */ + if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ return( True ); /* If all above, then true, */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6289b1cdb..bd1ead6921 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -145,40 +145,37 @@ static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ -int fd_attempt_close(file_fd_struct *fd_ptr) +uint16 fd_attempt_close(file_fd_struct *fd_ptr) { extern struct current_user current_user; + uint16 ret_ref = fd_ptr->ref_count; -#ifdef LARGE_SMB_INO_T DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n", fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, fd_ptr->real_open_flags, fd_ptr->ref_count)); -#else /* LARGE_SMB_INO_T */ - DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %lx, open_flags = %d, ref_count = %d.\n", - fd_ptr->fd, (unsigned int)fd_ptr->dev, (unsigned long)fd_ptr->inode, - fd_ptr->real_open_flags, - fd_ptr->ref_count)); -#endif /* LARGE_SMB_INO_T */ - if(fd_ptr->ref_count > 0) { - fd_ptr->ref_count--; - if(fd_ptr->ref_count == 0) { - if(fd_ptr->fd != -1) - close(fd_ptr->fd); - if(fd_ptr->fd_readonly != -1) - close(fd_ptr->fd_readonly); - if(fd_ptr->fd_writeonly != -1) - close(fd_ptr->fd_writeonly); - /* - * Delete this fd_ptr. - */ - fd_ptr_free(fd_ptr); - } else { - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - } - } - return fd_ptr->ref_count; + SMB_ASSERT(fd_ptr->ref_count != 0); + + fd_ptr->ref_count--; + ret_ref = fd_ptr->ref_count; + + if(fd_ptr->ref_count == 0) { + if(fd_ptr->fd != -1) + close(fd_ptr->fd); + if(fd_ptr->fd_readonly != -1) + close(fd_ptr->fd_readonly); + if(fd_ptr->fd_writeonly != -1) + close(fd_ptr->fd_writeonly); + /* + * Delete this fd_ptr. + */ + fd_ptr_free(fd_ptr); + } else { + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + } + + return ret_ref; } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d7ab997010..3d537d8868 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1891,7 +1891,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length data = smb_buf(outbuf) + 3; if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) { - if(ecode == ERRlock) { + if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -2485,7 +2485,7 @@ int reply_lock(connection_struct *conn, fsp->fd_ptr->fd, fsp->fnum, offset, count)); if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { - if(ecode == ERRlock) { + if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -3618,7 +3618,7 @@ dev = %x, inode = %lx\n", fsp->fnum, (unsigned int)dev, (unsigned long)inode)); (int)offset, (int)count, fsp->fsp_name )); if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) { - if((ecode == ERRlock) && (lock_timeout != 0)) { + if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it -- cgit From 5de3c136808d891ca25009beefc194dc825a5a16 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Wed, 9 Sep 1998 16:37:54 +0000 Subject: Copyright notices written to debug logs are now through 1998. Chris -)----- (This used to be commit ac13c29d46f564fc340b652b4b71dfa92e4b5b16) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5af62fd4a7..44d53c70cf 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -608,7 +608,7 @@ static void usage(char *pname) reopen_logs(); DEBUG(1,( "smbd version %s started.\n", VERSION)); - DEBUGADD(1,( "Copyright Andrew Tridgell 1992-1997\n")); + DEBUGADD(1,( "Copyright Andrew Tridgell 1992-1998\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); -- cgit From aab0323d294770f80c6514389e5f84d3abf82429 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Sep 1998 00:35:10 +0000 Subject: Improved stat cache code by uppercasing any search name that gets added to it if we're in case insensitive mode, and then doing a memcmp rather than a StrnCaseCmp (which is *horribly* slow) on every lookup. Fixed bug with refusing NT SMB's (use *brackets* where needed :-). Jeremy. (This used to be commit 02b3fddce33a58a4db2102670b502fc0c6f45fab) --- source3/smbd/filename.c | 32 +++++++++++++++----------------- source3/smbd/negprot.c | 4 ++-- 2 files changed, 17 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 0910e03ee3..caba4064d7 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -114,27 +114,18 @@ typedef struct { static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; -/**************************************************************************** - Compare two names in the stat cache - to check if we already have such an - entry. -*****************************************************************************/ - -static BOOL stat_name_equal( char *s1, char *s2) -{ - return (case_sensitive ? (strcmp( s1, s2) == 0) : (StrCaseCmp(s1, s2) == 0)); -} - /**************************************************************************** Compare a pathname to a name in the stat cache - of a given length. Note - this code always checks that the next character in the pathname is either a '/' character, or a '\0' character - to ensure we only - match *full* pathname components. + match *full* pathname components. Note we don't need to handle case + here, if we're case insensitive the stat cache orig names are all upper + case. *****************************************************************************/ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) { - BOOL matched = (case_sensitive ? (strncmp( stat_name, orig_name, len) == 0) : - (StrnCaseCmp(stat_name, orig_name, len) == 0)); + BOOL matched = (memcmp( stat_name, orig_name, len) == 0); if(orig_name[len] != '/' && orig_name[len] != '\0') return False; @@ -159,7 +150,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) /* * Don't cache trivial valid directory entries. */ - if(strequal(full_orig_name, ".") || strequal(full_orig_name, "..")) + if((strcmp(full_orig_name, ".") == 0) || (strcmp(full_orig_name, "..") == 0)) return; /* @@ -189,6 +180,8 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) */ StrnCpy(orig_name, full_orig_name, namelen); + if(!case_sensitive) + strupper( orig_name ); /* * Check this name doesn't exist in the cache before we @@ -197,7 +190,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; scp = (stat_cache_entry *)ubi_dlNext( scp )) { - if(stat_name_equal( scp->orig_name, orig_name) && + if((strcmp( scp->orig_name, orig_name) == 0) && (strcmp( scp->translated_name, translated_path) == 0)) { /* * Name does exist - promote it. @@ -239,6 +232,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; + pstring chk_name; int namelen; if (!lp_stat_cache()) return False; @@ -251,15 +245,19 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU /* * Don't lookup trivial valid directory entries. */ - if(strequal(name, ".") || strequal(name, "..")) { + if((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { global_stat_cache_misses++; return False; } + pstrcpy(chk_name, name); + if(!case_sensitive) + strupper( chk_name ); + for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; scp = (stat_cache_entry *)ubi_dlNext( scp )) { if(scp->name_len <= namelen) { - if(stat_name_equal_len(scp->orig_name, name, scp->name_len)) { + if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) { if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len)) longest_hit = scp; } diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b1e8a65c94..6a9cc9fb9b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -156,8 +156,8 @@ reply for the nt protocol static int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS | - lp_nt_smb_support() ? CAP_NT_SMBS : 0; + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| + (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0); /* other valid capabilities which we may support at some time... -- cgit From ede44ebdf089a835ea1f3141dd00b50b7bbc54e1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Sep 1998 18:57:06 +0000 Subject: smb.h: Removed fdnum from file_fd_struct. Not needed. files.c: Removed fd bitmap - not needed. Added code to do use arrays rather than linked list - disabled by default but can be enabled to check performance. Jeremy. (This used to be commit 069efc04545d5fdfc5c40467b8b7554ed5226a2e) --- source3/smbd/files.c | 138 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index ed14b86e5f..c1bb3df57c 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -31,10 +31,13 @@ extern int DEBUGLEVEL; #define FILE_HANDLE_OFFSET 0x1000 static struct bitmap *file_bmap; -static struct bitmap *fd_bmap; +#ifdef USE_FILES_ARRAY +static files_struct *Files[MAX_FNUMS]; +#else static files_struct *Files; - +#endif + /* a fsp to use when chaining */ static files_struct *chain_fsp = NULL; /* a fsp to use to save when breaking an oplock. */ @@ -77,12 +80,21 @@ files_struct *file_new(void ) * files batch oplocked for quite a long time * after they have finished with them. */ +#ifdef USE_FILES_ARRAY + for(i = 0; i < MAX_FNUMS; i++) { + if((fsp = Files[i]) == NULL) + continue; + if (attempt_close_oplocked_file(fsp)) + return file_new(); + } +#else for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (attempt_close_oplocked_file(fsp)) { return file_new(); } } +#endif DEBUG(0,("ERROR! Out of file structures\n")); return NULL; @@ -101,10 +113,14 @@ files_struct *file_new(void ) fsp->fnum = i + FILE_HANDLE_OFFSET; string_init(&fsp->fsp_name,""); +#ifdef USE_FILES_ARRAY + Files[i] = fsp; +#else DLIST_ADD(Files, fsp); +#endif - DEBUG(5,("allocated file structure %d (%d used)\n", - i, files_used)); + DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", + i, fsp->fnum, files_used)); chain_fsp = fsp; @@ -128,16 +144,11 @@ file_fd_struct *fd_get_already_open(SMB_STRUCT_STAT *sbuf) (sbuf->st_dev == fd_ptr->dev) && (sbuf->st_ino == fd_ptr->inode)) { fd_ptr->ref_count++; -#ifdef LARGE_SMB_INO_T + DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %.0f, ref_count = %d\n", (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, fd_ptr->ref_count)); -#else /* LARGE_SMB_INO_T */ - DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %x, ref_count = %d\n", - (unsigned int)fd_ptr->dev, - (unsigned int)fd_ptr->inode, - fd_ptr->ref_count)); -#endif /* LARGE_SMB_INO_T */ + return fd_ptr; } } @@ -154,21 +165,16 @@ Increments the ref_count of the returned entry. file_fd_struct *fd_get_new(void) { extern struct current_user current_user; - int i; file_fd_struct *fd_ptr; - i = bitmap_find(fd_bmap, 1); - if (i == -1) { - DEBUG(0,("ERROR! Out of file_fd structures\n")); - return NULL; - } - fd_ptr = (file_fd_struct *)malloc(sizeof(*fd_ptr)); - if (!fd_ptr) return NULL; + if (!fd_ptr) { + DEBUG(0,("ERROR! malloc fail for file_fd struct.\n")); + return NULL; + } ZERO_STRUCTP(fd_ptr); - fd_ptr->fdnum = i; fd_ptr->dev = (SMB_DEV_T)-1; fd_ptr->inode = (SMB_INO_T)-1; fd_ptr->fd = -1; @@ -178,13 +184,11 @@ file_fd_struct *fd_get_new(void) fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); fd_ptr->ref_count++; - bitmap_set(fd_bmap, i); fd_ptr_used++; DLIST_ADD(FileFd, fd_ptr); - DEBUG(5,("allocated fd_ptr structure %d (%d used)\n", - i, fd_ptr_used)); + DEBUG(5,("allocated fd_ptr structure (%d used)\n", fd_ptr_used)); return fd_ptr; } @@ -197,6 +201,19 @@ void file_close_conn(connection_struct *conn) { files_struct *fsp, *next; +#ifdef USE_FILES_ARRAY + int i; + for (i = 0; i < MAX_FNUMS; i++) { + if((fsp = Files[i]) == NULL) + continue; + if(fsp->conn == conn && fsp->open) { + if (fsp->is_directory) + close_directory(fsp); + else + close_file(fsp,False); + } + } +#else for (fsp=Files;fsp;fsp=next) { next = fsp->next; if (fsp->conn == conn && fsp->open) { @@ -206,6 +223,7 @@ void file_close_conn(connection_struct *conn) close_file(fsp,False); } } +#endif } /**************************************************************************** @@ -214,9 +232,8 @@ initialise file structures void file_init(void) { file_bmap = bitmap_allocate(MAX_FNUMS); - fd_bmap = bitmap_allocate(MAX_FNUMS); - if (!file_bmap || !fd_bmap) { + if (!file_bmap) { exit_server("out of memory in file_init"); } @@ -246,6 +263,19 @@ void file_close_user(int vuid) { files_struct *fsp, *next; +#ifdef USE_FILES_ARRAY + int i; + for(i = 0; i < MAX_FNUMS; i++) { + if((fsp = Files[i]) == NULL) + continue; + if((fsp->vuid == vuid) && fsp->open) { + if(!fsp->is_directory) + close_file(fsp,False); + else + close_directory(fsp); + } + } +#else for (fsp=Files;fsp;fsp=next) { next=fsp->next; if ((fsp->vuid == vuid) && fsp->open) { @@ -255,6 +285,7 @@ void file_close_user(int vuid) close_directory(fsp); } } +#endif } @@ -266,6 +297,18 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval int count=0; files_struct *fsp; +#ifdef USE_FILES_ARRAY + for(count = 0; count < MAX_FNUMS; count++) { + if((fsp = Files[count]) == NULL) + continue; + if (fsp->open && + fsp->fd_ptr->dev == dev && + fsp->fd_ptr->inode == inode && + fsp->open_time.tv_sec == tval->tv_sec && + fsp->open_time.tv_usec == tval->tv_usec) + return fsp; + } +#else for (fsp=Files;fsp;fsp=fsp->next,count++) { if (fsp->open && fsp->fd_ptr->dev == dev && @@ -278,6 +321,7 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval return fsp; } } +#endif return NULL; } @@ -290,9 +334,19 @@ files_struct *file_find_print(void) { files_struct *fsp; +#ifdef USE_FILES_ARRAY + int i; + for(i = 0; i < MAX_FNUMS; i++) { + if((fsp = Files[i]) == NULL) + continue; + if (fsp->open && fsp->print_file) return fsp; + } +#else for (fsp=Files;fsp;fsp=fsp->next) { if (fsp->open && fsp->print_file) return fsp; } +#endif + return NULL; } @@ -304,12 +358,22 @@ void file_sync_all(connection_struct *conn) { files_struct *fsp, *next; +#ifdef USE_FILES_ARRAY + int i; + for(i = 0; i < MAX_FNUMS; i++) { + if((fsp = Files[i]) == NULL) + continue; + if (fsp->open && conn == fsp->conn) + sync_file(conn,fsp); + } +#else for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (fsp->open && conn == fsp->conn) { sync_file(conn,fsp); } } +#endif } @@ -320,11 +384,9 @@ void fd_ptr_free(file_fd_struct *fd_ptr) { DLIST_REMOVE(FileFd, fd_ptr); - bitmap_clear(fd_bmap, fd_ptr->fdnum); fd_ptr_used--; - DEBUG(5,("freed fd_ptr structure %d (%d used)\n", - fd_ptr->fdnum, fd_ptr_used)); + DEBUG(5,("freed fd_ptr structure (%d used)\n", fd_ptr_used)); /* paranoia */ ZERO_STRUCTP(fd_ptr); @@ -338,7 +400,16 @@ free up a fsp ****************************************************************************/ void file_free(files_struct *fsp) { +#ifdef USE_FILES_ARRAY + files_struct *fsp1 = Files[fsp->fnum - FILE_HANDLE_OFFSET]; + if(fsp != fsp1) + DEBUG(0,("file_free: fnum = %d (array offset %d) <> fsp = %x, fnum = %d!\n", + fsp->fnum, fsp->fnum - FILE_HANDLE_OFFSET, fsp1, fsp1->fnum)); + SMB_ASSERT(fsp == fsp1); + Files[fsp->fnum - FILE_HANDLE_OFFSET] = NULL; +#else DLIST_REMOVE(Files, fsp); +#endif string_free(&fsp->fsp_name); @@ -374,6 +445,15 @@ files_struct *file_fsp(char *buf, int where) fnum = SVAL(buf, where); +#ifdef USE_FILES_ARRAY + fsp = Files[fnum - FILE_HANDLE_OFFSET]; + if(!fsp) + DEBUG(0,("file_fsp: fnum = %d (array offset %d) gave null fsp !\n", + fnum, fnum - FILE_HANDLE_OFFSET)); + SMB_ASSERT(fsp != NULL); + + return (chain_fsp = fsp); +#else for (fsp=Files;fsp;fsp=fsp->next, count++) { if (fsp->fnum == fnum) { chain_fsp = fsp; @@ -383,8 +463,8 @@ files_struct *file_fsp(char *buf, int where) return fsp; } } - return NULL; +#endif } /**************************************************************************** -- cgit From 06cc91f9a631a23dcd4902d710b89e4b7584c459 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Sep 1998 01:24:30 +0000 Subject: Added ssize_t to configure code. Got 'religion' about using size_t and ssize_t for read/write stuff as part of the code to expose 64 bits to the client. This checkin does all the 'easy' stuff - such as all the read/write/lock calls - but now comes the harder parts (open & friends) and all the file enquiry functions..... Jeremy. (This used to be commit 36544fe5476f7770bd5748574fc54be7b3ee4d4a) --- source3/smbd/blocking.c | 50 +++++-- source3/smbd/fileio.c | 60 ++++---- source3/smbd/nttrans.c | 12 +- source3/smbd/open.c | 30 ---- source3/smbd/oplock.c | 60 -------- source3/smbd/predict.c | 14 +- source3/smbd/reply.c | 363 ++++++++++++++++++++++++++++-------------------- 7 files changed, 295 insertions(+), 294 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2241b7aa8d..051e276ca7 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -195,11 +195,13 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec files_struct *fsp = blr->fsp; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint32 count, offset; + SMB_OFF_T count, offset; + unsigned char locktype = CVAL(inbuf,smb_vwv3); + BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; int i; - data = smb_buf(inbuf) + 10*num_ulocks; + data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); /* * Data now points at the beginning of the list @@ -209,8 +211,18 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec for(i = blr->lock_num; i >= 0; i--) { int dummy1; uint32 dummy2; - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + if(!large_file_format) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + } +#ifdef LARGE_SMB_OFF_T + else { + count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); + offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); + } +#endif do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } @@ -248,10 +260,11 @@ static BOOL process_lockread(blocking_lock_record *blr) { char *outbuf = OutBuffer; char *inbuf = blr->inbuf; - int nread = -1; + ssize_t nread = -1; char *data; int outsize = 0; - uint32 startpos, numtoread; + SMB_OFF_T startpos; + size_t numtoread; int eclass; uint32 ecode; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); @@ -316,7 +329,7 @@ static BOOL process_lock(blocking_lock_record *blr) char *outbuf = OutBuffer; char *inbuf = blr->inbuf; int outsize; - uint32 count,offset; + SMB_OFF_T count,offset; int eclass; uint32 ecode; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); @@ -352,8 +365,8 @@ static BOOL process_lock(blocking_lock_record *blr) * Success - we got the lock. */ - DEBUG(3,("process_lock : file=%s fnum=%d ofs=%d cnt=%d\n", - fsp->fsp_name, fsp->fnum, (int)offset, (int)count)); + DEBUG(3,("process_lock : file=%s fnum=%d offset=%.0f count=%.0f\n", + fsp->fsp_name, fsp->fnum, (double)offset, (double)count)); construct_reply_common(inbuf, outbuf); outsize = set_message(outbuf,0,0,True); @@ -374,12 +387,13 @@ static BOOL process_lockingX(blocking_lock_record *blr) connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); - uint32 count, offset; + SMB_OFF_T count, offset; + BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; int eclass=0; uint32 ecode=0; - data = smb_buf(inbuf) + 10*num_ulocks; + data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); /* * Data now points at the beginning of the list @@ -387,8 +401,18 @@ static BOOL process_lockingX(blocking_lock_record *blr) */ for(; blr->lock_num < num_locks; blr->lock_num++) { - count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); - offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); + if(!large_file_format) { + count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); + offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); + } +#ifdef LARGE_SMB_OFF_T + else { + count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(blr->lock_num))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(blr->lock_num))); + offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(blr->lock_num))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(blr->lock_num))); + } +#endif errno = 0; if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 6d6edf9d37..f0bb5e45ac 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -27,6 +27,7 @@ extern int DEBUGLEVEL; /**************************************************************************** seek a file. Try to avoid the seek if possible ****************************************************************************/ + SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { SMB_OFF_T offset = 0; @@ -41,45 +42,43 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) /**************************************************************************** read from a file ****************************************************************************/ -int read_file(files_struct *fsp,char *data,uint32 pos,int n) + +ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { - int ret=0,readret; + ssize_t ret=0,readret; #if USE_READ_PREDICTION - if (!fsp->can_write) - { - ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); + if (!fsp->can_write) { + ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); - data += ret; - n -= ret; - pos += ret; - } + data += ret; + n -= ret; + pos += ret; + } #endif #if WITH_MMAP - if (fsp->mmap_ptr) - { - int num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; - num = MIN(n,num); - if (num > 0) - { - memcpy(data,fsp->mmap_ptr+pos,num); - data += num; - pos += num; - n -= num; - ret += num; - } + if (fsp->mmap_ptr) { + SMB_OFF_T num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; + num = MIN(n,num); +#ifdef LARGE_SMB_OFF_T + if ((num > 0) && (num < (1<<(sizeof(size_t)*8))) { +#else /* LARGE_SMB_OFF_T */ + if (num > 0) { +#endif /* LARGE_SMB_OFF_T */ + memcpy(data,fsp->mmap_ptr+pos,num); + data += num; + pos += num; + n -= num; + ret += num; } + } #endif - if (n <= 0) + if (seek_file(fsp,pos) != pos) { + DEBUG(3,("Failed to seek to %.0f\n",(double)pos)); return(ret); - - if (seek_file(fsp,pos) != pos) - { - DEBUG(3,("Failed to seek to %d\n",pos)); - return(ret); - } + } if (n > 0) { readret = read(fsp->fd_ptr->fd,data,n); @@ -93,7 +92,8 @@ int read_file(files_struct *fsp,char *data,uint32 pos,int n) /**************************************************************************** write to a file ****************************************************************************/ -int write_file(files_struct *fsp,char *data,int n) + +ssize_t write_file(files_struct *fsp,char *data,size_t n) { if (!fsp->can_write) { @@ -119,6 +119,7 @@ int write_file(files_struct *fsp,char *data,int n) /******************************************************************* sync a file ********************************************************************/ + void sync_file(connection_struct *conn, files_struct *fsp) { #ifdef HAVE_FSYNC @@ -126,4 +127,3 @@ void sync_file(connection_struct *conn, files_struct *fsp) fsync(fsp->fd_ptr->fd); #endif } - diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0f50145d7f..81b3ff26d5 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -890,12 +890,12 @@ static int call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 12; -#if OFF_T_IS_64_BITS - SIVAL(p,0, file_len & 0xFFFFFFFF); - SIVAL(p,4, (file_len >> 32)); -#else /* OFF_T_IS_64_BITS */ - SIVAL(p,0,file_len); -#endif /* OFF_T_IS_64_BITS */ +#ifdef LARGE_SMB_OFF_T + SIVAL(p,0, file_len & 0xFFFFFFFF); + SIVAL(p,4, (file_len >> 32)); +#else /* LARGE_SMB_OFF_T */ + SIVAL(p,0,file_len); +#endif /* LARGE_SMB_OFF_T */ } /* Send the required number of replies */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bd1ead6921..bdd4816aa7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -815,13 +815,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) { -#ifdef LARGE_SMB_INO_T DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ -dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ /* Oplock break.... */ unlock_share_entry(conn, dev, inode, token); @@ -829,13 +824,8 @@ dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsig { free((char *)old_shares); -#ifdef LARGE_SMB_INO_T DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ errno = EACCES; unix_ERR_class = ERRDOS; @@ -940,13 +930,8 @@ dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsi global_oplocks_open++; port = oplock_port; -#ifdef LARGE_SMB_INO_T DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ } else @@ -1114,13 +1099,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) if(rename_op && (share_entry->pid == pid)) { -#ifdef LARGE_SMB_INO_T DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ -batch oplocked file %s, dev = %x, inode = %lx\n", fname, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ /* * This next line is a test that allows the deny-mode @@ -1135,13 +1115,8 @@ batch oplocked file %s, dev = %x, inode = %lx\n", fname, (unsigned int)dev, (uns else { -#ifdef LARGE_SMB_INO_T DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ /* Oplock break.... */ unlock_share_entry(conn, dev, inode, token); @@ -1149,13 +1124,8 @@ dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsig { free((char *)old_shares); -#ifdef LARGE_SMB_INO_T DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ return False; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index dd882d08cc..348e29dbe2 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -124,13 +124,8 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); -#ifdef LARGE_SMB_INO_T DEBUG(5,("process_local_message: oplock break request from \ pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(5,("process_local_message: oplock break request from \ -pid %d, port %d, dev = %x, inode = %lx\n", remotepid, from_port, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ /* * If we have no record of any currently open oplocks, @@ -170,15 +165,9 @@ oplocks. Returning success.\n")); return False; } -#ifdef LARGE_SMB_INO_T DEBUG(5,("process_local_message: oplock break reply sent to \ pid %d, port %d, for file dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %lx\n", - remotepid, from_port, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ } break; @@ -210,13 +199,8 @@ reply - dumping info.\n")); SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); #endif /* LARGE_SMB_INO_T */ -#ifdef LARGE_SMB_INO_T DEBUG(0,("process_local_message: unsolicited oplock break reply from \ pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %lx\n", remotepid, from_port, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ } return False; @@ -247,11 +231,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 3 ) ) { -#ifdef LARGE_SMB_INO_T dbgtext( "oplock_break: called for dev = %x, inode = %.0f.\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "oplock_break: called for dev = %x, inode = %lx.\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); } @@ -266,11 +246,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 0 ) ) { dbgtext( "oplock_break: cannot find open file with " ); -#ifdef LARGE_SMB_INO_T dbgtext( "dev = %x, inode = %.0f ", (unsigned int)dev, (double)inode); -#else /* LARGE_SMB_INO_T */ - dbgtext( "dev = %x, inode = %lx ", (unsigned int)dev, (unsigned long)inode); -#endif /* LARGE_SMB_INO_T */ dbgtext( "allowing break to succeed.\n" ); } return True; @@ -290,11 +266,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 0 ) ) { dbgtext( "oplock_break: file %s ", fsp->fsp_name ); -#ifdef LARGE_SMB_INO_T dbgtext( "(dev = %x, inode = %.0f) has no oplock.\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "(dev = %x, inode = %lx) has no oplock.\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ dbgtext( "Allowing break to succeed regardless.\n" ); } return True; @@ -307,11 +279,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); dbgtext( "file %s ", fsp->fsp_name); -#ifdef LARGE_SMB_INO_T dbgtext( "(dev = %x, inode = %.0f)\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "(dev = %x, inode = %lx)\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ } /* We have to fail the open here as we cannot send another oplock break on @@ -403,11 +371,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) OPLOCK_BREAK_TIMEOUT ) ); DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) ); -#ifdef LARGE_SMB_INO_T DEBUGADD( 0, ( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUGADD( 0, ( "(dev = %x, inode = %lx).\n", (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ shutdown_server = True; break; @@ -435,11 +399,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) dbgtext( "oplock_break: no break received from client " ); dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); -#ifdef LARGE_SMB_INO_T dbgtext( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "(dev = %x, inode = %lx).\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ } shutdown_server = True; @@ -507,11 +467,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if( DEBUGLVL( 3 ) ) { dbgtext( "oplock_break: returning success for " ); -#ifdef LARGE_SMB_INO_T dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); } @@ -576,11 +532,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); { dbgtext( "request_oplock_break: sending a oplock break message to " ); dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port ); -#ifdef LARGE_SMB_INO_T dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ } @@ -592,11 +544,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); dbgtext( "request_oplock_break: failed when sending a oplock " ); dbgtext( "break message to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); -#ifdef LARGE_SMB_INO_T dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ dbgtext( "Error was %s\n", strerror(errno) ); } return False; @@ -629,11 +577,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); dbgtext( "request_oplock_break: no response received to oplock " ); dbgtext( "break request to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); -#ifdef LARGE_SMB_INO_T dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ } /* @@ -651,11 +595,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); dbgtext( "request_oplock_break: error in response received " ); dbgtext( "to oplock break request to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); -#ifdef LARGE_SMB_INO_T dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); -#else /* LARGE_SMB_INO_T */ - dbgtext( "for dev = %x, inode = %lx\n", (unsigned int)dev, (unsigned long)inode ); -#endif /* LARGE_SMB_INO_T */ dbgtext( "Error was (%s).\n", strerror(errno) ); } return False; diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 0deda0c0b6..5f015139cf 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -28,11 +28,11 @@ extern int DEBUGLEVEL; /* variables used by the read prediction module */ static int rp_fd = -1; static SMB_OFF_T rp_offset = 0; -static int rp_length = 0; -static int rp_alloced = 0; +static ssize_t rp_length = 0; +static ssize_t rp_alloced = 0; static int rp_predict_fd = -1; static SMB_OFF_T rp_predict_offset = 0; -static int rp_predict_length = 0; +static size_t rp_predict_length = 0; static int rp_timeout = 5; static time_t rp_time = 0; static char *rp_buffer = NULL; @@ -42,10 +42,10 @@ extern time_t smb_last_time; /**************************************************************************** handle read prediction on a file ****************************************************************************/ -int read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,int num) +ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) { - int ret = 0; - int possible = rp_length - (offset - rp_offset); + ssize_t ret = 0; + ssize_t possible = rp_length - (offset - rp_offset); possible = MIN(possible,num); @@ -97,7 +97,7 @@ pre-read some data ****************************************************************************/ void do_read_prediction(void) { - static int readsize = 0; + static size_t readsize = 0; if (predict_skip) return; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3d537d8868..8ec2715d0d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1765,11 +1765,11 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ****************************************************************************/ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { - int maxcount,mincount; - int nread = 0; - uint32 startpos; + size_t maxcount,mincount; + size_t nread = 0; + SMB_OFF_T startpos; char *header = outbuf; - SMB_OFF_T ret=0; + ssize_t ret=0; int fd; char *fname; files_struct *fsp; @@ -1791,8 +1791,23 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s fsp = file_fsp(inbuf,smb_vwv0); startpos = IVAL(inbuf,smb_vwv1); - maxcount = SVAL(inbuf,smb_vwv3); - mincount = SVAL(inbuf,smb_vwv4); +#ifdef LARGE_SMB_OFF_T + if(SVAL(inbuf,smb_wct) == 10) { + /* + * This is a large offset (64 bit) read. + */ + startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32); + if(startpos < 0) { + DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", + (double)startpos )); + _smb_setlen(header,0); + transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + return(-1); + } + } +#endif /* LARGE_SMB_OFF_T */ + maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); + mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); @@ -1812,9 +1827,10 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) { SMB_OFF_T size = fsp->size; - int sizeneeded = startpos + maxcount; + SMB_OFF_T sizeneeded = startpos + maxcount; - if (size < sizeneeded) { + if (size < sizeneeded) + { SMB_STRUCT_STAT st; if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) size = st.st_size; @@ -1822,14 +1838,14 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s fsp->size = size; } - nread = MIN(maxcount,(int)(size - startpos)); + nread = MIN(maxcount,(size - startpos)); } if (nread < mincount) nread = 0; - DEBUG( 3, ( "readbraw fnum=%d start=%d max=%d min=%d nread=%d\n", - fsp->fnum, startpos, + DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", + fsp->fnum, (double)startpos, maxcount, mincount, nread ) ); #if UNSAFE_READRAW @@ -1840,12 +1856,12 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #if USE_READ_PREDICTION if (!fsp->can_write) predict = read_predict(fd,startpos,header+4,NULL,nread); -#endif +#endif /* USE_READ_PREDICTION */ if ((nread-predict) > 0) seek_file(fsp,startpos + predict); - ret = transfer_file(fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict, + ret = (ssize_t)transfer_file(fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } @@ -1853,13 +1869,13 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n", fname,startpos,nread,ret)); -#else +#else /* UNSAFE_READRAW */ ret = read_file(fsp,header+4,startpos,nread); if (ret < mincount) ret = 0; _smb_setlen(header,ret); transfer_file(0,Client,0,header,4+ret,0); -#endif +#endif /* UNSAFE_READRAW */ DEBUG(5,("readbraw finished\n")); return -1; @@ -1871,10 +1887,11 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s ****************************************************************************/ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz) { - int nread = -1; + ssize_t nread = -1; char *data; int outsize = 0; - uint32 startpos, numtoread; + SMB_OFF_T startpos; + size_t numtoread; int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -1925,10 +1942,10 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length ****************************************************************************/ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtoread; - int nread = 0; + size_t numtoread; + ssize_t nread = 0; char *data; - uint32 startpos; + SMB_OFF_T startpos; int outsize = 0; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -1971,10 +1988,10 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); - uint32 smb_offs = IVAL(inbuf,smb_vwv3); - int smb_maxcnt = SVAL(inbuf,smb_vwv5); - int smb_mincnt = SVAL(inbuf,smb_vwv6); - int nread = -1; + SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); + size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); + size_t smb_mincnt = SVAL(inbuf,smb_vwv6); + ssize_t nread = -1; char *data; BOOL ok = False; @@ -1989,9 +2006,18 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,12,0,True); data = smb_buf(outbuf); - if (is_locked(fsp,conn,smb_maxcnt,smb_offs, F_RDLCK)) +#ifdef LARGE_SMB_INO_T + if(SVAL(inbuf,smb_wct) == 12) { + /* + * This is a large offset (64 bit) read. + */ + startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); + } +#endif /* LARGE_SMB_INO_T */ + + if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); - nread = read_file(fsp,data,smb_offs,smb_maxcnt); + nread = read_file(fsp,data,startpos,smb_maxcnt); ok = True; if (nread < 0) @@ -2007,21 +2033,20 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return chain_reply(inbuf,outbuf,length,bufsize); } - /**************************************************************************** reply to a writebraw (core+ or LANMAN1.0 protocol) ****************************************************************************/ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int nwritten=0; - int total_written=0; - int numtowrite=0; - int outsize = 0; - long startpos; + ssize_t nwritten=0; + ssize_t total_written=0; + size_t numtowrite=0; + size_t tcount; + SMB_OFF_T startpos; char *data=NULL; BOOL write_through; - int tcount; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int outsize = 0; CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2049,13 +2074,13 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s return(ERROR(ERRDOS,ERRlock)); if (seek_file(fsp,startpos) != startpos) - DEBUG(0,("couldn't seek to %ld in writebraw\n",startpos)); + DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos)); if (numtowrite>0) nwritten = write_file(fsp,data,numtowrite); - DEBUG(3,("writebraw1 fnum=%d start=%ld num=%d wrote=%d sync=%d\n", - fsp->fnum, startpos, numtowrite, nwritten, write_through)); + DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", + fsp->fnum, (double)startpos, numtowrite, nwritten, write_through)); if (nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -2092,7 +2117,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s CVAL(outbuf,smb_com) = SMBwritec; SSVAL(outbuf,smb_vwv0,total_written); - if (nwritten < numtowrite) { + if (nwritten < (ssize_t)numtowrite) { CVAL(outbuf,smb_rcls) = ERRHRD; SSVAL(outbuf,smb_err,ERRdiskfull); } @@ -2100,8 +2125,8 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if (lp_syncalways(SNUM(conn)) || write_through) sync_file(conn,fsp); - DEBUG(3,("writebraw2 fnum=%d start=%ld num=%d wrote=%d\n", - fsp->fnum, startpos, numtowrite, total_written)); + DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", + fsp->fnum, (double)startpos, numtowrite, total_written)); /* we won't return a status if write through is not selected - this follows what WfWg does */ @@ -2111,19 +2136,19 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s return(outsize); } - /**************************************************************************** reply to a writeunlock (core+) ****************************************************************************/ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int nwritten = -1; - int outsize = 0; + ssize_t nwritten = -1; + size_t numtowrite; + SMB_OFF_T startpos; char *data; - uint32 numtowrite,startpos; int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int outsize = 0; CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2165,18 +2190,17 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum return(outsize); } - /**************************************************************************** reply to a write ****************************************************************************/ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize) { - int numtowrite; - int nwritten = -1; - int outsize = 0; - int startpos; + size_t numtowrite; + ssize_t nwritten = -1; + SMB_OFF_T startpos; char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int outsize = 0; CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2209,7 +2233,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i SSVAL(outbuf,smb_vwv0,nwritten); - if (nwritten < numtowrite) { + if (nwritten < (ssize_t)numtowrite) { CVAL(outbuf,smb_rcls) = ERRHRD; SSVAL(outbuf,smb_err,ERRdiskfull); } @@ -2227,11 +2251,11 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); - uint32 smb_offs = IVAL(inbuf,smb_vwv3); - int smb_dsize = SVAL(inbuf,smb_vwv10); - int smb_doff = SVAL(inbuf,smb_vwv11); + SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); + size_t numtowrite = SVAL(inbuf,smb_vwv10); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); - int nwritten = -1; + ssize_t nwritten = -1; + int smb_doff = SVAL(inbuf,smb_vwv11); char *data; CHECK_FSP(fsp,conn); @@ -2240,34 +2264,43 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng data = smb_base(inbuf) + smb_doff; - if (is_locked(fsp,conn,smb_dsize,smb_offs, F_WRLCK)) +#ifdef LLARGE_SMB_INO_T + if(SVAL(inbuf,smb_wct) == 14) { + /* + * This is a large offset (64 bit) write. + */ + startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); + } +#endif /* LARGE_SMB_INO_T */ + + if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fsp,smb_offs); + seek_file(fsp,startpos); /* X/Open SMB protocol says that, unlike SMBwrite if the length is zero then NO truncation is done, just a write of zero. To truncate a file, use SMBwrite. */ - if(smb_dsize == 0) + if(numtowrite == 0) nwritten = 0; else - nwritten = write_file(fsp,data,smb_dsize); + nwritten = write_file(fsp,data,numtowrite); - if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0)) + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); set_message(outbuf,6,0,True); SSVAL(outbuf,smb_vwv2,nwritten); - if (nwritten < smb_dsize) { + if (nwritten < (ssize_t)numtowrite) { CVAL(outbuf,smb_rcls) = ERRHRD; SSVAL(outbuf,smb_err,ERRdiskfull); } DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", - fsp->fnum, smb_dsize, nwritten)); + fsp->fnum, numtowrite, nwritten)); if (lp_syncalways(SNUM(conn)) || write_through) sync_file(conn,fsp); @@ -2281,7 +2314,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng ****************************************************************************/ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - uint32 startpos; + SMB_OFF_T startpos; SMB_OFF_T res= -1; int mode,umode; int outsize = 0; @@ -2302,19 +2335,18 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, umode = SEEK_SET; break; } - res = sys_lseek(fsp->fd_ptr->fd,(SMB_OFF_T)startpos,umode); + res = sys_lseek(fsp->fd_ptr->fd,startpos,umode); fsp->pos = res; outsize = set_message(outbuf,2,0,True); - SIVALS(outbuf,smb_vwv0,(uint32)res); + SIVALS(outbuf,smb_vwv0,res); - DEBUG(3,("lseek fnum=%d ofs=%d mode=%d\n", - fsp->fnum, startpos, mode)); + DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n", + fsp->fnum, (double)startpos, mode)); return(outsize); } - /**************************************************************************** reply to a flush ****************************************************************************/ @@ -2421,10 +2453,10 @@ int reply_close(connection_struct *conn, int reply_writeclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite; - int nwritten = -1; + size_t numtowrite; + ssize_t nwritten = -1; int outsize = 0; - int startpos; + SMB_OFF_T startpos; char *data; time_t mtime; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -2470,7 +2502,7 @@ int reply_lock(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); - uint32 count,offset; + SMB_OFF_T count,offset; int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -2481,8 +2513,8 @@ int reply_lock(connection_struct *conn, count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); - DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n", - fsp->fd_ptr->fd, fsp->fnum, offset, count)); + DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", + fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count)); if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { @@ -2507,7 +2539,7 @@ int reply_lock(connection_struct *conn, int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); - uint32 count,offset; + SMB_OFF_T count,offset; int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -2521,8 +2553,8 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); - DEBUG( 3, ( "unlock fd=%d fnum=%d ofs=%d cnt=%d\n", - fsp->fd_ptr->fd, fsp->fnum, offset, count ) ); + DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", + fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) ); return(outsize); } @@ -3476,8 +3508,6 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(outsize); } - - /**************************************************************************** reply to a setdir ****************************************************************************/ @@ -3515,7 +3545,6 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } - /**************************************************************************** reply to a lockingX request ****************************************************************************/ @@ -3528,13 +3557,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, #endif uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); - uint32 count, offset; + SMB_OFF_T count, offset; int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; uint32 ecode=0, dummy2; int eclass=0, dummy1; - + BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -3565,13 +3594,8 @@ no oplock granted on this file.\n", fsp->fnum)); lock_share_entry(fsp->conn, dev, inode, &token); if(remove_share_oplock(fsp, token)==False) { -#ifdef LARGE_SMB_INO_T DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); -#else /* LARGE_SMB_INO_T */ - DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ -dev = %x, inode = %lx\n", fsp->fnum, (unsigned int)dev, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ unlock_share_entry(fsp->conn, dev, inode, token); } else { @@ -3596,10 +3620,22 @@ dev = %x, inode = %lx\n", fsp->fnum, (unsigned int)dev, (unsigned long)inode)); /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - DEBUG(10,("reply_lockingX: unlock start=%d, len=%d for file %s\n", - (int)offset, (int)count, fsp->fsp_name )); + if(!large_file_format) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + } +#ifdef LARGE_SMB_OFF_T + else { + count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); + offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); + } +#endif + + DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", + (double)offset, (double)count, fsp->fsp_name )); + if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode)) return ERROR(eclass,ecode); } @@ -3608,14 +3644,28 @@ dev = %x, inode = %lx\n", fsp->fnum, (unsigned int)dev, (unsigned long)inode)); lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000); /* Now do any requested locks */ - data += 10*num_ulocks; + data += ((large_file_format ? 20 : 10)*num_ulocks); + /* Data now points at the beginning of the list of smb_lkrng structs */ + for(i = 0; i < (int)num_locks; i++) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - DEBUG(10,("reply_lockingX: lock start=%d, len=%d for file %s\n", - (int)offset, (int)count, fsp->fsp_name )); + if(!large_file_format) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + } +#ifdef LARGE_SMB_OFF_T + else { + count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); + offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); + } +#endif + + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", + (double)offset, (double)count, fsp->fsp_name )); + if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) { if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { @@ -3635,8 +3685,19 @@ dev = %x, inode = %lx\n", fsp->fnum, (unsigned int)dev, (unsigned long)inode)); all of the previous locks (X/Open spec). */ if(i != num_locks && num_locks != 0) { for(; i >= 0; i--) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + if(!large_file_format) { + count = IVAL(data,SMB_LKLEN_OFFSET(i)); + offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + } +#ifdef LARGE_SMB_OFF_T + else { + count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); + offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); + } +#endif + do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } return ERROR(eclass,ecode); @@ -3656,13 +3717,14 @@ dev = %x, inode = %lx\n", fsp->fnum, (unsigned int)dev, (unsigned long)inode)); ****************************************************************************/ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - int nread = -1; - int total_read; + ssize_t nread = -1; + ssize_t total_read; char *data; - uint32 startpos; - int outsize, mincount, maxcount; + SMB_OFF_T startpos; + int outsize; + size_t mincount, maxcount; int max_per_packet; - int tcount; + size_t tcount; int pad; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3694,14 +3756,14 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, do { - int N = MIN(max_per_packet,tcount-total_read); + size_t N = MIN(max_per_packet,tcount-total_read); nread = read_file(fsp,data,startpos,N); if (nread <= 0) nread = 0; - if (nread < N) - tcount = total_read + nread; + if (nread < (ssize_t)N) + tcount = total_read + nread; set_message(outbuf,8,nread,False); SIVAL(outbuf,smb_vwv0,startpos); @@ -3714,22 +3776,23 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, total_read += nread; startpos += nread; } - while (total_read < tcount); + while (total_read < (ssize_t)tcount); return(-1); } - /**************************************************************************** reply to a SMBwritebmpx (write block multiplex primary) request ****************************************************************************/ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite; - int nwritten = -1; + size_t numtowrite; + ssize_t nwritten = -1; int outsize = 0; - uint32 startpos; - int tcount, write_through, smb_doff; + SMB_OFF_T startpos; + size_t tcount; + BOOL write_through; + int smb_doff; char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3758,32 +3821,32 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if(lp_syncalways(SNUM(conn)) || write_through) sync_file(conn,fsp); - if(nwritten < numtowrite) + if(nwritten < (ssize_t)numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); /* If the maximum to be written to this file is greater than what we just wrote then set up a secondary struct to be attached to this fd, we will use this to cache error messages etc. */ - if(tcount > nwritten) + if((ssize_t)tcount > nwritten) + { + write_bmpx_struct *wbms; + if(fsp->wbmpx_ptr != NULL) + wbms = fsp->wbmpx_ptr; /* Use an existing struct */ + else + wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); + if(!wbms) { - write_bmpx_struct *wbms; - if(fsp->wbmpx_ptr != NULL) - wbms = fsp->wbmpx_ptr; /* Use an existing struct */ - else - wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); - if(!wbms) - { - DEBUG(0,("Out of memory in reply_readmpx\n")); - return(ERROR(ERRSRV,ERRnoresource)); - } - wbms->wr_mode = write_through; - wbms->wr_discard = False; /* No errors yet */ - wbms->wr_total_written = nwritten; - wbms->wr_errclass = 0; - wbms->wr_error = 0; - fsp->wbmpx_ptr = wbms; + DEBUG(0,("Out of memory in reply_readmpx\n")); + return(ERROR(ERRSRV,ERRnoresource)); } + wbms->wr_mode = write_through; + wbms->wr_discard = False; /* No errors yet */ + wbms->wr_total_written = nwritten; + wbms->wr_errclass = 0; + wbms->wr_error = 0; + fsp->wbmpx_ptr = wbms; + } /* We are returning successfully, set the message type back to SMBwritebmpx */ @@ -3816,11 +3879,13 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s ****************************************************************************/ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite; - int nwritten = -1; + size_t numtowrite; + ssize_t nwritten = -1; int outsize = 0; - int32 startpos; - int tcount, write_through, smb_doff; + SMB_OFF_T startpos; + size_t tcount; + BOOL write_through; + int smb_doff; char *data; write_bmpx_struct *wbms; BOOL send_response = False; @@ -3858,32 +3923,34 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz if(lp_syncalways(SNUM(conn)) || write_through) sync_file(conn,fsp); - if (nwritten < numtowrite) + if (nwritten < (ssize_t)numtowrite) + { + if(write_through) { - if(write_through) { - /* We are returning an error - we can delete the aux struct */ - if (wbms) free((char *)wbms); - fsp->wbmpx_ptr = NULL; - return(ERROR(ERRHRD,ERRdiskfull)); - } - return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); + /* We are returning an error - we can delete the aux struct */ + if (wbms) free((char *)wbms); + fsp->wbmpx_ptr = NULL; + return(ERROR(ERRHRD,ERRdiskfull)); } + return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); + } /* Increment the total written, if this matches tcount we can discard the auxiliary struct (hurrah !) and return a writeC */ wbms->wr_total_written += nwritten; if(wbms->wr_total_written >= tcount) + { + if (write_through) { - if (write_through) { - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); - send_response = True; - } - - free((char *)wbms); - fsp->wbmpx_ptr = NULL; + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); + send_response = True; } + free((char *)wbms); + fsp->wbmpx_ptr = NULL; + } + if(send_response) return(outsize); -- cgit From 27d0bef143fbc4d7547c022046c094bbdbd0bfc1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Sep 1998 19:14:27 +0000 Subject: Ok - this is the 'expose 64 bit to the clients' checkin. I have tested it by creating a 'holey' 20GB file - checking that it shows up correctl in the NT file view (it does) and am busily copying it to NULL: on the NT box. All good so far.... :-). Also implemented NT 'delete on close' semantics. Jeremy. (This used to be commit 1654faee80648583e6a47ab7eda990fefdf85124) --- source3/smbd/blocking.c | 4 +-- source3/smbd/close.c | 16 ++++++++- source3/smbd/negprot.c | 8 +++-- source3/smbd/open.c | 1 + source3/smbd/reply.c | 20 +++++------ source3/smbd/trans2.c | 90 ++++++++++++++++++++++++++++++++++++++----------- 6 files changed, 104 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 051e276ca7..27a5183952 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -222,7 +222,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif +#endif /* LARGE_SMB_OFF_T */ do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } @@ -412,7 +412,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(blr->lock_num))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(blr->lock_num))); } -#endif +#endif /* LARGE_SMB_OFF_T */ errno = 0; if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) diff --git a/source3/smbd/close.c b/source3/smbd/close.c index e9606cdfbe..981c0d77bb 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -102,6 +102,7 @@ void close_file(files_struct *fsp, BOOL normal_close) SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; int token; + BOOL last_reference = False; connection_struct *conn = fsp->conn; remove_pending_lock_requests_by_fid(fsp); @@ -118,7 +119,9 @@ void close_file(files_struct *fsp, BOOL normal_close) } if(fd_attempt_close(fsp->fd_ptr) == 0) - fsp->fd_ptr = NULL; + last_reference = True; + + fsp->fd_ptr = NULL; if (lp_share_modes(SNUM(conn))) unlock_share_entry(conn, dev, inode, token); @@ -132,6 +135,17 @@ void close_file(files_struct *fsp, BOOL normal_close) check_magic(fsp,conn); } + /* + * NT can set delete_on_close of the last open + * reference to a file. + */ + + if (normal_close && last_reference && fsp->delete_on_close) { + if(dos_unlink(fsp->fsp_name) != 0) + DEBUG(0,("close_file: file %s. Delete on close was set and unlink failed \ +with error %s\n", fsp->fsp_name, strerror(errno) )); + } + if(fsp->granted_oplock == True) global_oplocks_open--; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 6a9cc9fb9b..e9dd4614c4 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -157,11 +157,15 @@ static int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| - (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0); + (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | +#ifdef LARGE_SMB_OFF_T + (sizeof(SMB_OFF_T) == 8 ? CAP_LARGE_FILES : 0); +#else + 0; +#endif /* other valid capabilities which we may support at some time... - CAP_LARGE_FILES| CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bdd4816aa7..42b0fba425 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -507,6 +507,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->granted_oplock = False; fsp->sent_oplock_break = False; fsp->is_directory = False; + fsp->delete_on_close = False; fsp->conn = conn; /* * Note that the file name here is the *untranslated* name diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8ec2715d0d..e956ab6cd9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2006,14 +2006,14 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,12,0,True); data = smb_buf(outbuf); -#ifdef LARGE_SMB_INO_T +#ifdef LARGE_SMB_OFF_T if(SVAL(inbuf,smb_wct) == 12) { /* * This is a large offset (64 bit) read. */ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); } -#endif /* LARGE_SMB_INO_T */ +#endif /* LARGE_SMB_OFF_T */ if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); @@ -2264,14 +2264,14 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng data = smb_base(inbuf) + smb_doff; -#ifdef LLARGE_SMB_INO_T +#ifdef LLARGE_SMB_OFF_T if(SVAL(inbuf,smb_wct) == 14) { /* * This is a large offset (64 bit) write. */ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); } -#endif /* LARGE_SMB_INO_T */ +#endif /* LARGE_SMB_OFF_T */ if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); @@ -2408,8 +2408,8 @@ int reply_close(connection_struct *conn, * We can only use CHECK_FSP if we know it's not a directory. */ - if(!(fsp && fsp->open && fsp->is_directory)) - CHECK_FSP(fsp,conn); + if(!fsp || !fsp->open || (fsp->conn != conn)) + return(ERROR(ERRDOS,ERRbadfid)); if(HAS_CACHED_ERROR(fsp)) { eclass = fsp->wbmpx_ptr->wr_errclass; @@ -3631,7 +3631,7 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif +#endif /* LARGE_SMB_OFF_T */ DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); @@ -3661,8 +3661,8 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif - +#endif /* LARGE_SMB_OFF_T */ + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); @@ -3696,7 +3696,7 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif +#endif /* LARGE_SMB_OFF_T */ do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 709b8daecd..87d1ea27d0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -415,8 +415,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, { case 1: if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; + SIVAL(p,0,reskey); + p += 4; } put_dos_date2(p,l1_fdateCreation,cdate); put_dos_date2(p,l1_fdateLastAccess,adate); @@ -433,8 +433,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, case 2: /* info_level 2 */ if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; + SIVAL(p,0,reskey); + p += 4; } put_dos_date2(p,l2_fdateCreation,cdate); put_dos_date2(p,l2_fdateLastAccess,adate); @@ -466,8 +466,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, case 4: if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; + SIVAL(p,0,reskey); + p += 4; } SIVAL(p,0,33+strlen(fname)+1); put_dos_date2(p,4,cdate); @@ -492,17 +492,22 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); + SIVAL(p,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(p,4,size >> 32); + SIVAL(p,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ + p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { - pstrcpy(p+2,fname); - if (!name_map_mangle(p+2,True,SNUM(conn))) - (p+2)[12] = 0; + pstrcpy(p+2,fname); + if (!name_map_mangle(p+2,True,SNUM(conn))) + (p+2)[12] = 0; } else - *(p+2) = 0; + *(p+2) = 0; strupper(p+2); SSVAL(p,0,strlen(p+2)); p += 2 + 24; @@ -520,8 +525,13 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); + SIVAL(p,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(p,4,size >> 32); + SIVAL(p,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ + p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; pstrcpy(p,fname); @@ -538,8 +548,13 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); + SIVAL(p,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(p,4,size >> 32); + SIVAL(p,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ + p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; @@ -1055,6 +1070,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", /**************************************************************************** reply to a TRANS2_QFSINFO (query filesystem info) ****************************************************************************/ + static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1329,6 +1345,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 22; SIVAL(pdata,0,size); SIVAL(pdata,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(pdata,4,size>>32); + SIVAL(pdata,12,size>>32); +#endif /* LARGE_SMB_OFF_T */ SIVAL(pdata,16,sbuf.st_nlink); CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; @@ -1367,6 +1387,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; SIVAL(pdata,0,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(pdata,4,size >> 32); +#endif /* LARGE_SMB_OFF_T */ break; case SMB_QUERY_FILE_ALL_INFO: @@ -1378,6 +1401,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pdata += 40; SIVAL(pdata,0,size); SIVAL(pdata,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(pdata,4,size >> 32); + SIVAL(pdata,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ SIVAL(pdata,16,sbuf.st_nlink); CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; @@ -1385,9 +1412,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pdata += 8; /* index number */ pdata += 4; /* EA info */ if (mode & aRONLY) - SIVAL(pdata,0,0xA9); + SIVAL(pdata,0,0xA9); else - SIVAL(pdata,0,0xd01BF); + SIVAL(pdata,0,0xd01BF); pdata += 4; SIVAL(pdata,0,pos); /* current offset */ pdata += 8; @@ -1566,16 +1593,39 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_END_OF_FILE_INFO: { + size = IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) /* more than 32 bits? */ return(ERROR(ERRDOS,ERRunknownlevel)); - size = IVAL(pdata,0); +#endif /* LARGE_SMB_OFF_T */ break; } case SMB_SET_FILE_ALLOCATION_INFO: break; /* We don't need to do anything for this call. */ - case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */ + case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ + { + if (tran_call == TRANSACT2_SETFILEINFO) { + files_struct *fsp = file_fsp(params,0); + if(fsp->is_directory) + return(ERROR(ERRDOS,ERRnoaccess)); + /* + * TODO - check here is this means set + * this flag bit on all open files that + * reference this particular dev/inode pair. + * If so we'll need to search the open + * file entries here and set this flag on + * all of them that match. JRA. + */ + fsp->delete_on_close = CVAL(pdata,0); + } else + return(ERROR(ERRDOS,ERRunknownlevel)); + break; + } + default: { return(ERROR(ERRDOS,ERRunknownlevel)); -- cgit From 9b20e5bac2a7b83f8e3dfdf3a274a1ce12dbd92c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Sep 1998 21:42:18 +0000 Subject: Ok so with this bugfix 64 bit file access actually seems to work :-). Problems were just dumb bugs like (defining sys_lseek to return 'int' DOH !). Jeremy. (This used to be commit 54dd51176fbab18af0b21bdee71b53f8f86573a8) --- source3/smbd/fileio.c | 8 ++++++-- source3/smbd/nttrans.c | 22 ++++++++++++++++++---- source3/smbd/reply.c | 6 +++--- 3 files changed, 27 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index f0bb5e45ac..d40c159798 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -36,6 +36,10 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) offset = 3; fsp->pos = (sys_lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); + + DEBUG(10,("seek_file: requested pos = %.0f, new pos = %.0f\n", + (double)(pos+offset), (double)fsp->pos )); + return(fsp->pos); } @@ -62,7 +66,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) SMB_OFF_T num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; num = MIN(n,num); #ifdef LARGE_SMB_OFF_T - if ((num > 0) && (num < (1<<(sizeof(size_t)*8))) { + if ((num > 0) && (num < (1LL<<(sizeof(size_t)*8)))) { #else /* LARGE_SMB_OFF_T */ if (num > 0) { #endif /* LARGE_SMB_OFF_T */ @@ -76,7 +80,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #endif if (seek_file(fsp,pos) != pos) { - DEBUG(3,("Failed to seek to %.0f\n",(double)pos)); + DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); return(ret); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 81b3ff26d5..5052e6d52a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -661,9 +661,16 @@ int reply_ntcreate_and_X(connection_struct *conn, put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; SIVAL(p,0,fmode); /* File Attributes. */ - p += 12; + p += 4; +#ifdef LARGE_SMB_OFF_T + SIVAL(p,0, file_len); + SIVAL(p,4, file_len >> 32); +#else /* LARGE_SMB_OFF_T */ + SIVAL(p,0,file_len); +#endif /* LARGE_SMB_OFF_T */ + p += 8; #ifdef LARGE_SMB_OFF_T - SIVAL(p,0, file_len & 0xFFFFFFFF); + SIVAL(p,0, file_len); SIVAL(p,4, file_len >> 32); #else /* LARGE_SMB_OFF_T */ SIVAL(p,0,file_len); @@ -889,9 +896,16 @@ static int call_nt_transact_create(connection_struct *conn, put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; SIVAL(p,0,fmode); /* File Attributes. */ - p += 12; + p += 4; +#ifdef LARGE_SMB_OFF_T + SIVAL(p,0, file_len); + SIVAL(p,4, (file_len >> 32)); +#else /* LARGE_SMB_OFF_T */ + SIVAL(p,0,file_len); +#endif /* LARGE_SMB_OFF_T */ + p += 8; #ifdef LARGE_SMB_OFF_T - SIVAL(p,0, file_len & 0xFFFFFFFF); + SIVAL(p,0, file_len); SIVAL(p,4, (file_len >> 32)); #else /* LARGE_SMB_OFF_T */ SIVAL(p,0,file_len); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e956ab6cd9..38c39efad6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1792,7 +1792,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s startpos = IVAL(inbuf,smb_vwv1); #ifdef LARGE_SMB_OFF_T - if(SVAL(inbuf,smb_wct) == 10) { + if(CVAL(inbuf,smb_wct) == 10) { /* * This is a large offset (64 bit) read. */ @@ -2007,7 +2007,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt data = smb_buf(outbuf); #ifdef LARGE_SMB_OFF_T - if(SVAL(inbuf,smb_wct) == 12) { + if(CVAL(inbuf,smb_wct) == 12) { /* * This is a large offset (64 bit) read. */ @@ -2265,7 +2265,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng data = smb_base(inbuf) + smb_doff; #ifdef LLARGE_SMB_OFF_T - if(SVAL(inbuf,smb_wct) == 14) { + if(CVAL(inbuf,smb_wct) == 14) { /* * This is a large offset (64 bit) write. */ -- cgit From cd5d4d5c12395fc55cca5048ff368d52717ab9cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 Sep 1998 19:49:55 +0000 Subject: Fixed problems people were having with creating profile directories (NTTrans/Create with Security Descriptor for a directory). It turns out the CIFS spec is bogus (what a suprise) and the 'is a directory' flag is actually embedded in the create_options field. Jeremy. (This used to be commit 68750d8153f01bd0802bb86e93c3ca5d11acb199) --- source3/smbd/nttrans.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5052e6d52a..866d9938b1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -407,6 +407,7 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); + uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), ((uint32)sizeof(fname)-1)); int smb_ofun; @@ -521,7 +522,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * If it's a request for a directory open, deal with it separately. */ - if(flags & OPEN_DIRECTORY) { + if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; open_directory(fsp, conn, fname, smb_ofun, @@ -699,6 +700,7 @@ static int call_nt_transact_create(connection_struct *conn, uint32 file_attributes = IVAL(params,20); uint32 share_access = IVAL(params,24); uint32 create_disposition = IVAL(params,28); + uint32 create_options = IVAL(params,32); uint32 fname_len = MIN(((uint32)IVAL(params,44)), ((uint32)sizeof(fname)-1)); int smb_ofun; @@ -781,7 +783,7 @@ static int call_nt_transact_create(connection_struct *conn, * If it's a request for a directory open, deal with it separately. */ - if(flags & OPEN_DIRECTORY) { + if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; -- cgit From cabc8f6d3192a4d3e23234948419fc9c1d11b5fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 Sep 1998 20:43:50 +0000 Subject: Mapped correct open modes for READ_CONTROL access. Jeremy. (This used to be commit 4a62b73633b8f8707a2961b355d4997f429c86bc) --- source3/smbd/nttrans.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 866d9938b1..95adc5ccb7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -324,9 +324,10 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi } if (smb_open_mode == -1) { - if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) + if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES| + WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS)) smb_open_mode = 2; - else if( desired_access & FILE_EXECUTE) + else if(desired_access & (FILE_EXECUTE|READ_CONTROL_ACCESS)) smb_open_mode = 0; else { DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n", -- cgit From ac9b687cc2496409e1c8d86393812faf94ec7550 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Sep 1998 19:16:12 +0000 Subject: configure configure.in: Added tests for fseek64 and ftell64. config.h.in: Added fseek64 and ftell64. includes.h: Added definition of SMB_BIG_INTEGER. smb.h: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. access.c: Tidyup of dbug statement. system.c: Added sys_fseek and sys_ftell. Changed mode calls to use mode_t. asyncdns.c: Tidyup of comment. loadparm.c: Tidyup of set_default_server_announce_type() function definition. ldap.c: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. nispass.c: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. smbpass.c: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. smbpassfile.c: Use sys_fseek(). chgpasswd.c: Tidyup of debug statement. dosmode.c: Changed mode calls to use mode_t. ipc.c: Removal of dead code. nttrans.c: Changed mode calls to use mode_t. open.c: Changed mode calls to use mode_t. pipes.c: Removal of dead code. reply.c: Removal of dead code. trans2.c: Removal of dead code. Changed mode calls to use mode_t. Jeremy. (This used to be commit c381d32e3dc23fe887408016cae821aceb30da2c) --- source3/smbd/chgpasswd.c | 4 ++-- source3/smbd/dosmode.c | 2 +- source3/smbd/ipc.c | 24 ++++++++---------------- source3/smbd/nttrans.c | 9 +++++---- source3/smbd/open.c | 10 +++++----- source3/smbd/pipes.c | 3 --- source3/smbd/reply.c | 30 ++++++------------------------ source3/smbd/trans2.c | 7 ++----- 8 files changed, 29 insertions(+), 60 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 68cbe9b35b..4dc6d29e3c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -302,12 +302,12 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc /* allocate a pseudo-terminal device */ if ((master = findpty (&slavedev)) < 0) { - DEBUG(3,("Cannot Allocate pty for password change: %s",name)); + DEBUG(3,("Cannot Allocate pty for password change: %s\n",name)); return(False); } if ((pid = fork()) < 0) { - DEBUG(3,("Cannot fork() child for password change: %s",name)); + DEBUG(3,("Cannot fork() child for password change: %s\n",name)); close(master); return(False); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 1336e27281..c2c9cc2373 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -144,7 +144,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * SMB_STRUCT_STAT st1; int mask=0; int tmp; - int unixmode; + mode_t unixmode; if (!st) { st = &st1; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 61d9aa8bdd..ce300dc810 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -784,7 +784,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); char *QueueName = p; - int uLevel,cbBuf; + int uLevel; int count=0; int snum; char* str3; @@ -797,7 +797,6 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, p = skip_string(p,1); uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); str3 = p + 4; /* remove any trailing username */ @@ -2670,7 +2669,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int uLevel,cbBuf; + int uLevel; int count; int i; int snum; @@ -2680,7 +2679,6 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para print_status_struct status; uLevel = SVAL(p,2); - cbBuf = SVAL(p,4); bzero(&desc,sizeof(desc)); bzero(&status,sizeof(status)); @@ -2735,7 +2733,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); char* name = p; - int uLevel,cbBuf; + int uLevel; int count; int i, succnt=0; int snum; @@ -2748,7 +2746,6 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa p = skip_string(p,1); uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); @@ -2853,7 +2850,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); char* PrinterName = p; - int uLevel,cbBuf; + int uLevel; struct pack_desc desc; int snum; @@ -2861,7 +2858,6 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par p = skip_string(p,1); uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); @@ -2911,7 +2907,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int uLevel,cbBuf; + int uLevel; int queuecnt; int i, n, succnt=0; struct pack_desc desc; @@ -2920,7 +2916,6 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, bzero(&desc,sizeof(desc)); uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); @@ -2969,14 +2964,13 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int uLevel,cbBuf; + int uLevel; int succnt; struct pack_desc desc; bzero(&desc,sizeof(desc)); uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); @@ -3014,14 +3008,13 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int uLevel,cbBuf; + int uLevel; int succnt; struct pack_desc desc; bzero(&desc,sizeof(desc)); uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); @@ -3060,14 +3053,13 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int uLevel,cbBuf; + int uLevel; int succnt; struct pack_desc desc; bzero(&desc,sizeof(desc)); uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 95adc5ccb7..d6d60c45cd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -417,8 +417,9 @@ int reply_ntcreate_and_X(connection_struct *conn, /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - int unixmode, pnum = -1; - int fmode=0,mtime=0,rmode=0; + mode_t unixmode; + int pnum = -1; + int fmode=0,rmode=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int smb_action = 0; @@ -619,7 +620,6 @@ int reply_ntcreate_and_X(connection_struct *conn, fmode = dos_mode(conn,fname,&sbuf); if(fmode == 0) fmode = FILE_ATTRIBUTE_NORMAL; - mtime = sbuf.st_mtime; if (!fsp->is_directory && (fmode & aDIR)) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); @@ -710,7 +710,8 @@ static int call_nt_transact_create(connection_struct *conn, /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - int unixmode, pnum = -1; + mode_t unixmode; + int pnum = -1; int fmode=0,mtime=0,rmode=0; off_t file_len = 0; SMB_STRUCT_STAT sbuf; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 42b0fba425..ad4dd9f52f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -31,7 +31,7 @@ extern uint16 oplock_port; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ -static int fd_attempt_open(char *fname, int flags, int mode) +static int fd_attempt_open(char *fname, int flags, mode_t mode) { int fd = dos_open(fname,flags,mode); @@ -125,7 +125,7 @@ static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) fd support routines - attempt to re-open an already open fd as O_RDWR. Save the already open fd (we cannot close due to POSIX file locking braindamage. ****************************************************************************/ -static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) +static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) { int fd = dos_open( fname, O_RDWR, mode); @@ -268,7 +268,7 @@ static void check_for_pipe(char *fname) open a file ****************************************************************************/ static void open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,int mode, SMB_STRUCT_STAT *sbuf) + char *fname1,int flags,mode_t mode, SMB_STRUCT_STAT *sbuf) { extern struct current_user current_user; pstring fname; @@ -688,7 +688,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, open a file with a share mode ****************************************************************************/ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, - int mode,int oplock_request, int *Access,int *action) + mode_t mode,int oplock_request, int *Access,int *action) { int flags=0; int flags2=0; @@ -865,7 +865,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - flags,flags2,mode)); + flags,flags2,(int)mode)); open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen) diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 97df3abfc3..15d395b29a 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -119,7 +119,6 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) int smb_mincnt = SVAL(inbuf,smb_vwv6); int nread = -1; char *data; - BOOL ok = False; if (!p) return(ERROR(ERRDOS,ERRbadfid)); @@ -128,8 +127,6 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) nread = read_pipe(p, data, smb_offs, smb_maxcnt); - ok = True; - if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 38c39efad6..d7f29b60c6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -453,9 +453,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int int gid; int uid; int smb_bufsize; - int smb_mpxmax; - int smb_vc_num; - uint32 smb_sesskey; int smb_apasslen = 0; pstring smb_apasswd; int smb_ntpasslen = 0; @@ -472,9 +469,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); - smb_mpxmax = SVAL(inbuf,smb_vwv3); - smb_vc_num = SVAL(inbuf,smb_vwv4); - smb_sesskey = IVAL(inbuf,smb_vwv5); if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); @@ -1247,7 +1241,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int share_mode; SMB_OFF_T size = 0; time_t mtime=0; - int unixmode; + mode_t unixmode; int rmode=0; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; @@ -1344,7 +1338,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); #endif int smb_ofun = SVAL(inbuf,smb_vwv8); - int unixmode; + mode_t unixmode; SMB_OFF_T size=0; int fmode=0,mtime=0,rmode=0; SMB_STRUCT_STAT sbuf; @@ -1770,8 +1764,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s SMB_OFF_T startpos; char *header = outbuf; ssize_t ret=0; - int fd; - char *fname; files_struct *fsp; /* @@ -1818,12 +1810,8 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s _smb_setlen(header,0); transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); return(-1); - } else { - fd = fsp->fd_ptr->fd; - fname = fsp->fsp_name; } - if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) { SMB_OFF_T size = fsp->size; @@ -1855,19 +1843,19 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #if USE_READ_PREDICTION if (!fsp->can_write) - predict = read_predict(fd,startpos,header+4,NULL,nread); + predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread); #endif /* USE_READ_PREDICTION */ if ((nread-predict) > 0) seek_file(fsp,startpos + predict); - ret = (ssize_t)transfer_file(fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict, + ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } if (ret != nread+4) DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n", - fname,startpos,nread,ret)); + fsp->fsp_name,startpos,nread,ret)); #else /* UNSAFE_READRAW */ ret = read_file(fsp,header+4,startpos,nread); @@ -1993,7 +1981,6 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt size_t smb_mincnt = SVAL(inbuf,smb_vwv6); ssize_t nread = -1; char *data; - BOOL ok = False; /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) @@ -2018,7 +2005,6 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); nread = read_file(fsp,data,startpos,smb_maxcnt); - ok = True; if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2718,9 +2704,6 @@ int reply_printqueue(connection_struct *conn, int outsize = set_message(outbuf,2,3,True); int max_count = SVAL(inbuf,smb_vwv0); int start_index = SVAL(inbuf,smb_vwv1); - uint16 vuid; - - vuid = SVAL(inbuf,smb_uid); /* we used to allow the client to get the cnum wrong, but that is really quite gross and only worked when there was only @@ -3722,7 +3705,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, char *data; SMB_OFF_T startpos; int outsize; - size_t mincount, maxcount; + size_t maxcount; int max_per_packet; size_t tcount; int pad; @@ -3740,7 +3723,6 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, startpos = IVAL(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); - mincount = SVAL(inbuf,smb_vwv4); data = smb_buf(outbuf); pad = ((long)data)%4; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 87d1ea27d0..fb93fd9e10 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -199,7 +199,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int16 namelen = strlen(pname)+1; pstring fname; - int unixmode; + mode_t unixmode; SMB_OFF_T size=0; int fmode=0,mtime=0,rmode; SMB_INO_T inode = 0; @@ -307,14 +307,13 @@ static int get_lanman2_dir_entry(connection_struct *conn, pstring mask; pstring pathreal; pstring fname; - BOOL matched; char *p, *pdata = *ppdata; uint32 reskey=0; int prev_dirpos=0; int mode=0; SMB_OFF_T size = 0; uint32 len; - uint32 mdate=0, adate=0, cdate=0; + time_t mdate=0, adate=0, cdate=0; char *nameptr; BOOL isrootdir = (strequal(conn->dirpath,"./") || strequal(conn->dirpath,".") || @@ -361,8 +360,6 @@ static int get_lanman2_dir_entry(connection_struct *conn, if (!dname) return(False); - matched = False; - pstrcpy(fname,dname); if(mask_match(fname, mask, case_sensitive, True)) -- cgit From b8b67f4fab4a6fd686c5796c2701882197a7bd9d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Sep 1998 23:06:57 +0000 Subject: configure configure.in: Added checks for statvfs64. Last bit of 64 bit widening (I hope :-). include/config.h.in: Added #undef STAT_STATVFS64. include/includes.h: Added SMB_STRUCT_STATVFS type, Changed SMB_BIG_INTEGER to SMB_BIG_UINT and SMB_BIG_INT types. include/smb.h: Added flag defines from CIFS spec. lib/debug.c: Fixed one more mode_t issue. lib/system.c: Added sys_statvfs wrapper. lib/util.c: Changed trim_string to use size_t. param/loadparm.c: Moved "blocking locks" into locking section. Alphabetised locking options. Question - shuld we do this for all options ? passdb/ldap.c: Changed SMB_BIG_INTEGER to SMB_BIG_UINT. passdb/nispass.c: Changed SMB_BIG_INTEGER to SMB_BIG_UINT. passdb/smbpass.c: Changed SMB_BIG_INTEGER to SMB_BIG_UINT. smbd/dfree.c: Changed to use 64 bit types if available. Moved to use unsigned types. smbd/dosmode.c: Fixed one more mode_t issue. smbd/negprot.c: Changed literals to be FLAG_ #defines. smbd/nttrans.c: Removed dead code. smbd/open.c: Changed disk_free call. smbd/process.c: Changed literals to be FLAG_ #defines. smbd/reply.c: Changed disk_free call. smbd/trans2.c: Fixed but in SMB_QUERY_FS_VOLUME_INFO call. Was using UNICODE - should use ascii. tests/summary.c: Added STAT_STATVFS64 check. Jeremy. (This used to be commit c512b1b91fb7f2a7a93b9033a33e06d966daadb4) --- source3/smbd/dfree.c | 40 +++++++++++++++++----------------------- source3/smbd/dosmode.c | 2 +- source3/smbd/negprot.c | 10 ++++++---- source3/smbd/nttrans.c | 3 +-- source3/smbd/open.c | 7 +++---- source3/smbd/process.c | 4 ++-- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 23 ++++++++++++++++------- 8 files changed, 47 insertions(+), 44 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 799ff6a24c..499d089260 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -27,10 +27,10 @@ extern int DEBUGLEVEL; /**************************************************************************** normalise for DOS usage ****************************************************************************/ -static void disk_norm(int *bsize,int *dfree,int *dsize) +static void disk_norm(SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { /* check if the disk is beyond the max disk size */ - int maxdisksize = lp_maxdisksize(); + SMB_BIG_UINT maxdisksize = lp_maxdisksize(); if (maxdisksize) { /* convert to blocks - and don't overflow */ maxdisksize = ((maxdisksize*1024)/(*bsize))*1024; @@ -58,19 +58,15 @@ static void disk_norm(int *bsize,int *dfree,int *dsize) /* Return the number of TOSIZE-byte blocks used by BLOCKS FROMSIZE-byte blocks, rounding away from zero. - TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */ -static int adjust_blocks(int blocks, int fromsize, int tosize) +*/ +static SMB_BIG_UINT adjust_blocks(SMB_BIG_UINT blocks, SMB_BIG_UINT fromsize, SMB_BIG_UINT tosize) { - if (tosize <= 0 || fromsize <= 0) { - return -1; - } - if (fromsize == tosize) /* e.g., from 512 to 512 */ return blocks; else if (fromsize > tosize) /* e.g., from 2048 to 512 */ return blocks * (fromsize / tosize); else /* e.g., from 256 to 512 */ - return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize); + return (blocks + 1) / (tosize / fromsize); } /* this does all of the system specific guff to get the free disk space. @@ -79,10 +75,10 @@ static int adjust_blocks(int blocks, int fromsize, int tosize) results are returned in *dfree and *dsize, in 512 byte units */ -static int fsusage(const char *path, int *dfree, int *dsize) +static int fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { #ifdef STAT_STATFS3_OSF1 -#define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512) +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) struct statfs fsd; if (statfs (path, &fsd, sizeof (struct statfs)) != 0) @@ -90,7 +86,7 @@ static int fsusage(const char *path, int *dfree, int *dsize) #endif /* STAT_STATFS3_OSF1 */ #ifdef STAT_STATFS2_FS_DATA /* Ultrix */ -#define CONVERT_BLOCKS(B) adjust_blocks ((B), 1024, 512) +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)1024, (SMB_BIG_UINT)512) struct fs_data fsd; if (statfs (path, &fsd) != 1) @@ -101,7 +97,7 @@ static int fsusage(const char *path, int *dfree, int *dsize) #endif /* STAT_STATFS2_FS_DATA */ #ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ -#define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512) +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) struct statfs fsd; if (statfs (path, &fsd) < 0) @@ -123,7 +119,7 @@ static int fsusage(const char *path, int *dfree, int *dsize) #ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ -#define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512) +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) struct statfs fsd; @@ -133,12 +129,12 @@ static int fsusage(const char *path, int *dfree, int *dsize) #ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ # if _AIX || defined(_CRAY) -# define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512) +# define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) # ifdef _CRAY # define f_bavail f_bfree # endif # else -# define CONVERT_BLOCKS(B) (B) +# define CONVERT_BLOCKS(B) ((SMB_BIG_UINT)B) # ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ # ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ # define f_bavail f_bfree @@ -158,11 +154,11 @@ static int fsusage(const char *path, int *dfree, int *dsize) #ifdef STAT_STATVFS /* SVR4 */ # define CONVERT_BLOCKS(B) \ - adjust_blocks ((B), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512) + adjust_blocks ((SMB_BIG_UINT)(B), fsd.f_frsize ? (SMB_BIG_UINT)fsd.f_frsize : (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) - struct statvfs fsd; + SMB_STRUCT_STATVFS fsd; - if (statvfs (path, &fsd) < 0) + if (sys_statvfs (path, &fsd) < 0) return -1; /* f_frsize isn't guaranteed to be supported. */ @@ -185,7 +181,7 @@ static int fsusage(const char *path, int *dfree, int *dsize) /**************************************************************************** return number of 1K blocks available on a path and total number ****************************************************************************/ -static int disk_free(char *path,int *bsize,int *dfree,int *dsize) +static SMB_BIG_UINT disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { int dfree_retval; @@ -223,9 +219,7 @@ static int disk_free(char *path,int *bsize,int *dfree,int *dsize) /**************************************************************************** wrap it to get filenames right ****************************************************************************/ -int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize) +SMB_BIG_UINT sys_disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize)); } - - diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index c2c9cc2373..b74e11e643 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -143,7 +143,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * { SMB_STRUCT_STAT st1; int mask=0; - int tmp; + mode_t tmp; mode_t unixmode; if (!st) { diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e9dd4614c4..e79743cfd4 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -50,7 +50,8 @@ static int reply_coreplus(char *outbuf) int outsize = set_message(outbuf,13,0,True); SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support readbraw and writebraw (possibly) */ - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + /* Reply, SMBlockread, SMBwritelock supported. */ + SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */ Protocol = PROTOCOL_COREPLUS; @@ -80,7 +81,8 @@ static int reply_lanman1(char *outbuf) Protocol = PROTOCOL_LANMAN1; - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + /* Reply, SMBlockread, SMBwritelock supported. */ + SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ SSVAL(outbuf,smb_vwv4,1); @@ -138,7 +140,8 @@ static int reply_lanman2(char *outbuf) Protocol = PROTOCOL_LANMAN2; - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ + /* Reply, SMBlockread, SMBwritelock supported. */ + SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); SSVAL(outbuf,smb_vwv4,1); @@ -417,4 +420,3 @@ int reply_negprot(connection_struct *conn, return(outsize); } - diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d6d60c45cd..ca977c39dc 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -712,7 +712,7 @@ static int call_nt_transact_create(connection_struct *conn, int oplock_request = 0; mode_t unixmode; int pnum = -1; - int fmode=0,mtime=0,rmode=0; + int fmode=0,rmode=0; off_t file_len = 0; SMB_STRUCT_STAT sbuf; int smb_action = 0; @@ -834,7 +834,6 @@ static int call_nt_transact_create(connection_struct *conn, fmode = dos_mode(conn,fname,&sbuf); if(fmode == 0) fmode = FILE_ATTRIBUTE_NORMAL; - mtime = sbuf.st_mtime; if (fmode & aDIR) { close_file(fsp,False); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ad4dd9f52f..108ef814ee 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -444,13 +444,12 @@ static void open_file(files_struct *fsp,connection_struct *conn, if ((fd_ptr->fd >=0) && conn->printer && lp_minprintspace(SNUM(conn))) { pstring dname; - int dum1,dum2,dum3; + SMB_BIG_UINT dum1,dum2,dum3; char *p; pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (sys_disk_free(dname,&dum1,&dum2,&dum3) < - lp_minprintspace(SNUM(conn))) { + if (sys_disk_free(dname,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { if(fd_attempt_close(fd_ptr) == 0) dos_unlink(fname); fsp->fd_ptr = 0; @@ -957,7 +956,7 @@ dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)ino Open a directory from an NT SMB call. ****************************************************************************/ int open_directory(files_struct *fsp,connection_struct *conn, - char *fname, int smb_ofun, int unixmode, int *action) + char *fname, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; SMB_STRUCT_STAT st; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b72178013d..1d6de37df0 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -501,9 +501,9 @@ void construct_reply_common(char *inbuf,char *outbuf) memcpy(outbuf+4,inbuf+4,4); CVAL(outbuf,smb_rcls) = SMB_SUCCESS; CVAL(outbuf,smb_reh) = 0; - CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set + SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set means a reply */ - SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS); /* say we support long filenames */ SSVAL(outbuf,smb_err,SMB_SUCCESS); SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d7f29b60c6..93beb12af3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -921,7 +921,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; - int dfree,dsize,bsize; + SMB_BIG_UINT dfree,dsize,bsize; sys_disk_free(".",&bsize,&dfree,&dsize); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fb93fd9e10..49687d4cca 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1094,7 +1094,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { case 1: { - int dfree,dsize,bsize; + SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; sys_disk_free(".",&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); @@ -1102,8 +1102,9 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,l1_cUnit,dsize); SIVAL(pdata,l1_cUnitAvail,dfree); SSVAL(pdata,l1_cbSector,512); - DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n", - bsize, (unsigned)st.st_dev, bsize/512, dsize, dfree, 512)); + DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n", + (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize, + (unsigned int)dfree, 512)); break; } case 2: @@ -1132,6 +1133,7 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,4,128); /* Max filename component length */ SIVAL(pdata,8,2*strlen(FSTYPE_STRING)); PutUniCode(pdata+12,FSTYPE_STRING); + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); break; case SMB_QUERY_FS_LABEL_INFO: data_len = 4 + strlen(vname); @@ -1139,20 +1141,27 @@ static int call_trans2qfsinfo(connection_struct *conn, pstrcpy(pdata+4,vname); break; case SMB_QUERY_FS_VOLUME_INFO: - data_len = 18 + 2*strlen(vname); + + /* + * NB: The earlier CIFS spec that says this always + * uses UNICODE is incorrect ! JRA. + */ + + data_len = 18 + strlen(vname); + /* * Add volume serial number - hash of a combination of * the called hostname and the service name. */ SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - SIVAL(pdata,12,2*strlen(vname)); - PutUniCode(pdata+18,vname); + SIVAL(pdata,12,strlen(vname)); + pstrcpy(pdata+18,vname); DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), vname)); break; case SMB_QUERY_FS_SIZE_INFO: { - int dfree,dsize,bsize; + SMB_BIG_UINT dfree,dsize,bsize; data_len = 24; sys_disk_free(".",&bsize,&dfree,&dsize); SIVAL(pdata,0,dsize); -- cgit From 6dfbe2fa1a1d6eb5de05c8f5516c891abe7bdb74 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Sep 1998 00:30:28 +0000 Subject: include/includes.h: lib/system.c: Can't assume every system has a statvfs varient. Return -1 for those that don't. smbd/reply.c: Fixed printf warning. Jeremy. (This used to be commit 14c134e8316687aa5a4ee089c2acfa6428faceae) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 93beb12af3..c4aadb9dad 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -932,7 +932,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz SSVAL(outbuf,smb_vwv2,512); SSVAL(outbuf,smb_vwv3,dfree); - DEBUG(3,("dskattr dfree=%d\n", dfree)); + DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree)); return(outsize); } -- cgit From 55c492fba1da31bc82de5bba5e19dec54b18e2ce Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 1998 02:26:36 +0000 Subject: fixed a usage of off_t that should have been SMB_OFF_T (This used to be commit 24ae7657011929fd3529caa909f3afe866186cd2) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ca977c39dc..ee3385f152 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -713,7 +713,7 @@ static int call_nt_transact_create(connection_struct *conn, mode_t unixmode; int pnum = -1; int fmode=0,rmode=0; - off_t file_len = 0; + SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; -- cgit From b3b44e02f3c0c2f6c4b66bc112e546a08ef45316 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 1998 02:27:24 +0000 Subject: removed another use of the LL suffix. Hopefully this is the last one (a grep doesn't show any more) (This used to be commit c1bd188744b0df950f2e00550c25f7d3e148094b) --- source3/smbd/open.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 108ef814ee..a02fe91e68 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -562,27 +562,25 @@ static void open_file(files_struct *fsp,connection_struct *conn, static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, BOOL *share_locked) { - if (fsp->can_write){ -#ifdef LARGE_SMB_OFF_T - if (is_locked(fsp,conn,0x3FFFFFFFFFFFFFFFLL,0,F_WRLCK)){ -#else - if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){ -#endif - /* If share modes are in force for this connection we - have the share entry locked. Unlock it before closing. */ - if (*share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, token); - close_file(fsp,False); - /* Share mode no longer locked. */ - *share_locked = False; - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRlock; - } - else - sys_ftruncate(fsp->fd_ptr->fd,0); - } + if (fsp->can_write){ + SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4); + + if (is_locked(fsp,conn,~mask,0,F_WRLCK)){ + /* If share modes are in force for this connection we + have the share entry locked. Unlock it before closing. */ + if (*share_locked && lp_share_modes(SNUM(conn))) + unlock_share_entry( conn, fsp->fd_ptr->dev, + fsp->fd_ptr->inode, token); + close_file(fsp,False); + /* Share mode no longer locked. */ + *share_locked = False; + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRlock; + } else { + sys_ftruncate(fsp->fd_ptr->fd,0); + } + } } -- cgit From bc3766c5bc55ac7744aaf8cd6871c11b8bf2cfb3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 1998 02:28:21 +0000 Subject: fixed a typo (LLARGE_SMB_OFF_T instead of LARGE_SMB_OFF_T) (This used to be commit 3e77d94cd2d693490265b60ad7c576a25902d8ea) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c4aadb9dad..1aa4cb988e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2250,7 +2250,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng data = smb_base(inbuf) + smb_doff; -#ifdef LLARGE_SMB_OFF_T +#ifdef LARGE_SMB_OFF_T if(CVAL(inbuf,smb_wct) == 14) { /* * This is a large offset (64 bit) write. -- cgit From c7da9992cb39fc84a6a915dd2158beaf5e616617 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 1998 03:00:20 +0000 Subject: gto ri of a bunch more #ifdef LARGE_SMB_OFF_T checks by introducing a SOFF_T() macro for setting an SMB_OFF_T variable also limited mmap based reads to MAX_MMAP_SIZE. We really can't mmap 2^50 bytes due to virtual address space problems. (This used to be commit 4e784b18899eddd2399a51fa7d8c219560432922) --- source3/smbd/fileio.c | 22 +++++++++------------- source3/smbd/negprot.c | 7 ++----- source3/smbd/nttrans.c | 30 +++++------------------------- source3/smbd/open.c | 16 +++++++++------- source3/smbd/trans2.c | 45 +++++++++++---------------------------------- 5 files changed, 36 insertions(+), 84 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index d40c159798..5c4bf7dfc2 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -63,19 +63,15 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #if WITH_MMAP if (fsp->mmap_ptr) { - SMB_OFF_T num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; - num = MIN(n,num); -#ifdef LARGE_SMB_OFF_T - if ((num > 0) && (num < (1LL<<(sizeof(size_t)*8)))) { -#else /* LARGE_SMB_OFF_T */ - if (num > 0) { -#endif /* LARGE_SMB_OFF_T */ - memcpy(data,fsp->mmap_ptr+pos,num); - data += num; - pos += num; - n -= num; - ret += num; - } + SMB_OFF_T num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; + num = MIN(n,num); + if (num > 0) { + memcpy(data,fsp->mmap_ptr+pos,num); + data += num; + pos += num; + n -= num; + ret += num; + } } #endif diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e79743cfd4..d4e6180261 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -161,11 +161,8 @@ static int reply_nt1(char *outbuf) /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | -#ifdef LARGE_SMB_OFF_T - (sizeof(SMB_OFF_T) == 8 ? CAP_LARGE_FILES : 0); -#else - 0; -#endif + (SMB_OFF_T_BITS == 64 ? CAP_LARGE_FILES : 0); + /* other valid capabilities which we may support at some time... diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ee3385f152..2d991eef20 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -663,20 +663,10 @@ int reply_ntcreate_and_X(connection_struct *conn, put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; SIVAL(p,0,fmode); /* File Attributes. */ - p += 4; -#ifdef LARGE_SMB_OFF_T - SIVAL(p,0, file_len); - SIVAL(p,4, file_len >> 32); -#else /* LARGE_SMB_OFF_T */ - SIVAL(p,0,file_len); -#endif /* LARGE_SMB_OFF_T */ + p += 4; + SOFF_T(p, 0, file_len); p += 8; -#ifdef LARGE_SMB_OFF_T - SIVAL(p,0, file_len); - SIVAL(p,4, file_len >> 32); -#else /* LARGE_SMB_OFF_T */ - SIVAL(p,0,file_len); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(p,0,file_len); p += 12; SCVAL(p,0,fsp->is_directory ? 1 : 0); @@ -900,19 +890,9 @@ static int call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; -#ifdef LARGE_SMB_OFF_T - SIVAL(p,0, file_len); - SIVAL(p,4, (file_len >> 32)); -#else /* LARGE_SMB_OFF_T */ - SIVAL(p,0,file_len); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(p,0,file_len); p += 8; -#ifdef LARGE_SMB_OFF_T - SIVAL(p,0, file_len); - SIVAL(p,4, (file_len >> 32)); -#else /* LARGE_SMB_OFF_T */ - SIVAL(p,0,file_len); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(p,0,file_len); } /* Send the required number of replies */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a02fe91e68..394c7be3f8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -541,13 +541,15 @@ static void open_file(files_struct *fsp,connection_struct *conn, /* mmap it if read-only */ if (!fsp->can_write) { fsp->mmap_size = file_size(fname); - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); - - if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { - DEBUG(3,("Failed to mmap() %s - %s\n", - fname,strerror(errno))); - fsp->mmap_ptr = NULL; + if (fsp->mmap_size < MAX_MMAP_SIZE) { + fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, + PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + + if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { + DEBUG(3,("Failed to mmap() %s - %s\n", + fname,strerror(errno))); + fsp->mmap_ptr = NULL; + } } } #endif diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 49687d4cca..fe2869db93 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -489,12 +489,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); - SIVAL(p,8,size); -#ifdef LARGE_SMB_OFF_T - SIVAL(p,4,size >> 32); - SIVAL(p,12,size >> 32); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(p,0,size); + SOFF_T(p,8,size); p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; @@ -522,12 +518,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); - SIVAL(p,8,size); -#ifdef LARGE_SMB_OFF_T - SIVAL(p,4,size >> 32); - SIVAL(p,12,size >> 32); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(p,0,size); + SOFF_T(p,8,size); p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; @@ -545,12 +537,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); - SIVAL(p,8,size); -#ifdef LARGE_SMB_OFF_T - SIVAL(p,4,size >> 32); - SIVAL(p,12,size >> 32); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(p,0,size); + SOFF_T(p,8,size); p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; @@ -1349,12 +1337,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_STANDARD_INFO: data_size = 22; - SIVAL(pdata,0,size); - SIVAL(pdata,8,size); -#ifdef LARGE_SMB_OFF_T - SIVAL(pdata,4,size>>32); - SIVAL(pdata,12,size>>32); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(pdata,0,size); + SOFF_T(pdata,8,size); SIVAL(pdata,16,sbuf.st_nlink); CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; @@ -1392,10 +1376,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_ALLOCATION_INFO: case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; - SIVAL(pdata,0,size); -#ifdef LARGE_SMB_OFF_T - SIVAL(pdata,4,size >> 32); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(pdata,0,size); break; case SMB_QUERY_FILE_ALL_INFO: @@ -1405,12 +1386,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); pdata += 40; - SIVAL(pdata,0,size); - SIVAL(pdata,8,size); -#ifdef LARGE_SMB_OFF_T - SIVAL(pdata,4,size >> 32); - SIVAL(pdata,12,size >> 32); -#endif /* LARGE_SMB_OFF_T */ + SOFF_T(pdata,0,size); + SOFF_T(pdata,8,size); SIVAL(pdata,16,sbuf.st_nlink); CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; -- cgit From d1a82e643b2e75db8e0c5afa7280ca383917ba64 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 1998 03:53:14 +0000 Subject: got rid of SMB_STRUCT_STATVFS. I don't think we should be defining structures that only apply on some platforms. (This used to be commit 926591067cd8646426ca06df0b00a1d6f6dd5752) --- source3/smbd/dfree.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 499d089260..c96a599e77 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -156,10 +156,14 @@ static int fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) # define CONVERT_BLOCKS(B) \ adjust_blocks ((SMB_BIG_UINT)(B), fsd.f_frsize ? (SMB_BIG_UINT)fsd.f_frsize : (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) - SMB_STRUCT_STATVFS fsd; +#ifdef STAT_STATVFS64 + struct statvfs64 fsd; + if (statvfs64(path, &fsd) < 0) return -1; +#else + struct statvfs fsd; + if (statvfs(path, &fsd) < 0) return -1; +#endif - if (sys_statvfs (path, &fsd) < 0) - return -1; /* f_frsize isn't guaranteed to be supported. */ #endif /* STAT_STATVFS */ -- cgit From 184db9266efcbcea13169f99002b32208dc2ec9b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Sep 1998 17:50:18 +0000 Subject: configure configure.in include/config.h.in include/includes.h Fixed bugs in readline autoconf. param/loadparm.c smbd/open.c smbd/oplock.c: Started on kernel oplock code - checking forced by above issue. Should not be used currently. Jeremy. (This used to be commit f939efac9e6c45331b17e3d3aa6bc2235e886c1a) --- source3/smbd/open.c | 20 ++++++++++++----- source3/smbd/oplock.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 394c7be3f8..abbc0d6741 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -687,7 +687,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, open a file with a share mode ****************************************************************************/ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, - mode_t mode,int oplock_request, int *Access,int *action) + mode_t mode,int *oplock_request, int *Access,int *action) { int flags=0; int flags2=0; @@ -922,24 +922,34 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou be extended to level II oplocks (multiple reader oplocks). */ - if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && + if((*oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && !IS_VETO_OPLOCK_PATH(conn,fname)) { +#if defined(HAVE_KERNEL_OPLOCKS) + /* + * Try and get a *real* oplock on this file. + * If we fail, set the port and oplock request to + * zero so that we don't tell other SMB's that we + * got an oplock. + */ + if(lp_kernel_oplocks()) +#endif /* HAVE_KERNEL_OPLOCKS */ + fsp->granted_oplock = True; fsp->sent_oplock_break = False; global_oplocks_open++; port = oplock_port; DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); +dev = %x, inode = %.0f\n", *oplock_request, fname, (unsigned int)dev, (double)inode)); } else { port = 0; - oplock_request = 0; + *oplock_request = 0; } - set_share_mode(token, fsp, port, oplock_request); + set_share_mode(token, fsp, port, *oplock_request); } if ((flags2&O_TRUNC) && file_existed) diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 348e29dbe2..962043380d 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -26,7 +26,11 @@ extern int DEBUGLEVEL; /* Oplock ipc UDP socket. */ int oplock_sock = -1; uint16 oplock_port = 0; +#if defined(HAVE_KERNEL_OPLOCKS) +static int oplock_pipes[2]; +#endif /* HAVE_KERNEL_OPLOCKS */ +int oplock /* Current number of oplocks we have outstanding. */ int32 global_oplocks_open = 0; BOOL global_oplock_break = False; @@ -678,3 +682,60 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) return False; } +void check_kernel_oplocks(BOOL *have_oplocks) +{ + static BOOL done; + int fd; + int pfd[2]; + pstring tmpname; + + /* + * We only do this check once on startup. + */ + + if(done) + return; + + done = True; + *have_oplocks = False + +#if defined(HAVE_KERNEL_OPLOCKS) + slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid()); + mktemp(tmpname); + + if(pipe(pfd) != 0) { + DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", + strerror(errno) )); + return; + } + + if((fd = open(tmpname, O_RDWR)) < 0) { + DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", + tmpname, strerror(errno) )); + unlink( tmpname ); + close(pfd[0]); + close(pfd[1]); + return; + } + + unlink( tmpname ); + + if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { + DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ +Disabling kernel oplock supprt.\n" )); + close(pfd[0]); + close(pfd[1]); + close(fd); + return; + } + + fcntl(fd, F_OPLKACK, OP_REVOKE); + close(pfd[0]); + close(pfd[1]); + close(fd); + + DEBUG(3,("check_kernel_oplocks: Kernel oplocks enabled.\n")); + + *have_oplocks = True; +#endif /* HAVE_KERNEL_OPLOCKS */ +} -- cgit From 31ebc956e5f17fef8411b5fef1a6529df072df2a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Sep 1998 18:09:17 +0000 Subject: Fixed problems with premature kernel oplock checkin code. The ./configure & build now seem to work ok. Jeremy. (This used to be commit 7c1a5ed1c2a55543d3f3c8bbd38e6c9c35b80390) --- source3/smbd/open.c | 10 +++++----- source3/smbd/oplock.c | 3 +-- source3/smbd/reply.c | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index abbc0d6741..0d8fcddbe5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -687,7 +687,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, open a file with a share mode ****************************************************************************/ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, - mode_t mode,int *oplock_request, int *Access,int *action) + mode_t mode,int oplock_request, int *Access,int *action) { int flags=0; int flags2=0; @@ -922,7 +922,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou be extended to level II oplocks (multiple reader oplocks). */ - if((*oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && + if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && !IS_VETO_OPLOCK_PATH(conn,fname)) { #if defined(HAVE_KERNEL_OPLOCKS) @@ -941,15 +941,15 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou port = oplock_port; DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", *oplock_request, fname, (unsigned int)dev, (double)inode)); +dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); } else { port = 0; - *oplock_request = 0; + oplock_request = 0; } - set_share_mode(token, fsp, port, *oplock_request); + set_share_mode(token, fsp, port, oplock_request); } if ((flags2&O_TRUNC) && file_existed) diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 962043380d..94e8559d2a 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -30,7 +30,6 @@ uint16 oplock_port = 0; static int oplock_pipes[2]; #endif /* HAVE_KERNEL_OPLOCKS */ -int oplock /* Current number of oplocks we have outstanding. */ int32 global_oplocks_open = 0; BOOL global_oplock_break = False; @@ -697,7 +696,7 @@ void check_kernel_oplocks(BOOL *have_oplocks) return; done = True; - *have_oplocks = False + *have_oplocks = False; #if defined(HAVE_KERNEL_OPLOCKS) slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid()); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1aa4cb988e..ad1894358a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1373,7 +1373,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unixmode = unix_mode(conn,smb_attr | aARCH); open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode, - oplock_request, &rmode,&smb_action); + oplock_request, &rmode,&smb_action); if (!fsp->open) { -- cgit From fc82bd2914c5687c0d03636ed05280c3506cea0c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Sep 1998 03:34:12 +0000 Subject: Small bit of paranioa. Ensure that if the incoming name to unix_convert() was a single '\' (the base directory of the service) that it gets translated to a '.', not a '\0'. Jeremy. (This used to be commit f74f39f45fa55c1768d6622a52c494328f22f50b) --- source3/smbd/filename.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index caba4064d7..7cbb3392cb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,7 +150,8 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) /* * Don't cache trivial valid directory entries. */ - if((strcmp(full_orig_name, ".") == 0) || (strcmp(full_orig_name, "..") == 0)) + if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || + (strcmp(full_orig_name, "..") == 0)) return; /* @@ -245,7 +246,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU /* * Don't lookup trivial valid directory entries. */ - if((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { + if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { global_stat_cache_misses++; return False; } @@ -365,6 +366,17 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); + /* + * If we trimmed down to a single '\0' character + * then we should use the "." directory to avoid + * searching the cache. + */ + + if(!*name) { + name[0] = '.'; + name[1] = '\0'; + } + /* * Ensure saved_last_component is valid even if file exists. */ -- cgit From 5e634ef68c2abfda88153a402b189eb71e5aea0e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 20 Sep 1998 15:48:10 +0000 Subject: 3 changes: 1) use lp_fstype() instead of FSTYPE_STRING 2) added SMB_SEARCH_BITS to the TconX reply options (in vwv3). I noted that NT sets this (undocumented) bit and setting it helped get autorun from exported cdroms working. 3) fixed volume labels in QFSINFO level 258. I made these changes while getting the Encyclopadia Brittanica CD to run from a Samba drive. (I bought it for Sue yesterday). The first and second changes allowed Samba to export CDs with autorun info and the client will autorun it when mounted. There are all sorts of nasty implications in that that perhaps we can go into on samba-technical. Think about creating some autorun info in /tmp/ then waiting for people to mount it as scratch space ... The last change was because EB wanted the right volume label. The code we had used a non unicode volume label but tests with W95->NT4 showed that it has to be unicode. There was a note in the code from Jeremy saying that he thought it should _not_ be unicode. Jeremy, can you explain why? It certainly didn't work as non-unicode (the client displays a garbage volume label) and when I fixed it to use unicode it all worked from Win95. and in case anyone is interested EB98 now works fine from a Samba drive :) (This used to be commit 66268ae5881f43fbdc1ccd751122ab2285c375ad) --- source3/smbd/reply.c | 6 ++++-- source3/smbd/trans2.c | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ad1894358a..254fb32a51 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -319,7 +319,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,2,strlen(devicename)+1,True); pstrcpy(smb_buf(outbuf),devicename); } else { - char *fsname = FSTYPE_STRING; + char *fsname = lp_fstype(SNUM(conn)); set_message(outbuf,3,3,True); @@ -329,7 +329,9 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); - SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */ + /* what does setting this bit do? It is set by NT4 and + may affect the ability to autorun mounted cdroms */ + SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS); } DEBUG(3,("tconX service=%s user=%s\n", diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fe2869db93..5c8c64a63c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1068,6 +1068,7 @@ static int call_trans2qfsinfo(connection_struct *conn, SMB_STRUCT_STAT st; char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); + char *fstype = lp_fstype(SNUM(conn)); DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); @@ -1113,14 +1114,14 @@ static int call_trans2qfsinfo(connection_struct *conn, break; } case SMB_QUERY_FS_ATTRIBUTE_INFO: - data_len = 12 + 2*strlen(FSTYPE_STRING); + data_len = 12 + 2*strlen(fstype); SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */ #if 0 /* Old code. JRA. */ SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ #endif /* Old code. */ SIVAL(pdata,4,128); /* Max filename component length */ - SIVAL(pdata,8,2*strlen(FSTYPE_STRING)); - PutUniCode(pdata+12,FSTYPE_STRING); + SIVAL(pdata,8,2*strlen(fstype)); + PutUniCode(pdata+12,fstype); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); break; case SMB_QUERY_FS_LABEL_INFO: @@ -1130,20 +1131,22 @@ static int call_trans2qfsinfo(connection_struct *conn, break; case SMB_QUERY_FS_VOLUME_INFO: - /* - * NB: The earlier CIFS spec that says this always - * uses UNICODE is incorrect ! JRA. + /* NT4 always serves this up as unicode. JRA had noted this was + * not the case in an earlier comment. What is going on? I + * tested with Win95 -> NT and a sniff definately showed + * unicode. The volume label now shows up correctly under Win95 + * with unicode here (tridge, Sep98) */ - data_len = 18 + strlen(vname); + data_len = 18 + 2*strlen(vname); /* * Add volume serial number - hash of a combination of * the called hostname and the service name. */ SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - SIVAL(pdata,12,strlen(vname)); - pstrcpy(pdata+18,vname); + SIVAL(pdata,12,strlen(vname)*2); + PutUniCode(pdata+18,vname); DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), vname)); break; -- cgit From e649750cb4d2d2577f0577b1d7a87ae4daf8fb6f Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 21 Sep 1998 09:07:08 +0000 Subject: major autoconf clean-up fix problems in builds with srcdir!=builddir (This used to be commit 1ffc3b807a3f80644c974b454ff5e6f68e89b546) --- source3/smbd/dummy.in | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dummy.in b/source3/smbd/dummy.in index e69de29bb2..8b13789179 100644 --- a/source3/smbd/dummy.in +++ b/source3/smbd/dummy.in @@ -0,0 +1 @@ + -- cgit From 3b7cee95ac741ee24b8edd36095cc30e3377a23c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 23 Sep 1998 01:25:33 +0000 Subject: look at the CAP_NT_SMBS bit in the client capabilities to determine if we should serve up volume labels as ascii or unicode. NT wants ascii, W95 wants unicode. It's a crazy protocol! (This used to be commit 24b8a757ae2899d54dd2b2f091a3c0de6de84dbb) --- source3/smbd/reply.c | 8 +++++--- source3/smbd/trans2.c | 35 ++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 254fb32a51..21fa2e9a79 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -41,6 +41,8 @@ extern pstring sesssetup_user; extern fstring global_myworkgroup; extern int Client; extern int global_oplock_break; +uint32 global_client_caps = 0; + /**************************************************************************** report a possible attack via the password buffer overflow bug @@ -489,11 +491,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); - uint32 client_caps = IVAL(inbuf,smb_vwv11); enum remote_arch_types ra_type = get_remote_arch(); - char *p = smb_buf(inbuf); + global_client_caps = IVAL(inbuf,smb_vwv11); + /* client_caps is used as final determination if client is NT or Win95. This is needed to return the correct error codes in some circumstances. @@ -501,7 +503,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if(ra_type == RA_WINNT || ra_type == RA_WIN95) { - if(client_caps & (CAP_NT_SMBS | CAP_STATUS32)) + if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32)) set_remote_arch( RA_WINNT); else set_remote_arch( RA_WIN95); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5c8c64a63c..fe44965674 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1069,7 +1069,8 @@ static int call_trans2qfsinfo(connection_struct *conn, char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); - + extern uint32 global_client_caps; + DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); if(dos_stat(".",&st)!=0) { @@ -1131,24 +1132,28 @@ static int call_trans2qfsinfo(connection_struct *conn, break; case SMB_QUERY_FS_VOLUME_INFO: - /* NT4 always serves this up as unicode. JRA had noted this was - * not the case in an earlier comment. What is going on? I - * tested with Win95 -> NT and a sniff definately showed - * unicode. The volume label now shows up correctly under Win95 - * with unicode here (tridge, Sep98) - */ - - data_len = 18 + 2*strlen(vname); - /* * Add volume serial number - hash of a combination of * the called hostname and the service name. */ - SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - SIVAL(pdata,12,strlen(vname)*2); - PutUniCode(pdata+18,vname); - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), - vname)); + SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ + (str_checksum(local_machine)<<16)); + + /* NT4 always serves this up as unicode but expects it to be + * delivered as ascii! (tridge && JRA) + */ + if (global_client_caps & CAP_NT_SMBS) { + data_len = 18 + strlen(vname); + SIVAL(pdata,12,strlen(vname)); + pstrcpy(pdata+18,vname); + } else { + data_len = 18 + 2*strlen(vname); + SIVAL(pdata,12,strlen(vname)*2); + PutUniCode(pdata+18,vname); + } + + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", + strlen(vname),vname)); break; case SMB_QUERY_FS_SIZE_INFO: { -- cgit From aab2fe021643417854451c65e564932f4ac25f10 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Sep 1998 01:48:45 +0000 Subject: First cut at kernel oplocks. This should have no effect unless runnin on a machine that supports them in autoconf. Move various functions out of lib/util.c into smbd/process.c and smbd/oplock.c where they belong. Jeremy. (This used to be commit c3c5e13f85c97939746070132dad941e79c546fb) --- source3/smbd/files.c | 28 +-- source3/smbd/ipc.c | 3 +- source3/smbd/nttrans.c | 4 +- source3/smbd/open.c | 26 +-- source3/smbd/oplock.c | 618 ++++++++++++++++++++++++++++++++++++++----------- source3/smbd/process.c | 159 ++++++++++++- source3/smbd/server.c | 2 + source3/smbd/trans2.c | 4 +- 8 files changed, 653 insertions(+), 191 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index c1bb3df57c..e8b391d117 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -290,31 +290,33 @@ void file_close_user(int vuid) /**************************************************************************** -find a fsp given a device, inode and timevalue + Find a fsp given a device, inode and timevalue + If this is from a kernel oplock break request then tval may be NULL. ****************************************************************************/ + files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { int count=0; files_struct *fsp; #ifdef USE_FILES_ARRAY - for(count = 0; count < MAX_FNUMS; count++) { - if((fsp = Files[count]) == NULL) - continue; - if (fsp->open && - fsp->fd_ptr->dev == dev && - fsp->fd_ptr->inode == inode && - fsp->open_time.tv_sec == tval->tv_sec && - fsp->open_time.tv_usec == tval->tv_usec) - return fsp; - } + for(count = 0; count < MAX_FNUMS; count++) { + if((fsp = Files[count]) == NULL) + continue; + if (fsp->open && + fsp->fd_ptr->dev == dev && + fsp->fd_ptr->inode == inode && + (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True) && + (tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True)) + return fsp; + } #else for (fsp=Files;fsp;fsp=fsp->next,count++) { if (fsp->open && fsp->fd_ptr->dev == dev && fsp->fd_ptr->inode == inode && - fsp->open_time.tv_sec == tval->tv_sec && - fsp->open_time.tv_usec == tval->tv_usec) { + (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) && + (tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True )) { if (count > 10) { DLIST_PROMOTE(Files, fsp); } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ce300dc810..22fd318f63 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -60,7 +60,6 @@ extern fstring global_myworkgroup; #define QNLEN 12 /* queue name maximum length */ extern int Client; -extern int oplock_sock; extern int smb_read_error; static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -3660,7 +3659,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int BOOL ret; int pcnt,poff,dcnt,doff,pdisp,ddisp; - ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT); + ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) { if(ret) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2d991eef20..514b5a0813 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -25,7 +25,6 @@ extern int DEBUGLEVEL; extern int Protocol; extern int Client; -extern int oplock_sock; extern int smb_read_error; extern int global_oplock_break; extern int chain_size; @@ -1365,8 +1364,7 @@ due to being in oplock break state.\n" )); while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { BOOL ret; - ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize, - SMB_SECONDARY_WAIT); + ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) { outsize = set_message(outbuf,0,0,True); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d8fcddbe5..64f28ddfe2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -24,8 +24,7 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; -extern int global_oplocks_open; -extern uint16 oplock_port; +extern uint16 global_oplock_port; /**************************************************************************** @@ -917,38 +916,23 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if (lp_share_modes(SNUM(conn))) { uint16 port = 0; + /* JRA. Currently this only services Exlcusive and batch oplocks (no other opens on this file). This needs to be extended to level II oplocks (multiple reader oplocks). */ if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && - !IS_VETO_OPLOCK_PATH(conn,fname)) + !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp) ) { -#if defined(HAVE_KERNEL_OPLOCKS) - /* - * Try and get a *real* oplock on this file. - * If we fail, set the port and oplock request to - * zero so that we don't tell other SMB's that we - * got an oplock. - */ - if(lp_kernel_oplocks()) -#endif /* HAVE_KERNEL_OPLOCKS */ - - fsp->granted_oplock = True; - fsp->sent_oplock_break = False; - global_oplocks_open++; - port = oplock_port; - - DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); - + port = global_oplock_port; } else { port = 0; oplock_request = 0; } + set_share_mode(token, fsp, port, oplock_request); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 94e8559d2a..0cd6f0bef6 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -24,22 +24,21 @@ extern int DEBUGLEVEL; /* Oplock ipc UDP socket. */ -int oplock_sock = -1; -uint16 oplock_port = 0; +static int oplock_sock = -1; +uint16 global_oplock_port = 0; #if defined(HAVE_KERNEL_OPLOCKS) -static int oplock_pipes[2]; +static int oplock_pipe_read = -1; +static int oplock_pipe_write = -1; #endif /* HAVE_KERNEL_OPLOCKS */ /* Current number of oplocks we have outstanding. */ int32 global_oplocks_open = 0; BOOL global_oplock_break = False; - extern int smb_read_error; static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval); - /**************************************************************************** open the oplock IPC socket communication ****************************************************************************/ @@ -56,7 +55,7 @@ BOOL open_oplock_ipc(void) { DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); - oplock_port = 0; + global_oplock_port = 0; return(False); } @@ -67,39 +66,332 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); strerror(errno))); close(oplock_sock); oplock_sock = -1; - oplock_port = 0; + global_oplock_port = 0; + return False; + } + global_oplock_port = ntohs(sock_name.sin_port); + + DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", + (int)getpid(), global_oplock_port)); + + return True; +} + +/**************************************************************************** + Read an oplock break message from the either the oplock UDP fd + or the kernel oplock pipe fd (if kernel oplocks are supported). + + If timeout is zero then *fds contains the file descriptors that + are ready to be read and acted upon. If timeout is non-zero then + *fds contains the file descriptors to be selected on for read. + The timeout is in milliseconds + +****************************************************************************/ + +BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeout) +{ + struct sockaddr_in from; + int fromlen = sizeof(from); + int32 msg_len = 0; + + smb_read_error = 0; + + if(timeout != 0) { + struct timeval to; + int selrtn; + int maxfd = oplock_sock; + +#if defined(HAVE_KERNEL_OPLOCKS) + if(lp_kernel_oplocks()) + maxfd = MAX(maxfd, oplock_pipe_read); +#endif /* HAVE_KERNEL_OPLOCKS */ + + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; + + selrtn = sys_select(maxfd+1,fds,&to); + + /* Check if error */ + if(selrtn == -1) { + /* something is wrong. Maybe the socket is dead? */ + smb_read_error = READ_ERROR; + return False; + } + + /* Did we timeout ? */ + if (selrtn == 0) { + smb_read_error = READ_TIMEOUT; + return False; + } + } + +#if defined(HAVE_KERNEL_OPLOCKS) + if(FD_ISSET(oplock_pipe_read,fds)) { + /* + * Deal with the kernel <--> smbd + * oplock break protocol. + */ + + oplock_stat_t os; + SMB_DEV_T dev; + SMB_INO_T inode; + char dummy; + + /* + * Read one byte of zero to clear the + * kernel break notify message. + */ + + if(read(oplock_pipe_read, &dummy, 1) != 1) { + DEBUG(0,("receive_local_message: read of kernel notification failed. \ +Error was %s.\n", strerror(errno) )); + smb_read_error = READ_ERROR; + return False; + } + + /* + * Do a query to get the + * device and inode of the file that has the break + * request outstanding. + */ + + if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { + DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ +Error was %s.\n", strerror(errno) )); + smb_read_error = READ_ERROR; + return False; + } + + dev = (SMB_DEV_T)os.os_dev; + inode = (SMB_DEV_T)os.os_ino; + + DEBUG(5,("receive_local_message: kernel oplock break request received for \ +dev = %x, inode = %0.f\n", (unsigned int)dev, (double)inode )); + + /* + * Create a kernel oplock break message. + */ + + /* Setup the message header */ + SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); + SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); + + buffer += OPBRK_CMD_HEADER_LEN; + + SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); + SIVAL(buffer,KERNEL_OPLOCK_BREAK_DEV_OFFSET,dev); + +#ifdef LARGE_SMB_INO_T + SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET,inode & 0xFFFFFFFF); + SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET+4, (inode >> 32 ) & 0xFFFFFFFF ); +#else /* LARGE_SMB_INO_T */ + SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET,inode); +#endif /* LARGE_SMB_INO_T */ + + return True; + } +#endif /* HAVE_KERNEL_OPLOCKS */ + + /* + * From here down we deal with the smbd <--> smbd + * oplock break protocol only. + */ + + /* + * Read a loopback udp message. + */ + msg_len = recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], + buffer_len - OPBRK_CMD_HEADER_LEN, 0, + (struct sockaddr *)&from, &fromlen); + + if(msg_len < 0) { + DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); + return False; + } + + /* Validate message length. */ + if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { + DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", + msg_len, + buffer_len - OPBRK_CMD_HEADER_LEN)); return False; } - oplock_port = ntohs(sock_name.sin_port); - DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", - (int)getpid(), oplock_port)); + /* Validate message from address (must be localhost). */ + if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { + DEBUG(0,("receive_local_message: invalid 'from' address \ +(was %x should be 127.0.0.1\n", from.sin_addr.s_addr)); + return False; + } + + /* Setup the message header */ + SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,msg_len); + SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,ntohs(from.sin_port)); + + return True; +} + +/**************************************************************************** + Attempt to set an oplock on a file. Always succeeds if kernel oplocks are + disabled (just sets flags). Returns True if oplock set. +****************************************************************************/ + +BOOL set_file_oplock(files_struct *fsp) +{ +#if defined(HAVE_KERNEL_OPLOCKS) + if(lp_kernel_oplocks()) { + if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0) { + if(errno != EAGAIN) { + DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ +inode = %0.f. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, + strerror(errno) )); + } else { + DEBUG(5,("set_file_oplock: Refused oplock on file %s, dev = %x, \ +inode = %0.f. Another process had the file open.\n", + fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode )); + } + return False; + } + } +#endif /* HAVE_KERNEL_OPLOCKS */ + + DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f\n", + fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode)); + + fsp->granted_oplock = True; + fsp->sent_oplock_break = False; + global_oplocks_open++; return True; } /**************************************************************************** - process an oplock break message. + Attempt to release an oplock on a file. Always succeeds if kernel oplocks are + disabled (just clears flags). +****************************************************************************/ + +static void release_file_oplock(files_struct *fsp) +{ +#if defined(HAVE_KERNEL_OPLOCKS) + if(fsp->granted_oplock && lp_kernel_oplocks()) + { + if( DEBUGLVL( 10 )) + { + /* + * Check and print out the current kernel + * oplock state of this file. + */ + int state = fcntl(fsp->fd_ptr->fd, F_OPLKACK, -1); + dbgtext("release_file_oplock: file %s, dev = %x, inode = %.0f has kernel \ +oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, + (double)fsp->fd_ptr->inode, state ); + } + + /* + * Remove the kernel oplock on this file. + */ + + if(fcntl(fsp->fd_ptr->fd, F_OPLKACK, OP_REVOKE) < 0) + { + if( DEBUGLVL( 0 )) + { + dbgtext("release_file_oplock: Error when removing kernel oplock on file " ); + dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, + (double)fsp->fd_ptr->inode, strerror(errno) ); + } + } + } +#endif /* HAVE_KERNEL_OPLOCKS */ + + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + global_oplocks_open--; +} + +/**************************************************************************** + Setup the listening set of file descriptors for an oplock break + message either from the UDP socket or from the kernel. Returns the maximum + fd used. +****************************************************************************/ + +int setup_oplock_select_set( fd_set *fds) +{ + int maxfd = oplock_sock; + FD_SET(oplock_sock,fds); + +#if defined(HAVE_KERNEL_OPLOCKS) + if(lp_kernel_oplocks()) { + FD_SET(oplock_pipe_read,fds); + maxfd = MAX(maxfd,oplock_pipe_read); + } +#endif /* HAVE_KERNEL_OPLOCKS */ + + return maxfd; +} + +/**************************************************************************** + Process an oplock break message - whether it came from the UDP socket + or from the kernel. ****************************************************************************/ -BOOL process_local_message(int sock, char *buffer, int buf_size) + +BOOL process_local_message(char *buffer, int buf_size) { int32 msg_len; uint16 from_port; char *msg_start; + SMB_DEV_T dev; + SMB_INO_T inode; + uint32 remotepid; + struct timeval tval; + struct timeval *ptval = NULL; - msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET); - from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET); + msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET); + from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET); - msg_start = &buffer[UDP_CMD_HEADER_LEN]; + msg_start = &buffer[OPBRK_CMD_HEADER_LEN]; DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", msg_len, from_port)); - /* Switch on message command - currently OPLOCK_BREAK_CMD is the - only valid request. */ + /* + * Pull the info out of the requesting packet. + */ - switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET)) + switch(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET)) { +#if defined(HAVE_KERNEL_OPLOCKS) + case KERNEL_OPLOCK_BREAK_CMD: + /* Ensure that the msg length is correct. */ + if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) + { + DEBUG(0,("process_local_message: incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, \ +should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); + return False; + } + { + /* + * Warning - beware of SMB_INO_T <> 4 bytes. !! + */ +#ifdef LARGE_SMB_INO_T + SMB_INO_T inode_low = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET); + SMB_INO_T inode_high = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET + 4); + inode = inode_low | (inode_high << 32); +#else /* LARGE_SMB_INO_T */ + inode = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET); +#endif /* LARGE_SMB_INO_T */ + + dev = IVAL(msg_start,KERNEL_OPLOCK_BREAK_DEV_OFFSET); + + ptval = NULL; + + DEBUG(5,("process_local_message: kernel oplock break request for \ +file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); + } + break; +#endif /* HAVE_KERNEL_OPLOCKS */ + case OPLOCK_BREAK_CMD: /* Ensure that the msg length is correct. */ if(msg_len != OPLOCK_BREAK_MSG_LEN) @@ -109,71 +401,31 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); return False; } { - uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); /* * Warning - beware of SMB_INO_T <> 4 bytes. !! */ #ifdef LARGE_SMB_INO_T SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4); - SMB_INO_T inode = inode_low | (inode_high << 32); + inode = inode_low | (inode_high << 32); #else /* LARGE_SMB_INO_T */ - SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); #endif /* LARGE_SMB_INO_T */ - struct timeval tval; - struct sockaddr_in toaddr; + + dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); - DEBUG(5,("process_local_message: oplock break request from \ -pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); - - /* - * If we have no record of any currently open oplocks, - * it's not an error, as a close command may have - * just been issued on the file that was oplocked. - * Just return success in this case. - */ - - if(global_oplocks_open != 0) - { - if(oplock_break(dev, inode, &tval) == False) - { - DEBUG(0,("process_local_message: oplock break failed - \ -not returning udp message.\n")); - return False; - } - } - else - { - DEBUG(3,("process_local_message: oplock break requested with no outstanding \ -oplocks. Returning success.\n")); - } - - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); - - bzero((char *)&toaddr,sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; - - if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) - { - DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", - remotepid, strerror(errno))); - return False; - } + ptval = &tval; - DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %.0f\n", - remotepid, from_port, (unsigned int)dev, (double)inode)); + remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + DEBUG(5,("process_local_message: oplock break request from \ +pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); } break; + /* * Keep this as a debug case - eventually we can remove it. */ @@ -189,19 +441,20 @@ reply - dumping info.\n")); } { - uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); /* * Warning - beware of SMB_INO_T <> 4 bytes. !! */ #ifdef LARGE_SMB_INO_T SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4); - SMB_INO_T inode = inode_low | (inode_high << 32); + inode = inode_low | (inode_high << 32); #else /* LARGE_SMB_INO_T */ - SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); #endif /* LARGE_SMB_INO_T */ + remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + DEBUG(0,("process_local_message: unsolicited oplock break reply from \ pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); @@ -213,12 +466,67 @@ pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int) (unsigned int)SVAL(msg_start,0))); return False; } + + /* + * Now actually process the break request. + */ + + if(global_oplocks_open != 0) + { + if(oplock_break(dev, inode, ptval) == False) + { + DEBUG(0,("process_local_message: oplock break failed.\n")); + return False; + } + } + else + { + /* + * If we have no record of any currently open oplocks, + * it's not an error, as a close command may have + * just been issued on the file that was oplocked. + * Just log a message and return success in this case. + */ + DEBUG(3,("process_local_message: oplock break requested with no outstanding \ +oplocks. Returning success.\n")); + } + + /* + * Do the appropriate reply - none in the kernel case. + */ + + if(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET) == OPLOCK_BREAK_CMD) + { + struct sockaddr_in toaddr; + + /* Send the message back after OR'ing in the 'REPLY' bit. */ + SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); + + bzero((char *)&toaddr,sizeof(toaddr)); + toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + toaddr.sin_port = htons(from_port); + toaddr.sin_family = AF_INET; + + if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) + { + DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", + remotepid, strerror(errno))); + return False; + } + + DEBUG(5,("process_local_message: oplock break reply sent to \ +pid %d, port %d, for file dev = %x, inode = %.0f\n", + remotepid, from_port, (unsigned int)dev, (double)inode)); + } + return True; } /**************************************************************************** Process an oplock break directly. ****************************************************************************/ + static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { extern struct current_user current_user; @@ -233,10 +541,10 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) pstring saved_dir; if( DEBUGLVL( 3 ) ) - { + { dbgtext( "oplock_break: called for dev = %x, inode = %.0f.\n", (unsigned int)dev, (double)inode ); dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); - } + } /* We need to search the file open table for the entry containing this dev and inode, and ensure @@ -247,11 +555,11 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { /* The file could have been closed in the meantime - return success. */ if( DEBUGLVL( 0 ) ) - { + { dbgtext( "oplock_break: cannot find open file with " ); dbgtext( "dev = %x, inode = %.0f ", (unsigned int)dev, (double)inode); dbgtext( "allowing break to succeed.\n" ); - } + } return True; } @@ -267,11 +575,11 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if(!fsp->granted_oplock) { if( DEBUGLVL( 0 ) ) - { + { dbgtext( "oplock_break: file %s ", fsp->fsp_name ); dbgtext( "(dev = %x, inode = %.0f) has no oplock.\n", (unsigned int)dev, (double)inode ); dbgtext( "Allowing break to succeed regardless.\n" ); - } + } return True; } @@ -279,11 +587,11 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if (fsp->sent_oplock_break) { if( DEBUGLVL( 0 ) ) - { + { dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); dbgtext( "file %s ", fsp->fsp_name); dbgtext( "(dev = %x, inode = %.0f)\n", (unsigned int)dev, (double)inode ); - } + } /* We have to fail the open here as we cannot send another oplock break on this file whilst we are awaiting a response from the client - neither @@ -403,7 +711,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); dbgtext( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode ); - } shutdown_server = True; break; @@ -453,10 +760,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { /* The lockingX reply will have removed the oplock flag from the sharemode. */ - /* Paranoia.... */ - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; - global_oplocks_open--; + release_file_oplock(fsp); } /* Santity check - remove this later. JRA */ @@ -467,12 +771,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) exit_server("oplock_break: global_oplocks_open < 0"); } + if( DEBUGLVL( 3 ) ) - { + { dbgtext( "oplock_break: returning success for " ); dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); - } + } return True; } @@ -494,10 +799,10 @@ BOOL request_oplock_break(share_mode_entry *share_entry, if(pid == share_entry->pid) { /* We are breaking our own oplock, make sure it's us. */ - if(share_entry->op_port != oplock_port) + if(share_entry->op_port != global_oplock_port) { DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ -should be %d\n", pid, share_entry->op_port, oplock_port)); +should be %d\n", pid, share_entry->op_port, global_oplock_port)); return False; } @@ -510,7 +815,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ - SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); @@ -532,24 +837,23 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); addr_out.sin_family = AF_INET; if( DEBUGLVL( 3 ) ) - { + { dbgtext( "request_oplock_break: sending a oplock break message to " ); dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); - - } + } if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { if( DEBUGLVL( 0 ) ) - { + { dbgtext( "request_oplock_break: failed when sending a oplock " ); dbgtext( "break message to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); dbgtext( "Error was %s\n", strerror(errno) ); - } + } return False; } @@ -565,24 +869,32 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); while(time_left >= 0) { - char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; + char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; int32 reply_msg_len; uint16 reply_from_port; char *reply_msg_start; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(oplock_sock,&fds); +#if defined(HAVE_KERNEL_OPLOCKS) + if(lp_kernel_oplocks()) + FD_SET(oplock_pipe_read,&fds); +#endif /* HAVE_KERNEL_OPLOCKS */ - if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), + if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply), time_left ? time_left * 1000 : 1) == False) { if(smb_read_error == READ_TIMEOUT) { if( DEBUGLVL( 0 ) ) - { + { dbgtext( "request_oplock_break: no response received to oplock " ); dbgtext( "break request to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); + } - } /* * This is a hack to make handling of failing clients more robust. * If a oplock break response message is not received in the timeout @@ -594,25 +906,30 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); } else if( DEBUGLVL( 0 ) ) - { + { dbgtext( "request_oplock_break: error in response received " ); dbgtext( "to oplock break request to pid %d ", share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); dbgtext( "Error was (%s).\n", strerror(errno) ); - } + } return False; } - reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET); - reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET); + reply_msg_len = IVAL(op_break_reply,OPBRK_CMD_LEN_OFFSET); + reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET); + + reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; - reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN]; +#if defined(HAVE_KERNEL_OPLOCKS) + if((reply_msg_len != OPLOCK_BREAK_MSG_LEN) && (reply_msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN)) +#else if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) +#endif { /* Ignore it. */ - DEBUG( 0, ( "request_oplock_break: invalid message length received." ) ); + DEBUG( 0, ( "request_oplock_break: invalid message length (%d) received.", reply_msg_len ) ); DEBUGADD( 0, ( " Ignoring.\n" ) ); continue; } @@ -621,7 +938,8 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); * Test to see if this is the reply we are awaiting. */ - if((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) && + if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) && + ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == OPLOCK_BREAK_CMD) && (reply_from_port == share_entry->op_port) && (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], &op_break_msg[OPLOCK_BREAK_PID_OFFSET], @@ -635,7 +953,11 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); else { /* - * This is another message - probably a break request. + * This is another message - a break request. + * Note that both kernel oplock break requests + * and UDP inter-smbd oplock break requests will + * be processed here. + * * Process it to prevent potential deadlock. * Note that the code in switch_message() prevents * us from recursing into here as any SMB requests @@ -644,7 +966,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); * JRA. */ - process_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply)); + process_local_message(op_break_reply, sizeof(op_break_reply)); } time_left -= (time(NULL) - start_time); @@ -655,7 +977,6 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); return True; } - /**************************************************************************** Attempt to break an oplock on a file (if oplocked). Returns True if the file was closed as a result of @@ -681,12 +1002,13 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) return False; } -void check_kernel_oplocks(BOOL *have_oplocks) +/**************************************************************************** + Init function to check if kernel level oplocks are available. +****************************************************************************/ + +void check_kernel_oplocks(void) { static BOOL done; - int fd; - int pfd[2]; - pstring tmpname; /* * We only do this check once on startup. @@ -696,45 +1018,59 @@ void check_kernel_oplocks(BOOL *have_oplocks) return; done = True; - *have_oplocks = False; + lp_set_kernel_oplocks(False); #if defined(HAVE_KERNEL_OPLOCKS) - slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid()); - mktemp(tmpname); + { + int fd; + int pfd[2]; + pstring tmpname; - if(pipe(pfd) != 0) { - DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", - strerror(errno) )); - return; - } + slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid()); + mktemp(tmpname); + + if(pipe(pfd) != 0) { + DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", + strerror(errno) )); + return; + } + + if((fd = open(tmpname, O_RDWR)) < 0) { + DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", + tmpname, strerror(errno) )); + unlink( tmpname ); + close(pfd[0]); + close(pfd[1]); + return; + } - if((fd = open(tmpname, O_RDWR)) < 0) { - DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", - tmpname, strerror(errno) )); unlink( tmpname ); - close(pfd[0]); - close(pfd[1]); - return; - } - unlink( tmpname ); + if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { + DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ +Disabling kernel oplock supprt.\n" )); + close(pfd[0]); + close(pfd[1]); + close(fd); + return; + } - if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { - DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ + if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) { + DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ Disabling kernel oplock supprt.\n" )); - close(pfd[0]); - close(pfd[1]); - close(fd); - return; - } + close(pfd[0]); + close(pfd[1]); + close(fd); + return; + } - fcntl(fd, F_OPLKACK, OP_REVOKE); - close(pfd[0]); - close(pfd[1]); - close(fd); + oplock_pipe_read = pfd[0]; + oplock_pipe_write = pfd[1]; + close(fd); - DEBUG(3,("check_kernel_oplocks: Kernel oplocks enabled.\n")); + DEBUG(3,("check_kernel_oplocks: Kernel oplocks enabled.\n")); - *have_oplocks = True; + lp_set_kernel_oplocks(True); + } #endif /* HAVE_KERNEL_OPLOCKS */ } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1d6de37df0..656e2e99e1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -47,7 +47,6 @@ extern pstring sesssetup_user; extern char *last_inbuf; extern char *InBuffer; extern char *OutBuffer; -extern int oplock_sock; extern int smb_read_error; extern BOOL reload_after_sighup; extern BOOL global_machine_pasword_needs_changing; @@ -55,24 +54,168 @@ extern fstring global_myworkgroup; extern pstring global_myname; extern int max_send; +/**************************************************************************** + structure to hold a linked list of queued messages. + for processing. +****************************************************************************/ + +typedef struct { + ubi_slNode msg_next; + char *msg_buf; + int msg_len; +} pending_message_list; + +static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0}; + +/**************************************************************************** + Function to push a message onto the tail of a linked list of smb messages ready + for processing. +****************************************************************************/ + +static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) +{ + pending_message_list *msg = (pending_message_list *) + malloc(sizeof(pending_message_list)); + + if(msg == NULL) + { + DEBUG(0,("push_message: malloc fail (1)\n")); + return False; + } + + msg->msg_buf = (char *)malloc(msg_len); + if(msg->msg_buf == NULL) + { + DEBUG(0,("push_message: malloc fail (2)\n")); + free((char *)msg); + return False; + } + + memcpy(msg->msg_buf, buf, msg_len); + msg->msg_len = msg_len; + + ubi_slAddTail( list_head, msg); + + return True; +} + +/**************************************************************************** + Function to push a smb message onto a linked list of local smb messages ready + for processing. +****************************************************************************/ + +BOOL push_oplock_pending_smb_message(char *buf, int msg_len) +{ + return push_message(&smb_oplock_queue, buf, msg_len); +} + +/**************************************************************************** + Do a select on an two fd's - with timeout. + + If a local udp message has been pushed onto the + queue (this can only happen during oplock break + processing) return this first. + + If a pending smb message has been pushed onto the + queue (this can only happen during oplock break + processing) return this next. + + If the first smbfd is ready then read an smb from it. + if the second (loopback UDP) fd is ready then read a message + from it and setup the buffer header to identify the length + and from address. + Returns False on timeout or error. + Else returns True. + +The timeout is in milli seconds +****************************************************************************/ + +static BOOL receive_message_or_smb(char *buffer, int buffer_len, + int timeout, BOOL *got_smb) +{ + extern int Client; + fd_set fds; + int selrtn; + struct timeval to; + int maxfd; + + smb_read_error = 0; + + *got_smb = False; + + /* + * Check to see if we already have a message on the smb queue. + * If so - copy and return it. + */ + + if(ubi_slCount(&smb_oplock_queue) != 0) + { + pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue); + memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); + + /* Free the message we just copied. */ + free((char *)msg->msg_buf); + free((char *)msg); + *got_smb = True; + + DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); + return True; + } + + /* + * Setup the select read fd set. + */ + + FD_ZERO(&fds); + FD_SET(Client,&fds); + maxfd = setup_oplock_select_set(&fds); + + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; + + selrtn = sys_select(MAX(maxfd,Client)+1,&fds,timeout>0?&to:NULL); + + /* Check if error */ + if(selrtn == -1) { + /* something is wrong. Maybe the socket is dead? */ + smb_read_error = READ_ERROR; + return False; + } + + /* Did we timeout ? */ + if (selrtn == 0) { + smb_read_error = READ_TIMEOUT; + return False; + } + + if (FD_ISSET(Client,&fds)) + { + *got_smb = True; + return receive_smb(Client, buffer, 0); + } + else + { + return receive_local_message(&fds, buffer, buffer_len, 0); + } +} /**************************************************************************** Get the next SMB packet, doing the local message processing automatically. ****************************************************************************/ -BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout) + +BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) { BOOL got_smb = False; BOOL ret; do { - ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize, - timeout,&got_smb); + ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb); if(ret && !got_smb) { /* Deal with oplock break requests from other smbd's. */ - process_local_message(oplock_sock, inbuf, bufsize); + process_local_message(inbuf, bufsize); continue; } @@ -644,8 +787,8 @@ void smbd_process(void) errno = 0; for (counter=SMBD_SELECT_LOOP; - !receive_message_or_smb(Client,oplock_sock, - InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); + !receive_message_or_smb(InBuffer,BUFFER_SIZE, + SMBD_SELECT_LOOP*1000,&got_smb); counter += SMBD_SELECT_LOOP) { time_t t; @@ -792,6 +935,6 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); if(got_smb) process_smb(InBuffer, OutBuffer); else - process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); + process_local_message(InBuffer, BUFFER_SIZE); } } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 44d53c70cf..c06c0ce1cb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -700,6 +700,8 @@ static void usage(char *pname) if( !open_oplock_ipc() ) exit(1); + check_kernel_oplocks(); + smbd_process(); close_sockets(); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fe44965674..70f834af8a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -28,7 +28,6 @@ extern int DEBUGLEVEL; extern int Protocol; extern BOOL case_sensitive; extern int Client; -extern int oplock_sock; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; @@ -1922,8 +1921,7 @@ int reply_trans2(connection_struct *conn, num_params_sofar < total_params) { BOOL ret; - ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize, - SMB_SECONDARY_WAIT); + ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); if ((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) { -- cgit From e4962b80f88d9937b2b509fcbffe02c94e1a5b69 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Sep 1998 01:58:27 +0000 Subject: smbd/oplock.c: Use O_CREAT and O_TRUNC and correct mode flags when creating oplock test file. smbd/server.c: Check for existance of kernel oplocks before becoming a daemon. Jeremy. (This used to be commit b42779e17e754d4a2f75904e2187c9209e0a53f0) --- source3/smbd/oplock.c | 2 +- source3/smbd/server.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 0cd6f0bef6..b87d664046 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1035,7 +1035,7 @@ void check_kernel_oplocks(void) return; } - if((fd = open(tmpname, O_RDWR)) < 0) { + if((fd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) { DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", tmpname, strerror(errno) )); unlink( tmpname ); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c06c0ce1cb..e1b5e42764 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -661,6 +661,8 @@ static void usage(char *pname) DEBUG(3,( "loaded services\n")); + check_kernel_oplocks(); + if (!is_daemon && !is_a_socket(0)) { DEBUG(0,("standard input is not a socket, assuming -D option\n")); is_daemon = True; @@ -700,8 +702,6 @@ static void usage(char *pname) if( !open_oplock_ipc() ) exit(1); - check_kernel_oplocks(); - smbd_process(); close_sockets(); -- cgit From 0e091a52074655aedeeaad488d61e241909a3dc5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Sep 1998 17:56:34 +0000 Subject: Hoist by my own petard with warnings (forgot to set strict warnings in Makefile before compiling & checking in :-). Jeremy. (This used to be commit 05fb3c82a57549fba74016eae31b53de30417b3c) --- source3/smbd/oplock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index b87d664046..d73fcda117 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -166,7 +166,7 @@ Error was %s.\n", strerror(errno) )); inode = (SMB_DEV_T)os.os_ino; DEBUG(5,("receive_local_message: kernel oplock break request received for \ -dev = %x, inode = %0.f\n", (unsigned int)dev, (double)inode )); +dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); /* * Create a kernel oplock break message. @@ -243,12 +243,12 @@ BOOL set_file_oplock(files_struct *fsp) if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0) { if(errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ -inode = %0.f. Error was %s\n", +inode = %.0f. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, strerror(errno) )); } else { DEBUG(5,("set_file_oplock: Refused oplock on file %s, dev = %x, \ -inode = %0.f. Another process had the file open.\n", +inode = %.0f. Another process had the file open.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode )); } return False; @@ -1026,7 +1026,7 @@ void check_kernel_oplocks(void) int pfd[2]; pstring tmpname; - slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid()); + slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", (unsigned int)getpid()); mktemp(tmpname); if(pipe(pfd) != 0) { @@ -1048,7 +1048,7 @@ void check_kernel_oplocks(void) if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ -Disabling kernel oplock supprt.\n" )); +Disabling kernel oplock support.\n" )); close(pfd[0]); close(pfd[1]); close(fd); @@ -1057,7 +1057,7 @@ Disabling kernel oplock supprt.\n" )); if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) { DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ -Disabling kernel oplock supprt.\n" )); +Disabling kernel oplock support.\n", strerror(errno) )); close(pfd[0]); close(pfd[1]); close(fd); -- cgit From 500a474aae49bd1cc8e75481a3b3cd6e79720d89 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 23 Sep 1998 21:49:09 +0000 Subject: nttrans.c: winreg was missing from the list of pipes. advise using the array already defined in... rpc_parse/parse_rpc.c's pipe_names[], but writing code to strip "\PIPE\" from the front when making the check. one location to update when adding new pipes, not two. srv_pipe_hnd.c: moved the ZERO_STRUCT(p) macro to _before_ the DLIST_ADD(Pipes, p) macro. dlinklist.h: added { }s around the code inserted by DLIST_ADD and DLIST_REMOVE macros (This used to be commit 29201d4b9b52652c7a992d0f6b677a09b4c33912) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 514b5a0813..4d3572c6a8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -44,6 +44,7 @@ static char *known_nt_pipes[] = { "\\ntsvcs", "\\lsass", "\\lsarpc", + "\\winreg", NULL }; -- cgit From dc36d8768aa13000c48b520f09f6678ea9ffbf28 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Sep 1998 22:33:13 +0000 Subject: Integration of Anders Blomdell 's smbpasswd changes. Not exactly the same as his code - several changes. Jeremy. (This used to be commit e96747a8e3b9ea5a79c4258e55d7e8f3bf0bf193) --- source3/smbd/oplock.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index d73fcda117..b418e7cd54 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -240,16 +240,47 @@ BOOL set_file_oplock(files_struct *fsp) { #if defined(HAVE_KERNEL_OPLOCKS) if(lp_kernel_oplocks()) { - if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0) { - if(errno != EAGAIN) { +#if 0 /* for now. */ + extern struct current_user current_user; +#endif + int saved_errno; + int fcntl_ret; + +#if 0 /* for now. */ + /* + * Go back to being root. + */ + + unbecome_user(); +#endif + + fcntl_ret = fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write); + saved_errno = errno; + +#if 0 /* for now. */ + /* + * Go back to being the correct user. + */ + if(!become_user(fsp->conn, current_user.vuid)) + { + DEBUG( 0, ( "set_file_oplock: unable to re-become user!" ) ); + DEBUGADD( 0, ( "Shutting down server\n" ) ); + close_sockets(); + close(oplock_sock); + exit_server("unable to re-become user"); + } +#endif + + if(fcntl_ret < 0) { + if(saved_errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, strerror(errno) )); } else { - DEBUG(5,("set_file_oplock: Refused oplock on file %s, dev = %x, \ + DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. Another process had the file open.\n", - fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode )); + fsp->fsp_name, fsp->fd_ptr->fd, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode )); } return False; } -- cgit From 95f99e80b4d0bf23e9e638f3024ae9d074482f57 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 25 Sep 1998 03:52:29 +0000 Subject: I've disabled the conversion of null filenames to "." until we solve the win95 printing problem. I suspect it is a smbgetatr() problem with a null name (which requires special behaviour). This is an interim solution. (This used to be commit 0a69e091a2ec75bce89760d69ea1488941108740) --- source3/smbd/filename.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7cbb3392cb..685725f096 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -366,6 +366,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); + /* I've disabled this till we fix printing (probably a getatr problem) (tridge) */ +#if TRIM_NULL_NAMES /* * If we trimmed down to a single '\0' character * then we should use the "." directory to avoid @@ -376,6 +378,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, name[0] = '.'; name[1] = '\0'; } +#endif /* * Ensure saved_last_component is valid even if file exists. -- cgit From 66d5d73a5d75e88a77970f7b27687b8354ab2e80 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 25 Sep 1998 21:01:52 +0000 Subject: added rpcclient program (This used to be commit aa38f39d67fade4dfd7badb7a9b39c833a1dd1ca) --- source3/smbd/password.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1d90af3066..75934ec294 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -29,6 +29,7 @@ BOOL global_machine_pasword_needs_changing; /* users from session setup */ static pstring session_users=""; +extern pstring scope; extern pstring global_myname; extern fstring global_myworkgroup; @@ -929,6 +930,7 @@ struct cli_state *server_cryptkey(void) extern fstring local_machine; char *p; BOOL connected_ok = False; + struct nmb_name calling, called; if (!cli_initialise(&pw_cli)) return NULL; @@ -961,7 +963,11 @@ struct cli_state *server_cryptkey(void) return NULL; } - if (!cli_session_request(&pw_cli, desthost, 0x20, local_machine)) { + make_nmb_name(&calling, local_machine, 0x0 , scope); + make_nmb_name(&called , desthost , 0x20, scope); + + if (!cli_session_request(&pw_cli, &calling, &called)) + { DEBUG(1,("%s rejected the session\n",desthost)); cli_shutdown(&pw_cli); return NULL; @@ -1124,6 +1130,7 @@ BOOL domain_client_validate( char *user, char *domain, struct cli_state cli; uint32 smb_uid_low; BOOL connected_ok = False; + struct nmb_name calling, called; /* * Check that the requested domain is not our own machine name. @@ -1236,7 +1243,11 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) )); continue; } - if (!cli_session_request(&cli, remote_machine, 0x20, global_myname)) { + make_nmb_name(&calling, global_myname , 0x0 , scope); + make_nmb_name(&called , remote_machine, 0x20, scope); + + if (!cli_session_request(&pw_cli, &calling, &called)) + { DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); cli_shutdown(&cli); -- cgit From 5f7ee360567a6b4e1a6f43ff01da057d2998fef8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Sep 1998 23:40:49 +0000 Subject: Makefile.in: Fixed bug with continuation line causing proto to fail. Added $(PROGS) $(SPROGS) as targets for make clean. acconfig.h: Added HAVE_IRIX_SPECIFIC_CAPABILITIES. configure.in: Added sys/capability.h header check. Added function checks for srandom random srand rand. Added HAVE_IRIX_SPECIFIC_CAPABILITIES test. includes.h: Added #include . ntdomain.h: Moved struct acct_info into here from smb.h smb.h: Added KERNEL_OPLOCK_CAPABILITY define. Moved enum action_type into rpcclient.h Moved struct cli_state into client.h Moved struct nt_client_info, struct tar_client_info, struct client_info into rpcclient.h lib/genrand.c: Changed to use sys_random() & friends. lib/smbrun.c: Lose capabilities after fork. lib/system.c: Added set_process_capability(), set_inherited_process_capability() sys_random(), sys_srandom(). lib/util.c: Added Ander's EFBIG lock check to fcntl_lock for 64 bit access to an 32 bit mounted NFS filesystem. nmbd/nmbd.c: Changed to use sys_random() & friends. nmbd/nmbd_browsesync.c: Changed to use sys_random() & friends. passdb/ldap.c: Missed one pdb_encode_acct_ctrl call. passdb/passdb.c: Changed to Ander's code for ' ' characters. passdb/smbpass.c: Added Ander's code to reset ACB_PWNOTREQ. script/mkproto.awk: Added 'long' to prototypes. smbd/chgpasswd.c: Lose capabilities after fork. smbd/open.c: Do the mmap *after* the kernel oplock. smbd/oplock.c: Removed stub code from kernel oplock path. Added set_process_capability(), set_inherited_process_capability() calls. smbd/reply.c: Initialize count = 0, offset = 0. smbd/server.c: Added set_process_capability(), set_inherited_process_capability() calls. tests/summary.c: Ensure we have RANDOM or RAND. utils/smbpasswd.c: Added Ander's code to reset ACB_PWNOTREQ. utils/torture.c: Changed to use sys_random() & friends. Jeremy. (This used to be commit e8be306f23963ac00b1a383ebe0cc1421529fb02) --- source3/smbd/chgpasswd.c | 6 ++++++ source3/smbd/open.c | 24 +++++++++++++++++++++--- source3/smbd/oplock.c | 46 ++++++++++++---------------------------------- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 12 ++++++++++-- 5 files changed, 50 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 4dc6d29e3c..4131bc9297 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -343,6 +343,12 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc } else { /* CHILD */ + /* + * Lose any oplock capabilities. + */ + set_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + /* make sure it doesn't freeze */ alarm(20); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 64f28ddfe2..2b2f0f0524 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -535,18 +535,30 @@ static void open_file(files_struct *fsp,connection_struct *conn, conn->num_files_open)); } +} +/**************************************************************************** + If it's a read-only file, and we were compiled with mmap enabled, + try and mmap the file. This is split out from open_file() above + as mmap'ing the file can cause the kernel reference count to + be incremented, which can cause kernel oplocks to be refused. + Splitting this call off allows the kernel oplock to be granted, then + the file mmap'ed. +****************************************************************************/ + +static void mmap_open_file(files_struct *fsp) +{ #if WITH_MMAP /* mmap it if read-only */ if (!fsp->can_write) { - fsp->mmap_size = file_size(fname); + fsp->mmap_size = file_size(fsp->fsp_name); if (fsp->mmap_size < MAX_MMAP_SIZE) { fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { DEBUG(3,("Failed to mmap() %s - %s\n", - fname,strerror(errno))); + fsp->fsp_name,strerror(errno))); fsp->mmap_ptr = NULL; } } @@ -554,7 +566,6 @@ static void open_file(files_struct *fsp,connection_struct *conn, #endif } - /**************************************************************************** C. Hoch 11/22/95 Helper for open_file_shared. @@ -938,6 +949,13 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fsp,conn,token,&share_locked); + + /* + * Attempt to mmap a read only file. + * Moved until after a kernel oplock may + * be granted due to reference count issues. JRA. + */ + mmap_open_file(fsp); } if (share_locked && lp_share_modes(SNUM(conn))) diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index b418e7cd54..27d802c151 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -240,39 +240,9 @@ BOOL set_file_oplock(files_struct *fsp) { #if defined(HAVE_KERNEL_OPLOCKS) if(lp_kernel_oplocks()) { -#if 0 /* for now. */ - extern struct current_user current_user; -#endif - int saved_errno; - int fcntl_ret; -#if 0 /* for now. */ - /* - * Go back to being root. - */ - - unbecome_user(); -#endif - - fcntl_ret = fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write); - saved_errno = errno; - -#if 0 /* for now. */ - /* - * Go back to being the correct user. - */ - if(!become_user(fsp->conn, current_user.vuid)) - { - DEBUG( 0, ( "set_file_oplock: unable to re-become user!" ) ); - DEBUGADD( 0, ( "Shutting down server\n" ) ); - close_sockets(); - close(oplock_sock); - exit_server("unable to re-become user"); - } -#endif - - if(fcntl_ret < 0) { - if(saved_errno != EAGAIN) { + if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { + if(errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, @@ -284,6 +254,10 @@ inode = %.0f. Another process had the file open.\n", } return False; } + + DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", + fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode)); + } #endif /* HAVE_KERNEL_OPLOCKS */ @@ -305,7 +279,8 @@ inode = %.0f. Another process had the file open.\n", static void release_file_oplock(files_struct *fsp) { #if defined(HAVE_KERNEL_OPLOCKS) - if(fsp->granted_oplock && lp_kernel_oplocks()) + + if(lp_kernel_oplocks()) { if( DEBUGLVL( 10 )) { @@ -320,7 +295,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, } /* - * Remove the kernel oplock on this file. + * Remote the kernel oplock on this file. */ if(fcntl(fsp->fd_ptr->fd, F_OPLKACK, OP_REVOKE) < 0) @@ -1057,6 +1032,9 @@ void check_kernel_oplocks(void) int pfd[2]; pstring tmpname; + set_process_capability(KERNEL_OPLOCK_CAPABILITY,True); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,True); + slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", (unsigned int)getpid()); mktemp(tmpname); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 21fa2e9a79..63bbcbcdba 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3544,7 +3544,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, #endif uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); - SMB_OFF_T count, offset; + SMB_OFF_T count = 0, offset = 0; int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e1b5e42764..fb97cf8380 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -240,6 +240,14 @@ max can be %d\n", that client substitutions will be done correctly in the process. */ reset_globals_after_fork(); + + /* + * Ensure this child has kernel oplock + * capabilities, but not it's children. + */ + set_process_capability(KERNEL_OPLOCK_CAPABILITY, True); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + return True; } /* The parent doesn't need this socket */ @@ -661,8 +669,6 @@ static void usage(char *pname) DEBUG(3,( "loaded services\n")); - check_kernel_oplocks(); - if (!is_daemon && !is_a_socket(0)) { DEBUG(0,("standard input is not a socket, assuming -D option\n")); is_daemon = True; @@ -673,6 +679,8 @@ static void usage(char *pname) become_daemon(); } + check_kernel_oplocks(); + if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); } -- cgit From 1ea570da834fa72c88dd35a86fdf68ae5ecbeb19 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Sat, 26 Sep 1998 00:41:20 +0000 Subject: Small update to clitar.c to omit warnings about servers not letting us change the date unless tar_real_noisy is True. Also updated a few places where variables are declared but not set. (This used to be commit b46f1024c939ee9ecb8deb9c844acbd4b5f109c6) --- source3/smbd/blocking.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 27a5183952..32b6d010a4 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -195,7 +195,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec files_struct *fsp = blr->fsp; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - SMB_OFF_T count, offset; + SMB_OFF_T count = (SMB_OFF_T) 0, offset = (SMB_OFF_T) 0; unsigned char locktype = CVAL(inbuf,smb_vwv3); BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; @@ -329,7 +329,7 @@ static BOOL process_lock(blocking_lock_record *blr) char *outbuf = OutBuffer; char *inbuf = blr->inbuf; int outsize; - SMB_OFF_T count,offset; + SMB_OFF_T count = 0, offset = 0; int eclass; uint32 ecode; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); @@ -387,7 +387,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); - SMB_OFF_T count, offset; + SMB_OFF_T count = 0, offset = 0; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; int eclass=0; -- cgit From a377543cc0af26ddcaf58aa4bc368afd70bca5ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 Sep 1998 03:49:25 +0000 Subject: Fixed the problem with reply_getatr() being passed a "" name in reply_getatr, replaced the paranoid code in smbd/filename.c that replaces a "" with a ".". I am starting to think this code may well be needed. Jeremy. (This used to be commit bdc3d9f52fbded4b1483af8be0059decfd4bad34) --- source3/smbd/filename.c | 3 --- source3/smbd/reply.c | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 685725f096..7cbb3392cb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -366,8 +366,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); - /* I've disabled this till we fix printing (probably a getatr problem) (tridge) */ -#if TRIM_NULL_NAMES /* * If we trimmed down to a single '\0' character * then we should use the "." directory to avoid @@ -378,7 +376,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, name[0] = '.'; name[1] = '\0'; } -#endif /* * Ensure saved_last_component is valid even if file exists. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 63bbcbcdba..12a39589d6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -812,19 +812,20 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,conn,0,&bad_path,&sbuf); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (! (*fname)) - { - mode = aHIDDEN | aDIR; - if (!CAN_WRITE(conn)) mode |= aRONLY; - size = 0; - mtime = 0; - ok = True; - } + { + mode = aHIDDEN | aDIR; + if (!CAN_WRITE(conn)) mode |= aRONLY; + size = 0; + mtime = 0; + ok = True; + } else + { + unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0) @@ -839,6 +840,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size else DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); } + } if (!ok) { -- cgit From cf971f88ac188eec353a7fb021744b8076cc4eb7 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 28 Sep 1998 00:14:36 +0000 Subject: automated generation of .dummy files for each subdirectory; dummy.in files are no longer needed, and new directories will be taken care of automatically, at configure (or config.status --recheck) time (This used to be commit 237a8e5fe62d757c04b8207cbbee4df1470cfe4e) --- source3/smbd/dummy.in | 1 - 1 file changed, 1 deletion(-) delete mode 100644 source3/smbd/dummy.in (limited to 'source3/smbd') diff --git a/source3/smbd/dummy.in b/source3/smbd/dummy.in deleted file mode 100644 index 8b13789179..0000000000 --- a/source3/smbd/dummy.in +++ /dev/null @@ -1 +0,0 @@ - -- cgit From cf3a9741dc7427efb97eff09a3c197a906ce6767 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Sep 1998 21:43:48 +0000 Subject: Changes to test in configure if capabilities are enabled on a system. Changes to get Samba to compile cleanly with the IRIX compiler with the options : -fullwarn -woff 1209,1174 (the -woff options are to turn off warnings about unused function parameters and controlling loop expressions being constants). Split prototype generation as we hit a limit in IRIX nawk. Removed "." code in smbd/filename.c (yet again :-). Jeremy. (This used to be commit e0567433bd72aec17bf5a54cc292701095d25f09) --- source3/smbd/dir.c | 3 --- source3/smbd/filename.c | 24 +++++++++++------------- source3/smbd/oplock.c | 4 ++-- source3/smbd/password.c | 2 +- 4 files changed, 14 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 73db295548..03864334eb 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -428,7 +428,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, pstring pathreal; BOOL isrootdir; pstring filename; - BOOL matched; BOOL needslash; *path = *pathreal = *filename = 0; @@ -453,8 +452,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, if (dname == NULL) return(False); - matched = False; - pstrcpy(filename,dname); if ((strcmp(filename,mask) == 0) || diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7cbb3392cb..ff4d682747 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -332,7 +332,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; - char *start, *end, *orig_start; + char *start, *end; pstring dirpath; pstring orig_path; int saved_errno; @@ -366,17 +366,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); - /* - * If we trimmed down to a single '\0' character - * then we should use the "." directory to avoid - * searching the cache. - */ - - if(!*name) { - name[0] = '.'; - name[1] = '\0'; - } - /* * Ensure saved_last_component is valid even if file exists. */ @@ -413,6 +402,15 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, return(True); } + /* + * If we trimmed down to a single '\0' character + * then we will be using the "." directory. + * As we know this is valid we can return true here. + */ + + if(!*name) + return(True); + start = name; while (strncmp(start,"./",2) == 0) start += 2; @@ -479,7 +477,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * as is first, then trying to scan the directory for matching names. */ - for (orig_start = start; start ; start = (end?end+1:(char *)NULL)) { + for (; start ; start = (end?end+1:(char *)NULL)) { /* * Pinpoint the end of this section of the filename. */ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 27d802c151..d5c06312f5 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -420,8 +420,8 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); - tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); + tval.tv_sec = (time_t)IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); + tval.tv_usec = (long)IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); ptval = &tval; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 75934ec294..f542dbe608 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -75,7 +75,7 @@ void generate_next_challenge(char *challenge) /******************************************************************* set the last challenge sent, usually from a password server ********************************************************************/ -BOOL set_challenge(char *challenge) +BOOL set_challenge(unsigned char *challenge) { memcpy(saved_challenge,challenge,8); challenge_sent = True; -- cgit From 008fd973097303ac984cd7c004e3dea67d54813d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Sep 1998 23:55:09 +0000 Subject: Fixed problems found in lint pass over the old code by . These were the problems that still existed in the 2.0 branch. Jeremy. (This used to be commit 3fd28812f75f2311a114ff905143634e3bbb1fac) --- source3/smbd/ipc.c | 54 +++++++++++++++++++++++++++++++++++++++++---------- source3/smbd/trans2.c | 4 ++++ 2 files changed, 48 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 22fd318f63..ec126c89ff 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -642,7 +642,13 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, return; } - p=(char *)malloc(8192*sizeof(char)); + if((p=(char *)malloc(8192*sizeof(char))) == NULL) { + DEBUG(0,("fill_printq_info: malloc fail !\n")); + desc->errcode=NERR_notsupported; + fclose(f); + return; + } + bzero(p, 8192*sizeof(char)); q=p; @@ -741,7 +747,12 @@ static int get_printerdrivernumber(int snum) return(0); } - p=(char *)malloc(8192*sizeof(char)); + if((p=(char *)malloc(8192*sizeof(char))) == NULL) { + DEBUG(3,("get_printerdrivernumber: malloc fail !\n")); + fclose(f); + return 0; + } + q=p; /* need it to free memory because p change ! */ /* lookup the long printer driver name in the file description */ @@ -882,11 +893,20 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) queuecnt++; if (uLevel > 0) { - queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*)); + if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + return False; + } memset(queue,0,queuecnt*sizeof(print_queue_struct*)); - status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct)); + if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + return False; + } memset(status,0,queuecnt*sizeof(print_status_struct)); - subcntarr = (int*)malloc(queuecnt*sizeof(int)); + if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + return False; + } subcnt = 0; n = 0; for (i = 0; i < services; i++) @@ -3525,13 +3545,18 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data for (i=0;api_commands[i].name;i++) if (api_commands[i].id == api_command && api_commands[i].fn) { - DEBUG(3,("Doing %s\n",api_commands[i].name)); - break; + DEBUG(3,("Doing %s\n",api_commands[i].name)); + break; } rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); + if(!rdata || !rparam) { + DEBUG(0,("api_reply: malloc fail !\n")); + return -1; + } + reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); @@ -3629,18 +3654,27 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if (tdscnt) { - data = (char *)malloc(tdscnt); + if((data = (char *)malloc(tdscnt)) == NULL) { + DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt)); + return(ERROR(ERRDOS,ERRnomem)); + } memcpy(data,smb_base(inbuf)+dsoff,dscnt); } if (tpscnt) { - params = (char *)malloc(tpscnt); + if((params = (char *)malloc(tpscnt)) == NULL) { + DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt)); + return(ERROR(ERRDOS,ERRnomem)); + } memcpy(params,smb_base(inbuf)+psoff,pscnt); } if (suwcnt) { int i; - setup = (uint16 *)malloc(suwcnt*sizeof(setup[0])); + if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { + DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16))); + return(ERROR(ERRDOS,ERRnomem)); + } for (i=0;i Date: Tue, 29 Sep 1998 04:52:17 +0000 Subject: get away with dummy and .dummy files (This used to be commit 90a8a02484a0897b053fd6531b7fec5d23098b6f) --- source3/smbd/.cvsignore | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/.cvsignore b/source3/smbd/.cvsignore index 421376db9e..e69de29bb2 100644 --- a/source3/smbd/.cvsignore +++ b/source3/smbd/.cvsignore @@ -1 +0,0 @@ -dummy -- cgit From 9066025a8a4afe1f7f559c455d86fc023792ed17 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Sep 1998 20:24:17 +0000 Subject: Got very strict about the differences and uses of uid_t, gid_t and vuid. Added sys_getgroups() to get around the int * return problem. Set correct datatypes for all uid, gid and vuid variables. Jeremy. (This used to be commit e570db46fc3a78e499523fd342e9a34cebb18998) --- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 35 ++++++++++++++++++++--------------- source3/smbd/service.c | 2 +- source3/smbd/uid.c | 38 +++++++++++++++++++------------------- 4 files changed, 41 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ec126c89ff..db6ee62f91 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2383,7 +2383,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); if(vuser != NULL) - DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name)); *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f542dbe608..5a7e20e47e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -107,7 +107,7 @@ user_struct *get_valid_user_struct(uint16 vuid) return NULL; vuid -= VUID_OFFSET; if ((vuid >= (uint16)num_validated_users) || - (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1)) + (validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1)) return NULL; return &validated_users[vuid]; } @@ -121,17 +121,19 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; - vuser->uid = -1; - vuser->gid = -1; + vuser->uid = (uid_t)-1; + vuser->gid = (gid_t)-1; vuser->n_sids = 0; /* same number of igroups as groups */ vuser->n_groups = 0; - if (vuser->groups) free(vuser->groups); + if (vuser->groups) + free((char *)vuser->groups); - if (vuser->sids) free(vuser->sids); + if (vuser->sids) + free((char *)vuser->sids); vuser->sids = NULL; vuser->groups = NULL; @@ -153,11 +155,11 @@ char *validated_username(uint16 vuid) /**************************************************************************** Setup the groups a user belongs to. ****************************************************************************/ -int setup_groups(char *user, int uid, int gid, int *p_ngroups, GID_T **p_groups) +int setup_groups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups) { int i,ngroups; - GID_T *groups; - GID_T grp = 0; + gid_t grp = 0; + gid_t *groups = NULL; if (-1 == initgroups(user,gid)) { if (getuid() == 0) { @@ -170,15 +172,18 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups, GID_T **p_groups) return -1; } - ngroups = getgroups(0,&grp); - if (ngroups <= 0) ngroups = 32; + ngroups = sys_getgroups(0,&grp); + if (ngroups <= 0) + ngroups = 32; - groups = (GID_T *)malloc(sizeof(groups[0])*ngroups); + if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) { + DEBUG(0,("setup_groups malloc fail !\n")); + return -1; + } - ngroups = getgroups(ngroups,(gid_t *)groups); + ngroups = sys_getgroups(ngroups,groups); (*p_ngroups) = ngroups; - (*p_groups) = groups; DEBUG( 3, ( "%s is in %d groups: ", user, ngroups ) ); @@ -196,7 +201,7 @@ register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -uint16 register_vuid(int uid,int gid, char *unix_name, char *requested_name, BOOL guest) +uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -258,7 +263,7 @@ uint16 register_vuid(int uid,int gid, char *unix_name, char *requested_name, BOO &vuser->n_groups, &vuser->groups); - DEBUG(3,("uid %d registered to name %s\n",uid,unix_name)); + DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->real_name, "\0"); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b0c74aa53e..ee195e12ec 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -485,7 +485,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); dbgtext( "as user %s ", user ); - dbgtext( "(uid=%d, gid=%d) ", conn->uid, conn->gid ); + dbgtext( "(uid=%d, gid=%d) ", (int)conn->uid, (int)conn->gid ); dbgtext( "(pid %d)\n", (int)getpid() ); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 4ffec90521..7cd8c8673c 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -23,8 +23,8 @@ extern int DEBUGLEVEL; -static int initial_uid; -static int initial_gid; +static uid_t initial_uid; +static gid_t initial_gid; /* what user is current? */ extern struct current_user current_user; @@ -61,17 +61,16 @@ void init_uid(void) /**************************************************************************** become the specified uid ****************************************************************************/ -static BOOL become_uid(int uid) +static BOOL become_uid(uid_t uid) { if (initial_uid != 0) { return(True); } - if (uid == -1 || uid == 65535) { + if (uid == (uid_t)-1 || ((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) { static int done; if (!done) { - DEBUG(1,("WARNING: using uid %d is a security risk\n", - uid)); + DEBUG(1,("WARNING: using uid %d is a security risk\n",(int)uid)); done=1; } } @@ -79,9 +78,9 @@ static BOOL become_uid(int uid) #ifdef HAVE_TRAPDOOR_UID #ifdef HAVE_SETUIDX /* AIX3 has setuidx which is NOT a trapoor function (tridge) */ - if (setuidx(ID_EFFECTIVE, (uid_t)uid) != 0) { - if (seteuid((uid_t)uid) != 0) { - DEBUG(1,("Can't set uid (setuidx)\n")); + if (setuidx(ID_EFFECTIVE, uid) != 0) { + if (seteuid(uid) != 0) { + DEBUG(1,("Can't set uid %d (setuidx)\n", (int)uid)); return False; } } @@ -96,14 +95,14 @@ static BOOL become_uid(int uid) #endif { DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n", - uid,(int)getuid(), (int)geteuid())); - if (uid > 32000) { + (int)uid,(int)getuid(), (int)geteuid())); + if (uid > (uid_t)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) { + if (((uid == (uid_t)-1) || ((sizeof(uid_t) == 2) && (uid == 65535))) && (geteuid() != uid)) { DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n")); return(False); } @@ -117,13 +116,13 @@ static BOOL become_uid(int uid) /**************************************************************************** become the specified gid ****************************************************************************/ -static BOOL become_gid(int gid) +static BOOL become_gid(gid_t gid) { if (initial_uid != 0) return(True); - if (gid == -1 || gid == 65535) { - DEBUG(1,("WARNING: using gid %d is a security risk\n",gid)); + if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) && (gid == (gid_t)65535))) { + DEBUG(1,("WARNING: using gid %d is a security risk\n",(int)gid)); } #ifdef HAVE_SETRESUID @@ -133,7 +132,7 @@ static BOOL become_gid(int gid) #endif { DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n", - gid,(int)getgid(),(int)getegid())); + (int)gid,(int)getgid(),(int)getegid())); if (gid > 32000) { DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); } @@ -149,7 +148,7 @@ static BOOL become_gid(int gid) /**************************************************************************** become the specified uid and gid ****************************************************************************/ -static BOOL become_id(int uid,int gid) +static BOOL become_id(uid_t uid,gid_t gid) { return(become_gid(gid) && become_uid(uid)); } @@ -213,8 +212,9 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) BOOL become_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); - int snum,gid; - int uid; + int snum; + gid_t gid; + uid_t uid; /* * We need a separate check in security=share mode due to vuid -- cgit From 5a8458c377b6901b67a039eafbd5727ed1207cf3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Sep 1998 01:05:51 +0000 Subject: libsmb/clientgen.c: Fixed signed/unsigned compile warnings spotted by Herb. param/loadparm.c: smbd/oplock.c: Allow kernel oplocks to be turned off in the smb.conf file. smbd/server.c: Move init_structs() to after the smb.conf file is loaded - preparation for making a "max open files" parameter. Jeremy. (This used to be commit 6a261517a09b005f502a37941431308fa8bf2c5c) --- source3/smbd/oplock.c | 6 ++++-- source3/smbd/server.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index d5c06312f5..c5a19df0e9 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1077,9 +1077,11 @@ Disabling kernel oplock support.\n", strerror(errno) )); oplock_pipe_write = pfd[1]; close(fd); - DEBUG(3,("check_kernel_oplocks: Kernel oplocks enabled.\n")); - lp_set_kernel_oplocks(True); + + DEBUG(3,("check_kernel_oplocks: Kernel oplocks available and set to %s.\n", + lp_kernel_oplocks() ? "True" : "False" )); + } #endif /* HAVE_KERNEL_OPLOCKS */ } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index fb97cf8380..62f2bcea9f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -626,11 +626,11 @@ static void usage(char *pname) exit(1); } - init_structs(); - if (!reload_services(False)) return(-1); + init_structs(); + #ifdef WITH_SSL { extern BOOL sslEnabled; -- cgit From 5b4d94e20fdb5888da1b71a7b6a30ebede6cb06a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Sep 1998 01:49:24 +0000 Subject: (Finally) implemented "max open files" as a global smb.conf parameter. Sets up the files array correctly - limited by the smb.conf parameter and by the max fd's per process as found by getrlimit(). Jeremy. (This used to be commit eca24bd24352c688cdf48c1ef14adb8ac353468f) --- source3/smbd/files.c | 66 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e8b391d117..9b58ef5b31 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -23,17 +23,16 @@ extern int DEBUGLEVEL; -/* the only restriction is that this must be less than PIPE_HANDLE_OFFSET */ -#define MAX_FNUMS 4096 +static int real_max_open_files; -#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_FNUMS)) +#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files)) #define FILE_HANDLE_OFFSET 0x1000 static struct bitmap *file_bmap; #ifdef USE_FILES_ARRAY -static files_struct *Files[MAX_FNUMS]; +static files_struct **Files; #else static files_struct *Files; #endif @@ -66,7 +65,7 @@ files_struct *file_new(void ) increases the chance that the errant client will get an error rather than causing corruption */ if (first_file == 0) { - first_file = (getpid() ^ (int)time(NULL)) % MAX_FNUMS; + first_file = (getpid() ^ (int)time(NULL)) % real_max_open_files; } i = bitmap_find(file_bmap, first_file); @@ -81,7 +80,7 @@ files_struct *file_new(void ) * after they have finished with them. */ #ifdef USE_FILES_ARRAY - for(i = 0; i < MAX_FNUMS; i++) { + for(i = 0; i < real_max_open_files; i++) { if((fsp = Files[i]) == NULL) continue; if (attempt_close_oplocked_file(fsp)) @@ -105,7 +104,7 @@ files_struct *file_new(void ) ZERO_STRUCTP(fsp); - first_file = (i+1) % MAX_FNUMS; + first_file = (i+1) % real_max_open_files; bitmap_set(file_bmap, i); files_used++; @@ -203,7 +202,7 @@ void file_close_conn(connection_struct *conn) #ifdef USE_FILES_ARRAY int i; - for (i = 0; i < MAX_FNUMS; i++) { + for (i = 0; i < real_max_open_files; i++) { if((fsp = Files[i]) == NULL) continue; if(fsp->conn == conn && fsp->open) { @@ -229,30 +228,53 @@ void file_close_conn(connection_struct *conn) /**************************************************************************** initialise file structures ****************************************************************************/ + +#define MAX_OPEN_FUDGEFACTOR 10 + void file_init(void) { - file_bmap = bitmap_allocate(MAX_FNUMS); - - if (!file_bmap) { - exit_server("out of memory in file_init"); - } + real_max_open_files = lp_max_open_files(); #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)) { struct rlimit rlp; getrlimit(RLIMIT_NOFILE, &rlp); - /* Set the fd limit to be MAX_FNUMS + 10 to + /* Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to * account for the extra fd we need * as well as the log files and standard * handles etc. */ - rlp.rlim_cur = (MAX_FNUMS+10>rlp.rlim_max)? - rlp.rlim_max:MAX_FNUMS+10; + rlp.rlim_cur = (real_max_open_files+MAX_OPEN_FUDGEFACTOR>rlp.rlim_max)? + rlp.rlim_max:real_max_open_files+MAX_OPEN_FUDGEFACTOR; setrlimit(RLIMIT_NOFILE, &rlp); getrlimit(RLIMIT_NOFILE, &rlp); - DEBUG(3,("Maximum number of open files per session is %d\n", - (int)rlp.rlim_cur)); + if(rlp.rlim_cur != (real_max_open_files + MAX_OPEN_FUDGEFACTOR)) + DEBUG(0,("file_init: Maximum number of open files requested per session \ +was %d, actual files available per session = %d\n", + real_max_open_files, (int)rlp.rlim_cur - MAX_OPEN_FUDGEFACTOR )); + + DEBUG(2,("Maximum number of open files per session is %d\n", + (int)rlp.rlim_cur - MAX_OPEN_FUDGEFACTOR)); + + real_max_open_files = (int)rlp.rlim_cur - MAX_OPEN_FUDGEFACTOR; } #endif + + file_bmap = bitmap_allocate(real_max_open_files); + + if (!file_bmap) { + exit_server("out of memory in file_init"); + } + +#ifdef USE_FILES_ARRAY + Files = (files_struct **)malloc( sizeof(files_struct *) * real_max_open_files); + if(Files == NULL) + exit_server("out of memory for file array in file_init"); +#endif + + /* + * Ensure that pipe_handle_oppset is set correctly. + */ + set_pipe_handle_offset(real_max_open_files); } @@ -265,7 +287,7 @@ void file_close_user(int vuid) #ifdef USE_FILES_ARRAY int i; - for(i = 0; i < MAX_FNUMS; i++) { + for(i = 0; i < real_max_open_files; i++) { if((fsp = Files[i]) == NULL) continue; if((fsp->vuid == vuid) && fsp->open) { @@ -300,7 +322,7 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval files_struct *fsp; #ifdef USE_FILES_ARRAY - for(count = 0; count < MAX_FNUMS; count++) { + for(count = 0; count < real_max_open_files; count++) { if((fsp = Files[count]) == NULL) continue; if (fsp->open && @@ -338,7 +360,7 @@ files_struct *file_find_print(void) #ifdef USE_FILES_ARRAY int i; - for(i = 0; i < MAX_FNUMS; i++) { + for(i = 0; i < real_max_open_files; i++) { if((fsp = Files[i]) == NULL) continue; if (fsp->open && fsp->print_file) return fsp; @@ -362,7 +384,7 @@ void file_sync_all(connection_struct *conn) #ifdef USE_FILES_ARRAY int i; - for(i = 0; i < MAX_FNUMS; i++) { + for(i = 0; i < real_max_open_files; i++) { if((fsp = Files[i]) == NULL) continue; if (fsp->open && conn == fsp->conn) -- cgit From 864f5457be3a98631b7d8ecb6d3ba17fce5cfe0e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Sep 1998 19:27:04 +0000 Subject: Implemented directory-relative opens for NT opens. Jeremy. (This used to be commit 740784f9cf3d4f85eb71848a29b95d5db977d264) --- source3/smbd/nttrans.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4d3572c6a8..b439ba9560 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -399,6 +399,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn, /**************************************************************************** Reply to an NT create and X call. ****************************************************************************/ + int reply_ntcreate_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { @@ -411,6 +412,7 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), ((uint32)sizeof(fname)-1)); + uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); int smb_ofun; int smb_open_mode; int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); @@ -449,8 +451,43 @@ int reply_ntcreate_and_X(connection_struct *conn, /* * Get the file name. */ - StrnCpy(fname,smb_buf(inbuf),fname_len); - fname[fname_len] = '\0'; + + if(root_dir_fid != 0) { + /* + * This filename is relative to a directory fid. + */ + files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid); + size_t dir_name_len; + + if(!dir_fsp || !dir_fsp->is_directory) + return(ERROR(ERRDOS,ERRbadfid)); + + /* + * Copy in the base directory name. + */ + + pstrcpy( fname, dir_fsp->fsp_name ); + dir_name_len = strlen(fname); + + /* + * Ensure it ends in a '\'. + */ + + if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') { + pstrcat(fname, "\\"); + dir_name_len++; + } + + if(fname_len + dir_name_len >= sizeof(pstring)) + return(ERROR(ERRSRV,ERRfilespecs)); + + StrnCpy(&fname[dir_name_len], smb_buf(inbuf),fname_len); + fname[dir_name_len+fname_len] = '\0'; + + } else { + StrnCpy(fname,smb_buf(inbuf),fname_len); + fname[fname_len] = '\0'; + } /* If it's an IPC, use the pipe handler. */ @@ -694,6 +731,7 @@ static int call_nt_transact_create(connection_struct *conn, uint32 create_options = IVAL(params,32); uint32 fname_len = MIN(((uint32)IVAL(params,44)), ((uint32)sizeof(fname)-1)); + uint16 root_dir_fid = (uint16)IVAL(params,4); int smb_ofun; int smb_open_mode; int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); @@ -726,12 +764,48 @@ static int call_nt_transact_create(connection_struct *conn, if((smb_open_mode = map_share_mode( desired_access, share_access, file_attributes)) == -1) return(ERROR(ERRDOS,ERRbadaccess)); + /* * Get the file name. */ - StrnCpy(fname,params+53,fname_len); - fname[fname_len] = '\0'; + if(root_dir_fid != 0) { + /* + * This filename is relative to a directory fid. + */ + + files_struct *dir_fsp = file_fsp(params,4); + size_t dir_name_len; + + if(!dir_fsp || !dir_fsp->is_directory) + return(ERROR(ERRDOS,ERRbadfid)); + + /* + * Copy in the base directory name. + */ + + pstrcpy( fname, dir_fsp->fsp_name ); + dir_name_len = strlen(fname); + + /* + * Ensure it ends in a '\'. + */ + + if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { + pstrcat(fname, "\\"); + dir_name_len++; + } + + if(fname_len + dir_name_len >= sizeof(pstring)) + return(ERROR(ERRSRV,ERRfilespecs)); + + StrnCpy(&fname[dir_name_len], params+53, fname_len); + fname[dir_name_len+fname_len] = '\0'; + + } else { + StrnCpy(fname,params+53,fname_len); + fname[fname_len] = '\0'; + } /* If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { -- cgit From eb7f62f911583028892841f8b1f0ef9a4614040e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Oct 1998 03:07:09 +0000 Subject: got rid of USE_FILES_ARRAY code (it was unused) (This used to be commit f15ece53162304d855bea4f329f3faed8813a831) --- source3/smbd/files.c | 110 ++------------------------------------------------- 1 file changed, 4 insertions(+), 106 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 9b58ef5b31..4000439db0 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -31,11 +31,7 @@ static int real_max_open_files; static struct bitmap *file_bmap; -#ifdef USE_FILES_ARRAY -static files_struct **Files; -#else static files_struct *Files; -#endif /* a fsp to use when chaining */ static files_struct *chain_fsp = NULL; @@ -79,21 +75,12 @@ files_struct *file_new(void ) * files batch oplocked for quite a long time * after they have finished with them. */ -#ifdef USE_FILES_ARRAY - for(i = 0; i < real_max_open_files; i++) { - if((fsp = Files[i]) == NULL) - continue; - if (attempt_close_oplocked_file(fsp)) - return file_new(); - } -#else for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (attempt_close_oplocked_file(fsp)) { return file_new(); } } -#endif DEBUG(0,("ERROR! Out of file structures\n")); return NULL; @@ -112,11 +99,7 @@ files_struct *file_new(void ) fsp->fnum = i + FILE_HANDLE_OFFSET; string_init(&fsp->fsp_name,""); -#ifdef USE_FILES_ARRAY - Files[i] = fsp; -#else DLIST_ADD(Files, fsp); -#endif DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", i, fsp->fnum, files_used)); @@ -200,19 +183,6 @@ void file_close_conn(connection_struct *conn) { files_struct *fsp, *next; -#ifdef USE_FILES_ARRAY - int i; - for (i = 0; i < real_max_open_files; i++) { - if((fsp = Files[i]) == NULL) - continue; - if(fsp->conn == conn && fsp->open) { - if (fsp->is_directory) - close_directory(fsp); - else - close_file(fsp,False); - } - } -#else for (fsp=Files;fsp;fsp=next) { next = fsp->next; if (fsp->conn == conn && fsp->open) { @@ -222,7 +192,6 @@ void file_close_conn(connection_struct *conn) close_file(fsp,False); } } -#endif } /**************************************************************************** @@ -265,16 +234,10 @@ was %d, actual files available per session = %d\n", exit_server("out of memory in file_init"); } -#ifdef USE_FILES_ARRAY - Files = (files_struct **)malloc( sizeof(files_struct *) * real_max_open_files); - if(Files == NULL) - exit_server("out of memory for file array in file_init"); -#endif - - /* - * Ensure that pipe_handle_oppset is set correctly. - */ - set_pipe_handle_offset(real_max_open_files); + /* + * Ensure that pipe_handle_oppset is set correctly. + */ + set_pipe_handle_offset(real_max_open_files); } @@ -285,19 +248,6 @@ void file_close_user(int vuid) { files_struct *fsp, *next; -#ifdef USE_FILES_ARRAY - int i; - for(i = 0; i < real_max_open_files; i++) { - if((fsp = Files[i]) == NULL) - continue; - if((fsp->vuid == vuid) && fsp->open) { - if(!fsp->is_directory) - close_file(fsp,False); - else - close_directory(fsp); - } - } -#else for (fsp=Files;fsp;fsp=next) { next=fsp->next; if ((fsp->vuid == vuid) && fsp->open) { @@ -307,7 +257,6 @@ void file_close_user(int vuid) close_directory(fsp); } } -#endif } @@ -321,18 +270,6 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval int count=0; files_struct *fsp; -#ifdef USE_FILES_ARRAY - for(count = 0; count < real_max_open_files; count++) { - if((fsp = Files[count]) == NULL) - continue; - if (fsp->open && - fsp->fd_ptr->dev == dev && - fsp->fd_ptr->inode == inode && - (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True) && - (tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True)) - return fsp; - } -#else for (fsp=Files;fsp;fsp=fsp->next,count++) { if (fsp->open && fsp->fd_ptr->dev == dev && @@ -345,7 +282,6 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval return fsp; } } -#endif return NULL; } @@ -358,18 +294,9 @@ files_struct *file_find_print(void) { files_struct *fsp; -#ifdef USE_FILES_ARRAY - int i; - for(i = 0; i < real_max_open_files; i++) { - if((fsp = Files[i]) == NULL) - continue; - if (fsp->open && fsp->print_file) return fsp; - } -#else for (fsp=Files;fsp;fsp=fsp->next) { if (fsp->open && fsp->print_file) return fsp; } -#endif return NULL; } @@ -382,22 +309,12 @@ void file_sync_all(connection_struct *conn) { files_struct *fsp, *next; -#ifdef USE_FILES_ARRAY - int i; - for(i = 0; i < real_max_open_files; i++) { - if((fsp = Files[i]) == NULL) - continue; - if (fsp->open && conn == fsp->conn) - sync_file(conn,fsp); - } -#else for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (fsp->open && conn == fsp->conn) { sync_file(conn,fsp); } } -#endif } @@ -424,16 +341,7 @@ free up a fsp ****************************************************************************/ void file_free(files_struct *fsp) { -#ifdef USE_FILES_ARRAY - files_struct *fsp1 = Files[fsp->fnum - FILE_HANDLE_OFFSET]; - if(fsp != fsp1) - DEBUG(0,("file_free: fnum = %d (array offset %d) <> fsp = %x, fnum = %d!\n", - fsp->fnum, fsp->fnum - FILE_HANDLE_OFFSET, fsp1, fsp1->fnum)); - SMB_ASSERT(fsp == fsp1); - Files[fsp->fnum - FILE_HANDLE_OFFSET] = NULL; -#else DLIST_REMOVE(Files, fsp); -#endif string_free(&fsp->fsp_name); @@ -469,15 +377,6 @@ files_struct *file_fsp(char *buf, int where) fnum = SVAL(buf, where); -#ifdef USE_FILES_ARRAY - fsp = Files[fnum - FILE_HANDLE_OFFSET]; - if(!fsp) - DEBUG(0,("file_fsp: fnum = %d (array offset %d) gave null fsp !\n", - fnum, fnum - FILE_HANDLE_OFFSET)); - SMB_ASSERT(fsp != NULL); - - return (chain_fsp = fsp); -#else for (fsp=Files;fsp;fsp=fsp->next, count++) { if (fsp->fnum == fnum) { chain_fsp = fsp; @@ -488,7 +387,6 @@ files_struct *file_fsp(char *buf, int where) } } return NULL; -#endif } /**************************************************************************** -- cgit From d0fb78b85efa70f4a62618873e6a03318b1f7b38 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Oct 1998 11:54:00 +0000 Subject: use O_ACCMODE (This used to be commit cc6270f327fdc998e5e3a2d8c3b50f33a29ec3c1) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2b2f0f0524..311c494a97 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -273,7 +273,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstring fname; SMB_STRUCT_STAT statbuf; file_fd_struct *fd_ptr; - int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); + int accmode = (flags & O_ACCMODE); fsp->open = False; fsp->fd_ptr = 0; -- cgit From 6760e69a68571e01ee57b959193a56278962a23c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Oct 1998 09:42:51 +0000 Subject: added support for printing via smbwrapper You can print using "cp filename /smb/SERVER/PRINTER/jobname" You can list the current printqueue using ls (This used to be commit 080fb61b69620e26e8122705383dc2bd0468a519) --- source3/smbd/trans2.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6fd0272a0a..6d2f61f5b9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -249,7 +249,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); - return(ERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } size = sbuf.st_size; @@ -681,7 +681,7 @@ static int call_trans2findfirst(connection_struct *conn, } #endif - return(ERROR(ERRDOS,ERRbadpath)); + return(UNIXERROR(ERRDOS,ERRbadpath)); } p = strrchr(directory,'/'); @@ -707,7 +707,7 @@ static int call_trans2findfirst(connection_struct *conn, dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid)); if (dptr_num < 0) - return(ERROR(ERRDOS,ERRbadfile)); + return(UNIXERROR(ERRDOS,ERRbadfile)); /* Convert the formatted mask. */ mask_convert(mask); @@ -1475,7 +1475,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(sys_fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRbadpath)); + return(UNIXERROR(ERRDOS,ERRbadpath)); } } else { /* set path info */ @@ -1639,7 +1639,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if(file_utime(conn, fname, &tvs)!=0) { - return(ERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } } @@ -1647,7 +1647,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL)) { DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } if(size != st.st_size) @@ -1657,7 +1657,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fd = dos_open(fname,O_RDWR,0); if (fd == -1) { - return(ERROR(ERRDOS,ERRbadpath)); + return(UNIXERROR(ERRDOS,ERRbadpath)); } set_filelen(fd, size); close(fd); -- cgit From 40984f6b55212c710f6a7c7b940a785b2b607985 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Oct 1998 12:00:40 +0000 Subject: - modified resolve_name() to take a name_type - cleaned up resolve_name() (split into separate functions for each resolver) - if can't find local master then use #1B name - support listing of foreign workgroups in /smb/ (This used to be commit a4e607c17d1119925c9d0e1d05e0fe81e9a2d1aa) --- source3/smbd/password.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 5a7e20e47e..0ba4f1b7bf 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -945,7 +945,7 @@ struct cli_state *server_cryptkey(void) standard_sub_basic(desthost); strupper(desthost); - if(!resolve_name( desthost, &dest_ip)) { + if(!resolve_name( desthost, &dest_ip, 0x20)) { DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); continue; } @@ -1232,7 +1232,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); standard_sub_basic(remote_machine); strupper(remote_machine); - if(!resolve_name( remote_machine, &dest_ip)) { + if(!resolve_name( remote_machine, &dest_ip, 0x20)) { DEBUG(1,("domain_client_validate: Can't resolve address for %s\n", remote_machine)); continue; } -- cgit From 93bbfce02b4ad3f51cef9b057a3959f4e091529f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Oct 1998 01:57:03 +0000 Subject: added a function set_maxfiles() to set our file rlimit to the max possible and return the max. (This used to be commit 7a7b5ee1689b6be57752d176c7b77a2f1b453486) --- source3/smbd/files.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4000439db0..6afa059753 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -202,38 +202,19 @@ initialise file structures void file_init(void) { - real_max_open_files = lp_max_open_files(); - -#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)) - { - struct rlimit rlp; - getrlimit(RLIMIT_NOFILE, &rlp); - /* Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to - * account for the extra fd we need - * as well as the log files and standard - * handles etc. */ - rlp.rlim_cur = (real_max_open_files+MAX_OPEN_FUDGEFACTOR>rlp.rlim_max)? - rlp.rlim_max:real_max_open_files+MAX_OPEN_FUDGEFACTOR; - setrlimit(RLIMIT_NOFILE, &rlp); - getrlimit(RLIMIT_NOFILE, &rlp); - if(rlp.rlim_cur != (real_max_open_files + MAX_OPEN_FUDGEFACTOR)) - DEBUG(0,("file_init: Maximum number of open files requested per session \ -was %d, actual files available per session = %d\n", - real_max_open_files, (int)rlp.rlim_cur - MAX_OPEN_FUDGEFACTOR )); - - DEBUG(2,("Maximum number of open files per session is %d\n", - (int)rlp.rlim_cur - MAX_OPEN_FUDGEFACTOR)); - - real_max_open_files = (int)rlp.rlim_cur - MAX_OPEN_FUDGEFACTOR; - } -#endif + int real_max_open_files, lim; - file_bmap = bitmap_allocate(real_max_open_files); + lim = set_maxfiles(); + lim = MIN(lim, lp_max_open_files()); + real_max_open_files = lim - MAX_OPEN_FUDGEFACTOR; + + file_bmap = bitmap_allocate(real_max_open_files); + if (!file_bmap) { exit_server("out of memory in file_init"); } - + /* * Ensure that pipe_handle_oppset is set correctly. */ -- cgit From a2297c720388bd098394552590dd9120622f97c5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Oct 1998 12:36:23 +0000 Subject: fixed some cast warnings from "cc -64" on IRIX (This used to be commit 624097e8f4a104393865ee100e884f000ca3f6df) --- source3/smbd/dir.c | 7 ++++--- source3/smbd/trans2.c | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 03864334eb..da907b27a2 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -355,7 +355,8 @@ BOOL dptr_fill(char *buf1,unsigned int key) return(False); } offset = TellDir(p); - DEBUG(6,("fill on key %d dirptr 0x%x now at %d\n",key,(unsigned)p,offset)); + DEBUG(6,("fill on key %ld dirptr 0x%x now at %d\n",key, + (long)p,offset)); buf[0] = key; SIVAL(buf,1,offset | DPTR_MASK); return(True); @@ -446,8 +447,8 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, { dname = ReadDirName(conn->dirptr); - DEBUG(6,("readdir on dirptr 0x%x now at offset %d\n", - (unsigned)conn->dirptr,TellDir(conn->dirptr))); + DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n", + (long)conn->dirptr,TellDir(conn->dirptr))); if (dname == NULL) return(False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6d2f61f5b9..c075ae6c1b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -353,8 +353,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, reskey = 0; - DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", - (unsigned)conn->dirptr,TellDir(conn->dirptr))); + DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n", + (long)conn->dirptr,TellDir(conn->dirptr))); if (!dname) return(False); @@ -905,9 +905,9 @@ resume_key = %d resume name = %s continue=%d level = %d\n", /* Get the attr mask from the dptr */ dirtype = dptr_attr(dptr_num); - DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n", + DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n", dptr_num, mask, dirtype, - (unsigned)conn->dirptr, + (long)conn->dirptr, TellDir(conn->dirptr))); /* We don't need to check for VOL here as this is returned by -- cgit From 404f14fb36577ee182fd8a928e6cb7b374e4ecb9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 6 Oct 1998 13:10:06 +0000 Subject: implemented unix semantics for rename in smbwrapper (This used to be commit a5c18f9c82f5f76b00ff29c5668b4f0d3e8d6bd0) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 12a39589d6..6dfff54a0f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3210,7 +3210,7 @@ int rename_internals(connection_struct *conn, if (!count) exists = file_exist(directory,NULL); if (!count && exists && file_exist(newname,NULL)) { exists = True; - error = 183; + error = ERRrename; } } else { /* -- cgit From f8a3e2df1186de898866087536e56892b8e10ba7 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 6 Oct 1998 16:25:24 +0000 Subject: using wrong cli_state in "security = domain" call. (This used to be commit 1c08cc2466f7bf615a3508e028f0b65f120d2e5d) --- source3/smbd/password.c | 98 +++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0ba4f1b7bf..49ad4a514f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -915,13 +915,12 @@ BOOL check_hosts_equiv(char *user) } -static struct cli_state pw_cli; - /**************************************************************************** return the client state structure ****************************************************************************/ struct cli_state *server_client(void) { + static struct cli_state pw_cli; return &pw_cli; } @@ -930,6 +929,7 @@ support for server level security ****************************************************************************/ struct cli_state *server_cryptkey(void) { + struct cli_state *cli; fstring desthost; struct in_addr dest_ip; extern fstring local_machine; @@ -937,7 +937,9 @@ struct cli_state *server_cryptkey(void) BOOL connected_ok = False; struct nmb_name calling, called; - if (!cli_initialise(&pw_cli)) + cli = server_client(); + + if (!cli_initialise(cli)) return NULL; p = lp_passwordserver(); @@ -955,7 +957,7 @@ struct cli_state *server_cryptkey(void) continue; } - if (cli_connect(&pw_cli, desthost, &dest_ip)) { + if (cli_connect(cli, desthost, &dest_ip)) { DEBUG(3,("connected to password server %s\n",desthost)); connected_ok = True; break; @@ -964,38 +966,38 @@ struct cli_state *server_cryptkey(void) if (!connected_ok) { DEBUG(0,("password server not available\n")); - cli_shutdown(&pw_cli); + cli_shutdown(cli); return NULL; } make_nmb_name(&calling, local_machine, 0x0 , scope); make_nmb_name(&called , desthost , 0x20, scope); - if (!cli_session_request(&pw_cli, &calling, &called)) + if (!cli_session_request(cli, &calling, &called)) { DEBUG(1,("%s rejected the session\n",desthost)); - cli_shutdown(&pw_cli); + cli_shutdown(cli); return NULL; } DEBUG(3,("got session\n")); - if (!cli_negprot(&pw_cli)) { + if (!cli_negprot(cli)) { DEBUG(1,("%s rejected the negprot\n",desthost)); - cli_shutdown(&pw_cli); + cli_shutdown(cli); return NULL; } - if (pw_cli.protocol < PROTOCOL_LANMAN2 || - !(pw_cli.sec_mode & 1)) { + if (cli->protocol < PROTOCOL_LANMAN2 || + !(cli->sec_mode & 1)) { DEBUG(1,("%s isn't in user level security mode\n",desthost)); - cli_shutdown(&pw_cli); + cli_shutdown(cli); return NULL; } DEBUG(3,("password server OK\n")); - return &pw_cli; + return cli; } /**************************************************************************** @@ -1005,11 +1007,13 @@ BOOL server_validate(char *user, char *domain, char *pass, int passlen, char *ntpass, int ntpasslen) { + struct cli_state *cli; extern fstring local_machine; static unsigned char badpass[24]; + cli = server_client(); - if (!pw_cli.initialised) { - DEBUG(1,("password server %s is not connected\n", pw_cli.desthost)); + if (!cli->initialised) { + DEBUG(1,("password server %s is not connected\n", cli->desthost)); return(False); } @@ -1030,17 +1034,17 @@ BOOL server_validate(char *user, char *domain, * need to detect this as some versions of NT4.x are broken. JRA. */ - if (cli_session_setup(&pw_cli, user, (char *)badpass, sizeof(badpass), + if (cli_session_setup(cli, user, (char *)badpass, sizeof(badpass), (char *)badpass, sizeof(badpass), domain)) { - if ((SVAL(pw_cli.inbuf,smb_vwv2) & 1) == 0) { + if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { DEBUG(0,("server_validate: password server %s allows users as non-guest \ -with a bad password.\n", pw_cli.desthost)); +with a bad password.\n", cli->desthost)); DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ use this machine as the password server.\n")); - cli_ulogoff(&pw_cli); + cli_ulogoff(cli); return False; } - cli_ulogoff(&pw_cli); + cli_ulogoff(cli); } /* @@ -1048,15 +1052,15 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(&pw_cli, user, pass, passlen, ntpass, ntpasslen, domain)) { - DEBUG(1,("password server %s rejected the password\n", pw_cli.desthost)); + if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); return False; } /* if logged in as guest then reject */ - if ((SVAL(pw_cli.inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", pw_cli.desthost)); - cli_ulogoff(&pw_cli); + if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); + cli_ulogoff(cli); return(False); } @@ -1070,45 +1074,45 @@ use this machine as the password server.\n")); */ if (lp_net_wksta_user_logon()) { - DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", pw_cli.desthost)); + DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", cli->desthost)); - if (!cli_send_tconX(&pw_cli, "IPC$", "IPC", "", 1)) { - DEBUG(0,("password server %s refused IPC$ connect\n", pw_cli.desthost)); - cli_ulogoff(&pw_cli); + if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { + DEBUG(0,("password server %s refused IPC$ connect\n", cli->desthost)); + cli_ulogoff(cli); return False; } - if (!cli_NetWkstaUserLogon(&pw_cli,user,local_machine)) { - DEBUG(0,("password server %s failed NetWkstaUserLogon\n", pw_cli.desthost)); - cli_tdis(&pw_cli); - cli_ulogoff(&pw_cli); + if (!cli_NetWkstaUserLogon(cli,user,local_machine)) { + DEBUG(0,("password server %s failed NetWkstaUserLogon\n", cli->desthost)); + cli_tdis(cli); + cli_ulogoff(cli); return False; } - if (pw_cli.privilages == 0) { - DEBUG(0,("password server %s gave guest privilages\n", pw_cli.desthost)); - cli_tdis(&pw_cli); - cli_ulogoff(&pw_cli); + if (cli->privilages == 0) { + DEBUG(0,("password server %s gave guest privilages\n", cli->desthost)); + cli_tdis(cli); + cli_ulogoff(cli); return False; } - if (!strequal(pw_cli.eff_name, user)) { + if (!strequal(cli->eff_name, user)) { DEBUG(0,("password server %s gave different username %s\n", - pw_cli.desthost, - pw_cli.eff_name)); - cli_tdis(&pw_cli); - cli_ulogoff(&pw_cli); + cli->desthost, + cli->eff_name)); + cli_tdis(cli); + cli_ulogoff(cli); return False; } - cli_tdis(&pw_cli); + cli_tdis(cli); } else { - DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", pw_cli.desthost)); + DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", cli->desthost)); } - DEBUG(3,("password server %s accepted the password\n", pw_cli.desthost)); + DEBUG(3,("password server %s accepted the password\n", cli->desthost)); - cli_ulogoff(&pw_cli); + cli_ulogoff(cli); return(True); } @@ -1251,7 +1255,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) )); make_nmb_name(&calling, global_myname , 0x0 , scope); make_nmb_name(&called , remote_machine, 0x20, scope); - if (!cli_session_request(&pw_cli, &calling, &called)) + if (!cli_session_request(&cli, &calling, &called)) { DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); -- cgit From c07b2bdf9032c870f7f50a9671e8d9fb0a56739a Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 6 Oct 1998 22:03:04 +0000 Subject: dce/rpc (This used to be commit eb279cabd059603b6c8d9b74e4fd31c4ffe87593) --- source3/smbd/ipc.c | 80 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index db6ee62f91..ebb3c11da8 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3110,6 +3110,34 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, return(True); } +static BOOL api_pipe_ntlmssp(pipes_struct *p, prs_struct *pd) +{ + /* receive a negotiate; send a challenge; receive a response */ + switch (p->auth_verifier.msg_type) + { + case NTLMSSP_NEGOTIATE: + { + smb_io_rpc_auth_ntlmssp_neg("", &p->ntlmssp_neg, pd, 0); + break; + } + case NTLMSSP_AUTH: + { + smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, pd, 0); + break; + } + default: + { + /* NTLMSSP expected: unexpected message type */ + DEBUG(3,("unexpected message type in NTLMSSP %d\n", + p->auth_verifier.msg_type)); + return False; + break; + } + } + + return (pd->offset != 0); +} + struct api_cmd { char * pipe_clnt_name; @@ -3159,12 +3187,16 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) if (p->hdr.auth_len != 0) { /* decode the authentication verifier */ - smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0); + smb_io_rpc_auth_verifier("", &p->auth_verifier, pd, 0); if (pd->offset == 0) return False; - /* ignore the version number for now */ - ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP"); + ntlmssp_auth = strequal(p->auth_verifier.signature, "NTLMSSP"); + + if (ntlmssp_auth) + { + if (!api_pipe_ntlmssp(p, pd)) return False; + } } /* name has to be \PIPE\xxxxx */ @@ -3176,18 +3208,19 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) prs_init(&(p->rdata), 1024, 4, 0, False); prs_init(&(p->rhdr ), 0x10, 4, 0, False); prs_init(&(p->rauth), 1024, 4, 0, False); + prs_init(&(p->rntlm), 1024, 4, 0, False); /***/ /*** do the bind ack first ***/ /***/ make_rpc_hdr_ba(&p->hdr_ba, - p->hdr_rb.bba.max_tsize, + p->hdr_rb.bba.max_tsize, p->hdr_rb.bba.max_rsize, p->hdr_rb.bba.assoc_gid, - ack_pipe_name, - 0x1, 0x0, 0x0, - &(p->hdr_rb.transfer)); + ack_pipe_name, + 0x1, 0x0, 0x0, + &(p->hdr_rb.transfer)); smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0); mem_realloc_data(p->rdata.data, p->rdata.offset); @@ -3198,16 +3231,19 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) if (ntlmssp_auth) { - uint8 data[16]; - bzero(data, sizeof(data)); /* first 8 bytes are non-zero */ - - make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp, - 0x0a, 0x06, 0, - "NTLMSSP", 2, - 0x00000000, 0x0000b2b3, 0x000082b1, - data); - smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0); + uint8 challenge[8]; + generate_random_buffer(challenge, 8, False); + + make_rpc_auth_verifier(&p->auth_verifier, + 0x0a, 0x06, 0, + "NTLMSSP", NTLMSSP_CHALLENGE); + smb_io_rpc_auth_verifier("", &p->auth_verifier, &p->rauth, 0); mem_realloc_data(p->rauth.data, p->rauth.offset); + + make_rpc_auth_ntlmssp_chal(&p->ntlmssp_chal, + 0x000082b1, challenge); + smb_io_rpc_auth_ntlmssp_chal("", &p->ntlmssp_chal, &p->rntlm, 0); + mem_realloc_data(p->rntlm.data, p->rntlm.offset); } /***/ @@ -3216,8 +3252,8 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, p->hdr.call_id, - p->rdata.offset + p->rauth.offset + 0x10, - p->rauth.offset); + p->rdata.offset + p->rauth.offset + p->rntlm.offset + 0x10, + p->rauth.offset + p->rntlm.offset); smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0); mem_realloc_data(p->rhdr.data, p->rdata.offset); @@ -3237,8 +3273,12 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) p->rdata.data->next = p->rauth.data; p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset; - p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset; - p->rauth.data->next = NULL; + p->rauth.data->offset.end = p->rhdr.offset + p->rdata.offset + p->rauth.offset; + p->rauth.data->next = p->rntlm.data; + + p->rntlm.data->offset.start = p->rhdr.offset + p->rdata.offset + p->rauth.offset; + p->rntlm.data->offset.end = p->rhdr.offset + p->rdata.offset + p->rauth.offset + p->rntlm.offset; + p->rntlm.data->next = NULL; } else { -- cgit From 2fef8f2e87f61043e3f1a2cf7d1f2a4ff9f119ff Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 7 Oct 1998 15:22:49 +0000 Subject: dce/rpc (This used to be commit 34afa638f6f7bb145ec094510ac58f7a22dfc3aa) --- source3/smbd/ipc.c | 12 +++++++++++- source3/smbd/pipes.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 4 ++++ 4 files changed, 62 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ebb3c11da8..f2831ce888 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3159,6 +3159,7 @@ static struct api_cmd api_fd_commands[] = static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) { BOOL ntlmssp_auth = False; + uint16 assoc_gid; fstring ack_pipe_name; int i = 0; @@ -3214,10 +3215,19 @@ static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) /*** do the bind ack first ***/ /***/ + if (ntlmssp_auth) + { + assoc_gid = 0x7a77; + } + else + { + assoc_gid = p->hdr_rb.bba.assoc_gid; + } + make_rpc_hdr_ba(&p->hdr_ba, p->hdr_rb.bba.max_tsize, p->hdr_rb.bba.max_rsize, - p->hdr_rb.bba.assoc_gid, + assoc_gid, ack_pipe_name, 0x1, 0x0, 0x0, &(p->hdr_rb.transfer)); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 15d395b29a..00eec4e0e3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -105,6 +105,50 @@ int reply_open_pipe_and_X(connection_struct *conn, } +/**************************************************************************** + reply to a write and X + + This code is basically stolen from reply_write_and_X with some + wrinkles to handle pipes. +****************************************************************************/ +int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) +{ + pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); + uint32 smb_offs = IVAL(inbuf,smb_vwv3); + size_t numtowrite = SVAL(inbuf,smb_vwv10); + BOOL write_through = BITSETW(inbuf+smb_vwv7, 0); + int nwritten = -1; + int smb_doff = SVAL(inbuf, smb_vwv11); + char *data; + + if (!p) return(ERROR(ERRDOS,ERRbadfid)); + + data = smb_buf(inbuf) + smb_doff; + + if (numtowrite == 0) + { + nwritten = 0; + } + else + { + nwritten = write_pipe(p, data, numtowrite); + } + + if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) + { + return (UNIXERROR(ERRDOS,ERRnoaccess)); + } + + set_message(outbuf,6,0,True); + + SSVAL(outbuf,smb_vwv2,nwritten); + + DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", + p->pnum, nwritten)); + + return chain_reply(inbuf,outbuf,length,bufsize); +} + /**************************************************************************** reply to a read and X @@ -134,11 +178,12 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - DEBUG(3,("readX pnum=%04x min=%d max=%d nread=%d\n", + DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); return chain_reply(inbuf,outbuf,length,bufsize); } + /**************************************************************************** reply to a close ****************************************************************************/ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 656e2e99e1..6e1bdc941a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -329,7 +329,7 @@ struct smb_message_struct {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, - {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER}, + {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, {SMBffirst,"SMBffirst",reply_search,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6dfff54a0f..7cbd0520d9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2250,6 +2250,10 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng int smb_doff = SVAL(inbuf,smb_vwv11); char *data; + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) + return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize); + CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); CHECK_ERROR(fsp); -- cgit From 4c172b5575600d05f7cb15e15d0d981f920697b5 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 7 Oct 1998 16:45:44 +0000 Subject: return False _and_ a break in a switch statement. (This used to be commit e3f0f1ad9c2b81fd3489d858a9a98338001538c5) --- source3/smbd/ipc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f2831ce888..c0ce190023 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3131,7 +3131,6 @@ static BOOL api_pipe_ntlmssp(pipes_struct *p, prs_struct *pd) DEBUG(3,("unexpected message type in NTLMSSP %d\n", p->auth_verifier.msg_type)); return False; - break; } } -- cgit From 48b31ae44fb2a1961bd738b0b3e7a986259168a2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 7 Oct 1998 21:42:24 +0000 Subject: dce/rpc (This used to be commit 6677b888bdb45df00646eb7cc13005b9465ff971) --- source3/smbd/ipc.c | 251 +++------------------------------------------------ source3/smbd/pipes.c | 2 +- 2 files changed, 12 insertions(+), 241 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c0ce190023..c647a5de3e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3110,251 +3110,18 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, return(True); } -static BOOL api_pipe_ntlmssp(pipes_struct *p, prs_struct *pd) -{ - /* receive a negotiate; send a challenge; receive a response */ - switch (p->auth_verifier.msg_type) - { - case NTLMSSP_NEGOTIATE: - { - smb_io_rpc_auth_ntlmssp_neg("", &p->ntlmssp_neg, pd, 0); - break; - } - case NTLMSSP_AUTH: - { - smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, pd, 0); - break; - } - default: - { - /* NTLMSSP expected: unexpected message type */ - DEBUG(3,("unexpected message type in NTLMSSP %d\n", - p->auth_verifier.msg_type)); - return False; - } - } - - return (pd->offset != 0); -} - -struct api_cmd -{ - char * pipe_clnt_name; - char * pipe_srv_name; - BOOL (*fn) (pipes_struct *, prs_struct *); -}; - -static struct api_cmd api_fd_commands[] = -{ - { "lsarpc", "lsass", api_ntlsa_rpc }, - { "samr", "lsass", api_samr_rpc }, - { "srvsvc", "ntsvcs", api_srvsvc_rpc }, - { "wkssvc", "ntsvcs", api_wkssvc_rpc }, - { "NETLOGON", "lsass", api_netlog_rpc }, - { "winreg", "winreg", api_reg_rpc }, - { NULL, NULL, NULL } -}; - -static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) -{ - BOOL ntlmssp_auth = False; - uint16 assoc_gid; - fstring ack_pipe_name; - int i = 0; - - DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); - - for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) - { - if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && - api_fd_commands[i].fn != NULL) - { - DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", - api_fd_commands[i].pipe_clnt_name, - api_fd_commands[i].pipe_srv_name)); - fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name); - break; - } - } - - if (api_fd_commands[i].fn == NULL) return False; - - /* decode the bind request */ - smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0); - - if (pd->offset == 0) return False; - - if (p->hdr.auth_len != 0) - { - /* decode the authentication verifier */ - smb_io_rpc_auth_verifier("", &p->auth_verifier, pd, 0); - - if (pd->offset == 0) return False; - - ntlmssp_auth = strequal(p->auth_verifier.signature, "NTLMSSP"); - - if (ntlmssp_auth) - { - if (!api_pipe_ntlmssp(p, pd)) return False; - } - } - - /* name has to be \PIPE\xxxxx */ - fstrcpy(ack_pipe_name, "\\PIPE\\"); - fstrcat(ack_pipe_name, p->pipe_srv_name); - - DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); - - prs_init(&(p->rdata), 1024, 4, 0, False); - prs_init(&(p->rhdr ), 0x10, 4, 0, False); - prs_init(&(p->rauth), 1024, 4, 0, False); - prs_init(&(p->rntlm), 1024, 4, 0, False); - - /***/ - /*** do the bind ack first ***/ - /***/ - - if (ntlmssp_auth) - { - assoc_gid = 0x7a77; - } - else - { - assoc_gid = p->hdr_rb.bba.assoc_gid; - } - - make_rpc_hdr_ba(&p->hdr_ba, - p->hdr_rb.bba.max_tsize, - p->hdr_rb.bba.max_rsize, - assoc_gid, - ack_pipe_name, - 0x1, 0x0, 0x0, - &(p->hdr_rb.transfer)); - - smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0); - mem_realloc_data(p->rdata.data, p->rdata.offset); - - /***/ - /*** now the authentication ***/ - /***/ - - if (ntlmssp_auth) - { - uint8 challenge[8]; - generate_random_buffer(challenge, 8, False); - - make_rpc_auth_verifier(&p->auth_verifier, - 0x0a, 0x06, 0, - "NTLMSSP", NTLMSSP_CHALLENGE); - smb_io_rpc_auth_verifier("", &p->auth_verifier, &p->rauth, 0); - mem_realloc_data(p->rauth.data, p->rauth.offset); - - make_rpc_auth_ntlmssp_chal(&p->ntlmssp_chal, - 0x000082b1, challenge); - smb_io_rpc_auth_ntlmssp_chal("", &p->ntlmssp_chal, &p->rntlm, 0); - mem_realloc_data(p->rntlm.data, p->rntlm.offset); - } - - /***/ - /*** then do the header, now we know the length ***/ - /***/ - - make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, - p->hdr.call_id, - p->rdata.offset + p->rauth.offset + p->rntlm.offset + 0x10, - p->rauth.offset + p->rntlm.offset); - - smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0); - mem_realloc_data(p->rhdr.data, p->rdata.offset); - - /***/ - /*** link rpc header, bind acknowledgment and authentication responses ***/ - /***/ - - p->rhdr.data->offset.start = 0; - p->rhdr.data->offset.end = p->rhdr.offset; - p->rhdr.data->next = p->rdata.data; - - if (ntlmssp_auth) - { - p->rdata.data->offset.start = p->rhdr.offset; - p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; - p->rdata.data->next = p->rauth.data; - - p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset; - p->rauth.data->offset.end = p->rhdr.offset + p->rdata.offset + p->rauth.offset; - p->rauth.data->next = p->rntlm.data; - - p->rntlm.data->offset.start = p->rhdr.offset + p->rdata.offset + p->rauth.offset; - p->rntlm.data->offset.end = p->rhdr.offset + p->rdata.offset + p->rauth.offset + p->rntlm.offset; - p->rntlm.data->next = NULL; - } - else - { - p->rdata.data->offset.start = p->rhdr.offset; - p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; - p->rdata.data->next = NULL; - } - - return True; -} - -static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd) -{ - int i = 0; - - for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) - { - if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && - api_fd_commands[i].fn != NULL) - { - DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name)); - return api_fd_commands[i].fn(p, pd); - } - } - return False; -} - -static BOOL api_dce_rpc_command(char *outbuf, +static void api_rpc_trans_reply(char *outbuf, pipes_struct *p, prs_struct *pd) { - BOOL reply = False; - if (pd->data == NULL) return False; - - /* process the rpc header */ - smb_io_rpc_hdr("", &p->hdr, pd, 0); - - if (pd->offset == 0) return False; + send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset); - switch (p->hdr.pkt_type) + if (mem_buf_len(p->rhdr.data) <= p->file_offset) { - case RPC_BIND : - { - reply = api_pipe_bind_req(p, pd); - break; - } - case RPC_REQUEST: - { - reply = api_pipe_request (p, pd); - break; - } + /* all of data was sent: no need to wait for SMBreadX calls */ + mem_free_data(p->rhdr .data); + mem_free_data(p->rdata.data); } - - if (reply) - { - /* now send the reply */ - send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset); - - if (mem_buf_len(p->rhdr.data) <= p->file_offset) - { - /* all of data was sent: no need to wait for SMBreadX calls */ - mem_free_data(p->rhdr .data); - mem_free_data(p->rdata.data); - } - } - - return reply; } /**************************************************************************** @@ -3463,7 +3230,11 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, case 0x26: { /* dce/rpc command */ - reply = api_dce_rpc_command(outbuf, p, &pd); + reply = rpc_command(p, &pd); + if (reply) + { + api_rpc_trans_reply(outbuf, p, &pd); + } break; } case 0x01: diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 00eec4e0e3..65da9337b2 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -123,7 +123,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!p) return(ERROR(ERRDOS,ERRbadfid)); - data = smb_buf(inbuf) + smb_doff; + data = smb_base(inbuf) + smb_doff; if (numtowrite == 0) { -- cgit From 788263ba2f749c5bb1546ca6c9363fd508e94280 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Oct 1998 06:21:33 +0000 Subject: - fixed a bunch of warnings and minor errors - got smbtorture to compile - removed %D from some of lukes code - Luke, what is %D? it ain't portable anyway (This used to be commit 91597c12fb593f49b23c7cea5b64dbb89a0428b3) --- source3/smbd/dir.c | 2 +- source3/smbd/files.c | 2 +- source3/smbd/pipes.c | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index da907b27a2..4b1a58016c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -356,7 +356,7 @@ BOOL dptr_fill(char *buf1,unsigned int key) } offset = TellDir(p); DEBUG(6,("fill on key %ld dirptr 0x%x now at %d\n",key, - (long)p,offset)); + (long)p,(int)offset)); buf[0] = key; SIVAL(buf,1,offset | DPTR_MASK); return(True); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 6afa059753..4030ad4c49 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -202,7 +202,7 @@ initialise file structures void file_init(void) { - int real_max_open_files, lim; + int lim; lim = set_maxfiles(); lim = MIN(lim, lp_max_open_files()); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 65da9337b2..3e10065711 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -116,7 +116,6 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); uint32 smb_offs = IVAL(inbuf,smb_vwv3); size_t numtowrite = SVAL(inbuf,smb_vwv10); - BOOL write_through = BITSETW(inbuf+smb_vwv7, 0); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); char *data; -- cgit From a813f38e2dc894b548c23dea2bef98cef7d4f4e9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Oct 1998 06:49:00 +0000 Subject: - don't generate 0 params in torture - handle 0 params in ipc.c (This used to be commit c0dc8e87f0d56444a8ddff0817a94065ca295847) --- source3/smbd/ipc.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c647a5de3e..0c4d0d5bfe 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3348,7 +3348,7 @@ struct static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { - int api_command = SVAL(params,0); + int api_command; struct mem_buf rdata_buf; struct mem_buf rparam_buf; char *rdata = NULL; @@ -3358,8 +3358,14 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data BOOL reply=False; int i; + SMB_ASSERT(params != 0); + + api_command = SVAL(params,0); + DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - api_command,params+2,skip_string(params+2,1), + api_command, + params+2, + skip_string(params+2,1), tdscnt,tpscnt,mdrcnt,mprcnt)); for (i=0;api_commands[i].name;i++) @@ -3448,7 +3454,6 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize) { fstring name; - char *data=NULL,*params=NULL; uint16 *setup=NULL; int outsize = 0; @@ -3475,17 +3480,17 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (tdscnt) { if((data = (char *)malloc(tdscnt)) == NULL) { - DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt)); - return(ERROR(ERRDOS,ERRnomem)); - } + DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt)); + return(ERROR(ERRDOS,ERRnomem)); + } memcpy(data,smb_base(inbuf)+dsoff,dscnt); } if (tpscnt) { if((params = (char *)malloc(tpscnt)) == NULL) { - DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt)); - return(ERROR(ERRDOS,ERRnomem)); - } + DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt)); + return(ERROR(ERRDOS,ERRnomem)); + } memcpy(params,smb_base(inbuf)+psoff,pscnt); } @@ -3560,7 +3565,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) { DEBUG(5,("calling named_pipe\n")); - outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, + outsize = named_pipe(conn,vuid,outbuf, + name+strlen("\\PIPE\\"),setup,data,params, suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); } else { DEBUG(3,("invalid pipe name\n")); -- cgit From 3a4a2d56befe66e16003a46432ae77f6b6d62c8d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Oct 1998 21:54:26 +0000 Subject: fixed a warning (This used to be commit d4291d353b293bbc65fb0bf76c2d943733297726) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 4b1a58016c..5b7b08b476 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -355,7 +355,7 @@ BOOL dptr_fill(char *buf1,unsigned int key) return(False); } offset = TellDir(p); - DEBUG(6,("fill on key %ld dirptr 0x%x now at %d\n",key, + DEBUG(6,("fill on key %ld dirptr 0x%lx now at %d\n",key, (long)p,(int)offset)); buf[0] = key; SIVAL(buf,1,offset | DPTR_MASK); -- cgit From eaac4014f08f62ba3e64cc179650fe0fe93ea8ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Oct 1998 21:58:24 +0000 Subject: really fixed the warning this time :) (This used to be commit 64692f292fc610b90de97a85101203946ce65bfa) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5b7b08b476..db2de23f6d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -355,7 +355,7 @@ BOOL dptr_fill(char *buf1,unsigned int key) return(False); } offset = TellDir(p); - DEBUG(6,("fill on key %ld dirptr 0x%lx now at %d\n",key, + DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, (long)p,(int)offset)); buf[0] = key; SIVAL(buf,1,offset | DPTR_MASK); -- cgit From 4c2b041e78ccac4a71b368e6998644cab3140ff7 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 9 Oct 1998 06:47:22 +0000 Subject: Add a DEBUG to unix_convert (This used to be commit ac61a102473c7f23938368f9bfea494cd56344a1) --- source3/smbd/filename.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ff4d682747..d311d56b99 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -343,6 +343,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, extern char magic_char; #endif + DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); + *dirpath = 0; *bad_path = False; if(pst) { -- cgit From 7c45b3c25c665d65cfdb503724efe094b5172c12 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 9 Oct 1998 10:03:19 +0000 Subject: Added code to convert empty file names to "." so we avoid searching the cache, but only if we are not on a print share. This code is known to work on at least one site! (This used to be commit a2898af463132147cbe19b18585c793960cb39ee) --- source3/smbd/filename.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d311d56b99..1b4f7f8c77 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -368,6 +368,18 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, trim_string(name,"/","/"); + /* + * If we trimmed down to a single '\0' character + * then we should use the "." directory to avoid + * searching the cache, but not if we are in a + * printing share. + */ + + if (!*name && (!conn -> printer)) { + name[0] = '.'; + name[1] = '\0'; + } + /* * Ensure saved_last_component is valid even if file exists. */ -- cgit From 755986764f5a6b0ec25c7f20fde0a80eb4d121ba Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 9 Oct 1998 19:05:19 +0000 Subject: dce/rpc (This used to be commit 32d0f5e4a564686ad6b270dd24423ee49a81f223) --- source3/smbd/pipes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 3e10065711..7cf7fd8ea3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -99,7 +99,7 @@ int reply_open_pipe_and_X(connection_struct *conn, put_dos_date3(outbuf,smb_vwv4,mtime); SIVAL(outbuf,smb_vwv6,size); SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,0); + SSVAL(outbuf,smb_vwv11,0x0001); return chain_reply(inbuf,outbuf,length,bufsize); } -- cgit From 4e004a0b5e7521a361444f6d67a3c2910c5688c2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 9 Oct 1998 19:34:57 +0000 Subject: basic client-side ntcreateX function (hard-wired values except filename) (This used to be commit caeb99201a1471bd709b4e8f07c57e5caabf0795) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b439ba9560..758c46a6cd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -412,7 +412,7 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), ((uint32)sizeof(fname)-1)); - uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); + uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); int smb_ofun; int smb_open_mode; int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); -- cgit From 99208208fa37483f2a97c004355628423e0c40eb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Oct 1998 14:14:09 +0000 Subject: use level 0 for DEBUG() of malformed password entry in smbpasswd (This used to be commit bff457b4a469c03977683c4521464c41f74db1ae) --- source3/smbd/password.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 49ad4a514f..b505da18fa 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -470,26 +470,26 @@ static BOOL pass_check_smb(char *user,char *password, struct passwd *pwd) } if (!pass) { - DEBUG(3,("Couldn't find user %s\n",user)); + DEBUG(1,("Couldn't find user %s\n",user)); return(False); } smb_pass = getsmbpwnam(user); if (!smb_pass) { - DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); + DEBUG(0,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); } /* Quit if the account was disabled. */ if(smb_pass->acct_ctrl & ACB_DISABLED) { - DEBUG(3,("account for user %s was disabled.\n", user)); + DEBUG(0,("account for user %s was disabled.\n", user)); return(False); } /* Ensure the uid's match */ if (smb_pass->smb_userid != pass->pw_uid) { - DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); + DEBUG(0,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); } -- cgit From 935dc98f6670ba630bd2086ef9eddcc94a0562e2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 14 Oct 1998 06:29:20 +0000 Subject: dce/rpc (This used to be commit 69f5f9f88935de1f63ffc9aa19c0629b395e66e6) --- source3/smbd/password.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b505da18fa..49ad4a514f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -470,26 +470,26 @@ static BOOL pass_check_smb(char *user,char *password, struct passwd *pwd) } if (!pass) { - DEBUG(1,("Couldn't find user %s\n",user)); + DEBUG(3,("Couldn't find user %s\n",user)); return(False); } smb_pass = getsmbpwnam(user); if (!smb_pass) { - DEBUG(0,("Couldn't find user %s in smb_passwd file.\n", user)); + DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); } /* Quit if the account was disabled. */ if(smb_pass->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("account for user %s was disabled.\n", user)); + DEBUG(3,("account for user %s was disabled.\n", user)); return(False); } /* Ensure the uid's match */ if (smb_pass->smb_userid != pass->pw_uid) { - DEBUG(0,("Error : UNIX and SMB uids in password files do not match !\n")); + DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); } -- cgit From 1cdfdd4f0e1dc8610992786ce946db71f493c746 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 14 Oct 1998 07:02:12 +0000 Subject: unused variable in pipe_smb_write_X (This used to be commit cbc6ab6bb94dad7d71cfb71df3ee283831638e11) --- source3/smbd/pipes.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 7cf7fd8ea3..374aa70d0f 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -114,7 +114,6 @@ int reply_open_pipe_and_X(connection_struct *conn, int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); - uint32 smb_offs = IVAL(inbuf,smb_vwv3); size_t numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); -- cgit From c09647c3e1faa54e36c383958d9ea6def911f77d Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 14 Oct 1998 07:08:43 +0000 Subject: more warnings... (This used to be commit 8b9c0bad889d4f26987d87c54b4d8bf102af1744) --- source3/smbd/oplock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c5a19df0e9..fee1b8141d 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -54,7 +54,7 @@ BOOL open_oplock_ipc(void) if (oplock_sock == -1) { DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); +address %lx. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); global_oplock_port = 0; return(False); } -- cgit From fc7d3e4caa7650c02ef36fff83b64b06050f66b1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Oct 1998 00:55:17 +0000 Subject: config: Fix crypt prototype on RedHat Linux. include/includes.h: Fix crypt prototype on RedHat Linux. smbd/fileio.c: Fix mmap bug found by WinCE client. smbd/ipc.c: Fix WinCE wierdness with pipes being opened as \server\pipe\lanman smbd/password.c: Fix encrypted null passwords. Jeremy. (This used to be commit 475992730c0ecbf31c09b3518df2f0354cec61da) --- source3/smbd/fileio.c | 2 +- source3/smbd/ipc.c | 14 ++++++++++++-- source3/smbd/oplock.c | 2 +- source3/smbd/password.c | 14 ++++++++++---- 4 files changed, 24 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 5c4bf7dfc2..ebc4544a76 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -63,7 +63,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #if WITH_MMAP if (fsp->mmap_ptr) { - SMB_OFF_T num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; + SMB_OFF_T num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : 0; num = MIN(n,num); if (num > 0) { memcpy(data,fsp->mmap_ptr+pos,num); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0c4d0d5bfe..646ac83331 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3454,6 +3454,7 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize) { fstring name; + int name_offset = 0; char *data=NULL,*params=NULL; uint16 *setup=NULL; int outsize = 0; @@ -3563,10 +3564,19 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n", name,tdscnt,tpscnt,suwcnt)); - if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) { + /* + * WinCE wierdness.... + */ + + if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, + strlen(local_machine)) == 0)) { + name_offset = strlen(local_machine)+1; + } + + if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) { DEBUG(5,("calling named_pipe\n")); outsize = named_pipe(conn,vuid,outbuf, - name+strlen("\\PIPE\\"),setup,data,params, + name+name_offset+strlen("\\PIPE\\"),setup,data,params, suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); } else { DEBUG(3,("invalid pipe name\n")); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index fee1b8141d..b1c6d9a981 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -54,7 +54,7 @@ BOOL open_oplock_ipc(void) if (oplock_sock == -1) { DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %lx. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); +address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); global_oplock_port = 0; return(False); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 49ad4a514f..761313b688 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -379,6 +379,7 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ + BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar lm_pass[24], uchar nt_pass[24]) { @@ -386,6 +387,9 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, if (!lm_pass || !smb_pass) return(False); + DEBUG(4,("Checking SMB password for user %s\n", + smb_pass->smb_name)); + if(smb_pass->acct_ctrl & ACB_DISABLED) { DEBUG(3,("account for user %s was disabled.\n", smb_pass->smb_name)); @@ -397,9 +401,6 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, return False; } - DEBUG(4,("Checking SMB password for user %s\n", - smb_pass->smb_name)); - if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). @@ -493,6 +494,11 @@ static BOOL pass_check_smb(char *user,char *password, struct passwd *pwd) return(False); } + if(password[0] == '\0' && smb_pass->acct_ctrl & ACB_PWNOTREQ && lp_null_passwords()) { + DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->smb_name)); + return(True); + } + if (smb_password_ok(smb_pass, (unsigned char *)password, (uchar *)password)) { @@ -510,7 +516,7 @@ return True if the password is correct, False otherwise ****************************************************************************/ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) { - if (pwlen == 24) { + if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { /* if it is 24 bytes long then assume it is an encrypted password */ return pass_check_smb(user, password, pwd); -- cgit From a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 15 Oct 1998 05:47:29 +0000 Subject: bug-fixing against: AS/U: it returns dce/rpc "first" and "last" bits _clear_ in a bind/ack response, when they should be set in a (small) packet. they also, in the bind/ack do not set a secondary address string at all, so we can't check against that... Win95: client-side dce/rpc code is a bit odd. it does a "WaitNamedPipeState" and has slightly different pipe-naming (\PIPE\LANMAN is joined by \PIPE\SRVSVC, \PIPE\WINREG etc whereas nt just has \PIPE\LANMAN and \PIPE\). Win95-USRMGR.EXE: added LsaOpenPolicy (renamed existing to LsaOpenPolicy2). added SamrConnect (renamed existing to SamrConnect2). (This used to be commit a7fccd807b938cbb51002ebae8c7a48b40dbb655) --- source3/smbd/ipc.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 646ac83331..bfd618f325 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3124,6 +3124,29 @@ static void api_rpc_trans_reply(char *outbuf, } } +/**************************************************************************** + WaitNamedPipeHandleState +****************************************************************************/ +static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param) +{ + uint16 priority; + + if (!param) return False; + + priority = param[0] + (param[1] << 8); + DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority)); + + if (wait_rpc_pipe_hnd_state(p, priority)) + { + /* now send the reply */ + send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset); + + return True; + } + return False; +} + + /**************************************************************************** SetNamedPipeHandleState ****************************************************************************/ @@ -3134,7 +3157,7 @@ static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) if (!param) return False; id = param[0] + (param[1] << 8); - DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id)); + DEBUG(4,("SetNamedPipeHandleState to code %x\n", id)); if (set_rpc_pipe_hnd_state(p, id)) { @@ -3237,6 +3260,12 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, } break; } + case 0x53: + { + /* Wait Named Pipe Handle state */ + reply = api_WNPHS(outbuf, p, params); + break; + } case 0x01: { /* Set Named Pipe Handle state */ @@ -3434,6 +3463,16 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt); } + if (strequal(name,"WKSSVC") || + strequal(name,"SRVSVC") || + strequal(name,"WINREG") || + strequal(name,"SAMR") || + strequal(name,"LSARPC")) + { + DEBUG(4,("named pipe command from Win95 (wow!)\n")); + return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); + } + if (strlen(name) < 1) { return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); -- cgit From c404bb775414139a4b07a73f79cf069a083acb26 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 15 Oct 1998 23:51:07 +0000 Subject: rpcclient interactive login (with trust account changing if you are root) cli_session_setup handles null sessions correctly (This used to be commit 60c0f22a4e84703467006dfe1971384a6294a9aa) --- source3/smbd/password.c | 25 ++----------------------- source3/smbd/process.c | 2 +- 2 files changed, 3 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 761313b688..45d4d72863 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -24,8 +24,6 @@ extern int DEBUGLEVEL; extern int Protocol; -BOOL global_machine_pasword_needs_changing; - /* users from session setup */ static pstring session_users=""; @@ -1136,7 +1134,6 @@ BOOL domain_client_validate( char *user, char *domain, unsigned char local_lm_response[24]; unsigned char local_nt_reponse[24]; unsigned char trust_passwd[16]; - time_t lct; fstring remote_machine; char *p; struct in_addr dest_ip; @@ -1193,29 +1190,11 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password. */ - if(!trust_password_lock( global_myworkgroup, global_myname, False)) { - DEBUG(0,("domain_client_validate: unable to open the machine account password file for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - return False; - } - - if(get_trust_account_password( trust_passwd, &lct) == False) { - DEBUG(0,("domain_client_validate: unable to read the machine account password for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - trust_password_unlock(); + if (!trust_get_passwd( trust_passwd, global_myworkgroup, global_myname)) + { return False; } - trust_password_unlock(); - - /* - * Here we check the last change time to see if the machine - * password needs changing. JRA. - */ - - if(time(NULL) > lct + lp_machine_password_timeout()) - global_machine_pasword_needs_changing = True; - /* * At this point, smb_apasswd points to the lanman response to * the challenge in local_challenge, and smb_ntpasswd points to diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6e1bdc941a..9c00d6fc00 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -49,7 +49,7 @@ extern char *InBuffer; extern char *OutBuffer; extern int smb_read_error; extern BOOL reload_after_sighup; -extern BOOL global_machine_pasword_needs_changing; +extern BOOL global_machine_password_needs_changing; extern fstring global_myworkgroup; extern pstring global_myname; extern int max_send; -- cgit From 1bcbc67767e68ae12533c1ea44e2c0a567e4c93c Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 16 Oct 1998 00:07:25 +0000 Subject: trust password (This used to be commit fa86770d56fd4a3e280ee4f5685e29dee2a713fb) --- source3/smbd/process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9c00d6fc00..a38e6da683 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -873,7 +873,7 @@ void smbd_process(void) return; } - if(global_machine_pasword_needs_changing) + if(global_machine_password_needs_changing) { unsigned char trust_passwd_hash[16]; time_t lct; @@ -908,7 +908,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); if(t < lct + lp_machine_password_timeout()) { trust_password_unlock(); - global_machine_pasword_needs_changing = False; + global_machine_password_needs_changing = False; continue; } @@ -916,7 +916,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); change_trust_account_password( global_myworkgroup, remote_machine_list); trust_password_unlock(); - global_machine_pasword_needs_changing = False; + global_machine_password_needs_changing = False; } /* -- cgit From 070b33489179d07ed76530ad52b828e6e708789d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Oct 1998 00:54:16 +0000 Subject: trans2.h: Added Thursby MAC extension. smbd/trans2.c: Added Thursby MAX extension. libsmb/clientgen.c: Fixed smbtorture lock code. Jeremy. (This used to be commit 514e52e4b4d6c7db7ebe2265e60c77b4f18d11b3) --- source3/smbd/trans2.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c075ae6c1b..550be0df41 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1170,6 +1170,13 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,0,0); /* dev type */ SIVAL(pdata,4,0); /* characteristics */ break; + case SMB_MAC_QUERY_FS_INFO: + /* + * Thursby MAC extension... + */ + data_len = 88; + SIVAL(pdata,84,0x100); /* Don't support mac... */ + break; default: return(ERROR(ERRDOS,ERRunknownlevel)); } -- cgit From f3793be1651c055da7cfa58afb817547df766de8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Oct 1998 06:16:10 +0000 Subject: Re-added code to tell the user how many open files they have. Needed for server diagnosis purposes... Jeremy. (This used to be commit 04d79a9ae515e7259277f9980552f1d61df239f1) --- source3/smbd/files.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4030ad4c49..c369a45bab 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -202,13 +202,23 @@ initialise file structures void file_init(void) { - int lim; + int request_max_open_files = lp_max_open_files(); + int real_lim; - lim = set_maxfiles(); - lim = MIN(lim, lp_max_open_files()); + /* + * Set the max_open files to be the requested + * max plus a fudgefactor to allow for the extra + * fd's we need such as log files etc... + */ + real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR); + + real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR; + + if(real_max_open_files != request_max_open_files) { + DEBUG(1,("file_init: Information only: requested %d \ +open files, %d are available.\n", request_max_open_files, real_max_open_files)); + } - real_max_open_files = lim - MAX_OPEN_FUDGEFACTOR; - file_bmap = bitmap_allocate(real_max_open_files); if (!file_bmap) { -- cgit From 967dcab94580a0c1bf9ee6335abc0d64001154b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Oct 1998 17:40:58 +0000 Subject: only do the MAC extensions if we are a NTFS filesystem (This used to be commit 91d224735d1a4ef26d75d87e3b35d8d156b8998b) --- source3/smbd/trans2.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 550be0df41..f9186115f5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1171,12 +1171,16 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,4,0); /* characteristics */ break; case SMB_MAC_QUERY_FS_INFO: - /* - * Thursby MAC extension... - */ - data_len = 88; - SIVAL(pdata,84,0x100); /* Don't support mac... */ - break; + /* + * Thursby MAC extension... ONLY on NTFS filesystems + * once we do streams then we don't need this + */ + if (strequal(lp_fstype(SNUM(conn)),"NTFS")) { + data_len = 88; + SIVAL(pdata,84,0x100); /* Don't support mac... */ + break; + } + /* drop through */ default: return(ERROR(ERRDOS,ERRunknownlevel)); } -- cgit From 5cb99177aff3522427d520d5f5159989f6d72265 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 16 Oct 1998 20:13:26 +0000 Subject: setup_groups() - code clarification. no functional change. (This used to be commit dae7c5ea9a139552e1722357172fa1ad0c4a7143) --- source3/smbd/password.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 45d4d72863..3ab963bfa8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -157,14 +157,16 @@ int setup_groups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_gro { int i,ngroups; gid_t grp = 0; - gid_t *groups = NULL; + gid_t *groups = NULL; - if (-1 == initgroups(user,gid)) { - if (getuid() == 0) { + 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)); + if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000) + { + DEBUG(0,("This is probably a problem with the account %s\n", user)); } } return -1; @@ -172,20 +174,24 @@ int setup_groups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_gro ngroups = sys_getgroups(0,&grp); if (ngroups <= 0) - ngroups = 32; + { + ngroups = 32; + } - if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) { - DEBUG(0,("setup_groups malloc fail !\n")); - return -1; - } + if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) + { + DEBUG(0,("setup_groups malloc fail !\n")); + return -1; + } - ngroups = sys_getgroups(ngroups,groups); + 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++ ) { + for (i = 0; i < ngroups; i++ ) + { DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) ); } DEBUG( 3, ( "\n" ) ); -- cgit From 3637ad5f2b0e5716aceaada0eed47f926c95520f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 16 Oct 1998 20:18:46 +0000 Subject: cli_nt_session_open() encrypt arg removed (This used to be commit 63def717992695ed4a4933c2605abe26086fb8c7) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3ab963bfa8..ac8210abf8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1313,7 +1313,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(&cli, PIPE_NETLOGON, False) == False) { + if(cli_nt_session_open(&cli, PIPE_NETLOGON) == False) { DEBUG(0,("domain_client_validate: unable to open the domain client session to \ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); cli_nt_session_close(&cli); -- cgit From 97f0c9d55014db221fdceaaf07318ae9df9688a1 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 16 Oct 1998 21:36:19 +0000 Subject: made pass_check_smb() available for dce/rpc use. (This used to be commit 95e8a910c5d9ba0ef57669fb1256eaa932e0bb09) --- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 59 ++++++++++++++++++++++++++++--------------------- source3/smbd/reply.c | 4 ++-- 3 files changed, 37 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index bfd618f325..df04cd82a0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1653,7 +1653,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param * Older versions of Windows seem to do this. */ - if (password_ok(user,pass1,strlen(pass1),NULL) && + if (password_ok(user, pass1,strlen(pass1),NULL) && chgpasswd(user,pass1,pass2,False)) { SSVAL(*rparam,0,NERR_Success); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ac8210abf8..4df359f46c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -449,39 +449,38 @@ check if a username/password is OK assuming the password is a 24 byte SMB hash return True if the password is correct, False otherwise ****************************************************************************/ -static BOOL pass_check_smb(char *user,char *password, struct passwd *pwd) +BOOL pass_check_smb(char *user, char *domain, + char *challenge, char *lm_pwd, char *nt_pwd, + struct passwd *pwd) { struct passwd *pass; - uchar challenge[8]; struct smb_passwd *smb_pass; - BOOL challenge_done; - if (!password) { + if (!lm_pwd || !nt_pwd) + { return(False); } - challenge_done = last_challenge(challenge); - - if (!challenge_done) { - DEBUG(0,("Error: challenge not done for user=%s\n", user)); - return False; - } - - if (pwd && !user) { + if (pwd != NULL && user == NULL) + { pass = (struct passwd *) pwd; user = pass->pw_name; - } else { + } + else + { pass = Get_Pwnam(user,True); } - if (!pass) { + if (pass != NULL) + { DEBUG(3,("Couldn't find user %s\n",user)); return(False); } smb_pass = getsmbpwnam(user); - if (!smb_pass) { + if (smb_pass != NULL) + { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); } @@ -493,19 +492,20 @@ static BOOL pass_check_smb(char *user,char *password, struct passwd *pwd) } /* Ensure the uid's match */ - if (smb_pass->smb_userid != pass->pw_uid) { + if (smb_pass->smb_userid != pass->pw_uid) + { DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); } - if(password[0] == '\0' && smb_pass->acct_ctrl & ACB_PWNOTREQ && lp_null_passwords()) { + if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords()) + { DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->smb_name)); return(True); } - if (smb_password_ok(smb_pass, - (unsigned char *)password, - (uchar *)password)) { + if (smb_password_ok(smb_pass, (uchar *)lm_pwd, (uchar *)nt_pwd)) + { return(True); } @@ -518,12 +518,21 @@ check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) +BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) { - if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { - /* if it is 24 bytes long then assume it is an encrypted - password */ - return pass_check_smb(user, password, pwd); + if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) + { + /* if 24 bytes long assume it is an encrypted password */ + uchar challenge[8]; + + if (!last_challenge(challenge)) + { + DEBUG(0,("Error: challenge not done for user=%s\n", user)); + return False; + } + + return pass_check_smb(user, global_myworkgroup, + challenge, password, password, pwd); } return pass_check(user, password, pwlen, pwd, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7cbd0520d9..5afc4593e6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -651,12 +651,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int 128 length unicode */ if(smb_ntpasslen) { - if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) + if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); else valid_nt_password = True; } - if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) + if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) { if (lp_security() >= SEC_USER) { #if (GUEST_SESSSETUP == 0) -- cgit From b6993a89af080d4d5c176ae9d539ff553f69c247 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 16 Oct 1998 21:41:42 +0000 Subject: !pass -> pass != NULL is wrong: !pass -> pass == NULL is correct. oops. (This used to be commit 866e1018180a70ff2ffa39e6a5ce5f187eca2764) --- source3/smbd/password.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 4df359f46c..1c9eb19759 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -471,7 +471,7 @@ BOOL pass_check_smb(char *user, char *domain, pass = Get_Pwnam(user,True); } - if (pass != NULL) + if (pass == NULL) { DEBUG(3,("Couldn't find user %s\n",user)); return(False); @@ -479,7 +479,7 @@ BOOL pass_check_smb(char *user, char *domain, smb_pass = getsmbpwnam(user); - if (smb_pass != NULL) + if (smb_pass == NULL) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); -- cgit From fc62d6bf368c950e1e51bc42771cce8b299df42c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 Oct 1998 17:41:13 +0000 Subject: Small tidyups for gcc in 'preen' mode.... Jeremy. (This used to be commit 60dc1a4a00a22088d33369588b0d5eb292cf084a) --- source3/smbd/quotas.c | 1 + source3/smbd/ssl.c | 1 + 2 files changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index b7a538e189..716c2357c6 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -661,6 +661,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #else /* this keeps fussy compilers happy */ + void quotas_dummy(void); void quotas_dummy(void) {} #endif /* QUOTAS */ diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index 27bb8f3a52..1c953272c3 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -261,5 +261,6 @@ char *reqHosts, *resignHosts; } #else /* WITH_SSL */ + void ssl_dummy(void); void ssl_dummy(void) {;} /* So some compilers don't complain. */ #endif /* WITH_SSL */ -- cgit From b4ef754715a8dcb67341f30e0c7f06d18c3ebf00 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 18 Oct 1998 19:30:26 +0000 Subject: check for lp_nt_pipe_support() in open calls (This used to be commit 44d901b3e040a520c4ad9089e68c566c78acacca) --- source3/smbd/nttrans.c | 2 +- source3/smbd/reply.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 758c46a6cd..128a234304 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -491,7 +491,7 @@ int reply_ntcreate_and_X(connection_struct *conn, /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(conn)) { + if (IS_IPC(conn) && lp_nt_pipe_support()) { int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5afc4593e6..d801ce4a63 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1353,7 +1353,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt files_struct *fsp; /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) + if (IS_IPC(conn) && lp_nt_pipe_support()) return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); /* XXXX we need to handle passed times, sattr and flags */ -- cgit From b8aec499dc49b1d86d9f44296e07d40232813642 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 18 Oct 1998 22:06:35 +0000 Subject: Fixed sys_lseek and seek_file calls so all returns are *checked* :-). Jeremy. (This used to be commit b8b781191dd7d28944d87eec5fa0fbef798e289b) --- source3/smbd/connection.c | 6 ++++- source3/smbd/fileio.c | 13 +++++++-- source3/smbd/reply.c | 67 ++++++++++++++++++++++++++++++++++++----------- source3/smbd/trans2.c | 3 ++- 4 files changed, 70 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 0170fa5497..af74e40f6a 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -166,7 +166,11 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO } if (Clear && crec.pid && !process_exists(crec.pid)) { - sys_lseek(fd,i*sizeof(crec),SEEK_SET); + if(sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec)) { + DEBUG(0,("claim_connection: ERROR: sys_lseek failed to seek \ +to %d\n", i*sizeof(crec) )); + continue; + } bzero((void *)&crec,sizeof(crec)); write(fd, &crec,sizeof(crec)); if (foundi < 0) foundi = i; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index ebc4544a76..c7ffb6412d 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -31,11 +31,20 @@ seek a file. Try to avoid the seek if possible SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { SMB_OFF_T offset = 0; + SMB_OFF_T seek_ret; if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; - fsp->pos = (sys_lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset); + seek_ret = sys_lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); + + if((seek_ret == -1) || (seek_ret != pos+offset)) { + DEBUG(0,("seek_file: sys_lseek failed. Error was %s\n", strerror(errno) )); + fsp->pos = -1; + return -1; + } + + fsp->pos = seek_ret - offset; DEBUG(10,("seek_file: requested pos = %.0f, new pos = %.0f\n", (double)(pos+offset), (double)fsp->pos )); @@ -75,7 +84,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) } #endif - if (seek_file(fsp,pos) != pos) { + if (seek_file(fsp,pos) == -1) { DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); return(ret); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d801ce4a63..bcb408c2a6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1844,6 +1844,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #if UNSAFE_READRAW { + BOOL seek_fail = False; int predict=0; _smb_setlen(header,nread); @@ -1852,11 +1853,18 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread); #endif /* USE_READ_PREDICTION */ - if ((nread-predict) > 0) - seek_file(fsp,startpos + predict); - - ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict, - startpos+predict); + if ((nread-predict) > 0) { + if(seek_file(fsp,startpos + predict) == -1) { + DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); + ret = 0; + seek_fail = True; + } + } + + if(!seek_fail) + ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client, + (SMB_OFF_T)(nread-predict),header,4+predict, + startpos+predict); } if (ret != nread+4) @@ -2065,8 +2073,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if (is_locked(fsp,conn,tcount,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - if (seek_file(fsp,startpos) != startpos) + if (seek_file(fsp,startpos) == -1) { DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos)); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } if (numtowrite>0) nwritten = write_file(fsp,data,numtowrite); @@ -2153,7 +2163,8 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fsp,startpos); + if(seek_file(fsp,startpos) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); /* The special X/Open SMB protocol handling of zero length writes is *NOT* done for @@ -2205,7 +2216,8 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fsp,startpos); + if(seek_file(fsp,startpos) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); /* X/Open SMB protocol says that if smb_vwv1 is zero then the file size should be extended or @@ -2272,7 +2284,8 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fsp,startpos); + if(seek_file(fsp,startpos) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); /* X/Open SMB protocol says that, unlike SMBwrite if the length is zero then NO truncation is @@ -2331,7 +2344,9 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, umode = SEEK_SET; break; } - res = sys_lseek(fsp->fd_ptr->fd,startpos,umode); + if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + fsp->pos = res; outsize = set_message(outbuf,2,0,True); @@ -2469,7 +2484,8 @@ int reply_writeclose(connection_struct *conn, if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fsp,startpos); + if(seek_file(fsp,startpos) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); nwritten = write_file(fsp,data,numtowrite); @@ -3312,7 +3328,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, { int Access,action; SMB_STRUCT_STAT st; - int ret=0; + int ret=-1; files_struct *fsp1,*fsp2; pstring dest; @@ -3357,7 +3373,15 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END); + if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { + DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", + strerror(errno) )); + /* + * Stop the copy from occurring. + */ + ret = -1; + st.st_size = 0; + } } if (st.st_size) @@ -3807,7 +3831,9 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if (is_locked(fsp,conn,tcount,startpos,F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - seek_file(fsp,startpos); + if(seek_file(fsp,startpos) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + nwritten = write_file(fsp,data,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) @@ -3909,7 +3935,18 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz if(wbms->wr_discard) return -1; /* Just discard the packet */ - seek_file(fsp,startpos); + if(seek_file(fsp,startpos) == -1) + { + if(write_through) + { + /* We are returning an error - we can delete the aux struct */ + if (wbms) free((char *)wbms); + fsp->wbmpx_ptr = NULL; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess)); + } + nwritten = write_file(fsp,data,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f9186115f5..62bfb612e5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1253,7 +1253,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR); + if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); } else { /* qpathinfo */ info_level = SVAL(params,0); -- cgit From 01de6030843f5f402dee8bf72f564a91ae8437ca Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 19 Oct 1998 17:32:10 +0000 Subject: - dce/rpc code - removed debug info in struni2 and unistr2 (security risk) - rpc_pipe function was getting pointer to data then calling realloc *dur* - password check function, the start of "credential checking", user, wks, domain, pass as the credentials (not just user,pass which is incorrect in a domain context) - cli_write needs to return ssize_t not size_t, because total can be -1 if the write fails. - fixed signed / unsigned warnings (how come i don't get those any more when i compile with gcc???) - nt password change added in smbd. yes, jeremy, i verified that the SMBtrans2 version still works. (This used to be commit fcfb40d2b0fc565ee4f66b3a3761c246366a2ef3) --- source3/smbd/chgpasswd.c | 323 +++++++++++++++++++++++++++++++---------------- source3/smbd/ipc.c | 24 +--- source3/smbd/password.c | 23 +++- source3/smbd/reply.c | 2 +- 4 files changed, 234 insertions(+), 138 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 4131bc9297..45497e4cf8 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -69,7 +69,7 @@ static int findpty(char **slave) grantpt(master); unlockpt(master); *slave = ptsname(master); - if(*slave == NULL) { + if (*slave == NULL) { DEBUG(0,("findpty: Unable to create master/slave pty pair.\n")); return -1; } else { @@ -109,7 +109,7 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, int gid; int uid; - if(pass == NULL) { + if (pass == NULL) { DEBUG(0,("dochild: user name %s doesn't exist in the UNIX password database.\n", name)); return False; @@ -180,7 +180,7 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, } /* make us completely into the right uid */ - if(!as_root) { + if (!as_root) { #ifdef HAVE_SETRESUID setresgid(0,0,0); setresuid(0,0,0); @@ -269,7 +269,7 @@ static int talktochild(int master, char *chatsequence) if (!strequal(chatbuf,".")) ok = expect(master,chatbuf,buf); - if(lp_passwd_chat_debug()) + if (lp_passwd_chat_debug()) DEBUG(100,("talktochild: chatbuf=[%s] responsebuf=[%s]\n",chatbuf,buf)); if (!ok) { @@ -282,7 +282,7 @@ static int talktochild(int master, char *chatsequence) if (!strequal(chatbuf,".")) writestring(master,chatbuf); - if(lp_passwd_chat_debug()) + if (lp_passwd_chat_debug()) DEBUG(100,("talktochild: sendbuf=[%s]\n",chatbuf)); } @@ -352,16 +352,16 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc /* make sure it doesn't freeze */ alarm(20); - if(as_root) + if (as_root) become_root(False); DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid())); chstat = dochild(master, slavedev, name, passwordprogram, as_root); - if(as_root) + if (as_root) unbecome_root(False); } - if(chstat) + if (chstat) DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); return (chstat); } @@ -416,7 +416,7 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) len = strlen(oldpass); for(i = 0; i < len; i++) { - if(iscntrl((int)oldpass[i])) { + if (iscntrl((int)oldpass[i])) { DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n")); return False; } @@ -424,7 +424,7 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) len = strlen(newpass); for(i = 0; i < len; i++) { - if(iscntrl((int)newpass[i])) { + if (iscntrl((int)newpass[i])) { DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n")); return False; } @@ -452,12 +452,12 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) Code to check the lanman hashed password. ************************************************************/ -BOOL check_lanman_password(char *user, unsigned char *pass1, - unsigned char *pass2, struct smb_passwd **psmbpw) +BOOL check_lanman_password(char *user, uchar *pass1, + uchar *pass2, struct smb_passwd **psmbpw) { - unsigned char unenc_new_pw[16]; - unsigned char unenc_old_pw[16]; - unsigned char null_pw[16]; + uchar unenc_new_pw[16]; + uchar unenc_old_pw[16]; + uchar null_pw[16]; struct smb_passwd *smbpw; *psmbpw = NULL; @@ -466,21 +466,21 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, smbpw = getsmbpwnam(user); unbecome_root(0); - if(smbpw == NULL) + if (smbpw == NULL) { DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n")); return False; } - if(smbpw->acct_ctrl & ACB_DISABLED) + if (smbpw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } - if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { - unsigned char no_pw[14]; + uchar no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); smbpw->smb_passwd = null_pw; @@ -496,7 +496,7 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, D_P16(unenc_new_pw, pass1, unenc_old_pw); /* Check that the two old passwords match. */ - if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); return False; @@ -512,27 +512,27 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, no longer be valid. ************************************************************/ -BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2) +BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2) { - unsigned char unenc_new_pw[16]; - unsigned char null_pw[16]; + uchar unenc_new_pw[16]; + uchar null_pw[16]; BOOL ret; - if(smbpw == NULL) + if (smbpw == NULL) { DEBUG(0,("change_lanman_password: no smb password entry.\n")); return False; } - if(smbpw->acct_ctrl & ACB_DISABLED) + if (smbpw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); return False; } - if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { - unsigned char no_pw[14]; + uchar no_pw[14]; memset(no_pw, '\0', 14); E_P16((uchar *)no_pw, (uchar *)null_pw); smbpw->smb_passwd = null_pw; @@ -556,90 +556,197 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi } /*********************************************************** - Code to check the OEM hashed password. + Code to check and change the OEM hashed password. ************************************************************/ - -BOOL check_oem_password(char *user, unsigned char *data, - struct smb_passwd **psmbpw, char *new_passwd, - int new_passwd_size) +BOOL pass_oem_change(char *user, + uchar *lmdata, uchar *lmhash, + uchar *ntdata, uchar *nthash) { - struct smb_passwd *smbpw = NULL; - int new_pw_len; - fstring upper_case_new_passwd; - unsigned char new_p16[16]; - unsigned char unenc_old_pw[16]; - unsigned char null_pw[16]; - - become_root(0); - *psmbpw = smbpw = getsmbpwnam(user); - unbecome_root(0); - - if(smbpw == NULL) - { - DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); - return False; - } - - if(smbpw->acct_ctrl & ACB_DISABLED) - { - DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); - return False; - } - - if((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) - { - unsigned char no_pw[14]; - memset(no_pw, '\0', 14); - E_P16((uchar *)no_pw, (uchar *)null_pw); - smbpw->smb_passwd = null_pw; - } else if (smbpw->smb_passwd == NULL) { - DEBUG(0,("check_oem_password: no lanman password !\n")); - return False; - } - - /* - * Call the hash function to get the new password. - */ - SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd, True); - - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - new_pw_len = IVAL(data,512); - if(new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); - return False; - } - - memcpy(new_passwd, &data[512-new_pw_len], new_pw_len); - new_passwd[new_pw_len] = '\0'; - - /* - * To ensure we got the correct new password, hash it and - * use it as a key to test the passed old password. - */ - - memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd)); - fstrcpy(upper_case_new_passwd, new_passwd); - strupper(upper_case_new_passwd); - - E_P16((uchar *)upper_case_new_passwd, new_p16); - - /* - * Now use new_p16 as the key to see if the old - * password matches. - */ - D_P16(new_p16, &data[516], unenc_old_pw); + fstring new_passwd; + struct smb_passwd *sampw; + BOOL ret = check_oem_password( user, lmdata, lmhash, ntdata, nthash, + &sampw, + new_passwd, sizeof(new_passwd)); + + /* + * At this point we have the new case-sensitive plaintext + * password in the fstring new_passwd. If we wanted to synchronise + * with UNIX passwords we would call a UNIX password changing + * function here. However it would have to be done as root + * as the plaintext of the old users password is not + * available. JRA. + */ + + if ( ret && lp_unix_password_sync()) + { + ret = chgpasswd(user,"", new_passwd, True); + } + + if (ret) + { + ret = change_oem_password( sampw, new_passwd, False ); + } + + memset(new_passwd, 0, sizeof(new_passwd)); + + return ret; +} - if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { - DEBUG(0,("check_oem_password: old password doesn't match.\n")); - return False; - } +/*********************************************************** + Code to check the OEM hashed password. - memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd)); + this function ignores the 516 byte nt OEM hashed password + but does use the lm OEM password to check the nt hashed-hash. - return True; +************************************************************/ +BOOL check_oem_password(char *user, + uchar *lmdata, uchar *lmhash, + uchar *ntdata, uchar *nthash, + struct smb_passwd **psmbpw, char *new_passwd, + int new_passwd_size) +{ + struct smb_passwd *smbpw = NULL; + int new_pw_len; + uchar new_ntp16[16]; + uchar unenc_old_ntpw[16]; + uchar new_p16[16]; + uchar unenc_old_pw[16]; + uchar null_pw[16]; + uchar null_ntpw[16]; + uchar no_pw[2]; + BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); + + become_root(False); + *psmbpw = smbpw = getsmbpwnam(user); + unbecome_root(False); + + if (smbpw == NULL) + { + DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); + return False; + } + + if (smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + return False; + } + + /* construct a null password (in case one is needed */ + no_pw[0] = 0; + no_pw[1] = 0; + nt_lm_owf_gen(no_pw, null_ntpw, null_pw); + + /* check for null passwords */ + if (smbpw->smb_passwd == NULL) + { + if (smbpw->acct_ctrl & ACB_PWNOTREQ) + { + smbpw->smb_passwd = null_pw; + } + else + { + DEBUG(0,("check_oem_password: no lanman password !\n")); + return False; + } + } + + if (smbpw->smb_nt_passwd == NULL && nt_pass_set) + { + if (smbpw->acct_ctrl & ACB_PWNOTREQ) + { + smbpw->smb_nt_passwd = null_pw; + } + else + { + DEBUG(0,("check_oem_password: no ntlm password !\n")); + return False; + } + } + + /* + * Call the hash function to get the new password. + */ + SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); + + /* + * The length of the new password is in the last 4 bytes of + * the data buffer. + */ + + new_pw_len = IVAL(lmdata, 512); + if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) + { + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); + return False; + } + + if (nt_pass_set) + { + /* + * nt passwords are in unicode + */ + int uni_pw_len = new_pw_len; + char *pw; + new_pw_len /= 2; + pw = unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); + memcpy(new_passwd, pw, new_pw_len+1); + } + else + { + memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); + new_passwd[new_pw_len] = '\0'; + } + + /* + * To ensure we got the correct new password, hash it and + * use it as a key to test the passed old password. + */ + + nt_lm_owf_gen(new_passwd, new_ntp16, new_p16); + + if (!nt_pass_set) + { + /* + * Now use new_p16 as the key to see if the old + * password matches. + */ + D_P16(new_p16 , lmhash, unenc_old_pw); + + if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + { + DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + return False; + } + +#ifdef DEBUG_PASSWORD + DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); +#endif + return True; + } + + /* + * Now use new_p16 as the key to see if the old + * password matches. + */ + D_P16(new_ntp16, lmhash, unenc_old_pw); + D_P16(new_ntp16, nthash, unenc_old_ntpw); + + if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + { + DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + return False; + } + + if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16)) + { + DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); + return False; + } +#ifdef DEBUG_PASSWORD + DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); +#endif + return True; } /*********************************************************** @@ -653,8 +760,8 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL overri { int ret; fstring upper_case_new_passwd; - unsigned char new_nt_p16[16]; - unsigned char new_p16[16]; + uchar new_nt_p16[16]; + uchar new_p16[16]; memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd)); fstrcpy(upper_case_new_passwd, new_passwd); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index df04cd82a0..2b8b8698db 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1692,11 +1692,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * int *rdata_len,int *rparam_len) { fstring user; - fstring new_passwd; - struct smb_passwd *sampw = NULL; char *p = param + 2; - int ret = True; - *rparam_len = 2; *rparam = REALLOC(*rparam,*rparam_len); @@ -1736,24 +1732,8 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * */ (void)Get_Pwnam( user, True); - if(check_oem_password( user, (unsigned char *)data, &sampw, - new_passwd, (int)sizeof(new_passwd)) == False) { - return True; - } - - /* - * At this point we have the new case-sensitive plaintext - * password in the fstring new_passwd. If we wanted to synchronise - * with UNIX passwords we would call a UNIX password changing - * function here. However it would have to be done as root - * as the plaintext of the old users password is not - * available. JRA. - */ - - if(lp_unix_password_sync()) - ret = chgpasswd(user,"", new_passwd, True); - - if(ret && change_oem_password( sampw, new_passwd, False)) { + if (pass_oem_change(user, (uchar*) data, &data[516], NULL, NULL)) + { SSVAL(*rparam,0,NERR_Success); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1c9eb19759..eac8c9cd65 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -383,8 +383,7 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ - -BOOL smb_password_ok(struct smb_passwd *smb_pass, +BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], uchar lm_pass[24], uchar nt_pass[24]) { uchar challenge[8]; @@ -400,9 +399,19 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, return(False); } - if (!last_challenge(challenge)) { - DEBUG(1,("no challenge done - password failed\n")); - return False; + if (chal == NULL) + { + DEBUG(5,("use last SMBnegprot challenge\n")); + if (!last_challenge(challenge)) + { + DEBUG(1,("no challenge done - password failed\n")); + return False; + } + } + else + { + DEBUG(5,("challenge received\n")); + memcpy(challenge, chal, 8); } if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) { @@ -450,7 +459,7 @@ SMB hash return True if the password is correct, False otherwise ****************************************************************************/ BOOL pass_check_smb(char *user, char *domain, - char *challenge, char *lm_pwd, char *nt_pwd, + uchar *chal, char *lm_pwd, char *nt_pwd, struct passwd *pwd) { struct passwd *pass; @@ -504,7 +513,7 @@ BOOL pass_check_smb(char *user, char *domain, return(True); } - if (smb_password_ok(smb_pass, (uchar *)lm_pwd, (uchar *)nt_pwd)) + if (smb_password_ok(smb_pass, chal, (uchar *)lm_pwd, (uchar *)nt_pwd)) { return(True); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bcb408c2a6..8b96ff17fd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -413,7 +413,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) + if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); -- cgit From 60cf45b2bc7a2a57fbda303440655cf2640cab35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Oct 1998 03:17:43 +0000 Subject: smbd/nttrans.c smbd/trans2.c: First fixes for NT5.0beta2. That redirector has some *horrible* bugs ! smbwrapper/shared.c smbwrapper/smbsh.c smbwrapper/smbw.c: Fixed gcc warnings. Jeremy. (This used to be commit 76448d1d82a78520953c662afee0886122ce134b) --- source3/smbd/nttrans.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/trans2.c | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 76 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 128a234304..d30b59f0d3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -232,6 +232,39 @@ static int send_nt_replies(char *outbuf, int bufsize, char *params, return 0; } +/**************************************************************************** + (Hopefully) temporary call to fix bugs in NT5.0beta2. This OS sends unicode + strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!! +****************************************************************************/ + +static void my_wcstombs(char *dst, uint16 *src, size_t len) +{ + size_t i; + + for(i = 0; i < len; i++) + dst[i] = (char)SVAL(src,i*2); +} + +static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) +{ + if(data_len - fname_len > 1) { + /* + * NT 5.0 Beta 2 has kindly sent us a UNICODE string + * without bothering to set the unicode bit. How kind. + * + * Firstly - ensure that the data offset is aligned + * on a 2 byte boundary - add one if not. + */ + fname_len = fname_len/2; + if(data_offset & 1) + data_offset++; + my_wcstombs( fname, (uint16 *)(inbuf+data_offset), fname_len); + } else { + StrnCpy(fname,inbuf+data_offset,fname_len); + } + fname[fname_len] = '\0'; +} + /**************************************************************************** Save case statics. ****************************************************************************/ @@ -327,7 +360,7 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES| WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS)) smb_open_mode = 2; - else if(desired_access & (FILE_EXECUTE|READ_CONTROL_ACCESS)) + else if(desired_access & (FILE_EXECUTE|FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS)) smb_open_mode = 0; else { DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n", @@ -481,12 +514,22 @@ int reply_ntcreate_and_X(connection_struct *conn, if(fname_len + dir_name_len >= sizeof(pstring)) return(ERROR(ERRSRV,ERRfilespecs)); + get_filename(&fname[dir_name_len], inbuf, smb_buf(inbuf)-inbuf, + smb_buflen(inbuf),fname_len); +#if 0 StrnCpy(&fname[dir_name_len], smb_buf(inbuf),fname_len); fname[dir_name_len+fname_len] = '\0'; +#endif } else { + + get_filename(fname, inbuf, smb_buf(inbuf)-inbuf, + smb_buflen(inbuf),fname_len); + +#if 0 StrnCpy(fname,smb_buf(inbuf),fname_len); fname[fname_len] = '\0'; +#endif } /* If it's an IPC, use the pipe handler. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 62bfb612e5..35bd10fb13 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1115,7 +1115,7 @@ static int call_trans2qfsinfo(connection_struct *conn, } case SMB_QUERY_FS_ATTRIBUTE_INFO: data_len = 12 + 2*strlen(fstype); - SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */ + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH); /* FS ATTRIBUTES */ #if 0 /* Old code. JRA. */ SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ #endif /* Old code. */ @@ -1238,23 +1238,45 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *fname; char *p; int l; - SMB_OFF_T pos; + SMB_OFF_T pos = 0; BOOL bad_path = False; if (tran_call == TRANSACT2_QFILEINFO) { files_struct *fsp = file_fsp(params,0); info_level = SVAL(params,2); - CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); + if(fsp && fsp->open && fsp->is_directory) { + /* + * This is actually a QFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + fname = fsp->fsp_name; + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + } else { + /* + * Original code - this is an open file. + */ + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); - fname = fsp->fsp_name; - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadfid)); + fname = fsp->fsp_name; + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); } else { /* qpathinfo */ info_level = SVAL(params,0); @@ -1270,7 +1292,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } return(UNIXERROR(ERRDOS,ERRbadpath)); } - pos = 0; } -- cgit From 1ebeb54932de01323356e8201d465656b8723d46 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 20 Oct 1998 18:27:49 +0000 Subject: some quite important bug-fixes i missed because i transferred the wrong smb.tgz file from my portable. particularly the call to mem_data followed by a realloc of that data in cli_pipe.c's rpc_read() function. smbd responses now use p->rdata_i which is a faked-up pointer into p->rdata's response data. rdata can be very long; rdata_i is limited to point to no more than max_tsize - 0x18 in length. this will make it an almost trivial task to add the encrypted rpc headers after rdata_i, and mem_buf_copy will cope admirably with rhdr chained to rdata_i chained to auth_verifier etc etc... (This used to be commit 05a297e3a98c14360782af4ad0d851638fb5da9a) --- source3/smbd/ipc.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 2b8b8698db..3e697a59ce 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3101,6 +3101,7 @@ static void api_rpc_trans_reply(char *outbuf, /* all of data was sent: no need to wait for SMBreadX calls */ mem_free_data(p->rhdr .data); mem_free_data(p->rdata.data); + mem_free_data(p->rdata_i.data); } } @@ -3190,20 +3191,12 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, int subcommand; pipes_struct *p = NULL; prs_struct pd; - struct mem_buf data_buf; DEBUG(5,("api_fd_reply\n")); - /* fake up a data buffer from the api_fd_reply data parameters */ - mem_create(&data_buf, data, tdscnt, 0, False); - data_buf.offset.start = 0; - data_buf.offset.end = tdscnt; - - /* fake up a parsing structure */ - pd.data = &data_buf; - pd.align = 4; - pd.io = True; - pd.offset = 0; + /* make a static data parsing structure from the api_fd_reply data */ + prs_init(&pd, 0, 4, True, 0); + mem_create(pd.data, data, 0, tdscnt, 0, False); /* First find out the name of this file. */ if (suwcnt != 2) @@ -3259,6 +3252,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); } + mem_free_data(pd.data); + if (!reply) { return api_no_reply(outbuf, mdrcnt); @@ -3410,14 +3405,8 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data &rdata,&rparam,&rdata_len,&rparam_len); - mem_create(&rdata_buf , rdata , rdata_len , 0, False); - mem_create(&rparam_buf, rparam, rparam_len, 0, False); - - rdata_buf.offset.start = 0; - rdata_buf.offset.end = rdata_len; - - rparam_buf.offset.start = 0; - rparam_buf.offset.end = rparam_len; + mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False); + mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False); /* now send the reply */ send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0); -- cgit From 89087385fe1da642ff80d0558c72817c276f631b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 20 Oct 1998 22:25:52 +0000 Subject: dce/rpc. bug-fix in ipc.c (introduced today :) (This used to be commit 48ff3e2429964404c8bf33ef625791147913a3c0) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3e697a59ce..249c286ec7 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3195,7 +3195,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, DEBUG(5,("api_fd_reply\n")); /* make a static data parsing structure from the api_fd_reply data */ - prs_init(&pd, 0, 4, True, 0); + prs_init(&pd, 0, 4, 0, True); mem_create(pd.data, data, 0, tdscnt, 0, False); /* First find out the name of this file. */ -- cgit From 053d6c605caebf5ed61b86f320da6a35f0c5257f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 Oct 1998 00:31:14 +0000 Subject: at the interop Isaac (at least I _think_ it was Isaac) said that if a MS client doesn't respond to a oplock break request then we might try resending the request. This morning Sues Win95 machine had this problem (thus forcing me to do something about it!). When starting winword her box refused to answer an oplock break request. I have added code to resend the oplock break request up to 3 times at 10 second intervals before killing the socket. of course, as soon as I did this her box started to behave again so I haven't been able to tell if this fix actually works, but it can't be worse than dropping the socket immediately. (This used to be commit a1c4d8351b9171416693e6d7a9045bdce9217edb) --- source3/smbd/oplock.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index b1c6d9a981..03feae3a98 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -545,6 +545,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) connection_struct *saved_conn; int saved_vuid; pstring saved_dir; + int break_counter = OPLOCK_BREAK_RESENDS; if( DEBUGLVL( 3 ) ) { @@ -671,8 +672,20 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) while(OPEN_FSP(fsp) && fsp->granted_oplock) { - if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) + if(receive_smb(Client,inbuf, + (OPLOCK_BREAK_TIMEOUT/OPLOCK_BREAK_RESENDS) * 1000) == False) { + + /* Isaac suggestd that if a MS client doesn't respond to a + oplock break request then we might try resending + it. Certainly it's no worse than just dropping the + socket! */ + if (smb_read_error == READ_TIMEOUT && break_counter--) { + DEBUG(2, ( "oplock_break resend\n" ) ); + send_smb(Client, outbuf); + continue; + } + /* * Die if we got an error. */ -- cgit From 477350638399b8ff264100c7832c14df719055f3 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 21 Oct 1998 16:28:44 +0000 Subject: signed / unsigned issues (This used to be commit bd2fc6bb85739cb8e7ed2254e2a553486daed054) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/ipc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 45497e4cf8..91062268f9 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -613,7 +613,7 @@ BOOL check_oem_password(char *user, uchar unenc_old_pw[16]; uchar null_pw[16]; uchar null_ntpw[16]; - uchar no_pw[2]; + char no_pw[2]; BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); become_root(False); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 249c286ec7..4e4eeb40ca 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1732,7 +1732,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * */ (void)Get_Pwnam( user, True); - if (pass_oem_change(user, (uchar*) data, &data[516], NULL, NULL)) + if (pass_oem_change(user, (uchar*) data, (uchar*)(&data[516]), NULL, NULL)) { SSVAL(*rparam,0,NERR_Success); } -- cgit From 6e3af45afe237790f1d7cd94ab2b22e1ca772157 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Oct 1998 16:58:34 +0000 Subject: Fixed mainly signed/unsigned issues found by SGI cc in -fullwarn mode. smbd/chgpasswd.c: Fixed (my) stupid bug where I was returning stack based variables. Doh ! smbd/trans2.c: Allows SETFILEINFO as well as QFILEINFO on directory handles. Jeremy. (This used to be commit 0b44d27d0b5cc3948a6c2d78370ccddf1a84cd80) --- source3/smbd/chgpasswd.c | 13 +++++++------ source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 7 ++++--- source3/smbd/trans2.c | 36 +++++++++++++++++++++++++++++------- 4 files changed, 41 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 91062268f9..59022c80a8 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -455,9 +455,9 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) BOOL check_lanman_password(char *user, uchar *pass1, uchar *pass2, struct smb_passwd **psmbpw) { + static uchar null_pw[16]; uchar unenc_new_pw[16]; uchar unenc_old_pw[16]; - uchar null_pw[16]; struct smb_passwd *smbpw; *psmbpw = NULL; @@ -482,7 +482,7 @@ BOOL check_lanman_password(char *user, uchar *pass1, { uchar no_pw[14]; memset(no_pw, '\0', 14); - E_P16((uchar *)no_pw, (uchar *)null_pw); + E_P16(no_pw, null_pw); smbpw->smb_passwd = null_pw; } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("check_lanman_password: no lanman password !\n")); @@ -514,8 +514,8 @@ BOOL check_lanman_password(char *user, uchar *pass1, BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2) { + static uchar null_pw[16]; uchar unenc_new_pw[16]; - uchar null_pw[16]; BOOL ret; if (smbpw == NULL) @@ -534,7 +534,7 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2 { uchar no_pw[14]; memset(no_pw, '\0', 14); - E_P16((uchar *)no_pw, (uchar *)null_pw); + E_P16(no_pw, null_pw); smbpw->smb_passwd = null_pw; } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); @@ -605,15 +605,16 @@ BOOL check_oem_password(char *user, struct smb_passwd **psmbpw, char *new_passwd, int new_passwd_size) { + static uchar null_pw[16]; + static uchar null_ntpw[16]; struct smb_passwd *smbpw = NULL; int new_pw_len; uchar new_ntp16[16]; uchar unenc_old_ntpw[16]; uchar new_p16[16]; uchar unenc_old_pw[16]; - uchar null_pw[16]; - uchar null_ntpw[16]; char no_pw[2]; + BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); become_root(False); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 4e4eeb40ca..112a79b5ca 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1732,7 +1732,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * */ (void)Get_Pwnam( user, True); - if (pass_oem_change(user, (uchar*) data, (uchar*)(&data[516]), NULL, NULL)) + if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)) { SSVAL(*rparam,0,NERR_Success); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index eac8c9cd65..95560df66b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -458,8 +458,9 @@ check if a username/password is OK assuming the password is a 24 byte SMB hash return True if the password is correct, False otherwise ****************************************************************************/ + BOOL pass_check_smb(char *user, char *domain, - uchar *chal, char *lm_pwd, char *nt_pwd, + uchar *chal, uchar *lm_pwd, uchar *nt_pwd, struct passwd *pwd) { struct passwd *pass; @@ -513,7 +514,7 @@ BOOL pass_check_smb(char *user, char *domain, return(True); } - if (smb_password_ok(smb_pass, chal, (uchar *)lm_pwd, (uchar *)nt_pwd)) + if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) { return(True); } @@ -541,7 +542,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) } return pass_check_smb(user, global_myworkgroup, - challenge, password, password, pwd); + challenge, (uchar *)password, (uchar *)password, pwd); } return pass_check(user, password, pwlen, pwd, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 35bd10fb13..5b057410ca 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1500,15 +1500,37 @@ static int call_trans2setfilepathinfo(connection_struct *conn, files_struct *fsp = file_fsp(params,0); info_level = SVAL(params,2); - CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); + if(fsp && fsp->open && fsp->is_directory) { + /* + * This is actually a SETFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + fname = fsp->fsp_name; + unix_convert(fname,conn,0,&bad_path,&st); + if (!check_name(fname,conn) || (!VALID_STAT(st) && dos_stat(fname,&st))) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) + { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + } else { + /* + * Original code - this is an open file. + */ + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); - fname = fsp->fsp_name; - fd = fsp->fd_ptr->fd; + fname = fsp->fsp_name; + fd = fsp->fd_ptr->fd; - if(sys_fstat(fd,&st)!=0) { - DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadpath)); + if (sys_fstat(fd,&st) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } } } else { /* set path info */ -- cgit From eadc5b8c6ecdd6892647d391e1976b2c708d1ea0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 21 Oct 1998 22:36:26 +0000 Subject: domain aliases added a bit better: does local aliases if you query for sid S-1-5-20 and does (nothing at the moment) if you query for your own sid. (This used to be commit da40f26f4b2f7ce286076b4e39dffd76aa2ef8e6) --- source3/smbd/groupname.c | 6 +++--- source3/smbd/server.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 29236e2ca5..4afa9ece88 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -23,7 +23,7 @@ #include "includes.h" extern int DEBUGLEVEL; -extern DOM_SID global_machine_sid; +extern DOM_SID global_sam_sid; /************************************************************************** @@ -164,7 +164,7 @@ Error was %s.\n", unixname, strerror(errno) )); * It's not a well known name, convert the UNIX gid_t * to a rid within this domain SID. */ - tmp_sid = global_machine_sid; + tmp_sid = global_sam_sid; tmp_sid.sub_auths[tmp_sid.num_auths++] = pdb_gid_to_group_rid((gid_t)gptr->gr_gid); } @@ -233,7 +233,7 @@ void map_gid_to_sid( gid_t gid, DOM_SID *psid) * If there's no map, convert the UNIX gid_t * to a rid within this domain SID. */ - *psid = global_machine_sid; + *psid = global_sam_sid; psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid); return; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 62f2bcea9f..744320887b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -644,8 +644,8 @@ static void usage(char *pname) pstrcpy(global_myworkgroup, lp_workgroup()); - if(!pdb_generate_machine_sid()) { - DEBUG(0,("ERROR: Samba cannot get a machine SID.\n")); + if(!pdb_generate_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } -- cgit From 1ee499385c1ea0b4add82d3d4513ea997d048af1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Oct 1998 16:55:03 +0000 Subject: libsmb/smbdes.c: #ifdef'ed out code prior to removal. rpc_client/cli_pipe.c: Inlined code removed from smbdes.c rpc_server/srv_samr.c: Fixed unused variable warning. rpc_server/srv_util.c: Inlined code removed from smbdes.c Luke - the above changes are the first part of the changes you and I discussed as being neccessary at the CIFS conference. *PLEASE REVIEW THESE CHANGES* - make sure I haven't broken any of the authenticated DCE/RPC code. smbd/nttrans.c: Fixed to allow NT5.0beta2 to use Samba shares with NT SMB support. smbd/open.c: Fixed mkdir when called from nttrans calls. smbd/server.c: Set correct size for strcpy of global_myworkgroup. Jeremy. (This used to be commit d891421d16ff80998dee429227bd391455f9d1a1) --- source3/smbd/nttrans.c | 92 ++++++++++++++++++++++++++++++++------------------ source3/smbd/open.c | 11 +++++- source3/smbd/server.c | 2 +- 3 files changed, 71 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d30b59f0d3..62ca9fe1c8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -312,35 +312,47 @@ static void restore_case_semantics(uint32 file_attributes) static int map_create_disposition( uint32 create_disposition) { + int ret; + switch( create_disposition ) { case FILE_CREATE: /* create if not exist, fail if exist */ - return 0x10; + ret = 0x10; + break; case FILE_SUPERSEDE: case FILE_OVERWRITE_IF: /* create if not exist, trunc if exist */ - return 0x12; + ret = 0x12; + break; case FILE_OPEN: /* fail if not exist, open if exists */ - return 0x1; + ret = 0x1; + break; case FILE_OPEN_IF: /* create if not exist, open if exists */ - return 0x11; + ret = 0x11; + break; case FILE_OVERWRITE: /* fail if not exist, truncate if exists */ - return 0x2; + ret = 0x2; + break; default: DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n", create_disposition )); return -1; } + + DEBUG(10,("map_create_disposition: Mapped create_disposition %lx to %x\n", + (unsigned long)create_disposition, ret )); + + return ret; } /**************************************************************************** Utility function to map share modes. ****************************************************************************/ -static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 file_attributes) +static int map_share_mode( char *fname, uint32 desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode = -1; @@ -356,15 +368,28 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi break; } + /* + * NB. For DELETE_ACCESS we should really check the + * directory permissions, as that is what controls + * delete, and for WRITE_DAC_ACCESS we should really + * check the ownership, as that is what controls the + * chmod. Note that this is *NOT* a security hole (this + * note is for you, Andrew) as we are not *allowing* + * the access at this point, the actual unlink or + * chown or chmod call would do this. We are just helping + * clients out by telling them if they have a hope + * of any of this succeeding. POSIX acls may still + * deny the real call. JRA. + */ + if (smb_open_mode == -1) { - if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES| - WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS)) - smb_open_mode = 2; - else if(desired_access & (FILE_EXECUTE|FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS)) + if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| + FILE_EXECUTE|FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) smb_open_mode = 0; else { - DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n", - desired_access)); + DEBUG(0,("map_share_mode: Incorrect value %lx for desired_access to file %s\n", + (unsigned long)desired_access, fname)); return -1; } } @@ -391,6 +416,10 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi if(file_attributes & FILE_FLAG_WRITE_THROUGH) smb_open_mode |= (1<<14); + DEBUG(10,("map_share_mode: Mapped desired access %lx, share access %lx, file attributes %lx \ +to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access, + (unsigned long)file_attributes, smb_open_mode )); + return smb_open_mode; } @@ -470,17 +499,6 @@ int reply_ntcreate_and_X(connection_struct *conn, if((smb_ofun = map_create_disposition( create_disposition )) == -1) return(ERROR(ERRDOS,ERRbadaccess)); - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ - - if((smb_open_mode = map_share_mode(desired_access, - share_access, - file_attributes)) == -1) { - return(ERROR(ERRDOS,ERRbadaccess)); - } - /* * Get the file name. */ @@ -565,6 +583,17 @@ int reply_ntcreate_and_X(connection_struct *conn, return chain_reply(inbuf,outbuf,length,bufsize); } + /* + * Now contruct the smb_open_mode value from the filename, + * desired access and the share access. + */ + + if((smb_open_mode = map_share_mode(fname, desired_access, + share_access, + file_attributes)) == -1) { + return(ERROR(ERRDOS,ERRbadaccess)); + } + /* * Ordinary file or directory. */ @@ -799,15 +828,6 @@ static int call_nt_transact_create(connection_struct *conn, if((smb_ofun = map_create_disposition( create_disposition )) == -1) return(ERROR(ERRDOS,ERRbadaccess)); - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ - - if((smb_open_mode = map_share_mode( desired_access, share_access, file_attributes)) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); - - /* * Get the file name. */ @@ -888,6 +908,14 @@ static int call_nt_transact_create(connection_struct *conn, oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ + + if((smb_open_mode = map_share_mode( fname, desired_access, share_access, file_attributes)) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + /* * If it's a request for a directory open, deal with it separately. */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 311c494a97..a6e2953263 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -696,6 +696,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, /**************************************************************************** open a file with a share mode ****************************************************************************/ + void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) { @@ -714,6 +715,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int fsp->open = False; fsp->fd_ptr = 0; + DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", + fname, share_mode, ofun, mode, oplock_request )); + /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) { @@ -725,11 +729,14 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; #endif /* OS2_WPS_FIX */ + DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n")); return; } if ((ofun & 0x3) == 0 && file_existed) { + DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", + fname )); errno = EEXIST; return; } @@ -770,6 +777,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int { if (!fcbopen) { + DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", + fname, !CAN_WRITE(conn) ? "share" : "file" )); errno = EACCES; return; } @@ -978,7 +987,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Create the directory. */ - if(dos_mkdir(fname, unixmode) < 0) { + if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 744320887b..4151bbe12a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -642,7 +642,7 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); - pstrcpy(global_myworkgroup, lp_workgroup()); + fstrcpy(global_myworkgroup, lp_workgroup()); if(!pdb_generate_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); -- cgit From 1c753388d3b9a659272b6b04e0c365eb821b6c73 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 22 Oct 1998 17:26:44 +0000 Subject: extern fstring global_myworkgroup should be a pstring (This used to be commit 89f6e05ce4cc21fd2e3c0e416e49383f7b56d1ea) --- source3/smbd/ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 112a79b5ca..d359bc3500 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -37,8 +37,8 @@ extern int DEBUGLEVEL; extern int max_send; -extern fstring local_machine; -extern fstring global_myworkgroup; +extern pstring local_machine; +extern pstring global_myworkgroup; #define NERR_Success 0 #define NERR_badpass 86 -- cgit From 80f920181f8d2d58bd3b341aac57de0c71e21374 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Oct 1998 18:51:16 +0000 Subject: server/srv_samr.c smbd/ipc.c: Changed global_myworkgroup back to fstring (as it is everywhere else). smbwrapper/smbsh.c: For IRIX n32 binaries, set _RLDN32_LIST not _RLD32_LIST. Exec users preferred shell is SHELL environment variable is set. tests/fcntl_lock.c: Added sys/types.h for systems that need this. Jeremy. (This used to be commit 50413d0d819d4f13e760ca8439c5bdde0898d63e) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index d359bc3500..d9ef53e70f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -38,7 +38,7 @@ extern int DEBUGLEVEL; extern int max_send; extern pstring local_machine; -extern pstring global_myworkgroup; +extern fstring global_myworkgroup; #define NERR_Success 0 #define NERR_badpass 86 -- cgit From 5d6ed11ef3c860c95ae7b3a855b0ddb123bd9737 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 00:58:28 +0000 Subject: include/smb.h: Added #defines for lots of things - makes our code a *lot* easier to read. lib/util.c: Fixed Luke's set_first_token() function - should return void. smbd/close.c: Move delete_on_close into file_fd_struct structure. smbd/ipc.c: Changed local_machine back to fstring. smbd/nttrans.c: Use defines for mapping share modes. smbd/open.c: Move delete_on_close into file_fd_struct structure, added code for ALLOW_SHARE_DELETE. smbd/reply.c: Use defines for mapping share modes. smbd/trans2.c: Move delete_on_close into file_fd_struct structure. Jeremy. (This used to be commit 8e1ce307bd6a9056b4a95fe6f52ff42dc6e03a08) --- source3/smbd/close.c | 3 ++- source3/smbd/ipc.c | 2 +- source3/smbd/nttrans.c | 42 +++++++++++++++++------------ source3/smbd/open.c | 71 ++++++++++++++++++++++++++++++++------------------ source3/smbd/reply.c | 38 +++++++++++++++------------ source3/smbd/trans2.c | 11 +++----- 6 files changed, 100 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 981c0d77bb..2dba691a1c 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -103,6 +103,7 @@ void close_file(files_struct *fsp, BOOL normal_close) SMB_INO_T inode = fsp->fd_ptr->inode; int token; BOOL last_reference = False; + BOOL delete_on_close = fsp->fd_ptr->delete_on_close; connection_struct *conn = fsp->conn; remove_pending_lock_requests_by_fid(fsp); @@ -140,7 +141,7 @@ void close_file(files_struct *fsp, BOOL normal_close) * reference to a file. */ - if (normal_close && last_reference && fsp->delete_on_close) { + if (normal_close && last_reference && delete_on_close) { if(dos_unlink(fsp->fsp_name) != 0) DEBUG(0,("close_file: file %s. Delete on close was set and unlink failed \ with error %s\n", fsp->fsp_name, strerror(errno) )); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index d9ef53e70f..112a79b5ca 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -37,7 +37,7 @@ extern int DEBUGLEVEL; extern int max_send; -extern pstring local_machine; +extern fstring local_machine; extern fstring global_myworkgroup; #define NERR_Success 0 diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 62ca9fe1c8..8b4049cd96 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -317,24 +317,24 @@ static int map_create_disposition( uint32 create_disposition) switch( create_disposition ) { case FILE_CREATE: /* create if not exist, fail if exist */ - ret = 0x10; + ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL); break; case FILE_SUPERSEDE: case FILE_OVERWRITE_IF: /* create if not exist, trunc if exist */ - ret = 0x12; + ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); break; case FILE_OPEN: /* fail if not exist, open if exists */ - ret = 0x1; + ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN); break; case FILE_OPEN_IF: /* create if not exist, open if exists */ - ret = 0x11; + ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_OPEN); break; case FILE_OVERWRITE: /* fail if not exist, truncate if exists */ - ret = 0x2; + ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); break; default: DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n", @@ -358,13 +358,13 @@ static int map_share_mode( char *fname, uint32 desired_access, uint32 share_acce switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) { case FILE_READ_DATA: - smb_open_mode = 0; + smb_open_mode = DOS_OPEN_RDONLY; break; case FILE_WRITE_DATA: - smb_open_mode = 1; + smb_open_mode = DOS_OPEN_WRONLY; break; case FILE_READ_DATA|FILE_WRITE_DATA: - smb_open_mode = 2; + smb_open_mode = DOS_OPEN_RDWR; break; } @@ -386,7 +386,7 @@ static int map_share_mode( char *fname, uint32 desired_access, uint32 share_acce if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| FILE_EXECUTE|FILE_READ_ATTRIBUTES| FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) - smb_open_mode = 0; + smb_open_mode = DOS_OPEN_RDONLY; else { DEBUG(0,("map_share_mode: Incorrect value %lx for desired_access to file %s\n", (unsigned long)desired_access, fname)); @@ -394,27 +394,37 @@ static int map_share_mode( char *fname, uint32 desired_access, uint32 share_acce } } - /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */ + /* + * Set the special bit that means allow share delete. + * This is held outside the normal share mode bits at 1<<15. + * JRA. + */ + + if(share_access & FILE_SHARE_DELETE) + smb_open_mode |= ALLOW_SHARE_DELETE; + + /* Add in the requested share mode. */ switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) { case FILE_SHARE_READ: - smb_open_mode |= (DENY_WRITE<<4); + smb_open_mode |= SET_DENY_MODE(DENY_WRITE); break; case FILE_SHARE_WRITE: - smb_open_mode |= (DENY_READ<<4); + smb_open_mode |= SET_DENY_MODE(DENY_READ); break; case (FILE_SHARE_READ|FILE_SHARE_WRITE): - smb_open_mode |= (DENY_NONE<<4); + smb_open_mode |= SET_DENY_MODE(DENY_NONE); break; case FILE_SHARE_NONE: - smb_open_mode |= (DENY_ALL<<4); + smb_open_mode |= SET_DENY_MODE(DENY_ALL); break; } /* - * Handle a O_SYNC request. + * Handle an O_SYNC request. */ + if(file_attributes & FILE_FLAG_WRITE_THROUGH) - smb_open_mode |= (1<<14); + smb_open_mode |= FILE_SYNC_OPENMODE; DEBUG(10,("map_share_mode: Mapped desired access %lx, share access %lx, file attributes %lx \ to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access, diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a6e2953263..b6b2ef5bb8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -505,7 +505,6 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->granted_oplock = False; fsp->sent_oplock_break = False; fsp->is_directory = False; - fsp->delete_on_close = False; fsp->conn = conn; /* * Note that the file name here is the *untranslated* name @@ -657,8 +656,8 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags) { - int old_open_mode = share->share_mode &0xF; - int old_deny_mode = (share->share_mode >>4)&7; + int old_open_mode = GET_OPEN_MODE(share->share_mode); + int old_deny_mode = GET_DENY_MODE(share->share_mode); if (old_deny_mode > 4 || old_open_mode > 2) { @@ -702,7 +701,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int { int flags=0; int flags2=0; - int deny_mode = (share_mode>>4)&7; + int deny_mode = GET_DENY_MODE(share_mode); + BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); SMB_STRUCT_STAT sbuf; BOOL file_existed = file_exist(fname,&sbuf); BOOL share_locked = False; @@ -733,7 +733,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int return; } - if ((ofun & 0x3) == 0 && file_existed) + if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed) { DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", fname )); @@ -741,24 +741,25 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int return; } - if (ofun & 0x10) + if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST) flags2 |= O_CREAT; - if ((ofun & 0x3) == 2) + + if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE) flags2 |= O_TRUNC; /* note that we ignore the append flag as append does not mean the same thing under dos and unix */ - switch (share_mode&0xF) + switch (GET_OPEN_MODE(share_mode)) { - case 1: + case DOS_OPEN_WRONLY: flags = O_WRONLY; break; - case 0xF: + case DOS_OPEN_FCB: fcbopen = True; flags = O_RDWR; break; - case 2: + case DOS_OPEN_RDWR: flags = O_RDWR; break; default: @@ -767,7 +768,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int } #if defined(O_SYNC) - if (share_mode&(1<<14)) { + if (GET_FILE_SYNC_OPENMODE(share_mode)) { flags2 |= O_SYNC; } #endif /* O_SYNC */ @@ -792,7 +793,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int return; } - if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; + if (deny_mode == DENY_FCB) + deny_mode = DENY_DOS; if (lp_share_modes(SNUM(conn))) { @@ -908,17 +910,19 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou switch (flags) { case O_RDONLY: - open_mode = 0; + open_mode = DOS_OPEN_RDONLY; break; case O_RDWR: - open_mode = 2; + open_mode = DOS_OPEN_RDWR; break; case O_WRONLY: - open_mode = 1; + open_mode = DOS_OPEN_WRONLY; break; } - fsp->share_mode = (deny_mode<<4) | open_mode; + fsp->share_mode = SET_DENY_MODE(deny_mode) | + SET_OPEN_MODE(open_mode) | + SET_ALLOW_SHARE_DELETE(allow_share_delete); if (Access) (*Access) = open_mode; @@ -971,11 +975,10 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou unlock_share_entry( conn, dev, inode, token); } - - /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ + int open_directory(files_struct *fsp,connection_struct *conn, char *fname, int smb_ofun, mode_t unixmode, int *action) { @@ -1057,6 +1060,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, check if the share mode on a file allows it to be deleted or unlinked return True if sharing doesn't prevent the operation ********************************************************************/ + BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) { int i; @@ -1156,9 +1160,20 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } } - /* someone else has a share lock on it, check to see - if we can too */ - if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) + /* + * If this is a delete request and ALLOW_SHARE_DELETE is set then allow + * this to proceed. This takes precedence over share modes. + */ + + if(!rename_op && GET_ALLOW_SHARE_DELETE(share_entry->share_mode)) + continue; + + /* + * Someone else has a share lock on it, check to see + * if we can too. + */ + + if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || (share_entry->pid != pid)) goto free_and_exit; } /* end for */ @@ -1173,8 +1188,14 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou /* XXXX exactly what share mode combinations should be allowed for deleting/renaming? */ - /* If we got here then either there were no share modes or - all share modes were DENY_DOS and the pid == getpid() */ + /* + * If we got here then either there were no share modes or + * all share modes were DENY_DOS and the pid == getpid() or + * delete access was requested and all share modes had the + * ALLOW_SHARE_DELETE bit set (takes precedence over other + * share modes). + */ + ret = True; free_and_exit: @@ -1184,5 +1205,3 @@ free_and_exit: free((char *)old_shares); return(ret); } - - diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8b96ff17fd..bc19f1a931 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1239,6 +1239,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size /**************************************************************************** reply to an open ****************************************************************************/ + int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; @@ -1276,8 +1277,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,aARCH); - open_file_shared(fsp,conn,fname,share_mode,3,unixmode, - oplock_request,&rmode,NULL); + open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + unixmode, oplock_request,&rmode,NULL); if (!fsp->open) { @@ -1529,8 +1530,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file in dos compatibility share mode. */ - open_file_shared(fsp,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, - oplock_request, NULL, NULL); + open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + ofun, unixmode, oplock_request, NULL, NULL); if (!fsp->open) { @@ -1601,8 +1602,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fsp,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, - oplock_request, NULL, NULL); + open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL); if (!fsp->open) { @@ -1702,8 +1703,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++; - if (!count) exists = file_exist(directory,NULL); + if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) + count++; + if (!count) + exists = file_exist(directory,NULL); } else { void *dirptr = NULL; char *dname; @@ -2675,9 +2678,8 @@ int reply_printopen(connection_struct *conn, } /* Open for exclusive use, write only. */ - open_file_shared(fsp,conn,fname2, - (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0), - 0, NULL, NULL); + open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE), unix_mode(conn,0), 0, NULL, NULL); if (!fsp->open) { file_free(fsp); @@ -3323,6 +3325,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in /******************************************************************* copy a file as part of a reply_copy ******************************************************************/ + static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory) { @@ -3343,12 +3346,15 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!file_exist(src,&st)) return(False); + if (!file_exist(src,&st)) + return(False); fsp1 = file_new(); - if (!fsp1) return(False); - open_file_shared(fsp1,conn,src,(DENY_NONE<<4), - 1,0,0,&Access,&action); + if (!fsp1) + return(False); + + open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); if (!fsp1->open) { file_free(fsp1); @@ -3363,7 +3369,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, close_file(fsp1,False); return(False); } - open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1, + open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), ofun,st.st_mode,0,&Access,&action); if (!fsp2->open) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5b057410ca..f8d90cd871 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1658,14 +1658,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(fsp->is_directory) return(ERROR(ERRDOS,ERRnoaccess)); /* - * TODO - check here is this means set - * this flag bit on all open files that - * reference this particular dev/inode pair. - * If so we'll need to search the open - * file entries here and set this flag on - * all of them that match. JRA. + * Set the delete on close flag in the reference + * counted struct. Delete when the last reference + * goes away. */ - fsp->delete_on_close = CVAL(pdata,0); + fsp->fd_ptr->delete_on_close = CVAL(pdata,0); } else return(ERROR(ERRDOS,ERRunknownlevel)); break; -- cgit From 9bb7ac81b6e4d33e1be49447dbdbbb8d24259f53 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 03:34:50 +0000 Subject: Reasonably large change to give us *exactly* correct NT delete on close semantics. This was trickier than it looks :-). Check out the new DELETE_ON_CLOSE flag in the share modes and the new code that iterates through all open files on the same device and inode in files.c and trans2.c Also changed the code that modifies share mode entries to take generic function pointers rather than doing a specific thing so this sort of change should be easier in the future. Jeremy. (This used to be commit 5e6a7cd99d29d1cf068fc517272559c1cf47ea3a) --- source3/smbd/close.c | 1 + source3/smbd/files.c | 35 ++++++++++++++++++++++++++++++++++ source3/smbd/open.c | 23 +++++++++++++++++++++-- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 109 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 2dba691a1c..50ad01f575 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -142,6 +142,7 @@ void close_file(files_struct *fsp, BOOL normal_close) */ if (normal_close && last_reference && delete_on_close) { + DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n")); if(dos_unlink(fsp->fsp_name) != 0) DEBUG(0,("close_file: file %s. Delete on close was set and unlink failed \ with error %s\n", fsp->fsp_name, strerror(errno) )); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index c369a45bab..e58c3834a0 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -277,6 +277,41 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval return NULL; } +/**************************************************************************** + Find the first fsp given a device and inode. +****************************************************************************/ + +files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) +{ + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->open && + fsp->fd_ptr->dev == dev && + fsp->fd_ptr->inode == inode ) + return fsp; + } + + return NULL; +} + +/**************************************************************************** + Find the next fsp having the same device and inode. +****************************************************************************/ + +files_struct *file_find_di_next(files_struct *start_fsp) +{ + files_struct *fsp; + + for (fsp = start_fsp->next;fsp;fsp=fsp->next) { + if (fsp->open && + fsp->fd_ptr->dev == start_fsp->fd_ptr->dev && + fsp->fd_ptr->inode == start_fsp->fd_ptr->inode ) + return fsp; + } + + return NULL; +} /**************************************************************************** find a fsp that is open for printing diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b6b2ef5bb8..aac4b02fba 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -659,6 +659,26 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); + /* + * Setup the potential error to return. + */ + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + /* + * Don't allow any open once the delete on close flag has been + * set. + */ + + if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) + { + DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", + fname )); + unix_ERR_code = ERRnoaccess; + return False; + } + if (old_deny_mode > 4 || old_open_mode > 2) { DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", @@ -688,6 +708,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, *flags = O_WRONLY; } + return True; } @@ -865,8 +886,6 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free((char *)old_shares); unlock_share_entry(conn, dev, inode, token); errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; return; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bc19f1a931..babdd2056c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3615,7 +3615,7 @@ no oplock granted on this file.\n", fsp->fnum)); /* Remove the oplock flag from the sharemode. */ lock_share_entry(fsp->conn, dev, inode, &token); - if(remove_share_oplock(fsp, token)==False) { + if(remove_share_oplock(token, fsp)==False) { DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f8d90cd871..1c2bdb1ddf 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1655,14 +1655,64 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if (tran_call == TRANSACT2_SETFILEINFO) { files_struct *fsp = file_fsp(params,0); + BOOL delete_on_close = (CVAL(pdata,0) ? True : False); + if(fsp->is_directory) return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * We can only set the delete on close flag if + * the share mode contained ALLOW_SHARE_DELETE + */ + + if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * If the flag has changed from its previous value then + * modify the share mode entry for all files we have open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. + */ + + if(GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode) != delete_on_close) + { + int token; + files_struct *iterate_fsp; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; + int new_share_mode = (delete_on_close ? + (fsp->share_mode | DELETE_ON_CLOSE_FLAG) : + (fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + + if(lock_share_entry(fsp->conn, dev, inode, &token) == False) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + */ + + for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; + iterate_fsp = file_find_di_next(iterate_fsp)) + { + if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) + DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ +dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); + } + + unlock_share_entry(fsp->conn, dev, inode, token); + } + /* * Set the delete on close flag in the reference * counted struct. Delete when the last reference * goes away. */ - fsp->fd_ptr->delete_on_close = CVAL(pdata,0); + fsp->fd_ptr->delete_on_close = delete_on_close; } else return(ERROR(ERRDOS,ERRunknownlevel)); break; -- cgit From 5a85f2070cfd5a5c3defad59506e151dd47be58b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 03:41:11 +0000 Subject: Fixed bug in previous commit where I was overwriting share_mode from one fsp with that of another. Not good :-). Jeremy. (This used to be commit 269bca2b3bbf5cae9fdf05d0405bfd80272da5d1) --- source3/smbd/trans2.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1c2bdb1ddf..e19b3a94a8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1681,9 +1681,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, files_struct *iterate_fsp; SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; - int new_share_mode = (delete_on_close ? - (fsp->share_mode | DELETE_ON_CLOSE_FLAG) : - (fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); @@ -1699,6 +1696,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp)) { + int new_share_mode = (delete_on_close ? + (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : + (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); -- cgit From a4b02a62b790022027e94f6e2bef3a6ff2898aa6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 03:44:57 +0000 Subject: Fixed debug reporting in the changed code. Jeremy. (This used to be commit d815e2d7a65c95ae71372b4fc8fe82f0202386dc) --- source3/smbd/trans2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e19b3a94a8..e335afb001 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1700,9 +1700,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s\ +dev = %x, inode = %.0f from %x to %x\n", + iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, + (double)inode, iterate_fsp->share_mode, new_share_mode )); + if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ -dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); +dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)); } unlock_share_entry(fsp->conn, dev, inode, token); -- cgit From 22201781e48b374213a6f962fd5bd8f7db1e3985 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 03:52:28 +0000 Subject: Make the new code conditional on lp_share_modes() just like the code in open_file_shared(). Jeremy. (This used to be commit 8de02620ea8f45f6a700617911947467e7be46e1) --- source3/smbd/trans2.c | 75 ++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e335afb001..c9765c9ba8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1665,53 +1665,56 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * the share mode contained ALLOW_SHARE_DELETE */ - if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) - return(ERROR(ERRDOS,ERRnoaccess)); - - /* - * If the flag has changed from its previous value then - * modify the share mode entry for all files we have open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. - */ - - if(GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode) != delete_on_close) + if(lp_share_modes(SNUM(conn))) { - int token; - files_struct *iterate_fsp; - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; - - DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - - if(lock_share_entry(fsp->conn, dev, inode, &token) == False) + if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) return(ERROR(ERRDOS,ERRnoaccess)); /* - * Go through all files we have open on the same device and - * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + * If the flag has changed from its previous value then + * modify the share mode entry for all files we have open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. */ - for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; - iterate_fsp = file_find_di_next(iterate_fsp)) + if(GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode) != delete_on_close) { - int new_share_mode = (delete_on_close ? - (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : - (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); - - DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s\ + int token; + files_struct *iterate_fsp; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; + + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + + if(lock_share_entry(fsp->conn, dev, inode, &token) == False) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + */ + + for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; + iterate_fsp = file_find_di_next(iterate_fsp)) + { + int new_share_mode = (delete_on_close ? + (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : + (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + + DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s\ dev = %x, inode = %.0f from %x to %x\n", - iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, - (double)inode, iterate_fsp->share_mode, new_share_mode )); + iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, + (double)inode, iterate_fsp->share_mode, new_share_mode )); - if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) - DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ + if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) + DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)); - } + } - unlock_share_entry(fsp->conn, dev, inode, token); - } + unlock_share_entry(fsp->conn, dev, inode, token); + } + } /* end if lp_share_modes() */ /* * Set the delete on close flag in the reference -- cgit From 8fb0cd3c11ec58da9e292fd3acaf77e8d45e1522 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 23 Oct 1998 15:21:37 +0000 Subject: possible bug in change oem password code: replaced E_P16 and E_md4hash with a call to nt_lm_owf_gen. if this still doesn't get the NT hash generated correctly then there may instead be a bug in mod_smbpwd_entry(). (This used to be commit 1c8c644210870fef7ea3eddf411b01a98f991fcc) --- source3/smbd/chgpasswd.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 59022c80a8..4369573fe8 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -760,19 +760,12 @@ BOOL check_oem_password(char *user, BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) { int ret; - fstring upper_case_new_passwd; uchar new_nt_p16[16]; uchar new_p16[16]; - memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd)); - fstrcpy(upper_case_new_passwd, new_passwd); - strupper(upper_case_new_passwd); - - E_P16((uchar *)upper_case_new_passwd, new_p16); + nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); smbpw->smb_passwd = new_p16; - - E_md4hash((uchar *) new_passwd, new_nt_p16); smbpw->smb_nt_passwd = new_nt_p16; /* Now write it into the file. */ @@ -780,7 +773,6 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL overri ret = mod_smbpwd_entry(smbpw,override); unbecome_root(0); - memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd)); memset(new_passwd, '\0', strlen(new_passwd)); return ret; -- cgit From 6d99f5f339b572df1cd737286fbb64ad23f74fc7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 17:25:14 +0000 Subject: Handle the case where multiple smbd have the file open, some of whom don't have the ALLOW_DELETE_ON_CLOSE share flag enabled. Told you this was fiddly code :-). Jeremy. (This used to be commit 222d686a6cdbc2947e7201636ae80ef4c650a65d) --- source3/smbd/close.c | 13 +++++++-- source3/smbd/trans2.c | 80 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 50ad01f575..fcb65e1331 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -143,9 +143,18 @@ void close_file(files_struct *fsp, BOOL normal_close) if (normal_close && last_reference && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n")); - if(dos_unlink(fsp->fsp_name) != 0) - DEBUG(0,("close_file: file %s. Delete on close was set and unlink failed \ + if(dos_unlink(fsp->fsp_name) != 0) { + + /* + * This call can potentially fail as another smbd may have + * had the file open with delete on close set and deleted + * it when its last reference to this file went away. Hence + * we log this but not at debug level zero. + */ + + DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \ with error %s\n", fsp->fsp_name, strerror(errno) )); + } } if(fsp->granted_oplock == True) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c9765c9ba8..44e9d499e2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1653,7 +1653,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { - if (tran_call == TRANSACT2_SETFILEINFO) { + if (tran_call == TRANSACT2_SETFILEINFO) + { files_struct *fsp = file_fsp(params,0); BOOL delete_on_close = (CVAL(pdata,0) ? True : False); @@ -1671,28 +1672,75 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(ERROR(ERRDOS,ERRnoaccess)); /* - * If the flag has changed from its previous value then + * If the flag has been set then * modify the share mode entry for all files we have open * on this device and inode to tell other smbds we have * changed the delete on close flag. */ - if(GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode) != delete_on_close) + if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) { int token; + int i; files_struct *iterate_fsp; SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; - - DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + int num_share_modes; + share_mode_entry *current_shares = NULL; if(lock_share_entry(fsp->conn, dev, inode, &token) == False) return(ERROR(ERRDOS,ERRnoaccess)); + /* + * Before we allow this we need to ensure that all current opens + * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they + * do not then we deny this (as we are essentially deleting the + * file at this point. + */ + + num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares); + for(i = 0; i < num_share_modes; i++) + { + if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) + { + DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \ +file %s as a share exists that was not opened with FILE_DELETE access.\n", + fsp->fnum, fsp->fsp_name )); + /* + * Release the lock. + */ + + unlock_share_entry(fsp->conn, dev, inode, token); + + /* + * current_shares was malloced by get_share_modes - free it here. + */ + + free((char *)current_shares); + + /* + * Even though share violation would be more appropriate here, + * return ERRnoaccess as that's what NT does. + */ + + return(ERROR(ERRDOS,ERRnoaccess)); + } + } + + /* + * current_shares was malloced by get_share_modes - free it here. + */ + + free((char *)current_shares); + + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + /* * Go through all files we have open on the same device and * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + * Other smbd's that have this file open will have to fend for themselves. We + * take care of this (rare) case in close_file(). See the comment there. */ for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; @@ -1704,24 +1752,26 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s\ dev = %x, inode = %.0f from %x to %x\n", - iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, - (double)inode, iterate_fsp->share_mode, new_share_mode )); + iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, + (double)inode, iterate_fsp->share_mode, new_share_mode )); if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)); } + /* + * Set the delete on close flag in the reference + * counted struct. Delete when the last reference + * goes away. + */ + fsp->fd_ptr->delete_on_close = delete_on_close; + unlock_share_entry(fsp->conn, dev, inode, token); - } + + } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */ } /* end if lp_share_modes() */ - /* - * Set the delete on close flag in the reference - * counted struct. Delete when the last reference - * goes away. - */ - fsp->fd_ptr->delete_on_close = delete_on_close; } else return(ERROR(ERRDOS,ERRunknownlevel)); break; -- cgit From fb556e14f3b47d5a1f465589084e8b30d84af8ca Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Oct 1998 08:08:05 +0000 Subject: volker was concerned about unique inode numbers and smbsh. This set of changes uses the unique index number from a SMB_QUERY_FILE_ALL_INFO to try to provide inode numbers. If it is 0 then use the hash of the filename as before. (This used to be commit 2565ccf9de9d5e80fdb5bcadbc7130faba386d95) --- source3/smbd/trans2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 44e9d499e2..f0bd458798 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1432,6 +1432,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; pdata += 24; + SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); pdata += 8; /* index number */ pdata += 4; /* EA info */ if (mode & aRONLY) -- cgit From 8546b7ec9486881261d3a97c893d4cb09b24461e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Oct 1998 18:44:01 +0000 Subject: Fixed a couple of issues with the SMB_QUERY_FILE_ALL_INFO query. Ensured offset was being reported correctly for 64 bit file access, ensured delete on close bit was being reported correctly. Jeremy. (This used to be commit 4332bc06c6604a3e14007eda4f40e6183a1f8526) --- source3/smbd/trans2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f0bd458798..fdd3652cf7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1240,6 +1240,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, int l; SMB_OFF_T pos = 0; BOOL bad_path = False; + BOOL delete_pending = False; if (tran_call == TRANSACT2_QFILEINFO) { files_struct *fsp = file_fsp(params,0); @@ -1276,6 +1277,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); + + delete_pending = fsp->fd_ptr->delete_on_close; } } else { /* qpathinfo */ @@ -1429,7 +1432,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SOFF_T(pdata,0,size); SOFF_T(pdata,8,size); SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = 0; + CVAL(pdata,20) = delete_pending; CVAL(pdata,21) = (mode&aDIR)?1:0; pdata += 24; SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); @@ -1440,7 +1443,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, else SIVAL(pdata,0,0xd01BF); pdata += 4; - SIVAL(pdata,0,pos); /* current offset */ + SOFF_T(pdata,0,pos); /* current offset */ pdata += 8; SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ pdata += 4; -- cgit From f5400e6f02953a97ac6c852f98491c8988466bfd Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 27 Oct 1998 15:08:02 +0000 Subject: debug string with no %s parameter. oops (This used to be commit 22721b027139ffb7ff2625741b68701ba15fbb98) --- source3/smbd/close.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index fcb65e1331..94923b6db2 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -142,7 +142,8 @@ void close_file(files_struct *fsp, BOOL normal_close) */ if (normal_close && last_reference && delete_on_close) { - DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n")); + DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", + fsp->fsp_name)); if(dos_unlink(fsp->fsp_name) != 0) { /* -- cgit From 3fcd6d69cb7df37b8169df66d23cba1ea7ce067a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Oct 1998 17:15:28 +0000 Subject: Fix from thwartedefforts@wonky.org (slightly modified) to fix username overwriting problem in security=share. Jeremy. (This used to be commit 17621964344336c6303386c3c9e8a3e23b9e46e1) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index babdd2056c..1d8ccd61eb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -597,7 +597,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * working. */ - if((lp_security() != SEC_SHARE) || *user) + if((lp_security() != SEC_SHARE) || (*user && !guest)) pstrcpy(sesssetup_user,user); reload_services(True); -- cgit From 94f7ce7624c22ce735c7b0f9a7079f41ac248af5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Oct 1998 17:51:49 +0000 Subject: Quick fixes to fix the broken tree. Needed for my morning compiles. Chris - feel free to fix these things differently if these fixes don't work for you. Jeremy. (This used to be commit 1f225abfbe6b021b589711c2e4c599a63050c5b2) --- source3/smbd/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4151bbe12a..68f722ff51 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -486,6 +486,7 @@ static void usage(char *pname) printf("\t-P passive only\n"); printf("\t-a append to log file (default)\n"); printf("\t-o overwrite log file, don't append\n"); + printf("\t-i scope NetBIOS scope to use (default none)\n"); printf("\n"); } -- cgit From ce2a92d86434c1b04d9b09b710ad362407d9bdc6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Oct 1998 20:17:02 +0000 Subject: Fixed bug (that I introduced when doing the "delete on close" work that caused NetBench to fail as the wrong error code was being returned from a getatr call. Change was not to set the unix_ERR_class global when you are not returning an error. This is a big of Samba internal folklore that is *important*. Jeremy. (This used to be commit a1923d465be4c63a40d55abb800cc9b16a4b87d0) --- source3/smbd/open.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aac4b02fba..670161f2d0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -659,13 +659,6 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); - /* - * Setup the potential error to return. - */ - - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - /* * Don't allow any open once the delete on close flag has been * set. @@ -675,6 +668,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", fname )); + unix_ERR_class = ERRDOS; unix_ERR_code = ERRnoaccess; return False; } @@ -683,6 +677,10 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", deny_mode,old_deny_mode,old_open_mode,fname)); + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return False; } @@ -698,6 +696,10 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", deny_mode,old_deny_mode,old_open_mode, share->pid,fname, fcbopen, *flags, access_allowed)); + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return False; } -- cgit From 502e2ec3cf3dc1e0d64771f52b7bc7ff54050526 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 2 Nov 1998 16:20:25 +0000 Subject: removed comment line at end of file (This used to be commit 5e2fc8b7ccf4a9c8b0a2acf4bd752531ac6fa775) --- source3/smbd/mangle.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index f0d5a9d85c..b829746a32 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -983,4 +983,3 @@ BOOL name_map_mangle(char *OutName, BOOL need83, int snum) return(True); } /* name_map_mangle */ -/* ========================================================================== */ -- cgit From 01e04614c7c466fdbdc398c782acaa931965f925 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Nov 1998 02:25:28 +0000 Subject: Makefile.in configure configure.in include/proto.h smbd/noquotas.c smbd/quotas.c: Added quotas patch for autoconf from Dejan Ilic . printing/printing.c: Filenames with spaces patch from Allan Bjorklund utils/nmblookup.c: Fix usage() function. smbd/reply.c: Split out the security=server and security=domain checks into check_server_security() and check_domain_security() to aid the writing of the 'hack' appliance mode invented by John Schimmel. Jeremy. (This used to be commit f09ab9b52251087a58af92ec753537ca34a970fc) --- source3/smbd/noquotas.c | 31 ++++++++++++ source3/smbd/quotas.c | 8 --- source3/smbd/reply.c | 130 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 117 insertions(+), 52 deletions(-) create mode 100644 source3/smbd/noquotas.c (limited to 'source3/smbd') diff --git a/source3/smbd/noquotas.c b/source3/smbd/noquotas.c new file mode 100644 index 0000000000..c62fb368c7 --- /dev/null +++ b/source3/smbd/noquotas.c @@ -0,0 +1,31 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + No support for quotas :-). + Copyright (C) Andrew Tridgell 1992-1998 + + 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" + +/* + * Needed for auto generation of proto.h. + */ + +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + return False; +} diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 716c2357c6..d610bbe15a 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -1,4 +1,3 @@ -#ifdef QUOTAS /* Unix SMB/Netbios implementation. Version 1.9. @@ -658,10 +657,3 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #endif - -#else -/* this keeps fussy compilers happy */ - void quotas_dummy(void); - void quotas_dummy(void) {} -#endif /* QUOTAS */ - diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1d8ccd61eb..67c2abb9b5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -447,10 +447,42 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } +/**************************************************************************** + Check for a valid username and password in security=server mode. +****************************************************************************/ + +static BOOL check_server_security(char *orig_user, char *domain, + char *smb_apasswd, int smb_apasslen, + char *smb_ntpasswd, int smb_ntpasslen) +{ + if(lp_security() != SEC_SERVER) + return False; + + return server_validate(orig_user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen); +} + +/**************************************************************************** + Check for a valid username and password in security=domain mode. +****************************************************************************/ + +static BOOL check_domain_security(char *orig_user, char *domain, + char *smb_apasswd, int smb_apasslen, + char *smb_ntpasswd, int smb_ntpasslen) +{ + if(lp_security() != SEC_DOMAIN) + return False; + + return domain_client_validate(orig_user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen); +} /**************************************************************************** reply to a session setup command ****************************************************************************/ + int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 sess_vuid; @@ -582,12 +614,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* If no username is sent use the guest account */ if (!*user) - { - pstrcpy(user,lp_guestaccount(-1)); - /* If no user and no password then set guest flag. */ - if( *smb_apasswd == 0) - guest = True; - } + { + pstrcpy(user,lp_guestaccount(-1)); + /* If no user and no password then set guest flag. */ + if( *smb_apasswd == 0) + guest = True; + } strlower(user); @@ -631,48 +663,58 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) guest = True; - if (!guest && !(lp_security() == SEC_SERVER && - /* Check with orig_user for security=server and - security=domain. */ - server_validate(orig_user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen)) && - !(lp_security() == SEC_DOMAIN && - domain_client_validate(orig_user, domain, + /* + * Check with orig_user for security=server and + * security=domain. + */ + + if (!guest && + !check_server_security(orig_user, domain, smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen)) && + smb_ntpasswd, smb_ntpasslen) && + !check_domain_security(orig_user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen) && !check_hosts_equiv(user) ) + { + + /* + * If we get here then the user wasn't guest and the remote + * authentication methods failed. Check the authentication + * methods on this local server. + * + * If an NT password was supplied try and validate with that + * first. This is superior as the passwords are mixed case + * 128 length unicode. + */ + + if(smb_ntpasslen) { + if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) + DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); + else + valid_nt_password = True; + } - /* now check if it's a valid username/password */ - /* If an NT password was supplied try and validate with that - first. This is superior as the passwords are mixed case - 128 length unicode */ - if(smb_ntpasslen) - { - if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) - DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); - else - valid_nt_password = True; - } - if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) - { - if (lp_security() >= SEC_USER) { + if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) + { + if (lp_security() >= SEC_USER) + { #if (GUEST_SESSSETUP == 0) - return(ERROR(ERRSRV,ERRbadpw)); + return(ERROR(ERRSRV,ERRbadpw)); #endif #if (GUEST_SESSSETUP == 1) - if (Get_Pwnam(user,True)) - return(ERROR(ERRSRV,ERRbadpw)); + if (Get_Pwnam(user,True)) + return(ERROR(ERRSRV,ERRbadpw)); #endif - } - if (*smb_apasswd || !Get_Pwnam(user,True)) - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } + } + if (*smb_apasswd || !Get_Pwnam(user,True)) + pstrcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; } + } if (!Get_Pwnam(user,True)) { DEBUG(3,("No such user %s - using guest account\n",user)); @@ -682,12 +724,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!strequal(user,lp_guestaccount(-1)) && lp_servicenumber(user) < 0) - { - int homes = lp_servicenumber(HOMES_NAME); - char *home = get_home_dir(user); - if (homes >= 0 && home) - lp_add_home(user,homes,home); - } + { + int homes = lp_servicenumber(HOMES_NAME); + char *home = get_home_dir(user); + if (homes >= 0 && home) + lp_add_home(user,homes,home); + } /* it's ok - setup a reply */ -- cgit From 4bd1feb68c4f5134293d87433da932c20cded915 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Nov 1998 18:40:51 +0000 Subject: lib/charcnv.c: Improved debug comment. libsmb/namequery.c: Fix to remove 2 second wait is we are doing a unicast and got a reply. smbd/dfree.c: smbd/noquotas.c: smbd/quotas.c: Fixes from Dejan Ilic for the quota code. utils/smbpasswd.c: Fixes to allow smbpasswd to be called from swat. Jeremy. (This used to be commit b5981c0149ad8c6f13ea87db450080616538b5d5) --- source3/smbd/dfree.c | 11 +++++++++++ source3/smbd/noquotas.c | 10 +++++++++- source3/smbd/quotas.c | 43 +++++++++++++++++++++++-------------------- 3 files changed, 43 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index c96a599e77..020386645c 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -188,13 +188,24 @@ static int fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) static SMB_BIG_UINT disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { int dfree_retval; + SMB_BIG_UINT dfree_q = 0; + SMB_BIG_UINT bsize_q = 0; + SMB_BIG_UINT dsize_q = 0; (*dfree) = (*dsize) = 0; (*bsize) = 512; fsusage(path, dfree, dsize); + if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { + (*bsize) = bsize_q; + (*dfree) = MIN(*dfree,dfree_q); + (*dsize) = MIN(*dsize,dsize_q); + } + + /* FIXME : Any reason for this assumption ? */ if (*bsize < 256) { + DEBUG(5,("disk_free:Warning: bsize == %d < 256 . Changing to assumed correct bsize = 512\n",*bsize)); *bsize = 512; } diff --git a/source3/smbd/noquotas.c b/source3/smbd/noquotas.c index c62fb368c7..5c55bb47c8 100644 --- a/source3/smbd/noquotas.c +++ b/source3/smbd/noquotas.c @@ -25,7 +25,15 @@ * Needed for auto generation of proto.h. */ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +BOOL disk_quotas(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { + (*bsize) = 512; /* This value should be ignored */ + + /* And just to be sure we set some values that hopefully */ + /* will be larger that any possible real-world value */ + (*dfree) = (SMB_BIG_UINT)-1; + (*dsize) = (SMB_BIG_UINT)-1; + + /* As we have select not to use quotas, allways fail */ return False; } diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index d610bbe15a..d5ecf73451 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -45,7 +45,7 @@ _syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr try to get the disk space from disk quotas (LINUX version) ****************************************************************************/ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t euser_id; int r; @@ -130,7 +130,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) /**************************************************************************** try to get the disk space from disk quotas (CRAY VERSION) ****************************************************************************/ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) + +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { struct mntent *mnt; FILE *fd; @@ -227,6 +228,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #elif defined(SUNOS5) || defined(SUNOS4) #include +#include #if defined(SUNOS5) #include #include @@ -236,10 +238,11 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #endif /**************************************************************************** -try to get the disk space from disk quotas (solaris 2 version) -****************************************************************************/ +try to get the disk space from disk quotas (SunOS & Solaris2 version) /* Quota code by Peter Urbanec (amiga@cse.unsw.edu.au) */ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +****************************************************************************/ + +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t user_id, euser_id; int ret; @@ -249,7 +252,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) int file; struct mnttab mnt; static pstring name; -#else +#else /* SunOS4 */ struct mntent *mnt; static pstring name; #endif @@ -285,7 +288,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) pstrcpy(name,mnt.mnt_mountp) ; pstrcat(name,"/quotas") ; fclose(fd) ; -#else +#else /* SunOS4 */ if ((fd = setmntent(MOUNTED, "r")) == NULL) return(False) ; @@ -336,7 +339,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) seteuid(euser_id); if (ret < 0) { - DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); + DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); return(False); } @@ -349,17 +352,18 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) if (D.dqb_bsoftlimit==0) return(False); - *bsize = 512; + *bsize = DEV_BSIZE; *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; *dsize = D.dqb_bsoftlimit; + if(*dfree < 0) { *dfree = 0; *dsize = D.dqb_curblocks; } -DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n", - path,*bsize,*dfree,*dsize)); + DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", + path,(double)*bsize,(double)*dfree,(double)*dsize)); return(True); } @@ -371,7 +375,8 @@ DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n" /**************************************************************************** try to get the disk space from disk quotas - OFS1 version ****************************************************************************/ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) + +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t user_id, euser_id; int r, save_errno; @@ -426,7 +431,7 @@ try to get the disk space from disk quotas (IRIX 6.2 version) #include #include -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t euser_id; int r; @@ -518,11 +523,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit) ) { - /* - * Fixme!: these are __uint64_t, this may truncate values - */ *dfree = 0; - *dsize = (int) F.d_bcount; + *dsize = F.d_bcount; } else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) { @@ -530,8 +532,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } else { - *dfree = (int)(F.d_blk_softlimit - F.d_bcount); - *dsize = (int)F.d_blk_softlimit; + *dfree = (F.d_blk_softlimit - F.d_bcount); + *dsize = F.d_blk_softlimit; } } @@ -565,7 +567,8 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) /**************************************************************************** try to get the disk space from disk quotas - default version ****************************************************************************/ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) + +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t euser_id; int r; -- cgit From 548b417d404a2653ebb5918b0c169ccdfafe856f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 7 Nov 1998 05:32:37 +0000 Subject: codepages/codepage_def.936: Updated comment. param/loadparm.c: Removed "networkstation user login", "domain controller", and "domain sid" parameters. passdb/passdb.c: Removed "networkstation user login" code and changed bug test code to only check once for a bad password server. This will stop the complaints of many "bad login" audit records in NT PDC logs. utils/smbpasswd.c: Removed check for "domain controller". Jeremy. (This used to be commit d6e6e936b5dd90dd8fc38d9404efbe5c546c15e5) --- source3/smbd/password.c | 162 ++++++++++++++++++++++-------------------------- 1 file changed, 73 insertions(+), 89 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 95560df66b..d49ea7c562 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1036,114 +1036,98 @@ BOOL server_validate(char *user, char *domain, char *pass, int passlen, char *ntpass, int ntpasslen) { - struct cli_state *cli; - extern fstring local_machine; - static unsigned char badpass[24]; - cli = server_client(); + struct cli_state *cli; + extern fstring local_machine; + static unsigned char badpass[24]; + static BOOL tested_password_server = False; + static BOOL bad_password_server = False; - if (!cli->initialised) { - DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return(False); - } + cli = server_client(); - if(badpass[0] == 0) { - memset(badpass, 0x1f, sizeof(badpass)); - } + if (!cli->initialised) { + DEBUG(1,("password server %s is not connected\n", cli->desthost)); + return(False); + } - if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) { - /* Very unlikely, our random bad password is the same as the users - password. */ - memset(badpass, badpass[0]+1, sizeof(badpass)); - } + if(badpass[0] == 0) + memset(badpass, 0x1f, sizeof(badpass)); - /* - * Attempt a session setup with a totally incorrect password. - * If this succeeds with the guest bit *NOT* set then the password - * server is broken and is not correctly setting the guest bit. We - * need to detect this as some versions of NT4.x are broken. JRA. - */ + if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) { + /* + * Very unlikely, our random bad password is the same as the users + * password. */ + memset(badpass, badpass[0]+1, sizeof(badpass)); + } - if (cli_session_setup(cli, user, (char *)badpass, sizeof(badpass), - (char *)badpass, sizeof(badpass), domain)) { - if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { - DEBUG(0,("server_validate: password server %s allows users as non-guest \ -with a bad password.\n", cli->desthost)); - DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ -use this machine as the password server.\n")); - cli_ulogoff(cli); - return False; - } - cli_ulogoff(cli); - } + /* + * Attempt a session setup with a totally incorrect password. + * If this succeeds with the guest bit *NOT* set then the password + * server is broken and is not correctly setting the guest bit. We + * need to detect this as some versions of NT4.x are broken. JRA. + */ - /* - * Now we know the password server will correctly set the guest bit, or is - * not guest enabled, we can try with the real password. - */ + if(!tested_password_server) { + if (cli_session_setup(cli, user, (char *)badpass, sizeof(badpass), + (char *)badpass, sizeof(badpass), domain)) { - if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - return False; - } + /* + * We connected to the password server so we + * can say we've tested it. + */ + tested_password_server = True; - /* if logged in as guest then reject */ - if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); - cli_ulogoff(cli); - return(False); - } + if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { + DEBUG(0,("server_validate: password server %s allows users as non-guest \ +with a bad password.\n", cli->desthost)); + DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ +use this machine as the password server.\n")); + cli_ulogoff(cli); /* - * This patch from Rob Nielsen makes doing - * the NetWksaUserLogon a dynamic, rather than compile-time - * parameter, defaulting to on. This is somewhat dangerous - * as it allows people to turn off this neccessary check, - * but so many people have had problems with this that I - * think it is a neccessary change. JRA. + * Password server has the bug. */ + bad_password_server = True; + return False; + } + cli_ulogoff(cli); + } + } else { - if (lp_net_wksta_user_logon()) { - DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", cli->desthost)); + /* + * We have already tested the password server. + * Fail immediately if it has the bug. + */ - if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { - DEBUG(0,("password server %s refused IPC$ connect\n", cli->desthost)); - cli_ulogoff(cli); - return False; - } + if(bad_password_server) { + DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \ +with a bad password.\n", cli->desthost)); + DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \ +use this machine as the password server.\n")); + return False; + } + } - if (!cli_NetWkstaUserLogon(cli,user,local_machine)) { - DEBUG(0,("password server %s failed NetWkstaUserLogon\n", cli->desthost)); - cli_tdis(cli); - cli_ulogoff(cli); - return False; - } + /* + * Now we know the password server will correctly set the guest bit, or is + * not guest enabled, we can try with the real password. + */ - if (cli->privilages == 0) { - DEBUG(0,("password server %s gave guest privilages\n", cli->desthost)); - cli_tdis(cli); - cli_ulogoff(cli); - return False; - } + if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + return False; + } - if (!strequal(cli->eff_name, user)) { - DEBUG(0,("password server %s gave different username %s\n", - cli->desthost, - cli->eff_name)); - cli_tdis(cli); - cli_ulogoff(cli); - return False; - } - cli_tdis(cli); - } - else { - DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", cli->desthost)); - } + /* if logged in as guest then reject */ + if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); + cli_ulogoff(cli); + return(False); + } - DEBUG(3,("password server %s accepted the password\n", cli->desthost)); - cli_ulogoff(cli); + cli_ulogoff(cli); - return(True); + return(True); } /*********************************************************************** -- cgit From 8c62b28e0ef1e012ebb0713701916d82ffc7661e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 9 Nov 1998 03:45:49 +0000 Subject: converted smbclient to use clientgen.c rather than clientutil.c I did this when I saw yet another bug report complaining about smbclient intermittently missing files. Rather than applying more patches to smbclient it was better to move to the more robust clientgen.c code. The conversion wasn't perfect, I probably lost some features of smbclient while doing it, but at least smbclient should be consistent now. It if fails it should _always_ fail rather than giving people the false impression of a reliable utility. the tar stuff seems to work, but hasn't had much testing as I never use it myself. I'm sure someone will find bugs in my conversion of smbtar.c. It was quite tricky as it did a lot of its own SMB calls. It now uses clientgen.c exclusively. smbclient is still quite messy, but at least it doesn't build its own SMB packets. I haven't touched smbmount as I never use it. Mike, do you want to convert smbmount to use clientgen.c? (This used to be commit e14ca7765ace1b721dad8eca4a527a4e4a8f1ab8) --- source3/smbd/dfree.c | 2 +- source3/smbd/password.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 020386645c..8cba8d0644 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -205,7 +205,7 @@ static SMB_BIG_UINT disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree /* FIXME : Any reason for this assumption ? */ if (*bsize < 256) { - DEBUG(5,("disk_free:Warning: bsize == %d < 256 . Changing to assumed correct bsize = 512\n",*bsize)); + DEBUG(5,("disk_free:Warning: bsize == %d < 256 . Changing to assumed correct bsize = 512\n",(int)*bsize)); *bsize = 512; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index d49ea7c562..fb5acf156f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1037,7 +1037,6 @@ BOOL server_validate(char *user, char *domain, char *ntpass, int ntpasslen) { struct cli_state *cli; - extern fstring local_machine; static unsigned char badpass[24]; static BOOL tested_password_server = False; static BOOL bad_password_server = False; -- cgit From e4f974c611c179a5e7827ec8325e01811db6540b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Nov 1998 20:33:37 +0000 Subject: Makefile.in: Removed rpc_server/srv_ldap_helpers.c per J.F.'s instructions. client/client.c: client/clitar.c: include/client.h: smbwrapper/smbw_dir.c: smbwrapper/smbw_stat.c: smbwrapper/smbw.c: lib/util.c: Converted all use of 'mode' to uint16. smbd/quotas.c: Fixed stupid comment bug I put in there :-(. printing/printing.c: Fix from J.F. to new code. Jeremy. (This used to be commit bacd3e9d2036a804e73644a28fc498f229c8446c) --- source3/smbd/quotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index d5ecf73451..6df668e279 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -239,7 +239,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U /**************************************************************************** try to get the disk space from disk quotas (SunOS & Solaris2 version) -/* Quota code by Peter Urbanec (amiga@cse.unsw.edu.au) */ +Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). ****************************************************************************/ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -- cgit From 375e53826c59c33d52009307f757b71a1fe3d589 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 10 Nov 1998 20:51:25 +0000 Subject: include/local.h: include/smb.h: param/loadparm.c: Made GUEST_SESSSETUP run time selectable. Horror of horrors :-). printing/printing.c: Added J.F.'s latest fix. rpc_parse/parse_misc.c: parse_reg.c: rpcclient/cmd_reg.c: rpcclient/display.c: SGI compiler signed/unsigned issues. smbd/reply.c: Made GUEST_SESSSETUP run time selectable. Horror of horrors :-). utils/testparm.c: Added extra test. Jeremy. (This used to be commit 9668a5ef50be2e6b575f9989e87ee2ff8da5ac1d) --- source3/smbd/reply.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 67c2abb9b5..d3131b5fea 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -701,14 +701,21 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int { if (lp_security() >= SEC_USER) { -#if (GUEST_SESSSETUP == 0) - return(ERROR(ERRSRV,ERRbadpw)); -#endif -#if (GUEST_SESSSETUP == 1) - if (Get_Pwnam(user,True)) + if (lp_map_to_guest() == NEVER_MAP_TO_GUEST) return(ERROR(ERRSRV,ERRbadpw)); -#endif + + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) + { + if (Get_Pwnam(user,True)) + return(ERROR(ERRSRV,ERRbadpw)); + } + + /* + * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD + * Then always map to guest account - as done below. + */ } + if (*smb_apasswd || !Get_Pwnam(user,True)) pstrcpy(user,lp_guestaccount(-1)); DEBUG(3,("Registered username %s for guest access\n",user)); -- cgit From 16a243ec5efe0fed8a6934442e87f57c635e4703 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Nov 1998 17:42:36 +0000 Subject: Fixed two debug prints. Jeremy. (This used to be commit 74530677d5301abd2da5bcdcb1fde6e6f903ad70) --- source3/smbd/ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 112a79b5ca..eed5a71401 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1704,13 +1704,13 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * * Check the parameter definition is correct. */ if(!strequal(param + 2, "zsT")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2)); + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); return False; } p = skip_string(p, 1); if(!strequal(p, "B516B16")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p)); + DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); return False; } p = skip_string(p,1); -- cgit From aba85cb152e0baf686e879643926de0fa2fce80f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Nov 1998 03:50:29 +0000 Subject: Fix fd leak in error condition in grantpt code case. Jeremy. (This used to be commit 22df2dae30b815f1c86bd21ac0ccf02da5b85eba) --- source3/smbd/chgpasswd.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 4369573fe8..52ca364070 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -71,6 +71,8 @@ static int findpty(char **slave) *slave = ptsname(master); if (*slave == NULL) { DEBUG(0,("findpty: Unable to create master/slave pty pair.\n")); + /* Stop fd leak on error. */ + close(master); return -1; } else { DEBUG(10, ("findpty: Allocated slave pty %s\n", *slave)); @@ -81,7 +83,8 @@ static int findpty(char **slave) fstrcpy( line, "/dev/ptyXX" ); dirp = OpenDir(NULL, "/dev", False); - if (!dirp) return(-1); + if (!dirp) + return(-1); while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); @@ -89,10 +92,10 @@ static int findpty(char **slave) line[9] = dpname[4]; if ((master = open(line, O_RDWR)) >= 0) { DEBUG(3,("pty: opened %s\n", line ) ); - line[5] = 't'; - *slave = line; - CloseDir(dirp); - return (master); + line[5] = 't'; + *slave = line; + CloseDir(dirp); + return (master); } } } -- cgit From 29e36b713468d7e7de301c483fc340ef42b4a9fb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Nov 1998 07:06:48 +0000 Subject: extracted the password change code from smbpasswd and used it in swat instead of opening pipes and other horrible stuff. (This used to be commit 49bf19710345a59a2d17cd449be1a132885ed821) --- source3/smbd/uid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 7cd8c8673c..7c951b461a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -421,3 +421,5 @@ void unbecome_root(BOOL restore_dir) become_root_depth = 0; } + + -- cgit From 2164685b9f959814af2067aa0dcac2d1b2ac0bc5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Nov 1998 02:07:07 +0000 Subject: include/smb.h: Re-added zero pointer protection to ZERO_STRUCTP. lib/util_sock.c: Added strerror() calls to getpeername failures (which seem to be giving IRIX trouble at the moment). rpc_parse/parse_sec.c: Changed use of ZERO_STRUCTPN to ZERO_STRUCTP which again does zero pointer protection. smbd/quotas.c: Fixed typo. Jeremy. (This used to be commit b62f008974c96e0302d6c146cf49bc2045bef005) --- source3/smbd/quotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 6df668e279..5cd5a895c6 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -373,7 +373,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #include /**************************************************************************** -try to get the disk space from disk quotas - OFS1 version +try to get the disk space from disk quotas - OSF1 version ****************************************************************************/ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -- cgit From 8fc1504ff8204dd1ca735f31c769f6dadf0f88cb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Nov 1998 21:41:01 +0000 Subject: Makefile.in configure configure.in include/config.h.in: Changes for DGUX and UNIXWARE. groupdb/aliasdb.c groupdb/aliasfile.c groupdb/groupfile.c: Don't use snprinf, use slprintf. include/includes.h: Fix YP problem. include/smb.h: Fix ZERO_STRUCTP. lib/util_sock.c: Added strerror() in debugs. passdb/ldap.c: Don't use snprinf, use slprintf. rpc_client/cli_lsarpc.c rpc_client/cli_pipe.c rpc_parse/parse_sec.c rpc_server/srv_pipe.c: Don't use snprinf, use slprintf. script/installman.sh: DGUX changes. smbd/open.c smbd/oplock.c: Fixed gcc warnings. web/swat.c: Changes USER to SWAT_USER. (This used to be commit 4c2b5a00983501e5d4aad1456ba8b5ab0dfd9b4c) --- source3/smbd/open.c | 2 +- source3/smbd/oplock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 670161f2d0..f9ddc969a8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -739,7 +739,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int fsp->fd_ptr = 0; DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", - fname, share_mode, ofun, mode, oplock_request )); + fname, share_mode, ofun, (int)mode, oplock_request )); /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 03feae3a98..89a2adb900 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -220,7 +220,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); /* Validate message from address (must be localhost). */ if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { DEBUG(0,("receive_local_message: invalid 'from' address \ -(was %x should be 127.0.0.1\n", from.sin_addr.s_addr)); +(was %lx should be 127.0.0.1\n", (long)from.sin_addr.s_addr)); return False; } -- cgit From 00ae36ffd8079dc830fb4c7016a1f6ddd96d9b5c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 15 Nov 1998 23:07:54 +0000 Subject: change ROUNDUP to SMB_ROUNDUP to prevent conflicts with system macros (This used to be commit d9d44d98ec719b7fc6d5b0fc35bf8727f4cd0372) --- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d3131b5fea..d466884ab6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4129,7 +4129,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si else { SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); - SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024)); + SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024)); } SSVAL(outbuf,smb_vwv10, mode); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fdd3652cf7..f1d415e290 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -418,7 +418,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,l1_fdateLastAccess,adate); put_dos_date2(p,l1_fdateLastWrite,mdate); SIVAL(p,l1_cbFile,(uint32)size); - SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024)); + SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024)); SSVAL(p,l1_attrFile,mode); SCVAL(p,l1_cchName,strlen(fname)); pstrcpy(p + l1_achName, fname); @@ -436,7 +436,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,l2_fdateLastAccess,adate); put_dos_date2(p,l2_fdateLastWrite,mdate); SIVAL(p,l2_cbFile,(uint32)size); - SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024)); + SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024)); SSVAL(p,l2_attrFile,mode); SIVAL(p,l2_cbList,0); /* No extended attributes */ SCVAL(p,l2_cchName,strlen(fname)); @@ -451,7 +451,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,8,adate); put_dos_date2(p,12,mdate); SIVAL(p,16,(uint32)size); - SIVAL(p,20,ROUNDUP(size,1024)); + SIVAL(p,20,SMB_ROUNDUP(size,1024)); SSVAL(p,24,mode); SIVAL(p,26,4); CVAL(p,30) = strlen(fname); @@ -470,7 +470,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,8,adate); put_dos_date2(p,12,mdate); SIVAL(p,16,(uint32)size); - SIVAL(p,20,ROUNDUP(size,1024)); + SIVAL(p,20,SMB_ROUNDUP(size,1024)); SSVAL(p,24,mode); CVAL(p,32) = strlen(fname); pstrcpy(p + 33, fname); @@ -1335,7 +1335,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,(uint32)size); - SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); + SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024)); SSVAL(pdata,l1_attrFile,mode); SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ break; @@ -1346,7 +1346,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,(uint32)size); - SIVAL(pdata,16,ROUNDUP(size,1024)); + SIVAL(pdata,16,SMB_ROUNDUP(size,1024)); SIVAL(pdata,20,mode); break; -- cgit From 31739a0e1e32abfa7da166afbc5075aeab4124e6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Nov 1998 21:38:13 +0000 Subject: O_EXCL fixes for printing files & oplocks. Jeremy. (This used to be commit 4ca71c90985b1c88d92bdd0f9079a4afc263dc46) --- source3/smbd/open.c | 5 ++++- source3/smbd/oplock.c | 2 +- source3/smbd/reply.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f9ddc969a8..c81334c8ae 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -312,7 +312,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, /* this handles a bug in Win95 - it doesn't say to create the file when it should */ if (conn->printer) { - flags |= O_CREAT; + flags |= (O_CREAT|O_EXCL); } /* @@ -770,6 +770,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE) flags2 |= O_TRUNC; + if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) + flags2 |= O_EXCL; + /* note that we ignore the append flag as append does not mean the same thing under dos and unix */ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 89a2adb900..e0e1658a78 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1057,7 +1057,7 @@ void check_kernel_oplocks(void) return; } - if((fd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) { + if((fd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", tmpname, strerror(errno) )); unlink( tmpname ); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d466884ab6..ee0053aed0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2728,7 +2728,7 @@ int reply_printopen(connection_struct *conn, /* Open for exclusive use, write only. */ open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE), unix_mode(conn,0), 0, NULL, NULL); + (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL); if (!fsp->open) { file_free(fsp); -- cgit From 3b4a9ff3809ee05a7f06c3eaddd1e5a6e35bfc49 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Nov 1998 23:28:59 +0000 Subject: Makefile.in: Re-added quotes round ROFF call for DGUX. script/installman.sh: Make installman ignore ROFF argument if it is "". smbd/oplock.c: Move location of oplock test file to lockdir. Jeremy. (This used to be commit 6c25a3314243997508b0b2da4bfa10bb979e9c10) --- source3/smbd/oplock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e0e1658a78..19a3afa998 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1048,8 +1048,7 @@ void check_kernel_oplocks(void) set_process_capability(KERNEL_OPLOCK_CAPABILITY,True); set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,True); - slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", (unsigned int)getpid()); - mktemp(tmpname); + slprintf(tmpname,sizeof(tmpname)-1, "%/koplock.%d", lp_lockdir(), (int)getpid()); if(pipe(pfd) != 0) { DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", -- cgit From 74d539f5573a3ed3ff1b96c54752a389da4c3e14 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 17 Nov 1998 16:19:04 +0000 Subject: - group database API. oops and oh dear, the threat has been carried out: the pre-alpha "domain group" etc parameters have disappeared. - interactive debug detection - re-added mem_man (andrew's memory management, detects memory corruption) - american spellings of "initialise" replaced with english spelling of "initialise". - started on "lookup_name()" and "lookup_sid()" functions. proper ones. - moved lots of functions around. created some modules of commonly used code. e.g the password file locking code, which is used in groupfile.c and aliasfile.c and smbpass.c - moved RID_TYPE_MASK up another bit. this is really unfortunate, but there is no other "fast" way to identify users from groups from aliases. i do not believe that this code saves us anything (the multipliers) and puts us at a disadvantage (reduces the useable rid space). the designers of NT aren't silly: if they can get away with a user- interface-speed LsaLookupNames / LsaLookupSids, then so can we. i spoke with isaac at the cifs conference, the only time for example that they do a security context check is on file create. certainly not on individual file reads / writes, which would drastically hit their performance and ours, too. - renamed myworkgroup to global_sam_name, amongst other things, when used in the rpc code. there is also a global_member_name, as we are always responsible for a SAM database, the scope of which is limited by the role of the machine (e.g if a member of a workgroup, your SAM is for _local_ logins only, and its name is the name of your server. you even still have a SID. see LsaQueryInfoPolicy, levels 3 and 5). - updated functionality of groupname.c to be able to cope with names like DOMAIN\group and SERVER\alias. used this code to be able to do aliases as well as groups. this code may actually be better off being used in username mapping, too. - created a connect to serverlist function in clientgen.c and used it in password.c - initialisation in server.c depends on the role of the server. well, it does now. - rpctorture. smbtorture. EXERCISE EXTREME CAUTION. (This used to be commit 0d21e1e6090b933f396c764af535ca3388a562db) --- source3/smbd/groupname.c | 729 +++++++++++++++++++++++++++++++++++------------ source3/smbd/nttrans.c | 4 +- source3/smbd/password.c | 114 +------- source3/smbd/reply.c | 4 +- source3/smbd/server.c | 51 +++- source3/smbd/service.c | 2 +- 6 files changed, 609 insertions(+), 295 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 4afa9ece88..2b87cad330 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -19,12 +19,43 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifdef USING_GROUPNAME_MAP +/* + * UNIX gid and Local or Domain SID resolution. This module resolves + * only those entries in the map files, it is *NOT* responsible for + * resolving UNIX groups not listed: that is an entirely different + * matter, altogether... + */ + +/* + * + * + + format of the file is: + + unixname NT Group name + unixname Domain Admins (well-known Domain Group) + unixname DOMAIN_NAME\NT Group name + unixname OTHER_DOMAIN_NAME\NT Group name + unixname DOMAIN_NAME\Domain Admins (well-known Domain Group) + .... + + if the DOMAIN_NAME\ component is left off, then your own domain is assumed. + + * + * + */ + #include "includes.h" extern int DEBUGLEVEL; -extern DOM_SID global_sam_sid; +/* we can map either local aliases or domain groups */ +typedef enum +{ + GROUP_LOCAL, + GROUP_DOMAIN + +} GROUP_TYPE; /************************************************************************** Groupname map functionality. The code loads a groupname map file and @@ -33,211 +64,543 @@ extern DOM_SID global_sam_sid; if the demands on it become excessive. ***************************************************************************/ -typedef struct groupname_map { - ubi_slNode next; - - char *windows_name; - DOM_SID windows_sid; +typedef struct group_name_info +{ + char *nt_name; + char *nt_domain; char *unix_name; - gid_t unix_gid; -} groupname_map_entry; + + DOM_SID sid; + gid_t unix_gid; + +} GROUP_NAME_INFO; + +typedef struct name_map +{ + ubi_slNode next; + GROUP_NAME_INFO grp; + +} name_map_entry; static ubi_slList groupname_map_list; +static ubi_slList aliasname_map_list; + +static void delete_name_entry(name_map_entry *gmep) +{ + if (gmep->grp.nt_name) + { + free(gmep->grp.nt_name); + } + if (gmep->grp.nt_domain) + { + free(gmep->grp.nt_domain); + } + if (gmep->grp.unix_name) + { + free(gmep->grp.unix_name); + } + free((char*)gmep); +} + +/************************************************************************** + Delete all the entries in the name map list. +***************************************************************************/ + +static void delete_map_list(ubi_slList *map_list) +{ + name_map_entry *gmep; + + while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL) + { + delete_name_entry(gmep); + } +} + /************************************************************************** - Delete all the entries in the groupname map list. + makes a group sid out of a domain sid and a _unix_ gid. ***************************************************************************/ +static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type) +{ + uint32 tmp_rid; + uint8 tmp_type; + + DEBUG(10,("make_mydomain_sid\n")); + + if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) + { + DEBUG(0,("make_mydomain_sid: unknown domain %s\n", + grp->nt_domain)); + return False; + } + else if (lookup_wk_group_rid(grp->nt_name, &tmp_rid, &tmp_type)) + { + return sid_append_rid(&grp->sid, tmp_rid); + } + else + { + if (type == GROUP_DOMAIN) + { + tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid); + } + else + { + tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid); + } + return sid_append_rid(&(grp->sid), tmp_rid); + } +} -static void delete_groupname_map_list(void) +/************************************************************************** + makes a group sid out of an nt domain, nt group name or a unix group name. +***************************************************************************/ +static BOOL unix_name_to_group_info(GROUP_NAME_INFO *grp, GROUP_TYPE type) { - groupname_map_entry *gmep; + extern fstring global_sam_name; + struct group *gptr = NULL; + + /* + * Attempt to get the unix gid_t for this name. + */ + + DEBUG(5,("unix_name_to_group_info: unix_name:%s\n", grp->unix_name)); + + gptr = (struct group *)getgrnam(grp->unix_name); + if (gptr == NULL) + { + DEBUG(0,("unix_name_to_group_info: getgrnam for group %s\ +failed. Error was %s.\n", grp->unix_name, strerror(errno) )); + return False; + } + + grp->unix_gid = (gid_t)gptr->gr_gid; + + DEBUG(5,("unix_name_to_group_info: unix gid:%d\n", grp->unix_gid)); + + /* + * Now map the name to an NT SID+RID. + */ + + if (grp->nt_domain != NULL && !strequal(grp->nt_domain, global_sam_name)) + { + /* Must add client-call lookup code here, to + * resolve remote domain's sid and the group's rid, + * in that domain. + * + * NOTE: it is _incorrect_ to put code here that assumes + * that we can call pwdb_gid_to_group_rid() or _alias_rid(): + * it is a totally different domain for which we are *NOT* + * responsible. + * for foriegn domains for which we are *NOT* the PDC, all + * we can be responsible for is the unix * gid_t to which + * the foriegn SID+rid maps to, on this _local_ machine. + */ + + if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) + { + DEBUG(0,("unix_name_to_group_info: no known sid for %s\n", + grp->nt_domain)); + return False; + } + + DEBUG(0,("unix_name_to_group_info: cannot resolve domain %s\n", + grp->nt_domain)); + + return False; + } + else + { + return make_mydomain_sid(grp, type); + } +} - while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) { - if(gmep->windows_name) - free(gmep->windows_name); - if(gmep->unix_name) - free(gmep->unix_name); - free((char *)gmep); - } +static BOOL make_name_entry(name_map_entry **new_ep, + char *nt_domain, char *nt_group, char *unix_group, + GROUP_TYPE type) +{ + /* + * Create the list entry and add it onto the list. + */ + + DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group)); + + (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry)); + if ((*new_ep) == NULL) + { + DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n")); + return False; + } + + ZERO_STRUCTP(*new_ep); + + (*new_ep)->grp.nt_name = strdup(nt_group ); + (*new_ep)->grp.nt_domain = strdup(nt_domain ); + (*new_ep)->grp.unix_name = strdup(unix_group); + + if ((*new_ep)->grp.nt_name == NULL || + (*new_ep)->grp.unix_name == NULL) + { + DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n")); + delete_name_entry((*new_ep)); + return False; + } + + /* + * look up the group names, make the Group-SID and unix gid + */ + + if (!unix_name_to_group_info(&(*new_ep)->grp, type)) + { + delete_name_entry((*new_ep)); + return False; + } + + return True; } /************************************************************************** - Load a groupname map file. Sets last accessed timestamp. + Load a name map file. Sets last accessed timestamp. ***************************************************************************/ +static void load_name_map(GROUP_TYPE type) +{ + static time_t groupmap_file_last_modified = (time_t)0; + static time_t aliasmap_file_last_modified = (time_t)0; + static BOOL initialised_group = False; + static BOOL initialised_alias = False; + char *groupname_map_file = lp_groupname_map(); + char *aliasname_map_file = lp_aliasname_map(); + + SMB_STRUCT_STAT st; + FILE *fp; + char *s; + pstring buf; + name_map_entry *new_ep; + + time_t *file_last_modified; + int *initialised; + char *map_file; + ubi_slList *map_list; + + if (type == GROUP_DOMAIN) + { + file_last_modified = &groupmap_file_last_modified; + initialised = &initialised_group; + map_file = groupname_map_file; + map_list = &groupname_map_list; + } + else + { + file_last_modified = &aliasmap_file_last_modified; + initialised = &initialised_alias; + map_file = aliasname_map_file; + map_list = &aliasname_map_list; + } + + DEBUG(10,("load_name_map : %s\n", map_file)); + + if (!(*initialised)) + { + ubi_slInitList(map_list); + (*initialised) = True; + } + + if (!*map_file) + { + return; + } + + if (sys_stat(map_file, &st) != 0) + { + DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n", + map_file, strerror(errno) )); + return; + } + + /* + * Check if file has changed. + */ + if (st.st_mtime <= (*file_last_modified)) + { + return; + } + + (*file_last_modified) = st.st_mtime; + + /* + * Load the file. + */ + + fp = fopen(map_file,"r"); + if (!fp) + { + DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n", + map_file, strerror(errno))); + return; + } + + /* + * Throw away any previous list. + */ + delete_map_list(map_list); + + DEBUG(4,("load_name_map: Scanning name map %s\n",map_file)); + + while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL) + { + pstring unixname; + pstring nt_name; + fstring nt_domain; + fstring nt_group; + char *p; + + DEBUG(10,("Read line |%s|\n", s)); + + memset(nt_name, 0, sizeof(nt_name)); + + if (!*s || strchr("#;",*s)) + continue; + + if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) + continue; + + if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name))) + continue; + + trim_string(unixname, " ", " "); + trim_string(nt_name, " ", " "); + + if (!*nt_name) + continue; + + if (!*unixname) + continue; + + DEBUG(5,("unixname = %s, ntname = %s.\n", + unixname, nt_name)); + + p = strchr(nt_name, '\\'); + + if (p == NULL) + { + memset(nt_domain, 0, sizeof(nt_domain)); + fstrcpy(nt_group, nt_name); + } + else + { + *p = 0; + p++; + fstrcpy(nt_domain, nt_name); + fstrcpy(nt_group , p); + } + + if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type)) + { + ubi_slAddHead(map_list, (ubi_slNode *)new_ep); + } + } + + DEBUG(10,("load_name_map: Added %ld entries to name map.\n", + ubi_slCount(map_list))); + + fclose(fp); +} + +/*********************************************************** + Lookup a gid_t by SID +************************************************************/ +static BOOL map_sid_to_gid(GROUP_TYPE type, ubi_slList *map_list, + DOM_SID *psid, gid_t *gid) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (sid_equal(&gmep->grp.sid, psid)) + { + *gid = gmep->grp.unix_gid; + DEBUG(7,("map_sid_to_gid: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + Lookup a SID entry by nt name. +************************************************************/ +static BOOL map_sid_to_ntname(GROUP_TYPE type, ubi_slList *map_list, + DOM_SID *psid, char *ntname, char *ntdomain) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (sid_equal(&gmep->grp.sid, psid)) + { + if (ntname != NULL) + { + fstrcpy(ntname, gmep->grp.nt_name); + } + if (ntdomain != NULL) + { + fstrcpy(ntname, gmep->grp.nt_domain); + } + DEBUG(7,("map_sid_to_ntname: Mapping unix group %s to nt group \%s\%s\n", + gmep->grp.unix_name, + gmep->grp.nt_domain, gmep->grp.nt_name )); + return True; + } + } + + return False; +} -void load_groupname_map(void) -{ - static time_t groupmap_file_last_modified = (time_t)0; - static BOOL initialized = False; - char *groupname_map_file = lp_groupname_map(); - SMB_STRUCT_STAT st; - FILE *fp; - char *s; - pstring buf; - groupname_map_entry *new_ep; - - if(!initialized) { - ubi_slInitList( &groupname_map_list ); - initialized = True; - } - - if (!*groupname_map_file) - return; - - if(sys_stat(groupname_map_file, &st) != 0) { - DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n", - groupname_map_file, strerror(errno) )); - return; - } - - /* - * Check if file has changed. - */ - if( st.st_mtime <= groupmap_file_last_modified) - return; - - groupmap_file_last_modified = st.st_mtime; - - /* - * Load the file. - */ - - fp = fopen(groupname_map_file,"r"); - if (!fp) { - DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n", - groupname_map_file, strerror(errno))); - return; - } - - /* - * Throw away any previous list. - */ - delete_groupname_map_list(); - - DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file)); - - while((s=fgets_slash(buf,sizeof(buf),fp))!=NULL) { - pstring unixname; - pstring windows_name; - struct group *gptr; - DOM_SID tmp_sid; - - DEBUG(10,("load_groupname_map: Read line |%s|\n", s)); - - if (!*s || strchr("#;",*s)) - continue; - - if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) - continue; - - if(!next_token(&s,windows_name, "\t\n\r=", sizeof(windows_name))) - continue; - - trim_string(unixname, " ", " "); - trim_string(windows_name, " ", " "); - - if (!*windows_name) - continue; - - if(!*unixname) - continue; - - DEBUG(5,("load_groupname_map: unixname = %s, windowsname = %s.\n", - unixname, windows_name)); - - /* - * Attempt to get the unix gid_t for this name. - */ - - if((gptr = (struct group *)getgrnam(unixname)) == NULL) { - DEBUG(0,("load_groupname_map: getgrnam for group %s failed.\ -Error was %s.\n", unixname, strerror(errno) )); - continue; - } - - /* - * Now map to an NT SID. - */ - - if(!lookup_wellknown_sid_from_name(windows_name, &tmp_sid)) { - /* - * It's not a well known name, convert the UNIX gid_t - * to a rid within this domain SID. - */ - tmp_sid = global_sam_sid; - tmp_sid.sub_auths[tmp_sid.num_auths++] = - pdb_gid_to_group_rid((gid_t)gptr->gr_gid); - } - - /* - * Create the list entry and add it onto the list. - */ - - if((new_ep = (groupname_map_entry *)malloc( sizeof(groupname_map_entry) ))== NULL) { - DEBUG(0,("load_groupname_map: malloc fail for groupname_map_entry.\n")); - fclose(fp); - return; - } - - new_ep->unix_gid = gptr->gr_gid; - new_ep->windows_sid = tmp_sid; - new_ep->windows_name = strdup( windows_name ); - new_ep->unix_name = strdup( unixname ); - - if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) { - DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n")); - fclose(fp); - if(new_ep->windows_name != NULL) - free(new_ep->windows_name); - if(new_ep->unix_name != NULL) - free(new_ep->unix_name); - free((char *)new_ep); - return; - } - memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) ); - - ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep); - } - - DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n", - ubi_slCount(&groupname_map_list))); - - fclose(fp); +/*********************************************************** + Lookup a SID entry by nt name. +************************************************************/ +static BOOL map_ntname_to_sid(GROUP_TYPE type, ubi_slList *map_list, + char * ntname, DOM_SID *psid) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (strequal(gmep->grp.nt_name, ntname)) + { + *psid = gmep->grp.sid; + DEBUG(7,("map_ntname_to_sid: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; } /*********************************************************** Lookup a SID entry by gid_t. ************************************************************/ +static BOOL map_gid_to_sid(GROUP_TYPE type, ubi_slList *map_list, + gid_t gid, DOM_SID *psid) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (gmep->grp.unix_gid == gid) + { + *psid = gmep->grp.sid; + DEBUG(7,("map_gid_to_sid: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/* + * Call these four functions to resolve unix group ids and either + * local group SIDs or domain group SIDs listed in the local group + * or domain group map files. + * + * Note that it is *NOT* the responsibility of these functions to + * resolve entries that are not in the map files. + * + * Any SID can be in the map files (i.e from any Domain). + */ -void map_gid_to_sid( gid_t gid, DOM_SID *psid) +/*********************************************************** + Lookup a Group entry by sid. +************************************************************/ +BOOL map_group_sid_to_name(DOM_SID *psid, char *group_name, char *nt_domain) +{ + return map_sid_to_ntname(GROUP_DOMAIN, &groupname_map_list, psid, group_name, nt_domain); +} + +/*********************************************************** + Lookup an Alias SID entry by name. +************************************************************/ +BOOL map_alias_sid_to_name(DOM_SID *psid, char *alias_name, char *nt_domain) +{ + return map_sid_to_ntname(GROUP_LOCAL, &aliasname_map_list, psid, alias_name, nt_domain); +} + +/*********************************************************** + Lookup a Group SID entry by name. +************************************************************/ +BOOL map_group_name_to_sid(char *group_name, DOM_SID *psid) { - groupname_map_entry *gmep; + return map_ntname_to_sid(GROUP_DOMAIN, &groupname_map_list, group_name, psid); +} - /* - * Initialize and load if not already loaded. - */ - load_groupname_map(); +/*********************************************************** + Lookup an Alias SID entry by name. +************************************************************/ +BOOL map_alias_name_to_sid(char *alias_name, DOM_SID *psid) +{ + return map_ntname_to_sid(GROUP_LOCAL, &aliasname_map_list, alias_name, psid); +} - for( gmep = (groupname_map_entry *)ubi_slFirst( &groupname_map_list); - gmep; gmep = (groupname_map_entry *)ubi_slNext( gmep )) { +/*********************************************************** + Lookup an Alias SID entry by gid_t. +************************************************************/ +BOOL map_gid_to_alias_sid(gid_t gid, DOM_SID *psid) +{ + return map_gid_to_sid(GROUP_LOCAL, &aliasname_map_list, gid, psid); +} - if( gmep->unix_gid == gid) { - *psid = gmep->windows_sid; - DEBUG(7,("map_gid_to_sid: Mapping unix group %s to windows group %s.\n", - gmep->unix_name, gmep->windows_name )); - return; - } - } +/*********************************************************** + Lookup a Group SID entry by gid_t. +************************************************************/ +BOOL map_gid_to_group_sid( gid_t gid, DOM_SID *psid) +{ + return map_gid_to_sid(GROUP_DOMAIN, &groupname_map_list, gid, psid); +} - /* - * If there's no map, convert the UNIX gid_t - * to a rid within this domain SID. - */ - *psid = global_sam_sid; - psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid); +/*********************************************************** + Lookup a Group gid_t by SID +************************************************************/ +BOOL map_group_sid_to_gid( DOM_SID *psid, gid_t *gid) +{ + return map_sid_to_gid(GROUP_DOMAIN, &groupname_map_list, psid, gid); +} - return; +/*********************************************************** + Lookup an Alias gid_t by SID +************************************************************/ +BOOL map_alias_sid_to_gid( DOM_SID *psid, gid_t *gid) +{ + return map_sid_to_gid(GROUP_LOCAL, &aliasname_map_list, psid, gid); } -#else /* USING_GROUPNAME_MAP */ - void load_groupname_map(void) {;} -#endif /* USING_GROUPNAME_MAP */ + diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8b4049cd96..e4f0d2e2ec 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -562,8 +562,8 @@ int reply_ntcreate_and_X(connection_struct *conn, /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(conn) && lp_nt_pipe_support()) { - + if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE) + { int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) return ret; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fb5acf156f..0c8eb124ff 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -153,7 +153,7 @@ char *validated_username(uint16 vuid) /**************************************************************************** Setup the groups a user belongs to. ****************************************************************************/ -int setup_groups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups) +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; @@ -180,7 +180,7 @@ int setup_groups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_gro if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) { - DEBUG(0,("setup_groups malloc fail !\n")); + DEBUG(0,("get_unixgroups malloc fail !\n")); return -1; } @@ -263,7 +263,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(unix_name,uid,gid, + get_unixgroups(unix_name,uid,gid, &vuser->n_groups, &vuser->groups); @@ -1142,15 +1142,10 @@ BOOL domain_client_validate( char *user, char *domain, unsigned char local_lm_response[24]; unsigned char local_nt_reponse[24]; unsigned char trust_passwd[16]; - fstring remote_machine; - char *p; - struct in_addr dest_ip; NET_ID_INFO_CTR ctr; NET_USER_INFO_3 info3; struct cli_state cli; uint32 smb_uid_low; - BOOL connected_ok = False; - struct nmb_name calling, called; /* * Check that the requested domain is not our own machine name. @@ -1211,102 +1206,9 @@ BOOL domain_client_validate( char *user, char *domain, * see if they were valid. */ - ZERO_STRUCT(cli); - - if(cli_initialise(&cli) == False) { - DEBUG(0,("domain_client_validate: unable to initialize client connection.\n")); - return False; - } - - /* - * Treat each name in the 'password server =' line as a potential - * PDC/BDC. Contact each in turn and try and authenticate. - */ - - p = lp_passwordserver(); - while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { - - standard_sub_basic(remote_machine); - strupper(remote_machine); - - if(!resolve_name( remote_machine, &dest_ip, 0x20)) { - DEBUG(1,("domain_client_validate: Can't resolve address for %s\n", remote_machine)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("domain_client_validate: Password server loop - not using password server %s\n",remote_machine)); - continue; - } - - if (!cli_connect(&cli, remote_machine, &dest_ip)) { - DEBUG(0,("domain_client_validate: unable to connect to SMB server on \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - continue; - } - - make_nmb_name(&calling, global_myname , 0x0 , scope); - make_nmb_name(&called , remote_machine, 0x20, scope); - - if (!cli_session_request(&cli, &calling, &called)) + if (!cli_connect_serverlist(&cli, lp_passwordserver())) { - DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - continue; - } - - cli.protocol = PROTOCOL_NT1; - - if (!cli_negprot(&cli)) { - DEBUG(0,("domain_client_validate: machine %s rejected the negotiate protocol. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - continue; - } - - if (cli.protocol != PROTOCOL_NT1) { - DEBUG(0,("domain_client_validate: machine %s didn't negotiate NT protocol.\n", - remote_machine)); - cli_shutdown(&cli); - continue; - } - - /* - * Do an anonymous session setup. - */ - - if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) { - DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - continue; - } - - if (!(cli.sec_mode & 1)) { - DEBUG(1,("domain_client_validate: machine %s isn't in user level security mode\n", - remote_machine)); - cli_shutdown(&cli); - continue; - } - - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { - DEBUG(0,("domain_client_validate: machine %s rejected the tconX on the IPC$ share. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - continue; - } - - /* - * We have an anonymous connection to IPC$. - */ - connected_ok = True; - break; - } - - if (!connected_ok) { DEBUG(0,("domain_client_validate: Domain password server not available.\n")); - cli_shutdown(&cli); return False; } @@ -1317,7 +1219,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); if(cli_nt_session_open(&cli, PIPE_NETLOGON) == False) { DEBUG(0,("domain_client_validate: unable to open the domain client session to \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); +machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); @@ -1326,7 +1228,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); if(cli_nt_setup_creds(&cli, trust_passwd) == False) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ -%s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); +%s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); @@ -1341,7 +1243,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), &ctr, &info3) == False) { DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); +%s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); @@ -1361,7 +1263,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); if(cli_nt_logoff(&cli, &ctr) == False) { DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); +%s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ee0053aed0..78a09e46e7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1403,8 +1403,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt files_struct *fsp; /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn) && lp_nt_pipe_support()) + if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE) + { return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); + } /* XXXX we need to handle passed times, sattr and flags */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 68f722ff51..49816e5d47 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -25,6 +25,7 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; extern fstring global_myworkgroup; +extern fstring global_sam_name; extern pstring global_myname; int am_parent = 1; @@ -428,6 +429,13 @@ void exit_server(char *reason) locking_end(); DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); +#ifdef MEM_MAN + { + extern FILE *dbf; + smb_mem_write_verbose(dbf); + dbgflush(); + } +#endif exit(0); } @@ -644,12 +652,42 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); fstrcpy(global_myworkgroup, lp_workgroup()); + memset(global_sam_name, 0, sizeof(global_sam_name)); + + if (lp_domain_logons()) + { + if (lp_security() == SEC_USER) + { + /* we are PDC (or BDC) for a Domain */ + fstrcpy(global_sam_name, lp_workgroup()); + } + else if (lp_security() == SEC_DOMAIN) + { + /* we are a "PDC", but FOR LOCAL SAM DATABASE ONLY */ + fstrcpy(global_sam_name, global_myname); + } + else if (lp_security() == SEC_SHARE) + { + DEBUG(0,("ERROR: no Domain functionality in security = share\n")); + exit(1); + } + } + + generate_wellknown_sids(); - if(!pdb_generate_sam_sid()) { + if (!generate_sam_sid()) + { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } + if (lp_security() == SEC_DOMAIN && !get_member_domain_sid()) + { + DEBUG(0,("ERROR: Samba cannot obtain PDC SID from PDC(s) %s.\n", + lp_passwordserver())); + exit(1); + } + CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); /* Setup the signals that allow the debug log level @@ -696,7 +734,16 @@ static void usage(char *pname) if (!locking_init(0)) exit(1); - if(!initialize_password_db()) + if(!initialise_passgrp_db()) + exit(1); + + if(!initialise_password_db()) + exit(1); + + if(!initialise_group_db()) + exit(1); + + if(!initialise_alias_db()) exit(1); /* possibly reload the services file. */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ee195e12ec..cedac1c76f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -387,7 +387,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!IS_IPC(conn)) { /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(conn->user,conn->uid,conn->gid, + get_unixgroups(conn->user,conn->uid,conn->gid, &conn->ngroups,&conn->groups); /* check number of connections */ -- cgit From 768761820e8d7481c586c4e0ab4ac7cb36d18c4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Nov 1998 20:50:07 +0000 Subject: Added the same open()/fopen()/creat()/mmap() -> sys_XXX calls. Tidied up some of the mess (no other word for it). Still doesn't compile cleanly. There are calls with incorrect parameters that don't seem to be doing the right thing. This code still needs surgery :-(. Jeremy. (This used to be commit 18ff93a9abbf68ee8c59c0af3e57c63e4a015dac) --- source3/smbd/chgpasswd.c | 6 +++--- source3/smbd/connection.c | 6 +++--- source3/smbd/groupname.c | 4 ++-- source3/smbd/ipc.c | 6 +++--- source3/smbd/message.c | 2 +- source3/smbd/open.c | 4 ++-- source3/smbd/oplock.c | 2 +- source3/smbd/password.c | 2 +- source3/smbd/quotas.c | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 52ca364070..69ac69b59b 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -65,7 +65,7 @@ static int findpty(char **slave) #endif /* !HAVE_GRANTPT */ #if defined(HAVE_GRANTPT) - if ((master = open("/dev/ptmx", O_RDWR)) >= 1) { + if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 1) { grantpt(master); unlockpt(master); *slave = ptsname(master); @@ -90,7 +90,7 @@ static int findpty(char **slave) DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); line[8] = dpname[3]; line[9] = dpname[4]; - if ((master = open(line, O_RDWR)) >= 0) { + if ((master = sys_open(line, O_RDWR, 0)) >= 0) { DEBUG(3,("pty: opened %s\n", line ) ); line[5] = 't'; *slave = line; @@ -133,7 +133,7 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, } /* Open slave pty and acquire as new controlling terminal. */ - if ((slave = open(slavedev, O_RDWR)) < 0) { + if ((slave = sys_open(slavedev, O_RDWR, 0)) < 0) { DEBUG(3,("More weirdness, could not open %s\n", slavedev)); return(False); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index af74e40f6a..db6c66f1d5 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -51,7 +51,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) pstrcat(fname,name); pstrcat(fname,".LCK"); - fd = open(fname,O_RDWR); + fd = sys_open(fname,O_RDWR,0); if (fd == -1) { DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno))); return(False); @@ -137,11 +137,11 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO pstrcat(fname,".LCK"); if (!file_exist(fname,NULL)) { - fd = open(fname,O_RDWR|O_CREAT|O_EXCL, 0644); + fd = sys_open(fname,O_RDWR|O_CREAT|O_EXCL, 0644); } if (fd == -1) { - fd = open(fname,O_RDWR); + fd = sys_open(fname,O_RDWR,0); } if (fd == -1) { diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 2b87cad330..44625cf54a 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -330,7 +330,7 @@ static void load_name_map(GROUP_TYPE type) * Load the file. */ - fp = fopen(map_file,"r"); + fp = sys_fopen(map_file,"r"); if (!fp) { DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n", @@ -461,7 +461,7 @@ static BOOL map_sid_to_ntname(GROUP_TYPE type, ubi_slList *map_list, { fstrcpy(ntname, gmep->grp.nt_domain); } - DEBUG(7,("map_sid_to_ntname: Mapping unix group %s to nt group \%s\%s\n", + DEBUG(7,("map_sid_to_ntname: Mapping unix group %s to nt group \\%s\\%s\n", gmep->grp.unix_name, gmep->grp.nt_domain, gmep->grp.nt_name )); return True; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index eed5a71401..d5ff7ddf28 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -635,7 +635,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, pstring fname; pstrcpy(fname,lp_driverfile()); - f=fopen(fname,"r"); + f=sys_fopen(fname,"r"); if (!f) { DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno))); desc->errcode=NERR_notsupported; @@ -741,7 +741,7 @@ static int get_printerdrivernumber(int snum) pstrcpy(fname,lp_driverfile()); DEBUG(4,("In get_printerdrivernumber: %s\n",fname)); - f=fopen(fname,"r"); + f=sys_fopen(fname,"r"); if (!f) { DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno))); return(0); @@ -999,7 +999,7 @@ static int get_server_info(uint32 servertype, pstrcat(fname,"/"); pstrcat(fname,SERVER_LIST); - f = fopen(fname,"r"); + f = sys_fopen(fname,"r"); if (!f) { DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno))); diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 001fc652b2..d13dfda1e0 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -56,7 +56,7 @@ static void msg_deliver(void) slprintf(s,sizeof(s)-1, "%s/msg.XXXXXX",tmpdir()); fstrcpy(name,(char *)mktemp(s)); - fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); + fd = sys_open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); if (fd == -1) { DEBUG(1,("can't open message file %s\n",name)); return; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c81334c8ae..d7cef6d63b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -552,8 +552,8 @@ static void mmap_open_file(files_struct *fsp) if (!fsp->can_write) { fsp->mmap_size = file_size(fsp->fsp_name); if (fsp->mmap_size < MAX_MMAP_SIZE) { - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + fsp->mmap_ptr = (char *)sys_mmap(NULL,fsp->mmap_size, + PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,(SMB_OFF_T)0); if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { DEBUG(3,("Failed to mmap() %s - %s\n", diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 19a3afa998..1d38b362ec 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1056,7 +1056,7 @@ void check_kernel_oplocks(void) return; } - if((fd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { + if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", tmpname, strerror(errno) )); unlink( tmpname ); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0c8eb124ff..9011b9b95e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -813,7 +813,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) int plus_allowed = 1; char *file_host; char *file_user; - FILE *fp = fopen(equiv_file, "r"); + FILE *fp = sys_fopen(equiv_file, "r"); DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); if (! fp) return False; while(fgets(buf, sizeof(buf), fp)) diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 5cd5a895c6..afabb1befd 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -270,7 +270,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U if ( devno != devno_cached ) { devno_cached = devno ; #if defined(SUNOS5) - if ((fd = fopen(MNTTAB, "r")) == NULL) + if ((fd = sys_fopen(MNTTAB, "r")) == NULL) return(False) ; found = False ; @@ -320,7 +320,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #if defined(SUNOS5) DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); - if((file=open(name, O_RDONLY))<0) { + if((file=sys_open(name, O_RDONLY,0))<0) { setuid(user_id); /* Restore the original UID status */ seteuid(euser_id); return(False); -- cgit From 490439d77a7fe3daadce1f30f17f03896c6739aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Nov 1998 23:44:52 +0000 Subject: Fixed NT modify timestamp issue. If a client does a modify timestamp on an open file (which will do no good at all on UNIX :-) then keep the modify request pending in the files_struct and apply it at close instead. Jeremy. (This used to be commit 92a7a86f0e0255e3812dd35bebfcd653091514ae) --- source3/smbd/reply.c | 11 +++++++++++ source3/smbd/trans2.c | 17 +++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 78a09e46e7..12bf098a94 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2492,6 +2492,17 @@ int reply_close(connection_struct *conn, /* * Close ordinary file. */ + + /* + * If there was a modify time outstanding, + * try and set it here. + */ + if(fsp->pending_modtime) + set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); + + /* + * Now take care of any time sent in the close. + */ mtime = make_unix_date3(inbuf+smb_vwv1); /* try and set the date */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f1d415e290..81ba511c77 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1496,14 +1496,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *fname; int fd = -1; BOOL bad_path = False; + files_struct *fsp = NULL; if (!CAN_WRITE(conn)) return(ERROR(ERRSRV,ERRaccess)); if (tran_call == TRANSACT2_SETFILEINFO) { - files_struct *fsp = file_fsp(params,0); info_level = SVAL(params,2); + fsp = file_fsp(params,0); + if(fsp && fsp->open && fsp->is_directory) { /* * This is actually a SETFILEINFO on a directory @@ -1802,7 +1804,18 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) */ if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { - if(file_utime(conn, fname, &tvs)!=0) + if(fsp != NULL) + { + /* + * This was a setfileinfo on an open file. + * NT does this a lot. It's actually pointless + * setting the time here, as it will be overwritten + * on the next write, so we save the request + * away and will set it on file code. JRA. + */ + fsp->pending_modtime = tvs.modtime; + } + else if(file_utime(conn, fname, &tvs)!=0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } -- cgit From bb9622bfa6bbbe74a6e4c032cf81501bcbff999d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Nov 1998 19:06:51 +0000 Subject: Fixed crash bug which was assuming that fd_ptr was always non-null (which is not the case with open directories). Jeremy. (This used to be commit c154b1601f5891d664fc538ec8874fa8ef2061e6) --- source3/smbd/files.c | 7 +++++-- source3/smbd/oplock.c | 2 +- source3/smbd/trans2.c | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e58c3834a0..3a41c83766 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -263,6 +263,7 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval for (fsp=Files;fsp;fsp=fsp->next,count++) { if (fsp->open && + fsp->fd_ptr != NULL && fsp->fd_ptr->dev == dev && fsp->fd_ptr->inode == inode && (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) && @@ -287,6 +288,7 @@ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) for (fsp=Files;fsp;fsp=fsp->next) { if (fsp->open && + fsp->fd_ptr != NULL && fsp->fd_ptr->dev == dev && fsp->fd_ptr->inode == inode ) return fsp; @@ -305,6 +307,7 @@ files_struct *file_find_di_next(files_struct *start_fsp) for (fsp = start_fsp->next;fsp;fsp=fsp->next) { if (fsp->open && + fsp->fd_ptr != NULL && fsp->fd_ptr->dev == start_fsp->fd_ptr->dev && fsp->fd_ptr->inode == start_fsp->fd_ptr->inode ) return fsp; @@ -337,7 +340,7 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if (fsp->open && conn == fsp->conn) { + if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL)) { sync_file(conn,fsp); } } @@ -371,7 +374,7 @@ void file_free(files_struct *fsp) string_free(&fsp->fsp_name); - if (fsp->fd_ptr && fsp->fd_ptr->ref_count == 0) { + if ((fsp->fd_ptr != NULL) && fsp->fd_ptr->ref_count == 0) { fd_ptr_free(fsp->fd_ptr); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1d38b362ec..96afb127aa 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1008,7 +1008,7 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) { + if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break && (fsp->fd_ptr != NULL)) { /* Try and break the oplock. */ file_fd_struct *fd_ptr = fsp->fd_ptr; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 81ba511c77..db2be094b1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1756,7 +1756,7 @@ file %s as a share exists that was not opened with FILE_DELETE access.\n", (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); - DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s\ + DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \ dev = %x, inode = %.0f from %x to %x\n", iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, (double)inode, iterate_fsp->share_mode, new_share_mode )); @@ -1771,9 +1771,12 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) * counted struct. Delete when the last reference * goes away. */ - fsp->fd_ptr->delete_on_close = delete_on_close; + fsp->fd_ptr->delete_on_close = delete_on_close; - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode, token); + + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */ } /* end if lp_share_modes() */ -- cgit From 17590be23d342259578d87c3d9310824863a5137 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Nov 1998 22:37:33 +0000 Subject: Sync up with 2.0 code. Added HPUX autoconf changes. Added "gross hack" printer code. Jeremy. (This used to be commit 1ef6d3bd63722afe9c376793a6ea72046d1a0602) --- source3/smbd/ipc.c | 20 +++++++++++++ source3/smbd/nttrans.c | 80 +++++++++++++++++++++++++++++++++++++++++++++----- source3/smbd/trans2.c | 3 +- 3 files changed, 94 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index d5ff7ddf28..41892504ad 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -842,6 +842,26 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, if (init_package(&desc,1,count)) { desc.subcount = count; fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); + } else if(uLevel == 0) { + /* + * This is a *disgusting* hack. + * This is *so* bad that even I'm embarrassed (and I + * have no shame). Here's the deal : + * Until we get the correct SPOOLSS code into smbd + * then when we're running with NT SMB support then + * NT makes this call with a level of zero, and then + * immediately follows it with an open request to + * the \\SRVSVC pipe. If we allow that open to + * succeed then NT barfs when it cannot open the + * \\SPOOLSS pipe immediately after and continually + * whines saying "Printer name is invalid" forever + * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC + * to fail, then NT downgrades to using the downlevel code + * and everything works as well as before. I hate + * myself for adding this code.... JRA. + */ + + fail_next_srvsvc_open(); } *rdata_len = desc.usedlen; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e4f0d2e2ec..c1c82b48e3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -433,6 +433,38 @@ to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access, return smb_open_mode; } +/* + * This is a *disgusting* hack. + * This is *so* bad that even I'm embarrassed (and I + * have no shame). Here's the deal : + * Until we get the correct SPOOLSS code into smbd + * then when we're running with NT SMB support then + * NT makes this call with a level of zero, and then + * immediately follows it with an open request to + * the \\SRVSVC pipe. If we allow that open to + * succeed then NT barfs when it cannot open the + * \\SPOOLSS pipe immediately after and continually + * whines saying "Printer name is invalid" forever + * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC + * to fail, then NT downgrades to using the downlevel code + * and everything works as well as before. I hate + * myself for adding this code.... JRA. + * + * The HACK_FAIL_TIME define allows only a 2 + * second window for this to occur, just in + * case... + */ + +static BOOL fail_next_srvsvc = False; +static time_t fail_time; +#define HACK_FAIL_TIME 2 /* In seconds. */ + +void fail_next_srvsvc_open(void) +{ + fail_next_srvsvc = True; + fail_time = time(NULL); +} + /**************************************************************************** Reply to an NT create and X call on a pipe. ****************************************************************************/ @@ -451,6 +483,24 @@ static int nt_open_pipe(char *fname, connection_struct *conn, if( strequal(fname,known_nt_pipes[i])) break; + /* + * HACK alert.... see above - JRA. + */ + + if(fail_next_srvsvc && (time(NULL) > fail_time + HACK_FAIL_TIME)) { + fail_next_srvsvc = False; + fail_time = (time_t)0; + } + + if(fail_next_srvsvc && strequal(fname, "\\srvsvc")) { + fail_next_srvsvc = False; + return(ERROR(ERRSRV,ERRaccess)); + } + + /* + * End hack alert.... see above - JRA. + */ + if ( known_nt_pipes[i] == NULL ) return(ERROR(ERRSRV,ERRaccess)); @@ -562,8 +612,8 @@ int reply_ntcreate_and_X(connection_struct *conn, /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE) - { + if (IS_IPC(conn) && lp_nt_pipe_support()) { + int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) return ret; @@ -1393,7 +1443,13 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n")); + static BOOL logged_message = False; + + if(!logged_message) { + DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n")); + logged_message = True; /* Only print this once... */ + } + return(ERROR(ERRSRV,ERRnosupport)); } @@ -1408,8 +1464,13 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char **ppsetup, char **ppparams, char **ppdata) { - DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n")); - return(ERROR(ERRSRV,ERRnosupport)); + static BOOL logged_message = False; + + if(!logged_message) { + DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n")); + logged_message = True; /* Only print this once... */ + } + return(ERROR(ERRSRV,ERRnosupport)); } /**************************************************************************** @@ -1420,8 +1481,13 @@ static int call_nt_transact_ioctl(connection_struct *conn, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); - return(ERROR(ERRSRV,ERRnosupport)); + static BOOL logged_message = False; + + if(!logged_message) { + DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); + logged_message = True; /* Only print this once... */ + } + return(ERROR(ERRSRV,ERRnosupport)); } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index db2be094b1..d71c23c87b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1502,9 +1502,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(ERROR(ERRSRV,ERRaccess)); if (tran_call == TRANSACT2_SETFILEINFO) { - info_level = SVAL(params,2); - fsp = file_fsp(params,0); + info_level = SVAL(params,2); if(fsp && fsp->open && fsp->is_directory) { /* -- cgit From ab1ab1ce0d49e968bcbd37841df1a13a2cf42884 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Nov 1998 23:22:43 +0000 Subject: Instrumented hack fix with debug level 10 statements just in case :-). Jeremy. (This used to be commit 10f51b85722141f99ffecc3f19a39de108400828) --- source3/smbd/nttrans.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c1c82b48e3..8aacfa3867 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -463,6 +463,7 @@ void fail_next_srvsvc_open(void) { fail_next_srvsvc = True; fail_time = time(NULL); + DEBUG(10,("fail_next_srvsvc_open: setting up timeout close of \\srvsvc pipe for print fix.\n")); } /**************************************************************************** @@ -490,10 +491,12 @@ static int nt_open_pipe(char *fname, connection_struct *conn, if(fail_next_srvsvc && (time(NULL) > fail_time + HACK_FAIL_TIME)) { fail_next_srvsvc = False; fail_time = (time_t)0; + DEBUG(10,("nt_open_pipe: End of timeout close of \\srvsvc pipe for print fix.\n")); } if(fail_next_srvsvc && strequal(fname, "\\srvsvc")) { fail_next_srvsvc = False; + DEBUG(10,("nt_open_pipe: Deliberately failing open of \\srvsvc pipe for print fix.\n")); return(ERROR(ERRSRV,ERRaccess)); } -- cgit From a97baa50fdbf951cf3568b7068a7194f22642d52 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 21 Nov 1998 00:16:28 +0000 Subject: smbd/password.c: Added *SMBSERVER fix is name is too long. web/swat.c: Changed '?' to help. Jeremy. (This used to be commit 631913ea856926a77304692c74a1bd27faead179) --- source3/smbd/password.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9011b9b95e..683303ff87 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1000,7 +1000,15 @@ struct cli_state *server_cryptkey(void) } make_nmb_name(&calling, local_machine, 0x0 , scope); - make_nmb_name(&called , desthost , 0x20, scope); + + if(strlen(desthost) > 15) + { + DEBUG(1,("server_cryptkey: %s is too long for a password server NetBIOS \ +name, using *SMBSERVER for the connection.\n", desthost )); + make_nmb_name(&called , "*SMBSERVER", 0x20, scope); + } + else + make_nmb_name(&called , desthost , 0x20, scope); if (!cli_session_request(cli, &calling, &called)) { -- cgit From bb5fab7b553dc18d8b0c03f6a65ee92586752955 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 21 Nov 1998 01:26:18 +0000 Subject: formatting change (This used to be commit 94fc7fe3afa1dc5547050248738eb697c1eeef59) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1b4f7f8c77..83e6fe092e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -411,7 +411,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, for (s=name2 ; *s ; s++) if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)mktemp(name2)); + pstrcpy(name,(char *)mktemp(name2)); } return(True); } -- cgit From 091a92e9962a9526dd355b8f6c2e57b0fba167ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 21 Nov 1998 01:28:15 +0000 Subject: try to use *SMBSERVER to connect to password server if the first session_request fails. (This used to be commit ab2370e7ac770f1e32b8d726ab955457fcc8c2d7) --- source3/smbd/password.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 683303ff87..8b73ff4518 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1000,21 +1000,19 @@ struct cli_state *server_cryptkey(void) } make_nmb_name(&calling, local_machine, 0x0 , scope); + make_nmb_name(&called , desthost , 0x20, scope); - if(strlen(desthost) > 15) - { - DEBUG(1,("server_cryptkey: %s is too long for a password server NetBIOS \ -name, using *SMBSERVER for the connection.\n", desthost )); - make_nmb_name(&called , "*SMBSERVER", 0x20, scope); - } - else - make_nmb_name(&called , desthost , 0x20, scope); - - if (!cli_session_request(cli, &calling, &called)) - { - DEBUG(1,("%s rejected the session\n",desthost)); + if (!cli_session_request(cli, &calling, &called)) { + /* try with *SMBSERVER if the first name fails */ cli_shutdown(cli); - return NULL; + make_nmb_name(&called , "*SMBSERVER", 0x20, scope); + if (!cli_initialise(cli) || + !cli_connect(cli, desthost, &dest_ip) || + !cli_session_request(cli, &calling, &called)) { + DEBUG(1,("%s rejected the session\n",desthost)); + cli_shutdown(cli); + return NULL; + } } DEBUG(3,("got session\n")); -- cgit From 8757254f39ab75c93e9917a6bdf99475c6a024d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 23 Nov 1998 03:36:10 +0000 Subject: changed string_sub() to replace " ; and ` in the inserted string with _ use all_string_sub() if you don't want this. (This used to be commit a3357ab49335106674fe7a7481cd0f146d74fbe5) --- source3/smbd/chgpasswd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 69ac69b59b..30b9b3fed6 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -434,12 +434,12 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) } string_sub(passwordprogram,"%u",name); - string_sub(passwordprogram,"%o",oldpass); - string_sub(passwordprogram,"%n",newpass); + all_string_sub(passwordprogram,"%o",oldpass); + all_string_sub(passwordprogram,"%n",newpass); string_sub(chatsequence,"%u",name); - string_sub(chatsequence,"%o",oldpass); - string_sub(chatsequence,"%n",newpass); + all_string_sub(chatsequence,"%o",oldpass); + all_string_sub(chatsequence,"%n",newpass); return(chat_with_program(passwordprogram,name,chatsequence, as_root)); } -- cgit From 4cee58780cb15fe5889b9dd0dc34459512d75062 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 23 Nov 1998 21:51:05 +0000 Subject: unix instance of group database API (This used to be commit e76f593b3572ac881f1aa1fb3326d8b7169b0078) --- source3/smbd/groupname.c | 606 ----------------------------------------------- source3/smbd/nttrans.c | 4 +- source3/smbd/server.c | 20 +- 3 files changed, 3 insertions(+), 627 deletions(-) delete mode 100644 source3/smbd/groupname.c (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c deleted file mode 100644 index 44625cf54a..0000000000 --- a/source3/smbd/groupname.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Groupname handling - Copyright (C) Jeremy Allison 1998. - - 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. -*/ - -/* - * UNIX gid and Local or Domain SID resolution. This module resolves - * only those entries in the map files, it is *NOT* responsible for - * resolving UNIX groups not listed: that is an entirely different - * matter, altogether... - */ - -/* - * - * - - format of the file is: - - unixname NT Group name - unixname Domain Admins (well-known Domain Group) - unixname DOMAIN_NAME\NT Group name - unixname OTHER_DOMAIN_NAME\NT Group name - unixname DOMAIN_NAME\Domain Admins (well-known Domain Group) - .... - - if the DOMAIN_NAME\ component is left off, then your own domain is assumed. - - * - * - */ - - -#include "includes.h" -extern int DEBUGLEVEL; - -/* we can map either local aliases or domain groups */ -typedef enum -{ - GROUP_LOCAL, - GROUP_DOMAIN - -} GROUP_TYPE; - -/************************************************************************** - Groupname map functionality. The code loads a groupname map file and - (currently) loads it into a linked list. This is slow and memory - hungry, but can be changed into a more efficient storage format - if the demands on it become excessive. -***************************************************************************/ - -typedef struct group_name_info -{ - char *nt_name; - char *nt_domain; - char *unix_name; - - DOM_SID sid; - gid_t unix_gid; - -} GROUP_NAME_INFO; - -typedef struct name_map -{ - ubi_slNode next; - GROUP_NAME_INFO grp; - -} name_map_entry; - -static ubi_slList groupname_map_list; -static ubi_slList aliasname_map_list; - -static void delete_name_entry(name_map_entry *gmep) -{ - if (gmep->grp.nt_name) - { - free(gmep->grp.nt_name); - } - if (gmep->grp.nt_domain) - { - free(gmep->grp.nt_domain); - } - if (gmep->grp.unix_name) - { - free(gmep->grp.unix_name); - } - free((char*)gmep); -} - -/************************************************************************** - Delete all the entries in the name map list. -***************************************************************************/ - -static void delete_map_list(ubi_slList *map_list) -{ - name_map_entry *gmep; - - while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL) - { - delete_name_entry(gmep); - } -} - - -/************************************************************************** - makes a group sid out of a domain sid and a _unix_ gid. -***************************************************************************/ -static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type) -{ - uint32 tmp_rid; - uint8 tmp_type; - - DEBUG(10,("make_mydomain_sid\n")); - - if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) - { - DEBUG(0,("make_mydomain_sid: unknown domain %s\n", - grp->nt_domain)); - return False; - } - else if (lookup_wk_group_rid(grp->nt_name, &tmp_rid, &tmp_type)) - { - return sid_append_rid(&grp->sid, tmp_rid); - } - else - { - if (type == GROUP_DOMAIN) - { - tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid); - } - else - { - tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid); - } - return sid_append_rid(&(grp->sid), tmp_rid); - } -} - -/************************************************************************** - makes a group sid out of an nt domain, nt group name or a unix group name. -***************************************************************************/ -static BOOL unix_name_to_group_info(GROUP_NAME_INFO *grp, GROUP_TYPE type) -{ - extern fstring global_sam_name; - struct group *gptr = NULL; - - /* - * Attempt to get the unix gid_t for this name. - */ - - DEBUG(5,("unix_name_to_group_info: unix_name:%s\n", grp->unix_name)); - - gptr = (struct group *)getgrnam(grp->unix_name); - if (gptr == NULL) - { - DEBUG(0,("unix_name_to_group_info: getgrnam for group %s\ -failed. Error was %s.\n", grp->unix_name, strerror(errno) )); - return False; - } - - grp->unix_gid = (gid_t)gptr->gr_gid; - - DEBUG(5,("unix_name_to_group_info: unix gid:%d\n", grp->unix_gid)); - - /* - * Now map the name to an NT SID+RID. - */ - - if (grp->nt_domain != NULL && !strequal(grp->nt_domain, global_sam_name)) - { - /* Must add client-call lookup code here, to - * resolve remote domain's sid and the group's rid, - * in that domain. - * - * NOTE: it is _incorrect_ to put code here that assumes - * that we can call pwdb_gid_to_group_rid() or _alias_rid(): - * it is a totally different domain for which we are *NOT* - * responsible. - * for foriegn domains for which we are *NOT* the PDC, all - * we can be responsible for is the unix * gid_t to which - * the foriegn SID+rid maps to, on this _local_ machine. - */ - - if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) - { - DEBUG(0,("unix_name_to_group_info: no known sid for %s\n", - grp->nt_domain)); - return False; - } - - DEBUG(0,("unix_name_to_group_info: cannot resolve domain %s\n", - grp->nt_domain)); - - return False; - } - else - { - return make_mydomain_sid(grp, type); - } -} - -static BOOL make_name_entry(name_map_entry **new_ep, - char *nt_domain, char *nt_group, char *unix_group, - GROUP_TYPE type) -{ - /* - * Create the list entry and add it onto the list. - */ - - DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group)); - - (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry)); - if ((*new_ep) == NULL) - { - DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n")); - return False; - } - - ZERO_STRUCTP(*new_ep); - - (*new_ep)->grp.nt_name = strdup(nt_group ); - (*new_ep)->grp.nt_domain = strdup(nt_domain ); - (*new_ep)->grp.unix_name = strdup(unix_group); - - if ((*new_ep)->grp.nt_name == NULL || - (*new_ep)->grp.unix_name == NULL) - { - DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n")); - delete_name_entry((*new_ep)); - return False; - } - - /* - * look up the group names, make the Group-SID and unix gid - */ - - if (!unix_name_to_group_info(&(*new_ep)->grp, type)) - { - delete_name_entry((*new_ep)); - return False; - } - - return True; -} - -/************************************************************************** - Load a name map file. Sets last accessed timestamp. -***************************************************************************/ -static void load_name_map(GROUP_TYPE type) -{ - static time_t groupmap_file_last_modified = (time_t)0; - static time_t aliasmap_file_last_modified = (time_t)0; - static BOOL initialised_group = False; - static BOOL initialised_alias = False; - char *groupname_map_file = lp_groupname_map(); - char *aliasname_map_file = lp_aliasname_map(); - - SMB_STRUCT_STAT st; - FILE *fp; - char *s; - pstring buf; - name_map_entry *new_ep; - - time_t *file_last_modified; - int *initialised; - char *map_file; - ubi_slList *map_list; - - if (type == GROUP_DOMAIN) - { - file_last_modified = &groupmap_file_last_modified; - initialised = &initialised_group; - map_file = groupname_map_file; - map_list = &groupname_map_list; - } - else - { - file_last_modified = &aliasmap_file_last_modified; - initialised = &initialised_alias; - map_file = aliasname_map_file; - map_list = &aliasname_map_list; - } - - DEBUG(10,("load_name_map : %s\n", map_file)); - - if (!(*initialised)) - { - ubi_slInitList(map_list); - (*initialised) = True; - } - - if (!*map_file) - { - return; - } - - if (sys_stat(map_file, &st) != 0) - { - DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n", - map_file, strerror(errno) )); - return; - } - - /* - * Check if file has changed. - */ - if (st.st_mtime <= (*file_last_modified)) - { - return; - } - - (*file_last_modified) = st.st_mtime; - - /* - * Load the file. - */ - - fp = sys_fopen(map_file,"r"); - if (!fp) - { - DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n", - map_file, strerror(errno))); - return; - } - - /* - * Throw away any previous list. - */ - delete_map_list(map_list); - - DEBUG(4,("load_name_map: Scanning name map %s\n",map_file)); - - while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL) - { - pstring unixname; - pstring nt_name; - fstring nt_domain; - fstring nt_group; - char *p; - - DEBUG(10,("Read line |%s|\n", s)); - - memset(nt_name, 0, sizeof(nt_name)); - - if (!*s || strchr("#;",*s)) - continue; - - if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) - continue; - - if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name))) - continue; - - trim_string(unixname, " ", " "); - trim_string(nt_name, " ", " "); - - if (!*nt_name) - continue; - - if (!*unixname) - continue; - - DEBUG(5,("unixname = %s, ntname = %s.\n", - unixname, nt_name)); - - p = strchr(nt_name, '\\'); - - if (p == NULL) - { - memset(nt_domain, 0, sizeof(nt_domain)); - fstrcpy(nt_group, nt_name); - } - else - { - *p = 0; - p++; - fstrcpy(nt_domain, nt_name); - fstrcpy(nt_group , p); - } - - if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type)) - { - ubi_slAddHead(map_list, (ubi_slNode *)new_ep); - } - } - - DEBUG(10,("load_name_map: Added %ld entries to name map.\n", - ubi_slCount(map_list))); - - fclose(fp); -} - -/*********************************************************** - Lookup a gid_t by SID -************************************************************/ -static BOOL map_sid_to_gid(GROUP_TYPE type, ubi_slList *map_list, - DOM_SID *psid, gid_t *gid) -{ - name_map_entry *gmep; - - /* - * Initialize and load if not already loaded. - */ - load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - if (sid_equal(&gmep->grp.sid, psid)) - { - *gid = gmep->grp.unix_gid; - DEBUG(7,("map_sid_to_gid: Mapping unix group %s to nt group %s.\n", - gmep->grp.unix_name, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/*********************************************************** - Lookup a SID entry by nt name. -************************************************************/ -static BOOL map_sid_to_ntname(GROUP_TYPE type, ubi_slList *map_list, - DOM_SID *psid, char *ntname, char *ntdomain) -{ - name_map_entry *gmep; - - /* - * Initialize and load if not already loaded. - */ - load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(&map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - if (sid_equal(&gmep->grp.sid, psid)) - { - if (ntname != NULL) - { - fstrcpy(ntname, gmep->grp.nt_name); - } - if (ntdomain != NULL) - { - fstrcpy(ntname, gmep->grp.nt_domain); - } - DEBUG(7,("map_sid_to_ntname: Mapping unix group %s to nt group \\%s\\%s\n", - gmep->grp.unix_name, - gmep->grp.nt_domain, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/*********************************************************** - Lookup a SID entry by nt name. -************************************************************/ -static BOOL map_ntname_to_sid(GROUP_TYPE type, ubi_slList *map_list, - char * ntname, DOM_SID *psid) -{ - name_map_entry *gmep; - - /* - * Initialize and load if not already loaded. - */ - load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(&map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - if (strequal(gmep->grp.nt_name, ntname)) - { - *psid = gmep->grp.sid; - DEBUG(7,("map_ntname_to_sid: Mapping unix group %s to nt group %s.\n", - gmep->grp.unix_name, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/*********************************************************** - Lookup a SID entry by gid_t. -************************************************************/ -static BOOL map_gid_to_sid(GROUP_TYPE type, ubi_slList *map_list, - gid_t gid, DOM_SID *psid) -{ - name_map_entry *gmep; - - /* - * Initialize and load if not already loaded. - */ - load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(&map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - if (gmep->grp.unix_gid == gid) - { - *psid = gmep->grp.sid; - DEBUG(7,("map_gid_to_sid: Mapping unix group %s to nt group %s.\n", - gmep->grp.unix_name, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/* - * Call these four functions to resolve unix group ids and either - * local group SIDs or domain group SIDs listed in the local group - * or domain group map files. - * - * Note that it is *NOT* the responsibility of these functions to - * resolve entries that are not in the map files. - * - * Any SID can be in the map files (i.e from any Domain). - */ - -/*********************************************************** - Lookup a Group entry by sid. -************************************************************/ -BOOL map_group_sid_to_name(DOM_SID *psid, char *group_name, char *nt_domain) -{ - return map_sid_to_ntname(GROUP_DOMAIN, &groupname_map_list, psid, group_name, nt_domain); -} - -/*********************************************************** - Lookup an Alias SID entry by name. -************************************************************/ -BOOL map_alias_sid_to_name(DOM_SID *psid, char *alias_name, char *nt_domain) -{ - return map_sid_to_ntname(GROUP_LOCAL, &aliasname_map_list, psid, alias_name, nt_domain); -} - -/*********************************************************** - Lookup a Group SID entry by name. -************************************************************/ -BOOL map_group_name_to_sid(char *group_name, DOM_SID *psid) -{ - return map_ntname_to_sid(GROUP_DOMAIN, &groupname_map_list, group_name, psid); -} - -/*********************************************************** - Lookup an Alias SID entry by name. -************************************************************/ -BOOL map_alias_name_to_sid(char *alias_name, DOM_SID *psid) -{ - return map_ntname_to_sid(GROUP_LOCAL, &aliasname_map_list, alias_name, psid); -} - -/*********************************************************** - Lookup an Alias SID entry by gid_t. -************************************************************/ -BOOL map_gid_to_alias_sid(gid_t gid, DOM_SID *psid) -{ - return map_gid_to_sid(GROUP_LOCAL, &aliasname_map_list, gid, psid); -} - -/*********************************************************** - Lookup a Group SID entry by gid_t. -************************************************************/ -BOOL map_gid_to_group_sid( gid_t gid, DOM_SID *psid) -{ - return map_gid_to_sid(GROUP_DOMAIN, &groupname_map_list, gid, psid); -} - -/*********************************************************** - Lookup a Group gid_t by SID -************************************************************/ -BOOL map_group_sid_to_gid( DOM_SID *psid, gid_t *gid) -{ - return map_sid_to_gid(GROUP_DOMAIN, &groupname_map_list, psid, gid); -} - -/*********************************************************** - Lookup an Alias gid_t by SID -************************************************************/ -BOOL map_alias_sid_to_gid( DOM_SID *psid, gid_t *gid) -{ - return map_sid_to_gid(GROUP_LOCAL, &aliasname_map_list, psid, gid); -} - diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8aacfa3867..60620c9854 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -615,8 +615,8 @@ int reply_ntcreate_and_X(connection_struct *conn, /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(conn) && lp_nt_pipe_support()) { - + if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE) + { int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) return ret; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 49816e5d47..e064b52dfa 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -652,26 +652,8 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); fstrcpy(global_myworkgroup, lp_workgroup()); - memset(global_sam_name, 0, sizeof(global_sam_name)); - if (lp_domain_logons()) - { - if (lp_security() == SEC_USER) - { - /* we are PDC (or BDC) for a Domain */ - fstrcpy(global_sam_name, lp_workgroup()); - } - else if (lp_security() == SEC_DOMAIN) - { - /* we are a "PDC", but FOR LOCAL SAM DATABASE ONLY */ - fstrcpy(global_sam_name, global_myname); - } - else if (lp_security() == SEC_SHARE) - { - DEBUG(0,("ERROR: no Domain functionality in security = share\n")); - exit(1); - } - } + get_sam_domain_name(); generate_wellknown_sids(); -- cgit From a5cbb4ab27c0167730de45993a77f7fa2727bdb6 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 23 Nov 1998 21:54:19 +0000 Subject: remove / add / attempt to stop remove didn't work. (This used to be commit 82b6292dff38f4e22ee8feab1b54504b95d705fa) --- source3/smbd/groupname.c | 651 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 651 insertions(+) create mode 100644 source3/smbd/groupname.c (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c new file mode 100644 index 0000000000..3c09c11830 --- /dev/null +++ b/source3/smbd/groupname.c @@ -0,0 +1,651 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Groupname handling + Copyright (C) Jeremy Allison 1998. + + 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. +*/ + +/* + * UNIX gid and Local or Domain SID resolution. This module resolves + * only those entries in the map files, it is *NOT* responsible for + * resolving UNIX groups not listed: that is an entirely different + * matter, altogether... + */ + +/* + * + * + + format of the file is: + + unixname NT Group name + unixname Domain Admins (well-known Domain Group) + unixname DOMAIN_NAME\NT Group name + unixname OTHER_DOMAIN_NAME\NT Group name + unixname DOMAIN_NAME\Domain Admins (well-known Domain Group) + .... + + if the DOMAIN_NAME\ component is left off, then your own domain is assumed. + + * + * + */ + + +#include "includes.h" +extern int DEBUGLEVEL; + +extern fstring global_sam_name; + +/* we can map either local aliases or domain groups */ +typedef enum +{ + GROUP_LOCAL, + GROUP_DOMAIN + +} GROUP_TYPE; + +/************************************************************************** + Groupname map functionality. The code loads a groupname map file and + (currently) loads it into a linked list. This is slow and memory + hungry, but can be changed into a more efficient storage format + if the demands on it become excessive. +***************************************************************************/ + +typedef struct group_name_info +{ + char *nt_name; + char *nt_domain; + char *unix_name; + + DOM_SID sid; + gid_t unix_gid; + +} GROUP_NAME_INFO; + +typedef struct name_map +{ + ubi_slNode next; + GROUP_NAME_INFO grp; + +} name_map_entry; + +static ubi_slList groupname_map_list; +static ubi_slList aliasname_map_list; + +static void delete_name_entry(name_map_entry *gmep) +{ + if (gmep->grp.nt_name) + { + free(gmep->grp.nt_name); + } + if (gmep->grp.nt_domain) + { + free(gmep->grp.nt_domain); + } + if (gmep->grp.unix_name) + { + free(gmep->grp.unix_name); + } + free((char*)gmep); +} + +/************************************************************************** + Delete all the entries in the name map list. +***************************************************************************/ + +static void delete_map_list(ubi_slList *map_list) +{ + name_map_entry *gmep; + + while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL) + { + delete_name_entry(gmep); + } +} + + +/************************************************************************** + makes a group sid out of a domain sid and a _unix_ gid. +***************************************************************************/ +static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type) +{ + uint32 tmp_rid; + DOM_SID sid; + uint8 tmp_type; + + DEBUG(10,("make_mydomain_sid\n")); + + if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) + { + DEBUG(0,("make_mydomain_sid: unknown domain %s\n", + grp->nt_domain)); + return False; + } + + if (strequal(grp->nt_domain, global_sam_name) && + lookup_wk_group_name(grp->nt_name, &sid, &tmp_type)) + { + sid_copy(&grp->sid, &sid); + return True; + } + else + { + if (type == GROUP_DOMAIN) + { + tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid); + } + else + { + tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid); + } + return sid_append_rid(&(grp->sid), tmp_rid); + } +} + +/************************************************************************** + makes a group sid out of an nt domain, nt group name or a unix group name. +***************************************************************************/ +static BOOL unix_name_to_group_info(GROUP_NAME_INFO *grp, GROUP_TYPE type) +{ + struct group *gptr = NULL; + + /* + * Attempt to get the unix gid_t for this name. + */ + + DEBUG(5,("unix_name_to_group_info: unix_name:%s\n", grp->unix_name)); + + gptr = (struct group *)getgrnam(grp->unix_name); + if (gptr == NULL) + { + DEBUG(0,("unix_name_to_group_info: getgrnam for group %s\ +failed. Error was %s.\n", grp->unix_name, strerror(errno) )); + return False; + } + + grp->unix_gid = (gid_t)gptr->gr_gid; + + DEBUG(5,("unix_name_to_group_info: unix gid:%d\n", grp->unix_gid)); + + /* + * Now map the name to an NT SID+RID. + */ + + if (grp->nt_domain != NULL && !strequal(grp->nt_domain, global_sam_name)) + { + /* Must add client-call lookup code here, to + * resolve remote domain's sid and the group's rid, + * in that domain. + * + * NOTE: it is _incorrect_ to put code here that assumes + * that we can call pwdb_gid_to_group_rid() or _alias_rid(): + * it is a totally different domain for which we are *NOT* + * responsible. + * for foriegn domains for which we are *NOT* the PDC, all + * we can be responsible for is the unix * gid_t to which + * the foriegn SID+rid maps to, on this _local_ machine. + */ + + if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) + { + DEBUG(0,("unix_name_to_group_info: no known sid for %s\n", + grp->nt_domain)); + return False; + } + + DEBUG(0,("unix_name_to_group_info: cannot resolve domain %s\n", + grp->nt_domain)); + + return False; + } + else + { + return make_mydomain_sid(grp, type); + } +} + +static BOOL make_name_entry(name_map_entry **new_ep, + char *nt_domain, char *nt_group, char *unix_group, + GROUP_TYPE type) +{ + /* + * Create the list entry and add it onto the list. + */ + + DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group)); + + (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry)); + if ((*new_ep) == NULL) + { + DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n")); + return False; + } + + ZERO_STRUCTP(*new_ep); + + (*new_ep)->grp.nt_name = strdup(nt_group ); + (*new_ep)->grp.nt_domain = strdup(nt_domain ); + (*new_ep)->grp.unix_name = strdup(unix_group); + + if ((*new_ep)->grp.nt_name == NULL || + (*new_ep)->grp.unix_name == NULL) + { + DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n")); + delete_name_entry((*new_ep)); + return False; + } + + /* + * look up the group names, make the Group-SID and unix gid + */ + + if (!unix_name_to_group_info(&(*new_ep)->grp, type)) + { + delete_name_entry((*new_ep)); + return False; + } + + return True; +} + +/************************************************************************** + Load a name map file. Sets last accessed timestamp. +***************************************************************************/ +static void load_name_map(GROUP_TYPE type) +{ + static time_t groupmap_file_last_modified = (time_t)0; + static time_t aliasmap_file_last_modified = (time_t)0; + static BOOL initialised_group = False; + static BOOL initialised_alias = False; + char *groupname_map_file = lp_groupname_map(); + char *aliasname_map_file = lp_aliasname_map(); + + SMB_STRUCT_STAT st; + FILE *fp; + char *s; + pstring buf; + name_map_entry *new_ep; + + time_t *file_last_modified; + int *initialised; + char *map_file; + ubi_slList *map_list; + + if (type == GROUP_DOMAIN) + { + file_last_modified = &groupmap_file_last_modified; + initialised = &initialised_group; + map_file = groupname_map_file; + map_list = &groupname_map_list; + } + else + { + file_last_modified = &aliasmap_file_last_modified; + initialised = &initialised_alias; + map_file = aliasname_map_file; + map_list = &aliasname_map_list; + } + + DEBUG(10,("load_name_map : %s\n", map_file)); + + if (!(*initialised)) + { + ubi_slInitList(map_list); + (*initialised) = True; + } + + if (!*map_file) + { + return; + } + + if (sys_stat(map_file, &st) != 0) + { + DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n", + map_file, strerror(errno) )); + return; + } + + /* + * Check if file has changed. + */ + if (st.st_mtime <= (*file_last_modified)) + { + return; + } + + (*file_last_modified) = st.st_mtime; + + /* + * Load the file. + */ + + fp = fopen(map_file,"r"); + if (!fp) + { + DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n", + map_file, strerror(errno))); + return; + } + + /* + * Throw away any previous list. + */ + delete_map_list(map_list); + + DEBUG(4,("load_name_map: Scanning name map %s\n",map_file)); + + while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL) + { + pstring unixname; + pstring nt_name; + fstring nt_domain; + fstring nt_group; + char *p; + + DEBUG(10,("Read line |%s|\n", s)); + + memset(nt_name, 0, sizeof(nt_name)); + + if (!*s || strchr("#;",*s)) + continue; + + if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) + continue; + + if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name))) + continue; + + trim_string(unixname, " ", " "); + trim_string(nt_name, " ", " "); + + if (!*nt_name) + continue; + + if (!*unixname) + continue; + + DEBUG(5,("unixname = %s, ntname = %s.\n", + unixname, nt_name)); + + p = strchr(nt_name, '\\'); + + if (p == NULL) + { + memset(nt_domain, 0, sizeof(nt_domain)); + fstrcpy(nt_group, nt_name); + } + else + { + *p = 0; + p++; + fstrcpy(nt_domain, nt_name); + fstrcpy(nt_group , p); + } + + if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type)) + { + ubi_slAddHead(map_list, (ubi_slNode *)new_ep); + } + } + + DEBUG(10,("load_name_map: Added %ld entries to name map.\n", + ubi_slCount(map_list))); + + fclose(fp); +} + +/*********************************************************** + Lookup by SID +************************************************************/ +static BOOL map_sid(GROUP_TYPE type, ubi_slList *map_list, + DOM_SID *psid, gid_t *gid, char *ntname, char *ntdomain) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (sid_equal(&gmep->grp.sid, psid)) + { + if (gid != NULL) + { + *gid = gmep->grp.unix_gid; + } + if (ntname != NULL) + { + fstrcpy(ntname, gmep->grp.nt_name); + } + if (ntdomain != NULL) + { + fstrcpy(ntdomain, gmep->grp.nt_domain); + } + DEBUG(7,("map_sid: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + Lookup nt name. +************************************************************/ +static BOOL map_ntname(GROUP_TYPE type, ubi_slList *map_list, + char *ntname, char *ntdomain, DOM_SID *psid, + char *unixname, gid_t *gid) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (strequal(gmep->grp.nt_name , ntname) && + strequal(gmep->grp.nt_domain, ntdomain)) + { + if (psid != NULL) + { + *psid = gmep->grp.sid; + } + if (gid != NULL) + { + *gid = gmep->grp.unix_gid; + } + if (unixname != NULL) + { + fstrcpy(unixname, gmep->grp.unix_name); + } + DEBUG(7,("map_ntname: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + Lookup unix name. +************************************************************/ +static BOOL map_unixname(GROUP_TYPE type, ubi_slList *map_list, + char *unixname, DOM_SID *psid, char *ntname, char *ntdomain) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (strequal(gmep->grp.unix_name, unixname)) + { + if (psid != NULL) + { + *psid = gmep->grp.sid; + } + if (ntname != NULL) + { + fstrcpy(ntname, gmep->grp.nt_name); + } + if (ntdomain != NULL) + { + fstrcpy(ntdomain, gmep->grp.nt_domain); + } + DEBUG(7,("map_unixname: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + Lookup by gid_t. +************************************************************/ +static BOOL map_gid(GROUP_TYPE type, ubi_slList *map_list, + gid_t gid, DOM_SID *psid, char *ntname, char *ntdomain) +{ + name_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_name_map(type); + + for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + gmep != NULL; + gmep = (name_map_entry *)ubi_slNext(gmep )) + { + if (gmep->grp.unix_gid == gid) + { + if (psid != NULL) + { + *psid = gmep->grp.sid; + } + if (ntname != NULL) + { + fstrcpy(ntname, gmep->grp.nt_name); + } + if (ntdomain != NULL) + { + fstrcpy(ntdomain, gmep->grp.nt_domain); + } + DEBUG(7,("map_gid: Mapping unix group %s to nt group %s.\n", + gmep->grp.unix_name, gmep->grp.nt_name )); + return True; + } + } + + return False; +} + +/*********************************************************** + * + * Call four functions to resolve unix group ids and either + * local group SIDs or domain group SIDs listed in the local group + * or domain group map files. + * + * Note that it is *NOT* the responsibility of these functions to + * resolve entries that are not in the map files. + * + * Any SID can be in the map files (i.e from any Domain). + * + ***********************************************************/ + +/*********************************************************** + Lookup a Group entry by sid. +************************************************************/ +BOOL map_group_sid(DOM_SID *psid, gid_t *gid, char *group_name, char *nt_domain) +{ + return map_sid(GROUP_DOMAIN, &groupname_map_list, psid, gid, group_name, nt_domain); +} + +/*********************************************************** + Lookup an Alias SID entry by name. +************************************************************/ +BOOL map_alias_sid(DOM_SID *psid, gid_t *gid, char *alias_name, char *nt_domain) +{ + return map_sid(GROUP_LOCAL, &aliasname_map_list, psid, gid, alias_name, nt_domain); +} + +/*********************************************************** + Lookup a UNIX Group entry by name. +************************************************************/ +BOOL map_unix_group_name(char *group_name, DOM_SID *psid, char *ntgroup_name, char *nt_domain) +{ + return map_unixname(GROUP_DOMAIN, &groupname_map_list, group_name, psid, ntgroup_name, nt_domain); +} + +/*********************************************************** + Lookup a UNIX Alias entry by name. +************************************************************/ +BOOL map_unix_alias_name(char *alias_name, DOM_SID *psid, char *ntalias_name, char *nt_domain) +{ + return map_unixname(GROUP_LOCAL, &aliasname_map_list, alias_name, psid, ntalias_name, nt_domain); +} + +/*********************************************************** + Lookup a Group entry +************************************************************/ +BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_SID *psid, char *group_name, gid_t *gid) +{ + return map_ntname(GROUP_DOMAIN, &groupname_map_list, ntgroup_name, nt_domain, psid, group_name, gid); +} + +/*********************************************************** + Lookup an Alias name entry +************************************************************/ +BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_SID *psid, char *alias_name, gid_t *gid) +{ + return map_ntname(GROUP_LOCAL, &aliasname_map_list, ntalias_name, nt_domain, psid, alias_name, gid); +} + +/*********************************************************** + Lookup an Alias SID entry by gid_t. +************************************************************/ +BOOL map_alias_gid(gid_t gid, DOM_SID *psid, char *nt_als_name, char *nt_domain) +{ + return map_gid(GROUP_LOCAL, &aliasname_map_list, gid, psid, nt_als_name, nt_domain); +} + +/*********************************************************** + Lookup a Group SID entry by gid_t. +************************************************************/ +BOOL map_group_gid( gid_t gid, DOM_SID *psid, char *nt_grp_name, char *nt_domain) +{ + return map_gid(GROUP_DOMAIN, &groupname_map_list, gid, psid, nt_grp_name, nt_domain); +} + -- cgit From a4cfbedf1ef5899629b4b8fc12ecf7897d089785 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Nov 1998 23:55:33 +0000 Subject: Fixed -Wall -Wshadow warning. Jeremy. (This used to be commit 81b90208910528a4ace683f30e39c54d8cfa12b7) --- source3/smbd/trans2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d71c23c87b..7bfb046cc2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1658,9 +1658,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { - if (tran_call == TRANSACT2_SETFILEINFO) + if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL)) { - files_struct *fsp = file_fsp(params,0); BOOL delete_on_close = (CVAL(pdata,0) ? True : False); if(fsp->is_directory) -- cgit From 51b85654e3c3b4a451ce39688769c1a5e7d75dc2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Nov 1998 00:40:27 +0000 Subject: Fixed oplock test path spec bug. Jeremy. (This used to be commit 252dd8b8929adbdff9917395d4f8caad2d7882b2) --- source3/smbd/oplock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 96afb127aa..f61b025227 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1048,7 +1048,7 @@ void check_kernel_oplocks(void) set_process_capability(KERNEL_OPLOCK_CAPABILITY,True); set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,True); - slprintf(tmpname,sizeof(tmpname)-1, "%/koplock.%d", lp_lockdir(), (int)getpid()); + slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)getpid()); if(pipe(pfd) != 0) { DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", -- cgit From c9b2f20efcb9cd2e93f29928442e9a61360fa5a0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 25 Nov 1998 14:54:23 +0000 Subject: fixing domain join and domain login problems (This used to be commit 90a24664318da97a6e8cfe4622a8573c0e3cbe5e) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e064b52dfa..acde9eebf3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -663,7 +663,7 @@ static void usage(char *pname) exit(1); } - if (lp_security() == SEC_DOMAIN && !get_member_domain_sid()) + if (!get_member_domain_sid()) { DEBUG(0,("ERROR: Samba cannot obtain PDC SID from PDC(s) %s.\n", lp_passwordserver())); -- cgit From 59d4087160ba41aac724722dc29c4b6e4e3b69b0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 25 Nov 1998 19:57:04 +0000 Subject: LsaLookupNames client call (first used as lookupnames command in rpcclient). (This used to be commit 68342a29a892e515cf2b22d759476d61944bcd59) --- source3/smbd/groupname.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 3c09c11830..95992cc84b 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -207,16 +207,9 @@ failed. Error was %s.\n", grp->unix_name, strerror(errno) )); grp->nt_domain)); return False; } - - DEBUG(0,("unix_name_to_group_info: cannot resolve domain %s\n", - grp->nt_domain)); - - return False; - } - else - { - return make_mydomain_sid(grp, type); } + + return make_mydomain_sid(grp, type); } static BOOL make_name_entry(name_map_entry **new_ep, @@ -301,8 +294,6 @@ static void load_name_map(GROUP_TYPE type) map_list = &aliasname_map_list; } - DEBUG(10,("load_name_map : %s\n", map_file)); - if (!(*initialised)) { ubi_slInitList(map_list); -- cgit From bfc38ff872446e0ad365c22327c779e72a81bef9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Nov 1998 21:17:20 +0000 Subject: Makefile.in: Added maintainer mode fixes. aclocal.m4: Added AC_LIBTESTFUNC. configure.in: Fixed -lsecurity -lsec problems. client.c: dos_ fixes. groupdb/aliasunix.c: Dead code removal. include/includes.h: Added default PRINTCAP_NAME. lib/genrand.c: dos_ fixes. lib/replace.c: Added strtoul. lib/system.c: dos_ fixes. lib/util.c: dos_ fixes. lib/util_sid.c: Signed/unsigned fixes. lib/util_str.c: removed bad const. locking/locking_slow.c: dos_ fixes. printing/printing.c: dos_ fixes. rpc_server/srv_samr.c: Dead code removal. rpc_server/srv_sid.c: global_myworkgroup defined with wrong size AGAIN ! smbd/dir.c: dos_ fixes. smbd/open.c: dos_ fixes. smbd/oplock.c: dos_ fixes. smbd/reply.c smbd/server.c smbd/service.c smbd/uid.c: dos_ fixes. Jeremy. (This used to be commit 6acb4b68f68d516e2ac3c47e500f5600d653435e) --- source3/smbd/dir.c | 4 ++-- source3/smbd/open.c | 4 ++-- source3/smbd/oplock.c | 4 ++-- source3/smbd/reply.c | 28 ++++++++++++++-------------- source3/smbd/server.c | 2 +- source3/smbd/service.c | 10 +++++----- source3/smbd/uid.c | 10 +++++----- 7 files changed, 31 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index db2de23f6d..dcf1d158b4 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -518,7 +518,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - void *p = dos_opendir(name); + DIR *p = dos_opendir(name); int used=0; if (!p) return(NULL); @@ -530,7 +530,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; - while ((n = readdirname(p))) + while ((n = dos_readdirname(p))) { int l = strlen(n)+1; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d7cef6d63b..dd1ece7fe1 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -550,7 +550,7 @@ static void mmap_open_file(files_struct *fsp) #if WITH_MMAP /* mmap it if read-only */ if (!fsp->can_write) { - fsp->mmap_size = file_size(fsp->fsp_name); + fsp->mmap_size = dos_file_size(fsp->fsp_name); if (fsp->mmap_size < MAX_MMAP_SIZE) { fsp->mmap_ptr = (char *)sys_mmap(NULL,fsp->mmap_size, PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,(SMB_OFF_T)0); @@ -727,7 +727,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); SMB_STRUCT_STAT sbuf; - BOOL file_existed = file_exist(fname,&sbuf); + BOOL file_existed = dos_file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; int token; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index f61b025227..bc2d46bb95 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -665,7 +665,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) */ saved_conn = fsp->conn; saved_vuid = current_user.vuid; - GetWd(saved_dir); + dos_GetWd(saved_dir); unbecome_user(); /* Save the chain fnum. */ file_chain_save(); @@ -749,7 +749,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) exit_server("unable to re-become user"); } /* Including the directory. */ - ChDir(saved_dir); + dos_ChDir(saved_dir); /* Restore the chain fnum. */ file_chain_restore(); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 12bf098a94..1abb084124 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -809,7 +809,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if(VALID_STAT(st)) ok = S_ISDIR(st.st_mode); else - ok = directory_exist(name,NULL); + ok = dos_directory_exist(name,NULL); } if (!ok) @@ -944,7 +944,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL)) + if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL)) mode |= aDIR; if (check_name(fname,conn)) ok = (file_chmod(conn,fname,mode,NULL) == 0); @@ -1757,7 +1757,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++; if (!count) - exists = file_exist(directory,NULL); + exists = dos_file_exist(directory,NULL); } else { void *dirptr = NULL; char *dname; @@ -3274,7 +3274,7 @@ int rename_internals(connection_struct *conn, /* * NT SMB specific flag - rename can overwrite * file with the same name so don't check for - * file_exist(). + * dos_file_exist(). */ if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && @@ -3283,7 +3283,7 @@ int rename_internals(connection_struct *conn, } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !file_exist(newname,NULL) && + !dos_file_exist(newname,NULL) && !dos_rename(directory,newname)) count++; } @@ -3291,8 +3291,8 @@ int rename_internals(connection_struct *conn, DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); - if (!count) exists = file_exist(directory,NULL); - if (!count && exists && file_exist(newname,NULL)) { + if (!count) exists = dos_file_exist(directory,NULL); + if (!count && exists && dos_file_exist(newname,NULL)) { exists = True; error = ERRrename; } @@ -3333,8 +3333,8 @@ int rename_internals(connection_struct *conn, continue; } - if (!replace_if_exists && file_exist(destname,NULL)) { - DEBUG(6,("file_exist %s\n", destname)); + if (!replace_if_exists && dos_file_exist(destname,NULL)) { + DEBUG(6,("dos_file_exist %s\n", destname)); error = 183; continue; } @@ -3408,7 +3408,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!file_exist(src,&st)) + if (!dos_file_exist(src,&st)) return(False); fsp1 = file_new(); @@ -3501,7 +3501,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(name,conn,0,&bad_path1,NULL); unix_convert(newname,conn,0,&bad_path2,NULL); - target_is_directory = directory_exist(newname,NULL); + target_is_directory = dos_directory_exist(newname,NULL); if ((flags&1) && target_is_directory) { return(ERROR(ERRDOS,ERRbadfile)); @@ -3511,7 +3511,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRDOS,ERRbadpath)); } - if ((flags&(1<<5)) && directory_exist(name,NULL)) { + if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); return(ERROR(ERRSRV,ERRerror)); @@ -3538,7 +3538,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (resolve_wildcards(directory,newname) && copy_file(directory,newname,conn,ofun, count,target_is_directory)) count++; - if (!count) exists = file_exist(directory,NULL); + if (!count) exists = dos_file_exist(directory,NULL); } else { void *dirptr = NULL; char *dname; @@ -3613,7 +3613,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (strlen(newdir) == 0) { ok = True; } else { - ok = directory_exist(newdir,NULL); + ok = dos_directory_exist(newdir,NULL); if (ok) { string_set(&conn->connectpath,newdir); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index acde9eebf3..d0178508d9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -553,7 +553,7 @@ static void usage(char *pname) so set our umask to 0 */ umask(0); - GetWd(OriginalDir); + dos_GetWd(OriginalDir); init_uid(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index cedac1c76f..b4a1115867 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -54,8 +54,8 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir) snum = SNUM(conn); if (do_chdir && - ChDir(conn->connectpath) != 0 && - ChDir(conn->origpath) != 0) { + dos_ChDir(conn->connectpath) != 0 && + dos_ChDir(conn->origpath) != 0) { DEBUG(0,("chdir (%s) failed\n", conn->connectpath)); return(False); @@ -430,7 +430,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } - if (ChDir(conn->connectpath) != 0) { + if (dos_ChDir(conn->connectpath) != 0) { DEBUG(0,("Can't change directory to %s (%s)\n", conn->connectpath,strerror(errno))); unbecome_user(); @@ -453,9 +453,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int { pstring s; pstrcpy(s,conn->connectpath); - GetWd(s); + dos_GetWd(s); string_set(&conn->connectpath,s); - ChDir(conn->connectpath); + dos_ChDir(conn->connectpath); } #endif diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 7c951b461a..f76fa49d56 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -54,7 +54,7 @@ void init_uid(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; - ChDir(OriginalDir); + dos_ChDir(OriginalDir); } @@ -303,7 +303,7 @@ BOOL unbecome_user(void ) if (!current_user.conn) return(False); - ChDir(OriginalDir); + dos_ChDir(OriginalDir); if (initial_uid == 0) { @@ -336,7 +336,7 @@ BOOL unbecome_user(void ) current_user.uid = initial_uid; current_user.gid = initial_gid; - if (ChDir(OriginalDir) != 0) + if (dos_ChDir(OriginalDir) != 0) DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", @@ -366,7 +366,7 @@ void become_root(BOOL save_dir) DEBUG(0,("ERROR: become root depth is non zero\n")); } if (save_dir) - GetWd(become_root_dir); + dos_GetWd(become_root_dir); current_user_saved = current_user; become_root_depth = 1; @@ -415,7 +415,7 @@ void unbecome_root(BOOL restore_dir) } if (restore_dir) - ChDir(become_root_dir); + dos_ChDir(become_root_dir); current_user = current_user_saved; -- cgit From 9a0cb06b240f3d772b53a6acc4804ccd9cbc4072 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 25 Nov 1998 23:11:25 +0000 Subject: fixing group database issues (This used to be commit 591c63e3e1e3201ddcd7582585b652fb848d80ca) --- source3/smbd/groupname.c | 87 +++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 95992cc84b..a81114169c 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -138,13 +138,15 @@ static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type) } if (strequal(grp->nt_domain, global_sam_name) && - lookup_wk_group_name(grp->nt_name, &sid, &tmp_type)) + lookup_builtin_grp_name(grp->nt_name, &sid, &tmp_type) == 0x0) { sid_copy(&grp->sid, &sid); return True; } else { + BOOL ret; + fstring sid_str; if (type == GROUP_DOMAIN) { tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid); @@ -153,7 +155,11 @@ static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type) { tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid); } - return sid_append_rid(&(grp->sid), tmp_rid); + ret = sid_append_rid(&(grp->sid), tmp_rid); + sid_to_string(sid_str, &grp->sid); + DEBUG(10,("nt name %s gid %d mapped to %s\n", + grp->nt_name, grp->unix_gid, sid_str)); + return ret; } } @@ -259,7 +265,7 @@ static BOOL make_name_entry(name_map_entry **new_ep, /************************************************************************** Load a name map file. Sets last accessed timestamp. ***************************************************************************/ -static void load_name_map(GROUP_TYPE type) +static ubi_slList *load_name_map(GROUP_TYPE type) { static time_t groupmap_file_last_modified = (time_t)0; static time_t aliasmap_file_last_modified = (time_t)0; @@ -296,20 +302,21 @@ static void load_name_map(GROUP_TYPE type) if (!(*initialised)) { + DEBUG(10,("initialising group map %s\n", map_file)); ubi_slInitList(map_list); (*initialised) = True; } if (!*map_file) { - return; + return map_list; } if (sys_stat(map_file, &st) != 0) { DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n", map_file, strerror(errno) )); - return; + return map_list; } /* @@ -317,7 +324,7 @@ static void load_name_map(GROUP_TYPE type) */ if (st.st_mtime <= (*file_last_modified)) { - return; + return map_list; } (*file_last_modified) = st.st_mtime; @@ -331,7 +338,7 @@ static void load_name_map(GROUP_TYPE type) { DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n", map_file, strerror(errno))); - return; + return map_list; } /* @@ -391,28 +398,31 @@ static void load_name_map(GROUP_TYPE type) if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type)) { - ubi_slAddHead(map_list, (ubi_slNode *)new_ep); + ubi_slAddTail(map_list, (ubi_slNode *)new_ep); } } DEBUG(10,("load_name_map: Added %ld entries to name map.\n", - ubi_slCount(map_list))); + ubi_slCount(map_list))); fclose(fp); + + return map_list; } /*********************************************************** Lookup by SID ************************************************************/ -static BOOL map_sid(GROUP_TYPE type, ubi_slList *map_list, +static BOOL map_sid(GROUP_TYPE type, DOM_SID *psid, gid_t *gid, char *ntname, char *ntdomain) { name_map_entry *gmep; + ubi_slList *map_list; /* - * Initialize and load if not already loaded. + * Initialise and load if not already loaded. */ - load_name_map(type); + map_list = load_name_map(type); for (gmep = (name_map_entry *)ubi_slFirst(map_list); gmep != NULL; @@ -444,18 +454,19 @@ static BOOL map_sid(GROUP_TYPE type, ubi_slList *map_list, /*********************************************************** Lookup nt name. ************************************************************/ -static BOOL map_ntname(GROUP_TYPE type, ubi_slList *map_list, +static BOOL map_ntname(GROUP_TYPE type, char *ntname, char *ntdomain, DOM_SID *psid, char *unixname, gid_t *gid) { name_map_entry *gmep; + ubi_slList *map_list; /* - * Initialize and load if not already loaded. + * Initialise and load if not already loaded. */ - load_name_map(type); + map_list = load_name_map(type); - for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + for (gmep = (name_map_entry *)ubi_slFirst(map_list); gmep != NULL; gmep = (name_map_entry *)ubi_slNext(gmep )) { @@ -464,7 +475,7 @@ static BOOL map_ntname(GROUP_TYPE type, ubi_slList *map_list, { if (psid != NULL) { - *psid = gmep->grp.sid; + sid_copy(psid, &gmep->grp.sid); } if (gid != NULL) { @@ -486,17 +497,18 @@ static BOOL map_ntname(GROUP_TYPE type, ubi_slList *map_list, /*********************************************************** Lookup unix name. ************************************************************/ -static BOOL map_unixname(GROUP_TYPE type, ubi_slList *map_list, +static BOOL map_unixname(GROUP_TYPE type, char *unixname, DOM_SID *psid, char *ntname, char *ntdomain) { name_map_entry *gmep; + ubi_slList *map_list; /* - * Initialize and load if not already loaded. + * Initialise and load if not already loaded. */ - load_name_map(type); + map_list = load_name_map(type); - for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + for (gmep = (name_map_entry *)ubi_slFirst(map_list); gmep != NULL; gmep = (name_map_entry *)ubi_slNext(gmep )) { @@ -504,7 +516,7 @@ static BOOL map_unixname(GROUP_TYPE type, ubi_slList *map_list, { if (psid != NULL) { - *psid = gmep->grp.sid; + sid_copy(psid, &gmep->grp.sid); } if (ntname != NULL) { @@ -526,25 +538,30 @@ static BOOL map_unixname(GROUP_TYPE type, ubi_slList *map_list, /*********************************************************** Lookup by gid_t. ************************************************************/ -static BOOL map_gid(GROUP_TYPE type, ubi_slList *map_list, +static BOOL map_gid(GROUP_TYPE type, gid_t gid, DOM_SID *psid, char *ntname, char *ntdomain) { name_map_entry *gmep; + ubi_slList *map_list; /* - * Initialize and load if not already loaded. + * Initialise and load if not already loaded. */ - load_name_map(type); + map_list = load_name_map(type); - for (gmep = (name_map_entry *)ubi_slFirst(&map_list); + for (gmep = (name_map_entry *)ubi_slFirst(map_list); gmep != NULL; gmep = (name_map_entry *)ubi_slNext(gmep )) { + fstring sid_str; + sid_to_string(sid_str, &gmep->grp.sid); + DEBUG(10,("map_gid: enum entry unix group %s %d nt %s %s\n", + gmep->grp.unix_name, gmep->grp.unix_gid, gmep->grp.nt_name, sid_str)); if (gmep->grp.unix_gid == gid) { if (psid != NULL) { - *psid = gmep->grp.sid; + sid_copy(psid, &gmep->grp.sid); } if (ntname != NULL) { @@ -581,7 +598,7 @@ static BOOL map_gid(GROUP_TYPE type, ubi_slList *map_list, ************************************************************/ BOOL map_group_sid(DOM_SID *psid, gid_t *gid, char *group_name, char *nt_domain) { - return map_sid(GROUP_DOMAIN, &groupname_map_list, psid, gid, group_name, nt_domain); + return map_sid(GROUP_DOMAIN, psid, gid, group_name, nt_domain); } /*********************************************************** @@ -589,7 +606,7 @@ BOOL map_group_sid(DOM_SID *psid, gid_t *gid, char *group_name, char *nt_domain) ************************************************************/ BOOL map_alias_sid(DOM_SID *psid, gid_t *gid, char *alias_name, char *nt_domain) { - return map_sid(GROUP_LOCAL, &aliasname_map_list, psid, gid, alias_name, nt_domain); + return map_sid(GROUP_LOCAL, psid, gid, alias_name, nt_domain); } /*********************************************************** @@ -597,7 +614,7 @@ BOOL map_alias_sid(DOM_SID *psid, gid_t *gid, char *alias_name, char *nt_domain) ************************************************************/ BOOL map_unix_group_name(char *group_name, DOM_SID *psid, char *ntgroup_name, char *nt_domain) { - return map_unixname(GROUP_DOMAIN, &groupname_map_list, group_name, psid, ntgroup_name, nt_domain); + return map_unixname(GROUP_DOMAIN, group_name, psid, ntgroup_name, nt_domain); } /*********************************************************** @@ -605,7 +622,7 @@ BOOL map_unix_group_name(char *group_name, DOM_SID *psid, char *ntgroup_name, ch ************************************************************/ BOOL map_unix_alias_name(char *alias_name, DOM_SID *psid, char *ntalias_name, char *nt_domain) { - return map_unixname(GROUP_LOCAL, &aliasname_map_list, alias_name, psid, ntalias_name, nt_domain); + return map_unixname(GROUP_LOCAL, alias_name, psid, ntalias_name, nt_domain); } /*********************************************************** @@ -613,7 +630,7 @@ BOOL map_unix_alias_name(char *alias_name, DOM_SID *psid, char *ntalias_name, ch ************************************************************/ BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_SID *psid, char *group_name, gid_t *gid) { - return map_ntname(GROUP_DOMAIN, &groupname_map_list, ntgroup_name, nt_domain, psid, group_name, gid); + return map_ntname(GROUP_DOMAIN, ntgroup_name, nt_domain, psid, group_name, gid); } /*********************************************************** @@ -621,7 +638,7 @@ BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_SID *psid, char ************************************************************/ BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_SID *psid, char *alias_name, gid_t *gid) { - return map_ntname(GROUP_LOCAL, &aliasname_map_list, ntalias_name, nt_domain, psid, alias_name, gid); + return map_ntname(GROUP_LOCAL, ntalias_name, nt_domain, psid, alias_name, gid); } /*********************************************************** @@ -629,7 +646,7 @@ BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_SID *psid, char ************************************************************/ BOOL map_alias_gid(gid_t gid, DOM_SID *psid, char *nt_als_name, char *nt_domain) { - return map_gid(GROUP_LOCAL, &aliasname_map_list, gid, psid, nt_als_name, nt_domain); + return map_gid(GROUP_LOCAL, gid, psid, nt_als_name, nt_domain); } /*********************************************************** @@ -637,6 +654,6 @@ BOOL map_alias_gid(gid_t gid, DOM_SID *psid, char *nt_als_name, char *nt_domain) ************************************************************/ BOOL map_group_gid( gid_t gid, DOM_SID *psid, char *nt_grp_name, char *nt_domain) { - return map_gid(GROUP_DOMAIN, &groupname_map_list, gid, psid, nt_grp_name, nt_domain); + return map_gid(GROUP_DOMAIN, gid, psid, nt_grp_name, nt_domain); } -- cgit From 6192feac174627a9191de7c8f162f4ce78d272df Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 29 Nov 1998 06:23:16 +0000 Subject: don't allow ".." in service name when doing "default service" processing. (This used to be commit 702263bba555a1d7c7999d40e5789b7e920dbce4) --- source3/smbd/service.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b4a1115867..bc7fb88387 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -146,7 +146,9 @@ int find_service(char *service) if (iService < 0) { char *pdefservice = lp_defaultservice(); - if (pdefservice && *pdefservice && !strequal(pdefservice,service)) + if (pdefservice && *pdefservice && + !strequal(pdefservice,service) && + !strstr(service,"..")) { /* * We need to do a local copy here as lp_defaultservice() -- cgit From 30038de4623bc827ee8019c569faf00583d1fe58 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 29 Nov 1998 20:03:33 +0000 Subject: weekend work. user / group database API. - split sam_passwd and smb_passwd into separate higher-order function tables - renamed struct smb_passwd's "smb_user" to "unix_user". added "nt_user" plus user_rid, and added a "wrap" function in both sam_passwd and smb_passwd password databases to fill in the blank entries that are not obtained from whatever password database API instance is being used. NOTE: whenever a struct smb_passwd or struct sam_passwd is used, it MUST be initialised with pwdb_sam_init() or pwd_smb_init(), see chgpasswd.c for the only example outside of the password database APIs i could find. - added query_useraliases code to rpcclient. - dealt with some nasty interdependencies involving non-smbd programs and the password database API. this is still not satisfactorily resolved completelely, but it's the best i can do for now. - #ifdef'd out some password database options so that people don't mistakenly set them unless they recompile to _use_ those options. lots of debugging done, it's still not finished. the unix/NT uid/gid and user-rid/group-rid issues are better, but not perfect. the "BUILTIN" domain is still missing: users cannot be added to "BUILTIN" groups yet, as we only have an "alias" db API and a "group" db API but not "builtin-alias" db API... (This used to be commit 5d5d7e4de7d1514ab87b07ede629de8aa00519a1) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/password.c | 12 ++++++------ source3/smbd/server.c | 37 +++++++++++++++++++------------------ 3 files changed, 26 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 30b9b3fed6..9791d3a38e 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -529,7 +529,7 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2 if (smbpw->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); + DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->unix_name)); return False; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8b73ff4518..ed47e6d3e5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -391,11 +391,11 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], if (!lm_pass || !smb_pass) return(False); DEBUG(4,("Checking SMB password for user %s\n", - smb_pass->smb_name)); + smb_pass->unix_name)); if(smb_pass->acct_ctrl & ACB_DISABLED) { DEBUG(3,("account for user %s was disabled.\n", - smb_pass->smb_name)); + smb_pass->unix_name)); return(False); } @@ -436,7 +436,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ)) { DEBUG(4,("no password required for user %s\n", - smb_pass->smb_name)); + smb_pass->unix_name)); return True; } @@ -502,7 +502,7 @@ BOOL pass_check_smb(char *user, char *domain, } /* Ensure the uid's match */ - if (smb_pass->smb_userid != pass->pw_uid) + if (smb_pass->unix_uid != pass->pw_uid) { DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); @@ -510,7 +510,7 @@ BOOL pass_check_smb(char *user, char *domain, if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords()) { - DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->smb_name)); + DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->unix_name)); return(True); } @@ -587,7 +587,7 @@ validate a group username entry. Return the username or NULL ****************************************************************************/ static char *validate_group(char *group,char *password,int pwlen,int snum) { -#ifdef HAVE_NETGROUP +#if defined(HAVE_NETGROUP) && defined(HAVE_GETNETGRENT) && defined(HAVE_SETNETGRENT) && defined(HAVE_ENDNETGRENT) { char *host, *user, *domain; setnetgrent(group); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d0178508d9..3a32e1871f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -651,15 +651,28 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); - fstrcpy(global_myworkgroup, lp_workgroup()); + if (!pwdb_initialise()) + { + exit(1); + } - get_sam_domain_name(); + if(!initialise_sam_password_db()) + { + exit(1); + } - generate_wellknown_sids(); + if(!initialise_passgrp_db()) + { + exit(1); + } - if (!generate_sam_sid()) + if(!initialise_group_db()) + { + exit(1); + } + + if(!initialise_alias_db()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } @@ -700,7 +713,7 @@ static void usage(char *pname) become_daemon(); } - check_kernel_oplocks(); + check_kernel_oplocks(); if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); @@ -716,18 +729,6 @@ static void usage(char *pname) if (!locking_init(0)) exit(1); - if(!initialise_passgrp_db()) - exit(1); - - if(!initialise_password_db()) - exit(1); - - if(!initialise_group_db()) - exit(1); - - if(!initialise_alias_db()) - exit(1); - /* possibly reload the services file. */ reload_services(True); -- cgit From 53373894acfff45885caf1e19a54141546ba5eea Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 29 Nov 1998 20:06:52 +0000 Subject: "retired" two modules to preserve their cvs history. added their replacements, added sam password database API modules (This used to be commit b1d1c1337c69c6f6bf25ab932a1a6a757e3ea2ae) --- source3/smbd/groupname.c | 639 +---------------------------------------------- 1 file changed, 1 insertion(+), 638 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index a81114169c..0be558848a 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -19,641 +19,4 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * UNIX gid and Local or Domain SID resolution. This module resolves - * only those entries in the map files, it is *NOT* responsible for - * resolving UNIX groups not listed: that is an entirely different - * matter, altogether... - */ - -/* - * - * - - format of the file is: - - unixname NT Group name - unixname Domain Admins (well-known Domain Group) - unixname DOMAIN_NAME\NT Group name - unixname OTHER_DOMAIN_NAME\NT Group name - unixname DOMAIN_NAME\Domain Admins (well-known Domain Group) - .... - - if the DOMAIN_NAME\ component is left off, then your own domain is assumed. - - * - * - */ - - -#include "includes.h" -extern int DEBUGLEVEL; - -extern fstring global_sam_name; - -/* we can map either local aliases or domain groups */ -typedef enum -{ - GROUP_LOCAL, - GROUP_DOMAIN - -} GROUP_TYPE; - -/************************************************************************** - Groupname map functionality. The code loads a groupname map file and - (currently) loads it into a linked list. This is slow and memory - hungry, but can be changed into a more efficient storage format - if the demands on it become excessive. -***************************************************************************/ - -typedef struct group_name_info -{ - char *nt_name; - char *nt_domain; - char *unix_name; - - DOM_SID sid; - gid_t unix_gid; - -} GROUP_NAME_INFO; - -typedef struct name_map -{ - ubi_slNode next; - GROUP_NAME_INFO grp; - -} name_map_entry; - -static ubi_slList groupname_map_list; -static ubi_slList aliasname_map_list; - -static void delete_name_entry(name_map_entry *gmep) -{ - if (gmep->grp.nt_name) - { - free(gmep->grp.nt_name); - } - if (gmep->grp.nt_domain) - { - free(gmep->grp.nt_domain); - } - if (gmep->grp.unix_name) - { - free(gmep->grp.unix_name); - } - free((char*)gmep); -} - -/************************************************************************** - Delete all the entries in the name map list. -***************************************************************************/ - -static void delete_map_list(ubi_slList *map_list) -{ - name_map_entry *gmep; - - while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL) - { - delete_name_entry(gmep); - } -} - - -/************************************************************************** - makes a group sid out of a domain sid and a _unix_ gid. -***************************************************************************/ -static BOOL make_mydomain_sid(GROUP_NAME_INFO *grp, GROUP_TYPE type) -{ - uint32 tmp_rid; - DOM_SID sid; - uint8 tmp_type; - - DEBUG(10,("make_mydomain_sid\n")); - - if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) - { - DEBUG(0,("make_mydomain_sid: unknown domain %s\n", - grp->nt_domain)); - return False; - } - - if (strequal(grp->nt_domain, global_sam_name) && - lookup_builtin_grp_name(grp->nt_name, &sid, &tmp_type) == 0x0) - { - sid_copy(&grp->sid, &sid); - return True; - } - else - { - BOOL ret; - fstring sid_str; - if (type == GROUP_DOMAIN) - { - tmp_rid = pwdb_gid_to_group_rid(grp->unix_gid); - } - else - { - tmp_rid = pwdb_gid_to_alias_rid(grp->unix_gid); - } - ret = sid_append_rid(&(grp->sid), tmp_rid); - sid_to_string(sid_str, &grp->sid); - DEBUG(10,("nt name %s gid %d mapped to %s\n", - grp->nt_name, grp->unix_gid, sid_str)); - return ret; - } -} - -/************************************************************************** - makes a group sid out of an nt domain, nt group name or a unix group name. -***************************************************************************/ -static BOOL unix_name_to_group_info(GROUP_NAME_INFO *grp, GROUP_TYPE type) -{ - struct group *gptr = NULL; - - /* - * Attempt to get the unix gid_t for this name. - */ - - DEBUG(5,("unix_name_to_group_info: unix_name:%s\n", grp->unix_name)); - - gptr = (struct group *)getgrnam(grp->unix_name); - if (gptr == NULL) - { - DEBUG(0,("unix_name_to_group_info: getgrnam for group %s\ -failed. Error was %s.\n", grp->unix_name, strerror(errno) )); - return False; - } - - grp->unix_gid = (gid_t)gptr->gr_gid; - - DEBUG(5,("unix_name_to_group_info: unix gid:%d\n", grp->unix_gid)); - - /* - * Now map the name to an NT SID+RID. - */ - - if (grp->nt_domain != NULL && !strequal(grp->nt_domain, global_sam_name)) - { - /* Must add client-call lookup code here, to - * resolve remote domain's sid and the group's rid, - * in that domain. - * - * NOTE: it is _incorrect_ to put code here that assumes - * that we can call pwdb_gid_to_group_rid() or _alias_rid(): - * it is a totally different domain for which we are *NOT* - * responsible. - * for foriegn domains for which we are *NOT* the PDC, all - * we can be responsible for is the unix * gid_t to which - * the foriegn SID+rid maps to, on this _local_ machine. - */ - - if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain))) - { - DEBUG(0,("unix_name_to_group_info: no known sid for %s\n", - grp->nt_domain)); - return False; - } - } - - return make_mydomain_sid(grp, type); -} - -static BOOL make_name_entry(name_map_entry **new_ep, - char *nt_domain, char *nt_group, char *unix_group, - GROUP_TYPE type) -{ - /* - * Create the list entry and add it onto the list. - */ - - DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group)); - - (*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry)); - if ((*new_ep) == NULL) - { - DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n")); - return False; - } - - ZERO_STRUCTP(*new_ep); - - (*new_ep)->grp.nt_name = strdup(nt_group ); - (*new_ep)->grp.nt_domain = strdup(nt_domain ); - (*new_ep)->grp.unix_name = strdup(unix_group); - - if ((*new_ep)->grp.nt_name == NULL || - (*new_ep)->grp.unix_name == NULL) - { - DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n")); - delete_name_entry((*new_ep)); - return False; - } - - /* - * look up the group names, make the Group-SID and unix gid - */ - - if (!unix_name_to_group_info(&(*new_ep)->grp, type)) - { - delete_name_entry((*new_ep)); - return False; - } - - return True; -} - -/************************************************************************** - Load a name map file. Sets last accessed timestamp. -***************************************************************************/ -static ubi_slList *load_name_map(GROUP_TYPE type) -{ - static time_t groupmap_file_last_modified = (time_t)0; - static time_t aliasmap_file_last_modified = (time_t)0; - static BOOL initialised_group = False; - static BOOL initialised_alias = False; - char *groupname_map_file = lp_groupname_map(); - char *aliasname_map_file = lp_aliasname_map(); - - SMB_STRUCT_STAT st; - FILE *fp; - char *s; - pstring buf; - name_map_entry *new_ep; - - time_t *file_last_modified; - int *initialised; - char *map_file; - ubi_slList *map_list; - - if (type == GROUP_DOMAIN) - { - file_last_modified = &groupmap_file_last_modified; - initialised = &initialised_group; - map_file = groupname_map_file; - map_list = &groupname_map_list; - } - else - { - file_last_modified = &aliasmap_file_last_modified; - initialised = &initialised_alias; - map_file = aliasname_map_file; - map_list = &aliasname_map_list; - } - - if (!(*initialised)) - { - DEBUG(10,("initialising group map %s\n", map_file)); - ubi_slInitList(map_list); - (*initialised) = True; - } - - if (!*map_file) - { - return map_list; - } - - if (sys_stat(map_file, &st) != 0) - { - DEBUG(0, ("load_name_map: Unable to stat file %s. Error was %s\n", - map_file, strerror(errno) )); - return map_list; - } - - /* - * Check if file has changed. - */ - if (st.st_mtime <= (*file_last_modified)) - { - return map_list; - } - - (*file_last_modified) = st.st_mtime; - - /* - * Load the file. - */ - - fp = fopen(map_file,"r"); - if (!fp) - { - DEBUG(0,("load_name_map: can't open name map %s. Error was %s\n", - map_file, strerror(errno))); - return map_list; - } - - /* - * Throw away any previous list. - */ - delete_map_list(map_list); - - DEBUG(4,("load_name_map: Scanning name map %s\n",map_file)); - - while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL) - { - pstring unixname; - pstring nt_name; - fstring nt_domain; - fstring nt_group; - char *p; - - DEBUG(10,("Read line |%s|\n", s)); - - memset(nt_name, 0, sizeof(nt_name)); - - if (!*s || strchr("#;",*s)) - continue; - - if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) - continue; - - if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name))) - continue; - - trim_string(unixname, " ", " "); - trim_string(nt_name, " ", " "); - - if (!*nt_name) - continue; - - if (!*unixname) - continue; - - DEBUG(5,("unixname = %s, ntname = %s.\n", - unixname, nt_name)); - - p = strchr(nt_name, '\\'); - - if (p == NULL) - { - memset(nt_domain, 0, sizeof(nt_domain)); - fstrcpy(nt_group, nt_name); - } - else - { - *p = 0; - p++; - fstrcpy(nt_domain, nt_name); - fstrcpy(nt_group , p); - } - - if (make_name_entry(&new_ep, nt_domain, nt_name, unixname, type)) - { - ubi_slAddTail(map_list, (ubi_slNode *)new_ep); - } - } - - DEBUG(10,("load_name_map: Added %ld entries to name map.\n", - ubi_slCount(map_list))); - - fclose(fp); - - return map_list; -} - -/*********************************************************** - Lookup by SID -************************************************************/ -static BOOL map_sid(GROUP_TYPE type, - DOM_SID *psid, gid_t *gid, char *ntname, char *ntdomain) -{ - name_map_entry *gmep; - ubi_slList *map_list; - - /* - * Initialise and load if not already loaded. - */ - map_list = load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - if (sid_equal(&gmep->grp.sid, psid)) - { - if (gid != NULL) - { - *gid = gmep->grp.unix_gid; - } - if (ntname != NULL) - { - fstrcpy(ntname, gmep->grp.nt_name); - } - if (ntdomain != NULL) - { - fstrcpy(ntdomain, gmep->grp.nt_domain); - } - DEBUG(7,("map_sid: Mapping unix group %s to nt group %s.\n", - gmep->grp.unix_name, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/*********************************************************** - Lookup nt name. -************************************************************/ -static BOOL map_ntname(GROUP_TYPE type, - char *ntname, char *ntdomain, DOM_SID *psid, - char *unixname, gid_t *gid) -{ - name_map_entry *gmep; - ubi_slList *map_list; - - /* - * Initialise and load if not already loaded. - */ - map_list = load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - if (strequal(gmep->grp.nt_name , ntname) && - strequal(gmep->grp.nt_domain, ntdomain)) - { - if (psid != NULL) - { - sid_copy(psid, &gmep->grp.sid); - } - if (gid != NULL) - { - *gid = gmep->grp.unix_gid; - } - if (unixname != NULL) - { - fstrcpy(unixname, gmep->grp.unix_name); - } - DEBUG(7,("map_ntname: Mapping unix group %s to nt group %s.\n", - gmep->grp.unix_name, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/*********************************************************** - Lookup unix name. -************************************************************/ -static BOOL map_unixname(GROUP_TYPE type, - char *unixname, DOM_SID *psid, char *ntname, char *ntdomain) -{ - name_map_entry *gmep; - ubi_slList *map_list; - - /* - * Initialise and load if not already loaded. - */ - map_list = load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - if (strequal(gmep->grp.unix_name, unixname)) - { - if (psid != NULL) - { - sid_copy(psid, &gmep->grp.sid); - } - if (ntname != NULL) - { - fstrcpy(ntname, gmep->grp.nt_name); - } - if (ntdomain != NULL) - { - fstrcpy(ntdomain, gmep->grp.nt_domain); - } - DEBUG(7,("map_unixname: Mapping unix group %s to nt group %s.\n", - gmep->grp.unix_name, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/*********************************************************** - Lookup by gid_t. -************************************************************/ -static BOOL map_gid(GROUP_TYPE type, - gid_t gid, DOM_SID *psid, char *ntname, char *ntdomain) -{ - name_map_entry *gmep; - ubi_slList *map_list; - - /* - * Initialise and load if not already loaded. - */ - map_list = load_name_map(type); - - for (gmep = (name_map_entry *)ubi_slFirst(map_list); - gmep != NULL; - gmep = (name_map_entry *)ubi_slNext(gmep )) - { - fstring sid_str; - sid_to_string(sid_str, &gmep->grp.sid); - DEBUG(10,("map_gid: enum entry unix group %s %d nt %s %s\n", - gmep->grp.unix_name, gmep->grp.unix_gid, gmep->grp.nt_name, sid_str)); - if (gmep->grp.unix_gid == gid) - { - if (psid != NULL) - { - sid_copy(psid, &gmep->grp.sid); - } - if (ntname != NULL) - { - fstrcpy(ntname, gmep->grp.nt_name); - } - if (ntdomain != NULL) - { - fstrcpy(ntdomain, gmep->grp.nt_domain); - } - DEBUG(7,("map_gid: Mapping unix group %s to nt group %s.\n", - gmep->grp.unix_name, gmep->grp.nt_name )); - return True; - } - } - - return False; -} - -/*********************************************************** - * - * Call four functions to resolve unix group ids and either - * local group SIDs or domain group SIDs listed in the local group - * or domain group map files. - * - * Note that it is *NOT* the responsibility of these functions to - * resolve entries that are not in the map files. - * - * Any SID can be in the map files (i.e from any Domain). - * - ***********************************************************/ - -/*********************************************************** - Lookup a Group entry by sid. -************************************************************/ -BOOL map_group_sid(DOM_SID *psid, gid_t *gid, char *group_name, char *nt_domain) -{ - return map_sid(GROUP_DOMAIN, psid, gid, group_name, nt_domain); -} - -/*********************************************************** - Lookup an Alias SID entry by name. -************************************************************/ -BOOL map_alias_sid(DOM_SID *psid, gid_t *gid, char *alias_name, char *nt_domain) -{ - return map_sid(GROUP_LOCAL, psid, gid, alias_name, nt_domain); -} - -/*********************************************************** - Lookup a UNIX Group entry by name. -************************************************************/ -BOOL map_unix_group_name(char *group_name, DOM_SID *psid, char *ntgroup_name, char *nt_domain) -{ - return map_unixname(GROUP_DOMAIN, group_name, psid, ntgroup_name, nt_domain); -} - -/*********************************************************** - Lookup a UNIX Alias entry by name. -************************************************************/ -BOOL map_unix_alias_name(char *alias_name, DOM_SID *psid, char *ntalias_name, char *nt_domain) -{ - return map_unixname(GROUP_LOCAL, alias_name, psid, ntalias_name, nt_domain); -} - -/*********************************************************** - Lookup a Group entry -************************************************************/ -BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_SID *psid, char *group_name, gid_t *gid) -{ - return map_ntname(GROUP_DOMAIN, ntgroup_name, nt_domain, psid, group_name, gid); -} - -/*********************************************************** - Lookup an Alias name entry -************************************************************/ -BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_SID *psid, char *alias_name, gid_t *gid) -{ - return map_ntname(GROUP_LOCAL, ntalias_name, nt_domain, psid, alias_name, gid); -} - -/*********************************************************** - Lookup an Alias SID entry by gid_t. -************************************************************/ -BOOL map_alias_gid(gid_t gid, DOM_SID *psid, char *nt_als_name, char *nt_domain) -{ - return map_gid(GROUP_LOCAL, gid, psid, nt_als_name, nt_domain); -} - -/*********************************************************** - Lookup a Group SID entry by gid_t. -************************************************************/ -BOOL map_group_gid( gid_t gid, DOM_SID *psid, char *nt_grp_name, char *nt_domain) -{ - return map_gid(GROUP_DOMAIN, gid, psid, nt_grp_name, nt_domain); -} - +/* this module is retired, it is moved to lib/domain_namemap.c */ -- cgit From 31044dd8e6419b305779408a4b3b0fbd8eab11b5 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 30 Nov 1998 15:08:58 +0000 Subject: - adding builtin[alias]db. - lib/sids.c: generate_sam_sid() modified to take a domain name: it now generates "DOMAIN_NAME.SID". reasons: 1) if you run multiple samba servers on the same machine under different netbios names as members of a domain, they won't all use the same SID, which is a _big_ mistake but it would happen _by default_. 2) we have (had) a problem with sid_to_string() and string_to_sid() which cause SIDs to be incorrectly read. one of the major reasons for *NOT* making this change was so as not to disrupt existing users. but as they will be anyway by this bug, we might as well go ahead. - passdb/smbpass.c: wanted to change the meaning of the name in the smbpasswd file to an "nt" name not a "unix" name. this is probably not a good idea: reverted this. - output formatting / bug-fixing in rpcclient query_useraliases code. (This used to be commit e4930f5f48f8246ceec8add8bf769954a963190c) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3a32e1871f..7a16d8abf3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -676,6 +676,11 @@ static void usage(char *pname) exit(1); } + if(!initialise_builtin_db()) + { + exit(1); + } + if (!get_member_domain_sid()) { DEBUG(0,("ERROR: Samba cannot obtain PDC SID from PDC(s) %s.\n", -- cgit From c6ad04b8fb4ee5cbf862a35b4c143a6f75555718 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 30 Nov 1998 22:42:13 +0000 Subject: attempting to fix "domain user map" up, but it's a bit complicated. i may simply go for a response in the NetSamLogon returning the unix username, forcing the NT user to appear to be a unix user, however even that is fraught with implications. might just have to go the whole hog and do this tuple thing, "unix_name + nt_name" always associated together... issue with api_net_sam_logon, getsam21pwent() being called twice, the second time overwriting static buffer data (argh) so had to make a copy. noticed a nested "become_root()"/"unbecome_root()" which will have to be tracked down... (This used to be commit 474f94f419a531e33b475249da7efb99ac22f454) --- source3/smbd/reply.c | 90 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1abb084124..505067c83e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -60,6 +60,49 @@ static void overflow_attack(int len) } +/**************************************************************************** + does _both_ nt->unix and unix->unix username remappings. +****************************************************************************/ +static BOOL map_nt_and_unix_username(const char *domain, char *user) +{ + DOM_NAME_MAP gmep; + fstring nt_username; + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + memset(nt_username, 0, sizeof(nt_username)); + if (domain != NULL) + { + slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s", + domain, user); + } + else + { + fstrcpy(nt_username, user); + } + if (!lookupsmbpwntnam(nt_username, &gmep)) + { + return False; + } + + fstrcpy(user, gmep.unix_name); + + /* + * Pass the user through the unix -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + return Get_Pwnam( user, True) != NULL; +} + /**************************************************************************** reply to an special message ****************************************************************************/ @@ -220,17 +263,10 @@ int reply_tcon(connection_struct *conn, parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); + if (!map_nt_and_unix_username(global_myworkgroup, user)) + { + return(connection_error(inbuf,outbuf,ERRbadpw)); + } conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode); @@ -300,18 +336,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt StrnCpy(devicename,path + strlen(path) + 1,6); DEBUG(4,("Got device type %s\n",devicename)); - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam(user, True); - + if (!map_nt_and_unix_username(global_myworkgroup, user)) + { + return(connection_error(inbuf,outbuf,ERRbadpw)); + } + conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode); if (!conn) @@ -642,17 +671,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstrcpy( orig_user, user); - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); + if (!map_nt_and_unix_username(domain, user)) + { + return(ERROR(ERRSRV,ERRbadpw)); + } add_session_user(user); -- cgit From 308da9e82b496b0ecfcbf1ee8fd347f37c136ab9 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 1 Dec 1998 16:41:34 +0000 Subject: hm. removed the "if failed to map nt name to unix name, fail tcon call" restriction and "domain user map" seems to work. amazing. (This used to be commit 2c0d91e64a6b330b209ca62c3306ec1a53fda873) --- source3/smbd/reply.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 505067c83e..bd238c130c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -263,10 +263,7 @@ int reply_tcon(connection_struct *conn, parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); - if (!map_nt_and_unix_username(global_myworkgroup, user)) - { - return(connection_error(inbuf,outbuf,ERRbadpw)); - } + map_nt_and_unix_username(global_myworkgroup, user); conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode); @@ -336,10 +333,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt StrnCpy(devicename,path + strlen(path) + 1,6); DEBUG(4,("Got device type %s\n",devicename)); - if (!map_nt_and_unix_username(global_myworkgroup, user)) - { - return(connection_error(inbuf,outbuf,ERRbadpw)); - } + map_nt_and_unix_username(global_myworkgroup, user); conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode); -- cgit From e2d51234002609f00bfa92b8031ac15616d6fe26 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 1 Dec 1998 18:24:23 +0000 Subject: andrej spotted that entries _not_ in domain map user were being refused. modified map_nt_and_unix_names() to never refuse a mapping (returns void now not BOOL). (This used to be commit faffcb3c8955dcea3987e2978dc34b4dba580167) --- source3/smbd/reply.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bd238c130c..169f69ee07 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -63,7 +63,7 @@ static void overflow_attack(int len) /**************************************************************************** does _both_ nt->unix and unix->unix username remappings. ****************************************************************************/ -static BOOL map_nt_and_unix_username(const char *domain, char *user) +static void map_nt_and_unix_username(const char *domain, char *user) { DOM_NAME_MAP gmep; fstring nt_username; @@ -83,13 +83,12 @@ static BOOL map_nt_and_unix_username(const char *domain, char *user) { fstrcpy(nt_username, user); } - if (!lookupsmbpwntnam(nt_username, &gmep)) + + if (lookupsmbpwntnam(nt_username, &gmep)) { - return False; + fstrcpy(user, gmep.unix_name); } - fstrcpy(user, gmep.unix_name); - /* * Pass the user through the unix -> unix user mapping * function. @@ -100,7 +99,7 @@ static BOOL map_nt_and_unix_username(const char *domain, char *user) /* * Do any UNIX username case mangling. */ - return Get_Pwnam( user, True) != NULL; + (void)Get_Pwnam( user, True); } /**************************************************************************** @@ -665,10 +664,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstrcpy( orig_user, user); - if (!map_nt_and_unix_username(domain, user)) - { - return(ERROR(ERRSRV,ERRbadpw)); - } + map_nt_and_unix_username(domain, user); add_session_user(user); -- cgit From 04e382fb166a64de193dc3c7b21187d8382eaeea Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 1 Dec 1998 19:10:44 +0000 Subject: rpc_samr.h parse_samr.c srv_samr.c : samr_query_aliasmembers (cool!) util_pwdb.c sids.c nmbd.c server.c smbpasswd.c swat.c : pwdb_initialise(BOOL is_server) now creates / reads DOMAIN_NAME.SID if is_server is True, and does LsaQueryInfoPolicy(levels 3 and 5) to obtain member and pdc sids. (This used to be commit 3e1eb4f26b67e484b05e1dde94fd4e4dae982631) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7a16d8abf3..3e25bfa633 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -651,7 +651,7 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); - if (!pwdb_initialise()) + if (!pwdb_initialise(True)) { exit(1); } -- cgit From 08cdea519c692de092ba7a70664411c1a3cedac0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 1 Dec 1998 22:39:33 +0000 Subject: check server role before doing nt user to unix user mapping (This used to be commit 9d4e810e7dd8d6d80b47204636f9a37774f95455) --- source3/smbd/reply.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 169f69ee07..d706976714 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -73,20 +73,23 @@ static void map_nt_and_unix_username(const char *domain, char *user) * function. */ - memset(nt_username, 0, sizeof(nt_username)); - if (domain != NULL) + if (lp_server_role() != ROLE_DOMAIN_NONE) { - slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s", - domain, user); - } - else - { - fstrcpy(nt_username, user); - } + memset(nt_username, 0, sizeof(nt_username)); + if (domain != NULL) + { + slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s", + domain, user); + } + else + { + fstrcpy(nt_username, user); + } - if (lookupsmbpwntnam(nt_username, &gmep)) - { - fstrcpy(user, gmep.unix_name); + if (lookupsmbpwntnam(nt_username, &gmep)) + { + fstrcpy(user, gmep.unix_name); + } } /* -- cgit From f3787515d67b80a91786cfdd2fd2fb5972b4b094 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 3 Dec 1998 17:41:14 +0000 Subject: moved get_unixgroups it will be needed by the unix instance of the group DB API (This used to be commit ef58e48bc9af338ed6c734205d4faf82371284ac) --- source3/smbd/password.c | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ed47e6d3e5..8718e75c3b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -150,55 +150,6 @@ char *validated_username(uint16 vuid) } -/**************************************************************************** -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; -} - /**************************************************************************** register a uid/name pair as being valid and that a valid password -- cgit From 85549599854e34718330c2fc428d443a1f91e854 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 5 Dec 1998 01:03:42 +0000 Subject: Sync up critical kernel oplock bugfix. I don't want to lose this.... Jeremy. (This used to be commit 5287f3d19b7d8e76970f1ce1abfd95b7341434e5) --- source3/smbd/oplock.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index bc2d46bb95..1455b4d8e5 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -39,6 +39,29 @@ extern int smb_read_error; static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval); +/**************************************************************************** + Setup the kernel level oplock backchannel for this process. +****************************************************************************/ + +BOOL setup_kernel_oplock_pipe(void) +{ +#if defined(HAVE_KERNEL_OPLOCKS) + if(lp_kernel_oplocks()) { + int pfd[2]; + + if(pipe(pfd) != 0) { + DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n", + strerror(errno) )); + return False; + } + + oplock_pipe_read = pfd[0]; + oplock_pipe_write = pfd[1]; + } +#endif /* HAVE_KERNEL_OPLOCKS */ + return True; +} + /**************************************************************************** open the oplock IPC socket communication ****************************************************************************/ @@ -71,6 +94,9 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); } global_oplock_port = ntohs(sock_name.sin_port); + if(!setup_kernel_oplock_pipe()) + return False; + DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", (int)getpid(), global_oplock_port)); @@ -158,6 +184,13 @@ Error was %s.\n", strerror(errno) )); if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ Error was %s.\n", strerror(errno) )); + if(errno == EAGAIN) { + /* + * Duplicate kernel break message - ignore. + */ + memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); + return True; + } smb_read_error = READ_ERROR; return False; } @@ -1056,7 +1089,7 @@ void check_kernel_oplocks(void) return; } - if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { + if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) { DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", tmpname, strerror(errno) )); unlink( tmpname ); @@ -1085,13 +1118,13 @@ Disabling kernel oplock support.\n", strerror(errno) )); return; } - oplock_pipe_read = pfd[0]; - oplock_pipe_write = pfd[1]; + close(pfd[0]); + close(pfd[1]); close(fd); lp_set_kernel_oplocks(True); - DEBUG(3,("check_kernel_oplocks: Kernel oplocks available and set to %s.\n", + DEBUG(0,("check_kernel_oplocks: Kernel oplocks available and set to %s.\n", lp_kernel_oplocks() ? "True" : "False" )); } -- cgit From 9c848ec329a6ce86cffb2304746590116d9292f0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 7 Dec 1998 20:23:41 +0000 Subject: removed nt_pipe_fnum from struct cli_state. need to be able to call LsaLookupSids etc from within SamrQueryAliasMembers, for example. fnum is now a parameter to client functions. thanks to mike black for starting the ball rolling. (This used to be commit bee8f7fa6b0f7f995f71303f4e14a4aaed0c2437) --- source3/smbd/password.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8718e75c3b..726d93e404 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1095,6 +1095,7 @@ BOOL domain_client_validate( char *user, char *domain, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { + uint16 nt_pipe_fnum; unsigned char local_challenge[8]; unsigned char local_lm_response[24]; unsigned char local_nt_reponse[24]; @@ -1174,19 +1175,19 @@ BOOL domain_client_validate( char *user, char *domain, * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(&cli, PIPE_NETLOGON) == False) { + if(cli_nt_session_open(&cli, PIPE_NETLOGON, &nt_pipe_fnum) == False) { DEBUG(0,("domain_client_validate: unable to open the domain client session to \ machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli); + cli_nt_session_close(&cli, nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); return False; } - if(cli_nt_setup_creds(&cli, trust_passwd) == False) { + if(cli_nt_setup_creds(&cli, nt_pipe_fnum, trust_passwd) == False) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli); + cli_nt_session_close(&cli, nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); return False; @@ -1195,13 +1196,13 @@ machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); /* We really don't care what LUID we give the user. */ generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - if(cli_nt_login_network(&cli, domain, user, smb_uid_low, (char *)local_challenge, + if(cli_nt_login_network(&cli, nt_pipe_fnum, domain, user, smb_uid_low, (char *)local_challenge, ((smb_apasslen != 0) ? smb_apasswd : NULL), ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), &ctr, &info3) == False) { DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ %s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli); + cli_nt_session_close(&cli, nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); return False; @@ -1218,17 +1219,17 @@ machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); * send here. JRA. */ - if(cli_nt_logoff(&cli, &ctr) == False) { + if(cli_nt_logoff(&cli, nt_pipe_fnum, &ctr) == False) { DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ %s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli); + cli_nt_session_close(&cli, nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); return False; } #endif /* 0 */ - cli_nt_session_close(&cli); + cli_nt_session_close(&cli, nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); return True; -- cgit From e50ab2b528a3dd176d98f95cb644fc6695c55318 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 7 Dec 1998 22:43:43 +0000 Subject: fixed warnings (and potential errors) due to integer overflow when creating locking masks (This used to be commit 5e2844d5edb15de29b976d2ff077ffbe012b860c) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd1ece7fe1..6658b8926f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -574,7 +574,8 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i BOOL *share_locked) { if (fsp->can_write){ - 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); if (is_locked(fsp,conn,~mask,0,F_WRLCK)){ /* If share modes are in force for this connection we -- cgit From 8308c000b2022769644ed8ea1fc772776257c99b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 8 Dec 1998 00:25:04 +0000 Subject: adding srvsvc pipe. (This used to be commit d06d6369942828ec89e90f99bd0d0d3f91d61d13) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 60620c9854..52a1005397 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -37,6 +37,7 @@ static void remove_pending_change_notify_requests_by_mid(int mid); static char *known_nt_pipes[] = { "\\LANMAN", "\\srvsvc", + "\\svcctl", "\\samr", "\\wkssvc", "\\NETLOGON", -- cgit From d4385df3e80d63dbc7a1c90cc903d8343dfba652 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 14 Dec 1998 20:21:39 +0000 Subject: trying to track down issues in get_home_dir(). (This used to be commit 2cce78aa00f31b79d51aaf46da72019b926e8226) --- source3/smbd/reply.c | 6 +++++- source3/smbd/service.c | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d706976714..694cf3cdd5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -750,7 +750,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int int homes = lp_servicenumber(HOMES_NAME); char *home = get_home_dir(user); if (homes >= 0 && home) - lp_add_home(user,homes,home); + { + pstring home_dir; + fstrcpy(home_dir, home); + lp_add_home(user,homes,home_dir); + } } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index bc7fb88387..4dd3cb4d97 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -92,8 +92,9 @@ int find_service(char *service) if (iService < 0) { char *phome_dir = get_home_dir(service); + pstring home_dir; - if(!phome_dir) + if(phome_dir == NULL) { /* * Try mapping the servicename, it may @@ -109,9 +110,10 @@ int find_service(char *service) if (phome_dir) { int iHomeService; + pstrcpy(home_dir, phome_dir); if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) { - lp_add_home(service,iHomeService,phome_dir); + lp_add_home(service,iHomeService,home_dir); iService = lp_servicenumber(service); } } -- cgit From e67a8d9d984dbdef307294358d7d9a7f4314ea09 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 14 Dec 1998 21:22:59 +0000 Subject: server_cryptkey() now calling cli_connectserverlist(). stupid microsoft idiotic *SMBSERVER connectionism added to cli_connect_serverlist(). also added check for protocol < LANMAN2. (This used to be commit c2bcb3a286f22ed4f0f55da2a3eb2bff17906fb1) --- source3/smbd/password.c | 78 +++---------------------------------------------- 1 file changed, 4 insertions(+), 74 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 726d93e404..7eed028a80 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -909,81 +909,11 @@ support for server level security ****************************************************************************/ struct cli_state *server_cryptkey(void) { - struct cli_state *cli; - fstring desthost; - struct in_addr dest_ip; - extern fstring local_machine; - char *p; - BOOL connected_ok = False; - struct nmb_name calling, called; - - cli = server_client(); - - if (!cli_initialise(cli)) - return NULL; - - p = lp_passwordserver(); - while(p && next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { - standard_sub_basic(desthost); - strupper(desthost); - - if(!resolve_name( desthost, &dest_ip, 0x20)) { - DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); - continue; - } - - if (cli_connect(cli, desthost, &dest_ip)) { - DEBUG(3,("connected to password server %s\n",desthost)); - connected_ok = True; - break; - } - } - - if (!connected_ok) { - DEBUG(0,("password server not available\n")); - cli_shutdown(cli); - return NULL; - } - - make_nmb_name(&calling, local_machine, 0x0 , scope); - make_nmb_name(&called , desthost , 0x20, scope); - - if (!cli_session_request(cli, &calling, &called)) { - /* try with *SMBSERVER if the first name fails */ - cli_shutdown(cli); - make_nmb_name(&called , "*SMBSERVER", 0x20, scope); - if (!cli_initialise(cli) || - !cli_connect(cli, desthost, &dest_ip) || - !cli_session_request(cli, &calling, &called)) { - DEBUG(1,("%s rejected the session\n",desthost)); - cli_shutdown(cli); - return NULL; - } - } - - DEBUG(3,("got session\n")); - - if (!cli_negprot(cli)) { - DEBUG(1,("%s rejected the negprot\n",desthost)); - cli_shutdown(cli); - return NULL; - } - - if (cli->protocol < PROTOCOL_LANMAN2 || - !(cli->sec_mode & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",desthost)); - cli_shutdown(cli); - return NULL; + if (cli_connect_serverlist(server_client(), lp_passwordserver())) + { + return server_client(); } - - DEBUG(3,("password server OK\n")); - - return cli; + return NULL; } /**************************************************************************** -- cgit From f5f913b001ab66c2266e3325f8c91af2486116a2 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Mon, 25 Jan 1999 01:46:14 +0000 Subject: Putting back the -p flag in smbclient. However, it seems that the -s flag in smbclient is also ignored :-( (This used to be commit f6c78192664d611d4663ed7459a2789315861eec) --- source3/smbd/ssl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index 1c953272c3..1f098b2533 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -19,9 +19,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" + +/* + * Hmmm, only check on WITH_SSL after we have included includes.h + * which pulls in config.h which is where WITH_SSL is defined, if + * at all :-) + */ + #ifdef WITH_SSL /* should always be defined if this module is compiled */ -#include "includes.h" #include #include -- cgit From ceef08b60e1fc3839df89b27028aa9ac0f920f25 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 3 Feb 1999 17:10:44 +0000 Subject: initialise my name (used in %h) prior to loading smb.conf files. (This used to be commit ed128c38a88746ec7822d598e72f0106a30a4af7) --- source3/smbd/server.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3e25bfa633..0b332db0fd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -444,35 +444,14 @@ void exit_server(char *reason) /**************************************************************************** initialise connect, service and file structs ****************************************************************************/ -static void init_structs(void ) +static void init_structs(void) { get_myname(myhostname,NULL); - /* - * Set the machine NETBIOS name if not already - * set from the config file. - */ - - if (!*global_myname) { - char *p; - fstrcpy( global_myname, myhostname ); - p = strchr( global_myname, '.' ); - if (p) - *p = 0; - } - - strupper( global_myname ); - conn_init(); - file_init(); - - /* for RPC pipes */ - init_rpc_pipe_hnd(); - - /* for LSA handles */ - init_lsa_policy_hnd(); - + init_rpc_pipe_hnd(); /* for RPC pipes */ + init_lsa_policy_hnd(); /* for LSA handles */ init_dptrs(); } @@ -635,11 +614,21 @@ static void usage(char *pname) exit(1); } + init_structs(); + if (!reload_services(False)) return(-1); - init_structs(); - + /* + * Set the machine NETBIOS name if not already + * set from the config file. + */ + if (!*global_myname) + { + fstrcpy(global_myname, dns_to_netbios_name(myhostname)); + } + strupper(global_myname); + #ifdef WITH_SSL { extern BOOL sslEnabled; -- cgit From 37c9693fc8055773812ed86d91f9dfcc554eea30 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 8 Feb 1999 01:46:46 +0000 Subject: reload_services needs to be called prior to init_files but after get_myname. (This used to be commit 9ab81caa065a0e08368fc9137d42ed810fd4b817) --- source3/smbd/server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0b332db0fd..9b397bcdeb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -446,8 +446,6 @@ void exit_server(char *reason) ****************************************************************************/ static void init_structs(void) { - get_myname(myhostname,NULL); - conn_init(); file_init(); init_rpc_pipe_hnd(); /* for RPC pipes */ @@ -614,11 +612,13 @@ static void usage(char *pname) exit(1); } - init_structs(); - + get_myname(myhostname,NULL); + if (!reload_services(False)) return(-1); + init_structs(); + /* * Set the machine NETBIOS name if not already * set from the config file. -- cgit From 99a9b0f7c4f85f46102457cf4707e8948b77fb3f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 8 Feb 1999 23:40:49 +0000 Subject: UNICODE byte ordering issue: typecast to uint16* replaced with SSVAL() (This used to be commit 9084b7e33dfe717bd8d5604ee71d137e3baef0f5) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 9791d3a38e..a2e75ecc43 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -693,7 +693,7 @@ BOOL check_oem_password(char *user, int uni_pw_len = new_pw_len; char *pw; new_pw_len /= 2; - pw = unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); + pw = unistrn2(&lmdata[512-uni_pw_len], new_pw_len); memcpy(new_passwd, pw, new_pw_len+1); } else -- cgit From 96983a13bac8276590024b37149b7bf3e80477dd Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 9 Feb 1999 21:42:39 +0000 Subject: when multiple independent large rpc calls come in on the same pipe, prev_pdu_file_offset was not being re-initialised to zero. (This used to be commit fcaa1214412f5a417a648d4da5c4332f75f59f57) --- source3/smbd/ipc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 41892504ad..31ae8e6fc0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3236,7 +3236,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, subcommand, p->name, pnum)); /* record maximum data length that can be transmitted in an SMBtrans */ - p->file_offset = mdrcnt; + p->file_offset = mdrcnt; + p->prev_pdu_file_offset = 0; DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n", p, p->file_offset)); -- cgit From 8b6b6b57b54aeafb915cf99e5610941ee1d464b8 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 10 Feb 1999 22:30:47 +0000 Subject: use jeremy's versions of the UNICODE routines. (This used to be commit c5109ff782be8774db47a92b48ca6335ec8d6065) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a2e75ecc43..9791d3a38e 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -693,7 +693,7 @@ BOOL check_oem_password(char *user, int uni_pw_len = new_pw_len; char *pw; new_pw_len /= 2; - pw = unistrn2(&lmdata[512-uni_pw_len], new_pw_len); + pw = unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); memcpy(new_passwd, pw, new_pw_len+1); } else -- cgit From f38bfc7d9aa07c4e21448aa846956bd89a259a65 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 11 Feb 1999 22:12:49 +0000 Subject: UNICODE issues. (This used to be commit 6a437cfb33f24913e0c1f8484c0b08ef317e513b) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 9791d3a38e..a2e75ecc43 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -693,7 +693,7 @@ BOOL check_oem_password(char *user, int uni_pw_len = new_pw_len; char *pw; new_pw_len /= 2; - pw = unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); + pw = unistrn2(&lmdata[512-uni_pw_len], new_pw_len); memcpy(new_passwd, pw, new_pw_len+1); } else -- cgit From fd96929ec1fa27e0affd4c4e9ba307c4ee30b978 Mon Sep 17 00:00:00 2001 From: Matthew Chapman Date: Fri, 12 Feb 1999 00:16:09 +0000 Subject: UNICODE cleanup (see lib/util_unistr.c). No more ugly static library buffers and all functions take a destination string length (especially unistrcpy was rather dangerous; we were only saved by the fact that datagrams are limited in size). (This used to be commit a1d39af1ce1d451b811dbd7c2ba391214851b87e) --- source3/smbd/chgpasswd.c | 4 +--- source3/smbd/trans2.c | 13 +++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a2e75ecc43..167fce6e8c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -691,10 +691,8 @@ BOOL check_oem_password(char *user, * nt passwords are in unicode */ int uni_pw_len = new_pw_len; - char *pw; new_pw_len /= 2; - pw = unistrn2(&lmdata[512-uni_pw_len], new_pw_len); - memcpy(new_passwd, pw, new_pw_len+1); + unibuf_to_ascii(new_passwd, &lmdata[512-uni_pw_len], new_pw_len); } else { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7bfb046cc2..1bfcaa5f12 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1121,7 +1121,7 @@ static int call_trans2qfsinfo(connection_struct *conn, #endif /* Old code. */ SIVAL(pdata,4,128); /* Max filename component length */ SIVAL(pdata,8,2*strlen(fstype)); - PutUniCode(pdata+12,fstype); + ascii_to_unibuf(pdata+12, fstype, 1024-12); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); break; case SMB_QUERY_FS_LABEL_INFO: @@ -1148,7 +1148,7 @@ static int call_trans2qfsinfo(connection_struct *conn, } else { data_len = 18 + 2*strlen(vname); SIVAL(pdata,12,strlen(vname)*2); - PutUniCode(pdata+18,vname); + ascii_to_unibuf(pdata+18, vname, 1024-18); } DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", @@ -1395,6 +1395,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_ALT_NAME_INFO: { pstring short_name; + char *data_end; + pstrcpy(short_name,p); /* Mangle if not already 8.3 */ if(!is_8_3(short_name, True)) @@ -1403,10 +1405,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, *short_name = '\0'; } strupper(short_name); - l = strlen(short_name); - PutUniCode(pdata + 4, short_name); - data_size = 4 + (2*l); - SIVAL(pdata,0,2*l); + data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-4); + data_size = data_end - pdata; + SIVAL(pdata,0,2*(data_size-4)); } break; -- cgit From 2737f26ad64ee32d6ef7365dcce0a3eb881f99db Mon Sep 17 00:00:00 2001 From: Matthew Chapman Date: Mon, 15 Feb 1999 05:33:30 +0000 Subject: Always null-terminate strings. Also some string length and sizeof(pointer) corrections. (This used to be commit ce24191939b82985d09eabe945199f38b0fea486) --- source3/smbd/trans2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1bfcaa5f12..f041393dab 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1121,7 +1121,7 @@ static int call_trans2qfsinfo(connection_struct *conn, #endif /* Old code. */ SIVAL(pdata,4,128); /* Max filename component length */ SIVAL(pdata,8,2*strlen(fstype)); - ascii_to_unibuf(pdata+12, fstype, 1024-12); + ascii_to_unibuf(pdata+12, fstype, 1024-2-12); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); break; case SMB_QUERY_FS_LABEL_INFO: @@ -1148,7 +1148,7 @@ static int call_trans2qfsinfo(connection_struct *conn, } else { data_len = 18 + 2*strlen(vname); SIVAL(pdata,12,strlen(vname)*2); - ascii_to_unibuf(pdata+18, vname, 1024-18); + ascii_to_unibuf(pdata+18, vname, 1024-2-18); } DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", @@ -1405,7 +1405,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, *short_name = '\0'; } strupper(short_name); - data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-4); + data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-2-4); data_size = data_end - pdata; SIVAL(pdata,0,2*(data_size-4)); } -- cgit From 05f772b431f9c77a2fb37736fc4f801d84cac365 Mon Sep 17 00:00:00 2001 From: Matthew Chapman Date: Wed, 24 Feb 1999 01:52:30 +0000 Subject: Win9x user level security. * Added SAMR_LOOKUP_DOMAIN (-> SamrLookupDomainInSamServer) * Added real SAMR_ENUM_DOM_GROUPS (corresponding to SamrEnumerateGroupsInDomain). The existing one is just an alias for SamrQueryDisplayInformation (see below). * Added three extra info levels to SAMR_QUERY_DISPINFO. Info level 3 is what was previously SAMR_ENUM_DOM_GROUPS; info levels 4 and 5 are simple user/group list requests used by Win9x and I suspect (haven't checked) the "low speed connection" User Manager. * Added another two aliases for SAMR_QUERY_DISPINFO, opcodes 0x30 and 0x33. Usually the first is with info level 3 and the second 4 but there is some overlap so indeed these should be implemented as just aliases. * Return ERRDOS/ERRmoredata on extra data instead of STATUS_BUFFER_OVERFLOW for Win95's benefit. On a named pipe this results in an SMBreadX as usual. Still need to fix SAMR_QUERY_DOMAIN_INFO which has a hard-coded number of users and groups - which Win95 proceeds to truncate at. (This used to be commit 7d03e6e21908f3a759a4e65c5edd850622335e3e) --- source3/smbd/ipc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 31ae8e6fc0..c8c3b52194 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -187,9 +187,13 @@ static void send_trans_reply(char *outbuf, if (buffer_too_large) { +#if 0 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); +#endif + SCVAL(outbuf, smb_rcls, ERRDOS); + SSVAL(outbuf, smb_err, ERRmoredata); } copy_trans_params_and_data(outbuf, align, -- cgit From 869f9860ebe86a864daacd40115d432e55eebd68 Mon Sep 17 00:00:00 2001 From: Matthew Chapman Date: Wed, 24 Feb 1999 19:08:43 +0000 Subject: Return either STATUS_BUFFER_OVERFLOW or ERRDOS/ERRmoredata depending on whether the client supports 32-bit error codes. (This used to be commit cb5428308d6978f7bd76c1b878dd4a43135a274d) --- source3/smbd/ipc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c8c3b52194..a4d452b2a8 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -61,6 +61,7 @@ extern fstring global_myworkgroup; extern int Client; extern int smb_read_error; +extern uint32 global_client_caps; static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, @@ -187,13 +188,15 @@ static void send_trans_reply(char *outbuf, if (buffer_too_large) { -#if 0 - /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ - SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); -#endif - SCVAL(outbuf, smb_rcls, ERRDOS); - SSVAL(outbuf, smb_err, ERRmoredata); + if (global_client_caps & CAP_STATUS32) + { + /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ + SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SIVAL(outbuf, smb_rcls, 0x80000005); /* STATUS_BUFFER_OVERFLOW */ + } else { + SCVAL(outbuf, smb_rcls, ERRDOS); + SSVAL(outbuf, smb_err, ERRmoredata); + } } copy_trans_params_and_data(outbuf, align, -- cgit From c4241b56628469227f84f9d0b7589d9bc07d7bd3 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 12 Mar 1999 19:37:40 +0000 Subject: cli_setup_creds new arguments added. (This used to be commit 5fa3a3f710cfd3a51641d560a96bd08f92afca32) --- source3/smbd/password.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 7eed028a80..e1a4e66c40 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1114,7 +1114,9 @@ machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); return False; } - if(cli_nt_setup_creds(&cli, nt_pipe_fnum, trust_passwd) == False) { + if(cli_nt_setup_creds(&cli, nt_pipe_fnum, + cli.mach_acct, trust_passwd, SEC_CHAN_WKSTA) == False) + { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); cli_nt_session_close(&cli, nt_pipe_fnum); -- cgit From fda194255c156ce373d5f195e960bf8712fe4d67 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 19 Mar 1999 05:00:39 +0000 Subject: Beau Kuiper: provided patch so that passwords could only be changed by root if the ACB_PWLOCK bit is set (on a per-user basis). he also added an extra smbpasswd option so that this bit can be modified from command-line. (This used to be commit 534fe319d9de8da2ed7e911dbba3c7df08193efa) --- source3/smbd/chgpasswd.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 167fce6e8c..852d6aa618 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -571,6 +571,14 @@ BOOL pass_oem_change(char *user, &sampw, new_passwd, sizeof(new_passwd)); + /* now we check to see if we are actually allowed to change the + password. */ + + if (ret && (sampw->acct_ctrl & ACB_PWLOCK)) + { + ret = False; + } + /* * At this point we have the new case-sensitive plaintext * password in the fstring new_passwd. If we wanted to synchronise -- cgit From bd76e02ec43124e5666868e272b9b4bcfbccc99b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 19 Mar 1999 15:49:22 +0000 Subject: going to start adding inter-domain trust logons soon. (This used to be commit f9f594c03e220a0d902c5c3c5835948348b19fee) --- source3/smbd/password.c | 253 +++++++++++++++++++++++++----------------------- 1 file changed, 130 insertions(+), 123 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e1a4e66c40..68d75b933f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1018,151 +1018,158 @@ use this machine as the password server.\n")); /*********************************************************************** Do the same as security=server, but using NT Domain calls and a session - key from the machine password. + key from the workstation trust account password. ************************************************************************/ BOOL domain_client_validate( char *user, char *domain, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { - uint16 nt_pipe_fnum; - unsigned char local_challenge[8]; - unsigned char local_lm_response[24]; - unsigned char local_nt_reponse[24]; - unsigned char trust_passwd[16]; - NET_ID_INFO_CTR ctr; - NET_USER_INFO_3 info3; - struct cli_state cli; - uint32 smb_uid_low; - - /* - * Check that the requested domain is not our own machine name. - * If it is, we should never check the PDC here, we use our own local - * password file. - */ - - if(strequal( domain, global_myname)) { - DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); - return False; - } - - /* - * Next, check that the passwords given were encrypted. - */ - - if(((smb_apasslen != 24) && (smb_apasslen != 0)) || - ((smb_ntpasslen != 24) && (smb_ntpasslen != 0))) { - - /* - * Not encrypted - do so. - */ + uint16 nt_pipe_fnum; + unsigned char local_challenge[8]; + unsigned char local_lm_response[24]; + unsigned char local_nt_reponse[24]; + unsigned char trust_passwd[16]; + NET_ID_INFO_CTR ctr; + NET_USER_INFO_3 info3; + struct cli_state cli; + uint32 smb_uid_low; + + /* + * Check that the requested domain is not our own machine name. + * If it is, we should never check the PDC here, we use our own local + * password file. + */ + + if(strequal( domain, global_myname)) + { + DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); + return False; + } - DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); - generate_random_buffer( local_challenge, 8, False); - SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); - SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_reponse); - smb_apasslen = 24; - smb_ntpasslen = 24; - smb_apasswd = (char *)local_lm_response; - smb_ntpasswd = (char *)local_nt_reponse; - } else { + /* + * Next, check that the passwords given were encrypted. + */ - /* - * Encrypted - get the challenge we sent for these - * responses. - */ + if(((smb_apasslen != 24) && (smb_apasslen != 0)) || + ((smb_ntpasslen != 24) && (smb_ntpasslen != 0))) + { + /* + * Not encrypted - do so. + */ + + DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); + generate_random_buffer( local_challenge, 8, False); + SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); + SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_reponse); + smb_apasslen = 24; + smb_ntpasslen = 24; + smb_apasswd = (char *)local_lm_response; + smb_ntpasswd = (char *)local_nt_reponse; + } + else + { + /* + * Encrypted - get the challenge we sent for these + * responses. + */ - if (!last_challenge(local_challenge)) { - DEBUG(0,("domain_client_validate: no challenge done - password failed\n")); - return False; - } - } + if (!last_challenge(local_challenge)) + { + DEBUG(0,("domain_client_validate: no challenge done - password failed\n")); + return False; + } + } - /* - * Get the machine account password. - */ - if (!trust_get_passwd( trust_passwd, global_myworkgroup, global_myname)) - { - return False; - } + /* + * Get the workstation trust account password. + */ + if (!trust_get_passwd( trust_passwd, global_myworkgroup, global_myname)) + { + return False; + } - /* - * At this point, smb_apasswd points to the lanman response to - * the challenge in local_challenge, and smb_ntpasswd points to - * the NT response to the challenge in local_challenge. Ship - * these over the secure channel to a domain controller and - * see if they were valid. - */ + /* + * At this point, smb_apasswd points to the lanman response to + * the challenge in local_challenge, and smb_ntpasswd points to + * the NT response to the challenge in local_challenge. Ship + * these over the secure channel to a domain controller and + * see if they were valid. + */ if (!cli_connect_serverlist(&cli, lp_passwordserver())) { - DEBUG(0,("domain_client_validate: Domain password server not available.\n")); - return False; - } + DEBUG(0,("domain_client_validate: Domain password server not available.\n")); + return False; + } - /* - * Ok - we have an anonymous connection to the IPC$ share. - * Now start the NT Domain stuff :-). - */ + /* + * Ok - we have an anonymous connection to the IPC$ share. + * Now start the NT Domain stuff :-). + */ + + if(cli_nt_session_open(&cli, PIPE_NETLOGON, &nt_pipe_fnum) == False) { + DEBUG(0,("domain_client_validate: unable to open the domain client session to \ + machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); + cli_nt_session_close(&cli, nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } - if(cli_nt_session_open(&cli, PIPE_NETLOGON, &nt_pipe_fnum) == False) { - DEBUG(0,("domain_client_validate: unable to open the domain client session to \ -machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } + if(cli_nt_setup_creds(&cli, nt_pipe_fnum, + cli.mach_acct, trust_passwd, SEC_CHAN_WKSTA) == False) + { + DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ + %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); + cli_nt_session_close(&cli, nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } - if(cli_nt_setup_creds(&cli, nt_pipe_fnum, - cli.mach_acct, trust_passwd, SEC_CHAN_WKSTA) == False) - { - DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ -%s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } + /* We really don't care what LUID we give the user. */ + generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - /* We really don't care what LUID we give the user. */ - generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - - if(cli_nt_login_network(&cli, nt_pipe_fnum, domain, user, smb_uid_low, (char *)local_challenge, - ((smb_apasslen != 0) ? smb_apasswd : NULL), - ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), - &ctr, &info3) == False) { - DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } + if (!cli_nt_login_network(&cli, nt_pipe_fnum, domain, user, smb_uid_low, (char *)local_challenge, + ((smb_apasslen != 0) ? smb_apasswd : NULL), + ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), + &ctr, &info3)) + { + DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ + %s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); + cli_nt_session_close(&cli, nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } - /* - * Here, if we really want it, we have lots of info about the user in info3. - */ + /* + * Here, if we really want it, we have lots of info about the user in info3. + * LKCLXXXX - really important to check things like "is this user acct + * locked out / disabled" etc!!!! + */ #if 0 - /* - * We don't actually need to do this - plus it fails currently with - * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to - * send here. JRA. - */ + /* + * We don't actually need to do this - plus it fails currently with + * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to + * send here. JRA. + */ - if(cli_nt_logoff(&cli, nt_pipe_fnum, &ctr) == False) { - DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } + if (!cli_nt_logoff(&cli, nt_pipe_fnum, &ctr)) + { + DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ + %s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); + cli_nt_session_close(&cli, nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } #endif /* 0 */ - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return True; + cli_nt_session_close(&cli, nt_pipe_fnum); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return True; } -- cgit From 43a460075a39148060d4193fcb9c62bfa4acc737 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 25 Mar 1999 13:54:31 +0000 Subject: SAM database "set user info". ---------------------------- - removed DOM_RID4 - removed SAMR_UNKNOWN_32 - added SAMR_SET_USERINFO (opcode 0x32) - added level 0x1 to SAMR_QUERY_DOM_INFO (needed for create user) - fixed pwdb_gethexpwd() it was failing on XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - added mod_sam21pwd_entry() - preparing to call mod_sam21pwd_entry() - added "user session key" to user_struct.dc. this is md4(nt#) and is needed to decode user's clear-text passwords in SAMR_SET_USERINFO. - split code out in chgpasswd.c to decode 516 byte password buffers. (This used to be commit 2e58ed742435befe419aa366c4052019fede8c23) --- source3/smbd/chgpasswd.c | 61 +++++++++++++++++++++++++++++------------------- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 37 ++++++++++++++++++----------- source3/smbd/reply.c | 7 +++--- 4 files changed, 66 insertions(+), 41 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 852d6aa618..c22f268684 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -603,6 +603,42 @@ BOOL pass_oem_change(char *user, return ret; } +/*********************************************************** + decode a password buffer +************************************************************/ +BOOL decode_pw_buffer(const char buffer[516], char *new_passwd, + int new_passwd_size, BOOL nt_pass_set) +{ + /* + * The length of the new password is in the last 4 bytes of + * the data buffer. + */ + + uint32 new_pw_len = IVAL(buffer, 512); + if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) + { + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); + return False; + } + + if (nt_pass_set) + { + /* + * nt passwords are in unicode + */ + int uni_pw_len = new_pw_len; + new_pw_len /= 2; + unibuf_to_ascii(new_passwd, &buffer[512-uni_pw_len], new_pw_len); + } + else + { + memcpy(new_passwd, &buffer[512-new_pw_len], new_pw_len); + new_passwd[new_pw_len] = '\0'; + } + + return True; +} + /*********************************************************** Code to check the OEM hashed password. @@ -619,7 +655,6 @@ BOOL check_oem_password(char *user, static uchar null_pw[16]; static uchar null_ntpw[16]; struct smb_passwd *smbpw = NULL; - int new_pw_len; uchar new_ntp16[16]; uchar unenc_old_ntpw[16]; uchar new_p16[16]; @@ -681,33 +716,11 @@ BOOL check_oem_password(char *user, */ SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - - new_pw_len = IVAL(lmdata, 512); - if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) + if (!decode_pw_buffer(lmdata, new_passwd, new_passwd_size, nt_pass_set)) { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } - if (nt_pass_set) - { - /* - * nt passwords are in unicode - */ - int uni_pw_len = new_pw_len; - new_pw_len /= 2; - unibuf_to_ascii(new_passwd, &lmdata[512-uni_pw_len], new_pw_len); - } - else - { - memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); - new_passwd[new_pw_len] = '\0'; - } - /* * To ensure we got the correct new password, hash it and * use it as a key to test the passed old password. diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a4d452b2a8..5001b16b35 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1680,7 +1680,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param * Older versions of Windows seem to do this. */ - if (password_ok(user, pass1,strlen(pass1),NULL) && + if (password_ok(user, pass1,strlen(pass1),NULL, NULL) && chgpasswd(user,pass1,pass2,False)) { SSVAL(*rparam,0,NERR_Success); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 68d75b933f..11fe69b103 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -156,7 +156,7 @@ register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest) +uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -205,6 +205,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, vuser->guest = guest; fstrcpy(vuser->name,unix_name); fstrcpy(vuser->requested_name,requested_name); + memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key)); vuser->n_sids = 0; vuser->sids = NULL; @@ -412,7 +413,7 @@ return True if the password is correct, False otherwise BOOL pass_check_smb(char *user, char *domain, uchar *chal, uchar *lm_pwd, uchar *nt_pwd, - struct passwd *pwd) + struct passwd *pwd, uchar user_sess_key[16]) { struct passwd *pass; struct smb_passwd *smb_pass; @@ -467,6 +468,14 @@ BOOL pass_check_smb(char *user, char *domain, if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) { + if (user_sess_key != NULL) + { + mdfour(user_sess_key, smb_pass->smb_nt_passwd, 16); +#ifdef DEBUG_PASSWORD + DEBUG(100,("user session key: ")); + dump_data(100, user_sess_key, 16); +#endif + } return(True); } @@ -479,7 +488,8 @@ check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) +BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, + uchar user_sess_key[16]) { if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { @@ -493,7 +503,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) } return pass_check_smb(user, global_myworkgroup, - challenge, (uchar *)password, (uchar *)password, pwd); + challenge, (uchar *)password, (uchar *)password, pwd, user_sess_key); } return pass_check(user, password, pwlen, pwd, @@ -536,7 +546,8 @@ BOOL user_ok(char *user,int snum) /**************************************************************************** validate a group username entry. Return the username or NULL ****************************************************************************/ -static char *validate_group(char *group,char *password,int pwlen,int snum) +static char *validate_group(char *group,char *password,int pwlen,int snum, + uchar user_sess_key[16]) { #if defined(HAVE_NETGROUP) && defined(HAVE_GETNETGRENT) && defined(HAVE_SETNETGRENT) && defined(HAVE_ENDNETGRENT) { @@ -545,7 +556,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL)) { + password_ok(user,password,pwlen,NULL, user_sess_key)) { endnetgrent(); return(user); } @@ -567,7 +578,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; fstrcpy(name,*member); if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL)) + password_ok(name,password,pwlen,NULL, user_sess_key)) return(&name[0]); member++; } @@ -580,7 +591,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (pwd = getpwent ()) { if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { /* This Entry have PASSWORD and same GID then check pwd */ - if (password_ok(NULL, password, pwlen, pwd)) { + if (password_ok(NULL, password, pwlen, pwd, user_sess_key)) { fstrcpy(tm, pwd->pw_name); endpwent (); return tm; @@ -633,14 +644,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL); + ok = password_ok(user,password, pwlen, NULL, vuser->dc.user_sess_key); if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); } /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->name,snum) && - password_ok(vuser->name, password, pwlen, NULL)) { + password_ok(vuser->name, password, pwlen, NULL, vuser->dc.user_sess_key)) { fstrcpy(user, vuser->name); vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); @@ -664,7 +675,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstrcpy(user2,auser); if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL)) { + if (password_ok(user2,password, pwlen, NULL, vuser->dc.user_sess_key)) { ok = True; fstrcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); @@ -703,7 +714,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, { if (*auser == '@') { - auser = validate_group(auser+1,password,pwlen,snum); + auser = validate_group(auser+1,password,pwlen,snum, vuser->dc.user_sess_key); if (auser) { ok = True; @@ -716,7 +727,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstring user2; fstrcpy(user2,auser); if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL)) + password_ok(user2,password,pwlen,NULL, vuser->dc.user_sess_key)) { ok = True; fstrcpy(user,user2); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 694cf3cdd5..57742003ff 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -511,6 +511,7 @@ reply to a session setup command int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 sess_vuid; + uchar user_sess_key[16]; int gid; int uid; int smb_bufsize; @@ -706,13 +707,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if(smb_ntpasslen) { - if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) + if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key)) DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); else valid_nt_password = True; } - if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) + if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key)) { if (lp_security() >= SEC_USER) { @@ -791,7 +792,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From d330c907bdc5d8e3c242cea76dfafaae84041270 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Apr 1999 05:22:58 +0000 Subject: Ken McDonell from SGI was interested in adding some profiling capabilities to Samba so that Samba could talk to the SGI PCP (Performance Co-Pilot) apps. This change adds a profiling shared memory area and uses it to count two fairly trivial things, the number of uid switches and the number of SMB packets processes. To add more just edit include/profile.h and then increment it at the right place. I've also added a -P switch to smbstatus to dump the profile area. (This used to be commit ef3d61a80ad0b87c196a63ef2bd4fe8fc3863bd0) --- source3/smbd/process.c | 4 ++++ source3/smbd/server.c | 9 ++++++++- source3/smbd/uid.c | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a38e6da683..420598157f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -545,6 +545,10 @@ void process_smb(char *inbuf, char *outbuf) int32 len = smb_len(inbuf); int nread = len + 4; +#ifdef WITH_PROFILE + profile_p->smb_count++; +#endif + if (trans_num == 0) { /* on the first packet, check the global hosts allow/ hosts deny parameters before doing any parsing of the packet diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9b397bcdeb..dcc53cb8d0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -618,7 +618,14 @@ static void usage(char *pname) return(-1); init_structs(); - + +#ifdef WITH_PROFILE + if (!profile_setup(False)) { + DEBUG(0,("ERROR: failed to setup profiling\n")); + return -1; + } +#endif + /* * Set the machine NETBIOS name if not already * set from the config file. diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index f76fa49d56..b2407ed5fc 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -109,6 +109,10 @@ static BOOL become_uid(uid_t uid) current_user.uid = uid; +#ifdef WITH_PROFILE + profile_p->uid_changes++; +#endif + return(True); } -- cgit From d4ba8a3fb31698603cb2da740a0e434dd43eb48e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 05:40:28 +0000 Subject: Use VFS operations for file I/O. Changed calls to dos_{opendir,readdir} to vfs_{opendir,readdir} equivalents. (This used to be commit 5051a210619374639121124e32d24217255e992e) --- source3/smbd/dir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index dcf1d158b4..52d271e284 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -470,7 +470,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (dos_stat(pathreal,&sbuf) != 0) + if (conn->vfs_ops.stat(dos_to_unix(pathreal, False), &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]\n",path)); continue; @@ -518,7 +518,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - DIR *p = dos_opendir(name); + DIR *p = conn->vfs_ops.opendir(name); int used=0; if (!p) return(NULL); @@ -530,7 +530,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; - while ((n = dos_readdirname(p))) + while ((n = vfs_readdirname(conn, p))) { int l = strlen(n)+1; -- cgit From 5bdddf2462f23a8752a547e8adb61944d7899f42 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 05:46:40 +0000 Subject: Use VFS operations for file I/O. Pass files_struct and connection_struct to read_predict() and do_read_prediction() functions, respectively. (This used to be commit 6479abc5b985981f571cb1ee16a0dbb843fcd270) --- source3/smbd/predict.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index 5f015139cf..f51e54a568 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -42,7 +42,7 @@ extern time_t smb_last_time; /**************************************************************************** handle read prediction on a file ****************************************************************************/ -ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) +ssize_t read_predict(files_struct *fsp, int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) { ssize_t ret = 0; ssize_t possible = rp_length - (offset - rp_offset); @@ -70,7 +70,7 @@ ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) /* Find the end of the file - ensure we don't read predict beyond it. */ - if(sys_fstat(fd,&rp_stat) < 0) + if(fsp->conn->vfs_ops.fstat(fd,&rp_stat) < 0) { DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); predict_skip = True; @@ -95,7 +95,7 @@ ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) /**************************************************************************** pre-read some data ****************************************************************************/ -void do_read_prediction(void) +void do_read_prediction(connection_struct *conn) { static size_t readsize = 0; @@ -134,13 +134,13 @@ void do_read_prediction(void) } } - if (sys_lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { + if (conn->vfs_ops.lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { rp_fd = -1; rp_predict_fd = -1; return; } - rp_length = read(rp_fd,rp_buffer,rp_predict_length); + rp_length = conn->vfs_ops.read(rp_fd,rp_buffer,rp_predict_length); rp_time = time(NULL); if (rp_length < 0) rp_length = 0; -- cgit From 10858bba8e790eeff1d8bfb60733cff65fca70c9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 05:57:16 +0000 Subject: Use VFS operations for file I/O. Changed arg to fd_attempt_close() from fd to fsp_struct. (This used to be commit c40124bc9a2ebccf0bb56b1fafa81a551d934aa5) --- source3/smbd/open.c | 54 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6658b8926f..da5303fc5a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -144,10 +144,17 @@ static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ -uint16 fd_attempt_close(file_fd_struct *fd_ptr) +uint16 fd_attempt_close(files_struct *fsp) { extern struct current_user current_user; - uint16 ret_ref = fd_ptr->ref_count; + file_fd_struct *fd_ptr = fsp->fd_ptr; + uint16 ret_ref; + + if (fd_ptr != NULL) { + ret_ref = fd_ptr->ref_count; + } else { + return 0; + } DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n", fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, @@ -161,11 +168,11 @@ uint16 fd_attempt_close(file_fd_struct *fd_ptr) if(fd_ptr->ref_count == 0) { if(fd_ptr->fd != -1) - close(fd_ptr->fd); + fsp->conn->vfs_ops.close(fd_ptr->fd); if(fd_ptr->fd_readonly != -1) - close(fd_ptr->fd_readonly); + fsp->conn->vfs_ops.close(fd_ptr->fd_readonly); if(fd_ptr->fd_writeonly != -1) - close(fd_ptr->fd_writeonly); + fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly); /* * Delete this fd_ptr. */ @@ -325,7 +332,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * open fd table. */ if(sbuf == 0) { - if(dos_stat(fname, &statbuf) < 0) { + if(conn->vfs_ops.stat(dos_to_unix(fname,False), &statbuf) < 0) { if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); @@ -423,7 +430,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fd_ptr->real_open_flags = O_RDWR; /* Set the flags as needed without the read/write modes. */ open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); + fd_ptr->fd = conn->vfs_ops.open(fname, open_flags|O_RDWR, mode); /* * On some systems opening a file for R/W access on a read only * filesystems sets errno to EROFS. @@ -434,7 +441,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if((fd_ptr->fd == -1) && (errno == EACCES)) { #endif /* EROFS */ if(accmode != O_RDWR) { - fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); + fd_ptr->fd = conn->vfs_ops.open(fname, open_flags|accmode, mode); fd_ptr->real_open_flags = accmode; } } @@ -448,9 +455,10 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (sys_disk_free(dname,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { - if(fd_attempt_close(fd_ptr) == 0) - dos_unlink(fname); + if (conn->vfs_ops.disk_free(dname,&dum1,&dum2,&dum3) < + (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { + if(fd_attempt_close(fsp) == 0) + conn->vfs_ops.unlink(fname); fsp->fd_ptr = 0; errno = ENOSPC; return; @@ -462,7 +470,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); + fd_attempt_close(fsp); check_for_pipe(fname); return; } @@ -471,12 +479,12 @@ static void open_file(files_struct *fsp,connection_struct *conn, { if(sbuf == 0) { /* Do the fstat */ - if(sys_fstat(fd_ptr->fd, &statbuf) == -1) { + if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) { /* Error - backout !! */ DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", fd_ptr->fd, fname,strerror(errno))); /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); + fd_attempt_close(fsp); return; } sbuf = &statbuf; @@ -525,7 +533,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { DEBUG(3,("Writing postscript line\n")); - write_file(fsp,"%!\n",3); + conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3); } DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -719,16 +727,17 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, /**************************************************************************** open a file with a share mode ****************************************************************************/ - -void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, - mode_t mode,int oplock_request, int *Access,int *action) +void open_file_shared(files_struct *fsp, connection_struct *conn, + char *fname, int share_mode, int ofun, + mode_t mode, int oplock_request, int *Access, + int *action) { int flags=0; int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); SMB_STRUCT_STAT sbuf; - BOOL file_existed = dos_file_exist(fname,&sbuf); + BOOL file_existed = vfs_file_exist(conn, dos_to_unix(fname,False), &sbuf); BOOL share_locked = False; BOOL fcbopen = False; int token; @@ -1015,7 +1024,8 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Create the directory. */ - if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 0) { + if(conn->vfs_ops.mkdir(dos_to_unix(fname,False), + unix_mode(conn,aDIR)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -1027,7 +1037,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Check that it *was* a directory. */ - if(dos_stat(fname, &st) < 0) { + if(conn->vfs_ops.stat(dos_to_unix(fname,False), &st) < 0) { DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -1101,7 +1111,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) if(!lp_share_modes(SNUM(conn))) return True; - if (dos_stat(fname,&sbuf) == -1) return(True); + if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) return(True); dev = sbuf.st_dev; inode = sbuf.st_ino; -- cgit From afc00dbd6f1c7281893ea55f4cca0bdb483f0c75 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 06:22:22 +0000 Subject: Call VFS initialisation, share connect and share disconnect functions. Initialise VFS function pointers with symbols from the 'vfs object' file, use disk pointers otherwise. Added a hook to check for a 'default' VFS share (like the [homes] section). Currently empty - I'm unsure whether this will be useful or not. (This used to be commit 15805164fe77b127372eba1ec51c70758467adee) --- source3/smbd/service.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4dd3cb4d97..8202294293 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -144,6 +144,11 @@ int find_service(char *service) } } + /* Check for default vfs service? Unsure whether to implement this */ + if (iService < 0) + { + } + /* just possibly it's a default service? */ if (iService < 0) { @@ -340,7 +345,24 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->veto_oplock_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); - + + /* Initialise VFS function pointers */ + + if (*lp_vfsobj(SNUM(conn))) { + + /* Loadable object file */ + + if (vfs_init_custom(conn) < 0) { + return NULL; + } + + } else { + + /* Normal share - initialise with disk access functions */ + + vfs_init_default(conn); + } + #ifdef HAVE_GETGRNAM if (*lp_force_group(snum)) { struct group *gptr; @@ -492,6 +514,14 @@ connection_struct *make_connection(char *service,char *user,char *password, int dbgtext( "(uid=%d, gid=%d) ", (int)conn->uid, (int)conn->gid ); dbgtext( "(pid %d)\n", (int)getpid() ); } + + /* Invoke make connection hook */ + + if (conn->vfs_ops.connect) { + if (conn->vfs_ops.connect(conn, service, user) < 0) { + return NULL; + } + } return(conn); } @@ -511,6 +541,10 @@ void close_cnum(connection_struct *conn, uint16 vuid) remote_machine,client_addr(Client), lp_servicename(SNUM(conn)))); + if (conn->vfs_ops.disconnect != NULL) { + conn->vfs_ops.disconnect(conn, lp_servicename(SNUM(conn))); + } + yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); -- cgit From 6d5ef2e92995df1cbf5cd3d7c6a33fe55cedb311 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 06:25:13 +0000 Subject: Use VFS operations for file I/O. (This used to be commit cfddbdb62485256a947a30e04c753200451cbe1c) --- source3/smbd/dosmode.c | 10 ++-- source3/smbd/filename.c | 7 ++- source3/smbd/files.c | 5 +- source3/smbd/ipc.c | 2 +- source3/smbd/nttrans.c | 26 ++++---- source3/smbd/reply.c | 153 +++++++++++++++++++++++++----------------------- source3/smbd/trans2.c | 33 ++++++----- 7 files changed, 126 insertions(+), 110 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index b74e11e643..e6f1dc7206 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -148,7 +148,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * if (!st) { st = &st1; - if (dos_stat(fname,st)) return(-1); + if (conn->vfs_ops.stat(dos_to_unix(fname,False),st)) return(-1); } if (S_ISDIR(st->st_mode)) dosmode |= aDIR; @@ -186,7 +186,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * unixmode |= tmp; } - return(dos_chmod(fname,unixmode)); + return(conn->vfs_ops.chmod(fname,unixmode)); } @@ -202,7 +202,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(dos_utime(fname, times) == 0) + if(conn->vfs_ops.utime(dos_to_unix(fname, False), times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -217,7 +217,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(dos_stat(fname,&sb) != 0) + if(conn->vfs_ops.stat(dos_to_unix(fname,False),&sb) != 0) return -1; /* Check if we have write access. */ @@ -230,7 +230,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(False); - ret = dos_utime(fname, times); + ret = conn->vfs_ops.utime(dos_to_unix(fname, False), times); unbecome_root(False); } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 83e6fe092e..913d0b367e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -441,7 +441,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (dos_stat(name,&st) == 0) { + if (conn->vfs_ops.stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -509,7 +509,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Check if the name exists up to this point. */ - if (dos_stat(name, &st) == 0) { + + if (conn->vfs_ops.stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -661,7 +662,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (dos_lstat(name,&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 3a41c83766..8aca336bf8 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -340,13 +340,12 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL)) { - sync_file(conn,fsp); + if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL)){ + conn->vfs_ops.sync(conn, fsp); } } } - /**************************************************************************** free up a fd_ptr ****************************************************************************/ diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 5001b16b35..cdbb4416af 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2005,7 +2005,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha !become_service(fconn,True)) break; - if (dos_rename(fsp->fsp_name,name) == 0) { + if (conn->vfs_ops.rename(dos_to_unix(fsp->fsp_name,False),name) == 0) { string_set(&fsp->fsp_name,name); } break; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 52a1005397..923de7a197 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -700,8 +700,8 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, - unixmode, &smb_action); + open_directory(fsp, conn, fname, smb_ofun, unixmode, + &smb_action); restore_case_semantics(file_attributes); @@ -727,7 +727,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - open_file_shared(fsp,conn,fname,smb_open_mode, + open_file_shared(fsp,conn,fname,smb_open_mode, smb_ofun,unixmode, oplock_request,&rmode,&smb_action); @@ -751,7 +751,9 @@ int reply_ntcreate_and_X(connection_struct *conn, if(errno == EISDIR) { oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + open_directory(fsp, conn, fname, + smb_ofun, unixmode, + &smb_action); if(!fsp->open) { file_free(fsp); @@ -774,13 +776,15 @@ int reply_ntcreate_and_X(connection_struct *conn, } if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), + &sbuf) != 0) { close_directory(fsp); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) + != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1006,8 +1010,8 @@ static int call_nt_transact_create(connection_struct *conn, * Ordinary file case. */ - open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun, + unixmode,oplock_request,&rmode,&smb_action); if (!fsp->open) { if((errno == ENOENT) && bad_path) { @@ -1021,7 +1025,7 @@ static int call_nt_transact_create(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); @@ -1329,7 +1333,7 @@ void process_pending_change_notify_queue(time_t t) continue; } - if(dos_stat(fsp->fsp_name, &st) < 0) { + if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &st) < 0) { DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \ Error was %s.\n", fsp->fsp_name, strerror(errno) )); /* @@ -1408,7 +1412,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, * Store the current timestamp on the directory we are monitoring. */ - if(dos_stat(fsp->fsp_name, &st) < 0) { + if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &st) < 0) { DEBUG(0,("call_nt_transact_notify_change: Unable to stat name = %s. \ Error was %s\n", fsp->fsp_name, strerror(errno) )); free((char *)cnbp); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 57742003ff..59a883f2d8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -625,7 +625,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int domain,skip_string(p,1),skip_string(p,2))); } - DEBUG(3,("sesssetupX:name=[%s]\n",user)); /* If name ends in $ then I think it's asking about whether a */ @@ -648,7 +647,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } strlower(user); - /* * In share level security, only overwrite sesssetup_use if * it's a non null-session share. Helps keep %U and %G @@ -657,7 +655,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if((lp_security() != SEC_SHARE) || (*user && !guest)) pstrcpy(sesssetup_user,user); - reload_services(True); /* @@ -668,7 +665,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstrcpy( orig_user, user); - map_nt_and_unix_username(domain, user); + map_nt_and_unix_username(domain, user); add_session_user(user); @@ -758,7 +755,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } } - /* it's ok - setup a reply */ if (Protocol < PROTOCOL_NT1) { set_message(outbuf,3,0,True); @@ -897,7 +893,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0) + if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; @@ -998,7 +994,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz int outsize = 0; SMB_BIG_UINT dfree,dsize,bsize; - sys_disk_free(".",&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -1346,8 +1342,9 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,aARCH); - open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - unixmode, oplock_request,&rmode,NULL); + open_file_shared(fsp, conn, fname, share_mode, + (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), + unixmode, oplock_request, &rmode, NULL); if (!fsp->open) { @@ -1360,7 +1357,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1450,8 +1447,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unixmode = unix_mode(conn,smb_attr | aARCH); - open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode, - oplock_request, &rmode,&smb_action); + open_file_shared(fsp, conn, fname, smb_mode, smb_ofun, unixmode, + oplock_request, &rmode, &smb_action); if (!fsp->open) { @@ -1464,7 +1461,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1601,8 +1598,9 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file in dos compatibility share mode. */ - open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - ofun, unixmode, oplock_request, NULL, NULL); + open_file_shared(fsp, conn, fname, + SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + ofun, unixmode, oplock_request, NULL, NULL); if (!fsp->open) { @@ -1673,8 +1671,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL); + open_file_shared(fsp,conn,fname2, + SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + (FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL), + unixmode, oplock_request, NULL, NULL); if (!fsp->open) { @@ -1717,7 +1717,7 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return(False); - if (dos_lstat(fname,&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); if (!lp_delete_readonly(SNUM(conn))) { @@ -1774,10 +1774,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) + if (can_delete(directory,conn,dirtype) && !conn->vfs_ops.unlink(directory)) count++; if (!count) - exists = dos_file_exist(directory,NULL); + exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); } else { void *dirptr = NULL; char *dname; @@ -1807,7 +1807,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; - if (!dos_unlink(fname)) count++; + if (!conn->vfs_ops.unlink(fname)) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); } CloseDir(dirptr); @@ -1900,7 +1900,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -1924,11 +1924,11 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #if USE_READ_PREDICTION if (!fsp->can_write) - predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread); + predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread); #endif /* USE_READ_PREDICTION */ if ((nread-predict) > 0) { - if(seek_file(fsp,startpos + predict) == -1) { + if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) { DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); ret = 0; seek_fail = True; @@ -1936,7 +1936,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s } if(!seek_fail) - ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client, + ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL, (SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } @@ -2039,8 +2039,9 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); - if (numtoread > 0) + if (numtoread > 0) { nread = read_file(fsp,data,startpos,numtoread); + } if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2092,15 +2093,15 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); - nread = read_file(fsp,data,startpos,smb_maxcnt); - + nread = read_file(fsp,data,smb_maxcnt); + if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - + DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n", fsp->fnum, smb_mincnt, smb_maxcnt, nread ) ); @@ -2184,8 +2185,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s tcount,nwritten,numtowrite)); } - nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0, - startpos+nwritten); + nwritten = vfs_transfer_file(Client, NULL, -1, fsp, + (SMB_OFF_T)numtowrite,NULL,0, + startpos+nwritten); total_written += nwritten; /* Set up outbuf to return the correct return */ @@ -2199,7 +2201,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s } if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + conn->vfs_ops.sync(conn, fsp); DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", fsp->fnum, (double)startpos, numtowrite, total_written)); @@ -2249,7 +2251,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum nwritten = write_file(fsp,data,numtowrite); if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); + conn->vfs_ops.sync(conn, fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2302,7 +2304,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i nwritten = write_file(fsp,data,numtowrite); if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); + conn->vfs_ops.sync(conn, fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2386,7 +2388,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng fsp->fnum, numtowrite, nwritten)); if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + conn->vfs_ops.sync(conn, fsp); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2418,7 +2420,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, umode = SEEK_SET; break; } - if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) + if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); fsp->pos = res; @@ -2448,7 +2450,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { file_sync_all(conn); } else { - sync_file(conn,fsp); + conn->vfs_ops.sync(conn, fsp); } DEBUG(3,("flush\n")); @@ -2914,7 +2916,8 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) - ret = dos_mkdir(directory,unix_mode(conn,aDIR)); + ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), + unix_mode(conn,aDIR)); if (ret < 0) { @@ -2937,11 +2940,11 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Static function used by reply_rmdir to delete an entire directory tree recursively. ****************************************************************************/ -static BOOL recursive_rmdir(char *directory) +static BOOL recursive_rmdir(connection_struct *conn, char *directory) { char *dname = NULL; BOOL ret = False; - void *dirptr = OpenDir(NULL, directory, False); + void *dirptr = OpenDir(conn, directory, False); if(dirptr == NULL) return True; @@ -2965,7 +2968,7 @@ static BOOL recursive_rmdir(char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(dos_lstat(fullname, &st) != 0) + if(conn->vfs_ops.lstat(fullname, &st) != 0) { ret = True; break; @@ -2973,18 +2976,18 @@ static BOOL recursive_rmdir(char *directory) if(st.st_mode & S_IFDIR) { - if(recursive_rmdir(fullname)!=0) + if(recursive_rmdir(conn, fullname)!=0) { ret = True; break; } - if(dos_rmdir(fullname) != 0) + if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0) { ret = True; break; } } - else if(dos_unlink(fullname) != 0) + else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0) { ret = True; break; @@ -3011,7 +3014,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { dptr_closepath(directory,SVAL(inbuf,smb_pid)); - ok = (dos_rmdir(directory) == 0); + ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0); if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn))) { /* Check to see if the only thing in this directory are @@ -3056,24 +3059,25 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(dos_lstat(fullname, &st) != 0) + if(conn->vfs_ops.lstat(fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) { if(lp_recursive_veto_delete(SNUM(conn))) { - if(recursive_rmdir(fullname) != 0) + DEBUG(0, ("ERROR: recursive_rmdir()\n")); + if(recursive_rmdir(conn, fullname) != 0) break; } - if(dos_rmdir(fullname) != 0) + if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0) break; } - else if(dos_unlink(fullname) != 0) + else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0) break; } CloseDir(dirptr); /* Retry the rmdir */ - ok = (dos_rmdir(directory) == 0); + ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0); } else CloseDir(dirptr); @@ -3178,7 +3182,7 @@ static BOOL can_rename(char *fname,connection_struct *conn) if (!CAN_WRITE(conn)) return(False); - if (dos_lstat(fname,&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); return(True); @@ -3298,21 +3302,23 @@ int rename_internals(connection_struct *conn, */ if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !dos_rename(directory,newname)) + !conn->vfs_ops.rename(dos_to_unix(directory,False), + newname)) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !dos_file_exist(newname,NULL) && - !dos_rename(directory,newname)) + !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) && + !conn->vfs_ops.rename(dos_to_unix(directory,False), + newname)) count++; } DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); - if (!count) exists = dos_file_exist(directory,NULL); - if (!count && exists && dos_file_exist(newname,NULL)) { + if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); + if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) { exists = True; error = ERRrename; } @@ -3353,13 +3359,13 @@ int rename_internals(connection_struct *conn, continue; } - if (!replace_if_exists && dos_file_exist(destname,NULL)) { - DEBUG(6,("dos_file_exist %s\n", destname)); + if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) { + DEBUG(6,("file_exist %s\n", destname)); error = 183; continue; } - if (!dos_rename(fname,destname)) + if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3428,15 +3434,16 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!dos_file_exist(src,&st)) + if (!vfs_file_exist(conn,dos_to_unix(src,False),&st)) return(False); fsp1 = file_new(); - if (!fsp1) + if (!fsp1) return(False); - open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); + open_file_shared(fsp1, conn, src, + SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_RDONLY), + (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), 0, 0, &Access, &action); if (!fsp1->open) { file_free(fsp1); @@ -3451,8 +3458,9 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, close_file(fsp1,False); return(False); } - open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,st.st_mode,0,&Access,&action); + open_file_shared(fsp2, conn, dest, + SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_WRONLY), + ofun, st.st_mode, 0, &Access, &action); if (!fsp2->open) { close_file(fsp1,False); @@ -3461,7 +3469,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { + if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", strerror(errno) )); /* @@ -3473,8 +3481,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if (st.st_size) - ret = transfer_file(fsp1->fd_ptr->fd, - fsp2->fd_ptr->fd,st.st_size,NULL,0,0); + ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0); close_file(fsp1,False); close_file(fsp2,False); @@ -3558,7 +3565,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (resolve_wildcards(directory,newname) && copy_file(directory,newname,conn,ofun, count,target_is_directory)) count++; - if (!count) exists = dos_file_exist(directory,NULL); + if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); } else { void *dirptr = NULL; char *dname; @@ -3862,7 +3869,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, { size_t N = MIN(max_per_packet,tcount-total_read); - nread = read_file(fsp,data,startpos,N); + nread = read_file(fsp,data,N); if (nread <= 0) nread = 0; @@ -3925,7 +3932,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s nwritten = write_file(fsp,data,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + conn->vfs_ops.sync(conn, fsp); if(nwritten < (ssize_t)numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -4038,7 +4045,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz nwritten = write_file(fsp,data,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + conn->vfs_ops.sync(conn, fsp); if (nwritten < (ssize_t)numtowrite) { @@ -4143,7 +4150,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si CHECK_ERROR(fsp); /* Do an fstat on this file */ - if(sys_fstat(fsp->fd_ptr->fd, &sbuf)) + if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(conn,fsp->fsp_name,&sbuf); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f041393dab..8a182399e7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -247,7 +247,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -374,7 +374,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (dos_stat(pathreal,&sbuf) != 0) + if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); continue; @@ -1072,7 +1072,7 @@ static int call_trans2qfsinfo(connection_struct *conn, DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(dos_stat(".",&st)!=0) { + if(conn->vfs_ops.stat(".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return (ERROR(ERRSRV,ERRinvdevice)); } @@ -1085,7 +1085,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; - sys_disk_free(".",&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); SIVAL(pdata,l1_cSectorUnit,bsize/512); SIVAL(pdata,l1_cUnit,dsize); @@ -1158,7 +1158,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { SMB_BIG_UINT dfree,dsize,bsize; data_len = 24; - sys_disk_free(".",&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize); SIVAL(pdata,0,dsize); SIVAL(pdata,8,dfree); SIVAL(pdata,16,bsize/512); @@ -1254,7 +1254,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, */ fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { + if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && + conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1271,11 +1272,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); delete_pending = fsp->fd_ptr->delete_on_close; @@ -1286,7 +1287,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname = &fname1[0]; pstrcpy(fname,¶ms[6]); unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { + if (!check_name(fname,conn) || + (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False), + &sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1514,7 +1517,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, */ fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&st); - if (!check_name(fname,conn) || (!VALID_STAT(st) && dos_stat(fname,&st))) { + if (!check_name(fname,conn) || (!VALID_STAT(st) && + conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1533,7 +1537,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; fd = fsp->fd_ptr->fd; - if (sys_fstat(fd,&st) != 0) { + if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1554,7 +1558,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) { + if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1771,7 +1775,6 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) * goes away. */ fsp->fd_ptr->delete_on_close = delete_on_close; - unlock_share_entry(fsp->conn, dev, inode, token); DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", @@ -1834,6 +1837,7 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) { if (fd == -1) { +DEBUG(0, ("@@@ 23 @@@\n")); fd = dos_open(fname,O_RDWR,0); if (fd == -1) { @@ -1876,7 +1880,8 @@ static int call_trans2mkdir(connection_struct *conn, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory,conn)) - ret = dos_mkdir(directory,unix_mode(conn,aDIR)); + ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), + unix_mode(conn,aDIR)); if(ret < 0) { -- cgit From a107d80596bb98c687b6ccdb4363c8d318c3c336 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 06:37:07 +0000 Subject: Wrapped up all VFS disk I/O functions for portability. I remember tridge telling me why this needed to be done but I have since forgotten. (-: (This used to be commit 6e607ef760bd2c0eb3ac31252601ab30de626270) --- source3/smbd/vfs-wrap.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 source3/smbd/vfs-wrap.c (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c new file mode 100644 index 0000000000..b8325dd1e7 --- /dev/null +++ b/source3/smbd/vfs-wrap.c @@ -0,0 +1,180 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Wrap disk only vfs functions to sidestep dodgy compilers. + Copyright (C) Tim Potter 1998 + + 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" + +/* Disk operations */ + +SMB_BIG_UINT vfswrap_disk_free(char *path, SMB_BIG_UINT *bsize, + SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + SMB_BIG_UINT result; + + result = sys_disk_free(path, bsize, dfree, dsize); + return result; +} + +/* Directory operations */ + +DIR *vfswrap_opendir(char *fname) +{ + DIR *result; + + result = opendir(fname); + return result; +} + +struct dirent *vfswrap_readdir(DIR *dirp) +{ + struct dirent *result; + + result = readdir(dirp); + return result; +} + +int vfswrap_mkdir(char *path, mode_t mode) +{ + int result; + + result = mkdir(path, mode); + return result; +} + +int vfswrap_rmdir(char *path) +{ + int result; + + result = rmdir(path); + return result; +} + +/* File operations */ + +int vfswrap_open(char *fname, int flags, mode_t mode) +{ + int result; + + result = sys_open(fname, flags, mode); + return result; +} + +int vfswrap_close(int fd) +{ + int result; + + result = close(fd); + return result; +} + +ssize_t vfswrap_read(int fd, char *data, size_t n) +{ + ssize_t result; + + result = read(fd, data, n); + return result; +} + +ssize_t vfswrap_write(int fd, char *data, size_t n) +{ + ssize_t result; + + result = write(fd, data, n); + return result; +} + +SMB_OFF_T vfswrap_lseek(int filedes, SMB_OFF_T offset, int whence) +{ + SMB_OFF_T result; + + result = sys_lseek(filedes, offset, whence); + return result; +} + +int vfswrap_rename(char *old, char *new) +{ + int result; + + result = rename(old, new); + return result; +} + +void vfswrap_sync_file(struct connection_struct *conn, files_struct *fsp) +{ + return sys_sync_file(conn, fsp); +} + +int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) +{ + int result; + + result = sys_stat(fname, sbuf); + return result; +} + +int vfswrap_fstat(int fd, SMB_STRUCT_STAT *sbuf) +{ + int result; + + result = sys_fstat(fd, sbuf); + return result; +} + +int vfswrap_lstat(char *path, + SMB_STRUCT_STAT *sbuf) +{ + int result; + + result = sys_lstat(path, sbuf); + return result; +} + +BOOL vfswrap_fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, + int type) +{ + BOOL result; + + result = fcntl_lock(fd, op, offset, count, type); + return result; +} + +int vfswrap_unlink(char *path) +{ + int result; + + result = unlink(path); + return result; +} + +int vfswrap_chmod(char *path, mode_t mode) +{ + int result; + + result = chmod(path, mode); + return result; +} + +int vfswrap_utime(char *path, struct utimbuf *times) +{ + int result; + + result = utime(path, times); + return result; +} -- cgit From e2cd60b4e10d2d3d8e3a062228d6637416a2d987 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 06:39:45 +0000 Subject: Wrote VFS initialisation routines. Converted some useful routines from doscalls.c and changed them to use VFS I/O functions: dos_file_exist dos_read_data dos_write_data dos_transfer_file dos_readdirname Some of these functions have been #ifdef'ed out of doscalls.c as they are not used anywhere else. Not sure whether they should be deleted or not. The remaining dos_* calls seem to be used by clients and for locking stuff. This should be cleaned up sometime. (This used to be commit ddde0ab9a1e1b90c2a96103721056eb035dcd49d) --- source3/smbd/vfs.c | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 source3/smbd/vfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c new file mode 100644 index 0000000000..937bc1606e --- /dev/null +++ b/source3/smbd/vfs.c @@ -0,0 +1,407 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + vfs initialisation and support functions + Copyright (C) Tim Potter 1992-1998 + + 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 + +extern int DEBUGLEVEL; + +/* Some structures to help us initialise the vfs operations table */ + +struct vfs_syminfo { + char *name; + void *fptr; +}; + +struct vfs_ops dl_ops; + +struct vfs_syminfo vfs_syminfo[] = { + + /* Global operations */ + + {"vfs_init", &dl_ops.init}, + + /* Disk operations */ + + {"vfs_connect", &dl_ops.connect}, + {"vfs_disconnect", &dl_ops.disconnect}, + {"vfs_disk_free", &dl_ops.disk_free}, + + /* Directory operations */ + + {"vfs_opendir", &dl_ops.opendir}, + {"vfs_readdir", &dl_ops.readdir}, + {"vfs_mkdir", &dl_ops.mkdir}, + {"vfs_rmdir", &dl_ops.rmdir}, + + /* File operations */ + + {"vfs_open", &dl_ops.open}, + {"vfs_close", &dl_ops.close}, + {"vfs_read", &dl_ops.read}, + {"vfs_write", &dl_ops.write}, + {"vfs_lseek", &dl_ops.lseek}, + {"vfs_rename", &dl_ops.rename}, + {"vfs_sync", &dl_ops.sync}, + {"vfs_stat", &dl_ops.stat}, + {"vfs_fstat", &dl_ops.fstat}, + {"vfs_lstat", &dl_ops.lstat}, + {"vfs_lock", &dl_ops.lock}, + {"vfs_unlink", &dl_ops.unlink}, + {"vfs_chmod", &dl_ops.chmod}, + {"vfs_utime", &dl_ops.utime}, + + {NULL, 0} +}; + +/* Default vfs hooks. WARNING: The order of these initialisers is + very important. Change at your own peril. */ + +struct vfs_ops default_vfs_ops = { + + /* Global operations */ + + NULL, /* init */ + + /* Disk operations */ + + NULL, /* connect */ + NULL, /* disconnect */ + vfswrap_disk_free, + + /* Directory operations */ + + vfswrap_opendir, + vfswrap_readdir, + vfswrap_mkdir, + vfswrap_rmdir, + + /* File operations */ + + vfswrap_open, + vfswrap_close, + vfswrap_read, + vfswrap_write, + vfswrap_lseek, + vfswrap_rename, + vfswrap_sync_file, + vfswrap_stat, + vfswrap_fstat, + vfswrap_lstat, + vfswrap_fcntl_lock, + vfswrap_unlink, + vfswrap_chmod, + vfswrap_utime +}; + +/**************************************************************************** + call vfs_init function of loadable module +****************************************************************************/ +BOOL do_vfs_init(char *vfs_object) +{ + void *handle, (*fptr)(void); + + DEBUG(3, ("Calling vfs_init for module %s\n", vfs_object)); + + handle = dlopen(vfs_object, RTLD_NOW); + if (!handle) { + DEBUG(0, ("Error opening %s: %s\n", vfs_object, dlerror())); + return False; + } + + fptr = dlsym(handle, "vfs_init"); + + /* Call initialisation function */ + + if (fptr != NULL) { + fptr(); + } + + dlclose(handle); + + return True; +} + +/**************************************************************************** + initialise default vfs hooks +****************************************************************************/ +int vfs_init_default(connection_struct *conn) +{ + DEBUG(3, ("Initialising default vfs hooks\n")); + + bcopy(&default_vfs_ops, &conn->vfs_ops, sizeof(conn->vfs_ops)); + return 0; +} + +/**************************************************************************** + initialise custom vfs hooks +****************************************************************************/ +int vfs_init_custom(connection_struct *conn) +{ + void *handle, *fptr; + int index; + + DEBUG(3, ("Initialising custom vfs hooks from %s\n", + lp_vfsobj(SNUM(conn)))); + + /* Open object file */ + + handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW); + if (!handle) { + DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), + dlerror())); + return -1; + } + + /* Read list of symbols */ + + for(index = 0; vfs_syminfo[index].name; index++) { + fptr = dlsym(handle, vfs_syminfo[index].name); + if (fptr == NULL) { + DEBUG(0, ("Symbol %s not found in %s\n", vfs_syminfo[index].name, + lp_vfsobj(SNUM(conn)))); + return -1; + } + + *((void **)vfs_syminfo[index].fptr) = fptr; + } + + /* Copy loaded symbols into connection struct */ + + bcopy(&dl_ops, &conn->vfs_ops, sizeof(dl_ops)); + dlclose(handle); + +#if 0 + do_vfs_init(lp_vfsobj(SNUM(conn))); +#endif + + return 0; +} + +/******************************************************************* + check if a vfs file exists +********************************************************************/ +BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) +{ + SMB_STRUCT_STAT st; + if (!sbuf) sbuf = &st; + + if (conn->vfs_ops.stat(fname,sbuf) != 0) + return(False); + + return(S_ISREG(sbuf->st_mode)); +} + +/**************************************************************************** + read data from the client vfs, reading exactly N bytes. +****************************************************************************/ +ssize_t vfs_read_data(files_struct *fsp,char *buffer,size_t N) +{ + ssize_t ret; + size_t total=0; + int fd = fsp->fd_ptr->fd; + extern int smb_read_error; + + smb_read_error = 0; + + while (total < N) + { +#ifdef WITH_SSL + DEBUG(0, ("WARNING: read_data() called with SSL enabled\n")); + if(fd == sslFd){ + ret = SSL_read(ssl, buffer + total, N - total); + }else{ + ret = read(fd,buffer + total,N - total); + } +#else /* WITH_SSL */ + ret = fsp->conn->vfs_ops.read(fd,buffer + total,N - total); + DEBUG(0, ("VFS_READ -> read %d/%d bytes\n", ret, N)); +#endif /* WITH_SSL */ + + if (ret == 0) + { + smb_read_error = READ_EOF; + return 0; + } + if (ret == -1) + { + smb_read_error = READ_ERROR; + return -1; + } + total += ret; + } + return (ssize_t)total; +} + +/**************************************************************************** + write data to a fd on the vfs +****************************************************************************/ +ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) +{ + size_t total=0; + ssize_t ret; + int fd = fsp->fd_ptr->fd; + + while (total < N) + { +#ifdef WITH_SSL + DEBUG(0, ("WARNING: write_data called with SSL enabled\n")); + if(fd == sslFd){ + ret = SSL_write(ssl,buffer + total,N - total); + }else{ + ret = write(fd,buffer + total,N - total); + } +#else /* WITH_SSL */ + ret = fsp->conn->vfs_ops.write(fd,buffer + total,N - total); +#endif /* WITH_SSL */ + + if (ret == -1) return -1; + if (ret == 0) return total; + + total += ret; + } + return (ssize_t)total; +} + +/**************************************************************************** +transfer some data between two file_struct's +****************************************************************************/ +SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, + int out_fd, files_struct *out_fsp, + SMB_OFF_T n, char *header, int headlen, int align) +{ + static char *buf=NULL; + static int size=0; + char *buf1,*abuf; + SMB_OFF_T total = 0; + + DEBUG(4,("vfs_transfer_file n=%.0f (head=%d) called\n",(double)n,headlen)); + + /* Check we have at least somewhere to read from */ + + SMB_ASSERT((in_fd != -1) || (in_fsp != NULL)); + + if (size == 0) { + size = lp_readsize(); + size = MAX(size,1024); + } + + while (!buf && size>0) { + buf = (char *)Realloc(buf,size+8); + if (!buf) size /= 2; + } + + if (!buf) { + DEBUG(0,("Can't allocate transfer buffer!\n")); + exit(1); + } + + abuf = buf + (align%8); + + if (header) + n += headlen; + + while (n > 0) + { + int s = (int)MIN(n,(SMB_OFF_T)size); + int ret,ret2=0; + + ret = 0; + + if (header && (headlen >= MIN(s,1024))) { + buf1 = header; + s = headlen; + ret = headlen; + headlen = 0; + header = NULL; + } else { + buf1 = abuf; + } + + if (header && headlen > 0) + { + ret = MIN(headlen,size); + memcpy(buf1,header,ret); + headlen -= ret; + header += ret; + if (headlen <= 0) header = NULL; + } + + if (s > ret) { + ret += in_fsp ? + in_fsp->conn->vfs_ops.read(in_fsp->fd_ptr->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); + } + + if (ret > 0) + { + if (out_fsp) { + ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd_ptr->fd,buf1,ret); + } else { + ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret; + } + } + + if (ret2 > 0) total += ret2; + /* if we can't write then dump excess data */ + if (ret2 != ret) + vfs_transfer_file(in_fd, in_fsp, -1,NULL,n-(ret+headlen),NULL,0,0); + + if (ret <= 0 || ret2 != ret) + return(total); + n -= ret; + } + return(total); +} + +/******************************************************************* +a vfs_readdir wrapper which just returns the file name +********************************************************************/ +char *vfs_readdirname(connection_struct *conn, void *p) +{ + struct dirent *ptr; + char *dname; + + if (!p) return(NULL); + + ptr = (struct dirent *)conn->vfs_ops.readdir(p); + if (!ptr) return(NULL); + + dname = ptr->d_name; + +#ifdef NEXT2 + if (telldir(p) < 0) return(NULL); +#endif + +#ifdef HAVE_BROKEN_READDIR + /* using /usr/ucb/cc is BAD */ + dname = dname - 2; +#endif + + { + static pstring buf; + memcpy(buf, dname, NAMLEN(ptr)+1); + unix_to_dos(buf, True); + dname = buf; + } + + unix_to_dos(dname, True); + return(dname); +} -- cgit From 6001bd4c46b5b5bda423c314de0bb68a4b55ab1d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 07:03:47 +0000 Subject: Use VFS operations for file I/O. Modified invocations of fd_attempt_close as it now takes a fsp instead of a fd. (This used to be commit ef24fcb7b2248aae9c3f1fb4df7466b5ae35f5ce) --- source3/smbd/close.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 94923b6db2..024a3c03e4 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -119,7 +119,7 @@ void close_file(files_struct *fsp, BOOL normal_close) del_share_mode(token, fsp); } - if(fd_attempt_close(fsp->fd_ptr) == 0) + if(fd_attempt_close(fsp) == 0) last_reference = True; fsp->fd_ptr = NULL; @@ -144,8 +144,7 @@ void close_file(files_struct *fsp, BOOL normal_close) if (normal_close && last_reference && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(dos_unlink(fsp->fsp_name) != 0) { - + if(fsp->conn->vfs_ops.unlink(dos_to_unix(fsp->fsp_name, False)) != 0) { /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted -- cgit From 5cf21e60c8e406d390ee271b9e5945a9c229695e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 07:05:03 +0000 Subject: Use VFS operations for file I/O. Modified args to read_predict to pass in fsp. Renamed sync_file() function to sys_sync_file(). (This used to be commit 7ced7fd3958c76303e4b6019b5d54eda666d7b33) --- source3/smbd/fileio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index c7ffb6412d..7ab13f33f4 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -36,7 +36,7 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; - seek_ret = sys_lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); + seek_ret = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); if((seek_ret == -1) || (seek_ret != pos+offset)) { DEBUG(0,("seek_file: sys_lseek failed. Error was %s\n", strerror(errno) )); @@ -62,7 +62,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #if USE_READ_PREDICTION if (!fsp->can_write) { - ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); + ret = read_predict(fsp, fsp->fd_ptr->fd,pos,data,NULL,n); data += ret; n -= ret; @@ -88,9 +88,9 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); return(ret); } - + if (n > 0) { - readret = read(fsp->fd_ptr->fd,data,n); + readret = fsp->conn->vfs_ops.read(fsp->fd_ptr->fd,data,n); if (readret > 0) ret += readret; } @@ -104,7 +104,6 @@ write to a file ssize_t write_file(files_struct *fsp,char *data,size_t n) { - if (!fsp->can_write) { errno = EPERM; return(0); @@ -113,7 +112,7 @@ ssize_t write_file(files_struct *fsp,char *data,size_t n) if (!fsp->modified) { SMB_STRUCT_STAT st; fsp->modified = True; - if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); @@ -121,7 +120,7 @@ ssize_t write_file(files_struct *fsp,char *data,size_t n) } } - return(write_data(fsp->fd_ptr->fd,data,n)); + return(vfs_write_data(fsp,data,n)); } @@ -129,7 +128,7 @@ ssize_t write_file(files_struct *fsp,char *data,size_t n) sync a file ********************************************************************/ -void sync_file(connection_struct *conn, files_struct *fsp) +void sys_sync_file(struct connection_struct *conn, files_struct *fsp) { #ifdef HAVE_FSYNC if(lp_strict_sync(SNUM(conn))) -- cgit From 0ca4ce887c8aaf6059b6c989af00e642ef84f92e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 07:18:38 +0000 Subject: Fixed up incorrect calls to read_file(). (This used to be commit 17d007daa3d1fa60501eae1eecfc2d0f88c1692e) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 59a883f2d8..51d737a784 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2093,7 +2093,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); - nread = read_file(fsp,data,smb_maxcnt); + nread = read_file(fsp,data,startpos,smb_maxcnt); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -3869,7 +3869,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, { size_t N = MIN(max_per_packet,tcount-total_read); - nread = read_file(fsp,data,N); + nread = read_file(fsp,data,startpos,N); if (nread <= 0) nread = 0; -- cgit From 69ae7902bb2ba16f6312aaaa0cdee1204297905a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Apr 1999 05:18:07 +0000 Subject: Disable VFS routines if no libdl available. (This used to be commit cbfd8a8990b4d06d0c866274e7d28e4a5e384686) --- source3/smbd/service.c | 7 +++++++ source3/smbd/vfs.c | 9 ++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8202294293..5c7929d1b6 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -350,11 +350,18 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (*lp_vfsobj(SNUM(conn))) { +#ifdef HAVE_LIBDL + /* Loadable object file */ if (vfs_init_custom(conn) < 0) { return NULL; } +#else + DEBUG(0, ("No libdl present - cannot use VFS objects\n")); + conn_free(conn); + return NULL; +#endif } else { diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 937bc1606e..59e7bb4935 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -20,7 +20,9 @@ */ #include "includes.h" +#ifdef HAVE_LIBDL #include +#endif extern int DEBUGLEVEL; @@ -115,6 +117,7 @@ struct vfs_ops default_vfs_ops = { /**************************************************************************** call vfs_init function of loadable module ****************************************************************************/ +#ifdef HAVE_LIBDL BOOL do_vfs_init(char *vfs_object) { void *handle, (*fptr)(void); @@ -139,6 +142,7 @@ BOOL do_vfs_init(char *vfs_object) return True; } +#endif /**************************************************************************** initialise default vfs hooks @@ -154,6 +158,7 @@ int vfs_init_default(connection_struct *conn) /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ +#ifdef HAVE_LIBDL int vfs_init_custom(connection_struct *conn) { void *handle, *fptr; @@ -189,12 +194,11 @@ int vfs_init_custom(connection_struct *conn) bcopy(&dl_ops, &conn->vfs_ops, sizeof(dl_ops)); dlclose(handle); -#if 0 do_vfs_init(lp_vfsobj(SNUM(conn))); -#endif return 0; } +#endif /******************************************************************* check if a vfs file exists @@ -233,7 +237,6 @@ ssize_t vfs_read_data(files_struct *fsp,char *buffer,size_t N) } #else /* WITH_SSL */ ret = fsp->conn->vfs_ops.read(fd,buffer + total,N - total); - DEBUG(0, ("VFS_READ -> read %d/%d bytes\n", ret, N)); #endif /* WITH_SSL */ if (ret == 0) -- cgit From a4194191ce87cc630e34fe65ac8f207cc4330cae Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Apr 1999 05:18:44 +0000 Subject: Use VFS I/O for stat_cache_lookup() (This used to be commit 5ece1fcffbc5a5062c02edf6f2ecb405c2a2f43e) --- source3/smbd/filename.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 913d0b367e..fb2f57339b 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -229,7 +229,9 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) +static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, + char *dirpath, char **start, + SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -282,7 +284,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU * and then promote it to the top. */ - if(dos_stat( longest_hit->translated_name, pst) != 0) { + if(conn->vfs_ops.stat(longest_hit->translated_name, pst) != 0) { /* * Discard this entry. */ @@ -431,7 +433,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstrcpy(orig_path, name); - if(stat_cache_lookup( name, dirpath, &start, &st)) { + if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { if(pst) *pst = st; return True; -- cgit From 4085fb08fdd936212d9f3bbc9ded660dd3332786 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Apr 1999 05:19:34 +0000 Subject: Fix incorrect conversion of fd_attempt_open() calls to vfs_ops.open(). Use VFS I/O for fd_attempt_open() and check_access_allowed_for_current_user(). (This used to be commit abf31ca66f3dab1b8bd7772f83e736e41afb4b1e) --- source3/smbd/open.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index da5303fc5a..2c12d425b9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,16 +30,17 @@ extern uint16 global_oplock_port; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ -static int fd_attempt_open(char *fname, int flags, mode_t mode) +static int fd_attempt_open(struct connection_struct *conn, char *fname, + int flags, mode_t mode) { - int fd = dos_open(fname,flags,mode); + int fd = conn->vfs_ops.open(fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = dos_open(fname,flags,mode); + fd = conn->vfs_ops.open(fname,flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -70,7 +71,7 @@ static int fd_attempt_open(char *fname, int flags, mode_t mode) char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = dos_open(fname,flags,mode)) == -1) + if ((fd = conn->vfs_ops.open(fname,flags,mode)) == -1) p[max_len] = tmp; } } @@ -191,7 +192,9 @@ This is really ugly code, as due to POSIX locking braindamage we must fork and then attempt to open the file, and return success or failure via an exit code. ****************************************************************************/ -static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) +static BOOL check_access_allowed_for_current_user(struct connection_struct + *conn, char *fname, + int accmode ) { pid_t child_pid; @@ -242,7 +245,7 @@ static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) */ int fd; DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode )); - if((fd = fd_attempt_open( fname, accmode, 0)) < 0) { + if((fd = fd_attempt_open(conn, fname, accmode, 0)) < 0) { /* Access denied. */ _exit(EACCES); } @@ -373,7 +376,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { - if(!check_access_allowed_for_current_user( fname, accmode )) { + if(!check_access_allowed_for_current_user(conn, fname, accmode )) { /* Error - permission denied. */ DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", fname, flags, accmode)); @@ -430,7 +433,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fd_ptr->real_open_flags = O_RDWR; /* Set the flags as needed without the read/write modes. */ open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); - fd_ptr->fd = conn->vfs_ops.open(fname, open_flags|O_RDWR, mode); + fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|O_RDWR, mode); /* * On some systems opening a file for R/W access on a read only * filesystems sets errno to EROFS. @@ -441,7 +444,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if((fd_ptr->fd == -1) && (errno == EACCES)) { #endif /* EROFS */ if(accmode != O_RDWR) { - fd_ptr->fd = conn->vfs_ops.open(fname, open_flags|accmode, mode); + fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode); fd_ptr->real_open_flags = accmode; } } -- cgit From 44784f69e0390af171d2206b964253a34ac19b4d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Apr 1999 23:35:50 +0000 Subject: Under IRIX, a void function may return a value, even if that value is void! (This used to be commit e15da6882426edd39ff7fdcd47f1be30c053d4ec) --- source3/smbd/vfs-wrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index b8325dd1e7..b3d1a35329 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -118,7 +118,7 @@ int vfswrap_rename(char *old, char *new) void vfswrap_sync_file(struct connection_struct *conn, files_struct *fsp) { - return sys_sync_file(conn, fsp); + sys_sync_file(conn, fsp); } int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) -- cgit From 06c7ec8485c449dbcff7ea4f24ecce068fdab44c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 8 Apr 1999 03:01:18 +0000 Subject: Forgot about closedir() function for VFS. Hoo embarassing. (This used to be commit c1cbe07c0391c36066b068fdd42bf1aa40259a5c) --- source3/smbd/dir.c | 4 ++-- source3/smbd/vfs-wrap.c | 8 ++++++++ source3/smbd/vfs.c | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 52d271e284..b7ae2af47c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -524,7 +524,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { - closedir(p); + conn->vfs_ops.closedir(p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; @@ -554,7 +554,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->numentries++; } - closedir(p); + conn->vfs_ops.closedir(p); return((void *)dirp); } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index b3d1a35329..da69b3f006 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -66,6 +66,14 @@ int vfswrap_rmdir(char *path) return result; } +int vfswrap_closedir(DIR *dirp) +{ + int result; + + result = closedir(path); + return result; +} + /* File operations */ int vfswrap_open(char *fname, int flags, mode_t mode) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 59e7bb4935..fdff87496b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -53,6 +53,7 @@ struct vfs_syminfo vfs_syminfo[] = { {"vfs_readdir", &dl_ops.readdir}, {"vfs_mkdir", &dl_ops.mkdir}, {"vfs_rmdir", &dl_ops.rmdir}, + {"vfs_closedir", &dl_ops.closedir}, /* File operations */ @@ -95,6 +96,7 @@ struct vfs_ops default_vfs_ops = { vfswrap_readdir, vfswrap_mkdir, vfswrap_rmdir, + vfswrap_closedir, /* File operations */ -- cgit From ab0d0a6f4e55d85c32757d3dda3bf40c339d4a23 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 8 Apr 1999 03:13:33 +0000 Subject: Always do a compile before CVS commit! )-: (This used to be commit 0f37e900fa0744573754796916abf967fee05ea2) --- source3/smbd/vfs-wrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index da69b3f006..990e931adf 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -70,7 +70,7 @@ int vfswrap_closedir(DIR *dirp) { int result; - result = closedir(path); + result = closedir(dirp); return result; } -- cgit From 68e1888fd3f3b26896ef99d689537c73ceecf639 Mon Sep 17 00:00:00 2001 From: Matthew Chapman Date: Thu, 8 Apr 1999 05:36:39 +0000 Subject: Mainly BDC-related changes. * Added SEC_CHAN_BDC * Propagate sec_chan into the various functions which change trust account passwords, so they can be used for domain control and inter-domain trusts. (This used to be commit ca540c21f78b4bc8ca36ac3d5af2b8f67cf716c3) --- source3/smbd/process.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 420598157f..a4c1acba8f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -882,6 +882,7 @@ void smbd_process(void) unsigned char trust_passwd_hash[16]; time_t lct; pstring remote_machine_list; + int sec_chan = SEC_CHAN_WKSTA; /* * We're in domain level security, and the code that @@ -917,8 +918,11 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); } pstrcpy(remote_machine_list, lp_passwordserver()); + if (lp_server_role() == ROLE_DOMAIN_BDC) + sec_chan = SEC_CHAN_BDC; - change_trust_account_password( global_myworkgroup, remote_machine_list); + change_trust_account_password(global_myworkgroup, remote_machine_list, + sec_chan); trust_password_unlock(); global_machine_password_needs_changing = False; } -- cgit From bc6858805b280dd0ff5393350b699176e138e39f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 14 Apr 1999 07:21:48 +0000 Subject: Removed unused vfs_read_data() function at the request of tridge. Removed unnecessary SSL stuff from vfs_write_data(). (This used to be commit fdbe79c1c3061c844c1eb859e3e40634a098a8f3) --- source3/smbd/vfs.c | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index fdff87496b..7304229f8d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -216,46 +216,6 @@ BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) return(S_ISREG(sbuf->st_mode)); } -/**************************************************************************** - read data from the client vfs, reading exactly N bytes. -****************************************************************************/ -ssize_t vfs_read_data(files_struct *fsp,char *buffer,size_t N) -{ - ssize_t ret; - size_t total=0; - int fd = fsp->fd_ptr->fd; - extern int smb_read_error; - - smb_read_error = 0; - - while (total < N) - { -#ifdef WITH_SSL - DEBUG(0, ("WARNING: read_data() called with SSL enabled\n")); - if(fd == sslFd){ - ret = SSL_read(ssl, buffer + total, N - total); - }else{ - ret = read(fd,buffer + total,N - total); - } -#else /* WITH_SSL */ - ret = fsp->conn->vfs_ops.read(fd,buffer + total,N - total); -#endif /* WITH_SSL */ - - if (ret == 0) - { - smb_read_error = READ_EOF; - return 0; - } - if (ret == -1) - { - smb_read_error = READ_ERROR; - return -1; - } - total += ret; - } - return (ssize_t)total; -} - /**************************************************************************** write data to a fd on the vfs ****************************************************************************/ @@ -267,16 +227,7 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) while (total < N) { -#ifdef WITH_SSL - DEBUG(0, ("WARNING: write_data called with SSL enabled\n")); - if(fd == sslFd){ - ret = SSL_write(ssl,buffer + total,N - total); - }else{ - ret = write(fd,buffer + total,N - total); - } -#else /* WITH_SSL */ ret = fsp->conn->vfs_ops.write(fd,buffer + total,N - total); -#endif /* WITH_SSL */ if (ret == -1) return -1; if (ret == 0) return total; -- cgit From 1e1a52bb5f0475327d435c06032d1e6234c28bcb Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 20 Apr 1999 03:29:05 +0000 Subject: Changed arguments to fsync() function to break dependency on connection_struct. (This used to be commit ee6f826ccc0897a4538f6f9a560127c54a4c4038) --- source3/smbd/fileio.c | 5 ++--- source3/smbd/files.c | 5 +++-- source3/smbd/reply.c | 30 +++++++++++++++++------------- 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 7ab13f33f4..1e16627515 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -128,10 +128,9 @@ ssize_t write_file(files_struct *fsp,char *data,size_t n) sync a file ********************************************************************/ -void sys_sync_file(struct connection_struct *conn, files_struct *fsp) +void sys_sync_file(int fd) { #ifdef HAVE_FSYNC - if(lp_strict_sync(SNUM(conn))) - fsync(fsp->fd_ptr->fd); + fsync(fd); #endif } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 8aca336bf8..d366fa1e1a 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -340,8 +340,9 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL)){ - conn->vfs_ops.sync(conn, fsp); + if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL) + && lp_strict_sync(SNUM(conn))){ + conn->vfs_ops.sync(fsp->fd_ptr->fd); } } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 51d737a784..b20236d6f4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2200,8 +2200,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s SSVAL(outbuf,smb_err,ERRdiskfull); } - if (lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.sync(conn, fsp); + if ((lp_syncalways(SNUM(conn)) || write_through) && + lp_strict_sync(SNUM(conn))) + conn->vfs_ops.sync(fsp->fd_ptr->fd); DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", fsp->fnum, (double)startpos, numtowrite, total_written)); @@ -2250,8 +2251,8 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum else nwritten = write_file(fsp,data,numtowrite); - if (lp_syncalways(SNUM(conn))) - conn->vfs_ops.sync(conn, fsp); + if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn))) + conn->vfs_ops.sync(fsp->fd_ptr->fd); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2303,8 +2304,8 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i else nwritten = write_file(fsp,data,numtowrite); - if (lp_syncalways(SNUM(conn))) - conn->vfs_ops.sync(conn, fsp); + if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn))) + conn->vfs_ops.sync(fsp->fd_ptr->fd); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2387,8 +2388,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", fsp->fnum, numtowrite, nwritten)); - if (lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.sync(conn, fsp); + if ((lp_syncalways(SNUM(conn)) || write_through) && + lp_strict_sync(SNUM(conn))) + conn->vfs_ops.sync(fsp->fd_ptr->fd); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2450,7 +2452,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { file_sync_all(conn); } else { - conn->vfs_ops.sync(conn, fsp); + conn->vfs_ops.sync(fsp->fd_ptr->fd); } DEBUG(3,("flush\n")); @@ -3931,8 +3933,9 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s nwritten = write_file(fsp,data,numtowrite); - if(lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.sync(conn, fsp); + if((lp_syncalways(SNUM(conn)) || write_through) && + lp_strict_sync(SNUM(conn))) + conn->vfs_ops.sync(fsp->fd_ptr->fd); if(nwritten < (ssize_t)numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -4044,8 +4047,9 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz nwritten = write_file(fsp,data,numtowrite); - if(lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.sync(conn, fsp); + if((lp_syncalways(SNUM(conn)) || write_through) && + lp_strict_sync(SNUM(conn))) + conn->vfs_ops.sync(fsp->fd_ptr->fd); if (nwritten < (ssize_t)numtowrite) { -- cgit From b7100673febaaaf37e0875ded640126425be9f8e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 20 Apr 1999 03:37:11 +0000 Subject: Changed the way a VFS is initialised. The vfs_init() function is executed from the VFS object file and it returns a pointer to a vfs_ops structure. If any of the function pointers in vfs_ops are NULL, then they are replaced with the standard disk functions. This should allow disk-related VFS modules to be easily added. I've written an auditing VFS module which logs various calls (connect, disconnect, mkdir, rmdir, open and a few others) to syslog in a couple of pages of code. Thanks to tridge for various useful suggestions. (This used to be commit 346c78d7078d87bc95abc274f2bc66476aeee54c) --- source3/smbd/service.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 5c7929d1b6..7628f9c8f0 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -354,7 +354,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* Loadable object file */ - if (vfs_init_custom(conn) < 0) { + if (!vfs_init_custom(conn)) { return NULL; } #else @@ -516,7 +516,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int extern int Client; dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); - dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); + dbgtext( "connect to service %s ", lp_servicename(SNUM(conn))); dbgtext( "as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)conn->uid, (int)conn->gid ); dbgtext( "(pid %d)\n", (int)getpid() ); @@ -525,7 +525,42 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* Invoke make connection hook */ if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn, service, user) < 0) { + struct vfs_connection_struct *vconn; + + vconn = (struct vfs_connection_struct *) + malloc(sizeof(struct vfs_connection_struct)); + + if (vconn == NULL) { + DEBUG(0, ("No memory to create vfs_connection_struct")); + return NULL; + } + + ZERO_STRUCTP(vconn); + + /* Copy across relevant data from connection struct */ + + vconn->printer = conn->printer; + vconn->ipc = conn->ipc; + vconn->read_only = conn->read_only; + vconn->admin_user = conn->admin_user; + + pstrcpy(vconn->dirpath, conn->dirpath); + pstrcpy(vconn->connectpath, conn->connectpath); + pstrcpy(vconn->origpath, conn->origpath); + + pstrcpy(vconn->user, conn->user); + vconn->uid = conn->uid; + vconn->gid = conn->gid; + vconn->ngroups = conn->ngroups; + vconn->groups = (gid_t *)malloc(conn->ngroups * sizeof(gid_t)); + if (vconn->groups != NULL) { + memcpy(vconn->groups, conn->groups, + conn->ngroups * sizeof(gid_t)); + } + + /* Call connect hook */ + + if (conn->vfs_ops.connect(vconn, service, user) < 0) { return NULL; } } @@ -549,7 +584,19 @@ void close_cnum(connection_struct *conn, uint16 vuid) lp_servicename(SNUM(conn)))); if (conn->vfs_ops.disconnect != NULL) { - conn->vfs_ops.disconnect(conn, lp_servicename(SNUM(conn))); + + /* Call disconnect hook */ + + conn->vfs_ops.disconnect(); + + /* Free vfs_connection_struct */ + + if (conn->vfs_conn != NULL) { + if (conn->vfs_conn->groups != NULL) { + free(conn->vfs_conn->groups); + } + free(conn->vfs_conn); + } } yield_connection(conn, -- cgit From c1d60a9b26ed9a25f974bf1c3e533118fe0af29a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 20 Apr 1999 03:38:22 +0000 Subject: Added dummy connect and disconnect VFS operations to avoid the possibilty of NULL function pointers being called. Changed arguments to fsync() function to break dependency on connection_struct. (This used to be commit f6d0b55e92cc5250dc65f65c8689bf96cf7001df) --- source3/smbd/vfs-wrap.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 990e931adf..2e25a2540b 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -21,6 +21,21 @@ #include "includes.h" +/* We don't want to have NULL function pointers lying around. Someone + is sure to try and execute them. These stubs are used to prevent + this possibility. */ + +int vfswrap_dummy_connect(struct vfs_connection_struct *conn, char *service, + char *user) +{ + /* Do nothing */ +} + +void vfswrap_dummy_disconnect(void) +{ + /* Do nothing a bit more */ +} + /* Disk operations */ SMB_BIG_UINT vfswrap_disk_free(char *path, SMB_BIG_UINT *bsize, @@ -124,9 +139,9 @@ int vfswrap_rename(char *old, char *new) return result; } -void vfswrap_sync_file(struct connection_struct *conn, files_struct *fsp) +void vfswrap_sync_file(int fd) { - sys_sync_file(conn, fsp); + sys_sync_file(fd); } int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) -- cgit From 025493a3c9bab5097db024aadc9786d73af71a76 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 20 Apr 1999 03:42:48 +0000 Subject: Rewrite of VFS initialisation routines. (This used to be commit acc1c9e49cd40a600479a1a586d314b42e2cdf77) --- source3/smbd/vfs.c | 215 ++++++++++++++++++++++++++++------------------------- 1 file changed, 114 insertions(+), 101 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7304229f8d..b0bc1a9f4d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1,8 +1,8 @@ /* Unix SMB/Netbios implementation. Version 1.9. - vfs initialisation and support functions - Copyright (C) Tim Potter 1992-1998 + VFS initialisation and support functions + Copyright (C) Tim Potter 1999 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 @@ -33,61 +33,16 @@ struct vfs_syminfo { void *fptr; }; -struct vfs_ops dl_ops; - -struct vfs_syminfo vfs_syminfo[] = { - - /* Global operations */ - - {"vfs_init", &dl_ops.init}, - - /* Disk operations */ - - {"vfs_connect", &dl_ops.connect}, - {"vfs_disconnect", &dl_ops.disconnect}, - {"vfs_disk_free", &dl_ops.disk_free}, - - /* Directory operations */ - - {"vfs_opendir", &dl_ops.opendir}, - {"vfs_readdir", &dl_ops.readdir}, - {"vfs_mkdir", &dl_ops.mkdir}, - {"vfs_rmdir", &dl_ops.rmdir}, - {"vfs_closedir", &dl_ops.closedir}, - - /* File operations */ - - {"vfs_open", &dl_ops.open}, - {"vfs_close", &dl_ops.close}, - {"vfs_read", &dl_ops.read}, - {"vfs_write", &dl_ops.write}, - {"vfs_lseek", &dl_ops.lseek}, - {"vfs_rename", &dl_ops.rename}, - {"vfs_sync", &dl_ops.sync}, - {"vfs_stat", &dl_ops.stat}, - {"vfs_fstat", &dl_ops.fstat}, - {"vfs_lstat", &dl_ops.lstat}, - {"vfs_lock", &dl_ops.lock}, - {"vfs_unlink", &dl_ops.unlink}, - {"vfs_chmod", &dl_ops.chmod}, - {"vfs_utime", &dl_ops.utime}, - - {NULL, 0} -}; - /* Default vfs hooks. WARNING: The order of these initialisers is - very important. Change at your own peril. */ + very important. They must be in the same order as defined in + vfs.h. Change at your own peril. */ struct vfs_ops default_vfs_ops = { - /* Global operations */ - - NULL, /* init */ - /* Disk operations */ - NULL, /* connect */ - NULL, /* disconnect */ + vfswrap_dummy_connect, + vfswrap_dummy_disconnect, vfswrap_disk_free, /* Directory operations */ @@ -116,36 +71,6 @@ struct vfs_ops default_vfs_ops = { vfswrap_utime }; -/**************************************************************************** - call vfs_init function of loadable module -****************************************************************************/ -#ifdef HAVE_LIBDL -BOOL do_vfs_init(char *vfs_object) -{ - void *handle, (*fptr)(void); - - DEBUG(3, ("Calling vfs_init for module %s\n", vfs_object)); - - handle = dlopen(vfs_object, RTLD_NOW); - if (!handle) { - DEBUG(0, ("Error opening %s: %s\n", vfs_object, dlerror())); - return False; - } - - fptr = dlsym(handle, "vfs_init"); - - /* Call initialisation function */ - - if (fptr != NULL) { - fptr(); - } - - dlclose(handle); - - return True; -} -#endif - /**************************************************************************** initialise default vfs hooks ****************************************************************************/ @@ -153,18 +78,18 @@ int vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); - bcopy(&default_vfs_ops, &conn->vfs_ops, sizeof(conn->vfs_ops)); - return 0; + memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(conn->vfs_ops)); + return True; } /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ #ifdef HAVE_LIBDL -int vfs_init_custom(connection_struct *conn) +BOOL vfs_init_custom(connection_struct *conn) { - void *handle, *fptr; - int index; + void *handle; + struct vfs_ops *ops, *(*fptr)(void); DEBUG(3, ("Initialising custom vfs hooks from %s\n", lp_vfsobj(SNUM(conn)))); @@ -175,30 +100,118 @@ int vfs_init_custom(connection_struct *conn) if (!handle) { DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); - return -1; + return False; } - /* Read list of symbols */ + /* Get handle on vfs_init() symbol */ - for(index = 0; vfs_syminfo[index].name; index++) { - fptr = dlsym(handle, vfs_syminfo[index].name); - if (fptr == NULL) { - DEBUG(0, ("Symbol %s not found in %s\n", vfs_syminfo[index].name, - lp_vfsobj(SNUM(conn)))); - return -1; - } + fptr = dlsym(handle, "vfs_init"); + if (fptr == NULL) { + DEBUG(0, ("No vfs_init() symbol found in %s\n", + lp_vfsobj(SNUM(conn)))); + return False; + } + + dlclose(handle); + + /* Initialise vfs_ops and fill in unused operations with default + (disk based) ones. There's probably a neater way to do this. */ - *((void **)vfs_syminfo[index].fptr) = fptr; + if ((ops = fptr()) == NULL) { + return False; + } + + memcpy(&conn->vfs_ops, ops, sizeof(conn->vfs_ops)); + + if (conn->vfs_ops.connect == NULL) { + conn->vfs_ops.connect = default_vfs_ops.connect; } - /* Copy loaded symbols into connection struct */ + if (conn->vfs_ops.disconnect == NULL) { + conn->vfs_ops.disconnect = default_vfs_ops.disconnect; + } - bcopy(&dl_ops, &conn->vfs_ops, sizeof(dl_ops)); - dlclose(handle); + if (conn->vfs_ops.disk_free == NULL) { + conn->vfs_ops.disk_free = default_vfs_ops.disk_free; + } + + if (conn->vfs_ops.opendir == NULL) { + conn->vfs_ops.opendir = default_vfs_ops.opendir; + } - do_vfs_init(lp_vfsobj(SNUM(conn))); + if (conn->vfs_ops.readdir == NULL) { + conn->vfs_ops.readdir = default_vfs_ops.readdir; + } + + if (conn->vfs_ops.mkdir == NULL) { + conn->vfs_ops.mkdir = default_vfs_ops.mkdir; + } - return 0; + if (conn->vfs_ops.rmdir == NULL) { + conn->vfs_ops.rmdir = default_vfs_ops.rmdir; + } + + if (conn->vfs_ops.closedir == NULL) { + conn->vfs_ops.closedir = default_vfs_ops.closedir; + } + + if (conn->vfs_ops.open == NULL) { + conn->vfs_ops.open = default_vfs_ops.open; + } + + if (conn->vfs_ops.close == NULL) { + conn->vfs_ops.close = default_vfs_ops.close; + } + + if (conn->vfs_ops.read == NULL) { + conn->vfs_ops.read = default_vfs_ops.read; + } + + if (conn->vfs_ops.write == NULL) { + conn->vfs_ops.write = default_vfs_ops.write; + } + + if (conn->vfs_ops.lseek == NULL) { + conn->vfs_ops.lseek = default_vfs_ops.lseek; + } + + if (conn->vfs_ops.rename == NULL) { + conn->vfs_ops.rename = default_vfs_ops.rename; + } + + if (conn->vfs_ops.sync == NULL) { + conn->vfs_ops.sync = default_vfs_ops.sync; + } + + if (conn->vfs_ops.stat == NULL) { + conn->vfs_ops.stat = default_vfs_ops.stat; + } + + if (conn->vfs_ops.fstat == NULL) { + conn->vfs_ops.fstat = default_vfs_ops.fstat; + } + + if (conn->vfs_ops.lstat == NULL) { + conn->vfs_ops.lstat = default_vfs_ops.lstat; + } + + if (conn->vfs_ops.lock == NULL) { + conn->vfs_ops.lock = default_vfs_ops.lock; + } + + if (conn->vfs_ops.unlink == NULL) { + conn->vfs_ops.unlink = default_vfs_ops.unlink; + } + + if (conn->vfs_ops.chmod == NULL) { + conn->vfs_ops.chmod = default_vfs_ops.chmod; + } + + if (conn->vfs_ops.utime == NULL) { + conn->vfs_ops.utime = default_vfs_ops.utime; + } + + return True; } #endif -- cgit From be552ca3504ebd98da37e70bac1f10b248cf860b Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Tue, 27 Apr 1999 10:43:32 +0000 Subject: rpc_parse/parse_misc.c : defined a new BUFFER5 struct include/ntdomain.h : added rpc_spoolss.h include statement include/proto.h include/rpc_dce.h : added definition of RPC_ALTER_CONTEXT request & reply param/loadparm.c : 2 new options for NT printing support and some changes to initial values in the LPRNG case. rpc_parse/parse_prs.c : added prs_uint16s() rpc_parse/parse_rpc.c : added SYNT_SPOOLSS_V1 and code for the alter-context support. rpc_server/srv_pipe.c : alter-context support smbd/nttrans.c smbd/server.c include/rpc_misc.h Makefile.in include/smb.h Jean Francois (This used to be commit 4c515804b70254248e378a3f90f47e4c32639d29) --- source3/smbd/nttrans.c | 1 + source3/smbd/server.c | 1 + 2 files changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 923de7a197..5c26c7f578 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -46,6 +46,7 @@ static char *known_nt_pipes[] = { "\\lsass", "\\lsarpc", "\\winreg", + "\\spoolss", NULL }; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index dcc53cb8d0..339fab8398 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -450,6 +450,7 @@ static void init_structs(void) file_init(); init_rpc_pipe_hnd(); /* for RPC pipes */ init_lsa_policy_hnd(); /* for LSA handles */ + init_printer_hnd(); /* for SPOOLSS handles */ init_dptrs(); } -- cgit From 89d51caba5bed5c3329b3776e15fce2bb41f7592 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 1 May 1999 01:41:28 +0000 Subject: added server ntlmv2 false/auto/true parameter, defaults to off. (This used to be commit 209944dabc764c6ea0c471e7868306c7d8d020d4) --- source3/smbd/negprot.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index d4e6180261..e66bf9f163 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -159,16 +159,6 @@ reply for the nt protocol static int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| - (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | - (SMB_OFF_T_BITS == 64 ? CAP_LARGE_FILES : 0); - - -/* - other valid capabilities which we may support at some time... - CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; - */ - int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); @@ -177,9 +167,26 @@ static int reply_nt1(char *outbuf) char cryptkey[8]; char crypt_len = 0; - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ; + + if (lp_nt_smb_support()) + { + capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS; + } + + if (SMB_OFF_T_BITS == 64) + { + capabilities |= CAP_LARGE_FILES; + } +/* + other valid capabilities which we may support at some time... + CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; + */ + + if (lp_security() == SEC_SERVER) + { + cli = server_cryptkey(); + } if (cli) { DEBUG(3,("using password server validation\n")); -- cgit From 150645f955d1f15b0ea43069020070424f774521 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 6 May 1999 18:05:45 +0000 Subject: Jani Jaakkola's "getpwuid() / getpwnam()" hash-cache-hack (This used to be commit 899fc053c50448db65092d9f25fea99433cfb29f) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 11fe69b103..daead8bb82 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -224,7 +224,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->real_name, "\0"); if (lp_unix_realname()) { - if ((pwfile=getpwnam(vuser->name))!= NULL) + if ((pwfile=hashed_getpwnam(vuser->name))!= NULL) { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); fstrcpy(vuser->real_name, pwfile->pw_gecos); -- cgit From 798fdf4fd838cd361968debb56aaba2006f5bed1 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 6 May 1999 23:52:00 +0000 Subject: Fix compiler warning. Added checks to panic if VFS functions are passed NULL pointers. This may expose some bugs that have been lurking about. Checks can be easily removed later. (This used to be commit c33c6330e3a2025f2fda0234635dfdd3acd04890) --- source3/smbd/vfs-wrap.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 2e25a2540b..3493c23178 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -21,6 +21,10 @@ #include "includes.h" +/* Check for NULL pointer parameters in vfswrap_* functions */ + +#define VFS_CHECK_NULL + /* We don't want to have NULL function pointers lying around. Someone is sure to try and execute them. These stubs are used to prevent this possibility. */ @@ -28,12 +32,11 @@ int vfswrap_dummy_connect(struct vfs_connection_struct *conn, char *service, char *user) { - /* Do nothing */ + return 0; /* Return >= 0 for success */ } void vfswrap_dummy_disconnect(void) { - /* Do nothing a bit more */ } /* Disk operations */ @@ -43,6 +46,14 @@ SMB_BIG_UINT vfswrap_disk_free(char *path, SMB_BIG_UINT *bsize, { SMB_BIG_UINT result; +#ifdef VFS_CHECK_NULL + if ((path == NULL) || (bsize == NULL) || (dfree == NULL) || + (dsize == NULL)) { + + smb_panic("NULL pointer passed to vfswrap_disk_free() function\n"); + } +#endif + result = sys_disk_free(path, bsize, dfree, dsize); return result; } @@ -53,6 +64,12 @@ DIR *vfswrap_opendir(char *fname) { DIR *result; +#ifdef VFS_CHECK_NULL + if (fname == NULL) { + smb_panic("NULL pointer passed to vfswrap_opendir()\n"); + } +#endif + result = opendir(fname); return result; } @@ -61,6 +78,12 @@ struct dirent *vfswrap_readdir(DIR *dirp) { struct dirent *result; +#ifdef VFS_CHECK_NULL + if (dirp == NULL) { + smb_panic("NULL pointer passed to vfswrap_readdir()\n"); + } +#endif + result = readdir(dirp); return result; } @@ -69,6 +92,12 @@ int vfswrap_mkdir(char *path, mode_t mode) { int result; +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_mkdir()\n"); + } +#endif + result = mkdir(path, mode); return result; } @@ -77,6 +106,12 @@ int vfswrap_rmdir(char *path) { int result; +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_rmdir()\n"); + } +#endif + result = rmdir(path); return result; } @@ -84,7 +119,13 @@ int vfswrap_rmdir(char *path) int vfswrap_closedir(DIR *dirp) { int result; - + +#ifdef VFS_CHECK_NULL + if (dirp == NULL) { + smb_panic("NULL pointer passed to vfswrap_closedir()\n"); + } +#endif + result = closedir(dirp); return result; } @@ -95,6 +136,12 @@ int vfswrap_open(char *fname, int flags, mode_t mode) { int result; +#ifdef VFS_CHECK_NULL + if (fname == NULL) { + smb_panic("NULL pointer passed to vfswrap_open()\n"); + } +#endif + result = sys_open(fname, flags, mode); return result; } @@ -111,6 +158,12 @@ ssize_t vfswrap_read(int fd, char *data, size_t n) { ssize_t result; +#ifdef VFS_CHECK_NULL + if (data == NULL) { + smb_panic("NULL pointer passed to vfswrap_read()\n"); + } +#endif + result = read(fd, data, n); return result; } @@ -119,6 +172,12 @@ ssize_t vfswrap_write(int fd, char *data, size_t n) { ssize_t result; +#ifdef VFS_CHECK_NULL + if (data == NULL) { + smb_panic("NULL pointer passed to vfswrap_write()\n"); + } +#endif + result = write(fd, data, n); return result; } @@ -135,6 +194,12 @@ int vfswrap_rename(char *old, char *new) { int result; +#ifdef VFS_CHECK_NULL + if ((old == NULL) || (new == NULL)) { + smb_panic("NULL pointer passed to vfswrap_rename()\n"); + } +#endif + result = rename(old, new); return result; } @@ -148,6 +213,12 @@ int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) { int result; +#ifdef VFS_CHECK_NULL + if ((fname == NULL) || (sbuf == NULL)) { + smb_panic("NULL pointer passed to vfswrap_stat()\n"); + } +#endif + result = sys_stat(fname, sbuf); return result; } @@ -156,6 +227,12 @@ int vfswrap_fstat(int fd, SMB_STRUCT_STAT *sbuf) { int result; +#ifdef VFS_CHECK_NULL + if (sbuf == NULL) { + smb_panic("NULL pointer passed to vfswrap_fstat()\n"); + } +#endif + result = sys_fstat(fd, sbuf); return result; } @@ -165,6 +242,12 @@ int vfswrap_lstat(char *path, { int result; +#ifdef VFS_CHECK_NULL + if ((path == NULL) || (sbuf == NULL)) { + smb_panic("NULL pointer passed to vfswrap_lstat()\n"); + } +#endif + result = sys_lstat(path, sbuf); return result; } @@ -182,6 +265,12 @@ int vfswrap_unlink(char *path) { int result; +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_unlink()\n"); + } +#endif + result = unlink(path); return result; } @@ -190,6 +279,12 @@ int vfswrap_chmod(char *path, mode_t mode) { int result; +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_chmod()\n"); + } +#endif + result = chmod(path, mode); return result; } @@ -198,6 +293,12 @@ int vfswrap_utime(char *path, struct utimbuf *times) { int result; +#ifdef VFS_CHECK_NULL + if ((path == NULL) || (times == NULL)) { + smb_panic("NULL pointer passed to vfswrap_utime()\n"); + } +#endif + result = utime(path, times); return result; } -- cgit From 6aa63bd761241c8b80808651fc570b2d941ee135 Mon Sep 17 00:00:00 2001 From: Matthew Chapman Date: Wed, 2 Jun 1999 04:11:50 +0000 Subject: Fixing core dump bug with unix password sync, caused by a NULL connection_struct in a call to OpenDir. JF, you fixed a similar bug in printing/nt_printing.c, I think your fix is incorrect as global configuration files should not go through a VFS. (This used to be commit 0e0c310a3ea102c61e74b604bcc793a82554a828) --- source3/smbd/chgpasswd.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index c22f268684..734f72c08d 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -60,7 +60,8 @@ static int findpty(char **slave) int master; #ifndef HAVE_GRANTPT static fstring line; - void *dirp; + DIR *dirp; + struct dirent *dentry; char *dpname; #endif /* !HAVE_GRANTPT */ @@ -82,10 +83,11 @@ static int findpty(char **slave) #else /* HAVE_GRANTPT */ fstrcpy( line, "/dev/ptyXX" ); - dirp = OpenDir(NULL, "/dev", False); + dirp = opendir("/dev"); if (!dirp) return(-1); - while ((dpname = ReadDirName(dirp)) != NULL) { + while ((dentry = readdir(dirp)) != NULL) { + dpname = dentry->d_name; if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); line[8] = dpname[3]; @@ -94,12 +96,12 @@ static int findpty(char **slave) DEBUG(3,("pty: opened %s\n", line ) ); line[5] = 't'; *slave = line; - CloseDir(dirp); + closedir(dirp); return (master); } } } - CloseDir(dirp); + closedir(dirp); #endif /* HAVE_GRANTPT */ return (-1); } -- cgit From 731c7f2ecfe17651506ba05b88358360e4654a37 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 13 Jun 1999 04:14:24 +0000 Subject: Moved code that changes the pw_passwd entry (i.e shadow password and weird unixware stuff) into _Get_Pwnam() to fix a memory allocation bug. Note that the Get_Pwnam() function now returns a const struct passwd * as a hint to other developers not to change entries in the struct passwd. (This used to be commit 36d7cb4ccc42268e8e6a7b783c945d1853624958) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/password.c | 4 ++-- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 2 +- source3/smbd/uid.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 734f72c08d..f84ae0ccb5 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -110,7 +110,7 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, { int slave; struct termios stermios; - struct passwd *pass = Get_Pwnam(name,True); + const struct passwd *pass = Get_Pwnam(name,True); int gid; int uid; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index daead8bb82..c05b82ef15 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -415,7 +415,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, uchar *lm_pwd, uchar *nt_pwd, struct passwd *pwd, uchar user_sess_key[16]) { - struct passwd *pass; + const struct passwd *pass; struct smb_passwd *smb_pass; if (!lm_pwd || !nt_pwd) @@ -877,7 +877,7 @@ BOOL check_hosts_equiv(char *user) { char *fname = NULL; pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user,True); + const struct passwd *pass = Get_Pwnam(user,True); if (!pass) return(False); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b20236d6f4..faf9c051d2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -774,7 +774,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int user we should become. */ { - struct passwd *pw = Get_Pwnam(user,False); + const struct passwd *pw = Get_Pwnam(user,False); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); return(ERROR(ERRSRV,ERRbadpw)); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 7628f9c8f0..becfd01504 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -194,7 +194,7 @@ int find_service(char *service) connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode) { int snum; - struct passwd *pass = NULL; + const struct passwd *pass = NULL; BOOL guest = False; BOOL force = False; extern int Client; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b2407ed5fc..92565b7507 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -163,7 +163,7 @@ become the guest user BOOL become_guest(void) { BOOL ret; - static struct passwd *pass=NULL; + static const struct passwd *pass=NULL; if (initial_uid != 0) return(True); -- cgit From 07afc549e2cde45e1c5b536cc03903fe8765902f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 24 Jun 1999 18:50:55 +0000 Subject: debugging of NBT messages added. (This used to be commit ceb20adb3c924818201fa8992e19e82f45b40710) --- source3/smbd/reply.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index faf9c051d2..58f327771d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -125,6 +125,9 @@ int reply_special(char *inbuf,char *outbuf) smb_setlen(outbuf,0); + DEBUG(20,("NBT message\n")); + dump_data(20, inbuf, smb_len(inbuf)); + switch (msg_type) { case 0x81: /* session request */ CVAL(outbuf,0) = 0x82; -- cgit From 73891ca8e4f6cca6aa8bb0ae043f660a64baa056 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 29 Jun 1999 18:47:06 +0000 Subject: improving authentication code (tidyup). (This used to be commit ab1a6aa42db5217f025941fb5107436556bc23b7) --- source3/smbd/password.c | 147 +++++++++++++++++++++++++++++++++--------------- source3/smbd/reply.c | 8 ++- source3/smbd/service.c | 4 +- 3 files changed, 109 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c05b82ef15..14a63c6ef4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -292,51 +292,78 @@ static BOOL update_smbpassword_file(char *user, char *password) /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8) +static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd, + unsigned char *c8) { /* Finish the encryption of part_passwd. */ - unsigned char p21[21]; unsigned char p24[24]; if (part_passwd == NULL) DEBUG(10,("No password set - allowing access\n")); /* No password set - always true ! */ if (part_passwd == NULL) - return 1; + return True; - memset(p21,'\0',21); - memcpy(p21,part_passwd,16); - E_P24(p21, c8, p24); + SMBOWFencrypt(part_passwd, c8, p24); #if DEBUG_PASSWORD - { - int i; - DEBUG(100,("Part password (P16) was |")); - for(i = 0; i < 16; i++) - DEBUG(100,("%X ", (unsigned char)part_passwd[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Password from client was |")); - for(i = 0; i < 24; i++) - DEBUG(100,("%X ", (unsigned char)password[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Given challenge was |")); - for(i = 0; i < 8; i++) - DEBUG(100,("%X ", (unsigned char)c8[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Value from encryption was |")); - for(i = 0; i < 24; i++) - DEBUG(100,("%X ", (unsigned char)p24[i])); - DEBUG(100,("|\n")); - } + DEBUG(100,("Part password (P16) was |")); + dump_data(100, part_passwd, 16); + DEBUG(100,("Password from client was |")); + dump_data(100, password, 24); + DEBUG(100,("Given challenge was |")); + dump_data(100, c8, 8); + DEBUG(100,("Value from encryption was |")); + dump_data(100, p24, 24); #endif return (memcmp(p24, password, 24) == 0); } +/**************************************************************************** +core of smb password checking routine. +****************************************************************************/ +static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len, + unsigned char *part_passwd, + unsigned char const *c8, + const char *user, const char *domain) +{ + /* Finish the encryption of part_passwd. */ + unsigned char kr[16]; + + if (part_passwd == NULL) + { + DEBUG(10,("No password set - allowing access\n")); + } + /* No password set - always true ! */ + if (part_passwd == NULL) + { + return True; + } + + ntv2_owf_gen(part_passwd, user, domain, kr); + SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, kr); + +#if DEBUG_PASSWORD + DEBUG(100,("Part password (P16) was |")); + dump_data(100, part_passwd, 16); + DEBUG(100,("Password from client was |")); + dump_data(100, password, pwd_len); + DEBUG(100,("Given challenge was |")); + dump_data(100, c8, 8); + DEBUG(100,("Value from encryption was |")); + dump_data(100, kr, 16); +#endif + + return (memcmp(kr, password, 16) == 0); +} + /**************************************************************************** Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], - uchar lm_pass[24], uchar nt_pass[24]) + const char *user, const char *domain, + uchar *lm_pass, size_t lm_pwd_len, + uchar *nt_pass, size_t nt_pwd_len) { uchar challenge[8]; @@ -345,7 +372,8 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], DEBUG(4,("Checking SMB password for user %s\n", smb_pass->unix_name)); - if(smb_pass->acct_ctrl & ACB_DISABLED) { + if (smb_pass->acct_ctrl & ACB_DISABLED) + { DEBUG(3,("account for user %s was disabled.\n", smb_pass->unix_name)); return(False); @@ -366,35 +394,59 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], memcpy(challenge, chal, 8); } - if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) { + if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) + { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_password_check((char *)nt_pass, + if (lp_server_ntlmv2()) + { + DEBUG(4,("smb_password_ok: Check NTLMv2 password\n")); + if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len, + (uchar *)smb_pass->smb_nt_passwd, + challenge, user, domain)) + { + return True; + } + } + if (lp_server_ntlmv2() != True && nt_pwd_len == 24) + { + DEBUG(4,("smb_password_ok: Check NT MD4 password\n")); + if (smb_pwd_check_ntlmv1((char *)nt_pass, (uchar *)smb_pass->smb_nt_passwd, - challenge)) { - DEBUG(4,("NT MD4 password check succeeded\n")); - return(True); + challenge)) + { + DEBUG(4,("NT MD4 password check succeeded\n")); + return True; + } } DEBUG(4,("NT MD4 password check failed\n")); } + if (lp_server_ntlmv2() == False) + { + DEBUG(4,("Not checking LM MD4 password\n")); + return False; + } + /* Try against the lanman password. smb_pass->smb_passwd == NULL means no password, allow access. */ DEBUG(4,("Checking LM MD4 password\n")); - if((smb_pass->smb_passwd == NULL) && - (smb_pass->acct_ctrl & ACB_PWNOTREQ)) { + if ((smb_pass->smb_passwd == NULL) && + (smb_pass->acct_ctrl & ACB_PWNOTREQ)) + { DEBUG(4,("no password required for user %s\n", smb_pass->unix_name)); return True; } - if((smb_pass->smb_passwd != NULL) && - smb_password_check((char *)lm_pass, - (uchar *)smb_pass->smb_passwd, challenge)) { + if ((smb_pass->smb_passwd != NULL) && + smb_pwd_check_ntlmv1((char *)lm_pass, + (uchar *)smb_pass->smb_passwd, + challenge)) + { DEBUG(4,("LM MD4 password check succeeded\n")); return(True); } @@ -411,8 +463,9 @@ SMB hash return True if the password is correct, False otherwise ****************************************************************************/ -BOOL pass_check_smb(char *user, char *domain, - uchar *chal, uchar *lm_pwd, uchar *nt_pwd, +BOOL pass_check_smb(char *user, char *domain, uchar *chal, + uchar *lm_pwd, size_t lm_pwd_len, + uchar *nt_pwd, size_t nt_pwd_len, struct passwd *pwd, uchar user_sess_key[16]) { const struct passwd *pass; @@ -466,7 +519,9 @@ BOOL pass_check_smb(char *user, char *domain, return(True); } - if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) + if (smb_password_ok(smb_pass, chal, user, domain, + lm_pwd, lm_pwd_len, + nt_pwd, nt_pwd_len)) { if (user_sess_key != NULL) { @@ -479,7 +534,7 @@ BOOL pass_check_smb(char *user, char *domain, return(True); } - DEBUG(3,("Error smb_password_check failed\n")); + DEBUG(3,("Error pass_check_smb failed\n")); return False; } @@ -491,9 +546,9 @@ return True if the password is correct, False otherwise BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, uchar user_sess_key[16]) { - if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) + if (pwlen >= 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { - /* if 24 bytes long assume it is an encrypted password */ + /* if 24 bytes or longer assume it is an encrypted password */ uchar challenge[8]; if (!last_challenge(challenge)) @@ -503,7 +558,9 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, } return pass_check_smb(user, global_myworkgroup, - challenge, (uchar *)password, (uchar *)password, pwd, user_sess_key); + challenge, (uchar *)password, + pwlen, (uchar *)password, pwlen, + pwd, user_sess_key); } return pass_check(user, password, pwlen, pwd, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 58f327771d..c44cf069a9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -441,7 +441,9 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) + if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL, + (unsigned char *)smb_passwd, smb_passlen, + (unsigned char *)smb_nt_passwd, smb_nt_passlen)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); @@ -570,7 +572,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int set_remote_arch( RA_WIN95); } - if (passlen1 != 24 && passlen2 != 24) + if (passlen1 != 24 && passlen2 <= 24) doencrypt = False; if (passlen1 > MAX_PASS_LEN) { @@ -593,7 +595,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int setting passlen2 to some random value which really stuffs things up. we need to fix that one. */ - if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1) + if (passlen1 > 0 && passlen2 > 0 && passlen2 <= 24 && passlen2 != 1) passlen2 = 0; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index becfd01504..232579a0f1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -390,10 +390,10 @@ connection_struct *make_connection(char *service,char *user,char *password, int #endif if (*lp_force_user(snum)) { - struct passwd *pass2; + const struct passwd *pass2; fstring fuser; fstrcpy(fuser,lp_force_user(snum)); - pass2 = (struct passwd *)Get_Pwnam(fuser,True); + pass2 = (const struct passwd *)Get_Pwnam(fuser,True); if (pass2) { conn->uid = pass2->pw_uid; string_set(&conn->user,fuser); -- cgit From ec711742c0b656e8c660f1d990e16b64addbf119 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 6 Jul 1999 21:25:42 +0000 Subject: smb_password_ok() checking incorrectly whether lm password exists. when lmcompatibilitylevel=0x2 on nt sp4+ clients, lm# is not sent. (This used to be commit e655e68474dd0234b49c23a07d9cb8bdd8f6016a) --- source3/smbd/password.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 14a63c6ef4..026fd5c10c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -85,7 +85,7 @@ get the last challenge sent ********************************************************************/ static BOOL last_challenge(unsigned char *challenge) { - if (!challenge_sent) return(False); + if (!challenge_sent) return False; memcpy(challenge,saved_challenge,8); return(True); } @@ -367,7 +367,10 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], { uchar challenge[8]; - if (!lm_pass || !smb_pass) return(False); + if (smb_pass == NULL) + { + return False; + } DEBUG(4,("Checking SMB password for user %s\n", smb_pass->unix_name)); @@ -376,7 +379,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], { DEBUG(3,("account for user %s was disabled.\n", smb_pass->unix_name)); - return(False); + return False; } if (chal == NULL) @@ -473,7 +476,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (!lm_pwd || !nt_pwd) { - return(False); + return False; } if (pwd != NULL && user == NULL) @@ -489,7 +492,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (pass == NULL) { DEBUG(3,("Couldn't find user %s\n",user)); - return(False); + return False; } smb_pass = getsmbpwnam(user); @@ -497,20 +500,20 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (smb_pass == NULL) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); - return(False); + return False; } /* Quit if the account was disabled. */ if(smb_pass->acct_ctrl & ACB_DISABLED) { DEBUG(3,("account for user %s was disabled.\n", user)); - return(False); + return False; } /* Ensure the uid's match */ if (smb_pass->unix_uid != pass->pw_uid) { DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); - return(False); + return False; } if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords()) @@ -722,7 +725,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, { char *auser; char *user_list = strdup(session_users); - if (!user_list) return(False); + if (!user_list) return False; for (auser=strtok(user_list,LIST_SEP); !ok && auser; @@ -937,7 +940,7 @@ BOOL check_hosts_equiv(char *user) const struct passwd *pass = Get_Pwnam(user,True); if (!pass) - return(False); + return False; fname = lp_hosts_equiv(); @@ -959,7 +962,7 @@ BOOL check_hosts_equiv(char *user) } } - return(False); + return False; } @@ -1000,7 +1003,7 @@ BOOL server_validate(char *user, char *domain, if (!cli->initialised) { DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return(False); + return False; } if(badpass[0] == 0) @@ -1075,7 +1078,7 @@ use this machine as the password server.\n")); if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); cli_ulogoff(cli); - return(False); + return False; } -- cgit From e71801c3de1e2bc0cb710cb1157adea1b50e12e1 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 6 Jul 1999 21:26:39 +0000 Subject: reporting failure to accept ntlmv2 (only) with down-level protocols (LANMAN1 and below). (This used to be commit be7b978249ddb5e2e94aa160a360fecbf51f016e) --- source3/smbd/reply.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c44cf069a9..29dccaf9e8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -537,7 +537,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int smb_bufsize = SVAL(inbuf,smb_vwv2); - if (Protocol < PROTOCOL_NT1) { + if (Protocol < PROTOCOL_NT1) + { smb_apasslen = SVAL(inbuf,smb_vwv7); if (smb_apasslen > MAX_PASS_LEN) { @@ -551,7 +552,16 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!doencrypt && (lp_security() != SEC_SERVER)) { smb_apasslen = strlen(smb_apasswd); } - } else { + + if (lp_server_ntlmv2() == True) + { + DEBUG(1,("NTLMv2-only accepted with NT LANMAN 1.0 and above.\n\ +user %s attempted down-level SMB connection\n", user)); + return(ERROR(ERRSRV,ERRbadpw)); + } + } + else + { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); enum remote_arch_types ra_type = get_remote_arch(); @@ -707,7 +717,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * 128 length unicode. */ - if(smb_ntpasslen) + if (smb_ntpasslen) { if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key)) DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); -- cgit From 527820d30646f3954155a509752e2b08c96b1448 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 7 Jul 1999 16:44:38 +0000 Subject: oops, refused lm when ntlmv2 was true not false/auto. oops! (This used to be commit 6b4b24d2208b1b076dfc2f7202917ca0acaeb398) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 026fd5c10c..b10bc33a3a 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -426,7 +426,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], DEBUG(4,("NT MD4 password check failed\n")); } - if (lp_server_ntlmv2() == False) + if (lp_server_ntlmv2() == True) { DEBUG(4,("Not checking LM MD4 password\n")); return False; -- cgit From 8f1404739fe75464fe1500c3f6e6d39d4878ec1e Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 12 Jul 1999 18:46:15 +0000 Subject: Jean-Francois Micouleau's rewritten DFS patch, originally written by Nigel Williams. despite the data format being *exactly* the same as NT's, this still doesn't work yet. more work needed. (This used to be commit 270981960bb5aab52d2f8e494827101ece6729c4) --- source3/smbd/negprot.c | 7 + source3/smbd/nttrans.c | 1 + source3/smbd/process.c | 2 +- source3/smbd/reply.c | 10 ++ source3/smbd/server.c | 3 + source3/smbd/trans2.c | 398 +++++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 354 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e66bf9f163..51ec963b8c 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -27,6 +27,7 @@ extern int max_recv; extern fstring global_myworkgroup; extern fstring remote_machine; extern pstring myhostname; +extern dfs_internal dfs_struct; /**************************************************************************** reply for the core protocol @@ -178,6 +179,12 @@ static int reply_nt1(char *outbuf) { capabilities |= CAP_LARGE_FILES; } + + if (dfs_struct.ready==True) + { + capabilities |= CAP_DFS; + } + /* other valid capabilities which we may support at some time... CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5c26c7f578..657dd8b130 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1666,6 +1666,7 @@ due to being in oplock break state.\n" )); length, bufsize, &setup, ¶ms, &data); break; + default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a4c1acba8f..bc60cb474d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -339,7 +339,7 @@ struct smb_message_struct /* LANMAN2.0 PROTOCOL FOLLOWS */ {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER }, + {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | CAN_IPC}, {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, /* NT PROTOCOL FOLLOWS */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 29dccaf9e8..652d6e4795 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -835,6 +835,11 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unix_convert(name,conn,0,&bad_path,&st); mode = SVAL(inbuf,smb_vwv0); + + if(under_dfs(conn, name)) { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(name,conn)) { if(VALID_STAT(st)) @@ -892,6 +897,11 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); + + if (under_dfs(conn, fname)) { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 339fab8398..4ea39e14c6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -27,6 +27,7 @@ extern pstring debugf; extern fstring global_myworkgroup; extern fstring global_sam_name; extern pstring global_myname; +extern dfs_internal dfs_struct; int am_parent = 1; @@ -50,6 +51,7 @@ extern fstring remote_machine; extern pstring OriginalDir; extern pstring myhostname; + /**************************************************************************** when exiting, take the whole family ****************************************************************************/ @@ -452,6 +454,7 @@ static void init_structs(void) init_lsa_policy_hnd(); /* for LSA handles */ init_printer_hnd(); /* for SPOOLSS handles */ init_dptrs(); + init_dfs_table(); } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8a182399e7..381f4ed392 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -31,6 +31,7 @@ extern int Client; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; +extern dfs_internal dfs_struct; /**************************************************************************** Send the required number of replies back. @@ -112,7 +113,8 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, SSVAL(outbuf,smb_prcnt, params_sent_thistime); if(params_sent_thistime == 0) { - SSVAL(outbuf,smb_proff,0); + /*SSVAL(outbuf,smb_proff,0);*/ + SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); SSVAL(outbuf,smb_prdisp,0); } else @@ -2019,6 +2021,238 @@ int reply_findnclose(connection_struct *conn, return(outsize); } +/**************************************************************************** + reply to a TRANS2_GET_DFS_REFERRAL + ****************************************************************************/ +static int call_trans2getdfsreferral(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, + char **pparams, char **ppdata, + int total_data) +{ + char *params = *pparams; + char *pdata; + char *pheader; + char *localstring_offset; + char *mangledstring_offset; + char *sharename_offset; + char *referal_offset; + + int i; + int j; + unsigned int total_params = SVAL(inbuf, smb_tpscnt); + int query_file_len=0; + int bytesreq=0; + int filename_len; + + BOOL first_one=True; + + referal_trans_param rtp; + dfs_internal_table *list=dfs_struct.table; + dfs_response reply; + + DEBUG(0,("call_trans2getdfsreferral:1\n")); + + ZERO_STRUCT(rtp); + /* decode the param member of query */ + rtp.level=SVAL(params, 0); + DEBUGADD(0,("rtp.level:[%d]\n",rtp.level)); + + DEBUGADD(0,("total_params:[%d]\n",total_params)); + for (i=0; i<(total_params-2)/2; i++) + { + rtp.directory[i]=SVAL(params, 2+2*i); + } +/* + strupper(rtp.directory); +*/ + query_file_len=strlen(rtp.directory); + DEBUGADD(0,("rtp.directory:[%s]\n",rtp.directory)); + DEBUGADD(0,("query_file_len:[%d]\n",query_file_len)); + + /* + lookup in the internal DFS table all the entries + and calculate the required data buffer size + */ + bytesreq=8; /* the header */ + reply.number_of_referal=0; + DEBUGADD(0,("call_trans2getdfsreferral:2\n")); + + for(i=0; i Date: Mon, 12 Jul 1999 18:57:05 +0000 Subject: lengths of NT passwords when "encrypt passwords = no" can be completely random. values seen can be as high as 18255. this fails the check of <= 24 which sets NT password length to 0, effectively ignoring it. the <= 24 was removed in reply_sesssetup_X. (This used to be commit 98d43b20dc4df72ddbfaeb34581222adc53d15dd) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 652d6e4795..bfa68ab140 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -605,7 +605,7 @@ user %s attempted down-level SMB connection\n", user)); setting passlen2 to some random value which really stuffs things up. we need to fix that one. */ - if (passlen1 > 0 && passlen2 > 0 && passlen2 <= 24 && passlen2 != 1) + if (passlen1 > 0 && passlen2 > 0 && passlen2 != 1) passlen2 = 0; } -- cgit From d9a18c82d13dda861e1cbcce8390b52aa73118a5 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 12 Jul 1999 21:33:11 +0000 Subject: Jean-Francois Micouleau's rewrite of Nigel William's DFS support (This used to be commit e6116c40d4d0473a7412e82791afd9f44e4905a4) --- source3/smbd/dfs.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 source3/smbd/dfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/dfs.c b/source3/smbd/dfs.c new file mode 100644 index 0000000000..0c1b3db4c4 --- /dev/null +++ b/source3/smbd/dfs.c @@ -0,0 +1,215 @@ + +#include "includes.h" + +extern int DEBUGLEVEL; + +dfs_internal dfs_struct; +extern pstring global_myname; + +/**************************************************************************** +read a line and split it +****************************************************************************/ +static BOOL parse_dfs_text_entry(char *line, dfs_internal_table *buf) +{ +#define MAXTOK 4 + char *tok[MAXTOK+1]; + int count = 0; + + tok[count] = strtok(line,":"); + + /* strip the comment lines */ + if (tok[0][0]=='#') return (False); + count++; + + while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count1) { + StrnCpy(buf->localpath, tok[0], sizeof(buf->localpath)-1); + StrnCpy(buf->sharename, tok[1], sizeof(buf->sharename)-1); +/* + strupper(buf->localpath); + strupper(buf->sharename); +*/ + buf->localpath_length=strlen(buf->localpath); + buf->sharename_length=strlen(buf->sharename); + } + else + return (False); + + if (count>2) + buf->proximity = atoi(tok[2]); + else + buf->proximity = 0; + + if (count>3) + buf->type = atoi(tok[3]); + else + buf->type = 2; + + DEBUGADD(7,("[%s]\n", buf->localpath)); + DEBUGADD(7,("[%s]\n", buf->sharename)); + return(True); +} + +/**************************************************************************** +mangle the localpath and store it. +****************************************************************************/ +static void mangle_dfs_path(dfs_internal_table *buf) +{ + char *p; + char *s; + char *q; + int i; + + fstring temp; + + p=buf->localpath; + s=buf->mangledpath; + + ZERO_STRUCTP(s); + DEBUG(0, ("DFS name is:[%s]\n", buf->localpath)); + + /* copy the head: \server-name\ */ + q=strchr(p+1, '\\'); + strncpy(s, p, q-p+1); + p=q+1; + + while (q!=NULL) + { + q=strchr(p, '\\'); + if (q!=NULL) + i=PTR_DIFF(q,p); + else + i=strlen(p); + + strncpy(temp, p, i); + + if (!is_8_3(temp, True)) + mangle_name_83(temp); + + strncat(s, temp, i); + if (q!=NULL) + strncat(s, "\\", 1); + p=q+1; + } + +/* + strupper(buf->mangledpath); +*/ + buf->mangledpath_length=strlen(buf->mangledpath); + DEBUGADD(0, ("DFS mangled name is: [%s]\n", buf->mangledpath)); +} + +/**************************************************************************** +initialisation de la table dfs en memoire au demarrage de samba +****************************************************************************/ +BOOL init_dfs_table(void) +{ + char *file=lp_dfs_map(); + int num_lines=0; + int total=0; + FILE *f; + pstring line; + int i; + + dfs_internal_table *entry; + + entry=NULL; + dfs_struct.ready=False; + + if (*file=='\0') { + DEBUG(0,("No DFS map, Samba is running in NON DFS mode\n")); + return False; + } + + f = sys_fopen(file, "r"); + if (!f) { + DEBUG(0,("No DFS map file, Samba is running in NON DFS mode\n")); + return False; + } + + while ( fgets(line, sizeof(pstring), f) ) + { + entry = Realloc(entry,sizeof(dfs_internal_table)*(total+1)); + if (! entry) + { + total = 0; + break; + } + + if ( parse_dfs_text_entry(line, &(entry[total]) ) ) + { + total++; + } + num_lines++; + } + dfs_struct.size=total; + dfs_struct.table=entry; + fclose(f); + + /* we have the file in memory */ + /* now initialise the mangled names */ + for (i=0; i Date: Tue, 13 Jul 1999 19:52:33 +0000 Subject: dfs parsed string length was being set explicitly to value "6", overwriting the correct length. (This used to be commit 5d1fad53c2bdfef63930e0b9d5cc460c9740066e) --- source3/smbd/trans2.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 381f4ed392..7cfe291c0d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2021,6 +2021,8 @@ int reply_findnclose(connection_struct *conn, return(outsize); } +#define UNICODE_DFS + /**************************************************************************** reply to a TRANS2_GET_DFS_REFERRAL ****************************************************************************/ @@ -2054,6 +2056,8 @@ static int call_trans2getdfsreferral(connection_struct *conn, DEBUG(0,("call_trans2getdfsreferral:1\n")); ZERO_STRUCT(rtp); + ZERO_STRUCT(reply); + /* decode the param member of query */ rtp.level=SVAL(params, 0); DEBUGADD(0,("rtp.level:[%d]\n",rtp.level)); @@ -2084,7 +2088,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, DEBUGADD(0,("checking against [%s][%d]\n", list[i].localpath, filename_len)); if( (filename_len==query_file_len) && - (!strncmp(rtp.directory, list[i].localpath, query_file_len)) ) + (!StrnCaseCmp(rtp.directory, list[i].localpath, query_file_len)) ) { bytesreq+=22; /* the referal size */ @@ -2117,14 +2121,14 @@ static int call_trans2getdfsreferral(connection_struct *conn, localstring_offset = pdata + 8 + reply.number_of_referal*22; -/* unicode version */ +#ifdef UNICODE_DFS mangledstring_offset = localstring_offset + 2*(1+strlen(reply.filename)); sharename_offset = mangledstring_offset + 2*(1+strlen(reply.mangledname)); -/*ascii version +#else mangledstring_offset = localstring_offset + (1+strlen(reply.filename)); sharename_offset = mangledstring_offset + (1+strlen(reply.mangledname)); -*/ +#endif referal_offset = pdata + 8; /* right now respond storage server */ @@ -2134,50 +2138,45 @@ static int call_trans2getdfsreferral(connection_struct *conn, reply.server_function=1; /* write the header */ -/* unicode version*/ - /*SSVAL(pheader, 0, reply.path_consumed*2);*/ -/*ascii version - +#ifdef UNICODE_DFS + SSVAL(pheader, 0, reply.path_consumed*2); +#else SSVAL(pheader, 0, reply.path_consumed); -*/ - - SSVAL(pheader, 0, 6); - +#endif SSVAL(pheader, 2, reply.number_of_referal); SIVAL(pheader, 4, reply.server_function); /* write the local path string */ -/* unicode version*/ +#ifdef UNICODE_DFS for(i=0; i Date: Wed, 14 Jul 1999 18:16:57 +0000 Subject: removed strncpy() (This used to be commit 4bdff2748956a61f12a92e19a9af98c7b9668e8f) --- source3/smbd/dfs.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfs.c b/source3/smbd/dfs.c index 0c1b3db4c4..baae960538 100644 --- a/source3/smbd/dfs.c +++ b/source3/smbd/dfs.c @@ -62,47 +62,49 @@ mangle the localpath and store it. static void mangle_dfs_path(dfs_internal_table *buf) { char *p; - char *s; + char *mp; char *q; - int i; + int mlen; fstring temp; - p=buf->localpath; - s=buf->mangledpath; + p = buf->localpath; + mp =buf->mangledpath; + mlen = sizeof(buf->mangledpath); - ZERO_STRUCTP(s); - DEBUG(0, ("DFS name is:[%s]\n", buf->localpath)); + ZERO_STRUCTP(mp); + DEBUG(2, ("DFS name is: [%s]\n", buf->localpath)); /* copy the head: \server-name\ */ - q=strchr(p+1, '\\'); - strncpy(s, p, q-p+1); - p=q+1; + q = strchr(p + 1, '\\'); + safe_strcpy(mp, p, mlen); + p = q + 1; - while (q!=NULL) + while (q != NULL) { - q=strchr(p, '\\'); - if (q!=NULL) - i=PTR_DIFF(q,p); - else - i=strlen(p); + q = strchr(p, '\\'); - strncpy(temp, p, i); + safe_strcpy(temp, p, sizeof(temp)); if (!is_8_3(temp, True)) + { mangle_name_83(temp); + } - strncat(s, temp, i); - if (q!=NULL) - strncat(s, "\\", 1); - p=q+1; + safe_strcat(mp, temp, mlen); + + if (q != NULL) + { + safe_strcat(mp, "\\", mlen); + } + p = q + 1; } /* - strupper(buf->mangledpath); + strupper(mp); */ - buf->mangledpath_length=strlen(buf->mangledpath); - DEBUGADD(0, ("DFS mangled name is: [%s]\n", buf->mangledpath)); + buf->mangledpath_length = strlen(mp); + DEBUGADD(2, ("DFS mangled name is: [%s]\n", mp)); } /**************************************************************************** -- cgit From 92b8937bae9139e3f7464b8cba445e929c802381 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 15 Jul 1999 17:50:27 +0000 Subject: added %d %d to error message, try to track down the uid / smb_uid mismatch (This used to be commit ec918ba144e7c1bd1689007143ca2b8bee604768) --- source3/smbd/password.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b10bc33a3a..1f1ca12713 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -504,7 +504,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, } /* Quit if the account was disabled. */ - if(smb_pass->acct_ctrl & ACB_DISABLED) { + if (smb_pass->acct_ctrl & ACB_DISABLED) { DEBUG(3,("account for user %s was disabled.\n", user)); return False; } @@ -512,7 +512,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, /* Ensure the uid's match */ if (smb_pass->unix_uid != pass->pw_uid) { - DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); + DEBUG(3,("Error : UNIX (%d) and SMB (%d) uids in password files do not match !\n", pass->pw_uid, smb_pass->unix_uid)); return False; } -- cgit From 2b354d7330785337558a678f2b2484691ad7f2eb Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 15 Jul 1999 17:52:44 +0000 Subject: dfs issues (This used to be commit d9ada8b55d539e555d25298e0a308ea952e2807e) --- source3/smbd/dfs.c | 21 ++++++++++++++------- source3/smbd/trans2.c | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfs.c b/source3/smbd/dfs.c index baae960538..ca45d89b37 100644 --- a/source3/smbd/dfs.c +++ b/source3/smbd/dfs.c @@ -184,14 +184,21 @@ int under_dfs(connection_struct *conn, const char *path) dfs_internal_table *list=dfs_struct.table; snum=SNUM(conn); - snprintf(fullpath, sizeof(fullpath), "\\%s\\%s\\%s", global_myname, - lp_servicename(snum), path); + if (path[0] != '\\') + { + snprintf(fullpath, sizeof(fullpath), "\\%s\\%s\\%s", + global_myname, lp_servicename(snum), path); + } + else + { + safe_strcpy(fullpath, path, sizeof(fullpath)); + } strupper(fullpath); path_len=strlen(fullpath); - DEBUG(0,("looking for: [%s]\n", fullpath)); + DEBUG(2,("DFS looking for: [%s]\n", fullpath)); for(i=0; i Date: Thu, 15 Jul 1999 20:44:24 +0000 Subject: more dfs stuff. this looks like it's going to be more appropriate to use the vfs tables. at the moment, i replaced all calls to unix_convert() with unix_dfs_convert(). this does the job, but it's not very nice. (This used to be commit 00d4aebce9f268a737ef9df9bdbe59f8fe831979) --- source3/smbd/dfs.c | 125 ++++++++++++++++++++++++++++++------------------ source3/smbd/filename.c | 36 ++++++++++++-- source3/smbd/nttrans.c | 12 ++++- source3/smbd/reply.c | 100 ++++++++++++++++++++++++++++---------- source3/smbd/trans2.c | 42 +++++++++++++--- 5 files changed, 231 insertions(+), 84 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfs.c b/source3/smbd/dfs.c index ca45d89b37..55433f2c47 100644 --- a/source3/smbd/dfs.c +++ b/source3/smbd/dfs.c @@ -18,42 +18,42 @@ static BOOL parse_dfs_text_entry(char *line, dfs_internal_table *buf) tok[count] = strtok(line,":"); /* strip the comment lines */ - if (tok[0][0]=='#') return (False); + if (tok[0][0] == '#') return (False); count++; - while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count1) { + if (count > 1) { StrnCpy(buf->localpath, tok[0], sizeof(buf->localpath)-1); StrnCpy(buf->sharename, tok[1], sizeof(buf->sharename)-1); /* strupper(buf->localpath); strupper(buf->sharename); */ - buf->localpath_length=strlen(buf->localpath); - buf->sharename_length=strlen(buf->sharename); + buf->localpath_length = strlen(buf->localpath); + buf->sharename_length = strlen(buf->sharename); } else return (False); - if (count>2) + if (count > 2) buf->proximity = atoi(tok[2]); else buf->proximity = 0; - if (count>3) + if (count > 3) buf->type = atoi(tok[3]); else buf->type = 2; - DEBUGADD(7,("[%s]\n", buf->localpath)); - DEBUGADD(7,("[%s]\n", buf->sharename)); - return(True); + DEBUGADD(7,("localpath: [%s]\n", buf->localpath)); + DEBUGADD(7,("sharename: [%s]\n", buf->sharename)); + return True; } /**************************************************************************** @@ -69,7 +69,7 @@ static void mangle_dfs_path(dfs_internal_table *buf) fstring temp; p = buf->localpath; - mp =buf->mangledpath; + mp = buf->mangledpath; mlen = sizeof(buf->mangledpath); ZERO_STRUCTP(mp); @@ -112,19 +112,19 @@ initialisation de la table dfs en memoire au demarrage de samba ****************************************************************************/ BOOL init_dfs_table(void) { - char *file=lp_dfs_map(); - int num_lines=0; - int total=0; + char *file = lp_dfs_map(); + int num_lines = 0; + int total = 0; FILE *f; pstring line; int i; dfs_internal_table *entry; - entry=NULL; - dfs_struct.ready=False; + entry = NULL; + dfs_struct.ready = False; - if (*file=='\0') { + if (*file == '\0') { DEBUG(0,("No DFS map, Samba is running in NON DFS mode\n")); return False; } @@ -150,75 +150,106 @@ BOOL init_dfs_table(void) } num_lines++; } - dfs_struct.size=total; - dfs_struct.table=entry; + dfs_struct.size = total; + dfs_struct.table = entry; fclose(f); /* we have the file in memory */ /* now initialise the mangled names */ - for (i=0; iname_len); } +/**************************************************************************** + this routine converts from the dos and dfs namespace to the unix namespace. +****************************************************************************/ +BOOL unix_dfs_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) +{ + pstring local_path; + + DEBUG(10,("unix_dfs_convert: %s\n", name)); + + if (name != NULL && + under_dfs(conn, name, local_path, sizeof(local_path))) + { + DEBUG(10,("%s is in dfs map.\n", name)); + + /* check for our own name */ + if (StrCaseCmp(global_myname, name+1) > 0) + { + return False; + } + + pstrcpy(name, local_path); + + DEBUG(10,("removed name: %s\n", name)); + } + return unix_convert(name, conn, saved_last_component, bad_path, pst); +} + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -329,9 +359,9 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ - -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) +BOOL unix_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 657dd8b130..ac688a5baa 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -669,7 +669,11 @@ int reply_ntcreate_and_X(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) { @@ -952,7 +956,11 @@ static int call_nt_transact_create(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bfa68ab140..b8300da40a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -832,15 +832,14 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT st; pstrcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,conn,0,&bad_path,&st); - - mode = SVAL(inbuf,smb_vwv0); - - if(under_dfs(conn, name)) { + if (!unix_dfs_convert(name,conn,0,&bad_path,&st)) + { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); } + mode = SVAL(inbuf,smb_vwv0); + if (check_name(name,conn)) { if(VALID_STAT(st)) ok = S_ISDIR(st.st_mode); @@ -898,11 +897,6 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(fname,smb_buf(inbuf) + 1); - if (under_dfs(conn, fname)) { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (! (*fname)) @@ -915,7 +909,11 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { - unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(fname,conn)) { if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0) @@ -980,7 +978,11 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,conn,0,&bad_path,&st); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); @@ -1087,7 +1089,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(directory,smb_buf(inbuf)+1); pstrcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } unix_format(dir2); if (!check_name(directory,conn)) @@ -1348,7 +1354,11 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) @@ -1453,7 +1463,11 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) @@ -1587,7 +1601,11 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (createmode & aVOLID) { @@ -1673,7 +1691,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } unixmode = unix_mode(conn,createmode); @@ -1779,7 +1801,11 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - unix_convert(name,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(name,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } p = strrchr(name,'/'); if (!p) { @@ -2940,7 +2966,11 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(directory, conn)) ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), @@ -3035,7 +3065,11 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,conn, NULL,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn, NULL,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(directory,conn)) { @@ -3236,12 +3270,20 @@ int rename_internals(connection_struct *conn, *directory = *mask = 0; - unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,newname_last_component,&bad_path2,NULL); + if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } + if (!unix_dfs_convert(newname,conn,newname_last_component,&bad_path2,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } /* * Split the old name into directory and last component - * strings. Note that unix_convert may have stripped off a + * strings. Note that if (!unix_dfs_convert may have stripped off a * leading ./ from both name and newname if the rename is * at the root of the share. We need to make sure either both * name and newname contain a / character or neither of them do @@ -3552,8 +3594,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRSRV,ERRinvdevice)); } - unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,0,&bad_path2,NULL); + if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } + if (!unix_dfs_convert(newname,conn,0,&bad_path2,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } target_is_directory = dos_directory_exist(newname,NULL); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f324b658b9..14fa26dd55 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -216,7 +216,11 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) @@ -665,7 +669,11 @@ static int call_trans2findfirst(connection_struct *conn, DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if(!check_name(directory,conn)) { if((errno == ENOENT) && bad_path) { @@ -1255,7 +1263,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, * to do this call. JRA. */ fname = fsp->fsp_name; - unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); @@ -1288,7 +1300,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = &fname1[0]; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False), &sbuf))) { @@ -1518,7 +1534,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * to do this call. JRA. */ fname = fsp->fsp_name; - unix_convert(fname,conn,0,&bad_path,&st); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (!check_name(fname,conn) || (!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); @@ -1549,7 +1569,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = fname1; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path,&st); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if(!check_name(fname, conn)) { if((errno == ENOENT) && bad_path) @@ -1880,7 +1904,11 @@ static int call_trans2mkdir(connection_struct *conn, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(directory,conn)) ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), unix_mode(conn,aDIR)); -- cgit From 7c29698e4182f034c0b8251be3bb9370cb35ec08 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 15 Jul 1999 21:25:58 +0000 Subject: work-around for win95 NULL session bug: NULL password actually being placed in data stream before username / domain, whereas NT doesn't do this... (This used to be commit 44e6d4c1b0b6ae54e76e96471b40bb784c8b3c8c) --- source3/smbd/reply.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b8300da40a..bb6e8654d3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -609,7 +609,7 @@ user %s attempted down-level SMB connection\n", user)); passlen2 = 0; } - if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { + if (doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; memcpy(smb_apasswd,p,smb_apasslen); @@ -632,12 +632,22 @@ user %s attempted down-level SMB connection\n", user)); } } - p += passlen1 + passlen2; + if (passlen2 == 0 && smb_apasslen == 0 && ra_type == RA_WIN95) + { + /* work-around for win95 NULL sessions, where NULL password is + actually put in the data stream before the domain name etc */ + p++; + } + else + { + p += passlen1 + passlen2; + } + fstrcpy(user,p); p = skip_string(p,1); domain = p; DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - domain,skip_string(p,1),skip_string(p,2))); + domain, skip_string(p,1), skip_string(p,2))); } DEBUG(3,("sesssetupX:name=[%s]\n",user)); -- cgit From 0262b2a6b49d3a2418e3f335f06cbb227382bc86 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 16 Jul 1999 22:03:15 +0000 Subject: copy of password struct needed to be made prior to calling copy_passwd_struct found by Bertl . (This used to be commit 93298bca1c573532c5250c84bac39cf9214ba3b5) --- source3/smbd/password.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1f1ca12713..022d432787 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -472,6 +472,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, struct passwd *pwd, uchar user_sess_key[16]) { const struct passwd *pass; + struct passwd pw; struct smb_passwd *smb_pass; if (!lm_pwd || !nt_pwd) @@ -487,12 +488,13 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, else { pass = Get_Pwnam(user,True); - } - - if (pass == NULL) - { - DEBUG(3,("Couldn't find user %s\n",user)); - return False; + if (pass == NULL) + { + DEBUG(3,("Couldn't find user %s\n",user)); + return False; + } + memcpy(&pw, pass, sizeof(struct passwd)); + pass = &pw; } smb_pass = getsmbpwnam(user); -- cgit From 33ed8059a2bbf8e8a43aee9ca9d6da736e84d686 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 16 Jul 1999 22:23:45 +0000 Subject: NTLMv2 check being actioned when NT password response was only 24 chars. added check to ensure response is more than 24 chars before bothering to do an NTLMv2 check. (This used to be commit 7a58895ff26fcad09ee45de99086739bf5761fd9) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 022d432787..6ec290ca25 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -402,7 +402,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - if (lp_server_ntlmv2()) + if (lp_server_ntlmv2() != False && nt_pwd_len > 24) { DEBUG(4,("smb_password_ok: Check NTLMv2 password\n")); if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len, -- cgit From 46ce0d4619839f40f910eb4a0d2c3da01436bc88 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 21 Jul 1999 00:31:16 +0000 Subject: comments requested by jeremy as to why NT/95 NULL-password distinction hack was modified. (This used to be commit 50f7bd8a9c47d073bbde66ae26e9f71f030afc4c) --- source3/smbd/reply.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bb6e8654d3..8723779d30 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -603,7 +603,12 @@ user %s attempted down-level SMB connection\n", user)); if passlen1>0 and passlen2>0 then maybe its a NT box and its setting passlen2 to some random value which really stuffs - things up. we need to fix that one. */ + things up. we need to fix that one. + + LKCLXXXX: the random value can be random 16 bit. old test + used to have ... && passlen <= 24) which of course fails + most of the time. + */ if (passlen1 > 0 && passlen2 > 0 && passlen2 != 1) passlen2 = 0; -- cgit From f809734105eaa1c111720111a10594a27bdf639f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 22 Jul 1999 04:43:59 +0000 Subject: Pass VFS options defined in smb.conf to vfs_init() function. (This used to be commit 8cde172a77a1582c0af2e685097c53ba5f302a4e) --- source3/smbd/vfs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b0bc1a9f4d..95bb4c9414 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -89,7 +89,7 @@ int vfs_init_default(connection_struct *conn) BOOL vfs_init_custom(connection_struct *conn) { void *handle; - struct vfs_ops *ops, *(*fptr)(void); + struct vfs_ops *ops, *(*fptr)(struct vfs_options *options); DEBUG(3, ("Initialising custom vfs hooks from %s\n", lp_vfsobj(SNUM(conn)))); @@ -114,13 +114,16 @@ BOOL vfs_init_custom(connection_struct *conn) dlclose(handle); - /* Initialise vfs_ops and fill in unused operations with default - (disk based) ones. There's probably a neater way to do this. */ + /* Initialise vfs_ops structure */ - if ((ops = fptr()) == NULL) { + if ((ops = fptr(lp_vfsoptions(SNUM(conn)))) == NULL) { return False; } + /* Fill in unused operations with default (disk based) ones. + There's probably a neater way to do this then a whole bunch of + if statements. */ + memcpy(&conn->vfs_ops, ops, sizeof(conn->vfs_ops)); if (conn->vfs_ops.connect == NULL) { -- cgit From 331ab45321dd37ba72b9569c1d62e887200595f3 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 22 Jul 1999 04:47:14 +0000 Subject: Copy service name into vfs_connection_struct. (This used to be commit 19242cd44e059d90e91f1c27bfb45899ce5de26a) --- source3/smbd/service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 232579a0f1..f0af82fb4e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -548,7 +548,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int pstrcpy(vconn->connectpath, conn->connectpath); pstrcpy(vconn->origpath, conn->origpath); + pstrcpy(vconn->service, service); pstrcpy(vconn->user, conn->user); + vconn->uid = conn->uid; vconn->gid = conn->gid; vconn->ngroups = conn->ngroups; -- cgit From dde759352fb8b097f20c680ac954708af2a86443 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 13 Aug 1999 19:35:33 +0000 Subject: pnum should be a uint16. (This used to be commit 41cb8b0ba071ef73bf00130ec863b592c16d359a) --- source3/smbd/ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index cdbb4416af..5a0bf6ac07 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3214,8 +3214,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, { BOOL reply = False; - int pnum; - int subcommand; + uint16 pnum; + uint16 subcommand; pipes_struct *p = NULL; prs_struct pd; -- cgit From ad000ee7dcf1c9c53f3222cb2e4c933bcc3c27b9 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 13 Aug 1999 21:11:38 +0000 Subject: spelling mistake. (This used to be commit b8ac96cd9c8efaf0e07651657f878a2dea127290) --- source3/smbd/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d366fa1e1a..7f4533e7ae 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -226,7 +226,7 @@ open files, %d are available.\n", request_max_open_files, real_max_open_files)); } /* - * Ensure that pipe_handle_oppset is set correctly. + * Ensure that pipe_handle_offset is set correctly. */ set_pipe_handle_offset(real_max_open_files); } -- cgit From 7f8f5e15bdffec00454168c0591fa39a88d191c2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 8 Sep 1999 19:37:45 +0000 Subject: bertl patch for making samba listen on port 445, just like nt 5 does. cool! (This used to be commit 727e1421b2c0f8c72c428776593498103304082b) --- source3/smbd/process.c | 28 +++++++++++++++++++ source3/smbd/server.c | 76 +++++++++++++++++++++++++++++++------------------- 2 files changed, 76 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index bc60cb474d..13dd932a57 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -746,6 +746,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) void smbd_process(void) { extern int Client; + extern int ClientPort; InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); @@ -772,6 +773,33 @@ void smbd_process(void) /* re-initialise the timezone */ TimeInit(); + /* if connection on port 445, fake session setup... */ + if(ClientPort == 445) + { + extern fstring remote_machine; + extern fstring local_machine; + char *s; + + fstrcpy(remote_machine, dns_to_netbios_name(client_name(Client))); + fstrcpy(local_machine, global_myname); + remote_machine[15] = 0; + local_machine[15] = 0; + strlower(remote_machine); + strlower(local_machine); + + DEBUG(2, ("smbd_process(): faking session setup\n" + "client_name: %s my_name: %s\n", remote_machine, local_machine)); + + add_session_user(remote_machine); + + reload_services(True); + reopen_logs(); + + if(lp_status(-1)) { + claim_connection(NULL,"STATUS.",MAXSTATUS,True); + } + } + while (True) { int deadtime = lp_deadtime()*60; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4ea39e14c6..036ca9353c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -76,11 +76,13 @@ static void killkids(void) static BOOL open_sockets_inetd(void) { extern int Client; + extern int ClientPort; /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ Client = dup(0); + ClientPort = 138; /* close our standard file descriptors */ close_low_fds(); @@ -91,13 +93,32 @@ static BOOL open_sockets_inetd(void) return True; } +/**************************************************************************** + open and listen to a socket +****************************************************************************/ +static int open_server_socket(int port, ulong ipaddr) +{ + int s; + + s = open_socket_in(SOCK_STREAM, port, 0, ipaddr); + if(s == -1) + return -1; + /* ready to listen */ + if (listen(s, 5) == -1) { + DEBUG(0,("listen: %s\n", strerror(errno))); + close(s); + return -1; + } + return s; +} /**************************************************************************** open the socket communication ****************************************************************************/ -static BOOL open_sockets(BOOL is_daemon,int port) +static BOOL open_sockets(BOOL is_daemon,int port,int port445) { extern int Client; + extern int ClientPort; int num_interfaces = iface_count(); int fd_listenset[FD_SETSIZE]; fd_set listen_set; @@ -131,7 +152,7 @@ static BOOL open_sockets(BOOL is_daemon,int port) socket per interface and bind to only these. */ - if(num_interfaces > FD_SETSIZE) { + if(num_interfaces * 2 > FD_SETSIZE) { DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ max can be %d\n", num_interfaces, FD_SETSIZE)); @@ -147,15 +168,11 @@ max can be %d\n", DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); continue; } - s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr); - if(s == -1) - return False; - /* ready to listen */ - if (listen(s, 5) == -1) { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; - } + s = fd_listenset[i * 2] = open_server_socket(port, ifip->s_addr); + if(s == -1) return False; + FD_SET(s,&listen_set); + s = fd_listenset[i * 2 + 1] = open_server_socket(port445, ifip->s_addr); + if(s == -1) return False; FD_SET(s,&listen_set); } } else { @@ -164,21 +181,16 @@ max can be %d\n", num_interfaces = 1; /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address())); + s = open_server_socket(port, interpret_addr(lp_socket_address())); if (s == -1) return(False); - - /* ready to listen */ - if (listen(s, 5) == -1) { - DEBUG(0,("open_sockets: listen: %s\n", - strerror(errno))); - close(s); - return False; - } - fd_listenset[0] = s; FD_SET(s,&listen_set); + s = open_server_socket(port445, interpret_addr(lp_socket_address())); + if (s == -1) + return(False); + fd_listenset[1] = s; + FD_SET(s,&listen_set); } /* now accept incoming connections - forking a new process @@ -204,15 +216,22 @@ max can be %d\n", s = -1; for(i = 0; i < num_interfaces; i++) { - if(FD_ISSET(fd_listenset[i],&lfds)) { - s = fd_listenset[i]; - /* Clear this so we don't look - at it again. */ - FD_CLR(fd_listenset[i],&lfds); + if(FD_ISSET(fd_listenset[i * 2],&lfds)) { + s = fd_listenset[i * 2]; + ClientPort = 138; + break; + } + if(FD_ISSET(fd_listenset[i * 2 + 1],&lfds)) { + s = fd_listenset[i * 2 + 1]; + ClientPort = 445; break; } } + /* Clear this so we don't look + at it again. */ + FD_CLR(s,&lfds); + Client = accept(s,&addr,&in_addrlen); if (Client == -1 && errno == EINTR) @@ -489,6 +508,7 @@ static void usage(char *pname) /* shall I run as a daemon */ BOOL is_daemon = False; int port = SMB_PORT; + int port445 = 455; int opt; extern char *optarg; @@ -728,7 +748,7 @@ static void usage(char *pname) pidfile_create("smbd"); } - if (!open_sockets(is_daemon,port)) + if (!open_sockets(is_daemon,port,port445)) exit(1); if (!locking_init(0)) -- cgit From 856a3e27405c3d92a56af6914e55af696a517f1c Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 10 Sep 1999 16:27:14 +0000 Subject: oops, port 455 instead of 445 (This used to be commit 4e5eac18d0d9325c8e524fb53b4e049f0893fae7) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 036ca9353c..04d369df04 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -508,7 +508,7 @@ static void usage(char *pname) /* shall I run as a daemon */ BOOL is_daemon = False; int port = SMB_PORT; - int port445 = 455; + int port445 = 445; int opt; extern char *optarg; -- cgit From ddf33698b517967deaa5e620dd65a2670a7779e6 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Sep 1999 22:40:27 +0000 Subject: - initialising mach_passwd_file locks to zero (prev. uninit.) - cleanup - #defined report to sprintf as it's #defined to another function in other uses of cmd_lsarpc.c (This used to be commit 8fb2ff247a2fe0ec5ce0c232d8a3da9774f7e6ae) --- source3/smbd/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 13dd932a57..e9fb230624 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -778,7 +778,6 @@ void smbd_process(void) { extern fstring remote_machine; extern fstring local_machine; - char *s; fstrcpy(remote_machine, dns_to_netbios_name(client_name(Client))); fstrcpy(local_machine, global_myname); -- cgit From b9b4c1d56349824616f2fcaff57cedbc52168059 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 15 Sep 1999 17:30:02 +0000 Subject: #defines for port 445 to SMB_PORT2 (This used to be commit a8d4560e0064a67a234eae89a564b79d2426d9a9) --- source3/smbd/server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 04d369df04..9d006fd176 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -82,7 +82,7 @@ static BOOL open_sockets_inetd(void) /* We will abort gracefully when the client or remote system goes away */ Client = dup(0); - ClientPort = 138; + ClientPort = SMB_PORT; /* close our standard file descriptors */ close_low_fds(); @@ -218,12 +218,12 @@ max can be %d\n", for(i = 0; i < num_interfaces; i++) { if(FD_ISSET(fd_listenset[i * 2],&lfds)) { s = fd_listenset[i * 2]; - ClientPort = 138; + ClientPort = SMB_PORT; break; } if(FD_ISSET(fd_listenset[i * 2 + 1],&lfds)) { s = fd_listenset[i * 2 + 1]; - ClientPort = 445; + ClientPort = SMB_PORT2; break; } } @@ -508,7 +508,7 @@ static void usage(char *pname) /* shall I run as a daemon */ BOOL is_daemon = False; int port = SMB_PORT; - int port445 = 445; + int port445 = SMB_PORT2; int opt; extern char *optarg; -- cgit From 701f9ed2c97ad50a4258e278a3674b8f5a747d8e Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 16 Sep 1999 22:46:45 +0000 Subject: reading in smb server domain name from SMBnegprot response (This used to be commit 25025f450531c66c0fd9f7eed886cb288d76d025) --- source3/smbd/negprot.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 51ec963b8c..0b48b0e2b2 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -218,12 +218,13 @@ static int reply_nt1(char *outbuf) if (doencrypt) secword |= 2; /* decide where (if) to put the encryption challenge, and - follow it with the OEM'd domain name + follow it with the OEM'd domain name in Unicode. */ - data_len = crypt_len + strlen(global_myworkgroup) + 1; + data_len = crypt_len + (strlen(global_myworkgroup)+1)*2; set_message(outbuf,17,data_len,True); - pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); + ascii_to_unibuf(smb_buf(outbuf)+crypt_len, global_myworkgroup, + (strlen(global_myworkgroup)+1)*2); CVAL(outbuf,smb_vwv1) = secword; SSVALS(outbuf,smb_vwv16+1,crypt_len); -- cgit From ed5fbd743be07a3c6e1a3879df283d0222ef0eb5 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Mon, 27 Sep 1999 13:12:55 +0000 Subject: don't leak printer handles, don't coredump when adding forms, and a small non obvious memory leak in the rpc buffers J.F. (This used to be commit bee11f8889378b9f1cc6e2818fd0f8dd7ddcf10d) --- source3/smbd/ipc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 5a0bf6ac07..10c859d266 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3128,7 +3128,10 @@ static void api_rpc_trans_reply(char *outbuf, /* all of data was sent: no need to wait for SMBreadX calls */ mem_free_data(p->rhdr .data); mem_free_data(p->rdata.data); - mem_free_data(p->rdata_i.data); + mem_free_data(p->rdata_i.data); + mem_free_data(p->rauth.data); + mem_free_data(p->rverf.data); + mem_free_data(p->rntlm.data); } } @@ -3281,7 +3284,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, } mem_free_data(pd.data); - + if (!reply) { return api_no_reply(outbuf, mdrcnt); -- cgit From eb9268550f2330d4a9a3381f560bd7d70743e19a Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 5 Oct 1999 21:35:17 +0000 Subject: David van Geyn spotted that ulong is not defined on FREEBSD, not supposed to use ulong use uint32 instead. (This used to be commit 16dd94db1fd2ed8ed7d240c5aac5a481b64cd26d) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9d006fd176..c59e189a9d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -96,7 +96,7 @@ static BOOL open_sockets_inetd(void) /**************************************************************************** open and listen to a socket ****************************************************************************/ -static int open_server_socket(int port, ulong ipaddr) +static int open_server_socket(int port, uint32 ipaddr) { int s; -- cgit From 6f9105c853020fde1691a28cd707d6d3f6561b4d Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 21 Oct 1999 16:53:50 +0000 Subject: various. debug levels changed. nmbd doesn't need libsmb/clienttrust.c. samr_lookup_rids() moved to a dynamic memory structure not a static one limited to 32 RIDs. cli_pipe.c reading wasn't checking ERRmoredata when DOS error codes negotiated (this terminates MSRPC code with prejudice). (This used to be commit 8976eca2db43576c32069dcda017e8777048e007) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6ec290ca25..a98c6289b8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1191,7 +1191,7 @@ BOOL domain_client_validate( char *user, char *domain, } if(cli_nt_setup_creds(&cli, nt_pipe_fnum, - cli.mach_acct, trust_passwd, SEC_CHAN_WKSTA) == False) + cli.mach_acct, global_myname, trust_passwd, SEC_CHAN_WKSTA) == False) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); -- cgit From 902b53dcc0933045980ed5d7df4959eee6f016d3 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 29 Oct 1999 15:53:18 +0000 Subject: cli_nt_setup_creds() returns uint32 NT status code not a BOOL. removed all comparisons to if (fn() == False), replaced with if (!fn()). (This used to be commit fdef97eb7c20a33b26104661cd010baebcb4bdcd) --- source3/smbd/password.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a98c6289b8..1612b8264f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -278,7 +278,8 @@ static BOOL update_smbpassword_file(char *user, char *password) /* Here, the flag is one, because we want to ignore the XXXXXXX'd out password */ ret = change_oem_password( smbpw, password, True); - if (ret == False) { + if (!ret) + { DEBUG(3,("change_oem_password returned False\n")); } @@ -1181,7 +1182,7 @@ BOOL domain_client_validate( char *user, char *domain, * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(&cli, PIPE_NETLOGON, &nt_pipe_fnum) == False) { + if (!cli_nt_session_open(&cli, PIPE_NETLOGON, &nt_pipe_fnum)) { DEBUG(0,("domain_client_validate: unable to open the domain client session to \ machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); cli_nt_session_close(&cli, nt_pipe_fnum); @@ -1191,7 +1192,7 @@ BOOL domain_client_validate( char *user, char *domain, } if(cli_nt_setup_creds(&cli, nt_pipe_fnum, - cli.mach_acct, global_myname, trust_passwd, SEC_CHAN_WKSTA) == False) + cli.mach_acct, global_myname, trust_passwd, SEC_CHAN_WKSTA) != 0x0) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); -- cgit From cae821d45926157a250e9fa047e0c8aa8c0c2c54 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 4 Nov 1999 00:09:15 +0000 Subject: adding experimental set user password command to rpcclient, it returns error wrong password against nt. ???? (This used to be commit b3f16e6b5aa5ba1b6afa38ad698646c8e765ec90) --- source3/smbd/chgpasswd.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index f84ae0ccb5..fa208acdc8 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -641,6 +641,37 @@ BOOL decode_pw_buffer(const char buffer[516], char *new_passwd, return True; } +/*********************************************************** + encode a password buffer +************************************************************/ +BOOL encode_pw_buffer(char buffer[516], const char *new_passwd, + int new_pw_len, BOOL nt_pass_set) +{ + if (nt_pass_set) + { + /* + * nt passwords are in unicode. last char overwrites NULL + * in ascii_to_unibuf, so use SIVAL *afterwards*. + */ + int uni_pw_len = new_pw_len; + new_pw_len /= 2; + ascii_to_unibuf(&buffer[512-uni_pw_len], new_passwd, new_pw_len); + } + else + { + memcpy(&buffer[512-new_pw_len], new_passwd, new_pw_len); + } + + /* + * The length of the new password is in the last 4 bytes of + * the data buffer. + */ + + SIVAL(buffer, 512, new_passwd_size); + + return True; +} + /*********************************************************** Code to check the OEM hashed password. -- cgit From fe8383382d5b8221093a5340705c4e5b3731a249 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 4 Nov 1999 21:41:36 +0000 Subject: samuserset -p password. YESSSSS :) you have to use "ntlmv1" at the moment (i.e set client ntlmv2 = no). (This used to be commit f52504c553becc64b89d546a57b1bd9cf1bc5b5c) --- source3/smbd/chgpasswd.c | 67 ------------------------------------------------ 1 file changed, 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fa208acdc8..a21b598238 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -605,73 +605,6 @@ BOOL pass_oem_change(char *user, return ret; } -/*********************************************************** - decode a password buffer -************************************************************/ -BOOL decode_pw_buffer(const char buffer[516], char *new_passwd, - int new_passwd_size, BOOL nt_pass_set) -{ - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - - uint32 new_pw_len = IVAL(buffer, 512); - if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) - { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); - return False; - } - - if (nt_pass_set) - { - /* - * nt passwords are in unicode - */ - int uni_pw_len = new_pw_len; - new_pw_len /= 2; - unibuf_to_ascii(new_passwd, &buffer[512-uni_pw_len], new_pw_len); - } - else - { - memcpy(new_passwd, &buffer[512-new_pw_len], new_pw_len); - new_passwd[new_pw_len] = '\0'; - } - - return True; -} - -/*********************************************************** - encode a password buffer -************************************************************/ -BOOL encode_pw_buffer(char buffer[516], const char *new_passwd, - int new_pw_len, BOOL nt_pass_set) -{ - if (nt_pass_set) - { - /* - * nt passwords are in unicode. last char overwrites NULL - * in ascii_to_unibuf, so use SIVAL *afterwards*. - */ - int uni_pw_len = new_pw_len; - new_pw_len /= 2; - ascii_to_unibuf(&buffer[512-uni_pw_len], new_passwd, new_pw_len); - } - else - { - memcpy(&buffer[512-new_pw_len], new_passwd, new_pw_len); - } - - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - - SIVAL(buffer, 512, new_passwd_size); - - return True; -} - /*********************************************************** Code to check the OEM hashed password. -- cgit From b231d2fafaff8dc67ef2dbaec778f716524d4f6a Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 15 Nov 1999 22:11:10 +0000 Subject: - added DCE/RPC "fault" PDU support. - disabled (AGAIN) the GETDC "if (MAILSLOT\NTLOGON)" code that will get NT5rc2 to work but WILL break win95 (AGAIN). this needs _not_ to be re-enabled but to be replaced with a better mechanism. - added SMBwrite support (note: SMBwriteX already existed) as NT5rc2 is sending DCE/RPC over SMBwrite not SMBwriteX. (This used to be commit 25c70e3c984c4fed19763ed405741e83fe14f87e) --- source3/smbd/ipc.c | 9 +++++---- source3/smbd/pipes.c | 41 +++++++++++++++++++++++++++++++++++++++++ source3/smbd/process.c | 2 +- source3/smbd/reply.c | 4 ++++ 4 files changed, 51 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 10c859d266..a3e7932529 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3127,11 +3127,12 @@ static void api_rpc_trans_reply(char *outbuf, { /* all of data was sent: no need to wait for SMBreadX calls */ mem_free_data(p->rhdr .data); - mem_free_data(p->rdata.data); + mem_free_data(p->rfault .data); + mem_free_data(p->rdata .data); mem_free_data(p->rdata_i.data); - mem_free_data(p->rauth.data); - mem_free_data(p->rverf.data); - mem_free_data(p->rntlm.data); + mem_free_data(p->rauth .data); + mem_free_data(p->rverf .data); + mem_free_data(p->rntlm .data); } } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 374aa70d0f..e20d049834 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -104,6 +104,47 @@ int reply_open_pipe_and_X(connection_struct *conn, return chain_reply(inbuf,outbuf,length,bufsize); } +/**************************************************************************** + reply to a write + + This code is basically stolen from reply_write with some + wrinkles to handle pipes. +****************************************************************************/ +int reply_pipe_write(char *inbuf,char *outbuf,int length,int bufsize) +{ + pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); + size_t numtowrite = SVAL(inbuf,smb_vwv1); + int nwritten = -1; + char *data; + size_t outsize; + + if (!p) return(ERROR(ERRDOS,ERRbadfid)); + + data = smb_buf(inbuf) + 3; + + if (numtowrite == 0) + { + nwritten = 0; + } + else + { + nwritten = write_pipe(p, data, numtowrite); + } + + if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) + { + return (UNIXERROR(ERRDOS,ERRnoaccess)); + } + + outsize = set_message(outbuf,1,0,True); + + SSVAL(outbuf,smb_vwv0,nwritten); + + DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", + p->pnum, nwritten)); + + return outsize; +} /**************************************************************************** reply to a write and X diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e9fb230624..1a6ec320e1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -283,7 +283,7 @@ struct smb_message_struct {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, {SMBread,"SMBread",reply_read,AS_USER}, - {SMBwrite,"SMBwrite",reply_write,AS_USER}, + {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC}, {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8723779d30..0c4fb2003c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2348,6 +2348,10 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) + return reply_pipe_write(inbuf,outbuf,dum_size,dum_buffsize); + CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); CHECK_ERROR(fsp); -- cgit From 4245278ca3fea4a6b79daf58a8712a2774811c58 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 18 Nov 1999 22:03:47 +0000 Subject: set "key does not exist" response to reg_query_val() (win32 status code of 0x2). [p.s. getting REALLY bored of this nt5rc2->samba domain stuff]. (This used to be commit a8801942f72b2394a54e4a46546029fac70efeed) --- source3/smbd/server.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c59e189a9d..590d8533b3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -125,6 +125,8 @@ static BOOL open_sockets(BOOL is_daemon,int port,int port445) int s; int i; + memset(&fd_listenset, 0, sizeof(fd_listenset)); + if (!is_daemon) { return open_sockets_inetd(); } @@ -186,11 +188,13 @@ max can be %d\n", return(False); fd_listenset[0] = s; FD_SET(s,&listen_set); +#if 0 s = open_server_socket(port445, interpret_addr(lp_socket_address())); if (s == -1) return(False); fd_listenset[1] = s; FD_SET(s,&listen_set); +#endif } /* now accept incoming connections - forking a new process @@ -221,11 +225,13 @@ max can be %d\n", ClientPort = SMB_PORT; break; } +#if 0 if(FD_ISSET(fd_listenset[i * 2 + 1],&lfds)) { s = fd_listenset[i * 2 + 1]; ClientPort = SMB_PORT2; break; } +#endif } /* Clear this so we don't look -- cgit From 161c11e4bcd408064493c063b228aab589fd2a19 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 19 Nov 1999 01:01:07 +0000 Subject: - bug in nmbd registering DOMAIN_NAME<1c> to WINS server; recursion desired flag MUST be set in any NBT UDP packets sent to a WINS server, else they will go to the WINS client side of the NT NetBIOS kernel instead, and will get trashed. - added \PIPE\browser server-side code. (This used to be commit 8e406c1fa296c3f97b1cd7ddde7b5aeb9232b26e) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ac688a5baa..70023e2407 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -40,6 +40,7 @@ static char *known_nt_pipes[] = { "\\svcctl", "\\samr", "\\wkssvc", + "\\browser", "\\NETLOGON", "\\ntlsa", "\\ntsvcs", -- cgit From 24a069eac302069559c6347b24276e7f1a04cc91 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 20 Nov 1999 20:54:29 +0000 Subject: modified domain_client_validate to take trust account name / type. this is to pass DOMAIN_NAME$ and SEC_CHAN_DOMAIN instead of WKSTA_NAME$ and SEC_CHAN_WKSTA. modified check_domain_security to determine if domain name is own domain, and to use wksta trust account if so, otherwise check "trusting domains" parameter and use inter-domain trust account if so, otherwise return False. (This used to be commit 97ec74e1fa99d773812d2df402251fafb76b181c) --- source3/smbd/chgpasswd.c | 3 ++- source3/smbd/password.c | 15 ++++++++---- source3/smbd/reply.c | 61 ++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a21b598238..3d31db7fb5 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -626,6 +626,7 @@ BOOL check_oem_password(char *user, uchar new_p16[16]; uchar unenc_old_pw[16]; char no_pw[2]; + uint32 len; BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); @@ -682,7 +683,7 @@ BOOL check_oem_password(char *user, */ SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); - if (!decode_pw_buffer(lmdata, new_passwd, new_passwd_size, nt_pass_set)) + if (!decode_pw_buffer(lmdata, new_passwd, new_passwd_size, &len)) { return False; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1612b8264f..f74cc49eca 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1095,7 +1095,8 @@ use this machine as the password server.\n")); key from the workstation trust account password. ************************************************************************/ -BOOL domain_client_validate( char *user, char *domain, +BOOL domain_client_validate( char *user, char *domain, char *server_list, + char *acct_name, uint16 acct_type, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { @@ -1108,6 +1109,10 @@ BOOL domain_client_validate( char *user, char *domain, NET_USER_INFO_3 info3; struct cli_state cli; uint32 smb_uid_low; + fstring trust_acct; + + fstrcpy(trust_acct, acct_name); + fstrcat(trust_acct, "$"); /* * Check that the requested domain is not our own machine name. @@ -1126,7 +1131,7 @@ BOOL domain_client_validate( char *user, char *domain, */ if(((smb_apasslen != 24) && (smb_apasslen != 0)) || - ((smb_ntpasslen != 24) && (smb_ntpasslen != 0))) + ((smb_ntpasslen <= 24) && (smb_ntpasslen != 0))) { /* * Not encrypted - do so. @@ -1158,7 +1163,7 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the workstation trust account password. */ - if (!trust_get_passwd( trust_passwd, global_myworkgroup, global_myname)) + if (!trust_get_passwd( trust_passwd, domain, acct_name)) { return False; } @@ -1171,7 +1176,7 @@ BOOL domain_client_validate( char *user, char *domain, * see if they were valid. */ - if (!cli_connect_serverlist(&cli, lp_passwordserver())) + if (!cli_connect_serverlist(&cli, server_list)) { DEBUG(0,("domain_client_validate: Domain password server not available.\n")); return False; @@ -1192,7 +1197,7 @@ BOOL domain_client_validate( char *user, char *domain, } if(cli_nt_setup_creds(&cli, nt_pipe_fnum, - cli.mach_acct, global_myname, trust_passwd, SEC_CHAN_WKSTA) != 0x0) + trust_acct, global_myname, trust_passwd, acct_type) != 0x0) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0c4fb2003c..79b24a986c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -39,6 +39,7 @@ extern BOOL case_preserve; extern BOOL short_case_preserve; extern pstring sesssetup_user; extern fstring global_myworkgroup; +extern fstring global_myname; extern int Client; extern int global_oplock_break; uint32 global_client_caps = 0; @@ -501,12 +502,62 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { - if(lp_security() != SEC_DOMAIN) - return False; + fstring acct_name; + uint16 acct_type = 0; + + char *server_list = NULL; + pstring srv_list; + char *trusted_list = lp_trusted_domains(); + + if (lp_security() == SEC_SHARE || lp_security() == SEC_SERVER) + { + return False; + } + + if (lp_security() == SEC_DOMAIN) + { + fstrcpy(acct_name, global_myname); + acct_type = SEC_CHAN_WKSTA; + if (strequal(lp_workgroup(), domain)) + { + DEBUG(10,("local domain server list: %s\n", server_list)); + pstrcpy(srv_list, lp_passwordserver()); + server_list = srv_list; + } + } + + if (server_list == NULL) + { + pstring tmp; + if (next_token(&trusted_list, tmp, NULL, sizeof(tmp))) + { + do + { + fstring trust_dom; + split_at_first_component(tmp, trust_dom, '=', srv_list); + + if (strequal(domain, trust_dom)) + { + DEBUG(10,("trusted domain server list: %s\n", server_list)); + fstrcpy(acct_name, global_myworkgroup); + acct_type = SEC_CHAN_DOMAIN; + server_list = srv_list; + break; + } + + } while (next_token(NULL, tmp, NULL, sizeof(tmp))); + } + } + + if (server_list == NULL) + { + return False; + } - return domain_client_validate(orig_user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen); + return domain_client_validate(orig_user, domain, server_list, + acct_name, acct_type, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen); } /**************************************************************************** -- cgit From 27b8df4d9bc31fc73f7db6ceed24a6fca1271d3f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 20 Nov 1999 21:59:16 +0000 Subject: attempting to establish inter-domain trust relationships. modified smbpasswd so it can be used to set up inter-domain trust account. (This used to be commit 99ec0620c3bf4af96440c684f880d414659de2e9) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f74cc49eca..b279e76f41 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1247,8 +1247,10 @@ BOOL domain_client_validate( char *user, char *domain, char *server_list, } #endif /* 0 */ +#if 0 cli_nt_session_close(&cli, nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); +#endif return True; } -- cgit From 387cc182e6a8a500fe4e0115b33230c6acca8084 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 20 Nov 1999 22:05:31 +0000 Subject: oops, #ifdef'd cli_shutdown out, as the fun has _already_ started: NT refuses to play nice, and establish a trust relationship. (This used to be commit 98c42764fba365d612a8ae4b3172b03367066112) --- source3/smbd/password.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b279e76f41..2f0ab6e137 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1247,10 +1247,9 @@ BOOL domain_client_validate( char *user, char *domain, char *server_list, } #endif /* 0 */ -#if 0 cli_nt_session_close(&cli, nt_pipe_fnum); cli_ulogoff(&cli); cli_shutdown(&cli); -#endif + return True; } -- cgit From 4081147c31919a973ce1859394d0f5a49a0c2f39 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 21 Nov 1999 17:11:00 +0000 Subject: adding user session key into network netlogon response. (This used to be commit c73f6b0d02fa7700319ba696f54296006167e5d1) --- source3/smbd/password.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2f0ab6e137..690e2e5f5c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -467,16 +467,24 @@ SMB hash return True if the password is correct, False otherwise ****************************************************************************/ -BOOL pass_check_smb(char *user, char *domain, uchar *chal, +BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal, uchar *lm_pwd, size_t lm_pwd_len, uchar *nt_pwd, size_t nt_pwd_len, struct passwd *pwd, uchar user_sess_key[16]) { const struct passwd *pass; struct passwd pw; - struct smb_passwd *smb_pass; + char *user = NULL; - if (!lm_pwd || !nt_pwd) + if (smb_pass == NULL) + { + DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); + return False; + } + + user = smb_pass->unix_name; + + if (lm_pwd == NULL || nt_pwd == NULL) { return False; } @@ -498,14 +506,6 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, pass = &pw; } - smb_pass = getsmbpwnam(user); - - if (smb_pass == NULL) - { - DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); - return False; - } - /* Quit if the account was disabled. */ if (smb_pass->acct_ctrl & ACB_DISABLED) { DEBUG(3,("account for user %s was disabled.\n", user)); @@ -563,7 +563,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, return False; } - return pass_check_smb(user, global_myworkgroup, + return pass_check_smb(getsmbpwnam(user), global_myworkgroup, challenge, (uchar *)password, pwlen, (uchar *)password, pwlen, pwd, user_sess_key); -- cgit From 680dcc934182544aa49a4a426f2263c1aaedd4aa Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 21 Nov 1999 17:27:20 +0000 Subject: hmmm... have to add client-side support in domain_client_validate() to _use_ user session key. (This used to be commit be6a6b13939798a9c7242b38864f0ce842391a74) --- source3/smbd/password.c | 5 +++-- source3/smbd/reply.c | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 690e2e5f5c..3d7a35fac8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1097,8 +1097,9 @@ use this machine as the password server.\n")); BOOL domain_client_validate( char *user, char *domain, char *server_list, char *acct_name, uint16 acct_type, - char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen) + char *smb_apasswd, int smb_apasslen, + char *smb_ntpasswd, int smb_ntpasslen, + uchar user_sess_key[16]) { uint16 nt_pipe_fnum; unsigned char local_challenge[8]; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 79b24a986c..da72c9f3b5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -499,8 +499,9 @@ static BOOL check_server_security(char *orig_user, char *domain, ****************************************************************************/ static BOOL check_domain_security(char *orig_user, char *domain, - char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen) + char *smb_apasswd, int smb_apasslen, + char *smb_ntpasswd, int smb_ntpasslen, + uchar user_sess_key[16]) { fstring acct_name; uint16 acct_type = 0; @@ -557,7 +558,8 @@ static BOOL check_domain_security(char *orig_user, char *domain, return domain_client_validate(orig_user, domain, server_list, acct_name, acct_type, smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen); + smb_ntpasswd, smb_ntpasslen, + user_sess_key); } /**************************************************************************** @@ -768,7 +770,7 @@ user %s attempted down-level SMB connection\n", user)); smb_ntpasswd, smb_ntpasslen) && !check_domain_security(orig_user, domain, smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen) && + smb_ntpasswd, smb_ntpasslen, user_sess_key) && !check_hosts_equiv(user) ) { -- cgit From 32b9508d066f002e778873edc19266a6d897f922 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 21 Nov 1999 19:59:56 +0000 Subject: implement server-side generation of NTLMv2 session key. YESSS :-) (This used to be commit 1092b4f6fbdf3770c0dab756b982a562def1738e) --- source3/smbd/password.c | 37 ++++++++++++++++++++++++++----------- source3/smbd/reply.c | 2 +- 2 files changed, 27 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3d7a35fac8..010272b807 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -294,7 +294,8 @@ static BOOL update_smbpassword_file(char *user, char *password) core of smb password checking routine. ****************************************************************************/ static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd, - unsigned char *c8) + unsigned char *c8, + uchar sess_key[16]) { /* Finish the encryption of part_passwd. */ unsigned char p24[24]; @@ -306,6 +307,11 @@ static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd, return True; SMBOWFencrypt(part_passwd, c8, p24); + if (sess_key != NULL) + { + SMBsesskeygen_ntv1(part_passwd, NULL, sess_key); + } + #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); dump_data(100, part_passwd, 16); @@ -325,10 +331,12 @@ core of smb password checking routine. static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len, unsigned char *part_passwd, unsigned char const *c8, - const char *user, const char *domain) + const char *user, const char *domain, + char *sess_key) { /* Finish the encryption of part_passwd. */ unsigned char kr[16]; + unsigned char resp[16]; if (part_passwd == NULL) { @@ -341,7 +349,11 @@ static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len, } ntv2_owf_gen(part_passwd, user, domain, kr); - SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, kr); + SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp); + if (sess_key != NULL) + { + SMBsesskeygen_ntv2(kr, resp, sess_key); + } #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); @@ -351,10 +363,10 @@ static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len, DEBUG(100,("Given challenge was |")); dump_data(100, c8, 8); DEBUG(100,("Value from encryption was |")); - dump_data(100, kr, 16); + dump_data(100, resp, 16); #endif - return (memcmp(kr, password, 16) == 0); + return (memcmp(resp, password, 16) == 0); } /**************************************************************************** @@ -364,7 +376,8 @@ static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len, BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], const char *user, const char *domain, uchar *lm_pass, size_t lm_pwd_len, - uchar *nt_pass, size_t nt_pwd_len) + uchar *nt_pass, size_t nt_pwd_len, + uchar sess_key[16]) { uchar challenge[8]; @@ -408,7 +421,8 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], DEBUG(4,("smb_password_ok: Check NTLMv2 password\n")); if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len, (uchar *)smb_pass->smb_nt_passwd, - challenge, user, domain)) + challenge, user, domain, + sess_key)) { return True; } @@ -418,7 +432,8 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], DEBUG(4,("smb_password_ok: Check NT MD4 password\n")); if (smb_pwd_check_ntlmv1((char *)nt_pass, (uchar *)smb_pass->smb_nt_passwd, - challenge)) + challenge, + sess_key)) { DEBUG(4,("NT MD4 password check succeeded\n")); return True; @@ -449,7 +464,7 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], if ((smb_pass->smb_passwd != NULL) && smb_pwd_check_ntlmv1((char *)lm_pass, (uchar *)smb_pass->smb_passwd, - challenge)) + challenge, NULL)) { DEBUG(4,("LM MD4 password check succeeded\n")); return(True); @@ -527,11 +542,11 @@ BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal, if (smb_password_ok(smb_pass, chal, user, domain, lm_pwd, lm_pwd_len, - nt_pwd, nt_pwd_len)) + nt_pwd, nt_pwd_len, + user_sess_key)) { if (user_sess_key != NULL) { - mdfour(user_sess_key, smb_pass->smb_nt_passwd, 16); #ifdef DEBUG_PASSWORD DEBUG(100,("user session key: ")); dump_data(100, user_sess_key, 16); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index da72c9f3b5..d5d0884436 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -444,7 +444,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL, (unsigned char *)smb_passwd, smb_passlen, - (unsigned char *)smb_nt_passwd, smb_nt_passlen)) + (unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); -- cgit From d7889cd22347e7acd4effb7682d442eef7a666e4 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 24 Nov 1999 18:09:33 +0000 Subject: rewrote policy handle code to be generic (it's needed for client-side too) attempted to fix regsetsec command (This used to be commit eaac0923e0e5e3f4c3d944272a71f3235ac2a741) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 590d8533b3..c2162a091b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -476,7 +476,7 @@ static void init_structs(void) conn_init(); file_init(); init_rpc_pipe_hnd(); /* for RPC pipes */ - init_lsa_policy_hnd(); /* for LSA handles */ + init_policy_hnd(MAX_SERVER_POLICY_HANDLES); /* for policy handles */ init_printer_hnd(); /* for SPOOLSS handles */ init_dptrs(); init_dfs_table(); -- cgit From 2752e372b64337de24edef52575ddc7da0ed8d04 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 24 Nov 1999 18:15:50 +0000 Subject: WARNING! MOVED rpc_server/srv_lsa_hnd.c TO lib/util_hnd.c CVS UPDATE MAY ISSUE WARNING ABOUT lib/util_hnd.c MODIFICATION DATE BEING IN THE FUTURE. CVS CHECKOUT A NEW REPOSITORY MAY BE SAFER. (This used to be commit c26e8a6ac59934ae580077df937439c2c538dbdb) --- source3/smbd/server.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c2162a091b..a0c9ab7c56 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -476,7 +476,10 @@ static void init_structs(void) conn_init(); file_init(); init_rpc_pipe_hnd(); /* for RPC pipes */ - init_policy_hnd(MAX_SERVER_POLICY_HANDLES); /* for policy handles */ + if (!init_policy_hnd(MAX_SERVER_POLICY_HANDLES)) + { + exit_server("could not allocate policy handles\n"); + } init_printer_hnd(); /* for SPOOLSS handles */ init_dptrs(); init_dfs_table(); -- cgit From 0d44ff9a765f2e89be8b0ee99ec7c907e7c225c3 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 29 Nov 1999 21:47:14 +0000 Subject: attempting to resolve the issue that multiple servers often specified in parameters to connect to \PIPE\NETLOGON. (This used to be commit d1986ade30bdcac1f49707221a3e5a5ae597ce62) --- source3/smbd/password.c | 64 +++++++++---------------------------------------- 1 file changed, 11 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 010272b807..fa6f2b06e3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1116,16 +1116,15 @@ BOOL domain_client_validate( char *user, char *domain, char *server_list, char *smb_ntpasswd, int smb_ntpasslen, uchar user_sess_key[16]) { - uint16 nt_pipe_fnum; unsigned char local_challenge[8]; unsigned char local_lm_response[24]; unsigned char local_nt_reponse[24]; unsigned char trust_passwd[16]; NET_ID_INFO_CTR ctr; NET_USER_INFO_3 info3; - struct cli_state cli; uint32 smb_uid_low; fstring trust_acct; + fstring srv_name; fstrcpy(trust_acct, acct_name); fstrcat(trust_acct, "$"); @@ -1192,50 +1191,31 @@ BOOL domain_client_validate( char *user, char *domain, char *server_list, * see if they were valid. */ - if (!cli_connect_serverlist(&cli, server_list)) - { - DEBUG(0,("domain_client_validate: Domain password server not available.\n")); - return False; - } - /* * Ok - we have an anonymous connection to the IPC$ share. * Now start the NT Domain stuff :-). */ - if (!cli_nt_session_open(&cli, PIPE_NETLOGON, &nt_pipe_fnum)) { - DEBUG(0,("domain_client_validate: unable to open the domain client session to \ - machine %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } - - if(cli_nt_setup_creds(&cli, nt_pipe_fnum, - trust_acct, global_myname, trust_passwd, acct_type) != 0x0) + if(cli_nt_setup_creds(server_list, global_myname, trust_acct, + trust_passwd, acct_type, srv_name) != 0x0) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ - %s. Error was : %s.\n", cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); + %s.\n", srv_name)); return False; } /* We really don't care what LUID we give the user. */ generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - if (!cli_nt_login_network(&cli, nt_pipe_fnum, domain, user, smb_uid_low, (char *)local_challenge, - ((smb_apasslen != 0) ? smb_apasswd : NULL), - ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), - &ctr, &info3)) + if (!cli_nt_login_network(srv_name, global_myname, + domain, user, + smb_uid_low, (char *)local_challenge, + ((smb_apasslen != 0) ? smb_apasswd : NULL), + ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), + &ctr, &info3)) { DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ - %s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); + %s to Domain controller %s.\n", user, domain, srv_name)); return False; } @@ -1245,27 +1225,5 @@ BOOL domain_client_validate( char *user, char *domain, char *server_list, * locked out / disabled" etc!!!! */ -#if 0 - /* - * We don't actually need to do this - plus it fails currently with - * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to - * send here. JRA. - */ - - if (!cli_nt_logoff(&cli, nt_pipe_fnum, &ctr)) - { - DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ - %s to Domain controller %s. Error was %s.\n", user, domain, cli.desthost, cli_errstr(&cli))); - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } -#endif /* 0 */ - - cli_nt_session_close(&cli, nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return True; } -- cgit From 6ddfc68e0496dc41f8c9a022a0b04a2066b43c9d Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 1 Dec 1999 02:15:14 +0000 Subject: sys_select added one more argument (read, write selectors). (This used to be commit e4d92ff9dfc51735e6932748f66a7c20b2c1cb6a) --- source3/smbd/oplock.c | 2 +- source3/smbd/process.c | 2 +- source3/smbd/server.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1455b4d8e5..99fe7a69fa 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -135,7 +135,7 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(maxfd+1,fds,&to); + selrtn = sys_select(maxfd+1,fds,NULL, &to); /* Check if error */ if(selrtn == -1) { diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1a6ec320e1..95222d3f51 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -173,7 +173,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(MAX(maxfd,Client)+1,&fds,timeout>0?&to:NULL); + selrtn = sys_select(MAX(maxfd,Client)+1,&fds,NULL, timeout>0?&to:NULL); /* Check if error */ if(selrtn == -1) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a0c9ab7c56..5512e6e56b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -207,7 +207,7 @@ max can be %d\n", memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select(256,&lfds,NULL); + num = sys_select(256,&lfds,NULL, NULL); if (num == -1 && errno == EINTR) continue; -- cgit From c15b95cd1ede75b38d3a2c5192f2d1fd2a310c9a Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 1 Dec 1999 21:47:30 +0000 Subject: cli_session_setup() now takes an extra argument (host name). hey, what the heck is a cli_session_setup() call doing in here??? this should use cli_establish_connection()server! (This used to be commit fa054c96c62ed0f0a0c6649a7ad7a143fe09694b) --- source3/smbd/password.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fa6f2b06e3..3e4a856bfb 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1042,7 +1042,8 @@ BOOL server_validate(char *user, char *domain, */ if(!tested_password_server) { - if (cli_session_setup(cli, user, (char *)badpass, sizeof(badpass), + if (cli_session_setup(cli, global_myname, + user, (char *)badpass, sizeof(badpass), (char *)badpass, sizeof(badpass), domain)) { /* @@ -1087,7 +1088,8 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + if (!cli_session_setup(cli, global_myname, + user, pass, passlen, ntpass, ntpasslen, domain)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); return False; } -- cgit From 7aebbb90c8e09febd345de10c0b438e98f30468b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 2 Dec 1999 16:52:38 +0000 Subject: need a domain resolving function, but get_trusted_serverlist() will do. this is horrible. (This used to be commit 9df973fe711f322075d86d6792d6c0b8539c1d00) --- source3/smbd/reply.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d5d0884436..5cf2ac2a7a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -507,49 +507,25 @@ static BOOL check_domain_security(char *orig_user, char *domain, uint16 acct_type = 0; char *server_list = NULL; - pstring srv_list; - char *trusted_list = lp_trusted_domains(); if (lp_security() == SEC_SHARE || lp_security() == SEC_SERVER) { return False; } - if (lp_security() == SEC_DOMAIN) + if (lp_security() == SEC_DOMAIN && strequal(domain, global_myworkgroup)) { fstrcpy(acct_name, global_myname); acct_type = SEC_CHAN_WKSTA; - if (strequal(lp_workgroup(), domain)) - { - DEBUG(10,("local domain server list: %s\n", server_list)); - pstrcpy(srv_list, lp_passwordserver()); - server_list = srv_list; - } } - - if (server_list == NULL) + else { - pstring tmp; - if (next_token(&trusted_list, tmp, NULL, sizeof(tmp))) - { - do - { - fstring trust_dom; - split_at_first_component(tmp, trust_dom, '=', srv_list); - - if (strequal(domain, trust_dom)) - { - DEBUG(10,("trusted domain server list: %s\n", server_list)); - fstrcpy(acct_name, global_myworkgroup); - acct_type = SEC_CHAN_DOMAIN; - server_list = srv_list; - break; - } - - } while (next_token(NULL, tmp, NULL, sizeof(tmp))); - } + fstrcpy(acct_name, global_myworkgroup); + acct_type = SEC_CHAN_DOMAIN; } + server_list = get_trusted_serverlist(domain); + if (server_list == NULL) { return False; -- cgit From b96e4e4f7d80bf783aeea1592fbca58769a58e1d Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 2 Dec 1999 19:07:13 +0000 Subject: domain_client_validate() no longer takes serverlist, it calls get_any_dc_name(). (This used to be commit e21367c0ebdc5e202cdc39d50950bff089bf67f8) --- source3/smbd/password.c | 13 ++++++++++--- source3/smbd/reply.c | 11 +---------- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3e4a856bfb..c14b50d3a6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1112,7 +1112,7 @@ use this machine as the password server.\n")); key from the workstation trust account password. ************************************************************************/ -BOOL domain_client_validate( char *user, char *domain, char *server_list, +BOOL domain_client_validate( char *user, char *domain, char *acct_name, uint16 acct_type, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen, @@ -1143,6 +1143,13 @@ BOOL domain_client_validate( char *user, char *domain, char *server_list, return False; } + if (!get_any_dc_name(domain, srv_name)) + { + DEBUG(3,("domain_client_validate: could not find domain %s\n", + domain)); + return False; + } + /* * Next, check that the passwords given were encrypted. */ @@ -1198,8 +1205,8 @@ BOOL domain_client_validate( char *user, char *domain, char *server_list, * Now start the NT Domain stuff :-). */ - if(cli_nt_setup_creds(server_list, global_myname, trust_acct, - trust_passwd, acct_type, srv_name) != 0x0) + if(cli_nt_setup_creds(srv_name, global_myname, trust_acct, + trust_passwd, acct_type) != 0x0) { DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ %s.\n", srv_name)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5cf2ac2a7a..a0ad2ca20d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -506,8 +506,6 @@ static BOOL check_domain_security(char *orig_user, char *domain, fstring acct_name; uint16 acct_type = 0; - char *server_list = NULL; - if (lp_security() == SEC_SHARE || lp_security() == SEC_SERVER) { return False; @@ -524,14 +522,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, acct_type = SEC_CHAN_DOMAIN; } - server_list = get_trusted_serverlist(domain); - - if (server_list == NULL) - { - return False; - } - - return domain_client_validate(orig_user, domain, server_list, + return domain_client_validate(orig_user, domain, acct_name, acct_type, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen, -- cgit From a0ba234cf9b40adf6b5390e4e67730163a42883f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 6 Dec 1999 00:44:32 +0000 Subject: the first independent msrpc daemon - lsarpcd. one horrible cut / paste job from smbd, plus a code split of shared components between the two. the job is not _yet_ complete, as i need to be able to do a become_user() call for security reasons. i picked lsarpcd first because you don't _need_ security on it (microsoft botched so badly on this one, it's not real. at least they fixed this in nt5 with restrictanonymous=0x2). fixing this involves sending the current smb and unix credentials down the unix pipe so that the daemon it eventually goes to can pick them up at the other end. i can't believe this all worked!!! (This used to be commit 2245b0c6d13c7c5886e81f9137b05df883598c26) --- source3/smbd/challenge.c | 61 ++++++ source3/smbd/password.c | 501 ----------------------------------------------- source3/smbd/reply.c | 5 +- source3/smbd/server.c | 12 ++ 4 files changed, 76 insertions(+), 503 deletions(-) create mode 100644 source3/smbd/challenge.c (limited to 'source3/smbd') diff --git a/source3/smbd/challenge.c b/source3/smbd/challenge.c new file mode 100644 index 0000000000..cbb34e6395 --- /dev/null +++ b/source3/smbd/challenge.c @@ -0,0 +1,61 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Password and authentication handling + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + +/* Data to do lanman1/2 password challenge. */ +static unsigned char saved_challenge[8]; +static BOOL challenge_sent=False; + +/******************************************************************* +Get the next challenge value - no repeats. +********************************************************************/ +void generate_next_challenge(char *challenge) +{ + unsigned char buf[8]; + generate_random_buffer(buf,8,False); + memcpy(saved_challenge, buf, 8); + memcpy(challenge,buf,8); + challenge_sent = True; +} + +/******************************************************************* +set the last challenge sent, usually from a password server +********************************************************************/ +BOOL set_challenge(unsigned char *challenge) +{ + memcpy(saved_challenge,challenge,8); + challenge_sent = True; + return(True); +} + +/******************************************************************* +get the last challenge sent +********************************************************************/ +BOOL last_challenge(unsigned char *challenge) +{ + if (!challenge_sent) return False; + memcpy(challenge,saved_challenge,8); + return(True); +} + diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c14b50d3a6..240ec30c3f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -31,209 +31,6 @@ extern pstring scope; extern pstring global_myname; extern fstring global_myworkgroup; -/* Data to do lanman1/2 password challenge. */ -static unsigned char saved_challenge[8]; -static BOOL challenge_sent=False; - -/******************************************************************* -Get the next challenge value - no repeats. -********************************************************************/ -void generate_next_challenge(char *challenge) -{ -#if 0 - /* - * Leave this ifdef'd out while we test - * the new crypto random number generator. - * JRA. - */ - unsigned char buf[16]; - static int counter = 0; - struct timeval tval; - int v1,v2; - - /* get a sort-of random number */ - GetTimeOfDay(&tval); - v1 = (counter++) + getpid() + tval.tv_sec; - v2 = (counter++) * getpid() + tval.tv_usec; - SIVAL(challenge,0,v1); - SIVAL(challenge,4,v2); - - /* mash it up with md4 */ - mdfour(buf, (unsigned char *)challenge, 8); -#else - unsigned char buf[8]; - - generate_random_buffer(buf,8,False); -#endif - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,8); - challenge_sent = True; -} - -/******************************************************************* -set the last challenge sent, usually from a password server -********************************************************************/ -BOOL set_challenge(unsigned char *challenge) -{ - memcpy(saved_challenge,challenge,8); - challenge_sent = True; - return(True); -} - -/******************************************************************* -get the last challenge sent -********************************************************************/ -static BOOL last_challenge(unsigned char *challenge) -{ - if (!challenge_sent) return False; - memcpy(challenge,saved_challenge,8); - return(True); -} - -/* this holds info on user ids that are already validated for this VC */ -static user_struct *validated_users = NULL; -static int num_validated_users = 0; - -/**************************************************************************** -check if a uid has been validated, and return an pointer to the user_struct -if it has. NULL if not. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. -****************************************************************************/ -user_struct *get_valid_user_struct(uint16 vuid) -{ - if (vuid == UID_FIELD_INVALID) - return NULL; - vuid -= VUID_OFFSET; - if ((vuid >= (uint16)num_validated_users) || - (validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1)) - return NULL; - return &validated_users[vuid]; -} - -/**************************************************************************** -invalidate a uid -****************************************************************************/ -void invalidate_vuid(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - - if (vuser == NULL) return; - - vuser->uid = (uid_t)-1; - vuser->gid = (gid_t)-1; - - vuser->n_sids = 0; - - /* same number of igroups as groups */ - vuser->n_groups = 0; - - if (vuser->groups) - free((char *)vuser->groups); - - if (vuser->sids) - free((char *)vuser->sids); - - vuser->sids = NULL; - vuser->groups = NULL; -} - - -/**************************************************************************** -return a validated username -****************************************************************************/ -char *validated_username(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - if (vuser == NULL) - return 0; - return(vuser->name); -} - - - -/**************************************************************************** -register a uid/name pair as being valid and that a valid password -has been given. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. -****************************************************************************/ -uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]) -{ - user_struct *vuser; - struct passwd *pwfile; /* for getting real name from passwd file */ - - /* Ensure no vuid gets registered in share level security. */ - if(lp_security() == SEC_SHARE) - return UID_FIELD_INVALID; - -#if 0 - /* - * After observing MS-Exchange services writing to a Samba share - * I belive this code is incorrect. Each service does its own - * sessionsetup_and_X for the same user, and as each service shuts - * down, it does a user_logoff_and_X. As we are consolidating multiple - * sessionsetup_and_X's onto the same vuid here, when the first service - * shuts down, it invalidates all the open files for the other services. - * Hence I am removing this code and forcing each sessionsetup_and_X - * to get a new vuid. - * Jeremy Allison. (jallison@whistle.com). - */ - - int i; - for(i = 0; i < num_validated_users; i++) { - vuser = &validated_users[i]; - if ( vuser->uid == uid ) - return (uint16)(i + VUID_OFFSET); /* User already validated */ - } -#endif - - validated_users = (user_struct *)Realloc(validated_users, - sizeof(user_struct)* - (num_validated_users+1)); - - if (!validated_users) - { - DEBUG(0,("Failed to realloc users struct!\n")); - num_validated_users = 0; - return UID_FIELD_INVALID; - } - - vuser = &validated_users[num_validated_users]; - num_validated_users++; - - vuser->uid = uid; - vuser->gid = gid; - vuser->guest = guest; - fstrcpy(vuser->name,unix_name); - fstrcpy(vuser->requested_name,requested_name); - memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key)); - - vuser->n_sids = 0; - vuser->sids = NULL; - - vuser->n_groups = 0; - vuser->groups = NULL; - - /* Find all the groups this uid is in and store them. - Used by become_user() */ - get_unixgroups(unix_name,uid,gid, - &vuser->n_groups, - &vuser->groups); - - DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); - - DEBUG(3, ("Clearing default real name\n")); - fstrcpy(vuser->real_name, "\0"); - if (lp_unix_realname()) { - if ((pwfile=hashed_getpwnam(vuser->name))!= NULL) - { - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); - fstrcpy(vuser->real_name, pwfile->pw_gecos); - } - } - - return (uint16)((num_validated_users - 1) + VUID_OFFSET); -} - /**************************************************************************** add a name to the session users list @@ -290,275 +87,6 @@ static BOOL update_smbpassword_file(char *user, char *password) -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd, - unsigned char *c8, - uchar sess_key[16]) -{ - /* Finish the encryption of part_passwd. */ - unsigned char p24[24]; - - if (part_passwd == NULL) - DEBUG(10,("No password set - allowing access\n")); - /* No password set - always true ! */ - if (part_passwd == NULL) - return True; - - SMBOWFencrypt(part_passwd, c8, p24); - if (sess_key != NULL) - { - SMBsesskeygen_ntv1(part_passwd, NULL, sess_key); - } - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); - dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, password, 24); - DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); - DEBUG(100,("Value from encryption was |")); - dump_data(100, p24, 24); -#endif - return (memcmp(p24, password, 24) == 0); -} - -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len, - unsigned char *part_passwd, - unsigned char const *c8, - const char *user, const char *domain, - char *sess_key) -{ - /* Finish the encryption of part_passwd. */ - unsigned char kr[16]; - unsigned char resp[16]; - - if (part_passwd == NULL) - { - DEBUG(10,("No password set - allowing access\n")); - } - /* No password set - always true ! */ - if (part_passwd == NULL) - { - return True; - } - - ntv2_owf_gen(part_passwd, user, domain, kr); - SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp); - if (sess_key != NULL) - { - SMBsesskeygen_ntv2(kr, resp, sess_key); - } - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); - dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, password, pwd_len); - DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); - DEBUG(100,("Value from encryption was |")); - dump_data(100, resp, 16); -#endif - - return (memcmp(resp, password, 16) == 0); -} - -/**************************************************************************** - Do a specific test for an smb password being correct, given a smb_password and - the lanman and NT responses. -****************************************************************************/ -BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], - const char *user, const char *domain, - uchar *lm_pass, size_t lm_pwd_len, - uchar *nt_pass, size_t nt_pwd_len, - uchar sess_key[16]) -{ - uchar challenge[8]; - - if (smb_pass == NULL) - { - return False; - } - - DEBUG(4,("Checking SMB password for user %s\n", - smb_pass->unix_name)); - - if (smb_pass->acct_ctrl & ACB_DISABLED) - { - DEBUG(3,("account for user %s was disabled.\n", - smb_pass->unix_name)); - return False; - } - - if (chal == NULL) - { - DEBUG(5,("use last SMBnegprot challenge\n")); - if (!last_challenge(challenge)) - { - DEBUG(1,("no challenge done - password failed\n")); - return False; - } - } - else - { - DEBUG(5,("challenge received\n")); - memcpy(challenge, chal, 8); - } - - if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) - { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - if (lp_server_ntlmv2() != False && nt_pwd_len > 24) - { - DEBUG(4,("smb_password_ok: Check NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len, - (uchar *)smb_pass->smb_nt_passwd, - challenge, user, domain, - sess_key)) - { - return True; - } - } - if (lp_server_ntlmv2() != True && nt_pwd_len == 24) - { - DEBUG(4,("smb_password_ok: Check NT MD4 password\n")); - if (smb_pwd_check_ntlmv1((char *)nt_pass, - (uchar *)smb_pass->smb_nt_passwd, - challenge, - sess_key)) - { - DEBUG(4,("NT MD4 password check succeeded\n")); - return True; - } - } - DEBUG(4,("NT MD4 password check failed\n")); - } - - if (lp_server_ntlmv2() == True) - { - DEBUG(4,("Not checking LM MD4 password\n")); - return False; - } - - /* Try against the lanman password. smb_pass->smb_passwd == NULL means - no password, allow access. */ - - DEBUG(4,("Checking LM MD4 password\n")); - - if ((smb_pass->smb_passwd == NULL) && - (smb_pass->acct_ctrl & ACB_PWNOTREQ)) - { - DEBUG(4,("no password required for user %s\n", - smb_pass->unix_name)); - return True; - } - - if ((smb_pass->smb_passwd != NULL) && - smb_pwd_check_ntlmv1((char *)lm_pass, - (uchar *)smb_pass->smb_passwd, - challenge, NULL)) - { - DEBUG(4,("LM MD4 password check succeeded\n")); - return(True); - } - - DEBUG(4,("LM MD4 password check failed\n")); - - return False; -} - - -/**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash -return True if the password is correct, False otherwise -****************************************************************************/ - -BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal, - uchar *lm_pwd, size_t lm_pwd_len, - uchar *nt_pwd, size_t nt_pwd_len, - struct passwd *pwd, uchar user_sess_key[16]) -{ - const struct passwd *pass; - struct passwd pw; - char *user = NULL; - - if (smb_pass == NULL) - { - DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); - return False; - } - - user = smb_pass->unix_name; - - if (lm_pwd == NULL || nt_pwd == NULL) - { - return False; - } - - if (pwd != NULL && user == NULL) - { - pass = (struct passwd *) pwd; - user = pass->pw_name; - } - else - { - pass = Get_Pwnam(user,True); - if (pass == NULL) - { - DEBUG(3,("Couldn't find user %s\n",user)); - return False; - } - memcpy(&pw, pass, sizeof(struct passwd)); - pass = &pw; - } - - /* Quit if the account was disabled. */ - if (smb_pass->acct_ctrl & ACB_DISABLED) { - DEBUG(3,("account for user %s was disabled.\n", user)); - return False; - } - - /* Ensure the uid's match */ - if (smb_pass->unix_uid != pass->pw_uid) - { - DEBUG(3,("Error : UNIX (%d) and SMB (%d) uids in password files do not match !\n", pass->pw_uid, smb_pass->unix_uid)); - return False; - } - - if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords()) - { - DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->unix_name)); - return(True); - } - - if (smb_password_ok(smb_pass, chal, user, domain, - lm_pwd, lm_pwd_len, - nt_pwd, nt_pwd_len, - user_sess_key)) - { - if (user_sess_key != NULL) - { -#ifdef DEBUG_PASSWORD - DEBUG(100,("user session key: ")); - dump_data(100, user_sess_key, 16); -#endif - } - return(True); - } - - DEBUG(3,("Error pass_check_smb failed\n")); - return False; -} - /**************************************************************************** check if a username/password pair is OK either via the system password database or the encrypted SMB password database @@ -589,35 +117,6 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, update_smbpassword_file : NULL); } -/**************************************************************************** -check if a username is valid -****************************************************************************/ -BOOL user_ok(char *user,int snum) -{ - pstring valid, invalid; - BOOL ret; - - StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)); - StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)); - - string_sub(valid,"%S",lp_servicename(snum)); - string_sub(invalid,"%S",lp_servicename(snum)); - - ret = !user_in_list(user,invalid); - - if (ret && valid && *valid) { - ret = user_in_list(user,valid); - } - - if (ret && lp_onlyuser(snum)) { - char *user_list = lp_username(snum); - string_sub(user_list,"%S",lp_servicename(snum)); - ret = user_in_list(user,user_list); - } - - return(ret); -} - diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a0ad2ca20d..81f2a9beb9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -415,6 +415,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out char *smb_nt_passwd, int smb_nt_passlen) { struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ + uchar last_chal[8]; if (lp_security() == SEC_USER) { smb_trust_acct = getsmbpwnam(user); @@ -441,8 +442,8 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - - if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL, + if (!last_challenge(last_chal) || + !smb_password_ok(smb_trust_acct, last_chal, NULL, NULL, (unsigned char *)smb_passwd, smb_passlen, (unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL)) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5512e6e56b..7fde1fc6f6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -678,6 +678,18 @@ static void usage(char *pname) } #endif /* WITH_SSL */ +#if 0 + start_msrpc_agent("lsarpc"); +#endif + add_msrpc_command_processor( "samr", "lsass", api_samr_rpc ); + add_msrpc_command_processor( "srvsvc", "ntsvcs", api_srvsvc_rpc ); + add_msrpc_command_processor( "wkssvc", "ntsvcs", api_wkssvc_rpc ); + add_msrpc_command_processor( "browser", "ntsvcs", api_brs_rpc ); + add_msrpc_command_processor( "svcctl", "ntsvcs", api_svcctl_rpc ); + add_msrpc_command_processor( "NETLOGON", "lsass", api_netlog_rpc ); + add_msrpc_command_processor( "winreg", "winreg", api_reg_rpc ); + add_msrpc_command_processor( "spoolss", "spoolss", api_spoolss_rpc ); + codepage_initialise(lp_client_code_page()); if (!pwdb_initialise(True)) -- cgit From 4ab9d91428b66bd2fe407b0dba94f4130160b576 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 8 Dec 1999 21:43:03 +0000 Subject: ABOUT TIME!!!!!!!! damn, this one is bad. started, at least two days ago, to add an authentication mechanism to the smbd<->msrpc redirector/relay, such that sufficient unix / nt information could be transferred across the unix socket to do a become_user() on the other side of the socket. it is necessary that the msrpc daemon inherit the same unix and nt credentials as the smbd process from which it was spawned, until such time as the msrpc daemon receives an authentication request of its own, whereupon the msrpc daemon is responsible for authenticating the new credentials and doing yet another become_user() etc sequence. (This used to be commit 30c7fdd6ef10ecd35594311c1b250b95ff895489) --- source3/smbd/server.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7fde1fc6f6..f6ea8ecb65 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -678,9 +678,7 @@ static void usage(char *pname) } #endif /* WITH_SSL */ -#if 0 start_msrpc_agent("lsarpc"); -#endif add_msrpc_command_processor( "samr", "lsass", api_samr_rpc ); add_msrpc_command_processor( "srvsvc", "ntsvcs", api_srvsvc_rpc ); add_msrpc_command_processor( "wkssvc", "ntsvcs", api_wkssvc_rpc ); -- cgit From 0ce128e3550794d4dbbd1def00e87c020f72c992 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Dec 1999 01:25:49 +0000 Subject: delineation between smb and msrpc more marked. smbd now constructs pdus, and then feeds them over either a "local" function call or a "remote" function call to an msrpc service. the "remote" msrpc daemon, on the other side of a unix socket, then calls the same "local" function that smbd would, if the msrpc service were being run from inside smbd. this allows a transition from local msrpc services (inside the same smbd process) to remote (over a unix socket). removed reference to pipes_struct in msrpc services. all msrpc processing functions take rpcsrv_struct which is a structure containing state info for the msrpc functions to decode and create pdus. created become_vuser() which does everything not related to connection_struct that become_user() does. removed, as best i could, connection_struct dependencies from the nt spoolss printing code. todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific info on a per-connection basis, and if the connection dies then so does the info, and that's a fairly serious problem. had to put pretty much everything that is in user_struct into parse_creds.c to feed unix user info over to the msrpc daemons. why? because it's expensive to do unix password/group database lookups, and it's definitely expensive to do nt user profile lookups, not to mention pretty difficult and if you did either of these it would introduce a complication / unnecessary interdependency. so, send uid/gid/num_groups/gid_t* + SID+num_rids+domain_group_rids* + unix username + nt username + nt domain + user session key etc. this is the MINIMUM info identified so far that's actually implemented. missing bits include the called and calling netbios names etc. (basically, anything that can be loaded into standard_sub() and standard_sub_basic()...) (This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d) --- source3/smbd/close.c | 2 +- source3/smbd/ipc.c | 27 +++-------- source3/smbd/password.c | 10 ++-- source3/smbd/uid.c | 124 ++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 127 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 024a3c03e4..c37c2ceab2 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -129,7 +129,7 @@ void close_file(files_struct *fsp, BOOL normal_close) /* NT uses smbclose to start a print - weird */ if (normal_close && fsp->print_file) - print_file(conn, fsp); + print_file(conn, SNUM(conn), fsp); /* check for magic scripts */ if (normal_close) { diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a3e7932529..eeb367bcb5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3118,21 +3118,14 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, } static void api_rpc_trans_reply(char *outbuf, - pipes_struct *p, - prs_struct *pd) + pipes_struct *p) { - send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset); + send_trans_reply(outbuf, p->rsmb_pdu.data, NULL, NULL, 0, p->file_offset); - if (mem_buf_len(p->rhdr.data) <= p->file_offset) + if (mem_buf_len(p->rsmb_pdu.data) <= p->file_offset) { /* all of data was sent: no need to wait for SMBreadX calls */ - mem_free_data(p->rhdr .data); - mem_free_data(p->rfault .data); - mem_free_data(p->rdata .data); - mem_free_data(p->rdata_i.data); - mem_free_data(p->rauth .data); - mem_free_data(p->rverf .data); - mem_free_data(p->rntlm .data); + mem_free_data(p->rsmb_pdu.data); } } @@ -3221,14 +3214,9 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, uint16 pnum; uint16 subcommand; pipes_struct *p = NULL; - prs_struct pd; DEBUG(5,("api_fd_reply\n")); - /* make a static data parsing structure from the api_fd_reply data */ - prs_init(&pd, 0, 4, 0, True); - mem_create(pd.data, data, 0, tdscnt, 0, False); - /* First find out the name of this file. */ if (suwcnt != 2) { @@ -3257,11 +3245,10 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, { case 0x26: { - /* dce/rpc command */ - reply = rpc_command(p, &pd); + reply = rpc_to_smb(p, data, tdscnt); if (reply) { - api_rpc_trans_reply(outbuf, p, &pd); + api_rpc_trans_reply(outbuf, p); } break; } @@ -3284,8 +3271,6 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); } - mem_free_data(pd.data); - if (!reply) { return api_no_reply(outbuf, mdrcnt); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 240ec30c3f..91f727701c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -221,14 +221,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL, vuser->dc.user_sess_key); + ok = password_ok(user,password, pwlen, NULL, vuser->user_sess_key); if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); } /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->name,snum) && - password_ok(vuser->name, password, pwlen, NULL, vuser->dc.user_sess_key)) { + password_ok(vuser->name, password, pwlen, NULL, vuser->user_sess_key)) { fstrcpy(user, vuser->name); vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); @@ -252,7 +252,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstrcpy(user2,auser); if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL, vuser->dc.user_sess_key)) { + if (password_ok(user2,password, pwlen, NULL, vuser->user_sess_key)) { ok = True; fstrcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); @@ -291,7 +291,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, { if (*auser == '@') { - auser = validate_group(auser+1,password,pwlen,snum, vuser->dc.user_sess_key); + auser = validate_group(auser+1,password,pwlen,snum, vuser->user_sess_key); if (auser) { ok = True; @@ -304,7 +304,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstring user2; fstrcpy(user2,auser); if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL, vuser->dc.user_sess_key)) + password_ok(user2,password,pwlen,NULL, vuser->user_sess_key)) { ok = True; fstrcpy(user,user2); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 92565b7507..3501879d5f 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -25,6 +25,7 @@ extern int DEBUGLEVEL; static uid_t initial_uid; static gid_t initial_gid; +static struct uid_cache vcache; /* what user is current? */ extern struct current_user current_user; @@ -54,6 +55,8 @@ void init_uid(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; + vcache.entries = 0; + dos_ChDir(OriginalDir); } @@ -192,24 +195,127 @@ BOOL become_guest(void) /******************************************************************* check if a username is OK ********************************************************************/ -static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) +static BOOL check_vuser_ok(struct uid_cache *cache, user_struct *vuser,int snum) { int i; - for (i=0;iuid_cache.entries;i++) - if (conn->uid_cache.list[i] == vuser->uid) return(True); + for (i=0;ientries;i++) + if (cache->list[i] == vuser->uid) return(True); if (!user_ok(vuser->name,snum)) return(False); - i = conn->uid_cache.entries % UID_CACHE_SIZE; - conn->uid_cache.list[i] = vuser->uid; + i = cache->entries % UID_CACHE_SIZE; + cache->list[i] = vuser->uid; - if (conn->uid_cache.entries < UID_CACHE_SIZE) - conn->uid_cache.entries++; + if (cache->entries < UID_CACHE_SIZE) + cache->entries++; return(True); } +/**************************************************************************** + become the user of a connection number +****************************************************************************/ +BOOL become_vuser(uint16 vuid) +{ + user_struct *vuser = get_valid_user_struct(vuid); + gid_t gid; + uid_t uid; + + unbecome_vuser(); + + if((vuser != NULL) && !check_vuser_ok(&vcache, vuser, -1)) + return False; + + if ( vuser != 0 && + current_user.vuid == vuid && + current_user.uid == vuser->uid) + { + DEBUG(4,("Skipping become_vuser - already user\n")); + return(True); + } + uid = vuser->uid; + gid = vuser->gid; + current_user.ngroups = vuser->n_groups; + current_user.groups = vuser->groups; + + if (initial_uid == 0) + { + if (!become_gid(gid)) return(False); + +#ifdef HAVE_SETGROUPS + /* 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 (!become_uid(uid)) return(False); + } + + current_user.conn = NULL; + current_user.vuid = vuid; + + DEBUG(5,("become_vuser uid=(%d,%d) gid=(%d,%d)\n", + (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); + + return(True); +} + +/**************************************************************************** + unbecome a user +****************************************************************************/ +BOOL unbecome_vuser(void) +{ + dos_ChDir(OriginalDir); + + if (initial_uid == 0) + { +#ifdef HAVE_SETRESUID + 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 + + current_user.uid = initial_uid; + current_user.gid = initial_gid; + + if (dos_ChDir(OriginalDir) != 0) + DEBUG( 0, ( "chdir(%s) failed in unbecome_vuser\n", OriginalDir ) ); + + DEBUG(5,("unbecome_vuser now uid=(%d,%d) gid=(%d,%d)\n", + (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); + + current_user.conn = NULL; + current_user.vuid = UID_FIELD_INVALID; + + return(True); +} + /**************************************************************************** become the user of a connection number ****************************************************************************/ @@ -217,7 +323,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; - gid_t gid; + gid_t gid; uid_t uid; /* @@ -247,7 +353,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) snum = SNUM(conn); - if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) + if((vuser != NULL) && !check_vuser_ok(&conn->uid_cache, vuser, snum)) return False; if (conn->force_user || -- cgit From 4f8a24522c683761c6f2ee23dba56f6c7913377b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Dec 1999 20:03:42 +0000 Subject: final part of "first" phase converting over to msrpc daemon architecture. done a minimal amout of clean-up in the Makefile, removing unnecessary modules from the link stage. this is not complete, yet, and will involve some changes, for example to smbd, to remove dependencies on the password database API that shouldn't be there. for example, smbd should not ever call getsmbpwXXX() it should call the Samr or Lsa API. this first implementation has minor problems with not reinstantiating the same services as the caller. the "homes" service is a good example. (This used to be commit caa50525220b0d0250fa139367593c2de2c12135) --- source3/smbd/password.c | 129 ------------------------------------------------ source3/smbd/reply.c | 38 ++------------ source3/smbd/server.c | 11 ----- 3 files changed, 3 insertions(+), 175 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 91f727701c..fa46a74c14 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -606,132 +606,3 @@ use this machine as the password server.\n")); return(True); } -/*********************************************************************** - Do the same as security=server, but using NT Domain calls and a session - key from the workstation trust account password. -************************************************************************/ - -BOOL domain_client_validate( char *user, char *domain, - char *acct_name, uint16 acct_type, - char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen, - uchar user_sess_key[16]) -{ - unsigned char local_challenge[8]; - unsigned char local_lm_response[24]; - unsigned char local_nt_reponse[24]; - unsigned char trust_passwd[16]; - NET_ID_INFO_CTR ctr; - NET_USER_INFO_3 info3; - uint32 smb_uid_low; - fstring trust_acct; - fstring srv_name; - - fstrcpy(trust_acct, acct_name); - fstrcat(trust_acct, "$"); - - /* - * Check that the requested domain is not our own machine name. - * If it is, we should never check the PDC here, we use our own local - * password file. - */ - - if(strequal( domain, global_myname)) - { - DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); - return False; - } - - if (!get_any_dc_name(domain, srv_name)) - { - DEBUG(3,("domain_client_validate: could not find domain %s\n", - domain)); - return False; - } - - /* - * Next, check that the passwords given were encrypted. - */ - - if(((smb_apasslen != 24) && (smb_apasslen != 0)) || - ((smb_ntpasslen <= 24) && (smb_ntpasslen != 0))) - { - /* - * Not encrypted - do so. - */ - - DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); - generate_random_buffer( local_challenge, 8, False); - SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); - SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_reponse); - smb_apasslen = 24; - smb_ntpasslen = 24; - smb_apasswd = (char *)local_lm_response; - smb_ntpasswd = (char *)local_nt_reponse; - } - else - { - /* - * Encrypted - get the challenge we sent for these - * responses. - */ - - if (!last_challenge(local_challenge)) - { - DEBUG(0,("domain_client_validate: no challenge done - password failed\n")); - return False; - } - } - - /* - * Get the workstation trust account password. - */ - if (!trust_get_passwd( trust_passwd, domain, acct_name)) - { - return False; - } - - /* - * At this point, smb_apasswd points to the lanman response to - * the challenge in local_challenge, and smb_ntpasswd points to - * the NT response to the challenge in local_challenge. Ship - * these over the secure channel to a domain controller and - * see if they were valid. - */ - - /* - * Ok - we have an anonymous connection to the IPC$ share. - * Now start the NT Domain stuff :-). - */ - - if(cli_nt_setup_creds(srv_name, global_myname, trust_acct, - trust_passwd, acct_type) != 0x0) - { - DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \ - %s.\n", srv_name)); - return False; - } - - /* We really don't care what LUID we give the user. */ - generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - - if (!cli_nt_login_network(srv_name, global_myname, - domain, user, - smb_uid_low, (char *)local_challenge, - ((smb_apasslen != 0) ? smb_apasswd : NULL), - ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), - &ctr, &info3)) - { - DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ - %s to Domain controller %s.\n", user, domain, srv_name)); - return False; - } - - /* - * Here, if we really want it, we have lots of info about the user in info3. - * LKCLXXXX - really important to check things like "is this user acct - * locked out / disabled" etc!!!! - */ - - return True; -} diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 81f2a9beb9..10146c1287 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -495,41 +495,6 @@ static BOOL check_server_security(char *orig_user, char *domain, smb_ntpasswd, smb_ntpasslen); } -/**************************************************************************** - Check for a valid username and password in security=domain mode. -****************************************************************************/ - -static BOOL check_domain_security(char *orig_user, char *domain, - char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen, - uchar user_sess_key[16]) -{ - fstring acct_name; - uint16 acct_type = 0; - - if (lp_security() == SEC_SHARE || lp_security() == SEC_SERVER) - { - return False; - } - - if (lp_security() == SEC_DOMAIN && strequal(domain, global_myworkgroup)) - { - fstrcpy(acct_name, global_myname); - acct_type = SEC_CHAN_WKSTA; - } - else - { - fstrcpy(acct_name, global_myworkgroup); - acct_type = SEC_CHAN_DOMAIN; - } - - return domain_client_validate(orig_user, domain, - acct_name, acct_type, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen, - user_sess_key); -} - /**************************************************************************** reply to a session setup command ****************************************************************************/ @@ -552,6 +517,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; + uchar last_chal[8]; *smb_apasswd = 0; *smb_ntpasswd = 0; @@ -736,7 +702,9 @@ user %s attempted down-level SMB connection\n", user)); !check_server_security(orig_user, domain, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) && + !last_challenge(last_chal) && !check_domain_security(orig_user, domain, + last_chal, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen, user_sess_key) && !check_hosts_equiv(user) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f6ea8ecb65..bdb2827483 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -480,7 +480,6 @@ static void init_structs(void) { exit_server("could not allocate policy handles\n"); } - init_printer_hnd(); /* for SPOOLSS handles */ init_dptrs(); init_dfs_table(); } @@ -678,16 +677,6 @@ static void usage(char *pname) } #endif /* WITH_SSL */ - start_msrpc_agent("lsarpc"); - add_msrpc_command_processor( "samr", "lsass", api_samr_rpc ); - add_msrpc_command_processor( "srvsvc", "ntsvcs", api_srvsvc_rpc ); - add_msrpc_command_processor( "wkssvc", "ntsvcs", api_wkssvc_rpc ); - add_msrpc_command_processor( "browser", "ntsvcs", api_brs_rpc ); - add_msrpc_command_processor( "svcctl", "ntsvcs", api_svcctl_rpc ); - add_msrpc_command_processor( "NETLOGON", "lsass", api_netlog_rpc ); - add_msrpc_command_processor( "winreg", "winreg", api_reg_rpc ); - add_msrpc_command_processor( "spoolss", "spoolss", api_spoolss_rpc ); - codepage_initialise(lp_client_code_page()); if (!pwdb_initialise(True)) -- cgit From f6276724bafdb6145c0c7b565172d80cb04516ea Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 12 Dec 1999 21:00:35 +0000 Subject: changed function name of get_home_dir() to get_unixhome_dir(), to stop clash with gnu readline library. fixed issue with [homes] service not being there - call lp_add_home() just before starting the msrpc processing. (This used to be commit 054195df9b6187c663ede5cf4489499abbdc29fc) --- source3/smbd/password.c | 2 +- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fa46a74c14..e15e08a1af 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -470,7 +470,7 @@ BOOL check_hosts_equiv(char *user) if (lp_use_rhosts()) { - char *home = get_home_dir(user); + char *home = get_unixhome_dir(user); if (home) { extern int Client; slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 10146c1287..fed82b5e54 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -765,7 +765,7 @@ user %s attempted down-level SMB connection\n", user)); lp_servicenumber(user) < 0) { int homes = lp_servicenumber(HOMES_NAME); - char *home = get_home_dir(user); + char *home = get_unixhome_dir(user); if (homes >= 0 && home) { pstring home_dir; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f0af82fb4e..64abf3de1d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -91,7 +91,7 @@ int find_service(char *service) /* now handle the special case of a home directory */ if (iService < 0) { - char *phome_dir = get_home_dir(service); + char *phome_dir = get_unixhome_dir(service); pstring home_dir; if(phome_dir == NULL) @@ -101,7 +101,7 @@ int find_service(char *service) * be a Windows to unix mapped user name. */ if(map_username(service)) - phome_dir = get_home_dir(service); + phome_dir = get_unixhome_dir(service); } DEBUG(3,("checking for home directory %s gave %s\n",service, -- cgit From 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 1999 13:27:58 +0000 Subject: first pass at updating head branch to be to be the same as the SAMBA_2_0 branch (This used to be commit 453a822a76780063dff23526c35408866d0c0154) --- source3/smbd/blocking.c | 55 +- source3/smbd/chgpasswd.c | 277 +++---- source3/smbd/close.c | 92 ++- source3/smbd/connection.c | 14 +- source3/smbd/dfree.c | 36 +- source3/smbd/dir.c | 643 ++++++++++------ source3/smbd/dosmode.c | 25 +- source3/smbd/fileio.c | 567 +++++++++++++- source3/smbd/filename.c | 68 +- source3/smbd/files.c | 18 +- source3/smbd/groupname.c | 223 +++++- source3/smbd/ipc.c | 493 ++++++------ source3/smbd/mangle.c | 101 ++- source3/smbd/message.c | 20 +- source3/smbd/negprot.c | 95 ++- source3/smbd/nttrans.c | 1227 ++++++++++++++++++++++++++---- source3/smbd/open.c | 386 ++++++---- source3/smbd/oplock.c | 664 +++++++++++----- source3/smbd/password.c | 1042 +++++++++++++++++++++++--- source3/smbd/pipes.c | 64 +- source3/smbd/predict.c | 14 +- source3/smbd/process.c | 501 ++++++++----- source3/smbd/quotas.c | 111 ++- source3/smbd/reply.c | 1831 +++++++++++++++++++++++++++------------------ source3/smbd/server.c | 324 ++++---- source3/smbd/service.c | 262 +++---- source3/smbd/ssl.c | 12 +- source3/smbd/trans2.c | 1034 +++++++++++-------------- source3/smbd/uid.c | 434 ++++------- 29 files changed, 6984 insertions(+), 3649 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 32b6d010a4..16882be2bb 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -211,18 +211,16 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec for(i = blr->lock_num; i >= 0; i--) { int dummy1; uint32 dummy2; - if(!large_file_format) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - } -#ifdef LARGE_SMB_OFF_T - else { - count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); - offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); - } -#endif /* LARGE_SMB_OFF_T */ + BOOL err; + + count = get_lock_count( data, i, large_file_format, &err); + offset = get_lock_offset( data, i, large_file_format, &err); + + /* + * We know err cannot be set as if it was the lock + * request would never have been queued. JRA. + */ + do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } @@ -313,7 +311,7 @@ static BOOL process_lockread(blocking_lock_record *blr) SSVAL(smb_buf(outbuf),1,nread); DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", - fsp->fsp_name, fsp->fnum, numtoread, nread ) ); + fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) ); send_blocking_reply(outbuf,outsize); return True; @@ -401,18 +399,15 @@ static BOOL process_lockingX(blocking_lock_record *blr) */ for(; blr->lock_num < num_locks; blr->lock_num++) { - if(!large_file_format) { - count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); - offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); - } -#ifdef LARGE_SMB_OFF_T - else { - count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(blr->lock_num))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(blr->lock_num))); - offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(blr->lock_num))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(blr->lock_num))); - } -#endif /* LARGE_SMB_OFF_T */ + BOOL err; + + count = get_lock_count( data, blr->lock_num, large_file_format, &err); + offset = get_lock_offset( data, blr->lock_num, large_file_format, &err); + + /* + * We know err cannot be set as if it was the lock + * request would never have been queued. JRA. + */ errno = 0; if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) @@ -526,6 +521,16 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); } } +/**************************************************************************** + Return True if the blocking lock queue has entries. +*****************************************************************************/ + +BOOL blocking_locks_pending(void) +{ + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + return (blr == NULL ? False : True); +} + /**************************************************************************** Process the blocking lock queue. Note that this is only called as root. *****************************************************************************/ diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 3d31db7fb5..b86091e773 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -52,24 +52,20 @@ extern int DEBUGLEVEL; #if ALLOW_CHANGE_PASSWORD -#define MINPASSWDLENGTH 5 -#define BUFSIZE 512 static int findpty(char **slave) { int master; -#ifndef HAVE_GRANTPT static fstring line; - DIR *dirp; - struct dirent *dentry; + void *dirp; char *dpname; -#endif /* !HAVE_GRANTPT */ #if defined(HAVE_GRANTPT) - if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 1) { + /* Try to open /dev/ptmx. If that fails, fall through to old method. */ + if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0) { grantpt(master); unlockpt(master); - *slave = ptsname(master); + *slave = (char *)ptsname(master); if (*slave == NULL) { DEBUG(0,("findpty: Unable to create master/slave pty pair.\n")); /* Stop fd leak on error. */ @@ -80,14 +76,14 @@ static int findpty(char **slave) return (master); } } -#else /* HAVE_GRANTPT */ +#endif /* HAVE_GRANTPT */ + fstrcpy( line, "/dev/ptyXX" ); - dirp = opendir("/dev"); + dirp = OpenDir(NULL, "/dev", False); if (!dirp) return(-1); - while ((dentry = readdir(dirp)) != NULL) { - dpname = dentry->d_name; + while ((dpname = ReadDirName(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); line[8] = dpname[3]; @@ -96,13 +92,12 @@ static int findpty(char **slave) DEBUG(3,("pty: opened %s\n", line ) ); line[5] = 't'; *slave = line; - closedir(dirp); + CloseDir(dirp); return (master); } } } - closedir(dirp); -#endif /* HAVE_GRANTPT */ + CloseDir(dirp); return (-1); } @@ -110,9 +105,9 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, { int slave; struct termios stermios; - const struct passwd *pass = Get_Pwnam(name,True); - int gid; - int uid; + struct passwd *pass = Get_Pwnam(name,True); + gid_t gid; + uid_t uid; if (pass == NULL) { DEBUG(0,("dochild: user name %s doesn't exist in the UNIX password database.\n", @@ -122,11 +117,8 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, gid = pass->pw_gid; uid = pass->pw_uid; -#ifdef HAVE_SETRESUID - setresuid(0,0,0); -#else - setuid(0); -#endif + + gain_root_privilege(); /* Start new session - gets rid of controlling terminal. */ if (setsid() < 0) { @@ -186,19 +178,7 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, /* make us completely into the right uid */ if (!as_root) { -#ifdef HAVE_SETRESUID - setresgid(0,0,0); - setresuid(0,0,0); - setresgid(gid,gid,gid); - setresuid(uid,uid,uid); -#else - setuid(0); - seteuid(0); - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); -#endif + become_user_permanently(uid, gid); } DEBUG(10, ("Invoking '%s' as password change program.\n", passwordprogram)); @@ -211,92 +191,91 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram, return(True); } -static int expect(int master,char *expected,char *buf) +static int expect(int master, char *issue, char *expected) { - int n, m; - - n = 0; - buf[0] = 0; - while (1) { - if (n >= BUFSIZE-1) { - return False; - } + pstring buffer; + int attempts, timeout, nread, len; + BOOL match = False; - /* allow 4 seconds for some output to appear */ - m = read_with_timeout(master, buf+n, 1, BUFSIZE-1-n, 4000); - if (m < 0) - return False; + for (attempts = 0; attempts < 2; attempts++) + { + if (!strequal(issue, ".")) + { + if (lp_passwd_chat_debug()) + DEBUG(100, ("expect: sending [%s]\n", issue)); - n += m; - buf[n] = 0; + write(master, issue, strlen(issue)); + } - { - pstring s1,s2; - pstrcpy(s1,buf); - pstrcpy(s2,expected); - if (do_match(s1, s2, False)) - return(True); - } - } + if (strequal(expected, ".")) + return True; + + timeout = 2000; + nread = 0; + buffer[nread] = 0; + + while ((len = read_with_timeout(master, buffer + nread, 1, + sizeof(buffer) - nread - 1, timeout)) > 0) + { + nread += len; + buffer[nread] = 0; + + if ((match = unix_do_match(buffer, expected, False))) + timeout = 200; + } + + if (lp_passwd_chat_debug()) + DEBUG(100, ("expect: expected [%s] received [%s]\n", + expected, buffer)); + + if (match) + break; + + if (len < 0) + { + DEBUG(2, ("expect: %s\n", strerror(errno))); + return False; + } + } + + return match; } static void pwd_sub(char *buf) { - string_sub(buf,"\\n","\n"); - string_sub(buf,"\\r","\r"); - string_sub(buf,"\\s"," "); - string_sub(buf,"\\t","\t"); + all_string_sub(buf,"\\n","\n",0); + all_string_sub(buf,"\\r","\r",0); + all_string_sub(buf,"\\s"," ",0); + all_string_sub(buf,"\\t","\t",0); } -static void writestring(int fd,char *s) +static int talktochild(int master, char *seq) { - int l; - - l = strlen (s); - write (fd, s, l); -} + int count = 0; + fstring issue, expected; + fstrcpy(issue, "."); -static int talktochild(int master, char *chatsequence) -{ - char buf[BUFSIZE]; - int count=0; - char *ptr=chatsequence; - fstring chatbuf; - - *buf = 0; - sleep(1); - - while (next_token(&ptr,chatbuf,NULL,sizeof(chatbuf))) { - BOOL ok=True; - count++; - pwd_sub(chatbuf); - if (!strequal(chatbuf,".")) - ok = expect(master,chatbuf,buf); - - if (lp_passwd_chat_debug()) - DEBUG(100,("talktochild: chatbuf=[%s] responsebuf=[%s]\n",chatbuf,buf)); - - if (!ok) { - DEBUG(3,("response %d incorrect\n",count)); - return(False); - } + while (next_token(&seq, expected, NULL, sizeof(expected))) + { + pwd_sub(expected); + count++; - if (!next_token(&ptr,chatbuf,NULL,sizeof(chatbuf))) break; - pwd_sub(chatbuf); - if (!strequal(chatbuf,".")) - writestring(master,chatbuf); + if (!expect(master, issue, expected)) + { + DEBUG(3,("Response %d incorrect\n", count)); + return False; + } - if (lp_passwd_chat_debug()) - DEBUG(100,("talktochild: sendbuf=[%s]\n",chatbuf)); - } + if (!next_token(&seq, issue, NULL, sizeof(issue))) + fstrcpy(issue, "."); - if (count<1) return(False); + pwd_sub(issue); + } - return (True); + return (count > 0); } - static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root) { char *slavedev; @@ -311,9 +290,17 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc return(False); } + /* + * We need to temporarily stop CatchChild from eating + * SIGCLD signals as it also eats the exit status code. JRA. + */ + + CatchChildLeaveStatus(); + if ((pid = fork()) < 0) { DEBUG(3,("Cannot fork() child for password change: %s\n",name)); close(master); + CatchChild(); return(False); } @@ -324,12 +311,26 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc kill(pid, SIGKILL); /* be sure to end this process */ } - if ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { + while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { + if(errno == EINTR) { + errno = 0; + continue; + } + break; + } + + if (wpid < 0) { DEBUG(3,("The process is no longer waiting!\n\n")); close(master); + CatchChild(); return(False); } + /* + * Go back to ignoring children. + */ + CatchChild(); + close(master); if (pid != wpid) { @@ -362,8 +363,12 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid())); chstat = dochild(master, slavedev, name, passwordprogram, as_root); - if (as_root) - unbecome_root(False); + /* + * The child should never return from dochild() .... + */ + + DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat )); + exit(1); } if (chstat) @@ -376,8 +381,8 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; - int i; - int len; + size_t i; + size_t len; strlower(name); DEBUG(3,("Password change for user: %s\n",name)); @@ -388,9 +393,10 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) /* Take the passed information and test it for minimum criteria */ /* Minimum password length */ - if (strlen(newpass) < MINPASSWDLENGTH) /* too short, must be at least MINPASSWDLENGTH */ + if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ { - DEBUG(2,("Password Change: %s, New password is shorter than MINPASSWDLENGTH\n",name)); + DEBUG(0,("Password Change: user %s, New password is shorter than minimum password length = %d\n", + name, lp_min_passwd_length())); return (False); /* inform the user */ } @@ -435,13 +441,14 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) } } - string_sub(passwordprogram,"%u",name); - all_string_sub(passwordprogram,"%o",oldpass); - all_string_sub(passwordprogram,"%n",newpass); + pstring_sub(passwordprogram,"%u",name); + /* note that we do NOT substitute the %o and %n in the password program + as this would open up a security hole where the user could use + a new password containing shell escape characters */ - string_sub(chatsequence,"%u",name); - all_string_sub(chatsequence,"%o",oldpass); - all_string_sub(chatsequence,"%n",newpass); + pstring_sub(chatsequence,"%u",name); + all_string_sub(chatsequence,"%o",oldpass,sizeof(pstring)); + all_string_sub(chatsequence,"%n",newpass,sizeof(pstring)); return(chat_with_program(passwordprogram,name,chatsequence, as_root)); } @@ -531,7 +538,7 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2 if (smbpw->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->unix_name)); + DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); return False; } @@ -573,14 +580,6 @@ BOOL pass_oem_change(char *user, &sampw, new_passwd, sizeof(new_passwd)); - /* now we check to see if we are actually allowed to change the - password. */ - - if (ret && (sampw->acct_ctrl & ACB_PWLOCK)) - { - ret = False; - } - /* * At this point we have the new case-sensitive plaintext * password in the fstring new_passwd. If we wanted to synchronise @@ -621,12 +620,12 @@ BOOL check_oem_password(char *user, static uchar null_pw[16]; static uchar null_ntpw[16]; struct smb_passwd *smbpw = NULL; + int new_pw_len; uchar new_ntp16[16]; uchar unenc_old_ntpw[16]; uchar new_p16[16]; uchar unenc_old_pw[16]; char no_pw[2]; - uint32 len; BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); @@ -683,11 +682,35 @@ BOOL check_oem_password(char *user, */ SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); - if (!decode_pw_buffer(lmdata, new_passwd, new_passwd_size, &len)) + /* + * The length of the new password is in the last 4 bytes of + * the data buffer. + */ + + new_pw_len = IVAL(lmdata, 512); + if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } + if (nt_pass_set) + { + /* + * nt passwords are in unicode + */ + int uni_pw_len = new_pw_len; + char *pw; + new_pw_len /= 2; + pw = dos_unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); + memcpy(new_passwd, pw, new_pw_len+1); + } + else + { + memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); + new_passwd[new_pw_len] = '\0'; + } + /* * To ensure we got the correct new password, hash it and * use it as a key to test the passed old password. diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c37c2ceab2..d06cb3b5bb 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -23,9 +23,6 @@ extern int DEBUGLEVEL; -extern int32 global_oplocks_open; - - /**************************************************************************** run a file if it is a magic script ****************************************************************************/ @@ -72,6 +69,8 @@ static void close_filestruct(files_struct *fsp) { connection_struct *conn = fsp->conn; + flush_write_cache(fsp, CLOSE_FLUSH); + fsp->open = False; fsp->is_directory = False; @@ -80,13 +79,6 @@ static void close_filestruct(files_struct *fsp) free((char *)fsp->wbmpx_ptr); fsp->wbmpx_ptr = NULL; } - -#if WITH_MMAP - if(fsp->mmap_ptr) { - munmap(fsp->mmap_ptr,fsp->mmap_size); - fsp->mmap_ptr = NULL; - } -#endif } /**************************************************************************** @@ -97,14 +89,16 @@ static void close_filestruct(files_struct *fsp) the closing of the connection. In the latter case printing and magic scripts are not run. ****************************************************************************/ -void close_file(files_struct *fsp, BOOL normal_close) + +static int close_normal_file(files_struct *fsp, BOOL normal_close) { SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; int token; - BOOL last_reference = False; - BOOL delete_on_close = fsp->fd_ptr->delete_on_close; + BOOL last_reference = False; + BOOL delete_on_close = fsp->fd_ptr->delete_on_close; connection_struct *conn = fsp->conn; + int err = 0; remove_pending_lock_requests_by_fid(fsp); @@ -119,7 +113,10 @@ void close_file(files_struct *fsp, BOOL normal_close) del_share_mode(token, fsp); } - if(fd_attempt_close(fsp) == 0) + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + release_file_oplock(fsp); + + if(fd_attempt_close(fsp->fd_ptr,&err) == 0) last_reference = True; fsp->fd_ptr = NULL; @@ -129,7 +126,7 @@ void close_file(files_struct *fsp, BOOL normal_close) /* NT uses smbclose to start a print - weird */ if (normal_close && fsp->print_file) - print_file(conn, SNUM(conn), fsp); + print_file(conn, fsp); /* check for magic scripts */ if (normal_close) { @@ -144,7 +141,8 @@ void close_file(files_struct *fsp, BOOL normal_close) if (normal_close && last_reference && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(fsp->conn->vfs_ops.unlink(dos_to_unix(fsp->fsp_name, False)) != 0) { + if(dos_unlink(fsp->fsp_name) != 0) { + /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted @@ -157,30 +155,46 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); } } - if(fsp->granted_oplock == True) - global_oplocks_open--; - - fsp->sent_oplock_break = False; - - DEBUG(2,("%s closed file %s (numopen=%d)\n", + DEBUG(2,("%s closed file %s (numopen=%d) %s\n", conn->user,fsp->fsp_name, - conn->num_files_open)); + conn->num_files_open, err ? strerror(err) : "")); if (fsp->fsp_name) { string_free(&fsp->fsp_name); } file_free(fsp); + + return err; } /**************************************************************************** Close a directory opened by an NT SMB call. ****************************************************************************/ -void close_directory(files_struct *fsp) +static int close_directory(files_struct *fsp, BOOL normal_close) { remove_pending_change_notify_requests_by_fid(fsp); + /* + * NT can set delete_on_close of the last open + * reference to a directory also. + */ + + if (normal_close && fsp->directory_delete_on_close) { + BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name); + DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", + fsp->fsp_name, ok ? "succeeded" : "failed" )); + + /* + * Ensure we remove any change notify requests that would + * now fail as the directory has been deleted. + */ + + if(ok) + remove_pending_change_notify_requests_by_filename(fsp); + } + /* * Do the code common to files and directories. */ @@ -190,5 +204,35 @@ void close_directory(files_struct *fsp) string_free(&fsp->fsp_name); file_free(fsp); + + return 0; +} + +/**************************************************************************** + Close a file opened with null permissions in order to read permissions. +****************************************************************************/ + +static int close_statfile(files_struct *fsp, BOOL normal_close) +{ + close_filestruct(fsp); + + if (fsp->fsp_name) + string_free(&fsp->fsp_name); + + file_free(fsp); + + return 0; } +/**************************************************************************** + Close a directory opened by an NT SMB call. +****************************************************************************/ + +int close_file(files_struct *fsp, BOOL normal_close) +{ + if(fsp->is_directory) + return close_directory(fsp, normal_close); + else if(fsp->stat_open) + return close_statfile(fsp, normal_close); + return close_normal_file(fsp, normal_close); +} diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index db6c66f1d5..393a3e7372 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -34,7 +34,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) struct connect_record crec; pstring fname; int fd; - int mypid = getpid(); + pid_t mypid = getpid(); int i; DEBUG(3,("Yielding connection to %s\n",name)); @@ -42,7 +42,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) if (max_connections <= 0) return(True); - bzero(&crec,sizeof(crec)); + memset((char *)&crec,'\0',sizeof(crec)); pstrcpy(fname,lp_lockdir()); trim_string(fname,"","/"); @@ -85,7 +85,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) return(False); } - bzero((void *)&crec,sizeof(crec)); + memset((void *)&crec,'\0',sizeof(crec)); /* remove our mark */ if (sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || @@ -154,7 +154,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO return False; } - total_recs = file_size(fname) / sizeof(crec); + total_recs = get_file_size(fname) / sizeof(crec); /* find a free spot */ for (i=0;i WORDMAX || *dsize > WORDMAX || *bsize < 512) { *dfree /= 2; *dsize /= 2; *bsize *= 2; - if (*bsize > WORDMAX) { - *bsize = WORDMAX; - if (*dsize > WORDMAX) - *dsize = WORDMAX; - if (*dfree > WORDMAX) - *dfree = WORDMAX; - break; + if(small_query) { + /* + * Force max to fit in 16 bit fields. + */ + if (*bsize > (WORDMAX*512)) { + *bsize = (WORDMAX*512); + if (*dsize > WORDMAX) + *dsize = WORDMAX; + if (*dfree > WORDMAX) + *dfree = WORDMAX; + break; + } } } } @@ -152,7 +157,7 @@ static int fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) #endif /* STAT_STATFS4 */ -#ifdef STAT_STATVFS /* SVR4 */ +#if defined(STAT_STATVFS) || defined(STAT_STATVFS64) /* SVR4 */ # define CONVERT_BLOCKS(B) \ adjust_blocks ((SMB_BIG_UINT)(B), fsd.f_frsize ? (SMB_BIG_UINT)fsd.f_frsize : (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) @@ -185,7 +190,9 @@ static int fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) /**************************************************************************** return number of 1K blocks available on a path and total number ****************************************************************************/ -static SMB_BIG_UINT disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) + +static SMB_BIG_UINT disk_free(char *path, BOOL small_query, + SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { int dfree_retval; SMB_BIG_UINT dfree_q = 0; @@ -219,7 +226,7 @@ static SMB_BIG_UINT disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree *dfree = MAX(1,*dfree); } - disk_norm(bsize,dfree,dsize); + disk_norm(small_query,bsize,dfree,dsize); if ((*bsize) < 1024) { dfree_retval = (*dfree)/(1024/(*bsize)); @@ -234,7 +241,8 @@ static SMB_BIG_UINT disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree /**************************************************************************** wrap it to get filenames right ****************************************************************************/ -SMB_BIG_UINT sys_disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +SMB_BIG_UINT sys_disk_free(char *path, BOOL small_query, + SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { - return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize)); + return(disk_free(dos_to_unix(path,False),small_query, bsize,dfree,dsize)); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index b7ae2af47c..28faa9a06b 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -27,257 +27,378 @@ extern int DEBUGLEVEL; This module implements directory related functions for Samba. */ - - -static uint32 dircounter = 0; - - -#define NUMDIRPTRS 256 - - -static struct dptr_struct { - int pid; +typedef struct _dptr_struct { + struct _dptr_struct *next, *prev; + int dnum; + uint16 spid; connection_struct *conn; - uint32 lastused; void *ptr; - BOOL valid; - BOOL finished; BOOL expect_close; char *wcard; /* Field only used for trans2_ searches */ uint16 attr; /* Field only used for trans2_ searches */ char *path; -} -dirptrs[NUMDIRPTRS]; +} dptr_struct; +static struct bitmap *dptr_bmap; +static dptr_struct *dirptrs; static int dptrs_open = 0; +#define INVALID_DPTR_KEY (-3) + /**************************************************************************** -initialise the dir array + Initialise the dir bitmap. ****************************************************************************/ + void init_dptrs(void) { static BOOL dptrs_init=False; - int i; - if (dptrs_init) return; - for (i=0;iptr) { + DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); dptrs_open--; - CloseDir(dirptrs[key].ptr); - dirptrs[key].ptr = NULL; - } + CloseDir(dptr->ptr); + dptr->ptr = NULL; + } } /**************************************************************************** -idle the oldest dptr + Idle the oldest dptr. ****************************************************************************/ + static void dptr_idleoldest(void) { - int i; - uint32 old=dircounter+1; - int oldi= -1; - for (i=0;inext; dptr = dptr->next) + ; + + if(!dptr) { + DEBUG(0,("No dptrs available to idle ?\n")); + return; + } + + /* + * Idle the oldest pointer. + */ + + for(; dptr; dptr = dptr->prev) { + if (dptr->ptr) { + dptr_idle(dptr); + return; } - if (oldi != -1) - dptr_idle(oldi); - else - DEBUG(0,("No dptrs available to idle??\n")); + } } /**************************************************************************** -get the dir ptr for a dir index + Get the dptr_struct for a dir index. ****************************************************************************/ -static void *dptr_get(int key,uint32 lastused) + +static dptr_struct *dptr_get(int key, BOOL forclose) { - struct dptr_struct *dp = &dirptrs[key]; - - if (dp->valid) { - if (lastused) dp->lastused = lastused; - if (!dp->ptr) { - if (dptrs_open >= MAX_OPEN_DIRECTORIES) - dptr_idleoldest(); - DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dp->ptr = OpenDir(dp->conn, dp->path, True))) - dptrs_open++; - } - return(dp->ptr); - } - return(NULL); + dptr_struct *dptr; + + for(dptr = dirptrs; dptr; dptr = dptr->next) { + if(dptr->dnum == key) { + if (!forclose && !dptr->ptr) { + if (dptrs_open >= MAX_OPEN_DIRECTORIES) + dptr_idleoldest(); + DEBUG(4,("Reopening dptr key %d\n",key)); + if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True))) + dptrs_open++; + } + DLIST_PROMOTE(dirptrs,dptr); + return dptr; + } + } + return(NULL); } /**************************************************************************** -get the dir path for a dir index + Get the dptr ptr for a dir index. ****************************************************************************/ + +static void *dptr_ptr(int key) +{ + dptr_struct *dptr = dptr_get(key, False); + + if (dptr) + return(dptr->ptr); + return(NULL); +} + +/**************************************************************************** + Get the dir path for a dir index. +****************************************************************************/ + char *dptr_path(int key) { - if (dirptrs[key].valid) - return(dirptrs[key].path); + dptr_struct *dptr = dptr_get(key, False); + + if (dptr) + return(dptr->path); return(NULL); } /**************************************************************************** -get the dir wcard for a dir index (lanman2 specific) + Get the dir wcard for a dir index (lanman2 specific). ****************************************************************************/ + char *dptr_wcard(int key) { - if (dirptrs[key].valid) - return(dirptrs[key].wcard); + dptr_struct *dptr = dptr_get(key, False); + + if (dptr) + return(dptr->wcard); return(NULL); } /**************************************************************************** -set the dir wcard for a dir index (lanman2 specific) -Returns 0 on ok, 1 on fail. + Set the dir wcard for a dir index (lanman2 specific). + Returns 0 on ok, 1 on fail. ****************************************************************************/ + BOOL dptr_set_wcard(int key, char *wcard) { - if (dirptrs[key].valid) { - dirptrs[key].wcard = wcard; + dptr_struct *dptr = dptr_get(key, False); + + if (dptr) { + dptr->wcard = wcard; return True; } return False; } /**************************************************************************** -set the dir attrib for a dir index (lanman2 specific) -Returns 0 on ok, 1 on fail. + Set the dir attrib for a dir index (lanman2 specific). + Returns 0 on ok, 1 on fail. ****************************************************************************/ + BOOL dptr_set_attr(int key, uint16 attr) { - if (dirptrs[key].valid) { - dirptrs[key].attr = attr; + dptr_struct *dptr = dptr_get(key, False); + + if (dptr) { + dptr->attr = attr; return True; } return False; } /**************************************************************************** -get the dir attrib for a dir index (lanman2 specific) + Get the dir attrib for a dir index (lanman2 specific) ****************************************************************************/ + uint16 dptr_attr(int key) { - if (dirptrs[key].valid) - return(dirptrs[key].attr); + dptr_struct *dptr = dptr_get(key, False); + + if (dptr) + return(dptr->attr); return(0); } /**************************************************************************** -close a dptr + Close a dptr (internal func). +****************************************************************************/ + +static void dptr_close_internal(dptr_struct *dptr) +{ + DEBUG(4,("closing dptr key %d\n",dptr->dnum)); + + DLIST_REMOVE(dirptrs, dptr); + + /* + * Free the dnum in the bitmap. Remember the dnum value is always + * biased by one with respect to the bitmap. + */ + + if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) { + DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n", + dptr->dnum )); + } + + bitmap_clear(dptr_bmap, dptr->dnum - 1); + + if (dptr->ptr) { + CloseDir(dptr->ptr); + dptrs_open--; + } + + /* Lanman 2 specific code */ + if (dptr->wcard) + free(dptr->wcard); + string_set(&dptr->path,""); + free((char *)dptr); +} + +/**************************************************************************** + Close a dptr given a key. ****************************************************************************/ -void dptr_close(int key) + +void dptr_close(int *key) { + dptr_struct *dptr; + + if(*key == INVALID_DPTR_KEY) + return; + /* OS/2 seems to use -1 to indicate "close all directories" */ - if (key == -1) { - int i; - for (i=0;inext; + dptr_close_internal(dptr); + } + *key = INVALID_DPTR_KEY; return; } - if (key < 0 || key >= NUMDIRPTRS) { - DEBUG(3,("Invalid key %d given to dptr_close\n",key)); + dptr = dptr_get(*key, True); + + if (!dptr) { + DEBUG(0,("Invalid key %d given to dptr_close\n", *key)); return; } - if (dirptrs[key].valid) { - DEBUG(4,("closing dptr key %d\n",key)); - if (dirptrs[key].ptr) { - CloseDir(dirptrs[key].ptr); - dptrs_open--; - } - /* Lanman 2 specific code */ - if (dirptrs[key].wcard) - free(dirptrs[key].wcard); - dirptrs[key].valid = False; - string_set(&dirptrs[key].path,""); - } + dptr_close_internal(dptr); + + *key = INVALID_DPTR_KEY; } /**************************************************************************** -close all dptrs for a cnum + Close all dptrs for a cnum. ****************************************************************************/ + void dptr_closecnum(connection_struct *conn) { - int i; - for (i=0;inext; + if (dptr->conn == conn) + dptr_close_internal(dptr); + } } /**************************************************************************** -idle all dptrs for a cnum + Idle all dptrs for a cnum. ****************************************************************************/ + void dptr_idlecnum(connection_struct *conn) { - int i; - for (i=0;inext) { + if (dptr->conn == conn && dptr->ptr) + dptr_idle(dptr); + } } /**************************************************************************** -close a dptr that matches a given path, only if it matches the pid also + Close a dptr that matches a given path, only if it matches the spid also. ****************************************************************************/ -void dptr_closepath(char *path,int pid) + +void dptr_closepath(char *path,uint16 spid) { - int i; - for (i=0;inext; + if (spid == dptr->spid && strequal(dptr->path,path)) + dptr_close_internal(dptr); + } } /**************************************************************************** - start a directory listing + Start a directory listing. ****************************************************************************/ + static BOOL start_dir(connection_struct *conn,char *directory) { - DEBUG(5,("start_dir dir=%s\n",directory)); + DEBUG(5,("start_dir dir=%s\n",directory)); - if (!check_name(directory,conn)) - return(False); + if (!check_name(directory,conn)) + return(False); - if (! *directory) - directory = "."; - - conn->dirptr = OpenDir(conn, directory, True); - if (conn->dirptr) { - dptrs_open++; - string_set(&conn->dirpath,directory); - return(True); - } + if (! *directory) + directory = "."; + + conn->dirptr = OpenDir(conn, directory, True); + if (conn->dirptr) { + dptrs_open++; + string_set(&conn->dirpath,directory); + return(True); + } - return(False); + return(False); } +/**************************************************************************** + Try and close the oldest handle not marked for + expect close in the hope that the client has + finished with that one. +****************************************************************************/ + +static void dptr_close_oldest(BOOL old) +{ + dptr_struct *dptr; + + /* + * Go to the end of the list. + */ + for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) + ; + + if(!dptr) { + DEBUG(0,("No old dptrs available to close oldest ?\n")); + return; + } + + /* + * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that + * does not have expect_close set. If 'old' is false, close + * one of the new dnum handles. + */ + + for(; dptr; dptr = dptr->prev) { + if ((old && (dptr->dnum < 256) && !dptr->expect_close) || + (!old && (dptr->dnum > 255))) { + dptr_close_internal(dptr); + return; + } + } +} /**************************************************************************** -create a new dir ptr + Create a new dir ptr. If the flag old_handle is true then we must allocate + from the bitmap range 0 - 255 as old SMBsearch directory handles are only + one byte long. If old_handle is false we allocate from the range + 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure + a directory handle is never zero. All the above is folklore taught to + me at Andrew's knee.... :-) :-). JRA. ****************************************************************************/ -int dptr_create(connection_struct *conn,char *path, BOOL expect_close,int pid) + +int dptr_create(connection_struct *conn,char *path, BOOL old_handle, BOOL expect_close,uint16 spid) { - int i; - uint32 old; - int oldi; + dptr_struct *dptr; if (!start_dir(conn,path)) return(-2); /* Code to say use a unix error return code. */ @@ -285,70 +406,103 @@ int dptr_create(connection_struct *conn,char *path, BOOL expect_close,int pid) if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); - for (i=0;idnum = bitmap_find(dptr_bmap, 0); + + if(dptr->dnum == -1 || dptr->dnum > 254) { + + /* + * Try and close the oldest handle not marked for + * expect close in the hope that the client has + * finished with that one. + */ + + dptr_close_oldest(True); + /* Now try again... */ + dptr->dnum = bitmap_find(dptr_bmap, 0); - /* as a 2nd option, grab the oldest not marked for expect_close */ - if (i == -1) { - old=dircounter+1; - oldi= -1; - for (i=0;idnum == -1 || dptr->dnum > 254) { + DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); + free((char *)dptr); + return -1; } - i = oldi; - } + } + } else { + + /* + * This is a new-style trans2 request. Allocate from + * a range that will return 256 - MAX_DIRECTORY_HANDLES. + */ + + dptr->dnum = bitmap_find(dptr_bmap, 255); + + if(dptr->dnum == -1 || dptr->dnum < 255) { - /* a 3rd option - grab the oldest one */ - if (i == -1) { - old=dircounter+1; - oldi= -1; - for (i=0;idnum = bitmap_find(dptr_bmap, 255); + + if(dptr->dnum == -1 || dptr->dnum < 255) { + DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); + free((char *)dptr); + return -1; } - i = oldi; + } } - if (i == -1) { - DEBUG(0,("Error - all dirptrs in use??\n")); - return(-1); - } + bitmap_set(dptr_bmap, dptr->dnum); + + dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ - if (dirptrs[i].valid) - dptr_close(i); + dptr->ptr = conn->dirptr; + string_set(&dptr->path,path); + dptr->conn = conn; + dptr->spid = spid; + dptr->expect_close = expect_close; + dptr->wcard = NULL; /* Only used in lanman2 searches */ + dptr->attr = 0; /* Only used in lanman2 searches */ - dirptrs[i].ptr = conn->dirptr; - string_set(&dirptrs[i].path,path); - dirptrs[i].lastused = dircounter++; - dirptrs[i].finished = False; - dirptrs[i].conn = conn; - dirptrs[i].pid = pid; - dirptrs[i].expect_close = expect_close; - dirptrs[i].wcard = NULL; /* Only used in lanman2 searches */ - dirptrs[i].attr = 0; /* Only used in lanman2 searches */ - dirptrs[i].valid = True; + DLIST_ADD(dirptrs, dptr); DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", - i,path,expect_close)); + dptr->dnum,path,expect_close)); - return(i); + return(dptr->dnum); } #define DPTR_MASK ((uint32)(((uint32)1)<<31)) /**************************************************************************** -fill the 5 byte server reserved dptr field + Fill the 5 byte server reserved dptr field. ****************************************************************************/ + BOOL dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_get(key,0); + void *p = dptr_ptr(key); uint32 offset; if (!p) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -364,20 +518,22 @@ BOOL dptr_fill(char *buf1,unsigned int key) /**************************************************************************** -return True is the offset is at zero + Return True if the offset is at zero. ****************************************************************************/ + BOOL dptr_zero(char *buf) { return((IVAL(buf,1)&~DPTR_MASK) == 0); } /**************************************************************************** -fetch the dir ptr and seek it given the 5 byte server field + Fetch the dir ptr and seek it given the 5 byte server field. ****************************************************************************/ + void *dptr_fetch(char *buf,int *num) { unsigned int key = *(unsigned char *)buf; - void *p = dptr_get(key,dircounter++); + void *p = dptr_ptr(key); uint32 offset; if (!p) { DEBUG(3,("fetched null dirptr %d\n",key)); @@ -392,11 +548,12 @@ void *dptr_fetch(char *buf,int *num) } /**************************************************************************** -fetch the dir ptr. + Fetch the dir ptr. ****************************************************************************/ + void *dptr_fetch_lanman2(int dptr_num) { - void *p = dptr_get(dptr_num,dircounter++); + void *p = dptr_ptr(dptr_num); if (!p) { DEBUG(3,("fetched null dirptr %d\n",dptr_num)); @@ -407,8 +564,9 @@ void *dptr_fetch_lanman2(int dptr_num) } /**************************************************************************** -check a filetype for being valid + Check a filetype for being valid. ****************************************************************************/ + BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype) { if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) @@ -417,8 +575,9 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int di } /**************************************************************************** - get a directory entry + Get an 8.3 directory entry. ****************************************************************************/ + BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) { @@ -437,64 +596,71 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, strequal(conn->dirpath,".") || strequal(conn->dirpath,"/")); - needslash = - ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); + needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); if (!conn->dirptr) return(False); while (!found) - { - dname = ReadDirName(conn->dirptr); + { + BOOL filename_is_mask = False; + dname = ReadDirName(conn->dirptr); - DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n", - (long)conn->dirptr,TellDir(conn->dirptr))); + DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n", + (long)conn->dirptr,TellDir(conn->dirptr))); - if (dname == NULL) - return(False); + if (dname == NULL) + return(False); - pstrcpy(filename,dname); - - if ((strcmp(filename,mask) == 0) || - (name_map_mangle(filename,True,SNUM(conn)) && - mask_match(filename,mask,False,False))) - { - if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) - continue; - - pstrcpy(fname,filename); - *path = 0; - pstrcpy(path,conn->dirpath); - if(needslash) - pstrcat(path,"/"); - pstrcpy(pathreal,path); - pstrcat(path,fname); - pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(dos_to_unix(pathreal, False), &sbuf) != 0) - { - DEBUG(5,("Couldn't stat 1 [%s]\n",path)); - continue; - } - - if (check_descend && - !strequal(fname,".") && !strequal(fname,"..")) - continue; + pstrcpy(filename,dname); + + if ((filename_is_mask = (strcmp(filename,mask) == 0)) || + (name_map_mangle(filename,True,False,SNUM(conn)) && + mask_match(filename,mask,False,False))) + { + if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) + continue; + + pstrcpy(fname,filename); + *path = 0; + pstrcpy(path,conn->dirpath); + if(needslash) + pstrcat(path,"/"); + pstrcpy(pathreal,path); + pstrcat(path,fname); + pstrcat(pathreal,dname); + if (dos_stat(pathreal,&sbuf) != 0) + { + DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); + continue; + } + + if (check_descend && !strequal(fname,".") && !strequal(fname,"..")) + continue; - *mode = dos_mode(conn,pathreal,&sbuf); + *mode = dos_mode(conn,pathreal,&sbuf); + + if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) + { + DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); + continue; + } - if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); - continue; - } + if (!filename_is_mask) + { + /* Now we can allow the mangled cache to be updated */ + pstrcpy(filename,dname); + name_map_mangle(filename,True,True,SNUM(conn)); + } - *size = sbuf.st_size; - *date = sbuf.st_mtime; + *size = sbuf.st_size; + *date = sbuf.st_mtime; - DEBUG(5,("get_dir_entry found %s fname=%s\n",pathreal,fname)); + DEBUG(5,("get_dir_entry found %s fname=%s\n",pathreal,fname)); - found = True; - } + found = True; } + } return(found); } @@ -512,25 +678,26 @@ typedef struct /******************************************************************* -open a directory + Open a directory. ********************************************************************/ + void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - DIR *p = conn->vfs_ops.opendir(name); + DIR *p = dos_opendir(name); int used=0; if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { - conn->vfs_ops.closedir(p); + closedir(p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; - while ((n = vfs_readdirname(conn, p))) + while ((n = dos_readdirname(p))) { int l = strlen(n)+1; @@ -554,14 +721,15 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->numentries++; } - conn->vfs_ops.closedir(p); + closedir(p); return((void *)dirp); } /******************************************************************* -close a directory + Close a directory. ********************************************************************/ + void CloseDir(void *p) { Dir *dirp = (Dir *)p; @@ -571,8 +739,9 @@ void CloseDir(void *p) } /******************************************************************* -read from a directory + Read from a directory. ********************************************************************/ + char *ReadDirName(void *p) { char *ret; @@ -589,8 +758,9 @@ char *ReadDirName(void *p) /******************************************************************* -seek a dir + Seek a dir. ********************************************************************/ + BOOL SeekDir(void *p,int pos) { Dir *dirp = (Dir *)p; @@ -608,8 +778,9 @@ BOOL SeekDir(void *p,int pos) } /******************************************************************* -tell a dir position + Tell a dir position. ********************************************************************/ + int TellDir(void *p) { Dir *dirp = (Dir *)p; diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index e6f1dc7206..27393fe1c6 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -50,7 +50,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode) can always create a file in a read-only directory. */ result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); /* Apply directory mask */ - result &= lp_dir_mode(SNUM(conn)); + result &= lp_dir_mask(SNUM(conn)); /* Add in force bits */ result |= lp_force_dir_mode(SNUM(conn)); } else { @@ -64,7 +64,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode) result |= S_IXOTH; /* Apply mode mask */ - result &= lp_create_mode(SNUM(conn)); + result &= lp_create_mask(SNUM(conn)); /* Add in force bits */ result |= lp_force_create_mode(SNUM(conn)); } @@ -148,7 +148,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * if (!st) { st = &st1; - if (conn->vfs_ops.stat(dos_to_unix(fname,False),st)) return(-1); + if (dos_stat(fname,st)) return(-1); } if (S_ISDIR(st->st_mode)) dosmode |= aDIR; @@ -179,14 +179,12 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * } /* if we previously had any w bits set then leave them alone - if the new mode is not rdonly */ - if (!IS_DOS_READONLY(dosmode) && - (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) { - unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); - unixmode |= tmp; + whilst adding in the new w bits, if the new mode is not rdonly */ + if (!IS_DOS_READONLY(dosmode)) { + unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - return(conn->vfs_ops.chmod(fname,unixmode)); + return(dos_chmod(fname,unixmode)); } @@ -202,7 +200,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(conn->vfs_ops.utime(dos_to_unix(fname, False), times) == 0) + if(dos_utime(fname, times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -217,7 +215,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(conn->vfs_ops.stat(dos_to_unix(fname,False),&sb) != 0) + if(dos_stat(fname,&sb) != 0) return -1; /* Check if we have write access. */ @@ -230,7 +228,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(False); - ret = conn->vfs_ops.utime(dos_to_unix(fname, False), times); + ret = dos_utime(fname, times); unbecome_root(False); } } @@ -251,9 +249,8 @@ BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) if (file_utime(conn, fname, ×)) { DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); + return False; } return(True); } - - diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 1e16627515..8b48a921fd 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -23,6 +23,7 @@ extern int DEBUGLEVEL; +static BOOL setup_write_cache(files_struct *, SMB_OFF_T); /**************************************************************************** seek a file. Try to avoid the seek if possible @@ -36,7 +37,19 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; - seek_ret = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); + seek_ret = sys_lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); + + /* + * We want to maintain the fiction that we can seek + * on a fifo for file system purposes. This allows + * people to set up UNIX fifo's that feed data to Windows + * applications. JRA. + */ + + if((seek_ret == -1) && (errno == ESPIPE)) { + seek_ret = pos+offset; + errno = 0; + } if((seek_ret == -1) || (seek_ret != pos+offset)) { DEBUG(0,("seek_file: sys_lseek failed. Error was %s\n", strerror(errno) )); @@ -52,6 +65,29 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) return(fsp->pos); } +/**************************************************************************** + Read from write cache if we can. +****************************************************************************/ + +static unsigned int cache_read_hits; + +BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) +{ + write_cache *wcp = fsp->wcp; + + if(!wcp) + return False; + + if(n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size) + return False; + + memcpy(data, wcp->data + (pos - wcp->offset), n); + + cache_read_hits++; + + return True; +} + /**************************************************************************** read from a file ****************************************************************************/ @@ -62,7 +98,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #if USE_READ_PREDICTION if (!fsp->can_write) { - ret = read_predict(fsp, fsp->fd_ptr->fd,pos,data,NULL,n); + ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); data += ret; n -= ret; @@ -70,40 +106,64 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) } #endif -#if WITH_MMAP - if (fsp->mmap_ptr) { - SMB_OFF_T num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : 0; - num = MIN(n,num); - if (num > 0) { - memcpy(data,fsp->mmap_ptr+pos,num); - data += num; - pos += num; - n -= num; - ret += num; - } - } -#endif + /* + * Serve from write cache if we can. + */ + if(read_from_write_cache(fsp, data, pos, n)) + return n; + + flush_write_cache(fsp, READ_FLUSH); if (seek_file(fsp,pos) == -1) { DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); return(ret); } - + if (n > 0) { - readret = fsp->conn->vfs_ops.read(fsp->fd_ptr->fd,data,n); + readret = read(fsp->fd_ptr->fd,data,n); if (readret > 0) ret += readret; } return(ret); } +/* Write cache static counters. */ + +static unsigned int abutted_writes; +static unsigned int total_writes; +static unsigned int non_oplock_writes; +static unsigned int direct_writes; +static unsigned int init_writes; +static unsigned int flushed_writes; +static unsigned int num_perfect_writes; +static unsigned int flush_reasons[NUM_FLUSH_REASONS]; + +/* how many write cache buffers have been allocated */ +static unsigned int allocated_write_caches; +static unsigned int num_write_caches; + +/**************************************************************************** + *Really* write to a file +****************************************************************************/ + +static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_t n) +{ + if ((pos != -1) && (seek_file(fsp,pos) == -1)) + return -1; + + return write_data(fsp->fd_ptr->fd,data,n); +} /**************************************************************************** write to a file ****************************************************************************/ -ssize_t write_file(files_struct *fsp,char *data,size_t n) +ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) { + write_cache *wcp = fsp->wcp; + ssize_t total_written = 0; + int write_path = -1; + if (!fsp->can_write) { errno = EPERM; return(0); @@ -112,25 +172,488 @@ ssize_t write_file(files_struct *fsp,char *data,size_t n) if (!fsp->modified) { SMB_STRUCT_STAT st; fsp->modified = True; - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) { + + if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); } + + /* + * If this is the first write and we have an exclusive oplock then setup + * the write cache. + */ + + if ((fsp->oplock_type == EXCLUSIVE_OPLOCK) && !wcp) { + setup_write_cache(fsp, st.st_size); + wcp = fsp->wcp; + } } } - return(vfs_write_data(fsp,data,n)); + total_writes++; + if (!fsp->oplock_type) { + non_oplock_writes++; + } + + /* + * If this file is level II oplocked then we need + * to grab the shared memory lock and inform all + * other files with a level II lock that they need + * to flush their read caches. We keep the lock over + * the shared memory area whilst doing this. + */ + + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; + share_mode_entry *share_list = NULL; + pid_t pid = getpid(); + int token = -1; + int num_share_modes = 0; + int i; + + if (lock_share_entry(fsp->conn, dev, inode, &token) == False) { + DEBUG(0,("write_file: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); + } + + num_share_modes = get_share_modes(fsp->conn, token, dev, inode, &share_list); + + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &share_list[i]; + + /* + * As there could have been multiple writes waiting at the lock_share_entry + * gate we may not be the first to enter. Hence the state of the op_types + * in the share mode entries may be partly NO_OPLOCK and partly LEVEL_II + * oplock. It will do no harm to re-send break messages to those smbd's + * that are still waiting their turn to remove their LEVEL_II state, and + * also no harm to ignore existing NO_OPLOCK states. JRA. + */ + + if (share_entry->op_type == NO_OPLOCK) + continue; + + /* Paranoia .... */ + if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { + DEBUG(0,("write_file: PANIC. share mode entry %d is an exlusive oplock !\n", i )); + abort(); + } + + /* + * Check if this is a file we have open (including the + * file we've been called to do write_file on. If so + * then break it directly without releasing the lock. + */ + + if (pid == share_entry->pid) { + files_struct *new_fsp = file_find_dit(dev, inode, &share_entry->time); + + /* Paranoia check... */ + if(new_fsp == NULL) { + DEBUG(0,("write_file: PANIC. share mode entry %d is not a local file !\n", i )); + abort(); + } + oplock_break_level2(new_fsp, True, token); + + } else { + + /* + * This is a remote file and so we send an asynchronous + * message. + */ + + request_oplock_break(share_entry, dev, inode); + } + } + + free((char *)share_list); + unlock_share_entry(fsp->conn, dev, inode, token); + } + + /* Paranoia check... */ + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + DEBUG(0,("write_file: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name)); + abort(); + } + + if (total_writes % 500 == 0) { + DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u flushes=%u total=%u \ +nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", + init_writes, abutted_writes, flushed_writes, total_writes, non_oplock_writes, + allocated_write_caches, + num_write_caches, direct_writes, num_perfect_writes, cache_read_hits )); + + DEBUG(3,("WRITECACHE: SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", + flush_reasons[SEEK_FLUSH], + flush_reasons[READ_FLUSH], + flush_reasons[WRITE_FLUSH], + flush_reasons[READRAW_FLUSH], + flush_reasons[OPLOCK_RELEASE_FLUSH], + flush_reasons[CLOSE_FLUSH], + flush_reasons[SYNC_FLUSH] )); + } + + if(!wcp) { + direct_writes++; + return real_write_file(fsp, data, pos, n); + } + + DEBUG(9,("write_file(fd=%d pos=%d size=%d) wofs=%d wsize=%d\n", + fsp->fd_ptr->fd, (int)pos, (int)n, (int)wcp->offset, (int)wcp->data_size)); + + /* + * If we have active cache and it isn't contiguous then we flush. + * NOTE: There is a small problem with running out of disk .... + */ + + if (wcp->data_size) { + + BOOL cache_flush_needed = False; + + if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) { + + /* + * Start of write overlaps or abutts the existing data. + */ + + size_t data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), n); + + memcpy(wcp->data + (pos - wcp->offset), data, data_used); + + /* + * Update the current buffer size with the new data. + */ + + if(pos + data_used > wcp->offset + wcp->data_size) + wcp->data_size = pos + data_used - wcp->offset; + + /* + * If we used all the data then + * return here. + */ + + if(n == data_used) + return n; + else + cache_flush_needed = True; + + /* + * Move the start of data forward by the amount used, + * cut down the amount left by the same amount. + */ + + data += data_used; + pos += data_used; + n -= data_used; + + abutted_writes++; + total_written = data_used; + + write_path = 1; + + } else if ((pos < wcp->offset) && (pos + n > wcp->offset) && + (pos + n <= wcp->offset + wcp->alloc_size)) { + + /* + * End of write overlaps the existing data. + */ + + size_t data_used = pos + n - wcp->offset; + + memcpy(wcp->data, data + n - data_used, data_used); + + /* + * Update the current buffer size with the new data. + */ + + if(pos + n > wcp->offset + wcp->data_size) + wcp->data_size = pos + n - wcp->offset; + + /* + * We don't need to move the start of data, but we + * cut down the amount left by the amount used. + */ + + n -= data_used; + + /* + * We cannot have used all the data here. + */ + + cache_flush_needed = True; + + abutted_writes++; + total_written = data_used; + + write_path = 2; + + } else if ( (pos >= wcp->file_size) && + (pos > wcp->offset + wcp->data_size) && + (pos < wcp->offset + wcp->alloc_size) ) { + + /* + * Non-contiguous write part of which fits within + * the cache buffer and is extending the file. + */ + + size_t data_used; + + if(pos + n <= wcp->offset + wcp->alloc_size) + data_used = n; + else + data_used = wcp->offset + wcp->alloc_size - pos; + + /* + * Fill in the non-continuous area with zeros. + */ + + memset(wcp->data + wcp->data_size, '\0', + pos - (wcp->offset + wcp->data_size) ); + + memcpy(wcp->data + (pos - wcp->offset), data, data_used); + + /* + * Update the current buffer size with the new data. + */ + + if(pos + data_used > wcp->offset + wcp->data_size) + wcp->data_size = pos + data_used - wcp->offset; + + /* + * Update the known file length. + */ + + wcp->file_size = wcp->offset + wcp->data_size; + +#if 0 + if (set_filelen(fsp->fd_ptr->fd, wcp->file_size) == -1) { + DEBUG(0,("write_file: error %s in setting file to length %.0f\n", + strerror(errno), (double)wcp->file_size )); + return -1; + } +#endif + + /* + * If we used all the data then + * return here. + */ + + if(n == data_used) + return n; + else + cache_flush_needed = True; + + /* + * Move the start of data forward by the amount used, + * cut down the amount left by the same amount. + */ + + data += data_used; + pos += data_used; + n -= data_used; + + abutted_writes++; + total_written = data_used; + + write_path = 3; + + } else { + + /* + * Write is bigger than buffer, or there is no overlap on the + * low or high ends. + */ + + DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \ +len = %u\n",fsp->fd_ptr->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); + + /* + * Update the file size if needed. + */ + + if(pos + n > wcp->file_size) + wcp->file_size = pos + n; + + /* + * If write would fit in the cache, and is larger than + * the data already in the cache, flush the cache and + * preferentially copy the data new data into it. Otherwise + * just write the data directly. + */ + + if ( n <= wcp->alloc_size && n > wcp->data_size) { + cache_flush_needed = True; + } else { + direct_writes++; + return real_write_file(fsp, data, pos, n); + } + + write_path = 4; + + } + + if(wcp->data_size > wcp->file_size) + wcp->file_size = wcp->data_size; + + if (cache_flush_needed) { + flushed_writes++; + + DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ +n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", + write_path, fsp->fd_ptr->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, + (double)wcp->offset, (unsigned int)wcp->data_size )); + + flush_write_cache(fsp, WRITE_FLUSH); + } + } + + /* + * If the write request is bigger than the cache + * size, write it all out. + */ + + if (n > wcp->alloc_size ) { + if(real_write_file(fsp, data, pos, n) == -1) + return -1; + direct_writes++; + return total_written + n; + } + + /* + * If there's any data left, cache it. + */ + + if (n) { + if (wcp->data_size) { + abutted_writes++; + DEBUG(9,("abutted write (%u)\n", abutted_writes)); + } else { + init_writes++; + } + memcpy(wcp->data+wcp->data_size, data, n); + if (wcp->data_size == 0) { + wcp->offset = pos; + num_write_caches++; + } + wcp->data_size += n; + DEBUG(9,("cache return %u\n", (unsigned int)n)); + total_written += n; + return total_written; /* .... that's a write :) */ + } + + return total_written; } +/**************************************************************************** + Delete the write cache structure. +****************************************************************************/ +void delete_write_cache(files_struct *fsp) +{ + write_cache *wcp; + + if(!fsp) + return; + + if(!(wcp = fsp->wcp)) + return; + + allocated_write_caches--; + + SMB_ASSERT(wcp->data_size == 0); + + free(wcp->data); + free(wcp); + + fsp->wcp = NULL; +} + +/**************************************************************************** + Setup the write cache structure. +****************************************************************************/ + +static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) +{ + ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); + write_cache *wcp; + + if (allocated_write_caches >= MAX_WRITE_CACHES) return False; + + if(alloc_size == 0 || fsp->wcp) + return False; + + if((wcp = (write_cache *)malloc(sizeof(write_cache))) == NULL) { + DEBUG(0,("setup_write_cache: malloc fail.\n")); + return False; + } + + wcp->file_size = file_size; + wcp->offset = 0; + wcp->alloc_size = alloc_size; + wcp->data_size = 0; + if((wcp->data = malloc(wcp->alloc_size)) == NULL) { + DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", + (unsigned int)wcp->alloc_size )); + free(wcp); + return False; + } + + fsp->wcp = wcp; + allocated_write_caches++; + + return True; +} + +/**************************************************************************** + Cope with a size change. +****************************************************************************/ + +void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) +{ + if(fsp->wcp) { + flush_write_cache(fsp, SIZECHANGE_FLUSH); + fsp->wcp->file_size = file_size; + } +} + +/******************************************************************* + Flush a write cache struct to disk. +********************************************************************/ + +ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) +{ + write_cache *wcp = fsp->wcp; + size_t data_size; + + if(!wcp || !wcp->data_size) + return 0; + + data_size = wcp->data_size; + wcp->data_size = 0; + + num_write_caches--; + + flush_reasons[(int)reason]++; + + DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", + fsp->fd_ptr->fd, (double)wcp->offset, (unsigned int)data_size)); + + if(data_size == wcp->alloc_size) + num_perfect_writes++; + + return real_write_file(fsp, wcp->data, wcp->offset, data_size); +} /******************************************************************* sync a file ********************************************************************/ -void sys_sync_file(int fd) +void sync_file(connection_struct *conn, files_struct *fsp) { #ifdef HAVE_FSYNC - fsync(fd); + if(lp_strict_sync(SNUM(conn)) && fsp->fd_ptr != NULL) { + flush_write_cache(fsp, SYNC_FLUSH); + fsync(fsp->fd_ptr->fd); + } #endif } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1d9c5ef754..64f63805f3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,7 +26,6 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; extern fstring remote_machine; -extern pstring global_myname; extern BOOL use_mangled_map; static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); @@ -97,7 +96,12 @@ static int global_stat_cache_hits; void print_stat_cache_statistics(void) { - double eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; + double eff; + + if(global_stat_cache_lookups == 0) + return; + + eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ stat cache was %f%% effective.\n", global_stat_cache_lookups, @@ -230,9 +234,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, - char *dirpath, char **start, - SMB_STRUCT_STAT *pst) +static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -285,7 +287,7 @@ static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, * and then promote it to the top. */ - if(conn->vfs_ops.stat(longest_hit->translated_name, pst) != 0) { + if(dos_stat( longest_hit->translated_name, pst) != 0) { /* * Discard this entry. */ @@ -309,35 +311,6 @@ static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, return (namelen == longest_hit->name_len); } -/**************************************************************************** - this routine converts from the dos and dfs namespace to the unix namespace. -****************************************************************************/ -BOOL unix_dfs_convert(char *name,connection_struct *conn, - char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) -{ - pstring local_path; - - DEBUG(10,("unix_dfs_convert: %s\n", name)); - - if (name != NULL && - under_dfs(conn, name, local_path, sizeof(local_path))) - { - DEBUG(10,("%s is in dfs map.\n", name)); - - /* check for our own name */ - if (StrCaseCmp(global_myname, name+1) > 0) - { - return False; - } - - pstrcpy(name, local_path); - - DEBUG(10,("removed name: %s\n", name)); - } - return unix_convert(name, conn, saved_last_component, bad_path, pst); -} - /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -359,15 +332,14 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ -BOOL unix_convert(char *name,connection_struct *conn, - char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) + +BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; pstring dirpath; pstring orig_path; - int saved_errno; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; #if 0 @@ -443,7 +415,7 @@ BOOL unix_convert(char *name,connection_struct *conn, for (s=name2 ; *s ; s++) if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)mktemp(name2)); + pstrcpy(name,(char *)smbd_mktemp(name2)); } return(True); } @@ -463,7 +435,7 @@ BOOL unix_convert(char *name,connection_struct *conn, pstrcpy(orig_path, name); - if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(stat_cache_lookup( name, dirpath, &start, &st)) { if(pst) *pst = st; return True; @@ -473,7 +445,7 @@ BOOL unix_convert(char *name,connection_struct *conn, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(name,&st) == 0) { + if (dos_stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -481,8 +453,6 @@ BOOL unix_convert(char *name,connection_struct *conn, return(True); } - saved_errno = errno; - DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); @@ -492,7 +462,7 @@ BOOL unix_convert(char *name,connection_struct *conn, */ if (case_sensitive && !is_mangled(name) && - !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) + !lp_strip_dot() && !use_mangled_map) return(False); if(strchr(start,'?') || strchr(start,'*')) @@ -541,8 +511,7 @@ BOOL unix_convert(char *name,connection_struct *conn, /* * Check if the name exists up to this point. */ - - if (conn->vfs_ops.stat(name, &st) == 0) { + if (dos_stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -694,7 +663,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && + if ( (dos_lstat(name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); @@ -758,7 +727,8 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d continue; pstrcpy(name2,dname); - if (!name_map_mangle(name2,False,SNUM(conn))) continue; + if (!name_map_mangle(name2,False,True,SNUM(conn))) + continue; if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 7f4533e7ae..d6203580cf 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -186,10 +186,7 @@ void file_close_conn(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next = fsp->next; if (fsp->conn == conn && fsp->open) { - if (fsp->is_directory) - close_directory(fsp); - else - close_file(fsp,False); + close_file(fsp,False); } } } @@ -226,7 +223,7 @@ open files, %d are available.\n", request_max_open_files, real_max_open_files)); } /* - * Ensure that pipe_handle_offset is set correctly. + * Ensure that pipe_handle_oppset is set correctly. */ set_pipe_handle_offset(real_max_open_files); } @@ -242,10 +239,7 @@ void file_close_user(int vuid) for (fsp=Files;fsp;fsp=next) { next=fsp->next; if ((fsp->vuid == vuid) && fsp->open) { - if(!fsp->is_directory) - close_file(fsp,False); - else - close_directory(fsp); + close_file(fsp,False); } } } @@ -340,13 +334,13 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL) - && lp_strict_sync(SNUM(conn))){ - conn->vfs_ops.sync(fsp->fd_ptr->fd); + if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL)) { + sync_file(conn,fsp); } } } + /**************************************************************************** free up a fd_ptr ****************************************************************************/ diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 0be558848a..4dadfaa939 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -19,4 +19,225 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* this module is retired, it is moved to lib/domain_namemap.c */ +#ifdef USING_GROUPNAME_MAP + +#include "includes.h" +extern int DEBUGLEVEL; +extern DOM_SID global_sam_sid; + + +/************************************************************************** + Groupname map functionality. The code loads a groupname map file and + (currently) loads it into a linked list. This is slow and memory + hungry, but can be changed into a more efficient storage format + if the demands on it become excessive. +***************************************************************************/ + +typedef struct groupname_map { + ubi_slNode next; + + char *windows_name; + DOM_SID windows_sid; + char *unix_name; + gid_t unix_gid; +} groupname_map_entry; + +static ubi_slList groupname_map_list; + +/************************************************************************** + Delete all the entries in the groupname map list. +***************************************************************************/ + +static void delete_groupname_map_list(void) +{ + groupname_map_entry *gmep; + + while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) { + if(gmep->windows_name) + free(gmep->windows_name); + if(gmep->unix_name) + free(gmep->unix_name); + free((char *)gmep); + } +} + +/************************************************************************** + Load a groupname map file. Sets last accessed timestamp. +***************************************************************************/ + +void load_groupname_map(void) +{ + static time_t groupmap_file_last_modified = (time_t)0; + static BOOL initialized = False; + char *groupname_map_file = lp_groupname_map(); + SMB_STRUCT_STAT st; + FILE *fp; + char *s; + pstring buf; + groupname_map_entry *new_ep; + + if(!initialized) { + ubi_slInitList( &groupname_map_list ); + initialized = True; + } + + if (!*groupname_map_file) + return; + + if(sys_stat(groupname_map_file, &st) != 0) { + DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n", + groupname_map_file, strerror(errno) )); + return; + } + + /* + * Check if file has changed. + */ + if( st.st_mtime <= groupmap_file_last_modified) + return; + + groupmap_file_last_modified = st.st_mtime; + + /* + * Load the file. + */ + + fp = sys_fopen(groupname_map_file,"r"); + if (!fp) { + DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n", + groupname_map_file, strerror(errno))); + return; + } + + /* + * Throw away any previous list. + */ + delete_groupname_map_list(); + + DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file)); + + while((s=fgets_slash(buf,sizeof(buf),fp))!=NULL) { + pstring unixname; + pstring windows_name; + struct group *gptr; + DOM_SID tmp_sid; + + DEBUG(10,("load_groupname_map: Read line |%s|\n", s)); + + if (!*s || strchr("#;",*s)) + continue; + + if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) + continue; + + if(!next_token(&s,windows_name, "\t\n\r=", sizeof(windows_name))) + continue; + + trim_string(unixname, " ", " "); + trim_string(windows_name, " ", " "); + + if (!*windows_name) + continue; + + if(!*unixname) + continue; + + DEBUG(5,("load_groupname_map: unixname = %s, windowsname = %s.\n", + unixname, windows_name)); + + /* + * Attempt to get the unix gid_t for this name. + */ + + if((gptr = (struct group *)getgrnam(unixname)) == NULL) { + DEBUG(0,("load_groupname_map: getgrnam for group %s failed.\ +Error was %s.\n", unixname, strerror(errno) )); + continue; + } + + /* + * Now map to an NT SID. + */ + + if(!lookup_wellknown_sid_from_name(windows_name, &tmp_sid)) { + /* + * It's not a well known name, convert the UNIX gid_t + * to a rid within this domain SID. + */ + tmp_sid = global_sam_sid; + tmp_sid.sub_auths[tmp_sid.num_auths++] = + pdb_gid_to_group_rid((gid_t)gptr->gr_gid); + } + + /* + * Create the list entry and add it onto the list. + */ + + if((new_ep = (groupname_map_entry *)malloc( sizeof(groupname_map_entry) ))== NULL) { + DEBUG(0,("load_groupname_map: malloc fail for groupname_map_entry.\n")); + fclose(fp); + return; + } + + new_ep->unix_gid = gptr->gr_gid; + new_ep->windows_sid = tmp_sid; + new_ep->windows_name = strdup( windows_name ); + new_ep->unix_name = strdup( unixname ); + + if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) { + DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n")); + fclose(fp); + if(new_ep->windows_name != NULL) + free(new_ep->windows_name); + if(new_ep->unix_name != NULL) + free(new_ep->unix_name); + free((char *)new_ep); + return; + } + memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) ); + + ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep); + } + + DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n", + ubi_slCount(&groupname_map_list))); + + fclose(fp); +} + +/*********************************************************** + Lookup a SID entry by gid_t. +************************************************************/ + +void map_gid_to_sid( gid_t gid, DOM_SID *psid) +{ + groupname_map_entry *gmep; + + /* + * Initialize and load if not already loaded. + */ + load_groupname_map(); + + for( gmep = (groupname_map_entry *)ubi_slFirst( &groupname_map_list); + gmep; gmep = (groupname_map_entry *)ubi_slNext( gmep )) { + + if( gmep->unix_gid == gid) { + *psid = gmep->windows_sid; + DEBUG(7,("map_gid_to_sid: Mapping unix group %s to windows group %s.\n", + gmep->unix_name, gmep->windows_name )); + return; + } + } + + /* + * If there's no map, convert the UNIX gid_t + * to a rid within this domain SID. + */ + *psid = global_sam_sid; + psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid); + + return; +} +#else /* USING_GROUPNAME_MAP */ + void load_groupname_map(void) {;} +#endif /* USING_GROUPNAME_MAP */ diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index eeb367bcb5..4e9418fa94 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -61,7 +61,6 @@ extern fstring global_myworkgroup; extern int Client; extern int smb_read_error; -extern uint32 global_client_caps; static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, @@ -82,7 +81,7 @@ static int CopyExpanded(connection_struct *conn, if (!src || !dst || !n || !(*dst)) return(0); StrnCpy(buf,src,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); + pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub(conn,buf); StrnCpy(*dst,buf,*n); l = strlen(*dst) + 1; @@ -95,7 +94,7 @@ static int CopyAndAdvance(char** dst, char* src, int* n) { int l; if (!src || !dst || !n || !(*dst)) return(0); - StrnCpy(*dst,src,*n); + StrnCpy(*dst,src,*n-1); l = strlen(*dst) + 1; (*dst) += l; (*n) -= l; @@ -107,7 +106,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char* s) pstring buf; if (!s) return(0); StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); + pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub(conn,buf); return strlen(buf) + 1; } @@ -117,7 +116,7 @@ static char* Expand(connection_struct *conn, int snum, char* s) static pstring buf; if (!s) return(NULL); StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); + pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub(conn,buf); return &buf[0]; } @@ -139,70 +138,69 @@ static BOOL prefix_ok(char *str,char *prefix) cause of some of the ipc problems being experienced. lkcl26dec97 ******************************************************************/ + static void copy_trans_params_and_data(char *outbuf, int align, - struct mem_buf *rparam, struct mem_buf *rdata, - int param_offset, int data_offset, - int param_len, int data_len) + char *rparam, int param_offset, int param_len, + char *rdata, int data_offset, int data_len) { char *copy_into = smb_buf(outbuf)+1; + if(param_len < 0) + param_len = 0; + + if(data_len < 0) + data_len = 0; + DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", param_offset, param_offset + param_len, data_offset , data_offset + data_len)); - if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len); + if (param_len) + memcpy(copy_into, &rparam[param_offset], param_len); + copy_into += param_len + align; - if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len); + + if (data_len ) + memcpy(copy_into, &rdata[data_offset], data_len); } /**************************************************************************** - send a trans reply - ****************************************************************************/ + Send a trans reply. + ****************************************************************************/ + static void send_trans_reply(char *outbuf, - struct mem_buf *rdata, - struct mem_buf *rparam, - uint16 *setup, int lsetup, int max_data_ret) + char *rparam, int rparam_len, + char *rdata, int rdata_len, + BOOL buffer_too_large) { - int i; int this_ldata,this_lparam; - int tot_data=0,tot_param=0; + int tot_data_sent = 0; + int tot_param_sent = 0; int align; - int ldata = rdata ? mem_buf_len(rdata ) : 0; - int lparam = rparam ? mem_buf_len(rparam) : 0; - - BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False; + int ldata = rdata ? rdata_len : 0; + int lparam = rparam ? rparam_len : 0; if (buffer_too_large) - { - DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret)); - ldata = max_data_ret; - } + DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata )); - this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); + this_lparam = MIN(lparam,max_send - 500); /* hack */ + this_ldata = MIN(ldata,max_send - (500+this_lparam)); align = ((this_lparam)%4); - set_message(outbuf,10+lsetup,1+align+this_ldata+this_lparam,True); + set_message(outbuf,10,1+align+this_ldata+this_lparam,True); if (buffer_too_large) { - if (global_client_caps & CAP_STATUS32) - { - /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ - SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - SIVAL(outbuf, smb_rcls, 0x80000005); /* STATUS_BUFFER_OVERFLOW */ - } else { - SCVAL(outbuf, smb_rcls, ERRDOS); - SSVAL(outbuf, smb_err, ERRmoredata); - } + /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ + SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); } copy_trans_params_and_data(outbuf, align, - rparam , rdata, - tot_param , tot_data, - this_lparam, this_ldata); + rparam, tot_param_sent, this_lparam, + rdata, tot_data_sent, this_ldata); SSVAL(outbuf,smb_vwv0,lparam); SSVAL(outbuf,smb_vwv1,ldata); @@ -212,46 +210,46 @@ static void send_trans_reply(char *outbuf, SSVAL(outbuf,smb_vwv6,this_ldata); SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,lsetup); - - for (i=0;icurpos) return(0); + if (!p->curpos) { + va_end(args); + return(0); + } switch( *p->curpos++ ) { case 'W': /* word (2 byte) */ @@ -400,7 +401,7 @@ va_dcl needed = get_counter(&p->curpos); { char *s = va_arg(args,char*); - if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed); + if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1); } break; case 'z': /* offset to zero terminated string (4 byte) */ @@ -656,7 +657,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, return; } - bzero(p, 8192*sizeof(char)); + memset(p, '\0',8192*sizeof(char)); q=p; /* lookup the long printer driver name in the file description */ @@ -809,8 +810,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, print_queue_struct *queue=NULL; print_status_struct status; - bzero(&status,sizeof(status)); - bzero(&desc,sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); + memset((char *)&desc,'\0',sizeof(desc)); p = skip_string(p,1); uLevel = SVAL(p,0); @@ -823,7 +824,20 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, /* check it's a supported varient */ if (!prefix_ok(str1,"zWrLh")) return False; - if (!check_printq_info(&desc,uLevel,str2,str3)) return False; + if (!check_printq_info(&desc,uLevel,str2,str3)) { + /* + * Patch from Scott Moomaw + * to return the 'invalid info level' error if an + * unknown level was requested. + */ + *rdata_len = 0; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,ERROR_INVALID_LEVEL); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,0); + return(True); + } snum = lp_servicenumber(QueueName); if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { @@ -908,13 +922,26 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, int* subcntarr = NULL; int queuecnt, subcnt=0, succnt=0; - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); if (!prefix_ok(param_format,"WrLeh")) return False; - if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) - return False; + if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) { + /* + * Patch from Scott Moomaw + * to return the 'invalid info level' error if an + * unknown level was requested. + */ + *rdata_len = 0; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,ERROR_INVALID_LEVEL); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,0); + return(True); + } + queuecnt = 0; for (i = 0; i < services; i++) if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) @@ -1057,7 +1084,7 @@ static int get_server_info(uint32 servertype, (*servers) = (struct srv_info_struct *) Realloc(*servers,sizeof(**servers)*alloced); if (!(*servers)) return(0); - bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count)); + memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); } s = &(*servers)[count]; @@ -1297,7 +1324,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param *rdata_len = fixed_len + string_len; *rdata = REALLOC(*rdata,*rdata_len); - bzero(*rdata,*rdata_len); + memset(*rdata,'\0',*rdata_len); p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ p = *rdata; @@ -1355,7 +1382,6 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa if (!prefix_ok(str1,"zWrLeh")) return False; *rdata_len = 0; - *rdata = NULL; *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); @@ -1650,6 +1676,8 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param p = skip_string(p,1); + memset(pass1,'\0',sizeof(pass1)); + memset(pass2,'\0',sizeof(pass2)); memcpy(pass1,p,16); memcpy(pass2,p+16,16); @@ -1680,7 +1708,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param * Older versions of Windows seem to do this. */ - if (password_ok(user, pass1,strlen(pass1),NULL, NULL) && + if (password_ok(user, pass1,strlen(pass1),NULL) && chgpasswd(user,pass1,pass2,False)) { SSVAL(*rparam,0,NERR_Success); @@ -1703,8 +1731,8 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param } } - bzero(pass1,sizeof(fstring)); - bzero(pass2,sizeof(fstring)); + memset((char *)pass1,'\0',sizeof(fstring)); + memset((char *)pass2,'\0',sizeof(fstring)); return(True); } @@ -2005,7 +2033,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha !become_service(fconn,True)) break; - if (conn->vfs_ops.rename(dos_to_unix(fsp->fsp_name,False),name) == 0) { + if (dos_rename(fsp->fsp_name,name) == 0) { string_set(&fsp->fsp_name,name); } break; @@ -2091,7 +2119,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par pstring comment; uint32 servertype= lp_default_server_announce(); - pstrcpy(comment,lp_serverstring()); + pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) { for (i=0;iadmin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - pstrcpy(p2,lp_logon_path()); + pstrcpy(p2,lp_logon_home()); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; SSVAL(p,52,0); /* flags */ - SIVAL(p,54,0); /* script_path */ + SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ + pstrcpy(p2,lp_logon_script()); + standard_sub( conn, p2 ); + p2 = skip_string(p2,1); if (uLevel == 2) { SIVAL(p,60,0); /* auth_flags */ @@ -2590,12 +2621,11 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param int uLevel; struct pack_desc desc; char* name; - char* logon_script; uLevel = SVAL(p,0); name = p + 2; - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); @@ -2636,9 +2666,12 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param /* JHT - By calling lp_logon_script() and standard_sub() we have */ /* made sure all macros are fully substituted and available */ - logon_script = lp_logon_script(); - standard_sub( conn, logon_script ); - PACKS(&desc,"z", logon_script); /* script path */ + { + pstring logon_script; + pstrcpy(logon_script,lp_logon_script()); + standard_sub( conn, logon_script ); + PACKS(&desc,"z", logon_script); /* script path */ + } /* End of JHT mods */ PACKI(&desc,"D",0x00000000); /* reserved */ @@ -2706,8 +2739,8 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para uLevel = SVAL(p,2); - bzero(&desc,sizeof(desc)); - bzero(&status,sizeof(status)); + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0))); @@ -2767,8 +2800,8 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa print_queue_struct *queue=NULL; print_status_struct status; - bzero(&desc,sizeof(desc)); - bzero(&status,sizeof(status)); + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); p = skip_string(p,1); uLevel = SVAL(p,0); @@ -2880,7 +2913,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par struct pack_desc desc; int snum; - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); p = skip_string(p,1); uLevel = SVAL(p,0); @@ -2939,7 +2972,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, struct pack_desc desc; int services = lp_numservices(); - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); uLevel = SVAL(p,0); @@ -2994,7 +3027,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para int succnt; struct pack_desc desc; - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); uLevel = SVAL(p,0); @@ -3038,7 +3071,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param int succnt; struct pack_desc desc; - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); uLevel = SVAL(p,0); @@ -3083,7 +3116,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, int succnt; struct pack_desc desc; - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); uLevel = SVAL(p,0); @@ -3094,7 +3127,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - bzero(&desc,sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); desc.base = *rdata; desc.buflen = mdrcnt; desc.format = str2; @@ -3117,35 +3150,48 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, return(True); } -static void api_rpc_trans_reply(char *outbuf, - pipes_struct *p) +/**************************************************************************** + Start the first part of an RPC reply which began with an SMBtrans request. +****************************************************************************/ + +static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) { - send_trans_reply(outbuf, p->rsmb_pdu.data, NULL, NULL, 0, p->file_offset); + char *rdata = malloc(p->max_trans_reply); + int data_len; - if (mem_buf_len(p->rsmb_pdu.data) <= p->file_offset) - { - /* all of data was sent: no need to wait for SMBreadX calls */ - mem_free_data(p->rsmb_pdu.data); + if(rdata == NULL) { + DEBUG(0,("api_rpc_trans_reply: malloc fail.\n")); + return False; } + + if((data_len = read_from_pipe( p, rdata, p->max_trans_reply)) < 0) { + free(rdata); + return False; + } + + send_trans_reply(outbuf, NULL, 0, rdata, data_len, (int)prs_offset(&p->rdata) > data_len); + + free(rdata); + return True; } /**************************************************************************** WaitNamedPipeHandleState ****************************************************************************/ -static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param) + +static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len) { uint16 priority; - if (!param) return False; + if (!param || param_len < 2) + return False; - priority = param[0] + (param[1] << 8); + priority = SVAL(param,0); DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority)); - if (wait_rpc_pipe_hnd_state(p, priority)) - { + if (wait_rpc_pipe_hnd_state(p, priority)) { /* now send the reply */ - send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset); - + send_trans_reply(outbuf, NULL, 0, NULL, 0, False); return True; } return False; @@ -3155,20 +3201,20 @@ static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param) /**************************************************************************** SetNamedPipeHandleState ****************************************************************************/ -static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) + +static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param, int param_len) { uint16 id; - if (!param) return False; + if (!param || param_len < 2) + return False; - id = param[0] + (param[1] << 8); + id = SVAL(param,0); DEBUG(4,("SetNamedPipeHandleState to code %x\n", id)); - if (set_rpc_pipe_hnd_state(p, id)) - { + if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset); - + send_trans_reply(outbuf, NULL, 0, NULL, 0, False); return True; } return False; @@ -3176,111 +3222,93 @@ static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) /**************************************************************************** - when no reply is generated, indicate unsupported. + When no reply is generated, indicate unsupported. ****************************************************************************/ + static BOOL api_no_reply(char *outbuf, int max_rdata_len) { - struct mem_buf rparam; - - mem_init(&rparam, 0); - mem_alloc_data(&rparam, 4); - - rparam.offset.start = 0; - rparam.offset.end = 4; + char rparam[4]; /* unsupported */ - SSVAL(rparam.data,0,NERR_notsupported); - SSVAL(rparam.data,2,0); /* converter word */ + SSVAL(rparam,0,NERR_notsupported); + SSVAL(rparam,2,0); /* converter word */ DEBUG(3,("Unsupported API fd command\n")); /* now send the reply */ - send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len); - - mem_free_data(&rparam); + send_trans_reply(outbuf, rparam, 4, NULL, 0, False); - return(-1); + return -1; } /**************************************************************************** - handle remote api calls delivered to a named pipe already opened. - ****************************************************************************/ + Handle remote api calls delivered to a named pipe already opened. + ****************************************************************************/ + static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, uint16 *setup,char *data,char *params, int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { - BOOL reply = False; - - uint16 pnum; - uint16 subcommand; + BOOL reply = False; pipes_struct *p = NULL; + int pnum; + int subcommand; DEBUG(5,("api_fd_reply\n")); /* First find out the name of this file. */ - if (suwcnt != 2) - { + if (suwcnt != 2) { DEBUG(0,("Unexpected named pipe transaction.\n")); return(-1); } /* Get the file handle and hence the file name. */ - pnum = setup[1]; - subcommand = setup[0]; - p = get_rpc_pipe(pnum); + /* + * NB. The setup array has already been transformed + * via SVAL and so is in gost byte order. + */ + pnum = ((int)setup[1]) & 0xFFFF; + subcommand = ((int)setup[0]) & 0xFFFF; - if (p != NULL) - { - DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", - subcommand, p->name, pnum)); + if(!(p = get_rpc_pipe(pnum))) { + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); + return api_no_reply(outbuf, mdrcnt); + } - /* record maximum data length that can be transmitted in an SMBtrans */ - p->file_offset = mdrcnt; - p->prev_pdu_file_offset = 0; + DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum)); - DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n", - p, p->file_offset)); + /* record maximum data length that can be transmitted in an SMBtrans */ + p->max_trans_reply = mdrcnt; - switch (subcommand) - { - case 0x26: - { - reply = rpc_to_smb(p, data, tdscnt); - if (reply) - { - api_rpc_trans_reply(outbuf, p); - } - break; - } - case 0x53: - { - /* Wait Named Pipe Handle state */ - reply = api_WNPHS(outbuf, p, params); - break; - } - case 0x01: - { - /* Set Named Pipe Handle state */ - reply = api_SNPHS(outbuf, p, params); - break; - } - } - } - else - { - DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); + DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply)); + + switch (subcommand) { + case 0x26: + /* dce/rpc command */ + reply = rpc_command(p, data, tdscnt); + if (reply) + reply = api_rpc_trans_reply(outbuf, p); + break; + case 0x53: + /* Wait Named Pipe Handle state */ + reply = api_WNPHS(outbuf, p, params, tpscnt); + break; + case 0x01: + /* Set Named Pipe Handle state */ + reply = api_SNPHS(outbuf, p, params, tpscnt); + break; } if (!reply) - { return api_no_reply(outbuf, mdrcnt); - } + return -1; } /**************************************************************************** - the buffer was too small - ****************************************************************************/ + The buffer was too small + ****************************************************************************/ + static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -3300,8 +3328,9 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char * /**************************************************************************** - the request is not supported - ****************************************************************************/ + The request is not supported + ****************************************************************************/ + static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -3364,14 +3393,13 @@ struct /**************************************************************************** - handle remote api calls - ****************************************************************************/ + Handle remote api calls + ****************************************************************************/ + static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { int api_command; - struct mem_buf rdata_buf; - struct mem_buf rparam_buf; char *rdata = NULL; char *rparam = NULL; int rdata_len = 0; @@ -3379,7 +3407,10 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data BOOL reply=False; int i; - SMB_ASSERT(params != 0); + if (!params) { + DEBUG(0,("ERROR: NULL params in api_reply()\n")); + return 0; + } api_command = SVAL(params,0); @@ -3389,15 +3420,20 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data skip_string(params+2,1), tdscnt,tpscnt,mdrcnt,mprcnt)); - for (i=0;api_commands[i].name;i++) - if (api_commands[i].id == api_command && api_commands[i].fn) - { + for (i=0;api_commands[i].name;i++) { + if (api_commands[i].id == api_command && api_commands[i].fn) { DEBUG(3,("Doing %s\n",api_commands[i].name)); break; - } + } + } - rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); - rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); + rdata = (char *)malloc(1024); + if (rdata) + memset(rdata,'\0',1024); + + rparam = (char *)malloc(1024); + if (rparam) + memset(rparam,'\0',1024); if(!rdata || !rparam) { DEBUG(0,("api_reply: malloc fail !\n")); @@ -3409,29 +3445,24 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data if (rdata_len > mdrcnt || - rparam_len > mprcnt) - { + rparam_len > mprcnt) { reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); - } - + } /* if we get False back then it's actually unsupported */ if (!reply) api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); - - mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False); - mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False); - - /* now send the reply */ - send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0); + send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); - if (rdata ) free(rdata); - if (rparam) free(rparam); + if (rdata ) + free(rdata); + if (rparam) + free(rparam); - return(-1); + return -1; } /**************************************************************************** @@ -3445,9 +3476,7 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na DEBUG(3,("named pipe command on <%s> name\n", name)); if (strequal(name,"LANMAN")) - { return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt); - } if (strequal(name,"WKSSVC") || strequal(name,"SRVSVC") || @@ -3460,26 +3489,23 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na } if (strlen(name) < 1) - { return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); - } if (setup) - { DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1])); - } return 0; } /**************************************************************************** - reply to a SMBtrans - ****************************************************************************/ + Reply to a SMBtrans. + ****************************************************************************/ + int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize) { fstring name; - int name_offset = 0; + int name_offset = 0; char *data=NULL,*params=NULL; uint16 *setup=NULL; int outsize = 0; @@ -3497,7 +3523,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int int dsoff = SVAL(inbuf,smb_vwv12); int suwcnt = CVAL(inbuf,smb_vwv13); - bzero(name, sizeof(name)); + memset(name, '\0',sizeof(name)); fstrcpy(name,smb_buf(inbuf)); if (dscnt > tdscnt || pscnt > tpscnt) { @@ -3523,7 +3549,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (suwcnt) { int i; if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { - DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16))); + DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16)))); return(ERROR(ERRDOS,ERRnomem)); } for (i=0;i data=%d params=%d setup=%d\n", name,tdscnt,tpscnt,suwcnt)); - /* - * WinCE wierdness.... - */ + /* + * WinCE wierdness.... + */ - if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, - strlen(local_machine)) == 0)) { - name_offset = strlen(local_machine)+1; - } + if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) && + (name[strlen(local_machine)+1] == '\\')) + name_offset = strlen(local_machine)+1; if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) { DEBUG(5,("calling named_pipe\n")); @@ -3609,9 +3637,12 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } - if (data) free(data); - if (params) free(params); - if (setup) free(setup); + if (data) + free(data); + if (params) + free(params); + if (setup) + free(setup); if (close_on_completion) close_cnum(conn,vuid); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index b829746a32..48e16e5332 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -63,11 +63,13 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ * global. There is a call to lp_magicchar() in server.c * that is used to override the initial value. * - * basechars - The set of 36 characters used for name mangling. This + * MANGLE_BASE - This is the number of characters we use for name mangling. + * + * basechars - The set characters used for name mangling. This * is static (scope is this file only). * - * base36() - Macro used to select a character from basechars (i.e., - * base36(n) will return the nth digit, modulo 36). + * mangle() - Macro used to select a character from basechars (i.e., + * mangle(n) will return the nth digit, modulo MANGLE_BASE). * * chartest - array 0..255. The index range is the set of all possible * values of a byte. For each byte value, the content is a @@ -110,12 +112,13 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ char magic_char = '~'; -static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; +#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) static unsigned char chartest[256] = { 0 }; static BOOL ct_initialized = False; -#define base36(V) ((char)(basechars[(V) % 36])) +#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) #define BASECHAR_MASK 0xf0 #define ILLEGAL_MASK 0x0f #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) @@ -148,7 +151,7 @@ static void init_chartest( void ) char *illegalchars = "*\\/?<>|\":"; unsigned char *s; - bzero( (char *)chartest, 256 ); + memset( (char *)chartest, '\0', 256 ); for( s = (unsigned char *)illegalchars; *s; s++ ) chartest[*s] = ILLEGAL_MASK; @@ -514,7 +517,7 @@ void reset_mangled_cache( void ) * * If the extension of the raw name maps directly to the * extension of the mangled name, then we'll store both names - * *without* extensions. That way, we can provide consistant + * *without* extensions. That way, we can provide consistent * reverse mangling for all names that match. The test here is * a bit more careful than the one done in earlier versions of * mangle.c: @@ -533,9 +536,9 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) ubi_cacheEntryPtr new_entry; char *s1; char *s2; - int mangled_len; - int raw_len; - int i; + size_t mangled_len; + size_t raw_len; + size_t i; /* If the cache isn't initialized, give up. */ if( !mc_initialized ) @@ -561,7 +564,7 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) } } - /* Allocate a new cache entry. If the allcoation fails, just return. */ + /* Allocate a new cache entry. If the allocation fails, just return. */ i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; new_entry = malloc( i ); if( !new_entry ) @@ -589,11 +592,13 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) * * ************************************************************************** ** */ + BOOL check_mangled_cache( char *s ) - { +{ ubi_cacheEntryPtr FoundPtr; char *ext_start = NULL; char *found_name; + char *saved_ext = NULL; /* If the cache isn't initialized, give up. */ if( !mc_initialized ) @@ -603,19 +608,34 @@ BOOL check_mangled_cache( char *s ) /* If we didn't find the name *with* the extension, try without. */ if( !FoundPtr ) - { + { ext_start = strrchr( s, '.' ); if( ext_start ) - { + { + if((saved_ext = strdup(ext_start)) == NULL) + return False; + *ext_start = '\0'; FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - *ext_start = '.'; - } + /* + * At this point s is the name without the + * extension. We re-add the extension if saved_ext + * is not null, before freeing saved_ext. + */ } + } /* Okay, if we haven't found it we're done. */ if( !FoundPtr ) + { + if(saved_ext) + { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + free(saved_ext); + } return( False ); + } /* If we *did* find it, we need to copy it into the string buffer. */ found_name = (char *)(FoundPtr + 1); @@ -624,13 +644,17 @@ BOOL check_mangled_cache( char *s ) DEBUG( 3, ("Found %s on mangled stack ", s) ); (void)pstrcpy( s, found_name ); - if( ext_start ) - (void)pstrcat( s, ext_start ); + if( saved_ext ) + { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + free(saved_ext); + } DEBUG( 3, ("as %s\n", s) ); return( True ); - } /* check_mangled_cache */ +} /* check_mangled_cache */ /* ************************************************************************** ** @@ -652,6 +676,12 @@ static char *map_filename( char *s, /* This is null terminated */ pstrcpy( matching_bit, "" ); /* Match but no star gets this. */ pp = pat; /* Initialize the pointers. */ sp = s; + + if( strequal(s, ".") || strequal(s, "..")) + { + return NULL; /* Do not map '.' and '..' */ + } + if( (len == 1) && (*pattern == '*') ) { return NULL; /* Impossible, too ambiguous for */ @@ -807,7 +837,7 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) */ void mangle_name_83( char *s) { - int csum = str_checksum(s); + int csum; char *p; char extension[4]; char base[9]; @@ -829,7 +859,11 @@ void mangle_name_83( char *s) csum = str_checksum( s ); *p = '.'; } + else + csum = str_checksum(s); } + else + csum = str_checksum(s); strupper( s ); @@ -855,7 +889,7 @@ void mangle_name_83( char *s) } else { - extension[extlen++] = base36( (unsigned char)*p ); + extension[extlen++] = mangle( (unsigned char)*p ); } p += 2; break; @@ -889,7 +923,7 @@ void mangle_name_83( char *s) } else { - base[baselen++] = base36( (unsigned char)*p ); + base[baselen++] = mangle( (unsigned char)*p ); } p += 2; break; @@ -906,10 +940,10 @@ void mangle_name_83( char *s) } base[baselen] = 0; - csum = csum % (36*36); + csum = csum % (MANGLE_BASE*MANGLE_BASE); (void)slprintf(s, 12, "%s%c%c%c", - base, magic_char, base36( csum/36 ), base36( csum ) ); + base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); if( *extension ) { @@ -935,6 +969,11 @@ void mangle_name_83( char *s) * signal that a client does not require name mangling, * thus skipping the name mangling even on shares which * have name-mangling turned on. + * cache83 - If False, the mangled name cache will not be updated. + * This is usually used to prevent that we overwrite + * a conflicting cache entry prematurely, i.e. before + * we know whether the client is really interested in the + * current name. (See PR#13758). UKD. * snum - Share number. This identifies the share in which the * name exists. * @@ -943,11 +982,11 @@ void mangle_name_83( char *s) * * **************************************************************************** */ -BOOL name_map_mangle(char *OutName, BOOL need83, int snum) +BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) { char *map; - DEBUG(5,("name_map_mangle( %s, %s, %d )\n", - OutName, need83?"TRUE":"FALSE", snum)); + DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s, %d )\n", OutName, + need83 ? "TRUE" : "FALSE", cache83 ? "TRUE" : "FALSE", snum)); #ifdef MANGLE_LONG_FILENAMES if( !need83 && is_illegal_name(OutName) ) @@ -963,17 +1002,19 @@ BOOL name_map_mangle(char *OutName, BOOL need83, int snum) /* check if it's already in 8.3 format */ if (need83 && !is_8_3(OutName, True)) { - char *tmp; + char *tmp = NULL; if (!lp_manglednames(snum)) { return(False); } /* mangle it into 8.3 */ - tmp = strdup(OutName); + if (cache83) + tmp = strdup(OutName); + mangle_name_83(OutName); - if(tmp) { + if(tmp != NULL) { cache_mangled_name(OutName, tmp); free(tmp); } diff --git a/source3/smbd/message.c b/source3/smbd/message.c index d13dfda1e0..2f94bdf111 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -54,7 +54,7 @@ static void msg_deliver(void) /* put it in a temporary file */ slprintf(s,sizeof(s)-1, "%s/msg.XXXXXX",tmpdir()); - fstrcpy(name,(char *)mktemp(s)); + fstrcpy(name,(char *)smbd_mktemp(s)); fd = sys_open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); if (fd == -1) { @@ -74,10 +74,13 @@ static void msg_deliver(void) /* run the command */ if (*lp_msg_command()) { + fstring alpha_msgfrom; + fstring alpha_msgto; + pstrcpy(s,lp_msg_command()); - string_sub(s,"%s",name); - string_sub(s,"%f",msgfrom); - string_sub(s,"%t",msgto); + pstring_sub(s,"%s",name); + pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,sizeof(alpha_msgfrom))); + pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,sizeof(alpha_msgto))); standard_sub_basic(s); smbrun(s,NULL,False); } @@ -99,7 +102,6 @@ int reply_sends(connection_struct *conn, msgpos = 0; - if (! (*lp_msg_command())) return(ERROR(ERRSRV,ERRmsgoff)); @@ -113,7 +115,9 @@ int reply_sends(connection_struct *conn, fstrcpy(msgto,dest); len = SVAL(msg,0); - len = MIN(len,1600-msgpos); + len = MIN(len,sizeof(msgbuf)-msgpos); + + memset(msgbuf,'\0',sizeof(msgbuf)); memcpy(&msgbuf[msgpos],msg+2,len); msgpos += len; @@ -140,6 +144,7 @@ int reply_sendstrt(connection_struct *conn, outsize = set_message(outbuf,1,0,True); + memset(msgbuf,'\0',sizeof(msgbuf)); msgpos = 0; orig = smb_buf(inbuf)+1; @@ -172,7 +177,7 @@ int reply_sendtxt(connection_struct *conn, msg = smb_buf(inbuf) + 1; len = SVAL(msg,0); - len = MIN(len,1600-msgpos); + len = MIN(len,sizeof(msgbuf)-msgpos); memcpy(&msgbuf[msgpos],msg+2,len); msgpos += len; @@ -202,4 +207,3 @@ int reply_sendend(connection_struct *conn, return(outsize); } - diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 0b48b0e2b2..b2366b0a37 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -26,8 +26,6 @@ extern int Protocol; extern int max_recv; extern fstring global_myworkgroup; extern fstring remote_machine; -extern pstring myhostname; -extern dfs_internal dfs_struct; /**************************************************************************** reply for the core protocol @@ -160,6 +158,16 @@ reply for the nt protocol static int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| + (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | + (SMB_OFF_T_BITS == 64 ? CAP_LARGE_FILES : 0); + + +/* + other valid capabilities which we may support at some time... + CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; + */ + int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); @@ -168,32 +176,9 @@ static int reply_nt1(char *outbuf) char cryptkey[8]; char crypt_len = 0; - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ; - - if (lp_nt_smb_support()) - { - capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS; - } - - if (SMB_OFF_T_BITS == 64) - { - capabilities |= CAP_LARGE_FILES; - } - - if (dfs_struct.ready==True) - { - capabilities |= CAP_DFS; - } - -/* - other valid capabilities which we may support at some time... - CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; - */ - - if (lp_security() == SEC_SERVER) - { - cli = server_cryptkey(); - } + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } if (cli) { DEBUG(3,("using password server validation\n")); @@ -218,13 +203,12 @@ static int reply_nt1(char *outbuf) if (doencrypt) secword |= 2; /* decide where (if) to put the encryption challenge, and - follow it with the OEM'd domain name in Unicode. + follow it with the OEM'd domain name */ - data_len = crypt_len + (strlen(global_myworkgroup)+1)*2; + data_len = crypt_len + strlen(global_myworkgroup) + 1; set_message(outbuf,17,data_len,True); - ascii_to_unibuf(smb_buf(outbuf)+crypt_len, global_myworkgroup, - (strlen(global_myworkgroup)+1)*2); + pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); CVAL(outbuf,smb_vwv1) = secword; SSVALS(outbuf,smb_vwv16+1,crypt_len); @@ -268,6 +252,14 @@ protocol [LM1.2X002] protocol [LANMAN2.1] protocol [NT LM 0.12] +Win2K: +protocol [PC NETWORK PROGRAM 1.0] +protocol [LANMAN1.0] +protocol [Windows for Workgroups 3.1a] +protocol [LM1.2X002] +protocol [LANMAN2.1] +protocol [NT LM 0.12] + OS/2: protocol [PC NETWORK PROGRAM 1.0] protocol [XENIX CORE] @@ -281,29 +273,31 @@ protocol [LANMAN2.1] * * This appears to be the matrix of which protocol is used by which * MS product. - Protocol WfWg Win95 WinNT OS/2 - PC NETWORK PROGRAM 1.0 1 1 1 1 - XENIX CORE 2 2 + Protocol WfWg Win95 WinNT Win2K OS/2 + PC NETWORK PROGRAM 1.0 1 1 1 1 1 + XENIX CORE 2 2 MICROSOFT NETWORKS 3.0 2 2 DOS LM1.2X002 3 3 MICROSOFT NETWORKS 1.03 3 DOS LANMAN2.1 4 4 - LANMAN1.0 4 3 - Windows for Workgroups 3.1a 5 5 5 - LM1.2X002 6 4 - LANMAN2.1 7 5 - NT LM 0.12 6 8 + LANMAN1.0 4 2 3 + Windows for Workgroups 3.1a 5 5 5 3 + LM1.2X002 6 4 4 + LANMAN2.1 7 5 5 + NT LM 0.12 6 8 6 * * tim@fsg.com 09/29/95 + * Win2K added by matty 17/7/99 */ #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */ #define ARCH_WIN95 0x2 -#define ARCH_OS2 0xC /* Again OS/2 is like NT */ -#define ARCH_WINNT 0x8 -#define ARCH_SAMBA 0x10 +#define ARCH_WINNT 0x4 +#define ARCH_WIN2K 0xC /* Win2K is like NT */ +#define ARCH_OS2 0x14 /* Again OS/2 is like NT */ +#define ARCH_SAMBA 0x20 -#define ARCH_ALL 0x1F +#define ARCH_ALL 0x3F /* List of supported protocols, most desired first */ static struct { @@ -346,17 +340,17 @@ int reply_negprot(connection_struct *conn, Index++; DEBUG(3,("Requested protocol [%s]\n",p)); if (strcsequal(p,"Windows for Workgroups 3.1a")) - arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT ); + arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); else if (strcsequal(p,"DOS LM1.2X002")) arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(p,"DOS LANMAN2.1")) arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(p,"NT LM 0.12")) - arch &= ( ARCH_WIN95 | ARCH_WINNT ); + arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); else if (strcsequal(p,"LANMAN2.1")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); + arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(p,"LM1.2X002")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); + arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) arch &= ARCH_WINNT; else if (strcsequal(p,"XENIX CORE")) @@ -382,6 +376,9 @@ int reply_negprot(connection_struct *conn, case ARCH_WINNT: set_remote_arch(RA_WINNT); break; + case ARCH_WIN2K: + set_remote_arch(RA_WIN2K); + break; case ARCH_OS2: set_remote_arch(RA_OS2); break; @@ -394,7 +391,7 @@ int reply_negprot(connection_struct *conn, reload_services(True); /* a special case to stop password server loops */ - if (Index == 1 && strequal(remote_machine,myhostname) && + if (Index == 1 && strequal(remote_machine,myhostname()) && (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN)) exit_server("Password server loop!"); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 70023e2407..9615c5ada2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -37,17 +37,14 @@ static void remove_pending_change_notify_requests_by_mid(int mid); static char *known_nt_pipes[] = { "\\LANMAN", "\\srvsvc", - "\\svcctl", "\\samr", "\\wkssvc", - "\\browser", "\\NETLOGON", "\\ntlsa", "\\ntsvcs", "\\lsass", "\\lsarpc", "\\winreg", - "\\spoolss", NULL }; @@ -58,7 +55,7 @@ static char *known_nt_pipes[] = { HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_nt_replies(char *outbuf, int bufsize, char *params, +static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_error, char *params, int paramsize, char *pdata, int datasize) { extern int max_send; @@ -78,6 +75,13 @@ static int send_nt_replies(char *outbuf, int bufsize, char *params, set_message(outbuf,18,0,True); + if(nt_error != 0) { + /* NT Error. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + + ERROR(0,nt_error); + } + /* * If there genuinely are no parameters or data to send just send * the empty packet. @@ -355,18 +359,25 @@ static int map_create_disposition( uint32 create_disposition) Utility function to map share modes. ****************************************************************************/ -static int map_share_mode( char *fname, uint32 desired_access, uint32 share_access, uint32 file_attributes) +static int map_share_mode( BOOL *pstat_open_only, char *fname, + uint32 desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode = -1; - switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) { + *pstat_open_only = False; + + switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) { case FILE_READ_DATA: smb_open_mode = DOS_OPEN_RDONLY; break; case FILE_WRITE_DATA: + case FILE_APPEND_DATA: + case FILE_WRITE_DATA|FILE_APPEND_DATA: smb_open_mode = DOS_OPEN_WRONLY; break; case FILE_READ_DATA|FILE_WRITE_DATA: + case FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA: + case FILE_READ_DATA|FILE_APPEND_DATA: smb_open_mode = DOS_OPEN_RDWR; break; } @@ -386,8 +397,12 @@ static int map_share_mode( char *fname, uint32 desired_access, uint32 share_acce */ if (smb_open_mode == -1) { + if(desired_access == WRITE_DAC_ACCESS || desired_access == READ_CONTROL_ACCESS) + *pstat_open_only = True; + if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| FILE_EXECUTE|FILE_READ_ATTRIBUTES| + FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) smb_open_mode = DOS_OPEN_RDONLY; else { @@ -464,11 +479,40 @@ static time_t fail_time; void fail_next_srvsvc_open(void) { + /* Check client is WinNT proper; Win2K doesn't like Jeremy's hack - matty */ + if (get_remote_arch() != RA_WINNT) + return; + fail_next_srvsvc = True; fail_time = time(NULL); DEBUG(10,("fail_next_srvsvc_open: setting up timeout close of \\srvsvc pipe for print fix.\n")); } +/* + * HACK alert.... see above - JRA. + */ + +BOOL should_fail_next_srvsvc_open(const char *pipename) +{ + + DEBUG(10,("should_fail_next_srvsvc_open: fail = %d, pipe = %s\n", + (int)fail_next_srvsvc, pipename)); + + if(fail_next_srvsvc && (time(NULL) > fail_time + HACK_FAIL_TIME)) { + fail_next_srvsvc = False; + fail_time = (time_t)0; + DEBUG(10,("should_fail_next_srvsvc_open: End of timeout close of \\srvsvc pipe for print fix.\n")); + } + + if(fail_next_srvsvc && strequal(pipename, "srvsvc")) { + fail_next_srvsvc = False; + DEBUG(10,("should_fail_next_srvsvc_open: Deliberately failing open of \\srvsvc pipe for print fix.\n")); + return True; + } + return False; +} + + /**************************************************************************** Reply to an NT create and X call on a pipe. ****************************************************************************/ @@ -487,32 +531,15 @@ static int nt_open_pipe(char *fname, connection_struct *conn, if( strequal(fname,known_nt_pipes[i])) break; - /* - * HACK alert.... see above - JRA. - */ - - if(fail_next_srvsvc && (time(NULL) > fail_time + HACK_FAIL_TIME)) { - fail_next_srvsvc = False; - fail_time = (time_t)0; - DEBUG(10,("nt_open_pipe: End of timeout close of \\srvsvc pipe for print fix.\n")); - } - - if(fail_next_srvsvc && strequal(fname, "\\srvsvc")) { - fail_next_srvsvc = False; - DEBUG(10,("nt_open_pipe: Deliberately failing open of \\srvsvc pipe for print fix.\n")); - return(ERROR(ERRSRV,ERRaccess)); - } - - /* - * End hack alert.... see above - JRA. - */ - if ( known_nt_pipes[i] == NULL ) return(ERROR(ERRSRV,ERRaccess)); /* Strip \\ off the name. */ fname++; + if(should_fail_next_srvsvc_open(fname)) + return (ERROR(ERRSRV,ERRaccess)); + DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); p = open_rpc_pipe_p(fname, conn, vuid); @@ -547,7 +574,7 @@ int reply_ntcreate_and_X(connection_struct *conn, /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - mode_t unixmode; + mode_t unixmode; int pnum = -1; int fmode=0,rmode=0; SMB_OFF_T file_len = 0; @@ -556,6 +583,7 @@ int reply_ntcreate_and_X(connection_struct *conn, BOOL bad_path = False; files_struct *fsp=NULL; char *p = NULL; + BOOL stat_open_only = False; /* * We need to construct the open_and_X ofun value from the @@ -576,9 +604,24 @@ int reply_ntcreate_and_X(connection_struct *conn, files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid); size_t dir_name_len; - if(!dir_fsp || !dir_fsp->is_directory) + if(!dir_fsp) return(ERROR(ERRDOS,ERRbadfid)); + if(!dir_fsp->is_directory) { + /* + * Check to see if this is a mac fork of some kind. + */ + + get_filename(&fname[0], inbuf, smb_buf(inbuf)-inbuf, + smb_buflen(inbuf),fname_len); + + if( fname[0] == ':') { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_OBJECT_PATH_NOT_FOUND)); + } + return(ERROR(ERRDOS,ERRbadfid)); + } + /* * Copy in the base directory name. */ @@ -600,26 +643,17 @@ int reply_ntcreate_and_X(connection_struct *conn, get_filename(&fname[dir_name_len], inbuf, smb_buf(inbuf)-inbuf, smb_buflen(inbuf),fname_len); -#if 0 - StrnCpy(&fname[dir_name_len], smb_buf(inbuf),fname_len); - fname[dir_name_len+fname_len] = '\0'; -#endif } else { get_filename(fname, inbuf, smb_buf(inbuf)-inbuf, smb_buflen(inbuf),fname_len); - -#if 0 - StrnCpy(fname,smb_buf(inbuf),fname_len); - fname[fname_len] = '\0'; -#endif } /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE) - { + if (IS_IPC(conn) && lp_nt_pipe_support()) { + int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); if(ret != 0) return ret; @@ -654,11 +688,13 @@ int reply_ntcreate_and_X(connection_struct *conn, * desired access and the share access. */ - if((smb_open_mode = map_share_mode(fname, desired_access, + if((smb_open_mode = map_share_mode(&stat_open_only, fname, desired_access, share_access, - file_attributes)) == -1) { + file_attributes)) == -1) return(ERROR(ERRDOS,ERRbadaccess)); - } + + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; /* * Ordinary file or directory. @@ -670,11 +706,7 @@ int reply_ntcreate_and_X(connection_struct *conn, set_posix_case_semantics(file_attributes); - if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) { @@ -696,9 +728,6 @@ int reply_ntcreate_and_X(connection_struct *conn, unixmode = unix_mode(conn,smb_attr | aARCH); - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - /* * If it's a request for a directory open, deal with it separately. */ @@ -706,8 +735,8 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, unixmode, - &smb_action); + open_directory(fsp, conn, fname, smb_ofun, + unixmode, &smb_action); restore_case_semantics(file_attributes); @@ -733,13 +762,12 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - open_file_shared(fsp,conn,fname,smb_open_mode, - smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + open_file_shared(fsp,conn,fname,smb_open_mode, + smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp->open) { - /* We cheat here. The only case we - * care about is a directory rename, + /* We cheat here. There are two cases we + * care about. One is a directory rename, * where the NT client will attempt to * open the source directory for * DELETE access. Note that when the @@ -752,21 +780,54 @@ int reply_ntcreate_and_X(connection_struct *conn, * will generate an EISDIR error, so * we can catch this here and open a * pseudo handle that is flagged as a - * directory. JRA. */ + * directory. The second is an open + * for a permissions read only, which + * we handle in the open_file_stat case. JRA. + */ if(errno == EISDIR) { + + /* + * Fail the open if it was explicitly a non-directory file. + */ + + if (create_options & FILE_NON_DIRECTORY_FILE) { + file_free(fsp); + restore_case_semantics(file_attributes); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); + } + oplock_request = 0; + open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); - open_directory(fsp, conn, fname, - smb_ofun, unixmode, - &smb_action); - if(!fsp->open) { file_free(fsp); restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } +#ifdef EROFS + } else if (((errno == EACCES) || (errno == EROFS)) && stat_open_only) { +#else /* !EROFS */ + } else if (errno == EACCES && stat_open_only) { +#endif + /* + * We couldn't open normally and all we want + * are the permissions. Try and do a stat open. + */ + + oplock_request = 0; + + open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action); + + if(!fsp->open) { + file_free(fsp); + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; @@ -782,15 +843,13 @@ int reply_ntcreate_and_X(connection_struct *conn, } if(fsp->is_directory) { - if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), - &sbuf) != 0) { - close_directory(fsp); + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + close_file(fsp,True); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) - != 0) { + if (!fsp->stat_open && sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -817,9 +876,9 @@ int reply_ntcreate_and_X(connection_struct *conn, if (oplock_request && lp_fake_oplocks(SNUM(conn))) smb_action |= EXTENDED_OPLOCK_GRANTED; - if(oplock_request && fsp->granted_oplock) + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) smb_action |= EXTENDED_OPLOCK_GRANTED; - + set_message(outbuf,34,0,True); p = outbuf + smb_vwv2; @@ -828,8 +887,14 @@ int reply_ntcreate_and_X(connection_struct *conn, * Currently as we don't support level II oplocks we just report * exclusive & batch here. */ + + if (smb_action & EXTENDED_OPLOCK_GRANTED) + SCVAL(p,0, BATCH_OPLOCK_RETURN); + else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); + else + SCVAL(p,0,NO_OPLOCK_RETURN); - SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); p++; SSVAL(p,0,fsp->fnum); p += 2; @@ -861,6 +926,7 @@ int reply_ntcreate_and_X(connection_struct *conn, /**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ + static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -893,6 +959,7 @@ static int call_nt_transact_create(connection_struct *conn, BOOL bad_path = False; files_struct *fsp = NULL; char *p = NULL; + BOOL stat_open_only = False; /* * We need to construct the open_and_X ofun value from the @@ -914,8 +981,24 @@ static int call_nt_transact_create(connection_struct *conn, files_struct *dir_fsp = file_fsp(params,4); size_t dir_name_len; - if(!dir_fsp || !dir_fsp->is_directory) + if(!dir_fsp) + return(ERROR(ERRDOS,ERRbadfid)); + + if(!dir_fsp->is_directory) { + /* + * Check to see if this is a mac fork of some kind. + */ + + StrnCpy(fname,params+53,fname_len); + fname[fname_len] = '\0'; + + if( fname[0] == ':') { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_OBJECT_PATH_NOT_FOUND)); + } + return(ERROR(ERRDOS,ERRbadfid)); + } /* * Copy in the base directory name. @@ -951,17 +1034,26 @@ static int call_nt_transact_create(connection_struct *conn, return ret; smb_action = FILE_WAS_OPENED; } else { + + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ + + if((smb_open_mode = map_share_mode( &stat_open_only, fname, desired_access, + share_access, file_attributes)) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); + + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + /* * Check if POSIX semantics are wanted. */ set_posix_case_semantics(file_attributes); - if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) { @@ -983,17 +1075,6 @@ static int call_nt_transact_create(connection_struct *conn, unixmode = unix_mode(conn,smb_attr | aARCH); - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ - - if((smb_open_mode = map_share_mode( fname, desired_access, share_access, file_attributes)) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); - /* * If it's a request for a directory open, deal with it separately. */ @@ -1012,37 +1093,96 @@ static int call_nt_transact_create(connection_struct *conn, if(!fsp->open) { file_free(fsp); + restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } + + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + close_file(fsp,True); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } else { /* * Ordinary file case. */ - open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun, - unixmode,oplock_request,&rmode,&smb_action); + open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); if (!fsp->open) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - restore_case_semantics(file_attributes); + if(errno == EISDIR) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fsp,False); + /* + * Fail the open if it was explicitly a non-directory file. + */ - restore_case_semantics(file_attributes); + if (create_options & FILE_NON_DIRECTORY_FILE) { + file_free(fsp); + restore_case_semantics(file_attributes); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); + } + + oplock_request = 0; + open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + + if(!fsp->open) { + file_free(fsp); + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } +#ifdef EROFS + } else if (((errno == EACCES) || (errno == EROFS)) && stat_open_only) { +#else /* !EROFS */ + } else if (errno == EACCES && stat_open_only) { +#endif - return(ERROR(ERRDOS,ERRnoaccess)); + /* + * We couldn't open normally and all we want + * are the permissions. Try and do a stat open. + */ + + oplock_request = 0; + + open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action); + + if(!fsp->open) { + file_free(fsp); + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + file_free(fsp); + + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } + if(fsp->is_directory) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + close_file(fsp,True); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } else { + if (!fsp->stat_open && sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fsp,False); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } + file_len = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); if(fmode == 0) @@ -1063,7 +1203,7 @@ static int call_nt_transact_create(connection_struct *conn, if (oplock_request && lp_fake_oplocks(SNUM(conn))) smb_action |= EXTENDED_OPLOCK_GRANTED; - if(oplock_request && fsp->granted_oplock) + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) smb_action |= EXTENDED_OPLOCK_GRANTED; } } @@ -1075,8 +1215,16 @@ static int call_nt_transact_create(connection_struct *conn, if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); + memset((char *)params,'\0',69); + p = params; - SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0)); + if (smb_action & EXTENDED_OPLOCK_GRANTED) + SCVAL(p,0, BATCH_OPLOCK_RETURN); + else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); + else + SCVAL(p,0,NO_OPLOCK_RETURN); + p += 2; if (IS_IPC(conn)) { SSVAL(p,0,pnum); @@ -1119,7 +1267,7 @@ static int call_nt_transact_create(connection_struct *conn, } /* Send the required number of replies */ - send_nt_replies(outbuf, bufsize, params, 69, *ppdata, 0); + send_nt_replies(inbuf, outbuf, bufsize, 0, params, 69, *ppdata, 0); return -1; } @@ -1156,6 +1304,7 @@ int reply_nttranss(connection_struct *conn, /**************************************************************************** Reply to an NT transact rename command. ****************************************************************************/ + static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1179,7 +1328,7 @@ static int call_nt_transact_rename(connection_struct *conn, /* * Rename was successful. */ - send_nt_replies(outbuf, bufsize, NULL, 0, NULL, 0); + send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); @@ -1190,6 +1339,18 @@ static int call_nt_transact_rename(connection_struct *conn, return(outsize); } +/**************************************************************************** + This is the structure to keep the information needed to + determine if a directory has changed. +*****************************************************************************/ + +typedef struct { + time_t modify_time; /* Info from the directory we're monitoring. */ + time_t status_time; /* Info from the directory we're monitoring. */ + time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ + unsigned int num_entries; /* Zero or the number of files in the directory. */ +} change_hash_data; + /**************************************************************************** This is the structure to queue to implement NT change notify. It consists of smb_size bytes stored from the @@ -1201,9 +1362,9 @@ typedef struct { ubi_slNode msg_next; files_struct *fsp; connection_struct *conn; + uint32 flags; time_t next_check_time; - time_t modify_time; /* Info from the directory we're monitoring. */ - time_t status_time; /* Info from the directory we're monitoring. */ + change_hash_data change_data; char request_buf[smb_size]; } change_notify_buf; @@ -1243,9 +1404,93 @@ static void change_notify_reply_packet(char *inbuf, int error_class, uint32 erro send_smb(Client,outbuf); } +/**************************************************************************** + Create the hash we will use to determine if the contents changed. +*****************************************************************************/ + +static BOOL create_directory_notify_hash( change_notify_buf *cnbp, change_hash_data *change_data) +{ + SMB_STRUCT_STAT st; + files_struct *fsp = cnbp->fsp; + + memset((char *)change_data, '\0', sizeof(change_data)); + + /* + * Store the current timestamp on the directory we are monitoring. + */ + + if(dos_stat(fsp->fsp_name, &st) < 0) { + DEBUG(0,("create_directory_notify_hash: Unable to stat name = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + return False; + } + + change_data->modify_time = st.st_mtime; + change_data->status_time = st.st_ctime; + + /* + * If we are to watch for changes that are only stored + * in inodes of files, not in the directory inode, we must + * scan the directory and produce a unique identifier with + * which we can determine if anything changed. We use the + * modify and change times from all the files in the + * directory, added together (ignoring wrapping if it's + * larger than the max time_t value). + */ + + if(cnbp->flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE)) { + pstring full_name; + char *p; + char *fname; + size_t remaining_len; + size_t fullname_len; + void *dp = OpenDir(cnbp->conn, fsp->fsp_name, True); + + if(dp == NULL) { + DEBUG(0,("create_directory_notify_hash: Unable to open directory = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + return False; + } + + change_data->num_entries = 0; + + pstrcpy(full_name, fsp->fsp_name); + pstrcat(full_name, "/"); + + fullname_len = strlen(full_name); + remaining_len = sizeof(full_name) - fullname_len - 1; + p = &full_name[fullname_len]; + + while ((fname = ReadDirName(dp))) { + if(strequal(fname, ".") || strequal(fname, "..")) + continue; + + change_data->num_entries++; + safe_strcpy( p, fname, remaining_len); + + memset(&st, '\0', sizeof(st)); + + /* + * Do the stat - but ignore errors. + */ + + if(dos_stat(full_name, &st) < 0) { + DEBUG(5,("create_directory_notify_hash: Unable to stat content file = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + } + change_data->total_time += (st.st_mtime + st.st_ctime); + } + + CloseDir(dp); + } + + return True; +} + /**************************************************************************** Delete entries by fnum from the change notify pending queue. *****************************************************************************/ + void remove_pending_change_notify_requests_by_fid(files_struct *fsp) { change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); @@ -1274,7 +1519,34 @@ static void remove_pending_change_notify_requests_by_mid(int mid) while(cnbp != NULL) { if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_CANCELLED); + change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Delete entries by filename and cnum from the change notify pending queue. + Always send reply. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_filename(files_struct *fsp) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + /* + * We know it refers to the same directory if the connection number and + * the filename are identical. + */ + if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { + change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; @@ -1287,18 +1559,20 @@ static void remove_pending_change_notify_requests_by_mid(int mid) /**************************************************************************** Process the change notify queue. Note that this is only called as root. + Returns True if there are still outstanding change notify requests on the + queue. *****************************************************************************/ -void process_pending_change_notify_queue(time_t t) +BOOL process_pending_change_notify_queue(time_t t) { change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); change_notify_buf *prev = NULL; if(cnbp == NULL) - return; + return False; if(cnbp->next_check_time >= t) - return; + return True; /* * It's time to check. Go through the queue and see if @@ -1306,8 +1580,7 @@ void process_pending_change_notify_queue(time_t t) */ while((cnbp != NULL) && (cnbp->next_check_time <= t)) { - SMB_STRUCT_STAT st; - files_struct *fsp = cnbp->fsp; + change_hash_data change_data; connection_struct *conn = cnbp->conn; uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); @@ -1343,9 +1616,9 @@ void process_pending_change_notify_queue(time_t t) continue; } - if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &st) < 0) { - DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \ -Error was %s.\n", fsp->fsp_name, strerror(errno) )); + if(!create_directory_notify_hash( cnbp, &change_data)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to create change data for \ +directory %s\n", cnbp->fsp->fsp_name )); /* * Remove the entry and return an error to the client. */ @@ -1356,13 +1629,12 @@ Error was %s.\n", fsp->fsp_name, strerror(errno) )); continue; } - if(cnbp->modify_time != st.st_mtime || - cnbp->status_time != st.st_ctime) { + if(memcmp( (char *)&cnbp->change_data, (char *)&change_data, sizeof(change_data))) { /* * Remove the entry and return a change notify to the client. */ - DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed\n", - fsp->fsp_name )); + DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed.\n", + cnbp->fsp->fsp_name )); change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); @@ -1378,22 +1650,34 @@ Error was %s.\n", fsp->fsp_name, strerror(errno) )); prev = cnbp; cnbp = (change_notify_buf *)ubi_slNext(cnbp); } + + return (cnbp != NULL); +} + +/**************************************************************************** + Return true if there are pending change notifies. +****************************************************************************/ + +BOOL change_notifies_pending(void) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + return (cnbp != NULL); } /**************************************************************************** Reply to a notify change - queue the request and don't allow a directory to be opened. ****************************************************************************/ + static int call_nt_transact_notify_change(connection_struct *conn, - char *inbuf, char *outbuf, int length, + char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, - char **ppparams, char **ppdata) + char **ppparams, char **ppdata) { char *setup = *ppsetup; files_struct *fsp; change_notify_buf *cnbp; - SMB_STRUCT_STAT st; fsp = file_fsp(setup,4); @@ -1414,28 +1698,22 @@ static int call_nt_transact_notify_change(connection_struct *conn, */ if((cnbp = (change_notify_buf *)malloc(sizeof(change_notify_buf))) == NULL) { - DEBUG(0,("call_nt_transact_notify_change: Malloc fail (2) !\n" )); + DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); return -1; } - /* - * Store the current timestamp on the directory we are monitoring. - */ + memset((char *)cnbp, '\0', sizeof(change_notify_buf)); - if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &st) < 0) { - DEBUG(0,("call_nt_transact_notify_change: Unable to stat name = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - free((char *)cnbp); - return(UNIXERROR(ERRDOS,ERRbadfid)); - } - memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; cnbp->conn = conn; - cnbp->modify_time = st.st_mtime; - cnbp->status_time = st.st_ctime; - cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); + cnbp->flags = IVAL(setup, 0); + + if(!create_directory_notify_hash( cnbp, &cnbp->change_data )) { + free((char *)cnbp); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } /* * Adding to the tail enables us to check only @@ -1452,43 +1730,661 @@ name = %s\n", fsp->fsp_name )); } /**************************************************************************** - Reply to query a security descriptor - currently this is not implemented (it - is planned to be though). + Map unix perms to NT. ****************************************************************************/ -static int call_nt_transact_query_security_desc(connection_struct *conn, - char *inbuf, char *outbuf, - int length, - int bufsize, - char **ppsetup, char **ppparams, char **ppdata) + +static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w_mask, int x_mask, BOOL is_directory) { - static BOOL logged_message = False; + SEC_ACCESS sa; + uint32 nt_mask = 0; - if(!logged_message) { - DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n")); - logged_message = True; /* Only print this once... */ - } + *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; + + if((perm & (r_mask|w_mask|x_mask)) == (r_mask|w_mask|x_mask)) { + nt_mask = UNIX_ACCESS_RWX; + } else if((perm & (r_mask|w_mask|x_mask)) == 0) { + nt_mask = UNIX_ACCESS_NONE; + } else { + nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; + if(is_directory) + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + else + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; + } + init_sec_access(&sa,nt_mask); + return sa; +} + +/**************************************************************************** + Reply to query a security descriptor from an fsp. If it succeeds it allocates + the space for the return elements and returns True. +****************************************************************************/ + +static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) +{ + extern DOM_SID global_sam_sid; + extern DOM_SID global_sid_World; + SMB_STRUCT_STAT sbuf; + SEC_ACE ace_list[6]; + DOM_SID owner_sid; + DOM_SID group_sid; + size_t sec_desc_size; + SEC_ACL *psa = NULL; + SEC_ACCESS owner_access; + int owner_acl_type; + SEC_ACCESS group_access; + int grp_acl_type; + SEC_ACCESS other_access; + int other_acl_type; + int num_acls = 0; + + *ppdesc = NULL; + + if(!lp_nt_acl_support()) { + sid_copy( &owner_sid, &global_sid_World); + sid_copy( &group_sid, &global_sid_World); + } else { + + if(fsp->is_directory || fsp->fd_ptr == NULL) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + return 0; + } + } else { + if(sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + return 0; + } + } + + /* + * Get the owner, group and world SIDs. + */ + + sid_copy(&owner_sid, &global_sam_sid); + sid_copy(&group_sid, &global_sam_sid); + sid_append_rid(&owner_sid, pdb_uid_to_user_rid(sbuf.st_uid)); + sid_append_rid(&group_sid, pdb_gid_to_group_rid(sbuf.st_gid)); + + /* + * Create the generic 3 element UNIX acl. + */ + + owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, + S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); + group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, + S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); + other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, + S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); + + if(owner_access.mask) + init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, + owner_access, 0); + + if(group_access.mask) + init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, + group_access, 0); + + if(other_access.mask) + init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, + other_access, 0); + + if(fsp->is_directory) { + /* + * For directory ACLs we also add in the inherited permissions + * ACE entries. These are the permissions a file would get when + * being created in the directory. + */ + mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE); + + owner_access = map_unix_perms(&owner_acl_type, mode, + S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); + group_access = map_unix_perms(&grp_acl_type, mode, + S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); + other_access = map_unix_perms(&other_acl_type, mode, + S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); + + if(owner_access.mask) + init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, + owner_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + + if(group_access.mask) + init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, + group_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + + if(other_access.mask) + init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, + other_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + } + + if(num_acls) + if((psa = make_sec_acl( 3, num_acls, ace_list)) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); + return 0; + } + } + + *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sec_desc_size); + + if(!*ppdesc) { + DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); + sec_desc_size = 0; + } + + free_sec_acl(&psa); + + return sec_desc_size; +} - return(ERROR(ERRSRV,ERRnosupport)); -} - /**************************************************************************** - Reply to set a security descriptor - currently this is not implemented (it - is planned to be though). + Reply to query a security descriptor - currently this is not implemented (it + is planned to be though). Right now it just returns the same thing NT would + when queried on a FAT filesystem. JRA. ****************************************************************************/ + +static int call_nt_transact_query_security_desc(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, + char **ppsetup, char **ppparams, char **ppdata) +{ + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); + char *params = *ppparams; + char *data = *ppdata; + prs_struct pd; + SEC_DESC *psd; + size_t sec_desc_size; + + files_struct *fsp = file_fsp(params,0); + + if(!fsp) + return(ERROR(ERRDOS,ERRbadfid)); + + DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); + + params = *ppparams = Realloc(*ppparams, 4); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + /* + * Get the permissions to return. + */ + + if((sec_desc_size = get_nt_acl(fsp, &psd)) == 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + DEBUG(3,("call_nt_transact_query_security_desc: sec_desc_size = %d.\n",(int)sec_desc_size)); + + SIVAL(params,0,(uint32)sec_desc_size); + + if(max_data_count < sec_desc_size) { + + free_sec_desc(&psd); + + send_nt_replies(inbuf, outbuf, bufsize, 0xC0000000|NT_STATUS_BUFFER_TOO_SMALL, + params, 4, *ppdata, 0); + return -1; + } + + /* + * Allocate the data we will point this at. + */ + + data = *ppdata = Realloc(*ppdata, sec_desc_size); + if(data == NULL) { + free_sec_desc(&psd); + return(ERROR(ERRDOS,ERRnomem)); + } + + memset(data, '\0', sec_desc_size); + + /* + * Init the parse struct we will marshall into. + */ + + prs_init(&pd, 0, 4, MARSHALL); + + /* + * Setup the prs_struct to point at the memory we just + * allocated. + */ + + prs_give_memory( &pd, data, (uint32)sec_desc_size, False); + + /* + * Finally, linearize into the outgoing buffer. + */ + + if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + free_sec_desc(&psd); + DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ +security descriptor.\n")); + /* + * Return access denied for want of a better error message.. + */ + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* + * Now we can delete the security descriptor. + */ + + free_sec_desc(&psd); + + send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sec_desc_size); + return -1; +} + +/**************************************************************************** + Validate a SID. +****************************************************************************/ + +static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) +{ + extern DOM_SID global_sam_sid; + DOM_SID sid; + + if(!sd_sid) { + DEBUG(5,("validate_unix_sid: sid missing.\n")); + return False; + } + + sid_copy(psid, sd_sid); + sid_copy(&sid, sd_sid); + + if(!sid_split_rid(&sid, prid)) { + DEBUG(5,("validate_unix_sid: cannot get RID from sid.\n")); + return False; + } + + if(!sid_equal( &sid, &global_sam_sid)) { + DEBUG(5,("validate_unix_sid: sid is not ours.\n")); + return False; + } + + return True; +} + +/**************************************************************************** + Map NT perms to UNIX. +****************************************************************************/ + +#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) +#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) +#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) + +static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) +{ + mode_t mode = 0; + + switch(type) { + case S_IRUSR: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRUSR|S_IWUSR|S_IXUSR; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; + } + break; + case S_IRGRP: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRGRP|S_IWGRP|S_IXGRP; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; + } + break; + case S_IROTH: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IROTH|S_IWOTH|S_IXOTH; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; + } + break; + } + + return mode; +} + +/**************************************************************************** + Unpack a SEC_DESC into a owner, group and set of UNIX permissions. +****************************************************************************/ + +static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint32 security_info_sent, + SEC_DESC *psd, BOOL is_directory) +{ + extern DOM_SID global_sid_World; + DOM_SID owner_sid; + DOM_SID grp_sid; + uint32 owner_rid; + uint32 grp_rid; + SEC_ACL *dacl = psd->dacl; + int i; + + *pmode = 0; + *puser = (uid_t)-1; + *pgrp = (gid_t)-1; + + if(security_info_sent == 0) { + DEBUG(0,("unpack_unix_permissions: no security info sent !\n")); + return False; + } + + /* + * Validate the owner and group SID's. + */ + + memset(&owner_sid, '\0', sizeof(owner_sid)); + memset(&grp_sid, '\0', sizeof(grp_sid)); + + DEBUG(5,("unpack_unix_permissions: validating owner_sid.\n")); + + /* + * Don't immediately fail if the owner sid cannot be validated. + * This may be a group chown only set. + */ + + if(!validate_unix_sid( &owner_sid, &owner_rid, psd->owner_sid)) + DEBUG(3,("unpack_unix_permissions: unable to validate owner sid.\n")); + else if(security_info_sent & OWNER_SECURITY_INFORMATION) + *puser = pdb_user_rid_to_uid(owner_rid); + + /* + * Don't immediately fail if the group sid cannot be validated. + * This may be an owner chown only set. + */ + + if(!validate_unix_sid( &grp_sid, &grp_rid, psd->grp_sid)) + DEBUG(3,("unpack_unix_permissions: unable to validate group sid.\n")); + else if(security_info_sent & GROUP_SECURITY_INFORMATION) + *pgrp = pdb_user_rid_to_gid(grp_rid); + + /* + * If no DACL then this is a chown only security descriptor. + */ + + if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) { + *pmode = 0; + return True; + } + + /* + * Now go through the DACL and ensure that + * any owner/group sids match. + */ + + for(i = 0; i < dacl->num_aces; i++) { + DOM_SID ace_sid; + SEC_ACE *psa = &dacl->ace_list[i]; + + if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && + (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { + DEBUG(3,("unpack_unix_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); + return False; + } + + /* + * Ignore or remove bits we don't care about on a directory ACE. + */ + + if(is_directory) { + if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + DEBUG(3,("unpack_unix_permissions: ignoring inherit only ACE.\n")); + continue; + } + + psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); + } + + if(psa->flags != 0) { + DEBUG(1,("unpack_unix_permissions: unable to set ACE flags (%x).\n", + (unsigned int)psa->flags)); + return False; + } + + /* + * The security mask may be UNIX_ACCESS_NONE which should map into + * no permissions (we overload the WRITE_OWNER bit for this) or it + * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this + * to be so. Any other bits override the UNIX_ACCESS_NONE bit. + */ + + psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| + GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); + + if(psa->info.mask != UNIX_ACCESS_NONE) + psa->info.mask &= ~UNIX_ACCESS_NONE; + + sid_copy(&ace_sid, &psa->sid); + + if(sid_equal(&ace_sid, &owner_sid)) { + /* + * Map the desired permissions into owner perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IRUSR); + else + *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); + + } else if( sid_equal(&ace_sid, &grp_sid)) { + /* + * Map the desired permissions into group perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IRGRP); + else + *pmode &= ~(map_nt_perms( psa->info, S_IRGRP)); + + } else if( sid_equal(&ace_sid, &global_sid_World)) { + /* + * Map the desired permissions into other perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IROTH); + else + *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); + + } else { + DEBUG(0,("unpack_unix_permissions: unknown SID used in ACL.\n")); + return False; + } + } + + return True; +} + +/**************************************************************************** + Reply to set a security descriptor. Map to UNIX perms. +****************************************************************************/ + static int call_nt_transact_set_security_desc(connection_struct *conn, - char *inbuf, char *outbuf, - int length, - int bufsize, - char **ppsetup, - char **ppparams, char **ppdata) + char *inbuf, char *outbuf, int length, + int bufsize, char **ppsetup, + char **ppparams, char **ppdata) { - static BOOL logged_message = False; + uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); + char *params= *ppparams; + char *data = *ppdata; + prs_struct pd; + SEC_DESC *psd = NULL; + uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); + uid_t user = (uid_t)-1; + gid_t grp = (gid_t)-1; + mode_t perms = 0; + SMB_STRUCT_STAT sbuf; + files_struct *fsp = NULL; + uint32 security_info_sent = 0; + BOOL got_dacl = False; - if(!logged_message) { - DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n")); - logged_message = True; /* Only print this once... */ + if(!lp_nt_acl_support()) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if(total_parameter_count < 8) + return(ERROR(ERRDOS,ERRbadfunc)); + + if((fsp = file_fsp(params,0)) == NULL) + return(ERROR(ERRDOS,ERRbadfid)); + + security_info_sent = IVAL(params,4); + + DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, + (unsigned int)security_info_sent )); + + /* + * Init the parse struct we will unmarshall from. + */ + + prs_init(&pd, 0, 4, UNMARSHALL); + + /* + * Setup the prs_struct to point at the memory we just + * allocated. + */ + + prs_give_memory( &pd, data, total_data_count, False); + + /* + * Finally, unmarshall from the data buffer. + */ + + if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + free_sec_desc(&psd); + DEBUG(0,("call_nt_transact_set_security_desc: Error in unmarshalling \ +security descriptor.\n")); + /* + * Return access denied for want of a better error message.. + */ + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - return(ERROR(ERRSRV,ERRnosupport)); + + /* + * Unpack the user/group/world id's and permissions. + */ + + if(!unpack_nt_permissions( &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) { + free_sec_desc(&psd); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if (psd->dacl != NULL) + got_dacl = True; + + free_sec_desc(&psd); + + /* + * Get the current state of the file. + */ + + if(fsp->is_directory) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + + int ret; + + if(fsp->fd_ptr == NULL) + ret = dos_stat(fsp->fsp_name, &sbuf); + else + ret = sys_fstat(fsp->fd_ptr->fd,&sbuf); + + if(ret != 0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } + + /* + * Do we need to chown ? + */ + + if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { + + DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); + + if(dos_chown( fsp->fsp_name, user, grp) == -1) { + DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* + * Recheck the current state of the file, which may have changed. + * (suid/sgid bits, for instance) + */ + + if(fsp->is_directory) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + + int ret; + + if(fsp->fd_ptr == NULL) + ret = dos_stat(fsp->fsp_name, &sbuf); + else + ret = sys_fstat(fsp->fd_ptr->fd,&sbuf); + + if(ret != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } + + /* + * Only change security if we got a DACL. + */ + + if((security_info_sent & DACL_SECURITY_INFORMATION) && got_dacl) { + + /* + * Check to see if we need to change anything. + * Enforce limits on modified bits *only*. Don't enforce masks + * on bits not changed by the user. + */ + + if(fsp->is_directory) { + + perms &= (lp_dir_security_mask(SNUM(conn)) | sbuf.st_mode); + perms |= (lp_force_dir_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + + } else { + + perms &= (lp_security_mask(SNUM(conn)) | sbuf.st_mode); + perms |= (lp_force_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + + } + + /* + * Preserve special bits. + */ + + perms |= (sbuf.st_mode & ~0777); + + /* + * Do we need to chmod ? + */ + + if(sbuf.st_mode != perms) { + + DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", + fsp->fsp_name, (unsigned int)perms )); + + if(dos_chmod( fsp->fsp_name, perms) == -1) { + DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)perms, strerror(errno) )); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } + } + + send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); + return -1; } /**************************************************************************** @@ -1675,7 +2571,6 @@ due to being in oplock break state.\n" )); length, bufsize, &setup, ¶ms, &data); break; - default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2c12d425b9..4491082b2c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -25,22 +25,22 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; extern uint16 global_oplock_port; - +extern BOOL global_client_failed_oplock_break; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ -static int fd_attempt_open(struct connection_struct *conn, char *fname, - int flags, mode_t mode) + +static int fd_attempt_open(char *fname, int flags, mode_t mode) { - int fd = conn->vfs_ops.open(fname,flags,mode); + int fd = dos_open(fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(fname,flags,mode); + fd = dos_open(fname,flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -71,7 +71,7 @@ static int fd_attempt_open(struct connection_struct *conn, char *fname, char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = conn->vfs_ops.open(fname,flags,mode)) == -1) + if ((fd = dos_open(fname,flags,mode)) == -1) p[max_len] = tmp; } } @@ -83,6 +83,7 @@ static int fd_attempt_open(struct connection_struct *conn, char *fname, Cache a uid_t currently with this file open. This is an optimization only used when multiple sessionsetup's have been done to one smbd. ****************************************************************************/ + void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) { if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) @@ -94,6 +95,7 @@ void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) Remove a uid_t that currently has this file open. This is an optimization only used when multiple sessionsetup's have been done to one smbd. ****************************************************************************/ + static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) { int i; @@ -111,6 +113,7 @@ static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) Check if a uid_t that currently has this file open is present. This is an optimization only used when multiple sessionsetup's have been done to one smbd. ****************************************************************************/ + static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) { int i; @@ -120,11 +123,11 @@ static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) return False; } - /**************************************************************************** fd support routines - attempt to re-open an already open fd as O_RDWR. Save the already open fd (we cannot close due to POSIX file locking braindamage. ****************************************************************************/ + static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) { int fd = dos_open( fname, O_RDWR, mode); @@ -145,17 +148,13 @@ static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ -uint16 fd_attempt_close(files_struct *fsp) + +uint16 fd_attempt_close(file_fd_struct *fd_ptr, int *err_ret) { extern struct current_user current_user; - file_fd_struct *fd_ptr = fsp->fd_ptr; - uint16 ret_ref; + uint16 ret_ref = fd_ptr->ref_count; - if (fd_ptr != NULL) { - ret_ref = fd_ptr->ref_count; - } else { - return 0; - } + *err_ret = 0; DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n", fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, @@ -168,12 +167,26 @@ uint16 fd_attempt_close(files_struct *fsp) ret_ref = fd_ptr->ref_count; if(fd_ptr->ref_count == 0) { - if(fd_ptr->fd != -1) - fsp->conn->vfs_ops.close(fd_ptr->fd); - if(fd_ptr->fd_readonly != -1) - fsp->conn->vfs_ops.close(fd_ptr->fd_readonly); - if(fd_ptr->fd_writeonly != -1) - fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly); + + if(fd_ptr->fd != -1) { + if(close(fd_ptr->fd) < 0) + *err_ret = errno; + } + + if(fd_ptr->fd_readonly != -1) { + if(close(fd_ptr->fd_readonly) < 0) { + if(*err_ret == 0) + *err_ret = errno; + } + } + + if(fd_ptr->fd_writeonly != -1) { + if( close(fd_ptr->fd_writeonly) < 0) { + if(*err_ret == 0) + *err_ret = errno; + } + } + /* * Delete this fd_ptr. */ @@ -182,7 +195,7 @@ uint16 fd_attempt_close(files_struct *fsp) fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); } - return ret_ref; + return ret_ref; } /**************************************************************************** @@ -192,14 +205,21 @@ This is really ugly code, as due to POSIX locking braindamage we must fork and then attempt to open the file, and return success or failure via an exit code. ****************************************************************************/ -static BOOL check_access_allowed_for_current_user(struct connection_struct - *conn, char *fname, - int accmode ) + +static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) { pid_t child_pid; + /* + * We need to temporarily stop CatchChild from eating + * SIGCLD signals as it also eats the exit status code. JRA. + */ + + CatchChildLeaveStatus(); + if((child_pid = fork()) < 0) { DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); + CatchChild(); return False; } @@ -209,11 +229,23 @@ static BOOL check_access_allowed_for_current_user(struct connection_struct */ pid_t wpid; int status_code; - if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { - DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n")); + + while ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { + if(errno == EINTR) { + errno = 0; + continue; + } + DEBUG(0,("check_access_allowed_for_current_user: The process \ +is no longer waiting ! Error = %s\n", strerror(errno) )); + CatchChild(); return(False); } + /* + * Go back to ignoring children. + */ + CatchChild(); + if (child_pid != wpid) { DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); return(False); @@ -245,7 +277,7 @@ static BOOL check_access_allowed_for_current_user(struct connection_struct */ int fd; DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode )); - if((fd = fd_attempt_open(conn, fname, accmode, 0)) < 0) { + if((fd = fd_attempt_open( fname, accmode, 0)) < 0) { /* Access denied. */ _exit(EACCES); } @@ -260,11 +292,12 @@ static BOOL check_access_allowed_for_current_user(struct connection_struct /**************************************************************************** check a filename for the pipe string ****************************************************************************/ + static void check_for_pipe(char *fname) { /* special case of pipe opens */ char s[10]; - StrnCpy(s,fname,9); + StrnCpy(s,fname,sizeof(s)-1); strlower(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); @@ -276,6 +309,7 @@ static void check_for_pipe(char *fname) /**************************************************************************** open a file ****************************************************************************/ + static void open_file(files_struct *fsp,connection_struct *conn, char *fname1,int flags,mode_t mode, SMB_STRUCT_STAT *sbuf) { @@ -287,7 +321,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->open = False; fsp->fd_ptr = 0; - fsp->granted_oplock = False; + fsp->oplock_type = NO_OPLOCK; errno = EPERM; pstrcpy(fname,fname1); @@ -304,7 +338,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * JRA. */ - if (conn->read_only && !conn->printer) { + if (!CAN_WRITE(conn) && !conn->printer) { /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); @@ -335,7 +369,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * open fd table. */ if(sbuf == 0) { - if(conn->vfs_ops.stat(dos_to_unix(fname,False), &statbuf) < 0) { + if(dos_stat(fname, &statbuf) < 0) { if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); @@ -376,7 +410,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { - if(!check_access_allowed_for_current_user(conn, fname, accmode )) { + if(!check_access_allowed_for_current_user( fname, accmode )) { /* Error - permission denied. */ DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", fname, flags, accmode)); @@ -433,7 +467,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fd_ptr->real_open_flags = O_RDWR; /* Set the flags as needed without the read/write modes. */ open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); - fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|O_RDWR, mode); + fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); /* * On some systems opening a file for R/W access on a read only * filesystems sets errno to EROFS. @@ -444,7 +478,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if((fd_ptr->fd == -1) && (errno == EACCES)) { #endif /* EROFS */ if(accmode != O_RDWR) { - fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode); + fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); fd_ptr->real_open_flags = accmode; } } @@ -458,10 +492,10 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (conn->vfs_ops.disk_free(dname,&dum1,&dum2,&dum3) < - (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { - if(fd_attempt_close(fsp) == 0) - conn->vfs_ops.unlink(fname); + if (sys_disk_free(dname,False,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { + int err; + if(fd_attempt_close(fd_ptr, &err) == 0) + dos_unlink(fname); fsp->fd_ptr = 0; errno = ENOSPC; return; @@ -470,10 +504,11 @@ static void open_file(files_struct *fsp,connection_struct *conn, if (fd_ptr->fd < 0) { + int err; DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); /* Ensure the ref_count is decremented. */ - fd_attempt_close(fsp); + fd_attempt_close(fd_ptr,&err); check_for_pipe(fname); return; } @@ -482,12 +517,13 @@ static void open_file(files_struct *fsp,connection_struct *conn, { if(sbuf == 0) { /* Do the fstat */ - if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) { + if(sys_fstat(fd_ptr->fd, &statbuf) == -1) { + int err; /* Error - backout !! */ DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", fd_ptr->fd, fname,strerror(errno))); /* Ensure the ref_count is decremented. */ - fd_attempt_close(fsp); + fd_attempt_close(fd_ptr,&err); return; } sbuf = &statbuf; @@ -505,17 +541,17 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->size = 0; fsp->pos = -1; fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); fsp->share_mode = 0; fsp->print_file = conn->printer; fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; + fsp->stat_open = False; + fsp->directory_delete_on_close = False; fsp->conn = conn; /* * Note that the file name here is the *untranslated* name @@ -526,6 +562,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; + fsp->wcp = NULL; /* Write cache pointer. */ /* * If the printer is marked as postscript output a leading @@ -536,7 +573,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { DEBUG(3,("Writing postscript line\n")); - conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3); + write_file(fsp,"%!\n",-1,3); } DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -547,40 +584,12 @@ static void open_file(files_struct *fsp,connection_struct *conn, } } -/**************************************************************************** - If it's a read-only file, and we were compiled with mmap enabled, - try and mmap the file. This is split out from open_file() above - as mmap'ing the file can cause the kernel reference count to - be incremented, which can cause kernel oplocks to be refused. - Splitting this call off allows the kernel oplock to be granted, then - the file mmap'ed. -****************************************************************************/ - -static void mmap_open_file(files_struct *fsp) -{ -#if WITH_MMAP - /* mmap it if read-only */ - if (!fsp->can_write) { - fsp->mmap_size = dos_file_size(fsp->fsp_name); - if (fsp->mmap_size < MAX_MMAP_SIZE) { - fsp->mmap_ptr = (char *)sys_mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,(SMB_OFF_T)0); - - if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { - DEBUG(3,("Failed to mmap() %s - %s\n", - fsp->fsp_name,strerror(errno))); - fsp->mmap_ptr = NULL; - } - } - } -#endif -} - /**************************************************************************** C. Hoch 11/22/95 Helper for open_file_shared. Truncate a file after checking locking; close file if locked. **************************************************************************/ + static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, BOOL *share_locked) { @@ -606,19 +615,19 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i } } - enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* reproduce the share mode access table ********************************************************************/ + static int access_table(int new_deny,int old_deny,int old_mode, - int share_pid,char *fname) + pid_t share_pid,char *fname) { if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - int pid = getpid(); + pid_t pid = getpid(); if (old_deny == new_deny && share_pid == pid) return(AALL); @@ -660,10 +669,10 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } - /**************************************************************************** check if we can open a file with a share mode ****************************************************************************/ + static int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags) @@ -707,7 +716,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", deny_mode,old_deny_mode,old_open_mode, - share->pid,fname, fcbopen, *flags, access_allowed)); + (int)share->pid,fname, fcbopen, *flags, access_allowed)); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -726,34 +735,39 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, return True; } - /**************************************************************************** open a file with a share mode ****************************************************************************/ -void open_file_shared(files_struct *fsp, connection_struct *conn, - char *fname, int share_mode, int ofun, - mode_t mode, int oplock_request, int *Access, - int *action) + +void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, + mode_t mode,int oplock_request, int *Access,int *action) { int flags=0; int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); SMB_STRUCT_STAT sbuf; - BOOL file_existed = vfs_file_exist(conn, dos_to_unix(fname,False), &sbuf); + BOOL file_existed = dos_file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; - int token; + int token = 0; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; - + int oplock_contention_count = 0; + BOOL all_current_opens_are_level_II = False; fsp->open = False; fsp->fd_ptr = 0; DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, share_mode, ofun, (int)mode, oplock_request )); + + /* ignore any oplock requests if oplocks are disabled */ + if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { + oplock_request = 0; + } + /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) { @@ -861,6 +875,8 @@ void open_file_shared(files_struct *fsp, connection_struct *conn, { broke_oplock = False; + all_current_opens_are_level_II = True; + for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &old_shares[i]; @@ -872,7 +888,8 @@ void open_file_shared(files_struct *fsp, connection_struct *conn, * Check if someone has an oplock on this file. If so we must break * it before continuing. */ - if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) + if((oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || + (!oplock_request && (share_entry->op_type != NO_OPLOCK))) { DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ @@ -894,7 +911,10 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } lock_share_entry(conn, dev, inode, &token); broke_oplock = True; + all_current_opens_are_level_II = False; break; + } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + all_current_opens_are_level_II = False; } /* someone else has a share lock on it, check to see @@ -913,6 +933,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou { free((char *)old_shares); num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + oplock_contention_count++; } } while(broke_oplock); } @@ -921,6 +942,18 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free((char *)old_shares); } + /* + * Refuse to grant an oplock in case the contention limit is + * reached when going through the lock list multiple times. + */ + + if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) + { + oplock_request = 0; + DEBUG(4,("open_file_shared: oplock contention = %d. Not granting oplock.\n", + oplock_contention_count )); + } + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); @@ -978,18 +1011,19 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou { uint16 port = 0; - /* JRA. Currently this only services Exlcusive and batch - oplocks (no other opens on this file). This needs to - be extended to level II oplocks (multiple reader - oplocks). */ + /* + * Setup the oplock info in both the shared memory and + * file structs. + */ - if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && - !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp) ) - { + if(oplock_request && (num_share_modes == 0) && + !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { port = global_oplock_port; - } - else - { + } else if (oplock_request && all_current_opens_are_level_II) { + port = global_oplock_port; + oplock_request = LEVEL_II_OPLOCK; + set_file_oplock(fsp, oplock_request); + } else { port = 0; oplock_request = 0; } @@ -999,19 +1033,75 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fsp,conn,token,&share_locked); - - /* - * Attempt to mmap a read only file. - * Moved until after a kernel oplock may - * be granted due to reference count issues. JRA. - */ - mmap_open_file(fsp); } if (share_locked && lp_share_modes(SNUM(conn))) unlock_share_entry( conn, dev, inode, token); } +/**************************************************************************** + Open a file for permissions read only. Return a pseudo file entry + with the 'stat_open' flag set and a fd_ptr of NULL. +****************************************************************************/ + +int open_file_stat(files_struct *fsp,connection_struct *conn, + char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action) +{ + extern struct current_user current_user; + + if(dos_stat(fname, pst) < 0) { + DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + if(S_ISDIR(pst->st_mode)) { + DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); + return -1; + } + + *action = FILE_WAS_OPENED; + + DEBUG(5,("open_file_stat: opening file %s as a stat entry\n", fname)); + + /* + * Setup the files_struct for it. + */ + + fsp->fd_ptr = NULL; + conn->num_files_open++; + fsp->mode = 0; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->can_lock = False; + fsp->can_read = False; + fsp->can_write = False; + fsp->share_mode = 0; + fsp->print_file = False; + fsp->modified = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->is_directory = False; + fsp->stat_open = True; + fsp->directory_delete_on_close = False; + fsp->conn = conn; + /* + * Note that the file name here is the *untranslated* name + * ie. it is still in the DOS codepage sent from the client. + * All use of this filename will pass though the sys_xxxx + * functions which will do the dos_to_unix translation before + * mapping into a UNIX filename. JRA. + */ + string_set(&fsp->fsp_name,fname); + fsp->wbmpx_ptr = NULL; + fsp->wcp = NULL; /* Write cache pointer. */ + + return 0; +} + /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -1021,26 +1111,55 @@ int open_directory(files_struct *fsp,connection_struct *conn, { extern struct current_user current_user; SMB_STRUCT_STAT st; + BOOL got_stat = False; - if (smb_ofun & 0x10) { - /* - * Create the directory. - */ + if(dos_stat(fname, &st) == 0) { + got_stat = True; + } - if(conn->vfs_ops.mkdir(dos_to_unix(fname,False), - unix_mode(conn,aDIR)) < 0) { - DEBUG(0,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); - return -1; - } + if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { + errno = EEXIST; /* Setup so correct error is returned to client. */ + return -1; + } + + if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) { + + if (got_stat) { + + if(!S_ISDIR(st.st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + errno = EACCES; + return -1; + } + *action = FILE_WAS_OPENED; + + } else { + + /* + * Try and create the directory. + */ + + if(!CAN_WRITE(conn)) { + DEBUG(2,("open_directory: failing create on read-only share\n")); + errno = EACCES; + return -1; + } - *action = FILE_WAS_CREATED; + if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 0) { + DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + *action = FILE_WAS_CREATED; + + } } else { + /* - * Check that it *was* a directory. + * Don't create - just check that it *was* a directory. */ - if(conn->vfs_ops.stat(dos_to_unix(fname,False), &st) < 0) { + if(!got_stat) { DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -1050,6 +1169,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, DEBUG(0,("open_directory: %s is not a directory !\n", fname )); return -1; } + *action = FILE_WAS_OPENED; } @@ -1068,17 +1188,16 @@ int open_directory(files_struct *fsp,connection_struct *conn, fsp->size = 0; fsp->pos = -1; fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; fsp->share_mode = 0; fsp->print_file = False; fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; + fsp->directory_delete_on_close = False; fsp->conn = conn; /* * Note that the file name here is the *untranslated* name @@ -1093,10 +1212,9 @@ int open_directory(files_struct *fsp,connection_struct *conn, return 0; } - /******************************************************************* -check if the share mode on a file allows it to be deleted or unlinked -return True if sharing doesn't prevent the operation + Check if the share mode on a file allows it to be deleted or unlinked. + Return True if sharing doesn't prevent the operation. ********************************************************************/ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) @@ -1107,14 +1225,14 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) int num_share_modes; SMB_STRUCT_STAT sbuf; int token; - int pid = getpid(); + pid_t pid = getpid(); SMB_DEV_T dev; SMB_INO_T inode; if(!lp_share_modes(SNUM(conn))) return True; - if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) return(True); + if (dos_stat(fname,&sbuf) == -1) return(True); dev = sbuf.st_dev; inode = sbuf.st_ino; @@ -1144,9 +1262,16 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) * Check if someone has an oplock on this file. If so we must * break it before continuing. */ - if(share_entry->op_type & BATCH_OPLOCK) + if(BATCH_OPLOCK_TYPE(share_entry->op_type)) { +#if 0 + +/* JRA. Try removing this code to see if the new oplock changes + fix the problem. I'm dubious, but Andrew is recommending we + try this.... +*/ + /* * It appears that the NT redirector may have a bug, in that * it tries to do an SMBmv on a file that it has open with a @@ -1176,6 +1301,7 @@ batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (do continue; } else +#endif /* 0 */ { DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 99fe7a69fa..a64dd2d0ef 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -26,18 +26,30 @@ extern int DEBUGLEVEL; /* Oplock ipc UDP socket. */ static int oplock_sock = -1; uint16 global_oplock_port = 0; -#if defined(HAVE_KERNEL_OPLOCKS) static int oplock_pipe_read = -1; + +#if defined(HAVE_KERNEL_OPLOCKS) static int oplock_pipe_write = -1; -#endif /* HAVE_KERNEL_OPLOCKS */ +#endif /* Current number of oplocks we have outstanding. */ -int32 global_oplocks_open = 0; +static int32 exclusive_oplocks_open = 0; +static int32 level_II_oplocks_open = 0; +BOOL global_client_failed_oplock_break = False; BOOL global_oplock_break = False; extern int smb_read_error; -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval); +static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, BOOL local); + +/**************************************************************************** + Get the number of current exclusive oplocks. +****************************************************************************/ + +int32 get_number_of_exclusive_open_oplocks(void) +{ + return exclusive_oplocks_open; +} /**************************************************************************** Setup the kernel level oplock backchannel for this process. @@ -63,8 +75,9 @@ BOOL setup_kernel_oplock_pipe(void) } /**************************************************************************** - open the oplock IPC socket communication + Open the oplock IPC socket communication. ****************************************************************************/ + BOOL open_oplock_ipc(void) { struct sockaddr_in sock_name; @@ -73,7 +86,7 @@ BOOL open_oplock_ipc(void) DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK)); + oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK),False); if (oplock_sock == -1) { DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ @@ -127,15 +140,13 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou int selrtn; int maxfd = oplock_sock; -#if defined(HAVE_KERNEL_OPLOCKS) - if(lp_kernel_oplocks()) + if(lp_kernel_oplocks() && (oplock_pipe_read != -1)) maxfd = MAX(maxfd, oplock_pipe_read); -#endif /* HAVE_KERNEL_OPLOCKS */ to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(maxfd+1,fds,NULL, &to); + selrtn = sys_select(maxfd+1,fds,&to); /* Check if error */ if(selrtn == -1) { @@ -196,7 +207,7 @@ Error was %s.\n", strerror(errno) )); } dev = (SMB_DEV_T)os.os_dev; - inode = (SMB_DEV_T)os.os_ino; + inode = (SMB_INO_T)os.os_ino; DEBUG(5,("receive_local_message: kernel oplock break request received for \ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); @@ -212,14 +223,9 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); buffer += OPBRK_CMD_HEADER_LEN; SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - SIVAL(buffer,KERNEL_OPLOCK_BREAK_DEV_OFFSET,dev); -#ifdef LARGE_SMB_INO_T - SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET,inode & 0xFFFFFFFF); - SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET+4, (inode >> 32 ) & 0xFFFFFFFF ); -#else /* LARGE_SMB_INO_T */ - SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET,inode); -#endif /* LARGE_SMB_INO_T */ + memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); return True; } @@ -265,11 +271,11 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); } /**************************************************************************** - Attempt to set an oplock on a file. Always succeeds if kernel oplocks are - disabled (just sets flags). Returns True if oplock set. + Attempt to set an kernel oplock on a file. Always returns True if kernel + oplocks not available. ****************************************************************************/ -BOOL set_file_oplock(files_struct *fsp) +static BOOL set_kernel_oplock(files_struct *fsp, int oplock_type) { #if defined(HAVE_KERNEL_OPLOCKS) if(lp_kernel_oplocks()) { @@ -293,23 +299,38 @@ inode = %.0f. Another process had the file open.\n", } #endif /* HAVE_KERNEL_OPLOCKS */ + return True; +} - DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f\n", - fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode)); +/**************************************************************************** + Attempt to set an oplock on a file. Always succeeds if kernel oplocks are + disabled (just sets flags). Returns True if oplock set. +****************************************************************************/ - fsp->granted_oplock = True; - fsp->sent_oplock_break = False; - global_oplocks_open++; +BOOL set_file_oplock(files_struct *fsp, int oplock_type) +{ + if (!set_kernel_oplock(fsp, oplock_type)) + return False; + + fsp->oplock_type = oplock_type; + fsp->sent_oplock_break = NO_BREAK_SENT; + if ( oplock_type == LEVEL_II_OPLOCK) + level_II_oplocks_open++; + else + exclusive_oplocks_open++; + + DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", + fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, + (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); return True; } /**************************************************************************** - Attempt to release an oplock on a file. Always succeeds if kernel oplocks are - disabled (just clears flags). + Release a kernel oplock on a file. ****************************************************************************/ -static void release_file_oplock(files_struct *fsp) +static void release_kernel_oplock(files_struct *fsp) { #if defined(HAVE_KERNEL_OPLOCKS) @@ -322,20 +343,20 @@ static void release_file_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fd_ptr->fd, F_OPLKACK, -1); - dbgtext("release_file_oplock: file %s, dev = %x, inode = %.0f has kernel \ + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, state ); } /* - * Remote the kernel oplock on this file. + * Remove the kernel oplock on this file. */ if(fcntl(fsp->fd_ptr->fd, F_OPLKACK, OP_REVOKE) < 0) { if( DEBUGLVL( 0 )) { - dbgtext("release_file_oplock: Error when removing kernel oplock on file " ); + dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, strerror(errno) ); @@ -343,10 +364,91 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, } } #endif /* HAVE_KERNEL_OPLOCKS */ +} + + +/**************************************************************************** + Attempt to release an oplock on a file. Decrements oplock count. +****************************************************************************/ + +void release_file_oplock(files_struct *fsp) +{ + release_kernel_oplock(fsp); + + if (fsp->oplock_type == LEVEL_II_OPLOCK) + level_II_oplocks_open--; + else + exclusive_oplocks_open--; + + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; + + flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH); +} + +/**************************************************************************** + Attempt to downgrade an oplock on a file. Doesn't decrement oplock count. +****************************************************************************/ + +static void downgrade_file_oplock(files_struct *fsp) +{ + release_kernel_oplock(fsp); + fsp->oplock_type = LEVEL_II_OPLOCK; + exclusive_oplocks_open--; + level_II_oplocks_open++; + fsp->sent_oplock_break = NO_BREAK_SENT; +} + +/**************************************************************************** + Remove a file oplock. Copes with level II and exclusive. + Locks then unlocks the share mode lock. +****************************************************************************/ + +BOOL remove_oplock(files_struct *fsp) +{ + int token; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; + BOOL ret = True; + + /* Remove the oplock flag from the sharemode. */ + if (lock_share_entry(fsp->conn, dev, inode, &token) == False) { + DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", + fsp->fsp_name )); + ret = False; + } + + if (fsp->sent_oplock_break == EXCLUSIVE_BREAK_SENT) { + + /* + * Deal with a reply when a break-to-none was sent. + */ + + if(remove_share_oplock(token, fsp)==False) { + DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \ +dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); + ret = False; + } + + release_file_oplock(fsp); + + } else { + + /* + * Deal with a reply when a break-to-level II was sent. + */ + + if(downgrade_share_oplock(token, fsp)==False) { + DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \ +dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); + ret = False; + } - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; - global_oplocks_open--; + downgrade_file_oplock(fsp); + } + + unlock_share_entry(fsp->conn, dev, inode, token); + return ret; } /**************************************************************************** @@ -358,14 +460,16 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, int setup_oplock_select_set( fd_set *fds) { int maxfd = oplock_sock; + + if(oplock_sock == -1) + return 0; + FD_SET(oplock_sock,fds); -#if defined(HAVE_KERNEL_OPLOCKS) - if(lp_kernel_oplocks()) { + if(lp_kernel_oplocks() && (oplock_pipe_read != -1)) { FD_SET(oplock_pipe_read,fds); maxfd = MAX(maxfd,oplock_pipe_read); } -#endif /* HAVE_KERNEL_OPLOCKS */ return maxfd; } @@ -382,9 +486,10 @@ BOOL process_local_message(char *buffer, int buf_size) char *msg_start; SMB_DEV_T dev; SMB_INO_T inode; - uint32 remotepid; + pid_t remotepid; struct timeval tval; struct timeval *ptval = NULL; + uint16 break_cmd_type; msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET); from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET); @@ -398,7 +503,9 @@ BOOL process_local_message(char *buffer, int buf_size) * Pull the info out of the requesting packet. */ - switch(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET)) + break_cmd_type = SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET); + + switch(break_cmd_type) { #if defined(HAVE_KERNEL_OPLOCKS) case KERNEL_OPLOCK_BREAK_CMD: @@ -410,18 +517,8 @@ should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); return False; } { - /* - * Warning - beware of SMB_INO_T <> 4 bytes. !! - */ -#ifdef LARGE_SMB_INO_T - SMB_INO_T inode_low = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET); - SMB_INO_T inode_high = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET + 4); - inode = inode_low | (inode_high << 32); -#else /* LARGE_SMB_INO_T */ - inode = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET); -#endif /* LARGE_SMB_INO_T */ - - dev = IVAL(msg_start,KERNEL_OPLOCK_BREAK_DEV_OFFSET); + memcpy((char *)&inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(inode)); + memcpy((char *)&dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(dev)); ptval = NULL; @@ -432,36 +529,34 @@ file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); #endif /* HAVE_KERNEL_OPLOCKS */ case OPLOCK_BREAK_CMD: + case LEVEL_II_OPLOCK_BREAK_CMD: + /* Ensure that the msg length is correct. */ if(msg_len != OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); + DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, should be %d).\n", + (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); return False; } { - /* - * Warning - beware of SMB_INO_T <> 4 bytes. !! - */ -#ifdef LARGE_SMB_INO_T - SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); - SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4); - inode = inode_low | (inode_high << 32); -#else /* LARGE_SMB_INO_T */ - inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); -#endif /* LARGE_SMB_INO_T */ + long usec; + time_t sec; - dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - - tval.tv_sec = (time_t)IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); - tval.tv_usec = (long)IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); + memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); + memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); + memcpy((char *)&sec, msg_start+OPLOCK_BREAK_SEC_OFFSET,sizeof(sec)); + tval.tv_sec = sec; + memcpy((char *)&usec, msg_start+OPLOCK_BREAK_USEC_OFFSET, sizeof(usec)); + tval.tv_usec = usec; ptval = &tval; - remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); - DEBUG(5,("process_local_message: oplock break request from \ -pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); + DEBUG(5,("process_local_message: (%s) oplock break request from \ +pid %d, port %d, dev = %x, inode = %.0f\n", + (break_cmd_type == OPLOCK_BREAK_CMD) ? "exclusive" : "level II", + (int)remotepid, from_port, (unsigned int)dev, (double)inode)); } break; @@ -475,27 +570,17 @@ reply - dumping info.\n")); if(msg_len != OPLOCK_BREAK_MSG_LEN) { DEBUG(0,("process_local_message: ubr: incorrect length for reply \ -(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); +(was %d, should be %d).\n", (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); return False; } { - /* - * Warning - beware of SMB_INO_T <> 4 bytes. !! - */ -#ifdef LARGE_SMB_INO_T - SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); - SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4); - inode = inode_low | (inode_high << 32); -#else /* LARGE_SMB_INO_T */ - inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); -#endif /* LARGE_SMB_INO_T */ - - remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); + memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); + memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode)); +pid %d, port %d, dev = %x, inode = %.0f\n", (int)remotepid, from_port, (unsigned int)dev, (double)inode)); } return False; @@ -510,9 +595,9 @@ pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int) * Now actually process the break request. */ - if(global_oplocks_open != 0) + if((exclusive_oplocks_open + level_II_oplocks_open) != 0) { - if(oplock_break(dev, inode, ptval) == False) + if (oplock_break(dev, inode, ptval, False) == False) { DEBUG(0,("process_local_message: oplock break failed.\n")); return False; @@ -531,7 +616,7 @@ oplocks. Returning success.\n")); } /* - * Do the appropriate reply - none in the kernel case. + * Do the appropriate reply - none in the kernel or level II case. */ if(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET) == OPLOCK_BREAK_CMD) @@ -541,7 +626,7 @@ oplocks. Returning success.\n")); /* Send the message back after OR'ing in the 'REPLY' bit. */ SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); - bzero((char *)&toaddr,sizeof(toaddr)); + memset((char *)&toaddr,'\0',sizeof(toaddr)); toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); toaddr.sin_port = htons(from_port); toaddr.sin_family = AF_INET; @@ -550,40 +635,77 @@ oplocks. Returning success.\n")); (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", - remotepid, strerror(errno))); + (int)remotepid, strerror(errno))); return False; } DEBUG(5,("process_local_message: oplock break reply sent to \ pid %d, port %d, for file dev = %x, inode = %.0f\n", - remotepid, from_port, (unsigned int)dev, (double)inode)); + (int)remotepid, from_port, (unsigned int)dev, (double)inode)); } return True; } /**************************************************************************** - Process an oplock break directly. + Set up an oplock break message. ****************************************************************************/ -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) +static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) +{ + memset(outbuf,'\0',smb_size); + set_message(outbuf,8,0,True); + + SCVAL(outbuf,smb_com,SMBlockingX); + SSVAL(outbuf,smb_tid,fsp->conn->cnum); + SSVAL(outbuf,smb_pid,0xFFFF); + SSVAL(outbuf,smb_uid,0); + SSVAL(outbuf,smb_mid,0xFFFF); + SCVAL(outbuf,smb_vwv0,0xFF); + SSVAL(outbuf,smb_vwv2,fsp->fnum); + SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); + SCVAL(outbuf,smb_vwv3+1,level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); +} + +/**************************************************************************** + Function to do the waiting before sending a local break. +****************************************************************************/ + +static void wait_before_sending_break(BOOL local_request) +{ + extern struct timeval smb_last_time; + + if(local_request) { + struct timeval cur_tv; + long wait_left = (long)lp_oplock_break_wait_time(); + + GetTimeOfDay(&cur_tv); + + wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) + + ((cur_tv.tv_usec - smb_last_time.tv_usec)/1000); + + if(wait_left > 0) { + wait_left = MIN(wait_left, 1000); + sys_usleep(wait_left * 1000); + } + } +} + +/**************************************************************************** + Ensure that we have a valid oplock. +****************************************************************************/ + +static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { - extern struct current_user current_user; - extern int Client; - char *inbuf = NULL; - char *outbuf = NULL; files_struct *fsp = NULL; - time_t start_time; - BOOL shutdown_server = False; - connection_struct *saved_conn; - int saved_vuid; - pstring saved_dir; - int break_counter = OPLOCK_BREAK_RESENDS; if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break: called for dev = %x, inode = %.0f.\n", (unsigned int)dev, (double)inode ); - dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); + dbgtext( "initial_break_processing: called for dev = %x, inode = %.0f tv_sec = %x, tv_usec = %x.\n", + (unsigned int)dev, (double)inode, tval ? (int)tval->tv_sec : 0, + tval ? (int)tval->tv_usec : 0); + dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", + exclusive_oplocks_open, level_II_oplocks_open ); } /* We need to search the file open table for the @@ -594,13 +716,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if(fsp == NULL) { /* The file could have been closed in the meantime - return success. */ - if( DEBUGLVL( 0 ) ) + if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break: cannot find open file with " ); + dbgtext( "initial_break_processing: cannot find open file with " ); dbgtext( "dev = %x, inode = %.0f ", (unsigned int)dev, (double)inode); dbgtext( "allowing break to succeed.\n" ); } - return True; + return NULL; } /* Ensure we have an oplock on the file */ @@ -612,18 +734,130 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) as we may have just freed it. */ - if(!fsp->granted_oplock) + if(fsp->oplock_type == NO_OPLOCK) { - if( DEBUGLVL( 0 ) ) + if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break: file %s ", fsp->fsp_name ); + dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); dbgtext( "(dev = %x, inode = %.0f) has no oplock.\n", (unsigned int)dev, (double)inode ); dbgtext( "Allowing break to succeed regardless.\n" ); } - return True; + return NULL; } - /* mark the oplock break as sent - we don't want to send twice! */ + return fsp; +} + +/**************************************************************************** + Process a level II oplock break directly. +****************************************************************************/ + +BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) +{ + extern int Client; + extern uint32 global_client_caps; + char outbuf[128]; + BOOL got_lock = False; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; + + /* + * We can have a level II oplock even if the client is not + * level II oplock aware. In this case just remove the + * flags and don't send the break-to-none message to + * the client. + */ + + if (global_client_caps & CAP_LEVEL_II_OPLOCKS) { + /* + * If we are sending an oplock break due to an SMB sent + * by our own client we ensure that we wait at leat + * lp_oplock_break_wait_time() milliseconds before sending + * the packet. Sending the packet sooner can break Win9x + * and has reported to cause problems on NT. JRA. + */ + + wait_before_sending_break(local_request); + + /* Prepare the SMBlockingX message. */ + + prepare_break_message( outbuf, fsp, False); + send_smb(Client, outbuf); + } + + /* + * Now we must update the shared memory structure to tell + * everyone else we no longer have a level II oplock on + * this open file. If local_request is true then token is + * the existing lock on the shared memory area. + */ + + if(!local_request && lock_share_entry(fsp->conn, dev, inode, &token) == False) { + DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); + } else { + got_lock = True; + } + + if(remove_share_oplock(token, fsp)==False) { + DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); + } + + if (!local_request && got_lock) + unlock_share_entry(fsp->conn, dev, inode, token); + + fsp->oplock_type = NO_OPLOCK; + level_II_oplocks_open--; + + if(level_II_oplocks_open < 0) + { + DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", + level_II_oplocks_open)); + abort(); + } + + if( DEBUGLVL( 3 ) ) + { + dbgtext( "oplock_break_level2: returning success for " ); + dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); + dbgtext( "Current level II oplocks_open = %d\n", level_II_oplocks_open ); + } + + return True; +} + +/**************************************************************************** + Process an oplock break directly. +****************************************************************************/ + +static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, BOOL local_request) +{ + extern uint32 global_client_caps; + extern struct current_user current_user; + extern int Client; + char *inbuf = NULL; + char *outbuf = NULL; + files_struct *fsp = NULL; + time_t start_time; + BOOL shutdown_server = False; + BOOL oplock_timeout = False; + connection_struct *saved_conn; + int saved_vuid; + pstring saved_dir; + int timeout = (OPLOCK_BREAK_TIMEOUT * 1000); + pstring file_name; + BOOL using_levelII; + + if((fsp = initial_break_processing(dev, inode, tval)) == NULL) + return True; + + /* + * Deal with a level II oplock going break to none separately. + */ + + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + return oplock_break_level2(fsp, local_request, -1); + + /* Mark the oplock break as sent - we don't want to send twice! */ if (fsp->sent_oplock_break) { if( DEBUGLVL( 0 ) ) @@ -641,6 +875,11 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) return False; } + if(global_oplock_break) { + DEBUG(0,("ABORT : ABORT : recursion in oplock_break !!!!!\n")); + abort(); + } + /* Now comes the horrid part. We must send an oplock break to the client, and then process incoming messages until we get a close or oplock release. At this point we know we need a new inbuf/outbuf buffer pair. @@ -662,25 +901,30 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) return False; } + /* + * If we are sending an oplock break due to an SMB sent + * by our own client we ensure that we wait at leat + * lp_oplock_break_wait_time() milliseconds before sending + * the packet. Sending the packet sooner can break Win9x + * and has reported to cause problems on NT. JRA. + */ + + wait_before_sending_break(local_request); + /* Prepare the SMBlockingX message. */ - bzero(outbuf,smb_size); - set_message(outbuf,8,0,True); - SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->conn->cnum); - SSVAL(outbuf,smb_pid,0xFFFF); - SSVAL(outbuf,smb_uid,0); - SSVAL(outbuf,smb_mid,0xFFFF); - SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fsp->fnum); - SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); - /* Change this when we have level II oplocks. */ - SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE); - - send_smb(Client, outbuf); + if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && !lp_kernel_oplocks() && lp_level2_oplocks(SNUM(fsp->conn))) { + using_levelII = True; + } else { + using_levelII = False; + } + + prepare_break_message( outbuf, fsp, using_levelII); + /* Remember if we just sent a break to level II on this file. */ + fsp->sent_oplock_break = using_levelII? + LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - /* Remember we just sent an oplock break on this file. */ - fsp->sent_oplock_break = True; + send_smb(Client, outbuf); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; @@ -703,40 +947,39 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) /* Save the chain fnum. */ file_chain_save(); - while(OPEN_FSP(fsp) && fsp->granted_oplock) - { - if(receive_smb(Client,inbuf, - (OPLOCK_BREAK_TIMEOUT/OPLOCK_BREAK_RESENDS) * 1000) == False) - { + /* + * From Charles Hoch . If the break processing + * code closes the file (as it often does), then the fsp pointer here + * points to free()'d memory. We *must* revalidate fsp each time + * around the loop. + */ - /* Isaac suggestd that if a MS client doesn't respond to a - oplock break request then we might try resending - it. Certainly it's no worse than just dropping the - socket! */ - if (smb_read_error == READ_TIMEOUT && break_counter--) { - DEBUG(2, ( "oplock_break resend\n" ) ); - send_smb(Client, outbuf); - continue; - } + pstrcpy(file_name, fsp->fsp_name); + while((fsp = initial_break_processing(dev, inode, tval)) && + OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + { + if(receive_smb(Client,inbuf, timeout) == False) + { /* * Die if we got an error. */ - if (smb_read_error == READ_EOF) + if (smb_read_error == READ_EOF) { DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); - - if (smb_read_error == READ_ERROR) + shutdown_server = True; + } else if (smb_read_error == READ_ERROR) { DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); - - if (smb_read_error == READ_TIMEOUT) + shutdown_server = True; + } else if (smb_read_error == READ_TIMEOUT) { DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); + oplock_timeout = True; + } - DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) ); + DEBUGADD( 0, ( "oplock_break failed for file %s ", file_name ) ); DEBUGADD( 0, ( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode)); - shutdown_server = True; break; } @@ -758,13 +1001,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) { if( DEBUGLVL( 0 ) ) - { + { dbgtext( "oplock_break: no break received from client " ); dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); dbgtext( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode ); - } - shutdown_server = True; + } + oplock_timeout = True; break; } } @@ -796,7 +1039,21 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) global_oplock_break = False; /* - * If the client did not respond we must die. + * If the client timed out then clear the oplock (or go to level II) + * and continue. This seems to be what NT does and is better than dropping + * the connection. + */ + + if(oplock_timeout && (fsp = initial_break_processing(dev, inode, tval)) && + OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + { + DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name)); + remove_oplock(fsp); + global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */ + } + + /* + * If the client had an error we must die. */ if(shutdown_server) @@ -808,27 +1065,19 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) exit_server("oplock break failure"); } - if(OPEN_FSP(fsp)) - { - /* The lockingX reply will have removed the oplock flag - from the sharemode. */ - release_file_oplock(fsp); - } - /* Santity check - remove this later. JRA */ - if(global_oplocks_open < 0) + if(exclusive_oplocks_open < 0) { - DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", - global_oplocks_open)); - exit_server("oplock_break: global_oplocks_open < 0"); + DEBUG(0,("oplock_break: exclusive_oplocks_open < 0 (%d). PANIC ERROR\n", + exclusive_oplocks_open)); + abort(); } - if( DEBUGLVL( 3 ) ) { dbgtext( "oplock_break: returning success for " ); dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); - dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open ); + dbgtext( "Current exclusive_oplocks_open = %d\n", exclusive_oplocks_open ); } return True; @@ -844,9 +1093,11 @@ BOOL request_oplock_break(share_mode_entry *share_entry, { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; - int pid = getpid(); + pid_t pid = getpid(); time_t start_time; int time_left; + long usec; + time_t sec; if(pid == share_entry->pid) { @@ -854,36 +1105,34 @@ BOOL request_oplock_break(share_mode_entry *share_entry, if(share_entry->op_port != global_oplock_port) { DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ -should be %d\n", pid, share_entry->op_port, global_oplock_port)); +should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); return False; } DEBUG(5,("request_oplock_break: breaking our own oplock\n")); /* Call oplock break direct. */ - return oplock_break(dev, inode, &share_entry->time); + return oplock_break(dev, inode, &share_entry->time, True); } /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); - SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); - SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); - SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); - SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); - /* - * WARNING - beware of SMB_INO_T <> 4 bytes. - */ -#ifdef LARGE_SMB_INO_T - SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,(inode & 0xFFFFFFFFL)); - SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET+4,((inode >> 32) & 0xFFFFFFFFL)); -#else /* LARGE_SMB_INO_T */ - SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); -#endif /* LARGE_SMB_INO_T */ + if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,LEVEL_II_OPLOCK_BREAK_CMD); + } else { + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); + } + memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); + sec = (time_t)share_entry->time.tv_sec; + memcpy(op_break_msg+OPLOCK_BREAK_SEC_OFFSET,(char *)&sec,sizeof(sec)); + usec = (long)share_entry->time.tv_usec; + memcpy(op_break_msg+OPLOCK_BREAK_USEC_OFFSET,(char *)&usec,sizeof(usec)); + memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); + memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); /* set the address and port */ - bzero((char *)&addr_out,sizeof(addr_out)); + memset((char *)&addr_out,'\0',sizeof(addr_out)); addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr_out.sin_port = htons( share_entry->op_port ); addr_out.sin_family = AF_INET; @@ -891,8 +1140,11 @@ should be %d\n", pid, share_entry->op_port, global_oplock_port)); if( DEBUGLVL( 3 ) ) { dbgtext( "request_oplock_break: sending a oplock break message to " ); - dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); + dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", + (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, + (int)share_entry->time.tv_usec ); + } if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, @@ -901,14 +1153,26 @@ should be %d\n", pid, share_entry->op_port, global_oplock_port)); if( DEBUGLVL( 0 ) ) { dbgtext( "request_oplock_break: failed when sending a oplock " ); - dbgtext( "break message to pid %d ", share_entry->pid ); + dbgtext( "break message to pid %d ", (int)share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); + dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", + (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, + (int)share_entry->time.tv_usec ); dbgtext( "Error was %s\n", strerror(errno) ); } return False; } + /* + * If we just sent a message to a level II oplock share entry then + * we are done and may return. + */ + + if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + DEBUG(3,("request_oplock_break: sent break message to level II entry.\n")); + return True; + } + /* * Now we must await the oplock broken message coming back * from the target smbd process. Timeout if it fails to @@ -929,10 +1193,8 @@ should be %d\n", pid, share_entry->op_port, global_oplock_port)); FD_ZERO(&fds); FD_SET(oplock_sock,&fds); -#if defined(HAVE_KERNEL_OPLOCKS) - if(lp_kernel_oplocks()) + if(lp_kernel_oplocks() && (oplock_pipe_read != -1)) FD_SET(oplock_pipe_read,&fds); -#endif /* HAVE_KERNEL_OPLOCKS */ if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply), time_left ? time_left * 1000 : 1) == False) @@ -942,9 +1204,12 @@ should be %d\n", pid, share_entry->op_port, global_oplock_port)); if( DEBUGLVL( 0 ) ) { dbgtext( "request_oplock_break: no response received to oplock " ); - dbgtext( "break request to pid %d ", share_entry->pid ); + dbgtext( "break request to pid %d ", (int)share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); + dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", + (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, + (int)share_entry->time.tv_usec ); } /* @@ -960,9 +1225,11 @@ should be %d\n", pid, share_entry->op_port, global_oplock_port)); if( DEBUGLVL( 0 ) ) { dbgtext( "request_oplock_break: error in response received " ); - dbgtext( "to oplock break request to pid %d ", share_entry->pid ); + dbgtext( "to oplock break request to pid %d ", (int)share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); + dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", + (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, + (int)share_entry->time.tv_usec ); dbgtext( "Error was (%s).\n", strerror(errno) ); } return False; @@ -1036,16 +1303,17 @@ should be %d\n", pid, share_entry->op_port, global_oplock_port)); Used as a last ditch attempt to free a space in the file table when we have run out. ****************************************************************************/ + BOOL attempt_close_oplocked_file(files_struct *fsp) { DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break && (fsp->fd_ptr != NULL)) { + if (fsp->open && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd_ptr != NULL)) { /* Try and break the oplock. */ file_fd_struct *fd_ptr = fsp->fd_ptr; - if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time)) { + if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time, True)) { if(!fsp->open) /* Did the oplock break close the file ? */ return True; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e15e08a1af..9792c9ebc8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -23,6 +23,7 @@ extern int DEBUGLEVEL; extern int Protocol; +extern struct in_addr ipzero; /* users from session setup */ static pstring session_users=""; @@ -31,6 +32,261 @@ extern pstring scope; extern pstring global_myname; extern fstring global_myworkgroup; +/* Data to do lanman1/2 password challenge. */ +static unsigned char saved_challenge[8]; +static BOOL challenge_sent=False; + +/******************************************************************* +Get the next challenge value - no repeats. +********************************************************************/ +void generate_next_challenge(char *challenge) +{ +#if 0 + /* + * Leave this ifdef'd out while we test + * the new crypto random number generator. + * JRA. + */ + unsigned char buf[16]; + static int counter = 0; + struct timeval tval; + int v1,v2; + + /* get a sort-of random number */ + GetTimeOfDay(&tval); + v1 = (counter++) + getpid() + tval.tv_sec; + v2 = (counter++) * getpid() + tval.tv_usec; + SIVAL(challenge,0,v1); + SIVAL(challenge,4,v2); + + /* mash it up with md4 */ + mdfour(buf, (unsigned char *)challenge, 8); +#else + unsigned char buf[8]; + + generate_random_buffer(buf,8,False); +#endif + memcpy(saved_challenge, buf, 8); + memcpy(challenge,buf,8); + challenge_sent = True; +} + +/******************************************************************* +set the last challenge sent, usually from a password server +********************************************************************/ +BOOL set_challenge(unsigned char *challenge) +{ + memcpy(saved_challenge,challenge,8); + challenge_sent = True; + return(True); +} + +/******************************************************************* +get the last challenge sent +********************************************************************/ +static BOOL last_challenge(unsigned char *challenge) +{ + if (!challenge_sent) return(False); + memcpy(challenge,saved_challenge,8); + return(True); +} + +/* this holds info on user ids that are already validated for this VC */ +static user_struct *validated_users = NULL; +static int num_validated_users = 0; + +/**************************************************************************** +check if a uid has been validated, and return an pointer to the user_struct +if it has. NULL if not. vuid is biased by an offset. This allows us to +tell random client vuid's (normally zero) from valid vuids. +****************************************************************************/ +user_struct *get_valid_user_struct(uint16 vuid) +{ + if (vuid == UID_FIELD_INVALID) + return NULL; + vuid -= VUID_OFFSET; + if ((vuid >= (uint16)num_validated_users) || + (validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1)) + return NULL; + return &validated_users[vuid]; +} + +/**************************************************************************** +invalidate a uid +****************************************************************************/ +void invalidate_vuid(uint16 vuid) +{ + user_struct *vuser = get_valid_user_struct(vuid); + + if (vuser == NULL) return; + + vuser->uid = (uid_t)-1; + vuser->gid = (gid_t)-1; + + vuser->n_sids = 0; + + /* same number of igroups as groups */ + vuser->n_groups = 0; + + if (vuser->groups) + free((char *)vuser->groups); + + if (vuser->sids) + free((char *)vuser->sids); + + vuser->sids = NULL; + vuser->groups = NULL; +} + + +/**************************************************************************** +return a validated username +****************************************************************************/ +char *validated_username(uint16 vuid) +{ + user_struct *vuser = get_valid_user_struct(vuid); + if (vuser == NULL) + return 0; + return(vuser->name); +} + + +/**************************************************************************** +Setup the groups a user belongs to. +****************************************************************************/ +int setup_groups(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)) + { + DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); + if (getuid() == 0) + { + if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) + { + 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; + } + +#ifdef NGROUPS_MAX + if((groups = (gid_t *)malloc(sizeof(gid_t)*NGROUPS_MAX)) == NULL) +#else /* NGROUPS_MAX */ + if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) +#endif /* NGROUPS_MAX */ + { + DEBUG(0,("setup_groups 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; +} + + +/**************************************************************************** +register a uid/name pair as being valid and that a valid password +has been given. vuid is biased by an offset. This allows us to +tell random client vuid's (normally zero) from valid vuids. +****************************************************************************/ +uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest) +{ + user_struct *vuser; + struct passwd *pwfile; /* for getting real name from passwd file */ + + /* Ensure no vuid gets registered in share level security. */ + if(lp_security() == SEC_SHARE) + return UID_FIELD_INVALID; + +#if 0 + /* + * After observing MS-Exchange services writing to a Samba share + * I belive this code is incorrect. Each service does its own + * sessionsetup_and_X for the same user, and as each service shuts + * down, it does a user_logoff_and_X. As we are consolidating multiple + * sessionsetup_and_X's onto the same vuid here, when the first service + * shuts down, it invalidates all the open files for the other services. + * Hence I am removing this code and forcing each sessionsetup_and_X + * to get a new vuid. + * Jeremy Allison. (jallison@whistle.com). + */ + + int i; + for(i = 0; i < num_validated_users; i++) { + vuser = &validated_users[i]; + if ( vuser->uid == uid ) + return (uint16)(i + VUID_OFFSET); /* User already validated */ + } +#endif + + validated_users = (user_struct *)Realloc(validated_users, + sizeof(user_struct)* + (num_validated_users+1)); + + if (!validated_users) + { + DEBUG(0,("Failed to realloc users struct!\n")); + num_validated_users = 0; + return UID_FIELD_INVALID; + } + + vuser = &validated_users[num_validated_users]; + num_validated_users++; + + vuser->uid = uid; + vuser->gid = gid; + vuser->guest = guest; + fstrcpy(vuser->name,unix_name); + fstrcpy(vuser->requested_name,requested_name); + + vuser->n_sids = 0; + vuser->sids = NULL; + + vuser->n_groups = 0; + vuser->groups = NULL; + + /* Find all the groups this uid is in and store them. + Used by become_user() */ + setup_groups(unix_name,uid,gid, + &vuser->n_groups, + &vuser->groups); + + DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); + + DEBUG(3, ("Clearing default real name\n")); + fstrcpy(vuser->real_name, "\0"); + if (lp_unix_realname()) { + if ((pwfile=sys_getpwnam(vuser->name))!= NULL) + { + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); + fstrcpy(vuser->real_name, pwfile->pw_gecos); + } + } + + return (uint16)((num_validated_users - 1) + VUID_OFFSET); +} + /**************************************************************************** add a name to the session users list @@ -71,12 +327,17 @@ static BOOL update_smbpassword_file(char *user, char *password) DEBUG(0,("getsmbpwnam returned NULL\n")); return False; } - + + /* + * Remove the account disabled flag - we are updating the + * users password from a login. + */ + smbpw->acct_ctrl &= ~ACB_DISABLED; + /* Here, the flag is one, because we want to ignore the XXXXXXX'd out password */ ret = change_oem_password( smbpw, password, True); - if (!ret) - { + if (ret == False) { DEBUG(3,("change_oem_password returned False\n")); } @@ -87,17 +348,202 @@ static BOOL update_smbpassword_file(char *user, char *password) +/**************************************************************************** +core of smb password checking routine. +****************************************************************************/ +BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8) +{ + /* Finish the encryption of part_passwd. */ + unsigned char p21[21]; + unsigned char p24[24]; + + if (part_passwd == NULL) + DEBUG(10,("No password set - allowing access\n")); + /* No password set - always true ! */ + if (part_passwd == NULL) + return 1; + + memset(p21,'\0',21); + memcpy(p21,part_passwd,16); + E_P24(p21, c8, p24); +#if DEBUG_PASSWORD + { + int i; + DEBUG(100,("Part password (P16) was |")); + for(i = 0; i < 16; i++) + DEBUG(100,("%X ", (unsigned char)part_passwd[i])); + DEBUG(100,("|\n")); + DEBUG(100,("Password from client was |")); + for(i = 0; i < 24; i++) + DEBUG(100,("%X ", (unsigned char)password[i])); + DEBUG(100,("|\n")); + DEBUG(100,("Given challenge was |")); + for(i = 0; i < 8; i++) + DEBUG(100,("%X ", (unsigned char)c8[i])); + DEBUG(100,("|\n")); + DEBUG(100,("Value from encryption was |")); + for(i = 0; i < 24; i++) + DEBUG(100,("%X ", (unsigned char)p24[i])); + DEBUG(100,("|\n")); + } +#endif + return (memcmp(p24, password, 24) == 0); +} + +/**************************************************************************** + Do a specific test for an smb password being correct, given a smb_password and + the lanman and NT responses. +****************************************************************************/ +BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], + uchar lm_pass[24], uchar nt_pass[24]) +{ + uchar challenge[8]; + + if (!lm_pass || !smb_pass) return(False); + + DEBUG(4,("Checking SMB password for user %s\n", + smb_pass->smb_name)); + + if(smb_pass->acct_ctrl & ACB_DISABLED) { + DEBUG(1,("account for user %s was disabled.\n", + smb_pass->smb_name)); + return(False); + } + + if (chal == NULL) + { + DEBUG(5,("use last SMBnegprot challenge\n")); + if (!last_challenge(challenge)) + { + DEBUG(1,("no challenge done - password failed\n")); + return False; + } + } + else + { + DEBUG(5,("challenge received\n")); + memcpy(challenge, chal, 8); + } + + if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_password_check((char *)nt_pass, + (uchar *)smb_pass->smb_nt_passwd, + challenge)) { + DEBUG(4,("NT MD4 password check succeeded\n")); + return(True); + } + DEBUG(4,("NT MD4 password check failed\n")); + } + + /* Try against the lanman password. smb_pass->smb_passwd == NULL means + no password, allow access. */ + + DEBUG(4,("Checking LM MD4 password\n")); + + if((smb_pass->smb_passwd == NULL) && + (smb_pass->acct_ctrl & ACB_PWNOTREQ)) { + DEBUG(4,("no password required for user %s\n", + smb_pass->smb_name)); + return True; + } + + if((smb_pass->smb_passwd != NULL) && + smb_password_check((char *)lm_pass, + (uchar *)smb_pass->smb_passwd, challenge)) { + DEBUG(4,("LM MD4 password check succeeded\n")); + return(True); + } + + DEBUG(4,("LM MD4 password check failed\n")); + + return False; +} + + +/**************************************************************************** +check if a username/password is OK assuming the password is a 24 byte +SMB hash +return True if the password is correct, False otherwise +****************************************************************************/ + +BOOL pass_check_smb(char *user, char *domain, + uchar *chal, uchar *lm_pwd, uchar *nt_pwd, + struct passwd *pwd) +{ + struct passwd *pass; + struct smb_passwd *smb_pass; + + if (!lm_pwd || !nt_pwd) + { + return(False); + } + + if (pwd != NULL && user == NULL) + { + pass = (struct passwd *) pwd; + user = pass->pw_name; + } + else + { + pass = Get_Pwnam(user,True); + } + + if (pass == NULL) + { + DEBUG(1,("Couldn't find user '%s' in UNIX password database.\n",user)); + return(False); + } + + smb_pass = getsmbpwnam(user); + + if (smb_pass == NULL) + { + DEBUG(1,("Couldn't find user '%s' in smb_passwd file.\n", user)); + return(False); + } + + /* Quit if the account was disabled. */ + if(smb_pass->acct_ctrl & ACB_DISABLED) { + DEBUG(1,("Account for user '%s' was disabled.\n", user)); + return(False); + } + + /* Ensure the uid's match */ + if (smb_pass->smb_userid != pass->pw_uid) + { + DEBUG(0,("Error : UNIX and SMB uids in password files do not match for user '%s'!\n", user)); + return(False); + } + + if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords()) + { + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", smb_pass->smb_name)); + return(True); + } + + if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) + { + return(True); + } + + DEBUG(2,("pass_check_smb failed - invalid password for user [%s]\n", user)); + return False; +} + /**************************************************************************** check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, - uchar user_sess_key[16]) +BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) { - if (pwlen >= 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) + if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { - /* if 24 bytes or longer assume it is an encrypted password */ + /* if 24 bytes long assume it is an encrypted password */ uchar challenge[8]; if (!last_challenge(challenge)) @@ -106,10 +552,8 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, return False; } - return pass_check_smb(getsmbpwnam(user), global_myworkgroup, - challenge, (uchar *)password, - pwlen, (uchar *)password, pwlen, - pwd, user_sess_key); + return pass_check_smb(user, global_myworkgroup, + challenge, (uchar *)password, (uchar *)password, pwd); } return pass_check(user, password, pwlen, pwd, @@ -117,71 +561,84 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, update_smbpassword_file : NULL); } +/**************************************************************************** +check if a username is valid +****************************************************************************/ +BOOL user_ok(char *user,int snum) +{ + pstring valid, invalid; + BOOL ret; + + StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)-1); + StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)-1); + + pstring_sub(valid,"%S",lp_servicename(snum)); + pstring_sub(invalid,"%S",lp_servicename(snum)); + + ret = !user_in_list(user,invalid); + + if (ret && valid && *valid) { + ret = user_in_list(user,valid); + } + + if (ret && lp_onlyuser(snum)) { + char *user_list = lp_username(snum); + pstring_sub(user_list,"%S",lp_servicename(snum)); + ret = user_in_list(user,user_list); + } + + return(ret); +} + /**************************************************************************** validate a group username entry. Return the username or NULL ****************************************************************************/ -static char *validate_group(char *group,char *password,int pwlen,int snum, - uchar user_sess_key[16]) +static char *validate_group(char *group,char *password,int pwlen,int snum) { -#if defined(HAVE_NETGROUP) && defined(HAVE_GETNETGRENT) && defined(HAVE_SETNETGRENT) && defined(HAVE_ENDNETGRENT) - { - char *host, *user, *domain; - setnetgrent(group); - while (getnetgrent(&host, &user, &domain)) { - if (user) { - if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL, user_sess_key)) { - endnetgrent(); - return(user); +#ifdef HAVE_NETGROUP + { + char *host, *user, *domain; + setnetgrent(group); + while (getnetgrent(&host, &user, &domain)) { + if (user) { + if (user_ok(user, snum) && + password_ok(user,password,pwlen,NULL)) { + endnetgrent(); + return(user); + } + } + } + endnetgrent(); } - } - } - endnetgrent(); - } #endif -#ifdef HAVE_GETGRNAM - { - struct group *gptr = (struct group *)getgrnam(group); - char **member; - if (gptr) - { - member = gptr->gr_mem; - while (member && *member) - { - static fstring name; - fstrcpy(name,*member); - if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL, user_sess_key)) - return(&name[0]); - member++; - } -#ifdef GROUP_CHECK_PWENT +#ifdef HAVE_GETGRENT { - struct passwd *pwd; - static fstring tm; - - setpwent (); - while (pwd = getpwent ()) { - if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { - /* This Entry have PASSWORD and same GID then check pwd */ - if (password_ok(NULL, password, pwlen, pwd, user_sess_key)) { - fstrcpy(tm, pwd->pw_name); - endpwent (); - return tm; - } - } - } - endpwent (); + struct group *gptr; + char **member; + setgrent(); + while ((gptr = (struct group *)getgrent())) { + if (!strequal(gptr->gr_name,group)) + continue; + member = gptr->gr_mem; + while (member && *member) { + static fstring name; + fstrcpy(name,*member); + if (user_ok(name,snum) && + password_ok(name,password,pwlen,NULL)) { + endgrent(); + return(&name[0]); + } + member++; + } + } + endgrent(); } -#endif /* GROUP_CHECK_PWENT */ - } - } #endif - return(NULL); + return(NULL); } @@ -221,14 +678,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL, vuser->user_sess_key); + ok = password_ok(user,password, pwlen, NULL); if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); } /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->name,snum) && - password_ok(vuser->name, password, pwlen, NULL, vuser->user_sess_key)) { + password_ok(vuser->name, password, pwlen, NULL)) { fstrcpy(user, vuser->name); vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); @@ -242,7 +699,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, { char *auser; char *user_list = strdup(session_users); - if (!user_list) return False; + if (!user_list) return(False); for (auser=strtok(user_list,LIST_SEP); !ok && auser; @@ -252,7 +709,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstrcpy(user2,auser); if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL, vuser->user_sess_key)) { + if (password_ok(user2,password, pwlen, NULL)) { ok = True; fstrcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); @@ -283,7 +740,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, pstring user_list; StrnCpy(user_list,lp_username(snum),sizeof(pstring)); - string_sub(user_list,"%S",lp_servicename(snum)); + pstring_sub(user_list,"%S",lp_servicename(snum)); for (auser=strtok(user_list,LIST_SEP); auser && !ok; @@ -291,7 +748,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, { if (*auser == '@') { - auser = validate_group(auser+1,password,pwlen,snum, vuser->user_sess_key); + auser = validate_group(auser+1,password,pwlen,snum); if (auser) { ok = True; @@ -304,7 +761,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstring user2; fstrcpy(user2,auser); if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL, vuser->user_sess_key)) + password_ok(user2,password,pwlen,NULL)) { ok = True; fstrcpy(user,user2); @@ -454,10 +911,10 @@ BOOL check_hosts_equiv(char *user) { char *fname = NULL; pstring rhostsfile; - const struct passwd *pass = Get_Pwnam(user,True); + struct passwd *pass = Get_Pwnam(user,True); if (!pass) - return False; + return(False); fname = lp_hosts_equiv(); @@ -470,7 +927,7 @@ BOOL check_hosts_equiv(char *user) if (lp_use_rhosts()) { - char *home = get_unixhome_dir(user); + char *home = get_user_home_dir(user); if (home) { extern int Client; slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); @@ -479,13 +936,14 @@ BOOL check_hosts_equiv(char *user) } } - return False; + return(False); } /**************************************************************************** -return the client state structure + Return the client state structure. ****************************************************************************/ + struct cli_state *server_client(void) { static struct cli_state pw_cli; @@ -493,20 +951,77 @@ struct cli_state *server_client(void) } /**************************************************************************** -support for server level security + Support for server level security. ****************************************************************************/ + struct cli_state *server_cryptkey(void) { - if (cli_connect_serverlist(server_client(), lp_passwordserver())) - { - return server_client(); + struct cli_state *cli; + fstring desthost; + struct in_addr dest_ip; + char *p; + BOOL connected_ok = False; + + cli = server_client(); + + if (!cli_initialise(cli)) + return NULL; + + p = lp_passwordserver(); + while(p && next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { + standard_sub_basic(desthost); + strupper(desthost); + + if(!resolve_name( desthost, &dest_ip, 0x20)) { + DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); + continue; + } + + if (ismyip(dest_ip)) { + DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); + continue; + } + + if (cli_connect(cli, desthost, &dest_ip)) { + DEBUG(3,("connected to password server %s\n",desthost)); + connected_ok = True; + break; + } + } + + if (!connected_ok) { + DEBUG(0,("password server not available\n")); + cli_shutdown(cli); + return NULL; } - return NULL; + + if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) + return NULL; + + DEBUG(3,("got session\n")); + + if (!cli_negprot(cli)) { + DEBUG(1,("%s rejected the negprot\n",desthost)); + cli_shutdown(cli); + return NULL; + } + + if (cli->protocol < PROTOCOL_LANMAN2 || + !(cli->sec_mode & 1)) { + DEBUG(1,("%s isn't in user level security mode\n",desthost)); + cli_shutdown(cli); + return NULL; + } + + DEBUG(3,("password server OK\n")); + + return cli; } /**************************************************************************** -validate a password with the password server + Validate a password with the password server. ****************************************************************************/ + BOOL server_validate(char *user, char *domain, char *pass, int passlen, char *ntpass, int ntpasslen) @@ -520,7 +1035,7 @@ BOOL server_validate(char *user, char *domain, if (!cli->initialised) { DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return False; + return(False); } if(badpass[0] == 0) @@ -541,8 +1056,7 @@ BOOL server_validate(char *user, char *domain, */ if(!tested_password_server) { - if (cli_session_setup(cli, global_myname, - user, (char *)badpass, sizeof(badpass), + if (cli_session_setup(cli, user, (char *)badpass, sizeof(badpass), (char *)badpass, sizeof(badpass), domain)) { /* @@ -587,8 +1101,7 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, global_myname, - user, pass, passlen, ntpass, ntpasslen, domain)) { + if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); return False; } @@ -597,12 +1110,365 @@ use this machine as the password server.\n")); if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); cli_ulogoff(cli); - return False; + return(False); } - cli_ulogoff(cli); return(True); } +/*********************************************************************** + Connect to a remote machine for domain security authentication + given a name or IP address. +************************************************************************/ + +static BOOL connect_to_domain_password_server(struct cli_state *pcli, char *remote_machine, + unsigned char *trust_passwd) +{ + struct in_addr dest_ip; + + if(cli_initialise(pcli) == False) { + DEBUG(0,("connect_to_domain_password_server: unable to initialize client connection.\n")); + return False; + } + + standard_sub_basic(remote_machine); + strupper(remote_machine); + + if(!resolve_name( remote_machine, &dest_ip, 0x20)) { + DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n", remote_machine)); + cli_shutdown(pcli); + return False; + } + + if (ismyip(dest_ip)) { + DEBUG(1,("connect_to_domain_password_server: Password server loop - not using password server %s\n", + remote_machine)); + cli_shutdown(pcli); + return False; + } + + if (!cli_connect(pcli, remote_machine, &dest_ip)) { + DEBUG(0,("connect_to_domain_password_server: unable to connect to SMB server on \ +machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + if (!attempt_netbios_session_request(pcli, global_myname, remote_machine, &dest_ip)) { + DEBUG(0,("connect_to_password_server: machine %s rejected the NetBIOS \ +session request. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + return False; + } + + pcli->protocol = PROTOCOL_NT1; + + if (!cli_negprot(pcli)) { + DEBUG(0,("connect_to_domain_password_server: machine %s rejected the negotiate protocol. \ +Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + if (pcli->protocol != PROTOCOL_NT1) { + DEBUG(0,("connect_to_domain_password_server: machine %s didn't negotiate NT protocol.\n", + remote_machine)); + cli_shutdown(pcli); + return False; + } + + /* + * Do an anonymous session setup. + */ + + if (!cli_session_setup(pcli, "", "", 0, "", 0, "")) { + DEBUG(0,("connect_to_domain_password_server: machine %s rejected the session setup. \ +Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + if (!(pcli->sec_mode & 1)) { + DEBUG(1,("connect_to_domain_password_server: machine %s isn't in user level security mode\n", + remote_machine)); + cli_shutdown(pcli); + return False; + } + + if (!cli_send_tconX(pcli, "IPC$", "IPC", "", 1)) { + DEBUG(0,("connect_to_domain_password_server: machine %s rejected the tconX on the IPC$ share. \ +Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + /* + * We now have an anonymous connection to IPC$ on the domain password server. + */ + + /* + * Even if the connect succeeds we need to setup the netlogon + * pipe here. We do this as we may just have changed the domain + * account password on the PDC and yet we may be talking to + * a BDC that doesn't have this replicated yet. In this case + * a successful connect to a DC needs to take the netlogon connect + * into account also. This patch from "Bjart Kvarme" . + */ + + if(cli_nt_session_open(pcli, PIPE_NETLOGON) == False) { + DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ +machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); + cli_nt_session_close(pcli); + cli_ulogoff(pcli); + cli_shutdown(pcli); + return False; + } + + if (cli_nt_setup_creds(pcli, trust_passwd) == False) { + DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \ +%s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); + cli_nt_session_close(pcli); + cli_ulogoff(pcli); + cli_shutdown(pcli); + return(False); + } + + return True; +} + +/*********************************************************************** + Utility function to attempt a connection to an IP address of a DC. +************************************************************************/ + +static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, unsigned char *trust_passwd) +{ + fstring dc_name; + + /* + * Ignore addresses we have already tried. + */ + + if(ip_equal(ipzero, *ip)) + return False; + + if(!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) + return False; + + return connect_to_domain_password_server(pcli, dc_name, trust_passwd); +} + +/*********************************************************************** + Do the same as security=server, but using NT Domain calls and a session + key from the machine password. +************************************************************************/ + +BOOL domain_client_validate( char *user, char *domain, + char *smb_apasswd, int smb_apasslen, + char *smb_ntpasswd, int smb_ntpasslen, + BOOL *user_exists) +{ + unsigned char local_challenge[8]; + unsigned char local_lm_response[24]; + unsigned char local_nt_reponse[24]; + unsigned char trust_passwd[16]; + fstring remote_machine; + char *p; + NET_ID_INFO_CTR ctr; + NET_USER_INFO_3 info3; + struct cli_state cli; + uint32 smb_uid_low; + BOOL connected_ok = False; + + if(user_exists != NULL) + *user_exists = True; /* Only set false on a very specific error. */ + + /* + * Check that the requested domain is not our own machine name. + * If it is, we should never check the PDC here, we use our own local + * password file. + */ + + if(strequal( domain, global_myname)) { + DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); + return False; + } + + /* + * Next, check that the passwords given were encrypted. + */ + + if(((smb_apasslen != 24) && (smb_apasslen != 0)) || + ((smb_ntpasslen != 24) && (smb_ntpasslen != 0))) { + + /* + * Not encrypted - do so. + */ + + DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); + generate_random_buffer( local_challenge, 8, False); + SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); + SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_reponse); + smb_apasslen = 24; + smb_ntpasslen = 24; + smb_apasswd = (char *)local_lm_response; + smb_ntpasswd = (char *)local_nt_reponse; + } else { + + /* + * Encrypted - get the challenge we sent for these + * responses. + */ + + if (!last_challenge(local_challenge)) { + DEBUG(0,("domain_client_validate: no challenge done - password failed\n")); + return False; + } + } + + /* + * Get the machine account password. + */ + if (!trust_get_passwd( trust_passwd, global_myworkgroup, global_myname)) + { + return False; + } + + /* + * At this point, smb_apasswd points to the lanman response to + * the challenge in local_challenge, and smb_ntpasswd points to + * the NT response to the challenge in local_challenge. Ship + * these over the secure channel to a domain controller and + * see if they were valid. + */ + + ZERO_STRUCT(cli); + + /* + * Treat each name in the 'password server =' line as a potential + * PDC/BDC. Contact each in turn and try and authenticate. + */ + + p = lp_passwordserver(); + while(!connected_ok && p && + next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { + if(strequal(remote_machine, "*")) { + + /* + * We have been asked to dynamcially determine the IP addresses of + * the PDC and BDC's for this DOMAIN, and query them in turn. + */ + + struct in_addr *ip_list = NULL; + int count = 0; + int i; + + if(!get_dc_list(lp_workgroup(), &ip_list, &count)) + continue; + + /* + * Firstly try and contact a PDC/BDC who has the same + * network address as any of our interfaces. + */ + + for(i = 0; i < count; i++) { + if(!is_local_net(ip_list[i])) + continue; + + if((connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd))) + break; + + ip_list[i] = ipzero; /* Tried and failed. */ + } + + /* + * Secondly try and contact a random PDC/BDC. + */ + + if(!connected_ok) { + i = (sys_random() % count); + + if(!(connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd))) + ip_list[i] = ipzero; /* Tried and failed. */ + } + + /* + * Finally go through the IP list in turn, ignoring any addresses + * we have already tried. + */ + + if(!connected_ok) { + + /* + * Try and connect to any of the other IP addresses in the PDC/BDC list. + * Note that from a WINS server the #1 IP address is the PDC. + */ + + for(i = 0; i < count; i++) { + if((connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd))) + break; + } + } + + if(ip_list != NULL) + free((char *)ip_list); + + } else { + connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); + } + } + + if (!connected_ok) { + DEBUG(0,("domain_client_validate: Domain password server not available.\n")); + cli_shutdown(&cli); + return False; + } + + /* We really don't care what LUID we give the user. */ + generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); + + if(cli_nt_login_network(&cli, domain, user, smb_uid_low, (char *)local_challenge, + ((smb_apasslen != 0) ? smb_apasswd : NULL), + ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), + &ctr, &info3) == False) { + uint32 nt_rpc_err; + + cli_error(&cli, NULL, NULL, &nt_rpc_err); + DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ +%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); + cli_nt_session_close(&cli); + cli_ulogoff(&cli); + cli_shutdown(&cli); + + if((nt_rpc_err == NT_STATUS_NO_SUCH_USER) && (user_exists != NULL)) + *user_exists = False; + + return False; + } + + /* + * Here, if we really want it, we have lots of info about the user in info3. + */ + +#if 0 + /* + * We don't actually need to do this - plus it fails currently with + * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to + * send here. JRA. + */ + + if(cli_nt_logoff(&cli, &ctr) == False) { + DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ +%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); + cli_nt_session_close(&cli); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return False; + } +#endif /* 0 */ + + cli_nt_session_close(&cli); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return True; +} diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index e20d049834..15f52c0af6 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -74,10 +74,16 @@ int reply_open_pipe_and_X(connection_struct *conn, /* Strip \PIPE\ off the name. */ pstrcpy(fname,smb_buf(inbuf) + PIPELEN); + /* + * Hack for NT printers... JRA. + */ + if(should_fail_next_srvsvc_open(fname)) + return(ERROR(ERRSRV,ERRaccess)); + /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); - smb_ofun |= 0x10; /* Add Create it not exists flag */ + smb_ofun |= FILE_CREATE_IF_NOT_EXIST; p = open_rpc_pipe_p(fname, conn, vuid); if (!p) return(ERROR(ERRSRV,ERRnofids)); @@ -105,45 +111,37 @@ int reply_open_pipe_and_X(connection_struct *conn, } /**************************************************************************** - reply to a write - - This code is basically stolen from reply_write with some - wrinkles to handle pipes. + reply to a write on a pipe ****************************************************************************/ -int reply_pipe_write(char *inbuf,char *outbuf,int length,int bufsize) +int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) { pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); size_t numtowrite = SVAL(inbuf,smb_vwv1); - int nwritten = -1; + int nwritten; + int outsize; char *data; - size_t outsize; - if (!p) return(ERROR(ERRDOS,ERRbadfid)); + if (!p) + return(ERROR(ERRDOS,ERRbadfid)); data = smb_buf(inbuf) + 3; if (numtowrite == 0) - { nwritten = 0; - } else - { - nwritten = write_pipe(p, data, numtowrite); - } + nwritten = write_to_pipe(p, data, numtowrite); if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) - { return (UNIXERROR(ERRDOS,ERRnoaccess)); - } outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); - + DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); - return outsize; + return(outsize); } /**************************************************************************** @@ -160,23 +158,18 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) int smb_doff = SVAL(inbuf, smb_vwv11); char *data; - if (!p) return(ERROR(ERRDOS,ERRbadfid)); + if (!p) + return(ERROR(ERRDOS,ERRbadfid)); data = smb_base(inbuf) + smb_doff; if (numtowrite == 0) - { nwritten = 0; - } else - { - nwritten = write_pipe(p, data, numtowrite); - } + nwritten = write_to_pipe(p, data, numtowrite); if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) - { return (UNIXERROR(ERRDOS,ERRnoaccess)); - } set_message(outbuf,6,0,True); @@ -197,18 +190,24 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); - uint32 smb_offs = IVAL(inbuf,smb_vwv3); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); int nread = -1; char *data; + /* we don't use the offset given to use for pipe reads. This + is deliberate, instead we always return the next lump of + data on the pipe */ +#if 0 + uint32 smb_offs = IVAL(inbuf,smb_vwv3); +#endif - if (!p) return(ERROR(ERRDOS,ERRbadfid)); + if (!p) + return(ERROR(ERRDOS,ERRbadfid)); set_message(outbuf,12,0,True); data = smb_buf(outbuf); - nread = read_pipe(p, data, smb_offs, smb_maxcnt); + nread = read_from_pipe(p, data, smb_maxcnt); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -231,12 +230,13 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); int outsize = set_message(outbuf,0,0,True); - if (!p) return(ERROR(ERRDOS,ERRbadfid)); + if (!p) + return(ERROR(ERRDOS,ERRbadfid)); DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum)); - if (!close_rpc_pipe_hnd(p, conn)) return(ERROR(ERRDOS,ERRbadfid)); + if (!close_rpc_pipe_hnd(p, conn)) + return(ERROR(ERRDOS,ERRbadfid)); return(outsize); } - diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index f51e54a568..de85a4a553 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -37,12 +37,12 @@ static int rp_timeout = 5; static time_t rp_time = 0; static char *rp_buffer = NULL; static BOOL predict_skip=False; -extern time_t smb_last_time; +extern struct timeval smb_last_time; /**************************************************************************** handle read prediction on a file ****************************************************************************/ -ssize_t read_predict(files_struct *fsp, int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) +ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) { ssize_t ret = 0; ssize_t possible = rp_length - (offset - rp_offset); @@ -53,7 +53,7 @@ ssize_t read_predict(files_struct *fsp, int fd,SMB_OFF_T offset,char *buf,char * if (fd == rp_fd && offset >= rp_offset && possible>0 && - smb_last_time-rp_time < rp_timeout) + smb_last_time.tv_secs - rp_time < rp_timeout) { ret = possible; if (buf) @@ -70,7 +70,7 @@ ssize_t read_predict(files_struct *fsp, int fd,SMB_OFF_T offset,char *buf,char * /* Find the end of the file - ensure we don't read predict beyond it. */ - if(fsp->conn->vfs_ops.fstat(fd,&rp_stat) < 0) + if(sys_fstat(fd,&rp_stat) < 0) { DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); predict_skip = True; @@ -95,7 +95,7 @@ ssize_t read_predict(files_struct *fsp, int fd,SMB_OFF_T offset,char *buf,char * /**************************************************************************** pre-read some data ****************************************************************************/ -void do_read_prediction(connection_struct *conn) +void do_read_prediction(void) { static size_t readsize = 0; @@ -134,13 +134,13 @@ void do_read_prediction(connection_struct *conn) } } - if (conn->vfs_ops.lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { + if (sys_lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { rp_fd = -1; rp_predict_fd = -1; return; } - rp_length = conn->vfs_ops.read(rp_fd,rp_buffer,rp_predict_length); + rp_length = read(rp_fd,rp_buffer,rp_predict_length); rp_time = time(NULL); if (rp_length < 0) rp_length = 0; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 95222d3f51..7e94ffa173 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -23,7 +23,7 @@ extern int DEBUGLEVEL; -time_t smb_last_time=(time_t)0; +struct timeval smb_last_time; char *InBuffer = NULL; char *OutBuffer = NULL; @@ -48,7 +48,7 @@ extern char *last_inbuf; extern char *InBuffer; extern char *OutBuffer; extern int smb_read_error; -extern BOOL reload_after_sighup; +extern VOLATILE SIG_ATOMIC_T reload_after_sighup; extern BOOL global_machine_password_needs_changing; extern fstring global_myworkgroup; extern pstring global_myname; @@ -173,7 +173,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(MAX(maxfd,Client)+1,&fds,NULL, timeout>0?&to:NULL); + selrtn = sys_select(MAX(maxfd,Client)+1,&fds,timeout>0?&to:NULL); /* Check if error */ if(selrtn == -1) { @@ -231,6 +231,52 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) return ret; } +/**************************************************************************** + We're terminating and have closed all our files/connections etc. + If there are any pending local messages we need to respond to them + before termination so that other smbds don't think we just died whilst + holding oplocks. +****************************************************************************/ + +void respond_to_all_remaining_local_messages(void) +{ + char buffer[1024]; + fd_set fds; + + /* + * Assert we have no exclusive open oplocks. + */ + + if(get_number_of_exclusive_open_oplocks()) { + DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", + get_number_of_exclusive_open_oplocks() )); + return; + } + + /* + * Setup the select read fd set. + */ + + FD_ZERO(&fds); + if(!setup_oplock_select_set(&fds)) + return; + + /* + * Keep doing receive_local_message with a 1 ms timeout until + * we have no more messages. + */ + + while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) { + /* Deal with oplock break requests from other smbd's. */ + process_local_message(buffer, sizeof(buffer)); + + FD_ZERO(&fds); + (void)setup_oplock_select_set(&fds); + } + + return; +} + /* These flags determine some of the permissions required to do an operation @@ -283,8 +329,8 @@ struct smb_message_struct {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, {SMBread,"SMBread",reply_read,AS_USER}, - {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC}, - {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, + {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC }, + {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC }, {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER}, @@ -319,9 +365,9 @@ struct smb_message_struct {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER}, {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER}, {SMBwritec,"SMBwritec",NULL,AS_USER}, - {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE}, - {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER}, - {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC}, + {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, + {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER }, + {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC}, {SMBioctls,"SMBioctls",NULL,AS_USER}, {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, @@ -330,7 +376,7 @@ struct smb_message_struct {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, - {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, + {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER }, {SMBffirst,"SMBffirst",reply_search,AS_USER}, {SMBfunique,"SMBfunique",reply_search,AS_USER}, @@ -339,14 +385,14 @@ struct smb_message_struct /* LANMAN2.0 PROTOCOL FOLLOWS */ {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | CAN_IPC}, + {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK }, {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, /* NT PROTOCOL FOLLOWS */ {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, - {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, + {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, - {SMBntcancel, "SMBntcancel", reply_ntcancel, AS_USER }, + {SMBntcancel, "SMBntcancel", reply_ntcancel, 0 }, /* messaging routines */ {SMBsends,"SMBsends",reply_sends,AS_GUEST}, @@ -368,14 +414,14 @@ do a switch on the message type, and return the response size ****************************************************************************/ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize) { - static int pid= -1; + static pid_t pid= (pid_t)-1; int outsize = 0; static int num_smb_messages = sizeof(smb_messages) / sizeof(struct smb_message_struct); int match; extern int Client; - if (pid == -1) + if (pid == (pid_t)-1) pid = getpid(); errno = 0; @@ -399,21 +445,25 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize } else { - DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid)); + DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,(int)pid)); - if(global_oplock_break && (smb_messages[match].flags & QUEUE_IN_OPLOCK)) + if(global_oplock_break) { - /* - * Queue this message as we are the process of an oplock break. - */ + int flags = smb_messages[match].flags; - DEBUG( 2, ( "switch_message: queueing message due to being in " ) ); - DEBUGADD( 2, ( "oplock break state.\n" ) ); + if(flags & QUEUE_IN_OPLOCK) + { + /* + * Queue this message as we are the process of an oplock break. + */ - push_oplock_pending_smb_message( inbuf, size ); - return -1; - } + DEBUG( 2, ( "switch_message: queueing message due to being in " ) ); + DEBUGADD( 2, ( "oplock break state.\n" ) ); + push_oplock_pending_smb_message( inbuf, size ); + return -1; + } + } if (smb_messages[match].fn) { int flags = smb_messages[match].flags; @@ -508,7 +558,7 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) int msg_type = CVAL(inbuf,0); extern int chain_size; - smb_last_time = time(NULL); + GetTimeOfDay(&smb_last_time); chain_size = 0; file_chain_reset(); @@ -640,7 +690,7 @@ char *smb_fn_name(int type) void construct_reply_common(char *inbuf,char *outbuf) { - bzero(outbuf,smb_size); + memset(outbuf,'\0',smb_size); set_message(outbuf,0,0,True); CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); @@ -687,6 +737,14 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) orig_outbuf = outbuf; } + /* + * The original Win95 redirector dies on a reply to + * a lockingX and read chain unless the chain reply is + * 4 byte aligned. JRA. + */ + + outsize = (outsize + 3) & ~3; + /* we need to tell the client where the next part of the reply will be */ SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); CVAL(outbuf,smb_vwv0) = smb_com2; @@ -741,234 +799,271 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) } /**************************************************************************** - process commands from the client + Setup the needed select timeout. ****************************************************************************/ -void smbd_process(void) + +static int setup_select_timeout(void) { - extern int Client; - extern int ClientPort; + int change_notify_timeout = lp_change_notify_timeout() * 1000; + int select_timeout; - InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if ((InBuffer == NULL) || (OutBuffer == NULL)) - return; + /* + * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we + * have removed any blocking locks. JRA. + */ - InBuffer += SMB_ALIGNMENT; - OutBuffer += SMB_ALIGNMENT; + select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 : + SMBD_SELECT_TIMEOUT*1000; + + if (change_notifies_pending()) + select_timeout = MIN(select_timeout, change_notify_timeout); + + return select_timeout; +} + +/**************************************************************************** + Check if services need reloading. +****************************************************************************/ + +void check_reload(int t) +{ + static time_t last_smb_conf_reload_time = 0; + + if(last_smb_conf_reload_time == 0) + last_smb_conf_reload_time = t; -#if PRIME_NMBD - DEBUG(3,("priming nmbd\n")); + if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { - struct in_addr ip; - ip = *interpret_addr2("localhost"); - if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1"); - *OutBuffer = 0; - send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM); + reload_services(True); + reload_after_sighup = False; + last_smb_conf_reload_time = t; } -#endif +} +/**************************************************************************** + Process any timeout housekeeping. Return False if the caler should exit. +****************************************************************************/ - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); +static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time) +{ + extern int Client; + static time_t last_keepalive_sent_time = 0; + static time_t last_idle_closed_check = 0; + time_t t; + BOOL allidle = True; + extern int keepalive; - /* re-initialise the timezone */ - TimeInit(); + if (smb_read_error == READ_EOF) + { + DEBUG(3,("end of file from client\n")); + return False; + } - /* if connection on port 445, fake session setup... */ - if(ClientPort == 445) + if (smb_read_error == READ_ERROR) { - extern fstring remote_machine; - extern fstring local_machine; + DEBUG(3,("receive_smb error (%s) exiting\n", + strerror(errno))); + return False; + } - fstrcpy(remote_machine, dns_to_netbios_name(client_name(Client))); - fstrcpy(local_machine, global_myname); - remote_machine[15] = 0; - local_machine[15] = 0; - strlower(remote_machine); - strlower(local_machine); + *last_timeout_processing_time = t = time(NULL); - DEBUG(2, ("smbd_process(): faking session setup\n" - "client_name: %s my_name: %s\n", remote_machine, local_machine)); + if(last_keepalive_sent_time == 0) + last_keepalive_sent_time = t; - add_session_user(remote_machine); + if(last_idle_closed_check == 0) + last_idle_closed_check = t; - reload_services(True); - reopen_logs(); + /* become root again if waiting */ + unbecome_user(); - if(lp_status(-1)) { - claim_connection(NULL,"STATUS.",MAXSTATUS,True); - } + /* check if we need to reload services */ + check_reload(t); + + /* automatic timeout if all connections are closed */ + if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) + { + DEBUG( 2, ( "Closing idle connection\n" ) ); + return False; } + else + last_idle_closed_check = t; - while (True) + if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - int deadtime = lp_deadtime()*60; - int counter; - int last_keepalive=0; - int service_load_counter = 0; - BOOL got_smb = False; + struct cli_state *cli = server_client(); + if (!send_keepalive(Client)) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + /* also send a keepalive to the password server if its still + connected */ + if (cli && cli->initialised) + send_keepalive(cli->fd); + last_keepalive_sent_time = t; + } - if (deadtime <= 0) - deadtime = DEFAULT_SMBD_TIMEOUT; + /* check for connection timeouts */ + allidle = conn_idle_all(t, deadtime); -#if USE_READ_PREDICTION - if (lp_readprediction()) - do_read_prediction(); -#endif + if (allidle && conn_num_open()>0) { + DEBUG(2,("Closing idle connection 2.\n")); + return False; + } - errno = 0; + if(global_machine_password_needs_changing) + { + unsigned char trust_passwd_hash[16]; + time_t lct; + pstring remote_machine_list; + + /* + * We're in domain level security, and the code that + * read the machine password flagged that the machine + * password needs changing. + */ + + /* + * First, open the machine password file with an exclusive lock. + */ + + if(!trust_password_lock( global_myworkgroup, global_myname, True)) { + DEBUG(0,("process: unable to open the machine account password file for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + return True; + } - for (counter=SMBD_SELECT_LOOP; - !receive_message_or_smb(InBuffer,BUFFER_SIZE, - SMBD_SELECT_LOOP*1000,&got_smb); - counter += SMBD_SELECT_LOOP) - { - time_t t; - BOOL allidle = True; - extern int keepalive; + if(!get_trust_account_password( trust_passwd_hash, &lct)) { + DEBUG(0,("process: unable to read the machine account password for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + trust_password_unlock(); + return True; + } - if (counter > 365 * 3600) /* big number of seconds. */ - { - counter = 0; - service_load_counter = 0; - } + /* + * Make sure someone else hasn't already done this. + */ - if (smb_read_error == READ_EOF) - { - DEBUG(3,("end of file from client\n")); - return; - } + if(t < lct + lp_machine_password_timeout()) { + trust_password_unlock(); + global_machine_password_needs_changing = False; + return True; + } - if (smb_read_error == READ_ERROR) - { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return; - } + pstrcpy(remote_machine_list, lp_passwordserver()); - t = time(NULL); + change_trust_account_password( global_myworkgroup, remote_machine_list); + trust_password_unlock(); + global_machine_password_needs_changing = False; + } - /* become root again if waiting */ - unbecome_user(); + /* + * Check to see if we have any blocking locks + * outstanding on the queue. + */ + process_blocking_lock_queue(t); - /* check for smb.conf reload */ - if (counter >= service_load_counter + SMBD_RELOAD_CHECK) - { - service_load_counter = counter; + /* + * Check to see if we have any change notifies + * outstanding on the queue. + */ + process_pending_change_notify_queue(t); - /* reload services, if files have changed. */ - reload_services(True); - } + /* + * Modify the select timeout depending upon + * what we have remaining in our queues. + */ - /* - * If reload_after_sighup == True then we got a SIGHUP - * and are being asked to reload. Fix from - */ + *select_timeout = setup_select_timeout(); - if (reload_after_sighup) - { - DEBUG(0,("Reloading services after SIGHUP\n")); - reload_services(False); - reload_after_sighup = False; - /* - * Use this as an excuse to print some stats. - */ - print_stat_cache_statistics(); - } + return True; +} - /* automatic timeout if all connections are closed */ - if (conn_num_open()==0 && counter >= IDLE_CLOSED_TIMEOUT) - { - DEBUG( 2, ( "Closing idle connection\n" ) ); - return; - } +/**************************************************************************** + process commands from the client +****************************************************************************/ - if (keepalive && (counter-last_keepalive)>keepalive) - { - struct cli_state *cli = server_client(); - if (!send_keepalive(Client)) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return; - } - /* also send a keepalive to the password server if its still - connected */ - if (cli && cli->initialised) - send_keepalive(cli->fd); - last_keepalive = counter; - } +void smbd_process(void) +{ + extern int smb_echo_count; + time_t last_timeout_processing_time = time(NULL); + unsigned int num_smbs = 0; + + InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if ((InBuffer == NULL) || (OutBuffer == NULL)) + return; - /* check for connection timeouts */ - allidle = conn_idle_all(t, deadtime); + InBuffer += SMB_ALIGNMENT; + OutBuffer += SMB_ALIGNMENT; - if (allidle && conn_num_open()>0) { - DEBUG(2,("Closing idle connection 2.\n")); - return; - } + max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); - if(global_machine_password_needs_changing) - { - unsigned char trust_passwd_hash[16]; - time_t lct; - pstring remote_machine_list; - int sec_chan = SEC_CHAN_WKSTA; - - /* - * We're in domain level security, and the code that - * read the machine password flagged that the machine - * password needs changing. - */ + /* re-initialise the timezone */ + TimeInit(); - /* - * First, open the machine password file with an exclusive lock. - */ + while (True) + { + int deadtime = lp_deadtime()*60; + BOOL got_smb = False; + int select_timeout = setup_select_timeout(); - if(!trust_password_lock( global_myworkgroup, global_myname, True)) { - DEBUG(0,("process: unable to open the machine account password file for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - continue; - } + if (deadtime <= 0) + deadtime = DEFAULT_SMBD_TIMEOUT; - if(!get_trust_account_password( trust_passwd_hash, &lct)) { - DEBUG(0,("process: unable to read the machine account password for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - trust_password_unlock(); - continue; - } +#if USE_READ_PREDICTION + if (lp_readprediction()) + do_read_prediction(); +#endif - /* - * Make sure someone else hasn't already done this. - */ + errno = 0; - if(t < lct + lp_machine_password_timeout()) { - trust_password_unlock(); - global_machine_password_needs_changing = False; - continue; - } + while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb)) + { + if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + return; + num_smbs = 0; /* Reset smb counter. */ + } - pstrcpy(remote_machine_list, lp_passwordserver()); - if (lp_server_role() == ROLE_DOMAIN_BDC) - sec_chan = SEC_CHAN_BDC; + if(got_smb) { + /* + * Ensure we do timeout processing if the SMB we just got was + * only an echo request. This allows us to set the select + * timeout in 'receive_message_or_smb()' to any value we like + * without worrying that the client will send echo requests + * faster than the select timeout, thus starving out the + * essential processing (change notify, blocking locks) that + * the timeout code does. JRA. + */ + int num_echos = smb_echo_count; + + process_smb(InBuffer, OutBuffer); - change_trust_account_password(global_myworkgroup, remote_machine_list, - sec_chan); - trust_password_unlock(); - global_machine_password_needs_changing = False; + if(smb_echo_count != num_echos) { + if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + return; + num_smbs = 0; /* Reset smb counter. */ } - /* - * Check to see if we have any blocking locks - * outstanding on the queue. - */ - process_blocking_lock_queue(t); + num_smbs++; /* - * Check to see if we have any change notifies - * outstanding on the queue. + * If we are getting smb requests in a constant stream + * with no echos, make sure we attempt timeout processing + * every select_timeout milliseconds - but only check for this + * every 200 smb requests. */ - process_pending_change_notify_queue(t); - } - if(got_smb) - process_smb(InBuffer, OutBuffer); + if((num_smbs % 200) == 0) { + time_t new_check_time = time(NULL); + if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) { + if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + return; + num_smbs = 0; /* Reset smb counter. */ + last_timeout_processing_time = new_check_time; /* Reset time. */ + } + } + } else process_local_message(InBuffer, BUFFER_SIZE); } diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index afabb1befd..badc0562bc 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -47,7 +47,6 @@ try to get the disk space from disk quotas (LINUX version) BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - uid_t euser_id; int r; struct dqblk D; SMB_STRUCT_STAT S; @@ -55,6 +54,9 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U struct mntent *mnt; SMB_DEV_T devno; int found; + uid_t euser_id; + + euser_id = geteuid(); /* find the block device file */ @@ -81,10 +83,10 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return(False); } - euser_id=geteuid(); - seteuid(0); + save_re_uid(); + set_effective_uid(0); r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D); - seteuid(euser_id); + restore_re_uid(); /* Use softlimit to determine disk space, except when it has been exceeded */ *bsize = 1024; @@ -212,11 +214,10 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U *dsize = request.qf_entry.user_q.f_use ; - if ( *dfree ) - *dfree -= *dsize ; - - if ( *dfree < 0 ) + if ( *dfree < *dsize ) *dfree = 0 ; + else + *dfree -= *dsize ; *bsize = 4096 ; /* Cray blocksize */ @@ -244,7 +245,7 @@ Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - uid_t user_id, euser_id; + uid_t euser_id; int ret; struct dqblk D; #if defined(SUNOS5) @@ -261,6 +262,8 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U SMB_DEV_T devno ; static SMB_DEV_T devno_cached = 0 ; int found ; + + euser_id = geteuid(); if ( sys_stat(path,&sbuf) == -1 ) return(False) ; @@ -312,18 +315,14 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return(False) ; } - euser_id = geteuid(); - user_id = getuid(); - - setuid(0); /* Solaris seems to want to give info only to super-user */ - seteuid(0); + save_re_uid(); + set_effective_uid(0); #if defined(SUNOS5) DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); if((file=sys_open(name, O_RDONLY,0))<0) { - setuid(user_id); /* Restore the original UID status */ - seteuid(euser_id); - return(False); + restore_re_uid(); + return(False); } command.op = Q_GETQUOTA; command.uid = euser_id; @@ -335,8 +334,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - setuid(user_id); /* Restore the original uid status. */ - seteuid(euser_id); + restore_re_uid(); if (ret < 0) { DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); @@ -353,14 +351,13 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U if (D.dqb_bsoftlimit==0) return(False); *bsize = DEV_BSIZE; - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; *dsize = D.dqb_bsoftlimit; - if(*dfree < 0) - { + if (D.dqb_curblocks > D.dqb_bsoftlimit) { *dfree = 0; *dsize = D.dqb_curblocks; - } + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", path,(double)*bsize,(double)*dfree,(double)*dsize)); @@ -378,21 +375,26 @@ try to get the disk space from disk quotas - OSF1 version BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - uid_t user_id, euser_id; int r, save_errno; struct dqblk D; SMB_STRUCT_STAT S; + uid_t euser_id; + /* + * This code presumes that OSF1 will only + * give out quota info when the real uid + * matches the effective uid. JRA. + */ euser_id = geteuid(); - user_id = getuid(); + save_re_uid(); + if (set_re_uid() != 0) return False; - setreuid(euser_id, -1); r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D); - if (r) + if (r) { save_errno = errno; + } - if (setreuid(user_id, -1) == -1) - DEBUG(5,("Unable to reset uid to %d\n", user_id)); + restore_re_uid(); *bsize = DEV_BSIZE; @@ -423,7 +425,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return (True); } -#elif defined (SGI6) +#elif defined (IRIX6) /**************************************************************************** try to get the disk space from disk quotas (IRIX 6.2 version) ****************************************************************************/ @@ -469,7 +471,8 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U } euser_id=geteuid(); - seteuid(0); + save_re_uid(); + set_effective_uid(0); /* Use softlimit to determine disk space, except when it has been exceeded */ @@ -479,7 +482,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U { r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); - seteuid(euser_id); /* Restore the original uid status. */ + restore_re_uid(); if (r==-1) return(False); @@ -510,7 +513,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U { r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); - seteuid(euser_id); /* Restore the original uid status. */ + restore_re_uid(); if (r==-1) return(False); @@ -539,8 +542,8 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U } else { - seteuid(euser_id); /* Restore the original uid status. */ - return(False); + restore_re_uid(); + return(False); } return (True); @@ -570,9 +573,9 @@ try to get the disk space from disk quotas - default version BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - uid_t euser_id; int r; struct dqblk D; + uid_t euser_id; #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) char dev_disk[256]; SMB_STRUCT_STAT S; @@ -584,36 +587,32 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U euser_id = geteuid(); #ifdef HPUX - { - uid_t user_id; - - /* for HPUX, real uid must be same as euid to execute quotactl for euid */ - user_id = getuid(); - setresuid(euser_id,-1,-1); - r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); - if (setresuid(user_id,-1,-1)) - DEBUG(5,("Unable to reset uid to %d\n", user_id)); - } + /* for HPUX, real uid must be same as euid to execute quotactl for euid */ + save_re_uid(); + if (set_re_uid() != 0) return False; + + r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); + + restore_re_uid(); #else #if defined(__FreeBSD__) || defined(__OpenBSD__) { /* FreeBSD patches from Marty Moll */ - uid_t user_id; gid_t egrp_id; - /* Need to be root to get quotas in FreeBSD */ - user_id = getuid(); + save_re_uid(); + set_effective_uid(0); + egrp_id = getegid(); - setuid(0); - seteuid(0); r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); /* As FreeBSD has group quotas, if getting the user quota fails, try getting the group instead. */ - if (r) - r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); - setuid(user_id); - seteuid(euser_id); + if (r) { + r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); + } + + restore_re_uid(); } #elif defined(AIX) /* AIX has both USER and GROUP quotas: @@ -622,7 +621,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ -#endif /* HAVE_SETRES */ +#endif /* HPUX */ /* Use softlimit to determine disk space, except when it has been exceeded */ #if defined(__FreeBSD__) || defined(__OpenBSD__) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fed82b5e54..54f646e091 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -38,77 +38,33 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; extern pstring sesssetup_user; +extern pstring global_myname; extern fstring global_myworkgroup; -extern fstring global_myname; extern int Client; extern int global_oplock_break; uint32 global_client_caps = 0; - +unsigned int smb_echo_count = 0; /**************************************************************************** report a possible attack via the password buffer overflow bug ****************************************************************************/ + static void overflow_attack(int len) { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "ERROR: Invalid password length %d.\n", len ); - dbgtext( "Your machine may be under attack by someone " ); - dbgtext( "attempting to exploit an old bug.\n" ); - dbgtext( "Attack was from IP = %s.\n", client_addr(Client) ); - } + if( DEBUGLVL( 0 ) ) { + dbgtext( "ERROR: Invalid password length %d.\n", len ); + dbgtext( "Your machine may be under attack by someone " ); + dbgtext( "attempting to exploit an old bug.\n" ); + dbgtext( "Attack was from IP = %s.\n", client_addr(Client) ); + } exit_server("possible attack"); } -/**************************************************************************** - does _both_ nt->unix and unix->unix username remappings. -****************************************************************************/ -static void map_nt_and_unix_username(const char *domain, char *user) -{ - DOM_NAME_MAP gmep; - fstring nt_username; - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - if (lp_server_role() != ROLE_DOMAIN_NONE) - { - memset(nt_username, 0, sizeof(nt_username)); - if (domain != NULL) - { - slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s", - domain, user); - } - else - { - fstrcpy(nt_username, user); - } - - if (lookupsmbpwntnam(nt_username, &gmep)) - { - fstrcpy(user, gmep.unix_name); - } - } - - /* - * Pass the user through the unix -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); -} - /**************************************************************************** reply to an special message ****************************************************************************/ + int reply_special(char *inbuf,char *outbuf) { int outsize = 4; @@ -122,13 +78,10 @@ int reply_special(char *inbuf,char *outbuf) *name1 = *name2 = 0; - bzero(outbuf,smb_size); + memset(outbuf,'\0',smb_size); smb_setlen(outbuf,0); - DEBUG(20,("NBT message\n")); - dump_data(20, inbuf, smb_len(inbuf)); - switch (msg_type) { case 0x81: /* session request */ CVAL(outbuf,0) = 0x82; @@ -202,11 +155,11 @@ int reply_special(char *inbuf,char *outbuf) /******************************************************************* work out what error to give to a failed connection ********************************************************************/ + static int connection_error(char *inbuf,char *outbuf,int ecode) { - if (ecode == ERRnoipc) { + if (ecode == ERRnoipc) return(ERROR(ERRDOS,ERRnoipc)); - } return(ERROR(ERRSRV,ecode)); } @@ -247,15 +200,14 @@ static void parse_connect(char *p,char *service,char *user, } } - - - /**************************************************************************** - reply to a tcon + Reply to a tcon. ****************************************************************************/ + int reply_tcon(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { + BOOL doencrypt = SMBENCRYPT(); pstring service; pstring user; pstring password; @@ -269,7 +221,25 @@ int reply_tcon(connection_struct *conn, parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); - map_nt_and_unix_username(global_myworkgroup, user); + /* + * Ensure the user and password names are in UNIX codepage format. + */ + + dos_to_unix(user,True); + if (!doencrypt) + dos_to_unix(password,True); + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode); @@ -288,16 +258,17 @@ int reply_tcon(connection_struct *conn, return(outsize); } - /**************************************************************************** - reply to a tcon and X + Reply to a tcon and X. ****************************************************************************/ + int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring service; pstring user; pstring password; pstring devicename; + BOOL doencrypt = SMBENCRYPT(); int ecode = -1; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); @@ -314,7 +285,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (passlen > MAX_PASS_LEN) { overflow_attack(passlen); } - + memcpy(password,smb_buf(inbuf),passlen); password[passlen]=0; path = smb_buf(inbuf) + passlen; @@ -339,8 +310,26 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt StrnCpy(devicename,path + strlen(path) + 1,6); DEBUG(4,("Got device type %s\n",devicename)); - map_nt_and_unix_username(global_myworkgroup, user); + /* + * Ensure the user and password names are in UNIX codepage format. + */ + + dos_to_unix(user,True); + if (!doencrypt) + dos_to_unix(password,True); + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam(user, True); + conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode); if (!conn) @@ -397,14 +386,39 @@ int reply_unknown(char *inbuf,char *outbuf) int reply_ioctl(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - DEBUG(3,("ignoring ioctl\n")); -#if 0 - /* we just say it succeeds and hope its all OK. - some day it would be nice to interpret them individually */ - return set_message(outbuf,1,0,True); -#else - return(ERROR(ERRSRV,ERRnosupport)); -#endif + uint16 device = SVAL(inbuf,smb_vwv1); + uint16 function = SVAL(inbuf,smb_vwv2); + uint32 ioctl_code = (device << 16) + function; + int replysize, outsize; + char *p; + + DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); + + switch (ioctl_code) + { + case IOCTL_QUERY_JOB_INFO: + replysize = 32; + break; + default: + return(ERROR(ERRSRV,ERRnosupport)); + } + + outsize = set_message(outbuf,8,replysize+1,True); + SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */ + SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */ + SSVAL(outbuf,smb_vwv6,52); /* Offset to data */ + p = smb_buf(outbuf) + 1; /* Allow for alignment */ + + switch (ioctl_code) + { + case IOCTL_QUERY_JOB_INFO: + SSVAL(p,0,1); /* Job number */ + StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */ + StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */ + break; + } + + return outsize; } /**************************************************************************** @@ -415,7 +429,6 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out char *smb_nt_passwd, int smb_nt_passlen) { struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ - uchar last_chal[8]; if (lp_security() == SEC_USER) { smb_trust_acct = getsmbpwnam(user); @@ -442,10 +455,8 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } - if (!last_challenge(last_chal) || - !smb_password_ok(smb_trust_acct, last_chal, NULL, NULL, - (unsigned char *)smb_passwd, smb_passlen, - (unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL)) + + if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); @@ -479,20 +490,155 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); } +/**************************************************************************** + Create a UNIX user on demand. +****************************************************************************/ + +static int smb_create_user(char *unix_user) +{ + pstring add_script; + int ret; + + pstrcpy(add_script, lp_adduser_script()); + pstring_sub(add_script, "%u", unix_user); + ret = smbrun(add_script,NULL,False); + DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); + return ret; +} + +/**************************************************************************** + Delete a UNIX user on demand. +****************************************************************************/ + +static int smb_delete_user(char *unix_user) +{ + pstring del_script; + int ret; + + pstrcpy(del_script, lp_deluser_script()); + pstring_sub(del_script, "%u", unix_user); + ret = smbrun(del_script,NULL,False); + DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); + return ret; +} + +/**************************************************************************** + Check user is in correct domain if required +****************************************************************************/ + +static BOOL check_domain_match(char *user, char *domain) +{ + /* + * If we aren't serving to trusted domains, we must make sure that + * the validation request comes from an account in the same domain + * as the Samba server + */ + + if (!lp_allow_trusted_domains() && + !strequal(lp_workgroup(), domain) ) { + DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain)); + return False; + } else { + return True; + } +} + /**************************************************************************** Check for a valid username and password in security=server mode. ****************************************************************************/ -static BOOL check_server_security(char *orig_user, char *domain, +static BOOL check_server_security(char *orig_user, char *domain, char *unix_user, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { + BOOL ret = False; + if(lp_security() != SEC_SERVER) return False; - return server_validate(orig_user, domain, + if (!check_domain_match(orig_user, domain)) + return False; + + ret = server_validate(orig_user, domain, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen); + if(ret) { + /* + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. + * Note that we can never delete users when in server + * level security as we never know if it was a failure + * due to a bad password, or the user really doesn't exist. + */ + if(lp_adduser_script() && !Get_Pwnam(unix_user,True)) { + smb_create_user(unix_user); + } + } + + return ret; +} + +/**************************************************************************** + Check for a valid username and password in security=domain mode. +****************************************************************************/ + +static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user, + char *smb_apasswd, int smb_apasslen, + char *smb_ntpasswd, int smb_ntpasslen) +{ + BOOL ret = False; + BOOL user_exists = True; + + if(lp_security() != SEC_DOMAIN) + return False; + + if (!check_domain_match(orig_user, domain)) + return False; + + ret = domain_client_validate(orig_user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen, + &user_exists); + + if(ret) { + /* + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. + */ + if(user_exists && lp_adduser_script() && !Get_Pwnam(unix_user,True)) { + smb_create_user(unix_user); + } + } else { + /* + * User failed to validate ok against Domain controller. + * If the failure was "user doesn't exist" and admin + * wants us to try and delete that UNIX user on the fly, + * do so. + */ + if(!user_exists && lp_deluser_script() && Get_Pwnam(unix_user,True)) { + smb_delete_user(unix_user); + } + } + + return ret; +} + +/**************************************************************************** + Return a bad password error configured for the correct client type. +****************************************************************************/ + +static int bad_password_error(char *inbuf,char *outbuf) +{ + enum remote_arch_types ra_type = get_remote_arch(); + + if(ra_type == RA_WINNT && (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { + SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0,0xc0000000|NT_STATUS_LOGON_FAILURE)); + } + + return(ERROR(ERRSRV,ERRbadpw)); } /**************************************************************************** @@ -502,9 +648,8 @@ reply to a session setup command int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 sess_vuid; - uchar user_sess_key[16]; - int gid; - int uid; + gid_t gid; + uid_t uid; int smb_bufsize; int smb_apasslen = 0; pstring smb_apasswd; @@ -517,63 +662,55 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; - uchar last_chal[8]; *smb_apasswd = 0; *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); - if (Protocol < PROTOCOL_NT1) - { + if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); if (smb_apasslen > MAX_PASS_LEN) - { - overflow_attack(smb_apasslen); - } + overflow_attack(smb_apasslen); memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); smb_apasswd[smb_apasslen] = 0; pstrcpy(user,smb_buf(inbuf)+smb_apasslen); - + /* + * Incoming user is in DOS codepage format. Convert + * to UNIX. + */ + dos_to_unix(user,True); + if (!doencrypt && (lp_security() != SEC_SERVER)) { - smb_apasslen = strlen(smb_apasswd); + smb_apasslen = strlen(smb_apasswd); } - - if (lp_server_ntlmv2() == True) - { - DEBUG(1,("NTLMv2-only accepted with NT LANMAN 1.0 and above.\n\ -user %s attempted down-level SMB connection\n", user)); - return(ERROR(ERRSRV,ERRbadpw)); - } - } - else - { + } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); enum remote_arch_types ra_type = get_remote_arch(); char *p = smb_buf(inbuf); - global_client_caps = IVAL(inbuf,smb_vwv11); + if(global_client_caps == 0) + global_client_caps = IVAL(inbuf,smb_vwv11); /* client_caps is used as final determination if client is NT or Win95. This is needed to return the correct error codes in some circumstances. */ - if(ra_type == RA_WINNT || ra_type == RA_WIN95) - { + if(ra_type == RA_WINNT || ra_type == RA_WIN95) { if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32)) set_remote_arch( RA_WINNT); else set_remote_arch( RA_WIN95); } - if (passlen1 != 24 && passlen2 <= 24) + if (passlen1 != 24 && passlen2 != 24) doencrypt = False; if (passlen1 > MAX_PASS_LEN) { - overflow_attack(passlen1); + overflow_attack(passlen1); } passlen1 = MIN(passlen1, MAX_PASS_LEN); @@ -590,18 +727,33 @@ user %s attempted down-level SMB connection\n", user)); if passlen1>0 and passlen2>0 then maybe its a NT box and its setting passlen2 to some random value which really stuffs - things up. we need to fix that one. + things up. we need to fix that one. */ - LKCLXXXX: the random value can be random 16 bit. old test - used to have ... && passlen <= 24) which of course fails - most of the time. - */ - - if (passlen1 > 0 && passlen2 > 0 && passlen2 != 1) + if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1) passlen2 = 0; } - if (doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { + if (lp_restrict_anonymous()) { + /* there seems to be no reason behind the differences in MS clients formatting + * various info like the domain, NativeOS, and NativeLanMan fields. Win95 + * in particular seems to have an extra null byte between the username and the + * domain, or the password length calculation is wrong, which throws off the + * string extraction routines below. This makes the value of domain be the + * empty string, which fails the restrict anonymous check further down. + * This compensates for that, and allows browsing to work in mixed NT and + * win95 environments even when restrict anonymous is true. AAB + */ + dump_data(100, p, 0x70); + DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2)); + if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) { + DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n")); + DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n")); + DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n")); + passlen1 = 1; + } + } + + if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; memcpy(smb_apasswd,p,smb_apasslen); @@ -609,54 +761,77 @@ user %s attempted down-level SMB connection\n", user)); smb_ntpasslen = passlen2; memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); smb_ntpasswd[smb_ntpasslen] = 0; + + /* + * Ensure the plaintext passwords are in UNIX format. + */ + if(!doencrypt) { + dos_to_unix(smb_apasswd,True); + dos_to_unix(smb_ntpasswd,True); + } + } else { /* we use the first password that they gave */ smb_apasslen = passlen1; StrnCpy(smb_apasswd,p,smb_apasslen); + /* + * Ensure the plaintext password is in UNIX format. + */ + dos_to_unix(smb_apasswd,True); /* trim the password */ smb_apasslen = strlen(smb_apasswd); /* wfwg sometimes uses a space instead of a null */ if (strequal(smb_apasswd," ")) { - smb_apasslen = 0; - *smb_apasswd = 0; + smb_apasslen = 0; + *smb_apasswd = 0; } } - if (passlen2 == 0 && smb_apasslen == 0 && ra_type == RA_WIN95) - { - /* work-around for win95 NULL sessions, where NULL password is - actually put in the data stream before the domain name etc */ - p++; - } - else - { - p += passlen1 + passlen2; - } - - fstrcpy(user,p); p = skip_string(p,1); + p += passlen1 + passlen2; + fstrcpy(user,p); + p = skip_string(p,1); + /* + * Incoming user is in DOS codepage format. Convert + * to UNIX. + */ + dos_to_unix(user,True); domain = p; DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - domain, skip_string(p,1), skip_string(p,2))); + domain,skip_string(p,1),skip_string(p,2))); } + DEBUG(3,("sesssetupX:name=[%s]\n",user)); /* If name ends in $ then I think it's asking about whether a */ /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ - if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) - { + + if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) { return session_trust_account(conn, inbuf, outbuf, user, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen); } + if (done_sesssetup && lp_restrict_anonymous()) { + /* tests show that even if browsing is done over already validated connections + * without a username and password the domain is still provided, which it + * wouldn't be if it was a purely anonymous connection. So, in order to + * restrict anonymous, we only deny connections that have no session + * information. If a domain has been provided, then it's not a purely + * anonymous connection. AAB + */ + if (!*user && !*smb_apasswd && !*domain) { + DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } + /* If no username is sent use the guest account */ - if (!*user) - { + if (!*user) { pstrcpy(user,lp_guestaccount(-1)); /* If no user and no password then set guest flag. */ if( *smb_apasswd == 0) @@ -664,6 +839,7 @@ user %s attempted down-level SMB connection\n", user)); } strlower(user); + /* * In share level security, only overwrite sesssetup_use if * it's a non null-session share. Helps keep %U and %G @@ -672,6 +848,7 @@ user %s attempted down-level SMB connection\n", user)); if((lp_security() != SEC_SHARE) || (*user && !guest)) pstrcpy(sesssetup_user,user); + reload_services(True); /* @@ -682,7 +859,17 @@ user %s attempted down-level SMB connection\n", user)); pstrcpy( orig_user, user); - map_nt_and_unix_username(domain, user); + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); add_session_user(user); @@ -699,14 +886,12 @@ user %s attempted down-level SMB connection\n", user)); */ if (!guest && - !check_server_security(orig_user, domain, + !check_server_security(orig_user, domain, user, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen) && + !check_domain_security(orig_user, domain, user, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) && - !last_challenge(last_chal) && - !check_domain_security(orig_user, domain, - last_chal, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen, user_sess_key) && !check_hosts_equiv(user) ) { @@ -721,25 +906,31 @@ user %s attempted down-level SMB connection\n", user)); * 128 length unicode. */ - if (smb_ntpasslen) + if(smb_ntpasslen) { - if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key)) - DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); + if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) + DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user)); else valid_nt_password = True; } - if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key)) + if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) { if (lp_security() >= SEC_USER) { if (lp_map_to_guest() == NEVER_MAP_TO_GUEST) - return(ERROR(ERRSRV,ERRbadpw)); + { + DEBUG(1,("Rejecting user '%s': authentication failed\n", user)); + return bad_password_error(inbuf,outbuf); + } if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) { - if (Get_Pwnam(user,True)) - return(ERROR(ERRSRV,ERRbadpw)); + if (Get_Pwnam(user,True)) + { + DEBUG(1,("Rejecting user '%s': bad password\n", user)); + return bad_password_error(inbuf,outbuf); + } } /* @@ -765,15 +956,12 @@ user %s attempted down-level SMB connection\n", user)); lp_servicenumber(user) < 0) { int homes = lp_servicenumber(HOMES_NAME); - char *home = get_unixhome_dir(user); + char *home = get_user_home_dir(user); if (homes >= 0 && home) - { - pstring home_dir; - fstrcpy(home_dir, home); - lp_add_home(user,homes,home_dir); - } + lp_add_home(user,homes,home); } + /* it's ok - setup a reply */ if (Protocol < PROTOCOL_NT1) { set_message(outbuf,3,0,True); @@ -793,10 +981,10 @@ user %s attempted down-level SMB connection\n", user)); user we should become. */ { - const struct passwd *pw = Get_Pwnam(user,False); + struct passwd *pw = Get_Pwnam(user,False); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); - return(ERROR(ERRSRV,ERRbadpw)); + return bad_password_error(inbuf,outbuf); } gid = pw->pw_gid; uid = pw->pw_uid; @@ -807,7 +995,7 @@ user %s attempted down-level SMB connection\n", user)); /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -836,14 +1024,10 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT st; pstrcpy(name,smb_buf(inbuf) + 1); - if (!unix_dfs_convert(name,conn,0,&bad_path,&st)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(name,conn,0,&bad_path,&st); mode = SVAL(inbuf,smb_vwv0); - + if (check_name(name,conn)) { if(VALID_STAT(st)) ok = S_ISDIR(st.st_mode); @@ -900,7 +1084,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); - + /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (! (*fname)) @@ -913,14 +1097,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { - if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0) + if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; @@ -982,11 +1162,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); - if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,&st); mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); @@ -1025,7 +1201,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz int outsize = 0; SMB_BIG_UINT dfree,dsize,bsize; - conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize); + sys_disk_free(".",True,&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -1084,74 +1260,70 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size /* dirtype &= ~aDIR; */ - DEBUG(5,("path=%s status_len=%d\n",path,status_len)); + DEBUG(5,("reply_search: path=%s status_len=%d\n",path,status_len)); if (status_len == 0) - { - pstring dir2; - - pstrcpy(directory,smb_buf(inbuf)+1); - pstrcpy(dir2,smb_buf(inbuf)+1); - if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - unix_format(dir2); + pstring dir2; - if (!check_name(directory,conn)) - can_open = False; + pstrcpy(directory,smb_buf(inbuf)+1); + pstrcpy(dir2,smb_buf(inbuf)+1); + unix_convert(directory,conn,0,&bad_path,NULL); + unix_format(dir2); - p = strrchr(dir2,'/'); - if (p == NULL) - { - pstrcpy(mask,dir2); - *dir2 = 0; - } - else - { - *p = 0; - pstrcpy(mask,p+1); - } + if (!check_name(directory,conn)) + can_open = False; - p = strrchr(directory,'/'); - if (!p) - *directory = 0; - else - *p = 0; - - if (strlen(directory) == 0) - pstrcpy(directory,"./"); - bzero(status,21); - CVAL(status,0) = dirtype; + p = strrchr(dir2,'/'); + if (p == NULL) + { + pstrcpy(mask,dir2); + *dir2 = 0; } - else + else { - memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); - memcpy(mask,status+1,11); - mask[11] = 0; - dirtype = CVAL(status,0) & 0x1F; - conn->dirptr = dptr_fetch(status+12,&dptr_num); - if (!conn->dirptr) - goto SearchEmpty; - string_set(&conn->dirpath,dptr_path(dptr_num)); - if (!case_sensitive) - strnorm(mask); + *p = 0; + pstrcpy(mask,p+1); } + p = strrchr(directory,'/'); + if (!p) + *directory = 0; + else + *p = 0; + + if (strlen(directory) == 0) + pstrcpy(directory,"./"); + memset((char *)status,'\0',21); + CVAL(status,0) = dirtype; + } + else + { + memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); + memcpy(mask,status+1,11); + mask[11] = 0; + dirtype = CVAL(status,0) & 0x1F; + conn->dirptr = dptr_fetch(status+12,&dptr_num); + if (!conn->dirptr) + goto SearchEmpty; + string_set(&conn->dirpath,dptr_path(dptr_num)); + if (!case_sensitive) + strnorm(mask); + } + /* turn strings of spaces into a . */ { trim_string(mask,NULL," "); if ((p = strrchr(mask,' '))) - { - fstring ext; - fstrcpy(ext,p+1); - *p = 0; - trim_string(mask,NULL," "); - pstrcat(mask,"."); - pstrcat(mask,ext); - } + { + fstring ext; + fstrcpy(ext,p+1); + *p = 0; + trim_string(mask,NULL," "); + pstrcat(mask,"."); + pstrcat(mask,ext); + } } /* Convert the formatted mask. (This code lives in trans2.c) */ @@ -1179,104 +1351,104 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } if (!strchr(mask,'.') && strlen(mask)>8) - { - fstring tmp; - fstrcpy(tmp,&mask[8]); - mask[8] = '.'; - mask[9] = 0; - pstrcat(mask,tmp); - } + { + fstring tmp; + fstrcpy(tmp,&mask[8]); + mask[8] = '.'; + mask[9] = 0; + pstrcat(mask,tmp); + } DEBUG(5,("mask=%s directory=%s\n",mask,directory)); if (can_open) - { - p = smb_buf(outbuf) + 3; - - ok = True; + { + p = smb_buf(outbuf) + 3; - if (status_len == 0) - { - dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) + ok = True; + + if (status_len == 0) + { + dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid)); + if (dptr_num < 0) + { + if(dptr_num == -2) { - if(dptr_num == -2) + if((errno == ENOENT) && bad_path) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return (UNIXERROR(ERRDOS,ERRnofids)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; } - return(ERROR(ERRDOS,ERRnofids)); + return (UNIXERROR(ERRDOS,ERRnofids)); } - } + return(ERROR(ERRDOS,ERRnofids)); + } + } - DEBUG(4,("dptr_num is %d\n",dptr_num)); + DEBUG(4,("dptr_num is %d\n",dptr_num)); - if (ok) - { - if ((dirtype&0x1F) == aVOLID) - { - memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); - dptr_fill(p+12,dptr_num); - if (dptr_zero(p+12) && (status_len==0)) - numentries = 1; - else - numentries = 0; - p += DIR_STRUCT_SIZE; - } - else - { - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath, - lp_dontdescend(SNUM(conn)),True)) - check_descend = True; - - for (i=numentries;(i dontdescend=<%s>\n", + conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) + check_descend = True; + + for (i=numentries;(i= 0 && CVAL(inbuf,smb_com) == SMBfunique) - dptr_close(dptr_num); + dptr_close(&dptr_num); SSVAL(outbuf,smb_vwv0,numentries); SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); @@ -1295,8 +1467,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n", - smb_fn_name(CVAL(inbuf,smb_com)), - mask, directory, dirtype, numentries, maxentries ) ); + smb_fn_name(CVAL(inbuf,smb_com)), + mask, directory, dirtype, numentries, maxentries ) ); return(outsize); } @@ -1311,7 +1483,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int status_len; char *path; char status[21]; - int dptr_num= -1; + int dptr_num= -2; outsize = set_message(outbuf,1,0,True); path = smb_buf(inbuf) + 1; @@ -1325,7 +1497,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if(dptr_fetch(status+12,&dptr_num)) { /* Close the dptr - we know it's gone */ - dptr_close(dptr_num); + dptr_close(&dptr_num); } SSVAL(outbuf,smb_vwv0,0); @@ -1358,11 +1530,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) @@ -1381,9 +1549,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,aARCH); - open_file_shared(fsp, conn, fname, share_mode, - (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), - unixmode, oplock_request, &rmode, NULL); + open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + unixmode, oplock_request,&rmode,NULL); if (!fsp->open) { @@ -1396,7 +1563,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1425,7 +1592,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } - if(fsp->granted_oplock) + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; return(outsize); } @@ -1459,19 +1626,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt files_struct *fsp; /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE) - { + if (IS_IPC(conn) && lp_nt_pipe_support()) return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); - } /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); - if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) @@ -1490,8 +1651,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unixmode = unix_mode(conn,smb_attr | aARCH); - open_file_shared(fsp, conn, fname, smb_mode, smb_ofun, unixmode, - oplock_request, &rmode, &smb_action); + open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode, + oplock_request, &rmode,&smb_action); if (!fsp->open) { @@ -1504,7 +1665,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1526,7 +1687,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt smb_action |= EXTENDED_OPLOCK_GRANTED; } - if(ex_oplock_request && fsp->granted_oplock) { + if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { smb_action |= EXTENDED_OPLOCK_GRANTED; } @@ -1539,7 +1700,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } - if(core_oplock_request && fsp->granted_oplock) { + if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } @@ -1605,11 +1766,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,NULL); if (createmode & aVOLID) { @@ -1636,18 +1793,17 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if(com == SMBmknew) { /* We should fail if file exists. */ - ofun = 0x10; + ofun = FILE_CREATE_IF_NOT_EXIST; } else { /* SMBcreate - Create if file doesn't exist, truncate if it does. */ - ofun = 0x12; + ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE; } /* Open file in dos compatibility share mode. */ - open_file_shared(fsp, conn, fname, - SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - ofun, unixmode, oplock_request, NULL, NULL); + open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + ofun, unixmode, oplock_request, NULL, NULL); if (!fsp->open) { @@ -1667,7 +1823,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } - if(fsp->granted_oplock) + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG( 2, ( "new file %s\n", fname ) ); @@ -1695,11 +1851,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); - if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,NULL); unixmode = unix_mode(conn,createmode); @@ -1718,14 +1870,12 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - pstrcpy(fname2,(char *)mktemp(fname)); + pstrcpy(fname2,(char *)smbd_mktemp(fname)); /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fsp,conn,fname2, - SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - (FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL), - unixmode, oplock_request, NULL, NULL); + open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL); if (!fsp->open) { @@ -1747,7 +1897,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } - if(fsp->granted_oplock) + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG( 2, ( "created temp file %s\n", fname2 ) ); @@ -1768,7 +1918,7 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); + if (dos_lstat(fname,&sbuf) != 0) return(False); fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); if (!lp_delete_readonly(SNUM(conn))) { @@ -1781,8 +1931,9 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) } /**************************************************************************** - reply to a unlink + Reply to a unlink ****************************************************************************/ + int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; @@ -1796,6 +1947,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL has_wild; BOOL exists=False; BOOL bad_path = False; + BOOL rc = True; *directory = *mask = 0; @@ -1805,11 +1957,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - if (!unix_dfs_convert(name,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + rc = unix_convert(name,conn,0,&bad_path,NULL); p = strrchr(name,'/'); if (!p) { @@ -1821,7 +1969,16 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(mask,p+1); } - if (is_mangled(mask)) + /* + * We should only check the mangled cache + * here if unix_convert failed. This means + * that the path in 'mask' doesn't exist + * on the file system and so we need to look + * for a possible mangle. This patch from + * Tine Smukavec . + */ + + if (!rc && is_mangled(mask)) check_mangled_cache( mask ); has_wild = strchr(mask,'*') || strchr(mask,'?'); @@ -1829,10 +1986,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (can_delete(directory,conn,dirtype) && !conn->vfs_ops.unlink(directory)) + if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++; if (!count) - exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); + exists = dos_file_exist(directory,NULL); } else { void *dirptr = NULL; char *dname; @@ -1862,7 +2019,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; - if (!conn->vfs_ops.unlink(fname)) count++; + if (!dos_unlink(fname)) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); } CloseDir(dirptr); @@ -1892,6 +2049,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size /**************************************************************************** reply to a readbraw (core+ protocol) ****************************************************************************/ + int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { size_t maxcount,mincount; @@ -1917,13 +2075,45 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s fsp = file_fsp(inbuf,smb_vwv0); + if (!FNUM_OK(fsp,conn) || !fsp->can_read) { + /* + * fsp could be NULL here so use the value from the packet. JRA. + */ + DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0))); + _smb_setlen(header,0); + transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + return(-1); + } + + CHECK_FSP(fsp,conn); + + flush_write_cache(fsp, READRAW_FLUSH); + startpos = IVAL(inbuf,smb_vwv1); -#ifdef LARGE_SMB_OFF_T if(CVAL(inbuf,smb_wct) == 10) { /* * This is a large offset (64 bit) read. */ +#ifdef LARGE_SMB_OFF_T + startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32); + +#else /* !LARGE_SMB_OFF_T */ + + /* + * Ensure we haven't been sent a >32 bit offset. + */ + + if(IVAL(inbuf,smb_vwv8) != 0) { + DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ +64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) )); + _smb_setlen(header,0); + transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + return(-1); + } + +#endif /* LARGE_SMB_OFF_T */ + if(startpos < 0) { DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos )); @@ -1932,7 +2122,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s return(-1); } } -#endif /* LARGE_SMB_OFF_T */ maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); @@ -1940,13 +2129,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s maxcount = MIN(65535,maxcount); maxcount = MAX(mincount,maxcount); - if (!FNUM_OK(fsp,conn) || !fsp->can_read) { - DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum)); - _smb_setlen(header,0); - transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); - return(-1); - } - if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) { SMB_OFF_T size = fsp->size; @@ -1955,7 +2137,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) + if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -1969,7 +2151,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, - maxcount, mincount, nread ) ); + (int)maxcount, (int)mincount, (int)nread ) ); #if UNSAFE_READRAW { @@ -1979,11 +2161,11 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #if USE_READ_PREDICTION if (!fsp->can_write) - predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread); + predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread); #endif /* USE_READ_PREDICTION */ if ((nread-predict) > 0) { - if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) { + if(seek_file(fsp,startpos + predict) == -1) { DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); ret = 0; seek_fail = True; @@ -1991,7 +2173,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s } if(!seek_fail) - ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL, + ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client, (SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } @@ -2037,8 +2219,15 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length outsize = set_message(outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - - if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) { + + /* + * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+ + * protocol request that predates the read/write lock concept. + * Thus instead of asking for a read lock here we need to ask + * for a write lock. JRA. + */ + + if(!do_lock( fsp, conn, numtoread, startpos, F_WRLCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up @@ -2062,7 +2251,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length SSVAL(smb_buf(outbuf),1,nread); DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n", - fsp->fnum, numtoread, nread ) ); + fsp->fnum, (int)numtoread, (int)nread ) ); return(outsize); } @@ -2071,7 +2260,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length /**************************************************************************** reply to a read ****************************************************************************/ -int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { size_t numtoread; ssize_t nread = 0; @@ -2094,9 +2284,8 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); - if (numtoread > 0) { + if (numtoread > 0) nread = read_file(fsp,data,startpos,numtoread); - } if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2108,7 +2297,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(smb_buf(outbuf),1,nread); DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", - fsp->fnum, numtoread, nread ) ); + fsp->fnum, (int)numtoread, (int)nread ) ); return(outsize); } @@ -2137,28 +2326,42 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,12,0,True); data = smb_buf(outbuf); -#ifdef LARGE_SMB_OFF_T if(CVAL(inbuf,smb_wct) == 12) { +#ifdef LARGE_SMB_OFF_T /* * This is a large offset (64 bit) read. */ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); - } + +#else /* !LARGE_SMB_OFF_T */ + + /* + * Ensure we haven't been sent a >32 bit offset. + */ + + if(IVAL(inbuf,smb_vwv10) != 0) { + DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \ +64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) )); + return(ERROR(ERRDOS,ERRbadaccess)); + } + #endif /* LARGE_SMB_OFF_T */ + } + if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); nread = read_file(fsp,data,startpos,smb_maxcnt); - + if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); - + DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n", - fsp->fnum, smb_mincnt, smb_maxcnt, nread ) ); + fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) ); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2166,7 +2369,8 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /**************************************************************************** reply to a writebraw (core+ or LANMAN1.0 protocol) ****************************************************************************/ -int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { ssize_t nwritten=0; ssize_t total_written=0; @@ -2203,16 +2407,11 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if (is_locked(fsp,conn,tcount,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - if (seek_file(fsp,startpos) == -1) { - DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos)); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - if (numtowrite>0) - nwritten = write_file(fsp,data,numtowrite); + nwritten = write_file(fsp,data,startpos,numtowrite); DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", - fsp->fnum, (double)startpos, numtowrite, nwritten, write_through)); + fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); if (nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -2237,12 +2436,11 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if (tcount > nwritten+numtowrite) { DEBUG(3,("Client overestimated the write %d %d %d\n", - tcount,nwritten,numtowrite)); + (int)tcount,(int)nwritten,(int)numtowrite)); } - nwritten = vfs_transfer_file(Client, NULL, -1, fsp, - (SMB_OFF_T)numtowrite,NULL,0, - startpos+nwritten); + nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0, + startpos+nwritten); total_written += nwritten; /* Set up outbuf to return the correct return */ @@ -2255,12 +2453,11 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s SSVAL(outbuf,smb_err,ERRdiskfull); } - if ((lp_syncalways(SNUM(conn)) || write_through) && - lp_strict_sync(SNUM(conn))) - conn->vfs_ops.sync(fsp->fd_ptr->fd); + if (lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fsp); DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", - fsp->fnum, (double)startpos, numtowrite, total_written)); + fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); /* we won't return a status if write through is not selected - this follows what WfWg does */ @@ -2273,7 +2470,8 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_s /**************************************************************************** reply to a writeunlock (core+) ****************************************************************************/ -int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { ssize_t nwritten = -1; size_t numtowrite; @@ -2295,19 +2493,16 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - if(seek_file(fsp,startpos) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - /* The special X/Open SMB protocol handling of zero length writes is *NOT* done for this call */ if(numtowrite == 0) nwritten = 0; else - nwritten = write_file(fsp,data,numtowrite); + nwritten = write_file(fsp,data,startpos,numtowrite); - if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn))) - conn->vfs_ops.sync(fsp->fd_ptr->fd); + if (lp_syncalways(SNUM(conn))) + sync_file(conn,fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2320,7 +2515,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum SSVAL(outbuf,smb_vwv0,nwritten); DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n", - fsp->fnum, numtowrite, nwritten ) ); + fsp->fnum, (int)numtowrite, (int)nwritten ) ); return(outsize); } @@ -2328,7 +2523,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum /**************************************************************************** reply to a write ****************************************************************************/ -int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize) +int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize) { size_t numtowrite; ssize_t nwritten = -1; @@ -2337,9 +2532,9 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) - return reply_pipe_write(inbuf,outbuf,dum_size,dum_buffsize); + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) + return reply_pipe_write(inbuf,outbuf,size,dum_buffsize); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2350,21 +2545,19 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i data = smb_buf(inbuf) + 3; if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) - return(ERROR(ERRDOS,ERRlock)); - - if(seek_file(fsp,startpos) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(ERROR(ERRDOS,ERRlock)); /* X/Open SMB protocol says that if smb_vwv1 is zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ - if(numtowrite == 0) - nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos); - else - nwritten = write_file(fsp,data,numtowrite); + if(numtowrite == 0) { + if((nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos)) >= 0) + set_filelen_write_cache(fsp, startpos); + } else + nwritten = write_file(fsp,data,startpos,numtowrite); - if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn))) - conn->vfs_ops.sync(fsp->fd_ptr->fd); + if (lp_syncalways(SNUM(conn))) + sync_file(conn,fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2379,7 +2572,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,i } DEBUG(3,("write fnum=%d num=%d wrote=%d\n", - fsp->fnum, numtowrite, nwritten)); + fsp->fnum, (int)numtowrite, (int)nwritten)); return(outsize); } @@ -2408,21 +2601,31 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng data = smb_base(inbuf) + smb_doff; -#ifdef LARGE_SMB_OFF_T if(CVAL(inbuf,smb_wct) == 14) { +#ifdef LARGE_SMB_OFF_T /* * This is a large offset (64 bit) write. */ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); - } + +#else /* !LARGE_SMB_OFF_T */ + + /* + * Ensure we haven't been sent a >32 bit offset. + */ + + if(IVAL(inbuf,smb_vwv12) != 0) { + DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \ +64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) )); + return(ERROR(ERRDOS,ERRbadaccess)); + } + #endif /* LARGE_SMB_OFF_T */ + } if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - if(seek_file(fsp,startpos) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - /* X/Open SMB protocol says that, unlike SMBwrite if the length is zero then NO truncation is done, just a write of zero. To truncate a file, @@ -2430,7 +2633,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if(numtowrite == 0) nwritten = 0; else - nwritten = write_file(fsp,data,numtowrite); + nwritten = write_file(fsp,data,startpos,numtowrite); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2445,11 +2648,10 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng } DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", - fsp->fnum, numtowrite, nwritten)); + fsp->fnum, (int)numtowrite, (int)nwritten)); - if ((lp_syncalways(SNUM(conn)) || write_through) && - lp_strict_sync(SNUM(conn))) - conn->vfs_ops.sync(fsp->fd_ptr->fd); + if (lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fsp); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2458,7 +2660,8 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng /**************************************************************************** reply to a lseek ****************************************************************************/ -int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { SMB_OFF_T startpos; SMB_OFF_T res= -1; @@ -2469,11 +2672,12 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); + flush_write_cache(fsp, SEEK_FLUSH); + mode = SVAL(inbuf,smb_vwv1) & 3; - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVALS(inbuf,smb_vwv2); - switch (mode & 3) - { + switch (mode) { case 0: umode = SEEK_SET; break; case 1: umode = SEEK_CUR; break; case 2: umode = SEEK_END; break; @@ -2481,16 +2685,48 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, umode = SEEK_SET; break; } - if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) { + /* + * Check for the special case where a seek before the start + * of the file sets the offset to zero. Added in the CIFS spec, + * section 4.2.7. + */ + + if(errno == EINVAL) { + SMB_OFF_T current_pos = startpos; + + if(umode == SEEK_CUR) { + + if((current_pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + current_pos += startpos; + + } else if (umode == SEEK_END) { + + SMB_STRUCT_STAT sbuf; + + if(sys_fstat( fsp->fd_ptr->fd, &sbuf) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + current_pos += sbuf.st_size; + } + + if(current_pos < 0) + res = sys_lseek(fsp->fd_ptr->fd,0,SEEK_SET); + } + + if(res == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } fsp->pos = res; outsize = set_message(outbuf,2,0,True); - SIVALS(outbuf,smb_vwv0,res); + SIVAL(outbuf,smb_vwv0,res); - DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n", - fsp->fnum, (double)startpos, mode)); + DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n", + fsp->fnum, (double)startpos, (double)res, mode)); return(outsize); } @@ -2498,7 +2734,8 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /**************************************************************************** reply to a flush ****************************************************************************/ -int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -2511,7 +2748,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { file_sync_all(conn); } else { - conn->vfs_ops.sync(fsp->fd_ptr->fd); + sync_file(conn,fsp); } DEBUG(3,("flush\n")); @@ -2535,8 +2772,8 @@ int reply_exit(connection_struct *conn, /**************************************************************************** Reply to a close - has to deal with closing a directory opened by NT SMB's. ****************************************************************************/ -int reply_close(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, + int dum_buffsize) { int outsize = 0; time_t mtime; @@ -2546,9 +2783,8 @@ int reply_close(connection_struct *conn, outsize = set_message(outbuf,0,0,True); /* If it's an IPC, pass off to the pipe handler. */ - if (IS_IPC(conn)) { + if (IS_IPC(conn)) return reply_pipe_close(conn, inbuf,outbuf); - } fsp = file_fsp(inbuf,smb_vwv0); @@ -2556,25 +2792,26 @@ int reply_close(connection_struct *conn, * We can only use CHECK_FSP if we know it's not a directory. */ - if(!fsp || !fsp->open || (fsp->conn != conn)) - return(ERROR(ERRDOS,ERRbadfid)); + if(!fsp || !fsp->open || (fsp->conn != conn)) + return(ERROR(ERRDOS,ERRbadfid)); if(HAS_CACHED_ERROR(fsp)) { eclass = fsp->wbmpx_ptr->wr_errclass; err = fsp->wbmpx_ptr->wr_error; } - if(fsp->is_directory) { + if(fsp->is_directory || fsp->stat_open) { /* - * Special case - close NT SMB directory + * Special case - close NT SMB directory or stat file * handle. */ - DEBUG(3,("close directory fnum=%d\n", fsp->fnum)); - close_directory(fsp); + DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum)); + close_file(fsp,True); } else { /* * Close ordinary file. */ + int close_err; /* * If there was a modify time outstanding, @@ -2592,10 +2829,19 @@ int reply_close(connection_struct *conn, set_filetime(conn, fsp->fsp_name,mtime); DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", - fsp->fd_ptr->fd, fsp->fnum, + fsp->fd_ptr ? fsp->fd_ptr->fd : -1, fsp->fnum, conn->num_files_open)); - - close_file(fsp,True); + + /* + * close_file() returns the unix errno if an error + * was detected on close - normally this is due to + * a disk full error. If not then it was probably an I/O error. + */ + + if((close_err = close_file(fsp,True)) != 0) { + errno = close_err; + return (UNIXERROR(ERRHRD,ERRgeneral)); + } } /* We have a cached error */ @@ -2609,12 +2855,14 @@ int reply_close(connection_struct *conn, /**************************************************************************** reply to a writeclose (Core+ protocol) ****************************************************************************/ + int reply_writeclose(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + char *inbuf,char *outbuf, int size, int dum_buffsize) { size_t numtowrite; ssize_t nwritten = -1; int outsize = 0; + int close_err = 0; SMB_OFF_T startpos; char *data; time_t mtime; @@ -2631,23 +2879,25 @@ int reply_writeclose(connection_struct *conn, if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - - if(seek_file(fsp,startpos) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - nwritten = write_file(fsp,data,numtowrite); + + nwritten = write_file(fsp,data,startpos,numtowrite); set_filetime(conn, fsp->fsp_name,mtime); - close_file(fsp,True); + close_err = close_file(fsp,True); DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n", - fsp->fnum, numtowrite, nwritten, + fsp->fnum, (int)numtowrite, (int)nwritten, conn->num_files_open)); if (nwritten <= 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); - + + if(close_err != 0) { + errno = close_err; + return(UNIXERROR(ERRHRD,ERRgeneral)); + } + outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); @@ -2696,7 +2946,8 @@ int reply_lock(connection_struct *conn, /**************************************************************************** reply to a unlock ****************************************************************************/ -int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); SMB_OFF_T count,offset; @@ -2775,6 +3026,8 @@ int reply_echo(connection_struct *conn, DEBUG(3,("echo %d times\n", smb_reverb)); + smb_echo_count++; + return -1; } @@ -2815,7 +3068,7 @@ int reply_printopen(connection_struct *conn, if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - pstrcpy(fname2,(char *)mktemp(fname)); + pstrcpy(fname2,(char *)smbd_mktemp(fname)); if (!check_name(fname2,conn)) { file_free(fsp); @@ -2852,6 +3105,7 @@ int reply_printclose(connection_struct *conn, { int outsize = set_message(outbuf,0,0,True); files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int close_err = 0; CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2862,7 +3116,12 @@ int reply_printclose(connection_struct *conn, DEBUG(3,("printclose fd=%d fnum=%d\n", fsp->fd_ptr->fd,fsp->fnum)); - close_file(fsp,True); + close_err = close_file(fsp,True); + + if(close_err != 0) { + errno = close_err; + return(UNIXERROR(ERRHRD,ERRgeneral)); + } return(outsize); } @@ -2955,7 +3214,7 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ numtowrite = SVAL(smb_buf(inbuf),1); data = smb_buf(inbuf) + 3; - if (write_file(fsp,data,numtowrite) != numtowrite) + if (write_file(fsp,data,-1,numtowrite) != numtowrite) return(UNIXERROR(ERRDOS,ERRnoaccess)); DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); @@ -2974,15 +3233,10 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) - ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), - unix_mode(conn,aDIR)); + ret = dos_mkdir(directory,unix_mode(conn,aDIR)); if (ret < 0) { @@ -3005,11 +3259,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Static function used by reply_rmdir to delete an entire directory tree recursively. ****************************************************************************/ -static BOOL recursive_rmdir(connection_struct *conn, char *directory) + +static BOOL recursive_rmdir(char *directory) { char *dname = NULL; BOOL ret = False; - void *dirptr = OpenDir(conn, directory, False); + void *dirptr = OpenDir(NULL, directory, False); if(dirptr == NULL) return True; @@ -3033,7 +3288,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(fullname, &st) != 0) + if(dos_lstat(fullname, &st) != 0) { ret = True; break; @@ -3041,18 +3296,18 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) if(st.st_mode & S_IFDIR) { - if(recursive_rmdir(conn, fullname)!=0) + if(recursive_rmdir(fullname)!=0) { ret = True; break; } - if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0) + if(dos_rmdir(fullname) != 0) { ret = True; break; } } - else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0) + else if(dos_unlink(fullname) != 0) { ret = True; break; @@ -3063,8 +3318,97 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) } /**************************************************************************** - reply to a rmdir + The internals of the rmdir code - called elsewhere. +****************************************************************************/ + +BOOL rmdir_internals(connection_struct *conn, char *directory) +{ + BOOL ok; + + ok = (dos_rmdir(directory) == 0); + if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) + { + /* + * Check to see if the only thing in this directory are + * vetoed files/directories. If so then delete them and + * retry. If we fail to delete any of them (and we *don't* + * do a recursive delete) then fail the rmdir. + */ + BOOL all_veto_files = True; + char *dname; + void *dirptr = OpenDir(conn, directory, False); + + if(dirptr != NULL) + { + int dirpos = TellDir(dirptr); + while ((dname = ReadDirName(dirptr))) + { + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + if(!IS_VETO_PATH(conn, dname)) + { + all_veto_files = False; + break; + } + } + if(all_veto_files) + { + SeekDir(dirptr,dirpos); + while ((dname = ReadDirName(dirptr))) + { + pstring fullname; + SMB_STRUCT_STAT st; + + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + + /* Construct the full name. */ + if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) + { + errno = ENOMEM; + break; + } + pstrcpy(fullname, directory); + pstrcat(fullname, "/"); + pstrcat(fullname, dname); + + if(dos_lstat(fullname, &st) != 0) + break; + if(st.st_mode & S_IFDIR) + { + if(lp_recursive_veto_delete(SNUM(conn))) + { + if(recursive_rmdir(fullname) != 0) + break; + } + if(dos_rmdir(fullname) != 0) + break; + } + else if(dos_unlink(fullname) != 0) + break; + } + CloseDir(dirptr); + /* Retry the rmdir */ + ok = (dos_rmdir(directory) == 0); + } + else + CloseDir(dirptr); + } + else + errno = ENOTEMPTY; + } + + if (!ok) + DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", + directory,strerror(errno))); + + return ok; +} + +/**************************************************************************** + Reply to a rmdir. ****************************************************************************/ + int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring directory; @@ -3073,92 +3417,13 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - if (!unix_dfs_convert(directory,conn, NULL,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(directory,conn, NULL,&bad_path,NULL); if (check_name(directory,conn)) - { - - dptr_closepath(directory,SVAL(inbuf,smb_pid)); - ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0); - if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn))) - { - /* Check to see if the only thing in this directory are - vetoed files/directories. If so then delete them and - retry. If we fail to delete any of them (and we *don't* - do a recursive delete) then fail the rmdir. */ - BOOL all_veto_files = True; - char *dname; - void *dirptr = OpenDir(conn, directory, False); - - if(dirptr != NULL) - { - int dirpos = TellDir(dirptr); - while ((dname = ReadDirName(dirptr))) - { - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - if(!IS_VETO_PATH(conn, dname)) - { - all_veto_files = False; - break; - } - } - if(all_veto_files) - { - SeekDir(dirptr,dirpos); - while ((dname = ReadDirName(dirptr))) - { - pstring fullname; - SMB_STRUCT_STAT st; - - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) - { - errno = ENOMEM; - break; - } - pstrcpy(fullname, directory); - pstrcat(fullname, "/"); - pstrcat(fullname, dname); - - if(conn->vfs_ops.lstat(fullname, &st) != 0) - break; - if(st.st_mode & S_IFDIR) - { - if(lp_recursive_veto_delete(SNUM(conn))) - { - DEBUG(0, ("ERROR: recursive_rmdir()\n")); - if(recursive_rmdir(conn, fullname) != 0) - break; - } - if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0) - break; - } - else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0) - break; - } - CloseDir(dirptr); - /* Retry the rmdir */ - ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0); - } - else - CloseDir(dirptr); - } - else - errno = ENOTEMPTY; - } - - if (!ok) - DEBUG(3,("couldn't remove directory %s : %s\n", - directory,strerror(errno))); - } + { + dptr_closepath(directory,SVAL(inbuf,smb_pid)); + ok = rmdir_internals(conn, directory); + } if (!ok) { @@ -3251,7 +3516,7 @@ static BOOL can_rename(char *fname,connection_struct *conn) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); + if (dos_lstat(fname,&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); return(True); @@ -3275,23 +3540,16 @@ int rename_internals(connection_struct *conn, int count=0; int error = ERRnoaccess; BOOL exists=False; + BOOL rc = True; *directory = *mask = 0; - if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - if (!unix_dfs_convert(newname,conn,newname_last_component,&bad_path2,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + rc = unix_convert(name,conn,0,&bad_path1,NULL); + unix_convert(newname,conn,newname_last_component,&bad_path2,NULL); /* * Split the old name into directory and last component - * strings. Note that if (!unix_dfs_convert may have stripped off a + * strings. Note that unix_convert may have stripped off a * leading ./ from both name and newname if the rename is * at the root of the share. We need to make sure either both * name and newname contain a / character or neither of them do @@ -3309,7 +3567,16 @@ int rename_internals(connection_struct *conn, *p = '/'; /* Replace needed for exceptional test below. */ } - if (is_mangled(mask)) + /* + * We should only check the mangled cache + * here if unix_convert failed. This means + * that the path in 'mask' doesn't exist + * on the file system and so we need to look + * for a possible mangle. This patch from + * Tine Smukavec . + */ + + if (!rc && is_mangled(mask)) check_mangled_cache( mask ); has_wild = strchr(mask,'*') || strchr(mask,'?'); @@ -3379,23 +3646,21 @@ int rename_internals(connection_struct *conn, */ if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !conn->vfs_ops.rename(dos_to_unix(directory,False), - newname)) + !dos_rename(directory,newname)) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) && - !conn->vfs_ops.rename(dos_to_unix(directory,False), - newname)) + !dos_file_exist(newname,NULL) && + !dos_rename(directory,newname)) count++; } DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); - if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); - if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) { + if (!count) exists = dos_file_exist(directory,NULL); + if (!count && exists && dos_file_exist(newname,NULL)) { exists = True; error = ERRrename; } @@ -3436,13 +3701,13 @@ int rename_internals(connection_struct *conn, continue; } - if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) { - DEBUG(6,("file_exist %s\n", destname)); + if (!replace_if_exists && dos_file_exist(destname,NULL)) { + DEBUG(6,("dos_file_exist %s\n", destname)); error = 183; continue; } - if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname)) + if (!dos_rename(fname,destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3492,14 +3757,16 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in ******************************************************************/ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, - int count,BOOL target_is_directory) + int count,BOOL target_is_directory, int *err_ret) { int Access,action; SMB_STRUCT_STAT st; - int ret=-1; + SMB_OFF_T ret=-1; files_struct *fsp1,*fsp2; pstring dest; + *err_ret = 0; + pstrcpy(dest,dest1); if (target_is_directory) { char *p = strrchr(src,'/'); @@ -3511,16 +3778,15 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!vfs_file_exist(conn,dos_to_unix(src,False),&st)) + if (!dos_file_exist(src,&st)) return(False); fsp1 = file_new(); - if (!fsp1) + if (!fsp1) return(False); - open_file_shared(fsp1, conn, src, - SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_RDONLY), - (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), 0, 0, &Access, &action); + open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); if (!fsp1->open) { file_free(fsp1); @@ -3535,9 +3801,8 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, close_file(fsp1,False); return(False); } - open_file_shared(fsp2, conn, dest, - SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun, st.st_mode, 0, &Access, &action); + open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + ofun,st.st_mode,0,&Access,&action); if (!fsp2->open) { close_file(fsp1,False); @@ -3546,7 +3811,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { + if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", strerror(errno) )); /* @@ -3558,12 +3823,19 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if (st.st_size) - ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0); + ret = transfer_file(fsp1->fd_ptr->fd, + fsp2->fd_ptr->fd,st.st_size,NULL,0,0); close_file(fsp1,False); - close_file(fsp2,False); + /* + * As we are opening fsp1 read-only we only expect + * an error on close on fsp2 if we are out of space. + * Thus we don't look at the error return from the + * close of fsp1. + */ + *err_ret = close_file(fsp2,False); - return(ret == st.st_size); + return(ret == (SMB_OFF_T)st.st_size); } @@ -3580,6 +3852,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, char *p; int count=0; int error = ERRnoaccess; + int err = 0; BOOL has_wild; BOOL exists=False; int tid2 = SVAL(inbuf,smb_vwv0); @@ -3588,6 +3861,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL target_is_directory=False; BOOL bad_path1 = False; BOOL bad_path2 = False; + BOOL rc = True; *directory = *mask = 0; @@ -3602,16 +3876,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRSRV,ERRinvdevice)); } - if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - if (!unix_dfs_convert(newname,conn,0,&bad_path2,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + rc = unix_convert(name,conn,0,&bad_path1,NULL); + unix_convert(newname,conn,0,&bad_path2,NULL); target_is_directory = dos_directory_exist(newname,NULL); @@ -3639,7 +3905,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcpy(mask,p+1); } - if (is_mangled(mask)) + /* + * We should only check the mangled cache + * here if unix_convert failed. This means + * that the path in 'mask' doesn't exist + * on the file system and so we need to look + * for a possible mangle. This patch from + * Tine Smukavec . + */ + + if (!rc && is_mangled(mask)) check_mangled_cache( mask ); has_wild = strchr(mask,'*') || strchr(mask,'?'); @@ -3649,8 +3924,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(directory,mask); if (resolve_wildcards(directory,newname) && copy_file(directory,newname,conn,ofun, - count,target_is_directory)) count++; - if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); + count,target_is_directory,&err)) count++; + if(!count && err) { + errno = err; + return(UNIXERROR(ERRHRD,ERRgeneral)); + } + if (!count) exists = dos_file_exist(directory,NULL); } else { void *dirptr = NULL; char *dname; @@ -3659,33 +3938,38 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (check_name(directory,conn)) dirptr = OpenDir(conn, directory, True); - if (dirptr) - { + if (dirptr) { error = ERRbadfile; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr))) - { + while ((dname = ReadDirName(dirptr))) { pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) continue; + if(!mask_match(fname, mask, case_sensitive, False)) + continue; error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); pstrcpy(destname,newname); if (resolve_wildcards(fname,destname) && - copy_file(directory,newname,conn,ofun, - count,target_is_directory)) count++; + copy_file(fname,destname,conn,ofun, + count,target_is_directory,&err)) count++; DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); } CloseDir(dirptr); - } + } } if (count == 0) { + if(err) { + /* Error on close... */ + errno = err; + return(UNIXERROR(ERRHRD,ERRgeneral)); + } + if (exists) return(ERROR(ERRDOS,error)); else @@ -3742,9 +4026,149 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } +/**************************************************************************** + Get a lock count, dealing with large count requests. +****************************************************************************/ + +SMB_OFF_T get_lock_count( char *data, int data_offset, BOOL large_file_format, BOOL *err) +{ + SMB_OFF_T count = 0; + + *err = False; + + if(!large_file_format) { + count = (SMB_OFF_T)IVAL(data,SMB_LKLEN_OFFSET(data_offset)); + } else { + +#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + + count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset))); + +#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * NT4.x seems to be broken in that it sends large file + * lockingX calls even if the CAP_LARGE_FILES was *not* + * negotiated. For boxes without large file locks truncate the + * lock count by dropping the top 32 bits. + */ + + if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) { + DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n", + (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)), + (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) )); + SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0); + } + + if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) { + /* + * Before we error out, see if we can sensibly map the top bits + * down to the lower bits - or lose the top bits if they are all 1's. + * It seems that NT has this horrible bug where it will send 64 bit + * lock requests even if told not to. JRA. + */ + + if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF) + count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)); + else if (IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF) + count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); + else { + + DEBUG(0,("get_lock_count: Error : a large file count (%x << 32 | %x) was sent and we don't \ +support large counts.\n", (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)), + (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) )); + + *err = True; + return (SMB_OFF_T)-1; + } + } + else + count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); + +#endif /* LARGE_SMB_OFF_T */ + } + return count; +} + +/**************************************************************************** + Get a lock offset, dealing with large offset requests. +****************************************************************************/ + +SMB_OFF_T get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err) +{ + SMB_OFF_T offset = 0; + + *err = False; + + if(!large_file_format) { + offset = (SMB_OFF_T)IVAL(data,SMB_LKOFF_OFFSET(data_offset)); + } else { + +#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + + offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) | + ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset))); + +#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * NT4.x seems to be broken in that it sends large file + * lockingX calls even if the CAP_LARGE_FILES was *not* + * negotiated. For boxes without large file locks mangle the + * lock offset by mapping the top 32 bits onto the lower 32. + */ + + if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) { + uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); + uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)); + uint32 new_low = 0; + + if((new_low = map_lock_offset(high, low)) == 0) { + *err = True; + return (SMB_OFF_T)-1; + } + + DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n", + (unsigned int)high, (unsigned int)low, (unsigned int)new_low )); + SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0); + SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low); + } + + if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0){ + /* + * Before we error out, see if we can sensibly map the top bits + * down to the lower bits - or lose the top bits if they are all 1's. + * It seems that NT has this horrible bug where it will send 64 bit + * lock requests even if told not to. JRA. + */ + + if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF) + offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)); + else if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF) + offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); + else { + + DEBUG(0,("get_lock_count: Error : a large file offset (%x << 32 | %x) was sent and we don't \ +support large offsets.\n", (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)), + (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) )); + + *err = True; + return (SMB_OFF_T)-1; + } + } + else + offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); + +#endif /* LARGE_SMB_OFF_T */ + } + return offset; +} + /**************************************************************************** reply to a lockingX request ****************************************************************************/ + int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); @@ -3761,6 +4185,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, uint32 ecode=0, dummy2; int eclass=0, dummy1; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); + BOOL err1, err2; + CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -3771,35 +4197,28 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, */ if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { - int token; - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; - DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", fsp->fnum)); + /* - * Make sure we have granted an oplock on this file. + * Make sure we have granted an exclusive or batch oplock on this file. */ - if(!fsp->granted_oplock) + + if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ -no oplock granted on this file.\n", fsp->fnum)); - return ERROR(ERRDOS,ERRlock); - } - - /* Remove the oplock flag from the sharemode. */ - lock_share_entry(fsp->conn, dev, inode, &token); - if(remove_share_oplock(token, fsp)==False) { - - DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ -dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); +no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); - unlock_share_entry(fsp->conn, dev, inode, token); - } else { - unlock_share_entry(fsp->conn, dev, inode, token); + /* if this is a pure oplock break request then don't send a reply */ + if (num_locks == 0 && num_ulocks == 0) + return -1; + else + return ERROR(ERRDOS,ERRlock); + } - /* Clear the granted flag and return. */ - fsp->granted_oplock = False; + if (remove_oplock(fsp) == False) { + DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n", + fsp->fsp_name )); } /* if this is a pure oplock break request then don't send a reply */ @@ -3817,18 +4236,14 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { - if(!large_file_format) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - } -#ifdef LARGE_SMB_OFF_T - else { - count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); - offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); - } -#endif /* LARGE_SMB_OFF_T */ + count = get_lock_count( data, i, large_file_format, &err1); + offset = get_lock_offset( data, i, large_file_format, &err2); + + /* + * There is no error code marked "stupid client bug".... :-). + */ + if(err1 || err2) + return ERROR(ERRDOS,ERRnoaccess); DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); @@ -3847,18 +4262,14 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); of smb_lkrng structs */ for(i = 0; i < (int)num_locks; i++) { - if(!large_file_format) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - } -#ifdef LARGE_SMB_OFF_T - else { - count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); - offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); - } -#endif /* LARGE_SMB_OFF_T */ + count = get_lock_count( data, i, large_file_format, &err1); + offset = get_lock_offset( data, i, large_file_format, &err2); + + /* + * There is no error code marked "stupid client bug".... :-). + */ + if(err1 || err2) + return ERROR(ERRDOS,ERRnoaccess); DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); @@ -3882,19 +4293,15 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); all of the previous locks (X/Open spec). */ if(i != num_locks && num_locks != 0) { for(; i >= 0; i--) { - if(!large_file_format) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - } -#ifdef LARGE_SMB_OFF_T - else { - count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i))); - offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); - } -#endif /* LARGE_SMB_OFF_T */ + count = get_lock_count( data, i, large_file_format, &err1); + offset = get_lock_offset( data, i, large_file_format, &err2); + /* + * There is no error code marked "stupid client bug".... :-). + */ + if(err1 || err2) + return ERROR(ERRDOS,ERRnoaccess); + do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } return ERROR(eclass,ecode); @@ -3980,7 +4387,8 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, /**************************************************************************** reply to a SMBwritebmpx (write block multiplex primary) request ****************************************************************************/ -int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { size_t numtowrite; ssize_t nwritten = -1; @@ -4011,14 +4419,10 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s if (is_locked(fsp,conn,tcount,startpos,F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); - if(seek_file(fsp,startpos) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - nwritten = write_file(fsp,data,numtowrite); + nwritten = write_file(fsp,data,startpos,numtowrite); - if((lp_syncalways(SNUM(conn)) || write_through) && - lp_strict_sync(SNUM(conn))) - conn->vfs_ops.sync(fsp->fd_ptr->fd); + if(lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fsp); if(nwritten < (ssize_t)numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -4056,7 +4460,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_s SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n", - fsp->fnum, numtowrite, nwritten ) ); + fsp->fnum, (int)numtowrite, (int)nwritten ) ); if (write_through && tcount==nwritten) { /* we need to send both a primary and a secondary response */ @@ -4116,23 +4520,10 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz if(wbms->wr_discard) return -1; /* Just discard the packet */ - if(seek_file(fsp,startpos) == -1) - { - if(write_through) - { - /* We are returning an error - we can delete the aux struct */ - if (wbms) free((char *)wbms); - fsp->wbmpx_ptr = NULL; - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess)); - } - - nwritten = write_file(fsp,data,numtowrite); + nwritten = write_file(fsp,data,startpos,numtowrite); - if((lp_syncalways(SNUM(conn)) || write_through) && - lp_strict_sync(SNUM(conn))) - conn->vfs_ops.sync(fsp->fd_ptr->fd); + if(lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fsp); if (nwritten < (ssize_t)numtowrite) { @@ -4172,7 +4563,8 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz /**************************************************************************** reply to a SMBsetattrE ****************************************************************************/ -int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { struct utimbuf unix_times; int outsize = 0; @@ -4224,7 +4616,8 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si /**************************************************************************** reply to a SMBgetattrE ****************************************************************************/ -int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { SMB_STRUCT_STAT sbuf; int outsize = 0; @@ -4237,7 +4630,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si CHECK_ERROR(fsp); /* Do an fstat on this file */ - if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf)) + if(sys_fstat(fsp->fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(conn,fsp->fsp_name,&sbuf); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bdb2827483..1c6d6536ad 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -25,9 +25,7 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; extern fstring global_myworkgroup; -extern fstring global_sam_name; extern pstring global_myname; -extern dfs_internal dfs_struct; int am_parent = 1; @@ -49,8 +47,6 @@ extern int dcelogin_atmost_once; extern fstring remote_machine; extern pstring OriginalDir; -extern pstring myhostname; - /**************************************************************************** when exiting, take the whole family @@ -76,13 +72,11 @@ static void killkids(void) static BOOL open_sockets_inetd(void) { extern int Client; - extern int ClientPort; /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ Client = dup(0); - ClientPort = SMB_PORT; /* close our standard file descriptors */ close_low_fds(); @@ -93,40 +87,19 @@ static BOOL open_sockets_inetd(void) return True; } -/**************************************************************************** - open and listen to a socket -****************************************************************************/ -static int open_server_socket(int port, uint32 ipaddr) -{ - int s; - - s = open_socket_in(SOCK_STREAM, port, 0, ipaddr); - if(s == -1) - return -1; - /* ready to listen */ - if (listen(s, 5) == -1) { - DEBUG(0,("listen: %s\n", strerror(errno))); - close(s); - return -1; - } - return s; -} /**************************************************************************** open the socket communication ****************************************************************************/ -static BOOL open_sockets(BOOL is_daemon,int port,int port445) +static BOOL open_sockets(BOOL is_daemon,int port) { extern int Client; - extern int ClientPort; int num_interfaces = iface_count(); int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; int i; - memset(&fd_listenset, 0, sizeof(fd_listenset)); - if (!is_daemon) { return open_sockets_inetd(); } @@ -154,7 +127,7 @@ static BOOL open_sockets(BOOL is_daemon,int port,int port445) socket per interface and bind to only these. */ - if(num_interfaces * 2 > FD_SETSIZE) { + if(num_interfaces > FD_SETSIZE) { DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ max can be %d\n", num_interfaces, FD_SETSIZE)); @@ -170,11 +143,15 @@ max can be %d\n", DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); continue; } - s = fd_listenset[i * 2] = open_server_socket(port, ifip->s_addr); - if(s == -1) return False; - FD_SET(s,&listen_set); - s = fd_listenset[i * 2 + 1] = open_server_socket(port445, ifip->s_addr); - if(s == -1) return False; + s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + if(s == -1) + return False; + /* ready to listen */ + if (listen(s, 5) == -1) { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } FD_SET(s,&listen_set); } } else { @@ -183,18 +160,21 @@ max can be %d\n", num_interfaces = 1; /* open an incoming socket */ - s = open_server_socket(port, interpret_addr(lp_socket_address())); + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address()),True); if (s == -1) return(False); + + /* ready to listen */ + if (listen(s, 5) == -1) { + DEBUG(0,("open_sockets: listen: %s\n", + strerror(errno))); + close(s); + return False; + } + fd_listenset[0] = s; FD_SET(s,&listen_set); -#if 0 - s = open_server_socket(port445, interpret_addr(lp_socket_address())); - if (s == -1) - return(False); - fd_listenset[1] = s; - FD_SET(s,&listen_set); -#endif } /* now accept incoming connections - forking a new process @@ -207,11 +187,14 @@ max can be %d\n", memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select(256,&lfds,NULL, NULL); + num = sys_select(FD_SETSIZE,&lfds,NULL); if (num == -1 && errno == EINTR) continue; + /* check if we need to reload services */ + check_reload(time(NULL)); + /* Find the sockets that are read-ready - accept on these. */ for( ; num > 0; num--) { @@ -220,24 +203,15 @@ max can be %d\n", s = -1; for(i = 0; i < num_interfaces; i++) { - if(FD_ISSET(fd_listenset[i * 2],&lfds)) { - s = fd_listenset[i * 2]; - ClientPort = SMB_PORT; + if(FD_ISSET(fd_listenset[i],&lfds)) { + s = fd_listenset[i]; + /* Clear this so we don't look + at it again. */ + FD_CLR(fd_listenset[i],&lfds); break; } -#if 0 - if(FD_ISSET(fd_listenset[i * 2 + 1],&lfds)) { - s = fd_listenset[i * 2 + 1]; - ClientPort = SMB_PORT2; - break; - } -#endif } - /* Clear this so we don't look - at it again. */ - FD_CLR(s,&lfds); - Client = accept(s,&addr,&in_addrlen); if (Client == -1 && errno == EINTR) @@ -357,9 +331,10 @@ BOOL reload_services(BOOL test) /**************************************************************************** -this prevents zombie child processes + Catch a sighup. ****************************************************************************/ -BOOL reload_after_sighup = False; + +VOLATILE SIG_ATOMIC_T reload_after_sighup = False; static void sig_hup(int sig) { @@ -434,6 +409,8 @@ void exit_server(char *reason) conn_close_all(); + respond_to_all_remaining_local_messages(); + #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); @@ -456,13 +433,6 @@ void exit_server(char *reason) locking_end(); DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); -#ifdef MEM_MAN - { - extern FILE *dbf; - smb_mem_write_verbose(dbf); - dbgflush(); - } -#endif exit(0); } @@ -471,17 +441,34 @@ void exit_server(char *reason) /**************************************************************************** initialise connect, service and file structs ****************************************************************************/ -static void init_structs(void) +static void init_structs(void ) { + /* + * Set the machine NETBIOS name if not already + * set from the config file. + */ + + if (!*global_myname) { + char *p; + fstrcpy( global_myname, myhostname() ); + p = strchr( global_myname, '.' ); + if (p) + *p = 0; + } + + strupper( global_myname ); + conn_init(); + file_init(); - init_rpc_pipe_hnd(); /* for RPC pipes */ - if (!init_policy_hnd(MAX_SERVER_POLICY_HANDLES)) - { - exit_server("could not allocate policy handles\n"); - } + + /* for RPC pipes */ + init_rpc_pipe_hnd(); + + /* for LSA handles */ + init_lsa_policy_hnd(); + init_dptrs(); - init_dfs_table(); } /**************************************************************************** @@ -489,19 +476,21 @@ usage on the program ****************************************************************************/ static void usage(char *pname) { - DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); - - printf("Usage: %s [-D] [-p port] [-d debuglevel] ", pname); - printf("[-l log basename] [-s services file]\n" ); - printf("Version %s\n",VERSION); - printf("\t-D become a daemon\n"); - printf("\t-p port listen on the specified port\n"); - printf("\t-d debuglevel set the debuglevel\n"); + + printf("Usage: %s [-DaoPh?V] [-d debuglevel] [-l log basename] [-p port]\n", pname); + printf(" [-O socket options] [-s services file] [-i scope]\n"); + printf("\t-D Become a daemon\n"); + printf("\t-a Append to log file (default)\n"); + printf("\t-o Overwrite log file, don't append\n"); + printf("\t-P Passive only\n"); + printf("\t-h Print usage\n"); + printf("\t-? Print usage\n"); + printf("\t-V Print version\n"); + printf("\t-d debuglevel Set the debuglevel\n"); printf("\t-l log basename. Basename for log/debug files\n"); + printf("\t-p port Listen on the specified port\n"); + printf("\t-O socket options Socket options\n"); printf("\t-s services file. Filename of services file\n"); - printf("\t-P passive only\n"); - printf("\t-a append to log file (default)\n"); - printf("\t-o overwrite log file, don't append\n"); printf("\t-i scope NetBIOS scope to use (default none)\n"); printf("\n"); } @@ -516,7 +505,6 @@ static void usage(char *pname) /* shall I run as a daemon */ BOOL is_daemon = False; int port = SMB_PORT; - int port445 = SMB_PORT2; int opt; extern char *optarg; @@ -524,55 +512,13 @@ static void usage(char *pname) set_auth_parameters(argc,argv); #endif -#ifdef HAVE_SETLUID - /* needed for SecureWare on SCO */ - setluid(0); -#endif - - append_log = True; - - TimeInit(); - - pstrcpy(debugf,SMBLOGFILE); - - pstrcpy(remote_machine, "smb"); - - setup_logging(argv[0],False); - - charset_initialise(); - - /* make absolutely sure we run as root - to handle cases where people - are crazy enough to have it setuid */ -#ifdef HAVE_SETRESUID - setresuid(0,0,0); -#else - setuid(0); - seteuid(0); - setuid(0); - seteuid(0); -#endif - - fault_setup((void (*)(void *))exit_server); - CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig); - - /* we are never interested in SIGPIPE */ - BlockSignals(True,SIGPIPE); - - /* we want total control over the permissions on created files, - so set our umask to 0 */ - umask(0); - - dos_GetWd(OriginalDir); - - init_uid(); - /* this is for people who can't start the program correctly */ while (argc > 1 && (*argv[1] != '-')) { argv++; argc--; } - while ( EOF != (opt = getopt(argc, argv, "O:i:l:s:d:Dp:h?Paof:")) ) + while ( EOF != (opt = getopt(argc, argv, "O:i:l:s:d:Dp:h?VPaof:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); @@ -626,11 +572,72 @@ static void usage(char *pname) exit(0); break; + case 'V': + printf("Version %s\n",VERSION); + exit(0); + break; default: + DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); usage(argv[0]); exit(1); } +#ifdef HAVE_SETLUID + /* needed for SecureWare on SCO */ + setluid(0); +#endif + + /* + * gain_root_privilege uses an assert than will cause a core + * dump if euid != 0. Ensure this is the case. + */ + + if(geteuid() != (uid_t)0) { + fprintf(stderr, "%s: Version %s : Must have effective user id of zero to run.\n", argv[0], VERSION); + exit(1); + } + + append_log = True; + + TimeInit(); + + pstrcpy(debugf,SMBLOGFILE); + + pstrcpy(remote_machine, "smb"); + + setup_logging(argv[0],False); + + charset_initialise(); + + /* we want to re-seed early to prevent time delays causing + client problems at a later date. (tridge) */ + generate_random_buffer(NULL, 0, False); + + /* make absolutely sure we run as root - to handle cases where people + are crazy enough to have it setuid */ + + gain_root_privilege(); + gain_root_group_privilege(); + + fault_setup((void (*)(void *))exit_server); + CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig); + + /* we are never interested in SIGPIPE */ + BlockSignals(True,SIGPIPE); + +#if defined(SIGFPE) + /* we are never interested in SIGFPE */ + BlockSignals(True,SIGFPE); +#endif + + /* we want total control over the permissions on created files, + so set our umask to 0 */ + umask(0); + + dos_GetWd(OriginalDir); + + init_uid(); + reopen_logs(); DEBUG(1,( "smbd version %s started.\n", VERSION)); @@ -644,13 +651,15 @@ static void usage(char *pname) exit(1); } - get_myname(myhostname,NULL); + /* + * Do this before reload_services. + */ if (!reload_services(False)) return(-1); init_structs(); - + #ifdef WITH_PROFILE if (!profile_setup(False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); @@ -658,16 +667,6 @@ static void usage(char *pname) } #endif - /* - * Set the machine NETBIOS name if not already - * set from the config file. - */ - if (!*global_myname) - { - fstrcpy(global_myname, dns_to_netbios_name(myhostname)); - } - strupper(global_myname); - #ifdef WITH_SSL { extern BOOL sslEnabled; @@ -679,40 +678,10 @@ static void usage(char *pname) codepage_initialise(lp_client_code_page()); - if (!pwdb_initialise(True)) - { - exit(1); - } - - if(!initialise_sam_password_db()) - { - exit(1); - } - - if(!initialise_passgrp_db()) - { - exit(1); - } + fstrcpy(global_myworkgroup, lp_workgroup()); - if(!initialise_group_db()) - { - exit(1); - } - - if(!initialise_alias_db()) - { - exit(1); - } - - if(!initialise_builtin_db()) - { - exit(1); - } - - if (!get_member_domain_sid()) - { - DEBUG(0,("ERROR: Samba cannot obtain PDC SID from PDC(s) %s.\n", - lp_passwordserver())); + if(!pdb_generate_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } @@ -746,7 +715,7 @@ static void usage(char *pname) become_daemon(); } - check_kernel_oplocks(); + check_kernel_oplocks(); if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); @@ -756,10 +725,13 @@ static void usage(char *pname) pidfile_create("smbd"); } - if (!open_sockets(is_daemon,port,port445)) + if (!locking_init(0)) exit(1); - if (!locking_init(0)) + if (!open_sockets(is_daemon,port)) + exit(1); + + if(!initialize_password_db()) exit(1); /* possibly reload the services file. */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 64abf3de1d..92807e2d43 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -23,7 +23,7 @@ extern int DEBUGLEVEL; -extern time_t smb_last_time; +extern struct timeval smb_last_time; extern int case_default; extern BOOL case_preserve; extern BOOL short_case_preserve; @@ -49,7 +49,7 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir) return(False); } - conn->lastused = smb_last_time; + conn->lastused = smb_last_time.tv_sec; snum = SNUM(conn); @@ -84,24 +84,23 @@ int find_service(char *service) { int iService; - string_sub(service,"\\","/"); + all_string_sub(service,"\\","/",0); iService = lp_servicenumber(service); /* now handle the special case of a home directory */ if (iService < 0) { - char *phome_dir = get_unixhome_dir(service); - pstring home_dir; + char *phome_dir = get_user_home_dir(service); - if(phome_dir == NULL) + if(!phome_dir) { /* * Try mapping the servicename, it may * be a Windows to unix mapped user name. */ if(map_username(service)) - phome_dir = get_unixhome_dir(service); + phome_dir = get_user_home_dir(service); } DEBUG(3,("checking for home directory %s gave %s\n",service, @@ -110,10 +109,9 @@ int find_service(char *service) if (phome_dir) { int iHomeService; - pstrcpy(home_dir, phome_dir); if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) { - lp_add_home(service,iHomeService,home_dir); + lp_add_home(service,iHomeService,phome_dir); iService = lp_servicenumber(service); } } @@ -144,11 +142,6 @@ int find_service(char *service) } } - /* Check for default vfs service? Unsure whether to implement this */ - if (iService < 0) - { - } - /* just possibly it's a default service? */ if (iService < 0) { @@ -168,7 +161,7 @@ int find_service(char *service) iService = find_service(defservice); if (iService >= 0) { - string_sub(service,"_","/"); + all_string_sub(service,"_","/",0); iService = lp_add_service(service,iService); } } @@ -194,11 +187,12 @@ int find_service(char *service) connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode) { int snum; - const struct passwd *pass = NULL; + struct passwd *pass = NULL; BOOL guest = False; BOOL force = False; extern int Client; connection_struct *conn; + int ret; strlower(service); @@ -218,21 +212,31 @@ connection_struct *make_connection(char *service,char *user,char *password, int } if (strequal(service,HOMES_NAME)) { - if (*user && Get_Pwnam(user,True)) - return(make_connection(user,user,password, + if (*user && Get_Pwnam(user,True)) { + fstring dos_username; + fstrcpy(dos_username, user); + unix_to_dos(dos_username, True); + return(make_connection(dos_username,user,password, pwlen,dev,vuid,ecode)); + } if(lp_security() != SEC_SHARE) { if (validated_username(vuid)) { - pstrcpy(user,validated_username(vuid)); - return(make_connection(user,user,password,pwlen,dev,vuid,ecode)); + fstring dos_username; + fstrcpy(user,validated_username(vuid)); + fstrcpy(dos_username, user); + unix_to_dos(dos_username, True); + return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); } } else { /* Security = share. Try with sesssetup_user * as the username. */ if(*sesssetup_user) { - pstrcpy(user,sesssetup_user); - return(make_connection(user,user,password,pwlen,dev,vuid,ecode)); + fstring dos_username; + fstrcpy(user,sesssetup_user); + fstrcpy(dos_username, user); + unix_to_dos(dos_username, True); + return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); } } } @@ -300,13 +304,13 @@ connection_struct *make_connection(char *service,char *user,char *password, int { pstring list; StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); + pstring_sub(list,"%S",service); if (user_in_list(user,list)) conn->read_only = True; StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); + pstring_sub(list,"%S",service); if (user_in_list(user,list)) conn->read_only = False; @@ -333,6 +337,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->vuid = vuid; conn->uid = pass->pw_uid; conn->gid = pass->pw_gid; + safe_strcpy(conn->client_address, client_addr(Client), sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = time(NULL); conn->service = snum; @@ -345,65 +350,83 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->veto_oplock_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); + + /* + * If force user is true, then store the + * given userid and also the primary groupid + * of the user we're forcing. + */ + + if (*lp_force_user(snum)) { + struct passwd *pass2; + pstring fuser; + pstrcpy(fuser,lp_force_user(snum)); - /* Initialise VFS function pointers */ - - if (*lp_vfsobj(SNUM(conn))) { - -#ifdef HAVE_LIBDL - - /* Loadable object file */ - - if (!vfs_init_custom(conn)) { - return NULL; - } -#else - DEBUG(0, ("No libdl present - cannot use VFS objects\n")); - conn_free(conn); - return NULL; -#endif - - } else { - - /* Normal share - initialise with disk access functions */ + /* Allow %S to be used by force user. */ + pstring_sub(fuser,"%S",service); - vfs_init_default(conn); + pass2 = (struct passwd *)Get_Pwnam(fuser,True); + if (pass2) { + conn->uid = pass2->pw_uid; + conn->gid = pass2->pw_gid; + string_set(&conn->user,fuser); + fstrcpy(user,fuser); + conn->force_user = True; + DEBUG(3,("Forced user %s\n",fuser)); + } else { + DEBUG(1,("Couldn't find user %s\n",fuser)); + } } #ifdef HAVE_GETGRNAM + /* + * If force group is true, then override + * any groupid stored for the connecting user. + */ + if (*lp_force_group(snum)) { struct group *gptr; pstring gname; + pstring tmp_gname; + BOOL user_must_be_member = False; - StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1); + StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1); + + if (tmp_gname[0] == '+') { + user_must_be_member = True; + StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2); + } else { + StrnCpy(gname,tmp_gname,sizeof(pstring)-1); + } /* default service may be a group name */ - string_sub(gname,"%S",service); + pstring_sub(gname,"%S",service); gptr = (struct group *)getgrnam(gname); if (gptr) { - conn->gid = gptr->gr_gid; - DEBUG(3,("Forced group %s\n",gname)); + /* + * If the user has been forced and the forced group starts + * with a '+', then we only set the group to be the forced + * group if the forced user is a member of that group. + * Otherwise, the meaning of the '+' would be ignored. + */ + if (conn->force_user && user_must_be_member) { + int i; + for (i = 0; gptr->gr_mem[i] != NULL; i++) { + if (strcmp(user,gptr->gr_mem[i]) == 0) { + conn->gid = gptr->gr_gid; + DEBUG(3,("Forced group %s for member %s\n",gname,user)); + break; + } + } + } else { + conn->gid = gptr->gr_gid; + DEBUG(3,("Forced group %s\n",gname)); + } } else { DEBUG(1,("Couldn't find group %s\n",gname)); } } -#endif - - if (*lp_force_user(snum)) { - const struct passwd *pass2; - fstring fuser; - fstrcpy(fuser,lp_force_user(snum)); - pass2 = (const struct passwd *)Get_Pwnam(fuser,True); - if (pass2) { - conn->uid = pass2->pw_uid; - string_set(&conn->user,fuser); - fstrcpy(user,fuser); - conn->force_user = True; - DEBUG(3,("Forced user %s\n",fuser)); - } else { - DEBUG(1,("Couldn't find user %s\n",fuser)); - } - } +#endif /* HAVE_GETGRNAM */ { pstring s; @@ -420,7 +443,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!IS_IPC(conn)) { /* Find all the groups this uid is in and store them. Used by become_user() */ - get_unixgroups(conn->user,conn->uid,conn->gid, + setup_groups(conn->user,conn->uid,conn->gid, &conn->ngroups,&conn->groups); /* check number of connections */ @@ -445,7 +468,13 @@ connection_struct *make_connection(char *service,char *user,char *password, int pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); standard_sub(conn,cmd); DEBUG(5,("cmd=%s\n",cmd)); - smbrun(cmd,NULL,False); + ret = smbrun(cmd,NULL,False); + if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { + DEBUG(1,("preexec gave %d - failing connection\n", ret)); + conn_free(conn); + *ecode = ERRsrverror; + return NULL; + } } if (!become_user(conn, conn->vuid)) { @@ -499,7 +528,26 @@ connection_struct *make_connection(char *service,char *user,char *password, int pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); standard_sub(conn,cmd); - smbrun(cmd,NULL,False); + ret = smbrun(cmd,NULL,False); + if (ret != 0 && lp_preexec_close(SNUM(conn))) { + DEBUG(1,("preexec gave %d - failing connection\n", ret)); + conn_free(conn); + *ecode = ERRsrverror; + return NULL; + } + } + + /* + * Print out the 'connected as' stuff here as we need + * to know the effective uid and gid we will be using. + */ + + if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { + dbgtext( "%s (%s) ", remote_machine, conn->client_address ); + dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); + dbgtext( "as user %s ", user ); + dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); + dbgtext( "(pid %d)\n", (int)getpid() ); } /* we've finished with the sensitive stuff */ @@ -512,61 +560,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn))); } - if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { - extern int Client; - - dbgtext( "%s (%s) ", remote_machine, client_addr(Client) ); - dbgtext( "connect to service %s ", lp_servicename(SNUM(conn))); - dbgtext( "as user %s ", user ); - dbgtext( "(uid=%d, gid=%d) ", (int)conn->uid, (int)conn->gid ); - dbgtext( "(pid %d)\n", (int)getpid() ); - } - - /* Invoke make connection hook */ - - if (conn->vfs_ops.connect) { - struct vfs_connection_struct *vconn; - - vconn = (struct vfs_connection_struct *) - malloc(sizeof(struct vfs_connection_struct)); - - if (vconn == NULL) { - DEBUG(0, ("No memory to create vfs_connection_struct")); - return NULL; - } - - ZERO_STRUCTP(vconn); - - /* Copy across relevant data from connection struct */ - - vconn->printer = conn->printer; - vconn->ipc = conn->ipc; - vconn->read_only = conn->read_only; - vconn->admin_user = conn->admin_user; - - pstrcpy(vconn->dirpath, conn->dirpath); - pstrcpy(vconn->connectpath, conn->connectpath); - pstrcpy(vconn->origpath, conn->origpath); - - pstrcpy(vconn->service, service); - pstrcpy(vconn->user, conn->user); - - vconn->uid = conn->uid; - vconn->gid = conn->gid; - vconn->ngroups = conn->ngroups; - vconn->groups = (gid_t *)malloc(conn->ngroups * sizeof(gid_t)); - if (vconn->groups != NULL) { - memcpy(vconn->groups, conn->groups, - conn->ngroups * sizeof(gid_t)); - } - - /* Call connect hook */ - - if (conn->vfs_ops.connect(vconn, service, user) < 0) { - return NULL; - } - } - return(conn); } @@ -576,31 +569,14 @@ close a cnum ****************************************************************************/ void close_cnum(connection_struct *conn, uint16 vuid) { - extern int Client; DirCacheFlush(SNUM(conn)); unbecome_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", - remote_machine,client_addr(Client), + remote_machine,conn->client_address, lp_servicename(SNUM(conn)))); - if (conn->vfs_ops.disconnect != NULL) { - - /* Call disconnect hook */ - - conn->vfs_ops.disconnect(); - - /* Free vfs_connection_struct */ - - if (conn->vfs_conn != NULL) { - if (conn->vfs_conn->groups != NULL) { - free(conn->vfs_conn->groups); - } - free(conn->vfs_conn); - } - } - yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); @@ -632,5 +608,3 @@ void close_cnum(connection_struct *conn, uint16 vuid) conn_free(conn); } - - diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index 1f098b2533..be9aae7c5c 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -19,14 +19,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "includes.h" - -/* - * Hmmm, only check on WITH_SSL after we have included includes.h - * which pulls in config.h which is where WITH_SSL is defined, if - * at all :-) +/* + * since includes.h pulls in config.h which is were WITH_SSL will be + * defined, we want to include includes.h before testing for WITH_SSL + * RJS 26-Jan-1999 */ +#include "includes.h" + #ifdef WITH_SSL /* should always be defined if this module is compiled */ #include diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 14fa26dd55..e971f8bbb6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -31,7 +31,7 @@ extern int Client; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; -extern dfs_internal dfs_struct; +extern uint32 global_client_caps; /**************************************************************************** Send the required number of replies back. @@ -113,8 +113,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, SSVAL(outbuf,smb_prcnt, params_sent_thistime); if(params_sent_thistime == 0) { - /*SSVAL(outbuf,smb_proff,0);*/ - SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + SSVAL(outbuf,smb_proff,0); SSVAL(outbuf,smb_prdisp,0); } else @@ -216,11 +215,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, /* XXXX we need to handle passed times, sattr and flags */ - if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); if (!fsp) @@ -253,7 +248,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -272,7 +267,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); - bzero(params,28); + memset((char *)params,'\0',28); SSVAL(params,0,fsp->fnum); SSVAL(params,2,fmode); put_dos_date2(params,4, mtime); @@ -298,12 +293,12 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, /**************************************************************************** get a level dependent lanman2 dir entry. ****************************************************************************/ -static int get_lanman2_dir_entry(connection_struct *conn, +static BOOL get_lanman2_dir_entry(connection_struct *conn, char *path_mask,int dirtype,int info_level, int requires_resume_key, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, - BOOL *out_of_space, + BOOL *out_of_space, BOOL *got_exact_match, int *last_name_off) { char *dname; @@ -329,6 +324,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, *fname = 0; *out_of_space = False; + *got_exact_match = False; if (!conn->dirptr) return(False); @@ -346,6 +342,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, while (!found) { + BOOL got_match; + /* Needed if we run out of space */ prev_dirpos = TellDir(conn->dirptr); dname = ReadDirName(conn->dirptr); @@ -367,7 +365,26 @@ static int get_lanman2_dir_entry(connection_struct *conn, pstrcpy(fname,dname); - if(mask_match(fname, mask, case_sensitive, True)) + if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) + got_match = mask_match(fname, mask, case_sensitive, True); + + if(!got_match && !is_8_3(fname, False)) { + + /* + * It turns out that NT matches wildcards against + * both long *and* short names. This may explain some + * of the wildcard wierdness from old DOS clients + * that some people have been seeing.... JRA. + */ + + pstring newname; + pstrcpy( newname, fname); + name_map_mangle( newname, True, False, SNUM(conn)); + if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive))) + got_match = mask_match(newname, mask, case_sensitive, True); + } + + if(got_match) { BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); if (dont_descend && !isdots) @@ -380,7 +397,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) + if (dos_stat(pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); continue; @@ -406,7 +423,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, } } - name_map_mangle(fname,False,SNUM(conn)); + name_map_mangle(fname,False,True,SNUM(conn)); p = pdata; nameptr = p; @@ -502,7 +519,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,0); p += 4; if (!was_8_3) { pstrcpy(p+2,fname); - if (!name_map_mangle(p+2,True,SNUM(conn))) + if (!name_map_mangle(p+2,True,True,SNUM(conn))) (p+2)[12] = 0; } else *(p+2) = 0; @@ -579,6 +596,7 @@ static int get_lanman2_dir_entry(connection_struct *conn, *last_name_off = PTR_DIFF(nameptr,base_data); /* Advance the data pointer to the next slot */ *ppdata = p; + return(found); } @@ -610,8 +628,9 @@ void mask_convert( char *mask) } /**************************************************************************** - reply to a TRANS2_FINDFIRST + Reply to a TRANS2_FINDFIRST. ****************************************************************************/ + static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, char **pparams, char **ppdata) @@ -669,11 +688,7 @@ static int call_trans2findfirst(connection_struct *conn, DEBUG(5,("path=%s\n",directory)); - if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(directory,conn,0,&bad_path,NULL); if(!check_name(directory,conn)) { if((errno == ENOENT) && bad_path) { @@ -708,40 +723,25 @@ static int call_trans2findfirst(connection_struct *conn, pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024); if(!*ppdata) return(ERROR(ERRDOS,ERRnomem)); - bzero(pdata,max_data_bytes); + memset((char *)pdata,'\0',max_data_bytes + 1024); /* Realloc the params space */ params = *pparams = Realloc(*pparams, 10); if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); - dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid)); + dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); if (dptr_num < 0) return(UNIXERROR(ERRDOS,ERRbadfile)); /* Convert the formatted mask. */ mask_convert(mask); -#if 0 /* JRA */ - /* - * Now we have a working mask_match in util.c, I believe - * we no longer need these hacks (in fact they break - * things). JRA. - */ - - /* a special case for 16 bit apps */ - if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - - /* handle broken clients that send us old 8.3 format */ - string_sub(mask,"????????","*"); - string_sub(mask,".???",".*"); -#endif /* JRA */ - /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ if(!(wcard = strdup(mask))) { - dptr_close(dptr_num); + dptr_close(&dptr_num); return(ERROR(ERRDOS,ERRnomem)); } @@ -763,39 +763,49 @@ static int call_trans2findfirst(connection_struct *conn, out_of_space = False; for (i=0;(i 0) { + out_of_space = True; + finished = False; + } + else + { + finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level, + requires_resume_key,dont_descend, + &p,pdata,space_remaining, &out_of_space, &got_exact_match, + &last_name_off); + } - /* this is a heuristic to avoid seeking the dirptr except when - absolutely necessary. It allows for a filename of about 40 chars */ - if (space_remaining < DIRLEN_GUESS && numentries > 0) - { - out_of_space = True; - finished = False; - } - else - { - finished = - !get_lanman2_dir_entry(conn,mask,dirtype,info_level, - requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, - &last_name_off); - } + if (finished && out_of_space) + finished = False; - if (finished && out_of_space) - finished = False; + if (!finished && !out_of_space) + numentries++; - if (!finished && !out_of_space) - numentries++; - space_remaining = max_data_bytes - PTR_DIFF(p,pdata); - } + /* + * As an optimisation if we know we aren't looking + * for a wildcard name (ie. the name matches the wildcard exactly) + * then we can finish on any (first) match. + * This speeds up large directory searches. JRA. + */ + + if(got_exact_match) + finished = True; + + space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + } /* Check if we can close the dirptr */ if(close_after_first || (finished && close_if_end)) - { - dptr_close(dptr_num); - DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); - dptr_num = -1; - } + { + DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); + dptr_close(&dptr_num); + } /* * If there are no matching entries we must return ERRDOS/ERRbadfile - @@ -803,7 +813,10 @@ static int call_trans2findfirst(connection_struct *conn, */ if(numentries == 0) + { + dptr_close(&dptr_num); return(ERROR(ERRDOS,ERRbadfile)); + } /* At this point pdata points to numentries directory entries. */ @@ -823,6 +836,17 @@ static int call_trans2findfirst(connection_struct *conn, smb_fn_name(CVAL(inbuf,smb_com)), mask, directory, dirtype, numentries ) ); + /* + * Force a name mangle here to ensure that the + * mask as an 8.3 name is top of the mangled cache. + * The reasons for this are subtle. Don't remove + * this code unless you know what you are doing + * (see PR#13758). JRA. + */ + + if(!is_8_3( mask, False)) + name_map_mangle(mask, True, True, SNUM(conn)); + return(-1); } @@ -843,7 +867,7 @@ static int call_trans2findnext(connection_struct *conn, int max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *params = *pparams; char *pdata = *ppdata; - int16 dptr_num = SVAL(params,0); + int dptr_num = SVAL(params,0); int maxentries = SVAL(params,2); uint16 info_level = SVAL(params,4); uint32 resume_key = IVAL(params,6); @@ -891,7 +915,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024); if(!*ppdata) return(ERROR(ERRDOS,ERRnomem)); - bzero(pdata,max_data_bytes); + memset((char *)pdata,'\0',max_data_bytes + 1024); /* Realloc the params space */ params = *pparams = Realloc(*pparams, 6*SIZEOFWORD); @@ -968,7 +992,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", */ if(dname != NULL) - name_map_mangle( dname, False, SNUM(conn)); + name_map_mangle( dname, False, True, SNUM(conn)); if(dname && strcsequal( resume_name, dname)) { @@ -996,7 +1020,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", */ if(dname != NULL) - name_map_mangle( dname, False, SNUM(conn)); + name_map_mangle( dname, False, True, SNUM(conn)); if(dname && strcsequal( resume_name, dname)) { @@ -1009,38 +1033,49 @@ resume_key = %d resume name = %s continue=%d level = %d\n", } /* end if requires_resume_key && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) + { + BOOL got_exact_match; + + /* this is a heuristic to avoid seeking the dirptr except when + absolutely necessary. It allows for a filename of about 40 chars */ + if (space_remaining < DIRLEN_GUESS && numentries > 0) { - /* this is a heuristic to avoid seeking the dirptr except when - absolutely necessary. It allows for a filename of about 40 chars */ - if (space_remaining < DIRLEN_GUESS && numentries > 0) - { - out_of_space = True; - finished = False; - } - else - { - finished = - !get_lanman2_dir_entry(conn,mask,dirtype,info_level, - requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, - &last_name_off); - } + out_of_space = True; + finished = False; + } + else + { + finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level, + requires_resume_key,dont_descend, + &p,pdata,space_remaining, &out_of_space, &got_exact_match, + &last_name_off); + } - if (finished && out_of_space) - finished = False; + if (finished && out_of_space) + finished = False; - if (!finished && !out_of_space) - numentries++; - space_remaining = max_data_bytes - PTR_DIFF(p,pdata); - } + if (!finished && !out_of_space) + numentries++; + + /* + * As an optimisation if we know we aren't looking + * for a wildcard name (ie. the name matches the wildcard exactly) + * then we can finish on any (first) match. + * This speeds up large directory searches. JRA. + */ + + if(got_exact_match) + finished = True; + + space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + } /* Check if we can close the dirptr */ if(close_after_request || (finished && close_if_end)) - { - dptr_close(dptr_num); /* This frees up the saved mask */ - DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); - dptr_num = -1; - } + { + DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); + dptr_close(&dptr_num); /* This frees up the saved mask */ + } /* Set up the return parameter block */ @@ -1070,6 +1105,7 @@ static int call_trans2qfsinfo(connection_struct *conn, int length, int bufsize, char **pparams, char **ppdata) { + int max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *pdata = *ppdata; char *params = *pparams; uint16 info_level = SVAL(params,0); @@ -1078,16 +1114,16 @@ static int call_trans2qfsinfo(connection_struct *conn, char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); - extern uint32 global_client_caps; DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(conn->vfs_ops.stat(".",&st)!=0) { + if(dos_stat(".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return (ERROR(ERRSRV,ERRinvdevice)); } - pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024); + pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024); + memset((char *)pdata,'\0',max_data_bytes + 1024); switch (info_level) { @@ -1095,7 +1131,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; - conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize); + sys_disk_free(".",False,&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); SIVAL(pdata,l1_cSectorUnit,bsize/512); SIVAL(pdata,l1_cUnit,dsize); @@ -1124,16 +1160,21 @@ static int call_trans2qfsinfo(connection_struct *conn, break; } case SMB_QUERY_FS_ATTRIBUTE_INFO: - data_len = 12 + 2*strlen(fstype); - SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH); /* FS ATTRIBUTES */ + { + int fstype_len; + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| + lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0); /* FS ATTRIBUTES */ #if 0 /* Old code. JRA. */ SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ #endif /* Old code. */ + SIVAL(pdata,4,128); /* Max filename component length */ - SIVAL(pdata,8,2*strlen(fstype)); - ascii_to_unibuf(pdata+12, fstype, 1024-2-12); + fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring)/2); + SIVAL(pdata,8,fstype_len); + data_len = 12 + fstype_len; SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); break; + } case SMB_QUERY_FS_LABEL_INFO: data_len = 4 + strlen(vname); SIVAL(pdata,0,strlen(vname)); @@ -1158,19 +1199,19 @@ static int call_trans2qfsinfo(connection_struct *conn, } else { data_len = 18 + 2*strlen(vname); SIVAL(pdata,12,strlen(vname)*2); - ascii_to_unibuf(pdata+18, vname, 1024-2-18); + dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring)/2); } DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", - strlen(vname),vname)); + (int)strlen(vname),vname)); break; case SMB_QUERY_FS_SIZE_INFO: { SMB_BIG_UINT dfree,dsize,bsize; data_len = 24; - conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize); - SIVAL(pdata,0,dsize); - SIVAL(pdata,8,dfree); + sys_disk_free(".",False,&bsize,&dfree,&dsize); + SBIG_UINT(pdata,0,dsize); + SBIG_UINT(pdata,8,dfree); SIVAL(pdata,16,bsize/512); SIVAL(pdata,20,512); break; @@ -1236,6 +1277,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char **pparams,char **ppdata, int total_data) { + int max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *params = *pparams; char *pdata = *ppdata; uint16 tran_call = SVAL(inbuf, smb_setup0); @@ -1256,20 +1298,17 @@ static int call_trans2qfilepathinfo(connection_struct *conn, files_struct *fsp = file_fsp(params,0); info_level = SVAL(params,2); - if(fsp && fsp->open && fsp->is_directory) { + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); + + if(fsp && fsp->open && (fsp->is_directory || fsp->stat_open)) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems * to do this call. JRA. */ fname = fsp->fsp_name; - if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && - conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1278,6 +1317,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } return(UNIXERROR(ERRDOS,ERRbadpath)); } + + delete_pending = fsp->directory_delete_on_close; + } else { /* * Original code - this is an open file. @@ -1286,11 +1328,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); delete_pending = fsp->fd_ptr->delete_on_close; @@ -1298,16 +1340,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } else { /* qpathinfo */ info_level = SVAL(params,0); + + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); + fname = &fname1[0]; pstrcpy(fname,¶ms[6]); - if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False), - &sbuf))) { + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1335,8 +1374,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* from now on we only want the part after the / */ fname = p; - params = *pparams = Realloc(*pparams,2); bzero(params,2); - data_size = 1024; + params = *pparams = Realloc(*pparams,2); + memset((char *)params,'\0',2); + data_size = max_data_bytes + 1024; pdata = *ppdata = Realloc(*ppdata, data_size); if (total_data > 0 && IVAL(pdata,0) == total_data) { @@ -1345,7 +1385,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); } - bzero(pdata,data_size); + memset((char *)pdata,'\0',data_size); switch (info_level) { @@ -1416,26 +1456,37 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_ALT_NAME_INFO: { pstring short_name; - char *data_end; - pstrcpy(short_name,p); /* Mangle if not already 8.3 */ if(!is_8_3(short_name, True)) { - if(!name_map_mangle(short_name,True,SNUM(conn))) + if(!name_map_mangle(short_name,True,True,SNUM(conn))) *short_name = '\0'; } strupper(short_name); - data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-2-4); - data_size = data_end - pdata; - SIVAL(pdata,0,2*(data_size-4)); + l = strlen(short_name); + dos_PutUniCode(pdata + 4, unix_to_dos(short_name,False),sizeof(pstring)*2); + data_size = 4 + (2*l); + SIVAL(pdata,0,2*l); } break; case SMB_QUERY_FILE_NAME_INFO: + /* + * The first part of this code is essential + * to get security descriptors to work on mapped + * drives. Don't ask how I discovered this unless + * you like hearing about me suffering.... :-). JRA. + */ + if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) { + l = l*2; + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); + dos_PutUniCode(pdata + 4, unix_to_dos("\\",False),sizeof(pstring)*2); + } else { + pstrcpy(pdata+4,fname); + } data_size = 4 + l; SIVAL(pdata,0,l); - pstrcpy(pdata+4,fname); break; case SMB_QUERY_FILE_ALLOCATION_INFO: @@ -1527,20 +1578,15 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fsp = file_fsp(params,0); info_level = SVAL(params,2); - if(fsp && fsp->open && fsp->is_directory) { + if(fsp && fsp->open && (fsp->is_directory || fsp->stat_open)) { /* * This is actually a SETFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems * to do this call. JRA. */ fname = fsp->fsp_name; - if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - if (!check_name(fname,conn) || (!VALID_STAT(st) && - conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) { + unix_convert(fname,conn,0,&bad_path,&st); + if (!check_name(fname,conn) || (!VALID_STAT(st) && dos_stat(fname,&st))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1559,7 +1605,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; fd = fsp->fd_ptr->fd; - if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) { + if (sys_fstat(fd,&st) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1569,11 +1615,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = fname1; pstrcpy(fname,¶ms[6]); - if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(fname,conn,0,&bad_path,&st); if(!check_name(fname, conn)) { if((errno == ENOENT) && bad_path) @@ -1584,7 +1626,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) { + if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1599,10 +1641,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, tran_call,fname,info_level,total_data)); /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0); + params = *pparams = Realloc(*pparams,2); if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); + SSVAL(params,0,0); + size = st.st_size; tvs.modtime = st.st_mtime; tvs.actime = st.st_atime; @@ -1656,7 +1700,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, tvs.actime = interpret_long_date(pdata+8); /* write time + changed time, combined. */ - tvs.modtime=MAX(interpret_long_date(pdata+16), + tvs.modtime=MIN(interpret_long_date(pdata+16), interpret_long_date(pdata+24)); #if 0 /* Needs more testing... */ @@ -1672,6 +1716,26 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + /* + * NT seems to use this call with a size of zero + * to mean truncate the file. JRA. + */ + + case SMB_SET_FILE_ALLOCATION_INFO: + { + SMB_OFF_T newsize = IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + newsize |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) /* more than 32 bits? */ + return(ERROR(ERRDOS,ERRunknownlevel)); +#endif /* LARGE_SMB_OFF_T */ + DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)newsize )); + if(newsize == 0) + size = 0; + break; + } + case SMB_SET_FILE_END_OF_FILE_INFO: { size = IVAL(pdata,0); @@ -1681,12 +1745,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (IVAL(pdata,4) != 0) /* more than 32 bits? */ return(ERROR(ERRDOS,ERRunknownlevel)); #endif /* LARGE_SMB_OFF_T */ + DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size )); break; } - case SMB_SET_FILE_ALLOCATION_INFO: - break; /* We don't need to do anything for this call. */ - case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL)) @@ -1694,121 +1756,134 @@ static int call_trans2setfilepathinfo(connection_struct *conn, BOOL delete_on_close = (CVAL(pdata,0) ? True : False); if(fsp->is_directory) - return(ERROR(ERRDOS,ERRnoaccess)); - - /* - * We can only set the delete on close flag if - * the share mode contained ALLOW_SHARE_DELETE - */ + { + fsp->directory_delete_on_close = delete_on_close; + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - if(lp_share_modes(SNUM(conn))) + } + else if(fsp->stat_open) + { + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + } + else { - if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) - return(ERROR(ERRDOS,ERRnoaccess)); /* - * If the flag has been set then - * modify the share mode entry for all files we have open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. + * We can only set the delete on close flag if + * the share mode contained ALLOW_SHARE_DELETE */ - if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) + if(lp_share_modes(SNUM(conn))) { - int token; - int i; - files_struct *iterate_fsp; - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; - int num_share_modes; - share_mode_entry *current_shares = NULL; - - if(lock_share_entry(fsp->conn, dev, inode, &token) == False) + if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) return(ERROR(ERRDOS,ERRnoaccess)); /* - * Before we allow this we need to ensure that all current opens - * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they - * do not then we deny this (as we are essentially deleting the - * file at this point. + * If the flag has been set then + * modify the share mode entry for all files we have open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. */ - num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares); - for(i = 0; i < num_share_modes; i++) + if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) { - if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) + int token; + int i; + files_struct *iterate_fsp; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; + int num_share_modes; + share_mode_entry *current_shares = NULL; + + if(lock_share_entry(fsp->conn, dev, inode, &token) == False) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * Before we allow this we need to ensure that all current opens + * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they + * do not then we deny this (as we are essentially deleting the + * file at this point. + */ + + num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares); + for(i = 0; i < num_share_modes; i++) { - DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \ + if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) + { + DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \ file %s as a share exists that was not opened with FILE_DELETE access.\n", - fsp->fnum, fsp->fsp_name )); - /* - * Release the lock. - */ + fsp->fnum, fsp->fsp_name )); + /* + * Release the lock. + */ - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode, token); - /* - * current_shares was malloced by get_share_modes - free it here. - */ + /* + * current_shares was malloced by get_share_modes - free it here. + */ - free((char *)current_shares); + free((char *)current_shares); - /* - * Even though share violation would be more appropriate here, - * return ERRnoaccess as that's what NT does. - */ + /* + * Even though share violation would be more appropriate here, + * return ERRnoaccess as that's what NT does. + */ - return(ERROR(ERRDOS,ERRnoaccess)); + return(ERROR(ERRDOS,ERRnoaccess)); + } } - } - /* - * current_shares was malloced by get_share_modes - free it here. - */ + /* + * current_shares was malloced by get_share_modes - free it here. + */ - free((char *)current_shares); + free((char *)current_shares); - DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - /* - * Go through all files we have open on the same device and - * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. - * Other smbd's that have this file open will have to fend for themselves. We - * take care of this (rare) case in close_file(). See the comment there. - */ + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + * Other smbd's that have this file open will have to fend for themselves. We + * take care of this (rare) case in close_file(). See the comment there. + */ - for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; - iterate_fsp = file_find_di_next(iterate_fsp)) - { - int new_share_mode = (delete_on_close ? - (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : - (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; + iterate_fsp = file_find_di_next(iterate_fsp)) + { + int new_share_mode = (delete_on_close ? + (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : + (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); - DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \ + DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \ dev = %x, inode = %.0f from %x to %x\n", - iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, - (double)inode, iterate_fsp->share_mode, new_share_mode )); + iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, + (double)inode, iterate_fsp->share_mode, new_share_mode )); - if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) - DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ + if(modify_share_mode(token, iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False) + DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)); - } + } - /* - * Set the delete on close flag in the reference - * counted struct. Delete when the last reference - * goes away. - */ - fsp->fd_ptr->delete_on_close = delete_on_close; - unlock_share_entry(fsp->conn, dev, inode, token); + /* + * Set the delete on close flag in the reference + * counted struct. Delete when the last reference + * goes away. + */ + fsp->fd_ptr->delete_on_close = delete_on_close; - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + unlock_share_entry(fsp->conn, dev, inode, token); - } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */ - } /* end if lp_share_modes() */ + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */ + } /* end if lp_share_modes() */ + } /* end if is_directory. */ } else return(ERROR(ERRDOS,ERRunknownlevel)); break; @@ -1820,23 +1895,33 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) } } + /* get some defaults (no modifications) if any info is zero or -1. */ + if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1) + tvs.actime = st.st_atime; + + if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) + tvs.modtime = st.st_mtime; + DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); DEBUG(6,("size: %.0f ", (double)size)); DEBUG(6,("mode: %x\n" , mode)); - /* get some defaults (no modifications) if any info is zero. */ - if (!tvs.actime) tvs.actime = st.st_atime; - if (!tvs.modtime) tvs.modtime = st.st_mtime; - if (!size) size = st.st_size; + if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || + (info_level == SMB_SET_FILE_ALLOCATION_INFO))) { + /* + * Only do this test if we are not explicitly + * changing the size of a file. + */ + if (!size) + size = st.st_size; + } /* Try and set the times, size and mode of this file - if they are different from the current values */ - if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) - { - if(fsp != NULL) - { + if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { + if(fsp != NULL) { /* * This was a setfileinfo on an open file. * NT does this a lot. It's actually pointless @@ -1844,38 +1929,51 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) * on the next write, so we save the request * away and will set it on file code. JRA. */ - fsp->pending_modtime = tvs.modtime; - } - else if(file_utime(conn, fname, &tvs)!=0) - { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { + DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", + ctime(&tvs.modtime) )); + fsp->pending_modtime = tvs.modtime; + } + + } else { + + DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); + + if(file_utime(conn, fname, &tvs)!=0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); } } /* check the mode isn't different, before changing it */ - if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL)) - { - DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if ((mode != 0) && (mode != dos_mode(conn, fname, &st))) { + + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", + fname, mode )); + + if(file_chmod(conn, fname, mode, NULL)) { + DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } - if(size != st.st_size) - { - if (fd == -1) - { -DEBUG(0, ("@@@ 23 @@@\n")); + if(size != st.st_size) { + + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", + fname, (double)size )); + + if (fd == -1) { fd = dos_open(fname,O_RDWR,0); if (fd == -1) - { return(UNIXERROR(ERRDOS,ERRbadpath)); - } set_filelen(fd, size); close(fd); - } - else - { + } else { set_filelen(fd, size); } + + if(fsp) + set_filelen_write_cache(fsp, size); } SSVAL(params,0,0); @@ -1904,14 +2002,9 @@ static int call_trans2mkdir(connection_struct *conn, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) - { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } + unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory,conn)) - ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), - unix_mode(conn,aDIR)); + ret = dos_mkdir(directory,unix_mode(conn,aDIR)); if(ret < 0) { @@ -2012,11 +2105,11 @@ int reply_findclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { int outsize = 0; - int16 dptr_num=SVALS(inbuf,smb_vwv0); + int dptr_num=SVALS(inbuf,smb_vwv0); DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num)); - dptr_close(dptr_num); + dptr_close(&dptr_num); outsize = set_message(outbuf,0,0,True); @@ -2049,237 +2142,6 @@ int reply_findnclose(connection_struct *conn, return(outsize); } -#define UNICODE_DFS - -/**************************************************************************** - reply to a TRANS2_GET_DFS_REFERRAL - ****************************************************************************/ -static int call_trans2getdfsreferral(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **pparams, char **ppdata, - int total_data) -{ - char *params = *pparams; - char *pdata; - char *pheader; - char *localstring_offset; - char *mangledstring_offset; - char *sharename_offset; - char *referal_offset; - - int i; - int j; - unsigned int total_params = SVAL(inbuf, smb_tpscnt); - int query_file_len=0; - int bytesreq=0; - int filename_len; - - BOOL first_one=True; - - referal_trans_param rtp; - dfs_internal_table *list=dfs_struct.table; - dfs_response reply; - - DEBUG(0,("call_trans2getdfsreferral:1\n")); - - ZERO_STRUCT(rtp); - ZERO_STRUCT(reply); - - /* decode the param member of query */ - rtp.level=SVAL(params, 0); - DEBUGADD(0,("rtp.level:[%d]\n",rtp.level)); - - DEBUGADD(0,("total_params:[%d]\n",total_params)); - for (i=0; i<(total_params-2)/2; i++) - { - rtp.directory[i]=SVAL(params, 2+2*i); - } -/* - strupper(rtp.directory); -*/ - query_file_len=strlen(rtp.directory); - DEBUGADD(0,("rtp.directory:[%s]\n",rtp.directory)); - DEBUGADD(0,("query_file_len:[%d]\n",query_file_len)); - - /* - lookup in the internal DFS table all the entries - and calculate the required data buffer size - */ - bytesreq=8; /* the header */ - reply.number_of_referal=0; - DEBUGADD(0,("call_trans2getdfsreferral:2\n")); - - for(i=0; i (uid_t)32000) { - DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n")); - } - return(False); - } - - if (((uid == (uid_t)-1) || ((sizeof(uid_t) == 2) && (uid == 65535))) && (geteuid() != uid)) { - DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n")); - return(False); - } + set_effective_uid(uid); - current_user.uid = uid; + current_user.uid = uid; #ifdef WITH_PROFILE - profile_p->uid_changes++; + profile_p->uid_changes++; #endif - return(True); + return(True); } /**************************************************************************** - become the specified gid + Become the specified gid. ****************************************************************************/ + static BOOL become_gid(gid_t gid) { - if (initial_uid != 0) - return(True); - - if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) && (gid == (gid_t)65535))) { - DEBUG(1,("WARNING: using gid %d is a security risk\n",(int)gid)); - } - -#ifdef HAVE_SETRESUID - 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", - (int)gid,(int)getgid(),(int)getegid())); - if (gid > 32000) { - DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); + if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) && (gid == (gid_t)65535))) { + DEBUG(1,("WARNING: using gid %d is a security risk\n",(int)gid)); } - return(False); - } - - current_user.gid = gid; - - return(True); + + set_effective_gid(gid); + + current_user.gid = gid; + + return(True); } /**************************************************************************** - become the specified uid and gid + Become the specified uid and gid. ****************************************************************************/ + static BOOL become_id(uid_t uid,gid_t gid) { return(become_gid(gid) && become_uid(uid)); } /**************************************************************************** -become the guest user + Become the guest user. ****************************************************************************/ + BOOL become_guest(void) { BOOL ret; - static const struct passwd *pass=NULL; - - if (initial_uid != 0) - return(True); + static struct passwd *pass=NULL; if (!pass) pass = Get_Pwnam(lp_guestaccount(-1),True); @@ -193,138 +131,43 @@ BOOL become_guest(void) } /******************************************************************* -check if a username is OK + Check if a username is OK. ********************************************************************/ -static BOOL check_vuser_ok(struct uid_cache *cache, user_struct *vuser,int snum) + +static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { int i; - for (i=0;ientries;i++) - if (cache->list[i] == vuser->uid) return(True); + for (i=0;iuid_cache.entries;i++) + if (conn->uid_cache.list[i] == vuser->uid) return(True); if (!user_ok(vuser->name,snum)) return(False); - i = cache->entries % UID_CACHE_SIZE; - cache->list[i] = vuser->uid; + i = conn->uid_cache.entries % UID_CACHE_SIZE; + conn->uid_cache.list[i] = vuser->uid; - if (cache->entries < UID_CACHE_SIZE) - cache->entries++; + if (conn->uid_cache.entries < UID_CACHE_SIZE) + conn->uid_cache.entries++; return(True); } /**************************************************************************** - become the user of a connection number -****************************************************************************/ -BOOL become_vuser(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - gid_t gid; - uid_t uid; - - unbecome_vuser(); - - if((vuser != NULL) && !check_vuser_ok(&vcache, vuser, -1)) - return False; - - if ( vuser != 0 && - current_user.vuid == vuid && - current_user.uid == vuser->uid) - { - DEBUG(4,("Skipping become_vuser - already user\n")); - return(True); - } - uid = vuser->uid; - gid = vuser->gid; - current_user.ngroups = vuser->n_groups; - current_user.groups = vuser->groups; - - if (initial_uid == 0) - { - if (!become_gid(gid)) return(False); - -#ifdef HAVE_SETGROUPS - /* 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 (!become_uid(uid)) return(False); - } - - current_user.conn = NULL; - current_user.vuid = vuid; - - DEBUG(5,("become_vuser uid=(%d,%d) gid=(%d,%d)\n", - (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - - return(True); -} - -/**************************************************************************** - unbecome a user + Become the user of a connection number. ****************************************************************************/ -BOOL unbecome_vuser(void) -{ - dos_ChDir(OriginalDir); - - if (initial_uid == 0) - { -#ifdef HAVE_SETRESUID - 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 - current_user.uid = initial_uid; - current_user.gid = initial_gid; - - if (dos_ChDir(OriginalDir) != 0) - DEBUG( 0, ( "chdir(%s) failed in unbecome_vuser\n", OriginalDir ) ); - - DEBUG(5,("unbecome_vuser now uid=(%d,%d) gid=(%d,%d)\n", - (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - - current_user.conn = NULL; - current_user.vuid = UID_FIELD_INVALID; - - return(True); -} - -/**************************************************************************** - become the user of a connection number -****************************************************************************/ BOOL become_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; - gid_t gid; + gid_t gid; uid_t uid; + char group_c; + + if (!conn) { + DEBUG(2,("Connection not open\n")); + return(False); + } /* * We need a separate check in security=share mode due to vuid @@ -346,14 +189,9 @@ BOOL become_user(connection_struct *conn, uint16 vuid) unbecome_user(); - if (!conn) { - DEBUG(2,("Connection not open\n")); - return(False); - } - snum = SNUM(conn); - if((vuser != NULL) && !check_vuser_ok(&conn->uid_cache, vuser, snum)) + if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) return False; if (conn->force_user || @@ -369,32 +207,55 @@ BOOL become_user(connection_struct *conn, uint16 vuid) return(False); } uid = vuser->uid; - if(!*lp_force_group(snum)) { - gid = vuser->gid; + gid = vuser->gid; + current_user.ngroups = vuser->n_groups; + current_user.groups = vuser->groups; + } + + /* + * See if we should force group for this service. + * If so this overrides any group set in the force + * user code. + */ + + if((group_c = *lp_force_group(snum))) { + if(group_c == '+') { + + /* + * Only force group if the user is a member of + * the service group. Check the group memberships for + * this user (we already have this) to + * see if we should force the group. + */ + + int i; + for (i = 0; i < current_user.ngroups; i++) { + if (current_user.groups[i] == conn->gid) { + gid = conn->gid; + break; + } + } } else { gid = conn->gid; } - current_user.ngroups = vuser->n_groups; - current_user.groups = vuser->groups; } - if (initial_uid == 0) { - if (!become_gid(gid)) return(False); + if (!become_gid(gid)) + return(False); #ifdef HAVE_SETGROUPS - if (!(conn && conn->ipc)) { - /* 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")); - } - } + if (!(conn && conn->ipc)) { + /* groups stuff added by ih/wreu */ + if (current_user.ngroups > 0) + if (sys_setgroups(current_user.ngroups, + current_user.groups)<0) { + DEBUG(0,("sys_setgroups call failed!\n")); + } + } #endif - if (!conn->admin_user && !become_uid(uid)) - return(False); - } + if (!conn->admin_user && !become_uid(uid)) + return(False); current_user.conn = conn; current_user.vuid = vuid; @@ -406,56 +267,83 @@ BOOL become_user(connection_struct *conn, uint16 vuid) } /**************************************************************************** - unbecome the user of a connection number + Unbecome the user of a connection number. ****************************************************************************/ + BOOL unbecome_user(void ) { - if (!current_user.conn) - return(False); - - dos_ChDir(OriginalDir); - - if (initial_uid == 0) - { -#ifdef HAVE_SETRESUID - 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 (!current_user.conn) + return(False); + + dos_ChDir(OriginalDir); - current_user.uid = initial_uid; - current_user.gid = initial_gid; + set_effective_uid(0); + set_effective_gid(0); + + if (geteuid() != 0) { + DEBUG(0,("Warning: You appear to have a trapdoor uid system\n")); + } + if (getegid() != 0) { + DEBUG(0,("Warning: You appear to have a trapdoor gid system\n")); + } + + current_user.uid = 0; + current_user.gid = 0; - if (dos_ChDir(OriginalDir) != 0) - DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); + if (dos_ChDir(OriginalDir) != 0) + DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); - DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", - (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); + DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", + (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - current_user.conn = NULL; - current_user.vuid = UID_FIELD_INVALID; + current_user.conn = NULL; + current_user.vuid = UID_FIELD_INVALID; - return(True); + return(True); +} + +/**************************************************************************** + Become the user of an authenticated connected named pipe. + When this is called we are currently running as the connection + user. +****************************************************************************/ + +BOOL become_authenticated_pipe_user(pipes_struct *p) +{ + /* + * Go back to root. + */ + + if(!unbecome_user()) + return False; + + /* + * Now become the authenticated user stored in the pipe struct. + */ + + if(!become_id(p->uid, p->gid)) { + /* Go back to the connection user. */ + become_user(p->conn, p->vuid); + return False; + } + + return True; +} + +/**************************************************************************** + Unbecome the user of an authenticated connected named pipe. + When this is called we are running as the authenticated pipe + user and need to go back to being the connection user. +****************************************************************************/ + +BOOL unbecome_authenticated_pipe_user(pipes_struct *p) +{ + if(!become_id(0,0)) { + DEBUG(0,("unbecome_authenticated_pipe_user: Unable to go back to root.\n")); + return False; + } + + return become_user(p->conn, p->vuid); } static struct current_user current_user_saved; @@ -463,13 +351,14 @@ static int become_root_depth; static pstring become_root_dir; /**************************************************************************** -This is used when we need to do a privilaged operation (such as mucking +This is used when we need to do a privileged operation (such as mucking with share mode files) and temporarily need root access to do it. This call should always be paired with an unbecome_root() call immediately after the operation Set save_dir if you also need to save/restore the CWD ****************************************************************************/ + void become_root(BOOL save_dir) { if (become_root_depth) { @@ -486,10 +375,11 @@ void become_root(BOOL save_dir) } /**************************************************************************** -When the privilaged operation is over call this +When the privileged operation is over call this Set save_dir if you also need to save/restore the CWD ****************************************************************************/ + void unbecome_root(BOOL restore_dir) { if (become_root_depth != 1) { @@ -512,9 +402,9 @@ void unbecome_root(BOOL restore_dir) #ifdef HAVE_SETGROUPS if (current_user_saved.ngroups > 0) { - if (setgroups(current_user_saved.ngroups, + if (sys_setgroups(current_user_saved.ngroups, current_user_saved.groups)<0) - DEBUG(0,("ERROR: setgroups call failed!\n")); + DEBUG(0,("ERROR: sys_setgroups call failed!\n")); } #endif @@ -531,5 +421,3 @@ void unbecome_root(BOOL restore_dir) become_root_depth = 0; } - - -- cgit From 32a965e09ce4befe971855e11e1fb5ceb51a9ed1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 1999 13:35:20 +0000 Subject: 2nd phase of head branch sync with SAMBA_2_0 - this delets all the files that were in the head branch but weren't in SAMBA_2_0 (This used to be commit d7b208786590b5a28618590172b8d523627dda09) --- source3/smbd/challenge.c | 61 -------- source3/smbd/dfs.c | 255 ------------------------------- source3/smbd/vfs-wrap.c | 304 ------------------------------------- source3/smbd/vfs.c | 379 ----------------------------------------------- 4 files changed, 999 deletions(-) delete mode 100644 source3/smbd/challenge.c delete mode 100644 source3/smbd/dfs.c delete mode 100644 source3/smbd/vfs-wrap.c delete mode 100644 source3/smbd/vfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/challenge.c b/source3/smbd/challenge.c deleted file mode 100644 index cbb34e6395..0000000000 --- a/source3/smbd/challenge.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Password and authentication handling - Copyright (C) Andrew Tridgell 1992-1998 - - 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; - -/* Data to do lanman1/2 password challenge. */ -static unsigned char saved_challenge[8]; -static BOOL challenge_sent=False; - -/******************************************************************* -Get the next challenge value - no repeats. -********************************************************************/ -void generate_next_challenge(char *challenge) -{ - unsigned char buf[8]; - generate_random_buffer(buf,8,False); - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,8); - challenge_sent = True; -} - -/******************************************************************* -set the last challenge sent, usually from a password server -********************************************************************/ -BOOL set_challenge(unsigned char *challenge) -{ - memcpy(saved_challenge,challenge,8); - challenge_sent = True; - return(True); -} - -/******************************************************************* -get the last challenge sent -********************************************************************/ -BOOL last_challenge(unsigned char *challenge) -{ - if (!challenge_sent) return False; - memcpy(challenge,saved_challenge,8); - return(True); -} - diff --git a/source3/smbd/dfs.c b/source3/smbd/dfs.c deleted file mode 100644 index 55433f2c47..0000000000 --- a/source3/smbd/dfs.c +++ /dev/null @@ -1,255 +0,0 @@ - -#include "includes.h" - -extern int DEBUGLEVEL; - -dfs_internal dfs_struct; -extern pstring global_myname; - -/**************************************************************************** -read a line and split it -****************************************************************************/ -static BOOL parse_dfs_text_entry(char *line, dfs_internal_table *buf) -{ -#define MAXTOK 4 - char *tok[MAXTOK+1]; - int count = 0; - - tok[count] = strtok(line,":"); - - /* strip the comment lines */ - if (tok[0][0] == '#') return (False); - count++; - - while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count < MAXTOK) - { - count++; - } - - DEBUG(7,("Found [%d] tokens\n", count)); - - if (count > 1) { - StrnCpy(buf->localpath, tok[0], sizeof(buf->localpath)-1); - StrnCpy(buf->sharename, tok[1], sizeof(buf->sharename)-1); -/* - strupper(buf->localpath); - strupper(buf->sharename); -*/ - buf->localpath_length = strlen(buf->localpath); - buf->sharename_length = strlen(buf->sharename); - } - else - return (False); - - if (count > 2) - buf->proximity = atoi(tok[2]); - else - buf->proximity = 0; - - if (count > 3) - buf->type = atoi(tok[3]); - else - buf->type = 2; - - DEBUGADD(7,("localpath: [%s]\n", buf->localpath)); - DEBUGADD(7,("sharename: [%s]\n", buf->sharename)); - return True; -} - -/**************************************************************************** -mangle the localpath and store it. -****************************************************************************/ -static void mangle_dfs_path(dfs_internal_table *buf) -{ - char *p; - char *mp; - char *q; - int mlen; - - fstring temp; - - p = buf->localpath; - mp = buf->mangledpath; - mlen = sizeof(buf->mangledpath); - - ZERO_STRUCTP(mp); - DEBUG(2, ("DFS name is: [%s]\n", buf->localpath)); - - /* copy the head: \server-name\ */ - q = strchr(p + 1, '\\'); - safe_strcpy(mp, p, mlen); - p = q + 1; - - while (q != NULL) - { - q = strchr(p, '\\'); - - safe_strcpy(temp, p, sizeof(temp)); - - if (!is_8_3(temp, True)) - { - mangle_name_83(temp); - } - - safe_strcat(mp, temp, mlen); - - if (q != NULL) - { - safe_strcat(mp, "\\", mlen); - } - p = q + 1; - } - -/* - strupper(mp); -*/ - buf->mangledpath_length = strlen(mp); - DEBUGADD(2, ("DFS mangled name is: [%s]\n", mp)); -} - -/**************************************************************************** -initialisation de la table dfs en memoire au demarrage de samba -****************************************************************************/ -BOOL init_dfs_table(void) -{ - char *file = lp_dfs_map(); - int num_lines = 0; - int total = 0; - FILE *f; - pstring line; - int i; - - dfs_internal_table *entry; - - entry = NULL; - dfs_struct.ready = False; - - if (*file == '\0') { - DEBUG(0,("No DFS map, Samba is running in NON DFS mode\n")); - return False; - } - - f = sys_fopen(file, "r"); - if (!f) { - DEBUG(0,("No DFS map file, Samba is running in NON DFS mode\n")); - return False; - } - - while ( fgets(line, sizeof(pstring), f) ) - { - entry = Realloc(entry,sizeof(dfs_internal_table)*(total+1)); - if (! entry) - { - total = 0; - break; - } - - if ( parse_dfs_text_entry(line, &(entry[total]) ) ) - { - total++; - } - num_lines++; - } - dfs_struct.size = total; - dfs_struct.table = entry; - fclose(f); - - /* we have the file in memory */ - /* now initialise the mangled names */ - for (i = 0; i < total; i++) - { - mangle_dfs_path(&(entry[i])); - } - - dfs_struct.ready = True; - DEBUG(0,("Samba is DFS aware now!\n")); - return True; -} - -static BOOL check_dfs_path(int search_len, const char *search_path, - int path_len, const char* fullpath, - const char* sharename, - const char* share_path, size_t share_len, - char *localpath, size_t local_plen) -{ - if (StrnCaseCmp(search_path, fullpath, search_len) != 0) - { - return False; - } - - DEBUG(2,("found one linked to [%s]. share_path: %s\n", - sharename, share_path)); - - if (StrnCaseCmp(fullpath, share_path, share_len) == 0) - { - safe_strcpy(localpath, fullpath + share_len, local_plen); - } - else - { - localpath[0] = 0; - } - - return True; -} - -/**************************************************************************** - check if a path name is a DFS branch -****************************************************************************/ -int under_dfs(connection_struct *conn, const char *path, - char *local_path, size_t local_plen) -{ - fstring fullpath; - pstring share_path; - int i; - int snum; - - int path_len; - int share_len; - - dfs_internal_table *list = dfs_struct.table; - - snum = SNUM(conn); - snprintf(share_path, sizeof(share_path), "\\%s\\%s", - global_myname, lp_servicename(snum)); - share_len = strlen(share_path); - - if (path[0] != '\\') - { - snprintf(fullpath, sizeof(fullpath), "%s\\%s", - share_path, path); - } - else - { - safe_strcpy(fullpath, path, sizeof(fullpath)); - } - - path_len = strlen(fullpath); - - DEBUG(2,("DFS looking for: [%s]\n", fullpath)); - - for (i = 0; i < dfs_struct.size; i++) - { - DEBUG(6,("checking against [%s][%d]\n", list[i].localpath,i)); - - if (check_dfs_path(list[i].localpath_length, - list[i].localpath, - path_len, fullpath, - list[i].sharename, - share_path, share_len, - local_path, local_plen)) - { - return True; - } - - if (check_dfs_path(list[i].mangledpath_length, - list[i].mangledpath, - path_len, fullpath, - list[i].sharename, - share_path, share_len, - local_path, local_plen)) - { - return True; - } - } - return False; -} diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c deleted file mode 100644 index 3493c23178..0000000000 --- a/source3/smbd/vfs-wrap.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Wrap disk only vfs functions to sidestep dodgy compilers. - Copyright (C) Tim Potter 1998 - - 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" - -/* Check for NULL pointer parameters in vfswrap_* functions */ - -#define VFS_CHECK_NULL - -/* We don't want to have NULL function pointers lying around. Someone - is sure to try and execute them. These stubs are used to prevent - this possibility. */ - -int vfswrap_dummy_connect(struct vfs_connection_struct *conn, char *service, - char *user) -{ - return 0; /* Return >= 0 for success */ -} - -void vfswrap_dummy_disconnect(void) -{ -} - -/* Disk operations */ - -SMB_BIG_UINT vfswrap_disk_free(char *path, SMB_BIG_UINT *bsize, - SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -{ - SMB_BIG_UINT result; - -#ifdef VFS_CHECK_NULL - if ((path == NULL) || (bsize == NULL) || (dfree == NULL) || - (dsize == NULL)) { - - smb_panic("NULL pointer passed to vfswrap_disk_free() function\n"); - } -#endif - - result = sys_disk_free(path, bsize, dfree, dsize); - return result; -} - -/* Directory operations */ - -DIR *vfswrap_opendir(char *fname) -{ - DIR *result; - -#ifdef VFS_CHECK_NULL - if (fname == NULL) { - smb_panic("NULL pointer passed to vfswrap_opendir()\n"); - } -#endif - - result = opendir(fname); - return result; -} - -struct dirent *vfswrap_readdir(DIR *dirp) -{ - struct dirent *result; - -#ifdef VFS_CHECK_NULL - if (dirp == NULL) { - smb_panic("NULL pointer passed to vfswrap_readdir()\n"); - } -#endif - - result = readdir(dirp); - return result; -} - -int vfswrap_mkdir(char *path, mode_t mode) -{ - int result; - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_mkdir()\n"); - } -#endif - - result = mkdir(path, mode); - return result; -} - -int vfswrap_rmdir(char *path) -{ - int result; - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_rmdir()\n"); - } -#endif - - result = rmdir(path); - return result; -} - -int vfswrap_closedir(DIR *dirp) -{ - int result; - -#ifdef VFS_CHECK_NULL - if (dirp == NULL) { - smb_panic("NULL pointer passed to vfswrap_closedir()\n"); - } -#endif - - result = closedir(dirp); - return result; -} - -/* File operations */ - -int vfswrap_open(char *fname, int flags, mode_t mode) -{ - int result; - -#ifdef VFS_CHECK_NULL - if (fname == NULL) { - smb_panic("NULL pointer passed to vfswrap_open()\n"); - } -#endif - - result = sys_open(fname, flags, mode); - return result; -} - -int vfswrap_close(int fd) -{ - int result; - - result = close(fd); - return result; -} - -ssize_t vfswrap_read(int fd, char *data, size_t n) -{ - ssize_t result; - -#ifdef VFS_CHECK_NULL - if (data == NULL) { - smb_panic("NULL pointer passed to vfswrap_read()\n"); - } -#endif - - result = read(fd, data, n); - return result; -} - -ssize_t vfswrap_write(int fd, char *data, size_t n) -{ - ssize_t result; - -#ifdef VFS_CHECK_NULL - if (data == NULL) { - smb_panic("NULL pointer passed to vfswrap_write()\n"); - } -#endif - - result = write(fd, data, n); - return result; -} - -SMB_OFF_T vfswrap_lseek(int filedes, SMB_OFF_T offset, int whence) -{ - SMB_OFF_T result; - - result = sys_lseek(filedes, offset, whence); - return result; -} - -int vfswrap_rename(char *old, char *new) -{ - int result; - -#ifdef VFS_CHECK_NULL - if ((old == NULL) || (new == NULL)) { - smb_panic("NULL pointer passed to vfswrap_rename()\n"); - } -#endif - - result = rename(old, new); - return result; -} - -void vfswrap_sync_file(int fd) -{ - sys_sync_file(fd); -} - -int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) -{ - int result; - -#ifdef VFS_CHECK_NULL - if ((fname == NULL) || (sbuf == NULL)) { - smb_panic("NULL pointer passed to vfswrap_stat()\n"); - } -#endif - - result = sys_stat(fname, sbuf); - return result; -} - -int vfswrap_fstat(int fd, SMB_STRUCT_STAT *sbuf) -{ - int result; - -#ifdef VFS_CHECK_NULL - if (sbuf == NULL) { - smb_panic("NULL pointer passed to vfswrap_fstat()\n"); - } -#endif - - result = sys_fstat(fd, sbuf); - return result; -} - -int vfswrap_lstat(char *path, - SMB_STRUCT_STAT *sbuf) -{ - int result; - -#ifdef VFS_CHECK_NULL - if ((path == NULL) || (sbuf == NULL)) { - smb_panic("NULL pointer passed to vfswrap_lstat()\n"); - } -#endif - - result = sys_lstat(path, sbuf); - return result; -} - -BOOL vfswrap_fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, - int type) -{ - BOOL result; - - result = fcntl_lock(fd, op, offset, count, type); - return result; -} - -int vfswrap_unlink(char *path) -{ - int result; - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_unlink()\n"); - } -#endif - - result = unlink(path); - return result; -} - -int vfswrap_chmod(char *path, mode_t mode) -{ - int result; - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_chmod()\n"); - } -#endif - - result = chmod(path, mode); - return result; -} - -int vfswrap_utime(char *path, struct utimbuf *times) -{ - int result; - -#ifdef VFS_CHECK_NULL - if ((path == NULL) || (times == NULL)) { - smb_panic("NULL pointer passed to vfswrap_utime()\n"); - } -#endif - - result = utime(path, times); - return result; -} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c deleted file mode 100644 index 95bb4c9414..0000000000 --- a/source3/smbd/vfs.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - VFS initialisation and support functions - Copyright (C) Tim Potter 1999 - - 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" -#ifdef HAVE_LIBDL -#include -#endif - -extern int DEBUGLEVEL; - -/* Some structures to help us initialise the vfs operations table */ - -struct vfs_syminfo { - char *name; - void *fptr; -}; - -/* Default vfs hooks. WARNING: The order of these initialisers is - very important. They must be in the same order as defined in - vfs.h. Change at your own peril. */ - -struct vfs_ops default_vfs_ops = { - - /* Disk operations */ - - vfswrap_dummy_connect, - vfswrap_dummy_disconnect, - vfswrap_disk_free, - - /* Directory operations */ - - vfswrap_opendir, - vfswrap_readdir, - vfswrap_mkdir, - vfswrap_rmdir, - vfswrap_closedir, - - /* File operations */ - - vfswrap_open, - vfswrap_close, - vfswrap_read, - vfswrap_write, - vfswrap_lseek, - vfswrap_rename, - vfswrap_sync_file, - vfswrap_stat, - vfswrap_fstat, - vfswrap_lstat, - vfswrap_fcntl_lock, - vfswrap_unlink, - vfswrap_chmod, - vfswrap_utime -}; - -/**************************************************************************** - initialise default vfs hooks -****************************************************************************/ -int vfs_init_default(connection_struct *conn) -{ - DEBUG(3, ("Initialising default vfs hooks\n")); - - memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(conn->vfs_ops)); - return True; -} - -/**************************************************************************** - initialise custom vfs hooks -****************************************************************************/ -#ifdef HAVE_LIBDL -BOOL vfs_init_custom(connection_struct *conn) -{ - void *handle; - struct vfs_ops *ops, *(*fptr)(struct vfs_options *options); - - DEBUG(3, ("Initialising custom vfs hooks from %s\n", - lp_vfsobj(SNUM(conn)))); - - /* Open object file */ - - handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW); - if (!handle) { - DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), - dlerror())); - return False; - } - - /* Get handle on vfs_init() symbol */ - - fptr = dlsym(handle, "vfs_init"); - if (fptr == NULL) { - DEBUG(0, ("No vfs_init() symbol found in %s\n", - lp_vfsobj(SNUM(conn)))); - return False; - } - - dlclose(handle); - - /* Initialise vfs_ops structure */ - - if ((ops = fptr(lp_vfsoptions(SNUM(conn)))) == NULL) { - return False; - } - - /* Fill in unused operations with default (disk based) ones. - There's probably a neater way to do this then a whole bunch of - if statements. */ - - memcpy(&conn->vfs_ops, ops, sizeof(conn->vfs_ops)); - - if (conn->vfs_ops.connect == NULL) { - conn->vfs_ops.connect = default_vfs_ops.connect; - } - - if (conn->vfs_ops.disconnect == NULL) { - conn->vfs_ops.disconnect = default_vfs_ops.disconnect; - } - - if (conn->vfs_ops.disk_free == NULL) { - conn->vfs_ops.disk_free = default_vfs_ops.disk_free; - } - - if (conn->vfs_ops.opendir == NULL) { - conn->vfs_ops.opendir = default_vfs_ops.opendir; - } - - if (conn->vfs_ops.readdir == NULL) { - conn->vfs_ops.readdir = default_vfs_ops.readdir; - } - - if (conn->vfs_ops.mkdir == NULL) { - conn->vfs_ops.mkdir = default_vfs_ops.mkdir; - } - - if (conn->vfs_ops.rmdir == NULL) { - conn->vfs_ops.rmdir = default_vfs_ops.rmdir; - } - - if (conn->vfs_ops.closedir == NULL) { - conn->vfs_ops.closedir = default_vfs_ops.closedir; - } - - if (conn->vfs_ops.open == NULL) { - conn->vfs_ops.open = default_vfs_ops.open; - } - - if (conn->vfs_ops.close == NULL) { - conn->vfs_ops.close = default_vfs_ops.close; - } - - if (conn->vfs_ops.read == NULL) { - conn->vfs_ops.read = default_vfs_ops.read; - } - - if (conn->vfs_ops.write == NULL) { - conn->vfs_ops.write = default_vfs_ops.write; - } - - if (conn->vfs_ops.lseek == NULL) { - conn->vfs_ops.lseek = default_vfs_ops.lseek; - } - - if (conn->vfs_ops.rename == NULL) { - conn->vfs_ops.rename = default_vfs_ops.rename; - } - - if (conn->vfs_ops.sync == NULL) { - conn->vfs_ops.sync = default_vfs_ops.sync; - } - - if (conn->vfs_ops.stat == NULL) { - conn->vfs_ops.stat = default_vfs_ops.stat; - } - - if (conn->vfs_ops.fstat == NULL) { - conn->vfs_ops.fstat = default_vfs_ops.fstat; - } - - if (conn->vfs_ops.lstat == NULL) { - conn->vfs_ops.lstat = default_vfs_ops.lstat; - } - - if (conn->vfs_ops.lock == NULL) { - conn->vfs_ops.lock = default_vfs_ops.lock; - } - - if (conn->vfs_ops.unlink == NULL) { - conn->vfs_ops.unlink = default_vfs_ops.unlink; - } - - if (conn->vfs_ops.chmod == NULL) { - conn->vfs_ops.chmod = default_vfs_ops.chmod; - } - - if (conn->vfs_ops.utime == NULL) { - conn->vfs_ops.utime = default_vfs_ops.utime; - } - - return True; -} -#endif - -/******************************************************************* - check if a vfs file exists -********************************************************************/ -BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) -{ - SMB_STRUCT_STAT st; - if (!sbuf) sbuf = &st; - - if (conn->vfs_ops.stat(fname,sbuf) != 0) - return(False); - - return(S_ISREG(sbuf->st_mode)); -} - -/**************************************************************************** - write data to a fd on the vfs -****************************************************************************/ -ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) -{ - size_t total=0; - ssize_t ret; - int fd = fsp->fd_ptr->fd; - - while (total < N) - { - ret = fsp->conn->vfs_ops.write(fd,buffer + total,N - total); - - if (ret == -1) return -1; - if (ret == 0) return total; - - total += ret; - } - return (ssize_t)total; -} - -/**************************************************************************** -transfer some data between two file_struct's -****************************************************************************/ -SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, - int out_fd, files_struct *out_fsp, - SMB_OFF_T n, char *header, int headlen, int align) -{ - static char *buf=NULL; - static int size=0; - char *buf1,*abuf; - SMB_OFF_T total = 0; - - DEBUG(4,("vfs_transfer_file n=%.0f (head=%d) called\n",(double)n,headlen)); - - /* Check we have at least somewhere to read from */ - - SMB_ASSERT((in_fd != -1) || (in_fsp != NULL)); - - if (size == 0) { - size = lp_readsize(); - size = MAX(size,1024); - } - - while (!buf && size>0) { - buf = (char *)Realloc(buf,size+8); - if (!buf) size /= 2; - } - - if (!buf) { - DEBUG(0,("Can't allocate transfer buffer!\n")); - exit(1); - } - - abuf = buf + (align%8); - - if (header) - n += headlen; - - while (n > 0) - { - int s = (int)MIN(n,(SMB_OFF_T)size); - int ret,ret2=0; - - ret = 0; - - if (header && (headlen >= MIN(s,1024))) { - buf1 = header; - s = headlen; - ret = headlen; - headlen = 0; - header = NULL; - } else { - buf1 = abuf; - } - - if (header && headlen > 0) - { - ret = MIN(headlen,size); - memcpy(buf1,header,ret); - headlen -= ret; - header += ret; - if (headlen <= 0) header = NULL; - } - - if (s > ret) { - ret += in_fsp ? - in_fsp->conn->vfs_ops.read(in_fsp->fd_ptr->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); - } - - if (ret > 0) - { - if (out_fsp) { - ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd_ptr->fd,buf1,ret); - } else { - ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret; - } - } - - if (ret2 > 0) total += ret2; - /* if we can't write then dump excess data */ - if (ret2 != ret) - vfs_transfer_file(in_fd, in_fsp, -1,NULL,n-(ret+headlen),NULL,0,0); - - if (ret <= 0 || ret2 != ret) - return(total); - n -= ret; - } - return(total); -} - -/******************************************************************* -a vfs_readdir wrapper which just returns the file name -********************************************************************/ -char *vfs_readdirname(connection_struct *conn, void *p) -{ - struct dirent *ptr; - char *dname; - - if (!p) return(NULL); - - ptr = (struct dirent *)conn->vfs_ops.readdir(p); - if (!ptr) return(NULL); - - dname = ptr->d_name; - -#ifdef NEXT2 - if (telldir(p) < 0) return(NULL); -#endif - -#ifdef HAVE_BROKEN_READDIR - /* using /usr/ucb/cc is BAD */ - dname = dname - 2; -#endif - - { - static pstring buf; - memcpy(buf, dname, NAMLEN(ptr)+1); - unix_to_dos(buf, True); - dname = buf; - } - - unix_to_dos(dname, True); - return(dname); -} -- cgit From 80a180853d2d177f5c991a36e4b86943d9efa3fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Dec 1999 21:46:41 +0000 Subject: *Finally*. Correct patch to fix timestamp problems from Paul Eggert . I wish I had written this one :-). Jeremy. (This used to be commit 8f93c08881c22d121c7337d11de070e2b8f7ba33) --- source3/smbd/trans2.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e971f8bbb6..5a8db7efda 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1694,14 +1694,25 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_BASIC_INFO: { + /* Patch to do this correctly from Paul Eggert . */ + time_t write_time; + time_t changed_time; + /* Ignore create time at offset pdata. */ /* access time */ tvs.actime = interpret_long_date(pdata+8); - /* write time + changed time, combined. */ - tvs.modtime=MIN(interpret_long_date(pdata+16), - interpret_long_date(pdata+24)); + write_time = interpret_long_date(pdata+16); + changed_time = interpret_long_date(pdata+24); + + tvs.modtime = MAX(write_time, changed_time); + + /* Prefer a defined time to an undefined one. */ + if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) + tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1 + ? changed_time + : write_time); #if 0 /* Needs more testing... */ /* Test from Luke to prevent Win95 from -- cgit From 7b39ef295073847b29af3220e0566131e503b0a0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Dec 1999 00:06:00 +0000 Subject: Fix from tulipant-gergely@dbrt.hu for returning incorrect error code on user auth fail. Jeremy. (This used to be commit 886ad59d798175f037ea9249dcefa78660e4992a) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7e94ffa173..36eb882340 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -504,7 +504,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if (flags & AS_GUEST) flags &= ~AS_USER; else - return(ERROR(ERRSRV,ERRinvnid)); + return(ERROR(ERRSRV,ERRaccess)); } /* this code is to work around a bug is MS client 3 without introducing a security hole - it needs to be able to do -- cgit From 69d24d869bf97978b31a51fe8e8d08cac4874d67 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Dec 1999 04:54:30 +0000 Subject: first cut at using the tdb code for the connections structure, the SWAT status page and smbstatus. It made the code _much_ simpler, I wish we'd done a database module a long time ago! (This used to be commit 4951755413c11d4c5b9af4699a6e622056d52433) --- source3/smbd/connection.c | 225 +++++++++++++++------------------------------- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 8 +- 3 files changed, 75 insertions(+), 160 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 393a3e7372..f88d707983 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -27,202 +27,117 @@ extern fstring remote_machine; extern int DEBUGLEVEL; /**************************************************************************** -simple routines to do connection counting +open the connections database ****************************************************************************/ -BOOL yield_connection(connection_struct *conn,char *name,int max_connections) +TDB_CONTEXT *open_db(char *name) { - struct connect_record crec; pstring fname; - int fd; - pid_t mypid = getpid(); - int i; - - DEBUG(3,("Yielding connection to %s\n",name)); - - if (max_connections <= 0) - return(True); - - memset((char *)&crec,'\0',sizeof(crec)); pstrcpy(fname,lp_lockdir()); trim_string(fname,"","/"); - - pstrcat(fname,"/"); - pstrcat(fname,name); - pstrcat(fname,".LCK"); - - fd = sys_open(fname,O_RDWR,0); - if (fd == -1) { - DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno))); - return(False); + + if (!directory_exist(fname,NULL)) { + mkdir(fname,0755); } + + pstrcat(fname,"/connections.tdb"); + + return tdb_open(fname, 0, O_RDWR | O_CREAT, 0644); +} - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) { - DEBUG(0,("ERROR: can't get lock on %s\n", fname)); - return False; - } - /* find the right spot */ - for (i=0;icnum) - break; - } - if (crec.pid != mypid || crec.cnum != conn->cnum) { - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { - DEBUG(0,("ERROR: can't release lock on %s\n", fname)); - } - close(fd); - DEBUG(2,("Entry not found in lock file %s\n",fname)); - return(False); - } +/**************************************************************************** +delete a connection record +****************************************************************************/ +BOOL yield_connection(connection_struct *conn,char *name,int max_connections) +{ + struct connections_key key; + TDB_DATA kbuf; + TDB_CONTEXT *tdb; - memset((void *)&crec,'\0',sizeof(crec)); - - /* remove our mark */ - if (sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || - write(fd, &crec,sizeof(crec)) != sizeof(crec)) { - DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno))); - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { - DEBUG(0,("ERROR: can't release lock on %s\n", fname)); - } - close(fd); - return(False); - } + if (!(tdb = open_db(name))) return False; - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { - DEBUG(0,("ERROR: can't release lock on %s\n", fname)); - } + DEBUG(3,("Yielding connection to %s\n",name)); - DEBUG(3,("Yield successful\n")); + ZERO_STRUCT(key); + key.pid = getpid(); + if (conn) key.cnum = conn->cnum; + fstrcpy(key.name, name); - close(fd); + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + + tdb_delete(tdb, kbuf); + tdb_close(tdb); return(True); } /**************************************************************************** -simple routines to do connection counting +claim an entry in the connections database +****************************************************************************/ +int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) +{ + struct connections_key key; + memcpy(&key, kbuf.dptr, sizeof(key)); + if (!process_exists(key.pid)) tdb_delete(tdb, kbuf); + return 0; +} + + +/**************************************************************************** +claim an entry in the connections database ****************************************************************************/ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear) { + struct connections_key key; + struct connections_data crec; + TDB_DATA kbuf, dbuf; + TDB_CONTEXT *tdb; extern int Client; - struct connect_record crec; - pstring fname; - int fd=-1; - int i,foundi= -1; - int total_recs; - + if (max_connections <= 0) return(True); - DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections)); - - pstrcpy(fname,lp_lockdir()); - trim_string(fname,"","/"); - - if (!directory_exist(fname,NULL)) - mkdir(fname,0755); - - pstrcat(fname,"/"); - pstrcat(fname,name); - pstrcat(fname,".LCK"); - - if (!file_exist(fname,NULL)) { - fd = sys_open(fname,O_RDWR|O_CREAT|O_EXCL, 0644); - } + if (!(tdb = open_db(name))) return False; - if (fd == -1) { - fd = sys_open(fname,O_RDWR,0); - } - - if (fd == -1) { - DEBUG(1,("couldn't open lock file %s\n",fname)); - return(False); - } + DEBUG(5,("claiming %s %d\n",name,max_connections)); + + ZERO_STRUCT(key); + key.pid = getpid(); + key.cnum = conn?conn->cnum:-1; + fstrcpy(key.name, name); + + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) { - DEBUG(0,("ERROR: can't get lock on %s\n", fname)); - return False; + if (Clear) { + tdb_traverse(tdb, delete_dead); } - total_recs = get_file_size(fname) / sizeof(crec); - - /* find a free spot */ - for (i=0;i=total_recs || - sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) || - read(fd,&crec,sizeof(crec)) != sizeof(crec)) { - if (foundi < 0) foundi = i; - break; - } - - if (Clear && crec.pid && !process_exists(crec.pid)) { - if(sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec)) { - DEBUG(0,("claim_connection: ERROR: sys_lseek failed to seek \ -to %d\n", (int)(i*sizeof(crec)) )); - continue; - } - memset((void *)&crec,'\0',sizeof(crec)); - write(fd, &crec,sizeof(crec)); - if (foundi < 0) foundi = i; - continue; - } - if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) { - foundi=i; - if (!Clear) break; - } - } - - if (foundi < 0) { - DEBUG(3,("no free locks in %s\n",fname)); - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { - DEBUG(0,("ERROR: can't release lock on %s\n", fname)); - } - close(fd); - return(False); - } - /* fill in the crec */ - memset((void *)&crec,'\0',sizeof(crec)); + ZERO_STRUCT(crec); crec.magic = 0x280267; crec.pid = getpid(); + crec.cnum = conn?conn->cnum:-1; if (conn) { - crec.cnum = conn->cnum; crec.uid = conn->uid; crec.gid = conn->gid; StrnCpy(crec.name, lp_servicename(SNUM(conn)),sizeof(crec.name)-1); - } else { - crec.cnum = -1; } crec.start = time(NULL); StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); - StrnCpy(crec.addr,client_addr(Client),sizeof(crec.addr)-1); - - /* make our mark */ - if (sys_lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) || - write(fd, &crec,sizeof(crec)) != sizeof(crec)) { - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { - DEBUG(0,("ERROR: can't release lock on %s\n", fname)); - } - close(fd); - return(False); - } + StrnCpy(crec.addr,conn?conn->client_address:client_addr(Client),sizeof(crec.addr)-1); - if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) { - DEBUG(0,("ERROR: can't release lock on %s\n", fname)); - } - - close(fd); - return(True); + dbuf.dptr = (char *)&crec; + dbuf.dsize = sizeof(crec); + + if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False; + + tdb_close(tdb); + + return True; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 54f646e091..aa7e95294d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -123,7 +123,7 @@ int reply_special(char *inbuf,char *outbuf) reopen_logs(); if (lp_status(-1)) { - claim_connection(NULL,"STATUS.",MAXSTATUS,True); + claim_connection(NULL,"",MAXSTATUS,True); } break; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 92807e2d43..ec723e13b9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -458,7 +458,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int } if (lp_status(SNUM(conn))) - claim_connection(conn,"STATUS.", + claim_connection(conn,"", MAXSTATUS,False); } /* IS_IPC */ @@ -484,7 +484,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); if (lp_status(SNUM(conn))) { - yield_connection(conn,"STATUS.",MAXSTATUS); + yield_connection(conn,"",MAXSTATUS); } } conn_free(conn); @@ -501,7 +501,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); if (lp_status(SNUM(conn))) - yield_connection(conn,"STATUS.",MAXSTATUS); + yield_connection(conn,"",MAXSTATUS); } conn_free(conn); *ecode = ERRinvnetname; @@ -582,7 +582,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) lp_max_connections(SNUM(conn))); if (lp_status(SNUM(conn))) - yield_connection(conn,"STATUS.",MAXSTATUS); + yield_connection(conn,"",MAXSTATUS); file_close_conn(conn); dptr_closecnum(conn); -- cgit From 4e1291a83f61a72989045879763d9ef05fd38f71 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Dec 1999 09:25:59 +0000 Subject: converted all our existing shared memory code to use a tdb database instead of either sysv or mmap shared memory or lock files. this means we can now completely remove locking_shm.c locking_slow.c shmem.c shmem_sysv.c and lots of other things also got simpler locking.c got a bit larger, but is much better compartmentalised now (This used to be commit e48c2d9937eea0667b8cd3332e49c06314ef31e7) --- source3/smbd/close.c | 7 +++---- source3/smbd/connection.c | 27 ++++----------------------- source3/smbd/fileio.c | 6 +++--- source3/smbd/open.c | 33 ++++++++++++++++----------------- source3/smbd/oplock.c | 15 +++++++-------- source3/smbd/trans2.c | 11 +++++------ 6 files changed, 38 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d06cb3b5bb..bfef7c5235 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -94,7 +94,6 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) { SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; - int token; BOOL last_reference = False; BOOL delete_on_close = fsp->fd_ptr->delete_on_close; connection_struct *conn = fsp->conn; @@ -109,8 +108,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) #endif if (lp_share_modes(SNUM(conn))) { - lock_share_entry(conn, dev, inode, &token); - del_share_mode(token, fsp); + lock_share_entry(conn, dev, inode); + del_share_mode(fsp); } if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) @@ -122,7 +121,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) fsp->fd_ptr = NULL; if (lp_share_modes(SNUM(conn))) - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); /* NT uses smbclose to start a print - weird */ if (normal_close && fsp->print_file) diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index f88d707983..5b5ab005c8 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -26,27 +26,6 @@ extern fstring remote_machine; extern int DEBUGLEVEL; -/**************************************************************************** -open the connections database -****************************************************************************/ -TDB_CONTEXT *open_db(char *name) -{ - pstring fname; - - pstrcpy(fname,lp_lockdir()); - trim_string(fname,"","/"); - - if (!directory_exist(fname,NULL)) { - mkdir(fname,0755); - } - - pstrcat(fname,"/connections.tdb"); - - return tdb_open(fname, 0, O_RDWR | O_CREAT, 0644); -} - - - /**************************************************************************** delete a connection record ****************************************************************************/ @@ -56,7 +35,8 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) TDB_DATA kbuf; TDB_CONTEXT *tdb; - if (!(tdb = open_db(name))) return False; + tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644); + if (!tdb) return False; DEBUG(3,("Yielding connection to %s\n",name)); @@ -100,7 +80,8 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO if (max_connections <= 0) return(True); - if (!(tdb = open_db(name))) return False; + tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644); + if (!tdb) return False; DEBUG(5,("claiming %s %d\n",name,max_connections)); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 8b48a921fd..fa04e671f8 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -213,11 +213,11 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) int num_share_modes = 0; int i; - if (lock_share_entry(fsp->conn, dev, inode, &token) == False) { + if (lock_share_entry(fsp->conn, dev, inode) == False) { DEBUG(0,("write_file: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); } - num_share_modes = get_share_modes(fsp->conn, token, dev, inode, &share_list); + num_share_modes = get_share_modes(fsp->conn, dev, inode, &share_list); for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &share_list[i]; @@ -268,7 +268,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) } free((char *)share_list); - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode); } /* Paranoia check... */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4491082b2c..a940eda85d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -602,7 +602,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(conn))) unlock_share_entry( conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, token); + fsp->fd_ptr->inode); close_file(fsp,False); /* Share mode no longer locked. */ *share_locked = False; @@ -858,9 +858,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int { dev = sbuf.st_dev; inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); share_locked = True; - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); } /* @@ -896,7 +896,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); @@ -909,7 +909,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou unix_ERR_code = ERRbadshare; return; } - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); broke_oplock = True; all_current_opens_are_level_II = False; break; @@ -922,7 +922,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) { free((char *)old_shares); - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); errno = EACCES; return; } @@ -932,7 +932,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); oplock_contention_count++; } } while(broke_oplock); @@ -973,7 +973,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou /* We created the file - thus we must now lock the share entry before creating it. */ dev = fsp->fd_ptr->dev; inode = fsp->fd_ptr->inode; - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); share_locked = True; } @@ -1028,7 +1028,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou oplock_request = 0; } - set_share_mode(token, fsp, port, oplock_request); + set_share_mode(fsp, port, oplock_request); } if ((flags2&O_TRUNC) && file_existed) @@ -1036,7 +1036,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } if (share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, dev, inode, token); + unlock_share_entry( conn, dev, inode); } /**************************************************************************** @@ -1224,7 +1224,6 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) share_mode_entry *old_shares = 0; int num_share_modes; SMB_STRUCT_STAT sbuf; - int token; pid_t pid = getpid(); SMB_DEV_T dev; SMB_INO_T inode; @@ -1237,8 +1236,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) dev = sbuf.st_dev; inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode, &token); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + lock_share_entry(conn, dev, inode); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); /* * Check if the share modes will give us access. @@ -1308,7 +1307,7 @@ batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (do dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); @@ -1318,7 +1317,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou return False; } - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); broke_oplock = True; break; } @@ -1345,7 +1344,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); } } while(broke_oplock); } @@ -1364,7 +1363,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free_and_exit: - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(old_shares != NULL) free((char *)old_shares); return(ret); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index a64dd2d0ef..c5cab8c225 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -406,13 +406,12 @@ static void downgrade_file_oplock(files_struct *fsp) BOOL remove_oplock(files_struct *fsp) { - int token; SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; BOOL ret = True; /* Remove the oplock flag from the sharemode. */ - if (lock_share_entry(fsp->conn, dev, inode, &token) == False) { + if (lock_share_entry(fsp->conn, dev, inode) == False) { DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", fsp->fsp_name )); ret = False; @@ -424,7 +423,7 @@ BOOL remove_oplock(files_struct *fsp) * Deal with a reply when a break-to-none was sent. */ - if(remove_share_oplock(token, fsp)==False) { + if(remove_share_oplock(fsp)==False) { DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); ret = False; @@ -438,7 +437,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double) * Deal with a reply when a break-to-level II was sent. */ - if(downgrade_share_oplock(token, fsp)==False) { + if(downgrade_share_oplock(fsp)==False) { DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); ret = False; @@ -447,7 +446,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double) downgrade_file_oplock(fsp); } - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode); return ret; } @@ -792,18 +791,18 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) * the existing lock on the shared memory area. */ - if(!local_request && lock_share_entry(fsp->conn, dev, inode, &token) == False) { + if(!local_request && lock_share_entry(fsp->conn, dev, inode) == False) { DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); } else { got_lock = True; } - if(remove_share_oplock(token, fsp)==False) { + if(remove_share_oplock(fsp)==False) { DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); } if (!local_request && got_lock) - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode); fsp->oplock_type = NO_OPLOCK; level_II_oplocks_open--; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5a8db7efda..bbbfda7468 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1800,7 +1800,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) { - int token; int i; files_struct *iterate_fsp; SMB_DEV_T dev = fsp->fd_ptr->dev; @@ -1808,7 +1807,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, int num_share_modes; share_mode_entry *current_shares = NULL; - if(lock_share_entry(fsp->conn, dev, inode, &token) == False) + if(lock_share_entry(fsp->conn, dev, inode) == False) return(ERROR(ERRDOS,ERRnoaccess)); /* @@ -1818,7 +1817,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * file at this point. */ - num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares); + num_share_modes = get_share_modes(conn, dev, inode, ¤t_shares); for(i = 0; i < num_share_modes; i++) { if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) @@ -1830,7 +1829,7 @@ file %s as a share exists that was not opened with FILE_DELETE access.\n", * Release the lock. */ - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode); /* * current_shares was malloced by get_share_modes - free it here. @@ -1875,7 +1874,7 @@ dev = %x, inode = %.0f from %x to %x\n", iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, (double)inode, iterate_fsp->share_mode, new_share_mode )); - if(modify_share_mode(token, iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False) + if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False) DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)); } @@ -1887,7 +1886,7 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) */ fsp->fd_ptr->delete_on_close = delete_on_close; - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode); DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); -- cgit From 44dc314fea03d23b137fb6f2f51a271e6c0ed1c2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Dec 1999 19:14:17 +0000 Subject: Changed MAX to MIN in SET_FILE_BASIC_INFO as recommended by "Michael C. Adler" as this breaks the least number of programs. Jeremy. (This used to be commit 2cf408772f7b763a484fdd893da28999c8f9d025) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bbbfda7468..9811a9ff01 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1706,7 +1706,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, write_time = interpret_long_date(pdata+16); changed_time = interpret_long_date(pdata+24); - tvs.modtime = MAX(write_time, changed_time); + tvs.modtime = MIN(write_time, changed_time); /* Prefer a defined time to an undefined one. */ if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) -- cgit From 9a781a8c6de9513ba5f4cafef41379fae96807c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2000 23:00:27 +0000 Subject: - added tdb_flags option to tdb_open() - added TDB_CLEAR_IF_FIRST flag to clear the database if this is the first attached process. Useful for non-persistent databases like our locking area (this will also make upgrades to new database layouts easier) - use lock_path() in a couple of places - leave connections database open while smbd running - cleaned up some tdb code a little, using macros for constants (This used to be commit 00e9da3ca577527db392aced62f02c69cfee8f4f) --- source3/smbd/connection.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5b5ab005c8..13c051a5a3 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -23,6 +23,7 @@ extern fstring remote_machine; +static TDB_CONTEXT *tdb; extern int DEBUGLEVEL; @@ -33,9 +34,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) { struct connections_key key; TDB_DATA kbuf; - TDB_CONTEXT *tdb; - tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644); if (!tdb) return False; DEBUG(3,("Yielding connection to %s\n",name)); @@ -49,23 +48,10 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) kbuf.dsize = sizeof(key); tdb_delete(tdb, kbuf); - tdb_close(tdb); return(True); } -/**************************************************************************** -claim an entry in the connections database -****************************************************************************/ -int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) -{ - struct connections_key key; - memcpy(&key, kbuf.dptr, sizeof(key)); - if (!process_exists(key.pid)) tdb_delete(tdb, kbuf); - return 0; -} - - /**************************************************************************** claim an entry in the connections database ****************************************************************************/ @@ -74,13 +60,15 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO struct connections_key key; struct connections_data crec; TDB_DATA kbuf, dbuf; - TDB_CONTEXT *tdb; extern int Client; if (max_connections <= 0) return(True); - - tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644); + + if (!tdb) { + tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT, 0644); + } if (!tdb) return False; DEBUG(5,("claiming %s %d\n",name,max_connections)); @@ -93,10 +81,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); - if (Clear) { - tdb_traverse(tdb, delete_dead); - } - /* fill in the crec */ ZERO_STRUCT(crec); crec.magic = 0x280267; -- cgit From 5105c1b4506c35371d7cb0e9e5ac55fe4a6a53af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 Jan 2000 00:22:43 +0000 Subject: don't close the database after each claim_connection() (This used to be commit d5ceb2972b65c261cfb04b6dcccb3ace9f2238a7) --- source3/smbd/connection.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 13c051a5a3..82f789f7a1 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -102,7 +102,5 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False; - tdb_close(tdb); - return True; } -- cgit From d705b62141d092a5a9ca4e905bab2d1f1a1c3e9e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 Jan 2000 03:31:41 +0000 Subject: got rid of mem_man yamd is much better, and doesn't require any source code changes if you haven't seen yamd then take a look at http://www3.hmc.edu/~neldredge/yamd/ its excellent! (This used to be commit 25b13f8b79d648188036f027f45bc78ec117cc88) --- source3/smbd/server.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1c6d6536ad..0d45f11693 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -693,7 +693,6 @@ static void usage(char *pname) /* If we are using the malloc debug code we can't use SIGUSR1 and SIGUSR2 to do debug level changes. */ -#ifndef MEM_MAN #if defined(SIGUSR1) CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 ); #endif /* SIGUSR1 */ @@ -701,7 +700,6 @@ static void usage(char *pname) #if defined(SIGUSR2) CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 ); #endif /* SIGUSR2 */ -#endif /* MEM_MAN */ DEBUG(3,( "loaded services\n")); -- cgit From 632b4f806eae15e319b8f62caef5d25634cf720c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 Jan 2000 06:30:50 +0000 Subject: added suppport for unexpected udp/138 packets I also fixed up the lookup_pdc_name() code so that it now works, even with a NT server that insists on replying to udp/138. The method I used to match packets was to use the mailslot string as a datagram ID. The true dgm_id doesn't work as NT doesn't set it correctly. uggh. PS: Jeremy, I had to change your code quite a bit, are you sure this worked with a Samba PDC?? The code looked broken, it got the offsets wrong in the SMB portion of the packet and filled in the IP incorrectly. (This used to be commit 32f66f4ea63038cb4b3785bdf1762abdde076f5d) --- source3/smbd/password.c | 163 ++++++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 75 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9792c9ebc8..ca588c6681 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -959,16 +959,18 @@ struct cli_state *server_cryptkey(void) struct cli_state *cli; fstring desthost; struct in_addr dest_ip; - char *p; - BOOL connected_ok = False; + char *p, *pserver; + BOOL connected_ok = False; cli = server_client(); if (!cli_initialise(cli)) return NULL; - p = lp_passwordserver(); - while(p && next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { + pserver = strdup(lp_passwordserver()); + p = pserver; + + while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { standard_sub_basic(desthost); strupper(desthost); @@ -989,6 +991,8 @@ struct cli_state *server_cryptkey(void) } } + free(pserver); + if (!connected_ok) { DEBUG(0,("password server not available\n")); cli_shutdown(cli); @@ -1249,15 +1253,79 @@ static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, un * Ignore addresses we have already tried. */ - if(ip_equal(ipzero, *ip)) - return False; + if (ip_equal(ipzero, *ip)) + return False; - if(!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) - return False; + if (!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) + return False; return connect_to_domain_password_server(pcli, dc_name, trust_passwd); } + + +/*********************************************************************** + We have been asked to dynamcially determine the IP addresses of + the PDC and BDC's for this DOMAIN, and query them in turn. +************************************************************************/ +static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd) +{ + struct in_addr *ip_list = NULL; + int count = 0; + int i; + BOOL connected_ok = False; + + if (!get_dc_list(lp_workgroup(), &ip_list, &count)) + return False; + + /* + * Firstly try and contact a PDC/BDC who has the same + * network address as any of our interfaces. + */ + for(i = 0; i < count; i++) { + if(!is_local_net(ip_list[i])) + continue; + + if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) + break; + + ip_list[i] = ipzero; /* Tried and failed. */ + } + + /* + * Secondly try and contact a random PDC/BDC. + */ + if(!connected_ok) { + i = (sys_random() % count); + + if (!(connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) + ip_list[i] = ipzero; /* Tried and failed. */ + } + + /* + * Finally go through the IP list in turn, ignoring any addresses + * we have already tried. + */ + if(!connected_ok) { + /* + * Try and connect to any of the other IP addresses in the PDC/BDC list. + * Note that from a WINS server the #1 IP address is the PDC. + */ + for(i = 0; i < count; i++) { + if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) + break; + } + } + + if(ip_list != NULL) + free((char *)ip_list); + + + return connected_ok; +} + + + /*********************************************************************** Do the same as security=server, but using NT Domain calls and a session key from the machine password. @@ -1273,7 +1341,7 @@ BOOL domain_client_validate( char *user, char *domain, unsigned char local_nt_reponse[24]; unsigned char trust_passwd[16]; fstring remote_machine; - char *p; + char *p, *pserver; NET_ID_INFO_CTR ctr; NET_USER_INFO_3 info3; struct cli_state cli; @@ -1349,75 +1417,20 @@ BOOL domain_client_validate( char *user, char *domain, * PDC/BDC. Contact each in turn and try and authenticate. */ - p = lp_passwordserver(); - while(!connected_ok && p && - next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { - if(strequal(remote_machine, "*")) { - - /* - * We have been asked to dynamcially determine the IP addresses of - * the PDC and BDC's for this DOMAIN, and query them in turn. - */ - - struct in_addr *ip_list = NULL; - int count = 0; - int i; - - if(!get_dc_list(lp_workgroup(), &ip_list, &count)) - continue; - - /* - * Firstly try and contact a PDC/BDC who has the same - * network address as any of our interfaces. - */ - - for(i = 0; i < count; i++) { - if(!is_local_net(ip_list[i])) - continue; - - if((connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd))) - break; - - ip_list[i] = ipzero; /* Tried and failed. */ - } - - /* - * Secondly try and contact a random PDC/BDC. - */ - - if(!connected_ok) { - i = (sys_random() % count); + pserver = strdup(lp_passwordserver()); + p = pserver; - if(!(connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd))) - ip_list[i] = ipzero; /* Tried and failed. */ - } - - /* - * Finally go through the IP list in turn, ignoring any addresses - * we have already tried. - */ - - if(!connected_ok) { - - /* - * Try and connect to any of the other IP addresses in the PDC/BDC list. - * Note that from a WINS server the #1 IP address is the PDC. - */ - - for(i = 0; i < count; i++) { - if((connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd))) - break; - } - } - - if(ip_list != NULL) - free((char *)ip_list); - - } else { - connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); - } + while (!connected_ok && + next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { + if(strequal(remote_machine, "*")) { + connected_ok = find_connect_pdc(&cli, trust_passwd); + } else { + connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); + } } + free(pserver); + if (!connected_ok) { DEBUG(0,("domain_client_validate: Domain password server not available.\n")); cli_shutdown(&cli); -- cgit From fbd17c8dafeefac788f4bc1c41045726825f513f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 3 Jan 2000 19:19:48 +0000 Subject: simple mods to add msrpc pipe redirection. default behaviour: fall back to using internal msrpc code in smbd. (This used to be commit 8976e26d46cb991710bc77463f7f928ac00dd4d8) --- source3/smbd/ipc.c | 31 ++++++++++++++++++++++++++----- source3/smbd/pipes.c | 20 ++++++++++++++++++-- source3/smbd/server.c | 25 +++++++++++++++++++------ 3 files changed, 63 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 4e9418fa94..cb4127aee4 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3154,11 +3154,20 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) +static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p, + char *redir_data, int redir_len) { - char *rdata = malloc(p->max_trans_reply); + char *rdata; int data_len; + if (redir_data != NULL) + { + send_trans_reply(outbuf, NULL, 0, redir_data, redir_len, + redir_len > p->max_trans_reply); + return True; + } + + rdata = malloc(p->max_trans_reply); if(rdata == NULL) { DEBUG(0,("api_rpc_trans_reply: malloc fail.\n")); return False; @@ -3284,11 +3293,23 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, switch (subcommand) { case 0x26: - /* dce/rpc command */ - reply = rpc_command(p, data, tdscnt); + { + char *rdata = NULL; + int rlen = mdrcnt; + + if (p->m) + { + reply = readwrite_pipe(p, data, tdscnt, &rdata, &rlen); + } + else + { + /* dce/rpc command */ + reply = rpc_command(p, data, tdscnt); + } if (reply) - reply = api_rpc_trans_reply(outbuf, p); + reply = api_rpc_trans_reply(outbuf, p, rdata, rlen); break; + } case 0x53: /* Wait Named Pipe Handle state */ reply = api_WNPHS(outbuf, p, params, tpscnt); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 15f52c0af6..1a9ac1d7a4 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -129,7 +129,16 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) if (numtowrite == 0) nwritten = 0; else - nwritten = write_to_pipe(p, data, numtowrite); + { + if (p->m != NULL) + { + nwritten = write_pipe(p, data, numtowrite); + } + else + { + nwritten = write_to_pipe(p, data, numtowrite); + } + } if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) return (UNIXERROR(ERRDOS,ERRnoaccess)); @@ -207,7 +216,14 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,12,0,True); data = smb_buf(outbuf); - nread = read_from_pipe(p, data, smb_maxcnt); + if (p->m != NULL) + { + nread = read_pipe(p, data, smb_maxcnt); + } + else + { + nread = read_from_pipe(p, data, smb_maxcnt); + } if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0d45f11693..716f555c65 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -501,6 +501,8 @@ static void usage(char *pname) ****************************************************************************/ int main(int argc,char *argv[]) { + fstring sam_name; + extern BOOL append_log; /* shall I run as a daemon */ BOOL is_daemon = False; @@ -680,11 +682,6 @@ static void usage(char *pname) fstrcpy(global_myworkgroup, lp_workgroup()); - if(!pdb_generate_sam_sid()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); - exit(1); - } - CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); /* Setup the signals that allow the debug log level @@ -734,7 +731,23 @@ static void usage(char *pname) /* possibly reload the services file. */ reload_services(True); - + + /* obtain or create a SAM SID */ + if (lp_domain_logons()) + { + fstrcpy(sam_name, global_myworkgroup); + } + else + { + fstrcpy(sam_name, global_myname); + } + + if(!pdb_generate_sam_sid(sam_name, NULL)) + { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); + exit(1); + } + if (*lp_rootdir()) { if (sys_chroot(lp_rootdir()) == 0) DEBUG(2,("Changed root to %s\n", lp_rootdir())); -- cgit From 7434c1aabdee5e71ffc752d9df7250808c824d46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Jan 2000 01:01:27 +0000 Subject: Fixed getgrent() recurse problem. Jeremy. (This used to be commit b5420f6152d5df415231cb3fdf614542dbbd7db3) --- source3/smbd/password.c | 53 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ca588c6681..e7f7f2c039 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -618,24 +618,61 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) #ifdef HAVE_GETGRENT { struct group *gptr; - char **member; setgrent(); while ((gptr = (struct group *)getgrent())) { - if (!strequal(gptr->gr_name,group)) - continue; - member = gptr->gr_mem; - while (member && *member) { + if (strequal(gptr->gr_name,group)) + break; + } + + /* + * As user_ok can recurse doing a getgrent(), we must + * copy the member list into a pstring on the stack before + * use. Bug pointed out by leon@eatworms.swmed.edu. + */ + + if (gptr) { + pstring member_list; + char *member; + size_t copied_len = 0; + int i; + + *member_list = '\0'; + member = member_list; + + for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) { + size_t member_len = strlen(gptr->gr_mem[i]) + 1; + if( copied_len + member_len < sizeof(pstring)) { + + DEBUG(10,("validate_group: = gr_mem = %s\n", gptr->gr_mem[i])); + + safe_strcpy(member, gptr->gr_mem[i], sizeof(pstring) - copied_len - 1); + copied_len += member_len; + member += copied_len; + } else { + *member = '\0'; + } + } + + endgrent(); + + member = member_list; + while (*member) { static fstring name; - fstrcpy(name,*member); + fstrcpy(name,member); if (user_ok(name,snum) && password_ok(name,password,pwlen,NULL)) { endgrent(); return(&name[0]); } - member++; + + DEBUG(10,("validate_group = member = %s\n", member)); + + member += strlen(member) + 1; } + } else { + endgrent(); + return NULL; } - endgrent(); } #endif return(NULL); -- cgit From 5e9f5591873fc5c5b5c8dbb0e29a080b8afe9966 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Jan 2000 06:36:36 +0000 Subject: implemented talloc() as described on samba-technical. This fixes the lp_string() bug properly. we still need to add lp_talloc_free() calls in all the main event loops, I've only put it in smbd and nmbd thus far. (This used to be commit aa7f81552540f5dca2c146f5edd805611d5b390f) --- source3/smbd/process.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 36eb882340..04432adb96 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1018,6 +1018,9 @@ void smbd_process(void) errno = 0; + /* free up temporary memory */ + lp_talloc_free(); + while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) -- cgit From c4914e2202c17dd37b88c63446c14f7eb5f94d56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Jan 2000 19:59:42 +0000 Subject: client/client.c: I18N fixes. smbd/dir.c: Reformatting comments. smbd/ipc.c: New password change code for Win98. Jeremy. (This used to be commit 9e90122afd1b6a7cf38660fc3bc3aa8e526bf08b) --- source3/smbd/dir.c | 96 ++++++++++++++++++++------------------------------ source3/smbd/ipc.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 130 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 28faa9a06b..cae6281e91 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -790,38 +790,32 @@ int TellDir(void *p) return(dirp->pos); } +/******************************************************************************* + This section manages a global directory cache. + (It should probably be split into a separate module. crh) +********************************************************************************/ -/* -------------------------------------------------------------------------- ** - * This section manages a global directory cache. - * (It should probably be split into a separate module. crh) - * -------------------------------------------------------------------------- ** - */ - -typedef struct - { +typedef struct { ubi_dlNode node; char *path; char *name; char *dname; int snum; - } dir_cache_entry; +} dir_cache_entry; static ubi_dlNewList( dir_cache ); +/***************************************************************************** + Add an entry to the directory cache. + Input: path - + name - + dname - + snum - + Output: None. +*****************************************************************************/ + void DirCacheAdd( char *path, char *name, char *dname, int snum ) - /* ------------------------------------------------------------------------ ** - * Add an entry to the directory cache. - * - * Input: path - - * name - - * dname - - * snum - - * - * Output: None. - * - * ------------------------------------------------------------------------ ** - */ - { +{ int pathlen; int namelen; dir_cache_entry *entry; @@ -852,27 +846,23 @@ void DirCacheAdd( char *path, char *name, char *dname, int snum ) while( DIRCACHESIZE < dir_cache->count ) free( ubi_dlRemTail( dir_cache ) ); - } /* DirCacheAdd */ +} +/***************************************************************************** + Search for an entry to the directory cache. + Input: path - + name - + snum - + Output: The dname string of the located entry, or NULL if the entry was + not found. + + Notes: This uses a linear search, which is is okay because of + the small size of the cache. Use a splay tree or hash + for large caches. +*****************************************************************************/ char *DirCacheCheck( char *path, char *name, int snum ) - /* ------------------------------------------------------------------------ ** - * Search for an entry to the directory cache. - * - * Input: path - - * name - - * snum - - * - * Output: The dname string of the located entry, or NULL if the entry was - * not found. - * - * Notes: This uses a linear search, which is is okay because of - * the small size of the cache. Use a splay tree or hash - * for large caches. - * - * ------------------------------------------------------------------------ ** - */ - { +{ dir_cache_entry *entry; for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); @@ -889,18 +879,15 @@ char *DirCacheCheck( char *path, char *name, int snum ) } return(NULL); - } /* DirCacheCheck */ +} + +/***************************************************************************** + Remove all cache entries which have an snum that matches the input. + Input: snum - + Output: None. +*****************************************************************************/ void DirCacheFlush(int snum) - /* ------------------------------------------------------------------------ ** - * Remove all cache entries which have an snum that matches the input. - * - * Input: snum - - * - * Output: None. - * - * ------------------------------------------------------------------------ ** - */ { dir_cache_entry *entry; ubi_dlNodePtr next; @@ -912,11 +899,4 @@ void DirCacheFlush(int snum) free( ubi_dlRemThis( dir_cache, entry ) ); entry = (dir_cache_entry *)next; } -} /* DirCacheFlush */ - -/* -------------------------------------------------------------------------- ** - * End of the section that manages the global directory cache. - * -------------------------------------------------------------------------- ** - */ - - +} diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index cb4127aee4..086a4bfa0b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1660,9 +1660,53 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch return(True); } +/*********************************************************** + Code to check a plaintext password against smbpasswd entries. +***********************************************************/ + +static BOOL check_plaintext_password(char *user,char *old_passwd, + int old_passwd_size, struct smb_passwd **psmbpw) +{ + struct smb_passwd *smbpw = NULL; + uchar old_pw[16],old_ntpw[16]; + + become_root(False); + *psmbpw = smbpw = getsmbpwnam(user); + unbecome_root(False); + + if (smbpw == NULL) { + DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); + return False; + } + + if (smbpw->acct_ctrl & ACB_DISABLED) { + DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); + return(False); + } + + nt_lm_owf_gen(old_passwd,old_ntpw,old_pw); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("check_plaintext_password: smbpw->smb_nt_passwd \n")); + dump_data(100,smbpw->smb_nt_passwd,16); + DEBUG(100,("check_plaintext_password: old_ntpw \n")); + dump_data(100,old_ntpw,16); + DEBUG(100,("check_plaintext_password: smbpw->smb_passwd \n")); + dump_data(100,smbpw->smb_passwd,16); + DEBUG(100,("check_plaintext_password: old_pw\n")); + dump_data(100,old_pw,16); +#endif + + if(memcmp(smbpw->smb_nt_passwd,old_ntpw,16) && memcmp(smbpw->smb_passwd,old_pw,16)) + return(False); + else + return(True); +} + /**************************************************************************** - set the user password - ****************************************************************************/ + Set the user password. +*****************************************************************************/ + static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1704,20 +1748,59 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param (void)Get_Pwnam( user, True); /* - * Attempt the plaintext password change first. - * Older versions of Windows seem to do this. + * Attempt to verify the old password against smbpasswd entries + * Win98 clients send old and new password in plaintext for this call. */ - if (password_ok(user, pass1,strlen(pass1),NULL) && - chgpasswd(user,pass1,pass2,False)) { - SSVAL(*rparam,0,NERR_Success); + fstring saved_pass2; + struct smb_passwd *smbpw = NULL; + + /* + * Save the new password as change_oem_password overwrites it + * with zeros. + */ + + fstrcpy(saved_pass2, pass2); + + if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) && + change_oem_password(smbpw,pass2,False)) + { + SSVAL(*rparam,0,NERR_Success); + + /* + * If unix password sync was requested, attempt to change + * the /etc/passwd database also. Return failure if this cannot + * be done. + */ + + if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) + SSVAL(*rparam,0,NERR_badpass); + } + } + + /* + * If the above failed, attempt the plaintext password change. + * This tests against the /etc/passwd database only. + */ + + if(SVAL(*rparam,0) != NERR_Success) + { + if (password_ok(user, pass1,strlen(pass1),NULL) && + chgpasswd(user,pass1,pass2,False)) + { + SSVAL(*rparam,0,NERR_Success); + } } /* * If the plaintext change failed, attempt - * the encrypted. NT will generate this - * after trying the samr method. + * the old encrypted method. NT will generate this + * after trying the samr method. Note that this + * method is done as a last resort as this + * password change method loses the NT password hash + * and cannot change the UNIX password as no plaintext + * is received. */ if(SVAL(*rparam,0) != NERR_Success) -- cgit From 5983a77020a27dd6d7591107070e5167833727d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Jan 2000 23:46:47 +0000 Subject: Moved check_plaintext_password() into smbd/chgpasswd.c from smbd/ipc.c. configure configure.in include/config.h.in: Added autoconf code for Luke's UNIX domain sockets code. Jeremy. (This used to be commit 210d61db08136122f51a93428607fccd582c9e7d) --- source3/smbd/chgpasswd.c | 43 +++++++++++++++++++++++++++++++++++++++++++ source3/smbd/ipc.c | 43 ------------------------------------------- 2 files changed, 43 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index b86091e773..406f4604b1 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -789,3 +789,46 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL overri return ret; } + +/*********************************************************** + Code to check a plaintext password against smbpasswd entries. +***********************************************************/ + +BOOL check_plaintext_password(char *user,char *old_passwd, + int old_passwd_size, struct smb_passwd **psmbpw) +{ + struct smb_passwd *smbpw = NULL; + uchar old_pw[16],old_ntpw[16]; + + become_root(False); + *psmbpw = smbpw = getsmbpwnam(user); + unbecome_root(False); + + if (smbpw == NULL) { + DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); + return False; + } + + if (smbpw->acct_ctrl & ACB_DISABLED) { + DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); + return(False); + } + + nt_lm_owf_gen(old_passwd,old_ntpw,old_pw); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("check_plaintext_password: smbpw->smb_nt_passwd \n")); + dump_data(100,smbpw->smb_nt_passwd,16); + DEBUG(100,("check_plaintext_password: old_ntpw \n")); + dump_data(100,old_ntpw,16); + DEBUG(100,("check_plaintext_password: smbpw->smb_passwd \n")); + dump_data(100,smbpw->smb_passwd,16); + DEBUG(100,("check_plaintext_password: old_pw\n")); + dump_data(100,old_pw,16); +#endif + + if(memcmp(smbpw->smb_nt_passwd,old_ntpw,16) && memcmp(smbpw->smb_passwd,old_pw,16)) + return(False); + else + return(True); +} diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 086a4bfa0b..737b364c6b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1660,49 +1660,6 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch return(True); } -/*********************************************************** - Code to check a plaintext password against smbpasswd entries. -***********************************************************/ - -static BOOL check_plaintext_password(char *user,char *old_passwd, - int old_passwd_size, struct smb_passwd **psmbpw) -{ - struct smb_passwd *smbpw = NULL; - uchar old_pw[16],old_ntpw[16]; - - become_root(False); - *psmbpw = smbpw = getsmbpwnam(user); - unbecome_root(False); - - if (smbpw == NULL) { - DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); - return False; - } - - if (smbpw->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); - return(False); - } - - nt_lm_owf_gen(old_passwd,old_ntpw,old_pw); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("check_plaintext_password: smbpw->smb_nt_passwd \n")); - dump_data(100,smbpw->smb_nt_passwd,16); - DEBUG(100,("check_plaintext_password: old_ntpw \n")); - dump_data(100,old_ntpw,16); - DEBUG(100,("check_plaintext_password: smbpw->smb_passwd \n")); - dump_data(100,smbpw->smb_passwd,16); - DEBUG(100,("check_plaintext_password: old_pw\n")); - dump_data(100,old_pw,16); -#endif - - if(memcmp(smbpw->smb_nt_passwd,old_ntpw,16) && memcmp(smbpw->smb_passwd,old_pw,16)) - return(False); - else - return(True); -} - /**************************************************************************** Set the user password. *****************************************************************************/ -- cgit From 8bd94c178ff108bbc6e686e33b99588876ab8a5a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Jan 2000 01:41:27 +0000 Subject: Re-added "dfree command" functionality that was described in the man pages but was not in the code. Jeremy. (This used to be commit f4898a1f16a2dbc25d062b0088d6c589a34c93a0) --- source3/smbd/dfree.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 86a155f526..ddb91ab498 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -198,11 +198,58 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, SMB_BIG_UINT dfree_q = 0; SMB_BIG_UINT bsize_q = 0; SMB_BIG_UINT dsize_q = 0; + char *dfree_command; (*dfree) = (*dsize) = 0; (*bsize) = 512; - fsusage(path, dfree, dsize); + + /* + * If external disk calculation specified, use it. + */ + + dfree_command = lp_dfree_command(); + if (dfree_command && *dfree_command) { + pstring line; + char *p; + FILE *pp; + + snprintf (line, sizeof(pstring), "%s %s", dfree_command, path); + pp = popen(line, "r"); + if (pp) { + fgets(line, sizeof(pstring), pp); + line[sizeof(pstring)-1] = '\0'; + if (strlen(line) > 0) + line[strlen(line)-1] = '\0'; + + DEBUG (3, ("Read input from dfree, \"%s\"\n", line)); + + *dsize = (SMB_BIG_UINT)strtoul(line, &p, 10); + while (p && *p & isspace(*p)) + p++; + if (p && *p) + *dfree = (SMB_BIG_UINT)strtoul(p, &p, 10); + while (p && *p & isspace(*p)) + p++; + if (p && *p) + *bsize = (SMB_BIG_UINT)strtoul(p, NULL, 10); + else + *bsize = 1024; + pclose (pp); + DEBUG (3, ("Parsed output of dfree, dsize=%u, dfree=%u, bsize=%u\n", + (unsigned int)*dsize, (unsigned int)*dfree, (unsigned int)*bsize)); + + if (!*dsize) + *dsize = 2048; + if (!*dfree) + *dfree = 1024; + } else { + DEBUG (0, ("disk_free: popen() failed for command %s. Error was : %s\n", + line, strerror(errno) )); + fsusage(path, dfree, dsize); + } + } else + fsusage(path, dfree, dsize); if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { (*bsize) = bsize_q; -- cgit From 171da4d78736730557a94b44af9f2d62081b80ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Jan 2000 06:55:36 +0000 Subject: this looks like a big commit, but it isn't really :) This fixes our netbios scope handling. We now have a 'netbios scope' option in smb.conf and the scope option is removed from make_nmb_name() this was prompted by a bug in our PDC finding code where it didn't append the scope to the query of the '*' name. (This used to be commit b563be824b8c3141c49558eced7829b48d4ab26f) --- source3/smbd/password.c | 1 - source3/smbd/server.c | 10 ++-------- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e7f7f2c039..44fbdfa8ec 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -28,7 +28,6 @@ extern struct in_addr ipzero; /* users from session setup */ static pstring session_users=""; -extern pstring scope; extern pstring global_myname; extern fstring global_myworkgroup; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 716f555c65..79d37e5093 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -35,7 +35,6 @@ int last_message = -1; /* a useful macro to debug the last message processed */ #define LAST_MESSAGE() smb_fn_name(last_message) -extern pstring scope; extern int DEBUGLEVEL; extern pstring user_socket_options; @@ -478,7 +477,7 @@ static void usage(char *pname) { printf("Usage: %s [-DaoPh?V] [-d debuglevel] [-l log basename] [-p port]\n", pname); - printf(" [-O socket options] [-s services file] [-i scope]\n"); + printf(" [-O socket options] [-s services file]\n"); printf("\t-D Become a daemon\n"); printf("\t-a Append to log file (default)\n"); printf("\t-o Overwrite log file, don't append\n"); @@ -491,7 +490,6 @@ static void usage(char *pname) printf("\t-p port Listen on the specified port\n"); printf("\t-O socket options Socket options\n"); printf("\t-s services file. Filename of services file\n"); - printf("\t-i scope NetBIOS scope to use (default none)\n"); printf("\n"); } @@ -520,16 +518,12 @@ static void usage(char *pname) argc--; } - while ( EOF != (opt = getopt(argc, argv, "O:i:l:s:d:Dp:h?VPaof:")) ) + while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?VPaof:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); break; - case 'i': - pstrcpy(scope,optarg); - break; - case 'P': { extern BOOL passive; -- cgit From faa302c7688eeb03f543d6dac817b5a80753a9f5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 8 Jan 2000 01:23:13 +0000 Subject: Fixed deny mode bug : : If a file is resident on NT and the first user opens it read/write with DENY_READ then a subsequent : attempt by a second user (running under Windows 95) to open it read/write DENY_NONE fails. : Under samba 2.0.5a the second open succeeds but the file is write only. Jeremy. (This used to be commit 974af581fe428fd0233c2516b16a5132b0e1b583) --- source3/smbd/open.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a940eda85d..2e4f54e40f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -631,7 +631,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == new_deny && share_pid == pid) return(AALL); - if (old_mode == 0) return(AREAD); + if (old_mode == DOS_OPEN_RDONLY) return(AREAD); /* the new smbpub.zip spec says that if the file extension is .com, .dll, .exe or .sym then allow the open. I will force @@ -651,14 +651,14 @@ static int access_table(int new_deny,int old_deny,int old_mode, switch (new_deny) { case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==0) return(AREAD); - if (old_deny==DENY_READ && old_mode==0) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==0) return(AALL); + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); return(AFAIL); case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==1) return(AREAD); - if (old_deny==DENY_READ && old_mode==1) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==1) return(AALL); + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL); return(AFAIL); case DENY_NONE: if (old_deny==DENY_WRITE) return(AREAD); @@ -711,8 +711,8 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags == O_WRONLY) || - (access_allowed == AWRITE && *flags == O_RDONLY)) + (access_allowed == AREAD && *flags != O_RDONLY) || + (access_allowed == AWRITE && *flags != O_WRONLY)) { DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", deny_mode,old_deny_mode,old_open_mode, -- cgit From fab3e0eb08ce3f479131eaea040f3d9215caa038 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 8 Jan 2000 02:16:15 +0000 Subject: smbd/mangle.c smbd/negprot.c: Tidyup of static initializers. smbd/server.c: Fix -l option. Jeremy. (This used to be commit d120f22fefde21b38e43ea5ad0180bf27304d2eb) --- source3/smbd/mangle.c | 2 +- source3/smbd/negprot.c | 2 +- source3/smbd/server.c | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 48e16e5332..4c306ad00f 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -124,7 +124,7 @@ static BOOL ct_initialized = False; #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) #define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) -static ubi_cacheRoot mangled_cache[1] = { { { 0 }, 0, 0, 0, 0, 0, 0} }; +static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } }; static BOOL mc_initialized = False; #define MANGLED_CACHE_MAX_ENTRIES 0 #define MANGLED_CACHE_MAX_MEMORY 16384 diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b2366b0a37..3cabc6b229 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -315,7 +315,7 @@ static struct { {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS}, {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE}, - {NULL,NULL}, + {NULL,NULL,NULL,0}, }; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 79d37e5093..bd07ed8458 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -504,6 +504,7 @@ static void usage(char *pname) extern BOOL append_log; /* shall I run as a daemon */ BOOL is_daemon = False; + BOOL specified_logfile = False; int port = SMB_PORT; int opt; extern char *optarg; @@ -536,6 +537,7 @@ static void usage(char *pname) break; case 'l': + specified_logfile = True; pstrcpy(debugf,optarg); break; @@ -597,7 +599,8 @@ static void usage(char *pname) TimeInit(); - pstrcpy(debugf,SMBLOGFILE); + if(!specified_logfile) + pstrcpy(debugf,SMBLOGFILE); pstrcpy(remote_machine, "smb"); @@ -714,10 +717,16 @@ static void usage(char *pname) pidfile_create("smbd"); } - if (!locking_init(0)) + if (!open_sockets(is_daemon,port)) exit(1); - if (!open_sockets(is_daemon,port)) + /* + * Note that this call should be done after the fork() call + * in open_sockets(), as some versions of the locking shared + * memory code register openers in a flat file. + */ + + if (!locking_init(0)) exit(1); if(!initialize_password_db()) -- cgit From f2fc3a2dca56fcca71e0b677625d3cdb7946d5c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 8 Jan 2000 11:32:00 +0000 Subject: fix a error in access_table revealed by the new deny test in smbtorture. We now exactly match NT for normal files. We still don't match for *.exe files though (This used to be commit 3f7fea58e8da6d98acadaabf0498ea2e88ea5678) --- source3/smbd/open.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2e4f54e40f..57f90b78b4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -631,8 +631,6 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == new_deny && share_pid == pid) return(AALL); - if (old_mode == DOS_OPEN_RDONLY) return(AREAD); - /* the new smbpub.zip spec says that if the file extension is .com, .dll, .exe or .sym then allow the open. I will force it to read-only as this seems sensible although the spec is @@ -645,6 +643,10 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AREAD); } + if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; + if (old_mode == DOS_OPEN_RDONLY) return(AREAD); + + return(AFAIL); } @@ -707,7 +709,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); + share->pid,fname); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || -- cgit From a2dac5f8f22ac58fbc3178e90288444f24190c8b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jan 2000 02:52:42 +0000 Subject: Use slprintf not snprintf. Jeremy. (This used to be commit b0a5ba9e01e71a64c7e693b6bf3f9bd499d3e095) --- source3/smbd/dfree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index ddb91ab498..bd06d3f235 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -214,7 +214,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, char *p; FILE *pp; - snprintf (line, sizeof(pstring), "%s %s", dfree_command, path); + slprintf (line, sizeof(pstring) - 1, "%s %s", dfree_command, path); pp = popen(line, "r"); if (pp) { fgets(line, sizeof(pstring), pp); -- cgit From 1e2f92af555166ea4e042e33ef41957354d233f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jan 2000 03:09:17 +0000 Subject: Added utmp fix from David Lee . Jeremy. (This used to be commit 95d37a1d25d56316c80eec54aea1f358cd621d4c) --- source3/smbd/connection.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 82f789f7a1..9a678ba88f 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -27,6 +27,11 @@ static TDB_CONTEXT *tdb; extern int DEBUGLEVEL; +#ifdef WITH_UTMP +static void utmp_yield(pid_t pid, const connection_struct *conn); +static void utmp_claim(const struct connections_data *crec, const connection_struct *conn); +#endif + /**************************************************************************** delete a connection record ****************************************************************************/ @@ -48,6 +53,12 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) kbuf.dsize = sizeof(key); tdb_delete(tdb, kbuf); + +#ifdef WITH_UTMP + if(conn) + utmp_yield(key.pid, conn); +#endif + return(True); } @@ -102,5 +113,206 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False; +#ifdef WITH_UTMP + if (conn) + utmp_claim(&crec, conn); +#endif + return True; } + +#ifdef WITH_UTMP + +/**************************************************************************** +Reflect connection status in utmp/wtmp files. + T.D.Lee@durham.ac.uk September 1999 + +Hints for porting: + o Always attempt to use programmatic interface (pututline() etc.) + o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable. + +OS status: + Solaris 2.x: Tested on 2.6 and 2.7; should be OK on other flavours. + T.D.Lee@durham.ac.uk + HPUX 9.x: Not tested. Appears not to have "x". + IRIX 6.5: Not tested. Appears to have "x". + +Notes: + The 4 byte 'ut_id' component is vital to distinguish connections, + of which there could be several hundered or even thousand. + Entries seem to be printable characters, with optional NULL pads. + + We need to be distinct from other entries in utmp/wtmp. + + Observed things: therefore avoid them. Add to this list please. + From Solaris 2.x (because that's what I have): + 'sN' : run-levels; N: [0-9] + 'co' : console + 'CC' : arbitrary things; C: [a-z] + 'rXNN' : rlogin; N: [0-9]; X: [0-9a-z] + 'tXNN' : rlogin; N: [0-9]; X: [0-9a-z] + '/NNN' : Solaris CDE + 'ftpZ' : ftp (Z is the number 255, aka 0377, aka 0xff) + Mostly a record uses the same 'ut_id' in both "utmp" and "wtmp", + but differences have been seen. + + Arbitrarily I have chosen to use a distinctive 'SM' for the + first two bytes. + + The remaining two encode the connection number used in samba locking + functions "claim_connection() and "yield_connection()". This seems + to be a "nicely behaved" number: starting from 0 then working up + looking for an available slot. + +****************************************************************************/ + +#include + +#ifdef HAVE_UTMPX_H +#include +#endif + +static const char *ut_id_encstr = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +static +int +ut_id_encode(int i, char *fourbyte) +{ + int nbase; + + fourbyte[0] = 'S'; + fourbyte[1] = 'M'; + +/* + * Encode remaining 2 bytes from 'i'. + * 'ut_id_encstr' is the character set on which modulo arithmetic is done. + * Example: digits would produce the base-10 numbers from '001'. + */ + nbase = strlen(ut_id_encstr); + + fourbyte[3] = ut_id_encstr[i % nbase]; + i /= nbase; + fourbyte[2] = ut_id_encstr[i % nbase]; + i /= nbase; + + return(i); /* 0: good; else overflow */ +} + +static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid, int i) +{ + struct timeval timeval; + int rc; + + pstrcpy(u->ut_user, conn->user); + rc = ut_id_encode(i, u->ut_id); + slprintf(u->ut_line, 12, "smb/%d", i); + + u->ut_pid = pid; + + gettimeofday(&timeval, NULL); + u->ut_time = timeval.tv_sec; + + return(rc); +} + +static void utmp_update(const pstring dirname, const struct utmp *u, const char *host) +{ + pstring fname; + +#ifdef HAVE_UTMPX_H + struct utmpx ux, *uxrc; + + getutmpx(u, &ux); + if (host) { + ux.ut_syslen = strlen(host); + pstrcpy(ux.ut_host, host); + } + + pstrcpy(fname, dirname); + pstrcat(fname, "utmpx"); + utmpxname(fname); + uxrc = pututxline(&ux); + if (uxrc == NULL) { + DEBUG(2,("utmp_update: pututxline() failed\n")); + return; + } + + pstrcpy(fname, dirname); + pstrcat(fname, "wtmpx"); + updwtmpx(fname, &ux); +#else + pstrcpy(fname, dirname); + pstrcat(fname, "utmp"); + + utmpname(fname); + pututline(u); + + pstrcpy(fname, dirname); + pstrcat(fname, "wtmp"); + + /* *** OK. Appending wtmp (as distinct from overwriting utmp) has + me baffled. How is it to be done? *** */ +#endif +} + +static void utmp_yield(int pid, const connection_struct *conn) +{ + struct utmp u; + pstring dirname; + + if (! lp_utmp(SNUM(conn))) { + DEBUG(2,("utmp_yield: lp_utmp() NULL\n")); + return; + } + + pstrcpy(dirname,lp_utmpdir()); + trim_string(dirname,"","/"); + pstrcat(dirname,"/"); + + DEBUG(2,("utmp_yield: dir:%s conn: user:%s cnum:%d i:%d\n", + dirname, conn->user, conn->cnum, conn->cnum)); + + memset((char *)&u, '\0', sizeof(struct utmp)); + u.ut_type = DEAD_PROCESS; + u.ut_exit.e_termination = 0; + u.ut_exit.e_exit = 0; + if (utmp_fill(&u, conn, pid, conn->cnum) == 0) { + utmp_update(dirname, &u, NULL); + } +} + +static void utmp_claim(const struct connections_data *crec, const connection_struct *conn) +{ + extern int Client; + struct utmp u; + pstring dirname; + + if (conn == NULL) { + DEBUG(2,("utmp_claim: conn NULL\n")); + return; + } + + if (! lp_utmp(SNUM(conn))) { + DEBUG(2,("utmp_claim: lp_utmp() NULL\n")); + return; + } + + pstrcpy(dirname,lp_utmpdir()); + trim_string(dirname,"","/"); + pstrcat(dirname,"/"); + + DEBUG(2,("utmp_claim: dir:%s conn: user:%s cnum:%d i:%d\n", + dirname, conn->user, conn->cnum, conn->cnum)); + DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s\n", + crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name(Client))); + + + memset((char *)&u, '\0', sizeof(struct utmp)); + u.ut_type = USER_PROCESS; + if (utmp_fill(&u, conn, crec->pid, conn->cnum) == 0) { + utmp_update(dirname, &u, crec->machine); + } +} + +#endif -- cgit From 826446ddef1ef0f462c02932d11e3713f00497c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 13 Jan 2000 12:10:48 +0000 Subject: changes to reflect the new syntax of the locking calls. (This used to be commit 44117df2c908d473b3e1a1020b22af6d584809ef) --- source3/smbd/blocking.c | 6 +++--- source3/smbd/open.c | 4 ++-- source3/smbd/reply.c | 29 ++++++++++++++--------------- 3 files changed, 19 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 16882be2bb..5e7d4a0c87 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -274,7 +274,7 @@ static BOOL process_lockread(blocking_lock_record *blr) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) { + if(!do_lock( fsp, conn, numtoread, startpos, READ_LOCK, &eclass, &ecode)) { if((errno != EACCES) && (errno != EAGAIN)) { /* * We have other than a "can't get lock" POSIX @@ -337,7 +337,7 @@ static BOOL process_lock(blocking_lock_record *blr) offset = IVAL(inbuf,smb_vwv3); errno = 0; - if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { + if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) { if((errno != EACCES) && (errno != EAGAIN)) { /* @@ -409,7 +409,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &eclass, &ecode)) break; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 57f90b78b4..88de1db151 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -597,7 +597,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i SMB_OFF_T mask2 = ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4); SMB_OFF_T mask = (mask2<<2); - if (is_locked(fsp,conn,~mask,0,F_WRLCK)){ + if (is_locked(fsp,conn,~mask,0,WRITE_LOCK)){ /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(conn))) @@ -640,7 +640,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, strequal(fname,".dll") || strequal(fname,".exe") || strequal(fname,".sym")) - return(AREAD); + return(AALL); } if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index aa7e95294d..1e90ff4c4f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2129,7 +2129,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s maxcount = MIN(65535,maxcount); maxcount = MAX(mincount,maxcount); - if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) + if (!is_locked(fsp,conn,maxcount,startpos, READ_LOCK)) { SMB_OFF_T size = fsp->size; SMB_OFF_T sizeneeded = startpos + maxcount; @@ -2227,7 +2227,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * for a write lock. JRA. */ - if(!do_lock( fsp, conn, numtoread, startpos, F_WRLCK, &eclass, &ecode)) { + if(!do_lock( fsp, conn, numtoread, startpos, WRITE_LOCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up @@ -2281,7 +2281,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK)) + if (is_locked(fsp,conn,numtoread,startpos, READ_LOCK)) return(ERROR(ERRDOS,ERRlock)); if (numtoread > 0) @@ -2349,7 +2349,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) + if (is_locked(fsp,conn,smb_maxcnt,startpos, READ_LOCK)) return(ERROR(ERRDOS,ERRlock)); nread = read_file(fsp,data,startpos,smb_maxcnt); @@ -2404,7 +2404,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CVAL(inbuf,smb_com) = SMBwritec; CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,tcount,startpos, F_WRLCK)) + if (is_locked(fsp,conn,tcount,startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); if (numtowrite>0) @@ -2490,7 +2490,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) + if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); /* The special X/Open SMB protocol handling of @@ -2544,7 +2544,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) + if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); /* X/Open SMB protocol says that if smb_vwv1 is @@ -2623,7 +2623,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) + if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); /* X/Open SMB protocol says that, unlike SMBwrite @@ -2877,7 +2877,7 @@ int reply_writeclose(connection_struct *conn, mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) + if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); nwritten = write_file(fsp,data,startpos,numtowrite); @@ -2926,7 +2926,7 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count)); - if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { + if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up @@ -2946,7 +2946,6 @@ int reply_lock(connection_struct *conn, /**************************************************************************** reply to a unlock ****************************************************************************/ - int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); @@ -4248,7 +4247,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); - if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode)) + if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode)) return ERROR(eclass,ecode); } @@ -4274,7 +4273,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); - if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), + if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &eclass, &ecode)) { if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { /* @@ -4354,7 +4353,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK)) + if (is_locked(fsp,conn,maxcount,startpos, READ_LOCK)) return(ERROR(ERRDOS,ERRlock)); do @@ -4416,7 +4415,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,tcount,startpos,F_WRLCK)) + if (is_locked(fsp,conn,tcount,startpos,WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); nwritten = write_file(fsp,data,startpos,numtowrite); -- cgit From 2afd5d5eb5c176f09a9f4f00ea3b517e89ef0ddf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 Jan 2000 00:50:48 +0000 Subject: some more work on the byte range locking note the ugly global_smbpid - I hope that won't bethere for long, I just didn't want to do two lots of major surgery at the one time. Using global_smbpid avoids the big change of getting rid of our inbuf/outbuf interface to reply routines. I'll do that once the locking stuff passes all tests. (This used to be commit f8bebf91abcaa5bda3ec8701f9242f220da8943a) --- source3/smbd/process.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 04432adb96..d3551b96b1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -25,7 +25,7 @@ extern int DEBUGLEVEL; struct timeval smb_last_time; -char *InBuffer = NULL; +static char *InBuffer = NULL; char *OutBuffer = NULL; char *last_inbuf = NULL; @@ -420,6 +420,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize sizeof(smb_messages) / sizeof(struct smb_message_struct); int match; extern int Client; + extern int global_smbpid; if (pid == (pid_t)-1) pid = getpid(); @@ -438,6 +439,10 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if (smb_messages[match].code == type) break; + /* yuck! this is an interim measure before we get rid of our + current inbuf/outbuf system */ + global_smbpid = SVAL(inbuf,smb_pid); + if (match == num_smb_messages) { DEBUG(0,("Unknown message type %d!\n",type)); @@ -841,7 +846,7 @@ void check_reload(int t) } /**************************************************************************** - Process any timeout housekeeping. Return False if the caler should exit. + Process any timeout housekeeping. Return False if the caller should exit. ****************************************************************************/ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time) -- cgit From 3a6c2069d77176bfa2b379ef711034396c477791 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Jan 2000 01:41:04 +0000 Subject: Added "inherit permissions" patch. Fixed locking bug found by Andrew. Jeremy. (This used to be commit 38dffd360dc2e44bfc9e751f017e24f81ff0f2fa) --- source3/smbd/blocking.c | 8 ++++- source3/smbd/dosmode.c | 77 +++++++++++++++++++++++++++++++++++++------------ source3/smbd/nttrans.c | 6 ++-- source3/smbd/open.c | 2 +- source3/smbd/reply.c | 19 +++++++----- source3/smbd/trans2.c | 4 +-- 6 files changed, 84 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 5e7d4a0c87..292eb2455e 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -208,7 +208,13 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec * of smb_lkrng structs. */ - for(i = blr->lock_num; i >= 0; i--) { + /* + * Ensure we don't do a remove on the lock that just failed, + * as under POSIX rules, if we have a lock already there, we + * will delete it (and we shouldn't) ..... + */ + + for(i = blr->lock_num - 1; i >= 0; i--) { int dummy1; uint32 dummy2; BOOL err; diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 27393fe1c6..9690f115c4 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -26,33 +26,68 @@ extern int DEBUGLEVEL; /**************************************************************************** change a dos mode to a unix mode base permission for files: - everybody gets read bit set + if inheriting + apply read/write bits from parent directory. + else + everybody gets read bit set dos readonly is represented in unix by removing everyone's write bit dos archive is represented in unix by the user's execute bit dos system is represented in unix by the group's execute bit dos hidden is represented in unix by the other's execute bit - Then apply create mask, - then add force bits. + if !inheriting { + Then apply create mask, + then add force bits. + } base permission for directories: dos directory is represented in unix by unix's dir bit and the exec bit - Then apply create mask, - then add force bits. + if !inheriting { + Then apply create mask, + then add force bits. + } ****************************************************************************/ -mode_t unix_mode(connection_struct *conn,int dosmode) +mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) { mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); + mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ if ( !IS_DOS_READONLY(dosmode) ) result |= (S_IWUSR | S_IWGRP | S_IWOTH); - + + if (fname && lp_inherit_perms(SNUM(conn))) { + char *dname; + SMB_STRUCT_STAT sbuf; + + dname = parent_dirname(fname); + DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); + if (dos_stat(dname,&sbuf) != 0) { + DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); + return(0); /* *** shouldn't happen! *** */ + } + + /* Save for later - but explicitly remove setuid bit for safety. */ + dir_mode = sbuf.st_mode & ~S_ISUID; + DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode)); + /* Clear "result" */ + result = 0; + } + if (IS_DOS_DIR(dosmode)) { /* We never make directories read only for the owner as under DOS a user can always create a file in a read-only directory. */ - result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); - /* Apply directory mask */ - result &= lp_dir_mask(SNUM(conn)); - /* Add in force bits */ - result |= lp_force_dir_mode(SNUM(conn)); + result |= (S_IFDIR | S_IWUSR); + + if (dir_mode) { + /* Inherit mode of parent directory. */ + result |= dir_mode; + } else { + /* Provisionally add all 'x' bits */ + result |= (S_IXUSR | S_IXGRP | S_IXOTH); + + /* Apply directory mask */ + result &= lp_dir_mask(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_dir_mode(SNUM(conn)); + } } else { if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode)) result |= S_IXUSR; @@ -62,11 +97,17 @@ mode_t unix_mode(connection_struct *conn,int dosmode) if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode)) result |= S_IXOTH; - - /* Apply mode mask */ - result &= lp_create_mask(SNUM(conn)); - /* Add in force bits */ - result |= lp_force_create_mode(SNUM(conn)); + + if (dir_mode) { + /* Inherit 666 component of parent directory mode */ + result |= dir_mode + & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); + } else { + /* Apply mode mask */ + result &= lp_create_mask(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_create_mode(SNUM(conn)); + } } return(result); } @@ -155,7 +196,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * if (dos_mode(conn,fname,st) == dosmode) return(0); - unixmode = unix_mode(conn,dosmode); + unixmode = unix_mode(conn,dosmode,fname); /* preserve the s bits */ mask |= (S_ISUID | S_ISGID); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9615c5ada2..81536156e5 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -726,7 +726,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(conn,smb_attr | aARCH); + unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* * If it's a request for a directory open, deal with it separately. @@ -1073,7 +1073,7 @@ static int call_nt_transact_create(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(conn,smb_attr | aARCH); + unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* * If it's a request for a directory open, deal with it separately. @@ -1834,7 +1834,7 @@ static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * ACE entries. These are the permissions a file would get when * being created in the directory. */ - mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE); + mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); owner_access = map_unix_perms(&owner_acl_type, mode, S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 88de1db151..ad208005a0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1147,7 +1147,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, return -1; } - if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 0) { + if(dos_mkdir(fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1e90ff4c4f..d15a26b20c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1547,7 +1547,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(conn,aARCH); + unixmode = unix_mode(conn,aARCH,fname); open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unixmode, oplock_request,&rmode,NULL); @@ -1649,7 +1649,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(conn,smb_attr | aARCH); + unixmode = unix_mode(conn,smb_attr | aARCH, fname); open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); @@ -1773,7 +1773,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); } - unixmode = unix_mode(conn,createmode); + unixmode = unix_mode(conn,createmode,fname); fsp = file_new(); if (!fsp) @@ -1853,7 +1853,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(fname,"/TMXXXXXX"); unix_convert(fname,conn,0,&bad_path,NULL); - unixmode = unix_mode(conn,createmode); + unixmode = unix_mode(conn,createmode,fname); fsp = file_new(); if (fsp) @@ -3076,7 +3076,7 @@ int reply_printopen(connection_struct *conn, /* Open for exclusive use, write only. */ open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL); + (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0,fname2), 0, NULL, NULL); if (!fsp->open) { file_free(fsp); @@ -3235,7 +3235,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) - ret = dos_mkdir(directory,unix_mode(conn,aDIR)); + ret = dos_mkdir(directory,unix_mode(conn,aDIR,directory)); if (ret < 0) { @@ -4291,7 +4291,12 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* If any of the above locks failed, then we must unlock all of the previous locks (X/Open spec). */ if(i != num_locks && num_locks != 0) { - for(; i >= 0; i--) { + /* + * Ensure we don't do a remove on the lock that just failed, + * as under POSIX rules, if we have a lock already there, we + * will delete it (and we shouldn't) ..... + */ + for(i--; i >= 0; i--) { count = get_lock_count( data, i, large_file_format, &err1); offset = get_lock_offset( data, i, large_file_format, &err2); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9811a9ff01..896200059f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -232,7 +232,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - unixmode = unix_mode(conn,open_attr | aARCH); + unixmode = unix_mode(conn,open_attr | aARCH, fname); open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); @@ -2014,7 +2014,7 @@ static int call_trans2mkdir(connection_struct *conn, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory,conn)) - ret = dos_mkdir(directory,unix_mode(conn,aDIR)); + ret = dos_mkdir(directory,unix_mode(conn,aDIR,directory)); if(ret < 0) { -- cgit From 82af221e4a7e456f580f16bc5d2fd904fc018c96 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 Jan 2000 04:32:57 +0000 Subject: we now pass all byte range locking tests the last piece was to use a smb timeout slightly larger than the locking timeout in bloking locks to prevent a race (This used to be commit 1b54cb4a33a65e62c2e3189b78ef073869a60c75) --- source3/smbd/close.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index bfef7c5235..7f5769b368 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -115,6 +115,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) release_file_oplock(fsp); + locking_close_file(fsp); + if(fd_attempt_close(fsp->fd_ptr,&err) == 0) last_reference = True; -- cgit From 94bdf0572b44f6751e89d4a6291b65444c6de9ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Jan 2000 23:50:38 +0000 Subject: useable_space does not include the alignment offset calculations. Bugfix from Marc_Jacobsen@hp.com. Jeremy. (This used to be commit eb06c199163232453e2d9ca50d00765c90f8f3e2) --- source3/smbd/trans2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 896200059f..4b774a4ed1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -95,7 +95,14 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset; /* We can never send more than useable_space */ - total_sent_thistime = MIN(total_sent_thistime, useable_space); + /* + * Note that 'useable_space' does not include the alignment offsets, + * but we must include the alignment offsets in the calculation of + * the length of the data we send over the wire, as the alignment offsets + * are sent here. Fix from Marc_Jacobsen@hp.com. + */ + total_sent_thistime = MIN(total_sent_thistime, useable_space + + alignment_offset + data_alignment_offset); set_message(outbuf, 10, total_sent_thistime, True); -- cgit From b3b634ff4251cca647e1e545fe1e4160736d96b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 11:18:04 +0000 Subject: use string_set() instead of string_init() bug pointed out by Richard (This used to be commit 070f49397ff24e4d6ba7c2c1cfaef2dfa0944bd0) --- source3/smbd/conn.c | 8 ++++---- source3/smbd/files.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 5dc904bd91..83289b2184 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -115,10 +115,10 @@ connection_struct *conn_new(void) num_open++; - string_init(&conn->user,""); - string_init(&conn->dirpath,""); - string_init(&conn->connectpath,""); - string_init(&conn->origpath,""); + string_set(&conn->user,""); + string_set(&conn->dirpath,""); + string_set(&conn->connectpath,""); + string_set(&conn->origpath,""); DLIST_ADD(Connections, conn); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d6203580cf..dd1f7037f6 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -97,7 +97,7 @@ files_struct *file_new(void ) files_used++; fsp->fnum = i + FILE_HANDLE_OFFSET; - string_init(&fsp->fsp_name,""); + string_set(&fsp->fsp_name,""); DLIST_ADD(Files, fsp); -- cgit From 2d96e58287a89d6f2cf584ada6154eca83cf1e6b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 11:21:33 +0000 Subject: rewrote the access_table() code to get it right for *.exe, *.dll, *.sym and *.com files. I still find it incredible that SMB treats file locking differently depending on the file name - that is so ugly it stinks. anyway, we now behave the same way as NT, except for the same-connection case which I'm still working on. (This used to be commit 5b9be3feca26f1f20fe3f32ba90769cc78f9bb6b) --- source3/smbd/open.c | 68 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ad208005a0..7558954ec6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -620,34 +620,50 @@ enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* reproduce the share mode access table ********************************************************************/ - static int access_table(int new_deny,int old_deny,int old_mode, pid_t share_pid,char *fname) { if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - pid_t pid = getpid(); - if (old_deny == new_deny && share_pid == pid) - return(AALL); - - /* the new smbpub.zip spec says that if the file extension is - .com, .dll, .exe or .sym then allow the open. I will force - it to read-only as this seems sensible although the spec is - a little unclear on this. */ - if ((fname = strrchr(fname,'.'))) { - if (strequal(fname,".com") || - strequal(fname,".dll") || - strequal(fname,".exe") || - strequal(fname,".sym")) - return(AALL); - } - - if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; - if (old_mode == DOS_OPEN_RDONLY) return(AREAD); - - - return(AFAIL); + if (old_deny == DENY_DOS || new_deny == DENY_DOS || + old_deny == DENY_FCB || new_deny == DENY_FCB) { + if ((fname = strrchr(fname,'.'))) { + if (strequal(fname,".com") || + strequal(fname,".dll") || + strequal(fname,".exe") || + strequal(fname,".sym")) { + if (old_deny == DENY_FCB || new_deny == DENY_FCB) { + return AFAIL; + } + if (old_deny == DENY_DOS) { + if (new_deny == DENY_READ && + (old_mode == DOS_OPEN_RDONLY || + old_mode == DOS_OPEN_RDWR)) { + return AFAIL; + } + if (new_deny == DENY_WRITE && + (old_mode == DOS_OPEN_WRONLY || + old_mode == DOS_OPEN_RDWR)) { + return AFAIL; + } + return AALL; + } + if (old_deny == DENY_NONE) return AALL; + if (old_deny == DENY_READ) return AWRITE; + if (old_deny == DENY_WRITE) return AREAD; + } + } + /* it isn't a exe, dll, sym or com file */ + { + pid_t pid = getpid(); + if (old_deny == new_deny && share_pid == pid) + return(AALL); + + if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; + if (old_mode == DOS_OPEN_RDONLY) return(AREAD); + + return(AFAIL); + } } switch (new_deny) @@ -848,9 +864,6 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int return; } - if (deny_mode == DENY_FCB) - deny_mode = DENY_DOS; - if (lp_share_modes(SNUM(conn))) { int i; @@ -1338,7 +1351,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou * if we can too. */ - if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || (share_entry->pid != pid)) + if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || + (share_entry->pid != pid)) goto free_and_exit; } /* end for */ -- cgit From 446f2aef8326f41a0f56c9f2d8229413a61f1d81 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 12:26:42 +0000 Subject: as obelix would say "these romans are crazy" I've finally got the access table code right for the case where the two opens are on the same connection. It is _incredibly_ complex, but now all 1296 test cases pass. I'll be very surprised if anyone by MS and us gets this right at CIFS2000 (This used to be commit 31a5857ce4f03eb53ff8ea96c5f1ce335941336d) --- source3/smbd/open.c | 99 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7558954ec6..d0a48ced4b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -623,15 +623,49 @@ reproduce the share mode access table static int access_table(int new_deny,int old_deny,int old_mode, pid_t share_pid,char *fname) { - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (old_deny == DENY_DOS || new_deny == DENY_DOS || - old_deny == DENY_FCB || new_deny == DENY_FCB) { + pid_t pid = getpid(); + BOOL isexe = False; + if ((fname = strrchr(fname,'.'))) { if (strequal(fname,".com") || strequal(fname,".dll") || strequal(fname,".exe") || strequal(fname,".sym")) { + isexe = True; + } + } + + if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); + + if (share_pid == pid) { + if (isexe && old_mode == O_RDONLY && + old_deny == DENY_DOS && new_deny == DENY_READ) { + return AFAIL; + } + if (!isexe && old_mode == O_RDONLY && + old_deny == DENY_DOS && new_deny == DENY_DOS) { + return AREAD; + } + if (new_deny == DENY_FCB && old_deny == DENY_DOS) { + if (isexe) return AFAIL; + if (old_mode == DOS_OPEN_RDONLY) return AFAIL; + return AALL; + } + if (old_mode == O_RDONLY && old_deny == DENY_DOS) { + if (new_deny == DENY_FCB || new_deny == DENY_READ) { + if (isexe) return AREAD; + return AFAIL; + } + } + if (old_deny == DENY_FCB) { + if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL; + return AFAIL; + } + } + + if (old_deny == DENY_DOS || new_deny == DENY_DOS || + old_deny == DENY_FCB || new_deny == DENY_FCB) { + if (isexe) { if (old_deny == DENY_FCB || new_deny == DENY_FCB) { return AFAIL; } @@ -652,10 +686,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == DENY_READ) return AWRITE; if (old_deny == DENY_WRITE) return AREAD; } - } - /* it isn't a exe, dll, sym or com file */ - { - pid_t pid = getpid(); + /* it isn't a exe, dll, sym or com file */ if (old_deny == new_deny && share_pid == pid) return(AALL); @@ -664,27 +695,26 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL); - return(AFAIL); - case DENY_NONE: - if (old_deny==DENY_WRITE) return(AREAD); - if (old_deny==DENY_READ) return(AWRITE); - if (old_deny==DENY_NONE) return(AALL); - return(AFAIL); - } - return(AFAIL); + + switch (new_deny) + { + case DENY_WRITE: + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); + return(AFAIL); + case DENY_READ: + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL); + return(AFAIL); + case DENY_NONE: + if (old_deny==DENY_WRITE) return(AREAD); + if (old_deny==DENY_READ) return(AWRITE); + if (old_deny==DENY_NONE) return(AALL); + return(AFAIL); + } + return(AFAIL); } /**************************************************************************** @@ -712,17 +742,6 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, return False; } - if (old_deny_mode > 4 || old_open_mode > 2) - { - DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", - deny_mode,old_deny_mode,old_open_mode,fname)); - - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - - return False; - } - { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, share->pid,fname); -- cgit From 62b02ca2e277e45a5b0377710dfa5f13ae58f0b6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 12:53:12 +0000 Subject: made access_table() a pure logic function - makes it simpler to apply maths to (This used to be commit 0ad62f128d1c26b8f7e71bc045c6f4a584f8d374) --- source3/smbd/open.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d0a48ced4b..8a30f5e5c3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -615,29 +615,38 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i } } + +/******************************************************************* +return True if the filename is one of the special executable types +********************************************************************/ +static BOOL is_executable(char *fname) +{ + if ((fname = strrchr(fname,'.'))) { + if (strequal(fname,".com") || + strequal(fname,".dll") || + strequal(fname,".exe") || + strequal(fname,".sym")) { + return True; + } + } + return False; +} + enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* reproduce the share mode access table +this is horrendoously complex, and really can't be justified on any +rational grounds except that this is _exactly_ what NT does. See +the DENY1 and DENY2 tests in smbtorture for a comprehensive set of +test routines. ********************************************************************/ static int access_table(int new_deny,int old_deny,int old_mode, - pid_t share_pid,char *fname) + BOOL same_pid, BOOL isexe) { - pid_t pid = getpid(); - BOOL isexe = False; - - if ((fname = strrchr(fname,'.'))) { - if (strequal(fname,".com") || - strequal(fname,".dll") || - strequal(fname,".exe") || - strequal(fname,".sym")) { - isexe = True; - } - } - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - if (share_pid == pid) { + if (same_pid) { if (isexe && old_mode == O_RDONLY && old_deny == DENY_DOS && new_deny == DENY_READ) { return AFAIL; @@ -687,7 +696,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == DENY_WRITE) return AREAD; } /* it isn't a exe, dll, sym or com file */ - if (old_deny == new_deny && share_pid == pid) + if (old_deny == new_deny && same_pid) return(AALL); if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; @@ -717,6 +726,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } + /**************************************************************************** check if we can open a file with a share mode ****************************************************************************/ @@ -744,7 +754,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); + (share->pid == getpid()),is_executable(fname)); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || -- cgit From 4e15be9cf1378149688f7a2744c1fe36a7f54f7e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 13:17:05 +0000 Subject: fixed some typos in access_table() which, amaziingly enough, make no difference to the result. (This used to be commit 9e28b7220bc293e386fec30c2d2e7e401b61b1f7) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8a30f5e5c3..57fbdb24c4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -647,11 +647,11 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); if (same_pid) { - if (isexe && old_mode == O_RDONLY && + if (isexe && old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS && new_deny == DENY_READ) { return AFAIL; } - if (!isexe && old_mode == O_RDONLY && + if (!isexe && old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS && new_deny == DENY_DOS) { return AREAD; } @@ -660,7 +660,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_mode == DOS_OPEN_RDONLY) return AFAIL; return AALL; } - if (old_mode == O_RDONLY && old_deny == DENY_DOS) { + if (old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS) { if (new_deny == DENY_FCB || new_deny == DENY_READ) { if (isexe) return AREAD; return AFAIL; -- cgit From b5e7e4277d87c9eaa663f92c081a869b34170380 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Jan 2000 22:57:51 +0000 Subject: First set of speed improvements from Ying Chen . Inline several commonly used functions as macros. Jeremy. (This used to be commit fc0219c7cc4b83e6db17d5b3be70d74fd7971089) --- source3/smbd/blocking.c | 1 - source3/smbd/dir.c | 12 ------------ source3/smbd/nttrans.c | 1 - source3/smbd/process.c | 2 -- 4 files changed, 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 292eb2455e..c90f475b46 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -22,7 +22,6 @@ #include "includes.h" extern int DEBUGLEVEL; extern int Client; -extern int chain_size; extern char *OutBuffer; /**************************************************************************** diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index cae6281e91..f3f261f0b2 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -493,8 +493,6 @@ int dptr_create(connection_struct *conn,char *path, BOOL old_handle, BOOL expect return(dptr->dnum); } -#define DPTR_MASK ((uint32)(((uint32)1)<<31)) - /**************************************************************************** Fill the 5 byte server reserved dptr field. ****************************************************************************/ @@ -516,16 +514,6 @@ BOOL dptr_fill(char *buf1,unsigned int key) return(True); } - -/**************************************************************************** - Return True if the offset is at zero. -****************************************************************************/ - -BOOL dptr_zero(char *buf) -{ - return((IVAL(buf,1)&~DPTR_MASK) == 0); -} - /**************************************************************************** Fetch the dir ptr and seek it given the 5 byte server field. ****************************************************************************/ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 81536156e5..f4015d50df 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -27,7 +27,6 @@ extern int Protocol; extern int Client; extern int smb_read_error; extern int global_oplock_break; -extern int chain_size; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d3551b96b1..7d6e171d05 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -561,7 +561,6 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) int type = CVAL(inbuf,smb_com); int outsize = 0; int msg_type = CVAL(inbuf,0); - extern int chain_size; GetTimeOfDay(&smb_last_time); @@ -726,7 +725,6 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) int outsize2; char inbuf_saved[smb_wct]; char outbuf_saved[smb_wct]; - extern int chain_size; int wct = CVAL(outbuf,smb_wct); int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); -- cgit From d867b86721e988dee56d5e9382b32c870ccb2790 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jan 2000 00:12:35 +0000 Subject: Second set of inline optimisation fixes from Ying Chen . Stop makeing function calls for every use of skip_multibyte_char. This function is called several *million* times during a NetBench run :-). Jeremy. (This used to be commit e5a3deba46ea2d4cb49a6c4b73edd766fe8b5a5c) --- source3/smbd/mangle.c | 8 ++++---- source3/smbd/reply.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 4c306ad00f..e47bcd896f 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -255,7 +255,7 @@ static BOOL is_illegal_name( char *name ) s = (unsigned char *)name; while( *s ) { - skip = skip_multibyte_char( *s ); + skip = get_character_len( *s ); if( skip != 0 ) { s += skip; @@ -374,7 +374,7 @@ BOOL is_8_3( char *fname, BOOL check_case ) dot_pos = NULL; while( *p ) { - if( (skip = skip_multibyte_char( *p )) != 0 ) + if( (skip = get_character_len( *p )) != 0 ) p += skip; else { @@ -878,7 +878,7 @@ void mangle_name_83( char *s) *p++ = 0; while( *p && extlen < 3 ) { - skip = skip_multibyte_char( *p ); + skip = get_character_len( *p ); switch( skip ) { case 2: @@ -912,7 +912,7 @@ void mangle_name_83( char *s) while( *p && baselen < 5 ) { - skip = skip_multibyte_char(*p); + skip = get_character_len(*p); switch( skip ) { case 2: diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d15a26b20c..d1ccda1750 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1334,7 +1334,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size p = mask; while(*p) { - if((skip = skip_multibyte_char( *p )) != 0 ) + if((skip = get_character_len( *p )) != 0 ) { p += skip; } -- cgit From ace4006c9f7ac16b3c09b1b2222f607bccfa040e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jan 2000 21:25:35 +0000 Subject: Added hash-based stat cache code from Ying Chen. Jeremy. (This used to be commit b62a1bd6328f5894ae1a2fef3ef6fc66304ade52) --- source3/smbd/filename.c | 173 +++++++++++++++++++++++++----------------------- source3/smbd/server.c | 1 + 2 files changed, 93 insertions(+), 81 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 64f63805f3..2f8e92d98e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -3,6 +3,8 @@ Version 1.9. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1999-200 + Copyright (C) Ying Chen 2000 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 @@ -19,6 +21,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * New hash table stat cache code added by Ying Chen. + */ + #include "includes.h" extern int DEBUGLEVEL; @@ -109,15 +115,12 @@ stat cache was %f%% effective.\n", global_stat_cache_lookups, } typedef struct { - ubi_dlNode link; int name_len; - pstring orig_name; - pstring translated_name; + char names[2]; /* This is extended via malloc... */ } stat_cache_entry; -#define MAX_STAT_CACHE_SIZE 50 - -static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0}; +#define INIT_STAT_CACHE_SIZE 512 +static hash_table stat_cache; /**************************************************************************** Compare a pathname to a name in the stat cache - of a given length. @@ -144,9 +147,11 @@ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) static void stat_cache_add( char *full_orig_name, char *orig_translated_path) { stat_cache_entry *scp; + stat_cache_entry *found_scp; pstring orig_name; pstring translated_path; int namelen; + hash_element *hash_elem; if (!lp_stat_cache()) return; @@ -194,39 +199,39 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) * add it. */ - for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; - scp = (stat_cache_entry *)ubi_dlNext( scp )) { - if((strcmp( scp->orig_name, orig_name) == 0) && - (strcmp( scp->translated_name, translated_path) == 0)) { - /* - * Name does exist - promote it. - */ - if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != scp ) { - ubi_dlRemThis( &stat_cache, scp); - ubi_dlAddHead( &stat_cache, scp); - } + if (hash_elem = hash_lookup(&stat_cache, orig_name)) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { return; + } else { + hash_remove(&stat_cache, hash_elem); + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy((scp->names+namelen+1), translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); } - } - - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry))) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); return; - } - - pstrcpy(scp->orig_name, orig_name); - pstrcpy(scp->translated_name, translated_path); - scp->name_len = namelen; - - ubi_dlAddHead( &stat_cache, scp); + } else { - DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name )); + /* + * New entry. + */ - if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) { - scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache ); - free((char *)scp); - return; + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy(scp->names+namelen+1, translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); } + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); } /**************************************************************************** @@ -238,10 +243,14 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; + char *trans_name; pstring chk_name; int namelen; + hash_element *hash_elem; + char *sp; - if (!lp_stat_cache()) return False; + if (!lp_stat_cache()) + return False; namelen = strlen(name); @@ -260,55 +269,44 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU if(!case_sensitive) strupper( chk_name ); - for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; - scp = (stat_cache_entry *)ubi_dlNext( scp )) { - if(scp->name_len <= namelen) { - if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) { - if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len)) - longest_hit = scp; + while (1) { + hash_elem = hash_lookup(&stat_cache, chk_name); + if(hash_elem == NULL) { + /* + * Didn't find it - remove last component for next try. + */ + sp = strrchr(chk_name, '/'); + if (sp) { + *sp = '\0'; + } else { + /* + * We reached the end of the name - no match. + */ + global_stat_cache_misses++; + return False; } + if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) + || (strcmp(chk_name, "..") == 0)) { + global_stat_cache_misses++; + return False; + } + } else { + scp = (stat_cache_entry *)(hash_elem->value); + global_stat_cache_hits++; + trans_name = scp->names+scp->name_len+1; + if(dos_stat( trans_name, pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + hash_remove(&stat_cache, hash_elem); + return False; + } + memcpy(name, trans_name, scp->name_len); + *start = &name[scp->name_len]; + if(**start == '/') + ++*start; + StrnCpy( dirpath, trans_name, name - (*start)); + return (namelen == scp->name_len); } } - - if(longest_hit == NULL) { - DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name)); - global_stat_cache_misses++; - return False; - } - - global_stat_cache_hits++; - - DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n", - name, longest_hit->orig_name, longest_hit->translated_name )); - - /* - * longest_hit is the longest match we got in the list. - * Check it exists - if so, overwrite the original name - * and then promote it to the top. - */ - - if(dos_stat( longest_hit->translated_name, pst) != 0) { - /* - * Discard this entry. - */ - ubi_dlRemThis( &stat_cache, longest_hit); - free((char *)longest_hit); - return False; - } - - memcpy(name, longest_hit->translated_name, longest_hit->name_len); - if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) { - ubi_dlRemThis( &stat_cache, longest_hit); - ubi_dlAddHead( &stat_cache, longest_hit); - } - - *start = &name[longest_hit->name_len]; - if(**start == '/') - ++*start; - - StrnCpy( dirpath, longest_hit->translated_name, name - (*start)); - - return (namelen == longest_hit->name_len); } /**************************************************************************** @@ -352,7 +350,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, *dirpath = 0; *bad_path = False; if(pst) { - ZERO_STRUCTP(pst); + ZERO_STRUCTP(pst); } if(saved_last_component) @@ -744,3 +742,16 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d CloseDir(cur_dir); return(False); } + +/*************************************************************************** ** + * Initializes or clears the stat cache. + * + * Input: none. + * Output: none. + * + * ************************************************************************** ** + */ +BOOL reset_stat_cache( void ) +{ + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); +} /* reset_stat_cache */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bd07ed8458..0e9675076f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -320,6 +320,7 @@ BOOL reload_services(BOOL test) } reset_mangled_cache(); + reset_stat_cache(); /* this forces service parameters to be flushed */ become_service(NULL,True); -- cgit From 451dcb3351461f52fee619e0d8a1b04d31725181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Jan 2000 01:09:21 +0000 Subject: Fixed code page conversions of messages outgoing/incoming. Jeremy. (This used to be commit 84b045cbc8b337f1e23f200af433ac9d265a22d4) --- source3/smbd/message.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 2f94bdf111..cc329d61a6 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -62,6 +62,16 @@ static void msg_deliver(void) return; } + /* + * Incoming message is in DOS codepage format. Convert to UNIX in + * place. + */ + + if(msgpos > 0) { + msgbuf[msgpos] = '\0'; /* Ensure null terminated. */ + dos_to_unix(msgbuf,True); + } + for (i=0;i Date: Sat, 29 Jan 2000 00:23:40 +0000 Subject: Wrapped popen calls in HAVE_POPEN - needed if we are to add the env patch. Jeremy. (This used to be commit 94c075faee88538e48d1898f1694500b8a5d4c8b) --- source3/smbd/dfree.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index bd06d3f235..7838080461 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -208,6 +208,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, * If external disk calculation specified, use it. */ +#ifdef HAVE_POPEN dfree_command = lp_dfree_command(); if (dfree_command && *dfree_command) { pstring line; @@ -249,6 +250,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, fsusage(path, dfree, dsize); } } else +#endif /* HAVE_POPEN */ fsusage(path, dfree, dsize); if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { -- cgit From 3d9a9cbe966fbbfccfcce3204e4bdcb1a8ccdcf5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 3 Feb 2000 05:10:09 +0000 Subject: Comments to use vfs_* functions instead of dos_* unless really accessing files on local disk. (This used to be commit b55f63da7e6a3c306ce668c77ed63a41d33240db) --- source3/smbd/vfs-wrap.c | 295 +++++++++++++++++++++++++++++++ source3/smbd/vfs.c | 450 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 745 insertions(+) create mode 100644 source3/smbd/vfs-wrap.c create mode 100644 source3/smbd/vfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c new file mode 100644 index 0000000000..24e45a6d24 --- /dev/null +++ b/source3/smbd/vfs-wrap.c @@ -0,0 +1,295 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. +s Wrap disk only vfs functions to sidestep dodgy compilers. + Copyright (C) Tim Potter 1998 + + 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" + +/* Check for NULL pointer parameters in vfswrap_* functions */ + +#define VFS_CHECK_NULL + +/* We don't want to have NULL function pointers lying around. Someone + is sure to try and execute them. These stubs are used to prevent + this possibility. */ + +int vfswrap_dummy_connect(struct vfs_connection_struct *conn, char *service, + char *user) +{ + return 0; /* Return >= 0 for success */ +} + +void vfswrap_dummy_disconnect(void) +{ +} + +/* Disk operations */ + +SMB_BIG_UINT vfswrap_disk_free(char *path, BOOL small_query, SMB_BIG_UINT *bsize, + SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + SMB_BIG_UINT result; + +#ifdef VFS_CHECK_NULL + if ((path == NULL) || (bsize == NULL) || (dfree == NULL) || + (dsize == NULL)) { + + smb_panic("NULL pointer passed to vfswrap_disk_free() function\n"); + } +#endif + + result = sys_disk_free(path, small_query, bsize, dfree, dsize); + return result; +} + +/* Directory operations */ + +DIR *vfswrap_opendir(char *fname) +{ + DIR *result; + +#ifdef VFS_CHECK_NULL + if (fname == NULL) { + smb_panic("NULL pointer passed to vfswrap_opendir()\n"); + } +#endif + + result = opendir(fname); + return result; +} + +struct dirent *vfswrap_readdir(DIR *dirp) +{ + struct dirent *result; + +#ifdef VFS_CHECK_NULL + if (dirp == NULL) { + smb_panic("NULL pointer passed to vfswrap_readdir()\n"); + } +#endif + + result = readdir(dirp); + return result; +} + +int vfswrap_mkdir(char *path, mode_t mode) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_mkdir()\n"); + } +#endif + + result = mkdir(path, mode); + return result; +} + +int vfswrap_rmdir(char *path) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_rmdir()\n"); + } +#endif + + result = rmdir(path); + return result; +} + +int vfswrap_closedir(DIR *dirp) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (dirp == NULL) { + smb_panic("NULL pointer passed to vfswrap_closedir()\n"); + } +#endif + + result = closedir(dirp); + return result; +} + +/* File operations */ + +int vfswrap_open(char *fname, int flags, mode_t mode) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (fname == NULL) { + smb_panic("NULL pointer passed to vfswrap_open()\n"); + } +#endif + + result = sys_open(fname, flags, mode); + return result; +} + +int vfswrap_close(int fd) +{ + int result; + + result = close(fd); + return result; +} + +ssize_t vfswrap_read(int fd, char *data, size_t n) +{ + ssize_t result; + +#ifdef VFS_CHECK_NULL + if (data == NULL) { + smb_panic("NULL pointer passed to vfswrap_read()\n"); + } +#endif + + result = read(fd, data, n); + return result; +} + +ssize_t vfswrap_write(int fd, char *data, size_t n) +{ + ssize_t result; + +#ifdef VFS_CHECK_NULL + if (data == NULL) { + smb_panic("NULL pointer passed to vfswrap_write()\n"); + } +#endif + + result = write(fd, data, n); + return result; +} + +SMB_OFF_T vfswrap_lseek(int filedes, SMB_OFF_T offset, int whence) +{ + SMB_OFF_T result; + + result = sys_lseek(filedes, offset, whence); + return result; +} + +int vfswrap_rename(char *old, char *new) +{ + int result; + +#ifdef VFS_CHECK_NULL + if ((old == NULL) || (new == NULL)) { + smb_panic("NULL pointer passed to vfswrap_rename()\n"); + } +#endif + + result = rename(old, new); + return result; +} + +void vfswrap_fsync(int fd) +{ + fsync(fd); +} + +int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) +{ + int result; + +#ifdef VFS_CHECK_NULL + if ((fname == NULL) || (sbuf == NULL)) { + smb_panic("NULL pointer passed to vfswrap_stat()\n"); + } +#endif + + result = sys_stat(fname, sbuf); + return result; +} + +int vfswrap_fstat(int fd, SMB_STRUCT_STAT *sbuf) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (sbuf == NULL) { + smb_panic("NULL pointer passed to vfswrap_fstat()\n"); + } +#endif + + result = sys_fstat(fd, sbuf); + return result; +} + +int vfswrap_lstat(char *path, + SMB_STRUCT_STAT *sbuf) +{ + int result; + +#ifdef VFS_CHECK_NULL + if ((path == NULL) || (sbuf == NULL)) { + smb_panic("NULL pointer passed to vfswrap_lstat()\n"); + } +#endif + + result = sys_lstat(path, sbuf); + return result; +} + +int vfswrap_unlink(char *path) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_unlink()\n"); + } +#endif + + result = unlink(path); + return result; +} + +int vfswrap_chmod(char *path, mode_t mode) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_chmod()\n"); + } +#endif + + result = chmod(path, mode); + return result; +} + +int vfswrap_utime(char *path, struct utimbuf *times) +{ + int result; + +#ifdef VFS_CHECK_NULL + if ((path == NULL) || (times == NULL)) { + smb_panic("NULL pointer passed to vfswrap_utime()\n"); + } +#endif + + result = utime(path, times); + return result; +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c new file mode 100644 index 0000000000..2f9f847188 --- /dev/null +++ b/source3/smbd/vfs.c @@ -0,0 +1,450 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + VFS initialisation and support functions + Copyright (C) Tim Potter 1999 + + 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; + +/* Some structures to help us initialise the vfs operations table */ + +struct vfs_syminfo { + char *name; + void *fptr; +}; + +/* Default vfs hooks. WARNING: The order of these initialisers is + very important. They must be in the same order as defined in + vfs.h. Change at your own peril. */ + +struct vfs_ops default_vfs_ops = { + + /* Disk operations */ + + vfswrap_dummy_connect, + vfswrap_dummy_disconnect, + vfswrap_disk_free, + + /* Directory operations */ + + vfswrap_opendir, + vfswrap_readdir, + vfswrap_mkdir, + vfswrap_rmdir, + vfswrap_closedir, + + /* File operations */ + + vfswrap_open, + vfswrap_close, + vfswrap_read, + vfswrap_write, + vfswrap_lseek, + vfswrap_rename, + vfswrap_fsync, + vfswrap_stat, + vfswrap_fstat, + vfswrap_lstat, + vfswrap_unlink, + vfswrap_chmod, + vfswrap_utime +}; + +/**************************************************************************** + initialise default vfs hooks +****************************************************************************/ +int vfs_init_default(connection_struct *conn) +{ + DEBUG(3, ("Initialising default vfs hooks\n")); + + memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(conn->vfs_ops)); + return True; +} + +/**************************************************************************** + initialise custom vfs hooks +****************************************************************************/ +#ifdef HAVE_LIBDL +BOOL vfs_init_custom(connection_struct *conn) +{ + void *handle; + struct vfs_ops *ops, *(*fptr)(struct vfs_options *options); + + DEBUG(3, ("Initialising custom vfs hooks from %s\n", + lp_vfsobj(SNUM(conn)))); + + /* Open object file */ + + handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL); + conn->vfs_conn->dl_handle = handle; + + if (!handle) { + DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), + dlerror())); + return False; + } + + /* Get handle on vfs_init() symbol */ + + fptr = dlsym(handle, "vfs_init"); + + if (fptr == NULL) { + DEBUG(0, ("No vfs_init() symbol found in %s\n", + lp_vfsobj(SNUM(conn)))); + return False; + } + + /* Initialise vfs_ops structure */ + + if ((ops = fptr(NULL)) == NULL) { + DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); + return False; + } + + /* Fill in unused operations with default (disk based) ones. + There's probably a neater way to do this then a whole bunch of + if statements. */ + + memcpy(&conn->vfs_ops, ops, sizeof(conn->vfs_ops)); + + if (conn->vfs_ops.connect == NULL) { + conn->vfs_ops.connect = default_vfs_ops.connect; + } + + if (conn->vfs_ops.disconnect == NULL) { + conn->vfs_ops.disconnect = default_vfs_ops.disconnect; + } + + if (conn->vfs_ops.disk_free == NULL) { + conn->vfs_ops.disk_free = default_vfs_ops.disk_free; + } + + if (conn->vfs_ops.opendir == NULL) { + conn->vfs_ops.opendir = default_vfs_ops.opendir; + } + + if (conn->vfs_ops.readdir == NULL) { + conn->vfs_ops.readdir = default_vfs_ops.readdir; + } + + if (conn->vfs_ops.mkdir == NULL) { + conn->vfs_ops.mkdir = default_vfs_ops.mkdir; + } + + if (conn->vfs_ops.rmdir == NULL) { + conn->vfs_ops.rmdir = default_vfs_ops.rmdir; + } + + if (conn->vfs_ops.closedir == NULL) { + conn->vfs_ops.closedir = default_vfs_ops.closedir; + } + + if (conn->vfs_ops.open == NULL) { + conn->vfs_ops.open = default_vfs_ops.open; + } + + if (conn->vfs_ops.close == NULL) { + conn->vfs_ops.close = default_vfs_ops.close; + } + + if (conn->vfs_ops.read == NULL) { + conn->vfs_ops.read = default_vfs_ops.read; + } + + if (conn->vfs_ops.write == NULL) { + conn->vfs_ops.write = default_vfs_ops.write; + } + + if (conn->vfs_ops.lseek == NULL) { + conn->vfs_ops.lseek = default_vfs_ops.lseek; + } + + if (conn->vfs_ops.rename == NULL) { + conn->vfs_ops.rename = default_vfs_ops.rename; + } + + if (conn->vfs_ops.fsync == NULL) { + conn->vfs_ops.fsync = default_vfs_ops.fsync; + } + + if (conn->vfs_ops.stat == NULL) { + conn->vfs_ops.stat = default_vfs_ops.stat; + } + + if (conn->vfs_ops.fstat == NULL) { + conn->vfs_ops.fstat = default_vfs_ops.fstat; + } + + if (conn->vfs_ops.lstat == NULL) { + conn->vfs_ops.lstat = default_vfs_ops.lstat; + } + + if (conn->vfs_ops.unlink == NULL) { + conn->vfs_ops.unlink = default_vfs_ops.unlink; + } + + if (conn->vfs_ops.chmod == NULL) { + conn->vfs_ops.chmod = default_vfs_ops.chmod; + } + + if (conn->vfs_ops.utime == NULL) { + conn->vfs_ops.utime = default_vfs_ops.utime; + } + + return True; +} +#endif + +BOOL vfs_directory_exist(connection_struct *conn, char *dname, + SMB_STRUCT_STAT *st) +{ + SMB_STRUCT_STAT st2; + BOOL ret; + + if (!st) st = &st2; + + if (conn->vfs_ops.stat(dname,st) != 0) + return(False); + + ret = S_ISDIR(st->st_mode); + if(!ret) + errno = ENOTDIR; + + return ret; +} + +/******************************************************************* + check if a vfs file exists +********************************************************************/ +BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) +{ + SMB_STRUCT_STAT st; + if (!sbuf) sbuf = &st; + + if (conn->vfs_ops.stat(fname,sbuf) != 0) + return(False); + + return(S_ISREG(sbuf->st_mode)); +} + +/**************************************************************************** + write data to a fd on the vfs +****************************************************************************/ +ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) +{ + size_t total=0; + ssize_t ret; + int fd = fsp->fd_ptr->fd; + + while (total < N) + { + ret = fsp->conn->vfs_ops.write(fd,buffer + total,N - total); + + if (ret == -1) return -1; + if (ret == 0) return total; + + total += ret; + } + return (ssize_t)total; +} + +/**************************************************************************** +transfer some data between two file_struct's +****************************************************************************/ +SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, + int out_fd, files_struct *out_fsp, + SMB_OFF_T n, char *header, int headlen, int align) +{ + static char *buf=NULL; + static int size=0; + char *buf1,*abuf; + SMB_OFF_T total = 0; + + DEBUG(4,("vfs_transfer_file n=%.0f (head=%d) called\n",(double)n,headlen)); + + /* Check we have at least somewhere to read from */ + + SMB_ASSERT((in_fd != -1) || (in_fsp != NULL)); + + if (size == 0) { + size = lp_readsize(); + size = MAX(size,1024); + } + + while (!buf && size>0) { + buf = (char *)Realloc(buf,size+8); + if (!buf) size /= 2; + } + + if (!buf) { + DEBUG(0,("Can't allocate transfer buffer!\n")); + exit(1); + } + + abuf = buf + (align%8); + + if (header) + n += headlen; + + while (n > 0) + { + int s = (int)MIN(n,(SMB_OFF_T)size); + int ret,ret2=0; + + ret = 0; + + if (header && (headlen >= MIN(s,1024))) { + buf1 = header; + s = headlen; + ret = headlen; + headlen = 0; + header = NULL; + } else { + buf1 = abuf; + } + + if (header && headlen > 0) + { + ret = MIN(headlen,size); + memcpy(buf1,header,ret); + headlen -= ret; + header += ret; + if (headlen <= 0) header = NULL; + } + + if (s > ret) { + ret += in_fsp ? + in_fsp->conn->vfs_ops.read(in_fsp->fd_ptr->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); + } + + if (ret > 0) + { + if (out_fsp) { + ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd_ptr->fd,buf1,ret); + } else { + ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret; + } + } + + if (ret2 > 0) total += ret2; + /* if we can't write then dump excess data */ + if (ret2 != ret) + vfs_transfer_file(in_fd, in_fsp, -1,NULL,n-(ret+headlen),NULL,0,0); + + if (ret <= 0 || ret2 != ret) + return(total); + n -= ret; + } + return(total); +} + +/******************************************************************* +a vfs_readdir wrapper which just returns the file name +********************************************************************/ +char *vfs_readdirname(connection_struct *conn, void *p) +{ + struct dirent *ptr; + char *dname; + + if (!p) return(NULL); + + ptr = (struct dirent *)conn->vfs_ops.readdir(p); + if (!ptr) return(NULL); + + dname = ptr->d_name; + +#ifdef NEXT2 + if (telldir(p) < 0) return(NULL); +#endif + +#ifdef HAVE_BROKEN_READDIR + /* using /usr/ucb/cc is BAD */ + dname = dname - 2; +#endif + + { + static pstring buf; + memcpy(buf, dname, NAMLEN(ptr)+1); + unix_to_dos(buf, True); + dname = buf; + } + + unix_to_dos(dname, True); + return(dname); +} + +/*************************************************************************** + handle the interpretation of the vfs option parameter + *************************************************************************/ +static BOOL handle_vfs_option(char *pszParmValue, char **ptr) +{ + struct vfs_options *new_option, **options = (struct vfs_options **)ptr; + int i; + + /* Create new vfs option */ + + new_option = (struct vfs_options *)malloc(sizeof(*new_option)); + if (new_option == NULL) { + return False; + } + + ZERO_STRUCTP(new_option); + + /* Get name and value */ + + new_option->name = strtok(pszParmValue, "="); + + if (new_option->name == NULL) { + return False; + } + + while(isspace(*new_option->name)) { + new_option->name++; + } + + for (i = strlen(new_option->name); i > 0; i--) { + if (!isspace(new_option->name[i - 1])) break; + } + + new_option->name[i] = '\0'; + new_option->name = strdup(new_option->name); + + new_option->value = strtok(NULL, "="); + + if (new_option->value != NULL) { + + while(isspace(*new_option->value)) { + new_option->value++; + } + + for (i = strlen(new_option->value); i > 0; i--) { + if (!isspace(new_option->value[i - 1])) break; + } + + new_option->value[i] = '\0'; + new_option->value = strdup(new_option->value); + } + + /* Add to list */ + + DLIST_ADD(*options, new_option); + + return True; +} -- cgit From 16bb009dbbe6302febf3848cee61e9927eeb0fb5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 3 Feb 2000 05:17:25 +0000 Subject: Mega-VFS merge. Yeah baby! Synopsis: change every disk access function to work through a vfs_ops structure contained in the connection_struct. (This used to be commit 3aad500c0fb61232ed3431ff4b743b5d18ec852f) --- source3/smbd/close.c | 7 ++- source3/smbd/dir.c | 13 ++---- source3/smbd/dosmode.c | 10 ++-- source3/smbd/fileio.c | 11 +++-- source3/smbd/filename.c | 14 +++--- source3/smbd/files.c | 2 +- source3/smbd/ipc.c | 2 +- source3/smbd/nttrans.c | 25 +++++----- source3/smbd/open.c | 71 ++++++++++++++-------------- source3/smbd/predict.c | 10 ++-- source3/smbd/reply.c | 120 +++++++++++++++++++++++++----------------------- source3/smbd/server.c | 4 +- source3/smbd/service.c | 92 ++++++++++++++++++++++++++++++++++++- source3/smbd/trans2.c | 38 ++++++++------- 14 files changed, 261 insertions(+), 158 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 7f5769b368..8e2ed0de0e 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -117,10 +117,10 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) locking_close_file(fsp); - if(fd_attempt_close(fsp->fd_ptr,&err) == 0) + if(fd_attempt_close(fsp, &err) == 0) last_reference = True; - fsp->fd_ptr = NULL; + fsp->fd_ptr = NULL; if (lp_share_modes(SNUM(conn))) unlock_share_entry(conn, dev, inode); @@ -142,8 +142,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (normal_close && last_reference && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(dos_unlink(fsp->fsp_name) != 0) { - + if(fsp->conn->vfs_ops.unlink(dos_to_unix(fsp->fsp_name, False)) != 0) { /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f3f261f0b2..32fc523541 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -617,14 +617,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (dos_stat(pathreal,&sbuf) != 0) + if (conn->vfs_ops.stat(dos_to_unix(pathreal, False), &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; } - - if (check_descend && !strequal(fname,".") && !strequal(fname,"..")) - continue; *mode = dos_mode(conn,pathreal,&sbuf); @@ -673,19 +670,19 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - DIR *p = dos_opendir(name); + DIR *p = conn->vfs_ops.opendir(name); int used=0; if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { - closedir(p); + conn->vfs_ops.closedir(p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; - while ((n = dos_readdirname(p))) + while ((n = vfs_readdirname(conn, p))) { int l = strlen(n)+1; @@ -709,7 +706,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->numentries++; } - closedir(p); + conn->vfs_ops.closedir(p); return((void *)dirp); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 9690f115c4..1ae1e7e2cb 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -189,7 +189,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * if (!st) { st = &st1; - if (dos_stat(fname,st)) return(-1); + if (conn->vfs_ops.stat(dos_to_unix(fname,False),st)) return(-1); } if (S_ISDIR(st->st_mode)) dosmode |= aDIR; @@ -225,7 +225,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - return(dos_chmod(fname,unixmode)); + return(conn->vfs_ops.chmod(fname,unixmode)); } @@ -241,7 +241,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(dos_utime(fname, times) == 0) + if(conn->vfs_ops.utime(dos_to_unix(fname, False), times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -256,7 +256,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(dos_stat(fname,&sb) != 0) + if(conn->vfs_ops.stat(dos_to_unix(fname,False),&sb) != 0) return -1; /* Check if we have write access. */ @@ -269,7 +269,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(False); - ret = dos_utime(fname, times); + ret = conn->vfs_ops.utime(dos_to_unix(fname, False), times); unbecome_root(False); } } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index fa04e671f8..348486d430 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -37,7 +37,7 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; - seek_ret = sys_lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); + seek_ret = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); /* * We want to maintain the fiction that we can seek @@ -120,7 +120,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) } if (n > 0) { - readret = read(fsp->fd_ptr->fd,data,n); + readret = fsp->conn->vfs_ops.read(fsp->fd_ptr->fd,data,n); if (readret > 0) ret += readret; } @@ -173,7 +173,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) SMB_STRUCT_STAT st; fsp->modified = True; - if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); @@ -644,16 +644,17 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) return real_write_file(fsp, wcp->data, wcp->offset, data_size); } + /******************************************************************* sync a file ********************************************************************/ -void sync_file(connection_struct *conn, files_struct *fsp) +void sys_fsync_file(connection_struct *conn, files_struct *fsp) { #ifdef HAVE_FSYNC if(lp_strict_sync(SNUM(conn)) && fsp->fd_ptr != NULL) { flush_write_cache(fsp, SYNC_FLUSH); - fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); } #endif } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 2f8e92d98e..b1550e5c73 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -239,7 +239,8 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) Return True if we translated (and did a scuccessful stat on) the entire name. *****************************************************************************/ -static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst) +static BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, + char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; stat_cache_entry *longest_hit = NULL; @@ -294,7 +295,7 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU scp = (stat_cache_entry *)(hash_elem->value); global_stat_cache_hits++; trans_name = scp->names+scp->name_len+1; - if(dos_stat( trans_name, pst) != 0) { + if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; @@ -433,7 +434,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstrcpy(orig_path, name); - if(stat_cache_lookup( name, dirpath, &start, &st)) { + if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { if(pst) *pst = st; return True; @@ -443,7 +444,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (dos_stat(name,&st) == 0) { + if (conn->vfs_ops.stat(name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -509,7 +510,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Check if the name exists up to this point. */ - if (dos_stat(name, &st) == 0) { + + if (conn->vfs_ops.stat(name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -661,7 +663,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (dos_lstat(name,&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index dd1f7037f6..d62950c568 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -335,7 +335,7 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL)) { - sync_file(conn,fsp); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); } } } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 737b364c6b..3e16dba4f5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2073,7 +2073,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha !become_service(fconn,True)) break; - if (dos_rename(fsp->fsp_name,name) == 0) { + if (fsp->conn->vfs_ops.rename(fsp->fsp_name,name) == 0) { string_set(&fsp->fsp_name,name); } break; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f4015d50df..4b344c3318 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -842,13 +842,15 @@ int reply_ntcreate_and_X(connection_struct *conn, } if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), + &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (!fsp->stat_open && sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) + != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1096,7 +1098,8 @@ static int call_nt_transact_create(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), + &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1169,13 +1172,13 @@ static int call_nt_transact_create(connection_struct *conn, } if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (!fsp->stat_open && sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (!fsp->stat_open && conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1790,7 +1793,7 @@ static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) return 0; } } else { - if(sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { return 0; } } @@ -2288,9 +2291,9 @@ security descriptor.\n")); int ret; if(fsp->fd_ptr == NULL) - ret = dos_stat(fsp->fsp_name, &sbuf); + ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); else - ret = sys_fstat(fsp->fd_ptr->fd,&sbuf); + ret = conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf); if(ret != 0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2326,9 +2329,9 @@ security descriptor.\n")); int ret; if(fsp->fd_ptr == NULL) - ret = dos_stat(fsp->fsp_name, &sbuf); + ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); else - ret = sys_fstat(fsp->fd_ptr->fd,&sbuf); + ret = conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf); if(ret != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2374,7 +2377,7 @@ security descriptor.\n")); DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)perms )); - if(dos_chmod( fsp->fsp_name, perms) == -1) { + if(conn->vfs_ops.chmod(dos_to_unix(fsp->fsp_name, False), perms) == -1) { DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)perms, strerror(errno) )); return(UNIXERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 57fbdb24c4..1b4179da33 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,17 +30,17 @@ extern BOOL global_client_failed_oplock_break; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ - -static int fd_attempt_open(char *fname, int flags, mode_t mode) +static int fd_attempt_open(struct connection_struct *conn, char *fname, + int flags, mode_t mode) { - int fd = dos_open(fname,flags,mode); + int fd = conn->vfs_ops.open(fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = dos_open(fname,flags,mode); + fd = conn->vfs_ops.open(fname,flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -71,7 +71,7 @@ static int fd_attempt_open(char *fname, int flags, mode_t mode) char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = dos_open(fname,flags,mode)) == -1) + if ((fd = conn->vfs_ops.open(fname,flags,mode)) == -1) p[max_len] = tmp; } } @@ -128,9 +128,10 @@ fd support routines - attempt to re-open an already open fd as O_RDWR. Save the already open fd (we cannot close due to POSIX file locking braindamage. ****************************************************************************/ -static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) +static void fd_attempt_reopen(char *fname, mode_t mode, files_struct *fsp) { - int fd = dos_open( fname, O_RDWR, mode); + int fd = fsp->conn->vfs_ops.open(dos_to_unix(fname, False), O_RDWR, mode); + file_fd_struct *fd_ptr = fsp->fd_ptr; if(fd == -1) return; @@ -148,10 +149,10 @@ static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ - -uint16 fd_attempt_close(file_fd_struct *fd_ptr, int *err_ret) +uint16 fd_attempt_close(files_struct *fsp, int *err_ret) { extern struct current_user current_user; + file_fd_struct *fd_ptr = fsp->fd_ptr; uint16 ret_ref = fd_ptr->ref_count; *err_ret = 0; @@ -169,19 +170,19 @@ uint16 fd_attempt_close(file_fd_struct *fd_ptr, int *err_ret) if(fd_ptr->ref_count == 0) { if(fd_ptr->fd != -1) { - if(close(fd_ptr->fd) < 0) + if(fsp->conn->vfs_ops.close(fd_ptr->fd) < 0) *err_ret = errno; } if(fd_ptr->fd_readonly != -1) { - if(close(fd_ptr->fd_readonly) < 0) { + if(fsp->conn->vfs_ops.close(fd_ptr->fd_readonly) < 0) { if(*err_ret == 0) *err_ret = errno; } } if(fd_ptr->fd_writeonly != -1) { - if( close(fd_ptr->fd_writeonly) < 0) { + if(fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly) < 0) { if(*err_ret == 0) *err_ret = errno; } @@ -205,8 +206,9 @@ This is really ugly code, as due to POSIX locking braindamage we must fork and then attempt to open the file, and return success or failure via an exit code. ****************************************************************************/ - -static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) +static BOOL check_access_allowed_for_current_user(struct connection_struct + *conn, char *fname, + int accmode ) { pid_t child_pid; @@ -277,11 +279,11 @@ is no longer waiting ! Error = %s\n", strerror(errno) )); */ int fd; DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode )); - if((fd = fd_attempt_open( fname, accmode, 0)) < 0) { + if((fd = fd_attempt_open(conn, fname, accmode, 0)) < 0) { /* Access denied. */ _exit(EACCES); } - close(fd); + conn->vfs_ops.close(fd); DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); _exit(0); } @@ -369,7 +371,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * open fd table. */ if(sbuf == 0) { - if(dos_stat(fname, &statbuf) < 0) { + if(conn->vfs_ops.stat(dos_to_unix(fname,False), &statbuf) < 0) { if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); @@ -410,7 +412,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { - if(!check_access_allowed_for_current_user( fname, accmode )) { + if(!check_access_allowed_for_current_user(conn, fname, accmode )) { /* Error - permission denied. */ DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", fname, flags, accmode)); @@ -430,7 +432,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * between the last open and now. */ if(fd_ptr->real_open_flags != O_RDWR) - fd_attempt_reopen(fname, mode, fd_ptr); + fd_attempt_reopen(fname, mode, fsp); /* * Ensure that if we wanted write access @@ -467,7 +469,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fd_ptr->real_open_flags = O_RDWR; /* Set the flags as needed without the read/write modes. */ open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); + fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|O_RDWR, mode); /* * On some systems opening a file for R/W access on a read only * filesystems sets errno to EROFS. @@ -478,7 +480,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if((fd_ptr->fd == -1) && (errno == EACCES)) { #endif /* EROFS */ if(accmode != O_RDWR) { - fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); + fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode); fd_ptr->real_open_flags = accmode; } } @@ -492,10 +494,11 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (sys_disk_free(dname,False,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { + if (conn->vfs_ops.disk_free(dname,False,&dum1,&dum2,&dum3) < + (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { int err; - if(fd_attempt_close(fd_ptr, &err) == 0) - dos_unlink(fname); + if(fd_attempt_close(fsp, &err) == 0) + conn->vfs_ops.unlink(dos_to_unix(fname, False)); fsp->fd_ptr = 0; errno = ENOSPC; return; @@ -508,7 +511,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr,&err); + fd_attempt_close(fsp,&err); check_for_pipe(fname); return; } @@ -517,13 +520,13 @@ static void open_file(files_struct *fsp,connection_struct *conn, { if(sbuf == 0) { /* Do the fstat */ - if(sys_fstat(fd_ptr->fd, &statbuf) == -1) { - int err; + if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) { + int err; /* Error - backout !! */ DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", fd_ptr->fd, fname,strerror(errno))); /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr,&err); + fd_attempt_close(fsp,&err); return; } sbuf = &statbuf; @@ -573,7 +576,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { DEBUG(3,("Writing postscript line\n")); - write_file(fsp,"%!\n",-1,3); + conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3); } DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -794,7 +797,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); SMB_STRUCT_STAT sbuf; - BOOL file_existed = dos_file_exist(fname,&sbuf); + BOOL file_existed = vfs_file_exist(conn, dos_to_unix(fname,False), &sbuf); BOOL share_locked = False; BOOL fcbopen = False; int token = 0; @@ -1093,7 +1096,7 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, { extern struct current_user current_user; - if(dos_stat(fname, pst) < 0) { + if(conn->vfs_ops.stat(dos_to_unix(fname, False), pst) < 0) { DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -1157,7 +1160,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, SMB_STRUCT_STAT st; BOOL got_stat = False; - if(dos_stat(fname, &st) == 0) { + if(conn->vfs_ops.stat(dos_to_unix(fname, False), &st) == 0) { got_stat = True; } @@ -1189,7 +1192,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, return -1; } - if(dos_mkdir(fname, unix_mode(conn,aDIR, fname)) < 0) { + if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -1275,7 +1278,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) if(!lp_share_modes(SNUM(conn))) return True; - if (dos_stat(fname,&sbuf) == -1) return(True); + if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) return(True); dev = sbuf.st_dev; inode = sbuf.st_ino; diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c index de85a4a553..34044b82f2 100644 --- a/source3/smbd/predict.c +++ b/source3/smbd/predict.c @@ -42,7 +42,7 @@ extern struct timeval smb_last_time; /**************************************************************************** handle read prediction on a file ****************************************************************************/ -ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) +ssize_t read_predict(files_struct *fsp, int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) { ssize_t ret = 0; ssize_t possible = rp_length - (offset - rp_offset); @@ -70,7 +70,7 @@ ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) /* Find the end of the file - ensure we don't read predict beyond it. */ - if(sys_fstat(fd,&rp_stat) < 0) + if(fsp->conn->vfs_ops.fstat(fd,&rp_stat) < 0) { DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); predict_skip = True; @@ -95,7 +95,7 @@ ssize_t read_predict(int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) /**************************************************************************** pre-read some data ****************************************************************************/ -void do_read_prediction(void) +void do_read_prediction(connection_struct *conn) { static size_t readsize = 0; @@ -134,13 +134,13 @@ void do_read_prediction(void) } } - if (sys_lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { + if (conn->vfs_ops.lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { rp_fd = -1; rp_predict_fd = -1; return; } - rp_length = read(rp_fd,rp_buffer,rp_predict_length); + rp_length = conn->vfs_ops.read(rp_fd,rp_buffer,rp_predict_length); rp_time = time(NULL); if (rp_length < 0) rp_length = 0; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d1ccda1750..f022301450 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -981,7 +981,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int user we should become. */ { - struct passwd *pw = Get_Pwnam(user,False); + const struct passwd *pw = Get_Pwnam(user,False); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); return bad_password_error(inbuf,outbuf); @@ -1032,7 +1032,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if(VALID_STAT(st)) ok = S_ISDIR(st.st_mode); else - ok = dos_directory_exist(name,NULL); + ok = vfs_directory_exist(conn,dos_to_unix(name,False),NULL); } if (!ok) @@ -1167,7 +1167,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL)) + if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, dos_to_unix(fname,False),NULL)) mode |= aDIR; if (check_name(fname,conn)) ok = (file_chmod(conn,fname,mode,NULL) == 0); @@ -1201,7 +1201,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz int outsize = 0; SMB_BIG_UINT dfree,dsize,bsize; - sys_disk_free(".",True,&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(".",True,&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -1563,7 +1563,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1665,7 +1665,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1918,7 +1918,7 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return(False); - if (dos_lstat(fname,&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); if (!lp_delete_readonly(SNUM(conn))) { @@ -1989,7 +1989,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++; if (!count) - exists = dos_file_exist(directory,NULL); + exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); } else { void *dirptr = NULL; char *dname; @@ -2019,7 +2019,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; - if (!dos_unlink(fname)) count++; + if (!conn->vfs_ops.unlink(fname)) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); } CloseDir(dirptr); @@ -2137,7 +2137,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (sys_fstat(fsp->fd_ptr->fd,&st) == 0) + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -2161,11 +2161,11 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #if USE_READ_PREDICTION if (!fsp->can_write) - predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread); + predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread); #endif /* USE_READ_PREDICTION */ if ((nread-predict) > 0) { - if(seek_file(fsp,startpos + predict) == -1) { + if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) { DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); ret = 0; seek_fail = True; @@ -2173,7 +2173,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s } if(!seek_fail) - ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client, + ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL, (SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } @@ -2439,8 +2439,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, (int)tcount,(int)nwritten,(int)numtowrite)); } - nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0, - startpos+nwritten); + nwritten = vfs_transfer_file(Client, NULL, -1, fsp, + (SMB_OFF_T)numtowrite,NULL,0, + startpos+nwritten); total_written += nwritten; /* Set up outbuf to return the correct return */ @@ -2453,8 +2454,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SSVAL(outbuf,smb_err,ERRdiskfull); } - if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + if ((lp_syncalways(SNUM(conn)) || write_through) && + lp_strict_sync(SNUM(conn))) + conn->vfs_ops.fsync(fsp->fd_ptr->fd); DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); @@ -2502,7 +2504,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz nwritten = write_file(fsp,data,startpos,numtowrite); if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2551,13 +2553,13 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) { - if((nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos)) >= 0) + if((nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos)) >= 0) /* tpot vfs */ set_filelen_write_cache(fsp, startpos); } else nwritten = write_file(fsp,data,startpos,numtowrite); if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2651,7 +2653,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng fsp->fnum, (int)numtowrite, (int)nwritten)); if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2685,7 +2687,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int umode = SEEK_SET; break; } - if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) { + if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) { /* * Check for the special case where a seek before the start * of the file sets the offset to zero. Added in the CIFS spec, @@ -2697,7 +2699,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int if(umode == SEEK_CUR) { - if((current_pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + if((current_pos = conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); current_pos += startpos; @@ -2706,14 +2708,14 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; - if(sys_fstat( fsp->fd_ptr->fd, &sbuf) == -1) + if(conn->vfs_ops.fstat( fsp->fd_ptr->fd, &sbuf) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); current_pos += sbuf.st_size; } if(current_pos < 0) - res = sys_lseek(fsp->fd_ptr->fd,0,SEEK_SET); + res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_SET); } if(res == -1) @@ -2748,7 +2750,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (!fsp) { file_sync_all(conn); } else { - sync_file(conn,fsp); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); } DEBUG(3,("flush\n")); @@ -3235,7 +3237,8 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) - ret = dos_mkdir(directory,unix_mode(conn,aDIR,directory)); + ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), + unix_mode(conn,aDIR,directory)); if (ret < 0) { @@ -3259,7 +3262,7 @@ Static function used by reply_rmdir to delete an entire directory tree recursively. ****************************************************************************/ -static BOOL recursive_rmdir(char *directory) +static BOOL recursive_rmdir(connection_struct *conn, char *directory) { char *dname = NULL; BOOL ret = False; @@ -3287,7 +3290,7 @@ static BOOL recursive_rmdir(char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(dos_lstat(fullname, &st) != 0) + if(conn->vfs_ops.lstat(fullname, &st) != 0) { ret = True; break; @@ -3295,18 +3298,18 @@ static BOOL recursive_rmdir(char *directory) if(st.st_mode & S_IFDIR) { - if(recursive_rmdir(fullname)!=0) + if(recursive_rmdir(conn, fullname)!=0) { ret = True; break; } - if(dos_rmdir(fullname) != 0) + if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0) { ret = True; break; } } - else if(dos_unlink(fullname) != 0) + else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0) { ret = True; break; @@ -3324,7 +3327,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) { BOOL ok; - ok = (dos_rmdir(directory) == 0); + ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0); if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { /* @@ -3371,24 +3374,24 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(dos_lstat(fullname, &st) != 0) + if(conn->vfs_ops.lstat(dos_to_unix(fullname, False), &st) != 0) break; if(st.st_mode & S_IFDIR) { if(lp_recursive_veto_delete(SNUM(conn))) { - if(recursive_rmdir(fullname) != 0) + if(recursive_rmdir(conn, fullname) != 0) break; } - if(dos_rmdir(fullname) != 0) + if(conn->vfs_ops.rmdir(dos_to_unix(fullname, False)) != 0) break; } - else if(dos_unlink(fullname) != 0) + else if(conn->vfs_ops.unlink(dos_to_unix(fullname, False)) != 0) break; } CloseDir(dirptr); /* Retry the rmdir */ - ok = (dos_rmdir(directory) == 0); + ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0); } else CloseDir(dirptr); @@ -3515,7 +3518,7 @@ static BOOL can_rename(char *fname,connection_struct *conn) if (!CAN_WRITE(conn)) return(False); - if (dos_lstat(fname,&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); return(True); @@ -3645,21 +3648,23 @@ int rename_internals(connection_struct *conn, */ if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !dos_rename(directory,newname)) + !conn->vfs_ops.rename(dos_to_unix(directory,False), + newname)) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !dos_file_exist(newname,NULL) && - !dos_rename(directory,newname)) + !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) && + !conn->vfs_ops.rename(dos_to_unix(directory,False), + newname)) count++; } DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); - if (!count) exists = dos_file_exist(directory,NULL); - if (!count && exists && dos_file_exist(newname,NULL)) { + if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); + if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) { exists = True; error = ERRrename; } @@ -3700,13 +3705,13 @@ int rename_internals(connection_struct *conn, continue; } - if (!replace_if_exists && dos_file_exist(destname,NULL)) { - DEBUG(6,("dos_file_exist %s\n", destname)); + if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) { + DEBUG(6,("file_exist %s\n", destname)); error = 183; continue; } - if (!dos_rename(fname,destname)) + if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3777,7 +3782,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!dos_file_exist(src,&st)) + if (!vfs_file_exist(conn,dos_to_unix(src,False),&st)) return(False); fsp1 = file_new(); @@ -3810,7 +3815,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { + if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", strerror(errno) )); /* @@ -3822,8 +3827,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if (st.st_size) - ret = transfer_file(fsp1->fd_ptr->fd, - fsp2->fd_ptr->fd,st.st_size,NULL,0,0); + ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0); close_file(fsp1,False); /* @@ -3878,7 +3882,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, rc = unix_convert(name,conn,0,&bad_path1,NULL); unix_convert(newname,conn,0,&bad_path2,NULL); - target_is_directory = dos_directory_exist(newname,NULL); + target_is_directory = vfs_directory_exist(conn,dos_to_unix(newname,False),NULL); if ((flags&1) && target_is_directory) { return(ERROR(ERRDOS,ERRbadfile)); @@ -3888,7 +3892,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRDOS,ERRbadpath)); } - if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) { + if ((flags&(1<<5)) && vfs_directory_exist(conn,dos_to_unix(name,False),NULL)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); return(ERROR(ERRSRV,ERRerror)); @@ -3928,7 +3932,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, errno = err; return(UNIXERROR(ERRHRD,ERRgeneral)); } - if (!count) exists = dos_file_exist(directory,NULL); + if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); } else { void *dirptr = NULL; char *dname; @@ -4008,7 +4012,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (strlen(newdir) == 0) { ok = True; } else { - ok = dos_directory_exist(newdir,NULL); + ok = vfs_directory_exist(conn,dos_to_unix(newdir,False),NULL); if (ok) { string_set(&conn->connectpath,newdir); } @@ -4426,7 +4430,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, nwritten = write_file(fsp,data,startpos,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); if(nwritten < (ssize_t)numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -4527,7 +4531,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz nwritten = write_file(fsp,data,startpos,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + conn->vfs_ops.fsync(fsp->fd_ptr->fd); if (nwritten < (ssize_t)numtowrite) { @@ -4634,7 +4638,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_ERROR(fsp); /* Do an fstat on this file */ - if(sys_fstat(fsp->fd_ptr->fd, &sbuf)) + if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(conn,fsp->fsp_name,&sbuf); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0e9675076f..44e347b104 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -707,8 +707,8 @@ static void usage(char *pname) DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(); } - - check_kernel_oplocks(); + + check_kernel_oplocks(); if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ec723e13b9..3abd55de0c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -142,6 +142,11 @@ int find_service(char *service) } } + /* Check for default vfs service? Unsure whether to implement this */ + if (iService < 0) + { + } + /* just possibly it's a default service? */ if (iService < 0) { @@ -351,6 +356,60 @@ connection_struct *make_connection(char *service,char *user,char *password, int string_set(&conn->dirpath,""); string_set(&conn->user,user); + conn->vfs_conn = (struct vfs_connection_struct *) + malloc(sizeof(struct vfs_connection_struct)); + + if (conn->vfs_conn == NULL) { + DEBUG(0, ("No memory to create vfs_connection_struct")); + return NULL; + } + + ZERO_STRUCTP(conn->vfs_conn); + + /* Copy across relevant data from connection struct */ + + conn->vfs_conn->printer = conn->printer; + conn->vfs_conn->ipc = conn->ipc; + conn->vfs_conn->read_only = conn->read_only; + conn->vfs_conn->admin_user = conn->admin_user; + + pstrcpy(conn->vfs_conn->dirpath, conn->dirpath); + pstrcpy(conn->vfs_conn->connectpath, conn->connectpath); + pstrcpy(conn->vfs_conn->origpath, conn->origpath); + + pstrcpy(conn->vfs_conn->service, service); + pstrcpy(conn->vfs_conn->user, conn->user); + + conn->vfs_conn->uid = conn->uid; + conn->vfs_conn->gid = conn->gid; + conn->vfs_conn->ngroups = conn->ngroups; + conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, + conn->ngroups * sizeof(gid_t)); + + /* Initialise VFS function pointers */ + + if (*lp_vfsobj(SNUM(conn))) { + +#ifdef HAVE_LIBDL + + /* Loadable object file */ + + if (!vfs_init_custom(conn)) { + return NULL; + } +#else + DEBUG(0, ("No libdl present - cannot use VFS objects\n")); + conn_free(conn); + return NULL; +#endif + + } else { + + /* Normal share - initialise with disk access functions */ + + vfs_init_default(conn); + } + /* * If force user is true, then store the * given userid and also the primary groupid @@ -560,7 +619,15 @@ connection_struct *make_connection(char *service,char *user,char *password, int set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn))); } - return(conn); + /* Invoke VFS make connection hook */ + + if (conn->vfs_ops.connect) { + if (conn->vfs_ops.connect(conn->vfs_conn, service, user) < 0) { + return NULL; + } + } + + return(conn); } @@ -577,6 +644,29 @@ void close_cnum(connection_struct *conn, uint16 vuid) remote_machine,conn->client_address, lp_servicename(SNUM(conn)))); + if (conn->vfs_ops.disconnect != NULL) { + + /* Call VFS disconnect hook */ + + conn->vfs_ops.disconnect(); + + } + + /* Close dlopen() handle */ + + if (conn->vfs_conn->dl_handle != NULL) { + dlclose(conn->vfs_conn->dl_handle); /* should we check return val? */ + } + + /* Free vfs_connection_struct */ + + if (conn->vfs_conn != NULL) { + if (conn->vfs_conn->groups != NULL) { + free(conn->vfs_conn->groups); + } + free(conn->vfs_conn); + } + yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4b774a4ed1..bd2237253e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -255,7 +255,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -404,7 +404,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (dos_stat(pathreal,&sbuf) != 0) + if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); continue; @@ -1124,7 +1124,7 @@ static int call_trans2qfsinfo(connection_struct *conn, DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(dos_stat(".",&st)!=0) { + if(conn->vfs_ops.stat(".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return (ERROR(ERRSRV,ERRinvdevice)); } @@ -1138,7 +1138,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; - sys_disk_free(".",False,&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); SIVAL(pdata,l1_cSectorUnit,bsize/512); SIVAL(pdata,l1_cUnit,dsize); @@ -1216,7 +1216,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { SMB_BIG_UINT dfree,dsize,bsize; data_len = 24; - sys_disk_free(".",False,&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize); SBIG_UINT(pdata,0,dsize); SBIG_UINT(pdata,8,dfree); SIVAL(pdata,16,bsize/512); @@ -1315,7 +1315,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, */ fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { + if (!check_name(fname,conn) || + (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1335,11 +1336,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); delete_pending = fsp->fd_ptr->delete_on_close; @@ -1353,7 +1354,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname = &fname1[0]; pstrcpy(fname,¶ms[6]); unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) { + if (!check_name(fname,conn) || + (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1593,7 +1595,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, */ fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&st); - if (!check_name(fname,conn) || (!VALID_STAT(st) && dos_stat(fname,&st))) { + if (!check_name(fname,conn) || + (!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1612,7 +1615,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; fd = fsp->fd_ptr->fd; - if (sys_fstat(fd,&st) != 0) { + if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1633,7 +1636,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) { + if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1980,13 +1983,13 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) fname, (double)size )); if (fd == -1) { - fd = dos_open(fname,O_RDWR,0); + fd = conn->vfs_ops.open(dos_to_unix(fname,False),O_RDWR,0); if (fd == -1) return(UNIXERROR(ERRDOS,ERRbadpath)); - set_filelen(fd, size); - close(fd); + set_filelen(fd, size); /* tpot vfs */ + conn->vfs_ops.close(fd); } else { - set_filelen(fd, size); + set_filelen(fd, size); /* tpot vfs */ } if(fsp) @@ -2021,7 +2024,8 @@ static int call_trans2mkdir(connection_struct *conn, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory,conn)) - ret = dos_mkdir(directory,unix_mode(conn,aDIR,directory)); + ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), + unix_mode(conn,aDIR,directory)); if(ret < 0) { -- cgit From ae7696117e81bb469fa71f9bc880f6b5aac0724e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 3 Feb 2000 23:08:24 +0000 Subject: Put back lots of missing calls to dos_to_unix(). Thanks to aono@cc.osaka-kyoiku.ac.jp (Tomoki AONO) (This used to be commit 176c405d2702a4245561ff56c8eac3c754a0dea3) --- source3/smbd/dir.c | 12 ++++++++---- source3/smbd/dosmode.c | 2 +- source3/smbd/filename.c | 4 ++-- source3/smbd/ipc.c | 27 +++++++++++++++++---------- source3/smbd/open.c | 13 +++++++------ source3/smbd/reply.c | 41 ++++++++++++++++++++++------------------- source3/smbd/vfs.c | 4 ++-- 7 files changed, 59 insertions(+), 44 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 32fc523541..58b0061e19 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -670,7 +670,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - DIR *p = conn->vfs_ops.opendir(name); + DIR *p = conn->vfs_ops.opendir(dos_to_unix(name,False)); int used=0; if (!p) return(NULL); @@ -684,10 +684,14 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) while ((n = vfs_readdirname(conn, p))) { - int l = strlen(n)+1; + int l; + pstring zn; + + pstrcpy(zn, unix_to_dos(n,True)); + l = strlen(zn)+1; /* If it's a vetoed file, pretend it doesn't even exist */ - if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; + if (use_veto && conn && IS_VETO_PATH(conn, zn)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); @@ -701,7 +705,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->mallocsize = s; dirp->current = dirp->data; } - pstrcpy(dirp->data+used,n); + pstrcpy(dirp->data+used,zn); used += l; dirp->numentries++; } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 1ae1e7e2cb..278a4ab5e3 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -225,7 +225,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - return(conn->vfs_ops.chmod(fname,unixmode)); + return(conn->vfs_ops.chmod(dos_to_unix(fname,False),unixmode)); } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b1550e5c73..85055f676a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -444,7 +444,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(name,&st) == 0) { + if (conn->vfs_ops.stat(dos_to_unix(name,False),&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -511,7 +511,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - if (conn->vfs_ops.stat(name, &st) == 0) { + if (conn->vfs_ops.stat(dos_to_unix(name,False), &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3e16dba4f5..b5a6e4ba90 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -2055,6 +2055,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha if (isalpha((int)*s)) { pstring name; int l = 0; + while (l<64 && *s) { if (issafe(*s)) name[l++] = *s; s++; @@ -2066,17 +2067,23 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha fsp = file_find_print(); if (fsp) { - connection_struct *fconn = fsp->conn; - unbecome_user(); - - if (!become_user(fconn,vuid) || - !become_service(fconn,True)) - break; + pstring zfrom,zto; + connection_struct *fconn = fsp->conn; + + unbecome_user(); - if (fsp->conn->vfs_ops.rename(fsp->fsp_name,name) == 0) { - string_set(&fsp->fsp_name,name); - } - break; + if (!become_user(fconn,vuid) || + !become_service(fconn,True)) + break; + + pstrcpy(zfrom, dos_to_unix(fsp->fsp_name,False)); + pstrcpy(zto, dos_to_unix(name,False)); + + if (fsp->conn->vfs_ops.rename(zfrom,zto) == 0) { + string_set(&fsp->fsp_name,name); + } + + break; } } desc.errcode=NERR_Success; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1b4179da33..30409707d3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -33,14 +33,14 @@ fd support routines - attempt to do a dos_open static int fd_attempt_open(struct connection_struct *conn, char *fname, int flags, mode_t mode) { - int fd = conn->vfs_ops.open(fname,flags,mode); + int fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(fname,flags,mode); + fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -71,7 +71,7 @@ static int fd_attempt_open(struct connection_struct *conn, char *fname, char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = conn->vfs_ops.open(fname,flags,mode)) == -1) + if ((fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode)) == -1) p[max_len] = tmp; } } @@ -494,7 +494,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (conn->vfs_ops.disk_free(dname,False,&dum1,&dum2,&dum3) < + if (conn->vfs_ops.disk_free(dos_to_unix(dname,False),False,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { int err; if(fd_attempt_close(fsp, &err) == 0) @@ -797,7 +797,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); SMB_STRUCT_STAT sbuf; - BOOL file_existed = vfs_file_exist(conn, dos_to_unix(fname,False), &sbuf); + BOOL file_existed = vfs_file_exist(conn, fname, &sbuf); BOOL share_locked = False; BOOL fcbopen = False; int token = 0; @@ -1192,7 +1192,8 @@ int open_directory(files_struct *fsp,connection_struct *conn, return -1; } - if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), unix_mode(conn,aDIR, fname)) < 0) { + if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), + unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f022301450..3715bd224f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1032,7 +1032,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if(VALID_STAT(st)) ok = S_ISDIR(st.st_mode); else - ok = vfs_directory_exist(conn,dos_to_unix(name,False),NULL); + ok = vfs_directory_exist(conn,name,NULL); } if (!ok) @@ -1167,7 +1167,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, dos_to_unix(fname,False),NULL)) + if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, fname, NULL)) mode |= aDIR; if (check_name(fname,conn)) ok = (file_chmod(conn,fname,mode,NULL) == 0); @@ -1918,7 +1918,7 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False); fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); if (!lp_delete_readonly(SNUM(conn))) { @@ -1989,7 +1989,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++; if (!count) - exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); + exists = vfs_file_exist(conn,directory,NULL); } else { void *dirptr = NULL; char *dname; @@ -2019,7 +2019,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; - if (!conn->vfs_ops.unlink(fname)) count++; + if (!conn->vfs_ops.unlink(dos_to_unix(fname,False))) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); } CloseDir(dirptr); @@ -2708,7 +2708,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; - if(conn->vfs_ops.fstat( fsp->fd_ptr->fd, &sbuf) == -1) + if(conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); current_pos += sbuf.st_size; @@ -3290,7 +3290,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(fullname, &st) != 0) + if(conn->vfs_ops.lstat(dos_to_unix(fullname,False), &st) != 0) { ret = True; break; @@ -3518,7 +3518,7 @@ static BOOL can_rename(char *fname,connection_struct *conn) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); return(True); @@ -3654,7 +3654,7 @@ int rename_internals(connection_struct *conn, } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) && + !vfs_file_exist(conn,newname,NULL) && !conn->vfs_ops.rename(dos_to_unix(directory,False), newname)) count++; @@ -3663,8 +3663,8 @@ int rename_internals(connection_struct *conn, DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", directory,newname)); - if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); - if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) { + if (!count) exists = vfs_file_exist(conn,directory,NULL); + if (!count && exists && vfs_file_exist(conn,newname,NULL)) { exists = True; error = ERRrename; } @@ -3701,17 +3701,20 @@ int rename_internals(connection_struct *conn, pstrcpy(destname,newname); if (!resolve_wildcards(fname,destname)) { - DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname)); + DEBUG(6,("resolve_wildcards %s %s failed\n", + fname, destname)); continue; } - if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) { + if (!replace_if_exists && + vfs_file_exist(conn,destname, NULL)) { DEBUG(6,("file_exist %s\n", destname)); error = 183; continue; } - if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname)) + if (!conn->vfs_ops.rename(dos_to_unix(fname,False), + destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3782,7 +3785,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!vfs_file_exist(conn,dos_to_unix(src,False),&st)) + if (!vfs_file_exist(conn,src,&st)) return(False); fsp1 = file_new(); @@ -3882,7 +3885,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, rc = unix_convert(name,conn,0,&bad_path1,NULL); unix_convert(newname,conn,0,&bad_path2,NULL); - target_is_directory = vfs_directory_exist(conn,dos_to_unix(newname,False),NULL); + target_is_directory = vfs_directory_exist(conn,False,NULL); if ((flags&1) && target_is_directory) { return(ERROR(ERRDOS,ERRbadfile)); @@ -3892,7 +3895,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRDOS,ERRbadpath)); } - if ((flags&(1<<5)) && vfs_directory_exist(conn,dos_to_unix(name,False),NULL)) { + if ((flags&(1<<5)) && vfs_directory_exist(conn,name,NULL)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); return(ERROR(ERRSRV,ERRerror)); @@ -3932,7 +3935,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, errno = err; return(UNIXERROR(ERRHRD,ERRgeneral)); } - if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL); + if (!count) exists = vfs_file_exist(conn,directory,NULL); } else { void *dirptr = NULL; char *dname; @@ -4012,7 +4015,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (strlen(newdir) == 0) { ok = True; } else { - ok = vfs_directory_exist(conn,dos_to_unix(newdir,False),NULL); + ok = vfs_directory_exist(conn,newdir,NULL); if (ok) { string_set(&conn->connectpath,newdir); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2f9f847188..f5c2ec3426 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -220,7 +220,7 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, if (!st) st = &st2; - if (conn->vfs_ops.stat(dname,st) != 0) + if (conn->vfs_ops.stat(dos_to_unix(dname,False),st) != 0) return(False); ret = S_ISDIR(st->st_mode); @@ -238,7 +238,7 @@ BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) SMB_STRUCT_STAT st; if (!sbuf) sbuf = &st; - if (conn->vfs_ops.stat(fname,sbuf) != 0) + if (conn->vfs_ops.stat(dos_to_unix(fname,False),sbuf) != 0) return(False); return(S_ISREG(sbuf->st_mode)); -- cgit From 3b6298b001467ff3d700624cf2bae5b1dc963a4c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 4 Feb 2000 05:18:06 +0000 Subject: Fix some compile warnings. (This used to be commit ccbd936211d4bfc8687cef78405ae58127289d13) --- source3/smbd/filename.c | 2 +- source3/smbd/vfs.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 85055f676a..b0c44d503a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -199,7 +199,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path) * add it. */ - if (hash_elem = hash_lookup(&stat_cache, orig_name)) { + if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { found_scp = (stat_cache_entry *)(hash_elem->value); if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { return; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f5c2ec3426..44f44bd169 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -390,6 +390,10 @@ char *vfs_readdirname(connection_struct *conn, void *p) return(dname); } +/* VFS options not quite working yet */ + +#if 0 + /*************************************************************************** handle the interpretation of the vfs option parameter *************************************************************************/ @@ -448,3 +452,6 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr) return True; } + +#endif + -- cgit From 427a3baa9ccb942b82832f255e09acc87afca166 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Feb 2000 00:41:58 +0000 Subject: Fix some more compile warnings. (This used to be commit 507624dbc0a1a9e1df72a6b8de45038e86a9e5b1) --- source3/smbd/filename.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b0c44d503a..729ef8c809 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -131,6 +131,7 @@ static hash_table stat_cache; case. *****************************************************************************/ +#if 0 /* This function unused?? */ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) { BOOL matched = (memcmp( stat_name, orig_name, len) == 0); @@ -139,6 +140,7 @@ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) return matched; } +#endif /**************************************************************************** Add an entry into the stat cache. @@ -243,7 +245,6 @@ static BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - stat_cache_entry *longest_hit = NULL; char *trans_name; pstring chk_name; int namelen; -- cgit From 59ac32c2556e970ea1fe171e7b76cfee2142fbf0 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Mon, 7 Feb 2000 16:22:16 +0000 Subject: Jeremy can you check lib/util_unistr.c for codepages support ? I added 2 UNICODE <-> ASCII functions which _don't_ honor codepage support. J.F. (This used to be commit b81dc7b7f832cae2e66076398a134fbb6c1f78ca) --- source3/smbd/nttrans.c | 1 + source3/smbd/server.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4b344c3318..d9ad16e7d3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -44,6 +44,7 @@ static char *known_nt_pipes[] = { "\\lsass", "\\lsarpc", "\\winreg", + "\\spoolss", NULL }; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 44e347b104..d1788678a7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -468,6 +468,9 @@ static void init_structs(void ) /* for LSA handles */ init_lsa_policy_hnd(); + /* for SPOOLSS handles */ + init_printer_hnd(); + init_dptrs(); } @@ -707,8 +710,8 @@ static void usage(char *pname) DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(); } - - check_kernel_oplocks(); + + check_kernel_oplocks(); if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); -- cgit From 3cf31a194f5721b67b1255e3f168d4bc87d433fc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Feb 2000 19:36:47 +0000 Subject: Added replacement functions sys_popen and sys_pclose. These are based on the glibc source code and are safer than the traditional popen as they don't use a shell to exec the requested command. Now we have these functions they can be tightened up (environment etc.) as required to make a safe popen. It should now be safe to add the environement variable loading code to loadparm.c Jeremy. (This used to be commit b52e92b09d4ca3b66e534f520468dee27065d048) --- source3/smbd/dfree.c | 10 +++++----- source3/smbd/nttrans.c | 6 ++---- source3/smbd/password.c | 6 +----- 3 files changed, 8 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 7838080461..7866d60277 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -208,7 +208,6 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, * If external disk calculation specified, use it. */ -#ifdef HAVE_POPEN dfree_command = lp_dfree_command(); if (dfree_command && *dfree_command) { pstring line; @@ -216,7 +215,9 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, FILE *pp; slprintf (line, sizeof(pstring) - 1, "%s %s", dfree_command, path); - pp = popen(line, "r"); + DEBUG (3, ("disk_free: Running command %s\n", line)); + + pp = sys_popen(line, "r"); if (pp) { fgets(line, sizeof(pstring), pp); line[sizeof(pstring)-1] = '\0'; @@ -236,7 +237,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, *bsize = (SMB_BIG_UINT)strtoul(p, NULL, 10); else *bsize = 1024; - pclose (pp); + sys_pclose (pp); DEBUG (3, ("Parsed output of dfree, dsize=%u, dfree=%u, bsize=%u\n", (unsigned int)*dsize, (unsigned int)*dfree, (unsigned int)*bsize)); @@ -245,12 +246,11 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, if (!*dfree) *dfree = 1024; } else { - DEBUG (0, ("disk_free: popen() failed for command %s. Error was : %s\n", + DEBUG (0, ("disk_free: sys_popen() failed for command %s. Error was : %s\n", line, strerror(errno) )); fsusage(path, dfree, dsize); } } else -#endif /* HAVE_POPEN */ fsusage(path, dfree, dsize); if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d9ad16e7d3..e94e603661 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -843,15 +843,13 @@ int reply_ntcreate_and_X(connection_struct *conn, } if(fsp->is_directory) { - if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), - &sbuf) != 0) { + if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) - != 0) { + if (conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 44fbdfa8ec..19e7d36443 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -175,14 +175,10 @@ int setup_groups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_gro ngroups = sys_getgroups(0,&grp); if (ngroups <= 0) { - ngroups = 32; + ngroups = groups_max(); } -#ifdef NGROUPS_MAX - if((groups = (gid_t *)malloc(sizeof(gid_t)*NGROUPS_MAX)) == NULL) -#else /* NGROUPS_MAX */ if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) -#endif /* NGROUPS_MAX */ { DEBUG(0,("setup_groups malloc fail !\n")); return -1; -- cgit From 92bf37e21d63c0c9edede1617c85510a16011e7a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 17 Feb 2000 23:22:26 +0000 Subject: Don't assume that the (files_struct *) passed to fd_attempt_close() will be non-NULL. (This used to be commit 02f845e54351ec57ee873a8ed887285552c6ecab) --- source3/smbd/open.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 30409707d3..6352233dbc 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -152,11 +152,18 @@ Decrements the ref_count and returns it. uint16 fd_attempt_close(files_struct *fsp, int *err_ret) { extern struct current_user current_user; - file_fd_struct *fd_ptr = fsp->fd_ptr; - uint16 ret_ref = fd_ptr->ref_count; + file_fd_struct *fd_ptr; + uint16 ret_ref; *err_ret = 0; + if ((fsp == NULL) || (fsp->fd_ptr == NULL)) { + return 0; + } + + fd_ptr = fsp->fd_ptr; + ret_ref = fd_ptr->ref_count; + DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n", fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, fd_ptr->real_open_flags, -- cgit From 8dcac9f8daab74e1a95293fbf64d0c95ce7a0d2a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Feb 2000 03:54:26 +0000 Subject: Fix for reporting file system attributes correctly. Jeremy. (This used to be commit 801ed2389b97f921aa855513696d304c542fda04) --- source3/smbd/trans2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bd2237253e..dff57a41c2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1170,7 +1170,8 @@ static int call_trans2qfsinfo(connection_struct *conn, { int fstype_len; SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0); /* FS ATTRIBUTES */ + FILE_DEVICE_IS_MOUNTED| + (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ #if 0 /* Old code. JRA. */ SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ #endif /* Old code. */ -- cgit From 9db96b7646aa36aa5b4ff309419235fe20bef78a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Feb 2000 02:02:33 +0000 Subject: lib/system.c: Fixed gcc warnings. nmbd/nmbd_processlogon.c: Use "True" and "False" instead of 1 and 0. Others - preparing for multiple pdu write code. Jeremy. (This used to be commit 9f879ec396230deba34fbe5e82d8a65f92137c54) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b5a6e4ba90..5ee70e7d94 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3225,7 +3225,7 @@ static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p, return False; } - send_trans_reply(outbuf, NULL, 0, rdata, data_len, (int)prs_offset(&p->rdata) > data_len); + send_trans_reply(outbuf, NULL, 0, rdata, data_len, (int)prs_offset(&p->out_data.rdata) > data_len); free(rdata); return True; -- cgit From f429162313c199b2b1466f25830c3241aa81f2b4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Feb 2000 18:46:45 +0000 Subject: Fixes for strange Win2K attempts to auto-inherit ACLs. Jeremy. (This used to be commit 41e37c51816ec048952ada1513c62f2689589001) --- source3/smbd/nttrans.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e94e603661..b65deefaef 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2062,6 +2062,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint uint32 owner_rid; uint32 grp_rid; SEC_ACL *dacl = psd->dacl; + BOOL all_aces_are_inherit_only = (is_directory ? True : False); int i; *pmode = 0; @@ -2069,7 +2070,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint *pgrp = (gid_t)-1; if(security_info_sent == 0) { - DEBUG(0,("unpack_unix_permissions: no security info sent !\n")); + DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); return False; } @@ -2080,7 +2081,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint memset(&owner_sid, '\0', sizeof(owner_sid)); memset(&grp_sid, '\0', sizeof(grp_sid)); - DEBUG(5,("unpack_unix_permissions: validating owner_sid.\n")); + DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n")); /* * Don't immediately fail if the owner sid cannot be validated. @@ -2088,7 +2089,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint */ if(!validate_unix_sid( &owner_sid, &owner_rid, psd->owner_sid)) - DEBUG(3,("unpack_unix_permissions: unable to validate owner sid.\n")); + DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); else if(security_info_sent & OWNER_SECURITY_INFORMATION) *puser = pdb_user_rid_to_uid(owner_rid); @@ -2098,7 +2099,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint */ if(!validate_unix_sid( &grp_sid, &grp_rid, psd->grp_sid)) - DEBUG(3,("unpack_unix_permissions: unable to validate group sid.\n")); + DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); else if(security_info_sent & GROUP_SECURITY_INFORMATION) *pgrp = pdb_user_rid_to_gid(grp_rid); @@ -2122,7 +2123,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - DEBUG(3,("unpack_unix_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); + DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); return False; } @@ -2132,15 +2133,22 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint if(is_directory) { if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - DEBUG(3,("unpack_unix_permissions: ignoring inherit only ACE.\n")); + DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n")); continue; } + /* + * At least one of the ACE entries wasn't inherit only. + * Flag this so we know the returned mode is valid. + */ + + all_aces_are_inherit_only = False; + psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); } if(psa->flags != 0) { - DEBUG(1,("unpack_unix_permissions: unable to set ACE flags (%x).\n", + DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", (unsigned int)psa->flags)); return False; } @@ -2191,11 +2199,22 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); } else { - DEBUG(0,("unpack_unix_permissions: unknown SID used in ACL.\n")); + DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n")); return False; } } + if (is_directory && all_aces_are_inherit_only) { + /* + * Windows 2000 is doing one of these weird 'inherit acl' + * traverses to conserve NTFS ACL resources. Just pretend + * there was no DACL sent. JRA. + */ + + DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); + free_sec_acl(&psd->dacl); + } + return True; } -- cgit From 72606557082f7bdd87729dd3871b57833a6ff060 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Mar 2000 02:42:06 +0000 Subject: Fix for Win2k unicode bug where doing SMB_NT_TRANSACT_CREATE it uses unicode filenames whilst *not* bothering to set the unicode bit. Nice :-(. Jeremy. (This used to be commit ccddf4d92e4b1af6076692c21247a838498201fc) --- source3/smbd/nttrans.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b65deefaef..4dd80f1579 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -254,9 +254,9 @@ static void my_wcstombs(char *dst, uint16 *src, size_t len) static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) { - if(data_len - fname_len > 1) { + if((data_len - fname_len > 1) || (inbuf[data_offset] == '\0')) { /* - * NT 5.0 Beta 2 has kindly sent us a UNICODE string + * NT 5.0 Beta 2 or Windows 2000 final release (!) has kindly sent us a UNICODE string * without bothering to set the unicode bit. How kind. * * Firstly - ensure that the data offset is aligned @@ -638,6 +638,11 @@ int reply_ntcreate_and_X(connection_struct *conn, dir_name_len++; } + /* + * This next calculation can refuse a correct filename if we're dealing + * with the Win2k unicode bug, but that would be rare. JRA. + */ + if(fname_len + dir_name_len >= sizeof(pstring)) return(ERROR(ERRSRV,ERRfilespecs)); @@ -928,13 +933,13 @@ int reply_ntcreate_and_X(connection_struct *conn, ****************************************************************************/ static int call_nt_transact_create(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, char **ppparams, - char **ppdata) + char *inbuf, char *outbuf, int length, + int bufsize, char **ppsetup, char **ppparams, + char **ppdata) { pstring fname; char *params = *ppparams; + int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); uint32 flags = IVAL(params,0); uint32 desired_access = IVAL(params,8); uint32 file_attributes = IVAL(params,20); @@ -989,8 +994,7 @@ static int call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - StrnCpy(fname,params+53,fname_len); - fname[fname_len] = '\0'; + get_filename(&fname[0], params, 53, total_parameter_count - 53 - fname_len, fname_len); if( fname[0] == ':') { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); @@ -1016,15 +1020,18 @@ static int call_nt_transact_create(connection_struct *conn, dir_name_len++; } + /* + * This next calculation can refuse a correct filename if we're dealing + * with the Win2k unicode bug, but that would be rare. JRA. + */ + if(fname_len + dir_name_len >= sizeof(pstring)) return(ERROR(ERRSRV,ERRfilespecs)); - StrnCpy(&fname[dir_name_len], params+53, fname_len); - fname[dir_name_len+fname_len] = '\0'; + get_filename(&fname[dir_name_len], params, 53, total_parameter_count - 53 - fname_len, fname_len); } else { - StrnCpy(fname,params+53,fname_len); - fname[fname_len] = '\0'; + get_filename(&fname[0], params, 53, total_parameter_count - 53 - fname_len, fname_len); } /* If it's an IPC, use the pipe handler. */ @@ -1267,6 +1274,8 @@ static int call_nt_transact_create(connection_struct *conn, SOFF_T(p,0,file_len); } + DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); + /* Send the required number of replies */ send_nt_replies(inbuf, outbuf, bufsize, 0, params, 69, *ppdata, 0); -- cgit From 99be80bd805df7137490c5b372a4f5b79c31460a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Mar 2000 23:37:33 +0000 Subject: Off by one error in detecting Win2k unicode bug. Jeremy. (This used to be commit 4971e8b44ac38806f6fc0b3bd22d3ccafd1f5d4e) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4dd80f1579..a4d59004e8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -254,7 +254,7 @@ static void my_wcstombs(char *dst, uint16 *src, size_t len) static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) { - if((data_len - fname_len > 1) || (inbuf[data_offset] == '\0')) { + if((data_len - fname_len >= 1) || (inbuf[data_offset] == '\0')) { /* * NT 5.0 Beta 2 or Windows 2000 final release (!) has kindly sent us a UNICODE string * without bothering to set the unicode bit. How kind. -- cgit From 952799d9afe028d822181831715b85521c89a7ef Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Wed, 8 Mar 2000 22:14:30 +0000 Subject: dded Microsoft Dfs services. * added a new msdfs/ directory under source/ * added msdfs sources under this directory. * modified configure setup to add a --with-msdfs configure time option Modified Files: Makefile.in acconfig.h configure configure.in include/config.h.in include/includes.h include/proto.h include/smb.h include/smb_macros.h param/loadparm.c smbd/negprot.c smbd/nttrans.c smbd/process.c smbd/reply.c smbd/server.c smbd/trans2.c Added Files: include/msdfs.h msdfs/README msdfs/msdfs.c msdfs/msdfs_tdb.c msdfs/parse_dfs_map.c ---------------------------------------------------------------------- (This used to be commit 4684b4a188b54493dbe7f0de2909a8d3c5c3ebf9) --- source3/smbd/negprot.c | 5 +++++ source3/smbd/nttrans.c | 5 ++++- source3/smbd/process.c | 6 +++-- source3/smbd/reply.c | 35 +++++++++++++++++++++++++++++- source3/smbd/server.c | 14 ++++++++++-- source3/smbd/trans2.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 115 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 3cabc6b229..47a82c6e31 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -199,6 +199,11 @@ static int reply_nt1(char *outbuf) capabilities |= CAP_RAW_MODE; } +#ifdef MS_DFS + if(lp_host_msdfs()) + capabilities |= CAP_DFS; +#endif + if (lp_security() >= SEC_USER) secword |= 1; if (doencrypt) secword |= 2; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a4d59004e8..c57c9c56cc 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -692,7 +692,8 @@ int reply_ntcreate_and_X(connection_struct *conn, * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ - + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if((smb_open_mode = map_share_mode(&stat_open_only, fname, desired_access, share_access, file_attributes)) == -1) @@ -1059,6 +1060,8 @@ static int call_nt_transact_create(connection_struct *conn, */ set_posix_case_semantics(file_attributes); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,NULL); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7d6e171d05..403990a79d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -385,7 +385,7 @@ struct smb_message_struct /* LANMAN2.0 PROTOCOL FOLLOWS */ {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK }, + {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC }, {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, /* NT PROTOCOL FOLLOWS */ @@ -704,7 +704,9 @@ void construct_reply_common(char *inbuf,char *outbuf) CVAL(outbuf,smb_reh) = 0; SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set means a reply */ - SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS); /* say we support long filenames */ + SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS); + /* say we support long filenames */ + SSVAL(outbuf,smb_err,SMB_SUCCESS); SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3715bd224f..6b1d28abe0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -352,7 +352,10 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* what does setting this bit do? It is set by NT4 and may affect the ability to autorun mounted cdroms */ SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS); + + init_dfsroot(conn, inbuf, outbuf); } + DEBUG(3,("tconX service=%s user=%s\n", service, user)); @@ -1024,6 +1027,9 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT st; pstrcpy(name,smb_buf(inbuf) + 1); + + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + unix_convert(name,conn,0,&bad_path,&st); mode = SVAL(inbuf,smb_vwv0); @@ -1085,6 +1091,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(fname,smb_buf(inbuf) + 1); + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + + /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf)); + */ /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (! (*fname)) @@ -1530,6 +1540,9 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); @@ -1632,6 +1645,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + unix_convert(fname,conn,0,&bad_path,NULL); fsp = file_new(); @@ -1766,6 +1782,9 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + unix_convert(fname,conn,0,&bad_path,NULL); if (createmode & aVOLID) @@ -1851,6 +1870,9 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + unix_convert(fname,conn,0,&bad_path,NULL); unixmode = unix_mode(conn,createmode,fname); @@ -1955,6 +1977,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(name,smb_buf(inbuf) + 1); + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + DEBUG(3,("reply_unlink : %s\n",name)); rc = unix_convert(name,conn,0,&bad_path,NULL); @@ -3419,6 +3443,9 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); + + RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) + unix_convert(directory,conn, NULL,&bad_path,NULL); if (check_name(directory,conn)) @@ -3749,7 +3776,10 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in pstrcpy(name,smb_buf(inbuf) + 1); pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); - + + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); outsize = rename_internals(conn, inbuf, outbuf, name, newname, False); @@ -3882,6 +3912,9 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRSRV,ERRinvdevice)); } + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + rc = unix_convert(name,conn,0,&bad_path1,NULL); unix_convert(newname,conn,0,&bad_path2,NULL); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d1788678a7..1c4a4e3752 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -282,7 +282,8 @@ max can be %d\n", BOOL reload_services(BOOL test) { BOOL ret; - + int i=0; + if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); @@ -298,9 +299,15 @@ BOOL reload_services(BOOL test) return(True); lp_killunused(conn_snum_used); - + ret = lp_load(servicesf,False,False,True); + /* load the dfs maps of all the services having + a dfs_map parameter + we don't want to do this in lp_load because we want just the smbd + server to load up the dfs maps into msdfds.tdb. not nmbd, swat etc*/ + load_dfsmaps(); + load_printers(); /* perhaps the config filename is now set */ @@ -431,6 +438,9 @@ void exit_server(char *reason) } locking_end(); +#ifdef MS_DFS + msdfs_end(); +#endif DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); exit(0); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dff57a41c2..21fa9b5cc5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -101,8 +101,8 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, * the length of the data we send over the wire, as the alignment offsets * are sent here. Fix from Marc_Jacobsen@hp.com. */ - total_sent_thistime = MIN(total_sent_thistime, useable_space + - alignment_offset + data_alignment_offset); + total_sent_thistime = MIN(total_sent_thistime, useable_space+ + alignment_offset + data_alignment_offset); set_message(outbuf, 10, total_sent_thistime, True); @@ -120,7 +120,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, SSVAL(outbuf,smb_prcnt, params_sent_thistime); if(params_sent_thistime == 0) { - SSVAL(outbuf,smb_proff,0); + SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); SSVAL(outbuf,smb_prdisp,0); } else @@ -693,6 +693,8 @@ static int call_trans2findfirst(connection_struct *conn, pstrcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */ + RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); + DEBUG(5,("path=%s\n",directory)); unix_convert(directory,conn,0,&bad_path,NULL); @@ -1354,6 +1356,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname = &fname1[0]; pstrcpy(fname,¶ms[6]); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { @@ -2120,6 +2125,49 @@ static int call_trans2findnotifynext(connection_struct *conn, return(-1); } +/**************************************************************************** + reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele +****************************************************************************/ +static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, + char* outbuf, int length, int bufsize, + char** pparams, char** ppdata) +{ + char *params = *pparams; + enum remote_arch_types ra_type = get_remote_arch(); + BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)); + pstring pathname; + int reply_size = 0; + char* dfs_referral = NULL; + int max_referral_level = SVAL(params,0); + + DEBUG(10,("call_trans2getdfsreferral\n")); +#ifdef MS_DFS + if(!lp_host_msdfs()) + return(ERROR(ERRDOS,ERRbadfunc)); + + /* if pathname is in UNICODE, convert to DOS */ + /* NT always sends in UNICODE, may not set UNICODE flag */ + if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS)) + { + unistr_to_dos(pathname, ¶ms[2]); + DEBUG(10,("UNICODE referral for %s\n",pathname)); + } + else + pstrcpy(pathname,¶ms[2]); + + if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) + return(ERROR(ERRDOS,ERRbadfile)); + + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | + FLAGS2_DFS_PATHNAMES); + send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); +#else + DEBUG(0,("Unexpected DFS referral request!\n")); + return(ERROR(ERRDOS,ERRbadfunc)); +#endif +} + + /**************************************************************************** reply to a SMBfindclose (stop trans2 directory search) ****************************************************************************/ @@ -2353,6 +2401,11 @@ int reply_trans2(connection_struct *conn, outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize, ¶ms, &data); break; + + case TRANSACT2_GET_DFS_REFERRAL: + outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, + bufsize, ¶ms, &data); + break; default: /* Error in request */ DEBUG(2,("Unknown request %d in trans2 call\n", tran_call)); -- cgit From 18465ec2cd94dc0f4da0a2984d395c18a23291f1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Mar 2000 20:00:23 +0000 Subject: Fixups for Win2K security descriptors from the 2.0.x branch. Jeremy. (This used to be commit d22d4482b5e170f352dbfde5b37fc4d4e0eb0a49) --- source3/smbd/nttrans.c | 86 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c57c9c56cc..e07e5e41df 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -254,7 +254,12 @@ static void my_wcstombs(char *dst, uint16 *src, size_t len) static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) { - if((data_len - fname_len >= 1) || (inbuf[data_offset] == '\0')) { + /* + * We need various heuristics here to detect a unicode string... JRA. + */ + DEBUG(10,("data_offset = %d, data_len = %d, fname_len = %d\n", data_offset, data_len, fname_len )); + + if((data_len - fname_len > 1) || (inbuf[data_offset] == '\0')) { /* * NT 5.0 Beta 2 or Windows 2000 final release (!) has kindly sent us a UNICODE string * without bothering to set the unicode bit. How kind. @@ -1769,6 +1774,20 @@ static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w return sa; } +/**************************************************************************** + Function to create owner and group SIDs from a SMB_STRUCT_STAT. +****************************************************************************/ + +static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) +{ + extern DOM_SID global_sam_sid; + + sid_copy(powner_sid, &global_sam_sid); + sid_copy(pgroup_sid, &global_sam_sid); + sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); + sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); +} + /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns True. @@ -1776,7 +1795,6 @@ static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { - extern DOM_SID global_sam_sid; extern DOM_SID global_sid_World; SMB_STRUCT_STAT sbuf; SEC_ACE ace_list[6]; @@ -1813,10 +1831,7 @@ static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * Get the owner, group and world SIDs. */ - sid_copy(&owner_sid, &global_sam_sid); - sid_copy(&group_sid, &global_sam_sid); - sid_append_rid(&owner_sid, pdb_uid_to_user_rid(sbuf.st_uid)); - sid_append_rid(&group_sid, pdb_gid_to_group_rid(sbuf.st_gid)); + create_file_sids(&sbuf, &owner_sid, &group_sid); /* * Create the generic 3 element UNIX acl. @@ -2065,12 +2080,14 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a owner, group and set of UNIX permissions. ****************************************************************************/ -static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint32 security_info_sent, - SEC_DESC *psd, BOOL is_directory) +static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode, + uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) { extern DOM_SID global_sid_World; DOM_SID owner_sid; DOM_SID grp_sid; + DOM_SID file_owner_sid; + DOM_SID file_grp_sid; uint32 owner_rid; uint32 grp_rid; SEC_ACL *dacl = psd->dacl; @@ -2086,6 +2103,15 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint return False; } + /* + * Windows 2000 sends the owner and group SIDs as the logged in + * user, not the connected user. But it still sends the file + * owner SIDs on an ACL set. So we need to check for the file + * owner and group SIDs as well as the owner SIDs. JRA. + */ + + create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); + /* * Validate the owner and group SID's. */ @@ -2155,10 +2181,16 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint */ all_aces_are_inherit_only = False; - - psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); } + /* + * Windows 2000 sets these flags even on *file* ACE's. This is wrong + * but we can ignore them for now. Revisit this when we go to POSIX + * ACLs on directories. + */ + + psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); + if(psa->flags != 0) { DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", (unsigned int)psa->flags)); @@ -2180,7 +2212,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint sid_copy(&ace_sid, &psa->sid); - if(sid_equal(&ace_sid, &owner_sid)) { + if(sid_equal(&ace_sid, &file_owner_sid)) { /* * Map the desired permissions into owner perms. */ @@ -2190,7 +2222,7 @@ static BOOL unpack_nt_permissions(uid_t *puser, gid_t *pgrp, mode_t *pmode, uint else *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); - } else if( sid_equal(&ace_sid, &grp_sid)) { + } else if( sid_equal(&ace_sid, &file_grp_sid)) { /* * Map the desired permissions into group perms. */ @@ -2294,26 +2326,13 @@ security descriptor.\n")); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - /* - * Unpack the user/group/world id's and permissions. - */ - - if(!unpack_nt_permissions( &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) { - free_sec_desc(&psd); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (psd->dacl != NULL) - got_dacl = True; - - free_sec_desc(&psd); - /* * Get the current state of the file. */ if(fsp->is_directory) { if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + free_sec_desc(&psd); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { @@ -2326,10 +2345,25 @@ security descriptor.\n")); ret = conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf); if(ret != 0) { + free_sec_desc(&psd); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } + /* + * Unpack the user/group/world id's and permissions. + */ + + if(!unpack_nt_permissions( &sbuf, &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) { + free_sec_desc(&psd); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if (psd->dacl != NULL) + got_dacl = True; + + free_sec_desc(&psd); + /* * Do we need to chown ? */ -- cgit From 6bb92a6d38db41a11e80c4369623d137763f0f52 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Mar 2000 21:45:16 +0000 Subject: Big update moving the multi-pdu support from 2.0.x into HEAD for JF and the printer functions. Also tidied up some header includes and got the order right so you can now do a : make proto make clean make Jeremy. (This used to be commit 833cd9fba92e4ad5297b235d108dd2be8c17079b) --- source3/smbd/ipc.c | 31 +++++-------------------------- source3/smbd/pipes.c | 47 +++++++++++++++++++++++++---------------------- 2 files changed, 30 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 5ee70e7d94..d42c2727d4 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3201,20 +3201,11 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p, - char *redir_data, int redir_len) +static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) { - char *rdata; + char *rdata = malloc(p->max_trans_reply); int data_len; - if (redir_data != NULL) - { - send_trans_reply(outbuf, NULL, 0, redir_data, redir_len, - redir_len > p->max_trans_reply); - return True; - } - - rdata = malloc(p->max_trans_reply); if(rdata == NULL) { DEBUG(0,("api_rpc_trans_reply: malloc fail.\n")); return False; @@ -3340,23 +3331,11 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, switch (subcommand) { case 0x26: - { - char *rdata = NULL; - int rlen = mdrcnt; - - if (p->m) - { - reply = readwrite_pipe(p, data, tdscnt, &rdata, &rlen); - } - else - { - /* dce/rpc command */ - reply = rpc_command(p, data, tdscnt); - } + /* dce/rpc command */ + reply = write_to_pipe(p, data, tdscnt); if (reply) - reply = api_rpc_trans_reply(outbuf, p, rdata, rlen); + reply = api_rpc_trans_reply(outbuf, p); break; - } case 0x53: /* Wait Named Pipe Handle state */ reply = api_WNPHS(outbuf, p, params, tpscnt); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 1a9ac1d7a4..65a71e1c00 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -129,16 +129,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) if (numtowrite == 0) nwritten = 0; else - { - if (p->m != NULL) - { - nwritten = write_pipe(p, data, numtowrite); - } - else - { - nwritten = write_to_pipe(p, data, numtowrite); - } - } + nwritten = write_to_pipe(p, data, numtowrite); if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) return (UNIXERROR(ERRDOS,ERRnoaccess)); @@ -154,17 +145,19 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) } /**************************************************************************** - reply to a write and X + Reply to a write and X. - This code is basically stolen from reply_write_and_X with some - wrinkles to handle pipes. + This code is basically stolen from reply_write_and_X with some + wrinkles to handle pipes. ****************************************************************************/ + int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); size_t numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); + BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) != 0); char *data; if (!p) @@ -174,14 +167,31 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (numtowrite == 0) nwritten = 0; - else + else { + if(pipe_start_message_raw) { + /* + * For the start of a message in named pipe byte mode, + * the first two bytes are a length-of-pdu field. Ignore + * them (we don't trust the client. JRA. + */ + if(numtowrite < 2) { + DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n", + (unsigned int)numtowrite )); + return (UNIXERROR(ERRDOS,ERRnoaccess)); + } + + data += 2; + numtowrite -= 2; + } nwritten = write_to_pipe(p, data, numtowrite); + } if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) return (UNIXERROR(ERRDOS,ERRnoaccess)); set_message(outbuf,6,0,True); + nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); SSVAL(outbuf,smb_vwv2,nwritten); DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", @@ -216,14 +226,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,12,0,True); data = smb_buf(outbuf); - if (p->m != NULL) - { - nread = read_pipe(p, data, smb_maxcnt); - } - else - { - nread = read_from_pipe(p, data, smb_maxcnt); - } + nread = read_from_pipe(p, data, smb_maxcnt); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); -- cgit From 115d98e639b94fdd0773bfb9516af14d857c59d2 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Fri, 10 Mar 2000 17:06:12 +0000 Subject: removed unused variable J.F. (This used to be commit e2557ae5515ce30d0341ef7785cc4380266d4c94) --- source3/smbd/server.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1c4a4e3752..d0b909609f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -282,7 +282,6 @@ max can be %d\n", BOOL reload_services(BOOL test) { BOOL ret; - int i=0; if (lp_loaded()) { pstring fname; -- cgit From e0ebb76a7453c07c16e8f736233226a774ab58e8 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Fri, 10 Mar 2000 17:12:24 +0000 Subject: getprinter level 0: was to short, found most of the fields, undocumented, undecoded, nothing in MSDN, but now it works :-) cleanup of error codes. fixed some dfs declarations function. J.F. (This used to be commit 87da4404aba29a2ebd999886e4c06958c96d3e05) --- source3/smbd/ipc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index d42c2727d4..fc05811ccf 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -48,7 +48,6 @@ extern fstring global_myworkgroup; #define NERR_BufTooSmall (NERR_BASE+23) #define NERR_JobNotFound (NERR_BASE+51) #define NERR_DestNotFound (NERR_BASE+52) -#define ERROR_INVALID_LEVEL 124 #define ACCESS_READ 0x01 #define ACCESS_WRITE 0x02 -- cgit From 83ee9372fc18eaef6d00fbc7c1fb68747e2303bb Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 10 Mar 2000 18:10:10 +0000 Subject: you know, when you do a cvs commit, you _really_ expect it to actually work. this explains why j-f wasn't happy. (This used to be commit c51e38214a5323d0aa9b6dcd948a76ddc29f5305) --- source3/smbd/password.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 19e7d36443..bdb0385a48 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -122,18 +122,12 @@ void invalidate_vuid(uint16 vuid) vuser->uid = (uid_t)-1; vuser->gid = (gid_t)-1; - vuser->n_sids = 0; - /* same number of igroups as groups */ vuser->n_groups = 0; if (vuser->groups) free((char *)vuser->groups); - if (vuser->sids) - free((char *)vuser->sids); - - vuser->sids = NULL; vuser->groups = NULL; } @@ -255,9 +249,6 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, fstrcpy(vuser->name,unix_name); fstrcpy(vuser->requested_name,requested_name); - vuser->n_sids = 0; - vuser->sids = NULL; - vuser->n_groups = 0; vuser->groups = NULL; -- cgit From 5e22394654eba2ed5d01e81b165a044a59dd65ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Mar 2000 19:50:03 +0000 Subject: Fixups for compiles with gcc flags -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual Partially implemented rpc daemon redirect (needs more work). Jeremy. (This used to be commit a462191698fa589ceac4afd14c652adf699eccad) --- source3/smbd/trans2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 21fa9b5cc5..3135079514 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2132,6 +2132,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize, char** pparams, char** ppdata) { +#ifdef MS_DFS char *params = *pparams; enum remote_arch_types ra_type = get_remote_arch(); BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)); @@ -2139,6 +2140,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, int reply_size = 0; char* dfs_referral = NULL; int max_referral_level = SVAL(params,0); +#endif DEBUG(10,("call_trans2getdfsreferral\n")); #ifdef MS_DFS -- cgit From 0307b23a31e23649493c4bcc21134d275c0d6293 Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Fri, 10 Mar 2000 22:53:36 +0000 Subject: Cleaning up the warnings from configure.developer. Found that Jeremy had already made some of the changes. (This used to be commit ca02d9f8219265f80fe11236c8c146db1dbb1ae2) --- source3/smbd/server.c | 4 +++- source3/smbd/trans2.c | 9 +++------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d0b909609f..401c236374 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -301,11 +301,13 @@ BOOL reload_services(BOOL test) ret = lp_load(servicesf,False,False,True); +#ifdef MS_DFS /* load the dfs maps of all the services having a dfs_map parameter we don't want to do this in lp_load because we want just the smbd - server to load up the dfs maps into msdfds.tdb. not nmbd, swat etc*/ + server to load up the dfs maps into msdfs.tdb. not nmbd, swat etc*/ load_dfsmaps(); +#endif load_printers(); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3135079514..e3dbc91e50 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2138,12 +2138,11 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)); pstring pathname; int reply_size = 0; - char* dfs_referral = NULL; int max_referral_level = SVAL(params,0); #endif DEBUG(10,("call_trans2getdfsreferral\n")); -#ifdef MS_DFS + if(!lp_host_msdfs()) return(ERROR(ERRDOS,ERRbadfunc)); @@ -2163,10 +2162,8 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); -#else - DEBUG(0,("Unexpected DFS referral request!\n")); - return(ERROR(ERRDOS,ERRbadfunc)); -#endif + + return(-1); } -- cgit From 741dfefd565dbcd9ec8a861ebe3a7e6c0e80eac1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 11 Mar 2000 01:28:57 +0000 Subject: Fix stupid logic bug in detecting start-of-pdu in writeX on pipe. Found by JF. Jeremy. (This used to be commit 8315583694249278c57948406c1f48e2128f2b08) --- source3/smbd/pipes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 65a71e1c00..5d5c6a653a 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -157,7 +157,8 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) size_t numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); - BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) != 0); + BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == + (PIPE_START_MESSAGE|PIPE_RAW_MODE)); char *data; if (!p) -- cgit From 530a01c2cbf787e4f3ff116aba3e8b392c8871fc Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Mon, 13 Mar 2000 11:05:59 +0000 Subject: moved #endif to end of function to compile when dfs is disabled. J.F. (This used to be commit b534fb03b1ef39e5362c29a05cca53782cd157f7) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e3dbc91e50..ebcf6b077b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2139,7 +2139,6 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, pstring pathname; int reply_size = 0; int max_referral_level = SVAL(params,0); -#endif DEBUG(10,("call_trans2getdfsreferral\n")); @@ -2162,6 +2161,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); +#endif return(-1); } -- cgit From 3e07f63b7c13049a49f3c1bf8a436b147390ecae Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Mon, 13 Mar 2000 17:38:13 +0000 Subject: Cleaned up call_trans2getdfsreferral for when MS_DFS is not defined. (This used to be commit 2b99318341a3f3a3ac138fe96ad271726bf1552c) --- source3/smbd/quotas.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/trans2.c | 2 +- 2 files changed, 146 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index badc0562bc..329f261f27 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -30,6 +30,17 @@ extern int DEBUGLEVEL; +#if defined(VXFS_QUOTA) + +/* + * In addition to their native filesystems, some systems have Veritas VxFS. + * Declare here, define at end: reduces likely "include" interaction problems. + * David Lee + */ +BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); + +#endif /* VXFS_QUOTA */ + #ifdef LINUX #include @@ -251,7 +262,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #if defined(SUNOS5) struct quotctl command; int file; - struct mnttab mnt; + static struct mnttab mnt; static pstring name; #else /* SunOS4 */ struct mntent *mnt; @@ -338,7 +349,18 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U if (ret < 0) { DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); - return(False); + +#if defined(SUNOS5) && defined(VXFS_QUOTA) + /* If normal quotactl() fails, try vxfs private calls */ + set_effective_uid(euser_id); + DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); + if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { + ret = disk_quotas_vxfs(name, path, bsize, dfree, dsize); + return(ret); + } +#else + return(False); +#endif } @@ -659,3 +681,124 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U } #endif + +#if defined(VXFS_QUOTA) + +/**************************************************************************** +Try to get the disk space from Veritas disk quotas. + David Lee August 1999. + +Background assumptions: + Potentially under many Operating Systems. Initially Solaris 2. + + My guess is that Veritas is largely, though not entirely, + independent of OS. So I have separated it out. + + There may be some details. For example, OS-specific "include" files. + + It is understood that HPUX 10 somehow gets Veritas quotas without + any special effort; if so, this routine need not be compiled in. + Dirk De Wachter + +Warning: + It is understood that Veritas do not publicly support this ioctl interface. + Rather their preference would be for the user (us) to call the native + OS and then for the OS itself to call through to the VxFS filesystem. + Presumably HPUX 10, see above, does this. + +Hints for porting: + Add your OS to "IFLIST" below. + Get it to compile successfully: + Almost certainly "include"s require attention: see SUNOS5. + In the main code above, arrange for it to be called: see SUNOS5. + Test! + +****************************************************************************/ + +/* "IFLIST" + * This "if" is a list of ports: + * if defined(OS1) || defined(OS2) || ... + */ +#if defined(SUNOS5) + +#if defined(SUNOS5) +#include +#endif +#include +#include +#include +#include +#include + +BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + uid_t user_id, euser_id; + int ret; + struct vx_dqblk D; + struct vx_quotctl quotabuf; + struct vx_genioctl genbuf; + pstring qfname; + int file; + + /* + * "name" may or may not include a trailing "/quotas". + * Arranging consistency of calling here in "quotas.c" may not be easy and + * it might be easier to examine and adjust it here. + * Fortunately, VxFS seems not to mind at present. + */ + pstrcpy(qfname, name) ; + /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */ + + euser_id = geteuid(); + set_effective_uid(0); + + DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname)); + if((file=sys_open(qfname, O_RDONLY,0))<0) { + set_effective_uid(euser_id); + return(False); + } + genbuf.ioc_cmd = VX_QUOTACTL; + genbuf.ioc_up = (void *) "abuf; + + quotabuf.cmd = VX_GETQUOTA; + quotabuf.uid = euser_id; + quotabuf.addr = (caddr_t) &D; + ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf); + close(file); + + set_effective_uid(euser_id); + + if (ret < 0) { + DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) )); + return(False); + } + + /* Use softlimit to determine disk space. A user exceeding the quota is told + * that there's no space left. Writes might actually work for a bit if the + * hardlimit is set higher than softlimit. Effectively the disk becomes + * made of rubber latex and begins to expand to accommodate the user :-) + */ + DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n", + path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit, + D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit)); + + if (D.dqb_bsoftlimit==0) + return(False); + *bsize = DEV_BSIZE; + *dsize = D.dqb_bsoftlimit; + + if (D.dqb_curblocks > D.dqb_bsoftlimit) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + + DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", + path,(double)*bsize,(double)*dfree,(double)*dsize)); + + return(True); +} + +#endif /* SUNOS5 || ... */ + +#endif /* VXFS_QUOTA */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ebcf6b077b..3283cbacce 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2132,7 +2132,6 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize, char** pparams, char** ppdata) { -#ifdef MS_DFS char *params = *pparams; enum remote_arch_types ra_type = get_remote_arch(); BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)); @@ -2140,6 +2139,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, int reply_size = 0; int max_referral_level = SVAL(params,0); + DEBUG(10,("call_trans2getdfsreferral\n")); if(!lp_host_msdfs()) -- cgit From 7d2a8cd4c621e6a13476b994f872661390cb6787 Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Mon, 13 Mar 2000 18:18:36 +0000 Subject: Cleaning up call_trans2getdfsreferral. Instead of a #ifdef MS_DFS in call_trans2getdfsreferral()... , now using a generic call leading to some #define problems.. hopefully I've corrected the last of them. (This used to be commit b5a489fbb808cc7c8ff2338344ef2dae8e351e44) --- source3/smbd/trans2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3283cbacce..308ba2dacd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2161,7 +2161,6 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); -#endif return(-1); } -- cgit From 01d88573ea1b3809a3e264989e1e04cd397528f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Mar 2000 20:05:18 +0000 Subject: include/smb.h: smbd/negprot.c: smbd/reply.c: Fixes to recognise Win2k. param/loadparm.c: Put debug timestamp parameter back to correct default. smbd/nttrans.c: Fix to detect Win2k unicode bug with transact create. Jeremy. (This used to be commit bb100352ab2f98fab3978008d269920e03efcf6d) --- source3/smbd/negprot.c | 5 ++- source3/smbd/nttrans.c | 103 ++++++++++++++++++++++++++++++++++++++++--------- source3/smbd/reply.c | 10 ++--- 3 files changed, 93 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 47a82c6e31..adef4a57f3 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -379,7 +379,10 @@ int reply_negprot(connection_struct *conn, set_remote_arch(RA_WIN95); break; case ARCH_WINNT: - set_remote_arch(RA_WINNT); + if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE) + set_remote_arch(RA_WIN2K); + else + set_remote_arch(RA_WINNT); break; case ARCH_WIN2K: set_remote_arch(RA_WIN2K); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e07e5e41df..05d9c82c38 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -252,16 +252,23 @@ static void my_wcstombs(char *dst, uint16 *src, size_t len) dst[i] = (char)SVAL(src,i*2); } +/**************************************************************************** + (Hopefully) temporary call to fix bugs in NT5.0beta2. This OS sends unicode + strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!! +****************************************************************************/ + static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) { /* * We need various heuristics here to detect a unicode string... JRA. */ - DEBUG(10,("data_offset = %d, data_len = %d, fname_len = %d\n", data_offset, data_len, fname_len )); - if((data_len - fname_len > 1) || (inbuf[data_offset] == '\0')) { + DEBUG(10,("get_filename: data_offset = %d, data_len = %d, fname_len = %d\n", + data_offset, data_len, fname_len )); + + if(data_len - fname_len > 1) { /* - * NT 5.0 Beta 2 or Windows 2000 final release (!) has kindly sent us a UNICODE string + * NT 5.0 Beta 2 has kindly sent us a UNICODE string * without bothering to set the unicode bit. How kind. * * Firstly - ensure that the data offset is aligned @@ -277,6 +284,41 @@ static void get_filename( char *fname, char *inbuf, int data_offset, int data_le fname[fname_len] = '\0'; } +/**************************************************************************** + Fix bugs in Win2000 final release. In trans calls this OS sends unicode + strings AND DOESN'T SET THE UNICODE BIT !!!!!!! +****************************************************************************/ + +static void get_filename_transact( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) +{ + /* + * We need various heuristics here to detect a unicode string... JRA. + */ + + DEBUG(10,("get_filename_transact: data_offset = %d, data_len = %d, fname_len = %d\n", + data_offset, data_len, fname_len )); + + /* + * Win2K sends a unicode filename plus one extra alingment byte. + * WinNT4.x send an ascii string with multiple garbage bytes on + * the end here. + */ + + if((data_len - fname_len == 1) || (inbuf[data_offset] == '\0')) { + /* + * Ensure that the data offset is aligned + * on a 2 byte boundary - add one if not. + */ + fname_len = fname_len/2; + if(data_offset & 1) + data_offset++; + my_wcstombs( fname, (uint16 *)(inbuf+data_offset), fname_len); + } else { + StrnCpy(fname,inbuf+data_offset,fname_len); + } + fname[fname_len] = '\0'; +} + /**************************************************************************** Save case statics. ****************************************************************************/ @@ -946,18 +988,6 @@ static int call_nt_transact_create(connection_struct *conn, pstring fname; char *params = *ppparams; int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); - uint32 flags = IVAL(params,0); - uint32 desired_access = IVAL(params,8); - uint32 file_attributes = IVAL(params,20); - uint32 share_access = IVAL(params,24); - uint32 create_disposition = IVAL(params,28); - uint32 create_options = IVAL(params,32); - uint32 fname_len = MIN(((uint32)IVAL(params,44)), - ((uint32)sizeof(fname)-1)); - uint16 root_dir_fid = (uint16)IVAL(params,4); - int smb_ofun; - int smb_open_mode; - int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; @@ -971,6 +1001,38 @@ static int call_nt_transact_create(connection_struct *conn, files_struct *fsp = NULL; char *p = NULL; BOOL stat_open_only = False; + uint32 flags; + uint32 desired_access; + uint32 file_attributes; + uint32 share_access; + uint32 create_disposition; + uint32 create_options; + uint32 fname_len; + uint16 root_dir_fid; + int smb_ofun; + int smb_open_mode; + int smb_attr; + + DEBUG(5,("call_nt_transact_create\n")); + + /* + * Ensure minimum number of parameters sent. + */ + + if(total_parameter_count < 54) { + DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); + return(ERROR(ERRDOS,ERRbadaccess)); + } + + flags = IVAL(params,0); + desired_access = IVAL(params,8); + file_attributes = IVAL(params,20); + share_access = IVAL(params,24); + create_disposition = IVAL(params,28); + create_options = IVAL(params,32); + fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1)); + root_dir_fid = (uint16)IVAL(params,4); + smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); /* * We need to construct the open_and_X ofun value from the @@ -978,7 +1040,7 @@ static int call_nt_transact_create(connection_struct *conn, */ if((smb_ofun = map_create_disposition( create_disposition )) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); + return(ERROR(ERRDOS,ERRbadmem)); /* * Get the file name. @@ -1000,7 +1062,8 @@ static int call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - get_filename(&fname[0], params, 53, total_parameter_count - 53 - fname_len, fname_len); + get_filename_transact(&fname[0], params, 53, + total_parameter_count - 53 - fname_len, fname_len); if( fname[0] == ':') { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); @@ -1034,10 +1097,12 @@ static int call_nt_transact_create(connection_struct *conn, if(fname_len + dir_name_len >= sizeof(pstring)) return(ERROR(ERRSRV,ERRfilespecs)); - get_filename(&fname[dir_name_len], params, 53, total_parameter_count - 53 - fname_len, fname_len); + get_filename_transact(&fname[dir_name_len], params, 53, + total_parameter_count - 53 - fname_len, fname_len); } else { - get_filename(&fname[0], params, 53, total_parameter_count - 53 - fname_len, fname_len); + get_filename_transact(&fname[0], params, 53, + total_parameter_count - 53 - fname_len, fname_len); } /* If it's an IPC, use the pipe handler. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6b1d28abe0..4b0400fe6c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -636,7 +636,8 @@ static int bad_password_error(char *inbuf,char *outbuf) { enum remote_arch_types ra_type = get_remote_arch(); - if(ra_type == RA_WINNT && (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { + if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) && + (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0,0xc0000000|NT_STATUS_LOGON_FAILURE)); } @@ -702,11 +703,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int circumstances. */ - if(ra_type == RA_WINNT || ra_type == RA_WIN95) { - if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32)) - set_remote_arch( RA_WINNT); - else + if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) { + if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) { set_remote_arch( RA_WIN95); + } } if (passlen1 != 24 && passlen2 != 24) -- cgit From e601c0259e9e6a48e04ce3e0ff793cb564a89716 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Mar 2000 20:55:37 +0000 Subject: Fixes to add "paranoid" option to popen. Checks some basic things. Jeremy (This used to be commit 3b8cbb10de322fd7a1063fb5b681790b10d24ab0) --- source3/smbd/dfree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 7866d60277..0a892bad05 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -217,7 +217,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, slprintf (line, sizeof(pstring) - 1, "%s %s", dfree_command, path); DEBUG (3, ("disk_free: Running command %s\n", line)); - pp = sys_popen(line, "r"); + pp = sys_popen(line, "r", False); if (pp) { fgets(line, sizeof(pstring), pp); line[sizeof(pstring)-1] = '\0'; -- cgit From 2864ac574b7d2c7422b632068ace7a02dcc61cee Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 21 Mar 2000 21:08:07 +0000 Subject: indent update to make t easier to see setuid mods in TNG. some code from these modules i had to leave out (nothing to do withj setuid) (This used to be commit 96717211edcc389daa4494907251ffb79ffa56d9) --- source3/smbd/chgpasswd.c | 1013 +++++++++++++++++++++++++--------------------- 1 file changed, 558 insertions(+), 455 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 406f4604b1..4131ae61ca 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -55,140 +55,168 @@ extern int DEBUGLEVEL; static int findpty(char **slave) { - int master; - static fstring line; - void *dirp; - char *dpname; - + int master; + static fstring line; + void *dirp; + char *dpname; + #if defined(HAVE_GRANTPT) - /* Try to open /dev/ptmx. If that fails, fall through to old method. */ - if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0) { - grantpt(master); - unlockpt(master); - *slave = (char *)ptsname(master); - if (*slave == NULL) { - DEBUG(0,("findpty: Unable to create master/slave pty pair.\n")); - /* Stop fd leak on error. */ - close(master); - return -1; - } else { - DEBUG(10, ("findpty: Allocated slave pty %s\n", *slave)); - return (master); - } - } + /* Try to open /dev/ptmx. If that fails, fall through to old method. */ + if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0) + { + grantpt(master); + unlockpt(master); + *slave = (char *)ptsname(master); + if (*slave == NULL) + { + DEBUG(0, + ("findpty: Unable to create master/slave pty pair.\n")); + /* Stop fd leak on error. */ + close(master); + return -1; + } + else + { + DEBUG(10, + ("findpty: Allocated slave pty %s\n", *slave)); + return (master); + } + } #endif /* HAVE_GRANTPT */ - fstrcpy( line, "/dev/ptyXX" ); - - dirp = OpenDir(NULL, "/dev", False); - if (!dirp) - return(-1); - while ((dpname = ReadDirName(dirp)) != NULL) { - if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { - DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); - line[8] = dpname[3]; - line[9] = dpname[4]; - if ((master = sys_open(line, O_RDWR, 0)) >= 0) { - DEBUG(3,("pty: opened %s\n", line ) ); - line[5] = 't'; - *slave = line; - CloseDir(dirp); - return (master); - } - } - } - CloseDir(dirp); - return (-1); + fstrcpy(line, "/dev/ptyXX"); + + dirp = OpenDir(NULL, "/dev", False); + if (!dirp) + return (-1); + while ((dpname = ReadDirName(dirp)) != NULL) + { + if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) + { + DEBUG(3, + ("pty: try to open %s, line was %s\n", dpname, + line)); + line[8] = dpname[3]; + line[9] = dpname[4]; + if ((master = sys_open(line, O_RDWR, 0)) >= 0) + { + DEBUG(3, ("pty: opened %s\n", line)); + line[5] = 't'; + *slave = line; + CloseDir(dirp); + return (master); + } + } + } + CloseDir(dirp); + return (-1); } -static int dochild(int master,char *slavedev, char *name, char *passwordprogram, BOOL as_root) +static int dochild(int master, char *slavedev, char *name, + char *passwordprogram, BOOL as_root) { - int slave; - struct termios stermios; - struct passwd *pass = Get_Pwnam(name,True); - gid_t gid; - uid_t uid; - - if (pass == NULL) { - DEBUG(0,("dochild: user name %s doesn't exist in the UNIX password database.\n", - name)); - return False; - } - - gid = pass->pw_gid; - uid = pass->pw_uid; - - gain_root_privilege(); - - /* Start new session - gets rid of controlling terminal. */ - if (setsid() < 0) { - DEBUG(3,("Weirdness, couldn't let go of controlling terminal\n")); - return(False); - } - - /* Open slave pty and acquire as new controlling terminal. */ - if ((slave = sys_open(slavedev, O_RDWR, 0)) < 0) { - DEBUG(3,("More weirdness, could not open %s\n", - slavedev)); - return(False); - } + int slave; + struct termios stermios; + struct passwd *pass = Get_Pwnam(name, True); + gid_t gid; + uid_t uid; + + if (pass == NULL) + { + DEBUG(0, + ("dochild: user name %s doesn't exist in the UNIX password database.\n", + name)); + return False; + } + + gid = pass->pw_gid; + uid = pass->pw_uid; + + gain_root_privilege(); + + /* Start new session - gets rid of controlling terminal. */ + if (setsid() < 0) + { + DEBUG(3, + ("Weirdness, couldn't let go of controlling terminal\n")); + return (False); + } + + /* Open slave pty and acquire as new controlling terminal. */ + if ((slave = sys_open(slavedev, O_RDWR, 0)) < 0) + { + DEBUG(3, ("More weirdness, could not open %s\n", slavedev)); + return (False); + } #ifdef I_PUSH - ioctl(slave, I_PUSH, "ptem"); - ioctl(slave, I_PUSH, "ldterm"); + ioctl(slave, I_PUSH, "ptem"); + ioctl(slave, I_PUSH, "ldterm"); #elif defined(TIOCSCTTY) - if (ioctl(slave,TIOCSCTTY,0) <0) { - DEBUG(3,("Error in ioctl call for slave pty\n")); - /* return(False); */ - } -#endif - - /* Close master. */ - close(master); - - /* Make slave stdin/out/err of child. */ - - if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) { - DEBUG(3,("Could not re-direct stdin\n")); - return(False); - } - if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) { - DEBUG(3,("Could not re-direct stdout\n")); - return(False); - } - if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) { - DEBUG(3,("Could not re-direct stderr\n")); - return(False); - } - if (slave > 2) close(slave); - - /* Set proper terminal attributes - no echo, canonical input processing, - no map NL to CR/NL on output. */ - - if (tcgetattr(0, &stermios) < 0) { - DEBUG(3,("could not read default terminal attributes on pty\n")); - return(False); - } - stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); - stermios.c_lflag |= ICANON; - stermios.c_oflag &= ~(ONLCR); - if (tcsetattr(0, TCSANOW, &stermios) < 0) { - DEBUG(3,("could not set attributes of pty\n")); - return(False); - } - - /* make us completely into the right uid */ - if (!as_root) { - become_user_permanently(uid, gid); - } - - DEBUG(10, ("Invoking '%s' as password change program.\n", passwordprogram)); - - /* execl() password-change application */ - if (execl("/bin/sh","sh","-c",passwordprogram,NULL) < 0) { - DEBUG(3,("Bad status returned from %s\n",passwordprogram)); - return(False); - } - return(True); + if (ioctl(slave, TIOCSCTTY, 0) < 0) + { + DEBUG(3, ("Error in ioctl call for slave pty\n")); + /* return(False); */ + } +#endif + + /* Close master. */ + close(master); + + /* Make slave stdin/out/err of child. */ + + if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) + { + DEBUG(3, ("Could not re-direct stdin\n")); + return (False); + } + if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) + { + DEBUG(3, ("Could not re-direct stdout\n")); + return (False); + } + if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) + { + DEBUG(3, ("Could not re-direct stderr\n")); + return (False); + } + if (slave > 2) + close(slave); + + /* Set proper terminal attributes - no echo, canonical input processing, + no map NL to CR/NL on output. */ + + if (tcgetattr(0, &stermios) < 0) + { + DEBUG(3, + ("could not read default terminal attributes on pty\n")); + return (False); + } + stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); + stermios.c_lflag |= ICANON; + stermios.c_oflag &= ~(ONLCR); + if (tcsetattr(0, TCSANOW, &stermios) < 0) + { + DEBUG(3, ("could not set attributes of pty\n")); + return (False); + } + + /* make us completely into the right uid */ + if (!as_root) + { + become_user_permanently(uid, gid); + } + + DEBUG(10, + ("Invoking '%s' as password change program.\n", + passwordprogram)); + + /* execl() password-change application */ + if (execl("/bin/sh", "sh", "-c", passwordprogram, NULL) < 0) + { + DEBUG(3, ("Bad status returned from %s\n", passwordprogram)); + return (False); + } + return (True); } static int expect(int master, char *issue, char *expected) @@ -215,7 +243,8 @@ static int expect(int master, char *issue, char *expected) buffer[nread] = 0; while ((len = read_with_timeout(master, buffer + nread, 1, - sizeof(buffer) - nread - 1, timeout)) > 0) + sizeof(buffer) - nread - 1, + timeout)) > 0) { nread += len; buffer[nread] = 0; @@ -243,10 +272,10 @@ static int expect(int master, char *issue, char *expected) static void pwd_sub(char *buf) { - all_string_sub(buf,"\\n","\n",0); - all_string_sub(buf,"\\r","\r",0); - all_string_sub(buf,"\\s"," ",0); - all_string_sub(buf,"\\t","\t",0); + all_string_sub(buf, "\\n", "\n", 0); + all_string_sub(buf, "\\r", "\r", 0); + all_string_sub(buf, "\\s", " ", 0); + all_string_sub(buf, "\\t", "\t", 0); } static int talktochild(int master, char *seq) @@ -263,7 +292,7 @@ static int talktochild(int master, char *seq) if (!expect(master, issue, expected)) { - DEBUG(3,("Response %d incorrect\n", count)); + DEBUG(3, ("Response %d incorrect\n", count)); return False; } @@ -276,187 +305,230 @@ static int talktochild(int master, char *seq) return (count > 0); } -static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root) +static BOOL chat_with_program(char *passwordprogram, char *name, + char *chatsequence, BOOL as_root) { - char *slavedev; - int master; - pid_t pid, wpid; - int wstat; - BOOL chstat = False; - - /* allocate a pseudo-terminal device */ - if ((master = findpty (&slavedev)) < 0) { - DEBUG(3,("Cannot Allocate pty for password change: %s\n",name)); - return(False); - } - - /* - * We need to temporarily stop CatchChild from eating - * SIGCLD signals as it also eats the exit status code. JRA. - */ - - CatchChildLeaveStatus(); - - if ((pid = fork()) < 0) { - DEBUG(3,("Cannot fork() child for password change: %s\n",name)); - close(master); - CatchChild(); - return(False); - } - - /* we now have a pty */ - if (pid > 0){ /* This is the parent process */ - if ((chstat = talktochild(master, chatsequence)) == False) { - DEBUG(3,("Child failed to change password: %s\n",name)); - kill(pid, SIGKILL); /* be sure to end this process */ - } - - while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { - if(errno == EINTR) { - errno = 0; - continue; - } - break; - } - - if (wpid < 0) { - DEBUG(3,("The process is no longer waiting!\n\n")); - close(master); - CatchChild(); - return(False); - } - - /* - * Go back to ignoring children. - */ - CatchChild(); - - close(master); - - if (pid != wpid) { - DEBUG(3,("We were waiting for the wrong process ID\n")); - return(False); - } - if (WIFEXITED(wstat) == 0) { - DEBUG(3,("The process exited while we were waiting\n")); - return(False); - } - if (WEXITSTATUS(wstat) != 0) { - DEBUG(3,("The status of the process exiting was %d\n", wstat)); - return(False); - } - - } else { - /* CHILD */ - - /* - * Lose any oplock capabilities. - */ - set_process_capability(KERNEL_OPLOCK_CAPABILITY, False); - set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); - - /* make sure it doesn't freeze */ - alarm(20); - - if (as_root) - become_root(False); - DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid())); - chstat = dochild(master, slavedev, name, passwordprogram, as_root); + char *slavedev; + int master; + pid_t pid, wpid; + int wstat; + BOOL chstat = False; + + /* allocate a pseudo-terminal device */ + if ((master = findpty(&slavedev)) < 0) + { + DEBUG(3, + ("Cannot Allocate pty for password change: %s\n", + name)); + return (False); + } /* - * The child should never return from dochild() .... + * We need to temporarily stop CatchChild from eating + * SIGCLD signals as it also eats the exit status code. JRA. */ - DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat )); - exit(1); - } + CatchChildLeaveStatus(); + + if ((pid = fork()) < 0) + { + DEBUG(3, + ("Cannot fork() child for password change: %s\n", + name)); + close(master); + CatchChild(); + return (False); + } + + /* we now have a pty */ + if (pid > 0) + { /* This is the parent process */ + if ((chstat = talktochild(master, chatsequence)) == False) + { + DEBUG(3, + ("Child failed to change password: %s\n", + name)); + kill(pid, SIGKILL); /* be sure to end this process */ + } + + while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) + { + if (errno == EINTR) + { + errno = 0; + continue; + } + break; + } + + if (wpid < 0) + { + DEBUG(3, ("The process is no longer waiting!\n\n")); + close(master); + CatchChild(); + return (False); + } + + /* + * Go back to ignoring children. + */ + CatchChild(); + + close(master); + + if (pid != wpid) + { + DEBUG(3, + ("We were waiting for the wrong process ID\n")); + return (False); + } + if (WIFEXITED(wstat) == 0) + { + DEBUG(3, + ("The process exited while we were waiting\n")); + return (False); + } + if (WEXITSTATUS(wstat) != 0) + { + DEBUG(3, + ("The status of the process exiting was %d\n", + wstat)); + return (False); + } + + } + else + { + /* CHILD */ - if (chstat) - DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); - return (chstat); + /* + * Lose any oplock capabilities. + */ + set_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, + False); + + /* make sure it doesn't freeze */ + alarm(20); + + if (as_root) + become_root(False); + DEBUG(3, + ("Dochild for user %s (uid=%d,gid=%d)\n", name, + (int)getuid(), (int)getgid())); + chstat = + dochild(master, slavedev, name, passwordprogram, + as_root); + + /* + * The child should never return from dochild() .... + */ + + DEBUG(0, + ("chat_with_program: Error: dochild() returned %d\n", + chstat)); + exit(1); + } + + if (chstat) + DEBUG(3, + ("Password change %ssuccessful for user %s\n", + (chstat ? "" : "un"), name)); + return (chstat); } -BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) +BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) { - pstring passwordprogram; - pstring chatsequence; - size_t i; - size_t len; + pstring passwordprogram; + pstring chatsequence; + size_t i; + size_t len; - strlower(name); - DEBUG(3,("Password change for user: %s\n",name)); + strlower(name); + DEBUG(3, ("Password change for user: %s\n", name)); #if DEBUG_PASSWORD - DEBUG(100,("Passwords: old=%s new=%s\n",oldpass,newpass)); + DEBUG(100, ("Passwords: old=%s new=%s\n", oldpass, newpass)); #endif - /* Take the passed information and test it for minimum criteria */ - /* Minimum password length */ - if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ - { - DEBUG(0,("Password Change: user %s, New password is shorter than minimum password length = %d\n", - name, lp_min_passwd_length())); - return (False); /* inform the user */ - } - - /* Password is same as old password */ - if (strcmp(oldpass,newpass) == 0) /* don't allow same password */ - { - DEBUG(2,("Password Change: %s, New password is same as old\n",name)); /* log the attempt */ - return (False); /* inform the user */ - } - - pstrcpy(passwordprogram,lp_passwd_program()); - pstrcpy(chatsequence,lp_passwd_chat()); - - if (!*chatsequence) { - DEBUG(2,("Null chat sequence - no password changing\n")); - return(False); - } - - if (!*passwordprogram) { - DEBUG(2,("Null password program - no password changing\n")); - return(False); - } - - /* - * Check the old and new passwords don't contain any control - * characters. - */ + /* Take the passed information and test it for minimum criteria */ + /* Minimum password length */ + if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ + { + DEBUG(0, + ("Password Change: user %s, New password is shorter than minimum password length = %d\n", + name, lp_min_passwd_length())); + return (False); /* inform the user */ + } - len = strlen(oldpass); - for(i = 0; i < len; i++) { - if (iscntrl((int)oldpass[i])) { - DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n")); - return False; - } - } - - len = strlen(newpass); - for(i = 0; i < len; i++) { - if (iscntrl((int)newpass[i])) { - DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n")); - return False; - } - } - - pstring_sub(passwordprogram,"%u",name); - /* note that we do NOT substitute the %o and %n in the password program - as this would open up a security hole where the user could use - a new password containing shell escape characters */ - - pstring_sub(chatsequence,"%u",name); - all_string_sub(chatsequence,"%o",oldpass,sizeof(pstring)); - all_string_sub(chatsequence,"%n",newpass,sizeof(pstring)); - return(chat_with_program(passwordprogram,name,chatsequence, as_root)); + /* Password is same as old password */ + if (strcmp(oldpass, newpass) == 0) /* don't allow same password */ + { + DEBUG(2, + ("Password Change: %s, New password is same as old\n", name)); /* log the attempt */ + return (False); /* inform the user */ + } + + pstrcpy(passwordprogram, lp_passwd_program()); + pstrcpy(chatsequence, lp_passwd_chat()); + + if (!*chatsequence) + { + DEBUG(2, ("Null chat sequence - no password changing\n")); + return (False); + } + + if (!*passwordprogram) + { + DEBUG(2, ("Null password program - no password changing\n")); + return (False); + } + + /* + * Check the old and new passwords don't contain any control + * characters. + */ + + len = strlen(oldpass); + for (i = 0; i < len; i++) + { + if (iscntrl((int)oldpass[i])) + { + DEBUG(0, + ("chat_with_program: oldpass contains control characters (disallowed).\n")); + return False; + } + } + + len = strlen(newpass); + for (i = 0; i < len; i++) + { + if (iscntrl((int)newpass[i])) + { + DEBUG(0, + ("chat_with_program: newpass contains control characters (disallowed).\n")); + return False; + } + } + + pstring_sub(passwordprogram, "%u", name); + /* note that we do NOT substitute the %o and %n in the password program + as this would open up a security hole where the user could use + a new password containing shell escape characters */ + + pstring_sub(chatsequence, "%u", name); + all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring)); + all_string_sub(chatsequence, "%n", newpass, sizeof(pstring)); + return (chat_with_program + (passwordprogram, name, chatsequence, as_root)); } #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) +BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) { - DEBUG(0,("Password changing not compiled in (user=%s)\n",name)); - return(False); + DEBUG(0, ("Password changing not compiled in (user=%s)\n", name)); + return (False); } #endif /* ALLOW_CHANGE_PASSWORD */ @@ -464,58 +536,64 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) Code to check the lanman hashed password. ************************************************************/ -BOOL check_lanman_password(char *user, uchar *pass1, - uchar *pass2, struct smb_passwd **psmbpw) +BOOL check_lanman_password(char *user, uchar * pass1, + uchar * pass2, struct smb_passwd **psmbpw) { - static uchar null_pw[16]; - uchar unenc_new_pw[16]; - uchar unenc_old_pw[16]; - struct smb_passwd *smbpw; - - *psmbpw = NULL; - - become_root(0); - smbpw = getsmbpwnam(user); - unbecome_root(0); - - if (smbpw == NULL) - { - DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n")); - return False; - } - - if (smbpw->acct_ctrl & ACB_DISABLED) - { - DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); - return False; - } - - if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) - { - uchar no_pw[14]; - memset(no_pw, '\0', 14); - E_P16(no_pw, null_pw); - smbpw->smb_passwd = null_pw; - } else if (smbpw->smb_passwd == NULL) { - DEBUG(0,("check_lanman_password: no lanman password !\n")); - return False; - } - - /* Get the new lanman hash. */ - D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); - - /* Use this to get the old lanman hash. */ - D_P16(unenc_new_pw, pass1, unenc_old_pw); - - /* Check that the two old passwords match. */ - if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) - { - DEBUG(0,("check_lanman_password: old password doesn't match.\n")); - return False; - } - - *psmbpw = smbpw; - return True; + static uchar null_pw[16]; + uchar unenc_new_pw[16]; + uchar unenc_old_pw[16]; + struct smb_passwd *smbpw; + + *psmbpw = NULL; + + become_root(0); + smbpw = getsmbpwnam(user); + unbecome_root(0); + + if (smbpw == NULL) + { + DEBUG(0, + ("check_lanman_password: getsmbpwnam returned NULL\n")); + return False; + } + + if (smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0, + ("check_lanman_password: account %s disabled.\n", + user)); + return False; + } + + if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + { + uchar no_pw[14]; + memset(no_pw, '\0', 14); + E_P16(no_pw, null_pw); + smbpw->smb_passwd = null_pw; + } + else if (smbpw->smb_passwd == NULL) + { + DEBUG(0, ("check_lanman_password: no lanman password !\n")); + return False; + } + + /* Get the new lanman hash. */ + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + + /* Use this to get the old lanman hash. */ + D_P16(unenc_new_pw, pass1, unenc_old_pw); + + /* Check that the two old passwords match. */ + if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + { + DEBUG(0, + ("check_lanman_password: old password doesn't match.\n")); + return False; + } + + *psmbpw = smbpw; + return True; } /*********************************************************** @@ -524,61 +602,67 @@ BOOL check_lanman_password(char *user, uchar *pass1, no longer be valid. ************************************************************/ -BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2) +BOOL change_lanman_password(struct smb_passwd *smbpw, uchar * pass1, + uchar * pass2) { - static uchar null_pw[16]; - uchar unenc_new_pw[16]; - BOOL ret; - - if (smbpw == NULL) - { - DEBUG(0,("change_lanman_password: no smb password entry.\n")); - return False; - } - - if (smbpw->acct_ctrl & ACB_DISABLED) - { - DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); - return False; - } - - if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) - { - uchar no_pw[14]; - memset(no_pw, '\0', 14); - E_P16(no_pw, null_pw); - smbpw->smb_passwd = null_pw; - } else if (smbpw->smb_passwd == NULL) { - DEBUG(0,("change_lanman_password: no lanman password !\n")); - return False; - } - - /* Get the new lanman hash. */ - D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); - - smbpw->smb_passwd = unenc_new_pw; - smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ - - /* Now write it into the file. */ - become_root(0); - ret = mod_smbpwd_entry(smbpw,False); - unbecome_root(0); - - return ret; + static uchar null_pw[16]; + uchar unenc_new_pw[16]; + BOOL ret; + + if (smbpw == NULL) + { + DEBUG(0, + ("change_lanman_password: no smb password entry.\n")); + return False; + } + + if (smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0, + ("change_lanman_password: account %s disabled.\n", + smbpw->smb_name)); + return False; + } + + if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + { + uchar no_pw[14]; + memset(no_pw, '\0', 14); + E_P16(no_pw, null_pw); + smbpw->smb_passwd = null_pw; + } + else if (smbpw->smb_passwd == NULL) + { + DEBUG(0, ("change_lanman_password: no lanman password !\n")); + return False; + } + + /* Get the new lanman hash. */ + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + + smbpw->smb_passwd = unenc_new_pw; + smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ + + /* Now write it into the file. */ + become_root(0); + ret = mod_smbpwd_entry(smbpw, False); + unbecome_root(0); + + return ret; } /*********************************************************** Code to check and change the OEM hashed password. ************************************************************/ BOOL pass_oem_change(char *user, - uchar *lmdata, uchar *lmhash, - uchar *ntdata, uchar *nthash) + uchar * lmdata, uchar * lmhash, + uchar * ntdata, uchar * nthash) { fstring new_passwd; struct smb_passwd *sampw; - BOOL ret = check_oem_password( user, lmdata, lmhash, ntdata, nthash, - &sampw, - new_passwd, sizeof(new_passwd)); + BOOL ret = check_oem_password(user, lmdata, lmhash, ntdata, nthash, + &sampw, + new_passwd, sizeof(new_passwd)); /* * At this point we have the new case-sensitive plaintext @@ -589,14 +673,14 @@ BOOL pass_oem_change(char *user, * available. JRA. */ - if ( ret && lp_unix_password_sync()) + if (ret && lp_unix_password_sync()) { - ret = chgpasswd(user,"", new_passwd, True); + ret = chgpasswd(user, "", new_passwd, True); } if (ret) { - ret = change_oem_password( sampw, new_passwd, False ); + ret = change_oem_password(sampw, new_passwd, False); } memset(new_passwd, 0, sizeof(new_passwd)); @@ -612,10 +696,10 @@ BOOL pass_oem_change(char *user, ************************************************************/ BOOL check_oem_password(char *user, - uchar *lmdata, uchar *lmhash, - uchar *ntdata, uchar *nthash, - struct smb_passwd **psmbpw, char *new_passwd, - int new_passwd_size) + uchar * lmdata, uchar * lmhash, + uchar * ntdata, uchar * nthash, + struct smb_passwd **psmbpw, char *new_passwd, + int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; @@ -635,13 +719,15 @@ BOOL check_oem_password(char *user, if (smbpw == NULL) { - DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); + DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); return False; } if (smbpw->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + DEBUG(0, + ("check_lanman_password: account %s disabled.\n", + user)); return False; } @@ -657,9 +743,10 @@ BOOL check_oem_password(char *user, { smbpw->smb_passwd = null_pw; } - else + else { - DEBUG(0,("check_oem_password: no lanman password !\n")); + DEBUG(0, + ("check_oem_password: no lanman password !\n")); return False; } } @@ -670,9 +757,10 @@ BOOL check_oem_password(char *user, { smbpw->smb_nt_passwd = null_pw; } - else + else { - DEBUG(0,("check_oem_password: no ntlm password !\n")); + DEBUG(0, + ("check_oem_password: no ntlm password !\n")); return False; } } @@ -680,7 +768,7 @@ BOOL check_oem_password(char *user, /* * Call the hash function to get the new password. */ - SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); + SamOEMhash((uchar *) lmdata, (uchar *) smbpw->smb_passwd, True); /* * The length of the new password is in the last 4 bytes of @@ -690,7 +778,9 @@ BOOL check_oem_password(char *user, new_pw_len = IVAL(lmdata, 512); if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); + DEBUG(0, + ("check_oem_password: incorrect password length (%d).\n", + new_pw_len)); return False; } @@ -702,12 +792,14 @@ BOOL check_oem_password(char *user, int uni_pw_len = new_pw_len; char *pw; new_pw_len /= 2; - pw = dos_unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); - memcpy(new_passwd, pw, new_pw_len+1); + pw = + dos_unistrn2((uint16 *)(&lmdata[512 - uni_pw_len]), + new_pw_len); + memcpy(new_passwd, pw, new_pw_len + 1); } else { - memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); + memcpy(new_passwd, &lmdata[512 - new_pw_len], new_pw_len); new_passwd[new_pw_len] = '\0'; } @@ -724,16 +816,18 @@ BOOL check_oem_password(char *user, * Now use new_p16 as the key to see if the old * password matches. */ - D_P16(new_p16 , lmhash, unenc_old_pw); + D_P16(new_p16, lmhash, unenc_old_pw); if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { - DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + DEBUG(0, + ("check_oem_password: old lm password doesn't match.\n")); return False; } #ifdef DEBUG_PASSWORD - DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); + DEBUG(100, + ("check_oem_password: password %s ok\n", new_passwd)); #endif return True; } @@ -747,17 +841,19 @@ BOOL check_oem_password(char *user, if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { - DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + DEBUG(0, + ("check_oem_password: old lm password doesn't match.\n")); return False; } if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16)) { - DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); + DEBUG(0, + ("check_oem_password: old nt password doesn't match.\n")); return False; } #ifdef DEBUG_PASSWORD - DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); + DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); #endif return True; } @@ -769,66 +865,73 @@ BOOL check_oem_password(char *user, override = True, override XXXXXXXXXX'd password ************************************************************/ -BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) +BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, + BOOL override) { - int ret; - uchar new_nt_p16[16]; - uchar new_p16[16]; + int ret; + uchar new_nt_p16[16]; + uchar new_p16[16]; - nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); + nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); - smbpw->smb_passwd = new_p16; - smbpw->smb_nt_passwd = new_nt_p16; - - /* Now write it into the file. */ - become_root(0); - ret = mod_smbpwd_entry(smbpw,override); - unbecome_root(0); + smbpw->smb_passwd = new_p16; + smbpw->smb_nt_passwd = new_nt_p16; - memset(new_passwd, '\0', strlen(new_passwd)); + /* Now write it into the file. */ + become_root(0); + ret = mod_smbpwd_entry(smbpw, override); + unbecome_root(0); - return ret; + memset(new_passwd, '\0', strlen(new_passwd)); + + return ret; } /*********************************************************** Code to check a plaintext password against smbpasswd entries. ***********************************************************/ -BOOL check_plaintext_password(char *user,char *old_passwd, - int old_passwd_size, struct smb_passwd **psmbpw) +BOOL check_plaintext_password(char *user, char *old_passwd, + int old_passwd_size, struct smb_passwd **psmbpw) { - struct smb_passwd *smbpw = NULL; - uchar old_pw[16],old_ntpw[16]; + struct smb_passwd *smbpw = NULL; + uchar old_pw[16], old_ntpw[16]; - become_root(False); - *psmbpw = smbpw = getsmbpwnam(user); - unbecome_root(False); + become_root(False); + *psmbpw = smbpw = getsmbpwnam(user); + unbecome_root(False); - if (smbpw == NULL) { - DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); - return False; - } + if (smbpw == NULL) + { + DEBUG(0, + ("check_plaintext_password: getsmbpwnam returned NULL\n")); + return False; + } - if (smbpw->acct_ctrl & ACB_DISABLED) { - DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); - return(False); - } + if (smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0, + ("check_plaintext_password: account %s disabled.\n", + user)); + return (False); + } - nt_lm_owf_gen(old_passwd,old_ntpw,old_pw); + nt_lm_owf_gen(old_passwd, old_ntpw, old_pw); #ifdef DEBUG_PASSWORD - DEBUG(100,("check_plaintext_password: smbpw->smb_nt_passwd \n")); - dump_data(100,smbpw->smb_nt_passwd,16); - DEBUG(100,("check_plaintext_password: old_ntpw \n")); - dump_data(100,old_ntpw,16); - DEBUG(100,("check_plaintext_password: smbpw->smb_passwd \n")); - dump_data(100,smbpw->smb_passwd,16); - DEBUG(100,("check_plaintext_password: old_pw\n")); - dump_data(100,old_pw,16); + DEBUG(100, ("check_plaintext_password: smbpw->smb_nt_passwd \n")); + dump_data(100, smbpw->smb_nt_passwd, 16); + DEBUG(100, ("check_plaintext_password: old_ntpw \n")); + dump_data(100, old_ntpw, 16); + DEBUG(100, ("check_plaintext_password: smbpw->smb_passwd \n")); + dump_data(100, smbpw->smb_passwd, 16); + DEBUG(100, ("check_plaintext_password: old_pw\n")); + dump_data(100, old_pw, 16); #endif - if(memcmp(smbpw->smb_nt_passwd,old_ntpw,16) && memcmp(smbpw->smb_passwd,old_pw,16)) - return(False); - else - return(True); + if (memcmp(smbpw->smb_nt_passwd, old_ntpw, 16) + && memcmp(smbpw->smb_passwd, old_pw, 16)) + return (False); + else + return (True); } -- cgit From 8f1620125dcb9c29c223f4efb6485528ece70f11 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Mar 2000 19:03:12 +0000 Subject: acconfig.h configure configure.in: Added check for UT_SYSLEN for utmp code. include/byteorder.h: Added alignment macros. include/nameserv.h: Added defines for msg_type field options - from rfc1002. lib/time.c: Typo fix. lib/util_unistr.c: Updates from UNICODE branch. printing/nt_printing.c: bzero -> memset. smbd/connection.c: Added check for UT_SYSLEN for utmp code. Other fixes : Rollback of unapproved commit from Luke. Please *ask* next time before doing large changes to HEAD. Jeremy. (This used to be commit f02999dbf7971b4ea05050d7206205d7737a78b2) --- source3/smbd/connection.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 9a678ba88f..972ffa52dd 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -225,7 +225,9 @@ static void utmp_update(const pstring dirname, const struct utmp *u, const char getutmpx(u, &ux); if (host) { +#if defined(HAVE_UX_UT_SYSLEN) ux.ut_syslen = strlen(host); +#endif /* defined(HAVE_UX_UT_SYSLEN) */ pstrcpy(ux.ut_host, host); } -- cgit From 6814d0f45689d2a17af3d95511208421d10f5fce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Mar 2000 20:39:31 +0000 Subject: Correctly convert from little-endian UNICODE to dos_codepage when doing secure file create. Jeremy. (This used to be commit 90134dd13721f60d4fb05ce9434b65e95ff09629) --- source3/smbd/nttrans.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 05d9c82c38..1a43350e90 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -244,19 +244,6 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!! ****************************************************************************/ -static void my_wcstombs(char *dst, uint16 *src, size_t len) -{ - size_t i; - - for(i = 0; i < len; i++) - dst[i] = (char)SVAL(src,i*2); -} - -/**************************************************************************** - (Hopefully) temporary call to fix bugs in NT5.0beta2. This OS sends unicode - strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!! -****************************************************************************/ - static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) { /* @@ -277,11 +264,11 @@ static void get_filename( char *fname, char *inbuf, int data_offset, int data_le fname_len = fname_len/2; if(data_offset & 1) data_offset++; - my_wcstombs( fname, (uint16 *)(inbuf+data_offset), fname_len); + pstrcpy(fname, dos_unistrn2((uint16 *)(inbuf+data_offset), fname_len)); } else { StrnCpy(fname,inbuf+data_offset,fname_len); + fname[fname_len] = '\0'; } - fname[fname_len] = '\0'; } /**************************************************************************** @@ -312,11 +299,11 @@ static void get_filename_transact( char *fname, char *inbuf, int data_offset, in fname_len = fname_len/2; if(data_offset & 1) data_offset++; - my_wcstombs( fname, (uint16 *)(inbuf+data_offset), fname_len); + pstrcpy(fname, dos_unistrn2((uint16 *)(inbuf+data_offset), fname_len)); } else { StrnCpy(fname,inbuf+data_offset,fname_len); + fname[fname_len] = '\0'; } - fname[fname_len] = '\0'; } /**************************************************************************** -- cgit From 614929752ecfc7a2f621bc868406d3d77b63895d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Mar 2000 01:37:08 +0000 Subject: rpc_parse/parse_spoolss.c: Added checks on mallocs/overflow checks on all prs_xx calls. smbd/connection.c: Fix from David Lee . Jeremy. (This used to be commit 53721fbc7d2a986cf999b8f031a2d9003c0dccae) --- source3/smbd/connection.c | 116 +++++++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 972ffa52dd..95645bfdf6 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -216,7 +216,65 @@ static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid, i return(rc); } -static void utmp_update(const pstring dirname, const struct utmp *u, const char *host) +/* Default path (if possible) */ +#ifdef HAVE_UTMPX_H + +# ifdef UTMPX_FILE +static char *ut_pathname = UTMPX_FILE; +# else +static char *ut_pathname = ""; +# endif +# ifdef WTMPX_FILE +static char *wt_pathname = WTMPX_FILE; +# else +static char *wt_pathname = ""; +# endif + +#else /* HAVE_UTMPX_H */ + +# ifdef UTMP_FILE +static char *ut_pathname = UTMP_FILE; +# else +static char *ut_pathname = ""; +# endif +# ifdef WTMP_FILE +static char *wt_pathname = WTMP_FILE; +# else +static char *wt_pathname = ""; +# endif + +#endif /* HAVE_UTMPX_H */ + +static void uw_pathname(pstring fname, const char *uw_name) +{ + pstring dirname; + + pstrcpy(dirname,lp_utmpdir()); + trim_string(dirname,"","/"); + + /* Given directory: use it */ + if (dirname != 0 && strlen(dirname) != 0) { + pstrcpy(fname, dirname); + pstrcat(fname, "/"); + pstrcat(fname, uw_name); + return; + } + + /* No given directory: attempt to use default paths */ + if (uw_name[0] == 'u') { + pstrcpy(fname, ut_pathname); + return; + } + + if (uw_name[0] == 'w') { + pstrcpy(fname, wt_pathname); + return; + } + + pstrcpy(fname, ""); +} + +static void utmp_update(const struct utmp *u, const char *host) { pstring fname; @@ -231,64 +289,62 @@ static void utmp_update(const pstring dirname, const struct utmp *u, const char pstrcpy(ux.ut_host, host); } - pstrcpy(fname, dirname); - pstrcat(fname, "utmpx"); - utmpxname(fname); + uw_pathname(fname, "utmpx"); + DEBUG(2,("utmp_update: fname:%s\n", fname)); + if (strlen(fname) != 0) { + utmpxname(fname); + } uxrc = pututxline(&ux); if (uxrc == NULL) { DEBUG(2,("utmp_update: pututxline() failed\n")); return; } - pstrcpy(fname, dirname); - pstrcat(fname, "wtmpx"); - updwtmpx(fname, &ux); + uw_pathname(fname, "wtmpx"); + DEBUG(2,("utmp_update: fname:%s\n", fname)); + if (strlen(fname) != 0) { + updwtmpx(fname, &ux); + } #else - pstrcpy(fname, dirname); - pstrcat(fname, "utmp"); - - utmpname(fname); + uw_pathname(fname, "utmp"); + DEBUG(2,("utmp_update: fname:%s\n", fname)); + if (strlen(fname) != 0) { + utmpname(fname); + } pututline(u); - pstrcpy(fname, dirname); - pstrcat(fname, "wtmp"); + uw_pathname(fname, "wtmp"); - /* *** OK. Appending wtmp (as distinct from overwriting utmp) has + /* *** Hmmm. Appending wtmp (as distinct from overwriting utmp) has me baffled. How is it to be done? *** */ #endif } -static void utmp_yield(int pid, const connection_struct *conn) +static void utmp_yield(pid_t pid, const connection_struct *conn) { struct utmp u; - pstring dirname; if (! lp_utmp(SNUM(conn))) { DEBUG(2,("utmp_yield: lp_utmp() NULL\n")); return; } - pstrcpy(dirname,lp_utmpdir()); - trim_string(dirname,"","/"); - pstrcat(dirname,"/"); - - DEBUG(2,("utmp_yield: dir:%s conn: user:%s cnum:%d i:%d\n", - dirname, conn->user, conn->cnum, conn->cnum)); + DEBUG(2,("utmp_yield: conn: user:%s cnum:%d i:%d\n", + conn->user, conn->cnum, i)); memset((char *)&u, '\0', sizeof(struct utmp)); u.ut_type = DEAD_PROCESS; u.ut_exit.e_termination = 0; u.ut_exit.e_exit = 0; if (utmp_fill(&u, conn, pid, conn->cnum) == 0) { - utmp_update(dirname, &u, NULL); + utmp_update(&u, NULL); } } -static void utmp_claim(const struct connections_data *crec, const connection_struct *conn) +static void utmp_claim(const struct connect_record *crec, const connection_struct *conn) { extern int Client; struct utmp u; - pstring dirname; if (conn == NULL) { DEBUG(2,("utmp_claim: conn NULL\n")); @@ -300,12 +356,8 @@ static void utmp_claim(const struct connections_data *crec, const connection_str return; } - pstrcpy(dirname,lp_utmpdir()); - trim_string(dirname,"","/"); - pstrcat(dirname,"/"); - - DEBUG(2,("utmp_claim: dir:%s conn: user:%s cnum:%d i:%d\n", - dirname, conn->user, conn->cnum, conn->cnum)); + DEBUG(2,("utmp_claim: conn: user:%s cnum:%d i:%d\n", + conn->user, conn->cnum, i)); DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s\n", crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name(Client))); @@ -313,7 +365,7 @@ static void utmp_claim(const struct connections_data *crec, const connection_str memset((char *)&u, '\0', sizeof(struct utmp)); u.ut_type = USER_PROCESS; if (utmp_fill(&u, conn, crec->pid, conn->cnum) == 0) { - utmp_update(dirname, &u, crec->machine); + utmp_update(&u, crec->machine); } } -- cgit From 18bc76a0c6830358a137b4198e17b1b7ce92b9bf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Mar 2000 12:38:45 +0000 Subject: changed the definition of dos_PutUniCode the previous definition could result is us overflowing a buffer. The null termination was always added yet the size returned did not include the null termination. the new function takes a BOOL null_terminate, and always returns the total number of bytes consumed by the string. (This used to be commit 426c90433396a95033eefcc4af97603abc934221) --- source3/smbd/trans2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 308ba2dacd..24abf60a79 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1179,7 +1179,7 @@ static int call_trans2qfsinfo(connection_struct *conn, #endif /* Old code. */ SIVAL(pdata,4,128); /* Max filename component length */ - fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring)/2); + fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring), False); SIVAL(pdata,8,fstype_len); data_len = 12 + fstype_len; SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); @@ -1209,7 +1209,7 @@ static int call_trans2qfsinfo(connection_struct *conn, } else { data_len = 18 + 2*strlen(vname); SIVAL(pdata,12,strlen(vname)*2); - dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring)/2); + dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring), False); } DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", @@ -1480,7 +1480,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } strupper(short_name); l = strlen(short_name); - dos_PutUniCode(pdata + 4, unix_to_dos(short_name,False),sizeof(pstring)*2); + dos_PutUniCode(pdata + 4, unix_to_dos(short_name,False),sizeof(pstring), False); data_size = 4 + (2*l); SIVAL(pdata,0,2*l); } @@ -1496,7 +1496,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) { l = l*2; SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); - dos_PutUniCode(pdata + 4, unix_to_dos("\\",False),sizeof(pstring)*2); + dos_PutUniCode(pdata + 4, unix_to_dos("\\",False),sizeof(pstring), False); } else { pstrcpy(pdata+4,fname); } -- cgit From aaa8aadd35dcdba542bda897bfe6c55c1567714b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Mar 2000 02:20:57 +0000 Subject: Moved common code to set parameter offset field correctly oout of 'if' statement into main function code path. Jeremy. (This used to be commit f15ca0d9273d718534ba2fdd2ccd14ab90a95c8b) --- source3/smbd/trans2.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 24abf60a79..38f2802df3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -118,21 +118,19 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, data_sent_thistime = MIN(data_sent_thistime,data_to_send); SSVAL(outbuf,smb_prcnt, params_sent_thistime); + + /* smb_proff is the offset from the start of the SMB header to the + parameter bytes, however the first 4 bytes of outbuf are + the Netbios over TCP header. Thus use smb_base() to subtract + them from the calculation */ + + SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + if(params_sent_thistime == 0) - { - SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); SSVAL(outbuf,smb_prdisp,0); - } else - { - /* smb_proff is the offset from the start of the SMB header to the - parameter bytes, however the first 4 bytes of outbuf are - the Netbios over TCP header. Thus use smb_base() to subtract - them from the calculation */ - SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); /* Absolute displacement of param bytes sent in this packet */ SSVAL(outbuf,smb_prdisp,pp - params); - } SSVAL(outbuf,smb_drcnt, data_sent_thistime); if(data_sent_thistime == 0) -- cgit From b546035ba8b29188e249aaa55d140b1b93304dd4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Mar 2000 02:38:59 +0000 Subject: Win2k will only accept volume labels in UNICODE. Fixed.... :-(. Jeremy. (This used to be commit 676db02f1cd7cb81c58cbbdd3bc94da17dad5227) --- source3/smbd/trans2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 38f2802df3..e6ee65d101 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1200,7 +1200,7 @@ static int call_trans2qfsinfo(connection_struct *conn, /* NT4 always serves this up as unicode but expects it to be * delivered as ascii! (tridge && JRA) */ - if (global_client_caps & CAP_NT_SMBS) { + if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) { data_len = 18 + strlen(vname); SIVAL(pdata,12,strlen(vname)); pstrcpy(pdata+18,vname); @@ -1208,6 +1208,7 @@ static int call_trans2qfsinfo(connection_struct *conn, data_len = 18 + 2*strlen(vname); SIVAL(pdata,12,strlen(vname)*2); dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring), False); + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); } DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", -- cgit From 84b16407bf8bdf2f318eba75a483c5b2a367d6ae Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 29 Mar 2000 07:44:23 +0000 Subject: More Japanese filename fixes wrt VFS code from Tomoki AONO (This used to be commit a9b628ebaa90e464366d0284226753f31439af9f) --- source3/smbd/dir.c | 13 +++++++------ source3/smbd/reply.c | 15 +++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 58b0061e19..55d5bf132c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -685,13 +685,14 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) while ((n = vfs_readdirname(conn, p))) { int l; - pstring zn; - - pstrcpy(zn, unix_to_dos(n,True)); - l = strlen(zn)+1; + + l = strlen(n)+1; + + /* Return value of vfs_readdirname has already gone through + unix_to_dos() */ /* If it's a vetoed file, pretend it doesn't even exist */ - if (use_veto && conn && IS_VETO_PATH(conn, zn)) continue; + if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); @@ -705,7 +706,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->mallocsize = s; dirp->current = dirp->data; } - pstrcpy(dirp->data+used,zn); + pstrcpy(dirp->data+used,n); used += l; dirp->numentries++; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4b0400fe6c..0092d6b397 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3570,6 +3570,7 @@ int rename_internals(connection_struct *conn, int error = ERRnoaccess; BOOL exists=False; BOOL rc = True; + pstring zdirectory; *directory = *mask = 0; @@ -3667,23 +3668,24 @@ int rename_internals(connection_struct *conn, } } + pstrcpy(zdirectory, dos_to_unix(directory, False)); if(replace_if_exists) { /* * NT SMB specific flag - rename can overwrite * file with the same name so don't check for - * dos_file_exist(). + * vfs_file_exist(). */ if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !conn->vfs_ops.rename(dos_to_unix(directory,False), - newname)) + !conn->vfs_ops.rename(zdirectory, + dos_to_unix(newname,False))) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && !vfs_file_exist(conn,newname,NULL) && - !conn->vfs_ops.rename(dos_to_unix(directory,False), - newname)) + !conn->vfs_ops.rename(zdirectory, + dos_to_unix(newname,False))) count++; } @@ -3714,6 +3716,7 @@ int rename_internals(connection_struct *conn, while ((dname = ReadDirName(dirptr))) { pstring fname; + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) @@ -3741,7 +3744,7 @@ int rename_internals(connection_struct *conn, } if (!conn->vfs_ops.rename(dos_to_unix(fname,False), - destname)) + dos_to_unix(destname,False))) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } -- cgit From 0d9d264625e482f55b2c5b76d7aa7d989529dd07 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Mar 2000 22:19:58 +0000 Subject: Fixed bug found by JF where if the amount of data to return in the prs_struct was small enough to pass the SMBtrans max data test we weren't setting the "more data needed" error. I was fogetting the RPC_HEADER_LEN.... I now check the correct length (current pdu staging area length). More printer spool enum stuff works now. This bug does not affect TNG. Jeremy. (This used to be commit 1c9d2c016a78b0ed11dc68adeabb709903444837) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index fc05811ccf..271b0e253b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3215,7 +3215,7 @@ static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) return False; } - send_trans_reply(outbuf, NULL, 0, rdata, data_len, (int)prs_offset(&p->out_data.rdata) > data_len); + send_trans_reply(outbuf, NULL, 0, rdata, data_len, p->out_data.current_pdu_len > data_len); free(rdata); return True; -- cgit From 9d5ddab76661878e08d9f3b4c6c34f52119318c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Apr 2000 01:13:54 +0000 Subject: Removed strange optimisation (paranoia fix maybe ?) that stopped smbd from returning '.' and '..' in a top level listing of a trans2 directory scan. NT does return these entries. Jeremy. (This used to be commit 7325059a0940909ddd98b32d62423700545ef87e) --- source3/smbd/trans2.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e6ee65d101..f90ce2ede4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -320,9 +320,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint32 len; time_t mdate=0, adate=0, cdate=0; char *nameptr; - BOOL isrootdir = (strequal(conn->dirpath,"./") || - strequal(conn->dirpath,".") || - strequal(conn->dirpath,"/")); BOOL was_8_3; int nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); @@ -395,9 +392,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (dont_descend && !isdots) continue; - if (isrootdir && isdots) - continue; - pstrcpy(pathreal,conn->dirpath); if(needslash) pstrcat(pathreal,"/"); -- cgit From 2d15c34f4fc2f3943328976361ab8c67508b6e82 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Apr 2000 18:44:04 +0000 Subject: Change to vfs API. POSIX states fsync should return an int, not a void. Jeremy. (This used to be commit 6c442d68afae4140e28b770343a900b5ce510b4a) --- source3/smbd/fileio.c | 2 -- source3/smbd/vfs-wrap.c | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 348486d430..00a515d16d 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -651,10 +651,8 @@ sync a file void sys_fsync_file(connection_struct *conn, files_struct *fsp) { -#ifdef HAVE_FSYNC if(lp_strict_sync(SNUM(conn)) && fsp->fd_ptr != NULL) { flush_write_cache(fsp, SYNC_FLUSH); conn->vfs_ops.fsync(fsp->fd_ptr->fd); } -#endif } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 24e45a6d24..b9c22ef1f9 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -204,9 +204,13 @@ int vfswrap_rename(char *old, char *new) return result; } -void vfswrap_fsync(int fd) +int vfswrap_fsync(int fd) { - fsync(fd); +#ifdef HAVE_FSYNC + return fsync(fd); +#else + return 0; +#endif } int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) -- cgit From f4274fe897c8456df74dda92df13398dc5a2ffdc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Apr 2000 02:44:06 +0000 Subject: utmp compile fix from peter@cadcamlab.org (This used to be commit c0562a02c345c3eb7d9a26b85bef454355023ba3) --- source3/smbd/connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 95645bfdf6..c796fee8b5 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -329,8 +329,8 @@ static void utmp_yield(pid_t pid, const connection_struct *conn) return; } - DEBUG(2,("utmp_yield: conn: user:%s cnum:%d i:%d\n", - conn->user, conn->cnum, i)); + DEBUG(2,("utmp_yield: conn: user:%s cnum:%d\n", + conn->user, conn->cnum)); memset((char *)&u, '\0', sizeof(struct utmp)); u.ut_type = DEAD_PROCESS; -- cgit From 689ec46450a3f373b583ebe98d124ab4a99ce3ef Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Apr 2000 13:05:23 +0000 Subject: the bulk of the changes to get rid of fd_ptr and move print open handling to printing/printing.c most of this was just replacing things like fsp->fd_ptr->fd with fsp->fd the changes in open.c are quite dramatic. Most of it is removing all the functions that handled the fd multiplexing (This used to be commit d1827a3648009fd0a0d165055015d9aeda7a1037) --- source3/smbd/close.c | 22 +- source3/smbd/fileio.c | 44 ++-- source3/smbd/filename.c | 6 + source3/smbd/files.c | 118 +-------- source3/smbd/nttrans.c | 40 +-- source3/smbd/open.c | 650 +++++++++--------------------------------------- source3/smbd/oplock.c | 52 ++-- source3/smbd/predict.c | 162 ------------ source3/smbd/reply.c | 131 +++------- source3/smbd/trans2.c | 22 +- source3/smbd/vfs.c | 7 +- 11 files changed, 231 insertions(+), 1023 deletions(-) delete mode 100644 source3/smbd/predict.c (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 8e2ed0de0e..61e8264159 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -92,10 +92,7 @@ static void close_filestruct(files_struct *fsp) static int close_normal_file(files_struct *fsp, BOOL normal_close) { - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; - BOOL last_reference = False; - BOOL delete_on_close = fsp->fd_ptr->delete_on_close; + BOOL delete_on_close = fsp->delete_on_close; connection_struct *conn = fsp->conn; int err = 0; @@ -103,12 +100,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) close_filestruct(fsp); -#if USE_READ_PREDICTION - invalidate_read_prediction(fsp->fd_ptr->fd); -#endif - if (lp_share_modes(SNUM(conn))) { - lock_share_entry(conn, dev, inode); + lock_share_entry_fsp(fsp); del_share_mode(fsp); } @@ -117,13 +110,10 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) locking_close_file(fsp); - if(fd_attempt_close(fsp, &err) == 0) - last_reference = True; - - fsp->fd_ptr = NULL; - if (lp_share_modes(SNUM(conn))) - unlock_share_entry(conn, dev, inode); + unlock_share_entry_fsp(fsp); + + fd_close(fsp, &err); /* NT uses smbclose to start a print - weird */ if (normal_close && fsp->print_file) @@ -139,7 +129,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * reference to a file. */ - if (normal_close && last_reference && delete_on_close) { + if (normal_close && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); if(fsp->conn->vfs_ops.unlink(dos_to_unix(fsp->fsp_name, False)) != 0) { diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 00a515d16d..43fd091b49 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -37,7 +37,7 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; - seek_ret = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET); + seek_ret = fsp->conn->vfs_ops.lseek(fsp->fd,pos+offset,SEEK_SET); /* * We want to maintain the fiction that we can seek @@ -96,16 +96,6 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { ssize_t ret=0,readret; -#if USE_READ_PREDICTION - if (!fsp->can_write) { - ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n); - - data += ret; - n -= ret; - pos += ret; - } -#endif - /* * Serve from write cache if we can. */ @@ -120,7 +110,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) } if (n > 0) { - readret = fsp->conn->vfs_ops.read(fsp->fd_ptr->fd,data,n); + readret = fsp->conn->vfs_ops.read(fsp->fd,data,n); if (readret > 0) ret += readret; } @@ -151,7 +141,7 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ if ((pos != -1) && (seek_file(fsp,pos) == -1)) return -1; - return write_data(fsp->fd_ptr->fd,data,n); + return write_data(fsp->fd,data,n); } /**************************************************************************** @@ -173,7 +163,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) SMB_STRUCT_STAT st; fsp->modified = True; - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); @@ -205,19 +195,17 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) */ if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; share_mode_entry *share_list = NULL; pid_t pid = getpid(); int token = -1; int num_share_modes = 0; int i; - if (lock_share_entry(fsp->conn, dev, inode) == False) { + if (lock_share_entry_fsp(fsp) == False) { DEBUG(0,("write_file: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); } - num_share_modes = get_share_modes(fsp->conn, dev, inode, &share_list); + num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list); for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &share_list[i]; @@ -247,7 +235,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) */ if (pid == share_entry->pid) { - files_struct *new_fsp = file_find_dit(dev, inode, &share_entry->time); + files_struct *new_fsp = file_find_dit(fsp->dev, fsp->inode, &share_entry->time); /* Paranoia check... */ if(new_fsp == NULL) { @@ -263,12 +251,12 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) * message. */ - request_oplock_break(share_entry, dev, inode); + request_oplock_break(share_entry, fsp->dev, fsp->inode); } } free((char *)share_list); - unlock_share_entry(fsp->conn, dev, inode); + unlock_share_entry_fsp(fsp); } /* Paranoia check... */ @@ -300,7 +288,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", } DEBUG(9,("write_file(fd=%d pos=%d size=%d) wofs=%d wsize=%d\n", - fsp->fd_ptr->fd, (int)pos, (int)n, (int)wcp->offset, (int)wcp->data_size)); + fsp->fd, (int)pos, (int)n, (int)wcp->offset, (int)wcp->data_size)); /* * If we have active cache and it isn't contiguous then we flush. @@ -427,7 +415,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", wcp->file_size = wcp->offset + wcp->data_size; #if 0 - if (set_filelen(fsp->fd_ptr->fd, wcp->file_size) == -1) { + if (set_filelen(fsp->fd, wcp->file_size) == -1) { DEBUG(0,("write_file: error %s in setting file to length %.0f\n", strerror(errno), (double)wcp->file_size )); return -1; @@ -466,7 +454,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", */ DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \ -len = %u\n",fsp->fd_ptr->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); +len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); /* * Update the file size if needed. @@ -501,7 +489,7 @@ len = %u\n",fsp->fd_ptr->fd, (double)pos, (unsigned int)n, (double)wcp->offset, DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", - write_path, fsp->fd_ptr->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, + write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); flush_write_cache(fsp, WRITE_FLUSH); @@ -637,7 +625,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) flush_reasons[(int)reason]++; DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", - fsp->fd_ptr->fd, (double)wcp->offset, (unsigned int)data_size)); + fsp->fd, (double)wcp->offset, (unsigned int)data_size)); if(data_size == wcp->alloc_size) num_perfect_writes++; @@ -651,8 +639,8 @@ sync a file void sys_fsync_file(connection_struct *conn, files_struct *fsp) { - if(lp_strict_sync(SNUM(conn)) && fsp->fd_ptr != NULL) { + if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { flush_write_cache(fsp, SYNC_FLUSH); - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 729ef8c809..7afa9e9986 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -347,6 +347,12 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, extern char magic_char; #endif + if (conn->printer) { + /* we don't ever use the filenames on a printer share as a + filename - so don't convert them */ + return True; + } + DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); *dirpath = 0; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d62950c568..127d2fcac9 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -38,13 +38,7 @@ static files_struct *chain_fsp = NULL; /* a fsp to use to save when breaking an oplock. */ static files_struct *oplock_save_chain_fsp = NULL; -/* - * Indirection for file fd's. Needed as POSIX locking - * is based on file/process, not fd/process. - */ -static file_fd_struct *FileFd; - -static int files_used, fd_ptr_used; +static int files_used; /**************************************************************************** find first available file slot @@ -110,72 +104,6 @@ files_struct *file_new(void ) } - -/**************************************************************************** -fd support routines - attempt to find an already open file by dev -and inode - increments the ref_count of the returned file_fd_struct *. -****************************************************************************/ -file_fd_struct *fd_get_already_open(SMB_STRUCT_STAT *sbuf) -{ - file_fd_struct *fd_ptr; - - if(!sbuf) return NULL; - - for (fd_ptr=FileFd;fd_ptr;fd_ptr=fd_ptr->next) { - if ((fd_ptr->ref_count > 0) && - (sbuf->st_dev == fd_ptr->dev) && - (sbuf->st_ino == fd_ptr->inode)) { - fd_ptr->ref_count++; - - DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %.0f, ref_count = %d\n", - (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, - fd_ptr->ref_count)); - - return fd_ptr; - } - } - - return NULL; -} - - - -/**************************************************************************** -fd support routines - attempt to find a empty slot in the FileFd array. -Increments the ref_count of the returned entry. -****************************************************************************/ -file_fd_struct *fd_get_new(void) -{ - extern struct current_user current_user; - file_fd_struct *fd_ptr; - - fd_ptr = (file_fd_struct *)malloc(sizeof(*fd_ptr)); - if (!fd_ptr) { - DEBUG(0,("ERROR! malloc fail for file_fd struct.\n")); - return NULL; - } - - ZERO_STRUCTP(fd_ptr); - - fd_ptr->dev = (SMB_DEV_T)-1; - fd_ptr->inode = (SMB_INO_T)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); - fd_ptr->ref_count++; - - fd_ptr_used++; - - DLIST_ADD(FileFd, fd_ptr); - - DEBUG(5,("allocated fd_ptr structure (%d used)\n", fd_ptr_used)); - - return fd_ptr; -} - - /**************************************************************************** close all open files for a connection ****************************************************************************/ @@ -257,9 +185,9 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval for (fsp=Files;fsp;fsp=fsp->next,count++) { if (fsp->open && - fsp->fd_ptr != NULL && - fsp->fd_ptr->dev == dev && - fsp->fd_ptr->inode == inode && + fsp->fd != -1 && + fsp->dev == dev && + fsp->inode == inode && (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) && (tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True )) { if (count > 10) { @@ -282,9 +210,9 @@ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) for (fsp=Files;fsp;fsp=fsp->next) { if (fsp->open && - fsp->fd_ptr != NULL && - fsp->fd_ptr->dev == dev && - fsp->fd_ptr->inode == inode ) + fsp->fd != -1 && + fsp->dev == dev && + fsp->inode == inode ) return fsp; } @@ -301,9 +229,9 @@ files_struct *file_find_di_next(files_struct *start_fsp) for (fsp = start_fsp->next;fsp;fsp=fsp->next) { if (fsp->open && - fsp->fd_ptr != NULL && - fsp->fd_ptr->dev == start_fsp->fd_ptr->dev && - fsp->fd_ptr->inode == start_fsp->fd_ptr->inode ) + fsp->fd != -1 && + fsp->dev == start_fsp->dev && + fsp->inode == start_fsp->inode ) return fsp; } @@ -334,31 +262,13 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if (fsp->open && (conn == fsp->conn) && (fsp->fd_ptr != NULL)) { - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + if (fsp->open && (conn == fsp->conn) && (fsp->fd != -1)) { + conn->vfs_ops.fsync(fsp->fd); } } } -/**************************************************************************** -free up a fd_ptr -****************************************************************************/ -void fd_ptr_free(file_fd_struct *fd_ptr) -{ - DLIST_REMOVE(FileFd, fd_ptr); - - fd_ptr_used--; - - DEBUG(5,("freed fd_ptr structure (%d used)\n", fd_ptr_used)); - - /* paranoia */ - ZERO_STRUCTP(fd_ptr); - - free(fd_ptr); -} - - /**************************************************************************** free up a fsp ****************************************************************************/ @@ -368,10 +278,6 @@ void file_free(files_struct *fsp) string_free(&fsp->fsp_name); - if ((fsp->fd_ptr != NULL) && fsp->fd_ptr->ref_count == 0) { - fd_ptr_free(fsp->fd_ptr); - } - bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1a43350e90..54e67f5593 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -754,18 +754,6 @@ int reply_ntcreate_and_X(connection_struct *conn, return(ERROR(ERRSRV,ERRnofids)); } - if (!check_name(fname,conn)) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - - restore_case_semantics(file_attributes); - - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* @@ -889,7 +877,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1128,18 +1116,6 @@ static int call_nt_transact_create(connection_struct *conn, return(ERROR(ERRSRV,ERRnofids)); } - if (!check_name(fname,conn)) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - - restore_case_semantics(file_attributes); - - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* @@ -1244,7 +1220,7 @@ static int call_nt_transact_create(connection_struct *conn, return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (!fsp->stat_open && conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (!fsp->stat_open && conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1869,12 +1845,12 @@ static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) sid_copy( &group_sid, &global_sid_World); } else { - if(fsp->is_directory || fsp->fd_ptr == NULL) { + if(fsp->is_directory || fsp->fd == -1) { if(dos_stat(fsp->fsp_name, &sbuf) != 0) { return 0; } } else { - if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { return 0; } } @@ -2391,10 +2367,10 @@ security descriptor.\n")); int ret; - if(fsp->fd_ptr == NULL) + if(fsp->fd == -1) ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); else - ret = conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf); + ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); if(ret != 0) { free_sec_desc(&psd); @@ -2444,10 +2420,10 @@ security descriptor.\n")); int ret; - if(fsp->fd_ptr == NULL) + if(fsp->fd == -1) ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); else - ret = conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf); + ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); if(ret != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6352233dbc..4c5605fb3b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,274 +30,31 @@ extern BOOL global_client_failed_oplock_break; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ -static int fd_attempt_open(struct connection_struct *conn, char *fname, - int flags, mode_t mode) +static int fd_open(struct connection_struct *conn, char *fname, + int flags, mode_t mode) { - int fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); + int fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); - /* Fix for files ending in '.' */ - if((fd == -1) && (errno == ENOENT) && - (strchr(fname,'.')==NULL)) - { - pstrcat(fname,"."); - fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); - } - -#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) - if ((fd == -1) && (errno == ENAMETOOLONG)) - { - int max_len; - char *p = strrchr(fname, '/'); - - if (p == fname) /* name is "/xxx" */ - { - max_len = pathconf("/", _PC_NAME_MAX); - p++; - } - else if ((p == NULL) || (p == fname)) - { - p = fname; - max_len = pathconf(".", _PC_NAME_MAX); - } - else - { - *p = '\0'; - max_len = pathconf(fname, _PC_NAME_MAX); - *p = '/'; - p++; - } - if (strlen(p) > max_len) - { - char tmp = p[max_len]; - - p[max_len] = '\0'; - if ((fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode)) == -1) - p[max_len] = tmp; - } - } -#endif - return fd; -} - -/**************************************************************************** -Cache a uid_t currently with this file open. This is an optimization only -used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ - -void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) - return; - fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u; -} - -/**************************************************************************** -Remove a uid_t that currently has this file open. This is an optimization only -used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ - -static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - int i; - for(i = 0; i < fd_ptr->uid_cache_count; i++) - if(fd_ptr->uid_users_cache[i] == u) { - if(i < (fd_ptr->uid_cache_count-1)) - memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1], - sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) ); - fd_ptr->uid_cache_count--; - } - return; -} - -/**************************************************************************** -Check if a uid_t that currently has this file open is present. This is an -optimization only used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ - -static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - int i; - for(i = 0; i < fd_ptr->uid_cache_count; i++) - if(fd_ptr->uid_users_cache[i] == u) - return True; - return False; -} - -/**************************************************************************** -fd support routines - attempt to re-open an already open fd as O_RDWR. -Save the already open fd (we cannot close due to POSIX file locking braindamage. -****************************************************************************/ - -static void fd_attempt_reopen(char *fname, mode_t mode, files_struct *fsp) -{ - int fd = fsp->conn->vfs_ops.open(dos_to_unix(fname, False), O_RDWR, mode); - file_fd_struct *fd_ptr = fsp->fd_ptr; - - if(fd == -1) - return; - - if(fd_ptr->real_open_flags == O_RDONLY) - fd_ptr->fd_readonly = fd_ptr->fd; - if(fd_ptr->real_open_flags == O_WRONLY) - fd_ptr->fd_writeonly = fd_ptr->fd; - - fd_ptr->fd = fd; - fd_ptr->real_open_flags = O_RDWR; -} - -/**************************************************************************** -fd support routines - attempt to close the file referenced by this fd. -Decrements the ref_count and returns it. -****************************************************************************/ -uint16 fd_attempt_close(files_struct *fsp, int *err_ret) -{ - extern struct current_user current_user; - file_fd_struct *fd_ptr; - uint16 ret_ref; - - *err_ret = 0; - - if ((fsp == NULL) || (fsp->fd_ptr == NULL)) { - return 0; - } - - fd_ptr = fsp->fd_ptr; - ret_ref = fd_ptr->ref_count; - - DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n", - fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode, - fd_ptr->real_open_flags, - fd_ptr->ref_count)); - - SMB_ASSERT(fd_ptr->ref_count != 0); - - fd_ptr->ref_count--; - ret_ref = fd_ptr->ref_count; - - if(fd_ptr->ref_count == 0) { - - if(fd_ptr->fd != -1) { - if(fsp->conn->vfs_ops.close(fd_ptr->fd) < 0) - *err_ret = errno; - } - - if(fd_ptr->fd_readonly != -1) { - if(fsp->conn->vfs_ops.close(fd_ptr->fd_readonly) < 0) { - if(*err_ret == 0) - *err_ret = errno; - } - } - - if(fd_ptr->fd_writeonly != -1) { - if(fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly) < 0) { - if(*err_ret == 0) - *err_ret = errno; - } + /* Fix for files ending in '.' */ + if((fd == -1) && (errno == ENOENT) && + (strchr(fname,'.')==NULL)) { + pstrcat(fname,"."); + fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); } - /* - * Delete this fd_ptr. - */ - fd_ptr_free(fd_ptr); - } else { - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - } - - return ret_ref; + return fd; } /**************************************************************************** -fd support routines - check that current user has permissions -to open this file. Used when uid not found in optimization cache. -This is really ugly code, as due to POSIX locking braindamage we must -fork and then attempt to open the file, and return success or failure -via an exit code. +close the file associated with a fsp ****************************************************************************/ -static BOOL check_access_allowed_for_current_user(struct connection_struct - *conn, char *fname, - int accmode ) +void fd_close(files_struct *fsp, int *err_ret) { - pid_t child_pid; - - /* - * We need to temporarily stop CatchChild from eating - * SIGCLD signals as it also eats the exit status code. JRA. - */ - - CatchChildLeaveStatus(); - - if((child_pid = fork()) < 0) { - DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); - CatchChild(); - return False; - } - - if(child_pid) { - /* - * Parent. - */ - pid_t wpid; - int status_code; - - while ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { - if(errno == EINTR) { - errno = 0; - continue; - } - DEBUG(0,("check_access_allowed_for_current_user: The process \ -is no longer waiting ! Error = %s\n", strerror(errno) )); - CatchChild(); - return(False); - } - - /* - * Go back to ignoring children. - */ - CatchChild(); - - if (child_pid != wpid) { - DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); - return(False); - } -#if defined(WIFEXITED) && defined(WEXITSTATUS) - if (WIFEXITED(status_code) == 0) { - DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n")); - return(False); - } - if (WEXITSTATUS(status_code) != 0) { - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); - return(False); - } -#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */ - if(status_code != 0) { - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); - return(False); - } -#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */ - - /* - * Success - the child could open the file. - */ - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code)); - return True; - } else { - /* - * Child. - */ - int fd; - DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode )); - if((fd = fd_attempt_open(conn, fname, accmode, 0)) < 0) { - /* Access denied. */ - _exit(EACCES); - } - conn->vfs_ops.close(fd); - DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); - _exit(0); - } - - return False; + fsp->conn->vfs_ops.close(fsp->fd); + fsp->fd = -1; } + /**************************************************************************** check a filename for the pipe string ****************************************************************************/ @@ -320,278 +77,95 @@ open a file ****************************************************************************/ static void open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,mode_t mode, SMB_STRUCT_STAT *sbuf) + char *fname1,int flags,mode_t mode) { - extern struct current_user current_user; - pstring fname; - SMB_STRUCT_STAT statbuf; - file_fd_struct *fd_ptr; - int accmode = (flags & O_ACCMODE); - - fsp->open = False; - fsp->fd_ptr = 0; - fsp->oplock_type = NO_OPLOCK; - errno = EPERM; - - pstrcpy(fname,fname1); - - /* check permissions */ - - /* - * This code was changed after seeing a client open request - * containing the open mode of (DENY_WRITE/read-only) with - * the 'create if not exist' bit set. The previous code - * would fail to open the file read only on a read-only share - * as it was checking the flags parameter directly against O_RDONLY, - * this was failing as the flags parameter was set to O_RDONLY|O_CREAT. - * JRA. - */ - - if (!CAN_WRITE(conn) && !conn->printer) { - /* It's a read-only share - fail if we wanted to write. */ - if(accmode != O_RDONLY) { - DEBUG(3,("Permission denied opening %s\n",fname)); - check_for_pipe(fname); - return; - } else if(flags & O_CREAT) { - /* We don't want to write - but we must make sure that O_CREAT - doesn't create the file if we have write access into the - directory. - */ - flags &= ~O_CREAT; - } - } - - /* this handles a bug in Win95 - it doesn't say to create the file when it - should */ - if (conn->printer) { - flags |= (O_CREAT|O_EXCL); - } - -/* - if (flags == O_WRONLY) - DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); -*/ - - /* - * Ensure we have a valid struct stat so we can search the - * open fd table. - */ - if(sbuf == 0) { - if(conn->vfs_ops.stat(dos_to_unix(fname,False), &statbuf) < 0) { - if(errno != ENOENT) { - DEBUG(3,("Error doing stat on file %s (%s)\n", - fname,strerror(errno))); - - check_for_pipe(fname); - return; - } - sbuf = 0; - } else { - sbuf = &statbuf; - } - } - - /* - * Check to see if we have this file already - * open. If we do, just use the already open fd and increment the - * reference count (fd_get_already_open increments the ref_count). - */ - if((fd_ptr = fd_get_already_open(sbuf))!= 0) { - /* - * File was already open. - */ - - /* - * Check it wasn't open for exclusive use. - */ - if((flags & O_CREAT) && (flags & O_EXCL)) { - fd_ptr->ref_count--; - errno = EEXIST; - return; - } - - /* - * Ensure that the user attempting to open - * this file has permissions to do so, if - * the user who originally opened the file wasn't - * the same as the current user. - */ + extern struct current_user current_user; + pstring fname; + int accmode = (flags & O_ACCMODE); + SMB_STRUCT_STAT sbuf; - if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { - if(!check_access_allowed_for_current_user(conn, fname, accmode )) { - /* Error - permission denied. */ - DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", - fname, flags, accmode)); - /* Ensure the ref_count is decremented. */ - fd_ptr->ref_count--; - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - errno = EACCES; - return; - } - } + fsp->open = False; + fsp->fd = 0; + fsp->oplock_type = NO_OPLOCK; + errno = EPERM; - fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + pstrcpy(fname,fname1); - /* - * If not opened O_RDWR try - * and do that here - a chmod may have been done - * between the last open and now. - */ - if(fd_ptr->real_open_flags != O_RDWR) - fd_attempt_reopen(fname, mode, fsp); + /* check permissions */ - /* - * Ensure that if we wanted write access - * it has been opened for write, and if we wanted read it - * was open for read. - */ - if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) || - ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) || - ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { - DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", - fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); - check_for_pipe(fname); - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - fd_ptr->ref_count--; - return; - } + /* + * This code was changed after seeing a client open request + * containing the open mode of (DENY_WRITE/read-only) with + * the 'create if not exist' bit set. The previous code + * would fail to open the file read only on a read-only share + * as it was checking the flags parameter directly against O_RDONLY, + * this was failing as the flags parameter was set to O_RDONLY|O_CREAT. + * JRA. + */ - } else { - int open_flags; - /* We need to allocate a new file_fd_struct (this increments the - ref_count). */ - if((fd_ptr = fd_get_new()) == 0) - return; - /* - * Whatever the requested flags, attempt read/write access, - * as we don't know what flags future file opens may require. - * If this fails, try again with the required flags. - * Even if we open read/write when only read access was - * requested the setting of the can_write flag in - * the file_struct will protect us from errant - * write requests. We never need to worry about O_APPEND - * as this is not set anywhere in Samba. - */ - fd_ptr->real_open_flags = O_RDWR; - /* Set the flags as needed without the read/write modes. */ - open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); - fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|O_RDWR, mode); - /* - * On some systems opening a file for R/W access on a read only - * filesystems sets errno to EROFS. - */ -#ifdef EROFS - if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) { -#else /* No EROFS */ - if((fd_ptr->fd == -1) && (errno == EACCES)) { -#endif /* EROFS */ - if(accmode != O_RDWR) { - fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode); - fd_ptr->real_open_flags = accmode; - } - } - } + if (!CAN_WRITE(conn)) { + /* It's a read-only share - fail if we wanted to write. */ + if(accmode != O_RDONLY) { + DEBUG(3,("Permission denied opening %s\n",fname)); + check_for_pipe(fname); + return; + } else if(flags & O_CREAT) { + /* We don't want to write - but we must make sure that O_CREAT + doesn't create the file if we have write access into the + directory. + */ + flags &= ~O_CREAT; + } + } - if ((fd_ptr->fd >=0) && - conn->printer && lp_minprintspace(SNUM(conn))) { - pstring dname; - SMB_BIG_UINT dum1,dum2,dum3; - char *p; - pstrcpy(dname,fname); - p = strrchr(dname,'/'); - if (p) *p = 0; - if (conn->vfs_ops.disk_free(dos_to_unix(dname,False),False,&dum1,&dum2,&dum3) < - (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { - int err; - if(fd_attempt_close(fsp, &err) == 0) - conn->vfs_ops.unlink(dos_to_unix(fname, False)); - fsp->fd_ptr = 0; - errno = ENOSPC; - return; - } - } - - if (fd_ptr->fd < 0) - { - int err; - DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", - fname,strerror(errno),flags)); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fsp,&err); - check_for_pipe(fname); - return; - } + /* actually do the open */ + fsp->fd = fd_open(conn, fname, flags, mode); - if (fd_ptr->fd >= 0) - { - if(sbuf == 0) { - /* Do the fstat */ - if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) { - int err; - /* Error - backout !! */ - DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", - fd_ptr->fd, fname,strerror(errno))); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fsp,&err); - return; - } - sbuf = &statbuf; - } + if (fsp->fd == -1) { + DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", + fname,strerror(errno),flags)); + check_for_pipe(fname); + return; + } - /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = sbuf->st_dev; - fd_ptr->inode = sbuf->st_ino; - - fsp->fd_ptr = fd_ptr; - conn->num_files_open++; - fsp->mode = sbuf->st_mode; - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; - fsp->size = 0; - fsp->pos = -1; - fsp->open = True; - fsp->can_lock = True; - fsp->can_read = ((flags & O_WRONLY)==0); - fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - fsp->share_mode = 0; - fsp->print_file = conn->printer; - fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->is_directory = False; - fsp->stat_open = False; - fsp->directory_delete_on_close = False; - fsp->conn = conn; - /* - * Note that the file name here is the *untranslated* name - * ie. it is still in the DOS codepage sent from the client. - * All use of this filename will pass though the sys_xxxx - * functions which will do the dos_to_unix translation before - * mapping into a UNIX filename. JRA. - */ - string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; - fsp->wcp = NULL; /* Write cache pointer. */ + conn->vfs_ops.fstat(fsp->fd, &sbuf); - /* - * If the printer is marked as postscript output a leading - * file identifier to ensure the file is treated as a raw - * postscript file. - * This has a similar effect as CtrlD=0 in WIN.INI file. - * tim@fsg.com 09/06/94 - */ - if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { - DEBUG(3,("Writing postscript line\n")); - conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3); - } - - DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name, - BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), - conn->num_files_open)); + conn->num_files_open++; + fsp->mode = sbuf.st_mode; + fsp->inode = sbuf.st_ino; + fsp->dev = sbuf.st_dev; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->can_lock = True; + fsp->can_read = ((flags & O_WRONLY)==0); + fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + fsp->share_mode = 0; + fsp->print_file = False; + fsp->modified = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->is_directory = False; + fsp->stat_open = False; + fsp->directory_delete_on_close = False; + fsp->conn = conn; + /* + * Note that the file name here is the *untranslated* name + * ie. it is still in the DOS codepage sent from the client. + * All use of this filename will pass though the sys_xxxx + * functions which will do the dos_to_unix translation before + * mapping into a UNIX filename. JRA. + */ + string_set(&fsp->fsp_name,fname); + fsp->wbmpx_ptr = NULL; + fsp->wcp = NULL; /* Write cache pointer. */ - } + DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", + *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name, + BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), + conn->num_files_open)); } /**************************************************************************** @@ -611,8 +185,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode); + unlock_share_entry_fsp(fsp); close_file(fsp,False); /* Share mode no longer locked. */ *share_locked = False; @@ -620,7 +193,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; } else { - sys_ftruncate(fsp->fd_ptr->fd,0); + sys_ftruncate(fsp->fd,0); } } } @@ -814,11 +387,23 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int int oplock_contention_count = 0; BOOL all_current_opens_are_level_II = False; fsp->open = False; - fsp->fd_ptr = 0; + fsp->fd = -1; + + if (conn->printer) { + /* printers are handled completely differently. Most of the passed parameters are + ignored */ + *Access = DOS_OPEN_WRONLY; + *action = FILE_WAS_CREATED; + print_open_file(fsp, conn, fname); + return; + } DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, share_mode, ofun, (int)mode, oplock_request )); + if (!check_name(fname,conn)) { + return; + } /* ignore any oplock requests if oplocks are disabled */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { @@ -1011,11 +596,10 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); - open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); - if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen) - { - flags = O_RDONLY; - open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); + open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); + if (!fsp->open && flags==O_RDWR && errno != ENOENT && fcbopen) { + flags = O_RDONLY; + open_file(fsp,conn,fname,flags,mode); } if (fsp->open) @@ -1025,9 +609,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if((share_locked == False) && lp_share_modes(SNUM(conn))) { /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fsp->fd_ptr->dev; - inode = fsp->fd_ptr->inode; - lock_share_entry(conn, dev, inode); + lock_share_entry_fsp(fsp); share_locked = True; } @@ -1090,12 +672,12 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } if (share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, dev, inode); + unlock_share_entry_fsp(fsp); } /**************************************************************************** Open a file for permissions read only. Return a pseudo file entry - with the 'stat_open' flag set and a fd_ptr of NULL. + with the 'stat_open' flag set ****************************************************************************/ int open_file_stat(files_struct *fsp,connection_struct *conn, @@ -1122,7 +704,7 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, * Setup the files_struct for it. */ - fsp->fd_ptr = NULL; + fsp->fd = -1; conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); @@ -1235,7 +817,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Setup the files_struct for it. */ - fsp->fd_ptr = NULL; + fsp->fd = -1; conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c5cab8c225..218961d88c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -280,22 +280,22 @@ static BOOL set_kernel_oplock(files_struct *fsp, int oplock_type) #if defined(HAVE_KERNEL_OPLOCKS) if(lp_kernel_oplocks()) { - if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { + if(fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { if(errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno) )); } else { DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. Another process had the file open.\n", - fsp->fsp_name, fsp->fd_ptr->fd, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode )); + fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode )); } return False; } DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", - fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode)); + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); } #endif /* HAVE_KERNEL_OPLOCKS */ @@ -320,7 +320,7 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) exclusive_oplocks_open++; DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); return True; @@ -342,24 +342,24 @@ static void release_kernel_oplock(files_struct *fsp) * Check and print out the current kernel * oplock state of this file. */ - int state = fcntl(fsp->fd_ptr->fd, F_OPLKACK, -1); + int state = fcntl(fsp->fd, F_OPLKACK, -1); dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ -oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, - (double)fsp->fd_ptr->inode, state ); +oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, state ); } /* * Remove the kernel oplock on this file. */ - if(fcntl(fsp->fd_ptr->fd, F_OPLKACK, OP_REVOKE) < 0) + if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { if( DEBUGLVL( 0 )) { dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, - (double)fsp->fd_ptr->inode, strerror(errno) ); + fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, strerror(errno) ); } } } @@ -406,12 +406,12 @@ static void downgrade_file_oplock(files_struct *fsp) BOOL remove_oplock(files_struct *fsp) { - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; BOOL ret = True; /* Remove the oplock flag from the sharemode. */ - if (lock_share_entry(fsp->conn, dev, inode) == False) { + if (lock_share_entry_fsp(fsp) == False) { DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", fsp->fsp_name )); ret = False; @@ -446,7 +446,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double) downgrade_file_oplock(fsp); } - unlock_share_entry(fsp->conn, dev, inode); + unlock_share_entry_fsp(fsp); return ret; } @@ -757,8 +757,8 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) extern uint32 global_client_caps; char outbuf[128]; BOOL got_lock = False; - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; /* * We can have a level II oplock even if the client is not @@ -791,7 +791,7 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) * the existing lock on the shared memory area. */ - if(!local_request && lock_share_entry(fsp->conn, dev, inode) == False) { + if(!local_request && lock_share_entry_fsp(fsp) == False) { DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); } else { got_lock = True; @@ -802,7 +802,7 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) } if (!local_request && got_lock) - unlock_share_entry(fsp->conn, dev, inode); + unlock_share_entry_fsp(fsp); fsp->oplock_type = NO_OPLOCK; level_II_oplocks_open--; @@ -1308,14 +1308,12 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - if (fsp->open && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd_ptr != NULL)) { - - /* Try and break the oplock. */ - file_fd_struct *fd_ptr = fsp->fd_ptr; - if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time, True)) { - if(!fsp->open) /* Did the oplock break close the file ? */ - return True; - } + if (fsp->open && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd != -1)) { + /* Try and break the oplock. */ + if (oplock_break(fsp->dev, fsp->inode, &fsp->open_time, True)) { + if(!fsp->open) /* Did the oplock break close the file ? */ + return True; + } } return False; diff --git a/source3/smbd/predict.c b/source3/smbd/predict.c deleted file mode 100644 index 34044b82f2..0000000000 --- a/source3/smbd/predict.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - file read prediction routines - Copyright (C) Andrew Tridgell 1992-1998 - - 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; - -#if USE_READ_PREDICTION - -/* variables used by the read prediction module */ -static int rp_fd = -1; -static SMB_OFF_T rp_offset = 0; -static ssize_t rp_length = 0; -static ssize_t rp_alloced = 0; -static int rp_predict_fd = -1; -static SMB_OFF_T rp_predict_offset = 0; -static size_t rp_predict_length = 0; -static int rp_timeout = 5; -static time_t rp_time = 0; -static char *rp_buffer = NULL; -static BOOL predict_skip=False; -extern struct timeval smb_last_time; - -/**************************************************************************** -handle read prediction on a file -****************************************************************************/ -ssize_t read_predict(files_struct *fsp, int fd,SMB_OFF_T offset,char *buf,char **ptr,size_t num) -{ - ssize_t ret = 0; - ssize_t possible = rp_length - (offset - rp_offset); - - possible = MIN(possible,num); - - /* give data if possible */ - if (fd == rp_fd && - offset >= rp_offset && - possible>0 && - smb_last_time.tv_secs - rp_time < rp_timeout) - { - ret = possible; - if (buf) - memcpy(buf,rp_buffer + (offset-rp_offset),possible); - else - *ptr = rp_buffer + (offset-rp_offset); - DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); - } - - if (ret == num) { - predict_skip = True; - } else { - SMB_STRUCT_STAT rp_stat; - - /* Find the end of the file - ensure we don't - read predict beyond it. */ - if(fsp->conn->vfs_ops.fstat(fd,&rp_stat) < 0) - { - DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); - predict_skip = True; - } - else - { - predict_skip = False; - - /* prepare the next prediction */ - rp_predict_fd = fd; - /* Make sure we don't seek beyond the end of the file. */ - rp_predict_offset = MIN((offset + num),rp_stat.st_size); - rp_predict_length = num; - } - } - - if (ret < 0) ret = 0; - - return(ret); -} - -/**************************************************************************** -pre-read some data -****************************************************************************/ -void do_read_prediction(connection_struct *conn) -{ - static size_t readsize = 0; - - if (predict_skip) return; - - if (rp_predict_fd == -1) - return; - - rp_fd = rp_predict_fd; - rp_offset = rp_predict_offset; - rp_length = 0; - - rp_predict_fd = -1; - - if (readsize == 0) { - readsize = lp_readsize(); - readsize = MAX(readsize,1024); - } - - rp_predict_length = MIN(rp_predict_length,2*readsize); - rp_predict_length = MAX(rp_predict_length,1024); - rp_offset = (rp_offset/1024)*1024; - rp_predict_length = (rp_predict_length/1024)*1024; - - if (rp_predict_length > rp_alloced) - { - rp_buffer = Realloc(rp_buffer,rp_predict_length); - rp_alloced = rp_predict_length; - if (!rp_buffer) - { - DEBUG(0,("can't allocate read-prediction buffer\n")); - rp_predict_fd = -1; - rp_fd = -1; - rp_alloced = 0; - return; - } - } - - if (conn->vfs_ops.lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { - rp_fd = -1; - rp_predict_fd = -1; - return; - } - - rp_length = conn->vfs_ops.read(rp_fd,rp_buffer,rp_predict_length); - rp_time = time(NULL); - if (rp_length < 0) - rp_length = 0; -} - -/**************************************************************************** -invalidate read-prediction on a fd -****************************************************************************/ -void invalidate_read_prediction(int fd) -{ - if (rp_fd == fd) - rp_fd = -1; - if (rp_predict_fd == fd) - rp_predict_fd = -1; -} - -#else - void read_prediction_dummy(void) ; -#endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0092d6b397..81d3ef32b3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1549,17 +1549,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - if (!check_name(fname,conn)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - unixmode = unix_mode(conn,aARCH,fname); open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), @@ -1576,7 +1565,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1654,17 +1643,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - if (!check_name(fname,conn)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - unixmode = unix_mode(conn,smb_attr | aARCH, fname); open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode, @@ -1681,7 +1659,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { close_file(fsp,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1798,17 +1776,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - if (!check_name(fname,conn)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - if(com == SMBmknew) { /* We should fail if file exists. */ @@ -1847,7 +1814,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 2, ( "new file %s\n", fname ) ); DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", - fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) ); + fname, fsp->fd, createmode, (int)unixmode ) ); return(outsize); } @@ -1881,17 +1848,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (fsp) return(ERROR(ERRSRV,ERRnofids)); - if (!check_name(fname,conn)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - file_free(fsp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - pstrcpy(fname2,(char *)smbd_mktemp(fname)); /* Open file in dos compatibility share mode. */ @@ -1924,7 +1880,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 2, ( "created temp file %s\n", fname2 ) ); DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", - fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) ); + fname2, fsp->fd, createmode, (int)unixmode ) ); return(outsize); } @@ -2161,7 +2117,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0) + if (fsp->conn->vfs_ops.fstat(fsp->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -2185,7 +2141,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #if USE_READ_PREDICTION if (!fsp->can_write) - predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread); + predict = read_predict(fsp, fsp->fd,startpos,header+4,NULL,nread); #endif /* USE_READ_PREDICTION */ if ((nread-predict) > 0) { @@ -2197,7 +2153,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s } if(!seek_fail) - ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL, + ret = (ssize_t)vfs_transfer_file(-1, fsp->fd, Client, NULL, (SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } @@ -2480,7 +2436,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn))) - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); @@ -2528,7 +2484,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz nwritten = write_file(fsp,data,startpos,numtowrite); if (lp_syncalways(SNUM(conn))) - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2577,13 +2533,13 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) { - if((nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos)) >= 0) /* tpot vfs */ + if((nwritten = set_filelen(fsp->fd, (SMB_OFF_T)startpos)) >= 0) /* tpot vfs */ set_filelen_write_cache(fsp, startpos); } else nwritten = write_file(fsp,data,startpos,numtowrite); if (lp_syncalways(SNUM(conn))) - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2677,7 +2633,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng fsp->fnum, (int)numtowrite, (int)nwritten)); if (lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2711,7 +2667,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int umode = SEEK_SET; break; } - if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) { + if((res = conn->vfs_ops.lseek(fsp->fd,startpos,umode)) == -1) { /* * Check for the special case where a seek before the start * of the file sets the offset to zero. Added in the CIFS spec, @@ -2723,7 +2679,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int if(umode == SEEK_CUR) { - if((current_pos = conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + if((current_pos = conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); current_pos += startpos; @@ -2732,14 +2688,14 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; - if(conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf) == -1) + if(conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); current_pos += sbuf.st_size; } if(current_pos < 0) - res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_SET); + res = conn->vfs_ops.lseek(fsp->fd,0,SEEK_SET); } if(res == -1) @@ -2774,7 +2730,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (!fsp) { file_sync_all(conn); } else { - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); } DEBUG(3,("flush\n")); @@ -2855,7 +2811,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, set_filetime(conn, fsp->fsp_name,mtime); DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", - fsp->fd_ptr ? fsp->fd_ptr->fd : -1, fsp->fnum, + fsp->fd, fsp->fnum, conn->num_files_open)); /* @@ -2950,7 +2906,7 @@ int reply_lock(connection_struct *conn, offset = IVAL(inbuf,smb_vwv3); DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", - fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count)); + fsp->fd, fsp->fnum, (double)offset, (double)count)); if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { @@ -2990,7 +2946,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, in return (ERROR(eclass,ecode)); DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", - fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) ); + fsp->fd, fsp->fnum, (double)offset, (double)count ) ); return(outsize); } @@ -3063,60 +3019,29 @@ int reply_echo(connection_struct *conn, int reply_printopen(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring fname; - pstring fname2; int outsize = 0; files_struct *fsp; - *fname = *fname2 = 0; - if (!CAN_PRINT(conn)) return(ERROR(ERRDOS,ERRnoaccess)); - { - pstring s; - char *p; - pstrcpy(s,smb_buf(inbuf)+1); - p = s; - while (*p) { - if (!(isalnum((int)*p) || strchr("._-",*p))) - *p = 'X'; - p++; - } - - if (strlen(s) > 10) s[10] = 0; - - slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s); - } - fsp = file_new(); if (!fsp) return(ERROR(ERRSRV,ERRnofids)); - pstrcpy(fname2,(char *)smbd_mktemp(fname)); - - if (!check_name(fname2,conn)) { - file_free(fsp); - return(ERROR(ERRDOS,ERRnoaccess)); - } - /* Open for exclusive use, write only. */ - open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0,fname2), 0, NULL, NULL); + print_open_file(fsp,conn,"dos.prn"); if (!fsp->open) { file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - /* force it to be a print file */ - fsp->print_file = True; - outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); - DEBUG(3,("openprint %s fd=%d fnum=%d\n", - fname2, fsp->fd_ptr->fd, fsp->fnum)); + DEBUG(3,("openprint fd=%d fnum=%d\n", + fsp->fd, fsp->fnum)); return(outsize); } @@ -3139,7 +3064,7 @@ int reply_printclose(connection_struct *conn, return(ERROR(ERRDOS,ERRnoaccess)); DEBUG(3,("printclose fd=%d fnum=%d\n", - fsp->fd_ptr->fd,fsp->fnum)); + fsp->fd,fsp->fnum)); close_err = close_file(fsp,True); @@ -3851,7 +3776,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) { + if(conn->vfs_ops.lseek(fsp2->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", strerror(errno) )); /* @@ -4469,7 +4394,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, nwritten = write_file(fsp,data,startpos,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); if(nwritten < (ssize_t)numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -4570,7 +4495,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz nwritten = write_file(fsp,data,startpos,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.fsync(fsp->fd_ptr->fd); + conn->vfs_ops.fsync(fsp->fd); if (nwritten < (ssize_t)numtowrite) { @@ -4677,7 +4602,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_ERROR(fsp); /* Do an fstat on this file */ - if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf)) + if(fsp->conn->vfs_ops.fstat(fsp->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(conn,fsp->fsp_name,&sbuf); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f90ce2ede4..f1fa30b0c6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -253,7 +253,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { close_file(fsp,False); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1332,14 +1332,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1) + if((pos = fsp->conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); - delete_pending = fsp->fd_ptr->delete_on_close; + delete_pending = fsp->delete_on_close; } } else { /* qpathinfo */ @@ -1612,7 +1612,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - fd = fsp->fd_ptr->fd; + fd = fsp->fd; if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); @@ -1811,12 +1811,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { int i; files_struct *iterate_fsp; - SMB_DEV_T dev = fsp->fd_ptr->dev; - SMB_INO_T inode = fsp->fd_ptr->inode; + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; int num_share_modes; share_mode_entry *current_shares = NULL; - if(lock_share_entry(fsp->conn, dev, inode) == False) + if (lock_share_entry_fsp(fsp) == False) return(ERROR(ERRDOS,ERRnoaccess)); /* @@ -1838,7 +1838,7 @@ file %s as a share exists that was not opened with FILE_DELETE access.\n", * Release the lock. */ - unlock_share_entry(fsp->conn, dev, inode); + unlock_share_entry_fsp(fsp); /* * current_shares was malloced by get_share_modes - free it here. @@ -1893,9 +1893,9 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) * counted struct. Delete when the last reference * goes away. */ - fsp->fd_ptr->delete_on_close = delete_on_close; + fsp->delete_on_close = delete_on_close; - unlock_share_entry(fsp->conn, dev, inode); + unlock_share_entry_fsp(fsp); DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 44f44bd169..e92235e230 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -251,11 +251,10 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) { size_t total=0; ssize_t ret; - int fd = fsp->fd_ptr->fd; while (total < N) { - ret = fsp->conn->vfs_ops.write(fd,buffer + total,N - total); + ret = fsp->conn->vfs_ops.write(fsp->fd,buffer + total,N - total); if (ret == -1) return -1; if (ret == 0) return total; @@ -331,13 +330,13 @@ SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, if (s > ret) { ret += in_fsp ? - in_fsp->conn->vfs_ops.read(in_fsp->fd_ptr->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); + in_fsp->conn->vfs_ops.read(in_fsp->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); } if (ret > 0) { if (out_fsp) { - ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd_ptr->fd,buf1,ret); + ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd,buf1,ret); } else { ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret; } -- cgit From 2733f5352a384561b4df7ea14c5962f3cd079166 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Apr 2000 13:12:04 +0000 Subject: initialise fsp->fd to -1 (This used to be commit 5257ff5d67632922a64266ad2ce5d5a38c701cbc) --- source3/smbd/files.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 127d2fcac9..e971de095b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -84,6 +84,7 @@ files_struct *file_new(void ) if (!fsp) return NULL; ZERO_STRUCTP(fsp); + fsp->fd = -1; first_file = (i+1) % real_max_open_files; -- cgit From 4379d359a8cdcc5b2d4ebf713a0ac32b1c7df4d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Apr 2000 21:02:45 +0000 Subject: Fix for soft quotas not being set from Norbert Püschel Jeremy. (This used to be commit 5480ecf24bc7c97f25a5a6aee7e24eba7e87a458) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/quotas.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 329f261f27..1e81443c5e 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -363,6 +363,11 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #endif } + /* If softlimit is zero, set it equal to hardlimit. + */ + + if (D.dqb_bsoftlimit==0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; /* Use softlimit to determine disk space. A user exceeding the quota is told * that there's no space left. Writes might actually work for a bit if the @@ -432,6 +437,12 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return (False); } + /* If softlimit is zero, set it equal to hardlimit. + */ + + if (D.dqb_bsoftlimit==0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; + /* Use softlimit to determine disk space, except when it has been exceeded */ if (D.dqb_bsoftlimit==0) @@ -662,6 +673,13 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U } else return(False); } + + /* If softlimit is zero, set it equal to hardlimit. + */ + + if (D.dqb_bsoftlimit==0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; + if (D.dqb_bsoftlimit==0) return(False); /* Use softlimit to determine disk space, except when it has been exceeded */ @@ -773,6 +791,12 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B return(False); } + /* If softlimit is zero, set it equal to hardlimit. + */ + + if (D.dqb_bsoftlimit==0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; + /* Use softlimit to determine disk space. A user exceeding the quota is told * that there's no space left. Writes might actually work for a bit if the * hardlimit is set higher than softlimit. Effectively the disk becomes -- cgit From 2fa922611bf7160e2c1ce80c11b50006448bf98d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Apr 2000 13:55:53 +0000 Subject: finally got sick of the "extern int Client" code and the stupid assumption that we have one socket everywhere while doing so I discovered a few bugs! 1) the clientgen session retarget code if used from smbd or nmbd would cause a crash as it called close_sockets() which closed our main socket! fixed by removing close_sockets() completely - it is unnecessary 2) the caching in client_addr() and client_name() was bogus - it could easily get fooled and give the wrong result. fixed. 3) the retarget could could recurse, allowing an easy denial of service attack on nmbd. fixed. (This used to be commit 5937ab14d222696e40a3fc6f0e6a536f2d7305d3) --- source3/smbd/blocking.c | 5 ++--- source3/smbd/connection.c | 6 ++---- source3/smbd/ipc.c | 7 +++---- source3/smbd/nttrans.c | 10 ++++------ source3/smbd/oplock.c | 10 +++------- source3/smbd/password.c | 6 ++---- source3/smbd/process.c | 26 ++++++++++-------------- source3/smbd/reply.c | 25 +++++++++++------------ source3/smbd/server.c | 51 ++++++++++++++++++++++++++++++----------------- source3/smbd/service.c | 8 +++----- source3/smbd/ssl.c | 6 +++--- source3/smbd/trans2.c | 7 +++---- 12 files changed, 81 insertions(+), 86 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index c90f475b46..ea8d2fd053 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -21,7 +21,6 @@ #include "includes.h" extern int DEBUGLEVEL; -extern int Client; extern char *OutBuffer; /**************************************************************************** @@ -134,7 +133,7 @@ static void send_blocking_reply(char *outbuf, int outsize) if(outsize > 4) smb_setlen(outbuf,outsize - 4); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); } /**************************************************************************** @@ -180,7 +179,7 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, i SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); ERROR(eclass,ecode); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); } /**************************************************************************** diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index c796fee8b5..9c859e4d89 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -71,7 +71,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO struct connections_key key; struct connections_data crec; TDB_DATA kbuf, dbuf; - extern int Client; if (max_connections <= 0) return(True); @@ -106,7 +105,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO crec.start = time(NULL); StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); - StrnCpy(crec.addr,conn?conn->client_address:client_addr(Client),sizeof(crec.addr)-1); + StrnCpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1); dbuf.dptr = (char *)&crec; dbuf.dsize = sizeof(crec); @@ -343,7 +342,6 @@ static void utmp_yield(pid_t pid, const connection_struct *conn) static void utmp_claim(const struct connect_record *crec, const connection_struct *conn) { - extern int Client; struct utmp u; if (conn == NULL) { @@ -359,7 +357,7 @@ static void utmp_claim(const struct connect_record *crec, const connection_struc DEBUG(2,("utmp_claim: conn: user:%s cnum:%d i:%d\n", conn->user, conn->cnum, i)); DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s\n", - crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name(Client))); + crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name())); memset((char *)&u, '\0', sizeof(struct utmp)); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 271b0e253b..46ef677f38 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -58,7 +58,6 @@ extern fstring global_myworkgroup; #define SNLEN 15 /* service name length */ #define QNLEN 12 /* queue name maximum length */ -extern int Client; extern int smb_read_error; static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -212,7 +211,7 @@ static void send_trans_reply(char *outbuf, SSVAL(outbuf,smb_vwv9,0); show_msg(outbuf); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); tot_data_sent = this_ldata; tot_param_sent = this_lparam; @@ -245,7 +244,7 @@ static void send_trans_reply(char *outbuf, SSVAL(outbuf,smb_vwv9,0); show_msg(outbuf); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); tot_data_sent += this_ldata; tot_param_sent += this_lparam; @@ -3608,7 +3607,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); show_msg(outbuf); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); } /* receive the rest of the trans packet */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 54e67f5593..bd77f17802 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -24,7 +24,6 @@ extern int DEBUGLEVEL; extern int Protocol; -extern int Client; extern int smb_read_error; extern int global_oplock_break; extern BOOL case_sensitive; @@ -88,7 +87,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err */ if(params_to_send == 0 && data_to_send == 0) { - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); return 0; } @@ -217,7 +216,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err params_to_send, data_to_send, paramsize, datasize)); /* Send the packet */ - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); pp += params_sent_thistime; pd += data_sent_thistime; @@ -1422,7 +1421,6 @@ static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_qu static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) { - extern int Client; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); @@ -1447,7 +1445,7 @@ static void change_notify_reply_packet(char *inbuf, int error_class, uint32 erro */ set_message(outbuf,18,0,False); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); } /**************************************************************************** @@ -2589,7 +2587,7 @@ due to being in oplock break state.\n" )); /* We need to send an interim response then receive the rest of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { BOOL ret; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 218961d88c..e794d2d923 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -753,7 +753,6 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, st BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) { - extern int Client; extern uint32 global_client_caps; char outbuf[128]; BOOL got_lock = False; @@ -781,7 +780,7 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) /* Prepare the SMBlockingX message. */ prepare_break_message( outbuf, fsp, False); - send_smb(Client, outbuf); + send_smb(smbd_server_fd(), outbuf); } /* @@ -832,7 +831,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B { extern uint32 global_client_caps; extern struct current_user current_user; - extern int Client; char *inbuf = NULL; char *outbuf = NULL; files_struct *fsp = NULL; @@ -923,7 +921,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - send_smb(Client, outbuf); + send_smb(smbd_server_fd(), outbuf); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; @@ -958,7 +956,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B while((fsp = initial_break_processing(dev, inode, tval)) && OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - if(receive_smb(Client,inbuf, timeout) == False) + if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) { /* * Die if we got an error. @@ -1019,7 +1017,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B { DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); DEBUGADD( 0, ( "Shutting down server\n" ) ); - close_sockets(); close(oplock_sock); exit_server("unable to re-become user"); } @@ -1059,7 +1056,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B { DEBUG( 0, ( "oplock_break: client failure in break - " ) ); DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); - close_sockets(); close(oplock_sock); exit_server("oplock break failure"); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index bdb0385a48..208dbd2bff 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -943,8 +943,7 @@ BOOL check_hosts_equiv(char *user) /* note: don't allow hosts.equiv on root */ if (fname && *fname && (pass->pw_uid != 0)) { - extern int Client; - if (check_user_equiv(user,client_name(Client),fname)) + if (check_user_equiv(user,client_name(),fname)) return(True); } @@ -952,9 +951,8 @@ BOOL check_hosts_equiv(char *user) { char *home = get_user_home_dir(user); if (home) { - extern int Client; slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(user,client_name(Client),rhostsfile)) + if (check_user_equiv(user,client_name(),rhostsfile)) return(True); } } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 403990a79d..2383b7a3a5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -133,7 +133,6 @@ The timeout is in milli seconds static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout, BOOL *got_smb) { - extern int Client; fd_set fds; int selrtn; struct timeval to; @@ -167,13 +166,13 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, */ FD_ZERO(&fds); - FD_SET(Client,&fds); + FD_SET(smbd_server_fd(),&fds); maxfd = setup_oplock_select_set(&fds); to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(MAX(maxfd,Client)+1,&fds,timeout>0?&to:NULL); + selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL); /* Check if error */ if(selrtn == -1) { @@ -188,10 +187,10 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, return False; } - if (FD_ISSET(Client,&fds)) + if (FD_ISSET(smbd_server_fd(),&fds)) { *got_smb = True; - return receive_smb(Client, buffer, 0); + return receive_smb(smbd_server_fd(), buffer, 0); } else { @@ -419,7 +418,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize static int num_smb_messages = sizeof(smb_messages) / sizeof(struct smb_message_struct); int match; - extern int Client; extern int global_smbpid; if (pid == (pid_t)-1) @@ -535,7 +533,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* does this protocol need to be run as guest? */ if ((flags & AS_GUEST) && (!become_guest() || - !check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1)))) { + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { return(ERROR(ERRSRV,ERRaccess)); } @@ -589,7 +587,6 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) ****************************************************************************/ void process_smb(char *inbuf, char *outbuf) { - extern int Client; #ifdef WITH_SSL extern BOOL sslEnabled; /* don't use function for performance reasons */ static int sslConnected = 0; @@ -608,13 +605,13 @@ void process_smb(char *inbuf, char *outbuf) deny parameters before doing any parsing of the packet passed to us by the client. This prevents attacks on our parsing code from hosts not in the hosts allow list */ - if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) { + if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { /* send a negative session response "not listining on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", - client_addr(Client) ) ); - send_smb(Client,(char *)buf); + client_addr() ) ); + send_smb(smbd_server_fd(),(char *)buf); exit_server("connection denied"); } } @@ -624,7 +621,7 @@ void process_smb(char *inbuf, char *outbuf) #ifdef WITH_SSL if(sslEnabled && !sslConnected){ - sslConnected = sslutil_negotiate_ssl(Client, msg_type); + sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type); if(sslConnected < 0){ /* an error occured */ exit_server("SSL negotiation failed"); }else if(sslConnected){ @@ -660,7 +657,7 @@ void process_smb(char *inbuf, char *outbuf) nread, smb_len(outbuf))); } else - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); } trans_num++; } @@ -851,7 +848,6 @@ void check_reload(int t) static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time) { - extern int Client; static time_t last_keepalive_sent_time = 0; static time_t last_idle_closed_check = 0; time_t t; @@ -897,7 +893,7 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t if (keepalive && (t - last_keepalive_sent_time)>keepalive) { struct cli_state *cli = server_client(); - if (!send_keepalive(Client)) { + if (!send_keepalive(smbd_server_fd())) { DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); return False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 81d3ef32b3..3ada28364b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -40,7 +40,6 @@ extern BOOL short_case_preserve; extern pstring sesssetup_user; extern pstring global_myname; extern fstring global_myworkgroup; -extern int Client; extern int global_oplock_break; uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; @@ -55,7 +54,7 @@ static void overflow_attack(int len) dbgtext( "ERROR: Invalid password length %d.\n", len ); dbgtext( "Your machine may be under attack by someone " ); dbgtext( "attempting to exploit an old bug.\n" ); - dbgtext( "Attack was from IP = %s.\n", client_addr(Client) ); + dbgtext( "Attack was from IP = %s.\n", client_addr() ); } exit_server("possible attack"); } @@ -2048,7 +2047,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if(global_oplock_break) { _smb_setlen(header,0); - transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); DEBUG(5,("readbraw - oplock break finished\n")); return -1; } @@ -2061,7 +2060,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s */ DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0))); _smb_setlen(header,0); - transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); return(-1); } @@ -2088,7 +2087,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) )); _smb_setlen(header,0); - transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); return(-1); } @@ -2098,7 +2097,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos )); _smb_setlen(header,0); - transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); return(-1); } } @@ -2167,7 +2166,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (ret < mincount) ret = 0; _smb_setlen(header,ret); - transfer_file(0,Client,0,header,4+ret,0); + transfer_file(0,smbd_server_fd(),0,header,4+ret,0); #endif /* UNSAFE_READRAW */ DEBUG(5,("readbraw finished\n")); @@ -2403,10 +2402,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CVAL(outbuf,smb_com) = SMBwritebraw; SSVALS(outbuf,smb_vwv0,-1); outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); /* Now read the raw data into the buffer and write it */ - if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) { + if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { exit_server("secondary writebraw failed"); } @@ -2419,7 +2418,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, (int)tcount,(int)nwritten,(int)numtowrite)); } - nwritten = vfs_transfer_file(Client, NULL, -1, fsp, + nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp, (SMB_OFF_T)numtowrite,NULL,0, startpos+nwritten); total_written += nwritten; @@ -3002,7 +3001,7 @@ int reply_echo(connection_struct *conn, smb_setlen(outbuf,outsize - 4); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); } DEBUG(3,("echo %d times\n", smb_reverb)); @@ -4346,7 +4345,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, SSVAL(outbuf,smb_vwv6,nread); SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); total_read += nread; startpos += nread; @@ -4437,7 +4436,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, if (write_through && tcount==nwritten) { /* we need to send both a primary and a secondary response */ smb_setlen(outbuf,outsize - 4); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); /* now the secondary */ outsize = set_message(outbuf,1,0,True); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 401c236374..576f6d14d2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -47,6 +47,26 @@ extern int dcelogin_atmost_once; extern fstring remote_machine; extern pstring OriginalDir; + +/* really we should have a top level context structure that has the + client file descriptor as an element. That would require a major rewrite :( + + the following 2 functions are an alternative - they make the file + descriptor private to smbd + */ +static int server_fd; + +int smbd_server_fd(void) +{ + return server_fd; +} + +void smbd_set_server_fd(int fd) +{ + server_fd = fd; + client_setfd(fd); +} + /**************************************************************************** when exiting, take the whole family ****************************************************************************/ @@ -70,18 +90,16 @@ static void killkids(void) ****************************************************************************/ static BOOL open_sockets_inetd(void) { - extern int Client; - /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ - Client = dup(0); + smbd_set_server_fd(dup(0)); /* close our standard file descriptors */ close_low_fds(); - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); + set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); + set_socket_options(smbd_server_fd(),user_socket_options); return True; } @@ -92,7 +110,6 @@ static BOOL open_sockets_inetd(void) ****************************************************************************/ static BOOL open_sockets(BOOL is_daemon,int port) { - extern int Client; int num_interfaces = iface_count(); int fd_listenset[FD_SETSIZE]; fd_set listen_set; @@ -211,18 +228,18 @@ max can be %d\n", } } - Client = accept(s,&addr,&in_addrlen); + smbd_set_server_fd(accept(s,&addr,&in_addrlen)); - if (Client == -1 && errno == EINTR) + if (smbd_server_fd() == -1 && errno == EINTR) continue; - if (Client == -1) { + if (smbd_server_fd() == -1) { DEBUG(0,("open_sockets: accept: %s\n", strerror(errno))); continue; } - if (Client != -1 && fork()==0) { + if (smbd_server_fd() != -1 && fork()==0) { /* Child code ... */ /* close the listening socket(s) */ @@ -234,8 +251,8 @@ max can be %d\n", close_low_fds(); am_parent = 0; - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); + set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); + set_socket_options(smbd_server_fd(),user_socket_options); /* Reset global variables in util.c so that client substitutions will be @@ -252,7 +269,7 @@ max can be %d\n", return True; } /* The parent doesn't need this socket */ - close(Client); + close(smbd_server_fd()); /* Force parent to check log size after * spawning child. Fix from @@ -320,10 +337,9 @@ BOOL reload_services(BOOL test) load_interfaces(); { - extern int Client; - if (Client != -1) { - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); + if (smbd_server_fd() != -1) { + set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); + set_socket_options(smbd_server_fd(),user_socket_options); } } @@ -776,7 +792,6 @@ static void usage(char *pname) exit(1); smbd_process(); - close_sockets(); exit_server("normal exit"); return(0); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 3abd55de0c..24ba79906b 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -195,7 +195,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int struct passwd *pass = NULL; BOOL guest = False; BOOL force = False; - extern int Client; connection_struct *conn; int ret; @@ -203,7 +202,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int snum = find_service(service); if (snum < 0) { - extern int Client; if (strequal(service,"IPC$")) { DEBUG(3,("refusing IPC connection\n")); *ecode = ERRnoipc; @@ -211,7 +209,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int } DEBUG(0,("%s (%s) couldn't find service %s\n", - remote_machine, client_addr(Client), service)); + remote_machine, client_addr(), service)); *ecode = ERRinvnetname; return NULL; } @@ -247,7 +245,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int } if (!lp_snum_ok(snum) || - !check_access(Client, + !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum))) { *ecode = ERRaccess; return NULL; @@ -342,7 +340,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->vuid = vuid; conn->uid = pass->pw_uid; conn->gid = pass->pw_gid; - safe_strcpy(conn->client_address, client_addr(Client), sizeof(conn->client_address)-1); + safe_strcpy(conn->client_address, client_addr(), sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = time(NULL); conn->service = snum; diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index be9aae7c5c..65d6532d48 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -248,20 +248,20 @@ char *reqHosts, *resignHosts; reqHosts = lp_ssl_hosts(); resignHosts = lp_ssl_hosts_resign(); - if(!allow_access(resignHosts, reqHosts, client_name(fd), client_addr(fd))){ + if(!allow_access(resignHosts, reqHosts, get_socket_name(fd), get_socket_addr(fd))){ sslEnabled = False; return 0; } if(msg_type != 0x81){ /* first packet must be a session request */ DEBUG( 0, ( "Client %s did not use session setup; access denied\n", - client_addr(fd) ) ); + client_addr() ) ); send_smb(fd, (char *)buf); return -1; } buf[4] = 0x8e; /* negative session response: use SSL */ send_smb(fd, (char *)buf); if(sslutil_accept(fd) != 0){ - DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr(fd) ) ); + DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr() ) ); return -1; } return 1; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f1fa30b0c6..2ca06ab746 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -27,7 +27,6 @@ extern int DEBUGLEVEL; extern int Protocol; extern BOOL case_sensitive; -extern int Client; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; @@ -66,7 +65,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, the empty packet */ if(params_to_send == 0 && data_to_send == 0) { - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); return 0; } @@ -161,7 +160,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, params_to_send, data_to_send, paramsize, datasize)); /* Send the packet */ - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); pp += params_sent_thistime; pd += data_sent_thistime; @@ -2288,7 +2287,7 @@ int reply_trans2(connection_struct *conn, /* We need to send an interim response then receive the rest of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); - send_smb(Client,outbuf); + send_smb(smbd_server_fd(),outbuf); while (num_data_sofar < total_data || num_params_sofar < total_params) { -- cgit From f6be38cae223f1ad3f4ecc5b81d14c44d92f58ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Apr 2000 19:44:54 +0000 Subject: include/byteorder.h: ALIGN4/ALIGN2 macros. include/includes.h: Added SMB_BIG_UINT_BITS. lib/util.c: Removed align2/align4 - use macros. libsmb/namequery.c: Use ALIGN2. locking/locking.c: Replace do_lock, do_unlock, args with SMB_BIG_UINT, not SMB_OFF_T. Needed to move to hiding POSIX locks at a lower layer. nmbd/nmbd_processlogon.c: Use ALIGN2/ALIGN4 macros. smbd/blocking.c: Replace do_lock, do_unlock, args with SMB_BIG_UINT, not SMB_OFF_T. smbd/reply.c: Replace do_lock, do_unlock, args with SMB_BIG_UINT, not SMB_OFF_T. Jeremy. (This used to be commit 491eea8a20bf80d426625479326211dc975857a6) --- source3/smbd/blocking.c | 12 ++-- source3/smbd/reply.c | 158 ++++++++++++++++-------------------------------- 2 files changed, 59 insertions(+), 111 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ea8d2fd053..ddf7de3f5b 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -193,7 +193,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec files_struct *fsp = blr->fsp; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - SMB_OFF_T count = (SMB_OFF_T) 0, offset = (SMB_OFF_T) 0; + SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; unsigned char locktype = CVAL(inbuf,smb_vwv3); BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; @@ -217,7 +217,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec uint32 dummy2; BOOL err; - count = get_lock_count( data, i, large_file_format, &err); + count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); /* @@ -278,7 +278,7 @@ static BOOL process_lockread(blocking_lock_record *blr) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fsp, conn, numtoread, startpos, READ_LOCK, &eclass, &ecode)) { + if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, READ_LOCK, &eclass, &ecode)) { if((errno != EACCES) && (errno != EAGAIN)) { /* * We have other than a "can't get lock" POSIX @@ -341,7 +341,7 @@ static BOOL process_lock(blocking_lock_record *blr) offset = IVAL(inbuf,smb_vwv3); errno = 0; - if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) { + if (!do_lock(fsp, conn, (SMB_BIG_UINT)count, (SMB_BIG_UINT)offset, WRITE_LOCK, &eclass, &ecode)) { if((errno != EACCES) && (errno != EAGAIN)) { /* @@ -389,7 +389,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); - SMB_OFF_T count = 0, offset = 0; + SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; int eclass=0; @@ -405,7 +405,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) for(; blr->lock_num < num_locks; blr->lock_num++) { BOOL err; - count = get_lock_count( data, blr->lock_num, large_file_format, &err); + count = get_lock_count( data, blr->lock_num, large_file_format); offset = get_lock_offset( data, blr->lock_num, large_file_format, &err); /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3ada28364b..96149acaa1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2108,7 +2108,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s maxcount = MIN(65535,maxcount); maxcount = MAX(mincount,maxcount); - if (!is_locked(fsp,conn,maxcount,startpos, READ_LOCK)) + if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { SMB_OFF_T size = fsp->size; SMB_OFF_T sizeneeded = startpos + maxcount; @@ -2206,7 +2206,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * for a write lock. JRA. */ - if(!do_lock( fsp, conn, numtoread, startpos, WRITE_LOCK, &eclass, &ecode)) { + if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up @@ -2260,7 +2260,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if (is_locked(fsp,conn,numtoread,startpos, READ_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) return(ERROR(ERRDOS,ERRlock)); if (numtoread > 0) @@ -2328,7 +2328,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,conn,smb_maxcnt,startpos, READ_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) return(ERROR(ERRDOS,ERRlock)); nread = read_file(fsp,data,startpos,smb_maxcnt); @@ -2383,7 +2383,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CVAL(inbuf,smb_com) = SMBwritec; CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,tcount,startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); if (numtowrite>0) @@ -2471,7 +2471,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); /* The special X/Open SMB protocol handling of @@ -2488,7 +2488,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode)) + if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) return(ERROR(eclass,ecode)); outsize = set_message(outbuf,1,0,True); @@ -2525,7 +2525,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); /* X/Open SMB protocol says that if smb_vwv1 is @@ -2604,7 +2604,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); /* X/Open SMB protocol says that, unlike SMBwrite @@ -2858,7 +2858,7 @@ int reply_writeclose(connection_struct *conn, mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); nwritten = write_file(fsp,data,startpos,numtowrite); @@ -2893,7 +2893,7 @@ int reply_lock(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); - SMB_OFF_T count,offset; + SMB_BIG_UINT count,offset; int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -2901,8 +2901,8 @@ int reply_lock(connection_struct *conn, CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); + count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); + offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fd, fsp->fnum, (double)offset, (double)count)); @@ -2930,7 +2930,7 @@ int reply_lock(connection_struct *conn, int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); - SMB_OFF_T count,offset; + SMB_BIG_UINT count,offset; int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -2938,8 +2938,8 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, in CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); + count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); + offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); @@ -3996,27 +3996,23 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size Get a lock count, dealing with large count requests. ****************************************************************************/ -SMB_OFF_T get_lock_count( char *data, int data_offset, BOOL large_file_format, BOOL *err) +SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format) { - SMB_OFF_T count = 0; - - *err = False; + SMB_BIG_UINT count = 0; if(!large_file_format) { - count = (SMB_OFF_T)IVAL(data,SMB_LKLEN_OFFSET(data_offset)); + count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset)); } else { -#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) - - count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset))); - -#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ +#if defined(HAVE_LONGLONG) + count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) | + ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset))); +#else /* HAVE_LONGLONG */ /* - * NT4.x seems to be broken in that it sends large file + * NT4.x seems to be broken in that it sends large file (64 bit) * lockingX calls even if the CAP_LARGE_FILES was *not* - * negotiated. For boxes without large file locks truncate the + * negotiated. For boxes without large unsigned ints truncate the * lock count by dropping the top 32 bits. */ @@ -4027,33 +4023,10 @@ SMB_OFF_T get_lock_count( char *data, int data_offset, BOOL large_file_format, B SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0); } - if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) { - /* - * Before we error out, see if we can sensibly map the top bits - * down to the lower bits - or lose the top bits if they are all 1's. - * It seems that NT has this horrible bug where it will send 64 bit - * lock requests even if told not to. JRA. - */ - - if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF) - count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)); - else if (IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF) - count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); - else { - - DEBUG(0,("get_lock_count: Error : a large file count (%x << 32 | %x) was sent and we don't \ -support large counts.\n", (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)), - (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) )); - - *err = True; - return (SMB_OFF_T)-1; - } - } - else - count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); - -#endif /* LARGE_SMB_OFF_T */ + count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); +#endif /* HAVE_LONGLONG */ } + return count; } @@ -4061,27 +4034,25 @@ support large counts.\n", (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(da Get a lock offset, dealing with large offset requests. ****************************************************************************/ -SMB_OFF_T get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err) +SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err) { - SMB_OFF_T offset = 0; + SMB_BIG_UINT offset = 0; *err = False; if(!large_file_format) { - offset = (SMB_OFF_T)IVAL(data,SMB_LKOFF_OFFSET(data_offset)); + offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset)); } else { -#if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) - - offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) | - ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset))); - -#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ +#if defined(HAVE_LONGLONG) + offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) | + ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset))); +#else /* HAVE_LONGLONG */ /* - * NT4.x seems to be broken in that it sends large file + * NT4.x seems to be broken in that it sends large file (64 bit) * lockingX calls even if the CAP_LARGE_FILES was *not* - * negotiated. For boxes without large file locks mangle the + * negotiated. For boxes without large unsigned ints mangle the * lock offset by mapping the top 32 bits onto the lower 32. */ @@ -4092,7 +4063,7 @@ SMB_OFF_T get_lock_offset( char *data, int data_offset, BOOL large_file_format, if((new_low = map_lock_offset(high, low)) == 0) { *err = True; - return (SMB_OFF_T)-1; + return (SMB_BIG_UINT)-1; } DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n", @@ -4101,33 +4072,10 @@ SMB_OFF_T get_lock_offset( char *data, int data_offset, BOOL large_file_format, SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low); } - if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0){ - /* - * Before we error out, see if we can sensibly map the top bits - * down to the lower bits - or lose the top bits if they are all 1's. - * It seems that NT has this horrible bug where it will send 64 bit - * lock requests even if told not to. JRA. - */ - - if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF) - offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)); - else if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF) - offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); - else { - - DEBUG(0,("get_lock_count: Error : a large file offset (%x << 32 | %x) was sent and we don't \ -support large offsets.\n", (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)), - (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) )); - - *err = True; - return (SMB_OFF_T)-1; - } - } - else - offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); - + offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); #endif /* LARGE_SMB_OFF_T */ } + return offset; } @@ -4144,14 +4092,14 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, #endif uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); - SMB_OFF_T count = 0, offset = 0; + SMB_BIG_UINT count = 0, offset = 0; int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; uint32 ecode=0, dummy2; int eclass=0, dummy1; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); - BOOL err1, err2; + BOOL err; CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -4202,13 +4150,13 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { - count = get_lock_count( data, i, large_file_format, &err1); - offset = get_lock_offset( data, i, large_file_format, &err2); + count = get_lock_count( data, i, large_file_format); + offset = get_lock_offset( data, i, large_file_format, &err); /* * There is no error code marked "stupid client bug".... :-). */ - if(err1 || err2) + if(err) return ERROR(ERRDOS,ERRnoaccess); DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", @@ -4228,13 +4176,13 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); of smb_lkrng structs */ for(i = 0; i < (int)num_locks; i++) { - count = get_lock_count( data, i, large_file_format, &err1); - offset = get_lock_offset( data, i, large_file_format, &err2); + count = get_lock_count( data, i, large_file_format); + offset = get_lock_offset( data, i, large_file_format, &err); /* * There is no error code marked "stupid client bug".... :-). */ - if(err1 || err2) + if(err) return ERROR(ERRDOS,ERRnoaccess); DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", @@ -4264,13 +4212,13 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); * will delete it (and we shouldn't) ..... */ for(i--; i >= 0; i--) { - count = get_lock_count( data, i, large_file_format, &err1); - offset = get_lock_offset( data, i, large_file_format, &err2); + count = get_lock_count( data, i, large_file_format); + offset = get_lock_offset( data, i, large_file_format, &err); /* * There is no error code marked "stupid client bug".... :-). */ - if(err1 || err2) + if(err) return ERROR(ERRDOS,ERRnoaccess); do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); @@ -4325,7 +4273,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,conn,maxcount,startpos, READ_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) return(ERROR(ERRDOS,ERRlock)); do @@ -4387,7 +4335,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,tcount,startpos,WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) return(ERROR(ERRDOS,ERRlock)); nwritten = write_file(fsp,data,startpos,numtowrite); -- cgit From 2311ecab4c8aa4026d2ac609f439b90834ff96e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Apr 2000 21:38:45 +0000 Subject: The latest open() code changes broke the NT directory opens. Detect if a read-only open on a directory was done and return an EISDIR from open_file(). Changed interface to fd_close to return error. Jeremy. (This used to be commit df4302f3911447fcebe9342f6cbf3b89bd3bafba) --- source3/smbd/close.c | 2 +- source3/smbd/open.c | 34 ++++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 61e8264159..4358f8fc2f 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -113,7 +113,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (lp_share_modes(SNUM(conn))) unlock_share_entry_fsp(fsp); - fd_close(fsp, &err); + err = fd_close(conn, fsp); /* NT uses smbclose to start a print - weird */ if (normal_close && fsp->print_file) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4c5605fb3b..02832308c6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -28,8 +28,9 @@ extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; /**************************************************************************** -fd support routines - attempt to do a dos_open + fd support routines - attempt to do a dos_open. ****************************************************************************/ + static int fd_open(struct connection_struct *conn, char *fname, int flags, mode_t mode) { @@ -42,21 +43,26 @@ static int fd_open(struct connection_struct *conn, char *fname, fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); } + DEBUG(10,("fd_open: name %s, mode = %d, fd = %d. %s\n", fname, (int)mode, fd, + (fd == -1) ? strerror(errno) : "" )); + return fd; } /**************************************************************************** -close the file associated with a fsp + Close the file associated with a fsp. ****************************************************************************/ -void fd_close(files_struct *fsp, int *err_ret) + +int fd_close(struct connection_struct *conn, files_struct *fsp) { - fsp->conn->vfs_ops.close(fsp->fd); + int ret = conn->vfs_ops.close(fsp->fd); fsp->fd = -1; + return ret; } /**************************************************************************** -check a filename for the pipe string + Check a filename for the pipe string. ****************************************************************************/ static void check_for_pipe(char *fname) @@ -73,7 +79,7 @@ static void check_for_pipe(char *fname) } /**************************************************************************** -open a file + Open a file. ****************************************************************************/ static void open_file(files_struct *fsp,connection_struct *conn, @@ -91,7 +97,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(fname,fname1); - /* check permissions */ + /* Check permissions */ /* * This code was changed after seeing a client open request @@ -121,7 +127,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, /* actually do the open */ fsp->fd = fd_open(conn, fname, flags, mode); - if (fsp->fd == -1) { + if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); check_for_pipe(fname); @@ -130,6 +136,18 @@ static void open_file(files_struct *fsp,connection_struct *conn, conn->vfs_ops.fstat(fsp->fd, &sbuf); + /* + * POSIX allows read-only opens of directories. We don't + * want to do this (we use a different code path for this) + * so catch a directory open and return an EISDIR. JRA. + */ + + if(S_ISDIR(sbuf.st_mode)) { + fd_close(conn, fsp); + errno = EISDIR; + return; + } + conn->num_files_open++; fsp->mode = sbuf.st_mode; fsp->inode = sbuf.st_ino; -- cgit From e1083ea7df16323e63efb6f752a6d5c6f0c4910e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2000 00:37:08 +0000 Subject: Roll back to using static MACHINE.SID after consultation with Andrew. This code will be removed soon and a SID auto-generated from (probably) primary hostname and never stored in a file will replace it. Jeremy. (This used to be commit fbfe94a799cda7f728bc920d4f0655d4f537e3b6) --- source3/smbd/server.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 576f6d14d2..00ea801cca 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -530,8 +530,6 @@ static void usage(char *pname) ****************************************************************************/ int main(int argc,char *argv[]) { - fstring sam_name; - extern BOOL append_log; /* shall I run as a daemon */ BOOL is_daemon = False; @@ -766,18 +764,7 @@ static void usage(char *pname) /* possibly reload the services file. */ reload_services(True); - /* obtain or create a SAM SID */ - if (lp_domain_logons()) - { - fstrcpy(sam_name, global_myworkgroup); - } - else - { - fstrcpy(sam_name, global_myname); - } - - if(!pdb_generate_sam_sid(sam_name, NULL)) - { + if(!pdb_generate_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } -- cgit From 8316237e9ca83d1bd0cecdc63d7e47b44cf13181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2000 17:59:09 +0000 Subject: Code to map tdb locks onto POSIX. Mainly placeholder code at the moment, but the structure is done enough so that Andrew can look it over and give a yea/nay decision. Jeremy. (This used to be commit db96f83e34a139f47776fcbb5c1624fbf9d9943b) --- source3/smbd/open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 02832308c6..1c5a7e26e2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -165,6 +165,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = False; fsp->stat_open = False; fsp->directory_delete_on_close = False; @@ -738,6 +739,7 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = False; fsp->stat_open = True; fsp->directory_delete_on_close = False; @@ -851,6 +853,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; -- cgit From 96b3bf3140a57c6adeaedd9f7ed427d207d47ee9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2000 21:46:22 +0000 Subject: Implmented mapping of lock offset/count from 64 bit MS ranges to either 63 or 31 bit POSIX ranges. Code to get these locks not yet added. Jeremy. (This used to be commit 9c3b9146a3baff4b2e403ae8fac6c48df1b7e642) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 96149acaa1..b280b07f7c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4073,7 +4073,7 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma } offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); -#endif /* LARGE_SMB_OFF_T */ +#endif /* HAVE_LONGLONG */ } return offset; -- cgit From ce5e230952c18b2308d0e41fff39f0bfdf2cc32b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Apr 2000 00:31:56 +0000 Subject: Log file check patch from Mattias Gronlund . Modified to do checks in timeout processing not in main loop. This (IMHO) is the correct place as (a) we are already root, and (b) it is guarenteed to be called every 200 smb requests. Jeremy. (This used to be commit c3794fd29fdc4e5a0dbd725cdc24fe210934caf2) --- source3/smbd/process.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2383b7a3a5..f378550282 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -970,6 +970,12 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); */ process_pending_change_notify_queue(t); + /* + * Now we are root, check if the log files need pruning. + */ + if(need_to_check_log_size()) + check_log_size(); + /* * Modify the select timeout depending upon * what we have remaining in our queues. -- cgit From 54de56a1be8ede7476c741cd1631ad1ac8107fcc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Apr 2000 06:22:31 +0000 Subject: the changes to the main smb code ------------ The following series of commits are for the new tdb based printing backend. This completely replaces our old printing backend. Major changes include: - all print ops are now done in printing/*.c rather than scattered all over the place - system job ids are decoupled from SMB job ids - the lpq parsers don't need to be nearly so smart, they only need to parse the filename, the status and system job id - we can store lots more info about a job, including the full job name - the queue cache control is much better I also added a new utility routine file_lines_load() that loads a text file and parses it into lines. This is used in out lpq parsing and I also want to use it to replace all of our fgets() based code in other places. (This used to be commit d870542c2884510bd45fd5b54ff2157434d53f4c) --- source3/smbd/close.c | 10 +- source3/smbd/fileio.c | 9 + source3/smbd/ipc.c | 639 +++++++++++++++++++++++--------------------------- source3/smbd/open.c | 2 +- source3/smbd/reply.c | 12 +- source3/smbd/server.c | 4 + 6 files changed, 318 insertions(+), 358 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4358f8fc2f..c4d323b1ba 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -100,6 +100,12 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) close_filestruct(fsp); + if (normal_close && fsp->print_file) { + print_fsp_end(fsp); + file_free(fsp); + return 0; + } + if (lp_share_modes(SNUM(conn))) { lock_share_entry_fsp(fsp); del_share_mode(fsp); @@ -115,10 +121,6 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) err = fd_close(conn, fsp); - /* NT uses smbclose to start a print - weird */ - if (normal_close && fsp->print_file) - print_file(conn, fsp); - /* check for magic scripts */ if (normal_close) { check_magic(fsp,conn); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 43fd091b49..5d8c3a9710 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -96,6 +96,11 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { ssize_t ret=0,readret; + /* you can't read from print files */ + if (fsp->print_file) { + return -1; + } + /* * Serve from write cache if we can. */ @@ -154,6 +159,10 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) ssize_t total_written = 0; int write_path = -1; + if (fsp->print_file) { + return print_job_write(fsp->print_jobid, data, n); + } + if (!fsp->can_write) { errno = EPERM; return(0); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 46ef677f38..5c923acd49 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -290,6 +290,9 @@ static int getlen(char* p) case 'W': /* word (2 byte) */ n += 2; break; + case 'K': /* status word? (2 byte) */ + n += 2; + break; case 'N': /* count of substructures (word) at end */ n += 2; break; @@ -385,6 +388,11 @@ va_dcl temp = va_arg(args,int); if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); break; + case 'K': /* status word? (2 byte) */ + needed = 2; + temp = va_arg(args,int); + if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); + break; case 'N': /* count of substructures (word) at end */ needed = 2; p->subcount = va_arg(args,int); @@ -474,7 +482,6 @@ static void PACKS(struct pack_desc* desc,char *t,char *v) /**************************************************************************** get a print queue ****************************************************************************/ - static void PackDriverData(struct pack_desc* desc) { char drivdata[4+4+32]; @@ -510,6 +517,9 @@ static int check_printq_info(struct pack_desc* desc, case 5: desc->format = "z"; break; + case 51: + desc->format = "K"; + break; case 52: desc->format = "WzzzzzzzzN"; desc->subformat = "z"; @@ -530,7 +540,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, /* the client expects localtime */ t -= TimeDiff(t); - PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */ + PACKI(desc,"W",queue->job); /* uJobId */ if (uLevel == 1) { PACKS(desc,"B21",queue->user); /* szUserName */ PACKS(desc,"B",""); /* pad */ @@ -568,171 +578,187 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, } } + +static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, + struct pack_desc* desc, + int count, print_queue_struct* queue, + print_status_struct* status) +{ + int i,ok=0; + pstring tok,driver,datafile,langmon,helpfile,datatype; + char *p,*q; + FILE *f; + pstring fname; + + pstrcpy(fname,lp_driverfile()); + f=sys_fopen(fname,"r"); + if (!f) { + DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno))); + desc->errcode=NERR_notsupported; + return; + } + + if((p=(char *)malloc(8192*sizeof(char))) == NULL) { + DEBUG(0,("fill_printq_info: malloc fail !\n")); + desc->errcode=NERR_notsupported; + fclose(f); + return; + } + + memset(p, '\0',8192*sizeof(char)); + q=p; + + /* lookup the long printer driver name in the file + description */ + while (f && !feof(f) && !ok) { + p = q; /* reset string pointer */ + fgets(p,8191,f); + p[strlen(p)-1]='\0'; + if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + ok=1; + } + fclose(f); + + /* driver file name */ + if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0; + /* data file name */ + if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0; + /* + * for the next tokens - which may be empty - I have + * to check for empty tokens first because the + * next_token function will skip all empty token + * fields */ + if (ok) { + /* help file */ + if (*p == ':') { + *helpfile = '\0'; + p++; + } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0; + } + + if (ok) { + /* language monitor */ + if (*p == ':') { + *langmon = '\0'; + p++; + } else if (!next_token(&p,langmon,":",sizeof(langmon))) + ok = 0; + } + + /* default data type */ + if (ok && !next_token(&p,datatype,":",sizeof(datatype))) + ok = 0; + + if (ok) { + PACKI(desc,"W",0x0400); /* don't know */ + PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ + PACKS(desc,"z",driver); /* Driverfile Name */ + PACKS(desc,"z",datafile); /* Datafile name */ + PACKS(desc,"z",langmon); /* language monitor */ + PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ + PACKS(desc,"z",datatype); /* default data type */ + PACKS(desc,"z",helpfile); /* helpfile name */ + PACKS(desc,"z",driver); /* driver name */ + DEBUG(3,("Driver:%s:\n",driver)); + DEBUG(3,("Data File:%s:\n",datafile)); + DEBUG(3,("Language Monitor:%s:\n",langmon)); + DEBUG(3,("Data Type:%s:\n",datatype)); + DEBUG(3,("Help File:%s:\n",helpfile)); + PACKI(desc,"N",count); /* number of files to copy */ + for (i=0;i gave %d entries\n", + SERVICE(snum),count)); + } else { + DEBUG(3,("fill_printq_info: Can't supply driver files\n")); + desc->errcode=NERR_notsupported; + } + free(q); +} + + static void fill_printq_info(connection_struct *conn, int snum, int uLevel, struct pack_desc* desc, int count, print_queue_struct* queue, print_status_struct* status) { - switch (uLevel) { - case 1: - case 2: - PACKS(desc,"B13",SERVICE(snum)); - break; - case 3: - case 4: - case 5: - PACKS(desc,"z",Expand(conn,snum,SERVICE(snum))); - break; - } - - if (uLevel == 1 || uLevel == 2) { - PACKS(desc,"B",""); /* alignment */ - PACKI(desc,"W",5); /* priority */ - PACKI(desc,"W",0); /* start time */ - PACKI(desc,"W",0); /* until time */ - PACKS(desc,"z",""); /* pSepFile */ - PACKS(desc,"z","lpd"); /* pPrProc */ - PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ - PACKS(desc,"z",""); /* pParms */ - if (snum < 0) { - PACKS(desc,"z","UNKNOWN PRINTER"); - PACKI(desc,"W",LPSTAT_ERROR); - } - else if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); - PACKI(desc,"W",LPSTAT_OK); /* status */ - } else { - PACKS(desc,"z",status->message); - PACKI(desc,"W",status->status); /* status */ - } - PACKI(desc,(uLevel == 1 ? "W" : "N"),count); - } - if (uLevel == 3 || uLevel == 4) { - PACKI(desc,"W",5); /* uPriority */ - PACKI(desc,"W",0); /* uStarttime */ - PACKI(desc,"W",0); /* uUntiltime */ - PACKI(desc,"W",5); /* pad1 */ - PACKS(desc,"z",""); /* pszSepFile */ - PACKS(desc,"z","WinPrint"); /* pszPrProc */ - PACKS(desc,"z",""); /* pszParms */ - if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */ - PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ - } else { - PACKS(desc,"z",status->message); /* pszComment */ - PACKI(desc,"W",status->status); /* fsStatus */ - } - PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ - PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - } - if (uLevel == 2 || uLevel == 4) { - int i; - for (i=0;ierrcode=NERR_notsupported; - return; - } - - if((p=(char *)malloc(8192*sizeof(char))) == NULL) { - DEBUG(0,("fill_printq_info: malloc fail !\n")); - desc->errcode=NERR_notsupported; - fclose(f); - return; - } - - memset(p, '\0',8192*sizeof(char)); - q=p; - - /* lookup the long printer driver name in the file description */ - while (f && !feof(f) && !ok) - { - p = q; /* reset string pointer */ - fgets(p,8191,f); - p[strlen(p)-1]='\0'; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok=1; - } - fclose(f); + switch (uLevel) { + case 1: + case 2: + PACKS(desc,"B13",SERVICE(snum)); + break; + case 3: + case 4: + case 5: + PACKS(desc,"z",Expand(conn,snum,SERVICE(snum))); + break; + case 51: + PACKI(desc,"K",status->status); + break; + } - /* driver file name */ - if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0; - /* data file name */ - if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0; - /* - * for the next tokens - which may be empty - I have to check for empty - * tokens first because the next_token function will skip all empty - * token fields - */ - if (ok) { - /* help file */ - if (*p == ':') { - *helpfile = '\0'; - p++; - } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0; - } + if (uLevel == 1 || uLevel == 2) { + PACKS(desc,"B",""); /* alignment */ + PACKI(desc,"W",5); /* priority */ + PACKI(desc,"W",0); /* start time */ + PACKI(desc,"W",0); /* until time */ + PACKS(desc,"z",""); /* pSepFile */ + PACKS(desc,"z","lpd"); /* pPrProc */ + PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ + PACKS(desc,"z",""); /* pParms */ + if (snum < 0) { + PACKS(desc,"z","UNKNOWN PRINTER"); + PACKI(desc,"W",LPSTAT_ERROR); + } + else if (!status || !status->message[0]) { + PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); + PACKI(desc,"W",LPSTAT_OK); /* status */ + } else { + PACKS(desc,"z",status->message); + PACKI(desc,"W",status->status); /* status */ + } + PACKI(desc,(uLevel == 1 ? "W" : "N"),count); + } - if (ok) { - /* language monitor */ - if (*p == ':') { - *langmon = '\0'; - p++; - } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0; - } + if (uLevel == 3 || uLevel == 4) { + PACKI(desc,"W",5); /* uPriority */ + PACKI(desc,"W",0); /* uStarttime */ + PACKI(desc,"W",0); /* uUntiltime */ + PACKI(desc,"W",5); /* pad1 */ + PACKS(desc,"z",""); /* pszSepFile */ + PACKS(desc,"z","WinPrint"); /* pszPrProc */ + PACKS(desc,"z",""); /* pszParms */ + if (!status || !status->message[0]) { + PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */ + PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ + } else { + PACKS(desc,"z",status->message); /* pszComment */ + PACKI(desc,"W",status->status); /* fsStatus */ + } + PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ + PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ + PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ + PackDriverData(desc); /* pDriverData */ + } - /* default data type */ - if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0; - - if (ok) { - PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ - PACKS(desc,"z",driver); /* Driverfile Name */ - PACKS(desc,"z",datafile); /* Datafile name */ - PACKS(desc,"z",langmon); /* language monitor */ - PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ - PACKS(desc,"z",datatype); /* default data type */ - PACKS(desc,"z",helpfile); /* helpfile name */ - PACKS(desc,"z",driver); /* driver name */ - DEBUG(3,("Driver:%s:\n",driver)); - DEBUG(3,("Data File:%s:\n",datafile)); - DEBUG(3,("Language Monitor:%s:\n",langmon)); - DEBUG(3,("Data Type:%s:\n",datatype)); - DEBUG(3,("Help File:%s:\n",helpfile)); - PACKI(desc,"N",count); /* number of files to copy */ - for (i=0;i gave %d entries\n", - SERVICE(snum),count)); - } else { - DEBUG(3,("fill_printq_info: Can't supply driver files\n")); - desc->errcode=NERR_notsupported; - } - free(q); - } + if (uLevel==52) { + fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status); + } } /* This function returns the number of files for a given driver */ @@ -852,7 +878,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, count = get_printerdrivernumber(snum); DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); } else { - count = get_printqueue(snum, conn,&queue,&status); + count = print_queue_status(snum, &queue,&status); } if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); @@ -963,7 +989,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, n = 0; for (i = 0; i < services; i++) if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]); + subcntarr[n] = print_queue_status(i, &queue[n],&status[n]); subcnt += subcntarr[n]; n++; } @@ -1842,60 +1868,46 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int jobid, snum; - int i, count; - - printjob_decode(SVAL(p,0), &snum, &jobid); - - /* check it's a supported varient */ - if (!(strcsequal(str1,"W") && strcsequal(str2,""))) - return(False); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + int function = SVAL(param,0); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int jobid, errcode; - *rdata_len = 0; + jobid = SVAL(p,0); - SSVAL(*rparam,0,NERR_Success); + /* check it's a supported varient */ + if (!(strcsequal(str1,"W") && strcsequal(str2,""))) + return(False); - if (snum >= 0 && VALID_SNUM(snum)) - { - print_queue_struct *queue=NULL; - lpq_reset(snum); - count = get_printqueue(snum,conn,&queue,NULL); - - for (i=0;i= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } + switch (function) { + case 74: /* Pause queue */ + if (print_queue_pause(snum)) errcode = NERR_Success; + break; + case 75: /* Resume queue */ + if (print_queue_resume(snum)) errcode = NERR_Success; + break; + case 103: /* Purge */ + if (print_queue_purge(snum)) errcode = NERR_Success; + break; + } - if (snum >= 0 && VALID_SNUM(snum)) { - lpq_reset(snum); - - switch (function) { - case 74: /* Pause queue */ - case 75: /* Resume queue */ - status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK)); - DEBUG(3,("Print queue %s, queue=%s\n", - (function==74?"pause":"resume"),QueueName)); - break; - case 103: /* Purge */ - { - print_queue_struct *queue=NULL; - int i, count; - count = get_printqueue(snum,conn,&queue,NULL); - for (i = 0; i < count; i++) - del_printqueue(conn,snum,queue[i].job); - - if (queue) free(queue); - DEBUG(3,("Print queue purge, queue=%s\n",QueueName)); - break; - } - } - } + out: + SSVAL(*rparam,0,errcode); + SSVAL(*rparam,2,0); /* converter word */ - return(True); + return(True); } @@ -1972,16 +1970,16 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para static int check_printjob_info(struct pack_desc* desc, int uLevel, char* id) { - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "W"; break; - case 1: desc->format = "WB21BB16B10zWWzDDz"; break; - case 2: desc->format = "WWzWWDDzz"; break; - case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; + desc->subformat = NULL; + switch( uLevel ) { + case 0: desc->format = "W"; break; + case 1: desc->format = "WB21BB16B10zWWzDDz"; break; + case 2: desc->format = "WWzWWDDzz"; break; + case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; + default: return False; + } + if (strcmp(desc->format,id) != 0) return False; + return True; } static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data, @@ -1993,15 +1991,12 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int jobid, snum; + int jobid; int uLevel = SVAL(p,2); - int function = SVAL(p,4); /* what is this ?? */ - int i; - char *s = data; - files_struct *fsp; + int function = SVAL(p,4); + int place, errcode; - printjob_decode(SVAL(p,0), &snum, &jobid); - + jobid = SVAL(p,0); *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); @@ -2011,87 +2006,37 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2))) return(False); - + + if (!print_job_exists(jobid)) { + errcode=NERR_JobNotFound; + goto out; + } + + errcode = NERR_notsupported; + switch (function) { - case 0x6: /* change job place in the queue, - data gives the new place */ - if (snum >= 0 && VALID_SNUM(snum)) { - print_queue_struct *queue=NULL; - int count; - - lpq_reset(snum); - count = get_printqueue(snum,conn,&queue,NULL); - for (i=0;i place ) /* move up */; - } -#endif - desc.errcode=NERR_notsupported; /* not yet - supported */ - if (queue) free(queue); - } - } else { - desc.errcode=NERR_JobNotFound; + case 0x6: + /* change job place in the queue, + data gives the new place */ + place = SVAL(data,0); + if (print_job_set_place(jobid, place)) { + errcode=NERR_Success; } break; - case 0xb: /* change print job name, data gives the name */ - /* jobid, snum should be zero */ - if (isalpha((int)*s)) { - pstring name; - int l = 0; - - while (l<64 && *s) { - if (issafe(*s)) name[l++] = *s; - s++; - } - name[l] = 0; - - DEBUG(3,("Setting print name to %s\n",name)); - - fsp = file_find_print(); - - if (fsp) { - pstring zfrom,zto; - connection_struct *fconn = fsp->conn; - - unbecome_user(); - - if (!become_user(fconn,vuid) || - !become_service(fconn,True)) - break; - - pstrcpy(zfrom, dos_to_unix(fsp->fsp_name,False)); - pstrcpy(zto, dos_to_unix(name,False)); - - if (fsp->conn->vfs_ops.rename(zfrom,zto) == 0) { - string_set(&fsp->fsp_name,name); - } - - break; - } + case 0xb: + /* change print job name, data gives the name */ + if (print_job_set_name(jobid, data)) { + errcode=NERR_Success; } - desc.errcode=NERR_Success; break; - default: /* not implemented */ + default: return False; } - - SSVALS(*rparam,0,desc.errcode); + + out: + SSVALS(*rparam,0,errcode); SSVAL(*rparam,2,0); /* converter word */ return(True); @@ -2793,13 +2738,13 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para if (strcmp(str1,"WWrLh") != 0) return False; if (!check_printjob_info(&desc,uLevel,str2)) return False; - printjob_decode(SVAL(p,0), &snum, &job); + job = SVAL(p,0); if (snum < 0 || !VALID_SNUM(snum)) return(False); - count = get_printqueue(snum,conn,&queue,&status); + count = print_queue_status(snum,&queue,&status); for (i = 0; i < count; i++) { - if ((queue[i].job & 0xFF) == job) break; + if (queue[i].job == job) break; } if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; @@ -2869,7 +2814,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa if (snum < 0 || !VALID_SNUM(snum)) return(False); - count = get_printqueue(snum,conn,&queue,&status); + count = print_queue_status(snum,&queue,&status); if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1c5a7e26e2..bd8e860a17 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -413,7 +413,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int ignored */ *Access = DOS_OPEN_WRONLY; *action = FILE_WAS_CREATED; - print_open_file(fsp, conn, fname); + print_fsp_open(fsp, conn, fname); return; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b280b07f7c..e998e1741c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -393,6 +393,7 @@ int reply_ioctl(connection_struct *conn, uint32 ioctl_code = (device << 16) + function; int replysize, outsize; char *p; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); @@ -413,8 +414,8 @@ int reply_ioctl(connection_struct *conn, switch (ioctl_code) { - case IOCTL_QUERY_JOB_INFO: - SSVAL(p,0,1); /* Job number */ + case IOCTL_QUERY_JOB_INFO: + SSVAL(p,0,fsp->print_jobid); /* Job number */ StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */ StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */ break; @@ -3029,7 +3030,7 @@ int reply_printopen(connection_struct *conn, return(ERROR(ERRSRV,ERRnofids)); /* Open for exclusive use, write only. */ - print_open_file(fsp,conn,"dos.prn"); + print_fsp_open(fsp,conn,"dos.prn"); if (!fsp->open) { file_free(fsp); @@ -3104,7 +3105,7 @@ int reply_printqueue(connection_struct *conn, { print_queue_struct *queue = NULL; char *p = smb_buf(outbuf) + 3; - int count = get_printqueue(SNUM(conn), conn,&queue,NULL); + int count = print_queue_status(SNUM(conn), &queue,NULL); int num_to_get = ABS(max_count); int first = (max_count>0?start_index:start_index+max_count+1); int i; @@ -3118,8 +3119,7 @@ int reply_printqueue(connection_struct *conn, for (i=first;i Date: Sun, 16 Apr 2000 07:28:36 +0000 Subject: added helper fns to change from internal status codes to nt spoolss codes (This used to be commit 8af879b3f513e7e8ca5f63848d22824b05e68398) --- source3/smbd/ipc.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 5c923acd49..055b8344bb 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -531,6 +531,42 @@ static int check_printq_info(struct pack_desc* desc, return True; } +/* turn a print job status into a on the wire status + right now these are complete guesses - need to fill them in (tridge) +*/ +static int printj_status(int v) +{ + switch (v) { + case LPQ_QUEUED: + return 0; + case LPQ_PAUSED: + return 1; + case LPQ_SPOOLING: + return 2; + case LPQ_PRINTING: + return 3; + } + return 4; +} + +/* turn a print queue status into a on the wire status + right now these are complete guesses - need to fill them in (tridge) +*/ +static int printq_status(int v) +{ + switch (v) { + case LPQ_QUEUED: + return 0; + case LPQ_PAUSED: + return 1; + case LPQ_SPOOLING: + return 2; + case LPQ_PRINTING: + return 3; + } + return 4; +} + static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, struct pack_desc* desc, print_queue_struct* queue, int n) @@ -548,7 +584,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ PACKS(desc,"z",""); /* pszParms */ PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",queue->status); /* fsStatus */ + PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ PACKS(desc,"z",""); /* pszStatus */ PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ @@ -558,7 +594,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKI(desc,"W",queue->priority); /* uPriority */ PACKS(desc,"z",queue->user); /* pszUserName */ PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",queue->status); /* fsStatus */ + PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z","Samba"); /* pszComment */ @@ -702,7 +738,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z",Expand(conn,snum,SERVICE(snum))); break; case 51: - PACKI(desc,"K",status->status); + PACKI(desc,"K",printq_status(status->status)); break; } @@ -724,7 +760,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, PACKI(desc,"W",LPSTAT_OK); /* status */ } else { PACKS(desc,"z",status->message); - PACKI(desc,"W",status->status); /* status */ + PACKI(desc,"W",printq_status(status->status)); /* status */ } PACKI(desc,(uLevel == 1 ? "W" : "N"),count); } @@ -742,7 +778,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ } else { PACKS(desc,"z",status->message); /* pszComment */ - PACKI(desc,"W",status->status); /* fsStatus */ + PACKI(desc,"W",printq_status(status->status)); /* fsStatus */ } PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ -- cgit From 2c80622a946a0e2ffe4b4b4ad3d3f5a203bdb0f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Apr 2000 07:38:45 +0000 Subject: use some symbolic names for print queue status (This used to be commit e8418ab73667e011b15e00a844240723ff4a8cd6) --- source3/smbd/ipc.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 055b8344bb..4f87d632d2 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -531,6 +531,16 @@ static int check_printq_info(struct pack_desc* desc, return True; } + +#define JOB_STATUS_QUEUED 0 +#define JOB_STATUS_PAUSED 1 +#define JOB_STATUS_SPOOLING 2 +#define JOB_STATUS_PRINTING 3 +#define JOB_STATUS_PRINTED 4 + +#define QUEUE_STATUS_PAUSED 1 +#define QUEUE_STATUS_ERROR 2 + /* turn a print job status into a on the wire status right now these are complete guesses - need to fill them in (tridge) */ @@ -538,15 +548,15 @@ static int printj_status(int v) { switch (v) { case LPQ_QUEUED: - return 0; + return JOB_STATUS_QUEUED; case LPQ_PAUSED: - return 1; + return JOB_STATUS_PAUSED; case LPQ_SPOOLING: - return 2; + return JOB_STATUS_SPOOLING; case LPQ_PRINTING: - return 3; + return JOB_STATUS_PRINTING; } - return 4; + return 0; } /* turn a print queue status into a on the wire status @@ -558,13 +568,9 @@ static int printq_status(int v) case LPQ_QUEUED: return 0; case LPQ_PAUSED: - return 1; - case LPQ_SPOOLING: - return 2; - case LPQ_PRINTING: - return 3; + return QUEUE_STATUS_PAUSED; } - return 4; + return QUEUE_STATUS_ERROR; } static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, -- cgit From d79a8c68d6ea2288dc8574f994bb281c2a784cf8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Apr 2000 08:04:06 +0000 Subject: removed old comments (This used to be commit 9f49d17d4cf904034ce3718626450dc25541b420) --- source3/smbd/ipc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 4f87d632d2..205d00b803 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -542,7 +542,6 @@ static int check_printq_info(struct pack_desc* desc, #define QUEUE_STATUS_ERROR 2 /* turn a print job status into a on the wire status - right now these are complete guesses - need to fill them in (tridge) */ static int printj_status(int v) { @@ -560,7 +559,6 @@ static int printj_status(int v) } /* turn a print queue status into a on the wire status - right now these are complete guesses - need to fill them in (tridge) */ static int printq_status(int v) { -- cgit From 19f946ba6fe442544ac9b0f71bcd33112fc79995 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Apr 2000 11:00:21 +0000 Subject: converted a bunch more functions to use a fd instead of a FILE* to support some of this I added the following functions in util_file.c file_lines_pload : load lines from a pipe file_pload : load a pipe into memory (This used to be commit a09470817c5b21dba42f9ef4ce5e8b768a254c0b) --- source3/smbd/dfree.c | 20 ++++--- source3/smbd/ipc.c | 150 ++++++++++++++++++++------------------------------- 2 files changed, 68 insertions(+), 102 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 0a892bad05..eff718b148 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -203,24 +203,22 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, (*dfree) = (*dsize) = 0; (*bsize) = 512; - /* * If external disk calculation specified, use it. */ dfree_command = lp_dfree_command(); if (dfree_command && *dfree_command) { - pstring line; char *p; - FILE *pp; + char **lines; + pstring syscmd; - slprintf (line, sizeof(pstring) - 1, "%s %s", dfree_command, path); - DEBUG (3, ("disk_free: Running command %s\n", line)); + slprintf(syscmd, sizeof(syscmd), "%s %s", dfree_command, path); + DEBUG (3, ("disk_free: Running command %s\n", syscmd)); - pp = sys_popen(line, "r", False); - if (pp) { - fgets(line, sizeof(pstring), pp); - line[sizeof(pstring)-1] = '\0'; + lines = file_lines_pload(syscmd, NULL); + if (lines) { + char *line = lines[0]; if (strlen(line) > 0) line[strlen(line)-1] = '\0'; @@ -237,7 +235,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, *bsize = (SMB_BIG_UINT)strtoul(p, NULL, 10); else *bsize = 1024; - sys_pclose (pp); + file_lines_free(lines); DEBUG (3, ("Parsed output of dfree, dsize=%u, dfree=%u, bsize=%u\n", (unsigned int)*dsize, (unsigned int)*dfree, (unsigned int)*bsize)); @@ -247,7 +245,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, *dfree = 1024; } else { DEBUG (0, ("disk_free: sys_popen() failed for command %s. Error was : %s\n", - line, strerror(errno) )); + syscmd, strerror(errno) )); fsusage(path, dfree, dsize); } } else diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 205d00b803..17aa83b72b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -626,40 +626,29 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, { int i,ok=0; pstring tok,driver,datafile,langmon,helpfile,datatype; - char *p,*q; - FILE *f; - pstring fname; + char *p; + char **lines, *line; - pstrcpy(fname,lp_driverfile()); - f=sys_fopen(fname,"r"); - if (!f) { - DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno))); + lines = file_lines_load(lp_driverfile(),NULL); + if (!lines) { + DEBUG(3,("fill_printq_info: Can't open %s - %s\n", + lp_driverfile(),strerror(errno))); desc->errcode=NERR_notsupported; return; } - if((p=(char *)malloc(8192*sizeof(char))) == NULL) { - DEBUG(0,("fill_printq_info: malloc fail !\n")); - desc->errcode=NERR_notsupported; - fclose(f); - return; - } - - memset(p, '\0',8192*sizeof(char)); - q=p; - /* lookup the long printer driver name in the file description */ - while (f && !feof(f) && !ok) { - p = q; /* reset string pointer */ - fgets(p,8191,f); - p[strlen(p)-1]='\0'; + for (i=0;lines[i] && !ok;i++) { + p = lines[i]; if (next_token(&p,tok,":",sizeof(tok)) && (strlen(lp_printerdriver(snum)) == strlen(tok)) && (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) ok=1; } - fclose(f); + line = strdup(p); + p = line; + file_lines_free(lines); /* driver file name */ if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0; @@ -722,7 +711,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, DEBUG(3,("fill_printq_info: Can't supply driver files\n")); desc->errcode=NERR_notsupported; } - free(q); + free(line); } @@ -804,56 +793,45 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, /* This function returns the number of files for a given driver */ static int get_printerdrivernumber(int snum) { - int i=0,ok=0; - pstring tok; - char *p,*q; - FILE *f; - pstring fname; - - pstrcpy(fname,lp_driverfile()); - - DEBUG(4,("In get_printerdrivernumber: %s\n",fname)); - f=sys_fopen(fname,"r"); - if (!f) { - DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno))); - return(0); - } - - if((p=(char *)malloc(8192*sizeof(char))) == NULL) { - DEBUG(3,("get_printerdrivernumber: malloc fail !\n")); - fclose(f); - return 0; - } - - q=p; /* need it to free memory because p change ! */ - - /* lookup the long printer driver name in the file description */ - while (!feof(f) && !ok) - { - p = q; /* reset string pointer */ - fgets(p,8191,f); - if (next_token(&p,tok,":",sizeof(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok=1; - } - fclose(f); - - if (ok) { - /* skip 5 fields */ - i = 5; - while (*p && i) { - if (*p++ == ':') i--; - } - if (!*p || i) - return(0); + int i=0,ok=0; + pstring tok; + char *p; + char **lines, *line; - /* count the number of files */ - while (next_token(&p,tok,",",sizeof(tok))) - i++; - } - free(q); - - return(i); + lines = file_lines_load(lp_driverfile(), NULL); + if (!lines) { + DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n", + lp_driverfile(),strerror(errno))); + return(0); + } + + /* lookup the long printer driver name in the file description */ + for (i=0;lines[i] && !ok; i++) { + p = lines[i]; + if (next_token(&p,tok,":",sizeof(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + ok=1; + } + line = strdup(p); + p = line; + file_lines_free(lines); + + if (ok) { + /* skip 5 fields */ + i = 5; + while (*p && i) { + if (*p++ == ':') i--; + } + if (!*p || i) + return(0); + + /* count the number of files */ + while (next_token(&p,tok,",",sizeof(tok))) + i++; + } + free(line); + + return(i); } static BOOL api_DosPrintQGetInfo(connection_struct *conn, @@ -1105,22 +1083,15 @@ static int get_server_info(uint32 servertype, struct srv_info_struct **servers, char *domain) { - FILE *f; - pstring fname; int count=0; int alloced=0; - pstring line; + char **lines; BOOL local_list_only; + int i; - pstrcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - pstrcat(fname,"/"); - pstrcat(fname,SERVER_LIST); - - f = sys_fopen(fname,"r"); - - if (!f) { - DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno))); + lines = file_lines_load(lock_path(SERVER_LIST), NULL); + if (!lines) { + DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); return(0); } @@ -1132,16 +1103,13 @@ static int get_server_info(uint32 servertype, DEBUG(4,("Servertype search: %8x\n",servertype)); - while (!feof(f)) - { + for (i=0;lines[i];i++) { fstring stype; struct srv_info_struct *s; - char *ptr = line; + char *ptr = lines[i]; BOOL ok = True; - *ptr = 0; - fgets(line,sizeof(line)-1,f); - if (!*line) continue; + if (!*ptr) continue; if (count == alloced) { alloced += 10; @@ -1209,7 +1177,7 @@ static int get_server_info(uint32 servertype, } } - fclose(f); + file_lines_free(lines); return(count); } -- cgit From 8d7e498db160f9a366400fc1c55dacbcffaf4196 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Apr 2000 11:17:19 +0000 Subject: converted a couple more functions to use a fd instead of a FILE* added a new utility fn file_lines_slashcont() which is used to handle files that treat a \ followed by a newline as a blank (This used to be commit 384ecd9d66ccd31ee85000c0ca55d413d8f2cc53) --- source3/smbd/groupname.c | 15 ++++++++------- source3/smbd/password.c | 17 +++++++++-------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 4dadfaa939..fcbf5dd778 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -71,9 +71,8 @@ void load_groupname_map(void) static BOOL initialized = False; char *groupname_map_file = lp_groupname_map(); SMB_STRUCT_STAT st; - FILE *fp; - char *s; - pstring buf; + char **lines; + int i; groupname_map_entry *new_ep; if(!initialized) { @@ -102,12 +101,13 @@ void load_groupname_map(void) * Load the file. */ - fp = sys_fopen(groupname_map_file,"r"); - if (!fp) { + lines = file_lines_load(groupname_map_file,NULL); + if (!lines) { DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n", groupname_map_file, strerror(errno))); return; } + file_lines_slashcont(lines); /* * Throw away any previous list. @@ -116,11 +116,12 @@ void load_groupname_map(void) DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file)); - while((s=fgets_slash(buf,sizeof(buf),fp))!=NULL) { + for (i=0; lines[i]; i++) { pstring unixname; pstring windows_name; struct group *gptr; DOM_SID tmp_sid; + char *s = lines[i]; DEBUG(10,("load_groupname_map: Read line |%s|\n", s)); @@ -202,7 +203,7 @@ Error was %s.\n", unixname, strerror(errno) )); DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n", ubi_slCount(&groupname_map_list))); - fclose(fp); + file_lines_free(lines); } /*********************************************************** diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 208dbd2bff..f92d31718c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -828,15 +828,16 @@ allows this user from this machine ****************************************************************************/ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) { - pstring buf; int plus_allowed = 1; char *file_host; char *file_user; - FILE *fp = sys_fopen(equiv_file, "r"); + char **lines = file_lines_load(equiv_file, NULL); + int i; + DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); - if (! fp) return False; - while(fgets(buf, sizeof(buf), fp)) - { + if (! lines) return False; + for (i=0; lines[i]; i++) { + char *buf = lines[i]; trim_string(buf," "," "); if (buf[0] != '#' && buf[0] != '\n') @@ -857,7 +858,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) { /* a bare plus means everbody allowed */ DEBUG(6, ("check_user_equiv everybody allowed\n")); - fclose(fp); + file_lines_free(lines); return True; } } @@ -912,17 +913,17 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) /* is it this user */ if (file_user == 0 || strequal(user, file_user)) { - fclose(fp); DEBUG(5, ("check_user_equiv matched %s%s %s\n", (plus ? "+" : "-"), file_host, (file_user ? file_user : ""))); + file_lines_free(lines); return (plus ? True : False); } } } } } - fclose(fp); + file_lines_free(lines); return False; } -- cgit From 9ff032320da86c88b481f68886cdda713ed136fa Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 18 Apr 2000 02:09:50 +0000 Subject: ReadDirName calls vfs->readdirname calls dos_readdirname. replaced with readdirname. ditto for OpenDir and CloseDir. (This used to be commit a0afe0d5f8378463b1e47cd779aee3af98c1940a) --- source3/smbd/chgpasswd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 4131ae61ca..df1f92f5ce 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -57,7 +57,7 @@ static int findpty(char **slave) { int master; static fstring line; - void *dirp; + DIR *dirp; char *dpname; #if defined(HAVE_GRANTPT) @@ -86,10 +86,10 @@ static int findpty(char **slave) fstrcpy(line, "/dev/ptyXX"); - dirp = OpenDir(NULL, "/dev", False); + dirp = opendir("/dev"); if (!dirp) return (-1); - while ((dpname = ReadDirName(dirp)) != NULL) + while ((dpname = readdirname(dirp)) != NULL) { if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { @@ -103,12 +103,12 @@ static int findpty(char **slave) DEBUG(3, ("pty: opened %s\n", line)); line[5] = 't'; *slave = line; - CloseDir(dirp); + closedir(dirp); return (master); } } } - CloseDir(dirp); + closedir(dirp); return (-1); } -- cgit From 4217c939ec6bdb80a3fe953e5b60f6f7b7a43635 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Apr 2000 20:41:04 +0000 Subject: locking/locking.c: Fixed placeholder code for POSIX locking. printing/printing.c: Cast tdb_delete to (tdb_traverse_func) to stop warning. tmpfile gives mirror warning. smbd/groupname.c: Remember to file_lines_free() on exit. tdb/tdb.h: Add tdb_traverse_func typedef. Jeremy (This used to be commit 204ca1195c86499bd9beb273ce573db7a56ccead) --- source3/smbd/groupname.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index fcbf5dd778..f0b11e1b36 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -193,6 +193,7 @@ Error was %s.\n", unixname, strerror(errno) )); if(new_ep->unix_name != NULL) free(new_ep->unix_name); free((char *)new_ep); + file_lines_free(lines); return; } memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) ); -- cgit From 612682354fa978d7b883028b3aace52a2882adca Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Apr 2000 04:01:16 +0000 Subject: - got rid of the "passive" option - cleaned up the standard_sub_*() calls a lot (This used to be commit 2c2d95d77d3667eaa9252506a82b9054b0d0e01c) --- source3/smbd/ipc.c | 14 +++++++------- source3/smbd/server.c | 10 +--------- source3/smbd/service.c | 10 +++++----- 3 files changed, 13 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 17aa83b72b..64ec05b017 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -80,7 +80,7 @@ static int CopyExpanded(connection_struct *conn, StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub(conn,buf); + standard_sub_conn(conn,buf); StrnCpy(*dst,buf,*n); l = strlen(*dst) + 1; (*dst) += l; @@ -105,7 +105,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char* s) if (!s) return(0); StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub(conn,buf); + standard_sub_conn(conn,buf); return strlen(buf) + 1; } @@ -115,7 +115,7 @@ static char* Expand(connection_struct *conn, int snum, char* s) if (!s) return(NULL); StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub(conn,buf); + standard_sub_conn(conn,buf); return &buf[0]; } @@ -2137,7 +2137,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par SIVAL(p,6,0); } else { SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub(conn,comment); + standard_sub_conn(conn,comment); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); p2 = skip_string(p2,1); } @@ -2519,7 +2519,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ pstrcpy(p2,lp_logon_script()); - standard_sub( conn, p2 ); + standard_sub_conn( conn, p2 ); p2 = skip_string(p2,1); if (uLevel == 2) { @@ -2544,7 +2544,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVALS(p,104,-1); /* num_logons */ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ pstrcpy(p2,"\\\\%L"); - standard_sub_basic(p2); + standard_sub_conn(conn, p2); p2 = skip_string(p2,1); SSVAL(p,110,49); /* country_code */ SSVAL(p,112,860); /* code page */ @@ -2667,7 +2667,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param { pstring logon_script; pstrcpy(logon_script,lp_logon_script()); - standard_sub( conn, logon_script ); + standard_sub_conn( conn, logon_script ); PACKS(&desc,"z", logon_script); /* script path */ } /* End of JHT mods */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index cbcdad157a..a7baa9e327 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -512,7 +512,6 @@ static void usage(char *pname) printf("\t-D Become a daemon\n"); printf("\t-a Append to log file (default)\n"); printf("\t-o Overwrite log file, don't append\n"); - printf("\t-P Passive only\n"); printf("\t-h Print usage\n"); printf("\t-? Print usage\n"); printf("\t-V Print version\n"); @@ -548,19 +547,12 @@ static void usage(char *pname) argc--; } - while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?VPaof:")) ) + while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?Vaof:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); break; - case 'P': - { - extern BOOL passive; - passive = True; - } - break; - case 's': pstrcpy(servicesf,optarg); break; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 24ba79906b..b7942906df 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -488,7 +488,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int { pstring s; pstrcpy(s,lp_pathname(snum)); - standard_sub(conn,s); + standard_sub_conn(conn,s); string_set(&conn->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); } @@ -523,7 +523,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (*lp_rootpreexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); - standard_sub(conn,cmd); + standard_sub_conn(conn,cmd); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL,False); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { @@ -584,7 +584,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (*lp_preexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); - standard_sub(conn,cmd); + standard_sub_conn(conn,cmd); ret = smbrun(cmd,NULL,False); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); @@ -680,7 +680,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) become_user(conn, vuid)) { pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); - standard_sub(conn,cmd); + standard_sub_conn(conn,cmd); smbrun(cmd,NULL,False); unbecome_user(); } @@ -690,7 +690,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) if (*lp_rootpostexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); - standard_sub(conn,cmd); + standard_sub_conn(conn,cmd); smbrun(cmd,NULL,False); } -- cgit From 59f992f12de9a0c6a0bc30f8953b324699623a03 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Apr 2000 07:00:22 +0000 Subject: patch from luke to split out lanman code from ipc.c into lanman.c (This used to be commit 95246a8432e04bcdeed962d1a6112dfd90518941) --- source3/smbd/ipc.c | 3330 ++----------------------------------------------- source3/smbd/lanman.c | 3180 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3272 insertions(+), 3238 deletions(-) create mode 100644 source3/smbd/lanman.c (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 64ec05b017..f87423c9ca 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -29,3123 +29,137 @@ #include "includes.h" #include "nterr.h" -#ifdef CHECK_TYPES -#undef CHECK_TYPES -#endif -#define CHECK_TYPES 0 - -extern int DEBUGLEVEL; -extern int max_send; - -extern fstring local_machine; -extern fstring global_myworkgroup; - -#define NERR_Success 0 -#define NERR_badpass 86 -#define NERR_notsupported 50 - -#define NERR_BASE (2100) -#define NERR_BufTooSmall (NERR_BASE+23) -#define NERR_JobNotFound (NERR_BASE+51) -#define NERR_DestNotFound (NERR_BASE+52) - -#define ACCESS_READ 0x01 -#define ACCESS_WRITE 0x02 -#define ACCESS_CREATE 0x04 - -#define SHPWLEN 8 /* share password length */ -#define NNLEN 12 /* 8.3 net name length */ -#define SNLEN 15 /* service name length */ -#define QNLEN 12 /* queue name maximum length */ - -extern int smb_read_error; - -static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); -static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - - -static int CopyExpanded(connection_struct *conn, - int snum, char** dst, char* src, int* n) -{ - pstring buf; - int l; - - if (!src || !dst || !n || !(*dst)) return(0); - - StrnCpy(buf,src,sizeof(buf)/2); - pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); - StrnCpy(*dst,buf,*n); - l = strlen(*dst) + 1; - (*dst) += l; - (*n) -= l; - return l; -} - -static int CopyAndAdvance(char** dst, char* src, int* n) -{ - int l; - if (!src || !dst || !n || !(*dst)) return(0); - StrnCpy(*dst,src,*n-1); - l = strlen(*dst) + 1; - (*dst) += l; - (*n) -= l; - return l; -} - -static int StrlenExpanded(connection_struct *conn, int snum, char* s) -{ - pstring buf; - if (!s) return(0); - StrnCpy(buf,s,sizeof(buf)/2); - pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); - return strlen(buf) + 1; -} - -static char* Expand(connection_struct *conn, int snum, char* s) -{ - static pstring buf; - if (!s) return(NULL); - StrnCpy(buf,s,sizeof(buf)/2); - pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); - return &buf[0]; -} - -/******************************************************************* - check a API string for validity when we only need to check the prefix - ******************************************************************/ -static BOOL prefix_ok(char *str,char *prefix) -{ - return(strncmp(str,prefix,strlen(prefix)) == 0); -} - -/******************************************************************* - copies parameters and data, as needed, into the smb buffer - - *both* the data and params sections should be aligned. this - is fudged in the rpc pipes by - at present, only the data section is. this may be a possible - cause of some of the ipc problems being experienced. lkcl26dec97 - - ******************************************************************/ - -static void copy_trans_params_and_data(char *outbuf, int align, - char *rparam, int param_offset, int param_len, - char *rdata, int data_offset, int data_len) -{ - char *copy_into = smb_buf(outbuf)+1; - - if(param_len < 0) - param_len = 0; - - if(data_len < 0) - data_len = 0; - - DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", - param_offset, param_offset + param_len, - data_offset , data_offset + data_len)); - - if (param_len) - memcpy(copy_into, &rparam[param_offset], param_len); - - copy_into += param_len + align; - - if (data_len ) - memcpy(copy_into, &rdata[data_offset], data_len); -} - -/**************************************************************************** - Send a trans reply. - ****************************************************************************/ - -static void send_trans_reply(char *outbuf, - char *rparam, int rparam_len, - char *rdata, int rdata_len, - BOOL buffer_too_large) -{ - int this_ldata,this_lparam; - int tot_data_sent = 0; - int tot_param_sent = 0; - int align; - - int ldata = rdata ? rdata_len : 0; - int lparam = rparam ? rparam_len : 0; - - if (buffer_too_large) - DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata )); - - this_lparam = MIN(lparam,max_send - 500); /* hack */ - this_ldata = MIN(ldata,max_send - (500+this_lparam)); - - align = ((this_lparam)%4); - - set_message(outbuf,10,1+align+this_ldata+this_lparam,True); - - if (buffer_too_large) - { - /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ - SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); - } - - copy_trans_params_and_data(outbuf, align, - rparam, tot_param_sent, this_lparam, - rdata, tot_data_sent, this_ldata); - - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,0); - - show_msg(outbuf); - send_smb(smbd_server_fd(),outbuf); - - tot_data_sent = this_ldata; - tot_param_sent = this_lparam; - - while (tot_data_sent < ldata || tot_param_sent < lparam) - { - this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */ - this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam)); - - if(this_lparam < 0) - this_lparam = 0; - - if(this_ldata < 0) - this_ldata = 0; - - align = (this_lparam%4); - - set_message(outbuf,10,1+this_ldata+this_lparam+align,False); - - copy_trans_params_and_data(outbuf, align, - rparam, tot_param_sent, this_lparam, - rdata, tot_data_sent, this_ldata); - - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,tot_param_sent); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,tot_data_sent); - SSVAL(outbuf,smb_vwv9,0); - - show_msg(outbuf); - send_smb(smbd_server_fd(),outbuf); - - tot_data_sent += this_ldata; - tot_param_sent += this_lparam; - } -} - -struct pack_desc { - char* format; /* formatstring for structure */ - char* subformat; /* subformat for structure */ - char* base; /* baseaddress of buffer */ - int buflen; /* remaining size for fixed part; on init: length of base */ - int subcount; /* count of substructures */ - char* structbuf; /* pointer into buffer for remaining fixed part */ - int stringlen; /* remaining size for variable part */ - char* stringbuf; /* pointer into buffer for remaining variable part */ - int neededlen; /* total needed size */ - int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ - char* curpos; /* current position; pointer into format or subformat */ - int errcode; -}; - -static int get_counter(char** p) -{ - int i, n; - if (!p || !(*p)) return(1); - if (!isdigit((int)**p)) return 1; - for (n = 0;;) { - i = **p; - if (isdigit(i)) - n = 10 * n + (i - '0'); - else - return n; - (*p)++; - } -} - -static int getlen(char* p) -{ - int n = 0; - if (!p) return(0); - while (*p) { - switch( *p++ ) { - case 'W': /* word (2 byte) */ - n += 2; - break; - case 'K': /* status word? (2 byte) */ - n += 2; - break; - case 'N': /* count of substructures (word) at end */ - n += 2; - break; - case 'D': /* double word (4 byte) */ - case 'z': /* offset to zero terminated string (4 byte) */ - case 'l': /* offset to user data (4 byte) */ - n += 4; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - n += 4; - get_counter(&p); - break; - case 'B': /* byte (with optional counter) */ - n += get_counter(&p); - break; - } - } - return n; -} - -static BOOL init_package(struct pack_desc* p, int count, int subcount) -{ - int n = p->buflen; - int i; - - if (!p->format || !p->base) return(False); - - i = count * getlen(p->format); - if (p->subformat) i += subcount * getlen(p->subformat); - p->structbuf = p->base; - p->neededlen = 0; - p->usedlen = 0; - p->subcount = 0; - p->curpos = p->format; - if (i > n) { - p->neededlen = i; - i = n = 0; - p->errcode = ERRmoredata; - } - else - p->errcode = NERR_Success; - p->buflen = i; - n -= i; - p->stringbuf = p->base + i; - p->stringlen = n; - return(p->errcode == NERR_Success); -} - -#ifdef HAVE_STDARG_H -static int package(struct pack_desc* p, ...) -{ -#else -static int package(va_alist) -va_dcl -{ - struct pack_desc* p; -#endif - va_list args; - int needed=0, stringneeded; - char* str=NULL; - int is_string=0, stringused; - int32 temp; - -#ifdef HAVE_STDARG_H - va_start(args,p); -#else - va_start(args); - p = va_arg(args,struct pack_desc *); -#endif - - if (!*p->curpos) { - if (!p->subcount) - p->curpos = p->format; - else { - p->curpos = p->subformat; - p->subcount--; - } - } -#if CHECK_TYPES - str = va_arg(args,char*); - SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); -#endif - stringneeded = -1; - - if (!p->curpos) { - va_end(args); - return(0); - } - - switch( *p->curpos++ ) { - case 'W': /* word (2 byte) */ - needed = 2; - temp = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); - break; - case 'K': /* status word? (2 byte) */ - needed = 2; - temp = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); - break; - case 'N': /* count of substructures (word) at end */ - needed = 2; - p->subcount = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount); - break; - case 'D': /* double word (4 byte) */ - needed = 4; - temp = va_arg(args,int); - if (p->buflen >= needed) SIVAL(p->structbuf,0,temp); - break; - case 'B': /* byte (with optional counter) */ - needed = get_counter(&p->curpos); - { - char *s = va_arg(args,char*); - if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1); - } - break; - case 'z': /* offset to zero terminated string (4 byte) */ - str = va_arg(args,char*); - stringneeded = (str ? strlen(str)+1 : 0); - is_string = 1; - break; - case 'l': /* offset to user data (4 byte) */ - str = va_arg(args,char*); - stringneeded = va_arg(args,int); - is_string = 0; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - str = va_arg(args,char*); - stringneeded = get_counter(&p->curpos); - is_string = 0; - break; - } - va_end(args); - if (stringneeded >= 0) { - needed = 4; - if (p->buflen >= needed) { - stringused = stringneeded; - if (stringused > p->stringlen) { - stringused = (is_string ? p->stringlen : 0); - if (p->errcode == NERR_Success) p->errcode = ERRmoredata; - } - if (!stringused) - SIVAL(p->structbuf,0,0); - else { - SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); - memcpy(p->stringbuf,str?str:"",stringused); - if (is_string) p->stringbuf[stringused-1] = '\0'; - p->stringbuf += stringused; - p->stringlen -= stringused; - p->usedlen += stringused; - } - } - p->neededlen += stringneeded; - } - p->neededlen += needed; - if (p->buflen >= needed) { - p->structbuf += needed; - p->buflen -= needed; - p->usedlen += needed; - } - else { - if (p->errcode == NERR_Success) p->errcode = ERRmoredata; - } - return 1; -} - -#if CHECK_TYPES -#define PACK(desc,t,v) package(desc,t,v,0,0,0,0) -#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0) -#else -#define PACK(desc,t,v) package(desc,v) -#define PACKl(desc,t,v,l) package(desc,v,l) -#endif - -static void PACKI(struct pack_desc* desc,char *t,int v) -{ - PACK(desc,t,v); -} - -static void PACKS(struct pack_desc* desc,char *t,char *v) -{ - PACK(desc,t,v); -} - - -/**************************************************************************** - get a print queue - ****************************************************************************/ -static void PackDriverData(struct pack_desc* desc) -{ - char drivdata[4+4+32]; - SIVAL(drivdata,0,sizeof drivdata); /* cb */ - SIVAL(drivdata,4,1000); /* lVersion */ - memset(drivdata+8,0,32); /* szDeviceName */ - pstrcpy(drivdata+8,"NULL"); - PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ -} - -static int check_printq_info(struct pack_desc* desc, - int uLevel, char *id1, char *id2) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: - desc->format = "B13"; - break; - case 1: - desc->format = "B13BWWWzzzzzWW"; - break; - case 2: - desc->format = "B13BWWWzzzzzWN"; - desc->subformat = "WB21BB16B10zWWzDDz"; - break; - case 3: - desc->format = "zWWWWzzzzWWzzl"; - break; - case 4: - desc->format = "zWWWWzzzzWNzzl"; - desc->subformat = "WWzWWDDzz"; - break; - case 5: - desc->format = "z"; - break; - case 51: - desc->format = "K"; - break; - case 52: - desc->format = "WzzzzzzzzN"; - desc->subformat = "z"; - break; - default: return False; - } - if (strcmp(desc->format,id1) != 0) return False; - if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False; - return True; -} - - -#define JOB_STATUS_QUEUED 0 -#define JOB_STATUS_PAUSED 1 -#define JOB_STATUS_SPOOLING 2 -#define JOB_STATUS_PRINTING 3 -#define JOB_STATUS_PRINTED 4 - -#define QUEUE_STATUS_PAUSED 1 -#define QUEUE_STATUS_ERROR 2 - -/* turn a print job status into a on the wire status -*/ -static int printj_status(int v) -{ - switch (v) { - case LPQ_QUEUED: - return JOB_STATUS_QUEUED; - case LPQ_PAUSED: - return JOB_STATUS_PAUSED; - case LPQ_SPOOLING: - return JOB_STATUS_SPOOLING; - case LPQ_PRINTING: - return JOB_STATUS_PRINTING; - } - return 0; -} - -/* turn a print queue status into a on the wire status -*/ -static int printq_status(int v) -{ - switch (v) { - case LPQ_QUEUED: - return 0; - case LPQ_PAUSED: - return QUEUE_STATUS_PAUSED; - } - return QUEUE_STATUS_ERROR; -} - -static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc, - print_queue_struct* queue, int n) -{ - time_t t = queue->time; - - /* the client expects localtime */ - t -= TimeDiff(t); - - PACKI(desc,"W",queue->job); /* uJobId */ - if (uLevel == 1) { - PACKS(desc,"B21",queue->user); /* szUserName */ - PACKS(desc,"B",""); /* pad */ - PACKS(desc,"B16",""); /* szNotifyName */ - PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",t); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z",queue->file); /* pszComment */ - } - if (uLevel == 2 || uLevel == 3) { - PACKI(desc,"W",queue->priority); /* uPriority */ - PACKS(desc,"z",queue->user); /* pszUserName */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ - PACKI(desc,"D",t); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z","Samba"); /* pszComment */ - PACKS(desc,"z",queue->file); /* pszDocument */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszNotifyName */ - PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ - PACKS(desc,"z","lpd"); /* pszQProcName */ - PACKS(desc,"z",""); /* pszQProcParms */ - PACKS(desc,"z","NULL"); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - PACKS(desc,"z",""); /* pszPrinterName */ - } - } -} - - -static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc, - int count, print_queue_struct* queue, - print_status_struct* status) -{ - int i,ok=0; - pstring tok,driver,datafile,langmon,helpfile,datatype; - char *p; - char **lines, *line; - - lines = file_lines_load(lp_driverfile(),NULL); - if (!lines) { - DEBUG(3,("fill_printq_info: Can't open %s - %s\n", - lp_driverfile(),strerror(errno))); - desc->errcode=NERR_notsupported; - return; - } - - /* lookup the long printer driver name in the file - description */ - for (i=0;lines[i] && !ok;i++) { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok=1; - } - line = strdup(p); - p = line; - file_lines_free(lines); - - /* driver file name */ - if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0; - /* data file name */ - if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0; - /* - * for the next tokens - which may be empty - I have - * to check for empty tokens first because the - * next_token function will skip all empty token - * fields */ - if (ok) { - /* help file */ - if (*p == ':') { - *helpfile = '\0'; - p++; - } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0; - } - - if (ok) { - /* language monitor */ - if (*p == ':') { - *langmon = '\0'; - p++; - } else if (!next_token(&p,langmon,":",sizeof(langmon))) - ok = 0; - } - - /* default data type */ - if (ok && !next_token(&p,datatype,":",sizeof(datatype))) - ok = 0; - - if (ok) { - PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ - PACKS(desc,"z",driver); /* Driverfile Name */ - PACKS(desc,"z",datafile); /* Datafile name */ - PACKS(desc,"z",langmon); /* language monitor */ - PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ - PACKS(desc,"z",datatype); /* default data type */ - PACKS(desc,"z",helpfile); /* helpfile name */ - PACKS(desc,"z",driver); /* driver name */ - DEBUG(3,("Driver:%s:\n",driver)); - DEBUG(3,("Data File:%s:\n",datafile)); - DEBUG(3,("Language Monitor:%s:\n",langmon)); - DEBUG(3,("Data Type:%s:\n",datatype)); - DEBUG(3,("Help File:%s:\n",helpfile)); - PACKI(desc,"N",count); /* number of files to copy */ - for (i=0;i gave %d entries\n", - SERVICE(snum),count)); - } else { - DEBUG(3,("fill_printq_info: Can't supply driver files\n")); - desc->errcode=NERR_notsupported; - } - free(line); -} - - -static void fill_printq_info(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc, - int count, print_queue_struct* queue, - print_status_struct* status) -{ - switch (uLevel) { - case 1: - case 2: - PACKS(desc,"B13",SERVICE(snum)); - break; - case 3: - case 4: - case 5: - PACKS(desc,"z",Expand(conn,snum,SERVICE(snum))); - break; - case 51: - PACKI(desc,"K",printq_status(status->status)); - break; - } - - if (uLevel == 1 || uLevel == 2) { - PACKS(desc,"B",""); /* alignment */ - PACKI(desc,"W",5); /* priority */ - PACKI(desc,"W",0); /* start time */ - PACKI(desc,"W",0); /* until time */ - PACKS(desc,"z",""); /* pSepFile */ - PACKS(desc,"z","lpd"); /* pPrProc */ - PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ - PACKS(desc,"z",""); /* pParms */ - if (snum < 0) { - PACKS(desc,"z","UNKNOWN PRINTER"); - PACKI(desc,"W",LPSTAT_ERROR); - } - else if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); - PACKI(desc,"W",LPSTAT_OK); /* status */ - } else { - PACKS(desc,"z",status->message); - PACKI(desc,"W",printq_status(status->status)); /* status */ - } - PACKI(desc,(uLevel == 1 ? "W" : "N"),count); - } - - if (uLevel == 3 || uLevel == 4) { - PACKI(desc,"W",5); /* uPriority */ - PACKI(desc,"W",0); /* uStarttime */ - PACKI(desc,"W",0); /* uUntiltime */ - PACKI(desc,"W",5); /* pad1 */ - PACKS(desc,"z",""); /* pszSepFile */ - PACKS(desc,"z","WinPrint"); /* pszPrProc */ - PACKS(desc,"z",""); /* pszParms */ - if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */ - PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ - } else { - PACKS(desc,"z",status->message); /* pszComment */ - PACKI(desc,"W",printq_status(status->status)); /* fsStatus */ - } - PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ - PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - } - - if (uLevel == 2 || uLevel == 4) { - int i; - for (i=0;i - * to return the 'invalid info level' error if an - * unknown level was requested. - */ - *rdata_len = 0; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,ERROR_INVALID_LEVEL); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,0); - return(True); - } - - snum = lp_servicenumber(QueueName); - if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - if (uLevel==52) { - count = get_printerdrivernumber(snum); - DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); - } else { - count = print_queue_status(snum, &queue,&status); - } - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,count)) { - desc.subcount = count; - fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); - } else if(uLevel == 0) { - /* - * This is a *disgusting* hack. - * This is *so* bad that even I'm embarrassed (and I - * have no shame). Here's the deal : - * Until we get the correct SPOOLSS code into smbd - * then when we're running with NT SMB support then - * NT makes this call with a level of zero, and then - * immediately follows it with an open request to - * the \\SRVSVC pipe. If we allow that open to - * succeed then NT barfs when it cannot open the - * \\SPOOLSS pipe immediately after and continually - * whines saying "Printer name is invalid" forever - * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC - * to fail, then NT downgrades to using the downlevel code - * and everything works as well as before. I hate - * myself for adding this code.... JRA. - */ - - fail_next_srvsvc_open(); - } - - *rdata_len = desc.usedlen; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); - - if (queue) free(queue); - - return(True); -} - - -/**************************************************************************** - view list of all print jobs on all queues - ****************************************************************************/ -static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data, - int mdrcnt, int mprcnt, - char **rdata, char** rparam, - int *rdata_len, int *rparam_len) -{ - char *param_format = param+2; - char *output_format1 = skip_string(param_format,1); - char *p = skip_string(output_format1,1); - int uLevel = SVAL(p,0); - char *output_format2 = p + 4; - int services = lp_numservices(); - int i, n; - struct pack_desc desc; - print_queue_struct **queue = NULL; - print_status_struct *status = NULL; - int* subcntarr = NULL; - int queuecnt, subcnt=0, succnt=0; - - memset((char *)&desc,'\0',sizeof(desc)); - - DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); - - if (!prefix_ok(param_format,"WrLeh")) return False; - if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) { - /* - * Patch from Scott Moomaw - * to return the 'invalid info level' error if an - * unknown level was requested. - */ - *rdata_len = 0; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,ERROR_INVALID_LEVEL); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,0); - return(True); - } - - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - if (uLevel > 0) { - if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - memset(queue,0,queuecnt*sizeof(print_queue_struct*)); - if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - memset(status,0,queuecnt*sizeof(print_status_struct)); - if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - subcnt = 0; - n = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = print_queue_status(i, &queue[n],&status[n]); - subcnt += subcntarr[n]; - n++; - } - } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,queuecnt,subcnt)) { - n = 0; - succnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - - if (subcntarr) free(subcntarr); - - *rdata_len = desc.usedlen; - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); - - for (i = 0; i < queuecnt; i++) { - if (queue && queue[i]) free(queue[i]); - } - - if (queue) free(queue); - if (status) free(status); - - return True; -} - -/**************************************************************************** - get info level for a server list query - ****************************************************************************/ -static BOOL check_server_info(int uLevel, char* id) -{ - switch( uLevel ) { - case 0: - if (strcmp(id,"B16") != 0) return False; - break; - case 1: - if (strcmp(id,"B16BBDz") != 0) return False; - break; - default: - return False; - } - return True; -} - -struct srv_info_struct -{ - fstring name; - uint32 type; - fstring comment; - fstring domain; - BOOL server_added; -}; - - -/******************************************************************* - 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, - char *domain) -{ - int count=0; - int alloced=0; - char **lines; - BOOL local_list_only; - int i; - - lines = file_lines_load(lock_path(SERVER_LIST), NULL); - if (!lines) { - DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); - return(0); - } - - /* request for everything is code for request all servers */ - if (servertype == SV_TYPE_ALL) - servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); - - local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); - - DEBUG(4,("Servertype search: %8x\n",servertype)); - - for (i=0;lines[i];i++) { - fstring stype; - struct srv_info_struct *s; - char *ptr = lines[i]; - BOOL ok = True; - - if (!*ptr) continue; - - if (count == alloced) { - alloced += 10; - (*servers) = (struct srv_info_struct *) - Realloc(*servers,sizeof(**servers)*alloced); - if (!(*servers)) return(0); - memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); - } - s = &(*servers)[count]; - - if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue; - if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue; - if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue; - if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) { - /* this allows us to cope with an old nmbd */ - pstrcpy(s->domain,global_myworkgroup); - } - - if (sscanf(stype,"%X",&s->type) != 1) { - DEBUG(4,("r:host file ")); - ok = False; - } - - /* Filter the servers/domains we return based on what was asked for. */ - - /* Check to see if we are being asked for a local list only. */ - if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) { - DEBUG(4,("r: local list only")); - ok = False; - } - - /* doesn't match up: don't want it */ - 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: dom mismatch ")); - ok = False; - } - - if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) - { - ok = False; - } - - /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ - s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; - - if (ok) - { - DEBUG(4,("**SV** %20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - - s->server_added = True; - count++; - } - else - { - DEBUG(4,("%20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - } - } - - file_lines_free(lines); - return(count); -} - - -/******************************************************************* - fill in a server info structure - ******************************************************************/ -static int fill_srv_info(struct srv_info_struct *service, - int uLevel, char **buf, int *buflen, - char **stringbuf, int *stringspace, char *baseaddr) -{ - int struct_len; - char* p; - char* p2; - int l2; - int len; - - switch (uLevel) { - case 0: struct_len = 16; break; - case 1: struct_len = 26; break; - default: return -1; - } - - if (!buf) - { - len = 0; - switch (uLevel) - { - case 1: - len = strlen(service->comment)+1; - break; - } - - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } - - len = struct_len; - p = *buf; - if (*buflen < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = *buflen - struct_len; - } - if (!baseaddr) baseaddr = p; - - switch (uLevel) - { - case 0: - StrnCpy(p,service->name,15); - break; - - case 1: - StrnCpy(p,service->name,15); - SIVAL(p,18,service->type); - SIVAL(p,22,PTR_DIFF(p2,baseaddr)); - len += CopyAndAdvance(&p2,service->comment,&l2); - break; - } - - if (stringbuf) - { - *buf = p + struct_len; - *buflen -= struct_len; - *stringbuf = p2; - *stringspace = l2; - } - else - { - *buf = p2; - *buflen -= len; - } - return len; -} - - -static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) -{ - return(strcmp(s1->name,s2->name)); -} - -/**************************************************************************** - view list of servers available (or possibly domains). The info is - extracted from lists saved by nmbd on the local host - ****************************************************************************/ -static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, char **rdata, - char **rparam, int *rdata_len, int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - uint32 servertype = IVAL(p,4); - char *p2; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; - struct srv_info_struct *servers=NULL; - int counted=0,total=0; - int i,missed; - fstring domain; - BOOL domain_request; - BOOL local_request; - - /* If someone sets all the bits they don't really mean to set - DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the - known servers. */ - - if (servertype == SV_TYPE_ALL) - servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); - - /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set - any other bit (they may just set this bit on it's own) they - want all the locally seen servers. However this bit can be - set on its own so set the requested servers to be - ALL - DOMAIN_ENUM. */ - - if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) - servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); - - domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); - local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0); - - p += 8; - - if (!prefix_ok(str1,"WrLehD")) return False; - if (!check_server_info(uLevel,str2)) return False; - - 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, "WrLehDz") == 0) { - StrnCpy(domain, p, sizeof(fstring)-1); - } else { - StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1); - } - - if (lp_browse_list()) - total = get_server_info(servertype,&servers,domain); - - data_len = fixed_len = string_len = 0; - missed = 0; - - qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); - - { - char *lastname=NULL; - - for (i=0;iname)) continue; - lastname = s->name; - 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; - } else { - missed++; - } - } - } - - *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); - memset(*rdata,'\0',*rdata_len); - - p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ - p = *rdata; - f_len = fixed_len; - s_len = string_len; - - { - char *lastname=NULL; - int count2 = counted; - for (i = 0; i < total && count2;i++) - { - struct srv_info_struct *s = &servers[i]; - if (lastname && strequal(lastname,s->name)) continue; - lastname = s->name; - 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--; - } - } - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,counted+missed); - - if (servers) free(servers); - - DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", - domain,uLevel,counted,counted+missed)); - - return(True); -} - -/**************************************************************************** - command 0x34 - suspected of being a "Lookup Names" stub api - ****************************************************************************/ -static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, char **rdata, - char **rparam, int *rdata_len, int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - int counted=0; - int missed=0; - - DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", - str1, str2, p, uLevel, buf_len)); - - if (!prefix_ok(str1,"zWrLeh")) return False; - - *rdata_len = 0; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - - SSVAL(*rparam,0,0x08AC); /* informational warning message */ - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,counted+missed); - - return(True); -} - -/**************************************************************************** - get info about a share - ****************************************************************************/ -static BOOL check_share_info(int uLevel, char* id) -{ - switch( uLevel ) { - case 0: - if (strcmp(id,"B13") != 0) return False; - break; - case 1: - if (strcmp(id,"B13BWz") != 0) return False; - break; - case 2: - if (strcmp(id,"B13BWzWWWzB9B") != 0) return False; - break; - case 91: - if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False; - break; - default: return False; - } - return True; -} - -static int fill_share_info(connection_struct *conn, int snum, int uLevel, - char** buf, int* buflen, - char** stringbuf, int* stringspace, char* baseaddr) -{ - int struct_len; - char* p; - char* p2; - int l2; - int len; - - switch( uLevel ) { - case 0: struct_len = 13; break; - case 1: struct_len = 20; break; - case 2: struct_len = 40; break; - case 91: struct_len = 68; break; - default: return -1; - } - - - if (!buf) - { - len = 0; - if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum)); - if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } - - len = struct_len; - p = *buf; - if ((*buflen) < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = (*buflen) - struct_len; - } - if (!baseaddr) baseaddr = p; - - StrnCpy(p,lp_servicename(snum),13); - - if (uLevel > 0) - { - int type; - CVAL(p,13) = 0; - type = STYPE_DISKTREE; - if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; - SSVAL(p,14,type); /* device type */ - SIVAL(p,16,PTR_DIFF(p2,baseaddr)); - len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); - } - - if (uLevel > 1) - { - SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ - SSVALS(p,22,-1); /* max uses */ - SSVAL(p,24,1); /* current uses */ - SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ - len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); - memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ - } - - if (uLevel > 2) - { - memset(p+40,0,SHPWLEN+2); - SSVAL(p,50,0); - SIVAL(p,52,0); - SSVAL(p,56,0); - SSVAL(p,58,0); - SIVAL(p,60,0); - SSVAL(p,64,0); - SSVAL(p,66,0); - } - - if (stringbuf) - { - (*buf) = p + struct_len; - (*buflen) -= struct_len; - (*stringbuf) = p2; - (*stringspace) = l2; - } - else - { - (*buf) = p2; - (*buflen) -= len; - } - return len; -} - -static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *netname = skip_string(str2,1); - char *p = skip_string(netname,1); - int uLevel = SVAL(p,0); - int snum = find_service(netname); - - if (snum < 0) return False; - - /* check it's a supported varient */ - if (!prefix_ok(str1,"zWrLh")) return False; - if (!check_share_info(uLevel,str2)) return False; - - *rdata = REALLOC(*rdata,mdrcnt); - p = *rdata; - *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); - if (*rdata_len < 0) return False; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - - return(True); -} - -/**************************************************************************** - view list of shares available - ****************************************************************************/ -static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - char *p2; - int count=lp_numservices(); - int total=0,counted=0; - BOOL missed = False; - int i; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; - - if (!prefix_ok(str1,"WrLeh")) return False; - if (!check_share_info(uLevel,str2)) return False; - - data_len = fixed_len = string_len = 0; - for (i=0;itm_hour; - CVAL(p,9) = t->tm_min; - CVAL(p,10) = t->tm_sec; - CVAL(p,11) = 0; /* hundredths of seconds */ - SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */ - SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ - CVAL(p,16) = t->tm_mday; - CVAL(p,17) = t->tm_mon + 1; - SSVAL(p,18,1900+t->tm_year); - CVAL(p,20) = t->tm_wday; - } - - - return(True); -} - -/**************************************************************************** - Set the user password. -*****************************************************************************/ - -static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *p = skip_string(param+2,2); - fstring user; - fstring pass1,pass2; - - fstrcpy(user,p); - - p = skip_string(p,1); - - memset(pass1,'\0',sizeof(pass1)); - memset(pass2,'\0',sizeof(pass2)); - memcpy(pass1,p,16); - memcpy(pass2,p+16,16); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_badpass); - SSVAL(*rparam,2,0); /* converter word */ - - DEBUG(3,("Set password for <%s>\n",user)); - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); - - /* - * Attempt to verify the old password against smbpasswd entries - * Win98 clients send old and new password in plaintext for this call. - */ - - { - fstring saved_pass2; - struct smb_passwd *smbpw = NULL; - - /* - * Save the new password as change_oem_password overwrites it - * with zeros. - */ - - fstrcpy(saved_pass2, pass2); - - if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) && - change_oem_password(smbpw,pass2,False)) - { - SSVAL(*rparam,0,NERR_Success); - - /* - * If unix password sync was requested, attempt to change - * the /etc/passwd database also. Return failure if this cannot - * be done. - */ - - if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) - SSVAL(*rparam,0,NERR_badpass); - } - } - - /* - * If the above failed, attempt the plaintext password change. - * This tests against the /etc/passwd database only. - */ - - if(SVAL(*rparam,0) != NERR_Success) - { - if (password_ok(user, pass1,strlen(pass1),NULL) && - chgpasswd(user,pass1,pass2,False)) - { - SSVAL(*rparam,0,NERR_Success); - } - } - - /* - * If the plaintext change failed, attempt - * the old encrypted method. NT will generate this - * after trying the samr method. Note that this - * method is done as a last resort as this - * password change method loses the NT password hash - * and cannot change the UNIX password as no plaintext - * is received. - */ - - if(SVAL(*rparam,0) != NERR_Success) - { - struct smb_passwd *sampw = NULL; - - if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) && - change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - } - - memset((char *)pass1,'\0',sizeof(fstring)); - memset((char *)pass2,'\0',sizeof(fstring)); - - return(True); -} - -/**************************************************************************** - Set the user password (SamOEM version - gets plaintext). -****************************************************************************/ - -static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - fstring user; - char *p = param + 2; - *rparam_len = 2; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_badpass); - - /* - * Check the parameter definition is correct. - */ - if(!strequal(param + 2, "zsT")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); - return False; - } - p = skip_string(p, 1); - - if(!strequal(p, "B516B16")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); - return False; - } - p = skip_string(p,1); - - fstrcpy(user,p); - p = skip_string(p,1); - - DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); - - if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)) - { - SSVAL(*rparam,0,NERR_Success); - } - - return(True); -} - -/**************************************************************************** - delete a print job - Form: <> - ****************************************************************************/ -static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int jobid, errcode; - - jobid = SVAL(p,0); - - /* check it's a supported varient */ - if (!(strcsequal(str1,"W") && strcsequal(str2,""))) - return(False); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; - - if (!print_job_exists(jobid)) { - errcode = NERR_JobNotFound; - goto out; - } - - errcode = NERR_notsupported; - - switch (function) { - case 81: /* delete */ - if (print_job_delete(jobid)) errcode = NERR_Success; - break; - case 82: /* pause */ - if (print_job_pause(jobid)) errcode = NERR_Success; - break; - case 83: /* resume */ - if (print_job_resume(jobid)) errcode = NERR_Success; - break; - } - - out: - SSVAL(*rparam,0,errcode); - SSVAL(*rparam,2,0); /* converter word */ - - return(True); -} - -/**************************************************************************** - Purge a print queue - or pause or resume it. - ****************************************************************************/ -static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *QueueName = skip_string(str2,1); - int errcode = NERR_notsupported; - int snum; - - /* check it's a supported varient */ - if (!(strcsequal(str1,"z") && strcsequal(str2,""))) - return(False); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; - - snum = print_queue_snum(QueueName); - - if (snum == -1) { - errcode = NERR_JobNotFound; - goto out; - } - - switch (function) { - case 74: /* Pause queue */ - if (print_queue_pause(snum)) errcode = NERR_Success; - break; - case 75: /* Resume queue */ - if (print_queue_resume(snum)) errcode = NERR_Success; - break; - case 103: /* Purge */ - if (print_queue_purge(snum)) errcode = NERR_Success; - break; - } - - out: - SSVAL(*rparam,0,errcode); - SSVAL(*rparam,2,0); /* converter word */ - - return(True); -} - - -/**************************************************************************** - set the property of a print job (undocumented?) - ? function = 0xb -> set name of print job - ? function = 0x6 -> move print job up/down - Form: - or -****************************************************************************/ -static int check_printjob_info(struct pack_desc* desc, - int uLevel, char* id) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "W"; break; - case 1: desc->format = "WB21BB16B10zWWzDDz"; break; - case 2: desc->format = "WWzWWDDzz"; break; - case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; -} - -static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - struct pack_desc desc; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int jobid; - int uLevel = SVAL(p,2); - int function = SVAL(p,4); - int place, errcode; - - jobid = SVAL(p,0); - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - /* check it's a supported varient */ - if ((strcmp(str1,"WWsTP")) || - (!check_printjob_info(&desc,uLevel,str2))) - return(False); - - if (!print_job_exists(jobid)) { - errcode=NERR_JobNotFound; - goto out; - } - - errcode = NERR_notsupported; - - switch (function) { - case 0x6: - /* change job place in the queue, - data gives the new place */ - place = SVAL(data,0); - if (print_job_set_place(jobid, place)) { - errcode=NERR_Success; - } - break; - - case 0xb: - /* change print job name, data gives the name */ - if (print_job_set_name(jobid, data)) { - errcode=NERR_Success; - } - break; - - default: - return False; - } - - out: - SSVALS(*rparam,0,errcode); - SSVAL(*rparam,2,0); /* converter word */ - - return(True); -} - - -/**************************************************************************** - get info about the server - ****************************************************************************/ -static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - char *p2; - int struct_len; - - DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); - - /* check it's a supported varient */ - if (!prefix_ok(str1,"WrLh")) return False; - switch( uLevel ) { - case 0: - if (strcmp(str2,"B16") != 0) return False; - struct_len = 16; - break; - case 1: - if (strcmp(str2,"B16BBDz") != 0) return False; - struct_len = 26; - break; - case 2: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz") - != 0) return False; - struct_len = 134; - break; - case 3: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") - != 0) return False; - struct_len = 144; - break; - case 20: - if (strcmp(str2,"DN") != 0) return False; - struct_len = 6; - break; - case 50: - if (strcmp(str2,"B16BBDzWWzzz") != 0) return False; - struct_len = 42; - break; - default: return False; - } - - *rdata_len = mdrcnt; - *rdata = REALLOC(*rdata,*rdata_len); - - p = *rdata; - p2 = p + struct_len; - if (uLevel != 20) { - StrnCpy(p,local_machine,16); - strupper(p); - } - p += 16; - if (uLevel > 0) - { - struct srv_info_struct *servers=NULL; - int i,count; - pstring comment; - uint32 servertype= lp_default_server_announce(); - - pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); - - if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) { - for (i=0;i 1) - { - return False; /* not yet implemented */ - } - - *rdata_len = PTR_DIFF(p2,*rdata); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - - return(True); -} - - -/**************************************************************************** - get info about the server - ****************************************************************************/ -static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char *p2; - extern pstring sesssetup_user; - int level = SVAL(p,0); - - DEBUG(4,("NetWkstaGetInfo level %d\n",level)); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported varient */ - if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) - return(False); - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - p2 = p + 22; - - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ - pstrcpy(p2,local_machine); - strupper(p2); - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - pstrcpy(p2,sesssetup_user); - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ - pstrcpy(p2,global_myworkgroup); - strupper(p2); - p2 = skip_string(p2,1); - p += 4; - - SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ - SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */ - p += 2; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */ - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ - pstrcpy(p2,""); - p2 = skip_string(p2,1); - p += 4; - - *rdata_len = PTR_DIFF(p2,*rdata); - - SSVAL(*rparam,4,*rdata_len); - - return(True); -} - -/**************************************************************************** - get info about a user - - struct user_info_11 { - char usri11_name[21]; 0-20 - char usri11_pad; 21 - char *usri11_comment; 22-25 - char *usri11_usr_comment; 26-29 - unsigned short usri11_priv; 30-31 - unsigned long usri11_auth_flags; 32-35 - long usri11_password_age; 36-39 - char *usri11_homedir; 40-43 - char *usri11_parms; 44-47 - long usri11_last_logon; 48-51 - long usri11_last_logoff; 52-55 - unsigned short usri11_bad_pw_count; 56-57 - unsigned short usri11_num_logons; 58-59 - char *usri11_logon_server; 60-63 - unsigned short usri11_country_code; 64-65 - char *usri11_workstations; 66-69 - unsigned long usri11_max_storage; 70-73 - unsigned short usri11_units_per_week; 74-75 - unsigned char *usri11_logon_hours; 76-79 - unsigned short usri11_code_page; 80-81 - }; - -where: - - usri11_name specifies the user name for which information is retireved - - usri11_pad aligns the next data structure element to a word boundary - - usri11_comment is a null terminated ASCII comment - - usri11_user_comment is a null terminated ASCII comment about the user - - usri11_priv specifies the level of the privilege assigned to the user. - The possible values are: - -Name Value Description -USER_PRIV_GUEST 0 Guest privilege -USER_PRIV_USER 1 User privilege -USER_PRV_ADMIN 2 Administrator privilege - - usri11_auth_flags specifies the account operator privileges. The - possible values are: - -Name Value Description -AF_OP_PRINT 0 Print operator - - -Leach, Naik [Page 28] - - -INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 - - -AF_OP_COMM 1 Communications operator -AF_OP_SERVER 2 Server operator -AF_OP_ACCOUNTS 3 Accounts operator - - - usri11_password_age specifies how many seconds have elapsed since the - password was last changed. - - usri11_home_dir points to a null terminated ASCII string that contains - the path name of the user's home directory. - - usri11_parms points to a null terminated ASCII string that is set - aside for use by applications. - - usri11_last_logon specifies the time when the user last logged on. - This value is stored as the number of seconds elapsed since - 00:00:00, January 1, 1970. - - usri11_last_logoff specifies the time when the user last logged off. - This value is stored as the number of seconds elapsed since - 00:00:00, January 1, 1970. A value of 0 means the last logoff - time is unknown. - - usri11_bad_pw_count specifies the number of incorrect passwords - entered since the last successful logon. - - usri11_log1_num_logons specifies the number of times this user has - logged on. A value of -1 means the number of logons is unknown. - - usri11_logon_server points to a null terminated ASCII string that - contains the name of the server to which logon requests are sent. - A null string indicates logon requests should be sent to the - domain controller. - - usri11_country_code specifies the country code for the user's language - of choice. - - usri11_workstations points to a null terminated ASCII string that - contains the names of workstations the user may log on from. - There may be up to 8 workstations, with the names separated by - commas. A null strings indicates there are no restrictions. - - usri11_max_storage specifies the maximum amount of disk space the user - can occupy. A value of 0xffffffff indicates there are no - restrictions. - - usri11_units_per_week specifies the equal number of time units into - which a week is divided. This value must be equal to 168. - - usri11_logon_hours points to a 21 byte (168 bits) string that - specifies the time during which the user can log on. Each bit - represents one unique hour in a week. The first bit (bit 0, word - 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is - - - -Leach, Naik [Page 29] - - -INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 - - - Sunday, 1:00 to 1:59 and so on. A null pointer indicates there - are no restrictions. - - usri11_code_page specifies the code page for the user's language of - choice - -All of the pointers in this data structure need to be treated -specially. The pointer is a 32 bit pointer. The higher 16 bits need -to be ignored. The converter word returned in the parameters section -needs to be subtracted from the lower 16 bits to calculate an offset -into the return buffer where this ASCII string resides. - -There is no auxiliary data in the response. - - ****************************************************************************/ - -#define usri11_name 0 -#define usri11_pad 21 -#define usri11_comment 22 -#define usri11_usr_comment 26 -#define usri11_full_name 30 -#define usri11_priv 34 -#define usri11_auth_flags 36 -#define usri11_password_age 40 -#define usri11_homedir 44 -#define usri11_parms 48 -#define usri11_last_logon 52 -#define usri11_last_logoff 56 -#define usri11_bad_pw_count 60 -#define usri11_num_logons 62 -#define usri11_logon_server 64 -#define usri11_country_code 68 -#define usri11_workstations 70 -#define usri11_max_storage 74 -#define usri11_units_per_week 78 -#define usri11_logon_hours 80 -#define usri11_code_page 84 -#define usri11_end 86 - -#define USER_PRIV_GUEST 0 -#define USER_PRIV_USER 1 -#define USER_PRIV_ADMIN 2 - -#define AF_OP_PRINT 0 -#define AF_OP_COMM 1 -#define AF_OP_SERVER 2 -#define AF_OP_ACCOUNTS 3 - - -static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *UserName = skip_string(str2,1); - char *p = skip_string(UserName,1); - int uLevel = SVAL(p,0); - char *p2; - - /* get NIS home of a previously validated user - simeon */ - /* With share level security vuid will always be zero. - Don't depend on vuser being non-null !!. JRA */ - user_struct *vuser = get_valid_user_struct(vuid); - if(vuser != NULL) - DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name)); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - - DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); - - /* check it's a supported variant */ - if (strcmp(str1,"zWrLh") != 0) return False; - switch( uLevel ) - { - case 0: p2 = "B21"; break; - case 1: p2 = "B21BB16DWzzWz"; break; - case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; - case 10: p2 = "B21Bzzz"; break; - case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break; - default: return False; - } - - if (strcmp(p2,str2) != 0) return False; - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - p2 = p + usri11_end; - - memset(p,0,21); - fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ - - if (uLevel > 0) - { - SCVAL(p,usri11_pad,0); /* padding - 1 byte */ - *p2 = 0; - } - if (uLevel >= 10) - { - SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ - pstrcpy(p2,"Comment"); - p2 = skip_string(p2,1); - - SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ - pstrcpy(p2,"UserComment"); - p2 = skip_string(p2,1); - - /* EEK! the cifsrap.txt doesn't have this in!!!! */ - SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); - p2 = skip_string(p2,1); - } - - if (uLevel == 11) /* modelled after NTAS 3.51 reply */ - { - SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ - SIVALS(p,usri11_password_age,-1); /* password age */ - SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - pstrcpy(p2, lp_logon_home()); - p2 = skip_string(p2,1); - SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ - pstrcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,usri11_last_logon,0); /* last logon */ - SIVAL(p,usri11_last_logoff,0); /* last logoff */ - SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ - SSVALS(p,usri11_num_logons,-1); /* num logons */ - SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ - pstrcpy(p2,"\\\\*"); - p2 = skip_string(p2,1); - SSVAL(p,usri11_country_code,0); /* country code */ - - SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ - pstrcpy(p2,""); - p2 = skip_string(p2,1); - - SIVALS(p,usri11_max_storage,-1); /* max storage */ - SSVAL(p,usri11_units_per_week,168); /* units per week */ - SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */ - - /* a simple way to get logon hours at all times. */ - memset(p2,0xff,21); - SCVAL(p2,21,0); /* fix zero termination */ - p2 = skip_string(p2,1); - - SSVAL(p,usri11_code_page,0); /* code page */ - } - if (uLevel == 1 || uLevel == 2) - { - memset(p+22,' ',16); /* password */ - SIVALS(p,38,-1); /* password age */ - SSVAL(p,42, - conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - pstrcpy(p2,lp_logon_home()); - p2 = skip_string(p2,1); - SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ - *p2++ = 0; - SSVAL(p,52,0); /* flags */ - SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ - pstrcpy(p2,lp_logon_script()); - standard_sub_conn( conn, p2 ); - p2 = skip_string(p2,1); - if (uLevel == 2) - { - SIVAL(p,60,0); /* auth_flags */ - SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); - p2 = skip_string(p2,1); - SIVAL(p,68,0); /* urs_comment */ - SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ - pstrcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,76,0); /* workstations */ - SIVAL(p,80,0); /* last_logon */ - SIVAL(p,84,0); /* last_logoff */ - SIVALS(p,88,-1); /* acct_expires */ - SIVALS(p,92,-1); /* max_storage */ - SSVAL(p,96,168); /* units_per_week */ - SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */ - memset(p2,-1,21); - p2 += 21; - SSVALS(p,102,-1); /* bad_pw_count */ - SSVALS(p,104,-1); /* num_logons */ - SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ - pstrcpy(p2,"\\\\%L"); - standard_sub_conn(conn, p2); - p2 = skip_string(p2,1); - SSVAL(p,110,49); /* country_code */ - SSVAL(p,112,860); /* code page */ - } - } +extern int DEBUGLEVEL; +extern int max_send; - *rdata_len = PTR_DIFF(p2,*rdata); +extern fstring local_machine; - SSVAL(*rparam,4,*rdata_len); /* is this right?? */ +#define NERR_notsupported 50 - return(True); -} +extern int smb_read_error; /******************************************************************* - get groups that a user is a member of - ******************************************************************/ -static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *UserName = skip_string(str2,1); - char *p = skip_string(UserName,1); - int uLevel = SVAL(p,0); - char *p2; - int count=0; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLeh") != 0) return False; - switch( uLevel ) { - case 0: p2 = "B21"; break; - default: return False; - } - if (strcmp(p2,str2) != 0) return False; - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - - /* XXXX we need a real SAM database some day */ - pstrcpy(p,"Users"); p += 21; count++; - pstrcpy(p,"Domain Users"); p += 21; count++; - pstrcpy(p,"Guests"); p += 21; count++; - pstrcpy(p,"Domain Guests"); p += 21; count++; - - *rdata_len = PTR_DIFF(p,*rdata); - - SSVAL(*rparam,4,count); /* is this right?? */ - SSVAL(*rparam,6,count); /* is this right?? */ + copies parameters and data, as needed, into the smb buffer - return(True); -} + *both* the data and params sections should be aligned. this + is fudged in the rpc pipes by + at present, only the data section is. this may be a possible + cause of some of the ipc problems being experienced. lkcl26dec97 + ******************************************************************/ -static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static void copy_trans_params_and_data(char *outbuf, int align, + char *rparam, int param_offset, int param_len, + char *rdata, int data_offset, int data_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - struct pack_desc desc; - char* name; - - uLevel = SVAL(p,0); - name = p + 2; - - memset((char *)&desc,'\0',sizeof(desc)); - - DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported varient */ - if (strcmp(str1,"OOWb54WrLh") != 0) return False; - if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.subformat = NULL; - desc.format = str2; - - if (init_package(&desc,1,0)) - { - PACKI(&desc,"W",0); /* code */ - PACKS(&desc,"B21",name); /* eff. name */ - PACKS(&desc,"B",""); /* pad */ - PACKI(&desc,"W", - conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - PACKI(&desc,"D",0); /* auth flags XXX */ - PACKI(&desc,"W",0); /* num logons */ - PACKI(&desc,"W",0); /* bad pw count */ - PACKI(&desc,"D",0); /* last logon */ - PACKI(&desc,"D",-1); /* last logoff */ - PACKI(&desc,"D",-1); /* logoff time */ - PACKI(&desc,"D",-1); /* kickoff time */ - PACKI(&desc,"D",0); /* password age */ - PACKI(&desc,"D",0); /* password can change */ - PACKI(&desc,"D",-1); /* password must change */ - { - fstring mypath; - fstrcpy(mypath,"\\\\"); - fstrcat(mypath,local_machine); - strupper(mypath); - PACKS(&desc,"z",mypath); /* computer */ - } - PACKS(&desc,"z",global_myworkgroup);/* domain */ - -/* JHT - By calling lp_logon_script() and standard_sub() we have */ -/* made sure all macros are fully substituted and available */ - { - pstring logon_script; - pstrcpy(logon_script,lp_logon_script()); - standard_sub_conn( conn, logon_script ); - PACKS(&desc,"z", logon_script); /* script path */ - } -/* End of JHT mods */ - - PACKI(&desc,"D",0x00000000); /* reserved */ - } - - *rdata_len = desc.usedlen; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); - return(True); -} + char *copy_into = smb_buf(outbuf)+1; + if(param_len < 0) + param_len = 0; -/**************************************************************************** - api_WAccessGetUserPerms - ****************************************************************************/ -static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *user = skip_string(str2,1); - char *resource = skip_string(user,1); + if(data_len < 0) + data_len = 0; - DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); + DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", + param_offset, param_offset + param_len, + data_offset , data_offset + data_len)); - /* check it's a supported varient */ - if (strcmp(str1,"zzh") != 0) return False; - if (strcmp(str2,"") != 0) return False; + if (param_len) + memcpy(copy_into, &rparam[param_offset], param_len); - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,0); /* errorcode */ - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,0x7f); /* permission flags */ + copy_into += param_len + align; - return(True); + if (data_len ) + memcpy(copy_into, &rdata[data_offset], data_len); } /**************************************************************************** - api_WPrintJobEnumerate - ****************************************************************************/ -static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int count; - int i; - int snum; - int job; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - uLevel = SVAL(p,2); - - memset((char *)&desc,'\0',sizeof(desc)); - memset((char *)&status,'\0',sizeof(status)); - - DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0))); - - /* check it's a supported varient */ - if (strcmp(str1,"WWrLh") != 0) return False; - if (!check_printjob_info(&desc,uLevel,str2)) return False; - - job = SVAL(p,0); - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = print_queue_status(snum,&queue,&status); - for (i = 0; i < count; i++) { - if (queue[i].job == job) break; - } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,1,0)) { - if (i < count) { - fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); - *rdata_len = desc.usedlen; - } - else { - desc.errcode = NERR_JobNotFound; - *rdata_len = 0; - } - } - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - if (queue) free(queue); - - DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* name = p; - int uLevel; - int count; - int i, succnt=0; - int snum; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - memset((char *)&desc,'\0',sizeof(desc)); - memset((char *)&status,'\0',sizeof(status)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - - DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLeh") != 0) return False; - if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */ - if (!check_printjob_info(&desc,uLevel,str2)) return False; - - snum = lp_servicenumber(name); - if (snum < 0 && pcap_printername_ok(name,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(name,pnum); - snum = lp_servicenumber(name); - } - } - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = print_queue_status(snum,&queue,&status); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,count,0)) { - succnt = 0; - for (i = 0; i < count; i++) { - fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); - if (desc.errcode == NERR_Success) succnt = i+1; - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,count); - - if (queue) free(queue); - - DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); - return(True); -} - -static int check_printdest_info(struct pack_desc* desc, - int uLevel, char* id) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "B9"; break; - case 1: desc->format = "B9B21WWzW"; break; - case 2: desc->format = "z"; break; - case 3: desc->format = "zzzWWzzzWW"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; -} - -static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc) -{ - char buf[100]; - strncpy(buf,SERVICE(snum),sizeof(buf)-1); - buf[sizeof(buf)-1] = 0; - strupper(buf); - if (uLevel <= 1) { - PACKS(desc,"B9",buf); /* szName */ - if (uLevel == 1) { - PACKS(desc,"B21",""); /* szUserName */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"W",0); /* time */ - } - } - if (uLevel == 2 || uLevel == 3) { - PACKS(desc,"z",buf); /* pszPrinterName */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszUserName */ - PACKS(desc,"z",""); /* pszLogAddr */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",""); /* pszComment */ - PACKS(desc,"z","NULL"); /* pszDrivers */ - PACKI(desc,"W",0); /* time */ - PACKI(desc,"W",0); /* pad1 */ - } - } -} - -static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* PrinterName = p; - int uLevel; - struct pack_desc desc; - int snum; - - memset((char *)&desc,'\0',sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - - DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - snum = lp_servicenumber(PrinterName); - if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(PrinterName,pnum); - snum = lp_servicenumber(PrinterName); - } - } - - if (snum < 0) { - *rdata_len = 0; - desc.errcode = NERR_DestNotFound; - desc.neededlen = 0; - } - else { - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - fill_printdest_info(conn,snum,uLevel,&desc); - } - *rdata_len = desc.usedlen; - } - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int queuecnt; - int i, n, succnt=0; - struct pack_desc desc; - int services = lp_numservices(); - - memset((char *)&desc,'\0',sizeof(desc)); - - uLevel = SVAL(p,0); - - DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,queuecnt,0)) { - succnt = 0; - n = 0; - for (i = 0; i < services; i++) { - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printdest_info(conn,i,uLevel,&desc); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); - - DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int succnt; - struct pack_desc desc; - - memset((char *)&desc,'\0',sizeof(desc)); - - uLevel = SVAL(p,0); - - DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B41") != 0) return False; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B41","NULL"); - } - - succnt = (desc.errcode == NERR_Success ? 1 : 0); - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); - - DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); - return(True); -} + Send a trans reply. + ****************************************************************************/ -static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +void send_trans_reply(char *outbuf, + char *rparam, int rparam_len, + char *rdata, int rdata_len, + BOOL buffer_too_large) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int succnt; - struct pack_desc desc; + int this_ldata,this_lparam; + int tot_data_sent = 0; + int tot_param_sent = 0; + int align; - memset((char *)&desc,'\0',sizeof(desc)); + int ldata = rdata ? rdata_len : 0; + int lparam = rparam ? rparam_len : 0; - uLevel = SVAL(p,0); + if (buffer_too_large) + DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata )); - DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); + this_lparam = MIN(lparam,max_send - 500); /* hack */ + this_ldata = MIN(ldata,max_send - (500+this_lparam)); - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; + align = ((this_lparam)%4); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lpd"); - } + set_message(outbuf,10,1+align+this_ldata+this_lparam,True); - succnt = (desc.errcode == NERR_Success ? 1 : 0); + if (buffer_too_large) + { + /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ + SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); + } - *rdata_len = desc.usedlen; + copy_trans_params_and_data(outbuf, align, + rparam, tot_param_sent, this_lparam, + rdata, tot_data_sent, this_ldata); - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); + SSVAL(outbuf,smb_vwv0,lparam); + SSVAL(outbuf,smb_vwv1,ldata); + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); + SSVAL(outbuf,smb_vwv5,0); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,0); + SSVAL(outbuf,smb_vwv9,0); - DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); - return(True); -} + show_msg(outbuf); + send_smb(smbd_server_fd(),outbuf); -static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int succnt; - struct pack_desc desc; + tot_data_sent = this_ldata; + tot_param_sent = this_lparam; - memset((char *)&desc,'\0',sizeof(desc)); + while (tot_data_sent < ldata || tot_param_sent < lparam) + { + this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */ + this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam)); - uLevel = SVAL(p,0); + if(this_lparam < 0) + this_lparam = 0; - DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); + if(this_ldata < 0) + this_ldata = 0; - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; + align = (this_lparam%4); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - memset((char *)&desc,'\0',sizeof(desc)); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lp0"); - } + set_message(outbuf,10,1+this_ldata+this_lparam+align,False); - succnt = (desc.errcode == NERR_Success ? 1 : 0); + copy_trans_params_and_data(outbuf, align, + rparam, tot_param_sent, this_lparam, + rdata, tot_data_sent, this_ldata); - *rdata_len = desc.usedlen; + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); + SSVAL(outbuf,smb_vwv5,tot_param_sent); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,tot_data_sent); + SSVAL(outbuf,smb_vwv9,0); - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); + show_msg(outbuf); + send_smb(smbd_server_fd(),outbuf); - DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); - return(True); + tot_data_sent += this_ldata; + tot_param_sent += this_lparam; + } } /**************************************************************************** @@ -3303,166 +317,6 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, return -1; } -/**************************************************************************** - The buffer was too small - ****************************************************************************/ - -static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - *rparam_len = MIN(*rparam_len,mprcnt); - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_BufTooSmall); - - DEBUG(3,("Supplied buffer too small in API command\n")); - - return(True); -} - - -/**************************************************************************** - The request is not supported - ****************************************************************************/ - -static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_notsupported); - SSVAL(*rparam,2,0); /* converter word */ - - DEBUG(3,("Unsupported API command\n")); - - return(True); -} - - - - -struct -{ - char *name; - int id; - BOOL (*fn)(connection_struct *,uint16,char *,char *, - int,int,char **,char **,int *,int *); - int flags; -} api_commands[] = { - {"RNetShareEnum", 0, api_RNetShareEnum,0}, - {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, - {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, - {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0}, - {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, - {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, - {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, - {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, - {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, - {"WPrintQueuePause", 74, api_WPrintQueuePurge,0}, - {"WPrintQueueResume", 75, api_WPrintQueuePurge,0}, - {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, - {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, - {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, - {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0}, - {"RDosPrintJobResume",83, api_RDosPrintJobDel,0}, - {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, - {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, - {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, - {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0}, - {"NetServerEnum", 104, api_RNetServerEnum,0}, - {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, - {"SetUserPassword", 115, api_SetUserPassword,0}, - {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0}, - {"PrintJobInfo", 147, api_PrintJobInfo,0}, - {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0}, - {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0}, - {"WPrintPortEnum", 207, api_WPrintPortEnum,0}, - {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0}, - {NULL, -1, api_Unsupported,0}}; - - -/**************************************************************************** - Handle remote api calls - ****************************************************************************/ - -static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, - int tdscnt,int tpscnt,int mdrcnt,int mprcnt) -{ - int api_command; - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; - BOOL reply=False; - int i; - - if (!params) { - DEBUG(0,("ERROR: NULL params in api_reply()\n")); - return 0; - } - - api_command = SVAL(params,0); - - DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - api_command, - params+2, - skip_string(params+2,1), - tdscnt,tpscnt,mdrcnt,mprcnt)); - - for (i=0;api_commands[i].name;i++) { - if (api_commands[i].id == api_command && api_commands[i].fn) { - DEBUG(3,("Doing %s\n",api_commands[i].name)); - break; - } - } - - rdata = (char *)malloc(1024); - if (rdata) - memset(rdata,'\0',1024); - - rparam = (char *)malloc(1024); - if (rparam) - memset(rparam,'\0',1024); - - if(!rdata || !rparam) { - DEBUG(0,("api_reply: malloc fail !\n")); - return -1; - } - - reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - - if (rdata_len > mdrcnt || - rparam_len > mprcnt) { - reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - /* if we get False back then it's actually unsupported */ - if (!reply) - api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); - - if (rdata ) - free(rdata); - if (rparam) - free(rparam); - - return -1; -} - /**************************************************************************** handle named pipe commands ****************************************************************************/ diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c new file mode 100644 index 0000000000..391a94596a --- /dev/null +++ b/source3/smbd/lanman.c @@ -0,0 +1,3180 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Inter-process communication and named pipe handling + Copyright (C) Andrew Tridgell 1992-1998 + + SMB Version handling + Copyright (C) John H Terpstra 1995-1998 + + 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. + */ +/* + This file handles the named pipe and mailslot calls + in the SMBtrans protocol + */ + +#include "includes.h" +#include "nterr.h" + +#ifdef CHECK_TYPES +#undef CHECK_TYPES +#endif +#define CHECK_TYPES 0 + +extern int DEBUGLEVEL; + +extern fstring local_machine; +extern fstring global_myworkgroup; + +#define NERR_Success 0 +#define NERR_badpass 86 +#define NERR_notsupported 50 + +#define NERR_BASE (2100) +#define NERR_BufTooSmall (NERR_BASE+23) +#define NERR_JobNotFound (NERR_BASE+51) +#define NERR_DestNotFound (NERR_BASE+52) + +#define ACCESS_READ 0x01 +#define ACCESS_WRITE 0x02 +#define ACCESS_CREATE 0x04 + +#define SHPWLEN 8 /* share password length */ + +static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); +static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); + + +static int CopyExpanded(connection_struct *conn, + int snum, char** dst, char* src, int* n) +{ + pstring buf; + int l; + + if (!src || !dst || !n || !(*dst)) return(0); + + StrnCpy(buf,src,sizeof(buf)/2); + pstring_sub(buf,"%S",lp_servicename(snum)); + standard_sub_conn(conn,buf); + StrnCpy(*dst,buf,*n); + l = strlen(*dst) + 1; + (*dst) += l; + (*n) -= l; + return l; +} + +static int CopyAndAdvance(char** dst, char* src, int* n) +{ + int l; + if (!src || !dst || !n || !(*dst)) return(0); + StrnCpy(*dst,src,*n-1); + l = strlen(*dst) + 1; + (*dst) += l; + (*n) -= l; + return l; +} + +static int StrlenExpanded(connection_struct *conn, int snum, char* s) +{ + pstring buf; + if (!s) return(0); + StrnCpy(buf,s,sizeof(buf)/2); + pstring_sub(buf,"%S",lp_servicename(snum)); + standard_sub_conn(conn,buf); + return strlen(buf) + 1; +} + +static char* Expand(connection_struct *conn, int snum, char* s) +{ + static pstring buf; + if (!s) return(NULL); + StrnCpy(buf,s,sizeof(buf)/2); + pstring_sub(buf,"%S",lp_servicename(snum)); + standard_sub_conn(conn,buf); + return &buf[0]; +} + +/******************************************************************* + check a API string for validity when we only need to check the prefix + ******************************************************************/ +static BOOL prefix_ok(char *str,char *prefix) +{ + return(strncmp(str,prefix,strlen(prefix)) == 0); +} + +struct pack_desc { + char* format; /* formatstring for structure */ + char* subformat; /* subformat for structure */ + char* base; /* baseaddress of buffer */ + int buflen; /* remaining size for fixed part; on init: length of base */ + int subcount; /* count of substructures */ + char* structbuf; /* pointer into buffer for remaining fixed part */ + int stringlen; /* remaining size for variable part */ + char* stringbuf; /* pointer into buffer for remaining variable part */ + int neededlen; /* total needed size */ + int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ + char* curpos; /* current position; pointer into format or subformat */ + int errcode; +}; + +static int get_counter(char** p) +{ + int i, n; + if (!p || !(*p)) return(1); + if (!isdigit((int)**p)) return 1; + for (n = 0;;) { + i = **p; + if (isdigit(i)) + n = 10 * n + (i - '0'); + else + return n; + (*p)++; + } +} + +static int getlen(char* p) +{ + int n = 0; + if (!p) return(0); + while (*p) { + switch( *p++ ) { + case 'W': /* word (2 byte) */ + n += 2; + break; + case 'K': /* status word? (2 byte) */ + n += 2; + break; + case 'N': /* count of substructures (word) at end */ + n += 2; + break; + case 'D': /* double word (4 byte) */ + case 'z': /* offset to zero terminated string (4 byte) */ + case 'l': /* offset to user data (4 byte) */ + n += 4; + break; + case 'b': /* offset to data (with counter) (4 byte) */ + n += 4; + get_counter(&p); + break; + case 'B': /* byte (with optional counter) */ + n += get_counter(&p); + break; + } + } + return n; +} + +static BOOL init_package(struct pack_desc* p, int count, int subcount) +{ + int n = p->buflen; + int i; + + if (!p->format || !p->base) return(False); + + i = count * getlen(p->format); + if (p->subformat) i += subcount * getlen(p->subformat); + p->structbuf = p->base; + p->neededlen = 0; + p->usedlen = 0; + p->subcount = 0; + p->curpos = p->format; + if (i > n) { + p->neededlen = i; + i = n = 0; + p->errcode = ERRmoredata; + } + else + p->errcode = NERR_Success; + p->buflen = i; + n -= i; + p->stringbuf = p->base + i; + p->stringlen = n; + return(p->errcode == NERR_Success); +} + +#ifdef HAVE_STDARG_H +static int package(struct pack_desc* p, ...) +{ +#else +static int package(va_alist) +va_dcl +{ + struct pack_desc* p; +#endif + va_list args; + int needed=0, stringneeded; + char* str=NULL; + int is_string=0, stringused; + int32 temp; + +#ifdef HAVE_STDARG_H + va_start(args,p); +#else + va_start(args); + p = va_arg(args,struct pack_desc *); +#endif + + if (!*p->curpos) { + if (!p->subcount) + p->curpos = p->format; + else { + p->curpos = p->subformat; + p->subcount--; + } + } +#if CHECK_TYPES + str = va_arg(args,char*); + SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); +#endif + stringneeded = -1; + + if (!p->curpos) { + va_end(args); + return(0); + } + + switch( *p->curpos++ ) { + case 'W': /* word (2 byte) */ + needed = 2; + temp = va_arg(args,int); + if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); + break; + case 'K': /* status word? (2 byte) */ + needed = 2; + temp = va_arg(args,int); + if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); + break; + case 'N': /* count of substructures (word) at end */ + needed = 2; + p->subcount = va_arg(args,int); + if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount); + break; + case 'D': /* double word (4 byte) */ + needed = 4; + temp = va_arg(args,int); + if (p->buflen >= needed) SIVAL(p->structbuf,0,temp); + break; + case 'B': /* byte (with optional counter) */ + needed = get_counter(&p->curpos); + { + char *s = va_arg(args,char*); + if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1); + } + break; + case 'z': /* offset to zero terminated string (4 byte) */ + str = va_arg(args,char*); + stringneeded = (str ? strlen(str)+1 : 0); + is_string = 1; + break; + case 'l': /* offset to user data (4 byte) */ + str = va_arg(args,char*); + stringneeded = va_arg(args,int); + is_string = 0; + break; + case 'b': /* offset to data (with counter) (4 byte) */ + str = va_arg(args,char*); + stringneeded = get_counter(&p->curpos); + is_string = 0; + break; + } + va_end(args); + if (stringneeded >= 0) { + needed = 4; + if (p->buflen >= needed) { + stringused = stringneeded; + if (stringused > p->stringlen) { + stringused = (is_string ? p->stringlen : 0); + if (p->errcode == NERR_Success) p->errcode = ERRmoredata; + } + if (!stringused) + SIVAL(p->structbuf,0,0); + else { + SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); + memcpy(p->stringbuf,str?str:"",stringused); + if (is_string) p->stringbuf[stringused-1] = '\0'; + p->stringbuf += stringused; + p->stringlen -= stringused; + p->usedlen += stringused; + } + } + p->neededlen += stringneeded; + } + p->neededlen += needed; + if (p->buflen >= needed) { + p->structbuf += needed; + p->buflen -= needed; + p->usedlen += needed; + } + else { + if (p->errcode == NERR_Success) p->errcode = ERRmoredata; + } + return 1; +} + +#if CHECK_TYPES +#define PACK(desc,t,v) package(desc,t,v,0,0,0,0) +#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0) +#else +#define PACK(desc,t,v) package(desc,v) +#define PACKl(desc,t,v,l) package(desc,v,l) +#endif + +static void PACKI(struct pack_desc* desc,char *t,int v) +{ + PACK(desc,t,v); +} + +static void PACKS(struct pack_desc* desc,char *t,char *v) +{ + PACK(desc,t,v); +} + + +/**************************************************************************** + get a print queue + ****************************************************************************/ +static void PackDriverData(struct pack_desc* desc) +{ + char drivdata[4+4+32]; + SIVAL(drivdata,0,sizeof drivdata); /* cb */ + SIVAL(drivdata,4,1000); /* lVersion */ + memset(drivdata+8,0,32); /* szDeviceName */ + pstrcpy(drivdata+8,"NULL"); + PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ +} + +static int check_printq_info(struct pack_desc* desc, + int uLevel, char *id1, char *id2) +{ + desc->subformat = NULL; + switch( uLevel ) { + case 0: + desc->format = "B13"; + break; + case 1: + desc->format = "B13BWWWzzzzzWW"; + break; + case 2: + desc->format = "B13BWWWzzzzzWN"; + desc->subformat = "WB21BB16B10zWWzDDz"; + break; + case 3: + desc->format = "zWWWWzzzzWWzzl"; + break; + case 4: + desc->format = "zWWWWzzzzWNzzl"; + desc->subformat = "WWzWWDDzz"; + break; + case 5: + desc->format = "z"; + break; + case 51: + desc->format = "K"; + break; + case 52: + desc->format = "WzzzzzzzzN"; + desc->subformat = "z"; + break; + default: return False; + } + if (strcmp(desc->format,id1) != 0) return False; + if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False; + return True; +} + + +#define JOB_STATUS_QUEUED 0 +#define JOB_STATUS_PAUSED 1 +#define JOB_STATUS_SPOOLING 2 +#define JOB_STATUS_PRINTING 3 +#define JOB_STATUS_PRINTED 4 + +#define QUEUE_STATUS_PAUSED 1 +#define QUEUE_STATUS_ERROR 2 + +/* turn a print job status into a on the wire status +*/ +static int printj_status(int v) +{ + switch (v) { + case LPQ_QUEUED: + return JOB_STATUS_QUEUED; + case LPQ_PAUSED: + return JOB_STATUS_PAUSED; + case LPQ_SPOOLING: + return JOB_STATUS_SPOOLING; + case LPQ_PRINTING: + return JOB_STATUS_PRINTING; + } + return 0; +} + +/* turn a print queue status into a on the wire status +*/ +static int printq_status(int v) +{ + switch (v) { + case LPQ_QUEUED: + return 0; + case LPQ_PAUSED: + return QUEUE_STATUS_PAUSED; + } + return QUEUE_STATUS_ERROR; +} + +static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, + struct pack_desc* desc, + print_queue_struct* queue, int n) +{ + time_t t = queue->time; + + /* the client expects localtime */ + t -= TimeDiff(t); + + PACKI(desc,"W",queue->job); /* uJobId */ + if (uLevel == 1) { + PACKS(desc,"B21",queue->user); /* szUserName */ + PACKS(desc,"B",""); /* pad */ + PACKS(desc,"B16",""); /* szNotifyName */ + PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ + PACKS(desc,"z",""); /* pszParms */ + PACKI(desc,"W",n+1); /* uPosition */ + PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",t); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z",queue->file); /* pszComment */ + } + if (uLevel == 2 || uLevel == 3) { + PACKI(desc,"W",queue->priority); /* uPriority */ + PACKS(desc,"z",queue->user); /* pszUserName */ + PACKI(desc,"W",n+1); /* uPosition */ + PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ + PACKI(desc,"D",t); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z","Samba"); /* pszComment */ + PACKS(desc,"z",queue->file); /* pszDocument */ + if (uLevel == 3) { + PACKS(desc,"z",""); /* pszNotifyName */ + PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ + PACKS(desc,"z",""); /* pszParms */ + PACKS(desc,"z",""); /* pszStatus */ + PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ + PACKS(desc,"z","lpd"); /* pszQProcName */ + PACKS(desc,"z",""); /* pszQProcParms */ + PACKS(desc,"z","NULL"); /* pszDriverName */ + PackDriverData(desc); /* pDriverData */ + PACKS(desc,"z",""); /* pszPrinterName */ + } + } +} + + +static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, + struct pack_desc* desc, + int count, print_queue_struct* queue, + print_status_struct* status) +{ + int i,ok=0; + pstring tok,driver,datafile,langmon,helpfile,datatype; + char *p; + char **lines, *line; + + lines = file_lines_load(lp_driverfile(),NULL); + if (!lines) { + DEBUG(3,("fill_printq_info: Can't open %s - %s\n", + lp_driverfile(),strerror(errno))); + desc->errcode=NERR_notsupported; + return; + } + + /* lookup the long printer driver name in the file + description */ + for (i=0;lines[i] && !ok;i++) { + p = lines[i]; + if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + ok=1; + } + line = strdup(p); + p = line; + file_lines_free(lines); + + /* driver file name */ + if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0; + /* data file name */ + if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0; + /* + * for the next tokens - which may be empty - I have + * to check for empty tokens first because the + * next_token function will skip all empty token + * fields */ + if (ok) { + /* help file */ + if (*p == ':') { + *helpfile = '\0'; + p++; + } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0; + } + + if (ok) { + /* language monitor */ + if (*p == ':') { + *langmon = '\0'; + p++; + } else if (!next_token(&p,langmon,":",sizeof(langmon))) + ok = 0; + } + + /* default data type */ + if (ok && !next_token(&p,datatype,":",sizeof(datatype))) + ok = 0; + + if (ok) { + PACKI(desc,"W",0x0400); /* don't know */ + PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ + PACKS(desc,"z",driver); /* Driverfile Name */ + PACKS(desc,"z",datafile); /* Datafile name */ + PACKS(desc,"z",langmon); /* language monitor */ + PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ + PACKS(desc,"z",datatype); /* default data type */ + PACKS(desc,"z",helpfile); /* helpfile name */ + PACKS(desc,"z",driver); /* driver name */ + DEBUG(3,("Driver:%s:\n",driver)); + DEBUG(3,("Data File:%s:\n",datafile)); + DEBUG(3,("Language Monitor:%s:\n",langmon)); + DEBUG(3,("Data Type:%s:\n",datatype)); + DEBUG(3,("Help File:%s:\n",helpfile)); + PACKI(desc,"N",count); /* number of files to copy */ + for (i=0;i gave %d entries\n", + SERVICE(snum),count)); + } else { + DEBUG(3,("fill_printq_info: Can't supply driver files\n")); + desc->errcode=NERR_notsupported; + } + free(line); +} + + +static void fill_printq_info(connection_struct *conn, int snum, int uLevel, + struct pack_desc* desc, + int count, print_queue_struct* queue, + print_status_struct* status) +{ + switch (uLevel) { + case 1: + case 2: + PACKS(desc,"B13",SERVICE(snum)); + break; + case 3: + case 4: + case 5: + PACKS(desc,"z",Expand(conn,snum,SERVICE(snum))); + break; + case 51: + PACKI(desc,"K",printq_status(status->status)); + break; + } + + if (uLevel == 1 || uLevel == 2) { + PACKS(desc,"B",""); /* alignment */ + PACKI(desc,"W",5); /* priority */ + PACKI(desc,"W",0); /* start time */ + PACKI(desc,"W",0); /* until time */ + PACKS(desc,"z",""); /* pSepFile */ + PACKS(desc,"z","lpd"); /* pPrProc */ + PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ + PACKS(desc,"z",""); /* pParms */ + if (snum < 0) { + PACKS(desc,"z","UNKNOWN PRINTER"); + PACKI(desc,"W",LPSTAT_ERROR); + } + else if (!status || !status->message[0]) { + PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); + PACKI(desc,"W",LPSTAT_OK); /* status */ + } else { + PACKS(desc,"z",status->message); + PACKI(desc,"W",printq_status(status->status)); /* status */ + } + PACKI(desc,(uLevel == 1 ? "W" : "N"),count); + } + + if (uLevel == 3 || uLevel == 4) { + PACKI(desc,"W",5); /* uPriority */ + PACKI(desc,"W",0); /* uStarttime */ + PACKI(desc,"W",0); /* uUntiltime */ + PACKI(desc,"W",5); /* pad1 */ + PACKS(desc,"z",""); /* pszSepFile */ + PACKS(desc,"z","WinPrint"); /* pszPrProc */ + PACKS(desc,"z",""); /* pszParms */ + if (!status || !status->message[0]) { + PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */ + PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ + } else { + PACKS(desc,"z",status->message); /* pszComment */ + PACKI(desc,"W",printq_status(status->status)); /* fsStatus */ + } + PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ + PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ + PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ + PackDriverData(desc); /* pDriverData */ + } + + if (uLevel == 2 || uLevel == 4) { + int i; + for (i=0;i + * to return the 'invalid info level' error if an + * unknown level was requested. + */ + *rdata_len = 0; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,ERROR_INVALID_LEVEL); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,0); + return(True); + } + + snum = lp_servicenumber(QueueName); + if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { + int pnum = lp_servicenumber(PRINTERS_NAME); + if (pnum >= 0) { + lp_add_printer(QueueName,pnum); + snum = lp_servicenumber(QueueName); + } + } + + if (snum < 0 || !VALID_SNUM(snum)) return(False); + + if (uLevel==52) { + count = get_printerdrivernumber(snum); + DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); + } else { + count = print_queue_status(snum, &queue,&status); + } + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,count)) { + desc.subcount = count; + fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); + } else if(uLevel == 0) { + /* + * This is a *disgusting* hack. + * This is *so* bad that even I'm embarrassed (and I + * have no shame). Here's the deal : + * Until we get the correct SPOOLSS code into smbd + * then when we're running with NT SMB support then + * NT makes this call with a level of zero, and then + * immediately follows it with an open request to + * the \\SRVSVC pipe. If we allow that open to + * succeed then NT barfs when it cannot open the + * \\SPOOLSS pipe immediately after and continually + * whines saying "Printer name is invalid" forever + * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC + * to fail, then NT downgrades to using the downlevel code + * and everything works as well as before. I hate + * myself for adding this code.... JRA. + */ + + fail_next_srvsvc_open(); + } + + *rdata_len = desc.usedlen; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); + + if (queue) free(queue); + + return(True); +} + + +/**************************************************************************** + view list of all print jobs on all queues + ****************************************************************************/ +static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data, + int mdrcnt, int mprcnt, + char **rdata, char** rparam, + int *rdata_len, int *rparam_len) +{ + char *param_format = param+2; + char *output_format1 = skip_string(param_format,1); + char *p = skip_string(output_format1,1); + int uLevel = SVAL(p,0); + char *output_format2 = p + 4; + int services = lp_numservices(); + int i, n; + struct pack_desc desc; + print_queue_struct **queue = NULL; + print_status_struct *status = NULL; + int* subcntarr = NULL; + int queuecnt, subcnt=0, succnt=0; + + memset((char *)&desc,'\0',sizeof(desc)); + + DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); + + if (!prefix_ok(param_format,"WrLeh")) return False; + if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) { + /* + * Patch from Scott Moomaw + * to return the 'invalid info level' error if an + * unknown level was requested. + */ + *rdata_len = 0; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,ERROR_INVALID_LEVEL); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,0); + return(True); + } + + queuecnt = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) + queuecnt++; + if (uLevel > 0) { + if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + return False; + } + memset(queue,0,queuecnt*sizeof(print_queue_struct*)); + if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + return False; + } + memset(status,0,queuecnt*sizeof(print_status_struct)); + if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + return False; + } + subcnt = 0; + n = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + subcntarr[n] = print_queue_status(i, &queue[n],&status[n]); + subcnt += subcntarr[n]; + n++; + } + } + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,queuecnt,subcnt)) { + n = 0; + succnt = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); + n++; + if (desc.errcode == NERR_Success) succnt = n; + } + } + + if (subcntarr) free(subcntarr); + + *rdata_len = desc.usedlen; + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,queuecnt); + + for (i = 0; i < queuecnt; i++) { + if (queue && queue[i]) free(queue[i]); + } + + if (queue) free(queue); + if (status) free(status); + + return True; +} + +/**************************************************************************** + get info level for a server list query + ****************************************************************************/ +static BOOL check_server_info(int uLevel, char* id) +{ + switch( uLevel ) { + case 0: + if (strcmp(id,"B16") != 0) return False; + break; + case 1: + if (strcmp(id,"B16BBDz") != 0) return False; + break; + default: + return False; + } + return True; +} + +struct srv_info_struct +{ + fstring name; + uint32 type; + fstring comment; + fstring domain; + BOOL server_added; +}; + + +/******************************************************************* + 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, + char *domain) +{ + int count=0; + int alloced=0; + char **lines; + BOOL local_list_only; + int i; + + lines = file_lines_load(lock_path(SERVER_LIST), NULL); + if (!lines) { + DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); + return(0); + } + + /* request for everything is code for request all servers */ + if (servertype == SV_TYPE_ALL) + servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + + local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); + + DEBUG(4,("Servertype search: %8x\n",servertype)); + + for (i=0;lines[i];i++) { + fstring stype; + struct srv_info_struct *s; + char *ptr = lines[i]; + BOOL ok = True; + + if (!*ptr) continue; + + if (count == alloced) { + alloced += 10; + (*servers) = (struct srv_info_struct *) + Realloc(*servers,sizeof(**servers)*alloced); + if (!(*servers)) return(0); + memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); + } + s = &(*servers)[count]; + + if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue; + if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue; + if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue; + if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) { + /* this allows us to cope with an old nmbd */ + pstrcpy(s->domain,global_myworkgroup); + } + + if (sscanf(stype,"%X",&s->type) != 1) { + DEBUG(4,("r:host file ")); + ok = False; + } + + /* Filter the servers/domains we return based on what was asked for. */ + + /* Check to see if we are being asked for a local list only. */ + if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) { + DEBUG(4,("r: local list only")); + ok = False; + } + + /* doesn't match up: don't want it */ + 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: dom mismatch ")); + ok = False; + } + + if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) + { + ok = False; + } + + /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ + s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; + + if (ok) + { + DEBUG(4,("**SV** %20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + + s->server_added = True; + count++; + } + else + { + DEBUG(4,("%20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + } + } + + file_lines_free(lines); + return(count); +} + + +/******************************************************************* + fill in a server info structure + ******************************************************************/ +static int fill_srv_info(struct srv_info_struct *service, + int uLevel, char **buf, int *buflen, + char **stringbuf, int *stringspace, char *baseaddr) +{ + int struct_len; + char* p; + char* p2; + int l2; + int len; + + switch (uLevel) { + case 0: struct_len = 16; break; + case 1: struct_len = 26; break; + default: return -1; + } + + if (!buf) + { + len = 0; + switch (uLevel) + { + case 1: + len = strlen(service->comment)+1; + break; + } + + if (buflen) *buflen = struct_len; + if (stringspace) *stringspace = len; + return struct_len + len; + } + + len = struct_len; + p = *buf; + if (*buflen < struct_len) return -1; + if (stringbuf) + { + p2 = *stringbuf; + l2 = *stringspace; + } + else + { + p2 = p + struct_len; + l2 = *buflen - struct_len; + } + if (!baseaddr) baseaddr = p; + + switch (uLevel) + { + case 0: + StrnCpy(p,service->name,15); + break; + + case 1: + StrnCpy(p,service->name,15); + SIVAL(p,18,service->type); + SIVAL(p,22,PTR_DIFF(p2,baseaddr)); + len += CopyAndAdvance(&p2,service->comment,&l2); + break; + } + + if (stringbuf) + { + *buf = p + struct_len; + *buflen -= struct_len; + *stringbuf = p2; + *stringspace = l2; + } + else + { + *buf = p2; + *buflen -= len; + } + return len; +} + + +static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) +{ + return(strcmp(s1->name,s2->name)); +} + +/**************************************************************************** + view list of servers available (or possibly domains). The info is + extracted from lists saved by nmbd on the local host + ****************************************************************************/ +static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + uint32 servertype = IVAL(p,4); + char *p2; + int data_len, fixed_len, string_len; + int f_len = 0, s_len = 0; + struct srv_info_struct *servers=NULL; + int counted=0,total=0; + int i,missed; + fstring domain; + BOOL domain_request; + BOOL local_request; + + /* If someone sets all the bits they don't really mean to set + DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the + known servers. */ + + if (servertype == SV_TYPE_ALL) + servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + + /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set + any other bit (they may just set this bit on it's own) they + want all the locally seen servers. However this bit can be + set on its own so set the requested servers to be + ALL - DOMAIN_ENUM. */ + + if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) + servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); + + domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); + local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0); + + p += 8; + + if (!prefix_ok(str1,"WrLehD")) return False; + if (!check_server_info(uLevel,str2)) return False; + + 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, "WrLehDz") == 0) { + StrnCpy(domain, p, sizeof(fstring)-1); + } else { + StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1); + } + + if (lp_browse_list()) + total = get_server_info(servertype,&servers,domain); + + data_len = fixed_len = string_len = 0; + missed = 0; + + qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); + + { + char *lastname=NULL; + + for (i=0;iname)) continue; + lastname = s->name; + 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; + } else { + missed++; + } + } + } + + *rdata_len = fixed_len + string_len; + *rdata = REALLOC(*rdata,*rdata_len); + memset(*rdata,'\0',*rdata_len); + + p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ + p = *rdata; + f_len = fixed_len; + s_len = string_len; + + { + char *lastname=NULL; + int count2 = counted; + for (i = 0; i < total && count2;i++) + { + struct srv_info_struct *s = &servers[i]; + if (lastname && strequal(lastname,s->name)) continue; + lastname = s->name; + 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--; + } + } + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); + + if (servers) free(servers); + + DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", + domain,uLevel,counted,counted+missed)); + + return(True); +} + +/**************************************************************************** + command 0x34 - suspected of being a "Lookup Names" stub api + ****************************************************************************/ +static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + int counted=0; + int missed=0; + + DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", + str1, str2, p, uLevel, buf_len)); + + if (!prefix_ok(str1,"zWrLeh")) return False; + + *rdata_len = 0; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + + SSVAL(*rparam,0,0x08AC); /* informational warning message */ + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); + + return(True); +} + +/**************************************************************************** + get info about a share + ****************************************************************************/ +static BOOL check_share_info(int uLevel, char* id) +{ + switch( uLevel ) { + case 0: + if (strcmp(id,"B13") != 0) return False; + break; + case 1: + if (strcmp(id,"B13BWz") != 0) return False; + break; + case 2: + if (strcmp(id,"B13BWzWWWzB9B") != 0) return False; + break; + case 91: + if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False; + break; + default: return False; + } + return True; +} + +static int fill_share_info(connection_struct *conn, int snum, int uLevel, + char** buf, int* buflen, + char** stringbuf, int* stringspace, char* baseaddr) +{ + int struct_len; + char* p; + char* p2; + int l2; + int len; + + switch( uLevel ) { + case 0: struct_len = 13; break; + case 1: struct_len = 20; break; + case 2: struct_len = 40; break; + case 91: struct_len = 68; break; + default: return -1; + } + + + if (!buf) + { + len = 0; + if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum)); + if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; + if (buflen) *buflen = struct_len; + if (stringspace) *stringspace = len; + return struct_len + len; + } + + len = struct_len; + p = *buf; + if ((*buflen) < struct_len) return -1; + if (stringbuf) + { + p2 = *stringbuf; + l2 = *stringspace; + } + else + { + p2 = p + struct_len; + l2 = (*buflen) - struct_len; + } + if (!baseaddr) baseaddr = p; + + StrnCpy(p,lp_servicename(snum),13); + + if (uLevel > 0) + { + int type; + CVAL(p,13) = 0; + type = STYPE_DISKTREE; + if (lp_print_ok(snum)) type = STYPE_PRINTQ; + if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; + SSVAL(p,14,type); /* device type */ + SIVAL(p,16,PTR_DIFF(p2,baseaddr)); + len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); + } + + if (uLevel > 1) + { + SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ + SSVALS(p,22,-1); /* max uses */ + SSVAL(p,24,1); /* current uses */ + SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ + len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); + memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ + } + + if (uLevel > 2) + { + memset(p+40,0,SHPWLEN+2); + SSVAL(p,50,0); + SIVAL(p,52,0); + SSVAL(p,56,0); + SSVAL(p,58,0); + SIVAL(p,60,0); + SSVAL(p,64,0); + SSVAL(p,66,0); + } + + if (stringbuf) + { + (*buf) = p + struct_len; + (*buflen) -= struct_len; + (*stringbuf) = p2; + (*stringspace) = l2; + } + else + { + (*buf) = p2; + (*buflen) -= len; + } + return len; +} + +static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *netname = skip_string(str2,1); + char *p = skip_string(netname,1); + int uLevel = SVAL(p,0); + int snum = find_service(netname); + + if (snum < 0) return False; + + /* check it's a supported varient */ + if (!prefix_ok(str1,"zWrLh")) return False; + if (!check_share_info(uLevel,str2)) return False; + + *rdata = REALLOC(*rdata,mdrcnt); + p = *rdata; + *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); + if (*rdata_len < 0) return False; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + + return(True); +} + +/**************************************************************************** + view list of shares available + ****************************************************************************/ +static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + char *p2; + int count=lp_numservices(); + int total=0,counted=0; + BOOL missed = False; + int i; + int data_len, fixed_len, string_len; + int f_len = 0, s_len = 0; + + if (!prefix_ok(str1,"WrLeh")) return False; + if (!check_share_info(uLevel,str2)) return False; + + data_len = fixed_len = string_len = 0; + for (i=0;itm_hour; + CVAL(p,9) = t->tm_min; + CVAL(p,10) = t->tm_sec; + CVAL(p,11) = 0; /* hundredths of seconds */ + SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */ + SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ + CVAL(p,16) = t->tm_mday; + CVAL(p,17) = t->tm_mon + 1; + SSVAL(p,18,1900+t->tm_year); + CVAL(p,20) = t->tm_wday; + } + + + return(True); +} + +/**************************************************************************** + Set the user password. +*****************************************************************************/ + +static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *p = skip_string(param+2,2); + fstring user; + fstring pass1,pass2; + + fstrcpy(user,p); + + p = skip_string(p,1); + + memset(pass1,'\0',sizeof(pass1)); + memset(pass2,'\0',sizeof(pass2)); + memcpy(pass1,p,16); + memcpy(pass2,p+16,16); + + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,2,0); /* converter word */ + + DEBUG(3,("Set password for <%s>\n",user)); + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); + + /* + * Attempt to verify the old password against smbpasswd entries + * Win98 clients send old and new password in plaintext for this call. + */ + + { + fstring saved_pass2; + struct smb_passwd *smbpw = NULL; + + /* + * Save the new password as change_oem_password overwrites it + * with zeros. + */ + + fstrcpy(saved_pass2, pass2); + + if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) && + change_oem_password(smbpw,pass2,False)) + { + SSVAL(*rparam,0,NERR_Success); + + /* + * If unix password sync was requested, attempt to change + * the /etc/passwd database also. Return failure if this cannot + * be done. + */ + + if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) + SSVAL(*rparam,0,NERR_badpass); + } + } + + /* + * If the above failed, attempt the plaintext password change. + * This tests against the /etc/passwd database only. + */ + + if(SVAL(*rparam,0) != NERR_Success) + { + if (password_ok(user, pass1,strlen(pass1),NULL) && + chgpasswd(user,pass1,pass2,False)) + { + SSVAL(*rparam,0,NERR_Success); + } + } + + /* + * If the plaintext change failed, attempt + * the old encrypted method. NT will generate this + * after trying the samr method. Note that this + * method is done as a last resort as this + * password change method loses the NT password hash + * and cannot change the UNIX password as no plaintext + * is received. + */ + + if(SVAL(*rparam,0) != NERR_Success) + { + struct smb_passwd *sampw = NULL; + + if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) && + change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2)) + { + SSVAL(*rparam,0,NERR_Success); + } + } + + memset((char *)pass1,'\0',sizeof(fstring)); + memset((char *)pass2,'\0',sizeof(fstring)); + + return(True); +} + +/**************************************************************************** + Set the user password (SamOEM version - gets plaintext). +****************************************************************************/ + +static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + fstring user; + char *p = param + 2; + *rparam_len = 2; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_badpass); + + /* + * Check the parameter definition is correct. + */ + if(!strequal(param + 2, "zsT")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); + return False; + } + p = skip_string(p, 1); + + if(!strequal(p, "B516B16")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); + return False; + } + p = skip_string(p,1); + + fstrcpy(user,p); + p = skip_string(p,1); + + DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); + + if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)) + { + SSVAL(*rparam,0,NERR_Success); + } + + return(True); +} + +/**************************************************************************** + delete a print job + Form: <> + ****************************************************************************/ +static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + int function = SVAL(param,0); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int jobid, errcode; + + jobid = SVAL(p,0); + + /* check it's a supported varient */ + if (!(strcsequal(str1,"W") && strcsequal(str2,""))) + return(False); + + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + *rdata_len = 0; + + if (!print_job_exists(jobid)) { + errcode = NERR_JobNotFound; + goto out; + } + + errcode = NERR_notsupported; + + switch (function) { + case 81: /* delete */ + if (print_job_delete(jobid)) errcode = NERR_Success; + break; + case 82: /* pause */ + if (print_job_pause(jobid)) errcode = NERR_Success; + break; + case 83: /* resume */ + if (print_job_resume(jobid)) errcode = NERR_Success; + break; + } + + out: + SSVAL(*rparam,0,errcode); + SSVAL(*rparam,2,0); /* converter word */ + + return(True); +} + +/**************************************************************************** + Purge a print queue - or pause or resume it. + ****************************************************************************/ +static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + int function = SVAL(param,0); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *QueueName = skip_string(str2,1); + int errcode = NERR_notsupported; + int snum; + + /* check it's a supported varient */ + if (!(strcsequal(str1,"z") && strcsequal(str2,""))) + return(False); + + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + *rdata_len = 0; + + snum = print_queue_snum(QueueName); + + if (snum == -1) { + errcode = NERR_JobNotFound; + goto out; + } + + switch (function) { + case 74: /* Pause queue */ + if (print_queue_pause(snum)) errcode = NERR_Success; + break; + case 75: /* Resume queue */ + if (print_queue_resume(snum)) errcode = NERR_Success; + break; + case 103: /* Purge */ + if (print_queue_purge(snum)) errcode = NERR_Success; + break; + } + + out: + SSVAL(*rparam,0,errcode); + SSVAL(*rparam,2,0); /* converter word */ + + return(True); +} + + +/**************************************************************************** + set the property of a print job (undocumented?) + ? function = 0xb -> set name of print job + ? function = 0x6 -> move print job up/down + Form: + or +****************************************************************************/ +static int check_printjob_info(struct pack_desc* desc, + int uLevel, char* id) +{ + desc->subformat = NULL; + switch( uLevel ) { + case 0: desc->format = "W"; break; + case 1: desc->format = "WB21BB16B10zWWzDDz"; break; + case 2: desc->format = "WWzWWDDzz"; break; + case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; + default: return False; + } + if (strcmp(desc->format,id) != 0) return False; + return True; +} + +static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + struct pack_desc desc; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int jobid; + int uLevel = SVAL(p,2); + int function = SVAL(p,4); + int place, errcode; + + jobid = SVAL(p,0); + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + /* check it's a supported varient */ + if ((strcmp(str1,"WWsTP")) || + (!check_printjob_info(&desc,uLevel,str2))) + return(False); + + if (!print_job_exists(jobid)) { + errcode=NERR_JobNotFound; + goto out; + } + + errcode = NERR_notsupported; + + switch (function) { + case 0x6: + /* change job place in the queue, + data gives the new place */ + place = SVAL(data,0); + if (print_job_set_place(jobid, place)) { + errcode=NERR_Success; + } + break; + + case 0xb: + /* change print job name, data gives the name */ + if (print_job_set_name(jobid, data)) { + errcode=NERR_Success; + } + break; + + default: + return False; + } + + out: + SSVALS(*rparam,0,errcode); + SSVAL(*rparam,2,0); /* converter word */ + + return(True); +} + + +/**************************************************************************** + get info about the server + ****************************************************************************/ +static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + char *p2; + int struct_len; + + DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); + + /* check it's a supported varient */ + if (!prefix_ok(str1,"WrLh")) return False; + switch( uLevel ) { + case 0: + if (strcmp(str2,"B16") != 0) return False; + struct_len = 16; + break; + case 1: + if (strcmp(str2,"B16BBDz") != 0) return False; + struct_len = 26; + break; + case 2: + if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz") + != 0) return False; + struct_len = 134; + break; + case 3: + if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") + != 0) return False; + struct_len = 144; + break; + case 20: + if (strcmp(str2,"DN") != 0) return False; + struct_len = 6; + break; + case 50: + if (strcmp(str2,"B16BBDzWWzzz") != 0) return False; + struct_len = 42; + break; + default: return False; + } + + *rdata_len = mdrcnt; + *rdata = REALLOC(*rdata,*rdata_len); + + p = *rdata; + p2 = p + struct_len; + if (uLevel != 20) { + StrnCpy(p,local_machine,16); + strupper(p); + } + p += 16; + if (uLevel > 0) + { + struct srv_info_struct *servers=NULL; + int i,count; + pstring comment; + uint32 servertype= lp_default_server_announce(); + + pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); + + if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) { + for (i=0;i 1) + { + return False; /* not yet implemented */ + } + + *rdata_len = PTR_DIFF(p2,*rdata); + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + + return(True); +} + + +/**************************************************************************** + get info about the server + ****************************************************************************/ +static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char *p2; + extern pstring sesssetup_user; + int level = SVAL(p,0); + + DEBUG(4,("NetWkstaGetInfo level %d\n",level)); + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + + /* check it's a supported varient */ + if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) + return(False); + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + p2 = p + 22; + + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ + pstrcpy(p2,local_machine); + strupper(p2); + p2 = skip_string(p2,1); + p += 4; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + pstrcpy(p2,sesssetup_user); + p2 = skip_string(p2,1); + p += 4; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ + pstrcpy(p2,global_myworkgroup); + strupper(p2); + p2 = skip_string(p2,1); + p += 4; + + SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ + SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */ + p += 2; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */ + p2 = skip_string(p2,1); + p += 4; + + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ + pstrcpy(p2,""); + p2 = skip_string(p2,1); + p += 4; + + *rdata_len = PTR_DIFF(p2,*rdata); + + SSVAL(*rparam,4,*rdata_len); + + return(True); +} + +/**************************************************************************** + get info about a user + + struct user_info_11 { + char usri11_name[21]; 0-20 + char usri11_pad; 21 + char *usri11_comment; 22-25 + char *usri11_usr_comment; 26-29 + unsigned short usri11_priv; 30-31 + unsigned long usri11_auth_flags; 32-35 + long usri11_password_age; 36-39 + char *usri11_homedir; 40-43 + char *usri11_parms; 44-47 + long usri11_last_logon; 48-51 + long usri11_last_logoff; 52-55 + unsigned short usri11_bad_pw_count; 56-57 + unsigned short usri11_num_logons; 58-59 + char *usri11_logon_server; 60-63 + unsigned short usri11_country_code; 64-65 + char *usri11_workstations; 66-69 + unsigned long usri11_max_storage; 70-73 + unsigned short usri11_units_per_week; 74-75 + unsigned char *usri11_logon_hours; 76-79 + unsigned short usri11_code_page; 80-81 + }; + +where: + + usri11_name specifies the user name for which information is retireved + + usri11_pad aligns the next data structure element to a word boundary + + usri11_comment is a null terminated ASCII comment + + usri11_user_comment is a null terminated ASCII comment about the user + + usri11_priv specifies the level of the privilege assigned to the user. + The possible values are: + +Name Value Description +USER_PRIV_GUEST 0 Guest privilege +USER_PRIV_USER 1 User privilege +USER_PRV_ADMIN 2 Administrator privilege + + usri11_auth_flags specifies the account operator privileges. The + possible values are: + +Name Value Description +AF_OP_PRINT 0 Print operator + + +Leach, Naik [Page 28] + + +INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 + + +AF_OP_COMM 1 Communications operator +AF_OP_SERVER 2 Server operator +AF_OP_ACCOUNTS 3 Accounts operator + + + usri11_password_age specifies how many seconds have elapsed since the + password was last changed. + + usri11_home_dir points to a null terminated ASCII string that contains + the path name of the user's home directory. + + usri11_parms points to a null terminated ASCII string that is set + aside for use by applications. + + usri11_last_logon specifies the time when the user last logged on. + This value is stored as the number of seconds elapsed since + 00:00:00, January 1, 1970. + + usri11_last_logoff specifies the time when the user last logged off. + This value is stored as the number of seconds elapsed since + 00:00:00, January 1, 1970. A value of 0 means the last logoff + time is unknown. + + usri11_bad_pw_count specifies the number of incorrect passwords + entered since the last successful logon. + + usri11_log1_num_logons specifies the number of times this user has + logged on. A value of -1 means the number of logons is unknown. + + usri11_logon_server points to a null terminated ASCII string that + contains the name of the server to which logon requests are sent. + A null string indicates logon requests should be sent to the + domain controller. + + usri11_country_code specifies the country code for the user's language + of choice. + + usri11_workstations points to a null terminated ASCII string that + contains the names of workstations the user may log on from. + There may be up to 8 workstations, with the names separated by + commas. A null strings indicates there are no restrictions. + + usri11_max_storage specifies the maximum amount of disk space the user + can occupy. A value of 0xffffffff indicates there are no + restrictions. + + usri11_units_per_week specifies the equal number of time units into + which a week is divided. This value must be equal to 168. + + usri11_logon_hours points to a 21 byte (168 bits) string that + specifies the time during which the user can log on. Each bit + represents one unique hour in a week. The first bit (bit 0, word + 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is + + + +Leach, Naik [Page 29] + + +INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 + + + Sunday, 1:00 to 1:59 and so on. A null pointer indicates there + are no restrictions. + + usri11_code_page specifies the code page for the user's language of + choice + +All of the pointers in this data structure need to be treated +specially. The pointer is a 32 bit pointer. The higher 16 bits need +to be ignored. The converter word returned in the parameters section +needs to be subtracted from the lower 16 bits to calculate an offset +into the return buffer where this ASCII string resides. + +There is no auxiliary data in the response. + + ****************************************************************************/ + +#define usri11_name 0 +#define usri11_pad 21 +#define usri11_comment 22 +#define usri11_usr_comment 26 +#define usri11_full_name 30 +#define usri11_priv 34 +#define usri11_auth_flags 36 +#define usri11_password_age 40 +#define usri11_homedir 44 +#define usri11_parms 48 +#define usri11_last_logon 52 +#define usri11_last_logoff 56 +#define usri11_bad_pw_count 60 +#define usri11_num_logons 62 +#define usri11_logon_server 64 +#define usri11_country_code 68 +#define usri11_workstations 70 +#define usri11_max_storage 74 +#define usri11_units_per_week 78 +#define usri11_logon_hours 80 +#define usri11_code_page 84 +#define usri11_end 86 + +#define USER_PRIV_GUEST 0 +#define USER_PRIV_USER 1 +#define USER_PRIV_ADMIN 2 + +#define AF_OP_PRINT 0 +#define AF_OP_COMM 1 +#define AF_OP_SERVER 2 +#define AF_OP_ACCOUNTS 3 + + +static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *UserName = skip_string(str2,1); + char *p = skip_string(UserName,1); + int uLevel = SVAL(p,0); + char *p2; + + /* get NIS home of a previously validated user - simeon */ + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ + user_struct *vuser = get_valid_user_struct(vuid); + if(vuser != NULL) + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name)); + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + + DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); + + /* check it's a supported variant */ + if (strcmp(str1,"zWrLh") != 0) return False; + switch( uLevel ) + { + case 0: p2 = "B21"; break; + case 1: p2 = "B21BB16DWzzWz"; break; + case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; + case 10: p2 = "B21Bzzz"; break; + case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break; + default: return False; + } + + if (strcmp(p2,str2) != 0) return False; + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + p2 = p + usri11_end; + + memset(p,0,21); + fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ + + if (uLevel > 0) + { + SCVAL(p,usri11_pad,0); /* padding - 1 byte */ + *p2 = 0; + } + if (uLevel >= 10) + { + SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ + pstrcpy(p2,"Comment"); + p2 = skip_string(p2,1); + + SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ + pstrcpy(p2,"UserComment"); + p2 = skip_string(p2,1); + + /* EEK! the cifsrap.txt doesn't have this in!!!! */ + SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ + pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); + p2 = skip_string(p2,1); + } + + if (uLevel == 11) /* modelled after NTAS 3.51 reply */ + { + SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ + SIVALS(p,usri11_password_age,-1); /* password age */ + SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ + pstrcpy(p2, lp_logon_home()); + p2 = skip_string(p2,1); + SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ + pstrcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,usri11_last_logon,0); /* last logon */ + SIVAL(p,usri11_last_logoff,0); /* last logoff */ + SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ + SSVALS(p,usri11_num_logons,-1); /* num logons */ + SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ + pstrcpy(p2,"\\\\*"); + p2 = skip_string(p2,1); + SSVAL(p,usri11_country_code,0); /* country code */ + + SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ + pstrcpy(p2,""); + p2 = skip_string(p2,1); + + SIVALS(p,usri11_max_storage,-1); /* max storage */ + SSVAL(p,usri11_units_per_week,168); /* units per week */ + SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */ + + /* a simple way to get logon hours at all times. */ + memset(p2,0xff,21); + SCVAL(p2,21,0); /* fix zero termination */ + p2 = skip_string(p2,1); + + SSVAL(p,usri11_code_page,0); /* code page */ + } + if (uLevel == 1 || uLevel == 2) + { + memset(p+22,' ',16); /* password */ + SIVALS(p,38,-1); /* password age */ + SSVAL(p,42, + conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ + pstrcpy(p2,lp_logon_home()); + p2 = skip_string(p2,1); + SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ + *p2++ = 0; + SSVAL(p,52,0); /* flags */ + SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ + pstrcpy(p2,lp_logon_script()); + standard_sub_conn( conn, p2 ); + p2 = skip_string(p2,1); + if (uLevel == 2) + { + SIVAL(p,60,0); /* auth_flags */ + SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ + pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); + p2 = skip_string(p2,1); + SIVAL(p,68,0); /* urs_comment */ + SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ + pstrcpy(p2,""); + p2 = skip_string(p2,1); + SIVAL(p,76,0); /* workstations */ + SIVAL(p,80,0); /* last_logon */ + SIVAL(p,84,0); /* last_logoff */ + SIVALS(p,88,-1); /* acct_expires */ + SIVALS(p,92,-1); /* max_storage */ + SSVAL(p,96,168); /* units_per_week */ + SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */ + memset(p2,-1,21); + p2 += 21; + SSVALS(p,102,-1); /* bad_pw_count */ + SSVALS(p,104,-1); /* num_logons */ + SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ + pstrcpy(p2,"\\\\%L"); + standard_sub_conn(conn, p2); + p2 = skip_string(p2,1); + SSVAL(p,110,49); /* country_code */ + SSVAL(p,112,860); /* code page */ + } + } + + *rdata_len = PTR_DIFF(p2,*rdata); + + SSVAL(*rparam,4,*rdata_len); /* is this right?? */ + + return(True); +} + +/******************************************************************* + get groups that a user is a member of + ******************************************************************/ +static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *UserName = skip_string(str2,1); + char *p = skip_string(UserName,1); + int uLevel = SVAL(p,0); + char *p2; + int count=0; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLeh") != 0) return False; + switch( uLevel ) { + case 0: p2 = "B21"; break; + default: return False; + } + if (strcmp(p2,str2) != 0) return False; + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + + /* XXXX we need a real SAM database some day */ + pstrcpy(p,"Users"); p += 21; count++; + pstrcpy(p,"Domain Users"); p += 21; count++; + pstrcpy(p,"Guests"); p += 21; count++; + pstrcpy(p,"Domain Guests"); p += 21; count++; + + *rdata_len = PTR_DIFF(p,*rdata); + + SSVAL(*rparam,4,count); /* is this right?? */ + SSVAL(*rparam,6,count); /* is this right?? */ + + return(True); +} + + +static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + struct pack_desc desc; + char* name; + + uLevel = SVAL(p,0); + name = p + 2; + + memset((char *)&desc,'\0',sizeof(desc)); + + DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); + + /* check it's a supported varient */ + if (strcmp(str1,"OOWb54WrLh") != 0) return False; + if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False; + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.subformat = NULL; + desc.format = str2; + + if (init_package(&desc,1,0)) + { + PACKI(&desc,"W",0); /* code */ + PACKS(&desc,"B21",name); /* eff. name */ + PACKS(&desc,"B",""); /* pad */ + PACKI(&desc,"W", + conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + PACKI(&desc,"D",0); /* auth flags XXX */ + PACKI(&desc,"W",0); /* num logons */ + PACKI(&desc,"W",0); /* bad pw count */ + PACKI(&desc,"D",0); /* last logon */ + PACKI(&desc,"D",-1); /* last logoff */ + PACKI(&desc,"D",-1); /* logoff time */ + PACKI(&desc,"D",-1); /* kickoff time */ + PACKI(&desc,"D",0); /* password age */ + PACKI(&desc,"D",0); /* password can change */ + PACKI(&desc,"D",-1); /* password must change */ + { + fstring mypath; + fstrcpy(mypath,"\\\\"); + fstrcat(mypath,local_machine); + strupper(mypath); + PACKS(&desc,"z",mypath); /* computer */ + } + PACKS(&desc,"z",global_myworkgroup);/* domain */ + +/* JHT - By calling lp_logon_script() and standard_sub() we have */ +/* made sure all macros are fully substituted and available */ + { + pstring logon_script; + pstrcpy(logon_script,lp_logon_script()); + standard_sub_conn( conn, logon_script ); + PACKS(&desc,"z", logon_script); /* script path */ + } +/* End of JHT mods */ + + PACKI(&desc,"D",0x00000000); /* reserved */ + } + + *rdata_len = desc.usedlen; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); + return(True); +} + + +/**************************************************************************** + api_WAccessGetUserPerms + ****************************************************************************/ +static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *user = skip_string(str2,1); + char *resource = skip_string(user,1); + + DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); + + /* check it's a supported varient */ + if (strcmp(str1,"zzh") != 0) return False; + if (strcmp(str2,"") != 0) return False; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,0); /* errorcode */ + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,0x7f); /* permission flags */ + + return(True); +} + +/**************************************************************************** + api_WPrintJobEnumerate + ****************************************************************************/ +static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int count; + int i; + int snum; + int job; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + + uLevel = SVAL(p,2); + + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); + + DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0))); + + /* check it's a supported varient */ + if (strcmp(str1,"WWrLh") != 0) return False; + if (!check_printjob_info(&desc,uLevel,str2)) return False; + + job = SVAL(p,0); + + if (snum < 0 || !VALID_SNUM(snum)) return(False); + + count = print_queue_status(snum,&queue,&status); + for (i = 0; i < count; i++) { + if (queue[i].job == job) break; + } + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,1,0)) { + if (i < count) { + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); + *rdata_len = desc.usedlen; + } + else { + desc.errcode = NERR_JobNotFound; + *rdata_len = 0; + } + } + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + if (queue) free(queue); + + DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char* name = p; + int uLevel; + int count; + int i, succnt=0; + int snum; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLeh") != 0) return False; + if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */ + if (!check_printjob_info(&desc,uLevel,str2)) return False; + + snum = lp_servicenumber(name); + if (snum < 0 && pcap_printername_ok(name,NULL)) { + int pnum = lp_servicenumber(PRINTERS_NAME); + if (pnum >= 0) { + lp_add_printer(name,pnum); + snum = lp_servicenumber(name); + } + } + + if (snum < 0 || !VALID_SNUM(snum)) return(False); + + count = print_queue_status(snum,&queue,&status); + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,count,0)) { + succnt = 0; + for (i = 0; i < count; i++) { + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); + if (desc.errcode == NERR_Success) succnt = i+1; + } + } + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,count); + + if (queue) free(queue); + + DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); + return(True); +} + +static int check_printdest_info(struct pack_desc* desc, + int uLevel, char* id) +{ + desc->subformat = NULL; + switch( uLevel ) { + case 0: desc->format = "B9"; break; + case 1: desc->format = "B9B21WWzW"; break; + case 2: desc->format = "z"; break; + case 3: desc->format = "zzzWWzzzWW"; break; + default: return False; + } + if (strcmp(desc->format,id) != 0) return False; + return True; +} + +static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, + struct pack_desc* desc) +{ + char buf[100]; + strncpy(buf,SERVICE(snum),sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; + strupper(buf); + if (uLevel <= 1) { + PACKS(desc,"B9",buf); /* szName */ + if (uLevel == 1) { + PACKS(desc,"B21",""); /* szUserName */ + PACKI(desc,"W",0); /* uJobId */ + PACKI(desc,"W",0); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"W",0); /* time */ + } + } + if (uLevel == 2 || uLevel == 3) { + PACKS(desc,"z",buf); /* pszPrinterName */ + if (uLevel == 3) { + PACKS(desc,"z",""); /* pszUserName */ + PACKS(desc,"z",""); /* pszLogAddr */ + PACKI(desc,"W",0); /* uJobId */ + PACKI(desc,"W",0); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKS(desc,"z",""); /* pszComment */ + PACKS(desc,"z","NULL"); /* pszDrivers */ + PACKI(desc,"W",0); /* time */ + PACKI(desc,"W",0); /* pad1 */ + } + } +} + +static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char* PrinterName = p; + int uLevel; + struct pack_desc desc; + int snum; + + memset((char *)&desc,'\0',sizeof(desc)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLh") != 0) return False; + if (!check_printdest_info(&desc,uLevel,str2)) return False; + + snum = lp_servicenumber(PrinterName); + if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) { + int pnum = lp_servicenumber(PRINTERS_NAME); + if (pnum >= 0) { + lp_add_printer(PrinterName,pnum); + snum = lp_servicenumber(PrinterName); + } + } + + if (snum < 0) { + *rdata_len = 0; + desc.errcode = NERR_DestNotFound; + desc.neededlen = 0; + } + else { + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,0)) { + fill_printdest_info(conn,snum,uLevel,&desc); + } + *rdata_len = desc.usedlen; + } + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int queuecnt; + int i, n, succnt=0; + struct pack_desc desc; + int services = lp_numservices(); + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (!check_printdest_info(&desc,uLevel,str2)) return False; + + queuecnt = 0; + for (i = 0; i < services; i++) + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) + queuecnt++; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,queuecnt,0)) { + succnt = 0; + n = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + fill_printdest_info(conn,i,uLevel,&desc); + n++; + if (desc.errcode == NERR_Success) succnt = n; + } + } + } + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,queuecnt); + + DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int succnt; + struct pack_desc desc; + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (uLevel != 0 || strcmp(str2,"B41") != 0) return False; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B41","NULL"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); + + DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int succnt; + struct pack_desc desc; + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B13","lpd"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); + + DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); + return(True); +} + +static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int succnt; + struct pack_desc desc; + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) return False; + if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + memset((char *)&desc,'\0',sizeof(desc)); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B13","lp0"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); + + DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); + return(True); +} + +/**************************************************************************** + The buffer was too small + ****************************************************************************/ + +static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + *rparam_len = MIN(*rparam_len,mprcnt); + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_BufTooSmall); + + DEBUG(3,("Supplied buffer too small in API command\n")); + + return(True); +} + + +/**************************************************************************** + The request is not supported + ****************************************************************************/ + +static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + + *rdata_len = 0; + + SSVAL(*rparam,0,NERR_notsupported); + SSVAL(*rparam,2,0); /* converter word */ + + DEBUG(3,("Unsupported API command\n")); + + return(True); +} + + + + +struct +{ + char *name; + int id; + BOOL (*fn)(connection_struct *,uint16,char *,char *, + int,int,char **,char **,int *,int *); + int flags; +} api_commands[] = { + {"RNetShareEnum", 0, api_RNetShareEnum,0}, + {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, + {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, + {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0}, + {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, + {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, + {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, + {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, + {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, + {"WPrintQueuePause", 74, api_WPrintQueuePurge,0}, + {"WPrintQueueResume", 75, api_WPrintQueuePurge,0}, + {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, + {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, + {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, + {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0}, + {"RDosPrintJobResume",83, api_RDosPrintJobDel,0}, + {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, + {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, + {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, + {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0}, + {"NetServerEnum", 104, api_RNetServerEnum,0}, + {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, + {"SetUserPassword", 115, api_SetUserPassword,0}, + {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0}, + {"PrintJobInfo", 147, api_PrintJobInfo,0}, + {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0}, + {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0}, + {"WPrintPortEnum", 207, api_WPrintPortEnum,0}, + {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0}, + {NULL, -1, api_Unsupported,0}}; + + +/**************************************************************************** + Handle remote api calls + ****************************************************************************/ + +int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, + int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +{ + int api_command; + char *rdata = NULL; + char *rparam = NULL; + int rdata_len = 0; + int rparam_len = 0; + BOOL reply=False; + int i; + + if (!params) { + DEBUG(0,("ERROR: NULL params in api_reply()\n")); + return 0; + } + + api_command = SVAL(params,0); + + DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", + api_command, + params+2, + skip_string(params+2,1), + tdscnt,tpscnt,mdrcnt,mprcnt)); + + for (i=0;api_commands[i].name;i++) { + if (api_commands[i].id == api_command && api_commands[i].fn) { + DEBUG(3,("Doing %s\n",api_commands[i].name)); + break; + } + } + + rdata = (char *)malloc(1024); + if (rdata) + memset(rdata,'\0',1024); + + rparam = (char *)malloc(1024); + if (rparam) + memset(rparam,'\0',1024); + + if(!rdata || !rparam) { + DEBUG(0,("api_reply: malloc fail !\n")); + return -1; + } + + reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + + if (rdata_len > mdrcnt || + rparam_len > mprcnt) { + reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } + + /* if we get False back then it's actually unsupported */ + if (!reply) + api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); + + if (rdata ) + free(rdata); + if (rparam) + free(rparam); + + return -1; +} + -- cgit From f074d6ef57de28a2855fb2f8d3357ec46cbe8be0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Apr 2000 08:23:13 +0000 Subject: split fsusage() into a separate module (to fix linking problems with spoolssd in tng) (This used to be commit e2eacdd74c369fbbcd118148149321e36f3d0010) --- source3/smbd/dfree.c | 129 +-------------------------------------------------- 1 file changed, 2 insertions(+), 127 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index eff718b148..ee5722acd5 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -61,131 +61,6 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree, } -/* Return the number of TOSIZE-byte blocks used by - BLOCKS FROMSIZE-byte blocks, rounding away from zero. -*/ -static SMB_BIG_UINT adjust_blocks(SMB_BIG_UINT blocks, SMB_BIG_UINT fromsize, SMB_BIG_UINT tosize) -{ - if (fromsize == tosize) /* e.g., from 512 to 512 */ - return blocks; - else if (fromsize > tosize) /* e.g., from 2048 to 512 */ - return blocks * (fromsize / tosize); - else /* e.g., from 256 to 512 */ - return (blocks + 1) / (tosize / fromsize); -} - -/* this does all of the system specific guff to get the free disk space. - It is derived from code in the GNU fileutils package, but has been - considerably mangled for use here - - results are returned in *dfree and *dsize, in 512 byte units -*/ -static int fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -{ -#ifdef STAT_STATFS3_OSF1 -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) - struct statfs fsd; - - if (statfs (path, &fsd, sizeof (struct statfs)) != 0) - return -1; -#endif /* STAT_STATFS3_OSF1 */ - -#ifdef STAT_STATFS2_FS_DATA /* Ultrix */ -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)1024, (SMB_BIG_UINT)512) - struct fs_data fsd; - - if (statfs (path, &fsd) != 1) - return -1; - - (*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot); - (*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen); -#endif /* STAT_STATFS2_FS_DATA */ - -#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) - struct statfs fsd; - - if (statfs (path, &fsd) < 0) - return -1; - -#ifdef STATFS_TRUNCATES_BLOCK_COUNTS - /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the - struct statfs are truncated to 2GB. These conditions detect that - truncation, presumably without botching the 4.1.1 case, in which - the values are not truncated. The correct counts are stored in - undocumented spare fields. */ - if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) { - fsd.f_blocks = fsd.f_spare[0]; - fsd.f_bfree = fsd.f_spare[1]; - fsd.f_bavail = fsd.f_spare[2]; - } -#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ -#endif /* STAT_STATFS2_BSIZE */ - - -#ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) - - struct statfs fsd; - - if (statfs (path, &fsd) < 0) - return -1; -#endif /* STAT_STATFS2_FSIZE */ - -#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ -# if _AIX || defined(_CRAY) -# define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) -# ifdef _CRAY -# define f_bavail f_bfree -# endif -# else -# define CONVERT_BLOCKS(B) ((SMB_BIG_UINT)B) -# ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ -# ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ -# define f_bavail f_bfree -# endif -# endif -# endif - - struct statfs fsd; - - if (statfs (path, &fsd, sizeof fsd, 0) < 0) - return -1; - /* Empirically, the block counts on most SVR3 and SVR3-derived - systems seem to always be in terms of 512-byte blocks, - no matter what value f_bsize has. */ - -#endif /* STAT_STATFS4 */ - -#if defined(STAT_STATVFS) || defined(STAT_STATVFS64) /* SVR4 */ -# define CONVERT_BLOCKS(B) \ - adjust_blocks ((SMB_BIG_UINT)(B), fsd.f_frsize ? (SMB_BIG_UINT)fsd.f_frsize : (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) - -#ifdef STAT_STATVFS64 - struct statvfs64 fsd; - if (statvfs64(path, &fsd) < 0) return -1; -#else - struct statvfs fsd; - if (statvfs(path, &fsd) < 0) return -1; -#endif - - /* f_frsize isn't guaranteed to be supported. */ - -#endif /* STAT_STATVFS */ - -#ifndef CONVERT_BLOCKS - /* we don't have any dfree code! */ - return -1; -#else -#if !defined(STAT_STATFS2_FS_DATA) - /* !Ultrix */ - (*dsize) = CONVERT_BLOCKS (fsd.f_blocks); - (*dfree) = CONVERT_BLOCKS (fsd.f_bavail); -#endif /* not STAT_STATFS2_FS_DATA */ -#endif - - return 0; -} /**************************************************************************** return number of 1K blocks available on a path and total number @@ -246,10 +121,10 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, } else { DEBUG (0, ("disk_free: sys_popen() failed for command %s. Error was : %s\n", syscmd, strerror(errno) )); - fsusage(path, dfree, dsize); + sys_fsusage(path, dfree, dsize); } } else - fsusage(path, dfree, dsize); + sys_fsusage(path, dfree, dsize); if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { (*bsize) = bsize_q; -- cgit From 6259f51dd9918eccc9697f3763d918f7c9b82b50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Apr 2000 00:33:16 +0000 Subject: This is a *big* checkin that may break some things, but implements the new open mechanism Andrew & I discussed. config.sub: configure: Included the QNX patch. include/vfs.h: smbd/vfs-wrap.c: smbd/vfs.c: Added ftruncate vfs call (needed). Note that we will also need locking calls in the vfs (to be added). lib/util_unistr.c: nmbd/nmbd_processlogon.c: Fix for NT domain logons causing nmbd to core dump. Also fix for sidsize DOS bug. locking/locking.c: Check value of ret before using it for memdup. printing/printing.c: Convert print_fsp_open to return an allocated fsp. rpc_server/srv_lsa.c: Fix for NT domain logons. I have removed all use of lp_share_modes() from the code (although I left the parameter in the table for backwards compatibility). It no longer makes sense for this to exist. smbd/close.c: Removed lp_share_modes(). smbd/fileio.c: Fixed parameters to unlock_share_entry call in panic code. smbd/files.c: Correctly set the unix_ERR_code to ERRnofids on fsp allocation fail. smbd/nttrans.c: smbd/reply.c: smbd/trans2.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. smbd/open.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. In addition I have fixed a long standing race condition in the deny mode processing w.r.t. two smbd's creating a file. Andrew, please note that your original idea of using open with O_EXCL in this case would not work (I went over the races very carefully) and so we must re-check deny modes *after* the open() call returns. This is because there is a race between the open with O_EXCL and the lock of the share mode entry. Imagine the case where the first smbd does the open with O_EXCL and a deny mode of DENY_ALL, but is pre-empted before it locks the share modes and creates the deny mode entry for DENY_ALL. A second smbd could then come in with O_RDONLY and a deny mode of DENY_NONE and the two opens would be allowed. The *only* way to fix this race is to lock the share modes after the open and then do the deny mode checks *after* this lock in the case where the file did not originally exist. This code will need extensive testing but seems to initially work. Jeremy. (This used to be commit ab0ecc39d688f16b9692fe90b991f0b89287070a) --- source3/smbd/close.c | 13 +- source3/smbd/fileio.c | 2 + source3/smbd/files.c | 8 +- source3/smbd/nttrans.c | 56 ++-- source3/smbd/open.c | 751 ++++++++++++++++++++++++++---------------------- source3/smbd/reply.c | 64 +---- source3/smbd/trans2.c | 165 +++++------ source3/smbd/vfs-wrap.c | 8 + source3/smbd/vfs.c | 7 +- 9 files changed, 547 insertions(+), 527 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c4d323b1ba..ec28ff3540 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -65,7 +65,8 @@ static void check_magic(files_struct *fsp,connection_struct *conn) /**************************************************************************** Common code to close a file or a directory. ****************************************************************************/ -static void close_filestruct(files_struct *fsp) + +void close_filestruct(files_struct *fsp) { connection_struct *conn = fsp->conn; @@ -106,19 +107,15 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) return 0; } - if (lp_share_modes(SNUM(conn))) { - lock_share_entry_fsp(fsp); - del_share_mode(fsp); - } + lock_share_entry_fsp(fsp); + del_share_mode(fsp); + unlock_share_entry_fsp(fsp); if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) release_file_oplock(fsp); locking_close_file(fsp); - if (lp_share_modes(SNUM(conn))) - unlock_share_entry_fsp(fsp); - err = fd_close(conn, fsp); /* check for magic scripts */ diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 5d8c3a9710..8f8f17563e 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -234,6 +234,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) /* Paranoia .... */ if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { DEBUG(0,("write_file: PANIC. share mode entry %d is an exlusive oplock !\n", i )); + unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); abort(); } @@ -249,6 +250,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) /* Paranoia check... */ if(new_fsp == NULL) { DEBUG(0,("write_file: PANIC. share mode entry %d is not a local file !\n", i )); + unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); abort(); } oplock_break_level2(new_fsp, True, token); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e971de095b..6c0465097b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -77,11 +77,17 @@ files_struct *file_new(void ) } DEBUG(0,("ERROR! Out of file structures\n")); + unix_ERR_class = ERRSRV; + unix_ERR_code = ERRnofids; return NULL; } fsp = (files_struct *)malloc(sizeof(*fsp)); - if (!fsp) return NULL; + if (!fsp) { + unix_ERR_class = ERRSRV; + unix_ERR_code = ERRnofids; + return NULL; + } ZERO_STRUCTP(fsp); fsp->fd = -1; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bd77f17802..c82a8074d9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -747,12 +747,6 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,NULL); - fsp = file_new(); - if (!fsp) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); - } - unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* @@ -762,13 +756,11 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, - unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { @@ -789,10 +781,10 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - open_file_shared(fsp,conn,fname,smb_open_mode, + fsp = open_file_shared(conn,fname,smb_open_mode, smb_ofun,unixmode, oplock_request,&rmode,&smb_action); - if (!fsp->open) { + if (!fsp) { /* We cheat here. There are two cases we * care about. One is a directory rename, * where the NT client will attempt to @@ -819,17 +811,15 @@ int reply_ntcreate_and_X(connection_struct *conn, */ if (create_options & FILE_NON_DIRECTORY_FILE) { - file_free(fsp); restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); } oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -845,10 +835,9 @@ int reply_ntcreate_and_X(connection_struct *conn, oplock_request = 0; - open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -860,8 +849,6 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_ERR_code = ERRbadpath; } - file_free(fsp); - restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1109,12 +1096,6 @@ static int call_nt_transact_create(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,NULL); - fsp = file_new(); - if (!fsp) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); - } - unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* @@ -1131,10 +1112,9 @@ static int call_nt_transact_create(connection_struct *conn, * CreateDirectory() call. */ - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1152,10 +1132,10 @@ static int call_nt_transact_create(connection_struct *conn, * Ordinary file case. */ - open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); - if (!fsp->open) { + if (!fsp) { if(errno == EISDIR) { @@ -1164,17 +1144,15 @@ static int call_nt_transact_create(connection_struct *conn, */ if (create_options & FILE_NON_DIRECTORY_FILE) { - file_free(fsp); restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); } oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1191,10 +1169,9 @@ static int call_nt_transact_create(connection_struct *conn, oplock_request = 0; - open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1204,7 +1181,6 @@ static int call_nt_transact_create(connection_struct *conn, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); restore_case_semantics(file_attributes); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bd8e860a17..d2368aa44d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -82,7 +82,7 @@ static void check_for_pipe(char *fname) Open a file. ****************************************************************************/ -static void open_file(files_struct *fsp,connection_struct *conn, +static BOOL open_file(files_struct *fsp,connection_struct *conn, char *fname1,int flags,mode_t mode) { extern struct current_user current_user; @@ -114,7 +114,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); check_for_pipe(fname); - return; + return False; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that O_CREAT doesn't create the file if we have write access into the @@ -131,7 +131,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); check_for_pipe(fname); - return; + return False; } conn->vfs_ops.fstat(fsp->fd, &sbuf); @@ -145,10 +145,9 @@ static void open_file(files_struct *fsp,connection_struct *conn, if(S_ISDIR(sbuf.st_mode)) { fd_close(conn, fsp); errno = EISDIR; - return; + return False; } - conn->num_files_open++; fsp->mode = sbuf.st_mode; fsp->inode = sbuf.st_ino; fsp->dev = sbuf.st_dev; @@ -184,7 +183,9 @@ static void open_file(files_struct *fsp,connection_struct *conn, DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), - conn->num_files_open)); + conn->num_files_open + 1)); + + return True; } /**************************************************************************** @@ -193,35 +194,27 @@ static void open_file(files_struct *fsp,connection_struct *conn, Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, - BOOL *share_locked) +static int truncate_unless_locked(struct connection_struct *conn, files_struct *fsp) { - if (fsp->can_write){ - SMB_OFF_T mask2 = ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4); - SMB_OFF_T mask = (mask2<<2); - - if (is_locked(fsp,conn,~mask,0,WRITE_LOCK)){ - /* If share modes are in force for this connection we - have the share entry locked. Unlock it before closing. */ - if (*share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry_fsp(fsp); - close_file(fsp,False); - /* Share mode no longer locked. */ - *share_locked = False; - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRlock; - } else { - sys_ftruncate(fsp->fd,0); - } + SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; + + if (!fsp->can_write) + return -1; + + if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK)){ + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRlock; + return -1; + } else { + return conn->vfs_ops.ftruncate(fsp->fd,0); } } - /******************************************************************* return True if the filename is one of the special executable types ********************************************************************/ -static BOOL is_executable(char *fname) +static BOOL is_executable(const char *fname) { if ((fname = strrchr(fname,'.'))) { if (strequal(fname,".com") || @@ -334,364 +327,426 @@ check if we can open a file with a share mode ****************************************************************************/ static int check_share_mode( share_mode_entry *share, int deny_mode, - char *fname, - BOOL fcbopen, int *flags) + const char *fname, BOOL fcbopen, int *flags) { - int old_open_mode = GET_OPEN_MODE(share->share_mode); - int old_deny_mode = GET_DENY_MODE(share->share_mode); + int old_open_mode = GET_OPEN_MODE(share->share_mode); + int old_deny_mode = GET_DENY_MODE(share->share_mode); + + /* + * Don't allow any open once the delete on close flag has been + * set. + */ + + if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) { + DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", + fname )); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRnoaccess; + return False; + } + + { + int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, + (share->pid == getpid()),is_executable(fname)); + + if ((access_allowed == AFAIL) || + (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || + (access_allowed == AREAD && *flags != O_RDONLY) || + (access_allowed == AWRITE && *flags != O_WRONLY)) { + + DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", + deny_mode,old_deny_mode,old_open_mode, + (int)share->pid,fname, fcbopen, *flags, access_allowed)); + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + return False; + } + + if (access_allowed == AREAD) + *flags = O_RDONLY; + + if (access_allowed == AWRITE) + *flags = O_WRONLY; + + } + + return True; +} + +/**************************************************************************** + Deal with open deny mode and oplock break processing. + Invarient: Share mode must be locked on entry and exit. + Returns -1 on error, or number of share modes on success (may be zero). +****************************************************************************/ + +static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev, + SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request, + BOOL *p_all_current_opens_are_level_II) +{ + int i; + int num_share_modes; + int oplock_contention_count = 0; + share_mode_entry *old_shares = 0; + BOOL fcbopen = False; + int deny_mode = GET_DENY_MODE(share_mode); + BOOL broke_oplock; + + if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) + fcbopen = True; + + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + + if(num_share_modes == 0) + return 0; /* - * Don't allow any open once the delete on close flag has been - * set. + * Check if the share modes will give us access. */ - if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) - { - DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", - fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRnoaccess; - return False; - } + do { - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == getpid()),is_executable(fname)); + broke_oplock = False; + *p_all_current_opens_are_level_II = True; - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags != O_RDONLY) || - (access_allowed == AWRITE && *flags != O_WRONLY)) - { - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", - deny_mode,old_deny_mode,old_open_mode, - (int)share->pid,fname, fcbopen, *flags, access_allowed)); + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + + /* + * By observation of NetBench, oplocks are broken *before* share + * modes are checked. This allows a file to be closed by the client + * if the share mode would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so we must break + * it before continuing. + */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; + if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || + (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { - return False; + BOOL opb_ret; + + DEBUG(5,("open_mode_check: breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + + /* Oplock break - unlock to request it. */ + unlock_share_entry(conn, dev, inode); + + opb_ret = request_oplock_break(share_entry, dev, inode); + + /* Now relock. */ + lock_share_entry(conn, dev, inode); + + if(opb_ret == False) { + free((char *)old_shares); + DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } + + broke_oplock = True; + *p_all_current_opens_are_level_II = False; + break; + + } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + *p_all_current_opens_are_level_II = False; + } + + /* someone else has a share lock on it, check to see + if we can too */ + + if(check_share_mode(share_entry, deny_mode, fname, fcbopen, p_flags) == False) { + free((char *)old_shares); + errno = EACCES; + return -1; + } + + } /* end for */ + + if(broke_oplock) { + free((char *)old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + oplock_contention_count++; } + } while(broke_oplock); - if (access_allowed == AREAD) - *flags = O_RDONLY; + if(old_shares != 0) + free((char *)old_shares); - if (access_allowed == AWRITE) - *flags = O_WRONLY; + /* + * Refuse to grant an oplock in case the contention limit is + * reached when going through the lock list multiple times. + */ + if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) { + *p_oplock_request = 0; + DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n", + oplock_contention_count )); } - return True; + return num_share_modes; } /**************************************************************************** -open a file with a share mode + Open a file with a share mode. ****************************************************************************/ -void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, +files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) { - int flags=0; - int flags2=0; - int deny_mode = GET_DENY_MODE(share_mode); - BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); - SMB_STRUCT_STAT sbuf; - BOOL file_existed = vfs_file_exist(conn, fname, &sbuf); - BOOL share_locked = False; - BOOL fcbopen = False; - int token = 0; - SMB_DEV_T dev = 0; - SMB_INO_T inode = 0; - int num_share_modes = 0; - int oplock_contention_count = 0; - BOOL all_current_opens_are_level_II = False; - fsp->open = False; - fsp->fd = -1; - - if (conn->printer) { - /* printers are handled completely differently. Most of the passed parameters are - ignored */ - *Access = DOS_OPEN_WRONLY; - *action = FILE_WAS_CREATED; - print_fsp_open(fsp, conn, fname); - return; - } + int flags=0; + int flags2=0; + int deny_mode = GET_DENY_MODE(share_mode); + BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); + SMB_STRUCT_STAT sbuf; + BOOL file_existed = vfs_file_exist(conn, fname, &sbuf); + BOOL fcbopen = False; + SMB_DEV_T dev = 0; + SMB_INO_T inode = 0; + int num_share_modes = 0; + BOOL all_current_opens_are_level_II = False; + files_struct *fsp = NULL; + int open_mode=0; + uint16 port = 0; + + if (conn->printer) { + /* printers are handled completely differently. Most of the passed parameters are + ignored */ + *Access = DOS_OPEN_WRONLY; + *action = FILE_WAS_CREATED; + return print_fsp_open(conn, fname); + } - DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", - fname, share_mode, ofun, (int)mode, oplock_request )); + fsp = file_new(); + if(!fsp) + return NULL; - if (!check_name(fname,conn)) { - return; - } + fsp->open = False; + fsp->fd = -1; - /* ignore any oplock requests if oplocks are disabled */ - if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { - oplock_request = 0; - } + DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", + fname, share_mode, ofun, (int)mode, oplock_request )); - /* this is for OS/2 EAs - try and say we don't support them */ - if (strstr(fname,".+,;=[].")) - { - unix_ERR_class = ERRDOS; - /* OS/2 Workplace shell fix may be main code stream in a later release. */ + if (!check_name(fname,conn)) { + file_free(fsp); + return NULL; + } + + /* ignore any oplock requests if oplocks are disabled */ + if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { + oplock_request = 0; + } + + /* this is for OS/2 EAs - try and say we don't support them */ + if (strstr(fname,".+,;=[].")) { + unix_ERR_class = ERRDOS; + /* OS/2 Workplace shell fix may be main code stream in a later release. */ #if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ - unix_ERR_code = ERRcannotopen; + unix_ERR_code = ERRcannotopen; #else /* OS2_WPS_FIX */ - unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; + unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; #endif /* OS2_WPS_FIX */ - DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n")); - return; - } + DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n")); + file_free(fsp); + return NULL; + } - if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed) - { - DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", - fname )); - errno = EEXIST; - return; - } + if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed) { + DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", + fname )); + file_free(fsp); + errno = EEXIST; + return NULL; + } - if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST) - flags2 |= O_CREAT; - - if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE) - flags2 |= O_TRUNC; - - if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) - flags2 |= O_EXCL; - - /* note that we ignore the append flag as - append does not mean the same thing under dos and unix */ - - switch (GET_OPEN_MODE(share_mode)) - { - case DOS_OPEN_WRONLY: - flags = O_WRONLY; - break; - case DOS_OPEN_FCB: - fcbopen = True; - flags = O_RDWR; - break; - case DOS_OPEN_RDWR: - flags = O_RDWR; - break; - default: - flags = O_RDONLY; - break; - } + if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST) + flags2 |= O_CREAT; + + if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE) + flags2 |= O_TRUNC; + + if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) + flags2 |= O_EXCL; + + /* note that we ignore the append flag as + append does not mean the same thing under dos and unix */ + + switch (GET_OPEN_MODE(share_mode)) { + case DOS_OPEN_WRONLY: + flags = O_WRONLY; + break; + case DOS_OPEN_FCB: + fcbopen = True; + flags = O_RDWR; + break; + case DOS_OPEN_RDWR: + flags = O_RDWR; + break; + default: + flags = O_RDONLY; + break; + } #if defined(O_SYNC) - if (GET_FILE_SYNC_OPENMODE(share_mode)) { - flags2 |= O_SYNC; - } + if (GET_FILE_SYNC_OPENMODE(share_mode)) { + flags2 |= O_SYNC; + } #endif /* O_SYNC */ - if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) - { - if (!fcbopen) - { - DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", - fname, !CAN_WRITE(conn) ? "share" : "file" )); - errno = EACCES; - return; - } - flags = O_RDONLY; - } - - if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) - { - DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - errno = EINVAL; - return; - } - - if (lp_share_modes(SNUM(conn))) - { - int i; - share_mode_entry *old_shares = 0; - - if (file_existed) - { - dev = sbuf.st_dev; - inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode); - share_locked = True; - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - } + if (flags != O_RDONLY && file_existed && + (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) { + if (!fcbopen) { + DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", + fname, !CAN_WRITE(conn) ? "share" : "file" )); + file_free(fsp); + errno = EACCES; + return NULL; + } + flags = O_RDONLY; + } - /* - * Check if the share modes will give us access. - */ + if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { + DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); + file_free(fsp); + errno = EINVAL; + return NULL; + } - if(share_locked && (num_share_modes != 0)) - { - BOOL broke_oplock; + if (file_existed) { + dev = sbuf.st_dev; + inode = sbuf.st_ino; - do - { + lock_share_entry(conn, dev, inode); - broke_oplock = False; - all_current_opens_are_level_II = True; + num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, + &flags, &oplock_request, &all_current_opens_are_level_II); + if(num_share_modes == -1) { + unlock_share_entry(conn, dev, inode); + file_free(fsp); + return NULL; + } - for(i = 0; i < num_share_modes; i++) - { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * By observation of NetBench, oplocks are broken *before* share - * modes are checked. This allows a file to be closed by the client - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. - */ - if((oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || - (!oplock_request && (share_entry->op_type != NO_OPLOCK))) - { + /* + * We exit this block with the share entry *locked*..... + */ + } - DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", + flags,flags2,(int)mode)); - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); + fsp->open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); - DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); + if (!fsp->open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { + if((fsp->open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True) + flags = O_RDONLY; + } - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - lock_share_entry(conn, dev, inode); - broke_oplock = True; - all_current_opens_are_level_II = False; - break; - } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - all_current_opens_are_level_II = False; - } + if (!fsp->open) { + if(file_existed) + unlock_share_entry(conn, dev, inode); + file_free(fsp); + return NULL; + } - /* someone else has a share lock on it, check to see - if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) - { - free((char *)old_shares); - unlock_share_entry(conn, dev, inode); - errno = EACCES; - return; - } + /* + * Deal with the race condition where two smbd's detect the file doesn't + * exist and do the create at the same time. One of them will win and + * set a share mode, the other (ie. this one) should check if the + * requested share mode for this create is allowed. + */ - } /* end for */ + if (!file_existed) { - if(broke_oplock) - { - free((char *)old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - oplock_contention_count++; - } - } while(broke_oplock); - } + lock_share_entry_fsp(fsp); - if(old_shares != 0) - free((char *)old_shares); - } + num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, + &flags, &oplock_request, &all_current_opens_are_level_II); - /* - * Refuse to grant an oplock in case the contention limit is - * reached when going through the lock list multiple times. - */ + if(num_share_modes == -1) { + unlock_share_entry_fsp(fsp); + fd_close(conn,fsp); + file_free(fsp); + return NULL; + } - if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) - { - oplock_request = 0; - DEBUG(4,("open_file_shared: oplock contention = %d. Not granting oplock.\n", - oplock_contention_count )); - } + /* + * We exit this block with the share entry *locked*..... + */ + } - DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - flags,flags2,(int)mode)); + /* + * At this point onwards, we can guarentee that the share entry + * is locked, whether we created the file or not, and that the + * deny mode is compatible with all current opens. + */ - open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); - if (!fsp->open && flags==O_RDWR && errno != ENOENT && fcbopen) { - flags = O_RDONLY; - open_file(fsp,conn,fname,flags,mode); - } + /* + * If requested, truncate the file. + */ - if (fsp->open) - { - int open_mode=0; + if ((flags2&O_TRUNC) && (truncate_unless_locked(conn,fsp) == -1)) { + unlock_share_entry_fsp(fsp); + fd_close(conn,fsp); + file_free(fsp); + return NULL; + } - if((share_locked == False) && lp_share_modes(SNUM(conn))) - { - /* We created the file - thus we must now lock the share entry before creating it. */ - lock_share_entry_fsp(fsp); - share_locked = True; - } + switch (flags) { + case O_RDONLY: + open_mode = DOS_OPEN_RDONLY; + break; + case O_RDWR: + open_mode = DOS_OPEN_RDWR; + break; + case O_WRONLY: + open_mode = DOS_OPEN_WRONLY; + break; + } - switch (flags) - { - case O_RDONLY: - open_mode = DOS_OPEN_RDONLY; - break; - case O_RDWR: - open_mode = DOS_OPEN_RDWR; - break; - case O_WRONLY: - open_mode = DOS_OPEN_WRONLY; - break; - } + fsp->share_mode = SET_DENY_MODE(deny_mode) | + SET_OPEN_MODE(open_mode) | + SET_ALLOW_SHARE_DELETE(allow_share_delete); - fsp->share_mode = SET_DENY_MODE(deny_mode) | - SET_OPEN_MODE(open_mode) | - SET_ALLOW_SHARE_DELETE(allow_share_delete); + if (Access) + (*Access) = open_mode; - if (Access) - (*Access) = open_mode; + if (action) { + if (file_existed && !(flags2 & O_TRUNC)) + *action = FILE_WAS_OPENED; + if (!file_existed) + *action = FILE_WAS_CREATED; + if (file_existed && (flags2 & O_TRUNC)) + *action = FILE_WAS_OVERWRITTEN; + } - if (action) - { - if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED; - if (!file_existed) *action = FILE_WAS_CREATED; - if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN; - } - /* We must create the share mode entry before truncate as - truncate can fail due to locking and have to close the - file (which expects the share_mode_entry to be there). - */ - if (lp_share_modes(SNUM(conn))) - { - uint16 port = 0; + /* + * Setup the oplock info in both the shared memory and + * file structs. + */ - /* - * Setup the oplock info in both the shared memory and - * file structs. - */ + if(oplock_request && (num_share_modes == 0) && + !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { + port = global_oplock_port; + } else if (oplock_request && all_current_opens_are_level_II) { + port = global_oplock_port; + oplock_request = LEVEL_II_OPLOCK; + set_file_oplock(fsp, oplock_request); + } else { + port = 0; + oplock_request = 0; + } - if(oplock_request && (num_share_modes == 0) && - !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { - port = global_oplock_port; - } else if (oplock_request && all_current_opens_are_level_II) { - port = global_oplock_port; - oplock_request = LEVEL_II_OPLOCK; - set_file_oplock(fsp, oplock_request); - } else { - port = 0; - oplock_request = 0; - } + set_share_mode(fsp, port, oplock_request); - set_share_mode(fsp, port, oplock_request); - } + unlock_share_entry_fsp(fsp); - if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fsp,conn,token,&share_locked); - } + conn->num_files_open++; - if (share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry_fsp(fsp); + return fsp; } /**************************************************************************** @@ -699,20 +754,26 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou with the 'stat_open' flag set ****************************************************************************/ -int open_file_stat(files_struct *fsp,connection_struct *conn, +files_struct *open_file_stat(connection_struct *conn, char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action) { extern struct current_user current_user; + files_struct *fsp = file_new(); + + if(!fsp) + return NULL; if(conn->vfs_ops.stat(dos_to_unix(fname, False), pst) < 0) { DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); - return -1; + file_free(fsp); + return NULL; } if(S_ISDIR(pst->st_mode)) { DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); - return -1; + file_free(fsp); + return NULL; } *action = FILE_WAS_OPENED; @@ -724,7 +785,6 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, */ fsp->fd = -1; - conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; @@ -755,27 +815,34 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, fsp->wbmpx_ptr = NULL; fsp->wcp = NULL; /* Write cache pointer. */ - return 0; + conn->num_files_open++; + + return fsp; } /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ -int open_directory(files_struct *fsp,connection_struct *conn, +files_struct *open_directory(connection_struct *conn, char *fname, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; SMB_STRUCT_STAT st; BOOL got_stat = False; + files_struct *fsp = file_new(); + + if(!fsp) + return NULL; if(conn->vfs_ops.stat(dos_to_unix(fname, False), &st) == 0) { got_stat = True; } if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { + file_free(fsp); errno = EEXIST; /* Setup so correct error is returned to client. */ - return -1; + return NULL; } if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) { @@ -784,8 +851,9 @@ int open_directory(files_struct *fsp,connection_struct *conn, if(!S_ISDIR(st.st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + file_free(fsp); errno = EACCES; - return -1; + return NULL; } *action = FILE_WAS_OPENED; @@ -797,15 +865,17 @@ int open_directory(files_struct *fsp,connection_struct *conn, if(!CAN_WRITE(conn)) { DEBUG(2,("open_directory: failing create on read-only share\n")); + file_free(fsp); errno = EACCES; - return -1; + return NULL; } if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); - return -1; + file_free(fsp); + return NULL; } *action = FILE_WAS_CREATED; @@ -819,12 +889,14 @@ int open_directory(files_struct *fsp,connection_struct *conn, if(!got_stat) { DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); - return -1; + file_free(fsp); + return NULL; } if(!S_ISDIR(st.st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - return -1; + file_free(fsp); + return NULL; } *action = FILE_WAS_OPENED; @@ -838,7 +910,6 @@ int open_directory(files_struct *fsp,connection_struct *conn, */ fsp->fd = -1; - conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; @@ -867,7 +938,9 @@ int open_directory(files_struct *fsp,connection_struct *conn, string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; - return 0; + conn->num_files_open++; + + return fsp; } /******************************************************************* @@ -886,10 +959,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) SMB_DEV_T dev; SMB_INO_T inode; - if(!lp_share_modes(SNUM(conn))) - return True; - - if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) return(True); + if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) + return(True); dev = sbuf.st_dev; inode = sbuf.st_ino; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e998e1741c..3acfd988d6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1545,23 +1545,18 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(fname,conn,0,&bad_path,NULL); - fsp = file_new(); - if (!fsp) - return(ERROR(ERRSRV,ERRnofids)); - unixmode = unix_mode(conn,aARCH,fname); - open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + fsp = open_file_shared(conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unixmode, oplock_request,&rmode,NULL); - if (!fsp->open) + if (!fsp) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1639,23 +1634,18 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unix_convert(fname,conn,0,&bad_path,NULL); - fsp = file_new(); - if (!fsp) - return(ERROR(ERRSRV,ERRnofids)); - unixmode = unix_mode(conn,smb_attr | aARCH, fname); - open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); - if (!fsp->open) + if (!fsp) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1772,10 +1762,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,createmode,fname); - fsp = file_new(); - if (!fsp) - return(ERROR(ERRSRV,ERRnofids)); - if(com == SMBmknew) { /* We should fail if file exists. */ @@ -1788,17 +1774,16 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file in dos compatibility share mode. */ - open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + fsp = open_file_shared(conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), ofun, unixmode, oplock_request, NULL, NULL); - if (!fsp->open) + if (!fsp) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1844,25 +1829,20 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,createmode,fname); - fsp = file_new(); - if (fsp) - return(ERROR(ERRSRV,ERRnofids)); - pstrcpy(fname2,(char *)smbd_mktemp(fname)); /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + fsp = open_file_shared(conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL); - if (!fsp->open) + if (!fsp) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -3025,15 +3005,10 @@ int reply_printopen(connection_struct *conn, if (!CAN_PRINT(conn)) return(ERROR(ERRDOS,ERRnoaccess)); - fsp = file_new(); - if (!fsp) - return(ERROR(ERRSRV,ERRnofids)); - /* Open for exclusive use, write only. */ - print_fsp_open(fsp,conn,"dos.prn"); + fsp = print_fsp_open(conn,"dos.prn"); - if (!fsp->open) { - file_free(fsp); + if (!fsp) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -3745,32 +3720,21 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!vfs_file_exist(conn,src,&st)) return(False); - fsp1 = file_new(); - if (!fsp1) - return(False); - - open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + fsp1 = open_file_shared(conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); - if (!fsp1->open) { - file_free(fsp1); + if (!fsp1) { return(False); } if (!target_is_directory && count) ofun = 1; - fsp2 = file_new(); - if (!fsp2) { - close_file(fsp1,False); - return(False); - } - open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + fsp2 = open_file_shared(conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), ofun,st.st_mode,0,&Access,&action); - if (!fsp2->open) { + if (!fsp2) { close_file(fsp1,False); - file_free(fsp2); return(False); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2ca06ab746..f0a645d6c7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -221,10 +221,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unix_convert(fname,conn,0,&bad_path,NULL); - fsp = file_new(); - if (!fsp) - return(ERROR(ERRSRV,ERRnofids)); - if (!check_name(fname,conn)) { if((errno == ENOENT) && bad_path) @@ -232,23 +228,21 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } unixmode = unix_mode(conn,open_attr | aARCH, fname); - open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode, + fsp = open_file_shared(conn,fname,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); - if (!fsp->open) + if (!fsp) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1794,113 +1788,110 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * the share mode contained ALLOW_SHARE_DELETE */ - if(lp_share_modes(SNUM(conn))) + if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * If the flag has been set then + * modify the share mode entry for all files we have open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. + */ + + if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) { - if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) + int i; + files_struct *iterate_fsp; + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; + int num_share_modes; + share_mode_entry *current_shares = NULL; + + if (lock_share_entry_fsp(fsp) == False) return(ERROR(ERRDOS,ERRnoaccess)); /* - * If the flag has been set then - * modify the share mode entry for all files we have open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. + * Before we allow this we need to ensure that all current opens + * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they + * do not then we deny this (as we are essentially deleting the + * file at this point. */ - if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) + num_share_modes = get_share_modes(conn, dev, inode, ¤t_shares); + for(i = 0; i < num_share_modes; i++) { - int i; - files_struct *iterate_fsp; - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; - int num_share_modes; - share_mode_entry *current_shares = NULL; - - if (lock_share_entry_fsp(fsp) == False) - return(ERROR(ERRDOS,ERRnoaccess)); - - /* - * Before we allow this we need to ensure that all current opens - * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they - * do not then we deny this (as we are essentially deleting the - * file at this point. - */ - - num_share_modes = get_share_modes(conn, dev, inode, ¤t_shares); - for(i = 0; i < num_share_modes; i++) + if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) { - if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) - { - DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \ + DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \ file %s as a share exists that was not opened with FILE_DELETE access.\n", - fsp->fnum, fsp->fsp_name )); - /* - * Release the lock. - */ + fsp->fnum, fsp->fsp_name )); + /* + * Release the lock. + */ - unlock_share_entry_fsp(fsp); + unlock_share_entry_fsp(fsp); - /* - * current_shares was malloced by get_share_modes - free it here. - */ + /* + * current_shares was malloced by get_share_modes - free it here. + */ - free((char *)current_shares); + free((char *)current_shares); - /* - * Even though share violation would be more appropriate here, - * return ERRnoaccess as that's what NT does. - */ + /* + * Even though share violation would be more appropriate here, + * return ERRnoaccess as that's what NT does. + */ - return(ERROR(ERRDOS,ERRnoaccess)); - } + return(ERROR(ERRDOS,ERRnoaccess)); } + } - /* - * current_shares was malloced by get_share_modes - free it here. - */ + /* + * current_shares was malloced by get_share_modes - free it here. + */ - free((char *)current_shares); + free((char *)current_shares); - DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - /* - * Go through all files we have open on the same device and - * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. - * Other smbd's that have this file open will have to fend for themselves. We - * take care of this (rare) case in close_file(). See the comment there. - */ + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + * Other smbd's that have this file open will have to fend for themselves. We + * take care of this (rare) case in close_file(). See the comment there. + */ - for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; - iterate_fsp = file_find_di_next(iterate_fsp)) - { - int new_share_mode = (delete_on_close ? - (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : - (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; + iterate_fsp = file_find_di_next(iterate_fsp)) + { + int new_share_mode = (delete_on_close ? + (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : + (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); - DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \ + DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \ dev = %x, inode = %.0f from %x to %x\n", - iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, - (double)inode, iterate_fsp->share_mode, new_share_mode )); + iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, + (double)inode, iterate_fsp->share_mode, new_share_mode )); - if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False) - DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ + if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False) + DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)); - } + } - /* - * Set the delete on close flag in the reference - * counted struct. Delete when the last reference - * goes away. - */ - fsp->delete_on_close = delete_on_close; + /* + * Set the delete on close flag in the reference + * counted struct. Delete when the last reference + * goes away. + */ + fsp->delete_on_close = delete_on_close; - unlock_share_entry_fsp(fsp); + unlock_share_entry_fsp(fsp); - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */ - } /* end if lp_share_modes() */ + } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */ } /* end if is_directory. */ } else return(ERROR(ERRDOS,ERRunknownlevel)); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index b9c22ef1f9..a3dd752023 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -297,3 +297,11 @@ int vfswrap_utime(char *path, struct utimbuf *times) result = utime(path, times); return result; } + +int vfswrap_ftruncate(int fd, SMB_OFF_T offset) +{ + int result; + + result = sys_ftruncate(fd, offset); + return result; +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index e92235e230..d76d64684b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -64,7 +64,8 @@ struct vfs_ops default_vfs_ops = { vfswrap_lstat, vfswrap_unlink, vfswrap_chmod, - vfswrap_utime + vfswrap_utime, + vfswrap_ftruncate }; /**************************************************************************** @@ -208,6 +209,10 @@ BOOL vfs_init_custom(connection_struct *conn) conn->vfs_ops.utime = default_vfs_ops.utime; } + if (conn->vfs_ops.ftruncate == NULL) { + conn->vfs_ops.ftruncate= default_vfs_ops.ftruncate; + } + return True; } #endif -- cgit From d384e1801d7cd841f67f3c9216900d2e59e9d1d5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 22 Apr 2000 08:27:48 +0000 Subject: fixed uninitialised snum (This used to be commit 14251aab2ec00aa7f3e6a6e791e78732cb5a9eda) --- source3/smbd/lanman.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 391a94596a..aaf2bc017f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2617,6 +2617,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para if (!check_printjob_info(&desc,uLevel,str2)) return False; job = SVAL(p,0); + snum = print_job_snum(job); if (snum < 0 || !VALID_SNUM(snum)) return(False); -- cgit From f7608e853596bcb6e8d3d4dd6bb4407fa090fbc1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 22 Apr 2000 08:28:22 +0000 Subject: fixed overlapping strcpy() found by insure (This used to be commit 1106fa7f24d229c3877263b7a7dde359556435e6) --- source3/smbd/reply.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3acfd988d6..baff8f2ac8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -260,10 +260,9 @@ int reply_tcon(connection_struct *conn, /**************************************************************************** Reply to a tcon and X. ****************************************************************************/ - int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - pstring service; + fstring service; pstring user; pstring password; pstring devicename; @@ -295,11 +294,9 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt passlen = strlen(password); } - fstrcpy(service,path+2); - p = strchr(service,'\\'); + p = strchr(path+2,'\\'); if (!p) return(ERROR(ERRSRV,ERRinvnetname)); - *p = 0; fstrcpy(service,p+1); p = strchr(service,'%'); if (p) { @@ -309,11 +306,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt StrnCpy(devicename,path + strlen(path) + 1,6); DEBUG(4,("Got device type %s\n",devicename)); - /* - * Ensure the user and password names are in UNIX codepage format. - */ + /* + * Ensure the user and password names are in UNIX codepage format. + */ - dos_to_unix(user,True); + dos_to_unix(user,True); if (!doencrypt) dos_to_unix(password,True); -- cgit From 67239541cdd0d1098be05f44d9f7a18e7604cef5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 22 Apr 2000 08:28:49 +0000 Subject: don't copy a null groups list (This used to be commit d0fc1675df35e65488a19d7f5929792fba347b07) --- source3/smbd/service.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b7942906df..8d04ce36e1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -381,8 +381,12 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->vfs_conn->uid = conn->uid; conn->vfs_conn->gid = conn->gid; conn->vfs_conn->ngroups = conn->ngroups; - conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, - conn->ngroups * sizeof(gid_t)); + if (conn->vfs_conn->ngroups != 0) { + conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, + conn->ngroups * sizeof(gid_t)); + } else { + conn->vfs_conn->groups = NULL; + } /* Initialise VFS function pointers */ -- cgit From 71499fbe98b35b7253dbe158ba9d417adecefdc9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 Apr 2000 07:40:13 +0000 Subject: avoided a memory leak in the ubi code by deleting a mangled cache entry before adding to ensure that we don't ever add a duplicate entry this code can be removed when ubi gets fixed (This used to be commit 062d79bf8ba5308803393c7b9140d1f77db3690f) --- source3/smbd/mangle.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index e47bcd896f..8ac91d49c8 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -465,7 +465,8 @@ static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) */ static void cache_free_entry( ubi_trNodePtr WarrenZevon ) { - free( WarrenZevon ); + ZERO_STRUCTP(WarrenZevon); + free( WarrenZevon ); } /* cache_free_entry */ /* ************************************************************************** ** @@ -575,6 +576,15 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) s2 = (char *)&(s1[mangled_len + 1]); (void)StrnCpy( s1, mangled_name, mangled_len ); (void)StrnCpy( s2, raw_name, raw_len ); + + /* possibly delete an old entry - this avoids a memory leak in the + ubi code to do with overwriting existing entries. + + remove this test when ubi gets fixed */ + if (ubi_cacheGet(mangled_cache, s1)) { + ubi_cacheDelete(mangled_cache, s1); + } + ubi_cachePut( mangled_cache, i, new_entry, s1 ); } /* cache_mangled_name */ -- cgit From d44ae9e229c67f0bf230c0d64d903a55f592f248 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 Apr 2000 07:42:13 +0000 Subject: insure caught an uninitialised memory reference - ensure it starts as zero (This used to be commit 53077295b76487a6eafc6b14b69a91074a02aa35) --- source3/smbd/nttrans.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c82a8074d9..ca9522ecfc 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1605,6 +1605,8 @@ BOOL process_pending_change_notify_queue(time_t t) uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); + ZERO_STRUCT(change_data); + /* * Ensure we don't have any old chain_fsp values * sitting around.... -- cgit From c389bd2d6b53e3b913352677ac48288b5b90c6b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 Apr 2000 07:43:32 +0000 Subject: trick to get full stack trace when using the free version of insure (This used to be commit bb9b3e03deebe23cf3fe10c2cb9b67a730e086a2) --- source3/smbd/server.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a7baa9e327..387aeb5df1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -779,3 +779,27 @@ static void usage(char *pname) exit_server("normal exit"); return(0); } + + +#ifdef __INSURE__ +int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6) +{ + static int (*fn)(); + int ret; + char *cmd = lp_panic_action(); + + if (!fn) { + static void *h; + h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY); + fn = dlsym(h, "_Insure_trap_error"); + } + + ret = fn(a1, a2, a3, a4, a5, a6); + + if (cmd && *cmd) { + system(cmd); + } + + return ret; +} +#endif -- cgit From 7fcdb8fb7ea14b014902342cf4eb1e4d92446498 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 Apr 2000 07:44:01 +0000 Subject: fixed two uninitialised memory references (This used to be commit e4ddd1a4a96b7f723d3d92e4334f4033e1dbc8a8) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f0a645d6c7..7a5276aa42 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -758,7 +758,7 @@ static int call_trans2findfirst(connection_struct *conn, for (i=0;(i Date: Mon, 24 Apr 2000 11:31:20 +0000 Subject: moved INSURE hook into util.c (This used to be commit 2fba24ef0e4cae64c5a179370c83d8bbf4e70bb8) --- source3/smbd/server.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 387aeb5df1..83c70a9e89 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -780,26 +780,3 @@ static void usage(char *pname) return(0); } - -#ifdef __INSURE__ -int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6) -{ - static int (*fn)(); - int ret; - char *cmd = lp_panic_action(); - - if (!fn) { - static void *h; - h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY); - fn = dlsym(h, "_Insure_trap_error"); - } - - ret = fn(a1, a2, a3, a4, a5, a6); - - if (cmd && *cmd) { - system(cmd); - } - - return ret; -} -#endif -- cgit From e82dbfcbe97c79b1c81915ae949bb2b1763970ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Apr 2000 19:23:51 +0000 Subject: Now that fsp's are created on successful file open, the structure member fsp->open is no longer needed (if an fsp pointer is valid, then it's open :-). NB for Luke, this patch also did not apply to TNG. TNG is not yet identical w.r.t file serving with HEAD. This makes it impossible for me to help maintain TNG. Please fix asap. lib/substitute.c: Removed unused variable (pidstr). Jeremy. (This used to be commit 389b700a26e8a308a0dff6fc038c38068aa0119a) --- source3/smbd/close.c | 2 +- source3/smbd/files.c | 33 +++++++++++++++++++++++---------- source3/smbd/nttrans.c | 2 +- source3/smbd/open.c | 16 ++++++---------- source3/smbd/oplock.c | 4 ++-- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 4 ++-- 7 files changed, 36 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index ec28ff3540..03f6aaf81a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -72,8 +72,8 @@ void close_filestruct(files_struct *fsp) flush_write_cache(fsp, CLOSE_FLUSH); - fsp->open = False; fsp->is_directory = False; + fsp->stat_open = False; conn->num_files_open--; if(fsp->wbmpx_ptr) { diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 6c0465097b..e644f52669 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -120,7 +120,7 @@ void file_close_conn(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next = fsp->next; - if (fsp->conn == conn && fsp->open) { + if (fsp->conn == conn) { close_file(fsp,False); } } @@ -173,7 +173,7 @@ void file_close_user(int vuid) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if ((fsp->vuid == vuid) && fsp->open) { + if (fsp->vuid == vuid) { close_file(fsp,False); } } @@ -191,8 +191,7 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { - if (fsp->open && - fsp->fd != -1 && + if (fsp->fd != -1 && fsp->dev == dev && fsp->inode == inode && (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) && @@ -207,6 +206,22 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval return NULL; } +/**************************************************************************** + Check if an fsp still exists. +****************************************************************************/ + +files_struct *file_find_fsp(files_struct *orig_fsp) +{ + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp == orig_fsp) + return fsp; + } + + return NULL; +} + /**************************************************************************** Find the first fsp given a device and inode. ****************************************************************************/ @@ -216,8 +231,7 @@ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next) { - if (fsp->open && - fsp->fd != -1 && + if ( fsp->fd != -1 && fsp->dev == dev && fsp->inode == inode ) return fsp; @@ -235,8 +249,7 @@ files_struct *file_find_di_next(files_struct *start_fsp) files_struct *fsp; for (fsp = start_fsp->next;fsp;fsp=fsp->next) { - if (fsp->open && - fsp->fd != -1 && + if ( fsp->fd != -1 && fsp->dev == start_fsp->dev && fsp->inode == start_fsp->inode ) return fsp; @@ -253,7 +266,7 @@ files_struct *file_find_print(void) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next) { - if (fsp->open && fsp->print_file) return fsp; + if (fsp->print_file) return fsp; } return NULL; @@ -269,7 +282,7 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if (fsp->open && (conn == fsp->conn) && (fsp->fd != -1)) { + if ((conn == fsp->conn) && (fsp->fd != -1)) { conn->vfs_ops.fsync(fsp->fd); } } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ca9522ecfc..b4ae0f61a9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1708,7 +1708,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, if(!fsp) return(ERROR(ERRDOS,ERRbadfid)); - if((!fsp->open) || (!fsp->is_directory) || (conn != fsp->conn)) + if((!fsp->is_directory) || (conn != fsp->conn)) return(ERROR(ERRDOS,ERRbadfid)); /* diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d2368aa44d..353e20df8a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -90,8 +90,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, int accmode = (flags & O_ACCMODE); SMB_STRUCT_STAT sbuf; - fsp->open = False; - fsp->fd = 0; + fsp->fd = -1; fsp->oplock_type = NO_OPLOCK; errno = EPERM; @@ -155,7 +154,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->vuid = current_user.vuid; fsp->size = 0; fsp->pos = -1; - fsp->open = True; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); @@ -508,6 +506,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod SMB_INO_T inode = 0; int num_share_modes = 0; BOOL all_current_opens_are_level_II = False; + BOOL fsp_open = False; files_struct *fsp = NULL; int open_mode=0; uint16 port = 0; @@ -524,7 +523,6 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod if(!fsp) return NULL; - fsp->open = False; fsp->fd = -1; DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", @@ -638,14 +636,14 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); - fsp->open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); + fsp_open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); - if (!fsp->open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { - if((fsp->open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True) + if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { + if((fsp_open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True) flags = O_RDONLY; } - if (!fsp->open) { + if (!fsp_open) { if(file_existed) unlock_share_entry(conn, dev, inode); file_free(fsp); @@ -790,7 +788,6 @@ files_struct *open_file_stat(connection_struct *conn, fsp->vuid = current_user.vuid; fsp->size = 0; fsp->pos = -1; - fsp->open = True; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; @@ -915,7 +912,6 @@ files_struct *open_directory(connection_struct *conn, fsp->vuid = current_user.vuid; fsp->size = 0; fsp->pos = -1; - fsp->open = True; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e794d2d923..28ab29d027 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1304,10 +1304,10 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - if (fsp->open && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd != -1)) { + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd != -1)) { /* Try and break the oplock. */ if (oplock_break(fsp->dev, fsp->inode, &fsp->open_time, True)) { - if(!fsp->open) /* Did the oplock break close the file ? */ + if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */ return True; } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index baff8f2ac8..a020f5eb3b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2751,7 +2751,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * We can only use CHECK_FSP if we know it's not a directory. */ - if(!fsp || !fsp->open || (fsp->conn != conn)) + if(!fsp || (fsp->conn != conn)) return(ERROR(ERRDOS,ERRbadfid)); if(HAS_CACHED_ERROR(fsp)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7a5276aa42..a30038a431 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1296,7 +1296,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); - if(fsp && fsp->open && (fsp->is_directory || fsp->stat_open)) { + if(fsp && (fsp->is_directory || fsp->stat_open)) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems @@ -1579,7 +1579,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fsp = file_fsp(params,0); info_level = SVAL(params,2); - if(fsp && fsp->open && (fsp->is_directory || fsp->stat_open)) { + if(fsp && (fsp->is_directory || fsp->stat_open)) { /* * This is actually a SETFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems -- cgit From 644f22ac6141f58f2badd3a9761ac156831c16a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Apr 2000 20:48:40 +0000 Subject: Added the code that keeps fd's open across a close if there are other fsp's open on the same dev/inode pair with existing POSIX locks. This is done at the smbd/open layer, so smbd just calls fd_close() and the transfer of any open fd's is done under the covers of fd_close(). When an fsp is closed and no other fsp's open on the same dev/inode pair have existing POSIX locks then all fd's associated with this fsp are closed. Now only the hard part of doing the POSIX range unlock code when read locks overlap remains for full POSIX/SMB lock integration.... Jeremy. (This used to be commit 1df48ed55ee303b6d84d7277fd79761cfe5f7052) --- source3/smbd/open.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 353e20df8a..44bb6ebaf7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -49,14 +49,126 @@ static int fd_open(struct connection_struct *conn, char *fname, return fd; } +/**************************************************************************** + Take care of moving any POSIX pending close fd's to another fsp. +****************************************************************************/ + +static BOOL fd_close_posix_locks(files_struct *fsp) +{ + files_struct *other_fsp; + + DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u.\n", fsp->fsp_name, + (unsigned int)fsp->num_posix_pending_closes )); + + for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp; + other_fsp = file_find_di_next(other_fsp)) { + + if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) { + + /* + * POSIX locks pending on another fsp held open, transfer + * the fd in this fsp and all the pending fd's in this fsp pending close array + * to the other_fsp pending close array. + */ + + unsigned int extra_fds = fsp->num_posix_pending_closes + 1; + + DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \ +file %s, other_fsp->num_posix_pending_closes = %u.\n", + fsp->fsp_name, other_fsp->fsp_name, (unsigned int)other_fsp->num_posix_pending_closes )); + + other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds, + (other_fsp->num_posix_pending_closes + + extra_fds)*sizeof(int)); + + if(other_fsp->posix_pending_close_fds == NULL) { + DEBUG(0,("fd_close_posix_locks: Unable to increase posix_pending_close_fds array size !\n")); + return False; + } + + /* + * Copy over any fd's in the existing fsp's pending array. + */ + + if(fsp->posix_pending_close_fds) { + memcpy(&other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes], + &fsp->posix_pending_close_fds[0], fsp->num_posix_pending_closes * sizeof(int) ); + + free((char *)fsp->posix_pending_close_fds); + fsp->posix_pending_close_fds = NULL; + fsp->num_posix_pending_closes = 0; + } + + other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes+extra_fds-1] = fsp->fd; + other_fsp->num_posix_pending_closes += extra_fds; + + fsp->fd = -1; /* We have moved this fd to other_fsp's pending close array.... */ + + break; + } + } + + return True; +} + /**************************************************************************** Close the file associated with a fsp. + + This is where we must deal with POSIX "first close drops all locks" + locking braindamage. We do this by searching for any other fsp open + on the same dev/inode with open POSIX locks, and then transferring this + fd (and all pending fd's attached to this fsp) to the posix_pending_close_fds + array in that fsp. + + If there are no open fsp's on the same dev/inode then we close all the + fd's in the posix_pending_close_fds array and then close the fd. + ****************************************************************************/ int fd_close(struct connection_struct *conn, files_struct *fsp) { - int ret = conn->vfs_ops.close(fsp->fd); + int ret = 0; + int saved_errno = 0; + unsigned int i; + + /* + * Deal with transferring any pending fd's if there + * are POSIX locks outstanding. + */ + + if(!fd_close_posix_locks(fsp)) + return -1; + + /* + * Close and free any pending closes given to use from + * other fsp's. + */ + + if (fsp->posix_pending_close_fds) { + + for(i = 0; i < fsp->num_posix_pending_closes; i++) { + if (fsp->posix_pending_close_fds[i] != -1) { + if (conn->vfs_ops.close(fsp->posix_pending_close_fds[i]) == -1) { + saved_errno = errno; + } + } + } + + free((char *)fsp->posix_pending_close_fds); + fsp->posix_pending_close_fds = NULL; + fsp->num_posix_pending_closes = 0; + } + + if(fsp->fd != -1) + ret = conn->vfs_ops.close(fsp->fd); + fsp->fd = -1; + + if (saved_errno != 0) { + errno = saved_errno; + ret = -1; + } + return ret; } @@ -163,6 +275,8 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->num_posix_locks = 0; + fsp->num_posix_pending_closes = 0; + fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = False; fsp->directory_delete_on_close = False; @@ -797,6 +911,8 @@ files_struct *open_file_stat(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->num_posix_locks = 0; + fsp->num_posix_pending_closes = 0; + fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = True; fsp->directory_delete_on_close = False; @@ -921,6 +1037,8 @@ files_struct *open_directory(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->num_posix_locks = 0; + fsp->num_posix_pending_closes = 0; + fsp->posix_pending_close_fds = NULL; fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; -- cgit From 00e3fe132476fcaed0f4b9bbe74b0a6559c39df0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 25 Apr 2000 14:06:57 +0000 Subject: moved trans2.h and nterr.h into includes.h with all our other includes (This used to be commit d7cd7c88fdabb01d9e40ae8a657737907a21ac37) --- source3/smbd/ipc.c | 1 - source3/smbd/lanman.c | 1 - source3/smbd/nttrans.c | 1 - source3/smbd/pipes.c | 1 - source3/smbd/reply.c | 2 -- source3/smbd/server.c | 1 - source3/smbd/trans2.c | 1 - 7 files changed, 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f87423c9ca..73addda086 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -27,7 +27,6 @@ */ #include "includes.h" -#include "nterr.h" extern int DEBUGLEVEL; extern int max_send; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index aaf2bc017f..9774305fc9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -27,7 +27,6 @@ */ #include "includes.h" -#include "nterr.h" #ifdef CHECK_TYPES #undef CHECK_TYPES diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b4ae0f61a9..98f5959c2d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "nterr.h" extern int DEBUGLEVEL; extern int Protocol; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 5d5c6a653a..0cfe653d30 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -27,7 +27,6 @@ #include "includes.h" -#include "trans2.h" #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a020f5eb3b..590dc4f427 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -25,8 +25,6 @@ #include "includes.h" -#include "trans2.h" -#include "nterr.h" /* look in server.c for some explanation of these variables */ extern int Protocol; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 83c70a9e89..8e4de78cbf 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -20,7 +20,6 @@ */ #include "includes.h" -#include "trans2.h" pstring servicesf = CONFIGFILE; extern pstring debugf; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a30038a431..4e502f767b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -22,7 +22,6 @@ */ #include "includes.h" -#include "trans2.h" extern int DEBUGLEVEL; extern int Protocol; -- cgit From c4af7ad8dc75ca252c6e8812b126a171849cc7d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 16:53:31 +0000 Subject: Tidyup of smbecho. Jeremy. (This used to be commit 4a4b7a994bbe327216f736133edc51cf9a351716) --- source3/smbd/reply.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 590dc4f427..4134df221e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2960,9 +2960,11 @@ int reply_echo(connection_struct *conn, { int smb_reverb = SVAL(inbuf,smb_vwv0); int seq_num; - int data_len = smb_buflen(inbuf); + unsigned int data_len = smb_buflen(inbuf); int outsize = set_message(outbuf,1,data_len,True); - + + data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf))); + /* copy any incoming data back out */ if (data_len > 0) memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len); -- cgit From 3d9141d4156a3207af03d4137acd4b1cde46cfae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 17:14:45 +0000 Subject: Fixed range check on writeX. Jeremy. (This used to be commit 9cde198108439358e99128fa9a1b3000e33f5414) --- source3/smbd/reply.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4134df221e..41c6dcb143 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2545,7 +2545,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng size_t numtowrite = SVAL(inbuf,smb_vwv10); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); ssize_t nwritten = -1; - int smb_doff = SVAL(inbuf,smb_vwv11); + unsigned int smb_doff = SVAL(inbuf,smb_vwv11); char *data; /* If it's an IPC, pass off the pipe handler. */ @@ -2556,6 +2556,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_WRITE(fsp); CHECK_ERROR(fsp); + if(smb_doff > smb_len(inbuf)) + return(ERROR(ERRDOS,ERRbadmem)); + data = smb_base(inbuf) + smb_doff; if(CVAL(inbuf,smb_wct) == 14) { -- cgit From e3987ff7a638f9ea8b6794f1ed0df530d8488033 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 18:46:10 +0000 Subject: Fixed crash bugs Andrew pointed out with LOCK4 smbtorture test. Was miscounting posix locks, plus was not taking into account the case where other_fsp == fsp in the 'move locks' case. DOH ! This code will be re-written anyway :-). Jeremy. (This used to be commit 5278ec016cb24d8263fe6e7c1d389f466270ef24) --- source3/smbd/open.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 44bb6ebaf7..c7ca8256d2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -57,12 +57,16 @@ static BOOL fd_close_posix_locks(files_struct *fsp) { files_struct *other_fsp; - DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u.\n", fsp->fsp_name, - (unsigned int)fsp->num_posix_pending_closes )); + DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u \ +fsp->posix_pending_close_fds = %lx.\n", fsp->fsp_name, + (unsigned int)fsp->num_posix_pending_closes, (unsigned long)fsp->posix_pending_close_fds )); for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp; other_fsp = file_find_di_next(other_fsp)) { + if(other_fsp == fsp) + continue; + if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) { /* @@ -74,8 +78,8 @@ static BOOL fd_close_posix_locks(files_struct *fsp) unsigned int extra_fds = fsp->num_posix_pending_closes + 1; DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \ -file %s, other_fsp->num_posix_pending_closes = %u.\n", - fsp->fsp_name, other_fsp->fsp_name, (unsigned int)other_fsp->num_posix_pending_closes )); +file %s, extra_fds = %u, other_fsp->num_posix_pending_closes = %u.\n", + fsp->fsp_name, other_fsp->fsp_name, extra_fds, (unsigned int)other_fsp->num_posix_pending_closes )); other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds, (other_fsp->num_posix_pending_closes + -- cgit From 3d3c50326ba7f32ebb2fc683a3410dc0d1f18cdc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 21:12:33 +0000 Subject: Did the rewrite Andrew wanted where all knowledge of POSIX locking is removed from the smbd/open.c code. We now use a dlink list of structures indexed by dev/inode to store all pending fd's for close. This could be rewritten to use lib/hash.c if this is discovered to be too slow in use. Andrew, please take a look and let me know if this is what you had in mind. Jeremy. (This used to be commit 0487841120a7584da9a2b83b9574562c415d7024) --- source3/smbd/open.c | 115 +--------------------------------------------------- 1 file changed, 1 insertion(+), 114 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c7ca8256d2..737b9b5ef3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -49,130 +49,26 @@ static int fd_open(struct connection_struct *conn, char *fname, return fd; } -/**************************************************************************** - Take care of moving any POSIX pending close fd's to another fsp. -****************************************************************************/ - -static BOOL fd_close_posix_locks(files_struct *fsp) -{ - files_struct *other_fsp; - - DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u \ -fsp->posix_pending_close_fds = %lx.\n", fsp->fsp_name, - (unsigned int)fsp->num_posix_pending_closes, (unsigned long)fsp->posix_pending_close_fds )); - - for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp; - other_fsp = file_find_di_next(other_fsp)) { - - if(other_fsp == fsp) - continue; - - if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) { - - /* - * POSIX locks pending on another fsp held open, transfer - * the fd in this fsp and all the pending fd's in this fsp pending close array - * to the other_fsp pending close array. - */ - - unsigned int extra_fds = fsp->num_posix_pending_closes + 1; - - DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \ -file %s, extra_fds = %u, other_fsp->num_posix_pending_closes = %u.\n", - fsp->fsp_name, other_fsp->fsp_name, extra_fds, (unsigned int)other_fsp->num_posix_pending_closes )); - - other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds, - (other_fsp->num_posix_pending_closes + - extra_fds)*sizeof(int)); - - if(other_fsp->posix_pending_close_fds == NULL) { - DEBUG(0,("fd_close_posix_locks: Unable to increase posix_pending_close_fds array size !\n")); - return False; - } - - /* - * Copy over any fd's in the existing fsp's pending array. - */ - - if(fsp->posix_pending_close_fds) { - memcpy(&other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes], - &fsp->posix_pending_close_fds[0], fsp->num_posix_pending_closes * sizeof(int) ); - - free((char *)fsp->posix_pending_close_fds); - fsp->posix_pending_close_fds = NULL; - fsp->num_posix_pending_closes = 0; - } - - other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes+extra_fds-1] = fsp->fd; - other_fsp->num_posix_pending_closes += extra_fds; - - fsp->fd = -1; /* We have moved this fd to other_fsp's pending close array.... */ - - break; - } - } - - return True; -} - /**************************************************************************** Close the file associated with a fsp. - - This is where we must deal with POSIX "first close drops all locks" - locking braindamage. We do this by searching for any other fsp open - on the same dev/inode with open POSIX locks, and then transferring this - fd (and all pending fd's attached to this fsp) to the posix_pending_close_fds - array in that fsp. - - If there are no open fsp's on the same dev/inode then we close all the - fd's in the posix_pending_close_fds array and then close the fd. - ****************************************************************************/ int fd_close(struct connection_struct *conn, files_struct *fsp) { int ret = 0; - int saved_errno = 0; - unsigned int i; /* * Deal with transferring any pending fd's if there * are POSIX locks outstanding. */ - if(!fd_close_posix_locks(fsp)) + if(!fd_close_posix_locks(conn,fsp)) return -1; - /* - * Close and free any pending closes given to use from - * other fsp's. - */ - - if (fsp->posix_pending_close_fds) { - - for(i = 0; i < fsp->num_posix_pending_closes; i++) { - if (fsp->posix_pending_close_fds[i] != -1) { - if (conn->vfs_ops.close(fsp->posix_pending_close_fds[i]) == -1) { - saved_errno = errno; - } - } - } - - free((char *)fsp->posix_pending_close_fds); - fsp->posix_pending_close_fds = NULL; - fsp->num_posix_pending_closes = 0; - } - if(fsp->fd != -1) ret = conn->vfs_ops.close(fsp->fd); fsp->fd = -1; - - if (saved_errno != 0) { - errno = saved_errno; - ret = -1; - } - return ret; } @@ -278,9 +174,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->num_posix_locks = 0; - fsp->num_posix_pending_closes = 0; - fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = False; fsp->directory_delete_on_close = False; @@ -914,9 +807,6 @@ files_struct *open_file_stat(connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->num_posix_locks = 0; - fsp->num_posix_pending_closes = 0; - fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = True; fsp->directory_delete_on_close = False; @@ -1040,9 +930,6 @@ files_struct *open_directory(connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->num_posix_locks = 0; - fsp->num_posix_pending_closes = 0; - fsp->posix_pending_close_fds = NULL; fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; -- cgit From 36db78fedad935aaa689d52d7f58e075f1f71812 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 22:23:04 +0000 Subject: Fixed subtle unlocking bug when a file is closed. We need to store the smbpid used when a file was opened in the files_struct. Else we use the wrong global_smbpid when we are closing the file and trying to remove the brl locks - this causes the brl locks to be left when the file is closed as the samba_context check fails. Jeremy. (This used to be commit 2746e5602e493e5b022764b4b839eb4d2f14363b) --- source3/smbd/open.c | 4 ++++ source3/smbd/process.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 737b9b5ef3..92bba76619 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -26,6 +26,7 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; +extern int global_smbpid; /**************************************************************************** fd support routines - attempt to do a dos_open. @@ -164,6 +165,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = sbuf.st_dev; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; + fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; @@ -797,6 +799,7 @@ files_struct *open_file_stat(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; + fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = False; @@ -920,6 +923,7 @@ files_struct *open_directory(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; + fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f378550282..77e6fc2aa7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -28,6 +28,7 @@ struct timeval smb_last_time; static char *InBuffer = NULL; char *OutBuffer = NULL; char *last_inbuf = NULL; +int global_smbpid; /* * Size of data we can send to client. Set @@ -418,7 +419,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize static int num_smb_messages = sizeof(smb_messages) / sizeof(struct smb_message_struct); int match; - extern int global_smbpid; if (pid == (pid_t)-1) pid = getpid(); -- cgit From 4b60a33c6fa733060068e192b87c2e858103d6eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 23:28:56 +0000 Subject: Ok - this is more subtle than it looks :-). When a file is being closed, once it passes the fnum and tid tests then the locking context should be ignored when removing all locks. This is what is done in the brl close case, but when you have outstanding POSIX locks, then you cannot remove all the brl locks in one go, you have to get the lock list and call do_unlock individually. As this uses global_smbpid as the locking context, you need to make sure that this is set correctly for the specific lock being removed. I now do this by storing the smbpid in each entry in the unlock list returned from the query call. I removed the smbpid from fsp (not needed) and things seem ok (even with the stupid smbpid tricks that smbtorture plays :-). Jeremy. (This used to be commit 6baa96bb466915cc17e8cbad50254d6bd47b967b) --- source3/smbd/open.c | 4 ---- source3/smbd/process.c | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 92bba76619..737b9b5ef3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -26,7 +26,6 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; -extern int global_smbpid; /**************************************************************************** fd support routines - attempt to do a dos_open. @@ -165,7 +164,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = sbuf.st_dev; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; @@ -799,7 +797,6 @@ files_struct *open_file_stat(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = False; @@ -923,7 +920,6 @@ files_struct *open_directory(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 77e6fc2aa7..f378550282 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -28,7 +28,6 @@ struct timeval smb_last_time; static char *InBuffer = NULL; char *OutBuffer = NULL; char *last_inbuf = NULL; -int global_smbpid; /* * Size of data we can send to client. Set @@ -419,6 +418,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize static int num_smb_messages = sizeof(smb_messages) / sizeof(struct smb_message_struct); int match; + extern int global_smbpid; if (pid == (pid_t)-1) pid = getpid(); -- cgit From be828fcec88a43306ddfb53473fda52df1d9965b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 00:39:23 +0000 Subject: Made changes suggested by Andrew review. fd_close now calls fd_close_posix() directly. set_posix_lock/release_posix_lock() now handle the reference counting. More changes due when this gets moved to the file locking/posix.c Jeremy. (This used to be commit 239abd48f049c6a8d2bbc0636eacf347ab77588c) --- source3/smbd/open.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 737b9b5ef3..9aadb39bc9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -55,21 +55,7 @@ static int fd_open(struct connection_struct *conn, char *fname, int fd_close(struct connection_struct *conn, files_struct *fsp) { - int ret = 0; - - /* - * Deal with transferring any pending fd's if there - * are POSIX locks outstanding. - */ - - if(!fd_close_posix_locks(conn,fsp)) - return -1; - - if(fsp->fd != -1) - ret = conn->vfs_ops.close(fsp->fd); - - fsp->fd = -1; - return ret; + return fd_close_posix(conn, fsp); } -- cgit From 46d66938e7e683586746b18583ce1670f0ad3544 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 21:09:26 +0000 Subject: Moved deletion of vfs handle into smbd/conn.c as it was being done too soon in smbd/service.c (file operations were being done after the handle was closed). It looks cleaner in smbd/conn.c as it is part of the closing of a conn struct anyway. Jeremy. (This used to be commit 858eb53dc510d1b27c4f91045fa932a3ef546754) --- source3/smbd/conn.c | 15 +++++++++++++++ source3/smbd/service.c | 16 ---------------- 2 files changed, 15 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 83289b2184..1dc4ac9e7d 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -164,6 +164,21 @@ free a conn structure ****************************************************************************/ void conn_free(connection_struct *conn) { + /* Close dlopen() handle */ + + if (conn->vfs_conn->dl_handle != NULL) { + dlclose(conn->vfs_conn->dl_handle); /* should we check return val? */ + } + + /* Free vfs_connection_struct */ + + if (conn->vfs_conn != NULL) { + if (conn->vfs_conn->groups != NULL) { + free(conn->vfs_conn->groups); + } + free(conn->vfs_conn); + } + DLIST_REMOVE(Connections, conn); if (conn->ngroups && conn->groups) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8d04ce36e1..8e04f7e989 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -654,21 +654,6 @@ void close_cnum(connection_struct *conn, uint16 vuid) } - /* Close dlopen() handle */ - - if (conn->vfs_conn->dl_handle != NULL) { - dlclose(conn->vfs_conn->dl_handle); /* should we check return val? */ - } - - /* Free vfs_connection_struct */ - - if (conn->vfs_conn != NULL) { - if (conn->vfs_conn->groups != NULL) { - free(conn->vfs_conn->groups); - } - free(conn->vfs_conn); - } - yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); @@ -697,6 +682,5 @@ void close_cnum(connection_struct *conn, uint16 vuid) standard_sub_conn(conn,cmd); smbrun(cmd,NULL,False); } - conn_free(conn); } -- cgit From 700f72453ed8dfd356a5591b9447127b5066ac4b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 11:04:28 +0000 Subject: - removed all our old wildcard matching code and replaced it with a call to ms_fnmatch(). This also removes all the Win9X semantics stuff and a bunch of other associated cruft. - moved the stat cache code into statcache.c - fixed the uint16 alignment requirements of ascii_to_unistr() and unistr_to_ascii() - trans2 SMB_FIND_FILE_BOTH_DIRECTORY_INFO returns the short name as unicode always (at least thats what NT4 does) - fixed some errors in the in-memory tdb code. Still ugly, but doesn't crash as much (This used to be commit 03e9cea004bbba72161a5323cf3b4556c94aed8e) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/dir.c | 2 +- source3/smbd/filename.c | 259 +---------------------------------------------- source3/smbd/reply.c | 15 ++- source3/smbd/statcache.c | 243 ++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/trans2.c | 67 ++++++------ 6 files changed, 282 insertions(+), 306 deletions(-) create mode 100644 source3/smbd/statcache.c (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index df1f92f5ce..484523bd27 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -249,7 +249,7 @@ static int expect(int master, char *issue, char *expected) nread += len; buffer[nread] = 0; - if ((match = unix_do_match(buffer, expected, False))) + if ((match = (ms_fnmatch(expected, buffer) == 0))) timeout = 200; } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 55d5bf132c..bd4e2a44f9 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -604,7 +604,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, if ((filename_is_mask = (strcmp(filename,mask) == 0)) || (name_map_mangle(filename,True,False,SNUM(conn)) && - mask_match(filename,mask,False,False))) + mask_match(filename,mask,False))) { if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) continue; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7afa9e9986..ed1a1c3f63 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -88,228 +88,6 @@ static BOOL mangled_equal(char *name1, char *name2) return(strequal(name1,tmpname)); } -/**************************************************************************** - Stat cache code used in unix_convert. -*****************************************************************************/ - -static int global_stat_cache_lookups; -static int global_stat_cache_misses; -static int global_stat_cache_hits; - -/**************************************************************************** - Stat cache statistics code. -*****************************************************************************/ - -void print_stat_cache_statistics(void) -{ - double eff; - - if(global_stat_cache_lookups == 0) - return; - - eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; - - DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ -stat cache was %f%% effective.\n", global_stat_cache_lookups, - global_stat_cache_hits, global_stat_cache_misses, eff )); -} - -typedef struct { - int name_len; - char names[2]; /* This is extended via malloc... */ -} stat_cache_entry; - -#define INIT_STAT_CACHE_SIZE 512 -static hash_table stat_cache; - -/**************************************************************************** - Compare a pathname to a name in the stat cache - of a given length. - Note - this code always checks that the next character in the pathname - is either a '/' character, or a '\0' character - to ensure we only - match *full* pathname components. Note we don't need to handle case - here, if we're case insensitive the stat cache orig names are all upper - case. -*****************************************************************************/ - -#if 0 /* This function unused?? */ -static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len) -{ - BOOL matched = (memcmp( stat_name, orig_name, len) == 0); - if(orig_name[len] != '/' && orig_name[len] != '\0') - return False; - - return matched; -} -#endif - -/**************************************************************************** - Add an entry into the stat cache. -*****************************************************************************/ - -static void stat_cache_add( char *full_orig_name, char *orig_translated_path) -{ - stat_cache_entry *scp; - stat_cache_entry *found_scp; - pstring orig_name; - pstring translated_path; - int namelen; - hash_element *hash_elem; - - if (!lp_stat_cache()) return; - - namelen = strlen(orig_translated_path); - - /* - * Don't cache trivial valid directory entries. - */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) - return; - - /* - * If we are in case insentive mode, we need to - * store names that need no translation - else, it - * would be a waste. - */ - - if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) - return; - - /* - * Remove any trailing '/' characters from the - * translated path. - */ - - pstrcpy(translated_path, orig_translated_path); - if(translated_path[namelen-1] == '/') { - translated_path[namelen-1] = '\0'; - namelen--; - } - - /* - * We will only replace namelen characters - * of full_orig_name. - * StrnCpy always null terminates. - */ - - StrnCpy(orig_name, full_orig_name, namelen); - if(!case_sensitive) - strupper( orig_name ); - - /* - * Check this name doesn't exist in the cache before we - * add it. - */ - - if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { - return; - } else { - hash_remove(&stat_cache, hash_elem); - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - pstrcpy(scp->names, orig_name); - pstrcpy((scp->names+namelen+1), translated_path); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } - return; - } else { - - /* - * New entry. - */ - - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - pstrcpy(scp->names, orig_name); - pstrcpy(scp->names+namelen+1, translated_path); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } - - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); -} - -/**************************************************************************** - Look through the stat cache for an entry - promote it to the top if found. - Return True if we translated (and did a scuccessful stat on) the entire name. -*****************************************************************************/ - -static BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, - char **start, SMB_STRUCT_STAT *pst) -{ - stat_cache_entry *scp; - char *trans_name; - pstring chk_name; - int namelen; - hash_element *hash_elem; - char *sp; - - if (!lp_stat_cache()) - return False; - - namelen = strlen(name); - - *start = name; - global_stat_cache_lookups++; - - /* - * Don't lookup trivial valid directory entries. - */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - global_stat_cache_misses++; - return False; - } - - pstrcpy(chk_name, name); - if(!case_sensitive) - strupper( chk_name ); - - while (1) { - hash_elem = hash_lookup(&stat_cache, chk_name); - if(hash_elem == NULL) { - /* - * Didn't find it - remove last component for next try. - */ - sp = strrchr(chk_name, '/'); - if (sp) { - *sp = '\0'; - } else { - /* - * We reached the end of the name - no match. - */ - global_stat_cache_misses++; - return False; - } - if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) - || (strcmp(chk_name, "..") == 0)) { - global_stat_cache_misses++; - return False; - } - } else { - scp = (stat_cache_entry *)(hash_elem->value); - global_stat_cache_hits++; - trans_name = scp->names+scp->name_len+1; - if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { - /* Discard this entry - it doesn't exist in the filesystem. */ - hash_remove(&stat_cache, hash_elem); - return False; - } - memcpy(name, trans_name, scp->name_len); - *start = &name[scp->name_len]; - if(**start == '/') - ++*start; - StrnCpy( dirpath, trans_name, name - (*start)); - return (namelen == scp->name_len); - } - } -} /**************************************************************************** This routine is called to convert names from the dos namespace to unix @@ -406,26 +184,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) strnorm(name); - /* - * Check if it's a printer file. - */ - if (conn->printer) { - if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) { - char *s; - fstring name2; - slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine); - - /* - * Sanitise the name. - */ - - for (s=name2 ; *s ; s++) - if (!issafe(*s)) *s = '_'; - pstrcpy(name,(char *)smbd_mktemp(name2)); - } - return(True); - } - /* * If we trimmed down to a single '\0' character * then we will be using the "." directory. @@ -471,8 +229,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, !lp_strip_dot() && !use_mangled_map) return(False); - if(strchr(start,'?') || strchr(start,'*')) - name_has_wildcard = True; + name_has_wildcard = ms_has_wild(start); /* * is_mangled() was changed to look at an entire pathname, not @@ -549,7 +306,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Try to find this part of the path in the directory. */ - if (strchr(start,'?') || strchr(start,'*') || + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { /* @@ -752,15 +509,3 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d return(False); } -/*************************************************************************** ** - * Initializes or clears the stat cache. - * - * Input: none. - * Output: none. - * - * ************************************************************************** ** - */ -BOOL reset_stat_cache( void ) -{ - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); -} /* reset_stat_cache */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 41c6dcb143..990a9aecb2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1331,9 +1331,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } } - /* Convert the formatted mask. (This code lives in trans2.c) */ - mask_convert(mask); - { int skip; p = mask; @@ -1936,7 +1933,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!rc && is_mangled(mask)) check_mangled_cache( mask ); - has_wild = strchr(mask,'*') || strchr(mask,'?'); + has_wild = ms_has_wild(mask); if (!has_wild) { pstrcat(directory,"/"); @@ -1969,7 +1966,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) continue; + if(!mask_match(fname, mask, case_sensitive)) continue; error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); @@ -3508,7 +3505,7 @@ int rename_internals(connection_struct *conn, if (!rc && is_mangled(mask)) check_mangled_cache( mask ); - has_wild = strchr(mask,'*') || strchr(mask,'?'); + has_wild = ms_has_wild(mask); if (!has_wild) { /* @@ -3618,7 +3615,7 @@ int rename_internals(connection_struct *conn, pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) + if(!mask_match(fname, mask, case_sensitive)) continue; error = ERRnoaccess; @@ -3847,7 +3844,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!rc && is_mangled(mask)) check_mangled_cache( mask ); - has_wild = strchr(mask,'*') || strchr(mask,'?'); + has_wild = ms_has_wild(mask); if (!has_wild) { pstrcat(directory,"/"); @@ -3878,7 +3875,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) + if(!mask_match(fname, mask, case_sensitive)) continue; error = ERRnoaccess; diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c new file mode 100644 index 0000000000..ae5dbb1ef7 --- /dev/null +++ b/source3/smbd/statcache.c @@ -0,0 +1,243 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + stat cache code + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Jeremy Allison 1999-200 + + + 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 BOOL case_sensitive; + + +/**************************************************************************** + Stat cache code used in unix_convert. +*****************************************************************************/ + +static int global_stat_cache_lookups; +static int global_stat_cache_misses; +static int global_stat_cache_hits; + +/**************************************************************************** + Stat cache statistics code. +*****************************************************************************/ + +void print_stat_cache_statistics(void) +{ + double eff; + + if(global_stat_cache_lookups == 0) + return; + + eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; + + DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ +stat cache was %f%% effective.\n", global_stat_cache_lookups, + global_stat_cache_hits, global_stat_cache_misses, eff )); +} + +typedef struct { + int name_len; + char names[2]; /* This is extended via malloc... */ +} stat_cache_entry; + +#define INIT_STAT_CACHE_SIZE 512 +static hash_table stat_cache; + +/**************************************************************************** + Add an entry into the stat cache. +*****************************************************************************/ + +void stat_cache_add( char *full_orig_name, char *orig_translated_path) +{ + stat_cache_entry *scp; + stat_cache_entry *found_scp; + pstring orig_name; + pstring translated_path; + int namelen; + hash_element *hash_elem; + + if (!lp_stat_cache()) return; + + namelen = strlen(orig_translated_path); + + /* + * Don't cache trivial valid directory entries. + */ + if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || + (strcmp(full_orig_name, "..") == 0)) + return; + + /* + * If we are in case insentive mode, we need to + * store names that need no translation - else, it + * would be a waste. + */ + + if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + return; + + /* + * Remove any trailing '/' characters from the + * translated path. + */ + + pstrcpy(translated_path, orig_translated_path); + if(translated_path[namelen-1] == '/') { + translated_path[namelen-1] = '\0'; + namelen--; + } + + /* + * We will only replace namelen characters + * of full_orig_name. + * StrnCpy always null terminates. + */ + + StrnCpy(orig_name, full_orig_name, namelen); + if(!case_sensitive) + strupper( orig_name ); + + /* + * Check this name doesn't exist in the cache before we + * add it. + */ + + if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { + return; + } else { + hash_remove(&stat_cache, hash_elem); + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy((scp->names+namelen+1), translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); + } + return; + } else { + + /* + * New entry. + */ + + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy(scp->names+namelen+1, translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); + } + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); +} + +/**************************************************************************** + Look through the stat cache for an entry - promote it to the top if found. + Return True if we translated (and did a scuccessful stat on) the entire name. +*****************************************************************************/ + +BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, + char **start, SMB_STRUCT_STAT *pst) +{ + stat_cache_entry *scp; + char *trans_name; + pstring chk_name; + int namelen; + hash_element *hash_elem; + char *sp; + + if (!lp_stat_cache()) + return False; + + namelen = strlen(name); + + *start = name; + global_stat_cache_lookups++; + + /* + * Don't lookup trivial valid directory entries. + */ + if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { + global_stat_cache_misses++; + return False; + } + + pstrcpy(chk_name, name); + if(!case_sensitive) + strupper( chk_name ); + + while (1) { + hash_elem = hash_lookup(&stat_cache, chk_name); + if(hash_elem == NULL) { + /* + * Didn't find it - remove last component for next try. + */ + sp = strrchr(chk_name, '/'); + if (sp) { + *sp = '\0'; + } else { + /* + * We reached the end of the name - no match. + */ + global_stat_cache_misses++; + return False; + } + if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) + || (strcmp(chk_name, "..") == 0)) { + global_stat_cache_misses++; + return False; + } + } else { + scp = (stat_cache_entry *)(hash_elem->value); + global_stat_cache_hits++; + trans_name = scp->names+scp->name_len+1; + if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + hash_remove(&stat_cache, hash_elem); + return False; + } + memcpy(name, trans_name, scp->name_len); + *start = &name[scp->name_len]; + if(**start == '/') + ++*start; + StrnCpy( dirpath, trans_name, name - (*start)); + return (namelen == scp->name_len); + } + } +} + +/*************************************************************************** ** + * Initializes or clears the stat cache. + * + * Input: none. + * Output: none. + * + * ************************************************************************** ** + */ +BOOL reset_stat_cache( void ) +{ + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); +} /* reset_stat_cache */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4e502f767b..7ae24f9e38 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -287,6 +287,19 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return -1; } +/********************************************************* +* Routine to check if a given string matches exactly. +* as a special case a mask of "." does NOT match. That +* is required for correct wildcard semantics +* Case can be significant or not. +**********************************************************/ +static BOOL exact_match(char *str,char *mask, BOOL case_sig) +{ + if (mask[0] == '.' && mask[1] == 0) return False; + if (case_sig) return strcmp(str,mask)==0; + return strcasecmp(str,mask) == 0; +} + /**************************************************************************** get a level dependent lanman2 dir entry. ****************************************************************************/ @@ -360,7 +373,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(fname,dname); if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) - got_match = mask_match(fname, mask, case_sensitive, True); + got_match = mask_match(fname, mask, case_sensitive); if(!got_match && !is_8_3(fname, False)) { @@ -375,7 +388,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy( newname, fname); name_map_mangle( newname, True, False, SNUM(conn)); if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive))) - got_match = mask_match(newname, mask, case_sensitive, True); + got_match = mask_match(newname, mask, case_sensitive); } if(got_match) @@ -509,13 +522,20 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { - pstrcpy(p+2,fname); - if (!name_map_mangle(p+2,True,True,SNUM(conn))) - (p+2)[12] = 0; - } else - *(p+2) = 0; - strupper(p+2); - SSVAL(p,0,strlen(p+2)); + /* NT4 always uses unicode here */ + fstring short_name, ushort_name; + int slen; + pstrcpy(short_name,fname); + name_map_mangle(short_name,True,True,SNUM(conn)); + strupper(short_name); + slen = strlen(short_name); + ascii_to_unistr(ushort_name, short_name, 24); + memcpy(p+2, ushort_name, 2*slen); + SSVAL(p, 0, 2*slen); + } else { + SSVAL(p,0,0); + *(p+2) = 0; + } p += 2 + 24; /* nameptr = p; */ pstrcpy(p,fname); p += strlen(p); @@ -591,32 +611,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, return(found); } -/**************************************************************************** - Convert the directory masks formated for the wire. -****************************************************************************/ - -void mask_convert( char *mask) -{ - /* - * We know mask is a pstring. - */ - char *p = mask; - while (*p) { - if (*p == '<') { - pstring expnd; - if(p[1] != '"' && p[1] != '.') { - pstrcpy( expnd, p+1 ); - *p++ = '*'; - *p = '.'; - safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2); - } else - *p = '*'; - } - if (*p == '>') *p = '?'; - if (*p == '"') *p = '.'; - p++; - } -} /**************************************************************************** Reply to a TRANS2_FINDFIRST. @@ -727,9 +721,6 @@ static int call_trans2findfirst(connection_struct *conn, if (dptr_num < 0) return(UNIXERROR(ERRDOS,ERRbadfile)); - /* Convert the formatted mask. */ - mask_convert(mask); - /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ -- cgit From 34cd425c1ded2afe5adc4d898843c31f66f26b5a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 14:29:45 +0000 Subject: fixed our smbsearch code. We now store the mask with the dptr, this turns out to be essential for a correct implementation (there ins't enough room to store all possible masks in the status return structure!) (This used to be commit 38f5e133670ada6e5799a16cf1a0e2e3ee1d9afd) --- source3/smbd/dir.c | 21 +++++++++++---------- source3/smbd/reply.c | 30 ++++++++---------------------- 2 files changed, 19 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index bd4e2a44f9..ee383ea72a 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -591,7 +591,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, while (!found) { - BOOL filename_is_mask = False; dname = ReadDirName(conn->dirptr); DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n", @@ -602,13 +601,22 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, pstrcpy(filename,dname); - if ((filename_is_mask = (strcmp(filename,mask) == 0)) || + /* notice the special *.* handling. This appears to be the only difference + between the wildcard handling in this routine and in the trans2 routines. + see masktest for a demo + */ + if ((strcmp(mask,"*.*") == 0) || + mask_match(filename,mask,False) || (name_map_mangle(filename,True,False,SNUM(conn)) && mask_match(filename,mask,False))) { if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) continue; + if (!is_8_3(filename, False)) { + name_map_mangle(filename,True,False,SNUM(conn)); + } + pstrcpy(fname,filename); *path = 0; pstrcpy(path,conn->dirpath); @@ -631,17 +639,10 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, continue; } - if (!filename_is_mask) - { - /* Now we can allow the mangled cache to be updated */ - pstrcpy(filename,dname); - name_map_mangle(filename,True,True,SNUM(conn)); - } - *size = sbuf.st_size; *date = sbuf.st_mtime; - DEBUG(5,("get_dir_entry found %s fname=%s\n",pathreal,fname)); + DEBUG(0,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); found = True; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 990a9aecb2..939696dd89 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1265,9 +1265,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size /* dirtype &= ~aDIR; */ - DEBUG(5,("reply_search: path=%s status_len=%d\n",path,status_len)); - - if (status_len == 0) { pstring dir2; @@ -1306,15 +1303,12 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size else { memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); - memcpy(mask,status+1,11); - mask[11] = 0; dirtype = CVAL(status,0) & 0x1F; conn->dirptr = dptr_fetch(status+12,&dptr_num); if (!conn->dirptr) goto SearchEmpty; string_set(&conn->dirpath,dptr_path(dptr_num)); - if (!case_sensitive) - strnorm(mask); + fstrcpy(mask, dptr_wcard(dptr_num)); } /* turn strings of spaces into a . */ @@ -1326,8 +1320,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size fstrcpy(ext,p+1); *p = 0; trim_string(mask,NULL," "); - pstrcat(mask,"."); - pstrcat(mask,ext); + if (ext[0]) { + pstrcat(mask,"."); + pstrcat(mask,ext); + } } } @@ -1352,17 +1348,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } } - if (!strchr(mask,'.') && strlen(mask)>8) - { - fstring tmp; - fstrcpy(tmp,&mask[8]); - mask[8] = '.'; - mask[9] = 0; - pstrcat(mask,tmp); - } - - DEBUG(5,("mask=%s directory=%s\n",mask,directory)); - if (can_open) { p = smb_buf(outbuf) + 3; @@ -1385,6 +1370,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } return(ERROR(ERRDOS,ERRnofids)); } + dptr_set_wcard(dptr_num, mask); } DEBUG(4,("dptr_num is %d\n",dptr_num)); @@ -1419,8 +1405,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size make_dir_struct(p,mask,fname,size,mode,date); dptr_fill(p+12,dptr_num); numentries++; - } - p += DIR_STRUCT_SIZE; + } + p += DIR_STRUCT_SIZE; } } } /* if (ok ) */ -- cgit From 0f35ded18e399b2a5dfcb36d5b83368c1072fd5a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 14:30:47 +0000 Subject: go back to ascii in SMB_FIND_FILE_BOTH_DIRECTORY_INFO NT gives out unicode, but NT clients can't handle a unicode response! (This used to be commit 85d634974f4f8841bf68cd2b22d134fbc010b568) --- source3/smbd/trans2.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7ae24f9e38..458d6f3ec0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -522,16 +522,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { - /* NT4 always uses unicode here */ - fstring short_name, ushort_name; - int slen; - pstrcpy(short_name,fname); - name_map_mangle(short_name,True,True,SNUM(conn)); - strupper(short_name); - slen = strlen(short_name); - ascii_to_unistr(ushort_name, short_name, 24); - memcpy(p+2, ushort_name, 2*slen); - SSVAL(p, 0, 2*slen); + fstrcpy(p+2,fname); + name_map_mangle(p+2,True,True,SNUM(conn)); + strupper(p+2); + SSVAL(p, 0, strlen(p+2)); } else { SSVAL(p,0,0); *(p+2) = 0; -- cgit From cb6327cd2d221ab0248a802d8717ea669463845e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 14:34:31 +0000 Subject: removed more cruft from our old wildcard matching code (This used to be commit 4a15924ffe36ed37ec193a0ef5a0487238edc311) --- source3/smbd/reply.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 939696dd89..b152ca59ee 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1311,43 +1311,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size fstrcpy(mask, dptr_wcard(dptr_num)); } - /* turn strings of spaces into a . */ - { - trim_string(mask,NULL," "); - if ((p = strrchr(mask,' '))) - { - fstring ext; - fstrcpy(ext,p+1); - *p = 0; - trim_string(mask,NULL," "); - if (ext[0]) { - pstrcat(mask,"."); - pstrcat(mask,ext); - } - } - } - - { - int skip; - p = mask; - while(*p) - { - if((skip = get_character_len( *p )) != 0 ) - { - p += skip; - } - else - { - if (*p != '?' && *p != '*' && !isdoschar(*p)) - { - DEBUG(5,("Invalid char [%c] in search mask?\n",*p)); - *p = '?'; - } - p++; - } - } - } - if (can_open) { p = smb_buf(outbuf) + 3; -- cgit From 29ba16f7925bddb96e2a51cc87e6e509608f8ce7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 14:59:00 +0000 Subject: fixed dptr_wcard handling (need to use strdup) (This used to be commit 0bab0300748a22b4b861fa443be2014bcd7b348c) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b152ca59ee..ead59ebfc2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1333,7 +1333,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } return(ERROR(ERRDOS,ERRnofids)); } - dptr_set_wcard(dptr_num, mask); + dptr_set_wcard(dptr_num, strdup(mask)); } DEBUG(4,("dptr_num is %d\n",dptr_num)); -- cgit From 05cb3464f972d336dcb82ca332bf9b2617646070 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 15:13:15 +0000 Subject: - added some error checking - removed the VTP hook in smbd (This used to be commit 09355fcd50e6c9c0c81e5f70ab9b7ff88aa897bf) --- source3/smbd/process.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f378550282..b81e831133 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -631,14 +631,6 @@ void process_smb(char *inbuf, char *outbuf) } #endif /* WITH_SSL */ -#ifdef WITH_VTP - if(trans_num == 1 && VT_Check(inbuf)) - { - VT_Process(); - return; - } -#endif - if (msg_type == 0) show_msg(inbuf); else if(msg_type == 0x85) -- cgit From 693ffb8466ada58ecc59fde754ba79fc6f51528d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 May 2000 02:23:41 +0000 Subject: Added sys_fork() and sys_getpid() functions to stop the overhead of doing a system call every time we want to just get our pid. Jeremy. (This used to be commit 148628b616b5c29ba6340d65fc3ddbcabba6e67a) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/connection.c | 6 +++--- source3/smbd/fileio.c | 2 +- source3/smbd/files.c | 2 +- source3/smbd/negprot.c | 6 +++--- source3/smbd/open.c | 4 ++-- source3/smbd/oplock.c | 6 +++--- source3/smbd/password.c | 4 ++-- source3/smbd/process.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/service.c | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 484523bd27..708b52f4bc 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -330,7 +330,7 @@ static BOOL chat_with_program(char *passwordprogram, char *name, CatchChildLeaveStatus(); - if ((pid = fork()) < 0) + if ((pid = sys_fork()) < 0) { DEBUG(3, ("Cannot fork() child for password change: %s\n", diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 9c859e4d89..aa49f8cf7c 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -45,7 +45,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) DEBUG(3,("Yielding connection to %s\n",name)); ZERO_STRUCT(key); - key.pid = getpid(); + key.pid = sys_getpid(); if (conn) key.cnum = conn->cnum; fstrcpy(key.name, name); @@ -84,7 +84,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO DEBUG(5,("claiming %s %d\n",name,max_connections)); ZERO_STRUCT(key); - key.pid = getpid(); + key.pid = sys_getpid(); key.cnum = conn?conn->cnum:-1; fstrcpy(key.name, name); @@ -94,7 +94,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO /* fill in the crec */ ZERO_STRUCT(crec); crec.magic = 0x280267; - crec.pid = getpid(); + crec.pid = sys_getpid(); crec.cnum = conn?conn->cnum:-1; if (conn) { crec.uid = conn->uid; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 8f8f17563e..2d83378b3d 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -205,7 +205,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { share_mode_entry *share_list = NULL; - pid_t pid = getpid(); + pid_t pid = sys_getpid(); int token = -1; int num_share_modes = 0; int i; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e644f52669..5b930f9940 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -55,7 +55,7 @@ files_struct *file_new(void ) increases the chance that the errant client will get an error rather than causing corruption */ if (first_file == 0) { - first_file = (getpid() ^ (int)time(NULL)) % real_max_open_files; + first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; } i = bitmap_find(file_bmap, first_file); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index adef4a57f3..e8302a43e6 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -87,7 +87,7 @@ static int reply_lanman1(char *outbuf) SSVAL(outbuf,smb_vwv4,1); SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support readbraw writebraw (possibly) */ - SIVAL(outbuf,smb_vwv6,getpid()); + SIVAL(outbuf,smb_vwv6,sys_getpid()); SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); put_dos_date(outbuf,smb_vwv8,t); @@ -133,7 +133,7 @@ static int reply_lanman2(char *outbuf) set_message(outbuf,13,crypt_len,True); SSVAL(outbuf,smb_vwv1,secword); - SIVAL(outbuf,smb_vwv6,getpid()); + SIVAL(outbuf,smb_vwv6,sys_getpid()); if (doencrypt) memcpy(smb_buf(outbuf), cryptkey, 8); @@ -226,7 +226,7 @@ static int reply_nt1(char *outbuf) SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ - SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ + SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */ SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ put_long_date(outbuf+smb_vwv11+1,t); SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9aadb39bc9..0c6927ba2a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -342,7 +342,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == getpid()),is_executable(fname)); + (share->pid == sys_getpid()),is_executable(fname)); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || @@ -946,7 +946,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) share_mode_entry *old_shares = 0; int num_share_modes; SMB_STRUCT_STAT sbuf; - pid_t pid = getpid(); + pid_t pid = sys_getpid(); SMB_DEV_T dev; SMB_INO_T inode; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 28ab29d027..4a363d45e9 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -111,7 +111,7 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); return False; DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", - (int)getpid(), global_oplock_port)); + (int)sys_getpid(), global_oplock_port)); return True; } @@ -1088,7 +1088,7 @@ BOOL request_oplock_break(share_mode_entry *share_entry, { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; - pid_t pid = getpid(); + pid_t pid = sys_getpid(); time_t start_time; int time_left; long usec; @@ -1342,7 +1342,7 @@ void check_kernel_oplocks(void) set_process_capability(KERNEL_OPLOCK_CAPABILITY,True); set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,True); - slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)getpid()); + slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid()); if(pipe(pfd) != 0) { DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f92d31718c..a8b9050030 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -53,8 +53,8 @@ void generate_next_challenge(char *challenge) /* get a sort-of random number */ GetTimeOfDay(&tval); - v1 = (counter++) + getpid() + tval.tv_sec; - v2 = (counter++) * getpid() + tval.tv_usec; + v1 = (counter++) + sys_getpid() + tval.tv_sec; + v2 = (counter++) * sys_getpid() + tval.tv_usec; SIVAL(challenge,0,v1); SIVAL(challenge,4,v2); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b81e831133..1eb5899667 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -421,7 +421,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize extern int global_smbpid; if (pid == (pid_t)-1) - pid = getpid(); + pid = sys_getpid(); errno = 0; last_message = type; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8e4de78cbf..574be64553 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -238,7 +238,7 @@ max can be %d\n", continue; } - if (smbd_server_fd() != -1 && fork()==0) { + if (smbd_server_fd() != -1 && sys_fork()==0) { /* Child code ... */ /* close the listening socket(s) */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8e04f7e989..ebc4c9a790 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -608,7 +608,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); dbgtext( "as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); - dbgtext( "(pid %d)\n", (int)getpid() ); + dbgtext( "(pid %d)\n", (int)sys_getpid() ); } /* we've finished with the sensitive stuff */ -- cgit From ba020b0612ee975df15ceaf2eabf0cc3f208dc3e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 May 2000 03:20:47 +0000 Subject: Moved uglyness needed in fcntl locking (64->32 bit mapping, NFS errors etc.) into locking/posix.c, where it is needed. fcntl_lock in lib/util.c is now very small and clean. Added (*lock) op to vfs layer. Jeremy. (This used to be commit 46092ee1410faa4e3c143d80a960a8adaa19d7fc) --- source3/smbd/vfs-wrap.c | 5 +++++ source3/smbd/vfs.c | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index a3dd752023..5db1689450 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -305,3 +305,8 @@ int vfswrap_ftruncate(int fd, SMB_OFF_T offset) result = sys_ftruncate(fd, offset); return result; } + +BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +{ + return fcntl_lock(fd, op, offset, count,type); +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index d76d64684b..895d84d51c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -65,7 +65,8 @@ struct vfs_ops default_vfs_ops = { vfswrap_unlink, vfswrap_chmod, vfswrap_utime, - vfswrap_ftruncate + vfswrap_ftruncate, + vfswrap_lock }; /**************************************************************************** @@ -210,7 +211,11 @@ BOOL vfs_init_custom(connection_struct *conn) } if (conn->vfs_ops.ftruncate == NULL) { - conn->vfs_ops.ftruncate= default_vfs_ops.ftruncate; + conn->vfs_ops.ftruncate = default_vfs_ops.ftruncate; + } + + if (conn->vfs_ops.lock == NULL) { + conn->vfs_ops.lock = default_vfs_ops.lock; } return True; -- cgit From c39e2e6f9a9fb3ac2e21ef31eaad6d280cfc3d9e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 May 2000 07:10:54 +0000 Subject: fixed a memory leak (calling hash_table_init twice) (This used to be commit 610fcef4d33db2b62e6298bdb68546a2411d03b1) --- source3/smbd/statcache.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index ae5dbb1ef7..e0ceddff1d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -239,5 +239,11 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, */ BOOL reset_stat_cache( void ) { - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + static BOOL initialised; + if (!initialised) { + initialised = True; + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + } + hash_clear(&stat_cache); + return True; } /* reset_stat_cache */ -- cgit From 32d5416b6a777a7874fec8518ec44e750560d882 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 May 2000 13:55:42 +0000 Subject: split the username in the vuser structure into a separate userdom_struct. As the name implies this also contains a domain (unused at the moment). This will be important shortly, as operation in appliance mode needs the domain to be always carried with the username. (This used to be commit ee8546342d5be90e730372b985710d764564b124) --- source3/smbd/lanman.c | 7 ++++--- source3/smbd/password.c | 24 ++++++++++++------------ source3/smbd/process.c | 2 +- source3/smbd/uid.c | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 9774305fc9..2ec08ddbf9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2285,7 +2285,8 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); if(vuser != NULL) - DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name)); + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, + vuser->user.unix_name)); *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); @@ -2335,7 +2336,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); + pstrcpy(p2,((vuser != NULL) ? vuser->user.real_name : UserName)); p2 = skip_string(p2,1); } @@ -2394,7 +2395,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); + pstrcpy(p2,((vuser != NULL) ? vuser->user.real_name : UserName)); p2 = skip_string(p2,1); SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a8b9050030..cff47c0a94 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -140,7 +140,7 @@ char *validated_username(uint16 vuid) user_struct *vuser = get_valid_user_struct(vuid); if (vuser == NULL) return 0; - return(vuser->name); + return(vuser->user.unix_name); } @@ -246,8 +246,8 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, vuser->uid = uid; vuser->gid = gid; vuser->guest = guest; - fstrcpy(vuser->name,unix_name); - fstrcpy(vuser->requested_name,requested_name); + fstrcpy(vuser->user.unix_name,unix_name); + fstrcpy(vuser->user.smb_name,requested_name); vuser->n_groups = 0; vuser->groups = NULL; @@ -261,12 +261,12 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); - fstrcpy(vuser->real_name, "\0"); + fstrcpy(vuser->user.real_name, ""); if (lp_unix_realname()) { - if ((pwfile=sys_getpwnam(vuser->name))!= NULL) + if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); - fstrcpy(vuser->real_name, pwfile->pw_gecos); + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); + fstrcpy(vuser->user.real_name, pwfile->pw_gecos); } } @@ -707,9 +707,9 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { - if (user_ok(vuser->name,snum) && - password_ok(vuser->name, password, pwlen, NULL)) { - fstrcpy(user, vuser->name); + if (user_ok(vuser->user.unix_name,snum) && + password_ok(vuser->user.unix_name, password, pwlen, NULL)) { + fstrcpy(user, vuser->user.unix_name); vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); ok = True; @@ -744,8 +744,8 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check for a previously validated username/password pair */ if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) && (vuser != 0) && !vuser->guest && - user_ok(vuser->name,snum)) { - fstrcpy(user,vuser->name); + user_ok(vuser->user.unix_name,snum)) { + fstrcpy(user,vuser->user.unix_name); *guest = False; DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); ok = True; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1eb5899667..6482ccd538 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -495,7 +495,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if(session_tag != UID_FIELD_INVALID) vuser = get_valid_user_struct(session_tag); if(vuser != NULL) - pstrcpy( sesssetup_user, vuser->requested_name); + pstrcpy( sesssetup_user, vuser->user.smb_name); } /* does this protocol need to be run as root? */ diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index ce0631e418..28d2fb71f6 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -140,7 +140,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) for (i=0;iuid_cache.entries;i++) if (conn->uid_cache.list[i] == vuser->uid) return(True); - if (!user_ok(vuser->name,snum)) return(False); + if (!user_ok(vuser->user.unix_name,snum)) return(False); i = conn->uid_cache.entries % UID_CACHE_SIZE; conn->uid_cache.list[i] = vuser->uid; -- cgit From 99352a098656ac9d3886d047ff273a6880990d2f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2000 02:24:01 +0000 Subject: Insure uninitialized memory read fixes. Jeremy. (This used to be commit 577ddbfbec857dec3ade811f735ec6b183566435) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index cff47c0a94..989d3f045d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -270,6 +270,8 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, } } + memset(&vuser->dc, '\0', sizeof(vuser->dc)); + return (uint16)((num_validated_users - 1) + VUID_OFFSET); } -- cgit From 6ed606cab4e9fc4c954576ffe1d0d781d3e21929 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 May 2000 06:28:38 +0000 Subject: if the stat cache is off then don't initialise it (This used to be commit cd5dcd9e659a7255f03eb496c0202986375e73a6) --- source3/smbd/statcache.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index e0ceddff1d..7b8701337f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -240,6 +240,8 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, BOOL reset_stat_cache( void ) { static BOOL initialised; + if (!lp_stat_cache()) return True; + if (!initialised) { initialised = True; return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); -- cgit From f3a861e04e33901c89408a9c89ebaa81fc606f97 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 May 2000 07:59:34 +0000 Subject: - use full_name instead of real_name - got rid of guest map code in lpq parser (This used to be commit 8e53f781d3cf6a7007764916a0d8e8f1abea1f66) --- source3/smbd/lanman.c | 4 ++-- source3/smbd/password.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 2ec08ddbf9..b986df6d07 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2336,7 +2336,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - pstrcpy(p2,((vuser != NULL) ? vuser->user.real_name : UserName)); + pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); p2 = skip_string(p2,1); } @@ -2395,7 +2395,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - pstrcpy(p2,((vuser != NULL) ? vuser->user.real_name : UserName)); + pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); p2 = skip_string(p2,1); SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 989d3f045d..a727d2feb3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -261,12 +261,12 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); - fstrcpy(vuser->user.real_name, ""); + fstrcpy(vuser->user.full_name, ""); if (lp_unix_realname()) { if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); - fstrcpy(vuser->user.real_name, pwfile->pw_gecos); + fstrcpy(vuser->user.full_name, pwfile->pw_gecos); } } -- cgit From f6844e0b7eb4412bc44c5533b09f856dc9272e75 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 May 2000 16:01:47 +0000 Subject: a minimal change to get appliance mode to work with winbindd we needed to accept usernames of the form DOMAIN/user, which means we needed to pass the domain to a getpwnam() like routine in certain critical spots. What I'd rather do is get rid of "char *user" everywhere and use the new userdom_struct, but that will have to wait a few days. (This used to be commit 8b7a10febead8be182e7d5b1d68259e31530b69c) --- source3/smbd/password.c | 30 ++++++++++++++++++++++-------- source3/smbd/reply.c | 6 +++--- source3/smbd/service.c | 4 ++-- 3 files changed, 27 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a727d2feb3..782d04631a 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -137,23 +137,35 @@ return a validated username ****************************************************************************/ char *validated_username(uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); - if (vuser == NULL) - return 0; - return(vuser->user.unix_name); + user_struct *vuser = get_valid_user_struct(vuid); + if (vuser == NULL) + return 0; + return(vuser->user.unix_name); +} + +/**************************************************************************** +return a validated domain +****************************************************************************/ +char *validated_domain(uint16 vuid) +{ + user_struct *vuser = get_valid_user_struct(vuid); + if (vuser == NULL) + return 0; + return(vuser->user.domain); } /**************************************************************************** Setup the groups a user belongs to. ****************************************************************************/ -int setup_groups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups) +int setup_groups(char *user, char *domain, + 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 (-1 == smb_initgroups(user,domain,gid)) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); if (getuid() == 0) @@ -199,7 +211,8 @@ register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest) +uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, + char *domain,BOOL guest) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -248,13 +261,14 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, vuser->guest = guest; fstrcpy(vuser->user.unix_name,unix_name); fstrcpy(vuser->user.smb_name,requested_name); + fstrcpy(vuser->user.domain,domain); vuser->n_groups = 0; vuser->groups = NULL; /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(unix_name,uid,gid, + setup_groups(unix_name,domain,uid,gid, &vuser->n_groups, &vuser->groups); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ead59ebfc2..90d4200f5e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -944,7 +944,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } } - if (!Get_Pwnam(user,True)) { + if (!smb_getpwnam(user,domain,True)) { DEBUG(3,("No such user %s - using guest account\n",user)); pstrcpy(user,lp_guestaccount(-1)); guest = True; @@ -979,7 +979,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int user we should become. */ { - const struct passwd *pw = Get_Pwnam(user,False); + const struct passwd *pw = smb_getpwnam(user,domain,False); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); return bad_password_error(inbuf,outbuf); @@ -993,7 +993,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ebc4c9a790..0701b854b7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -293,7 +293,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int } /* find out some info about the user */ - pass = Get_Pwnam(user,True); + pass = smb_getpwnam(user,validated_domain(vuid),True); if (pass == NULL) { DEBUG(0,( "Couldn't find account %s\n",user)); @@ -504,7 +504,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!IS_IPC(conn)) { /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(conn->user,conn->uid,conn->gid, + setup_groups(conn->user,validated_domain(vuid),conn->uid,conn->gid, &conn->ngroups,&conn->groups); /* check number of connections */ -- cgit From 045469493c2870cb1d63c964b18afc5e2210dcd5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 May 2000 21:57:28 +0000 Subject: rpc_server/srv_lsa.c: Bring into sync with 2.0.x. rpc_server/srv_pipe_hnd.c: Bring into sync with 2.0.x. smbd/blocking.c: Improve blocking debug reporting. utils/torture.c: Added check for NT locking bug. Jeremy. (This used to be commit e8ff6d3fb5537c39611a5784bf7216ae812acd27) --- source3/smbd/blocking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ddf7de3f5b..e8dc29f80a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -117,8 +117,8 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int ubi_slAddTail(&blocking_lock_queue, blr); - DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d \ -for fnum = %d, name = %s\n", length, (int)blr->expire_time, + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ +for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); return True; -- cgit From a12b2cd9e806fefeabdbe73b46b569f5b9bc927f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 May 2000 02:39:02 +0000 Subject: Fix for read_file() returning -1. Jeremy. (This used to be commit b899943658bee90994b416aa6caff0ee7cab5f28) --- source3/smbd/fileio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 2d83378b3d..6507f56606 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -116,6 +116,8 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) if (n > 0) { readret = fsp->conn->vfs_ops.read(fsp->fd,data,n); + if (readret == -1) + return -1; if (readret > 0) ret += readret; } -- cgit From 652d98c0bc22b761de72d0ce9c5a5f96412453fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 May 2000 19:57:02 +0000 Subject: Fix for dual unix_to_dos conversion in readdir from A.V.Shutko Jeremy. (This used to be commit 1152f2ed008dbfa7e2b1cb9719d31575e7d05b89) --- source3/smbd/vfs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 895d84d51c..9a1af18b3d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -395,7 +395,6 @@ char *vfs_readdirname(connection_struct *conn, void *p) dname = buf; } - unix_to_dos(dname, True); return(dname); } -- cgit From 2684f508493ca2563b736216af0801b9532d225e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 6 May 2000 15:00:49 +0000 Subject: fixed a vfs crash bug (This used to be commit 76da586396c85b6614579b9234eec34f57c12ffe) --- source3/smbd/conn.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 1dc4ac9e7d..f43a30d320 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -164,15 +164,13 @@ free a conn structure ****************************************************************************/ void conn_free(connection_struct *conn) { - /* Close dlopen() handle */ - - if (conn->vfs_conn->dl_handle != NULL) { - dlclose(conn->vfs_conn->dl_handle); /* should we check return val? */ - } - /* Free vfs_connection_struct */ if (conn->vfs_conn != NULL) { + /* Close dlopen() handle */ + if (conn->vfs_conn->dl_handle) { + dlclose(conn->vfs_conn->dl_handle); + } if (conn->vfs_conn->groups != NULL) { free(conn->vfs_conn->groups); } -- cgit From 2958dfcdf87d5169fe1152806be6ad03acb04d88 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 8 May 2000 10:42:21 +0000 Subject: added secrets.tdb and changed storage of trust account password to use it (This used to be commit 88ad00b82acc4636ab57dfe710af08ea85b82ff1) --- source3/smbd/password.c | 2 +- source3/smbd/process.c | 11 +---------- source3/smbd/reply.c | 9 +-------- source3/smbd/server.c | 2 ++ 4 files changed, 5 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 782d04631a..0478e205d1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1435,7 +1435,7 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password. */ - if (!trust_get_passwd( trust_passwd, global_myworkgroup, global_myname)) + if (!get_trust_account_password(domain, trust_passwd, NULL)) { return False; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6482ccd538..805bbe4415 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -920,16 +920,9 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t * First, open the machine password file with an exclusive lock. */ - if(!trust_password_lock( global_myworkgroup, global_myname, True)) { - DEBUG(0,("process: unable to open the machine account password file for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - return True; - } - - if(!get_trust_account_password( trust_passwd_hash, &lct)) { + if(!get_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) { DEBUG(0,("process: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname, global_myworkgroup )); - trust_password_unlock(); return True; } @@ -938,7 +931,6 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); */ if(t < lct + lp_machine_password_timeout()) { - trust_password_unlock(); global_machine_password_needs_changing = False; return True; } @@ -946,7 +938,6 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); pstrcpy(remote_machine_list, lp_passwordserver()); change_trust_account_password( global_myworkgroup, remote_machine_list); - trust_password_unlock(); global_machine_password_needs_changing = False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 90d4200f5e..7a818971d9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -838,14 +838,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int strlower(user); - /* - * In share level security, only overwrite sesssetup_use if - * it's a non null-session share. Helps keep %U and %G - * working. - */ - - if((lp_security() != SEC_SHARE) || (*user && !guest)) - pstrcpy(sesssetup_user,user); + pstrcpy(sesssetup_user,user); reload_services(True); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 574be64553..d2ccd75059 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -498,6 +498,8 @@ static void init_structs(void ) init_printer_hnd(); init_dptrs(); + + secrets_init(); } /**************************************************************************** -- cgit From 4c061ca15cd1e9b0e2ce32218727c4040757c98d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 9 May 2000 15:09:52 +0000 Subject: - use smb_gwtpwnam() in another couple of places - don't call add/del user if the scripts are empty (This used to be commit 43860215d4d16cb1bacdc77f1c46c54e4c54abd7) --- source3/smbd/password.c | 2 +- source3/smbd/reply.c | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0478e205d1..70663f0909 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -491,7 +491,7 @@ BOOL pass_check_smb(char *user, char *domain, } else { - pass = Get_Pwnam(user,True); + pass = smb_getpwnam(user,domain,True); } if (pass == NULL) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7a818971d9..b09e09bc6d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -498,6 +498,7 @@ static int smb_create_user(char *unix_user) int ret; pstrcpy(add_script, lp_adduser_script()); + if (! *add_script) return -1; pstring_sub(add_script, "%u", unix_user); ret = smbrun(add_script,NULL,False); DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); @@ -514,6 +515,7 @@ static int smb_delete_user(char *unix_user) int ret; pstrcpy(del_script, lp_deluser_script()); + if (! *del_script) return -1; pstring_sub(del_script, "%u", unix_user); ret = smbrun(del_script,NULL,False); DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); @@ -569,7 +571,7 @@ static BOOL check_server_security(char *orig_user, char *domain, char *unix_user * level security as we never know if it was a failure * due to a bad password, or the user really doesn't exist. */ - if(lp_adduser_script() && !Get_Pwnam(unix_user,True)) { + if(lp_adduser_script() && !smb_getpwnam(unix_user,domain, True)) { smb_create_user(unix_user); } } @@ -605,7 +607,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user * If the admin wants us to try and create a UNIX * user on the fly, do so. */ - if(user_exists && lp_adduser_script() && !Get_Pwnam(unix_user,True)) { + if(user_exists && lp_adduser_script() && !smb_getpwnam(unix_user,domain,True)) { smb_create_user(unix_user); } } else { @@ -615,7 +617,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user * wants us to try and delete that UNIX user on the fly, * do so. */ - if(!user_exists && lp_deluser_script() && Get_Pwnam(unix_user,True)) { + if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,domain,True)) { smb_delete_user(unix_user); } } @@ -860,7 +862,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* * Do any UNIX username case mangling. */ - (void)Get_Pwnam( user, True); + smb_getpwnam(user, domain, True); add_session_user(user); @@ -917,7 +919,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) { - if (Get_Pwnam(user,True)) + if (smb_getpwnam(user,domain,True)) { DEBUG(1,("Rejecting user '%s': bad password\n", user)); return bad_password_error(inbuf,outbuf); @@ -930,7 +932,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int */ } - if (*smb_apasswd || !Get_Pwnam(user,True)) + if (*smb_apasswd || !smb_getpwnam(user,domain,True)) pstrcpy(user,lp_guestaccount(-1)); DEBUG(3,("Registered username %s for guest access\n",user)); guest = True; @@ -938,7 +940,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } if (!smb_getpwnam(user,domain,True)) { - DEBUG(3,("No such user %s - using guest account\n",user)); + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); pstrcpy(user,lp_guestaccount(-1)); guest = True; } -- cgit From 4fb6ca66771ba402e280eb17de720d0d3a7114cc Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 9 May 2000 22:05:39 +0000 Subject: This is reall Jeremy commiting as Herb at SGI labs. Fix for "socket operation on non-socket" error in log.smb on HEAD branch startup (server_fd not initialized to -1). Jeremy. (This used to be commit ebb4f76550062b0ea2005a2b8842641a2c91f528) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d2ccd75059..2f6a6ad7ed 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -53,7 +53,7 @@ extern pstring OriginalDir; the following 2 functions are an alternative - they make the file descriptor private to smbd */ -static int server_fd; +static int server_fd = -1; int smbd_server_fd(void) { -- cgit From f7089e3cbaa8429a5dd6f5ecf3f524291faa1881 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 9 May 2000 22:07:07 +0000 Subject: Fix for check_kernel_oplocks looking for the var directory before it may need to be created. Jeremy. (This used to be commit 6bf74da8b84a22aaddb0fbb160f02621abba01ba) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2f6a6ad7ed..7938b00ddc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -729,12 +729,12 @@ static void usage(char *pname) become_daemon(); } - check_kernel_oplocks(); - if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); } + check_kernel_oplocks(); + if (is_daemon) { pidfile_create("smbd"); } -- cgit From c88222da0ced7edf90b68e68ec49e0fe35a512fe Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 10 May 2000 01:31:46 +0000 Subject: Fix for misunderstanding of fsync added when vfs layer was done. Samba was doing fsync's (bleagh). Jeremy. (This used to be commit f9a52cadbf11f7afcef754a59d783964a2edb5bc) --- source3/smbd/fileio.c | 2 +- source3/smbd/files.c | 2 +- source3/smbd/reply.c | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 6507f56606..79dcd8ab83 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -650,7 +650,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) sync a file ********************************************************************/ -void sys_fsync_file(connection_struct *conn, files_struct *fsp) +void sync_file(connection_struct *conn, files_struct *fsp) { if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { flush_write_cache(fsp, SYNC_FLUSH); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 5b930f9940..a4837a1a8b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -283,7 +283,7 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; if ((conn == fsp->conn) && (fsp->fd != -1)) { - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); } } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b09e09bc6d..2072667174 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2352,7 +2352,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn))) - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); @@ -2400,7 +2400,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz nwritten = write_file(fsp,data,startpos,numtowrite); if (lp_syncalways(SNUM(conn))) - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2455,7 +2455,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d nwritten = write_file(fsp,data,startpos,numtowrite); if (lp_syncalways(SNUM(conn))) - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2552,7 +2552,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng fsp->fnum, (int)numtowrite, (int)nwritten)); if (lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2649,7 +2649,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (!fsp) { file_sync_all(conn); } else { - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); } DEBUG(3,("flush\n")); @@ -4246,7 +4246,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, nwritten = write_file(fsp,data,startpos,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); if(nwritten < (ssize_t)numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -4347,7 +4347,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz nwritten = write_file(fsp,data,startpos,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) - conn->vfs_ops.fsync(fsp->fd); + sync_file(conn,fsp); if (nwritten < (ssize_t)numtowrite) { -- cgit From ddc9b8b40642c90fe7c34b088eae4f8075f4033a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 09:49:55 +0000 Subject: more merging it is now at the stage that winbindd can compile in the head branch, but not link (This used to be commit d178c00aae77710ae6ff20a7f54a30e3bd8232bb) --- source3/smbd/server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7938b00ddc..54c6ddc5bd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -621,8 +621,9 @@ static void usage(char *pname) TimeInit(); - if(!specified_logfile) - pstrcpy(debugf,SMBLOGFILE); + if(!specified_logfile) { + slprintf(debugf, sizeof(debugf), "%s/log.smbd", LOGFILEBASE); + } pstrcpy(remote_machine, "smb"); -- cgit From 49a0e6d5989656c1b3c9c063a20308ca4ee5d73b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 10:41:59 +0000 Subject: more merging voodoo this adds "#define OLD_NTDOMAIN 1" in lots of places. Don't panic - this isn't permanent, it should go after another few merge steps have been done (This used to be commit 92109d7b3c06f240452d39f669ecb8c9c86ab610) --- source3/smbd/blocking.c | 4 ++++ source3/smbd/chgpasswd.c | 4 ++++ source3/smbd/close.c | 4 ++++ source3/smbd/conn.c | 4 ++++ source3/smbd/dir.c | 4 ++++ source3/smbd/dosmode.c | 4 ++++ source3/smbd/error.c | 4 ++++ source3/smbd/fileio.c | 2 ++ source3/smbd/filename.c | 4 ++++ source3/smbd/files.c | 2 ++ source3/smbd/ipc.c | 2 ++ source3/smbd/lanman.c | 3 +++ source3/smbd/message.c | 4 ++++ source3/smbd/negprot.c | 4 ++++ source3/smbd/nttrans.c | 4 +++- source3/smbd/open.c | 4 ++++ source3/smbd/oplock.c | 4 ++++ source3/smbd/password.c | 4 ++++ source3/smbd/pipes.c | 3 +++ source3/smbd/process.c | 3 +++ source3/smbd/reply.c | 2 ++ source3/smbd/server.c | 2 ++ source3/smbd/service.c | 4 ++++ source3/smbd/trans2.c | 4 ++++ source3/smbd/uid.c | 4 ++++ 25 files changed, 86 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index e8dc29f80a..16caf8b52e 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -631,3 +633,5 @@ void process_blocking_lock_queue(time_t t) blr = (blocking_lock_record *)ubi_slNext(blr); } } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 708b52f4bc..d27cf373f5 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -935,3 +937,5 @@ BOOL check_plaintext_password(char *user, char *old_passwd, else return (True); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 03f6aaf81a..0b7b5f794e 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -225,3 +227,5 @@ int close_file(files_struct *fsp, BOOL normal_close) return close_statfile(fsp, normal_close); return close_normal_file(fsp, normal_close); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index f43a30d320..ebd18861fc 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -200,3 +202,5 @@ void conn_free(connection_struct *conn) ZERO_STRUCTP(conn); free(conn); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ee383ea72a..aaab206a26 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -891,3 +893,5 @@ void DirCacheFlush(int snum) entry = (dir_cache_entry *)next; } } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 278a4ab5e3..26fd2aff14 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -295,3 +297,5 @@ BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) return(True); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/error.c b/source3/smbd/error.c index d879f9a93c..49da44d68e 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -144,3 +146,5 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int return(outsize); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 79dcd8ab83..45ad959a3c 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -657,3 +658,4 @@ void sync_file(connection_struct *conn, files_struct *fsp) conn->vfs_ops.fsync(fsp->fd); } } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ed1a1c3f63..294e80250a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -509,3 +511,5 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d return(False); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/files.c b/source3/smbd/files.c index a4837a1a8b..2909d49a2a 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -363,3 +364,4 @@ void file_chain_restore(void) { chain_fsp = oplock_save_chain_fsp; } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 73addda086..30ac8932aa 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -506,3 +507,4 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int return(outsize); } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b986df6d07..fe2cc3ae7d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -3179,3 +3180,5 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * return -1; } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/message.c b/source3/smbd/message.c index cc329d61a6..a65539affa 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -217,3 +219,5 @@ int reply_sendend(connection_struct *conn, return(outsize); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e8302a43e6..60af2924b2 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -437,3 +439,5 @@ int reply_negprot(connection_struct *conn, return(outsize); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 98f5959c2d..e98187de25 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -2160,7 +2161,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p for(i = 0; i < dacl->num_aces; i++) { DOM_SID ace_sid; - SEC_ACE *psa = &dacl->ace_list[i]; + SEC_ACE *psa = &dacl->ace[i]; if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { @@ -2669,3 +2670,4 @@ due to being in oplock break state.\n" )); calls have already sent it. If outsize != -1 then it is returning an error packet. */ } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0c6927ba2a..e501d9ded8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -1089,3 +1091,5 @@ free_and_exit: free((char *)old_shares); return(ret); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 4a363d45e9..ef43400074 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -1391,3 +1393,5 @@ Disabling kernel oplock support.\n", strerror(errno) )); } #endif /* HAVE_KERNEL_OPLOCKS */ } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 70663f0909..325600e92e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -1523,3 +1525,5 @@ BOOL domain_client_validate( char *user, char *domain, cli_shutdown(&cli); return True; } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 0cfe653d30..c1d5c261fe 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -259,3 +260,5 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) return(outsize); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 805bbe4415..ac81116999 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -1061,3 +1062,5 @@ void smbd_process(void) process_local_message(InBuffer, BUFFER_SIZE); } } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2072667174..0d099a7b4c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -4481,3 +4482,4 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, return(outsize); } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 54c6ddc5bd..f2a3631cb1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -782,3 +783,4 @@ static void usage(char *pname) return(0); } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0701b854b7..71d718154d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -684,3 +686,5 @@ void close_cnum(connection_struct *conn, uint16 vuid) } conn_free(conn); } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 458d6f3ec0..55c0b306b0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -2396,3 +2398,5 @@ int reply_trans2(connection_struct *conn, call_trans2xxx calls have already sent it. If outsize != -1 then it is returning */ } + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 28d2fb71f6..d749470793 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -421,3 +423,5 @@ void unbecome_root(BOOL restore_dir) become_root_depth = 0; } + +#undef OLD_NTDOMAIN -- cgit From 15c1b7663d63a481ae7719efbdd38f5a05b494d2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 11:08:08 +0000 Subject: patch from Dominik Kubla (This used to be commit 9c598e571decb449607042ba9628f68de9b45043) --- source3/smbd/connection.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index aa49f8cf7c..bc014c300d 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -340,7 +340,7 @@ static void utmp_yield(pid_t pid, const connection_struct *conn) } } -static void utmp_claim(const struct connect_record *crec, const connection_struct *conn) +static void utmp_claim(const struct connections_data *crec, const connection_struct *conn) { struct utmp u; @@ -354,8 +354,8 @@ static void utmp_claim(const struct connect_record *crec, const connection_struc return; } - DEBUG(2,("utmp_claim: conn: user:%s cnum:%d i:%d\n", - conn->user, conn->cnum, i)); + DEBUG(2,("utmp_claim: conn: user:%s cnum:%d\n", + conn->user, conn->cnum)); DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s\n", crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name())); -- cgit From a3d897cfb3d8b66501a1ccedc78bd59782c11b14 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 11:45:16 +0000 Subject: formatting fix (This used to be commit 3e710f660253fe6fa5c0ed7435ec66a2ed908b28) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f2a3631cb1..622251b375 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -344,7 +344,7 @@ BOOL reload_services(BOOL test) } reset_mangled_cache(); - reset_stat_cache(); + reset_stat_cache(); /* this forces service parameters to be flushed */ become_service(NULL,True); -- cgit From e86cba2194a04a581b872076d408c66c28b16760 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 11:49:55 +0000 Subject: check for sighup on each packet - otherwise it can take a _long_ time to reload services (This used to be commit 0fb4ba4e037f25b8b75bcae0ecb1d9b43f0f9e5f) --- source3/smbd/process.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ac81116999..3d2a507cca 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1012,6 +1012,18 @@ void smbd_process(void) /* free up temporary memory */ lp_talloc_free(); + /* + * If reload_after_sighup == True then we got a SIGHUP + * and are being asked to reload. Fix from + */ + if (reload_after_sighup) { + /* become root */ + unbecome_user(); + DEBUG(1,("Reloading services after SIGHUP\n")); + reload_services(False); + reload_after_sighup = False; + } + while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) -- cgit From a71d9b291c5365f08250b77d281f4cc8f24ec2e2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 13:21:32 +0000 Subject: treat a blank "password server =" line as a "*" if in domain security (This used to be commit 5a617c013cce65434d315dc33279a4bc28dc63de) --- source3/smbd/password.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 325600e92e..3953c5b0e3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1457,7 +1457,8 @@ BOOL domain_client_validate( char *user, char *domain, * PDC/BDC. Contact each in turn and try and authenticate. */ - pserver = strdup(lp_passwordserver()); + pserver = lp_passwordserver(); + if (! *pserver) pserver = "*"; p = pserver; while (!connected_ok && @@ -1469,8 +1470,6 @@ BOOL domain_client_validate( char *user, char *domain, } } - free(pserver); - if (!connected_ok) { DEBUG(0,("domain_client_validate: Domain password server not available.\n")); cli_shutdown(&cli); -- cgit From 43a3faab0831a866559ca56e70c81be582047d0b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 14:48:33 +0000 Subject: - changed smb_getpwnam() to use winbind style usernames - finished ntdom -> winbind rename in head (This used to be commit ada483cb56453afc6df4ec4be18bfe5e943c7150) --- source3/smbd/password.c | 2 +- source3/smbd/reply.c | 27 +++++++++++++++++++-------- source3/smbd/service.c | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3953c5b0e3..314b3dd3c7 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -493,7 +493,7 @@ BOOL pass_check_smb(char *user, char *domain, } else { - pass = smb_getpwnam(user,domain,True); + pass = smb_getpwnam(user,True); } if (pass == NULL) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0d099a7b4c..1fc377f362 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -572,7 +572,7 @@ static BOOL check_server_security(char *orig_user, char *domain, char *unix_user * level security as we never know if it was a failure * due to a bad password, or the user really doesn't exist. */ - if(lp_adduser_script() && !smb_getpwnam(unix_user,domain, True)) { + if(lp_adduser_script() && !smb_getpwnam(unix_user,True)) { smb_create_user(unix_user); } } @@ -608,7 +608,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user * If the admin wants us to try and create a UNIX * user on the fly, do so. */ - if(user_exists && lp_adduser_script() && !smb_getpwnam(unix_user,domain,True)) { + if(user_exists && lp_adduser_script() && !smb_getpwnam(unix_user,True)) { smb_create_user(unix_user); } } else { @@ -618,7 +618,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user * wants us to try and delete that UNIX user on the fly, * do so. */ - if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,domain,True)) { + if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) { smb_delete_user(unix_user); } } @@ -853,6 +853,17 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstrcpy( orig_user, user); + /* if the username exists as a domain/username pair on the unix system then use + that */ + if (!Get_Pwnam(user, False)) { + pstring user2; + slprintf(user2,sizeof(user2),"%s/%s", domain, user); + if (Get_Pwnam(user2, True)) { + DEBUG(3,("Using unix username %s\n", user2)); + pstrcpy(user, user2); + } + } + /* * Pass the user through the NT -> unix user mapping * function. @@ -863,7 +874,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* * Do any UNIX username case mangling. */ - smb_getpwnam(user, domain, True); + smb_getpwnam(user, True); add_session_user(user); @@ -920,7 +931,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) { - if (smb_getpwnam(user,domain,True)) + if (smb_getpwnam(user,True)) { DEBUG(1,("Rejecting user '%s': bad password\n", user)); return bad_password_error(inbuf,outbuf); @@ -933,14 +944,14 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int */ } - if (*smb_apasswd || !smb_getpwnam(user,domain,True)) + if (*smb_apasswd || !smb_getpwnam(user,True)) pstrcpy(user,lp_guestaccount(-1)); DEBUG(3,("Registered username %s for guest access\n",user)); guest = True; } } - if (!smb_getpwnam(user,domain,True)) { + if (!smb_getpwnam(user,True)) { DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); pstrcpy(user,lp_guestaccount(-1)); guest = True; @@ -975,7 +986,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int user we should become. */ { - const struct passwd *pw = smb_getpwnam(user,domain,False); + const struct passwd *pw = smb_getpwnam(user,False); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); return bad_password_error(inbuf,outbuf); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 71d718154d..f713b18562 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -295,7 +295,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int } /* find out some info about the user */ - pass = smb_getpwnam(user,validated_domain(vuid),True); + pass = smb_getpwnam(user,True); if (pass == NULL) { DEBUG(0,( "Couldn't find account %s\n",user)); -- cgit From 612738a9e14b6fb6a2687993d6416bbe6c3ea94d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 May 2000 22:47:09 +0000 Subject: lib/util_unistr.c: libsmb/clilist.c: rpc_server/srv_spoolss_nt.c: smbd/trans2.c: Changed unistr_to_ascii to unistr_to_dos - do codepage conversion. msdfs/msdfs.c: Removed stub unistr_to_dos. libsmb/pwd_cache.c: Removed obfuscation functions as they don't do anything and don't add any security. Jeremy. (This used to be commit 1ed146467e764e6a81d8f78cd58fb5765ebf5d21) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 55c0b306b0..e0156c083d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2118,7 +2118,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, /* NT always sends in UNICODE, may not set UNICODE flag */ if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS)) { - unistr_to_dos(pathname, ¶ms[2]); + unistr_to_dos(pathname, ¶ms[2], sizeof(pathname)); DEBUG(10,("UNICODE referral for %s\n",pathname)); } else -- cgit From 28d8970987265275f53ba1898b0057cf20629c9c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 May 2000 00:11:49 +0000 Subject: Check fstat return for error. Jeremy. (This used to be commit c54e77b1f9defce3d6c2e530e0fb460c2b0c54c2) --- source3/smbd/open.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e501d9ded8..23d95eadfd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -133,7 +133,11 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return False; } - conn->vfs_ops.fstat(fsp->fd, &sbuf); + if (conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1) { + DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); + fd_close(conn, fsp); + return False; + } /* * POSIX allows read-only opens of directories. We don't -- cgit From ebd73f37a2103965eea4967b3983b8a6219316a1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 May 2000 05:07:26 +0000 Subject: use our primary domain trust account for trusted domain authentication (This used to be commit db90a4b9609a980fa2f4328d38a0d2c60a1384a0) --- source3/smbd/password.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 314b3dd3c7..f9aa10eced 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1435,9 +1435,9 @@ BOOL domain_client_validate( char *user, char *domain, } /* - * Get the machine account password. + * Get the machine account password for our primary domain */ - if (!get_trust_account_password(domain, trust_passwd, NULL)) + if (!get_trust_account_password(lp_workgroup(), trust_passwd, NULL)) { return False; } -- cgit From dd8f9b5491e92b04bc0c13df265698e97a3ea3c2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 May 2000 05:10:32 +0000 Subject: fixed a problem with appliance operation (This used to be commit acf9286e82b851e25ee863f673bff713a38002e7) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1fc377f362..5c80a61511 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -855,10 +855,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* if the username exists as a domain/username pair on the unix system then use that */ - if (!Get_Pwnam(user, False)) { + if (!getpwnam(user)) { pstring user2; slprintf(user2,sizeof(user2),"%s/%s", domain, user); - if (Get_Pwnam(user2, True)) { + if (getpwnam(user2)) { DEBUG(3,("Using unix username %s\n", user2)); pstrcpy(user, user2); } -- cgit From 60c04512a0af1656447eeb489452a13adbbd91d4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 May 2000 05:25:22 +0000 Subject: fixed error code for buffer_too_large in trans reply (This used to be commit a0a556a36b8ad0f14f97a1b7ccc5d429bf8f950e) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 30ac8932aa..a8c1502e94 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -104,7 +104,7 @@ void send_trans_reply(char *outbuf, { /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); + SIVAL(outbuf, smb_rcls, 0x80000000 | STATUS_BUFFER_OVERFLOW); } copy_trans_params_and_data(outbuf, align, -- cgit From 479c73559e137a406f912f8e262e1658861dc9db Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 May 2000 06:30:45 +0000 Subject: use "winbind separator" option for domain/user separator character (This used to be commit 6cbb826b154e61085fd651116caf472d4d438c1d) --- source3/smbd/password.c | 2 +- source3/smbd/reply.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f9aa10eced..95f03ab204 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -167,7 +167,7 @@ int setup_groups(char *user, char *domain, gid_t grp = 0; gid_t *groups = NULL; - if (-1 == smb_initgroups(user,domain,gid)) + if (-1 == initgroups(user,gid)) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); if (getuid() == 0) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5c80a61511..b08606452f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -857,7 +857,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int that */ if (!getpwnam(user)) { pstring user2; - slprintf(user2,sizeof(user2),"%s/%s", domain, user); + slprintf(user2,sizeof(user2),"%s%s%s", domain, lp_winbind_separator(), user); if (getpwnam(user2)) { DEBUG(3,("Using unix username %s\n", user2)); pstrcpy(user, user2); -- cgit From 0806cf75ff96dee6715610bd61e21cde08fa1c61 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 May 2000 14:28:46 +0000 Subject: added spool_io_printer_driver_info_level_6() thsi function and the associated header structure were autogenerated using a little awk based code geerator I wroe ths evening. I'll commit that next ... (This used to be commit 974813f0d4afb6c14ed27c48ab24b19932557f9f) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f713b18562..fa3bc3cb10 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -281,7 +281,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* shall we let them in? */ if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { - DEBUG( 2, ( "Invalid username/password for %s\n", service ) ); + DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) ); *ecode = ERRbadpw; return NULL; } -- cgit From b27886addbdb1ff7c8e678023c7c1ef6d3bba9a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 May 2000 17:13:50 +0000 Subject: passdb/secrets.c: Fix typo in comment. rpc_server/srv_pipe.c: Use accessor functions rather than diddling with structure internals directly. smbd/process.c: smbd/reply.c: Remove READ_PREDICTION #ifdefs. Jeremy. (This used to be commit eba825ff030a175bd271caa6f543379dfdbbd646) --- source3/smbd/process.c | 5 ----- source3/smbd/reply.c | 5 ----- 2 files changed, 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3d2a507cca..9e5b7b1477 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1002,11 +1002,6 @@ void smbd_process(void) if (deadtime <= 0) deadtime = DEFAULT_SMBD_TIMEOUT; -#if USE_READ_PREDICTION - if (lp_readprediction()) - do_read_prediction(); -#endif - errno = 0; /* free up temporary memory */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b08606452f..eddd06e343 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2067,11 +2067,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s int predict=0; _smb_setlen(header,nread); -#if USE_READ_PREDICTION - if (!fsp->can_write) - predict = read_predict(fsp, fsp->fd,startpos,header+4,NULL,nread); -#endif /* USE_READ_PREDICTION */ - if ((nread-predict) > 0) { if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) { DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); -- cgit From 651946153e41354769839fa6cbcfd36fd320efbe Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Tue, 16 May 2000 01:13:16 +0000 Subject: The new msdfs implementation that uses symlinks to point to other servers. Very intuitive. Removed the dfs map parsing code and tdb maintenance code (files msdfs/parse_dfs_map.c & msdfs/msdfs_tdb.c), dfs map loading and unloading calls (param/loadparm.c smbd/server.c). Added code to display msdfs format symlinks as directories in a transact2_findfirst/findnext. (smbd/trans2.c) Modified msdfs/msdfs.c to use the msdfs symlinks to create dfs referrals. Changed msdfs/README to reflect new operability. (This used to be commit 6803d2574fab9e5931786d5c9aa5dc5867bb5f05) --- source3/smbd/dosmode.c | 2 +- source3/smbd/server.c | 11 ----------- source3/smbd/trans2.c | 15 +++++++++++++-- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 26fd2aff14..5b077110bb 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -138,7 +138,7 @@ int dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) if (S_ISDIR(sbuf->st_mode)) result = aDIR | (result & aRONLY); - + #ifdef S_ISLNK #if LINKS_READ_ONLY if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 622251b375..a8e7540d28 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -318,14 +318,6 @@ BOOL reload_services(BOOL test) ret = lp_load(servicesf,False,False,True); -#ifdef MS_DFS - /* load the dfs maps of all the services having - a dfs_map parameter - we don't want to do this in lp_load because we want just the smbd - server to load up the dfs maps into msdfs.tdb. not nmbd, swat etc*/ - load_dfsmaps(); -#endif - load_printers(); /* perhaps the config filename is now set */ @@ -455,9 +447,6 @@ void exit_server(char *reason) } locking_end(); -#ifdef MS_DFS - msdfs_end(); -#endif DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); exit(0); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e0156c083d..18452158c8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -405,8 +405,19 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcat(pathreal,dname); if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) { - DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); - continue; + /* Needed to show the msdfs symlinks as directories */ + if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) + || !is_msdfs_volume(conn, pathreal)) + { + DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", + pathreal,strerror(errno))); + continue; + } + else + { + DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal)); + sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; + } } mode = dos_mode(conn,pathreal,&sbuf); -- cgit From 74d677ec591a715e28dba29a33ee40e1b1c2f830 Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Thu, 18 May 2000 18:43:53 +0000 Subject: Added the NETDFS pipe to allow remote administration of the msdfs symlinks on the samba server. (This used to be commit 15e7d8f6c5cddf6ce409ee2505744250d181ec34) --- source3/smbd/nttrans.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e98187de25..5f58962799 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -44,6 +44,9 @@ static char *known_nt_pipes[] = { "\\lsarpc", "\\winreg", "\\spoolss", +#ifdef MS_DFS + "\\netdfs", +#endif NULL }; -- cgit From 3cbaf59726fc9fb7fc5a3124b3e1b8c5480a568e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 May 2000 01:27:19 +0000 Subject: Fixed bug where file access was allowed on IPC$ share. Return correct error codes on invalid share name. Jeremy. (This used to be commit 420d6bc4809cef9d74354175d0fa956ab4e8ac3c) --- source3/smbd/nttrans.c | 3 +++ source3/smbd/reply.c | 6 +++--- source3/smbd/service.c | 4 ++-- source3/smbd/trans2.c | 3 +++ 4 files changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5f58962799..cfd0faaf4f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2512,6 +2512,9 @@ due to being in oplock break state.\n" )); return -1; } + if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) + return (ERROR(ERRSRV,ERRaccess)); + outsize = set_message(outbuf,0,0,True); /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eddd06e343..c2db6dd082 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -156,8 +156,8 @@ work out what error to give to a failed connection static int connection_error(char *inbuf,char *outbuf,int ecode) { - if (ecode == ERRnoipc) - return(ERROR(ERRDOS,ERRnoipc)); + if (ecode == ERRnoipc || ecode == ERRnosuchshare) + return(ERROR(ERRDOS,ecode)); return(ERROR(ERRSRV,ecode)); } @@ -295,7 +295,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt p = strchr(path+2,'\\'); if (!p) - return(ERROR(ERRSRV,ERRinvnetname)); + return(ERROR(ERRDOS,ERRnosuchshare)); fstrcpy(service,p+1); p = strchr(service,'%'); if (p) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index fa3bc3cb10..e6c8b2a6d8 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -212,7 +212,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int DEBUG(0,("%s (%s) couldn't find service %s\n", remote_machine, client_addr(), service)); - *ecode = ERRinvnetname; + *ecode = ERRnosuchshare; return NULL; } @@ -567,7 +567,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int yield_connection(conn,"",MAXSTATUS); } conn_free(conn); - *ecode = ERRinvnetname; + *ecode = ERRnosuchshare; return NULL; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 18452158c8..f4cc9b218f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2234,6 +2234,9 @@ int reply_trans2(connection_struct *conn, return -1; } + if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)) + return(ERROR(ERRSRV,ERRaccess)); + outsize = set_message(outbuf,0,0,True); /* All trans2 messages we handle have smb_sucnt == 1 - ensure this -- cgit From 295b2d31a55c1450667519502fb94d852bf6cfd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 May 2000 17:57:51 +0000 Subject: Did a proper fix for the file access on IPC$. Denied all pipe opens on trans2 open calls as we don't have the pipe open response coded up yet. Jeremy. (This used to be commit 8142e27c9c32aba5a7dabc48a676b93cf680151b) --- source3/smbd/nttrans.c | 316 ++++++++++++++++++++++++++++++------------------- source3/smbd/reply.c | 8 +- source3/smbd/trans2.c | 4 + 3 files changed, 202 insertions(+), 126 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index cfd0faaf4f..27635cae25 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -587,6 +587,50 @@ static int nt_open_pipe(char *fname, connection_struct *conn, return 0; } +/**************************************************************************** + Reply to an NT create and X call for pipes. +****************************************************************************/ + +static int do_ntcreate_pipe_open(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) +{ + pstring fname; + int ret; + int pnum = -1; + char *p = NULL; + uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), + ((uint32)sizeof(fname)-1)); + + get_filename(fname, inbuf, smb_buf(inbuf)-inbuf, + smb_buflen(inbuf),fname_len); + if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) + return ret; + + /* + * Deal with pipe return. + */ + + set_message(outbuf,34,0,True); + + p = outbuf + smb_vwv2; + p++; + SSVAL(p,0,pnum); + p += 2; + SIVAL(p,0,FILE_WAS_OPENED); + p += 4; + p += 32; + SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ + p += 20; + /* File type. */ + SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); + /* Device state. */ + SSVAL(p,2, 0x5FF); /* ? */ + + DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname)); + + return chain_reply(inbuf,outbuf,length,bufsize); +} + /**************************************************************************** Reply to an NT create and X call. ****************************************************************************/ @@ -611,7 +655,6 @@ int reply_ntcreate_and_X(connection_struct *conn, reply bits separately. */ int oplock_request = 0; mode_t unixmode; - int pnum = -1; int fmode=0,rmode=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; @@ -621,6 +664,16 @@ int reply_ntcreate_and_X(connection_struct *conn, char *p = NULL; BOOL stat_open_only = False; + /* If it's an IPC, use the pipe handler. */ + + if (IS_IPC(conn)) { + if (lp_nt_pipe_support()) + return do_ntcreate_pipe_open(conn,inbuf,outbuf,length,bufsize); + else + return(ERROR(ERRDOS,ERRbadaccess)); + } + + /* * We need to construct the open_and_X ofun value from the * NT values, as that's what our code is structured to accept. @@ -691,39 +744,6 @@ int reply_ntcreate_and_X(connection_struct *conn, smb_buflen(inbuf),fname_len); } - /* If it's an IPC, use the pipe handler. */ - - if (IS_IPC(conn) && lp_nt_pipe_support()) { - - int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); - if(ret != 0) - return ret; - - /* - * Deal with pipe return. - */ - - set_message(outbuf,34,0,True); - - p = outbuf + smb_vwv2; - p++; - SSVAL(p,0,pnum); - p += 2; - SIVAL(p,0,FILE_WAS_OPENED); - p += 4; - p += 32; - SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ - p += 20; - /* File type. */ - SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); - /* Device state. */ - SSVAL(p,2, 0x5FF); /* ? */ - - DEBUG(5,("reply_ntcreate_and_X: open pipe = %s\n", fname)); - - return chain_reply(inbuf,outbuf,length,bufsize); - } - /* * Now contruct the smb_open_mode value from the filename, * desired access and the share access. @@ -940,6 +960,72 @@ int reply_ntcreate_and_X(connection_struct *conn, return chain_reply(inbuf,outbuf,length,bufsize); } +/**************************************************************************** + Reply to a NT_TRANSACT_CREATE call to open a pipe. +****************************************************************************/ + +static int do_nt_transact_create_pipe( connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, char **ppsetup, char **ppparams, + char **ppdata) +{ + pstring fname; + uint32 fname_len; + int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); + char *params = *ppparams; + int ret; + int pnum = -1; + char *p = NULL; + + /* + * Ensure minimum number of parameters sent. + */ + + if(total_parameter_count < 54) { + DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); + return(ERROR(ERRDOS,ERRbadaccess)); + } + + fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1)); + + get_filename_transact(&fname[0], params, 53, + total_parameter_count - 53 - fname_len, fname_len); + + if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) + return ret; + + /* Realloc the size of parameters and data we will return */ + params = *ppparams = Realloc(*ppparams, 69); + if(params == NULL) + return(ERROR(ERRDOS,ERRnomem)); + + memset((char *)params,'\0',69); + + p = params; + SCVAL(p,0,NO_OPLOCK_RETURN); + + p += 2; + SSVAL(p,0,pnum); + p += 2; + SIVAL(p,0,FILE_WAS_OPENED); + p += 8; + + p += 32; + SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ + p += 20; + /* File type. */ + SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); + /* Device state. */ + SSVAL(p,2, 0x5FF); /* ? */ + + DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); + + /* Send the required number of replies */ + send_nt_replies(inbuf, outbuf, bufsize, 0, params, 69, *ppdata, 0); + + return -1; +} + /**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ @@ -956,7 +1042,6 @@ static int call_nt_transact_create(connection_struct *conn, reply bits separately. */ int oplock_request = 0; mode_t unixmode; - int pnum = -1; int fmode=0,rmode=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; @@ -979,6 +1064,18 @@ static int call_nt_transact_create(connection_struct *conn, DEBUG(5,("call_nt_transact_create\n")); + /* + * If it's an IPC, use the pipe handler. + */ + + if (IS_IPC(conn)) { + if (lp_nt_pipe_support()) + return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, + bufsize, ppsetup, ppparams, ppdata); + else + return(ERROR(ERRDOS,ERRbadaccess)); + } + /* * Ensure minimum number of parameters sent. */ @@ -1069,76 +1166,68 @@ static int call_nt_transact_create(connection_struct *conn, total_parameter_count - 53 - fname_len, fname_len); } - /* If it's an IPC, use the pipe handler. */ - if (IS_IPC(conn)) { - int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum); - if(ret != 0) - return ret; - smb_action = FILE_WAS_OPENED; - } else { - - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ - if((smb_open_mode = map_share_mode( &stat_open_only, fname, desired_access, - share_access, file_attributes)) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); + if((smb_open_mode = map_share_mode( &stat_open_only, fname, desired_access, + share_access, file_attributes)) == -1) + return(ERROR(ERRDOS,ERRbadaccess)); - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - /* - * Check if POSIX semantics are wanted. - */ + /* + * Check if POSIX semantics are wanted. + */ - set_posix_case_semantics(file_attributes); + set_posix_case_semantics(file_attributes); - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); - - unixmode = unix_mode(conn,smb_attr | aARCH, fname); + unix_convert(fname,conn,0,&bad_path,NULL); - /* - * If it's a request for a directory open, deal with it separately. - */ + unixmode = unix_mode(conn,smb_attr | aARCH, fname); + + /* + * If it's a request for a directory open, deal with it separately. + */ - if(create_options & FILE_DIRECTORY_FILE) { + if(create_options & FILE_DIRECTORY_FILE) { - oplock_request = 0; + oplock_request = 0; - /* - * We will get a create directory here if the Win32 - * app specified a security descriptor in the - * CreateDirectory() call. - */ + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); - if(!fsp) { - restore_case_semantics(file_attributes); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if(!fsp) { + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), - &sbuf) != 0) { - close_file(fsp,True); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } + if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), + &sbuf) != 0) { + close_file(fsp,True); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } - } else { + } else { - /* - * Ordinary file case. - */ + /* + * Ordinary file case. + */ - fsp = open_file_shared(conn,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + fsp = open_file_shared(conn,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); - if (!fsp) { + if (!fsp) { if(errno == EISDIR) { @@ -1227,7 +1316,6 @@ static int call_nt_transact_create(connection_struct *conn, if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) smb_action |= EXTENDED_OPLOCK_GRANTED; - } } restore_case_semantics(file_attributes); @@ -1248,45 +1336,25 @@ static int call_nt_transact_create(connection_struct *conn, SCVAL(p,0,NO_OPLOCK_RETURN); p += 2; - if (IS_IPC(conn)) { - SSVAL(p,0,pnum); - } else { - SSVAL(p,0,fsp->fnum); - } + SSVAL(p,0,fsp->fnum); p += 2; SIVAL(p,0,smb_action); p += 8; - if (IS_IPC(conn)) { - /* - * Deal with pipe return. - */ - p += 32; - SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ - p += 20; - /* File type. */ - SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); - /* Device state. */ - SSVAL(p,2, 0x5FF); /* ? */ - } else { - /* - * Deal with file return. - */ - /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); - p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ - p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ - p += 4; - SOFF_T(p,0,file_len); - p += 8; - SOFF_T(p,0,file_len); - } + /* Create time. */ + put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fmode); /* File Attributes. */ + p += 4; + SOFF_T(p,0,file_len); + p += 8; + SOFF_T(p,0,file_len); DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c2db6dd082..9845853349 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1571,8 +1571,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt files_struct *fsp; /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn) && lp_nt_pipe_support()) - return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); + if (IS_IPC(conn)) { + if (lp_nt_pipe_support()) + return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); + else + return (ERROR(ERRSRV,ERRaccess)); + } /* XXXX we need to handle passed times, sattr and flags */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f4cc9b218f..cc3261a479 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -218,6 +218,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", fname,open_mode, open_attr, open_ofun, open_size)); + if (IS_IPC(conn)) { + return(ERROR(ERRSRV,ERRaccess)); + } + /* XXXX we need to handle passed times, sattr and flags */ unix_convert(fname,conn,0,&bad_path,NULL); -- cgit From 7f2b42abec143e06971114c9292ac9539d012456 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 24 May 2000 06:36:10 +0000 Subject: got rid of lp_revalidate() (This used to be commit 8dea95e62c7f4723cd4b71c1b03c613386392c49) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 95f03ab204..614e5a84fc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -760,7 +760,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, } /* check for a previously validated username/password pair */ - if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) && + if (!ok && (lp_security() > SEC_SHARE) && (vuser != 0) && !vuser->guest && user_ok(vuser->user.unix_name,snum)) { fstrcpy(user,vuser->user.unix_name); -- cgit From 8a86541e282424c4e0ea5626b26e818779ba0375 Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Fri, 26 May 2000 17:10:40 +0000 Subject: Changed MS_DFS to WITH_MSDFS throughout. Fixed trans2 calls on IPC$ to let dfs referral calls through. (This used to be commit e0965a80bdca5239886b11ef55dc29fed261bfc0) --- source3/smbd/negprot.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/trans2.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 60af2924b2..362d571ff1 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -201,7 +201,7 @@ static int reply_nt1(char *outbuf) capabilities |= CAP_RAW_MODE; } -#ifdef MS_DFS +#ifdef WITH_MSDFS if(lp_host_msdfs()) capabilities |= CAP_DFS; #endif diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 27635cae25..f64ca386f8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -44,7 +44,7 @@ static char *known_nt_pipes[] = { "\\lsarpc", "\\winreg", "\\spoolss", -#ifdef MS_DFS +#ifdef WITH_MSDFS "\\netdfs", #endif NULL diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cc3261a479..900a87e32b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -411,7 +411,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, { /* Needed to show the msdfs symlinks as directories */ if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) - || !is_msdfs_volume(conn, pathreal)) + || !is_msdfs_link(conn, pathreal)) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", pathreal,strerror(errno))); @@ -2238,7 +2238,8 @@ int reply_trans2(connection_struct *conn, return -1; } - if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)) + if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) + && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) return(ERROR(ERRSRV,ERRaccess)); outsize = set_message(outbuf,0,0,True); -- cgit From 54695647ef52558e5f83744898b7c5c95c9fed5a Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 27 May 2000 01:56:26 +0000 Subject: fixed nttrans.c (This used to be commit 06cd46b0ec10b32af54edd8256d2fdbec45e1371) --- source3/smbd/nttrans.c | 444 +++++-------------------------------------------- 1 file changed, 38 insertions(+), 406 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f64ca386f8..a149374114 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1822,47 +1822,6 @@ name = %s\n", fsp->fsp_name )); return -1; } -/**************************************************************************** - Map unix perms to NT. -****************************************************************************/ - -static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w_mask, int x_mask, BOOL is_directory) -{ - SEC_ACCESS sa; - uint32 nt_mask = 0; - - *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - - if((perm & (r_mask|w_mask|x_mask)) == (r_mask|w_mask|x_mask)) { - nt_mask = UNIX_ACCESS_RWX; - } else if((perm & (r_mask|w_mask|x_mask)) == 0) { - nt_mask = UNIX_ACCESS_NONE; - } else { - nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; - if(is_directory) - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - else - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; - } - init_sec_access(&sa,nt_mask); - return sa; -} - -/**************************************************************************** - Function to create owner and group SIDs from a SMB_STRUCT_STAT. -****************************************************************************/ - -static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) -{ - extern DOM_SID global_sam_sid; - - sid_copy(powner_sid, &global_sam_sid); - sid_copy(pgroup_sid, &global_sam_sid); - sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); - sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); -} - /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns True. @@ -1870,27 +1829,8 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { - extern DOM_SID global_sid_World; SMB_STRUCT_STAT sbuf; - SEC_ACE ace_list[6]; - DOM_SID owner_sid; - DOM_SID group_sid; - size_t sec_desc_size; - SEC_ACL *psa = NULL; - SEC_ACCESS owner_access; - int owner_acl_type; - SEC_ACCESS group_access; - int grp_acl_type; - SEC_ACCESS other_access; - int other_acl_type; - int num_acls = 0; - - *ppdesc = NULL; - - if(!lp_nt_acl_support()) { - sid_copy( &owner_sid, &global_sid_World); - sid_copy( &group_sid, &global_sid_World); - } else { + mode_t mode; if(fsp->is_directory || fsp->fd == -1) { if(dos_stat(fsp->fsp_name, &sbuf) != 0) { @@ -1902,80 +1842,19 @@ static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } } - /* - * Get the owner, group and world SIDs. - */ - - create_file_sids(&sbuf, &owner_sid, &group_sid); - - /* - * Create the generic 3 element UNIX acl. - */ - - owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, - owner_access, 0); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, - group_access, 0); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, - other_access, 0); - if(fsp->is_directory) { /* * For directory ACLs we also add in the inherited permissions * ACE entries. These are the permissions a file would get when * being created in the directory. */ - mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - - owner_access = map_unix_perms(&owner_acl_type, mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, - owner_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, - group_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, - other_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); } - - if(num_acls) - if((psa = make_sec_acl( 3, num_acls, ace_list)) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); - return 0; - } - } - - *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sec_desc_size); - - if(!*ppdesc) { - DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); - sec_desc_size = 0; - } - - free_sec_acl(&psa); - - return sec_desc_size; + else + { + mode = sbuf.st_mode; + } + return convertperms_unix_to_sd(&sbuf, fsp->is_directory, mode, ppdesc); } /**************************************************************************** @@ -1993,7 +1872,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *params = *ppparams; char *data = *ppdata; prs_struct pd; - SEC_DESC *psd; + SEC_DESC *psd = NULL; size_t sec_desc_size; files_struct *fsp = file_fsp(params,0); @@ -2020,7 +1899,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if(max_data_count < sec_desc_size) { - free_sec_desc(&psd); + free_sec_desc(psd); + safe_free(psd); send_nt_replies(inbuf, outbuf, bufsize, 0xC0000000|NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); @@ -2033,7 +1913,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, data = *ppdata = Realloc(*ppdata, sec_desc_size); if(data == NULL) { - free_sec_desc(&psd); + free_sec_desc(psd); + safe_free(psd); return(ERROR(ERRDOS,ERRnomem)); } @@ -2043,21 +1924,17 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Init the parse struct we will marshall into. */ - prs_init(&pd, 0, 4, MARSHALL); - - /* - * Setup the prs_struct to point at the memory we just - * allocated. - */ - - prs_give_memory( &pd, data, (uint32)sec_desc_size, False); + prs_init(&pd, sec_desc_size, 4, MARSHALL); /* * Finally, linearize into the outgoing buffer. */ - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - free_sec_desc(&psd); + if(!sec_io_desc( "sd data", psd, &pd, 1)) + { + free_sec_desc(psd); + safe_free(psd); + prs_mem_free(&pd); DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ security descriptor.\n")); /* @@ -2067,274 +1944,21 @@ security descriptor.\n")); } /* - * Now we can delete the security descriptor. - */ - - free_sec_desc(&psd); - - send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sec_desc_size); - return -1; -} - -/**************************************************************************** - Validate a SID. -****************************************************************************/ - -static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) -{ - extern DOM_SID global_sam_sid; - DOM_SID sid; - - if(!sd_sid) { - DEBUG(5,("validate_unix_sid: sid missing.\n")); - return False; - } - - sid_copy(psid, sd_sid); - sid_copy(&sid, sd_sid); - - if(!sid_split_rid(&sid, prid)) { - DEBUG(5,("validate_unix_sid: cannot get RID from sid.\n")); - return False; - } - - if(!sid_equal( &sid, &global_sam_sid)) { - DEBUG(5,("validate_unix_sid: sid is not ours.\n")); - return False; - } - - return True; -} - -/**************************************************************************** - Map NT perms to UNIX. -****************************************************************************/ - -#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) -#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) -#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) - -static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) -{ - mode_t mode = 0; - - switch(type) { - case S_IRUSR: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRUSR|S_IWUSR|S_IXUSR; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; - } - break; - case S_IRGRP: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRGRP|S_IWGRP|S_IXGRP; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; - } - break; - case S_IROTH: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IROTH|S_IWOTH|S_IXOTH; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; - } - break; - } - - return mode; -} - -/**************************************************************************** - Unpack a SEC_DESC into a owner, group and set of UNIX permissions. -****************************************************************************/ - -static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode, - uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) -{ - extern DOM_SID global_sid_World; - DOM_SID owner_sid; - DOM_SID grp_sid; - DOM_SID file_owner_sid; - DOM_SID file_grp_sid; - uint32 owner_rid; - uint32 grp_rid; - SEC_ACL *dacl = psd->dacl; - BOOL all_aces_are_inherit_only = (is_directory ? True : False); - int i; - - *pmode = 0; - *puser = (uid_t)-1; - *pgrp = (gid_t)-1; - - if(security_info_sent == 0) { - DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); - return False; - } - - /* - * Windows 2000 sends the owner and group SIDs as the logged in - * user, not the connected user. But it still sends the file - * owner SIDs on an ACL set. So we need to check for the file - * owner and group SIDs as well as the owner SIDs. JRA. - */ - - create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); - - /* - * Validate the owner and group SID's. - */ - - memset(&owner_sid, '\0', sizeof(owner_sid)); - memset(&grp_sid, '\0', sizeof(grp_sid)); - - DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n")); - - /* - * Don't immediately fail if the owner sid cannot be validated. - * This may be a group chown only set. - */ - - if(!validate_unix_sid( &owner_sid, &owner_rid, psd->owner_sid)) - DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); - else if(security_info_sent & OWNER_SECURITY_INFORMATION) - *puser = pdb_user_rid_to_uid(owner_rid); - - /* - * Don't immediately fail if the group sid cannot be validated. - * This may be an owner chown only set. - */ - - if(!validate_unix_sid( &grp_sid, &grp_rid, psd->grp_sid)) - DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); - else if(security_info_sent & GROUP_SECURITY_INFORMATION) - *pgrp = pdb_user_rid_to_gid(grp_rid); - - /* - * If no DACL then this is a chown only security descriptor. + * copy the data out of the marshalled structure */ - if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) { - *pmode = 0; - return True; - } + prs_give_memory( &pd, data, (uint32)sec_desc_size, False); /* - * Now go through the DACL and ensure that - * any owner/group sids match. + * Now we can delete the security descriptor. */ - for(i = 0; i < dacl->num_aces; i++) { - DOM_SID ace_sid; - SEC_ACE *psa = &dacl->ace[i]; - - if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && - (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); - return False; - } - - /* - * Ignore or remove bits we don't care about on a directory ACE. - */ - - if(is_directory) { - if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n")); - continue; - } - - /* - * At least one of the ACE entries wasn't inherit only. - * Flag this so we know the returned mode is valid. - */ + prs_mem_free(&pd); + free_sec_desc(psd); + safe_free(psd); - all_aces_are_inherit_only = False; - } - - /* - * Windows 2000 sets these flags even on *file* ACE's. This is wrong - * but we can ignore them for now. Revisit this when we go to POSIX - * ACLs on directories. - */ - - psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); - - if(psa->flags != 0) { - DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", - (unsigned int)psa->flags)); - return False; - } - - /* - * The security mask may be UNIX_ACCESS_NONE which should map into - * no permissions (we overload the WRITE_OWNER bit for this) or it - * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this - * to be so. Any other bits override the UNIX_ACCESS_NONE bit. - */ - - psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| - GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); - - if(psa->info.mask != UNIX_ACCESS_NONE) - psa->info.mask &= ~UNIX_ACCESS_NONE; - - sid_copy(&ace_sid, &psa->sid); - - if(sid_equal(&ace_sid, &file_owner_sid)) { - /* - * Map the desired permissions into owner perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRUSR); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); - - } else if( sid_equal(&ace_sid, &file_grp_sid)) { - /* - * Map the desired permissions into group perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRGRP); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRGRP)); - - } else if( sid_equal(&ace_sid, &global_sid_World)) { - /* - * Map the desired permissions into other perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IROTH); - else - *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); - - } else { - DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n")); - return False; - } - } - - if (is_directory && all_aces_are_inherit_only) { - /* - * Windows 2000 is doing one of these weird 'inherit acl' - * traverses to conserve NTFS ACL resources. Just pretend - * there was no DACL sent. JRA. - */ - - DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); - free_sec_acl(&psd->dacl); - } - - return True; + send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sec_desc_size); + return -1; } /**************************************************************************** @@ -2350,7 +1974,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *params= *ppparams; char *data = *ppdata; prs_struct pd; - SEC_DESC *psd = NULL; + SEC_DESC psd; uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); uid_t user = (uid_t)-1; gid_t grp = (gid_t)-1; @@ -2391,8 +2015,10 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, * Finally, unmarshall from the data buffer. */ - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + if(!sec_io_desc( "sd data", &psd, &pd, 1)) + { free_sec_desc(&psd); + prs_mem_free(&pd); DEBUG(0,("call_nt_transact_set_security_desc: Error in unmarshalling \ security descriptor.\n")); /* @@ -2401,6 +2027,12 @@ security descriptor.\n")); return(UNIXERROR(ERRDOS,ERRnoaccess)); } + /* + * finished with the marshalling structure, already + */ + + prs_mem_free(&pd); + /* * Get the current state of the file. */ @@ -2429,12 +2061,12 @@ security descriptor.\n")); * Unpack the user/group/world id's and permissions. */ - if(!unpack_nt_permissions( &sbuf, &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) { + if(!convertperms_sd_to_unix( &sbuf, &user, &grp, &perms, security_info_sent, &psd, fsp->is_directory)) { free_sec_desc(&psd); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (psd->dacl != NULL) + if (psd.dacl != NULL) got_dacl = True; free_sec_desc(&psd); -- cgit From 712a30ed51ca2b58e00d38a5d6d70d564b1da11b Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 27 May 2000 09:19:57 +0000 Subject: prs_give_memory in wrong place, also poss. was losing mem. (This used to be commit 9805e17cd0ce427c329a8b5a8318d5f75227e283) --- source3/smbd/nttrans.c | 14 +++++++------- source3/smbd/process.c | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a149374114..bb0436aab3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1924,7 +1924,13 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Init the parse struct we will marshall into. */ - prs_init(&pd, sec_desc_size, 4, MARSHALL); + prs_init(&pd, 0, 4, MARSHALL); + + /* + * copy the data out of the marshalled structure + */ + + prs_give_memory( &pd, data, (uint32)sec_desc_size, False); /* * Finally, linearize into the outgoing buffer. @@ -1943,12 +1949,6 @@ security descriptor.\n")); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - /* - * copy the data out of the marshalled structure - */ - - prs_give_memory( &pd, data, (uint32)sec_desc_size, False); - /* * Now we can delete the security descriptor. */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9e5b7b1477..74ec3b64db 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -408,6 +408,29 @@ struct smb_message_struct {SMBgetmac,"SMBgetmac",NULL,AS_GUEST} }; +/******************************************************************* +dump a prs to a file + ********************************************************************/ +static void smb_dump(char *name, int type, char *data, ssize_t len) +{ + int fd, i; + pstring fname; + if (DEBUGLEVEL < 50) return; + + if (len < 4) len = smb_buflen(data); + for (i=1;i<100;i++) { + slprintf(fname,sizeof(fname), "/tmp/%s.%d.%s", name, i, + type ? "req" : "resp"); + fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644); + if (fd != -1 || errno != EEXIST) break; + } + if (fd != -1) { + write(fd, data, len); + close(fd); + DEBUG(0,("created %s len %d\n", fname, len)); + } +} + /**************************************************************************** do a switch on the message type, and return the response size @@ -445,12 +468,14 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if (match == num_smb_messages) { DEBUG(0,("Unknown message type %d!\n",type)); + smb_dump("Unknown", 1, inbuf, size); outsize = reply_unknown(inbuf,outbuf); } else { DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,(int)pid)); + smb_dump(smb_messages[match].name, 1, inbuf, size); if(global_oplock_break) { int flags = smb_messages[match].flags; @@ -548,6 +573,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize } } + smb_dump(smb_messages[match].name, 0, outbuf, outsize); + return(outsize); } -- cgit From 62707533f72f7a2438c8e5c918b4cb75470cd871 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 28 May 2000 20:11:04 +0000 Subject: debug output to /tmp. (This used to be commit f9077e50cba5c7c3e6cf7739888120d8cc757c7c) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 74ec3b64db..077a97ed64 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -417,7 +417,7 @@ static void smb_dump(char *name, int type, char *data, ssize_t len) pstring fname; if (DEBUGLEVEL < 50) return; - if (len < 4) len = smb_buflen(data); + if (len < 4) len = smb_len(data)+4; for (i=1;i<100;i++) { slprintf(fname,sizeof(fname), "/tmp/%s.%d.%s", name, i, type ? "req" : "resp"); -- cgit From a811ade9aa5871d609a33e9141333bd91955e12d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 May 2000 17:51:28 +0000 Subject: Fixed interface between new ACLS and nttrans code. Jeremy. (This used to be commit 400263245b4e5344b496c5de52a659f040206798) --- source3/smbd/nttrans.c | 195 +--------------- source3/smbd/unix_acls.c | 574 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 586 insertions(+), 183 deletions(-) create mode 100644 source3/smbd/unix_acls.c (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bb0436aab3..6c677f3f4c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1822,41 +1822,6 @@ name = %s\n", fsp->fsp_name )); return -1; } -/**************************************************************************** - Reply to query a security descriptor from an fsp. If it succeeds it allocates - the space for the return elements and returns True. -****************************************************************************/ - -static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) -{ - SMB_STRUCT_STAT sbuf; - mode_t mode; - - if(fsp->is_directory || fsp->fd == -1) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { - return 0; - } - } else { - if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { - return 0; - } - } - - if(fsp->is_directory) { - /* - * For directory ACLs we also add in the inherited permissions - * ACE entries. These are the permissions a file would get when - * being created in the directory. - */ - mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - } - else - { - mode = sbuf.st_mode; - } - return convertperms_unix_to_sd(&sbuf, fsp->is_directory, mode, ppdesc); -} - /**************************************************************************** Reply to query a security descriptor - currently this is not implemented (it is planned to be though). Right now it just returns the same thing NT would @@ -1899,8 +1864,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if(max_data_count < sec_desc_size) { - free_sec_desc(psd); - safe_free(psd); + free_sec_desc(&psd); send_nt_replies(inbuf, outbuf, bufsize, 0xC0000000|NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); @@ -1913,8 +1877,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, data = *ppdata = Realloc(*ppdata, sec_desc_size); if(data == NULL) { - free_sec_desc(psd); - safe_free(psd); + free_sec_desc(&psd); return(ERROR(ERRDOS,ERRnomem)); } @@ -1927,7 +1890,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, prs_init(&pd, 0, 4, MARSHALL); /* - * copy the data out of the marshalled structure + * Setup the prs_struct to point at the memory we just + * allocated. */ prs_give_memory( &pd, data, (uint32)sec_desc_size, False); @@ -1936,11 +1900,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Finally, linearize into the outgoing buffer. */ - if(!sec_io_desc( "sd data", psd, &pd, 1)) - { - free_sec_desc(psd); - safe_free(psd); - prs_mem_free(&pd); + if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + free_sec_desc(&psd); DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ security descriptor.\n")); /* @@ -1953,9 +1914,7 @@ security descriptor.\n")); * Now we can delete the security descriptor. */ - prs_mem_free(&pd); - free_sec_desc(psd); - safe_free(psd); + free_sec_desc(&psd); send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sec_desc_size); return -1; @@ -1974,15 +1933,10 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *params= *ppparams; char *data = *ppdata; prs_struct pd; - SEC_DESC psd; + SEC_DESC *psd = NULL; uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); - uid_t user = (uid_t)-1; - gid_t grp = (gid_t)-1; - mode_t perms = 0; - SMB_STRUCT_STAT sbuf; files_struct *fsp = NULL; uint32 security_info_sent = 0; - BOOL got_dacl = False; if(!lp_nt_acl_support()) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2015,10 +1969,8 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, * Finally, unmarshall from the data buffer. */ - if(!sec_io_desc( "sd data", &psd, &pd, 1)) - { + if(!sec_io_desc( "sd data", &psd, &pd, 1)) { free_sec_desc(&psd); - prs_mem_free(&pd); DEBUG(0,("call_nt_transact_set_security_desc: Error in unmarshalling \ security descriptor.\n")); /* @@ -2027,135 +1979,12 @@ security descriptor.\n")); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - /* - * finished with the marshalling structure, already - */ - - prs_mem_free(&pd); - - /* - * Get the current state of the file. - */ - - if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { - free_sec_desc(&psd); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } else { - - int ret; - - if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); - else - ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); - - if(ret != 0) { - free_sec_desc(&psd); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } - - /* - * Unpack the user/group/world id's and permissions. - */ - - if(!convertperms_sd_to_unix( &sbuf, &user, &grp, &perms, security_info_sent, &psd, fsp->is_directory)) { - free_sec_desc(&psd); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if (!set_nt_acl(fsp, psd)) { + free_sec_desc(&psd); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (psd.dacl != NULL) - got_dacl = True; - free_sec_desc(&psd); - - /* - * Do we need to chown ? - */ - - if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { - - DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - - if(dos_chown( fsp->fsp_name, user, grp) == -1) { - DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - /* - * Recheck the current state of the file, which may have changed. - * (suid/sgid bits, for instance) - */ - - if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } else { - - int ret; - - if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); - else - ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); - - if(ret != 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } - - /* - * Only change security if we got a DACL. - */ - - if((security_info_sent & DACL_SECURITY_INFORMATION) && got_dacl) { - - /* - * Check to see if we need to change anything. - * Enforce limits on modified bits *only*. Don't enforce masks - * on bits not changed by the user. - */ - - if(fsp->is_directory) { - - perms &= (lp_dir_security_mask(SNUM(conn)) | sbuf.st_mode); - perms |= (lp_force_dir_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); - - } else { - - perms &= (lp_security_mask(SNUM(conn)) | sbuf.st_mode); - perms |= (lp_force_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); - - } - - /* - * Preserve special bits. - */ - - perms |= (sbuf.st_mode & ~0777); - - /* - * Do we need to chmod ? - */ - - if(sbuf.st_mode != perms) { - - DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", - fsp->fsp_name, (unsigned int)perms )); - - if(conn->vfs_ops.chmod(dos_to_unix(fsp->fsp_name, False), perms) == -1) { - DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)perms, strerror(errno) )); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } - } - send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); return -1; } diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c new file mode 100644 index 0000000000..706170b264 --- /dev/null +++ b/source3/smbd/unix_acls.c @@ -0,0 +1,574 @@ +#define OLD_NTDOMAIN 1 +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB NT Security Descriptor / Unix permission conversion. + Copyright (C) Jeremy Allison 1994-2000 + + 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" + +/**************************************************************************** + Function to create owner and group SIDs from a SMB_STRUCT_STAT. +****************************************************************************/ + +static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) +{ + extern DOM_SID global_sam_sid; + + sid_copy(powner_sid, &global_sam_sid); + sid_copy(pgroup_sid, &global_sam_sid); + sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); + sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); +} + +/**************************************************************************** + Map unix perms to NT. +****************************************************************************/ + +static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w_mask, int x_mask, BOOL is_directory) +{ + SEC_ACCESS sa; + uint32 nt_mask = 0; + + *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; + + if((perm & (r_mask|w_mask|x_mask)) == (r_mask|w_mask|x_mask)) { + nt_mask = UNIX_ACCESS_RWX; + } else if((perm & (r_mask|w_mask|x_mask)) == 0) { + nt_mask = UNIX_ACCESS_NONE; + } else { + nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; + if(is_directory) + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + else + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; + } + init_sec_access(&sa,nt_mask); + return sa; +} + +/**************************************************************************** + Validate a SID. +****************************************************************************/ + +static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) +{ + extern DOM_SID global_sam_sid; + DOM_SID sid; + + if(!sd_sid) { + DEBUG(5,("validate_unix_sid: sid missing.\n")); + return False; + } + + sid_copy(psid, sd_sid); + sid_copy(&sid, sd_sid); + + if(!sid_split_rid(&sid, prid)) { + DEBUG(5,("validate_unix_sid: cannot get RID from sid.\n")); + return False; + } + + if(!sid_equal( &sid, &global_sam_sid)) { + DEBUG(5,("validate_unix_sid: sid is not ours.\n")); + return False; + } + + return True; +} + +/**************************************************************************** + Map NT perms to UNIX. +****************************************************************************/ + +#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) +#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) +#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) + +static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) +{ + mode_t mode = 0; + + switch(type) { + case S_IRUSR: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRUSR|S_IWUSR|S_IXUSR; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; + } + break; + case S_IRGRP: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRGRP|S_IWGRP|S_IXGRP; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; + } + break; + case S_IROTH: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IROTH|S_IWOTH|S_IXOTH; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; + } + break; + } + + return mode; +} + +/**************************************************************************** + Unpack a SEC_DESC into a owner, group and set of UNIX permissions. +****************************************************************************/ + +static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode, + uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) +{ + extern DOM_SID global_sid_World; + DOM_SID owner_sid; + DOM_SID grp_sid; + DOM_SID file_owner_sid; + DOM_SID file_grp_sid; + uint32 owner_rid; + uint32 grp_rid; + SEC_ACL *dacl = psd->dacl; + BOOL all_aces_are_inherit_only = (is_directory ? True : False); + int i; + + *pmode = 0; + *puser = (uid_t)-1; + *pgrp = (gid_t)-1; + + if(security_info_sent == 0) { + DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); + return False; + } + + /* + * Windows 2000 sends the owner and group SIDs as the logged in + * user, not the connected user. But it still sends the file + * owner SIDs on an ACL set. So we need to check for the file + * owner and group SIDs as well as the owner SIDs. JRA. + */ + + create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); + + /* + * Validate the owner and group SID's. + */ + + memset(&owner_sid, '\0', sizeof(owner_sid)); + memset(&grp_sid, '\0', sizeof(grp_sid)); + + DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n")); + + /* + * Don't immediately fail if the owner sid cannot be validated. + * This may be a group chown only set. + */ + + if(!validate_unix_sid( &owner_sid, &owner_rid, psd->owner_sid)) + DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); + else if(security_info_sent & OWNER_SECURITY_INFORMATION) + *puser = pdb_user_rid_to_uid(owner_rid); + + /* + * Don't immediately fail if the group sid cannot be validated. + * This may be an owner chown only set. + */ + + if(!validate_unix_sid( &grp_sid, &grp_rid, psd->grp_sid)) + DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); + else if(security_info_sent & GROUP_SECURITY_INFORMATION) + *pgrp = pdb_user_rid_to_gid(grp_rid); + + /* + * If no DACL then this is a chown only security descriptor. + */ + + if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) { + *pmode = 0; + return True; + } + + /* + * Now go through the DACL and ensure that + * any owner/group sids match. + */ + + for(i = 0; i < dacl->num_aces; i++) { + DOM_SID ace_sid; + SEC_ACE *psa = &dacl->ace[i]; + + if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && + (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { + DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); + return False; + } + + /* + * Ignore or remove bits we don't care about on a directory ACE. + */ + + if(is_directory) { + if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n")); + continue; + } + + /* + * At least one of the ACE entries wasn't inherit only. + * Flag this so we know the returned mode is valid. + */ + + all_aces_are_inherit_only = False; + } + + /* + * Windows 2000 sets these flags even on *file* ACE's. This is wrong + * but we can ignore them for now. Revisit this when we go to POSIX + * ACLs on directories. + */ + + psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); + + if(psa->flags != 0) { + DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", + (unsigned int)psa->flags)); + return False; + } + + /* + * The security mask may be UNIX_ACCESS_NONE which should map into + * no permissions (we overload the WRITE_OWNER bit for this) or it + * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this + * to be so. Any other bits override the UNIX_ACCESS_NONE bit. + */ + + psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| + GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); + + if(psa->info.mask != UNIX_ACCESS_NONE) + psa->info.mask &= ~UNIX_ACCESS_NONE; + + sid_copy(&ace_sid, &psa->sid); + + if(sid_equal(&ace_sid, &file_owner_sid)) { + /* + * Map the desired permissions into owner perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IRUSR); + else + *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); + + } else if( sid_equal(&ace_sid, &file_grp_sid)) { + /* + * Map the desired permissions into group perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IRGRP); + else + *pmode &= ~(map_nt_perms( psa->info, S_IRGRP)); + + } else if( sid_equal(&ace_sid, &global_sid_World)) { + /* + * Map the desired permissions into other perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IROTH); + else + *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); + + } else { + DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n")); + return False; + } + } + + if (is_directory && all_aces_are_inherit_only) { + /* + * Windows 2000 is doing one of these weird 'inherit acl' + * traverses to conserve NTFS ACL resources. Just pretend + * there was no DACL sent. JRA. + */ + + DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); + free_sec_acl(&psd->dacl); + } + + return True; +} + +/**************************************************************************** + Reply to query a security descriptor from an fsp. If it succeeds it allocates + the space for the return elements and returns the size needed to return the + security descriptor. This should be the only external function needed for + the UNIX style get ACL. +****************************************************************************/ + +size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) +{ + extern DOM_SID global_sid_World; + SMB_STRUCT_STAT sbuf; + SEC_ACE ace_list[6]; + DOM_SID owner_sid; + DOM_SID group_sid; + size_t sec_desc_size; + SEC_ACL *psa = NULL; + SEC_ACCESS owner_access; + int owner_acl_type; + SEC_ACCESS group_access; + int grp_acl_type; + SEC_ACCESS other_access; + int other_acl_type; + int num_acls = 0; + + *ppdesc = NULL; + + if(!lp_nt_acl_support()) { + sid_copy( &owner_sid, &global_sid_World); + sid_copy( &group_sid, &global_sid_World); + } else { + + if(fsp->is_directory || fsp->fd == -1) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + return 0; + } + } else { + if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + return 0; + } + } + + /* + * Get the owner, group and world SIDs. + */ + + create_file_sids(&sbuf, &owner_sid, &group_sid); + + /* + * Create the generic 3 element UNIX acl. + */ + + owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, + S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); + group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, + S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); + other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, + S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); + + if(owner_access.mask) + init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, + owner_access, 0); + + if(group_access.mask) + init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, + group_access, 0); + + if(other_access.mask) + init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, + other_access, 0); + + if(fsp->is_directory) { + /* + * For directory ACLs we also add in the inherited permissions + * ACE entries. These are the permissions a file would get when + * being created in the directory. + */ + mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); + + owner_access = map_unix_perms(&owner_acl_type, mode, + S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); + group_access = map_unix_perms(&grp_acl_type, mode, + S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); + other_access = map_unix_perms(&other_acl_type, mode, + S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); + + if(owner_access.mask) + init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, + owner_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + + if(group_access.mask) + init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, + group_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + + if(other_access.mask) + init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, + other_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + } + + if(num_acls) + if((psa = make_sec_acl( 3, num_acls, ace_list)) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); + return 0; + } + } + + *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sec_desc_size); + + if(!*ppdesc) { + DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); + sec_desc_size = 0; + } + + free_sec_acl(&psa); + + return sec_desc_size; +} + +/**************************************************************************** + Reply to set a security descriptor on an fsp. If it succeeds it returns + This should be the only external function needed for the UNIX style set ACL. +****************************************************************************/ + +BOOL set_nt_acl(files_struct *fsp, SEC_DESC *pdesc) +{ + uid_t user = (uid_t)-1; + gid_t grp = (gid_t)-1; + mode_t perms = 0; + SMB_STRUCT_STAT sbuf; + BOOL got_dacl = False; + + /* + * Get the current state of the file. + */ + + if(fsp->is_directory) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) + return False; + } else { + + int ret; + + if(fsp->fd == -1) + ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + else + ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); + + if(ret != 0) + return False; + } + + /* + * Unpack the user/group/world id's and permissions. + */ + + if (!unpack_nt_permissions( &sbuf, &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) + return False; + + if (psd->dacl != NULL) + got_dacl = True; + + /* + * Do we need to chown ? + */ + + if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { + + DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); + + if(dos_chown( fsp->fsp_name, user, grp) == -1) { + DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); + return False; + } + + /* + * Recheck the current state of the file, which may have changed. + * (suid/sgid bits, for instance) + */ + + if(fsp->is_directory) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + return False; + } + } else { + + int ret; + + if(fsp->fd == -1) + ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + else + ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); + + if(ret != 0) + return False; + } + } + + /* + * Only change security if we got a DACL. + */ + + if((security_info_sent & DACL_SECURITY_INFORMATION) && got_dacl) { + + /* + * Check to see if we need to change anything. + * Enforce limits on modified bits *only*. Don't enforce masks + * on bits not changed by the user. + */ + + if(fsp->is_directory) { + + perms &= (lp_dir_security_mask(SNUM(conn)) | sbuf.st_mode); + perms |= (lp_force_dir_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + + } else { + + perms &= (lp_security_mask(SNUM(conn)) | sbuf.st_mode); + perms |= (lp_force_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + + } + + /* + * Preserve special bits. + */ + + perms |= (sbuf.st_mode & ~0777); + + /* + * Do we need to chmod ? + */ + + if(sbuf.st_mode != perms) { + + DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", + fsp->fsp_name, (unsigned int)perms )); + + if(conn->vfs_ops.chmod(dos_to_unix(fsp->fsp_name, False), perms) == -1) { + DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)perms, strerror(errno) )); + return False; + } + } + } + + return True; +} +#undef OLD_NTDOMAIN -- cgit From 6c96a55ef55acc77328e4dcf8cabb89e1936e5c9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 May 2000 17:56:08 +0000 Subject: Working UNIX -> NT ACL mapper. Jeremy. (This used to be commit f09c53f6b15e96ab1d306c044cbdcd086006c977) --- source3/smbd/unix_acls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 706170b264..08dfbc0006 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -442,12 +442,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } /**************************************************************************** - Reply to set a security descriptor on an fsp. If it succeeds it returns + Reply to set a security descriptor on an fsp. security_info_sent is the + description of the following NT ACL. This should be the only external function needed for the UNIX style set ACL. ****************************************************************************/ -BOOL set_nt_acl(files_struct *fsp, SEC_DESC *pdesc) +BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) { + connection_struct *conn = fsp->conn; uid_t user = (uid_t)-1; gid_t grp = (gid_t)-1; mode_t perms = 0; -- cgit From e743e2b7073d7af540202f1c410f1acbab9b4131 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 May 2000 17:56:47 +0000 Subject: Changed interface to set_nt_acl slightly. Jeremy. (This used to be commit 4534eae405f952d4b93e445571fc487e66a7541b) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6c677f3f4c..68844f2bca 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1979,7 +1979,7 @@ security descriptor.\n")); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (!set_nt_acl(fsp, psd)) { + if (!set_nt_acl(fsp, security_info_sent, psd)) { free_sec_desc(&psd); return(UNIXERROR(ERRDOS,ERRnoaccess)); } -- cgit From f0080e5a3979fac94d6668cf6ee9d9f61302839c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Jun 2000 17:01:34 +0000 Subject: Getting back to a compilable state (not there yet but close). Added patches for random -> sys_random. Added set_effective_xxx patches for AFS code. Memory allocation changes in spoolss code. Jeremy. (This used to be commit c2099cfb033c2cdb6035f4f7f50ce21b98e1584d) --- source3/smbd/conn.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index ebd18861fc..0e74b62ee0 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -168,11 +168,14 @@ void conn_free(connection_struct *conn) { /* Free vfs_connection_struct */ +#ifdef HAVE_LIBDL if (conn->vfs_conn != NULL) { /* Close dlopen() handle */ if (conn->vfs_conn->dl_handle) { dlclose(conn->vfs_conn->dl_handle); } +#endif /* HAVE_LIBDL */ + if (conn->vfs_conn->groups != NULL) { free(conn->vfs_conn->groups); } -- cgit From b9fedcb2de5612bdb4e763fe0788e1a4a9c16d33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Jun 2000 21:00:37 +0000 Subject: param/loadparm.c: Looks like someone ran indent on this ! passdb/smbpass.c: Insure uninitialized memory reference fix. printing/nt_printing.c: rpc_server/srv_spoolss_nt.c: Insure memory leak fixes. smbd/unix_acls.c: Shadow ref fix. Jeremy. (This used to be commit d175d3ebefc053e9badd91ca5f2d8bd03eb6705d) --- source3/smbd/unix_acls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 08dfbc0006..40bb281c74 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -338,7 +338,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) SEC_ACE ace_list[6]; DOM_SID owner_sid; DOM_SID group_sid; - size_t sec_desc_size; + size_t sd_size; SEC_ACL *psa = NULL; SEC_ACCESS owner_access; int owner_acl_type; @@ -429,16 +429,16 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } } - *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sec_desc_size); + *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sd_size); if(!*ppdesc) { DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); - sec_desc_size = 0; + sd_size = 0; } free_sec_acl(&psa); - return sec_desc_size; + return sd_size; } /**************************************************************************** -- cgit From 5a5540f87a89224397d791f4fe8093be214e1f15 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Jun 2000 00:53:07 +0000 Subject: rpc_client/cli_lsarpc.c: Removed unused variable. rpc_server/srv_spoolss_nt.c: Fixed more memory leaks. smbd/nttrans.c: Fixed shadow variable problem. Jeremy. (This used to be commit f0a7540831181d3a47e7f8ce8be55a36a2f2aba1) --- source3/smbd/nttrans.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 68844f2bca..e3874e1b3e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1838,7 +1838,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *data = *ppdata; prs_struct pd; SEC_DESC *psd = NULL; - size_t sec_desc_size; + size_t sd_size; files_struct *fsp = file_fsp(params,0); @@ -1855,14 +1855,14 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Get the permissions to return. */ - if((sec_desc_size = get_nt_acl(fsp, &psd)) == 0) + if((sd_size = get_nt_acl(fsp, &psd)) == 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("call_nt_transact_query_security_desc: sec_desc_size = %d.\n",(int)sec_desc_size)); + DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size)); - SIVAL(params,0,(uint32)sec_desc_size); + SIVAL(params,0,(uint32)sd_size); - if(max_data_count < sec_desc_size) { + if(max_data_count < sd_size) { free_sec_desc(&psd); @@ -1875,13 +1875,13 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Allocate the data we will point this at. */ - data = *ppdata = Realloc(*ppdata, sec_desc_size); + data = *ppdata = Realloc(*ppdata, sd_size); if(data == NULL) { free_sec_desc(&psd); return(ERROR(ERRDOS,ERRnomem)); } - memset(data, '\0', sec_desc_size); + memset(data, '\0', sd_size); /* * Init the parse struct we will marshall into. @@ -1894,7 +1894,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * allocated. */ - prs_give_memory( &pd, data, (uint32)sec_desc_size, False); + prs_give_memory( &pd, data, (uint32)sd_size, False); /* * Finally, linearize into the outgoing buffer. @@ -1916,7 +1916,7 @@ security descriptor.\n")); free_sec_desc(&psd); - send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sec_desc_size); + send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sd_size); return -1; } -- cgit From da44845a0907bc6c9da9aabc0374b8280a85017f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Jun 2000 06:22:19 +0000 Subject: moved secrets fns into secrets.c (This used to be commit f890bcf06786e7c63bf76fad2fd46d287a99a270) --- source3/smbd/password.c | 2 +- source3/smbd/process.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 614e5a84fc..d3a728bf42 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1437,7 +1437,7 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password for our primary domain */ - if (!get_trust_account_password(lp_workgroup(), trust_passwd, NULL)) + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, NULL)) { return False; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 077a97ed64..82e61a138e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -948,7 +948,7 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t * First, open the machine password file with an exclusive lock. */ - if(!get_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) { + if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) { DEBUG(0,("process: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname, global_myworkgroup )); return True; -- cgit From 0164047afbd082b0003147845a72ca08b4781b81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Jun 2000 01:49:23 +0000 Subject: Fixing get/set of security descriptors. Removed ugly hack for NT printing. Fixed up tdb parse stuff memory leaks. Jeremy. (This used to be commit 8ef41f31c53e14ad057d883810a1cd2301fede2a) --- source3/smbd/lanman.c | 2 ++ source3/smbd/nttrans.c | 5 ++++- source3/smbd/pipes.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fe2cc3ae7d..cfc0e08d47 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -776,6 +776,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, desc.subcount = count; fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); } else if(uLevel == 0) { +#if 0 /* * This is a *disgusting* hack. * This is *so* bad that even I'm embarrassed (and I @@ -795,6 +796,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, */ fail_next_srvsvc_open(); +#endif } *rdata_len = desc.usedlen; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e3874e1b3e..aad09a75b6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -487,6 +487,7 @@ to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access, return smb_open_mode; } +#if 0 /* * This is a *disgusting* hack. * This is *so* bad that even I'm embarrassed (and I @@ -547,7 +548,7 @@ BOOL should_fail_next_srvsvc_open(const char *pipename) } return False; } - +#endif /**************************************************************************** Reply to an NT create and X call on a pipe. @@ -573,8 +574,10 @@ static int nt_open_pipe(char *fname, connection_struct *conn, /* Strip \\ off the name. */ fname++; +#if 0 if(should_fail_next_srvsvc_open(fname)) return (ERROR(ERRSRV,ERRaccess)); +#endif DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index c1d5c261fe..df7141764c 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -74,11 +74,13 @@ int reply_open_pipe_and_X(connection_struct *conn, /* Strip \PIPE\ off the name. */ pstrcpy(fname,smb_buf(inbuf) + PIPELEN); +#if 0 /* * Hack for NT printers... JRA. */ if(should_fail_next_srvsvc_open(fname)) return(ERROR(ERRSRV,ERRaccess)); +#endif /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ -- cgit From b2eef912cfaf768fd26b3b2acbcfc0be2951a197 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Jun 2000 00:17:05 +0000 Subject: Cause printer SD's to be displayed correctly (full control). Jeremy. (This used to be commit 341d07c516865bdd9be99f98cd0754d12b25f9c0) --- source3/smbd/unix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 40bb281c74..7a2dc6ab6e 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -423,7 +423,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } if(num_acls) - if((psa = make_sec_acl( 3, num_acls, ace_list)) == NULL) { + if((psa = make_sec_acl( ACL_REVISION, num_acls, ace_list)) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); return 0; } -- cgit From bda48b382477f2a6478ebd86b67cb63ac391854e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Jun 2000 07:40:55 +0000 Subject: - changed HAVE_KERNEL_OPLOCKS to HAVE_KERNEL_OPLOCKS_IRIX - added autoconf test for HAVE_KERNEL_OPLOCKS_LINUX (This used to be commit 0368f68529a9244663c199068e95d1a1d93152fa) --- source3/smbd/oplock.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ef43400074..5484728122 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -30,7 +30,7 @@ static int oplock_sock = -1; uint16 global_oplock_port = 0; static int oplock_pipe_read = -1; -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) static int oplock_pipe_write = -1; #endif @@ -59,7 +59,7 @@ int32 get_number_of_exclusive_open_oplocks(void) BOOL setup_kernel_oplock_pipe(void) { -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) if(lp_kernel_oplocks()) { int pfd[2]; @@ -72,7 +72,7 @@ BOOL setup_kernel_oplock_pipe(void) oplock_pipe_read = pfd[0]; oplock_pipe_write = pfd[1]; } -#endif /* HAVE_KERNEL_OPLOCKS */ +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ return True; } @@ -164,7 +164,7 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou } } -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) if(FD_ISSET(oplock_pipe_read,fds)) { /* * Deal with the kernel <--> smbd @@ -231,7 +231,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); return True; } -#endif /* HAVE_KERNEL_OPLOCKS */ +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ /* * From here down we deal with the smbd <--> smbd @@ -279,7 +279,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); static BOOL set_kernel_oplock(files_struct *fsp, int oplock_type) { -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) if(lp_kernel_oplocks()) { if(fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { @@ -300,7 +300,7 @@ inode = %.0f. Another process had the file open.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); } -#endif /* HAVE_KERNEL_OPLOCKS */ +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ return True; } @@ -334,7 +334,7 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) static void release_kernel_oplock(files_struct *fsp) { -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) if(lp_kernel_oplocks()) { @@ -365,7 +365,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, } } } -#endif /* HAVE_KERNEL_OPLOCKS */ +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ } @@ -508,7 +508,7 @@ BOOL process_local_message(char *buffer, int buf_size) switch(break_cmd_type) { -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) case KERNEL_OPLOCK_BREAK_CMD: /* Ensure that the msg length is correct. */ if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) @@ -527,7 +527,7 @@ should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); } break; -#endif /* HAVE_KERNEL_OPLOCKS */ +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ case OPLOCK_BREAK_CMD: case LEVEL_II_OPLOCK_BREAK_CMD: @@ -1238,7 +1238,7 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) if((reply_msg_len != OPLOCK_BREAK_MSG_LEN) && (reply_msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN)) #else if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) @@ -1335,7 +1335,7 @@ void check_kernel_oplocks(void) done = True; lp_set_kernel_oplocks(False); -#if defined(HAVE_KERNEL_OPLOCKS) +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) { int fd; int pfd[2]; @@ -1391,7 +1391,7 @@ Disabling kernel oplock support.\n", strerror(errno) )); lp_kernel_oplocks() ? "True" : "False" )); } -#endif /* HAVE_KERNEL_OPLOCKS */ +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ } #undef OLD_NTDOMAIN -- cgit From 84d40095e1d7ba5c66cabfd2d41012162d652970 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 8 Jun 2000 13:56:07 +0000 Subject: added a NET_USER_INFO_3 struct to user_struct. register_vuid fills it with constructed info. (This used to be commit b1889e4334012b1b2caa604b859da4271509fc87) --- source3/smbd/password.c | 35 ++++++++++++++++++++++++++++++++++- source3/smbd/reply.c | 5 ++++- 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index d3a728bf42..5815bbd164 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -214,7 +214,8 @@ has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest) + char *domain,BOOL guest, + NET_USER_INFO_3 *usr) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -274,6 +275,38 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, &vuser->n_groups, &vuser->groups); + if (usr == NULL) + { + int i; + extern DOM_SID global_sam_sid; + + DEBUG(0,("vuser struct usr being filled in with trash, today\n")); + DEBUG(0,("this needs to be replaced with a proper surs impl.\n")); + DEBUG(0,("e.g. the one used in winbindd. in fact, all\n")); + DEBUG(0,("occurrences of pdb_xxx_to_xxx should be replaced\n")); + DEBUG(0,("as soon as possible.\n")); + vuser->usr.user_id = pdb_uid_to_user_rid(uid); + vuser->usr.group_id = pdb_gid_to_group_rid(gid); + vuser->usr.num_groups = vuser->n_groups; + for (i = 0; i < vuser->usr.num_groups; i++) + { + DOM_GID *ntgid = &vuser->usr.gids[i]; + ntgid->attr = 0x7; + ntgid->g_rid = pdb_gid_to_group_rid(vuser->groups[i]); + } + + /* this is possibly the worst thing to do, ever. it assumes */ + /* that all users of this system are in the local SAM database */ + /* however, because there is no code to do anything otherwise, */ + /* we have no choice */ + + init_dom_sid2(&vuser->usr.dom_sid, &global_sam_sid); + } + else + { + vuser->usr = *usr; + } + DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9845853349..f9c0695a39 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1000,7 +1000,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest); + + DEBUG(0,("must call domain_client_validate() which returns a ")); + DEBUG(0,("NET_USER_INFO_3 structure to pass to register_vuid()")); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest, NULL); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From 28555ec92e061aafb31a9b071caf00e44132c70f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Jun 2000 17:50:19 +0000 Subject: include/smb.h: Removed NET_USER_3 struct from user struct. It doesn't belong there (yet) as there is no infrastructure for it. Replaced it with a dynamic array of group SIDs plus a user. passdb/passdb.c: Added setup_user_sids() function. This is where the lookup should be done, eventually calling winbind. smbd/password.c: Changed to call setup_user_sids(). Removed spurious DEBUG(0) statements. smbd/reply.c: Removed extra parameter to register_vuid(). Jeremy. (This used to be commit 425f4ad9a5e0e7d49620276100ade7a0cae47011) --- source3/smbd/password.c | 81 +++++++++++++++++-------------------------------- source3/smbd/reply.c | 4 +-- 2 files changed, 29 insertions(+), 56 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 5815bbd164..b8f5c5cf84 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -117,20 +117,27 @@ invalidate a uid ****************************************************************************/ void invalidate_vuid(uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); + user_struct *vuser = get_valid_user_struct(vuid); - if (vuser == NULL) return; + if (vuser == NULL) + return; - vuser->uid = (uid_t)-1; - vuser->gid = (gid_t)-1; + vuser->uid = (uid_t)-1; + vuser->gid = (gid_t)-1; - /* same number of igroups as groups */ - vuser->n_groups = 0; + ZERO_STRUCT(vuser->user_sid); - if (vuser->groups) - free((char *)vuser->groups); + /* same number of igroups as groups */ + vuser->n_groups = 0; - vuser->groups = NULL; + if (vuser->groups) + free((char *)vuser->groups); + + if (vuser->group_sids) + free((char *)vuser->group_sids); + + vuser->groups = NULL; + vuser->group_sids = NULL; } @@ -207,15 +214,14 @@ int setup_groups(char *user, char *domain, return 0; } - /**************************************************************************** -register a uid/name pair as being valid and that a valid password -has been given. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. + Register a uid/name pair as being valid and that a valid password + has been given. vuid is biased by an offset. This allows us to + tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ + uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest, - NET_USER_INFO_3 *usr) + char *domain,BOOL guest) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -249,12 +255,11 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, sizeof(user_struct)* (num_validated_users+1)); - if (!validated_users) - { + if (!validated_users) { DEBUG(0,("Failed to realloc users struct!\n")); num_validated_users = 0; return UID_FIELD_INVALID; - } + } vuser = &validated_users[num_validated_users]; num_validated_users++; @@ -275,50 +280,20 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, &vuser->n_groups, &vuser->groups); - if (usr == NULL) - { - int i; - extern DOM_SID global_sam_sid; - - DEBUG(0,("vuser struct usr being filled in with trash, today\n")); - DEBUG(0,("this needs to be replaced with a proper surs impl.\n")); - DEBUG(0,("e.g. the one used in winbindd. in fact, all\n")); - DEBUG(0,("occurrences of pdb_xxx_to_xxx should be replaced\n")); - DEBUG(0,("as soon as possible.\n")); - vuser->usr.user_id = pdb_uid_to_user_rid(uid); - vuser->usr.group_id = pdb_gid_to_group_rid(gid); - vuser->usr.num_groups = vuser->n_groups; - for (i = 0; i < vuser->usr.num_groups; i++) - { - DOM_GID *ntgid = &vuser->usr.gids[i]; - ntgid->attr = 0x7; - ntgid->g_rid = pdb_gid_to_group_rid(vuser->groups[i]); - } - - /* this is possibly the worst thing to do, ever. it assumes */ - /* that all users of this system are in the local SAM database */ - /* however, because there is no code to do anything otherwise, */ - /* we have no choice */ - - init_dom_sid2(&vuser->usr.dom_sid, &global_sam_sid); - } - else - { - vuser->usr = *usr; - } - DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->user.full_name, ""); if (lp_unix_realname()) { - if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) - { + if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); fstrcpy(vuser->user.full_name, pwfile->pw_gecos); - } + } } + /* Map this uid into user and group SIDs. */ + setup_user_sids(vuser); + memset(&vuser->dc, '\0', sizeof(vuser->dc)); return (uint16)((num_validated_users - 1) + VUID_OFFSET); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f9c0695a39..00a0ce3c4a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1001,9 +1001,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - DEBUG(0,("must call domain_client_validate() which returns a ")); - DEBUG(0,("NET_USER_INFO_3 structure to pass to register_vuid()")); - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest, NULL); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From f5a4d08d9ed37e08b709c3ee4b0f3db2b2249855 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Jun 2000 21:54:50 +0000 Subject: Fix for map_share_mode to allow desired access of zero map to stat open. Jeremy. (This used to be commit b0242080fe464e71815431559fe54d109e0b92f2) --- source3/smbd/nttrans.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index aad09a75b6..951851b5f9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -433,6 +433,17 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, */ if (smb_open_mode == -1) { + + /* + * JRA - NT seems to sometimes send desired_access as zero. play it safe + * and map to a stat open. + */ + + if(desired_access == 0) { + *pstat_open_only = True; + smb_open_mode = DOS_OPEN_RDONLY; + } + if(desired_access == WRITE_DAC_ACCESS || desired_access == READ_CONTROL_ACCESS) *pstat_open_only = True; -- cgit From a62d17dc618f3de641341118af02fb43b6cb7e6a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Jun 2000 22:24:13 +0000 Subject: Change from "David S. Chappell" to make "printer driver file" a share parameter. This fits better with the new NT printing subsystem. Jeremy. (This used to be commit 7afb68461f3938a647a6c48689293af8ed36ccb7) --- source3/smbd/lanman.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index cfc0e08d47..bee2b39f2f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -499,10 +499,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, char *p; char **lines, *line; - lines = file_lines_load(lp_driverfile(),NULL); + lines = file_lines_load(lp_driverfile(snum),NULL); if (!lines) { DEBUG(3,("fill_printq_info: Can't open %s - %s\n", - lp_driverfile(),strerror(errno))); + lp_driverfile(snum),strerror(errno))); desc->errcode=NERR_notsupported; return; } @@ -668,10 +668,10 @@ static int get_printerdrivernumber(int snum) char *p; char **lines, *line; - lines = file_lines_load(lp_driverfile(), NULL); + lines = file_lines_load(lp_driverfile(snum), NULL); if (!lines) { DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n", - lp_driverfile(),strerror(errno))); + lp_driverfile(snum),strerror(errno))); return(0); } -- cgit From c3487b00dd1dde7fa0511211f466acc1c05d8f3d Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 9 Jun 2000 01:26:42 +0000 Subject: reverted jeremy's changes that removed NET_USER_INFO_3. will you please not just undercut work in progress, thank you. (This used to be commit 86d440a88c948727bfcfedc694c52c58f9687d8b) --- source3/smbd/password.c | 81 ++++++++++++++++++++++++++++++++----------------- source3/smbd/reply.c | 4 ++- 2 files changed, 56 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b8f5c5cf84..5815bbd164 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -117,27 +117,20 @@ invalidate a uid ****************************************************************************/ void invalidate_vuid(uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); - - if (vuser == NULL) - return; - - vuser->uid = (uid_t)-1; - vuser->gid = (gid_t)-1; + user_struct *vuser = get_valid_user_struct(vuid); - ZERO_STRUCT(vuser->user_sid); + if (vuser == NULL) return; - /* same number of igroups as groups */ - vuser->n_groups = 0; + vuser->uid = (uid_t)-1; + vuser->gid = (gid_t)-1; - if (vuser->groups) - free((char *)vuser->groups); + /* same number of igroups as groups */ + vuser->n_groups = 0; - if (vuser->group_sids) - free((char *)vuser->group_sids); + if (vuser->groups) + free((char *)vuser->groups); - vuser->groups = NULL; - vuser->group_sids = NULL; + vuser->groups = NULL; } @@ -214,14 +207,15 @@ int setup_groups(char *user, char *domain, return 0; } + /**************************************************************************** - Register a uid/name pair as being valid and that a valid password - has been given. vuid is biased by an offset. This allows us to - tell random client vuid's (normally zero) from valid vuids. +register a uid/name pair as being valid and that a valid password +has been given. vuid is biased by an offset. This allows us to +tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ - uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest) + char *domain,BOOL guest, + NET_USER_INFO_3 *usr) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -255,11 +249,12 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, sizeof(user_struct)* (num_validated_users+1)); - if (!validated_users) { + if (!validated_users) + { DEBUG(0,("Failed to realloc users struct!\n")); num_validated_users = 0; return UID_FIELD_INVALID; - } + } vuser = &validated_users[num_validated_users]; num_validated_users++; @@ -280,20 +275,50 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, &vuser->n_groups, &vuser->groups); + if (usr == NULL) + { + int i; + extern DOM_SID global_sam_sid; + + DEBUG(0,("vuser struct usr being filled in with trash, today\n")); + DEBUG(0,("this needs to be replaced with a proper surs impl.\n")); + DEBUG(0,("e.g. the one used in winbindd. in fact, all\n")); + DEBUG(0,("occurrences of pdb_xxx_to_xxx should be replaced\n")); + DEBUG(0,("as soon as possible.\n")); + vuser->usr.user_id = pdb_uid_to_user_rid(uid); + vuser->usr.group_id = pdb_gid_to_group_rid(gid); + vuser->usr.num_groups = vuser->n_groups; + for (i = 0; i < vuser->usr.num_groups; i++) + { + DOM_GID *ntgid = &vuser->usr.gids[i]; + ntgid->attr = 0x7; + ntgid->g_rid = pdb_gid_to_group_rid(vuser->groups[i]); + } + + /* this is possibly the worst thing to do, ever. it assumes */ + /* that all users of this system are in the local SAM database */ + /* however, because there is no code to do anything otherwise, */ + /* we have no choice */ + + init_dom_sid2(&vuser->usr.dom_sid, &global_sam_sid); + } + else + { + vuser->usr = *usr; + } + DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->user.full_name, ""); if (lp_unix_realname()) { - if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { + if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) + { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); fstrcpy(vuser->user.full_name, pwfile->pw_gecos); - } + } } - /* Map this uid into user and group SIDs. */ - setup_user_sids(vuser); - memset(&vuser->dc, '\0', sizeof(vuser->dc)); return (uint16)((num_validated_users - 1) + VUID_OFFSET); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 00a0ce3c4a..f9c0695a39 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1001,7 +1001,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest); + DEBUG(0,("must call domain_client_validate() which returns a ")); + DEBUG(0,("NET_USER_INFO_3 structure to pass to register_vuid()")); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest, NULL); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From ad98207f54a7e3d88108d34c4cf365d5f8bc23ef Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 9 Jun 2000 03:00:34 +0000 Subject: dynamic allocation of NET_USER_INFO_3 gids. jeremy, the intent is to call se_access_check() with usr-sid, grp-sid, array-of-group-rids (but array-of-group-sids would do). please do look at smbd/lanman.c's api_NetWkstaGetInfo, it will show you that we really do need to store the entire NET_USER_INFO_3 structure. then again, api_NetWkstaGetInfo is only used by win9x so who cares :) (This used to be commit bd34f652390adc32c4959d164c628687f526d977) --- source3/smbd/password.c | 60 ++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 5815bbd164..6201b85357 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -277,30 +277,37 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, if (usr == NULL) { - int i; - extern DOM_SID global_sam_sid; - - DEBUG(0,("vuser struct usr being filled in with trash, today\n")); - DEBUG(0,("this needs to be replaced with a proper surs impl.\n")); - DEBUG(0,("e.g. the one used in winbindd. in fact, all\n")); - DEBUG(0,("occurrences of pdb_xxx_to_xxx should be replaced\n")); - DEBUG(0,("as soon as possible.\n")); - vuser->usr.user_id = pdb_uid_to_user_rid(uid); - vuser->usr.group_id = pdb_gid_to_group_rid(gid); - vuser->usr.num_groups = vuser->n_groups; - for (i = 0; i < vuser->usr.num_groups; i++) - { - DOM_GID *ntgid = &vuser->usr.gids[i]; - ntgid->attr = 0x7; - ntgid->g_rid = pdb_gid_to_group_rid(vuser->groups[i]); - } - - /* this is possibly the worst thing to do, ever. it assumes */ - /* that all users of this system are in the local SAM database */ - /* however, because there is no code to do anything otherwise, */ - /* we have no choice */ + int i; + extern DOM_SID global_sam_sid; + + DEBUG(0,("vuser struct usr being filled in with trash, today\n")); + DEBUG(0,("this needs to be replaced with a proper surs impl.\n")); + DEBUG(0,("e.g. the one used in winbindd. in fact, all\n")); + DEBUG(0,("occurrences of pdb_xxx_to_xxx should be replaced\n")); + DEBUG(0,("as soon as possible.\n")); + vuser->usr.user_id = pdb_uid_to_user_rid(uid); + vuser->usr.group_id = pdb_gid_to_group_rid(gid); + vuser->usr.num_groups = vuser->n_groups; + if (vuser->n_groups != 0) + { + vuser->usr.gids = g_new(DOM_GID, vuser->usr.num_groups); + if (vuser->usr.gids == NULL) + return UID_FIELD_INVALID; + } - init_dom_sid2(&vuser->usr.dom_sid, &global_sam_sid); + for (i = 0; i < vuser->usr.num_groups; i++) + { + DOM_GID *ntgid = &vuser->usr.gids[i]; + ntgid->attr = 0x7; + ntgid->g_rid = pdb_gid_to_group_rid(vuser->groups[i]); + } + + /* this is possibly the worst thing to do, ever. it assumes */ + /* that all users of this system are in the local SAM database */ + /* however, because there is no code to do anything otherwise, */ + /* we have no choice */ + + init_dom_sid2(&vuser->usr.dom_sid, &global_sam_sid); } else { @@ -1525,12 +1532,19 @@ BOOL domain_client_validate( char *user, char *domain, cli_ulogoff(&cli); cli_shutdown(&cli); + /* unused, so delete here. */ + if (info3.gids != NULL) + free (info3.gids); + if((nt_rpc_err == NT_STATUS_NO_SUCH_USER) && (user_exists != NULL)) *user_exists = False; return False; } + /* unused, so delete here. */ + if (info3.gids != NULL) + free (info3.gids); /* * Here, if we really want it, we have lots of info about the user in info3. */ -- cgit From 979f509e74c7cb2071478b9b1da9f254d98920cb Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Fri, 9 Jun 2000 03:30:54 +0000 Subject: free NET_USER_INFO_3 gids when vuser invalidated. (This used to be commit 2f056c2aadd2e16d89b66aabd1c166ab8d5abd76) --- source3/smbd/password.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6201b85357..4110530c0b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -131,6 +131,10 @@ void invalidate_vuid(uint16 vuid) free((char *)vuser->groups); vuser->groups = NULL; + + if (vuser->usr.gids != NULL) + free (vuser->usr.gids); + vuser->usr.gids = NULL; } -- cgit From 09ea9eac69374dac77b53072e9b54e0e7720375f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Jun 2000 04:22:02 +0000 Subject: split some of the irix kernel oplocks code into a function (This used to be commit 6b888d600d95e2595c3f79494edcc55e88e2980d) --- source3/smbd/oplock.c | 142 ++++++++++++++++++++++++++------------------------ 1 file changed, 74 insertions(+), 68 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 5484728122..1517ff7855 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -118,6 +118,76 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); return True; } +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) +/**************************************************************************** + * Deal with the IRIX kernel <--> smbd + * oplock break protocol. +****************************************************************************/ +static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len, int timeout) +{ + oplock_stat_t os; + SMB_DEV_T dev; + SMB_INO_T inode; + char dummy; + + /* + * Read one byte of zero to clear the + * kernel break notify message. + */ + + if(read(oplock_pipe_read, &dummy, 1) != 1) { + DEBUG(0,("receive_local_message: read of kernel notification failed. \ +Error was %s.\n", strerror(errno) )); + smb_read_error = READ_ERROR; + return False; + } + + /* + * Do a query to get the + * device and inode of the file that has the break + * request outstanding. + */ + + if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { + DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ +Error was %s.\n", strerror(errno) )); + if(errno == EAGAIN) { + /* + * Duplicate kernel break message - ignore. + */ + memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); + return True; + } + smb_read_error = READ_ERROR; + return False; + } + + dev = (SMB_DEV_T)os.os_dev; + inode = (SMB_INO_T)os.os_ino; + + DEBUG(5,("receive_local_message: kernel oplock break request received for \ +dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); + + /* + * Create a kernel oplock break message. + */ + + /* Setup the message header */ + SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); + SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); + + buffer += OPBRK_CMD_HEADER_LEN; + + SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); + + memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); + + return True; +} +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ + + /**************************************************************************** Read an oplock break message from the either the oplock UDP fd or the kernel oplock pipe fd (if kernel oplocks are supported). @@ -164,74 +234,11 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou } } -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) - if(FD_ISSET(oplock_pipe_read,fds)) { - /* - * Deal with the kernel <--> smbd - * oplock break protocol. - */ - - oplock_stat_t os; - SMB_DEV_T dev; - SMB_INO_T inode; - char dummy; - - /* - * Read one byte of zero to clear the - * kernel break notify message. - */ - - if(read(oplock_pipe_read, &dummy, 1) != 1) { - DEBUG(0,("receive_local_message: read of kernel notification failed. \ -Error was %s.\n", strerror(errno) )); - smb_read_error = READ_ERROR; - return False; - } - - /* - * Do a query to get the - * device and inode of the file that has the break - * request outstanding. - */ - - if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { - DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ -Error was %s.\n", strerror(errno) )); - if(errno == EAGAIN) { - /* - * Duplicate kernel break message - ignore. - */ - memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); - return True; - } - smb_read_error = READ_ERROR; - return False; - } - - dev = (SMB_DEV_T)os.os_dev; - inode = (SMB_INO_T)os.os_ino; - - DEBUG(5,("receive_local_message: kernel oplock break request received for \ -dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); - - /* - * Create a kernel oplock break message. - */ - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); - - buffer += OPBRK_CMD_HEADER_LEN; - - SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); - - return True; +#if HAVE_KERNEL_OPLOCKS_IRIX + if (FD_ISSET(oplock_pipe_read,fds)) { + return irix_receive_message(fds, buffer, buffer_len, timeout); } -#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ +#endif /* * From here down we deal with the smbd <--> smbd @@ -281,7 +288,6 @@ static BOOL set_kernel_oplock(files_struct *fsp, int oplock_type) { #if defined(HAVE_KERNEL_OPLOCKS_IRIX) if(lp_kernel_oplocks()) { - if(fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { if(errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ -- cgit From 15cf0e847009faf7fb90bd7e9e27db6999c88eef Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Jun 2000 06:58:06 +0000 Subject: clean up oplock capability code ready for Linux code (This used to be commit 70dcc791b45ac64fc536ef449e4e6b53b2b68fd4) --- source3/smbd/chgpasswd.c | 4 +- source3/smbd/oplock.c | 301 +++++++++++++++++++++++------------------------ source3/smbd/server.c | 11 +- 3 files changed, 155 insertions(+), 161 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d27cf373f5..b6aaf4765b 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -406,9 +406,7 @@ static BOOL chat_with_program(char *passwordprogram, char *name, /* * Lose any oplock capabilities. */ - set_process_capability(KERNEL_OPLOCK_CAPABILITY, False); - set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, - False); + oplock_set_capability(False, False); /* make sure it doesn't freeze */ alarm(20); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1517ff7855..af48b06ab0 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -53,27 +53,84 @@ int32 get_number_of_exclusive_open_oplocks(void) return exclusive_oplocks_open; } + +#if HAVE_KERNEL_OPLOCKS_IRIX /**************************************************************************** - Setup the kernel level oplock backchannel for this process. +test to see if IRIX kernel oplocks work ****************************************************************************/ +static BOOL irix_oplocks_available(void) +{ + int fd; + int pfd[2]; + pstring tmpname; + + oplock_set_capability(True, True); + + slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid()); + + if(pipe(pfd) != 0) { + DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", + strerror(errno) )); + return False; + } + + if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) { + DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", + tmpname, strerror(errno) )); + unlink( tmpname ); + close(pfd[0]); + close(pfd[1]); + return False; + } + + unlink( tmpname ); + + if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { + DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ +Disabling kernel oplock support.\n" )); + close(pfd[0]); + close(pfd[1]); + close(fd); + return False; + } + + if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) { + DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ +Disabling kernel oplock support.\n", strerror(errno) )); + close(pfd[0]); + close(pfd[1]); + close(fd); + return False; + } + + close(pfd[0]); + close(pfd[1]); + close(fd); + return True; +} +#endif + +/**************************************************************************** + Setup the kernel level oplock backchannel for this process. +****************************************************************************/ BOOL setup_kernel_oplock_pipe(void) { #if defined(HAVE_KERNEL_OPLOCKS_IRIX) - if(lp_kernel_oplocks()) { - int pfd[2]; - - if(pipe(pfd) != 0) { - DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n", - strerror(errno) )); - return False; - } - - oplock_pipe_read = pfd[0]; - oplock_pipe_write = pfd[1]; - } + if(lp_kernel_oplocks()) { + int pfd[2]; + + if(pipe(pfd) != 0) { + DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n", + strerror(errno) )); + return False; + } + + oplock_pipe_read = pfd[0]; + oplock_pipe_write = pfd[1]; + } #endif /* HAVE_KERNEL_OPLOCKS_IRIX */ - return True; + return True; } /**************************************************************************** @@ -189,8 +246,8 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); /**************************************************************************** - Read an oplock break message from the either the oplock UDP fd - or the kernel oplock pipe fd (if kernel oplocks are supported). + Read an oplock break message from either the oplock UDP fd or the + kernel oplock pipe fd (if kernel oplocks are supported). If timeout is zero then *fds contains the file descriptors that are ready to be read and acted upon. If timeout is non-zero then @@ -283,94 +340,85 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou Attempt to set an kernel oplock on a file. Always returns True if kernel oplocks not available. ****************************************************************************/ - static BOOL set_kernel_oplock(files_struct *fsp, int oplock_type) { + if(!lp_kernel_oplocks()) return True; + #if defined(HAVE_KERNEL_OPLOCKS_IRIX) - if(lp_kernel_oplocks()) { - if(fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { - if(errno != EAGAIN) { - DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ + if (fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { + if(errno != EAGAIN) { + DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - strerror(errno) )); - } else { - DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, + strerror(errno) )); + } else { + DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. Another process had the file open.\n", - fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode )); - } - return False; - } - - DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); - - } + fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode )); + } + return False; + } + + DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); #endif /* HAVE_KERNEL_OPLOCKS_IRIX */ - return True; + + return True; } /**************************************************************************** Attempt to set an oplock on a file. Always succeeds if kernel oplocks are disabled (just sets flags). Returns True if oplock set. ****************************************************************************/ - BOOL set_file_oplock(files_struct *fsp, int oplock_type) { - if (!set_kernel_oplock(fsp, oplock_type)) - return False; + if (!set_kernel_oplock(fsp, oplock_type)) + return False; - fsp->oplock_type = oplock_type; - fsp->sent_oplock_break = NO_BREAK_SENT; - if ( oplock_type == LEVEL_II_OPLOCK) - level_II_oplocks_open++; - else - exclusive_oplocks_open++; + fsp->oplock_type = oplock_type; + fsp->sent_oplock_break = NO_BREAK_SENT; + if (oplock_type == LEVEL_II_OPLOCK) + level_II_oplocks_open++; + else + exclusive_oplocks_open++; - DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); + DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, + (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); - return True; + return True; } /**************************************************************************** Release a kernel oplock on a file. ****************************************************************************/ - static void release_kernel_oplock(files_struct *fsp) { -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) + if (!lp_kernel_oplocks()) return; - if(lp_kernel_oplocks()) - { - if( DEBUGLVL( 10 )) - { - /* - * Check and print out the current kernel - * oplock state of this file. - */ - int state = fcntl(fsp->fd, F_OPLKACK, -1); - dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ +#if defined(HAVE_KERNEL_OPLOCKS_IRIX) + if (DEBUGLVL(10)) { + /* + * Check and print out the current kernel + * oplock state of this file. + */ + int state = fcntl(fsp->fd, F_OPLKACK, -1); + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, state ); - } - - /* - * Remove the kernel oplock on this file. - */ - - if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) - { - if( DEBUGLVL( 0 )) - { - dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, strerror(errno) ); - } - } - } + } + + /* + * Remove the kernel oplock on this file. + */ + if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { + if( DEBUGLVL( 0 )) { + dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); + dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, strerror(errno) ); + } + } #endif /* HAVE_KERNEL_OPLOCKS_IRIX */ } @@ -381,17 +429,17 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, void release_file_oplock(files_struct *fsp) { - release_kernel_oplock(fsp); - - if (fsp->oplock_type == LEVEL_II_OPLOCK) - level_II_oplocks_open--; - else - exclusive_oplocks_open--; - - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - - flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH); + release_kernel_oplock(fsp); + + if (fsp->oplock_type == LEVEL_II_OPLOCK) + level_II_oplocks_open--; + else + exclusive_oplocks_open--; + + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; + + flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH); } /**************************************************************************** @@ -1329,74 +1377,23 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) void check_kernel_oplocks(void) { - static BOOL done; - - /* - * We only do this check once on startup. - */ - - if(done) - return; + static BOOL done; - done = True; - lp_set_kernel_oplocks(False); + /* + * We only do this check once on startup. + */ + if(done) return; + + done = True; + lp_set_kernel_oplocks(False); #if defined(HAVE_KERNEL_OPLOCKS_IRIX) - { - int fd; - int pfd[2]; - pstring tmpname; - - set_process_capability(KERNEL_OPLOCK_CAPABILITY,True); - set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,True); - - slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid()); - - if(pipe(pfd) != 0) { - DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", - strerror(errno) )); - return; - } - - if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) { - DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", - tmpname, strerror(errno) )); - unlink( tmpname ); - close(pfd[0]); - close(pfd[1]); - return; - } - - unlink( tmpname ); + if (irix_oplocks_available()) { + lp_set_kernel_oplocks(True); - if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { - DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ -Disabling kernel oplock support.\n" )); - close(pfd[0]); - close(pfd[1]); - close(fd); - return; - } - - if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) { - DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ -Disabling kernel oplock support.\n", strerror(errno) )); - close(pfd[0]); - close(pfd[1]); - close(fd); - return; - } - - close(pfd[0]); - close(pfd[1]); - close(fd); - - lp_set_kernel_oplocks(True); - - DEBUG(0,("check_kernel_oplocks: Kernel oplocks available and set to %s.\n", - lp_kernel_oplocks() ? "True" : "False" )); - - } + DEBUG(0,("check_kernel_oplocks: Kernel oplocks available and set to %s.\n", + lp_kernel_oplocks() ? "True" : "False" )); + } #endif /* HAVE_KERNEL_OPLOCKS_IRIX */ } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a8e7540d28..72c0cb105d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -259,12 +259,11 @@ max can be %d\n", done correctly in the process. */ reset_globals_after_fork(); - /* - * Ensure this child has kernel oplock - * capabilities, but not it's children. - */ - set_process_capability(KERNEL_OPLOCK_CAPABILITY, True); - set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); + /* + * Ensure this child has kernel oplock + * capabilities, but not it's children. + */ + oplock_set_capability(True, False); return True; } -- cgit From 03e0164270ffd7ceeb8df6f3cc3917c111dc05f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Jun 2000 18:45:31 +0000 Subject: Luke, I am moving the code back into passdb/passdb.c, this the correct place to do this, not in smbd/passwd.c Please don't change this without asking first, I have run this past Andrew so talk to him (I'm on vacation next week). I also removed the g_newXXX macros. There are essentially a private C extension, not used anywhere else in the code, and add no functionality over malloc(XX) and make the code harder to understand (everyone knows what malloc does). Jeremy. (This used to be commit e1b1b6fb6794ba02e1fea510a981fa0ce0d12b58) --- source3/smbd/password.c | 66 +++++++++++-------------------------------------- source3/smbd/reply.c | 4 +-- 2 files changed, 15 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 4110530c0b..c38a6a0f2b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -117,24 +117,24 @@ invalidate a uid ****************************************************************************/ void invalidate_vuid(uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); + user_struct *vuser = get_valid_user_struct(vuid); - if (vuser == NULL) return; + if (vuser == NULL) + return; - vuser->uid = (uid_t)-1; - vuser->gid = (gid_t)-1; + vuser->uid = (uid_t)-1; + vuser->gid = (gid_t)-1; - /* same number of igroups as groups */ - vuser->n_groups = 0; + /* same number of igroups as groups */ + vuser->n_groups = 0; - if (vuser->groups) - free((char *)vuser->groups); + if (vuser->groups) + free((char *)vuser->groups); - vuser->groups = NULL; + vuser->groups = NULL; - if (vuser->usr.gids != NULL) - free (vuser->usr.gids); - vuser->usr.gids = NULL; + if (vuser->group_sids != NULL) + free (vuser->group_sids); } @@ -218,8 +218,7 @@ has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest, - NET_USER_INFO_3 *usr) + char *domain,BOOL guest) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -279,44 +278,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, &vuser->n_groups, &vuser->groups); - if (usr == NULL) - { - int i; - extern DOM_SID global_sam_sid; - - DEBUG(0,("vuser struct usr being filled in with trash, today\n")); - DEBUG(0,("this needs to be replaced with a proper surs impl.\n")); - DEBUG(0,("e.g. the one used in winbindd. in fact, all\n")); - DEBUG(0,("occurrences of pdb_xxx_to_xxx should be replaced\n")); - DEBUG(0,("as soon as possible.\n")); - vuser->usr.user_id = pdb_uid_to_user_rid(uid); - vuser->usr.group_id = pdb_gid_to_group_rid(gid); - vuser->usr.num_groups = vuser->n_groups; - if (vuser->n_groups != 0) - { - vuser->usr.gids = g_new(DOM_GID, vuser->usr.num_groups); - if (vuser->usr.gids == NULL) - return UID_FIELD_INVALID; - } - - for (i = 0; i < vuser->usr.num_groups; i++) - { - DOM_GID *ntgid = &vuser->usr.gids[i]; - ntgid->attr = 0x7; - ntgid->g_rid = pdb_gid_to_group_rid(vuser->groups[i]); - } - - /* this is possibly the worst thing to do, ever. it assumes */ - /* that all users of this system are in the local SAM database */ - /* however, because there is no code to do anything otherwise, */ - /* we have no choice */ - - init_dom_sid2(&vuser->usr.dom_sid, &global_sam_sid); - } - else - { - vuser->usr = *usr; - } + setup_user_sids(vuser); DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f9c0695a39..00a0ce3c4a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1001,9 +1001,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - DEBUG(0,("must call domain_client_validate() which returns a ")); - DEBUG(0,("NET_USER_INFO_3 structure to pass to register_vuid()")); - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest, NULL); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From 891bdd0d3e38f6046a0207129a5dfbd67d2e0269 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Jun 2000 19:41:48 +0000 Subject: (Correct) fix for desired_access being zero in map_share_mode(). Jeremy. (This used to be commit cc447fbe3cd77d57e18c3d1dff94a95d6032c311) --- source3/smbd/nttrans.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 951851b5f9..8b3eabff80 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -434,25 +434,25 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, if (smb_open_mode == -1) { - /* - * JRA - NT seems to sometimes send desired_access as zero. play it safe - * and map to a stat open. - */ - - if(desired_access == 0) { - *pstat_open_only = True; - smb_open_mode = DOS_OPEN_RDONLY; - } - if(desired_access == WRITE_DAC_ACCESS || desired_access == READ_CONTROL_ACCESS) *pstat_open_only = True; if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| FILE_EXECUTE|FILE_READ_ATTRIBUTES| FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| - FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) + FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) { smb_open_mode = DOS_OPEN_RDONLY; - else { + } else if(desired_access == 0) { + + /* + * JRA - NT seems to sometimes send desired_access as zero. play it safe + * and map to a stat open. + */ + + *pstat_open_only = True; + smb_open_mode = DOS_OPEN_RDONLY; + + } else { DEBUG(0,("map_share_mode: Incorrect value %lx for desired_access to file %s\n", (unsigned long)desired_access, fname)); return -1; -- cgit From 52cb05678a9b08b5aa7dbe13ae6b54ff9ee4ecac Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Jun 2000 13:38:07 +0000 Subject: continued the split of the kernel level oplocks code into a more modular form. In this pass I added oplock_irix.c and added a "struct kernel_oplocks" that describes a kernel oplock implementation. (This used to be commit b5ceab810292602ea9a81696c20a781c16b706c2) --- source3/smbd/oplock.c | 499 +++++++++++---------------------------------- source3/smbd/oplock_irix.c | 282 +++++++++++++++++++++++++ source3/smbd/server.c | 23 +-- 3 files changed, 412 insertions(+), 392 deletions(-) create mode 100644 source3/smbd/oplock_irix.c (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index af48b06ab0..33d82f3dde 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -28,11 +28,6 @@ extern int DEBUGLEVEL; /* Oplock ipc UDP socket. */ static int oplock_sock = -1; uint16 global_oplock_port = 0; -static int oplock_pipe_read = -1; - -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) -static int oplock_pipe_write = -1; -#endif /* Current number of oplocks we have outstanding. */ static int32 exclusive_oplocks_open = 0; @@ -42,6 +37,8 @@ BOOL global_oplock_break = False; extern int smb_read_error; +static struct kernel_oplocks *koplocks; + static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, BOOL local); /**************************************************************************** @@ -54,200 +51,9 @@ int32 get_number_of_exclusive_open_oplocks(void) } -#if HAVE_KERNEL_OPLOCKS_IRIX -/**************************************************************************** -test to see if IRIX kernel oplocks work -****************************************************************************/ -static BOOL irix_oplocks_available(void) -{ - int fd; - int pfd[2]; - pstring tmpname; - - oplock_set_capability(True, True); - - slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid()); - - if(pipe(pfd) != 0) { - DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", - strerror(errno) )); - return False; - } - - if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) { - DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", - tmpname, strerror(errno) )); - unlink( tmpname ); - close(pfd[0]); - close(pfd[1]); - return False; - } - - unlink( tmpname ); - - if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { - DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ -Disabling kernel oplock support.\n" )); - close(pfd[0]); - close(pfd[1]); - close(fd); - return False; - } - - if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) { - DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ -Disabling kernel oplock support.\n", strerror(errno) )); - close(pfd[0]); - close(pfd[1]); - close(fd); - return False; - } - - close(pfd[0]); - close(pfd[1]); - close(fd); - - return True; -} -#endif - -/**************************************************************************** - Setup the kernel level oplock backchannel for this process. -****************************************************************************/ -BOOL setup_kernel_oplock_pipe(void) -{ -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) - if(lp_kernel_oplocks()) { - int pfd[2]; - - if(pipe(pfd) != 0) { - DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n", - strerror(errno) )); - return False; - } - - oplock_pipe_read = pfd[0]; - oplock_pipe_write = pfd[1]; - } -#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ - return True; -} - -/**************************************************************************** - Open the oplock IPC socket communication. -****************************************************************************/ - -BOOL open_oplock_ipc(void) -{ - struct sockaddr_in sock_name; - int len = sizeof(sock_name); - - DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); - - /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK),False); - if (oplock_sock == -1) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); - global_oplock_port = 0; - return(False); - } - - /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", - strerror(errno))); - close(oplock_sock); - oplock_sock = -1; - global_oplock_port = 0; - return False; - } - global_oplock_port = ntohs(sock_name.sin_port); - - if(!setup_kernel_oplock_pipe()) - return False; - - DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", - (int)sys_getpid(), global_oplock_port)); - - return True; -} - -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) -/**************************************************************************** - * Deal with the IRIX kernel <--> smbd - * oplock break protocol. -****************************************************************************/ -static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len, int timeout) -{ - oplock_stat_t os; - SMB_DEV_T dev; - SMB_INO_T inode; - char dummy; - - /* - * Read one byte of zero to clear the - * kernel break notify message. - */ - - if(read(oplock_pipe_read, &dummy, 1) != 1) { - DEBUG(0,("receive_local_message: read of kernel notification failed. \ -Error was %s.\n", strerror(errno) )); - smb_read_error = READ_ERROR; - return False; - } - - /* - * Do a query to get the - * device and inode of the file that has the break - * request outstanding. - */ - - if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { - DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ -Error was %s.\n", strerror(errno) )); - if(errno == EAGAIN) { - /* - * Duplicate kernel break message - ignore. - */ - memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); - return True; - } - smb_read_error = READ_ERROR; - return False; - } - - dev = (SMB_DEV_T)os.os_dev; - inode = (SMB_INO_T)os.os_ino; - - DEBUG(5,("receive_local_message: kernel oplock break request received for \ -dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); - - /* - * Create a kernel oplock break message. - */ - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); - - buffer += OPBRK_CMD_HEADER_LEN; - - SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); - - return True; -} -#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ - - /**************************************************************************** Read an oplock break message from either the oplock UDP fd or the - kernel oplock pipe fd (if kernel oplocks are supported). + kernel (if kernel oplocks are supported). If timeout is zero then *fds contains the file descriptors that are ready to be read and acted upon. If timeout is non-zero then @@ -269,8 +75,9 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou int selrtn; int maxfd = oplock_sock; - if(lp_kernel_oplocks() && (oplock_pipe_read != -1)) - maxfd = MAX(maxfd, oplock_pipe_read); + if (koplocks && koplocks->notification_fd != -1) { + FD_SET(koplocks->notification_fd, fds); + } to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; @@ -291,11 +98,9 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou } } -#if HAVE_KERNEL_OPLOCKS_IRIX - if (FD_ISSET(oplock_pipe_read,fds)) { - return irix_receive_message(fds, buffer, buffer_len, timeout); + if (koplocks && koplocks->msg_waiting(fds)) { + return koplocks->receive_message(fds, buffer, buffer_len); } -#endif /* * From here down we deal with the smbd <--> smbd @@ -336,43 +141,13 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou return True; } -/**************************************************************************** - Attempt to set an kernel oplock on a file. Always returns True if kernel - oplocks not available. -****************************************************************************/ -static BOOL set_kernel_oplock(files_struct *fsp, int oplock_type) -{ - if(!lp_kernel_oplocks()) return True; - -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) - if (fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) < 0 ) { - if(errno != EAGAIN) { - DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ -inode = %.0f. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - strerror(errno) )); - } else { - DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ -inode = %.0f. Another process had the file open.\n", - fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode )); - } - return False; - } - - DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); -#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ - - return True; -} - /**************************************************************************** Attempt to set an oplock on a file. Always succeeds if kernel oplocks are disabled (just sets flags). Returns True if oplock set. ****************************************************************************/ BOOL set_file_oplock(files_struct *fsp, int oplock_type) { - if (!set_kernel_oplock(fsp, oplock_type)) + if (koplocks && !koplocks->set_oplock(fsp, oplock_type)) return False; fsp->oplock_type = oplock_type; @@ -389,47 +164,13 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) return True; } -/**************************************************************************** - Release a kernel oplock on a file. -****************************************************************************/ -static void release_kernel_oplock(files_struct *fsp) -{ - if (!lp_kernel_oplocks()) return; - -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) - if (DEBUGLVL(10)) { - /* - * Check and print out the current kernel - * oplock state of this file. - */ - int state = fcntl(fsp->fd, F_OPLKACK, -1); - dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ -oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, state ); - } - - /* - * Remove the kernel oplock on this file. - */ - if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { - if( DEBUGLVL( 0 )) { - dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, strerror(errno) ); - } - } -#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ -} - - /**************************************************************************** Attempt to release an oplock on a file. Decrements oplock count. ****************************************************************************/ void release_file_oplock(files_struct *fsp) { - release_kernel_oplock(fsp); + if (koplocks) koplocks->release_oplock(fsp); if (fsp->oplock_type == LEVEL_II_OPLOCK) level_II_oplocks_open--; @@ -448,11 +189,11 @@ void release_file_oplock(files_struct *fsp) static void downgrade_file_oplock(files_struct *fsp) { - release_kernel_oplock(fsp); - fsp->oplock_type = LEVEL_II_OPLOCK; - exclusive_oplocks_open--; - level_II_oplocks_open++; - fsp->sent_oplock_break = NO_BREAK_SENT; + if (koplocks) koplocks->release_oplock(fsp); + fsp->oplock_type = LEVEL_II_OPLOCK; + exclusive_oplocks_open--; + level_II_oplocks_open++; + fsp->sent_oplock_break = NO_BREAK_SENT; } /**************************************************************************** @@ -462,48 +203,44 @@ static void downgrade_file_oplock(files_struct *fsp) BOOL remove_oplock(files_struct *fsp) { - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; - BOOL ret = True; - - /* Remove the oplock flag from the sharemode. */ - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", - fsp->fsp_name )); - ret = False; - } - - if (fsp->sent_oplock_break == EXCLUSIVE_BREAK_SENT) { + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; + BOOL ret = True; + + /* Remove the oplock flag from the sharemode. */ + if (lock_share_entry_fsp(fsp) == False) { + DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", + fsp->fsp_name )); + ret = False; + } - /* - * Deal with a reply when a break-to-none was sent. - */ + if (fsp->sent_oplock_break == EXCLUSIVE_BREAK_SENT) { + /* + * Deal with a reply when a break-to-none was sent. + */ - if(remove_share_oplock(fsp)==False) { - DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \ + if(remove_share_oplock(fsp)==False) { + DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); - ret = False; - } - - release_file_oplock(fsp); - - } else { - - /* - * Deal with a reply when a break-to-level II was sent. - */ + ret = False; + } - if(downgrade_share_oplock(fsp)==False) { - DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \ + release_file_oplock(fsp); + } else { + /* + * Deal with a reply when a break-to-level II was sent. + */ + if(downgrade_share_oplock(fsp)==False) { + DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); - ret = False; - } - - downgrade_file_oplock(fsp); - } + ret = False; + } + + downgrade_file_oplock(fsp); + } - unlock_share_entry_fsp(fsp); - return ret; + unlock_share_entry_fsp(fsp); + return ret; } /**************************************************************************** @@ -514,26 +251,25 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double) int setup_oplock_select_set( fd_set *fds) { - int maxfd = oplock_sock; + int maxfd = oplock_sock; - if(oplock_sock == -1) - return 0; + if(oplock_sock == -1) + return 0; - FD_SET(oplock_sock,fds); + FD_SET(oplock_sock,fds); - if(lp_kernel_oplocks() && (oplock_pipe_read != -1)) { - FD_SET(oplock_pipe_read,fds); - maxfd = MAX(maxfd,oplock_pipe_read); - } + if (koplocks && koplocks->notification_fd != -1) { + FD_SET(koplocks->notification_fd, fds); + maxfd = MAX(maxfd, koplocks->notification_fd); + } - return maxfd; + return maxfd; } /**************************************************************************** Process an oplock break message - whether it came from the UDP socket or from the kernel. ****************************************************************************/ - BOOL process_local_message(char *buffer, int buf_size) { int32 msg_len; @@ -562,26 +298,15 @@ BOOL process_local_message(char *buffer, int buf_size) switch(break_cmd_type) { -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) case KERNEL_OPLOCK_BREAK_CMD: - /* Ensure that the msg length is correct. */ - if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); - return False; - } - { - memcpy((char *)&inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(inode)); - memcpy((char *)&dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(dev)); - - ptval = NULL; - - DEBUG(5,("process_local_message: kernel oplock break request for \ -file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); - } - break; -#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ + if (!koplocks) { + DEBUG(0,("unexpected kernel oplock break!\n")); + break; + } + if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev)) { + DEBUG(0,("kernel oplock break parse failure!\n")); + } + break; case OPLOCK_BREAK_CMD: case LEVEL_II_OPLOCK_BREAK_CMD: @@ -708,18 +433,18 @@ pid %d, port %d, for file dev = %x, inode = %.0f\n", static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) { - memset(outbuf,'\0',smb_size); - set_message(outbuf,8,0,True); - - SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->conn->cnum); - SSVAL(outbuf,smb_pid,0xFFFF); - SSVAL(outbuf,smb_uid,0); - SSVAL(outbuf,smb_mid,0xFFFF); - SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fsp->fnum); - SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); - SCVAL(outbuf,smb_vwv3+1,level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); + memset(outbuf,'\0',smb_size); + set_message(outbuf,8,0,True); + + SCVAL(outbuf,smb_com,SMBlockingX); + SSVAL(outbuf,smb_tid,fsp->conn->cnum); + SSVAL(outbuf,smb_pid,0xFFFF); + SSVAL(outbuf,smb_uid,0); + SSVAL(outbuf,smb_mid,0xFFFF); + SCVAL(outbuf,smb_vwv0,0xFF); + SSVAL(outbuf,smb_vwv2,fsp->fnum); + SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); + SCVAL(outbuf,smb_vwv3+1,level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); } /**************************************************************************** @@ -749,7 +474,6 @@ static void wait_before_sending_break(BOOL local_request) /**************************************************************************** Ensure that we have a valid oplock. ****************************************************************************/ - static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) { files_struct *fsp = NULL; @@ -966,7 +690,10 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B /* Prepare the SMBlockingX message. */ - if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && !lp_kernel_oplocks() && lp_level2_oplocks(SNUM(fsp->conn))) { + if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && + !koplocks && /* NOTE: we force levelII off for kernel oplocks - + this will change when it is supported */ + lp_level2_oplocks(SNUM(fsp->conn))) { using_levelII = True; } else { using_levelII = False; @@ -1244,8 +971,10 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); FD_ZERO(&fds); FD_SET(oplock_sock,&fds); - if(lp_kernel_oplocks() && (oplock_pipe_read != -1)) - FD_SET(oplock_pipe_read,&fds); + + if (koplocks && koplocks->notification_fd != -1) { + FD_SET(koplocks->notification_fd, &fds); + } if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply), time_left ? time_left * 1000 : 1) == False) @@ -1292,7 +1021,7 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) +#if HAVE_KERNEL_OPLOCKS_IRIX if((reply_msg_len != OPLOCK_BREAK_MSG_LEN) && (reply_msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN)) #else if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) @@ -1354,7 +1083,6 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); Used as a last ditch attempt to free a space in the file table when we have run out. ****************************************************************************/ - BOOL attempt_close_oplocked_file(files_struct *fsp) { @@ -1371,30 +1099,47 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) return False; } + /**************************************************************************** - Init function to check if kernel level oplocks are available. +setup oplocks for this process ****************************************************************************/ - -void check_kernel_oplocks(void) +BOOL init_oplocks(void) { - static BOOL done; - - /* - * We only do this check once on startup. - */ - if(done) return; - - done = True; - lp_set_kernel_oplocks(False); - -#if defined(HAVE_KERNEL_OPLOCKS_IRIX) - if (irix_oplocks_available()) { - lp_set_kernel_oplocks(True); - - DEBUG(0,("check_kernel_oplocks: Kernel oplocks available and set to %s.\n", - lp_kernel_oplocks() ? "True" : "False" )); + struct sockaddr_in sock_name; + int len = sizeof(sock_name); + + DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); + + /* Open a lookback UDP socket on a random port. */ + oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK),False); + if (oplock_sock == -1) { + DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ +address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); + global_oplock_port = 0; + return(False); + } + + /* Find out the transient UDP port we have been allocated. */ + if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) { + DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", + strerror(errno))); + close(oplock_sock); + oplock_sock = -1; + global_oplock_port = 0; + return False; } -#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ + global_oplock_port = ntohs(sock_name.sin_port); + + if (lp_kernel_oplocks()) { +#if HAVE_KERNEL_OPLOCKS_IRIX + koplocks = irix_init_kernel_oplocks(); +#endif + } + + DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", + (int)sys_getpid(), global_oplock_port)); + + return True; } #undef OLD_NTDOMAIN diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c new file mode 100644 index 0000000000..0820c4048d --- /dev/null +++ b/source3/smbd/oplock_irix.c @@ -0,0 +1,282 @@ +#define OLD_NTDOMAIN 1 +#if HAVE_KERNEL_OPLOCKS_IRIX + +/* + Unix SMB/Netbios implementation. + Version 1.9. + oplock processing + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + + +static int oplock_pipe_write = -1; +static int oplock_pipe_read = -1; + +/**************************************************************************** +test to see if IRIX kernel oplocks work +****************************************************************************/ +static BOOL irix_oplocks_available(void) +{ + int fd; + int pfd[2]; + pstring tmpname; + + oplock_set_capability(True, False); + + slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid()); + + if(pipe(pfd) != 0) { + DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", + strerror(errno) )); + return False; + } + + if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) { + DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", + tmpname, strerror(errno) )); + unlink( tmpname ); + close(pfd[0]); + close(pfd[1]); + return False; + } + + unlink(tmpname); + + if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { + DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ +Disabling kernel oplock support.\n" )); + close(pfd[0]); + close(pfd[1]); + close(fd); + return False; + } + + if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) { + DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ +Disabling kernel oplock support.\n", strerror(errno) )); + close(pfd[0]); + close(pfd[1]); + close(fd); + return False; + } + + close(pfd[0]); + close(pfd[1]); + close(fd); + + return True; +} + + + +/**************************************************************************** + * Deal with the IRIX kernel <--> smbd + * oplock break protocol. +****************************************************************************/ +static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) +{ + oplock_stat_t os; + SMB_DEV_T dev; + SMB_INO_T inode; + char dummy; + + /* + * Read one byte of zero to clear the + * kernel break notify message. + */ + + if(read(oplock_pipe_read, &dummy, 1) != 1) { + DEBUG(0,("receive_local_message: read of kernel notification failed. \ +Error was %s.\n", strerror(errno) )); + smb_read_error = READ_ERROR; + return False; + } + + /* + * Do a query to get the + * device and inode of the file that has the break + * request outstanding. + */ + + if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { + DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ +Error was %s.\n", strerror(errno) )); + if(errno == EAGAIN) { + /* + * Duplicate kernel break message - ignore. + */ + memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); + return True; + } + smb_read_error = READ_ERROR; + return False; + } + + dev = (SMB_DEV_T)os.os_dev; + inode = (SMB_INO_T)os.os_ino; + + DEBUG(5,("receive_local_message: kernel oplock break request received for \ +dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); + + /* + * Create a kernel oplock break message. + */ + + /* Setup the message header */ + SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); + SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); + + buffer += OPBRK_CMD_HEADER_LEN; + + SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); + + memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); + + return True; +} + + +/**************************************************************************** + Attempt to set an kernel oplock on a file. +****************************************************************************/ +static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) +{ + if (fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) == -1) { + if(errno != EAGAIN) { + DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ +inode = %.0f. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, + strerror(errno) )); + } else { + DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ +inode = %.0f. Another process had the file open.\n", + fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode )); + } + return False; + } + + DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); + + return True; +} + + +/**************************************************************************** + Release a kernel oplock on a file. +****************************************************************************/ +static void irix_release_kernel_oplock(files_struct *fsp) +{ + if (DEBUGLVL(10)) { + /* + * Check and print out the current kernel + * oplock state of this file. + */ + int state = fcntl(fsp->fd, F_OPLKACK, -1); + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ +oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, state ); + } + + /* + * Remove the kernel oplock on this file. + */ + if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { + if( DEBUGLVL( 0 )) { + dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); + dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, strerror(errno) ); + } + } +} + + +/**************************************************************************** +parse a kernel oplock message +****************************************************************************/ +static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode, SMB_DEV_T *dev) +{ + /* Ensure that the msg length is correct. */ + if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { + DEBUG(0,("process_local_message: incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, \ +should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); + return False; + } + + memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); + memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); + + DEBUG(5,("process_local_message: kernel oplock break request for \ +file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); + + return True; +} + + +/**************************************************************************** +set *maxfd to include oplock read pipe +****************************************************************************/ +static BOOL irix_oplock_msg_waiting(fd_set *fds) +{ + if (oplock_pipe_read == -1) return False; + + return FD_ISSET(oplock_pipe_read,fds); +} + + +/**************************************************************************** +setup kernel oplocks +****************************************************************************/ +struct kernel_oplocks *irix_init_kernel_oplocks(void) +{ + int pfd[2]; + static struct kernel_oplocks koplocks; + + if (!irix_oplocks_available()) return NULL; + + if(pipe(pfd) != 0) { + DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n", + strerror(errno) )); + return False; + } + + oplock_pipe_read = pfd[0]; + oplock_pipe_write = pfd[1]; + + koplocks.receive_message = irix_oplock_receive_message; + koplocks.set_oplock = irix_set_kernel_oplock; + koplocks.release_oplock = irix_release_kernel_oplock; + koplocks.parse_message = irix_kernel_oplock_parse; + koplocks.msg_waiting = irix_oplock_msg_waiting; + koplocks.notification_fd = oplock_pipe_read; + + return &koplocks; +} + + + +#else + void oplock_irix_dummy(void) {} +#endif /* HAVE_KERNEL_OPLOCKS_IRIX */ + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 72c0cb105d..ecf1deb05a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -259,12 +259,6 @@ max can be %d\n", done correctly in the process. */ reset_globals_after_fork(); - /* - * Ensure this child has kernel oplock - * capabilities, but not it's children. - */ - oplock_set_capability(True, False); - return True; } /* The parent doesn't need this socket */ @@ -723,8 +717,6 @@ static void usage(char *pname) mkdir(lp_lockdir(), 0755); } - check_kernel_oplocks(); - if (is_daemon) { pidfile_create("smbd"); } @@ -733,20 +725,20 @@ static void usage(char *pname) exit(1); /* - * Note that this call should be done after the fork() call - * in open_sockets(), as some versions of the locking shared - * memory code register openers in a flat file. + * everything after this point is run after the fork() */ - if (!locking_init(0)) + if (!locking_init(0)) { exit(1); + } if (!print_backend_init()) { exit(1); } - if(!initialize_password_db()) + if(!initialize_password_db()) { exit(1); + } /* possibly reload the services file. */ reload_services(True); @@ -761,9 +753,10 @@ static void usage(char *pname) DEBUG(2,("Changed root to %s\n", lp_rootdir())); } - /* Setup the oplock IPC socket. */ - if( !open_oplock_ipc() ) + /* Setup oplocks */ + if (!init_oplocks()) { exit(1); + } smbd_process(); -- cgit From 26848a3478ab132cd924f14a66f85f74c2433329 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Jun 2000 14:29:31 +0000 Subject: a first pass at Linux kernel oplocks support (This used to be commit 3253085d9883a181c04b9c9ecf7d0ccdfbcee88d) --- source3/smbd/oplock.c | 13 --- source3/smbd/oplock_irix.c | 4 +- source3/smbd/oplock_linux.c | 205 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 15 deletions(-) create mode 100644 source3/smbd/oplock_linux.c (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 33d82f3dde..44a8e9b071 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1021,22 +1021,9 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; -#if HAVE_KERNEL_OPLOCKS_IRIX - if((reply_msg_len != OPLOCK_BREAK_MSG_LEN) && (reply_msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN)) -#else - if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) -#endif - { - /* Ignore it. */ - DEBUG( 0, ( "request_oplock_break: invalid message length (%d) received.", reply_msg_len ) ); - DEBUGADD( 0, ( " Ignoring.\n" ) ); - continue; - } - /* * Test to see if this is the reply we are awaiting. */ - if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) && ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == OPLOCK_BREAK_CMD) && (reply_from_port == share_entry->op_port) && diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 0820c4048d..6eb8ff9191 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -3,8 +3,8 @@ /* Unix SMB/Netbios implementation. - Version 1.9. - oplock processing + Version 2.x + IRIX kernel oplock processing Copyright (C) Andrew Tridgell 1992-1998 This program is free software; you can redistribute it and/or modify diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c new file mode 100644 index 0000000000..d8496ca9ca --- /dev/null +++ b/source3/smbd/oplock_linux.c @@ -0,0 +1,205 @@ +#define OLD_NTDOMAIN 1 +#if HAVE_KERNEL_OPLOCKS_LINUX + +/* + Unix SMB/Netbios implementation. + Version 3.0 + kernel oplock processing for Linux + Copyright (C) Andrew Tridgell 2000 + + 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; + +static unsigned signals_received; +static unsigned signals_processed; +static int fd_pending; /* the fd of the current pending SIGIO */ + +/**************************************************************************** +handle a SIGIO, incrementing the signals_received and blocking SIGIO +****************************************************************************/ +static void sigio_handler(int signal, siginfo_t *info, void *unused) +{ + fd_pending = info->si_fd; + signals_received++; + BlockSignals(True, SIGIO); +} + +/**************************************************************************** + * Deal with the Linux kernel <--> smbd + * oplock break protocol. +****************************************************************************/ +static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) +{ + SMB_DEV_T dev; + SMB_INO_T inode; + SMB_STRUCT_STAT sbuf; + BOOL ret; + + if (signals_received == signals_processed) return False; + + if (sys_fstat(fd_pending,&sbuf) == -1) { + DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", fd_pending)); + ret = False; + goto out; + } + + dev = sbuf.st_dev; + inode = sbuf.st_ino; + + DEBUG(5,("receive_local_message: kernel oplock break request received for \ +dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); + + /* + * Create a kernel oplock break message. + */ + + /* Setup the message header */ + SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); + SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); + + buffer += OPBRK_CMD_HEADER_LEN; + + SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); + + memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); + + out: + /* now we can receive more signals */ + fd_pending = -1; + signals_processed++; + BlockSignals(False, SIGIO); + + return True; +} + + +/**************************************************************************** + Attempt to set an kernel oplock on a file. +****************************************************************************/ +static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) +{ + if (fcntl(fsp->fd, F_SETLEASE, F_WRLCK) == -1) { + DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ +inode = %.0f.\n", + fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode)); + return False; + } + + DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); + + return True; +} + + +/**************************************************************************** + Release a kernel oplock on a file. +****************************************************************************/ +static void linux_release_kernel_oplock(files_struct *fsp) +{ + if (DEBUGLVL(10)) { + /* + * Check and print out the current kernel + * oplock state of this file. + */ + int state = fcntl(fsp->fd, F_GETLEASE, 0); + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ +oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, state ); + } + + /* + * Remove the kernel oplock on this file. + */ + if (fcntl(fsp->fd, F_SETLEASE, F_UNLCK) == -1) { + if (DEBUGLVL(0)) { + dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); + dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, strerror(errno) ); + } + } +} + + +/**************************************************************************** +parse a kernel oplock message +****************************************************************************/ +static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode, SMB_DEV_T *dev) +{ + /* Ensure that the msg length is correct. */ + if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { + DEBUG(0,("process_local_message: incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, \ +should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); + return False; + } + + memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); + memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); + + DEBUG(5,("process_local_message: kernel oplock break request for \ +file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); + + return True; +} + + +/**************************************************************************** +see if a oplock message is waiting +****************************************************************************/ +static BOOL linux_oplock_msg_waiting(fd_set *fds) +{ + return signals_processed != signals_received; +} + + +/**************************************************************************** +setup kernel oplocks +****************************************************************************/ +struct kernel_oplocks *linux_init_kernel_oplocks(void) +{ + static struct kernel_oplocks koplocks; + struct sigaction act; + + act.sa_handler = NULL; + act.sa_sigaction = sigio_handler; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGIO, &act, NULL) != 0) { + DEBUG(0,("Failed to setup SIGIO handler\n")); + return NULL; + } + + koplocks.receive_message = linux_oplock_receive_message; + koplocks.set_oplock = linux_set_kernel_oplock; + koplocks.release_oplock = linux_release_kernel_oplock; + koplocks.parse_message = linux_kernel_oplock_parse; + koplocks.msg_waiting = linux_oplock_msg_waiting; + koplocks.notification_fd = -1; + + return &koplocks; +} + + + +#else + void oplock_linux_dummy(void) {} +#endif /* HAVE_KERNEL_OPLOCKS_LINUX */ + +#undef OLD_NTDOMAIN -- cgit From 8843a6379d7c1cf59f0f3673cbc567b09994b7d2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Jun 2000 05:57:58 +0000 Subject: Linux kernel oplocks now seem to work, but need a _lot_ of testing I had to modify sys_select() to not loop on EINTR. I added a wrapper called sys_select_intr() which gives the old behaviour. (This used to be commit b28cc4163bc2faaa80c5782fc02c8f03c410cdeb) --- source3/smbd/oplock.c | 9 ++++ source3/smbd/oplock_irix.c | 4 +- source3/smbd/oplock_linux.c | 63 +++++++++++++++++++++++--- source3/smbd/process.c | 107 +++++++++++++++++++++++--------------------- source3/smbd/server.c | 2 +- 5 files changed, 125 insertions(+), 60 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 44a8e9b071..5e63b4d4ff 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -84,6 +84,13 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou selrtn = sys_select(maxfd+1,fds,&to); + if (selrtn == -1 && errno == EINTR) { + /* could be a kernel oplock interrupt */ + if (koplocks && koplocks->msg_waiting(fds)) { + return koplocks->receive_message(fds, buffer, buffer_len); + } + } + /* Check if error */ if(selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ @@ -1120,6 +1127,8 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); if (lp_kernel_oplocks()) { #if HAVE_KERNEL_OPLOCKS_IRIX koplocks = irix_init_kernel_oplocks(); +#elif HAVE_KERNEL_OPLOCKS_LINUX + koplocks = linux_init_kernel_oplocks(); #endif } diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 6eb8ff9191..8d55a3d4a0 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -1,5 +1,4 @@ #define OLD_NTDOMAIN 1 -#if HAVE_KERNEL_OPLOCKS_IRIX /* Unix SMB/Netbios implementation. @@ -24,6 +23,7 @@ #include "includes.h" +#if HAVE_KERNEL_OPLOCKS_IRIX extern int DEBUGLEVEL; @@ -227,7 +227,7 @@ should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); DEBUG(5,("process_local_message: kernel oplock break request for \ -file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); +file dev = %x, inode = %.0f\n", (unsigned int)*dev, (double)*inode)); return True; } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index d8496ca9ca..73a14b3e88 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -1,5 +1,4 @@ #define OLD_NTDOMAIN 1 -#if HAVE_KERNEL_OPLOCKS_LINUX /* Unix SMB/Netbios implementation. @@ -24,12 +23,27 @@ #include "includes.h" +#if HAVE_KERNEL_OPLOCKS_LINUX + extern int DEBUGLEVEL; static unsigned signals_received; static unsigned signals_processed; static int fd_pending; /* the fd of the current pending SIGIO */ +/* these can be removed when they are in libc */ +typedef struct __user_cap_header_struct { + uint32 version; + int pid; +} *cap_user_header_t; + +typedef struct __user_cap_data_struct { + uint32 effective; + uint32 permitted; + uint32 inheritable; +} *cap_user_data_t; + + /**************************************************************************** handle a SIGIO, incrementing the signals_received and blocking SIGIO ****************************************************************************/ @@ -40,6 +54,41 @@ static void sigio_handler(int signal, siginfo_t *info, void *unused) BlockSignals(True, SIGIO); } +/**************************************************************************** +try to gain the CAP_LEASE capability +****************************************************************************/ +static void set_lease_capability(void) +{ + cap_user_header_t header; + cap_user_data_t data; + if (capget(header, data) == -1) { + DEBUG(3,("Unable to get kernel capabilities\n")); + return; + } + data->effective |= (1< smbd * oplock break protocol. @@ -95,10 +144,11 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); ****************************************************************************/ static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (fcntl(fsp->fd, F_SETLEASE, F_WRLCK) == -1) { + if (linux_setlease(fsp->fd, F_WRLCK) == -1) { DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ -inode = %.0f.\n", - fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode)); +inode = %.0f. (%s)\n", + fsp->fsp_name, fsp->fd, + (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno))); return False; } @@ -128,7 +178,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /* * Remove the kernel oplock on this file. */ - if (fcntl(fsp->fd, F_SETLEASE, F_UNLCK) == -1) { + if (linux_setlease(fsp->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", @@ -155,7 +205,7 @@ should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); DEBUG(5,("process_local_message: kernel oplock break request for \ -file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode)); +file dev = %x, inode = %.0f\n", (unsigned int)*dev, (double)*inode)); return True; } @@ -203,3 +253,4 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) #endif /* HAVE_KERNEL_OPLOCKS_LINUX */ #undef OLD_NTDOMAIN + diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 82e61a138e..30d03747d8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -134,69 +134,74 @@ The timeout is in milli seconds static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout, BOOL *got_smb) { - fd_set fds; - int selrtn; - struct timeval to; - int maxfd; + fd_set fds; + int selrtn; + struct timeval to; + int maxfd; - smb_read_error = 0; + smb_read_error = 0; - *got_smb = False; + *got_smb = False; - /* - * Check to see if we already have a message on the smb queue. - * If so - copy and return it. - */ + /* + * Check to see if we already have a message on the smb queue. + * If so - copy and return it. + */ - if(ubi_slCount(&smb_oplock_queue) != 0) - { - pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue); - memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); + if(ubi_slCount(&smb_oplock_queue) != 0) { + pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue); + memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); - /* Free the message we just copied. */ - free((char *)msg->msg_buf); - free((char *)msg); - *got_smb = True; + /* Free the message we just copied. */ + free((char *)msg->msg_buf); + free((char *)msg); + *got_smb = True; + + DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); + return True; + } - DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); - return True; - } + /* + * Setup the select read fd set. + */ - /* - * Setup the select read fd set. - */ + FD_ZERO(&fds); + FD_SET(smbd_server_fd(),&fds); + maxfd = setup_oplock_select_set(&fds); - FD_ZERO(&fds); - FD_SET(smbd_server_fd(),&fds); - maxfd = setup_oplock_select_set(&fds); + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; + selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL); - selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL); + /* if we get EINTR then maybe we have received an oplock + signal - treat this as select returning 1. This is ugly, but + is the best we can do until the oplock code knows more about + signals */ + if (selrtn == -1 && errno == EINTR) { + FD_ZERO(&fds); + selrtn = 1; + } - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } + /* Check if error */ + if(selrtn == -1 && errno != EINTR) { + /* something is wrong. Maybe the socket is dead? */ + smb_read_error = READ_ERROR; + return False; + } - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return False; - } - - if (FD_ISSET(smbd_server_fd(),&fds)) - { - *got_smb = True; - return receive_smb(smbd_server_fd(), buffer, 0); - } - else - { - return receive_local_message(&fds, buffer, buffer_len, 0); - } + /* Did we timeout ? */ + if (selrtn == 0) { + smb_read_error = READ_TIMEOUT; + return False; + } + + if (FD_ISSET(smbd_server_fd(),&fds)) { + *got_smb = True; + return receive_smb(smbd_server_fd(), buffer, 0); + } else { + return receive_local_message(&fds, buffer, buffer_len, 0); + } } /**************************************************************************** diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ecf1deb05a..a5da156250 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -203,7 +203,7 @@ max can be %d\n", memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select(FD_SETSIZE,&lfds,NULL); + num = sys_select_intr(FD_SETSIZE,&lfds,NULL); if (num == -1 && errno == EINTR) continue; -- cgit From 0fb1dbe7fa0da5a1374e4a8cb9c3e922c9a08c8d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Jun 2000 06:24:54 +0000 Subject: fixed Linux capabilities handling I used a trick where CAP_LEASE isn't claimed until it is needed. This means we avoid a system call per setreuid(), and never call capset() unless a user tries to get a oplock on a file that they don't own (This used to be commit afa98d511f70f455d599c3a36dd25e49fe74ac09) --- source3/smbd/oplock_linux.c | 60 +++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 73a14b3e88..ae0a72d0f6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -31,18 +31,18 @@ static unsigned signals_received; static unsigned signals_processed; static int fd_pending; /* the fd of the current pending SIGIO */ -/* these can be removed when they are in libc */ -typedef struct __user_cap_header_struct { - uint32 version; - int pid; -} *cap_user_header_t; - -typedef struct __user_cap_data_struct { - uint32 effective; - uint32 permitted; - uint32 inheritable; -} *cap_user_data_t; +#ifndef F_SETLEASE +#define F_SETLEASE 1024 +#endif + +#ifndef F_GETLEASE +#define F_GETLEASE 1025 +#endif + +#ifndef CAP_LEASE +#define CAP_LEASE 28 +#endif /**************************************************************************** handle a SIGIO, incrementing the signals_received and blocking SIGIO @@ -55,19 +55,37 @@ static void sigio_handler(int signal, siginfo_t *info, void *unused) } /**************************************************************************** -try to gain the CAP_LEASE capability +try to gain a linux capability ****************************************************************************/ -static void set_lease_capability(void) +static void set_capability(unsigned capability) { - cap_user_header_t header; - cap_user_data_t data; - if (capget(header, data) == -1) { - DEBUG(3,("Unable to get kernel capabilities\n")); +#ifndef _LINUX_CAPABILITY_VERSION +#define _LINUX_CAPABILITY_VERSION 0x19980330 +#endif + /* these can be removed when they are in glibc headers */ + struct { + uint32 version; + int pid; + } header; + struct { + uint32 effective; + uint32 permitted; + uint32 inheritable; + } data; + + header.version = _LINUX_CAPABILITY_VERSION; + header.pid = 0; + + if (capget(&header, &data) == -1) { + DEBUG(3,("Unable to get kernel capabilities (%s)\n", strerror(errno))); return; } - data->effective |= (1< Date: Sun, 11 Jun 2000 06:46:05 +0000 Subject: a better test for oplocks being enabled in this kernel (This used to be commit cc0e919fdcb116c8f9688a4f5d7803fc8d7f9588) --- source3/smbd/oplock_linux.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index ae0a72d0f6..46290683d2 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -31,7 +31,6 @@ static unsigned signals_received; static unsigned signals_processed; static int fd_pending; /* the fd of the current pending SIGIO */ - #ifndef F_SETLEASE #define F_SETLEASE 1024 #endif @@ -237,6 +236,19 @@ static BOOL linux_oplock_msg_waiting(fd_set *fds) return signals_processed != signals_received; } +/**************************************************************************** +see if the kernel supports oplocks +****************************************************************************/ +static BOOL linux_oplocks_available(void) +{ + int fd, ret; + fd = open("/dev/null", O_RDONLY); + if (fd == -1) return False; /* uggh! */ + ret = fcntl(fd, F_GETLEASE, 0); + close(fd); + return ret == F_UNLCK; +} + /**************************************************************************** setup kernel oplocks @@ -246,6 +258,11 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) static struct kernel_oplocks koplocks; struct sigaction act; + if (!linux_oplocks_available()) { + DEBUG(3,("Linux kernel oplocks not available\n")); + return NULL; + } + act.sa_handler = NULL; act.sa_sigaction = sigio_handler; act.sa_flags = SA_SIGINFO; -- cgit From 6db12f718007592cf971b22f376fde796e637727 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 05:32:28 +0000 Subject: split all the change notify code out into a separate module smbd/notify.c. All the data structures are now private to that module. this is in preparation for Linux kernel support for change notify (coming soon to a CVS tree near you) (This used to be commit 1bb0aad4f66dbfa2d0f767ea90f926affff20b17) --- source3/smbd/notify.c | 392 +++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/nttrans.c | 427 ++++--------------------------------------------- 2 files changed, 427 insertions(+), 392 deletions(-) create mode 100644 source3/smbd/notify.c (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c new file mode 100644 index 0000000000..26be17c590 --- /dev/null +++ b/source3/smbd/notify.c @@ -0,0 +1,392 @@ +#define OLD_NTDOMAIN 1 +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB NT transaction handling + Copyright (C) Jeremy Allison 1994-1998 + + 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; + +/**************************************************************************** + This is the structure to keep the information needed to + determine if a directory has changed. +*****************************************************************************/ + +typedef struct { + time_t modify_time; /* Info from the directory we're monitoring. */ + time_t status_time; /* Info from the directory we're monitoring. */ + time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ + unsigned int num_entries; /* Zero or the number of files in the directory. */ +} change_hash_data; + +/**************************************************************************** + This is the structure to queue to implement NT change + notify. It consists of smb_size bytes stored from the + transact command (to keep the mid, tid etc around). + Plus the fid to examine and the time to check next. +*****************************************************************************/ + +typedef struct { + ubi_slNode msg_next; + files_struct *fsp; + connection_struct *conn; + uint32 flags; + time_t next_check_time; + change_hash_data change_data; + char request_buf[smb_size]; +} change_notify_buf; + +static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_queue, 0}; + +/**************************************************************************** + Setup the common parts of the return packet and send it. +*****************************************************************************/ + +static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) +{ + char outbuf[smb_size+38]; + + memset(outbuf, '\0', sizeof(outbuf)); + construct_reply_common(inbuf, outbuf); + + /* + * If we're returning a 'too much in the directory changed' we need to + * set this is an NT error status flags. If we don't then the (probably + * untested) code in the NT redirector has a bug in that it doesn't re-issue + * the change notify.... Ah - I *love* it when I get so deeply into this I + * can even determine how MS failed to test stuff and why.... :-). JRA. + */ + + if(error_class == 0) /* NT Error. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + + ERROR(error_class,error_code); + + /* + * Seems NT needs a transact command with an error code + * in it. This is a longer packet than a simple error. + */ + set_message(outbuf,18,0,False); + + send_smb(smbd_server_fd(),outbuf); +} + +/**************************************************************************** + Create the hash we will use to determine if the contents changed. +*****************************************************************************/ + +static BOOL create_directory_notify_hash( change_notify_buf *cnbp, change_hash_data *change_data) +{ + SMB_STRUCT_STAT st; + files_struct *fsp = cnbp->fsp; + + memset((char *)change_data, '\0', sizeof(change_data)); + + /* + * Store the current timestamp on the directory we are monitoring. + */ + + if(dos_stat(fsp->fsp_name, &st) < 0) { + DEBUG(0,("create_directory_notify_hash: Unable to stat name = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + return False; + } + + change_data->modify_time = st.st_mtime; + change_data->status_time = st.st_ctime; + + /* + * If we are to watch for changes that are only stored + * in inodes of files, not in the directory inode, we must + * scan the directory and produce a unique identifier with + * which we can determine if anything changed. We use the + * modify and change times from all the files in the + * directory, added together (ignoring wrapping if it's + * larger than the max time_t value). + */ + + if(cnbp->flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE)) { + pstring full_name; + char *p; + char *fname; + size_t remaining_len; + size_t fullname_len; + void *dp = OpenDir(cnbp->conn, fsp->fsp_name, True); + + if(dp == NULL) { + DEBUG(0,("create_directory_notify_hash: Unable to open directory = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + return False; + } + + change_data->num_entries = 0; + + pstrcpy(full_name, fsp->fsp_name); + pstrcat(full_name, "/"); + + fullname_len = strlen(full_name); + remaining_len = sizeof(full_name) - fullname_len - 1; + p = &full_name[fullname_len]; + + while ((fname = ReadDirName(dp))) { + if(strequal(fname, ".") || strequal(fname, "..")) + continue; + + change_data->num_entries++; + safe_strcpy( p, fname, remaining_len); + + memset(&st, '\0', sizeof(st)); + + /* + * Do the stat - but ignore errors. + */ + + if(dos_stat(full_name, &st) < 0) { + DEBUG(5,("create_directory_notify_hash: Unable to stat content file = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + } + change_data->total_time += (st.st_mtime + st.st_ctime); + } + + CloseDir(dp); + } + + return True; +} + +/**************************************************************************** + Delete entries by fnum from the change notify pending queue. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_fid(files_struct *fsp) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + if(cnbp->fsp->fnum == fsp->fnum) { + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Delete entries by mid from the change notify pending queue. Always send reply. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_mid(int mid) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + if(SVAL(cnbp->request_buf,smb_mid) == mid) { + change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Delete entries by filename and cnum from the change notify pending queue. + Always send reply. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_filename(files_struct *fsp) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + /* + * We know it refers to the same directory if the connection number and + * the filename are identical. + */ + if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { + change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Process the change notify queue. Note that this is only called as root. + Returns True if there are still outstanding change notify requests on the + queue. +*****************************************************************************/ + +BOOL process_pending_change_notify_queue(time_t t) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + if(cnbp == NULL) + return False; + + if(cnbp->next_check_time >= t) + return True; + + /* + * It's time to check. Go through the queue and see if + * the timestamps changed. + */ + + while((cnbp != NULL) && (cnbp->next_check_time <= t)) { + change_hash_data change_data; + connection_struct *conn = cnbp->conn; + uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(cnbp->request_buf,smb_uid); + + ZERO_STRUCT(change_data); + + /* + * Ensure we don't have any old chain_fsp values + * sitting around.... + */ + chain_size = 0; + file_chain_reset(); + + if(!become_user(conn,vuid)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + if(!become_service(conn,True)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to become service Error was %s.\n", strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + if(!create_directory_notify_hash( cnbp, &change_data)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to create change data for \ +directory %s\n", cnbp->fsp->fsp_name )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + if(memcmp( (char *)&cnbp->change_data, (char *)&change_data, sizeof(change_data))) { + /* + * Remove the entry and return a change notify to the client. + */ + DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed.\n", + cnbp->fsp->fsp_name )); + change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + unbecome_user(); + + /* + * Move to the next in the list. + */ + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } + + return (cnbp != NULL); +} + +/**************************************************************************** + Return true if there are pending change notifies. +****************************************************************************/ +BOOL change_notifies_pending(void) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + return (cnbp != NULL); +} + +/**************************************************************************** + * Now queue an entry on the notify change stack. We timestamp + * the entry we are adding so that we know when to scan next. + * We only need to save smb_size bytes from this incoming packet + * as we will always by returning a 'read the directory yourself' + * error. +****************************************************************************/ +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) +{ + change_notify_buf *cnbp; + + if((cnbp = (change_notify_buf *)malloc(sizeof(change_notify_buf))) == NULL) { + DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); + return -1; + } + + ZERO_STRUCTP(cnbp); + + memcpy(cnbp->request_buf, inbuf, smb_size); + cnbp->fsp = fsp; + cnbp->conn = conn; + cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); + cnbp->flags = flags; + + if (!create_directory_notify_hash(cnbp, &cnbp->change_data)) { + free((char *)cnbp); + return False; + } + + /* + * Adding to the tail enables us to check only + * the head when scanning for change, as this entry + * is forced to have the first timeout expiration. + */ + + ubi_slAddTail(&change_notify_queue, cnbp); + + return True; +} + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8b3eabff80..4e4e418efd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -30,8 +30,6 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -static void remove_pending_change_notify_requests_by_mid(int mid); - static char *known_nt_pipes[] = { "\\LANMAN", "\\srvsvc", @@ -1407,6 +1405,41 @@ int reply_nttranss(connection_struct *conn, return(-1); } +/**************************************************************************** + Reply to a notify change - queue the request and + don't allow a directory to be opened. +****************************************************************************/ +static int call_nt_transact_notify_change(connection_struct *conn, + char *inbuf, char *outbuf, int length, + int bufsize, + char **ppsetup, + char **ppparams, char **ppdata) +{ + char *setup = *ppsetup; + files_struct *fsp; + uint32 flags; + + fsp = file_fsp(setup,4); + flags = IVAL(setup, 0); + + DEBUG(3,("call_nt_transact_notify_change\n")); + + if(!fsp) + return(ERROR(ERRDOS,ERRbadfid)); + + if((!fsp->is_directory) || (conn != fsp->conn)) + return(ERROR(ERRDOS,ERRbadfid)); + + if (!change_notify_set(inbuf, fsp, conn, flags)) { + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + + DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ +name = %s\n", fsp->fsp_name )); + + return -1; +} + /**************************************************************************** Reply to an NT transact rename command. ****************************************************************************/ @@ -1445,396 +1478,6 @@ static int call_nt_transact_rename(connection_struct *conn, return(outsize); } -/**************************************************************************** - This is the structure to keep the information needed to - determine if a directory has changed. -*****************************************************************************/ - -typedef struct { - time_t modify_time; /* Info from the directory we're monitoring. */ - time_t status_time; /* Info from the directory we're monitoring. */ - time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ - unsigned int num_entries; /* Zero or the number of files in the directory. */ -} change_hash_data; - -/**************************************************************************** - This is the structure to queue to implement NT change - notify. It consists of smb_size bytes stored from the - transact command (to keep the mid, tid etc around). - Plus the fid to examine and the time to check next. -*****************************************************************************/ - -typedef struct { - ubi_slNode msg_next; - files_struct *fsp; - connection_struct *conn; - uint32 flags; - time_t next_check_time; - change_hash_data change_data; - char request_buf[smb_size]; -} change_notify_buf; - -static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_queue, 0}; - -/**************************************************************************** - Setup the common parts of the return packet and send it. -*****************************************************************************/ - -static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) -{ - char outbuf[smb_size+38]; - - memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); - - /* - * If we're returning a 'too much in the directory changed' we need to - * set this is an NT error status flags. If we don't then the (probably - * untested) code in the NT redirector has a bug in that it doesn't re-issue - * the change notify.... Ah - I *love* it when I get so deeply into this I - * can even determine how MS failed to test stuff and why.... :-). JRA. - */ - - if(error_class == 0) /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - - ERROR(error_class,error_code); - - /* - * Seems NT needs a transact command with an error code - * in it. This is a longer packet than a simple error. - */ - set_message(outbuf,18,0,False); - - send_smb(smbd_server_fd(),outbuf); -} - -/**************************************************************************** - Create the hash we will use to determine if the contents changed. -*****************************************************************************/ - -static BOOL create_directory_notify_hash( change_notify_buf *cnbp, change_hash_data *change_data) -{ - SMB_STRUCT_STAT st; - files_struct *fsp = cnbp->fsp; - - memset((char *)change_data, '\0', sizeof(change_data)); - - /* - * Store the current timestamp on the directory we are monitoring. - */ - - if(dos_stat(fsp->fsp_name, &st) < 0) { - DEBUG(0,("create_directory_notify_hash: Unable to stat name = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - return False; - } - - change_data->modify_time = st.st_mtime; - change_data->status_time = st.st_ctime; - - /* - * If we are to watch for changes that are only stored - * in inodes of files, not in the directory inode, we must - * scan the directory and produce a unique identifier with - * which we can determine if anything changed. We use the - * modify and change times from all the files in the - * directory, added together (ignoring wrapping if it's - * larger than the max time_t value). - */ - - if(cnbp->flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE)) { - pstring full_name; - char *p; - char *fname; - size_t remaining_len; - size_t fullname_len; - void *dp = OpenDir(cnbp->conn, fsp->fsp_name, True); - - if(dp == NULL) { - DEBUG(0,("create_directory_notify_hash: Unable to open directory = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - return False; - } - - change_data->num_entries = 0; - - pstrcpy(full_name, fsp->fsp_name); - pstrcat(full_name, "/"); - - fullname_len = strlen(full_name); - remaining_len = sizeof(full_name) - fullname_len - 1; - p = &full_name[fullname_len]; - - while ((fname = ReadDirName(dp))) { - if(strequal(fname, ".") || strequal(fname, "..")) - continue; - - change_data->num_entries++; - safe_strcpy( p, fname, remaining_len); - - memset(&st, '\0', sizeof(st)); - - /* - * Do the stat - but ignore errors. - */ - - if(dos_stat(full_name, &st) < 0) { - DEBUG(5,("create_directory_notify_hash: Unable to stat content file = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - } - change_data->total_time += (st.st_mtime + st.st_ctime); - } - - CloseDir(dp); - } - - return True; -} - -/**************************************************************************** - Delete entries by fnum from the change notify pending queue. -*****************************************************************************/ - -void remove_pending_change_notify_requests_by_fid(files_struct *fsp) -{ - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - if(cnbp->fsp->fnum == fsp->fnum) { - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } -} - -/**************************************************************************** - Delete entries by mid from the change notify pending queue. Always send reply. -*****************************************************************************/ - -static void remove_pending_change_notify_requests_by_mid(int mid) -{ - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } -} - -/**************************************************************************** - Delete entries by filename and cnum from the change notify pending queue. - Always send reply. -*****************************************************************************/ - -void remove_pending_change_notify_requests_by_filename(files_struct *fsp) -{ - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - /* - * We know it refers to the same directory if the connection number and - * the filename are identical. - */ - if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } -} - -/**************************************************************************** - Process the change notify queue. Note that this is only called as root. - Returns True if there are still outstanding change notify requests on the - queue. -*****************************************************************************/ - -BOOL process_pending_change_notify_queue(time_t t) -{ - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - if(cnbp == NULL) - return False; - - if(cnbp->next_check_time >= t) - return True; - - /* - * It's time to check. Go through the queue and see if - * the timestamps changed. - */ - - while((cnbp != NULL) && (cnbp->next_check_time <= t)) { - change_hash_data change_data; - connection_struct *conn = cnbp->conn; - uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(cnbp->request_buf,smb_uid); - - ZERO_STRUCT(change_data); - - /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - file_chain_reset(); - - if(!become_user(conn,vuid)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", - vuid )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - if(!become_service(conn,True)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to become service Error was %s.\n", strerror(errno) )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - if(!create_directory_notify_hash( cnbp, &change_data)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to create change data for \ -directory %s\n", cnbp->fsp->fsp_name )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - if(memcmp( (char *)&cnbp->change_data, (char *)&change_data, sizeof(change_data))) { - /* - * Remove the entry and return a change notify to the client. - */ - DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed.\n", - cnbp->fsp->fsp_name )); - change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - unbecome_user(); - - /* - * Move to the next in the list. - */ - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } - - return (cnbp != NULL); -} - -/**************************************************************************** - Return true if there are pending change notifies. -****************************************************************************/ - -BOOL change_notifies_pending(void) -{ - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - return (cnbp != NULL); -} - -/**************************************************************************** - Reply to a notify change - queue the request and - don't allow a directory to be opened. -****************************************************************************/ - -static int call_nt_transact_notify_change(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, - char **ppparams, char **ppdata) -{ - char *setup = *ppsetup; - files_struct *fsp; - change_notify_buf *cnbp; - - fsp = file_fsp(setup,4); - - DEBUG(3,("call_nt_transact_notify_change\n")); - - if(!fsp) - return(ERROR(ERRDOS,ERRbadfid)); - - if((!fsp->is_directory) || (conn != fsp->conn)) - return(ERROR(ERRDOS,ERRbadfid)); - - /* - * Now queue an entry on the notify change stack. We timestamp - * the entry we are adding so that we know when to scan next. - * We only need to save smb_size bytes from this incoming packet - * as we will always by returning a 'read the directory yourself' - * error. - */ - - if((cnbp = (change_notify_buf *)malloc(sizeof(change_notify_buf))) == NULL) { - DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); - return -1; - } - - memset((char *)cnbp, '\0', sizeof(change_notify_buf)); - - memcpy(cnbp->request_buf, inbuf, smb_size); - cnbp->fsp = fsp; - cnbp->conn = conn; - cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); - cnbp->flags = IVAL(setup, 0); - - if(!create_directory_notify_hash( cnbp, &cnbp->change_data )) { - free((char *)cnbp); - return(UNIXERROR(ERRDOS,ERRbadfid)); - } - - /* - * Adding to the tail enables us to check only - * the head when scanning for change, as this entry - * is forced to have the first timeout expiration. - */ - - ubi_slAddTail(&change_notify_queue, cnbp); - - DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ -name = %s\n", fsp->fsp_name )); - - return -1; -} /**************************************************************************** Reply to query a security descriptor - currently this is not implemented (it -- cgit From 2b37fd8435fa2ee20395e028d0371a0eca7785ff Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 05:34:14 +0000 Subject: fixed comments at top of module (This used to be commit 02577ab7d275dfb49e104f3358cb3caa66b3b09e) --- source3/smbd/notify.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 26be17c590..3af9da238f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -1,9 +1,10 @@ #define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. - Version 1.9. - SMB NT transaction handling + Version 3.0 + change notify handling Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Andrew Tridgell 2000 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 -- cgit From b2d01bd2dbfed8b35cc324fad42eac562fcad3b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 15:53:31 +0000 Subject: totally rewrote the async signal, notification and oplock notification handling in Samba. This was needed due to several limitations and races in the previous code - as a side effect the new code is much cleaner :) in summary: - changed sys_select() to avoid a signal/select race condition. It is a rare race but once we have signals doing notification and oplocks it is important. - changed our main processing loop to take advantage of the new sys_select semantics - split the notify code into implementaion dependent and general parts. Added the following structure that defines an implementation: struct cnotify_fns { void * (*register_notify)(connection_struct *conn, char *path, uint32 flags); BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t); void (*remove_notify)(void *data); }; then I wrote two implementations, one using hash/poll (like our old code) and the other using the new Linux kernel change notify. It should be easy to add other change notify implementations by creating a sructure of the above type. - fixed a bug in change notify where we were returning the wrong error code. - rewrote the core change notify code to be much simpler - moved to real-time signals for leases and change notify Amazingly, it all seems to work. I was very surprised! (This used to be commit 44766c39e0027c762bee8b33b12c621c109a3267) --- source3/smbd/notify.c | 401 +++++++++++++------------------------------ source3/smbd/notify_hash.c | 184 ++++++++++++++++++++ source3/smbd/notify_kernel.c | 170 ++++++++++++++++++ source3/smbd/oplock.c | 55 +++--- source3/smbd/oplock_irix.c | 8 +- source3/smbd/oplock_linux.c | 29 ++-- source3/smbd/process.c | 253 +++++++++++++-------------- source3/smbd/server.c | 12 +- 8 files changed, 647 insertions(+), 465 deletions(-) create mode 100644 source3/smbd/notify_hash.c create mode 100644 source3/smbd/notify_kernel.c (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 3af9da238f..40867a71ee 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -3,8 +3,8 @@ Unix SMB/Netbios implementation. Version 3.0 change notify handling - Copyright (C) Jeremy Allison 1994-1998 Copyright (C) Andrew Tridgell 2000 + Copyright (C) Jeremy Allison 1994-1998 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 @@ -25,221 +25,128 @@ extern int DEBUGLEVEL; -/**************************************************************************** - This is the structure to keep the information needed to - determine if a directory has changed. -*****************************************************************************/ - -typedef struct { - time_t modify_time; /* Info from the directory we're monitoring. */ - time_t status_time; /* Info from the directory we're monitoring. */ - time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ - unsigned int num_entries; /* Zero or the number of files in the directory. */ -} change_hash_data; +static struct cnotify_fns *cnotify; /**************************************************************************** This is the structure to queue to implement NT change notify. It consists of smb_size bytes stored from the transact command (to keep the mid, tid etc around). - Plus the fid to examine and the time to check next. + Plus the fid to examine and notify private data *****************************************************************************/ -typedef struct { - ubi_slNode msg_next; - files_struct *fsp; - connection_struct *conn; - uint32 flags; - time_t next_check_time; - change_hash_data change_data; - char request_buf[smb_size]; -} change_notify_buf; +struct change_notify { + struct change_notify *next, *prev; + files_struct *fsp; + connection_struct *conn; + uint32 flags; + char request_buf[smb_size]; + void *change_data; +}; -static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_queue, 0}; +static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ - -static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) +static void change_notify_reply_packet(char *inbuf, uint32 error_code) { - char outbuf[smb_size+38]; - - memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + char outbuf[smb_size+38]; - /* - * If we're returning a 'too much in the directory changed' we need to - * set this is an NT error status flags. If we don't then the (probably - * untested) code in the NT redirector has a bug in that it doesn't re-issue - * the change notify.... Ah - I *love* it when I get so deeply into this I - * can even determine how MS failed to test stuff and why.... :-). JRA. - */ + memset(outbuf, '\0', sizeof(outbuf)); + construct_reply_common(inbuf, outbuf); - if(error_class == 0) /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - - ERROR(error_class,error_code); + /* + * If we're returning a 'too much in the directory changed' we need to + * set this is an NT error status flags. If we don't then the (probably + * untested) code in the NT redirector has a bug in that it doesn't re-issue + * the change notify.... Ah - I *love* it when I get so deeply into this I + * can even determine how MS failed to test stuff and why.... :-). JRA. + */ + + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + ERROR(0,error_code); - /* - * Seems NT needs a transact command with an error code - * in it. This is a longer packet than a simple error. - */ - set_message(outbuf,18,0,False); + /* + * Seems NT needs a transact command with an error code + * in it. This is a longer packet than a simple error. + */ + set_message(outbuf,18,0,False); - send_smb(smbd_server_fd(),outbuf); + send_smb(smbd_server_fd(),outbuf); } /**************************************************************************** - Create the hash we will use to determine if the contents changed. +remove an entry from the list and free it, also closing any +directory handle if necessary +Notice the horrible stuff we have to do because this is a singly linked list. *****************************************************************************/ - -static BOOL create_directory_notify_hash( change_notify_buf *cnbp, change_hash_data *change_data) +static void change_notify_remove(struct change_notify *cnbp) { - SMB_STRUCT_STAT st; - files_struct *fsp = cnbp->fsp; - - memset((char *)change_data, '\0', sizeof(change_data)); - - /* - * Store the current timestamp on the directory we are monitoring. - */ - - if(dos_stat(fsp->fsp_name, &st) < 0) { - DEBUG(0,("create_directory_notify_hash: Unable to stat name = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - return False; - } - - change_data->modify_time = st.st_mtime; - change_data->status_time = st.st_ctime; - - /* - * If we are to watch for changes that are only stored - * in inodes of files, not in the directory inode, we must - * scan the directory and produce a unique identifier with - * which we can determine if anything changed. We use the - * modify and change times from all the files in the - * directory, added together (ignoring wrapping if it's - * larger than the max time_t value). - */ - - if(cnbp->flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE)) { - pstring full_name; - char *p; - char *fname; - size_t remaining_len; - size_t fullname_len; - void *dp = OpenDir(cnbp->conn, fsp->fsp_name, True); - - if(dp == NULL) { - DEBUG(0,("create_directory_notify_hash: Unable to open directory = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - return False; - } - - change_data->num_entries = 0; - - pstrcpy(full_name, fsp->fsp_name); - pstrcat(full_name, "/"); - - fullname_len = strlen(full_name); - remaining_len = sizeof(full_name) - fullname_len - 1; - p = &full_name[fullname_len]; - - while ((fname = ReadDirName(dp))) { - if(strequal(fname, ".") || strequal(fname, "..")) - continue; - - change_data->num_entries++; - safe_strcpy( p, fname, remaining_len); - - memset(&st, '\0', sizeof(st)); - - /* - * Do the stat - but ignore errors. - */ - - if(dos_stat(full_name, &st) < 0) { - DEBUG(5,("create_directory_notify_hash: Unable to stat content file = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - } - change_data->total_time += (st.st_mtime + st.st_ctime); - } - - CloseDir(dp); - } - - return True; + cnotify->remove_notify(cnbp->change_data); + DLIST_REMOVE(change_notify_list, cnbp); + ZERO_STRUCTP(cnbp); + free(cnbp); } + /**************************************************************************** Delete entries by fnum from the change notify pending queue. *****************************************************************************/ - void remove_pending_change_notify_requests_by_fid(files_struct *fsp) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - if(cnbp->fsp->fnum == fsp->fnum) { - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } + struct change_notify *cnbp, *next; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if (cnbp->fsp->fnum == fsp->fnum) { + change_notify_remove(cnbp); + } + } } /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ - void remove_pending_change_notify_requests_by_mid(int mid) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } + struct change_notify *cnbp, *next; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if(SVAL(cnbp->request_buf,smb_mid) == mid) { + change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_remove(cnbp); + } + } } /**************************************************************************** Delete entries by filename and cnum from the change notify pending queue. Always send reply. *****************************************************************************/ - void remove_pending_change_notify_requests_by_filename(files_struct *fsp) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - /* - * We know it refers to the same directory if the connection number and - * the filename are identical. - */ - if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } + struct change_notify *cnbp, *next; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + /* + * We know it refers to the same directory if the connection number and + * the filename are identical. + */ + if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { + change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_remove(cnbp); + } + } +} + +/**************************************************************************** + Return true if there are pending change notifies. +****************************************************************************/ +BOOL change_notifies_pending(void) +{ + return (change_notify_list != NULL); } /**************************************************************************** @@ -247,121 +154,36 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) Returns True if there are still outstanding change notify requests on the queue. *****************************************************************************/ - BOOL process_pending_change_notify_queue(time_t t) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - if(cnbp == NULL) - return False; - - if(cnbp->next_check_time >= t) - return True; - - /* - * It's time to check. Go through the queue and see if - * the timestamps changed. - */ - - while((cnbp != NULL) && (cnbp->next_check_time <= t)) { - change_hash_data change_data; - connection_struct *conn = cnbp->conn; - uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(cnbp->request_buf,smb_uid); - - ZERO_STRUCT(change_data); - - /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - file_chain_reset(); - - if(!become_user(conn,vuid)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", - vuid )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - if(!become_service(conn,True)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to become service Error was %s.\n", strerror(errno) )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - if(!create_directory_notify_hash( cnbp, &change_data)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to create change data for \ -directory %s\n", cnbp->fsp->fsp_name )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - if(memcmp( (char *)&cnbp->change_data, (char *)&change_data, sizeof(change_data))) { - /* - * Remove the entry and return a change notify to the client. - */ - DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed.\n", - cnbp->fsp->fsp_name )); - change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - unbecome_user(); - - /* - * Move to the next in the list. - */ - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } - - return (cnbp != NULL); -} + struct change_notify *cnbp, *next; + uint16 vuid; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + + vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); + + if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { + change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); + change_notify_remove(cnbp); + } + } -/**************************************************************************** - Return true if there are pending change notifies. -****************************************************************************/ -BOOL change_notifies_pending(void) -{ - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - return (cnbp != NULL); + return (change_notify_list != NULL); } /**************************************************************************** - * Now queue an entry on the notify change stack. We timestamp - * the entry we are adding so that we know when to scan next. + * Now queue an entry on the notify change list. * We only need to save smb_size bytes from this incoming packet * as we will always by returning a 'read the directory yourself' * error. ****************************************************************************/ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) { - change_notify_buf *cnbp; + struct change_notify *cnbp; - if((cnbp = (change_notify_buf *)malloc(sizeof(change_notify_buf))) == NULL) { + if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); return -1; } @@ -371,23 +193,34 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; cnbp->conn = conn; - cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); cnbp->flags = flags; + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); - if (!create_directory_notify_hash(cnbp, &cnbp->change_data)) { - free((char *)cnbp); + if (!cnbp->change_data) { + free(cnbp); return False; } + + DLIST_ADD(change_notify_list, cnbp); + + return True; +} + + +/**************************************************************************** +initialise the change notify subsystem +****************************************************************************/ +BOOL init_change_notify(void) +{ + cnotify = hash_notify_init(); - /* - * Adding to the tail enables us to check only - * the head when scanning for change, as this entry - * is forced to have the first timeout expiration. - */ - - ubi_slAddTail(&change_notify_queue, cnbp); + if (!cnotify) { + DEBUG(0,("Failed to init change notify system\n")); + return False; + } return True; } + #undef OLD_NTDOMAIN diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c new file mode 100644 index 0000000000..e01f660700 --- /dev/null +++ b/source3/smbd/notify_hash.c @@ -0,0 +1,184 @@ +#define OLD_NTDOMAIN 1 +/* + Unix SMB/Netbios implementation. + Version 3.0 + change notify handling - hash based implementation + Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Andrew Tridgell 2000 + + 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; + + +struct change_data { + time_t last_check_time; /* time we last checked this entry */ + time_t modify_time; /* Info from the directory we're monitoring. */ + time_t status_time; /* Info from the directory we're monitoring. */ + time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ + unsigned int num_entries; /* Zero or the number of files in the directory. */ +}; + + +/**************************************************************************** + Create the hash we will use to determine if the contents changed. +*****************************************************************************/ +static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, + struct change_data *data) +{ + SMB_STRUCT_STAT st; + pstring full_name; + char *p; + char *fname; + size_t remaining_len; + size_t fullname_len; + void *dp; + + ZERO_STRUCTP(data); + + if(dos_stat(path, &st) == -1) return False; + + data->modify_time = st.st_mtime; + data->status_time = st.st_ctime; + + /* + * If we are to watch for changes that are only stored + * in inodes of files, not in the directory inode, we must + * scan the directory and produce a unique identifier with + * which we can determine if anything changed. We use the + * modify and change times from all the files in the + * directory, added together (ignoring wrapping if it's + * larger than the max time_t value). + */ + + if (!(flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE))) return True; + + dp = OpenDir(conn, path, True); + if (dp == NULL) return False; + + data->num_entries = 0; + + pstrcpy(full_name, path); + pstrcat(full_name, "/"); + + fullname_len = strlen(full_name); + remaining_len = sizeof(full_name) - fullname_len - 1; + p = &full_name[fullname_len]; + + while ((fname = ReadDirName(dp))) { + if(strequal(fname, ".") || strequal(fname, "..")) continue; + + data->num_entries++; + safe_strcpy(p, fname, remaining_len); + + ZERO_STRUCT(st); + + /* + * Do the stat - but ignore errors. + */ + dos_stat(full_name, &st); + data->total_time += (st.st_mtime + st.st_ctime); + } + + CloseDir(dp); + + return True; +} + + +/**************************************************************************** +register a change notify request +*****************************************************************************/ +static void *hash_register_notify(connection_struct *conn, char *path, uint32 flags) +{ + struct change_data data; + + if (!notify_hash(conn, path, flags, &data)) return NULL; + + data.last_check_time = time(NULL); + + return (void *)memdup(&data, sizeof(data)); +} + +/**************************************************************************** +check if a change notify should be issued +*****************************************************************************/ +static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) +{ + struct change_data *data = (struct change_data *)datap; + struct change_data data2; + + if (t < data->last_check_time + lp_change_notify_timeout()) return False; + + if (!become_user(conn,vuid)) return True; + if (!become_service(conn,True)) { + unbecome_user(); + return True; + } + + if (!notify_hash(conn, path, flags, &data2) || + data2.modify_time != data->modify_time || + data2.status_time != data->status_time || + data2.total_time != data->total_time || + data2.num_entries != data->num_entries) { + unbecome_user(); + return True; + } + + data->last_check_time = t; + unbecome_user(); + + return False; +} + +/**************************************************************************** +remove a change notify data structure +*****************************************************************************/ +static void hash_remove_notify(void *datap) +{ + free(datap); +} + + +/**************************************************************************** +setup hash based change notify +****************************************************************************/ +struct cnotify_fns *hash_notify_init(void) +{ + static struct cnotify_fns cnotify; + + cnotify.register_notify = hash_register_notify; + cnotify.check_notify = hash_check_notify; + cnotify.remove_notify = hash_remove_notify; + + return &cnotify; +} + + +/* + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); + + chain_size = 0; + file_chain_reset(); + + uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(cnbp->request_buf,smb_uid); +*/ + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c new file mode 100644 index 0000000000..7732bc646f --- /dev/null +++ b/source3/smbd/notify_kernel.c @@ -0,0 +1,170 @@ +#define OLD_NTDOMAIN 1 +/* + Unix SMB/Netbios implementation. + Version 3.0 + change notify handling - linux kernel based implementation + Copyright (C) Andrew Tridgell 2000 + + 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" + +#if HAVE_KERNEL_CHANGE_NOTIFY + +extern int DEBUGLEVEL; +static int fd_pending; +static unsigned signals_received; +static unsigned signals_processed; + +#ifndef DN_ACCESS +#define DN_ACCESS 0x00000001 /* File accessed in directory */ +#define DN_MODIFY 0x00000002 /* File modified in directory */ +#define DN_CREATE 0x00000004 /* File created in directory */ +#define DN_DELETE 0x00000008 /* File removed from directory */ +#define DN_RENAME 0x00000010 /* File renamed in directory */ +#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */ +#endif + + +#ifndef RT_SIGNAL_NOTIFY +#define RT_SIGNAL_NOTIFY 34 +#endif + +/**************************************************************************** + This is the structure to keep the information needed to + determine if a directory has changed. +*****************************************************************************/ +struct change_data { + int directory_handle; +}; + +/**************************************************************************** +the signal handler for change notify +*****************************************************************************/ +static void signal_handler(int signal, siginfo_t *info, void *unused) +{ + BlockSignals(True, signal); + fd_pending = info->si_fd; + signals_received++; + sys_select_signal(); +} + + + +/**************************************************************************** +check if a change notify should be issued +*****************************************************************************/ +static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) +{ + struct change_data *data = (struct change_data *)datap; + + if (data->directory_handle != fd_pending) return False; + + close(fd_pending); + data->directory_handle = fd_pending = -1; + signals_processed++; + BlockSignals(False, RT_SIGNAL_NOTIFY); + return True; +} + +/**************************************************************************** +remove a change notify data structure +*****************************************************************************/ +static void kernel_remove_notify(void *datap) +{ + struct change_data *data = (struct change_data *)datap; + if (data->directory_handle != -1) { + if (data->directory_handle == fd_pending) { + data->directory_handle = fd_pending = -1; + signals_processed++; + BlockSignals(False, RT_SIGNAL_NOTIFY); + } + close(data->directory_handle); + } + free(data); +} + + +/**************************************************************************** +register a change notify request +*****************************************************************************/ +static void *kernel_register_notify(connection_struct *conn, char *path, uint32 flags) +{ + struct change_data data; + int fd; + unsigned long kernel_flags; + + fd = dos_open(fsp->fsp_name, O_RDONLY, 0); + + if (fd == -1) { + DEBUG(3,("Failed to open directory %s for change notify\n", fsp->fsp_name)); + return NULL; + } + + if (fcntl(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) { + DEBUG(3,("Failed to set signal handler for change notify\n")); + return NULL; + } + + kernel_flags = 0; + if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME; + if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME; + if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_MODIFY; + if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY; + if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY; + if (flags & FILE_NOTIFY_CHANGE_LAST_ACCESS) kernel_flags |= DN_ACCESS; + if (flags & FILE_NOTIFY_CHANGE_CREATION) kernel_flags |= DN_CREATE; + + if (fcntl(fd, F_NOTIFY, kernel_flags) == -1) { + DEBUG(3,("Failed to set async flag for change notify\n")); + return NULL; + } + + data.directory_handle = fd; + + return (void *)memdup(&data, sizeof(data)); +} + + +/**************************************************************************** +setup kernel based change notify +****************************************************************************/ +struct cnotify_fns *kernel_notify_init(void) +{ + static struct cnotify_fns cnotify; + struct sigaction act; + + act.sa_handler = NULL; + act.sa_sigaction = signal_handler; + act.sa_flags = SA_SIGINFO; + if (sigaction(RT_SIGNAL_NOTIFY, &act, NULL) != 0) { + DEBUG(0,("Failed to setup RT_SIGNAL_NOTIFY handler\n")); + return NULL; + } + + cnotify.register_notify = kernel_register_notify; + cnotify.check_notify = kernel_check_notify; + cnotify.remove_notify = kernel_remove_notify; + + return &cnotify; +} + + +#else + void notify_kernel_dummy(void) {} +#endif /* HAVE_KERNEL_CHANGE_NOTIFY */ + +#undef OLD_NTDOMAIN diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 5e63b4d4ff..59c3c83f6f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -71,44 +71,47 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou smb_read_error = 0; if(timeout != 0) { - struct timeval to; - int selrtn; - int maxfd = oplock_sock; + struct timeval to; + int selrtn; + int maxfd = oplock_sock; - if (koplocks && koplocks->notification_fd != -1) { - FD_SET(koplocks->notification_fd, fds); - } + if (koplocks && koplocks->notification_fd != -1) { + FD_SET(koplocks->notification_fd, fds); + maxfd = MAX(maxfd, koplocks->notification_fd); + } - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(maxfd+1,fds,&to); + selrtn = sys_select(maxfd+1,fds,&to); - if (selrtn == -1 && errno == EINTR) { - /* could be a kernel oplock interrupt */ - if (koplocks && koplocks->msg_waiting(fds)) { - return koplocks->receive_message(fds, buffer, buffer_len); - } - } + if (selrtn == -1 && errno == EINTR) { + /* could be a kernel oplock interrupt */ + if (koplocks && koplocks->msg_waiting(fds)) { + return koplocks->receive_message(fds, buffer, buffer_len); + } + } - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } + /* Check if error */ + if(selrtn == -1) { + /* something is wrong. Maybe the socket is dead? */ + smb_read_error = READ_ERROR; + return False; + } - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return False; - } + /* Did we timeout ? */ + if (selrtn == 0) { + smb_read_error = READ_TIMEOUT; + return False; + } } if (koplocks && koplocks->msg_waiting(fds)) { return koplocks->receive_message(fds, buffer, buffer_len); } + if (!FD_ISSET(oplock_sock, fds)) return False; + /* * From here down we deal with the smbd <--> smbd * oplock break protocol only. diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 8d55a3d4a0..c4d528c835 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -218,16 +218,16 @@ static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *in { /* Ensure that the msg length is correct. */ if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); + DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %d).\n", + msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); return False; } memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - DEBUG(5,("process_local_message: kernel oplock break request for \ -file dev = %x, inode = %.0f\n", (unsigned int)*dev, (double)*inode)); + DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f\n", + (unsigned int)*dev, (double)*inode)); return True; } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 46290683d2..de2a4300a7 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -29,7 +29,7 @@ extern int DEBUGLEVEL; static unsigned signals_received; static unsigned signals_processed; -static int fd_pending; /* the fd of the current pending SIGIO */ +static int fd_pending; /* the fd of the current pending signal */ #ifndef F_SETLEASE #define F_SETLEASE 1024 @@ -43,14 +43,19 @@ static int fd_pending; /* the fd of the current pending SIGIO */ #define CAP_LEASE 28 #endif +#ifndef RT_SIGNAL_LEASE +#define RT_SIGNAL_LEASE 33 +#endif + /**************************************************************************** -handle a SIGIO, incrementing the signals_received and blocking SIGIO +handle a LEASE signal, incrementing the signals_received and blocking the signal ****************************************************************************/ -static void sigio_handler(int signal, siginfo_t *info, void *unused) +static void signal_handler(int signal, siginfo_t *info, void *unused) { + BlockSignals(True, signal); fd_pending = info->si_fd; signals_received++; - BlockSignals(True, SIGIO); + sys_select_signal(); } /**************************************************************************** @@ -150,7 +155,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); /* now we can receive more signals */ fd_pending = -1; signals_processed++; - BlockSignals(False, SIGIO); + BlockSignals(False, RT_SIGNAL_LEASE); return True; } @@ -213,16 +218,16 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i { /* Ensure that the msg length is correct. */ if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); + DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %d).\n", + msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); return False; } memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - DEBUG(5,("process_local_message: kernel oplock break request for \ -file dev = %x, inode = %.0f\n", (unsigned int)*dev, (double)*inode)); + DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f\n", + (unsigned int)*dev, (double)*inode)); return True; } @@ -264,10 +269,10 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) } act.sa_handler = NULL; - act.sa_sigaction = sigio_handler; + act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; - if (sigaction(SIGIO, &act, NULL) != 0) { - DEBUG(0,("Failed to setup SIGIO handler\n")); + if (sigaction(RT_SIGNAL_LEASE, &act, NULL) != 0) { + DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler\n")); return NULL; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 30d03747d8..b84e55343e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -107,7 +107,30 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) BOOL push_oplock_pending_smb_message(char *buf, int msg_len) { - return push_message(&smb_oplock_queue, buf, msg_len); + return push_message(&smb_oplock_queue, buf, msg_len); +} + +/**************************************************************************** +do all async processing in here. This includes UDB oplock messages, kernel +oplock messages, change notify events etc. +****************************************************************************/ +static void async_processing(fd_set *fds, char *buffer, int buffer_len) +{ + /* check for oplock messages (both UDP and kernel) */ + if (receive_local_message(fds, buffer, buffer_len, 0)) { + process_local_message(buffer, buffer_len); + } + + /* check for async change notify events */ + process_pending_change_notify_queue(0); + + /* check for sighup processing */ + if (reload_after_sighup) { + unbecome_user(); + DEBUG(1,("Reloading services after SIGHUP\n")); + reload_services(False); + reload_after_sighup = False; + } } /**************************************************************************** @@ -115,7 +138,7 @@ BOOL push_oplock_pending_smb_message(char *buf, int msg_len) If a local udp message has been pushed onto the queue (this can only happen during oplock break - processing) return this first. + processing) call async_processing() If a pending smb message has been pushed onto the queue (this can only happen during oplock break @@ -131,8 +154,7 @@ BOOL push_oplock_pending_smb_message(char *buf, int msg_len) The timeout is in milli seconds ****************************************************************************/ -static BOOL receive_message_or_smb(char *buffer, int buffer_len, - int timeout, BOOL *got_smb) +static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) { fd_set fds; int selrtn; @@ -141,30 +163,28 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, smb_read_error = 0; - *got_smb = False; - /* * Check to see if we already have a message on the smb queue. * If so - copy and return it. */ - - if(ubi_slCount(&smb_oplock_queue) != 0) { + if(ubi_slCount(&smb_oplock_queue) != 0) { pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue); memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); /* Free the message we just copied. */ free((char *)msg->msg_buf); free((char *)msg); - *got_smb = True; DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); return True; } + /* * Setup the select read fd set. */ + again: FD_ZERO(&fds); FD_SET(smbd_server_fd(),&fds); maxfd = setup_oplock_select_set(&fds); @@ -175,16 +195,16 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL); /* if we get EINTR then maybe we have received an oplock - signal - treat this as select returning 1. This is ugly, but - is the best we can do until the oplock code knows more about - signals */ + signal - treat this as select returning 1. This is ugly, but + is the best we can do until the oplock code knows more about + signals */ if (selrtn == -1 && errno == EINTR) { - FD_ZERO(&fds); - selrtn = 1; + async_processing(&fds, buffer, buffer_len); + goto again; } /* Check if error */ - if(selrtn == -1 && errno != EINTR) { + if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ smb_read_error = READ_ERROR; return False; @@ -195,13 +215,13 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, smb_read_error = READ_TIMEOUT; return False; } - - if (FD_ISSET(smbd_server_fd(),&fds)) { - *got_smb = True; - return receive_smb(smbd_server_fd(), buffer, 0); - } else { - return receive_local_message(&fds, buffer, buffer_len, 0); + + if (!FD_ISSET(smbd_server_fd(),&fds) || selrtn > 1) { + async_processing(&fds, buffer, buffer_len); + if (!FD_ISSET(smbd_server_fd(),&fds)) goto again; } + + return receive_smb(smbd_server_fd(), buffer, 0); } /**************************************************************************** @@ -210,30 +230,16 @@ Get the next SMB packet, doing the local message processing automatically. BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) { - BOOL got_smb = False; - BOOL ret; - - do - { - ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb); + BOOL got_keepalive; + BOOL ret; - if(ret && !got_smb) - { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(inbuf, bufsize); - continue; - } - - if(ret && (CVAL(inbuf,0) == 0x85)) - { - /* Keepalive packet. */ - got_smb = False; - } - - } - while(ret && !got_smb); + do { + ret = receive_message_or_smb(inbuf,bufsize,timeout); + + got_keepalive = (ret && (CVAL(inbuf,0) == 0x85)); + } while (ret && got_keepalive); - return ret; + return ret; } /**************************************************************************** @@ -270,13 +276,12 @@ void respond_to_all_remaining_local_messages(void) * Keep doing receive_local_message with a 1 ms timeout until * we have no more messages. */ - while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(buffer, sizeof(buffer)); + /* Deal with oplock break requests from other smbd's. */ + process_local_message(buffer, sizeof(buffer)); - FD_ZERO(&fds); - (void)setup_oplock_select_set(&fds); + FD_ZERO(&fds); + (void)setup_oplock_select_set(&fds); } return; @@ -1008,98 +1013,80 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); void smbd_process(void) { - extern int smb_echo_count; - time_t last_timeout_processing_time = time(NULL); - unsigned int num_smbs = 0; + extern int smb_echo_count; + time_t last_timeout_processing_time = time(NULL); + unsigned int num_smbs = 0; - InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if ((InBuffer == NULL) || (OutBuffer == NULL)) - return; + InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if ((InBuffer == NULL) || (OutBuffer == NULL)) + return; - InBuffer += SMB_ALIGNMENT; - OutBuffer += SMB_ALIGNMENT; + InBuffer += SMB_ALIGNMENT; + OutBuffer += SMB_ALIGNMENT; - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); + max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); - /* re-initialise the timezone */ - TimeInit(); + /* re-initialise the timezone */ + TimeInit(); - while (True) - { - int deadtime = lp_deadtime()*60; - BOOL got_smb = False; - int select_timeout = setup_select_timeout(); - - if (deadtime <= 0) - deadtime = DEFAULT_SMBD_TIMEOUT; - - errno = 0; - - /* free up temporary memory */ - lp_talloc_free(); - - /* - * If reload_after_sighup == True then we got a SIGHUP - * and are being asked to reload. Fix from - */ - if (reload_after_sighup) { - /* become root */ - unbecome_user(); - DEBUG(1,("Reloading services after SIGHUP\n")); - reload_services(False); - reload_after_sighup = False; - } - - while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb)) - { - if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) - return; - num_smbs = 0; /* Reset smb counter. */ - } - - if(got_smb) { - /* - * Ensure we do timeout processing if the SMB we just got was - * only an echo request. This allows us to set the select - * timeout in 'receive_message_or_smb()' to any value we like - * without worrying that the client will send echo requests - * faster than the select timeout, thus starving out the - * essential processing (change notify, blocking locks) that - * the timeout code does. JRA. - */ - int num_echos = smb_echo_count; - - process_smb(InBuffer, OutBuffer); - - if(smb_echo_count != num_echos) { - if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) - return; - num_smbs = 0; /* Reset smb counter. */ - } - - num_smbs++; + while (True) { + int deadtime = lp_deadtime()*60; + int select_timeout = setup_select_timeout(); + int num_echos; - /* - * If we are getting smb requests in a constant stream - * with no echos, make sure we attempt timeout processing - * every select_timeout milliseconds - but only check for this - * every 200 smb requests. - */ + if (deadtime <= 0) + deadtime = DEFAULT_SMBD_TIMEOUT; - if((num_smbs % 200) == 0) { - time_t new_check_time = time(NULL); - if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) { - if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) - return; - num_smbs = 0; /* Reset smb counter. */ - last_timeout_processing_time = new_check_time; /* Reset time. */ - } - } - } - else - process_local_message(InBuffer, BUFFER_SIZE); - } + errno = 0; + + /* free up temporary memory */ + lp_talloc_free(); + + while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) { + if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + return; + num_smbs = 0; /* Reset smb counter. */ + } + + /* + * Ensure we do timeout processing if the SMB we just got was + * only an echo request. This allows us to set the select + * timeout in 'receive_message_or_smb()' to any value we like + * without worrying that the client will send echo requests + * faster than the select timeout, thus starving out the + * essential processing (change notify, blocking locks) that + * the timeout code does. JRA. + */ + num_echos = smb_echo_count; + + process_smb(InBuffer, OutBuffer); + + if (smb_echo_count != num_echos) { + if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + return; + num_smbs = 0; /* Reset smb counter. */ + } + + num_smbs++; + + /* + * If we are getting smb requests in a constant stream + * with no echos, make sure we attempt timeout processing + * every select_timeout milliseconds - but only check for this + * every 200 smb requests. + */ + + if ((num_smbs % 200) == 0) { + time_t new_check_time = time(NULL); + if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) { + if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + return; + num_smbs = 0; /* Reset smb counter. */ + last_timeout_processing_time = new_check_time; /* Reset time. */ + } + } + } } #undef OLD_NTDOMAIN diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a5da156250..b28ba6d4ef 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -350,12 +350,7 @@ static void sig_hup(int sig) BlockSignals(True,SIGHUP); DEBUG(0,("Got SIGHUP\n")); - /* - * Fix from here. - * We used to reload in the signal handler - this - * is a *BIG* no-no. - */ - + sys_select_signal(); reload_after_sighup = True; BlockSignals(False,SIGHUP); } @@ -758,6 +753,11 @@ static void usage(char *pname) exit(1); } + /* Setup change notify */ + if (!init_change_notify()) { + exit(1); + } + smbd_process(); exit_server("normal exit"); -- cgit From c8de9b8fe14fe1e6e85652d543615dc187949a1a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 17:06:00 +0000 Subject: enable the Linux change notify code and change some notify debug code (This used to be commit c6be511fcc1be79619a0184f03d4c33dbfe12f04) --- source3/smbd/notify.c | 5 ++++- source3/smbd/notify_kernel.c | 51 +++++++++++++++++++++++++++++++++++++------- source3/smbd/oplock_linux.c | 23 ++++++++++++++------ 3 files changed, 64 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 40867a71ee..c577d0aef3 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -212,7 +212,10 @@ initialise the change notify subsystem ****************************************************************************/ BOOL init_change_notify(void) { - cnotify = hash_notify_init(); +#if HAVE_KERNEL_CHANGE_NOTIFY + cnotify = kernel_notify_init(); +#endif + if (!cnotify) cnotify = hash_notify_init(); if (!cnotify) { DEBUG(0,("Failed to init change notify system\n")); diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 7732bc646f..f78198f207 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -43,6 +43,14 @@ static unsigned signals_processed; #define RT_SIGNAL_NOTIFY 34 #endif +#ifndef F_SETSIG +#define F_SETSIG 10 +#endif + +#ifndef F_NOTIFY +#define F_NOTIFY 1026 +#endif + /**************************************************************************** This is the structure to keep the information needed to determine if a directory has changed. @@ -73,6 +81,8 @@ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path if (data->directory_handle != fd_pending) return False; + DEBUG(3,("kernel change notify on %s fd=%d\n", path, fd_pending)); + close(fd_pending); data->directory_handle = fd_pending = -1; signals_processed++; @@ -86,15 +96,17 @@ remove a change notify data structure static void kernel_remove_notify(void *datap) { struct change_data *data = (struct change_data *)datap; - if (data->directory_handle != -1) { - if (data->directory_handle == fd_pending) { - data->directory_handle = fd_pending = -1; + int fd = data->directory_handle; + if (fd != -1) { + if (fd == fd_pending) { + fd_pending = -1; signals_processed++; BlockSignals(False, RT_SIGNAL_NOTIFY); } - close(data->directory_handle); + close(fd); } free(data); + DEBUG(3,("removed kernel change notify fd=%d\n", fd)); } @@ -107,10 +119,10 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 int fd; unsigned long kernel_flags; - fd = dos_open(fsp->fsp_name, O_RDONLY, 0); + fd = dos_open(path, O_RDONLY, 0); if (fd == -1) { - DEBUG(3,("Failed to open directory %s for change notify\n", fsp->fsp_name)); + DEBUG(3,("Failed to open directory %s for change notify\n", path)); return NULL; } @@ -120,8 +132,8 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 } kernel_flags = 0; - if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME; - if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME; + if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE; + if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME|DN_DELETE; if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_MODIFY; if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY; if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY; @@ -133,11 +145,32 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 return NULL; } + if (fcntl(fd, F_SETOWN, sys_getpid()) == -1) { + DEBUG(3,("Failed to set owner for change notify\n")); + return NULL; + } + data.directory_handle = fd; + DEBUG(3,("kernel change notify on %s (flags=0x%x) fd=%d\n", + path, (int)kernel_flags, fd)); + return (void *)memdup(&data, sizeof(data)); } +/**************************************************************************** +see if the kernel supports change notify +****************************************************************************/ +static BOOL kernel_notify_available(void) +{ + int fd, ret; + fd = open("/tmp", O_RDONLY); + if (fd == -1) return False; /* uggh! */ + ret = fcntl(fd, F_NOTIFY, 0); + close(fd); + return ret == 0 || errno != EINVAL; +} + /**************************************************************************** setup kernel based change notify @@ -147,6 +180,8 @@ struct cnotify_fns *kernel_notify_init(void) static struct cnotify_fns cnotify; struct sigaction act; + if (!kernel_notify_available()) return NULL; + act.sa_handler = NULL; act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index de2a4300a7..c53dd1c57f 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -47,6 +47,10 @@ static int fd_pending; /* the fd of the current pending signal */ #define RT_SIGNAL_LEASE 33 #endif +#ifndef F_SETSIG +#define F_SETSIG 10 +#endif + /**************************************************************************** handle a LEASE signal, incrementing the signals_received and blocking the signal ****************************************************************************/ @@ -60,8 +64,7 @@ static void signal_handler(int signal, siginfo_t *info, void *unused) /**************************************************************************** try to gain a linux capability -****************************************************************************/ -static void set_capability(unsigned capability) +****************************************************************************/static void set_capability(unsigned capability) { #ifndef _LINUX_CAPABILITY_VERSION #define _LINUX_CAPABILITY_VERSION 0x19980330 @@ -101,6 +104,12 @@ try again static int linux_setlease(int fd, int leasetype) { int ret; + + if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) { + DEBUG(3,("Failed to set signal handler for kernel lease\n")); + return -1; + } + ret = fcntl(fd, F_SETLEASE, leasetype); if (ret == -1 && errno == EACCES) { set_capability(CAP_LEASE); @@ -133,7 +142,7 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l dev = sbuf.st_dev; inode = sbuf.st_ino; - DEBUG(5,("receive_local_message: kernel oplock break request received for \ + DEBUG(3,("receive_local_message: kernel oplock break request received for \ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); /* @@ -167,14 +176,14 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (linux_setlease(fsp->fd, F_WRLCK) == -1) { - DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ + DEBUG(3,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno))); return False; } - DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", + DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); return True; @@ -226,7 +235,7 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f\n", + DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f\n", (unsigned int)*dev, (double)*inode)); return True; @@ -283,6 +292,8 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) koplocks.msg_waiting = linux_oplock_msg_waiting; koplocks.notification_fd = -1; + DEBUG(3,("Linux kernel oplocks enabled\n")); + return &koplocks; } -- cgit From b7930178c35ed1b9e449ead7b8cd03bc4f0ce316 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Jun 2000 06:33:15 +0000 Subject: always use the DN_CREATE mask (NT expects file creation always to cause a notify) (This used to be commit 20a06b7fb7c855e874b79b86251d597e7797b3c0) --- source3/smbd/notify_kernel.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index f78198f207..bfa21a6e2c 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -131,7 +131,7 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 return NULL; } - kernel_flags = 0; + kernel_flags = DN_CREATE; /* always notify on file creation */ if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE; if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME|DN_DELETE; if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_MODIFY; @@ -145,15 +145,10 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 return NULL; } - if (fcntl(fd, F_SETOWN, sys_getpid()) == -1) { - DEBUG(3,("Failed to set owner for change notify\n")); - return NULL; - } - data.directory_handle = fd; - DEBUG(3,("kernel change notify on %s (flags=0x%x) fd=%d\n", - path, (int)kernel_flags, fd)); + DEBUG(3,("kernel change notify on %s (ntflags=0x%x flags=0x%x) fd=%d\n", + path, (int)flags, (int)kernel_flags, fd)); return (void *)memdup(&data, sizeof(data)); } -- cgit From bf575bf2839fe795af59ddd24b1ab3451aea5699 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Jun 2000 09:31:43 +0000 Subject: use DN_ATTRIB kernel change notify attribute (This used to be commit 9f542484d11b7b908d3170b702b3bad82ba71525) --- source3/smbd/notify_kernel.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index bfa21a6e2c..c7fb5ca0dd 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -35,6 +35,7 @@ static unsigned signals_processed; #define DN_CREATE 0x00000004 /* File created in directory */ #define DN_DELETE 0x00000008 /* File removed from directory */ #define DN_RENAME 0x00000010 /* File renamed in directory */ +#define DN_ATTRIB 0x00000020 /* File changed attribute */ #define DN_MULTISHOT 0x80000000 /* Don't remove notifier */ #endif @@ -131,14 +132,17 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 return NULL; } - kernel_flags = DN_CREATE; /* always notify on file creation */ - if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE; + kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion changes everything! */ + if (flags & FILE_NOTIFY_CHANGE_FILE) kernel_flags |= DN_MODIFY; if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME|DN_DELETE; - if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_MODIFY; + if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_ATTRIB; if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY; if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY; if (flags & FILE_NOTIFY_CHANGE_LAST_ACCESS) kernel_flags |= DN_ACCESS; if (flags & FILE_NOTIFY_CHANGE_CREATION) kernel_flags |= DN_CREATE; + if (flags & FILE_NOTIFY_CHANGE_SECURITY) kernel_flags |= DN_ATTRIB; + if (flags & FILE_NOTIFY_CHANGE_EA) kernel_flags |= DN_ATTRIB; + if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE; if (fcntl(fd, F_NOTIFY, kernel_flags) == -1) { DEBUG(3,("Failed to set async flag for change notify\n")); -- cgit From 898c5ddf071035418dcf3f351a9ecc9904069335 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Tue, 13 Jun 2000 19:29:32 +0000 Subject: Removed a patch that Andrew had added because 'insure' was incorrectly reporting a memory leak in the cache module. I've modified the cache code to prevent insure getting confused, so the patch can now be removed. (This used to be commit 50599b0fa2b78109e3bd2cf50007dc69c4059955) --- source3/smbd/mangle.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 8ac91d49c8..1cc602dc05 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -576,15 +576,6 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) s2 = (char *)&(s1[mangled_len + 1]); (void)StrnCpy( s1, mangled_name, mangled_len ); (void)StrnCpy( s2, raw_name, raw_len ); - - /* possibly delete an old entry - this avoids a memory leak in the - ubi code to do with overwriting existing entries. - - remove this test when ubi gets fixed */ - if (ubi_cacheGet(mangled_cache, s1)) { - ubi_cacheDelete(mangled_cache, s1); - } - ubi_cachePut( mangled_cache, i, new_entry, s1 ); } /* cache_mangled_name */ -- cgit From 31e83abd3d275014c2841e66f5d46ef0997e5737 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 14 Jun 2000 01:48:08 +0000 Subject: ZERO_STRUCT() of info3 structure before using it. (This used to be commit efe7f818c927a925f2dee1ef4f6040c137e0c84e) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c38a6a0f2b..06f4d72a40 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1485,6 +1485,8 @@ BOOL domain_client_validate( char *user, char *domain, /* We really don't care what LUID we give the user. */ generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); + ZERO_STRUCT(info3); + if(cli_nt_login_network(&cli, domain, user, smb_uid_low, (char *)local_challenge, ((smb_apasslen != 0) ? smb_apasswd : NULL), ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), -- cgit From cc5502a4d01bfc4946fbd198aad75ea03e9734d3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Jun 2000 07:11:27 +0000 Subject: allow the notify implementation to choose the select timeout change (This used to be commit b1441d9622609af5ef598c5e1e1f5af438dc0731) --- source3/smbd/notify.c | 4 ++-- source3/smbd/notify_hash.c | 1 + source3/smbd/notify_kernel.c | 7 ++++--- source3/smbd/process.c | 22 +++++++++++----------- 4 files changed, 18 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index c577d0aef3..912ab43e9e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -144,9 +144,9 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) /**************************************************************************** Return true if there are pending change notifies. ****************************************************************************/ -BOOL change_notifies_pending(void) +int change_notify_timeout(void) { - return (change_notify_list != NULL); + return cnotify->select_time; } /**************************************************************************** diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index e01f660700..fe09d9cf9d 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -165,6 +165,7 @@ struct cnotify_fns *hash_notify_init(void) cnotify.register_notify = hash_register_notify; cnotify.check_notify = hash_check_notify; cnotify.remove_notify = hash_remove_notify; + cnotify.select_time = lp_change_notify_timeout(); return &cnotify; } diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index c7fb5ca0dd..a7d4591cc9 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -167,7 +167,7 @@ static BOOL kernel_notify_available(void) if (fd == -1) return False; /* uggh! */ ret = fcntl(fd, F_NOTIFY, 0); close(fd); - return ret == 0 || errno != EINVAL; + return ret == 0; } @@ -179,8 +179,6 @@ struct cnotify_fns *kernel_notify_init(void) static struct cnotify_fns cnotify; struct sigaction act; - if (!kernel_notify_available()) return NULL; - act.sa_handler = NULL; act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; @@ -189,9 +187,12 @@ struct cnotify_fns *kernel_notify_init(void) return NULL; } + if (!kernel_notify_available()) return NULL; + cnotify.register_notify = kernel_register_notify; cnotify.check_notify = kernel_check_notify; cnotify.remove_notify = kernel_remove_notify; + cnotify.select_time = -1; return &cnotify; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b84e55343e..3c85c05312 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -836,21 +836,21 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) static int setup_select_timeout(void) { - int change_notify_timeout = lp_change_notify_timeout() * 1000; - int select_timeout; + int select_timeout; + int t; - /* - * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we - * have removed any blocking locks. JRA. - */ + /* + * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we + * have removed any blocking locks. JRA. + */ - select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 : - SMBD_SELECT_TIMEOUT*1000; + select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 : + SMBD_SELECT_TIMEOUT*1000; - if (change_notifies_pending()) - select_timeout = MIN(select_timeout, change_notify_timeout); + t = change_notify_timeout(); + if (t != -1) select_timeout = MIN(select_timeout, t*1000); - return select_timeout; + return select_timeout; } /**************************************************************************** -- cgit From f94f053b7618157f6caaa1d65553c1abb3aba917 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Jun 2000 09:35:37 +0000 Subject: added support for kernel level share modes. These are a (small) hack, I suspect we will either get rid of them or do them properly at some stage. (This used to be commit fabe1f350e1fc58db33d22cebd38652950697ced) --- source3/smbd/open.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 23d95eadfd..5a0493e625 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -492,9 +492,24 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } /**************************************************************************** - Open a file with a share mode. +set a kernel flock on a file for NFS interoperability +this requires a patch to Linux ****************************************************************************/ +static void kernel_flock(files_struct *fsp, int deny_mode) +{ +#if HAVE_KERNEL_SHARE_MODES + int kernel_mode = 0; + if (deny_mode == DENY_READ) kernel_mode = LOCK_MAND|LOCK_WRITE; + else if (deny_mode == DENY_WRITE) kernel_mode = LOCK_MAND|LOCK_READ; + else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND; + if (kernel_mode) flock(fsp->fd, kernel_mode); +#endif +} + +/**************************************************************************** + Open a file with a share mode. +****************************************************************************/ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) { @@ -653,6 +668,14 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod return NULL; } + /* not that we ignore failure for the following. It is + basically a hack for NFS, and NFS will never set one of + these only read them. Nobody but Samba can ever set a deny + mode and we have already checked our more authoritative + locking database for permission to set this deny mode. If + the kernel refuses the operations then the kernel is wrong */ + kernel_flock(fsp, deny_mode); + /* * Deal with the race condition where two smbd's detect the file doesn't * exist and do the create at the same time. One of them will win and -- cgit From c5285699d9cdfea1ce77955c311f08981a5a97ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Jun 2000 14:15:48 +0000 Subject: open files with O_NONBLOCK when available. This is necessary to prevent possible deadlocks with kernel leases and harmless when kernel leases are not used. basically we don't ever want smbd to block (This used to be commit 9fd67b94a7e43c9dcbe098940b88879ae8743c00) --- source3/smbd/open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5a0493e625..e9d2f01e10 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -36,7 +36,12 @@ extern BOOL global_client_failed_oplock_break; static int fd_open(struct connection_struct *conn, char *fname, int flags, mode_t mode) { - int fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); + int fd; +#ifdef O_NONBLOCK + flags |= O_NONBLOCK; +#endif + + fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && -- cgit From 5824ae2734fd4b7e765afe696c135a8fe5153c88 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 16 Jun 2000 08:18:57 +0000 Subject: Pass the vuid from the connection_struct to the printing back end functions. (This used to be commit 6120d03200ed6d89640332aedc75172bdf77e2a0) --- source3/smbd/lanman.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index bee2b39f2f..bf635b88b1 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1773,13 +1773,13 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param switch (function) { case 81: /* delete */ - if (print_job_delete(jobid)) errcode = NERR_Success; + if (print_job_delete(jobid, vuid)) errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(jobid)) errcode = NERR_Success; + if (print_job_pause(jobid, vuid)) errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(jobid)) errcode = NERR_Success; + if (print_job_resume(jobid, vuid)) errcode = NERR_Success; break; } @@ -1822,13 +1822,13 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para switch (function) { case 74: /* Pause queue */ - if (print_queue_pause(snum)) errcode = NERR_Success; + if (print_queue_pause(snum, vuid)) errcode = NERR_Success; break; case 75: /* Resume queue */ - if (print_queue_resume(snum)) errcode = NERR_Success; + if (print_queue_resume(snum, vuid)) errcode = NERR_Success; break; case 103: /* Purge */ - if (print_queue_purge(snum)) errcode = NERR_Success; + if (print_queue_purge(snum, vuid)) errcode = NERR_Success; break; } -- cgit From 5e06151e4d13f6c57559e73dcc88e03ec47c63a0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 Jun 2000 21:30:27 +0000 Subject: Paranoia changes to ensure that anything touched by a signal handler and the main code is declared as VOLATILE SIG_ATOMIC_T. Jeremy. (This used to be commit b737c784e34b0e1af014cb828ef37d5b6d73c3e2) --- source3/smbd/notify_kernel.c | 21 +++++++++++---------- source3/smbd/oplock_linux.c | 14 +++++++------- 2 files changed, 18 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index a7d4591cc9..c517254048 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -25,9 +25,9 @@ #if HAVE_KERNEL_CHANGE_NOTIFY extern int DEBUGLEVEL; -static int fd_pending; -static unsigned signals_received; -static unsigned signals_processed; +static VOLATILE SIG_ATOMIC_T fd_pending; +static VOLATILE SIG_ATOMIC_T signals_received; +static VOLATILE SIG_ATOMIC_T signals_processed; #ifndef DN_ACCESS #define DN_ACCESS 0x00000001 /* File accessed in directory */ @@ -66,7 +66,7 @@ the signal handler for change notify static void signal_handler(int signal, siginfo_t *info, void *unused) { BlockSignals(True, signal); - fd_pending = info->si_fd; + fd_pending = (SIG_ATOMIC_T)info->si_fd; signals_received++; sys_select_signal(); } @@ -80,12 +80,13 @@ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path { struct change_data *data = (struct change_data *)datap; - if (data->directory_handle != fd_pending) return False; + if (data->directory_handle != (int)fd_pending) return False; - DEBUG(3,("kernel change notify on %s fd=%d\n", path, fd_pending)); + DEBUG(3,("kernel change notify on %s fd=%d\n", path, (int)fd_pending)); - close(fd_pending); - data->directory_handle = fd_pending = -1; + close((int)fd_pending); + fd_pending = (SIG_ATOMIC_T)-1; + data->directory_handle = -1; signals_processed++; BlockSignals(False, RT_SIGNAL_NOTIFY); return True; @@ -99,8 +100,8 @@ static void kernel_remove_notify(void *datap) struct change_data *data = (struct change_data *)datap; int fd = data->directory_handle; if (fd != -1) { - if (fd == fd_pending) { - fd_pending = -1; + if (fd == (int)fd_pending) { + fd_pending = (SIG_ATOMIC_T)-1; signals_processed++; BlockSignals(False, RT_SIGNAL_NOTIFY); } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index c53dd1c57f..d97378ac5d 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -27,9 +27,9 @@ extern int DEBUGLEVEL; -static unsigned signals_received; -static unsigned signals_processed; -static int fd_pending; /* the fd of the current pending signal */ +static VOLATILE SIG_ATOMIC_T signals_received; +static VOLATILE SIG_ATOMIC_T signals_processed; +static VOLATILE SIG_ATOMIC_T fd_pending; /* the fd of the current pending signal */ #ifndef F_SETLEASE #define F_SETLEASE 1024 @@ -57,7 +57,7 @@ handle a LEASE signal, incrementing the signals_received and blocking the signal static void signal_handler(int signal, siginfo_t *info, void *unused) { BlockSignals(True, signal); - fd_pending = info->si_fd; + fd_pending = (SIG_ATOMIC_T)info->si_fd; signals_received++; sys_select_signal(); } @@ -133,8 +133,8 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l if (signals_received == signals_processed) return False; - if (sys_fstat(fd_pending,&sbuf) == -1) { - DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", fd_pending)); + if (sys_fstat((int)fd_pending,&sbuf) == -1) { + DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd_pending)); ret = False; goto out; } @@ -162,7 +162,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); out: /* now we can receive more signals */ - fd_pending = -1; + fd_pending = (SIG_ATOMIC_T)-1; signals_processed++; BlockSignals(False, RT_SIGNAL_LEASE); -- cgit From a69d47640cb150fbffa12dee68ead34a5b1931bb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Jun 2000 00:32:32 +0000 Subject: Fixes for IRIX kernel oplocks and systems that don't have nss.h Jeremy. (This used to be commit 711f15ac230092bac000e63f99e8dfaa4a644847) --- source3/smbd/oplock_irix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index c4d528c835..cf1cbbb0fc 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -26,7 +26,6 @@ #if HAVE_KERNEL_OPLOCKS_IRIX extern int DEBUGLEVEL; - static int oplock_pipe_write = -1; static int oplock_pipe_read = -1; @@ -93,6 +92,7 @@ Disabling kernel oplock support.\n", strerror(errno) )); ****************************************************************************/ static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) { + extern int smb_read_error; oplock_stat_t os; SMB_DEV_T dev; SMB_INO_T inode; -- cgit From 8005c837f5425397131b0a798d63521f61e25375 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 23 Jun 2000 05:49:11 +0000 Subject: I've been working on refactoring some of the mess that is the become_user() code. This code is now implemented as a stack of security contexts, where a security context is defined as a set of effective user, group and supplementary group ids. The following functions are implemented: BOOL push_sec_ctx(void); Create a new security context on the stack which is the same as the current security context. void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups); Set the current security context to a given set of user and group ids. void set_root_sec_ctx(void); Set to uid = gid = 0. No supplementary groups are set. BOOL pop_sec_ctx(void); Pop a security context from the stack and restore the user and group permissions of the previous context. void init_sec_ctx(void); Initialise the security context stack. This must be called before any of the other operations are used or weird things may happen. The idea is that there is a base security context which is either root or some authenticated unix user. Other security contexts can be pushed and popped as needed for things like changing passwords, or rpc pipe operations where the rpc pipe user is different from the smb user. (This used to be commit 87c78d6d5a6bf8d0907d6f8ef5ee0d642946cad3) --- source3/smbd/sec_ctx.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 source3/smbd/sec_ctx.c (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c new file mode 100644 index 0000000000..e3aac77d8e --- /dev/null +++ b/source3/smbd/sec_ctx.c @@ -0,0 +1,295 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + uid/user handling + Copyright (C) Tim Potter 2000 + + 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; +extern struct current_user current_user; + +struct sec_ctx { + uid_t uid; + uid_t gid; + int ngroups; + gid_t *groups; +}; + +/* A stack of security contexts. We include the current context as being + the first one, so there is room for another MAX_SEC_CTX_DEPTH more. */ + +static struct sec_ctx sec_ctx_stack[MAX_SEC_CTX_DEPTH + 1]; +static int sec_ctx_stack_ndx; + +/* Become the specified uid */ + +static BOOL become_uid(uid_t uid) +{ + /* Check for dodgy uid values */ + + if (uid == (uid_t)-1 || + ((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) { + static int done; + + if (!done) { + DEBUG(1,("WARNING: using uid %d is a security risk\n", + (int)uid)); + done = 1; + } + } + + /* Set effective user id */ + + set_effective_uid(uid); + current_user.uid = uid; + +#ifdef WITH_PROFILE + profile_p->uid_changes++; +#endif + + return True; +} + +/* Become the specified gid */ + +static BOOL become_gid(gid_t gid) +{ + /* Check for dodgy gid values */ + + if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) && + (gid == (gid_t)65535))) { + static int done; + + if (!done) { + DEBUG(1,("WARNING: using gid %d is a security risk\n", + (int)gid)); + done = 1; + } + } + + /* Set effective group id */ + + set_effective_gid(gid); + current_user.gid = gid; + + return True; +} + +/* Become the specified uid and gid */ + +static BOOL become_id(uid_t uid, gid_t gid) +{ + return become_gid(gid) && become_uid(uid); +} + +/* Drop back to root privileges in order to change to another user */ + +static void gain_root(void) +{ + if (geteuid() != 0) { + set_effective_uid(0); + + if (geteuid() != 0) { + DEBUG(0, + ("Warning: You appear to have a trapdoor " + "uid system\n")); + } + } + + if (getegid() != 0) { + set_effective_gid(0); + + if (getegid() != 0) { + DEBUG(0, + ("Warning: You appear to have a trapdoor " + "gid system\n")); + } + } +} + +/* Get the list of current groups */ + +static void get_current_groups(int *ngroups, gid_t **groups) +{ + *ngroups = getgroups(0, NULL); + *groups = (gid_t *)malloc(*ngroups * sizeof(gid_t)); + + if (!groups) { + DEBUG(0, ("Out of memory in get_current_groups\n")); + return; + } + + getgroups(*ngroups, *groups); +} + +/* Create a new security context on the stack. It is the same as the old + one. User changes are done using the set_sec_ctx() function. */ + +BOOL push_sec_ctx(void) +{ + /* Check we don't overflow our stack */ + + if (sec_ctx_stack_ndx == (MAX_SEC_CTX_DEPTH)) { + DEBUG(0, ("Security context stack overflow!\n")); + return False; + } + + /* Store previous user context */ + + sec_ctx_stack_ndx++; + + sec_ctx_stack[sec_ctx_stack_ndx].uid = geteuid(); + sec_ctx_stack[sec_ctx_stack_ndx].gid = getegid(); + + sec_ctx_stack[sec_ctx_stack_ndx].ngroups = sys_getgroups(0, NULL); + + if (!(sec_ctx_stack[sec_ctx_stack_ndx].groups = + malloc(sec_ctx_stack[sec_ctx_stack_ndx].ngroups * + sizeof(gid_t)))) { + DEBUG(0, ("Out of memory in push_sec_ctx()\n")); + return False; + } + + sys_getgroups(sec_ctx_stack[sec_ctx_stack_ndx].ngroups, + sec_ctx_stack[sec_ctx_stack_ndx].groups); + + return True; +} + +/* Set the current security context to a given user */ + +void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) +{ + /* Set the security context */ + + DEBUG(3, ("setting sec ctx (%d, %d)\n", uid, gid)); + + gain_root(); + +#ifdef HAVE_SETGROUPS + sys_setgroups(ngroups, groups); + + sec_ctx_stack[sec_ctx_stack_ndx].ngroups = ngroups; + sec_ctx_stack[sec_ctx_stack_ndx].groups = + memdup(groups, sizeof(gid_t) * ngroups); +#endif + + become_id(uid, gid); + + sec_ctx_stack[sec_ctx_stack_ndx].uid = uid; + sec_ctx_stack[sec_ctx_stack_ndx].gid = gid; + + /* Update current_user stuff */ + + current_user.uid = uid; + current_user.gid = gid; + current_user.ngroups = ngroups; + current_user.groups = groups; +} + +/* Become root context */ + +void set_root_sec_ctx(void) +{ + /* May need to worry about supplementary groups at some stage */ + + set_sec_ctx(0, 0, 0, NULL); +} + +/* Pop a security context from the stack */ + +BOOL pop_sec_ctx(void) +{ + /* Check for stack underflow */ + + if (sec_ctx_stack_ndx == 0) { + DEBUG(0, ("Security context stack underflow!\n")); + return False; + } + + /* Clear previous user info */ + + sec_ctx_stack[sec_ctx_stack_ndx].uid = (uid_t)-1; + sec_ctx_stack[sec_ctx_stack_ndx].gid = (gid_t)-1; + + safe_free(sec_ctx_stack[sec_ctx_stack_ndx].groups); + sec_ctx_stack[sec_ctx_stack_ndx].ngroups = 0; + + /* Pop back previous user */ + + sec_ctx_stack_ndx--; + + gain_root(); + +#ifdef HAVE_SETGROUPS + sys_setgroups(sec_ctx_stack[sec_ctx_stack_ndx].ngroups, + sec_ctx_stack[sec_ctx_stack_ndx].groups); +#endif + + become_id(sec_ctx_stack[sec_ctx_stack_ndx].uid, + sec_ctx_stack[sec_ctx_stack_ndx].gid); + + /* Update current_user stuff */ + + current_user.uid = sec_ctx_stack[sec_ctx_stack_ndx].uid; + current_user.gid = sec_ctx_stack[sec_ctx_stack_ndx].gid; + current_user.ngroups = sec_ctx_stack[sec_ctx_stack_ndx].ngroups; + current_user.groups = sec_ctx_stack[sec_ctx_stack_ndx].groups; + + DEBUG(3, ("popped off to sec ctx (%d, %d)\n", geteuid(), getegid())); + + return True; +} + +/* Initialise the security context system */ + +void init_sec_ctx(void) +{ + int i; + + /* Initialise security context stack */ + + memset(sec_ctx_stack, 0, sizeof(struct sec_ctx) * MAX_SEC_CTX_DEPTH); + + for (i = 0; i < MAX_SEC_CTX_DEPTH; i++) { + sec_ctx_stack[i].uid = (uid_t)-1; + sec_ctx_stack[i].gid = (gid_t)-1; + } + + /* Initialise first level of stack. It is the current context */ + + sec_ctx_stack[0].uid = geteuid(); + sec_ctx_stack[0].gid = getegid(); + + get_current_groups(&sec_ctx_stack[0].ngroups, + &sec_ctx_stack[0].groups); + + /* Initialise current_user global */ + + current_user.uid = sec_ctx_stack[sec_ctx_stack_ndx].uid; + current_user.gid = sec_ctx_stack[sec_ctx_stack_ndx].gid; + current_user.ngroups = sec_ctx_stack[sec_ctx_stack_ndx].ngroups; + current_user.groups = sec_ctx_stack[sec_ctx_stack_ndx].groups; + + /* The conn and vuid are usually taken care of by other modules. + We initialise them here. */ + + current_user.conn = NULL; + current_user.vuid = UID_FIELD_INVALID; +} -- cgit From dbc0b86d1647c8fbc8e550d01a03d88052606f15 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 23 Jun 2000 05:54:49 +0000 Subject: Call init_sec_ctx() instead of init_uid(). Delete OriginalDir stuff. (This used to be commit db5e6ad3a69a6fd744d8a22066587908470e3815) --- source3/smbd/server.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b28ba6d4ef..854a61d385 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -43,10 +43,7 @@ extern pstring user_socket_options; extern int dcelogin_atmost_once; #endif /* WITH_DFS */ - extern fstring remote_machine; -extern pstring OriginalDir; - /* really we should have a top level context structure that has the client file descriptor as an element. That would require a major rewrite :( @@ -395,7 +392,6 @@ static BOOL dump_core(void) } #endif - /**************************************************************************** exit the server ****************************************************************************/ @@ -440,8 +436,6 @@ void exit_server(char *reason) exit(0); } - - /**************************************************************************** initialise connect, service and file structs ****************************************************************************/ @@ -634,9 +628,7 @@ static void usage(char *pname) so set our umask to 0 */ umask(0); - dos_GetWd(OriginalDir); - - init_uid(); + init_sec_ctx(); reopen_logs(); -- cgit From dd4c0901b6da73452d2d748cb425a8d715bc56c0 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 23 Jun 2000 05:57:20 +0000 Subject: Moved some static functions to sec_ctx.c Implemented become_root() and friends in terms of push/pop/set security contexts. (This used to be commit 0bcdcd0606fc2b6aba35b03255aad5bb2bd8e848) --- source3/smbd/uid.c | 252 +++++++---------------------------------------------- 1 file changed, 30 insertions(+), 222 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index d749470793..f3a606a1b1 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -28,108 +28,30 @@ extern int DEBUGLEVEL; /* what user is current? */ extern struct current_user current_user; -pstring OriginalDir; - -/**************************************************************************** - Initialise the uid routines. -****************************************************************************/ - -void init_uid(void) -{ - current_user.uid = geteuid(); - current_user.gid = getegid(); - - if (current_user.gid != 0 && current_user.uid == 0) { - gain_root_group_privilege(); - } - - current_user.conn = NULL; - current_user.vuid = UID_FIELD_INVALID; - - dos_ChDir(OriginalDir); -} - -/**************************************************************************** - Become the specified uid. -****************************************************************************/ - -static BOOL become_uid(uid_t uid) -{ - if (uid == (uid_t)-1 || ((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) { - static int done; - if (!done) { - DEBUG(1,("WARNING: using uid %d is a security risk\n",(int)uid)); - done=1; - } - } - - set_effective_uid(uid); - - current_user.uid = uid; - -#ifdef WITH_PROFILE - profile_p->uid_changes++; -#endif - - return(True); -} - - -/**************************************************************************** - Become the specified gid. -****************************************************************************/ - -static BOOL become_gid(gid_t gid) -{ - if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) && (gid == (gid_t)65535))) { - DEBUG(1,("WARNING: using gid %d is a security risk\n",(int)gid)); - } - - set_effective_gid(gid); - - current_user.gid = gid; - - return(True); -} - - -/**************************************************************************** - Become the specified uid and gid. -****************************************************************************/ - -static BOOL become_id(uid_t uid,gid_t gid) -{ - return(become_gid(gid) && become_uid(uid)); -} - /**************************************************************************** Become the guest user. ****************************************************************************/ BOOL become_guest(void) { - BOOL ret; - static struct passwd *pass=NULL; - - if (!pass) - pass = Get_Pwnam(lp_guestaccount(-1),True); - if (!pass) return(False); - + static struct passwd *pass=NULL; + + if (!pass) + pass = Get_Pwnam(lp_guestaccount(-1),True); + if (!pass) return(False); + #ifdef AIX - /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before setting IDs */ - initgroups(pass->pw_name, (gid_t)pass->pw_gid); + /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before + setting IDs */ + initgroups(pass->pw_name, (gid_t)pass->pw_gid); #endif - - ret = become_id(pass->pw_uid,pass->pw_gid); - - if (!ret) { - DEBUG(1,("Failed to become guest. Invalid guest account?\n")); - } - - current_user.conn = NULL; - current_user.vuid = UID_FIELD_INVALID; - - return(ret); + + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL); + + current_user.conn = NULL; + current_user.vuid = UID_FIELD_INVALID; + + return True; } /******************************************************************* @@ -153,7 +75,6 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) return(True); } - /**************************************************************************** Become the user of a connection number. ****************************************************************************/ @@ -162,7 +83,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; - gid_t gid; + gid_t gid; uid_t uid; char group_c; @@ -189,8 +110,6 @@ BOOL become_user(connection_struct *conn, uint16 vuid) return(True); } - unbecome_user(); - snum = SNUM(conn); if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) @@ -242,23 +161,8 @@ BOOL become_user(connection_struct *conn, uint16 vuid) } } - if (!become_gid(gid)) - return(False); + set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups); -#ifdef HAVE_SETGROUPS - if (!(conn && conn->ipc)) { - /* groups stuff added by ih/wreu */ - if (current_user.ngroups > 0) - if (sys_setgroups(current_user.ngroups, - current_user.groups)<0) { - DEBUG(0,("sys_setgroups call failed!\n")); - } - } -#endif - - if (!conn->admin_user && !become_uid(uid)) - return(False); - current_user.conn = conn; current_user.vuid = vuid; @@ -274,26 +178,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) BOOL unbecome_user(void ) { - if (!current_user.conn) - return(False); - - dos_ChDir(OriginalDir); - - set_effective_uid(0); - set_effective_gid(0); - - if (geteuid() != 0) { - DEBUG(0,("Warning: You appear to have a trapdoor uid system\n")); - } - if (getegid() != 0) { - DEBUG(0,("Warning: You appear to have a trapdoor gid system\n")); - } - - current_user.uid = 0; - current_user.gid = 0; - - if (dos_ChDir(OriginalDir) != 0) - DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); + set_root_sec_ctx(); DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); @@ -312,24 +197,13 @@ BOOL unbecome_user(void ) BOOL become_authenticated_pipe_user(pipes_struct *p) { - /* - * Go back to root. - */ - - if(!unbecome_user()) - return False; - - /* - * Now become the authenticated user stored in the pipe struct. - */ + BOOL res = push_sec_ctx(); - if(!become_id(p->uid, p->gid)) { - /* Go back to the connection user. */ - become_user(p->conn, p->vuid); + if (!res) { return False; } - return True; + set_sec_ctx(p->uid, p->gid, 0, NULL); /* fix group stuff */ } /**************************************************************************** @@ -340,88 +214,22 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) BOOL unbecome_authenticated_pipe_user(pipes_struct *p) { - if(!become_id(0,0)) { - DEBUG(0,("unbecome_authenticated_pipe_user: Unable to go back to root.\n")); - return False; - } - - return become_user(p->conn, p->vuid); + return pop_sec_ctx(); } -static struct current_user current_user_saved; -static int become_root_depth; -static pstring become_root_dir; - -/**************************************************************************** -This is used when we need to do a privileged operation (such as mucking -with share mode files) and temporarily need root access to do it. This -call should always be paired with an unbecome_root() call immediately -after the operation - -Set save_dir if you also need to save/restore the CWD -****************************************************************************/ +/* Temporarily become a root user. Must match with unbecome_root(). */ -void become_root(BOOL save_dir) +void become_root(void) { - if (become_root_depth) { - DEBUG(0,("ERROR: become root depth is non zero\n")); - } - if (save_dir) - dos_GetWd(become_root_dir); - - current_user_saved = current_user; - become_root_depth = 1; - - become_uid(0); - become_gid(0); + push_sec_ctx(); + set_root_sec_ctx(); } -/**************************************************************************** -When the privileged operation is over call this - -Set save_dir if you also need to save/restore the CWD -****************************************************************************/ +/* Unbecome the root user */ -void unbecome_root(BOOL restore_dir) +void unbecome_root(void) { - if (become_root_depth != 1) { - DEBUG(0,("ERROR: unbecome root depth is %d\n", - become_root_depth)); - } - - /* we might have done a become_user() while running as root, - if we have then become root again in order to become - non root! */ - if (current_user.uid != 0) { - become_uid(0); - } - - /* restore our gid first */ - if (!become_gid(current_user_saved.gid)) { - DEBUG(0,("ERROR: Failed to restore gid\n")); - exit_server("Failed to restore gid"); - } - -#ifdef HAVE_SETGROUPS - if (current_user_saved.ngroups > 0) { - if (sys_setgroups(current_user_saved.ngroups, - current_user_saved.groups)<0) - DEBUG(0,("ERROR: sys_setgroups call failed!\n")); - } -#endif - - /* now restore our uid */ - if (!become_uid(current_user_saved.uid)) { - DEBUG(0,("ERROR: Failed to restore uid\n")); - exit_server("Failed to restore uid"); - } - - if (restore_dir) - dos_ChDir(become_root_dir); - - current_user = current_user_saved; - - become_root_depth = 0; + pop_sec_ctx(); } #undef OLD_NTDOMAIN -- cgit From 2a1dbb0acdc3acd837681e148729899fb0160836 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 23 Jun 2000 05:57:48 +0000 Subject: Delete OriginalDir stuff. (This used to be commit 3d0f1845c8cefccfabcfd35694264c1e5f52c3af) --- source3/smbd/chgpasswd.c | 26 +++++++++++++++----------- source3/smbd/dosmode.c | 4 ++-- source3/smbd/password.c | 6 +++--- 3 files changed, 20 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index b6aaf4765b..1f1ee96713 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -412,7 +412,8 @@ static BOOL chat_with_program(char *passwordprogram, char *name, alarm(20); if (as_root) - become_root(False); + become_root(); + DEBUG(3, ("Dochild for user %s (uid=%d,gid=%d)\n", name, (int)getuid(), (int)getgid())); @@ -420,6 +421,9 @@ static BOOL chat_with_program(char *passwordprogram, char *name, dochild(master, slavedev, name, passwordprogram, as_root); + if (as_root) + unbecome_root(); + /* * The child should never return from dochild() .... */ @@ -546,9 +550,9 @@ BOOL check_lanman_password(char *user, uchar * pass1, *psmbpw = NULL; - become_root(0); + become_root(); smbpw = getsmbpwnam(user); - unbecome_root(0); + unbecome_root(); if (smbpw == NULL) { @@ -644,9 +648,9 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, uchar * pass1, smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ /* Now write it into the file. */ - become_root(0); + become_root(); ret = mod_smbpwd_entry(smbpw, False); - unbecome_root(0); + unbecome_root(); return ret; } @@ -713,9 +717,9 @@ BOOL check_oem_password(char *user, BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); - become_root(False); + become_root(); *psmbpw = smbpw = getsmbpwnam(user); - unbecome_root(False); + unbecome_root(); if (smbpw == NULL) { @@ -878,9 +882,9 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, smbpw->smb_nt_passwd = new_nt_p16; /* Now write it into the file. */ - become_root(0); + become_root(); ret = mod_smbpwd_entry(smbpw, override); - unbecome_root(0); + unbecome_root(); memset(new_passwd, '\0', strlen(new_passwd)); @@ -897,9 +901,9 @@ BOOL check_plaintext_password(char *user, char *old_passwd, struct smb_passwd *smbpw = NULL; uchar old_pw[16], old_ntpw[16]; - become_root(False); + become_root(); *psmbpw = smbpw = getsmbpwnam(user); - unbecome_root(False); + unbecome_root(); if (smbpw == NULL) { diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 5b077110bb..8e2382ee9f 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -270,9 +270,9 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) in_group(sb.st_gid,current_user.gid, current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ - become_root(False); + become_root(); ret = conn->vfs_ops.utime(dos_to_unix(fname, False), times); - unbecome_root(False); + unbecome_root(); } } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 06f4d72a40..209e4402df 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -329,10 +329,10 @@ static BOOL update_smbpassword_file(char *user, char *password) struct smb_passwd *smbpw; BOOL ret; - become_root(0); + become_root(); smbpw = getsmbpwnam(user); - unbecome_root(0); - + unbecome_root(); + if(smbpw == NULL) { DEBUG(0,("getsmbpwnam returned NULL\n")); return False; -- cgit From 0e4a583374a39eefbf442b426f9a7340acc5553f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 23 Jun 2000 06:27:05 +0000 Subject: Added return for become_authenticated_pipe_user() function. (This used to be commit d0f55e04c9400481e4a981431715e167a8246e45) --- source3/smbd/uid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index f3a606a1b1..e66abd1e98 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -204,6 +204,8 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) } set_sec_ctx(p->uid, p->gid, 0, NULL); /* fix group stuff */ + + return True; } /**************************************************************************** -- cgit From 5dd2bd50768ef57072e27b42faf7790875c7bae8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Jun 2000 17:31:38 +0000 Subject: lib/util_unistr.c: Off-by-one fix for dos_PutUniStr from John Reilly jreilly@hp.com. Memory leak fix for new sec_ctx code (sorry Tim :-). Jeremy. (This used to be commit edaf49c66d5a5ccf6689b358c301e208599a468f) --- source3/smbd/sec_ctx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index e3aac77d8e..bbd801d76b 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -184,11 +184,15 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) #ifdef HAVE_SETGROUPS sys_setgroups(ngroups, groups); +#endif sec_ctx_stack[sec_ctx_stack_ndx].ngroups = ngroups; + + if (sec_ctx_stack[sec_ctx_stack_ndx].groups != NULL) + free(sec_ctx_stack[sec_ctx_stack_ndx].groups); + sec_ctx_stack[sec_ctx_stack_ndx].groups = memdup(groups, sizeof(gid_t) * ngroups); -#endif become_id(uid, gid); -- cgit From a8c21a8e6b747123d9a176a8048f05f68499b463 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Jun 2000 19:57:42 +0000 Subject: Fix a malloc of zero problem. Jeremy. (This used to be commit 2aa21db960666736331b18956422b7c13aad0f0f) --- source3/smbd/sec_ctx.c | 87 ++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index bbd801d76b..f7ea1e2d86 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -143,6 +143,8 @@ static void get_current_groups(int *ngroups, gid_t **groups) BOOL push_sec_ctx(void) { + struct sec_ctx *ctx_p; + /* Check we don't overflow our stack */ if (sec_ctx_stack_ndx == (MAX_SEC_CTX_DEPTH)) { @@ -154,20 +156,23 @@ BOOL push_sec_ctx(void) sec_ctx_stack_ndx++; - sec_ctx_stack[sec_ctx_stack_ndx].uid = geteuid(); - sec_ctx_stack[sec_ctx_stack_ndx].gid = getegid(); + ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; - sec_ctx_stack[sec_ctx_stack_ndx].ngroups = sys_getgroups(0, NULL); + ctx_p->uid = geteuid(); + ctx_p->gid = getegid(); - if (!(sec_ctx_stack[sec_ctx_stack_ndx].groups = - malloc(sec_ctx_stack[sec_ctx_stack_ndx].ngroups * - sizeof(gid_t)))) { - DEBUG(0, ("Out of memory in push_sec_ctx()\n")); - return False; - } + ctx_p->ngroups = sys_getgroups(0, NULL); + + if (ctx_p->ngroups != 0) { + if (!(ctx_p->groups = malloc(ctx_p->ngroups * sizeof(gid_t)))) { + DEBUG(0, ("Out of memory in push_sec_ctx()\n")); + return False; + } - sys_getgroups(sec_ctx_stack[sec_ctx_stack_ndx].ngroups, - sec_ctx_stack[sec_ctx_stack_ndx].groups); + sys_getgroups(ctx_p->ngroups, ctx_p->groups); + } else { + ctx_p->groups = NULL; + } return True; } @@ -176,6 +181,8 @@ BOOL push_sec_ctx(void) void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) { + struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; + /* Set the security context */ DEBUG(3, ("setting sec ctx (%d, %d)\n", uid, gid)); @@ -186,18 +193,16 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) sys_setgroups(ngroups, groups); #endif - sec_ctx_stack[sec_ctx_stack_ndx].ngroups = ngroups; + ctx_p->ngroups = ngroups; - if (sec_ctx_stack[sec_ctx_stack_ndx].groups != NULL) - free(sec_ctx_stack[sec_ctx_stack_ndx].groups); + safe_free(ctx_p->groups); - sec_ctx_stack[sec_ctx_stack_ndx].groups = - memdup(groups, sizeof(gid_t) * ngroups); + ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups); become_id(uid, gid); - sec_ctx_stack[sec_ctx_stack_ndx].uid = uid; - sec_ctx_stack[sec_ctx_stack_ndx].gid = gid; + ctx_p->uid = uid; + ctx_p->gid = gid; /* Update current_user stuff */ @@ -220,6 +225,9 @@ void set_root_sec_ctx(void) BOOL pop_sec_ctx(void) { + struct sec_ctx *ctx_p; + struct sec_ctx *prev_ctx_p; + /* Check for stack underflow */ if (sec_ctx_stack_ndx == 0) { @@ -227,13 +235,15 @@ BOOL pop_sec_ctx(void) return False; } + ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; + /* Clear previous user info */ - sec_ctx_stack[sec_ctx_stack_ndx].uid = (uid_t)-1; - sec_ctx_stack[sec_ctx_stack_ndx].gid = (gid_t)-1; + ctx_p->uid = (uid_t)-1; + ctx_p->gid = (gid_t)-1; - safe_free(sec_ctx_stack[sec_ctx_stack_ndx].groups); - sec_ctx_stack[sec_ctx_stack_ndx].ngroups = 0; + safe_free(ctx_p->groups); + ctx_p->ngroups = 0; /* Pop back previous user */ @@ -241,20 +251,20 @@ BOOL pop_sec_ctx(void) gain_root(); + prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; + #ifdef HAVE_SETGROUPS - sys_setgroups(sec_ctx_stack[sec_ctx_stack_ndx].ngroups, - sec_ctx_stack[sec_ctx_stack_ndx].groups); + sys_setgroups(prev_ctx_p->ngroups, prev_ctx_p->groups); #endif - become_id(sec_ctx_stack[sec_ctx_stack_ndx].uid, - sec_ctx_stack[sec_ctx_stack_ndx].gid); + become_id(prev_ctx_p->uid, prev_ctx_p->gid); /* Update current_user stuff */ - current_user.uid = sec_ctx_stack[sec_ctx_stack_ndx].uid; - current_user.gid = sec_ctx_stack[sec_ctx_stack_ndx].gid; - current_user.ngroups = sec_ctx_stack[sec_ctx_stack_ndx].ngroups; - current_user.groups = sec_ctx_stack[sec_ctx_stack_ndx].groups; + current_user.uid = prev_ctx_p->uid; + current_user.gid = prev_ctx_p->gid; + current_user.ngroups = prev_ctx_p->ngroups; + current_user.groups = prev_ctx_p->groups; DEBUG(3, ("popped off to sec ctx (%d, %d)\n", geteuid(), getegid())); @@ -266,6 +276,7 @@ BOOL pop_sec_ctx(void) void init_sec_ctx(void) { int i; + struct sec_ctx *ctx_p; /* Initialise security context stack */ @@ -277,19 +288,19 @@ void init_sec_ctx(void) } /* Initialise first level of stack. It is the current context */ + ctx_p = &sec_ctx_stack[0]; - sec_ctx_stack[0].uid = geteuid(); - sec_ctx_stack[0].gid = getegid(); + ctx_p->uid = geteuid(); + ctx_p->gid = getegid(); - get_current_groups(&sec_ctx_stack[0].ngroups, - &sec_ctx_stack[0].groups); + get_current_groups(&ctx_p->ngroups, &ctx_p->groups); /* Initialise current_user global */ - current_user.uid = sec_ctx_stack[sec_ctx_stack_ndx].uid; - current_user.gid = sec_ctx_stack[sec_ctx_stack_ndx].gid; - current_user.ngroups = sec_ctx_stack[sec_ctx_stack_ndx].ngroups; - current_user.groups = sec_ctx_stack[sec_ctx_stack_ndx].groups; + current_user.uid = ctx_p->uid; + current_user.gid = ctx_p->gid; + current_user.ngroups = ctx_p->ngroups; + current_user.groups = ctx_p->groups; /* The conn and vuid are usually taken care of by other modules. We initialise them here. */ -- cgit From f048209484b10ed397c55864ca9ee29789f4e372 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 3 Jul 2000 06:52:31 +0000 Subject: Some more sec_ctx changes. Modified some fields in the pipe_struct structure so authenticated pipe users can have their unix groups set when become_authenticated_pipe_user() is called. (This used to be commit 55c9bf124dc661df43bfe582ef14b1297aeaf0fa) --- source3/smbd/uid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index e66abd1e98..2078bb5a7d 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -203,7 +203,8 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) return False; } - set_sec_ctx(p->uid, p->gid, 0, NULL); /* fix group stuff */ + set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, + p->pipe_user.n_groups, p->pipe_user.groups); return True; } -- cgit From 96446651af3f41c74de751f091740b06268a7a8c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 6 Jul 2000 07:01:37 +0000 Subject: Moved authenticated pipe user details into a current_user struct. (This used to be commit 3c4a5f624bfa69eb81d998530d9227e158edd109) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 2078bb5a7d..172e872020 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -204,7 +204,7 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) } set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, - p->pipe_user.n_groups, p->pipe_user.groups); + p->pipe_user.ngroups, p->pipe_user.groups); return True; } -- cgit From 75dd5b5051f6e0f29ae51ecbc493d78e44ca5e21 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 6 Jul 2000 07:10:32 +0000 Subject: Don't check NT permissions when printing from lanman. (This used to be commit e84607eedf3be454f8f709c70cafc5ded4ea951d) --- source3/smbd/lanman.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index bf635b88b1..82f0c25fa8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1773,13 +1773,13 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param switch (function) { case 81: /* delete */ - if (print_job_delete(jobid, vuid)) errcode = NERR_Success; + if (print_job_delete(NULL, jobid)) errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(jobid, vuid)) errcode = NERR_Success; + if (print_job_pause(NULL, jobid)) errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(jobid, vuid)) errcode = NERR_Success; + if (print_job_resume(NULL, jobid)) errcode = NERR_Success; break; } @@ -1822,13 +1822,13 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para switch (function) { case 74: /* Pause queue */ - if (print_queue_pause(snum, vuid)) errcode = NERR_Success; + if (print_queue_pause(NULL, snum)) errcode = NERR_Success; break; case 75: /* Resume queue */ - if (print_queue_resume(snum, vuid)) errcode = NERR_Success; + if (print_queue_resume(NULL, snum)) errcode = NERR_Success; break; case 103: /* Purge */ - if (print_queue_purge(snum, vuid)) errcode = NERR_Success; + if (print_queue_purge(NULL, snum)) errcode = NERR_Success; break; } -- cgit From 5af35320a92e39b924b0bfebd2c4caae24724231 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 10 Jul 2000 04:57:09 +0000 Subject: Spelling fixes. (This used to be commit c1d242f1dd5b6addbe5d2df22e4759f6682fd9ef) --- source3/smbd/password.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 209e4402df..fffddb4610 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1384,7 +1384,7 @@ BOOL domain_client_validate( char *user, char *domain, { unsigned char local_challenge[8]; unsigned char local_lm_response[24]; - unsigned char local_nt_reponse[24]; + unsigned char local_nt_response[24]; unsigned char trust_passwd[16]; fstring remote_machine; char *p, *pserver; @@ -1422,11 +1422,11 @@ BOOL domain_client_validate( char *user, char *domain, DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); generate_random_buffer( local_challenge, 8, False); SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); - SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_reponse); + SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_response); smb_apasslen = 24; smb_ntpasslen = 24; smb_apasswd = (char *)local_lm_response; - smb_ntpasswd = (char *)local_nt_reponse; + smb_ntpasswd = (char *)local_nt_response; } else { /* -- cgit From 78a4848e8da7bb4f96e99e3419c5473c4c23bb6d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 10 Jul 2000 05:08:21 +0000 Subject: Re-instated lanman printing security checks (oops). A user can now pause, resume or delete their own job even if they don't have the Manage Documents privilege. Added call to se_access_check() for changing printer properties. The Full Access privilege is required for the user to perform this. Several uninitialised variables and memory leaks plugged. Modified default ACL created on new printers to be Everyone / Print instead of Everyone / Full Access. This required some random stuffing around with the value of the revision field to correspond with the ACL that NT produces when setting the same permission on the printer. Fixed dodgy function call in printing/printfsp.c (This used to be commit 2abce4dcfa351051df6e5f789b34fa99c9b81c22) --- source3/smbd/lanman.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 82f0c25fa8..e5a42d4db4 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1753,6 +1753,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); int jobid, errcode; + extern struct current_user current_user; jobid = SVAL(p,0); @@ -1773,13 +1774,16 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param switch (function) { case 81: /* delete */ - if (print_job_delete(NULL, jobid)) errcode = NERR_Success; + if (print_job_delete(¤t_user, jobid)) + errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(NULL, jobid)) errcode = NERR_Success; + if (print_job_pause(¤t_user, jobid)) + errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(NULL, jobid)) errcode = NERR_Success; + if (print_job_resume(¤t_user, jobid)) + errcode = NERR_Success; break; } -- cgit From b561c185972921861946a69b8846681bc7ed3f87 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 10 Jul 2000 06:41:04 +0000 Subject: Fixes for various compile warnings on Solaris 8. (This used to be commit 898a483cdab1ed7d8ff902c0dc0e0620440ae4cd) --- source3/smbd/vfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9a1af18b3d..7c34817351 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -83,6 +83,7 @@ int vfs_init_default(connection_struct *conn) /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ + #ifdef HAVE_LIBDL BOOL vfs_init_custom(connection_struct *conn) { @@ -105,7 +106,8 @@ BOOL vfs_init_custom(connection_struct *conn) /* Get handle on vfs_init() symbol */ - fptr = dlsym(handle, "vfs_init"); + fptr = (struct vfs_ops *(*)(struct vfs_options *)) + dlsym(handle, "vfs_init"); if (fptr == NULL) { DEBUG(0, ("No vfs_init() symbol found in %s\n", -- cgit From 5c162bbe5b6ce32f894c3ee77da9dcdd9c840ad4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2000 20:11:11 +0000 Subject: Code from John Reilly to add tdb lookups into the Win95 printer driver download if looking for the default driver files fail. Jeremy. (This used to be commit 1192d867c4e863471f9bc12afceb68a23ba2142e) --- source3/smbd/lanman.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e5a42d4db4..a51ea92353 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -498,15 +498,17 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, pstring tok,driver,datafile,langmon,helpfile,datatype; char *p; char **lines, *line; + pstring gen_line; + DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", + snum, lp_printerdriver(snum), lp_driverfile(snum))); lines = file_lines_load(lp_driverfile(snum),NULL); if (!lines) { DEBUG(3,("fill_printq_info: Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - desc->errcode=NERR_notsupported; - return; } - + else + { /* lookup the long printer driver name in the file description */ for (i=0;lines[i] && !ok;i++) { @@ -516,6 +518,22 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) ok=1; } + } + + if( !ok ) { + /* no printers.def, or driver not found, check the NT driver tdb */ + if ( ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) { + p = gen_line; + DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", + lp_printerdriver(snum), gen_line)); + } else { + /* didn't find driver in tdb either... oh well */ + DEBUG(10,("9x driver not found in tdb\n")); + desc->errcode=NERR_notsupported; + return; + } + } + line = strdup(p); p = line; file_lines_free(lines); @@ -667,21 +685,40 @@ static int get_printerdrivernumber(int snum) pstring tok; char *p; char **lines, *line; + pstring gen_line; + DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", + snum, lp_printerdriver(snum), lp_driverfile(snum))); lines = file_lines_load(lp_driverfile(snum), NULL); if (!lines) { DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - return(0); } - - /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok; i++) { + else + { + /* lookup the long printer driver name in the file + description */ + for (i=0;lines[i] && !ok;i++) { p = lines[i]; if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) ok=1; } + } + + if( !ok ) { + /* no printers.def, or driver not found, check the NT driver tdb */ + if ( ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) { + p = gen_line; + DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", + lp_printerdriver(snum), gen_line)); + } else { + /* didn't find driver in tdb either... oh well */ + DEBUG(10,("9x driver not found in tdb\n")); + return (0); + } + } line = strdup(p); p = line; file_lines_free(lines); -- cgit From 9f040cc17ea6c5f536571fa37a10125ec3f12765 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2000 23:47:10 +0000 Subject: Modified the patch to look in the tdb *first* - thus allowing legacy text filed to be ignored when an upload is done. Modified to code to goto err on problems, simplifies it. Jeremy. (This used to be commit 9157a6ab2646c035a731d53aa3be010488ccf51a) --- source3/smbd/lanman.c | 166 +++++++++++++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 75 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a51ea92353..078e3385dc 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -494,112 +494,128 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, int count, print_queue_struct* queue, print_status_struct* status) { - int i,ok=0; + int i; + BOOL ok = False; pstring tok,driver,datafile,langmon,helpfile,datatype; char *p; - char **lines, *line; + char **lines; + char *line = NULL; pstring gen_line; + /* + * Check in the tdb *first* before checking the legacy + * files. This allows an NT upload to take precedence over + * the existing fileset. JRA. + */ + + if ( ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) { + p = gen_line; + DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); + } else { + /* didn't find driver in tdb either... oh well */ + DEBUG(10,("9x driver not found in tdb\n")); + } + DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", snum, lp_printerdriver(snum), lp_driverfile(snum))); + lines = file_lines_load(lp_driverfile(snum),NULL); + if (!lines) { DEBUG(3,("fill_printq_info: Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - } - else - { - /* lookup the long printer driver name in the file - description */ - for (i=0;lines[i] && !ok;i++) { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok=1; - } - } - - if( !ok ) { - /* no printers.def, or driver not found, check the NT driver tdb */ - if ( ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) { - p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", - lp_printerdriver(snum), gen_line)); - } else { - /* didn't find driver in tdb either... oh well */ - DEBUG(10,("9x driver not found in tdb\n")); desc->errcode=NERR_notsupported; return; + } else { + /* lookup the long printer driver name in the file + description */ + for (i=0;lines[i] && !ok;i++) { + p = lines[i]; + if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + ok = True; } } - line = strdup(p); + if (!ok) + goto err; + + if ((line = strdup(p)) == NULL) + goto err; + p = line; file_lines_free(lines); /* driver file name */ - if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0; + if (!next_token(&p,driver,":",sizeof(driver))) + goto err; + /* data file name */ - if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0; + if (!next_token(&p,datafile,":",sizeof(datafile))) + goto err; + /* * for the next tokens - which may be empty - I have * to check for empty tokens first because the * next_token function will skip all empty token * fields */ - if (ok) { - /* help file */ - if (*p == ':') { - *helpfile = '\0'; - p++; - } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0; - } + + /* help file */ + if (*p == ':') { + *helpfile = '\0'; + p++; + } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) + goto err; - if (ok) { - /* language monitor */ - if (*p == ':') { - *langmon = '\0'; - p++; - } else if (!next_token(&p,langmon,":",sizeof(langmon))) - ok = 0; - } + /* language monitor */ + if (*p == ':') { + *langmon = '\0'; + p++; + } else if (!next_token(&p,langmon,":",sizeof(langmon))) + goto err; /* default data type */ - if (ok && !next_token(&p,datatype,":",sizeof(datatype))) - ok = 0; + if (!next_token(&p,datatype,":",sizeof(datatype))) + goto err; - if (ok) { - PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ - PACKS(desc,"z",driver); /* Driverfile Name */ - PACKS(desc,"z",datafile); /* Datafile name */ - PACKS(desc,"z",langmon); /* language monitor */ - PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ - PACKS(desc,"z",datatype); /* default data type */ - PACKS(desc,"z",helpfile); /* helpfile name */ - PACKS(desc,"z",driver); /* driver name */ - DEBUG(3,("Driver:%s:\n",driver)); - DEBUG(3,("Data File:%s:\n",datafile)); - DEBUG(3,("Language Monitor:%s:\n",langmon)); - DEBUG(3,("Data Type:%s:\n",datatype)); - DEBUG(3,("Help File:%s:\n",helpfile)); - PACKI(desc,"N",count); /* number of files to copy */ - for (i=0;i gave %d entries\n", - SERVICE(snum),count)); - } else { - DEBUG(3,("fill_printq_info: Can't supply driver files\n")); - desc->errcode=NERR_notsupported; + PACKI(desc,"W",0x0400); /* don't know */ + PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ + PACKS(desc,"z",driver); /* Driverfile Name */ + PACKS(desc,"z",datafile); /* Datafile name */ + PACKS(desc,"z",langmon); /* language monitor */ + PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ + PACKS(desc,"z",datatype); /* default data type */ + PACKS(desc,"z",helpfile); /* helpfile name */ + PACKS(desc,"z",driver); /* driver name */ + DEBUG(3,("Driver:%s:\n",driver)); + DEBUG(3,("Data File:%s:\n",datafile)); + DEBUG(3,("Language Monitor:%s:\n",langmon)); + DEBUG(3,("Data Type:%s:\n",datatype)); + DEBUG(3,("Help File:%s:\n",helpfile)); + PACKI(desc,"N",count); /* number of files to copy */ + + for (i=0;i gave %d entries\n", + SERVICE(snum),count)); + free(line); + return; + + err: + + DEBUG(3,("fill_printq_info: Can't supply driver files\n")); + desc->errcode=NERR_notsupported; + if (line) + free(line); } -- cgit From 47f8f8e52227024f6b5889f7d12d7d0aa0a7104e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 24 Jul 2000 06:20:13 +0000 Subject: Run main server loop with sys_select() instead of sys_select_intr(). The main daemon was not catching sighup and reloading the service file. (This used to be commit f026a897e9296a71fb5c4d5f6e1b4d3287689bde) --- source3/smbd/server.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 854a61d385..8691603eb3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -200,10 +200,21 @@ max can be %d\n", memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select_intr(FD_SETSIZE,&lfds,NULL); + num = sys_select(FD_SETSIZE,&lfds,NULL); - if (num == -1 && errno == EINTR) + if (num == -1 && errno == EINTR) { + extern VOLATILE SIG_ATOMIC_T reload_after_sighup; + + /* check for sighup processing */ + if (reload_after_sighup) { + unbecome_user(); + DEBUG(1,("Reloading services after SIGHUP\n")); + reload_services(False); + reload_after_sighup = False; + } + continue; + } /* check if we need to reload services */ check_reload(time(NULL)); -- cgit From b40175936ae3d7acd6eb3f386c467ba3f9868631 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 25 Jul 2000 06:10:59 +0000 Subject: Fix for mounting a printer as a share. Not that there's anything specifically wrong with this, but Samba is fooled by the client into thinking the printer is a file share. Files copied to the share gather dust in the spool directory and aren't printed. This patch has the effect of not allowing printers to be mounted as file shares. Not sure whether this is the correct solution or not. {Jeremy,JF,Tridge} please check! (This used to be commit dcf3249bb9fef2a05b376e9c8c1a0a7d602d8a2e) --- source3/smbd/service.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e6c8b2a6d8..2eab50c482 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -273,6 +273,11 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } + /* Behave as a printer if we are supposed to */ + if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { + pstrcpy(dev, "LPT1:"); + } + /* lowercase the user name */ strlower(user); -- cgit From 5a5ef183799dd84ff453db849e929533e709fd0b Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Tue, 25 Jul 2000 13:15:16 +0000 Subject: A rather big change set ! (listed in no particular order) - changed the default forms flag to 2 - all short architecture name are uppercased - get_short_archi() is now case unsensitive - the drivers TDB is indexed by archi/version/name - implemented code to move drivers from the upload area to the download area. Someone else need to look at that code. - don't return anymore a default driver if it doesn't exist in the TDB. Instead return an error. - cleaned prs_unistr. - #ifdef out jeremy's new SD parsing in printer_info_2 - removed the unused MANGLE_CODE - #ifdef out the security checking in update_printer() as it doesn't work for me. Zap your ntdrivers.tdb, it won't work anymore. J.F. (This used to be commit ac0a145acc0953a6f362497abbf4dfe70aa522a6) --- source3/smbd/reply.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 00a0ce3c4a..19af1fdc3d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3101,15 +3101,14 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ /**************************************************************************** - reply to a mkdir + The guts of the mkdir command, split out so it may be called by the NT SMB + code. ****************************************************************************/ -int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory) { - pstring directory; - int outsize,ret= -1; BOOL bad_path = False; - - pstrcpy(directory,smb_buf(inbuf) + 1); + int ret= -1; + unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) @@ -3125,10 +3124,23 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } return(UNIXERROR(ERRDOS,ERRnoaccess)); } +} - outsize = set_message(outbuf,0,0,True); +/**************************************************************************** + reply to a mkdir +****************************************************************************/ +int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +{ + pstring directory; + int outsize; + + pstrcpy(directory,smb_buf(inbuf) + 1); + + outsize=mkdir_internal(conn, inbuf, outbuf, directory); + if(outsize == 0) + outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) ); + DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); return(outsize); } -- cgit From fcbf69495784000861d432c13217702cc28884f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Jul 2000 17:09:29 +0000 Subject: Added some error checking and returns to the new 'move' code. Jeremy. (This used to be commit 0bd88d304cd773e0bbf3e6f7fedcb3b544d41cbe) --- source3/smbd/reply.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 19af1fdc3d..8aa7f7c9e4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3124,6 +3124,8 @@ int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring d } return(UNIXERROR(ERRDOS,ERRnoaccess)); } + + return ret; } /**************************************************************************** -- cgit From bc22ae0b47bddd919b07e4c81ae12243c1f3226a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Jul 2000 22:35:57 +0000 Subject: Fixed up error checking and move printer file code. Fixed a memory leak. Jeremy. (This used to be commit 5130dd0f8b80aed5fb3c0df290b627057cc9b825) --- source3/smbd/lanman.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 078e3385dc..6cb63f18f7 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -508,7 +508,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, * the existing fileset. JRA. */ - if ( ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) { + if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) == True) { p = gen_line; DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); } else { @@ -725,7 +725,7 @@ static int get_printerdrivernumber(int snum) if( !ok ) { /* no printers.def, or driver not found, check the NT driver tdb */ - if ( ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) { + if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)))==True ) { p = gen_line; DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); -- cgit From 5ec1642809d9de83da8c88c65d6595c6eb0270f5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Jul 2000 00:47:19 +0000 Subject: Ok - this is a *BIG* change - but it fixes the problems with static strings in the RPC code. This change was prompted by trying to save a long (>256) character comment in the printer properties page. The new system associates a TALLOC_CTX with the pipe struct, and frees the pool on return of a complete PDU. A global TALLOC_CTX is used for the odd buffer allocated in the BUFFERxx code, and is freed in the main loop. This code works with insure, and seems to be free of memory leaks and crashes (so far) but there are probably the occasional problem with code that uses UNISTRxx structs on the stack and expects them to contain storage without doing a init_unistrXX(). This means that rpcclient will probably be horribly broken. A TALLOC_CTX also needed associating with the struct cli_state also, to make the prs_xx code there work. The main interface change is the addition of a TALLOC_CTX to the prs_init calls - used for dynamic allocation in the prs_XXX calls. Now this is in place it should make dynamic allocation of all RPC memory on unmarshall *much* easier to fix. Jeremy. (This used to be commit 0ff2ce543ee54f7364e6d839db6d06e7ef1edcf4) --- source3/smbd/nttrans.c | 22 ++++++++++++++++++++-- source3/smbd/process.c | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4e4e418efd..4673c87f58 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1496,6 +1496,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, prs_struct pd; SEC_DESC *psd = NULL; size_t sd_size; + TALLOC_CTX *mem_ctx; files_struct *fsp = file_fsp(params,0); @@ -1544,7 +1545,13 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Init the parse struct we will marshall into. */ - prs_init(&pd, 0, 4, MARSHALL); + if ((mem_ctx = talloc_init()) == NULL) { + DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); + free_sec_desc(&psd); + return(ERROR(ERRDOS,ERRnomem)); + } + + prs_init(&pd, 0, 4, mem_ctx, MARSHALL); /* * Setup the prs_struct to point at the memory we just @@ -1564,6 +1571,7 @@ security descriptor.\n")); /* * Return access denied for want of a better error message.. */ + talloc_destroy(mem_ctx); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1572,6 +1580,7 @@ security descriptor.\n")); */ free_sec_desc(&psd); + talloc_destroy(mem_ctx); send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sd_size); return -1; @@ -1594,6 +1603,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); files_struct *fsp = NULL; uint32 security_info_sent = 0; + TALLOC_CTX *mem_ctx; if(!lp_nt_acl_support()) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1613,7 +1623,12 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, * Init the parse struct we will unmarshall from. */ - prs_init(&pd, 0, 4, UNMARSHALL); + if ((mem_ctx = talloc_init()) == NULL) { + DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); + return(ERROR(ERRDOS,ERRnomem)); + } + + prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL); /* * Setup the prs_struct to point at the memory we just @@ -1633,15 +1648,18 @@ security descriptor.\n")); /* * Return access denied for want of a better error message.. */ + talloc_destroy(mem_ctx); return(UNIXERROR(ERRDOS,ERRnoaccess)); } if (!set_nt_acl(fsp, security_info_sent, psd)) { free_sec_desc(&psd); + talloc_destroy(mem_ctx); return(UNIXERROR(ERRDOS,ERRnoaccess)); } free_sec_desc(&psd); + talloc_destroy(mem_ctx); send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); return -1; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3c85c05312..2662db5896 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1042,6 +1042,7 @@ void smbd_process(void) /* free up temporary memory */ lp_talloc_free(); + parse_talloc_free(); while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) -- cgit From 49fcb300de40d6da8682b485fd2c51236bcbb3dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Jul 2000 20:41:51 +0000 Subject: Added John Reilly's enumports/addprinter/delprinter scripting code plus the fix for the Win9x printer drivers. Changed command names to add "command" string on the end for some consistancy with the other scripting commands. Added '%P' option to tdbpack/unpack to store long comment string. Made port name be "Samba Printer Port" if no enum port script given. Fixed prs_uint32_pre code to cope with null args. Jeremy. (This used to be commit 902ada63799cf27924c72e24e7593a8c9fb5eba9) --- source3/smbd/lanman.c | 92 ++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 6cb63f18f7..ab2fd4d55d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -495,11 +495,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, print_status_struct* status) { int i; - BOOL ok = False; + BOOL ok; pstring tok,driver,datafile,langmon,helpfile,datatype; char *p; - char **lines; - char *line = NULL; + char **lines = NULL; pstring gen_line; /* @@ -512,23 +511,18 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, p = gen_line; DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); } else { - /* didn't find driver in tdb either... oh well */ - DEBUG(10,("9x driver not found in tdb\n")); - } + /* didn't find driver in tdb */ DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", snum, lp_printerdriver(snum), lp_driverfile(snum))); lines = file_lines_load(lp_driverfile(snum),NULL); - if (!lines) { - DEBUG(3,("fill_printq_info: Can't open %s - %s\n", - lp_driverfile(snum),strerror(errno))); + DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); desc->errcode=NERR_notsupported; return; } else { - /* lookup the long printer driver name in the file - description */ + /* lookup the long printer driver name in the file description */ for (i=0;lines[i] && !ok;i++) { p = lines[i]; if (next_token(&p,tok,":",sizeof(tok)) && @@ -537,16 +531,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, ok = True; } } + } - if (!ok) - goto err; - - if ((line = strdup(p)) == NULL) - goto err; - - p = line; - file_lines_free(lines); - + if (ok) + { /* driver file name */ if (!next_token(&p,driver,":",sizeof(driver))) goto err; @@ -588,9 +576,11 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z",datatype); /* default data type */ PACKS(desc,"z",helpfile); /* helpfile name */ PACKS(desc,"z",driver); /* driver name */ + DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum))); DEBUG(3,("Driver:%s:\n",driver)); DEBUG(3,("Data File:%s:\n",datafile)); DEBUG(3,("Language Monitor:%s:\n",langmon)); + DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum))); DEBUG(3,("Data Type:%s:\n",datatype)); DEBUG(3,("Help File:%s:\n",helpfile)); PACKI(desc,"N",count); /* number of files to copy */ @@ -607,15 +597,16 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),count)); - free(line); + desc->errcode=NERR_Success; + file_lines_free(lines); return; + } err: DEBUG(3,("fill_printq_info: Can't supply driver files\n")); desc->errcode=NERR_notsupported; - if (line) - free(line); + file_lines_free(lines); } @@ -697,64 +688,67 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, /* This function returns the number of files for a given driver */ static int get_printerdrivernumber(int snum) { - int i=0,ok=0; + int i; + BOOL ok; pstring tok; char *p; - char **lines, *line; + char **lines = NULL; pstring gen_line; + /* + * Check in the tdb *first* before checking the legacy + * files. This allows an NT upload to take precedence over + * the existing fileset. JRA. + */ + + if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum))) == True ) { + p = gen_line; + DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); + } else { + /* didn't find driver in tdb */ + DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", snum, lp_printerdriver(snum), lp_driverfile(snum))); + lines = file_lines_load(lp_driverfile(snum), NULL); if (!lines) { - DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n", - lp_driverfile(snum),strerror(errno))); + DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); } else { - /* lookup the long printer driver name in the file - description */ + /* lookup the long printer driver name in the file description */ for (i=0;lines[i] && !ok;i++) { p = lines[i]; if (next_token(&p,tok,":",sizeof(tok)) && (strlen(lp_printerdriver(snum)) == strlen(tok)) && (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok=1; + ok = True; } - } - - if( !ok ) { - /* no printers.def, or driver not found, check the NT driver tdb */ - if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)))==True ) { - p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", - lp_printerdriver(snum), gen_line)); - } else { - /* didn't find driver in tdb either... oh well */ - DEBUG(10,("9x driver not found in tdb\n")); - return (0); } } - line = strdup(p); - p = line; - file_lines_free(lines); - if (ok) { + if( ok ) { /* skip 5 fields */ i = 5; while (*p && i) { if (*p++ == ':') i--; } if (!*p || i) - return(0); + goto err; /* count the number of files */ while (next_token(&p,tok,",",sizeof(tok))) i++; - } - free(line); + file_lines_free(lines); return(i); + } + + err: + + DEBUG(3,("Can't determine number of printer driver files\n")); + file_lines_free(lines); + return (0); } static BOOL api_DosPrintQGetInfo(connection_struct *conn, -- cgit From d95777ac34f68a3525786103b9217f6397d9f1d4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Aug 2000 00:41:19 +0000 Subject: Added print job substitutions for %{printername}, %{sharename} and %{portname} from the NT printer tdb. Also added checks for time restrictions before allowing a job to print. Jeremy. (This used to be commit 8cfb55e81abebf0354e6d470ed68bbac1d6560ad) --- source3/smbd/lanman.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index ab2fd4d55d..047212bf9f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -707,23 +707,21 @@ static int get_printerdrivernumber(int snum) } else { /* didn't find driver in tdb */ - DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", + DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", snum, lp_printerdriver(snum), lp_driverfile(snum))); - lines = file_lines_load(lp_driverfile(snum), NULL); - if (!lines) { + lines = file_lines_load(lp_driverfile(snum), NULL); + if (!lines) { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - } - else - { + } else { /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + for (i=0;lines[i] && !ok;i++) { + p = lines[i]; + if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) ok = True; - } + } } } @@ -741,7 +739,7 @@ static int get_printerdrivernumber(int snum) i++; file_lines_free(lines); - return(i); + return(i); } err: @@ -861,10 +859,10 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, return(True); } - /**************************************************************************** - view list of all print jobs on all queues - ****************************************************************************/ + View list of all print jobs on all queues. +****************************************************************************/ + static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data, int mdrcnt, int mprcnt, char **rdata, char** rparam, -- cgit From 7f36df301e28dc8ca0e5bfadc109d6e907d9ba2b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Aug 2000 18:32:34 +0000 Subject: Tidyup removing many of the 0xC0000000 | NT_STATUS_XXX stuff (only need NT_STATUS_XXX). Removed IS_BITS_xxx macros as they were just reproducing "C" syntax in a more obscure way. Jeremy. (This used to be commit c55bcec817f47d6162466b193d533c877194124a) --- source3/smbd/nttrans.c | 10 +++++----- source3/smbd/password.c | 4 ++-- source3/smbd/reply.c | 47 ++++++++++++++++++----------------------------- 3 files changed, 25 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4673c87f58..8147a3adac 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -718,7 +718,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if( fname[0] == ':') { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_OBJECT_PATH_NOT_FOUND)); + return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } return(ERROR(ERRDOS,ERRbadfid)); } @@ -848,7 +848,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); + return(ERROR(0, NT_STATUS_FILE_IS_A_DIRECTORY)); } oplock_request = 0; @@ -1140,7 +1140,7 @@ static int call_nt_transact_create(connection_struct *conn, if( fname[0] == ':') { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_OBJECT_PATH_NOT_FOUND)); + return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } return(ERROR(ERRDOS,ERRbadfid)); @@ -1250,7 +1250,7 @@ static int call_nt_transact_create(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); + return(ERROR(0, NT_STATUS_FILE_IS_A_DIRECTORY)); } oplock_request = 0; @@ -1524,7 +1524,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, free_sec_desc(&psd); - send_nt_replies(inbuf, outbuf, bufsize, 0xC0000000|NT_STATUS_BUFFER_TOO_SMALL, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); return -1; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fffddb4610..f9291b8705 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -520,7 +520,7 @@ BOOL pass_check_smb(char *user, char *domain, if(smb_pass->acct_ctrl & ACB_DISABLED) { DEBUG(1,("Account for user '%s' was disabled.\n", user)); return(False); - } + } /* Ensure the uid's match */ if (smb_pass->smb_userid != pass->pw_uid) @@ -529,7 +529,7 @@ BOOL pass_check_smb(char *user, char *domain, return(False); } - if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords()) + if (lm_pwd[0] == '\0' && (smb_pass->acct_ctrl & ACB_PWNOTREQ) && lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", smb_pass->smb_name)); return(True); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8aa7f7c9e4..00697c999a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -428,65 +428,54 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out char *smb_nt_passwd, int smb_nt_passlen) { struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ - if (lp_security() == SEC_USER) - { + if (lp_security() == SEC_USER) { smb_trust_acct = getsmbpwnam(user); - } - else - { + } else { DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (smb_trust_acct == NULL) - { + if (smb_trust_acct == NULL) { /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER)); - } - else - { - if ((smb_passlen != 24) || (smb_nt_passlen != 24)) - { + return(ERROR(0, NT_STATUS_NO_SUCH_USER)); + } else { + if ((smb_passlen != 24) || (smb_nt_passlen != 24)) { DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) - { + if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST)) - { + if (smb_trust_acct->acct_ctrl & ACB_DOMTRUST) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); + return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST)) - { + if (smb_trust_acct->acct_ctrl & ACB_SVRTRUST) { DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); + return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); } - if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST)) - { + if (smb_trust_acct->acct_ctrl & ACB_WSTRUST) { DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); + return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); } } /* don't know what to do: indicate logon failure */ SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } /**************************************************************************** @@ -637,7 +626,7 @@ static int bad_password_error(char *inbuf,char *outbuf) if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) && (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0,0xc0000000|NT_STATUS_LOGON_FAILURE)); + return(ERROR(0,NT_STATUS_LOGON_FAILURE)); } return(ERROR(ERRSRV,ERRbadpw)); -- cgit From 17dcd9a834fc915fb1ff2d8042a23000eeb7acfa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Aug 2000 02:11:55 +0000 Subject: Started to canonicalize our handling of uid -> sid code in order to get ready and fix se_access_check(). Added cannonical lookup_name(), lookup_sid(), uid_to_sid(), gid_to_sid() functions that look via winbind first the fall back on local lookup. All Samba should use these rather than trying to call winbindd code directly. Added NT_USER_TOKEN struct in user_struct, contains list of NT sids associated with this user. se_access_check() should use this (cached) value rather than attempting to do the same thing itself when given a uid/gid pair. More work needs to be done to preserve these things accross security context changes (especially with the tricky pipe problem) but I'm beginning to see how this will be done..... probably by registering a new vuid for an authenticated RPC pipe and not treating the pipe calls specially. More thoughts needed - but we're almost there... Jeremy. (This used to be commit 5e5cc6efe2e4687be59085f562caea1e2e05d0a8) --- source3/smbd/password.c | 113 +++++++++++++++++++---------------------------- source3/smbd/process.c | 3 +- source3/smbd/sec_ctx.c | 34 +++++++++++--- source3/smbd/service.c | 4 +- source3/smbd/uid.c | 23 +++++----- source3/smbd/unix_acls.c | 8 +--- 6 files changed, 91 insertions(+), 94 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f9291b8705..0372e7a0f9 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -112,6 +112,16 @@ user_struct *get_valid_user_struct(uint16 vuid) return &validated_users[vuid]; } +/**************************************************************************** + Delete the SID list for this user. +****************************************************************************/ + +static void delete_nt_token(NT_USER_TOKEN *token) +{ + safe_free( token->user_sids ); + ZERO_STRUCTP(token); +} + /**************************************************************************** invalidate a uid ****************************************************************************/ @@ -133,8 +143,7 @@ void invalidate_vuid(uint16 vuid) vuser->groups = NULL; - if (vuser->group_sids != NULL) - free (vuser->group_sids); + delete_nt_token(&vuser->nt_user_token); } @@ -162,61 +171,54 @@ char *validated_domain(uint16 vuid) /**************************************************************************** -Setup the groups a user belongs to. + Initialize the groups a user belongs to. ****************************************************************************/ -int setup_groups(char *user, char *domain, - 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)) - { +int initialize_groups(char *user, uid_t uid, gid_t gid) +{ + if (initgroups(user,gid) == -1) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); - if (getuid() == 0) - { - if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) - { + if (getuid() == 0) { + if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { DEBUG(0,("This is probably a problem with the account %s\n", user)); } } return -1; } + return 0; +} - ngroups = sys_getgroups(0,&grp); - if (ngroups <= 0) - { - ngroups = groups_max(); - } +/**************************************************************************** + Create the SID list for this user. +****************************************************************************/ - if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) - { - DEBUG(0,("setup_groups malloc fail !\n")); - return -1; - } +void setup_nt_token(NT_USER_TOKEN *token, uid_t uid, gid_t gid, int ngroups, gid_t *groups) +{ + DOM_SID *psids; + int i; - ngroups = sys_getgroups(ngroups,groups); + ZERO_STRUCTP(token); - (*p_ngroups) = ngroups; - (*p_groups) = groups; + if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) + return; - 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" ) ); + psids = token->user_sids; - return 0; -} + token->num_sids = ngroups + 2; + + uid_to_sid( &psids[0], uid); + gid_to_sid( &psids[1], gid); + for (i = 0; i < ngroups; i++) + gid_to_sid( &psids[i+2], groups[i]); +} /**************************************************************************** register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ + uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, char *domain,BOOL guest) { @@ -227,37 +229,15 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, if(lp_security() == SEC_SHARE) return UID_FIELD_INVALID; -#if 0 - /* - * After observing MS-Exchange services writing to a Samba share - * I belive this code is incorrect. Each service does its own - * sessionsetup_and_X for the same user, and as each service shuts - * down, it does a user_logoff_and_X. As we are consolidating multiple - * sessionsetup_and_X's onto the same vuid here, when the first service - * shuts down, it invalidates all the open files for the other services. - * Hence I am removing this code and forcing each sessionsetup_and_X - * to get a new vuid. - * Jeremy Allison. (jallison@whistle.com). - */ - - int i; - for(i = 0; i < num_validated_users; i++) { - vuser = &validated_users[i]; - if ( vuser->uid == uid ) - return (uint16)(i + VUID_OFFSET); /* User already validated */ - } -#endif - validated_users = (user_struct *)Realloc(validated_users, sizeof(user_struct)* (num_validated_users+1)); - if (!validated_users) - { + if (!validated_users) { DEBUG(0,("Failed to realloc users struct!\n")); num_validated_users = 0; return UID_FIELD_INVALID; - } + } vuser = &validated_users[num_validated_users]; num_validated_users++; @@ -274,22 +254,21 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(unix_name,domain,uid,gid, - &vuser->n_groups, - &vuser->groups); + initialize_groups(unix_name, uid, gid); + get_current_groups( &vuser->n_groups, &vuser->groups); - setup_user_sids(vuser); + /* Create an NT_USER_TOKEN struct for this user. */ + setup_nt_token(&vuser->nt_user_token, uid,gid, vuser->n_groups, vuser->groups); DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->user.full_name, ""); if (lp_unix_realname()) { - if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) - { + if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); fstrcpy(vuser->user.full_name, pwfile->pw_gecos); - } + } } memset(&vuser->dc, '\0', sizeof(vuser->dc)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2662db5896..37d8f8dd73 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -561,8 +561,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize } /* load service specific parameters */ - if (conn && - !become_service(conn,(flags & AS_USER)?True:False)) { + if (conn && !become_service(conn,(flags & AS_USER)?True:False)) { return(ERROR(ERRSRV,ERRaccess)); } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f7ea1e2d86..432cb223e2 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -125,17 +125,37 @@ static void gain_root(void) /* Get the list of current groups */ -static void get_current_groups(int *ngroups, gid_t **groups) +int get_current_groups(int *p_ngroups, gid_t **p_groups) { - *ngroups = getgroups(0, NULL); - *groups = (gid_t *)malloc(*ngroups * sizeof(gid_t)); + int i; + gid_t grp; + int ngroups = sys_getgroups(0,&grp); + gid_t *groups; + + (*p_ngroups) = 0; + (*p_groups) = NULL; + + if (ngroups <= 0) + return -1; + + if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) { + DEBUG(0,("setup_groups malloc fail !\n")); + return -1; + } + + if ((ngroups = sys_getgroups(ngroups,groups)) == -1) + return -1; + + (*p_ngroups) = ngroups; + (*p_groups) = groups; - if (!groups) { - DEBUG(0, ("Out of memory in get_current_groups\n")); - return; + DEBUG( 3, ( "get_current_groups: uid %u is in %u groups: ", (unsigned int)getuid() , ngroups ) ); + for (i = 0; i < ngroups; i++ ) { + DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) ); } + DEBUG( 3, ( "\n" ) ); - getgroups(*ngroups, *groups); + return ngroups; } /* Create a new security context on the stack. It is the same as the old diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2eab50c482..d4760ca92d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -511,8 +511,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!IS_IPC(conn)) { /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(conn->user,validated_domain(vuid),conn->uid,conn->gid, - &conn->ngroups,&conn->groups); + initialize_groups(conn->user, conn->uid, conn->gid); + get_current_groups(&conn->ngroups,&conn->groups); /* check number of connections */ if (!claim_connection(conn, diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 172e872020..4cb2c512b6 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -38,7 +38,8 @@ BOOL become_guest(void) if (!pass) pass = Get_Pwnam(lp_guestaccount(-1),True); - if (!pass) return(False); + if (!pass) + return(False); #ifdef AIX /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before @@ -60,19 +61,21 @@ BOOL become_guest(void) static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { - int i; - for (i=0;iuid_cache.entries;i++) - if (conn->uid_cache.list[i] == vuser->uid) return(True); + int i; + for (i=0;iuid_cache.entries;i++) + if (conn->uid_cache.list[i] == vuser->uid) + return(True); - if (!user_ok(vuser->user.unix_name,snum)) return(False); + if (!user_ok(vuser->user.unix_name,snum)) + return(False); - i = conn->uid_cache.entries % UID_CACHE_SIZE; - conn->uid_cache.list[i] = vuser->uid; + i = conn->uid_cache.entries % UID_CACHE_SIZE; + conn->uid_cache.list[i] = vuser->uid; - if (conn->uid_cache.entries < UID_CACHE_SIZE) - conn->uid_cache.entries++; + if (conn->uid_cache.entries < UID_CACHE_SIZE) + conn->uid_cache.entries++; - return(True); + return(True); } /**************************************************************************** diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 7a2dc6ab6e..46c57af5de 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -28,12 +28,8 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) { - extern DOM_SID global_sam_sid; - - sid_copy(powner_sid, &global_sam_sid); - sid_copy(pgroup_sid, &global_sam_sid); - sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); - sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); + uid_to_sid( powner_sid, psbuf->st_uid ); + gid_to_sid( pgroup_sid, psbuf->st_gid ); } /**************************************************************************** -- cgit From f87399915b009f88c41cb75a583c2972fe3daf30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Aug 2000 22:38:43 +0000 Subject: Added an NT_USER_TOKEN structure that is copied/passed around associated with the current user. This will allow se_access_check() to quickly do a SD check without having to translate uid/gid's to SIDs. Still needs work on pipe calls. Jeremy. (This used to be commit e28d01b744b3dbd33e0e54af4e7f426fa8c082b8) --- source3/smbd/conn.c | 5 +- source3/smbd/password.c | 27 +++++----- source3/smbd/sec_ctx.c | 98 +++++++++++++++++++++++++++++----- source3/smbd/service.c | 138 +++++++++++++++++++++++++----------------------- source3/smbd/uid.c | 8 +-- 5 files changed, 179 insertions(+), 97 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 0e74b62ee0..c1f42be098 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -162,8 +162,9 @@ BOOL conn_idle_all(time_t t, int deadtime) } /**************************************************************************** -free a conn structure + Free a conn structure. ****************************************************************************/ + void conn_free(connection_struct *conn) { /* Free vfs_connection_struct */ @@ -179,6 +180,7 @@ void conn_free(connection_struct *conn) if (conn->vfs_conn->groups != NULL) { free(conn->vfs_conn->groups); } + delete_nt_token(&conn->vfs_conn->nt_user_token); free(conn->vfs_conn); } @@ -190,6 +192,7 @@ void conn_free(connection_struct *conn) conn->ngroups = 0; } + delete_nt_token(&conn->nt_user_token); free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0372e7a0f9..9af7d3b1e9 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -112,16 +112,6 @@ user_struct *get_valid_user_struct(uint16 vuid) return &validated_users[vuid]; } -/**************************************************************************** - Delete the SID list for this user. -****************************************************************************/ - -static void delete_nt_token(NT_USER_TOKEN *token) -{ - safe_free( token->user_sids ); - ZERO_STRUCTP(token); -} - /**************************************************************************** invalidate a uid ****************************************************************************/ @@ -146,7 +136,6 @@ void invalidate_vuid(uint16 vuid) delete_nt_token(&vuser->nt_user_token); } - /**************************************************************************** return a validated username ****************************************************************************/ @@ -192,15 +181,21 @@ int initialize_groups(char *user, uid_t uid, gid_t gid) Create the SID list for this user. ****************************************************************************/ -void setup_nt_token(NT_USER_TOKEN *token, uid_t uid, gid_t gid, int ngroups, gid_t *groups) +NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) { + NT_USER_TOKEN *token; DOM_SID *psids; int i; + if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) + return NULL; + ZERO_STRUCTP(token); - if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) - return; + if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) { + free(token); + return NULL; + } psids = token->user_sids; @@ -211,6 +206,8 @@ void setup_nt_token(NT_USER_TOKEN *token, uid_t uid, gid_t gid, int ngroups, gid for (i = 0; i < ngroups; i++) gid_to_sid( &psids[i+2], groups[i]); + + return token; } /**************************************************************************** @@ -258,7 +255,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, get_current_groups( &vuser->n_groups, &vuser->groups); /* Create an NT_USER_TOKEN struct for this user. */ - setup_nt_token(&vuser->nt_user_token, uid,gid, vuser->n_groups, vuser->groups); + vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups); DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 432cb223e2..118c2f46b6 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -29,6 +29,7 @@ struct sec_ctx { uid_t gid; int ngroups; gid_t *groups; + NT_USER_TOKEN *token; }; /* A stack of security contexts. We include the current context as being @@ -37,7 +38,9 @@ struct sec_ctx { static struct sec_ctx sec_ctx_stack[MAX_SEC_CTX_DEPTH + 1]; static int sec_ctx_stack_ndx; -/* Become the specified uid */ +/**************************************************************************** + Become the specified uid. +****************************************************************************/ static BOOL become_uid(uid_t uid) { @@ -66,7 +69,9 @@ static BOOL become_uid(uid_t uid) return True; } -/* Become the specified gid */ +/**************************************************************************** + Become the specified gid. +****************************************************************************/ static BOOL become_gid(gid_t gid) { @@ -91,14 +96,18 @@ static BOOL become_gid(gid_t gid) return True; } -/* Become the specified uid and gid */ +/**************************************************************************** + Become the specified uid and gid. +****************************************************************************/ static BOOL become_id(uid_t uid, gid_t gid) { return become_gid(gid) && become_uid(uid); } -/* Drop back to root privileges in order to change to another user */ +/**************************************************************************** + Drop back to root privileges in order to change to another user. +****************************************************************************/ static void gain_root(void) { @@ -123,7 +132,9 @@ static void gain_root(void) } } -/* Get the list of current groups */ +/**************************************************************************** + Get the list of current groups. +****************************************************************************/ int get_current_groups(int *p_ngroups, gid_t **p_groups) { @@ -158,8 +169,51 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups) return ngroups; } -/* Create a new security context on the stack. It is the same as the old - one. User changes are done using the set_sec_ctx() function. */ +/**************************************************************************** + Delete a SID token. +****************************************************************************/ + +void delete_nt_token(NT_USER_TOKEN **pptoken) +{ + if (*pptoken) { + NT_USER_TOKEN *ptoken = *pptoken; + safe_free( ptoken->user_sids ); + ZERO_STRUCTP(ptoken); + } + safe_free(*pptoken); + *pptoken = NULL; +} + +/**************************************************************************** + Duplicate a SID token. +****************************************************************************/ + +NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) +{ + NT_USER_TOKEN *token; + + if (!ptoken) + return NULL; + + if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) + return NULL; + + ZERO_STRUCTP(token); + + if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) { + free(token); + return NULL; + } + + token->num_sids = ptoken->num_sids; + + return token; +} + +/**************************************************************************** + Create a new security context on the stack. It is the same as the old + one. User changes are done using the set_sec_ctx() function. +****************************************************************************/ BOOL push_sec_ctx(void) { @@ -181,11 +235,14 @@ BOOL push_sec_ctx(void) ctx_p->uid = geteuid(); ctx_p->gid = getegid(); + ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); + ctx_p->ngroups = sys_getgroups(0, NULL); if (ctx_p->ngroups != 0) { if (!(ctx_p->groups = malloc(ctx_p->ngroups * sizeof(gid_t)))) { DEBUG(0, ("Out of memory in push_sec_ctx()\n")); + delete_nt_token(&ctx_p->token); return False; } @@ -197,9 +254,11 @@ BOOL push_sec_ctx(void) return True; } -/* Set the current security context to a given user */ +/**************************************************************************** + Set the current security context to a given user. +****************************************************************************/ -void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) +void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token) { struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; @@ -216,8 +275,10 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) ctx_p->ngroups = ngroups; safe_free(ctx_p->groups); - + delete_nt_token(&ctx_p->token); + ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups); + ctx_p->token = dup_nt_token(token); become_id(uid, gid); @@ -230,18 +291,23 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) current_user.gid = gid; current_user.ngroups = ngroups; current_user.groups = groups; + current_user.nt_user_token = token; } -/* Become root context */ +/**************************************************************************** + Become root context. +****************************************************************************/ void set_root_sec_ctx(void) { /* May need to worry about supplementary groups at some stage */ - set_sec_ctx(0, 0, 0, NULL); + set_sec_ctx(0, 0, 0, NULL, NULL); } -/* Pop a security context from the stack */ +/**************************************************************************** + Pop a security context from the stack. +****************************************************************************/ BOOL pop_sec_ctx(void) { @@ -265,6 +331,8 @@ BOOL pop_sec_ctx(void) safe_free(ctx_p->groups); ctx_p->ngroups = 0; + delete_nt_token(&ctx_p->token); + /* Pop back previous user */ sec_ctx_stack_ndx--; @@ -285,6 +353,7 @@ BOOL pop_sec_ctx(void) current_user.gid = prev_ctx_p->gid; current_user.ngroups = prev_ctx_p->ngroups; current_user.groups = prev_ctx_p->groups; + current_user.nt_user_token = prev_ctx_p->token; DEBUG(3, ("popped off to sec ctx (%d, %d)\n", geteuid(), getegid())); @@ -315,6 +384,8 @@ void init_sec_ctx(void) get_current_groups(&ctx_p->ngroups, &ctx_p->groups); + ctx_p->token = NULL; /* Maps to guest user. */ + /* Initialise current_user global */ current_user.uid = ctx_p->uid; @@ -327,4 +398,5 @@ void init_sec_ctx(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; + current_user.nt_user_token = NULL; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d4760ca92d..8b63fe6662 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -360,65 +360,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->veto_oplock_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); + conn->nt_user_token = NULL; - conn->vfs_conn = (struct vfs_connection_struct *) - malloc(sizeof(struct vfs_connection_struct)); - - if (conn->vfs_conn == NULL) { - DEBUG(0, ("No memory to create vfs_connection_struct")); - return NULL; - } - - ZERO_STRUCTP(conn->vfs_conn); - - /* Copy across relevant data from connection struct */ - - conn->vfs_conn->printer = conn->printer; - conn->vfs_conn->ipc = conn->ipc; - conn->vfs_conn->read_only = conn->read_only; - conn->vfs_conn->admin_user = conn->admin_user; - - pstrcpy(conn->vfs_conn->dirpath, conn->dirpath); - pstrcpy(conn->vfs_conn->connectpath, conn->connectpath); - pstrcpy(conn->vfs_conn->origpath, conn->origpath); - - pstrcpy(conn->vfs_conn->service, service); - pstrcpy(conn->vfs_conn->user, conn->user); - - conn->vfs_conn->uid = conn->uid; - conn->vfs_conn->gid = conn->gid; - conn->vfs_conn->ngroups = conn->ngroups; - if (conn->vfs_conn->ngroups != 0) { - conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, - conn->ngroups * sizeof(gid_t)); - } else { - conn->vfs_conn->groups = NULL; - } - - /* Initialise VFS function pointers */ - - if (*lp_vfsobj(SNUM(conn))) { - -#ifdef HAVE_LIBDL - - /* Loadable object file */ - - if (!vfs_init_custom(conn)) { - return NULL; - } -#else - DEBUG(0, ("No libdl present - cannot use VFS objects\n")); - conn_free(conn); - return NULL; -#endif - - } else { - - /* Normal share - initialise with disk access functions */ - - vfs_init_default(conn); - } - /* * If force user is true, then store the * given userid and also the primary groupid @@ -529,7 +472,73 @@ connection_struct *make_connection(char *service,char *user,char *password, int claim_connection(conn,"", MAXSTATUS,False); } /* IS_IPC */ - + + conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups); + + /* + * Now initialize the vfs layer. + */ + + conn->vfs_conn = (struct vfs_connection_struct *) + malloc(sizeof(struct vfs_connection_struct)); + + if (conn->vfs_conn == NULL) { + DEBUG(0, ("No memory to create vfs_connection_struct")); + return NULL; + } + + ZERO_STRUCTP(conn->vfs_conn); + + /* Copy across relevant data from connection struct */ + + conn->vfs_conn->printer = conn->printer; + conn->vfs_conn->ipc = conn->ipc; + conn->vfs_conn->read_only = conn->read_only; + conn->vfs_conn->admin_user = conn->admin_user; + + pstrcpy(conn->vfs_conn->dirpath, conn->dirpath); + pstrcpy(conn->vfs_conn->connectpath, conn->connectpath); + pstrcpy(conn->vfs_conn->origpath, conn->origpath); + + pstrcpy(conn->vfs_conn->service, service); + pstrcpy(conn->vfs_conn->user, conn->user); + + conn->vfs_conn->uid = conn->uid; + conn->vfs_conn->gid = conn->gid; + conn->vfs_conn->ngroups = conn->ngroups; + if (conn->vfs_conn->ngroups != 0) { + conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, + conn->ngroups * sizeof(gid_t)); + } else { + conn->vfs_conn->groups = NULL; + } + + conn->vfs_conn->nt_user_token = dup_nt_token(conn->nt_user_token); + + /* Initialise VFS function pointers */ + + if (*lp_vfsobj(SNUM(conn))) { + +#ifdef HAVE_LIBDL + + /* Loadable object file */ + + if (!vfs_init_custom(conn)) { + return NULL; + } +#else + DEBUG(0, ("No libdl present - cannot use VFS objects\n")); + conn_free(conn); + return NULL; +#endif + + } else { + + /* Normal share - initialise with disk access functions */ + + vfs_init_default(conn); + } + /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { pstring cmd; @@ -630,13 +639,12 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* Invoke VFS make connection hook */ - if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn->vfs_conn, service, user) < 0) { - return NULL; - } - } + if (conn->vfs_ops.connect) { + if (conn->vfs_ops.connect(conn->vfs_conn, service, user) < 0) + return NULL; + } - return(conn); + return(conn); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 4cb2c512b6..f6687e9a5a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -47,7 +47,7 @@ BOOL become_guest(void) initgroups(pass->pw_name, (gid_t)pass->pw_gid); #endif - set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL); + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; @@ -164,10 +164,11 @@ BOOL become_user(connection_struct *conn, uint16 vuid) } } - set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups); + set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, current_user.nt_user_token); current_user.conn = conn; current_user.vuid = vuid; + current_user.nt_user_token = conn->nt_user_token; DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); @@ -206,8 +207,9 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) return False; } + /* JRATEST - this needs fixined w.r.t. NT user tokens... */ set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, - p->pipe_user.ngroups, p->pipe_user.groups); + p->pipe_user.ngroups, p->pipe_user.groups, NULL); return True; } -- cgit From 06e4f11acd3aedd6c8e4adf365932a01eca902b8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Aug 2000 00:59:09 +0000 Subject: Fixed up the user/group contexts when using authenticated pipes. Added a become_root()/unbecome_root() (push/pop security context) around the initgroups() call to ensure it would succeed. Hmmm - I wonder if this call being done as non-root might explain any "group access" bugs we've had in the past.... Jeremy. (This used to be commit 06a65972e872f37d88b84f22ea714feebd38f6c0) --- source3/smbd/password.c | 9 ++++++--- source3/smbd/uid.c | 3 +-- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9af7d3b1e9..4aa753c022 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -163,8 +163,9 @@ char *validated_domain(uint16 vuid) Initialize the groups a user belongs to. ****************************************************************************/ -int initialize_groups(char *user, uid_t uid, gid_t gid) +BOOL initialize_groups(char *user, uid_t uid, gid_t gid) { + become_root(); if (initgroups(user,gid) == -1) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); if (getuid() == 0) { @@ -172,9 +173,11 @@ int initialize_groups(char *user, uid_t uid, gid_t gid) DEBUG(0,("This is probably a problem with the account %s\n", user)); } } - return -1; + unbecome_root(); + return False; } - return 0; + become_root(); + return True; } /**************************************************************************** diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index f6687e9a5a..fafcd71b1a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -207,9 +207,8 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) return False; } - /* JRATEST - this needs fixined w.r.t. NT user tokens... */ set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, - p->pipe_user.ngroups, p->pipe_user.groups, NULL); + p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token); return True; } -- cgit From 04de6d02584aa431cbd99e057407ffeb3bdc413d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Aug 2000 23:49:26 +0000 Subject: Found the sec_ctx_stack overflow - a become_root() should have been an unbecome_root() - typo. Jeremy. (This used to be commit ebb160663ed55e44e44f1c3d17eb077a32c2ffb9) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 4aa753c022..2b43f0baf4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -176,7 +176,7 @@ BOOL initialize_groups(char *user, uid_t uid, gid_t gid) unbecome_root(); return False; } - become_root(); + unbecome_root(); return True; } -- cgit From e3048cfc0b324ec5ab825efe87eaa97cc9504c09 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Aug 2000 18:40:48 +0000 Subject: Fixed memory leak with NT tokens. Added debug messages to se_access_check(). Added FULL_ACCESS acl to default acl on printers. Jeremy. (This used to be commit 7507f6f408cf8b0f8d7e2b3da54ce5fb5ef5343b) --- source3/smbd/sec_ctx.c | 17 ++++++++++++----- source3/smbd/uid.c | 22 ++++++++++++++++++++-- 2 files changed, 32 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 118c2f46b6..f185ffcdaa 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -221,15 +221,17 @@ BOOL push_sec_ctx(void) /* Check we don't overflow our stack */ - if (sec_ctx_stack_ndx == (MAX_SEC_CTX_DEPTH)) { + if (sec_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) { DEBUG(0, ("Security context stack overflow!\n")); - return False; + smb_panic("Security context stack overflow!\n"); } /* Store previous user context */ sec_ctx_stack_ndx++; + DEBUG(3, ("push_sec_ctx() : sec_ctx_stack_ndx = %d\n", sec_ctx_stack_ndx )); + ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; ctx_p->uid = geteuid(); @@ -264,7 +266,7 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN /* Set the security context */ - DEBUG(3, ("setting sec ctx (%d, %d)\n", uid, gid)); + DEBUG(3, ("setting sec ctx (%d, %d) - sec_ctx_stack_ndx = %d\n", uid, gid, sec_ctx_stack_ndx)); gain_root(); @@ -275,6 +277,11 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN ctx_p->ngroups = ngroups; safe_free(ctx_p->groups); +#if 1 /* JRATEST */ + if (token && (token == ctx_p->token)) + smb_panic("DUPLICATE_TOKEN"); +#endif + delete_nt_token(&ctx_p->token); ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups); @@ -318,7 +325,7 @@ BOOL pop_sec_ctx(void) if (sec_ctx_stack_ndx == 0) { DEBUG(0, ("Security context stack underflow!\n")); - return False; + smb_panic("Security context stack underflow!\n"); } ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; @@ -355,7 +362,7 @@ BOOL pop_sec_ctx(void) current_user.groups = prev_ctx_p->groups; current_user.nt_user_token = prev_ctx_p->token; - DEBUG(3, ("popped off to sec ctx (%d, %d)\n", geteuid(), getegid())); + DEBUG(3, ("pop_sec_ctx (%d, %d) - sec_ctx_stack_ndx = %d\n", geteuid(), getegid(), sec_ctx_stack_ndx)); return True; } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index fafcd71b1a..b28f056a30 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -89,6 +89,8 @@ BOOL become_user(connection_struct *conn, uint16 vuid) gid_t gid; uid_t uid; char group_c; + BOOL must_free_token = False; + NT_USER_TOKEN *token = NULL; if (!conn) { DEBUG(2,("Connection not open\n")); @@ -125,6 +127,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) gid = conn->gid; current_user.groups = conn->groups; current_user.ngroups = conn->ngroups; + token = conn->nt_user_token; } else { if (!vuser) { DEBUG(2,("Invalid vuid used %d\n",vuid)); @@ -134,6 +137,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) gid = vuser->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; + token = vuser->nt_user_token; } /* @@ -162,13 +166,27 @@ BOOL become_user(connection_struct *conn, uint16 vuid) } else { gid = conn->gid; } + + /* + * We've changed the group list in the token - we must + * re-create it. + */ + + token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups); + must_free_token = True; } - set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, current_user.nt_user_token); + set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token); + + /* + * Free the new token (as set_sec_ctx copies it). + */ + + if (must_free_token) + delete_nt_token(&token); current_user.conn = conn; current_user.vuid = vuid; - current_user.nt_user_token = conn->nt_user_token; DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); -- cgit From 150d8c6a87a2af724b22ebcc1fd58248ce99a2f3 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 17 Aug 2000 20:05:05 +0000 Subject: Fix for Win9x driver downloads when information is stored in the TDB. See the message I posted about this on samba-technical * If the admin does not desire the new NT print driver support, nothing needs to be done. All existing parameters work the same. * If the admin wants to take advantage of NT printer driver support but does not want to migrate the 9x drivers to the new setup, the leave the existing printers.def file. When smbd attempts to locate a 9x driver for the printer in the TDB and fails it will drop down to using the printers.def (and all associated parameters). The make_printerdef tool will also remain for backwards compatibility but will be moved to the "this tool is the old way of doing it" pile. * If the admin installs a 9x driver for a printer on a Samba host (in the printing TDB), this information will take precedence and the three old printing parameters will be ignored (including print driver location). * If an admin wants to migrate the printers.def file into the new setup, I can write a script to do this using rpcclient. The main problem is the driver namespace (we need the NT driver name first in order to be consistent). jerry (This used to be commit ac049f8bf348810dc068382fdbc6635a2015d36a) --- source3/smbd/lanman.c | 236 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 153 insertions(+), 83 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 047212bf9f..712016285e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -37,6 +37,7 @@ extern int DEBUGLEVEL; extern fstring local_machine; +extern fstring global_myname; extern fstring global_myworkgroup; #define NERR_Success 0 @@ -488,7 +489,10 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, } } - +/******************************************************************** + Respond to the DosPrintQInfo command with a level of 52 + This is used to get printer driver information for Win9x clients + ********************************************************************/ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, struct pack_desc* desc, int count, print_queue_struct* queue, @@ -500,106 +504,155 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, char *p; char **lines = NULL; pstring gen_line; + NT_PRINTER_INFO_LEVEL *info = NULL; + BOOL in_tdb = False; + fstring location; /* * Check in the tdb *first* before checking the legacy * files. This allows an NT upload to take precedence over * the existing fileset. JRA. + * + * we need to lookup the driver name prior to making the call + * to get_a_printer_driver_9x_compatible() and not rely on the + * 'print driver' parameter --jerry */ - if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) == True) { - p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); - } else { + get_a_printer (&info, 2, lp_servicename(snum)); + if ((info != NULL) && + ((ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername)) == True)) + { + in_tdb = True; + p = gen_line; + DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", + info->info_2->drivername, gen_line)); + } + else + { /* didn't find driver in tdb */ - DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", - snum, lp_printerdriver(snum), lp_driverfile(snum))); + DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", + snum, lp_printerdriver(snum), lp_driverfile(snum))); - lines = file_lines_load(lp_driverfile(snum),NULL); - if (!lines) { - DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - desc->errcode=NERR_notsupported; - return; - } else { + lines = file_lines_load(lp_driverfile(snum),NULL); + if (!lines) + { + DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum), + strerror(errno))); + desc->errcode=NERR_notsupported; + return; + } + else + { /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok = True; + for (i=0;lines[i] && !ok;i++) + { + p = lines[i]; + if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + ok = True; + } } } - } if (ok) { - /* driver file name */ - if (!next_token(&p,driver,":",sizeof(driver))) - goto err; + /* driver file name */ + if (!next_token(&p,driver,":",sizeof(driver))) + goto err; - /* data file name */ - if (!next_token(&p,datafile,":",sizeof(datafile))) - goto err; + /* data file name */ + if (!next_token(&p,datafile,":",sizeof(datafile))) + goto err; - /* - * for the next tokens - which may be empty - I have - * to check for empty tokens first because the - * next_token function will skip all empty token - * fields */ - - /* help file */ - if (*p == ':') { - *helpfile = '\0'; - p++; - } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) - goto err; + /* + * for the next tokens - which may be empty - I have + * to check for empty tokens first because the + * next_token function will skip all empty token + * fields */ + + /* help file */ + if (*p == ':') + { + *helpfile = '\0'; + p++; + } + else if (!next_token(&p,helpfile,":",sizeof(helpfile))) + goto err; - /* language monitor */ - if (*p == ':') { - *langmon = '\0'; - p++; - } else if (!next_token(&p,langmon,":",sizeof(langmon))) - goto err; + /* language monitor */ + if (*p == ':') + { + *langmon = '\0'; + p++; + } + else if (!next_token(&p,langmon,":",sizeof(langmon))) + goto err; - /* default data type */ - if (!next_token(&p,datatype,":",sizeof(datatype))) - goto err; + /* default data type */ + if (!next_token(&p,datatype,":",sizeof(datatype))) + goto err; - PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ - PACKS(desc,"z",driver); /* Driverfile Name */ - PACKS(desc,"z",datafile); /* Datafile name */ - PACKS(desc,"z",langmon); /* language monitor */ - PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ - PACKS(desc,"z",datatype); /* default data type */ - PACKS(desc,"z",helpfile); /* helpfile name */ - PACKS(desc,"z",driver); /* driver name */ - DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum))); - DEBUG(3,("Driver:%s:\n",driver)); - DEBUG(3,("Data File:%s:\n",datafile)); - DEBUG(3,("Language Monitor:%s:\n",langmon)); - DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum))); - DEBUG(3,("Data Type:%s:\n",datatype)); - DEBUG(3,("Help File:%s:\n",helpfile)); - PACKI(desc,"N",count); /* number of files to copy */ - - for (i=0;iinfo_2->drivername); /* long printer name */ + } + else + { + PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ + } + PACKS(desc,"z",driver); /* Driverfile Name */ + PACKS(desc,"z",datafile); /* Datafile name */ + PACKS(desc,"z",langmon); /* language monitor */ + if (in_tdb) + { + fstrcpy(location, "\\\\"); + fstrcat(location, global_myname); + fstrcat(location, "\\print$\\WIN40\\0"); + PACKS(desc,"z",location); /* share to retrieve files */ + } + else + { + PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ + } + PACKS(desc,"z",datatype); /* default data type */ + PACKS(desc,"z",helpfile); /* helpfile name */ + PACKS(desc,"z",driver); /* driver name */ + + if (in_tdb) + DEBUG(3,("lp_printerdriver:%s:\n",info->info_2->drivername)); + else + DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum))); + + DEBUG(3,("Driver:%s:\n",driver)); + DEBUG(3,("Data File:%s:\n",datafile)); + DEBUG(3,("Language Monitor:%s:\n",langmon)); + if (in_tdb) + DEBUG(3,("lp_driverlocation:%s:\n",location)); + else + DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum))); + DEBUG(3,("Data Type:%s:\n",datatype)); + DEBUG(3,("Help File:%s:\n",helpfile)); + PACKI(desc,"N",count); /* number of files to copy */ + + for (i=0;i gave %d entries\n", - SERVICE(snum),count)); + DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", + SERVICE(snum),count)); - desc->errcode=NERR_Success; + desc->errcode=NERR_Success; file_lines_free(lines); - return; + return; } err: @@ -694,28 +747,42 @@ static int get_printerdrivernumber(int snum) char *p; char **lines = NULL; pstring gen_line; - + NT_PRINTER_INFO_LEVEL *info = NULL; + /* * Check in the tdb *first* before checking the legacy * files. This allows an NT upload to take precedence over * the existing fileset. JRA. + * + * we need to lookup the driver name prior to making the call + * to get_a_printer_driver_9x_compatible() and not rely on the + * 'print driver' parameter --jerry */ - if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum))) == True ) { + get_a_printer (&info, 2, lp_servicename(snum)); + if ((info != NULL) && + (ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername) == True)) + { p = gen_line; DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); - } else { + } + else + { /* didn't find driver in tdb */ DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", snum, lp_printerdriver(snum), lp_driverfile(snum))); lines = file_lines_load(lp_driverfile(snum), NULL); - if (!lines) { + if (!lines) + { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - } else { + } + else + { /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) { + for (i=0;lines[i] && !ok;i++) + { p = lines[i]; if (next_token(&p,tok,":",sizeof(tok)) && (strlen(lp_printerdriver(snum)) == strlen(tok)) && @@ -725,7 +792,8 @@ static int get_printerdrivernumber(int snum) } } - if( ok ) { + if( ok ) + { /* skip 5 fields */ i = 5; while (*p && i) { @@ -2203,7 +2271,8 @@ Name Value Description AF_OP_PRINT 0 Print operator -Leach, Naik [Page 28] +Leach, Naik [Page 28] + INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 @@ -2265,7 +2334,8 @@ AF_OP_ACCOUNTS 3 Accounts operator -Leach, Naik [Page 29] +Leach, Naik [Page 29] + INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 -- cgit From 42e8f4102d1ddcfcae600b27641bf80989a0b175 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Aug 2000 19:48:31 +0000 Subject: Modified to use sid_to_uid and sid_to_gid. Now ready for POSIX ACL code.... Jeremy. (This used to be commit 28586c1dee18d99e0e0999ab1a945a33ce33c371) --- source3/smbd/unix_acls.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 46c57af5de..7ab448e6a3 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -151,6 +151,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p SEC_ACL *dacl = psd->dacl; BOOL all_aces_are_inherit_only = (is_directory ? True : False); int i; + enum SID_NAME_USE sid_type; *pmode = 0; *puser = (uid_t)-1; @@ -184,20 +185,20 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p * This may be a group chown only set. */ - if(!validate_unix_sid( &owner_sid, &owner_rid, psd->owner_sid)) - DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); - else if(security_info_sent & OWNER_SECURITY_INFORMATION) - *puser = pdb_user_rid_to_uid(owner_rid); + if (security_info_sent & OWNER_SECURITY_INFORMATION) { + if (!sid_to_uid( &owner_sid, puser, &sid_type)) + DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); + } /* * Don't immediately fail if the group sid cannot be validated. * This may be an owner chown only set. */ - if(!validate_unix_sid( &grp_sid, &grp_rid, psd->grp_sid)) - DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); - else if(security_info_sent & GROUP_SECURITY_INFORMATION) - *pgrp = pdb_user_rid_to_gid(grp_rid); + if (security_info_sent & GROUP_SECURITY_INFORMATION) { + if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) + DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); + } /* * If no DACL then this is a chown only security descriptor. -- cgit From ace6739f5e8b9cc3139c5ea1d42ab481856dd4c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Aug 2000 20:44:33 +0000 Subject: vfs write data fix. Fix for name matching in addtosmbpass Jeremy. (This used to be commit 85738b7ee1ea6d88999d6aedc51a2daf545cb8b8) --- source3/smbd/fileio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 45ad959a3c..7fbf6e2a37 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -141,7 +141,7 @@ static unsigned int allocated_write_caches; static unsigned int num_write_caches; /**************************************************************************** - *Really* write to a file + *Really* write to a file. ****************************************************************************/ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_t n) @@ -149,7 +149,7 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ if ((pos != -1) && (seek_file(fsp,pos) == -1)) return -1; - return write_data(fsp->fd,data,n); + return vfs_write_data(fsp,data,n); } /**************************************************************************** -- cgit From d12f3fea7529c03b6a3650e7aa8b4b47a445d548 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 28 Aug 2000 06:46:53 +0000 Subject: Merge from appliance branch. (This used to be commit 567b0095b1b8393b3b1e32533aa2860ab3dbfa47) --- source3/smbd/password.c | 10 ++++++++++ source3/smbd/service.c | 1 + 2 files changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2b43f0baf4..3545f41dff 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -188,6 +188,7 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) { NT_USER_TOKEN *token; DOM_SID *psids; + int i, psid_ndx = 0; int i; if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) @@ -202,11 +203,19 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) psids = token->user_sids; + token->num_sids = 2; token->num_sids = ngroups + 2; uid_to_sid( &psids[0], uid); gid_to_sid( &psids[1], gid); + for (i = 0; i < ngroups; i++) { + if (groups[i] != gid) { + gid_to_sid( &psids[psid_ndx+2], groups[i]); + psid_ndx++; + token->num_sids++; + } + } for (i = 0; i < ngroups; i++) gid_to_sid( &psids[i+2], groups[i]); @@ -254,6 +263,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, /* Find all the groups this uid is in and store them. Used by become_user() */ + initialise_groups(unix_name, uid, gid); initialize_groups(unix_name, uid, gid); get_current_groups( &vuser->n_groups, &vuser->groups); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8b63fe6662..500ba6e626 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -454,6 +454,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!IS_IPC(conn)) { /* Find all the groups this uid is in and store them. Used by become_user() */ + initialise_groups(conn->user, conn->uid, conn->gid); initialize_groups(conn->user, conn->uid, conn->gid); get_current_groups(&conn->ngroups,&conn->groups); -- cgit From 8b889a84a2b318d377e219345df2ecf9a160d2a2 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 28 Aug 2000 06:50:45 +0000 Subject: Oops - missed a file. (This used to be commit 5aed84b74981a4f4fcc4d466ef03178eff22ba85) --- source3/smbd/sec_ctx.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f185ffcdaa..0cab2a7e9c 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -210,6 +210,48 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) return token; } +/**************************************************************************** + Initialize the groups a user belongs to. +****************************************************************************/ + +BOOL initialise_groups(char *user, uid_t uid, gid_t gid) +{ + struct sec_ctx *prev_ctx_p; + BOOL result = True; + + become_root(); + + /* Call initgroups() to get user groups */ + + if (initgroups(user,gid) == -1) { + DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); + if (getuid() == 0) { + if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { + DEBUG(0,("This is probably a problem with the account %s\n", user)); + } + } + result = False; + goto done; + } + + /* Store groups in previous user's security context. This will + always work as the become_root() call increments the stack + pointer. */ + + prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx - 1]; + + safe_free(prev_ctx_p->groups); + prev_ctx_p->groups = NULL; + prev_ctx_p->ngroups = 0; + + get_current_groups(&prev_ctx_p->ngroups, &prev_ctx_p->groups); + + done: + unbecome_root(); + + return result; +} + /**************************************************************************** Create a new security context on the stack. It is the same as the old one. User changes are done using the set_sec_ctx() function. -- cgit From 66cc9787ef6b8d0f2c3161a09dda6e4ffa029739 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 28 Aug 2000 07:25:18 +0000 Subject: Merge bug - still getting used to dirdiff. (This used to be commit cb717b4a2bb55eb2ff008e59203ebfeac6c5ab9f) --- source3/smbd/password.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3545f41dff..baa2823732 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -189,7 +189,6 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) NT_USER_TOKEN *token; DOM_SID *psids; int i, psid_ndx = 0; - int i; if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) return NULL; -- cgit From 7d93eb3483029c9edd2c7b6361d514a7a3ec4e94 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Aug 2000 20:45:00 +0000 Subject: smbd/password.c: Fixed typo in Tim's new code that caused insure overrun error. smbd/reply.c: Fixed lowercasing UNIX character set problem. Jeremy. (This used to be commit 2b6e3ed7a6447d40d9dd7e9b5c286b1aabe4730d) --- source3/smbd/password.c | 1 - source3/smbd/reply.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index baa2823732..9e59815e52 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -203,7 +203,6 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) psids = token->user_sids; token->num_sids = 2; - token->num_sids = ngroups + 2; uid_to_sid( &psids[0], uid); gid_to_sid( &psids[1], gid); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 00697c999a..00e6f44dd0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -671,6 +671,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * Incoming user is in DOS codepage format. Convert * to UNIX. */ + strlower(user); dos_to_unix(user,True); if (!doencrypt && (lp_security() != SEC_SERVER)) { @@ -786,6 +787,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * Incoming user is in DOS codepage format. Convert * to UNIX. */ + strlower(user); dos_to_unix(user,True); domain = p; @@ -828,8 +830,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int guest = True; } - strlower(user); - pstrcpy(sesssetup_user,user); reload_services(True); -- cgit From 9e3098587b2ec49ff788a992c1d832fdfee26af6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Aug 2000 00:29:15 +0000 Subject: This doesn't compile but is a placeholder for moving the UNIX acl code over to POSIX acls. Jeremy. (This used to be commit a2829febe12513d26534c4977c2f41f480f4fa0e) --- source3/smbd/posix_acls.c | 618 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 618 insertions(+) create mode 100644 source3/smbd/posix_acls.c (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c new file mode 100644 index 0000000000..b463ec2479 --- /dev/null +++ b/source3/smbd/posix_acls.c @@ -0,0 +1,618 @@ +#ifdef HAVE_POSIX_ACLS +#define OLD_NTDOMAIN 1 +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB NT Security Descriptor / Unix permission conversion. + Copyright (C) Jeremy Allison 1994-2000 + + 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" + +/**************************************************************************** + Function to create owner and group SIDs from a SMB_STRUCT_STAT. +****************************************************************************/ + +static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) +{ + uid_to_sid( powner_sid, psbuf->st_uid ); + gid_to_sid( pgroup_sid, psbuf->st_gid ); +} + +/**************************************************************************** + Map unix perms to NT. +****************************************************************************/ + +static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w_mask, int x_mask, BOOL is_directory) +{ + SEC_ACCESS sa; + uint32 nt_mask = 0; + + *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; + + if((perm & (r_mask|w_mask|x_mask)) == (r_mask|w_mask|x_mask)) { + nt_mask = UNIX_ACCESS_RWX; + } else if((perm & (r_mask|w_mask|x_mask)) == 0) { + nt_mask = UNIX_ACCESS_NONE; + } else { + nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; + if(is_directory) + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + else + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; + } + init_sec_access(&sa,nt_mask); + return sa; +} + +/**************************************************************************** + Validate a SID. +****************************************************************************/ + +static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) +{ + extern DOM_SID global_sam_sid; + DOM_SID sid; + + if(!sd_sid) { + DEBUG(5,("validate_unix_sid: sid missing.\n")); + return False; + } + + sid_copy(psid, sd_sid); + sid_copy(&sid, sd_sid); + + if(!sid_split_rid(&sid, prid)) { + DEBUG(5,("validate_unix_sid: cannot get RID from sid.\n")); + return False; + } + + if(!sid_equal( &sid, &global_sam_sid)) { + DEBUG(5,("validate_unix_sid: sid is not ours.\n")); + return False; + } + + return True; +} + +/**************************************************************************** + Map NT perms to UNIX. +****************************************************************************/ + +#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) +#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) +#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) + +static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) +{ + mode_t mode = 0; + + switch(type) { + case S_IRUSR: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRUSR|S_IWUSR|S_IXUSR; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; + } + break; + case S_IRGRP: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRGRP|S_IWGRP|S_IXGRP; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; + } + break; + case S_IROTH: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IROTH|S_IWOTH|S_IXOTH; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; + } + break; + } + + return mode; +} + +/**************************************************************************** + Unpack a SEC_DESC into a owner, group and set of UNIX permissions. +****************************************************************************/ + +static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode, + uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) +{ + extern DOM_SID global_sid_World; + DOM_SID owner_sid; + DOM_SID grp_sid; + DOM_SID file_owner_sid; + DOM_SID file_grp_sid; + uint32 owner_rid; + uint32 grp_rid; + SEC_ACL *dacl = psd->dacl; + BOOL all_aces_are_inherit_only = (is_directory ? True : False); + int i; + enum SID_NAME_USE sid_type; + + *pmode = 0; + *puser = (uid_t)-1; + *pgrp = (gid_t)-1; + + if(security_info_sent == 0) { + DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); + return False; + } + + /* + * Windows 2000 sends the owner and group SIDs as the logged in + * user, not the connected user. But it still sends the file + * owner SIDs on an ACL set. So we need to check for the file + * owner and group SIDs as well as the owner SIDs. JRA. + */ + + create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); + + /* + * Validate the owner and group SID's. + */ + + memset(&owner_sid, '\0', sizeof(owner_sid)); + memset(&grp_sid, '\0', sizeof(grp_sid)); + + DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n")); + + /* + * Don't immediately fail if the owner sid cannot be validated. + * This may be a group chown only set. + */ + + if (security_info_sent & OWNER_SECURITY_INFORMATION) { + if (!sid_to_uid( &owner_sid, puser, &sid_type)) + DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); + } + + /* + * Don't immediately fail if the group sid cannot be validated. + * This may be an owner chown only set. + */ + + if (security_info_sent & GROUP_SECURITY_INFORMATION) { + if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) + DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); + } + + /* + * If no DACL then this is a chown only security descriptor. + */ + + if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) { + *pmode = 0; + return True; + } + + /* + * Now go through the DACL and ensure that + * any owner/group sids match. + */ + + for(i = 0; i < dacl->num_aces; i++) { + DOM_SID ace_sid; + SEC_ACE *psa = &dacl->ace[i]; + + if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && + (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { + DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); + return False; + } + + /* + * Ignore or remove bits we don't care about on a directory ACE. + */ + + if(is_directory) { + if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n")); + continue; + } + + /* + * At least one of the ACE entries wasn't inherit only. + * Flag this so we know the returned mode is valid. + */ + + all_aces_are_inherit_only = False; + } + + /* + * Windows 2000 sets these flags even on *file* ACE's. This is wrong + * but we can ignore them for now. Revisit this when we go to POSIX + * ACLs on directories. + */ + + psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); + + if(psa->flags != 0) { + DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", + (unsigned int)psa->flags)); + return False; + } + + /* + * The security mask may be UNIX_ACCESS_NONE which should map into + * no permissions (we overload the WRITE_OWNER bit for this) or it + * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this + * to be so. Any other bits override the UNIX_ACCESS_NONE bit. + */ + + psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| + GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); + + if(psa->info.mask != UNIX_ACCESS_NONE) + psa->info.mask &= ~UNIX_ACCESS_NONE; + + sid_copy(&ace_sid, &psa->sid); + + if(sid_equal(&ace_sid, &file_owner_sid)) { + /* + * Map the desired permissions into owner perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IRUSR); + else + *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); + + } else if( sid_equal(&ace_sid, &file_grp_sid)) { + /* + * Map the desired permissions into group perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IRGRP); + else + *pmode &= ~(map_nt_perms( psa->info, S_IRGRP)); + + } else if( sid_equal(&ace_sid, &global_sid_World)) { + /* + * Map the desired permissions into other perms. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms( psa->info, S_IROTH); + else + *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); + + } else { + DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n")); + return False; + } + } + + if (is_directory && all_aces_are_inherit_only) { + /* + * Windows 2000 is doing one of these weird 'inherit acl' + * traverses to conserve NTFS ACL resources. Just pretend + * there was no DACL sent. JRA. + */ + + DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); + free_sec_acl(&psd->dacl); + } + + return True; +} + +/**************************************************************************** + Go through the ACL entries one by one, count them and extract the permset + of the mask entry as we scan the acl. +****************************************************************************/ + +size_t get_num_posix_entries(acl_t posix_acl, acl_permset_t *posix_mask) +{ + size_t num_entries; + acl_entry_t entry; + int entry_id = ACL_FIRST_ENTRY; + + *posix_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); + + for( num_entries = 0; acl_get_entry(posix_acl, entry_id, &entry) != -1; num_entries++) { + acl_tag_t tagtype; + acl_permset_t permset; + + entry_id = ACL_NEXT_ENTRY; + if (acl_get_tag_type(entry, &tagtype) == -1) + continue; + + if (tagtype == ACL_MASK) + if (acl_get_permset(entry, &permset) == 0) + *posix_mask = permset; + } + + return num_entries; +} + +/**************************************************************************** + Reply to query a security descriptor from an fsp. If it succeeds it allocates + the space for the return elements and returns the size needed to return the + security descriptor. This should be the only external function needed for + the UNIX style get ACL. +****************************************************************************/ + +size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) +{ + extern DOM_SID global_sid_World; + SMB_STRUCT_STAT sbuf; + SEC_ACE ace_list[6]; + DOM_SID owner_sid; + DOM_SID group_sid; + size_t sd_size; + SEC_ACL *psa = NULL; + SEC_ACCESS owner_access; + int owner_acl_type; + SEC_ACCESS group_access; + int grp_acl_type; + SEC_ACCESS other_access; + int other_acl_type; + int num_acls = 0; + acl_t posix_acl; + + *ppdesc = NULL; + + if(fsp->is_directory || fsp->fd == -1) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + return 0; + } + /* + * Get the ACL from the path. + */ + + if ((posix_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_ACCESS)) == NULL) + return 0; + + } else { + if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + return 0; + } + /* + * Get the ACL from the fd. + */ + if ((posix_acl = acl_get_fd( fsp->fd)) == NULL) + return 0; + } + + /* + * Get the owner, group and world SIDs. + */ + + create_file_sids(&sbuf, &owner_sid, &group_sid); + + /* + * Count the number of entries in the ACL and return + * the mask. + */ + + num_posix_entries = get_num_posix_entries(posix_acl, &posix_mask); + + /* + * Create the generic 3 element UNIX acl. + */ + + owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, + S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); + group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, + S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); + other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, + S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); + + if(owner_access.mask) + init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, owner_access, 0); + + if(group_access.mask) + init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, group_access, 0); + + if(other_access.mask) + init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, other_access, 0); + + if(fsp->is_directory) { + /* + * For directory ACLs we also add in the inherited permissions + * ACE entries. These are the permissions a file would get when + * being created in the directory. + */ + mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); + + owner_access = map_unix_perms(&owner_acl_type, mode, + S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); + group_access = map_unix_perms(&grp_acl_type, mode, + S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); + other_access = map_unix_perms(&other_acl_type, mode, + S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); + + if(owner_access.mask) + init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, + owner_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + + if(group_access.mask) + init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, + group_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + + if(other_access.mask) + init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, + other_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + } + + if(num_acls) { + if((psa = make_sec_acl( ACL_REVISION, num_acls, ace_list)) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); + return 0; + } + } + + *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sd_size); + + if(!*ppdesc) { + DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); + sd_size = 0; + } + + free_sec_acl(&psa); + + return sd_size; +} + +/**************************************************************************** + Reply to set a security descriptor on an fsp. security_info_sent is the + description of the following NT ACL. + This should be the only external function needed for the UNIX style set ACL. +****************************************************************************/ + +BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) +{ + connection_struct *conn = fsp->conn; + uid_t user = (uid_t)-1; + gid_t grp = (gid_t)-1; + mode_t perms = 0; + SMB_STRUCT_STAT sbuf; + BOOL got_dacl = False; + + /* + * Get the current state of the file. + */ + + if(fsp->is_directory) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) + return False; + } else { + + int ret; + + if(fsp->fd == -1) + ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + else + ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); + + if(ret != 0) + return False; + } + + /* + * Unpack the user/group/world id's and permissions. + */ + + if (!unpack_nt_permissions( &sbuf, &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) + return False; + + if (psd->dacl != NULL) + got_dacl = True; + + /* + * Do we need to chown ? + */ + + if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { + + DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); + + if(dos_chown( fsp->fsp_name, user, grp) == -1) { + DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); + return False; + } + + /* + * Recheck the current state of the file, which may have changed. + * (suid/sgid bits, for instance) + */ + + if(fsp->is_directory) { + if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + return False; + } + } else { + + int ret; + + if(fsp->fd == -1) + ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + else + ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); + + if(ret != 0) + return False; + } + } + + /* + * Only change security if we got a DACL. + */ + + if((security_info_sent & DACL_SECURITY_INFORMATION) && got_dacl) { + + /* + * Check to see if we need to change anything. + * Enforce limits on modified bits *only*. Don't enforce masks + * on bits not changed by the user. + */ + + if(fsp->is_directory) { + + perms &= (lp_dir_security_mask(SNUM(conn)) | sbuf.st_mode); + perms |= (lp_force_dir_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + + } else { + + perms &= (lp_security_mask(SNUM(conn)) | sbuf.st_mode); + perms |= (lp_force_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + + } + + /* + * Preserve special bits. + */ + + perms |= (sbuf.st_mode & ~0777); + + /* + * Do we need to chmod ? + */ + + if(sbuf.st_mode != perms) { + + DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", + fsp->fsp_name, (unsigned int)perms )); + + if(conn->vfs_ops.chmod(dos_to_unix(fsp->fsp_name, False), perms) == -1) { + DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)perms, strerror(errno) )); + return False; + } + } + } + + return True; +} +#undef OLD_NTDOMAIN +#else /* HAVE_POSIX_ACLS */ + void dummy_posix_acls(void) {;} /* So some compilers don't complain. */ +#endif /* HAVE_POSIX_ACLS */ -- cgit From 92d1e90d497b7795dd671c1a52092ef7ba6d542b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 29 Aug 2000 14:38:38 +0000 Subject: fixed previous bug spotted by Elrond in get_printerdrivernumber(). Thought I had already committed this. jerry (This used to be commit 2ceb704c3d06a92b97ba67ac82c007a7ba084b75) --- source3/smbd/lanman.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 712016285e..170bb9e6bd 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -542,16 +542,16 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, desc->errcode=NERR_notsupported; return; } - else + + /* lookup the long printer driver name in the file description */ + for (i=0;lines[i] && !ok;i++) { - /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) + p = lines[i]; + if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok = True; + ok = True; } } } @@ -777,17 +777,18 @@ static int get_printerdrivernumber(int snum) if (!lines) { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); + return 0; } - else + + /* lookup the long printer driver name in the file description */ + for (i=0;lines[i] && !ok;i++) { - /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) + p = lines[i]; + if (next_token(&p,tok,":",sizeof(tok)) && + (strlen(lp_printerdriver(snum)) == strlen(tok)) && + (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) - ok = True; + ok = True; } } } -- cgit From d407579b94ee2647d1e51c536534024e5c4c51ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Aug 2000 00:45:59 +0000 Subject: Implemented AbortPrinter() from Gerald's Win32 test code. Just purge all possible printjobs from that printer (I think this is correct). Added error code returns for print_queue_XXX() functions. Jeremy. (This used to be commit 6d081a9017f87f59b7189ba507e211db01c40af5) --- source3/smbd/lanman.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 170bb9e6bd..82ab5f4d3c 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1940,13 +1940,13 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para switch (function) { case 74: /* Pause queue */ - if (print_queue_pause(NULL, snum)) errcode = NERR_Success; + if (print_queue_pause(NULL, snum, &errcode)) errcode = NERR_Success; break; case 75: /* Resume queue */ - if (print_queue_resume(NULL, snum)) errcode = NERR_Success; + if (print_queue_resume(NULL, snum, &errcode)) errcode = NERR_Success; break; case 103: /* Purge */ - if (print_queue_purge(NULL, snum)) errcode = NERR_Success; + if (print_queue_purge(NULL, snum, &errcode)) errcode = NERR_Success; break; } -- cgit From 177b962dfe4c6215424ff2a2e69a4da3cecb3687 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Aug 2000 18:33:56 +0000 Subject: Added vfs_unlink call to ensure vfs is used on unlink from client. Jeremy. (This used to be commit 38fc56c8434c427335cf264c4b27420c5ad47566) --- source3/smbd/reply.c | 2 +- source3/smbd/vfs.c | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 00e6f44dd0..7e6a244190 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1888,7 +1888,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) + if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory)) count++; if (!count) exists = vfs_file_exist(conn,directory,NULL); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7c34817351..496d3e0432 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -242,6 +242,15 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, return ret; } +/******************************************************************* + vfs Unlink wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_unlink(connection_struct *conn, char *fname) +{ + return(conn->vfs_ops.unlink(dos_to_unix(fname,False))); +} + /******************************************************************* check if a vfs file exists ********************************************************************/ -- cgit From 22fbda6c5616c89e774ed2550476f47aa9f0506f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 31 Aug 2000 07:11:45 +0000 Subject: fixed "admin users" option with new security code (This used to be commit b69c5de6bad9fad3aed1280e7d12fbfed276a16f) --- source3/smbd/service.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 500ba6e626..272d54e3ba 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -389,6 +389,11 @@ connection_struct *make_connection(char *service,char *user,char *password, int } } + /* admin users always run as uid=0 */ + if (conn->admin_user) { + conn->uid = 0; + } + #ifdef HAVE_GETGRNAM /* * If force group is true, then override -- cgit From 288ea15a564e0931f8002cfb2ca3b4064bb4c227 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 31 Aug 2000 07:11:59 +0000 Subject: make sure a couple of variables are initialised (This used to be commit 155c7c37398f5f9457ea249ded74f425b90ac9a0) --- source3/smbd/lanman.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 82ab5f4d3c..6595163ba9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -499,7 +499,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, print_status_struct* status) { int i; - BOOL ok; + BOOL ok = False; pstring tok,driver,datafile,langmon,helpfile,datatype; char *p; char **lines = NULL; @@ -742,7 +742,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, static int get_printerdrivernumber(int snum) { int i; - BOOL ok; + BOOL ok = False; pstring tok; char *p; char **lines = NULL; -- cgit From a3a28675fafbbc5a5a378b3a7235253d772ef63e Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Fri, 1 Sep 2000 18:49:26 +0000 Subject: Changes from APPLIANCE_HEAD (per Tim Potter): - make proto - addition of function to convert from errno values to NT status codes (source/lib/error.c) - purge queue done without full access permission will purge only the jobs owned by that user, rather than failing. - unlock job database tdb before sending job to printer - in print_job_start(), ensure that we don't pick a jobid with an existing temporary file that may be owned by another user, as it causes silent failures. - fixes for printer permission checking for NT5 clients (source/include/rpc_spoolss.h, source/printing/nt_printing.c, source/printing/printing.c, source/rpc_server/srv_spoolss_nt.c) - change from uint8 to 'enum SID_NAME_USE' (source/rpc_server/srv_lsa.c) - fixed memory leaks for win95 driver download process (source/smbd/lanman.c) - properly free prs_structs and dacl in testsuite/printing/psec.c (This used to be commit 74af3e2caec7197e5d1ca389e2f78054a4197502) --- source3/smbd/lanman.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 6595163ba9..54bfa3155b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -540,7 +540,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum), strerror(errno))); desc->errcode=NERR_notsupported; - return; + goto done; } /* lookup the long printer driver name in the file description */ @@ -651,14 +651,16 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, SERVICE(snum),count)); desc->errcode=NERR_Success; - file_lines_free(lines); - return; + goto done; } err: DEBUG(3,("fill_printq_info: Can't supply driver files\n")); desc->errcode=NERR_notsupported; + + done: + safe_free(info); file_lines_free(lines); } @@ -741,7 +743,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, /* This function returns the number of files for a given driver */ static int get_printerdrivernumber(int snum) { - int i; + int i, result = 0; BOOL ok = False; pstring tok; char *p; @@ -777,7 +779,7 @@ static int get_printerdrivernumber(int snum) if (!lines) { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - return 0; + goto done; } /* lookup the long printer driver name in the file description */ @@ -800,22 +802,24 @@ static int get_printerdrivernumber(int snum) while (*p && i) { if (*p++ == ':') i--; } - if (!*p || i) - goto err; + if (!*p || i) { + DEBUG(3,("Can't determine number of printer driver files\n")); + goto done; + } /* count the number of files */ while (next_token(&p,tok,",",sizeof(tok))) i++; - file_lines_free(lines); - return(i); + result = i; } - err: + done: - DEBUG(3,("Can't determine number of printer driver files\n")); + safe_free(info); file_lines_free(lines); - return (0); + + return result; } static BOOL api_DosPrintQGetInfo(connection_struct *conn, -- cgit From a1f66a820d78244fcab960fe33999c76cc1d65c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Sep 2000 01:06:39 +0000 Subject: Fix for the SID history problem when using a Win2k domain controller with security=domain. Also fixed to dynamically allocate the SIDs and GIDs. Jeremy. (This used to be commit 2b1f66eb82f05fe0b85ac5b4916e32847b8de675) --- source3/smbd/password.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9e59815e52..6d3a2d1a31 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1487,19 +1487,12 @@ BOOL domain_client_validate( char *user, char *domain, cli_ulogoff(&cli); cli_shutdown(&cli); - /* unused, so delete here. */ - if (info3.gids != NULL) - free (info3.gids); - if((nt_rpc_err == NT_STATUS_NO_SUCH_USER) && (user_exists != NULL)) *user_exists = False; return False; } - /* unused, so delete here. */ - if (info3.gids != NULL) - free (info3.gids); /* * Here, if we really want it, we have lots of info about the user in info3. */ @@ -1521,6 +1514,10 @@ BOOL domain_client_validate( char *user, char *domain, } #endif /* 0 */ + /* Note - once the cli stream is shutdown the mem_ctx used + to allocate the other_sids and gids structures has been deleted - so + these pointers are no longer valid..... */ + cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); -- cgit From 45d30f72ffc48ed06907f8eba1beed61be81f783 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 7 Sep 2000 08:43:05 +0000 Subject: Hopefully this should fix the primary group permission problem. (This used to be commit 2f33ec41ac1d3243340455b6c3a6cea22d267f14) --- source3/smbd/password.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6d3a2d1a31..fe3c9fea0f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -214,8 +214,6 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) token->num_sids++; } } - for (i = 0; i < ngroups; i++) - gid_to_sid( &psids[i+2], groups[i]); return token; } -- cgit From 3689e4ffc10fceb4c39814ef58fe31697e7dd976 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Sep 2000 07:02:43 +0000 Subject: the first cut of the internal messaging system. The motivation for this system is to replace the UDP message for oplocks, but this commit only does the "set debug level" message. (This used to be commit 2a34ee95f3929cff131db6c5a2b4820194c05b2d) --- source3/smbd/process.c | 3 +++ source3/smbd/server.c | 18 ++++-------------- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 37d8f8dd73..1599ade12d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -131,6 +131,9 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len) reload_services(False); reload_after_sighup = False; } + + /* check for any pending internal messages */ + message_dispatch(); } /**************************************************************************** diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8691603eb3..4442a1f71f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -685,20 +685,6 @@ static void usage(char *pname) CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); - /* Setup the signals that allow the debug log level - to by dynamically changed. */ - - /* If we are using the malloc debug code we can't use - SIGUSR1 and SIGUSR2 to do debug level changes. */ - -#if defined(SIGUSR1) - CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 ); -#endif /* SIGUSR1 */ - -#if defined(SIGUSR2) - CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 ); -#endif /* SIGUSR2 */ - DEBUG(3,( "loaded services\n")); if (!is_daemon && !is_a_socket(0)) { @@ -726,6 +712,10 @@ static void usage(char *pname) * everything after this point is run after the fork() */ + if (!message_init()) { + exit(1); + } + if (!locking_init(0)) { exit(1); } -- cgit From a19836ae5267fa967482f2baacd5e8cf8767bf79 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Sep 2000 04:50:36 +0000 Subject: we should not lowercase the username we receive in reply_sesssetup_and_X(). The getpwnam() wrapper handles the case munging operations later. this fixes a problem with mixed case usernames. (This used to be commit 2ebfdd21b3123d7daefeeed4dae6e8bc3a7a7653) --- source3/smbd/reply.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7e6a244190..397cae6221 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -671,7 +671,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * Incoming user is in DOS codepage format. Convert * to UNIX. */ - strlower(user); dos_to_unix(user,True); if (!doencrypt && (lp_security() != SEC_SERVER)) { @@ -787,7 +786,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * Incoming user is in DOS codepage format. Convert * to UNIX. */ - strlower(user); dos_to_unix(user,True); domain = p; -- cgit From 7ec53a14b149bcf90cf38548a0d9044286b3e3bb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Sep 2000 19:51:38 +0000 Subject: With John Reilly help tracking it down - fixed a *nasty* bug when authorising logins. If a user connected to a share as guest, then the snum was getting flagged as "force guest", meaning that all subsequent connections to it, even under a different vuid, would be bounced to guest. This explains several very hard to reproduce access denied bugs, and as the NT client also has bugs in that it will sometimes erroneously use guest instead of the correct vuid on an IPC$ connection lead to a *very* hard problem to find. This fix should be propagated into all branches (TNG/Applience take note) and I'll also make a separate patch availalble on the samba-technical list. Jeremy. (This used to be commit 0264fdafe909cf9e995df3ae7b64bedbe0b4e8a1) --- source3/smbd/password.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fe3c9fea0f..da01cf4f37 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -818,7 +818,6 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, else DEBUG(0,("Invalid guest account %s??\n",guestname)); *guest = True; - *force = True; } if (ok && !user_ok(user,snum)) -- cgit From 7a3795d5df8dc1b2e3d2afe2a9e12db34d80e305 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Sep 2000 19:00:21 +0000 Subject: Fix to allow a timestamp of zero to cause an instantaneous changenotify scan - then call this from renames. This allows instantaneous update for W2k renames. Jeremy. (This used to be commit 07dffc4ee931cbc61197e2da277df9c404a77469) --- source3/smbd/notify_hash.c | 9 ++++++--- source3/smbd/notify_kernel.c | 7 ++++++- source3/smbd/nttrans.c | 9 ++++++++- source3/smbd/reply.c | 11 ++++++++++- 4 files changed, 30 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index fe09d9cf9d..95d430d23b 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -116,14 +116,15 @@ static void *hash_register_notify(connection_struct *conn, char *path, uint32 fl } /**************************************************************************** -check if a change notify should be issued + Check if a change notify should be issued. + A time of zero means instantaneous check - don't modify the last check time. *****************************************************************************/ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) { struct change_data *data = (struct change_data *)datap; struct change_data data2; - if (t < data->last_check_time + lp_change_notify_timeout()) return False; + if (t && t < data->last_check_time + lp_change_notify_timeout()) return False; if (!become_user(conn,vuid)) return True; if (!become_service(conn,True)) { @@ -140,7 +141,9 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, return True; } - data->last_check_time = t; + if (t) + data->last_check_time = t; + unbecome_user(); return False; diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index c517254048..db823601f1 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -74,12 +74,17 @@ static void signal_handler(int signal, siginfo_t *info, void *unused) /**************************************************************************** -check if a change notify should be issued + Check if a change notify should be issued. + time zero means instantaneous check (used for hash). Ignore this (normal method + will be used instead). *****************************************************************************/ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) { struct change_data *data = (struct change_data *)datap; + if (!t) + return False; + if (data->directory_handle != (int)fd_pending) return False; DEBUG(3,("kernel change notify on %s fd=%d\n", path, (int)fd_pending)); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8147a3adac..1599f01aa5 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1473,11 +1473,18 @@ static int call_nt_transact_rename(connection_struct *conn, fsp->fsp_name, new_name)); outsize = -1; + + /* + * Win2k needs a changenotify request response before it will + * update after a rename.. + */ + + process_pending_change_notify_queue((time_t)0); } return(outsize); } - + /**************************************************************************** Reply to query a security descriptor - currently this is not implemented (it diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 397cae6221..9dd5a9ef68 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3639,8 +3639,17 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); outsize = rename_internals(conn, inbuf, outbuf, name, newname, False); - if(outsize == 0) + if(outsize == 0) { + + /* + * Win2k needs a changenotify request response before it will + * update after a rename.. + */ + + process_pending_change_notify_queue((time_t)0); + outsize = set_message(outbuf,0,0,True); + } return(outsize); } -- cgit From d31a72f7390339ec2bb0f3af5da014d635ce09dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Sep 2000 23:39:19 +0000 Subject: Optimization (noticed by bloody Andrew :-) to stop directory scan ever being done if any of the directory timestamps were changed. Jeremy. (This used to be commit 915152ed981e8e537d15fd4b80b3c3d10ee86bff) --- source3/smbd/notify_hash.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 95d430d23b..a8cdcea17d 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -39,7 +39,7 @@ struct change_data { Create the hash we will use to determine if the contents changed. *****************************************************************************/ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, - struct change_data *data) + struct change_data *data, struct change_data *old_data) { SMB_STRUCT_STAT st; pstring full_name; @@ -52,10 +52,21 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, ZERO_STRUCTP(data); if(dos_stat(path, &st) == -1) return False; - + data->modify_time = st.st_mtime; data->status_time = st.st_ctime; + if (old_data) { + /* + * Shortcut to avoid directory scan if the time + * has changed - we always must return true then. + */ + if (old_data->modify_time != data->modify_time || + old_data->status_time != data->status_time ) { + return True; + } + } + /* * If we are to watch for changes that are only stored * in inodes of files, not in the directory inode, we must @@ -108,7 +119,7 @@ static void *hash_register_notify(connection_struct *conn, char *path, uint32 fl { struct change_data data; - if (!notify_hash(conn, path, flags, &data)) return NULL; + if (!notify_hash(conn, path, flags, &data, NULL)) return NULL; data.last_check_time = time(NULL); @@ -132,7 +143,7 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, return True; } - if (!notify_hash(conn, path, flags, &data2) || + if (!notify_hash(conn, path, flags, &data2, data) || data2.modify_time != data->modify_time || data2.status_time != data->status_time || data2.total_time != data->total_time || -- cgit From b43b2e4f8a4be30e3f7aca6f570f5376fd508e3d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Sep 2000 19:09:59 +0000 Subject: Restructuring of the code to remove dos_ChDir/dos_GetWd and re-vector them through the VFS. All file access/directory access code in smbd should now go via the vfs. Added vfs_chown/vfs_chmod calls. Still looking at vfs_get_nt_acl() vfs_set_nt_acl() call API design. Jeremy. (This used to be commit f96625ec124adb6e110dc54632e006b3620a962b) --- source3/smbd/dosmode.c | 8 +- source3/smbd/filename.c | 2 +- source3/smbd/notify_hash.c | 4 +- source3/smbd/oplock.c | 4 +- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 10 +- source3/smbd/unix_acls.c | 14 +- source3/smbd/vfs-wrap.c | 46 +++++ source3/smbd/vfs.c | 413 ++++++++++++++++++++++++++++++++++++++++++--- 9 files changed, 455 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 8e2382ee9f..269d286517 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -61,7 +61,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) dname = parent_dirname(fname); DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (dos_stat(dname,&sbuf) != 0) { + if (vfs_stat(conn,dname,&sbuf) != 0) { DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); return(0); /* *** shouldn't happen! *** */ } @@ -191,7 +191,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * if (!st) { st = &st1; - if (conn->vfs_ops.stat(dos_to_unix(fname,False),st)) return(-1); + if (vfs_stat(conn,fname,st)) return(-1); } if (S_ISDIR(st->st_mode)) dosmode |= aDIR; @@ -227,7 +227,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - return(conn->vfs_ops.chmod(dos_to_unix(fname,False),unixmode)); + return(vfs_chmod(conn,fname,unixmode)); } @@ -258,7 +258,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(conn->vfs_ops.stat(dos_to_unix(fname,False),&sb) != 0) + if(vfs_stat(conn,fname,&sb) != 0) return -1; /* Check if we have write access. */ diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 294e80250a..67fa85d9cb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -419,7 +419,7 @@ BOOL check_name(char *name,connection_struct *conn) return(0); } - ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn))); + ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); /* Check if we are allowing users to follow symlinks */ /* Patch from David Clerc diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index a8cdcea17d..5a2f865310 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -51,7 +51,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, ZERO_STRUCTP(data); - if(dos_stat(path, &st) == -1) return False; + if(vfs_stat(conn,path, &st) == -1) return False; data->modify_time = st.st_mtime; data->status_time = st.st_ctime; @@ -102,7 +102,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, /* * Do the stat - but ignore errors. */ - dos_stat(full_name, &st); + vfs_stat(conn,full_name, &st); data->total_time += (st.st_mtime + st.st_ctime); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 59c3c83f6f..4a8260421c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -732,7 +732,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B */ saved_conn = fsp->conn; saved_vuid = current_user.vuid; - dos_GetWd(saved_dir); + vfs_GetWd(saved_conn,saved_dir); unbecome_user(); /* Save the chain fnum. */ file_chain_save(); @@ -814,7 +814,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B exit_server("unable to re-become user"); } /* Including the directory. */ - dos_ChDir(saved_dir); + vfs_ChDir(saved_conn,saved_dir); /* Restore the chain fnum. */ file_chain_restore(); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9dd5a9ef68..8624bdb9b4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1100,7 +1100,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0) + if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 272d54e3ba..e82bbefa5a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -56,8 +56,8 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir) snum = SNUM(conn); if (do_chdir && - dos_ChDir(conn->connectpath) != 0 && - dos_ChDir(conn->origpath) != 0) { + vfs_ChDir(conn,conn->connectpath) != 0 && + vfs_ChDir(conn,conn->origpath) != 0) { DEBUG(0,("chdir (%s) failed\n", conn->connectpath)); return(False); @@ -575,7 +575,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } - if (dos_ChDir(conn->connectpath) != 0) { + if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(0,("Can't change directory to %s (%s)\n", conn->connectpath,strerror(errno))); unbecome_user(); @@ -598,9 +598,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int { pstring s; pstrcpy(s,conn->connectpath); - dos_GetWd(s); + vfs_GetWd(conn,s); string_set(&conn->connectpath,s); - dos_ChDir(conn->connectpath); + vfs_ChDir(conn,conn->connectpath); } #endif diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 7ab448e6a3..48f6163596 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -146,8 +146,6 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p DOM_SID grp_sid; DOM_SID file_owner_sid; DOM_SID file_grp_sid; - uint32 owner_rid; - uint32 grp_rid; SEC_ACL *dacl = psd->dacl; BOOL all_aces_are_inherit_only = (is_directory ? True : False); int i; @@ -353,7 +351,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } else { if(fsp->is_directory || fsp->fd == -1) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; } } else { @@ -458,14 +456,14 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) + if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { int ret; if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + ret = vfs_stat(fsp->conn,fsp->fsp_name,&sbuf); else ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); @@ -492,7 +490,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - if(dos_chown( fsp->fsp_name, user, grp) == -1) { + if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); return False; @@ -504,7 +502,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { return False; } } else { @@ -512,7 +510,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) int ret; if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); else ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 5db1689450..12ba9bda84 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -284,6 +284,42 @@ int vfswrap_chmod(char *path, mode_t mode) return result; } +int vfswrap_chown(char *path, uid_t uid, gid_t gid) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_chown()\n"); + } +#endif + + result = sys_chown(path, uid, gid); + return result; +} + +int vfswrap_chdir(char *path) +{ +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_chdir()\n"); + } +#endif + + return chdir(path); +} + +char *vfswrap_getwd(char *path) +{ +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_getwd()\n"); + } +#endif + + return sys_getwd(path); +} + int vfswrap_utime(char *path, struct utimbuf *times) { int result; @@ -310,3 +346,13 @@ BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { return fcntl_lock(fd, op, offset, count,type); } + +#if 0 +size_t vfswrap_get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) +{ +} + +BOOL vfswrap_set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) +{ +} +#endif diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 496d3e0432..631d4bedbe 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -64,9 +64,16 @@ struct vfs_ops default_vfs_ops = { vfswrap_lstat, vfswrap_unlink, vfswrap_chmod, + vfswrap_chown, + vfswrap_chdir, + vfswrap_getwd, vfswrap_utime, vfswrap_ftruncate, - vfswrap_lock + vfswrap_lock, +#if 0 + vfswrap_get_nt_acl, + vfswrap_set_nt_acl +#endif }; /**************************************************************************** @@ -208,6 +215,10 @@ BOOL vfs_init_custom(connection_struct *conn) conn->vfs_ops.chmod = default_vfs_ops.chmod; } + if (conn->vfs_ops.chown == NULL) { + conn->vfs_ops.chown = default_vfs_ops.chown; + } + if (conn->vfs_ops.utime == NULL) { conn->vfs_ops.utime = default_vfs_ops.utime; } @@ -224,20 +235,33 @@ BOOL vfs_init_custom(connection_struct *conn) } #endif -BOOL vfs_directory_exist(connection_struct *conn, char *dname, - SMB_STRUCT_STAT *st) +/******************************************************************* + vfs stat wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st) { - SMB_STRUCT_STAT st2; - BOOL ret; + return(conn->vfs_ops.stat(dos_to_unix(fname,False),st)); +} - if (!st) st = &st2; +/******************************************************************* + Check if directory exists. +********************************************************************/ - if (conn->vfs_ops.stat(dos_to_unix(dname,False),st) != 0) - return(False); +BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT *st) +{ + SMB_STRUCT_STAT st2; + BOOL ret; + + if (!st) + st = &st2; - ret = S_ISDIR(st->st_mode); - if(!ret) - errno = ENOTDIR; + if (vfs_stat(conn,dname,st) != 0) + return(False); + + ret = S_ISDIR(st->st_mode); + if(!ret) + errno = ENOTDIR; return ret; } @@ -248,26 +272,70 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, int vfs_unlink(connection_struct *conn, char *fname) { - return(conn->vfs_ops.unlink(dos_to_unix(fname,False))); + return(conn->vfs_ops.unlink(dos_to_unix(fname,False))); +} + +/******************************************************************* + vfs chmod wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_chmod(connection_struct *conn, char *fname,mode_t mode) +{ + return(conn->vfs_ops.chmod(dos_to_unix(fname,False), mode)); +} + +/******************************************************************* + vfs chown wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid) +{ + return(conn->vfs_ops.chown(dos_to_unix(fname,False), uid, gid)); } /******************************************************************* - check if a vfs file exists + A wrapper for vfs_chdir(). +********************************************************************/ + +int vfs_chdir(connection_struct *conn, char *fname) +{ + return(conn->vfs_ops.chdir(dos_to_unix(fname,False))); +} + +/******************************************************************* + vfs getwd wrapper that calls dos_to_unix. +********************************************************************/ + +char *vfs_getwd(connection_struct *conn, char *unix_path) +{ + char *wd; + wd = conn->vfs_ops.getwd(unix_path); + if (wd) + unix_to_dos(wd, True); + return wd; +} + +/******************************************************************* + Check if a vfs file exists. ********************************************************************/ + BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) { - SMB_STRUCT_STAT st; - if (!sbuf) sbuf = &st; - - if (conn->vfs_ops.stat(dos_to_unix(fname,False),sbuf) != 0) - return(False); + SMB_STRUCT_STAT st; - return(S_ISREG(sbuf->st_mode)); + if (!sbuf) + sbuf = &st; + + if (vfs_stat(conn,fname,sbuf) != 0) + return(False); + + return(S_ISREG(sbuf->st_mode)); } /**************************************************************************** - write data to a fd on the vfs + Write data to a fd on the vfs. ****************************************************************************/ + ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) { size_t total=0; @@ -286,8 +354,9 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) } /**************************************************************************** -transfer some data between two file_struct's + Transfer some data between two file_struct's. ****************************************************************************/ + SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, int out_fd, files_struct *out_fsp, SMB_OFF_T n, char *header, int headlen, int align) @@ -376,22 +445,26 @@ SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, } /******************************************************************* -a vfs_readdir wrapper which just returns the file name + A vfs_readdir wrapper which just returns the file name. ********************************************************************/ + char *vfs_readdirname(connection_struct *conn, void *p) { struct dirent *ptr; char *dname; - if (!p) return(NULL); + if (!p) + return(NULL); ptr = (struct dirent *)conn->vfs_ops.readdir(p); - if (!ptr) return(NULL); + if (!ptr) + return(NULL); dname = ptr->d_name; #ifdef NEXT2 - if (telldir(p) < 0) return(NULL); + if (telldir(p) < 0) + return(NULL); #endif #ifdef HAVE_BROKEN_READDIR @@ -474,3 +547,293 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr) #endif + +/******************************************************************* + A wrapper for vfs_chdir(). +********************************************************************/ + +int vfs_ChDir(connection_struct *conn, char *path) +{ + int res; + static pstring LastDir=""; + + if (strcsequal(path,".")) + return(0); + + if (*path == '/' && strcsequal(LastDir,path)) + return(0); + + DEBUG(3,("vfs_ChDir to %s\n",path)); + + res = vfs_chdir(conn,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 *dos_path; /* The pathname in DOS format. */ + BOOL valid; +} ino_list[MAX_GETWDCACHE]; + +extern BOOL use_getwd_cache; + +/**************************************************************************** + Prompte a ptr (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,("array_promote: malloc fail\n")); + return; + } + + memcpy(p,array + element * elsize, elsize); + memmove(array + elsize,array,elsize*element); + memcpy(array,p,elsize); + free(p); +} + +/******************************************************************* + Return the absolute current directory path - given a UNIX pathname. + Note that this path is returned in DOS format, not UNIX + format. Note this can be called with conn == NULL. +********************************************************************/ + +char *vfs_GetWd(connection_struct *conn, char *path) +{ + pstring s; + static BOOL getwd_cache_init = False; + SMB_STRUCT_STAT st, st2; + int i; + + *s = 0; + + if (!use_getwd_cache) + return(vfs_getwd(conn,path)); + + /* init the cache */ + if (!getwd_cache_init) + { + getwd_cache_init = True; + for (i=0;i Date: Fri, 29 Sep 2000 04:42:29 +0000 Subject: fixed a harmess mixup of bitops and a boolean (This used to be commit 0e0f3dc577ceab540be6505a86697b14a2136b9f) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8624bdb9b4..96a43b48c8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4025,7 +4025,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, char *data; uint32 ecode=0, dummy2; int eclass=0, dummy1; - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); + BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; BOOL err; CHECK_FSP(fsp,conn); -- cgit From 2679fa315da579fbdc7dd35d3ee1cb364b85a1d9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Oct 2000 21:03:46 +0000 Subject: Memleak fix for cache code. Jeremy. (This used to be commit 1ebe54666b0fc6f224f17036063dfe0ef7ec9147) --- source3/smbd/close.c | 24 ++++++++++++++++++++---- source3/smbd/fileio.c | 8 +++++++- 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 0b7b5f794e..f71b6b04f1 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -68,11 +68,15 @@ static void check_magic(files_struct *fsp,connection_struct *conn) Common code to close a file or a directory. ****************************************************************************/ -void close_filestruct(files_struct *fsp) +static int close_filestruct(files_struct *fsp) { connection_struct *conn = fsp->conn; + int ret = 0; - flush_write_cache(fsp, CLOSE_FLUSH); + if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) + ret = -1; + + delete_write_cache(fsp); fsp->is_directory = False; fsp->stat_open = False; @@ -82,6 +86,8 @@ void close_filestruct(files_struct *fsp) free((char *)fsp->wbmpx_ptr); fsp->wbmpx_ptr = NULL; } + + return ret; } /**************************************************************************** @@ -98,10 +104,17 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) BOOL delete_on_close = fsp->delete_on_close; connection_struct *conn = fsp->conn; int err = 0; + int err1 = 0; remove_pending_lock_requests_by_fid(fsp); - close_filestruct(fsp); + /* + * If we're flushing on a close we can get a write + * error here, we must remember this. + */ + + if (close_filestruct(fsp) == -1) + err1 = -1; if (normal_close && fsp->print_file) { print_fsp_end(fsp); @@ -156,7 +169,10 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); file_free(fsp); - return err; + if (err == -1 || err1 == -1) + return -1; + else + return 0; } /**************************************************************************** diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 7fbf6e2a37..3ebc46e86b 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -186,7 +186,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) * the write cache. */ - if ((fsp->oplock_type == EXCLUSIVE_OPLOCK) && !wcp) { + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { setup_write_cache(fsp, st.st_size); wcp = fsp->wcp; } @@ -569,6 +569,9 @@ void delete_write_cache(files_struct *fsp) free(wcp); fsp->wcp = NULL; + + DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name )); + } /**************************************************************************** @@ -604,6 +607,9 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) fsp->wcp = wcp; allocated_write_caches++; + DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n", + fsp->fsp_name, wcp->alloc_size )); + return True; } -- cgit From 3ad2ee22bb4ecee24d069bb7efadff18c25044d1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Oct 2000 02:12:14 +0000 Subject: utf-8 and EUC3 patch from Hiroshi Miura Samba User Group Japan staff. mkdir high bits patch from Robert Dahlem" . jeremy. (This used to be commit b40191d27180ab1e59935086073c4d312552f717) --- source3/smbd/open.c | 3 +-- source3/smbd/reply.c | 3 +-- source3/smbd/trans2.c | 3 +-- source3/smbd/vfs.c | 24 ++++++++++++++++++++++++ 4 files changed, 27 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e9d2f01e10..4964e15e01 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -897,8 +897,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), - unix_mode(conn,aDIR, fname)) < 0) { + if(vfs_mkdir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 96a43b48c8..b98ae441ac 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3099,8 +3099,7 @@ int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring d unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory, conn)) - ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), - unix_mode(conn,aDIR,directory)); + ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret < 0) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 900a87e32b..9d1aa5dcfe 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2014,8 +2014,7 @@ static int call_trans2mkdir(connection_struct *conn, unix_convert(directory,conn,0,&bad_path,NULL); if (check_name(directory,conn)) - ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), - unix_mode(conn,aDIR,directory)); + ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); if(ret < 0) { diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 631d4bedbe..097f51d217 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -266,6 +266,30 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT * return ret; } +/******************************************************************* + vfs mkdir wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode) +{ + int ret; + pstring name; + SMB_STRUCT_STAT sbuf; + + pstrcpy(name,dos_to_unix(fname,False)); /* paranoia copy */ + if(!(ret=conn->vfs_ops.mkdir(name,mode))) { + /* + * Check if high bits should have been set, + * then (if bits are missing): add them. + * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir. + */ + if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && + !vfs_stat(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) + vfs_chmod(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); + } + return ret; +} + /******************************************************************* vfs Unlink wrapper that calls dos_to_unix. ********************************************************************/ -- cgit From 6692d0905e3e8605884ced5d38efb26929648d29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Oct 2000 19:15:05 +0000 Subject: Fixes for the fact that UNICODE sizes are no always 2*no of chars when in multibyte codepages. Fix from Hiroshi MIURA, Samba User Group Japan staff. Jeremy. (This used to be commit f2f373df67a3c6b0bd431c19e3494d45ef0a263c) --- source3/smbd/trans2.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9d1aa5dcfe..2366fceae7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1193,9 +1193,11 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,12,strlen(vname)); pstrcpy(pdata+18,vname); } else { - data_len = 18 + 2*strlen(vname); - SIVAL(pdata,12,strlen(vname)*2); - dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring), False); + int vnamelen; + + vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False); + data_len = 18 + vnamelen; + SIVAL(pdata,12,vnamelen); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); } @@ -1466,10 +1468,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, *short_name = '\0'; } strupper(short_name); - l = strlen(short_name); - dos_PutUniCode(pdata + 4, unix_to_dos(short_name,False),sizeof(pstring), False); - data_size = 4 + (2*l); - SIVAL(pdata,0,2*l); + l = dos_PutUniCode(pdata + 4, short_name, sizeof(pstring), False); + data_size = 4 + l; + SIVAL(pdata,0,l); } break; @@ -1483,7 +1484,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) { l = l*2; SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); - dos_PutUniCode(pdata + 4, unix_to_dos("\\",False),sizeof(pstring), False); + dos_PutUniCode(pdata + 4, "\\",sizeof(pstring), False); } else { pstrcpy(pdata+4,fname); } -- cgit From 4248374c84a3564de3c2cc728612b73ba72e2443 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Oct 2000 22:37:33 +0000 Subject: Made re-init of stat cache explicit rather than being hidden. Jeremy. (This used to be commit b0c40236bb4381fec0e812c20e5f8c09ebf005f9) --- source3/smbd/statcache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 7b8701337f..7b2916bb9a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -247,5 +247,6 @@ BOOL reset_stat_cache( void ) return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); } hash_clear(&stat_cache); - return True; + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + } /* reset_stat_cache */ -- cgit From f0af8acc9d6a546fe96a8a8ab985224c353084dd Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 5 Oct 2000 03:28:58 +0000 Subject: Added uid and gid to push_sec_ctx() debug. (This used to be commit 2817b6cc8af3edbaa63b5db67689ab94cb240d4f) --- source3/smbd/sec_ctx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 0cab2a7e9c..6837a8d4f8 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -272,13 +272,14 @@ BOOL push_sec_ctx(void) sec_ctx_stack_ndx++; - DEBUG(3, ("push_sec_ctx() : sec_ctx_stack_ndx = %d\n", sec_ctx_stack_ndx )); - ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; ctx_p->uid = geteuid(); ctx_p->gid = getegid(); + DEBUG(3, ("push_sec_ctx(%d, %d) : sec_ctx_stack_ndx = %d\n", + ctx_p->uid, ctx_p->gid, sec_ctx_stack_ndx )); + ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); ctx_p->ngroups = sys_getgroups(0, NULL); -- cgit From bbd7f7bf0fd4f6cda41989c3371d7bf18f49a592 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Oct 2000 18:50:18 +0000 Subject: Herb's fixes for profiling & compiler warnings. Jeremy. (This used to be commit 7914e9351abb5271ebb4990c3b1fe495d15a4eda) --- source3/smbd/fileio.c | 116 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 3ebc46e86b..0c43a255dc 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -70,7 +70,6 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) Read from write cache if we can. ****************************************************************************/ -static unsigned int cache_read_hits; BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { @@ -84,7 +83,9 @@ BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) memcpy(data, wcp->data + (pos - wcp->offset), n); - cache_read_hits++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_read_hits); +#endif return True; } @@ -125,20 +126,8 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) return(ret); } -/* Write cache static counters. */ - -static unsigned int abutted_writes; -static unsigned int total_writes; -static unsigned int non_oplock_writes; -static unsigned int direct_writes; -static unsigned int init_writes; -static unsigned int flushed_writes; -static unsigned int num_perfect_writes; -static unsigned int flush_reasons[NUM_FLUSH_REASONS]; - /* how many write cache buffers have been allocated */ static unsigned int allocated_write_caches; -static unsigned int num_write_caches; /**************************************************************************** *Really* write to a file. @@ -193,10 +182,12 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) } } - total_writes++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_total_writes); if (!fsp->oplock_type) { - non_oplock_writes++; + INC_PROFILE_COUNT(writecache_non_oplock_writes); } +#endif /* * If this file is level II oplocked then we need @@ -279,25 +270,35 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) abort(); } - if (total_writes % 500 == 0) { - DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u flushes=%u total=%u \ +#ifdef WITH_PROFILE + if (profile_p && profile_p->writecache_total_writes % 500 == 0) { + DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", - init_writes, abutted_writes, flushed_writes, total_writes, non_oplock_writes, - allocated_write_caches, - num_write_caches, direct_writes, num_perfect_writes, cache_read_hits )); - - DEBUG(3,("WRITECACHE: SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", - flush_reasons[SEEK_FLUSH], - flush_reasons[READ_FLUSH], - flush_reasons[WRITE_FLUSH], - flush_reasons[READRAW_FLUSH], - flush_reasons[OPLOCK_RELEASE_FLUSH], - flush_reasons[CLOSE_FLUSH], - flush_reasons[SYNC_FLUSH] )); + profile_p->writecache_init_writes, + profile_p->writecache_abutted_writes, + profile_p->writecache_total_writes, + profile_p->writecache_non_oplock_writes, + profile_p->writecache_allocated_write_caches, + profile_p->writecache_num_write_caches, + profile_p->writecache_direct_writes, + profile_p->writecache_num_perfect_writes, + profile_p->writecache_read_hits )); + + DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", + profile_p->writecache_flushed_writes[SEEK_FLUSH], + profile_p->writecache_flushed_writes[READ_FLUSH], + profile_p->writecache_flushed_writes[WRITE_FLUSH], + profile_p->writecache_flushed_writes[READRAW_FLUSH], + profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH], + profile_p->writecache_flushed_writes[CLOSE_FLUSH], + profile_p->writecache_flushed_writes[SYNC_FLUSH] )); } +#endif if(!wcp) { - direct_writes++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_direct_writes); +#endif return real_write_file(fsp, data, pos, n); } @@ -349,7 +350,9 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", pos += data_used; n -= data_used; - abutted_writes++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_abutted_writes); +#endif total_written = data_used; write_path = 1; @@ -385,7 +388,9 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", cache_flush_needed = True; - abutted_writes++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_abutted_writes); +#endif total_written = data_used; write_path = 2; @@ -455,7 +460,9 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", pos += data_used; n -= data_used; - abutted_writes++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_abutted_writes); +#endif total_written = data_used; write_path = 3; @@ -487,7 +494,9 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne if ( n <= wcp->alloc_size && n > wcp->data_size) { cache_flush_needed = True; } else { - direct_writes++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_direct_writes); +#endif return real_write_file(fsp, data, pos, n); } @@ -499,8 +508,6 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne wcp->file_size = wcp->data_size; if (cache_flush_needed) { - flushed_writes++; - DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, @@ -518,7 +525,9 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", if (n > wcp->alloc_size ) { if(real_write_file(fsp, data, pos, n) == -1) return -1; - direct_writes++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_direct_writes); +#endif return total_written + n; } @@ -527,16 +536,19 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", */ if (n) { +#ifdef WITH_PROFILE if (wcp->data_size) { - abutted_writes++; - DEBUG(9,("abutted write (%u)\n", abutted_writes)); + INC_PROFILE_COUNT(writecache_abutted_writes); } else { - init_writes++; + INC_PROFILE_COUNT(writecache_init_writes); } +#endif memcpy(wcp->data+wcp->data_size, data, n); if (wcp->data_size == 0) { wcp->offset = pos; - num_write_caches++; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_num_write_caches); +#endif } wcp->data_size += n; DEBUG(9,("cache return %u\n", (unsigned int)n)); @@ -561,6 +573,9 @@ void delete_write_cache(files_struct *fsp) if(!(wcp = fsp->wcp)) return; +#ifdef WITH_PROFILE + DEC_PROFILE_COUNT(writecache_allocated_write_caches); +#endif allocated_write_caches--; SMB_ASSERT(wcp->data_size == 0); @@ -583,7 +598,8 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); write_cache *wcp; - if (allocated_write_caches >= MAX_WRITE_CACHES) return False; + if (allocated_write_caches >= MAX_WRITE_CACHES) + return False; if(alloc_size == 0 || fsp->wcp) return False; @@ -605,6 +621,9 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) } fsp->wcp = wcp; +#ifdef WITH_PROFILE + INC_PROFILE_COUNT(writecache_allocated_write_caches); +#endif allocated_write_caches++; DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n", @@ -640,15 +659,18 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) data_size = wcp->data_size; wcp->data_size = 0; - num_write_caches--; - - flush_reasons[(int)reason]++; +#ifdef WITH_PROFILE + DEC_PROFILE_COUNT(writecache_num_write_caches); + INC_PROFILE_COUNT(writecache_flushed_writes[reason]); +#endif DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned int)data_size)); +#ifdef WITH_PROFILE if(data_size == wcp->alloc_size) - num_perfect_writes++; + INC_PROFILE_COUNT(writecache_num_perfect_writes); +#endif return real_write_file(fsp, wcp->data, wcp->offset, data_size); } -- cgit From 94c63f6ca473306a3e5607d76aa05a63a9da765c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Oct 2000 19:04:41 +0000 Subject: Vector get_nt_acl/set_nt_acl via vfs. POSIX ACL support should be added above this layer. Jeremy. (This used to be commit b90af886a951b7b049ed7a42e6d99c332e43897b) --- source3/smbd/nttrans.c | 5 ++++- source3/smbd/unix_acls.c | 32 ++++++++++++++++++++++---------- source3/smbd/vfs-wrap.c | 12 +----------- source3/smbd/vfs.c | 43 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 65 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1599f01aa5..95010cddc8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1611,6 +1611,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, files_struct *fsp = NULL; uint32 security_info_sent = 0; TALLOC_CTX *mem_ctx; + BOOL ret; if(!lp_nt_acl_support()) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1659,7 +1660,9 @@ security descriptor.\n")); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (!set_nt_acl(fsp, security_info_sent, psd)) { + ret = set_nt_acl( fsp, security_info_sent, psd); + + if (!ret) { free_sec_desc(&psd); talloc_destroy(mem_ctx); return(UNIXERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 48f6163596..a564ec9ee5 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -59,6 +59,7 @@ static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w return sa; } +#if 0 /**************************************************************************** Validate a SID. ****************************************************************************/ @@ -88,6 +89,7 @@ static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) return True; } +#endif /**************************************************************************** Map NT perms to UNIX. @@ -350,6 +352,15 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) sid_copy( &group_sid, &global_sid_World); } else { + /* + * If there is a VFS redirect, use it. + */ + + if ((fsp->is_directory || fsp->fd == -1) && fsp->conn->vfs_ops.get_nt_acl) + return fsp->conn->vfs_ops.get_nt_acl(dos_to_unix(fsp->fsp_name, False), ppdesc); + else if (fsp->conn->vfs_ops.fget_nt_acl) + return fsp->conn->vfs_ops.fget_nt_acl(fsp->fd, ppdesc); + if(fsp->is_directory || fsp->fd == -1) { if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; @@ -451,23 +462,24 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) SMB_STRUCT_STAT sbuf; BOOL got_dacl = False; + /* + * If there is a VFS redirect, use it. + */ + + if ((fsp->is_directory || fsp->fd == -1) && fsp->conn->vfs_ops.set_nt_acl) + return fsp->conn->vfs_ops.set_nt_acl(dos_to_unix(fsp->fsp_name, False), security_info_sent, psd); + else if (fsp->conn->vfs_ops.fset_nt_acl) + return fsp->conn->vfs_ops.fset_nt_acl(fsp->fd, security_info_sent, psd); + /* * Get the current state of the file. */ - if(fsp->is_directory) { + if(fsp->is_directory || fsp->fd == -1) { if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - - int ret; - - if(fsp->fd == -1) - ret = vfs_stat(fsp->conn,fsp->fsp_name,&sbuf); - else - ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); - - if(ret != 0) + if(conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) return False; } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 12ba9bda84..d19be7fb71 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -1,7 +1,7 @@ /* Unix SMB/Netbios implementation. Version 1.9. -s Wrap disk only vfs functions to sidestep dodgy compilers. + Wrap disk only vfs functions to sidestep dodgy compilers. Copyright (C) Tim Potter 1998 This program is free software; you can redistribute it and/or modify @@ -346,13 +346,3 @@ BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { return fcntl_lock(fd, op, offset, count,type); } - -#if 0 -size_t vfswrap_get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) -{ -} - -BOOL vfswrap_set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) -{ -} -#endif diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 097f51d217..4a4b1b2cfa 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -69,11 +69,11 @@ struct vfs_ops default_vfs_ops = { vfswrap_getwd, vfswrap_utime, vfswrap_ftruncate, - vfswrap_lock, -#if 0 - vfswrap_get_nt_acl, - vfswrap_set_nt_acl -#endif + vfswrap_lock, + NULL, /* The 4 security descriptor functions are not defined by default. */ + NULL, + NULL, + NULL }; /**************************************************************************** @@ -219,6 +219,14 @@ BOOL vfs_init_custom(connection_struct *conn) conn->vfs_ops.chown = default_vfs_ops.chown; } + if (conn->vfs_ops.chdir == NULL) { + conn->vfs_ops.chdir = default_vfs_ops.chdir; + } + + if (conn->vfs_ops.getwd == NULL) { + conn->vfs_ops.getwd = default_vfs_ops.getwd; + } + if (conn->vfs_ops.utime == NULL) { conn->vfs_ops.utime = default_vfs_ops.utime; } @@ -230,6 +238,22 @@ BOOL vfs_init_custom(connection_struct *conn) if (conn->vfs_ops.lock == NULL) { conn->vfs_ops.lock = default_vfs_ops.lock; } + + if (conn->vfs_ops.fget_nt_acl == NULL) { + conn->vfs_ops.fget_nt_acl = default_vfs_ops.fget_nt_acl; + } + + if (conn->vfs_ops.get_nt_acl == NULL) { + conn->vfs_ops.get_nt_acl = default_vfs_ops.get_nt_acl; + } + + if (conn->vfs_ops.fset_nt_acl == NULL) { + conn->vfs_ops.fset_nt_acl = default_vfs_ops.fset_nt_acl; + } + + if (conn->vfs_ops.set_nt_acl == NULL) { + conn->vfs_ops.set_nt_acl = default_vfs_ops.set_nt_acl; + } return True; } @@ -244,6 +268,15 @@ int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st) return(conn->vfs_ops.stat(dos_to_unix(fname,False),st)); } +/******************************************************************* + vfs fstat wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_fstat(connection_struct *conn, int fd, SMB_STRUCT_STAT *st) +{ + return(conn->vfs_ops.fstat(fd,st)); +} + /******************************************************************* Check if directory exists. ********************************************************************/ -- cgit From 56d514235ed16d3cb6b3682afa6980eb3455c50d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Oct 2000 22:51:57 +0000 Subject: Fix for null passwords being allowed bug. Jeremy. (This used to be commit d4d55488397832df35b558564c263a307b0bb629) --- source3/smbd/password.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index da01cf4f37..2f720db9c1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -514,10 +514,14 @@ BOOL pass_check_smb(char *user, char *domain, return(False); } - if (lm_pwd[0] == '\0' && (smb_pass->acct_ctrl & ACB_PWNOTREQ) && lp_null_passwords()) - { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", smb_pass->smb_name)); - return(True); + if (smb_pass->acct_ctrl & ACB_PWNOTREQ) { + if (lp_null_passwords()) { + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", smb_pass->smb_name)); + return(True); + } else { + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", smb_pass->smb_name)); + return(False); + } } if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) -- cgit From 636f146abf0a75cd3b21a57b50627ee149a635ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 03:21:49 +0000 Subject: Restructuring of vfs layer to include a "this" pointer - can be an fsp or a conn struct depending on the call. We need this to have a clean NT ACL call interface. This will break any existing VFS libraries (that's why this is pre-release code). Andrew gets credit for this one :-) :-). In addition - added Herb's WITH_PROFILE changes - Herb - please examine the changes I've made to the smbd/reply.c code you added. The original code was very ugly and I have replaced it with a START_PROFILE(x)/END_PROFILE(x) pair using the preprocessor. Please check this compiles ok with the --with-profile switch. Jeremy. (This used to be commit b07611f8159b0b3f42e7e02611be9f4d56de96f5) --- source3/smbd/close.c | 2 +- source3/smbd/conn.c | 14 +- source3/smbd/dir.c | 8 +- source3/smbd/dosmode.c | 4 +- source3/smbd/fileio.c | 8 +- source3/smbd/filename.c | 6 +- source3/smbd/nttrans.c | 10 +- source3/smbd/open.c | 14 +- source3/smbd/reply.c | 456 +++++++++++++++++++++++++++++++++++++---------- source3/smbd/service.c | 44 +---- source3/smbd/statcache.c | 2 +- source3/smbd/trans2.c | 28 +-- source3/smbd/unix_acls.c | 16 +- source3/smbd/vfs-wrap.c | 52 +++--- source3/smbd/vfs.c | 62 +++---- 15 files changed, 469 insertions(+), 257 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index f71b6b04f1..62194f73a5 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -146,7 +146,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (normal_close && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(fsp->conn->vfs_ops.unlink(dos_to_unix(fsp->fsp_name, False)) != 0) { + if(fsp->conn->vfs_ops.unlink(conn,dos_to_unix(fsp->fsp_name, False)) != 0) { /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index c1f42be098..cd4ca9ded4 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -170,19 +170,11 @@ void conn_free(connection_struct *conn) /* Free vfs_connection_struct */ #ifdef HAVE_LIBDL - if (conn->vfs_conn != NULL) { + if (conn->dl_handle != NULL) { /* Close dlopen() handle */ - if (conn->vfs_conn->dl_handle) { - dlclose(conn->vfs_conn->dl_handle); - } -#endif /* HAVE_LIBDL */ - - if (conn->vfs_conn->groups != NULL) { - free(conn->vfs_conn->groups); - } - delete_nt_token(&conn->vfs_conn->nt_user_token); - free(conn->vfs_conn); + dlclose(conn->dl_handle); } +#endif /* HAVE_LIBDL */ DLIST_REMOVE(Connections, conn); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index aaab206a26..bf15be2f1c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -627,7 +627,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(dos_to_unix(pathreal, False), &sbuf) != 0) + if (conn->vfs_ops.stat(conn,dos_to_unix(pathreal, False), &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; @@ -673,13 +673,13 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - DIR *p = conn->vfs_ops.opendir(dos_to_unix(name,False)); + DIR *p = conn->vfs_ops.opendir(conn,dos_to_unix(name,False)); int used=0; if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { - conn->vfs_ops.closedir(p); + conn->vfs_ops.closedir(conn,p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; @@ -714,7 +714,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->numentries++; } - conn->vfs_ops.closedir(p); + conn->vfs_ops.closedir(conn,p); return((void *)dirp); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 269d286517..377cfbb7cf 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -243,7 +243,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(conn->vfs_ops.utime(dos_to_unix(fname, False), times) == 0) + if(conn->vfs_ops.utime(conn,dos_to_unix(fname, False), times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -271,7 +271,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = conn->vfs_ops.utime(dos_to_unix(fname, False), times); + ret = conn->vfs_ops.utime(conn,dos_to_unix(fname, False), times); unbecome_root(); } } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 0c43a255dc..b8a0585d90 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -38,7 +38,7 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) if (fsp->print_file && lp_postscript(fsp->conn->service)) offset = 3; - seek_ret = fsp->conn->vfs_ops.lseek(fsp->fd,pos+offset,SEEK_SET); + seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos+offset,SEEK_SET); /* * We want to maintain the fiction that we can seek @@ -117,7 +117,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) } if (n > 0) { - readret = fsp->conn->vfs_ops.read(fsp->fd,data,n); + readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); if (readret == -1) return -1; if (readret > 0) ret += readret; @@ -164,7 +164,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) SMB_STRUCT_STAT st; fsp->modified = True; - if (fsp->conn->vfs_ops.fstat(fsp->fd,&st) == 0) { + if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); @@ -683,7 +683,7 @@ void sync_file(connection_struct *conn, files_struct *fsp) { if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { flush_write_cache(fsp, SYNC_FLUSH); - conn->vfs_ops.fsync(fsp->fd); + conn->vfs_ops.fsync(fsp,fsp->fd); } } #undef OLD_NTDOMAIN diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 67fa85d9cb..9ac82386f9 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -211,7 +211,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(dos_to_unix(name,False),&st) == 0) { + if (conn->vfs_ops.stat(conn,dos_to_unix(name,False),&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); if(pst) @@ -277,7 +277,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - if (conn->vfs_ops.stat(dos_to_unix(name,False), &st) == 0) { + if (conn->vfs_ops.stat(conn,dos_to_unix(name,False), &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -429,7 +429,7 @@ BOOL check_name(char *name,connection_struct *conn) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(conn,dos_to_unix(name,False),&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 95010cddc8..86b85ea766 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -892,13 +892,13 @@ int reply_ntcreate_and_X(connection_struct *conn, } if(fsp->is_directory) { - if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &sbuf) != 0) { + if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name, False), &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if (conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); @@ -1223,7 +1223,7 @@ static int call_nt_transact_create(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), + if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name, False), &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); @@ -1293,13 +1293,13 @@ static int call_nt_transact_create(connection_struct *conn, } if(fsp->is_directory) { - if(conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf) != 0) { + if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name,False), &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (!fsp->stat_open && conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if (!fsp->stat_open && conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4964e15e01..edd94bd865 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -41,13 +41,13 @@ static int fd_open(struct connection_struct *conn, char *fname, flags |= O_NONBLOCK; #endif - fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); + fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); + fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode); } DEBUG(10,("fd_open: name %s, mode = %d, fd = %d. %s\n", fname, (int)mode, fd, @@ -138,7 +138,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return False; } - if (conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1) { + if (conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf) == -1) { DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); fd_close(conn, fsp); return False; @@ -213,7 +213,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * unix_ERR_code = ERRlock; return -1; } else { - return conn->vfs_ops.ftruncate(fsp->fd,0); + return conn->vfs_ops.ftruncate(fsp,fsp->fd,0); } } @@ -792,7 +792,7 @@ files_struct *open_file_stat(connection_struct *conn, if(!fsp) return NULL; - if(conn->vfs_ops.stat(dos_to_unix(fname, False), pst) < 0) { + if(conn->vfs_ops.stat(conn,dos_to_unix(fname, False), pst) < 0) { DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); @@ -862,7 +862,7 @@ files_struct *open_directory(connection_struct *conn, if(!fsp) return NULL; - if(conn->vfs_ops.stat(dos_to_unix(fname, False), &st) == 0) { + if(conn->vfs_ops.stat(conn,dos_to_unix(fname, False), &st) == 0) { got_stat = True; } @@ -983,7 +983,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) SMB_DEV_T dev; SMB_INO_T inode; - if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) + if (conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf) == -1) return(True); dev = sbuf.st_dev; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b98ae441ac..e64875a805 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -214,6 +214,7 @@ int reply_tcon(connection_struct *conn, uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; int ecode = -1; + START_PROFILE(SMBtcon); *service = *user = *password = *dev = 0; @@ -242,6 +243,7 @@ int reply_tcon(connection_struct *conn, conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode); if (!conn) { + END_PROFILE(SMBtcon); return(connection_error(inbuf,outbuf,ecode)); } @@ -253,6 +255,7 @@ int reply_tcon(connection_struct *conn, DEBUG(3,("tcon service=%s user=%s cnum=%d\n", service, user, conn->cnum)); + END_PROFILE(SMBtcon); return(outsize); } @@ -271,6 +274,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int passlen = SVAL(inbuf,smb_vwv3); char *path; char *p; + START_PROFILE(SMBtconX); *service = *user = *password = *devicename = 0; @@ -294,8 +298,10 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } p = strchr(path+2,'\\'); - if (!p) + if (!p) { + END_PROFILE(SMBtconX); return(ERROR(ERRDOS,ERRnosuchshare)); + } fstrcpy(service,p+1); p = strchr(service,'%'); if (p) { @@ -327,8 +333,10 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode); - if (!conn) + if (!conn) { + END_PROFILE(SMBtconX); return(connection_error(inbuf,outbuf,ecode)); + } if (Protocol < PROTOCOL_NT1) { set_message(outbuf,2,strlen(devicename)+1,True); @@ -359,6 +367,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SSVAL(inbuf,smb_tid,conn->cnum); SSVAL(outbuf,smb_tid,conn->cnum); + END_PROFILE(SMBtconX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -390,6 +399,7 @@ int reply_ioctl(connection_struct *conn, int replysize, outsize; char *p; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBioctl); DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); @@ -399,6 +409,7 @@ int reply_ioctl(connection_struct *conn, replysize = 32; break; default: + END_PROFILE(SMBioctl); return(ERROR(ERRSRV,ERRnosupport)); } @@ -417,6 +428,7 @@ int reply_ioctl(connection_struct *conn, break; } + END_PROFILE(SMBioctl); return outsize; } @@ -653,6 +665,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; + START_PROFILE(SMBsesssetupX); *smb_apasswd = 0; *smb_ntpasswd = 0; @@ -801,6 +814,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* say yes to everything ending in $. */ if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) { + END_PROFILE(SMBsesssetupX); return session_trust_account(conn, inbuf, outbuf, user, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen); @@ -816,6 +830,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int */ if (!*user && !*smb_apasswd && !*domain) { DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); + END_PROFILE(SMBsesssetupX); return(ERROR(ERRDOS,ERRnoaccess)); } } @@ -913,6 +928,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (lp_map_to_guest() == NEVER_MAP_TO_GUEST) { DEBUG(1,("Rejecting user '%s': authentication failed\n", user)); + END_PROFILE(SMBsesssetupX); return bad_password_error(inbuf,outbuf); } @@ -921,6 +937,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (smb_getpwnam(user,True)) { DEBUG(1,("Rejecting user '%s': bad password\n", user)); + END_PROFILE(SMBsesssetupX); return bad_password_error(inbuf,outbuf); } } @@ -976,6 +993,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int const struct passwd *pw = smb_getpwnam(user,False); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); + END_PROFILE(SMBsesssetupX); return bad_password_error(inbuf,outbuf); } gid = pw->pw_gid; @@ -1000,6 +1018,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int done_sesssetup = True; + END_PROFILE(SMBsesssetupX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1015,6 +1034,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok = False; BOOL bad_path = False; SMB_STRUCT_STAT st; + START_PROFILE(SMBchkpth_count); pstrcpy(name,smb_buf(inbuf) + 1); @@ -1061,6 +1081,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("chkpth %s mode=%d\n", name, mode)); + END_PROFILE(SMBchkpth); return(outsize); } @@ -1078,6 +1099,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_OFF_T size=0; time_t mtime=0; BOOL bad_path = False; + START_PROFILE(SMBgetatr); pstrcpy(fname,smb_buf(inbuf) + 1); @@ -1122,6 +1144,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBgetatr); return(UNIXERROR(ERRDOS,ERRbadfile)); } @@ -1144,6 +1167,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); + END_PROFILE(SMBgetatr); return(outsize); } @@ -1160,6 +1184,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size time_t mtime; SMB_STRUCT_STAT st; BOOL bad_path = False; + START_PROFILE(SMBsetatr); pstrcpy(fname,smb_buf(inbuf) + 1); unix_convert(fname,conn,0,&bad_path,&st); @@ -1182,6 +1207,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBsetatr); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1189,6 +1215,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); + END_PROFILE(SMBsetatr); return(outsize); } @@ -1200,8 +1227,9 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz { int outsize = 0; SMB_BIG_UINT dfree,dsize,bsize; + START_PROFILE(SMBdskattr); - conn->vfs_ops.disk_free(".",True,&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -1212,6 +1240,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree)); + END_PROFILE(SMBdskattr); return(outsize); } @@ -1244,6 +1273,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL expect_close = False; BOOL can_open = True; BOOL bad_path = False; + START_PROFILE(SMBsearch); *mask = *directory = *fname = 0; @@ -1324,8 +1354,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBsearch); return (UNIXERROR(ERRDOS,ERRnofids)); } + END_PROFILE(SMBsearch); return(ERROR(ERRDOS,ERRnofids)); } dptr_set_wcard(dptr_num, strdup(mask)); @@ -1416,6 +1448,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size smb_fn_name(CVAL(inbuf,smb_com)), mask, directory, dirtype, numentries, maxentries ) ); + END_PROFILE(SMBsearch); return(outsize); } @@ -1430,14 +1463,17 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size char *path; char status[21]; int dptr_num= -2; + START_PROFILE(SMBfclose); outsize = set_message(outbuf,1,0,True); path = smb_buf(inbuf) + 1; status_len = SVAL(smb_buf(inbuf),3 + strlen(path)); - if (status_len == 0) + if (status_len == 0) { + END_PROFILE(SMBfclose); return(ERROR(ERRSRV,ERRsrverror)); + } memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); @@ -1450,6 +1486,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("search close\n")); + END_PROFILE(SMBfclose); return(outsize); } @@ -1472,6 +1509,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + START_PROFILE(SMBopen); share_mode = SVAL(inbuf,smb_vwv0); @@ -1493,11 +1531,13 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBopen); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { close_file(fsp,False); + END_PROFILE(SMBopen); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1508,6 +1548,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (fmode & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); close_file(fsp,False); + END_PROFILE(SMBopen); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1527,6 +1568,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + END_PROFILE(SMBopen); return(outsize); } @@ -1557,13 +1599,17 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int smb_action = 0; BOOL bad_path = False; files_struct *fsp; + START_PROFILE(SMBopenX); /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { - if (lp_nt_pipe_support()) + if (lp_nt_pipe_support()) { + END_PROFILE(SMBopenX); return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); - else + } else { + END_PROFILE(SMBopenX); return (ERROR(ERRSRV,ERRaccess)); + } } /* XXXX we need to handle passed times, sattr and flags */ @@ -1586,11 +1632,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBopenX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { close_file(fsp,False); + END_PROFILE(SMBopenX); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1599,6 +1647,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt mtime = sbuf.st_mtime; if (fmode & aDIR) { close_file(fsp,False); + END_PROFILE(SMBopenX); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1639,6 +1688,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,smb_action); + END_PROFILE(SMBopenX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1650,6 +1700,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, { uint16 vuid = SVAL(inbuf,smb_uid); user_struct *vuser = get_valid_user_struct(vuid); + START_PROFILE(SMBulogoffX); if(vuser == 0) { DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); @@ -1667,6 +1718,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); + END_PROFILE(SMBulogoffX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1685,6 +1737,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + START_PROFILE(SMBcreate); com = SVAL(inbuf,smb_com); @@ -1724,6 +1777,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBcreate); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1741,6 +1795,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) ); + END_PROFILE(SMBcreate); return(outsize); } @@ -1758,6 +1813,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + START_PROFILE(SMBctemp); createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); @@ -1783,6 +1839,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBctemp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1802,6 +1859,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", fname2, fsp->fd, createmode, (int)unixmode ) ); + END_PROFILE(SMBctemp); return(outsize); } @@ -1816,7 +1874,7 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False); fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); if (!lp_delete_readonly(SNUM(conn))) { @@ -1846,6 +1904,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL exists=False; BOOL bad_path = False; BOOL rc = True; + START_PROFILE(SMBunlink); *directory = *mask = 0; @@ -1919,7 +1978,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; - if (!conn->vfs_ops.unlink(dos_to_unix(fname,False))) count++; + if (!vfs_unlink(conn,fname)) count++; DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); } CloseDir(dirptr); @@ -1927,21 +1986,24 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } if (count == 0) { - if (exists) + if (exists) { + END_PROFILE(SMBunlink); return(ERROR(ERRDOS,error)); - else + } else { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBunlink); return(UNIXERROR(ERRDOS,error)); } } outsize = set_message(outbuf,0,0,True); + END_PROFILE(SMBunlink); return(outsize); } @@ -1958,6 +2020,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s char *header = outbuf; ssize_t ret=0; files_struct *fsp; + START_PROFILE(SMBreadbraw); /* * Special check if an oplock break has been issued @@ -1970,6 +2033,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s _smb_setlen(header,0); transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); DEBUG(5,("readbraw - oplock break finished\n")); + END_PROFILE(SMBreadbraw); return -1; } @@ -1982,6 +2046,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0))); _smb_setlen(header,0); transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); + END_PROFILE(SMBreadbraw); return(-1); } @@ -2009,6 +2074,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) )); _smb_setlen(header,0); transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); + END_PROFILE(SMBreadbraw); return(-1); } @@ -2019,6 +2085,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s (double)startpos )); _smb_setlen(header,0); transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); + END_PROFILE(SMBreadbraw); return(-1); } } @@ -2037,7 +2104,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (fsp->conn->vfs_ops.fstat(fsp->fd,&st) == 0) + if (vfs_fstat(fsp,fsp->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -2060,7 +2127,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s _smb_setlen(header,nread); if ((nread-predict) > 0) { - if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) { + if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) { DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); ret = 0; seek_fail = True; @@ -2068,7 +2135,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s } if(!seek_fail) - ret = (ssize_t)vfs_transfer_file(-1, fsp->fd, Client, NULL, + ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL, (SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); } @@ -2086,6 +2153,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s #endif /* UNSAFE_READRAW */ DEBUG(5,("readbraw finished\n")); + END_PROFILE(SMBreadbraw); return -1; } @@ -2103,6 +2171,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBlockread); CHECK_FSP(fsp,conn); CHECK_READ(fsp); @@ -2130,15 +2199,19 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * onto the blocking lock queue. */ if(push_blocking_lock_request(inbuf, length, -1, 0)) + END_PROFILE(SMBlockread); return -1; } + END_PROFILE(SMBlockread); return (ERROR(eclass,ecode)); } nread = read_file(fsp,data,startpos,numtoread); - if (nread < 0) + if (nread < 0) { + END_PROFILE(SMBlockread); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } outsize += nread; SSVAL(outbuf,smb_vwv0,nread); @@ -2148,6 +2221,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n", fsp->fnum, (int)numtoread, (int)nread ) ); + END_PROFILE(SMBlockread); return(outsize); } @@ -2164,6 +2238,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_OFF_T startpos; int outsize = 0; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBread); CHECK_FSP(fsp,conn); CHECK_READ(fsp); @@ -2176,14 +2251,18 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { + END_PROFILE(SMBread); return(ERROR(ERRDOS,ERRlock)); + } if (numtoread > 0) nread = read_file(fsp,data,startpos,numtoread); - if (nread < 0) + if (nread < 0) { + END_PROFILE(SMBread); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } outsize += nread; SSVAL(outbuf,smb_vwv0,nread); @@ -2194,6 +2273,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", fsp->fnum, (int)numtoread, (int)nread ) ); + END_PROFILE(SMBread); return(outsize); } @@ -2209,10 +2289,13 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt size_t smb_mincnt = SVAL(inbuf,smb_vwv6); ssize_t nread = -1; char *data; + START_PROFILE(SMBreadX); /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) + if (IS_IPC(conn)) { + END_PROFILE(SMBreadX); return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); + } CHECK_FSP(fsp,conn); CHECK_READ(fsp); @@ -2237,6 +2320,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if(IVAL(inbuf,smb_vwv10) != 0) { DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) )); + END_PROFILE(SMBreadX); return(ERROR(ERRDOS,ERRbadaccess)); } @@ -2244,12 +2328,16 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { + END_PROFILE(SMBreadX); return(ERROR(ERRDOS,ERRlock)); + } nread = read_file(fsp,data,startpos,smb_maxcnt); - if (nread < 0) + if (nread < 0) { + END_PROFILE(SMBreadX); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -2258,6 +2346,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n", fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) ); + END_PROFILE(SMBreadX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2276,6 +2365,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, BOOL write_through; files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; + START_PROFILE(SMBwritebraw); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2299,8 +2389,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CVAL(inbuf,smb_com) = SMBwritec; CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + END_PROFILE(SMBwritebraw); return(ERROR(ERRDOS,ERRlock)); + } if (numtowrite>0) nwritten = write_file(fsp,data,startpos,numtowrite); @@ -2308,8 +2400,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); - if (nwritten < numtowrite) + if (nwritten < numtowrite) { + END_PROFILE(SMBwritebraw); return(UNIXERROR(ERRHRD,ERRdiskfull)); + } total_written = nwritten; @@ -2358,8 +2452,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, /* we won't return a status if write through is not selected - this follows what WfWg does */ - if (!write_through && total_written==tcount) + END_PROFILE(SMBwritebraw); + if (!write_through && total_written==tcount) { return(-1); + } return(outsize); } @@ -2378,6 +2474,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; + START_PROFILE(SMBwriteunlock); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2387,8 +2484,10 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + END_PROFILE(SMBwriteunlock); return(ERROR(ERRDOS,ERRlock)); + } /* The special X/Open SMB protocol handling of zero length writes is *NOT* done for @@ -2401,11 +2500,15 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz if (lp_syncalways(SNUM(conn))) sync_file(conn,fsp); - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + END_PROFILE(SMBwriteunlock); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) + if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) { + END_PROFILE(SMBwriteunlock); return(ERROR(eclass,ecode)); + } outsize = set_message(outbuf,1,0,True); @@ -2414,6 +2517,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten ) ); + END_PROFILE(SMBwriteunlock); return(outsize); } @@ -2428,10 +2532,13 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; + START_PROFILE(SMBwrite); /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) + if (IS_IPC(conn)) { + END_PROFILE(SMBwrite); return reply_pipe_write(inbuf,outbuf,size,dum_buffsize); + } CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2441,8 +2548,10 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + END_PROFILE(SMBwrite); return(ERROR(ERRDOS,ERRlock)); + } /* X/Open SMB protocol says that if smb_vwv1 is zero then the file size should be extended or @@ -2456,8 +2565,10 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d if (lp_syncalways(SNUM(conn))) sync_file(conn,fsp); - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + END_PROFILE(SMBwrite); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } outsize = set_message(outbuf,1,0,True); @@ -2471,6 +2582,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); + END_PROFILE(SMBwrite); return(outsize); } @@ -2487,17 +2599,22 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng ssize_t nwritten = -1; unsigned int smb_doff = SVAL(inbuf,smb_vwv11); char *data; + START_PROFILE(SMBwriteX); /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) + if (IS_IPC(conn)) { + END_PROFILE(SMBwriteX); return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize); + } CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); CHECK_ERROR(fsp); - if(smb_doff > smb_len(inbuf)) + if(smb_doff > smb_len(inbuf)) { + END_PROFILE(SMBwriteX); return(ERROR(ERRDOS,ERRbadmem)); + } data = smb_base(inbuf) + smb_doff; @@ -2517,14 +2634,17 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if(IVAL(inbuf,smb_vwv12) != 0) { DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) )); + END_PROFILE(SMBwriteX); return(ERROR(ERRDOS,ERRbadaccess)); } #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + END_PROFILE(SMBwriteX); return(ERROR(ERRDOS,ERRlock)); + } /* X/Open SMB protocol says that, unlike SMBwrite if the length is zero then NO truncation is @@ -2535,8 +2655,10 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng else nwritten = write_file(fsp,data,startpos,numtowrite); - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + END_PROFILE(SMBwriteX); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } set_message(outbuf,6,0,True); @@ -2553,6 +2675,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if (lp_syncalways(SNUM(conn)) || write_through) sync_file(conn,fsp); + END_PROFILE(SMBwriteX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2568,6 +2691,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int int mode,umode; int outsize = 0; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBlseek); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2585,7 +2709,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int umode = SEEK_SET; break; } - if((res = conn->vfs_ops.lseek(fsp->fd,startpos,umode)) == -1) { + if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) { /* * Check for the special case where a seek before the start * of the file sets the offset to zero. Added in the CIFS spec, @@ -2597,8 +2721,10 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int if(umode == SEEK_CUR) { - if((current_pos = conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1) + if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) { + END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } current_pos += startpos; @@ -2606,18 +2732,22 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; - if(conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1) + if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) { + END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } current_pos += sbuf.st_size; } if(current_pos < 0) - res = conn->vfs_ops.lseek(fsp->fd,0,SEEK_SET); + res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET); } - if(res == -1) + if(res == -1) { + END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } fsp->pos = res; @@ -2628,6 +2758,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n", fsp->fnum, (double)startpos, (double)res, mode)); + END_PROFILE(SMBlseek); return(outsize); } @@ -2639,6 +2770,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int { int outsize = set_message(outbuf,0,0,True); files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBflush); if (fsp) { CHECK_FSP(fsp,conn); @@ -2652,6 +2784,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int } DEBUG(3,("flush\n")); + END_PROFILE(SMBflush); return(outsize); } @@ -2662,9 +2795,13 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int int reply_exit(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); + int outsize; + START_PROFILE(SMBexit); + outsize = set_message(outbuf,0,0,True); + DEBUG(3,("exit\n")); + END_PROFILE(SMBexit); return(outsize); } @@ -2679,12 +2816,15 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, time_t mtime; int32 eclass = 0, err = 0; files_struct *fsp = NULL; + START_PROFILE(SMBclose); outsize = set_message(outbuf,0,0,True); /* If it's an IPC, pass off to the pipe handler. */ - if (IS_IPC(conn)) + if (IS_IPC(conn)) { + END_PROFILE(SMBclose); return reply_pipe_close(conn, inbuf,outbuf); + } fsp = file_fsp(inbuf,smb_vwv0); @@ -2692,8 +2832,10 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * We can only use CHECK_FSP if we know it's not a directory. */ - if(!fsp || (fsp->conn != conn)) + if(!fsp || (fsp->conn != conn)) { + END_PROFILE(SMBclose); return(ERROR(ERRDOS,ERRbadfid)); + } if(HAS_CACHED_ERROR(fsp)) { eclass = fsp->wbmpx_ptr->wr_errclass; @@ -2740,14 +2882,18 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, if((close_err = close_file(fsp,True)) != 0) { errno = close_err; + END_PROFILE(SMBclose); return (UNIXERROR(ERRHRD,ERRgeneral)); } } /* We have a cached error */ - if(eclass || err) + if(eclass || err) { + END_PROFILE(SMBclose); return(ERROR(eclass,err)); + } + END_PROFILE(SMBclose); return(outsize); } @@ -2767,6 +2913,7 @@ int reply_writeclose(connection_struct *conn, char *data; time_t mtime; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBwriteclose); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2777,9 +2924,11 @@ int reply_writeclose(connection_struct *conn, mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + END_PROFILE(SMBwriteclose); return(ERROR(ERRDOS,ERRlock)); - + } + nwritten = write_file(fsp,data,startpos,numtowrite); set_filetime(conn, fsp->fsp_name,mtime); @@ -2790,17 +2939,21 @@ int reply_writeclose(connection_struct *conn, fsp->fnum, (int)numtowrite, (int)nwritten, conn->num_files_open)); - if (nwritten <= 0) + if (nwritten <= 0) { + END_PROFILE(SMBwriteclose); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } if(close_err != 0) { errno = close_err; + END_PROFILE(SMBwriteclose); return(UNIXERROR(ERRHRD,ERRgeneral)); } outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); + END_PROFILE(SMBwriteclose); return(outsize); } @@ -2816,6 +2969,7 @@ int reply_lock(connection_struct *conn, int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBlock); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2827,18 +2981,22 @@ int reply_lock(connection_struct *conn, fsp->fd, fsp->fnum, (double)offset, (double)count)); if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) { - if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(inbuf, length, -1, 0)) - return -1; - } - return (ERROR(eclass,ecode)); - } + if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, -1, 0)) { + END_PROFILE(SMBlock); + return -1; + } + } + END_PROFILE(SMBlock); + return (ERROR(eclass,ecode)); + } + END_PROFILE(SMBlock); return(outsize); } @@ -2853,6 +3011,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, in int eclass; uint32 ecode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBunlock); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -2860,12 +3019,15 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, in count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); - if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) + if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) { + END_PROFILE(SMBunlock); return (ERROR(eclass,ecode)); + } DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fd, fsp->fnum, (double)offset, (double)count ) ); + END_PROFILE(SMBunlock); return(outsize); } @@ -2878,11 +3040,13 @@ int reply_tdis(connection_struct *conn, { int outsize = set_message(outbuf,0,0,True); uint16 vuid; + START_PROFILE(SMBtdis); vuid = SVAL(inbuf,smb_uid); if (!conn) { DEBUG(4,("Invalid connection in tdis\n")); + END_PROFILE(SMBtdis); return(ERROR(ERRSRV,ERRinvnid)); } @@ -2890,6 +3054,7 @@ int reply_tdis(connection_struct *conn, close_cnum(conn,vuid); + END_PROFILE(SMBtdis); return outsize; } @@ -2905,6 +3070,7 @@ int reply_echo(connection_struct *conn, int seq_num; unsigned int data_len = smb_buflen(inbuf); int outsize = set_message(outbuf,1,data_len,True); + START_PROFILE(SMBecho); data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf))); @@ -2929,6 +3095,7 @@ int reply_echo(connection_struct *conn, smb_echo_count++; + END_PROFILE(SMBecho); return -1; } @@ -2941,14 +3108,18 @@ int reply_printopen(connection_struct *conn, { int outsize = 0; files_struct *fsp; + START_PROFILE(SMBsplopen); - if (!CAN_PRINT(conn)) + if (!CAN_PRINT(conn)) { + END_PROFILE(SMBsplopen); return(ERROR(ERRDOS,ERRnoaccess)); + } /* Open for exclusive use, write only. */ fsp = print_fsp_open(conn,"dos.prn"); if (!fsp) { + END_PROFILE(SMBsplopen); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2958,6 +3129,7 @@ int reply_printopen(connection_struct *conn, DEBUG(3,("openprint fd=%d fnum=%d\n", fsp->fd, fsp->fnum)); + END_PROFILE(SMBsplopen); return(outsize); } @@ -2971,12 +3143,15 @@ int reply_printclose(connection_struct *conn, int outsize = set_message(outbuf,0,0,True); files_struct *fsp = file_fsp(inbuf,smb_vwv0); int close_err = 0; + START_PROFILE(SMBsplclose); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); - if (!CAN_PRINT(conn)) + if (!CAN_PRINT(conn)) { + END_PROFILE(SMBsplclose); return(ERROR(ERRDOS,ERRnoaccess)); + } DEBUG(3,("printclose fd=%d fnum=%d\n", fsp->fd,fsp->fnum)); @@ -2985,9 +3160,11 @@ int reply_printclose(connection_struct *conn, if(close_err != 0) { errno = close_err; + END_PROFILE(SMBsplclose); return(UNIXERROR(ERRHRD,ERRgeneral)); } + END_PROFILE(SMBsplclose); return(outsize); } @@ -3001,13 +3178,16 @@ int reply_printqueue(connection_struct *conn, int outsize = set_message(outbuf,2,3,True); int max_count = SVAL(inbuf,smb_vwv0); int start_index = SVAL(inbuf,smb_vwv1); + START_PROFILE(SMBsplretq); /* we used to allow the client to get the cnum wrong, but that is really quite gross and only worked when there was only one printer - I think we should now only accept it if they get it right (tridge) */ - if (!CAN_PRINT(conn)) + if (!CAN_PRINT(conn)) { + END_PROFILE(SMBsplretq); return(ERROR(ERRDOS,ERRnoaccess)); + } SSVAL(outbuf,smb_vwv0,0); SSVAL(outbuf,smb_vwv1,0); @@ -3054,6 +3234,7 @@ int reply_printqueue(connection_struct *conn, DEBUG(3,("%d entries returned in queue\n",count)); } + END_PROFILE(SMBsplretq); return(outsize); } @@ -3067,9 +3248,12 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ int outsize = set_message(outbuf,0,0,True); char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBsplwr); - if (!CAN_PRINT(conn)) + if (!CAN_PRINT(conn)) { + END_PROFILE(SMBsplwr); return(ERROR(ERRDOS,ERRnoaccess)); + } CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -3078,11 +3262,14 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ numtowrite = SVAL(smb_buf(inbuf),1); data = smb_buf(inbuf) + 3; - if (write_file(fsp,data,-1,numtowrite) != numtowrite) + if (write_file(fsp,data,-1,numtowrite) != numtowrite) { + END_PROFILE(SMBsplwr); return(UNIXERROR(ERRDOS,ERRnoaccess)); - + } + DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); + END_PROFILE(SMBsplwr); return(outsize); } @@ -3121,6 +3308,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring directory; int outsize; + START_PROFILE(SMBmkdir); pstrcpy(directory,smb_buf(inbuf) + 1); @@ -3130,6 +3318,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); + END_PROFILE(SMBmkdir); return(outsize); } @@ -3166,7 +3355,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(dos_to_unix(fullname,False), &st) != 0) + if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname,False), &st) != 0) { ret = True; break; @@ -3179,13 +3368,13 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) ret = True; break; } - if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0) + if(vfs_rmdir(conn,fullname) != 0) { ret = True; break; } } - else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0) + else if(vfs_unlink(conn,fullname) != 0) { ret = True; break; @@ -3203,7 +3392,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) { BOOL ok; - ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0); + ok = (vfs_rmdir(conn,directory) == 0); if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { /* @@ -3250,7 +3439,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(dos_to_unix(fullname, False), &st) != 0) + if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname, False), &st) != 0) break; if(st.st_mode & S_IFDIR) { @@ -3259,15 +3448,15 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) if(recursive_rmdir(conn, fullname) != 0) break; } - if(conn->vfs_ops.rmdir(dos_to_unix(fullname, False)) != 0) + if(vfs_rmdir(conn,fullname) != 0) break; } - else if(conn->vfs_ops.unlink(dos_to_unix(fullname, False)) != 0) + else if(vfs_unlink(conn,fullname) != 0) break; } CloseDir(dirptr); /* Retry the rmdir */ - ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0); + ok = (vfs_rmdir(conn,directory) == 0); } else CloseDir(dirptr); @@ -3293,6 +3482,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int outsize = 0; BOOL ok = False; BOOL bad_path = False; + START_PROFILE(SMBrmdir); pstrcpy(directory,smb_buf(inbuf) + 1); @@ -3313,6 +3503,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBrmdir); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -3320,6 +3511,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG( 3, ( "rmdir %s\n", directory ) ); + END_PROFILE(SMBrmdir); return(outsize); } @@ -3397,7 +3589,7 @@ static BOOL can_rename(char *fname,connection_struct *conn) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); return(True); @@ -3529,14 +3721,14 @@ int rename_internals(connection_struct *conn, */ if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !conn->vfs_ops.rename(zdirectory, + !conn->vfs_ops.rename(conn,zdirectory, dos_to_unix(newname,False))) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && !vfs_file_exist(conn,newname,NULL) && - !conn->vfs_ops.rename(zdirectory, + !conn->vfs_ops.rename(conn,zdirectory, dos_to_unix(newname,False))) count++; } @@ -3595,7 +3787,7 @@ int rename_internals(connection_struct *conn, continue; } - if (!conn->vfs_ops.rename(dos_to_unix(fname,False), + if (!conn->vfs_ops.rename(conn,dos_to_unix(fname,False), dos_to_unix(destname,False))) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); @@ -3628,6 +3820,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in int outsize = 0; pstring name; pstring newname; + START_PROFILE(SMBmv); pstrcpy(name,smb_buf(inbuf) + 1); pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); @@ -3650,6 +3843,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in outsize = set_message(outbuf,0,0,True); } + END_PROFILE(SMBmv); return(outsize); } @@ -3701,7 +3895,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(conn->vfs_ops.lseek(fsp2->fd,0,SEEK_END) == -1) { + if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", strerror(errno) )); /* @@ -3751,6 +3945,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path1 = False; BOOL bad_path2 = False; BOOL rc = True; + START_PROFILE(SMBcopy); *directory = *mask = 0; @@ -3762,6 +3957,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (tid2 != conn->cnum) { /* can't currently handle inter share copies XXXX */ DEBUG(3,("Rejecting inter-share copy\n")); + END_PROFILE(SMBcopy); return(ERROR(ERRSRV,ERRinvdevice)); } @@ -3774,16 +3970,19 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, target_is_directory = vfs_directory_exist(conn,False,NULL); if ((flags&1) && target_is_directory) { + END_PROFILE(SMBcopy); return(ERROR(ERRDOS,ERRbadfile)); } if ((flags&2) && !target_is_directory) { + END_PROFILE(SMBcopy); return(ERROR(ERRDOS,ERRbadpath)); } if ((flags&(1<<5)) && vfs_directory_exist(conn,name,NULL)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); + END_PROFILE(SMBcopy); return(ERROR(ERRSRV,ERRerror)); } @@ -3819,6 +4018,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, count,target_is_directory,&err)) count++; if(!count && err) { errno = err; + END_PROFILE(SMBcopy); return(UNIXERROR(ERRHRD,ERRgeneral)); } if (!count) exists = vfs_file_exist(conn,directory,NULL); @@ -3859,18 +4059,21 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if(err) { /* Error on close... */ errno = err; + END_PROFILE(SMBcopy); return(UNIXERROR(ERRHRD,ERRgeneral)); } - if (exists) + if (exists) { + END_PROFILE(SMBcopy); return(ERROR(ERRDOS,error)); - else + } else { if((errno == ENOENT) && (bad_path1 || bad_path2)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBcopy); return(UNIXERROR(ERRDOS,error)); } } @@ -3878,6 +4081,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,count); + END_PROFILE(SMBcopy); return(outsize); } @@ -3890,10 +4094,13 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int outsize = 0; BOOL ok = False; pstring newdir; + START_PROFILE(pathworks_setdir); snum = SNUM(conn); - if (!CAN_SETDIR(snum)) + if (!CAN_SETDIR(snum)) { + END_PROFILE(pathworks_setdir); return(ERROR(ERRDOS,ERRnoaccess)); + } pstrcpy(newdir,smb_buf(inbuf) + 1); strlower(newdir); @@ -3907,14 +4114,17 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } } - if (!ok) + if (!ok) { + END_PROFILE(pathworks_setdir); return(ERROR(ERRDOS,ERRbadpath)); + } outsize = set_message(outbuf,0,0,True); CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh); DEBUG(3,("setdir %s\n", newdir)); + END_PROFILE(pathworks_setdir); return(outsize); } @@ -4026,6 +4236,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, int eclass=0, dummy1; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; BOOL err; + START_PROFILE(SMBlockingX); CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); @@ -4050,10 +4261,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* if this is a pure oplock break request then don't send a reply */ - if (num_locks == 0 && num_ulocks == 0) + if (num_locks == 0 && num_ulocks == 0) { + END_PROFILE(SMBlockingX); return -1; - else + } else { + END_PROFILE(SMBlockingX); return ERROR(ERRDOS,ERRlock); + } } if (remove_oplock(fsp) == False) { @@ -4069,6 +4283,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); if(CVAL(inbuf,smb_vwv0) != 0xff) DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", (unsigned int)CVAL(inbuf,smb_vwv0) )); + END_PROFILE(SMBlockingX); return -1; } } @@ -4082,14 +4297,18 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* * There is no error code marked "stupid client bug".... :-). */ - if(err) + if(err) { + END_PROFILE(SMBlockingX); return ERROR(ERRDOS,ERRnoaccess); + } DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); - if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode)) + if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode)) { + END_PROFILE(SMBlockingX); return ERROR(eclass,ecode); + } } /* Setup the timeout in seconds. */ @@ -4108,8 +4327,10 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* * There is no error code marked "stupid client bug".... :-). */ - if(err) + if(err) { + END_PROFILE(SMBlockingX); return ERROR(ERRDOS,ERRnoaccess); + } DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); @@ -4122,8 +4343,10 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) + if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) { + END_PROFILE(SMBlockingX); return -1; + } } break; } @@ -4144,11 +4367,14 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* * There is no error code marked "stupid client bug".... :-). */ - if(err) + if(err) { + END_PROFILE(SMBlockingX); return ERROR(ERRDOS,ERRnoaccess); + } do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } + END_PROFILE(SMBlockingX); return ERROR(eclass,ecode); } @@ -4157,6 +4383,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); + END_PROFILE(SMBlockingX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -4176,10 +4403,13 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, size_t tcount; int pad; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBreadBmpx); /* this function doesn't seem to work - disable by default */ - if (!lp_readbmpx()) + if (!lp_readbmpx()) { + END_PROFILE(SMBreadBmpx); return(ERROR(ERRSRV,ERRuseSTD)); + } outsize = set_message(outbuf,8,0,True); @@ -4199,9 +4429,11 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + END_PROFILE(SMBreadBmpx); return(ERROR(ERRDOS,ERRlock)); - + } + do { size_t N = MIN(max_per_packet,tcount-total_read); @@ -4226,6 +4458,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, } while (total_read < (ssize_t)tcount); + END_PROFILE(SMBreadBmpx); return(-1); } @@ -4244,6 +4477,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int smb_doff; char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBwriteBmpx); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -4261,16 +4495,20 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { + END_PROFILE(SMBwriteBmpx); return(ERROR(ERRDOS,ERRlock)); + } nwritten = write_file(fsp,data,startpos,numtowrite); if(lp_syncalways(SNUM(conn)) || write_through) sync_file(conn,fsp); - if(nwritten < (ssize_t)numtowrite) + if(nwritten < (ssize_t)numtowrite) { + END_PROFILE(SMBwriteBmpx); return(UNIXERROR(ERRHRD,ERRdiskfull)); + } /* If the maximum to be written to this file is greater than what we just wrote then set @@ -4286,6 +4524,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, if(!wbms) { DEBUG(0,("Out of memory in reply_readmpx\n")); + END_PROFILE(SMBwriteBmpx); return(ERROR(ERRSRV,ERRnoresource)); } wbms->wr_mode = write_through; @@ -4318,6 +4557,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, SSVAL(outbuf,smb_vwv0,nwritten); } + END_PROFILE(SMBwriteBmpx); return(outsize); } @@ -4338,6 +4578,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz write_bmpx_struct *wbms; BOOL send_response = False; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBwriteBs); CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -4355,15 +4596,20 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz /* This fd should have an auxiliary struct attached, check that it does */ wbms = fsp->wbmpx_ptr; - if(!wbms) return(-1); + if(!wbms) { + END_PROFILE(SMBwriteBs); + return(-1); + } /* If write through is set we can return errors, else we must cache them */ write_through = wbms->wr_mode; /* Check for an earlier error */ - if(wbms->wr_discard) + if(wbms->wr_discard) { + END_PROFILE(SMBwriteBs); return -1; /* Just discard the packet */ + } nwritten = write_file(fsp,data,startpos,numtowrite); @@ -4377,8 +4623,10 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz /* We are returning an error - we can delete the aux struct */ if (wbms) free((char *)wbms); fsp->wbmpx_ptr = NULL; + END_PROFILE(SMBwriteBs); return(ERROR(ERRHRD,ERRdiskfull)); } + END_PROFILE(SMBwriteBs); return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); } @@ -4398,9 +4646,12 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz fsp->wbmpx_ptr = NULL; } - if(send_response) + if(send_response) { + END_PROFILE(SMBwriteBs); return(outsize); + } + END_PROFILE(SMBwriteBs); return(-1); } @@ -4414,6 +4665,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, struct utimbuf unix_times; int outsize = 0; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBsetattrE); outsize = set_message(outbuf,0,0,True); @@ -4439,6 +4691,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); } + END_PROFILE(SMBsetattrE); return(outsize); } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) @@ -4448,12 +4701,15 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, } /* Set the date on this file */ - if(file_utime(conn, fsp->fsp_name, &unix_times)) + if(file_utime(conn, fsp->fsp_name, &unix_times)) { + END_PROFILE(SMBsetattrE); return(ERROR(ERRDOS,ERRnoaccess)); + } DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); + END_PROFILE(SMBsetattrE); return(outsize); } @@ -4468,6 +4724,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = 0; int mode; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBgetattrE); outsize = set_message(outbuf,11,0,True); @@ -4475,8 +4732,10 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_ERROR(fsp); /* Do an fstat on this file */ - if(fsp->conn->vfs_ops.fstat(fsp->fd, &sbuf)) + if(vfs_fstat(fsp,fsp->fd, &sbuf)) { + END_PROFILE(SMBgetattrE); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } mode = dos_mode(conn,fsp->fsp_name,&sbuf); @@ -4500,6 +4759,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum)); + END_PROFILE(SMBgetattrE); return(outsize); } #undef OLD_NTDOMAIN diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e82bbefa5a..e1e0fde32f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -481,46 +481,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups); - /* - * Now initialize the vfs layer. - */ - - conn->vfs_conn = (struct vfs_connection_struct *) - malloc(sizeof(struct vfs_connection_struct)); - - if (conn->vfs_conn == NULL) { - DEBUG(0, ("No memory to create vfs_connection_struct")); - return NULL; - } - - ZERO_STRUCTP(conn->vfs_conn); - - /* Copy across relevant data from connection struct */ - - conn->vfs_conn->printer = conn->printer; - conn->vfs_conn->ipc = conn->ipc; - conn->vfs_conn->read_only = conn->read_only; - conn->vfs_conn->admin_user = conn->admin_user; - - pstrcpy(conn->vfs_conn->dirpath, conn->dirpath); - pstrcpy(conn->vfs_conn->connectpath, conn->connectpath); - pstrcpy(conn->vfs_conn->origpath, conn->origpath); - - pstrcpy(conn->vfs_conn->service, service); - pstrcpy(conn->vfs_conn->user, conn->user); - - conn->vfs_conn->uid = conn->uid; - conn->vfs_conn->gid = conn->gid; - conn->vfs_conn->ngroups = conn->ngroups; - if (conn->vfs_conn->ngroups != 0) { - conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, - conn->ngroups * sizeof(gid_t)); - } else { - conn->vfs_conn->groups = NULL; - } - - conn->vfs_conn->nt_user_token = dup_nt_token(conn->nt_user_token); - /* Initialise VFS function pointers */ if (*lp_vfsobj(SNUM(conn))) { @@ -646,7 +606,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* Invoke VFS make connection hook */ if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn->vfs_conn, service, user) < 0) + if (conn->vfs_ops.connect(conn, service, user) < 0) return NULL; } @@ -671,7 +631,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) /* Call VFS disconnect hook */ - conn->vfs_ops.disconnect(); + conn->vfs_ops.disconnect(conn); } diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 7b2916bb9a..b66c5e2fe9 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -214,7 +214,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, scp = (stat_cache_entry *)(hash_elem->value); global_stat_cache_hits++; trans_name = scp->names+scp->name_len+1; - if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { + if(conn->vfs_ops.stat(conn,dos_to_unix(trans_name,False), pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2366fceae7..7df1c09fa0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -251,7 +251,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { close_file(fsp,False); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -407,7 +407,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) + if (conn->vfs_ops.stat(conn,dos_to_unix(pathreal,False),&sbuf) != 0) { /* Needed to show the msdfs symlinks as directories */ if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) @@ -1112,7 +1112,7 @@ static int call_trans2qfsinfo(connection_struct *conn, DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(conn->vfs_ops.stat(".",&st)!=0) { + if(conn->vfs_ops.stat(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return (ERROR(ERRSRV,ERRinvdevice)); } @@ -1126,7 +1126,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; - conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); SIVAL(pdata,l1_cSectorUnit,bsize/512); SIVAL(pdata,l1_cUnit,dsize); @@ -1208,7 +1208,7 @@ static int call_trans2qfsinfo(connection_struct *conn, { SMB_BIG_UINT dfree,dsize,bsize; data_len = 24; - conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize); + conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); SBIG_UINT(pdata,0,dsize); SBIG_UINT(pdata,8,dfree); SIVAL(pdata,16,bsize/512); @@ -1308,7 +1308,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { + (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1328,11 +1328,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = fsp->conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1) + if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); delete_pending = fsp->delete_on_close; @@ -1350,7 +1350,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { + (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1590,7 +1590,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&st); if (!check_name(fname,conn) || - (!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) { + (!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1609,7 +1609,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; fd = fsp->fd; - if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) { + if (fsp->conn->vfs_ops.fstat(fsp,fd,&st) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1630,7 +1630,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) { + if(!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st)!=0) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1974,11 +1974,11 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) fname, (double)size )); if (fd == -1) { - fd = conn->vfs_ops.open(dos_to_unix(fname,False),O_RDWR,0); + fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),O_RDWR,0); if (fd == -1) return(UNIXERROR(ERRDOS,ERRbadpath)); set_filelen(fd, size); /* tpot vfs */ - conn->vfs_ops.close(fd); + conn->vfs_ops.close(fsp,fd); } else { set_filelen(fd, size); /* tpot vfs */ } diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index a564ec9ee5..d32f1cfaae 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -357,16 +357,16 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) */ if ((fsp->is_directory || fsp->fd == -1) && fsp->conn->vfs_ops.get_nt_acl) - return fsp->conn->vfs_ops.get_nt_acl(dos_to_unix(fsp->fsp_name, False), ppdesc); + return fsp->conn->vfs_ops.get_nt_acl(fsp->conn,dos_to_unix(fsp->fsp_name, False), ppdesc); else if (fsp->conn->vfs_ops.fget_nt_acl) - return fsp->conn->vfs_ops.fget_nt_acl(fsp->fd, ppdesc); + return fsp->conn->vfs_ops.fget_nt_acl(fsp,fsp->fd, ppdesc); if(fsp->is_directory || fsp->fd == -1) { if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; } } else { - if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if(fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { return 0; } } @@ -467,9 +467,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if ((fsp->is_directory || fsp->fd == -1) && fsp->conn->vfs_ops.set_nt_acl) - return fsp->conn->vfs_ops.set_nt_acl(dos_to_unix(fsp->fsp_name, False), security_info_sent, psd); + return fsp->conn->vfs_ops.set_nt_acl(conn,dos_to_unix(fsp->fsp_name, False), security_info_sent, psd); else if (fsp->conn->vfs_ops.fset_nt_acl) - return fsp->conn->vfs_ops.fset_nt_acl(fsp->fd, security_info_sent, psd); + return fsp->conn->vfs_ops.fset_nt_acl(fsp,fsp->fd, security_info_sent, psd); /* * Get the current state of the file. @@ -479,7 +479,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - if(conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) + if(conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) return False; } @@ -524,7 +524,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(fsp->fd == -1) ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); else - ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); + ret = conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf); if(ret != 0) return False; @@ -570,7 +570,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)perms )); - if(conn->vfs_ops.chmod(dos_to_unix(fsp->fsp_name, False), perms) == -1) { + if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), perms) == -1) { DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)perms, strerror(errno) )); return False; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index d19be7fb71..7495a76687 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -29,8 +29,7 @@ is sure to try and execute them. These stubs are used to prevent this possibility. */ -int vfswrap_dummy_connect(struct vfs_connection_struct *conn, char *service, - char *user) +int vfswrap_dummy_connect(connection_struct *conn, char *service, char *user) { return 0; /* Return >= 0 for success */ } @@ -41,7 +40,7 @@ void vfswrap_dummy_disconnect(void) /* Disk operations */ -SMB_BIG_UINT vfswrap_disk_free(char *path, BOOL small_query, SMB_BIG_UINT *bsize, +SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { SMB_BIG_UINT result; @@ -60,7 +59,7 @@ SMB_BIG_UINT vfswrap_disk_free(char *path, BOOL small_query, SMB_BIG_UINT *bsize /* Directory operations */ -DIR *vfswrap_opendir(char *fname) +DIR *vfswrap_opendir(connection_struct *conn, char *fname) { DIR *result; @@ -74,7 +73,7 @@ DIR *vfswrap_opendir(char *fname) return result; } -struct dirent *vfswrap_readdir(DIR *dirp) +struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) { struct dirent *result; @@ -88,7 +87,7 @@ struct dirent *vfswrap_readdir(DIR *dirp) return result; } -int vfswrap_mkdir(char *path, mode_t mode) +int vfswrap_mkdir(connection_struct *conn, char *path, mode_t mode) { int result; @@ -102,7 +101,7 @@ int vfswrap_mkdir(char *path, mode_t mode) return result; } -int vfswrap_rmdir(char *path) +int vfswrap_rmdir(connection_struct *conn, char *path) { int result; @@ -116,7 +115,7 @@ int vfswrap_rmdir(char *path) return result; } -int vfswrap_closedir(DIR *dirp) +int vfswrap_closedir(connection_struct *conn, DIR *dirp) { int result; @@ -132,7 +131,7 @@ int vfswrap_closedir(DIR *dirp) /* File operations */ -int vfswrap_open(char *fname, int flags, mode_t mode) +int vfswrap_open(connection_struct *conn, char *fname, int flags, mode_t mode) { int result; @@ -146,7 +145,7 @@ int vfswrap_open(char *fname, int flags, mode_t mode) return result; } -int vfswrap_close(int fd) +int vfswrap_close(files_struct *fsp, int fd) { int result; @@ -154,7 +153,7 @@ int vfswrap_close(int fd) return result; } -ssize_t vfswrap_read(int fd, char *data, size_t n) +ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n) { ssize_t result; @@ -168,7 +167,7 @@ ssize_t vfswrap_read(int fd, char *data, size_t n) return result; } -ssize_t vfswrap_write(int fd, char *data, size_t n) +ssize_t vfswrap_write(files_struct *fsp, int fd, char *data, size_t n) { ssize_t result; @@ -182,7 +181,7 @@ ssize_t vfswrap_write(int fd, char *data, size_t n) return result; } -SMB_OFF_T vfswrap_lseek(int filedes, SMB_OFF_T offset, int whence) +SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) { SMB_OFF_T result; @@ -190,7 +189,7 @@ SMB_OFF_T vfswrap_lseek(int filedes, SMB_OFF_T offset, int whence) return result; } -int vfswrap_rename(char *old, char *new) +int vfswrap_rename(connection_struct *conn, char *old, char *new) { int result; @@ -204,7 +203,7 @@ int vfswrap_rename(char *old, char *new) return result; } -int vfswrap_fsync(int fd) +int vfswrap_fsync(files_struct *fsp, int fd) { #ifdef HAVE_FSYNC return fsync(fd); @@ -213,7 +212,7 @@ int vfswrap_fsync(int fd) #endif } -int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) +int vfswrap_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *sbuf) { int result; @@ -227,7 +226,7 @@ int vfswrap_stat(char *fname, SMB_STRUCT_STAT *sbuf) return result; } -int vfswrap_fstat(int fd, SMB_STRUCT_STAT *sbuf) +int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) { int result; @@ -241,8 +240,7 @@ int vfswrap_fstat(int fd, SMB_STRUCT_STAT *sbuf) return result; } -int vfswrap_lstat(char *path, - SMB_STRUCT_STAT *sbuf) +int vfswrap_lstat(connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf) { int result; @@ -256,7 +254,7 @@ int vfswrap_lstat(char *path, return result; } -int vfswrap_unlink(char *path) +int vfswrap_unlink(connection_struct *conn, char *path) { int result; @@ -270,7 +268,7 @@ int vfswrap_unlink(char *path) return result; } -int vfswrap_chmod(char *path, mode_t mode) +int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) { int result; @@ -284,7 +282,7 @@ int vfswrap_chmod(char *path, mode_t mode) return result; } -int vfswrap_chown(char *path, uid_t uid, gid_t gid) +int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) { int result; @@ -298,7 +296,7 @@ int vfswrap_chown(char *path, uid_t uid, gid_t gid) return result; } -int vfswrap_chdir(char *path) +int vfswrap_chdir(connection_struct *conn, char *path) { #ifdef VFS_CHECK_NULL if (path == NULL) { @@ -309,7 +307,7 @@ int vfswrap_chdir(char *path) return chdir(path); } -char *vfswrap_getwd(char *path) +char *vfswrap_getwd(connection_struct *conn, char *path) { #ifdef VFS_CHECK_NULL if (path == NULL) { @@ -320,7 +318,7 @@ char *vfswrap_getwd(char *path) return sys_getwd(path); } -int vfswrap_utime(char *path, struct utimbuf *times) +int vfswrap_utime(connection_struct *conn, char *path, struct utimbuf *times) { int result; @@ -334,7 +332,7 @@ int vfswrap_utime(char *path, struct utimbuf *times) return result; } -int vfswrap_ftruncate(int fd, SMB_OFF_T offset) +int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T offset) { int result; @@ -342,7 +340,7 @@ int vfswrap_ftruncate(int fd, SMB_OFF_T offset) return result; } -BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { return fcntl_lock(fd, op, offset, count,type); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 4a4b1b2cfa..91172401bc 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -83,7 +83,7 @@ int vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); - memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(conn->vfs_ops)); + memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops)); return True; } @@ -94,7 +94,6 @@ int vfs_init_default(connection_struct *conn) #ifdef HAVE_LIBDL BOOL vfs_init_custom(connection_struct *conn) { - void *handle; struct vfs_ops *ops, *(*fptr)(struct vfs_options *options); DEBUG(3, ("Initialising custom vfs hooks from %s\n", @@ -102,19 +101,15 @@ BOOL vfs_init_custom(connection_struct *conn) /* Open object file */ - handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL); - conn->vfs_conn->dl_handle = handle; - - if (!handle) { - DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), - dlerror())); - return False; + if ((conn->dl_handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { + DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); + return False; } /* Get handle on vfs_init() symbol */ fptr = (struct vfs_ops *(*)(struct vfs_options *)) - dlsym(handle, "vfs_init"); + dlsym(conn->dl_handle, "vfs_init"); if (fptr == NULL) { DEBUG(0, ("No vfs_init() symbol found in %s\n", @@ -133,7 +128,7 @@ BOOL vfs_init_custom(connection_struct *conn) There's probably a neater way to do this then a whole bunch of if statements. */ - memcpy(&conn->vfs_ops, ops, sizeof(conn->vfs_ops)); + memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); if (conn->vfs_ops.connect == NULL) { conn->vfs_ops.connect = default_vfs_ops.connect; @@ -265,16 +260,16 @@ BOOL vfs_init_custom(connection_struct *conn) int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st) { - return(conn->vfs_ops.stat(dos_to_unix(fname,False),st)); + return(conn->vfs_ops.stat(conn, dos_to_unix(fname,False),st)); } /******************************************************************* vfs fstat wrapper that calls dos_to_unix. ********************************************************************/ -int vfs_fstat(connection_struct *conn, int fd, SMB_STRUCT_STAT *st) +int vfs_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *st) { - return(conn->vfs_ops.fstat(fd,st)); + return(fsp->conn->vfs_ops.fstat(fsp,fd,st)); } /******************************************************************* @@ -310,7 +305,7 @@ int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode) SMB_STRUCT_STAT sbuf; pstrcpy(name,dos_to_unix(fname,False)); /* paranoia copy */ - if(!(ret=conn->vfs_ops.mkdir(name,mode))) { + if(!(ret=conn->vfs_ops.mkdir(conn,name,mode))) { /* * Check if high bits should have been set, * then (if bits are missing): add them. @@ -323,13 +318,22 @@ int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode) return ret; } +/******************************************************************* + vfs rmdir wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_rmdir(connection_struct *conn, char *fname) +{ + return(conn->vfs_ops.rmdir(conn,dos_to_unix(fname,False))); +} + /******************************************************************* vfs Unlink wrapper that calls dos_to_unix. ********************************************************************/ int vfs_unlink(connection_struct *conn, char *fname) { - return(conn->vfs_ops.unlink(dos_to_unix(fname,False))); + return(conn->vfs_ops.unlink(conn,dos_to_unix(fname,False))); } /******************************************************************* @@ -338,7 +342,7 @@ int vfs_unlink(connection_struct *conn, char *fname) int vfs_chmod(connection_struct *conn, char *fname,mode_t mode) { - return(conn->vfs_ops.chmod(dos_to_unix(fname,False), mode)); + return(conn->vfs_ops.chmod(conn,dos_to_unix(fname,False), mode)); } /******************************************************************* @@ -347,7 +351,7 @@ int vfs_chmod(connection_struct *conn, char *fname,mode_t mode) int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid) { - return(conn->vfs_ops.chown(dos_to_unix(fname,False), uid, gid)); + return(conn->vfs_ops.chown(conn,dos_to_unix(fname,False), uid, gid)); } /******************************************************************* @@ -356,7 +360,7 @@ int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid) int vfs_chdir(connection_struct *conn, char *fname) { - return(conn->vfs_ops.chdir(dos_to_unix(fname,False))); + return(conn->vfs_ops.chdir(conn,dos_to_unix(fname,False))); } /******************************************************************* @@ -366,7 +370,7 @@ int vfs_chdir(connection_struct *conn, char *fname) char *vfs_getwd(connection_struct *conn, char *unix_path) { char *wd; - wd = conn->vfs_ops.getwd(unix_path); + wd = conn->vfs_ops.getwd(conn,unix_path); if (wd) unix_to_dos(wd, True); return wd; @@ -400,7 +404,7 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) while (total < N) { - ret = fsp->conn->vfs_ops.write(fsp->fd,buffer + total,N - total); + ret = fsp->conn->vfs_ops.write(fsp,fsp->fd,buffer + total,N - total); if (ret == -1) return -1; if (ret == 0) return total; @@ -477,16 +481,14 @@ SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, if (s > ret) { ret += in_fsp ? - in_fsp->conn->vfs_ops.read(in_fsp->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); + in_fsp->conn->vfs_ops.read(in_fsp,in_fsp->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); } - if (ret > 0) - { - if (out_fsp) { - ret2 = out_fsp->conn->vfs_ops.write(out_fsp->fd,buf1,ret); - } else { - ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret; - } + if (ret > 0) { + if (out_fsp) + ret2 = out_fsp->conn->vfs_ops.write(out_fsp,out_fsp->fd,buf1,ret); + else + ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret; } if (ret2 > 0) total += ret2; @@ -513,7 +515,7 @@ char *vfs_readdirname(connection_struct *conn, void *p) if (!p) return(NULL); - ptr = (struct dirent *)conn->vfs_ops.readdir(p); + ptr = (struct dirent *)conn->vfs_ops.readdir(conn,p); if (!ptr) return(NULL); -- cgit From 14a8906e8ca491f3c7aa413daab1eaff29dad576 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 03:41:48 +0000 Subject: Inlined many of the vfs_XXX calls as macros for speed. Jeremy. (This used to be commit 0811d080abd374f47c7c3c8a1ef007e443e5b79c) --- source3/smbd/vfs.c | 63 ------------------------------------------------------ 1 file changed, 63 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 91172401bc..6b1b5ed22d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -254,24 +254,6 @@ BOOL vfs_init_custom(connection_struct *conn) } #endif -/******************************************************************* - vfs stat wrapper that calls dos_to_unix. -********************************************************************/ - -int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st) -{ - return(conn->vfs_ops.stat(conn, dos_to_unix(fname,False),st)); -} - -/******************************************************************* - vfs fstat wrapper that calls dos_to_unix. -********************************************************************/ - -int vfs_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *st) -{ - return(fsp->conn->vfs_ops.fstat(fsp,fd,st)); -} - /******************************************************************* Check if directory exists. ********************************************************************/ @@ -318,51 +300,6 @@ int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode) return ret; } -/******************************************************************* - vfs rmdir wrapper that calls dos_to_unix. -********************************************************************/ - -int vfs_rmdir(connection_struct *conn, char *fname) -{ - return(conn->vfs_ops.rmdir(conn,dos_to_unix(fname,False))); -} - -/******************************************************************* - vfs Unlink wrapper that calls dos_to_unix. -********************************************************************/ - -int vfs_unlink(connection_struct *conn, char *fname) -{ - return(conn->vfs_ops.unlink(conn,dos_to_unix(fname,False))); -} - -/******************************************************************* - vfs chmod wrapper that calls dos_to_unix. -********************************************************************/ - -int vfs_chmod(connection_struct *conn, char *fname,mode_t mode) -{ - return(conn->vfs_ops.chmod(conn,dos_to_unix(fname,False), mode)); -} - -/******************************************************************* - vfs chown wrapper that calls dos_to_unix. -********************************************************************/ - -int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid) -{ - return(conn->vfs_ops.chown(conn,dos_to_unix(fname,False), uid, gid)); -} - -/******************************************************************* - A wrapper for vfs_chdir(). -********************************************************************/ - -int vfs_chdir(connection_struct *conn, char *fname) -{ - return(conn->vfs_ops.chdir(conn,dos_to_unix(fname,False))); -} - /******************************************************************* vfs getwd wrapper that calls dos_to_unix. ********************************************************************/ -- cgit From 08657e539e4cd4105057a9c12db30dbe4bbfcb1d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 6 Oct 2000 04:36:05 +0000 Subject: global_myname is actually a pstring. (This used to be commit e451fd346105d5d34354ff9141d445b5f1a82e0a) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 54bfa3155b..dafbe2258f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -37,7 +37,7 @@ extern int DEBUGLEVEL; extern fstring local_machine; -extern fstring global_myname; +extern pstring global_myname; extern fstring global_myworkgroup; #define NERR_Success 0 -- cgit From ba00796e6dd13b87b7988a98e532676d9eab702c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 18:13:52 +0000 Subject: Herb's warning fixes. Also the POSIX locking fix. We now use our own vfs layer to do get/set acl calls (hurrah!). Jeremy. (This used to be commit dfe77c7046cbd65ee52aea7439f21503c1eac41d) --- source3/smbd/fileio.c | 55 +++++++---------------- source3/smbd/reply.c | 2 +- source3/smbd/statcache.c | 33 +++----------- source3/smbd/unix_acls.c | 18 -------- source3/smbd/vfs-wrap.c | 111 ++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/vfs.c | 80 +++++++++++++++++----------------- 6 files changed, 169 insertions(+), 130 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index b8a0585d90..bb7ab46baa 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -83,9 +83,7 @@ BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) memcpy(data, wcp->data + (pos - wcp->offset), n); -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_read_hits); -#endif + DO_PROFILE_INC(writecache_read_hits); return True; } @@ -183,9 +181,9 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) } #ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_total_writes); + DO_PROFILE_INC(writecache_total_writes); if (!fsp->oplock_type) { - INC_PROFILE_COUNT(writecache_non_oplock_writes); + DO_PROFILE_INC(writecache_non_oplock_writes); } #endif @@ -296,9 +294,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", #endif if(!wcp) { -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_direct_writes); -#endif + DO_PROFILE_INC(writecache_direct_writes); return real_write_file(fsp, data, pos, n); } @@ -350,9 +346,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", pos += data_used; n -= data_used; -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_abutted_writes); -#endif + DO_PROFILE_INC(writecache_abutted_writes); total_written = data_used; write_path = 1; @@ -388,9 +382,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", cache_flush_needed = True; -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_abutted_writes); -#endif + DO_PROFILE_INC(writecache_abutted_writes); total_written = data_used; write_path = 2; @@ -460,9 +452,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", pos += data_used; n -= data_used; -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_abutted_writes); -#endif + DO_PROFILE_INC(writecache_abutted_writes); total_written = data_used; write_path = 3; @@ -494,9 +484,7 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne if ( n <= wcp->alloc_size && n > wcp->data_size) { cache_flush_needed = True; } else { -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_direct_writes); -#endif + DO_PROFILE_INC(writecache_direct_writes); return real_write_file(fsp, data, pos, n); } @@ -525,9 +513,7 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", if (n > wcp->alloc_size ) { if(real_write_file(fsp, data, pos, n) == -1) return -1; -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_direct_writes); -#endif + DO_PROFILE_INC(writecache_direct_writes); return total_written + n; } @@ -538,17 +524,15 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", if (n) { #ifdef WITH_PROFILE if (wcp->data_size) { - INC_PROFILE_COUNT(writecache_abutted_writes); + DO_PROFILE_INC(writecache_abutted_writes); } else { - INC_PROFILE_COUNT(writecache_init_writes); + DO_PROFILE_INC(writecache_init_writes); } #endif memcpy(wcp->data+wcp->data_size, data, n); if (wcp->data_size == 0) { wcp->offset = pos; -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_num_write_caches); -#endif + DO_PROFILE_INC(writecache_num_write_caches); } wcp->data_size += n; DEBUG(9,("cache return %u\n", (unsigned int)n)); @@ -573,9 +557,7 @@ void delete_write_cache(files_struct *fsp) if(!(wcp = fsp->wcp)) return; -#ifdef WITH_PROFILE - DEC_PROFILE_COUNT(writecache_allocated_write_caches); -#endif + DO_PROFILE_DEC(writecache_allocated_write_caches); allocated_write_caches--; SMB_ASSERT(wcp->data_size == 0); @@ -621,9 +603,7 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) } fsp->wcp = wcp; -#ifdef WITH_PROFILE - INC_PROFILE_COUNT(writecache_allocated_write_caches); -#endif + DO_PROFILE_INC(writecache_allocated_write_caches); allocated_write_caches++; DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n", @@ -659,17 +639,14 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) data_size = wcp->data_size; wcp->data_size = 0; -#ifdef WITH_PROFILE - DEC_PROFILE_COUNT(writecache_num_write_caches); - INC_PROFILE_COUNT(writecache_flushed_writes[reason]); -#endif + DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]); DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned int)data_size)); #ifdef WITH_PROFILE if(data_size == wcp->alloc_size) - INC_PROFILE_COUNT(writecache_num_perfect_writes); + DO_PROFILE_INC(writecache_num_perfect_writes); #endif return real_write_file(fsp, wcp->data, wcp->offset, data_size); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e64875a805..fd4ff23461 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1034,7 +1034,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok = False; BOOL bad_path = False; SMB_STRUCT_STAT st; - START_PROFILE(SMBchkpth_count); + START_PROFILE(SMBchkpth); pstrcpy(name,smb_buf(inbuf) + 1); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index b66c5e2fe9..8d756a1d46 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -30,28 +30,6 @@ extern BOOL case_sensitive; Stat cache code used in unix_convert. *****************************************************************************/ -static int global_stat_cache_lookups; -static int global_stat_cache_misses; -static int global_stat_cache_hits; - -/**************************************************************************** - Stat cache statistics code. -*****************************************************************************/ - -void print_stat_cache_statistics(void) -{ - double eff; - - if(global_stat_cache_lookups == 0) - return; - - eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; - - DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ -stat cache was %f%% effective.\n", global_stat_cache_lookups, - global_stat_cache_hits, global_stat_cache_misses, eff )); -} - typedef struct { int name_len; char names[2]; /* This is extended via malloc... */ @@ -175,13 +153,14 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, namelen = strlen(name); *start = name; - global_stat_cache_lookups++; + + DO_PROFILE_INC(statcache_lookups); /* * Don't lookup trivial valid directory entries. */ if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - global_stat_cache_misses++; + DO_PROFILE_INC(statcache_misses); return False; } @@ -202,17 +181,17 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, /* * We reached the end of the name - no match. */ - global_stat_cache_misses++; + DO_PROFILE_INC(statcache_misses); return False; } if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) || (strcmp(chk_name, "..") == 0)) { - global_stat_cache_misses++; + DO_PROFILE_INC(statcache_misses); return False; } } else { scp = (stat_cache_entry *)(hash_elem->value); - global_stat_cache_hits++; + DO_PROFILE_INC(statcache_hits); trans_name = scp->names+scp->name_len+1; if(conn->vfs_ops.stat(conn,dos_to_unix(trans_name,False), pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index d32f1cfaae..2e16611b0c 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -352,15 +352,6 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) sid_copy( &group_sid, &global_sid_World); } else { - /* - * If there is a VFS redirect, use it. - */ - - if ((fsp->is_directory || fsp->fd == -1) && fsp->conn->vfs_ops.get_nt_acl) - return fsp->conn->vfs_ops.get_nt_acl(fsp->conn,dos_to_unix(fsp->fsp_name, False), ppdesc); - else if (fsp->conn->vfs_ops.fget_nt_acl) - return fsp->conn->vfs_ops.fget_nt_acl(fsp,fsp->fd, ppdesc); - if(fsp->is_directory || fsp->fd == -1) { if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; @@ -462,15 +453,6 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) SMB_STRUCT_STAT sbuf; BOOL got_dacl = False; - /* - * If there is a VFS redirect, use it. - */ - - if ((fsp->is_directory || fsp->fd == -1) && fsp->conn->vfs_ops.set_nt_acl) - return fsp->conn->vfs_ops.set_nt_acl(conn,dos_to_unix(fsp->fsp_name, False), security_info_sent, psd); - else if (fsp->conn->vfs_ops.fset_nt_acl) - return fsp->conn->vfs_ops.fset_nt_acl(fsp,fsp->fd, security_info_sent, psd); - /* * Get the current state of the file. */ diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 7495a76687..3b8d5eebcc 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -34,7 +34,7 @@ int vfswrap_dummy_connect(connection_struct *conn, char *service, char *user) return 0; /* Return >= 0 for success */ } -void vfswrap_dummy_disconnect(void) +void vfswrap_dummy_disconnect(connection_struct *conn) { } @@ -63,6 +63,8 @@ DIR *vfswrap_opendir(connection_struct *conn, char *fname) { DIR *result; + START_PROFILE(syscall_opendir); + #ifdef VFS_CHECK_NULL if (fname == NULL) { smb_panic("NULL pointer passed to vfswrap_opendir()\n"); @@ -70,6 +72,7 @@ DIR *vfswrap_opendir(connection_struct *conn, char *fname) #endif result = opendir(fname); + END_PROFILE(syscall_opendir); return result; } @@ -77,6 +80,8 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) { struct dirent *result; + START_PROFILE(syscall_readdir); + #ifdef VFS_CHECK_NULL if (dirp == NULL) { smb_panic("NULL pointer passed to vfswrap_readdir()\n"); @@ -84,6 +89,7 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) #endif result = readdir(dirp); + END_PROFILE(syscall_readdir); return result; } @@ -91,6 +97,8 @@ int vfswrap_mkdir(connection_struct *conn, char *path, mode_t mode) { int result; + START_PROFILE(syscall_mkdir); + #ifdef VFS_CHECK_NULL if (path == NULL) { smb_panic("NULL pointer passed to vfswrap_mkdir()\n"); @@ -98,6 +106,7 @@ int vfswrap_mkdir(connection_struct *conn, char *path, mode_t mode) #endif result = mkdir(path, mode); + END_PROFILE(syscall_mkdir); return result; } @@ -105,6 +114,8 @@ int vfswrap_rmdir(connection_struct *conn, char *path) { int result; + START_PROFILE(syscall_rmdir); + #ifdef VFS_CHECK_NULL if (path == NULL) { smb_panic("NULL pointer passed to vfswrap_rmdir()\n"); @@ -112,6 +123,7 @@ int vfswrap_rmdir(connection_struct *conn, char *path) #endif result = rmdir(path); + END_PROFILE(syscall_rmdir); return result; } @@ -119,6 +131,8 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) { int result; + START_PROFILE(syscall_closedir); + #ifdef VFS_CHECK_NULL if (dirp == NULL) { smb_panic("NULL pointer passed to vfswrap_closedir()\n"); @@ -126,6 +140,7 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) #endif result = closedir(dirp); + END_PROFILE(syscall_closedir); return result; } @@ -135,6 +150,8 @@ int vfswrap_open(connection_struct *conn, char *fname, int flags, mode_t mode) { int result; + START_PROFILE(syscall_open); + #ifdef VFS_CHECK_NULL if (fname == NULL) { smb_panic("NULL pointer passed to vfswrap_open()\n"); @@ -142,6 +159,7 @@ int vfswrap_open(connection_struct *conn, char *fname, int flags, mode_t mode) #endif result = sys_open(fname, flags, mode); + END_PROFILE(syscall_open); return result; } @@ -149,7 +167,10 @@ int vfswrap_close(files_struct *fsp, int fd) { int result; + START_PROFILE(syscall_close); + result = close(fd); + END_PROFILE(syscall_close); return result; } @@ -157,6 +178,8 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n) { ssize_t result; + START_PROFILE_BYTES(syscall_read, n); + #ifdef VFS_CHECK_NULL if (data == NULL) { smb_panic("NULL pointer passed to vfswrap_read()\n"); @@ -164,6 +187,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n) #endif result = read(fd, data, n); + END_PROFILE(syscall_read); return result; } @@ -171,6 +195,8 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, char *data, size_t n) { ssize_t result; + START_PROFILE_BYTES(syscall_write, n); + #ifdef VFS_CHECK_NULL if (data == NULL) { smb_panic("NULL pointer passed to vfswrap_write()\n"); @@ -178,6 +204,7 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, char *data, size_t n) #endif result = write(fd, data, n); + END_PROFILE(syscall_write); return result; } @@ -185,7 +212,10 @@ SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int wh { SMB_OFF_T result; + START_PROFILE(syscall_lseek); + result = sys_lseek(filedes, offset, whence); + END_PROFILE(syscall_lseek); return result; } @@ -193,6 +223,8 @@ int vfswrap_rename(connection_struct *conn, char *old, char *new) { int result; + START_PROFILE(syscall_rename); + #ifdef VFS_CHECK_NULL if ((old == NULL) || (new == NULL)) { smb_panic("NULL pointer passed to vfswrap_rename()\n"); @@ -200,13 +232,20 @@ int vfswrap_rename(connection_struct *conn, char *old, char *new) #endif result = rename(old, new); + END_PROFILE(syscall_rename); return result; } int vfswrap_fsync(files_struct *fsp, int fd) { #ifdef HAVE_FSYNC - return fsync(fd); + int result; + + START_PROFILE(syscall_fsync); + + result = fsync(fd); + END_PROFILE(syscall_fsync); + return result; #else return 0; #endif @@ -216,6 +255,8 @@ int vfswrap_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *sbuf) { int result; + START_PROFILE(syscall_stat); + #ifdef VFS_CHECK_NULL if ((fname == NULL) || (sbuf == NULL)) { smb_panic("NULL pointer passed to vfswrap_stat()\n"); @@ -223,6 +264,7 @@ int vfswrap_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *sbuf) #endif result = sys_stat(fname, sbuf); + END_PROFILE(syscall_stat); return result; } @@ -230,6 +272,8 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) { int result; + START_PROFILE(syscall_fstat); + #ifdef VFS_CHECK_NULL if (sbuf == NULL) { smb_panic("NULL pointer passed to vfswrap_fstat()\n"); @@ -237,6 +281,7 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) #endif result = sys_fstat(fd, sbuf); + END_PROFILE(syscall_fstat); return result; } @@ -244,6 +289,8 @@ int vfswrap_lstat(connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf) { int result; + START_PROFILE(syscall_lstat); + #ifdef VFS_CHECK_NULL if ((path == NULL) || (sbuf == NULL)) { smb_panic("NULL pointer passed to vfswrap_lstat()\n"); @@ -251,6 +298,7 @@ int vfswrap_lstat(connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf) #endif result = sys_lstat(path, sbuf); + END_PROFILE(syscall_lstat); return result; } @@ -258,6 +306,8 @@ int vfswrap_unlink(connection_struct *conn, char *path) { int result; + START_PROFILE(syscall_unlink); + #ifdef VFS_CHECK_NULL if (path == NULL) { smb_panic("NULL pointer passed to vfswrap_unlink()\n"); @@ -265,6 +315,7 @@ int vfswrap_unlink(connection_struct *conn, char *path) #endif result = unlink(path); + END_PROFILE(syscall_unlink); return result; } @@ -272,6 +323,8 @@ int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) { int result; + START_PROFILE(syscall_chmod); + #ifdef VFS_CHECK_NULL if (path == NULL) { smb_panic("NULL pointer passed to vfswrap_chmod()\n"); @@ -279,6 +332,7 @@ int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) #endif result = chmod(path, mode); + END_PROFILE(syscall_chmod); return result; } @@ -286,6 +340,8 @@ int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) { int result; + START_PROFILE(syscall_chown); + #ifdef VFS_CHECK_NULL if (path == NULL) { smb_panic("NULL pointer passed to vfswrap_chown()\n"); @@ -293,35 +349,50 @@ int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) #endif result = sys_chown(path, uid, gid); + END_PROFILE(syscall_chown); return result; } int vfswrap_chdir(connection_struct *conn, char *path) { + int result; + + START_PROFILE(syscall_chdir); + #ifdef VFS_CHECK_NULL if (path == NULL) { smb_panic("NULL pointer passed to vfswrap_chdir()\n"); } #endif - return chdir(path); + result = chdir(path); + END_PROFILE(syscall_chdir); + return result; } char *vfswrap_getwd(connection_struct *conn, char *path) { + char *result; + + START_PROFILE(syscall_getwd); + #ifdef VFS_CHECK_NULL if (path == NULL) { smb_panic("NULL pointer passed to vfswrap_getwd()\n"); } #endif - return sys_getwd(path); + result = sys_getwd(path); + END_PROFILE(syscall_getwd); + return result; } int vfswrap_utime(connection_struct *conn, char *path, struct utimbuf *times) { int result; + START_PROFILE(syscall_utime); + #ifdef VFS_CHECK_NULL if ((path == NULL) || (times == NULL)) { smb_panic("NULL pointer passed to vfswrap_utime()\n"); @@ -329,6 +400,7 @@ int vfswrap_utime(connection_struct *conn, char *path, struct utimbuf *times) #endif result = utime(path, times); + END_PROFILE(syscall_utime); return result; } @@ -336,11 +408,40 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T offset) { int result; + START_PROFILE(syscall_ftruncate); + result = sys_ftruncate(fd, offset); + END_PROFILE(syscall_ftruncate); return result; } BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { - return fcntl_lock(fd, op, offset, count,type); + BOOL result; + + START_PROFILE(syscall_fcntl_lock); + + result = fcntl_lock(fd, op, offset, count,type); + END_PROFILE(syscall_fcntl_lock); + return result; +} + +size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) +{ + return get_nt_acl(fsp, ppdesc); +} + +size_t vfswrap_get_nt_acl(files_struct *fsp, char *name, SEC_DESC **ppdesc) +{ + return get_nt_acl(fsp, ppdesc); +} + +BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) +{ + return set_nt_acl(fsp, security_info_sent, psd); +} + +BOOL vfswrap_set_nt_acl(files_struct *fsp, char *name, uint32 security_info_sent, SEC_DESC *psd) +{ + return set_nt_acl(fsp, security_info_sent, psd); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 6b1b5ed22d..467f3e47a2 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -26,8 +26,8 @@ extern int DEBUGLEVEL; /* Some structures to help us initialise the vfs operations table */ struct vfs_syminfo { - char *name; - void *fptr; + char *name; + void *fptr; }; /* Default vfs hooks. WARNING: The order of these initialisers is @@ -36,44 +36,44 @@ struct vfs_syminfo { struct vfs_ops default_vfs_ops = { - /* Disk operations */ - - vfswrap_dummy_connect, - vfswrap_dummy_disconnect, - vfswrap_disk_free, - - /* Directory operations */ - - vfswrap_opendir, - vfswrap_readdir, - vfswrap_mkdir, - vfswrap_rmdir, - vfswrap_closedir, - - /* File operations */ - - vfswrap_open, - vfswrap_close, - vfswrap_read, - vfswrap_write, - vfswrap_lseek, - vfswrap_rename, - vfswrap_fsync, - vfswrap_stat, - vfswrap_fstat, - vfswrap_lstat, - vfswrap_unlink, - vfswrap_chmod, - vfswrap_chown, - vfswrap_chdir, - vfswrap_getwd, - vfswrap_utime, - vfswrap_ftruncate, - vfswrap_lock, - NULL, /* The 4 security descriptor functions are not defined by default. */ - NULL, - NULL, - NULL + /* Disk operations */ + + vfswrap_dummy_connect, + vfswrap_dummy_disconnect, + vfswrap_disk_free, + + /* Directory operations */ + + vfswrap_opendir, + vfswrap_readdir, + vfswrap_mkdir, + vfswrap_rmdir, + vfswrap_closedir, + + /* File operations */ + + vfswrap_open, + vfswrap_close, + vfswrap_read, + vfswrap_write, + vfswrap_lseek, + vfswrap_rename, + vfswrap_fsync, + vfswrap_stat, + vfswrap_fstat, + vfswrap_lstat, + vfswrap_unlink, + vfswrap_chmod, + vfswrap_chown, + vfswrap_chdir, + vfswrap_getwd, + vfswrap_utime, + vfswrap_ftruncate, + vfswrap_lock, + vfswrap_fget_nt_acl, + vfswrap_get_nt_acl, + vfswrap_fset_nt_acl, + vfswrap_set_nt_acl }; /**************************************************************************** -- cgit From 1929bcb89a8a5daf8ff9242324797e5340ec8fe9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 20:34:14 +0000 Subject: Fixed error return messages needed for NTTrans CreateDirectory. This patch allows the standard W2k recursive mkdir to work against Samba. Jeremy. (This used to be commit 947102784360c65d51441457bb54aa28d2b4452d) --- source3/smbd/nttrans.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 86b85ea766..f099583e55 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -796,6 +796,10 @@ int reply_ntcreate_and_X(connection_struct *conn, restore_case_semantics(file_attributes); if(!fsp) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { @@ -856,6 +860,10 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!fsp) { restore_case_semantics(file_attributes); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); } #ifdef EROFS @@ -1220,6 +1228,10 @@ static int call_nt_transact_create(connection_struct *conn, if(!fsp) { restore_case_semantics(file_attributes); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1258,6 +1270,10 @@ static int call_nt_transact_create(connection_struct *conn, if(!fsp) { restore_case_semantics(file_attributes); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); } #ifdef EROFS -- cgit From 11d999f2bc0c841696bc3ea1ddda48524242482c Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Tue, 10 Oct 2000 13:08:55 +0000 Subject: a netlogon enum trust query doesn't have a function_code at end. a sam_user_info_24 doesn't have a uint16 at end samr_create_user also creates the unix account now samr_set_userinfo changes the password. J.F. (This used to be commit 94f4024481fcd0cb6647af1bd4364033be020641) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fd4ff23461..efd18799a2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -494,7 +494,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out Create a UNIX user on demand. ****************************************************************************/ -static int smb_create_user(char *unix_user) +int smb_create_user(char *unix_user) { pstring add_script; int ret; -- cgit From cdb71ca5181aa1e06bebe2fffb02dc39de83645e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 10 Oct 2000 21:52:31 +0000 Subject: Fixes to periodically scan printing.tdb in idle time and occasionally on exit. Needed to fix printing.tdb from groving to 300Mb+ if being driven by smbclient clients that never ask for status... (effective DOS attack :-). Jeremy. (This used to be commit 6581066b93a674fadf6f9b92441428d2cc8b4a02) --- source3/smbd/process.c | 6 ++++++ source3/smbd/server.c | 4 ++++ 2 files changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1599ade12d..9ed83ec88c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -993,6 +993,12 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); */ process_pending_change_notify_queue(t); + /* + * Ensure the print queue tdb doesn't grow too + * big by periodically scanning it. + */ + process_print_queue(t); + /* * Now we are root, check if the log files need pruning. */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4442a1f71f..22a95fdd18 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -422,6 +422,10 @@ void exit_server(char *reason) respond_to_all_remaining_local_messages(); + /* Don't do this on every exit... */ + if (sys_random() % 10) + process_print_queue(time(NULL)); + #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); -- cgit From e9270d61fc8ddaecd8eb1d2c0a9ce8eba13b1194 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Oct 2000 02:04:46 +0000 Subject: Remove lpq as root fix - do this in print_job_start instead as part of print queue length processing. Jeremy. (This used to be commit e85a0fadd8dcf608822819f00f15569713518806) --- source3/smbd/process.c | 6 ------ source3/smbd/server.c | 4 ---- 2 files changed, 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9ed83ec88c..1599ade12d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -993,12 +993,6 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); */ process_pending_change_notify_queue(t); - /* - * Ensure the print queue tdb doesn't grow too - * big by periodically scanning it. - */ - process_print_queue(t); - /* * Now we are root, check if the log files need pruning. */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 22a95fdd18..4442a1f71f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -422,10 +422,6 @@ void exit_server(char *reason) respond_to_all_remaining_local_messages(); - /* Don't do this on every exit... */ - if (sys_random() % 10) - process_print_queue(time(NULL)); - #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); -- cgit From 7c4c781df2ef3d0ef772fdde215c72ded7445ab8 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 11 Oct 2000 04:54:01 +0000 Subject: Remove duplicate group initialisation function. Don't initialise groups twice. (This used to be commit 5375261152b28a65de18e817c75cab79c2f556b8) --- source3/smbd/password.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2f720db9c1..55c7f0709b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -159,27 +159,6 @@ char *validated_domain(uint16 vuid) } -/**************************************************************************** - Initialize the groups a user belongs to. -****************************************************************************/ - -BOOL initialize_groups(char *user, uid_t uid, gid_t gid) -{ - become_root(); - if (initgroups(user,gid) == -1) { - DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); - if (getuid() == 0) { - if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { - DEBUG(0,("This is probably a problem with the account %s\n", user)); - } - } - unbecome_root(); - return False; - } - unbecome_root(); - return True; -} - /**************************************************************************** Create the SID list for this user. ****************************************************************************/ @@ -260,7 +239,6 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, /* Find all the groups this uid is in and store them. Used by become_user() */ initialise_groups(unix_name, uid, gid); - initialize_groups(unix_name, uid, gid); get_current_groups( &vuser->n_groups, &vuser->groups); /* Create an NT_USER_TOKEN struct for this user. */ -- cgit From cbee552bdb1a4692a19667175fbbf090a9597d71 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 11 Oct 2000 04:54:37 +0000 Subject: Don't initialise groups twice. (This used to be commit 15d7f16bdc2ff4f2ae82871eb9f318ba45cf4d1c) --- source3/smbd/service.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e1e0fde32f..6d07562743 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -460,7 +460,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* Find all the groups this uid is in and store them. Used by become_user() */ initialise_groups(conn->user, conn->uid, conn->gid); - initialize_groups(conn->user, conn->uid, conn->gid); get_current_groups(&conn->ngroups,&conn->groups); /* check number of connections */ -- cgit From 8719c27726d3412edd0781beb956f48f76a62fb6 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 11 Oct 2000 05:31:39 +0000 Subject: changes to sync with 2.2. tree .cvsignore remove config.h - not in this directory include/profile.h profile changes lib/messages.c added message to return debug level libsmb/clierror.c cast to get rid of compiler warning libsmb/smbencrypt.c cast to get rid of compiler warning profile/profile.c add flush profile stats changes for profile struct rpc_parse/parse_samr.c fix for compiler warning rpc_server/srv_samr.c cast to get rid of compiler warning smbd/ipc.c profile stats message.c profile stats smbd/negprot.c profile stats smbd/nttrans.c profile stats smbd/trans2.c profile stats utils/smbcontrol.c new flush stats command (This used to be commit bbb24daa25dca4e4b6b1f8942cd84ee3aa1bed8e) --- source3/smbd/ipc.c | 14 +++++++++-- source3/smbd/message.c | 24 +++++++++++++++--- source3/smbd/negprot.c | 2 ++ source3/smbd/nttrans.c | 66 ++++++++++++++++++++++++++++++++++++++++++++------ source3/smbd/trans2.c | 47 +++++++++++++++++++++++++++++++---- 5 files changed, 134 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a8c1502e94..5ade667209 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -374,6 +374,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int int dscnt = SVAL(inbuf,smb_vwv11); int dsoff = SVAL(inbuf,smb_vwv12); int suwcnt = CVAL(inbuf,smb_vwv13); + START_PROFILE(SMBtrans); memset(name, '\0',sizeof(name)); fstrcpy(name,smb_buf(inbuf)); @@ -385,6 +386,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (tdscnt) { if((data = (char *)malloc(tdscnt)) == NULL) { DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt)); + END_PROFILE(SMBtrans); return(ERROR(ERRDOS,ERRnomem)); } memcpy(data,smb_base(inbuf)+dsoff,dscnt); @@ -393,6 +395,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (tpscnt) { if((params = (char *)malloc(tpscnt)) == NULL) { DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt)); + END_PROFILE(SMBtrans); return(ERROR(ERRDOS,ERRnomem)); } memcpy(params,smb_base(inbuf)+psoff,pscnt); @@ -402,6 +405,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int int i; if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16)))); + END_PROFILE(SMBtrans); return(ERROR(ERRDOS,ERRnomem)); } for (i=0;iis_directory) { /* @@ -718,8 +727,10 @@ int reply_ntcreate_and_X(connection_struct *conn, if( fname[0] == ':') { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + END_PROFILE(SMBntcreateX); return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } + END_PROFILE(SMBntcreateX); return(ERROR(ERRDOS,ERRbadfid)); } @@ -744,8 +755,10 @@ int reply_ntcreate_and_X(connection_struct *conn, * with the Win2k unicode bug, but that would be rare. JRA. */ - if(fname_len + dir_name_len >= sizeof(pstring)) + if(fname_len + dir_name_len >= sizeof(pstring)) { + END_PROFILE(SMBntcreateX); return(ERROR(ERRSRV,ERRfilespecs)); + } get_filename(&fname[dir_name_len], inbuf, smb_buf(inbuf)-inbuf, smb_buflen(inbuf),fname_len); @@ -764,8 +777,10 @@ int reply_ntcreate_and_X(connection_struct *conn, if((smb_open_mode = map_share_mode(&stat_open_only, fname, desired_access, share_access, - file_attributes)) == -1) + file_attributes)) == -1) { + END_PROFILE(SMBntcreateX); return(ERROR(ERRDOS,ERRbadaccess)); + } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; @@ -800,6 +815,7 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { @@ -852,6 +868,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + END_PROFILE(SMBntcreateX); return(ERROR(0, NT_STATUS_FILE_IS_A_DIRECTORY)); } @@ -864,6 +881,7 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } + END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } #ifdef EROFS @@ -882,6 +900,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!fsp) { restore_case_semantics(file_attributes); + END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -894,6 +913,7 @@ int reply_ntcreate_and_X(connection_struct *conn, restore_case_semantics(file_attributes); + END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } @@ -903,12 +923,14 @@ int reply_ntcreate_and_X(connection_struct *conn, if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name, False), &sbuf) != 0) { close_file(fsp,True); restore_case_semantics(file_attributes); + END_PROFILE(SMBntcreateX); return(ERROR(ERRDOS,ERRnoaccess)); } } else { if (conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { close_file(fsp,False); restore_case_semantics(file_attributes); + END_PROFILE(SMBntcreateX); return(ERROR(ERRDOS,ERRnoaccess)); } } @@ -921,6 +943,7 @@ int reply_ntcreate_and_X(connection_struct *conn, fmode = FILE_ATTRIBUTE_NORMAL; if (!fsp->is_directory && (fmode & aDIR)) { close_file(fsp,False); + END_PROFILE(SMBntcreateX); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -977,7 +1000,9 @@ int reply_ntcreate_and_X(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - return chain_reply(inbuf,outbuf,length,bufsize); + result = chain_reply(inbuf,outbuf,length,bufsize); + END_PROFILE(SMBntcreateX); + return result; } /**************************************************************************** @@ -1403,11 +1428,13 @@ int reply_ntcancel(connection_struct *conn, */ int mid = SVAL(inbuf,smb_mid); + START_PROFILE(SMBntcancel); remove_pending_change_notify_requests_by_mid(mid); remove_pending_lock_requests_by_mid(mid); DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); + END_PROFILE(SMBntcancel); return(-1); } @@ -1417,7 +1444,9 @@ int reply_ntcancel(connection_struct *conn, int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { + START_PROFILE(SMBnttranss); DEBUG(4,("Ignoring nttranss of length %d\n",length)); + END_PROFILE(SMBnttranss); return(-1); } @@ -1729,6 +1758,7 @@ int reply_nttrans(connection_struct *conn, uint16 function_code = SVAL( inbuf, smb_nt_Function); char *params = NULL, *data = NULL, *setup = NULL; uint32 num_params_sofar, num_data_sofar; + START_PROFILE(SMBnttrans); if(global_oplock_break && (function_code == NT_TRANSACT_CREATE)) { /* @@ -1739,11 +1769,14 @@ int reply_nttrans(connection_struct *conn, due to being in oplock break state.\n" )); push_oplock_pending_smb_message( inbuf, length); + END_PROFILE(SMBnttrans); return -1; } - if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) + if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { + END_PROFILE(SMBnttrans); return (ERROR(ERRSRV,ERRaccess)); + } outsize = set_message(outbuf,0,0,True); @@ -1755,6 +1788,7 @@ due to being in oplock break state.\n" )); if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) { DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", CVAL(inbuf, smb_wct), 19 + (setup_count/2))); + END_PROFILE(SMBnttrans); return(ERROR(ERRSRV,ERRerror)); } @@ -1770,6 +1804,7 @@ due to being in oplock break state.\n" )); if ((total_parameter_count && !params) || (total_data_count && !data) || (setup_count && !setup)) { DEBUG(0,("reply_nttrans : Out of memory\n")); + END_PROFILE(SMBnttrans); return(ERROR(ERRDOS,ERRnomem)); } @@ -1822,6 +1857,7 @@ due to being in oplock break state.\n" )); free(data); if(setup) free(setup); + END_PROFILE(SMBnttrans); return(ERROR(ERRSRV,ERRerror)); } @@ -1848,34 +1884,46 @@ due to being in oplock break state.\n" )); /* Now we must call the relevant NT_TRANS function */ switch(function_code) { case NT_TRANSACT_CREATE: + START_PROFILE_NESTED(NT_transact_create); outsize = call_nt_transact_create(conn, inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_create); break; case NT_TRANSACT_IOCTL: + START_PROFILE_NESTED(NT_transact_ioctl); outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_ioctl); break; case NT_TRANSACT_SET_SECURITY_DESC: + START_PROFILE_NESTED(NT_transact_set_security_desc); outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_set_security_desc); break; case NT_TRANSACT_NOTIFY_CHANGE: + START_PROFILE_NESTED(NT_transact_notify_change); outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_notify_change); break; case NT_TRANSACT_RENAME: + START_PROFILE_NESTED(NT_transact_rename); outsize = call_nt_transact_rename(conn, inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_rename); break; case NT_TRANSACT_QUERY_SECURITY_DESC: + START_PROFILE_NESTED(NT_transact_query_security_desc); outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, length, bufsize, &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_query_security_desc); break; default: /* Error in request */ @@ -1886,6 +1934,7 @@ due to being in oplock break state.\n" )); free(params); if(data) free(data); + END_PROFILE(SMBnttrans); return (ERROR(ERRSRV,ERRerror)); } @@ -1902,6 +1951,7 @@ due to being in oplock break state.\n" )); free(params); if(data) free(data); + END_PROFILE(SMBnttrans); return outsize; /* If a correct response was needed the call_nt_transact_xxxx calls have already sent it. If outsize != -1 then it is returning an error packet. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7df1c09fa0..7e2c25109a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2158,6 +2158,7 @@ int reply_findclose(connection_struct *conn, { int outsize = 0; int dptr_num=SVALS(inbuf,smb_vwv0); + START_PROFILE(SMBfindclose); DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num)); @@ -2167,6 +2168,7 @@ int reply_findclose(connection_struct *conn, DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num)); + END_PROFILE(SMBfindclose); return(outsize); } @@ -2178,6 +2180,7 @@ int reply_findnclose(connection_struct *conn, { int outsize = 0; int dptr_num= -1; + START_PROFILE(SMBfindnclose); dptr_num = SVAL(inbuf,smb_vwv0); @@ -2191,6 +2194,7 @@ int reply_findnclose(connection_struct *conn, DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num)); + END_PROFILE(SMBfindnclose); return(outsize); } @@ -2201,7 +2205,9 @@ int reply_findnclose(connection_struct *conn, int reply_transs2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { + START_PROFILE(SMBtranss2); DEBUG(4,("Ignoring transs2 of length %d\n",length)); + END_PROFILE(SMBtranss2); return(-1); } @@ -2226,6 +2232,7 @@ int reply_trans2(connection_struct *conn, unsigned int tran_call = SVAL(inbuf, smb_setup0); char *params = NULL, *data = NULL; int num_params, num_params_sofar, num_data, num_data_sofar; + START_PROFILE(SMBtrans2); if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) { /* Queue this open message as we are the process of an @@ -2235,12 +2242,15 @@ int reply_trans2(connection_struct *conn, DEBUGADD(2,( "in oplock break state.\n")); push_oplock_pending_smb_message(inbuf, length); + END_PROFILE(SMBtrans2); return -1; } if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) - && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) + && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) { + END_PROFILE(SMBtrans2); return(ERROR(ERRSRV,ERRaccess)); + } outsize = set_message(outbuf,0,0,True); @@ -2248,6 +2258,7 @@ int reply_trans2(connection_struct *conn, is so as a sanity check */ if (suwcnt != 1) { DEBUG(2,("Invalid smb_sucnt in trans2 call\n")); + END_PROFILE(SMBtrans2); return(ERROR(ERRSRV,ERRerror)); } @@ -2259,10 +2270,11 @@ int reply_trans2(connection_struct *conn, if ((total_params && !params) || (total_data && !data)) { DEBUG(2,("Out of memory in reply_trans2\n")); - if(params) - free(params); - if(data) - free(data); + if(params) + free(params); + if(data) + free(data); + END_PROFILE(SMBtrans2); return(ERROR(ERRDOS,ERRnomem)); } @@ -2303,6 +2315,7 @@ int reply_trans2(connection_struct *conn, free(params); if(data) free(data); + END_PROFILE(SMBtrans2); return(ERROR(ERRSRV,ERRerror)); } @@ -2330,67 +2343,89 @@ int reply_trans2(connection_struct *conn, /* Now we must call the relevant TRANS2 function */ switch(tran_call) { case TRANSACT2_OPEN: + START_PROFILE_NESTED(Trans2_open); outsize = call_trans2open(conn, inbuf, outbuf, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_open); break; case TRANSACT2_FINDFIRST: + START_PROFILE_NESTED(Trans2_findfirst); outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_findfirst); break; case TRANSACT2_FINDNEXT: + START_PROFILE_NESTED(Trans2_findnext); outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_findnext); break; case TRANSACT2_QFSINFO: + START_PROFILE_NESTED(Trans2_qfsinfo); outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_qfsinfo); break; case TRANSACT2_SETFSINFO: + START_PROFILE_NESTED(Trans2_setfsinfo); outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_setfsinfo); break; case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: + START_PROFILE_NESTED(Trans2_qpathinfo); outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, ¶ms, &data, total_data); + END_PROFILE_NESTED(Trans2_qpathinfo); break; case TRANSACT2_SETPATHINFO: case TRANSACT2_SETFILEINFO: + START_PROFILE_NESTED(Trans2_setpathinfo); outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, ¶ms, &data, total_data); + END_PROFILE_NESTED(Trans2_setpathinfo); break; case TRANSACT2_FINDNOTIFYFIRST: + START_PROFILE_NESTED(Trans2_findnotifyfirst); outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_findnotifyfirst); break; case TRANSACT2_FINDNOTIFYNEXT: + START_PROFILE_NESTED(Trans2_findnotifynext); outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_findnotifynext); break; case TRANSACT2_MKDIR: + START_PROFILE_NESTED(Trans2_mkdir); outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_mkdir); break; case TRANSACT2_GET_DFS_REFERRAL: + START_PROFILE_NESTED(Trans2_get_dfs_referral); outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize, ¶ms, &data); + END_PROFILE_NESTED(Trans2_get_dfs_referral); break; default: /* Error in request */ @@ -2399,6 +2434,7 @@ int reply_trans2(connection_struct *conn, free(params); if(data) free(data); + END_PROFILE(SMBtrans2); return (ERROR(ERRSRV,ERRerror)); } @@ -2413,6 +2449,7 @@ int reply_trans2(connection_struct *conn, free(params); if(data) free(data); + END_PROFILE(SMBtrans2); return outsize; /* If a correct response was needed the call_trans2xxx calls have already sent it. If outsize != -1 then it is returning */ -- cgit From 7a42a9da7d26ce4635aa479f93de6794317b2f29 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 12 Oct 2000 15:41:16 +0000 Subject: use macros for incrementing profile counters (This used to be commit cae5eeb16e81b6aa95c68223268513c32aed7056) --- source3/smbd/process.c | 4 +--- source3/smbd/sec_ctx.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1599ade12d..dc56534edb 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -636,9 +636,7 @@ void process_smb(char *inbuf, char *outbuf) int32 len = smb_len(inbuf); int nread = len + 4; -#ifdef WITH_PROFILE - profile_p->smb_count++; -#endif + DO_PROFILE_INC(smb_count); if (trans_num == 0) { /* on the first packet, check the global hosts allow/ hosts diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 6837a8d4f8..1f20ef062e 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -62,9 +62,7 @@ static BOOL become_uid(uid_t uid) set_effective_uid(uid); current_user.uid = uid; -#ifdef WITH_PROFILE - profile_p->uid_changes++; -#endif + DO_PROFILE_INC(uid_changes) return True; } -- cgit From 2a2a93bebec0d40e26860226f64c4964d5224f3b Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 12 Oct 2000 19:42:18 +0000 Subject: allow "master" smbd to call message_init so it is not killed by messages sent to it's PID Jeremy or Andrew please check this out for other possible side effects. (This used to be commit f365950e7dafa269ace647ae1cab6201f8ecf67d) --- source3/smbd/server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4442a1f71f..4c136f638b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -705,6 +705,10 @@ static void usage(char *pname) pidfile_create("smbd"); } + if (!message_init()) { + exit(1); + } + if (!open_sockets(is_daemon,port)) exit(1); @@ -712,10 +716,6 @@ static void usage(char *pname) * everything after this point is run after the fork() */ - if (!message_init()) { - exit(1); - } - if (!locking_init(0)) { exit(1); } -- cgit From c56301b1d117c27213fe2dc4faf72a1bec19d092 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Oct 2000 21:19:49 +0000 Subject: Ignore SIGUSR2. Terminate nmbd if we have no interfaces. Jeremy. (This used to be commit 580e2e044cfd1d011d9f28f0f49ef60ca6ba8d32) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4c136f638b..e4dd661ea5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -635,6 +635,11 @@ static void usage(char *pname) BlockSignals(True,SIGFPE); #endif +#if defined(SIGUSR2) + /* We are no longer interested in USR2 */ + BlockSignals(True,SIGUSR2); +#endif + /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); -- cgit From 330d678fbad70fabd9712c56ad15bd215f950255 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Oct 2000 01:59:14 +0000 Subject: Fix to allow smbd to call winbindd if it is running for all group enumeration, falling back to the UNIX calls on error. This should fix all problems with smbd enumerating all users in all groups in all trusted domains via winbindd. Also changed GETDC to query 1C name rather than 1b name as only the PDC registers 1b. Jeremy. (This used to be commit 5b0038a2afd8abbd6fd4a58f5477a40d1926d498) --- source3/smbd/groupname.c | 10 +-- source3/smbd/service.c | 16 ++-- source3/smbd/uid.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index f0b11e1b36..d53fa56a44 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -119,7 +119,7 @@ void load_groupname_map(void) for (i=0; lines[i]; i++) { pstring unixname; pstring windows_name; - struct group *gptr; + gid_t gid; DOM_SID tmp_sid; char *s = lines[i]; @@ -150,8 +150,8 @@ void load_groupname_map(void) * Attempt to get the unix gid_t for this name. */ - if((gptr = (struct group *)getgrnam(unixname)) == NULL) { - DEBUG(0,("load_groupname_map: getgrnam for group %s failed.\ + if ((gid = nametogid(unixname)) == (gid_t)-1) + DEBUG(0,("load_groupname_map: nametogid for group %s failed.\ Error was %s.\n", unixname, strerror(errno) )); continue; } @@ -167,7 +167,7 @@ Error was %s.\n", unixname, strerror(errno) )); */ tmp_sid = global_sam_sid; tmp_sid.sub_auths[tmp_sid.num_auths++] = - pdb_gid_to_group_rid((gid_t)gptr->gr_gid); + pdb_gid_to_group_rid(gid); } /* @@ -180,7 +180,7 @@ Error was %s.\n", unixname, strerror(errno) )); return; } - new_ep->unix_gid = gptr->gr_gid; + new_ep->unix_gid = gid; new_ep->windows_sid = tmp_sid; new_ep->windows_name = strdup( windows_name ); new_ep->unix_name = strdup( unixname ); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 6d07562743..b86f3beadd 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -401,7 +401,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int */ if (*lp_force_group(snum)) { - struct group *gptr; + gid_t gid; pstring gname; pstring tmp_gname; BOOL user_must_be_member = False; @@ -416,9 +416,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int } /* default service may be a group name */ pstring_sub(gname,"%S",service); - gptr = (struct group *)getgrnam(gname); + gid = nametogid(gname); - if (gptr) { + if (gid != (gid_t)-1) { /* * If the user has been forced and the forced group starts * with a '+', then we only set the group to be the forced @@ -426,16 +426,12 @@ connection_struct *make_connection(char *service,char *user,char *password, int * Otherwise, the meaning of the '+' would be ignored. */ if (conn->force_user && user_must_be_member) { - int i; - for (i = 0; gptr->gr_mem[i] != NULL; i++) { - if (strcmp(user,gptr->gr_mem[i]) == 0) { - conn->gid = gptr->gr_gid; + if (user_in_group_list( user, gname )) { + conn->gid = gid; DEBUG(3,("Forced group %s for member %s\n",gname,user)); - break; - } } } else { - conn->gid = gptr->gr_gid; + conn->gid = gid; DEBUG(3,("Forced group %s\n",gname)); } } else { diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b28f056a30..fb83e724b8 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -257,4 +257,230 @@ void unbecome_root(void) pop_sec_ctx(); } +/***************************************************************** + *THE CANONICAL* convert name to SID function. + Tries winbind first - then uses local lookup. +*****************************************************************/ + +BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) +{ + extern pstring global_myname; + fstring sid; + + if (!winbind_lookup_name(name, psid, name_type)) { + BOOL ret; + + DEBUG(10,("lookup_name: winbind lookup for %s failed - trying local\n", name )); + + ret = local_lookup_name(global_myname, name, psid, name_type); + if (ret) + DEBUG(10,("lookup_name : (local) %s -> SID %s (type %u)\n", + name, sid_to_string(sid,psid), + (unsigned int)*name_type )); + else + DEBUG(10,("lookup name : (local) %s failed.\n", + name )); + return ret; + } + + DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", + name, sid_to_string(sid,psid), (unsigned int)*name_type )); + return True; +} + +/***************************************************************** + *THE CANONICAL* convert SID to name function. + Tries winbind first - then uses local lookup. +*****************************************************************/ + +BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) +{ + if (!name_type) + return False; + + /* Check if this is our own sid. This should perhaps be done by + winbind? For the moment handle it here. */ + + if (sid->num_auths == 5) { + DOM_SID tmp_sid; + uint32 rid; + + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + + if (sid_equal(&global_sam_sid, &tmp_sid)) { + + return map_domain_sid_to_name(&tmp_sid, dom_name) && + local_lookup_rid(rid, name, name_type); + } + } + + if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { + fstring sid_str; + DOM_SID tmp_sid; + uint32 rid; + + DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); + + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + return map_domain_sid_to_name(&tmp_sid, dom_name) && + lookup_known_rid(&tmp_sid, rid, name, name_type); + } + return True; +} + +/***************************************************************** + *THE CANONICAL* convert uid_t to SID function. + Tries winbind first - then uses local lookup. + Returns SID pointer. +*****************************************************************/ + +DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) +{ + fstring sid; + + if (!winbind_uid_to_sid(psid, uid)) { + DEBUG(10,("uid_to_sid: winbind lookup for uid %u failed - trying local.\n", (unsigned int)uid )); + + return local_uid_to_sid(psid, uid); + } + + DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid) )); + + return psid; +} + +/***************************************************************** + *THE CANONICAL* convert gid_t to SID function. + Tries winbind first - then uses local lookup. + Returns SID pointer. +*****************************************************************/ + +DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) +{ + fstring sid; + + if (!winbind_gid_to_sid(psid, gid)) { + DEBUG(10,("gid_to_sid: winbind lookup for gid %u failed - trying local.\n", (unsigned int)gid )); + + return local_gid_to_sid(psid, gid); + } + + DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", + (unsigned int)gid, sid_to_string(sid,psid) )); + + return psid; +} + +/***************************************************************** + *THE CANONICAL* convert SID to uid function. + Tries winbind first - then uses local lookup. + Returns True if this name is a user sid and the conversion + was done correctly, False if not. +*****************************************************************/ + +BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + *sidtype = SID_NAME_UNKNOWN; + + /* + * First we must look up the name and decide if this is a user sid. + */ + + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + return local_sid_to_uid(puid, psid, sidtype); + } + + /* + * Ensure this is a user sid. + */ + + if (name_type != SID_NAME_USER) { + DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n", + (unsigned int)name_type )); + return False; + } + + *sidtype = SID_NAME_USER; + + /* + * Get the uid for this SID. + */ + + if (!winbind_sid_to_uid(puid, psid)) { + DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n", + sid_to_string(sid_str, psid) )); + return False; + } + + DEBUG(10,("sid_to_uid: winbindd %s -> %u\n", + sid_to_string(sid_str, psid), + (unsigned int)*puid )); + + return True; +} + +/***************************************************************** + *THE CANONICAL* convert SID to gid function. + Tries winbind first - then uses local lookup. + Returns True if this name is a user sid and the conversion + was done correctly, False if not. +*****************************************************************/ + +BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + *sidtype = SID_NAME_UNKNOWN; + + /* + * First we must look up the name and decide if this is a group sid. + */ + + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + return local_sid_to_gid(pgid, psid, sidtype); + } + + /* + * Ensure this is a group sid. + */ + + if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { + DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a know group (%u)\n", + (unsigned int)name_type )); + + return local_sid_to_gid(pgid, psid, sidtype); + } + + *sidtype = name_type; + + /* + * Get the gid for this SID. + */ + + if (!winbind_sid_to_gid(pgid, psid)) { + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n", + sid_to_string(sid_str, psid) )); + return False; + } + + DEBUG(10,("gid_to_uid: winbindd %s -> %u\n", + sid_to_string(sid_str, psid), + (unsigned int)*pgid )); + + return True; +} + #undef OLD_NTDOMAIN -- cgit From ecd90a0bf45d560b4532fe7ce04332b53947fbdc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 18 Oct 2000 06:22:20 +0000 Subject: Renamed WPrintQueuePurge to WPrintQueueCtrl as this function can purge, pause or resume a print queue. (This used to be commit 9998518a69c67c1540266549c69fca977a89acde) --- source3/smbd/lanman.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index dafbe2258f..fa6224b596 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1915,7 +1915,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param /**************************************************************************** Purge a print queue - or pause or resume it. ****************************************************************************/ -static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -3210,8 +3210,8 @@ struct {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, - {"WPrintQueuePause", 74, api_WPrintQueuePurge,0}, - {"WPrintQueueResume", 75, api_WPrintQueuePurge,0}, + {"WPrintQueuePause", 74, api_WPrintQueueCtrl,0}, + {"WPrintQueueResume", 75, api_WPrintQueueCtrl,0}, {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, @@ -3220,7 +3220,7 @@ struct {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, - {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0}, + {"WPrintQueuePurge", 103, api_WPrintQueueCtrl,0}, {"NetServerEnum", 104, api_RNetServerEnum,0}, {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, {"SetUserPassword", 115, api_SetUserPassword,0}, -- cgit From abf055046fe70842badc2a1904f2cd6966bafbf4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Oct 2000 02:58:24 +0000 Subject: Ok - this is a big patch - and it may break smbd a bit (although I hope not). If you encounter strange file-serving behavior after this patch then back it out. I analysed our stat() usage and realised we were doing approx. 3 stat calls per open, and 2 per getattr/setattr. This patch should fix all that. It causes the stat struct returned from unix_convert() (which now *must* be passed a valid SMB_STRUCT_STAT pointer) to be passed through into the open code. This should prevent the multiple stats that were being done so as not to violate layer encapsulation in the API's. Herb - if you could run a NetBench test with this code and do a padc/par syscall test and also run with the current 2.2.0 code and test the padc/par syscalls I'd appreciate it - you should find the number of stat calls reduced - not sure by how much. The patch depends on unix_convert() actually finding the file and returning a stat struct, or returning a zero'd out stat struct if the file didn't exist. I believe we can guarentee this to be the case - I just wasn't confident enough to make this an assertion before. Ok ok - I did write this whilst at the Miami conference..... sometimes you get a little free time at these things :-). Jeremy. (This used to be commit 66a5c05ec46b641224fbe01b30bd7e83571a2a1b) --- source3/smbd/filename.c | 83 +++++++++++++++++---------------- source3/smbd/nttrans.c | 57 ++++------------------- source3/smbd/open.c | 116 ++++++++++++++++++++++++++--------------------- source3/smbd/reply.c | 107 +++++++++++++++++++++---------------------- source3/smbd/statcache.c | 2 +- source3/smbd/trans2.c | 58 +++++++++++------------- source3/smbd/vfs.c | 2 + 7 files changed, 199 insertions(+), 226 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9ac82386f9..5fe4a4c903 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -111,6 +111,11 @@ The bad_path arg is set to True if the filename walk failed. This is used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. + +On exit from unix_convert, if *pst was not null, then the file stat +struct will be returned if the file exists and was found, if not this +stat struct will be filled with zeros (and this can be detected by checking +for nlinks = 0, which can never be true for any file). ****************************************************************************/ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, @@ -127,6 +132,13 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, extern char magic_char; #endif + ZERO_STRUCTP(pst); + + *dirpath = 0; + *bad_path = False; + if(saved_last_component) + *saved_last_component = 0; + if (conn->printer) { /* we don't ever use the filenames on a printer share as a filename - so don't convert them */ @@ -135,15 +147,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); - *dirpath = 0; - *bad_path = False; - if(pst) { - ZERO_STRUCTP(pst); - } - - if(saved_last_component) - *saved_last_component = 0; - /* * Convert to basic unix format - removing \ chars and cleaning it up. */ @@ -165,7 +168,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * printing share. */ - if (!*name && (!conn -> printer)) { + if (!*name) { name[0] = '.'; name[1] = '\0'; } @@ -202,8 +205,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstrcpy(orig_path, name); if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { - if(pst) - *pst = st; + *pst = st; return True; } @@ -211,11 +213,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(conn,dos_to_unix(name,False),&st) == 0) { + if (vfs_stat(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - if(pst) - *pst = st; + *pst = st; return(True); } @@ -277,7 +278,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - if (conn->vfs_ops.stat(conn,dos_to_unix(name,False), &st) == 0) { + ZERO_STRUCT(st); + if (vfs_stat(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -308,8 +310,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Try to find this part of the path in the directory. */ - if (ms_has_wild(start) || - !scan_directory(dirpath, start, conn, end?True:False)) { + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { /* * An intermediate part of the name can't be found. @@ -392,6 +393,14 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(!component_was_mangled && !name_has_wildcard) stat_cache_add(orig_path, name); + /* + * If we ended up resolving the entire path then return a valid + * stat struct if we got one. + */ + + if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) + *pst = st; + /* * The name has been resolved. */ @@ -426,15 +435,13 @@ BOOL check_name(char *name,connection_struct *conn) University of Geneva */ #ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) - { + if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; if ( (conn->vfs_ops.lstat(conn,dos_to_unix(name,False),&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) - { + (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; - } + } } #endif @@ -479,33 +486,29 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d mangled = !check_mangled_cache( name ); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) - { + if (!(cur_dir = OpenDir(conn, path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); - } + } /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) - { - if (*dname == '.' && - (strequal(dname,".") || strequal(dname,".."))) - continue; + while ((dname = ReadDirName(cur_dir))) { + if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) + continue; pstrcpy(name2,dname); if (!name_map_mangle(name2,False,True,SNUM(conn))) continue; - if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, name2)) - { - /* we've found the file, change it's name and return */ - if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); - CloseDir(cur_dir); - return(True); - } + if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) { + /* we've found the file, change it's name and return */ + if (docache) + DirCacheAdd(path,name,dname,SNUM(conn)); + pstrcpy(name, dname); + CloseDir(cur_dir); + return(True); } + } CloseDir(cur_dir); return(False); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 67f1a1bc9e..f8b6352ba1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -795,7 +795,7 @@ int reply_ntcreate_and_X(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,smb_attr | aARCH, fname); @@ -806,7 +806,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); @@ -836,7 +836,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_shared(conn,fname,smb_open_mode, + fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode, smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp) { @@ -873,7 +873,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -896,7 +896,7 @@ int reply_ntcreate_and_X(connection_struct *conn, oplock_request = 0; - fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,&sbuf,smb_open_mode,&smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -919,22 +919,6 @@ int reply_ntcreate_and_X(connection_struct *conn, } } - if(fsp->is_directory) { - if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name, False), &sbuf) != 0) { - close_file(fsp,True); - restore_case_semantics(file_attributes); - END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } else { - if (conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - restore_case_semantics(file_attributes); - END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } - restore_case_semantics(file_attributes); file_len = sbuf.st_size; @@ -1231,7 +1215,7 @@ static int call_nt_transact_create(connection_struct *conn, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,smb_attr | aARCH, fname); @@ -1249,7 +1233,7 @@ static int call_nt_transact_create(connection_struct *conn, * CreateDirectory() call. */ - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1260,20 +1244,13 @@ static int call_nt_transact_create(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name, False), - &sbuf) != 0) { - close_file(fsp,True); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } else { /* * Ordinary file case. */ - fsp = open_file_shared(conn,fname,smb_open_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp) { @@ -1291,7 +1268,7 @@ static int call_nt_transact_create(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1314,7 +1291,7 @@ static int call_nt_transact_create(connection_struct *conn, oplock_request = 0; - fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,&sbuf,smb_open_mode,&smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1333,20 +1310,6 @@ static int call_nt_transact_create(connection_struct *conn, } } - if(fsp->is_directory) { - if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name,False), &sbuf) != 0) { - close_file(fsp,True); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } else { - if (!fsp->stat_open && conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } - file_len = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); if(fmode == 0) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index edd94bd865..12f6d12948 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -88,12 +88,11 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,mode_t mode) + char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode) { extern struct current_user current_user; pstring fname; int accmode = (flags & O_ACCMODE); - SMB_STRUCT_STAT sbuf; fsp->fd = -1; fsp->oplock_type = NO_OPLOCK; @@ -138,10 +137,12 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return False; } - if (conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf) == -1) { - DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); - fd_close(conn, fsp); - return False; + if (!VALID_STAT(*psbuf)) { + if (vfs_fstat(fsp,fsp->fd,psbuf) == -1) { + DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); + fd_close(conn, fsp); + return False; + } } /* @@ -150,18 +151,18 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * so catch a directory open and return an EISDIR. JRA. */ - if(S_ISDIR(sbuf.st_mode)) { + if(S_ISDIR(psbuf->st_mode)) { fd_close(conn, fsp); errno = EISDIR; return False; } - fsp->mode = sbuf.st_mode; - fsp->inode = sbuf.st_ino; - fsp->dev = sbuf.st_dev; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->size = 0; + fsp->size = psbuf->st_size; fsp->pos = -1; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); @@ -513,17 +514,17 @@ static void kernel_flock(files_struct *fsp, int deny_mode) /**************************************************************************** - Open a file with a share mode. + Open a file with a share mode. On output from this open we are guarenteeing + that ****************************************************************************/ -files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mode,int ofun, - mode_t mode,int oplock_request, int *Access,int *action) +files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, + int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) { int flags=0; int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); - SMB_STRUCT_STAT sbuf; - BOOL file_existed = vfs_file_exist(conn, fname, &sbuf); + BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; @@ -619,7 +620,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod #endif /* O_SYNC */ if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) { + (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,psbuf)))) { if (!fcbopen) { DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); @@ -638,8 +639,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod } if (file_existed) { - dev = sbuf.st_dev; - inode = sbuf.st_ino; + + dev = psbuf->st_dev; + inode = psbuf->st_ino; lock_share_entry(conn, dev, inode); @@ -659,10 +661,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); - fsp_open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC)),mode); if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { - if((fsp_open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True) + if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode)) == True) flags = O_RDONLY; } @@ -717,11 +719,16 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod * If requested, truncate the file. */ - if ((flags2&O_TRUNC) && (truncate_unless_locked(conn,fsp) == -1)) { - unlock_share_entry_fsp(fsp); - fd_close(conn,fsp); - file_free(fsp); - return NULL; + if (flags2&O_TRUNC) { + /* + * We are modifing the file after open - update the stat struct.. + */ + if ((truncate_unless_locked(conn,fsp) == -1) || (vfs_fstat(fsp,fsp->fd,psbuf)==-1)) { + unlock_share_entry_fsp(fsp); + fd_close(conn,fsp); + file_free(fsp); + return NULL; + } } switch (flags) { @@ -783,28 +790,26 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod with the 'stat_open' flag set ****************************************************************************/ -files_struct *open_file_stat(connection_struct *conn, - char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action) +files_struct *open_file_stat(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf, int smb_ofun, int *action) { extern struct current_user current_user; - files_struct *fsp = file_new(); - - if(!fsp) - return NULL; + files_struct *fsp = NULL; - if(conn->vfs_ops.stat(conn,dos_to_unix(fname, False), pst) < 0) { - DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", - fname, strerror(errno) )); - file_free(fsp); + if (!VALID_STAT(*psbuf)) { + DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return NULL; } - if(S_ISDIR(pst->st_mode)) { + if(S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); - file_free(fsp); return NULL; } + fsp = file_new(); + if(!fsp) + return NULL; + *action = FILE_WAS_OPENED; DEBUG(5,("open_file_stat: opening file %s as a stat entry\n", fname)); @@ -814,10 +819,12 @@ files_struct *open_file_stat(connection_struct *conn, */ fsp->fd = -1; - fsp->mode = 0; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; GetTimeOfDay(&fsp->open_time); + fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->size = 0; fsp->pos = -1; fsp->can_lock = False; fsp->can_read = False; @@ -851,20 +858,18 @@ files_struct *open_file_stat(connection_struct *conn, Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, - char *fname, int smb_ofun, mode_t unixmode, int *action) +files_struct *open_directory(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; - SMB_STRUCT_STAT st; BOOL got_stat = False; files_struct *fsp = file_new(); if(!fsp) return NULL; - if(conn->vfs_ops.stat(conn,dos_to_unix(fname, False), &st) == 0) { + if (VALID_STAT(*psbuf)) got_stat = True; - } if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { file_free(fsp); @@ -876,7 +881,7 @@ files_struct *open_directory(connection_struct *conn, if (got_stat) { - if(!S_ISDIR(st.st_mode)) { + if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); file_free(fsp); errno = EACCES; @@ -903,6 +908,12 @@ files_struct *open_directory(connection_struct *conn, file_free(fsp); return NULL; } + + if(vfs_stat(conn,fname, psbuf) != 0) { + file_free(fsp); + return NULL; + } + *action = FILE_WAS_CREATED; } @@ -919,7 +930,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - if(!S_ISDIR(st.st_mode)) { + if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); file_free(fsp); return NULL; @@ -928,18 +939,19 @@ files_struct *open_directory(connection_struct *conn, *action = FILE_WAS_OPENED; } - DEBUG(5,("open_directory: opening directory %s\n", - fname)); + DEBUG(5,("open_directory: opening directory %s\n", fname)); /* * Setup the files_struct for it. */ fsp->fd = -1; - fsp->mode = 0; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; GetTimeOfDay(&fsp->open_time); + fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; fsp->can_read = False; @@ -983,7 +995,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) SMB_DEV_T dev; SMB_INO_T inode; - if (conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf) == -1) + if (vfs_stat(conn,fname,&sbuf) == -1) return(True); dev = sbuf.st_dev; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index efd18799a2..4fd9f9c42d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1033,22 +1033,20 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring name; BOOL ok = False; BOOL bad_path = False; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBchkpth); pstrcpy(name,smb_buf(inbuf) + 1); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - unix_convert(name,conn,0,&bad_path,&st); + unix_convert(name,conn,0,&bad_path,&sbuf); mode = SVAL(inbuf,smb_vwv0); if (check_name(name,conn)) { - if(VALID_STAT(st)) - ok = S_ISDIR(st.st_mode); - else - ok = vfs_directory_exist(conn,name,NULL); + if(VALID_STAT(sbuf)) + ok = S_ISDIR(sbuf.st_mode); } if (!ok) @@ -1182,17 +1180,17 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok=False; int mode; time_t mtime; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT sbuf; BOOL bad_path = False; START_PROFILE(SMBsetatr); pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,conn,0,&bad_path,&st); + unix_convert(fname,conn,0,&bad_path,&sbuf); mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, fname, NULL)) + if (VALID_STAT_OF_DIR(sbuf)) mode |= aDIR; if (check_name(fname,conn)) ok = (file_chmod(conn,fname,mode,NULL) == 0); @@ -1292,11 +1290,12 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (status_len == 0) { + SMB_STRUCT_STAT sbuf; pstring dir2; pstrcpy(directory,smb_buf(inbuf)+1); pstrcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); unix_format(dir2); if (!check_name(directory,conn)) @@ -1517,11 +1516,11 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,aARCH,fname); - fsp = open_file_shared(conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unixmode, oplock_request,&rmode,NULL); if (!fsp) @@ -1535,12 +1534,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - END_PROFILE(SMBopen); - return(ERROR(ERRDOS,ERRnoaccess)); - } - size = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; @@ -1618,11 +1611,11 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,smb_attr | aARCH, fname); - fsp = open_file_shared(conn,fname,smb_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp) @@ -1636,12 +1629,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - END_PROFILE(SMBopenX); - return(ERROR(ERRDOS,ERRnoaccess)); - } - size = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; @@ -1737,6 +1724,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBcreate); com = SVAL(inbuf,smb_com); @@ -1746,12 +1734,11 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); - if (createmode & aVOLID) - { + if (createmode & aVOLID) { DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); - } + } unixmode = unix_mode(conn,createmode,fname); @@ -1767,7 +1754,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file in dos compatibility share mode. */ - fsp = open_file_shared(conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), ofun, unixmode, oplock_request, NULL, NULL); if (!fsp) @@ -1813,23 +1800,27 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBctemp); - + createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,createmode,fname); pstrcpy(fname2,(char *)smbd_mktemp(fname)); + /* This file should not exist. */ + ZERO_STRUCT(sbuf); + vfs_stat(conn,fname2,&sbuf); /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - fsp = open_file_shared(conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + fsp = open_file_shared(conn,fname2,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL); if (!fsp) @@ -1904,6 +1895,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL exists=False; BOOL bad_path = False; BOOL rc = True; + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBunlink); *directory = *mask = 0; @@ -1916,7 +1908,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - rc = unix_convert(name,conn,0,&bad_path,NULL); + rc = unix_convert(name,conn,0,&bad_path,&sbuf); p = strrchr(name,'/'); if (!p) { @@ -1948,7 +1940,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory)) count++; if (!count) - exists = vfs_file_exist(conn,directory,NULL); + exists = vfs_file_exist(conn,directory,&sbuf); } else { void *dirptr = NULL; char *dname; @@ -3281,9 +3273,10 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory) { BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; int ret= -1; - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory, conn)) ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); @@ -3482,13 +3475,14 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int outsize = 0; BOOL ok = False; BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBrmdir); pstrcpy(directory,smb_buf(inbuf) + 1); RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) - unix_convert(directory,conn, NULL,&bad_path,NULL); + unix_convert(directory,conn, NULL,&bad_path,&sbuf); if (check_name(directory,conn)) { @@ -3614,12 +3608,13 @@ int rename_internals(connection_struct *conn, int error = ERRnoaccess; BOOL exists=False; BOOL rc = True; - pstring zdirectory; + SMB_STRUCT_STAT sbuf1, sbuf2; + pstring zdirectory; *directory = *mask = 0; - rc = unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,newname_last_component,&bad_path2,NULL); + rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); + unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); /* * Split the old name into directory and last component @@ -3855,7 +3850,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory, int *err_ret) { int Access,action; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT src_sbuf, sbuf2; SMB_OFF_T ret=-1; files_struct *fsp1,*fsp2; pstring dest; @@ -3873,10 +3868,10 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!vfs_file_exist(conn,src,&st)) + if (!vfs_file_exist(conn,src,&src_sbuf)) return(False); - fsp1 = open_file_shared(conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); if (!fsp1) { @@ -3884,10 +3879,11 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if (!target_is_directory && count) - ofun = 1; + ofun = FILE_EXISTS_OPEN; - fsp2 = open_file_shared(conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,st.st_mode,0,&Access,&action); + vfs_stat(conn,dest,&sbuf2); + fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + ofun,src_sbuf.st_mode,0,&Access,&action); if (!fsp2) { close_file(fsp1,False); @@ -3902,12 +3898,12 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, * Stop the copy from occurring. */ ret = -1; - st.st_size = 0; + src_sbuf.st_size = 0; } } - if (st.st_size) - ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0); + if (src_sbuf.st_size) + ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0); close_file(fsp1,False); /* @@ -3918,7 +3914,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, */ *err_ret = close_file(fsp2,False); - return(ret == (SMB_OFF_T)st.st_size); + return(ret == (SMB_OFF_T)src_sbuf.st_size); } @@ -3945,6 +3941,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path1 = False; BOOL bad_path2 = False; BOOL rc = True; + SMB_STRUCT_STAT sbuf1, sbuf2; START_PROFILE(SMBcopy); *directory = *mask = 0; @@ -3964,10 +3961,10 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(name, conn, inbuf, outbuf); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); - rc = unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,0,&bad_path2,NULL); + rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); + unix_convert(newname,conn,0,&bad_path2,&sbuf2); - target_is_directory = vfs_directory_exist(conn,False,NULL); + target_is_directory = VALID_STAT_OF_DIR(sbuf2); if ((flags&1) && target_is_directory) { END_PROFILE(SMBcopy); @@ -3979,7 +3976,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRDOS,ERRbadpath)); } - if ((flags&(1<<5)) && vfs_directory_exist(conn,name,NULL)) { + if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); END_PROFILE(SMBcopy); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8d756a1d46..8200c277b3 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -193,7 +193,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); trans_name = scp->names+scp->name_len+1; - if(conn->vfs_ops.stat(conn,dos_to_unix(trans_name,False), pst) != 0) { + if(vfs_stat(conn,trans_name, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7e2c25109a..17a362fb5c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -224,7 +224,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { @@ -238,7 +238,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unixmode = unix_mode(conn,open_attr | aARCH, fname); - fsp = open_file_shared(conn,fname,open_mode,open_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp) @@ -251,11 +251,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - size = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; @@ -407,7 +402,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(conn,dos_to_unix(pathreal,False),&sbuf) != 0) + if (vfs_stat(conn,pathreal,&sbuf) != 0) { /* Needed to show the msdfs symlinks as directories */ if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) @@ -657,6 +652,7 @@ static int call_trans2findfirst(connection_struct *conn, BOOL out_of_space = False; int space_remaining; BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; *directory = *mask = 0; @@ -686,7 +682,7 @@ static int call_trans2findfirst(connection_struct *conn, DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); if(!check_name(directory,conn)) { if((errno == ENOENT) && bad_path) { @@ -1112,7 +1108,7 @@ static int call_trans2qfsinfo(connection_struct *conn, DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(conn->vfs_ops.stat(conn,".",&st)!=0) { + if(vfs_stat(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return (ERROR(ERRSRV,ERRinvdevice)); } @@ -1308,7 +1304,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) { + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1328,7 +1324,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { + if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1350,7 +1346,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) { + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1567,7 +1563,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, int mode=0; SMB_OFF_T size=0; struct utimbuf tvs; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT sbuf; pstring fname1; char *fname; int fd = -1; @@ -1588,9 +1584,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * to do this call. JRA. */ fname = fsp->fsp_name; - unix_convert(fname,conn,0,&bad_path,&st); - if (!check_name(fname,conn) || - (!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st))) { + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1609,7 +1604,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; fd = fsp->fd; - if (fsp->conn->vfs_ops.fstat(fsp,fd,&st) != 0) { + if (vfs_fstat(fsp,fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1619,7 +1614,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = fname1; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path,&st); + unix_convert(fname,conn,0,&bad_path,&sbuf); if(!check_name(fname, conn)) { if((errno == ENOENT) && bad_path) @@ -1630,7 +1625,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st)!=0) { + if(!VALID_STAT(sbuf)) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1651,10 +1646,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, SSVAL(params,0,0); - size = st.st_size; - tvs.modtime = st.st_mtime; - tvs.actime = st.st_atime; - mode = dos_mode(conn,fname,&st); + size = sbuf.st_size; + tvs.modtime = sbuf.st_mtime; + tvs.actime = sbuf.st_atime; + mode = dos_mode(conn,fname,&sbuf); if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ @@ -1908,10 +1903,10 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) /* get some defaults (no modifications) if any info is zero or -1. */ if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1) - tvs.actime = st.st_atime; + tvs.actime = sbuf.st_atime; if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) - tvs.modtime = st.st_mtime; + tvs.modtime = sbuf.st_mtime; DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); @@ -1925,13 +1920,13 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) * changing the size of a file. */ if (!size) - size = st.st_size; + size = sbuf.st_size; } /* Try and set the times, size and mode of this file - if they are different from the current values */ - if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { + if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { if(fsp != NULL) { /* * This was a setfileinfo on an open file. @@ -1957,7 +1952,7 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) } /* check the mode isn't different, before changing it */ - if ((mode != 0) && (mode != dos_mode(conn, fname, &st))) { + if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) { DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode )); @@ -1968,7 +1963,7 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) } } - if(size != st.st_size) { + if(size != sbuf.st_size) { DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", fname, (double)size )); @@ -2004,6 +1999,7 @@ static int call_trans2mkdir(connection_struct *conn, char *params = *pparams; pstring directory; int ret = -1; + SMB_STRUCT_STAT sbuf; BOOL bad_path = False; if (!CAN_WRITE(conn)) @@ -2013,7 +2009,7 @@ static int call_trans2mkdir(connection_struct *conn, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory,conn)) ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 467f3e47a2..2f984aee4f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -323,6 +323,8 @@ BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) if (!sbuf) sbuf = &st; + + ZERO_STRUCTP(sbuf); if (vfs_stat(conn,fname,sbuf) != 0) return(False); -- cgit From bbce6b44eb2247362c353c5f90278bfafe98dc11 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Oct 2000 23:59:47 +0000 Subject: Fix for vfs_fstat() crash with new stat code. Jeremy. (This used to be commit 979aa01e011d433328af0ead7644f47d0cfadf13) --- source3/smbd/open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 12f6d12948..258e463ecf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -548,6 +548,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S return NULL; fsp->fd = -1; + fsp->conn = conn; /* The vfs_fXXX() macros need this. */ DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, share_mode, ofun, (int)mode, oplock_request )); @@ -868,6 +869,8 @@ files_struct *open_directory(connection_struct *conn, char *fname, if(!fsp) return NULL; + fsp->conn = conn; /* THe vfs_fXXX() macros need this. */ + if (VALID_STAT(*psbuf)) got_stat = True; -- cgit From b5ac72cc646a981469ee65305da83f273c4cd093 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Oct 2000 21:43:13 +0000 Subject: Sorry JF - no billable hours :-). I fixed the "stream of events" problem with PCL drivers. The problem was we were updating the changeid on every SETPRINTERDATA/DELETEPRINTERDATA call. We should not do this, we should just update the 'setprinter' called count. We update the changeid on calls to SETPRINTER/ADDPRINTER/ADDPRINTEREX etc. Also fixed the correct returning of the create time on printers. Jeremy. (This used to be commit 521f09829fd329f87b3d19e8871e2b989c98a58e) --- source3/smbd/sec_ctx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 1f20ef062e..f316156222 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -318,10 +318,8 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN ctx_p->ngroups = ngroups; safe_free(ctx_p->groups); -#if 1 /* JRATEST */ if (token && (token == ctx_p->token)) smb_panic("DUPLICATE_TOKEN"); -#endif delete_nt_token(&ctx_p->token); -- cgit From 1cb444057a7894ca97706fb65a756e5fdb635f81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 28 Oct 2000 19:38:39 +0000 Subject: David Lee's utmp patch (finally). Thanks David ! Jeremy. (This used to be commit b809a2d0c81c54e917ccc0c99b3e70ea8d7ceab1) --- source3/smbd/connection.c | 678 ++++++++++++++++++++++++++++++++++++++++------ source3/smbd/posix_acls.c | 19 +- source3/smbd/sec_ctx.c | 2 +- 3 files changed, 609 insertions(+), 90 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index bc014c300d..6e088f9f8f 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -126,17 +126,63 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO Reflect connection status in utmp/wtmp files. T.D.Lee@durham.ac.uk September 1999 -Hints for porting: - o Always attempt to use programmatic interface (pututline() etc.) - o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable. + With grateful thanks since then to many who have helped port it to + different operating systems. The variety of OS quirks thereby + uncovered is amazing... -OS status: - Solaris 2.x: Tested on 2.6 and 2.7; should be OK on other flavours. - T.D.Lee@durham.ac.uk - HPUX 9.x: Not tested. Appears not to have "x". - IRIX 6.5: Not tested. Appears to have "x". +Hints for porting: + o Always attempt to use programmatic interface (pututline() etc.) + Indeed, at present only programmatic use is supported. + o The only currently supported programmatic interface to "wtmp{,x}" + is through "updwtmp*()" routines. + o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable. + o The HAVE_* items should identify supported features. + o If at all possible, avoid "if defined(MY-OS)" constructions. + +OS observations and status: + Almost every OS seems to have its own quirks. + + Solaris 2.x: + Tested on 2.6 and 2.7; should be OK on other flavours. + AIX: + Apparently has utmpx.h but doesn't implement. + OSF: + Has utmpx.h, but (e.g.) no "getutmpx()". (Is this like AIX ?) + Redhat 6: + utmpx.h seems not to set default filenames. non-x better. + IRIX 6.5: + Not tested. Appears to have "x". + HP-UX 9.x: + Not tested. Appears to lack "x". + HP-UX 10.x: + Not tested. + "updwtmp*()" routines seem absent, so no current wtmp* support. + Has "ut_addr": probably trivial to implement (although remember + that IPv6 is coming...). + + FreeBSD: + No "putut*()" type of interface. + No "ut_type" and associated defines. + Write files directly. Alternatively use its login(3)/logout(3). + SunOS 4: + Not tested. Resembles FreeBSD, but no login()/logout(). + +lastlog: + Should "lastlog" files, if any, be updated? + BSD systems (SunOS 4, FreeBSD): + o Prominent mention on man pages. + System-V (e.g. Solaris 2): + o No mention on man pages, even under "man -k". + o Has a "/var/adm/lastlog" file, but pututxline() etc. seem + not to touch it. + o Despite downplaying (above), nevertheless has . + So perhaps UN*X "lastlog" facility is intended for tty/terminal only? Notes: + Each connection requires a small number (starting at 0, working up) + to represent the line (unum). This must be unique within and across + all smbd processes. + The 4 byte 'ut_id' component is vital to distinguish connections, of which there could be several hundered or even thousand. Entries seem to be printable characters, with optional NULL pads. @@ -158,10 +204,11 @@ Notes: Arbitrarily I have chosen to use a distinctive 'SM' for the first two bytes. - The remaining two encode the connection number used in samba locking - functions "claim_connection() and "yield_connection()". This seems - to be a "nicely behaved" number: starting from 0 then working up - looking for an available slot. + The remaining two encode the "unum" (see above). + + For "utmp consolidate" the suggestion was made to encode the pid into + those remaining two bytes (16 bits). But recent UNIX (e.g Solaris 8) + is migrating to pids > 16 bits, so we ought not to do this. ****************************************************************************/ @@ -171,6 +218,136 @@ Notes: #include #endif +/* BSD systems: some may need lastlog.h (SunOS 4), some may not (FreeBSD) */ +/* Some System-V systems (e.g. Solaris 2) declare this too. */ +#ifdef HAVE_LASTLOG_H +#include +#endif + +/**************************************************************************** +obtain/release a small number (0 upwards) unique within and across smbds +****************************************************************************/ +/* + * Need a "small" number to represent this connection, unique within this + * smbd and across all smbds. + * + * claim: + * Start at 0, hunt up for free, unique number "unum" by attempting to + * store it as a key in a tdb database: + * key: unum data: pid+conn + * Also store its inverse, ready for yield function: + * key: pid+conn data: unum + * + * yield: + * Find key: pid+conn; data is unum; delete record + * Find key: unum ; delete record. + * + * Comment: + * The claim algorithm (a "for" loop attempting to store numbers in a tdb + * database) will be increasingly inefficient with larger numbers of + * connections. Is it possible to write a suitable primitive within tdb? + * + * However, by also storing the inverse key/data pair, we at least make + * the yield algorithm efficient. + */ + +static TDB_CONTEXT *tdb_utmp; + +struct utmp_tdb_data { + pid_t pid; + int cnum; +}; + +static int utmp_claim_tdb(const connection_struct *conn) +{ + struct utmp_tdb_data udata; + int i, slotnum; + TDB_DATA kbuf, dbuf; + + if (!tdb_utmp) { + tdb_utmp = tdb_open(lock_path("utmp.tdb"), 0, + TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); + } + if (!tdb_utmp) return(-1); + + DEBUG(2,("utmp_claim_tdb: entered\n")); + + ZERO_STRUCT(udata); + udata.pid = sys_getpid(); + udata.cnum = conn ? conn->cnum : -1; + + dbuf.dptr = (char *) &udata; + dbuf.dsize = sizeof(udata); + + /* The key is simply a number as close as possible to zero: find it */ + slotnum = -1; + /* stop loop when overflow +ve integers (a huge, busy machine!) */ + for (i = 0; i >= 0 ; i++) { + kbuf.dptr = (char *) &i; + kbuf.dsize = sizeof(i); + + if (tdb_store(tdb_utmp, kbuf, dbuf, TDB_INSERT) == 0) { + /* have successfully grabbed a free slot */ + slotnum = i; + + /* store the inverse for faster utmp_yield_tdb() */ + tdb_store(tdb_utmp, dbuf, kbuf, TDB_INSERT); + + break; /* Got it; escape */ + } + } + if (slotnum < 0) { /* more connections than positive integers! */ + DEBUG(2,("utmp_claim_tdb: failed\n")); + return(-1); + } + + DEBUG(2,("utmp_claim_tdb: leaving with %d\n", slotnum)); + + return(slotnum); +} + +static int utmp_yield_tdb(const connection_struct *conn) +{ + struct utmp_tdb_data revkey; + int i, slotnum; + TDB_DATA kbuf, dbuf; + + if (!tdb_utmp) { + return(-1); + } + + DEBUG(2,("utmp_yield_tdb: entered\n")); + + ZERO_STRUCT(revkey); + revkey.pid = sys_getpid(); + revkey.cnum = conn ? conn->cnum : -1; + + kbuf.dptr = (char *) &revkey; + kbuf.dsize = sizeof(revkey); + + dbuf = tdb_fetch(tdb_utmp, kbuf); + if (dbuf.dptr == NULL) { + DEBUG(2,("utmp_yield_tdb: failed\n")); + return(-1); /* shouldn't happen */ + } + + /* Save our result */ + slotnum = (int) dbuf.dptr; + + /* Tidy up */ + tdb_delete(tdb_utmp, kbuf); + tdb_delete(tdb_utmp, dbuf); + + free(dbuf.dptr); + DEBUG(2,("utmp_yield_tdb: leaving with %d\n", slotnum)); + + return(slotnum); +} + +#if defined(HAVE_UT_UT_ID) +/**************************************************************************** +encode the unique connection number into "ut_id" +****************************************************************************/ static const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -197,61 +374,198 @@ ut_id_encode(int i, char *fourbyte) return(i); /* 0: good; else overflow */ } +#endif /* defined(HAVE_UT_UT_ID) */ -static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid, int i) +/* + * ut_line: + * size small, e.g. Solaris: 12; FreeBSD: 8 + * pattern conventions differ across systems. + * So take care in tweaking the template below. + * Arguably, this could be yet another smb.conf parameter. + */ +static const char *ut_line_template = +#if defined(__FreeBSD__) + "smb%d" ; +#else + "smb/%d" ; +#endif + +/**************************************************************************** +Fill in a utmp (not utmpx) template +****************************************************************************/ +static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid, + int i, pstring host) { +#if defined(HAVE_UT_UT_TIME) struct timeval timeval; - int rc; +#endif /* defined(HAVE_UT_UT_TIME) */ + char line_tmp[1024]; /* plenty big enough for slprintf() */ + int line_len; + int rc = 0; +/* + * ut_name, ut_user: + * Several (all?) systems seems to define one as the other. + * It is easier and clearer simply to let the following take its course, + * rather than to try to detect and optimise. + */ +#if defined(HAVE_UT_UT_USER) pstrcpy(u->ut_user, conn->user); - rc = ut_id_encode(i, u->ut_id); - slprintf(u->ut_line, 12, "smb/%d", i); +#endif /* defined(HAVE_UT_UT_USER) */ +#if defined(HAVE_UT_UT_NAME) + pstrcpy(u->ut_name, conn->user); +#endif /* defined(HAVE_UT_UT_NAME) */ + +/* + * ut_line: + * If size limit proves troublesome, then perhaps use "ut_id_encode()". + * + * Temporary variable "line_tmp" avoids trouble: + * o with unwanted trailing NULL if ut_line full; + * o with overflow if ut_line would be more than full. + */ + memset(line_tmp, '\0', sizeof(line_tmp)); + slprintf(line_tmp, sizeof(line_tmp), (char *) ut_line_template, i); + line_len = strlen(line_tmp); + if (line_len <= sizeof(u->ut_line)) { + memcpy(u->ut_line, line_tmp, sizeof(u->ut_line)); + } + else { + DEBUG(1,("utmp_fill: ut_line exceeds field length(%d > %d)\n", + line_len, sizeof(u->ut_line))); + return(1); + } + +#if defined(HAVE_UT_UT_PID) u->ut_pid = pid; +#endif /* defined(HAVE_UT_UT_PID) */ +/* + * ut_time, ut_tv: + * Some have one, some the other. Many have both, but defined (aliased). + * It is easier and clearer simply to let the following take its course. + * But note that we do the more precise ut_tv as the final assignment. + */ +#if defined(HAVE_UT_UT_TIME) gettimeofday(&timeval, NULL); u->ut_time = timeval.tv_sec; +#endif /* defined(HAVE_UT_UT_TIME) */ + +#if defined(HAVE_UT_UT_TV) + gettimeofday(&timeval, NULL); + u->ut_tv = timeval; +#endif /* defined(HAVE_UT_UT_TV) */ + +#if defined(HAVE_UT_UT_HOST) + if (host) { + pstrcpy(u->ut_host, host); + } +#endif /* defined(HAVE_UT_UT_HOST) */ + +#if defined(HAVE_UT_UT_ADDR) + /* + * "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20. + * Volunteer to implement, please ... + */ +#endif /* defined(HAVE_UT_UT_ADDR) */ + +#if defined(HAVE_UT_UT_ID) + rc = ut_id_encode(i, u->ut_id); +#endif /* defined(HAVE_UT_UT_ID) */ return(rc); } -/* Default path (if possible) */ +/**************************************************************************** +Default paths to various {u,w}tmp{,x} files +****************************************************************************/ #ifdef HAVE_UTMPX_H -# ifdef UTMPX_FILE -static char *ut_pathname = UTMPX_FILE; +static const char *ux_pathname = +# if defined (UTMPX_FILE) + UTMPX_FILE ; +# elif defined (_UTMPX_FILE) + _UTMPX_FILE ; +# elif defined (_PATH_UTMPX) + _PATH_UTMPX ; # else -static char *ut_pathname = ""; + "" ; # endif -# ifdef WTMPX_FILE -static char *wt_pathname = WTMPX_FILE; + +static const char *wx_pathname = +# if defined (WTMPX_FILE) + WTMPX_FILE ; +# elif defined (_WTMPX_FILE) + _WTMPX_FILE ; +# elif defined (_PATH_WTMPX) + _PATH_WTMPX ; # else -static char *wt_pathname = ""; + "" ; # endif -#else /* HAVE_UTMPX_H */ +#endif /* HAVE_UTMPX_H */ -# ifdef UTMP_FILE -static char *ut_pathname = UTMP_FILE; +static const char *ut_pathname = +# if defined (UTMP_FILE) + UTMP_FILE ; +# elif defined (_UTMP_FILE) + _UTMP_FILE ; +# elif defined (_PATH_UTMP) + _PATH_UTMP ; # else -static char *ut_pathname = ""; + "" ; # endif -# ifdef WTMP_FILE -static char *wt_pathname = WTMP_FILE; + +static const char *wt_pathname = +# if defined (WTMP_FILE) + WTMP_FILE ; +# elif defined (_WTMP_FILE) + _WTMP_FILE ; +# elif defined (_PATH_WTMP) + _PATH_WTMP ; # else -static char *wt_pathname = ""; + "" ; # endif -#endif /* HAVE_UTMPX_H */ +/* BSD-like systems might want "lastlog" support. */ +/* *** Not yet implemented */ +#ifndef HAVE_PUTUTLINE /* see "pututline_my()" */ +static const char *ll_pathname = +# if defined (_PATH_LASTLOG) /* what other names (if any?) */ + _PATH_LASTLOG ; +# else + "" ; +# endif /* _PATH_LASTLOG */ +#endif /* HAVE_PUTUTLINE */ -static void uw_pathname(pstring fname, const char *uw_name) +/* + * Get name of {u,w}tmp{,x} file. + * return: fname contains filename + * Possibly empty if this code not yet ported to this system. + * + * utmp{,x}: try "utmp dir", then default (a define) + * wtmp{,x}: try "wtmp dir", then "utmp dir", then default (a define) + */ +static void uw_pathname(pstring fname, const char *uw_name, const char *uw_default) { pstring dirname; - pstrcpy(dirname,lp_utmpdir()); - trim_string(dirname,"","/"); + pstrcpy(dirname, ""); + + /* For w-files, first look for explicit "wtmp dir" */ + if (uw_name[0] == 'w') { + pstrcpy(dirname,lp_wtmpdir()); + trim_string(dirname,"","/"); + } - /* Given directory: use it */ + /* For u-files and non-explicit w-dir, look for "utmp dir" */ + if (dirname == 0 || strlen(dirname) == 0) { + pstrcpy(dirname,lp_utmpdir()); + trim_string(dirname,"","/"); + } + + /* If explicit directory above, use it */ if (dirname != 0 && strlen(dirname) != 0) { pstrcpy(fname, dirname); pstrcat(fname, "/"); @@ -259,90 +573,256 @@ static void uw_pathname(pstring fname, const char *uw_name) return; } - /* No given directory: attempt to use default paths */ - if (uw_name[0] == 'u') { - pstrcpy(fname, ut_pathname); + /* No explicit directory: attempt to use default paths */ + if (strlen(uw_default) == 0) { + /* No explicit setting, no known default. + * Has it yet been ported to this OS? + */ + DEBUG(2,("uw_pathname: unable to determine pathname\n")); + } + pstrcpy(fname, uw_default); +} + +#ifndef HAVE_PUTUTLINE +/**************************************************************************** +Update utmp file directly. No subroutine interface: probably a BSD system. +****************************************************************************/ +static void pututline_my(pstring uname, struct utmp *u, BOOL claim) +{ + DEBUG(1,("pututline_my: not yet implemented\n")); + /* BSD implementor: may want to consider (or not) adjusting "lastlog" */ +} +#endif /* HAVE_PUTUTLINE */ + +#ifndef HAVE_UPDWTMP +/**************************************************************************** +Update wtmp file directly. No subroutine interface: probably a BSD system. +Credit: Michail Vidiassov +****************************************************************************/ +static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) +{ + int fd; + struct stat buf; + + if (! claim) { + /* + * BSD-like systems: + * may use empty ut_name to distinguish a logout record. + * + * May need "if defined(SUNOS4)" etc. around some of these, + * but try to avoid if possible. + * + * SunOS 4: + * man page indicates ut_name and ut_host both NULL + * FreeBSD 4.0: + * man page appears not to specify (hints non-NULL) + * A correspondent suggest at least ut_name should be NULL + */ + memset((char *)&(u->ut_name), '\0', sizeof(u->ut_name)); + memset((char *)&(u->ut_host), '\0', sizeof(u->ut_host)); + } + /* Stolen from logwtmp function in libutil. + * May be more locking/blocking is needed? + */ + if ((fd = open(wname, O_WRONLY|O_APPEND, 0)) < 0) return; + if (fstat(fd, &buf) == 0) { + if (write(fd, (char *)u, sizeof(struct utmp)) != sizeof(struct utmp)) + (void) ftruncate(fd, buf.st_size); } + (void) close(fd); +} +#endif /* HAVE_UPDWTMP */ - if (uw_name[0] == 'w') { - pstrcpy(fname, wt_pathname); +/**************************************************************************** +Update via utmp/wtmp (not utmpx/wtmpx) +****************************************************************************/ +static void utmp_nox_update(struct utmp *u, pstring host, BOOL claim) +{ + pstring uname, wname; +#if defined(PUTUTLINE_RETURNS_UTMP) + struct utmp *urc; +#endif /* PUTUTLINE_RETURNS_UTMP */ + + uw_pathname(uname, "utmp", ut_pathname); + DEBUG(2,("utmp_nox_update: uname:%s\n", uname)); + +#ifdef HAVE_PUTUTLINE + if (strlen(uname) != 0) { + utmpname(uname); + } + +# if defined(PUTUTLINE_RETURNS_UTMP) + setutent(); + urc = pututline(u); + endutent(); + if (urc == NULL) { + DEBUG(2,("utmp_nox_update: pututline() failed\n")); return; } +# else /* PUTUTLINE_RETURNS_UTMP */ + setutent(); + pututline(u); + endutent(); +# endif /* PUTUTLINE_RETURNS_UTMP */ - pstrcpy(fname, ""); +#else /* HAVE_PUTUTLINE */ + if (strlen(uname) != 0) { + pututline_my(uname, u, claim); + } +#endif /* HAVE_PUTUTLINE */ + + uw_pathname(wname, "wtmp", wt_pathname); + DEBUG(2,("utmp_nox_update: wname:%s\n", wname)); + if (strlen(wname) != 0) { +#ifdef HAVE_UPDWTMP + updwtmp(wname, u); + /* + * updwtmp() and the newer updwtmpx() may be unsymmetrical. + * At least one OS, Solaris 2.x declares the former in the + * "utmpx" (latter) file and context. + * In the Solaris case this is irrelevant: it has both and + * we always prefer the "x" case, so doesn't come here. + * But are there other systems, with no "x", which lack + * updwtmp() perhaps? + */ +#else + updwtmp_my(wname, u, claim); +#endif /* HAVE_UPDWTMP */ + } } -static void utmp_update(const struct utmp *u, const char *host) +/**************************************************************************** +Update via utmpx/wtmpx (preferred) or via utmp/wtmp +****************************************************************************/ +static void utmp_update(struct utmp *u, pstring host, BOOL claim) { - pstring fname; - -#ifdef HAVE_UTMPX_H +#if !defined(HAVE_UTMPX_H) + /* No utmpx stuff. Drop to non-x stuff */ + utmp_nox_update(u, host, claim); +#elif !defined(HAVE_PUTUTXLINE) + /* Odd. Have utmpx.h but no "pututxline()". Drop to non-x stuff */ + DEBUG(1,("utmp_update: have utmpx.h but no pututxline() function\n")); + utmp_nox_update(u, host, claim); +#elif !defined(HAVE_GETUTMPX) + /* Odd. Have utmpx.h but no "getutmpx()". Drop to non-x stuff */ + DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n")); + utmp_nox_update(u, host, claim); +#else + pstring uname, wname; struct utmpx ux, *uxrc; getutmpx(u, &ux); if (host) { #if defined(HAVE_UX_UT_SYSLEN) - ux.ut_syslen = strlen(host); + ux.ut_syslen = strlen(host) + 1; /* include end NULL */ #endif /* defined(HAVE_UX_UT_SYSLEN) */ pstrcpy(ux.ut_host, host); } - uw_pathname(fname, "utmpx"); - DEBUG(2,("utmp_update: fname:%s\n", fname)); - if (strlen(fname) != 0) { - utmpxname(fname); - } - uxrc = pututxline(&ux); - if (uxrc == NULL) { - DEBUG(2,("utmp_update: pututxline() failed\n")); - return; - } - - uw_pathname(fname, "wtmpx"); - DEBUG(2,("utmp_update: fname:%s\n", fname)); - if (strlen(fname) != 0) { - updwtmpx(fname, &ux); + uw_pathname(uname, "utmpx", ux_pathname); + uw_pathname(wname, "wtmpx", wx_pathname); + DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname)); + /* + * Check for either uname or wname being empty. + * Some systems, such as Redhat 6, have a "utmpx.h" which doesn't + * define default filenames. + * Also, our local installation has not provided an override. + * Drop to non-x method. (E.g. RH6 has good defaults in "utmp.h".) + */ + if ((strlen(uname) == 0) || (strlen(wname) == 0)) { + utmp_nox_update(u, host, claim); } + else { + utmpxname(uname); + setutxent(); + uxrc = pututxline(&ux); + endutxent(); + if (uxrc == NULL) { + DEBUG(2,("utmp_update: pututxline() failed\n")); + return; + } +#ifdef HAVE_UPDWTMPX + updwtmpx(wname, &ux); #else - uw_pathname(fname, "utmp"); - DEBUG(2,("utmp_update: fname:%s\n", fname)); - if (strlen(fname) != 0) { - utmpname(fname); + /* Have utmpx.h but no "updwtmpx()". */ + DEBUG(1,("utmp_update: no updwtmpx() function\n")); +#endif /* HAVE_UPDWTMPX */ } - pututline(u); - - uw_pathname(fname, "wtmp"); - - /* *** Hmmm. Appending wtmp (as distinct from overwriting utmp) has - me baffled. How is it to be done? *** */ -#endif +#endif /* HAVE_UTMPX_H */ } +/* + * "utmp consolidate": some background: + * False (default): + * In "utmp" files note every connection via this process. + * Argument "i" is simply a tty-like number we can use as-is. + * True: + * In "utmp" files, only note first open and final close. Keep: + * o count of open processes; + * o record value of first "i", to use as "i" in final close. + */ +static int utmp_count = 0; +static int utmp_consolidate_conn_num; + +/**************************************************************************** +close a connection +****************************************************************************/ static void utmp_yield(pid_t pid, const connection_struct *conn) { struct utmp u; + int conn_num, i; if (! lp_utmp(SNUM(conn))) { DEBUG(2,("utmp_yield: lp_utmp() NULL\n")); return; } - DEBUG(2,("utmp_yield: conn: user:%s cnum:%d\n", - conn->user, conn->cnum)); + i = utmp_yield_tdb(conn); + if (i < 0) { + DEBUG(2,("utmp_yield: utmp_yield_tdb() failed\n")); + return; + } + conn_num = i; + DEBUG(2,("utmp_yield: conn: user:%s cnum:%d i:%d (utmp_count:%d)\n", + conn->user, conn->cnum, i, utmp_count)); + + utmp_count -= 1; + if (lp_utmp_consolidate()) { + if (utmp_count > 0) { + DEBUG(2,("utmp_yield: utmp consolidate: %d entries still open\n", utmp_count)); + return; + } + else { + /* consolidate; final close: override conn_num */ + conn_num = utmp_consolidate_conn_num; + } + } memset((char *)&u, '\0', sizeof(struct utmp)); - u.ut_type = DEAD_PROCESS; + +#if defined(HAVE_UT_UT_EXIT) u.ut_exit.e_termination = 0; u.ut_exit.e_exit = 0; - if (utmp_fill(&u, conn, pid, conn->cnum) == 0) { - utmp_update(&u, NULL); +#endif /* defined(HAVE_UT_UT_EXIT) */ + +#if defined(HAVE_UT_UT_TYPE) + u.ut_type = DEAD_PROCESS; +#endif /* defined(HAVE_UT_UT_TYPE) */ + + if (utmp_fill(&u, conn, pid, conn_num, NULL) == 0) { + utmp_update(&u, NULL, False); } } +/**************************************************************************** +open a connection +****************************************************************************/ static void utmp_claim(const struct connections_data *crec, const connection_struct *conn) { struct utmp u; + pstring host; + int i; if (conn == NULL) { DEBUG(2,("utmp_claim: conn NULL\n")); @@ -354,17 +834,47 @@ static void utmp_claim(const struct connections_data *crec, const connection_str return; } - DEBUG(2,("utmp_claim: conn: user:%s cnum:%d\n", - conn->user, conn->cnum)); - DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s\n", - crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name())); + i = utmp_claim_tdb(conn); + if (i < 0) { + DEBUG(2,("utmp_claim: utmp_claim_tdb() failed\n")); + return; + } + pstrcpy(host, lp_utmp_hostname()); + if (host == 0 || strlen(host) == 0) { + pstrcpy(host, crec->machine); + } + else { + /* explicit "utmp host": expand for any "%" variables */ + standard_sub_basic(host); + } + + DEBUG(2,("utmp_claim: conn: user:%s cnum:%d i:%d (utmp_count:%d)\n", + conn->user, conn->cnum, i, utmp_count)); + DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s host:%s\n", + crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name(), host)); + + utmp_count += 1; + if (lp_utmp_consolidate()) { + if (utmp_count > 1) { + DEBUG(2,("utmp_claim: utmp consolidate: %d entries already open\n", (utmp_count-1))); + return; + } + else { + /* consolidate; first open: keep record of "i" */ + utmp_consolidate_conn_num = i; + } + } memset((char *)&u, '\0', sizeof(struct utmp)); + +#if defined(HAVE_UT_UT_TYPE) u.ut_type = USER_PROCESS; - if (utmp_fill(&u, conn, crec->pid, conn->cnum) == 0) { - utmp_update(&u, crec->machine); +#endif /* defined(HAVE_UT_UT_TYPE) */ + + if (utmp_fill(&u, conn, crec->pid, i, host) == 0) { + utmp_update(&u, host, True); } } -#endif +#endif /* WITH_UTMP */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b463ec2479..54b45529d0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -327,7 +327,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p of the mask entry as we scan the acl. ****************************************************************************/ -size_t get_num_posix_entries(acl_t posix_acl, acl_permset_t *posix_mask) +static size_t get_num_posix_entries(acl_t posix_acl, acl_permset_t *posix_mask) { size_t num_entries; acl_entry_t entry; @@ -362,7 +362,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { extern DOM_SID global_sid_World; SMB_STRUCT_STAT sbuf; - SEC_ACE ace_list[6]; + SEC_ACE *ace_list; DOM_SID owner_sid; DOM_SID group_sid; size_t sd_size; @@ -373,13 +373,15 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) int grp_acl_type; SEC_ACCESS other_access; int other_acl_type; - int num_acls = 0; - acl_t posix_acl; + size_t num_acls = 0; + size_t num_dir_acls = 0; + acl_t posix_acl = NULL; + acl_t directory_acl = NULL; *ppdesc = NULL; if(fsp->is_directory || fsp->fd == -1) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(vfs_stat(fsp,fsp->fsp_name, &sbuf) != 0) { return 0; } /* @@ -389,6 +391,13 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) if ((posix_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_ACCESS)) == NULL) return 0; + /* + * If it's a directory get the default POSIX ACL. + */ + + if(fsp->is_directory) { + } + } else { if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { return 0; diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f316156222..ef446ed759 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -62,7 +62,7 @@ static BOOL become_uid(uid_t uid) set_effective_uid(uid); current_user.uid = uid; - DO_PROFILE_INC(uid_changes) + DO_PROFILE_INC(uid_changes); return True; } -- cgit From ff6f0c1a3bd50463228cb6bdcf0018cf6ab4270f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Oct 2000 19:35:43 +0000 Subject: Call standard_sub_advanced() after lp_logon_XX() calls. Jeremy. (This used to be commit d5be2334d4fb007e39565b771cbe68e338a7fe68) --- source3/smbd/lanman.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fa6224b596..3b50960468 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2474,6 +2474,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ pstrcpy(p2, lp_logon_home()); + standard_sub_conn(conn, p2); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); @@ -2510,6 +2511,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ pstrcpy(p2,lp_logon_home()); + standard_sub_conn(conn, p2); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; -- cgit From 5073d116431a03b2d6e00f529dd03c5c19264c33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 4 Nov 2000 06:45:26 +0000 Subject: Fix for admin user being ignored. Jeremy. (This used to be commit f0dcc39d34202ed67d778ff40166856d4c2ad87b) --- source3/smbd/uid.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index fb83e724b8..c181b9a00f 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -121,6 +121,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) return False; if (conn->force_user || + conn->admin_user || lp_security() == SEC_SHARE || !(vuser) || (vuser->guest)) { uid = conn->uid; -- cgit From 6d36edaf437a9d109fe3bfff26c9f6a3b584aaf6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Nov 2000 21:44:33 +0000 Subject: Added a VFS version return to init call. Allows smbd to fail an init if versions don't match. Jeremy. (This used to be commit d0fbb4f5d999abade8930cc6fff231a2af6cccfb) --- source3/smbd/service.c | 2 ++ source3/smbd/vfs.c | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b86f3beadd..fcdd9a376b 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -485,6 +485,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* Loadable object file */ if (!vfs_init_custom(conn)) { + DEBUG(0, ("vfs_init failed\n")); + conn_free(conn); return NULL; } #else diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2f984aee4f..99c8e26fa8 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -94,7 +94,8 @@ int vfs_init_default(connection_struct *conn) #ifdef HAVE_LIBDL BOOL vfs_init_custom(connection_struct *conn) { - struct vfs_ops *ops, *(*fptr)(struct vfs_options *options); + int vfs_version = -1; + struct vfs_ops *ops, *(*init_fptr)(int *); DEBUG(3, ("Initialising custom vfs hooks from %s\n", lp_vfsobj(SNUM(conn)))); @@ -108,22 +109,27 @@ BOOL vfs_init_custom(connection_struct *conn) /* Get handle on vfs_init() symbol */ - fptr = (struct vfs_ops *(*)(struct vfs_options *)) - dlsym(conn->dl_handle, "vfs_init"); + init_fptr = (struct vfs_ops *(*)(int *))dlsym(conn->dl_handle, "vfs_init"); - if (fptr == NULL) { - DEBUG(0, ("No vfs_init() symbol found in %s\n", + if (init_fptr == NULL) { + DEBUG(0, ("No vfs_init() symbol found in %s\n", lp_vfsobj(SNUM(conn)))); - return False; + return False; } /* Initialise vfs_ops structure */ - if ((ops = fptr(NULL)) == NULL) { + if ((ops = init_fptr(&vfs_version)) == NULL) { DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); - return False; + return False; } + if (vfs_version != SMB_VFS_INTERFACE_VERSION) { + DEBUG(0, ("vfs_init returned wrong interface version info (was %d, should be %d)\n", + vfs_version, SMB_VFS_INTERFACE_VERSION )); + return False; + } + /* Fill in unused operations with default (disk based) ones. There's probably a neater way to do this then a whole bunch of if statements. */ -- cgit From e1cc6c85d793f5d86798eaf5ab452b11ed2f73bb Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 8 Nov 2000 00:16:38 +0000 Subject: More merging of printing stuff from appliance. (This used to be commit 18fa724a7969666dd5aa176af187054abc94bfd3) --- source3/smbd/lanman.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3b50960468..944a187ccc 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1892,15 +1892,15 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param switch (function) { case 81: /* delete */ - if (print_job_delete(¤t_user, jobid)) + if (print_job_delete(¤t_user, jobid, &errcode)) errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(¤t_user, jobid)) + if (print_job_pause(¤t_user, jobid, &errcode)) errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(¤t_user, jobid)) + if (print_job_resume(¤t_user, jobid, &errcode)) errcode = NERR_Success; break; } -- cgit From 9fede0dc0dbad51528cd1384023d24549c3f0ba4 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 13 Nov 2000 23:03:34 +0000 Subject: Large commit which restructures the local password storage API. Currently the only backend which works is smbpasswd (tdb, LDAP, and NIS+) are broken, but they were somewhat broken before. :) The following functions implement the storage manipulation interface /*The following definitions come from passdb/pdb_smbpasswd.c */ BOOL pdb_setsampwent (BOOL update); void pdb_endsampwent (void); SAM_ACCOUNT* pdb_getsampwent (void); SAM_ACCOUNT* pdb_getsampwnam (char *username); SAM_ACCOUNT* pdb_getsampwuid (uid_t uid); SAM_ACCOUNT* pdb_getsampwrid (uint32 rid); BOOL pdb_add_sam_account (SAM_ACCOUNT *sampass); BOOL pdb_update_sam_account (SAM_ACCOUNT *sampass, BOOL override); BOOL pdb_delete_sam_account (char* username); There is also a host of pdb_set..() and pdb_get..() functions for manipulating SAM_ACCOUNT struct members. Note that the struct passdb_ops {} has gone away. Also notice that struct smb_passwd (formally in smb.h) has been moved to passdb/pdb_smbpasswd.c and is not accessed outisde of static internal functions in this file. All local password searches should make use of the the SAM_ACCOUNT struct and the previously mentioned functions. I'll write some documentation for this later. The next step is to fix the TDB passdb backend, then work on spliting the backends out into share libraries, and finally get the LDAP backend going. What works and may not: o domain logons from Win9x works o domain logons from WinNT 4 works o user and group enumeration as implemented by Tim works o file and print access works o changing password from Win9x & NT ummm...i'll fix this tonight :) If I broke anything else, just yell and I'll fix it. I think it should be fairly quite. -- jerry (This used to be commit 0b92d0838ebdbe24f34f17e313ecbf61a0301389) --- source3/smbd/chgpasswd.c | 186 +++++++++++++++++++++++------------------------ source3/smbd/lanman.c | 12 +-- source3/smbd/password.c | 104 ++++++++++++++------------ source3/smbd/reply.c | 18 +++-- source3/smbd/server.c | 2 +- source3/smbd/uid.c | 2 +- 6 files changed, 168 insertions(+), 156 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 1f1ee96713..ba68557fdf 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -52,6 +52,7 @@ #include "includes.h" extern int DEBUGLEVEL; +extern struct passdb_ops pdb_ops; #if ALLOW_CHANGE_PASSWORD @@ -541,62 +542,64 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) ************************************************************/ BOOL check_lanman_password(char *user, uchar * pass1, - uchar * pass2, struct smb_passwd **psmbpw) + uchar * pass2, SAM_ACCOUNT **hnd) { static uchar null_pw[16]; uchar unenc_new_pw[16]; uchar unenc_old_pw[16]; - struct smb_passwd *smbpw; - - *psmbpw = NULL; + SAM_ACCOUNT *sampass = NULL; + uint16 acct_ctrl; + BYTE *lanman_pw; become_root(); - smbpw = getsmbpwnam(user); + sampass = pdb_getsampwnam(user); unbecome_root(); - if (smbpw == NULL) + if (sampass == NULL) { - DEBUG(0, - ("check_lanman_password: getsmbpwnam returned NULL\n")); + DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); return False; } + + acct_ctrl = pdb_get_acct_ctrl (sampass); + lanman_pw = pdb_get_lanman_passwd (sampass); - if (smbpw->acct_ctrl & ACB_DISABLED) + if (acct_ctrl & ACB_DISABLED) { - DEBUG(0, - ("check_lanman_password: account %s disabled.\n", + DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } - if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + if ((lanman_pw == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { uchar no_pw[14]; memset(no_pw, '\0', 14); E_P16(no_pw, null_pw); - smbpw->smb_passwd = null_pw; + pdb_set_lanman_passwd (sampass, null_pw); } - else if (smbpw->smb_passwd == NULL) + else if (lanman_pw == NULL) { DEBUG(0, ("check_lanman_password: no lanman password !\n")); return False; } /* Get the new lanman hash. */ - D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + D_P16(lanman_pw, pass2, unenc_new_pw); /* Use this to get the old lanman hash. */ D_P16(unenc_new_pw, pass1, unenc_old_pw); /* Check that the two old passwords match. */ - if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + if (memcmp(lanman_pw, unenc_old_pw, 16)) { - DEBUG(0, - ("check_lanman_password: old password doesn't match.\n")); + DEBUG(0,("check_lanman_password: old password doesn't match.\n")); return False; } - *psmbpw = smbpw; + /* this saves the pointer for the caller */ + *hnd = sampass; + return True; } @@ -606,50 +609,52 @@ BOOL check_lanman_password(char *user, uchar * pass1, no longer be valid. ************************************************************/ -BOOL change_lanman_password(struct smb_passwd *smbpw, uchar * pass1, +BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, uchar * pass2) { static uchar null_pw[16]; uchar unenc_new_pw[16]; BOOL ret; + uint16 acct_ctrl; + BYTE *pwd; - if (smbpw == NULL) + if (sampass == NULL) { - DEBUG(0, - ("change_lanman_password: no smb password entry.\n")); + DEBUG(0,("change_lanman_password: no smb password entry.\n")); return False; } + acct_ctrl = pdb_get_acct_ctrl(sampass); + pwd = pdb_get_lanman_passwd(sampass); - if (smbpw->acct_ctrl & ACB_DISABLED) + if (acct_ctrl & ACB_DISABLED) { - DEBUG(0, - ("change_lanman_password: account %s disabled.\n", - smbpw->smb_name)); + DEBUG(0,("change_lanman_password: account %s disabled.\n", + pdb_get_username(sampass))); return False; } - if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) + if ((pwd == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { uchar no_pw[14]; memset(no_pw, '\0', 14); E_P16(no_pw, null_pw); - smbpw->smb_passwd = null_pw; + pdb_set_lanman_passwd(sampass, null_pw); } - else if (smbpw->smb_passwd == NULL) + else if (pwd == NULL) { - DEBUG(0, ("change_lanman_password: no lanman password !\n")); + DEBUG(0,("change_lanman_password: no lanman password !\n")); return False; } /* Get the new lanman hash. */ - D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + D_P16(pwd, pass2, unenc_new_pw); - smbpw->smb_passwd = unenc_new_pw; - smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ + pdb_set_lanman_passwd(sampass, unenc_new_pw); + pdb_set_nt_passwd (sampass, NULL); /* We lose the NT hash. Sorry. */ - /* Now write it into the file. */ + /* Now flush the sam_passwd struct to persistent storage */ become_root(); - ret = mod_smbpwd_entry(smbpw, False); + ret = pdb_update_sam_account (sampass, False); unbecome_root(); return ret; @@ -663,10 +668,9 @@ BOOL pass_oem_change(char *user, uchar * ntdata, uchar * nthash) { fstring new_passwd; - struct smb_passwd *sampw; + SAM_ACCOUNT *sampass = NULL; BOOL ret = check_oem_password(user, lmdata, lmhash, ntdata, nthash, - &sampw, - new_passwd, sizeof(new_passwd)); + &sampass, new_passwd, sizeof(new_passwd)); /* * At this point we have the new case-sensitive plaintext @@ -684,7 +688,7 @@ BOOL pass_oem_change(char *user, if (ret) { - ret = change_oem_password(sampw, new_passwd, False); + ret = change_oem_password(sampass, new_passwd, False); } memset(new_passwd, 0, sizeof(new_passwd)); @@ -702,12 +706,14 @@ BOOL pass_oem_change(char *user, BOOL check_oem_password(char *user, uchar * lmdata, uchar * lmhash, uchar * ntdata, uchar * nthash, - struct smb_passwd **psmbpw, char *new_passwd, + SAM_ACCOUNT **hnd, char *new_passwd, int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; - struct smb_passwd *smbpw = NULL; + SAM_ACCOUNT *sampass = NULL; + BYTE *lanman_pw, *nt_pw; + uint16 acct_ctrl; int new_pw_len; uchar new_ntp16[16]; uchar unenc_old_ntpw[16]; @@ -718,20 +724,19 @@ BOOL check_oem_password(char *user, BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); become_root(); - *psmbpw = smbpw = getsmbpwnam(user); + *hnd = sampass = pdb_getsampwnam(user); unbecome_root(); - if (smbpw == NULL) + if (sampass == NULL) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); return False; } - - if (smbpw->acct_ctrl & ACB_DISABLED) + acct_ctrl = pdb_get_acct_ctrl(sampass); + + if (acct_ctrl & ACB_DISABLED) { - DEBUG(0, - ("check_lanman_password: account %s disabled.\n", - user)); + DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } @@ -740,31 +745,33 @@ BOOL check_oem_password(char *user, no_pw[1] = 0; nt_lm_owf_gen(no_pw, null_ntpw, null_pw); + /* save pointers to passwords so we don't have to keep looking them up */ + lanman_pw = pdb_get_lanman_passwd(sampass); + nt_pw = pdb_get_nt_passwd (sampass); + /* check for null passwords */ - if (smbpw->smb_passwd == NULL) + if (lanman_pw == NULL) { - if (smbpw->acct_ctrl & ACB_PWNOTREQ) + if (acct_ctrl & ACB_PWNOTREQ) { - smbpw->smb_passwd = null_pw; + pdb_set_lanman_passwd(sampass, null_pw); } else { - DEBUG(0, - ("check_oem_password: no lanman password !\n")); + DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } } - if (smbpw->smb_nt_passwd == NULL && nt_pass_set) + if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) { - if (smbpw->acct_ctrl & ACB_PWNOTREQ) + if (acct_ctrl & ACB_PWNOTREQ) { - smbpw->smb_nt_passwd = null_pw; + pdb_set_nt_passwd(sampass, null_pw); } else { - DEBUG(0, - ("check_oem_password: no ntlm password !\n")); + DEBUG(0,("check_oem_password: no ntlm password !\n")); return False; } } @@ -772,7 +779,7 @@ BOOL check_oem_password(char *user, /* * Call the hash function to get the new password. */ - SamOEMhash((uchar *) lmdata, (uchar *) smbpw->smb_passwd, True); + SamOEMhash((uchar *) lmdata, (uchar *)lanman_pw, True); /* * The length of the new password is in the last 4 bytes of @@ -782,8 +789,7 @@ BOOL check_oem_password(char *user, new_pw_len = IVAL(lmdata, 512); if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { - DEBUG(0, - ("check_oem_password: incorrect password length (%d).\n", + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } @@ -796,9 +802,7 @@ BOOL check_oem_password(char *user, int uni_pw_len = new_pw_len; char *pw; new_pw_len /= 2; - pw = - dos_unistrn2((uint16 *)(&lmdata[512 - uni_pw_len]), - new_pw_len); + pw = dos_unistrn2((uint16 *)(&lmdata[512 - uni_pw_len]),new_pw_len); memcpy(new_passwd, pw, new_pw_len + 1); } else @@ -822,10 +826,9 @@ BOOL check_oem_password(char *user, */ D_P16(new_p16, lmhash, unenc_old_pw); - if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + if (memcmp(lanman_pw, unenc_old_pw, 16)) { - DEBUG(0, - ("check_oem_password: old lm password doesn't match.\n")); + DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); return False; } @@ -843,17 +846,15 @@ BOOL check_oem_password(char *user, D_P16(new_ntp16, lmhash, unenc_old_pw); D_P16(new_ntp16, nthash, unenc_old_ntpw); - if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + if (memcmp(lanman_pw, unenc_old_pw, 16)) { - DEBUG(0, - ("check_oem_password: old lm password doesn't match.\n")); + DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); return False; } - if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16)) + if (memcmp(nt_pw, unenc_old_ntpw, 16)) { - DEBUG(0, - ("check_oem_password: old nt password doesn't match.\n")); + DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); return False; } #ifdef DEBUG_PASSWORD @@ -869,7 +870,7 @@ BOOL check_oem_password(char *user, override = True, override XXXXXXXXXX'd password ************************************************************/ -BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, +BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd, BOOL override) { int ret; @@ -878,12 +879,12 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); - smbpw->smb_passwd = new_p16; - smbpw->smb_nt_passwd = new_nt_p16; + pdb_set_lanman_passwd (hnd, new_p16); + pdb_set_nt_passwd (hnd, new_nt_p16); /* Now write it into the file. */ become_root(); - ret = mod_smbpwd_entry(smbpw, override); + ret = pdb_update_sam_account (hnd, override); unbecome_root(); memset(new_passwd, '\0', strlen(new_passwd)); @@ -896,45 +897,42 @@ BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, ***********************************************************/ BOOL check_plaintext_password(char *user, char *old_passwd, - int old_passwd_size, struct smb_passwd **psmbpw) + int old_passwd_size, SAM_ACCOUNT **hnd) { - struct smb_passwd *smbpw = NULL; + SAM_ACCOUNT *sampass = NULL; uchar old_pw[16], old_ntpw[16]; become_root(); - *psmbpw = smbpw = getsmbpwnam(user); + *hnd = sampass = pdb_getsampwnam(user); unbecome_root(); - if (smbpw == NULL) + if (sampass == NULL) { - DEBUG(0, - ("check_plaintext_password: getsmbpwnam returned NULL\n")); + DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); return False; } - if (smbpw->acct_ctrl & ACB_DISABLED) + if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { - DEBUG(0, - ("check_plaintext_password: account %s disabled.\n", - user)); + DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); return (False); } nt_lm_owf_gen(old_passwd, old_ntpw, old_pw); #ifdef DEBUG_PASSWORD - DEBUG(100, ("check_plaintext_password: smbpw->smb_nt_passwd \n")); - dump_data(100, smbpw->smb_nt_passwd, 16); + DEBUG(100, ("check_plaintext_password: nt_passwd \n")); + dump_data(100, pdb_get_nt_passwd(sampass), 16); DEBUG(100, ("check_plaintext_password: old_ntpw \n")); dump_data(100, old_ntpw, 16); - DEBUG(100, ("check_plaintext_password: smbpw->smb_passwd \n")); - dump_data(100, smbpw->smb_passwd, 16); + DEBUG(100, ("check_plaintext_password: lanman_passwd \n")); + dump_data(100, pdb_get_lanman_passwd, 16); DEBUG(100, ("check_plaintext_password: old_pw\n")); dump_data(100, old_pw, 16); #endif - if (memcmp(smbpw->smb_nt_passwd, old_ntpw, 16) - && memcmp(smbpw->smb_passwd, old_pw, 16)) + if (memcmp(pdb_get_nt_passwd(sampass), old_ntpw, 16) + && memcmp(pdb_get_lanman_passwd(sampass), old_pw, 16)) return (False); else return (True); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 944a187ccc..fe6b22a9bf 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1733,7 +1733,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param { fstring saved_pass2; - struct smb_passwd *smbpw = NULL; + SAM_ACCOUNT *sampass; /* * Save the new password as change_oem_password overwrites it @@ -1742,8 +1742,8 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param fstrcpy(saved_pass2, pass2); - if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) && - change_oem_password(smbpw,pass2,False)) + if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) && + change_oem_password(sampass,pass2,False)) { SSVAL(*rparam,0,NERR_Success); @@ -1784,10 +1784,10 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if(SVAL(*rparam,0) != NERR_Success) { - struct smb_passwd *sampw = NULL; + SAM_ACCOUNT *hnd = NULL; - if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) && - change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2)) + if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && + change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2)) { SSVAL(*rparam,0,NERR_Success); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 55c7f0709b..934b3155f3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -289,15 +289,15 @@ update the encrypted smbpasswd file from the plaintext username and password *****************************************************************************/ static BOOL update_smbpassword_file(char *user, char *password) { - struct smb_passwd *smbpw; - BOOL ret; + SAM_ACCOUNT *sampass = NULL; + BOOL ret; become_root(); - smbpw = getsmbpwnam(user); + sampass = pdb_getsampwnam(user); unbecome_root(); - if(smbpw == NULL) { - DEBUG(0,("getsmbpwnam returned NULL\n")); + if(sampass == NULL) { + DEBUG(0,("pdb_getsampwnam returned NULL\n")); return False; } @@ -305,11 +305,11 @@ static BOOL update_smbpassword_file(char *user, char *password) * Remove the account disabled flag - we are updating the * users password from a login. */ - smbpw->acct_ctrl &= ~ACB_DISABLED; + pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED); /* Here, the flag is one, because we want to ignore the XXXXXXX'd out password */ - ret = change_oem_password( smbpw, password, True); + ret = change_oem_password( sampass, password, True); if (ret == False) { DEBUG(3,("change_oem_password returned False\n")); } @@ -317,10 +317,6 @@ static BOOL update_smbpassword_file(char *user, char *password) return ret; } - - - - /**************************************************************************** core of smb password checking routine. ****************************************************************************/ @@ -367,19 +363,22 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], +BOOL smb_password_ok(SAM_ACCOUNT *sampass, uchar chal[8], uchar lm_pass[24], uchar nt_pass[24]) { uchar challenge[8]; + char* user_name; + BYTE *nt_pw, *lm_pw; - if (!lm_pass || !smb_pass) return(False); + if (!lm_pass || !sampass) + return(False); - DEBUG(4,("Checking SMB password for user %s\n", - smb_pass->smb_name)); + user_name = pdb_get_username(sampass); + + DEBUG(4,("Checking SMB password for user %s\n",user_name)); - if(smb_pass->acct_ctrl & ACB_DISABLED) { - DEBUG(1,("account for user %s was disabled.\n", - smb_pass->smb_name)); + if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { + DEBUG(1,("account for user %s was disabled.\n", user_name)); return(False); } @@ -398,35 +397,36 @@ BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8], memcpy(challenge, chal, 8); } - if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) { + nt_pw = pdb_get_nt_passwd(sampass); + + if ((Protocol >= PROTOCOL_NT1) && (nt_pw != NULL)) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_password_check((char *)nt_pass, - (uchar *)smb_pass->smb_nt_passwd, - challenge)) { + if (smb_password_check((char *)nt_pass, (uchar *)nt_pw, challenge)) + { DEBUG(4,("NT MD4 password check succeeded\n")); return(True); } DEBUG(4,("NT MD4 password check failed\n")); } - /* Try against the lanman password. smb_pass->smb_passwd == NULL means - no password, allow access. */ + /* Try against the lanman password. pdb_get_lanman_passwd(sampass) == NULL + means no password, allow access. */ DEBUG(4,("Checking LM MD4 password\n")); - if((smb_pass->smb_passwd == NULL) && - (smb_pass->acct_ctrl & ACB_PWNOTREQ)) { - DEBUG(4,("no password required for user %s\n", - smb_pass->smb_name)); + lm_pw = pdb_get_lanman_passwd(sampass); + + if((lm_pw == NULL) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) + { + DEBUG(4,("no password required for user %s\n",user_name)); return True; } - if((smb_pass->smb_passwd != NULL) && - smb_password_check((char *)lm_pass, - (uchar *)smb_pass->smb_passwd, challenge)) { + if((lm_pw != NULL) && smb_password_check((char *)lm_pass,(uchar *)lm_pw, challenge)) + { DEBUG(4,("LM MD4 password check succeeded\n")); return(True); } @@ -443,18 +443,19 @@ SMB hash return True if the password is correct, False otherwise ****************************************************************************/ -BOOL pass_check_smb(char *user, char *domain, - uchar *chal, uchar *lm_pwd, uchar *nt_pwd, - struct passwd *pwd) +BOOL pass_check_smb(char *user, char *domain, uchar *chal, + uchar *lm_pwd, uchar *nt_pwd, struct passwd *pwd) { struct passwd *pass; - struct smb_passwd *smb_pass; + SAM_ACCOUNT *sampass; if (!lm_pwd || !nt_pwd) { return(False); } + /* FIXME! this code looks to be unnecessary now that the passdb + validates that the username exists and has a valid uid */ if (pwd != NULL && user == NULL) { pass = (struct passwd *) pwd; @@ -462,6 +463,8 @@ BOOL pass_check_smb(char *user, char *domain, } else { + /* I don't get this call here. I think it should be moved. + Need to check on it. --jerry */ pass = smb_getpwnam(user,True); } @@ -471,38 +474,45 @@ BOOL pass_check_smb(char *user, char *domain, return(False); } - smb_pass = getsmbpwnam(user); - - if (smb_pass == NULL) + /* get the account information */ + sampass = pdb_getsampwnam(user); + if (sampass == NULL) { - DEBUG(1,("Couldn't find user '%s' in smb_passwd file.\n", user)); + DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user)); return(False); } /* Quit if the account was disabled. */ - if(smb_pass->acct_ctrl & ACB_DISABLED) { + if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { DEBUG(1,("Account for user '%s' was disabled.\n", user)); return(False); } - /* Ensure the uid's match */ + /* Ensure the uid's match + FIXME! This also seems unnecessary --jerry */ +#if 0 /* GWC */ if (smb_pass->smb_userid != pass->pw_uid) { DEBUG(0,("Error : UNIX and SMB uids in password files do not match for user '%s'!\n", user)); return(False); } +#endif - if (smb_pass->acct_ctrl & ACB_PWNOTREQ) { - if (lp_null_passwords()) { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", smb_pass->smb_name)); + if (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) + { + if (lp_null_passwords()) + { + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user)); return(True); - } else { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", smb_pass->smb_name)); + } + else + { + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user)); return(False); } } - if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) + if (smb_password_ok(sampass, chal, lm_pwd, nt_pwd)) { return(True); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4fd9f9c42d..fa8aa11277 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -439,16 +439,19 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out char *smb_passwd, int smb_passlen, char *smb_nt_passwd, int smb_nt_passlen) { - struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ + /* check if trust account exists */ + SAM_ACCOUNT *sam_trust_acct = NULL; + uint16 acct_ctrl; + if (lp_security() == SEC_USER) { - smb_trust_acct = getsmbpwnam(user); + sam_trust_acct = pdb_getsampwnam(user); } else { DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (smb_trust_acct == NULL) { + if (sam_trust_acct == NULL) { /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); @@ -460,25 +463,26 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { + if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (smb_trust_acct->acct_ctrl & ACB_DOMTRUST) { + acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct); + if (acct_ctrl & ACB_DOMTRUST) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); } - if (smb_trust_acct->acct_ctrl & ACB_SVRTRUST) { + if (acct_ctrl & ACB_SVRTRUST) { DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); } - if (smb_trust_acct->acct_ctrl & ACB_WSTRUST) { + if (acct_ctrl & ACB_WSTRUST) { DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e4dd661ea5..823536f2ab 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -729,7 +729,7 @@ static void usage(char *pname) exit(1); } - if(!initialize_password_db()) { + if(!initialize_password_db(False)) { exit(1); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c181b9a00f..d82edcbfae 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -243,8 +243,8 @@ BOOL unbecome_authenticated_pipe_user(pipes_struct *p) return pop_sec_ctx(); } -/* Temporarily become a root user. Must match with unbecome_root(). */ +/* Temporarily become a root user. Must match with unbecome_root(). */ void become_root(void) { push_sec_ctx(); -- cgit From 4bce271e4fe239a8b4aac2bb65a52165d68d8ea5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Nov 2000 21:56:32 +0000 Subject: Merge from appliance head of JR's changes for driver versioning. Jeremy. (This used to be commit cdbd2e99775642dc2e92004be9014bf38a92d80f) --- source3/smbd/reply.c | 65 +++++++++++++++++++++------------ source3/smbd/sec_ctx.c | 2 +- source3/smbd/uid.c | 50 +++++++++++++++++++------- source3/smbd/vfs.c | 97 +++++++++++++++++++++++++++++++------------------- 4 files changed, 141 insertions(+), 73 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fa8aa11277..0b3b5bbe27 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1882,14 +1882,13 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) } /**************************************************************************** - Reply to a unlink + The guts of the unlink command, split out so it may be called by the NT SMB + code. ****************************************************************************/ -int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, + int dirtype, char *name) { - int outsize = 0; - pstring name; - int dirtype; pstring directory; pstring mask; char *p; @@ -1900,18 +1899,9 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; BOOL rc = True; SMB_STRUCT_STAT sbuf; - START_PROFILE(SMBunlink); *directory = *mask = 0; - dirtype = SVAL(inbuf,smb_vwv0); - - pstrcpy(name,smb_buf(inbuf) + 1); - - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - - DEBUG(3,("reply_unlink : %s\n",name)); - rc = unix_convert(name,conn,0,&bad_path,&sbuf); p = strrchr(name,'/'); @@ -1975,29 +1965,58 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; if (!vfs_unlink(conn,fname)) count++; - DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); + DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dirptr); } } if (count == 0) { - if (exists) { - END_PROFILE(SMBunlink); + if (exists) return(ERROR(ERRDOS,error)); - } else - { - if((errno == ENOENT) && bad_path) - { + else { + if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - END_PROFILE(SMBunlink); return(UNIXERROR(ERRDOS,error)); } } + return 0; +} + +/**************************************************************************** + Reply to a unlink +****************************************************************************/ + +int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +{ + int outsize = 0; + pstring name; + int dirtype; + START_PROFILE(SMBunlink); + + dirtype = SVAL(inbuf,smb_vwv0); + + pstrcpy(name,smb_buf(inbuf) + 1); + + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + + DEBUG(3,("reply_unlink : %s\n",name)); + + outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name); + if(outsize == 0) { + + /* + * Win2k needs a changenotify request response before it will + * update after a rename.. + */ + + process_pending_change_notify_queue((time_t)0); + outsize = set_message(outbuf,0,0,True); + } END_PROFILE(SMBunlink); return(outsize); @@ -3589,7 +3608,6 @@ static BOOL can_rename(char *fname,connection_struct *conn) if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); - return(True); } @@ -3718,6 +3736,7 @@ int rename_internals(connection_struct *conn, * file with the same name so don't check for * vfs_file_exist(). */ + if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && !conn->vfs_ops.rename(conn,zdirectory, diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index ef446ed759..f3adcfce8f 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -221,7 +221,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) /* Call initgroups() to get user groups */ - if (initgroups(user,gid) == -1) { + if (winbind_initgroups(user,gid) == -1) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); if (getuid() == 0) { if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index d82edcbfae..008765cde1 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -243,8 +243,8 @@ BOOL unbecome_authenticated_pipe_user(pipes_struct *p) return pop_sec_ctx(); } - /* Temporarily become a root user. Must match with unbecome_root(). */ + void become_root(void) { push_sec_ctx(); @@ -267,25 +267,49 @@ BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern pstring global_myname; fstring sid; + char *sep = lp_winbind_separator(); if (!winbind_lookup_name(name, psid, name_type)) { BOOL ret; - DEBUG(10,("lookup_name: winbind lookup for %s failed - trying local\n", name )); + DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name)); + + /* If we are looking up a domain user, make sure it is + for the local machine only */ + + if (strchr(name, sep[0]) || strchr(name, '\\')) { + fstring domain, username; + + split_domain_name(name, domain, username); + + if (strcasecmp(global_myname, domain) != 0) { + DEBUG(5, ("domain %s is not local\n", domain)); + return False; + } + + ret = local_lookup_name(domain, username, psid, + name_type); + } else { + + ret = local_lookup_name(global_myname, name, psid, + name_type); + } + + if (ret) { + DEBUG(10, + ("lookup_name: (local) %s -> SID %s (type %u)\n", + name, sid_to_string(sid,psid), + (unsigned int)*name_type )); + } else { + DEBUG(10,("lookup name: (local) %s failed.\n", name)); + } - ret = local_lookup_name(global_myname, name, psid, name_type); - if (ret) - DEBUG(10,("lookup_name : (local) %s -> SID %s (type %u)\n", - name, sid_to_string(sid,psid), - (unsigned int)*name_type )); - else - DEBUG(10,("lookup name : (local) %s failed.\n", - name )); return ret; } - DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", - name, sid_to_string(sid,psid), (unsigned int)*name_type )); + DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", + name, sid_to_string(sid, psid), + (unsigned int)*name_type)); return True; } @@ -300,7 +324,7 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE return False; /* Check if this is our own sid. This should perhaps be done by - winbind? For the moment handle it here. */ + winbind? For the moment handle it here. */ if (sid->num_auths == 5) { DOM_SID tmp_sid; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 99c8e26fa8..77b42361ed 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1,19 +1,19 @@ -/* +/* Unix SMB/Netbios implementation. Version 1.9. VFS initialisation and support functions Copyright (C) Tim Potter 1999 - + 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. @@ -36,7 +36,7 @@ struct vfs_syminfo { struct vfs_ops default_vfs_ops = { - /* Disk operations */ + /* Disk operations */ vfswrap_dummy_connect, vfswrap_dummy_disconnect, @@ -112,7 +112,7 @@ BOOL vfs_init_custom(connection_struct *conn) init_fptr = (struct vfs_ops *(*)(int *))dlsym(conn->dl_handle, "vfs_init"); if (init_fptr == NULL) { - DEBUG(0, ("No vfs_init() symbol found in %s\n", + DEBUG(0, ("No vfs_init() symbol found in %s\n", lp_vfsobj(SNUM(conn)))); return False; } @@ -132,10 +132,10 @@ BOOL vfs_init_custom(connection_struct *conn) /* Fill in unused operations with default (disk based) ones. There's probably a neater way to do this then a whole bunch of - if statements. */ + if statements. */ memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); - + if (conn->vfs_ops.connect == NULL) { conn->vfs_ops.connect = default_vfs_ops.connect; } @@ -179,47 +179,47 @@ BOOL vfs_init_custom(connection_struct *conn) if (conn->vfs_ops.read == NULL) { conn->vfs_ops.read = default_vfs_ops.read; } - + if (conn->vfs_ops.write == NULL) { conn->vfs_ops.write = default_vfs_ops.write; } - + if (conn->vfs_ops.lseek == NULL) { conn->vfs_ops.lseek = default_vfs_ops.lseek; } - + if (conn->vfs_ops.rename == NULL) { conn->vfs_ops.rename = default_vfs_ops.rename; } - + if (conn->vfs_ops.fsync == NULL) { conn->vfs_ops.fsync = default_vfs_ops.fsync; } - + if (conn->vfs_ops.stat == NULL) { conn->vfs_ops.stat = default_vfs_ops.stat; } - + if (conn->vfs_ops.fstat == NULL) { conn->vfs_ops.fstat = default_vfs_ops.fstat; } - + if (conn->vfs_ops.lstat == NULL) { conn->vfs_ops.lstat = default_vfs_ops.lstat; } - + if (conn->vfs_ops.unlink == NULL) { conn->vfs_ops.unlink = default_vfs_ops.unlink; } - + if (conn->vfs_ops.chmod == NULL) { conn->vfs_ops.chmod = default_vfs_ops.chmod; } - + if (conn->vfs_ops.chown == NULL) { conn->vfs_ops.chown = default_vfs_ops.chown; } - + if (conn->vfs_ops.chdir == NULL) { conn->vfs_ops.chdir = default_vfs_ops.chdir; } @@ -227,15 +227,15 @@ BOOL vfs_init_custom(connection_struct *conn) if (conn->vfs_ops.getwd == NULL) { conn->vfs_ops.getwd = default_vfs_ops.getwd; } - + if (conn->vfs_ops.utime == NULL) { conn->vfs_ops.utime = default_vfs_ops.utime; } - + if (conn->vfs_ops.ftruncate == NULL) { conn->vfs_ops.ftruncate = default_vfs_ops.ftruncate; } - + if (conn->vfs_ops.lock == NULL) { conn->vfs_ops.lock = default_vfs_ops.lock; } @@ -255,7 +255,7 @@ BOOL vfs_init_custom(connection_struct *conn) if (conn->vfs_ops.set_nt_acl == NULL) { conn->vfs_ops.set_nt_acl = default_vfs_ops.set_nt_acl; } - + return True; } #endif @@ -272,7 +272,7 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT * if (!st) st = &st2; - if (vfs_stat(conn,dname,st) != 0) + if (vfs_stat(conn,dname,st) != 0) return(False); ret = S_ISDIR(st->st_mode); @@ -294,7 +294,7 @@ int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode) pstrcpy(name,dos_to_unix(fname,False)); /* paranoia copy */ if(!(ret=conn->vfs_ops.mkdir(conn,name,mode))) { - /* + /* * Check if high bits should have been set, * then (if bits are missing): add them. * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir. @@ -331,13 +331,38 @@ BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) sbuf = &st; ZERO_STRUCTP(sbuf); - - if (vfs_stat(conn,fname,sbuf) != 0) + + if (vfs_stat(conn,fname,sbuf) != 0) return(False); return(S_ISREG(sbuf->st_mode)); } +/**************************************************************************** + Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data) +****************************************************************************/ + +ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) +{ + size_t total=0; + + while (total < byte_count) + { + ssize_t ret = fsp->conn->vfs_ops.read(fsp, fsp->fd, buf + total, + byte_count - total); + + if (ret == 0) return total; + if (ret == -1) { + if (errno == EINTR) + continue; + else + return -1; + } + total += ret; + } + return (ssize_t)total; +} + /**************************************************************************** Write data to a fd on the vfs. ****************************************************************************/ @@ -363,11 +388,11 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) Transfer some data between two file_struct's. ****************************************************************************/ -SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, +SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, int out_fd, files_struct *out_fsp, SMB_OFF_T n, char *header, int headlen, int align) { - static char *buf=NULL; + static char *buf=NULL; static int size=0; char *buf1,*abuf; SMB_OFF_T total = 0; @@ -425,7 +450,7 @@ SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, } if (s > ret) { - ret += in_fsp ? + ret += in_fsp ? in_fsp->conn->vfs_ops.read(in_fsp,in_fsp->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); } @@ -459,7 +484,7 @@ char *vfs_readdirname(connection_struct *conn, void *p) if (!p) return(NULL); - + ptr = (struct dirent *)conn->vfs_ops.readdir(conn,p); if (!ptr) return(NULL); @@ -497,7 +522,7 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr) { struct vfs_options *new_option, **options = (struct vfs_options **)ptr; int i; - + /* Create new vfs option */ new_option = (struct vfs_options *)malloc(sizeof(*new_option)); @@ -508,7 +533,7 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr) ZERO_STRUCTP(new_option); /* Get name and value */ - + new_option->name = strtok(pszParmValue, "="); if (new_option->name == NULL) { @@ -714,7 +739,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) } /******************************************************************* - Reduce a file name, removing .. elements and checking that + Reduce a file name, removing .. elements and checking that it is below dir in the heirachy. This uses vfs_GetWd() and so must be run on the system that has the referenced file system. Widelinks are allowed if widelinks is true. @@ -749,7 +774,7 @@ BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks) return(True); } - + DEBUG(3,("reduce_name [%s] [%s]\n",s,dir)); /* remove any double slashes */ @@ -810,7 +835,7 @@ BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks) } { - size_t l = strlen(dir2); + size_t l = strlen(dir2); if (dir2[l-1] == '/') l--; -- cgit From 6f58dd587124c8b85fc62177b26129aaea5819b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Nov 2000 00:59:18 +0000 Subject: Ok - fixed a bug in our levelII oplock code. We need to break a level II on a byte range lock (write lock only, but Win2k breaks on read lock also so I do the same) - if you think about why, this is obvious. Also fixed our client code to do level II oplocks, if requested, and fixed the code where we would assume the client wanted level II if it advertised itself as being level II capable - it may not want that. Jeremy. (This used to be commit 213cd0b5192307cd4b0026cae94b2f52fb1b0c02) --- source3/smbd/fileio.c | 81 +--------------------------------------- source3/smbd/negprot.c | 2 +- source3/smbd/oplock.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++-- source3/smbd/reply.c | 25 +++++++++---- source3/smbd/trans2.c | 31 ++++++++++++---- source3/smbd/vfs-wrap.c | 68 +++++++++++++++++++++++++++++++-- source3/smbd/vfs.c | 18 +++++++++ 7 files changed, 220 insertions(+), 104 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index bb7ab46baa..35e2f1455e 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -195,78 +195,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) * the shared memory area whilst doing this. */ - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { - share_mode_entry *share_list = NULL; - pid_t pid = sys_getpid(); - int token = -1; - int num_share_modes = 0; - int i; - - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("write_file: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); - } - - num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list); - - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &share_list[i]; - - /* - * As there could have been multiple writes waiting at the lock_share_entry - * gate we may not be the first to enter. Hence the state of the op_types - * in the share mode entries may be partly NO_OPLOCK and partly LEVEL_II - * oplock. It will do no harm to re-send break messages to those smbd's - * that are still waiting their turn to remove their LEVEL_II state, and - * also no harm to ignore existing NO_OPLOCK states. JRA. - */ - - if (share_entry->op_type == NO_OPLOCK) - continue; - - /* Paranoia .... */ - if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { - DEBUG(0,("write_file: PANIC. share mode entry %d is an exlusive oplock !\n", i )); - unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); - abort(); - } - - /* - * Check if this is a file we have open (including the - * file we've been called to do write_file on. If so - * then break it directly without releasing the lock. - */ - - if (pid == share_entry->pid) { - files_struct *new_fsp = file_find_dit(fsp->dev, fsp->inode, &share_entry->time); - - /* Paranoia check... */ - if(new_fsp == NULL) { - DEBUG(0,("write_file: PANIC. share mode entry %d is not a local file !\n", i )); - unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); - abort(); - } - oplock_break_level2(new_fsp, True, token); - - } else { - - /* - * This is a remote file and so we send an asynchronous - * message. - */ - - request_oplock_break(share_entry, fsp->dev, fsp->inode); - } - } - - free((char *)share_list); - unlock_share_entry_fsp(fsp); - } - - /* Paranoia check... */ - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(0,("write_file: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name)); - abort(); - } + release_level_2_oplocks_on_change(fsp); #ifdef WITH_PROFILE if (profile_p && profile_p->writecache_total_writes % 500 == 0) { @@ -425,14 +354,6 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", wcp->file_size = wcp->offset + wcp->data_size; -#if 0 - if (set_filelen(fsp->fd, wcp->file_size) == -1) { - DEBUG(0,("write_file: error %s in setting file to length %.0f\n", - strerror(errno), (double)wcp->file_size )); - return -1; - } -#endif - /* * If we used all the data then * return here. diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 1029c8db62..41e95b816d 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -160,7 +160,7 @@ reply for the nt protocol static int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_LEVEL_II_OPLOCKS| (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | (SMB_OFF_T_BITS == 64 ? CAP_LARGE_FILES : 0); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 4a8260421c..366b4d0fec 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -208,10 +208,11 @@ static void downgrade_file_oplock(files_struct *fsp) /**************************************************************************** Remove a file oplock. Copes with level II and exclusive. - Locks then unlocks the share mode lock. + Locks then unlocks the share mode lock. Client can decide to go directly + to none even if a "break-to-level II" was sent. ****************************************************************************/ -BOOL remove_oplock(files_struct *fsp) +BOOL remove_oplock(files_struct *fsp, BOOL break_to_none) { SMB_DEV_T dev = fsp->dev; SMB_INO_T inode = fsp->inode; @@ -224,7 +225,7 @@ BOOL remove_oplock(files_struct *fsp) ret = False; } - if (fsp->sent_oplock_break == EXCLUSIVE_BREAK_SENT) { + if (fsp->sent_oplock_break == EXCLUSIVE_BREAK_SENT || break_to_none) { /* * Deal with a reply when a break-to-none was sent. */ @@ -837,7 +838,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name)); - remove_oplock(fsp); + remove_oplock(fsp,True); global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */ } @@ -1096,6 +1097,96 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) return False; } +/**************************************************************************** + This function is called on any file modification or lock request. If a file + is level 2 oplocked then it must tell all other level 2 holders to break to none. +****************************************************************************/ + +void release_level_2_oplocks_on_change(files_struct *fsp) +{ + share_mode_entry *share_list = NULL; + pid_t pid = sys_getpid(); + int token = -1; + int num_share_modes = 0; + int i; + + /* + * If this file is level II oplocked then we need + * to grab the shared memory lock and inform all + * other files with a level II lock that they need + * to flush their read caches. We keep the lock over + * the shared memory area whilst doing this. + */ + + if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + return; + + if (lock_share_entry_fsp(fsp) == False) { + DEBUG(0,("release_level_2_oplocks_on_change: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); + } + + num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list); + + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &share_list[i]; + + /* + * As there could have been multiple writes waiting at the lock_share_entry + * gate we may not be the first to enter. Hence the state of the op_types + * in the share mode entries may be partly NO_OPLOCK and partly LEVEL_II + * oplock. It will do no harm to re-send break messages to those smbd's + * that are still waiting their turn to remove their LEVEL_II state, and + * also no harm to ignore existing NO_OPLOCK states. JRA. + */ + + if (share_entry->op_type == NO_OPLOCK) + continue; + + /* Paranoia .... */ + if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { + DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is an exlusive oplock !\n", i )); + unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); + abort(); + } + + /* + * Check if this is a file we have open (including the + * file we've been called to do write_file on. If so + * then break it directly without releasing the lock. + */ + + if (pid == share_entry->pid) { + files_struct *new_fsp = file_find_dit(fsp->dev, fsp->inode, &share_entry->time); + + /* Paranoia check... */ + if(new_fsp == NULL) { + DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is not a local file !\n", i )); + unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); + abort(); + } + + oplock_break_level2(new_fsp, True, token); + + } else { + + /* + * This is a remote file and so we send an asynchronous + * message. + */ + + request_oplock_break(share_entry, fsp->dev, fsp->inode); + } + } + + free((char *)share_list); + unlock_share_entry_fsp(fsp); + + /* Paranoia check... */ + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + DEBUG(0,("release_level_2_oplocks_on_change: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name)); + abort(); + } +} /**************************************************************************** setup oplocks for this process diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0b3b5bbe27..dd53eb46e7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2192,6 +2192,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length CHECK_READ(fsp); CHECK_ERROR(fsp); + release_level_2_oplocks_on_change(fsp); + numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -2572,8 +2574,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) { - if((nwritten = set_filelen(fsp->fd, (SMB_OFF_T)startpos)) >= 0) /* tpot vfs */ - set_filelen_write_cache(fsp, startpos); + nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos); } else nwritten = write_file(fsp,data,startpos,numtowrite); @@ -2989,6 +2990,8 @@ int reply_lock(connection_struct *conn, CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); + release_level_2_oplocks_on_change(fsp); + count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); @@ -4243,9 +4246,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, { files_struct *fsp = file_fsp(inbuf,smb_vwv2); unsigned char locktype = CVAL(inbuf,smb_vwv3); -#if 0 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); -#endif uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = 0, offset = 0; @@ -4268,8 +4269,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, */ if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { - DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", - fsp->fnum)); + /* Client can insist on breaking to none. */ + BOOL break_to_none = (oplocklevel == 0); + + DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n", + fsp->fnum, (unsigned int)oplocklevel )); /* * Make sure we have granted an exclusive or batch oplock on this file. @@ -4290,7 +4294,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); } } - if (remove_oplock(fsp) == False) { + if (remove_oplock(fsp, break_to_none) == False) { DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n", fsp->fsp_name )); } @@ -4308,6 +4312,13 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); } } + /* + * We do this check *after* we have checked this is not a oplock break + * response message. JRA. + */ + + release_level_2_oplocks_on_change(fsp); + /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 17a362fb5c..5b6759aec0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1969,17 +1969,32 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) fname, (double)size )); if (fd == -1) { - fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),O_RDWR,0); - if (fd == -1) + files_struct *new_fsp = NULL; + int access_mode = 0; + int action = 0; + + if(global_oplock_break) { + /* Queue this file modify as we are the process of an oplock break. */ + + DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); + DEBUGADD(2,( "in oplock break state.\n")); + + push_oplock_pending_smb_message(inbuf, length); + return -1; + } + + new_fsp = open_file_shared(conn, fname, &sbuf, + SET_OPEN_MODE(DOS_OPEN_RDWR), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + 0, 0, &access_mode, &action); + + if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); - set_filelen(fd, size); /* tpot vfs */ - conn->vfs_ops.close(fsp,fd); + vfs_set_filelen(new_fsp, size); + close_file(new_fsp,True); } else { - set_filelen(fd, size); /* tpot vfs */ + vfs_set_filelen(fsp, size); } - - if(fsp) - set_filelen_write_cache(fsp, size); } SSVAL(params,0,0); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 3b8d5eebcc..ff150b4e40 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -404,13 +404,73 @@ int vfswrap_utime(connection_struct *conn, char *path, struct utimbuf *times) return result; } -int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T offset) +int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) { - int result; - + int result = -1; START_PROFILE(syscall_ftruncate); - result = sys_ftruncate(fd, offset); +#ifdef HAVE_FTRUNCATE_EXTEND + result = sys_ftruncate(fd, len); + END_PROFILE(syscall_ftruncate); + return result; +#else + + /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot + extend a file with ftruncate. Provide alternate implementation + for this */ + + struct vfs_ops *vfs_ops = fsp->conn->vfs_ops; + SMB_STRUCT_STAT st; + char c = 0; + SMB_OFF_T currpos; + + currpos = vfs_ops->lseek(fsp, (SMB_OFF_T)0, SEEK_CUR); + if(currpos == -1) { + goto done; + } + + /* Do an fstat to see if the file is longer than + the requested size (call ftruncate), + or shorter, in which case seek to len - 1 and write 1 + byte of zero */ + if(vfs_ops->fstat(fsp, &st)<0) { + goto done; + } + +#ifdef S_ISFIFO + if (S_ISFIFO(st.st_mode)) { + result = 0; + goto done; + } +#endif + + if(st.st_size == len) { + result = 0; + goto done; + } + + if(st.st_size > len) { + /* Yes this is *deliberately* sys_ftruncate ! JRA */ + result = sys_ftruncate(fd, len); + goto done; + } + + if(vfs_ops->lseek(fsp, len-1, SEEK_SET) != len -1) { + goto done; + } + + if(vfs_ops->write(fsp, &c, 1)!=1) { + goto done; + } + + /* Seek to where we were */ + if(vfs_ops->lseek(fsp, currpos, SEEK_SET) != currpos) { + goto done; + } +#endif + + done: + END_PROFILE(syscall_ftruncate); return result; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 77b42361ed..3db150ab6f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -384,6 +384,24 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) return (ssize_t)total; } +/**************************************************************************** + A vfs set_filelen call. + set the length of a file from a filedescriptor. + Returns 0 on success, -1 on failure. +****************************************************************************/ + +int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) +{ + int ret; + + release_level_2_oplocks_on_change(fsp); + if ((ret = fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, len)) != -1) { + set_filelen_write_cache(fsp, len); + } + + return ret; +} + /**************************************************************************** Transfer some data between two file_struct's. ****************************************************************************/ -- cgit From 9df3d64a2cdb2eafad5f597850f1a2fda8b1f8d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Nov 2000 19:08:55 +0000 Subject: Fix from Jim McDonough @ IBM for OS/2 clients. Jeremy. (This used to be commit f571e1efd01c7b1b500a833df3bd074a8c4c65ec) --- source3/smbd/lanman.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fe6b22a9bf..51472ea309 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -201,7 +201,17 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount) if (i > n) { p->neededlen = i; i = n = 0; +#if 0 + /* + * This is the old error code we used. Aparently + * WinNT/2k systems return ERRbuftoosmall (2123) and + * OS/2 needs this. I'm leaving this here so we can revert + * if needed. JRA. + */ p->errcode = ERRmoredata; +#else + p->errcode = ERRbuftoosmall; +#endif } else p->errcode = NERR_Success; -- cgit From 0de5569304ec1d1650865983dba32f13c313104c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Nov 2000 03:15:18 +0000 Subject: fixed the problem with messages not getting through the problem had nothing to do with being your own pid, it was instead a problem with IPC$ connections not being registered in the connections database and an incorrect test for -1 in the messaging code. These changes also mean that IPC$ shares now show up in smbstatus. That is probably a good thing. (This used to be commit 3575ad10985a18f897e38179ca69fa9a49a7ea02) --- source3/smbd/connection.c | 3 --- source3/smbd/service.c | 60 +++++++++++++++++++++-------------------------- 2 files changed, 27 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 6e088f9f8f..cf455c0a8b 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -72,9 +72,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO struct connections_data crec; TDB_DATA kbuf, dbuf; - if (max_connections <= 0) - return(True); - if (!tdb) { tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index fcdd9a376b..ba381a40e8 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -452,27 +452,25 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->ngroups = 0; conn->groups = NULL; - if (!IS_IPC(conn)) { - /* Find all the groups this uid is in and - store them. Used by become_user() */ - initialise_groups(conn->user, conn->uid, conn->gid); - get_current_groups(&conn->ngroups,&conn->groups); + /* Find all the groups this uid is in and + store them. Used by become_user() */ + initialise_groups(conn->user, conn->uid, conn->gid); + get_current_groups(&conn->ngroups,&conn->groups); - /* check number of connections */ - if (!claim_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn)), - False)) { - DEBUG(1,("too many connections - rejected\n")); - *ecode = ERRnoresource; - conn_free(conn); - return NULL; - } + /* check number of connections */ + if (!claim_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn)), + False)) { + DEBUG(1,("too many connections - rejected\n")); + *ecode = ERRnoresource; + conn_free(conn); + return NULL; + } - if (lp_status(SNUM(conn))) - claim_connection(conn,"", - MAXSTATUS,False); - } /* IS_IPC */ + if (lp_status(SNUM(conn))) + claim_connection(conn,"", + MAXSTATUS,False); conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups); @@ -519,13 +517,11 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!become_user(conn, conn->vuid)) { DEBUG(0,("Can't become connected user!\n")); - if (!IS_IPC(conn)) { - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(conn))) { - yield_connection(conn,"",MAXSTATUS); - } + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); + if (lp_status(SNUM(conn))) { + yield_connection(conn,"",MAXSTATUS); } conn_free(conn); *ecode = ERRbadpw; @@ -536,13 +532,11 @@ connection_struct *make_connection(char *service,char *user,char *password, int DEBUG(0,("Can't change directory to %s (%s)\n", conn->connectpath,strerror(errno))); unbecome_user(); - if (!IS_IPC(conn)) { - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(conn))) - yield_connection(conn,"",MAXSTATUS); - } + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); + if (lp_status(SNUM(conn))) + yield_connection(conn,"",MAXSTATUS); conn_free(conn); *ecode = ERRnosuchshare; return NULL; -- cgit From 5f8ff6056ad2d7432dfe64977cb15364f199b962 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Nov 2000 03:31:03 +0000 Subject: we don't need the separate lp_status() connection records any more (This used to be commit 209e20365e562371aafafea301b4ffecc3d4c3ed) --- source3/smbd/service.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ba381a40e8..2dbb2c0d17 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -468,10 +468,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } - if (lp_status(SNUM(conn))) - claim_connection(conn,"", - MAXSTATUS,False); - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups); /* Initialise VFS function pointers */ @@ -520,9 +516,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(conn))) { - yield_connection(conn,"",MAXSTATUS); - } conn_free(conn); *ecode = ERRbadpw; return NULL; @@ -535,8 +528,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(conn))) - yield_connection(conn,"",MAXSTATUS); conn_free(conn); *ecode = ERRnosuchshare; return NULL; @@ -630,9 +621,6 @@ void close_cnum(connection_struct *conn, uint16 vuid) lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); - if (lp_status(SNUM(conn))) - yield_connection(conn,"",MAXSTATUS); - file_close_conn(conn); dptr_closecnum(conn); -- cgit From 2bd3a436fd6ed218bced476b502d24f317511fb2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Nov 2000 00:30:15 +0000 Subject: Fix for updating of print queues changed from a local box. Essentially, this makes sure that the change messages sent to ourselves are handled synchronously w.r.t. other smb packets incoming. Jeremy. (This used to be commit 78a13074455618308d048d1c69f62e660988eb90) --- source3/smbd/process.c | 13 +++++++++---- source3/smbd/statcache.c | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dc56534edb..ea0309599f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -131,9 +131,6 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len) reload_services(False); reload_after_sighup = False; } - - /* check for any pending internal messages */ - message_dispatch(); } /**************************************************************************** @@ -166,6 +163,15 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) smb_read_error = 0; + again: + + /* + * Note that this call must be before processing any SMB + * messages as we need to synchronously process any messages + * we may have sent to ourselves from the previous SMB. + */ + message_dispatch(); + /* * Check to see if we already have a message on the smb queue. * If so - copy and return it. @@ -187,7 +193,6 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) * Setup the select read fd set. */ - again: FD_ZERO(&fds); FD_SET(smbd_server_fd(),&fds); maxfd = setup_oplock_select_set(&fds); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8200c277b3..4c885f34f1 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -218,7 +218,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, */ BOOL reset_stat_cache( void ) { - static BOOL initialised; + static BOOL initialised = False; if (!lp_stat_cache()) return True; if (!initialised) { -- cgit From 2130ced345a6f3ecffe61c3622aceb8986925baa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Nov 2000 02:38:22 +0000 Subject: Fix for off-by-one StrnCpy. Jeremy. (This used to be commit 63cafb34b39443d03d17ae01b47adc0926b05fe2) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 51472ea309..1e461f10a9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -76,7 +76,7 @@ static int CopyExpanded(connection_struct *conn, StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub_conn(conn,buf); - StrnCpy(*dst,buf,*n); + StrnCpy(*dst,buf,*n-1); l = strlen(*dst) + 1; (*dst) += l; (*n) -= l; -- cgit From 14067f9c9ce1ea4d0301c0c8c7ba71278234d1bb Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 21 Nov 2000 06:05:08 +0000 Subject: combined 2 if statments which used the same condition -- jerry (This used to be commit 445fd1dbd8bb93f56f20b5dd9e9d5b018147b21d) --- source3/smbd/password.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 934b3155f3..a1df5bf7f0 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -326,11 +326,13 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha unsigned char p21[21]; unsigned char p24[24]; - if (part_passwd == NULL) + if (part_passwd == NULL) + { DEBUG(10,("No password set - allowing access\n")); - /* No password set - always true ! */ - if (part_passwd == NULL) + + /* No password set - always true ! */ return 1; + } memset(p21,'\0',21); memcpy(p21,part_passwd,16); -- cgit From 7254a66e00f47578ebcb207368a7e33dede31c22 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Nov 2000 22:37:03 +0000 Subject: Don't forget to convert into UNIX character set before calling winbindd. Jeremy. (This used to be commit 00cd72c385f1e5d075dbacf834b68769b5ac38f3) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dd53eb46e7..5942d63206 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -863,7 +863,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int that */ if (!getpwnam(user)) { pstring user2; - slprintf(user2,sizeof(user2),"%s%s%s", domain, lp_winbind_separator(), user); + slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False), lp_winbind_separator(), user); if (getpwnam(user2)) { DEBUG(3,("Using unix username %s\n", user2)); pstrcpy(user, user2); -- cgit From b935b968ec0bf595940824cff2e0462badadf7a4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Nov 2000 19:42:54 +0000 Subject: Free talloc'ed memory from the main smbd. Patch from Rich Bollinger, Elliott Company Jeremy. (This used to be commit e041b144b2c7c6c9fdd6cd20256a197876aaf353) --- source3/smbd/server.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 823536f2ab..3ad2aa5b0f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -197,6 +197,9 @@ max can be %d\n", fd_set lfds; int num; + /* Free up temporary memory from the main smbd. */ + lp_talloc_free(); + memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); -- cgit From efb7bb3bcff6437593e0c9b9655e018f94fe9639 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 24 Nov 2000 19:53:38 +0000 Subject: This should fix Office failing to print to "FILE:". Jeremy. (This used to be commit a08b08f7782234f26b2656a229007a411c6fb521) --- source3/smbd/nttrans.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f8b6352ba1..c0ccea0add 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -725,9 +725,9 @@ int reply_ntcreate_and_X(connection_struct *conn, get_filename(&fname[0], inbuf, smb_buf(inbuf)-inbuf, smb_buflen(inbuf),fname_len); - if( fname[0] == ':') { + if( strchr(fname, ':')) { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - END_PROFILE(SMBntcreateX); + END_PROFILE(SMBntcreateX); return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } END_PROFILE(SMBntcreateX); @@ -1155,7 +1155,7 @@ static int call_nt_transact_create(connection_struct *conn, get_filename_transact(&fname[0], params, 53, total_parameter_count - 53 - fname_len, fname_len); - if( fname[0] == ':') { + if( strchr(fname, ':')) { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } -- cgit From a1c3f33d94d7c40f3511e8dafde839ef0915d9a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Nov 2000 19:14:10 +0000 Subject: Removed unnessesary init. Jeremy. (This used to be commit 2a797f9aa26b2d0c703b9d67f6e1ec97e4f408d2) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 4c885f34f1..8200c277b3 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -218,7 +218,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, */ BOOL reset_stat_cache( void ) { - static BOOL initialised = False; + static BOOL initialised; if (!lp_stat_cache()) return True; if (!initialised) { -- cgit From 120f3afa899eac9a03643ce3e81264d245e09d3d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Nov 2000 21:37:07 +0000 Subject: Fixed messaging so main smbd can get lib/message.c messages. Jeremy. (This used to be commit 349d58fb5758cebc5a8575f80103150b8cd0a080) --- source3/smbd/server.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3ad2aa5b0f..97a05686c3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -200,6 +200,9 @@ max can be %d\n", /* Free up temporary memory from the main smbd. */ lp_talloc_free(); + /* Ensure we respond to PING and DEBUG messages from the main smbd. */ + message_dispatch(); + memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); @@ -717,6 +720,11 @@ static void usage(char *pname) exit(1); } + /* Setup the main smbd so that we can get messages. */ + if (lp_status(-1)) { + claim_connection(NULL,"",MAXSTATUS,True); + } + if (!open_sockets(is_daemon,port)) exit(1); -- cgit From 0f1c800f8542297b9c1a6a4dff20263e3b6d9d40 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Nov 2000 23:59:42 +0000 Subject: passdb/secrets.c passdb/smbpassfile.c smbd/server.c : Actually *use* the code written to transition from an old DOMAIN.MACHINE.MAC file to secrets.tdb. printing/nt_printing.c: Fix case insensitive name lookups for driver files. John - this should fix the Win9x/WinME problem correctly. Jeremy. (This used to be commit 8f3332a9acf413ac5d12053ca5c52733a4e946cc) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 97a05686c3..07e554c4fb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -725,6 +725,11 @@ static void usage(char *pname) claim_connection(NULL,"",MAXSTATUS,True); } + /* Attempt to migrate from an old 2.0.x machine account file. */ + if (!migrate_from_old_password_file(global_myworkgroup)) { + DEBUG(0,("Failed to migrate from old MAC file.\n")); + } + if (!open_sockets(is_daemon,port)) exit(1); -- cgit From 366bf693d21a5fe3020b8528ae879d9734e67231 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Nov 2000 22:17:44 +0000 Subject: include/dlinklist.h: Added '{' '}' around DLIST_PROMOTE so it can be used as a single statement after an 'if'. Tracking this down took 4 hours from my life and ANDREW I WANT THEM BACK !!!!! :-). include/smb.h smbd/password.c: Fixed the bug veritas reported with realloc of the validated_users array growing without bounds. This is now a linked list as god (Andrew) intended :-). Jeremy. (This used to be commit 346f2f9206b9b4ed123e2a61c0a48de630397b8a) --- source3/smbd/password.c | 141 +++++++++++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 60 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a1df5bf7f0..48e4172ace 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -93,8 +93,9 @@ static BOOL last_challenge(unsigned char *challenge) } /* this holds info on user ids that are already validated for this VC */ -static user_struct *validated_users = NULL; -static int num_validated_users = 0; +static user_struct *validated_users; +static int next_vuid = VUID_OFFSET; +static int num_validated_vuids; /**************************************************************************** check if a uid has been validated, and return an pointer to the user_struct @@ -103,13 +104,21 @@ tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ user_struct *get_valid_user_struct(uint16 vuid) { - if (vuid == UID_FIELD_INVALID) - return NULL; - vuid -= VUID_OFFSET; - if ((vuid >= (uint16)num_validated_users) || - (validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1)) - return NULL; - return &validated_users[vuid]; + user_struct *usp; + int count=0; + + if (vuid == UID_FIELD_INVALID) + return NULL; + + for (usp=validated_users;usp;usp=usp->next,count++) { + if (vuid == usp->vuid) { + if (count > 10) + DLIST_PROMOTE(validated_users, usp); + return usp; + } + } + + return NULL; } /**************************************************************************** @@ -122,18 +131,12 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; - vuser->uid = (uid_t)-1; - vuser->gid = (gid_t)-1; - - /* same number of igroups as groups */ - vuser->n_groups = 0; - - if (vuser->groups) - free((char *)vuser->groups); - - vuser->groups = NULL; + DLIST_REMOVE(validated_users, vuser); + safe_free(vuser->groups); delete_nt_token(&vuser->nt_user_token); + safe_free(vuser); + num_validated_vuids--; } /**************************************************************************** @@ -206,58 +209,76 @@ tell random client vuid's (normally zero) from valid vuids. uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, char *domain,BOOL guest) { - user_struct *vuser; - struct passwd *pwfile; /* for getting real name from passwd file */ + user_struct *vuser = NULL; + user_struct *vsp; + struct passwd *pwfile; /* for getting real name from passwd file */ - /* Ensure no vuid gets registered in share level security. */ - if(lp_security() == SEC_SHARE) - return UID_FIELD_INVALID; + /* Ensure no vuid gets registered in share level security. */ + if(lp_security() == SEC_SHARE) + return UID_FIELD_INVALID; - validated_users = (user_struct *)Realloc(validated_users, - sizeof(user_struct)* - (num_validated_users+1)); - - if (!validated_users) { - DEBUG(0,("Failed to realloc users struct!\n")); - num_validated_users = 0; - return UID_FIELD_INVALID; - } + /* Limit allowed vuids to 16bits - VUID_OFFSET. */ + if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) + return UID_FIELD_INVALID; - vuser = &validated_users[num_validated_users]; - num_validated_users++; + if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) { + DEBUG(0,("Failed to malloc users struct!\n")); + return UID_FIELD_INVALID; + } - vuser->uid = uid; - vuser->gid = gid; - vuser->guest = guest; - fstrcpy(vuser->user.unix_name,unix_name); - fstrcpy(vuser->user.smb_name,requested_name); - fstrcpy(vuser->user.domain,domain); + ZERO_STRUCTP(vuser); - vuser->n_groups = 0; - vuser->groups = NULL; + DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)uid, (unsigned int)gid, + unix_name, requested_name, domain, guest )); - /* Find all the groups this uid is in and store them. - Used by become_user() */ - initialise_groups(unix_name, uid, gid); - get_current_groups( &vuser->n_groups, &vuser->groups); + /* Allocate a free vuid. Yes this is a linear search... :-) */ + while( (vsp = get_valid_user_struct(next_vuid)) != NULL ) { + next_vuid++; + /* Check for vuid wrap. */ + if (next_vuid == UID_FIELD_INVALID) + next_vuid = VUID_OFFSET; + } - /* Create an NT_USER_TOKEN struct for this user. */ - vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups); + DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid )); - DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); + vuser->vuid = next_vuid; + vuser->uid = uid; + vuser->gid = gid; + vuser->guest = guest; + fstrcpy(vuser->user.unix_name,unix_name); + fstrcpy(vuser->user.smb_name,requested_name); + fstrcpy(vuser->user.domain,domain); - DEBUG(3, ("Clearing default real name\n")); - fstrcpy(vuser->user.full_name, ""); - if (lp_unix_realname()) { - if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); - fstrcpy(vuser->user.full_name, pwfile->pw_gecos); - } - } + vuser->n_groups = 0; + vuser->groups = NULL; + + /* Find all the groups this uid is in and store them. + Used by become_user() */ + initialise_groups(unix_name, uid, gid); + get_current_groups( &vuser->n_groups, &vuser->groups); + + /* Create an NT_USER_TOKEN struct for this user. */ + vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups); + + next_vuid++; + num_validated_vuids++; + + DLIST_ADD(validated_users, vuser); + + DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); + + DEBUG(3, ("Clearing default real name\n")); + fstrcpy(vuser->user.full_name, ""); + if (lp_unix_realname()) { + if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); + fstrcpy(vuser->user.full_name, pwfile->pw_gecos); + } + } - memset(&vuser->dc, '\0', sizeof(vuser->dc)); + memset(&vuser->dc, '\0', sizeof(vuser->dc)); - return (uint16)((num_validated_users - 1) + VUID_OFFSET); + return vuser->vuid; } -- cgit From 94558441aabe4442fdbdb9e28ecdfd6178aa3ed2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Nov 2000 01:00:36 +0000 Subject: Work in progress, doesn't compile. Adding the POSIX ACL mapping.... Jeremy. (This used to be commit bcac4ede7608a91643f5fcd034f6b273a45b5c7a) --- source3/smbd/posix_acls.c | 220 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 198 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 54b45529d0..73f7326e6a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -23,6 +23,13 @@ #include "includes.h" +typedef struct canon_ace { + struct canon_ace *next, *prev; + acl_tag_t type; + acl_perm_t perms; + DOM_SID sid; +} canon_ace; + /**************************************************************************** Function to create owner and group SIDs from a SMB_STRUCT_STAT. ****************************************************************************/ @@ -322,30 +329,168 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p return True; } +/**************************************************************************** + Create a linked list of canonical ACE entries. This is sorted so that DENY + entries are at the front of the list, as NT requires. +****************************************************************************/ + +canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) +{ + extern DOM_SID global_sid_World; + acl_permset_t acl_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); + canon_ace *list_head = NULL; + canon_ace *ace = NULL; + canon_ace *next_ace = NULL; + int entry_id = ACL_FIRST_ENTRY; + + if (posix_acl == NULL) + return default_canonicalise_acl(psbuf); + + while ( acl_get_entry(posix_acl, entry_id, &entry) == 1) { + acl_tag_t tagtype; + acl_permset_t permset; + DOM_SID sid; + + /* get_next... */ + if (entry_id == ACL_FIRST_ENTRY) + entry_id = ACL_NEXT_ENTRY; + + /* Is this a MASK entry ? */ + if (acl_get_tag_type(entry, &tagtype) == -1) + continue; + + if (acl_get_permset(entry, &permset) == -1) + continue; + + /* Decide which SID to use based on the ACL type. */ + switch(tagtype) { + ACL_USER_OBJ: + /* Get the SID from the owner. */ + uid_to_sid( &sid, psbuf->st_uid ); + break; + ACL_USER: + { + uid_t *puid = (uid_t *)acl_get_qualifier(entry); + if (puid == NULL) { + DEBUG(0,("canonicalise_acl: Failed to get uid.\n")); + continue; + } + uid_to_sid( &sid, *puid); + break; + } + ACL_GROUP_OBJ: + /* Get the SID from the owning group. */ + gid_to_sid( &sid, psbuf->st_gid ); + break; + ACL_GROUP: + { + gid_t *pgid = (gid_t *)acl_get_qualifier(entry); + if (pgid == NULL) { + DEBUG(0,("canonicalise_acl: Failed to get gid.\n")); + continue; + } + gid_to_sid( &sid, *pgid); + break; + } + ACL_MASK: + acl_mask = permset; + continue; /* Don't count the mask as an entry. */ + ACL_OTHER_OBJ: + /* Use the Everyone SID */ + sid = global_sid_World; + break; + default: + DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype)); + continue; + } + + /* + * Add this entry to the list. + */ + + if ((ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) + goto fail; + + ZERO_STRUCTP(ace); + ace->type = tagtype; + ace->perms = permset; + ace->sid = sid; + + DLIST_ADD(list_head, ace); + } + + /* + * Now go through the list, masking the permissions with the + * acl_mask. If the permissions are 0 and the type is ACL_USER + * or ACL_GROUP then it's a DENY entry and should be listed + * first. If the permissions are 0 and the type is ACL_USER_OBJ, + * ACL_GROUP_OBJ or ACL_OTHER_OBJ then remove the entry as they + * can never apply. + */ + + for ( ace = list_head; ace; ace = next_ace) { + next_ace = ace_next; + ace->perms &= acl_mask; + + if (ace->perms == 0) { + switch (ace->type) { + ACL_USER_OBJ: + ACL_GROUP_OBJ: + ACL_OTHER_OBJ: + DLIST_REMOVE(list_head, ace); + break; + ACL_USER: + ACL_GROUP: + DLIST_PROMOTE(list_head, ace); + break; + } + } + } + + return list_head; +} + /**************************************************************************** Go through the ACL entries one by one, count them and extract the permset of the mask entry as we scan the acl. ****************************************************************************/ -static size_t get_num_posix_entries(acl_t posix_acl, acl_permset_t *posix_mask) +static size_t get_num_entries(acl_t posix_acl, acl_permset_t *file_mask) { size_t num_entries; acl_entry_t entry; int entry_id = ACL_FIRST_ENTRY; - *posix_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); + *file_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); + + /* + * If the acl is NULL, then return 3 as we will fake this using UNIX + * permissions. + */ - for( num_entries = 0; acl_get_entry(posix_acl, entry_id, &entry) != -1; num_entries++) { + if (posix_acl == NULL) + return 3; + + num_entries = 0; + while ( acl_get_entry(posix_acl, entry_id, &entry) == 1) { acl_tag_t tagtype; acl_permset_t permset; - entry_id = ACL_NEXT_ENTRY; + /* get_next... */ + if (entry_id == ACL_FIRST_ENTRY) + entry_id = ACL_NEXT_ENTRY; + + /* Is this a MASK entry ? */ if (acl_get_tag_type(entry, &tagtype) == -1) continue; - if (tagtype == ACL_MASK) + if (tagtype == ACL_MASK) { if (acl_get_permset(entry, &permset) == 0) - *posix_mask = permset; + *file_mask = permset; + continue; /* Don't count the mask as an entry. */ + } + + num_entries++; } return num_entries; @@ -375,12 +520,17 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) int other_acl_type; size_t num_acls = 0; size_t num_dir_acls = 0; + size _t i; acl_t posix_acl = NULL; acl_t directory_acl = NULL; + acl_permset_t file_mask = 0; + acl_permset_t directory_mask = 0; *ppdesc = NULL; if(fsp->is_directory || fsp->fd == -1) { + + /* Get the stat struct for the owner info. */ if(vfs_stat(fsp,fsp->fsp_name, &sbuf) != 0) { return 0; } @@ -388,25 +538,25 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * Get the ACL from the path. */ - if ((posix_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_ACCESS)) == NULL) - return 0; + posix_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_ACCESS); /* * If it's a directory get the default POSIX ACL. */ - if(fsp->is_directory) { - } + if(fsp->is_directory) + directory_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_DEFAULT); } else { + + /* Get the stat struct for the owner info. */ if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { return 0; } /* * Get the ACL from the fd. */ - if ((posix_acl = acl_get_fd( fsp->fd)) == NULL) - return 0; + posix_acl = acl_get_fd(fsp->fd); } /* @@ -420,18 +570,44 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * the mask. */ - num_posix_entries = get_num_posix_entries(posix_acl, &posix_mask); + num_acls = get_num_entries(posix_acl, &file_mask); + if (fsp->is_directory) + num_dir_acls = get_num_entries(directory_acl, &directory_mask); - /* - * Create the generic 3 element UNIX acl. - */ + /* Allocate the ace list. */ + if ((ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + goto fail: + } + + memset(ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + + for (i = 0; i < num_acls; i++) { + SEC_ACCESS acc = map_unix_perms(); + } + + for (i = 0; i < num_dir_acls; i++) { + SEC_ACCESS acc = map_unix_perms(); + } + + done: + + if (posix_acl) + acl_free(posix_acl); + if (directory_acl) + acl_free(directory_acl); + + } else { + + /* + * Fall back to the generic 3 element UNIX permissions. + */ - owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); + owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, + S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); + group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, + S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); + other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, + S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); if(owner_access.mask) init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, owner_access, 0); -- cgit From 8c0a28802a9660d55dbab08df29bc7ef655cca0a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Nov 2000 19:31:04 +0000 Subject: Keep syncing up POSIX ACL work... Jeremy. (This used to be commit 8f0062b873b2f4e8b27bb937ad213c4aa29443a7) --- source3/smbd/posix_acls.c | 221 +++++++++++++++++++++++----------------------- 1 file changed, 111 insertions(+), 110 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 73f7326e6a..427fc50472 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -41,62 +41,38 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI } /**************************************************************************** - Map unix perms to NT. + Map canon_ace perms to NT. ****************************************************************************/ -static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w_mask, int x_mask, BOOL is_directory) +static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon_ace *ace) { SEC_ACCESS sa; uint32 nt_mask = 0; *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - if((perm & (r_mask|w_mask|x_mask)) == (r_mask|w_mask|x_mask)) { + if((ace->perms & (ACL_READ|ACL_WRITE|ACL_EXECUTE)) == (ACL_READ|ACL_WRITE|ACL_EXECUTE)) { nt_mask = UNIX_ACCESS_RWX; - } else if((perm & (r_mask|w_mask|x_mask)) == 0) { - nt_mask = UNIX_ACCESS_NONE; + } else if((ace->perms & (ACL_READ|ACL_WRITE|ACL_EXECUTE)) == 0) { + /* + * Here we differentiate between the owner and any other user. + */ + if (sid_equal(powner_sid, &ace->sid) + nt_mask = UNIX_ACCESS_NONE; + } else { + /* Not owner, this is an access denied ACE. */ + nt_mask = UNIX_ACCESS_RWX; + *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED; + } } else { - nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; - if(is_directory) - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - else - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; + nt_mask |= (perm & ACL_READ) ? UNIX_ACCESS_R : 0; + nt_mask |= (perm & ACL_WRITE) ? UNIX_ACCESS_W : 0; + nt_mask |= (perm & ACL_EXECUTE) ? UNIX_ACCESS_X : 0; } init_sec_access(&sa,nt_mask); return sa; } -/**************************************************************************** - Validate a SID. -****************************************************************************/ - -static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) -{ - extern DOM_SID global_sam_sid; - DOM_SID sid; - - if(!sd_sid) { - DEBUG(5,("validate_unix_sid: sid missing.\n")); - return False; - } - - sid_copy(psid, sd_sid); - sid_copy(&sid, sd_sid); - - if(!sid_split_rid(&sid, prid)) { - DEBUG(5,("validate_unix_sid: cannot get RID from sid.\n")); - return False; - } - - if(!sid_equal( &sid, &global_sam_sid)) { - DEBUG(5,("validate_unix_sid: sid is not ours.\n")); - return False; - } - - return True; -} - /**************************************************************************** Map NT perms to UNIX. ****************************************************************************/ @@ -329,12 +305,40 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p return True; } +/**************************************************************************** + Count a linked list of canonical ACE entries. +****************************************************************************/ + +static size_t count_canon_ace_list( canon_ace *list_head ) +{ + size_t count = 0; + canon_ace *ace; + + for (ace = list_head; ace; ace = ace->next) + count++; + + return count; +} + +/**************************************************************************** + Free a linked list of canonical ACE entries. +****************************************************************************/ + +static void free_canon_ace_list( canon_ace *list_head ) +{ + while (list_head) { + canon_ace *old_head = list_head; + DLIST_REMOVE(list_head, list_head); + free(old_head); + } +} + /**************************************************************************** Create a linked list of canonical ACE entries. This is sorted so that DENY entries are at the front of the list, as NT requires. ****************************************************************************/ -canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) +static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) { extern DOM_SID global_sid_World; acl_permset_t acl_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); @@ -342,6 +346,7 @@ canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) canon_ace *ace = NULL; canon_ace *next_ace = NULL; int entry_id = ACL_FIRST_ENTRY; + acl_entry_t entry; if (posix_acl == NULL) return default_canonicalise_acl(psbuf); @@ -450,52 +455,6 @@ canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) return list_head; } -/**************************************************************************** - Go through the ACL entries one by one, count them and extract the permset - of the mask entry as we scan the acl. -****************************************************************************/ - -static size_t get_num_entries(acl_t posix_acl, acl_permset_t *file_mask) -{ - size_t num_entries; - acl_entry_t entry; - int entry_id = ACL_FIRST_ENTRY; - - *file_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); - - /* - * If the acl is NULL, then return 3 as we will fake this using UNIX - * permissions. - */ - - if (posix_acl == NULL) - return 3; - - num_entries = 0; - while ( acl_get_entry(posix_acl, entry_id, &entry) == 1) { - acl_tag_t tagtype; - acl_permset_t permset; - - /* get_next... */ - if (entry_id == ACL_FIRST_ENTRY) - entry_id = ACL_NEXT_ENTRY; - - /* Is this a MASK entry ? */ - if (acl_get_tag_type(entry, &tagtype) == -1) - continue; - - if (tagtype == ACL_MASK) { - if (acl_get_permset(entry, &permset) == 0) - *file_mask = permset; - continue; /* Don't count the mask as an entry. */ - } - - num_entries++; - } - - return num_entries; -} - /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns the size needed to return the @@ -507,10 +466,10 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { extern DOM_SID global_sid_World; SMB_STRUCT_STAT sbuf; - SEC_ACE *ace_list; + SEC_ACE *nt_ace_list; DOM_SID owner_sid; DOM_SID group_sid; - size_t sd_size; + size_t sd_size = 0; SEC_ACL *psa = NULL; SEC_ACCESS owner_access; int owner_acl_type; @@ -520,12 +479,12 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) int other_acl_type; size_t num_acls = 0; size_t num_dir_acls = 0; - size _t i; + size_t num_aces = 0; acl_t posix_acl = NULL; - acl_t directory_acl = NULL; - acl_permset_t file_mask = 0; - acl_permset_t directory_mask = 0; - + acl_t dir_acl = NULL; + canon_ace *file_ace = NULL; + canon_ace *dir_ace = NULL; + *ppdesc = NULL; if(fsp->is_directory || fsp->fd == -1) { @@ -545,7 +504,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) */ if(fsp->is_directory) - directory_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_DEFAULT); + dir_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_DEFAULT); } else { @@ -565,28 +524,59 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); - /* - * Count the number of entries in the ACL and return - * the mask. - */ + /* Create the canon_ace lists. */ + file_ace = canonicalise_acl( posix_acl, &sbuf); + num_acls = count_canon_ace_list(file_ace); - num_acls = get_num_entries(posix_acl, &file_mask); - if (fsp->is_directory) - num_dir_acls = get_num_entries(directory_acl, &directory_mask); + if (fsp->is_directory) { + dir_ace = canonicalise_acl( dir_acl, &sbuf); + num_dir_acls = count_canon_ace_list(dir_ace); + } /* Allocate the ace list. */ - if ((ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { - goto fail: + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); + goto done: } - memset(ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + + /* + * Create the NT ACE list from the canonical ace lists. + */ + + { + canon_ace *ace; + int nt_acl_type; - for (i = 0; i < num_acls; i++) { - SEC_ACCESS acc = map_unix_perms(); + ace = file_ace; + + for (i = 0; i < num_acls; i++, ace = ace->next) { + SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + init_sec_ace(&nt_ace_list[num_aces++], &ace->sid, nt_acl_type, acc, 0); + } + + ace = dir_ace; + + for (i = 0; i < num_dir_acls; i++, ace = ace->next) { + SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + init_sec_ace(&nt_ace_list[num_aces++], &ace->sid, nt_acl_type, acc, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + } } - for (i = 0; i < num_dir_acls; i++) { - SEC_ACCESS acc = map_unix_perms(); + if (num_acls) { + if((psa = make_sec_acl( ACL_REVISION, num_aces, ace_list)) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); + goto done; + } + } + + *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sd_size); + + if(!*ppdesc) { + DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); + sd_size = 0; } done: @@ -595,6 +585,17 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) acl_free(posix_acl); if (directory_acl) acl_free(directory_acl); + if (file_ace) + free_canon_ace_list(file_ace); + if (dir_ace) + free_canon_ace_list(dir_ace); + if (nt_ace_list) + free(nt_ace_list); + if (psa) + free_sec_acl(&psa); + + return sd_size; +} } else { -- cgit From 36390f729360bec7ad3ef6413b2245b0c2e420ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Dec 2000 00:32:25 +0000 Subject: Code to read & return POSIX ACLs as NT ACLs. Close to test on Linux. Jeremy. (This used to be commit 52e9311bc2a837d1f4791f36c3477c430f841378) --- source3/smbd/posix_acls.c | 169 ++++++++++++++++++++++++++-------------------- 1 file changed, 95 insertions(+), 74 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 427fc50472..705078e587 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -305,6 +305,21 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p return True; } +/**************************************************************************** + Map generic UNIX permissions to POSIX ACL perms. +****************************************************************************/ + +static acl_perm_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) +{ + acl_perm_t ret = 0; + + ret |= (mode & r_mask) ? ACL_READ : 0; + ret |= (mode & w_mask) ? ACL_WRITE : 0; + ret |= (mode & x_mask) ? ACL_EXECUTE : 0; + + return ret; +} + /**************************************************************************** Count a linked list of canonical ACE entries. ****************************************************************************/ @@ -333,6 +348,76 @@ static void free_canon_ace_list( canon_ace *list_head ) } } +/****************************************************************************** + Fall back to the generic 3 element UNIX permissions. +********************************************************************************/ + +static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbuf, + DOM_SID *powner, DOM_SID *pgroup) +{ + extern DOM_SID global_sid_World; + canon_ace *list_head = NULL; + canon_ace *owner_ace = NULL; + canon_ace *group_ace = NULL; + canon_ace *other_ace = NULL; + + /* + * Create 3 linked list entries. + */ + + if ((owner_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) + goto fail; + + if ((gtoup_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) + goto fail; + + if ((other_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) + goto fail; + + ZERO_STRUCTP(owner_ace); + ZERO_STRUCTP(group_ace); + ZERO_STRUCTP(other_ace); + + acl_tag_t type; + acl_perm_t perms; + DOM_SID sid; + + owner_ace->type = ACL_USER_OBJ; + owner_ace->sid = *powner; + + group_ace->type = ACL_GROUP_OBJ; + group_ace->sid = *pgroup; + + other_ace->type = ACL_OTHER_OBJ; + other_ace->sid = global_sid_World; + + if (!fsp->is_directory) { + owner_ace->perms = unix_perms_to_acl_perms(sbuf.st_mode, S_IRUSR, S_IWUSR, S_IXUSR); + group_ace->perms = unix_perms_to_acl_perms(sbuf.st_mode, S_IRGRP, S_IWGRP, S_IXGRP); + other_ace->perms = unix_perms_to_acl_perms(sbuf.st_mode, S_IROTH, S_IWOTH, S_IXOTH); + } else { + mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); + + owner_ace->perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR); + group_ace->perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); + other_ace->perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH); + } + + DLIST_ADD(list_head, other_ace); + DLIST_ADD(list_head, group_ace); + DLIST_ADD(list_head, owner_ace); + + return list_head; + + fail: + + safe_free(owner_ace); + safe_free(group_ace); + safe_free(other_ace); + + return NULL; +} + /**************************************************************************** Create a linked list of canonical ACE entries. This is sorted so that DENY entries are at the front of the list, as NT requires. @@ -348,9 +433,6 @@ static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) int entry_id = ACL_FIRST_ENTRY; acl_entry_t entry; - if (posix_acl == NULL) - return default_canonicalise_acl(psbuf); - while ( acl_get_entry(posix_acl, entry_id, &entry) == 1) { acl_tag_t tagtype; acl_permset_t permset; @@ -525,11 +607,19 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); /* Create the canon_ace lists. */ - file_ace = canonicalise_acl( posix_acl, &sbuf); + if (posix_acl) + file_ace = canonicalise_acl( posix_acl, &sbuf); + else + file_ace = unix_canonicalise_acl(fsp, &sbuf, &owner_sid, &group_sid); + num_acls = count_canon_ace_list(file_ace); if (fsp->is_directory) { - dir_ace = canonicalise_acl( dir_acl, &sbuf); + if (dir_ace) + dir_ace = canonicalise_acl( dir_acl, &sbuf); + else + dir_ace = unix_canonicalise_acl(fsp, &sbuf, &owner_sid, &group_sid); + num_dir_acls = count_canon_ace_list(dir_ace); } @@ -597,75 +687,6 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) return sd_size; } - } else { - - /* - * Fall back to the generic 3 element UNIX permissions. - */ - - owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, owner_access, 0); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, group_access, 0); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, other_access, 0); - - if(fsp->is_directory) { - /* - * For directory ACLs we also add in the inherited permissions - * ACE entries. These are the permissions a file would get when - * being created in the directory. - */ - mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - - owner_access = map_unix_perms(&owner_acl_type, mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, - owner_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, - group_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, - other_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - } - - if(num_acls) { - if((psa = make_sec_acl( ACL_REVISION, num_acls, ace_list)) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); - return 0; - } - } - - *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sd_size); - - if(!*ppdesc) { - DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); - sd_size = 0; - } - - free_sec_acl(&psa); - - return sd_size; -} - /**************************************************************************** Reply to set a security descriptor on an fsp. security_info_sent is the description of the following NT ACL. -- cgit From 7e9736703cba8a1d6378b1c089fd5dc865a7a303 Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Mon, 4 Dec 2000 17:16:44 +0000 Subject: Remove C++ style comments (This used to be commit 80c192244fdb07e8e9cf4c0376bbea60dde244a0) --- source3/smbd/quotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 1e81443c5e..9bbc027cf7 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -427,7 +427,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U if (r) { - if (save_errno == EDQUOT) // disk quota exceeded + if (save_errno == EDQUOT) /* disk quota exceeded */ { *dfree = 0; *dsize = D.dqb_curblocks; -- cgit From b881a55dfd8252d1114a0aa0cfd8ac09f2fbaf9e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Dec 2000 01:34:16 +0000 Subject: Moving to abstract API interface (sys_get_acl() etc.) to allow system specific ACL calls to be dealt with elsewhere. This file will eventually be able to replace the old UNIX acl interface. Jeremy. (This used to be commit b27cac77628a4b332b529115b0854c71f9eea374) --- source3/smbd/posix_acls.c | 84 +++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 705078e587..d9c044ec18 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -25,8 +25,8 @@ typedef struct canon_ace { struct canon_ace *next, *prev; - acl_tag_t type; - acl_perm_t perms; + SMB_ACL_TAG_T type; + SMB_ACL_PERM_T perms; DOM_SID sid; } canon_ace; @@ -51,9 +51,9 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - if((ace->perms & (ACL_READ|ACL_WRITE|ACL_EXECUTE)) == (ACL_READ|ACL_WRITE|ACL_EXECUTE)) { + if((ace->perms & (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) == (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { nt_mask = UNIX_ACCESS_RWX; - } else if((ace->perms & (ACL_READ|ACL_WRITE|ACL_EXECUTE)) == 0) { + } else if((ace->perms & (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) == 0) { /* * Here we differentiate between the owner and any other user. */ @@ -65,9 +65,9 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED; } } else { - nt_mask |= (perm & ACL_READ) ? UNIX_ACCESS_R : 0; - nt_mask |= (perm & ACL_WRITE) ? UNIX_ACCESS_W : 0; - nt_mask |= (perm & ACL_EXECUTE) ? UNIX_ACCESS_X : 0; + nt_mask |= (perm & SMB_ACL_READ) ? UNIX_ACCESS_R : 0; + nt_mask |= (perm & SMB_ACL_WRITE) ? UNIX_ACCESS_W : 0; + nt_mask |= (perm & SMB_ACL_EXECUTE) ? UNIX_ACCESS_X : 0; } init_sec_access(&sa,nt_mask); return sa; @@ -309,13 +309,13 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p Map generic UNIX permissions to POSIX ACL perms. ****************************************************************************/ -static acl_perm_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) +static SMB_ACL_PERM_T unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) { acl_perm_t ret = 0; - ret |= (mode & r_mask) ? ACL_READ : 0; - ret |= (mode & w_mask) ? ACL_WRITE : 0; - ret |= (mode & x_mask) ? ACL_EXECUTE : 0; + ret |= (mode & r_mask) ? SMB_ACL_READ : 0; + ret |= (mode & w_mask) ? SMB_ACL_WRITE : 0; + ret |= (mode & x_mask) ? SMB_ACL_EXECUTE : 0; return ret; } @@ -382,13 +382,13 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu acl_perm_t perms; DOM_SID sid; - owner_ace->type = ACL_USER_OBJ; + owner_ace->type = SMB_ACL_USER_OBJ; owner_ace->sid = *powner; - group_ace->type = ACL_GROUP_OBJ; + group_ace->type = SMB_ACL_GROUP_OBJ; group_ace->sid = *pgroup; - other_ace->type = ACL_OTHER_OBJ; + other_ace->type = SMB_ACL_OTHER_OBJ; other_ace->sid = global_sid_World; if (!fsp->is_directory) { @@ -426,21 +426,21 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) { extern DOM_SID global_sid_World; - acl_permset_t acl_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); + SMB_ACL_PERMSET_T acl_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); canon_ace *list_head = NULL; canon_ace *ace = NULL; canon_ace *next_ace = NULL; - int entry_id = ACL_FIRST_ENTRY; - acl_entry_t entry; + int entry_id = SMB_ACL_FIRST_ENTRY; + SMB_ACL_ENTRY_T entry; - while ( acl_get_entry(posix_acl, entry_id, &entry) == 1) { - acl_tag_t tagtype; - acl_permset_t permset; + while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; DOM_SID sid; /* get_next... */ - if (entry_id == ACL_FIRST_ENTRY) - entry_id = ACL_NEXT_ENTRY; + if (entry_id == SMB_ACL_FIRST_ENTRY) + entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ if (acl_get_tag_type(entry, &tagtype) == -1) @@ -451,13 +451,13 @@ static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) /* Decide which SID to use based on the ACL type. */ switch(tagtype) { - ACL_USER_OBJ: + SMB_ACL_USER_OBJ: /* Get the SID from the owner. */ uid_to_sid( &sid, psbuf->st_uid ); break; - ACL_USER: + SMB_ACL_USER: { - uid_t *puid = (uid_t *)acl_get_qualifier(entry); + uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry); if (puid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get uid.\n")); continue; @@ -465,13 +465,13 @@ static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) uid_to_sid( &sid, *puid); break; } - ACL_GROUP_OBJ: + SMB_ACL_GROUP_OBJ: /* Get the SID from the owning group. */ gid_to_sid( &sid, psbuf->st_gid ); break; - ACL_GROUP: + SMB_ACL_GROUP: { - gid_t *pgid = (gid_t *)acl_get_qualifier(entry); + gid_t *pgid = (gid_t *)sys_acl_get_qualifier(entry); if (pgid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get gid.\n")); continue; @@ -479,10 +479,10 @@ static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) gid_to_sid( &sid, *pgid); break; } - ACL_MASK: + SMB_ACL_MASK: acl_mask = permset; continue; /* Don't count the mask as an entry. */ - ACL_OTHER_OBJ: + SMB_ACL_OTHER_OBJ: /* Use the Everyone SID */ sid = global_sid_World; break; @@ -521,13 +521,13 @@ static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) if (ace->perms == 0) { switch (ace->type) { - ACL_USER_OBJ: - ACL_GROUP_OBJ: - ACL_OTHER_OBJ: + SMB_ACL_USER_OBJ: + SMB_ACL_GROUP_OBJ: + SMB_ACL_OTHER_OBJ: DLIST_REMOVE(list_head, ace); break; - ACL_USER: - ACL_GROUP: + SMB_ACL_USER: + SMB_ACL_GROUP: DLIST_PROMOTE(list_head, ace); break; } @@ -562,8 +562,8 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) size_t num_acls = 0; size_t num_dir_acls = 0; size_t num_aces = 0; - acl_t posix_acl = NULL; - acl_t dir_acl = NULL; + SMB_ACL_T posix_acl = NULL; + SMB_ACL_T dir_acl = NULL; canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; @@ -579,14 +579,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * Get the ACL from the path. */ - posix_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_ACCESS); + posix_acl = sys_acl_get_file( dos_to_unix(fsp->fsp_name, False), SMB_ACL_TYPE_ACCESS); /* * If it's a directory get the default POSIX ACL. */ if(fsp->is_directory) - dir_acl = acl_get_file( dos_to_unix(fsp->fsp_name, False), ACL_TYPE_DEFAULT); + dir_acl = sys_acl_get_file( dos_to_unix(fsp->fsp_name, False), SMB_ACL_TYPE_DEFAULT); } else { @@ -597,7 +597,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) /* * Get the ACL from the fd. */ - posix_acl = acl_get_fd(fsp->fd); + posix_acl = sys_acl_get_fd(fsp->fd); } /* @@ -672,9 +672,9 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) done: if (posix_acl) - acl_free(posix_acl); + sys_acl_free(posix_acl); if (directory_acl) - acl_free(directory_acl); + sys_acl_free(directory_acl); if (file_ace) free_canon_ace_list(file_ace); if (dir_ace) -- cgit From 1f6fc3988d452c247a6375d05a924228d73cec66 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 6 Dec 2000 01:47:06 +0000 Subject: Fixed compiler warning. (This used to be commit 5e81151e53300a8c58adca09d02d0b075a13c322) --- source3/smbd/vfs-wrap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index ff150b4e40..9007eb3b6d 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -467,10 +467,10 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) if(vfs_ops->lseek(fsp, currpos, SEEK_SET) != currpos) { goto done; } -#endif - done: +#endif + END_PROFILE(syscall_ftruncate); return result; } -- cgit From 0293259eaa6fd49f69bc6f0181c9145158c4e67f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Dec 2000 02:32:48 +0000 Subject: Make smbd/posix_acls.c use abstract interface. include/smb_acls.h lib/sysacls.c: Added as interface definitions. Jeremy. (This used to be commit 8359375bba5b3ae24956f66b066dedf11d3583df) --- source3/smbd/posix_acls.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d9c044ec18..b106975a86 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -26,7 +26,7 @@ typedef struct canon_ace { struct canon_ace *next, *prev; SMB_ACL_TAG_T type; - SMB_ACL_PERM_T perms; + SMB_ACL_PERMSET_T perms; DOM_SID sid; } canon_ace; @@ -309,9 +309,9 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p Map generic UNIX permissions to POSIX ACL perms. ****************************************************************************/ -static SMB_ACL_PERM_T unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) +static SMB_ACL_PERMSET_T unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) { - acl_perm_t ret = 0; + SMB_ACL_PERMSET_T ret = 0; ret |= (mode & r_mask) ? SMB_ACL_READ : 0; ret |= (mode & w_mask) ? SMB_ACL_WRITE : 0; @@ -360,6 +360,9 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu canon_ace *owner_ace = NULL; canon_ace *group_ace = NULL; canon_ace *other_ace = NULL; + SMB_ACL_TAG_T type; + SMB_ACL_PERMSET_T perms; + DOM_SID sid; /* * Create 3 linked list entries. @@ -378,10 +381,6 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu ZERO_STRUCTP(group_ace); ZERO_STRUCTP(other_ace); - acl_tag_t type; - acl_perm_t perms; - DOM_SID sid; - owner_ace->type = SMB_ACL_USER_OBJ; owner_ace->sid = *powner; @@ -423,10 +422,10 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu entries are at the front of the list, as NT requires. ****************************************************************************/ -static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) +static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) { extern DOM_SID global_sid_World; - SMB_ACL_PERMSET_T acl_mask = (ACL_READ|ACL_WRITE|ACL_EXECUTE); + SMB_ACL_PERMSET_T acl_mask = (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE); canon_ace *list_head = NULL; canon_ace *ace = NULL; canon_ace *next_ace = NULL; @@ -443,10 +442,10 @@ static canon_ace *canonicalise_acl( acl_t posix_acl, SMB_STRUCT_STAT *psbuf) entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ - if (acl_get_tag_type(entry, &tagtype) == -1) + if (sys_acl_get_tag_type(entry, &tagtype) == -1) continue; - if (acl_get_permset(entry, &permset) == -1) + if (sys_acl_get_permset(entry, &permset) == -1) continue; /* Decide which SID to use based on the ACL type. */ -- cgit From a1f4e6e9273d5cf98cfed330c02d9a41886edf44 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 6 Dec 2000 03:22:44 +0000 Subject: Print debug if domain_client_validate() cannot fetch the trust account password (say for example if the tdb file format has changed). (-: (This used to be commit 447fbb38a857a7e97cf2a99022576521c71a4512) --- source3/smbd/password.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 48e4172ace..f759f3b781 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1444,7 +1444,8 @@ BOOL domain_client_validate( char *user, char *domain, */ if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, NULL)) { - return False; + DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup())); + return False; } /* -- cgit From 70922b9bbe412dc43397ecfd3feeb01169ed0b96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Dec 2000 23:24:31 +0000 Subject: Cause smbd to use the new posix_acls code, not the old unix_acls code. Currently does exactly the same thing (returns ACLs the same way). This code is written to try and get a POSIX ACL via the abstract sys_XX interface, then fall back to providing a UNIX based ACL if the calls fail. Seems to work. Next step is to add a --with-posix-acls to configure.in and then check on a POSIX ACL system that a complex ACL is returned correctly as an NT ACL. Note that the ACL set (a more complex problem) is not addressed yet. Jeremy. (This used to be commit 4339e20202a876dbadc07980b731f711463b7299) --- source3/smbd/posix_acls.c | 108 ++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b106975a86..4f483c8f53 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1,4 +1,3 @@ -#ifdef HAVE_POSIX_ACLS #define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. @@ -57,17 +56,16 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon /* * Here we differentiate between the owner and any other user. */ - if (sid_equal(powner_sid, &ace->sid) + if (sid_equal(powner_sid, &ace->sid)) { nt_mask = UNIX_ACCESS_NONE; } else { - /* Not owner, this is an access denied ACE. */ - nt_mask = UNIX_ACCESS_RWX; - *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED; + /* Not owner, no access. */ + nt_mask = 0; } } else { - nt_mask |= (perm & SMB_ACL_READ) ? UNIX_ACCESS_R : 0; - nt_mask |= (perm & SMB_ACL_WRITE) ? UNIX_ACCESS_W : 0; - nt_mask |= (perm & SMB_ACL_EXECUTE) ? UNIX_ACCESS_X : 0; + nt_mask |= (ace->perms & SMB_ACL_READ) ? UNIX_ACCESS_R : 0; + nt_mask |= (ace->perms & SMB_ACL_WRITE) ? UNIX_ACCESS_W : 0; + nt_mask |= (ace->perms & SMB_ACL_EXECUTE) ? UNIX_ACCESS_X : 0; } init_sec_access(&sa,nt_mask); return sa; @@ -130,8 +128,6 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p DOM_SID grp_sid; DOM_SID file_owner_sid; DOM_SID file_grp_sid; - uint32 owner_rid; - uint32 grp_rid; SEC_ACL *dacl = psd->dacl; BOOL all_aces_are_inherit_only = (is_directory ? True : False); int i; @@ -360,9 +356,6 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu canon_ace *owner_ace = NULL; canon_ace *group_ace = NULL; canon_ace *other_ace = NULL; - SMB_ACL_TAG_T type; - SMB_ACL_PERMSET_T perms; - DOM_SID sid; /* * Create 3 linked list entries. @@ -371,7 +364,7 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu if ((owner_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) goto fail; - if ((gtoup_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) + if ((group_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) goto fail; if ((other_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) @@ -391,9 +384,9 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu other_ace->sid = global_sid_World; if (!fsp->is_directory) { - owner_ace->perms = unix_perms_to_acl_perms(sbuf.st_mode, S_IRUSR, S_IWUSR, S_IXUSR); - group_ace->perms = unix_perms_to_acl_perms(sbuf.st_mode, S_IRGRP, S_IWGRP, S_IXGRP); - other_ace->perms = unix_perms_to_acl_perms(sbuf.st_mode, S_IROTH, S_IWOTH, S_IXOTH); + owner_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); + group_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); + other_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IROTH, S_IWOTH, S_IXOTH); } else { mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); @@ -450,11 +443,11 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) /* Decide which SID to use based on the ACL type. */ switch(tagtype) { - SMB_ACL_USER_OBJ: + case SMB_ACL_USER_OBJ: /* Get the SID from the owner. */ uid_to_sid( &sid, psbuf->st_uid ); break; - SMB_ACL_USER: + case SMB_ACL_USER: { uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry); if (puid == NULL) { @@ -464,11 +457,11 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) uid_to_sid( &sid, *puid); break; } - SMB_ACL_GROUP_OBJ: + case SMB_ACL_GROUP_OBJ: /* Get the SID from the owning group. */ gid_to_sid( &sid, psbuf->st_gid ); break; - SMB_ACL_GROUP: + case SMB_ACL_GROUP: { gid_t *pgid = (gid_t *)sys_acl_get_qualifier(entry); if (pgid == NULL) { @@ -478,10 +471,10 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) gid_to_sid( &sid, *pgid); break; } - SMB_ACL_MASK: + case SMB_ACL_MASK: acl_mask = permset; continue; /* Don't count the mask as an entry. */ - SMB_ACL_OTHER_OBJ: + case SMB_ACL_OTHER_OBJ: /* Use the Everyone SID */ sid = global_sid_World; break; @@ -515,18 +508,18 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) */ for ( ace = list_head; ace; ace = next_ace) { - next_ace = ace_next; + next_ace = ace->next; ace->perms &= acl_mask; if (ace->perms == 0) { switch (ace->type) { - SMB_ACL_USER_OBJ: - SMB_ACL_GROUP_OBJ: - SMB_ACL_OTHER_OBJ: + case SMB_ACL_USER_OBJ: + case SMB_ACL_GROUP_OBJ: + case SMB_ACL_OTHER_OBJ: DLIST_REMOVE(list_head, ace); break; - SMB_ACL_USER: - SMB_ACL_GROUP: + case SMB_ACL_USER: + case SMB_ACL_GROUP: DLIST_PROMOTE(list_head, ace); break; } @@ -534,6 +527,11 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) } return list_head; + + fail: + + free_canon_ace_list(list_head); + return NULL; } /**************************************************************************** @@ -545,19 +543,12 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { - extern DOM_SID global_sid_World; SMB_STRUCT_STAT sbuf; SEC_ACE *nt_ace_list; DOM_SID owner_sid; DOM_SID group_sid; size_t sd_size = 0; SEC_ACL *psa = NULL; - SEC_ACCESS owner_access; - int owner_acl_type; - SEC_ACCESS group_access; - int grp_acl_type; - SEC_ACCESS other_access; - int other_acl_type; size_t num_acls = 0; size_t num_dir_acls = 0; size_t num_aces = 0; @@ -571,7 +562,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) if(fsp->is_directory || fsp->fd == -1) { /* Get the stat struct for the owner info. */ - if(vfs_stat(fsp,fsp->fsp_name, &sbuf) != 0) { + if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; } /* @@ -590,7 +581,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } else { /* Get the stat struct for the owner info. */ - if(fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) { + if(vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { return 0; } /* @@ -625,7 +616,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) /* Allocate the ace list. */ if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); - goto done: + goto done; } memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); @@ -637,6 +628,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { canon_ace *ace; int nt_acl_type; + int i; ace = file_ace; @@ -655,7 +647,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } if (num_acls) { - if((psa = make_sec_acl( ACL_REVISION, num_aces, ace_list)) == NULL) { + if((psa = make_sec_acl( ACL_REVISION, num_aces, nt_ace_list)) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); goto done; } @@ -672,8 +664,8 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) if (posix_acl) sys_acl_free(posix_acl); - if (directory_acl) - sys_acl_free(directory_acl); + if (dir_acl) + sys_acl_free(dir_acl); if (file_ace) free_canon_ace_list(file_ace); if (dir_ace) @@ -705,19 +697,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Get the current state of the file. */ - if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) + if(fsp->is_directory || fsp->fd == -1) { + if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - - int ret; - - if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); - else - ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); - - if(ret != 0) + if(conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) return False; } @@ -740,7 +724,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - if(dos_chown( fsp->fsp_name, user, grp) == -1) { + if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); return False; @@ -752,7 +736,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { return False; } } else { @@ -760,9 +744,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) int ret; if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); else - ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); + ret = conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf); if(ret != 0) return False; @@ -808,7 +792,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)perms )); - if(conn->vfs_ops.chmod(dos_to_unix(fsp->fsp_name, False), perms) == -1) { + if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), perms) == -1) { DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)perms, strerror(errno) )); return False; @@ -819,6 +803,8 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) return True; } #undef OLD_NTDOMAIN -#else /* HAVE_POSIX_ACLS */ - void dummy_posix_acls(void) {;} /* So some compilers don't complain. */ -#endif /* HAVE_POSIX_ACLS */ + + + + + -- cgit From 423227d7ca87a6a4b9412e9ecbc3d6dd073818b1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Dec 2000 05:38:01 +0000 Subject: Working code to read POSIX ACLs on a Linux system using the bestbits ACL patch from http://acl.bestbits.at/. configure support needs more work (just assumes correct headers at the moment). ACL writing needs adding. Jeremy. (This used to be commit 6ae63e502e6adf3666a34aa87860c74e106fdb84) --- source3/smbd/posix_acls.c | 99 +++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 4f483c8f53..6636279024 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -25,7 +25,7 @@ typedef struct canon_ace { struct canon_ace *next, *prev; SMB_ACL_TAG_T type; - SMB_ACL_PERMSET_T perms; + mode_t perms; DOM_SID sid; } canon_ace; @@ -50,9 +50,9 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - if((ace->perms & (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) == (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - nt_mask = UNIX_ACCESS_RWX; - } else if((ace->perms & (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) == 0) { + if((ace->perms & (S_IRWXU|S_IWUSR|S_IXUSR)) == (S_IRWXU|S_IWUSR|S_IXUSR)) { + nt_mask = UNIX_ACCESS_RWX; + } else if((ace->perms & (S_IRWXU|S_IWUSR|S_IXUSR)) == 0) { /* * Here we differentiate between the owner and any other user. */ @@ -63,10 +63,14 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon nt_mask = 0; } } else { - nt_mask |= (ace->perms & SMB_ACL_READ) ? UNIX_ACCESS_R : 0; - nt_mask |= (ace->perms & SMB_ACL_WRITE) ? UNIX_ACCESS_W : 0; - nt_mask |= (ace->perms & SMB_ACL_EXECUTE) ? UNIX_ACCESS_X : 0; + nt_mask |= ((ace->perms & S_IRWXU) ? UNIX_ACCESS_R : 0 ); + nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); + nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 ); } + + DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n", + (unsigned int)ace->perms, (unsigned int)nt_mask )); + init_sec_access(&sa,nt_mask); return sa; } @@ -305,13 +309,31 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p Map generic UNIX permissions to POSIX ACL perms. ****************************************************************************/ -static SMB_ACL_PERMSET_T unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) +static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset) +{ + mode_t ret = 0; + + ret |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRUSR : 0); + ret |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWUSR : 0); + ret |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); + + return ret; +} + +/**************************************************************************** + Map generic UNIX permissions to POSIX ACL perms. +****************************************************************************/ + +static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) { - SMB_ACL_PERMSET_T ret = 0; + mode_t ret = 0; - ret |= (mode & r_mask) ? SMB_ACL_READ : 0; - ret |= (mode & w_mask) ? SMB_ACL_WRITE : 0; - ret |= (mode & x_mask) ? SMB_ACL_EXECUTE : 0; + if (mode & r_mask) + ret |= S_IRUSR; + if (mode & w_mask) + ret |= S_IWUSR; + if (mode & x_mask) + ret |= S_IXUSR; return ret; } @@ -380,7 +402,7 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu group_ace->type = SMB_ACL_GROUP_OBJ; group_ace->sid = *pgroup; - other_ace->type = SMB_ACL_OTHER_OBJ; + other_ace->type = SMB_ACL_OTHER; other_ace->sid = global_sid_World; if (!fsp->is_directory) { @@ -418,7 +440,7 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) { extern DOM_SID global_sid_World; - SMB_ACL_PERMSET_T acl_mask = (SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE); + mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); canon_ace *list_head = NULL; canon_ace *ace = NULL; canon_ace *next_ace = NULL; @@ -472,16 +494,16 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) break; } case SMB_ACL_MASK: - acl_mask = permset; + acl_mask = convert_permset_to_mode_t(permset); continue; /* Don't count the mask as an entry. */ - case SMB_ACL_OTHER_OBJ: + case SMB_ACL_OTHER: /* Use the Everyone SID */ sid = global_sid_World; break; default: DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype)); continue; - } + } /* * Add this entry to the list. @@ -492,7 +514,7 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) ZERO_STRUCTP(ace); ace->type = tagtype; - ace->perms = permset; + ace->perms = convert_permset_to_mode_t(permset); ace->sid = sid; DLIST_ADD(list_head, ace); @@ -500,30 +522,27 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) /* * Now go through the list, masking the permissions with the - * acl_mask. If the permissions are 0 and the type is ACL_USER - * or ACL_GROUP then it's a DENY entry and should be listed - * first. If the permissions are 0 and the type is ACL_USER_OBJ, - * ACL_GROUP_OBJ or ACL_OTHER_OBJ then remove the entry as they - * can never apply. + * acl_mask. If the permissions are 0 it should be listed + * first. */ for ( ace = list_head; ace; ace = next_ace) { next_ace = ace->next; - ace->perms &= acl_mask; - - if (ace->perms == 0) { - switch (ace->type) { - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER_OBJ: - DLIST_REMOVE(list_head, ace); - break; - case SMB_ACL_USER: - case SMB_ACL_GROUP: - DLIST_PROMOTE(list_head, ace); - break; - } - } + + /* Masks are only applied to entries other than USER_OBJ and OTHER. */ + if (ace->type != SMB_ACL_OTHER && ace->type != SMB_ACL_USER_OBJ) + ace->perms &= acl_mask; + + if (ace->perms == 0) + DLIST_PROMOTE(list_head, ace); + } + + if( DEBUGLVL( 10 ) ) { + char *acl_text = sys_acl_to_text( posix_acl, NULL); + + dbgtext("canonicalize_acl: processed acl %s\n", acl_text == NULL ? "NULL" : acl_text ); + if (acl_text) + sys_acl_free(acl_text); } return list_head; @@ -590,6 +609,10 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) posix_acl = sys_acl_get_fd(fsp->fd); } + DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", + posix_acl ? "present" : "absent", + dir_acl ? "present" : "absent" )); + /* * Get the owner, group and world SIDs. */ -- cgit From cf5b71994d6cdb2f81c390579f4a0e676926c6b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Dec 2000 19:26:04 +0000 Subject: file_lines_load/file_lines_pload can now optionally convert unix_to_dos() on read. Jeremy. (This used to be commit 76b8dd376d13eb4469417be217c966d54d333367) --- source3/smbd/dfree.c | 2 +- source3/smbd/groupname.c | 2 +- source3/smbd/lanman.c | 6 +++--- source3/smbd/password.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index ee5722acd5..c8c4437155 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -91,7 +91,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, slprintf(syscmd, sizeof(syscmd), "%s %s", dfree_command, path); DEBUG (3, ("disk_free: Running command %s\n", syscmd)); - lines = file_lines_pload(syscmd, NULL); + lines = file_lines_pload(syscmd, NULL, True); if (lines) { char *line = lines[0]; if (strlen(line) > 0) diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index d53fa56a44..d44e9a7a39 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -101,7 +101,7 @@ void load_groupname_map(void) * Load the file. */ - lines = file_lines_load(groupname_map_file,NULL); + lines = file_lines_load(groupname_map_file,NULL,False); if (!lines) { DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n", groupname_map_file, strerror(errno))); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 1e461f10a9..c9193db4a8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -544,7 +544,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", snum, lp_printerdriver(snum), lp_driverfile(snum))); - lines = file_lines_load(lp_driverfile(snum),NULL); + lines = file_lines_load(lp_driverfile(snum),NULL, False); if (!lines) { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum), @@ -785,7 +785,7 @@ static int get_printerdrivernumber(int snum) DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", snum, lp_printerdriver(snum), lp_driverfile(snum))); - lines = file_lines_load(lp_driverfile(snum), NULL); + lines = file_lines_load(lp_driverfile(snum), NULL, False); if (!lines) { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); @@ -1089,7 +1089,7 @@ static int get_server_info(uint32 servertype, BOOL local_list_only; int i; - lines = file_lines_load(lock_path(SERVER_LIST), NULL); + lines = file_lines_load(lock_path(SERVER_LIST), NULL, False); if (!lines) { DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); return(0); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f759f3b781..f9657eb9ee 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -854,7 +854,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) int plus_allowed = 1; char *file_host; char *file_user; - char **lines = file_lines_load(equiv_file, NULL); + char **lines = file_lines_load(equiv_file, NULL, False); int i; DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); -- cgit From be7e02f9bcbce31bcc4b69c54fe0630ee83c7cd1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Dec 2000 21:55:10 +0000 Subject: Fixed bug with Win9x/ME where drivername was being returned incorrectly in one printq case. Now goes though common function. Jeremy. (This used to be commit e9f48c9cec960b6190fb7a2485c9476640863071) --- source3/smbd/lanman.c | 82 +++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index c9193db4a8..848a187f1a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -499,6 +499,28 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, } } +/******************************************************************** + Return a driver name given an snum. + Looks in a tdb first. Returns True if from tdb, False otherwise. + ********************************************************************/ + +static BOOL get_driver_name(int snum, pstring drivername) +{ + NT_PRINTER_INFO_LEVEL *info = NULL; + BOOL in_tdb = False; + + get_a_printer (&info, 2, lp_servicename(snum)); + if (info != NULL) { + pstrcpy( drivername, info->info_2->drivername); + in_tdb = True; + free_a_printer(&info, 2); + } else { + pstrcpy( drivername, lp_printerdriver(snum)); + } + + return in_tdb; +} + /******************************************************************** Respond to the DosPrintQInfo command with a level of 52 This is used to get printer driver information for Win9x clients @@ -514,10 +536,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, char *p; char **lines = NULL; pstring gen_line; - NT_PRINTER_INFO_LEVEL *info = NULL; BOOL in_tdb = False; fstring location; - + pstring drivername; + /* * Check in the tdb *first* before checking the legacy * files. This allows an NT upload to take precedence over @@ -528,21 +550,20 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, * 'print driver' parameter --jerry */ - get_a_printer (&info, 2, lp_servicename(snum)); - if ((info != NULL) && - ((ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername)) == True)) + + if ((get_driver_name(snum,drivername)) && + ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True)) { in_tdb = True; p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", - info->info_2->drivername, gen_line)); + DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line)); } else { /* didn't find driver in tdb */ - DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", - snum, lp_printerdriver(snum), lp_driverfile(snum))); + DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", + snum, drivername, lp_driverfile(snum))); lines = file_lines_load(lp_driverfile(snum),NULL, False); if (!lines) @@ -558,8 +579,8 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, { p = lines[i]; if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + (strlen(drivername) == strlen(tok)) && + (!strncmp(tok,drivername,strlen(drivername)))) { ok = True; } @@ -605,14 +626,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, goto err; PACKI(desc,"W",0x0400); /* don't know */ - if (in_tdb) - { - PACKS(desc,"z",info->info_2->drivername); /* long printer name */ - } - else - { - PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */ - } + PACKS(desc,"z",drivername); /* long printer name */ PACKS(desc,"z",driver); /* Driverfile Name */ PACKS(desc,"z",datafile); /* Datafile name */ PACKS(desc,"z",langmon); /* language monitor */ @@ -631,11 +645,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z",helpfile); /* helpfile name */ PACKS(desc,"z",driver); /* driver name */ - if (in_tdb) - DEBUG(3,("lp_printerdriver:%s:\n",info->info_2->drivername)); - else - DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum))); - + DEBUG(3,("printerdriver:%s:\n",drivername)); DEBUG(3,("Driver:%s:\n",driver)); DEBUG(3,("Data File:%s:\n",datafile)); DEBUG(3,("Language Monitor:%s:\n",langmon)); @@ -670,7 +680,6 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, desc->errcode=NERR_notsupported; done: - safe_free(info); file_lines_free(lines); } @@ -719,6 +728,8 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, } if (uLevel == 3 || uLevel == 4) { + pstring drivername; + PACKI(desc,"W",5); /* uPriority */ PACKI(desc,"W",0); /* uStarttime */ PACKI(desc,"W",0); /* uUntiltime */ @@ -735,7 +746,8 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, } PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ + get_driver_name(snum,drivername); + PACKS(desc,"z",drivername); /* pszDriverName */ PackDriverData(desc); /* pDriverData */ } @@ -759,7 +771,7 @@ static int get_printerdrivernumber(int snum) char *p; char **lines = NULL; pstring gen_line; - NT_PRINTER_INFO_LEVEL *info = NULL; + pstring drivername; /* * Check in the tdb *first* before checking the legacy @@ -771,19 +783,18 @@ static int get_printerdrivernumber(int snum) * 'print driver' parameter --jerry */ - get_a_printer (&info, 2, lp_servicename(snum)); - if ((info != NULL) && - (ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername) == True)) + if ((get_driver_name(snum,drivername)) && + (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True)) { p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line)); + DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line)); } else { /* didn't find driver in tdb */ - DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n", - snum, lp_printerdriver(snum), lp_driverfile(snum))); + DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", + snum, drivername, lp_driverfile(snum))); lines = file_lines_load(lp_driverfile(snum), NULL, False); if (!lines) @@ -797,8 +808,8 @@ static int get_printerdrivernumber(int snum) { p = lines[i]; if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(lp_printerdriver(snum)) == strlen(tok)) && - (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) + (strlen(drivername) == strlen(tok)) && + (!strncmp(tok,drivername,strlen(drivername)))) { ok = True; } @@ -826,7 +837,6 @@ static int get_printerdrivernumber(int snum) done: - safe_free(info); file_lines_free(lines); return result; -- cgit From 269acfe1d2e1776ca5afdc4d4ead20db0b88cacd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Dec 2000 00:39:32 +0000 Subject: Fixed *very* subtle statcache bug where invalid stat state could be being used if last component lookup failed, but was found in the directory scan. Jeremy. (This used to be commit 7055fa0bc43f6e2b3f04b8901fccea80d59bf490) --- source3/smbd/filename.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5fe4a4c903..aedd2e820f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -278,7 +278,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - ZERO_STRUCT(st); if (vfs_stat(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be @@ -296,6 +295,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } else { pstring rest; + /* Stat failed - ensure we don't use it. */ + ZERO_STRUCT(st); *rest = 0; /* -- cgit From 0f1ead1c93f1dcbbb3f108e4d879778d6b00d82e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Dec 2000 19:21:09 +0000 Subject: Removed unused auto (IRIX compiler warning). Jeremy. (This used to be commit 63e2ebc4272cd8bc52ea80e1e12996ab273b8ea4) --- source3/smbd/password.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f9657eb9ee..7232bffd11 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -210,7 +210,6 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, char *domain,BOOL guest) { user_struct *vuser = NULL; - user_struct *vsp; struct passwd *pwfile; /* for getting real name from passwd file */ /* Ensure no vuid gets registered in share level security. */ @@ -232,7 +231,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, unix_name, requested_name, domain, guest )); /* Allocate a free vuid. Yes this is a linear search... :-) */ - while( (vsp = get_valid_user_struct(next_vuid)) != NULL ) { + while( get_valid_user_struct(next_vuid) != NULL ) { next_vuid++; /* Check for vuid wrap. */ if (next_vuid == UID_FIELD_INVALID) -- cgit From 316cfee01c0040d1eca1e7ee18057fcc6f084baa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Dec 2000 19:35:58 +0000 Subject: Added OLD_NTDOMAIN to remove warnings about undefined functions. Jeremy. (This used to be commit f4c32a75e6e60eae6078449478d04ff22373d817) --- source3/smbd/sec_ctx.c | 2 ++ source3/smbd/vfs-wrap.c | 2 ++ source3/smbd/vfs.c | 2 ++ 3 files changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f3adcfce8f..eaaae9ace7 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -446,3 +447,4 @@ void init_sec_ctx(void) current_user.vuid = UID_FIELD_INVALID; current_user.nt_user_token = NULL; } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 9007eb3b6d..3ecad48371 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -505,3 +506,4 @@ BOOL vfswrap_set_nt_acl(files_struct *fsp, char *name, uint32 security_info_sent { return set_nt_acl(fsp, security_info_sent, psd); } +#undef OLD_NTDOMAIN diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 3db150ab6f..cbd1fd6825 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1,3 +1,4 @@ +#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -884,3 +885,4 @@ BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks) return(True); #endif } +#undef OLD_NTDOMAIN -- cgit From f3a0da8c0ed3523e7020950b0416180ce7630461 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Dec 2000 19:59:22 +0000 Subject: Fixed compiler warning. Jeremy. (This used to be commit e6a1a1e444631f0d674f33b5b8d1d71435de0511) --- source3/smbd/vfs-wrap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 3ecad48371..a9d8a32430 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -470,10 +470,10 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) } done: -#endif - END_PROFILE(syscall_ftruncate); return result; +#endif + } BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) -- cgit From ccb5cbf175c43455a956d42b2815a4529ab9383f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Dec 2000 21:09:48 +0000 Subject: Fixed very subtle bug returning correct error on an open, when we have a choice of invalid share mode and access denied. We must return the access denied by preference, but also remember to break the oplocks... This is needed for multi-user MS-Access. Jeremy. (This used to be commit 7eb7241442ea0f1e065b009c3cccd5821b89a8b6) --- source3/smbd/open.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 258e463ecf..b23da55542 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -649,6 +649,20 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, &flags, &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { + + /* + * This next line is a subtlety we need for MS-Access. If a file open will + * fail due to share permissions and also for security (access) + * reasons, we need to return the access failed error, not the + * share error. This means we must attempt to open the file anyway + * in order to get the UNIX access error - even if we're going to + * fail the open for share reasons. This is bad, as we're burning + * another fd if there are existing locks but there's nothing else + * we can do. We also ensure we're not going to create or tuncate + * the file as we only want an access decision at this stage. JRA. + */ + open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC|O_CREAT)),mode); + unlock_share_entry(conn, dev, inode); file_free(fsp); return NULL; @@ -676,14 +690,6 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S return NULL; } - /* not that we ignore failure for the following. It is - basically a hack for NFS, and NFS will never set one of - these only read them. Nobody but Samba can ever set a deny - mode and we have already checked our more authoritative - locking database for permission to set this deny mode. If - the kernel refuses the operations then the kernel is wrong */ - kernel_flock(fsp, deny_mode); - /* * Deal with the race condition where two smbd's detect the file doesn't * exist and do the create at the same time. One of them will win and @@ -710,6 +716,14 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S */ } + /* note that we ignore failure for the following. It is + basically a hack for NFS, and NFS will never set one of + these only read them. Nobody but Samba can ever set a deny + mode and we have already checked our more authoritative + locking database for permission to set this deny mode. If + the kernel refuses the operations then the kernel is wrong */ + kernel_flock(fsp, deny_mode); + /* * At this point onwards, we can guarentee that the share entry * is locked, whether we created the file or not, and that the -- cgit From 60337746ea0d0f324ec39a16e3b8bee836b8ef51 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Dec 2000 22:31:25 +0000 Subject: Fix for short names not being returned correctly with non-mangled shares. Jeremy. (This used to be commit bcf0a5c316ee8cf333d9d838b041e44a11cb5f1b) --- source3/smbd/trans2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5b6759aec0..a08127694a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -535,7 +535,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,0); p += 4; if (!was_8_3) { fstrcpy(p+2,fname); - name_map_mangle(p+2,True,True,SNUM(conn)); + if(!name_map_mangle(p+2,True,True,SNUM(conn))) + (p+2)[12] = 0; strupper(p+2); SSVAL(p, 0, strlen(p+2)); } else { -- cgit From 93e98d02818e079c9d714e3b5a7894238ead312a Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 11 Dec 2000 22:51:57 +0000 Subject: subtle bug where files which missed the stat_cache but were added to the cache during the look returned a blank stat struct. Made weird occurrences such as... $ smbclient //pogo/print$ smb:\ > cd w32x86 ERROR: Invalid path smb:\ > cd w32x86 smb:\w32x86\ > (This used to be commit 8938dc183112b039c21a5a0beadb60068a8c5b00) --- source3/smbd/filename.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index aedd2e820f..4962297428 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -387,20 +387,17 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. - */ - - if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, name); - - /* + * If we get to here, the filename should have ben added + * to the stat_cache. Therefore a stat_cache_lookup() is needed here + * to fill in the SMB_STRUCT_STAT. + * * If we ended up resolving the entire path then return a valid * stat struct if we got one. */ - - if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) + if (stat_cache_lookup(conn, name, dirpath, &start, &st) + && (strlen(orig_path) == strlen(name))) { *pst = st; + } /* * The name has been resolved. -- cgit From 71acf4cd1f80b1c8cb78aa0f36cc23d185c7fac3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Dec 2000 00:05:02 +0000 Subject: Extra part of fix that Gerald missed (sorry). Jeremy. (This used to be commit ebf754400f443452948020d68e29f597f1b2d60c) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5942d63206..59a94964fb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1049,7 +1049,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); if (check_name(name,conn)) { - if(VALID_STAT(sbuf)) + if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0) ok = S_ISDIR(sbuf.st_mode); } -- cgit From 4c639caa1f16dae804c4736eb59ffb65ccd15278 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Dec 2000 00:11:34 +0000 Subject: Sorry Gerald, I think the original code was better (plus safer as I'm sure it's working :-). Jeremy. (This used to be commit e18c104ee35d00dcbe2e73e6c9699300a3947364) --- source3/smbd/filename.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 4962297428..aedd2e820f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -387,17 +387,20 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } /* - * If we get to here, the filename should have ben added - * to the stat_cache. Therefore a stat_cache_lookup() is needed here - * to fill in the SMB_STRUCT_STAT. - * + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, name); + + /* * If we ended up resolving the entire path then return a valid * stat struct if we got one. */ - if (stat_cache_lookup(conn, name, dirpath, &start, &st) - && (strlen(orig_path) == strlen(name))) { + + if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) *pst = st; - } /* * The name has been resolved. -- cgit From 276364e2a4cee00f4521845347a0b0a371f6b0e6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Dec 2000 02:36:14 +0000 Subject: Removed the special casing of SIDs in se_access_check. This is now done (correctly) when the NT_USER_TOKEN is *created*. Jeremy. (This used to be commit 27d72ed1cf8ece2bede812341279ba5a7262ace4) --- source3/smbd/password.c | 37 ++++++++++++++++++++++++++++--------- source3/smbd/uid.c | 7 ++++++- 2 files changed, 34 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 7232bffd11..193653a867 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -166,37 +166,56 @@ char *validated_domain(uint16 vuid) Create the SID list for this user. ****************************************************************************/ -NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) +NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest) { + extern DOM_SID global_sid_World; + extern DOM_SID global_sid_Network; + extern DOM_SID global_sid_Builtin_Guests; + extern DOM_SID global_sid_Authenticated_Users; NT_USER_TOKEN *token; DOM_SID *psids; int i, psid_ndx = 0; + size_t num_sids = 0; if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) return NULL; ZERO_STRUCTP(token); - if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) { + /* We always have uid/gid plus World and Network and Authenticated Users or Guest SIDs. */ + num_sids = 5 + ngroups; + + if ((token->user_sids = (DOM_SID *)malloc( num_sids*sizeof(DOM_SID))) == NULL) { free(token); return NULL; } psids = token->user_sids; - token->num_sids = 2; + sid_copy( &psids[psid_ndx++], &global_sid_World); + sid_copy( &psids[psid_ndx++], &global_sid_Network); - uid_to_sid( &psids[0], uid); - gid_to_sid( &psids[1], gid); + /* + * The only difference between guest and "anonymous" (which we + * don't really support) is the addition of Authenticated_Users. + */ + + if (is_guest) + sid_copy( &psids[psid_ndx++], &global_sid_Builtin_Guests); + else + sid_copy( &psids[psid_ndx++], &global_sid_Authenticated_Users); + + uid_to_sid( &psids[psid_ndx++], uid); + gid_to_sid( &psids[psid_ndx++], gid); for (i = 0; i < ngroups; i++) { if (groups[i] != gid) { - gid_to_sid( &psids[psid_ndx+2], groups[i]); - psid_ndx++; - token->num_sids++; + gid_to_sid( &psids[psid_ndx++], groups[i]); } } + token->num_sids = psid_ndx; + return token; } @@ -257,7 +276,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, get_current_groups( &vuser->n_groups, &vuser->groups); /* Create an NT_USER_TOKEN struct for this user. */ - vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups); + vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups, guest); next_vuid++; num_validated_vuids++; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 008765cde1..25cadb51b0 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -148,6 +148,8 @@ BOOL become_user(connection_struct *conn, uint16 vuid) */ if((group_c = *lp_force_group(snum))) { + BOOL is_guest = False; + if(group_c == '+') { /* @@ -173,7 +175,10 @@ BOOL become_user(connection_struct *conn, uint16 vuid) * re-create it. */ - token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups); + if (vuser && vuser->guest) + is_guest = True; + + token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest); must_free_token = True; } -- cgit From 90a7d7d3d7e77ed1f33e2bb9969beef7aa464712 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 12 Dec 2000 05:29:47 +0000 Subject: Compile fix for new arg to create_nt_token() (This used to be commit 806185ca8cc8d28f16745a1db9427f52eb8d22e4) --- source3/smbd/service.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2dbb2c0d17..0713c0e49d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -468,7 +468,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups); + conn->nt_user_token = create_nt_token(conn->uid, conn->gid, + conn->ngroups, conn->groups, + guest); /* Initialise VFS function pointers */ -- cgit From 40890119643b6a44ff381d50db4f446c334ce75e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Dec 2000 19:44:50 +0000 Subject: Fixed processing of dfree script (was truncating). Jeremy. (This used to be commit 1e719a807669876b4d11f4653e9712f25fcba20b) --- source3/smbd/dfree.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index c8c4437155..c523f2cab4 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -94,8 +94,6 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, lines = file_lines_pload(syscmd, NULL, True); if (lines) { char *line = lines[0]; - if (strlen(line) > 0) - line[strlen(line)-1] = '\0'; DEBUG (3, ("Read input from dfree, \"%s\"\n", line)); -- cgit From cade42c05b4d050f0b222594e1d1ccc13097c339 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Dec 2000 20:41:02 +0000 Subject: Fixed bug noticed by JF. se_access_check needs user SID as first in token. Jeremy. (This used to be commit f0d7867801e3f78bfc55fdb36ca965e35457f51b) --- source3/smbd/password.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 193653a867..1924bf3217 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -192,28 +192,41 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, psids = token->user_sids; - sid_copy( &psids[psid_ndx++], &global_sid_World); - sid_copy( &psids[psid_ndx++], &global_sid_Network); - /* - * The only difference between guest and "anonymous" (which we - * don't really support) is the addition of Authenticated_Users. + * Note - user SID *MUST* be first in token ! + * se_access_check depends on this. */ - if (is_guest) - sid_copy( &psids[psid_ndx++], &global_sid_Builtin_Guests); - else - sid_copy( &psids[psid_ndx++], &global_sid_Authenticated_Users); - uid_to_sid( &psids[psid_ndx++], uid); + + /* + * Primary group SID is second in token. Convention. + */ + gid_to_sid( &psids[psid_ndx++], gid); + /* Now add the group SIDs. */ + for (i = 0; i < ngroups; i++) { if (groups[i] != gid) { gid_to_sid( &psids[psid_ndx++], groups[i]); } } + /* + * Finally add the "standard" SIDs. + * The only difference between guest and "anonymous" (which we + * don't really support) is the addition of Authenticated_Users. + */ + + sid_copy( &psids[psid_ndx++], &global_sid_World); + sid_copy( &psids[psid_ndx++], &global_sid_Network); + + if (is_guest) + sid_copy( &psids[psid_ndx++], &global_sid_Builtin_Guests); + else + sid_copy( &psids[psid_ndx++], &global_sid_Authenticated_Users); + token->num_sids = psid_ndx; return token; -- cgit From 369f5fd1d7a6e6298bc3cbe01e3aaed0106f6cf4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Dec 2000 01:02:11 +0000 Subject: Fixed memory leaks in lsa_XX calls. Fixed memory leaks in smbcacls. Merged in fixes from appliance-head and 2.2. Fixed multiple connection.tdb open problem. Jeremy. (This used to be commit 0a40bc83e14c69a09948ec09bb6fc5026c4f4c14) --- source3/smbd/connection.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index cf455c0a8b..d150508cef 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -32,6 +32,15 @@ static void utmp_yield(pid_t pid, const connection_struct *conn); static void utmp_claim(const struct connections_data *crec, const connection_struct *conn); #endif +/**************************************************************************** + Return the connection tdb context (used for message send all). +****************************************************************************/ + +TDB_CONTEXT *conn_tdb_ctx(void) +{ + return tdb; +} + /**************************************************************************** delete a connection record ****************************************************************************/ -- cgit From 8372087800c27115e4d211dcd58f2ef87b4ab5a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 16 Dec 2000 00:34:58 +0000 Subject: Fixed chown/chgrp setting from smbcacls. Jeremy. (This used to be commit 43ca0d991cc6489be16722a7ea89e01a42f2ca2f) --- source3/smbd/posix_acls.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6636279024..4c274ae161 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -170,6 +170,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p */ if (security_info_sent & OWNER_SECURITY_INFORMATION) { + sid_copy(&owner_sid, psd->owner_sid) if (!sid_to_uid( &owner_sid, puser, &sid_type)) DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); } @@ -180,6 +181,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p */ if (security_info_sent & GROUP_SECURITY_INFORMATION) { + sid_copy(&grp, psd->grp_sid) if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); } -- cgit From 667b4113a8aa6c04b72da139e26448602eeee83c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Dec 2000 07:22:10 +0000 Subject: Fix typos in new group sid check. Jeremy. (This used to be commit c48e95297e63c8b6f0c6686e5bcfa52229710dbc) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 4c274ae161..bc27ea9ae2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -170,7 +170,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p */ if (security_info_sent & OWNER_SECURITY_INFORMATION) { - sid_copy(&owner_sid, psd->owner_sid) + sid_copy(&owner_sid, psd->owner_sid); if (!sid_to_uid( &owner_sid, puser, &sid_type)) DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); } @@ -181,7 +181,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p */ if (security_info_sent & GROUP_SECURITY_INFORMATION) { - sid_copy(&grp, psd->grp_sid) + sid_copy(&grp_sid, psd->grp_sid); if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); } -- cgit From ed7ecca3aa12afab6feb5cf176a84a76994c9194 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Dec 2000 18:41:51 +0000 Subject: Split the one sys_acl_free call into sys_acl_free_TYPE calls, to allow easier wrapping of non-POSIX ACL interfaces. Jeremy. (This used to be commit 1a31b4eb082b23d60e3d9040b3c0110eef1f9385) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index bc27ea9ae2..7b8d693a1d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -544,7 +544,7 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) dbgtext("canonicalize_acl: processed acl %s\n", acl_text == NULL ? "NULL" : acl_text ); if (acl_text) - sys_acl_free(acl_text); + sys_acl_free_text(acl_text); } return list_head; @@ -688,9 +688,9 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) done: if (posix_acl) - sys_acl_free(posix_acl); + sys_acl_free_acl(posix_acl); if (dir_acl) - sys_acl_free(dir_acl); + sys_acl_free_acl(dir_acl); if (file_ace) free_canon_ace_list(file_ace); if (dir_ace) -- cgit From 0f95385d2887a50abbfed7ffe5631f13287bd4b4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Dec 2000 20:00:28 +0000 Subject: Split set_nt_acls into owner set (which uses chown) and permission set (which currently uses chmod) in preparation for ACL creation. Jeremy. (This used to be commit 0f39895ab007a7300aed6c011c487593ee8c91f0) --- source3/smbd/posix_acls.c | 203 +++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 94 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7b8d693a1d..670c5ffe49 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -124,12 +124,62 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a owner, group and set of UNIX permissions. ****************************************************************************/ -static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode, +static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +{ + DOM_SID owner_sid; + DOM_SID grp_sid; + enum SID_NAME_USE sid_type; + + *puser = (uid_t)-1; + *pgrp = (gid_t)-1; + + if(security_info_sent == 0) { + DEBUG(0,("unpack_nt_owners: no security info sent !\n")); + return False; + } + + /* + * Validate the owner and group SID's. + */ + + memset(&owner_sid, '\0', sizeof(owner_sid)); + memset(&grp_sid, '\0', sizeof(grp_sid)); + + DEBUG(5,("unpack_nt_owners: validating owner_sids.\n")); + + /* + * Don't immediately fail if the owner sid cannot be validated. + * This may be a group chown only set. + */ + + if (security_info_sent & OWNER_SECURITY_INFORMATION) { + sid_copy(&owner_sid, psd->owner_sid); + if (!sid_to_uid( &owner_sid, puser, &sid_type)) + DEBUG(3,("unpack_nt_owners: unable to validate owner sid.\n")); + } + + /* + * Don't immediately fail if the group sid cannot be validated. + * This may be an owner chown only set. + */ + + if (security_info_sent & GROUP_SECURITY_INFORMATION) { + sid_copy(&grp_sid, psd->grp_sid); + if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) + DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n")); + } + + return True; +} + +/**************************************************************************** + Unpack a SEC_DESC into a owner, group and set of UNIX permissions. +****************************************************************************/ + +static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, mode_t *pmode, uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) { extern DOM_SID global_sid_World; - DOM_SID owner_sid; - DOM_SID grp_sid; DOM_SID file_owner_sid; DOM_SID file_grp_sid; SEC_ACL *dacl = psd->dacl; @@ -138,8 +188,6 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p enum SID_NAME_USE sid_type; *pmode = 0; - *puser = (uid_t)-1; - *pgrp = (gid_t)-1; if(security_info_sent == 0) { DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); @@ -155,37 +203,6 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); - /* - * Validate the owner and group SID's. - */ - - memset(&owner_sid, '\0', sizeof(owner_sid)); - memset(&grp_sid, '\0', sizeof(grp_sid)); - - DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n")); - - /* - * Don't immediately fail if the owner sid cannot be validated. - * This may be a group chown only set. - */ - - if (security_info_sent & OWNER_SECURITY_INFORMATION) { - sid_copy(&owner_sid, psd->owner_sid); - if (!sid_to_uid( &owner_sid, puser, &sid_type)) - DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); - } - - /* - * Don't immediately fail if the group sid cannot be validated. - * This may be an owner chown only set. - */ - - if (security_info_sent & GROUP_SECURITY_INFORMATION) { - sid_copy(&grp_sid, psd->grp_sid); - if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) - DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); - } - /* * If no DACL then this is a chown only security descriptor. */ @@ -711,72 +728,75 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) { - connection_struct *conn = fsp->conn; - uid_t user = (uid_t)-1; - gid_t grp = (gid_t)-1; - mode_t perms = 0; - SMB_STRUCT_STAT sbuf; - BOOL got_dacl = False; + connection_struct *conn = fsp->conn; + uid_t user = (uid_t)-1; + gid_t grp = (gid_t)-1; + mode_t perms = 0; + SMB_STRUCT_STAT sbuf; + BOOL got_dacl = False; - /* - * Get the current state of the file. - */ - - if(fsp->is_directory || fsp->fd == -1) { - if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) - return False; - } else { - if(conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) - return False; - } + /* + * Get the current state of the file. + */ - /* - * Unpack the user/group/world id's and permissions. - */ + if(fsp->is_directory || fsp->fd == -1) { + if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) + return False; + } else { + if(conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) + return False; + } - if (!unpack_nt_permissions( &sbuf, &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) - return False; + /* + * Unpack the user/group/world id's. + */ - if (psd->dacl != NULL) - got_dacl = True; + if (!unpack_nt_owners( &sbuf, &user, &grp, security_info_sent, psd)) + return False; - /* - * Do we need to chown ? - */ + /* + * Do we need to chown ? + */ - if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { + if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { - DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); + DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { - DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); - return False; - } + if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { + DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); + return False; + } - /* - * Recheck the current state of the file, which may have changed. - * (suid/sgid bits, for instance) - */ + /* + * Recheck the current state of the file, which may have changed. + * (suid/sgid bits, for instance) + */ - if(fsp->is_directory) { - if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { - return False; - } - } else { + if(fsp->is_directory) { + if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { + return False; + } + } else { - int ret; + int ret; - if(fsp->fd == -1) - ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); - else - ret = conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf); + if(fsp->fd == -1) + ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); + else + ret = conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf); - if(ret != 0) - return False; - } - } + if(ret != 0) + return False; + } + } + + if (!unpack_nt_permissions( &sbuf, &perms, security_info_sent, psd, fsp->is_directory)) + return False; + + if (psd->dacl != NULL) + got_dacl = True; /* * Only change security if we got a DACL. @@ -828,8 +848,3 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) return True; } #undef OLD_NTDOMAIN - - - - - -- cgit From 7bf9d8ce4bb7e96a4c72f674e21d015b1ef1481e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Dec 2000 23:57:48 +0000 Subject: Fixed bug found by Gerald. If a Samba server joins a domain and is set to search for a DC to authenticate to using the "*" syntax than ensure that for the first hour after the password change is searches for the PDC using the 1B name not the 1C name as domain replication may not have occured. Jeremy. (This used to be commit c25533de9918ed9b0c79fd039e11d1b79f513db0) --- source3/smbd/password.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1924bf3217..c2bcac339e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1344,14 +1344,27 @@ static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, un We have been asked to dynamcially determine the IP addresses of the PDC and BDC's for this DOMAIN, and query them in turn. ************************************************************************/ -static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd) +static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd, time_t last_change_time) { struct in_addr *ip_list = NULL; int count = 0; int i; BOOL connected_ok = False; + time_t time_now = time(NULL); + BOOL use_pdc_only = False; - if (!get_dc_list(lp_workgroup(), &ip_list, &count)) + /* + * If the time the machine password has changed + * was less than an hour ago then we need to contact + * the PDC only, as we cannot be sure domain replication + * has yet taken place. Bug found by Gerald (way to go + * Gerald !). JRA. + */ + + if (time_now - last_change_time < 3600) + use_pdc_only = True; + + if (!get_dc_list(use_pdc_only, lp_workgroup(), &ip_list, &count)) return False; /* @@ -1423,6 +1436,7 @@ BOOL domain_client_validate( char *user, char *domain, struct cli_state cli; uint32 smb_uid_low; BOOL connected_ok = False; + time_t last_change_time; if(user_exists != NULL) *user_exists = True; /* Only set false on a very specific error. */ @@ -1473,7 +1487,7 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password for our primary domain */ - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, NULL)) + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) { DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup())); return False; @@ -1501,7 +1515,7 @@ BOOL domain_client_validate( char *user, char *domain, while (!connected_ok && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { if(strequal(remote_machine, "*")) { - connected_ok = find_connect_pdc(&cli, trust_passwd); + connected_ok = find_connect_pdc(&cli, trust_passwd, last_change_time); } else { connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); } -- cgit From 23807f2b308e80a1e325c8fd2bddeec3e2e15bc5 Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Thu, 4 Jan 2001 19:27:08 +0000 Subject: Changes from APPLIANCE_HEAD: source/Makefile.in - changes to ctags and etags rules that somehow got lost along the way. source/include/proto.h - make proto source/smbd/sec_ctx.c source/smbd/password.c - merge debugs for debugging user groups and NT token stuff. source/lib/util_str.c - capitalise domain name returned from parse_domain_user() source/nsswitch/wb_client.c - fix broken conditional in debug statement. source/include/rpc_secdes.h source/include/rpc_spoolss.h source/printing/nt_printing.c source/lib/util_seaccess.c - fix printer permission bugs related to ACE masks for printers. This adds mapping of generic access rights to object specific rights for NT printers. Still need to work out whether or not to ignore ACEs with certain flags set, though. See comments in util_seaccess.c:check_ace() for details. source/printing/nt_printing.c source/printing/printing.c - use PRINTER_ACCESS_ADMINISTER instead of JOB_ACCESS_ADMINISTER until we sort out printer/printjob permission stuff. (This used to be commit 1dba9c5cd1e6389734c648f6903abcb7c8d5b2f0) --- source3/smbd/password.c | 8 ++++++++ source3/smbd/sec_ctx.c | 14 +++++++++++++- source3/smbd/service.c | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c2bcac339e..69ba042155 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -176,6 +176,7 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, DOM_SID *psids; int i, psid_ndx = 0; size_t num_sids = 0; + fstring sid_str; if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) return NULL; @@ -229,6 +230,13 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, token->num_sids = psid_ndx; + /* Dump list of sids in token */ + + for (i = 0; i < token->num_sids; i++) { + DEBUG(5, ("user token sid %s\n", + sid_to_string(sid_str, &token->user_sids[i]))); + } + return token; } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index eaaae9ace7..f3cc9e04e0 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -305,11 +305,23 @@ BOOL push_sec_ctx(void) void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token) { struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; - + /* Set the security context */ DEBUG(3, ("setting sec ctx (%d, %d) - sec_ctx_stack_ndx = %d\n", uid, gid, sec_ctx_stack_ndx)); + if (ngroups) { + int i; + + DEBUG(3, ("%d user groups: \n", ngroups)); + for (i = 0; i < ngroups; i++) { + DEBUGADD(3, ("%d ", groups[i])); + } + + DEBUG(3, ("\n")); + } + + gain_root(); #ifdef HAVE_SETGROUPS diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0713c0e49d..4670d601d7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -468,7 +468,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, + conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups, guest); -- cgit From e76fe221b8912b2f94c0ac8ecbf59b940f11979c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 8 Jan 2001 21:19:15 +0000 Subject: Patch from Richard Bollinger for dead entries being left in connections tdb. Jeremy. (This used to be commit 48a3afcd4716a456c3072bf41450b361e4379be8) --- source3/smbd/connection.c | 2 +- source3/smbd/server.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index d150508cef..b0b4bbab7b 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -55,7 +55,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) ZERO_STRUCT(key); key.pid = sys_getpid(); - if (conn) key.cnum = conn->cnum; + key.cnum = conn?conn->cnum:-1; fstrcpy(key.name, name); kbuf.dptr = (char *)&key; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 07e554c4fb..c895972b0e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -426,6 +426,11 @@ void exit_server(char *reason) conn_close_all(); + /* delete our entry in the connections database. */ + if (lp_status(-1)) { + yield_connection(NULL,"",MAXSTATUS); + } + respond_to_all_remaining_local_messages(); #ifdef WITH_DFS -- cgit From 615af12cf2171001bc7da716cea25eab57ec3f4c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Jan 2001 20:34:37 +0000 Subject: Fix from "B.V.Dean" to add "dos filemode" parameter to allow a chmod to be done if the user has write access to a file, just like Windows allows. Off by default (compare with "dos filetimes" parameter). Jeremy. (This used to be commit 8abdf0e29fdb02a7929aa4395947b5023a7194a0) --- source3/smbd/dosmode.c | 106 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 377cfbb7cf..89e7c6b766 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -184,50 +184,84 @@ chmod a file - but preserve some bits ********************************************************************/ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *st) { - SMB_STRUCT_STAT st1; - int mask=0; - mode_t tmp; - mode_t unixmode; - - if (!st) { - st = &st1; - if (vfs_stat(conn,fname,st)) return(-1); - } + extern struct current_user current_user; + SMB_STRUCT_STAT st1; + int mask=0; + mode_t tmp; + mode_t unixmode; + int ret = -1; + + if (!st) { + st = &st1; + if (vfs_stat(conn,fname,st)) + return(-1); + } - if (S_ISDIR(st->st_mode)) dosmode |= aDIR; + if (S_ISDIR(st->st_mode)) + dosmode |= aDIR; - if (dos_mode(conn,fname,st) == dosmode) return(0); + if (dos_mode(conn,fname,st) == dosmode) + return(0); - unixmode = unix_mode(conn,dosmode,fname); + unixmode = unix_mode(conn,dosmode,fname); - /* preserve the s bits */ - mask |= (S_ISUID | S_ISGID); + /* preserve the s bits */ + mask |= (S_ISUID | S_ISGID); - /* preserve the t bit */ + /* preserve the t bit */ #ifdef S_ISVTX - mask |= S_ISVTX; + mask |= S_ISVTX; #endif - /* possibly preserve the x bits */ - if (!MAP_ARCHIVE(conn)) mask |= S_IXUSR; - if (!MAP_SYSTEM(conn)) mask |= S_IXGRP; - if (!MAP_HIDDEN(conn)) mask |= S_IXOTH; - - unixmode |= (st->st_mode & mask); - - /* if we previously had any r bits set then leave them alone */ - if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { - unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH); - unixmode |= tmp; - } - - /* if we previously had any w bits set then leave them alone - whilst adding in the new w bits, if the new mode is not rdonly */ - if (!IS_DOS_READONLY(dosmode)) { - unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); - } - - return(vfs_chmod(conn,fname,unixmode)); + /* possibly preserve the x bits */ + if (!MAP_ARCHIVE(conn)) + mask |= S_IXUSR; + if (!MAP_SYSTEM(conn)) + mask |= S_IXGRP; + if (!MAP_HIDDEN(conn)) + mask |= S_IXOTH; + + unixmode |= (st->st_mode & mask); + + /* if we previously had any r bits set then leave them alone */ + if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { + unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH); + unixmode |= tmp; + } + + /* if we previously had any w bits set then leave them alone + whilst adding in the new w bits, if the new mode is not rdonly */ + if (!IS_DOS_READONLY(dosmode)) { + unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); + } + + ret = vfs_chmod(conn,fname,unixmode); + + if((errno != EPERM) && (errno != EACCES)) + return -1; + + if(!lp_dos_filemode(SNUM(conn))) + return -1; + + /* We want DOS semantics, ie allow non owner with write permission to change the + bits on a file. Just like file_utime below. + */ + + /* Check if we have write access. */ + if (CAN_WRITE(conn)) { + if (((st->st_mode & S_IWOTH) || + conn->admin_user || + ((st->st_mode & S_IWUSR) && current_user.uid==st->st_uid) || + ((st->st_mode & S_IWGRP) && + in_group(st->st_gid,current_user.gid, current_user.ngroups,current_user.groups)))) { + /* We are allowed to become root and change the file mode. */ + become_root(); + ret = vfs_chmod(conn,fname,unixmode); + unbecome_root(); + } + } + + return( ret ); } -- cgit From adb91565b5ec81ebb9e0d57b7d91fbd9da410aa3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Jan 2001 18:38:55 +0000 Subject: rpc_server/srv_samr.c: smbd/reply.c: Added fix needed for appliances. When using winbindd - a new user may exist (from winbind) but have no home directory. Extend add user script so it is called with a %H substitution when a user exists but their home directory does not. Thanks to Alex Win at VA Linux for finding this one and testing the fix. libsmb/clidgram.c: Fixed missing return statements. smbd/uid.c: Fixed typo in debug. Jeremy. (This used to be commit 7ba0a2192b89954604dd793c537b4a17c2d1ac07) --- source3/smbd/reply.c | 42 +++++++++++++++++++++++++++++++++++++----- source3/smbd/uid.c | 2 +- 2 files changed, 38 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 59a94964fb..7738f2594f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -498,7 +498,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out Create a UNIX user on demand. ****************************************************************************/ -int smb_create_user(char *unix_user) +int smb_create_user(char *unix_user, char *homedir) { pstring add_script; int ret; @@ -506,6 +506,8 @@ int smb_create_user(char *unix_user) pstrcpy(add_script, lp_adduser_script()); if (! *add_script) return -1; pstring_sub(add_script, "%u", unix_user); + if (homedir) + pstring_sub(add_script, "%H", homedir); ret = smbrun(add_script,NULL,False); DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); return ret; @@ -569,6 +571,8 @@ static BOOL check_server_security(char *orig_user, char *domain, char *unix_user smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen); if(ret) { + struct passwd *pwd; + /* * User validated ok against Domain controller. * If the admin wants us to try and create a UNIX @@ -577,8 +581,21 @@ static BOOL check_server_security(char *orig_user, char *domain, char *unix_user * level security as we never know if it was a failure * due to a bad password, or the user really doesn't exist. */ - if(lp_adduser_script() && !smb_getpwnam(unix_user,True)) { - smb_create_user(unix_user); + if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) { + smb_create_user(unix_user, NULL); + } + + if(lp_adduser_script() && pwd) { + SMB_STRUCT_STAT st; + + /* + * Also call smb_create_user if the users home directory + * doesn't exist. Used with winbindd to allow the script to + * create the home directory for a user mapped with winbindd. + */ + + if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) + smb_create_user(unix_user, pwd->pw_dir); } } @@ -595,6 +612,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user { BOOL ret = False; BOOL user_exists = True; + struct passwd *pwd; if(lp_security() != SEC_DOMAIN) return False; @@ -613,9 +631,23 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user * If the admin wants us to try and create a UNIX * user on the fly, do so. */ - if(user_exists && lp_adduser_script() && !smb_getpwnam(unix_user,True)) { - smb_create_user(unix_user); + if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) { + smb_create_user(unix_user, NULL); } + + if(lp_adduser_script() && pwd) { + SMB_STRUCT_STAT st; + + /* + * Also call smb_create_user if the users home directory + * doesn't exist. Used with winbindd to allow the script to + * create the home directory for a user mapped with winbindd. + */ + + if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) + smb_create_user(unix_user, pwd->pw_dir); + } + } else { /* * User failed to validate ok against Domain controller. diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 25cadb51b0..1d2b8f4e9f 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -488,7 +488,7 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) */ if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { - DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a know group (%u)\n", + DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", (unsigned int)name_type )); return local_sid_to_gid(pgid, psid, sidtype); -- cgit From 3380ffae9c231a34406dd694c9ab03bb0b6d8070 Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Thu, 11 Jan 2001 20:41:19 +0000 Subject: Changes from APPLIANCE_HEAD: testsuite/printing/psec.c - Use lock directory from smb.conf parameter when peeking at the ntdrivers.tdb file. source/rpc_parse/parse_sec.c - fix typo in debug message source/script/installbin.sh - create private directory as part of 'make install'. source/nsswitch/winbindd_cache.c source/nsswitch/winbindd_idmap.c source/passdb/secrets.c source/smbd/connection.c - always convert tdb key to unix code-page when generating. source/printing/nt_printing.c - always convert tdb key to unix code-page when generating. - don't prepend path to a filename that is NULL in add_a_printer_driver_3(). source/rpc_server/srv_spoolss_nt.c - always convert tdb key to unix code-page when generating. - don't prepend server name to a path/filename that is NULL in the fill_printer_driver_info functions. source/printing/printing.c - always convert tdb key to unix code-page when generating. - move access check for print_queue_purge() outside of job delete loop. source/smbd/unix_acls.c - fix for setting ACLs (this got missed earlier) source/lib/messages.c - trivial sync with appliance_head (This used to be commit 376601d17d53ef7bfaafa576bd770e554516e808) --- source3/smbd/connection.c | 2 ++ source3/smbd/unix_acls.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index b0b4bbab7b..8ab4e0c5d3 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -57,6 +57,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) key.pid = sys_getpid(); key.cnum = conn?conn->cnum:-1; fstrcpy(key.name, name); + dos_to_unix(key.name, True); /* Convert key to unix-codepage */ kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); @@ -93,6 +94,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO key.pid = sys_getpid(); key.cnum = conn?conn->cnum:-1; fstrcpy(key.name, name); + dos_to_unix(key.name, True); /* Convert key to unix-codepage */ kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 2e16611b0c..9ab057f77a 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -186,6 +186,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p */ if (security_info_sent & OWNER_SECURITY_INFORMATION) { + sid_copy(&owner_sid, psd->owner_sid); if (!sid_to_uid( &owner_sid, puser, &sid_type)) DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); } @@ -196,6 +197,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p */ if (security_info_sent & GROUP_SECURITY_INFORMATION) { + sid_copy(&grp_sid, psd->grp_sid); if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); } -- cgit From d7c7283463a82ba8fd40d190c6231e398f57d466 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Jan 2001 22:37:59 +0000 Subject: First compiling version of code that sets NT ACLs as POSIX ACLs. Now the debugging starts.... :-). Jeremy. (This used to be commit 2300ac79f5eba84225288a87129b4df5bd471466) --- source3/smbd/posix_acls.c | 590 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 493 insertions(+), 97 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 670c5ffe49..10fbdf7bca 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -22,13 +22,43 @@ #include "includes.h" +enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE}; + +typedef union posix_id { + uid_t uid; + gid_t gid; + int world; +} posix_id; + typedef struct canon_ace { struct canon_ace *next, *prev; SMB_ACL_TAG_T type; - mode_t perms; + mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */ DOM_SID sid; + enum ace_owner owner_type; + posix_id unix_ug; } canon_ace; +static void free_canon_ace_list( canon_ace *list_head ); + +#if 0 +/**************************************************************************** + Function to duplicate a canon_ace struct. +****************************************************************************/ + +static canon_ace *dup_canon_ace( canon_ace *c_ace) +{ + canon_ace *new_ace = (canon_ace *)malloc(sizeof(canon_ace)); + + if (new_ace == NULL) + return NULL; + + *new_ace = *c_ace; + + return new_ace; +} +#endif + /**************************************************************************** Function to create owner and group SIDs from a SMB_STRUCT_STAT. ****************************************************************************/ @@ -40,7 +70,7 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI } /**************************************************************************** - Map canon_ace perms to NT. + Map canon_ace perms to permission bits NT. ****************************************************************************/ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon_ace *ace) @@ -76,7 +106,7 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon } /**************************************************************************** - Map NT perms to UNIX. + Map NT perms to a UNIX mode_t. ****************************************************************************/ #define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) @@ -85,43 +115,43 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) { - mode_t mode = 0; - - switch(type) { - case S_IRUSR: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRUSR|S_IWUSR|S_IXUSR; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; - } - break; - case S_IRGRP: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRGRP|S_IWGRP|S_IXGRP; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; - } - break; - case S_IROTH: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IROTH|S_IWOTH|S_IXOTH; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; - } - break; - } + mode_t mode = 0; + + switch(type) { + case S_IRUSR: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRUSR|S_IWUSR|S_IXUSR; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; + } + break; + case S_IRGRP: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRGRP|S_IWGRP|S_IXGRP; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; + } + break; + case S_IROTH: + if(sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IROTH|S_IWOTH|S_IXOTH; + else { + mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; + mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; + mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; + } + break; + } - return mode; + return mode; } /**************************************************************************** - Unpack a SEC_DESC into a owner, group and set of UNIX permissions. + Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) @@ -173,24 +203,188 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, } /**************************************************************************** - Unpack a SEC_DESC into a owner, group and set of UNIX permissions. + Unpack a SEC_DESC into two canonical ace lists. We don't depend on this + succeeding. ****************************************************************************/ -static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, mode_t *pmode, - uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) +static BOOL unpack_canon_ace(files_struct *fsp, + DOM_SID *pfile_owner_sid, + DOM_SID *pfile_grp_sid, + canon_ace **ppfile_ace, canon_ace **ppdir_ace, + uint32 security_info_sent, SEC_DESC *psd) +{ + extern DOM_SID global_sid_World; + SEC_ACL *dacl = psd->dacl; + BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); + canon_ace *file_ace = NULL; + canon_ace *dir_ace = NULL; + enum SID_NAME_USE sid_type; + int i; + + *ppfile_ace = NULL; + *ppdir_ace = NULL; + + if(security_info_sent == 0) { + DEBUG(0,("unpack_canon_ace: no security info sent !\n")); + return False; + } + + /* + * If no DACL then this is a chown only security descriptor. + */ + + if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) + return True; + + /* + * Now go through the DACL and create the canon_ace lists. + */ + + for(i = 0; i < dacl->num_aces; i++) { + SEC_ACE *psa = &dacl->ace[i]; + canon_ace *current_ace = NULL; + + if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { + DEBUG(3,("unpack_canon_ace: unable to set anything but an ALLOW or DENY ACE.\n")); + return False; + } + + /* + * The security mask may be UNIX_ACCESS_NONE which should map into + * no permissions (we overload the WRITE_OWNER bit for this) or it + * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this + * to be so. Any other bits override the UNIX_ACCESS_NONE bit. + */ + + psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| + GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); + + if(psa->info.mask != UNIX_ACCESS_NONE) + psa->info.mask &= ~UNIX_ACCESS_NONE; + + /* + * Create a cannon_ace entry representing this NT DACL ACE. + */ + + if ((current_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + DEBUG(0,("unpack_canon_ace: malloc fail.\n")); + return False; + } + + ZERO_STRUCTP(current_ace); + + sid_copy(¤t_ace->sid, &psa->sid); + + /* + * Try and work out if the SID is a user or group + * as we need to flag these differently for POSIX. + */ + + if( sid_equal(¤t_ace->sid, &global_sid_World)) { + current_ace->owner_type = WORLD_ACE; + current_ace->unix_ug.world = -1; + } else if (sid_to_uid( ¤t_ace->sid, ¤t_ace->unix_ug.uid, &sid_type)) { + current_ace->owner_type = UID_ACE; + } else if (sid_to_gid( ¤t_ace->sid, ¤t_ace->unix_ug.gid, &sid_type)) { + current_ace->owner_type = GID_ACE; + } else { + fstring str; + + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + free(current_ace); + DEBUG(0,("unpack_canon_ace: unable to map SID %s to uid or gid.\n", + sid_to_string(str, ¤t_ace->sid) )); + return False; + } + + /* + * Map the given NT permissions into a UNIX mode_t containing only + * S_I(R|W|X)USR bits. + */ + + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); + else + current_ace->perms &= ~(map_nt_perms( psa->info, S_IRUSR)); + + /* + * Now note what kind of a POSIX ACL this should map to. + */ + + if(sid_equal(¤t_ace->sid, pfile_owner_sid)) { + /* Note we should apply the default mode/mask here.... FIXME ! JRA */ + current_ace->type = SMB_ACL_USER_OBJ; + } else if( sid_equal(¤t_ace->sid, pfile_grp_sid)) { + /* Note we should apply the default mode/mask here.... FIXME ! JRA */ + current_ace->type = SMB_ACL_GROUP_OBJ; + } else if( sid_equal(¤t_ace->sid, &global_sid_World)) { + /* Note we should apply the default mode/mask here.... FIXME ! JRA */ + current_ace->type = SMB_ACL_OTHER; + } else { + /* + * Could be a SMB_ACL_USER or SMB_ACL_GROUP. Check by + * looking at owner_type. + */ + + current_ace->type = (current_ace->owner_type == UID_ACE) ? SMB_ACL_USER : SMB_ACL_GROUP; + } + + if (fsp->is_directory && (psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { + /* + * We can only add to the default POSIX ACE list if the ACE is + * designed to be inherited by both files and directories. + */ + if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) == + (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) { + DLIST_ADD(dir_ace, current_ace); + } else { + DEBUG(0,("unpack_canon_ace: unable to use a non-generic default ACE.\n")); + free(current_ace); + } + } else { + DLIST_ADD(file_ace, current_ace); + all_aces_are_inherit_only = False; + } + } + + if (fsp->is_directory && all_aces_are_inherit_only) { + /* + * Windows 2000 is doing one of these weird 'inherit acl' + * traverses to conserve NTFS ACL resources. Just pretend + * there was no DACL sent. JRA. + */ + + DEBUG(10,("unpack_posix_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); + free_sec_acl(&psd->dacl); + } + + *ppfile_ace = file_ace; + *ppdir_ace = dir_ace; + return True; +} + +/**************************************************************************** + Unpack a SEC_DESC into a set of standard POSIX permissions. +****************************************************************************/ + +static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, mode_t *pmode, + uint32 security_info_sent, SEC_DESC *psd) { extern DOM_SID global_sid_World; + connection_struct *conn = fsp->conn; DOM_SID file_owner_sid; DOM_SID file_grp_sid; SEC_ACL *dacl = psd->dacl; - BOOL all_aces_are_inherit_only = (is_directory ? True : False); + BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); int i; - enum SID_NAME_USE sid_type; *pmode = 0; if(security_info_sent == 0) { - DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); + DEBUG(0,("unpack_posix_permissions: no security info sent !\n")); return False; } @@ -223,7 +417,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, mode_t *pmode, if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); + DEBUG(3,("unpack_posix_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); return False; } @@ -231,9 +425,9 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, mode_t *pmode, * Ignore or remove bits we don't care about on a directory ACE. */ - if(is_directory) { + if(fsp->is_directory) { if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n")); + DEBUG(3,("unpack_posix_permissions: ignoring inherit only ACE.\n")); continue; } @@ -254,7 +448,7 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, mode_t *pmode, psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); if(psa->flags != 0) { - DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", + DEBUG(1,("unpack_posix_permissions: unable to set ACE flags (%x).\n", (unsigned int)psa->flags)); return False; } @@ -305,27 +499,51 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, mode_t *pmode, *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); } else { - DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n")); + DEBUG(0,("unpack_posix_permissions: unknown SID used in ACL.\n")); return False; } } - if (is_directory && all_aces_are_inherit_only) { + if (fsp->is_directory && all_aces_are_inherit_only) { /* * Windows 2000 is doing one of these weird 'inherit acl' * traverses to conserve NTFS ACL resources. Just pretend * there was no DACL sent. JRA. */ - DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); + DEBUG(10,("unpack_posix_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); free_sec_acl(&psd->dacl); } + /* + * Check to see if we need to change anything. + * Enforce limits on modified bits *only*. Don't enforce masks + * on bits not changed by the user. + */ + + if(fsp->is_directory) { + + *pmode &= (lp_dir_security_mask(SNUM(conn)) | psbuf->st_mode); + *pmode |= (lp_force_dir_security_mode(SNUM(conn)) & ( *pmode ^ psbuf->st_mode )); + + } else { + + *pmode &= (lp_security_mask(SNUM(conn)) | psbuf->st_mode); + *pmode |= (lp_force_security_mode(SNUM(conn)) & ( *pmode ^ psbuf->st_mode )); + + } + + /* + * Preserve special bits. + */ + + *pmode |= (psbuf->st_mode & ~0777); + return True; } /**************************************************************************** - Map generic UNIX permissions to POSIX ACL perms. + Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits). ****************************************************************************/ static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset) @@ -340,7 +558,7 @@ static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset) } /**************************************************************************** - Map generic UNIX permissions to POSIX ACL perms. + Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits). ****************************************************************************/ static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) @@ -357,6 +575,30 @@ static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x return ret; } +/**************************************************************************** + Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to + an SMB_ACL_PERMSET_T. +****************************************************************************/ + +static int map_acl_perms_to_permset(mode_t mode, SMB_ACL_PERMSET_T *p_permset) +{ + if (sys_acl_clear_perms(*p_permset) == -1) + return -1; + if (mode & S_IRUSR) { + if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1) + return -1; + } + if (mode & S_IWUSR) { + if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1) + return -1; + } + if (mode & S_IXUSR) { + if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1) + return -1; + } + return 0; +} + /**************************************************************************** Count a linked list of canonical ACE entries. ****************************************************************************/ @@ -417,12 +659,18 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu owner_ace->type = SMB_ACL_USER_OBJ; owner_ace->sid = *powner; + owner_ace->unix_ug.uid = psbuf->st_uid; + owner_ace->owner_type = UID_ACE; group_ace->type = SMB_ACL_GROUP_OBJ; group_ace->sid = *pgroup; + owner_ace->unix_ug.gid = psbuf->st_gid; + owner_ace->owner_type = GID_ACE; other_ace->type = SMB_ACL_OTHER; other_ace->sid = global_sid_World; + owner_ace->unix_ug.world = -1; + owner_ace->owner_type = WORLD_ACE; if (!fsp->is_directory) { owner_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); @@ -470,6 +718,8 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; DOM_SID sid; + posix_id unix_ug; + enum ace_owner owner_type; /* get_next... */ if (entry_id == SMB_ACL_FIRST_ENTRY) @@ -487,6 +737,8 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) case SMB_ACL_USER_OBJ: /* Get the SID from the owner. */ uid_to_sid( &sid, psbuf->st_uid ); + unix_ug.uid = psbuf->st_uid; + owner_type = UID_ACE; break; case SMB_ACL_USER: { @@ -496,11 +748,15 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) continue; } uid_to_sid( &sid, *puid); + unix_ug.uid = *puid; + owner_type = UID_ACE; break; } case SMB_ACL_GROUP_OBJ: /* Get the SID from the owning group. */ gid_to_sid( &sid, psbuf->st_gid ); + unix_ug.gid = psbuf->st_gid; + owner_type = GID_ACE; break; case SMB_ACL_GROUP: { @@ -510,6 +766,8 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) continue; } gid_to_sid( &sid, *pgid); + unix_ug.gid = *pgid; + owner_type = GID_ACE; break; } case SMB_ACL_MASK: @@ -518,6 +776,8 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) case SMB_ACL_OTHER: /* Use the Everyone SID */ sid = global_sid_World; + unix_ug.world = -1; + owner_type = WORLD_ACE; break; default: DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype)); @@ -535,7 +795,9 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) ace->type = tagtype; ace->perms = convert_permset_to_mode_t(permset); ace->sid = sid; - + ace->unix_ug = unix_ug; + ace->owner_type = owner_type; + DLIST_ADD(list_head, ace); } @@ -572,6 +834,129 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) return NULL; } +/**************************************************************************** + Attempt to apply an ACL to a file or directory. +****************************************************************************/ + +static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace) +{ + BOOL ret = False; + SMB_ACL_T the_acl = sys_acl_init((int)count_canon_ace_list(the_ace)); + canon_ace *p_ace; + int i; + SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS); + + if (the_acl == NULL) { +#if !defined(HAVE_NO_ACLS) + /* + * Only print this error message if we have some kind of ACL + * support that's not working. Otherwise we would always get this. + */ + DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n", + default_ace ? "default" : "file", strerror(errno) )); +#endif + return False; + } + + for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) { + SMB_ACL_ENTRY_T the_entry; + SMB_ACL_PERMSET_T the_permset; + + /* + * Get the entry for this ACE. + */ + + if (sys_acl_create_entry( &the_acl, &the_entry) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n", + i, strerror(errno) )); + goto done; + } + + /* + * Initialise the entry from the canon_ace. + */ + + /* + * First tell the entry what type of ACE this is. + */ + + if (sys_acl_set_tag_type(the_entry, p_ace->type) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n", + i, strerror(errno) )); + goto done; + } + + /* + * Only set the qualifier (user or group id) if the entry is a user + * or group id ACE. + */ + + if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) { + if (sys_acl_set_qualifier(the_entry,(void *)&p_ace->unix_ug.uid) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n", + i, strerror(errno) )); + goto done; + } + } + + /* + * Convert the mode_t perms in the canon_ace to a POSIX permset. + */ + + if (map_acl_perms_to_permset(p_ace->perms, &the_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to create permset on entry %d. (%s)\n", + i, strerror(errno) )); + goto done; + } + + /* + * ..and apply them to the entry. + */ + + if (sys_acl_set_permset(the_entry, the_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n", + i, strerror(errno) )); + goto done; + } + } + + /* + * Check if the ACL is valid. + */ + + if (sys_acl_valid(the_acl) == -1) { + DEBUG(0,("set_canon_ace_list: ACL is invalid for set (%s).\n", strerror(errno) )); + goto done; + } + + /* + * Finally apply it to the file or directory. + */ + + if(fsp->is_directory || fsp->fd == -1) { + if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { + DEBUG(0,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", + fsp->fsp_name, strerror(errno) )); + goto done; + } + } else { + if (sys_acl_set_fd(fsp->fd, the_acl_type, the_acl) == -1) { + DEBUG(0,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", + fsp->fsp_name, strerror(errno) )); + goto done; + } + } + + ret = True; + + done: + + if (the_acl != NULL) + sys_acl_free_acl(the_acl); + + return ret; +} + /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns the size needed to return the @@ -708,10 +1093,8 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) sys_acl_free_acl(posix_acl); if (dir_acl) sys_acl_free_acl(dir_acl); - if (file_ace) - free_canon_ace_list(file_ace); - if (dir_ace) - free_canon_ace_list(dir_ace); + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); if (nt_ace_list) free(nt_ace_list); if (psa) @@ -733,7 +1116,12 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) gid_t grp = (gid_t)-1; mode_t perms = 0; SMB_STRUCT_STAT sbuf; - BOOL got_dacl = False; + DOM_SID file_owner_sid; + DOM_SID file_grp_sid; + canon_ace *file_ace_list = NULL; + canon_ace *dir_ace_list = NULL; + BOOL posix_perms; + BOOL acl_perms; /* * Get the current state of the file. @@ -743,7 +1131,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - if(conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) + if(vfs_fstat(fsp,fsp->fd,&sbuf) != 0) return False; } @@ -785,66 +1173,74 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(fsp->fd == -1) ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); else - ret = conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf); + ret = vfs_fstat(fsp,fsp->fd,&sbuf); if(ret != 0) return False; } } - if (!unpack_nt_permissions( &sbuf, &perms, security_info_sent, psd, fsp->is_directory)) - return False; + create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); - if (psd->dacl != NULL) - got_dacl = True; + posix_perms = unpack_posix_permissions( fsp, &sbuf, &perms, security_info_sent, psd); + acl_perms = unpack_canon_ace( fsp, &file_owner_sid, &file_grp_sid, + &file_ace_list, &dir_ace_list, security_info_sent, psd); - /* - * Only change security if we got a DACL. - */ + if (!posix_perms && !acl_perms) { + /* + * Neither method of setting permissions can work. Fail here. + */ - if((security_info_sent & DACL_SECURITY_INFORMATION) && got_dacl) { + DEBUG(3,("set_nt_acl: cannot set normal POSIX permissions or POSIX ACL permissions\n")); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } - /* - * Check to see if we need to change anything. - * Enforce limits on modified bits *only*. Don't enforce masks - * on bits not changed by the user. - */ + /* + * Only change security if we got a DACL. + */ - if(fsp->is_directory) { + if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) { - perms &= (lp_dir_security_mask(SNUM(conn)) | sbuf.st_mode); - perms |= (lp_force_dir_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + BOOL acl_set_support = False; - } else { + /* + * Try using the POSIX ACL set first. All back to chmod if + * we have no ACL support on this filesystem. + */ - perms &= (lp_security_mask(SNUM(conn)) | sbuf.st_mode); - perms |= (lp_force_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); + if (acl_perms && file_ace_list && set_canon_ace_list(fsp, file_ace_list, False)) + acl_set_support = True; - } + if (acl_perms && acl_set_support && fsp->is_directory && dir_ace_list) + set_canon_ace_list(fsp, dir_ace_list, True); - /* - * Preserve special bits. - */ + /* + * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. + */ - perms |= (sbuf.st_mode & ~0777); + if(!acl_set_support && (sbuf.st_mode != perms)) { - /* - * Do we need to chmod ? - */ + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + file_ace_list = NULL; + dir_ace_list = NULL; - if(sbuf.st_mode != perms) { + DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", + fsp->fsp_name, (unsigned int)perms )); - DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", - fsp->fsp_name, (unsigned int)perms )); + if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), perms) == -1) { + DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)perms, strerror(errno) )); + return False; + } + } + } - if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), perms) == -1) { - DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)perms, strerror(errno) )); - return False; - } - } - } + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); - return True; + return True; } #undef OLD_NTDOMAIN -- cgit From cffc311b8a897641166728f27464ba7d37a2092c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Jan 2001 23:41:33 +0000 Subject: Fixed typo with acl_set_fd() not needing an ACL_TYPE_T parameter. Ensure HAVE_NO_ACLS is set in configure if ACL support not selected. Jeremy (This used to be commit 523c91935621ec2d200a79385046694806f7c837) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 10fbdf7bca..8890d54da0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -933,14 +933,14 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Finally apply it to the file or directory. */ - if(fsp->is_directory || fsp->fd == -1) { + if(default_ace || fsp->is_directory || fsp->fd == -1) { if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); goto done; } } else { - if (sys_acl_set_fd(fsp->fd, the_acl_type, the_acl) == -1) { + if (sys_acl_set_fd(fsp->fd, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); goto done; -- cgit From e870dd298881a1390e9f9559232bf23984f34943 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Jan 2001 19:02:57 +0000 Subject: Updated from 2.2. Jeremy. (This used to be commit 6fb5eb8b1eb7972ffafdb8a2b383c3eadf1a96ef) --- source3/smbd/posix_acls.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 8890d54da0..4791375851 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -841,9 +841,11 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace) { BOOL ret = False; - SMB_ACL_T the_acl = sys_acl_init((int)count_canon_ace_list(the_ace)); + SMB_ACL_T the_acl = sys_acl_init((int)count_canon_ace_list(the_ace) + 1); canon_ace *p_ace; int i; + SMB_ACL_ENTRY_T mask_entry; + SMB_ACL_PERMSET_T mask_permset; SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS); if (the_acl == NULL) { @@ -903,12 +905,18 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Convert the mode_t perms in the canon_ace to a POSIX permset. */ - if (map_acl_perms_to_permset(p_ace->perms, &the_permset) == -1) { - DEBUG(0,("set_canon_ace_list: Failed to create permset on entry %d. (%s)\n", + if (sys_acl_get_permset(the_entry, &the_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; } + if (map_acl_perms_to_permset(p_ace->perms, &the_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n", + p_ace->perms, i, strerror(errno) )); + goto done; + } + /* * ..and apply them to the entry. */ @@ -920,6 +928,35 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau } } + /* + * Add in a mask of rwx. + */ + + if (sys_acl_create_entry( &the_acl, &mask_entry) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); + goto done; + } + + if (sys_acl_set_tag_type(mask_entry, SMB_ACL_MASK) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); + goto done; + } + + if (sys_acl_get_permset(mask_entry, &mask_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); + goto done; + } + + if (map_acl_perms_to_permset(S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) )); + goto done; + } + + if (sys_acl_set_permset(mask_entry, mask_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); + goto done; + } + /* * Check if the ACL is valid. */ -- cgit From 7786e07735af78b8207485e3a9fae4dc09080849 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Jan 2001 22:46:22 +0000 Subject: Fixes for POSIX ACLS. ACL merge code. Jeremy. (This used to be commit 180e4a9cd05bcadb2f7c4c23d653724e867196f0) --- source3/smbd/posix_acls.c | 133 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 108 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 4791375851..0071f8786d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -41,32 +41,55 @@ typedef struct canon_ace { static void free_canon_ace_list( canon_ace *list_head ); -#if 0 /**************************************************************************** - Function to duplicate a canon_ace struct. + Function to create owner and group SIDs from a SMB_STRUCT_STAT. ****************************************************************************/ -static canon_ace *dup_canon_ace( canon_ace *c_ace) +static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) { - canon_ace *new_ace = (canon_ace *)malloc(sizeof(canon_ace)); - - if (new_ace == NULL) - return NULL; - - *new_ace = *c_ace; - - return new_ace; + uid_to_sid( powner_sid, psbuf->st_uid ); + gid_to_sid( pgroup_sid, psbuf->st_gid ); } -#endif /**************************************************************************** - Function to create owner and group SIDs from a SMB_STRUCT_STAT. + Print out a canon ace. ****************************************************************************/ -static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) +static void print_canon_ace(canon_ace *ace, int num) { - uid_to_sid( powner_sid, psbuf->st_uid ); - gid_to_sid( pgroup_sid, psbuf->st_gid ); + fstring str; + + dbgtext( "canon_ace index %d.", num ); + dbgtext( "SID = %s ", sid_to_string( str, &ace->sid)); + if (ace->owner_type == UID_ACE) { + struct passwd *pass = sys_getpwuid(ace->unix_ug.uid); + dbgtext( "uid %u (%s) ", (unsigned int)ace->unix_ug.uid, pass ? pass->pw_name : "UNKNOWN"); + } else if (ace->owner_type == GID_ACE) { + struct group *grp = getgrgid(ace->unix_ug.gid); + dbgtext( "gid %u (%s) ", (unsigned int)ace->unix_ug.gid, grp ? grp->gr_name : "UNKNOWN"); + } else + dbgtext( "other "); + switch (ace->type) { + case SMB_ACL_USER: + dbgtext( "SMB_ACL_USER "); + break; + case SMB_ACL_USER_OBJ: + dbgtext( "SMB_ACL_USER_OBJ "); + break; + case SMB_ACL_GROUP: + dbgtext( "SMB_ACL_GROUP "); + break; + case SMB_ACL_GROUP_OBJ: + dbgtext( "SMB_ACL_GROUP_OBJ "); + break; + case SMB_ACL_OTHER: + dbgtext( "SMB_ACL_OTHER "); + break; + } + dbgtext( "perms "); + dbgtext( "%c", ace->perms & S_IRUSR ? 'r' : '-'); + dbgtext( "%c", ace->perms & S_IWUSR ? 'w' : '-'); + dbgtext( "%c\n", ace->perms & S_IXUSR ? 'x' : '-'); } /**************************************************************************** @@ -80,9 +103,9 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - if((ace->perms & (S_IRWXU|S_IWUSR|S_IXUSR)) == (S_IRWXU|S_IWUSR|S_IXUSR)) { + if((ace->perms & (S_IRUSR|S_IWUSR|S_IXUSR)) == (S_IRUSR|S_IWUSR|S_IXUSR)) { nt_mask = UNIX_ACCESS_RWX; - } else if((ace->perms & (S_IRWXU|S_IWUSR|S_IXUSR)) == 0) { + } else if((ace->perms & (S_IRUSR|S_IWUSR|S_IXUSR)) == 0) { /* * Here we differentiate between the owner and any other user. */ @@ -93,7 +116,7 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon nt_mask = 0; } } else { - nt_mask |= ((ace->perms & S_IRWXU) ? UNIX_ACCESS_R : 0 ); + nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 ); } @@ -202,6 +225,34 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, return True; } +/**************************************************************************** + Merge aces with a common user. +****************************************************************************/ + +static BOOL merge_aces( canon_ace *list_head, canon_ace *p_ace) +{ + canon_ace *curr_ace; + + for (curr_ace = list_head; curr_ace; curr_ace = curr_ace->next) { + if (curr_ace == p_ace) + continue; + + if (curr_ace->type == p_ace->type && sid_equal(&curr_ace->sid, &p_ace->sid)) { + if( DEBUGLVL( 10 )) { + dbgtext("Merging ACE's\n"); + print_canon_ace( p_ace, 0); + print_canon_ace( curr_ace, 0); + } + p_ace->perms |= curr_ace->perms; + DLIST_REMOVE(list_head, curr_ace); + free(curr_ace); + return True; + } + } + + return False; +} + /**************************************************************************** Unpack a SEC_DESC into two canonical ace lists. We don't depend on this succeeding. @@ -218,6 +269,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; + canon_ace *current_ace = NULL; enum SID_NAME_USE sid_type; int i; @@ -242,7 +294,6 @@ static BOOL unpack_canon_ace(files_struct *fsp, for(i = 0; i < dacl->num_aces; i++) { SEC_ACE *psa = &dacl->ace[i]; - canon_ace *current_ace = NULL; if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { DEBUG(3,("unpack_canon_ace: unable to set anything but an ALLOW or DENY ACE.\n")); @@ -308,7 +359,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); else - current_ace->perms &= ~(map_nt_perms( psa->info, S_IRUSR)); + current_ace->perms = 0; /* * Now note what kind of a POSIX ACL this should map to. @@ -357,10 +408,29 @@ static BOOL unpack_canon_ace(files_struct *fsp, * there was no DACL sent. JRA. */ - DEBUG(10,("unpack_posix_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); + DEBUG(10,("unpack_canon_ace: Win2k inherit acl traverse. Ignoring DACL.\n")); free_sec_acl(&psd->dacl); } + /* + * Now go through the canon_ace lists and merge entries + * belonging to identical users. + */ + + again_file: + + for (current_ace = file_ace; current_ace; current_ace = current_ace->next ) { + if (merge_aces( file_ace, current_ace)) + goto again_file; + } + + again_dir: + + for (current_ace = dir_ace; current_ace; current_ace = current_ace->next ) { + if (merge_aces( dir_ace, current_ace)) + goto again_dir; + } + *ppfile_ace = file_ace; *ppdir_ace = dir_ace; return True; @@ -371,7 +441,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, ****************************************************************************/ static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, mode_t *pmode, - uint32 security_info_sent, SEC_DESC *psd) + uint32 security_info_sent, SEC_DESC *psd, BOOL posix_acls) { extern DOM_SID global_sid_World; connection_struct *conn = fsp->conn; @@ -478,6 +548,7 @@ static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, else *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); + } else if( sid_equal(&ace_sid, &file_grp_sid)) { /* * Map the desired permissions into group perms. @@ -499,7 +570,12 @@ static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); } else { - DEBUG(0,("unpack_posix_permissions: unknown SID used in ACL.\n")); + /* + * Only bother printing the level zero error if we didn't get any + * POSIX ACLS. + */ + if (!posix_acls) + DEBUG(0,("unpack_posix_permissions: unknown SID used in ACL.\n")); return False; } } @@ -926,6 +1002,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau i, strerror(errno) )); goto done; } + + if( DEBUGLVL( 10 )) + print_canon_ace( p_ace, i); } /* @@ -1019,6 +1098,8 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) *ppdesc = NULL; + DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name )); + if(fsp->is_directory || fsp->fd == -1) { /* Get the stat struct for the owner info. */ @@ -1160,6 +1241,8 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) BOOL posix_perms; BOOL acl_perms; + DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); + /* * Get the current state of the file. */ @@ -1219,9 +1302,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); - posix_perms = unpack_posix_permissions( fsp, &sbuf, &perms, security_info_sent, psd); acl_perms = unpack_canon_ace( fsp, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); + posix_perms = unpack_posix_permissions( fsp, &sbuf, &perms, security_info_sent, psd, acl_perms); if (!posix_perms && !acl_perms) { /* -- cgit From 792ca5d98938c3c52ff4e598bcb55056565dc202 Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Wed, 17 Jan 2001 18:47:46 +0000 Subject: Changes from APPLIANCE_HEAD: source/rpc_server/srv_spoolss_nt.c - Unrolled construct_notify_jobs_info() loop to only fetch printer info_2 structure once rather than num_print_jobs times. - convert command to unix codepage. - remove lp_remove_service() call as it prevents lp_killservice() from working. - Modified some DEBUG and DEBUGADD statements. source/param/loadparm.c source/param/params.c - change printer, preload, auto services to FLAG_DOS_STRING, reverted earlier changes to szPrintername et al, add comments. source/printing/load.c - fix bug with lp_auto_services() and strtok() source/printing/nt_printing.c source/printing/printing.c - remove redundant test that used SERVICE(snum) source/printing/pcap.c - add unix_to_dos() calls, add notes wrt FIXMEs for xxx_printer_fn() functions. source/web/swat.c - added FIXME comment. source/smbd/service.c - added comment re: dos codepage (This used to be commit 7b774b72c2857af9519012106714a9e2cb099da3) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4670d601d7..1db5dc4a5f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -80,7 +80,7 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir) /**************************************************************************** - find a service entry + find a service entry. service is always in dos codepage ****************************************************************************/ int find_service(char *service) { -- cgit From 8aec70075ae410502b9e70f885409bd709ad5a97 Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Wed, 17 Jan 2001 19:16:05 +0000 Subject: Changes from APPLIANCE_HEAD: source/smbd/lanman.c - Change fill_printq_info() to fix corrupted 9X/ME printer comment (This used to be commit acbed88a195b32d251fd15fc8fdd069726659d64) --- source3/smbd/lanman.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 848a187f1a..a2178f052b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -737,11 +737,12 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z",""); /* pszSepFile */ PACKS(desc,"z","WinPrint"); /* pszPrProc */ PACKS(desc,"z",""); /* pszParms */ - if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */ + PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */ + /* "don't ask" that it's done this way to fix corrupted + Win9X/ME printer comments. */ + if (!status) { PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ } else { - PACKS(desc,"z",status->message); /* pszComment */ PACKI(desc,"W",printq_status(status->status)); /* fsStatus */ } PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ -- cgit From aa7cd802062e60fa09c60cc396cfbf12fa08b935 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Jan 2001 23:41:01 +0000 Subject: Typo in new file_chmod code caused file attribute changes to fail. THIS NEEDS TO BE ADDED TO APPLIANCE-HEAD. Jeremy. (This used to be commit b92ccc0c8e5d066eeb077dfced6e717cd741c7a6) --- source3/smbd/dosmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 89e7c6b766..3a06dfe59a 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -237,7 +237,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * ret = vfs_chmod(conn,fname,unixmode); - if((errno != EPERM) && (errno != EACCES)) + if((ret == -1) && (errno != EPERM) && (errno != EACCES)) return -1; if(!lp_dos_filemode(SNUM(conn))) -- cgit From ebee2c6c6d95de7aa5f17173b846c5ada24b6ccc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Jan 2001 23:47:08 +0000 Subject: Get the logic right thistime :-(. Jeremy. (This used to be commit 83596034cdecc7b03e35c0b4bb149e6bf9cebc70) --- source3/smbd/dosmode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 3a06dfe59a..31c4fbdf31 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -235,9 +235,10 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - ret = vfs_chmod(conn,fname,unixmode); + if ((ret = vfs_chmod(conn,fname,unixmode)) == 0) + return 0; - if((ret == -1) && (errno != EPERM) && (errno != EACCES)) + if((errno != EPERM) && (errno != EACCES)) return -1; if(!lp_dos_filemode(SNUM(conn))) -- cgit From 7599c82cceec73fe33b6daa4a908937aed768f80 Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Mon, 22 Jan 2001 16:59:24 +0000 Subject: Changes from APPLIANCE_HEAD: source/smbd/lanman.c - cleanup and bug fix for win9x print queue purge. source/printing/printing.c - cleanup and bug fix for win9x print queue purge. - print_job_end() changed to cleanup spool file in the event of a failure returned from the print_run_command() (This used to be commit 0235fbef37b400a2bf875163878e497282cd1739) --- source3/smbd/lanman.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a2178f052b..fd59f4603a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1947,6 +1947,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param char *QueueName = skip_string(str2,1); int errcode = NERR_notsupported; int snum; + extern struct current_user current_user; /* check it's a supported varient */ if (!(strcsequal(str1,"z") && strcsequal(str2,""))) @@ -1965,13 +1966,13 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param switch (function) { case 74: /* Pause queue */ - if (print_queue_pause(NULL, snum, &errcode)) errcode = NERR_Success; + if (print_queue_pause(¤t_user, snum, &errcode)) errcode = NERR_Success; break; case 75: /* Resume queue */ - if (print_queue_resume(NULL, snum, &errcode)) errcode = NERR_Success; + if (print_queue_resume(¤t_user, snum, &errcode)) errcode = NERR_Success; break; case 103: /* Purge */ - if (print_queue_purge(NULL, snum, &errcode)) errcode = NERR_Success; + if (print_queue_purge(¤t_user, snum, &errcode)) errcode = NERR_Success; break; } -- cgit From 2f7c1db093504a9798cdfd9c5d08a259cb4abc46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Jan 2001 01:52:30 +0000 Subject: include/vfs.h: smbd/vfs-wrap.c: smbd/vfs.c: Added fchmod_acl and chmod_acl. lib/substitute.c: smbd/lanman.c: smbd/open.c: smbd/process.c: smbd/reply.c: smbd/service.c: Removed sessetup_user variable. Added current_user_info struct which conatins domain info etc. Added '%D' for client domain parameter. Jeremy. (This used to be commit 2844ec3d511680609d6794b8718001a1bda9e89f) --- source3/smbd/lanman.c | 4 +- source3/smbd/open.c | 4 +- source3/smbd/posix_acls.c | 319 +++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/process.c | 6 +- source3/smbd/reply.c | 6 +- source3/smbd/service.c | 32 ++++- source3/smbd/vfs-wrap.c | 38 ++++++ source3/smbd/vfs.c | 12 +- 8 files changed, 389 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fd59f4603a..33da479361 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2187,7 +2187,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); char *p2; - extern pstring sesssetup_user; + extern userdom_struct current_user_info; int level = SVAL(p,0); DEBUG(4,("NetWkstaGetInfo level %d\n",level)); @@ -2216,7 +2216,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); - pstrcpy(p2,sesssetup_user); + pstrcpy(p2,current_user_info.smb_name); p2 = skip_string(p2,1); p += 4; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b23da55542..77962562e3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -25,7 +25,7 @@ extern int DEBUGLEVEL; -extern pstring sesssetup_user; +extern userdom_struct current_user_info; extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; @@ -188,7 +188,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name, + *current_user_info.smb_name ? current_user_info.smb_name : conn->user,fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0071f8786d..2bd0065d58 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -41,6 +41,22 @@ typedef struct canon_ace { static void free_canon_ace_list( canon_ace *list_head ); +/**************************************************************************** + Function to duplicate a canon_ace entry. +****************************************************************************/ + +static canon_ace *dup_canon_ace( canon_ace *src_ace) +{ + canon_ace *dst_ace = (canon_ace *)malloc(sizeof(canon_ace)); + + if (dst_ace == NULL) + return NULL; + + *dst_ace = *src_ace; + dst_ace->prev = dst_ace->next = NULL; + return dst_ace; +} + /**************************************************************************** Function to create owner and group SIDs from a SMB_STRUCT_STAT. ****************************************************************************/ @@ -253,12 +269,121 @@ static BOOL merge_aces( canon_ace *list_head, canon_ace *p_ace) return False; } +/**************************************************************************** + Create a default mode for a directory default ACE. +****************************************************************************/ + +static mode_t get_default_ace_mode(files_struct *fsp, int type) +{ + mode_t force_mode = lp_force_dir_security_mode(SNUM(fsp->conn)); + mode_t mode = 0; + + switch(type) { + case S_IRUSR: + mode |= (force_mode & S_IRUSR) ? S_IRUSR : 0; + mode |= (force_mode & S_IWUSR) ? S_IWUSR : 0; + mode |= (force_mode & S_IXUSR) ? S_IXUSR : 0; + break; + case S_IRGRP: + mode |= (force_mode & S_IRGRP) ? S_IRUSR : 0; + mode |= (force_mode & S_IWGRP) ? S_IWUSR : 0; + mode |= (force_mode & S_IXGRP) ? S_IXUSR : 0; + break; + case S_IROTH: + mode |= (force_mode & S_IROTH) ? S_IRUSR : 0; + mode |= (force_mode & S_IWOTH) ? S_IWUSR : 0; + mode |= (force_mode & S_IXOTH) ? S_IXUSR : 0; + break; + } + + return mode; +} + +/**************************************************************************** + A well formed POSIX file or default ACL has at least 3 entries, a + SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ. +****************************************************************************/ + +static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, + files_struct *fsp, + DOM_SID *pfile_owner_sid, + DOM_SID *pfile_grp_sid, + SMB_STRUCT_STAT *pst, + BOOL default_acl) +{ + extern DOM_SID global_sid_World; + canon_ace *pace; + BOOL got_user = False; + BOOL got_grp = False; + BOOL got_other = False; + + for (pace = *pp_ace; pace; pace = pace->next) { + if (pace->type == SMB_ACL_USER_OBJ) + got_user = True; + else if (pace->type == SMB_ACL_GROUP_OBJ) + got_grp = True; + else if (pace->type == SMB_ACL_OTHER) + got_other = True; + } + + if (!got_user) { + if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); + return False; + } + + ZERO_STRUCTP(pace); + pace->type = SMB_ACL_USER_OBJ; + pace->owner_type = UID_ACE; + pace->unix_ug.uid = pst->st_uid; + pace->sid = *pfile_owner_sid; + pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRUSR): 0; + + DLIST_ADD(*pp_ace, pace); + } + + if (!got_grp) { + if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); + return False; + } + + ZERO_STRUCTP(pace); + pace->type = SMB_ACL_GROUP_OBJ; + pace->owner_type = GID_ACE; + pace->unix_ug.uid = pst->st_gid; + pace->sid = *pfile_grp_sid; + pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRGRP): 0; + + DLIST_ADD(*pp_ace, pace); + } + + if (!got_other) { + if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); + return False; + } + + ZERO_STRUCTP(pace); + pace->type = SMB_ACL_OTHER; + pace->owner_type = WORLD_ACE; + pace->unix_ug.world = -1; + pace->sid = global_sid_World; + pace->perms = default_acl ? get_default_ace_mode(fsp, S_IROTH): 0; + + DLIST_ADD(*pp_ace, pace); + } + + return True; +} + /**************************************************************************** Unpack a SEC_DESC into two canonical ace lists. We don't depend on this succeeding. ****************************************************************************/ static BOOL unpack_canon_ace(files_struct *fsp, + SMB_STRUCT_STAT *pst, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, canon_ace **ppfile_ace, canon_ace **ppdir_ace, @@ -383,7 +508,8 @@ static BOOL unpack_canon_ace(files_struct *fsp, current_ace->type = (current_ace->owner_type == UID_ACE) ? SMB_ACL_USER : SMB_ACL_GROUP; } - if (fsp->is_directory && (psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { + if (fsp->is_directory) { + /* * We can only add to the default POSIX ACE list if the ACE is * designed to be inherited by both files and directories. @@ -391,14 +517,45 @@ static BOOL unpack_canon_ace(files_struct *fsp, if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) == (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) { DLIST_ADD(dir_ace, current_ace); - } else { - DEBUG(0,("unpack_canon_ace: unable to use a non-generic default ACE.\n")); - free(current_ace); + + /* + * If this is not an inherit only ACE we need to add a duplicate + * to the file acl. + */ + + if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { + canon_ace *dup_ace = dup_canon_ace(current_ace); + + if (!dup_ace) { + DEBUG(0,("unpack_canon_ace: malloc fail !\n")); + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + return False; + } + + current_ace = dup_ace; + } else { + current_ace = NULL; + } } - } else { + } + + /* + * Only add to the file ACL if not inherit only. + */ + + if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { DLIST_ADD(file_ace, current_ace); all_aces_are_inherit_only = False; + current_ace = NULL; } + + /* + * Free if ACE was not addedd. + */ + + if (current_ace) + free(current_ace); } if (fsp->is_directory && all_aces_are_inherit_only) { @@ -431,6 +588,36 @@ static BOOL unpack_canon_ace(files_struct *fsp, goto again_dir; } + /* + * A well formed POSIX file or default ACL has at least 3 entries, a + * SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ + * and optionally a mask entry. Ensure this is the case. + */ + + if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, False)) { + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + return False; + } + + if (!ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + return False; + } + + if( DEBUGLVL( 10 )) { + dbgtext("unpack_canon_ace: File ACL:\n"); + for (i = 0, current_ace = file_ace; current_ace; current_ace = current_ace->next, i++ ) { + print_canon_ace( current_ace, i); + } + + dbgtext("unpack_canon_ace: Directory ACL:\n"); + for (i = 0, current_ace = dir_ace; current_ace; current_ace = current_ace->next, i++ ) { + print_canon_ace( current_ace, i); + } + } + *ppfile_ace = file_ace; *ppdir_ace = dir_ace; return True; @@ -914,7 +1101,7 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) Attempt to apply an ACL to a file or directory. ****************************************************************************/ -static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace) +static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, BOOL *pacl_set_support) { BOOL ret = False; SMB_ACL_T the_acl = sys_acl_init((int)count_canon_ace_list(the_ace) + 1); @@ -933,6 +1120,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n", default_ace ? "default" : "file", strerror(errno) )); #endif + *pacl_set_support = False; return False; } @@ -950,6 +1138,13 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } + /* + * Ok - we now know the ACL calls should be working, don't + * allow fallback to chmod. + */ + + *pacl_set_support = True; + /* * Initialise the entry from the canon_ace. */ @@ -1041,7 +1236,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if (sys_acl_valid(the_acl) == -1) { - DEBUG(0,("set_canon_ace_list: ACL is invalid for set (%s).\n", strerror(errno) )); + DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", + the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", + strerror(errno) )); goto done; } @@ -1051,7 +1248,8 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if(default_ace || fsp->is_directory || fsp->fd == -1) { if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { - DEBUG(0,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", + DEBUG(0,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", + the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", fsp->fsp_name, strerror(errno) )); goto done; } @@ -1150,7 +1348,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) num_acls = count_canon_ace_list(file_ace); if (fsp->is_directory) { - if (dir_ace) + if (dir_acl) dir_ace = canonicalise_acl( dir_acl, &sbuf); else dir_ace = unix_canonicalise_acl(fsp, &sbuf, &owner_sid, &group_sid); @@ -1302,7 +1500,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); - acl_perms = unpack_canon_ace( fsp, &file_owner_sid, &file_grp_sid, + acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); posix_perms = unpack_posix_permissions( fsp, &sbuf, &perms, security_info_sent, psd, acl_perms); @@ -1324,17 +1522,31 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) { BOOL acl_set_support = False; + BOOL ret = False; /* * Try using the POSIX ACL set first. All back to chmod if * we have no ACL support on this filesystem. */ - if (acl_perms && file_ace_list && set_canon_ace_list(fsp, file_ace_list, False)) - acl_set_support = True; + if (acl_perms && file_ace_list) { + ret = set_canon_ace_list(fsp, file_ace_list, False, &acl_set_support); + if (acl_set_support && ret == False) { + DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) )); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } + } - if (acl_perms && acl_set_support && fsp->is_directory && dir_ace_list) - set_canon_ace_list(fsp, dir_ace_list, True); + if (acl_perms && acl_set_support && fsp->is_directory && dir_ace_list) { + if (!set_canon_ace_list(fsp, dir_ace_list, True, &acl_set_support)) { + DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } + } /* * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. @@ -1347,7 +1559,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) file_ace_list = NULL; dir_ace_list = NULL; - DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", + DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)perms )); if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), perms) == -1) { @@ -1363,4 +1575,81 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) return True; } + +/**************************************************************************** + Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL + and set the mask to rwx. Needed to preserve complex ACLs set by NT. +****************************************************************************/ + +static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) +{ + int entry_id = SMB_ACL_FIRST_ENTRY; + SMB_ACL_ENTRY_T entry; + int num_entries = 0; + +#if 1 + return -1; +#else + while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; + + if (sys_acl_get_tag_type(entry, &tagtype) == -1) + return -1; + + if (sys_acl_get_permset(entry, &permset) == -1) + return -1; + + num_entries++; + + switch(tagtype) { + case SMB_ACL_USER_OBJ: + break; + case SMB_ACL_USER: + break; + case SMB_ACL_GROUP_OBJ: + break; + case SMB_ACL_GROUP: + break; + case SMB_ACL_MASK: + break; + case SMB_ACL_OTHER: + break; + } + + } +#endif +} + +/**************************************************************************** + Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL + and set the mask to rwx. Needed to preserve complex ACLs set by NT. + Note that name is in UNIX character set. +****************************************************************************/ + +int chmod_acl(char *name, mode_t mode) +{ + SMB_ACL_T posix_acl = NULL; + + if ((posix_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS)) == NULL) + return -1; + + return chmod_acl_internals(posix_acl, mode); +} + +/**************************************************************************** + Do an fchmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL + and set the mask to rwx. Needed to preserve complex ACLs set by NT. +****************************************************************************/ + +int fchmod_acl(int fd, mode_t mode) +{ + SMB_ACL_T posix_acl = NULL; + + if ((posix_acl = sys_acl_get_fd(fd)) == NULL) + return -1; + + return chmod_acl_internals(posix_acl, mode); +} + #undef OLD_NTDOMAIN diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ea0309599f..0916dc5b7e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -44,7 +44,7 @@ int max_recv = BUFFER_SIZE; extern int last_message; extern int global_oplock_break; -extern pstring sesssetup_user; +extern userdom_struct current_user_info; extern char *last_inbuf; extern char *InBuffer; extern char *OutBuffer; @@ -524,7 +524,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize SSVAL(inbuf,smb_uid,session_tag); /* - * Ensure the correct username is in sesssetup_user. + * Ensure the correct username is in current_user_info. * This is a really ugly bugfix for problems with * multiple session_setup_and_X's being done and * allowing %U and %G substitutions to work correctly. @@ -539,7 +539,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if(session_tag != UID_FIELD_INVALID) vuser = get_valid_user_struct(session_tag); if(vuser != NULL) - pstrcpy( sesssetup_user, vuser->user.smb_name); + current_user_info = vuser->user; } /* does this protocol need to be run as root? */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7738f2594f..624dc59084 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -36,7 +36,7 @@ extern char magic_char; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -extern pstring sesssetup_user; +extern userdom_struct current_user_info; extern pstring global_myname; extern fstring global_myworkgroup; extern int global_oplock_break; @@ -879,7 +879,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int guest = True; } - pstrcpy(sesssetup_user,user); + pstrcpy(current_user_info.smb_name,user); reload_services(True); @@ -1042,7 +1042,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest); + sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1db5dc4a5f..a6e66965c3 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -33,7 +33,7 @@ extern BOOL case_mangle; extern BOOL case_sensitive; extern BOOL use_mangled_map; extern fstring remote_machine; -extern pstring sesssetup_user; +extern userdom_struct current_user_info; extern fstring remote_machine; @@ -113,8 +113,28 @@ int find_service(char *service) int iHomeService; if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) { - lp_add_home(service,iHomeService,phome_dir); - iService = lp_servicenumber(service); + /* + * If this is a winbindd provided username, remove + * the domain component before adding the service. + * Log a warning if the "path=" parameter does not + * include any macros. + */ + + fstring new_service; + char *usr_p = NULL; + + fstrcpy(new_service, service); + + if ((usr_p = strchr(service,*lp_winbind_separator())) != NULL) + fstrcpy(new_service, usr_p+1); + + lp_add_home(new_service,iHomeService,phome_dir); + iService = lp_servicenumber(new_service); + + if (usr_p && (strchr(lp_pathname(iService),'%') == NULL)) + DEBUG(0,("find_service: Service %s added for user %s - contains non-local (Domain) user \ +with non parameterised path (%s). This may be cause the wrong directory to be seen.\n", + new_service, service, lp_pathname(iService) )); } } } @@ -234,11 +254,11 @@ connection_struct *make_connection(char *service,char *user,char *password, int return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); } } else { - /* Security = share. Try with sesssetup_user + /* Security = share. Try with current_user_info.smb_name * as the username. */ - if(*sesssetup_user) { + if(*current_user_info.smb_name) { fstring dos_username; - fstrcpy(user,sesssetup_user); + fstrcpy(user,current_user_info.smb_name); fstrcpy(dos_username, user); unix_to_dos(dos_username, True); return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index a9d8a32430..ad4d4ddbef 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -107,6 +107,20 @@ int vfswrap_mkdir(connection_struct *conn, char *path, mode_t mode) #endif result = mkdir(path, mode); + + if (result == 0) { + /* + * We need to do this as the default behavior of POSIX ACLs + * is to set the mask to be the requested group permission + * bits, not the group permission bits to be the requested + * group permission bits. This is not what we want, as it will + * mess up any inherited ACL bits that were set. JRA. + */ + if (conn->vfs_ops.chmod_acl != NULL) { + conn->vfs_ops.chmod_acl(conn, path, mode); + } + } + END_PROFILE(syscall_mkdir); return result; } @@ -332,6 +346,19 @@ int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) } #endif + /* + * We need to do this due to the fact that the default POSIX ACL + * chmod modifies the ACL *mask* for the group owner, not the + * group owner bits directly. JRA. + */ + + if (conn->vfs_ops.chmod_acl != NULL) { + if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) { + END_PROFILE(syscall_chmod); + return result; + } + } + result = chmod(path, mode); END_PROFILE(syscall_chmod); return result; @@ -506,4 +533,15 @@ BOOL vfswrap_set_nt_acl(files_struct *fsp, char *name, uint32 security_info_sent { return set_nt_acl(fsp, security_info_sent, psd); } + +int vfswrap_chmod_acl(connection_struct *conn, char *name, mode_t mode) +{ + return chmod_acl(name, mode); +} + +int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode) +{ + return fchmod_acl(fd, mode); +} + #undef OLD_NTDOMAIN diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index cbd1fd6825..2cd83c37f3 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -74,7 +74,10 @@ struct vfs_ops default_vfs_ops = { vfswrap_fget_nt_acl, vfswrap_get_nt_acl, vfswrap_fset_nt_acl, - vfswrap_set_nt_acl + vfswrap_set_nt_acl, + + vfswrap_chmod_acl, + vfswrap_fchmod_acl }; /**************************************************************************** @@ -257,6 +260,13 @@ BOOL vfs_init_custom(connection_struct *conn) conn->vfs_ops.set_nt_acl = default_vfs_ops.set_nt_acl; } + if (conn->vfs_ops.chmod_acl == NULL) { + conn->vfs_ops.chmod_acl = default_vfs_ops.chmod_acl; + } + + if (conn->vfs_ops.fchmod_acl == NULL) { + conn->vfs_ops.fchmod_acl = default_vfs_ops.fchmod_acl; + } return True; } #endif -- cgit From 42571a656f458d9a60850d08202b8daebdcb0bc1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 23 Jan 2001 22:13:41 +0000 Subject: only add the service name and client machine name to list of users names for a session when in share mode security --jerry (This used to be commit 22d6c2c163dd578365bff85ef95abfa59fe356ea) --- source3/smbd/reply.c | 7 ++++++- source3/smbd/service.c | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 624dc59084..dc604cf49b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -115,7 +115,12 @@ int reply_special(char *inbuf,char *outbuf) break; } - add_session_user(remote_machine); + /* only add the client's machine name to the list + of possibly valid usernames if we are operating + in share mode security */ + if (lp_security() == SEC_SHARE) { + add_session_user(remote_machine); + } reload_services(True); reopen_logs(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a6e66965c3..96f00eef12 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -301,8 +301,11 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* lowercase the user name */ strlower(user); - /* add it as a possible user name */ - add_session_user(service); + /* add it as a possible user name if we + are in share mode security */ + if (lp_security() == SEC_SHARE) { + add_session_user(service); + } /* shall we let them in? */ if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { -- cgit From 327e2b302991455d48fdbc7c05874c4fdad03e79 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Jan 2001 22:21:46 +0000 Subject: Fix from Kenichi Okuyama for memory leak on Realloc fail. Jeremy. (This used to be commit 6e568332254cf60d6a1f411df960ac2ec5f4bf8e) --- source3/smbd/trans2.c | 72 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a08127694a..a45c2183ce 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -261,9 +261,11 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, } /* Realloc the size of parameters and data we will return */ - params = *pparams = Realloc(*pparams, 28); - if(params == NULL) + params = Realloc(*pparams, 28); + if( params == NULL ) { return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; memset((char *)params,'\0',28); SSVAL(params,0,fsp->fnum); @@ -715,15 +717,19 @@ static int call_trans2findfirst(connection_struct *conn, DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); - pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024); - if(!*ppdata) + pdata = Realloc(*ppdata, max_data_bytes + 1024); + if( pdata == NULL ) { return(ERROR(ERRDOS,ERRnomem)); + } + *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + 1024); /* Realloc the params space */ - params = *pparams = Realloc(*pparams, 10); - if(params == NULL) + params = Realloc(*pparams, 10); + if( params == NULL ) { return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); if (dptr_num < 0) @@ -904,15 +910,19 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return(ERROR(ERRDOS,ERRunknownlevel)); } - pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024); - if(!*ppdata) + pdata = Realloc( *ppdata, max_data_bytes + 1024); + if(pdata == NULL) { return(ERROR(ERRDOS,ERRnomem)); + } + *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + 1024); /* Realloc the params space */ - params = *pparams = Realloc(*pparams, 6*SIZEOFWORD); - if(!params) + params = Realloc(*pparams, 6*SIZEOFWORD); + if( params == NULL ) { return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; /* Check that the dptr is valid */ if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) @@ -1114,7 +1124,11 @@ static int call_trans2qfsinfo(connection_struct *conn, return (ERROR(ERRSRV,ERRinvdevice)); } - pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024); + pdata = Realloc(*ppdata, max_data_bytes + 1024); + if ( pdata == NULL ) { + return(ERROR(ERRDOS,ERRnomem)); + } + *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + 1024); switch (info_level) @@ -1375,10 +1389,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* from now on we only want the part after the / */ fname = p; - params = *pparams = Realloc(*pparams,2); + params = Realloc(*pparams,2); + if ( params == NULL ) { + return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; memset((char *)params,'\0',2); data_size = max_data_bytes + 1024; - pdata = *ppdata = Realloc(*ppdata, data_size); + pdata = Realloc(*ppdata, data_size); + if ( pdata == NULL ) { + return(ERROR(ERRDOS,ERRnomem)); + } + *ppdata = pdata; if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ @@ -1641,9 +1663,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, tran_call,fname,info_level,total_data)); /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,2); - if(params == NULL) + params = Realloc(*pparams,2); + if(params == NULL) { return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; SSVAL(params,0,0); @@ -2041,9 +2065,11 @@ static int call_trans2mkdir(connection_struct *conn, } /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,2); - if(params == NULL) + params = Realloc(*pparams,2); + if(params == NULL) { return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; SSVAL(params,0,0); @@ -2077,9 +2103,11 @@ static int call_trans2findnotifyfirst(connection_struct *conn, } /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,6); - if(params == NULL) + params = Realloc(*pparams,6); + if(params == NULL) { return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; SSVAL(params,0,fnf_handle); SSVAL(params,2,0); /* No changes */ @@ -2109,9 +2137,11 @@ static int call_trans2findnotifynext(connection_struct *conn, DEBUG(3,("call_trans2findnotifynext\n")); /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,4); - if(params == NULL) + params = Realloc(*pparams,4); + if(params == NULL) { return(ERROR(ERRDOS,ERRnomem)); + } + *pparams = params; SSVAL(params,0,0); /* No changes */ SSVAL(params,2,0); /* No EA errors */ -- cgit From 918c3ebe32aacee82fe354d5b9b7ea4d477dcfda Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Jan 2001 19:04:56 +0000 Subject: smbd/lanman.c: Fix for calling qsort with 0 number. smbd/nttrans.c: Realloc mem fixes based on those that went into trans2.c smbd/process.c: Move to a table based dispatch, based on a comment from Andrew about Antons work. Jeremy. (This used to be commit a958f7822e095367efb8749b6f1f2e110ffb8866) --- source3/smbd/lanman.c | 3 +- source3/smbd/nttrans.c | 16 +- source3/smbd/process.c | 525 +++++++++++++++++++++++++++++++------------------ 3 files changed, 344 insertions(+), 200 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 33da479361..23ce19f532 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1341,7 +1341,8 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param data_len = fixed_len = string_len = 0; missed = 0; - qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); + if (total > 0) + qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); { char *lastname=NULL; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c0ccea0add..3aaaa9aebb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1024,10 +1024,12 @@ static int do_nt_transact_create_pipe( connection_struct *conn, return ret; /* Realloc the size of parameters and data we will return */ - params = *ppparams = Realloc(*ppparams, 69); + params = Realloc(*ppparams, 69); if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); + *ppparams = params; + memset((char *)params,'\0',69); p = params; @@ -1337,10 +1339,12 @@ static int call_nt_transact_create(connection_struct *conn, restore_case_semantics(file_attributes); /* Realloc the size of parameters and data we will return */ - params = *ppparams = Realloc(*ppparams, 69); + params = Realloc(*ppparams, 69); if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); + *ppparams = params; + memset((char *)params,'\0',69); p = params; @@ -1520,10 +1524,12 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); - params = *ppparams = Realloc(*ppparams, 4); + params = Realloc(*ppparams, 4); if(params == NULL) return(ERROR(ERRDOS,ERRnomem)); + *ppparams = params; + /* * Get the permissions to return. */ @@ -1548,12 +1554,14 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Allocate the data we will point this at. */ - data = *ppdata = Realloc(*ppdata, sd_size); + data = Realloc(*ppdata, sd_size); if(data == NULL) { free_sec_desc(&psd); return(ERROR(ERRDOS,ERRnomem)); } + *ppdata = data; + memset(data, '\0', sd_size); /* diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0916dc5b7e..9d857440b8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -317,114 +317,270 @@ force write permissions on print services. */ struct smb_message_struct { - int code; char *name; int (*fn)(connection_struct *conn, char *, char *, int, int); int flags; } - smb_messages[] = { - - /* CORE PROTOCOL */ - - {SMBnegprot,"SMBnegprot",reply_negprot,0}, - {SMBtcon,"SMBtcon",reply_tcon,0}, - {SMBtdis,"SMBtdis",reply_tdis,0}, - {SMBexit,"SMBexit",reply_exit,0}, - {SMBioctl,"SMBioctl",reply_ioctl,0}, - {SMBecho,"SMBecho",reply_echo,0}, - {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, - {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, - {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ - {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, - {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, - {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, - {SMBsearch,"SMBsearch",reply_search,AS_USER}, - {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK }, - - /* note that SMBmknew and SMBcreate are deliberately overloaded */ - {SMBcreate,"SMBcreate",reply_mknew,AS_USER}, - {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, - - {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, - {SMBread,"SMBread",reply_read,AS_USER}, - {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC }, - {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC }, - {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, - {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, - {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER}, - {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, - - /* this is a Pathworks specific call, allowing the - changing of the root path */ - {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, - - {SMBlseek,"SMBlseek",reply_lseek,AS_USER}, - {SMBflush,"SMBflush",reply_flush,AS_USER}, - {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, - {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK }, - {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER}, - {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER}, - {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER}, - {SMBlock,"SMBlock",reply_lock,AS_USER}, - {SMBunlock,"SMBunlock",reply_unlock,AS_USER}, - - /* CORE+ PROTOCOL FOLLOWS */ - - {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER}, - {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER}, - {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER}, - {SMBlockread,"SMBlockread",reply_lockread,AS_USER}, - {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER}, - - /* LANMAN1.0 PROTOCOL FOLLOWS */ - - {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER}, - {SMBreadBs,"SMBreadBs",NULL,AS_USER}, - {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER}, - {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER}, - {SMBwritec,"SMBwritec",NULL,AS_USER}, - {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, - {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER }, - {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, - {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC}, - {SMBioctls,"SMBioctls",NULL,AS_USER}, - {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, - {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, - - {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, - {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, - {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, - {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER }, - - {SMBffirst,"SMBffirst",reply_search,AS_USER}, - {SMBfunique,"SMBfunique",reply_search,AS_USER}, - {SMBfclose,"SMBfclose",reply_fclose,AS_USER}, - - /* LANMAN2.0 PROTOCOL FOLLOWS */ - {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, - {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC }, - {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, - - /* NT PROTOCOL FOLLOWS */ - {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, - {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, - {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, - {SMBntcancel, "SMBntcancel", reply_ntcancel, 0 }, - - /* messaging routines */ - {SMBsends,"SMBsends",reply_sends,AS_GUEST}, - {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST}, - {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST}, - {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST}, - - /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */ - - {SMBsendb,"SMBsendb",NULL,AS_GUEST}, - {SMBfwdname,"SMBfwdname",NULL,AS_GUEST}, - {SMBcancelf,"SMBcancelf",NULL,AS_GUEST}, - {SMBgetmac,"SMBgetmac",NULL,AS_GUEST} - }; + smb_messages[256] = { + +/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, +/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, +/* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK }, +/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER}, +/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC }, +/* 0x05 */ { "SMBflush",reply_flush,AS_USER}, +/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, +/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, +/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER}, +/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, +/* 0x0a */ { "SMBread",reply_read,AS_USER}, +/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC }, +/* 0x0c */ { "SMBlock",reply_lock,AS_USER}, +/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER}, +/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, +/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, +/* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER}, +/* 0x11 */ { "SMBexit",reply_exit,0}, +/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER}, +/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER}, +/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER}, +/* 0x15 */ { NULL, NULL, 0 }, +/* 0x16 */ { NULL, NULL, 0 }, +/* 0x17 */ { NULL, NULL, 0 }, +/* 0x18 */ { NULL, NULL, 0 }, +/* 0x19 */ { NULL, NULL, 0 }, +/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER}, +/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER}, +/* 0x1c */ { "SMBreadBs",NULL,AS_USER}, +/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER}, +/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER}, +/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER}, +/* 0x20 */ { "SMBwritec",NULL,AS_USER}, +/* 0x21 */ { NULL, NULL, 0 }, +/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, +/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, +/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER }, +/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, +/* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC}, +/* 0x27 */ { "SMBioctl",reply_ioctl,0}, +/* 0x28 */ { "SMBioctls",NULL,AS_USER}, +/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, +/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, +/* 0x2b */ { "SMBecho",reply_echo,0}, +/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER}, +/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, +/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, +/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, +/* 0x30 */ { NULL, NULL, 0 }, +/* 0x31 */ { NULL, NULL, 0 }, +/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC }, +/* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER}, +/* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER}, +/* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER}, +/* 0x36 */ { NULL, NULL, 0 }, +/* 0x37 */ { NULL, NULL, 0 }, +/* 0x38 */ { NULL, NULL, 0 }, +/* 0x39 */ { NULL, NULL, 0 }, +/* 0x3a */ { NULL, NULL, 0 }, +/* 0x3b */ { NULL, NULL, 0 }, +/* 0x3c */ { NULL, NULL, 0 }, +/* 0x3d */ { NULL, NULL, 0 }, +/* 0x3e */ { NULL, NULL, 0 }, +/* 0x3f */ { NULL, NULL, 0 }, +/* 0x40 */ { NULL, NULL, 0 }, +/* 0x41 */ { NULL, NULL, 0 }, +/* 0x42 */ { NULL, NULL, 0 }, +/* 0x43 */ { NULL, NULL, 0 }, +/* 0x44 */ { NULL, NULL, 0 }, +/* 0x45 */ { NULL, NULL, 0 }, +/* 0x46 */ { NULL, NULL, 0 }, +/* 0x47 */ { NULL, NULL, 0 }, +/* 0x48 */ { NULL, NULL, 0 }, +/* 0x49 */ { NULL, NULL, 0 }, +/* 0x4a */ { NULL, NULL, 0 }, +/* 0x4b */ { NULL, NULL, 0 }, +/* 0x4c */ { NULL, NULL, 0 }, +/* 0x4d */ { NULL, NULL, 0 }, +/* 0x4e */ { NULL, NULL, 0 }, +/* 0x4f */ { NULL, NULL, 0 }, +/* 0x50 */ { NULL, NULL, 0 }, +/* 0x51 */ { NULL, NULL, 0 }, +/* 0x52 */ { NULL, NULL, 0 }, +/* 0x53 */ { NULL, NULL, 0 }, +/* 0x54 */ { NULL, NULL, 0 }, +/* 0x55 */ { NULL, NULL, 0 }, +/* 0x56 */ { NULL, NULL, 0 }, +/* 0x57 */ { NULL, NULL, 0 }, +/* 0x58 */ { NULL, NULL, 0 }, +/* 0x59 */ { NULL, NULL, 0 }, +/* 0x5a */ { NULL, NULL, 0 }, +/* 0x5b */ { NULL, NULL, 0 }, +/* 0x5c */ { NULL, NULL, 0 }, +/* 0x5d */ { NULL, NULL, 0 }, +/* 0x5e */ { NULL, NULL, 0 }, +/* 0x5f */ { NULL, NULL, 0 }, +/* 0x60 */ { NULL, NULL, 0 }, +/* 0x61 */ { NULL, NULL, 0 }, +/* 0x62 */ { NULL, NULL, 0 }, +/* 0x63 */ { NULL, NULL, 0 }, +/* 0x64 */ { NULL, NULL, 0 }, +/* 0x65 */ { NULL, NULL, 0 }, +/* 0x66 */ { NULL, NULL, 0 }, +/* 0x67 */ { NULL, NULL, 0 }, +/* 0x68 */ { NULL, NULL, 0 }, +/* 0x69 */ { NULL, NULL, 0 }, +/* 0x6a */ { NULL, NULL, 0 }, +/* 0x6b */ { NULL, NULL, 0 }, +/* 0x6c */ { NULL, NULL, 0 }, +/* 0x6d */ { NULL, NULL, 0 }, +/* 0x6e */ { NULL, NULL, 0 }, +/* 0x6f */ { NULL, NULL, 0 }, +/* 0x70 */ { "SMBtcon",reply_tcon,0}, +/* 0x71 */ { "SMBtdis",reply_tdis,0}, +/* 0x72 */ { "SMBnegprot",reply_negprot,0}, +/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0}, +/* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ +/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0}, +/* 0x76 */ { NULL, NULL, 0 }, +/* 0x77 */ { NULL, NULL, 0 }, +/* 0x78 */ { NULL, NULL, 0 }, +/* 0x79 */ { NULL, NULL, 0 }, +/* 0x7a */ { NULL, NULL, 0 }, +/* 0x7b */ { NULL, NULL, 0 }, +/* 0x7c */ { NULL, NULL, 0 }, +/* 0x7d */ { NULL, NULL, 0 }, +/* 0x7e */ { NULL, NULL, 0 }, +/* 0x7f */ { NULL, NULL, 0 }, +/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER}, +/* 0x81 */ { "SMBsearch",reply_search,AS_USER}, +/* 0x82 */ { "SMBffirst",reply_search,AS_USER}, +/* 0x83 */ { "SMBfunique",reply_search,AS_USER}, +/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER}, +/* 0x85 */ { NULL, NULL, 0 }, +/* 0x86 */ { NULL, NULL, 0 }, +/* 0x87 */ { NULL, NULL, 0 }, +/* 0x88 */ { NULL, NULL, 0 }, +/* 0x89 */ { NULL, NULL, 0 }, +/* 0x8a */ { NULL, NULL, 0 }, +/* 0x8b */ { NULL, NULL, 0 }, +/* 0x8c */ { NULL, NULL, 0 }, +/* 0x8d */ { NULL, NULL, 0 }, +/* 0x8e */ { NULL, NULL, 0 }, +/* 0x8f */ { NULL, NULL, 0 }, +/* 0x90 */ { NULL, NULL, 0 }, +/* 0x91 */ { NULL, NULL, 0 }, +/* 0x92 */ { NULL, NULL, 0 }, +/* 0x93 */ { NULL, NULL, 0 }, +/* 0x94 */ { NULL, NULL, 0 }, +/* 0x95 */ { NULL, NULL, 0 }, +/* 0x96 */ { NULL, NULL, 0 }, +/* 0x97 */ { NULL, NULL, 0 }, +/* 0x98 */ { NULL, NULL, 0 }, +/* 0x99 */ { NULL, NULL, 0 }, +/* 0x9a */ { NULL, NULL, 0 }, +/* 0x9b */ { NULL, NULL, 0 }, +/* 0x9c */ { NULL, NULL, 0 }, +/* 0x9d */ { NULL, NULL, 0 }, +/* 0x9e */ { NULL, NULL, 0 }, +/* 0x9f */ { NULL, NULL, 0 }, +/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, +/* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, +/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, +/* 0xa3 */ { NULL, NULL, 0 }, +/* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 }, +/* 0xa5 */ { NULL, NULL, 0 }, +/* 0xa6 */ { NULL, NULL, 0 }, +/* 0xa7 */ { NULL, NULL, 0 }, +/* 0xa8 */ { NULL, NULL, 0 }, +/* 0xa9 */ { NULL, NULL, 0 }, +/* 0xaa */ { NULL, NULL, 0 }, +/* 0xab */ { NULL, NULL, 0 }, +/* 0xac */ { NULL, NULL, 0 }, +/* 0xad */ { NULL, NULL, 0 }, +/* 0xae */ { NULL, NULL, 0 }, +/* 0xaf */ { NULL, NULL, 0 }, +/* 0xb0 */ { NULL, NULL, 0 }, +/* 0xb1 */ { NULL, NULL, 0 }, +/* 0xb2 */ { NULL, NULL, 0 }, +/* 0xb3 */ { NULL, NULL, 0 }, +/* 0xb4 */ { NULL, NULL, 0 }, +/* 0xb5 */ { NULL, NULL, 0 }, +/* 0xb6 */ { NULL, NULL, 0 }, +/* 0xb7 */ { NULL, NULL, 0 }, +/* 0xb8 */ { NULL, NULL, 0 }, +/* 0xb9 */ { NULL, NULL, 0 }, +/* 0xba */ { NULL, NULL, 0 }, +/* 0xbb */ { NULL, NULL, 0 }, +/* 0xbc */ { NULL, NULL, 0 }, +/* 0xbd */ { NULL, NULL, 0 }, +/* 0xbe */ { NULL, NULL, 0 }, +/* 0xbf */ { NULL, NULL, 0 }, +/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK }, +/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER}, +/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER}, +/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER}, +/* 0xc4 */ { NULL, NULL, 0 }, +/* 0xc5 */ { NULL, NULL, 0 }, +/* 0xc6 */ { NULL, NULL, 0 }, +/* 0xc7 */ { NULL, NULL, 0 }, +/* 0xc8 */ { NULL, NULL, 0 }, +/* 0xc9 */ { NULL, NULL, 0 }, +/* 0xca */ { NULL, NULL, 0 }, +/* 0xcb */ { NULL, NULL, 0 }, +/* 0xcc */ { NULL, NULL, 0 }, +/* 0xcd */ { NULL, NULL, 0 }, +/* 0xce */ { NULL, NULL, 0 }, +/* 0xcf */ { NULL, NULL, 0 }, +/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST}, +/* 0xd1 */ { "SMBsendb",NULL,AS_GUEST}, +/* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST}, +/* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST}, +/* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST}, +/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST}, +/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST}, +/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST}, +/* 0xd8 */ { NULL, NULL, 0 }, +/* 0xd9 */ { NULL, NULL, 0 }, +/* 0xda */ { NULL, NULL, 0 }, +/* 0xdb */ { NULL, NULL, 0 }, +/* 0xdc */ { NULL, NULL, 0 }, +/* 0xdd */ { NULL, NULL, 0 }, +/* 0xde */ { NULL, NULL, 0 }, +/* 0xdf */ { NULL, NULL, 0 }, +/* 0xe0 */ { NULL, NULL, 0 }, +/* 0xe1 */ { NULL, NULL, 0 }, +/* 0xe2 */ { NULL, NULL, 0 }, +/* 0xe3 */ { NULL, NULL, 0 }, +/* 0xe4 */ { NULL, NULL, 0 }, +/* 0xe5 */ { NULL, NULL, 0 }, +/* 0xe6 */ { NULL, NULL, 0 }, +/* 0xe7 */ { NULL, NULL, 0 }, +/* 0xe8 */ { NULL, NULL, 0 }, +/* 0xe9 */ { NULL, NULL, 0 }, +/* 0xea */ { NULL, NULL, 0 }, +/* 0xeb */ { NULL, NULL, 0 }, +/* 0xec */ { NULL, NULL, 0 }, +/* 0xed */ { NULL, NULL, 0 }, +/* 0xee */ { NULL, NULL, 0 }, +/* 0xef */ { NULL, NULL, 0 }, +/* 0xf0 */ { NULL, NULL, 0 }, +/* 0xf1 */ { NULL, NULL, 0 }, +/* 0xf2 */ { NULL, NULL, 0 }, +/* 0xf3 */ { NULL, NULL, 0 }, +/* 0xf4 */ { NULL, NULL, 0 }, +/* 0xf5 */ { NULL, NULL, 0 }, +/* 0xf6 */ { NULL, NULL, 0 }, +/* 0xf7 */ { NULL, NULL, 0 }, +/* 0xf8 */ { NULL, NULL, 0 }, +/* 0xf9 */ { NULL, NULL, 0 }, +/* 0xfa */ { NULL, NULL, 0 }, +/* 0xfb */ { NULL, NULL, 0 }, +/* 0xfc */ { NULL, NULL, 0 }, +/* 0xfd */ { NULL, NULL, 0 }, +/* 0xfe */ { NULL, NULL, 0 }, +/* 0xff */ { NULL, NULL, 0 } + +}; /******************************************************************* dump a prs to a file @@ -457,9 +613,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { static pid_t pid= (pid_t)-1; int outsize = 0; - static int num_smb_messages = - sizeof(smb_messages) / sizeof(struct smb_message_struct); - int match; extern int global_smbpid; if (pid == (pid_t)-1) @@ -475,15 +628,11 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(-1); } - for (match=0;matchuser; - } - - /* does this protocol need to be run as root? */ - if (!(flags & AS_USER)) - unbecome_user(); - - /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(conn,session_tag)) { - if (flags & AS_GUEST) - flags &= ~AS_USER; - else - return(ERROR(ERRSRV,ERRaccess)); - } - /* this code is to work around a bug is MS client 3 without - introducing a security hole - it needs to be able to do - print queue checks as guest if it isn't logged in properly */ - if (flags & AS_USER) - flags &= ~AS_GUEST; - - /* does it need write permission? */ - if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); - /* ipc services are limited */ - if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) { - return(ERROR(ERRSRV,ERRaccess)); - } + /* Ensure this value is replaced in the incoming packet. */ + SSVAL(inbuf,smb_uid,session_tag); - /* load service specific parameters */ - if (conn && !become_service(conn,(flags & AS_USER)?True:False)) { - return(ERROR(ERRSRV,ERRaccess)); - } + /* + * Ensure the correct username is in current_user_info. + * This is a really ugly bugfix for problems with + * multiple session_setup_and_X's being done and + * allowing %U and %G substitutions to work correctly. + * There is a reason this code is done here, don't + * move it unless you know what you're doing... :-). + * JRA. + */ - /* does this protocol need to be run as guest? */ - if ((flags & AS_GUEST) && - (!become_guest() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { + if (session_tag != last_session_tag) { + user_struct *vuser = NULL; + + last_session_tag = session_tag; + if(session_tag != UID_FIELD_INVALID) + vuser = get_valid_user_struct(session_tag); + if(vuser != NULL) + current_user_info = vuser->user; + } + + /* does this protocol need to be run as root? */ + if (!(flags & AS_USER)) + unbecome_user(); + + /* does this protocol need to be run as the connected user? */ + if ((flags & AS_USER) && !become_user(conn,session_tag)) { + if (flags & AS_GUEST) + flags &= ~AS_USER; + else return(ERROR(ERRSRV,ERRaccess)); - } + } + + /* this code is to work around a bug is MS client 3 without + introducing a security hole - it needs to be able to do + print queue checks as guest if it isn't logged in properly */ + if (flags & AS_USER) + flags &= ~AS_GUEST; - last_inbuf = inbuf; + /* does it need write permission? */ + if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) + return(ERROR(ERRSRV,ERRaccess)); - outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize); + /* ipc services are limited */ + if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) { + return(ERROR(ERRSRV,ERRaccess)); } - else - { - outsize = reply_unknown(inbuf,outbuf); + + /* load service specific parameters */ + if (conn && !become_service(conn,(flags & AS_USER)?True:False)) { + return(ERROR(ERRSRV,ERRaccess)); + } + + /* does this protocol need to be run as guest? */ + if ((flags & AS_GUEST) && + (!become_guest() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { + return(ERROR(ERRSRV,ERRaccess)); } + + last_inbuf = inbuf; + + outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); } - smb_dump(smb_messages[match].name, 0, outbuf, outsize); + smb_dump(smb_fn_name(type), 0, outbuf, outsize); return(outsize); } @@ -705,18 +847,11 @@ return a string containing the function name of a SMB command char *smb_fn_name(int type) { static char *unknown_name = "SMBunknown"; - static int num_smb_messages = - sizeof(smb_messages) / sizeof(struct smb_message_struct); - int match; - - for (match=0;match Date: Wed, 24 Jan 2001 19:34:53 +0000 Subject: smbd/process.c: & type with 0xff for paranioa sake... smbd/reply.c smbd/service.c: cause all "add home service" calls to go through a winbindd aware function. Jeremy. (This used to be commit a72d12e992e2755e925032aef1aa99be74bf6652) --- source3/smbd/process.c | 2 ++ source3/smbd/reply.c | 5 +--- source3/smbd/service.c | 72 +++++++++++++++++++++++++++++--------------------- 3 files changed, 45 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9d857440b8..eb18219992 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -615,6 +615,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize int outsize = 0; extern int global_smbpid; + type &= 0xff; + if (pid == (pid_t)-1) pid = sys_getpid(); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dc604cf49b..b24ec7a944 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1005,10 +1005,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!strequal(user,lp_guestaccount(-1)) && lp_servicenumber(user) < 0) { - int homes = lp_servicenumber(HOMES_NAME); - char *home = get_user_home_dir(user); - if (homes >= 0 && home) - lp_add_home(user,homes,home); + add_home_service(user,get_user_home_dir(user)); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 96f00eef12..f0ab2ba771 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -78,10 +78,50 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir) return(True); } +/**************************************************************************** + Add a home service. Returns the new service number or -1 if fail. +****************************************************************************/ + +int add_home_service(char *service, char *homedir) +{ + int iHomeService; + int iService; + fstring new_service; + char *usr_p = NULL; + + if (!service || !homedir) + return -1; + + if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) + return -1; + + /* + * If this is a winbindd provided username, remove + * the domain component before adding the service. + * Log a warning if the "path=" parameter does not + * include any macros. + */ + + fstrcpy(new_service, service); + + if ((usr_p = strchr(service,*lp_winbind_separator())) != NULL) + fstrcpy(new_service, usr_p+1); + + lp_add_home(new_service,iHomeService,homedir); + iService = lp_servicenumber(new_service); + + if ((iService != -1) && usr_p && (strstr(lp_pathname(iService),"%D") == NULL)) + DEBUG(0,("find_service: Service %s added for user %s - contains non-local (Domain) user \ +with non-domain parameterised path (%s). This may be cause the wrong directory to be seen.\n", + new_service, service, lp_pathname(iService) )); + + return iService; +} /**************************************************************************** - find a service entry. service is always in dos codepage + Find a service entry. service is always in dos codepage. ****************************************************************************/ + int find_service(char *service) { int iService; @@ -108,35 +148,7 @@ int find_service(char *service) DEBUG(3,("checking for home directory %s gave %s\n",service, phome_dir?phome_dir:"(NULL)")); - if (phome_dir) - { - int iHomeService; - if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) - { - /* - * If this is a winbindd provided username, remove - * the domain component before adding the service. - * Log a warning if the "path=" parameter does not - * include any macros. - */ - - fstring new_service; - char *usr_p = NULL; - - fstrcpy(new_service, service); - - if ((usr_p = strchr(service,*lp_winbind_separator())) != NULL) - fstrcpy(new_service, usr_p+1); - - lp_add_home(new_service,iHomeService,phome_dir); - iService = lp_servicenumber(new_service); - - if (usr_p && (strchr(lp_pathname(iService),'%') == NULL)) - DEBUG(0,("find_service: Service %s added for user %s - contains non-local (Domain) user \ -with non parameterised path (%s). This may be cause the wrong directory to be seen.\n", - new_service, service, lp_pathname(iService) )); - } - } + iService = add_home_service(service,phome_dir); } /* If we still don't have a service, attempt to add it as a printer. */ -- cgit From b15e9adea1bd09cfe78f32be9a007a9731bcb3e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Jan 2001 21:54:44 +0000 Subject: Sync up with POSIX ACL code from 2.2. Jeremy. (This used to be commit e0431672cc54ed09d6c5cf083054db12ccd9dcf6) --- source3/smbd/open.c | 7 ++++++ source3/smbd/posix_acls.c | 58 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 77962562e3..3665e7d20f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -192,6 +192,13 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); + /* + * Take care of inherited ACLs on created files. JRA. + */ + + if ((flags & O_CREAT) && (conn->vfs_ops.fchmod_acl != NULL)) + conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode); + return True; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2bd0065d58..ed8c0a94c9 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1247,7 +1247,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if(default_ace || fsp->is_directory || fsp->fd == -1) { - if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { + if (sys_acl_set_file(dos_to_unix(fsp->fsp_name,False), the_acl_type, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", fsp->fsp_name, strerror(errno) )); @@ -1587,12 +1587,14 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) SMB_ACL_ENTRY_T entry; int num_entries = 0; -#if 1 - return -1; -#else while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; + mode_t perms; + + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) + entry_id = SMB_ACL_NEXT_ENTRY; if (sys_acl_get_tag_type(entry, &tagtype) == -1) return -1; @@ -1604,21 +1606,37 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) switch(tagtype) { case SMB_ACL_USER_OBJ: + perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR); break; - case SMB_ACL_USER: - break; case SMB_ACL_GROUP_OBJ: - break; - case SMB_ACL_GROUP: + perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); break; case SMB_ACL_MASK: + perms = S_IRUSR|S_IWUSR|S_IXUSR; break; case SMB_ACL_OTHER: + perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH); break; + default: + continue; } + if (map_acl_perms_to_permset(perms, &permset) == -1) + return -1; + + if (sys_acl_set_permset(entry, permset) == -1) + return -1; } -#endif + + /* + * If this is a simple 3 element ACL then it's a standard + * UNIX permission set. Just use chmod... + */ + + if (num_entries == 3) + return -1; + + return 0; } /**************************************************************************** @@ -1630,11 +1648,20 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) int chmod_acl(char *name, mode_t mode) { SMB_ACL_T posix_acl = NULL; + int ret = -1; if ((posix_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS)) == NULL) return -1; - return chmod_acl_internals(posix_acl, mode); + if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) + goto done; + + ret = sys_acl_set_file(name, SMB_ACL_TYPE_ACCESS, posix_acl); + + done: + + sys_acl_free_acl(posix_acl); + return ret; } /**************************************************************************** @@ -1645,11 +1672,20 @@ int chmod_acl(char *name, mode_t mode) int fchmod_acl(int fd, mode_t mode) { SMB_ACL_T posix_acl = NULL; + int ret = -1; if ((posix_acl = sys_acl_get_fd(fd)) == NULL) return -1; - return chmod_acl_internals(posix_acl, mode); + if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) + goto done; + + ret = sys_acl_set_fd(fd, posix_acl); + + done: + + sys_acl_free_acl(posix_acl); + return ret; } #undef OLD_NTDOMAIN -- cgit From 5aef8a21c6e3cd690afb11d2d69d2e9bac25b6b4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 Jan 2001 02:59:13 +0000 Subject: Fixes from appliance-head for pdc searches. Jeremy. (This used to be commit d04ed97ecab846def8467f313a71ef0e5c4005f6) --- source3/smbd/password.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 69ba042155..cdf3e28b03 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1211,16 +1211,31 @@ use this machine as the password server.\n")); given a name or IP address. ************************************************************************/ -static BOOL connect_to_domain_password_server(struct cli_state *pcli, char *remote_machine, +static BOOL connect_to_domain_password_server(struct cli_state *pcli, + char *server, unsigned char *trust_passwd) { struct in_addr dest_ip; + fstring remote_machine; if(cli_initialise(pcli) == False) { DEBUG(0,("connect_to_domain_password_server: unable to initialize client connection.\n")); return False; } + if (is_ipaddress(server)) { + struct in_addr to_ip; + + if (!inet_aton(server, &to_ip) || + !name_status_find(0x20, to_ip, remote_machine)) { + DEBUG(1, ("connect_to_domain_password_server: Can't " + "resolve name for IP %s\n", server)); + return False; + } + } else { + fstrcpy(remote_machine, server); + } + standard_sub_basic(remote_machine); strupper(remote_machine); -- cgit From fcfaebda7fb35989e62bc317287896c410c7833b Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Thu, 25 Jan 2001 16:36:42 +0000 Subject: Changes from APPLIANCE_HEAD: source/smbd/server.c source/nmbd/nmbd.c - Fixed a very subtle bug with signals. Seems that POSIX requires that the signal mask be inhereted. So, if you happen to kick off smbd/nmbd from code that has the mask set on SIGUSR1, you lose messages. (This used to be commit b4c98196fc65e8b3bce928296e854987622eae78) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c895972b0e..a13f34d506 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -651,6 +651,11 @@ static void usage(char *pname) BlockSignals(True,SIGUSR2); #endif + /* POSIX demands that signals are inherited. If the invoking process has + * these signals masked, we will have problems, as we won't recieve them. */ + BlockSignals(False, SIGHUP); + BlockSignals(False, SIGUSR1); + /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); -- cgit From 2506c61ab3bd667d54c5e004cc80ce5e40643b5d Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Mon, 29 Jan 2001 21:34:08 +0000 Subject: Changes from APPLIANCE_HEAD: source/include/proto.h - make proto source/printing/nt_printing.c source/rpc_server/srv_spoolss_nt.c - Fix for the overwriting of printerdata entries when WinNT and Win2k are modifying printer parameters on PCL printers. Turns out that Win2k creates a printer with a NULL devmode entry and then expects to set it on *OPEN* (yes this is insane). So we cannot return a "default" devmode for a printer - and we must allow an open to set it. source/tdb/tdb.c - Show freelist in an easier format. Show total free. - When storing a new record, allocate memory for the key + data before the tdb_allocate() as if the malloc fails a (sparse) hole is left in the tdb. source/tdb/tdbtool.c - Show freelist in an easier format. Show total free. source/tdb/Makefile - cleaned up Makefile dependancies source/smbd/lanman.c - Fix for Win9x corrupting it's own parameter string. source/printing/printfsp.c source/printing/printing.c source/rpc_server/srv_spoolss_nt.c source/smbd/close.c - Added normal close parameter into print_fsp_end() which treats an abnormal close as error condition and deletes the spool file. (This used to be commit 025f7a092ad258ff774e3f5e53737f8210cc8af6) --- source3/smbd/close.c | 4 ++-- source3/smbd/lanman.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 62194f73a5..87bd313327 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -116,8 +116,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (close_filestruct(fsp) == -1) err1 = -1; - if (normal_close && fsp->print_file) { - print_fsp_end(fsp); + if (fsp->print_file) { + print_fsp_end(fsp, normal_close); file_free(fsp); return 0; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 23ce19f532..7dba0c06f3 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -736,7 +736,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, PACKI(desc,"W",5); /* pad1 */ PACKS(desc,"z",""); /* pszSepFile */ PACKS(desc,"z","WinPrint"); /* pszPrProc */ - PACKS(desc,"z",""); /* pszParms */ + PACKS(desc,"z",NULL); /* pszParms */ PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */ /* "don't ask" that it's done this way to fix corrupted Win9X/ME printer comments. */ -- cgit From 8e18bd58f7706ffa17f826074689a6354c0f15ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2001 00:37:12 +0000 Subject: Fix inspited by Alan Romeril. 50% speedup in domain logins with this change to default break response time of 10ms -> 0ms. Jeremy. (This used to be commit 541c7df16fff03f98c253a46b501574cafb4469f) --- source3/smbd/oplock.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 366b4d0fec..4f26eaf7f2 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -470,6 +470,9 @@ static void wait_before_sending_break(BOOL local_request) struct timeval cur_tv; long wait_left = (long)lp_oplock_break_wait_time(); + if (wait_left == 0) + return; + GetTimeOfDay(&cur_tv); wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) + -- cgit From 66f6ad97297fe09b3cbd91aab6099fd3c98b078b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 30 Jan 2001 17:08:44 +0000 Subject: Turned down noisy debug statement. From "Richard Bollinger" (This used to be commit 1ec44d62eed67d88f59417d20680a073918626bd) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index bf15be2f1c..b9b3b88269 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -644,7 +644,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, *size = sbuf.st_size; *date = sbuf.st_mtime; - DEBUG(0,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); + DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); found = True; } -- cgit From 4d6b6eb94a3bb53ab47d458a4071ba805281c6a1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Jan 2001 05:14:31 +0000 Subject: lib/system.c: Fix for pw caching. srv_samr.c: Fix for pw caching. smbd/nttrans.c: Fix to allow trans create to set ACL on open. Jeremy. (This used to be commit c4f810a7588a2faf41f4222dc77678c53ab1dec0) --- source3/smbd/nttrans.c | 139 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 93 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3aaaa9aebb..19f5859abb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1057,6 +1057,77 @@ static int do_nt_transact_create_pipe( connection_struct *conn, return -1; } +/**************************************************************************** + Internal fn to set security descriptors. +****************************************************************************/ + +static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_info_sent, int *pdef_class,uint32 *pdef_code) +{ + prs_struct pd; + SEC_DESC *psd = NULL; + TALLOC_CTX *mem_ctx; + BOOL ret; + + if (sd_len == 0) { + *pdef_class = ERRDOS; + *pdef_code = ERRbadaccess; + return False; + } + + /* + * Init the parse struct we will unmarshall from. + */ + + if ((mem_ctx = talloc_init()) == NULL) { + DEBUG(0,("set_sd: talloc_init failed.\n")); + *pdef_class = ERRDOS; + *pdef_code = ERRnomem; + return False; + } + + prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL); + + /* + * Setup the prs_struct to point at the memory we just + * allocated. + */ + + prs_give_memory( &pd, data, sd_len, False); + + /* + * Finally, unmarshall from the data buffer. + */ + + if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + free_sec_desc(&psd); + DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n")); + /* + * Return access denied for want of a better error message.. + */ + talloc_destroy(mem_ctx); + *pdef_class = ERRDOS; + *pdef_code = ERRnomem; + return False; + } + + ret = set_nt_acl( fsp, security_info_sent, psd); + + if (!ret) { + free_sec_desc(&psd); + talloc_destroy(mem_ctx); + *pdef_class = ERRDOS; + *pdef_code = ERRnoaccess; + return False; + } + + free_sec_desc(&psd); + talloc_destroy(mem_ctx); + + *pdef_class = 0; + *pdef_code = 0; + return True; +} + /**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ @@ -1068,6 +1139,7 @@ static int call_nt_transact_create(connection_struct *conn, { pstring fname; char *params = *ppparams; + char *data = *ppdata; int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); /* Breakout the oplock request bits so we can set the reply bits separately. */ @@ -1088,10 +1160,13 @@ static int call_nt_transact_create(connection_struct *conn, uint32 create_disposition; uint32 create_options; uint32 fname_len; + uint32 sd_len; uint16 root_dir_fid; int smb_ofun; int smb_open_mode; int smb_attr; + int error_class; + uint32 error_code; DEBUG(5,("call_nt_transact_create\n")); @@ -1122,6 +1197,7 @@ static int call_nt_transact_create(connection_struct *conn, share_access = IVAL(params,24); create_disposition = IVAL(params,28); create_options = IVAL(params,32); + sd_len = IVAL(params,36); fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1)); root_dir_fid = (uint16)IVAL(params,4); smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); @@ -1336,6 +1412,16 @@ static int call_nt_transact_create(connection_struct *conn, smb_action |= EXTENDED_OPLOCK_GRANTED; } + /* + * Now try and apply the desired SD. + */ + + if (!set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION, &error_class, &error_code)) { + close_file(fsp,False); + restore_case_semantics(file_attributes); + return(ERROR(error_class, error_code)); + } + restore_case_semantics(file_attributes); /* Realloc the size of parameters and data we will return */ @@ -1621,13 +1707,11 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); char *params= *ppparams; char *data = *ppdata; - prs_struct pd; - SEC_DESC *psd = NULL; uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); files_struct *fsp = NULL; uint32 security_info_sent = 0; - TALLOC_CTX *mem_ctx; - BOOL ret; + int error_class; + uint32 error_code; if(!lp_nt_acl_support()) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1643,49 +1727,9 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, (unsigned int)security_info_sent )); - /* - * Init the parse struct we will unmarshall from. - */ - - if ((mem_ctx = talloc_init()) == NULL) { - DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - return(ERROR(ERRDOS,ERRnomem)); - } - - prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL); - - /* - * Setup the prs_struct to point at the memory we just - * allocated. - */ - - prs_give_memory( &pd, data, total_data_count, False); - - /* - * Finally, unmarshall from the data buffer. - */ - - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - free_sec_desc(&psd); - DEBUG(0,("call_nt_transact_set_security_desc: Error in unmarshalling \ -security descriptor.\n")); - /* - * Return access denied for want of a better error message.. - */ - talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - ret = set_nt_acl( fsp, security_info_sent, psd); + if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code)) + return (ERROR(error_class, error_code)); - if (!ret) { - free_sec_desc(&psd); - talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - free_sec_desc(&psd); - talloc_destroy(mem_ctx); send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); return -1; } @@ -1774,6 +1818,9 @@ due to being in oplock break state.\n" )); if ((total_parameter_count && !params) || (total_data_count && !data) || (setup_count && !setup)) { + safe_free(setup); + safe_free(params); + safe_free(data); DEBUG(0,("reply_nttrans : Out of memory\n")); END_PROFILE(SMBnttrans); return(ERROR(ERRDOS,ERRnomem)); -- cgit From 607ea0d6fa00b5a9f1dea0542c039411e60f0db4 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 8 Feb 2001 18:41:01 +0000 Subject: replaced inet_aton() with inet_addr() to keep Solaris from complaining. jerry (This used to be commit 2b18c4484313e77d98c8a7524cf9f5cc2c924dc2) --- source3/smbd/password.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index cdf3e28b03..311a019506 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1225,10 +1225,16 @@ static BOOL connect_to_domain_password_server(struct cli_state *pcli, if (is_ipaddress(server)) { struct in_addr to_ip; + + /* we shouldn't have 255.255.255.255 forthe IP address of + a password server anyways */ + if ((to_ip.s_addr=inet_addr(server)) == 0xFFFFFFFF) { + DEBUG (0,("connect_to_domain_password_server: inet_addr(%s) returned 0xFFFFFFFF!\n", server)); + return False; + } - if (!inet_aton(server, &to_ip) || - !name_status_find(0x20, to_ip, remote_machine)) { - DEBUG(1, ("connect_to_domain_password_server: Can't " + if (!name_status_find(0x20, to_ip, remote_machine)) { + DEBUG(0, ("connect_to_domain_password_server: Can't " "resolve name for IP %s\n", server)); return False; } -- cgit From 01634eaf129e90877c054664703d100be9f41ce0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 8 Feb 2001 20:47:09 +0000 Subject: merge from SAMBA_2_2 (This used to be commit 9347121ce6888afeae3cdf256b5f0c5b9c58b0bc) --- source3/smbd/dir.c | 5 +++++ source3/smbd/trans2.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index b9b3b88269..6a8cde1883 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -590,6 +590,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, if (!conn->dirptr) return(False); + + if (strequal(mask, "????????.???")) + pstrcpy(mask, "*"); + + while (!found) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a45c2183ce..2210b38d74 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -375,8 +375,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(fname,dname); - if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) - got_match = mask_match(fname, mask, case_sensitive); + if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) { + if (!strcmp(mask, "*.*")) { + got_match = True; + } + else { + got_match = mask_match(fname, mask, case_sensitive); + } + } if(!got_match && !is_8_3(fname, False)) { -- cgit From b652abf92344f7af3698cbd02edc60058f13c961 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Feb 2001 23:33:50 +0000 Subject: reverted *.* patch until someone explains to me what the test case is that requires this. i _know_ that this isn't the right solution and it breaks things, which is why I am reverting now. (This used to be commit c2a82a33da1b717b16fb71e597587c806bcf68b3) --- source3/smbd/trans2.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2210b38d74..4e44d71369 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -376,12 +376,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(fname,dname); if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) { - if (!strcmp(mask, "*.*")) { - got_match = True; - } - else { got_match = mask_match(fname, mask, case_sensitive); - } } if(!got_match && !is_8_3(fname, False)) { -- cgit From 35d9695c7633711dee4aba03fc9bd0163a7c0526 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Feb 2001 21:02:11 +0000 Subject: Ensure people know this is unused. Jeremy. (This used to be commit 4f87f0f4027a0b78e091b5daaf6fb907b5811044) --- source3/smbd/unix_acls.c | 567 ----------------------------------------------- 1 file changed, 567 deletions(-) delete mode 100644 source3/smbd/unix_acls.c (limited to 'source3/smbd') diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c deleted file mode 100644 index 9ab057f77a..0000000000 --- a/source3/smbd/unix_acls.c +++ /dev/null @@ -1,567 +0,0 @@ -#define OLD_NTDOMAIN 1 -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB NT Security Descriptor / Unix permission conversion. - Copyright (C) Jeremy Allison 1994-2000 - - 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" - -/**************************************************************************** - Function to create owner and group SIDs from a SMB_STRUCT_STAT. -****************************************************************************/ - -static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) -{ - uid_to_sid( powner_sid, psbuf->st_uid ); - gid_to_sid( pgroup_sid, psbuf->st_gid ); -} - -/**************************************************************************** - Map unix perms to NT. -****************************************************************************/ - -static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w_mask, int x_mask, BOOL is_directory) -{ - SEC_ACCESS sa; - uint32 nt_mask = 0; - - *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - - if((perm & (r_mask|w_mask|x_mask)) == (r_mask|w_mask|x_mask)) { - nt_mask = UNIX_ACCESS_RWX; - } else if((perm & (r_mask|w_mask|x_mask)) == 0) { - nt_mask = UNIX_ACCESS_NONE; - } else { - nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; - if(is_directory) - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - else - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; - } - init_sec_access(&sa,nt_mask); - return sa; -} - -#if 0 -/**************************************************************************** - Validate a SID. -****************************************************************************/ - -static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) -{ - extern DOM_SID global_sam_sid; - DOM_SID sid; - - if(!sd_sid) { - DEBUG(5,("validate_unix_sid: sid missing.\n")); - return False; - } - - sid_copy(psid, sd_sid); - sid_copy(&sid, sd_sid); - - if(!sid_split_rid(&sid, prid)) { - DEBUG(5,("validate_unix_sid: cannot get RID from sid.\n")); - return False; - } - - if(!sid_equal( &sid, &global_sam_sid)) { - DEBUG(5,("validate_unix_sid: sid is not ours.\n")); - return False; - } - - return True; -} -#endif - -/**************************************************************************** - Map NT perms to UNIX. -****************************************************************************/ - -#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) -#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) -#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) - -static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) -{ - mode_t mode = 0; - - switch(type) { - case S_IRUSR: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRUSR|S_IWUSR|S_IXUSR; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; - } - break; - case S_IRGRP: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRGRP|S_IWGRP|S_IXGRP; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; - } - break; - case S_IROTH: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IROTH|S_IWOTH|S_IXOTH; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; - } - break; - } - - return mode; -} - -/**************************************************************************** - Unpack a SEC_DESC into a owner, group and set of UNIX permissions. -****************************************************************************/ - -static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode, - uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) -{ - extern DOM_SID global_sid_World; - DOM_SID owner_sid; - DOM_SID grp_sid; - DOM_SID file_owner_sid; - DOM_SID file_grp_sid; - SEC_ACL *dacl = psd->dacl; - BOOL all_aces_are_inherit_only = (is_directory ? True : False); - int i; - enum SID_NAME_USE sid_type; - - *pmode = 0; - *puser = (uid_t)-1; - *pgrp = (gid_t)-1; - - if(security_info_sent == 0) { - DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); - return False; - } - - /* - * Windows 2000 sends the owner and group SIDs as the logged in - * user, not the connected user. But it still sends the file - * owner SIDs on an ACL set. So we need to check for the file - * owner and group SIDs as well as the owner SIDs. JRA. - */ - - create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); - - /* - * Validate the owner and group SID's. - */ - - memset(&owner_sid, '\0', sizeof(owner_sid)); - memset(&grp_sid, '\0', sizeof(grp_sid)); - - DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n")); - - /* - * Don't immediately fail if the owner sid cannot be validated. - * This may be a group chown only set. - */ - - if (security_info_sent & OWNER_SECURITY_INFORMATION) { - sid_copy(&owner_sid, psd->owner_sid); - if (!sid_to_uid( &owner_sid, puser, &sid_type)) - DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); - } - - /* - * Don't immediately fail if the group sid cannot be validated. - * This may be an owner chown only set. - */ - - if (security_info_sent & GROUP_SECURITY_INFORMATION) { - sid_copy(&grp_sid, psd->grp_sid); - if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) - DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); - } - - /* - * If no DACL then this is a chown only security descriptor. - */ - - if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) { - *pmode = 0; - return True; - } - - /* - * Now go through the DACL and ensure that - * any owner/group sids match. - */ - - for(i = 0; i < dacl->num_aces; i++) { - DOM_SID ace_sid; - SEC_ACE *psa = &dacl->ace[i]; - - if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && - (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); - return False; - } - - /* - * Ignore or remove bits we don't care about on a directory ACE. - */ - - if(is_directory) { - if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n")); - continue; - } - - /* - * At least one of the ACE entries wasn't inherit only. - * Flag this so we know the returned mode is valid. - */ - - all_aces_are_inherit_only = False; - } - - /* - * Windows 2000 sets these flags even on *file* ACE's. This is wrong - * but we can ignore them for now. Revisit this when we go to POSIX - * ACLs on directories. - */ - - psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); - - if(psa->flags != 0) { - DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", - (unsigned int)psa->flags)); - return False; - } - - /* - * The security mask may be UNIX_ACCESS_NONE which should map into - * no permissions (we overload the WRITE_OWNER bit for this) or it - * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this - * to be so. Any other bits override the UNIX_ACCESS_NONE bit. - */ - - psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| - GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); - - if(psa->info.mask != UNIX_ACCESS_NONE) - psa->info.mask &= ~UNIX_ACCESS_NONE; - - sid_copy(&ace_sid, &psa->sid); - - if(sid_equal(&ace_sid, &file_owner_sid)) { - /* - * Map the desired permissions into owner perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRUSR); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); - - } else if( sid_equal(&ace_sid, &file_grp_sid)) { - /* - * Map the desired permissions into group perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRGRP); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRGRP)); - - } else if( sid_equal(&ace_sid, &global_sid_World)) { - /* - * Map the desired permissions into other perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IROTH); - else - *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); - - } else { - DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n")); - return False; - } - } - - if (is_directory && all_aces_are_inherit_only) { - /* - * Windows 2000 is doing one of these weird 'inherit acl' - * traverses to conserve NTFS ACL resources. Just pretend - * there was no DACL sent. JRA. - */ - - DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); - free_sec_acl(&psd->dacl); - } - - return True; -} - -/**************************************************************************** - Reply to query a security descriptor from an fsp. If it succeeds it allocates - the space for the return elements and returns the size needed to return the - security descriptor. This should be the only external function needed for - the UNIX style get ACL. -****************************************************************************/ - -size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) -{ - extern DOM_SID global_sid_World; - SMB_STRUCT_STAT sbuf; - SEC_ACE ace_list[6]; - DOM_SID owner_sid; - DOM_SID group_sid; - size_t sd_size; - SEC_ACL *psa = NULL; - SEC_ACCESS owner_access; - int owner_acl_type; - SEC_ACCESS group_access; - int grp_acl_type; - SEC_ACCESS other_access; - int other_acl_type; - int num_acls = 0; - - *ppdesc = NULL; - - if(!lp_nt_acl_support()) { - sid_copy( &owner_sid, &global_sid_World); - sid_copy( &group_sid, &global_sid_World); - } else { - - if(fsp->is_directory || fsp->fd == -1) { - if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { - return 0; - } - } else { - if(fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { - return 0; - } - } - - /* - * Get the owner, group and world SIDs. - */ - - create_file_sids(&sbuf, &owner_sid, &group_sid); - - /* - * Create the generic 3 element UNIX acl. - */ - - owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, - owner_access, 0); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, - group_access, 0); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, - other_access, 0); - - if(fsp->is_directory) { - /* - * For directory ACLs we also add in the inherited permissions - * ACE entries. These are the permissions a file would get when - * being created in the directory. - */ - mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - - owner_access = map_unix_perms(&owner_acl_type, mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, - owner_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, - group_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, - other_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - } - - if(num_acls) - if((psa = make_sec_acl( ACL_REVISION, num_acls, ace_list)) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); - return 0; - } - } - - *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sd_size); - - if(!*ppdesc) { - DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); - sd_size = 0; - } - - free_sec_acl(&psa); - - return sd_size; -} - -/**************************************************************************** - Reply to set a security descriptor on an fsp. security_info_sent is the - description of the following NT ACL. - This should be the only external function needed for the UNIX style set ACL. -****************************************************************************/ - -BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) -{ - connection_struct *conn = fsp->conn; - uid_t user = (uid_t)-1; - gid_t grp = (gid_t)-1; - mode_t perms = 0; - SMB_STRUCT_STAT sbuf; - BOOL got_dacl = False; - - /* - * Get the current state of the file. - */ - - if(fsp->is_directory || fsp->fd == -1) { - if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) - return False; - } else { - if(conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) - return False; - } - - /* - * Unpack the user/group/world id's and permissions. - */ - - if (!unpack_nt_permissions( &sbuf, &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) - return False; - - if (psd->dacl != NULL) - got_dacl = True; - - /* - * Do we need to chown ? - */ - - if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { - - DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - - if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { - DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); - return False; - } - - /* - * Recheck the current state of the file, which may have changed. - * (suid/sgid bits, for instance) - */ - - if(fsp->is_directory) { - if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { - return False; - } - } else { - - int ret; - - if(fsp->fd == -1) - ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); - else - ret = conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf); - - if(ret != 0) - return False; - } - } - - /* - * Only change security if we got a DACL. - */ - - if((security_info_sent & DACL_SECURITY_INFORMATION) && got_dacl) { - - /* - * Check to see if we need to change anything. - * Enforce limits on modified bits *only*. Don't enforce masks - * on bits not changed by the user. - */ - - if(fsp->is_directory) { - - perms &= (lp_dir_security_mask(SNUM(conn)) | sbuf.st_mode); - perms |= (lp_force_dir_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); - - } else { - - perms &= (lp_security_mask(SNUM(conn)) | sbuf.st_mode); - perms |= (lp_force_security_mode(SNUM(conn)) & ( perms ^ sbuf.st_mode )); - - } - - /* - * Preserve special bits. - */ - - perms |= (sbuf.st_mode & ~0777); - - /* - * Do we need to chmod ? - */ - - if(sbuf.st_mode != perms) { - - DEBUG(3,("call_nt_transact_set_security_desc: chmod %s. perms = 0%o.\n", - fsp->fsp_name, (unsigned int)perms )); - - if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), perms) == -1) { - DEBUG(3,("call_nt_transact_set_security_desc: chmod %s, 0%o failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)perms, strerror(errno) )); - return False; - } - } - } - - return True; -} -#undef OLD_NTDOMAIN -- cgit From 94fc44a93c46cece9b9fa947bff62087dbcd89fa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Feb 2001 16:18:02 +0000 Subject: Merge of JohnR's changes to appliance-head, JF's changes to 2.2, updated the POSIX_ACL code to be in sync. Jeremy. (This used to be commit c0517d6f4e3079feca1309fd1ea7b21e83f0de02) --- source3/smbd/nttrans.c | 11 ++++++++++- source3/smbd/posix_acls.c | 2 ++ source3/smbd/process.c | 29 +++++++++++++++++++++++++++-- source3/smbd/reply.c | 10 +++++----- source3/smbd/server.c | 17 +++++++++++++++++ 5 files changed, 61 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 19f5859abb..207786768b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -291,7 +291,7 @@ static void get_filename_transact( char *fname, char *inbuf, int data_offset, in * the end here. */ - if((data_len - fname_len == 1) || (inbuf[data_offset] == '\0')) { + if((data_len == 1) || (inbuf[data_offset] == '\0')) { /* * Ensure that the data offset is aligned * on a 2 byte boundary - add one if not. @@ -1110,6 +1110,15 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_i return False; } + if (psd->off_owner_sid==0) + security_info_sent &= ~OWNER_SECURITY_INFORMATION; + if (psd->off_grp_sid==0) + security_info_sent &= ~GROUP_SECURITY_INFORMATION; + if (psd->off_sacl==0) + security_info_sent &= ~DACL_SECURITY_INFORMATION; + if (psd->off_dacl==0) + security_info_sent &= ~SACL_SECURITY_INFORMATION; + ret = set_nt_acl( fsp, security_info_sent, psd); if (!ret) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ed8c0a94c9..db2f933420 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -238,6 +238,8 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n")); } + DEBUG(5,("unpack_nt_owners: owner_sids validated.\n")); + return True; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index eb18219992..461fa99f39 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -769,6 +769,30 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) return(outsize); } +/**************************************************************************** + Keep track of the number of running smbd's. This functionality is used to + 'hard' limit Samba overhead on resource constrained systems. +****************************************************************************/ +static BOOL smbd_process_limit(void) +{ + int total_smbds; + + if (lp_max_smbd_processes()) { + + /* Always add one to the smbd process count, as exit_server() always + * subtracts one. + */ + tdb_lock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + total_smbds = tdb_fetch_int(conn_tdb_ctx(), "INFO/total_smbds"); + total_smbds = total_smbds < 0 ? 1 : total_smbds + 1; + tdb_store_int(conn_tdb_ctx(), "INFO/total_smbds", total_smbds); + tdb_unlock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + + return total_smbds > lp_max_smbd_processes(); + } + else + return False; +} /**************************************************************************** process an smb from the client - split out from the process() code so @@ -792,8 +816,9 @@ void process_smb(char *inbuf, char *outbuf) deny parameters before doing any parsing of the packet passed to us by the client. This prevents attacks on our parsing code from hosts not in the hosts allow list */ - if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { - /* send a negative session response "not listining on calling + if (smbd_process_limit() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { + /* send a negative session response "not listening on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b24ec7a944..2d205543fb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -510,9 +510,9 @@ int smb_create_user(char *unix_user, char *homedir) pstrcpy(add_script, lp_adduser_script()); if (! *add_script) return -1; - pstring_sub(add_script, "%u", unix_user); + all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); if (homedir) - pstring_sub(add_script, "%H", homedir); + all_string_sub(add_script, "%H", homedir, sizeof(pstring)); ret = smbrun(add_script,NULL,False); DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); return ret; @@ -529,7 +529,7 @@ static int smb_delete_user(char *unix_user) pstrcpy(del_script, lp_deluser_script()); if (! *del_script) return -1; - pstring_sub(del_script, "%u", unix_user); + all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); ret = smbrun(del_script,NULL,False); DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); return ret; @@ -898,10 +898,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* if the username exists as a domain/username pair on the unix system then use that */ - if (!getpwnam(user)) { + if (!sys_getpwnam(user)) { pstring user2; slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False), lp_winbind_separator(), user); - if (getpwnam(user2)) { + if (sys_getpwnam(user2)) { DEBUG(3,("Using unix username %s\n", user2)); pstrcpy(user, user2); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a13f34d506..8eacd4ed58 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -409,6 +409,22 @@ static BOOL dump_core(void) } #endif +/**************************************************************************** +update the current smbd process count +****************************************************************************/ +static void decrement_smbd_process_count(void) +{ + int total_smbds; + + if (lp_max_smbd_processes()) { + tdb_lock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + if ((total_smbds = tdb_fetch_int(conn_tdb_ctx(), "INFO/total_smbds")) > 0) + tdb_store_int(conn_tdb_ctx(), "INFO/total_smbds", total_smbds - 1); + + tdb_unlock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + } +} + /**************************************************************************** exit the server ****************************************************************************/ @@ -432,6 +448,7 @@ void exit_server(char *reason) } respond_to_all_remaining_local_messages(); + decrement_smbd_process_count(); #ifdef WITH_DFS if (dcelogin_atmost_once) { -- cgit From b94ef4b67cc0b33c4a2572620234419526066f82 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Feb 2001 22:37:40 +0000 Subject: Fix for DACL/SACL masking typo - spotted by medha@pezman.austin.ibm.com. Jeremy. (This used to be commit 8fc6bc170fd3dd1fd9437d4acc94bd251c35d544) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 207786768b..cf2bdef314 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1115,9 +1115,9 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_i if (psd->off_grp_sid==0) security_info_sent &= ~GROUP_SECURITY_INFORMATION; if (psd->off_sacl==0) - security_info_sent &= ~DACL_SECURITY_INFORMATION; - if (psd->off_dacl==0) security_info_sent &= ~SACL_SECURITY_INFORMATION; + if (psd->off_dacl==0) + security_info_sent &= ~DACL_SECURITY_INFORMATION; ret = set_nt_acl( fsp, security_info_sent, psd); -- cgit From 64172d82fcf1762a8bc938282919f9e3bd39675d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 14 Feb 2001 05:34:50 +0000 Subject: Merge of i18n fixes from appliance branch. Samba can now talk to a network with a PDC that has international netbios name and domain name. There's still quite a bit of i18n stuff to fix though... (This used to be commit 79045bd72ace9144e7dd73785b1d10a71b0d15aa) --- source3/smbd/reply.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2d205543fb..e1feb921f5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -900,7 +900,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int that */ if (!sys_getpwnam(user)) { pstring user2; - slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False), lp_winbind_separator(), user); + + slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False), + lp_winbind_separator(), user); + if (sys_getpwnam(user2)) { DEBUG(3,("Using unix username %s\n", user2)); pstrcpy(user, user2); @@ -1018,7 +1021,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int p = smb_buf(outbuf); pstrcpy(p,"Unix"); p = skip_string(p,1); pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1); - pstrcpy(p,global_myworkgroup); p = skip_string(p,1); + pstrcpy(p,global_myworkgroup); unix_to_dos(p, True); p = skip_string(p,1); set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); /* perhaps grab OS version here?? */ } -- cgit From a82df9c67367e0828afcc65b0635187c73e2813a Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 15 Feb 2001 19:50:34 +0000 Subject: samba/source/nmbd/nmbd.c change remote_machine name to nmbd instead of nmb so we write to same log file that was originally created as log.nmbd samba/source/smbd/server.c change remote_machine name to smbd instead of smb so we write to same log file that was originally created as log.smbd samba/source/lib/interface.c allow binding to all interface IP addresses even if on same subnet. This allows you to specify which IP's you want in interfaces line and use bind interfaces only (This used to be commit 01dfd59712f3730498784d7632da8fe0113d55b6) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8eacd4ed58..6457dd6295 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -636,7 +636,7 @@ static void usage(char *pname) slprintf(debugf, sizeof(debugf), "%s/log.smbd", LOGFILEBASE); } - pstrcpy(remote_machine, "smb"); + pstrcpy(remote_machine, "smbd"); setup_logging(argv[0],False); -- cgit From 62dc55a43295e9e3abd9da13148b322b3aa89917 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Feb 2001 00:24:43 +0000 Subject: configure configure.in smbd/posix_acls.c smbd/dosmode.c: Fix for zero permission W2K profiles. libsmb/cliconnect.c rpc_client/cli_login.c smbd/reply.c: codepage fixes from Tim. Jeremy. (This used to be commit 3ded1e6bd5f79948e437ce5b1799705945f36ad2) --- source3/smbd/dosmode.c | 2 ++ source3/smbd/posix_acls.c | 17 ++++++++++++++--- source3/smbd/reply.c | 5 ++--- 3 files changed, 18 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 31c4fbdf31..a4b4f65ad9 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -111,6 +111,8 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) result |= lp_force_create_mode(SNUM(conn)); } } + + DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result )); return(result); } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index db2f933420..da457604bb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -391,14 +391,16 @@ static BOOL unpack_canon_ace(files_struct *fsp, canon_ace **ppfile_ace, canon_ace **ppdir_ace, uint32 security_info_sent, SEC_DESC *psd) { +#if !defined(HAVE_NO_ACLS) extern DOM_SID global_sid_World; - SEC_ACL *dacl = psd->dacl; BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; canon_ace *current_ace = NULL; enum SID_NAME_USE sid_type; int i; +#endif /* HAVE_NO_ACLS */ + SEC_ACL *dacl = psd->dacl; *ppfile_ace = NULL; *ppdir_ace = NULL; @@ -415,6 +417,13 @@ static BOOL unpack_canon_ace(files_struct *fsp, if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) return True; +#if defined(HAVE_NO_ACLS) + + /* No point in doing this if we have no ACL support. */ + return False; + +#else /* HAVE_NO_ACLS */ + /* * Now go through the DACL and create the canon_ace lists. */ @@ -623,6 +632,8 @@ static BOOL unpack_canon_ace(files_struct *fsp, *ppfile_ace = file_ace; *ppdir_ace = dir_ace; return True; + +#endif /* HAVE_NO_ACLS */ } /**************************************************************************** @@ -704,7 +715,7 @@ static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, * ACLs on directories. */ - psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); + psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERITED_ACE); if(psa->flags != 0) { DEBUG(1,("unpack_posix_permissions: unable to set ACE flags (%x).\n", @@ -1554,7 +1565,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. */ - if(!acl_set_support && (sbuf.st_mode != perms)) { + if(!acl_set_support && posix_perms && (sbuf.st_mode != perms)) { free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e1feb921f5..402f9db754 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -837,17 +837,16 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int fstrcpy(user,p); p = skip_string(p,1); /* - * Incoming user is in DOS codepage format. Convert + * Incoming user and domain are in DOS codepage format. Convert * to UNIX. */ dos_to_unix(user,True); domain = p; - + dos_to_unix(domain, True); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", domain,skip_string(p,1),skip_string(p,2))); } - DEBUG(3,("sesssetupX:name=[%s]\n",user)); /* If name ends in $ then I think it's asking about whether a */ -- cgit From fd46817f0b20c633c80dee70a29cf7478e2dfd68 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Feb 2001 19:21:18 +0000 Subject: Excise snprintf -> slprintf. srv_samr.c: duplicate gid fix. srv_spoolss_nt.c: Merge of JF's work. uid.c: Fix for returning names when a PDC. Jeremy. (This used to be commit d938ad6963a2dd4eda930d508600ec1902dc2b16) --- source3/smbd/uid.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 1d2b8f4e9f..db43106b77 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -271,6 +271,7 @@ void unbecome_root(void) BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern pstring global_myname; + extern fstring global_myworkgroup; fstring sid; char *sep = lp_winbind_separator(); @@ -287,9 +288,17 @@ BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) split_domain_name(name, domain, username); - if (strcasecmp(global_myname, domain) != 0) { - DEBUG(5, ("domain %s is not local\n", domain)); - return False; + switch (lp_server_role()) { + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + if (strequal(domain, global_myworkgroup)) + fstrcpy(domain, global_myname); + /* No break is deliberate here. JRA. */ + default: + if (strcasecmp(global_myname, domain) != 0) { + DEBUG(5, ("domain %s is not local\n", domain)); + return False; + } } ret = local_lookup_name(domain, username, psid, -- cgit From 201753ddc623a18f4ddd0d9a19391ea0471d4c49 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Feb 2001 01:31:55 +0000 Subject: Fixed file descriptor leak in error processing of print jobs. NT sends "delete on close" to cancel a print job copied from the command line. Deal with this. Merged JohnR's fixes for print job errors. Jeremy. (This used to be commit 2060d74e48d62c99a1689ee02ac435b71918ddf0) --- source3/smbd/trans2.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4e44d71369..d94a775846 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1594,9 +1594,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, BOOL bad_path = False; files_struct *fsp = NULL; - if (!CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); - if (tran_call == TRANSACT2_SETFILEINFO) { fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -1618,6 +1615,20 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } return(UNIXERROR(ERRDOS,ERRbadpath)); } + } else if (fsp->print_file) { + /* + * Doing a DELETE_ON_CLOSE should cancel a print job. + */ + if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) { + fsp->share_mode = FILE_DELETE_ON_CLOSE; + + DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", + fsp->fsp_name )); + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } } else { /* * Original code - this is an open file. @@ -1660,6 +1671,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } } + if (!CAN_WRITE(conn)) + return(ERROR(ERRSRV,ERRaccess)); + DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", tran_call,fname,info_level,total_data)); -- cgit From ed77fca1990f96dba6fe9204e551056395c6ed29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Feb 2001 03:59:37 +0000 Subject: include/rpc_spoolss.h: Added JOB_STATUS_XXX defines. include/smb.h: Added LPQ_xx enums to correspond with the NT JOB_STATUS_XXX. We need these to be different as we're storing LPQ_xx enums in the tdb already. rpc_server/srv_spoolss_nt.c: Don't need to return status strings as we're now returning status codes. smbd/lanman.c: Change the RAP status codes to have "RAP" in the name. printing/printing.c: Keep track of the status of a job. Allow a job to be deleted from one smbd when being submitted by another. Made logic in mutex clearer. Jeremy. (This used to be commit 71029da7dd74eb91dd6953752bdf238f319d985d) --- source3/smbd/lanman.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7dba0c06f3..c29f0df434 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -413,14 +413,14 @@ static int check_printq_info(struct pack_desc* desc, } -#define JOB_STATUS_QUEUED 0 -#define JOB_STATUS_PAUSED 1 -#define JOB_STATUS_SPOOLING 2 -#define JOB_STATUS_PRINTING 3 -#define JOB_STATUS_PRINTED 4 +#define RAP_JOB_STATUS_QUEUED 0 +#define RAP_JOB_STATUS_PAUSED 1 +#define RAP_JOB_STATUS_SPOOLING 2 +#define RAP_JOB_STATUS_PRINTING 3 +#define RAP_JOB_STATUS_PRINTED 4 -#define QUEUE_STATUS_PAUSED 1 -#define QUEUE_STATUS_ERROR 2 +#define RAP_QUEUE_STATUS_PAUSED 1 +#define RAP_QUEUE_STATUS_ERROR 2 /* turn a print job status into a on the wire status */ @@ -428,13 +428,13 @@ static int printj_status(int v) { switch (v) { case LPQ_QUEUED: - return JOB_STATUS_QUEUED; + return RAP_JOB_STATUS_QUEUED; case LPQ_PAUSED: - return JOB_STATUS_PAUSED; + return RAP_JOB_STATUS_PAUSED; case LPQ_SPOOLING: - return JOB_STATUS_SPOOLING; + return RAP_JOB_STATUS_SPOOLING; case LPQ_PRINTING: - return JOB_STATUS_PRINTING; + return RAP_JOB_STATUS_PRINTING; } return 0; } @@ -447,9 +447,9 @@ static int printq_status(int v) case LPQ_QUEUED: return 0; case LPQ_PAUSED: - return QUEUE_STATUS_PAUSED; + return RAP_QUEUE_STATUS_PAUSED; } - return QUEUE_STATUS_ERROR; + return RAP_QUEUE_STATUS_ERROR; } static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, -- cgit From 53a2d8ce88d152b7d5571bbb74f8dbb171cfec1f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 23 Feb 2001 16:06:18 +0000 Subject: removed wrong patch to get_dir_entry(). This was left over from the wildcard stuff.... (This used to be commit f77fa6a0e510fe5ad54d20eaabd345e6ee0526dc) --- source3/smbd/dir.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 6a8cde1883..a7e05c5682 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -591,11 +591,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, if (!conn->dirptr) return(False); - if (strequal(mask, "????????.???")) - pstrcpy(mask, "*"); - - - while (!found) { dname = ReadDirName(conn->dirptr); -- cgit From 5265ce7837a185977f71bcb39a41b57492e24964 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Feb 2001 19:22:02 +0000 Subject: Added total memory allocated counter to talloc, so we can tell if a talloc pool is getting bloated. Also added a talloc_zero function to return zeroed memory. Added debug in rpc_server/srv_pipe_hnd.c so we know when a talloc pool is being freed. Syncup with srv_pipe_hnd.c from 2.2 so we are freeing memory at the same time. Jeremy. (This used to be commit d3a56c6042acf037bbd53de88d7636a5803ead20) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 461fa99f39..f8fde41b77 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1209,7 +1209,7 @@ void smbd_process(void) /* free up temporary memory */ lp_talloc_free(); - parse_talloc_free(); + main_loop_talloc_free(); while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) -- cgit From 8e99021e65f2d358b2ffc89e31bc2499c9b74690 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Feb 2001 21:46:01 +0000 Subject: Fixes from Toomas Soome code unicode problems, plus a solaris quota update fix. Jeremy. (This used to be commit 9efd7a778b7b172d76af922c3dda8ec31d74bd7d) --- source3/smbd/quotas.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 9bbc027cf7..7808d269f9 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -244,6 +244,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #if defined(SUNOS5) #include #include +#include #else /* defined(SUNOS4) */ #include #include @@ -264,6 +265,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U int file; static struct mnttab mnt; static pstring name; + pstring devopt; #else /* SunOS4 */ struct mntent *mnt; static pstring name; @@ -272,7 +274,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U SMB_STRUCT_STAT sbuf; SMB_DEV_T devno ; static SMB_DEV_T devno_cached = 0 ; - int found ; + static int found ; euser_id = geteuid(); @@ -280,7 +282,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return(False) ; devno = sbuf.st_dev ; - DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno)); + DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); if ( devno != devno_cached ) { devno_cached = devno ; #if defined(SUNOS5) @@ -288,12 +290,17 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return(False) ; found = False ; + slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); while (getmntent(fd, &mnt) == 0) { - if ( sys_stat(mnt.mnt_mountp,&sbuf) == -1 ) - continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", - mnt.mnt_mountp,sbuf.st_dev)); - if (sbuf.st_dev == devno) { + if( !hasmntopt(&mnt, devopt) ) + continue; + + DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); + + /* quotas are only on vxfs, UFS or NFS, but nfs is not supported here */ + if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || + strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) + { found = True ; break ; } @@ -322,10 +329,11 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U endmntent(fd) ; #endif - if ( ! found ) - return(False) ; } + if ( ! found ) + return(False) ; + save_re_uid(); set_effective_uid(0); -- cgit From 0f2799aaf1e33aa474a12b9389728d57af926cb3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Feb 2001 00:51:02 +0000 Subject: Move to talloc control of SPOOL_XXX structs. Move to talloc control of security descriptors and pointers. Syncup with 2.2 tree. Jeremy. (This used to be commit 14d5997dc841e78a619e865288486d50c245896d) --- source3/smbd/nttrans.c | 9 --------- source3/smbd/posix_acls.c | 13 ++++++------- 2 files changed, 6 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index cf2bdef314..c326dd561f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1099,7 +1099,6 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_i */ if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - free_sec_desc(&psd); DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n")); /* * Return access denied for want of a better error message.. @@ -1122,14 +1121,12 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_i ret = set_nt_acl( fsp, security_info_sent, psd); if (!ret) { - free_sec_desc(&psd); talloc_destroy(mem_ctx); *pdef_class = ERRDOS; *pdef_code = ERRnoaccess; return False; } - free_sec_desc(&psd); talloc_destroy(mem_ctx); *pdef_class = 0; @@ -1638,8 +1635,6 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if(max_data_count < sd_size) { - free_sec_desc(&psd); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); return -1; @@ -1651,7 +1646,6 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, data = Realloc(*ppdata, sd_size); if(data == NULL) { - free_sec_desc(&psd); return(ERROR(ERRDOS,ERRnomem)); } @@ -1665,7 +1659,6 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if ((mem_ctx = talloc_init()) == NULL) { DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - free_sec_desc(&psd); return(ERROR(ERRDOS,ERRnomem)); } @@ -1683,7 +1676,6 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, */ if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - free_sec_desc(&psd); DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ security descriptor.\n")); /* @@ -1697,7 +1689,6 @@ security descriptor.\n")); * Now we can delete the security descriptor. */ - free_sec_desc(&psd); talloc_destroy(mem_ctx); send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sd_size); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index da457604bb..9c5afad9c1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -41,6 +41,7 @@ typedef struct canon_ace { static void free_canon_ace_list( canon_ace *list_head ); +#if !defined(HAVE_NO_ACLS) /**************************************************************************** Function to duplicate a canon_ace entry. ****************************************************************************/ @@ -56,6 +57,7 @@ static canon_ace *dup_canon_ace( canon_ace *src_ace) dst_ace->prev = dst_ace->next = NULL; return dst_ace; } +#endif /* HAVE_NO_ACLS */ /**************************************************************************** Function to create owner and group SIDs from a SMB_STRUCT_STAT. @@ -243,6 +245,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, return True; } +#if !defined(HAVE_NO_ACLS) /**************************************************************************** Merge aces with a common user. ****************************************************************************/ @@ -378,6 +381,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, return True; } +#endif /* HAVE_NO_ACLS */ /**************************************************************************** Unpack a SEC_DESC into two canonical ace lists. We don't depend on this @@ -577,7 +581,6 @@ static BOOL unpack_canon_ace(files_struct *fsp, */ DEBUG(10,("unpack_canon_ace: Win2k inherit acl traverse. Ignoring DACL.\n")); - free_sec_acl(&psd->dacl); } /* @@ -788,7 +791,6 @@ static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, */ DEBUG(10,("unpack_posix_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); - free_sec_acl(&psd->dacl); } /* @@ -1403,13 +1405,13 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } if (num_acls) { - if((psa = make_sec_acl( ACL_REVISION, num_aces, nt_ace_list)) == NULL) { + if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); goto done; } } - *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sd_size); + *ppdesc = make_standard_sec_desc( main_loop_talloc_get(), &owner_sid, &group_sid, psa, &sd_size); if(!*ppdesc) { DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); @@ -1426,8 +1428,6 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) free_canon_ace_list(dir_ace); if (nt_ace_list) free(nt_ace_list); - if (psa) - free_sec_acl(&psa); return sd_size; } @@ -1700,5 +1700,4 @@ int fchmod_acl(int fd, mode_t mode) sys_acl_free_acl(posix_acl); return ret; } - #undef OLD_NTDOMAIN -- cgit From 0bfc10011bd5cacecda8b59c36e80f676e5c7fa3 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 9 Mar 2001 18:59:16 +0000 Subject: merge of 'lanman auth' and 'min protocol' from 2.2 (This used to be commit 1d84da779a0fe3219d77686a493d2b2fa1f8072a) --- source3/smbd/negprot.c | 3 ++- source3/smbd/reply.c | 33 ++++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 41e95b816d..74d8eb3983 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -411,7 +411,8 @@ int reply_negprot(connection_struct *conn, { p = smb_buf(inbuf)+1; Index = 0; - if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level) + if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) && + (supported_protocols[protocol].protocol_level >= lp_minprotocol())) while (p < (smb_buf(inbuf) + bcc)) { if (strequal(p,supported_protocols[protocol].proto_name)) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 402f9db754..4e87782a48 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -700,6 +700,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int int smb_ntpasslen = 0; pstring smb_ntpasswd; BOOL valid_nt_password = False; + BOOL valid_lm_password = False; pstring user; pstring orig_user; BOOL guest=False; @@ -935,15 +936,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * security=domain. */ - if (!guest && - !check_server_security(orig_user, domain, user, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen) && - !check_domain_security(orig_user, domain, user, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen) && - !check_hosts_equiv(user) - ) + if (!guest && !check_server_security(orig_user, domain, user, + smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) && + !check_domain_security(orig_user, domain, user, smb_apasswd, + smb_apasslen, smb_ntpasswd, smb_ntpasslen) && + !check_hosts_equiv(user)) { /* @@ -959,12 +956,26 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if(smb_ntpasslen) { if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) - DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user)); + DEBUG(2,("NT Password did not match for user '%s'!\n", user)); else valid_nt_password = True; } + + + /* check the LanMan password only if necessary and if allowed + by lp_lanman_auth() */ + if (!valid_nt_password && lp_lanman_auth()) + { + DEBUG(2,("Defaulting to Lanman password for %s\n", user)); + valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL); + } + - if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) + /* The true branch will be executed if + (1) the NT password failed (or was not tried), and + (2) LanMan authentication failed (or was disabled) + */ + if (!valid_nt_password && !valid_lm_password) { if (lp_security() >= SEC_USER) { -- cgit From 00ab9021b0cc5fe2667d383eb9cc2973072cdaaa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Mar 2001 23:48:58 +0000 Subject: Serious (and I *mean* serious) attempt to fix little/bigendian RPC issues. We were reading the endainness in the RPC header and then never propagating it to the internal parse_structs used to parse the data. Also removed the "align" argument to prs_init as it was *always* set to 4, and if needed can be set differently on a case by case basis. Now ready for AS/U testing when Herb gets it set up :-). Jeremy. (This used to be commit 0cd37c831d79a12a10e479bf4fa89ffe64c1292a) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c326dd561f..d9a93f8d78 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1085,7 +1085,7 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_i return False; } - prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL); + prs_init(&pd, 0, mem_ctx, UNMARSHALL); /* * Setup the prs_struct to point at the memory we just @@ -1662,7 +1662,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, return(ERROR(ERRDOS,ERRnomem)); } - prs_init(&pd, 0, 4, mem_ctx, MARSHALL); + prs_init(&pd, 0, mem_ctx, MARSHALL); /* * Setup the prs_struct to point at the memory we just -- cgit From b08b70faf873455ff14dcd633a7c9eb860ba4b28 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2001 11:38:27 +0000 Subject: started support for unicode on the wire in smbd. Using a very similar method to what was used in the client I now have session setup and tconx working. Currently this is enabled with SMBD_USE_UNICODE environment variable. Once the code is complete this will become a smb.conf option. (This used to be commit 7684c1e67294266d018c6f0cab58f1a9d797174f) --- source3/smbd/negprot.c | 6 ++ source3/smbd/reply.c | 69 +++++++++--------- source3/smbd/srvstr.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+), 36 deletions(-) create mode 100644 source3/smbd/srvstr.c (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 74d8eb3983..c2026f46f9 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -201,6 +201,12 @@ static int reply_nt1(char *outbuf) capabilities |= CAP_RAW_MODE; } + + /* until the unicode conversion is complete have it disabled by default */ + if (getenv("SMBD_USE_UNICODE")) { + capabilities |= CAP_UNICODE; + } + #ifdef WITH_MSDFS if(lp_host_msdfs()) capabilities |= CAP_DFS; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4e87782a48..4f98c264b8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -273,12 +273,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt pstring user; pstring password; pstring devicename; - BOOL doencrypt = SMBENCRYPT(); int ecode = -1; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); - char *path; - char *p; + pstring path; + char *p, *q; START_PROFILE(SMBtconX); *service = *user = *password = *devicename = 0; @@ -294,7 +293,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt memcpy(password,smb_buf(inbuf),passlen); password[passlen]=0; - path = smb_buf(inbuf) + passlen; + p = smb_buf(inbuf) + passlen; + p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT); if (passlen != 24) { if (strequal(password," ")) @@ -302,27 +302,20 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt passlen = strlen(password); } - p = strchr(path+2,'\\'); - if (!p) { + q = strchr(path+2,'\\'); + if (!q) { END_PROFILE(SMBtconX); return(ERROR(ERRDOS,ERRnosuchshare)); } - fstrcpy(service,p+1); - p = strchr(service,'%'); - if (p) { - *p++ = 0; - fstrcpy(user,p); + fstrcpy(service,q+1); + q = strchr(service,'%'); + if (q) { + *q++ = 0; + fstrcpy(user,q); } - StrnCpy(devicename,path + strlen(path) + 1,6); - DEBUG(4,("Got device type %s\n",devicename)); + p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_CONVERT); - /* - * Ensure the user and password names are in UNIX codepage format. - */ - - dos_to_unix(user,True); - if (!doencrypt) - dos_to_unix(password,True); + DEBUG(4,("Got device type %s\n",devicename)); /* * Pass the user through the NT -> unix user mapping @@ -349,13 +342,13 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } else { char *fsname = lp_fstype(SNUM(conn)); - set_message(outbuf,3,3,True); + set_message(outbuf,3,0,True); p = smb_buf(outbuf); - pstrcpy(p,devicename); p = skip_string(p,1); /* device name */ - pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ + p += srvstr_push(inbuf, outbuf, p, devicename, -1, STR_CONVERT|STR_TERMINATE); + p += srvstr_push(inbuf, outbuf, p, fsname, -1, STR_CONVERT|STR_TERMINATE); - set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + set_message_end(outbuf,p); /* what does setting this bit do? It is set by NT4 and may affect the ability to autorun mounted cdroms */ @@ -703,10 +696,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int BOOL valid_lm_password = False; pstring user; pstring orig_user; + fstring domain; + fstring native_os; + fstring native_lanman; BOOL guest=False; static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); - char *domain = ""; START_PROFILE(SMBsesssetupX); *smb_apasswd = 0; @@ -835,17 +830,19 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } p += passlen1 + passlen2; - fstrcpy(user,p); - p = skip_string(p,1); + p += srvstr_pull(inbuf, user, p, sizeof(user), -1, STR_CONVERT|STR_TERMINATE); /* * Incoming user and domain are in DOS codepage format. Convert * to UNIX. */ - dos_to_unix(user,True); - domain = p; - dos_to_unix(domain, True); + p += srvstr_pull(inbuf, domain, p, sizeof(domain), + -1, STR_CONVERT|STR_TERMINATE); + p += srvstr_pull(inbuf, native_os, p, sizeof(native_os), + -1, STR_CONVERT|STR_TERMINATE); + p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman), + -1, STR_CONVERT|STR_TERMINATE); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - domain,skip_string(p,1),skip_string(p,2))); + domain,native_os,native_lanman)); } DEBUG(3,("sesssetupX:name=[%s]\n",user)); @@ -1027,12 +1024,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int set_message(outbuf,3,0,True); } else { char *p; - set_message(outbuf,3,3,True); + set_message(outbuf,3,0,True); p = smb_buf(outbuf); - pstrcpy(p,"Unix"); p = skip_string(p,1); - pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1); - pstrcpy(p,global_myworkgroup); unix_to_dos(p, True); p = skip_string(p,1); - set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + p += srvstr_push(inbuf, outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(inbuf, outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(inbuf, outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT); + set_message_end(outbuf,p); /* perhaps grab OS version here?? */ } diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c new file mode 100644 index 0000000000..e420b8fa99 --- /dev/null +++ b/source3/smbd/srvstr.c @@ -0,0 +1,186 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + server specific string routines + Copyright (C) Andrew Tridgell 2001 + + 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. +*/ + +#define NO_SYSLOG + +#include "includes.h" + +#define UNICODE_FLAG() (SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) + +/**************************************************************************** +copy a string from a char* src to a unicode or ascii +dos code page destination choosing unicode or ascii based on the +FLAGS2_UNICODE_STRINGS bit in inbuf +return the number of bytes occupied by the string in the destination +flags can have: + STR_TERMINATE means include the null termination + STR_CONVERT means convert from unix to dos codepage + STR_UPPER means uppercase in the destination + STR_ASCII use ascii even with unicode servers +dest_len is the maximum length allowed in the destination. If dest_len +is -1 then no maxiumum is used +****************************************************************************/ +int srvstr_push(void *inbuf, void *outbuf, void *dest, const char *src, int dest_len, int flags) +{ + int len=0; + + /* treat a pstring as "unlimited" length */ + if (dest_len == -1) { + dest_len = sizeof(pstring); + } + + if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(dest, outbuf))) { + *(char *)dest = 0; + dest++; + dest_len--; + len++; + } + + if ((flags & STR_ASCII) || !UNICODE_FLAG()) { + /* the client doesn't want unicode */ + safe_strcpy(dest, src, dest_len); + len = strlen(dest); + if (flags & STR_TERMINATE) len++; + if (flags & STR_CONVERT) unix_to_dos(dest,True); + if (flags & STR_UPPER) strupper(dest); + return len; + } + + /* the server likes unicode. give it the works */ + if (flags & STR_CONVERT) { + dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE); + } else { + ascii_to_unistr(dest, src, dest_len); + } + if (flags & STR_UPPER) { + strupper_w(dest); + } + len += strlen(src)*2; + if (flags & STR_TERMINATE) len += 2; + return len; +} + + +/**************************************************************************** +return the length that a string would occupy when copied with srvstr_push() + STR_TERMINATE means include the null termination + STR_CONVERT means convert from unix to dos codepage + STR_UPPER means uppercase in the destination +note that dest is only used for alignment purposes. No data is written. +****************************************************************************/ +int srvstr_push_size(void *inbuf, void *outbuf, + const void *dest, const char *src, int dest_len, int flags) +{ + int len = strlen(src); + if (flags & STR_TERMINATE) len++; + if (!(flags & STR_ASCII) && UNICODE_FLAG()) len *= 2; + + if (!(flags & STR_ASCII) && dest && srvstr_align(inbuf, PTR_DIFF(outbuf, dest))) { + len++; + } + + return len; +} + +/**************************************************************************** +copy a string from a unicode or ascii source (depending on flg2) +to a char* destination +flags can have: + STR_CONVERT means convert from dos to unix codepage + STR_TERMINATE means the string in src is null terminated + STR_UNICODE means to force as unicode +if STR_TERMINATE is set then src_len is ignored +src_len is the length of the source area in bytes +return the number of bytes occupied by the string in src +****************************************************************************/ +int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_len, int flags) +{ + int len; + + if (dest_len == -1) { + dest_len = sizeof(pstring); + } + + if (srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { + src++; + if (src_len > 0) src_len--; + } + + if (!(flags & STR_UNICODE) && !UNICODE_FLAG()) { + /* the server doesn't want unicode */ + if (flags & STR_TERMINATE) { + safe_strcpy(dest, src, dest_len); + len = strlen(src)+1; + } else { + if (src_len > dest_len) src_len = dest_len; + len = src_len; + memcpy(dest, src, len); + dest[len] = 0; + } + if (flags & STR_CONVERT) dos_to_unix(dest,True); + return len; + } + + if (flags & STR_TERMINATE) { + unistr_to_ascii(dest, src, dest_len); + len = strlen(dest)*2 + 2; + } else { + int i, c; + if (dest_len*2 < src_len) src_len = 2*dest_len; + for (i=0; i < src_len; i += 2) { + c = SVAL(src, i); + *dest++ = c; + } + *dest++ = 0; + len = src_len; + } + if (flags & STR_CONVERT) dos_to_unix(dest,True); + return len; +} + +/**************************************************************************** +return the length that a string would occupy (not including the null) +when copied with srvstr_pull() +if src_len is -1 then assume the source is null terminated +****************************************************************************/ +int srvstr_pull_size(void *inbuf, const void *src, int src_len) +{ + if (srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { + src++; + if (src_len > 0) src_len--; + } + + if (!UNICODE_FLAG()) { + return strlen(src); + } + return strlen_w(src); +} + +/**************************************************************************** +return an alignment of either 0 or 1 +if unicode is not negotiated then return 0 +otherwise return 1 if offset is off +****************************************************************************/ +int srvstr_align(void *inbuf, int offset) +{ + if (!UNICODE_FLAG()) return 0; + return offset & 1; +} -- cgit From 20d3a2986e793deaa2243ee26bfa33f580a6d2e2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2001 11:57:38 +0000 Subject: converted reply_open, reply_open_and_x and reply_fclose (This used to be commit 2c8da0ae22309f153bde4e29095b60996fa8fcc5) --- source3/smbd/reply.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4f98c264b8..a505160b7d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1507,22 +1507,26 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size { int outsize = 0; int status_len; - char *path; + pstring path; char status[21]; int dptr_num= -2; + char *p; + START_PROFILE(SMBfclose); outsize = set_message(outbuf,1,0,True); - path = smb_buf(inbuf) + 1; - status_len = SVAL(smb_buf(inbuf),3 + strlen(path)); + p = smb_buf(inbuf) + 1; + p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT); + p++; + status_len = SVAL(p,0); + p += 2; - if (status_len == 0) { END_PROFILE(SMBfclose); return(ERROR(ERRSRV,ERRsrverror)); } - memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); + memcpy(status,p,21); if(dptr_fetch(status+12,&dptr_num)) { /* Close the dptr - we know it's gone */ @@ -1560,7 +1564,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); - pstrcpy(fname,smb_buf(inbuf)+1); + srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1654,8 +1658,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } /* XXXX we need to handle passed times, sattr and flags */ - - pstrcpy(fname,smb_buf(inbuf)); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); -- cgit From da3053048c3d224a20d6383ac6682d31059cd46c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 00:32:10 +0000 Subject: Merge of new 2.2 code into HEAD (Gerald I hate you :-) :-). Allows new SAMR RPC code to merge with new passdb code. Currently rpcclient doesn't compile. I'm working on it... Jeremy. (This used to be commit 0be41d5158ea4e645e93e8cd30617c038416e549) --- source3/smbd/blocking.c | 4 ---- source3/smbd/chgpasswd.c | 4 ---- source3/smbd/close.c | 4 ---- source3/smbd/conn.c | 4 ---- source3/smbd/dir.c | 4 ---- source3/smbd/dosmode.c | 4 ---- source3/smbd/error.c | 4 ---- source3/smbd/fileio.c | 2 -- source3/smbd/filename.c | 5 ----- source3/smbd/files.c | 2 -- source3/smbd/ipc.c | 2 -- source3/smbd/lanman.c | 4 ---- source3/smbd/message.c | 4 ---- source3/smbd/negprot.c | 4 ---- source3/smbd/notify.c | 4 ---- source3/smbd/notify_hash.c | 3 --- source3/smbd/notify_kernel.c | 3 --- source3/smbd/nttrans.c | 2 -- source3/smbd/open.c | 4 ---- source3/smbd/oplock.c | 6 ------ source3/smbd/oplock_irix.c | 6 +----- source3/smbd/oplock_linux.c | 5 ----- source3/smbd/password.c | 4 ---- source3/smbd/pipes.c | 3 --- source3/smbd/posix_acls.c | 2 -- source3/smbd/process.c | 3 --- source3/smbd/reply.c | 2 -- source3/smbd/sec_ctx.c | 2 -- source3/smbd/server.c | 9 --------- source3/smbd/service.c | 4 ---- source3/smbd/trans2.c | 4 ---- source3/smbd/uid.c | 4 ---- source3/smbd/vfs-wrap.c | 3 --- source3/smbd/vfs.c | 2 -- 34 files changed, 1 insertion(+), 125 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 16caf8b52e..e8dc29f80a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -633,5 +631,3 @@ void process_blocking_lock_queue(time_t t) blr = (blocking_lock_record *)ubi_slNext(blr); } } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index ba68557fdf..418ad6a675 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -937,5 +935,3 @@ BOOL check_plaintext_password(char *user, char *old_passwd, else return (True); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 87bd313327..56aad64391 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -243,5 +241,3 @@ int close_file(files_struct *fsp, BOOL normal_close) return close_statfile(fsp, normal_close); return close_normal_file(fsp, normal_close); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index cd4ca9ded4..e9f79fdf32 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -200,5 +198,3 @@ void conn_free(connection_struct *conn) ZERO_STRUCTP(conn); free(conn); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index a7e05c5682..5bf0dec944 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -893,5 +891,3 @@ void DirCacheFlush(int snum) entry = (dir_cache_entry *)next; } } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index a4b4f65ad9..8b2c482b0a 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -334,5 +332,3 @@ BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) return(True); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 49da44d68e..d879f9a93c 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -146,5 +144,3 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int return(outsize); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 35e2f1455e..c79f0aa89e 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -584,4 +583,3 @@ void sync_file(connection_struct *conn, files_struct *fsp) conn->vfs_ops.fsync(fsp,fsp->fd); } } -#undef OLD_NTDOMAIN diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index aedd2e820f..bdbcd81b64 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -514,6 +512,3 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d CloseDir(cur_dir); return(False); } - - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 2909d49a2a..a4837a1a8b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -364,4 +363,3 @@ void file_chain_restore(void) { chain_fsp = oplock_save_chain_fsp; } -#undef OLD_NTDOMAIN diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 5ade667209..3b9e34b4d7 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -517,4 +516,3 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int END_PROFILE(SMBtrans); return(outsize); } -#undef OLD_NTDOMAIN diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index c29f0df434..f5e1de1608 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -3330,6 +3329,3 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * return -1; } - - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/message.c b/source3/smbd/message.c index ab3c841d9c..3afe7218e0 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -235,5 +233,3 @@ int reply_sendend(connection_struct *conn, END_PROFILE(SMBsendend); return(outsize); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index c2026f46f9..e15af3f3ae 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -448,5 +446,3 @@ int reply_negprot(connection_struct *conn, END_PROFILE(SMBnegprot); return(outsize); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 912ab43e9e..429723c19e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 3.0 @@ -224,6 +223,3 @@ BOOL init_change_notify(void) return True; } - - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 5a2f865310..a0a61569a8 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 3.0 @@ -195,5 +194,3 @@ struct cnotify_fns *hash_notify_init(void) uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); */ - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index db823601f1..243a16a7f7 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 3.0 @@ -207,5 +206,3 @@ struct cnotify_fns *kernel_notify_init(void) #else void notify_kernel_dummy(void) {} #endif /* HAVE_KERNEL_CHANGE_NOTIFY */ - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d9a93f8d78..1ccac83b78 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -1974,4 +1973,3 @@ due to being in oplock break state.\n" )); calls have already sent it. If outsize != -1 then it is returning an error packet. */ } -#undef OLD_NTDOMAIN diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3665e7d20f..afcaeff1ae 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -1158,5 +1156,3 @@ free_and_exit: free((char *)old_shares); return(ret); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 4f26eaf7f2..e0b494017a 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -978,7 +976,6 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); while(time_left >= 0) { char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; - int32 reply_msg_len; uint16 reply_from_port; char *reply_msg_start; fd_set fds; @@ -1029,7 +1026,6 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); return False; } - reply_msg_len = IVAL(op_break_reply,OPBRK_CMD_LEN_OFFSET); reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET); reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; @@ -1234,5 +1230,3 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); return True; } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index cf1cbbb0fc..faf7e8e3c8 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -1,6 +1,4 @@ -#define OLD_NTDOMAIN 1 - -/* +/* Unix SMB/Netbios implementation. Version 2.x IRIX kernel oplock processing @@ -278,5 +276,3 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void) #else void oplock_irix_dummy(void) {} #endif /* HAVE_KERNEL_OPLOCKS_IRIX */ - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index d97378ac5d..e070761f10 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 3.0 @@ -302,6 +300,3 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) #else void oplock_linux_dummy(void) {} #endif /* HAVE_KERNEL_OPLOCKS_LINUX */ - -#undef OLD_NTDOMAIN - diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 311a019506..849aa87a75 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -1610,5 +1608,3 @@ BOOL domain_client_validate( char *user, char *domain, cli_shutdown(&cli); return True; } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index df7141764c..366707cd58 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -262,5 +261,3 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) return(outsize); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9c5afad9c1..fe2974b235 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -1700,4 +1699,3 @@ int fchmod_acl(int fd, mode_t mode) sys_acl_free_acl(posix_acl); return ret; } -#undef OLD_NTDOMAIN diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f8fde41b77..a34555adc1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -1256,5 +1255,3 @@ void smbd_process(void) } } } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a505160b7d..04e7b4c101 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -4840,4 +4839,3 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, END_PROFILE(SMBgetattrE); return(outsize); } -#undef OLD_NTDOMAIN diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f3cc9e04e0..f604f6cce7 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -459,4 +458,3 @@ void init_sec_ctx(void) current_user.vuid = UID_FIELD_INVALID; current_user.nt_user_token = NULL; } -#undef OLD_NTDOMAIN diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6457dd6295..d2a7ad3be4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -502,12 +501,6 @@ static void init_structs(void ) /* for RPC pipes */ init_rpc_pipe_hnd(); - /* for LSA handles */ - init_lsa_policy_hnd(); - - /* for SPOOLSS handles */ - init_printer_hnd(); - init_dptrs(); secrets_init(); @@ -804,5 +797,3 @@ static void usage(char *pname) exit_server("normal exit"); return(0); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f0ab2ba771..02405e8dda 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -681,5 +679,3 @@ void close_cnum(connection_struct *conn, uint16 vuid) } conn_free(conn); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d94a775846..6cc65d1b21 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -2511,5 +2509,3 @@ int reply_trans2(connection_struct *conn, call_trans2xxx calls have already sent it. If outsize != -1 then it is returning */ } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index db43106b77..3d37021fff 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -521,5 +519,3 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) return True; } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index ad4d4ddbef..8750f71151 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -543,5 +542,3 @@ int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode) { return fchmod_acl(fd, mode); } - -#undef OLD_NTDOMAIN diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2cd83c37f3..b8aa290cab 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 1.9. @@ -895,4 +894,3 @@ BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks) return(True); #endif } -#undef OLD_NTDOMAIN -- cgit From a2e5dbb1120e726ba80b00a159dad1a1ca2e3a18 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 00:51:54 +0000 Subject: Remove "BYTE" - we already have uint8 - don't need more conflicts with system header files... Jeremy. (This used to be commit 31e0ce310ec38b3a3a05b344d6450d442c6be471) --- source3/smbd/chgpasswd.c | 6 +++--- source3/smbd/password.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 418ad6a675..21b7722307 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -547,7 +547,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, uchar unenc_old_pw[16]; SAM_ACCOUNT *sampass = NULL; uint16 acct_ctrl; - BYTE *lanman_pw; + uint8 *lanman_pw; become_root(); sampass = pdb_getsampwnam(user); @@ -614,7 +614,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, uchar unenc_new_pw[16]; BOOL ret; uint16 acct_ctrl; - BYTE *pwd; + uint8 *pwd; if (sampass == NULL) { @@ -710,7 +710,7 @@ BOOL check_oem_password(char *user, static uchar null_pw[16]; static uchar null_ntpw[16]; SAM_ACCOUNT *sampass = NULL; - BYTE *lanman_pw, *nt_pw; + uint8 *lanman_pw, *nt_pw; uint16 acct_ctrl; int new_pw_len; uchar new_ntp16[16]; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 849aa87a75..9731b4140c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -428,7 +428,7 @@ BOOL smb_password_ok(SAM_ACCOUNT *sampass, uchar chal[8], { uchar challenge[8]; char* user_name; - BYTE *nt_pw, *lm_pw; + uint8 *nt_pw, *lm_pw; if (!lm_pass || !sampass) return(False); -- cgit From b840dce67639b8d270eaac27b29d7392981f55bd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 22:26:28 +0000 Subject: Moved cruft out of smb.h into ntdomain.h where it belongs. dc struct now in pipe struct (where used) rather than user_struct. Secured machine account password changing in srv_netlog_nt.c - ensure that only the given machine can change its own password. May need to free this up later for NT admin tools, but this is a fail-safe secure position for now. Jeremy. (This used to be commit 46b12f2275dcd4b3114085160cd456441f9e921e) --- source3/smbd/password.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9731b4140c..12f7385f06 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -313,8 +313,6 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, } } - memset(&vuser->dc, '\0', sizeof(vuser->dc)); - return vuser->vuid; } -- cgit From d3ec09326b27dd00b1f67a7ce48bc9817a313735 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Mar 2001 00:31:07 +0000 Subject: Added ADMIN$ share as alias for IPC$ except no guest connect. AS/U wants to do RPC calls down this treeid. Jeremy. (This used to be commit 83133bab0ed59e303a183fd91812165f08e88484) --- source3/smbd/service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 02405e8dda..2c03d4e514 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -234,7 +234,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int snum = find_service(service); if (snum < 0) { - if (strequal(service,"IPC$")) { + if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { DEBUG(3,("refusing IPC connection\n")); *ecode = ERRnoipc; return NULL; @@ -284,7 +284,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int } /* you can only connect to the IPC$ service as an ipc device */ - if (strequal(service,"IPC$")) + if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) pstrcpy(dev,"IPC"); if (*dev == '?' || !*dev) { @@ -386,7 +386,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); - conn->ipc = (strncmp(dev,"IPC",3) == 0); + conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$")); conn->dirptr = NULL; conn->veto_list = NULL; conn->hide_list = NULL; -- cgit From 23e5cf060d282c9ba9bdf49884ce23a13b285aac Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 00:55:19 +0000 Subject: this patch does a number of things: - removes SMB_ALIGNMENT. That macro caused all sorts of problems with getting unicode aligned right in sub-protocols (such as SMBtrans and SMBtrans2). I believe the performance reasons for having SMB_ALIGNMENT has gone away with the new variants of the SMB protocol anyway, as newer commands tend to have their own internal alignment. - fix the locations where we set smb_flg2 to absolute values. We must never do this if we want a hope of coping with unicode. - add initial support for unicode on the wire in smbd. Currently enabled using SMBD_USE_UNICODE environment variable. (This used to be commit b98b1435e9d8f8622444c9ff33082977e661f16b) --- source3/smbd/ipc.c | 4 +- source3/smbd/nttrans.c | 17 +++--- source3/smbd/process.c | 6 +- source3/smbd/reply.c | 40 ++++++------- source3/smbd/trans2.c | 153 ++++++++++++++++++++++++++++++------------------- 5 files changed, 127 insertions(+), 93 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3b9e34b4d7..3cc9aca99e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -102,7 +102,7 @@ void send_trans_reply(char *outbuf, if (buffer_too_large) { /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ - SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SIVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); SIVAL(outbuf, smb_rcls, 0x80000000 | STATUS_BUFFER_OVERFLOW); } @@ -376,7 +376,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int START_PROFILE(SMBtrans); memset(name, '\0',sizeof(name)); - fstrcpy(name,smb_buf(inbuf)); + srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE|STR_CONVERT); if (dscnt > tdscnt || pscnt > tpscnt) { exit_server("invalid trans parameters\n"); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1ccac83b78..5eadd2bc8e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -243,7 +243,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!! ****************************************************************************/ -static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) +static void get_filename(char *fname, char *inbuf, int data_offset, int data_len, int fname_len) { /* * We need various heuristics here to detect a unicode string... JRA. @@ -613,7 +613,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, ((uint32)sizeof(fname)-1)); get_filename(fname, inbuf, smb_buf(inbuf)-inbuf, - smb_buflen(inbuf),fname_len); + smb_buflen(inbuf),fname_len); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -725,7 +725,7 @@ int reply_ntcreate_and_X(connection_struct *conn, smb_buflen(inbuf),fname_len); if( strchr(fname, ':')) { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } @@ -866,7 +866,8 @@ int reply_ntcreate_and_X(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(file_attributes); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, + SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); return(ERROR(0, NT_STATUS_FILE_IS_A_DIRECTORY)); } @@ -1239,7 +1240,7 @@ static int call_nt_transact_create(connection_struct *conn, total_parameter_count - 53 - fname_len, fname_len); if( strchr(fname, ':')) { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } @@ -1346,7 +1347,8 @@ static int call_nt_transact_create(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(file_attributes); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, + SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_FILE_IS_A_DIRECTORY)); } @@ -1894,8 +1896,7 @@ due to being in oplock break state.\n" )); } if (Protocol >= PROTOCOL_NT1) { - uint16 flg2 = SVAL(outbuf,smb_flg2); - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ } /* Now we must call the relevant NT_TRANS function */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a34555adc1..dea7130cfe 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -897,7 +897,8 @@ void construct_reply_common(char *inbuf,char *outbuf) CVAL(outbuf,smb_reh) = 0; SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set means a reply */ - SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS); + SSVAL(outbuf,smb_flg2, + (SVAL(inbuf,smb_flg2)&FLAGS2_UNICODE_STRINGS) | FLAGS2_LONG_PATH_COMPONENTS); /* say we support long filenames */ SSVAL(outbuf,smb_err,SMB_SUCCESS); @@ -1188,9 +1189,6 @@ void smbd_process(void) if ((InBuffer == NULL) || (OutBuffer == NULL)) return; - InBuffer += SMB_ALIGNMENT; - OutBuffer += SMB_ALIGNMENT; - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); /* re-initialise the timezone */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 04e7b4c101..1240d16a98 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -336,16 +336,21 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,2,strlen(devicename)+1,True); - pstrcpy(smb_buf(outbuf),devicename); + set_message(outbuf,2,0,True); + p = smb_buf(outbuf); + p += srvstr_push(inbuf, outbuf, p, devicename, -1, + STR_CONVERT|STR_TERMINATE|STR_ASCII); + set_message_end(outbuf,p); } else { char *fsname = lp_fstype(SNUM(conn)); set_message(outbuf,3,0,True); p = smb_buf(outbuf); - p += srvstr_push(inbuf, outbuf, p, devicename, -1, STR_CONVERT|STR_TERMINATE); - p += srvstr_push(inbuf, outbuf, p, fsname, -1, STR_CONVERT|STR_TERMINATE); + p += srvstr_push(inbuf, outbuf, p, devicename, -1, + STR_CONVERT|STR_TERMINATE|STR_ASCII); + p += srvstr_push(inbuf, outbuf, p, fsname, -1, + STR_CONVERT|STR_TERMINATE); set_message_end(outbuf,p); @@ -444,50 +449,50 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out sam_trust_acct = pdb_getsampwnam(user); } else { DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } if (sam_trust_acct == NULL) { /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_NO_SUCH_USER)); } else { if ((smb_passlen != 24) || (smb_nt_passlen != 24)) { DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct); if (acct_ctrl & ACB_DOMTRUST) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); } if (acct_ctrl & ACB_SVRTRUST) { DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); } if (acct_ctrl & ACB_WSTRUST) { DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); } } /* don't know what to do: indicate logon failure */ - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } @@ -670,7 +675,7 @@ static int bad_password_error(char *inbuf,char *outbuf) if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) && (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { - SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0,NT_STATUS_LOGON_FAILURE)); } @@ -1203,11 +1208,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SIVAL(outbuf,smb_vwv3,(uint32)size); if (Protocol >= PROTOCOL_NT1) { - char *p = strrchr(fname,'/'); - uint16 flg2 = SVAL(outbuf,smb_flg2); - if (!p) p = fname; - if (!is_8_3(fname, True)) - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */ } DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); @@ -1480,8 +1481,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); if (Protocol >= PROTOCOL_NT1) { - uint16 flg2 = SVAL(outbuf,smb_flg2); - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */ } outsize += DIR_STRUCT_SIZE*numentries; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6cc65d1b21..76bb7fd4cc 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -305,6 +305,7 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) get a level dependent lanman2 dir entry. ****************************************************************************/ static BOOL get_lanman2_dir_entry(connection_struct *conn, + void *inbuf, void *outbuf, char *path_mask,int dirtype,int info_level, int requires_resume_key, BOOL dont_descend,char **ppdata, @@ -318,7 +319,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstring mask; pstring pathreal; pstring fname; - char *p, *pdata = *ppdata; + char *p, *q, *pdata = *ppdata; uint32 reskey=0; int prev_dirpos=0; int mode=0; @@ -460,10 +461,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,l1_cbFile,(uint32)size); SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024)); SSVAL(p,l1_attrFile,mode); - SCVAL(p,l1_cchName,strlen(fname)); - pstrcpy(p + l1_achName, fname); - nameptr = p + l1_achName; - p += l1_achName + strlen(fname) + 1; + p += l1_achName; + nameptr = p; + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SCVAL(p, -1, len); + p += len; break; case 2: @@ -479,10 +482,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024)); SSVAL(p,l2_attrFile,mode); SIVAL(p,l2_cbList,0); /* No extended attributes */ - SCVAL(p,l2_cchName,strlen(fname)); - pstrcpy(p + l2_achName, fname); - nameptr = p + l2_achName; - p += l2_achName + strlen(fname) + 1; + p += l2_achName; + nameptr = p; + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SCVAL(p, -1, len); + p += len; break; case 3: @@ -494,10 +499,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,20,SMB_ROUNDUP(size,1024)); SSVAL(p,24,mode); SIVAL(p,26,4); - CVAL(p,30) = strlen(fname); - pstrcpy(p+31, fname); - nameptr = p+31; - p += 31 + strlen(fname) + 1; + p += 31; + nameptr = p; + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SCVAL(p, -1, len); + p += len; break; case 4: @@ -505,24 +512,26 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - SIVAL(p,0,33+strlen(fname)+1); + q = p; put_dos_date2(p,4,cdate); put_dos_date2(p,8,adate); put_dos_date2(p,12,mdate); SIVAL(p,16,(uint32)size); SIVAL(p,20,SMB_ROUNDUP(size,1024)); SSVAL(p,24,mode); - CVAL(p,32) = strlen(fname); - pstrcpy(p + 33, fname); - nameptr = p+33; - p += 33 + strlen(fname) + 1; + p += 33; + nameptr = p; + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SCVAL(p, -1, len); + p += len; + SIVAL(q,4,PTR_DIFF(p, q)); + break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: was_8_3 = is_8_3(fname, True); - len = 94+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; + p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; put_long_date(p,adate); p += 8; @@ -532,28 +541,33 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,8,size); p += 16; SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; + q = p; p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { - fstrcpy(p+2,fname); - if(!name_map_mangle(p+2,True,True,SNUM(conn))) - (p+2)[12] = 0; - strupper(p+2); - SSVAL(p, 0, strlen(p+2)); + pstring mangled_name; + pstrcpy(mangled_name, fname); + name_map_mangle(mangled_name,True,True,SNUM(conn)); + mangled_name[12] = 0; + len = srvstr_push(inbuf, outbuf, p+2, mangled_name, 24, + STR_CONVERT|STR_UPPER); + SSVAL(p, 0, len); } else { SSVAL(p,0,0); *(p+2) = 0; } p += 2 + 24; - /* nameptr = p; */ - pstrcpy(p,fname); p += strlen(p); + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SIVAL(q,0,len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); p = pdata + len; break; case SMB_FIND_FILE_DIRECTORY_INFO: - len = 64+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; + p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; put_long_date(p,adate); p += 8; @@ -563,16 +577,20 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,8,size); p += 16; SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; - pstrcpy(p,fname); + p += 4; + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SIVAL(p, -4, len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); p = pdata + len; break; case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - len = 68+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; + p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; put_long_date(p,adate); p += 8; @@ -582,19 +600,31 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,8,size); p += 16; SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; + p += 4; SIVAL(p,0,0); p += 4; - pstrcpy(p,fname); + + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SIVAL(p, -4, len); + p += len; + + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); p = pdata + len; break; case SMB_FIND_FILE_NAMES_INFO: - len = 12+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; + p += 4; SIVAL(p,0,reskey); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; - pstrcpy(p,fname); + p += 4; + len = srvstr_push(inbuf, outbuf, p, fname, -1, + STR_TERMINATE|STR_CONVERT); + SIVAL(p, -4, len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); p = pdata + len; break; @@ -677,12 +707,14 @@ static int call_trans2findfirst(connection_struct *conn, return(ERROR(ERRDOS,ERRunknownlevel)); } - pstrcpy(directory, params + 12); /* Complete directory path with - wildcard mask appended */ + srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE); - RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); + DEBUG(0,("path=%s params=%p inbuf=%p params[0]=%c params[1]=%d params[2]=%c params[3]=%d\n", + directory, + params, inbuf, + params[12], params[13], params[14], params[15])); - DEBUG(5,("path=%s\n",directory)); + RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); if(!check_name(directory,conn)) { @@ -772,10 +804,12 @@ static int call_trans2findfirst(connection_struct *conn, } else { - finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level, - requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_name_off); + finished = !get_lanman2_dir_entry(conn, + inbuf, outbuf, + mask,dirtype,info_level, + requires_resume_key,dont_descend, + &p,pdata,space_remaining, &out_of_space, &got_exact_match, + &last_name_off); } if (finished && out_of_space) @@ -1046,10 +1080,12 @@ resume_key = %d resume name = %s continue=%d level = %d\n", } else { - finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level, - requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_name_off); + finished = !get_lanman2_dir_entry(conn, + inbuf, outbuf, + mask,dirtype,info_level, + requires_resume_key,dont_descend, + &p,pdata,space_remaining, &out_of_space, &got_exact_match, + &last_name_off); } if (finished && out_of_space) @@ -1208,7 +1244,7 @@ static int call_trans2qfsinfo(connection_struct *conn, vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False); data_len = 18 + vnamelen; SIVAL(pdata,12,vnamelen); - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); } DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", @@ -2391,8 +2427,7 @@ int reply_trans2(connection_struct *conn, } if (Protocol >= PROTOCOL_NT1) { - uint16 flg2 = SVAL(outbuf,smb_flg2); - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ } /* Now we must call the relevant TRANS2 function */ -- cgit From f869164a16db914f5b101cd82f54bf50b3076402 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 01:51:44 +0000 Subject: converted findnext to unicode (This used to be commit 84fc5a7795fe6e3b993649ecc05f6685f8295c02) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 76bb7fd4cc..a16dcc3e19 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -920,7 +920,7 @@ static int call_trans2findnext(connection_struct *conn, *mask = *directory = *resume_name = 0; - pstrcpy( resume_name, params+12); + srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE|STR_CONVERT); DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \ close_after_request=%d, close_if_end = %d requires_resume_key = %d \ -- cgit From 93143c96a6c7d882d83ea2724e4c1985fc1dbc2d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 03:45:09 +0000 Subject: - convert chkpath - devicename in tconx is always ascii (This used to be commit 242a6a96d10beeb54e93226ae50bd361486e1c0d) --- source3/smbd/reply.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1240d16a98..0cff1d5a56 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -312,7 +312,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt *q++ = 0; fstrcpy(user,q); } - p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_CONVERT); + p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_CONVERT|STR_ASCII); DEBUG(4,("Got device type %s\n",devicename)); @@ -342,7 +342,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt STR_CONVERT|STR_TERMINATE|STR_ASCII); set_message_end(outbuf,p); } else { - char *fsname = lp_fstype(SNUM(conn)); + /* NT sets the fstype of IPC$ to the null string */ + char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); set_message(outbuf,3,0,True); @@ -1087,8 +1088,8 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; SMB_STRUCT_STAT sbuf; START_PROFILE(SMBchkpth); - - pstrcpy(name,smb_buf(inbuf) + 1); + + srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); -- cgit From 26f63881e242947e7d4a5f5c3ce6f13305d2601e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 03:45:29 +0000 Subject: added STR_ASCII flag to srvstr_pull() (This used to be commit e54d37903013df1c799ab3aaa10f10df24e3de61) --- source3/smbd/srvstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index e420b8fa99..b944ed2578 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -119,12 +119,12 @@ int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_ dest_len = sizeof(pstring); } - if (srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { + if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { src++; if (src_len > 0) src_len--; } - if (!(flags & STR_UNICODE) && !UNICODE_FLAG()) { + if ((flags & STR_ASCII) || (!(flags & STR_UNICODE) && !UNICODE_FLAG())) { /* the server doesn't want unicode */ if (flags & STR_TERMINATE) { safe_strcpy(dest, src, dest_len); -- cgit From a7d2f5b06379cb0c553cd2d9a7c58e2cb8902965 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 06:37:12 +0000 Subject: converted a bunch more server functions to unicode (This used to be commit a074600a09387c2034ffb6651abad69bdc14145e) --- source3/smbd/reply.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0cff1d5a56..a401be1357 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1150,9 +1150,11 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_OFF_T size=0; time_t mtime=0; BOOL bad_path = False; + char *p; START_PROFILE(SMBgetatr); - - pstrcpy(fname,smb_buf(inbuf) + 1); + + p = smb_buf(inbuf) + 1; + p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1231,9 +1233,12 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size time_t mtime; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; + char *p; + START_PROFILE(SMBsetatr); - - pstrcpy(fname,smb_buf(inbuf) + 1); + + p = smb_buf(inbuf) + 1; + p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE); unix_convert(fname,conn,0,&bad_path,&sbuf); mode = SVAL(inbuf,smb_vwv0); @@ -1781,7 +1786,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); createmode = SVAL(inbuf,smb_vwv0); - pstrcpy(fname,smb_buf(inbuf)+1); + srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -2046,7 +2051,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dirtype = SVAL(inbuf,smb_vwv0); - pstrcpy(name,smb_buf(inbuf) + 1); + srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); @@ -3888,10 +3893,14 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in int outsize = 0; pstring name; pstring newname; + char *p; + START_PROFILE(SMBmv); - pstrcpy(name,smb_buf(inbuf) + 1); - pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); + p = smb_buf(inbuf) + 1; + p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE); + p++; + p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); @@ -4019,8 +4028,9 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, *directory = *mask = 0; - pstrcpy(name,smb_buf(inbuf)); - pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); + p = smb_buf(inbuf); + p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE); + p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE); DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); -- cgit From 20dd1f74893e9ea0a2a4ef21ec5e1b02eb9e504d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 06:55:47 +0000 Subject: converted reply_tcon() (This used to be commit 1e92d340ceb5be8e7d50cc7c889b2053ed67bad3) --- source3/smbd/reply.c | 62 +++++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a401be1357..230b3db750 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -167,41 +167,6 @@ static int connection_error(char *inbuf,char *outbuf,int ecode) } - -/**************************************************************************** - parse a share descriptor string -****************************************************************************/ -static void parse_connect(char *p,char *service,char *user, - char *password,int *pwlen,char *dev) -{ - char *p2; - - DEBUG(4,("parsing connect string %s\n",p)); - - p2 = strrchr(p,'\\'); - if (p2 == NULL) - fstrcpy(service,p); - else - fstrcpy(service,p2+1); - - p += strlen(p) + 2; - - fstrcpy(password,p); - *pwlen = strlen(password); - - p += strlen(p) + 2; - - fstrcpy(dev,p); - - *user = 0; - p = strchr(service,'%'); - if (p != NULL) - { - *p = 0; - fstrcpy(user,p+1); - } -} - /**************************************************************************** Reply to a tcon. ****************************************************************************/ @@ -218,17 +183,34 @@ int reply_tcon(connection_struct *conn, uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; int ecode = -1; + char *p; + START_PROFILE(SMBtcon); *service = *user = *password = *dev = 0; - parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); + p = smb_buf(inbuf)+1; + p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE|STR_CONVERT) + 1; + p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE|STR_CONVERT) + 1; + p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE|STR_CONVERT) + 1; - /* - * Ensure the user and password names are in UNIX codepage format. - */ + *user = 0; + p = strchr(service,'%'); + if (p != NULL) { + *p = 0; + fstrcpy(user,p+1); + } - dos_to_unix(user,True); + p = strrchr(service,'\\'); + if (p) { + pstrcpy(service, p+1); + } + + /* + * Ensure the user and password names are in UNIX codepage format. + */ + + dos_to_unix(user,True); if (!doencrypt) dos_to_unix(password,True); -- cgit From ff0462cde830a306105b9d585a36239f27e38f23 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 22:00:46 +0000 Subject: simpler and more correct srvstr_push() it now uses outbuf not inbuf for the unicode flag, which allows for some server fns to be ascii and means one less parameter in push calls (This used to be commit a6dd6662267eeddf368ff0ffba76b45761bf4eeb) --- source3/smbd/reply.c | 12 ++++++------ source3/smbd/srvstr.c | 20 ++++++++++---------- source3/smbd/trans2.c | 18 +++++++++--------- 3 files changed, 25 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 230b3db750..96192f0575 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -320,7 +320,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (Protocol < PROTOCOL_NT1) { set_message(outbuf,2,0,True); p = smb_buf(outbuf); - p += srvstr_push(inbuf, outbuf, p, devicename, -1, + p += srvstr_push(outbuf, p, devicename, -1, STR_CONVERT|STR_TERMINATE|STR_ASCII); set_message_end(outbuf,p); } else { @@ -330,9 +330,9 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,3,0,True); p = smb_buf(outbuf); - p += srvstr_push(inbuf, outbuf, p, devicename, -1, + p += srvstr_push(outbuf, p, devicename, -1, STR_CONVERT|STR_TERMINATE|STR_ASCII); - p += srvstr_push(inbuf, outbuf, p, fsname, -1, + p += srvstr_push(outbuf, p, fsname, -1, STR_CONVERT|STR_TERMINATE); set_message_end(outbuf,p); @@ -1013,9 +1013,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int char *p; set_message(outbuf,3,0,True); p = smb_buf(outbuf); - p += srvstr_push(inbuf, outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT); - p += srvstr_push(inbuf, outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT); - p += srvstr_push(inbuf, outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT); set_message_end(outbuf,p); /* perhaps grab OS version here?? */ } diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index b944ed2578..c3eef46440 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -23,7 +23,7 @@ #include "includes.h" -#define UNICODE_FLAG() (SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) +#define UNICODE_FLAG(buf) (SVAL(buf, smb_flg2) & FLAGS2_UNICODE_STRINGS) /**************************************************************************** copy a string from a char* src to a unicode or ascii @@ -38,7 +38,7 @@ flags can have: dest_len is the maximum length allowed in the destination. If dest_len is -1 then no maxiumum is used ****************************************************************************/ -int srvstr_push(void *inbuf, void *outbuf, void *dest, const char *src, int dest_len, int flags) +int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int flags) { int len=0; @@ -47,14 +47,14 @@ int srvstr_push(void *inbuf, void *outbuf, void *dest, const char *src, int dest dest_len = sizeof(pstring); } - if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(dest, outbuf))) { + if (!(flags & STR_ASCII) && srvstr_align(outbuf, PTR_DIFF(dest, outbuf))) { *(char *)dest = 0; dest++; dest_len--; len++; } - if ((flags & STR_ASCII) || !UNICODE_FLAG()) { + if ((flags & STR_ASCII) || !UNICODE_FLAG(outbuf)) { /* the client doesn't want unicode */ safe_strcpy(dest, src, dest_len); len = strlen(dest); @@ -86,14 +86,14 @@ return the length that a string would occupy when copied with srvstr_push() STR_UPPER means uppercase in the destination note that dest is only used for alignment purposes. No data is written. ****************************************************************************/ -int srvstr_push_size(void *inbuf, void *outbuf, +int srvstr_push_size(void *outbuf, const void *dest, const char *src, int dest_len, int flags) { int len = strlen(src); if (flags & STR_TERMINATE) len++; - if (!(flags & STR_ASCII) && UNICODE_FLAG()) len *= 2; + if (!(flags & STR_ASCII) && UNICODE_FLAG(outbuf)) len *= 2; - if (!(flags & STR_ASCII) && dest && srvstr_align(inbuf, PTR_DIFF(outbuf, dest))) { + if (!(flags & STR_ASCII) && dest && srvstr_align(outbuf, PTR_DIFF(outbuf, dest))) { len++; } @@ -124,7 +124,7 @@ int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_ if (src_len > 0) src_len--; } - if ((flags & STR_ASCII) || (!(flags & STR_UNICODE) && !UNICODE_FLAG())) { + if ((flags & STR_ASCII) || (!(flags & STR_UNICODE) && !UNICODE_FLAG(inbuf))) { /* the server doesn't want unicode */ if (flags & STR_TERMINATE) { safe_strcpy(dest, src, dest_len); @@ -168,7 +168,7 @@ int srvstr_pull_size(void *inbuf, const void *src, int src_len) if (src_len > 0) src_len--; } - if (!UNICODE_FLAG()) { + if (!UNICODE_FLAG(inbuf)) { return strlen(src); } return strlen_w(src); @@ -181,6 +181,6 @@ otherwise return 1 if offset is off ****************************************************************************/ int srvstr_align(void *inbuf, int offset) { - if (!UNICODE_FLAG()) return 0; + if (!UNICODE_FLAG(inbuf)) return 0; return offset & 1; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a16dcc3e19..714d42ce2a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -463,7 +463,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,l1_attrFile,mode); p += l1_achName; nameptr = p; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SCVAL(p, -1, len); p += len; @@ -484,7 +484,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,l2_cbList,0); /* No extended attributes */ p += l2_achName; nameptr = p; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SCVAL(p, -1, len); p += len; @@ -501,7 +501,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,26,4); p += 31; nameptr = p; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SCVAL(p, -1, len); p += len; @@ -521,7 +521,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,24,mode); p += 33; nameptr = p; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SCVAL(p, -1, len); p += len; @@ -548,7 +548,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(mangled_name, fname); name_map_mangle(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; - len = srvstr_push(inbuf, outbuf, p+2, mangled_name, 24, + len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_CONVERT|STR_UPPER); SSVAL(p, 0, len); } else { @@ -556,7 +556,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, *(p+2) = 0; } p += 2 + 24; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SIVAL(q,0,len); p += len; @@ -578,7 +578,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 16; SIVAL(p,0,nt_extmode); p += 4; p += 4; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SIVAL(p, -4, len); p += len; @@ -603,7 +603,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; SIVAL(p,0,0); p += 4; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SIVAL(p, -4, len); p += len; @@ -618,7 +618,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; SIVAL(p,0,reskey); p += 4; p += 4; - len = srvstr_push(inbuf, outbuf, p, fname, -1, + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE|STR_CONVERT); SIVAL(p, -4, len); p += len; -- cgit From 88028299c6f059399383f69125eff3b797236c40 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Mar 2001 23:16:39 +0000 Subject: Fix from Jim McDonough of IBM for using Win9x user manager. Jeremy. (This used to be commit f1839d469e1fc6054b407bd8c4d7c505d4212b45) --- source3/smbd/ipc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3cc9aca99e..1418d3444f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -36,6 +36,7 @@ extern fstring local_machine; #define NERR_notsupported 50 extern int smb_read_error; +extern uint32 global_client_caps; /******************************************************************* copies parameters and data, as needed, into the smb buffer @@ -102,8 +103,14 @@ void send_trans_reply(char *outbuf, if (buffer_too_large) { /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ - SIVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - SIVAL(outbuf, smb_rcls, 0x80000000 | STATUS_BUFFER_OVERFLOW); + if (!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { + /* Win9x version. */ + SSVAL(outbuf, smb_err, ERRmoredata); + SCVAL(outbuf, smb_rcls, ERRDOS); + } else { + SIVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + SIVAL(outbuf, smb_rcls, 0x80000000 | STATUS_BUFFER_OVERFLOW); + } } copy_trans_params_and_data(outbuf, align, -- cgit From 18b7efe9b302d8cb83ca2ae2e4a8d6329de5d39e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 23:17:45 +0000 Subject: converted a bunch more fns to unicode (This used to be commit fbb3bf12df5c79cac9445be21f1997234479b472) --- source3/smbd/reply.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 96192f0575..56a528b816 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -703,12 +703,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); smb_apasswd[smb_apasslen] = 0; - pstrcpy(user,smb_buf(inbuf)+smb_apasslen); - /* - * Incoming user is in DOS codepage format. Convert - * to UNIX. - */ - dos_to_unix(user,True); + srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE|STR_CONVERT); if (!doencrypt && (lp_security() != SEC_SERVER)) { smb_apasslen = strlen(smb_apasswd); @@ -1839,10 +1834,12 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); SMB_STRUCT_STAT sbuf; + char *p; + START_PROFILE(SMBctemp); createmode = SVAL(inbuf,smb_vwv0); - pstrcpy(fname,smb_buf(inbuf)+1); + srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); pstrcat(fname,"/TMXXXXXX"); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1872,10 +1869,12 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - outsize = set_message(outbuf,1,2 + strlen(fname2),True); + outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); CVAL(smb_buf(outbuf),0) = 4; - pstrcpy(smb_buf(outbuf) + 1,fname2); + p = smb_buf(outbuf) + 1; + p += srvstr_push(inbuf, outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT); + set_message_end(outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; @@ -3363,7 +3362,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int outsize; START_PROFILE(SMBmkdir); - pstrcpy(directory,smb_buf(inbuf) + 1); + srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); outsize=mkdir_internal(conn, inbuf, outbuf, directory); if(outsize == 0) @@ -3538,7 +3537,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SMB_STRUCT_STAT sbuf; START_PROFILE(SMBrmdir); - pstrcpy(directory,smb_buf(inbuf) + 1); + srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) @@ -4163,9 +4162,8 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(pathworks_setdir); return(ERROR(ERRDOS,ERRnoaccess)); } - - pstrcpy(newdir,smb_buf(inbuf) + 1); - strlower(newdir); + + srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE|STR_CONVERT); if (strlen(newdir) == 0) { ok = True; -- cgit From be8a6ea511b131aa065ffc51cf69811a4c3a76a6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2001 23:25:48 +0000 Subject: fixed srvstr_push() call (This used to be commit dca433d035dfb6e94ee659477c71edaa4549644d) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 56a528b816..55e6fb5255 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1873,7 +1873,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(outbuf,smb_vwv0,fsp->fnum); CVAL(smb_buf(outbuf),0) = 4; p = smb_buf(outbuf) + 1; - p += srvstr_push(inbuf, outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT); set_message_end(outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { -- cgit From df03c7480d32b60f45d5407dbabd82237570b54c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Mar 2001 07:29:53 +0000 Subject: converted a bunch more trans2 calls for unicode. This got quite tricky :( (This used to be commit ddee55087756db2a2ac0ee92471d9fea53f38bee) --- source3/smbd/trans2.c | 324 ++++++++++++++++++++++---------------------------- 1 file changed, 145 insertions(+), 179 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 714d42ce2a..22a7378ed9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -199,8 +199,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int16 open_ofun = SVAL(params,12); int32 open_size = IVAL(params,14); char *pname = ¶ms[28]; - int16 namelen = strlen(pname)+1; - pstring fname; mode_t unixmode; SMB_OFF_T size=0; @@ -211,7 +209,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, BOOL bad_path = False; files_struct *fsp; - StrnCpy(fname,pname,namelen); + srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE); DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", fname,open_mode, open_attr, open_ofun, open_size)); @@ -709,11 +707,6 @@ static int call_trans2findfirst(connection_struct *conn, srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE); - DEBUG(0,("path=%s params=%p inbuf=%p params[0]=%c params[1]=%d params[2]=%c params[3]=%d\n", - directory, - params, inbuf, - params[12], params[13], params[14], params[15])); - RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); @@ -1146,7 +1139,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *pdata = *ppdata; char *params = *pparams; uint16 info_level = SVAL(params,0); - int data_len; + int data_len, len; SMB_STRUCT_STAT st; char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); @@ -1184,72 +1177,49 @@ static int call_trans2qfsinfo(connection_struct *conn, break; } case 2: - { - /* Return volume name */ - int volname_len = MIN(strlen(vname),11); - data_len = l2_vol_szVolLabel + volname_len + 1; - /* - * Add volume serial number - hash of a combination of - * the called hostname and the service name. - */ - SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - SCVAL(pdata,l2_vol_cch,volname_len); - StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); - DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", - (unsigned)st.st_ctime, volname_len, - pdata+l2_vol_szVolLabel)); - break; - } + /* Return volume name */ + /* + * Add volume serial number - hash of a combination of + * the called hostname and the service name. + */ + SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, + STR_TERMINATE|STR_CONVERT); + SCVAL(pdata,l2_vol_cch,len); + data_len = l2_vol_szVolLabel + len; + DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", + (unsigned)st.st_ctime, len, vname)); + break; + case SMB_QUERY_FS_ATTRIBUTE_INFO: - { - int fstype_len; - SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - FILE_DEVICE_IS_MOUNTED| - (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ -#if 0 /* Old code. JRA. */ - SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ -#endif /* Old code. */ - - SIVAL(pdata,4,128); /* Max filename component length */ - fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring), False); - SIVAL(pdata,8,fstype_len); - data_len = 12 + fstype_len; - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); - break; - } + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| + FILE_DEVICE_IS_MOUNTED| + (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ + SIVAL(pdata,4,128); /* Max filename component length */ + len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE|STR_CONVERT); + SIVAL(pdata,8,len); + data_len = 12 + len; + break; + case SMB_QUERY_FS_LABEL_INFO: - data_len = 4 + strlen(vname); - SIVAL(pdata,0,strlen(vname)); - pstrcpy(pdata+4,vname); - break; + len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE|STR_CONVERT); + data_len = 4 + len; + SIVAL(pdata,0,len); + break; case SMB_QUERY_FS_VOLUME_INFO: - - /* - * Add volume serial number - hash of a combination of - * the called hostname and the service name. - */ - SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ - (str_checksum(local_machine)<<16)); - - /* NT4 always serves this up as unicode but expects it to be - * delivered as ascii! (tridge && JRA) - */ - if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) { - data_len = 18 + strlen(vname); - SIVAL(pdata,12,strlen(vname)); - pstrcpy(pdata+18,vname); - } else { - int vnamelen; - - vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False); - data_len = 18 + vnamelen; - SIVAL(pdata,12,vnamelen); - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); - } - - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", - (int)strlen(vname),vname)); - break; + /* + * Add volume serial number - hash of a combination of + * the called hostname and the service name. + */ + SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ + (str_checksum(local_machine)<<16)); + + len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE|STR_CONVERT); + SIVAL(pdata,12,len); + data_len = 18+len; + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", + (int)strlen(vname),vname)); + break; case SMB_QUERY_FS_SIZE_INFO: { SMB_BIG_UINT dfree,dsize,bsize; @@ -1277,8 +1247,8 @@ static int call_trans2qfsinfo(connection_struct *conn, break; } /* drop through */ - default: - return(ERROR(ERRDOS,ERRunknownlevel)); + default: + return(ERROR(ERRDOS,ERRunknownlevel)); } @@ -1331,80 +1301,79 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SMB_OFF_T size=0; unsigned int data_size; SMB_STRUCT_STAT sbuf; - pstring fname1; - char *fname; + pstring fname; + char *base_name; char *p; - int l; SMB_OFF_T pos = 0; BOOL bad_path = False; BOOL delete_pending = False; + int len; if (tran_call == TRANSACT2_QFILEINFO) { - files_struct *fsp = file_fsp(params,0); - info_level = SVAL(params,2); - - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); - - if(fsp && (fsp->is_directory || fsp->stat_open)) { - /* - * This is actually a QFILEINFO on a directory - * handle (returned from an NT SMB). NT5.0 seems - * to do this call. JRA. - */ - fname = fsp->fsp_name; - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } - - delete_pending = fsp->directory_delete_on_close; - - } else { - /* - * Original code - this is an open file. - */ - CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); - - fname = fsp->fsp_name; - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadfid)); - } - if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - delete_pending = fsp->delete_on_close; - } + files_struct *fsp = file_fsp(params,0); + info_level = SVAL(params,2); + + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", + info_level)); + + if(fsp && (fsp->is_directory || fsp->stat_open)) { + /* + * This is actually a QFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + pstrcpy(fname, fsp->fsp_name); + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + + delete_pending = fsp->directory_delete_on_close; + } else { + /* + * Original code - this is an open file. + */ + CHECK_FSP(fsp,conn); + CHECK_ERROR(fsp); + + pstrcpy(fname, fsp->fsp_name); + if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n", + fsp->fnum, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + delete_pending = fsp->delete_on_close; + } } else { - /* qpathinfo */ - info_level = SVAL(params,0); + /* qpathinfo */ + info_level = SVAL(params,0); - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", + info_level)); - fname = &fname1[0]; - pstrcpy(fname,¶ms[6]); + srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } } @@ -1412,21 +1381,19 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname,info_level,tran_call,total_data)); p = strrchr(fname,'/'); - if (!p) - p = fname; - else - p++; - l = strlen(p); + if (!p) { + base_name = fname; + } else { + base_name = p+1; + } + mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; if (mode & aDIR) size = 0; - /* from now on we only want the part after the / */ - fname = p; - params = Realloc(*pparams,2); - if ( params == NULL ) { - return(ERROR(ERRDOS,ERRnomem)); + if (params == NULL) { + return(ERROR(ERRDOS,ERRnomem)); } *pparams = params; memset((char *)params,'\0',2); @@ -1435,7 +1402,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if ( pdata == NULL ) { return(ERROR(ERRDOS,ERRnomem)); } - *ppdata = pdata; + *ppdata = pdata; if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ @@ -1514,43 +1481,42 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_ALT_NAME_INFO: { pstring short_name; - pstrcpy(short_name,p); + + pstrcpy(short_name,base_name); /* Mangle if not already 8.3 */ if(!is_8_3(short_name, True)) { if(!name_map_mangle(short_name,True,True,SNUM(conn))) *short_name = '\0'; } - strupper(short_name); - l = dos_PutUniCode(pdata + 4, short_name, sizeof(pstring), False); - data_size = 4 + l; - SIVAL(pdata,0,l); + len = srvstr_push(outbuf, pdata+4, short_name, -1, + STR_TERMINATE|STR_CONVERT|STR_UPPER); + data_size = 4 + len; + SIVAL(pdata,0,len); } break; case SMB_QUERY_FILE_NAME_INFO: - /* - * The first part of this code is essential - * to get security descriptors to work on mapped - * drives. Don't ask how I discovered this unless - * you like hearing about me suffering.... :-). JRA. - */ - if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) { - l = l*2; - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS); - dos_PutUniCode(pdata + 4, "\\",sizeof(pstring), False); - } else { - pstrcpy(pdata+4,fname); - } - data_size = 4 + l; - SIVAL(pdata,0,l); - break; + /* + * The first part of this code is essential + * to get security descriptors to work on mapped + * drives. Don't ask how I discovered this unless + * you like hearing about me suffering.... :-). JRA. + */ + if(strequal(".", fname)) { + len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE|STR_CONVERT); + } else { + len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE|STR_CONVERT); + } + data_size = 4 + len; + SIVAL(pdata,0,len); + break; case SMB_QUERY_FILE_ALLOCATION_INFO: case SMB_QUERY_FILE_END_OF_FILEINFO: - data_size = 8; - SOFF_T(pdata,0,size); - break; + data_size = 8; + SOFF_T(pdata,0,size); + break; case SMB_QUERY_FILE_ALL_INFO: put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); @@ -1578,9 +1544,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ pdata += 4; pdata += 4; /* alignment */ - SIVAL(pdata,0,l); - pstrcpy(pdata+4,fname); - pdata += 4 + l; + len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE|STR_CONVERT); + SIVAL(pdata,0,len); + pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); break; @@ -1588,12 +1554,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* NT4 server just returns "invalid query" to this - if we try to answer it then NTws gets a BSOD! (tridge) */ case SMB_QUERY_FILE_STREAM_INFO: - data_size = 24 + l; SIVAL(pdata,0,pos); SIVAL(pdata,4,size); SIVAL(pdata,12,size); - SIVAL(pdata,20,l); - pstrcpy(pdata+24,fname); + len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE|STR_CONVERT); + SIVAL(pdata,20,len); + data_size = 24 + len; break; #endif @@ -1601,7 +1567,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return(ERROR(ERRDOS,ERRunknownlevel)); } - send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size); return(-1); } -- cgit From 376a44c81d360026eb0c2886e9a05dd2bfefd2cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Mar 2001 11:55:08 +0000 Subject: converted the smb messaging code to unicode (This used to be commit 54bde1b3aec829ba55b8a6c946424fdaf38803a9) --- source3/smbd/message.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 3afe7218e0..21750f9cd4 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -31,9 +31,9 @@ extern int DEBUGLEVEL; static char msgbuf[1600]; -static int msgpos=0; -static fstring msgfrom=""; -static fstring msgto=""; +static int msgpos; +static fstring msgfrom; +static fstring msgto; /**************************************************************************** deliver the message @@ -107,8 +107,10 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int len; - char *orig,*dest,*msg; + char *msg; int outsize = 0; + char *p; + START_PROFILE(SMBsends); msgpos = 0; @@ -120,12 +122,11 @@ int reply_sends(connection_struct *conn, outsize = set_message(outbuf,0,0,True); - orig = smb_buf(inbuf)+1; - dest = skip_string(orig,1)+1; - msg = skip_string(dest,1)+1; + p = smb_buf(inbuf)+1; + p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE|STR_CONVERT) + 1; + p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE|STR_CONVERT) + 1; - fstrcpy(msgfrom,orig); - fstrcpy(msgto,dest); + msg = p; len = SVAL(msg,0); len = MIN(len,sizeof(msgbuf)-msgpos); @@ -135,8 +136,6 @@ int reply_sends(connection_struct *conn, memcpy(&msgbuf[msgpos],msg+2,len); msgpos += len; - DEBUG( 3, ( "SMBsends (from %s to %s)\n", orig, dest ) ); - msg_deliver(); END_PROFILE(SMBsends); @@ -150,8 +149,9 @@ int reply_sends(connection_struct *conn, int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - char *orig,*dest; int outsize = 0; + char *p; + START_PROFILE(SMBsendstrt); if (! (*lp_msg_command())) { @@ -164,11 +164,9 @@ int reply_sendstrt(connection_struct *conn, memset(msgbuf,'\0',sizeof(msgbuf)); msgpos = 0; - orig = smb_buf(inbuf)+1; - dest = skip_string(orig,1)+1; - - fstrcpy(msgfrom,orig); - fstrcpy(msgto,dest); + p = smb_buf(inbuf)+1; + p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE|STR_CONVERT) + 1; + p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE|STR_CONVERT) + 1; DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); -- cgit From fbab616c149a9549f30c7f9f0550386c815b69e8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Mar 2001 12:45:46 +0000 Subject: don't need srvstr_push_size or srvstr_pull_size (This used to be commit d5b39a1d435f7fe79eb556f7e6b55276ac68a73d) --- source3/smbd/srvstr.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index c3eef46440..241a74f02f 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -78,28 +78,6 @@ int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int fla return len; } - -/**************************************************************************** -return the length that a string would occupy when copied with srvstr_push() - STR_TERMINATE means include the null termination - STR_CONVERT means convert from unix to dos codepage - STR_UPPER means uppercase in the destination -note that dest is only used for alignment purposes. No data is written. -****************************************************************************/ -int srvstr_push_size(void *outbuf, - const void *dest, const char *src, int dest_len, int flags) -{ - int len = strlen(src); - if (flags & STR_TERMINATE) len++; - if (!(flags & STR_ASCII) && UNICODE_FLAG(outbuf)) len *= 2; - - if (!(flags & STR_ASCII) && dest && srvstr_align(outbuf, PTR_DIFF(outbuf, dest))) { - len++; - } - - return len; -} - /**************************************************************************** copy a string from a unicode or ascii source (depending on flg2) to a char* destination @@ -156,24 +134,6 @@ int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_ return len; } -/**************************************************************************** -return the length that a string would occupy (not including the null) -when copied with srvstr_pull() -if src_len is -1 then assume the source is null terminated -****************************************************************************/ -int srvstr_pull_size(void *inbuf, const void *src, int src_len) -{ - if (srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { - src++; - if (src_len > 0) src_len--; - } - - if (!UNICODE_FLAG(inbuf)) { - return strlen(src); - } - return strlen_w(src); -} - /**************************************************************************** return an alignment of either 0 or 1 if unicode is not negotiated then return 0 -- cgit From ae728ea761e82d6d0bd5c96e7c82f1b1115f2e24 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Mar 2001 03:19:01 +0000 Subject: Last tweak (I promise :-). Fallback to returning our SID if we're a domain member but can't get the domain sid. Jeremy. (This used to be commit 45e96777d0eeafbbf40759f02cd3f5e15b12c288) --- source3/smbd/posix_acls.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index fe2974b235..5c0878b9ca 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -961,9 +961,18 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu other_ace->perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH); } - DLIST_ADD(list_head, other_ace); - DLIST_ADD(list_head, group_ace); - DLIST_ADD(list_head, owner_ace); + if (other_ace->perms) { + DLIST_ADD(list_head, other_ace); + } else + safe_free(other_ace); + if (group_ace->perms) { + DLIST_ADD(list_head, group_ace); + } else + safe_free(group_ace); + if (owner_ace->perms) { + DLIST_ADD(list_head, owner_ace); + } else + safe_free(owner_ace); return list_head; -- cgit From a8d396f25ed483371e5085ae14000b194af1e70b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Mar 2001 04:34:53 +0000 Subject: Tidyup return of zero-permissions (map to ACE_DENIED, GENERIC_ALL, Everyone). Jeremy. (This used to be commit 0d6c7dedd261c15697a7781678fe6bed877b61f6) --- source3/smbd/posix_acls.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 5c0878b9ca..b9d6c7e32f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -130,7 +130,8 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon nt_mask = UNIX_ACCESS_NONE; } else { /* Not owner, no access. */ - nt_mask = 0; + *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED; + nt_mask = GENERIC_ALL_ACCESS; } } else { nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); @@ -941,13 +942,13 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu group_ace->type = SMB_ACL_GROUP_OBJ; group_ace->sid = *pgroup; - owner_ace->unix_ug.gid = psbuf->st_gid; - owner_ace->owner_type = GID_ACE; + group_ace->unix_ug.gid = psbuf->st_gid; + group_ace->owner_type = GID_ACE; other_ace->type = SMB_ACL_OTHER; other_ace->sid = global_sid_World; - owner_ace->unix_ug.world = -1; - owner_ace->owner_type = WORLD_ACE; + other_ace->unix_ug.world = -1; + other_ace->owner_type = WORLD_ACE; if (!fsp->is_directory) { owner_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); @@ -974,6 +975,23 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu } else safe_free(owner_ace); + if (list_head == NULL) { + /* + * Return an "Everyone" NO ACCESS ace. + */ + + if ((other_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) + goto fail; + + other_ace->type = SMB_ACL_OTHER; + other_ace->sid = global_sid_World; + other_ace->unix_ug.world = -1; + other_ace->owner_type = WORLD_ACE; + other_ace->perms = (mode_t)0; + + DLIST_ADD(list_head, other_ace); + } + return list_head; fail: @@ -1304,7 +1322,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { SMB_STRUCT_STAT sbuf; - SEC_ACE *nt_ace_list; + SEC_ACE *nt_ace_list = NULL; DOM_SID owner_sid; DOM_SID group_sid; size_t sd_size = 0; @@ -1379,13 +1397,15 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) num_dir_acls = count_canon_ace_list(dir_ace); } - /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); - goto done; - } + if ((num_acls + num_dir_acls) != 0) { + /* Allocate the ace list. */ + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); + goto done; + } - memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + } /* * Create the NT ACE list from the canonical ace lists. -- cgit From c9b8da47a68c98d72d59d25d1e2d8f3069300f40 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Mar 2001 02:31:24 +0000 Subject: enable unicode on the wire by default in smbd the unicode support isn't complete, but it is good enough to be usable for a test server. (This used to be commit e787fc1daf4a46c182e87bf0697eec80ff0ce87a) --- source3/smbd/negprot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e15af3f3ae..ffc5d5e398 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -200,8 +200,8 @@ static int reply_nt1(char *outbuf) } - /* until the unicode conversion is complete have it disabled by default */ - if (getenv("SMBD_USE_UNICODE")) { + /* allow for disabling unicode */ + if (lp_unicode()) { capabilities |= CAP_UNICODE; } -- cgit From 7906e8168cf717f19ba69435ddf353ce7db110db Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Mar 2001 03:25:33 +0000 Subject: converted reply_search (This used to be commit 0331f93a8117d4c295cda327c3a290296ff621d0) --- source3/smbd/reply.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 55e6fb5255..b559b9bdc5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1295,7 +1295,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size char *p; BOOL ok = False; int status_len; - char *path; + pstring path; char status[21]; int dptr_num= -1; BOOL check_descend = False; @@ -1313,9 +1313,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(outbuf,1,3,True); maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); - path = smb_buf(inbuf) + 1; - status_len = SVAL(smb_buf(inbuf),3 + strlen(path)); - + p = smb_buf(inbuf) + 1; + p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); + p++; + status_len = SVAL(p, 0); + p += 2; /* dirtype &= ~aDIR; */ @@ -1324,8 +1326,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT sbuf; pstring dir2; - pstrcpy(directory,smb_buf(inbuf)+1); - pstrcpy(dir2,smb_buf(inbuf)+1); + pstrcpy(directory,path); + pstrcpy(dir2,path); unix_convert(directory,conn,0,&bad_path,&sbuf); unix_format(dir2); @@ -1357,7 +1359,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { - memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); + memcpy(status,p,21); dirtype = CVAL(status,0) & 0x1F; conn->dirptr = dptr_fetch(status+12,&dptr_num); if (!conn->dirptr) -- cgit From f572cd9e35830c509968b29cb5f606bb9f9b929b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Mar 2001 03:43:14 +0000 Subject: converted reply_printqueue (This used to be commit 70d6b09ac9fbd612960fa02fad5adbf6d87c24ce) --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b559b9bdc5..35a4b0f54a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -408,8 +408,8 @@ int reply_ioctl(connection_struct *conn, { case IOCTL_QUERY_JOB_INFO: SSVAL(p,0,fsp->print_jobid); /* Job number */ - StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */ - StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */ + srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_CONVERT|STR_ASCII); + srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_CONVERT|STR_ASCII); break; } @@ -3270,7 +3270,7 @@ int reply_printqueue(connection_struct *conn, SSVAL(p,5, queue[i].job); SIVAL(p,7,queue[i].size); CVAL(p,11) = 0; - StrnCpy(p+12,queue[i].user,16); + srvstr_push(outbuf, p+12, queue[i].user, 16, STR_CONVERT|STR_ASCII); p += 28; } -- cgit From 4ea1740dce8c455cf00861f309043c3fb9767d0f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Mar 2001 03:53:59 +0000 Subject: converted the nttrans code to unicode on the wire (This used to be commit ecc2c35ca011a635729063cbc58e7fe687cf148a) --- source3/smbd/nttrans.c | 130 +++++-------------------------------------------- 1 file changed, 13 insertions(+), 117 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5eadd2bc8e..5d28f8bc3e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -238,73 +238,6 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err return 0; } -/**************************************************************************** - (Hopefully) temporary call to fix bugs in NT5.0beta2. This OS sends unicode - strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!! -****************************************************************************/ - -static void get_filename(char *fname, char *inbuf, int data_offset, int data_len, int fname_len) -{ - /* - * We need various heuristics here to detect a unicode string... JRA. - */ - - DEBUG(10,("get_filename: data_offset = %d, data_len = %d, fname_len = %d\n", - data_offset, data_len, fname_len )); - - if(data_len - fname_len > 1) { - /* - * NT 5.0 Beta 2 has kindly sent us a UNICODE string - * without bothering to set the unicode bit. How kind. - * - * Firstly - ensure that the data offset is aligned - * on a 2 byte boundary - add one if not. - */ - fname_len = fname_len/2; - if(data_offset & 1) - data_offset++; - pstrcpy(fname, dos_unistrn2((uint16 *)(inbuf+data_offset), fname_len)); - } else { - StrnCpy(fname,inbuf+data_offset,fname_len); - fname[fname_len] = '\0'; - } -} - -/**************************************************************************** - Fix bugs in Win2000 final release. In trans calls this OS sends unicode - strings AND DOESN'T SET THE UNICODE BIT !!!!!!! -****************************************************************************/ - -static void get_filename_transact( char *fname, char *inbuf, int data_offset, int data_len, int fname_len) -{ - /* - * We need various heuristics here to detect a unicode string... JRA. - */ - - DEBUG(10,("get_filename_transact: data_offset = %d, data_len = %d, fname_len = %d\n", - data_offset, data_len, fname_len )); - - /* - * Win2K sends a unicode filename plus one extra alingment byte. - * WinNT4.x send an ascii string with multiple garbage bytes on - * the end here. - */ - - if((data_len == 1) || (inbuf[data_offset] == '\0')) { - /* - * Ensure that the data offset is aligned - * on a 2 byte boundary - add one if not. - */ - fname_len = fname_len/2; - if(data_offset & 1) - data_offset++; - pstrcpy(fname, dos_unistrn2((uint16 *)(inbuf+data_offset), fname_len)); - } else { - StrnCpy(fname,inbuf+data_offset,fname_len); - fname[fname_len] = '\0'; - } -} - /**************************************************************************** Save case statics. ****************************************************************************/ @@ -609,11 +542,9 @@ static int do_ntcreate_pipe_open(connection_struct *conn, int ret; int pnum = -1; char *p = NULL; - uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), - ((uint32)sizeof(fname)-1)); - get_filename(fname, inbuf, smb_buf(inbuf)-inbuf, - smb_buflen(inbuf),fname_len); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); + if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -657,8 +588,6 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); - uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)), - ((uint32)sizeof(fname)-1)); uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); int smb_ofun; int smb_open_mode; @@ -721,8 +650,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - get_filename(&fname[0], inbuf, smb_buf(inbuf)-inbuf, - smb_buflen(inbuf),fname_len); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); if( strchr(fname, ':')) { SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); @@ -749,23 +677,11 @@ int reply_ntcreate_and_X(connection_struct *conn, dir_name_len++; } - /* - * This next calculation can refuse a correct filename if we're dealing - * with the Win2k unicode bug, but that would be rare. JRA. - */ - - if(fname_len + dir_name_len >= sizeof(pstring)) { - END_PROFILE(SMBntcreateX); - return(ERROR(ERRSRV,ERRfilespecs)); - } - - get_filename(&fname[dir_name_len], inbuf, smb_buf(inbuf)-inbuf, - smb_buflen(inbuf),fname_len); - + srvstr_pull(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, + -1, STR_TERMINATE|STR_CONVERT); } else { - - get_filename(fname, inbuf, smb_buf(inbuf)-inbuf, - smb_buflen(inbuf),fname_len); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), + -1, STR_TERMINATE|STR_CONVERT); } /* @@ -999,7 +915,6 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char **ppdata) { pstring fname; - uint32 fname_len; int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); char *params = *ppparams; int ret; @@ -1015,10 +930,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, return(ERROR(ERRDOS,ERRbadaccess)); } - fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1)); - - get_filename_transact(&fname[0], params, 53, - total_parameter_count - 53 - fname_len, fname_len); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -1165,7 +1077,6 @@ static int call_nt_transact_create(connection_struct *conn, uint32 share_access; uint32 create_disposition; uint32 create_options; - uint32 fname_len; uint32 sd_len; uint16 root_dir_fid; int smb_ofun; @@ -1204,7 +1115,6 @@ static int call_nt_transact_create(connection_struct *conn, create_disposition = IVAL(params,28); create_options = IVAL(params,32); sd_len = IVAL(params,36); - fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1)); root_dir_fid = (uint16)IVAL(params,4); smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); @@ -1236,8 +1146,7 @@ static int call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - get_filename_transact(&fname[0], params, 53, - total_parameter_count - 53 - fname_len, fname_len); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); if( strchr(fname, ':')) { SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); @@ -1263,20 +1172,10 @@ static int call_nt_transact_create(connection_struct *conn, dir_name_len++; } - /* - * This next calculation can refuse a correct filename if we're dealing - * with the Win2k unicode bug, but that would be rare. JRA. - */ - - if(fname_len + dir_name_len >= sizeof(pstring)) - return(ERROR(ERRSRV,ERRfilespecs)); - - get_filename_transact(&fname[dir_name_len], params, 53, - total_parameter_count - 53 - fname_len, fname_len); - + srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, + -1, STR_TERMINATE|STR_CONVERT); } else { - get_filename_transact(&fname[0], params, 53, - total_parameter_count - 53 - fname_len, fname_len); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); } /* @@ -1558,13 +1457,10 @@ static int call_nt_transact_rename(connection_struct *conn, pstring new_name; files_struct *fsp = file_fsp(params, 0); BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; - uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)), - ((uint32)sizeof(new_name)-1)); int outsize = 0; CHECK_FSP(fsp, conn); - StrnCpy(new_name,params+4,fname_len); - new_name[fname_len] = '\0'; + srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE|STR_CONVERT); outsize = rename_internals(conn, inbuf, outbuf, fsp->fsp_name, new_name, replace_if_exists); -- cgit From 977e0be9b3b01b9deecea905b78d81d3c58726a1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Mar 2001 04:09:47 +0000 Subject: finished the conversion to unicode of the last of the trans2 fns (This used to be commit 1d145a37860f7256a081c893e3640f5e18943518) --- source3/smbd/trans2.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 22a7378ed9..2f2c225183 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1588,8 +1588,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, SMB_OFF_T size=0; struct utimbuf tvs; SMB_STRUCT_STAT sbuf; - pstring fname1; - char *fname; + pstring fname; int fd = -1; BOOL bad_path = False; files_struct *fsp = NULL; @@ -1604,7 +1603,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * handle (returned from an NT SMB). NT5.0 seems * to do this call. JRA. */ - fname = fsp->fsp_name; + pstrcpy(fname, fsp->fsp_name); unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); @@ -1636,7 +1635,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, CHECK_FSP(fsp,conn); CHECK_ERROR(fsp); - fname = fsp->fsp_name; + pstrcpy(fname, fsp->fsp_name); fd = fsp->fd; if (vfs_fstat(fsp,fd,&sbuf) != 0) { @@ -1647,8 +1646,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } else { /* set path info */ info_level = SVAL(params,0); - fname = fname1; - pstrcpy(fname,¶ms[6]); + srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); unix_convert(fname,conn,0,&bad_path,&sbuf); if(!check_name(fname, conn)) { @@ -2060,7 +2058,7 @@ static int call_trans2mkdir(connection_struct *conn, if (!CAN_WRITE(conn)) return(ERROR(ERRSRV,ERRaccess)); - pstrcpy(directory, ¶ms[4]); + srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE); DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); @@ -2174,8 +2172,6 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char** pparams, char** ppdata) { char *params = *pparams; - enum remote_arch_types ra_type = get_remote_arch(); - BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)); pstring pathname; int reply_size = 0; int max_referral_level = SVAL(params,0); @@ -2186,15 +2182,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, if(!lp_host_msdfs()) return(ERROR(ERRDOS,ERRbadfunc)); - /* if pathname is in UNICODE, convert to DOS */ - /* NT always sends in UNICODE, may not set UNICODE flag */ - if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS)) - { - unistr_to_dos(pathname, ¶ms[2], sizeof(pathname)); - DEBUG(10,("UNICODE referral for %s\n",pathname)); - } - else - pstrcpy(pathname,¶ms[2]); + srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE|STR_CONVERT); if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) return(ERROR(ERRDOS,ERRbadfile)); -- cgit From 096550d86cfa7e73bd819417c5721c88c35999c5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Mar 2001 06:17:45 +0000 Subject: don't need to force unicode strings in flg2 anymore (This used to be commit 899ca6e832c72ea68b0ac76205d18a80c87b34d9) --- source3/smbd/trans2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2f2c225183..0489e23040 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1217,8 +1217,8 @@ static int call_trans2qfsinfo(connection_struct *conn, len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE|STR_CONVERT); SIVAL(pdata,12,len); data_len = 18+len; - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", - (int)strlen(vname),vname)); + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", + (int)strlen(vname),vname, lp_servicename(snum))); break; case SMB_QUERY_FS_SIZE_INFO: { @@ -2187,8 +2187,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) return(ERROR(ERRDOS,ERRbadfile)); - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | - FLAGS2_DFS_PATHNAMES); + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); return(-1); -- cgit From 70c812e6aee0fa9b10b660f4051cc5460c023917 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 Mar 2001 02:06:16 +0000 Subject: I'm happy with the mapping for NT getACL, now for NT setACL. Jeremy. (This used to be commit 7b97ac289ed472e03b2a6e9c51a568478a93562d) --- source3/smbd/posix_acls.c | 242 +++++++++++++++++++++++++++++++++------------- 1 file changed, 175 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b9d6c7e32f..f73f122f43 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -22,6 +22,7 @@ #include "includes.h" enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE}; +enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */ typedef union posix_id { uid_t uid; @@ -35,6 +36,7 @@ typedef struct canon_ace { mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */ DOM_SID sid; enum ace_owner owner_type; + enum ace_attribute attr; posix_id unix_ug; } canon_ace; @@ -76,7 +78,7 @@ static void print_canon_ace(canon_ace *ace, int num) { fstring str; - dbgtext( "canon_ace index %d.", num ); + dbgtext( "canon_ace index %d. Type = %s", num, ace->attr == ALLOW_ACE ? "allow" : "deny" ); dbgtext( "SID = %s ", sid_to_string( str, &ace->sid)); if (ace->owner_type == UID_ACE) { struct passwd *pass = sys_getpwuid(ace->unix_ug.uid); @@ -111,6 +113,8 @@ static void print_canon_ace(canon_ace *ace, int num) /**************************************************************************** Map canon_ace perms to permission bits NT. + The attr element is not used here - we only process deny entries on set, + not get. Deny entries are implicit on get with ace->perms = 0. ****************************************************************************/ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon_ace *ace) @@ -258,7 +262,8 @@ static BOOL merge_aces( canon_ace *list_head, canon_ace *p_ace) if (curr_ace == p_ace) continue; - if (curr_ace->type == p_ace->type && sid_equal(&curr_ace->sid, &p_ace->sid)) { + if ((curr_ace->type == p_ace->type) && (curr_ace->attr == p_ace->attr) && + sid_equal(&curr_ace->sid, &p_ace->sid)) { if( DEBUGLVL( 10 )) { dbgtext("Merging ACE's\n"); print_canon_ace( p_ace, 0); @@ -343,6 +348,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->unix_ug.uid = pst->st_uid; pace->sid = *pfile_owner_sid; pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRUSR): 0; + pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); } @@ -359,6 +365,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->unix_ug.uid = pst->st_gid; pace->sid = *pfile_grp_sid; pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRGRP): 0; + pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); } @@ -375,6 +382,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->unix_ug.world = -1; pace->sid = global_sid_World; pace->perms = default_acl ? get_default_ace_mode(fsp, S_IROTH): 0; + pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); } @@ -496,10 +504,13 @@ static BOOL unpack_canon_ace(files_struct *fsp, * S_I(R|W|X)USR bits. */ - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) { current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); - else + current_ace->attr = ALLOW_ACE; + } else { current_ace->perms = 0; + current_ace->attr = DENY_ACE; + } /* * Now note what kind of a POSIX ACL this should map to. @@ -531,8 +542,15 @@ static BOOL unpack_canon_ace(files_struct *fsp, */ if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) == (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) { + DLIST_ADD(dir_ace, current_ace); + + if( DEBUGLVL( 10 )) { + dbgtext("unpack_canon_ace: adding dir ACL:\n"); + print_canon_ace( current_ace, 0); + } + /* * If this is not an inherit only ACE we need to add a duplicate * to the file acl. @@ -905,18 +923,112 @@ static void free_canon_ace_list( canon_ace *list_head ) } } +/****************************************************************************** + When returning permissions, try and fit NT display + semantics if possible. Note the the canon_entries here must have been malloced. + The list format should be - first entry = owner, followed by group and other user + entries, last entry = other. +********************************************************************************/ + +static void arrange_posix_perms( char *filename, canon_ace *list_head) +{ + extern DOM_SID global_sid_World; + canon_ace *owner_ace = NULL; + canon_ace *other_ace = NULL; + canon_ace *ace = NULL; + mode_t owner_perms = 0; + mode_t group_perms = 0; + mode_t other_perms = 0; + + for (ace = list_head; ace; ace = ace->next) { + if (ace->type == SMB_ACL_USER_OBJ) + owner_ace = ace; + else if (ace->type == SMB_ACL_OTHER) { + /* Last ace - this is "other" */ + other_ace = ace; + } else { + /* Get the union of all the group and supplementary user perms. */ + group_perms |= ace->perms; + } + } + + if (!owner_ace || !other_ace) { + DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n", + filename )); + return; + } + + /* + * The POSIX algorithm applies to owner first, and other last, + * so ensure they are arranged in this order. + */ + + if (owner_ace) { + DLIST_PROMOTE(list_head, owner_ace); + } + + if (other_ace) { + DLIST_DEMOTE(list_head, other_ace, ace); + } + + owner_perms = owner_ace->perms; + other_perms = other_ace->perms; + + /* + * We have to be clever here. NT4.x won't display anything other + * Than an "Everyone, No access" DENY acl. Truncate blank perms + * from the end, but we can't truncate blank permissions from + * anywhere except the end, as they have an effect on allowing access + * under POSIX. + */ + + if ((owner_perms || group_perms) && !other_perms) { + DLIST_REMOVE(list_head, other_ace); + safe_free(other_ace); + } + + if (owner_perms && !group_perms && !other_perms) { + /* Free everything except the list head. */ + free_canon_ace_list(owner_ace->next); + owner_ace->next = NULL; + } + + if (!owner_perms && !group_perms && !other_perms) { + /* + * Special case - no one has any access. + * Return a 1 element ACL - other has "no access". + */ + + if (owner_ace->next) { + free_canon_ace_list(owner_ace->next); + owner_ace->next = NULL; + } + + owner_ace->type = SMB_ACL_OTHER; + owner_ace->sid = global_sid_World; + owner_ace->unix_ug.world = -1; + owner_ace->owner_type = WORLD_ACE; + owner_ace->attr = DENY_ACE; + owner_ace->perms = 0; + } +} + /****************************************************************************** Fall back to the generic 3 element UNIX permissions. ********************************************************************************/ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup) + DOM_SID *powner, DOM_SID *pgroup, BOOL default_acl) { extern DOM_SID global_sid_World; canon_ace *list_head = NULL; canon_ace *owner_ace = NULL; canon_ace *group_ace = NULL; canon_ace *other_ace = NULL; + mode_t mode; + + if (default_acl) + return NULL; /* * Create 3 linked list entries. @@ -939,58 +1051,36 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu owner_ace->sid = *powner; owner_ace->unix_ug.uid = psbuf->st_uid; owner_ace->owner_type = UID_ACE; + owner_ace->attr = ALLOW_ACE; group_ace->type = SMB_ACL_GROUP_OBJ; group_ace->sid = *pgroup; group_ace->unix_ug.gid = psbuf->st_gid; group_ace->owner_type = GID_ACE; + group_ace->attr = ALLOW_ACE; other_ace->type = SMB_ACL_OTHER; other_ace->sid = global_sid_World; other_ace->unix_ug.world = -1; other_ace->owner_type = WORLD_ACE; + other_ace->attr = ALLOW_ACE; - if (!fsp->is_directory) { - owner_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); - group_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); - other_ace->perms = unix_perms_to_acl_perms(psbuf->st_mode, S_IROTH, S_IWOTH, S_IXOTH); - } else { - mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - - owner_ace->perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR); - group_ace->perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); - other_ace->perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH); - } + mode = psbuf->st_mode; - if (other_ace->perms) { - DLIST_ADD(list_head, other_ace); - } else - safe_free(other_ace); - if (group_ace->perms) { - DLIST_ADD(list_head, group_ace); - } else - safe_free(group_ace); - if (owner_ace->perms) { - DLIST_ADD(list_head, owner_ace); - } else - safe_free(owner_ace); + owner_ace->perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR); + owner_ace->attr = owner_ace->perms ? ALLOW_ACE : DENY_ACE; + + group_ace->perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); + group_ace->attr = group_ace->perms ? ALLOW_ACE : DENY_ACE; - if (list_head == NULL) { - /* - * Return an "Everyone" NO ACCESS ace. - */ + other_ace->perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH); + other_ace->attr = other_ace->perms ? ALLOW_ACE : DENY_ACE; - if ((other_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) - goto fail; + DLIST_ADD(list_head, other_ace); + DLIST_ADD(list_head, group_ace); + DLIST_ADD(list_head, owner_ace); - other_ace->type = SMB_ACL_OTHER; - other_ace->sid = global_sid_World; - other_ace->unix_ug.world = -1; - other_ace->owner_type = WORLD_ACE; - other_ace->perms = (mode_t)0; - - DLIST_ADD(list_head, other_ace); - } + arrange_posix_perms(fsp->fsp_name,list_head ); return list_head; @@ -1004,19 +1094,26 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu } /**************************************************************************** - Create a linked list of canonical ACE entries. This is sorted so that DENY - entries are at the front of the list, as NT requires. + Create a linked list of canonical ACE entries. ****************************************************************************/ -static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) +static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, + DOM_SID *powner, DOM_SID *pgroup, BOOL default_acl) { extern DOM_SID global_sid_World; mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); canon_ace *list_head = NULL; canon_ace *ace = NULL; canon_ace *next_ace = NULL; + canon_ace *owner_ace = NULL; + canon_ace *group_ace = NULL; + canon_ace *other_ace = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; + size_t ace_count; + + if (posix_acl == NULL) + return unix_canonicalise_acl( fsp, psbuf, powner, pgroup, default_acl); while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; @@ -1098,30 +1195,44 @@ static canon_ace *canonicalise_acl( SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf) ZERO_STRUCTP(ace); ace->type = tagtype; ace->perms = convert_permset_to_mode_t(permset); + ace->attr = ace->perms ? ALLOW_ACE : DENY_ACE; ace->sid = sid; ace->unix_ug = unix_ug; ace->owner_type = owner_type; + /* + * Remember the user/group/other ACE entries. + */ + + if (tagtype == SMB_ACL_USER_OBJ) + owner_ace = ace; + else if (tagtype == SMB_ACL_GROUP_OBJ) + group_ace = ace; + else if (tagtype == SMB_ACL_OTHER) + other_ace = ace; + DLIST_ADD(list_head, ace); } /* * Now go through the list, masking the permissions with the - * acl_mask. If the permissions are 0 it should be listed - * first. + * acl_mask. */ - for ( ace = list_head; ace; ace = next_ace) { + for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { next_ace = ace->next; /* Masks are only applied to entries other than USER_OBJ and OTHER. */ if (ace->type != SMB_ACL_OTHER && ace->type != SMB_ACL_USER_OBJ) ace->perms &= acl_mask; - if (ace->perms == 0) + if (ace->perms == 0) { DLIST_PROMOTE(list_head, ace); + } } + arrange_posix_perms(fsp->fsp_name,list_head ); + if( DEBUGLVL( 10 ) ) { char *acl_text = sys_acl_to_text( posix_acl, NULL); @@ -1381,32 +1492,29 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); /* Create the canon_ace lists. */ - if (posix_acl) - file_ace = canonicalise_acl( posix_acl, &sbuf); - else - file_ace = unix_canonicalise_acl(fsp, &sbuf, &owner_sid, &group_sid); - + file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, False); num_acls = count_canon_ace_list(file_ace); - if (fsp->is_directory) { - if (dir_acl) - dir_ace = canonicalise_acl( dir_acl, &sbuf); - else - dir_ace = unix_canonicalise_acl(fsp, &sbuf, &owner_sid, &group_sid); + /* We must have *some* ACLS. */ - num_dir_acls = count_canon_ace_list(dir_ace); + if (num_acls == 0) { + DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); + return 0; } - if ((num_acls + num_dir_acls) != 0) { - /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); - goto done; - } + if (fsp->is_directory) { + dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, &owner_sid, &group_sid, True); + num_dir_acls = count_canon_ace_list(dir_ace); + } - memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + /* Allocate the ace list. */ + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); + goto done; } + memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + /* * Create the NT ACE list from the canonical ace lists. */ -- cgit From 0dfc30cf87ab3b5746701034150e3a6400857148 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 Mar 2001 03:36:38 +0000 Subject: lib/system.c (Finally) fixed all insure errors in password caching code. We can't stop libc routines from calling getpwXXX functions, so caching a pointer to them is impossible. This new code now makes two copies of the returned struct passwd struct - one used as a cache, one returned to allow the caller to modify. When doing a lookup we compare against the cached copy. Code is now easier to understand also. smbd/posix_acls.c: If we move the head of the linked list, remember to pass a reference to that pointer..... Jeremy. (This used to be commit af364b93d92f70aa52195c46d3cc516830752609) --- source3/smbd/posix_acls.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f73f122f43..e358e0238c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -930,9 +930,10 @@ static void free_canon_ace_list( canon_ace *list_head ) entries, last entry = other. ********************************************************************************/ -static void arrange_posix_perms( char *filename, canon_ace *list_head) +static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) { extern DOM_SID global_sid_World; + canon_ace *list_head = *pp_list_head; canon_ace *owner_ace = NULL; canon_ace *other_ace = NULL; canon_ace *ace = NULL; @@ -1011,6 +1012,10 @@ static void arrange_posix_perms( char *filename, canon_ace *list_head) owner_ace->attr = DENY_ACE; owner_ace->perms = 0; } + + /* We have probably changed the head of the list. */ + + *pp_list_head = list_head; } /****************************************************************************** @@ -1080,7 +1085,7 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu DLIST_ADD(list_head, group_ace); DLIST_ADD(list_head, owner_ace); - arrange_posix_perms(fsp->fsp_name,list_head ); + arrange_posix_perms(fsp->fsp_name,&list_head ); return list_head; @@ -1219,6 +1224,8 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * acl_mask. */ + DEBUG(10,("canonicalize_acl: ace entries before arrange :\n")); + for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { next_ace = ace->next; @@ -1229,9 +1236,13 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ if (ace->perms == 0) { DLIST_PROMOTE(list_head, ace); } + + if( DEBUGLVL( 10 ) ) { + print_canon_ace(ace, ace_count); + } } - arrange_posix_perms(fsp->fsp_name,list_head ); + arrange_posix_perms(fsp->fsp_name,&list_head ); if( DEBUGLVL( 10 ) ) { char *acl_text = sys_acl_to_text( posix_acl, NULL); @@ -1239,6 +1250,12 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ dbgtext("canonicalize_acl: processed acl %s\n", acl_text == NULL ? "NULL" : acl_text ); if (acl_text) sys_acl_free_text(acl_text); + + dbgtext("canonicalize_acl: ace entries after arrange :\n"); + + for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { + print_canon_ace(ace, ace_count); + } } return list_head; -- cgit From 1656c5d258939397e0131349d2539212a25b5a18 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 17 Mar 2001 14:02:44 +0000 Subject: ADMIN$ is an IPC share, not a disk share (This used to be commit 0ea62800edd618091fde81e8de4347f612f98a18) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f5e1de1608..45ce286634 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1512,7 +1512,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, CVAL(p,13) = 0; type = STYPE_DISKTREE; if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; + if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC; SSVAL(p,14,type); /* device type */ SIVAL(p,16,PTR_DIFF(p2,baseaddr)); len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); -- cgit From cf313f6232e02577b0d79cc90e74cf8f20a81896 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 18 Mar 2001 22:47:17 +0000 Subject: fixed some compilation errors with IRIX cc (This used to be commit e430ded56e9c15a462a171e6350f1eddefa8dd11) --- source3/smbd/srvstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 241a74f02f..55cbada10c 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -49,7 +49,7 @@ int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int fla if (!(flags & STR_ASCII) && srvstr_align(outbuf, PTR_DIFF(dest, outbuf))) { *(char *)dest = 0; - dest++; + dest = (void *)((char *)dest + 1); dest_len--; len++; } @@ -98,7 +98,7 @@ int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_ } if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { - src++; + src = (void *)((char *)src + 1); if (src_len > 0) src_len--; } -- cgit From c7a953a3188ccb6dfbe49ea66304b3d517b0c628 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 Mar 2001 07:08:02 +0000 Subject: Added sys_dlopen/sys_dlsym/sys_dlclose. Jeremy. (This used to be commit 49f0e7e7143f82bce9dfd8b06e9e515bc0869ab7) --- source3/smbd/vfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b8aa290cab..b41e1f27fd 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -105,14 +105,14 @@ BOOL vfs_init_custom(connection_struct *conn) /* Open object file */ - if ((conn->dl_handle = dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { + if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); return False; } /* Get handle on vfs_init() symbol */ - init_fptr = (struct vfs_ops *(*)(int *))dlsym(conn->dl_handle, "vfs_init"); + init_fptr = (struct vfs_ops *(*)(int *))sys_dlsym(conn->dl_handle, "vfs_init"); if (init_fptr == NULL) { DEBUG(0, ("No vfs_init() symbol found in %s\n", -- cgit From beec1ea8291c9c2b12745d37ffe307dd4e3bd6ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Mar 2001 23:07:36 +0000 Subject: Fix for crash when doing name lookup with a quoted string. Part of lookup_name was expecting to be able to write to the string. Changed lookup_name to use const. Jeremy. (This used to be commit 80c18d88491f1148ade623e81c33f84ba4f952f3) --- source3/smbd/uid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 3d37021fff..02522a37a2 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -266,7 +266,7 @@ void unbecome_root(void) Tries winbind first - then uses local lookup. *****************************************************************/ -BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) +BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern pstring global_myname; extern fstring global_myworkgroup; @@ -302,7 +302,6 @@ BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) ret = local_lookup_name(domain, username, psid, name_type); } else { - ret = local_lookup_name(global_myname, name, psid, name_type); } -- cgit From 8adfb4757cd42a6a0cd62929a8d24d3b1e40574a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Mar 2001 01:26:37 +0000 Subject: New POSIX ACL mapping code. Works with UNIX permissions, now for testing with real ACLs... Jeremy. (This used to be commit 852b9e15ac245a593460cfff3f629d0333372e41) --- source3/smbd/posix_acls.c | 1022 ++++++++++++++++++++++++++++++--------------- 1 file changed, 684 insertions(+), 338 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index e358e0238c..22d1038fcc 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -21,6 +21,10 @@ #include "includes.h" +/**************************************************************************** + Data structures representing the internal ACE format. +****************************************************************************/ + enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE}; enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */ @@ -40,9 +44,40 @@ typedef struct canon_ace { posix_id unix_ug; } canon_ace; -static void free_canon_ace_list( canon_ace *list_head ); +#define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR) + +/**************************************************************************** + Functions to manipulate the internal ACE format. +****************************************************************************/ + +/**************************************************************************** + Count a linked list of canonical ACE entries. +****************************************************************************/ + +static size_t count_canon_ace_list( canon_ace *list_head ) +{ + size_t count = 0; + canon_ace *ace; + + for (ace = list_head; ace; ace = ace->next) + count++; + + return count; +} + +/**************************************************************************** + Free a linked list of canonical ACE entries. +****************************************************************************/ + +static void free_canon_ace_list( canon_ace *list_head ) +{ + while (list_head) { + canon_ace *old_head = list_head; + DLIST_REMOVE(list_head, list_head); + free(old_head); + } +} -#if !defined(HAVE_NO_ACLS) /**************************************************************************** Function to duplicate a canon_ace entry. ****************************************************************************/ @@ -58,7 +93,6 @@ static canon_ace *dup_canon_ace( canon_ace *src_ace) dst_ace->prev = dst_ace->next = NULL; return dst_ace; } -#endif /* HAVE_NO_ACLS */ /**************************************************************************** Function to create owner and group SIDs from a SMB_STRUCT_STAT. @@ -78,7 +112,7 @@ static void print_canon_ace(canon_ace *ace, int num) { fstring str; - dbgtext( "canon_ace index %d. Type = %s", num, ace->attr == ALLOW_ACE ? "allow" : "deny" ); + dbgtext( "canon_ace index %d. Type = %s ", num, ace->attr == ALLOW_ACE ? "allow" : "deny" ); dbgtext( "SID = %s ", sid_to_string( str, &ace->sid)); if (ace->owner_type == UID_ACE) { struct passwd *pass = sys_getpwuid(ace->unix_ug.uid); @@ -111,6 +145,118 @@ static void print_canon_ace(canon_ace *ace, int num) dbgtext( "%c\n", ace->perms & S_IXUSR ? 'x' : '-'); } +/**************************************************************************** + Merge aces with a common sid - if both are allow or deny, OR the permissions together and + delete the second one. If the first is deny, mask the permissions off and delete the allow + if the permissions become zero, delete the deny if the permissions are non zero. +****************************************************************************/ + +static void merge_aces( canon_ace **pp_list_head ) +{ + canon_ace *list_head = *pp_list_head; + canon_ace *curr_ace_outer; + canon_ace *curr_ace_outer_next; + + /* + * First, merge allow entries with identical SIDs, and deny entries + * with identical SIDs. + */ + + for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) { + canon_ace *curr_ace; + canon_ace *curr_ace_next; + + curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */ + + for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) { + + curr_ace_next = curr_ace->next; /* Save the link in case of delete. */ + + if (sid_equal(&curr_ace->sid, &curr_ace_outer->sid) && + (curr_ace->attr == curr_ace_outer->attr)) { + + if( DEBUGLVL( 10 )) { + dbgtext("merge_aces: Merging ACE's\n"); + print_canon_ace( curr_ace_outer, 0); + print_canon_ace( curr_ace, 0); + } + + /* Merge two allow or two deny ACE's. */ + + curr_ace_outer->perms |= curr_ace->perms; + DLIST_REMOVE(list_head, curr_ace); + free(curr_ace); + curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */ + } + } + } + + /* + * Now go through and mask off allow permissions with deny permissions. + * We can delete either the allow or deny here as we know that each SID + * appears only once in the list. + */ + + for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) { + canon_ace *curr_ace; + canon_ace *curr_ace_next; + + curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */ + + for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) { + + curr_ace_next = curr_ace->next; /* Save the link in case of delete. */ + + /* + * Subtract ACE's with different entries. Due to the ordering constraints + * we've put on the ACL, we know the deny must be the first one. + */ + + if ((curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) { + + if( DEBUGLVL( 10 )) { + dbgtext("merge_aces: Masking ACE's\n"); + print_canon_ace( curr_ace_outer, 0); + print_canon_ace( curr_ace, 0); + } + + curr_ace->perms &= ~curr_ace_outer->perms; + + if (curr_ace->perms == 0) { + + /* + * The deny overrides the allow. Remove the allow. + */ + + DLIST_REMOVE(list_head, curr_ace); + free(curr_ace); + curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */ + + } else { + + /* + * Even after removing permissions, there + * are still allow permissions - delete the deny. + * It is safe to delete the deny here, + * as we are guarenteed by the deny first + * ordering that all the deny entries for + * this SID have already been merged into one + * before we can get to an allow ace. + */ + + DLIST_REMOVE(list_head, curr_ace_outer); + free(curr_ace_outer); + } + } + + } /* end for curr_ace */ + } /* end for curr_ace_outer */ + + /* We may have modified the list. */ + + *pp_list_head = list_head; +} + /**************************************************************************** Map canon_ace perms to permission bits NT. The attr element is not used here - we only process deny entries on set, @@ -124,9 +270,9 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - if((ace->perms & (S_IRUSR|S_IWUSR|S_IXUSR)) == (S_IRUSR|S_IWUSR|S_IXUSR)) { + if ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS) { nt_mask = UNIX_ACCESS_RWX; - } else if((ace->perms & (S_IRUSR|S_IWUSR|S_IXUSR)) == 0) { + } else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) { /* * Here we differentiate between the owner and any other user. */ @@ -249,36 +395,6 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, return True; } -#if !defined(HAVE_NO_ACLS) -/**************************************************************************** - Merge aces with a common user. -****************************************************************************/ - -static BOOL merge_aces( canon_ace *list_head, canon_ace *p_ace) -{ - canon_ace *curr_ace; - - for (curr_ace = list_head; curr_ace; curr_ace = curr_ace->next) { - if (curr_ace == p_ace) - continue; - - if ((curr_ace->type == p_ace->type) && (curr_ace->attr == p_ace->attr) && - sid_equal(&curr_ace->sid, &p_ace->sid)) { - if( DEBUGLVL( 10 )) { - dbgtext("Merging ACE's\n"); - print_canon_ace( p_ace, 0); - print_canon_ace( curr_ace, 0); - } - p_ace->perms |= curr_ace->perms; - DLIST_REMOVE(list_head, curr_ace); - free(curr_ace); - return True; - } - } - - return False; -} - /**************************************************************************** Create a default mode for a directory default ACE. ****************************************************************************/ @@ -312,6 +428,7 @@ static mode_t get_default_ace_mode(files_struct *fsp, int type) /**************************************************************************** A well formed POSIX file or default ACL has at least 3 entries, a SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ. + In addition, the owner must always have at least read access. ****************************************************************************/ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, @@ -328,9 +445,12 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, BOOL got_other = False; for (pace = *pp_ace; pace; pace = pace->next) { - if (pace->type == SMB_ACL_USER_OBJ) + if (pace->type == SMB_ACL_USER_OBJ) { + /* Ensure owner has read access. */ + if (pace->perms == (mode_t)0) + pace->perms = S_IRUSR; got_user = True; - else if (pace->type == SMB_ACL_GROUP_OBJ) + } else if (pace->type == SMB_ACL_GROUP_OBJ) got_grp = True; else if (pace->type == SMB_ACL_OTHER) got_other = True; @@ -389,62 +509,38 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, return True; } -#endif /* HAVE_NO_ACLS */ /**************************************************************************** - Unpack a SEC_DESC into two canonical ace lists. We don't depend on this - succeeding. + Unpack a SEC_DESC into two canonical ace lists. ****************************************************************************/ -static BOOL unpack_canon_ace(files_struct *fsp, - SMB_STRUCT_STAT *pst, +static BOOL create_canon_ace_lists(files_struct *fsp, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, canon_ace **ppfile_ace, canon_ace **ppdir_ace, - uint32 security_info_sent, SEC_DESC *psd) + SEC_ACL *dacl) { -#if !defined(HAVE_NO_ACLS) extern DOM_SID global_sid_World; BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; + canon_ace *tmp_ace = NULL; canon_ace *current_ace = NULL; - enum SID_NAME_USE sid_type; + BOOL got_dir_allow = False; + BOOL got_file_allow = False; int i; -#endif /* HAVE_NO_ACLS */ - SEC_ACL *dacl = psd->dacl; *ppfile_ace = NULL; *ppdir_ace = NULL; - if(security_info_sent == 0) { - DEBUG(0,("unpack_canon_ace: no security info sent !\n")); - return False; - } - - /* - * If no DACL then this is a chown only security descriptor. - */ - - if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) - return True; - -#if defined(HAVE_NO_ACLS) - - /* No point in doing this if we have no ACL support. */ - return False; - -#else /* HAVE_NO_ACLS */ - - /* - * Now go through the DACL and create the canon_ace lists. - */ - for(i = 0; i < dacl->num_aces; i++) { + enum SID_NAME_USE sid_type; SEC_ACE *psa = &dacl->ace[i]; if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - DEBUG(3,("unpack_canon_ace: unable to set anything but an ALLOW or DENY ACE.\n")); + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n")); return False; } @@ -468,7 +564,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, if ((current_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - DEBUG(0,("unpack_canon_ace: malloc fail.\n")); + DEBUG(0,("create_canon_ace_lists: malloc fail.\n")); return False; } @@ -494,7 +590,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); free(current_ace); - DEBUG(0,("unpack_canon_ace: unable to map SID %s to uid or gid.\n", + DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n", sid_to_string(str, ¤t_ace->sid) )); return False; } @@ -504,13 +600,8 @@ static BOOL unpack_canon_ace(files_struct *fsp, * S_I(R|W|X)USR bits. */ - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) { - current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); - current_ace->attr = ALLOW_ACE; - } else { - current_ace->perms = 0; - current_ace->attr = DENY_ACE; - } + current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); + current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE; /* * Now note what kind of a POSIX ACL this should map to. @@ -534,20 +625,43 @@ static BOOL unpack_canon_ace(files_struct *fsp, current_ace->type = (current_ace->owner_type == UID_ACE) ? SMB_ACL_USER : SMB_ACL_GROUP; } + /* + * Now add the created ace to either the file list, the directory + * list, or both. We *MUST* preserve the order here (hence we use + * DLIST_ADD_END) as NT ACLs are order dependent. + */ + if (fsp->is_directory) { /* * We can only add to the default POSIX ACE list if the ACE is * designed to be inherited by both files and directories. */ + if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) == (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) { - DLIST_ADD(dir_ace, current_ace); + DLIST_ADD_END(dir_ace, current_ace, tmp_ace); + /* + * Note if this was an allow ace. We can't process + * any further deny ace's after this. + */ + + if (current_ace->attr == ALLOW_ACE) + got_dir_allow = True; + + if ((current_ace->attr == DENY_ACE) && got_dir_allow) { + DEBUG(0,("create_canon_ace_lists: malformed ACL in inheritable ACL ! \ +Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + free(current_ace); + return False; + } if( DEBUGLVL( 10 )) { - dbgtext("unpack_canon_ace: adding dir ACL:\n"); + dbgtext("create_canon_ace_lists: adding dir ACL:\n"); print_canon_ace( current_ace, 0); } @@ -560,7 +674,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, canon_ace *dup_ace = dup_canon_ace(current_ace); if (!dup_ace) { - DEBUG(0,("unpack_canon_ace: malloc fail !\n")); + DEBUG(0,("create_canon_ace_lists: malloc fail !\n")); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -578,13 +692,35 @@ static BOOL unpack_canon_ace(files_struct *fsp, */ if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { - DLIST_ADD(file_ace, current_ace); + DLIST_ADD_END(file_ace, current_ace, tmp_ace); + + /* + * Note if this was an allow ace. We can't process + * any further deny ace's after this. + */ + + if (current_ace->attr == ALLOW_ACE) + got_file_allow = True; + + if ((current_ace->attr == DENY_ACE) && got_file_allow) { + DEBUG(0,("create_canon_ace_lists: malformed ACL in file ACL ! \ +Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + free(current_ace); + return False; + } + + if( DEBUGLVL( 10 )) { + dbgtext("create_canon_ace_lists: adding file ACL:\n"); + print_canon_ace( current_ace, 0); + } all_aces_are_inherit_only = False; current_ace = NULL; } /* - * Free if ACE was not addedd. + * Free if ACE was not added. */ if (current_ace) @@ -598,28 +734,375 @@ static BOOL unpack_canon_ace(files_struct *fsp, * there was no DACL sent. JRA. */ - DEBUG(10,("unpack_canon_ace: Win2k inherit acl traverse. Ignoring DACL.\n")); + DEBUG(10,("create_canon_ace_lists: Win2k inherit acl traverse. Ignoring DACL.\n")); + free_canon_ace_list(file_ace); + free_canon_ace_list(dir_ace); + file_ace = NULL; + dir_ace = NULL; } + *ppfile_ace = file_ace; + *ppdir_ace = dir_ace; + + return True; +} + +/**************************************************************************** + Check if a given uid/SID is in a group gid/SID. This is probably very + expensive and will need optimisation. A *lot* of optimisation :-). JRA. +****************************************************************************/ + +static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) +{ + extern DOM_SID global_sid_World; + struct passwd *pass = NULL; + struct group *gptr = NULL; + + /* "Everyone" always matches every uid. */ + + if (sid_equal(&group_ace->sid, &global_sid_World)) + return True; + + if (!(pass = sys_getpwuid(uid_ace->unix_ug.uid))) + return False; + + if (!(gptr = getgrgid(uid_ace->unix_ug.gid))) + return False; + /* - * Now go through the canon_ace lists and merge entries - * belonging to identical users. + * Due to the winbind interfaces we need to do this via names, + * not uids/gids. */ - again_file: + return user_in_group_list(pass->pw_name, gptr->gr_name ); +} + +/**************************************************************************** + ASCII art time again... JRA :-). + + We have 3 cases to process when moving from an NT ACL to a POSIX ACL. Firstly, + we insist the ACL is in canonical form (ie. all DENY entries preceede ALLOW + entries). Secondly, the merge code has ensured that all duplicate SID entries for + allow or deny have been merged, so the same SID can only appear once in the deny + list or once in the allow list. + + We then process as follows : + + --------------------------------------------------------------------------- + First pass - look for a Everyone DENY entry. + + If it is deny all (rwx) trunate the list at this point. + Else, walk the list from this point and use the deny permissions of this + entry as a mask on all following allow entries. Finally, delete + the Everyone DENY entry (we have applied it to everything possible). + + In addition, in this pass we remove any DENY entries that have + no permissions (ie. they are a DENY nothing). + --------------------------------------------------------------------------- + Second pass - only deal with deny user entries. + + DENY user1 (perms XXX) + + new_perms = 0 + for all following allow group entries where user1 is in group + new_perms |= group_perms; + + user1 entry perms = new_perms & ~ XXX; + + Convert the deny entry to an allow entry with the new perms and + push to the end of the list. Note if the user was in no groups + this maps to a specific allow nothing entry for this user. + + The common case from the NT ACL choser (userX deny all) is + optimised so we don't do the group lookup - we just map to + an allow nothing entry. + + What we're doing here is inferring the allow permissions the + person setting the ACE on user1 wanted by looking at the allow + permissions on the groups the user is currently in. This will + be a snapshot, depending on group membership but is the best + we can do and has the advantage of failing closed rather than + open. + --------------------------------------------------------------------------- + Third pass - only deal with deny group entries. + + DENY group1 (perms XXX) + + for all following allow user entries where user is in group1 + user entry perms = user entry perms & ~ XXX; + + If there is a group Everyone allow entry with permissions YYY, + convert the group1 entry to an allow entry and modify its + permissions to be : + + new_perms = YYY & ~ XXX + + and push to the end of the list. + + If there is no group Everyone allow entry then convert the + group1 entry to a allow nothing entry and push to the end of the list. + + Note that the common case from the NT ACL choser (groupX deny all) + cannot be optimised here as we need to modify user entries who are + in the group to change them to a deny all also. + + What we're doing here is modifying the allow permissions of + user entries (which are more specific in POSIX ACLs) to mask + out the explicit deny set on the group they are in. This will + be a snapshot depending on current group membership but is the + best we can do and has the advantage of failing closed rather + than open. + --------------------------------------------------------------------------- + + Note we *MUST* do the deny user pass first as this will convert deny user + entries into allow user entries which can then be processed by the deny + group pass. + + The above algorithm took a *lot* of thinking about - hence this + explaination :-). JRA. +****************************************************************************/ + +/**************************************************************************** + Process a canon_ace list entries. This is very complex code. We need + to go through and remove the "deny" permissions from any allow entry that matches + the id of this entry. We have already refused any NT ACL that wasn't in correct + order (DENY followed by ALLOW). If any allow entry ends up with zero permissions, + we just remove it (to fail safe). We have already removed any duplicate ace + entries. Treat an "Everyone" DENY_ACE as a special case - use it to mask all + allow entries. +****************************************************************************/ + +static void process_deny_list( canon_ace **pp_ace_list ) +{ + extern DOM_SID global_sid_World; + canon_ace *ace_list = *pp_ace_list; + canon_ace *curr_ace = NULL; + canon_ace *curr_ace_next = NULL; + + /* Pass 1 above - look for an Everyone, deny entry. */ + + for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) { + canon_ace *allow_ace_p; + + curr_ace_next = curr_ace->next; /* So we can't lose the link. */ + + if (curr_ace->attr != DENY_ACE) + continue; - for (current_ace = file_ace; current_ace; current_ace = current_ace->next ) { - if (merge_aces( file_ace, current_ace)) - goto again_file; + if (curr_ace->perms == (mode_t)0) { + + /* Deny nothing entry - delete. */ + + DLIST_REMOVE(ace_list, curr_ace); + continue; + } + + if (!sid_equal(&curr_ace->sid, &global_sid_World)) + continue; + + /* JRATEST - assert. */ + SMB_ASSERT(curr_ace->owner_type == WORLD_ACE); + + if (curr_ace->perms == ALL_ACE_PERMS) { + + /* + * Optimisation. This is a DENY_ALL to Everyone. Truncate the + * list at this point including this entry. + */ + + canon_ace *prev_entry = curr_ace->prev; + + free_canon_ace_list( curr_ace ); + if (prev_entry) + prev_entry->next = NULL; + else { + /* We deleted the entire list. */ + ace_list = NULL; + } + break; + } + + for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) { + + /* + * Only mask off allow entries. + */ + + if (allow_ace_p->attr != ALLOW_ACE) + continue; + + allow_ace_p->perms &= ~curr_ace->perms; + } + + /* + * Now it's been applied, remove it. + */ + + DLIST_REMOVE(ace_list, curr_ace); + } + + /* Pass 2 above - deal with deny user entries. */ + + for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) { + mode_t new_perms = (mode_t)0; + canon_ace *allow_ace_p; + canon_ace *tmp_ace; + + curr_ace_next = curr_ace->next; /* So we can't lose the link. */ + + if (curr_ace->attr != DENY_ACE) + continue; + + if (curr_ace->owner_type != UID_ACE) + continue; + + if (curr_ace->perms == ALL_ACE_PERMS) { + + /* + * Optimisation - this is a deny everything to this user. + * Convert to an allow nothing and push to the end of the list. + */ + + curr_ace->attr = ALLOW_ACE; + curr_ace->perms = (mode_t)0; + DLIST_DEMOTE(ace_list, curr_ace, tmp_ace); + continue; + } + + for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) { + + if (allow_ace_p->attr != ALLOW_ACE) + continue; + + /* We process GID_ACE and WORLD_ACE entries only. */ + + if (allow_ace_p->owner_type == UID_ACE) + continue; + + if (uid_entry_in_group( curr_ace, allow_ace_p)) + new_perms |= allow_ace_p->perms; + } + + /* + * Convert to a allow entry, modify the perms and push to the end + * of the list. + */ + + curr_ace->attr = ALLOW_ACE; + curr_ace->perms = (new_perms & ~curr_ace->perms); + DLIST_DEMOTE(ace_list, curr_ace, tmp_ace); } - again_dir: + /* Pass 3 above - deal with deny group entries. */ + + for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) { + canon_ace *tmp_ace; + canon_ace *allow_ace_p; + canon_ace *allow_everyone_p = NULL; + + curr_ace_next = curr_ace->next; /* So we can't lose the link. */ + + if (curr_ace->attr != DENY_ACE) + continue; + + if (curr_ace->owner_type != GID_ACE) + continue; + + for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) { + + if (allow_ace_p->attr != ALLOW_ACE) + continue; + + /* Store a pointer to the Everyone allow, if it exists. */ + if (allow_ace_p->owner_type == WORLD_ACE) + allow_everyone_p = allow_ace_p; + + /* We process UID_ACE entries only. */ + + if (allow_ace_p->owner_type != UID_ACE) + continue; + + /* Mask off the deny group perms. */ + + if (uid_entry_in_group( allow_ace_p, curr_ace)) + allow_ace_p->perms &= ~curr_ace->perms; + } + + /* + * Convert the deny to an allow with the correct perms and + * push to the end of the list. + */ + + curr_ace->attr = ALLOW_ACE; + if (allow_everyone_p) + curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms; + else + curr_ace->perms = (mode_t)0; + DLIST_DEMOTE(ace_list, curr_ace, tmp_ace); - for (current_ace = dir_ace; current_ace; current_ace = current_ace->next ) { - if (merge_aces( dir_ace, current_ace)) - goto again_dir; } + *pp_ace_list = ace_list; +} + +/**************************************************************************** + Unpack a SEC_DESC into two canonical ace lists. We don't depend on this + succeeding. +****************************************************************************/ + +static BOOL unpack_canon_ace(files_struct *fsp, + SMB_STRUCT_STAT *pst, + DOM_SID *pfile_owner_sid, + DOM_SID *pfile_grp_sid, + canon_ace **ppfile_ace, canon_ace **ppdir_ace, + uint32 security_info_sent, SEC_DESC *psd) +{ + canon_ace *file_ace = NULL; + canon_ace *dir_ace = NULL; + canon_ace *current_ace = NULL; + int i; + + *ppfile_ace = NULL; + *ppdir_ace = NULL; + + if(security_info_sent == 0) { + DEBUG(0,("unpack_canon_ace: no security info sent !\n")); + return False; + } + + /* + * If no DACL then this is a chown only security descriptor. + */ + + if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !psd->dacl) + return True; + + /* + * Now go through the DACL and create the canon_ace lists. + */ + + if (!create_canon_ace_lists( fsp, pfile_owner_sid, pfile_grp_sid, + &file_ace, &dir_ace, psd->dacl)) + return False; + + /* + * Go through the canon_ace list and merge entries + * belonging to identical users of identical allow or deny type. + * We can do this as all deny entries come first, followed by + * all allow entries (we have mandated this before accepting this acl). + */ + + merge_aces( &file_ace ); + merge_aces( &dir_ace ); + + /* + * NT ACLs are order dependent. Go through the acl lists and + * process DENY entries by masking the allow entries. + */ + + process_deny_list( &file_ace); + process_deny_list( &dir_ace); + /* * A well formed POSIX file or default ACL has at least 3 entries, a * SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ @@ -654,188 +1137,6 @@ static BOOL unpack_canon_ace(files_struct *fsp, *ppdir_ace = dir_ace; return True; -#endif /* HAVE_NO_ACLS */ -} - -/**************************************************************************** - Unpack a SEC_DESC into a set of standard POSIX permissions. -****************************************************************************/ - -static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, mode_t *pmode, - uint32 security_info_sent, SEC_DESC *psd, BOOL posix_acls) -{ - extern DOM_SID global_sid_World; - connection_struct *conn = fsp->conn; - DOM_SID file_owner_sid; - DOM_SID file_grp_sid; - SEC_ACL *dacl = psd->dacl; - BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); - int i; - - *pmode = 0; - - if(security_info_sent == 0) { - DEBUG(0,("unpack_posix_permissions: no security info sent !\n")); - return False; - } - - /* - * Windows 2000 sends the owner and group SIDs as the logged in - * user, not the connected user. But it still sends the file - * owner SIDs on an ACL set. So we need to check for the file - * owner and group SIDs as well as the owner SIDs. JRA. - */ - - create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); - - /* - * If no DACL then this is a chown only security descriptor. - */ - - if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) { - *pmode = 0; - return True; - } - - /* - * Now go through the DACL and ensure that - * any owner/group sids match. - */ - - for(i = 0; i < dacl->num_aces; i++) { - DOM_SID ace_sid; - SEC_ACE *psa = &dacl->ace[i]; - - if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && - (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - DEBUG(3,("unpack_posix_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); - return False; - } - - /* - * Ignore or remove bits we don't care about on a directory ACE. - */ - - if(fsp->is_directory) { - if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - DEBUG(3,("unpack_posix_permissions: ignoring inherit only ACE.\n")); - continue; - } - - /* - * At least one of the ACE entries wasn't inherit only. - * Flag this so we know the returned mode is valid. - */ - - all_aces_are_inherit_only = False; - } - - /* - * Windows 2000 sets these flags even on *file* ACE's. This is wrong - * but we can ignore them for now. Revisit this when we go to POSIX - * ACLs on directories. - */ - - psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERITED_ACE); - - if(psa->flags != 0) { - DEBUG(1,("unpack_posix_permissions: unable to set ACE flags (%x).\n", - (unsigned int)psa->flags)); - return False; - } - - /* - * The security mask may be UNIX_ACCESS_NONE which should map into - * no permissions (we overload the WRITE_OWNER bit for this) or it - * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this - * to be so. Any other bits override the UNIX_ACCESS_NONE bit. - */ - - psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| - GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); - - if(psa->info.mask != UNIX_ACCESS_NONE) - psa->info.mask &= ~UNIX_ACCESS_NONE; - - sid_copy(&ace_sid, &psa->sid); - - if(sid_equal(&ace_sid, &file_owner_sid)) { - /* - * Map the desired permissions into owner perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRUSR); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); - - - } else if( sid_equal(&ace_sid, &file_grp_sid)) { - /* - * Map the desired permissions into group perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRGRP); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRGRP)); - - } else if( sid_equal(&ace_sid, &global_sid_World)) { - /* - * Map the desired permissions into other perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IROTH); - else - *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); - - } else { - /* - * Only bother printing the level zero error if we didn't get any - * POSIX ACLS. - */ - if (!posix_acls) - DEBUG(0,("unpack_posix_permissions: unknown SID used in ACL.\n")); - return False; - } - } - - if (fsp->is_directory && all_aces_are_inherit_only) { - /* - * Windows 2000 is doing one of these weird 'inherit acl' - * traverses to conserve NTFS ACL resources. Just pretend - * there was no DACL sent. JRA. - */ - - DEBUG(10,("unpack_posix_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); - } - - /* - * Check to see if we need to change anything. - * Enforce limits on modified bits *only*. Don't enforce masks - * on bits not changed by the user. - */ - - if(fsp->is_directory) { - - *pmode &= (lp_dir_security_mask(SNUM(conn)) | psbuf->st_mode); - *pmode |= (lp_force_dir_security_mode(SNUM(conn)) & ( *pmode ^ psbuf->st_mode )); - - } else { - - *pmode &= (lp_security_mask(SNUM(conn)) | psbuf->st_mode); - *pmode |= (lp_force_security_mode(SNUM(conn)) & ( *pmode ^ psbuf->st_mode )); - - } - - /* - * Preserve special bits. - */ - - *pmode |= (psbuf->st_mode & ~0777); - - return True; } /**************************************************************************** @@ -895,39 +1196,24 @@ static int map_acl_perms_to_permset(mode_t mode, SMB_ACL_PERMSET_T *p_permset) return 0; } -/**************************************************************************** - Count a linked list of canonical ACE entries. -****************************************************************************/ - -static size_t count_canon_ace_list( canon_ace *list_head ) -{ - size_t count = 0; - canon_ace *ace; - - for (ace = list_head; ace; ace = ace->next) - count++; - - return count; -} - -/**************************************************************************** - Free a linked list of canonical ACE entries. -****************************************************************************/ - -static void free_canon_ace_list( canon_ace *list_head ) -{ - while (list_head) { - canon_ace *old_head = list_head; - DLIST_REMOVE(list_head, list_head); - free(old_head); - } -} - /****************************************************************************** When returning permissions, try and fit NT display semantics if possible. Note the the canon_entries here must have been malloced. The list format should be - first entry = owner, followed by group and other user entries, last entry = other. + + Note that this doesn't exactly match the NT semantics for an ACL. As POSIX entries + are not ordered, and match on the most specific entry rather than walking a list, + then a simple POSIX permission of rw-r--r-- should really map to 6 entries, + + Entry 0: owner : deny all except read and write. + Entry 1: group : deny all except read. + Entry 2: Everyone : deny all except read. + Entry 3: owner : allow read and write. + Entry 4: group : allow read. + Entry 5: Everyone : allow read. + + But NT cannot display this in their ACL editor ! ********************************************************************************/ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) @@ -1221,7 +1507,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ /* * Now go through the list, masking the permissions with the - * acl_mask. + * acl_mask. Ensure all DENY Entries are at the start of the list. */ DEBUG(10,("canonicalize_acl: ace entries before arrange :\n")); @@ -1281,14 +1567,15 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS); if (the_acl == NULL) { -#if !defined(HAVE_NO_ACLS) - /* - * Only print this error message if we have some kind of ACL - * support that's not working. Otherwise we would always get this. - */ - DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n", - default_ace ? "default" : "file", strerror(errno) )); -#endif + + if (errno != ENOSYS) { + /* + * Only print this error message if we have some kind of ACL + * support that's not working. Otherwise we would always get this. + */ + DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n", + default_ace ? "default" : "file", strerror(errno) )); + } *pacl_set_support = False; return False; } @@ -1440,6 +1727,63 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau return ret; } +/**************************************************************************** + Convert a canon_ace to a generic 3 element permission - if possible. +****************************************************************************/ + +#define MAP_PERM(p,mask,result) (((p) & (mask)) ? (result) : 0 ) + +static BOOL convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms) +{ + size_t ace_count = count_canon_ace_list(file_ace_list); + canon_ace *ace_p; + canon_ace *owner_ace = NULL; + canon_ace *group_ace = NULL; + canon_ace *other_ace = NULL; + + if (ace_count != 3) { + DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE entries for file %s to convert to \ +posix perms.\n", fsp->fsp_name )); + return False; + } + + for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) { + if (ace_p->owner_type == UID_ACE) + owner_ace = ace_p; + else if (ace_p->owner_type == GID_ACE) + group_ace = ace_p; + else if (ace_p->owner_type == WORLD_ACE) + other_ace = ace_p; + } + + if (!owner_ace || !group_ace || !other_ace) { + DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get standard entries for file %s.\n", + fsp->fsp_name )); + return False; + } + + *posix_perms = (mode_t)0; + + *posix_perms |= owner_ace->perms; + *posix_perms |= MAP_PERM(group_ace->perms, S_IRUSR, S_IRGRP); + *posix_perms |= MAP_PERM(group_ace->perms, S_IWUSR, S_IWGRP); + *posix_perms |= MAP_PERM(group_ace->perms, S_IXUSR, S_IXGRP); + *posix_perms |= MAP_PERM(other_ace->perms, S_IRUSR, S_IROTH); + *posix_perms |= MAP_PERM(other_ace->perms, S_IWUSR, S_IWOTH); + *posix_perms |= MAP_PERM(other_ace->perms, S_IXUSR, S_IXOTH); + + /* The owner must have at least read access. */ + + if (*posix_perms == (mode_t)0) + *posix_perms = S_IRUSR; + + DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n", + (int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms, + fsp->fsp_name )); + + return True; +} + /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns the size needed to return the @@ -1596,14 +1940,12 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) connection_struct *conn = fsp->conn; uid_t user = (uid_t)-1; gid_t grp = (gid_t)-1; - mode_t perms = 0; SMB_STRUCT_STAT sbuf; DOM_SID file_owner_sid; DOM_SID file_grp_sid; canon_ace *file_ace_list = NULL; canon_ace *dir_ace_list = NULL; - BOOL posix_perms; - BOOL acl_perms; + BOOL acl_perms = False; DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -1668,14 +2010,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); - posix_perms = unpack_posix_permissions( fsp, &sbuf, &perms, security_info_sent, psd, acl_perms); - - if (!posix_perms && !acl_perms) { - /* - * Neither method of setting permissions can work. Fail here. - */ - DEBUG(3,("set_nt_acl: cannot set normal POSIX permissions or POSIX ACL permissions\n")); + if (!acl_perms) { + DEBUG(3,("set_nt_acl: cannot set permissions\n")); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); return False; @@ -1691,7 +2028,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) BOOL ret = False; /* - * Try using the POSIX ACL set first. All back to chmod if + * Try using the POSIX ACL set first. Fall back to chmod if * we have no ACL support on this filesystem. */ @@ -1718,20 +2055,29 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. */ - if(!acl_set_support && posix_perms && (sbuf.st_mode != perms)) { + if(!acl_set_support && acl_perms) { + mode_t posix_perms; - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - file_ace_list = NULL; - dir_ace_list = NULL; + if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) { + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n", + fsp->fsp_name )); + return False; + } - DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", - fsp->fsp_name, (unsigned int)perms )); + if (sbuf.st_mode != posix_perms) { - if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), perms) == -1) { - DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)perms, strerror(errno) )); - return False; + DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", + fsp->fsp_name, (unsigned int)posix_perms )); + + if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), posix_perms) == -1) { + DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } } } } -- cgit From 0053bd8b80cc08d65948c97f8ab0b4e2b829f083 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Fri, 23 Mar 2001 00:50:31 +0000 Subject: first pass of the new group mapping code J.F. (This used to be commit 7154deb026d53cb0cd503562174c3332a372be63) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d2a7ad3be4..baa1536248 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -772,6 +772,11 @@ static void usage(char *pname) /* possibly reload the services file. */ reload_services(True); + if (init_group_mapping()==False) { + printf("Could not open tdb mapping file.\n"); + return 0; + } + if(!pdb_generate_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); -- cgit From 81afba28c3fecb5471e1ff03a0b3dda5126f5aa6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2001 00:54:55 +0000 Subject: Sync up with 2.2 ACL code. Jeremy. (This used to be commit 5b9a88c2d0da3479f91131f66ff741e88f9760ee) --- source3/smbd/posix_acls.c | 132 +++++++++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 22d1038fcc..ddf4d06b0e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -108,21 +108,21 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI Print out a canon ace. ****************************************************************************/ -static void print_canon_ace(canon_ace *ace, int num) +static void print_canon_ace(canon_ace *pace, int num) { fstring str; - dbgtext( "canon_ace index %d. Type = %s ", num, ace->attr == ALLOW_ACE ? "allow" : "deny" ); - dbgtext( "SID = %s ", sid_to_string( str, &ace->sid)); - if (ace->owner_type == UID_ACE) { - struct passwd *pass = sys_getpwuid(ace->unix_ug.uid); - dbgtext( "uid %u (%s) ", (unsigned int)ace->unix_ug.uid, pass ? pass->pw_name : "UNKNOWN"); - } else if (ace->owner_type == GID_ACE) { - struct group *grp = getgrgid(ace->unix_ug.gid); - dbgtext( "gid %u (%s) ", (unsigned int)ace->unix_ug.gid, grp ? grp->gr_name : "UNKNOWN"); + dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" ); + dbgtext( "SID = %s ", sid_to_string( str, &pace->sid)); + if (pace->owner_type == UID_ACE) { + struct passwd *pass = sys_getpwuid(pace->unix_ug.uid); + dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, pass ? pass->pw_name : "UNKNOWN"); + } else if (pace->owner_type == GID_ACE) { + struct group *grp = getgrgid(pace->unix_ug.gid); + dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, grp ? grp->gr_name : "UNKNOWN"); } else dbgtext( "other "); - switch (ace->type) { + switch (pace->type) { case SMB_ACL_USER: dbgtext( "SMB_ACL_USER "); break; @@ -140,9 +140,24 @@ static void print_canon_ace(canon_ace *ace, int num) break; } dbgtext( "perms "); - dbgtext( "%c", ace->perms & S_IRUSR ? 'r' : '-'); - dbgtext( "%c", ace->perms & S_IWUSR ? 'w' : '-'); - dbgtext( "%c\n", ace->perms & S_IXUSR ? 'x' : '-'); + dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-'); + dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-'); + dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-'); +} + +/**************************************************************************** + Print out a canon ace list. +****************************************************************************/ + +static void print_canon_ace_list(const char *name, canon_ace *ace_list) +{ + int count = 0; + + if( DEBUGLVL( 10 )) { + dbgtext( "print_canon_ace_list: %s\n", name ); + for (;ace_list; ace_list = ace_list->next, count++) + print_canon_ace(ace_list, count ); + } } /**************************************************************************** @@ -212,7 +227,8 @@ static void merge_aces( canon_ace **pp_list_head ) * we've put on the ACL, we know the deny must be the first one. */ - if ((curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) { + if (sid_equal(&curr_ace->sid, &curr_ace_outer->sid) && + (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) { if( DEBUGLVL( 10 )) { dbgtext("merge_aces: Masking ACE's\n"); @@ -280,8 +296,13 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon nt_mask = UNIX_ACCESS_NONE; } else { /* Not owner, no access. */ - *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED; - nt_mask = GENERIC_ALL_ACCESS; + if (ace->type == SMB_ACL_USER) { + /* user objects can be deny entries. */ + *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED; + nt_mask = GENERIC_ALL_ACCESS; + } + else + nt_mask = UNIX_ACCESS_NONE; } } else { nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); @@ -467,7 +488,8 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->owner_type = UID_ACE; pace->unix_ug.uid = pst->st_uid; pace->sid = *pfile_owner_sid; - pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRUSR): 0; + /* Ensure owner has read access. */ + pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRUSR): S_IRUSR; pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); @@ -766,7 +788,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) if (!(pass = sys_getpwuid(uid_ace->unix_ug.uid))) return False; - if (!(gptr = getgrgid(uid_ace->unix_ug.gid))) + if (!(gptr = getgrgid(group_ace->unix_ug.gid))) return False; /* @@ -1059,8 +1081,6 @@ static BOOL unpack_canon_ace(files_struct *fsp, { canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; - canon_ace *current_ace = NULL; - int i; *ppfile_ace = NULL; *ppdir_ace = NULL; @@ -1085,6 +1105,11 @@ static BOOL unpack_canon_ace(files_struct *fsp, &file_ace, &dir_ace, psd->dacl)) return False; + if ((file_ace == NULL) && (dir_ace == NULL)) { + /* W2K traverse DACL set - ignore. */ + return True; + } + /* * Go through the canon_ace list and merge entries * belonging to identical users of identical allow or deny type. @@ -1092,7 +1117,10 @@ static BOOL unpack_canon_ace(files_struct *fsp, * all allow entries (we have mandated this before accepting this acl). */ + print_canon_ace_list( "file ace - before merge", file_ace); merge_aces( &file_ace ); + + print_canon_ace_list( "dir ace - before merge", dir_ace); merge_aces( &dir_ace ); /* @@ -1100,7 +1128,10 @@ static BOOL unpack_canon_ace(files_struct *fsp, * process DENY entries by masking the allow entries. */ + print_canon_ace_list( "file ace - before deny", file_ace); process_deny_list( &file_ace); + + print_canon_ace_list( "dir ace - before deny", dir_ace); process_deny_list( &dir_ace); /* @@ -1109,29 +1140,24 @@ static BOOL unpack_canon_ace(files_struct *fsp, * and optionally a mask entry. Ensure this is the case. */ + print_canon_ace_list( "file ace - before valid", file_ace); + if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, False)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; } - if (!ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { + print_canon_ace_list( "dir ace - before valid", dir_ace); + + if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; } - if( DEBUGLVL( 10 )) { - dbgtext("unpack_canon_ace: File ACL:\n"); - for (i = 0, current_ace = file_ace; current_ace; current_ace = current_ace->next, i++ ) { - print_canon_ace( current_ace, i); - } - - dbgtext("unpack_canon_ace: Directory ACL:\n"); - for (i = 0, current_ace = dir_ace; current_ace; current_ace = current_ace->next, i++ ) { - print_canon_ace( current_ace, i); - } - } + print_canon_ace_list( "file ace - return", file_ace); + print_canon_ace_list( "dir ace - return", dir_ace); *ppfile_ace = file_ace; *ppdir_ace = dir_ace; @@ -1486,7 +1512,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ ZERO_STRUCTP(ace); ace->type = tagtype; ace->perms = convert_permset_to_mode_t(permset); - ace->attr = ace->perms ? ALLOW_ACE : DENY_ACE; + ace->attr = ALLOW_ACE; ace->sid = sid; ace->unix_ug = unix_ug; ace->owner_type = owner_type; @@ -1505,6 +1531,8 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ DLIST_ADD(list_head, ace); } + arrange_posix_perms(fsp->fsp_name,&list_head ); + /* * Now go through the list, masking the permissions with the * acl_mask. Ensure all DENY Entries are at the start of the list. @@ -1528,21 +1556,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ } } - arrange_posix_perms(fsp->fsp_name,&list_head ); - - if( DEBUGLVL( 10 ) ) { - char *acl_text = sys_acl_to_text( posix_acl, NULL); - - dbgtext("canonicalize_acl: processed acl %s\n", acl_text == NULL ? "NULL" : acl_text ); - if (acl_text) - sys_acl_free_text(acl_text); - - dbgtext("canonicalize_acl: ace entries after arrange :\n"); - - for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { - print_canon_ace(ace, ace_count); - } - } + print_canon_ace_list( "canonicalize_acl: ace entries after arrange", list_head ); return list_head; @@ -1784,6 +1798,16 @@ posix perms.\n", fsp->fsp_name )); return True; } +static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + if (a1->type == a2->type) + return 0; + + if (a1->type == SEC_ACE_TYPE_ACCESS_DENIED && a2->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + return -1; + return 1; +} + /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns the size needed to return the @@ -1899,6 +1923,13 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) init_sec_ace(&nt_ace_list[num_aces++], &ace->sid, nt_acl_type, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); } + + /* + * Sort to force deny entries to the front. + */ + + if (num_acls + num_dir_acls) + qsort( nt_ace_list, num_acls + num_dir_acls, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp); } if (num_acls) { @@ -2011,6 +2042,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); + if ((file_ace_list == NULL) && (dir_ace_list == NULL)) { + /* W2K traverse DACL set - ignore. */ + return True; + } + if (!acl_perms) { DEBUG(3,("set_nt_acl: cannot set permissions\n")); free_canon_ace_list(file_ace_list); -- cgit From da8805b377e361a7cab399b3c786a25f7175e7cf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2001 02:14:08 +0000 Subject: groupdb/mapping.c: include/proto.h: Fix missing (void) in proto. rpc_server/srv_samr_nt.c: Fix user private group problem by filtering out groups that clash with users. smbd/posix_acls.c: Ensure default ACE's are sensible. utils/pdbedit.c: Fix from Simo Sorce. Jeremy. (This used to be commit 29414fe0d6665642d9b5f88a35e712426376c47f) --- source3/smbd/posix_acls.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ddf4d06b0e..fe1c02e46c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -425,6 +425,8 @@ static mode_t get_default_ace_mode(files_struct *fsp, int type) mode_t force_mode = lp_force_dir_security_mode(SNUM(fsp->conn)); mode_t mode = 0; + DEBUG(10,("get_default_ace_mode: force_mode = 0%o\n", (int)force_mode )); + switch(type) { case S_IRUSR: mode |= (force_mode & S_IRUSR) ? S_IRUSR : 0; @@ -443,6 +445,8 @@ static mode_t get_default_ace_mode(files_struct *fsp, int type) break; } + DEBUG(10,("get_default_ace_mode: returning mode = 0%o\n", (int)mode )); + return mode; } @@ -489,7 +493,9 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->unix_ug.uid = pst->st_uid; pace->sid = *pfile_owner_sid; /* Ensure owner has read access. */ - pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRUSR): S_IRUSR; + pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRUSR) : S_IRUSR; + if (pace->perms == (mode_t)0) + pace->perms = S_IRUSR; pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); -- cgit From a44721750944af9beb46f169a49a439b614a8622 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2001 03:12:58 +0000 Subject: Two OS/2 printer fixes from Jim McDonough @ IBM. First one adds a new info level into the lanman printing and an ioctl to the trans2 code. Andrew - this uses ASCII only. It looks ok to me but please check ! Second one adds a parameter "os2 driver map" that allows OS/2 driver names to be mapped. Jeremy. (This used to be commit da79b519e0b6b4317d7fb5260d74e0e74a7e0b46) --- source3/smbd/lanman.c | 71 ++++++++++++++++++++++++++++++++++++++++++--------- source3/smbd/trans2.c | 67 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 121 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 45ce286634..e9df2ed41e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -474,7 +474,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z",queue->file); /* pszComment */ } - if (uLevel == 2 || uLevel == 3) { + if (uLevel == 2 || uLevel == 3 || uLevel == 4) { PACKI(desc,"W",queue->priority); /* uPriority */ PACKS(desc,"z",queue->user); /* pszUserName */ PACKI(desc,"W",n+1); /* uPosition */ @@ -494,6 +494,17 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z","NULL"); /* pszDriverName */ PackDriverData(desc); /* pDriverData */ PACKS(desc,"z",""); /* pszPrinterName */ + } else if (uLevel == 4) { /* OS2 */ + PACKS(desc,"z",""); /* pszSpoolFileName */ + PACKS(desc,"z",""); /* pszPortName */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",0); /* ulPagesSpooled */ + PACKI(desc,"D",0); /* ulPagesSent */ + PACKI(desc,"D",0); /* ulPagesPrinted */ + PACKI(desc,"D",0); /* ulTimePrinted */ + PACKI(desc,"D",0); /* ulExtendJobStatus */ + PACKI(desc,"D",0); /* ulStartPage */ + PACKI(desc,"D",0); /* ulEndPage */ } } } @@ -859,7 +870,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; - + char* tmpdata=NULL; + memset((char *)&status,'\0',sizeof(status)); memset((char *)&desc,'\0',sizeof(desc)); @@ -907,9 +919,19 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, count = print_queue_status(snum, &queue,&status); } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; + if (mdrcnt > 0) { + *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *) malloc (desc.buflen); + } + if (init_package(&desc,1,count)) { desc.subcount = count; fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); @@ -948,7 +970,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); if (queue) free(queue); - + if (tmpdata) free (tmpdata); + return(True); } @@ -2000,6 +2023,7 @@ static int check_printjob_info(struct pack_desc* desc, case 1: desc->format = "WB21BB16B10zWWzDDz"; break; case 2: desc->format = "WWzWWDDzz"; break; case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; + case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break; default: return False; } if (strcmp(desc->format,id) != 0) return False; @@ -2755,6 +2779,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; + char *tmpdata=NULL; uLevel = SVAL(p,2); @@ -2776,9 +2801,19 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para for (i = 0; i < count; i++) { if (queue[i].job == job) break; } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; + + if (mdrcnt > 0) { + *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)malloc ( desc.buflen ); + } if (init_package(&desc,1,0)) { if (i < count) { @@ -2798,6 +2833,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para SSVAL(*rparam,4,desc.neededlen); if (queue) free(queue); + if (tmpdata) free(tmpdata); DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); return(True); @@ -2932,6 +2968,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par int uLevel; struct pack_desc desc; int snum; + char *tmpdata=NULL; memset((char *)&desc,'\0',sizeof(desc)); @@ -2959,9 +2996,18 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par desc.neededlen = 0; } else { - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; + if (mdrcnt > 0) { + *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)malloc ( desc.buflen ); + } if (init_package(&desc,1,0)) { fill_printdest_info(conn,snum,uLevel,&desc); } @@ -2975,6 +3021,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par SSVAL(*rparam,4,desc.neededlen); DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); + if (tmpdata) free (tmpdata); return(True); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0489e23040..b9c8ab086c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -30,6 +30,7 @@ extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; extern uint32 global_client_caps; +extern pstring global_myname; /**************************************************************************** Send the required number of replies back. @@ -2193,6 +2194,41 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, return(-1); } +#define LMCAT_SPL 0x53 +#define LMFUNC_GETJOBID 0x60 + +/**************************************************************************** + reply to a TRANS2_IOCTL - used for OS/2 printing. +****************************************************************************/ + +static int call_trans2ioctl(connection_struct *conn, char* inbuf, + char* outbuf, int length, int bufsize, + char** pparams, char** ppdata) +{ + char *pdata = *ppdata; + files_struct *fsp = file_fsp(inbuf,smb_vwv15); + + if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && + (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + pdata = Realloc(*ppdata, 32); + if(pdata == NULL) { + return(ERROR(ERRDOS,ERRnomem)); + } + *ppdata = pdata; + + /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 + CAN ACCEPT THIS IN UNICODE. JRA. */ + + SSVAL(pdata,0,fsp->print_jobid); /* Job number */ + StrnCpy(pdata+2, global_myname, 15); /* Our NetBIOS name */ + StrnCpy(pdata+18, lp_servicename(SNUM(conn)), 13); /* Service name */ + send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); + return(-1); + } else { + DEBUG(2,("Unknown TRANS2_IOCTL\n")); + return(ERROR(ERRSRV,ERRerror)); + } +} /**************************************************************************** reply to a SMBfindclose (stop trans2 directory search) @@ -2301,9 +2337,24 @@ int reply_trans2(connection_struct *conn, /* All trans2 messages we handle have smb_sucnt == 1 - ensure this is so as a sanity check */ if (suwcnt != 1) { - DEBUG(2,("Invalid smb_sucnt in trans2 call\n")); - END_PROFILE(SMBtrans2); - return(ERROR(ERRSRV,ERRerror)); + /* + * Need to have rc=0 for ioctl to get job id for OS/2. + * Network printing will fail if function is not successful. + * Similar function in reply.c will be used if protocol + * is LANMAN1.0 instead of LM1.2X002. + * Until DosPrintSetJobInfo with PRJINFO3 is supported, + * outbuf doesn't have to be set(only job id is used). + */ + if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) && + (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && + (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + DEBUG(2,("Got Trans2 DevIOctl jobid\n")); + } else { + DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt)); + DEBUG(2,("Transaction is %d\n",tran_call)); + END_PROFILE(SMBtrans2); + return(ERROR(ERRSRV,ERRerror)); + } } /* Allocate the space for the maximum needed parameters and data */ @@ -2466,10 +2517,16 @@ int reply_trans2(connection_struct *conn, case TRANSACT2_GET_DFS_REFERRAL: START_PROFILE_NESTED(Trans2_get_dfs_referral); - outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, - bufsize, ¶ms, &data); + outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, + bufsize, ¶ms, &data); END_PROFILE_NESTED(Trans2_get_dfs_referral); break; + case TRANSACT2_IOCTL: + START_PROFILE_NESTED(Trans2_ioctl); + outsize = call_trans2ioctl(conn,inbuf,outbuf,length, + bufsize,¶ms,&data); + END_PROFILE_NESTED(Trans2_ioctl); + break; default: /* Error in request */ DEBUG(2,("Unknown request %d in trans2 call\n", tran_call)); -- cgit From 19faeac3472539f4fb5713f777d85cd5e66fd675 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2001 18:14:22 +0000 Subject: Made the fixes Andrew suggested to asci string code to use srvstr_push. Jeremy. (This used to be commit 1391aa6a6fbe8391a4421f5770da40556f011bb8) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b9c8ab086c..58e8056c31 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2220,8 +2220,8 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, CAN ACCEPT THIS IN UNICODE. JRA. */ SSVAL(pdata,0,fsp->print_jobid); /* Job number */ - StrnCpy(pdata+2, global_myname, 15); /* Our NetBIOS name */ - StrnCpy(pdata+18, lp_servicename(SNUM(conn)), 13); /* Service name */ + srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_CONVERT|STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ + srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_CONVERT|STR_ASCII|STR_TERMINATE); /* Service name */ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); return(-1); } else { -- cgit From cd4fea0098ce5200d764f51bef16980f972925ff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2001 20:41:22 +0000 Subject: More unused variables. Jeremy. (This used to be commit 38b19fad2851a65268b31c7e0240ed36a8407be4) --- source3/smbd/posix_acls.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index fe1c02e46c..54973d17a7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1428,9 +1428,6 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ canon_ace *list_head = NULL; canon_ace *ace = NULL; canon_ace *next_ace = NULL; - canon_ace *owner_ace = NULL; - canon_ace *group_ace = NULL; - canon_ace *other_ace = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; size_t ace_count; @@ -1523,17 +1520,6 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ ace->unix_ug = unix_ug; ace->owner_type = owner_type; - /* - * Remember the user/group/other ACE entries. - */ - - if (tagtype == SMB_ACL_USER_OBJ) - owner_ace = ace; - else if (tagtype == SMB_ACL_GROUP_OBJ) - group_ace = ace; - else if (tagtype == SMB_ACL_OTHER) - other_ace = ace; - DLIST_ADD(list_head, ace); } -- cgit From 162218259f59f61746a3a80bde372646f2107140 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Mar 2001 05:43:04 +0000 Subject: smbd/posix_acls.c: Sync up with 2.2 changes - don't return deny ACE's. smbd/vfs.c: Don't call [f]chmod_acl if no acl support. Jeremy. (This used to be commit 83f52394e688b4be3ac4cef67d8980a5b8ed3192) --- source3/smbd/posix_acls.c | 81 ++++++++--------------------------------------- source3/smbd/vfs.c | 5 +++ 2 files changed, 19 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 54973d17a7..325fd3b716 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -289,21 +289,7 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon if ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS) { nt_mask = UNIX_ACCESS_RWX; } else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) { - /* - * Here we differentiate between the owner and any other user. - */ - if (sid_equal(powner_sid, &ace->sid)) { - nt_mask = UNIX_ACCESS_NONE; - } else { - /* Not owner, no access. */ - if (ace->type == SMB_ACL_USER) { - /* user objects can be deny entries. */ - *pacl_type = SEC_ACE_TYPE_ACCESS_DENIED; - nt_mask = GENERIC_ALL_ACCESS; - } - else - nt_mask = UNIX_ACCESS_NONE; - } + nt_mask = UNIX_ACCESS_NONE; } else { nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); @@ -1255,9 +1241,6 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) canon_ace *owner_ace = NULL; canon_ace *other_ace = NULL; canon_ace *ace = NULL; - mode_t owner_perms = 0; - mode_t group_perms = 0; - mode_t other_perms = 0; for (ace = list_head; ace; ace = ace->next) { if (ace->type == SMB_ACL_USER_OBJ) @@ -1265,9 +1248,6 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) else if (ace->type == SMB_ACL_OTHER) { /* Last ace - this is "other" */ other_ace = ace; - } else { - /* Get the union of all the group and supplementary user perms. */ - group_perms |= ace->perms; } } @@ -1290,47 +1270,6 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) DLIST_DEMOTE(list_head, other_ace, ace); } - owner_perms = owner_ace->perms; - other_perms = other_ace->perms; - - /* - * We have to be clever here. NT4.x won't display anything other - * Than an "Everyone, No access" DENY acl. Truncate blank perms - * from the end, but we can't truncate blank permissions from - * anywhere except the end, as they have an effect on allowing access - * under POSIX. - */ - - if ((owner_perms || group_perms) && !other_perms) { - DLIST_REMOVE(list_head, other_ace); - safe_free(other_ace); - } - - if (owner_perms && !group_perms && !other_perms) { - /* Free everything except the list head. */ - free_canon_ace_list(owner_ace->next); - owner_ace->next = NULL; - } - - if (!owner_perms && !group_perms && !other_perms) { - /* - * Special case - no one has any access. - * Return a 1 element ACL - other has "no access". - */ - - if (owner_ace->next) { - free_canon_ace_list(owner_ace->next); - owner_ace->next = NULL; - } - - owner_ace->type = SMB_ACL_OTHER; - owner_ace->sid = global_sid_World; - owner_ace->unix_ug.world = -1; - owner_ace->owner_type = WORLD_ACE; - owner_ace->attr = DENY_ACE; - owner_ace->perms = 0; - } - /* We have probably changed the head of the list. */ *pp_list_head = list_head; @@ -1391,13 +1330,13 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu mode = psbuf->st_mode; owner_ace->perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR); - owner_ace->attr = owner_ace->perms ? ALLOW_ACE : DENY_ACE; + owner_ace->attr = ALLOW_ACE; group_ace->perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); - group_ace->attr = group_ace->perms ? ALLOW_ACE : DENY_ACE; + group_ace->attr = ALLOW_ACE; other_ace->perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH); - other_ace->attr = other_ace->perms ? ALLOW_ACE : DENY_ACE; + other_ace->attr = ALLOW_ACE; DLIST_ADD(list_head, other_ace); DLIST_ADD(list_head, group_ace); @@ -2187,11 +2126,15 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) int chmod_acl(char *name, mode_t mode) { + int saved_errno = errno; SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS)) == NULL) + if ((posix_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS)) == NULL) { + if (errno == ENOSYS) + errno = saved_errno; return -1; + } if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) goto done; @@ -2211,11 +2154,15 @@ int chmod_acl(char *name, mode_t mode) int fchmod_acl(int fd, mode_t mode) { + int saved_errno = errno; SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = sys_acl_get_fd(fd)) == NULL) + if ((posix_acl = sys_acl_get_fd(fd)) == NULL) { + if (errno == ENOSYS) + errno = saved_errno; return -1; + } if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) goto done; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b41e1f27fd..f5bd057ca6 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -75,8 +75,13 @@ struct vfs_ops default_vfs_ops = { vfswrap_fset_nt_acl, vfswrap_set_nt_acl, +#if defined(HAVE_NO_ACLS) + NULL, + NULL +#else vfswrap_chmod_acl, vfswrap_fchmod_acl +#endif }; /**************************************************************************** -- cgit From c4cfc3629038aa6c2d57d630452c538c737d1203 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Mar 2001 17:58:05 +0000 Subject: Ensure get/set NT ACL code is redirected through vfs. Jeremy. (This used to be commit d43d907c38008bb02042cb4bc2d899f62bdc115b) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5d28f8bc3e..58b484f44d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1030,7 +1030,7 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_i if (psd->off_dacl==0) security_info_sent &= ~DACL_SECURITY_INFORMATION; - ret = set_nt_acl( fsp, security_info_sent, psd); + ret = fsp->conn->vfs_ops.fset_nt_acl( fsp, fsp->fd, security_info_sent, psd); if (!ret) { talloc_destroy(mem_ctx); @@ -1523,7 +1523,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Get the permissions to return. */ - if((sd_size = get_nt_acl(fsp, &psd)) == 0) + if((sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd)) == 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size)); -- cgit From e670b3564c3c12baaab0e988f155a86b9437f66e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Mar 2001 19:18:06 +0000 Subject: smbd/posix_acls.c: Saving and restoring errno here is the wrong place. Moved it to the places where [f]chmod_acl is called instead. Jeremy. (This used to be commit 641ada44ae6429761c1fd0dbcafabc69f897fac7) --- source3/smbd/open.c | 9 ++++++--- source3/smbd/posix_acls.c | 13 ++----------- source3/smbd/vfs-wrap.c | 8 +++++++- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index afcaeff1ae..c601121459 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -194,9 +194,12 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * Take care of inherited ACLs on created files. JRA. */ - if ((flags & O_CREAT) && (conn->vfs_ops.fchmod_acl != NULL)) - conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode); - + if ((flags & O_CREAT) && (conn->vfs_ops.fchmod_acl != NULL)) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + errno = saved_errno; /* Ignore ENOSYS */ + } + return True; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 325fd3b716..b7ba8e44ef 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1236,7 +1236,6 @@ static int map_acl_perms_to_permset(mode_t mode, SMB_ACL_PERMSET_T *p_permset) static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) { - extern DOM_SID global_sid_World; canon_ace *list_head = *pp_list_head; canon_ace *owner_ace = NULL; canon_ace *other_ace = NULL; @@ -2126,15 +2125,11 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) int chmod_acl(char *name, mode_t mode) { - int saved_errno = errno; SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS)) == NULL) { - if (errno == ENOSYS) - errno = saved_errno; + if ((posix_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS)) == NULL) return -1; - } if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) goto done; @@ -2154,15 +2149,11 @@ int chmod_acl(char *name, mode_t mode) int fchmod_acl(int fd, mode_t mode) { - int saved_errno = errno; SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = sys_acl_get_fd(fd)) == NULL) { - if (errno == ENOSYS) - errno = saved_errno; + if ((posix_acl = sys_acl_get_fd(fd)) == NULL) return -1; - } if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) goto done; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 8750f71151..a4057eb7ce 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -115,8 +115,10 @@ int vfswrap_mkdir(connection_struct *conn, char *path, mode_t mode) * group permission bits. This is not what we want, as it will * mess up any inherited ACL bits that were set. JRA. */ + int saved_errno = errno; /* We may get ENOSYS */ if (conn->vfs_ops.chmod_acl != NULL) { - conn->vfs_ops.chmod_acl(conn, path, mode); + if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS)) + errno = saved_errno; } } @@ -351,11 +353,15 @@ int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) * group owner bits directly. JRA. */ + if (conn->vfs_ops.chmod_acl != NULL) { + int saved_errno = errno; /* We might get ENOSYS */ if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) { END_PROFILE(syscall_chmod); return result; } + /* Error - return the old errno. */ + errno = saved_errno; } result = chmod(path, mode); -- cgit From fab898f9cd06d136efbd2f1de047c744bdd1fd07 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Mar 2001 22:20:43 +0000 Subject: Patch from Sean.Batt@anu.edu.au to ensure error reporting is done before any code that could modify errno is called. Jeremy. (This used to be commit 109a174de9e23ccc89ae17d6b5b425b5947c8565) --- source3/smbd/error.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index d879f9a93c..472a8d8fd1 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -119,6 +119,9 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int int cmd = CVAL(inbuf,smb_com); int flgs2 = SVAL(outbuf,smb_flg2); + if (errno != 0) + DEBUG(3,("error string = %s\n",strerror(errno))); + if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) { SIVAL(outbuf,smb_rcls,error_code); @@ -139,8 +142,5 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int } - if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); - return(outsize); } -- cgit From 7bdf197e6237704af2ecf2718ce482d0dd840365 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Mar 2001 23:21:29 +0000 Subject: Patch from Massimo Sivilotti to log remote machine/ip on connection fail. Jeremy. (This used to be commit 07cee46d1de1caaf6f9f1b6139dd21bcc5d67e8e) --- source3/smbd/service.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2c03d4e514..849ccba5fb 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -557,7 +557,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int } if (vfs_ChDir(conn,conn->connectpath) != 0) { - DEBUG(0,("Can't change directory to %s (%s)\n", + DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", + remote_machine, conn->client_address, conn->connectpath,strerror(errno))); unbecome_user(); yield_connection(conn, -- cgit From bcdb9496e81c4d00a522ce57406dec08f6df9b34 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Mar 2001 00:24:40 +0000 Subject: Bail out early if null passwords and lp_null_passwords not set. Jeremy. (This used to be commit 7c718fc85e3dbfaf0195e352d06a8c682a6036fc) --- source3/smbd/password.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 12f7385f06..fa973dd720 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -586,6 +586,11 @@ return True if the password is correct, False otherwise ****************************************************************************/ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) { + if ((pwlen == 0) && !lp_null_passwords()) { + DEBUG(4,("Null passwords not allowed.\n")); + return False; + } + if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { /* if 24 bytes long assume it is an encrypted password */ -- cgit From 303c152f03c5cb4a8872673b548a7ee4caae2eb3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Mar 2001 02:43:34 +0000 Subject: Added NFS quota support for Solaris 5.x from Alan Romeril . sun1.samba.org is down at the moment so I can't test the compile on this. I'm sure Solaris people using quotas will scream if I've meesed anything up :-). Jeremy. (This used to be commit 3d2c59bfe0bc30d8cecf0af81b74d4232b09bdb2) --- source3/smbd/quotas.c | 391 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 279 insertions(+), 112 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 7808d269f9..57d7e36f10 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -250,6 +250,166 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #include #endif +#if defined(SUNOS5) + +/**************************************************************************** + Allows querying of remote hosts for quotas on NFS mounted shares. + Supports normal NFS and AMD mounts. + Alan Romeril July 2K. +****************************************************************************/ + +#include +#include +#include +#include +#include + +static int quotastat; + +static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) +{ + if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN )) + return(0); + if (!xdr_int(xdrsp, &args->gqa_uid)) + return(0); + return (1); +} + +static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) +{ + gqr_status status; + union { + rquota gqr_rquota; + } getquota_rslt_u; + + if (!xdr_int(xdrsp, "astat)) { + DEBUG(6,("nfs_quotas: Status bad or zero\n")); + return 0; + } + if (!xdr_int32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { + DEBUG(6,("nfs_quotas: Block size bad or zero\n")); + return 0; + } + if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) { + DEBUG(6,("nfs_quotas: Active bad or zero\n")); + return 0; + } + if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { + DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); + return 0; + } + if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { + DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); + return 0; + } + if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { + DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); + return 0; + } + return (1); +} + +/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ +static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + uid_t uid = euser_id; + struct dqblk D; + char *mnttype = nfspath; + CLIENT *clnt; + struct getquota_rslt gqr; + struct getquota_args args; + char *cutstr, *pathname, *host, *testpath; + int len; + static struct timeval timeout = {2,0}; + enum clnt_stat clnt_stat; + + len=strcspn(mnttype, ":"); + pathname=strstr(mnttype, ":"); + cutstr = (char *) malloc(sizeof(char) * len ); + if (!cutstr) + return False; + + host = strncat(cutstr,mnttype, sizeof(char) * len ); + DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); + DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); + testpath=strchr(mnttype, ':'); + args.gqa_pathp = testpath+1; + args.gqa_uid = uid; + + DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" +network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp")); + + if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) { + clnt->cl_auth = authunix_create_default(); + DEBUG(9,("nfs_quotas: auth_success\n")); + + clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, + xdr_getquota_rslt, (caddr_t)&gqr, timeout); + if (clnt_stat == RPC_SUCCESS) + DEBUG(9,("nfs_quotas: rpccall_success\n")); + }; + + + /* + * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is + * no quota set, and 3 if no permission to get the quota. If 0 or 3 return + * something sensible. + */ + + if (quotastat == 1) { + DEBUG(9,("nfs_quotas: Good quota data\n")); + D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; + D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; + D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; + } + + if (quotastat == 0 || quotastat == 3) { + D.dqb_bsoftlimit = 1; + D.dqb_curblocks = 1; + DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); + } + + if (quotastat == 2) { + DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + free(cutstr); + return(False); + } + + DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" \ +bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", + quotastat, + gqr.getquota_rslt_u.gqr_rquota.rq_bsize, + gqr.getquota_rslt_u.gqr_rquota.rq_active, + gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit, + gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit, + gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)); + + *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize; + *dsize = D.dqb_bsoftlimit; + + if (D.dqb_curblocks == D.dqb_curblocks == 1) + *bsize = 512; + + if (D.dqb_curblocks > D.dqb_bsoftlimit) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + + DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize \ +%.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize)); + + free(cutstr); + DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); + return(True); +} +#endif + /**************************************************************************** try to get the disk space from disk quotas (SunOS & Solaris2 version) Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). @@ -257,147 +417,154 @@ Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - uid_t euser_id; - int ret; - struct dqblk D; + uid_t euser_id; + int ret; + struct dqblk D; #if defined(SUNOS5) - struct quotctl command; - int file; - static struct mnttab mnt; - static pstring name; - pstring devopt; + struct quotctl command; + int file; + static struct mnttab mnt; + static pstring name; + pstring devopt; #else /* SunOS4 */ - struct mntent *mnt; - static pstring name; + struct mntent *mnt; + static pstring name; #endif - FILE *fd; - SMB_STRUCT_STAT sbuf; - SMB_DEV_T devno ; - static SMB_DEV_T devno_cached = 0 ; - static int found ; + FILE *fd; + SMB_STRUCT_STAT sbuf; + SMB_DEV_T devno ; + static SMB_DEV_T devno_cached = 0 ; + static int found ; - euser_id = geteuid(); + euser_id = geteuid(); - if ( sys_stat(path,&sbuf) == -1 ) - return(False) ; + if ( sys_stat(path,&sbuf) == -1 ) + return(False) ; - devno = sbuf.st_dev ; - DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); - if ( devno != devno_cached ) { - devno_cached = devno ; + devno = sbuf.st_dev ; + DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); + if ( devno != devno_cached ) { + devno_cached = devno ; #if defined(SUNOS5) - if ((fd = sys_fopen(MNTTAB, "r")) == NULL) - return(False) ; + if ((fd = sys_fopen(MNTTAB, "r")) == NULL) + return(False) ; - found = False ; - slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); - while (getmntent(fd, &mnt) == 0) { - if( !hasmntopt(&mnt, devopt) ) - continue; - - DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); - - /* quotas are only on vxfs, UFS or NFS, but nfs is not supported here */ - if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || - strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) - { - found = True ; - break ; - } - } + found = False ; + slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); + while (getmntent(fd, &mnt) == 0) { + if( !hasmntopt(&mnt, devopt) ) + continue; + + DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); + + /* quotas are only on vxfs, UFS or NFS */ + if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || + strcmp( mnt.mnt_fstype, "nfs" ) == 0 ) || + strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) { + found = True ; + break; + } + } - pstrcpy(name,mnt.mnt_mountp) ; - pstrcat(name,"/quotas") ; - fclose(fd) ; + pstrcpy(name,mnt.mnt_mountp) ; + pstrcat(name,"/quotas") ; + fclose(fd) ; #else /* SunOS4 */ - if ((fd = setmntent(MOUNTED, "r")) == NULL) - return(False) ; + if ((fd = setmntent(MOUNTED, "r")) == NULL) + return(False) ; - found = False ; - while ((mnt = getmntent(fd)) != NULL) { - if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", - mnt->mnt_dir,sbuf.st_dev)); - if (sbuf.st_dev == devno) { - found = True ; - break ; - } - } + found = False ; + while ((mnt = getmntent(fd)) != NULL) { + if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) + continue ; + DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); + if (sbuf.st_dev == devno) { + found = True ; + break; + } + } - pstrcpy(name,mnt->mnt_fsname) ; - endmntent(fd) ; + pstrcpy(name,mnt->mnt_fsname) ; + endmntent(fd) ; #endif - - } + } - if ( ! found ) - return(False) ; + if ( ! found ) + return(False) ; - save_re_uid(); - set_effective_uid(0); + save_re_uid(); + set_effective_uid(0); #if defined(SUNOS5) - DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); - if((file=sys_open(name, O_RDONLY,0))<0) { - restore_re_uid(); - return(False); - } - command.op = Q_GETQUOTA; - command.uid = euser_id; - command.addr = (caddr_t) &D; - ret = ioctl(file, Q_QUOTACTL, &command); - close(file); + if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) { + BOOL retval; + DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); + retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); + restore_re_uid(); + return retval; + } + + DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); + if((file=sys_open(name, O_RDONLY,0))<0) { + restore_re_uid(); + return(False); + } + command.op = Q_GETQUOTA; + command.uid = euser_id; + command.addr = (caddr_t) &D; + ret = ioctl(file, Q_QUOTACTL, &command); + close(file); #else - DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); - ret = quotactl(Q_GETQUOTA, name, euser_id, &D); + DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); + ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - restore_re_uid(); + restore_re_uid(); - if (ret < 0) { - DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); + if (ret < 0) { + DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); #if defined(SUNOS5) && defined(VXFS_QUOTA) - /* If normal quotactl() fails, try vxfs private calls */ - set_effective_uid(euser_id); - DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); - if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { - ret = disk_quotas_vxfs(name, path, bsize, dfree, dsize); - return(ret); - } + /* If normal quotactl() fails, try vxfs private calls */ + set_effective_uid(euser_id); + DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); + if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { + BOOL retval; + retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize); + return(retval); + } #else - return(False); + return(False); #endif - } + } - /* If softlimit is zero, set it equal to hardlimit. - */ + /* If softlimit is zero, set it equal to hardlimit. + */ - if (D.dqb_bsoftlimit==0) - D.dqb_bsoftlimit = D.dqb_bhardlimit; - - /* Use softlimit to determine disk space. A user exceeding the quota is told - * that there's no space left. Writes might actually work for a bit if the - * hardlimit is set higher than softlimit. Effectively the disk becomes - * made of rubber latex and begins to expand to accommodate the user :-) - */ - - if (D.dqb_bsoftlimit==0) - return(False); - *bsize = DEV_BSIZE; - *dsize = D.dqb_bsoftlimit; - - if (D.dqb_curblocks > D.dqb_bsoftlimit) { - *dfree = 0; - *dsize = D.dqb_curblocks; - } else - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + if (D.dqb_bsoftlimit==0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; + + /* Use softlimit to determine disk space. A user exceeding the quota is told + * that there's no space left. Writes might actually work for a bit if the + * hardlimit is set higher than softlimit. Effectively the disk becomes + * made of rubber latex and begins to expand to accommodate the user :-) + */ + + if (D.dqb_bsoftlimit==0) + return(False); + *bsize = DEV_BSIZE; + *dsize = D.dqb_bsoftlimit; + + if (D.dqb_curblocks > D.dqb_bsoftlimit) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", - path,(double)*bsize,(double)*dfree,(double)*dsize)); + DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", + path,(double)*bsize,(double)*dfree,(double)*dsize)); - return(True); + return(True); } -- cgit From c3eb491c9233c37c5d96cb6712ed8ccea1bd606c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Mar 2001 08:08:04 +0000 Subject: Removed NFS quotas code for Solaris as Alan wants to re-write it. Jeremy. (This used to be commit 13c9823eb19baa4b1262ad0fd416d9ecbc92b160) --- source3/smbd/quotas.c | 391 +++++++++++++++----------------------------------- 1 file changed, 112 insertions(+), 279 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 57d7e36f10..7808d269f9 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -250,166 +250,6 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #include #endif -#if defined(SUNOS5) - -/**************************************************************************** - Allows querying of remote hosts for quotas on NFS mounted shares. - Supports normal NFS and AMD mounts. - Alan Romeril July 2K. -****************************************************************************/ - -#include -#include -#include -#include -#include - -static int quotastat; - -static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) -{ - if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN )) - return(0); - if (!xdr_int(xdrsp, &args->gqa_uid)) - return(0); - return (1); -} - -static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) -{ - gqr_status status; - union { - rquota gqr_rquota; - } getquota_rslt_u; - - if (!xdr_int(xdrsp, "astat)) { - DEBUG(6,("nfs_quotas: Status bad or zero\n")); - return 0; - } - if (!xdr_int32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { - DEBUG(6,("nfs_quotas: Block size bad or zero\n")); - return 0; - } - if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) { - DEBUG(6,("nfs_quotas: Active bad or zero\n")); - return 0; - } - if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { - DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); - return 0; - } - if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { - DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); - return 0; - } - if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { - DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); - return 0; - } - return (1); -} - -/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ -static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -{ - uid_t uid = euser_id; - struct dqblk D; - char *mnttype = nfspath; - CLIENT *clnt; - struct getquota_rslt gqr; - struct getquota_args args; - char *cutstr, *pathname, *host, *testpath; - int len; - static struct timeval timeout = {2,0}; - enum clnt_stat clnt_stat; - - len=strcspn(mnttype, ":"); - pathname=strstr(mnttype, ":"); - cutstr = (char *) malloc(sizeof(char) * len ); - if (!cutstr) - return False; - - host = strncat(cutstr,mnttype, sizeof(char) * len ); - DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); - DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); - testpath=strchr(mnttype, ':'); - args.gqa_pathp = testpath+1; - args.gqa_uid = uid; - - DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" -network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp")); - - if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) { - clnt->cl_auth = authunix_create_default(); - DEBUG(9,("nfs_quotas: auth_success\n")); - - clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, - xdr_getquota_rslt, (caddr_t)&gqr, timeout); - if (clnt_stat == RPC_SUCCESS) - DEBUG(9,("nfs_quotas: rpccall_success\n")); - }; - - - /* - * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is - * no quota set, and 3 if no permission to get the quota. If 0 or 3 return - * something sensible. - */ - - if (quotastat == 1) { - DEBUG(9,("nfs_quotas: Good quota data\n")); - D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; - D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; - D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; - } - - if (quotastat == 0 || quotastat == 3) { - D.dqb_bsoftlimit = 1; - D.dqb_curblocks = 1; - DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); - } - - if (quotastat == 2) { - DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - free(cutstr); - return(False); - } - - DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" \ -bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", - quotastat, - gqr.getquota_rslt_u.gqr_rquota.rq_bsize, - gqr.getquota_rslt_u.gqr_rquota.rq_active, - gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit, - gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit, - gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)); - - *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize; - *dsize = D.dqb_bsoftlimit; - - if (D.dqb_curblocks == D.dqb_curblocks == 1) - *bsize = 512; - - if (D.dqb_curblocks > D.dqb_bsoftlimit) { - *dfree = 0; - *dsize = D.dqb_curblocks; - } else - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - - DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize \ -%.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize)); - - free(cutstr); - DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); - return(True); -} -#endif - /**************************************************************************** try to get the disk space from disk quotas (SunOS & Solaris2 version) Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). @@ -417,154 +257,147 @@ Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - uid_t euser_id; - int ret; - struct dqblk D; + uid_t euser_id; + int ret; + struct dqblk D; #if defined(SUNOS5) - struct quotctl command; - int file; - static struct mnttab mnt; - static pstring name; - pstring devopt; + struct quotctl command; + int file; + static struct mnttab mnt; + static pstring name; + pstring devopt; #else /* SunOS4 */ - struct mntent *mnt; - static pstring name; + struct mntent *mnt; + static pstring name; #endif - FILE *fd; - SMB_STRUCT_STAT sbuf; - SMB_DEV_T devno ; - static SMB_DEV_T devno_cached = 0 ; - static int found ; + FILE *fd; + SMB_STRUCT_STAT sbuf; + SMB_DEV_T devno ; + static SMB_DEV_T devno_cached = 0 ; + static int found ; - euser_id = geteuid(); + euser_id = geteuid(); - if ( sys_stat(path,&sbuf) == -1 ) - return(False) ; + if ( sys_stat(path,&sbuf) == -1 ) + return(False) ; - devno = sbuf.st_dev ; - DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); - if ( devno != devno_cached ) { - devno_cached = devno ; + devno = sbuf.st_dev ; + DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); + if ( devno != devno_cached ) { + devno_cached = devno ; #if defined(SUNOS5) - if ((fd = sys_fopen(MNTTAB, "r")) == NULL) - return(False) ; + if ((fd = sys_fopen(MNTTAB, "r")) == NULL) + return(False) ; - found = False ; - slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); - while (getmntent(fd, &mnt) == 0) { - if( !hasmntopt(&mnt, devopt) ) - continue; - - DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); - - /* quotas are only on vxfs, UFS or NFS */ - if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || - strcmp( mnt.mnt_fstype, "nfs" ) == 0 ) || - strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) { - found = True ; - break; - } - } + found = False ; + slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); + while (getmntent(fd, &mnt) == 0) { + if( !hasmntopt(&mnt, devopt) ) + continue; + + DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); + + /* quotas are only on vxfs, UFS or NFS, but nfs is not supported here */ + if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || + strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) + { + found = True ; + break ; + } + } - pstrcpy(name,mnt.mnt_mountp) ; - pstrcat(name,"/quotas") ; - fclose(fd) ; + pstrcpy(name,mnt.mnt_mountp) ; + pstrcat(name,"/quotas") ; + fclose(fd) ; #else /* SunOS4 */ - if ((fd = setmntent(MOUNTED, "r")) == NULL) - return(False) ; + if ((fd = setmntent(MOUNTED, "r")) == NULL) + return(False) ; - found = False ; - while ((mnt = getmntent(fd)) != NULL) { - if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); - if (sbuf.st_dev == devno) { - found = True ; - break; - } - } + found = False ; + while ((mnt = getmntent(fd)) != NULL) { + if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) + continue ; + DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", + mnt->mnt_dir,sbuf.st_dev)); + if (sbuf.st_dev == devno) { + found = True ; + break ; + } + } - pstrcpy(name,mnt->mnt_fsname) ; - endmntent(fd) ; + pstrcpy(name,mnt->mnt_fsname) ; + endmntent(fd) ; #endif - } + + } - if ( ! found ) - return(False) ; + if ( ! found ) + return(False) ; - save_re_uid(); - set_effective_uid(0); + save_re_uid(); + set_effective_uid(0); #if defined(SUNOS5) - if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) { - BOOL retval; - DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); - retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); - restore_re_uid(); - return retval; - } - - DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); - if((file=sys_open(name, O_RDONLY,0))<0) { - restore_re_uid(); - return(False); - } - command.op = Q_GETQUOTA; - command.uid = euser_id; - command.addr = (caddr_t) &D; - ret = ioctl(file, Q_QUOTACTL, &command); - close(file); + DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); + if((file=sys_open(name, O_RDONLY,0))<0) { + restore_re_uid(); + return(False); + } + command.op = Q_GETQUOTA; + command.uid = euser_id; + command.addr = (caddr_t) &D; + ret = ioctl(file, Q_QUOTACTL, &command); + close(file); #else - DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); - ret = quotactl(Q_GETQUOTA, name, euser_id, &D); + DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); + ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - restore_re_uid(); + restore_re_uid(); - if (ret < 0) { - DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); + if (ret < 0) { + DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); #if defined(SUNOS5) && defined(VXFS_QUOTA) - /* If normal quotactl() fails, try vxfs private calls */ - set_effective_uid(euser_id); - DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); - if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { - BOOL retval; - retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize); - return(retval); - } + /* If normal quotactl() fails, try vxfs private calls */ + set_effective_uid(euser_id); + DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); + if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { + ret = disk_quotas_vxfs(name, path, bsize, dfree, dsize); + return(ret); + } #else - return(False); + return(False); #endif - } + } - /* If softlimit is zero, set it equal to hardlimit. - */ + /* If softlimit is zero, set it equal to hardlimit. + */ - if (D.dqb_bsoftlimit==0) - D.dqb_bsoftlimit = D.dqb_bhardlimit; - - /* Use softlimit to determine disk space. A user exceeding the quota is told - * that there's no space left. Writes might actually work for a bit if the - * hardlimit is set higher than softlimit. Effectively the disk becomes - * made of rubber latex and begins to expand to accommodate the user :-) - */ - - if (D.dqb_bsoftlimit==0) - return(False); - *bsize = DEV_BSIZE; - *dsize = D.dqb_bsoftlimit; - - if (D.dqb_curblocks > D.dqb_bsoftlimit) { - *dfree = 0; - *dsize = D.dqb_curblocks; - } else - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + if (D.dqb_bsoftlimit==0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; + + /* Use softlimit to determine disk space. A user exceeding the quota is told + * that there's no space left. Writes might actually work for a bit if the + * hardlimit is set higher than softlimit. Effectively the disk becomes + * made of rubber latex and begins to expand to accommodate the user :-) + */ + + if (D.dqb_bsoftlimit==0) + return(False); + *bsize = DEV_BSIZE; + *dsize = D.dqb_bsoftlimit; + + if (D.dqb_curblocks > D.dqb_bsoftlimit) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", - path,(double)*bsize,(double)*dfree,(double)*dsize)); + DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", + path,(double)*bsize,(double)*dfree,(double)*dsize)); - return(True); + return(True); } -- cgit From a6d350881c5e366d9a8d3d812cb85e0d8c2dc5d1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Mar 2001 01:33:57 +0000 Subject: Fixed the problem Gerald reported. Unfortunately we need to go back to reporting imaginary "default" inheritable ACLs on directories, otherwise, when you add an entry and click on apply without noticing there's no default entry associated with it, it applies a null acl on the files within the directory (hey, that's what you told NT you wanted, right ! :-). Also ensure that minimum permissions for a directory are r-x for owner, not just r--. Jeremy. (This used to be commit 4fa8cf68c3921f93a27d290d6dd1ed4423dfcf1c) --- source3/smbd/posix_acls.c | 304 +++++++++++++++++----------------------------- 1 file changed, 110 insertions(+), 194 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b7ba8e44ef..5b0c22c77e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -94,16 +94,6 @@ static canon_ace *dup_canon_ace( canon_ace *src_ace) return dst_ace; } -/**************************************************************************** - Function to create owner and group SIDs from a SMB_STRUCT_STAT. -****************************************************************************/ - -static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) -{ - uid_to_sid( powner_sid, psbuf->st_uid ); - gid_to_sid( pgroup_sid, psbuf->st_gid ); -} - /**************************************************************************** Print out a canon ace. ****************************************************************************/ @@ -160,6 +150,72 @@ static void print_canon_ace_list(const char *name, canon_ace *ace_list) } } +/**************************************************************************** + Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits). +****************************************************************************/ + +static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset) +{ + mode_t ret = 0; + + ret |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRUSR : 0); + ret |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWUSR : 0); + ret |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); + + return ret; +} + +/**************************************************************************** + Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits). +****************************************************************************/ + +static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) +{ + mode_t ret = 0; + + if (mode & r_mask) + ret |= S_IRUSR; + if (mode & w_mask) + ret |= S_IWUSR; + if (mode & x_mask) + ret |= S_IXUSR; + + return ret; +} + +/**************************************************************************** + Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to + an SMB_ACL_PERMSET_T. +****************************************************************************/ + +static int map_acl_perms_to_permset(mode_t mode, SMB_ACL_PERMSET_T *p_permset) +{ + if (sys_acl_clear_perms(*p_permset) == -1) + return -1; + if (mode & S_IRUSR) { + if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1) + return -1; + } + if (mode & S_IWUSR) { + if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1) + return -1; + } + if (mode & S_IXUSR) { + if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1) + return -1; + } + return 0; +} +/**************************************************************************** + Function to create owner and group SIDs from a SMB_STRUCT_STAT. +****************************************************************************/ + +static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) +{ + uid_to_sid( powner_sid, psbuf->st_uid ); + gid_to_sid( pgroup_sid, psbuf->st_gid ); +} + /**************************************************************************** Merge aces with a common sid - if both are allow or deny, OR the permissions together and delete the second one. If the first is deny, mask the permissions off and delete the allow @@ -402,52 +458,20 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, return True; } -/**************************************************************************** - Create a default mode for a directory default ACE. -****************************************************************************/ - -static mode_t get_default_ace_mode(files_struct *fsp, int type) -{ - mode_t force_mode = lp_force_dir_security_mode(SNUM(fsp->conn)); - mode_t mode = 0; - - DEBUG(10,("get_default_ace_mode: force_mode = 0%o\n", (int)force_mode )); - - switch(type) { - case S_IRUSR: - mode |= (force_mode & S_IRUSR) ? S_IRUSR : 0; - mode |= (force_mode & S_IWUSR) ? S_IWUSR : 0; - mode |= (force_mode & S_IXUSR) ? S_IXUSR : 0; - break; - case S_IRGRP: - mode |= (force_mode & S_IRGRP) ? S_IRUSR : 0; - mode |= (force_mode & S_IWGRP) ? S_IWUSR : 0; - mode |= (force_mode & S_IXGRP) ? S_IXUSR : 0; - break; - case S_IROTH: - mode |= (force_mode & S_IROTH) ? S_IRUSR : 0; - mode |= (force_mode & S_IWOTH) ? S_IWUSR : 0; - mode |= (force_mode & S_IXOTH) ? S_IXUSR : 0; - break; - } - - DEBUG(10,("get_default_ace_mode: returning mode = 0%o\n", (int)mode )); - - return mode; -} - /**************************************************************************** A well formed POSIX file or default ACL has at least 3 entries, a SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ. In addition, the owner must always have at least read access. + When using this call on get_acl, the pst struct is valid and contains + the mode of the file. When using this call on set_acl, the pst struct has + been modified to have a mode of r--------. ****************************************************************************/ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, files_struct *fsp, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, - SMB_STRUCT_STAT *pst, - BOOL default_acl) + SMB_STRUCT_STAT *pst) { extern DOM_SID global_sid_World; canon_ace *pace; @@ -479,7 +503,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->unix_ug.uid = pst->st_uid; pace->sid = *pfile_owner_sid; /* Ensure owner has read access. */ - pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRUSR) : S_IRUSR; + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); if (pace->perms == (mode_t)0) pace->perms = S_IRUSR; pace->attr = ALLOW_ACE; @@ -498,7 +522,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->owner_type = GID_ACE; pace->unix_ug.uid = pst->st_gid; pace->sid = *pfile_grp_sid; - pace->perms = default_acl ? get_default_ace_mode(fsp, S_IRGRP): 0; + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); @@ -515,7 +539,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->owner_type = WORLD_ACE; pace->unix_ug.world = -1; pace->sid = global_sid_World; - pace->perms = default_acl ? get_default_ace_mode(fsp, S_IROTH): 0; + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); @@ -1134,7 +1158,16 @@ static BOOL unpack_canon_ace(files_struct *fsp, print_canon_ace_list( "file ace - before valid", file_ace); - if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, False)) { + /* + * A default 3 element mode entry for a file should be r-- --- ---. + * A default 3 element mode entry for a directory should be r-x --- ---. + */ + + pst->st_mode = S_IRUSR; + if (fsp->is_directory) + pst->st_mode |= S_IXUSR; + + if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -1142,7 +1175,17 @@ static BOOL unpack_canon_ace(files_struct *fsp, print_canon_ace_list( "dir ace - before valid", dir_ace); - if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { + /* + * A default inheritable 3 element mode entry for a directory should be the + * mode Samba will use to create a file within. Ensure user x bit is set if + * it's a directory. + */ + + pst->st_mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); + if (fsp->is_directory) + pst->st_mode |= S_IXUSR; + + if (!ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -1157,62 +1200,6 @@ static BOOL unpack_canon_ace(files_struct *fsp, } -/**************************************************************************** - Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits). -****************************************************************************/ - -static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset) -{ - mode_t ret = 0; - - ret |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRUSR : 0); - ret |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWUSR : 0); - ret |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); - - return ret; -} - -/**************************************************************************** - Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits). -****************************************************************************/ - -static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask) -{ - mode_t ret = 0; - - if (mode & r_mask) - ret |= S_IRUSR; - if (mode & w_mask) - ret |= S_IWUSR; - if (mode & x_mask) - ret |= S_IXUSR; - - return ret; -} - -/**************************************************************************** - Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to - an SMB_ACL_PERMSET_T. -****************************************************************************/ - -static int map_acl_perms_to_permset(mode_t mode, SMB_ACL_PERMSET_T *p_permset) -{ - if (sys_acl_clear_perms(*p_permset) == -1) - return -1; - if (mode & S_IRUSR) { - if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1) - return -1; - } - if (mode & S_IWUSR) { - if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1) - return -1; - } - if (mode & S_IXUSR) { - if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1) - return -1; - } - return 0; -} /****************************************************************************** When returning permissions, try and fit NT display @@ -1274,92 +1261,12 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) *pp_list_head = list_head; } -/****************************************************************************** - Fall back to the generic 3 element UNIX permissions. -********************************************************************************/ - -static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup, BOOL default_acl) -{ - extern DOM_SID global_sid_World; - canon_ace *list_head = NULL; - canon_ace *owner_ace = NULL; - canon_ace *group_ace = NULL; - canon_ace *other_ace = NULL; - mode_t mode; - - if (default_acl) - return NULL; - - /* - * Create 3 linked list entries. - */ - - if ((owner_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) - goto fail; - - if ((group_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) - goto fail; - - if ((other_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) - goto fail; - - ZERO_STRUCTP(owner_ace); - ZERO_STRUCTP(group_ace); - ZERO_STRUCTP(other_ace); - - owner_ace->type = SMB_ACL_USER_OBJ; - owner_ace->sid = *powner; - owner_ace->unix_ug.uid = psbuf->st_uid; - owner_ace->owner_type = UID_ACE; - owner_ace->attr = ALLOW_ACE; - - group_ace->type = SMB_ACL_GROUP_OBJ; - group_ace->sid = *pgroup; - group_ace->unix_ug.gid = psbuf->st_gid; - group_ace->owner_type = GID_ACE; - group_ace->attr = ALLOW_ACE; - - other_ace->type = SMB_ACL_OTHER; - other_ace->sid = global_sid_World; - other_ace->unix_ug.world = -1; - other_ace->owner_type = WORLD_ACE; - other_ace->attr = ALLOW_ACE; - - mode = psbuf->st_mode; - - owner_ace->perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR); - owner_ace->attr = ALLOW_ACE; - - group_ace->perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); - group_ace->attr = ALLOW_ACE; - - other_ace->perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH); - other_ace->attr = ALLOW_ACE; - - DLIST_ADD(list_head, other_ace); - DLIST_ADD(list_head, group_ace); - DLIST_ADD(list_head, owner_ace); - - arrange_posix_perms(fsp->fsp_name,&list_head ); - - return list_head; - - fail: - - safe_free(owner_ace); - safe_free(group_ace); - safe_free(other_ace); - - return NULL; -} - /**************************************************************************** Create a linked list of canonical ACE entries. ****************************************************************************/ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup, BOOL default_acl) + DOM_SID *powner, DOM_SID *pgroup) { extern DOM_SID global_sid_World; mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); @@ -1370,10 +1277,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ SMB_ACL_ENTRY_T entry; size_t ace_count; - if (posix_acl == NULL) - return unix_canonicalise_acl( fsp, psbuf, powner, pgroup, default_acl); - - while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) { + while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; DOM_SID sid; @@ -1461,6 +1365,13 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ DLIST_ADD(list_head, ace); } + /* + * This next call will ensure we have at least a user/group/world set. + */ + + if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf)) + goto fail; + arrange_posix_perms(fsp->fsp_name,&list_head ); /* @@ -1807,7 +1718,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); /* Create the canon_ace lists. */ - file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, False); + file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid); num_acls = count_canon_ace_list(file_ace); /* We must have *some* ACLS. */ @@ -1818,7 +1729,12 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } if (fsp->is_directory) { - dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, &owner_sid, &group_sid, True); + /* + * If we have to fake a default ACL then this is the mode to use. + */ + sbuf.st_mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); + + dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, &owner_sid, &group_sid); num_dir_acls = count_canon_ace_list(dir_ace); } -- cgit From 559c1692e7b23aca69ca747098dc594b8e0e61d0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Mar 2001 23:20:46 +0000 Subject: Insure fix. Don't read 4 bytes from data area unless there are 4 bytes to read. Jeremy. (This used to be commit 3f9cf2e07bb6d429858e47ab6989ea8cf30d0217) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 58e8056c31..5a7a5c72cb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1690,7 +1690,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, tvs.actime = sbuf.st_atime; mode = dos_mode(conn,fname,&sbuf); - if (total_data > 0 && IVAL(pdata,0) == total_data) { + if (total_data > 4 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); -- cgit From 6e7f03f9b920d1b81056959cca8c0b27ada4ee2d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2001 08:57:24 +0000 Subject: This is a big, rather ugly patch. Whilst investigating the files not truncated when copying to a full disk problem, I discovered that we were not allowing the delete on close flag to be set properly, this led to other things, and after investigation of the proper delete on close semantics and their relationship to the file_share_delete flag I discovered there were some cases where we weren't doing the deny modes properly. And this after only 5 years working on them..... :-) :-). So here's the latest attempt. I realised the delete on close flag needs to be set across all smbds with a dev/ino pair open - in addition, the delete on close flag, allow share delete and delete access requested all need to be stored in the share mode tdb. The "delete_on_close" entry in the fsp struct is now redundant and should really be removed. This may also mean we can get rid of the "iterate_fsp" calls that I didn't like adding in the first place. Whilst doing this patch, I also discovered we needed to do the se_map_generic() call for file opens and POSIX ACL mapping, so I added that also. This code, although ugly, now passes the deny mode torture tests plus the delete on close tests I added. I do need to add one more multiple connection delete on close test to make sure I got the semantics exactly right, plus we should also (as Andrew suggested) move to random testing here. The good news is that NT should now correctly delete the file on disk full error when copying to a disk :-). Jeremy. (This used to be commit 51987684bd231c744da2e5f3705fd236d5616173) --- source3/smbd/close.c | 45 +++++++--- source3/smbd/nttrans.c | 31 ++++++- source3/smbd/open.c | 45 ++++++++-- source3/smbd/posix_acls.c | 10 ++- source3/smbd/trans2.c | 218 ++++++++++++++++++---------------------------- 5 files changed, 194 insertions(+), 155 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 56aad64391..c290ee6f89 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -99,7 +99,9 @@ static int close_filestruct(files_struct *fsp) static int close_normal_file(files_struct *fsp, BOOL normal_close) { - BOOL delete_on_close = fsp->delete_on_close; + share_mode_entry *share_entry = NULL; + size_t share_entry_count = 0; + BOOL delete_on_close = False; connection_struct *conn = fsp->conn; int err = 0; int err1 = 0; @@ -120,21 +122,25 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) return 0; } - lock_share_entry_fsp(fsp); - del_share_mode(fsp); - unlock_share_entry_fsp(fsp); + /* + * Lock the share entries, and determine if we should delete + * on close. If so delete whilst the lock is still in effect. + * This prevents race conditions with the file being created. JRA. + */ - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - release_file_oplock(fsp); + lock_share_entry_fsp(fsp); + share_entry_count = del_share_mode(fsp, &share_entry); - locking_close_file(fsp); + /* + * We delete on close if it's the last open, and the + * delete on close flag was set in the entry we just deleted. + */ - err = fd_close(conn, fsp); + if ((share_entry_count == 0) && share_entry && + GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) ) + delete_on_close = True; - /* check for magic scripts */ - if (normal_close) { - check_magic(fsp,conn); - } + safe_free(share_entry); /* * NT can set delete_on_close of the last open @@ -157,6 +163,21 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); } } + unlock_share_entry_fsp(fsp); + + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + release_file_oplock(fsp); + + locking_close_file(fsp); + + err = fd_close(conn, fsp); + + /* check for magic scripts */ + if (normal_close) { + check_magic(fsp,conn); + } + + DEBUG(2,("%s closed file %s (numopen=%d) %s\n", conn->user,fsp->fsp_name, conn->num_files_open, err ? strerror(err) : "")); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 58b484f44d..b67815ff69 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -47,6 +47,15 @@ static char *known_nt_pipes[] = { NULL }; +/* Map generic permissions to file object specific permissions */ + +struct generic_mapping file_generic_mapping = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_GENERIC_ALL +}; + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -332,6 +341,12 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, *pstat_open_only = False; + /* + * Convert GENERIC bits to specific bits. + */ + + se_map_generic(&desired_access, &file_generic_mapping); + switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) { case FILE_READ_DATA: smb_open_mode = DOS_OPEN_RDONLY; @@ -395,8 +410,22 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, * JRA. */ - if(share_access & FILE_SHARE_DELETE) + if(share_access & FILE_SHARE_DELETE) { smb_open_mode |= ALLOW_SHARE_DELETE; + DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = %x\n", smb_open_mode)); + } + + /* + * We need to store the intent to open for Delete. This + * is what determines if a delete on close flag can be set. + * This is the wrong way (and place) to store this, but for 2.2 this + * is the only practical way. JRA. + */ + + if(desired_access & DELETE_ACCESS) { + smb_open_mode |= DELETE_ACCESS_REQUESTED; + DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = %x\n", smb_open_mode)); + } /* Add in the requested share mode. */ switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c601121459..5f8657262a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -341,18 +341,19 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if we can open a file with a share mode ****************************************************************************/ -static int check_share_mode( share_mode_entry *share, int deny_mode, +static int check_share_mode( share_mode_entry *share, int share_mode, const char *fname, BOOL fcbopen, int *flags) { + int deny_mode = GET_DENY_MODE(share_mode); int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); /* - * Don't allow any open once the delete on close flag has been + * Don't allow any opens once the delete on close flag has been * set. */ - if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) { + if (GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", fname )); unix_ERR_class = ERRDOS; @@ -360,6 +361,35 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, return False; } + /* + * If delete access was requested and the existing share mode doesn't have + * ALLOW_SHARE_DELETE then deny. + */ + + if (GET_DELETE_ACCESS_REQUESTED(share_mode) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { + DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", + fname )); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + return False; + } + + /* + * The inverse of the above. + * If delete access was granted and the new share mode doesn't have + * ALLOW_SHARE_DELETE then deny. + */ + + if (GET_DELETE_ACCESS_REQUESTED(share->share_mode) && !GET_ALLOW_SHARE_DELETE(share_mode)) { + DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", + fname )); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + return False; + } + { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, (share->pid == sys_getpid()),is_executable(fname)); @@ -405,7 +435,6 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T int oplock_contention_count = 0; share_mode_entry *old_shares = 0; BOOL fcbopen = False; - int deny_mode = GET_DENY_MODE(share_mode); BOOL broke_oplock; if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) @@ -473,7 +502,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou /* someone else has a share lock on it, check to see if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, p_flags) == False) { + if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { free((char *)old_shares); errno = EACCES; return -1; @@ -532,6 +561,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); + BOOL delete_access_requested = GET_DELETE_ACCESS_REQUESTED(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; SMB_DEV_T dev = 0; @@ -768,7 +798,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S fsp->share_mode = SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode) | - SET_ALLOW_SHARE_DELETE(allow_share_delete); + SET_ALLOW_SHARE_DELETE(allow_share_delete) | + SET_DELETE_ACCESS_REQUESTED(delete_access_requested); + + DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); if (Access) (*Access) = open_mode; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 5b0c22c77e..aa8f9376c7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -559,6 +559,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SEC_ACL *dacl) { extern DOM_SID global_sid_World; + extern struct generic_mapping *file_generic_mapping; BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; @@ -589,8 +590,13 @@ static BOOL create_canon_ace_lists(files_struct *fsp, * to be so. Any other bits override the UNIX_ACCESS_NONE bit. */ - psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| - GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); + /* + * Convert GENERIC bits to specific bits. + */ + + se_map_generic(&psa->info.mask, &file_generic_mapping); + + psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS); if(psa->info.mask != UNIX_ACCESS_NONE) psa->info.mask &= ~UNIX_ACCESS_NONE; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5a7a5c72cb..be130247c0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1800,144 +1800,94 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { - if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL)) - { - BOOL delete_on_close = (CVAL(pdata,0) ? True : False); + BOOL delete_on_close = (CVAL(pdata,0) ? True : False); - if(fsp->is_directory) - { - fsp->directory_delete_on_close = delete_on_close; - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + if (tran_call != TRANSACT2_SETFILEINFO) + return(ERROR(ERRDOS,ERRunknownlevel)); - } - else if(fsp->stat_open) - { - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } - else - { + if (fsp == NULL) + return(UNIXERROR(ERRDOS,ERRbadfid)); - /* - * We can only set the delete on close flag if - * the share mode contained ALLOW_SHARE_DELETE - */ - - if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) - return(ERROR(ERRDOS,ERRnoaccess)); - - /* - * If the flag has been set then - * modify the share mode entry for all files we have open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. - */ - - if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) - { - int i; - files_struct *iterate_fsp; - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; - int num_share_modes; - share_mode_entry *current_shares = NULL; - - if (lock_share_entry_fsp(fsp) == False) - return(ERROR(ERRDOS,ERRnoaccess)); - - /* - * Before we allow this we need to ensure that all current opens - * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they - * do not then we deny this (as we are essentially deleting the - * file at this point. - */ - - num_share_modes = get_share_modes(conn, dev, inode, ¤t_shares); - for(i = 0; i < num_share_modes; i++) - { - if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) - { - DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \ -file %s as a share exists that was not opened with FILE_DELETE access.\n", - fsp->fnum, fsp->fsp_name )); - /* - * Release the lock. - */ - - unlock_share_entry_fsp(fsp); - - /* - * current_shares was malloced by get_share_modes - free it here. - */ - - free((char *)current_shares); - - /* - * Even though share violation would be more appropriate here, - * return ERRnoaccess as that's what NT does. - */ - - return(ERROR(ERRDOS,ERRnoaccess)); - } - } - - /* - * current_shares was malloced by get_share_modes - free it here. - */ - - free((char *)current_shares); - - DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - - /* - * Go through all files we have open on the same device and - * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. - * Other smbd's that have this file open will have to fend for themselves. We - * take care of this (rare) case in close_file(). See the comment there. - */ - - for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; - iterate_fsp = file_find_di_next(iterate_fsp)) - { - int new_share_mode = (delete_on_close ? - (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) : - (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); - - DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \ -dev = %x, inode = %.0f from %x to %x\n", - iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, - (double)inode, iterate_fsp->share_mode, new_share_mode )); - - if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False) - DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ -dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)); - } - - /* - * Set the delete on close flag in the reference - * counted struct. Delete when the last reference - * goes away. - */ - fsp->delete_on_close = delete_on_close; - - unlock_share_entry_fsp(fsp); - - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - - } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */ - } /* end if is_directory. */ - } else - return(ERROR(ERRDOS,ERRunknownlevel)); - break; - } + /* + * Only allow delete on close for files/directories opened with delete intent. + */ - default: - { - return(ERROR(ERRDOS,ERRunknownlevel)); - } + if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) { + DEBUG(10,("call_trans2setfilepathinfo: file %s delete on close flag set but delete access denied.\n", + fsp->fsp_name )); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + if(fsp->is_directory) { + fsp->directory_delete_on_close = delete_on_close; + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + } else if(fsp->stat_open) { + + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + + } else { + + files_struct *iterate_fsp; + + /* + * Modify the share mode entry for all files open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. This will be noticed + * in the close code, the last closer will delete the file + * if flag is set. + */ + + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + + if (lock_share_entry_fsp(fsp) == False) + return(ERROR(ERRDOS,ERRnoaccess)); + + if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { + DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close flag for file %s\n", + fsp->fsp_name )); + unlock_share_entry_fsp(fsp); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* + * Release the lock. + */ + + unlock_share_entry_fsp(fsp); + + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + * Other smbd's that have this file open will look in the share_mode on close. + * take care of this (rare) case in close_file(). See the comment there. + * NB. JRA. We don't really need to do this anymore - all should be taken + * care of in the share_mode changes in the tdb. + */ + + for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode); + iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp)) + fsp->delete_on_close = delete_on_close; + + /* + * Set the delete on close flag in the fsp. + */ + fsp->delete_on_close = delete_on_close; + + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + + } + + break; + } + + default: + { + return(ERROR(ERRDOS,ERRunknownlevel)); + } } /* get some defaults (no modifications) if any info is zero or -1. */ -- cgit From 94f0c652fe89c7137650982a9416969de264e6e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2001 18:07:43 +0000 Subject: Fixed extern ref typo for file generic perms. 2am coding strikes again :-). Jeremy. (This used to be commit fe38692643ad7c163c30d9c031a8bd3dec81ffee) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index aa8f9376c7..ae8493220f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -559,7 +559,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SEC_ACL *dacl) { extern DOM_SID global_sid_World; - extern struct generic_mapping *file_generic_mapping; + extern struct generic_mapping file_generic_mapping; BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; -- cgit From fd6e9d6db98086e47650e5679064172fd5454f40 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2001 21:53:33 +0000 Subject: utils/torture.c: Added one more delete on close test. smbd/notify_kernel.c: This code was wrong I believe. It was structured to only return a changenotify event on being called from timeout processing (t != 0). The kernel changenotify events should fire on *asynchronous* processing (EINTR return from select caused by the realtime signal delivery) with t == 0. Reported by Juergen Hasch (Hasch@t-online.de). ANDREW PLEASE CHECK THIS ! Currently the hash style changenotify is done on async processing as well as timeout processing. As this is expensive we may want to revisit doing this and maybe set it to fire only on timeout processing. Jeremy. (This used to be commit f952380c5d0cfbbec1e7de98b712952f302cddfd) --- source3/smbd/notify_kernel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 243a16a7f7..6509354e9b 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -74,14 +74,14 @@ static void signal_handler(int signal, siginfo_t *info, void *unused) /**************************************************************************** Check if a change notify should be issued. - time zero means instantaneous check (used for hash). Ignore this (normal method - will be used instead). + time non-zero means timeout check (used for hash). Ignore this (async method + where time is zero will be used instead). *****************************************************************************/ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) { struct change_data *data = (struct change_data *)datap; - if (!t) + if (t) return False; if (data->directory_handle != (int)fd_pending) return False; -- cgit From 578a9fabfb08740bd13af7418ceda41d1341cc5d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 31 Mar 2001 13:48:24 +0000 Subject: started converting some of the only-ascii code to use srvstr_* added srvstr_push_ascii() and srvstr_pull_ascii() as convenience routines to replace the current usage of strncpy() like fns for packet pull/push. We need to do this in *lots* of places in Samba in order to get our codepage handling right (This used to be commit 8b0e3679a6dc479c0e3177707dff386559779b69) --- source3/smbd/lanman.c | 21 ++++++++++----------- source3/smbd/srvstr.c | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e9df2ed41e..73815a5c59 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -368,7 +368,7 @@ static void PackDriverData(struct pack_desc* desc) SIVAL(drivdata,0,sizeof drivdata); /* cb */ SIVAL(drivdata,4,1000); /* lVersion */ memset(drivdata+8,0,32); /* szDeviceName */ - pstrcpy(drivdata+8,"NULL"); + srvstr_push_ascii(drivdata+8,"NULL",-1); PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ } @@ -1267,11 +1267,11 @@ static int fill_srv_info(struct srv_info_struct *service, switch (uLevel) { case 0: - StrnCpy(p,service->name,15); + srvstr_push_ascii(p,service->name,15); break; case 1: - StrnCpy(p,service->name,15); + srvstr_push_ascii(p,service->name,15); SIVAL(p,18,service->type); SIVAL(p,22,PTR_DIFF(p2,baseaddr)); len += CopyAndAdvance(&p2,service->comment,&l2); @@ -1352,9 +1352,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); if (strcmp(str1, "WrLehDz") == 0) { - StrnCpy(domain, p, sizeof(fstring)-1); + srvstr_pull_ascii(domain, p, sizeof(fstring)); } else { - StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1); + fstrcpy(domain, global_myworkgroup); } if (lp_browse_list()) @@ -1527,7 +1527,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, } if (!baseaddr) baseaddr = p; - StrnCpy(p,lp_servicename(snum),13); + srvstr_push_ascii(p,lp_servicename(snum),13); if (uLevel > 0) { @@ -1739,7 +1739,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param fstring user; fstring pass1,pass2; - fstrcpy(user,p); + srvstr_pull_ascii(user,p,sizeof(user)); p = skip_string(p,1); @@ -1876,8 +1876,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * } p = skip_string(p,1); - fstrcpy(user,p); - p = skip_string(p,1); + p += srvstr_pull_ascii(user,p,sizeof(user)); DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); @@ -2146,8 +2145,8 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par p = *rdata; p2 = p + struct_len; if (uLevel != 20) { - StrnCpy(p,local_machine,16); - strupper(p); + srvstr_push(NULL, p,local_machine,16, + STR_ASCII|STR_UPPER|STR_TERMINATE|STR_CONVERT); } p += 16; if (uLevel > 0) diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 55cbada10c..6ca34a2428 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -144,3 +144,21 @@ int srvstr_align(void *inbuf, int offset) if (!UNICODE_FLAG(inbuf)) return 0; return offset & 1; } + + +/**************************************************************************** +these are useful for replacing all those StrnCpy() ops for copying data +to/from the wire +****************************************************************************/ + +int srvstr_push_ascii(void *dest, const char *src, int dest_len) +{ + return srvstr_push(NULL, dest, src, dest_len, + STR_ASCII|STR_CONVERT|STR_TERMINATE); +} + +int srvstr_pull_ascii(char *dest, const void *src, int dest_len) +{ + return srvstr_pull(NULL, dest, src, dest_len, -1, + STR_ASCII|STR_CONVERT|STR_TERMINATE); +} -- cgit From f439f72ceec665dbd1eae367eb5d7302d8a3338d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 1 Apr 2001 19:00:43 +0000 Subject: Integrated solaris nfs quota code from Alan Romeril Jeremy (This used to be commit 181d41572ceb17dc765d3c0f1a05934e35f56a61) --- source3/smbd/quotas.c | 387 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 275 insertions(+), 112 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 7808d269f9..75e27f356a 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -250,6 +250,162 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U #include #endif +#if defined(SUNOS5) + +/**************************************************************************** + Allows querying of remote hosts for quotas on NFS mounted shares. + Supports normal NFS and AMD mounts. + Alan Romeril July 2K. +****************************************************************************/ + +#include +#include +#include +#include +#include + +static int quotastat; + +static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) +{ + if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN )) + return(0); + if (!xdr_int(xdrsp, &args->gqa_uid)) + return(0); + return (1); +} + +static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) +{ + gqr_status status; + union { + rquota gqr_rquota; + } getquota_rslt_u; + + if (!xdr_int(xdrsp, "astat)) { + DEBUG(6,("nfs_quotas: Status bad or zero\n")); + return 0; + } + if (!xdr_int32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { + DEBUG(6,("nfs_quotas: Block size bad or zero\n")); + return 0; + } + if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) { + DEBUG(6,("nfs_quotas: Active bad or zero\n")); + return 0; + } + if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { + DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); + return 0; + } + if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { + DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); + return 0; + } + if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { + DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); + return 0; + } + return (1); +} + +/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ +static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + uid_t uid = euser_id; + struct dqblk D; + char *mnttype = nfspath; + CLIENT *clnt; + struct getquota_rslt gqr; + struct getquota_args args; + char *cutstr, *pathname, *host, *testpath; + int len; + static struct timeval timeout = {2,0}; + enum clnt_stat clnt_stat; + + len=strcspn(mnttype, ":"); + pathname=strstr(mnttype, ":"); + cutstr = (char *) malloc(sizeof(char) * len ); + if (!cutstr) + return False; + + host = strncat(cutstr,mnttype, sizeof(char) * len ); + DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); + DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); + testpath=strchr(mnttype, ':'); + args.gqa_pathp = testpath+1; + args.gqa_uid = uid; + + DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp")); + + if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) { + clnt->cl_auth = authunix_create_default(); + DEBUG(9,("nfs_quotas: auth_success\n")); + + clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout); + if (clnt_stat == RPC_SUCCESS) + DEBUG(9,("nfs_quotas: rpccall_success\n")); + }; + + + /* + * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is + * no quota set, and 3 if no permission to get the quota. If 0 or 3 return + * something sensible. + */ + + if (quotastat == 1) { + DEBUG(9,("nfs_quotas: Good quota data\n")); + D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; + D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; + D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; + } + + if (quotastat == 0 || quotastat == 3) { + D.dqb_bsoftlimit = 1; + D.dqb_curblocks = 1; + DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); + } + + if (quotastat == 2) { + DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + free(cutstr); + return(False); + } + + DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", + quotastat, + gqr.getquota_rslt_u.gqr_rquota.rq_bsize, + gqr.getquota_rslt_u.gqr_rquota.rq_active, + gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit, + gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit, + gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)); + + *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize; + *dsize = D.dqb_bsoftlimit; + + if (D.dqb_curblocks == D.dqb_curblocks == 1) + *bsize = 512; + + if (D.dqb_curblocks > D.dqb_bsoftlimit) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + + DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize)); + + free(cutstr); + DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); + return(True); +} +#endif + /**************************************************************************** try to get the disk space from disk quotas (SunOS & Solaris2 version) Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). @@ -257,147 +413,154 @@ Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - uid_t euser_id; - int ret; - struct dqblk D; + uid_t euser_id; + int ret; + struct dqblk D; #if defined(SUNOS5) - struct quotctl command; - int file; - static struct mnttab mnt; - static pstring name; - pstring devopt; + struct quotctl command; + int file; + static struct mnttab mnt; + static pstring name; + pstring devopt; #else /* SunOS4 */ - struct mntent *mnt; - static pstring name; + struct mntent *mnt; + static pstring name; #endif - FILE *fd; - SMB_STRUCT_STAT sbuf; - SMB_DEV_T devno ; - static SMB_DEV_T devno_cached = 0 ; - static int found ; + FILE *fd; + SMB_STRUCT_STAT sbuf; + SMB_DEV_T devno ; + static SMB_DEV_T devno_cached = 0 ; + static int found ; - euser_id = geteuid(); + euser_id = geteuid(); - if ( sys_stat(path,&sbuf) == -1 ) - return(False) ; + if ( sys_stat(path,&sbuf) == -1 ) + return(False) ; - devno = sbuf.st_dev ; - DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); - if ( devno != devno_cached ) { - devno_cached = devno ; + devno = sbuf.st_dev ; + DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); + if ( devno != devno_cached ) { + devno_cached = devno ; #if defined(SUNOS5) - if ((fd = sys_fopen(MNTTAB, "r")) == NULL) - return(False) ; + if ((fd = sys_fopen(MNTTAB, "r")) == NULL) + return(False) ; - found = False ; - slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); - while (getmntent(fd, &mnt) == 0) { - if( !hasmntopt(&mnt, devopt) ) - continue; - - DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); - - /* quotas are only on vxfs, UFS or NFS, but nfs is not supported here */ - if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || - strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) - { - found = True ; - break ; - } - } + found = False ; + slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); + while (getmntent(fd, &mnt) == 0) { + if( !hasmntopt(&mnt, devopt) ) + continue; + + DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); + + /* quotas are only on vxfs, UFS or NFS */ + if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || + strcmp( mnt.mnt_fstype, "nfs" ) == 0 || + strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) { + found = True ; + break; + } + } - pstrcpy(name,mnt.mnt_mountp) ; - pstrcat(name,"/quotas") ; - fclose(fd) ; + pstrcpy(name,mnt.mnt_mountp) ; + pstrcat(name,"/quotas") ; + fclose(fd) ; #else /* SunOS4 */ - if ((fd = setmntent(MOUNTED, "r")) == NULL) - return(False) ; + if ((fd = setmntent(MOUNTED, "r")) == NULL) + return(False) ; - found = False ; - while ((mnt = getmntent(fd)) != NULL) { - if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", - mnt->mnt_dir,sbuf.st_dev)); - if (sbuf.st_dev == devno) { - found = True ; - break ; - } - } + found = False ; + while ((mnt = getmntent(fd)) != NULL) { + if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) + continue ; + DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); + if (sbuf.st_dev == devno) { + found = True ; + break; + } + } - pstrcpy(name,mnt->mnt_fsname) ; - endmntent(fd) ; + pstrcpy(name,mnt->mnt_fsname) ; + endmntent(fd) ; #endif - - } + } - if ( ! found ) - return(False) ; + if ( ! found ) + return(False) ; - save_re_uid(); - set_effective_uid(0); + save_re_uid(); + set_effective_uid(0); #if defined(SUNOS5) - DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); - if((file=sys_open(name, O_RDONLY,0))<0) { - restore_re_uid(); - return(False); - } - command.op = Q_GETQUOTA; - command.uid = euser_id; - command.addr = (caddr_t) &D; - ret = ioctl(file, Q_QUOTACTL, &command); - close(file); + if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) { + BOOL retval; + DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); + retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); + restore_re_uid(); + return retval; + } + + DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); + if((file=sys_open(name, O_RDONLY,0))<0) { + restore_re_uid(); + return(False); + } + command.op = Q_GETQUOTA; + command.uid = euser_id; + command.addr = (caddr_t) &D; + ret = ioctl(file, Q_QUOTACTL, &command); + close(file); #else - DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); - ret = quotactl(Q_GETQUOTA, name, euser_id, &D); + DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); + ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - restore_re_uid(); + restore_re_uid(); - if (ret < 0) { - DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); + if (ret < 0) { + DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); #if defined(SUNOS5) && defined(VXFS_QUOTA) - /* If normal quotactl() fails, try vxfs private calls */ - set_effective_uid(euser_id); - DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); - if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { - ret = disk_quotas_vxfs(name, path, bsize, dfree, dsize); - return(ret); - } + /* If normal quotactl() fails, try vxfs private calls */ + set_effective_uid(euser_id); + DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); + if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { + BOOL retval; + retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize); + return(retval); + } #else - return(False); + return(False); #endif - } + } - /* If softlimit is zero, set it equal to hardlimit. - */ + /* If softlimit is zero, set it equal to hardlimit. + */ - if (D.dqb_bsoftlimit==0) - D.dqb_bsoftlimit = D.dqb_bhardlimit; - - /* Use softlimit to determine disk space. A user exceeding the quota is told - * that there's no space left. Writes might actually work for a bit if the - * hardlimit is set higher than softlimit. Effectively the disk becomes - * made of rubber latex and begins to expand to accommodate the user :-) - */ - - if (D.dqb_bsoftlimit==0) - return(False); - *bsize = DEV_BSIZE; - *dsize = D.dqb_bsoftlimit; - - if (D.dqb_curblocks > D.dqb_bsoftlimit) { - *dfree = 0; - *dsize = D.dqb_curblocks; - } else - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + if (D.dqb_bsoftlimit==0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; + + /* Use softlimit to determine disk space. A user exceeding the quota is told + * that there's no space left. Writes might actually work for a bit if the + * hardlimit is set higher than softlimit. Effectively the disk becomes + * made of rubber latex and begins to expand to accommodate the user :-) + */ + + if (D.dqb_bsoftlimit==0) + return(False); + *bsize = DEV_BSIZE; + *dsize = D.dqb_bsoftlimit; + + if (D.dqb_curblocks > D.dqb_bsoftlimit) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", - path,(double)*bsize,(double)*dfree,(double)*dsize)); + DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", + path,(double)*bsize,(double)*dfree,(double)*dsize)); - return(True); + return(True); } -- cgit From 5d609165969c5b06aed581b1a21d7b7b0dca9430 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Apr 2001 20:46:15 +0000 Subject: Fix from "Romeril, Alan" to get his NFS quota code to work on Solaris 2.6. Jeremy. (This used to be commit bd2fe239db24b8b3fa6a906542af2e238f435331) --- source3/smbd/quotas.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 75e27f356a..ccb5534641 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -278,15 +278,15 @@ static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) { gqr_status status; - union { + union { rquota gqr_rquota; } getquota_rslt_u; - + if (!xdr_int(xdrsp, "astat)) { DEBUG(6,("nfs_quotas: Status bad or zero\n")); return 0; } - if (!xdr_int32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { DEBUG(6,("nfs_quotas: Block size bad or zero\n")); return 0; } @@ -294,15 +294,15 @@ static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) DEBUG(6,("nfs_quotas: Active bad or zero\n")); return 0; } - if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); return 0; } - if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); return 0; } - if (!xdr_uint32_t(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); return 0; } -- cgit From d4e8c87005869fce7ec993c91cd972d9a2f1a53b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Apr 2001 20:32:36 +0000 Subject: Fix from Ed Boraas for not core dumping when out of connection structs. Jeremy. (This used to be commit f50ea32dd0deb07c626c211caedd86dc1ccd5427) --- source3/smbd/service.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 849ccba5fb..e20786595c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -328,7 +328,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!conn) { DEBUG(0,("Couldn't find free connection.\n")); *ecode = ERRnoresource; - conn_free(conn); return NULL; } -- cgit From f9a15ce1a69f905e94db7650f0a4805720cd9c88 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 8 Apr 2001 20:22:39 +0000 Subject: Got "medieval on our ass" about adding the -1 to slprintf. Jeremy. (This used to be commit 94747b4639ed9b19f7d0fb896e43aa392a84989a) --- source3/smbd/connection.c | 2 +- source3/smbd/dfree.c | 2 +- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 8ab4e0c5d3..125b2fbbe5 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -434,7 +434,7 @@ static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid, * o with overflow if ut_line would be more than full. */ memset(line_tmp, '\0', sizeof(line_tmp)); - slprintf(line_tmp, sizeof(line_tmp), (char *) ut_line_template, i); + slprintf(line_tmp, sizeof(line_tmp)-1, (char *) ut_line_template, i); line_len = strlen(line_tmp); if (line_len <= sizeof(u->ut_line)) { memcpy(u->ut_line, line_tmp, sizeof(u->ut_line)); diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index c523f2cab4..64c6182cd8 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -88,7 +88,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, char **lines; pstring syscmd; - slprintf(syscmd, sizeof(syscmd), "%s %s", dfree_command, path); + slprintf(syscmd, sizeof(syscmd)-1, "%s %s", dfree_command, path); DEBUG (3, ("disk_free: Running command %s\n", syscmd)); lines = file_lines_pload(syscmd, NULL, True); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dea7130cfe..ac5454c48c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -592,7 +592,7 @@ static void smb_dump(char *name, int type, char *data, ssize_t len) if (len < 4) len = smb_len(data)+4; for (i=1;i<100;i++) { - slprintf(fname,sizeof(fname), "/tmp/%s.%d.%s", name, i, + slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i, type ? "req" : "resp"); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644); if (fd != -1 || errno != EEXIST) break; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 35a4b0f54a..4176dd0104 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -880,7 +880,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!sys_getpwnam(user)) { pstring user2; - slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False), + slprintf(user2,sizeof(user2)-1,"%s%s%s", dos_to_unix(domain,False), lp_winbind_separator(), user); if (sys_getpwnam(user2)) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index baa1536248..adf57b3f55 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -626,7 +626,7 @@ static void usage(char *pname) TimeInit(); if(!specified_logfile) { - slprintf(debugf, sizeof(debugf), "%s/log.smbd", LOGFILEBASE); + slprintf(debugf, sizeof(debugf)-1, "%s/log.smbd", LOGFILEBASE); } pstrcpy(remote_machine, "smbd"); -- cgit From 9d6dd97624f50dec3edd3bb9a3c0f7f47f9ae071 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Apr 2001 06:36:38 +0000 Subject: Added set/get SD's on shares. Check before tcon. Jeremy. (This used to be commit 036b1a8b09fe6a7cca83d631624145574acad7f2) --- source3/smbd/server.c | 4 ++++ source3/smbd/service.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index adf57b3f55..84b7109294 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -765,6 +765,10 @@ static void usage(char *pname) exit(1); } + if (!share_info_db_init()) { + exit(1); + } + if(!initialize_password_db(False)) { exit(1); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e20786595c..11ae11054a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -343,6 +343,29 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->read_only = lp_readonly(snum); + /* + * New code to check if there's a share security descripter + * added from NT server manager. This is an additional check + * before the smb.conf checks are done. JRA. + */ + + { + BOOL can_write = share_access_check(snum, vuid, FILE_WRITE_DATA); + + if (!can_write) { + if (!share_access_check(snum, vuid, FILE_READ_DATA)) { + /* No access, read or write. */ + *ecode = ERRaccess; + DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", + service )); + conn_free(conn); + return NULL; + } else { + conn->read_only = True; + } + } + } + { pstring list; StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); -- cgit From 0ca9f5c023df2ee498dcd1bdb2f29abc632a5d60 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Apr 2001 21:19:25 +0000 Subject: Fix for core dump in security = share code with new share security db. Jeremy. (This used to be commit 20b13bafdff2fd7be9219ed164e7fe91b597298d) --- source3/smbd/service.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 11ae11054a..507d07cc42 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -343,28 +343,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->read_only = lp_readonly(snum); - /* - * New code to check if there's a share security descripter - * added from NT server manager. This is an additional check - * before the smb.conf checks are done. JRA. - */ - - { - BOOL can_write = share_access_check(snum, vuid, FILE_WRITE_DATA); - - if (!can_write) { - if (!share_access_check(snum, vuid, FILE_READ_DATA)) { - /* No access, read or write. */ - *ecode = ERRaccess; - DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", - service )); - conn_free(conn); - return NULL; - } else { - conn->read_only = True; - } - } - } { pstring list; @@ -527,6 +505,28 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->ngroups, conn->groups, guest); + /* + * New code to check if there's a share security descripter + * added from NT server manager. This is done after the + * smb.conf checks are done as we need a uid and token. JRA. + */ + + { + BOOL can_write = share_access_check(conn, snum, vuid, FILE_WRITE_DATA); + + if (!can_write) { + if (!share_access_check(conn, snum, vuid, FILE_READ_DATA)) { + /* No access, read or write. */ + *ecode = ERRaccess; + DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", + service )); + conn_free(conn); + return NULL; + } else { + conn->read_only = True; + } + } + } /* Initialise VFS function pointers */ if (*lp_vfsobj(SNUM(conn))) { -- cgit From 6578fd874283ee97c2896bcf7257db7f3e37c2ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Apr 2001 23:19:08 +0000 Subject: To stop people complaining about the mktemp call, move it into lib/util.c. Thanks to Andrew for all this code. Fixed extra line in lib/sysacls.c that broke XFS ACL code. Jeremy. (This used to be commit 9b32b8a8cfc8ddb93c14d5581f433d2e93f89ed2) --- source3/smbd/message.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 21750f9cd4..9206442b94 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -40,8 +40,7 @@ deliver the message ****************************************************************************/ static void msg_deliver(void) { - pstring s; - fstring name; + pstring name; int i; int fd; @@ -53,10 +52,9 @@ static void msg_deliver(void) } /* put it in a temporary file */ - slprintf(s,sizeof(s)-1, "%s/msg.XXXXXX",tmpdir()); - fstrcpy(name,(char *)smbd_mktemp(s)); + slprintf(name,sizeof(name)-1, "%s/msg.XXXXXX",tmpdir()); + fd = smb_mkstemp(name); - fd = sys_open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); if (fd == -1) { DEBUG(1,("can't open message file %s\n",name)); return; @@ -86,12 +84,13 @@ static void msg_deliver(void) { fstring alpha_msgfrom; fstring alpha_msgto; + pstring s; pstrcpy(s,lp_msg_command()); - pstring_sub(s,"%s",name); pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,sizeof(alpha_msgfrom))); pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,sizeof(alpha_msgto))); standard_sub_basic(s); + pstring_sub(s,"%s",name); smbrun(s,NULL,False); } -- cgit From 50e78a9ac8cf0949c2471fafde844c674f97d73d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Apr 2001 00:37:00 +0000 Subject: As Andrew suggested, make smbrun return a fd for a deleted file which can then be read. Jeremy. (This used to be commit e7d59d6de89a5fdd201e4b5c6072dab08b1519db) --- source3/smbd/close.c | 26 ++++++++++++++++++++++++-- source3/smbd/message.c | 2 +- source3/smbd/reply.c | 4 ++-- source3/smbd/service.c | 8 ++++---- 4 files changed, 31 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c290ee6f89..10c9539834 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -48,17 +48,39 @@ static void check_magic(files_struct *fsp,connection_struct *conn) int ret; pstring magic_output; pstring fname; - pstrcpy(fname,fsp->fsp_name); + SMB_STRUCT_STAT st; + int tmp_fd, outfd; + pstrcpy(fname,fsp->fsp_name); if (*lp_magicoutput(SNUM(conn))) pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); else slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); chmod(fname,0755); - ret = smbrun(fname,magic_output,False); + ret = smbrun(fname,&tmp_fd,magic_output); DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); unlink(fname); + if (ret != 0 || tmp_fd == -1) { + if (tmp_fd != -1) + close(tmp_fd); + return; + } + outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); + if (outfd == -1) { + close(tmp_fd); + return; + } + + if (sys_fstat(tmp_fd,&st) == -1) { + close(tmp_fd); + close(outfd); + return; + } + + transfer_file(tmp_fd,outfd,st.st_size, NULL,0,0); + close(tmp_fd); + close(outfd); } } diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 9206442b94..01b5f51acc 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -91,7 +91,7 @@ static void msg_deliver(void) pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,sizeof(alpha_msgto))); standard_sub_basic(s); pstring_sub(s,"%s",name); - smbrun(s,NULL,False); + smbrun(s,NULL,NULL); } msgpos = 0; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4176dd0104..b4e0d490ab 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -493,7 +493,7 @@ int smb_create_user(char *unix_user, char *homedir) all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); if (homedir) all_string_sub(add_script, "%H", homedir, sizeof(pstring)); - ret = smbrun(add_script,NULL,False); + ret = smbrun(add_script,NULL,NULL); DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); return ret; } @@ -510,7 +510,7 @@ static int smb_delete_user(char *unix_user) pstrcpy(del_script, lp_deluser_script()); if (! *del_script) return -1; all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); - ret = smbrun(del_script,NULL,False); + ret = smbrun(del_script,NULL,NULL); DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); return ret; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 507d07cc42..375587b539 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -559,7 +559,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); standard_sub_conn(conn,cmd); DEBUG(5,("cmd=%s\n",cmd)); - ret = smbrun(cmd,NULL,False); + ret = smbrun(cmd,NULL,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); conn_free(conn); @@ -611,7 +611,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); standard_sub_conn(conn,cmd); - ret = smbrun(cmd,NULL,False); + ret = smbrun(cmd,NULL,NULL); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); conn_free(conn); @@ -688,7 +688,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); standard_sub_conn(conn,cmd); - smbrun(cmd,NULL,False); + smbrun(cmd,NULL,NULL); unbecome_user(); } @@ -698,7 +698,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); standard_sub_conn(conn,cmd); - smbrun(cmd,NULL,False); + smbrun(cmd,NULL,NULL); } conn_free(conn); } -- cgit From 2ef68c7e92d4661664f0410509f7cb551e74a198 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Apr 2001 19:12:06 +0000 Subject: Merge of Andrew's changes in 2.2. Jeremy. (This used to be commit fc76681812b1469208ad6c8847afdfc68bc6db49) --- source3/smbd/close.c | 2 +- source3/smbd/message.c | 2 +- source3/smbd/reply.c | 4 ++-- source3/smbd/service.c | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 10c9539834..45df9b2e0d 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -58,7 +58,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn) slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); chmod(fname,0755); - ret = smbrun(fname,&tmp_fd,magic_output); + ret = smbrun(fname,&tmp_fd); DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); unlink(fname); if (ret != 0 || tmp_fd == -1) { diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 01b5f51acc..98eb336c0a 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -91,7 +91,7 @@ static void msg_deliver(void) pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,sizeof(alpha_msgto))); standard_sub_basic(s); pstring_sub(s,"%s",name); - smbrun(s,NULL,NULL); + smbrun(s,NULL); } msgpos = 0; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b4e0d490ab..9d517dcaa9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -493,7 +493,7 @@ int smb_create_user(char *unix_user, char *homedir) all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); if (homedir) all_string_sub(add_script, "%H", homedir, sizeof(pstring)); - ret = smbrun(add_script,NULL,NULL); + ret = smbrun(add_script,NULL); DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); return ret; } @@ -510,7 +510,7 @@ static int smb_delete_user(char *unix_user) pstrcpy(del_script, lp_deluser_script()); if (! *del_script) return -1; all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); - ret = smbrun(del_script,NULL,NULL); + ret = smbrun(del_script,NULL); DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); return ret; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 375587b539..9fb2dd9eeb 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -559,7 +559,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); standard_sub_conn(conn,cmd); DEBUG(5,("cmd=%s\n",cmd)); - ret = smbrun(cmd,NULL,NULL); + ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); conn_free(conn); @@ -611,7 +611,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); standard_sub_conn(conn,cmd); - ret = smbrun(cmd,NULL,NULL); + ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); conn_free(conn); @@ -688,7 +688,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); standard_sub_conn(conn,cmd); - smbrun(cmd,NULL,NULL); + smbrun(cmd,NULL); unbecome_user(); } @@ -698,7 +698,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); standard_sub_conn(conn,cmd); - smbrun(cmd,NULL,NULL); + smbrun(cmd,NULL); } conn_free(conn); } -- cgit From 3c2c047e822b6c74ecc176d1623d5292657cde62 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Apr 2001 19:33:26 +0000 Subject: Added fix from "Eric Boehm" to try and set hard limit before setting soft limit. Jeremy. (This used to be commit a1eb2752a8bee9cc7d92c664c3de84e02620933d) --- source3/smbd/files.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index a4837a1a8b..33243e1e94 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -134,7 +134,7 @@ initialise file structures void file_init(void) { - int request_max_open_files = lp_max_open_files(); + int request_max_open_files = lp_max_open_files(); int real_lim; /* @@ -146,8 +146,8 @@ void file_init(void) real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR; - if(real_max_open_files != request_max_open_files) { - DEBUG(1,("file_init: Information only: requested %d \ + if(real_max_open_files != request_max_open_files) { + DEBUG(1,("file_init: Information only: requested %d \ open files, %d are available.\n", request_max_open_files, real_max_open_files)); } -- cgit From 819482c07137937ee0c063437d2b2eade2895b99 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Apr 2001 20:49:11 +0000 Subject: Fixed potential file descriptor leak with MS-Access fix. Jeremy. (This used to be commit 192887fe72157a141b8df1977085f479e5204782) --- source3/smbd/open.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5f8657262a..007a169f9e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -60,6 +60,8 @@ static int fd_open(struct connection_struct *conn, char *fname, int fd_close(struct connection_struct *conn, files_struct *fsp) { + if (fsp->fd == -1) + return -1; return fd_close_posix(conn, fsp); } @@ -699,9 +701,15 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S * we can do. We also ensure we're not going to create or tuncate * the file as we only want an access decision at this stage. JRA. */ - open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC|O_CREAT)),mode); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC|O_CREAT)),mode); + + DEBUG(4,("open_file_shared : share_mode deny - calling open_file with \ +flags=0x%X flags2=0x%X mode=0%o returned %d\n", + flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); unlock_share_entry(conn, dev, inode); + if (fsp_open) + fd_close(conn, fsp); file_free(fsp); return NULL; } -- cgit From 9444e9d9f350961b594a1acbe7a7652d97faec0a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Apr 2001 21:11:57 +0000 Subject: Michael Davidson pointed out that acl_get_qualifier can potentially return a malloced area so added sys_acl_free_qualifier() calls to all supported ACL interfaces to code with this (only Linux needs actual free call). Jeremy. (This used to be commit 5870e6019b82d2088b99acdc0f84e9e4847a1fa5) --- source3/smbd/posix_acls.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ae8493220f..a9c8821238 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1319,6 +1319,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; + sys_acl_free_qualifier((void *)puid); break; } case SMB_ACL_GROUP_OBJ: @@ -1337,6 +1338,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ gid_to_sid( &sid, *pgid); unix_ug.gid = *pgid; owner_type = GID_ACE; + sys_acl_free_qualifier((void *)pgid); break; } case SMB_ACL_MASK: -- cgit From 53850c51caf1c4d53ff285b2e5505e0615beeeee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 14 Apr 2001 00:19:12 +0000 Subject: configure: configure.in: include/config.h.in: include/profile.h: smbd/vfs-wrap.c: smbd/vfs.c: Added fchmod and fchown to VFS (sorry Gerald - but we needed them anyway). smbd/dosmode.c: smbd/files.c: printing/printfsp.c: smbd/close.c: smbd/open.c: Fixed "dos filemode" correctly so there are no race conditions. Forces test of open of file O_WRONLY before allowing fchmod as root. Afterwards, calls standard close function that preserves POSIX locks due to POSIX-me-harder braindamage. :-). Andrew please review this code. Also - in removing the tmpdir param in smbrun an extra NULL parameter was missed in each print_run_command() call (which is a varargs fn.). Now fixed. Jeremy. (This used to be commit 32397e5bc6d995ce7ca37c82d6aedc1e5b1b6fbd) --- source3/smbd/close.c | 2 +- source3/smbd/dosmode.c | 26 ++++++++++++++---------- source3/smbd/files.c | 5 +++-- source3/smbd/open.c | 54 ++++++++++++++++++++++++++++++++++++++++++------- source3/smbd/vfs-wrap.c | 41 ++++++++++++++++++++++++++++++++++++- source3/smbd/vfs.c | 10 +++++++++ 6 files changed, 116 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 45df9b2e0d..217c81228f 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -111,7 +111,7 @@ static int close_filestruct(files_struct *fsp) } /**************************************************************************** - Close a file - possibly invalidating the read prediction. + Close a file. If normal_close is 1 then this came from a normal SMBclose (or equivalent) operation otherwise it came as the result of some other operation such as diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 8b2c482b0a..9ec1fa2606 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -184,7 +184,6 @@ chmod a file - but preserve some bits ********************************************************************/ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *st) { - extern struct current_user current_user; SMB_STRUCT_STAT st1; int mask=0; mode_t tmp; @@ -250,16 +249,21 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * /* Check if we have write access. */ if (CAN_WRITE(conn)) { - if (((st->st_mode & S_IWOTH) || - conn->admin_user || - ((st->st_mode & S_IWUSR) && current_user.uid==st->st_uid) || - ((st->st_mode & S_IWGRP) && - in_group(st->st_gid,current_user.gid, current_user.ngroups,current_user.groups)))) { - /* We are allowed to become root and change the file mode. */ - become_root(); - ret = vfs_chmod(conn,fname,unixmode); - unbecome_root(); - } + /* + * We need to open the file with write access whilst + * still in our current user context. This ensures we + * are not violating security in doing the fchmod. + * This file open does *not* break any oplocks we are + * holding. We need to review this.... may need to + * break batch oplocks open by others. JRA. + */ + files_struct *fsp = open_file_fchmod(conn,fname,st); + if (!fsp) + return -1; + become_root(); + ret = conn->vfs_ops.fchmod(fsp, fsp->fd, unixmode); + unbecome_root(); + close_file_fchmod(fsp); } return( ret ); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 33243e1e94..27dfad7c48 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -43,7 +43,7 @@ static int files_used; /**************************************************************************** find first available file slot ****************************************************************************/ -files_struct *file_new(void ) +files_struct *file_new(connection_struct *conn) { int i; static int first_file; @@ -72,7 +72,7 @@ files_struct *file_new(void ) for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (attempt_close_oplocked_file(fsp)) { - return file_new(); + return file_new(conn); } } @@ -91,6 +91,7 @@ files_struct *file_new(void ) ZERO_STRUCTP(fsp); fsp->fd = -1; + fsp->conn = conn; first_file = (i+1) % real_max_open_files; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 007a169f9e..f450e74e58 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -583,13 +583,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S return print_fsp_open(conn, fname); } - fsp = file_new(); + fsp = file_new(conn); if(!fsp) return NULL; - fsp->fd = -1; - fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, share_mode, ofun, (int)mode, oplock_request )); @@ -870,7 +867,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return NULL; } - fsp = file_new(); + fsp = file_new(conn); if(!fsp) return NULL; @@ -918,6 +915,49 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return fsp; } +/**************************************************************************** + Open a file for for write to ensure that we can fchmod it. +****************************************************************************/ + +files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) +{ + files_struct *fsp = NULL; + BOOL fsp_open; + + if (!VALID_STAT(*psbuf)) + return NULL; + + fsp = file_new(conn); + if(!fsp) + return NULL; + + fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0); + + /* + * This is not a user visible file open. + * Don't set a share mode and don't increment + * the conn->num_files_open. + */ + + if (!fsp_open) { + file_free(fsp); + return NULL; + } + + return fsp; +} + +/**************************************************************************** + Close the fchmod file fd - ensure no locks are lost. +****************************************************************************/ + +int close_file_fchmod(files_struct *fsp) +{ + int ret = fd_close(fsp->conn, fsp); + file_free(fsp); + return ret; +} + /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -927,12 +967,12 @@ files_struct *open_directory(connection_struct *conn, char *fname, { extern struct current_user current_user; BOOL got_stat = False; - files_struct *fsp = file_new(); + files_struct *fsp = file_new(conn); if(!fsp) return NULL; - fsp->conn = conn; /* THe vfs_fXXX() macros need this. */ + fsp->conn = conn; /* The vfs_fXXX() macros need this. */ if (VALID_STAT(*psbuf)) got_stat = True; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index a4057eb7ce..da8484e14e 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -369,6 +369,34 @@ int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) return result; } +int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) +{ + int result; + struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; + + START_PROFILE(syscall_fchmod); + + /* + * We need to do this due to the fact that the default POSIX ACL + * chmod modifies the ACL *mask* for the group owner, not the + * group owner bits directly. JRA. + */ + + if (vfs_ops->fchmod_acl != NULL) { + int saved_errno = errno; /* We might get ENOSYS */ + if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) { + END_PROFILE(syscall_chmod); + return result; + } + /* Error - return the old errno. */ + errno = saved_errno; + } + + result = fchmod(fd, mode); + END_PROFILE(syscall_fchmod); + return result; +} + int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) { int result; @@ -386,6 +414,17 @@ int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) return result; } +int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) +{ + int result; + + START_PROFILE(syscall_fchown); + + result = fchown(fd, uid, gid); + END_PROFILE(syscall_fchown); + return result; +} + int vfswrap_chdir(connection_struct *conn, char *path) { int result; @@ -452,7 +491,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) extend a file with ftruncate. Provide alternate implementation for this */ - struct vfs_ops *vfs_ops = fsp->conn->vfs_ops; + struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; SMB_STRUCT_STAT st; char c = 0; SMB_OFF_T currpos; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f5bd057ca6..713d58cdc8 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -64,7 +64,9 @@ struct vfs_ops default_vfs_ops = { vfswrap_lstat, vfswrap_unlink, vfswrap_chmod, + vfswrap_fchmod, vfswrap_chown, + vfswrap_fchown, vfswrap_chdir, vfswrap_getwd, vfswrap_utime, @@ -224,10 +226,18 @@ BOOL vfs_init_custom(connection_struct *conn) conn->vfs_ops.chmod = default_vfs_ops.chmod; } + if (conn->vfs_ops.fchmod == NULL) { + conn->vfs_ops.fchmod = default_vfs_ops.fchmod; + } + if (conn->vfs_ops.chown == NULL) { conn->vfs_ops.chown = default_vfs_ops.chown; } + if (conn->vfs_ops.fchown == NULL) { + conn->vfs_ops.fchown = default_vfs_ops.fchown; + } + if (conn->vfs_ops.chdir == NULL) { conn->vfs_ops.chdir = default_vfs_ops.chdir; } -- cgit From 2df39394fe01de6fb19cd919554272f407ecee4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 14 Apr 2001 20:47:30 +0000 Subject: This little piece of insanity is inspired by the fact that an NT client can open a file for O_RDONLY, but set the create disposition to FILE_EXISTS_TRUNCATE. If the client *can* write to the file, then it expects to truncate the file, even though it is opening for readonly. Quicken uses this stupid trick in backup file creation... Thanks *greatly* to "David W. Chapman Jr." for helping track this one down. It didn't bite us in 2.0.x as we always opened files read-write in that release. Jeremy. (This used to be commit 5baef56831f9bc4fa10a851abd5f9305b974fb3b) --- source3/smbd/open.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f450e74e58..cebb37ab29 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -48,8 +48,8 @@ static int fd_open(struct connection_struct *conn, char *fname, fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode); } - DEBUG(10,("fd_open: name %s, mode = %d, fd = %d. %s\n", fname, (int)mode, fd, - (fd == -1) ? strerror(errno) : "" )); + DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, + flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" )); return fd; } @@ -647,7 +647,22 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S flags = O_RDWR; break; default: - flags = O_RDONLY; + /* + * This little piece of insanity is inspired by the + * fact that an NT client can open a file for O_RDONLY, + * but set the create disposition to FILE_EXISTS_TRUNCATE. + * If the client *can* write to the file, then it expects to + * truncate the file, even though it is opening for readonly. + * Quicken uses this stupid trick in backup file creation... + * Thanks *greatly* to "David W. Chapman Jr." + * for helping track this one down. It didn't bite us in 2.0.x + * as we always opened files read-write in that release. JRA. + */ + + if (flags2 & O_TRUNC) + flags = O_RDWR; + else + flags = O_RDONLY; break; } -- cgit From 18f3f5ff9282417b350873fd572e9e0c4d4bcea4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 15 Apr 2001 23:36:05 +0000 Subject: Fixed potential bug in "become_guest" pointed out by elrond. Get_Pwnam() returns a pointer to changable storage so ensure we save the details and don't use the pointer directly. Jeremy. (This used to be commit d9fdaae54ee3a267aebd02ff6058a98aefc084c2) --- source3/smbd/uid.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 02522a37a2..da4c538319 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -33,19 +33,26 @@ extern struct current_user current_user; BOOL become_guest(void) { static struct passwd *pass=NULL; - - if (!pass) + static uid_t guest_uid = (uid_t)-1; + static gid_t guest_gid = (gid_t)-1; + static fstring guest_name; + + if (!pass) { pass = Get_Pwnam(lp_guestaccount(-1),True); - if (!pass) - return(False); + if (!pass) + return(False); + guest_uid = pass->pw_uid; + guest_gid = pass->pw_gid; + fstrcpy(guest_name, pass->pw_name); + } #ifdef AIX /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before setting IDs */ - initgroups(pass->pw_name, (gid_t)pass->pw_gid); + initgroups(guest_name, guest_gid); #endif - set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); + set_sec_ctx(guest_uid, guest_gid, 0, NULL, NULL); current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; -- cgit From d5b74f71300f4366441511620d519b63442773b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Apr 2001 00:02:29 +0000 Subject: Correct fix for open readonly with truncate. Jeremy. (This used to be commit 6706e258e17c3d69d617b95feb3407124f50852d) --- source3/smbd/open.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cebb37ab29..7c40b0720e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -93,6 +93,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, extern struct current_user current_user; pstring fname; int accmode = (flags & O_ACCMODE); + int local_flags = flags; fsp->fd = -1; fsp->oplock_type = NO_OPLOCK; @@ -127,8 +128,23 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, } } + /* + * This little piece of insanity is inspired by the + * fact that an NT client can open a file for O_RDONLY, + * but set the create disposition to FILE_EXISTS_TRUNCATE. + * If the client *can* write to the file, then it expects to + * truncate the file, even though it is opening for readonly. + * Quicken uses this stupid trick in backup file creation... + * Thanks *greatly* to "David W. Chapman Jr." + * for helping track this one down. It didn't bite us in 2.0.x + * as we always opened files read-write in that release. JRA. + */ + + if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) + local_flags = (flags & ~O_ACCMODE)|O_RDWR; + /* actually do the open */ - fsp->fd = fd_open(conn, fname, flags, mode); + fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", @@ -647,22 +663,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S flags = O_RDWR; break; default: - /* - * This little piece of insanity is inspired by the - * fact that an NT client can open a file for O_RDONLY, - * but set the create disposition to FILE_EXISTS_TRUNCATE. - * If the client *can* write to the file, then it expects to - * truncate the file, even though it is opening for readonly. - * Quicken uses this stupid trick in backup file creation... - * Thanks *greatly* to "David W. Chapman Jr." - * for helping track this one down. It didn't bite us in 2.0.x - * as we always opened files read-write in that release. JRA. - */ - - if (flags2 & O_TRUNC) - flags = O_RDWR; - else - flags = O_RDONLY; + flags = O_RDONLY; break; } -- cgit From 71ae6a09cd2c4792f95459220645c424f7659913 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Apr 2001 00:34:03 +0000 Subject: Finally got the semantics right (hurrah!). Jeremy. (This used to be commit 362574c5a32005d4247c7ac75a5aa9e35e894db0) --- source3/smbd/open.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c40b0720e..c6d4a44688 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -143,12 +143,19 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) local_flags = (flags & ~O_ACCMODE)|O_RDWR; + /* + * We can't actually truncate here as the file may be locked. + * open_file_shared will take care of the truncate later. JRA. + */ + + local_flags &= ~O_TRUNC; + /* actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { - DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", - fname,strerror(errno),flags)); + DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", + fname,strerror(errno),local_flags,flags)); check_for_pipe(fname); return False; } @@ -231,9 +238,6 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * { SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; - if (!fsp->can_write) - return -1; - if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK)){ errno = EACCES; unix_ERR_class = ERRDOS; @@ -735,7 +739,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); - fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC)),mode); + /* + * open_file strips any O_TRUNC flags itself. + */ + + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode); if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode)) == True) -- cgit From 4355098a757885462dd44b94b616014c30eea2bf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 Apr 2001 15:16:31 +0000 Subject: hide unreadable patch from idra (This used to be commit 7b6cfe243002a92f5dfb52413e9b3550c61cecfb) --- source3/smbd/dir.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5bf0dec944..46078b8d06 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -663,6 +663,36 @@ typedef struct } Dir; + +/******************************************************************* +check to see if a user can read a file. This is only approximate, +it is used as part of the "hide unreadable" option. Don't +use it for anything security sensitive +********************************************************************/ +static BOOL user_can_read_file(connection_struct *conn, const char *name) +{ + struct stat ste; + + /* if we can't stat it does not show it */ + if (stat(name, &ste) != 0) return False; + + if (ste.st_uid == conn->uid) { + return (ste.st_mode & S_IRUSR) == S_IRUSR; + } else { + int i; + if (ste.st_gid == conn->gid) { + return (ste.st_mode & S_IRGRP) == S_IRGRP; + } + for (i=0; ingroups; i++) { + if (conn->groups[i] == ste.st_gid) { + return (ste.st_mode & S_IRGRP) == S_IRGRP; + } + } + } + + return (ste.st_mode & S_IROTH) == S_IROTH; +} + /******************************************************************* Open a directory. ********************************************************************/ @@ -677,6 +707,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { + DEBUG(0,("Out of memory in OpenDir\n")); conn->vfs_ops.closedir(conn,p); return(NULL); } @@ -695,6 +726,24 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) /* If it's a vetoed file, pretend it doesn't even exist */ if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; + /* Honour _hide unreadable_ option */ + if (conn && lp_hideunreadable(SNUM(conn))) + { + char *entry; + int ret; + + entry = (char *)malloc(PATH_MAX); + if (!entry) { + DEBUG(0,("Out of memory in OpenDir\n")); + conn->vfs_ops.closedir(conn,p); + return(NULL); + } + slprintf(entry, PATH_MAX, "%s/%s/%s", conn->origpath, name, n); + ret = user_can_read_file(conn, entry); + free(entry); + if (!ret) continue; + } + if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; -- cgit From a5bd9ef712786a51089f15e034a32111bc416344 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Apr 2001 02:27:23 +0000 Subject: Rememver to use VFS at all times... even in new user_can_read_file code :-). Jeremy. (This used to be commit 0d10113d01d6d15f470359259a76e4f107a06c73) --- source3/smbd/dir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 46078b8d06..1d497574a6 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -669,12 +669,12 @@ check to see if a user can read a file. This is only approximate, it is used as part of the "hide unreadable" option. Don't use it for anything security sensitive ********************************************************************/ -static BOOL user_can_read_file(connection_struct *conn, const char *name) +static BOOL user_can_read_file(connection_struct *conn, char *name) { - struct stat ste; + SMB_STRUCT_STAT ste; /* if we can't stat it does not show it */ - if (stat(name, &ste) != 0) return False; + if (vfs_stat(conn, name, &ste) != 0) return False; if (ste.st_uid == conn->uid) { return (ste.st_mode & S_IRUSR) == S_IRUSR; -- cgit From 6f78636a56106c510545dc1c8218b3a90a486c67 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Apr 2001 05:12:46 +0000 Subject: Removed mktemp from HEAD - same as done in 2.2. Jeremy. (This used to be commit 121b59669fbcd1aaedb08011ff36169fc6561c55) --- source3/smbd/open.c | 2 +- source3/smbd/reply.c | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c6d4a44688..8db4400664 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -600,7 +600,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S ignored */ *Access = DOS_OPEN_WRONLY; *action = FILE_WAS_CREATED; - return print_fsp_open(conn, fname); + return print_fsp_open(conn); } fsp = file_new(conn); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9d517dcaa9..82ac230764 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1835,6 +1835,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + int tmpfd; SMB_STRUCT_STAT sbuf; char *p; @@ -1850,15 +1851,23 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode = unix_mode(conn,createmode,fname); - pstrcpy(fname2,(char *)smbd_mktemp(fname)); - /* This file should not exist. */ - ZERO_STRUCT(sbuf); + tmpfd = smb_mkstemp(fname); + if (tmpfd == -1) { + END_PROFILE(SMBctemp); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + vfs_stat(conn,fname2,&sbuf); /* Open file in dos compatibility share mode. */ - /* We should fail if file exists. */ - fsp = open_file_shared(conn,fname2,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL); + /* We should fail if file does not exist. */ + fsp = open_file_shared(conn,fname,&sbuf, + SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + FILE_FAIL_IF_NOT_EXIST, + unixmode, oplock_request, NULL, NULL); + + /* close fd from smb_mkstemp() */ + close(tmpfd); if (!fsp) { @@ -3169,7 +3178,7 @@ int reply_printopen(connection_struct *conn, } /* Open for exclusive use, write only. */ - fsp = print_fsp_open(conn,"dos.prn"); + fsp = print_fsp_open(conn); if (!fsp) { END_PROFILE(SMBsplopen); -- cgit From 9ce5a03ccbcc21c60a3dbc39b1dbd06b30655852 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 18 Apr 2001 16:41:04 +0000 Subject: merge from 2.2 (This used to be commit f52a5014ee325f9d91f266f88eac51b6136a75b9) --- source3/smbd/connection.c | 773 ---------------------------------------------- source3/smbd/password.c | 50 ++- source3/smbd/reply.c | 7 +- source3/smbd/server.c | 4 +- 4 files changed, 46 insertions(+), 788 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 125b2fbbe5..43e89abfbf 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -27,11 +27,6 @@ static TDB_CONTEXT *tdb; extern int DEBUGLEVEL; -#ifdef WITH_UTMP -static void utmp_yield(pid_t pid, const connection_struct *conn); -static void utmp_claim(const struct connections_data *crec, const connection_struct *conn); -#endif - /**************************************************************************** Return the connection tdb context (used for message send all). ****************************************************************************/ @@ -64,11 +59,6 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) tdb_delete(tdb, kbuf); -#ifdef WITH_UTMP - if(conn) - utmp_yield(key.pid, conn); -#endif - return(True); } @@ -120,769 +110,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False; -#ifdef WITH_UTMP - if (conn) - utmp_claim(&crec, conn); -#endif - return True; } -#ifdef WITH_UTMP - -/**************************************************************************** -Reflect connection status in utmp/wtmp files. - T.D.Lee@durham.ac.uk September 1999 - - With grateful thanks since then to many who have helped port it to - different operating systems. The variety of OS quirks thereby - uncovered is amazing... - -Hints for porting: - o Always attempt to use programmatic interface (pututline() etc.) - Indeed, at present only programmatic use is supported. - o The only currently supported programmatic interface to "wtmp{,x}" - is through "updwtmp*()" routines. - o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable. - o The HAVE_* items should identify supported features. - o If at all possible, avoid "if defined(MY-OS)" constructions. - -OS observations and status: - Almost every OS seems to have its own quirks. - - Solaris 2.x: - Tested on 2.6 and 2.7; should be OK on other flavours. - AIX: - Apparently has utmpx.h but doesn't implement. - OSF: - Has utmpx.h, but (e.g.) no "getutmpx()". (Is this like AIX ?) - Redhat 6: - utmpx.h seems not to set default filenames. non-x better. - IRIX 6.5: - Not tested. Appears to have "x". - HP-UX 9.x: - Not tested. Appears to lack "x". - HP-UX 10.x: - Not tested. - "updwtmp*()" routines seem absent, so no current wtmp* support. - Has "ut_addr": probably trivial to implement (although remember - that IPv6 is coming...). - - FreeBSD: - No "putut*()" type of interface. - No "ut_type" and associated defines. - Write files directly. Alternatively use its login(3)/logout(3). - SunOS 4: - Not tested. Resembles FreeBSD, but no login()/logout(). - -lastlog: - Should "lastlog" files, if any, be updated? - BSD systems (SunOS 4, FreeBSD): - o Prominent mention on man pages. - System-V (e.g. Solaris 2): - o No mention on man pages, even under "man -k". - o Has a "/var/adm/lastlog" file, but pututxline() etc. seem - not to touch it. - o Despite downplaying (above), nevertheless has . - So perhaps UN*X "lastlog" facility is intended for tty/terminal only? - -Notes: - Each connection requires a small number (starting at 0, working up) - to represent the line (unum). This must be unique within and across - all smbd processes. - - The 4 byte 'ut_id' component is vital to distinguish connections, - of which there could be several hundered or even thousand. - Entries seem to be printable characters, with optional NULL pads. - - We need to be distinct from other entries in utmp/wtmp. - - Observed things: therefore avoid them. Add to this list please. - From Solaris 2.x (because that's what I have): - 'sN' : run-levels; N: [0-9] - 'co' : console - 'CC' : arbitrary things; C: [a-z] - 'rXNN' : rlogin; N: [0-9]; X: [0-9a-z] - 'tXNN' : rlogin; N: [0-9]; X: [0-9a-z] - '/NNN' : Solaris CDE - 'ftpZ' : ftp (Z is the number 255, aka 0377, aka 0xff) - Mostly a record uses the same 'ut_id' in both "utmp" and "wtmp", - but differences have been seen. - - Arbitrarily I have chosen to use a distinctive 'SM' for the - first two bytes. - - The remaining two encode the "unum" (see above). - - For "utmp consolidate" the suggestion was made to encode the pid into - those remaining two bytes (16 bits). But recent UNIX (e.g Solaris 8) - is migrating to pids > 16 bits, so we ought not to do this. - -****************************************************************************/ - -#include - -#ifdef HAVE_UTMPX_H -#include -#endif - -/* BSD systems: some may need lastlog.h (SunOS 4), some may not (FreeBSD) */ -/* Some System-V systems (e.g. Solaris 2) declare this too. */ -#ifdef HAVE_LASTLOG_H -#include -#endif - -/**************************************************************************** -obtain/release a small number (0 upwards) unique within and across smbds -****************************************************************************/ -/* - * Need a "small" number to represent this connection, unique within this - * smbd and across all smbds. - * - * claim: - * Start at 0, hunt up for free, unique number "unum" by attempting to - * store it as a key in a tdb database: - * key: unum data: pid+conn - * Also store its inverse, ready for yield function: - * key: pid+conn data: unum - * - * yield: - * Find key: pid+conn; data is unum; delete record - * Find key: unum ; delete record. - * - * Comment: - * The claim algorithm (a "for" loop attempting to store numbers in a tdb - * database) will be increasingly inefficient with larger numbers of - * connections. Is it possible to write a suitable primitive within tdb? - * - * However, by also storing the inverse key/data pair, we at least make - * the yield algorithm efficient. - */ - -static TDB_CONTEXT *tdb_utmp; - -struct utmp_tdb_data { - pid_t pid; - int cnum; -}; - -static int utmp_claim_tdb(const connection_struct *conn) -{ - struct utmp_tdb_data udata; - int i, slotnum; - TDB_DATA kbuf, dbuf; - - if (!tdb_utmp) { - tdb_utmp = tdb_open(lock_path("utmp.tdb"), 0, - TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); - } - if (!tdb_utmp) return(-1); - - DEBUG(2,("utmp_claim_tdb: entered\n")); - - ZERO_STRUCT(udata); - udata.pid = sys_getpid(); - udata.cnum = conn ? conn->cnum : -1; - - dbuf.dptr = (char *) &udata; - dbuf.dsize = sizeof(udata); - - /* The key is simply a number as close as possible to zero: find it */ - slotnum = -1; - /* stop loop when overflow +ve integers (a huge, busy machine!) */ - for (i = 0; i >= 0 ; i++) { - kbuf.dptr = (char *) &i; - kbuf.dsize = sizeof(i); - - if (tdb_store(tdb_utmp, kbuf, dbuf, TDB_INSERT) == 0) { - /* have successfully grabbed a free slot */ - slotnum = i; - - /* store the inverse for faster utmp_yield_tdb() */ - tdb_store(tdb_utmp, dbuf, kbuf, TDB_INSERT); - - break; /* Got it; escape */ - } - } - if (slotnum < 0) { /* more connections than positive integers! */ - DEBUG(2,("utmp_claim_tdb: failed\n")); - return(-1); - } - - DEBUG(2,("utmp_claim_tdb: leaving with %d\n", slotnum)); - - return(slotnum); -} - -static int utmp_yield_tdb(const connection_struct *conn) -{ - struct utmp_tdb_data revkey; - int i, slotnum; - TDB_DATA kbuf, dbuf; - - if (!tdb_utmp) { - return(-1); - } - - DEBUG(2,("utmp_yield_tdb: entered\n")); - - ZERO_STRUCT(revkey); - revkey.pid = sys_getpid(); - revkey.cnum = conn ? conn->cnum : -1; - - kbuf.dptr = (char *) &revkey; - kbuf.dsize = sizeof(revkey); - - dbuf = tdb_fetch(tdb_utmp, kbuf); - if (dbuf.dptr == NULL) { - DEBUG(2,("utmp_yield_tdb: failed\n")); - return(-1); /* shouldn't happen */ - } - - /* Save our result */ - slotnum = (int) dbuf.dptr; - - /* Tidy up */ - tdb_delete(tdb_utmp, kbuf); - tdb_delete(tdb_utmp, dbuf); - - free(dbuf.dptr); - DEBUG(2,("utmp_yield_tdb: leaving with %d\n", slotnum)); - - return(slotnum); -} - -#if defined(HAVE_UT_UT_ID) -/**************************************************************************** -encode the unique connection number into "ut_id" -****************************************************************************/ -static const char *ut_id_encstr = - "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -static -int -ut_id_encode(int i, char *fourbyte) -{ - int nbase; - - fourbyte[0] = 'S'; - fourbyte[1] = 'M'; - -/* - * Encode remaining 2 bytes from 'i'. - * 'ut_id_encstr' is the character set on which modulo arithmetic is done. - * Example: digits would produce the base-10 numbers from '001'. - */ - nbase = strlen(ut_id_encstr); - - fourbyte[3] = ut_id_encstr[i % nbase]; - i /= nbase; - fourbyte[2] = ut_id_encstr[i % nbase]; - i /= nbase; - - return(i); /* 0: good; else overflow */ -} -#endif /* defined(HAVE_UT_UT_ID) */ - -/* - * ut_line: - * size small, e.g. Solaris: 12; FreeBSD: 8 - * pattern conventions differ across systems. - * So take care in tweaking the template below. - * Arguably, this could be yet another smb.conf parameter. - */ -static const char *ut_line_template = -#if defined(__FreeBSD__) - "smb%d" ; -#else - "smb/%d" ; -#endif - -/**************************************************************************** -Fill in a utmp (not utmpx) template -****************************************************************************/ -static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid, - int i, pstring host) -{ -#if defined(HAVE_UT_UT_TIME) - struct timeval timeval; -#endif /* defined(HAVE_UT_UT_TIME) */ - char line_tmp[1024]; /* plenty big enough for slprintf() */ - int line_len; - int rc = 0; - -/* - * ut_name, ut_user: - * Several (all?) systems seems to define one as the other. - * It is easier and clearer simply to let the following take its course, - * rather than to try to detect and optimise. - */ -#if defined(HAVE_UT_UT_USER) - pstrcpy(u->ut_user, conn->user); -#endif /* defined(HAVE_UT_UT_USER) */ - -#if defined(HAVE_UT_UT_NAME) - pstrcpy(u->ut_name, conn->user); -#endif /* defined(HAVE_UT_UT_NAME) */ - -/* - * ut_line: - * If size limit proves troublesome, then perhaps use "ut_id_encode()". - * - * Temporary variable "line_tmp" avoids trouble: - * o with unwanted trailing NULL if ut_line full; - * o with overflow if ut_line would be more than full. - */ - memset(line_tmp, '\0', sizeof(line_tmp)); - slprintf(line_tmp, sizeof(line_tmp)-1, (char *) ut_line_template, i); - line_len = strlen(line_tmp); - if (line_len <= sizeof(u->ut_line)) { - memcpy(u->ut_line, line_tmp, sizeof(u->ut_line)); - } - else { - DEBUG(1,("utmp_fill: ut_line exceeds field length(%d > %d)\n", - line_len, sizeof(u->ut_line))); - return(1); - } - -#if defined(HAVE_UT_UT_PID) - u->ut_pid = pid; -#endif /* defined(HAVE_UT_UT_PID) */ - -/* - * ut_time, ut_tv: - * Some have one, some the other. Many have both, but defined (aliased). - * It is easier and clearer simply to let the following take its course. - * But note that we do the more precise ut_tv as the final assignment. - */ -#if defined(HAVE_UT_UT_TIME) - gettimeofday(&timeval, NULL); - u->ut_time = timeval.tv_sec; -#endif /* defined(HAVE_UT_UT_TIME) */ - -#if defined(HAVE_UT_UT_TV) - gettimeofday(&timeval, NULL); - u->ut_tv = timeval; -#endif /* defined(HAVE_UT_UT_TV) */ - -#if defined(HAVE_UT_UT_HOST) - if (host) { - pstrcpy(u->ut_host, host); - } -#endif /* defined(HAVE_UT_UT_HOST) */ - -#if defined(HAVE_UT_UT_ADDR) - /* - * "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20. - * Volunteer to implement, please ... - */ -#endif /* defined(HAVE_UT_UT_ADDR) */ - -#if defined(HAVE_UT_UT_ID) - rc = ut_id_encode(i, u->ut_id); -#endif /* defined(HAVE_UT_UT_ID) */ - - return(rc); -} - -/**************************************************************************** -Default paths to various {u,w}tmp{,x} files -****************************************************************************/ -#ifdef HAVE_UTMPX_H - -static const char *ux_pathname = -# if defined (UTMPX_FILE) - UTMPX_FILE ; -# elif defined (_UTMPX_FILE) - _UTMPX_FILE ; -# elif defined (_PATH_UTMPX) - _PATH_UTMPX ; -# else - "" ; -# endif - -static const char *wx_pathname = -# if defined (WTMPX_FILE) - WTMPX_FILE ; -# elif defined (_WTMPX_FILE) - _WTMPX_FILE ; -# elif defined (_PATH_WTMPX) - _PATH_WTMPX ; -# else - "" ; -# endif - -#endif /* HAVE_UTMPX_H */ - -static const char *ut_pathname = -# if defined (UTMP_FILE) - UTMP_FILE ; -# elif defined (_UTMP_FILE) - _UTMP_FILE ; -# elif defined (_PATH_UTMP) - _PATH_UTMP ; -# else - "" ; -# endif - -static const char *wt_pathname = -# if defined (WTMP_FILE) - WTMP_FILE ; -# elif defined (_WTMP_FILE) - _WTMP_FILE ; -# elif defined (_PATH_WTMP) - _PATH_WTMP ; -# else - "" ; -# endif - -/* BSD-like systems might want "lastlog" support. */ -/* *** Not yet implemented */ -#ifndef HAVE_PUTUTLINE /* see "pututline_my()" */ -static const char *ll_pathname = -# if defined (_PATH_LASTLOG) /* what other names (if any?) */ - _PATH_LASTLOG ; -# else - "" ; -# endif /* _PATH_LASTLOG */ -#endif /* HAVE_PUTUTLINE */ - -/* - * Get name of {u,w}tmp{,x} file. - * return: fname contains filename - * Possibly empty if this code not yet ported to this system. - * - * utmp{,x}: try "utmp dir", then default (a define) - * wtmp{,x}: try "wtmp dir", then "utmp dir", then default (a define) - */ -static void uw_pathname(pstring fname, const char *uw_name, const char *uw_default) -{ - pstring dirname; - - pstrcpy(dirname, ""); - - /* For w-files, first look for explicit "wtmp dir" */ - if (uw_name[0] == 'w') { - pstrcpy(dirname,lp_wtmpdir()); - trim_string(dirname,"","/"); - } - - /* For u-files and non-explicit w-dir, look for "utmp dir" */ - if (dirname == 0 || strlen(dirname) == 0) { - pstrcpy(dirname,lp_utmpdir()); - trim_string(dirname,"","/"); - } - - /* If explicit directory above, use it */ - if (dirname != 0 && strlen(dirname) != 0) { - pstrcpy(fname, dirname); - pstrcat(fname, "/"); - pstrcat(fname, uw_name); - return; - } - - /* No explicit directory: attempt to use default paths */ - if (strlen(uw_default) == 0) { - /* No explicit setting, no known default. - * Has it yet been ported to this OS? - */ - DEBUG(2,("uw_pathname: unable to determine pathname\n")); - } - pstrcpy(fname, uw_default); -} - -#ifndef HAVE_PUTUTLINE -/**************************************************************************** -Update utmp file directly. No subroutine interface: probably a BSD system. -****************************************************************************/ -static void pututline_my(pstring uname, struct utmp *u, BOOL claim) -{ - DEBUG(1,("pututline_my: not yet implemented\n")); - /* BSD implementor: may want to consider (or not) adjusting "lastlog" */ -} -#endif /* HAVE_PUTUTLINE */ - -#ifndef HAVE_UPDWTMP -/**************************************************************************** -Update wtmp file directly. No subroutine interface: probably a BSD system. -Credit: Michail Vidiassov -****************************************************************************/ -static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) -{ - int fd; - struct stat buf; - - if (! claim) { - /* - * BSD-like systems: - * may use empty ut_name to distinguish a logout record. - * - * May need "if defined(SUNOS4)" etc. around some of these, - * but try to avoid if possible. - * - * SunOS 4: - * man page indicates ut_name and ut_host both NULL - * FreeBSD 4.0: - * man page appears not to specify (hints non-NULL) - * A correspondent suggest at least ut_name should be NULL - */ - memset((char *)&(u->ut_name), '\0', sizeof(u->ut_name)); - memset((char *)&(u->ut_host), '\0', sizeof(u->ut_host)); - } - /* Stolen from logwtmp function in libutil. - * May be more locking/blocking is needed? - */ - if ((fd = open(wname, O_WRONLY|O_APPEND, 0)) < 0) - return; - if (fstat(fd, &buf) == 0) { - if (write(fd, (char *)u, sizeof(struct utmp)) != sizeof(struct utmp)) - (void) ftruncate(fd, buf.st_size); - } - (void) close(fd); -} -#endif /* HAVE_UPDWTMP */ - -/**************************************************************************** -Update via utmp/wtmp (not utmpx/wtmpx) -****************************************************************************/ -static void utmp_nox_update(struct utmp *u, pstring host, BOOL claim) -{ - pstring uname, wname; -#if defined(PUTUTLINE_RETURNS_UTMP) - struct utmp *urc; -#endif /* PUTUTLINE_RETURNS_UTMP */ - - uw_pathname(uname, "utmp", ut_pathname); - DEBUG(2,("utmp_nox_update: uname:%s\n", uname)); - -#ifdef HAVE_PUTUTLINE - if (strlen(uname) != 0) { - utmpname(uname); - } - -# if defined(PUTUTLINE_RETURNS_UTMP) - setutent(); - urc = pututline(u); - endutent(); - if (urc == NULL) { - DEBUG(2,("utmp_nox_update: pututline() failed\n")); - return; - } -# else /* PUTUTLINE_RETURNS_UTMP */ - setutent(); - pututline(u); - endutent(); -# endif /* PUTUTLINE_RETURNS_UTMP */ - -#else /* HAVE_PUTUTLINE */ - if (strlen(uname) != 0) { - pututline_my(uname, u, claim); - } -#endif /* HAVE_PUTUTLINE */ - - uw_pathname(wname, "wtmp", wt_pathname); - DEBUG(2,("utmp_nox_update: wname:%s\n", wname)); - if (strlen(wname) != 0) { -#ifdef HAVE_UPDWTMP - updwtmp(wname, u); - /* - * updwtmp() and the newer updwtmpx() may be unsymmetrical. - * At least one OS, Solaris 2.x declares the former in the - * "utmpx" (latter) file and context. - * In the Solaris case this is irrelevant: it has both and - * we always prefer the "x" case, so doesn't come here. - * But are there other systems, with no "x", which lack - * updwtmp() perhaps? - */ -#else - updwtmp_my(wname, u, claim); -#endif /* HAVE_UPDWTMP */ - } -} - -/**************************************************************************** -Update via utmpx/wtmpx (preferred) or via utmp/wtmp -****************************************************************************/ -static void utmp_update(struct utmp *u, pstring host, BOOL claim) -{ -#if !defined(HAVE_UTMPX_H) - /* No utmpx stuff. Drop to non-x stuff */ - utmp_nox_update(u, host, claim); -#elif !defined(HAVE_PUTUTXLINE) - /* Odd. Have utmpx.h but no "pututxline()". Drop to non-x stuff */ - DEBUG(1,("utmp_update: have utmpx.h but no pututxline() function\n")); - utmp_nox_update(u, host, claim); -#elif !defined(HAVE_GETUTMPX) - /* Odd. Have utmpx.h but no "getutmpx()". Drop to non-x stuff */ - DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n")); - utmp_nox_update(u, host, claim); -#else - pstring uname, wname; - struct utmpx ux, *uxrc; - - getutmpx(u, &ux); - if (host) { -#if defined(HAVE_UX_UT_SYSLEN) - ux.ut_syslen = strlen(host) + 1; /* include end NULL */ -#endif /* defined(HAVE_UX_UT_SYSLEN) */ - pstrcpy(ux.ut_host, host); - } - - uw_pathname(uname, "utmpx", ux_pathname); - uw_pathname(wname, "wtmpx", wx_pathname); - DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname)); - /* - * Check for either uname or wname being empty. - * Some systems, such as Redhat 6, have a "utmpx.h" which doesn't - * define default filenames. - * Also, our local installation has not provided an override. - * Drop to non-x method. (E.g. RH6 has good defaults in "utmp.h".) - */ - if ((strlen(uname) == 0) || (strlen(wname) == 0)) { - utmp_nox_update(u, host, claim); - } - else { - utmpxname(uname); - setutxent(); - uxrc = pututxline(&ux); - endutxent(); - if (uxrc == NULL) { - DEBUG(2,("utmp_update: pututxline() failed\n")); - return; - } -#ifdef HAVE_UPDWTMPX - updwtmpx(wname, &ux); -#else - /* Have utmpx.h but no "updwtmpx()". */ - DEBUG(1,("utmp_update: no updwtmpx() function\n")); -#endif /* HAVE_UPDWTMPX */ - } -#endif /* HAVE_UTMPX_H */ -} - -/* - * "utmp consolidate": some background: - * False (default): - * In "utmp" files note every connection via this process. - * Argument "i" is simply a tty-like number we can use as-is. - * True: - * In "utmp" files, only note first open and final close. Keep: - * o count of open processes; - * o record value of first "i", to use as "i" in final close. - */ -static int utmp_count = 0; -static int utmp_consolidate_conn_num; - -/**************************************************************************** -close a connection -****************************************************************************/ -static void utmp_yield(pid_t pid, const connection_struct *conn) -{ - struct utmp u; - int conn_num, i; - - if (! lp_utmp(SNUM(conn))) { - DEBUG(2,("utmp_yield: lp_utmp() NULL\n")); - return; - } - - i = utmp_yield_tdb(conn); - if (i < 0) { - DEBUG(2,("utmp_yield: utmp_yield_tdb() failed\n")); - return; - } - conn_num = i; - DEBUG(2,("utmp_yield: conn: user:%s cnum:%d i:%d (utmp_count:%d)\n", - conn->user, conn->cnum, i, utmp_count)); - - utmp_count -= 1; - if (lp_utmp_consolidate()) { - if (utmp_count > 0) { - DEBUG(2,("utmp_yield: utmp consolidate: %d entries still open\n", utmp_count)); - return; - } - else { - /* consolidate; final close: override conn_num */ - conn_num = utmp_consolidate_conn_num; - } - } - - memset((char *)&u, '\0', sizeof(struct utmp)); - -#if defined(HAVE_UT_UT_EXIT) - u.ut_exit.e_termination = 0; - u.ut_exit.e_exit = 0; -#endif /* defined(HAVE_UT_UT_EXIT) */ - -#if defined(HAVE_UT_UT_TYPE) - u.ut_type = DEAD_PROCESS; -#endif /* defined(HAVE_UT_UT_TYPE) */ - - if (utmp_fill(&u, conn, pid, conn_num, NULL) == 0) { - utmp_update(&u, NULL, False); - } -} - -/**************************************************************************** -open a connection -****************************************************************************/ -static void utmp_claim(const struct connections_data *crec, const connection_struct *conn) -{ - struct utmp u; - pstring host; - int i; - - if (conn == NULL) { - DEBUG(2,("utmp_claim: conn NULL\n")); - return; - } - - if (! lp_utmp(SNUM(conn))) { - DEBUG(2,("utmp_claim: lp_utmp() NULL\n")); - return; - } - - i = utmp_claim_tdb(conn); - if (i < 0) { - DEBUG(2,("utmp_claim: utmp_claim_tdb() failed\n")); - return; - } - - pstrcpy(host, lp_utmp_hostname()); - if (host == 0 || strlen(host) == 0) { - pstrcpy(host, crec->machine); - } - else { - /* explicit "utmp host": expand for any "%" variables */ - standard_sub_basic(host); - } - - DEBUG(2,("utmp_claim: conn: user:%s cnum:%d i:%d (utmp_count:%d)\n", - conn->user, conn->cnum, i, utmp_count)); - DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s host:%s\n", - crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name(), host)); - - utmp_count += 1; - if (lp_utmp_consolidate()) { - if (utmp_count > 1) { - DEBUG(2,("utmp_claim: utmp consolidate: %d entries already open\n", (utmp_count-1))); - return; - } - else { - /* consolidate; first open: keep record of "i" */ - utmp_consolidate_conn_num = i; - } - } - - memset((char *)&u, '\0', sizeof(struct utmp)); - -#if defined(HAVE_UT_UT_TYPE) - u.ut_type = USER_PROCESS; -#endif /* defined(HAVE_UT_UT_TYPE) */ - - if (utmp_fill(&u, conn, crec->pid, i, host) == 0) { - utmp_update(&u, host, True); - } -} - -#endif /* WITH_UTMP */ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fa973dd720..6c0fe79845 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -110,8 +110,9 @@ user_struct *get_valid_user_struct(uint16 vuid) for (usp=validated_users;usp;usp=usp->next,count++) { if (vuid == usp->vuid) { - if (count > 10) - DLIST_PROMOTE(validated_users, usp); + if (count > 10) { + DLIST_PROMOTE(validated_users, usp); + } return usp; } } @@ -129,6 +130,8 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; + session_yield(vuid); + DLIST_REMOVE(validated_users, vuser); safe_free(vuser->groups); @@ -137,6 +140,20 @@ void invalidate_vuid(uint16 vuid) num_validated_vuids--; } +/**************************************************************************** +invalidate all vuid entries for this process +****************************************************************************/ +void invalidate_all_vuids(void) +{ + user_struct *usp, *next=NULL; + + for (usp=validated_users;usp;usp=next) { + next = usp->next; + + invalidate_vuid(usp->vuid); + } +} + /**************************************************************************** return a validated username ****************************************************************************/ @@ -244,8 +261,8 @@ has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest) +int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, + char *domain,BOOL guest) { user_struct *vuser = NULL; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -305,12 +322,15 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); - fstrcpy(vuser->user.full_name, ""); - if (lp_unix_realname()) { - if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); - fstrcpy(vuser->user.full_name, pwfile->pw_gecos); - } + if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); + fstrcpy(vuser->user.full_name, pwfile->pw_gecos); + } + + if (!session_claim(vuser->vuid)) { + DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid)); + invalidate_vuid(vuser->vuid); + return -1; } return vuser->vuid; @@ -737,6 +757,13 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, BOOL *guest,BOOL *force,uint16 vuid) { BOOL ok = False; + user_struct *vuser = get_valid_user_struct(vuid); + + if (lp_security() > SEC_SHARE && !vuser) { + DEBUG(1,("authorise_login: refusing user %s with no session setup\n", + user)); + return False; + } *guest = False; @@ -760,9 +787,6 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) { - - user_struct *vuser = get_valid_user_struct(vuid); - /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { ok = password_ok(user,password, pwlen, NULL); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 82ac230764..15e8e9537e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -671,7 +671,7 @@ reply to a session setup command int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - uint16 sess_vuid; + int sess_vuid; gid_t gid; uid_t uid; int smb_bufsize; @@ -1037,6 +1037,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int to a uid can get through without a password, on the same VC */ sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest); + + if (sess_vuid == -1) { + return(ERROR(ERRDOS,ERRnoaccess)); + } + SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 84b7109294..d2a9a64966 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -441,12 +441,14 @@ void exit_server(char *reason) conn_close_all(); + invalidate_all_vuids(); + /* delete our entry in the connections database. */ if (lp_status(-1)) { yield_connection(NULL,"",MAXSTATUS); } - respond_to_all_remaining_local_messages(); + respond_to_all_remaining_local_messages(); decrement_smbd_process_count(); #ifdef WITH_DFS -- cgit From 3b4d7082cb9723214fe2410dd7a1e2d11d0f748f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 18 Apr 2001 16:42:07 +0000 Subject: new files for head (This used to be commit c0d4a1f5dd34e49843c879dd88fc78c7dffd9269) --- source3/smbd/session.c | 175 +++++++++++++++ source3/smbd/utmp.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 750 insertions(+) create mode 100644 source3/smbd/session.c create mode 100644 source3/smbd/utmp.c (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c new file mode 100644 index 0000000000..653a3d9c02 --- /dev/null +++ b/source3/smbd/session.c @@ -0,0 +1,175 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + session handling for utmp and PAM + Copyright (C) tridge@samba.org 2001 + Copyright (C) abartlet@pcug.org.au 2001 + + 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. +*/ + +/* a "session" is claimed when we do a SessionSetupX operation + and is yielded when the corresponding vuid is destroyed. + + sessions are used to populate utmp and PAM session structures +*/ + +#include "includes.h" + +#if defined(WITH_PAM) || defined(WITH_UTMP) + +static TDB_CONTEXT *tdb; +struct sessionid { + fstring username; + fstring hostname; + fstring id_str; + uint32 id_num; + uint32 pid; +}; + +/* called when a session is created */ +BOOL session_claim(uint16 vuid) +{ + user_struct *vuser = get_valid_user_struct(vuid); + int i; + TDB_DATA data; + struct sessionid sessionid; + pstring dbuf; + int dlen; + uint32 pid = (uint32)sys_getpid(); + TDB_DATA key; + fstring keystr; + + vuser->session_id = 0; + + /* don't register sessions for the guest user - its just too + expensive to go through pam session code for browsing etc */ + if (strequal(vuser->user.unix_name,lp_guestaccount(-1))) { + return True; + } + + if (!tdb) { + tdb = tdb_open(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT, 0644); + if (!tdb) { + DEBUG(1,("session_claim: failed to open sessionid tdb\n")); + return False; + } + } + + ZERO_STRUCT(sessionid); + + data.dptr = NULL; + data.dsize = 0; + + for (i=1;iuser.unix_name); + fstrcpy(sessionid.hostname, lp_utmp_hostname()); + slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_TEMPLATE, i); + sessionid.id_num = i; + sessionid.pid = pid; + + dlen = tdb_pack(dbuf, sizeof(dbuf), "fffdd", + sessionid.username, sessionid.hostname, sessionid.id_str, + sessionid.id_num, sessionid.pid); + + data.dptr = dbuf; + data.dsize = dlen; + if (tdb_store(tdb, key, data, TDB_MODIFY) != 0) { + DEBUG(1,("session_claim: unable to create session id record\n")); + return False; + } + +#if WITH_PAM + if (!pam_session(True, sessionid.username, sessionid.id_str)) { + DEBUG(1,("pam_session rejected the session for %s [%s]\n", + sessionid.username, sessionid.id_str)); + tdb_delete(tdb, key); + return False; + } +#endif + +#if WITH_UTMP + if (lp_utmp()) { + sys_utmp_claim(sessionid.username, sessionid.hostname, + sessionid.id_str, sessionid.id_num); + } +#endif + + vuser->session_id = i; + return True; +} + +/* called when a session is destroyed */ +void session_yield(uint16 vuid) +{ + user_struct *vuser = get_valid_user_struct(vuid); + TDB_DATA data; + struct sessionid sessionid; + TDB_DATA key; + fstring keystr; + + if (!tdb) return; + + if (vuser->session_id == 0) { + return; + } + + slprintf(keystr, sizeof(keystr)-1, "ID/%d", vuser->session_id); + + key.dptr = keystr; + key.dsize = strlen(keystr)+1; + + data = tdb_fetch(tdb, key); + if (data.dptr == NULL) { + return; + } + + tdb_unpack(data.dptr, data.dsize, "fffdd", + &sessionid.username, &sessionid.hostname, &sessionid.id_str, + &sessionid.id_num, &sessionid.pid); + +#if WITH_UTMP + if (lp_utmp()) { + sys_utmp_yield(sessionid.username, sessionid.hostname, + sessionid.id_str, sessionid.id_num); + } +#endif + +#if WITH_PAM + pam_session(False, sessionid.username, sessionid.id_str); +#endif + + tdb_delete(tdb, key); +} + +#else + /* null functions - no session support needed */ + BOOL session_claim(uint16 vuid) { return True; } + void session_yield(uint16 vuid) {} +#endif diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c new file mode 100644 index 0000000000..486c7fe06e --- /dev/null +++ b/source3/smbd/utmp.c @@ -0,0 +1,575 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + utmp routines + Copyright (C) T.D.Lee@durham.ac.uk 1999 + Heavily modified by Andrew Bartlett and Tridge, April 2001 + + 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" + +#ifdef WITH_UTMP + +/**************************************************************************** +Reflect connection status in utmp/wtmp files. + T.D.Lee@durham.ac.uk September 1999 + + With grateful thanks since then to many who have helped port it to + different operating systems. The variety of OS quirks thereby + uncovered is amazing... + +Hints for porting: + o Always attempt to use programmatic interface (pututline() etc.) + Indeed, at present only programmatic use is supported. + o The only currently supported programmatic interface to "wtmp{,x}" + is through "updwtmp*()" routines. + o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable. + o The HAVE_* items should identify supported features. + o If at all possible, avoid "if defined(MY-OS)" constructions. + +OS observations and status: + Almost every OS seems to have its own quirks. + + Solaris 2.x: + Tested on 2.6 and 2.7; should be OK on other flavours. + AIX: + Apparently has utmpx.h but doesn't implement. + OSF: + Has utmpx.h, but (e.g.) no "getutmpx()". (Is this like AIX ?) + Redhat 6: + utmpx.h seems not to set default filenames. non-x better. + IRIX 6.5: + Not tested. Appears to have "x". + HP-UX 9.x: + Not tested. Appears to lack "x". + HP-UX 10.x: + Not tested. + "updwtmp*()" routines seem absent, so no current wtmp* support. + Has "ut_addr": probably trivial to implement (although remember + that IPv6 is coming...). + + FreeBSD: + No "putut*()" type of interface. + No "ut_type" and associated defines. + Write files directly. Alternatively use its login(3)/logout(3). + SunOS 4: + Not tested. Resembles FreeBSD, but no login()/logout(). + +lastlog: + Should "lastlog" files, if any, be updated? + BSD systems (SunOS 4, FreeBSD): + o Prominent mention on man pages. + System-V (e.g. Solaris 2): + o No mention on man pages, even under "man -k". + o Has a "/var/adm/lastlog" file, but pututxline() etc. seem + not to touch it. + o Despite downplaying (above), nevertheless has . + So perhaps UN*X "lastlog" facility is intended for tty/terminal only? + +Notes: + Each connection requires a small number (starting at 0, working up) + to represent the line (unum). This must be unique within and across + all smbd processes. + + The 4 byte 'ut_id' component is vital to distinguish connections, + of which there could be several hundered or even thousand. + Entries seem to be printable characters, with optional NULL pads. + + We need to be distinct from other entries in utmp/wtmp. + + Observed things: therefore avoid them. Add to this list please. + From Solaris 2.x (because that's what I have): + 'sN' : run-levels; N: [0-9] + 'co' : console + 'CC' : arbitrary things; C: [a-z] + 'rXNN' : rlogin; N: [0-9]; X: [0-9a-z] + 'tXNN' : rlogin; N: [0-9]; X: [0-9a-z] + '/NNN' : Solaris CDE + 'ftpZ' : ftp (Z is the number 255, aka 0377, aka 0xff) + Mostly a record uses the same 'ut_id' in both "utmp" and "wtmp", + but differences have been seen. + + Arbitrarily I have chosen to use a distinctive 'SM' for the + first two bytes. + + The remaining two encode the "unum" (see above). + + For "utmp consolidate" the suggestion was made to encode the pid into + those remaining two bytes (16 bits). But recent UNIX (e.g Solaris 8) + is migrating to pids > 16 bits, so we ought not to do this. + +****************************************************************************/ + +#include + +#ifdef HAVE_UTMPX_H +#include +#endif + +/* BSD systems: some may need lastlog.h (SunOS 4), some may not (FreeBSD) */ +/* Some System-V systems (e.g. Solaris 2) declare this too. */ +#ifdef HAVE_LASTLOG_H +#include +#endif + +/**************************************************************************** +obtain/release a small number (0 upwards) unique within and across smbds +****************************************************************************/ +/* + * Need a "small" number to represent this connection, unique within this + * smbd and across all smbds. + * + * claim: + * Start at 0, hunt up for free, unique number "unum" by attempting to + * store it as a key in a tdb database: + * key: unum data: pid+conn + * Also store its inverse, ready for yield function: + * key: pid+conn data: unum + * + * yield: + * Find key: pid+conn; data is unum; delete record + * Find key: unum ; delete record. + * + * Comment: + * The claim algorithm (a "for" loop attempting to store numbers in a tdb + * database) will be increasingly inefficient with larger numbers of + * connections. Is it possible to write a suitable primitive within tdb? + * + * However, by also storing the inverse key/data pair, we at least make + * the yield algorithm efficient. + */ + +/**************************************************************************** +Default paths to various {u,w}tmp{,x} files +****************************************************************************/ +#ifdef HAVE_UTMPX_H + +static const char *ux_pathname = +# if defined (UTMPX_FILE) + UTMPX_FILE ; +# elif defined (_UTMPX_FILE) + _UTMPX_FILE ; +# elif defined (_PATH_UTMPX) + _PATH_UTMPX ; +# else + "" ; +# endif + +static const char *wx_pathname = +# if defined (WTMPX_FILE) + WTMPX_FILE ; +# elif defined (_WTMPX_FILE) + _WTMPX_FILE ; +# elif defined (_PATH_WTMPX) + _PATH_WTMPX ; +# else + "" ; +# endif + +#endif /* HAVE_UTMPX_H */ + +static const char *ut_pathname = +# if defined (UTMP_FILE) + UTMP_FILE ; +# elif defined (_UTMP_FILE) + _UTMP_FILE ; +# elif defined (_PATH_UTMP) + _PATH_UTMP ; +# else + "" ; +# endif + +static const char *wt_pathname = +# if defined (WTMP_FILE) + WTMP_FILE ; +# elif defined (_WTMP_FILE) + _WTMP_FILE ; +# elif defined (_PATH_WTMP) + _PATH_WTMP ; +# else + "" ; +# endif + +/* BSD-like systems might want "lastlog" support. */ +/* *** Not yet implemented */ +#ifndef HAVE_PUTUTLINE /* see "pututline_my()" */ +static const char *ll_pathname = +# if defined (_PATH_LASTLOG) /* what other names (if any?) */ + _PATH_LASTLOG ; +# else + "" ; +# endif /* _PATH_LASTLOG */ +#endif /* HAVE_PUTUTLINE */ + +/* + * Get name of {u,w}tmp{,x} file. + * return: fname contains filename + * Possibly empty if this code not yet ported to this system. + * + * utmp{,x}: try "utmp dir", then default (a define) + * wtmp{,x}: try "wtmp dir", then "utmp dir", then default (a define) + */ +static void uw_pathname(pstring fname, const char *uw_name, const char *uw_default) +{ + pstring dirname; + + pstrcpy(dirname, ""); + + /* For w-files, first look for explicit "wtmp dir" */ + if (uw_name[0] == 'w') { + pstrcpy(dirname,lp_wtmpdir()); + trim_string(dirname,"","/"); + } + + /* For u-files and non-explicit w-dir, look for "utmp dir" */ + if (dirname == 0 || strlen(dirname) == 0) { + pstrcpy(dirname,lp_utmpdir()); + trim_string(dirname,"","/"); + } + + /* If explicit directory above, use it */ + if (dirname != 0 && strlen(dirname) != 0) { + pstrcpy(fname, dirname); + pstrcat(fname, "/"); + pstrcat(fname, uw_name); + return; + } + + /* No explicit directory: attempt to use default paths */ + if (strlen(uw_default) == 0) { + /* No explicit setting, no known default. + * Has it yet been ported to this OS? + */ + DEBUG(2,("uw_pathname: unable to determine pathname\n")); + } + pstrcpy(fname, uw_default); +} + +#ifndef HAVE_PUTUTLINE +/**************************************************************************** +Update utmp file directly. No subroutine interface: probably a BSD system. +****************************************************************************/ +static void pututline_my(pstring uname, struct utmp *u, BOOL claim) +{ + DEBUG(1,("pututline_my: not yet implemented\n")); + /* BSD implementor: may want to consider (or not) adjusting "lastlog" */ +} +#endif /* HAVE_PUTUTLINE */ + +#ifndef HAVE_UPDWTMP +/**************************************************************************** +Update wtmp file directly. No subroutine interface: probably a BSD system. +Credit: Michail Vidiassov +****************************************************************************/ +static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) +{ + int fd; + struct stat buf; + + if (! claim) { + /* + * BSD-like systems: + * may use empty ut_name to distinguish a logout record. + * + * May need "if defined(SUNOS4)" etc. around some of these, + * but try to avoid if possible. + * + * SunOS 4: + * man page indicates ut_name and ut_host both NULL + * FreeBSD 4.0: + * man page appears not to specify (hints non-NULL) + * A correspondent suggest at least ut_name should be NULL + */ + memset((char *)&(u->ut_name), '\0', sizeof(u->ut_name)); + memset((char *)&(u->ut_host), '\0', sizeof(u->ut_host)); + } + /* Stolen from logwtmp function in libutil. + * May be more locking/blocking is needed? + */ + if ((fd = open(wname, O_WRONLY|O_APPEND, 0)) < 0) + return; + if (fstat(fd, &buf) == 0) { + if (write(fd, (char *)u, sizeof(struct utmp)) != sizeof(struct utmp)) + (void) ftruncate(fd, buf.st_size); + } + (void) close(fd); +} +#endif /* HAVE_UPDWTMP */ + +/**************************************************************************** +Update via utmp/wtmp (not utmpx/wtmpx) +****************************************************************************/ +static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim) +{ + pstring uname, wname; +#if defined(PUTUTLINE_RETURNS_UTMP) + struct utmp *urc; +#endif /* PUTUTLINE_RETURNS_UTMP */ + + uw_pathname(uname, "utmp", ut_pathname); + DEBUG(2,("utmp_nox_update: uname:%s\n", uname)); + +#ifdef HAVE_PUTUTLINE + if (strlen(uname) != 0) { + utmpname(uname); + } + +# if defined(PUTUTLINE_RETURNS_UTMP) + setutent(); + urc = pututline(u); + endutent(); + if (urc == NULL) { + DEBUG(2,("utmp_nox_update: pututline() failed\n")); + return; + } +# else /* PUTUTLINE_RETURNS_UTMP */ + setutent(); + pututline(u); + endutent(); +# endif /* PUTUTLINE_RETURNS_UTMP */ + +#else /* HAVE_PUTUTLINE */ + if (strlen(uname) != 0) { + pututline_my(uname, u, claim); + } +#endif /* HAVE_PUTUTLINE */ + + uw_pathname(wname, "wtmp", wt_pathname); + DEBUG(2,("utmp_nox_update: wname:%s\n", wname)); + if (strlen(wname) != 0) { +#ifdef HAVE_UPDWTMP + updwtmp(wname, u); + /* + * updwtmp() and the newer updwtmpx() may be unsymmetrical. + * At least one OS, Solaris 2.x declares the former in the + * "utmpx" (latter) file and context. + * In the Solaris case this is irrelevant: it has both and + * we always prefer the "x" case, so doesn't come here. + * But are there other systems, with no "x", which lack + * updwtmp() perhaps? + */ +#else + updwtmp_my(wname, u, claim); +#endif /* HAVE_UPDWTMP */ + } +} + +/**************************************************************************** +Update via utmpx/wtmpx (preferred) or via utmp/wtmp +****************************************************************************/ +static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) +{ +#if !defined(HAVE_UTMPX_H) + /* No utmpx stuff. Drop to non-x stuff */ + utmp_nox_update(u, hostname, claim); +#elif !defined(HAVE_PUTUTXLINE) + /* Odd. Have utmpx.h but no "pututxline()". Drop to non-x stuff */ + DEBUG(1,("utmp_update: have utmpx.h but no pututxline() function\n")); + utmp_nox_update(u, hostname, claim); +#elif !defined(HAVE_GETUTMPX) + /* Odd. Have utmpx.h but no "getutmpx()". Drop to non-x stuff */ + DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n")); + utmp_nox_update(u, hostname, claim); +#else + pstring uname, wname; + struct utmpx ux, *uxrc; + + getutmpx(u, &ux); + +#if defined(HAVE_UX_UT_SYSLEN) + ux.ut_syslen = strlen(hostname) + 1; /* include end NULL */ +#endif + safe_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)-1); + + uw_pathname(uname, "utmpx", ux_pathname); + uw_pathname(wname, "wtmpx", wx_pathname); + DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname)); + /* + * Check for either uname or wname being empty. + * Some systems, such as Redhat 6, have a "utmpx.h" which doesn't + * define default filenames. + * Also, our local installation has not provided an override. + * Drop to non-x method. (E.g. RH6 has good defaults in "utmp.h".) + */ + if ((strlen(uname) == 0) || (strlen(wname) == 0)) { + utmp_nox_update(u, hostname, claim); + } else { + utmpxname(uname); + setutxent(); + uxrc = pututxline(&ux); + endutxent(); + if (uxrc == NULL) { + DEBUG(2,("utmp_update: pututxline() failed\n")); + return; + } + updwtmpx(wname, &ux); + } +#endif /* HAVE_UTMPX_H */ +} + +#if defined(HAVE_UT_UT_ID) +/**************************************************************************** +encode the unique connection number into "ut_id" +****************************************************************************/ +static int ut_id_encode(int i, char *fourbyte) +{ + int nbase; + char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + fourbyte[0] = 'S'; + fourbyte[1] = 'M'; + +/* + * Encode remaining 2 bytes from 'i'. + * 'ut_id_encstr' is the character set on which modulo arithmetic is done. + * Example: digits would produce the base-10 numbers from '001'. + */ + nbase = strlen(ut_id_encstr); + + fourbyte[3] = ut_id_encstr[i % nbase]; + i /= nbase; + fourbyte[2] = ut_id_encstr[i % nbase]; + i /= nbase; + + return(i); /* 0: good; else overflow */ +} +#endif /* defined(HAVE_UT_UT_ID) */ + + +/* + fill a system utmp structure given all the info we can gather +*/ +static BOOL sys_utmp_fill(struct utmp *u, + const char *username, const char *hostname, + const char *id_str, int id_num) +{ + struct timeval timeval; + + /* + * ut_name, ut_user: + * Several (all?) systems seems to define one as the other. + * It is easier and clearer simply to let the following take its course, + * rather than to try to detect and optimise. + */ +#if defined(HAVE_UT_UT_USER) + safe_strcpy(u->ut_user, username, sizeof(u->ut_user)-1); +#elif defined(HAVE_UT_UT_NAME) + safe_strcpy(u->ut_name, username, sizeof(u->ut_name)-1); +#endif + + /* + * ut_line: + * If size limit proves troublesome, then perhaps use "ut_id_encode()". + * + * Temporary variable "line_tmp" avoids trouble: + * o with unwanted trailing NULL if ut_line full; + * o with overflow if ut_line would be more than full. + */ + if (strlen(id_str) > sizeof(u->ut_line)) { + DEBUG(1,("id_str [%s] is too long for %d char utmp field\n", + id_str, sizeof(u->ut_line))); + return False; + } + memcpy(u->ut_line, id_str, sizeof(u->ut_line)); + +#if defined(HAVE_UT_UT_PID) + u->ut_pid = sys_getpid(); +#endif + +/* + * ut_time, ut_tv: + * Some have one, some the other. Many have both, but defined (aliased). + * It is easier and clearer simply to let the following take its course. + * But note that we do the more precise ut_tv as the final assignment. + */ +#if defined(HAVE_UT_UT_TIME) + gettimeofday(&timeval, NULL); + u->ut_time = timeval.tv_sec; +#elif defined(HAVE_UT_UT_TV) + gettimeofday(&timeval, NULL); + u->ut_tv = timeval; +#else +#error "with-utmp must have UT_TIME or UT_TV" +#endif + +#if defined(HAVE_UT_UT_HOST) + safe_strcpy(u->ut_host, hostname, sizeof(u->ut_host)-1); +#endif + +#if defined(HAVE_UT_UT_ADDR) + /* + * "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20. + * Volunteer to implement, please ... + */ +#endif + +#if defined(HAVE_UT_UT_ID) + if (ut_id_encode(id_num, u->ut_id) != 0) { + DEBUG(1,("utmp_fill: cannot encode id %d\n", id_num)); + return False; + } +#endif + + return True; +} + +/**************************************************************************** +close a connection +****************************************************************************/ +void sys_utmp_yield(const char *username, const char *hostname, + const char *id_str, int id_num) +{ + struct utmp u; + + ZERO_STRUCT(u); + +#if defined(HAVE_UT_UT_EXIT) + u.ut_exit.e_termination = 0; + u.ut_exit.e_exit = 0; +#endif + +#if defined(HAVE_UT_UT_TYPE) + u.ut_type = DEAD_PROCESS; +#endif + + if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return; + + sys_utmp_update(&u, NULL, False); +} + +/**************************************************************************** +claim a entry in whatever utmp system the OS uses +****************************************************************************/ +void sys_utmp_claim(const char *username, const char *hostname, + const char *id_str, int id_num) +{ + struct utmp u; + + ZERO_STRUCT(u); + +#if defined(HAVE_UT_UT_TYPE) + u.ut_type = USER_PROCESS; +#endif + + if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return; + + sys_utmp_update(&u, hostname, True); +} + +#else /* WITH_UTMP */ + void dummy_utmp(void) {} +#endif -- cgit From 6e4b0088298c926e4eb09b1c97f750e5c3feb295 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Wed, 18 Apr 2001 17:57:53 +0000 Subject: a missing string conversion. J.F. (This used to be commit 9513eb87c2d113fe27bcea2add05226495c33cb8) --- source3/smbd/pipes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 366707cd58..7a3c1fe20e 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -52,7 +52,7 @@ int reply_open_pipe_and_X(connection_struct *conn, int i; /* XXXX we need to handle passed times, sattr and flags */ - pstrcpy(fname,smb_buf(inbuf)); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ -- cgit From e129db422b7e2bf9a567ed4b778e7ca326e14a4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 21 Apr 2001 07:43:54 +0000 Subject: Fixed compile bug when using --with-pam but not --with-utmp. Jeremy. (This used to be commit 1e098744677e022547707ebff500fb4515402871) --- source3/smbd/session.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 653a3d9c02..4ede1d9a68 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -89,7 +89,14 @@ BOOL session_claim(uint16 vuid) } fstrcpy(sessionid.username, vuser->user.unix_name); +#if WITH_UTMP fstrcpy(sessionid.hostname, lp_utmp_hostname()); +#else + { + extern fstring remote_machine; + fstrcpy(sessionid.hostname, remote_machine); + } +#endif slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_TEMPLATE, i); sessionid.id_num = i; sessionid.pid = pid; -- cgit From e277c08631316ccda875a09a67ebb220c495c5a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 22 Apr 2001 07:20:24 +0000 Subject: Commit of a modified version of Andrew Bartlett's patch that removes the horrid utmp hostname parameter - now uses the client name instead. Also tidies up some of the unencrypted password checking when PAM is compiled in. FIXME ! An pam_accountcheck() is being called even when smb encrypted passwords are negotiated. Is this the correct thing to do when winbindd is running ! This needs *SEVERE* testing.... Jeremy. (This used to be commit 071c799f479dd25efdb9c41745fc8f2beea7b568) --- source3/smbd/password.c | 19 ++++++++++++++----- source3/smbd/session.c | 18 ++++++++---------- 2 files changed, 22 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6c0fe79845..698c6a1356 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -606,24 +606,33 @@ return True if the password is correct, False otherwise ****************************************************************************/ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) { + BOOL ret; + if ((pwlen == 0) && !lp_null_passwords()) { DEBUG(4,("Null passwords not allowed.\n")); return False; } - if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) - { + if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { /* if 24 bytes long assume it is an encrypted password */ uchar challenge[8]; - if (!last_challenge(challenge)) - { + if (!last_challenge(challenge)) { DEBUG(0,("Error: challenge not done for user=%s\n", user)); return False; } - return pass_check_smb(user, global_myworkgroup, + ret = pass_check_smb(user, global_myworkgroup, challenge, (uchar *)password, (uchar *)password, pwd); + + /* + * Try with PAM (may not be compiled in - returns True if not. JRA). + * FIXME ! Should this be called if we're using winbindd ? What about + * non-local accounts ? JRA. + */ + + if (ret) + return pam_accountcheck(user); } return pass_check(user, password, pwlen, pwd, diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 4ede1d9a68..fb13019812 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -51,6 +51,7 @@ BOOL session_claim(uint16 vuid) uint32 pid = (uint32)sys_getpid(); TDB_DATA key; fstring keystr; + char * hostname; vuser->session_id = 0; @@ -88,15 +89,12 @@ BOOL session_claim(uint16 vuid) return False; } + hostname = client_name(); + if (strequal(hostname,"UNKNOWN")) + hostname = client_addr(); + fstrcpy(sessionid.username, vuser->user.unix_name); -#if WITH_UTMP - fstrcpy(sessionid.hostname, lp_utmp_hostname()); -#else - { - extern fstring remote_machine; - fstrcpy(sessionid.hostname, remote_machine); - } -#endif + fstrcpy(sessionid.hostname, hostname); slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_TEMPLATE, i); sessionid.id_num = i; sessionid.pid = pid; @@ -113,7 +111,7 @@ BOOL session_claim(uint16 vuid) } #if WITH_PAM - if (!pam_session(True, sessionid.username, sessionid.id_str)) { + if (!pam_session(True, sessionid.username, sessionid.id_str, sessionid.hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", sessionid.username, sessionid.id_str)); tdb_delete(tdb, key); @@ -169,7 +167,7 @@ void session_yield(uint16 vuid) #endif #if WITH_PAM - pam_session(False, sessionid.username, sessionid.id_str); + pam_session(False, sessionid.username, sessionid.id_str, sessionid.hostname); #endif tdb_delete(tdb, key); -- cgit From ae8418d0c400f6458c1eb0b79881fd02629e5acd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Apr 2001 04:15:35 +0000 Subject: Added smb_ prefix to all Samba wrapper pam functions. Fixed off by one bug using StrnCpy instead of strdup(). Jeremy. (This used to be commit d4b1c0be2e700c86a4338bb497777f97e3c960a7) --- source3/smbd/password.c | 2 +- source3/smbd/session.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 698c6a1356..ba882f2bf2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -632,7 +632,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) */ if (ret) - return pam_accountcheck(user); + return smb_pam_accountcheck(user); } return pass_check(user, password, pwlen, pwd, diff --git a/source3/smbd/session.c b/source3/smbd/session.c index fb13019812..2f86832b4a 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -111,8 +111,8 @@ BOOL session_claim(uint16 vuid) } #if WITH_PAM - if (!pam_session(True, sessionid.username, sessionid.id_str, sessionid.hostname)) { - DEBUG(1,("pam_session rejected the session for %s [%s]\n", + if (!smb_pam_session(True, sessionid.username, sessionid.id_str, sessionid.hostname)) { + DEBUG(1,("smb_pam_session rejected the session for %s [%s]\n", sessionid.username, sessionid.id_str)); tdb_delete(tdb, key); return False; @@ -167,7 +167,7 @@ void session_yield(uint16 vuid) #endif #if WITH_PAM - pam_session(False, sessionid.username, sessionid.id_str, sessionid.hostname); + smb_pam_session(False, sessionid.username, sessionid.id_str, sessionid.hostname); #endif tdb_delete(tdb, key); -- cgit From 30daf2e939b6dbc50e9389f26f3b1f4a4d6d5c2e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Apr 2001 23:07:31 +0000 Subject: Fixed memory leak in new session code. Jeremy. (This used to be commit 43b69e5d6e78a30563d7c1d03c7e920d529487b5) --- source3/smbd/session.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 2f86832b4a..3131fb9f54 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -159,6 +159,9 @@ void session_yield(uint16 vuid) &sessionid.username, &sessionid.hostname, &sessionid.id_str, &sessionid.id_num, &sessionid.pid); + safe_free(data.dptr); + data.dptr = NULL; + #if WITH_UTMP if (lp_utmp()) { sys_utmp_yield(sessionid.username, sessionid.hostname, -- cgit From 95559fe994072bf6e6c5647f3625de1132b08cae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Apr 2001 23:25:58 +0000 Subject: Sync with default perm changes in 2.2. Jeremy. (This used to be commit f02e67a096b3bcf84615c4a6949c5e6283e07af0) --- source3/smbd/posix_acls.c | 149 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a9c8821238..c23ee00bd8 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -458,20 +458,61 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, return True; } +/**************************************************************************** + Ensure the enforced permissions for this share apply. +****************************************************************************/ + +static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type) +{ + int snum = SNUM(fsp->conn); + mode_t and_bits = (mode_t)0; + mode_t or_bits = (mode_t)0; + + /* Get the initial bits to apply. */ + + if (fsp->is_directory) { + and_bits = lp_dir_mask(snum); + or_bits = lp_force_dir_mode(snum); + } else { + and_bits = lp_create_mask(snum); + or_bits = lp_force_create_mode(snum); + } + + /* Now bounce them into the S_USR space. */ + switch(type) { + case S_IRUSR: + and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR); + or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR); + break; + case S_IRGRP: + and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP); + or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP); + break; + case S_IROTH: + and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH); + or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH); + break; + } + + return ((perms & and_bits)|or_bits); +} + /**************************************************************************** A well formed POSIX file or default ACL has at least 3 entries, a SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ. In addition, the owner must always have at least read access. When using this call on get_acl, the pst struct is valid and contains the mode of the file. When using this call on set_acl, the pst struct has - been modified to have a mode of r--------. + been modified to have a mode containing the default for this file or directory + type. ****************************************************************************/ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, files_struct *fsp, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, - SMB_STRUCT_STAT *pst) + SMB_STRUCT_STAT *pst, + BOOL setting_acl) { extern DOM_SID global_sid_World; canon_ace *pace; @@ -481,14 +522,42 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, for (pace = *pp_ace; pace; pace = pace->next) { if (pace->type == SMB_ACL_USER_OBJ) { - /* Ensure owner has read access. */ - if (pace->perms == (mode_t)0) - pace->perms = S_IRUSR; + + if (setting_acl) { + if (pace->perms == (mode_t)0) { + /* Ensure owner has read access. */ + pace->perms = S_IRUSR; + if (fsp->is_directory) + pace->perms |= (S_IWUSR|S_IXUSR); + } + + /* + * Ensure create mask/force create mode is respected on set. + */ + + pace->perms = apply_default_perms(fsp, pace->perms, S_IRUSR); + } + got_user = True; - } else if (pace->type == SMB_ACL_GROUP_OBJ) + } else if (pace->type == SMB_ACL_GROUP_OBJ) { + + /* + * Ensure create mask/force create mode is respected on set. + */ + + if (setting_acl) + pace->perms = apply_default_perms(fsp, pace->perms, S_IRGRP); got_grp = True; - else if (pace->type == SMB_ACL_OTHER) + } else if (pace->type == SMB_ACL_OTHER) { + + /* + * Ensure create mask/force create mode is respected on set. + */ + + if (setting_acl) + pace->perms = apply_default_perms(fsp, pace->perms, S_IROTH); got_other = True; + } } if (!got_user) { @@ -502,10 +571,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->owner_type = UID_ACE; pace->unix_ug.uid = pst->st_uid; pace->sid = *pfile_owner_sid; - /* Ensure owner has read access. */ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); - if (pace->perms == (mode_t)0) - pace->perms = S_IRUSR; pace->attr = ALLOW_ACE; DLIST_ADD(*pp_ace, pace); @@ -652,14 +718,17 @@ static BOOL create_canon_ace_lists(files_struct *fsp, */ if(sid_equal(¤t_ace->sid, pfile_owner_sid)) { - /* Note we should apply the default mode/mask here.... FIXME ! JRA */ + current_ace->type = SMB_ACL_USER_OBJ; + } else if( sid_equal(¤t_ace->sid, pfile_grp_sid)) { - /* Note we should apply the default mode/mask here.... FIXME ! JRA */ + current_ace->type = SMB_ACL_GROUP_OBJ; + } else if( sid_equal(¤t_ace->sid, &global_sid_World)) { - /* Note we should apply the default mode/mask here.... FIXME ! JRA */ + current_ace->type = SMB_ACL_OTHER; + } else { /* * Could be a SMB_ACL_USER or SMB_ACL_GROUP. Check by @@ -1089,6 +1158,37 @@ static void process_deny_list( canon_ace **pp_ace_list ) *pp_ace_list = ace_list; } +/**************************************************************************** + Create a default mode that will be used if a security descriptor entry has + no user/group/world entries. +****************************************************************************/ + +static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) +{ + int snum = SNUM(fsp->conn); + mode_t and_bits = (mode_t)0; + mode_t or_bits = (mode_t)0; + mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name) : S_IRUSR; + + if (fsp->is_directory) + mode |= (S_IWUSR|S_IXUSR); + + /* + * Now AND with the create mode/directory mode bits then OR with the + * force create mode/force directory mode bits. + */ + + if (fsp->is_directory) { + and_bits = lp_dir_mask(snum); + or_bits = lp_force_dir_mode(snum); + } else { + and_bits = lp_create_mask(snum); + or_bits = lp_force_create_mode(snum); + } + + return ((mode & and_bits)|or_bits); +} + /**************************************************************************** Unpack a SEC_DESC into two canonical ace lists. We don't depend on this succeeding. @@ -1166,14 +1266,12 @@ static BOOL unpack_canon_ace(files_struct *fsp, /* * A default 3 element mode entry for a file should be r-- --- ---. - * A default 3 element mode entry for a directory should be r-x --- ---. + * A default 3 element mode entry for a directory should be rwx --- ---. */ - pst->st_mode = S_IRUSR; - if (fsp->is_directory) - pst->st_mode |= S_IXUSR; + pst->st_mode = create_default_mode(fsp, False); - if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst)) { + if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -1183,15 +1281,13 @@ static BOOL unpack_canon_ace(files_struct *fsp, /* * A default inheritable 3 element mode entry for a directory should be the - * mode Samba will use to create a file within. Ensure user x bit is set if + * mode Samba will use to create a file within. Ensure user rwx bits are set if * it's a directory. */ - pst->st_mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - if (fsp->is_directory) - pst->st_mode |= S_IXUSR; + pst->st_mode = create_default_mode(fsp, True); - if (!ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst)) { + if (!ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -1206,7 +1302,6 @@ static BOOL unpack_canon_ace(files_struct *fsp, } - /****************************************************************************** When returning permissions, try and fit NT display semantics if possible. Note the the canon_entries here must have been malloced. @@ -1377,7 +1472,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * This next call will ensure we have at least a user/group/world set. */ - if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf)) + if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf, False)) goto fail; arrange_posix_perms(fsp->fsp_name,&list_head ); @@ -1387,7 +1482,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * acl_mask. Ensure all DENY Entries are at the start of the list. */ - DEBUG(10,("canonicalize_acl: ace entries before arrange :\n")); + DEBUG(10,("canonicalise_acl: ace entries before arrange :\n")); for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { next_ace = ace->next; @@ -1405,7 +1500,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ } } - print_canon_ace_list( "canonicalize_acl: ace entries after arrange", list_head ); + print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head ); return list_head; -- cgit From 77429f871772ad2efd98e4bab5d695137211f226 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Apr 2001 18:03:12 +0000 Subject: Fix from matthew.hart@veritas.com - bad error return from linux_oplock_receive_message(). Jeremy. (This used to be commit b35ca2c6b13877bc6e09c7c4179d9529a7d3e0b3) --- source3/smbd/oplock_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index e070761f10..5bf753d68c 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -127,7 +127,7 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l SMB_DEV_T dev; SMB_INO_T inode; SMB_STRUCT_STAT sbuf; - BOOL ret; + BOOL ret = True; if (signals_received == signals_processed) return False; @@ -164,7 +164,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); signals_processed++; BlockSignals(False, RT_SIGNAL_LEASE); - return True; + return ret; } -- cgit From 8f88c7cf4e2029be8b38ee9052dc12e90efcc8d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Apr 2001 19:56:15 +0000 Subject: Fixes for problems in NFS server code from Michael Gerdts . Jeremy. (This used to be commit 2fd5e0bf141807d31f6f1a817d271548d0ccfadc) --- source3/smbd/quotas.c | 64 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index ccb5534641..81da013cec 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -322,6 +322,9 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B int len; static struct timeval timeout = {2,0}; enum clnt_stat clnt_stat; + BOOL ret = True; + + *bsize = *dfree = *dsize = (SMB_BIG_UINT)0; len=strcspn(mnttype, ":"); pathname=strstr(mnttype, ":"); @@ -338,15 +341,21 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp")); - if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) { - clnt->cl_auth = authunix_create_default(); - DEBUG(9,("nfs_quotas: auth_success\n")); + if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) { + ret = False; + goto out; + } - clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout); - if (clnt_stat == RPC_SUCCESS) - DEBUG(9,("nfs_quotas: rpccall_success\n")); - }; + clnt->cl_auth = authunix_create_default(); + DEBUG(9,("nfs_quotas: auth_success\n")); + clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout); + + if (clnt_stat != RPC_SUCCESS) { + DEBUG(9,("nfs_quotas: clnt_call fail\n")); + ret = False; + goto out; + } /* * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is @@ -354,26 +363,30 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B * something sensible. */ - if (quotastat == 1) { + switch ( quotastat ) { + case 0: + DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); + ret = False; + goto out; + + case 1: DEBUG(9,("nfs_quotas: Good quota data\n")); D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; - } + break; - if (quotastat == 0 || quotastat == 3) { + case 2: + case 3: D.dqb_bsoftlimit = 1; D.dqb_curblocks = 1; - DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); - } + DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat )); + break; - if (quotastat == 2) { - DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - free(cutstr); - return(False); - } + default: + DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat )); + break; + } DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", quotastat, @@ -395,14 +408,19 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B } else *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); + out: + + if (clnt) { + if (clnt->cl_auth) + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + } DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize)); - free(cutstr); + safe_free(cutstr); DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); - return(True); + return ret; } #endif -- cgit From 38959a21052688f5897b7117450aba5b96b97b53 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Apr 2001 21:14:18 +0000 Subject: Tidy up args to DEBUG Statements - found by gcc on Solaris. Jeremy. (This used to be commit a60ecb4e53a6c8a3a6a37a89042ae943202263fe) --- source3/smbd/posix_acls.c | 2 +- source3/smbd/sec_ctx.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c23ee00bd8..0c613e8835 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1598,7 +1598,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (map_acl_perms_to_permset(p_ace->perms, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n", - p_ace->perms, i, strerror(errno) )); + (unsigned int)p_ace->perms, i, strerror(errno) )); goto done; } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f604f6cce7..f6563ffe96 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -275,8 +275,8 @@ BOOL push_sec_ctx(void) ctx_p->uid = geteuid(); ctx_p->gid = getegid(); - DEBUG(3, ("push_sec_ctx(%d, %d) : sec_ctx_stack_ndx = %d\n", - ctx_p->uid, ctx_p->gid, sec_ctx_stack_ndx )); + DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n", + (unsigned int)ctx_p->uid, (unsigned int)ctx_p->gid, sec_ctx_stack_ndx )); ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); @@ -307,14 +307,15 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN /* Set the security context */ - DEBUG(3, ("setting sec ctx (%d, %d) - sec_ctx_stack_ndx = %d\n", uid, gid, sec_ctx_stack_ndx)); + DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", + (unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx)); if (ngroups) { int i; DEBUG(3, ("%d user groups: \n", ngroups)); for (i = 0; i < ngroups; i++) { - DEBUGADD(3, ("%d ", groups[i])); + DEBUGADD(3, ("%u ", (unsigned int)groups[i])); } DEBUG(3, ("\n")); @@ -413,7 +414,8 @@ BOOL pop_sec_ctx(void) current_user.groups = prev_ctx_p->groups; current_user.nt_user_token = prev_ctx_p->token; - DEBUG(3, ("pop_sec_ctx (%d, %d) - sec_ctx_stack_ndx = %d\n", geteuid(), getegid(), sec_ctx_stack_ndx)); + DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", + (unsigned int)geteuid(), (unsigned int)getegid(), sec_ctx_stack_ndx)); return True; } -- cgit From c11887e3257c8dfe650f5004106a43a891ab4b31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Apr 2001 22:17:10 +0000 Subject: More debug %d -> %u issues. Jeremy. (This used to be commit 6fcb600dcd23c61d1a7d2ce8c2b7b2eea2e58623) --- source3/smbd/quotas.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 81da013cec..caf3997ba8 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -277,11 +277,6 @@ static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) { - gqr_status status; - union { - rquota gqr_rquota; - } getquota_rslt_u; - if (!xdr_int(xdrsp, "astat)) { DEBUG(6,("nfs_quotas: Status bad or zero\n")); return 0; @@ -456,7 +451,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return(False) ; devno = sbuf.st_dev ; - DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno)); + DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno)); if ( devno != devno_cached ) { devno_cached = devno ; #if defined(SUNOS5) @@ -464,7 +459,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U return(False) ; found = False ; - slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno); + slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno); while (getmntent(fd, &mnt) == 0) { if( !hasmntopt(&mnt, devopt) ) continue; @@ -491,7 +486,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U while ((mnt = getmntent(fd)) != NULL) { if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev)); + DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev)); if (sbuf.st_dev == devno) { found = True ; break; -- cgit From b238f4a2ffeb225d16857b594355dc60c976e3e0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 28 Apr 2001 00:05:11 +0000 Subject: rpcclient/rpcclient.c: Non-void return in void function. smbd/sec_ctx.c: Fixed potential memory leak spotted by Kenichi Okuyama@Tokyo Research Lab, IBM-Japan, Co. utils/nmblookup.c: gcc warning on Solaris fix. Jeremy. (This used to be commit 1be60597cd62af2b30a1496d06ea5704e87d3b7d) --- source3/smbd/sec_ctx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f6563ffe96..6f98e9df6b 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -152,8 +152,10 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups) return -1; } - if ((ngroups = sys_getgroups(ngroups,groups)) == -1) + if ((ngroups = sys_getgroups(ngroups,groups)) == -1) { + safe_free(groups); return -1; + } (*p_ngroups) = ngroups; (*p_groups) = groups; -- cgit From 944aeb7de472e0654561f7d8f37a5703487a973e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 28 Apr 2001 12:43:15 +0000 Subject: use asprintf for hideunreadable option (This used to be commit 338d5ca8addb3079e0ab4a68338596d6e3b17ddb) --- source3/smbd/dir.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 1d497574a6..fa9cbdc4a2 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -727,21 +727,15 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; /* Honour _hide unreadable_ option */ - if (conn && lp_hideunreadable(SNUM(conn))) - { - char *entry; - int ret; + if (conn && lp_hideunreadable(SNUM(conn))) { + char *entry; + int ret=0; - entry = (char *)malloc(PATH_MAX); - if (!entry) { - DEBUG(0,("Out of memory in OpenDir\n")); - conn->vfs_ops.closedir(conn,p); - return(NULL); - } - slprintf(entry, PATH_MAX, "%s/%s/%s", conn->origpath, name, n); - ret = user_can_read_file(conn, entry); - free(entry); - if (!ret) continue; + if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { + ret = user_can_read_file(conn, entry); + free(entry); + } + if (!ret) continue; } if (used + l > dirp->mallocsize) { -- cgit From d095b5249cf9e1496ad5a3d6b5acb77af2c587a7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 28 Apr 2001 13:49:34 +0000 Subject: - added test for vasprintf - cleaned up GNUC printf attribute macros - added enum handling in mkproto - removed non-vararg code - made slprintf and vslprintf just macros for snprintf and vsnprintf - don't need slprintf code any more (This used to be commit c7aeb2254dfc3cd0aa0b6c0bdd426f9323be0ddf) --- source3/smbd/lanman.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 73815a5c59..8dc3d8308a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -221,27 +221,15 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount) return(p->errcode == NERR_Success); } -#ifdef HAVE_STDARG_H static int package(struct pack_desc* p, ...) { -#else -static int package(va_alist) -va_dcl -{ - struct pack_desc* p; -#endif va_list args; int needed=0, stringneeded; char* str=NULL; int is_string=0, stringused; int32 temp; -#ifdef HAVE_STDARG_H va_start(args,p); -#else - va_start(args); - p = va_arg(args,struct pack_desc *); -#endif if (!*p->curpos) { if (!p->subcount) -- cgit From 63602d15afe96206e1fdcea4d2b9014582aa41aa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 28 Apr 2001 14:01:02 +0000 Subject: - fixed some compiler warnings - fixed slprintf and vsprintf macros (This used to be commit c986a3c51e8cdbc1230edbe0f4a91138c4ada29d) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 15e8e9537e..61b9390d08 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -556,7 +556,7 @@ static BOOL check_server_security(char *orig_user, char *domain, char *unix_user smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen); if(ret) { - struct passwd *pwd; + struct passwd *pwd=NULL; /* * User validated ok against Domain controller. @@ -597,7 +597,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user { BOOL ret = False; BOOL user_exists = True; - struct passwd *pwd; + struct passwd *pwd=NULL; if(lp_security() != SEC_DOMAIN) return False; -- cgit From c3a999409db6a9e0d38928feb02ab6815bd28d57 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Apr 2001 21:05:58 +0000 Subject: Based on an original PAM patch by Andrew Bartlett, re-written by me to remove global static PAM variables, and to tidy up the PAM internals code. Now looks like the rest of Samba. Still needs testing. Jeremy. (This used to be commit 1648ac64a75de74d1a1575eb49cccc4f75488bfa) --- source3/smbd/chgpasswd.c | 21 +++++++++++++++++++++ source3/smbd/password.c | 44 +++++++++++++++++++------------------------- source3/smbd/session.c | 20 ++++++++------------ 3 files changed, 48 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 21b7722307..72e97abc3b 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -54,6 +54,24 @@ extern struct passdb_ops pdb_ops; #if ALLOW_CHANGE_PASSWORD +#ifdef WITH_PAM +BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) +{ + BOOL ret; + + if (as_root) + become_root(); + + ret = smb_pam_passchange(name, oldpass, newpass); + + if (as_root) + unbecome_root(); + + return ret; +} + +#else /* WITH_PAM */ + static int findpty(char **slave) { int master; @@ -527,7 +545,10 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) (passwordprogram, name, chatsequence, as_root)); } +#endif /* WITH_PAM */ + #else /* ALLOW_CHANGE_PASSWORD */ + BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) { DEBUG(0, ("Password changing not compiled in (user=%s)\n", name)); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ba882f2bf2..03d96bebc0 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -453,25 +453,21 @@ BOOL smb_password_ok(SAM_ACCOUNT *sampass, uchar chal[8], user_name = pdb_get_username(sampass); - DEBUG(4,("Checking SMB password for user %s\n",user_name)); + DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",user_name)); if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { - DEBUG(1,("account for user %s was disabled.\n", user_name)); + DEBUG(1,("smb_password_ok: account for user %s was disabled.\n", user_name)); return(False); } - if (chal == NULL) - { - DEBUG(5,("use last SMBnegprot challenge\n")); - if (!last_challenge(challenge)) - { - DEBUG(1,("no challenge done - password failed\n")); + if (chal == NULL) { + DEBUG(5,("smb_password_ok: use last SMBnegprot challenge\n")); + if (!last_challenge(challenge)) { + DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); return False; } - } - else - { - DEBUG(5,("challenge received\n")); + } else { + DEBUG(5,("smb_password_ok: challenge received\n")); memcpy(challenge, chal, 8); } @@ -482,35 +478,33 @@ BOOL smb_password_ok(SAM_ACCOUNT *sampass, uchar chal[8], use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_password_check((char *)nt_pass, (uchar *)nt_pw, challenge)) - { - DEBUG(4,("NT MD4 password check succeeded\n")); + if (smb_password_check((char *)nt_pass, (uchar *)nt_pw, challenge)) { + DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); return(True); } - DEBUG(4,("NT MD4 password check failed\n")); + DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); } /* Try against the lanman password. pdb_get_lanman_passwd(sampass) == NULL means no password, allow access. */ - DEBUG(4,("Checking LM MD4 password\n")); - lm_pw = pdb_get_lanman_passwd(sampass); if((lm_pw == NULL) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) { - DEBUG(4,("no password required for user %s\n",user_name)); + DEBUG(4,("smb_password_ok: no password required for user %s\n",user_name)); return True; } - if((lm_pw != NULL) && smb_password_check((char *)lm_pass,(uchar *)lm_pw, challenge)) - { - DEBUG(4,("LM MD4 password check succeeded\n")); - return(True); + if(lp_lanman_auth() && (lm_pw != NULL)) { + DEBUG(4,("smb_password_ok: Checking LM password\n")); + if(smb_password_check((char *)lm_pass,(uchar *)lm_pw, challenge)) { + DEBUG(4,("smb_password_ok: LM password check succeeded\n")); + return(True); + } + DEBUG(4,("smb_password_ok: LM password check failed\n")); } - DEBUG(4,("LM MD4 password check failed\n")); - return False; } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 3131fb9f54..40654c0f43 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -99,6 +99,13 @@ BOOL session_claim(uint16 vuid) sessionid.id_num = i; sessionid.pid = pid; + if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) { + DEBUG(1,("pam_session rejected the session for %s [%s]\n", + sessionid.username, sessionid.id_str)); + tdb_delete(tdb, key); + return False; + } + dlen = tdb_pack(dbuf, sizeof(dbuf), "fffdd", sessionid.username, sessionid.hostname, sessionid.id_str, sessionid.id_num, sessionid.pid); @@ -110,15 +117,6 @@ BOOL session_claim(uint16 vuid) return False; } -#if WITH_PAM - if (!smb_pam_session(True, sessionid.username, sessionid.id_str, sessionid.hostname)) { - DEBUG(1,("smb_pam_session rejected the session for %s [%s]\n", - sessionid.username, sessionid.id_str)); - tdb_delete(tdb, key); - return False; - } -#endif - #if WITH_UTMP if (lp_utmp()) { sys_utmp_claim(sessionid.username, sessionid.hostname, @@ -169,9 +167,7 @@ void session_yield(uint16 vuid) } #endif -#if WITH_PAM - smb_pam_session(False, sessionid.username, sessionid.id_str, sessionid.hostname); -#endif + smb_pam_close_session(sessionid.username, sessionid.id_str, sessionid.hostname); tdb_delete(tdb, key); } -- cgit From aac630b382fefff2e3ead291d2d838832a180925 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 May 2001 23:32:09 +0000 Subject: Had to add a "pam password change" parameter (defaults to "off") and inlined the pam password change code to ensure that existing and working password chat scripts don't break with 2.2.1. PAM password changing has to be explicitly requested. Allowed wildcards in pam password change matching (matches password chat script matching). Had to add const (sorry Tim :-) to ms_fnmatch() to stop warnings. Don't worry - the const changes are isolated and don't cause any other warnings :-). Jeremy. (This used to be commit 47b4d82536c09bffe3a0d9917fa31d935f1be7d8) --- source3/smbd/chgpasswd.c | 96 +++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 72e97abc3b..d503e65897 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -20,9 +20,9 @@ */ /* fork a child process to exec passwd and write to its -* tty to change a users password. This is running as the -* user who is attempting to change the password. -*/ + * tty to change a users password. This is running as the + * user who is attempting to change the password. + */ /* * This code was copied/borrowed and stolen from various sources. @@ -54,24 +54,6 @@ extern struct passdb_ops pdb_ops; #if ALLOW_CHANGE_PASSWORD -#ifdef WITH_PAM -BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) -{ - BOOL ret; - - if (as_root) - become_root(); - - ret = smb_pam_passchange(name, oldpass, newpass); - - if (as_root) - unbecome_root(); - - return ret; -} - -#else /* WITH_PAM */ - static int findpty(char **slave) { int master; @@ -475,47 +457,28 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) /* Take the passed information and test it for minimum criteria */ /* Minimum password length */ - if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ - { - DEBUG(0, - ("Password Change: user %s, New password is shorter than minimum password length = %d\n", + if (strlen(newpass) < lp_min_passwd_length()) { + /* too short, must be at least MINPASSWDLENGTH */ + DEBUG(0, ("Password Change: user %s, New password is shorter than minimum password length = %d\n", name, lp_min_passwd_length())); return (False); /* inform the user */ } /* Password is same as old password */ - if (strcmp(oldpass, newpass) == 0) /* don't allow same password */ - { - DEBUG(2, - ("Password Change: %s, New password is same as old\n", name)); /* log the attempt */ + if (strcmp(oldpass, newpass) == 0) { + /* don't allow same password */ + DEBUG(2, ("Password Change: %s, New password is same as old\n", name)); /* log the attempt */ return (False); /* inform the user */ } - pstrcpy(passwordprogram, lp_passwd_program()); - pstrcpy(chatsequence, lp_passwd_chat()); - - if (!*chatsequence) - { - DEBUG(2, ("Null chat sequence - no password changing\n")); - return (False); - } - - if (!*passwordprogram) - { - DEBUG(2, ("Null password program - no password changing\n")); - return (False); - } - /* * Check the old and new passwords don't contain any control * characters. */ len = strlen(oldpass); - for (i = 0; i < len; i++) - { - if (iscntrl((int)oldpass[i])) - { + for (i = 0; i < len; i++) { + if (iscntrl((int)oldpass[i])) { DEBUG(0, ("chat_with_program: oldpass contains control characters (disallowed).\n")); return False; @@ -523,16 +486,43 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) } len = strlen(newpass); - for (i = 0; i < len; i++) - { - if (iscntrl((int)newpass[i])) - { + for (i = 0; i < len; i++) { + if (iscntrl((int)newpass[i])) { DEBUG(0, ("chat_with_program: newpass contains control characters (disallowed).\n")); return False; } } +#ifdef WITH_PAM + if (lp_pam_password_change()) { + BOOL ret; + + if (as_root) + become_root(); + + ret = smb_pam_passchange(name, oldpass, newpass); + + if (as_root) + unbecome_root(); + + return ret; + } +#endif + + pstrcpy(passwordprogram, lp_passwd_program()); + pstrcpy(chatsequence, lp_passwd_chat()); + + if (!*chatsequence) { + DEBUG(2, ("Null chat sequence - no password changing\n")); + return (False); + } + + if (!*passwordprogram) { + DEBUG(2, ("Null password program - no password changing\n")); + return (False); + } + pstring_sub(passwordprogram, "%u", name); /* note that we do NOT substitute the %o and %n in the password program as this would open up a security hole where the user could use @@ -545,8 +535,6 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) (passwordprogram, name, chatsequence, as_root)); } -#endif /* WITH_PAM */ - #else /* ALLOW_CHANGE_PASSWORD */ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) -- cgit From 548d16869acffdec899121906a7bcd88f58d9b6f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 May 2001 19:47:30 +0000 Subject: Fixed SHM_R/SHM_W warnings by moving sys/ipc.h and sys/shm.h into includes.h and using autoconf tests. Added "restrict acl with mask" parameter. Jeremy. (This used to be commit 7792e32ba7fd734cc68b354f31c382ac11521fe8) --- source3/smbd/posix_acls.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0c613e8835..bf8716d713 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -468,6 +468,9 @@ static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type) mode_t and_bits = (mode_t)0; mode_t or_bits = (mode_t)0; + if (!lp_restrict_acl_with_mask(snum)) + return perms; + /* Get the initial bits to apply. */ if (fsp->is_directory) { @@ -1173,6 +1176,9 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) if (fsp->is_directory) mode |= (S_IWUSR|S_IXUSR); + if (!lp_restrict_acl_with_mask(snum)) + return mode; + /* * Now AND with the create mode/directory mode bits then OR with the * force create mode/force directory mode bits. -- cgit From 1f7a451c1e059b5a86e1e78debd582579aa7bcb7 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 4 May 2001 14:28:28 +0000 Subject: merge from 2.2 in password_ok() to ensure that we check the return code from smb_pam_accountcheck() (This used to be commit d5d6f01aaf8d344bb44dbe047c2f760ca220529e) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 03d96bebc0..5820afacc8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -626,7 +626,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) */ if (ret) - return smb_pam_accountcheck(user); + return (smb_pam_accountcheck(user) == NT_STATUS_NOPROBLEMO); } return pass_check(user, password, pwlen, pwd, -- cgit From f35157f39293f9fa240a28642c41708b55d301c8 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Fri, 4 May 2001 15:44:27 +0000 Subject: Big cleanup of passdb and backends. I did some basic tests but I have probably broken something. Notably the password changing. So don't cry ;-) J.F. (This used to be commit a4a4c02b12f030a3b9e6225b999c90689dfc4719) --- source3/smbd/chgpasswd.c | 98 ++++++++++++++++++++++-------------------------- source3/smbd/lanman.c | 8 +++- source3/smbd/password.c | 24 +++++++++--- source3/smbd/reply.c | 14 +++++-- 4 files changed, 80 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d503e65897..2b4676eb33 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -557,37 +557,36 @@ BOOL check_lanman_password(char *user, uchar * pass1, SAM_ACCOUNT *sampass = NULL; uint16 acct_ctrl; uint8 *lanman_pw; - + BOOL ret; + become_root(); - sampass = pdb_getsampwnam(user); + ret = pdb_getsampwnam(sampass, user); unbecome_root(); - if (sampass == NULL) - { + if (ret == False) { DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); + pdb_clear_sam(sampass); return False; } acct_ctrl = pdb_get_acct_ctrl (sampass); lanman_pw = pdb_get_lanman_passwd (sampass); - if (acct_ctrl & ACB_DISABLED) - { - DEBUG(0,("check_lanman_password: account %s disabled.\n", - user)); + if (acct_ctrl & ACB_DISABLED) { + DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + pdb_clear_sam(sampass); return False; } - if ((lanman_pw == NULL) && (acct_ctrl & ACB_PWNOTREQ)) - { + if ((lanman_pw == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { uchar no_pw[14]; memset(no_pw, '\0', 14); E_P16(no_pw, null_pw); pdb_set_lanman_passwd (sampass, null_pw); } - else if (lanman_pw == NULL) - { + else if (lanman_pw == NULL) { DEBUG(0, ("check_lanman_password: no lanman password !\n")); + pdb_clear_sam(sampass); return False; } @@ -598,9 +597,9 @@ BOOL check_lanman_password(char *user, uchar * pass1, D_P16(unenc_new_pw, pass1, unenc_old_pw); /* Check that the two old passwords match. */ - if (memcmp(lanman_pw, unenc_old_pw, 16)) - { + if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); + pdb_clear_sam(sampass); return False; } @@ -625,30 +624,27 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, uint16 acct_ctrl; uint8 *pwd; - if (sampass == NULL) - { + if (sampass == NULL) { DEBUG(0,("change_lanman_password: no smb password entry.\n")); return False; } + acct_ctrl = pdb_get_acct_ctrl(sampass); pwd = pdb_get_lanman_passwd(sampass); - if (acct_ctrl & ACB_DISABLED) - { + if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("change_lanman_password: account %s disabled.\n", pdb_get_username(sampass))); return False; } - if ((pwd == NULL) && (acct_ctrl & ACB_PWNOTREQ)) - { + if ((pwd == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { uchar no_pw[14]; memset(no_pw, '\0', 14); E_P16(no_pw, null_pw); pdb_set_lanman_passwd(sampass, null_pw); } - else if (pwd == NULL) - { + else if (pwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); return False; } @@ -689,17 +685,15 @@ BOOL pass_oem_change(char *user, */ if (ret && lp_unix_password_sync()) - { ret = chgpasswd(user, "", new_passwd, True); - } if (ret) - { ret = change_oem_password(sampass, new_passwd, False); - } memset(new_passwd, 0, sizeof(new_passwd)); + pdb_clear_sam(sampass); + return ret; } @@ -727,22 +721,26 @@ BOOL check_oem_password(char *user, uchar new_p16[16]; uchar unenc_old_pw[16]; char no_pw[2]; + BOOL ret; BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); + pdb_init_sam(&sampass); + become_root(); - *hnd = sampass = pdb_getsampwnam(user); + ret = pdb_getsampwnam(sampass, user); unbecome_root(); - if (sampass == NULL) - { + if (ret == False) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); return False; } + + *hnd = sampass; + acct_ctrl = pdb_get_acct_ctrl(sampass); - if (acct_ctrl & ACB_DISABLED) - { + if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } @@ -757,27 +755,19 @@ BOOL check_oem_password(char *user, nt_pw = pdb_get_nt_passwd (sampass); /* check for null passwords */ - if (lanman_pw == NULL) - { + if (lanman_pw == NULL) { if (acct_ctrl & ACB_PWNOTREQ) - { pdb_set_lanman_passwd(sampass, null_pw); - } - else - { + else { DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } } - if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) - { + if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) { if (acct_ctrl & ACB_PWNOTREQ) - { pdb_set_nt_passwd(sampass, null_pw); - } - else - { + else { DEBUG(0,("check_oem_password: no ntlm password !\n")); return False; } @@ -794,15 +784,12 @@ BOOL check_oem_password(char *user, */ new_pw_len = IVAL(lmdata, 512); - if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) - { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", - new_pw_len)); + if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } - if (nt_pass_set) - { + if (nt_pass_set) { /* * nt passwords are in unicode */ @@ -811,9 +798,7 @@ BOOL check_oem_password(char *user, new_pw_len /= 2; pw = dos_unistrn2((uint16 *)(&lmdata[512 - uni_pw_len]),new_pw_len); memcpy(new_passwd, pw, new_pw_len + 1); - } - else - { + } else { memcpy(new_passwd, &lmdata[512 - new_pw_len], new_pw_len); new_passwd[new_pw_len] = '\0'; } @@ -908,12 +893,17 @@ BOOL check_plaintext_password(char *user, char *old_passwd, { SAM_ACCOUNT *sampass = NULL; uchar old_pw[16], old_ntpw[16]; + BOOL ret; + + pdb_init_sam(&sampass); become_root(); - *hnd = sampass = pdb_getsampwnam(user); + ret = pdb_getsampwnam(sampass, user); unbecome_root(); - if (sampass == NULL) + *hnd = sampass; + + if (ret == False) { DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); return False; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 8dc3d8308a..d5dd876670 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1765,7 +1765,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param { fstring saved_pass2; - SAM_ACCOUNT *sampass; + SAM_ACCOUNT *sampass=NULL; /* * Save the new password as change_oem_password overwrites it @@ -1788,7 +1788,9 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) SSVAL(*rparam,0,NERR_badpass); } - } + pdb_clear_sam(sampass); + } + /* * If the above failed, attempt the plaintext password change. @@ -1823,8 +1825,10 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param { SSVAL(*rparam,0,NERR_Success); } + pdb_clear_sam(hnd); } + memset((char *)pass1,'\0',sizeof(fstring)); memset((char *)pass2,'\0',sizeof(fstring)); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 5820afacc8..f42451dceb 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -368,12 +368,15 @@ static BOOL update_smbpassword_file(char *user, char *password) SAM_ACCOUNT *sampass = NULL; BOOL ret; + pdb_init_sam(&sampass); + become_root(); - sampass = pdb_getsampwnam(user); + ret = pdb_getsampwnam(sampass, user); unbecome_root(); - if(sampass == NULL) { + if(ret == False) { DEBUG(0,("pdb_getsampwnam returned NULL\n")); + pdb_clear_sam(sampass); return False; } @@ -390,6 +393,7 @@ static BOOL update_smbpassword_file(char *user, char *password) DEBUG(3,("change_oem_password returned False\n")); } + pdb_clear_sam(sampass); return ret; } @@ -519,7 +523,8 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, uchar *lm_pwd, uchar *nt_pwd, struct passwd *pwd) { struct passwd *pass; - SAM_ACCOUNT *sampass; + SAM_ACCOUNT *sampass=NULL; + BOOL ret; if (!lm_pwd || !nt_pwd) { @@ -546,17 +551,21 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, return(False); } + pdb_init_sam(&sampass); + /* get the account information */ - sampass = pdb_getsampwnam(user); - if (sampass == NULL) + ret = pdb_getsampwnam(sampass, user); + if (ret == False) { DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user)); + pdb_clear_sam(sampass); return(False); } /* Quit if the account was disabled. */ if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { DEBUG(1,("Account for user '%s' was disabled.\n", user)); + pdb_clear_sam(sampass); return(False); } @@ -566,6 +575,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (smb_pass->smb_userid != pass->pw_uid) { DEBUG(0,("Error : UNIX and SMB uids in password files do not match for user '%s'!\n", user)); + pdb_clear_sam(sampass); return(False); } #endif @@ -575,21 +585,25 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user)); + pdb_clear_sam(sampass); return(True); } else { DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user)); + pdb_clear_sam(sampass); return(False); } } if (smb_password_ok(sampass, chal, lm_pwd, nt_pwd)) { + pdb_clear_sam(sampass); return(True); } DEBUG(2,("pass_check_smb failed - invalid password for user [%s]\n", user)); + pdb_clear_sam(sampass); return False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 61b9390d08..c9ef881b59 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -427,34 +427,42 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out /* check if trust account exists */ SAM_ACCOUNT *sam_trust_acct = NULL; uint16 acct_ctrl; + BOOL ret; + + pdb_init_sam(&sam_trust_acct); if (lp_security() == SEC_USER) { - sam_trust_acct = pdb_getsampwnam(user); + ret = pdb_getsampwnam(sam_trust_acct, user); } else { DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + pdb_clear_sam(sam_trust_acct); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (sam_trust_acct == NULL) { + if (ret == False) { /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + pdb_clear_sam(sam_trust_acct); return(ERROR(0, NT_STATUS_NO_SUCH_USER)); } else { if ((smb_passlen != 24) || (smb_nt_passlen != 24)) { DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, NT_STATUS_LOGON_FAILURE)); + pdb_clear_sam(sam_trust_acct); + return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + pdb_clear_sam(sam_trust_acct); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct); + pdb_clear_sam(sam_trust_acct); if (acct_ctrl & ACB_DOMTRUST) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); -- cgit From 998fcd3f1ea496c0799cf9259d93135e13b4875e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 6 May 2001 20:56:14 +0000 Subject: Patch from David_Tiller@ccnotes.ccity.com finally applied now I've thought about it to stop account lockouts with "security=server" mode. Sorry for the delay David. Jeremy. (This used to be commit e8819715038ed49b07ed5639b1b88ad12e994b53) --- source3/smbd/password.c | 147 +++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 70 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f42451dceb..0bc21dbbd6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1156,96 +1156,103 @@ BOOL server_validate(char *user, char *domain, char *pass, int passlen, char *ntpass, int ntpasslen) { - struct cli_state *cli; - static unsigned char badpass[24]; - static BOOL tested_password_server = False; - static BOOL bad_password_server = False; + struct cli_state *cli; + static unsigned char badpass[24]; + static fstring baduser; + static BOOL tested_password_server = False; + static BOOL bad_password_server = False; - cli = server_client(); + cli = server_client(); - if (!cli->initialised) { - DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return(False); - } + if (!cli->initialised) { + DEBUG(1,("password server %s is not connected\n", cli->desthost)); + return(False); + } - if(badpass[0] == 0) - memset(badpass, 0x1f, sizeof(badpass)); + if(badpass[0] == 0) + memset(badpass, 0x1f, sizeof(badpass)); - if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) { - /* - * Very unlikely, our random bad password is the same as the users - * password. */ - memset(badpass, badpass[0]+1, sizeof(badpass)); - } + if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) { + /* + * Very unlikely, our random bad password is the same as the users + * password. + */ + memset(badpass, badpass[0]+1, sizeof(badpass)); + } - /* - * Attempt a session setup with a totally incorrect password. - * If this succeeds with the guest bit *NOT* set then the password - * server is broken and is not correctly setting the guest bit. We - * need to detect this as some versions of NT4.x are broken. JRA. - */ + if(baduser[0] == 0) { + fstrcpy(baduser, INVALID_USER_PREFIX); + fstrcat(baduser, global_myname); + } + + /* + * Attempt a session setup with a totally incorrect password. + * If this succeeds with the guest bit *NOT* set then the password + * server is broken and is not correctly setting the guest bit. We + * need to detect this as some versions of NT4.x are broken. JRA. + */ - if(!tested_password_server) { - if (cli_session_setup(cli, user, (char *)badpass, sizeof(badpass), - (char *)badpass, sizeof(badpass), domain)) { + if(!tested_password_server) { + if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass), + (char *)badpass, sizeof(badpass), domain)) { - /* - * We connected to the password server so we - * can say we've tested it. - */ - tested_password_server = True; + /* + * We connected to the password server so we + * can say we've tested it. + */ + tested_password_server = True; - if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { - DEBUG(0,("server_validate: password server %s allows users as non-guest \ + if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { + DEBUG(0,("server_validate: password server %s allows users as non-guest \ with a bad password.\n", cli->desthost)); - DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ + DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ use this machine as the password server.\n")); - cli_ulogoff(cli); + cli_ulogoff(cli); - /* - * Password server has the bug. - */ - bad_password_server = True; - return False; - } - cli_ulogoff(cli); - } - } else { + /* + * Password server has the bug. + */ + bad_password_server = True; + return False; + } + cli_ulogoff(cli); + } + } else { - /* - * We have already tested the password server. - * Fail immediately if it has the bug. - */ + /* + * We have already tested the password server. + * Fail immediately if it has the bug. + */ - if(bad_password_server) { - DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \ + if(bad_password_server) { + DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \ with a bad password.\n", cli->desthost)); - DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \ + DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \ use this machine as the password server.\n")); - return False; - } - } + return False; + } + } - /* - * Now we know the password server will correctly set the guest bit, or is - * not guest enabled, we can try with the real password. - */ + /* + * Now we know the password server will correctly set the guest bit, or is + * not guest enabled, we can try with the real password. + */ - if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - return False; - } + if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + return False; + } - /* if logged in as guest then reject */ - if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); - cli_ulogoff(cli); - return(False); - } + /* if logged in as guest then reject */ + if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); + cli_ulogoff(cli); + return(False); + } - cli_ulogoff(cli); + cli_ulogoff(cli); - return(True); + return(True); } /*********************************************************************** -- cgit From 30c4c04c2f584857633ce7605555dcfb37a3e1af Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 7 May 2001 14:04:46 +0000 Subject: Patch from Simo: o sed 's/pdb_clear_sam/pdb_free_sam/g' o add pdb_reset_sam() o password changing should be ok now as well. (This used to be commit 96d0e7c3301ad990f6c83b9c216720cb32661fb5) --- source3/smbd/chgpasswd.c | 10 +++++----- source3/smbd/lanman.c | 4 ++-- source3/smbd/password.c | 18 +++++++++--------- source3/smbd/reply.c | 10 +++++----- 4 files changed, 21 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 2b4676eb33..cf1fca405a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -565,7 +565,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (ret == False) { DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return False; } @@ -574,7 +574,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return False; } @@ -586,7 +586,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, } else if (lanman_pw == NULL) { DEBUG(0, ("check_lanman_password: no lanman password !\n")); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return False; } @@ -599,7 +599,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, /* Check that the two old passwords match. */ if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return False; } @@ -692,7 +692,7 @@ BOOL pass_oem_change(char *user, memset(new_passwd, 0, sizeof(new_passwd)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return ret; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d5dd876670..69a0fa5ac3 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1788,7 +1788,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) SSVAL(*rparam,0,NERR_badpass); } - pdb_clear_sam(sampass); + pdb_free_sam(sampass); } @@ -1825,7 +1825,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param { SSVAL(*rparam,0,NERR_Success); } - pdb_clear_sam(hnd); + pdb_free_sam(hnd); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0bc21dbbd6..01fc9cdd53 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -376,7 +376,7 @@ static BOOL update_smbpassword_file(char *user, char *password) if(ret == False) { DEBUG(0,("pdb_getsampwnam returned NULL\n")); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return False; } @@ -393,7 +393,7 @@ static BOOL update_smbpassword_file(char *user, char *password) DEBUG(3,("change_oem_password returned False\n")); } - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return ret; } @@ -558,14 +558,14 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (ret == False) { DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return(False); } /* Quit if the account was disabled. */ if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { DEBUG(1,("Account for user '%s' was disabled.\n", user)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return(False); } @@ -575,7 +575,7 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (smb_pass->smb_userid != pass->pw_uid) { DEBUG(0,("Error : UNIX and SMB uids in password files do not match for user '%s'!\n", user)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return(False); } #endif @@ -585,25 +585,25 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, if (lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return(True); } else { DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return(False); } } if (smb_password_ok(sampass, chal, lm_pwd, nt_pwd)) { - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return(True); } DEBUG(2,("pass_check_smb failed - invalid password for user [%s]\n", user)); - pdb_clear_sam(sampass); + pdb_free_sam(sampass); return False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c9ef881b59..41970c4040 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -436,7 +436,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out } else { DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - pdb_clear_sam(sam_trust_acct); + pdb_free_sam(sam_trust_acct); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } @@ -444,25 +444,25 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - pdb_clear_sam(sam_trust_acct); + pdb_free_sam(sam_trust_acct); return(ERROR(0, NT_STATUS_NO_SUCH_USER)); } else { if ((smb_passlen != 24) || (smb_nt_passlen != 24)) { DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - pdb_clear_sam(sam_trust_acct); + pdb_free_sam(sam_trust_acct); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - pdb_clear_sam(sam_trust_acct); + pdb_free_sam(sam_trust_acct); return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct); - pdb_clear_sam(sam_trust_acct); + pdb_free_sam(sam_trust_acct); if (acct_ctrl & ACB_DOMTRUST) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); -- cgit From 1cebd0fe989bc42f0a227f3ab2f0bc4b61a4ab7e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 May 2001 21:17:42 +0000 Subject: Fix for bad profile perms. Ensure r on files and rwx on directories. Jeremy. (This used to be commit f100e091abc57a9ba983e7c3cf84bfda2dbc2e18) --- source3/smbd/posix_acls.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index bf8716d713..0d020a8ebb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -527,12 +527,10 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, if (pace->type == SMB_ACL_USER_OBJ) { if (setting_acl) { - if (pace->perms == (mode_t)0) { - /* Ensure owner has read access. */ - pace->perms = S_IRUSR; - if (fsp->is_directory) - pace->perms |= (S_IWUSR|S_IXUSR); - } + /* Ensure owner has read access. */ + pace->perms |= S_IRUSR; + if (fsp->is_directory) + pace->perms |= (S_IWUSR|S_IXUSR); /* * Ensure create mask/force create mode is respected on set. @@ -1699,6 +1697,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau static BOOL convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms) { + int snum = SNUM(fsp->conn); size_t ace_count = count_canon_ace_list(file_ace_list); canon_ace *ace_p; canon_ace *owner_ace = NULL; @@ -1738,8 +1737,29 @@ posix perms.\n", fsp->fsp_name )); /* The owner must have at least read access. */ - if (*posix_perms == (mode_t)0) - *posix_perms = S_IRUSR; + *posix_perms |= S_IRUSR; + if (fsp->is_directory) + *posix_perms |= (S_IWUSR|S_IXUSR); + + /* If requested apply the masks. */ + + if (lp_restrict_acl_with_mask(snum)) { + mode_t and_bits; + mode_t or_bits; + + /* Get the initial bits to apply. */ + + if (fsp->is_directory) { + and_bits = lp_dir_mask(snum); + or_bits = lp_force_dir_mode(snum); + } else { + and_bits = lp_create_mask(snum); + or_bits = lp_force_create_mode(snum); + } + + *posix_perms = (((*posix_perms) & and_bits)|or_bits); + + } DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n", (int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms, -- cgit From 061beddc6187e710ceb9409baeba15f15eb7f30c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 May 2001 00:03:45 +0000 Subject: Patch from ackley@cs.unm.edu to clear server_fd/client_fd in root daemon to stop %I getpeername() failure. Jeremy. (This used to be commit 15584d30cd51650752fcbdd4f0dfc193fed18e5a) --- source3/smbd/server.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d2a9a64966..6f4f18562e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -277,6 +277,16 @@ max can be %d\n", /* The parent doesn't need this socket */ close(smbd_server_fd()); + /* Sun May 6 18:56:14 2001 ackley@cs.unm.edu: + Clear the closed fd info out of server_fd -- + and more importantly, out of client_fd in + util_sock.c, to avoid a possible + getpeername failure if we reopen the logs + and use %I in the filename. + */ + + smbd_set_server_fd(-1); + /* Force parent to check log size after * spawning child. Fix from * klausr@ITAP.Physik.Uni-Stuttgart.De. The -- cgit From 55eab3e23202c33eb144bfe6bf4c745fc4330a1b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 8 May 2001 06:14:08 +0000 Subject: More compiler warning fixes. (This used to be commit 88a7b2c3f80b17ca8ab2112e9a98f55f1a11d88c) --- source3/smbd/notify_kernel.c | 4 ++-- source3/smbd/oplock_linux.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 6509354e9b..ef4e47acf1 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -62,9 +62,9 @@ struct change_data { /**************************************************************************** the signal handler for change notify *****************************************************************************/ -static void signal_handler(int signal, siginfo_t *info, void *unused) +static void signal_handler(int sig, siginfo_t *info, void *unused) { - BlockSignals(True, signal); + BlockSignals(True, sig); fd_pending = (SIG_ATOMIC_T)info->si_fd; signals_received++; sys_select_signal(); diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 5bf753d68c..9edeb1b513 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -52,9 +52,9 @@ static VOLATILE SIG_ATOMIC_T fd_pending; /* the fd of the current pending signal /**************************************************************************** handle a LEASE signal, incrementing the signals_received and blocking the signal ****************************************************************************/ -static void signal_handler(int signal, siginfo_t *info, void *unused) +static void signal_handler(int sig, siginfo_t *info, void *unused) { - BlockSignals(True, signal); + BlockSignals(True, sig); fd_pending = (SIG_ATOMIC_T)info->si_fd; signals_received++; sys_select_signal(); -- cgit From f5243954faee5380d43f00cdb2fa820da5d50ebd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 May 2001 01:03:44 +0000 Subject: Made "security XXX" masks apply to ACL set. By default they have no effect. Removed "restrict acl with mask" - redundent. Jeremy. (This used to be commit 0db8a61d71f25ffa0e5c585e02e2fce973867156) --- source3/smbd/posix_acls.c | 48 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0d020a8ebb..53729a6f5d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -468,17 +468,14 @@ static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type) mode_t and_bits = (mode_t)0; mode_t or_bits = (mode_t)0; - if (!lp_restrict_acl_with_mask(snum)) - return perms; - /* Get the initial bits to apply. */ if (fsp->is_directory) { - and_bits = lp_dir_mask(snum); - or_bits = lp_force_dir_mode(snum); + and_bits = lp_dir_security_mask(snum); + or_bits = lp_force_dir_security_mode(snum); } else { - and_bits = lp_create_mask(snum); - or_bits = lp_force_create_mode(snum); + and_bits = lp_security_mask(snum); + or_bits = lp_force_security_mode(snum); } /* Now bounce them into the S_USR space. */ @@ -1174,20 +1171,17 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) if (fsp->is_directory) mode |= (S_IWUSR|S_IXUSR); - if (!lp_restrict_acl_with_mask(snum)) - return mode; - /* * Now AND with the create mode/directory mode bits then OR with the * force create mode/force directory mode bits. */ if (fsp->is_directory) { - and_bits = lp_dir_mask(snum); - or_bits = lp_force_dir_mode(snum); + and_bits = lp_dir_security_mask(snum); + or_bits = lp_force_dir_security_mode(snum); } else { - and_bits = lp_create_mask(snum); - or_bits = lp_force_create_mode(snum); + and_bits = lp_security_mask(snum); + or_bits = lp_force_security_mode(snum); } return ((mode & and_bits)|or_bits); @@ -1703,6 +1697,8 @@ static BOOL convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file canon_ace *owner_ace = NULL; canon_ace *group_ace = NULL; canon_ace *other_ace = NULL; + mode_t and_bits; + mode_t or_bits; if (ace_count != 3) { DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE entries for file %s to convert to \ @@ -1743,24 +1739,18 @@ posix perms.\n", fsp->fsp_name )); /* If requested apply the masks. */ - if (lp_restrict_acl_with_mask(snum)) { - mode_t and_bits; - mode_t or_bits; - - /* Get the initial bits to apply. */ - - if (fsp->is_directory) { - and_bits = lp_dir_mask(snum); - or_bits = lp_force_dir_mode(snum); - } else { - and_bits = lp_create_mask(snum); - or_bits = lp_force_create_mode(snum); - } - - *posix_perms = (((*posix_perms) & and_bits)|or_bits); + /* Get the initial bits to apply. */ + if (fsp->is_directory) { + and_bits = lp_dir_security_mask(snum); + or_bits = lp_force_dir_security_mode(snum); + } else { + and_bits = lp_security_mask(snum); + or_bits = lp_force_security_mode(snum); } + *posix_perms = (((*posix_perms) & and_bits)|or_bits); + DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n", (int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms, fsp->fsp_name )); -- cgit From 6e41b74e6d46a136ef9f7178d2d3cb1d3b4fe8f5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 May 2001 19:27:00 +0000 Subject: Fixed nasty little bug found by Gerald where we were corrupting the mode bits before checking if we should change them on non-acl systems. Jeremy. (This used to be commit aba243ca0867a0787f9f7c7b2cda6143bcc53087) --- source3/smbd/posix_acls.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 53729a6f5d..0cc0f2bac6 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1942,6 +1942,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) canon_ace *file_ace_list = NULL; canon_ace *dir_ace_list = NULL; BOOL acl_perms = False; + mode_t orig_mode = (mode_t)0; + uid_t orig_uid; + gid_t orig_gid; DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -1957,6 +1960,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) return False; } + /* Save the original elements we check against. */ + orig_mode = sbuf.st_mode; + orig_uid = sbuf.st_uid; + orig_gid = sbuf.st_gid; + /* * Unpack the user/group/world id's. */ @@ -1968,7 +1976,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Do we need to chown ? */ - if((user != (uid_t)-1 || grp != (uid_t)-1) && (sbuf.st_uid != user || sbuf.st_gid != grp)) { + if((user != (uid_t)-1 || grp != (uid_t)-1) && (orig_uid != user || orig_gid != grp)) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); @@ -2000,6 +2008,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(ret != 0) return False; } + + /* Save the original elements we check against. */ + orig_mode = sbuf.st_mode; + orig_uid = sbuf.st_uid; + orig_gid = sbuf.st_gid; } create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); @@ -2067,7 +2080,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) return False; } - if (sbuf.st_mode != posix_perms) { + if (orig_mode != posix_perms) { DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)posix_perms )); -- cgit From 8efe9427516aad533e94bb917de17ecec18b098f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 12 May 2001 00:31:59 +0000 Subject: Now we're doing the substituion in the lp_string code remove the erroneous debug 0 warning. Jeremy. (This used to be commit be7e1d0f2c078bd07c7087e1e36636dcd6d0a5d8) --- source3/smbd/service.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9fb2dd9eeb..c70ab42a61 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -108,11 +108,6 @@ int add_home_service(char *service, char *homedir) lp_add_home(new_service,iHomeService,homedir); iService = lp_servicenumber(new_service); - if ((iService != -1) && usr_p && (strstr(lp_pathname(iService),"%D") == NULL)) - DEBUG(0,("find_service: Service %s added for user %s - contains non-local (Domain) user \ -with non-domain parameterised path (%s). This may be cause the wrong directory to be seen.\n", - new_service, service, lp_pathname(iService) )); - return iService; } -- cgit From 9c54ddc7f9adeb63b5bc83fb7cd1b90bf0faf6ec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 12 May 2001 13:04:15 +0000 Subject: statcache initialisation fix pointed out by Elrond (This used to be commit 572a37534b7ee010aafd7e8bcb9da52957306f97) --- source3/smbd/statcache.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8200c277b3..65a4830016 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -221,11 +221,11 @@ BOOL reset_stat_cache( void ) static BOOL initialised; if (!lp_stat_cache()) return True; - if (!initialised) { - initialised = True; - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + if (initialised) { + hash_clear(&stat_cache); } - hash_clear(&stat_cache); - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, + (compare_function)(strcmp)); + return initialised; } /* reset_stat_cache */ -- cgit From 363e378dee1677f865bba3e8b347c600bbc08550 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 May 2001 06:15:46 +0000 Subject: Implemented max connections in a similar way to 2.0.x (scan of connection db). This needs testing ! Tidied up tabs in tdb.c. Jeremy. (This used to be commit 0852465053d0c1a23b6cfe6097267291b0595ef8) --- source3/smbd/connection.c | 88 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 43e89abfbf..6c401264d9 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -37,8 +37,9 @@ TDB_CONTEXT *conn_tdb_ctx(void) } /**************************************************************************** -delete a connection record + Delete a connection record. ****************************************************************************/ + BOOL yield_connection(connection_struct *conn,char *name,int max_connections) { struct connections_key key; @@ -62,21 +63,92 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) return(True); } +struct count_stat { + pid_t mypid; + int curr_connections; + char *name; +}; + +/**************************************************************************** + Count the entries belonging to a service in the connection db. +****************************************************************************/ + +static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *udp) +{ + struct connections_data crec; + struct count_stat *cs = (struct count_stat *)udp; + + memcpy(&crec, dbuf.dptr, sizeof(crec)); + + if (crec.cnum == -1) + return 0; + + /* if the pid was not found delete the entry from connections.tdb */ + if (!process_exists(crec.pid) && (errno == ESRCH)) { + DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", + (unsigned int)crec.pid, crec.cnum, crec.name)); + tdb_delete(the_tdb, kbuf); + return 0; + } + + if (strequal(crec.name, cs->name)) + cs->curr_connections++; + + return 0; +} /**************************************************************************** -claim an entry in the connections database + Claim an entry in the connections database. ****************************************************************************/ + BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear) { struct connections_key key; struct connections_data crec; TDB_DATA kbuf, dbuf; + BOOL db_locked = False; + BOOL ret = True; if (!tdb) { tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); } - if (!tdb) return False; + if (!tdb) + return False; + + /* + * Enforce the max connections parameter. + */ + + if (max_connections > 0) { + struct count_stat cs; + + cs.mypid = sys_getpid(); + cs.curr_connections = 0; + cs.name = lp_servicename(SNUM(conn)); + + /* + * Go through and count the connections with the db locked. This is + * slow but essentially what 2.0.x did. JRA. + */ + + if (tdb_lockall(tdb)) + return False; + + db_locked = True; + + if (tdb_traverse(tdb, count_fn, &cs)) { + ret = False; + goto out; + } + + if (cs.curr_connections >= max_connections) { + DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n", + max_connections, name )); + ret = False; + goto out; + } + } DEBUG(5,("claiming %s %d\n",name,max_connections)); @@ -108,8 +180,14 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO dbuf.dptr = (char *)&crec; dbuf.dsize = sizeof(crec); - if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False; + if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) + ret = False; + + out: + + if (db_locked) + tdb_unlockall(tdb); - return True; + return ret; } -- cgit From de6b5d8fb2ad8791c1bccbe86d08ef393a4e5f54 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 May 2001 18:43:49 +0000 Subject: tdb_traverse returns number of records, not zero, on success. Now tested max connections and it works again. Hurrah ! Jeremy. (This used to be commit 6565b8c9781f571735068aba5044a913b5fe31fe) --- source3/smbd/connection.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 6c401264d9..4a9d202fef 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -91,7 +91,7 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u return 0; } - if (strequal(crec.name, cs->name)) + if (cs && strequal(crec.name, cs->name)) cs->curr_connections++; return 0; @@ -137,7 +137,8 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO db_locked = True; - if (tdb_traverse(tdb, count_fn, &cs)) { + if (tdb_traverse(tdb, count_fn, &cs) == -1) { + DEBUG(0,("claim_connection: traverse of connections.tdb failed.\n")); ret = False; goto out; } @@ -191,3 +192,14 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO return ret; } +#if 0 +/**************************************************************************** + Use the count function to clean any dead records. Shouldn't be needed... +****************************************************************************/ + +void clean_connection_db(void) +{ + if (tdb_traverse(tdb, count_fn, NULL) == -1) + DEBUG(0,("clean_connection_db: traverse of connections.tdb failed.\n")); +} +#endif -- cgit From 8410ef028a5eefb257346b6023a0e96c3cca1012 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 15 May 2001 00:53:15 +0000 Subject: make the max_connections code less horrendously inefficient - it didn't honour the clear flag - it locked the database (not necessary) the previous code would do 10^6 kill() operations for 1000 people logging in - and all with the database locked. Not very scalable. Still haven't added the counter, that would make it really efficient (This used to be commit 6bdbeb4a32e52fb05328dcf38dbb90780e1761ef) --- source3/smbd/connection.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 4a9d202fef..47579fa5f7 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -67,6 +67,7 @@ struct count_stat { pid_t mypid; int curr_connections; char *name; + BOOL Clear; }; /**************************************************************************** @@ -80,11 +81,11 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u memcpy(&crec, dbuf.dptr, sizeof(crec)); - if (crec.cnum == -1) + if (crec.cnum == -1) return 0; /* if the pid was not found delete the entry from connections.tdb */ - if (!process_exists(crec.pid) && (errno == ESRCH)) { + if (cs->Clear && !process_exists(crec.pid)) { DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", (unsigned int)crec.pid, crec.cnum, crec.name)); tdb_delete(the_tdb, kbuf); @@ -106,8 +107,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO struct connections_key key; struct connections_data crec; TDB_DATA kbuf, dbuf; - BOOL db_locked = False; - BOOL ret = True; if (!tdb) { tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, @@ -126,28 +125,20 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO cs.mypid = sys_getpid(); cs.curr_connections = 0; cs.name = lp_servicename(SNUM(conn)); + cs.Clear = Clear; /* - * Go through and count the connections with the db locked. This is - * slow but essentially what 2.0.x did. JRA. + * Go through and count the connections */ - - if (tdb_lockall(tdb)) - return False; - - db_locked = True; - if (tdb_traverse(tdb, count_fn, &cs) == -1) { DEBUG(0,("claim_connection: traverse of connections.tdb failed.\n")); - ret = False; - goto out; + return False; } if (cs.curr_connections >= max_connections) { DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n", max_connections, name )); - ret = False; - goto out; + return False; } } @@ -182,14 +173,9 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO dbuf.dsize = sizeof(crec); if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) - ret = False; - - out: - - if (db_locked) - tdb_unlockall(tdb); + return False; - return ret; + return True; } #if 0 -- cgit From 10211f53f9fa9e21a6ededf892b8be27bad9643e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 May 2001 18:12:02 +0000 Subject: Check sizes of data entries in connections.tdb before deciding they're crecs... We will need this when we use finer grained locking for max connections. Jeremy. (This used to be commit c6cd42a6791e26174eb795fd08ddbbd797e5a9cf) --- source3/smbd/connection.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 47579fa5f7..5a3fcc2975 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -79,6 +79,9 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u struct connections_data crec; struct count_stat *cs = (struct count_stat *)udp; + if (dbuf.dsize != sizeof(crec)) + return 0; + memcpy(&crec, dbuf.dptr, sizeof(crec)); if (crec.cnum == -1) -- cgit From 8c4d6548a91961ecc2a177f4f6f95fbea4035cd3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 May 2001 00:24:34 +0000 Subject: groupdb/mapping.c: Fix gcc compiler warning. smbd/connection.c: Sync up with code in 2.2 Jeremy. (This used to be commit 87025c223dd33f2e02060c2a5cd45502946c87c6) --- source3/smbd/connection.c | 48 +++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5a3fcc2975..edbc49777e 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -84,18 +84,19 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u memcpy(&crec, dbuf.dptr, sizeof(crec)); - if (crec.cnum == -1) + if (crec.cnum == -1) return 0; - /* if the pid was not found delete the entry from connections.tdb */ - if (cs->Clear && !process_exists(crec.pid)) { + /* If the pid was not found delete the entry from connections.tdb */ + + if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) { DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", (unsigned int)crec.pid, crec.cnum, crec.name)); tdb_delete(the_tdb, kbuf); return 0; } - if (cs && strequal(crec.name, cs->name)) + if (strequal(crec.name, cs->name)) cs->curr_connections++; return 0; @@ -109,7 +110,9 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO { struct connections_key key; struct connections_data crec; - TDB_DATA kbuf, dbuf; + TDB_DATA kbuf, dbuf, lockkey; + BOOL rec_locked = False; + BOOL ret = True; if (!tdb) { tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, @@ -130,18 +133,30 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO cs.name = lp_servicename(SNUM(conn)); cs.Clear = Clear; + lockkey.dptr = cs.name; + lockkey.dsize = strlen(cs.name)+1; + /* - * Go through and count the connections + * Go through and count the connections with hash chain representing the service name + * locked. This is slow but removes race conditions. JRA. */ + + if (tdb_chainlock(tdb, lockkey)) + return False; + + rec_locked = True; + if (tdb_traverse(tdb, count_fn, &cs) == -1) { DEBUG(0,("claim_connection: traverse of connections.tdb failed.\n")); - return False; + ret = False; + goto out; } if (cs.curr_connections >= max_connections) { DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n", max_connections, name )); - return False; + ret = False; + goto out; } } @@ -176,19 +191,12 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO dbuf.dsize = sizeof(crec); if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) - return False; + ret = False; - return True; -} + out: -#if 0 -/**************************************************************************** - Use the count function to clean any dead records. Shouldn't be needed... -****************************************************************************/ + if (rec_locked) + tdb_chainunlock(tdb, lockkey); -void clean_connection_db(void) -{ - if (tdb_traverse(tdb, count_fn, NULL) == -1) - DEBUG(0,("clean_connection_db: traverse of connections.tdb failed.\n")); + return ret; } -#endif -- cgit From 2d27d8c720b705e8ca9575682948c0750c1bb080 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 17 May 2001 06:08:49 +0000 Subject: Fixes to get pam_auth() functionality working again. (This used to be commit 083b74c743f0026693fa0fbe665ed08a3ac706b8) --- source3/smbd/password.c | 21 +++++++++++---------- source3/smbd/reply.c | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 01fc9cdd53..303ed783e9 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1416,8 +1416,6 @@ static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, un return connect_to_domain_password_server(pcli, dc_name, trust_passwd); } - - /*********************************************************************** We have been asked to dynamcially determine the IP addresses of the PDC and BDC's for this DOMAIN, and query them in turn. @@ -1491,17 +1489,16 @@ static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd return connected_ok; } - - /*********************************************************************** Do the same as security=server, but using NT Domain calls and a session - key from the machine password. + key from the machine password. If the server parameter is specified + use it, otherwise figure out a server from the 'password server' param. ************************************************************************/ BOOL domain_client_validate( char *user, char *domain, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen, - BOOL *user_exists) + BOOL *user_exists, char *server) { unsigned char local_challenge[8]; unsigned char local_lm_response[24]; @@ -1541,7 +1538,7 @@ BOOL domain_client_validate( char *user, char *domain, * Not encrypted - do so. */ - DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n")); + DEBUG(5,("domain_client_validate: User passwords not in encrypted format.\n")); generate_random_buffer( local_challenge, 8, False); SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_response); @@ -1586,9 +1583,13 @@ BOOL domain_client_validate( char *user, char *domain, * PDC/BDC. Contact each in turn and try and authenticate. */ - pserver = lp_passwordserver(); - if (! *pserver) pserver = "*"; - p = pserver; + if (server) { + p = server; + } else { + pserver = lp_passwordserver(); + if (! *pserver) pserver = "*"; + p = pserver; + } while (!connected_ok && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 41970c4040..2e4837013e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -616,7 +616,7 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user ret = domain_client_validate(orig_user, domain, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen, - &user_exists); + &user_exists, NULL); if(ret) { /* -- cgit From faa0bef196b732b45c4614acd655af4881504808 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 May 2001 20:35:48 +0000 Subject: Defensive brlock and locking database cleaning code. Jeremy. (This used to be commit d7aa42e4593b02ee6e487f7a4633bd7e7620ef2f) --- source3/smbd/reply.c | 82 +++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2e4837013e..b43512329e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -603,57 +603,55 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { - BOOL ret = False; - BOOL user_exists = True; - struct passwd *pwd=NULL; + BOOL ret = False; + BOOL user_exists = True; + struct passwd *pwd=NULL; - if(lp_security() != SEC_DOMAIN) - return False; + if(lp_security() != SEC_DOMAIN) + return False; - if (!check_domain_match(orig_user, domain)) - return False; + if (!check_domain_match(orig_user, domain)) + return False; - ret = domain_client_validate(orig_user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen, - &user_exists, NULL); + ret = domain_client_validate(orig_user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen, + &user_exists, NULL); - if(ret) { - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - */ - if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) { - smb_create_user(unix_user, NULL); - } + if(ret) { + /* + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. + */ + if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) + smb_create_user(unix_user, NULL); - if(lp_adduser_script() && pwd) { - SMB_STRUCT_STAT st; + if(lp_adduser_script() && pwd) { + SMB_STRUCT_STAT st; - /* - * Also call smb_create_user if the users home directory - * doesn't exist. Used with winbindd to allow the script to - * create the home directory for a user mapped with winbindd. - */ + /* + * Also call smb_create_user if the users home directory + * doesn't exist. Used with winbindd to allow the script to + * create the home directory for a user mapped with winbindd. + */ - if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) - smb_create_user(unix_user, pwd->pw_dir); - } + if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) + smb_create_user(unix_user, pwd->pw_dir); + } - } else { - /* - * User failed to validate ok against Domain controller. - * If the failure was "user doesn't exist" and admin - * wants us to try and delete that UNIX user on the fly, - * do so. - */ - if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) { - smb_delete_user(unix_user); - } - } + } else { + /* + * User failed to validate ok against Domain controller. + * If the failure was "user doesn't exist" and admin + * wants us to try and delete that UNIX user on the fly, + * do so. + */ + if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) + smb_delete_user(unix_user); + } - return ret; + return ret; } /**************************************************************************** -- cgit From 4d86a2841cd3941c8b67e3f2dc1670562b6874a6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 May 2001 18:47:52 +0000 Subject: This is *very* cool. I'm pretty convinced we can just set the CAP_LARGE_READX|CAP_LARGE_WRITEX bits on negprot and out W2K performance goes through the roof...... And as we *always* offer 64 buffers we can do this with this simple change..... Jeremy. (This used to be commit c328dda0fa081e79049d7a9ddac06e80cc8b331b) --- source3/smbd/negprot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index ffc5d5e398..6c45e37654 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -160,6 +160,7 @@ static int reply_nt1(char *outbuf) /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_LEVEL_II_OPLOCKS| (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | + CAP_LARGE_READX | CAP_LARGE_WRITEX | (SMB_OFF_T_BITS == 64 ? CAP_LARGE_FILES : 0); -- cgit From b065de612caef016876328a3ab8cf842f700921b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 May 2001 21:33:43 +0000 Subject: Added tdb_errstr() messages so we can see if these functions fail. Jeremy. (This used to be commit ec64ddac5fa4688b18484d6599b17b8c4bcd34c0) --- source3/smbd/connection.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index edbc49777e..16f6ba6afd 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -141,13 +141,17 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO * locked. This is slow but removes race conditions. JRA. */ - if (tdb_chainlock(tdb, lockkey)) + if (tdb_chainlock(tdb, lockkey)) { + DEBUG(0,("claim_connection: tdb_chainlock failed %s\n", + tdb_errorstr(tdb) )); return False; + } rec_locked = True; if (tdb_traverse(tdb, count_fn, &cs) == -1) { - DEBUG(0,("claim_connection: traverse of connections.tdb failed.\n")); + DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", + tdb_errorstr(tdb) )); ret = False; goto out; } @@ -190,8 +194,11 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO dbuf.dptr = (char *)&crec; dbuf.dsize = sizeof(crec); - if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) + if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { + DEBUG(0,("claim_connection: tdb_store failed with error %s.\n", + tdb_errorstr(tdb) )); ret = False; + } out: -- cgit From 9ff6634db923da17b0946141abf3ce7df61a0dab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 May 2001 19:28:22 +0000 Subject: Fixup the large_writex problem (a large_writex can send a full 64k of data, we already have space for this we just need to understand the length correctly). Jeremy. (This used to be commit 19145bae720bbcc32dcab380c62a33d1f0e3eef0) --- source3/smbd/oplock.c | 4 ++-- source3/smbd/process.c | 6 +++--- source3/smbd/reply.c | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e0b494017a..ac0836324b 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -676,13 +676,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B messages crossing on the wire. */ - if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + if((inbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); return False; } - if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + if((outbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); free(inbuf); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ac5454c48c..74c0cbc96f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1184,8 +1184,8 @@ void smbd_process(void) time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; - InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + InBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); + OutBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); if ((InBuffer == NULL) || (OutBuffer == NULL)) return; @@ -1208,7 +1208,7 @@ void smbd_process(void) lp_talloc_free(); main_loop_talloc_free(); - while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) { + while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b43512329e..914f1801d2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2665,10 +2665,11 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng { files_struct *fsp = file_fsp(inbuf,smb_vwv2); SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); - size_t numtowrite = SVAL(inbuf,smb_vwv10); + size_t numtowrite = SVAL(inbuf,smb_vwv10)|(((size_t)SVAL(inbuf,smb_vwv9))<<16); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); ssize_t nwritten = -1; unsigned int smb_doff = SVAL(inbuf,smb_vwv11); + unsigned int smblen = smb_len(inbuf); char *data; START_PROFILE(SMBwriteX); @@ -2682,7 +2683,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_WRITE(fsp); CHECK_ERROR(fsp); - if(smb_doff > smb_len(inbuf)) { + if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { END_PROFILE(SMBwriteX); return(ERROR(ERRDOS,ERRbadmem)); } -- cgit From 15e66ba37ae56787897e49039e217b5426924829 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 May 2001 00:48:28 +0000 Subject: Added tdb_change_int_atomic() to allow atomic updates of a tdb int value. Jeremy. (This used to be commit cf5015f15935605cf69078bc15251db61ddc48c7) --- source3/smbd/process.c | 12 ++++++------ source3/smbd/server.c | 8 +++----- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 74c0cbc96f..1f575e2a46 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -781,12 +781,12 @@ static BOOL smbd_process_limit(void) /* Always add one to the smbd process count, as exit_server() always * subtracts one. */ - tdb_lock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); - total_smbds = tdb_fetch_int(conn_tdb_ctx(), "INFO/total_smbds"); - total_smbds = total_smbds < 0 ? 1 : total_smbds + 1; - tdb_store_int(conn_tdb_ctx(), "INFO/total_smbds", total_smbds); - tdb_unlock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); - + + total_smbds = 1; /* In case we need to create the entry. */ + + if (tdb_change_int_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1) + return True; + return total_smbds > lp_max_smbd_processes(); } else diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6f4f18562e..fcee30d667 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -421,16 +421,14 @@ static BOOL dump_core(void) /**************************************************************************** update the current smbd process count ****************************************************************************/ + static void decrement_smbd_process_count(void) { int total_smbds; if (lp_max_smbd_processes()) { - tdb_lock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); - if ((total_smbds = tdb_fetch_int(conn_tdb_ctx(), "INFO/total_smbds")) > 0) - tdb_store_int(conn_tdb_ctx(), "INFO/total_smbds", total_smbds - 1); - - tdb_unlock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + total_smbds = 0; + tdb_change_int_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1); } } -- cgit From fe6208d09a380e29831240aeb84365f60d048c00 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 25 May 2001 02:45:07 +0000 Subject: return an error code on password attack, rather than exiting. otherwise security scanners may think we are vulnerable! (This used to be commit ee8cb88682421464016d56209eecea764bddc032) --- source3/smbd/reply.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 914f1801d2..23fedccd88 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -54,7 +54,6 @@ static void overflow_attack(int len) dbgtext( "attempting to exploit an old bug.\n" ); dbgtext( "Attack was from IP = %s.\n", client_addr() ); } - exit_server("possible attack"); } @@ -270,6 +269,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (passlen > MAX_PASS_LEN) { overflow_attack(passlen); + return(ERROR(ERRDOS,ERRbuftoosmall)); } memcpy(password,smb_buf(inbuf),passlen); @@ -704,8 +704,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASS_LEN) - overflow_attack(smb_apasslen); + if (smb_apasslen > MAX_PASS_LEN) { + overflow_attack(smb_apasslen); + return(ERROR(ERRDOS,ERRbuftoosmall)); + } memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); smb_apasswd[smb_apasslen] = 0; @@ -738,7 +740,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int doencrypt = False; if (passlen1 > MAX_PASS_LEN) { - overflow_attack(passlen1); + overflow_attack(passlen1); + return(ERROR(ERRDOS,ERRbuftoosmall)); } passlen1 = MIN(passlen1, MAX_PASS_LEN); -- cgit From 22242c5038008171631c2625b2fd8b6d4b991078 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 25 May 2001 07:36:58 +0000 Subject: i18n fix for domain_client_validate() (This used to be commit d6dcca7cc9bc5a1948c1b6126ca4f6cb9ccacc52) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 303ed783e9..35aaf10e06 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1562,7 +1562,7 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password for our primary domain */ - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) + if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time)) { DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup())); return False; -- cgit From 5237500c736e9dcef05421e0b9234a51cb459625 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 30 May 2001 06:08:23 +0000 Subject: use the new tdb_open_log() fn on connections database (This used to be commit 68c0dcec3d3c17aae76ce093a601c9f452af5a0c) --- source3/smbd/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 16f6ba6afd..d3124e8d0c 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -115,7 +115,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO BOOL ret = True; if (!tdb) { - tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, + tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); } if (!tdb) -- cgit From 63c7ca9d6263fca56e335eccfbad1d773af5a1c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 May 2001 14:13:53 +0000 Subject: Fix debug statement so it doesn't use lp_workgroup() either. Jeremy. (This used to be commit 18e652a5e0d30d033be70e512cd94bf867507f64) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 35aaf10e06..51528be2b4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1564,7 +1564,7 @@ BOOL domain_client_validate( char *user, char *domain, */ if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time)) { - DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup())); + DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", domain)); return False; } -- cgit From e07b85ab195509cd1bd83e813ecf464f5629c566 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 1 Jun 2001 11:26:20 +0000 Subject: Added *.po to .cvsignore files. (This used to be commit 870e9e4e89dcf910c595cabb28f69ad070942072) --- source3/smbd/.cvsignore | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/.cvsignore b/source3/smbd/.cvsignore index e69de29bb2..6d609cec52 100644 --- a/source3/smbd/.cvsignore +++ b/source3/smbd/.cvsignore @@ -0,0 +1 @@ +*.po -- cgit From 05fc3e578c895f632b351969d09cd00feb7599c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 4 Jun 2001 05:13:59 +0000 Subject: use LDSHFLAGS not -shared in several places (This used to be commit 8ec9c87b5d1a7dae17d5b1a30f58effaf5e69e4b) --- source3/smbd/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 40654c0f43..8f6907c537 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -62,7 +62,7 @@ BOOL session_claim(uint16 vuid) } if (!tdb) { - tdb = tdb_open(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST, + tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); if (!tdb) { DEBUG(1,("session_claim: failed to open sessionid tdb\n")); -- cgit From 091fd5a1746080b8a988f08557ba5f9df97653a4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Jun 2001 06:29:57 +0000 Subject: Deal with incorrect large writes from old NT4.x clients. We still need to set the large write reply correctly. Jeremy. (This used to be commit 810dae29b8b45e91c0c35a4d96202c08b13d4e82) --- source3/smbd/reply.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 23fedccd88..7cb23d8629 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2668,7 +2668,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng { files_struct *fsp = file_fsp(inbuf,smb_vwv2); SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); - size_t numtowrite = SVAL(inbuf,smb_vwv10)|(((size_t)SVAL(inbuf,smb_vwv9))<<16); + size_t numtowrite = SVAL(inbuf,smb_vwv10); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); ssize_t nwritten = -1; unsigned int smb_doff = SVAL(inbuf,smb_vwv11); @@ -2686,6 +2686,10 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_WRITE(fsp); CHECK_ERROR(fsp); + /* Deal with possible LARGE_WRITEX */ + if (smblen > 0xFFFF) + numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); + if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { END_PROFILE(SMBwriteX); return(ERROR(ERRDOS,ERRbadmem)); -- cgit From 5264e9a2a737d6498be0f346bcbc3b583609abf5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Jun 2001 08:17:16 +0000 Subject: Set correct reply word in large writeX (greater than 64k) replies. Also added smbtorture test for this. Jeremy. (This used to be commit 6d65556ae8bea45a203defaded8436cbb56965e1) --- source3/smbd/reply.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7cb23d8629..d3f2527b35 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2674,6 +2674,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng unsigned int smb_doff = SVAL(inbuf,smb_vwv11); unsigned int smblen = smb_len(inbuf); char *data; + BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); START_PROFILE(SMBwriteX); /* If it's an IPC, pass off the pipe handler. */ @@ -2687,7 +2688,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_ERROR(fsp); /* Deal with possible LARGE_WRITEX */ - if (smblen > 0xFFFF) + if (large_writeX) numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { @@ -2742,7 +2743,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng set_message(outbuf,6,0,True); SSVAL(outbuf,smb_vwv2,nwritten); - + if (large_writeX) + SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); + if (nwritten < (ssize_t)numtowrite) { CVAL(outbuf,smb_rcls) = ERRHRD; SSVAL(outbuf,smb_err,ERRdiskfull); -- cgit From 79ca1f75bb98bd54feee7f2ad0fcfa36d017b92e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jun 2001 02:49:30 +0000 Subject: Correctly make max pathlength 255. Jeremy. (This used to be commit 30cffea8fa813a7448648b496a19e751441e436e) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index be130247c0..7b2167b6ca 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1196,7 +1196,7 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| FILE_DEVICE_IS_MOUNTED| (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ - SIVAL(pdata,4,128); /* Max filename component length */ + SIVAL(pdata,4,255); /* Max filename component length */ len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE|STR_CONVERT); SIVAL(pdata,8,len); data_len = 12 + len; -- cgit From 3414c71f6de04d0ba26841bceac381498f43ecad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jun 2001 03:02:34 +0000 Subject: Extra stuff for large readwrite support. Jeremy. (This used to be commit 4338ee78c3d7bcf4b9fac383ff2f572d882ab97c) --- source3/smbd/negprot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 6c45e37654..83c809de1c 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -160,7 +160,8 @@ static int reply_nt1(char *outbuf) /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_LEVEL_II_OPLOCKS| (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | - CAP_LARGE_READX | CAP_LARGE_WRITEX | + ((lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) ? + CAP_LARGE_READX | CAP_LARGE_WRITEX | CAP_W2K_SMBS : 0) | (SMB_OFF_T_BITS == 64 ? CAP_LARGE_FILES : 0); -- cgit From a72b7148226e7d838d174d5309bdb7fbd43a5cbd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jun 2001 20:26:46 +0000 Subject: Log tdb failures. Jeremy. (This used to be commit f004471aac3a1a0f2e40c05d1aadfe68456bc103) --- source3/smbd/connection.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index d3124e8d0c..796a54e77d 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -58,7 +58,10 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); - tdb_delete(tdb, kbuf); + if (tdb_delete(tdb, kbuf) != 0) { + DEBUG(0,("yield_connection: tdb_delete failed with error %s.\n", tdb_errorstr(tdb) )); + return (False); + } return(True); } @@ -92,7 +95,8 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) { DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", (unsigned int)crec.pid, crec.cnum, crec.name)); - tdb_delete(the_tdb, kbuf); + if (tdb_delete(the_tdb, kbuf) != 0) + DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) )); return 0; } -- cgit From f63ee18c684af33342de2c5757f9fdf0b7d84997 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 9 Jun 2001 01:38:54 +0000 Subject: *Wonderful* patch from Andrew Bartlett that will help ensure tdb's are cleaned on clients abending connections. Thanks Andrew ! Jeremy. (This used to be commit 1b3977c5367a0b713b194f369abd9872ae01ac2a) --- source3/smbd/blocking.c | 22 ++++++++++++---------- source3/smbd/ipc.c | 9 ++++++--- source3/smbd/notify.c | 3 ++- source3/smbd/nttrans.c | 9 ++++++--- source3/smbd/oplock.c | 6 ++++-- source3/smbd/posix_acls.c | 25 +++++++++++++++++++------ source3/smbd/process.c | 5 +++-- source3/smbd/reply.c | 12 ++++++++---- source3/smbd/ssl.c | 6 ++++-- source3/smbd/trans2.c | 9 ++++++--- 10 files changed, 70 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index e8dc29f80a..cebad5ce35 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -130,10 +130,11 @@ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, static void send_blocking_reply(char *outbuf, int outsize) { - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); + if(outsize > 4) + smb_setlen(outbuf,outsize - 4); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_blocking_reply: send_smb failed.\n"); } /**************************************************************************** @@ -171,15 +172,16 @@ static void reply_lockingX_success(blocking_lock_record *blr) static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, int32 ecode) { - char *outbuf = OutBuffer; - char *inbuf = blr->inbuf; - construct_reply_common(inbuf, outbuf); + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + construct_reply_common(inbuf, outbuf); - if(eclass == 0) /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + if(eclass == 0) /* NT Error. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - ERROR(eclass,ecode); - send_smb(smbd_server_fd(),outbuf); + ERROR(eclass,ecode); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("generic_blocking_lock_error: send_smb failed.\n"); } /**************************************************************************** diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1418d3444f..efad2d27c0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -128,7 +128,8 @@ void send_trans_reply(char *outbuf, SSVAL(outbuf,smb_vwv9,0); show_msg(outbuf); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans_reply: send_smb failed.\n"); tot_data_sent = this_ldata; tot_param_sent = this_lparam; @@ -161,7 +162,8 @@ void send_trans_reply(char *outbuf, SSVAL(outbuf,smb_vwv9,0); show_msg(outbuf); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans_reply: send_smb failed.\n"); tot_data_sent += this_ldata; tot_param_sent += this_lparam; @@ -424,7 +426,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); show_msg(outbuf); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_trans: send_smb failed.\n"); } /* receive the rest of the trans packet */ diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 429723c19e..3c21ce1e1b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -71,7 +71,8 @@ static void change_notify_reply_packet(char *inbuf, uint32 error_code) */ set_message(outbuf,18,0,False); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("change_notify_reply_packet: send_smb failed.\n"); } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b67815ff69..d58bb106af 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -96,7 +96,8 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err */ if(params_to_send == 0 && data_to_send == 0) { - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_nt_replies: send_smb failed.\n"); return 0; } @@ -225,7 +226,8 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err params_to_send, data_to_send, paramsize, datasize)); /* Send the packet */ - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_nt_replies: send_smb failed.\n"); pp += params_sent_thistime; pd += data_sent_thistime; @@ -1780,7 +1782,8 @@ due to being in oplock break state.\n" )); /* We need to send an interim response then receive the rest of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_nttrans: send_smb failed.\n"); while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { BOOL ret; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ac0836324b..4482c0221c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -572,7 +572,8 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) /* Prepare the SMBlockingX message. */ prepare_break_message( outbuf, fsp, False); - send_smb(smbd_server_fd(), outbuf); + if (!send_smb(smbd_server_fd(), outbuf)) + exit_server("oplock_break_level2: send_smb failed.\n"); } /* @@ -716,7 +717,8 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - send_smb(smbd_server_fd(), outbuf); + if (!send_smb(smbd_server_fd(), outbuf)) + exit_server("oplock_break: send_smb failed.\n"); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0cc0f2bac6..d369746e50 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2056,12 +2056,25 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) } } - if (acl_perms && acl_set_support && fsp->is_directory && dir_ace_list) { - if (!set_canon_ace_list(fsp, dir_ace_list, True, &acl_set_support)) { - DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - return False; + if (acl_perms && acl_set_support && fsp->is_directory) { + if (dir_ace_list) { + if (!set_canon_ace_list(fsp, dir_ace_list, True, &acl_set_support)) { + DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } + } else { + + /* + * No default ACL - delete one if it exists. + */ + + if (sys_acl_delete_def_file(dos_to_unix(fsp->fsp_name,False)) == -1) { + DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); + free_canon_ace_list(file_ace_list); + return False; + } } } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1f575e2a46..f757467680 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -822,7 +822,7 @@ void process_smb(char *inbuf, char *outbuf) static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) ); - send_smb(smbd_server_fd(),(char *)buf); + (void)send_smb(smbd_server_fd(),(char *)buf); exit_server("connection denied"); } } @@ -860,7 +860,8 @@ void process_smb(char *inbuf, char *outbuf) nread, smb_len(outbuf))); } else - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("process_smb: send_smb failed.\n"); } trans_num++; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d3f2527b35..9705bfd6b3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2487,7 +2487,8 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CVAL(outbuf,smb_com) = SMBwritebraw; SSVALS(outbuf,smb_vwv0,-1); outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_writebraw: send_smb failed.\n"); /* Now read the raw data into the buffer and write it */ if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { @@ -3172,7 +3173,8 @@ int reply_echo(connection_struct *conn, smb_setlen(outbuf,outsize - 4); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_echo: send_smb failed.\n"); } DEBUG(3,("echo %d times\n", smb_reverb)); @@ -4552,7 +4554,8 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, SSVAL(outbuf,smb_vwv6,nread); SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_readbmpx: send_smb failed.\n"); total_read += nread; startpos += nread; @@ -4650,7 +4653,8 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, if (write_through && tcount==nwritten) { /* we need to send both a primary and a secondary response */ smb_setlen(outbuf,outsize - 4); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_writebmpx: send_smb failed.\n"); /* now the secondary */ outsize = set_message(outbuf,1,0,True); diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index 65d6532d48..67a8afc82e 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -255,11 +255,13 @@ char *reqHosts, *resignHosts; if(msg_type != 0x81){ /* first packet must be a session request */ DEBUG( 0, ( "Client %s did not use session setup; access denied\n", client_addr() ) ); - send_smb(fd, (char *)buf); + if (!send_smb(fd, (char *)buf)) + exit_server("sslutil_negotiate_ssl: send_smb failed.\n"); return -1; } buf[4] = 0x8e; /* negative session response: use SSL */ - send_smb(fd, (char *)buf); + if (!send_smb(fd, (char *)buf)) + exit_server("sslutil_negotiate_ssl: send_smb failed.\n"); if(sslutil_accept(fd) != 0){ DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr() ) ); return -1; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7b2167b6ca..6f970ee3ac 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -65,7 +65,8 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, the empty packet */ if(params_to_send == 0 && data_to_send == 0) { - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans2_replies: send_smb failed.\n"); return 0; } @@ -160,7 +161,8 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, params_to_send, data_to_send, paramsize, datasize)); /* Send the packet */ - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans2_replies: send_smb failed.\n"); pp += params_sent_thistime; pd += data_sent_thistime; @@ -2340,7 +2342,8 @@ int reply_trans2(connection_struct *conn, /* We need to send an interim response then receive the rest of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_trans2: send_smb failed.\n"); while (num_data_sofar < total_data || num_params_sofar < total_params) { -- cgit From 2f99c0e602f4fe4d7a95e08d882a0669d9adad11 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Jun 2001 01:49:30 +0000 Subject: lib/util_getent.c: removed debug code. smbd/posix_acls.c: Attempt to fix the "lose default acl" problem in Solaris. Needs testing. lib/sysacls.c: Typo fix. Jeremy. (This used to be commit d989f8bd3e1524183a24fb67be1af05b3289f648) --- source3/smbd/posix_acls.c | 53 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d369746e50..4832184df7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -631,18 +631,19 @@ static BOOL create_canon_ace_lists(files_struct *fsp, canon_ace *current_ace = NULL; BOOL got_dir_allow = False; BOOL got_file_allow = False; - int i; + int i, j; *ppfile_ace = NULL; *ppdir_ace = NULL; + /* + * Convert the incoming ACL into a more regular form. + */ + for(i = 0; i < dacl->num_aces; i++) { - enum SID_NAME_USE sid_type; SEC_ACE *psa = &dacl->ace[i]; if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - free_canon_ace_list(file_ace); - free_canon_ace_list(dir_ace); DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n")); return False; } @@ -664,6 +665,50 @@ static BOOL create_canon_ace_lists(files_struct *fsp, if(psa->info.mask != UNIX_ACCESS_NONE) psa->info.mask &= ~UNIX_ACCESS_NONE; + } + + /* + * Deal with the fact that NT 4.x re-writes the canonical format + * that we return for default ACLs. If a directory ACE is identical + * to a inherited directory ACE then NT changes the bits so that the + * first ACE is set to OI|IO and the second ACE for this SID is set + * to CI. We need to repair this. JRA. + */ + + for(i = 0; i < dacl->num_aces; i++) { + SEC_ACE *psa1 = &dacl->ace[i]; + + for (j = i + 1; j < dacl->num_aces; j++) { + SEC_ACE *psa2 = &dacl->ace[j]; + + if (psa1->info.mask != psa2->info.mask) + continue; + + if (!sid_equal(&psa1->sid, &psa2->sid)) + continue; + + /* + * Ok - permission bits and SIDs are equal. + * Check if flags were re-written. + */ + + if (psa1->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + + psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)); + psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT); + + } else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + + psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)); + psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT); + + } + } + } + + for(i = 0; i < dacl->num_aces; i++) { + enum SID_NAME_USE sid_type; + SEC_ACE *psa = &dacl->ace[i]; /* * Create a cannon_ace entry representing this NT DACL ACE. -- cgit From 10f8162124cd29fdf8324f03baf950cf29d34921 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 12 Jun 2001 09:51:03 +0000 Subject: Removed commented out msdfs code that was being called anyway. (This used to be commit a542f4513ab792363fd5772582c6d317aa913257) --- source3/smbd/reply.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9705bfd6b3..da73a78a33 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1149,8 +1149,6 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf)); - */ /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (! (*fname)) -- cgit From 1aa05a31ac9eb0987e641312195ed12c76476b27 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 14 Jun 2001 00:08:42 +0000 Subject: Fixed some return code checks for cli_initialise() from False to NULL. Spotted by Joe Doran (This used to be commit 3e3b9bc5380652d882c02e7286258f0aabcaf395) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 51528be2b4..d2059e7e20 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1267,7 +1267,7 @@ static BOOL connect_to_domain_password_server(struct cli_state *pcli, struct in_addr dest_ip; fstring remote_machine; - if(cli_initialise(pcli) == False) { + if(cli_initialise(pcli) == NULL) { DEBUG(0,("connect_to_domain_password_server: unable to initialize client connection.\n")); return False; } -- cgit From 9b70bdfc38f20fb34c3b192819552d1e48cefed7 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 15 Jun 2001 08:00:36 +0000 Subject: Be sure to not use strlen with NULL pointer. (This used to be commit 53803b008717e8606b347ed8baab78121c6e9657) --- source3/smbd/utmp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 486c7fe06e..f79cd43c5b 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -391,7 +391,8 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) getutmpx(u, &ux); #if defined(HAVE_UX_UT_SYSLEN) - ux.ut_syslen = strlen(hostname) + 1; /* include end NULL */ + if (hostname) ux.ut_syslen = strlen(hostname) + 1; /* include end NULL */ + else ux.ut_syslen = 0; #endif safe_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)-1); -- cgit From c0be2fc029463428c604abdd8f90f49b3925ea90 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Jun 2001 23:42:41 +0000 Subject: Best-effort so far implementation of new W2K info levels. An-embrace-and-extending we will go... Jeremy. (This used to be commit 43bf9b2c7aad15d65bac3a9c4f799be050a074cd) --- source3/smbd/trans2.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6f970ee3ac..29c68bd0e0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1553,6 +1553,154 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = PTR_DIFF(pdata,(*ppdata)); break; + /* + * Windows 2000 completely undocumented new SMB info levels. + * Thanks Microsoft.... sure you're working on making this + * protocol a standard.... sure you are... :-). + * Lying rat-bastards. JRA. + */ + + case 1004: + put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + SIVAL(pdata,32,mode); + SIVAL(pdata,36,0); /* ??? */ + data_size = 40; + break; + + case 1005: + SIVAL(pdata,0,mode); + SIVAL(pdata,4,0); /* ??? */ + SOFF_T(pdata,8,size); + SIVAL(pdata,16,1); /* ??? */ + SIVAL(pdata,20,0); /* ??? */ + data_size = 24; + break; + + case 1006: + SIVAL(pdata,0,0x907); /* ??? */ + SIVAL(pdata,4,0x690000); /* ??? */ + data_size = 8; + break; + + case 1007: + SIVAL(pdata,0,0); /* ??? */ + data_size = 4; + break; + + case 1008: + SIVAL(pdata,0,0x12019F); /* ??? */ + data_size = 4; + break; + + case 1009: + /* Pathname with leading '\'. */ + { + pstring new_fname; + size_t byte_len; + + pstrcpy(new_fname, "\\"); + pstrcat(new_fname, fname); + byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False); + SIVAL(pdata,0,byte_len); + data_size = 4 + byte_len; + break; + } + + case 1014: + SIVAL(pdata,0,0); /* ??? */ + SIVAL(pdata,4,0); /* ??? */ + data_size = 8; + break; + + case 1016: + SIVAL(pdata,0,0); /* ??? */ + data_size = 4; + break; + + case 1017: + SIVAL(pdata,0,0); /* ??? */ + data_size = 4; + break; + +#if 0 + /* Not yet finished... JRA */ + case 1018: + { + pstring new_fname; + size_t byte_len; + + put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + SIVAL(pdata,32,mode); + SIVAL(pdata,36,0); /* ??? */ + SIVAL(pdata,40,0x20); /* ??? */ + SIVAL(pdata,44,0); /* ??? */ + SOFF_T(pdata,48,size); + SIVAL(pdata,56,0x1); /* ??? */ + SIVAL(pdata,60,0); /* ??? */ + SIVAL(pdata,64,0); /* ??? */ + SIVAL(pdata,68,length); /* Following string length in bytes. */ + dos_PutUniCode(pdata+72,,False); + break; + } +#endif + + case 1021: + /* Last component of pathname. */ + { + size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False); + SIVAL(pdata,0,byte_len); + data_size = 4 + byte_len; + break; + } + + case 1022: + { + size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False); + SIVAL(pdata,0,0); /* ??? */ + SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ + SOFF_T(pdata,8,size); + SIVAL(pdata,16,0x20); /* ??? */ + SIVAL(pdata,20,0); /* ??? */ + data_size = 24 + byte_len; + break; + } + + case 1028: + SOFF_T(pdata,0,size); + SIVAL(pdata,8,0); /* ??? */ + SIVAL(pdata,12,0); /* ??? */ + data_size = 16; + break; + + case 1034: + put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + SIVAL(pdata,32,0x20); /* ??? */ + SIVAL(pdata,36,0); /* ??? */ + SOFF_T(pdata,40,size); + SIVAL(pdata,48,mode); + SIVAL(pdata,52,0); /* ??? */ + data_size = 56; + break; + + case 1035: + SIVAL(pdata,0,mode); + SIVAL(pdata,4,0); + data_size = 8; + break; + + /* + * End new completely undocumented info levels... JRA. + */ + #if 0 /* NT4 server just returns "invalid query" to this - if we try to answer it then NTws gets a BSOD! (tridge) */ -- cgit From 5f633c0e5e17c3b0c30b819f147e5d6672e86649 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Jun 2001 00:11:12 +0000 Subject: Set support for info levels... Jeremy. (This used to be commit e033f758914f6631545af17041b4e49c1ff885d9) --- source3/smbd/trans2.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 29c68bd0e0..f88ddb41aa 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1448,7 +1448,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */ case SMB_QUERY_FILE_BASIC_INFO: - data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ + case 1004: + + if (info_level == SMB_QUERY_FILE_BASIC_INFO) + data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ + else { + data_size = 40; + SIVAL(pdata,36,0); + } put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ @@ -1560,16 +1567,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, * Lying rat-bastards. JRA. */ - case 1004: - put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - SIVAL(pdata,32,mode); - SIVAL(pdata,36,0); /* ??? */ - data_size = 40; - break; - case 1005: SIVAL(pdata,0,mode); SIVAL(pdata,4,0); /* ??? */ @@ -1881,6 +1878,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; case SMB_SET_FILE_BASIC_INFO: + case 1004: { /* Patch to do this correctly from Paul Eggert . */ time_t write_time; @@ -1902,14 +1900,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, ? changed_time : write_time); -#if 0 /* Needs more testing... */ - /* Test from Luke to prevent Win95 from - setting incorrect values here. - */ - if (tvs.actime < tvs.modtime) - return(ERROR(ERRDOS,ERRnoaccess)); -#endif /* Needs more testing... */ - /* attributes */ mode = IVAL(pdata,32); break; @@ -1920,6 +1910,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * to mean truncate the file. JRA. */ + case 1019: + case 1020: case SMB_SET_FILE_ALLOCATION_INFO: { SMB_OFF_T newsize = IVAL(pdata,0); @@ -2053,7 +2045,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(6,("mode: %x\n" , mode)); if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || - (info_level == SMB_SET_FILE_ALLOCATION_INFO))) { + (info_level == SMB_SET_FILE_ALLOCATION_INFO) || + (info_level == 1019) || + (info_level == 1020))) { /* * Only do this test if we are not explicitly * changing the size of a file. -- cgit From 850a0e27e19ac21bc66d3d26875d3f9bafd5245c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Jun 2001 07:31:55 +0000 Subject: Extra debug in open.c, fix for bad debug message in reply.c Jeremy. (This used to be commit 2c2fc8513699eb39721ac1d65fa1fdaecde526a8) --- source3/smbd/open.c | 4 ++-- source3/smbd/reply.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8db4400664..a88dfd5573 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -492,8 +492,8 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T BOOL opb_ret; - DEBUG(5,("open_mode_check: breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode)); /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index da73a78a33..2f9898616c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4343,7 +4343,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, BOOL break_to_none = (oplocklevel == 0); DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n", - fsp->fnum, (unsigned int)oplocklevel )); + (unsigned int)oplocklevel, fsp->fnum )); /* * Make sure we have granted an exclusive or batch oplock on this file. -- cgit From fcda2645f099e5d356361ec3de4f45d97285f0b5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jun 2001 03:05:09 +0000 Subject: added a close-share smbcontrol message that forcibly closes a share in smbd (to allow unmount) (This used to be commit 15b17a80db605a55f667c95fb7e316877a441887) --- source3/smbd/conn.c | 30 ++++++++++++++++++++++++++++++ source3/smbd/process.c | 9 +++++++++ source3/smbd/service.c | 2 ++ 3 files changed, 41 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index e9f79fdf32..c2faa4f15a 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -198,3 +198,33 @@ void conn_free(connection_struct *conn) ZERO_STRUCTP(conn); free(conn); } + + +/**************************************************************************** +receive a smbcontrol message to forcibly unmount a share +the message contains just a share name and all instances of that +share are unmounted +the special sharename '*' forces unmount of all shares +****************************************************************************/ +void msg_force_tdis(int msg_type, pid_t pid, void *buf, size_t len) +{ + connection_struct *conn, *next; + fstring sharename; + + fstrcpy(sharename, buf); + + if (strcmp(sharename, "*") == 0) { + DEBUG(1,("Forcing close of all shares\n")); + conn_close_all(); + return; + } + + for (conn=Connections;conn;conn=next) { + next=conn->next; + if (strequal(lp_servicename(conn->service), sharename)) { + DEBUG(1,("Forcing close of share %s cnum=%d\n", + sharename, conn->cnum)); + close_cnum(conn, (uint16)-1); + } + } +} diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f757467680..72e0fc311a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -693,6 +693,12 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if (!(flags & AS_USER)) unbecome_user(); + /* does this protocol need a valid tree connection? */ + if ((flags & AS_USER) && !conn) { + return ERROR(ERRSRV, ERRinvnid); + } + + /* does this protocol need to be run as the connected user? */ if ((flags & AS_USER) && !become_user(conn,session_tag)) { if (flags & AS_GUEST) @@ -1195,6 +1201,9 @@ void smbd_process(void) /* re-initialise the timezone */ TimeInit(); + /* register our message handlers */ + message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); + while (True) { int deadtime = lp_deadtime()*60; int select_timeout = setup_select_timeout(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c70ab42a61..61da72b2e9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -697,3 +697,5 @@ void close_cnum(connection_struct *conn, uint16 vuid) } conn_free(conn); } + + -- cgit From 3f1254bee1b3cc8cce1e17be6f0250090f579417 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Jun 2001 19:55:59 +0000 Subject: Fixed W2K SP2 joining a Samba PDC hosted domain. Jermey. (This used to be commit 05a2911403a0710d994a618e72743205a3b0b87a) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index cf1fca405a..c6f6eca0ba 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -776,7 +776,7 @@ BOOL check_oem_password(char *user, /* * Call the hash function to get the new password. */ - SamOEMhash((uchar *) lmdata, (uchar *)lanman_pw, True); + SamOEMhash((uchar *) lmdata, (uchar *)lanman_pw, 516); /* * The length of the new password is in the last 4 bytes of -- cgit From fda0f83d751a1ea6c731fd6a82484a724a1c6e32 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Jun 2001 01:01:15 +0000 Subject: Following info from TAKAHASHI Motonobu , Samba Users Group Japan, ensure that we don't use dos_to_unix(xx,True), but always use dos_to_unix(xx,False) to prevent overwriting. Jeremy. (This used to be commit 244aec8ea623fec828add3ab09c5003bf32bd5c7) --- source3/smbd/message.c | 5 ++--- source3/smbd/reply.c | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 98eb336c0a..a023650c74 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -61,13 +61,12 @@ static void msg_deliver(void) } /* - * Incoming message is in DOS codepage format. Convert to UNIX in - * place. + * Incoming message is in DOS codepage format. Convert to UNIX. */ if(msgpos > 0) { msgbuf[msgpos] = '\0'; /* Ensure null terminated. */ - dos_to_unix(msgbuf,True); + pstrcpy(msgbuf,dos_to_unix(msgbuf,False)); } for (i=0;i unix user mapping @@ -797,8 +797,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int * Ensure the plaintext passwords are in UNIX format. */ if(!doencrypt) { - dos_to_unix(smb_apasswd,True); - dos_to_unix(smb_ntpasswd,True); + pstrcpy(smb_apasswd,dos_to_unix(smb_apasswd,False)); + pstrcpy(smb_ntpasswd,dos_to_unix(smb_ntpasswd,False)); } } else { @@ -808,7 +808,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* * Ensure the plaintext password is in UNIX format. */ - dos_to_unix(smb_apasswd,True); + pstrcpy(smb_apasswd,dos_to_unix(smb_apasswd,False)); /* trim the password */ smb_apasslen = strlen(smb_apasswd); -- cgit From 4ff011d88ef5b79b92d2cea1abe32c93bc03f724 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jun 2001 05:38:28 +0000 Subject: Added STR_NOALIGN flags to clistr and srvstr fns. Yes, NT actually does send unaligned unicode strings sometimes! Fixed our handling of the workgroup name tacked on the end of the NT1 negprot response (a unaligned unicode) fixed a couple of places where we should be using the message_end fns instead of pre-calculated buffer lengths (This used to be commit 86613493a9b2e56523153486931d0bf8d39beb7a) --- source3/smbd/negprot.c | 18 +++++++++--------- source3/smbd/srvstr.c | 38 +++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 83c809de1c..2c6575d643 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -177,6 +177,7 @@ static int reply_nt1(char *outbuf) struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; + char *p; if (lp_security() == SEC_SERVER) { cli = server_cryptkey(); @@ -215,18 +216,10 @@ static int reply_nt1(char *outbuf) if (lp_security() >= SEC_USER) secword |= 1; if (doencrypt) secword |= 2; - /* decide where (if) to put the encryption challenge, and - follow it with the OEM'd domain name - */ - data_len = crypt_len + strlen(global_myworkgroup) + 1; - - set_message(outbuf,17,data_len,True); - pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup); + set_message(outbuf,17,0,True); CVAL(outbuf,smb_vwv1) = secword; SSVALS(outbuf,smb_vwv16+1,crypt_len); - if (doencrypt) - memcpy(smb_buf(outbuf), cryptkey, 8); Protocol = PROTOCOL_NT1; @@ -240,6 +233,13 @@ static int reply_nt1(char *outbuf) SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */ + p = smb_buf(outbuf); + if (doencrypt) memcpy(p, cryptkey, 8); + p += 8; + p += srvstr_push(outbuf, p, global_myworkgroup, -1, + STR_UNICODE|STR_CONVERT|STR_TERMINATE|STR_NOALIGN); + set_message_end(outbuf, p); + return (smb_len(outbuf)+4); } diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 6ca34a2428..0651fb725b 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -23,7 +23,20 @@ #include "includes.h" -#define UNICODE_FLAG(buf) (SVAL(buf, smb_flg2) & FLAGS2_UNICODE_STRINGS) +#define UNICODE_FLAG(buf, flags) (!(flags & STR_ASCII) && \ + ((flags & STR_UNICODE || \ + (SVAL(buf, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) + +/**************************************************************************** +return an alignment of either 0 or 1 +if unicode is not negotiated then return 0 +otherwise return 1 if offset is off +****************************************************************************/ +static int srvstr_align(void *inbuf, int offset, int flags) +{ + if ((flags & STR_NOALIGN) || !UNICODE_FLAG(inbuf, flags)) return 0; + return offset & 1; +} /**************************************************************************** copy a string from a char* src to a unicode or ascii @@ -35,6 +48,8 @@ flags can have: STR_CONVERT means convert from unix to dos codepage STR_UPPER means uppercase in the destination STR_ASCII use ascii even with unicode servers + STR_UNICODE means to force as unicode + STR_NOALIGN means don't do alignment dest_len is the maximum length allowed in the destination. If dest_len is -1 then no maxiumum is used ****************************************************************************/ @@ -47,14 +62,14 @@ int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int fla dest_len = sizeof(pstring); } - if (!(flags & STR_ASCII) && srvstr_align(outbuf, PTR_DIFF(dest, outbuf))) { + if (srvstr_align(outbuf, PTR_DIFF(dest, outbuf), flags)) { *(char *)dest = 0; dest = (void *)((char *)dest + 1); dest_len--; len++; } - if ((flags & STR_ASCII) || !UNICODE_FLAG(outbuf)) { + if (!UNICODE_FLAG(outbuf, flags)) { /* the client doesn't want unicode */ safe_strcpy(dest, src, dest_len); len = strlen(dest); @@ -85,6 +100,7 @@ flags can have: STR_CONVERT means convert from dos to unix codepage STR_TERMINATE means the string in src is null terminated STR_UNICODE means to force as unicode + STR_NOALIGN means don't do alignment if STR_TERMINATE is set then src_len is ignored src_len is the length of the source area in bytes return the number of bytes occupied by the string in src @@ -97,12 +113,12 @@ int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_ dest_len = sizeof(pstring); } - if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { + if (srvstr_align(inbuf, PTR_DIFF(src, inbuf), flags)) { src = (void *)((char *)src + 1); if (src_len > 0) src_len--; } - if ((flags & STR_ASCII) || (!(flags & STR_UNICODE) && !UNICODE_FLAG(inbuf))) { + if (!UNICODE_FLAG(inbuf, flags)) { /* the server doesn't want unicode */ if (flags & STR_TERMINATE) { safe_strcpy(dest, src, dest_len); @@ -134,18 +150,6 @@ int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_ return len; } -/**************************************************************************** -return an alignment of either 0 or 1 -if unicode is not negotiated then return 0 -otherwise return 1 if offset is off -****************************************************************************/ -int srvstr_align(void *inbuf, int offset) -{ - if (!UNICODE_FLAG(inbuf)) return 0; - return offset & 1; -} - - /**************************************************************************** these are useful for replacing all those StrnCpy() ops for copying data to/from the wire -- cgit From 91b8a8d1d21b810b6aca44ce647837669efd6dcf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jun 2001 09:10:42 +0000 Subject: next_token() was supposed to be a reentrant replacement for strtok(), but the code suffered from bitrot and is not now reentrant. That means we can get bizarre behaviour i've fixed this by making next_token() reentrant and creating a next_token_nr() that is a small non-reentrant wrapper for those lumps of code (mostly smbclient) that have come to rely on the non-reentrant behaviour (This used to be commit 674ee2f1d12b0afc164a9e9072758fd1c5e54df7) --- source3/smbd/blocking.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index cebad5ce35..843f3d07a6 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -265,7 +265,7 @@ static BOOL process_lockread(blocking_lock_record *blr) char *outbuf = OutBuffer; char *inbuf = blr->inbuf; ssize_t nread = -1; - char *data; + char *data, *p; int outsize = 0; SMB_OFF_T startpos; size_t numtoread; @@ -309,12 +309,15 @@ static BOOL process_lockread(blocking_lock_record *blr) } construct_reply_common(inbuf, outbuf); - outsize = set_message(outbuf,5,3,True); + outsize = set_message(outbuf,5,0,True); outsize += nread; SSVAL(outbuf,smb_vwv0,nread); SSVAL(outbuf,smb_vwv5,nread+3); - SSVAL(smb_buf(outbuf),1,nread); + p = smb_buf(outbuf); + *p++ = 1; + SSVAL(p,0,nread); p += 2; + set_message_end(outbuf, p+nread); DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) ); -- cgit From 100a54e221dd0712ab37daa5359b202d0a059090 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Jun 2001 00:57:59 +0000 Subject: Andrew - please look this over. I've fixed a long standing (maybe 4-5 years old) bug when chainging a sessionsetup_and_X and tcon together. The wrong username was being entered into the tdb, even though the correct user was used for accessing files. This is related to the fact that authorise_login() is not used for sessionsetup, but only for tcon auths. Jeremy. (This used to be commit 0187cd6aef7586d7ad4bdc70c50f3f2e7c69519c) --- source3/smbd/password.c | 283 +++++++++++++++++++++++++----------------------- source3/smbd/reply.c | 18 ++- 2 files changed, 164 insertions(+), 137 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index d2059e7e20..6be2989881 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -765,171 +765,182 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) return(NULL); } - - /**************************************************************************** -check for authority to login to a service with a given username/password + Check for authority to login to a service with a given username/password. + Note this is *NOT* used when logging on using sessionsetup_and_X. ****************************************************************************/ + BOOL authorise_login(int snum,char *user,char *password, int pwlen, BOOL *guest,BOOL *force,uint16 vuid) { - BOOL ok = False; - user_struct *vuser = get_valid_user_struct(vuid); + BOOL ok = False; + user_struct *vuser = get_valid_user_struct(vuid); - if (lp_security() > SEC_SHARE && !vuser) { - DEBUG(1,("authorise_login: refusing user %s with no session setup\n", - user)); - return False; - } - - *guest = False; - #if DEBUG_PASSWORD - DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password)); + DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n", + user,password)); #endif - /* there are several possibilities: - 1) login as the given user with given password - 2) login as a previously registered username with the given password - 3) login as a session list username with the given password - 4) login as a previously validated user/password pair - 5) login as the "user =" user with given password - 6) login as the "user =" user with no password (guest connection) - 7) login as guest user with no password + *guest = False; + + if (GUEST_ONLY(snum)) + *force = True; - if the service is guest_only then steps 1 to 5 are skipped - */ + if (!GUEST_ONLY(snum) && (lp_security() > SEC_SHARE)) { - if (GUEST_ONLY(snum)) *force = True; + /* + * We should just use the given vuid from a sessionsetup_and_X. + */ - if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) - { - /* check the given username and password */ - if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL); - if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); - } + if (!vuser) { + DEBUG(1,("authorise_login: refusing user %s with no session setup\n", + user)); + return False; + } - /* check for a previously registered guest username */ - if (!ok && (vuser != 0) && vuser->guest) { - if (user_ok(vuser->user.unix_name,snum) && - password_ok(vuser->user.unix_name, password, pwlen, NULL)) { - fstrcpy(user, vuser->user.unix_name); - vuser->guest = False; - DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); - ok = True; + if (!vuser->guest && user_ok(vuser->user.unix_name,snum)) { + fstrcpy(user,vuser->user.unix_name); + *guest = False; + DEBUG(3,("authorise_login: ACCEPTED: validated uid ok as non-guest \ +(user=%s)\n", user)); + return True; + } } - } - + + /* there are several possibilities: + 1) login as the given user with given password + 2) login as a previously registered username with the given password + 3) login as a session list username with the given password + 4) login as a previously validated user/password pair + 5) login as the "user =" user with given password + 6) login as the "user =" user with no password (guest connection) + 7) login as guest user with no password + + if the service is guest_only then steps 1 to 5 are skipped + */ + + if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) { + /* check the given username and password */ + if (!ok && (*user) && user_ok(user,snum)) { + ok = password_ok(user,password, pwlen, NULL); + if (ok) + DEBUG(3,("authorise_login: ACCEPTED: given username (%s) password ok\n", + user )); + } - /* now check the list of session users */ - if (!ok) - { - char *auser; - char *user_list = strdup(session_users); - if (!user_list) return(False); + /* check for a previously registered guest username */ + if (!ok && (vuser != 0) && vuser->guest) { + if (user_ok(vuser->user.unix_name,snum) && + password_ok(vuser->user.unix_name, password, pwlen, NULL)) { + fstrcpy(user, vuser->user.unix_name); + vuser->guest = False; + DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user)); + ok = True; + } + } - for (auser=strtok(user_list,LIST_SEP); - !ok && auser; - auser = strtok(NULL,LIST_SEP)) - { - fstring user2; - fstrcpy(user2,auser); - if (!user_ok(user2,snum)) continue; + /* now check the list of session users */ + if (!ok) { + char *auser; + char *user_list = strdup(session_users); + if (!user_list) + return(False); + + for (auser=strtok(user_list,LIST_SEP); !ok && auser; + auser = strtok(NULL,LIST_SEP)) { + fstring user2; + fstrcpy(user2,auser); + if (!user_ok(user2,snum)) + continue; - if (password_ok(user2,password, pwlen, NULL)) { - ok = True; - fstrcpy(user,user2); - DEBUG(3,("ACCEPTED: session list username and given password ok\n")); - } - } - free(user_list); - } + if (password_ok(user2,password, pwlen, NULL)) { + ok = True; + fstrcpy(user,user2); + DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \ +and given password ok\n", user)); + } + } - /* check for a previously validated username/password pair */ - if (!ok && (lp_security() > SEC_SHARE) && - (vuser != 0) && !vuser->guest && - user_ok(vuser->user.unix_name,snum)) { - fstrcpy(user,vuser->user.unix_name); - *guest = False; - DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); - ok = True; - } + free(user_list); + } - /* check for a rhosts entry */ - if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) { - ok = True; - DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n")); - } + /* check for a previously validated username/password pair */ + if (!ok && (lp_security() > SEC_SHARE) && (vuser != 0) && !vuser->guest && + user_ok(vuser->user.unix_name,snum)) { + fstrcpy(user,vuser->user.unix_name); + *guest = False; + DEBUG(3,("authorise_login: ACCEPTED: validated uid (%s) as non-guest\n", + user)); + ok = True; + } - /* check the user= fields and the given password */ - if (!ok && lp_username(snum)) { - char *auser; - pstring user_list; - StrnCpy(user_list,lp_username(snum),sizeof(pstring)); + /* check for a rhosts entry */ + if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) { + ok = True; + DEBUG(3,("authorise_login: ACCEPTED: hosts equiv or rhosts entry for %s\n", + user)); + } - pstring_sub(user_list,"%S",lp_servicename(snum)); - - for (auser=strtok(user_list,LIST_SEP); - auser && !ok; - auser = strtok(NULL,LIST_SEP)) - { - if (*auser == '@') - { - auser = validate_group(auser+1,password,pwlen,snum); - if (auser) - { - ok = True; - fstrcpy(user,auser); - DEBUG(3,("ACCEPTED: group username and given password ok\n")); - } - } - else - { - fstring user2; - fstrcpy(user2,auser); - if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL)) - { - ok = True; - fstrcpy(user,user2); - DEBUG(3,("ACCEPTED: user list username and given password ok\n")); - } - } - } - } - } /* not guest only */ + /* check the user= fields and the given password */ + if (!ok && lp_username(snum)) { + char *auser; + pstring user_list; + StrnCpy(user_list,lp_username(snum),sizeof(pstring)); - /* check for a normal guest connection */ - if (!ok && GUEST_OK(snum)) - { - fstring guestname; - StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); - if (Get_Pwnam(guestname,True)) - { - fstrcpy(user,guestname); - ok = True; - DEBUG(3,("ACCEPTED: guest account and guest ok\n")); + pstring_sub(user_list,"%S",lp_servicename(snum)); + + for (auser=strtok(user_list,LIST_SEP); auser && !ok; + auser = strtok(NULL,LIST_SEP)) { + if (*auser == '@') { + auser = validate_group(auser+1,password,pwlen,snum); + if (auser) { + ok = True; + fstrcpy(user,auser); + DEBUG(3,("authorise_login: ACCEPTED: group username \ +and given password ok (%s)\n", user)); + } + } else { + fstring user2; + fstrcpy(user2,auser); + if (user_ok(user2,snum) && password_ok(user2,password,pwlen,NULL)) { + ok = True; + fstrcpy(user,user2); + DEBUG(3,("authorise_login: ACCEPTED: user list username \ +and given password ok (%s)\n", user)); + } + } + } + } + } /* not guest only */ + + /* check for a normal guest connection */ + if (!ok && GUEST_OK(snum)) { + fstring guestname; + StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); + if (Get_Pwnam(guestname,True)) { + fstrcpy(user,guestname); + ok = True; + DEBUG(3,("authorise_login: ACCEPTED: guest account and guest ok (%s)\n", + user)); + } else { + DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname)); + } + *guest = True; } - else - DEBUG(0,("Invalid guest account %s??\n",guestname)); - *guest = True; - } - if (ok && !user_ok(user,snum)) - { - DEBUG(0,("rejected invalid user %s\n",user)); - ok = False; - } + if (ok && !user_ok(user,snum)) { + DEBUG(0,("authorise_login: rejected invalid user %s\n",user)); + ok = False; + } - return(ok); + return(ok); } - /**************************************************************************** -read the a hosts.equiv or .rhosts file and check if it -allows this user from this machine + Read the a hosts.equiv or .rhosts file and check if it + allows this user from this machine. ****************************************************************************/ + static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) { int plus_allowed = 1; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e0b0cea2d3..cd7b3fe6fe 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -205,6 +205,14 @@ int reply_tcon(connection_struct *conn, pstrcpy(service, p+1); } + /* + * If the vuid is valid, we should be using that.... + */ + + if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) { + pstrcpy(user,validated_username(vuid)); + } + /* * Ensure the user and password names are in UNIX codepage format. */ @@ -247,6 +255,7 @@ int reply_tcon(connection_struct *conn, /**************************************************************************** Reply to a tcon and X. ****************************************************************************/ + int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { fstring service; @@ -298,6 +307,14 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt DEBUG(4,("Got device type %s\n",devicename)); + /* + * If the vuid is valid, we should be using that.... + */ + + if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) { + pstrcpy(user,validated_username(vuid)); + } + /* * Pass the user through the NT -> unix user mapping * function. @@ -1066,7 +1083,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int return chain_reply(inbuf,outbuf,length,bufsize); } - /**************************************************************************** reply to a chkpth ****************************************************************************/ -- cgit From 868d010aa1b614109b54928e46eb626a1d320a2d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Jun 2001 15:14:45 +0000 Subject: added the ability to test smbd safely as an ordinary user. The way it works is that libsmb/ creates a local tcp socket then launches smbd as a subprocess attached to that socket. smbd thinks it is being launched from inetd. to use it do the following: - compile with -DSMB_REGRESSION_TEST - run like this (also works with smbtorture etc) export SMBD_TEST=1 export LIBSMB_PROG=bin/smbd smbclient //server/share -Uuser%pass obviously you need to setup a smb.conf etc. Using --prefix to configure is useful. The aim of all this stuff is to add a decent set of regression tests to the build farm, so we know if smbd actually runs correctly on all the platforms, not just builds. We can run smbtorture, masktest, locktest etc, plus a bunch of smbclient scripts and any new tests we write. This doesn't help much with nmbd (at least not yet) but its a good start. (This used to be commit 7e8e6ae9a88c4d2587eb4e7f0501cd71bd36ebb2) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index fcee30d667..f4c82839bb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -626,10 +626,12 @@ static void usage(char *pname) * dump if euid != 0. Ensure this is the case. */ +#ifndef SMB_REGRESSION_TEST if(geteuid() != (uid_t)0) { fprintf(stderr, "%s: Version %s : Must have effective user id of zero to run.\n", argv[0], VERSION); exit(1); } +#endif append_log = True; -- cgit From 5ba566efb70c1047301f551e8da0fcd0d3030283 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Jun 2001 20:56:52 +0000 Subject: Fixed logic bug in timeout processing spotted by Ying Chen . Jeremy. (This used to be commit 08c168242364bf4d415f49d134e507a7e234611b) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 72e0fc311a..dae99ec80e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1254,7 +1254,7 @@ void smbd_process(void) if ((num_smbs % 200) == 0) { time_t new_check_time = time(NULL); - if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) { + if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ -- cgit From 7133aed083612480a94a7b61d6a0a0308c304b6e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Jun 2001 00:22:14 +0000 Subject: Better fix for client name vulnarability. Jeremy. (This used to be commit 17c3faa367328d186d10f59f08549de0c608b16a) --- source3/smbd/reply.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cd7b3fe6fe..0c40e5f2b3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -96,6 +96,7 @@ int reply_special(char *inbuf,char *outbuf) remote_machine[15] = 0; trim_string(remote_machine," "," "); strlower(remote_machine); + alpha_strcpy(remote_machine,remote_machine,sizeof(remote_machine)-1); fstrcpy(local_machine,name1); len = strlen(local_machine); @@ -105,6 +106,7 @@ int reply_special(char *inbuf,char *outbuf) } trim_string(local_machine," "," "); strlower(local_machine); + alpha_strcpy(local_machine,local_machine,sizeof(local_machine)-1); if (name_type == 'R') { /* We are being asked for a pathworks session --- -- cgit From 37eb0d6c74ce158b1cc268cea446b33789550048 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Jun 2001 07:22:16 +0000 Subject: Added other_safe_chars to alpha_strcpy(). Needs testing but is a better fix for the problem. Jeremy. (This used to be commit e059fffd03a1382fb2b7059b6de369d9fc765a17) --- source3/smbd/message.c | 4 ++-- source3/smbd/reply.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index a023650c74..bae9f6c906 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -86,8 +86,8 @@ static void msg_deliver(void) pstring s; pstrcpy(s,lp_msg_command()); - pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,sizeof(alpha_msgfrom))); - pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,sizeof(alpha_msgto))); + pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); + pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); standard_sub_basic(s); pstring_sub(s,"%s",name); smbrun(s,NULL); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0c40e5f2b3..da4659dfa1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -96,7 +96,7 @@ int reply_special(char *inbuf,char *outbuf) remote_machine[15] = 0; trim_string(remote_machine," "," "); strlower(remote_machine); - alpha_strcpy(remote_machine,remote_machine,sizeof(remote_machine)-1); + alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); fstrcpy(local_machine,name1); len = strlen(local_machine); @@ -106,7 +106,7 @@ int reply_special(char *inbuf,char *outbuf) } trim_string(local_machine," "," "); strlower(local_machine); - alpha_strcpy(local_machine,local_machine,sizeof(local_machine)-1); + alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); if (name_type == 'R') { /* We are being asked for a pathworks session --- -- cgit From 08bda36755d75bc4f9a7e0354a93085b4f9ace66 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Jun 2001 20:01:23 +0000 Subject: Log debug before and after netbios names copied so we know if they've been changed. Jeremy. (This used to be commit f8c121c69c9561f011a0e08a9d0beaf1cefd1667) --- source3/smbd/reply.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index da4659dfa1..1b15639720 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -108,6 +108,9 @@ int reply_special(char *inbuf,char *outbuf) strlower(local_machine); alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); + DEBUG(2,("netbios connect: local=%s remote=%s\n", + local_machine, remote_machine )); + if (name_type == 'R') { /* We are being asked for a pathworks session --- no thanks! */ -- cgit From 8b79a473faf2ff25acb220500158920490c71576 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Jun 2001 00:46:34 +0000 Subject: - make the regresison test mode code build in by default. This should allow us to have test targets without special configure options - fixed make proto so that it actually does something (This used to be commit 55109a752578e9389d853cb27ec17c2114ecff77) --- source3/smbd/server.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f4c82839bb..17b7774b1d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -621,17 +621,7 @@ static void usage(char *pname) setluid(0); #endif - /* - * gain_root_privilege uses an assert than will cause a core - * dump if euid != 0. Ensure this is the case. - */ - -#ifndef SMB_REGRESSION_TEST - if(geteuid() != (uid_t)0) { - fprintf(stderr, "%s: Version %s : Must have effective user id of zero to run.\n", argv[0], VERSION); - exit(1); - } -#endif + sec_init(); append_log = True; -- cgit From b95a294a0879e800e816281a80d0074224cd8cd4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Jun 2001 02:53:13 +0000 Subject: fixed usage of socklen_t and also tidied up SIG_ATOMIC_T, using a typedef instead of a define (This used to be commit e2ecff419fdc0a0dc7551b33b377dc11061ef2a3) --- source3/smbd/notify_kernel.c | 12 ++++++------ source3/smbd/oplock.c | 2 +- source3/smbd/oplock_linux.c | 10 +++++----- source3/smbd/process.c | 2 +- source3/smbd/server.c | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index ef4e47acf1..d7408c06b5 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -24,9 +24,9 @@ #if HAVE_KERNEL_CHANGE_NOTIFY extern int DEBUGLEVEL; -static VOLATILE SIG_ATOMIC_T fd_pending; -static VOLATILE SIG_ATOMIC_T signals_received; -static VOLATILE SIG_ATOMIC_T signals_processed; +static VOLATILE sig_atomic_t fd_pending; +static VOLATILE sig_atomic_t signals_received; +static VOLATILE sig_atomic_t signals_processed; #ifndef DN_ACCESS #define DN_ACCESS 0x00000001 /* File accessed in directory */ @@ -65,7 +65,7 @@ the signal handler for change notify static void signal_handler(int sig, siginfo_t *info, void *unused) { BlockSignals(True, sig); - fd_pending = (SIG_ATOMIC_T)info->si_fd; + fd_pending = (sig_atomic_t)info->si_fd; signals_received++; sys_select_signal(); } @@ -89,7 +89,7 @@ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path DEBUG(3,("kernel change notify on %s fd=%d\n", path, (int)fd_pending)); close((int)fd_pending); - fd_pending = (SIG_ATOMIC_T)-1; + fd_pending = (sig_atomic_t)-1; data->directory_handle = -1; signals_processed++; BlockSignals(False, RT_SIGNAL_NOTIFY); @@ -105,7 +105,7 @@ static void kernel_remove_notify(void *datap) int fd = data->directory_handle; if (fd != -1) { if (fd == (int)fd_pending) { - fd_pending = (SIG_ATOMIC_T)-1; + fd_pending = (sig_atomic_t)-1; signals_processed++; BlockSignals(False, RT_SIGNAL_NOTIFY); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 4482c0221c..cc2581375e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1195,7 +1195,7 @@ setup oplocks for this process BOOL init_oplocks(void) { struct sockaddr_in sock_name; - int len = sizeof(sock_name); + socklen_t len = sizeof(sock_name); DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 9edeb1b513..39ee3eb86b 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -25,9 +25,9 @@ extern int DEBUGLEVEL; -static VOLATILE SIG_ATOMIC_T signals_received; -static VOLATILE SIG_ATOMIC_T signals_processed; -static VOLATILE SIG_ATOMIC_T fd_pending; /* the fd of the current pending signal */ +static VOLATILE sig_atomic_t signals_received; +static VOLATILE sig_atomic_t signals_processed; +static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal */ #ifndef F_SETLEASE #define F_SETLEASE 1024 @@ -55,7 +55,7 @@ handle a LEASE signal, incrementing the signals_received and blocking the signal static void signal_handler(int sig, siginfo_t *info, void *unused) { BlockSignals(True, sig); - fd_pending = (SIG_ATOMIC_T)info->si_fd; + fd_pending = (sig_atomic_t)info->si_fd; signals_received++; sys_select_signal(); } @@ -160,7 +160,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); out: /* now we can receive more signals */ - fd_pending = (SIG_ATOMIC_T)-1; + fd_pending = (sig_atomic_t)-1; signals_processed++; BlockSignals(False, RT_SIGNAL_LEASE); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dae99ec80e..f43c675289 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -48,7 +48,7 @@ extern char *last_inbuf; extern char *InBuffer; extern char *OutBuffer; extern int smb_read_error; -extern VOLATILE SIG_ATOMIC_T reload_after_sighup; +extern VOLATILE sig_atomic_t reload_after_sighup; extern BOOL global_machine_password_needs_changing; extern fstring global_myworkgroup; extern pstring global_myname; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 17b7774b1d..1dcf861a17 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -208,7 +208,7 @@ max can be %d\n", num = sys_select(FD_SETSIZE,&lfds,NULL); if (num == -1 && errno == EINTR) { - extern VOLATILE SIG_ATOMIC_T reload_after_sighup; + extern VOLATILE sig_atomic_t reload_after_sighup; /* check for sighup processing */ if (reload_after_sighup) { @@ -228,7 +228,7 @@ max can be %d\n", accept on these. */ for( ; num > 0; num--) { struct sockaddr addr; - int in_addrlen = sizeof(addr); + socklen_t in_addrlen = sizeof(addr); s = -1; for(i = 0; i < num_interfaces; i++) { @@ -366,7 +366,7 @@ BOOL reload_services(BOOL test) Catch a sighup. ****************************************************************************/ -VOLATILE SIG_ATOMIC_T reload_after_sighup = False; +VOLATILE sig_atomic_t reload_after_sighup = False; static void sig_hup(int sig) { -- cgit From 31ab8ae3ffd5ac3f7af5f5d7157f568c0e6d199f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Jun 2001 19:08:30 +0000 Subject: Fixed stupid typo that would stop trusted domains working. Jeremy. (This used to be commit fa721b4adfbcac4827251b02f6af7f0b5211c104) --- source3/smbd/password.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6be2989881..0c720b6a29 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1272,8 +1272,7 @@ use this machine as the password server.\n")); ************************************************************************/ static BOOL connect_to_domain_password_server(struct cli_state *pcli, - char *server, - unsigned char *trust_passwd) + char *server, unsigned char *trust_passwd) { struct in_addr dest_ip; fstring remote_machine; @@ -1573,9 +1572,9 @@ BOOL domain_client_validate( char *user, char *domain, /* * Get the machine account password for our primary domain */ - if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time)) + if (!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd, &last_change_time)) { - DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", domain)); + DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", global_myworkgroup)); return False; } -- cgit From 90498a10c79edabf629c98403363b8e0b934e047 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 26 Jun 2001 03:45:45 +0000 Subject: Remove warning about trapdoor systems for non-root mode. Andrew Bartlett (This used to be commit b33000cdc0cafd4888c3f07c56050626743abd14) --- source3/smbd/sec_ctx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 6f98e9df6b..9ca63a0f95 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -109,6 +109,10 @@ static BOOL become_id(uid_t uid, gid_t gid) static void gain_root(void) { + if (non_root_mode()) { + return; + } + if (geteuid() != 0) { set_effective_uid(0); -- cgit From 629a59fe85910229ddac8f02c20ead424ba03ac7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Jun 2001 06:06:42 +0000 Subject: Always use DOMAIN\user first that this is the more specific case. Jeremy. (This used to be commit 52143c08536a5f5d888b78b4769c06f7a0a2992b) --- source3/smbd/reply.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1b15639720..811a7558dc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -906,18 +906,23 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstrcpy( orig_user, user); - /* if the username exists as a domain/username pair on the unix system then use - that */ - if (!sys_getpwnam(user)) { - pstring user2; - - slprintf(user2,sizeof(user2)-1,"%s%s%s", dos_to_unix(domain,False), - lp_winbind_separator(), user); - - if (sys_getpwnam(user2)) { - DEBUG(3,("Using unix username %s\n", user2)); - pstrcpy(user, user2); - } + /* + * Always try the "DOMAIN\user" lookup first, as this is the most + * specific case. If this fails then try the simple "user" lookup. + */ + + { + pstring dom_user; + + /* Work out who's who */ + + slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s", + dos_to_unix(domain, False), lp_winbind_separator(), user); + + if (sys_getpwnam(dom_user) != NULL) { + pstrcpy(user, dom_user); + DEBUG(3,("Using unix username %s\n", dom_user)); + } } /* -- cgit From f83f2cd4fa3a610a92b17ac8006390cdd1f7ca94 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 29 Jun 2001 01:58:48 +0000 Subject: Win9x weirdness. When setting the named pipe handle state on a Unicode server, Win9x only sends \PIPE instead of \PIPE\. Looks suspiciously like an off-by one bug in the Win9x dce/rpc pipe code. (This used to be commit b4a9079833c261705e18fdcaab752cb5292a078f) --- source3/smbd/ipc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index efad2d27c0..eb6ccb4fce 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -492,10 +492,18 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int (name[strlen(local_machine)+1] == '\\')) name_offset = strlen(local_machine)+1; - if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) { + if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) { + name_offset += strlen("\\PIPE"); + + /* Win9x weirdness. When talking to a unicode server Win9x + only sends \PIPE instead of \PIPE\ */ + + if (name[name_offset] == '\\') + name_offset++; + DEBUG(5,("calling named_pipe\n")); outsize = named_pipe(conn,vuid,outbuf, - name+name_offset+strlen("\\PIPE\\"),setup,data,params, + name+name_offset,setup,data,params, suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); } else { DEBUG(3,("invalid pipe name\n")); -- cgit From e2ced932dbd34384f1e3752cc073b2fb66467b46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 29 Jun 2001 22:32:24 +0000 Subject: Ensured all the system calls in msdfs.c go through the vfs layer. Added vfs calls to symlink() and readlink() with appropriate configure checks. Jeremy. (This used to be commit c24e6b41ea60ab4bac2fcd19da947851d6df3c7c) --- source3/smbd/service.c | 26 +----- source3/smbd/vfs-wrap.c | 32 ++++++++ source3/smbd/vfs.c | 213 +++++++++++++++++++++++++----------------------- 3 files changed, 145 insertions(+), 126 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 61da72b2e9..0e2c0ff7a1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -524,28 +524,10 @@ connection_struct *make_connection(char *service,char *user,char *password, int } /* Initialise VFS function pointers */ - if (*lp_vfsobj(SNUM(conn))) { - -#ifdef HAVE_LIBDL - - /* Loadable object file */ - - if (!vfs_init_custom(conn)) { - DEBUG(0, ("vfs_init failed\n")); - conn_free(conn); - return NULL; - } -#else - DEBUG(0, ("No libdl present - cannot use VFS objects\n")); - conn_free(conn); - return NULL; -#endif - - } else { - - /* Normal share - initialise with disk access functions */ - - vfs_init_default(conn); + if (!vfs_init(conn)) { + DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); + conn_free(conn); + return NULL; } /* execute any "root preexec = " line */ diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index da8484e14e..a0b4966c59 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -558,6 +558,38 @@ BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T return result; } +int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath) +{ + int result; + + START_PROFILE(syscall_symlink); + +#ifdef VFS_CHECK_NULL + if ((oldpath == NULL) || (newpath == NULL)) + smb_panic("NULL pointer passed to vfswrap_symlink()\n"); +#endif + + result = sys_symlink(oldpath, newpath); + END_PROFILE(syscall_symlink); + return result; +} + +int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz) +{ + int result; + + START_PROFILE(syscall_readlink); + +#ifdef VFS_CHECK_NULL + if ((path == NULL) || (buf == NULL)) + smb_panic("NULL pointer passed to vfswrap_readlink()\n"); +#endif + + result = sys_readlink(path, buf, bufsiz); + END_PROFILE(syscall_readlink); + return result; +} + size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) { return get_nt_acl(fsp, ppdesc); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 713d58cdc8..ac00d00e9e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -72,6 +72,9 @@ struct vfs_ops default_vfs_ops = { vfswrap_utime, vfswrap_ftruncate, vfswrap_lock, + vfswrap_symlink, + vfswrap_readlink, + vfswrap_fget_nt_acl, vfswrap_get_nt_acl, vfswrap_fset_nt_acl, @@ -89,7 +92,8 @@ struct vfs_ops default_vfs_ops = { /**************************************************************************** initialise default vfs hooks ****************************************************************************/ -int vfs_init_default(connection_struct *conn) + +static BOOL vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); @@ -102,7 +106,7 @@ int vfs_init_default(connection_struct *conn) ****************************************************************************/ #ifdef HAVE_LIBDL -BOOL vfs_init_custom(connection_struct *conn) +static BOOL vfs_init_custom(connection_struct *conn) { int vfs_version = -1; struct vfs_ops *ops, *(*init_fptr)(int *); @@ -146,145 +150,146 @@ BOOL vfs_init_custom(connection_struct *conn) memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); - if (conn->vfs_ops.connect == NULL) { - conn->vfs_ops.connect = default_vfs_ops.connect; - } + if (conn->vfs_ops.connect == NULL) + conn->vfs_ops.connect = default_vfs_ops.connect; - if (conn->vfs_ops.disconnect == NULL) { - conn->vfs_ops.disconnect = default_vfs_ops.disconnect; - } + if (conn->vfs_ops.disconnect == NULL) + conn->vfs_ops.disconnect = default_vfs_ops.disconnect; - if (conn->vfs_ops.disk_free == NULL) { - conn->vfs_ops.disk_free = default_vfs_ops.disk_free; - } + if (conn->vfs_ops.disk_free == NULL) + conn->vfs_ops.disk_free = default_vfs_ops.disk_free; - if (conn->vfs_ops.opendir == NULL) { - conn->vfs_ops.opendir = default_vfs_ops.opendir; - } + if (conn->vfs_ops.opendir == NULL) + conn->vfs_ops.opendir = default_vfs_ops.opendir; - if (conn->vfs_ops.readdir == NULL) { - conn->vfs_ops.readdir = default_vfs_ops.readdir; - } + if (conn->vfs_ops.readdir == NULL) + conn->vfs_ops.readdir = default_vfs_ops.readdir; - if (conn->vfs_ops.mkdir == NULL) { - conn->vfs_ops.mkdir = default_vfs_ops.mkdir; - } + if (conn->vfs_ops.mkdir == NULL) + conn->vfs_ops.mkdir = default_vfs_ops.mkdir; - if (conn->vfs_ops.rmdir == NULL) { - conn->vfs_ops.rmdir = default_vfs_ops.rmdir; - } + if (conn->vfs_ops.rmdir == NULL) + conn->vfs_ops.rmdir = default_vfs_ops.rmdir; - if (conn->vfs_ops.closedir == NULL) { - conn->vfs_ops.closedir = default_vfs_ops.closedir; - } + if (conn->vfs_ops.closedir == NULL) + conn->vfs_ops.closedir = default_vfs_ops.closedir; - if (conn->vfs_ops.open == NULL) { - conn->vfs_ops.open = default_vfs_ops.open; - } + if (conn->vfs_ops.open == NULL) + conn->vfs_ops.open = default_vfs_ops.open; - if (conn->vfs_ops.close == NULL) { - conn->vfs_ops.close = default_vfs_ops.close; - } + if (conn->vfs_ops.close == NULL) + conn->vfs_ops.close = default_vfs_ops.close; - if (conn->vfs_ops.read == NULL) { - conn->vfs_ops.read = default_vfs_ops.read; - } + if (conn->vfs_ops.read == NULL) + conn->vfs_ops.read = default_vfs_ops.read; - if (conn->vfs_ops.write == NULL) { - conn->vfs_ops.write = default_vfs_ops.write; - } + if (conn->vfs_ops.write == NULL) + conn->vfs_ops.write = default_vfs_ops.write; - if (conn->vfs_ops.lseek == NULL) { - conn->vfs_ops.lseek = default_vfs_ops.lseek; - } + if (conn->vfs_ops.lseek == NULL) + conn->vfs_ops.lseek = default_vfs_ops.lseek; - if (conn->vfs_ops.rename == NULL) { - conn->vfs_ops.rename = default_vfs_ops.rename; - } + if (conn->vfs_ops.rename == NULL) + conn->vfs_ops.rename = default_vfs_ops.rename; - if (conn->vfs_ops.fsync == NULL) { - conn->vfs_ops.fsync = default_vfs_ops.fsync; - } + if (conn->vfs_ops.fsync == NULL) + conn->vfs_ops.fsync = default_vfs_ops.fsync; - if (conn->vfs_ops.stat == NULL) { - conn->vfs_ops.stat = default_vfs_ops.stat; - } + if (conn->vfs_ops.stat == NULL) + conn->vfs_ops.stat = default_vfs_ops.stat; - if (conn->vfs_ops.fstat == NULL) { - conn->vfs_ops.fstat = default_vfs_ops.fstat; - } + if (conn->vfs_ops.fstat == NULL) + conn->vfs_ops.fstat = default_vfs_ops.fstat; - if (conn->vfs_ops.lstat == NULL) { - conn->vfs_ops.lstat = default_vfs_ops.lstat; - } + if (conn->vfs_ops.lstat == NULL) + conn->vfs_ops.lstat = default_vfs_ops.lstat; - if (conn->vfs_ops.unlink == NULL) { - conn->vfs_ops.unlink = default_vfs_ops.unlink; - } + if (conn->vfs_ops.unlink == NULL) + conn->vfs_ops.unlink = default_vfs_ops.unlink; - if (conn->vfs_ops.chmod == NULL) { - conn->vfs_ops.chmod = default_vfs_ops.chmod; - } + if (conn->vfs_ops.chmod == NULL) + conn->vfs_ops.chmod = default_vfs_ops.chmod; - if (conn->vfs_ops.fchmod == NULL) { - conn->vfs_ops.fchmod = default_vfs_ops.fchmod; - } + if (conn->vfs_ops.fchmod == NULL) + conn->vfs_ops.fchmod = default_vfs_ops.fchmod; - if (conn->vfs_ops.chown == NULL) { - conn->vfs_ops.chown = default_vfs_ops.chown; - } + if (conn->vfs_ops.chown == NULL) + conn->vfs_ops.chown = default_vfs_ops.chown; - if (conn->vfs_ops.fchown == NULL) { - conn->vfs_ops.fchown = default_vfs_ops.fchown; - } + if (conn->vfs_ops.fchown == NULL) + conn->vfs_ops.fchown = default_vfs_ops.fchown; - if (conn->vfs_ops.chdir == NULL) { - conn->vfs_ops.chdir = default_vfs_ops.chdir; - } + if (conn->vfs_ops.chdir == NULL) + conn->vfs_ops.chdir = default_vfs_ops.chdir; - if (conn->vfs_ops.getwd == NULL) { - conn->vfs_ops.getwd = default_vfs_ops.getwd; - } + if (conn->vfs_ops.getwd == NULL) + conn->vfs_ops.getwd = default_vfs_ops.getwd; - if (conn->vfs_ops.utime == NULL) { - conn->vfs_ops.utime = default_vfs_ops.utime; - } + if (conn->vfs_ops.utime == NULL) + conn->vfs_ops.utime = default_vfs_ops.utime; - if (conn->vfs_ops.ftruncate == NULL) { - conn->vfs_ops.ftruncate = default_vfs_ops.ftruncate; - } + if (conn->vfs_ops.ftruncate == NULL) + conn->vfs_ops.ftruncate = default_vfs_ops.ftruncate; - if (conn->vfs_ops.lock == NULL) { - conn->vfs_ops.lock = default_vfs_ops.lock; - } + if (conn->vfs_ops.lock == NULL) + conn->vfs_ops.lock = default_vfs_ops.lock; - if (conn->vfs_ops.fget_nt_acl == NULL) { - conn->vfs_ops.fget_nt_acl = default_vfs_ops.fget_nt_acl; - } + if (conn->vfs_ops.symlink == NULL) + conn->vfs_ops.symlink = default_vfs_ops.symlink; - if (conn->vfs_ops.get_nt_acl == NULL) { - conn->vfs_ops.get_nt_acl = default_vfs_ops.get_nt_acl; - } + if (conn->vfs_ops.readlink == NULL) + conn->vfs_ops.readlink = default_vfs_ops.readlink; - if (conn->vfs_ops.fset_nt_acl == NULL) { - conn->vfs_ops.fset_nt_acl = default_vfs_ops.fset_nt_acl; - } + if (conn->vfs_ops.fget_nt_acl == NULL) + conn->vfs_ops.fget_nt_acl = default_vfs_ops.fget_nt_acl; - if (conn->vfs_ops.set_nt_acl == NULL) { - conn->vfs_ops.set_nt_acl = default_vfs_ops.set_nt_acl; - } + if (conn->vfs_ops.get_nt_acl == NULL) + conn->vfs_ops.get_nt_acl = default_vfs_ops.get_nt_acl; - if (conn->vfs_ops.chmod_acl == NULL) { - conn->vfs_ops.chmod_acl = default_vfs_ops.chmod_acl; - } + if (conn->vfs_ops.fset_nt_acl == NULL) + conn->vfs_ops.fset_nt_acl = default_vfs_ops.fset_nt_acl; + + if (conn->vfs_ops.set_nt_acl == NULL) + conn->vfs_ops.set_nt_acl = default_vfs_ops.set_nt_acl; + + if (conn->vfs_ops.chmod_acl == NULL) + conn->vfs_ops.chmod_acl = default_vfs_ops.chmod_acl; + + if (conn->vfs_ops.fchmod_acl == NULL) + conn->vfs_ops.fchmod_acl = default_vfs_ops.fchmod_acl; - if (conn->vfs_ops.fchmod_acl == NULL) { - conn->vfs_ops.fchmod_acl = default_vfs_ops.fchmod_acl; - } return True; } #endif +/***************************************************************** + Generic VFS init. +******************************************************************/ + +BOOL vfs_init(connection_struct *conn) +{ + if (*lp_vfsobj(SNUM(conn))) { +#ifdef HAVE_LIBDL + + /* Loadable object file */ + + if (!vfs_init_custom(conn)) { + DEBUG(0, ("vfs_init: vfs_init_custom failed\n")); + return False; + } + + return True; +#else + DEBUG(0, ("vfs_init: No libdl present - cannot use VFS objects\n")); + return False; +#endif + } + + /* Normal share - initialise with disk access functions */ + + return vfs_init_default(conn); +} + /******************************************************************* Check if directory exists. ********************************************************************/ -- cgit From d1f38ac53107d818b88cae9ee4d4442381dc4702 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 30 Jun 2001 01:59:48 +0000 Subject: Fixed the first locking error (test #8 found by locktest code from Clarion locktest. Jeremy. (This used to be commit 5c42845b5bb6fafd0ebf93fbdd23d9bf861da865) --- source3/smbd/open.c | 2 +- source3/smbd/reply.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a88dfd5573..8bfddd4c71 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -238,7 +238,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * { SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; - if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK)){ + if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK,True)){ errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 811a7558dc..b66149e7da 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2193,7 +2193,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s maxcount = MIN(65535,maxcount); maxcount = MAX(mincount,maxcount); - if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) + if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { SMB_OFF_T size = fsp->size; SMB_OFF_T sizeneeded = startpos + maxcount; @@ -2350,7 +2350,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { END_PROFILE(SMBread); return(ERROR(ERRDOS,ERRlock)); } @@ -2427,7 +2427,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { END_PROFILE(SMBreadX); return(ERROR(ERRDOS,ERRlock)); } @@ -2488,7 +2488,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CVAL(inbuf,smb_com) = SMBwritec; CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwritebraw); return(ERROR(ERRDOS,ERRlock)); } @@ -2584,7 +2584,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwriteunlock); return(ERROR(ERRDOS,ERRlock)); } @@ -2648,7 +2648,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwrite); return(ERROR(ERRDOS,ERRlock)); } @@ -2746,7 +2746,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwriteX); return(ERROR(ERRDOS,ERRlock)); } @@ -3031,7 +3031,7 @@ int reply_writeclose(connection_struct *conn, mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwriteclose); return(ERROR(ERRDOS,ERRlock)); } @@ -4556,7 +4556,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { END_PROFILE(SMBreadBmpx); return(ERROR(ERRDOS,ERRlock)); } @@ -4623,7 +4623,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ CVAL(outbuf,smb_com) = SMBwritec; - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) { END_PROFILE(SMBwriteBmpx); return(ERROR(ERRDOS,ERRlock)); } -- cgit From 247acd5521f28a4f932105c9c76699c62f3f95f9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 1 Jul 2001 10:39:37 +0000 Subject: - fix bug in reply_nt- fix bug in reply_nt1 (This used to be commit 200110a3b4caeb0d8be87f02476af29165e35ada) --- source3/smbd/negprot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 2c6575d643..11400af710 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -173,11 +173,10 @@ static int reply_nt1(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); - int data_len; struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; - char *p; + char *p, *q; if (lp_security() == SEC_SERVER) { cli = server_cryptkey(); @@ -231,13 +230,14 @@ static int reply_nt1(char *outbuf) SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ put_long_date(outbuf+smb_vwv11+1,t); SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); - SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */ - p = smb_buf(outbuf); + p = q = smb_buf(outbuf); if (doencrypt) memcpy(p, cryptkey, 8); p += 8; p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_UNICODE|STR_CONVERT|STR_TERMINATE|STR_NOALIGN); + + SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */ set_message_end(outbuf, p); return (smb_len(outbuf)+4); -- cgit From 5b69009b25886bfa8b07e3ac885064ffa730f9bf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Jul 2001 02:42:41 +0000 Subject: Fixed the nastiest locking bug to track down.... smb_pids are sent in the lockingX calls - use that instead of smb_pid in the packet. Jeremy. (This used to be commit a3925cb9c6303ce24e5fecad6c8f3a0ba78b9ee0) --- source3/smbd/blocking.c | 12 ++++++++---- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 38 +++++++++++++++++++++++++++----------- 3 files changed, 36 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 843f3d07a6..48d3c8a24a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -196,6 +196,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; + uint16 lock_pid; unsigned char locktype = CVAL(inbuf,smb_vwv3); BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; @@ -219,6 +220,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec uint32 dummy2; BOOL err; + lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); @@ -227,7 +229,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec * request would never have been queued. JRA. */ - do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); + do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2); } generic_blocking_lock_error(blr, eclass, ecode); @@ -280,7 +282,7 @@ static BOOL process_lockread(blocking_lock_record *blr) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, READ_LOCK, &eclass, &ecode)) { + if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, READ_LOCK, &eclass, &ecode)) { if((errno != EACCES) && (errno != EAGAIN)) { /* * We have other than a "can't get lock" POSIX @@ -346,7 +348,7 @@ static BOOL process_lock(blocking_lock_record *blr) offset = IVAL(inbuf,smb_vwv3); errno = 0; - if (!do_lock(fsp, conn, (SMB_BIG_UINT)count, (SMB_BIG_UINT)offset, WRITE_LOCK, &eclass, &ecode)) { + if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, (SMB_BIG_UINT)offset, WRITE_LOCK, &eclass, &ecode)) { if((errno != EACCES) && (errno != EAGAIN)) { /* @@ -395,6 +397,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; + uint16 lock_pid; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; int eclass=0; @@ -410,6 +413,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) for(; blr->lock_num < num_locks; blr->lock_num++) { BOOL err; + lock_pid = get_lock_pid( data, blr->lock_num, large_file_format); count = get_lock_count( data, blr->lock_num, large_file_format); offset = get_lock_offset( data, blr->lock_num, large_file_format, &err); @@ -418,7 +422,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), + if(!do_lock(fsp,conn,count,lock_pid,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &eclass, &ecode)) break; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f43c675289..dd2318b58a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -612,7 +612,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { static pid_t pid= (pid_t)-1; int outsize = 0; - extern int global_smbpid; + extern uint16 global_smbpid; type &= 0xff; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b66149e7da..2539537bfc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2290,7 +2290,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * for a write lock. JRA. */ - if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) { + if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up @@ -2605,7 +2605,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) { + if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) { END_PROFILE(SMBwriteunlock); return(ERROR(eclass,ecode)); } @@ -3089,7 +3089,7 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fd, fsp->fnum, (double)offset, (double)count)); - if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) { + if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) { if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up @@ -3128,7 +3128,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, in count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); - if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) { + if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) { END_PROFILE(SMBunlock); return (ERROR(eclass,ecode)); } @@ -4247,6 +4247,18 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } +/**************************************************************************** + Get a lock pid, dealing with large count requests. +****************************************************************************/ + +uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format) +{ + if(!large_file_format) + return SVAL(data,SMB_LPID_OFFSET(data_offset)); + else + return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset)); +} + /**************************************************************************** Get a lock count, dealing with large count requests. ****************************************************************************/ @@ -4346,6 +4358,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = 0, offset = 0; + uint16 lock_pid; int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; @@ -4418,6 +4431,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { + lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); @@ -4429,10 +4443,10 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR(ERRDOS,ERRnoaccess); } - DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", - (double)offset, (double)count, fsp->fsp_name )); + DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n", + (unsigned int)lock_pid, (double)offset, (double)count, fsp->fsp_name )); - if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode)) { + if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) { END_PROFILE(SMBlockingX); return ERROR(eclass,ecode); } @@ -4448,6 +4462,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); of smb_lkrng structs */ for(i = 0; i < (int)num_locks; i++) { + lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); @@ -4459,10 +4474,10 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR(ERRDOS,ERRnoaccess); } - DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", - (double)offset, (double)count, fsp->fsp_name )); + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n", + (unsigned int)lock_pid, (double)offset, (double)count, fsp->fsp_name )); - if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), + if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &eclass, &ecode)) { if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { /* @@ -4488,6 +4503,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); * will delete it (and we shouldn't) ..... */ for(i--; i >= 0; i--) { + lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); @@ -4499,7 +4515,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR(ERRDOS,ERRnoaccess); } - do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); + do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2); } END_PROFILE(SMBlockingX); return ERROR(eclass,ecode); -- cgit From 56b2a0c1140e27eef879de0bb7deb570652d8334 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Mon, 2 Jul 2001 16:25:00 +0000 Subject: Very minor cleanup. I was looking for another problem and found some bits of code that were unclear. Chris -)----- (This used to be commit c2977be3408645499915d728538ba2c65b97614f) --- source3/smbd/mangle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 1cc602dc05..61af1f7ded 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -113,7 +113,7 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ char magic_char = '~'; static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; -#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) +#define MANGLE_BASE ( (sizeof(basechars)/sizeof(char)) - 1 ) static unsigned char chartest[256] = { 0 }; static BOOL ct_initialized = False; @@ -124,7 +124,7 @@ static BOOL ct_initialized = False; #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) #define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) -static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } }; +static ubi_cacheRoot mangled_cache[1] = {{ { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 }}; static BOOL mc_initialized = False; #define MANGLED_CACHE_MAX_ENTRIES 0 #define MANGLED_CACHE_MAX_MEMORY 16384 -- cgit From 0eb28dc851cf4c970dab01a3ef6da15bad3b4fa2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Jul 2001 17:40:43 +0000 Subject: Fixed incorrect debug parameters for lock_pid. Jeremy. (This used to be commit 310d2af6b0797cbd4f776b5c6c5b90a5d86b1aa9) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2539537bfc..d27f7842eb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4444,7 +4444,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); } DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n", - (unsigned int)lock_pid, (double)offset, (double)count, fsp->fsp_name )); + (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) { END_PROFILE(SMBlockingX); @@ -4475,7 +4475,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); } DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n", - (unsigned int)lock_pid, (double)offset, (double)count, fsp->fsp_name )); + (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &eclass, &ecode)) { -- cgit From b96c379dae07988fd2582cd2f055069cf55e9510 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Jul 2001 21:32:23 +0000 Subject: Remove the exit_server() calls that stop nmbd linking. Jeremy. (This used to be commit 110061ff5a0de7a5d7c5ee003d85d4d600c2531c) --- source3/smbd/ssl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index 67a8afc82e..dff5f34d5d 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -256,12 +256,14 @@ char *reqHosts, *resignHosts; DEBUG( 0, ( "Client %s did not use session setup; access denied\n", client_addr() ) ); if (!send_smb(fd, (char *)buf)) - exit_server("sslutil_negotiate_ssl: send_smb failed.\n"); + DEBUG(0, ("sslutil_negotiate_ssl: send_smb failed.\n")); return -1; } buf[4] = 0x8e; /* negative session response: use SSL */ - if (!send_smb(fd, (char *)buf)) - exit_server("sslutil_negotiate_ssl: send_smb failed.\n"); + if (!send_smb(fd, (char *)buf)) { + DEBUG(0,("sslutil_negotiate_ssl: send_smb failed.\n")); + return -1; + } if(sslutil_accept(fd) != 0){ DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr() ) ); return -1; -- cgit From 17a0a89c797c02b34a7584c67643a8ceb2fd6660 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Jul 2001 01:01:02 +0000 Subject: Ensure we correctly round down to 2 second boundary if dos filetime set for a share. Jeremy. (This used to be commit 8f57233c0f871763bc3657d754c894dbd29ae501) --- source3/smbd/nttrans.c | 24 ++++++++++++++++++++++-- source3/smbd/trans2.c | 31 ++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d58bb106af..f2b6ba7a80 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -635,6 +635,7 @@ int reply_ntcreate_and_X(connection_struct *conn, files_struct *fsp=NULL; char *p = NULL; BOOL stat_open_only = False; + time_t c_time; START_PROFILE(SMBntcreateX); /* If it's an IPC, use the pipe handler. */ @@ -913,7 +914,16 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 4; /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + + if (lp_dos_filetime_resolution(SNUM(conn))) { + c_time &= ~1; + sbuf.st_atime &= ~1; + sbuf.st_mtime &= ~1; + sbuf.st_mtime &= ~1; + } + + put_long_date(p,c_time); p += 8; put_long_date(p,sbuf.st_atime); /* access time */ p += 8; @@ -1115,6 +1125,7 @@ static int call_nt_transact_create(connection_struct *conn, int smb_attr; int error_class; uint32 error_code; + time_t c_time; DEBUG(5,("call_nt_transact_create\n")); @@ -1385,7 +1396,16 @@ static int call_nt_transact_create(connection_struct *conn, p += 8; /* Create time. */ - put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + + if (lp_dos_filetime_resolution(SNUM(conn))) { + c_time &= ~1; + sbuf.st_atime &= ~1; + sbuf.st_mtime &= ~1; + sbuf.st_mtime &= ~1; + } + + put_long_date(p,c_time); p += 8; put_long_date(p,sbuf.st_atime); /* access time */ p += 8; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f88ddb41aa..f94b24f595 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -433,6 +433,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mdate = sbuf.st_mtime; adate = sbuf.st_atime; cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + + if (lp_dos_filetime_resolution(SNUM(conn))) { + cdate &= ~1; + mdate &= ~1; + adate &= ~1; + } + if(mode & aDIR) size = 0; @@ -1311,6 +1318,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, BOOL bad_path = False; BOOL delete_pending = False; int len; + time_t c_time; if (tran_call == TRANSACT2_QFILEINFO) { files_struct *fsp = file_fsp(params,0); @@ -1415,12 +1423,21 @@ static int call_trans2qfilepathinfo(connection_struct *conn, memset((char *)pdata,'\0',data_size); + c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + + if (lp_dos_filetime_resolution(SNUM(conn))) { + c_time &= ~1; + sbuf.st_atime &= ~1; + sbuf.st_mtime &= ~1; + sbuf.st_mtime &= ~1; + } + switch (info_level) { case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_dos_date2(pdata,l1_fdateCreation,c_time); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,(uint32)size); @@ -1431,7 +1448,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; - put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_dos_date2(pdata,0,c_time); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,(uint32)size); @@ -1456,7 +1473,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 40; SIVAL(pdata,36,0); } - put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ @@ -1464,7 +1481,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(5,("SMB_QFBI - ")); { - time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + time_t create_time = c_time; DEBUG(5,("create: %s ", ctime(&create_time))); } DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); @@ -1529,7 +1546,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ @@ -1629,7 +1646,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pstring new_fname; size_t byte_len; - put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ @@ -1676,7 +1693,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case 1034: - put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ -- cgit From 59db9bcbf084a23c1f8c7e1c7017f064b8c1e59c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 04:17:58 +0000 Subject: check for bad usernames early in session setup (This used to be commit 657836599a847578096696af27cd7c9f0d52c931) --- source3/smbd/reply.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d27f7842eb..edcc3f4838 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -858,6 +858,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int domain,native_os,native_lanman)); } + /* don't allow for weird usernames */ + alpha_strcpy(user, user, ". _-", sizeof(user)); + if (strstr(user, "..")) { + return bad_password_error(inbuf, outbuf); + } + DEBUG(3,("sesssetupX:name=[%s]\n",user)); /* If name ends in $ then I think it's asking about whether a */ -- cgit From 87fbb7092b8f8b2f0db0f361c3d625e19de57cd9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:15:53 +0000 Subject: The big character set handling changeover! This commit gets rid of all our old codepage handling and replaces it with iconv. All internal strings in Samba are now in "unix" charset, which may be multi-byte. See internals.doc and my posting to samba-technical for a more complete explanation. (This used to be commit debb471267960e56005a741817ebd227ecfc512a) --- source3/smbd/chgpasswd.c | 10 +-- source3/smbd/close.c | 2 +- source3/smbd/connection.c | 2 - source3/smbd/dfree.c | 8 +- source3/smbd/dir.c | 7 +- source3/smbd/dosmode.c | 4 +- source3/smbd/filename.c | 2 +- source3/smbd/ipc.c | 2 +- source3/smbd/lanman.c | 38 ++++---- source3/smbd/mangle.c | 70 ++------------- source3/smbd/message.c | 9 +- source3/smbd/negprot.c | 2 +- source3/smbd/noquotas.c | 2 +- source3/smbd/notify_kernel.c | 2 +- source3/smbd/nttrans.c | 18 ++-- source3/smbd/open.c | 26 +----- source3/smbd/password.c | 2 +- source3/smbd/posix_acls.c | 12 +-- source3/smbd/reply.c | 99 +++++++++------------ source3/smbd/server.c | 4 - source3/smbd/service.c | 3 - source3/smbd/srvstr.c | 145 ++----------------------------- source3/smbd/trans2.c | 52 +++++------ source3/smbd/vfs-wrap.c | 36 ++++---- source3/smbd/vfs.c | 202 +++++++++---------------------------------- 25 files changed, 186 insertions(+), 573 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index c6f6eca0ba..12e38f2a65 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -793,14 +793,12 @@ BOOL check_oem_password(char *user, /* * nt passwords are in unicode */ - int uni_pw_len = new_pw_len; - char *pw; - new_pw_len /= 2; - pw = dos_unistrn2((uint16 *)(&lmdata[512 - uni_pw_len]),new_pw_len); - memcpy(new_passwd, pw, new_pw_len + 1); + pull_ucs2(NULL, new_passwd, + (const smb_ucs2_t *)&lmdata[512 - new_pw_len], + new_passwd_size, new_pw_len, 0); } else { memcpy(new_passwd, &lmdata[512 - new_pw_len], new_pw_len); - new_passwd[new_pw_len] = '\0'; + new_passwd[new_pw_len] = 0; } /* diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 217c81228f..dfbc2272e6 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -172,7 +172,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (normal_close && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(fsp->conn->vfs_ops.unlink(conn,dos_to_unix(fsp->fsp_name, False)) != 0) { + if(fsp->conn->vfs_ops.unlink(conn,fsp->fsp_name) != 0) { /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 796a54e77d..a6c37c7aba 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -53,7 +53,6 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) key.pid = sys_getpid(); key.cnum = conn?conn->cnum:-1; fstrcpy(key.name, name); - dos_to_unix(key.name, True); /* Convert key to unix-codepage */ kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); @@ -174,7 +173,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO key.pid = sys_getpid(); key.cnum = conn?conn->cnum:-1; fstrcpy(key.name, name); - dos_to_unix(key.name, True); /* Convert key to unix-codepage */ kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 64c6182cd8..7848309a5e 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -66,7 +66,7 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree, return number of 1K blocks available on a path and total number ****************************************************************************/ -static SMB_BIG_UINT disk_free(char *path, BOOL small_query, +static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { int dfree_retval; @@ -91,7 +91,7 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, slprintf(syscmd, sizeof(syscmd)-1, "%s %s", dfree_command, path); DEBUG (3, ("disk_free: Running command %s\n", syscmd)); - lines = file_lines_pload(syscmd, NULL, True); + lines = file_lines_pload(syscmd, NULL); if (lines) { char *line = lines[0]; @@ -161,8 +161,8 @@ static SMB_BIG_UINT disk_free(char *path, BOOL small_query, /**************************************************************************** wrap it to get filenames right ****************************************************************************/ -SMB_BIG_UINT sys_disk_free(char *path, BOOL small_query, +SMB_BIG_UINT sys_disk_free(const char *path, BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { - return(disk_free(dos_to_unix(path,False),small_query, bsize,dfree,dsize)); + return disk_free(path,small_query, bsize,dfree,dsize); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index fa9cbdc4a2..9a9c745944 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -625,7 +625,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(conn,dos_to_unix(pathreal, False), &sbuf) != 0) + if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; @@ -701,7 +701,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - DIR *p = conn->vfs_ops.opendir(conn,dos_to_unix(name,False)); + DIR *p = conn->vfs_ops.opendir(conn,name); int used=0; if (!p) return(NULL); @@ -720,9 +720,6 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) l = strlen(n)+1; - /* Return value of vfs_readdirname has already gone through - unix_to_dos() */ - /* If it's a vetoed file, pretend it doesn't even exist */ if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 9ec1fa2606..89e5b1586c 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -282,7 +282,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(conn->vfs_ops.utime(conn,dos_to_unix(fname, False), times) == 0) + if(conn->vfs_ops.utime(conn,fname, times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -310,7 +310,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = conn->vfs_ops.utime(conn,dos_to_unix(fname, False), times); + ret = conn->vfs_ops.utime(conn,fname, times); unbecome_root(); } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index bdbcd81b64..9b76d63dc6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -436,7 +436,7 @@ BOOL check_name(char *name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(conn,dos_to_unix(name,False),&statbuf) != -1) && + if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index eb6ccb4fce..e853112bfe 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -385,7 +385,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int START_PROFILE(SMBtrans); memset(name, '\0',sizeof(name)); - srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE); if (dscnt > tdscnt || pscnt > tpscnt) { exit_server("invalid trans parameters\n"); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 69a0fa5ac3..2b71770b2e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -75,8 +75,7 @@ static int CopyExpanded(connection_struct *conn, StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub_conn(conn,buf); - StrnCpy(*dst,buf,*n-1); - l = strlen(*dst) + 1; + l = push_ascii(*dst,buf,*n-1, STR_TERMINATE); (*dst) += l; (*n) -= l; return l; @@ -86,8 +85,7 @@ static int CopyAndAdvance(char** dst, char* src, int* n) { int l; if (!src || !dst || !n || !(*dst)) return(0); - StrnCpy(*dst,src,*n-1); - l = strlen(*dst) + 1; + l = push_ascii(*dst,src,*n-1, STR_TERMINATE); (*dst) += l; (*n) -= l; return l; @@ -356,7 +354,7 @@ static void PackDriverData(struct pack_desc* desc) SIVAL(drivdata,0,sizeof drivdata); /* cb */ SIVAL(drivdata,4,1000); /* lVersion */ memset(drivdata+8,0,32); /* szDeviceName */ - srvstr_push_ascii(drivdata+8,"NULL",-1); + push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE); PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ } @@ -563,7 +561,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", snum, drivername, lp_driverfile(snum))); - lines = file_lines_load(lp_driverfile(snum),NULL, False); + lines = file_lines_load(lp_driverfile(snum),NULL); if (!lines) { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum), @@ -795,7 +793,7 @@ static int get_printerdrivernumber(int snum) DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", snum, drivername, lp_driverfile(snum))); - lines = file_lines_load(lp_driverfile(snum), NULL, False); + lines = file_lines_load(lp_driverfile(snum), NULL); if (!lines) { DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); @@ -1110,7 +1108,7 @@ static int get_server_info(uint32 servertype, BOOL local_list_only; int i; - lines = file_lines_load(lock_path(SERVER_LIST), NULL, False); + lines = file_lines_load(lock_path(SERVER_LIST), NULL); if (!lines) { DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); return(0); @@ -1255,15 +1253,15 @@ static int fill_srv_info(struct srv_info_struct *service, switch (uLevel) { case 0: - srvstr_push_ascii(p,service->name,15); - break; + push_ascii(p,service->name, 15, STR_TERMINATE); + break; case 1: - srvstr_push_ascii(p,service->name,15); - SIVAL(p,18,service->type); - SIVAL(p,22,PTR_DIFF(p2,baseaddr)); - len += CopyAndAdvance(&p2,service->comment,&l2); - break; + push_ascii(p,service->name,15, STR_TERMINATE); + SIVAL(p,18,service->type); + SIVAL(p,22,PTR_DIFF(p2,baseaddr)); + len += CopyAndAdvance(&p2,service->comment,&l2); + break; } if (stringbuf) @@ -1340,7 +1338,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); if (strcmp(str1, "WrLehDz") == 0) { - srvstr_pull_ascii(domain, p, sizeof(fstring)); + pull_ascii_fstring(domain, p); } else { fstrcpy(domain, global_myworkgroup); } @@ -1515,7 +1513,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, } if (!baseaddr) baseaddr = p; - srvstr_push_ascii(p,lp_servicename(snum),13); + push_ascii(p,lp_servicename(snum),13, STR_TERMINATE); if (uLevel > 0) { @@ -1727,7 +1725,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param fstring user; fstring pass1,pass2; - srvstr_pull_ascii(user,p,sizeof(user)); + pull_ascii_fstring(user,p); p = skip_string(p,1); @@ -1868,7 +1866,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * } p = skip_string(p,1); - p += srvstr_pull_ascii(user,p,sizeof(user)); + p += pull_ascii_fstring(user,p); DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); @@ -2138,7 +2136,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par p2 = p + struct_len; if (uLevel != 20) { srvstr_push(NULL, p,local_machine,16, - STR_ASCII|STR_UPPER|STR_TERMINATE|STR_CONVERT); + STR_ASCII|STR_UPPER|STR_TERMINATE); } p += 16; if (uLevel > 0) diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 61af1f7ded..8df71d4557 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -244,7 +244,6 @@ static BOOL is_reserved_msdos( char *fname ) static BOOL is_illegal_name( char *name ) { unsigned char *s; - int skip; if( !name ) return( True ); @@ -255,18 +254,10 @@ static BOOL is_illegal_name( char *name ) s = (unsigned char *)name; while( *s ) { - skip = get_character_len( *s ); - if( skip != 0 ) - { - s += skip; - } - else - { - if( isillegal( *s ) ) + if( *s>0x7F && isillegal( *s ) ) return( True ); else s++; - } } return( False ); @@ -325,7 +316,6 @@ BOOL is_8_3( char *fname, BOOL check_case ) { int len; int l; - int skip; char *p; char *dot_pos; char *slash_pos = strrchr( fname, '/' ); @@ -374,17 +364,12 @@ BOOL is_8_3( char *fname, BOOL check_case ) dot_pos = NULL; while( *p ) { - if( (skip = get_character_len( *p )) != 0 ) - p += skip; - else - { if( *p == '.' && !dot_pos ) dot_pos = (char *)p; - else + /*else if( !isdoschar( *p ) ) - return( False ); + return( False );*/ p++; - } } /* no dot and less than 9 means OK */ @@ -844,7 +829,6 @@ void mangle_name_83( char *s) char base[9]; int baselen = 0; int extlen = 0; - int skip; extension[0] = 0; base[0] = 0; @@ -879,31 +863,9 @@ void mangle_name_83( char *s) *p++ = 0; while( *p && extlen < 3 ) { - skip = get_character_len( *p ); - switch( skip ) - { - case 2: - if( extlen < 2 ) - { + if( /*isdoschar (*p) &&*/ *p != '.' ) extension[extlen++] = p[0]; - extension[extlen++] = p[1]; - } - else - { - extension[extlen++] = mangle( (unsigned char)*p ); - } - p += 2; - break; - case 1: - extension[extlen++] = p[0]; p++; - break; - default: - if( isdoschar (*p) && *p != '.' ) - extension[extlen++] = p[0]; - p++; - break; - } } extension[extlen] = 0; } @@ -913,31 +875,9 @@ void mangle_name_83( char *s) while( *p && baselen < 5 ) { - skip = get_character_len(*p); - switch( skip ) - { - case 2: - if( baselen < 4 ) - { + if( /*isdoschar( *p ) &&*/ *p != '.' ) base[baselen++] = p[0]; - base[baselen++] = p[1]; - } - else - { - base[baselen++] = mangle( (unsigned char)*p ); - } - p += 2; - break; - case 1: - base[baselen++] = p[0]; p++; - break; - default: - if( isdoschar( *p ) && *p != '.' ) - base[baselen++] = p[0]; - p++; - break; - } } base[baselen] = 0; diff --git a/source3/smbd/message.c b/source3/smbd/message.c index bae9f6c906..a5726d44f8 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -66,7 +66,6 @@ static void msg_deliver(void) if(msgpos > 0) { msgbuf[msgpos] = '\0'; /* Ensure null terminated. */ - pstrcpy(msgbuf,dos_to_unix(msgbuf,False)); } for (i=0;ivfs_ops.open(conn, path, O_RDONLY, 0); if (fd == -1) { DEBUG(3,("Failed to open directory %s for change notify\n", path)); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f2b6ba7a80..ea37b14e5e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -574,7 +574,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, int pnum = -1; char *p = NULL; - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -682,7 +682,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); if( strchr(fname, ':')) { SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); @@ -710,10 +710,10 @@ int reply_ntcreate_and_X(connection_struct *conn, } srvstr_pull(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, - -1, STR_TERMINATE|STR_CONVERT); + -1, STR_TERMINATE); } else { srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), - -1, STR_TERMINATE|STR_CONVERT); + -1, STR_TERMINATE); } /* @@ -971,7 +971,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, return(ERROR(ERRDOS,ERRbadaccess)); } - srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -1188,7 +1188,7 @@ static int call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); if( strchr(fname, ':')) { SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); @@ -1215,9 +1215,9 @@ static int call_nt_transact_create(connection_struct *conn, } srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, - -1, STR_TERMINATE|STR_CONVERT); + -1, STR_TERMINATE); } else { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); } /* @@ -1511,7 +1511,7 @@ static int call_nt_transact_rename(connection_struct *conn, int outsize = 0; CHECK_FSP(fsp, conn); - srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE); outsize = rename_internals(conn, inbuf, outbuf, fsp->fsp_name, new_name, replace_if_exists); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8bfddd4c71..7c48e28138 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,14 +38,13 @@ static int fd_open(struct connection_struct *conn, char *fname, #ifdef O_NONBLOCK flags |= O_NONBLOCK; #endif - - fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode); + fd = conn->vfs_ops.open(conn,fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode); + fd = conn->vfs_ops.open(conn,fname,flags,mode); } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, @@ -199,13 +198,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->stat_open = False; fsp->directory_delete_on_close = False; fsp->conn = conn; - /* - * Note that the file name here is the *untranslated* name - * ie. it is still in the DOS codepage sent from the client. - * All use of this filename will pass though the sys_xxxx - * functions which will do the dos_to_unix translation before - * mapping into a UNIX filename. JRA. - */ string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; fsp->wcp = NULL; /* Write cache pointer. */ @@ -923,13 +915,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, fsp->stat_open = True; fsp->directory_delete_on_close = False; fsp->conn = conn; - /* - * Note that the file name here is the *untranslated* name - * ie. it is still in the DOS codepage sent from the client. - * All use of this filename will pass though the sys_xxxx - * functions which will do the dos_to_unix translation before - * mapping into a UNIX filename. JRA. - */ string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; fsp->wcp = NULL; /* Write cache pointer. */ @@ -1094,13 +1079,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; - /* - * Note that the file name here is the *untranslated* name - * ie. it is still in the DOS codepage sent from the client. - * All use of this filename will pass though the sys_xxxx - * functions which will do the dos_to_unix translation before - * mapping into a UNIX filename. JRA. - */ string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0c720b6a29..8bcd17d326 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -946,7 +946,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) int plus_allowed = 1; char *file_host; char *file_user; - char **lines = file_lines_load(equiv_file, NULL, False); + char **lines = file_lines_load(equiv_file, NULL); int i; DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 4832184df7..db7e594a9e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1704,7 +1704,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if(default_ace || fsp->is_directory || fsp->fd == -1) { - if (sys_acl_set_file(dos_to_unix(fsp->fsp_name,False), the_acl_type, the_acl) == -1) { + if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", fsp->fsp_name, strerror(errno) )); @@ -1850,14 +1850,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * Get the ACL from the path. */ - posix_acl = sys_acl_get_file( dos_to_unix(fsp->fsp_name, False), SMB_ACL_TYPE_ACCESS); + posix_acl = sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS); /* * If it's a directory get the default POSIX ACL. */ if(fsp->is_directory) - dir_acl = sys_acl_get_file( dos_to_unix(fsp->fsp_name, False), SMB_ACL_TYPE_DEFAULT); + dir_acl = sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); } else { @@ -2115,7 +2115,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * No default ACL - delete one if it exists. */ - if (sys_acl_delete_def_file(dos_to_unix(fsp->fsp_name,False)) == -1) { + if (sys_acl_delete_def_file(fsp->fsp_name) == -1) { DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); return False; @@ -2143,7 +2143,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)posix_perms )); - if(conn->vfs_ops.chmod(conn,dos_to_unix(fsp->fsp_name, False), posix_perms) == -1) { + if(conn->vfs_ops.chmod(conn,fsp->fsp_name, posix_perms) == -1) { DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); free_canon_ace_list(file_ace_list); @@ -2229,7 +2229,7 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) Note that name is in UNIX character set. ****************************************************************************/ -int chmod_acl(char *name, mode_t mode) +int chmod_acl(const char *name, mode_t mode) { SMB_ACL_T posix_acl = NULL; int ret = -1; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index edcc3f4838..fe0f2862c6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -178,7 +178,6 @@ static int connection_error(char *inbuf,char *outbuf,int ecode) int reply_tcon(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - BOOL doencrypt = SMBENCRYPT(); pstring service; pstring user; pstring password; @@ -194,9 +193,9 @@ int reply_tcon(connection_struct *conn, *service = *user = *password = *dev = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE|STR_CONVERT) + 1; - p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE|STR_CONVERT) + 1; - p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE|STR_CONVERT) + 1; + p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1; + p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1; + p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1; *user = 0; p = strchr(service,'%'); @@ -218,14 +217,6 @@ int reply_tcon(connection_struct *conn, pstrcpy(user,validated_username(vuid)); } - /* - * Ensure the user and password names are in UNIX codepage format. - */ - - pstrcpy(user,dos_to_unix(user,False)); - if (!doencrypt) - pstrcpy(password,dos_to_unix(password,False)); - /* * Pass the user through the NT -> unix user mapping * function. @@ -289,7 +280,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt memcpy(password,smb_buf(inbuf),passlen); password[passlen]=0; p = smb_buf(inbuf) + passlen; - p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); if (passlen != 24) { if (strequal(password," ")) @@ -308,7 +299,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt *q++ = 0; fstrcpy(user,q); } - p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_CONVERT|STR_ASCII); + p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII); DEBUG(4,("Got device type %s\n",devicename)); @@ -343,7 +334,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,2,0,True); p = smb_buf(outbuf); p += srvstr_push(outbuf, p, devicename, -1, - STR_CONVERT|STR_TERMINATE|STR_ASCII); + STR_TERMINATE|STR_ASCII); set_message_end(outbuf,p); } else { /* NT sets the fstype of IPC$ to the null string */ @@ -353,9 +344,9 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt p = smb_buf(outbuf); p += srvstr_push(outbuf, p, devicename, -1, - STR_CONVERT|STR_TERMINATE|STR_ASCII); + STR_TERMINATE|STR_ASCII); p += srvstr_push(outbuf, p, fsname, -1, - STR_CONVERT|STR_TERMINATE); + STR_TERMINATE); set_message_end(outbuf,p); @@ -430,8 +421,8 @@ int reply_ioctl(connection_struct *conn, { case IOCTL_QUERY_JOB_INFO: SSVAL(p,0,fsp->print_jobid); /* Job number */ - srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_CONVERT|STR_ASCII); - srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_CONVERT|STR_ASCII); + srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII); + srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); break; } @@ -731,9 +722,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int return(ERROR(ERRDOS,ERRbuftoosmall)); } - memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - smb_apasswd[smb_apasslen] = 0; - srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, smb_apasswd, smb_buf(inbuf), sizeof(smb_apasswd), smb_apasslen, 0); + srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); if (!doencrypt && (lp_security() != SEC_SERVER)) { smb_apasslen = strlen(smb_apasswd); @@ -814,23 +804,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int smb_ntpasslen = passlen2; memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); smb_ntpasswd[smb_ntpasslen] = 0; - - /* - * Ensure the plaintext passwords are in UNIX format. - */ - if(!doencrypt) { - pstrcpy(smb_apasswd,dos_to_unix(smb_apasswd,False)); - pstrcpy(smb_ntpasswd,dos_to_unix(smb_ntpasswd,False)); - } - } else { /* we use the first password that they gave */ smb_apasslen = passlen1; StrnCpy(smb_apasswd,p,smb_apasslen); - /* - * Ensure the plaintext password is in UNIX format. - */ - pstrcpy(smb_apasswd,dos_to_unix(smb_apasswd,False)); /* trim the password */ smb_apasslen = strlen(smb_apasswd); @@ -843,20 +820,27 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } p += passlen1 + passlen2; - p += srvstr_pull(inbuf, user, p, sizeof(user), -1, STR_CONVERT|STR_TERMINATE); + p += srvstr_pull(inbuf, user, p, sizeof(user), -1, + STR_TERMINATE); /* * Incoming user and domain are in DOS codepage format. Convert * to UNIX. */ p += srvstr_pull(inbuf, domain, p, sizeof(domain), - -1, STR_CONVERT|STR_TERMINATE); + -1, STR_TERMINATE); p += srvstr_pull(inbuf, native_os, p, sizeof(native_os), - -1, STR_CONVERT|STR_TERMINATE); + -1, STR_TERMINATE); p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman), - -1, STR_CONVERT|STR_TERMINATE); + -1, STR_TERMINATE); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", domain,native_os,native_lanman)); } + + /* don't allow for weird usernames */ + alpha_strcpy(user, user, ". _-", sizeof(user)); + if (strstr(user, "..")) { + return bad_password_error(inbuf, outbuf); + } /* don't allow for weird usernames */ alpha_strcpy(user, user, ". _-", sizeof(user)); @@ -923,7 +907,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* Work out who's who */ slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s", - dos_to_unix(domain, False), lp_winbind_separator(), user); + domain, lp_winbind_separator(), user); if (sys_getpwnam(dom_user) != NULL) { pstrcpy(user, dom_user); @@ -1050,9 +1034,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int char *p; set_message(outbuf,3,0,True); p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT); - p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE); set_message_end(outbuf,p); /* perhaps grab OS version here?? */ } @@ -1544,7 +1528,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(outbuf,1,0,True); p = smb_buf(inbuf) + 1; - p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); p++; status_len = SVAL(p,0); p += 2; @@ -1886,7 +1870,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBctemp); createmode = SVAL(inbuf,smb_vwv0); - srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE); pstrcat(fname,"/TMXXXXXX"); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1928,7 +1912,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(outbuf,smb_vwv0,fsp->fnum); CVAL(smb_buf(outbuf),0) = 4; p = smb_buf(outbuf) + 1; - p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT); + p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE); set_message_end(outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { @@ -1957,7 +1941,7 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False); fmode = dos_mode(conn,fname,&sbuf); if (fmode & aDIR) return(False); if (!lp_delete_readonly(SNUM(conn))) { @@ -3333,7 +3317,7 @@ int reply_printqueue(connection_struct *conn, SSVAL(p,5, queue[i].job); SIVAL(p,7,queue[i].size); CVAL(p,11) = 0; - srvstr_push(outbuf, p+12, queue[i].user, 16, STR_CONVERT|STR_ASCII); + srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII); p += 28; } @@ -3472,7 +3456,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname,False), &st) != 0) + if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) { ret = True; break; @@ -3556,7 +3540,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname, False), &st) != 0) + if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) { @@ -3707,7 +3691,7 @@ static BOOL can_rename(char *fname,connection_struct *conn) if (!CAN_WRITE(conn)) return(False); - if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False); + if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False); if (!check_file_sharing(conn,fname,True)) return(False); return(True); } @@ -3732,7 +3716,6 @@ int rename_internals(connection_struct *conn, BOOL exists=False; BOOL rc = True; SMB_STRUCT_STAT sbuf1, sbuf2; - pstring zdirectory; *directory = *mask = 0; @@ -3830,7 +3813,6 @@ int rename_internals(connection_struct *conn, } } - pstrcpy(zdirectory, dos_to_unix(directory, False)); if(replace_if_exists) { /* * NT SMB specific flag - rename can overwrite @@ -3840,15 +3822,13 @@ int rename_internals(connection_struct *conn, if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !conn->vfs_ops.rename(conn,zdirectory, - dos_to_unix(newname,False))) + !conn->vfs_ops.rename(conn,directory,newname)) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && !vfs_file_exist(conn,newname,NULL) && - !conn->vfs_ops.rename(conn,zdirectory, - dos_to_unix(newname,False))) + !conn->vfs_ops.rename(conn,directory,newname)) count++; } @@ -3906,8 +3886,7 @@ int rename_internals(connection_struct *conn, continue; } - if (!conn->vfs_ops.rename(conn,dos_to_unix(fname,False), - dos_to_unix(destname,False))) + if (!conn->vfs_ops.rename(conn,fname,destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -4228,7 +4207,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(ERROR(ERRDOS,ERRnoaccess)); } - srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE); if (strlen(newdir) == 0) { ok = True; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1dcf861a17..8d115d954c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -635,8 +635,6 @@ static void usage(char *pname) setup_logging(argv[0],False); - charset_initialise(); - /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ generate_random_buffer(NULL, 0, False); @@ -712,8 +710,6 @@ static void usage(char *pname) } #endif /* WITH_SSL */ - codepage_initialise(lp_client_code_page()); - fstrcpy(global_myworkgroup, lp_workgroup()); CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0e2c0ff7a1..836ef30f80 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -245,7 +245,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (*user && Get_Pwnam(user,True)) { fstring dos_username; fstrcpy(dos_username, user); - unix_to_dos(dos_username, True); return(make_connection(dos_username,user,password, pwlen,dev,vuid,ecode)); } @@ -255,7 +254,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int fstring dos_username; fstrcpy(user,validated_username(vuid)); fstrcpy(dos_username, user); - unix_to_dos(dos_username, True); return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); } } else { @@ -265,7 +263,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int fstring dos_username; fstrcpy(user,current_user_info.smb_name); fstrcpy(dos_username, user); - unix_to_dos(dos_username, True); return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); } } diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 0651fb725b..3c452653f2 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -19,150 +19,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define NO_SYSLOG - #include "includes.h" -#define UNICODE_FLAG(buf, flags) (!(flags & STR_ASCII) && \ - ((flags & STR_UNICODE || \ - (SVAL(buf, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) - -/**************************************************************************** -return an alignment of either 0 or 1 -if unicode is not negotiated then return 0 -otherwise return 1 if offset is off -****************************************************************************/ -static int srvstr_align(void *inbuf, int offset, int flags) -{ - if ((flags & STR_NOALIGN) || !UNICODE_FLAG(inbuf, flags)) return 0; - return offset & 1; -} - -/**************************************************************************** -copy a string from a char* src to a unicode or ascii -dos code page destination choosing unicode or ascii based on the -FLAGS2_UNICODE_STRINGS bit in inbuf -return the number of bytes occupied by the string in the destination -flags can have: - STR_TERMINATE means include the null termination - STR_CONVERT means convert from unix to dos codepage - STR_UPPER means uppercase in the destination - STR_ASCII use ascii even with unicode servers - STR_UNICODE means to force as unicode - STR_NOALIGN means don't do alignment -dest_len is the maximum length allowed in the destination. If dest_len -is -1 then no maxiumum is used -****************************************************************************/ -int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int flags) -{ - int len=0; - - /* treat a pstring as "unlimited" length */ - if (dest_len == -1) { - dest_len = sizeof(pstring); - } - - if (srvstr_align(outbuf, PTR_DIFF(dest, outbuf), flags)) { - *(char *)dest = 0; - dest = (void *)((char *)dest + 1); - dest_len--; - len++; - } - - if (!UNICODE_FLAG(outbuf, flags)) { - /* the client doesn't want unicode */ - safe_strcpy(dest, src, dest_len); - len = strlen(dest); - if (flags & STR_TERMINATE) len++; - if (flags & STR_CONVERT) unix_to_dos(dest,True); - if (flags & STR_UPPER) strupper(dest); - return len; - } - - /* the server likes unicode. give it the works */ - if (flags & STR_CONVERT) { - dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE); - } else { - ascii_to_unistr(dest, src, dest_len); - } - if (flags & STR_UPPER) { - strupper_w(dest); - } - len += strlen(src)*2; - if (flags & STR_TERMINATE) len += 2; - return len; -} - -/**************************************************************************** -copy a string from a unicode or ascii source (depending on flg2) -to a char* destination -flags can have: - STR_CONVERT means convert from dos to unix codepage - STR_TERMINATE means the string in src is null terminated - STR_UNICODE means to force as unicode - STR_NOALIGN means don't do alignment -if STR_TERMINATE is set then src_len is ignored -src_len is the length of the source area in bytes -return the number of bytes occupied by the string in src -****************************************************************************/ -int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_len, int flags) -{ - int len; - - if (dest_len == -1) { - dest_len = sizeof(pstring); - } - - if (srvstr_align(inbuf, PTR_DIFF(src, inbuf), flags)) { - src = (void *)((char *)src + 1); - if (src_len > 0) src_len--; - } - - if (!UNICODE_FLAG(inbuf, flags)) { - /* the server doesn't want unicode */ - if (flags & STR_TERMINATE) { - safe_strcpy(dest, src, dest_len); - len = strlen(src)+1; - } else { - if (src_len > dest_len) src_len = dest_len; - len = src_len; - memcpy(dest, src, len); - dest[len] = 0; - } - if (flags & STR_CONVERT) dos_to_unix(dest,True); - return len; - } - - if (flags & STR_TERMINATE) { - unistr_to_ascii(dest, src, dest_len); - len = strlen(dest)*2 + 2; - } else { - int i, c; - if (dest_len*2 < src_len) src_len = 2*dest_len; - for (i=0; i < src_len; i += 2) { - c = SVAL(src, i); - *dest++ = c; - } - *dest++ = 0; - len = src_len; - } - if (flags & STR_CONVERT) dos_to_unix(dest,True); - return len; -} - -/**************************************************************************** -these are useful for replacing all those StrnCpy() ops for copying data -to/from the wire -****************************************************************************/ - -int srvstr_push_ascii(void *dest, const char *src, int dest_len) +int srvstr_push(void *base_ptr, void *dest, const char *src, int dest_len, int flags) { - return srvstr_push(NULL, dest, src, dest_len, - STR_ASCII|STR_CONVERT|STR_TERMINATE); + return push_string(base_ptr, dest, src, dest_len, flags); } -int srvstr_pull_ascii(char *dest, const void *src, int dest_len) +int srvstr_pull(void *base_ptr, char *dest, const void *src, int dest_len, int src_len, + int flags) { - return srvstr_pull(NULL, dest, src, dest_len, -1, - STR_ASCII|STR_CONVERT|STR_TERMINATE); + return pull_string(base_ptr, dest, src, dest_len, src_len, flags); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f94b24f595..f768a72c6d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -471,8 +471,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,l1_attrFile,mode); p += l1_achName; nameptr = p; - len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); SCVAL(p, -1, len); p += len; break; @@ -493,7 +492,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += l2_achName; nameptr = p; len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + STR_TERMINATE); SCVAL(p, -1, len); p += len; break; @@ -509,8 +508,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,26,4); p += 31; nameptr = p; - len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); SCVAL(p, -1, len); p += len; break; @@ -529,8 +527,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,24,mode); p += 33; nameptr = p; - len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); SCVAL(p, -1, len); p += len; SIVAL(q,4,PTR_DIFF(p, q)); @@ -556,16 +553,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(mangled_name, fname); name_map_mangle(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; - len = srvstr_push(outbuf, p+2, mangled_name, 24, - STR_CONVERT|STR_UPPER); + len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); SSVAL(p, 0, len); } else { SSVAL(p,0,0); *(p+2) = 0; } p += 2 + 24; - len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); SIVAL(q,0,len); p += len; len = PTR_DIFF(p, pdata); @@ -586,8 +581,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 16; SIVAL(p,0,nt_extmode); p += 4; p += 4; - len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); @@ -611,8 +605,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; SIVAL(p,0,0); p += 4; - len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); SIVAL(p, -4, len); p += len; @@ -626,8 +619,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; SIVAL(p,0,reskey); p += 4; p += 4; - len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); @@ -923,7 +915,7 @@ static int call_trans2findnext(connection_struct *conn, *mask = *directory = *resume_name = 0; - srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE); DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \ close_after_request=%d, close_if_end = %d requires_resume_key = %d \ @@ -1194,7 +1186,7 @@ static int call_trans2qfsinfo(connection_struct *conn, */ SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, - STR_TERMINATE|STR_CONVERT); + STR_TERMINATE); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", @@ -1206,13 +1198,13 @@ static int call_trans2qfsinfo(connection_struct *conn, FILE_DEVICE_IS_MOUNTED| (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ - len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE); SIVAL(pdata,8,len); data_len = 12 + len; break; case SMB_QUERY_FS_LABEL_INFO: - len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE); data_len = 4 + len; SIVAL(pdata,0,len); break; @@ -1224,7 +1216,7 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16)); - len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE); SIVAL(pdata,12,len); data_len = 18+len; DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", @@ -1517,7 +1509,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, *short_name = '\0'; } len = srvstr_push(outbuf, pdata+4, short_name, -1, - STR_TERMINATE|STR_CONVERT|STR_UPPER); + STR_TERMINATE|STR_UPPER); data_size = 4 + len; SIVAL(pdata,0,len); } @@ -1531,9 +1523,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, * you like hearing about me suffering.... :-). JRA. */ if(strequal(".", fname)) { - len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE); } else { - len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); } data_size = 4 + len; SIVAL(pdata,0,len); @@ -1571,7 +1563,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ pdata += 4; pdata += 4; /* alignment */ - len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -1722,7 +1714,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,pos); SIVAL(pdata,4,size); SIVAL(pdata,12,size); - len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE|STR_CONVERT); + len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE); SIVAL(pdata,20,len); data_size = 24 + len; break; @@ -2294,7 +2286,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, if(!lp_host_msdfs()) return(ERROR(ERRDOS,ERRbadfunc)); - srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE|STR_CONVERT); + srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) return(ERROR(ERRDOS,ERRbadfile)); @@ -2331,8 +2323,8 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, CAN ACCEPT THIS IN UNICODE. JRA. */ SSVAL(pdata,0,fsp->print_jobid); /* Job number */ - srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_CONVERT|STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ - srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_CONVERT|STR_ASCII|STR_TERMINATE); /* Service name */ + srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ + srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); return(-1); } else { diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index a0b4966c59..241216e9d7 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -29,7 +29,7 @@ is sure to try and execute them. These stubs are used to prevent this possibility. */ -int vfswrap_dummy_connect(connection_struct *conn, char *service, char *user) +int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user) { return 0; /* Return >= 0 for success */ } @@ -40,7 +40,7 @@ void vfswrap_dummy_disconnect(connection_struct *conn) /* Disk operations */ -SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, char *path, BOOL small_query, SMB_BIG_UINT *bsize, +SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { SMB_BIG_UINT result; @@ -59,7 +59,7 @@ SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, char *path, BOOL small_q /* Directory operations */ -DIR *vfswrap_opendir(connection_struct *conn, char *fname) +DIR *vfswrap_opendir(connection_struct *conn, const char *fname) { DIR *result; @@ -93,7 +93,7 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) return result; } -int vfswrap_mkdir(connection_struct *conn, char *path, mode_t mode) +int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) { int result; @@ -126,7 +126,7 @@ int vfswrap_mkdir(connection_struct *conn, char *path, mode_t mode) return result; } -int vfswrap_rmdir(connection_struct *conn, char *path) +int vfswrap_rmdir(connection_struct *conn, const char *path) { int result; @@ -162,7 +162,7 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) /* File operations */ -int vfswrap_open(connection_struct *conn, char *fname, int flags, mode_t mode) +int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode) { int result; @@ -207,7 +207,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n) return result; } -ssize_t vfswrap_write(files_struct *fsp, int fd, char *data, size_t n) +ssize_t vfswrap_write(files_struct *fsp, int fd, const char *data, size_t n) { ssize_t result; @@ -235,7 +235,7 @@ SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int wh return result; } -int vfswrap_rename(connection_struct *conn, char *old, char *new) +int vfswrap_rename(connection_struct *conn, const char *old, const char *new) { int result; @@ -267,7 +267,7 @@ int vfswrap_fsync(files_struct *fsp, int fd) #endif } -int vfswrap_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *sbuf) +int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) { int result; @@ -301,7 +301,7 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) return result; } -int vfswrap_lstat(connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf) +int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { int result; @@ -318,7 +318,7 @@ int vfswrap_lstat(connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf) return result; } -int vfswrap_unlink(connection_struct *conn, char *path) +int vfswrap_unlink(connection_struct *conn, const char *path) { int result; @@ -335,7 +335,7 @@ int vfswrap_unlink(connection_struct *conn, char *path) return result; } -int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode) +int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) { int result; @@ -397,7 +397,7 @@ int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) return result; } -int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid) +int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid) { int result; @@ -425,7 +425,7 @@ int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) return result; } -int vfswrap_chdir(connection_struct *conn, char *path) +int vfswrap_chdir(connection_struct *conn, const char *path) { int result; @@ -459,7 +459,7 @@ char *vfswrap_getwd(connection_struct *conn, char *path) return result; } -int vfswrap_utime(connection_struct *conn, char *path, struct utimbuf *times) +int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times) { int result; @@ -595,7 +595,7 @@ size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) return get_nt_acl(fsp, ppdesc); } -size_t vfswrap_get_nt_acl(files_struct *fsp, char *name, SEC_DESC **ppdesc) +size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc) { return get_nt_acl(fsp, ppdesc); } @@ -605,12 +605,12 @@ BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, S return set_nt_acl(fsp, security_info_sent, psd); } -BOOL vfswrap_set_nt_acl(files_struct *fsp, char *name, uint32 security_info_sent, SEC_DESC *psd) +BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) { return set_nt_acl(fsp, security_info_sent, psd); } -int vfswrap_chmod_acl(connection_struct *conn, char *name, mode_t mode) +int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode) { return chmod_acl(name, mode); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index ac00d00e9e..747d393386 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1,6 +1,6 @@ /* Unix SMB/Netbios implementation. - Version 1.9. + Version 3.0 VFS initialisation and support functions Copyright (C) Tim Potter 1999 @@ -109,156 +109,46 @@ static BOOL vfs_init_default(connection_struct *conn) static BOOL vfs_init_custom(connection_struct *conn) { int vfs_version = -1; - struct vfs_ops *ops, *(*init_fptr)(int *); + struct vfs_ops *ops, *(*init_fptr)(int *, struct vfs_ops *); - DEBUG(3, ("Initialising custom vfs hooks from %s\n", - lp_vfsobj(SNUM(conn)))); - - /* Open object file */ + DEBUG(3, ("Initialising custom vfs hooks from %s\n", + lp_vfsobj(SNUM(conn)))); - if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { + /* Open object file */ + if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), + RTLD_NOW | RTLD_GLOBAL)) == NULL) { DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); return False; - } - - /* Get handle on vfs_init() symbol */ + } - init_fptr = (struct vfs_ops *(*)(int *))sys_dlsym(conn->dl_handle, "vfs_init"); + /* Get handle on vfs_init() symbol */ + init_fptr = (struct vfs_ops *(*)(int *, struct vfs_ops *))sys_dlsym(conn->dl_handle, "vfs_init"); - if (init_fptr == NULL) { + if (init_fptr == NULL) { DEBUG(0, ("No vfs_init() symbol found in %s\n", - lp_vfsobj(SNUM(conn)))); + lp_vfsobj(SNUM(conn)))); return False; - } + } - /* Initialise vfs_ops structure */ + /* Initialise vfs_ops structure */ + conn->vfs_ops = default_vfs_ops; - if ((ops = init_fptr(&vfs_version)) == NULL) { - DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); + if ((ops = init_fptr(&vfs_version, &conn->vfs_ops)) == NULL) { + DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); return False; - } - + } + if (vfs_version != SMB_VFS_INTERFACE_VERSION) { DEBUG(0, ("vfs_init returned wrong interface version info (was %d, should be %d)\n", - vfs_version, SMB_VFS_INTERFACE_VERSION )); + vfs_version, SMB_VFS_INTERFACE_VERSION )); return False; } + + if (ops != &conn->vfs_ops) { + memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); + } - /* Fill in unused operations with default (disk based) ones. - There's probably a neater way to do this then a whole bunch of - if statements. */ - - memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); - - if (conn->vfs_ops.connect == NULL) - conn->vfs_ops.connect = default_vfs_ops.connect; - - if (conn->vfs_ops.disconnect == NULL) - conn->vfs_ops.disconnect = default_vfs_ops.disconnect; - - if (conn->vfs_ops.disk_free == NULL) - conn->vfs_ops.disk_free = default_vfs_ops.disk_free; - - if (conn->vfs_ops.opendir == NULL) - conn->vfs_ops.opendir = default_vfs_ops.opendir; - - if (conn->vfs_ops.readdir == NULL) - conn->vfs_ops.readdir = default_vfs_ops.readdir; - - if (conn->vfs_ops.mkdir == NULL) - conn->vfs_ops.mkdir = default_vfs_ops.mkdir; - - if (conn->vfs_ops.rmdir == NULL) - conn->vfs_ops.rmdir = default_vfs_ops.rmdir; - - if (conn->vfs_ops.closedir == NULL) - conn->vfs_ops.closedir = default_vfs_ops.closedir; - - if (conn->vfs_ops.open == NULL) - conn->vfs_ops.open = default_vfs_ops.open; - - if (conn->vfs_ops.close == NULL) - conn->vfs_ops.close = default_vfs_ops.close; - - if (conn->vfs_ops.read == NULL) - conn->vfs_ops.read = default_vfs_ops.read; - - if (conn->vfs_ops.write == NULL) - conn->vfs_ops.write = default_vfs_ops.write; - - if (conn->vfs_ops.lseek == NULL) - conn->vfs_ops.lseek = default_vfs_ops.lseek; - - if (conn->vfs_ops.rename == NULL) - conn->vfs_ops.rename = default_vfs_ops.rename; - - if (conn->vfs_ops.fsync == NULL) - conn->vfs_ops.fsync = default_vfs_ops.fsync; - - if (conn->vfs_ops.stat == NULL) - conn->vfs_ops.stat = default_vfs_ops.stat; - - if (conn->vfs_ops.fstat == NULL) - conn->vfs_ops.fstat = default_vfs_ops.fstat; - - if (conn->vfs_ops.lstat == NULL) - conn->vfs_ops.lstat = default_vfs_ops.lstat; - - if (conn->vfs_ops.unlink == NULL) - conn->vfs_ops.unlink = default_vfs_ops.unlink; - - if (conn->vfs_ops.chmod == NULL) - conn->vfs_ops.chmod = default_vfs_ops.chmod; - - if (conn->vfs_ops.fchmod == NULL) - conn->vfs_ops.fchmod = default_vfs_ops.fchmod; - - if (conn->vfs_ops.chown == NULL) - conn->vfs_ops.chown = default_vfs_ops.chown; - - if (conn->vfs_ops.fchown == NULL) - conn->vfs_ops.fchown = default_vfs_ops.fchown; - - if (conn->vfs_ops.chdir == NULL) - conn->vfs_ops.chdir = default_vfs_ops.chdir; - - if (conn->vfs_ops.getwd == NULL) - conn->vfs_ops.getwd = default_vfs_ops.getwd; - - if (conn->vfs_ops.utime == NULL) - conn->vfs_ops.utime = default_vfs_ops.utime; - - if (conn->vfs_ops.ftruncate == NULL) - conn->vfs_ops.ftruncate = default_vfs_ops.ftruncate; - - if (conn->vfs_ops.lock == NULL) - conn->vfs_ops.lock = default_vfs_ops.lock; - - if (conn->vfs_ops.symlink == NULL) - conn->vfs_ops.symlink = default_vfs_ops.symlink; - - if (conn->vfs_ops.readlink == NULL) - conn->vfs_ops.readlink = default_vfs_ops.readlink; - - if (conn->vfs_ops.fget_nt_acl == NULL) - conn->vfs_ops.fget_nt_acl = default_vfs_ops.fget_nt_acl; - - if (conn->vfs_ops.get_nt_acl == NULL) - conn->vfs_ops.get_nt_acl = default_vfs_ops.get_nt_acl; - - if (conn->vfs_ops.fset_nt_acl == NULL) - conn->vfs_ops.fset_nt_acl = default_vfs_ops.fset_nt_acl; - - if (conn->vfs_ops.set_nt_acl == NULL) - conn->vfs_ops.set_nt_acl = default_vfs_ops.set_nt_acl; - - if (conn->vfs_ops.chmod_acl == NULL) - conn->vfs_ops.chmod_acl = default_vfs_ops.chmod_acl; - - if (conn->vfs_ops.fchmod_acl == NULL) - conn->vfs_ops.fchmod_acl = default_vfs_ops.fchmod_acl; - - return True; + return True; } #endif @@ -294,7 +184,7 @@ BOOL vfs_init(connection_struct *conn) Check if directory exists. ********************************************************************/ -BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT *st) +BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st) { SMB_STRUCT_STAT st2; BOOL ret; @@ -309,20 +199,26 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT * if(!ret) errno = ENOTDIR; - return ret; + return ret; } /******************************************************************* - vfs mkdir wrapper that calls dos_to_unix. + vfs getwd wrapper ********************************************************************/ +char *vfs_getwd(connection_struct *conn, char *path) +{ + return conn->vfs_ops.getwd(conn,path); +} -int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode) +/******************************************************************* + vfs mkdir wrapper +********************************************************************/ + +int vfs_mkdir(connection_struct *conn, const char *name, mode_t mode) { int ret; - pstring name; SMB_STRUCT_STAT sbuf; - pstrcpy(name,dos_to_unix(fname,False)); /* paranoia copy */ if(!(ret=conn->vfs_ops.mkdir(conn,name,mode))) { /* * Check if high bits should have been set, @@ -336,24 +232,11 @@ int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode) return ret; } -/******************************************************************* - vfs getwd wrapper that calls dos_to_unix. -********************************************************************/ - -char *vfs_getwd(connection_struct *conn, char *unix_path) -{ - char *wd; - wd = conn->vfs_ops.getwd(conn,unix_path); - if (wd) - unix_to_dos(wd, True); - return wd; -} - /******************************************************************* Check if a vfs file exists. ********************************************************************/ -BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) +BOOL vfs_file_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_STAT st; @@ -397,7 +280,7 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) Write data to a fd on the vfs. ****************************************************************************/ -ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) +ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) { size_t total=0; ssize_t ret; @@ -549,13 +432,6 @@ char *vfs_readdirname(connection_struct *conn, void *p) dname = dname - 2; #endif - { - static pstring buf; - memcpy(buf, dname, NAMLEN(ptr)+1); - unix_to_dos(buf, True); - dname = buf; - } - return(dname); } -- cgit From 527e824293ee934ca5da0ef5424efe5ab7757248 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:36:09 +0000 Subject: strchr and strrchr are macros when compiling with optimisation in gcc, so we can't redefine them. damn. (This used to be commit c41fc06376d1a2b83690612304e85010b5e5f3cf) --- source3/smbd/close.c | 2 +- source3/smbd/dosmode.c | 2 +- source3/smbd/filename.c | 6 +++--- source3/smbd/groupname.c | 2 +- source3/smbd/lanman.c | 2 +- source3/smbd/mangle.c | 24 ++++++++++++------------ source3/smbd/nttrans.c | 4 ++-- source3/smbd/open.c | 4 ++-- source3/smbd/quotas.c | 2 +- source3/smbd/reply.c | 32 ++++++++++++++++---------------- source3/smbd/server.c | 4 ++-- source3/smbd/service.c | 2 +- source3/smbd/statcache.c | 2 +- source3/smbd/trans2.c | 6 +++--- source3/smbd/uid.c | 2 +- source3/smbd/vfs.c | 2 +- 16 files changed, 49 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index dfbc2272e6..6b72a8563a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -35,7 +35,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn) { char *p; - if (!(p = strrchr(fsp->fsp_name,'/'))) + if (!(p = strrchr_m(fsp->fsp_name,'/'))) p = fsp->fsp_name; else p++; diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 89e5b1586c..639e365d1b 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -149,7 +149,7 @@ int dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { - char *p = strrchr(path,'/'); + char *p = strrchr_m(path,'/'); if (p) p++; else diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9b76d63dc6..70f34c52ad 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -176,7 +176,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, */ if(saved_last_component) { - end = strrchr(name, '/'); + end = strrchr_m(name, '/'); if(end) pstrcpy(saved_last_component, end + 1); else @@ -243,7 +243,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, #if 0 /* Keep Andrew's conservative code around, just in case. JRA. */ /* this is an extremely conservative test for mangled names. */ - if (strchr(start,magic_char)) + if (strchr_m(start,magic_char)) component_was_mangled = True; #endif @@ -261,7 +261,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Pinpoint the end of this section of the filename. */ - end = strchr(start, '/'); + end = strchr_m(start, '/'); /* * Chop the name at this point. diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index d44e9a7a39..0640d4d7b2 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -125,7 +125,7 @@ void load_groupname_map(void) DEBUG(10,("load_groupname_map: Read line |%s|\n", s)); - if (!*s || strchr("#;",*s)) + if (!*s || strchr_m("#;",*s)) continue; if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 2b71770b2e..6e3145aa7d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -866,7 +866,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, str3 = p + 4; /* remove any trailing username */ - if ((p = strchr(QueueName,'%'))) *p = 0; + if ((p = strchr_m(QueueName,'%'))) *p = 0; DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName)); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 8df71d4557..16286a8bb1 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -85,11 +85,11 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ * * isbasecahr() - Given a character, check the chartest array to see * if that character is in the basechars set. This is - * faster than using strchr(). + * faster than using strchr_m(). * * isillegal() - Given a character, check the chartest array to see * if that character is in the illegal characters set. - * This is faster than using strchr(). + * This is faster than using strchr_m(). * * mangled_cache - Cache header used for storing mangled -> original * reverse maps. @@ -181,7 +181,7 @@ static BOOL is_reserved_msdos( char *fname ) StrnCpy (upperFname, fname, 12); /* lpt1.txt and con.txt etc are also illegal */ - p = strchr(upperFname,'.'); + p = strchr_m(upperFname,'.'); if( p ) *p = '\0'; @@ -287,14 +287,14 @@ BOOL is_mangled( char *s ) if( !ct_initialized ) init_chartest(); - magic = strchr( s, magic_char ); + magic = strchr_m( s, magic_char ); while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ { if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ return( True ); /* If all above, then true, */ - magic = strchr( magic+1, magic_char ); /* else seek next magic. */ + magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ } return( False ); } /* is_mangled */ @@ -318,7 +318,7 @@ BOOL is_8_3( char *fname, BOOL check_case ) int l; char *p; char *dot_pos; - char *slash_pos = strrchr( fname, '/' ); + char *slash_pos = strrchr_m( fname, '/' ); /* If there is a directory path, skip it. */ if( slash_pos ) @@ -389,7 +389,7 @@ BOOL is_8_3( char *fname, BOOL check_case ) /* see smb.conf(5) for a description of the 'strip dot' parameter. */ if( lp_strip_dot() && len - l == 1 - && !strchr( dot_pos + 1, '.' ) ) + && !strchr_m( dot_pos + 1, '.' ) ) { *dot_pos = 0; return( True ); @@ -400,7 +400,7 @@ BOOL is_8_3( char *fname, BOOL check_case ) return( False ); /* extensions may not have a dot */ - if( strchr( dot_pos+1, '.' ) ) + if( strchr_m( dot_pos+1, '.' ) ) return( False ); /* must be in 8.3 format */ @@ -537,8 +537,8 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) /* See if the extensions are unmangled. If so, store the entry * without the extension, thus creating a "group" reverse map. */ - s1 = strrchr( mangled_name, '.' ); - if( s1 && (s2 = strrchr( raw_name, '.' )) ) + s1 = strrchr_m( mangled_name, '.' ); + if( s1 && (s2 = strrchr_m( raw_name, '.' )) ) { i = 1; while( s1[i] && (tolower( s1[1] ) == s2[i]) ) @@ -595,7 +595,7 @@ BOOL check_mangled_cache( char *s ) /* If we didn't find the name *with* the extension, try without. */ if( !FoundPtr ) { - ext_start = strrchr( s, '.' ); + ext_start = strrchr_m( s, '.' ); if( ext_start ) { if((saved_ext = strdup(ext_start)) == NULL) @@ -833,7 +833,7 @@ void mangle_name_83( char *s) extension[0] = 0; base[0] = 0; - p = strrchr(s,'.'); + p = strrchr_m(s,'.'); if( p && (strlen(p+1) < (size_t)4) ) { BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ea37b14e5e..a156748cf8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -684,7 +684,7 @@ int reply_ntcreate_and_X(connection_struct *conn, srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); - if( strchr(fname, ':')) { + if( strchr_m(fname, ':')) { SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); @@ -1190,7 +1190,7 @@ static int call_nt_transact_create(connection_struct *conn, srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); - if( strchr(fname, ':')) { + if( strchr_m(fname, ':')) { SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c48e28138..858a26191f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -42,7 +42,7 @@ static int fd_open(struct connection_struct *conn, char *fname, /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && - (strchr(fname,'.')==NULL)) { + (strchr_m(fname,'.')==NULL)) { pstrcat(fname,"."); fd = conn->vfs_ops.open(conn,fname,flags,mode); } @@ -245,7 +245,7 @@ return True if the filename is one of the special executable types ********************************************************************/ static BOOL is_executable(const char *fname) { - if ((fname = strrchr(fname,'.'))) { + if ((fname = strrchr_m(fname,'.'))) { if (strequal(fname,".com") || strequal(fname,".dll") || strequal(fname,".exe") || diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index caf3997ba8..5d82756f24 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -330,7 +330,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B host = strncat(cutstr,mnttype, sizeof(char) * len ); DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); - testpath=strchr(mnttype, ':'); + testpath=strchr_m(mnttype, ':'); args.gqa_pathp = testpath+1; args.gqa_uid = uid; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fe0f2862c6..a331073093 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -198,13 +198,13 @@ int reply_tcon(connection_struct *conn, p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1; *user = 0; - p = strchr(service,'%'); + p = strchr_m(service,'%'); if (p != NULL) { *p = 0; fstrcpy(user,p+1); } - p = strrchr(service,'\\'); + p = strrchr_m(service,'\\'); if (p) { pstrcpy(service, p+1); } @@ -288,13 +288,13 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt passlen = strlen(password); } - q = strchr(path+2,'\\'); + q = strchr_m(path+2,'\\'); if (!q) { END_PROFILE(SMBtconX); return(ERROR(ERRDOS,ERRnosuchshare)); } fstrcpy(service,q+1); - q = strchr(service,'%'); + q = strchr_m(service,'%'); if (q) { *q++ = 0; fstrcpy(user,q); @@ -1362,7 +1362,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!check_name(directory,conn)) can_open = False; - p = strrchr(dir2,'/'); + p = strrchr_m(dir2,'/'); if (p == NULL) { pstrcpy(mask,dir2); @@ -1374,7 +1374,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(mask,p+1); } - p = strrchr(directory,'/'); + p = strrchr_m(directory,'/'); if (!p) *directory = 0; else @@ -1976,7 +1976,7 @@ int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, rc = unix_convert(name,conn,0,&bad_path,&sbuf); - p = strrchr(name,'/'); + p = strrchr_m(name,'/'); if (!p) { pstrcpy(directory,"./"); pstrcpy(mask,name); @@ -3627,21 +3627,21 @@ static BOOL resolve_wildcards(char *name1,char *name2) fstring ext1,ext2; char *p,*p2; - name1 = strrchr(name1,'/'); - name2 = strrchr(name2,'/'); + name1 = strrchr_m(name1,'/'); + name2 = strrchr_m(name2,'/'); if (!name1 || !name2) return(False); fstrcpy(root1,name1); fstrcpy(root2,name2); - p = strrchr(root1,'.'); + p = strrchr_m(root1,'.'); if (p) { *p = 0; fstrcpy(ext1,p+1); } else { fstrcpy(ext1,""); } - p = strrchr(root2,'.'); + p = strrchr_m(root2,'.'); if (p) { *p = 0; fstrcpy(ext2,p+1); @@ -3731,7 +3731,7 @@ int rename_internals(connection_struct *conn, * as this is checked in resolve_wildcards(). */ - p = strrchr(name,'/'); + p = strrchr_m(name,'/'); if (!p) { pstrcpy(directory,"."); pstrcpy(mask,name); @@ -3767,7 +3767,7 @@ int rename_internals(connection_struct *conn, pstrcat(directory,mask); /* Ensure newname contains a '/' also */ - if(strrchr(newname,'/') == 0) { + if(strrchr_m(newname,'/') == 0) { pstring tmpstr; pstrcpy(tmpstr, "./"); @@ -3800,7 +3800,7 @@ int rename_internals(connection_struct *conn, * Note that we guarantee that newname contains a '/' * character above. */ - p = strrchr(newname,'/'); + p = strrchr_m(newname,'/'); pstrcpy(newname_modified_last_component,p+1); if(strcsequal(newname_modified_last_component, @@ -3966,7 +3966,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcpy(dest,dest1); if (target_is_directory) { - char *p = strrchr(src,'/'); + char *p = strrchr_m(src,'/'); if (p) p++; else @@ -4091,7 +4091,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRSRV,ERRerror)); } - p = strrchr(name,'/'); + p = strrchr_m(name,'/'); if (!p) { pstrcpy(directory,"./"); pstrcpy(mask,name); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8d115d954c..f753d615ed 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -389,7 +389,7 @@ static BOOL dump_core(void) char *p; pstring dname; pstrcpy(dname,debugf); - if ((p=strrchr(dname,'/'))) *p=0; + if ((p=strrchr_m(dname,'/'))) *p=0; pstrcat(dname,"/corefiles"); mkdir(dname,0700); sys_chown(dname,getuid(),getgid()); @@ -497,7 +497,7 @@ static void init_structs(void ) if (!*global_myname) { char *p; fstrcpy( global_myname, myhostname() ); - p = strchr( global_myname, '.' ); + p = strchr_m( global_myname, '.' ); if (p) *p = 0; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 836ef30f80..04139be917 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -102,7 +102,7 @@ int add_home_service(char *service, char *homedir) fstrcpy(new_service, service); - if ((usr_p = strchr(service,*lp_winbind_separator())) != NULL) + if ((usr_p = strchr_m(service,*lp_winbind_separator())) != NULL) fstrcpy(new_service, usr_p+1); lp_add_home(new_service,iHomeService,homedir); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 65a4830016..2e31e1252e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -174,7 +174,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, /* * Didn't find it - remove last component for next try. */ - sp = strrchr(chk_name, '/'); + sp = strrchr_m(chk_name, '/'); if (sp) { *sp = '\0'; } else { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f768a72c6d..622b23c0b0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -339,7 +339,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (!conn->dirptr) return(False); - p = strrchr(path_mask,'/'); + p = strrchr_m(path_mask,'/'); if(p != NULL) { if(p[1] == '\0') @@ -732,7 +732,7 @@ static int call_trans2findfirst(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - p = strrchr(directory,'/'); + p = strrchr_m(directory,'/'); if(p == NULL) { pstrcpy(mask,directory); pstrcpy(directory,"./"); @@ -1383,7 +1383,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", fname,info_level,tran_call,total_data)); - p = strrchr(fname,'/'); + p = strrchr_m(fname,'/'); if (!p) { base_name = fname; } else { diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index da4c538319..0070781d24 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -288,7 +288,7 @@ BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) /* If we are looking up a domain user, make sure it is for the local machine only */ - if (strchr(name, sep[0]) || strchr(name, '\\')) { + if (strchr_m(name, sep[0]) || strchr_m(name, '\\')) { fstring domain, username; split_domain_name(name, domain, username); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 747d393386..71ebf9b506 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -705,7 +705,7 @@ BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks) all_string_sub(s,"//","/",0); pstrcpy(base_name,s); - p = strrchr(base_name,'/'); + p = strrchr_m(base_name,'/'); if (!p) return(True); -- cgit From 6b97f76be844a333502c1f17c65fb9e909599915 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Wed, 4 Jul 2001 21:57:03 +0000 Subject: allow to use usrmgr/svrmgr tools in win95 pretty cool (This used to be commit 04575ff17b9b5fe802e66bb8dd1948317ab35485) --- source3/smbd/pipes.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 7a3c1fe20e..c7e0c3a5e5 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -45,6 +45,7 @@ int reply_open_pipe_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; + pstring pipe_name; uint16 vuid = SVAL(inbuf, smb_uid); pipes_struct *p; int smb_ofun = SVAL(inbuf,smb_vwv8); @@ -52,26 +53,27 @@ int reply_open_pipe_and_X(connection_struct *conn, int i; /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); + srvstr_pull(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), -1, STR_TERMINATE); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ - if ( strncmp(fname,PIPE,PIPELEN) != 0 ) + if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) return(ERROR(ERRSRV,ERRaccess)); - DEBUG(4,("Opening pipe %s.\n", fname)); + DEBUG(4,("Opening pipe %s.\n", pipe_name)); /* See if it is one we want to handle. */ for( i = 0; pipe_names[i].client_pipe ; i++ ) - if( strequal(fname,pipe_names[i].client_pipe) ) + if( strequal(pipe_name,pipe_names[i].client_pipe) ) break; if (pipe_names[i].client_pipe == NULL) return(ERROR(ERRSRV,ERRaccess)); /* Strip \PIPE\ off the name. */ - pstrcpy(fname,smb_buf(inbuf) + PIPELEN); + pstrcpy(fname, pipe_name + PIPELEN); + #if 0 /* -- cgit From 55bd0867d8610f75e2696b1539ca1b1ca3aa062d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 5 Jul 2001 04:34:50 +0000 Subject: use alpha_strcpy on the domain as it comes off the wire (This used to be commit 3b9eb528f56b325399e5a4588242bb6d9f9226e2) --- source3/smbd/reply.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a331073093..b7291f5577 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -836,15 +836,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int domain,native_os,native_lanman)); } - /* don't allow for weird usernames */ + /* don't allow for weird usernames or domains */ alpha_strcpy(user, user, ". _-", sizeof(user)); - if (strstr(user, "..")) { - return bad_password_error(inbuf, outbuf); - } - - /* don't allow for weird usernames */ - alpha_strcpy(user, user, ". _-", sizeof(user)); - if (strstr(user, "..")) { + alpha_strcpy(domain, domain, ". _-", sizeof(domain)); + if (strstr(user, "..") || strstr(domain,"..")) { return bad_password_error(inbuf, outbuf); } -- cgit From 8ffcec213e633c4844b470339a5608000fdcf773 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 5 Jul 2001 06:39:15 +0000 Subject: fixed a bug in the parameters SMBctemp uses in open_file_shared() (This used to be commit a1dee993cbf52e7232b65323430c8574843eb168) --- source3/smbd/reply.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b7291f5577..3103ed9c8d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1851,7 +1851,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; - pstring fname2; int outsize = 0; int createmode; mode_t unixmode; @@ -1880,14 +1879,14 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - vfs_stat(conn,fname2,&sbuf); + vfs_stat(conn,fname,&sbuf); /* Open file in dos compatibility share mode. */ /* We should fail if file does not exist. */ fsp = open_file_shared(conn,fname,&sbuf, - SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - FILE_FAIL_IF_NOT_EXIST, - unixmode, oplock_request, NULL, NULL); + SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST, + unixmode, oplock_request, NULL, NULL); /* close fd from smb_mkstemp() */ close(tmpfd); @@ -1907,7 +1906,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(outbuf,smb_vwv0,fsp->fnum); CVAL(smb_buf(outbuf),0) = 4; p = smb_buf(outbuf) + 1; - p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); set_message_end(outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { @@ -1917,9 +1916,9 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - DEBUG( 2, ( "created temp file %s\n", fname2 ) ); + DEBUG( 2, ( "created temp file %s\n", fname ) ); DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", - fname2, fsp->fd, createmode, (int)unixmode ) ); + fname, fsp->fd, createmode, (int)unixmode ) ); END_PROFILE(SMBctemp); return(outsize); -- cgit From c9291d02c1628abd89c4e0c18cb592037cc24cb2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 5 Jul 2001 10:33:10 +0000 Subject: this fixes the failure of MS office on VFAT partitions on Linux The problem is that ftruncate can't expand on VFAT, but it can on ext2. That means our autoconf test is useless. I have recoded it to use the alternative to ftruncate when then sys_ftruncate fails. Jeremy, do you want this for 2.2.1? (This used to be commit 970236ee9926b64c0b39bd8a36b2a9317206873c) --- source3/smbd/vfs-wrap.c | 59 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 241216e9d7..2b465dbe15 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -479,33 +479,34 @@ int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *tim int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) { int result = -1; - START_PROFILE(syscall_ftruncate); - -#ifdef HAVE_FTRUNCATE_EXTEND - result = sys_ftruncate(fd, len); - END_PROFILE(syscall_ftruncate); - return result; -#else - - /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot - extend a file with ftruncate. Provide alternate implementation - for this */ - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; SMB_STRUCT_STAT st; char c = 0; SMB_OFF_T currpos; - currpos = vfs_ops->lseek(fsp, (SMB_OFF_T)0, SEEK_CUR); - if(currpos == -1) { + START_PROFILE(syscall_ftruncate); + + /* we used to just check HAVE_FTRUNCATE_EXTEND and only use + sys_ftruncate if the system supports it. Then I discovered that + you can have some filesystems that support ftruncate + expansion and some that don't! On Linux fat can't do + ftruncate extend but ext2 can. */ + result = sys_ftruncate(fd, len); + if (result == 0) goto done; + + /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot + extend a file with ftruncate. Provide alternate implementation + for this */ + currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR); + if (currpos == -1) { goto done; } - /* Do an fstat to see if the file is longer than - the requested size (call ftruncate), - or shorter, in which case seek to len - 1 and write 1 - byte of zero */ - if(vfs_ops->fstat(fsp, &st)<0) { + /* Do an fstat to see if the file is longer than the requested + size in which case the ftruncate above should have + succeeded or shorter, in which case seek to len - 1 and + write 1 byte of zero */ + if (vfs_ops->fstat(fsp, fd, &st) < 0) { goto done; } @@ -516,35 +517,33 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) } #endif - if(st.st_size == len) { + if (st.st_size == len) { result = 0; goto done; } - if(st.st_size > len) { - /* Yes this is *deliberately* sys_ftruncate ! JRA */ - result = sys_ftruncate(fd, len); + if (st.st_size > len) { + /* the sys_ftruncate should have worked */ goto done; } - if(vfs_ops->lseek(fsp, len-1, SEEK_SET) != len -1) { + if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1) { goto done; } - if(vfs_ops->write(fsp, &c, 1)!=1) { + if (vfs_ops->write(fsp, fd, &c, 1)!=1) { goto done; } /* Seek to where we were */ - if(vfs_ops->lseek(fsp, currpos, SEEK_SET) != currpos) { + if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) { goto done; } + result = 0; done: - END_PROFILE(syscall_ftruncate); - return result; -#endif - + END_PROFILE(syscall_ftruncate); + return result; } BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) -- cgit From aff5f5c15834ffd9b02ea91c7ac146bd4f3cb213 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Jul 2001 18:07:46 +0000 Subject: Fix for rabbit-pellet mode. Chris please test this. Thanks for Dave CB for help on this. Jeremy. (This used to be commit 7efaefdf60e1880cf4ab97e1901248abd00acd79) --- source3/smbd/reply.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3103ed9c8d..21a4eca714 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2538,6 +2538,12 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, follows what WfWg does */ END_PROFILE(SMBwritebraw); if (!write_through && total_written==tcount) { + /* + * Fix for "rabbit pellet" mode, trigger an early TCP ack by + * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA. + */ + if (!send_keepalive(smbd_server_fd())) + exit_server("reply_writebraw: send of keepalive failed"); return(-1); } -- cgit From aa91def29f54a466c7c7efbc8cf442b7a9759afa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Jul 2001 23:37:09 +0000 Subject: Fix race where wrong action (created or opened) could be returned. Jeremy. (This used to be commit af5b649b017f703a14a69f77a9067efb9c6a8269) --- source3/smbd/open.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 858a26191f..f67490b61d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -770,6 +770,14 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", return NULL; } + /* + * If there are any share modes set then the file *did* + * exist. Ensure we return the correct value for action. + */ + + if (num_share_modes > 0) + file_existed = True; + /* * We exit this block with the share entry *locked*..... */ -- cgit From 7a58c800ed8e86a26b2db44a417ebaadb0dd48b7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jul 2001 04:08:24 +0000 Subject: fixed bug where we looked at the first byte of a password to determine if the password is blank. That ain't valid with encrypted passwords! Jeremy, this changes the semantics of session setup. We no longer automatically set guest=True when the client happens to choose their username == the guest username. Instead we rely on the map_to_guest code. I'm pretty sure this is now the right thing, but please look at it carefully before putting it in 2.2 This is the bug that was causing the build farm to sometimes fail. Basically we failed every 256 attempts - ie. when the first byte of the encrypted password happened to be 0 (This used to be commit 4b35a3494c53fe38532fc12cf1c57e1a3715ad0f) --- source3/smbd/reply.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 21a4eca714..da0417203d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -873,10 +873,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* If no username is sent use the guest account */ if (!*user) { - pstrcpy(user,lp_guestaccount(-1)); - /* If no user and no password then set guest flag. */ - if( *smb_apasswd == 0) - guest = True; + pstrcpy(user,lp_guestaccount(-1)); + guest = True; } pstrcpy(current_user_info.smb_name,user); @@ -924,13 +922,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int add_session_user(user); - /* - * Check if the given username was the guest user with no password. - */ - - if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) - guest = True; - /* * Check with orig_user for security=server and * security=domain. @@ -942,7 +933,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int smb_apasslen, smb_ntpasswd, smb_ntpasslen) && !check_hosts_equiv(user)) { - /* * If we get here then the user wasn't guest and the remote * authentication methods failed. Check the authentication -- cgit From 9df203f876c617f67304fe436a339289dbbaf814 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Jul 2001 18:45:59 +0000 Subject: Wrapped dlerror() in the same way as the other dlxxx() calls. Jeremy. (This used to be commit ed5a1f70c6d155788b62e9e6e8c5d97a5ca0858d) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 71ebf9b506..50361564a5 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -117,7 +117,7 @@ static BOOL vfs_init_custom(connection_struct *conn) /* Open object file */ if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { - DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); + DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), sys_dlerror())); return False; } -- cgit From 1c3c9952210346aff1138a4417ff3ceff3ecd9c3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 7 Jul 2001 06:44:50 +0000 Subject: You can't dump_data() a function pointer... Andrew Bartlett (This used to be commit 4f7b2f51b071ee02b9a2ac7decd9fa7d9e078c1a) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 12e38f2a65..044cecb9fb 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -921,7 +921,7 @@ BOOL check_plaintext_password(char *user, char *old_passwd, DEBUG(100, ("check_plaintext_password: old_ntpw \n")); dump_data(100, old_ntpw, 16); DEBUG(100, ("check_plaintext_password: lanman_passwd \n")); - dump_data(100, pdb_get_lanman_passwd, 16); + dump_data(100, pdb_get_lanman_passwd(sampass), 16); DEBUG(100, ("check_plaintext_password: old_pw\n")); dump_data(100, old_pw, 16); #endif -- cgit From 1cc543ffa1306cf5038e67dfe9b8727ab23c31f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 7 Jul 2001 21:24:00 +0000 Subject: fixed some unicode and LANMAN2 bugs in trans2 find first/next (This used to be commit d5097b2f20c55ddcf4ae8da4d1d0a2fe91938a6b) --- source3/smbd/trans2.c | 42 +++--------------------------------------- 1 file changed, 3 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 622b23c0b0..e914a974fb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -471,8 +471,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,l1_attrFile,mode); p += l1_achName; nameptr = p; + p += align_string(outbuf, p, 0); len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SCVAL(p, -1, len); + SCVAL(nameptr, -1, len); p += len; break; @@ -492,46 +493,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += l2_achName; nameptr = p; len = srvstr_push(outbuf, p, fname, -1, - STR_TERMINATE); - SCVAL(p, -1, len); - p += len; - break; - - case 3: - SIVAL(p,0,reskey); - put_dos_date2(p,4,cdate); - put_dos_date2(p,8,adate); - put_dos_date2(p,12,mdate); - SIVAL(p,16,(uint32)size); - SIVAL(p,20,SMB_ROUNDUP(size,1024)); - SSVAL(p,24,mode); - SIVAL(p,26,4); - p += 31; - nameptr = p; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SCVAL(p, -1, len); - p += len; - break; - - case 4: - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - q = p; - put_dos_date2(p,4,cdate); - put_dos_date2(p,8,adate); - put_dos_date2(p,12,mdate); - SIVAL(p,16,(uint32)size); - SIVAL(p,20,SMB_ROUNDUP(size,1024)); - SSVAL(p,24,mode); - p += 33; - nameptr = p; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + STR_NOALIGN); SCVAL(p, -1, len); p += len; - SIVAL(q,4,PTR_DIFF(p, q)); - break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: -- cgit From 5b8d230e39cedda6117cf8528065cbab45bdd835 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 8 Jul 2001 14:10:30 +0000 Subject: This removes unused paramaters from various authtication functions, and should not change behaviour. This should make my later diffs smaller, where I actualy start cleaning up this mess... Andrew Bartlett (This used to be commit 04f090c224bb7ac3b53c430a591fce1fc939a81c) --- source3/smbd/lanman.c | 2 +- source3/smbd/password.c | 35 ++++++++++++++--------------------- source3/smbd/reply.c | 4 ++-- 3 files changed, 17 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 6e3145aa7d..aaf8b3fafe 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1797,7 +1797,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if(SVAL(*rparam,0) != NERR_Success) { - if (password_ok(user, pass1,strlen(pass1),NULL) && + if (password_ok(user, pass1,strlen(pass1)) && chgpasswd(user,pass1,pass2,False)) { SSVAL(*rparam,0,NERR_Success); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8bcd17d326..a0f730d7e2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -520,7 +520,7 @@ return True if the password is correct, False otherwise ****************************************************************************/ BOOL pass_check_smb(char *user, char *domain, uchar *chal, - uchar *lm_pwd, uchar *nt_pwd, struct passwd *pwd) + uchar *lm_pwd, uchar *nt_pwd) { struct passwd *pass; SAM_ACCOUNT *sampass=NULL; @@ -533,17 +533,10 @@ BOOL pass_check_smb(char *user, char *domain, uchar *chal, /* FIXME! this code looks to be unnecessary now that the passdb validates that the username exists and has a valid uid */ - if (pwd != NULL && user == NULL) - { - pass = (struct passwd *) pwd; - user = pass->pw_name; - } - else - { - /* I don't get this call here. I think it should be moved. - Need to check on it. --jerry */ - pass = smb_getpwnam(user,True); - } + + /* I don't get this call here. I think it should be moved. + Need to check on it. --jerry */ + pass = smb_getpwnam(user,True); if (pass == NULL) { @@ -612,7 +605,7 @@ check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) +BOOL password_ok(char *user, char *password, int pwlen) { BOOL ret; @@ -631,7 +624,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) } ret = pass_check_smb(user, global_myworkgroup, - challenge, (uchar *)password, (uchar *)password, pwd); + challenge, (uchar *)password, (uchar *)password); /* * Try with PAM (may not be compiled in - returns True if not. JRA). @@ -643,7 +636,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) return (smb_pam_accountcheck(user) == NT_STATUS_NOPROBLEMO); } - return pass_check(user, password, pwlen, pwd, + return pass_check(user, password, pwlen, lp_update_encrypted() ? update_smbpassword_file : NULL); } @@ -692,7 +685,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL)) { + password_ok(user,password,pwlen)) { endnetgrent(); return(user); } @@ -747,7 +740,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; fstrcpy(name,member); if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL)) { + password_ok(name,password,pwlen)) { endgrent(); return(&name[0]); } @@ -822,7 +815,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) { /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL); + ok = password_ok(user,password, pwlen); if (ok) DEBUG(3,("authorise_login: ACCEPTED: given username (%s) password ok\n", user )); @@ -831,7 +824,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->user.unix_name,snum) && - password_ok(vuser->user.unix_name, password, pwlen, NULL)) { + password_ok(vuser->user.unix_name, password, pwlen)) { fstrcpy(user, vuser->user.unix_name); vuser->guest = False; DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user)); @@ -853,7 +846,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL)) { + if (password_ok(user2,password, pwlen)) { ok = True; fstrcpy(user,user2); DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \ @@ -902,7 +895,7 @@ and given password ok (%s)\n", user)); } else { fstring user2; fstrcpy(user2,auser); - if (user_ok(user2,snum) && password_ok(user2,password,pwlen,NULL)) { + if (user_ok(user2,snum) && password_ok(user2,password,pwlen)) { ok = True; fstrcpy(user,user2); DEBUG(3,("authorise_login: ACCEPTED: user list username \ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index da0417203d..5abd737c37 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -945,7 +945,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if(smb_ntpasslen) { - if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) + if(!password_ok(user, smb_ntpasswd,smb_ntpasslen)) DEBUG(2,("NT Password did not match for user '%s'!\n", user)); else valid_nt_password = True; @@ -957,7 +957,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!valid_nt_password && lp_lanman_auth()) { DEBUG(2,("Defaulting to Lanman password for %s\n", user)); - valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL); + valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen); } -- cgit From 6baa40e3fe59a68046d31a93eb154237d7bd0837 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2001 02:28:17 +0000 Subject: added winbind_exclude_domain() so smbd can tell the winbind client code not to do lookups for a particular domain. This allows winbind to operate on a Samba PDC (This used to be commit d472ee3a690fb6db03fd4536e4093a18fc37ddbb) --- source3/smbd/server.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f753d615ed..7947b9cbc0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -693,6 +693,11 @@ static void usage(char *pname) return(-1); init_structs(); + + /* don't call winbind for our domain if we are the DC */ + if (lp_domain_logons()) { + winbind_exclude_domain(lp_workgroup()); + } #ifdef WITH_PROFILE if (!profile_setup(False)) { -- cgit From 1f9a689f1fe3adb91970b7b3aa962d96451a4e1e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2001 18:52:43 +0000 Subject: Toomas Soome's fix for joining a domain the old way. Jeremy. (This used to be commit 8db233c8b5866df2b3f9f4ed64e7de95807cf371) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5abd737c37..20f5e0fbe2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -837,7 +837,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } /* don't allow for weird usernames or domains */ - alpha_strcpy(user, user, ". _-", sizeof(user)); + alpha_strcpy(user, user, ". _-$", sizeof(user)); alpha_strcpy(domain, domain, ". _-", sizeof(domain)); if (strstr(user, "..") || strstr(domain,"..")) { return bad_password_error(inbuf, outbuf); -- cgit From e3fbb09cede1d2d8b5ad66c6952e86c153cfbefb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 16 Jul 2001 12:16:48 +0000 Subject: Test if machine password has expired. This test was lost somehow... (This used to be commit 065d8f69d5f4a8ffc062bc5592386ee1ac652969) --- source3/smbd/password.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a0f730d7e2..e905d9207f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1571,6 +1571,12 @@ BOOL domain_client_validate( char *user, char *domain, return False; } + /* Test if machine password is expired and need to be changed */ + if (time(NULL) > last_change_time + lp_machine_password_timeout()) + { + global_machine_password_needs_changing = True; + } + /* * At this point, smb_apasswd points to the lanman response to * the challenge in local_challenge, and smb_ntpasswd points to -- cgit From 0cf44bb3476279e1db878b0793aa04b6bcc44a91 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 17 Jul 2001 08:34:12 +0000 Subject: move the global_machine_password_needs_changing where we need it. (This used to be commit 8a2f6fbacd275acc7b356169f4022df4860a813e) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e905d9207f..fb9c39bde4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -25,6 +25,8 @@ extern int DEBUGLEVEL; extern int Protocol; extern struct in_addr ipzero; +BOOL global_machine_password_needs_changing = False; + /* users from session setup */ static pstring session_users=""; -- cgit From c6b51500af5d4f09b4e08d57a7e930a0817e080b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2001 20:42:59 +0000 Subject: Fixes from Jens-Uwe.Walther@force.de to make the -l option behave consistently. Jeremy. (This used to be commit f591ca9f25c54d3cdd0b76df472411e44c95ea47) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7947b9cbc0..6e9b9a4828 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -574,7 +574,7 @@ static void usage(char *pname) case 'l': specified_logfile = True; - pstrcpy(debugf,optarg); + slprintf(debugf, sizeof(debugf)-1, "%s/log.smbd", optarg); break; case 'a': -- cgit From c2aa4b762fd29b1a34c70bb984bca552d768a9fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2001 21:32:33 +0000 Subject: Connection record not existing is not a debug level 0. Jeremy. (This used to be commit d7da59f54eed69d50490205d6233bf4801c16998) --- source3/smbd/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index a6c37c7aba..eeec4a2ca2 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -58,7 +58,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) kbuf.dsize = sizeof(key); if (tdb_delete(tdb, kbuf) != 0) { - DEBUG(0,("yield_connection: tdb_delete failed with error %s.\n", tdb_errorstr(tdb) )); + DEBUG(3,("yield_connection: tdb_delete failed with error %s.\n", tdb_errorstr(tdb) )); return (False); } -- cgit From 54068ae8f390bc008116cbeb459bbd39cd098392 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2001 22:04:46 +0000 Subject: Tidied up calling yield_connection on connection allocation fail. Restore debug message to level zero. Jeremy. (This used to be commit 0b13f495b31887d526b46a48a812fa3fd418ce8e) --- source3/smbd/connection.c | 3 ++- source3/smbd/service.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index eeec4a2ca2..07ded5f4a3 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -58,7 +58,8 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) kbuf.dsize = sizeof(key); if (tdb_delete(tdb, kbuf) != 0) { - DEBUG(3,("yield_connection: tdb_delete failed with error %s.\n", tdb_errorstr(tdb) )); + DEBUG(0,("yield_connection: tdb_delete for name %s failed with error %s.\n", + name, tdb_errorstr(tdb) )); return (False); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 04139be917..2152a3e4df 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -512,6 +512,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int *ecode = ERRaccess; DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", service )); + yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); return NULL; } else { @@ -523,6 +524,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); + yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); return NULL; } @@ -536,6 +538,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); + yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); *ecode = ERRsrverror; return NULL; @@ -588,6 +591,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); + yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); *ecode = ERRsrverror; return NULL; -- cgit From 9cbe6e8166b3397add8c124c867e7848963c4b80 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 21 Jul 2001 02:23:19 +0000 Subject: This patch fixes up a few issues where we would do lookups in the local system on username we already know are perfectly valid, and in their final form. In particular we don't want to do a lookup for DOMAIN\nobody, it just does not make sense, nor should we do map_username and the like if the username is as specified in the vuid - we have done it already. Andrew Bartlett (This used to be commit 7cb517329b0fa2dec427a890a985c75cd467a3b0) --- source3/smbd/reply.c | 80 +++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 20f5e0fbe2..e32ea3e8e1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -215,20 +215,21 @@ int reply_tcon(connection_struct *conn, if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) { pstrcpy(user,validated_username(vuid)); + } else { + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam( user, True); } - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); - conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode); if (!conn) { @@ -309,20 +310,22 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) { pstrcpy(user,validated_username(vuid)); + } else { + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + (void)Get_Pwnam(user, True); + } - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam(user, True); - conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode); if (!conn) { @@ -892,9 +895,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* * Always try the "DOMAIN\user" lookup first, as this is the most * specific case. If this fails then try the simple "user" lookup. + * But don't do this for guests, as this is always a local user. */ - { + if (!guest) { pstring dom_user; /* Work out who's who */ @@ -906,20 +910,20 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstrcpy(user, dom_user); DEBUG(3,("Using unix username %s\n", dom_user)); } - } - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - smb_getpwnam(user, True); + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + smb_getpwnam(user, True); + } + add_session_user(user); /* -- cgit From a9ab7eaa5d023f0f6c2421f504f81988fd41467b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Jul 2001 22:06:05 +0000 Subject: Fix case insensitive password change code. Fixed crash bug with un-zeroed talloced memory. Jeremy. (This used to be commit eea1c30df246e081e672d7132345d0fd35ad9841) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 044cecb9fb..030c69bd4a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -250,7 +250,7 @@ static int expect(int master, char *issue, char *expected) nread += len; buffer[nread] = 0; - if ((match = (ms_fnmatch(expected, buffer) == 0))) + if ((match = (wild_match(expected, buffer) == 0))) timeout = 200; } -- cgit From 76f36b8c360c427fbcc19aa043a3c4b923fd37e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Jul 2001 01:18:43 +0000 Subject: We were making an assumption in the oplock break code path that was invalid (ie. we were assuming we could infer a non-levelII oplock when such an oplock was detected - this may no longer be valid once we've processed the break process dealing with the break will change the state of it anyway. This prevents the state where we get the following packet trace : client server NTcreate -> <- NTcreate resp NTcreate -> <- break to level II ok - broken -> <- break to none Thanks to Alan Romeril for providing the trace that allowed me to track this down. Jeremy. (This used to be commit c343e4f49070011986fc2ed4acd4ce690d5f1d71) --- source3/smbd/open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f67490b61d..a32e032921 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -506,7 +506,6 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } broke_oplock = True; - *p_all_current_opens_are_level_II = False; break; } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { -- cgit From 1cbae7315f99835ee294ce96858f73b5f8a18cfe Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 24 Jul 2001 20:02:48 +0000 Subject: Convert other parameters (read list, write list, valid users...) to the P_LIST format. changed functions to use list instead of strings addedd lp_list_substitute function (This used to be commit 7257d07563ba21bd88733d5d2b4ec4829fab2507) --- source3/smbd/password.c | 35 ++++++++++++++++++++++------------- source3/smbd/service.c | 29 +++++++++++++++++------------ 2 files changed, 39 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fb9c39bde4..bc05d5f500 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -648,25 +648,34 @@ check if a username is valid ****************************************************************************/ BOOL user_ok(char *user,int snum) { - pstring valid, invalid; + char **valid, **invalid; BOOL ret; - StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)-1); - StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)-1); + valid = invalid = NULL; + ret = True; - pstring_sub(valid,"%S",lp_servicename(snum)); - pstring_sub(invalid,"%S",lp_servicename(snum)); - - ret = !user_in_list(user,invalid); - - if (ret && valid && *valid) { - ret = user_in_list(user,valid); + if (lp_invalid_users(snum)) { + lp_list_copy(&invalid, lp_invalid_users(snum)); + if (invalid && lp_list_substitute(invalid, "%S", lp_servicename(snum))) { + ret = !user_in_list(user, invalid); + } } + if (invalid) lp_list_free (&invalid); + + if (ret && lp_valid_users(snum)) { + lp_list_copy(&valid, lp_valid_users(snum)); + if (valid && lp_list_substitute(valid, "%S", lp_servicename(snum))) { + ret = user_in_list(user,valid); + } + } + if (valid) lp_list_free (&valid); if (ret && lp_onlyuser(snum)) { - char *user_list = lp_username(snum); - pstring_sub(user_list,"%S",lp_servicename(snum)); - ret = user_in_list(user,user_list); + char **user_list = lp_list_make (lp_username(snum)); + if (user_list && lp_list_substitute(user_list, "%S", lp_servicename(snum))) { + ret = user_in_list(user, user_list); + } + if (user_list) lp_list_free (&user_list); } return(ret); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2152a3e4df..b65ac13e74 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -337,18 +337,23 @@ connection_struct *make_connection(char *service,char *user,char *password, int { - pstring list; - StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); - pstring_sub(list,"%S",service); + char **list; - if (user_in_list(user,list)) - conn->read_only = True; - - StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); - pstring_sub(list,"%S",service); - - if (user_in_list(user,list)) - conn->read_only = False; + lp_list_copy(&list, lp_readlist(snum)); + if(list && lp_list_substitute(list, "%S", service)) { + if (user_in_list(user, list)) + conn->read_only = True; + } + else DEBUG(0, ("read list substitution failed readlist: 0x%x list: 0x%x\n", lp_readlist(snum), list)); + if (list) lp_list_free(&list); + + lp_list_copy(&list, lp_writelist(snum)); + if(list && lp_list_substitute(list, "%S", service)) { + if (user_in_list(user, list)) + conn->read_only = False; + } + else DEBUG(0, ("write list substitution failed writelist: 0x%x list: 0x%x\n", lp_writelist(snum), list)); + if (list) lp_list_free(&list); } /* admin user check */ @@ -357,7 +362,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int marked read_only. Changed as I don't think this is needed, but old code left in case there is a problem here. */ - if (user_in_list(user,lp_admin_users(snum)) + if (user_in_list(user, lp_admin_users(snum)) #if 0 && !conn->read_only #endif -- cgit From 9de7c5e52155ee869605884526b9895ad58c0312 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 Jul 2001 06:29:26 +0000 Subject: - don't try to print pointers - removed some unused mangling code (This used to be commit 36af1c0dc41f72ec6a5c671fd6b4f6eb2590b8b4) --- source3/smbd/filename.c | 11 ----------- source3/smbd/service.c | 4 ++-- 2 files changed, 2 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 70f34c52ad..17fa35c0d7 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -125,10 +125,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstring orig_path; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; -#if 0 - /* Andrew's conservative code... JRA. */ - extern char magic_char; -#endif ZERO_STRUCTP(pst); @@ -240,13 +236,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(is_mangled(start)) component_was_mangled = True; -#if 0 - /* Keep Andrew's conservative code around, just in case. JRA. */ - /* this is an extremely conservative test for mangled names. */ - if (strchr_m(start,magic_char)) - component_was_mangled = True; -#endif - /* * Now we need to recursively match the name against the real * directory structure. diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b65ac13e74..6f29088a97 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -344,7 +344,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (user_in_list(user, list)) conn->read_only = True; } - else DEBUG(0, ("read list substitution failed readlist: 0x%x list: 0x%x\n", lp_readlist(snum), list)); + else DEBUG(0, ("read list substitution failed\n")); if (list) lp_list_free(&list); lp_list_copy(&list, lp_writelist(snum)); @@ -352,7 +352,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (user_in_list(user, list)) conn->read_only = False; } - else DEBUG(0, ("write list substitution failed writelist: 0x%x list: 0x%x\n", lp_writelist(snum), list)); + else DEBUG(0, ("write list substitution failed writelist\n")); if (list) lp_list_free(&list); } -- cgit From 1d07607b39c0d3ff345c10893b4e8b1a6c7dabb4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 Jul 2001 13:25:31 +0000 Subject: we need to pull passwords in client charset for crypto to work (This used to be commit 9a87d6f58fc005ddf2daf6fceb12a54fdc48f3b7) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e32ea3e8e1..324734a79d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -725,7 +725,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int return(ERROR(ERRDOS,ERRbuftoosmall)); } - srvstr_pull(inbuf, smb_apasswd, smb_buf(inbuf), sizeof(smb_apasswd), smb_apasslen, 0); + memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); if (!doencrypt && (lp_security() != SEC_SERVER)) { -- cgit From e662983fbe2068c977821f6563900d5a2b0a9323 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Jul 2001 18:07:36 +0000 Subject: Excellent patch from Anselm Kruis to fix problem with wrong token being used in current_user. Jeremy. (This used to be commit 2c7d2a1d533052d3556715439fcd66c5233d3137) --- source3/smbd/sec_ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 9ca63a0f95..e0e392decc 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -356,7 +356,7 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN current_user.gid = gid; current_user.ngroups = ngroups; current_user.groups = groups; - current_user.nt_user_token = token; + current_user.nt_user_token = ctx_p->token; } /**************************************************************************** -- cgit From 08138a32446404e64c6738c8f3653c727d113c03 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Jul 2001 21:16:39 +0000 Subject: Fix from Michael Davidson for DEC OSF/1 ACLs (ie. Digital UNIX). Jeremy. (This used to be commit 324ba0512ec84bb173c72be3dfd2447e0dc30e26) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index db7e594a9e..b87605ee07 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1457,7 +1457,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; - sys_acl_free_qualifier((void *)puid); + sys_acl_free_qualifier((void *)puid,tagtype); break; } case SMB_ACL_GROUP_OBJ: @@ -1476,7 +1476,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ gid_to_sid( &sid, *pgid); unix_ug.gid = *pgid; owner_type = GID_ACE; - sys_acl_free_qualifier((void *)pgid); + sys_acl_free_qualifier((void *)pgid,tagtype); break; } case SMB_ACL_MASK: -- cgit From b99e314cfbee90441c05669a824e7e5d4fec3f8e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 26 Jul 2001 22:05:51 +0000 Subject: better debug messages + fix typo in debug message (This used to be commit b377f06fd90f607fa9e0e2e61981e835527b568c) --- source3/smbd/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 6f29088a97..13a6a387ae 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -344,7 +344,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (user_in_list(user, list)) conn->read_only = True; } - else DEBUG(0, ("read list substitution failed\n")); + else DEBUG(0, ("ERROR: read list substitution failed\n")); if (list) lp_list_free(&list); lp_list_copy(&list, lp_writelist(snum)); @@ -352,7 +352,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (user_in_list(user, list)) conn->read_only = False; } - else DEBUG(0, ("write list substitution failed writelist\n")); + else DEBUG(0, ("ERROR: write list substitution failed\n")); if (list) lp_list_free(&list); } -- cgit From 4b28b5a1bb0eea0a1ad2853c15a99d223e3a6717 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 28 Jul 2001 01:26:44 +0000 Subject: Fix for potential crash bug with bad fid. Jeremy. (This used to be commit 82f81c830db53ce507c2a8e65db962f931141afd) --- source3/smbd/trans2.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e914a974fb..ae312cd5d2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1735,7 +1735,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } return(UNIXERROR(ERRDOS,ERRbadpath)); } - } else if (fsp->print_file) { + } else if (fsp && fsp->print_file) { /* * Doing a DELETE_ON_CLOSE should cancel a print job. */ @@ -1999,6 +1999,18 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + case 1013: +#if 0 /* JRA */ + /* + * This (new) W2K call seems to set one byte. Not sure + * yet what it's trying to do. JRA. + */ + { + unsigned char setval = CVAL(pdata,0); + } +#endif /* JRA */ + return(ERROR(ERRDOS,ERRnoaccess)); + default: { return(ERROR(ERRDOS,ERRunknownlevel)); -- cgit From bd0eacb24cb5b138e9c95dc56d023119dec66f4c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 28 Jul 2001 01:46:47 +0000 Subject: Fix invalid uid being used after logoff. Thanks to Nigel Williams for this bug report. Jeremy. (This used to be commit 50d8e5b22f2c2c792e3a2d33e00a1c9caab48981) --- source3/smbd/uid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 0070781d24..9fe634a7e9 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -127,8 +127,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) if (conn->force_user || conn->admin_user || - lp_security() == SEC_SHARE || - !(vuser) || (vuser->guest)) { + (lp_security() == SEC_SHARE)) { uid = conn->uid; gid = conn->gid; current_user.groups = conn->groups; -- cgit From f31a7ab1e27898f2c24da62d3a37da42849cdde4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Jul 2001 17:53:39 +0000 Subject: uint -> uint32. Jeremy. (This used to be commit 3e3155812c38cee65a5344a3879b07d27d160a1e) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a156748cf8..f0403f011e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1014,7 +1014,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, Internal fn to set security descriptors. ****************************************************************************/ -static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_info_sent, int *pdef_class,uint32 *pdef_code) +static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent, int *pdef_class,uint32 *pdef_code) { prs_struct pd; SEC_DESC *psd = NULL; -- cgit From 996719cce26700c68ff0e456e6a25d20085d091f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Jul 2001 22:21:31 +0000 Subject: Added "use mmap" for HPUX. Jeremy. (This used to be commit 840802f10677cb0009cb4df4c37c7d01aa5edacd) --- source3/smbd/connection.c | 2 +- source3/smbd/session.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 07ded5f4a3..df58697917 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -119,7 +119,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO BOOL ret = True; if (!tdb) { - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST, + tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, O_RDWR | O_CREAT, 0644); } if (!tdb) diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 8f6907c537..7616689fe0 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -62,7 +62,7 @@ BOOL session_claim(uint16 vuid) } if (!tdb) { - tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST, + tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, O_RDWR | O_CREAT, 0644); if (!tdb) { DEBUG(1,("session_claim: failed to open sessionid tdb\n")); -- cgit From 61bb3093e32e9e1e58cec079ea101b5b11c5fee0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Aug 2001 17:32:45 +0000 Subject: Pidfile check can be read-only. Removed old ifdef in password.c Jeremy. (This used to be commit d82efc61ef16533c5652a5d4a9863f8317cb4ea2) --- source3/smbd/password.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index bc05d5f500..743d6ebffe 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -42,31 +42,10 @@ Get the next challenge value - no repeats. ********************************************************************/ void generate_next_challenge(char *challenge) { -#if 0 - /* - * Leave this ifdef'd out while we test - * the new crypto random number generator. - * JRA. - */ - unsigned char buf[16]; - static int counter = 0; - struct timeval tval; - int v1,v2; - - /* get a sort-of random number */ - GetTimeOfDay(&tval); - v1 = (counter++) + sys_getpid() + tval.tv_sec; - v2 = (counter++) * sys_getpid() + tval.tv_usec; - SIVAL(challenge,0,v1); - SIVAL(challenge,4,v2); - - /* mash it up with md4 */ - mdfour(buf, (unsigned char *)challenge, 8); -#else - unsigned char buf[8]; + unsigned char buf[8]; + + generate_random_buffer(buf,8,False); - generate_random_buffer(buf,8,False); -#endif memcpy(saved_challenge, buf, 8); memcpy(challenge,buf,8); challenge_sent = True; -- cgit From 819a9117354e22a26608ea31fd75e6eb13a15d8e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Aug 2001 22:13:50 +0000 Subject: Added "strict allocate" per share parameter. This causes actual on-disk allocation to be done. Without it just does the ftruncate. Jeremy. (This used to be commit 0b052f103e82369088bc30724b86d8892c395cdb) --- source3/smbd/trans2.c | 54 +++++++++++++++++++++++++++------- source3/smbd/vfs.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 123 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ae312cd5d2..bb7ca6e0f8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1878,25 +1878,59 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } - /* - * NT seems to use this call with a size of zero - * to mean truncate the file. JRA. - */ - case 1019: case 1020: case SMB_SET_FILE_ALLOCATION_INFO: { - SMB_OFF_T newsize = IVAL(pdata,0); + int ret = -1; + size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T - newsize |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); + size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) /* more than 32 bits? */ return(ERROR(ERRDOS,ERRunknownlevel)); #endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)newsize )); - if(newsize == 0) - size = 0; + DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", + fname, (double)size )); + + if(size != sbuf.st_size) { + + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", + fname, (double)size )); + + if (fd == -1) { + files_struct *new_fsp = NULL; + int access_mode = 0; + int action = 0; + + if(global_oplock_break) { + /* Queue this file modify as we are the process of an oplock break. */ + + DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); + DEBUGADD(2,( "in oplock break state.\n")); + + push_oplock_pending_smb_message(inbuf, length); + return -1; + } + + new_fsp = open_file_shared(conn, fname, &sbuf, + SET_OPEN_MODE(DOS_OPEN_RDWR), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + 0, 0, &access_mode, &action); + + if (new_fsp == NULL) + return(UNIXERROR(ERRDOS,ERRbadpath)); + ret = vfs_allocate_file_space(new_fsp, size); + close_file(new_fsp,True); + } else { + ret = vfs_allocate_file_space(fsp, size); + } + } + + if (ret == -1) + return(UNIXERROR(ERRHRD,ERRdiskfull)); + + sbuf.st_size = size; break; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 50361564a5..834d75266e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -297,6 +297,84 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) return (ssize_t)total; } +/**************************************************************************** + An allocate file space call using the vfs interface. + Allocates space for a file from a filedescriptor. + Returns 0 on success, -1 on failure. +****************************************************************************/ + +int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) +{ + int ret; + SMB_STRUCT_STAT st; + struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; + + if (!lp_strict_allocate(SNUM(fsp->conn))) + return vfs_set_filelen(fsp, len); + + release_level_2_oplocks_on_change(fsp); + + /* + * Actually try and commit the space on disk.... + */ + + DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp->fsp_name, (double)len )); + + ret = vfs_fstat(fsp,fsp->fd,&st); + if (ret == -1) + return ret; + + if (len == st.st_size) + return 0; + + if (len < st.st_size) { + /* Shrink - use ftruncate. */ + + DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n", + fsp->fsp_name, (double)st.st_size )); + + if ((ret = vfs_ops->ftruncate(fsp, fsp->fd, len)) != -1) { + set_filelen_write_cache(fsp, len); + } + return ret; + } + + /* Grow - we need to write out the space.... */ + { + static unsigned char zero_space[65536]; + + SMB_OFF_T start_pos = st.st_size; + SMB_OFF_T len_to_write = len - st.st_size; + SMB_OFF_T retlen; + + DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f\n", + fsp->fsp_name, (double)st.st_size )); + + if ((retlen = vfs_ops->lseek(fsp, fsp->fd, start_pos, SEEK_SET)) != start_pos) + return -1; + + while ( len_to_write > 0) { + SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),len_to_write); + + retlen = vfs_ops->write(fsp,fsp->fd,zero_space,current_len_to_write); + if (retlen != current_len_to_write) { + /* Write fail - return to original size. */ + int save_errno = errno; + fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, st.st_size); + errno = save_errno; + return -1; + } + + DEBUG(10,("vfs_allocate_file_space: file %s, grow. wrote %.0f\n", + fsp->fsp_name, (double)current_len_to_write )); + + len_to_write -= current_len_to_write; + } + set_filelen_write_cache(fsp, len); + } + return 0; +} + /**************************************************************************** A vfs set_filelen call. set the length of a file from a filedescriptor. @@ -308,9 +386,8 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) int ret; release_level_2_oplocks_on_change(fsp); - if ((ret = fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, len)) != -1) { + if ((ret = fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, len)) != -1) set_filelen_write_cache(fsp, len); - } return ret; } -- cgit From 986372901e85a79343ba32f590a4a3e7658d2565 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Aug 2001 13:09:23 +0000 Subject: This is my 'Authentication Rewrite' version 1.01, mostly as submitted to samba-technical a few weeks ago. The idea here is to standardize the checking of user names and passwords, thereby ensuring that all authtentications pass the same standards. The interface currently implemented in as nt_status = check_password(user_info, server_info) where user_info contains (mostly) the authentication data, and server_info contains things like the user-id they got, and their resolved user name. The current ugliness with the way the structures are created will be killed the next revision, when they will be created and malloced by creator functions. This patch also includes the first implementation of NTLMv2 in HEAD, but which needs some more testing. We also add a hack to allow plaintext passwords to be compared with smbpasswd, not the system password database. Finally, this patch probably reintroduces the PAM accounts bug we had in 2.2.0, I'll fix that once this hits the tree. (I've just finished testing it on a wide variety of platforms, so I want to get this patch in). (This used to be commit b30b6202f31d339b48d51c0d38174cafd1cfcd42) --- source3/smbd/auth.c | 275 +++++++++++ source3/smbd/auth_domain.c | 417 ++++++++++++++++ source3/smbd/auth_rhosts.c | 165 +++++++ source3/smbd/auth_server.c | 244 ++++++++++ source3/smbd/auth_smbpasswd.c | 229 +++++++++ source3/smbd/auth_util.c | 141 ++++++ source3/smbd/negprot.c | 3 + source3/smbd/password.c | 1072 ----------------------------------------- source3/smbd/reply.c | 256 ++-------- 9 files changed, 1520 insertions(+), 1282 deletions(-) create mode 100644 source3/smbd/auth.c create mode 100644 source3/smbd/auth_domain.c create mode 100644 source3/smbd/auth_rhosts.c create mode 100644 source3/smbd/auth_server.c create mode 100644 source3/smbd/auth_smbpasswd.c create mode 100644 source3/smbd/auth_util.c (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c new file mode 100644 index 0000000000..851e1f53cf --- /dev/null +++ b/source3/smbd/auth.c @@ -0,0 +1,275 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Password and authentication handling + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Andrew Bartlett 2001 + + 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; + +extern pstring global_myname; + + +/**************************************************************************** +update the encrypted smbpasswd file from the plaintext username and password + +this ugly hack needs to die, but not quite yet... +*****************************************************************************/ +static BOOL update_smbpassword_file(char *user, char *password) +{ + SAM_ACCOUNT *sampass = NULL; + BOOL ret; + + pdb_init_sam(&sampass); + + become_root(); + ret = pdb_getsampwnam(sampass, user); + unbecome_root(); + + if(ret == False) { + DEBUG(0,("pdb_getsampwnam returned NULL\n")); + pdb_free_sam(sampass); + return False; + } + + /* + * Remove the account disabled flag - we are updating the + * users password from a login. + */ + pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED); + + /* Here, the flag is one, because we want to ignore the + XXXXXXX'd out password */ + ret = change_oem_password( sampass, password, True); + if (ret == False) { + DEBUG(3,("change_oem_password returned False\n")); + } + + pdb_free_sam(sampass); + return ret; +} + +/**************************************************************************** + Check user is in correct domain if required +****************************************************************************/ + +static BOOL check_domain_match(char *user, char *domain) +{ + /* + * If we aren't serving to trusted domains, we must make sure that + * the validation request comes from an account in the same domain + * as the Samba server + */ + + if (!lp_allow_trusted_domains() && + !strequal(lp_workgroup(), domain) ) { + DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain)); + return False; + } else { + return True; + } +} + + +uint32 check_password(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +{ + + uint32 nt_status = NT_STATUS_LOGON_FAILURE; + + DEBUG(3, ("check_password: Checking password for user %s with the new password interface\n", user_info->smb_username.str)); + if (check_hosts_equiv(user_info->smb_username.str)) { + nt_status = NT_STATUS_NOPROBLEMO; + } + + if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { + return NT_STATUS_LOGON_FAILURE; + } + + if ((lp_security() == SEC_DOMAIN) && (nt_status != NT_STATUS_NOPROBLEMO)) { + nt_status = check_domain_security(user_info, server_info); + } + + if ((lp_security() == SEC_SERVER) && (nt_status != NT_STATUS_NOPROBLEMO)) { + nt_status = check_server_security(user_info, server_info); + } + + if (lp_security() >= SEC_SERVER) { + smb_user_control(user_info->smb_username.str, nt_status); + } + + if ((nt_status != NT_STATUS_NOPROBLEMO) + && (user_info->plaintext_password.len > 0) + && (!lp_plaintext_to_smbpasswd())) { + return (pass_check(user_info->smb_username.str, + user_info->plaintext_password.str, + user_info->plaintext_password.len, + lp_update_encrypted() ? + update_smbpassword_file : NULL) + ? NT_STATUS_NOPROBLEMO : NT_STATUS_LOGON_FAILURE); + } + + if (nt_status != NT_STATUS_NOPROBLEMO) { + nt_status = check_smbpasswd_security(user_info, server_info); + } + + if (nt_status == NT_STATUS_NOPROBLEMO) { + nt_status = smb_pam_accountcheck(user_info->smb_username.str); + } + + if (nt_status == NT_STATUS_NOPROBLEMO) { + DEBUG(5, ("check_password: Password for user %s suceeded\n", user_info->smb_username.str)); + } else { + DEBUG(3, ("check_password: Password for user %s FAILED with error %d\n", user_info->smb_username.str, nt_status)); + } + return nt_status; + +} + +/**************************************************************************** + COMPATABILITY INTERFACES: + ***************************************************************************/ + +/**************************************************************************** +check if a username/password is OK assuming the password is a 24 byte +SMB hash +return True if the password is correct, False otherwise +****************************************************************************/ + +uint32 pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], + uchar *lm_pwd, int lm_pwd_len, + uchar *nt_pwd, int nt_pwd_len) +{ + + auth_usersupplied_info user_info; + auth_serversupplied_info server_info; + AUTH_STR ourdomain, theirdomain, smb_username, wksta_name; + + ZERO_STRUCT(user_info); + ZERO_STRUCT(ourdomain); + ZERO_STRUCT(theirdomain); + ZERO_STRUCT(smb_username); + ZERO_STRUCT(wksta_name); + + ourdomain.str = lp_workgroup(); + ourdomain.len = strlen(ourdomain.str); + + theirdomain.str = domain; + theirdomain.len = strlen(theirdomain.str); + + user_info.requested_domain = theirdomain; + user_info.domain = ourdomain; + + smb_username.str = user; + smb_username.len = strlen(smb_username.str); + + user_info.requested_username = smb_username; /* For the time-being */ + user_info.smb_username = smb_username; + + user_info.wksta_name.str = client_name(); + user_info.wksta_name.len = strlen(client_name()); + + user_info.wksta_name = wksta_name; + + memcpy(user_info.chal, chal, 8); + + if (lm_pwd_len >= 24 || (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) { + /* if 24 bytes long assume it is an encrypted password */ + + user_info.lm_resp.buffer = (uint8 *)lm_pwd; + user_info.lm_resp.len = lm_pwd_len; + user_info.nt_resp.buffer = (uint8 *)nt_pwd; + user_info.nt_resp.len = nt_pwd_len; + + } else { + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + + /* + * Not encrypted - do so. + */ + + DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + + if (lm_pwd_len > 0) { + SMBencrypt( (uchar *)lm_pwd, user_info.chal, local_lm_response); + user_info.lm_resp.buffer = (uint8 *)local_lm_response; + user_info.lm_resp.len = 24; + + /* This encrypts the lm_pwd feild, which actualy contains the password + rather than the nt_pwd field becouse that contains nothing */ + SMBNTencrypt((uchar *)lm_pwd, user_info.chal, local_nt_response); + user_info.nt_resp.buffer = (uint8 *)local_nt_response; + user_info.nt_resp.len = 24; + } + + user_info.plaintext_password.str = lm_pwd; + user_info.plaintext_password.len = lm_pwd_len; + + } + + return check_password(&user_info, &server_info); +} + +uint32 pass_check_smb(char *user, char *domain, + uchar *lm_pwd, int lm_pwd_len, + uchar *nt_pwd, int nt_pwd_len) +{ + uchar chal[8]; + + if (!last_challenge(chal)) { + generate_random_buffer( chal, 8, False); + } + + return pass_check_smb_with_chal(user, domain, chal, + lm_pwd, lm_pwd_len, + nt_pwd, nt_pwd_len); + +} + +/**************************************************************************** +check if a username/password pair is OK either via the system password +database or the encrypted SMB password database +return True if the password is correct, False otherwise +****************************************************************************/ +BOOL password_ok(char *user, char *password, int pwlen) +{ + + /* + * This hack must die! But until I rewrite the rest of samba + * it must stay - abartlet 2001-08-03 + */ + + if ((pwlen == 0) && !lp_null_passwords()) { + DEBUG(4,("Null passwords not allowed.\n")); + return False; + } + + if (pass_check_smb(user, lp_workgroup(), NULL, 0, password, pwlen) == NT_STATUS_NOPROBLEMO) { + return True; + } + + if (pass_check_smb(user, lp_workgroup(), password, pwlen, NULL, 0) == NT_STATUS_NOPROBLEMO) { + return True; + } + + return False; +} + diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c new file mode 100644 index 0000000000..4bf0a05d7f --- /dev/null +++ b/source3/smbd/auth_domain.c @@ -0,0 +1,417 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Authenticate against a remote domain + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Bartlett 2001 + + 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; +extern struct in_addr ipzero; + +BOOL global_machine_password_needs_changing = False; + +extern pstring global_myname; + +/*********************************************************************** + Connect to a remote machine for domain security authentication + given a name or IP address. + ***********************************************************************/ + +static BOOL connect_to_domain_password_server(struct cli_state *pcli, + char *server, unsigned char *trust_passwd) +{ + struct in_addr dest_ip; + fstring remote_machine; + + if(cli_initialise(pcli) == NULL) { + DEBUG(0,("connect_to_domain_password_server: unable to initialize client connection.\n")); + return False; + } + + if (is_ipaddress(server)) { + struct in_addr to_ip; + + /* we shouldn't have 255.255.255.255 forthe IP address of + a password server anyways */ + if ((to_ip.s_addr=inet_addr(server)) == 0xFFFFFFFF) { + DEBUG (0,("connect_to_domain_password_server: inet_addr(%s) returned 0xFFFFFFFF!\n", server)); + return False; + } + + if (!name_status_find(0x20, to_ip, remote_machine)) { + DEBUG(0, ("connect_to_domain_password_server: Can't " + "resolve name for IP %s\n", server)); + return False; + } + } else { + fstrcpy(remote_machine, server); + } + + standard_sub_basic(remote_machine); + strupper(remote_machine); + + if(!resolve_name( remote_machine, &dest_ip, 0x20)) { + DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n", remote_machine)); + cli_shutdown(pcli); + return False; + } + + if (ismyip(dest_ip)) { + DEBUG(1,("connect_to_domain_password_server: Password server loop - not using password server %s\n", + remote_machine)); + cli_shutdown(pcli); + return False; + } + + if (!cli_connect(pcli, remote_machine, &dest_ip)) { + DEBUG(0,("connect_to_domain_password_server: unable to connect to SMB server on \ +machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + if (!attempt_netbios_session_request(pcli, global_myname, remote_machine, &dest_ip)) { + DEBUG(0,("connect_to_password_server: machine %s rejected the NetBIOS \ +session request. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + return False; + } + + pcli->protocol = PROTOCOL_NT1; + + if (!cli_negprot(pcli)) { + DEBUG(0,("connect_to_domain_password_server: machine %s rejected the negotiate protocol. \ +Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + if (pcli->protocol != PROTOCOL_NT1) { + DEBUG(0,("connect_to_domain_password_server: machine %s didn't negotiate NT protocol.\n", + remote_machine)); + cli_shutdown(pcli); + return False; + } + + /* + * Do an anonymous session setup. + */ + + if (!cli_session_setup(pcli, "", "", 0, "", 0, "")) { + DEBUG(0,("connect_to_domain_password_server: machine %s rejected the session setup. \ +Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + if (!(pcli->sec_mode & 1)) { + DEBUG(1,("connect_to_domain_password_server: machine %s isn't in user level security mode\n", + remote_machine)); + cli_shutdown(pcli); + return False; + } + + if (!cli_send_tconX(pcli, "IPC$", "IPC", "", 1)) { + DEBUG(0,("connect_to_domain_password_server: machine %s rejected the tconX on the IPC$ share. \ +Error was : %s.\n", remote_machine, cli_errstr(pcli) )); + cli_shutdown(pcli); + return False; + } + + /* + * We now have an anonymous connection to IPC$ on the domain password server. + */ + + /* + * Even if the connect succeeds we need to setup the netlogon + * pipe here. We do this as we may just have changed the domain + * account password on the PDC and yet we may be talking to + * a BDC that doesn't have this replicated yet. In this case + * a successful connect to a DC needs to take the netlogon connect + * into account also. This patch from "Bjart Kvarme" . + */ + + if(cli_nt_session_open(pcli, PIPE_NETLOGON) == False) { + DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ +machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); + cli_nt_session_close(pcli); + cli_ulogoff(pcli); + cli_shutdown(pcli); + return False; + } + + if (cli_nt_setup_creds(pcli, trust_passwd) == False) { + DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \ +%s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); + cli_nt_session_close(pcli); + cli_ulogoff(pcli); + cli_shutdown(pcli); + return(False); + } + + return True; +} + +/*********************************************************************** + Utility function to attempt a connection to an IP address of a DC. +************************************************************************/ + +static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, + unsigned char *trust_passwd) +{ + fstring dc_name; + + /* + * Ignore addresses we have already tried. + */ + + if (ip_equal(ipzero, *ip)) + return False; + + if (!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) + return False; + + return connect_to_domain_password_server(pcli, dc_name, trust_passwd); +} + +/*********************************************************************** + We have been asked to dynamcially determine the IP addresses of + the PDC and BDC's for this DOMAIN, and query them in turn. +************************************************************************/ +static BOOL find_connect_pdc(struct cli_state *pcli, + unsigned char *trust_passwd, + time_t last_change_time) +{ + struct in_addr *ip_list = NULL; + int count = 0; + int i; + BOOL connected_ok = False; + time_t time_now = time(NULL); + BOOL use_pdc_only = False; + + /* + * If the time the machine password has changed + * was less than an hour ago then we need to contact + * the PDC only, as we cannot be sure domain replication + * has yet taken place. Bug found by Gerald (way to go + * Gerald !). JRA. + */ + + if (time_now - last_change_time < 3600) + use_pdc_only = True; + + if (!get_dc_list(use_pdc_only, lp_workgroup(), &ip_list, &count)) + return False; + + /* + * Firstly try and contact a PDC/BDC who has the same + * network address as any of our interfaces. + */ + for(i = 0; i < count; i++) { + if(!is_local_net(ip_list[i])) + continue; + + if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) + break; + + ip_list[i] = ipzero; /* Tried and failed. */ + } + + /* + * Secondly try and contact a random PDC/BDC. + */ + if(!connected_ok) { + i = (sys_random() % count); + + if (!(connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) + ip_list[i] = ipzero; /* Tried and failed. */ + } + + /* + * Finally go through the IP list in turn, ignoring any addresses + * we have already tried. + */ + if(!connected_ok) { + /* + * Try and connect to any of the other IP addresses in the PDC/BDC list. + * Note that from a WINS server the #1 IP address is the PDC. + */ + for(i = 0; i < count; i++) { + if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) + break; + } + } + + if(ip_list != NULL) + free((char *)ip_list); + + + return connected_ok; +} + +/*********************************************************************** + Do the same as security=server, but using NT Domain calls and a session + key from the machine password. If the server parameter is specified + use it, otherwise figure out a server from the 'password server' param. +************************************************************************/ + +uint32 domain_client_validate(const auth_usersupplied_info *user_info, + auth_serversupplied_info *server_info, + char *server) +{ + unsigned char trust_passwd[16]; + fstring remote_machine; + char *p, *pserver; + NET_ID_INFO_CTR ctr; + NET_USER_INFO_3 info3; + struct cli_state cli; + uint32 smb_uid_low; + BOOL connected_ok = False; + time_t last_change_time; + uint32 nt_status; + + /* + * Check that the requested domain is not our own machine name. + * If it is, we should never check the PDC here, we use our own local + * password file. + */ + + if(strequal(user_info->domain.str, global_myname)) { + DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); + return NT_STATUS_LOGON_FAILURE; + } + + /* + * Get the machine account password for our primary domain + */ + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) + { + DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup())); + return NT_STATUS_LOGON_FAILURE; + } + + /* Test if machine password is expired and need to be changed */ + if (time(NULL) > last_change_time + lp_machine_password_timeout()) + { + global_machine_password_needs_changing = True; + } + + /* + * At this point, smb_apasswd points to the lanman response to + * the challenge in local_challenge, and smb_ntpasswd points to + * the NT response to the challenge in local_challenge. Ship + * these over the secure channel to a domain controller and + * see if they were valid. + */ + + ZERO_STRUCT(cli); + + /* + * Treat each name in the 'password server =' line as a potential + * PDC/BDC. Contact each in turn and try and authenticate. + */ + + if (server) { + p = server; + } else { + pserver = lp_passwordserver(); + if (! *pserver) pserver = "*"; + p = pserver; + } + + while (!connected_ok && + next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { + if(strequal(remote_machine, "*")) { + connected_ok = find_connect_pdc(&cli, trust_passwd, last_change_time); + } else { + connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); + } + } + + if (!connected_ok) { + DEBUG(0,("domain_client_validate: Domain password server not available.\n")); + cli_shutdown(&cli); + return NT_STATUS_LOGON_FAILURE; + } + + /* We really don't care what LUID we give the user. */ + generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); + + ZERO_STRUCT(info3); + + cli_nt_login_network(&cli, user_info->domain.str, user_info->smb_username.str, smb_uid_low, user_info->chal, + user_info->lm_resp.buffer, user_info->lm_resp.len, + user_info->nt_resp.buffer, user_info->lm_resp.len, + &ctr, &info3); + + cli_error(&cli, NULL, NULL, &nt_status); + if (nt_status != NT_STATUS_NOPROBLEMO) { + DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ +%s to Domain controller %s. Error was %s.\n", user_info->smb_username.str, user_info->domain.str, remote_machine, cli_errstr(&cli))); + } + + /* + * Here, if we really want it, we have lots of info about the user in info3. + */ + +#if 0 + /* + * We don't actually need to do this - plus it fails currently with + * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to + * send here. JRA. + */ + + if (nt_status == NT_STATUS_NOPROBLMO) { + if(cli_nt_logoff(&cli, &ctr) == False) { + DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ +%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); + nt_status = NT_STATUS_LOGON_FAILURE; + } + } +#endif /* 0 */ + + /* Note - once the cli stream is shutdown the mem_ctx used + to allocate the other_sids and gids structures has been deleted - so + these pointers are no longer valid..... */ + + cli_nt_session_close(&cli); + cli_ulogoff(&cli); + cli_shutdown(&cli); + return nt_status; +} + +/**************************************************************************** + Check for a valid username and password in security=domain mode. +****************************************************************************/ + +uint32 check_domain_security(const auth_usersupplied_info *user_info, + auth_serversupplied_info *server_info) +{ + uint32 nt_status = NT_STATUS_LOGON_FAILURE; + + if(lp_security() != SEC_DOMAIN) + return NT_STATUS_LOGON_FAILURE; + + nt_status = domain_client_validate(user_info, server_info, NULL); + + return nt_status; +} + + + diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c new file mode 100644 index 0000000000..c1bee6247c --- /dev/null +++ b/source3/smbd/auth_rhosts.c @@ -0,0 +1,165 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Main SMB reply routines + Copyright (C) Andrew Tridgell 1992-1998 + + 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; + + +/**************************************************************************** + Read the a hosts.equiv or .rhosts file and check if it + allows this user from this machine. +****************************************************************************/ + +static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) +{ + int plus_allowed = 1; + char *file_host; + char *file_user; + char **lines = file_lines_load(equiv_file, NULL); + int i; + + DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); + if (! lines) return False; + for (i=0; lines[i]; i++) { + char *buf = lines[i]; + trim_string(buf," "," "); + + if (buf[0] != '#' && buf[0] != '\n') + { + BOOL is_group = False; + int plus = 1; + char *bp = buf; + if (strcmp(buf, "NO_PLUS\n") == 0) + { + DEBUG(6, ("check_user_equiv NO_PLUS\n")); + plus_allowed = 0; + } + else { + if (buf[0] == '+') + { + bp++; + if (*bp == '\n' && plus_allowed) + { + /* a bare plus means everbody allowed */ + DEBUG(6, ("check_user_equiv everybody allowed\n")); + file_lines_free(lines); + return True; + } + } + else if (buf[0] == '-') + { + bp++; + plus = 0; + } + if (*bp == '@') + { + is_group = True; + bp++; + } + file_host = strtok(bp, " \t\n"); + file_user = strtok(NULL, " \t\n"); + DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", + file_user ? file_user : "(null)" )); + if (file_host && *file_host) + { + BOOL host_ok = False; + +#if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN) + if (is_group) + { + static char *mydomain = NULL; + if (!mydomain) + yp_get_default_domain(&mydomain); + if (mydomain && innetgr(file_host,remote,user,mydomain)) + host_ok = True; + } +#else + if (is_group) + { + DEBUG(1,("Netgroups not configured\n")); + continue; + } +#endif + + /* is it this host */ + /* the fact that remote has come from a call of gethostbyaddr + * means that it may have the fully qualified domain name + * so we could look up the file version to get it into + * a canonical form, but I would rather just type it + * in full in the equiv file + */ + if (!host_ok && !is_group && strequal(remote, file_host)) + host_ok = True; + + if (!host_ok) + continue; + + /* is it this user */ + if (file_user == 0 || strequal(user, file_user)) + { + DEBUG(5, ("check_user_equiv matched %s%s %s\n", + (plus ? "+" : "-"), file_host, + (file_user ? file_user : ""))); + file_lines_free(lines); + return (plus ? True : False); + } + } + } + } + } + file_lines_free(lines); + return False; +} + + +/**************************************************************************** +check for a possible hosts equiv or rhosts entry for the user +****************************************************************************/ +BOOL check_hosts_equiv(char *user) +{ + char *fname = NULL; + pstring rhostsfile; + struct passwd *pass = Get_Pwnam(user,True); + + if (!pass) + return(False); + + fname = lp_hosts_equiv(); + + /* note: don't allow hosts.equiv on root */ + if (fname && *fname && (pass->pw_uid != 0)) { + if (check_user_equiv(user,client_name(),fname)) + return(True); + } + + if (lp_use_rhosts()) + { + char *home = get_user_home_dir(user); + if (home) { + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); + if (check_user_equiv(user,client_name(),rhostsfile)) + return(True); + } + } + + return(False); +} diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c new file mode 100644 index 0000000000..dc1d924b3c --- /dev/null +++ b/source3/smbd/auth_server.c @@ -0,0 +1,244 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Authenticate to a remote server + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Bartlett 2001 + + 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; + +extern pstring global_myname; + +/**************************************************************************** + Return the client state structure. +****************************************************************************/ + +struct cli_state *server_client(void) +{ + static struct cli_state pw_cli; + return &pw_cli; +} + +/**************************************************************************** + Support for server level security. +****************************************************************************/ + +struct cli_state *server_cryptkey(void) +{ + struct cli_state *cli; + fstring desthost; + struct in_addr dest_ip; + char *p, *pserver; + BOOL connected_ok = False; + + cli = server_client(); + + if (!cli_initialise(cli)) + return NULL; + + pserver = strdup(lp_passwordserver()); + p = pserver; + + while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { + standard_sub_basic(desthost); + strupper(desthost); + + if(!resolve_name( desthost, &dest_ip, 0x20)) { + DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); + continue; + } + + if (ismyip(dest_ip)) { + DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); + continue; + } + + if (cli_connect(cli, desthost, &dest_ip)) { + DEBUG(3,("connected to password server %s\n",desthost)); + connected_ok = True; + break; + } + } + + free(pserver); + + if (!connected_ok) { + DEBUG(0,("password server not available\n")); + cli_shutdown(cli); + return NULL; + } + + if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) + return NULL; + + DEBUG(3,("got session\n")); + + if (!cli_negprot(cli)) { + DEBUG(1,("%s rejected the negprot\n",desthost)); + cli_shutdown(cli); + return NULL; + } + + if (cli->protocol < PROTOCOL_LANMAN2 || + !(cli->sec_mode & 1)) { + DEBUG(1,("%s isn't in user level security mode\n",desthost)); + cli_shutdown(cli); + return NULL; + } + + DEBUG(3,("password server OK\n")); + + return cli; +} + + +/**************************************************************************** + Validate a password with the password server. +****************************************************************************/ + +static uint32 server_validate(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +{ + struct cli_state *cli; + static unsigned char badpass[24]; + static fstring baduser; + static BOOL tested_password_server = False; + static BOOL bad_password_server = False; + uint32 nt_status = NT_STATUS_LOGON_FAILURE; + + cli = server_client(); + + if (!cli->initialised) { + DEBUG(1,("password server %s is not connected\n", cli->desthost)); + return(NT_STATUS_LOGON_FAILURE); + } + + if(badpass[0] == 0) + memset(badpass, 0x1f, sizeof(badpass)); + + if((user_info->nt_resp.len == sizeof(badpass)) && + !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) { + /* + * Very unlikely, our random bad password is the same as the users + * password. + */ + memset(badpass, badpass[0]+1, sizeof(badpass)); + } + + if(baduser[0] == 0) { + fstrcpy(baduser, INVALID_USER_PREFIX); + fstrcat(baduser, global_myname); + } + + /* + * Attempt a session setup with a totally incorrect password. + * If this succeeds with the guest bit *NOT* set then the password + * server is broken and is not correctly setting the guest bit. We + * need to detect this as some versions of NT4.x are broken. JRA. + */ + + /* I sure as hell hope that there arn't servers out there that take + * NTLMv2 and have this bug, as we don't test for that... + * - abartlet@samba.org + */ + + if(!tested_password_server) { + if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass), + (char *)badpass, sizeof(badpass), user_info->domain.str)) { + + /* + * We connected to the password server so we + * can say we've tested it. + */ + tested_password_server = True; + + if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { + DEBUG(0,("server_validate: password server %s allows users as non-guest \ +with a bad password.\n", cli->desthost)); + DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ +use this machine as the password server.\n")); + cli_ulogoff(cli); + + /* + * Password server has the bug. + */ + bad_password_server = True; + return NT_STATUS_LOGON_FAILURE; + } + cli_ulogoff(cli); + } + } else { + + /* + * We have already tested the password server. + * Fail immediately if it has the bug. + */ + + if(bad_password_server) { + DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \ +with a bad password.\n", cli->desthost)); + DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \ +use this machine as the password server.\n")); + return NT_STATUS_LOGON_FAILURE; + } + } + + /* + * Now we know the password server will correctly set the guest bit, or is + * not guest enabled, we can try with the real password. + */ + + if (!cli_session_setup(cli, user_info->smb_username.str, + user_info->lm_resp.buffer, + user_info->lm_resp.len, + user_info->nt_resp.buffer, + user_info->nt_resp.len, + user_info->domain.str)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + nt_status = NT_STATUS_LOGON_FAILURE; + } else { + nt_status = NT_STATUS_NOPROBLEMO; + } + + /* if logged in as guest then reject */ + if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); + nt_status = NT_STATUS_LOGON_FAILURE; + } + + cli_ulogoff(cli); + + return(nt_status); +} + +/**************************************************************************** + Check for a valid username and password in security=server mode. +****************************************************************************/ + +uint32 check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +{ + + if(lp_security() != SEC_SERVER) + return NT_STATUS_LOGON_FAILURE; + + return server_validate(user_info, server_info); + +} + + diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c new file mode 100644 index 0000000000..ce0b03d942 --- /dev/null +++ b/source3/smbd/auth_smbpasswd.c @@ -0,0 +1,229 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Password and authentication handling + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Andrew Bartlett 2001 + + 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; + +/**************************************************************************** +core of smb password checking routine. +****************************************************************************/ +static BOOL smb_pwd_check_ntlmv1(const uchar *password, + const uchar *part_passwd, + const uchar *c8, + uchar user_sess_key[16]) +{ + /* Finish the encryption of part_passwd. */ + uchar p24[24]; + + if (part_passwd == NULL) { + DEBUG(10,("No password set - DISALLOWING access\n")); + /* No password set - always false ! */ + return False; + } + + SMBOWFencrypt(part_passwd, c8, p24); + if (user_sess_key != NULL) + { + SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); + } + + + +#if DEBUG_PASSWORD + DEBUG(100,("Part password (P16) was |")); + dump_data(100, part_passwd, 16); + DEBUG(100,("Password from client was |")); + dump_data(100, password, 24); + DEBUG(100,("Given challenge was |")); + dump_data(100, c8, 8); + DEBUG(100,("Value from encryption was |")); + dump_data(100, p24, 24); +#endif + return (memcmp(p24, password, 24) == 0); +} + +/**************************************************************************** +core of smb password checking routine. +****************************************************************************/ +static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, + uchar *part_passwd, + uchar const *c8, + const char *user, const char *domain, + char *user_sess_key) +{ + /* Finish the encryption of part_passwd. */ + uchar kr[16]; + uchar resp[16]; + + if (part_passwd == NULL) + { + DEBUG(10,("No password set - DISALLOWING access\n")); + /* No password set - always False */ + return False; + } + + ntv2_owf_gen(part_passwd, user, domain, kr); + SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp); + if (user_sess_key != NULL) + { + SMBsesskeygen_ntv2(kr, resp, user_sess_key); + } + +#if DEBUG_PASSWORD + DEBUG(100,("Part password (P16) was |")); + dump_data(100, part_passwd, 16); + DEBUG(100,("Password from client was |")); + dump_data(100, password, pwd_len); + DEBUG(100,("Given challenge was |")); + dump_data(100, c8, 8); + DEBUG(100,("Value from encryption was |")); + dump_data(100, resp, 16); +#endif + + return (memcmp(resp, password, 16) == 0); +} + + +/**************************************************************************** + Do a specific test for an smb password being correct, given a smb_password and + the lanman and NT responses. +****************************************************************************/ +uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +{ + uint8 *nt_pw, *lm_pw; + + /* Quit if the account was disabled. */ + if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { + DEBUG(1,("Account for user '%s' was disabled.\n", user_info->smb_username.str)); + return(NT_STATUS_ACCOUNT_DISABLED); + } + + if (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) + { + if (lp_null_passwords()) + { + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user_info->smb_username.str)); + return(NT_STATUS_NOPROBLEMO); + } + else + { + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user_info->smb_username.str)); + return(NT_STATUS_LOGON_FAILURE); + } + } + + if (!user_info || !sampass) + return(NT_STATUS_LOGON_FAILURE); + + DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",user_info->smb_username.str)); + + nt_pw = pdb_get_nt_passwd(sampass); + + if (nt_pw != NULL) { + if ((user_info->nt_resp.len > 24 )) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); + if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, + user_info->nt_resp.len, + nt_pw, + user_info->chal, user_info->requested_username.str, + user_info->requested_domain.str, + server_info->session_key)) + { + return NT_STATUS_NOPROBLEMO; + } + DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); + + } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24 )) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, + nt_pw, user_info->chal, + server_info->session_key)) { + DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); + return NT_STATUS_NOPROBLEMO; + } else { + DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; + } + } + } + + lm_pw = pdb_get_lanman_passwd(sampass); + + if(lp_lanman_auth() && (lm_pw != NULL) && (user_info->lm_resp.len == 24 )) { + DEBUG(4,("smb_password_ok: Checking LM password\n")); + if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, + lm_pw, user_info->chal, + server_info->session_key)) { + DEBUG(4,("smb_password_ok: LM password check succeeded\n")); + return NT_STATUS_NOPROBLEMO; + } else { + DEBUG(4,("smb_password_ok: LM password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; + } + } + + return NT_STATUS_LOGON_FAILURE; +} + + +/**************************************************************************** +check if a username/password is OK assuming the password is a 24 byte +SMB hash +return True if the password is correct, False otherwise +****************************************************************************/ + +uint32 check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +{ + SAM_ACCOUNT *sampass=NULL; + BOOL ret; + uint32 nt_status; + + pdb_init_sam(&sampass); + + /* get the account information */ + ret = pdb_getsampwnam(sampass, user_info->smb_username.str); + if (ret == False) + { + DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->smb_username.str)); + pdb_free_sam(sampass); + return(NT_STATUS_NO_SUCH_USER); + } + + if ((nt_status = smb_password_ok(sampass, user_info, server_info)) != NT_STATUS_NOPROBLEMO) + { + pdb_free_sam(sampass); + return(nt_status); + } + + pdb_free_sam(sampass); + return nt_status; +} + + diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c new file mode 100644 index 0000000000..1c12a4322d --- /dev/null +++ b/source3/smbd/auth_util.c @@ -0,0 +1,141 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Authentication utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Bartlett 2001 + + 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; + +/* Data to do lanman1/2 password challenge. */ +static unsigned char saved_challenge[8]; +static BOOL challenge_sent=False; + +/******************************************************************* +Get the next challenge value - no repeats. +********************************************************************/ +void generate_next_challenge(char *challenge) +{ + unsigned char buf[8]; + + generate_random_buffer(buf,8,False); + memcpy(saved_challenge, buf, 8); + memcpy(challenge,buf,8); + challenge_sent = True; +} + +/******************************************************************* +set the last challenge sent, usually from a password server +********************************************************************/ +BOOL set_challenge(unsigned char *challenge) +{ + memcpy(saved_challenge,challenge,8); + challenge_sent = True; + return(True); +} + +/******************************************************************* +get the last challenge sent +********************************************************************/ +BOOL last_challenge(unsigned char *challenge) +{ + if (!challenge_sent) return(False); + memcpy(challenge,saved_challenge,8); + return(True); +} + + +/**************************************************************************** + Create a UNIX user on demand. +****************************************************************************/ + +static int smb_create_user(char *unix_user, char *homedir) +{ + pstring add_script; + int ret; + + pstrcpy(add_script, lp_adduser_script()); + if (! *add_script) return -1; + all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); + if (homedir) + all_string_sub(add_script, "%H", homedir, sizeof(pstring)); + ret = smbrun(add_script,NULL); + DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); + return ret; +} + +/**************************************************************************** + Delete a UNIX user on demand. +****************************************************************************/ + +static int smb_delete_user(char *unix_user) +{ + pstring del_script; + int ret; + + pstrcpy(del_script, lp_deluser_script()); + if (! *del_script) return -1; + all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); + ret = smbrun(del_script,NULL); + DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); + return ret; +} + +/**************************************************************************** + Add and Delete UNIX users on demand, based on NT_STATUS codes. +****************************************************************************/ + +void smb_user_control(char *unix_user, uint32 nt_status) +{ + struct passwd *pwd=NULL; + + if(nt_status == NT_STATUS_NOPROBLEMO) { + /* + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. + */ + if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) + smb_create_user(unix_user, NULL); + + if(lp_adduser_script() && pwd) { + SMB_STRUCT_STAT st; + + /* + * Also call smb_create_user if the users home directory + * doesn't exist. Used with winbindd to allow the script to + * create the home directory for a user mapped with winbindd. + */ + + if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) + smb_create_user(unix_user, pwd->pw_dir); + } + + } else if (nt_status == NT_STATUS_NO_SUCH_USER) { + /* + * User failed to validate ok against Domain controller. + * If the failure was "user doesn't exist" and admin + * wants us to try and delete that UNIX user on the fly, + * do so. + */ + if(lp_deluser_script() && smb_getpwnam(unix_user,True)) + smb_delete_user(unix_user); + } + +} diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index de6f5d789f..6410aa2da6 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -179,7 +179,10 @@ static int reply_nt1(char *outbuf) char *p, *q; if (lp_security() == SEC_SERVER) { + DEBUG(5,("attempting password server validation\n")); cli = server_cryptkey(); + } else { + DEBUG(5,("attempting local password validation\n")); } if (cli) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 743d6ebffe..4aa5a0211e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -25,52 +25,12 @@ extern int DEBUGLEVEL; extern int Protocol; extern struct in_addr ipzero; -BOOL global_machine_password_needs_changing = False; - /* users from session setup */ static pstring session_users=""; extern pstring global_myname; extern fstring global_myworkgroup; -/* Data to do lanman1/2 password challenge. */ -static unsigned char saved_challenge[8]; -static BOOL challenge_sent=False; - -/******************************************************************* -Get the next challenge value - no repeats. -********************************************************************/ -void generate_next_challenge(char *challenge) -{ - unsigned char buf[8]; - - generate_random_buffer(buf,8,False); - - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,8); - challenge_sent = True; -} - -/******************************************************************* -set the last challenge sent, usually from a password server -********************************************************************/ -BOOL set_challenge(unsigned char *challenge) -{ - memcpy(saved_challenge,challenge,8); - challenge_sent = True; - return(True); -} - -/******************************************************************* -get the last challenge sent -********************************************************************/ -static BOOL last_challenge(unsigned char *challenge) -{ - if (!challenge_sent) return(False); - memcpy(challenge,saved_challenge,8); - return(True); -} - /* this holds info on user ids that are already validated for this VC */ static user_struct *validated_users; static int next_vuid = VUID_OFFSET; @@ -341,287 +301,6 @@ void add_session_user(char *user) } -/**************************************************************************** -update the encrypted smbpasswd file from the plaintext username and password -*****************************************************************************/ -static BOOL update_smbpassword_file(char *user, char *password) -{ - SAM_ACCOUNT *sampass = NULL; - BOOL ret; - - pdb_init_sam(&sampass); - - become_root(); - ret = pdb_getsampwnam(sampass, user); - unbecome_root(); - - if(ret == False) { - DEBUG(0,("pdb_getsampwnam returned NULL\n")); - pdb_free_sam(sampass); - return False; - } - - /* - * Remove the account disabled flag - we are updating the - * users password from a login. - */ - pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED); - - /* Here, the flag is one, because we want to ignore the - XXXXXXX'd out password */ - ret = change_oem_password( sampass, password, True); - if (ret == False) { - DEBUG(3,("change_oem_password returned False\n")); - } - - pdb_free_sam(sampass); - return ret; -} - -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8) -{ - /* Finish the encryption of part_passwd. */ - unsigned char p21[21]; - unsigned char p24[24]; - - if (part_passwd == NULL) - { - DEBUG(10,("No password set - allowing access\n")); - - /* No password set - always true ! */ - return 1; - } - - memset(p21,'\0',21); - memcpy(p21,part_passwd,16); - E_P24(p21, c8, p24); -#if DEBUG_PASSWORD - { - int i; - DEBUG(100,("Part password (P16) was |")); - for(i = 0; i < 16; i++) - DEBUG(100,("%X ", (unsigned char)part_passwd[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Password from client was |")); - for(i = 0; i < 24; i++) - DEBUG(100,("%X ", (unsigned char)password[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Given challenge was |")); - for(i = 0; i < 8; i++) - DEBUG(100,("%X ", (unsigned char)c8[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Value from encryption was |")); - for(i = 0; i < 24; i++) - DEBUG(100,("%X ", (unsigned char)p24[i])); - DEBUG(100,("|\n")); - } -#endif - return (memcmp(p24, password, 24) == 0); -} - -/**************************************************************************** - Do a specific test for an smb password being correct, given a smb_password and - the lanman and NT responses. -****************************************************************************/ -BOOL smb_password_ok(SAM_ACCOUNT *sampass, uchar chal[8], - uchar lm_pass[24], uchar nt_pass[24]) -{ - uchar challenge[8]; - char* user_name; - uint8 *nt_pw, *lm_pw; - - if (!lm_pass || !sampass) - return(False); - - user_name = pdb_get_username(sampass); - - DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",user_name)); - - if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { - DEBUG(1,("smb_password_ok: account for user %s was disabled.\n", user_name)); - return(False); - } - - if (chal == NULL) { - DEBUG(5,("smb_password_ok: use last SMBnegprot challenge\n")); - if (!last_challenge(challenge)) { - DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); - return False; - } - } else { - DEBUG(5,("smb_password_ok: challenge received\n")); - memcpy(challenge, chal, 8); - } - - nt_pw = pdb_get_nt_passwd(sampass); - - if ((Protocol >= PROTOCOL_NT1) && (nt_pw != NULL)) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_password_check((char *)nt_pass, (uchar *)nt_pw, challenge)) { - DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); - return(True); - } - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); - } - - /* Try against the lanman password. pdb_get_lanman_passwd(sampass) == NULL - means no password, allow access. */ - - lm_pw = pdb_get_lanman_passwd(sampass); - - if((lm_pw == NULL) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) - { - DEBUG(4,("smb_password_ok: no password required for user %s\n",user_name)); - return True; - } - - if(lp_lanman_auth() && (lm_pw != NULL)) { - DEBUG(4,("smb_password_ok: Checking LM password\n")); - if(smb_password_check((char *)lm_pass,(uchar *)lm_pw, challenge)) { - DEBUG(4,("smb_password_ok: LM password check succeeded\n")); - return(True); - } - DEBUG(4,("smb_password_ok: LM password check failed\n")); - } - - return False; -} - - -/**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash -return True if the password is correct, False otherwise -****************************************************************************/ - -BOOL pass_check_smb(char *user, char *domain, uchar *chal, - uchar *lm_pwd, uchar *nt_pwd) -{ - struct passwd *pass; - SAM_ACCOUNT *sampass=NULL; - BOOL ret; - - if (!lm_pwd || !nt_pwd) - { - return(False); - } - - /* FIXME! this code looks to be unnecessary now that the passdb - validates that the username exists and has a valid uid */ - - /* I don't get this call here. I think it should be moved. - Need to check on it. --jerry */ - pass = smb_getpwnam(user,True); - - if (pass == NULL) - { - DEBUG(1,("Couldn't find user '%s' in UNIX password database.\n",user)); - return(False); - } - - pdb_init_sam(&sampass); - - /* get the account information */ - ret = pdb_getsampwnam(sampass, user); - if (ret == False) - { - DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user)); - pdb_free_sam(sampass); - return(False); - } - - /* Quit if the account was disabled. */ - if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { - DEBUG(1,("Account for user '%s' was disabled.\n", user)); - pdb_free_sam(sampass); - return(False); - } - - /* Ensure the uid's match - FIXME! This also seems unnecessary --jerry */ -#if 0 /* GWC */ - if (smb_pass->smb_userid != pass->pw_uid) - { - DEBUG(0,("Error : UNIX and SMB uids in password files do not match for user '%s'!\n", user)); - pdb_free_sam(sampass); - return(False); - } -#endif - - if (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) - { - if (lp_null_passwords()) - { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user)); - pdb_free_sam(sampass); - return(True); - } - else - { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user)); - pdb_free_sam(sampass); - return(False); - } - } - - if (smb_password_ok(sampass, chal, lm_pwd, nt_pwd)) - { - pdb_free_sam(sampass); - return(True); - } - - DEBUG(2,("pass_check_smb failed - invalid password for user [%s]\n", user)); - pdb_free_sam(sampass); - return False; -} - -/**************************************************************************** -check if a username/password pair is OK either via the system password -database or the encrypted SMB password database -return True if the password is correct, False otherwise -****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen) -{ - BOOL ret; - - if ((pwlen == 0) && !lp_null_passwords()) { - DEBUG(4,("Null passwords not allowed.\n")); - return False; - } - - if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { - /* if 24 bytes long assume it is an encrypted password */ - uchar challenge[8]; - - if (!last_challenge(challenge)) { - DEBUG(0,("Error: challenge not done for user=%s\n", user)); - return False; - } - - ret = pass_check_smb(user, global_myworkgroup, - challenge, (uchar *)password, (uchar *)password); - - /* - * Try with PAM (may not be compiled in - returns True if not. JRA). - * FIXME ! Should this be called if we're using winbindd ? What about - * non-local accounts ? JRA. - */ - - if (ret) - return (smb_pam_accountcheck(user) == NT_STATUS_NOPROBLEMO); - } - - return pass_check(user, password, pwlen, - lp_update_encrypted() ? - update_smbpassword_file : NULL); -} - /**************************************************************************** check if a username is valid ****************************************************************************/ @@ -660,9 +339,6 @@ BOOL user_ok(char *user,int snum) return(ret); } - - - /**************************************************************************** validate a group username entry. Return the username or NULL ****************************************************************************/ @@ -857,13 +533,6 @@ and given password ok\n", user)); ok = True; } - /* check for a rhosts entry */ - if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) { - ok = True; - DEBUG(3,("authorise_login: ACCEPTED: hosts equiv or rhosts entry for %s\n", - user)); - } - /* check the user= fields and the given password */ if (!ok && lp_username(snum)) { char *auser; @@ -918,744 +587,3 @@ and given password ok (%s)\n", user)); return(ok); } - -/**************************************************************************** - Read the a hosts.equiv or .rhosts file and check if it - allows this user from this machine. -****************************************************************************/ - -static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) -{ - int plus_allowed = 1; - char *file_host; - char *file_user; - char **lines = file_lines_load(equiv_file, NULL); - int i; - - DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); - if (! lines) return False; - for (i=0; lines[i]; i++) { - char *buf = lines[i]; - trim_string(buf," "," "); - - if (buf[0] != '#' && buf[0] != '\n') - { - BOOL is_group = False; - int plus = 1; - char *bp = buf; - if (strcmp(buf, "NO_PLUS\n") == 0) - { - DEBUG(6, ("check_user_equiv NO_PLUS\n")); - plus_allowed = 0; - } - else { - if (buf[0] == '+') - { - bp++; - if (*bp == '\n' && plus_allowed) - { - /* a bare plus means everbody allowed */ - DEBUG(6, ("check_user_equiv everybody allowed\n")); - file_lines_free(lines); - return True; - } - } - else if (buf[0] == '-') - { - bp++; - plus = 0; - } - if (*bp == '@') - { - is_group = True; - bp++; - } - file_host = strtok(bp, " \t\n"); - file_user = strtok(NULL, " \t\n"); - DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", - file_user ? file_user : "(null)" )); - if (file_host && *file_host) - { - BOOL host_ok = False; - -#if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN) - if (is_group) - { - static char *mydomain = NULL; - if (!mydomain) - yp_get_default_domain(&mydomain); - if (mydomain && innetgr(file_host,remote,user,mydomain)) - host_ok = True; - } -#else - if (is_group) - { - DEBUG(1,("Netgroups not configured\n")); - continue; - } -#endif - - /* is it this host */ - /* the fact that remote has come from a call of gethostbyaddr - * means that it may have the fully qualified domain name - * so we could look up the file version to get it into - * a canonical form, but I would rather just type it - * in full in the equiv file - */ - if (!host_ok && !is_group && strequal(remote, file_host)) - host_ok = True; - - if (!host_ok) - continue; - - /* is it this user */ - if (file_user == 0 || strequal(user, file_user)) - { - DEBUG(5, ("check_user_equiv matched %s%s %s\n", - (plus ? "+" : "-"), file_host, - (file_user ? file_user : ""))); - file_lines_free(lines); - return (plus ? True : False); - } - } - } - } - } - file_lines_free(lines); - return False; -} - - -/**************************************************************************** -check for a possible hosts equiv or rhosts entry for the user -****************************************************************************/ -BOOL check_hosts_equiv(char *user) -{ - char *fname = NULL; - pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user,True); - - if (!pass) - return(False); - - fname = lp_hosts_equiv(); - - /* note: don't allow hosts.equiv on root */ - if (fname && *fname && (pass->pw_uid != 0)) { - if (check_user_equiv(user,client_name(),fname)) - return(True); - } - - if (lp_use_rhosts()) - { - char *home = get_user_home_dir(user); - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(user,client_name(),rhostsfile)) - return(True); - } - } - - return(False); -} - - -/**************************************************************************** - Return the client state structure. -****************************************************************************/ - -struct cli_state *server_client(void) -{ - static struct cli_state pw_cli; - return &pw_cli; -} - -/**************************************************************************** - Support for server level security. -****************************************************************************/ - -struct cli_state *server_cryptkey(void) -{ - struct cli_state *cli; - fstring desthost; - struct in_addr dest_ip; - char *p, *pserver; - BOOL connected_ok = False; - - cli = server_client(); - - if (!cli_initialise(cli)) - return NULL; - - pserver = strdup(lp_passwordserver()); - p = pserver; - - while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { - standard_sub_basic(desthost); - strupper(desthost); - - if(!resolve_name( desthost, &dest_ip, 0x20)) { - DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); - continue; - } - - if (cli_connect(cli, desthost, &dest_ip)) { - DEBUG(3,("connected to password server %s\n",desthost)); - connected_ok = True; - break; - } - } - - free(pserver); - - if (!connected_ok) { - DEBUG(0,("password server not available\n")); - cli_shutdown(cli); - return NULL; - } - - if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) - return NULL; - - DEBUG(3,("got session\n")); - - if (!cli_negprot(cli)) { - DEBUG(1,("%s rejected the negprot\n",desthost)); - cli_shutdown(cli); - return NULL; - } - - if (cli->protocol < PROTOCOL_LANMAN2 || - !(cli->sec_mode & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",desthost)); - cli_shutdown(cli); - return NULL; - } - - DEBUG(3,("password server OK\n")); - - return cli; -} - -/**************************************************************************** - Validate a password with the password server. -****************************************************************************/ - -BOOL server_validate(char *user, char *domain, - char *pass, int passlen, - char *ntpass, int ntpasslen) -{ - struct cli_state *cli; - static unsigned char badpass[24]; - static fstring baduser; - static BOOL tested_password_server = False; - static BOOL bad_password_server = False; - - cli = server_client(); - - if (!cli->initialised) { - DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return(False); - } - - if(badpass[0] == 0) - memset(badpass, 0x1f, sizeof(badpass)); - - if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) { - /* - * Very unlikely, our random bad password is the same as the users - * password. - */ - memset(badpass, badpass[0]+1, sizeof(badpass)); - } - - if(baduser[0] == 0) { - fstrcpy(baduser, INVALID_USER_PREFIX); - fstrcat(baduser, global_myname); - } - - /* - * Attempt a session setup with a totally incorrect password. - * If this succeeds with the guest bit *NOT* set then the password - * server is broken and is not correctly setting the guest bit. We - * need to detect this as some versions of NT4.x are broken. JRA. - */ - - if(!tested_password_server) { - if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass), - (char *)badpass, sizeof(badpass), domain)) { - - /* - * We connected to the password server so we - * can say we've tested it. - */ - tested_password_server = True; - - if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { - DEBUG(0,("server_validate: password server %s allows users as non-guest \ -with a bad password.\n", cli->desthost)); - DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ -use this machine as the password server.\n")); - cli_ulogoff(cli); - - /* - * Password server has the bug. - */ - bad_password_server = True; - return False; - } - cli_ulogoff(cli); - } - } else { - - /* - * We have already tested the password server. - * Fail immediately if it has the bug. - */ - - if(bad_password_server) { - DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \ -with a bad password.\n", cli->desthost)); - DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \ -use this machine as the password server.\n")); - return False; - } - } - - /* - * Now we know the password server will correctly set the guest bit, or is - * not guest enabled, we can try with the real password. - */ - - if (!cli_session_setup(cli, user, pass, passlen, ntpass, ntpasslen, domain)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - return False; - } - - /* if logged in as guest then reject */ - if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); - cli_ulogoff(cli); - return(False); - } - - cli_ulogoff(cli); - - return(True); -} - -/*********************************************************************** - Connect to a remote machine for domain security authentication - given a name or IP address. -************************************************************************/ - -static BOOL connect_to_domain_password_server(struct cli_state *pcli, - char *server, unsigned char *trust_passwd) -{ - struct in_addr dest_ip; - fstring remote_machine; - - if(cli_initialise(pcli) == NULL) { - DEBUG(0,("connect_to_domain_password_server: unable to initialize client connection.\n")); - return False; - } - - if (is_ipaddress(server)) { - struct in_addr to_ip; - - /* we shouldn't have 255.255.255.255 forthe IP address of - a password server anyways */ - if ((to_ip.s_addr=inet_addr(server)) == 0xFFFFFFFF) { - DEBUG (0,("connect_to_domain_password_server: inet_addr(%s) returned 0xFFFFFFFF!\n", server)); - return False; - } - - if (!name_status_find(0x20, to_ip, remote_machine)) { - DEBUG(0, ("connect_to_domain_password_server: Can't " - "resolve name for IP %s\n", server)); - return False; - } - } else { - fstrcpy(remote_machine, server); - } - - standard_sub_basic(remote_machine); - strupper(remote_machine); - - if(!resolve_name( remote_machine, &dest_ip, 0x20)) { - DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n", remote_machine)); - cli_shutdown(pcli); - return False; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("connect_to_domain_password_server: Password server loop - not using password server %s\n", - remote_machine)); - cli_shutdown(pcli); - return False; - } - - if (!cli_connect(pcli, remote_machine, &dest_ip)) { - DEBUG(0,("connect_to_domain_password_server: unable to connect to SMB server on \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - if (!attempt_netbios_session_request(pcli, global_myname, remote_machine, &dest_ip)) { - DEBUG(0,("connect_to_password_server: machine %s rejected the NetBIOS \ -session request. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - return False; - } - - pcli->protocol = PROTOCOL_NT1; - - if (!cli_negprot(pcli)) { - DEBUG(0,("connect_to_domain_password_server: machine %s rejected the negotiate protocol. \ -Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - if (pcli->protocol != PROTOCOL_NT1) { - DEBUG(0,("connect_to_domain_password_server: machine %s didn't negotiate NT protocol.\n", - remote_machine)); - cli_shutdown(pcli); - return False; - } - - /* - * Do an anonymous session setup. - */ - - if (!cli_session_setup(pcli, "", "", 0, "", 0, "")) { - DEBUG(0,("connect_to_domain_password_server: machine %s rejected the session setup. \ -Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - if (!(pcli->sec_mode & 1)) { - DEBUG(1,("connect_to_domain_password_server: machine %s isn't in user level security mode\n", - remote_machine)); - cli_shutdown(pcli); - return False; - } - - if (!cli_send_tconX(pcli, "IPC$", "IPC", "", 1)) { - DEBUG(0,("connect_to_domain_password_server: machine %s rejected the tconX on the IPC$ share. \ -Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - /* - * We now have an anonymous connection to IPC$ on the domain password server. - */ - - /* - * Even if the connect succeeds we need to setup the netlogon - * pipe here. We do this as we may just have changed the domain - * account password on the PDC and yet we may be talking to - * a BDC that doesn't have this replicated yet. In this case - * a successful connect to a DC needs to take the netlogon connect - * into account also. This patch from "Bjart Kvarme" . - */ - - if(cli_nt_session_open(pcli, PIPE_NETLOGON) == False) { - DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); - cli_nt_session_close(pcli); - cli_ulogoff(pcli); - cli_shutdown(pcli); - return False; - } - - if (cli_nt_setup_creds(pcli, trust_passwd) == False) { - DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \ -%s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); - cli_nt_session_close(pcli); - cli_ulogoff(pcli); - cli_shutdown(pcli); - return(False); - } - - return True; -} - -/*********************************************************************** - Utility function to attempt a connection to an IP address of a DC. -************************************************************************/ - -static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, unsigned char *trust_passwd) -{ - fstring dc_name; - - /* - * Ignore addresses we have already tried. - */ - - if (ip_equal(ipzero, *ip)) - return False; - - if (!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) - return False; - - return connect_to_domain_password_server(pcli, dc_name, trust_passwd); -} - -/*********************************************************************** - We have been asked to dynamcially determine the IP addresses of - the PDC and BDC's for this DOMAIN, and query them in turn. -************************************************************************/ -static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd, time_t last_change_time) -{ - struct in_addr *ip_list = NULL; - int count = 0; - int i; - BOOL connected_ok = False; - time_t time_now = time(NULL); - BOOL use_pdc_only = False; - - /* - * If the time the machine password has changed - * was less than an hour ago then we need to contact - * the PDC only, as we cannot be sure domain replication - * has yet taken place. Bug found by Gerald (way to go - * Gerald !). JRA. - */ - - if (time_now - last_change_time < 3600) - use_pdc_only = True; - - if (!get_dc_list(use_pdc_only, lp_workgroup(), &ip_list, &count)) - return False; - - /* - * Firstly try and contact a PDC/BDC who has the same - * network address as any of our interfaces. - */ - for(i = 0; i < count; i++) { - if(!is_local_net(ip_list[i])) - continue; - - if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) - break; - - ip_list[i] = ipzero; /* Tried and failed. */ - } - - /* - * Secondly try and contact a random PDC/BDC. - */ - if(!connected_ok) { - i = (sys_random() % count); - - if (!(connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) - ip_list[i] = ipzero; /* Tried and failed. */ - } - - /* - * Finally go through the IP list in turn, ignoring any addresses - * we have already tried. - */ - if(!connected_ok) { - /* - * Try and connect to any of the other IP addresses in the PDC/BDC list. - * Note that from a WINS server the #1 IP address is the PDC. - */ - for(i = 0; i < count; i++) { - if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) - break; - } - } - - if(ip_list != NULL) - free((char *)ip_list); - - - return connected_ok; -} - -/*********************************************************************** - Do the same as security=server, but using NT Domain calls and a session - key from the machine password. If the server parameter is specified - use it, otherwise figure out a server from the 'password server' param. -************************************************************************/ - -BOOL domain_client_validate( char *user, char *domain, - char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen, - BOOL *user_exists, char *server) -{ - unsigned char local_challenge[8]; - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - unsigned char trust_passwd[16]; - fstring remote_machine; - char *p, *pserver; - NET_ID_INFO_CTR ctr; - NET_USER_INFO_3 info3; - struct cli_state cli; - uint32 smb_uid_low; - BOOL connected_ok = False; - time_t last_change_time; - - if(user_exists != NULL) - *user_exists = True; /* Only set false on a very specific error. */ - - /* - * Check that the requested domain is not our own machine name. - * If it is, we should never check the PDC here, we use our own local - * password file. - */ - - if(strequal( domain, global_myname)) { - DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); - return False; - } - - /* - * Next, check that the passwords given were encrypted. - */ - - if(((smb_apasslen != 24) && (smb_apasslen != 0)) || - ((smb_ntpasslen != 24) && (smb_ntpasslen != 0))) { - - /* - * Not encrypted - do so. - */ - - DEBUG(5,("domain_client_validate: User passwords not in encrypted format.\n")); - generate_random_buffer( local_challenge, 8, False); - SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response); - SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_response); - smb_apasslen = 24; - smb_ntpasslen = 24; - smb_apasswd = (char *)local_lm_response; - smb_ntpasswd = (char *)local_nt_response; - } else { - - /* - * Encrypted - get the challenge we sent for these - * responses. - */ - - if (!last_challenge(local_challenge)) { - DEBUG(0,("domain_client_validate: no challenge done - password failed\n")); - return False; - } - } - - /* - * Get the machine account password for our primary domain - */ - if (!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd, &last_change_time)) - { - DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", global_myworkgroup)); - return False; - } - - /* Test if machine password is expired and need to be changed */ - if (time(NULL) > last_change_time + lp_machine_password_timeout()) - { - global_machine_password_needs_changing = True; - } - - /* - * At this point, smb_apasswd points to the lanman response to - * the challenge in local_challenge, and smb_ntpasswd points to - * the NT response to the challenge in local_challenge. Ship - * these over the secure channel to a domain controller and - * see if they were valid. - */ - - ZERO_STRUCT(cli); - - /* - * Treat each name in the 'password server =' line as a potential - * PDC/BDC. Contact each in turn and try and authenticate. - */ - - if (server) { - p = server; - } else { - pserver = lp_passwordserver(); - if (! *pserver) pserver = "*"; - p = pserver; - } - - while (!connected_ok && - next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { - if(strequal(remote_machine, "*")) { - connected_ok = find_connect_pdc(&cli, trust_passwd, last_change_time); - } else { - connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); - } - } - - if (!connected_ok) { - DEBUG(0,("domain_client_validate: Domain password server not available.\n")); - cli_shutdown(&cli); - return False; - } - - /* We really don't care what LUID we give the user. */ - generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - - ZERO_STRUCT(info3); - - if(cli_nt_login_network(&cli, domain, user, smb_uid_low, (char *)local_challenge, - ((smb_apasslen != 0) ? smb_apasswd : NULL), - ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), - &ctr, &info3) == False) { - uint32 nt_rpc_err; - - cli_error(&cli, NULL, NULL, &nt_rpc_err); - DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - - if((nt_rpc_err == NT_STATUS_NO_SUCH_USER) && (user_exists != NULL)) - *user_exists = False; - - return False; - } - - /* - * Here, if we really want it, we have lots of info about the user in info3. - */ - -#if 0 - /* - * We don't actually need to do this - plus it fails currently with - * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to - * send here. JRA. - */ - - if(cli_nt_logoff(&cli, &ctr) == False) { - DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } -#endif /* 0 */ - - /* Note - once the cli stream is shutdown the mem_ctx used - to allocate the other_sids and gids structures has been deleted - so - these pointers are no longer valid..... */ - - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return True; -} diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 324734a79d..ab3fba9830 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -433,6 +433,11 @@ int reply_ioctl(connection_struct *conn, return outsize; } +/**************************************************************************** + This function breaks the authentication split. It needs sorting out. + I can't see why we can't hadle this INSIDE the check_password, as in then + end all it does it spit out an nt_status code. + ****************************************************************************/ /**************************************************************************** always return an error: it's just a matter of which one... ****************************************************************************/ @@ -444,7 +449,40 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out SAM_ACCOUNT *sam_trust_acct = NULL; uint16 acct_ctrl; BOOL ret; - + auth_usersupplied_info user_info; + auth_serversupplied_info server_info; + AUTH_STR domain, smb_username, wksta_name; + + ZERO_STRUCT(user_info); + ZERO_STRUCT(server_info); + ZERO_STRUCT(domain); + ZERO_STRUCT(smb_username); + ZERO_STRUCT(wksta_name); + + domain.str = lp_workgroup(); + domain.len = strlen(domain.str); + + user_info.requested_domain = domain; + user_info.domain = domain; + + smb_username.str = user; + smb_username.len = strlen(smb_username.str); + + user_info.requested_username = smb_username; /* For the time-being */ + user_info.smb_username = smb_username; + + user_info.wksta_name = wksta_name; + + user_info.lm_resp.buffer = (uint8 *)smb_passwd; + user_info.lm_resp.len = smb_passlen; + user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd; + user_info.nt_resp.len = smb_nt_passlen; + + if (!last_challenge(user_info.chal)) { + DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); + return NT_STATUS_LOGON_FAILURE; + } + pdb_init_sam(&sam_trust_acct); if (lp_security() == SEC_USER) { @@ -470,7 +508,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) { + if (!smb_password_ok(sam_trust_acct, &user_info, &server_info)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); pdb_free_sam(sam_trust_acct); @@ -503,173 +541,6 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR(0, NT_STATUS_LOGON_FAILURE)); } -/**************************************************************************** - Create a UNIX user on demand. -****************************************************************************/ - -int smb_create_user(char *unix_user, char *homedir) -{ - pstring add_script; - int ret; - - pstrcpy(add_script, lp_adduser_script()); - if (! *add_script) return -1; - all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); - if (homedir) - all_string_sub(add_script, "%H", homedir, sizeof(pstring)); - ret = smbrun(add_script,NULL); - DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); - return ret; -} - -/**************************************************************************** - Delete a UNIX user on demand. -****************************************************************************/ - -static int smb_delete_user(char *unix_user) -{ - pstring del_script; - int ret; - - pstrcpy(del_script, lp_deluser_script()); - if (! *del_script) return -1; - all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); - ret = smbrun(del_script,NULL); - DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); - return ret; -} - -/**************************************************************************** - Check user is in correct domain if required -****************************************************************************/ - -static BOOL check_domain_match(char *user, char *domain) -{ - /* - * If we aren't serving to trusted domains, we must make sure that - * the validation request comes from an account in the same domain - * as the Samba server - */ - - if (!lp_allow_trusted_domains() && - !strequal(lp_workgroup(), domain) ) { - DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain)); - return False; - } else { - return True; - } -} - -/**************************************************************************** - Check for a valid username and password in security=server mode. -****************************************************************************/ - -static BOOL check_server_security(char *orig_user, char *domain, char *unix_user, - char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen) -{ - BOOL ret = False; - - if(lp_security() != SEC_SERVER) - return False; - - if (!check_domain_match(orig_user, domain)) - return False; - - ret = server_validate(orig_user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen); - if(ret) { - struct passwd *pwd=NULL; - - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - * Note that we can never delete users when in server - * level security as we never know if it was a failure - * due to a bad password, or the user really doesn't exist. - */ - if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) { - smb_create_user(unix_user, NULL); - } - - if(lp_adduser_script() && pwd) { - SMB_STRUCT_STAT st; - - /* - * Also call smb_create_user if the users home directory - * doesn't exist. Used with winbindd to allow the script to - * create the home directory for a user mapped with winbindd. - */ - - if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) - smb_create_user(unix_user, pwd->pw_dir); - } - } - - return ret; -} - -/**************************************************************************** - Check for a valid username and password in security=domain mode. -****************************************************************************/ - -static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user, - char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen) -{ - BOOL ret = False; - BOOL user_exists = True; - struct passwd *pwd=NULL; - - if(lp_security() != SEC_DOMAIN) - return False; - - if (!check_domain_match(orig_user, domain)) - return False; - - ret = domain_client_validate(orig_user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen, - &user_exists, NULL); - - if(ret) { - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - */ - if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) - smb_create_user(unix_user, NULL); - - if(lp_adduser_script() && pwd) { - SMB_STRUCT_STAT st; - - /* - * Also call smb_create_user if the users home directory - * doesn't exist. Used with winbindd to allow the script to - * create the home directory for a user mapped with winbindd. - */ - - if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) - smb_create_user(unix_user, pwd->pw_dir); - } - - } else { - /* - * User failed to validate ok against Domain controller. - * If the failure was "user doesn't exist" and admin - * wants us to try and delete that UNIX user on the fly, - * do so. - */ - if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) - smb_delete_user(unix_user); - } - - return ret; -} - /**************************************************************************** Return a bad password error configured for the correct client type. ****************************************************************************/ @@ -701,8 +572,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstring smb_apasswd; int smb_ntpasslen = 0; pstring smb_ntpasswd; - BOOL valid_nt_password = False; - BOOL valid_lm_password = False; + BOOL valid_password = False; pstring user; pstring orig_user; fstring domain; @@ -926,50 +796,16 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int add_session_user(user); - /* - * Check with orig_user for security=server and - * security=domain. - */ - - if (!guest && !check_server_security(orig_user, domain, user, - smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) && - !check_domain_security(orig_user, domain, user, smb_apasswd, - smb_apasslen, smb_ntpasswd, smb_ntpasslen) && - !check_hosts_equiv(user)) - { - /* - * If we get here then the user wasn't guest and the remote - * authentication methods failed. Check the authentication - * methods on this local server. - * - * If an NT password was supplied try and validate with that - * first. This is superior as the passwords are mixed case - * 128 length unicode. - */ - - if(smb_ntpasslen) - { - if(!password_ok(user, smb_ntpasswd,smb_ntpasslen)) - DEBUG(2,("NT Password did not match for user '%s'!\n", user)); - else - valid_nt_password = True; - } - - - /* check the LanMan password only if necessary and if allowed - by lp_lanman_auth() */ - if (!valid_nt_password && lp_lanman_auth()) - { - DEBUG(2,("Defaulting to Lanman password for %s\n", user)); - valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen); - } - + if (!guest) { + valid_password = (pass_check_smb(user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO); /* The true branch will be executed if (1) the NT password failed (or was not tried), and (2) LanMan authentication failed (or was disabled) */ - if (!valid_nt_password && !valid_lm_password) + if (!valid_password) { if (lp_security() >= SEC_USER) { -- cgit From 384b522c9235ab538c23b64bdf9b3d57e4b15b53 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Aug 2001 13:24:38 +0000 Subject: This is the fix for the PAM bug I probably introduced in the previous commit, which I will confirm once I can find a box it would break on in the first place. (this is the pam accounts as nobody thing we had with 2.2.0) Andrew Bartlett (This used to be commit 9746ad12bd2d310e5c255c7ea491b87170b807af) --- source3/smbd/auth.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 851e1f53cf..4bfbfe65fe 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -131,7 +131,10 @@ uint32 check_password(const auth_usersupplied_info *user_info, auth_serversuppli } if (nt_status == NT_STATUS_NOPROBLEMO) { + /* We might not be root if we are an RPC call */ + become_root(); nt_status = smb_pam_accountcheck(user_info->smb_username.str); + unbecome_root(); } if (nt_status == NT_STATUS_NOPROBLEMO) { -- cgit From 4f415ef128528bcecddceee353d40dd3eedf64fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Aug 2001 19:32:33 +0000 Subject: The write zero bytes is an allocate, not set EOF. Jeremy. (This used to be commit 28b4ee1eba5fbfd83c000a0e485632c477b7bfa9) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ab3fba9830..a956261a78 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2477,7 +2477,8 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) { - nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos); + /* This is actually an allocate call, not set EOF. JRA */ + nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos); } else nwritten = write_file(fsp,data,startpos,numtowrite); -- cgit From 27bdf594fbdb1d403c4810f8ae5d00dcb3999e9f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 4 Aug 2001 00:24:54 +0000 Subject: Extra debug to see what errno is on write fail. Jeremy. (This used to be commit 352a02bf5c1b3ab9db92f86fd22f7a781a2c2996) --- source3/smbd/vfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 834d75266e..84aa81c38c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -362,6 +362,8 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) int save_errno = errno; fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, st.st_size); errno = save_errno; + DEBUG(10,("vfs_allocate_file_space: file %s, grow. write fail %s\n", + fsp->fsp_name, strerror(errno) )); return -1; } -- cgit From ac989cbe0777beb4def038ab0b552a64a0f1ba0c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 6 Aug 2001 09:35:08 +0000 Subject: Record the NT_STATUS constant rather than its number in the logfiles Fix typo in lmhosts manpage (This used to be commit 9fff946cf113b4858b730f5ba644d5648ba95027) --- source3/smbd/auth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 4bfbfe65fe..b679312cc4 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -140,7 +140,8 @@ uint32 check_password(const auth_usersupplied_info *user_info, auth_serversuppli if (nt_status == NT_STATUS_NOPROBLEMO) { DEBUG(5, ("check_password: Password for user %s suceeded\n", user_info->smb_username.str)); } else { - DEBUG(3, ("check_password: Password for user %s FAILED with error %d\n", user_info->smb_username.str, nt_status)); + DEBUG(3, ("check_password: Password for user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status))); + } return nt_status; -- cgit From f8d9da99832a43907beba8e97df8f74aa488ea28 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Aug 2001 19:21:23 +0000 Subject: Fix for getting allocate_file_space to return the correct errno. Jeremy. (This used to be commit 298595e8cb0ac4f5b5ad9a522cca79d030d7e0fc) --- source3/smbd/vfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 84aa81c38c..70e0c8657b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -357,7 +357,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),len_to_write); retlen = vfs_ops->write(fsp,fsp->fd,zero_space,current_len_to_write); - if (retlen != current_len_to_write) { + if (retlen <= 0) { /* Write fail - return to original size. */ int save_errno = errno; fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, st.st_size); @@ -370,7 +370,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) DEBUG(10,("vfs_allocate_file_space: file %s, grow. wrote %.0f\n", fsp->fsp_name, (double)current_len_to_write )); - len_to_write -= current_len_to_write; + len_to_write -= retlen; } set_filelen_write_cache(fsp, len); } -- cgit From b026e6edf290ec4cd77c2bb9a378630ddf7bc450 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Aug 2001 22:39:51 +0000 Subject: Added Gerald's lanman printing only change to HEAD. Jeremy. (This used to be commit b7bd512d9a9b543b9caf93c264776db6852c03ea) --- source3/smbd/lanman.c | 190 +++++++++++++++++++++++-------------------------- source3/smbd/nttrans.c | 72 ++----------------- 2 files changed, 95 insertions(+), 167 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index aaf8b3fafe..c84812cb83 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -845,120 +845,112 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char *QueueName = p; - int uLevel; - int count=0; - int snum; - char* str3; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - char* tmpdata=NULL; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char *QueueName = p; + int uLevel; + int count=0; + int snum; + char* str3; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + char* tmpdata=NULL; - memset((char *)&status,'\0',sizeof(status)); - memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); + memset((char *)&desc,'\0',sizeof(desc)); - p = skip_string(p,1); - uLevel = SVAL(p,0); - str3 = p + 4; + p = skip_string(p,1); + uLevel = SVAL(p,0); + str3 = p + 4; - /* remove any trailing username */ - if ((p = strchr_m(QueueName,'%'))) *p = 0; + /* remove any trailing username */ + if ((p = strchr_m(QueueName,'%'))) + *p = 0; - DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName)); + DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName)); - /* check it's a supported varient */ - if (!prefix_ok(str1,"zWrLh")) return False; - if (!check_printq_info(&desc,uLevel,str2,str3)) { - /* - * Patch from Scott Moomaw - * to return the 'invalid info level' error if an - * unknown level was requested. - */ - *rdata_len = 0; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,ERROR_INVALID_LEVEL); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,0); - return(True); - } + /* check it's a supported varient */ + if (!prefix_ok(str1,"zWrLh")) + return False; + if (!check_printq_info(&desc,uLevel,str2,str3)) { + /* + * Patch from Scott Moomaw + * to return the 'invalid info level' error if an + * unknown level was requested. + */ + *rdata_len = 0; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,ERROR_INVALID_LEVEL); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,0); + return(True); + } - snum = lp_servicenumber(QueueName); - if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } + snum = lp_servicenumber(QueueName); + if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { + int pnum = lp_servicenumber(PRINTERS_NAME); + if (pnum >= 0) { + lp_add_printer(QueueName,pnum); + snum = lp_servicenumber(QueueName); + } + } - if (snum < 0 || !VALID_SNUM(snum)) return(False); + if (snum < 0 || !VALID_SNUM(snum)) + return(False); - if (uLevel==52) { - count = get_printerdrivernumber(snum); - DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); - } else { - count = print_queue_status(snum, &queue,&status); - } + if (uLevel==52) { + count = get_printerdrivernumber(snum); + DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); + } else { + count = print_queue_status(snum, &queue,&status); + } - if (mdrcnt > 0) { - *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - } else { - /* - * Don't return data but need to get correct length - * init_package will return wrong size if buflen=0 - */ - desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *) malloc (desc.buflen); - } + if (mdrcnt > 0) { + *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *) malloc (desc.buflen); + } - if (init_package(&desc,1,count)) { - desc.subcount = count; - fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); - } else if(uLevel == 0) { -#if 0 - /* - * This is a *disgusting* hack. - * This is *so* bad that even I'm embarrassed (and I - * have no shame). Here's the deal : - * Until we get the correct SPOOLSS code into smbd - * then when we're running with NT SMB support then - * NT makes this call with a level of zero, and then - * immediately follows it with an open request to - * the \\SRVSVC pipe. If we allow that open to - * succeed then NT barfs when it cannot open the - * \\SPOOLSS pipe immediately after and continually - * whines saying "Printer name is invalid" forever - * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC - * to fail, then NT downgrades to using the downlevel code - * and everything works as well as before. I hate - * myself for adding this code.... JRA. - */ - - fail_next_srvsvc_open(); -#endif - } + if (init_package(&desc,1,count)) { + desc.subcount = count; + fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); + } - *rdata_len = desc.usedlen; + *rdata_len = desc.usedlen; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); + /* + * We must set the return code to ERRbuftoosmall + * in order to support lanman style printing with Win NT/2k + * clients --jerry + */ + if (!mdrcnt && lp_lanman_printing_only()) + desc.errcode = ERRbuftoosmall; + + *rdata_len = desc.usedlen; + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); - DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); + DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); - if (queue) free(queue); - if (tmpdata) free (tmpdata); + if (queue) + free(queue); + if (tmpdata) + free (tmpdata); - return(True); + return(True); } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f0403f011e..d342e44ca4 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -459,69 +459,6 @@ to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access, return smb_open_mode; } -#if 0 -/* - * This is a *disgusting* hack. - * This is *so* bad that even I'm embarrassed (and I - * have no shame). Here's the deal : - * Until we get the correct SPOOLSS code into smbd - * then when we're running with NT SMB support then - * NT makes this call with a level of zero, and then - * immediately follows it with an open request to - * the \\SRVSVC pipe. If we allow that open to - * succeed then NT barfs when it cannot open the - * \\SPOOLSS pipe immediately after and continually - * whines saying "Printer name is invalid" forever - * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC - * to fail, then NT downgrades to using the downlevel code - * and everything works as well as before. I hate - * myself for adding this code.... JRA. - * - * The HACK_FAIL_TIME define allows only a 2 - * second window for this to occur, just in - * case... - */ - -static BOOL fail_next_srvsvc = False; -static time_t fail_time; -#define HACK_FAIL_TIME 2 /* In seconds. */ - -void fail_next_srvsvc_open(void) -{ - /* Check client is WinNT proper; Win2K doesn't like Jeremy's hack - matty */ - if (get_remote_arch() != RA_WINNT) - return; - - fail_next_srvsvc = True; - fail_time = time(NULL); - DEBUG(10,("fail_next_srvsvc_open: setting up timeout close of \\srvsvc pipe for print fix.\n")); -} - -/* - * HACK alert.... see above - JRA. - */ - -BOOL should_fail_next_srvsvc_open(const char *pipename) -{ - - DEBUG(10,("should_fail_next_srvsvc_open: fail = %d, pipe = %s\n", - (int)fail_next_srvsvc, pipename)); - - if(fail_next_srvsvc && (time(NULL) > fail_time + HACK_FAIL_TIME)) { - fail_next_srvsvc = False; - fail_time = (time_t)0; - DEBUG(10,("should_fail_next_srvsvc_open: End of timeout close of \\srvsvc pipe for print fix.\n")); - } - - if(fail_next_srvsvc && strequal(pipename, "srvsvc")) { - fail_next_srvsvc = False; - DEBUG(10,("should_fail_next_srvsvc_open: Deliberately failing open of \\srvsvc pipe for print fix.\n")); - return True; - } - return False; -} -#endif - /**************************************************************************** Reply to an NT create and X call on a pipe. ****************************************************************************/ @@ -536,6 +473,10 @@ static int nt_open_pipe(char *fname, connection_struct *conn, DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); /* See if it is one we want to handle. */ + + if (lp_lanman_printing_only() && strequal(fname, "\\spoolss")) + return(ERROR(ERRSRV,ERRaccess)); + for( i = 0; known_nt_pipes[i]; i++ ) if( strequal(fname,known_nt_pipes[i])) break; @@ -546,11 +487,6 @@ static int nt_open_pipe(char *fname, connection_struct *conn, /* Strip \\ off the name. */ fname++; -#if 0 - if(should_fail_next_srvsvc_open(fname)) - return (ERROR(ERRSRV,ERRaccess)); -#endif - DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); p = open_rpc_pipe_p(fname, conn, vuid); -- cgit From d851036d8205a13f64f3a14db8a60e72fbeee7d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Aug 2001 00:36:10 +0000 Subject: Correctly report amount written in debug when allocation space. Jeremy. (This used to be commit d1e7cf6073f2dcb91ec468f5f249610dd9f1623a) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 70e0c8657b..9709fc6a20 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -368,7 +368,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) } DEBUG(10,("vfs_allocate_file_space: file %s, grow. wrote %.0f\n", - fsp->fsp_name, (double)current_len_to_write )); + fsp->fsp_name, (double)retlen )); len_to_write -= retlen; } -- cgit From 0c218e1abe237e23014332b014ec06f2e9d27e5e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Aug 2001 01:19:32 +0000 Subject: Added fixes to return correct error codes on space allocation fail. Jeremy. (This used to be commit 3bf2419f4b7a9d46a1d48062212a6a6579c22b92) --- source3/smbd/reply.c | 31 ++++++++++++++++++++++++++++++- source3/smbd/trans2.c | 2 +- 2 files changed, 31 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a956261a78..d31c83da9b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2442,8 +2442,32 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int siz } /**************************************************************************** - reply to a write + Return correct error for space allocation fail. ****************************************************************************/ + +int allocate_space_error(char *inbuf,char *outbuf, int errno_val) +{ + errno = errno_val; + if (!(global_client_caps & CAP_STATUS32)) + return (UNIXERROR(ERRHRD,ERRdiskfull)); + + /* Use more specific WNT/W2K error codes. */ +#ifdef EDQUOT + if (errno_val == ENOSPC || errno_val == EDQUOT) { +#else + if (errno_val == ENOSPC) { +#endif + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0,errno == ENOSPC ? NT_STATUS_DISK_FULL : NT_STATUS_QUOTA_EXCEEDED)); + } + + return (UNIXERROR(ERRHRD,ERRdiskfull)); +} + +/**************************************************************************** + Reply to a write. +****************************************************************************/ + int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize) { size_t numtowrite; @@ -2479,6 +2503,11 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d if(numtowrite == 0) { /* This is actually an allocate call, not set EOF. JRA */ nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos); + if (nwritten < 0) { + int ret = allocate_space_error(inbuf, outbuf, errno); + END_PROFILE(SMBwrite); + return ret; + } } else nwritten = write_file(fsp,data,startpos,numtowrite); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bb7ca6e0f8..26b376ec2d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1928,7 +1928,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } if (ret == -1) - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return allocate_space_error(inbuf, outbuf, errno); sbuf.st_size = size; break; -- cgit From 64c24ebf6d0b159a744739cf14b1b45fd3dda01d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Aug 2001 19:18:27 +0000 Subject: Always return NT_STATUS_DISK_FULL, even for quota errors. Jeremy. (This used to be commit e4a295b730b3d1ee784c896611d184c7699c74e7) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d31c83da9b..3ba1d4eea9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2458,7 +2458,7 @@ int allocate_space_error(char *inbuf,char *outbuf, int errno_val) if (errno_val == ENOSPC) { #endif SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0,errno == ENOSPC ? NT_STATUS_DISK_FULL : NT_STATUS_QUOTA_EXCEEDED)); + return(ERROR(0,NT_STATUS_DISK_FULL)); } return (UNIXERROR(ERRHRD,ERRdiskfull)); -- cgit From 0897979a8b0976e03a84ccaf6a70cbaa62bbd195 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 8 Aug 2001 03:25:47 +0000 Subject: Some better debugs for our security=server code. I want to track down why we occasionally don't make the connection to the server. (This used to be commit 08e99f4c12ad8747a8fd0e47ed4165cea428128d) --- source3/smbd/negprot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 6410aa2da6..5bc3522506 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -182,12 +182,14 @@ static int reply_nt1(char *outbuf) DEBUG(5,("attempting password server validation\n")); cli = server_cryptkey(); } else { - DEBUG(5,("attempting local password validation\n")); + DEBUG(5,("not attempting password server validation\n")); } if (cli) { DEBUG(3,("using password server validation\n")); doencrypt = ((cli->sec_mode & 2) != 0); + } else { + DEBUG(3,("not using password server validation\n")); } if (doencrypt) { -- cgit From 3dbd870d37e66e2a63ecd671a6fd6f96753027b6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 9 Aug 2001 12:52:05 +0000 Subject: Try to set the socket options early for some OSs (like Sol 8) where they can't be set after the listen(). Andrew Bartlett (This used to be commit 23b6772a2454ff3b480807a4ca8f58e8a0dc0c81) --- source3/smbd/server.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6e9b9a4828..13071a5b65 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -158,7 +158,11 @@ max can be %d\n", s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); if(s == -1) return False; - /* ready to listen */ + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + if (listen(s, 5) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); close(s); @@ -178,6 +182,9 @@ max can be %d\n", return(False); /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + if (listen(s, 5) == -1) { DEBUG(0,("open_sockets: listen: %s\n", strerror(errno))); -- cgit From f8d3cac8af0185eca2995e524c62f064ab9b4017 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 9 Aug 2001 15:53:49 +0000 Subject: a few cleanups while mergeing the passdb code into 2.2 (This used to be commit ef01739708479c43f529c646dd136ee5670b08f9) --- source3/smbd/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index b679312cc4..94008e4d00 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -45,7 +45,7 @@ static BOOL update_smbpassword_file(char *user, char *password) unbecome_root(); if(ret == False) { - DEBUG(0,("pdb_getsampwnam returned NULL\n")); + DEBUG(0,("update_smbpassword_file: pdb_getsampwnam failed to locate %s\n", user)); pdb_free_sam(sampass); return False; } -- cgit From 541f2b73bcb1621f6660266a0165a3d4f3aee521 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Aug 2001 19:22:51 +0000 Subject: Fix inspired by Don @ HP. Close down password server connection if keepalive fails. Jeremy. (This used to be commit 1f6e3d18cdf460eb2569b737813f94d22680553e) --- source3/smbd/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dd2318b58a..65fa600be4 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1104,7 +1104,10 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t /* also send a keepalive to the password server if its still connected */ if (cli && cli->initialised) - send_keepalive(cli->fd); + if (!send_keepalive(cli->fd)) { + DEBUG( 2, ( "password server keepalive failed.\n")); + cli_shutdown(cli); + } last_keepalive_sent_time = t; } -- cgit From c604830585336ac0ad42dff4bb240fa709fb1d4c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Aug 2001 20:01:35 +0000 Subject: Fixed wrong placement of allocate code :-(. Changed alignment offset to 1 to allow netmon to parse ok. Jeremy. (This used to be commit fd89261a2c74910bd1cf8271d862a7b050b49f32) --- source3/smbd/trans2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 26b376ec2d..a1e95bce3b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -54,7 +54,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, char *pp = params; char *pd = pdata; int params_sent_thistime, data_sent_thistime, total_sent_thistime; - int alignment_offset = 3; + int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */ int data_alignment_offset = 0; /* Initially set the wcnt area to be 10 - this is true for all @@ -1925,12 +1925,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } else { ret = vfs_allocate_file_space(fsp, size); } - } + if (ret == -1) + return allocate_space_error(inbuf, outbuf, errno); - if (ret == -1) - return allocate_space_error(inbuf, outbuf, errno); + sbuf.st_size = size; + } - sbuf.st_size = size; break; } -- cgit From de5f42c9d9172592779fa2504d44544e3b6b1c0d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 10 Aug 2001 04:27:26 +0000 Subject: merge from 2.2 (This used to be commit 6ab0e949d18b97ea7177175a4e6abb5ba076db98) --- source3/smbd/lanman.c | 2 +- source3/smbd/nttrans.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index c84812cb83..fe3516ee9d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -933,7 +933,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, * in order to support lanman style printing with Win NT/2k * clients --jerry */ - if (!mdrcnt && lp_lanman_printing_only()) + if (!mdrcnt && lp_disable_spoolss()) desc.errcode = ERRbuftoosmall; *rdata_len = desc.usedlen; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d342e44ca4..f0195fc0dd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -474,7 +474,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn, /* See if it is one we want to handle. */ - if (lp_lanman_printing_only() && strequal(fname, "\\spoolss")) + if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) return(ERROR(ERRSRV,ERRaccess)); for( i = 0; known_nt_pipes[i]; i++ ) -- cgit From 4bbd1ddb274438e00f83fffa2051d8f7d6c2b17c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 10 Aug 2001 05:50:47 +0000 Subject: More constant conversions. (This used to be commit 00703d306f14a5977df75cb04ee34ae8628ed40e) --- source3/smbd/lanman.c | 4 ++-- source3/smbd/trans2.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fe3516ee9d..ad7e8aac86 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -883,7 +883,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, *rdata_len = 0; *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,ERROR_INVALID_LEVEL); + SSVALS(*rparam,0,ERRunknownlevel); SSVAL(*rparam,2,0); SSVAL(*rparam,4,0); return(True); @@ -989,7 +989,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, *rdata_len = 0; *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,ERROR_INVALID_LEVEL); + SSVALS(*rparam,0,ERRunknownlevel); SSVAL(*rparam,2,0); SSVAL(*rparam,4,0); return(True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a1e95bce3b..2c0286cf0a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1374,7 +1374,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); + return(ERROR(ERRDOS,ERReasnotsupported)); } memset((char *)pdata,'\0',data_size); @@ -1813,7 +1813,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (total_data > 4 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); + return(ERROR(ERRDOS,ERReasnotsupported)); } switch (info_level) -- cgit From 62f7f6a022dea6fd4fbe514dcb3154bda334a07f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 10 Aug 2001 06:01:11 +0000 Subject: Use the new client error api. (This used to be commit 688da3c41dd944f7f69083518d25e9edbc55406f) --- source3/smbd/auth_domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index 4bf0a05d7f..e94ea13edc 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -360,7 +360,7 @@ uint32 domain_client_validate(const auth_usersupplied_info *user_info, user_info->nt_resp.buffer, user_info->lm_resp.len, &ctr, &info3); - cli_error(&cli, NULL, NULL, &nt_status); + nt_status = cli_nt_error(&cli); if (nt_status != NT_STATUS_NOPROBLEMO) { DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ %s to Domain controller %s. Error was %s.\n", user_info->smb_username.str, user_info->domain.str, remote_machine, cli_errstr(&cli))); -- cgit From 6ad80352dd2523c310258de3211a2af0f1763d2a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 12 Aug 2001 11:19:57 +0000 Subject: This patch does a number of things, mostly smaller than they look :-) In particuar, it moves the domain_client_validate stuff out of auth_domain.c to somwhere where they (I hope) they can be shared with winbind better. (This may need some work) The main purpose of this patch was however to improve some of the internal documentation and to correctly place become_root()/unbecome_root() calls within the code. Finally this patch moves some more of auth.c into other files, auth_unix.c in this case. Andrew Bartlett (This used to be commit ea1c547ac880def29f150de2172c95213509350e) --- source3/smbd/auth.c | 83 +++------- source3/smbd/auth_domain.c | 374 +++--------------------------------------- source3/smbd/auth_rhosts.c | 21 +++ source3/smbd/auth_smbpasswd.c | 10 +- source3/smbd/auth_unix.c | 85 ++++++++++ 5 files changed, 153 insertions(+), 420 deletions(-) create mode 100644 source3/smbd/auth_unix.c (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 94008e4d00..bbcf34e8ca 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -27,46 +27,6 @@ extern int DEBUGLEVEL; extern pstring global_myname; - -/**************************************************************************** -update the encrypted smbpasswd file from the plaintext username and password - -this ugly hack needs to die, but not quite yet... -*****************************************************************************/ -static BOOL update_smbpassword_file(char *user, char *password) -{ - SAM_ACCOUNT *sampass = NULL; - BOOL ret; - - pdb_init_sam(&sampass); - - become_root(); - ret = pdb_getsampwnam(sampass, user); - unbecome_root(); - - if(ret == False) { - DEBUG(0,("update_smbpassword_file: pdb_getsampwnam failed to locate %s\n", user)); - pdb_free_sam(sampass); - return False; - } - - /* - * Remove the account disabled flag - we are updating the - * users password from a login. - */ - pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED); - - /* Here, the flag is one, because we want to ignore the - XXXXXXX'd out password */ - ret = change_oem_password( sampass, password, True); - if (ret == False) { - DEBUG(3,("change_oem_password returned False\n")); - } - - pdb_free_sam(sampass); - return ret; -} - /**************************************************************************** Check user is in correct domain if required ****************************************************************************/ @@ -88,21 +48,29 @@ static BOOL check_domain_match(char *user, char *domain) } } +/**************************************************************************** + Check a users password, as given in the user-info struct and return various + interesting details in the server_info struct. + + This functions does NOT need to be in a become_root()/unbecome_root() pair + as it makes the calls itself when needed. +****************************************************************************/ uint32 check_password(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { uint32 nt_status = NT_STATUS_LOGON_FAILURE; - + BOOL done_pam = False; + DEBUG(3, ("check_password: Checking password for user %s with the new password interface\n", user_info->smb_username.str)); - if (check_hosts_equiv(user_info->smb_username.str)) { - nt_status = NT_STATUS_NOPROBLEMO; - } - if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { return NT_STATUS_LOGON_FAILURE; } + if (nt_status != NT_STATUS_NOPROBLEMO) { + nt_status = check_rhosts_security(user_info, server_info); + } + if ((lp_security() == SEC_DOMAIN) && (nt_status != NT_STATUS_NOPROBLEMO)) { nt_status = check_domain_security(user_info, server_info); } @@ -115,28 +83,23 @@ uint32 check_password(const auth_usersupplied_info *user_info, auth_serversuppli smb_user_control(user_info->smb_username.str, nt_status); } - if ((nt_status != NT_STATUS_NOPROBLEMO) - && (user_info->plaintext_password.len > 0) - && (!lp_plaintext_to_smbpasswd())) { - return (pass_check(user_info->smb_username.str, - user_info->plaintext_password.str, - user_info->plaintext_password.len, - lp_update_encrypted() ? - update_smbpassword_file : NULL) - ? NT_STATUS_NOPROBLEMO : NT_STATUS_LOGON_FAILURE); - } - if (nt_status != NT_STATUS_NOPROBLEMO) { - nt_status = check_smbpasswd_security(user_info, server_info); + if ((user_info->plaintext_password.len > 0) + && (!lp_plaintext_to_smbpasswd())) { + nt_status = check_unix_security(user_info, server_info); + done_pam = True; + } else { + nt_status = check_smbpasswd_security(user_info, server_info); + } } - - if (nt_status == NT_STATUS_NOPROBLEMO) { + + if ((nt_status == NT_STATUS_NOPROBLEMO) && !done_pam) { /* We might not be root if we are an RPC call */ become_root(); nt_status = smb_pam_accountcheck(user_info->smb_username.str); unbecome_root(); } - + if (nt_status == NT_STATUS_NOPROBLEMO) { DEBUG(5, ("check_password: Password for user %s suceeded\n", user_info->smb_username.str)); } else { diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index e94ea13edc..a2e3c7a9b5 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -23,392 +23,56 @@ #include "includes.h" extern int DEBUGLEVEL; -extern struct in_addr ipzero; BOOL global_machine_password_needs_changing = False; -extern pstring global_myname; - -/*********************************************************************** - Connect to a remote machine for domain security authentication - given a name or IP address. - ***********************************************************************/ - -static BOOL connect_to_domain_password_server(struct cli_state *pcli, - char *server, unsigned char *trust_passwd) -{ - struct in_addr dest_ip; - fstring remote_machine; - - if(cli_initialise(pcli) == NULL) { - DEBUG(0,("connect_to_domain_password_server: unable to initialize client connection.\n")); - return False; - } - - if (is_ipaddress(server)) { - struct in_addr to_ip; - - /* we shouldn't have 255.255.255.255 forthe IP address of - a password server anyways */ - if ((to_ip.s_addr=inet_addr(server)) == 0xFFFFFFFF) { - DEBUG (0,("connect_to_domain_password_server: inet_addr(%s) returned 0xFFFFFFFF!\n", server)); - return False; - } - - if (!name_status_find(0x20, to_ip, remote_machine)) { - DEBUG(0, ("connect_to_domain_password_server: Can't " - "resolve name for IP %s\n", server)); - return False; - } - } else { - fstrcpy(remote_machine, server); - } - - standard_sub_basic(remote_machine); - strupper(remote_machine); - - if(!resolve_name( remote_machine, &dest_ip, 0x20)) { - DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n", remote_machine)); - cli_shutdown(pcli); - return False; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("connect_to_domain_password_server: Password server loop - not using password server %s\n", - remote_machine)); - cli_shutdown(pcli); - return False; - } - - if (!cli_connect(pcli, remote_machine, &dest_ip)) { - DEBUG(0,("connect_to_domain_password_server: unable to connect to SMB server on \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - if (!attempt_netbios_session_request(pcli, global_myname, remote_machine, &dest_ip)) { - DEBUG(0,("connect_to_password_server: machine %s rejected the NetBIOS \ -session request. Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - return False; - } - - pcli->protocol = PROTOCOL_NT1; - - if (!cli_negprot(pcli)) { - DEBUG(0,("connect_to_domain_password_server: machine %s rejected the negotiate protocol. \ -Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - if (pcli->protocol != PROTOCOL_NT1) { - DEBUG(0,("connect_to_domain_password_server: machine %s didn't negotiate NT protocol.\n", - remote_machine)); - cli_shutdown(pcli); - return False; - } - - /* - * Do an anonymous session setup. - */ - - if (!cli_session_setup(pcli, "", "", 0, "", 0, "")) { - DEBUG(0,("connect_to_domain_password_server: machine %s rejected the session setup. \ -Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - if (!(pcli->sec_mode & 1)) { - DEBUG(1,("connect_to_domain_password_server: machine %s isn't in user level security mode\n", - remote_machine)); - cli_shutdown(pcli); - return False; - } - - if (!cli_send_tconX(pcli, "IPC$", "IPC", "", 1)) { - DEBUG(0,("connect_to_domain_password_server: machine %s rejected the tconX on the IPC$ share. \ -Error was : %s.\n", remote_machine, cli_errstr(pcli) )); - cli_shutdown(pcli); - return False; - } - - /* - * We now have an anonymous connection to IPC$ on the domain password server. - */ - - /* - * Even if the connect succeeds we need to setup the netlogon - * pipe here. We do this as we may just have changed the domain - * account password on the PDC and yet we may be talking to - * a BDC that doesn't have this replicated yet. In this case - * a successful connect to a DC needs to take the netlogon connect - * into account also. This patch from "Bjart Kvarme" . - */ - - if(cli_nt_session_open(pcli, PIPE_NETLOGON) == False) { - DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); - cli_nt_session_close(pcli); - cli_ulogoff(pcli); - cli_shutdown(pcli); - return False; - } - - if (cli_nt_setup_creds(pcli, trust_passwd) == False) { - DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \ -%s. Error was : %s.\n", remote_machine, cli_errstr(pcli))); - cli_nt_session_close(pcli); - cli_ulogoff(pcli); - cli_shutdown(pcli); - return(False); - } - - return True; -} - -/*********************************************************************** - Utility function to attempt a connection to an IP address of a DC. -************************************************************************/ - -static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, - unsigned char *trust_passwd) -{ - fstring dc_name; - - /* - * Ignore addresses we have already tried. - */ - - if (ip_equal(ipzero, *ip)) - return False; - - if (!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) - return False; - - return connect_to_domain_password_server(pcli, dc_name, trust_passwd); -} - -/*********************************************************************** - We have been asked to dynamcially determine the IP addresses of - the PDC and BDC's for this DOMAIN, and query them in turn. -************************************************************************/ -static BOOL find_connect_pdc(struct cli_state *pcli, - unsigned char *trust_passwd, - time_t last_change_time) -{ - struct in_addr *ip_list = NULL; - int count = 0; - int i; - BOOL connected_ok = False; - time_t time_now = time(NULL); - BOOL use_pdc_only = False; - - /* - * If the time the machine password has changed - * was less than an hour ago then we need to contact - * the PDC only, as we cannot be sure domain replication - * has yet taken place. Bug found by Gerald (way to go - * Gerald !). JRA. - */ - - if (time_now - last_change_time < 3600) - use_pdc_only = True; - - if (!get_dc_list(use_pdc_only, lp_workgroup(), &ip_list, &count)) - return False; - - /* - * Firstly try and contact a PDC/BDC who has the same - * network address as any of our interfaces. - */ - for(i = 0; i < count; i++) { - if(!is_local_net(ip_list[i])) - continue; - - if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) - break; - - ip_list[i] = ipzero; /* Tried and failed. */ - } - - /* - * Secondly try and contact a random PDC/BDC. - */ - if(!connected_ok) { - i = (sys_random() % count); - - if (!(connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) - ip_list[i] = ipzero; /* Tried and failed. */ - } - - /* - * Finally go through the IP list in turn, ignoring any addresses - * we have already tried. - */ - if(!connected_ok) { - /* - * Try and connect to any of the other IP addresses in the PDC/BDC list. - * Note that from a WINS server the #1 IP address is the PDC. - */ - for(i = 0; i < count; i++) { - if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd))) - break; - } - } - - if(ip_list != NULL) - free((char *)ip_list); - - - return connected_ok; -} - -/*********************************************************************** - Do the same as security=server, but using NT Domain calls and a session - key from the machine password. If the server parameter is specified - use it, otherwise figure out a server from the 'password server' param. -************************************************************************/ +/**************************************************************************** + Check for a valid username and password in security=domain mode. +****************************************************************************/ -uint32 domain_client_validate(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info, - char *server) +uint32 check_domain_security(const auth_usersupplied_info *user_info, + auth_serversupplied_info *server_info) { - unsigned char trust_passwd[16]; - fstring remote_machine; + uint32 nt_status = NT_STATUS_LOGON_FAILURE; char *p, *pserver; - NET_ID_INFO_CTR ctr; - NET_USER_INFO_3 info3; - struct cli_state cli; - uint32 smb_uid_low; - BOOL connected_ok = False; + unsigned char trust_passwd[16]; time_t last_change_time; - uint32 nt_status; - - /* - * Check that the requested domain is not our own machine name. - * If it is, we should never check the PDC here, we use our own local - * password file. - */ - if(strequal(user_info->domain.str, global_myname)) { - DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n")); + if(lp_security() != SEC_DOMAIN) return NT_STATUS_LOGON_FAILURE; - } + + become_root(); /* * Get the machine account password for our primary domain */ + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) { DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup())); + unbecome_root(); return NT_STATUS_LOGON_FAILURE; } + unbecome_root(); + /* Test if machine password is expired and need to be changed */ if (time(NULL) > last_change_time + lp_machine_password_timeout()) { global_machine_password_needs_changing = True; } - /* - * At this point, smb_apasswd points to the lanman response to - * the challenge in local_challenge, and smb_ntpasswd points to - * the NT response to the challenge in local_challenge. Ship - * these over the secure channel to a domain controller and - * see if they were valid. - */ - - ZERO_STRUCT(cli); - /* * Treat each name in the 'password server =' line as a potential * PDC/BDC. Contact each in turn and try and authenticate. */ - if (server) { - p = server; - } else { - pserver = lp_passwordserver(); - if (! *pserver) pserver = "*"; - p = pserver; - } - - while (!connected_ok && - next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { - if(strequal(remote_machine, "*")) { - connected_ok = find_connect_pdc(&cli, trust_passwd, last_change_time); - } else { - connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); - } - } - - if (!connected_ok) { - DEBUG(0,("domain_client_validate: Domain password server not available.\n")); - cli_shutdown(&cli); - return NT_STATUS_LOGON_FAILURE; - } - - /* We really don't care what LUID we give the user. */ - generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - - ZERO_STRUCT(info3); - - cli_nt_login_network(&cli, user_info->domain.str, user_info->smb_username.str, smb_uid_low, user_info->chal, - user_info->lm_resp.buffer, user_info->lm_resp.len, - user_info->nt_resp.buffer, user_info->lm_resp.len, - &ctr, &info3); - - nt_status = cli_nt_error(&cli); - if (nt_status != NT_STATUS_NOPROBLEMO) { - DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user_info->smb_username.str, user_info->domain.str, remote_machine, cli_errstr(&cli))); - } - - /* - * Here, if we really want it, we have lots of info about the user in info3. - */ - -#if 0 - /* - * We don't actually need to do this - plus it fails currently with - * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to - * send here. JRA. - */ - - if (nt_status == NT_STATUS_NOPROBLMO) { - if(cli_nt_logoff(&cli, &ctr) == False) { - DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); - nt_status = NT_STATUS_LOGON_FAILURE; - } - } -#endif /* 0 */ - - /* Note - once the cli stream is shutdown the mem_ctx used - to allocate the other_sids and gids structures has been deleted - so - these pointers are no longer valid..... */ - - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return nt_status; -} - -/**************************************************************************** - Check for a valid username and password in security=domain mode. -****************************************************************************/ - -uint32 check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) -{ - uint32 nt_status = NT_STATUS_LOGON_FAILURE; - - if(lp_security() != SEC_DOMAIN) - return NT_STATUS_LOGON_FAILURE; + pserver = lp_passwordserver(); + if (! *pserver) pserver = "*"; + p = pserver; - nt_status = domain_client_validate(user_info, server_info, NULL); + nt_status = domain_client_validate(user_info, server_info, + p, trust_passwd, last_change_time); return nt_status; } diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index c1bee6247c..f11f9cf777 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -163,3 +163,24 @@ BOOL check_hosts_equiv(char *user) return(False); } + +/**************************************************************************** + Check for a valid .rhosts/hosts.equiv entry for this user +****************************************************************************/ + +uint32 check_rhosts_security(const auth_usersupplied_info *user_info, + auth_serversupplied_info *server_info) +{ + uint32 nt_status = NT_STATUS_LOGON_FAILURE; + + become_root(); + if (check_hosts_equiv(user_info->smb_username.str)) { + nt_status = NT_STATUS_NOPROBLEMO; + } + unbecome_root(); + + return nt_status; +} + + + diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index ce0b03d942..927a262dc6 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -208,7 +208,11 @@ uint32 check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_se pdb_init_sam(&sampass); /* get the account information */ + + become_root(); ret = pdb_getsampwnam(sampass, user_info->smb_username.str); + unbecome_root(); + if (ret == False) { DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->smb_username.str)); @@ -216,11 +220,7 @@ uint32 check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_se return(NT_STATUS_NO_SUCH_USER); } - if ((nt_status = smb_password_ok(sampass, user_info, server_info)) != NT_STATUS_NOPROBLEMO) - { - pdb_free_sam(sampass); - return(nt_status); - } + nt_status = smb_password_ok(sampass, user_info, server_info); pdb_free_sam(sampass); return nt_status; diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c new file mode 100644 index 0000000000..89e670747f --- /dev/null +++ b/source3/smbd/auth_unix.c @@ -0,0 +1,85 @@ +/* + Unix SMB/Netbios implementation. + Version 2.2 + Password and authentication handling + Copyright (C) Andrew Bartlett 2001 + + 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; + +/**************************************************************************** +update the encrypted smbpasswd file from the plaintext username and password + +this ugly hack needs to die, but not quite yet... +*****************************************************************************/ +static BOOL update_smbpassword_file(char *user, char *password) +{ + SAM_ACCOUNT *sampass = NULL; + BOOL ret; + + pdb_init_sam(&sampass); + + become_root(); + ret = pdb_getsampwnam(sampass, user); + unbecome_root(); + + if(ret == False) { + DEBUG(0,("pdb_getsampwnam returned NULL\n")); + pdb_free_sam(sampass); + return False; + } + + /* + * Remove the account disabled flag - we are updating the + * users password from a login. + */ + pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED); + + /* Here, the flag is one, because we want to ignore the + XXXXXXX'd out password */ + ret = change_oem_password( sampass, password, True); + if (ret == False) { + DEBUG(3,("change_oem_password returned False\n")); + } + + pdb_free_sam(sampass); + return ret; +} + + +/**************************************************************************** +check if a username/password is OK assuming the password +in PLAIN TEXT +****************************************************************************/ + +uint32 check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +{ + uint32 nt_status; + + become_root(); + nt_status = (pass_check(user_info->smb_username.str, user_info->plaintext_password.str, + user_info->plaintext_password.len, + lp_update_encrypted() ? update_smbpassword_file : NULL) + ? NT_STATUS_NOPROBLEMO : NT_STATUS_LOGON_FAILURE); + unbecome_root(); + + return nt_status; +} + + -- cgit From 2e783a47076bd0994b6ce86df7ec967bc1c2da63 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 12 Aug 2001 17:30:01 +0000 Subject: this is a big global fix for the ptr = Realloc(ptr, size) bug. many possible mem leaks, and segfaults fixed. someone should port this fix to 2.2 also. (This used to be commit fa8e55b8b465114ce209344965c1ca0333b84db9) --- source3/smbd/lanman.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index ad7e8aac86..6408bbff9e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1123,10 +1123,16 @@ static int get_server_info(uint32 servertype, if (!*ptr) continue; if (count == alloced) { + struct srv_info_struct *ts; + alloced += 10; - (*servers) = (struct srv_info_struct *) + ts = (struct srv_info_struct *) Realloc(*servers,sizeof(**servers)*alloced); - if (!(*servers)) return(0); + if (!ts) { + DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); + return(0); + } + else *servers = ts; memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); } s = &(*servers)[count]; -- cgit From 90d2460cf0e644e82650763c502332e5adad27e7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 05:38:44 +0000 Subject: One less getpwnam() call... Andrew Bartlett (This used to be commit 204da7ba96b0c562bab5e5536728a0378077bdc7) --- source3/smbd/password.c | 13 +++---------- source3/smbd/reply.c | 4 +++- 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 4aa5a0211e..b4d22a3850 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -203,10 +203,9 @@ tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest) + char *domain,BOOL guest, char* full_name) { user_struct *vuser = NULL; - struct passwd *pwfile; /* for getting real name from passwd file */ /* Ensure no vuid gets registered in share level security. */ if(lp_security() == SEC_SHARE) @@ -243,6 +242,8 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, fstrcpy(vuser->user.unix_name,unix_name); fstrcpy(vuser->user.smb_name,requested_name); fstrcpy(vuser->user.domain,domain); + fstrcpy(vuser->user.full_name, full_name); + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name)); vuser->n_groups = 0; vuser->groups = NULL; @@ -260,14 +261,6 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, DLIST_ADD(validated_users, vuser); - DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); - - DEBUG(3, ("Clearing default real name\n")); - if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); - fstrcpy(vuser->user.full_name, pwfile->pw_gecos); - } - if (!session_claim(vuser->vuid)) { DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid)); invalidate_vuid(vuser->vuid); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3ba1d4eea9..47a363ae8d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -567,6 +567,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int int sess_vuid; gid_t gid; uid_t uid; + char* full_name; int smb_bufsize; int smb_apasslen = 0; pstring smb_apasswd; @@ -879,6 +880,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } gid = pw->pw_gid; uid = pw->pw_uid; + full_name = pw->pw_gecos; } if (guest) @@ -887,7 +889,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest); + sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name); if (sess_vuid == -1) { return(ERROR(ERRDOS,ERRnoaccess)); -- cgit From a0171765ff080ea0510f8c4475348e6b33044b9b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 06:06:56 +0000 Subject: Style cleanup for the last vuid change. Style, doco and DEBUG() fixes for auth_smbpasswd.c (In particular for the account control call). Andrew Bartlett (This used to be commit 3d91c119420973d7dd1af416a1e26efa113dc626) --- source3/smbd/auth_smbpasswd.c | 13 ++++++++----- source3/smbd/password.c | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 927a262dc6..27cb801c33 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -112,14 +112,17 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { uint8 *nt_pw, *lm_pw; + uint16 acct_ctrl; + acct_ctrl = pdb_get_acct_ctrl(sampass); + /* Quit if the account was disabled. */ - if(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { + if(acct_ctrl & ACB_DISABLED) { DEBUG(1,("Account for user '%s' was disabled.\n", user_info->smb_username.str)); return(NT_STATUS_ACCOUNT_DISABLED); } - if (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) + if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) { @@ -155,7 +158,7 @@ uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_ { return NT_STATUS_NOPROBLEMO; } - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); + DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24 )) { /* We have the NT MD4 hash challenge available - see if we can @@ -195,8 +198,8 @@ uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_ /**************************************************************************** check if a username/password is OK assuming the password is a 24 byte -SMB hash -return True if the password is correct, False otherwise +SMB hash supplied in the user_info structure +return an NT_STATUS constant. ****************************************************************************/ uint32 check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b4d22a3850..bbdd0c3bf5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -203,7 +203,7 @@ tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest, char* full_name) + char *domain,BOOL guest, char *full_name) { user_struct *vuser = NULL; -- cgit From 578a39d44f532a211169a7635043e2dfc18b3c65 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 07:03:27 +0000 Subject: smbd/auth_server: Doco, we want to use cli_nt_error here soon smbd/password.c: We don't use globals here anymore smbd/reply.c: Tidyness, global_myworkgroup must die! smbd/service.c: Move some of the make_connection code into a helper function. (This used to be commit 15c87e404fcaff9e360a40b8b673938c6e611daf) --- source3/smbd/auth_server.c | 1 + source3/smbd/password.c | 3 -- source3/smbd/reply.c | 5 ++-- source3/smbd/service.c | 73 +++++++++++++++++++++++++++------------------- 4 files changed, 46 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index dc1d924b3c..1960fc1cfb 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -211,6 +211,7 @@ use this machine as the password server.\n")); user_info->nt_resp.len, user_info->domain.str)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + /* Make this cli_nt_error() when the conversion is in */ nt_status = NT_STATUS_LOGON_FAILURE; } else { nt_status = NT_STATUS_NOPROBLEMO; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index bbdd0c3bf5..51df7a95a2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -28,9 +28,6 @@ extern struct in_addr ipzero; /* users from session setup */ static pstring session_users=""; -extern pstring global_myname; -extern fstring global_myworkgroup; - /* this holds info on user ids that are already validated for this VC */ static user_struct *validated_users; static int next_vuid = VUID_OFFSET; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 47a363ae8d..ee71854687 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -37,7 +37,6 @@ extern BOOL case_preserve; extern BOOL short_case_preserve; extern userdom_struct current_user_info; extern pstring global_myname; -extern fstring global_myworkgroup; extern int global_oplock_break; uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; @@ -800,7 +799,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!guest) { valid_password = (pass_check_smb(user, domain, smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO); + smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO); /* The true branch will be executed if (1) the NT password failed (or was not tried), and @@ -862,7 +861,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int p = smb_buf(outbuf); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); set_message_end(outbuf,p); /* perhaps grab OS version here?? */ } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 13a6a387ae..fe0f95ba6a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -213,6 +213,47 @@ int find_service(char *service) } +/**************************************************************************** + do some basic sainity checks on the share. + This function modifies dev, ecode. +****************************************************************************/ +static BOOL share_sanity_checks(int snum, char* service, char *dev, int *ecode) +{ + + if (!lp_snum_ok(snum) || + !check_access(smbd_server_fd(), + lp_hostsallow(snum), lp_hostsdeny(snum))) { + *ecode = ERRaccess; + return False; + } + + /* you can only connect to the IPC$ service as an ipc device */ + if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) + pstrcpy(dev,"IPC"); + + if (*dev == '?' || !*dev) { + if (lp_print_ok(snum)) { + pstrcpy(dev,"LPT1:"); + } else { + pstrcpy(dev,"A:"); + } + } + + /* if the request is as a printer and you can't print then refuse */ + strupper(dev); + if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { + DEBUG(1,("Attempt to connect to non-printer as a printer\n")); + *ecode = ERRinvdevice; + return False; + } + + /* Behave as a printer if we are supposed to */ + if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { + pstrcpy(dev, "LPT1:"); + } + return True; +} + /**************************************************************************** make a connection to a service ****************************************************************************/ @@ -268,37 +309,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int } } - if (!lp_snum_ok(snum) || - !check_access(smbd_server_fd(), - lp_hostsallow(snum), lp_hostsdeny(snum))) { - *ecode = ERRaccess; - return NULL; - } - - /* you can only connect to the IPC$ service as an ipc device */ - if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) - pstrcpy(dev,"IPC"); - - if (*dev == '?' || !*dev) { - if (lp_print_ok(snum)) { - pstrcpy(dev,"LPT1:"); - } else { - pstrcpy(dev,"A:"); - } - } - - /* if the request is as a printer and you can't print then refuse */ - strupper(dev); - if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { - DEBUG(1,("Attempt to connect to non-printer as a printer\n")); - *ecode = ERRinvdevice; + if (!share_sanity_checks(snum, service, dev, ecode)) { return NULL; - } - - /* Behave as a printer if we are supposed to */ - if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { - pstrcpy(dev, "LPT1:"); - } + } /* lowercase the user name */ strlower(user); -- cgit From 7c332851b0ac4eab77f6e449cefd48f119c7ddf6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 07:47:10 +0000 Subject: Restore a debug I think I dropped earlier (This used to be commit dc635bde2262b248f58d3ce52c2575dae8546571) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 51df7a95a2..036cdbc55b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -253,6 +253,8 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, /* Create an NT_USER_TOKEN struct for this user. */ vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups, guest); + DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); + next_vuid++; num_validated_vuids++; -- cgit From 67967749a2ed584de3b0d670094724021eafc50b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 07:48:25 +0000 Subject: Move read only check into a helper funcion. Ensure conn->service is set before we use it to find a share's details. (This used to be commit 7dc716f174c38e73b8e6d07130a1bc39f4499ce3) --- source3/smbd/service.c | 90 ++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index fe0f95ba6a..5bb535f884 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -254,6 +254,37 @@ static BOOL share_sanity_checks(int snum, char* service, char *dev, int *ecode) return True; } + +/**************************************************************************** + readonly share? +****************************************************************************/ +static void set_read_only(connection_struct *conn) +{ + char *service = lp_servicename(conn->service); + conn->read_only = lp_readonly(conn->service); + + { + char **list; + + lp_list_copy(&list, lp_readlist(conn->service)); + if(list && lp_list_substitute(list, "%S", service)) { + if (user_in_list(conn->user, list)) + conn->read_only = True; + } + else DEBUG(0, ("ERROR: read list substitution failed\n")); + if (list) lp_list_free(&list); + + lp_list_copy(&list, lp_writelist(conn->service)); + if(list && lp_list_substitute(list, "%S", service)) { + if (user_in_list(conn->user, list)) + conn->read_only = False; + } + else DEBUG(0, ("ERROR: write list substitution failed\n")); + if (list) lp_list_free(&list); + } +} + + /**************************************************************************** make a connection to a service ****************************************************************************/ @@ -346,46 +377,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } - conn->read_only = lp_readonly(snum); - - - { - char **list; - - lp_list_copy(&list, lp_readlist(snum)); - if(list && lp_list_substitute(list, "%S", service)) { - if (user_in_list(user, list)) - conn->read_only = True; - } - else DEBUG(0, ("ERROR: read list substitution failed\n")); - if (list) lp_list_free(&list); - - lp_list_copy(&list, lp_writelist(snum)); - if(list && lp_list_substitute(list, "%S", service)) { - if (user_in_list(user, list)) - conn->read_only = False; - } - else DEBUG(0, ("ERROR: write list substitution failed\n")); - if (list) lp_list_free(&list); - } - - /* admin user check */ - - /* JRA - original code denied admin user if the share was - marked read_only. Changed as I don't think this is needed, - but old code left in case there is a problem here. - */ - if (user_in_list(user, lp_admin_users(snum)) -#if 0 - && !conn->read_only -#endif - ) { - conn->admin_user = True; - DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); - } else { - conn->admin_user = False; - } - conn->force_user = force; conn->vuid = vuid; conn->uid = pass->pw_uid; @@ -405,6 +396,25 @@ connection_struct *make_connection(char *service,char *user,char *password, int string_set(&conn->user,user); conn->nt_user_token = NULL; + set_read_only(conn); + + /* admin user check */ + + /* JRA - original code denied admin user if the share was + marked read_only. Changed as I don't think this is needed, + but old code left in case there is a problem here. + */ + if (user_in_list(user, lp_admin_users(snum)) +#if 0 + && !conn->read_only +#endif + ) { + conn->admin_user = True; + DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); + } else { + conn->admin_user = False; + } + /* * If force user is true, then store the * given userid and also the primary groupid -- cgit From 327fda27eddfb1be7f0e344e86cca438c103c6ea Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 08:12:33 +0000 Subject: Move admin user check into a helper function. Formatting fixes. (This used to be commit 6fd8eb08c12d0446ab639becf8825d26bce8eb8a) --- source3/smbd/service.c | 53 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 5bb535f884..3e29c8cf58 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -285,6 +285,37 @@ static void set_read_only(connection_struct *conn) } +/**************************************************************************** + admin user check +****************************************************************************/ +static void set_admin_user(connection_struct *conn) +{ + /* admin user check */ + + /* JRA - original code denied admin user if the share was + marked read_only. Changed as I don't think this is needed, + but old code left in case there is a problem here. + */ + if (user_in_list(conn->user,lp_admin_users(conn->service)) +#if 0 + && !conn->read_only +#endif + ) { + conn->admin_user = True; + DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user)); + } else { + conn->admin_user = False; + } + +#if 0 /* This done later, for now */ + /* admin users always run as uid=0 */ + if (conn->admin_user) { + conn->uid = 0; + } +#endif +} + + /**************************************************************************** make a connection to a service ****************************************************************************/ @@ -381,7 +412,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->vuid = vuid; conn->uid = pass->pw_uid; conn->gid = pass->pw_gid; - safe_strcpy(conn->client_address, client_addr(), sizeof(conn->client_address)-1); + safe_strcpy(conn->client_address, client_addr(), + sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = time(NULL); conn->service = snum; @@ -398,23 +430,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int set_read_only(conn); - /* admin user check */ - - /* JRA - original code denied admin user if the share was - marked read_only. Changed as I don't think this is needed, - but old code left in case there is a problem here. - */ - if (user_in_list(user, lp_admin_users(snum)) -#if 0 - && !conn->read_only -#endif - ) { - conn->admin_user = True; - DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); - } else { - conn->admin_user = False; - } - + set_admin_user(conn); + /* * If force user is true, then store the * given userid and also the primary groupid -- cgit From 9ed5f60a5b385d01e441c53318295fd32fefe0d6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 08:44:04 +0000 Subject: Move the claim_connection stuff till a little later in the process. (You don't have to clean up somthing you haven't done yet...) (This used to be commit ba76564c2a06bf7feefdaf9ef06cbf77c776b6e6) --- source3/smbd/service.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 3e29c8cf58..524b647b5e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -527,17 +527,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int initialise_groups(conn->user, conn->uid, conn->gid); get_current_groups(&conn->ngroups,&conn->groups); - /* check number of connections */ - if (!claim_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn)), - False)) { - DEBUG(1,("too many connections - rejected\n")); - *ecode = ERRnoresource; - conn_free(conn); - return NULL; - } - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups, guest); @@ -557,8 +546,6 @@ connection_struct *make_connection(char *service,char *user,char *password, int *ecode = ERRaccess; DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", service )); - yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); - conn_free(conn); return NULL; } else { conn->read_only = True; @@ -569,11 +556,20 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); - yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); - conn_free(conn); return NULL; } + /* check number of connections */ + if (!claim_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn)), + False)) { + DEBUG(1,("too many connections - rejected\n")); + *ecode = ERRnoresource; + conn_free(conn); + return NULL; + } + /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { pstring cmd; @@ -583,7 +579,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); - yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); + yield_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn))); conn_free(conn); *ecode = ERRsrverror; return NULL; -- cgit From 8db28234c548cc4a381f93981df607ffe816c664 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Aug 2001 08:57:58 +0000 Subject: OK, so not freeing these was a mistake. I'll try to be less exuberent next time :-) (This used to be commit 8c3cf2db95a0fcf48b21274cac93f13abb42d4bf) --- source3/smbd/service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 524b647b5e..edac97194e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -546,6 +546,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int *ecode = ERRaccess; DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", service )); + conn_free(conn); return NULL; } else { conn->read_only = True; @@ -556,6 +557,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); + conn_free(conn); return NULL; } -- cgit From 11ce0f4d2d493702386c0bd49c8e2dd2aad84d56 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Aug 2001 05:15:26 +0000 Subject: a bunch of fixes from the sflight to seattle in particular: - fixed NT status code for a bunch of ops - fixed handling of protocol levels in ms_fnmatch (This used to be commit 3eba9606f71f90bfd9820af26f8676277ed22390) --- source3/smbd/password.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 036cdbc55b..8e85ef3389 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -22,7 +22,6 @@ #include "includes.h" extern int DEBUGLEVEL; -extern int Protocol; extern struct in_addr ipzero; /* users from session setup */ -- cgit From f9ce2028104fcb1694bc3e8f8d4b7ac3ec8c972e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Aug 2001 21:11:55 +0000 Subject: two fixes for NT clients -> share level Samba server (This used to be commit a25911d58c752350b62b205cfb0d6fc5b1c90cef) --- source3/smbd/auth.c | 3 ++- source3/smbd/reply.c | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index bbcf34e8ca..cb0d54bf9b 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -157,7 +157,8 @@ uint32 pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], memcpy(user_info.chal, chal, 8); - if (lm_pwd_len >= 24 || (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) { + if ((lm_pwd_len >= 24 || nt_pwd_len >= 24) || + (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) { /* if 24 bytes long assume it is an encrypted password */ user_info.lm_resp.buffer = (uint8 *)lm_pwd; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ee71854687..eb97382750 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -632,7 +632,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int passlen1 = MIN(passlen1, MAX_PASS_LEN); passlen2 = MIN(passlen2, MAX_PASS_LEN); - if(!doencrypt) { + if (!doencrypt) { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. @@ -716,6 +716,14 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int return bad_password_error(inbuf, outbuf); } + if (lp_security() == SEC_SHARE) { + /* in share level we should ignore any passwords */ + smb_ntpasslen = 0; + smb_apasslen = 0; + guest = True; + } + + DEBUG(3,("sesssetupX:name=[%s]\n",user)); /* If name ends in $ then I think it's asking about whether a */ -- cgit From 68525e9021832a74608f2dc3e0247317e713e384 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 20 Aug 2001 22:01:44 +0000 Subject: Add comment to clarify why we call this twice. (This used to be commit afece03d023b2905c27e147516b61487a7503028) --- source3/smbd/auth.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index cb0d54bf9b..d33bc225e6 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -230,6 +230,8 @@ BOOL password_ok(char *user, char *password, int pwlen) return False; } + /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as + required. */ if (pass_check_smb(user, lp_workgroup(), NULL, 0, password, pwlen) == NT_STATUS_NOPROBLEMO) { return True; } -- cgit From e6a6dee0272a170848d3b9c177bf3839214d0a20 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 21 Aug 2001 01:25:45 +0000 Subject: This is Jeremy pretending to be Volker, 'cos the link from Seattle is having problems. I've added 3 things here to work on the fcntl spin problem. 1). Check *all* tdb return codes... :-). 2). If we're asking ourselves to break an oplock, and we can't find a fsp pointer that matches the entry, this is a *logic bug* and we should abort and panic so someone with gdb can pick up the pieces. 3). After we've broken an oplock, ensure that the entry itself has been removed, and if not remove it ourselves. This should not be neccessary in a correctly working environmen,t, but will provide an added layer of robustness in error situations. 4). I hate german keyboards :-) :-). Jeremy. (This used to be commit 1c94fa80646f9e31377fbb41332fe4780f550cab) --- source3/smbd/open.c | 10 ++++++++++ source3/smbd/oplock.c | 13 +++++++++++++ 2 files changed, 23 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a32e032921..143aa934a6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -464,6 +464,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T */ do { + share_mode_entry broken_entry; broke_oplock = False; *p_all_current_opens_are_level_II = True; @@ -506,6 +507,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } broke_oplock = True; + broken_entry = *share_entry; break; } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { @@ -525,6 +527,14 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); + if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { + DEBUG(0,("open_mode_check: cannot delete entry when breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", broken_entry.op_type, fname, (unsigned int)dev, (double)inode)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } num_share_modes = get_share_modes(conn, dev, inode, &old_shares); oplock_contention_count++; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index cc2581375e..4bc8fce698 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -903,6 +903,19 @@ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); DEBUG(5,("request_oplock_break: breaking our own oplock\n")); +#if 1 /* JRA PARANOIA TEST.... */ + { + files_struct *fsp = file_find_dit(dev, inode, &share_entry->time); + if (!fsp) { + DEBUG(0,("request_oplock_break: PANIC : breaking our own oplock requested for \ +dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x and no fsp found !\n", + (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, + (int)share_entry->time.tv_usec )); + smb_panic("request_oplock_break: no fsp found for our own oplock\n"); + } + } +#endif /* END JRA PARANOIA TEST... */ + /* Call oplock break direct. */ return oplock_break(dev, inode, &share_entry->time, True); } -- cgit From 252742f2b021e8d7a06c8c86e099e616511f9996 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 21 Aug 2001 02:58:07 +0000 Subject: Add a new option to disable our paranoid server check. Defaults to ON, ie checking (This used to be commit bd3010263be24425206587abfdb41164089e2157) --- source3/smbd/auth_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index 1960fc1cfb..0711b056bd 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -158,7 +158,7 @@ static uint32 server_validate(const auth_usersupplied_info *user_info, auth_serv * - abartlet@samba.org */ - if(!tested_password_server) { + if ((!tested_password_server) && (lp_paranoid_server_security())) { if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass), (char *)badpass, sizeof(badpass), user_info->domain.str)) { -- cgit From e4275a35a64fde95a3b59307572d44c8d53909ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 00:29:40 +0000 Subject: Fixed the (incorrect) paranioa fix I put in for the fcntl lock spin. Don't delete a share mode that failed to remove the oplock (doh!), just set the oplock entry to zero.... Jeremy. (This used to be commit fe4aa720181a43f7a636ca029680fab0c836b968) --- source3/smbd/close.c | 3 +++ source3/smbd/open.c | 44 +++++++++++++++++++++++++++++++++++--------- source3/smbd/oplock.c | 14 ++++++++++++-- 3 files changed, 50 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 6b72a8563a..dd1a25293d 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -153,6 +153,9 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) lock_share_entry_fsp(fsp); share_entry_count = del_share_mode(fsp, &share_entry); + DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n", + share_entry_count, fsp->fsp_name )); + /* * We delete on close if it's the last open, and the * delete on close flag was set in the entry we just deleted. diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 143aa934a6..633cf71817 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -527,17 +527,42 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); - if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { - DEBUG(0,("open_mode_check: cannot delete entry when breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", broken_entry.op_type, fname, (unsigned int)dev, (double)inode)); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return -1; - } num_share_modes = get_share_modes(conn, dev, inode, &old_shares); oplock_contention_count++; - } + + /* Paranoia check that this is no longer an exlusive entry. */ + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + + if (share_modes_identical(&broken_entry, share_entry) && + EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) { + + /* + * This should not happen. The target left this oplock + * as exlusive.... The process *must* be dead.... + */ + + DEBUG(0,("open_mode_check: exlusive oplock left after break ! For file %s, +dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); + + if (process_exists(broken_entry.pid)) { + pstring errmsg; + slprintf(errmsg, sizeof(errmsg)-1, + "open_mode_check: Existant process %d left active oplock.\n", + broken_entry.pid ); + smb_panic(errmsg); + } + + if (!clear_share_entry(dev, inode, &broken_entry)) { + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } + } + } /* end for paranoia... */ + } /* end if broke_oplock */ + } while(broke_oplock); if(old_shares != 0) @@ -570,6 +595,7 @@ static void kernel_flock(files_struct *fsp, int deny_mode) else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND; if (kernel_mode) flock(fsp->fd, kernel_mode); #endif + ;; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 4bc8fce698..f841432960 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1141,6 +1141,9 @@ void release_level_2_oplocks_on_change(files_struct *fsp) num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list); + DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", + num_share_modes )); + for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &share_list[i]; @@ -1153,6 +1156,9 @@ void release_level_2_oplocks_on_change(files_struct *fsp) * also no harm to ignore existing NO_OPLOCK states. JRA. */ + DEBUG(10,("release_level_2_oplocks_on_change: share_entry[%i]->op_type == %d\n", + i, share_entry->op_type )); + if (share_entry->op_type == NO_OPLOCK) continue; @@ -1179,6 +1185,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp) abort(); } + DEBUG(10,("release_level_2_oplocks_on_change: breaking our own oplock.\n")); + oplock_break_level2(new_fsp, True, token); } else { @@ -1188,17 +1196,19 @@ void release_level_2_oplocks_on_change(files_struct *fsp) * message. */ + DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock.\n")); request_oplock_break(share_entry, fsp->dev, fsp->inode); } } - free((char *)share_list); + if (share_list) + free((char *)share_list); unlock_share_entry_fsp(fsp); /* Paranoia check... */ if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { DEBUG(0,("release_level_2_oplocks_on_change: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name)); - abort(); + smb_panic("release_level_2_oplocks_on_change"); } } -- cgit From 85e063f5b8b9ac872dc5e30da99b34230434df84 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 01:01:37 +0000 Subject: Tidyup fixes for fcntl spin problem. Jeremy. (This used to be commit 27d3dd0e7cb777ef6b21d6966c07045c2940fd37) --- source3/smbd/open.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 633cf71817..a8cf9aba89 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3,6 +3,7 @@ Version 1.9. file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001 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 @@ -542,8 +543,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou * as exlusive.... The process *must* be dead.... */ - DEBUG(0,("open_mode_check: exlusive oplock left after break ! For file %s, -dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); + DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, +dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { pstring errmsg; @@ -553,12 +554,21 @@ dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); smb_panic(errmsg); } - if (!clear_share_entry(dev, inode, &broken_entry)) { + if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; return -1; } + + /* + * We must reload the share modes after deleting the + * other process's entry. + */ + + free((char *)old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + break; } } /* end for paranoia... */ } /* end if broke_oplock */ -- cgit From ecea36501ec6d4d2db0c27311d4548e8e404ec1a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 01:06:27 +0000 Subject: Missed '\' at eol... Jeremy. (This used to be commit 0dbd1be704209c1a66280148b40f7b7437d47242) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a8cf9aba89..2e1ddb07fb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -543,7 +543,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou * as exlusive.... The process *must* be dead.... */ - DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, + DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, \ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { -- cgit From c50ef232152551ac79502caaf259cdfc3a32ca96 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 22 Aug 2001 04:58:00 +0000 Subject: force checking of log size after 200 smbd in a row or after 30 sec with no smbds. This should fix one case of logs not getting rotated properly. We may need to test this to make sure there is no big performance hit from the extra stat call. (This used to be commit 2501fe7c0436fc00f35271e2dce17fe541e97424) --- source3/smbd/process.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 65fa600be4..2b75197c38 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1170,9 +1170,10 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); /* * Now we are root, check if the log files need pruning. + * Force a log file check. */ - if(need_to_check_log_size()) - check_log_size(); + force_check_log_size(); + check_log_size(); /* * Modify the select timeout depending upon -- cgit From fe626d22bfd25231db487180dd7e517db93b573e Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Wed, 22 Aug 2001 13:08:01 +0000 Subject: The DELL powervault 705 is sending a tcon&x with the service name being "share" instead of "\\server\share". Fix that. Still not able to get the user list but that's something else. Jeremy I don't think I broke anything ;-) J.F. (This used to be commit 59018c58e4158e9ccb51c42ca32e490f32ee0def) --- source3/smbd/reply.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eb97382750..bef1b15084 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -288,12 +288,22 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt passlen = strlen(password); } - q = strchr_m(path+2,'\\'); - if (!q) { - END_PROFILE(SMBtconX); - return(ERROR(ERRDOS,ERRnosuchshare)); + + /* + * the service name can be either: \\server\share + * or share directly like on the DELL PowerVault 705 + */ + if (*path=='\\') { + q = strchr_m(path+2,'\\'); + if (!q) { + END_PROFILE(SMBtconX); + return(ERROR(ERRDOS,ERRnosuchshare)); + } + fstrcpy(service,q+1); } - fstrcpy(service,q+1); + else + fstrcpy(service,path); + q = strchr_m(service,'%'); if (q) { *q++ = 0; -- cgit From 2051bb7d0366e07c5ecda5e5f7cfedc4153d6228 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Aug 2001 19:11:55 +0000 Subject: A few changes: drop paramaters: status utmp hostname change session code to always record each vuid current on the server. The sessionid struct is no longer packed, as I couldn't get that to work ;-) change smbstatus to show this info and less of the connections.tdb info (its not actualy that accurate). I'll get swat doing some of this shortly. (This used to be commit b068ad300527c44673bbee0aede7849199c89de7) --- source3/smbd/reply.c | 4 +--- source3/smbd/server.c | 8 ++------ source3/smbd/session.c | 43 ++++++++++++++----------------------------- 3 files changed, 17 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bef1b15084..b4fb6693e6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -127,9 +127,7 @@ int reply_special(char *inbuf,char *outbuf) reload_services(True); reopen_logs(); - if (lp_status(-1)) { - claim_connection(NULL,"",MAXSTATUS,True); - } + claim_connection(NULL,"",MAXSTATUS,True); break; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 13071a5b65..5bcb47393a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -459,9 +459,7 @@ void exit_server(char *reason) invalidate_all_vuids(); /* delete our entry in the connections database. */ - if (lp_status(-1)) { - yield_connection(NULL,"",MAXSTATUS); - } + yield_connection(NULL,"",MAXSTATUS); respond_to_all_remaining_local_messages(); decrement_smbd_process_count(); @@ -751,9 +749,7 @@ static void usage(char *pname) } /* Setup the main smbd so that we can get messages. */ - if (lp_status(-1)) { - claim_connection(NULL,"",MAXSTATUS,True); - } + claim_connection(NULL,"",MAXSTATUS,True); /* Attempt to migrate from an old 2.0.x machine account file. */ if (!migrate_from_old_password_file(global_myworkgroup)) { diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 7616689fe0..78c635d7cf 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -28,17 +28,9 @@ #include "includes.h" -#if defined(WITH_PAM) || defined(WITH_UTMP) +extern fstring remote_machine; static TDB_CONTEXT *tdb; -struct sessionid { - fstring username; - fstring hostname; - fstring id_str; - uint32 id_num; - uint32 pid; -}; - /* called when a session is created */ BOOL session_claim(uint16 vuid) { @@ -98,6 +90,10 @@ BOOL session_claim(uint16 vuid) slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_TEMPLATE, i); sessionid.id_num = i; sessionid.pid = pid; + sessionid.uid = vuser->uid; + sessionid.gid = vuser->gid; + fstrcpy(sessionid.remote_machine, remote_machine); + fstrcpy(sessionid.ip_addr, client_addr()); if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", @@ -106,12 +102,8 @@ BOOL session_claim(uint16 vuid) return False; } - dlen = tdb_pack(dbuf, sizeof(dbuf), "fffdd", - sessionid.username, sessionid.hostname, sessionid.id_str, - sessionid.id_num, sessionid.pid); - - data.dptr = dbuf; - data.dsize = dlen; + data.dptr = (char *)&sessionid; + data.dsize = sizeof(sessionid); if (tdb_store(tdb, key, data, TDB_MODIFY) != 0) { DEBUG(1,("session_claim: unable to create session id record\n")); return False; @@ -132,7 +124,7 @@ BOOL session_claim(uint16 vuid) void session_yield(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); - TDB_DATA data; + TDB_DATA dbuf; struct sessionid sessionid; TDB_DATA key; fstring keystr; @@ -148,17 +140,15 @@ void session_yield(uint16 vuid) key.dptr = keystr; key.dsize = strlen(keystr)+1; - data = tdb_fetch(tdb, key); - if (data.dptr == NULL) { + dbuf = tdb_fetch(tdb, key); + + if (dbuf.dsize != sizeof(sessionid)) return; - } - tdb_unpack(data.dptr, data.dsize, "fffdd", - &sessionid.username, &sessionid.hostname, &sessionid.id_str, - &sessionid.id_num, &sessionid.pid); + memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); - safe_free(data.dptr); - data.dptr = NULL; + safe_free(dbuf.dptr); + dbuf.dptr = NULL; #if WITH_UTMP if (lp_utmp()) { @@ -172,8 +162,3 @@ void session_yield(uint16 vuid) tdb_delete(tdb, key); } -#else - /* null functions - no session support needed */ - BOOL session_claim(uint16 vuid) { return True; } - void session_yield(uint16 vuid) {} -#endif -- cgit From 2f6486b55f05947205c380e071b16cd40af4d057 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 23 Aug 2001 18:13:56 +0000 Subject: Fix up some unused variables and functions, fix up formatting (This used to be commit bfce4ba7b6db261d981a60a7e262f2f690355f5c) --- source3/smbd/auth_util.c | 1 - source3/smbd/session.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 1c12a4322d..4a0f45f843 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -137,5 +137,4 @@ void smb_user_control(char *unix_user, uint32 nt_status) if(lp_deluser_script() && smb_getpwnam(unix_user,True)) smb_delete_user(unix_user); } - } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 78c635d7cf..eaff78c685 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -38,8 +38,6 @@ BOOL session_claim(uint16 vuid) int i; TDB_DATA data; struct sessionid sessionid; - pstring dbuf; - int dlen; uint32 pid = (uint32)sys_getpid(); TDB_DATA key; fstring keystr; -- cgit From 7495a1a894a44913adc9602d1759a11eb00b631c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 23 Aug 2001 20:45:23 +0000 Subject: Fix to only send the status32 error for status32 clients, not to other nt_smb clients. As spotted by Thursby. (This used to be commit 22de76a920671614144babac9f589419532d8671) --- source3/smbd/reply.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b4fb6693e6..fd4f5d62c0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -554,10 +554,8 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out static int bad_password_error(char *inbuf,char *outbuf) { - enum remote_arch_types ra_type = get_remote_arch(); - if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) && - (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { + if (global_client_caps & CAP_STATUS32) { SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0,NT_STATUS_LOGON_FAILURE)); } -- cgit From 964bfb219353369ba244cb7fb2177f03cce4d56c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Aug 2001 23:37:40 +0000 Subject: Fix W2K profiles writing to a Samba PDC. Thanks to Microsoft for their help ! Jeremy. (This used to be commit faae7512e059456db2450f878c435fd402839146) --- source3/smbd/trans2.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2c0286cf0a..f219d250c2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1629,8 +1629,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; } - case 1022: - { + case SMB_FILE_STREAM_INFORMATION: + if (mode & aDIR) { + data_size = 0; + } else { size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False); SIVAL(pdata,0,0); /* ??? */ SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ @@ -1638,8 +1640,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,16,0x20); /* ??? */ SIVAL(pdata,20,0); /* ??? */ data_size = 24 + byte_len; - break; } + break; case 1028: SOFF_T(pdata,0,size); @@ -1947,6 +1949,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + case SMB_FILE_DISPOSITION_INFORMATION: case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { BOOL delete_on_close = (CVAL(pdata,0) ? True : False); @@ -2033,18 +2036,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } - case 1013: -#if 0 /* JRA */ - /* - * This (new) W2K call seems to set one byte. Not sure - * yet what it's trying to do. JRA. - */ - { - unsigned char setval = CVAL(pdata,0); - } -#endif /* JRA */ - return(ERROR(ERRDOS,ERRnoaccess)); - default: { return(ERROR(ERRDOS,ERRunknownlevel)); -- cgit From a22db179a9439ab8455c3cbc13040c2d4a1f1882 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Aug 2001 04:56:33 +0000 Subject: flush on a invalid fsp should give an error (This used to be commit ef5f4866fbbfa6be07cdc3e612a8899967d48289) --- source3/smbd/reply.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fd4f5d62c0..fca16a2f04 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2740,24 +2740,24 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBflush); - - if (fsp) { - CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); - } + int outsize = set_message(outbuf,0,0,True); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBflush); - if (!fsp) { - file_sync_all(conn); - } else { + CHECK_FSP(fsp,conn); + if (fsp) { + CHECK_ERROR(fsp); + } + + if (!fsp) { + file_sync_all(conn); + } else { sync_file(conn,fsp); - } - - DEBUG(3,("flush\n")); - END_PROFILE(SMBflush); - return(outsize); + } + + DEBUG(3,("flush\n")); + END_PROFILE(SMBflush); + return(outsize); } -- cgit From bb94537ab5858fecb34f047c9e5c0e6fe4fd8ae9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 24 Aug 2001 18:55:56 +0000 Subject: Fixed incorrect debug. (This used to be commit cec051cf5fb93d9f45eca3f9cf462f78a7d7040d) --- source3/smbd/auth_domain.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index a2e3c7a9b5..d9d7b6fd40 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -49,7 +49,7 @@ uint32 check_domain_security(const auth_usersupplied_info *user_info, if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) { - DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", lp_workgroup())); + DEBUG(0, ("check_domain_security: could not fetch trust account password for domain %s\n", lp_workgroup())); unbecome_root(); return NT_STATUS_LOGON_FAILURE; } @@ -76,6 +76,3 @@ uint32 check_domain_security(const auth_usersupplied_info *user_info, return nt_status; } - - - -- cgit From db93134c3258cf78940a65f358852203c9af970d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Aug 2001 20:11:26 +0000 Subject: fixed level2 find first for unisys clients (This used to be commit cb8b21f71dbacc7ee658bef7011cd147fbe34101) --- source3/smbd/trans2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f219d250c2..13db9948ad 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -496,6 +496,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, STR_NOALIGN); SCVAL(p, -1, len); p += len; + *p++ = 0; /* craig from unisys pointed out we need this */ break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: -- cgit From 717533483b41ef975953f58e0c6be04828a3d467 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 24 Aug 2001 20:32:01 +0000 Subject: get rid of compiler warnings (This used to be commit 0768991d04ea03e774ca8662c9cae5e1951b88e0) --- source3/smbd/auth.c | 6 +++--- source3/smbd/auth_server.c | 4 ++-- source3/smbd/auth_smbpasswd.c | 6 +++--- source3/smbd/reply.c | 4 ++-- source3/smbd/vfs.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index d33bc225e6..8ea867fe8c 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -188,7 +188,7 @@ uint32 pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], user_info.nt_resp.len = 24; } - user_info.plaintext_password.str = lm_pwd; + user_info.plaintext_password.str = (char *)lm_pwd; user_info.plaintext_password.len = lm_pwd_len; } @@ -232,11 +232,11 @@ BOOL password_ok(char *user, char *password, int pwlen) /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as required. */ - if (pass_check_smb(user, lp_workgroup(), NULL, 0, password, pwlen) == NT_STATUS_NOPROBLEMO) { + if (pass_check_smb(user, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen) == NT_STATUS_NOPROBLEMO) { return True; } - if (pass_check_smb(user, lp_workgroup(), password, pwlen, NULL, 0) == NT_STATUS_NOPROBLEMO) { + if (pass_check_smb(user, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0) == NT_STATUS_NOPROBLEMO) { return True; } diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index 0711b056bd..ad66f0c4ac 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -205,9 +205,9 @@ use this machine as the password server.\n")); */ if (!cli_session_setup(cli, user_info->smb_username.str, - user_info->lm_resp.buffer, + (char *)user_info->lm_resp.buffer, user_info->lm_resp.len, - user_info->nt_resp.buffer, + (char *)user_info->nt_resp.buffer, user_info->nt_resp.len, user_info->domain.str)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 27cb801c33..1a5d02e4a4 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -45,7 +45,7 @@ static BOOL smb_pwd_check_ntlmv1(const uchar *password, SMBOWFencrypt(part_passwd, c8, p24); if (user_sess_key != NULL) { - SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); + SMBsesskeygen_ntv1(part_passwd, NULL, (char *)user_sess_key); } @@ -84,7 +84,7 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, } ntv2_owf_gen(part_passwd, user, domain, kr); - SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp); + SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, (char *)resp); if (user_sess_key != NULL) { SMBsesskeygen_ntv2(kr, resp, user_sess_key); @@ -154,7 +154,7 @@ uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_ nt_pw, user_info->chal, user_info->requested_username.str, user_info->requested_domain.str, - server_info->session_key)) + (char *)server_info->session_key)) { return NT_STATUS_NOPROBLEMO; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fca16a2f04..02531bd1cd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -812,8 +812,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!guest) { valid_password = (pass_check_smb(user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO); + (unsigned char *)smb_apasswd, smb_apasslen, + (unsigned char *)smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO); /* The true branch will be executed if (1) the NT password failed (or was not tried), and diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9709fc6a20..f5870a3119 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -356,7 +356,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) while ( len_to_write > 0) { SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),len_to_write); - retlen = vfs_ops->write(fsp,fsp->fd,zero_space,current_len_to_write); + retlen = vfs_ops->write(fsp,fsp->fd,(const char *)zero_space,current_len_to_write); if (retlen <= 0) { /* Write fail - return to original size. */ int save_errno = errno; -- cgit From e8e98c9ea0690e3acf1126b50882e59e1056c7b3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 08:19:43 +0000 Subject: converted smbd to use NTSTATUS by default major changes include: - added NSTATUS type - added automatic mapping between dos and nt error codes - changed all ERROR() calls to ERROR_DOS() and many to ERROR_NT() these calls auto-translate to the client error code system - got rid of the cached error code and the writebmpx code We eventually will need to also: - get rid of BOOL, so we don't lose error info - replace all ERROR_DOS() calls with ERROR_NT() calls but that is too much for one night (This used to be commit 83d9896c1ea8be796192b51a4678c2a3b87f7518) --- source3/smbd/blocking.c | 474 +++++++++--------- source3/smbd/close.c | 4 - source3/smbd/error.c | 129 +++-- source3/smbd/ipc.c | 28 +- source3/smbd/message.c | 8 +- source3/smbd/negprot.c | 176 +++---- source3/smbd/notify.c | 11 +- source3/smbd/nttrans.c | 85 ++-- source3/smbd/open.c | 5 +- source3/smbd/pipes.c | 16 +- source3/smbd/process.c | 18 +- source3/smbd/reply.c | 1264 +++++++++++++++++++---------------------------- source3/smbd/trans2.c | 104 ++-- 13 files changed, 997 insertions(+), 1325 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 48d3c8a24a..697e1df194 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -170,16 +170,13 @@ static void reply_lockingX_success(blocking_lock_record *blr) Return a generic lock fail error blocking call. *****************************************************************************/ -static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, int32 ecode) +static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status) { char *outbuf = OutBuffer; char *inbuf = blr->inbuf; construct_reply_common(inbuf, outbuf); - if(eclass == 0) /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - - ERROR(eclass,ecode); + ERROR_NT(status); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("generic_blocking_lock_error: send_smb failed.\n"); } @@ -189,72 +186,68 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, i obtained first. *****************************************************************************/ -static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ecode) +static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) { - char *inbuf = blr->inbuf; - files_struct *fsp = blr->fsp; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; - uint16 lock_pid; - unsigned char locktype = CVAL(inbuf,smb_vwv3); - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); - char *data; - int i; - - data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); - - /* - * Data now points at the beginning of the list - * of smb_lkrng structs. - */ - - /* - * Ensure we don't do a remove on the lock that just failed, - * as under POSIX rules, if we have a lock already there, we - * will delete it (and we shouldn't) ..... - */ - - for(i = blr->lock_num - 1; i >= 0; i--) { - int dummy1; - uint32 dummy2; - BOOL err; - - lock_pid = get_lock_pid( data, i, large_file_format); - count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); - - /* - * We know err cannot be set as if it was the lock - * request would never have been queued. JRA. - */ - - do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2); - } - - generic_blocking_lock_error(blr, eclass, ecode); + char *inbuf = blr->inbuf; + files_struct *fsp = blr->fsp; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; + uint16 lock_pid; + unsigned char locktype = CVAL(inbuf,smb_vwv3); + BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); + char *data; + int i; + + data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); + + /* + * Data now points at the beginning of the list + * of smb_lkrng structs. + */ + + /* + * Ensure we don't do a remove on the lock that just failed, + * as under POSIX rules, if we have a lock already there, we + * will delete it (and we shouldn't) ..... + */ + + for(i = blr->lock_num - 1; i >= 0; i--) { + BOOL err; + + lock_pid = get_lock_pid( data, i, large_file_format); + count = get_lock_count( data, i, large_file_format); + offset = get_lock_offset( data, i, large_file_format, &err); + + /* + * We know err cannot be set as if it was the lock + * request would never have been queued. JRA. + */ + + do_unlock(fsp,conn,lock_pid,count,offset); + } + + generic_blocking_lock_error(blr, status); } /**************************************************************************** Return a lock fail error. *****************************************************************************/ -static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status) { - switch(blr->com_type) { - case SMBlock: - generic_blocking_lock_error(blr, eclass, ecode); - break; - case SMBlockread: - generic_blocking_lock_error(blr, eclass, ecode); - break; - case SMBlockingX: - reply_lockingX_error(blr, eclass, ecode); - break; - default: - DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } + switch(blr->com_type) { + case SMBlock: + case SMBlockread: + generic_blocking_lock_error(blr, status); + break; + case SMBlockingX: + reply_lockingX_error(blr, status); + break; + default: + DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } } /**************************************************************************** @@ -264,68 +257,68 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int static BOOL process_lockread(blocking_lock_record *blr) { - char *outbuf = OutBuffer; - char *inbuf = blr->inbuf; - ssize_t nread = -1; - char *data, *p; - int outsize = 0; - SMB_OFF_T startpos; - size_t numtoread; - int eclass; - uint32 ecode; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - files_struct *fsp = blr->fsp; - - numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - - numtoread = MIN(BUFFER_SIZE-outsize,numtoread); - data = smb_buf(outbuf) + 3; + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + ssize_t nread = -1; + char *data, *p; + int outsize = 0; + SMB_OFF_T startpos; + size_t numtoread; + NTSTATUS status; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + files_struct *fsp = blr->fsp; + + numtoread = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + + numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + data = smb_buf(outbuf) + 3; - if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, READ_LOCK, &eclass, &ecode)) { - if((errno != EACCES) && (errno != EAGAIN)) { - /* - * We have other than a "can't get lock" POSIX - * error. Send an error. - * Return True so we get dequeued. - */ - - generic_blocking_lock_error(blr, eclass, ecode); - return True; - } - - /* - * Still waiting for lock.... - */ - - DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n", - fsp->fsp_name)); - return False; - } - - nread = read_file(fsp,data,startpos,numtoread); - - if (nread < 0) { - generic_blocking_lock_error(blr,ERRDOS,ERRnoaccess); - return True; - } - - construct_reply_common(inbuf, outbuf); - outsize = set_message(outbuf,5,0,True); - - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - p = smb_buf(outbuf); - *p++ = 1; - SSVAL(p,0,nread); p += 2; - set_message_end(outbuf, p+nread); - - DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", - fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) ); - - send_blocking_reply(outbuf,outsize); - return True; + status = do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, + (SMB_BIG_UINT)startpos, READ_LOCK); + if (status != NT_STATUS_NOPROBLEMO) { + if ((errno != EACCES) && (errno != EAGAIN)) { + /* + * We have other than a "can't get lock" POSIX + * error. Send an error. + * Return True so we get dequeued. + */ + generic_blocking_lock_error(blr, status); + return True; + } + + /* + * Still waiting for lock.... + */ + + DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n", + fsp->fsp_name)); + return False; + } + + nread = read_file(fsp,data,startpos,numtoread); + + if (nread < 0) { + generic_blocking_lock_error(blr,NT_STATUS_ACCESS_DENIED); + return True; + } + + construct_reply_common(inbuf, outbuf); + outsize = set_message(outbuf,5,0,True); + + outsize += nread; + SSVAL(outbuf,smb_vwv0,nread); + SSVAL(outbuf,smb_vwv5,nread+3); + p = smb_buf(outbuf); + *p++ = 1; + SSVAL(p,0,nread); p += 2; + set_message_end(outbuf, p+nread); + + DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", + fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) ); + + send_blocking_reply(outbuf,outsize); + return True; } /**************************************************************************** @@ -335,52 +328,50 @@ static BOOL process_lockread(blocking_lock_record *blr) static BOOL process_lock(blocking_lock_record *blr) { - char *outbuf = OutBuffer; - char *inbuf = blr->inbuf; - int outsize; - SMB_OFF_T count = 0, offset = 0; - int eclass; - uint32 ecode; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - files_struct *fsp = blr->fsp; - - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); - - errno = 0; - if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, (SMB_BIG_UINT)offset, WRITE_LOCK, &eclass, &ecode)) { - if((errno != EACCES) && (errno != EAGAIN)) { - - /* - * We have other than a "can't get lock" POSIX - * error. Send an error. - * Return True so we get dequeued. - */ - - blocking_lock_reply_error(blr, eclass, ecode); - return True; - } - - /* - * Still can't get the lock - keep waiting. - */ - - DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n", - fsp->fsp_name)); - return False; - } - - /* - * Success - we got the lock. - */ - - DEBUG(3,("process_lock : file=%s fnum=%d offset=%.0f count=%.0f\n", - fsp->fsp_name, fsp->fnum, (double)offset, (double)count)); - - construct_reply_common(inbuf, outbuf); - outsize = set_message(outbuf,0,0,True); - send_blocking_reply(outbuf,outsize); - return True; + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + int outsize; + SMB_OFF_T count = 0, offset = 0; + NTSTATUS status; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + files_struct *fsp = blr->fsp; + + count = IVAL(inbuf,smb_vwv1); + offset = IVAL(inbuf,smb_vwv3); + + errno = 0; + status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, + (SMB_BIG_UINT)offset, WRITE_LOCK); + if (status != NT_STATUS_NOPROBLEMO) { + if((errno != EACCES) && (errno != EAGAIN)) { + /* + * We have other than a "can't get lock" POSIX + * error. Send an error. + * Return True so we get dequeued. + */ + + blocking_lock_reply_error(blr, status); + return True; + } + /* + * Still can't get the lock - keep waiting. + */ + DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n", + fsp->fsp_name)); + return False; + } + + /* + * Success - we got the lock. + */ + + DEBUG(3,("process_lock : file=%s fnum=%d offset=%.0f count=%.0f\n", + fsp->fsp_name, fsp->fnum, (double)offset, (double)count)); + + construct_reply_common(inbuf, outbuf); + outsize = set_message(outbuf,0,0,True); + send_blocking_reply(outbuf,outsize); + return True; } /**************************************************************************** @@ -390,75 +381,72 @@ static BOOL process_lock(blocking_lock_record *blr) static BOOL process_lockingX(blocking_lock_record *blr) { - char *inbuf = blr->inbuf; - unsigned char locktype = CVAL(inbuf,smb_vwv3); - files_struct *fsp = blr->fsp; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint16 num_locks = SVAL(inbuf,smb_vwv7); - SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; - uint16 lock_pid; - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); - char *data; - int eclass=0; - uint32 ecode=0; - - data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); - - /* - * Data now points at the beginning of the list - * of smb_lkrng structs. - */ - - for(; blr->lock_num < num_locks; blr->lock_num++) { - BOOL err; - - lock_pid = get_lock_pid( data, blr->lock_num, large_file_format); - count = get_lock_count( data, blr->lock_num, large_file_format); - offset = get_lock_offset( data, blr->lock_num, large_file_format, &err); - - /* - * We know err cannot be set as if it was the lock - * request would never have been queued. JRA. - */ - errno = 0; - if(!do_lock(fsp,conn,count,lock_pid,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), - &eclass, &ecode)) - break; - } - - if(blr->lock_num == num_locks) { - - /* - * Success - we got all the locks. - */ - - DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n", - fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) ); - - reply_lockingX_success(blr); - return True; - - } else if((errno != EACCES) && (errno != EAGAIN)) { - - /* - * We have other than a "can't get lock" POSIX - * error. Free any locks we had and return an error. - * Return True so we get dequeued. - */ - - blocking_lock_reply_error(blr, eclass, ecode); - return True; - } - - /* - * Still can't get all the locks - keep waiting. - */ - - DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \ -Waiting....\n", blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum)); - - return False; + char *inbuf = blr->inbuf; + unsigned char locktype = CVAL(inbuf,smb_vwv3); + files_struct *fsp = blr->fsp; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint16 num_locks = SVAL(inbuf,smb_vwv7); + SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; + uint16 lock_pid; + BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); + char *data; + NTSTATUS status = 0; + + data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); + + /* + * Data now points at the beginning of the list + * of smb_lkrng structs. + */ + + for(; blr->lock_num < num_locks; blr->lock_num++) { + BOOL err; + + lock_pid = get_lock_pid( data, blr->lock_num, large_file_format); + count = get_lock_count( data, blr->lock_num, large_file_format); + offset = get_lock_offset( data, blr->lock_num, large_file_format, &err); + + /* + * We know err cannot be set as if it was the lock + * request would never have been queued. JRA. + */ + errno = 0; + status = do_lock(fsp,conn,count,lock_pid,offset, + ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); + if (status != NT_STATUS_NOPROBLEMO) break; + } + + if(blr->lock_num == num_locks) { + /* + * Success - we got all the locks. + */ + + DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n", + fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) ); + + reply_lockingX_success(blr); + return True; + } else if ((errno != EACCES) && (errno != EAGAIN)) { + /* + * We have other than a "can't get lock" POSIX + * error. Free any locks we had and return an error. + * Return True so we get dequeued. + */ + + blocking_lock_reply_error(blr, status); + return True; + } + + /* + * Still can't get all the locks - keep waiting. + */ + + DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \ +Waiting....\n", + blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum)); + + return False; } /**************************************************************************** @@ -523,7 +511,7 @@ void remove_pending_lock_requests_by_mid(int mid) DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - blocking_lock_reply_error(blr,0,NT_STATUS_CANCELLED); + blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -588,7 +576,7 @@ void process_blocking_lock_queue(time_t t) DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", fsp->fnum, fsp->fsp_name )); - blocking_lock_reply_error(blr,ERRSRV,ERRaccess); + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -600,7 +588,7 @@ void process_blocking_lock_queue(time_t t) /* * Remove the entry and return an error to the client. */ - blocking_lock_reply_error(blr,ERRSRV,ERRaccess); + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -611,7 +599,7 @@ void process_blocking_lock_queue(time_t t) /* * Remove the entry and return an error to the client. */ - blocking_lock_reply_error(blr,ERRSRV,ERRaccess); + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); unbecome_user(); diff --git a/source3/smbd/close.c b/source3/smbd/close.c index dd1a25293d..1a98a8bca5 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -102,10 +102,6 @@ static int close_filestruct(files_struct *fsp) fsp->stat_open = False; conn->num_files_open--; - if(fsp->wbmpx_ptr) { - free((char *)fsp->wbmpx_ptr); - fsp->wbmpx_ptr = NULL; - } return ret; } diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 472a8d8fd1..27dacda377 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -28,23 +28,6 @@ int unix_ERR_class=SMB_SUCCESS; int unix_ERR_code=0; -/**************************************************************************** - create an error packet from a cached error. -****************************************************************************/ -int cached_error_packet(char *inbuf,char *outbuf,files_struct *fsp,int line) -{ - write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; - - int32 eclass = wbmpx->wr_errclass; - int32 err = wbmpx->wr_error; - - /* We can now delete the auxiliary struct */ - free((char *)wbmpx); - fsp->wbmpx_ptr = NULL; - return error_packet(inbuf,outbuf,eclass,err,line); -} - - struct { int unixerror; @@ -79,68 +62,72 @@ struct /**************************************************************************** create an error packet from errno ****************************************************************************/ -int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line) +int unix_error_packet(char *outbuf,int def_class,uint32 def_code,int line) { - int eclass=def_class; - int ecode=def_code; - int i=0; - - if (unix_ERR_class != SMB_SUCCESS) - { - eclass = unix_ERR_class; - ecode = unix_ERR_code; - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - } - else - { - while (unix_smb_errmap[i].smbclass != 0) - { - if (unix_smb_errmap[i].unixerror == errno) - { - eclass = unix_smb_errmap[i].smbclass; - ecode = unix_smb_errmap[i].smbcode; - break; - } - i++; - } - } - - return(error_packet(inbuf,outbuf,eclass,ecode,line)); + int eclass=def_class; + int ecode=def_code; + int i=0; + + if (unix_ERR_class != SMB_SUCCESS) { + eclass = unix_ERR_class; + ecode = unix_ERR_code; + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + } else { + while (unix_smb_errmap[i].smbclass != 0) { + if (unix_smb_errmap[i].unixerror == errno) { + eclass = unix_smb_errmap[i].smbclass; + ecode = unix_smb_errmap[i].smbcode; + break; + } + i++; + } + } + + return error_packet(outbuf,0,eclass,ecode,line); } /**************************************************************************** create an error packet. Normally called using the ERROR() macro ****************************************************************************/ -int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line) +int error_packet(char *outbuf,uint32 ntstatus, + uint8 eclass,uint32 ecode,int line) { - int outsize = set_message(outbuf,0,0,True); - int cmd = CVAL(inbuf,smb_com); - int flgs2 = SVAL(outbuf,smb_flg2); - - if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); - - if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) - { - SIVAL(outbuf,smb_rcls,error_code); - - DEBUG( 3, ( "32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", - line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf) ) ); - } - else - { - CVAL(outbuf,smb_rcls) = error_class; - SSVAL(outbuf,smb_err,error_code); - DEBUG( 3, ( "error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - line, - (int)CVAL(inbuf,smb_com), - smb_fn_name(CVAL(inbuf,smb_com)), - error_class, - error_code ) ); + int outsize = set_message(outbuf,0,0,True); + extern uint32 global_client_caps; - } + if (errno != 0) + DEBUG(3,("error string = %s\n",strerror(errno))); - return(outsize); + if (global_client_caps & CAP_STATUS32) { + if (ntstatus == 0 && eclass) { + ntstatus = dos_to_ntstatus(eclass, ecode); + } + SIVAL(outbuf,smb_rcls,ntstatus); + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); + DEBUG(3,("error packet at line %d cmd=%d (%s) %s\n", + line, + (int)CVAL(outbuf,smb_com), + smb_fn_name(CVAL(outbuf,smb_com)), + get_nt_error_msg(ntstatus))); + return outsize; + } + + if (eclass == 0 && ntstatus) { + ntstatus_to_dos(ntstatus, &eclass, &ecode); + } + + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); + SVAL(outbuf,smb_rcls) = eclass; + SSVAL(outbuf,smb_err,ecode); + + DEBUG(3,("error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + line, + (int)CVAL(outbuf,smb_com), + smb_fn_name(CVAL(outbuf,smb_com)), + eclass, + ecode)); + + return outsize; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e853112bfe..a323261d88 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -36,7 +36,6 @@ extern fstring local_machine; #define NERR_notsupported 50 extern int smb_read_error; -extern uint32 global_client_caps; /******************************************************************* copies parameters and data, as needed, into the smb buffer @@ -98,21 +97,12 @@ void send_trans_reply(char *outbuf, align = ((this_lparam)%4); - set_message(outbuf,10,1+align+this_ldata+this_lparam,True); - - if (buffer_too_large) - { - /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ - if (!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) { - /* Win9x version. */ - SSVAL(outbuf, smb_err, ERRmoredata); - SCVAL(outbuf, smb_rcls, ERRDOS); - } else { - SIVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - SIVAL(outbuf, smb_rcls, 0x80000000 | STATUS_BUFFER_OVERFLOW); - } + if (buffer_too_large) { + ERROR_NT(STATUS_BUFFER_OVERFLOW); } + set_message(outbuf,10,1+align+this_ldata+this_lparam,True); + copy_trans_params_and_data(outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); @@ -395,7 +385,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if((data = (char *)malloc(tdscnt)) == NULL) { DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt)); END_PROFILE(SMBtrans); - return(ERROR(ERRDOS,ERRnomem)); + return(ERROR_DOS(ERRDOS,ERRnomem)); } memcpy(data,smb_base(inbuf)+dsoff,dscnt); } @@ -404,7 +394,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if((params = (char *)malloc(tpscnt)) == NULL) { DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt)); END_PROFILE(SMBtrans); - return(ERROR(ERRDOS,ERRnomem)); + return(ERROR_DOS(ERRDOS,ERRnomem)); } memcpy(params,smb_base(inbuf)+psoff,pscnt); } @@ -414,7 +404,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16)))); END_PROFILE(SMBtrans); - return(ERROR(ERRDOS,ERRnomem)); + return(ERROR_DOS(ERRDOS,ERRnomem)); } for (i=0;isec_mode & 2) != 0); - } else { - DEBUG(3,("not using password server validation\n")); - } - - if (doencrypt) { - crypt_len = 8; - if (!cli) { - generate_next_challenge(cryptkey); - } else { - memcpy(cryptkey, cli->cryptkey, 8); - set_challenge(cli->cryptkey); - } - } - - if (lp_readraw() && lp_writeraw()) { - capabilities |= CAP_RAW_MODE; - } - - - /* allow for disabling unicode */ - if (lp_unicode()) { - capabilities |= CAP_UNICODE; - } - + /* dual names + lock_and_read + nt SMBs + remote API calls */ + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| + CAP_LEVEL_II_OPLOCKS|CAP_STATUS32; + + int secword=0; + BOOL doencrypt = SMBENCRYPT(); + time_t t = time(NULL); + struct cli_state *cli = NULL; + char cryptkey[8]; + char crypt_len = 0; + char *p, *q; + + if (lp_security() == SEC_SERVER) { + DEBUG(5,("attempting password server validation\n")); + cli = server_cryptkey(); + } else { + DEBUG(5,("not attempting password server validation\n")); + } + + if (cli) { + DEBUG(3,("using password server validation\n")); + doencrypt = ((cli->sec_mode & 2) != 0); + } else { + DEBUG(3,("not using password server validation\n")); + } + + if (doencrypt) { + crypt_len = 8; + if (!cli) { + generate_next_challenge(cryptkey); + } else { + memcpy(cryptkey, cli->cryptkey, 8); + set_challenge(cli->cryptkey); + } + } + + if (lp_nt_smb_support()) { + capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; + } + + if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) { + capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS; + } + + if (SMB_OFF_T_BITS == 64) { + capabilities |= CAP_LARGE_FILES; + } + + if (lp_readraw() && lp_writeraw()) { + capabilities |= CAP_RAW_MODE; + } + + /* allow for disabling unicode */ + if (lp_unicode()) { + capabilities |= CAP_UNICODE; + } + #ifdef WITH_MSDFS - if(lp_host_msdfs()) - capabilities |= CAP_DFS; + if(lp_host_msdfs()) + capabilities |= CAP_DFS; #endif - - if (lp_security() >= SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; - - set_message(outbuf,17,0,True); - - CVAL(outbuf,smb_vwv1) = secword; - SSVALS(outbuf,smb_vwv16+1,crypt_len); - - Protocol = PROTOCOL_NT1; - - SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ - SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ - SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ - SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ - SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */ - SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ - put_long_date(outbuf+smb_vwv11+1,t); - SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); - - p = q = smb_buf(outbuf); - if (doencrypt) memcpy(p, cryptkey, 8); - p += 8; - p += srvstr_push(outbuf, p, global_myworkgroup, -1, - STR_UNICODE|STR_TERMINATE|STR_NOALIGN); - - SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */ - set_message_end(outbuf, p); - - return (smb_len(outbuf)+4); + + if (lp_security() >= SEC_USER) secword |= 1; + if (doencrypt) secword |= 2; + + set_message(outbuf,17,0,True); + + CVAL(outbuf,smb_vwv1) = secword; + SSVALS(outbuf,smb_vwv16+1,crypt_len); + + Protocol = PROTOCOL_NT1; + + SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ + SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ + SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ + SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ + SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */ + SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ + put_long_date(outbuf+smb_vwv11+1,t); + SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); + + p = q = smb_buf(outbuf); + if (doencrypt) memcpy(p, cryptkey, 8); + p += 8; + p += srvstr_push(outbuf, p, global_myworkgroup, -1, + STR_UNICODE|STR_TERMINATE|STR_NOALIGN); + + SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */ + set_message_end(outbuf, p); + + return (smb_len(outbuf)+4); } /* these are the protocol lists used for auto architecture detection: diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 3c21ce1e1b..a2a979b776 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -54,16 +54,7 @@ static void change_notify_reply_packet(char *inbuf, uint32 error_code) memset(outbuf, '\0', sizeof(outbuf)); construct_reply_common(inbuf, outbuf); - /* - * If we're returning a 'too much in the directory changed' we need to - * set this is an NT error status flags. If we don't then the (probably - * untested) code in the NT redirector has a bug in that it doesn't re-issue - * the change notify.... Ah - I *love* it when I get so deeply into this I - * can even determine how MS failed to test stuff and why.... :-). JRA. - */ - - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - ERROR(0,error_code); + ERROR_NT(error_code); /* * Seems NT needs a transact command with an error code diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f0195fc0dd..2981c6bfb2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -84,10 +84,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err set_message(outbuf,18,0,True); if(nt_error != 0) { - /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - - ERROR(0,nt_error); + ERROR_NT(nt_error); } /* @@ -475,14 +472,14 @@ static int nt_open_pipe(char *fname, connection_struct *conn, /* See if it is one we want to handle. */ if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); for( i = 0; known_nt_pipes[i]; i++ ) if( strequal(fname,known_nt_pipes[i])) break; if ( known_nt_pipes[i] == NULL ) - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); /* Strip \\ off the name. */ fname++; @@ -491,7 +488,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn, p = open_rpc_pipe_p(fname, conn, vuid); if (!p) - return(ERROR(ERRSRV,ERRnofids)); + return(ERROR_DOS(ERRSRV,ERRnofids)); *ppnum = p->pnum; @@ -582,7 +579,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return do_ntcreate_pipe_open(conn,inbuf,outbuf,length,bufsize); } else { END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRbadaccess)); + return(ERROR_DOS(ERRDOS,ERRbadaccess)); } } @@ -594,7 +591,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if((smb_ofun = map_create_disposition( create_disposition )) == -1) { END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRbadaccess)); + return(ERROR_DOS(ERRDOS,ERRbadaccess)); } /* @@ -610,7 +607,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!dir_fsp) { END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRbadfid)); + return(ERROR_DOS(ERRDOS,ERRbadfid)); } if(!dir_fsp->is_directory) { @@ -621,12 +618,11 @@ int reply_ntcreate_and_X(connection_struct *conn, srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); if( strchr_m(fname, ':')) { - SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); - return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRbadfid)); + return(ERROR_DOS(ERRDOS,ERRbadfid)); } /* @@ -662,7 +658,7 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, file_attributes)) == -1) { END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRbadaccess)); + return ERROR_DOS(ERRDOS,ERRbadaccess); } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -753,7 +749,7 @@ int reply_ntcreate_and_X(connection_struct *conn, SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); - return(ERROR(0, NT_STATUS_FILE_IS_A_DIRECTORY)); + return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } oplock_request = 0; @@ -812,7 +808,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if (!fsp->is_directory && (fmode & aDIR)) { close_file(fsp,False); END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } /* @@ -904,7 +900,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, if(total_parameter_count < 54) { DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); - return(ERROR(ERRDOS,ERRbadaccess)); + return ERROR_DOS(ERRDOS,ERRbadaccess); } srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); @@ -915,7 +911,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, /* Realloc the size of parameters and data we will return */ params = Realloc(*ppparams, 69); if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); *ppparams = params; @@ -1074,7 +1070,7 @@ static int call_nt_transact_create(connection_struct *conn, return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, bufsize, ppsetup, ppparams, ppdata); else - return(ERROR(ERRDOS,ERRbadaccess)); + return ERROR_DOS(ERRDOS,ERRbadaccess); } /* @@ -1083,7 +1079,7 @@ static int call_nt_transact_create(connection_struct *conn, if(total_parameter_count < 54) { DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); - return(ERROR(ERRDOS,ERRbadaccess)); + return ERROR_DOS(ERRDOS,ERRbadaccess); } flags = IVAL(params,0); @@ -1102,7 +1098,7 @@ static int call_nt_transact_create(connection_struct *conn, */ if((smb_ofun = map_create_disposition( create_disposition )) == -1) - return(ERROR(ERRDOS,ERRbadmem)); + return ERROR_DOS(ERRDOS,ERRbadmem); /* * Get the file name. @@ -1117,7 +1113,7 @@ static int call_nt_transact_create(connection_struct *conn, size_t dir_name_len; if(!dir_fsp) - return(ERROR(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); if(!dir_fsp->is_directory) { /* @@ -1127,11 +1123,10 @@ static int call_nt_transact_create(connection_struct *conn, srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); if( strchr_m(fname, ':')) { - SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, NT_STATUS_OBJECT_PATH_NOT_FOUND)); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - return(ERROR(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); } /* @@ -1163,7 +1158,7 @@ static int call_nt_transact_create(connection_struct *conn, if((smb_open_mode = map_share_mode( &stat_open_only, fname, desired_access, share_access, file_attributes)) == -1) - return(ERROR(ERRDOS,ERRbadaccess)); + return ERROR_DOS(ERRDOS,ERRbadaccess); oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; @@ -1226,7 +1221,7 @@ static int call_nt_transact_create(connection_struct *conn, restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, NT_STATUS_FILE_IS_A_DIRECTORY)); + return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } oplock_request = 0; @@ -1280,7 +1275,7 @@ static int call_nt_transact_create(connection_struct *conn, if (fmode & aDIR) { close_file(fsp,False); restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } /* @@ -1303,7 +1298,7 @@ static int call_nt_transact_create(connection_struct *conn, if (!set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION, &error_class, &error_code)) { close_file(fsp,False); restore_case_semantics(file_attributes); - return(ERROR(error_class, error_code)); + return ERROR_DOS(error_class, error_code); } restore_case_semantics(file_attributes); @@ -1311,7 +1306,7 @@ static int call_nt_transact_create(connection_struct *conn, /* Realloc the size of parameters and data we will return */ params = Realloc(*ppparams, 69); if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); *ppparams = params; @@ -1416,10 +1411,10 @@ static int call_nt_transact_notify_change(connection_struct *conn, DEBUG(3,("call_nt_transact_notify_change\n")); if(!fsp) - return(ERROR(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); if((!fsp->is_directory) || (conn != fsp->conn)) - return(ERROR(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); if (!change_notify_set(inbuf, fsp, conn, flags)) { return(UNIXERROR(ERRDOS,ERRbadfid)); @@ -1496,13 +1491,13 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, files_struct *fsp = file_fsp(params,0); if(!fsp) - return(ERROR(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); params = Realloc(*ppparams, 4); if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); *ppparams = params; @@ -1530,7 +1525,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, data = Realloc(*ppdata, sd_size); if(data == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *ppdata = data; @@ -1543,7 +1538,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if ((mem_ctx = talloc_init()) == NULL) { DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } prs_init(&pd, 0, mem_ctx, MARSHALL); @@ -1601,10 +1596,10 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); if(total_parameter_count < 8) - return(ERROR(ERRDOS,ERRbadfunc)); + return ERROR_DOS(ERRDOS,ERRbadfunc); if((fsp = file_fsp(params,0)) == NULL) - return(ERROR(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); security_info_sent = IVAL(params,4); @@ -1612,7 +1607,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, (unsigned int)security_info_sent )); if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code)) - return (ERROR(error_class, error_code)); + return ERROR_DOS(error_class, error_code); send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); return -1; @@ -1632,7 +1627,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); logged_message = True; /* Only print this once... */ } - return(ERROR(ERRSRV,ERRnosupport)); + return ERROR_DOS(ERRSRV,ERRnosupport); } /**************************************************************************** @@ -1674,7 +1669,7 @@ due to being in oplock break state.\n" )); if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { END_PROFILE(SMBnttrans); - return (ERROR(ERRSRV,ERRaccess)); + return ERROR_DOS(ERRSRV,ERRaccess); } outsize = set_message(outbuf,0,0,True); @@ -1688,7 +1683,7 @@ due to being in oplock break state.\n" )); DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", CVAL(inbuf, smb_wct), 19 + (setup_count/2))); END_PROFILE(SMBnttrans); - return(ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } /* Allocate the space for the setup, the maximum needed parameters and data */ @@ -1707,7 +1702,7 @@ due to being in oplock break state.\n" )); safe_free(data); DEBUG(0,("reply_nttrans : Out of memory\n")); END_PROFILE(SMBnttrans); - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } /* Copy the param and data bytes sent with this request into @@ -1761,7 +1756,7 @@ due to being in oplock break state.\n" )); if(setup) free(setup); END_PROFILE(SMBnttrans); - return(ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } /* Revise total_params and total_data in case they have changed downwards */ @@ -1837,7 +1832,7 @@ due to being in oplock break state.\n" )); if(data) free(data); END_PROFILE(SMBnttrans); - return (ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } /* As we do not know how many data packets will need to be diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2e1ddb07fb..6a1eac7602 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -200,7 +200,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -969,8 +968,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; - fsp->wcp = NULL; /* Write cache pointer. */ + fsp->wcp = NULL; /* Write cache pointer. */ conn->num_files_open++; @@ -1133,7 +1131,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; conn->num_files_open++; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index c7e0c3a5e5..162ad1603d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -59,7 +59,7 @@ int reply_open_pipe_and_X(connection_struct *conn, /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); DEBUG(4,("Opening pipe %s.\n", pipe_name)); @@ -69,7 +69,7 @@ int reply_open_pipe_and_X(connection_struct *conn, break; if (pipe_names[i].client_pipe == NULL) - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); /* Strip \PIPE\ off the name. */ pstrcpy(fname, pipe_name + PIPELEN); @@ -89,7 +89,7 @@ int reply_open_pipe_and_X(connection_struct *conn, smb_ofun |= FILE_CREATE_IF_NOT_EXIST; p = open_rpc_pipe_p(fname, conn, vuid); - if (!p) return(ERROR(ERRSRV,ERRnofids)); + if (!p) return(ERROR_DOS(ERRSRV,ERRnofids)); /* Prepare the reply */ set_message(outbuf,15,0,True); @@ -125,7 +125,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) char *data; if (!p) - return(ERROR(ERRDOS,ERRbadfid)); + return(ERROR_DOS(ERRDOS,ERRbadfid)); data = smb_buf(inbuf) + 3; @@ -165,7 +165,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) char *data; if (!p) - return(ERROR(ERRDOS,ERRbadfid)); + return(ERROR_DOS(ERRDOS,ERRbadfid)); data = smb_base(inbuf) + smb_doff; @@ -225,7 +225,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) #endif if (!p) - return(ERROR(ERRDOS,ERRbadfid)); + return(ERROR_DOS(ERRDOS,ERRbadfid)); set_message(outbuf,12,0,True); data = smb_buf(outbuf); @@ -254,12 +254,12 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) int outsize = set_message(outbuf,0,0,True); if (!p) - return(ERROR(ERRDOS,ERRbadfid)); + return(ERROR_DOS(ERRDOS,ERRbadfid)); DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum)); if (!close_rpc_pipe_hnd(p, conn)) - return(ERROR(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); return(outsize); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2b75197c38..ce1e855e29 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -352,9 +352,9 @@ struct smb_message_struct /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER}, /* 0x1c */ { "SMBreadBs",NULL,AS_USER}, /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER}, -/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER}, -/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER}, -/* 0x20 */ { "SMBwritec",NULL,AS_USER}, +/* 0x1e */ { NULL,NULL,0}, +/* 0x1f */ { NULL,NULL,0}, +/* 0x20 */ { NULL,NULL,0}, /* 0x21 */ { NULL, NULL, 0 }, /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, @@ -695,7 +695,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* does this protocol need a valid tree connection? */ if ((flags & AS_USER) && !conn) { - return ERROR(ERRSRV, ERRinvnid); + return ERROR_DOS(ERRSRV, ERRinvnid); } @@ -704,7 +704,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if (flags & AS_GUEST) flags &= ~AS_USER; else - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); } /* this code is to work around a bug is MS client 3 without @@ -715,23 +715,23 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* does it need write permission? */ if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); /* ipc services are limited */ if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) { - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); } /* load service specific parameters */ if (conn && !become_service(conn,(flags & AS_USER)?True:False)) { - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); } /* does this protocol need to be run as guest? */ if ((flags & AS_GUEST) && (!become_guest() || !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); } last_inbuf = inbuf; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 02531bd1cd..236bb48ce9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -162,9 +162,9 @@ work out what error to give to a failed connection static int connection_error(char *inbuf,char *outbuf,int ecode) { if (ecode == ERRnoipc || ecode == ERRnosuchshare) - return(ERROR(ERRDOS,ecode)); + return(ERROR_DOS(ERRDOS,ecode)); - return(ERROR(ERRSRV,ecode)); + return(ERROR_DOS(ERRSRV,ecode)); } @@ -272,7 +272,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (passlen > MAX_PASS_LEN) { overflow_attack(passlen); - return(ERROR(ERRDOS,ERRbuftoosmall)); + return(ERROR_DOS(ERRDOS,ERRbuftoosmall)); } memcpy(password,smb_buf(inbuf),passlen); @@ -295,7 +295,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt q = strchr_m(path+2,'\\'); if (!q) { END_PROFILE(SMBtconX); - return(ERROR(ERRDOS,ERRnosuchshare)); + return(ERROR_DOS(ERRDOS,ERRnosuchshare)); } fstrcpy(service,q+1); } @@ -391,7 +391,7 @@ int reply_unknown(char *inbuf,char *outbuf) DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n", smb_fn_name(type), type, type)); - return(ERROR(ERRSRV,ERRunknownsmb)); + return(ERROR_DOS(ERRSRV,ERRunknownsmb)); } @@ -418,7 +418,7 @@ int reply_ioctl(connection_struct *conn, break; default: END_PROFILE(SMBioctl); - return(ERROR(ERRSRV,ERRnosupport)); + return(ERROR_DOS(ERRSRV,ERRnosupport)); } outsize = set_message(outbuf,8,replysize+1,True); @@ -496,72 +496,50 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out ret = pdb_getsampwnam(sam_trust_acct, user); } else { DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); pdb_free_sam(sam_trust_acct); - return(ERROR(0, NT_STATUS_LOGON_FAILURE)); + return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); } if (ret == False) { /* lkclXXXX: workstation entry doesn't exist */ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); pdb_free_sam(sam_trust_acct); - return(ERROR(0, NT_STATUS_NO_SUCH_USER)); + return(ERROR_NT(NT_STATUS_NO_SUCH_USER)); } else { if ((smb_passlen != 24) || (smb_nt_passlen != 24)) { DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); pdb_free_sam(sam_trust_acct); - return(ERROR(0, NT_STATUS_LOGON_FAILURE)); + return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); } if (!smb_password_ok(sam_trust_acct, &user_info, &server_info)) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - pdb_free_sam(sam_trust_acct); - return(ERROR(0, NT_STATUS_LOGON_FAILURE)); + pdb_free_sam(sam_trust_acct); + return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); } acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct); pdb_free_sam(sam_trust_acct); if (acct_ctrl & ACB_DOMTRUST) { DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); + return(ERROR_NT(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); } if (acct_ctrl & ACB_SVRTRUST) { DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); + return(ERROR_NT(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); } if (acct_ctrl & ACB_WSTRUST) { DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); + return(ERROR_NT(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); } } /* don't know what to do: indicate logon failure */ - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, NT_STATUS_LOGON_FAILURE)); + return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); } -/**************************************************************************** - Return a bad password error configured for the correct client type. -****************************************************************************/ - -static int bad_password_error(char *inbuf,char *outbuf) -{ - - if (global_client_caps & CAP_STATUS32) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0,NT_STATUS_LOGON_FAILURE)); - } - - return(ERROR(ERRSRV,ERRbadpw)); -} /**************************************************************************** reply to a session setup command @@ -598,7 +576,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int smb_apasslen = SVAL(inbuf,smb_vwv7); if (smb_apasslen > MAX_PASS_LEN) { overflow_attack(smb_apasslen); - return(ERROR(ERRDOS,ERRbuftoosmall)); + return(ERROR_DOS(ERRDOS,ERRbuftoosmall)); } memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); @@ -632,7 +610,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (passlen1 > MAX_PASS_LEN) { overflow_attack(passlen1); - return(ERROR(ERRDOS,ERRbuftoosmall)); + return ERROR_DOS(ERRDOS,ERRbuftoosmall); } passlen1 = MIN(passlen1, MAX_PASS_LEN); @@ -719,7 +697,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int alpha_strcpy(user, user, ". _-$", sizeof(user)); alpha_strcpy(domain, domain, ". _-", sizeof(domain)); if (strstr(user, "..") || strstr(domain,"..")) { - return bad_password_error(inbuf, outbuf); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } if (lp_security() == SEC_SHARE) { @@ -754,7 +732,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!*user && !*smb_apasswd && !*domain) { DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); END_PROFILE(SMBsesssetupX); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } } @@ -825,9 +803,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int { if (lp_map_to_guest() == NEVER_MAP_TO_GUEST) { - DEBUG(1,("Rejecting user '%s': authentication failed\n", user)); - END_PROFILE(SMBsesssetupX); - return bad_password_error(inbuf,outbuf); + DEBUG(1,("Rejecting user '%s': authentication failed\n", user)); + END_PROFILE(SMBsesssetupX); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) @@ -836,7 +814,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int { DEBUG(1,("Rejecting user '%s': bad password\n", user)); END_PROFILE(SMBsesssetupX); - return bad_password_error(inbuf,outbuf); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } } @@ -889,7 +867,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); END_PROFILE(SMBsesssetupX); - return bad_password_error(inbuf,outbuf); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } gid = pw->pw_gid; uid = pw->pw_uid; @@ -905,7 +883,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name); if (sess_vuid == -1) { - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -949,28 +927,15 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ok = S_ISDIR(sbuf.st_mode); } - if (!ok) - { + if (!ok) { /* We special case this - as when a Windows machine is parsing a path is steps through the components one at a time - if a component fails it expects ERRbadpath, not ERRbadfile. */ - if(errno == ENOENT) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - -#if 0 - /* Ugly - NT specific hack - maybe not needed ? (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; + if(errno == ENOENT) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } -#endif return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -1258,7 +1223,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return (UNIXERROR(ERRDOS,ERRnofids)); } END_PROFILE(SMBsearch); - return(ERROR(ERRDOS,ERRnofids)); + return ERROR_DOS(ERRDOS,ERRnofids); } dptr_set_wcard(dptr_num, strdup(mask)); } @@ -1375,7 +1340,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (status_len == 0) { END_PROFILE(SMBfclose); - return(ERROR(ERRSRV,ERRsrverror)); + return ERROR_DOS(ERRSRV,ERRsrverror); } memcpy(status,p,21); @@ -1446,7 +1411,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG(3,("attempt to open a directory %s\n",fname)); close_file(fsp,False); END_PROFILE(SMBopen); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } outsize = set_message(outbuf,7,0,True); @@ -1505,7 +1470,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); } else { END_PROFILE(SMBopenX); - return (ERROR(ERRSRV,ERRaccess)); + return ERROR_DOS(ERRSRV,ERRaccess); } } @@ -1538,7 +1503,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (fmode & aDIR) { close_file(fsp,False); END_PROFILE(SMBopenX); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } /* If the caller set the extended oplock request bit @@ -1798,139 +1763,140 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) ****************************************************************************/ int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, - int dirtype, char *name) + int dirtype, char *name) { - pstring directory; - pstring mask; - char *p; - int count=0; - int error = ERRnoaccess; - BOOL has_wild; - BOOL exists=False; - BOOL bad_path = False; - BOOL rc = True; - SMB_STRUCT_STAT sbuf; - - *directory = *mask = 0; - - rc = unix_convert(name,conn,0,&bad_path,&sbuf); - - p = strrchr_m(name,'/'); - if (!p) { - pstrcpy(directory,"./"); - pstrcpy(mask,name); - } else { - *p = 0; - pstrcpy(directory,name); - pstrcpy(mask,p+1); - } - - /* - * We should only check the mangled cache - * here if unix_convert failed. This means - * that the path in 'mask' doesn't exist - * on the file system and so we need to look - * for a possible mangle. This patch from - * Tine Smukavec . - */ - - if (!rc && is_mangled(mask)) - check_mangled_cache( mask ); - - has_wild = ms_has_wild(mask); - - if (!has_wild) { - pstrcat(directory,"/"); - pstrcat(directory,mask); - if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory)) - count++; - if (!count) - exists = vfs_file_exist(conn,directory,&sbuf); - } else { - void *dirptr = NULL; - char *dname; - - if (check_name(directory,conn)) - dirptr = OpenDir(conn, directory, True); - - /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then - the pattern matches against the long name, otherwise the short name - We don't implement this yet XXXX - */ - - if (dirptr) - { - error = ERRbadfile; - - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - - while ((dname = ReadDirName(dirptr))) - { - pstring fname; - pstrcpy(fname,dname); - - if(!mask_match(fname, mask, case_sensitive)) continue; + pstring directory; + pstring mask; + char *p; + int count=0; + int error = ERRnoaccess; + BOOL has_wild; + BOOL exists=False; + BOOL bad_path = False; + BOOL rc = True; + SMB_STRUCT_STAT sbuf; + + *directory = *mask = 0; + + rc = unix_convert(name,conn,0,&bad_path,&sbuf); + + p = strrchr_m(name,'/'); + if (!p) { + pstrcpy(directory,"./"); + pstrcpy(mask,name); + } else { + *p = 0; + pstrcpy(directory,name); + pstrcpy(mask,p+1); + } + + /* + * We should only check the mangled cache + * here if unix_convert failed. This means + * that the path in 'mask' doesn't exist + * on the file system and so we need to look + * for a possible mangle. This patch from + * Tine Smukavec . + */ + + if (!rc && is_mangled(mask)) + check_mangled_cache( mask ); + + has_wild = ms_has_wild(mask); + + if (!has_wild) { + pstrcat(directory,"/"); + pstrcat(directory,mask); + if (!can_delete(directory,conn,dirtype)) { + return ERROR_NT(NT_STATUS_SHARING_VIOLATION); + } + if (vfs_unlink(conn,directory) == 0) { + count++; + } + if (!count) + exists = vfs_file_exist(conn,directory,&sbuf); + } else { + void *dirptr = NULL; + char *dname; + + if (check_name(directory,conn)) + dirptr = OpenDir(conn, directory, True); + + /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then + the pattern matches against the long name, otherwise the short name + We don't implement this yet XXXX + */ + + if (dirptr) { + error = ERRbadfile; + + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); - error = ERRnoaccess; - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - if (!can_delete(fname,conn,dirtype)) continue; - if (!vfs_unlink(conn,fname)) count++; - DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); - } - CloseDir(dirptr); - } - } - - if (count == 0) { - if (exists) - return(ERROR(ERRDOS,error)); - else { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,error)); - } - } - - return 0; + while ((dname = ReadDirName(dirptr))) { + pstring fname; + pstrcpy(fname,dname); + + if(!mask_match(fname, mask, case_sensitive)) continue; + + error = ERRnoaccess; + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + if (!can_delete(fname,conn,dirtype)) continue; + if (vfs_unlink(conn,fname) == 0) count++; + DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); + } + CloseDir(dirptr); + } + } + + if (count == 0) { + if (exists) + return ERROR_DOS(ERRDOS,error); + else { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,error)); + } + } + + return 0; } /**************************************************************************** Reply to a unlink ****************************************************************************/ -int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, + int dum_buffsize) { - int outsize = 0; - pstring name; - int dirtype; - START_PROFILE(SMBunlink); - - dirtype = SVAL(inbuf,smb_vwv0); - - srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE); - - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - - DEBUG(3,("reply_unlink : %s\n",name)); - - outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name); - if(outsize == 0) { - - /* - * Win2k needs a changenotify request response before it will - * update after a rename.. - */ - - process_pending_change_notify_queue((time_t)0); - - outsize = set_message(outbuf,0,0,True); - } + int outsize = 0; + pstring name; + int dirtype; + START_PROFILE(SMBunlink); + + dirtype = SVAL(inbuf,smb_vwv0); + + srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE); + + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + + DEBUG(3,("reply_unlink : %s\n",name)); + + outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name); + if(outsize == 0) { + /* + * Win2k needs a changenotify request response before it will + * update after a rename.. + */ + process_pending_change_notify_queue((time_t)0); + + outsize = set_message(outbuf,0,0,True); + } - END_PROFILE(SMBunlink); - return(outsize); + END_PROFILE(SMBunlink); + return outsize; } @@ -2089,68 +2055,69 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s ****************************************************************************/ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz) { - ssize_t nread = -1; - char *data; - int outsize = 0; - SMB_OFF_T startpos; - size_t numtoread; - int eclass; - uint32 ecode; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBlockread); + ssize_t nread = -1; + char *data; + int outsize = 0; + SMB_OFF_T startpos; + size_t numtoread; + NTSTATUS status; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBlockread); - CHECK_FSP(fsp,conn); - CHECK_READ(fsp); - CHECK_ERROR(fsp); + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); - release_level_2_oplocks_on_change(fsp); + release_level_2_oplocks_on_change(fsp); - numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + numtoread = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); - outsize = set_message(outbuf,5,3,True); - numtoread = MIN(BUFFER_SIZE-outsize,numtoread); - data = smb_buf(outbuf) + 3; - - /* - * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+ - * protocol request that predates the read/write lock concept. - * Thus instead of asking for a read lock here we need to ask - * for a write lock. JRA. - */ + outsize = set_message(outbuf,5,3,True); + numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + data = smb_buf(outbuf) + 3; + + /* + * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+ + * protocol request that predates the read/write lock concept. + * Thus instead of asking for a read lock here we need to ask + * for a write lock. JRA. + */ + + status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), + (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK); - if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) { - if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(inbuf, length, -1, 0)) + if (status != NT_STATUS_NOPROBLEMO) { + if (lp_blocking_locks(SNUM(conn))) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, -1, 0)) + END_PROFILE(SMBlockread); + return -1; + } END_PROFILE(SMBlockread); - return -1; - } - END_PROFILE(SMBlockread); - return (ERROR(eclass,ecode)); - } - - nread = read_file(fsp,data,startpos,numtoread); - - if (nread < 0) { - END_PROFILE(SMBlockread); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + return ERROR_NT(status); + } - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - SSVAL(smb_buf(outbuf),1,nread); + nread = read_file(fsp,data,startpos,numtoread); - DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n", - fsp->fnum, (int)numtoread, (int)nread ) ); + if (nread < 0) { + END_PROFILE(SMBlockread); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + outsize += nread; + SSVAL(outbuf,smb_vwv0,nread); + SSVAL(outbuf,smb_vwv5,nread+3); + SSVAL(smb_buf(outbuf),1,nread); + + DEBUG(3,("lockread fnum=%d num=%d nread=%d\n", + fsp->fnum, (int)numtoread, (int)nread)); - END_PROFILE(SMBlockread); - return(outsize); + END_PROFILE(SMBlockread); + return(outsize); } @@ -2170,23 +2137,23 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int CHECK_FSP(fsp,conn); CHECK_READ(fsp); - CHECK_ERROR(fsp); numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); - + + outsize = set_message(outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { END_PROFILE(SMBread); - return(ERROR(ERRDOS,ERRlock)); + return ERROR_DOS(ERRDOS,ERRlock); } if (numtoread > 0) nread = read_file(fsp,data,startpos,numtoread); - + if (nread < 0) { END_PROFILE(SMBread); return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2227,7 +2194,6 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt CHECK_FSP(fsp,conn); CHECK_READ(fsp); - CHECK_ERROR(fsp); set_message(outbuf,12,0,True); data = smb_buf(outbuf); @@ -2249,7 +2215,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) )); END_PROFILE(SMBreadX); - return(ERROR(ERRDOS,ERRbadaccess)); + return ERROR_DOS(ERRDOS,ERRbadaccess); } #endif /* LARGE_SMB_OFF_T */ @@ -2258,10 +2224,10 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { END_PROFILE(SMBreadX); - return(ERROR(ERRDOS,ERRlock)); + return ERROR_DOS(ERRDOS,ERRlock); } nread = read_file(fsp,data,startpos,smb_maxcnt); - + if (nread < 0) { END_PROFILE(SMBreadX); return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2297,7 +2263,6 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); - CHECK_ERROR(fsp); tcount = IVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv3); @@ -2319,7 +2284,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwritebraw); - return(ERROR(ERRDOS,ERRlock)); + return ERROR_DOS(ERRDOS,ERRlock); } if (numtowrite>0) @@ -2399,86 +2364,66 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, reply to a writeunlock (core+) ****************************************************************************/ -int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, + int size, int dum_buffsize) { - ssize_t nwritten = -1; - size_t numtowrite; - SMB_OFF_T startpos; - char *data; - int eclass; - uint32 ecode; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - int outsize = 0; - START_PROFILE(SMBwriteunlock); - - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); - CHECK_ERROR(fsp); - - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - data = smb_buf(inbuf) + 3; - - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { - END_PROFILE(SMBwriteunlock); - return(ERROR(ERRDOS,ERRlock)); - } - - /* The special X/Open SMB protocol handling of - zero length writes is *NOT* done for - this call */ - if(numtowrite == 0) - nwritten = 0; - else - nwritten = write_file(fsp,data,startpos,numtowrite); - - if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); - - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { - END_PROFILE(SMBwriteunlock); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) { - END_PROFILE(SMBwriteunlock); - return(ERROR(eclass,ecode)); - } + ssize_t nwritten = -1; + size_t numtowrite; + SMB_OFF_T startpos; + char *data; + NTSTATUS status; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int outsize = 0; + START_PROFILE(SMBwriteunlock); + + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); - outsize = set_message(outbuf,1,0,True); - - SSVAL(outbuf,smb_vwv0,nwritten); + numtowrite = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + data = smb_buf(inbuf) + 3; - DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n", - fsp->fnum, (int)numtowrite, (int)nwritten ) ); - - END_PROFILE(SMBwriteunlock); - return(outsize); -} - -/**************************************************************************** - Return correct error for space allocation fail. -****************************************************************************/ + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, + WRITE_LOCK,False)) { + END_PROFILE(SMBwriteunlock); + return ERROR_DOS(ERRDOS,ERRlock); + } -int allocate_space_error(char *inbuf,char *outbuf, int errno_val) -{ - errno = errno_val; - if (!(global_client_caps & CAP_STATUS32)) - return (UNIXERROR(ERRHRD,ERRdiskfull)); - - /* Use more specific WNT/W2K error codes. */ -#ifdef EDQUOT - if (errno_val == ENOSPC || errno_val == EDQUOT) { -#else - if (errno_val == ENOSPC) { -#endif - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0,NT_STATUS_DISK_FULL)); + /* The special X/Open SMB protocol handling of + zero length writes is *NOT* done for + this call */ + if(numtowrite == 0) + nwritten = 0; + else + nwritten = write_file(fsp,data,startpos,numtowrite); + + if (lp_syncalways(SNUM(conn))) + sync_file(conn,fsp); + + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + END_PROFILE(SMBwriteunlock); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - return (UNIXERROR(ERRHRD,ERRdiskfull)); + status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, + (SMB_BIG_UINT)startpos); + if (status != NT_STATUS_NOPROBLEMO) { + END_PROFILE(SMBwriteunlock); + return ERROR_NT(status); + } + + outsize = set_message(outbuf,1,0,True); + + SSVAL(outbuf,smb_vwv0,nwritten); + + DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n", + fsp->fnum, (int)numtowrite, (int)nwritten)); + + END_PROFILE(SMBwriteunlock); + return outsize; } + /**************************************************************************** Reply to a write. ****************************************************************************/ @@ -2501,7 +2446,6 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); - CHECK_ERROR(fsp); numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -2509,7 +2453,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwrite); - return(ERROR(ERRDOS,ERRlock)); + return ERROR_DOS(ERRDOS,ERRlock); } /* X/Open SMB protocol says that if smb_vwv1 is @@ -2519,9 +2463,8 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d /* This is actually an allocate call, not set EOF. JRA */ nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos); if (nwritten < 0) { - int ret = allocate_space_error(inbuf, outbuf, errno); - END_PROFILE(SMBwrite); - return ret; + END_PROFILE(SMBwrite); + return ERROR_NT(NT_STATUS_DISK_FULL); } } else nwritten = write_file(fsp,data,startpos,numtowrite); @@ -2575,7 +2518,6 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); - CHECK_ERROR(fsp); /* Deal with possible LARGE_WRITEX */ if (large_writeX) @@ -2583,7 +2525,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { END_PROFILE(SMBwriteX); - return(ERROR(ERRDOS,ERRbadmem)); + return ERROR_DOS(ERRDOS,ERRbadmem); } data = smb_base(inbuf) + smb_doff; @@ -2605,7 +2547,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) )); END_PROFILE(SMBwriteX); - return(ERROR(ERRDOS,ERRbadaccess)); + return ERROR_DOS(ERRDOS,ERRbadaccess); } #endif /* LARGE_SMB_OFF_T */ @@ -2613,7 +2555,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwriteX); - return(ERROR(ERRDOS,ERRlock)); + return ERROR_DOS(ERRDOS,ERRlock); } /* X/Open SMB protocol says that, unlike SMBwrite @@ -2666,7 +2608,6 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int START_PROFILE(SMBlseek); CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); flush_write_cache(fsp, SEEK_FLUSH); @@ -2745,9 +2686,6 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int START_PROFILE(SMBflush); CHECK_FSP(fsp,conn); - if (fsp) { - CHECK_ERROR(fsp); - } if (!fsp) { file_sync_all(conn); @@ -2806,12 +2744,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, if(!fsp || (fsp->conn != conn)) { END_PROFILE(SMBclose); - return(ERROR(ERRDOS,ERRbadfid)); - } - - if(HAS_CACHED_ERROR(fsp)) { - eclass = fsp->wbmpx_ptr->wr_errclass; - err = fsp->wbmpx_ptr->wr_error; + return ERROR_DOS(ERRDOS,ERRbadfid); } if(fsp->is_directory || fsp->stat_open) { @@ -2862,7 +2795,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, /* We have a cached error */ if(eclass || err) { END_PROFILE(SMBclose); - return(ERROR(eclass,err)); + return ERROR_DOS(eclass,err); } END_PROFILE(SMBclose); @@ -2889,7 +2822,6 @@ int reply_writeclose(connection_struct *conn, CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); - CHECK_ERROR(fsp); numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -2898,7 +2830,7 @@ int reply_writeclose(connection_struct *conn, if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwriteclose); - return(ERROR(ERRDOS,ERRlock)); + return ERROR_DOS(ERRDOS,ERRlock); } nwritten = write_file(fsp,data,startpos,numtowrite); @@ -2938,13 +2870,11 @@ int reply_lock(connection_struct *conn, { int outsize = set_message(outbuf,0,0,True); SMB_BIG_UINT count,offset; - int eclass; - uint32 ecode; + NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBlock); CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); release_level_2_oplocks_on_change(fsp); @@ -2954,20 +2884,21 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fd, fsp->fnum, (double)offset, (double)count)); - if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) { - if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(inbuf, length, -1, 0)) { - END_PROFILE(SMBlock); - return -1; - } - } - END_PROFILE(SMBlock); - return (ERROR(eclass,ecode)); + status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK); + if (status != NT_STATUS_NOPROBLEMO) { + if (status != NT_STATUS_NOPROBLEMO && lp_blocking_locks(SNUM(conn))) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, -1, 0)) { + END_PROFILE(SMBlock); + return -1; + } + } + END_PROFILE(SMBlock); + return ERROR_NT(status); } END_PROFILE(SMBlock); @@ -2978,31 +2909,31 @@ int reply_lock(connection_struct *conn, /**************************************************************************** reply to a unlock ****************************************************************************/ -int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, + int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); - SMB_BIG_UINT count,offset; - int eclass; - uint32 ecode; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBunlock); - - CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); - - count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); - offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); + int outsize = set_message(outbuf,0,0,True); + SMB_BIG_UINT count,offset; + NTSTATUS status; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBunlock); - if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) { - END_PROFILE(SMBunlock); - return (ERROR(eclass,ecode)); - } + CHECK_FSP(fsp,conn); + + count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); + offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); + + status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset); + if (status != NT_STATUS_NOPROBLEMO) { + END_PROFILE(SMBunlock); + return ERROR_NT(status); + } - DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", - fsp->fd, fsp->fnum, (double)offset, (double)count ) ); - - END_PROFILE(SMBunlock); - return(outsize); + DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", + fsp->fd, fsp->fnum, (double)offset, (double)count ) ); + + END_PROFILE(SMBunlock); + return(outsize); } @@ -3021,7 +2952,7 @@ int reply_tdis(connection_struct *conn, if (!conn) { DEBUG(4,("Invalid connection in tdis\n")); END_PROFILE(SMBtdis); - return(ERROR(ERRSRV,ERRinvnid)); + return ERROR_DOS(ERRSRV,ERRinvnid); } conn->used = False; @@ -3087,7 +3018,7 @@ int reply_printopen(connection_struct *conn, if (!CAN_PRINT(conn)) { END_PROFILE(SMBsplopen); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } /* Open for exclusive use, write only. */ @@ -3121,11 +3052,10 @@ int reply_printclose(connection_struct *conn, START_PROFILE(SMBsplclose); CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); if (!CAN_PRINT(conn)) { END_PROFILE(SMBsplclose); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } DEBUG(3,("printclose fd=%d fnum=%d\n", @@ -3161,7 +3091,7 @@ int reply_printqueue(connection_struct *conn, get it right (tridge) */ if (!CAN_PRINT(conn)) { END_PROFILE(SMBsplretq); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } SSVAL(outbuf,smb_vwv0,0); @@ -3227,12 +3157,11 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ if (!CAN_PRINT(conn)) { END_PROFILE(SMBsplwr); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); - CHECK_ERROR(fsp); numtowrite = SVAL(smb_buf(inbuf),1); data = smb_buf(inbuf) + 3; @@ -3771,7 +3700,7 @@ int rename_internals(connection_struct *conn, if (count == 0) { if (exists) - return(ERROR(ERRDOS,error)); + return ERROR_DOS(ERRDOS,error); else { if((errno == ENOENT) && (bad_path1 || bad_path2)) { unix_ERR_class = ERRDOS; @@ -3938,7 +3867,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* can't currently handle inter share copies XXXX */ DEBUG(3,("Rejecting inter-share copy\n")); END_PROFILE(SMBcopy); - return(ERROR(ERRSRV,ERRinvdevice)); + return ERROR_DOS(ERRSRV,ERRinvdevice); } RESOLVE_DFSPATH(name, conn, inbuf, outbuf); @@ -3951,19 +3880,19 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if ((flags&1) && target_is_directory) { END_PROFILE(SMBcopy); - return(ERROR(ERRDOS,ERRbadfile)); + return ERROR_DOS(ERRDOS,ERRbadfile); } if ((flags&2) && !target_is_directory) { END_PROFILE(SMBcopy); - return(ERROR(ERRDOS,ERRbadpath)); + return ERROR_DOS(ERRDOS,ERRbadpath); } if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); END_PROFILE(SMBcopy); - return(ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } p = strrchr_m(name,'/'); @@ -4045,7 +3974,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (exists) { END_PROFILE(SMBcopy); - return(ERROR(ERRDOS,error)); + return ERROR_DOS(ERRDOS,error); } else { if((errno == ENOENT) && (bad_path1 || bad_path2)) @@ -4079,7 +4008,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size snum = SNUM(conn); if (!CAN_SETDIR(snum)) { END_PROFILE(pathworks_setdir); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE); @@ -4095,7 +4024,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!ok) { END_PROFILE(pathworks_setdir); - return(ERROR(ERRDOS,ERRbadpath)); + return ERROR_DOS(ERRDOS,ERRbadpath); } outsize = set_message(outbuf,0,0,True); @@ -4212,182 +4141,180 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = file_fsp(inbuf,smb_vwv2); - unsigned char locktype = CVAL(inbuf,smb_vwv3); - unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint16 num_locks = SVAL(inbuf,smb_vwv7); - SMB_BIG_UINT count = 0, offset = 0; - uint16 lock_pid; - int32 lock_timeout = IVAL(inbuf,smb_vwv4); - int i; - char *data; - uint32 ecode=0, dummy2; - int eclass=0, dummy1; - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; - BOOL err; - START_PROFILE(SMBlockingX); - - CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); - - data = smb_buf(inbuf); - - /* Check if this is an oplock break on a file - we have granted an oplock on. - */ - if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) - { - /* Client can insist on breaking to none. */ - BOOL break_to_none = (oplocklevel == 0); - - DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n", - (unsigned int)oplocklevel, fsp->fnum )); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); + unsigned char locktype = CVAL(inbuf,smb_vwv3); + unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); + uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint16 num_locks = SVAL(inbuf,smb_vwv7); + SMB_BIG_UINT count = 0, offset = 0; + uint16 lock_pid; + int32 lock_timeout = IVAL(inbuf,smb_vwv4); + int i; + char *data; + BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; + BOOL err; + NTSTATUS status; - /* - * Make sure we have granted an exclusive or batch oplock on this file. - */ + START_PROFILE(SMBlockingX); + + CHECK_FSP(fsp,conn); + + data = smb_buf(inbuf); + + /* Check if this is an oplock break on a file + we have granted an oplock on. + */ + if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { + /* Client can insist on breaking to none. */ + BOOL break_to_none = (oplocklevel == 0); + + DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n", + (unsigned int)oplocklevel, fsp->fnum )); - if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - { - DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ + /* + * Make sure we have granted an exclusive or batch oplock on this file. + */ + + if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); - /* if this is a pure oplock break request then don't send a reply */ - if (num_locks == 0 && num_ulocks == 0) { - END_PROFILE(SMBlockingX); - return -1; - } else { - END_PROFILE(SMBlockingX); - return ERROR(ERRDOS,ERRlock); - } - } - - if (remove_oplock(fsp, break_to_none) == False) { - DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n", - fsp->fsp_name )); - } - - /* if this is a pure oplock break request then don't send a reply */ - if (num_locks == 0 && num_ulocks == 0) - { - /* Sanity check - ensure a pure oplock break is not a - chained request. */ - if(CVAL(inbuf,smb_vwv0) != 0xff) - DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", - (unsigned int)CVAL(inbuf,smb_vwv0) )); - END_PROFILE(SMBlockingX); - return -1; - } - } - - /* - * We do this check *after* we have checked this is not a oplock break - * response message. JRA. - */ - - release_level_2_oplocks_on_change(fsp); - - /* Data now points at the beginning of the list - of smb_unlkrng structs */ - for(i = 0; i < (int)num_ulocks; i++) { - lock_pid = get_lock_pid( data, i, large_file_format); - count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); - - /* - * There is no error code marked "stupid client bug".... :-). - */ - if(err) { - END_PROFILE(SMBlockingX); - return ERROR(ERRDOS,ERRnoaccess); - } - - DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n", - (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); - - if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) { - END_PROFILE(SMBlockingX); - return ERROR(eclass,ecode); - } - } - - /* Setup the timeout in seconds. */ - lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000); - - /* Now do any requested locks */ - data += ((large_file_format ? 20 : 10)*num_ulocks); - - /* Data now points at the beginning of the list - of smb_lkrng structs */ + /* if this is a pure oplock break request then don't send a reply */ + if (num_locks == 0 && num_ulocks == 0) { + END_PROFILE(SMBlockingX); + return -1; + } else { + END_PROFILE(SMBlockingX); + return ERROR_DOS(ERRDOS,ERRlock); + } + } - for(i = 0; i < (int)num_locks; i++) { - lock_pid = get_lock_pid( data, i, large_file_format); - count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); + if (remove_oplock(fsp, break_to_none) == False) { + DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n", + fsp->fsp_name )); + } + + /* if this is a pure oplock break request then don't send a reply */ + if (num_locks == 0 && num_ulocks == 0) { + /* Sanity check - ensure a pure oplock break is not a + chained request. */ + if(CVAL(inbuf,smb_vwv0) != 0xff) + DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", + (unsigned int)CVAL(inbuf,smb_vwv0) )); + END_PROFILE(SMBlockingX); + return -1; + } + } - /* - * There is no error code marked "stupid client bug".... :-). - */ - if(err) { - END_PROFILE(SMBlockingX); - return ERROR(ERRDOS,ERRnoaccess); - } - - DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n", - (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); + /* + * We do this check *after* we have checked this is not a oplock break + * response message. JRA. + */ + + release_level_2_oplocks_on_change(fsp); + + /* Data now points at the beginning of the list + of smb_unlkrng structs */ + for(i = 0; i < (int)num_ulocks; i++) { + lock_pid = get_lock_pid( data, i, large_file_format); + count = get_lock_count( data, i, large_file_format); + offset = get_lock_offset( data, i, large_file_format, &err); + + /* + * There is no error code marked "stupid client bug".... :-). + */ + if(err) { + END_PROFILE(SMBlockingX); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), - &eclass, &ecode)) { - if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) { - END_PROFILE(SMBlockingX); - return -1; + DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n", + (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); + + status = do_unlock(fsp,conn,lock_pid,count,offset); + if (status != NT_STATUS_NOPROBLEMO) { + END_PROFILE(SMBlockingX); + return ERROR_NT(status); + } } - } - break; - } - } - /* If any of the above locks failed, then we must unlock - all of the previous locks (X/Open spec). */ - if(i != num_locks && num_locks != 0) { - /* - * Ensure we don't do a remove on the lock that just failed, - * as under POSIX rules, if we have a lock already there, we - * will delete it (and we shouldn't) ..... - */ - for(i--; i >= 0; i--) { - lock_pid = get_lock_pid( data, i, large_file_format); - count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); + /* Setup the timeout in seconds. */ + lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000); + + /* Now do any requested locks */ + data += ((large_file_format ? 20 : 10)*num_ulocks); + + /* Data now points at the beginning of the list + of smb_lkrng structs */ + + for(i = 0; i < (int)num_locks; i++) { + lock_pid = get_lock_pid( data, i, large_file_format); + count = get_lock_count( data, i, large_file_format); + offset = get_lock_offset( data, i, large_file_format, &err); + + /* + * There is no error code marked "stupid client bug".... :-). + */ + if(err) { + END_PROFILE(SMBlockingX); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n", + (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); + + status = do_lock(fsp,conn,lock_pid, count,offset, + ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); + if (status != NT_STATUS_NOPROBLEMO) { + if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) { + END_PROFILE(SMBlockingX); + return -1; + } + } + break; + } + } + + /* If any of the above locks failed, then we must unlock + all of the previous locks (X/Open spec). */ + if (i != num_locks && num_locks != 0) { + /* + * Ensure we don't do a remove on the lock that just failed, + * as under POSIX rules, if we have a lock already there, we + * will delete it (and we shouldn't) ..... + */ + for(i--; i >= 0; i--) { + lock_pid = get_lock_pid( data, i, large_file_format); + count = get_lock_count( data, i, large_file_format); + offset = get_lock_offset( data, i, large_file_format, &err); + + /* + * There is no error code marked "stupid client bug".... :-). + */ + if(err) { + END_PROFILE(SMBlockingX); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + do_unlock(fsp,conn,lock_pid,count,offset); + } + END_PROFILE(SMBlockingX); + return ERROR_NT(status); + } - /* - * There is no error code marked "stupid client bug".... :-). - */ - if(err) { + set_message(outbuf,2,0,True); + + DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", + fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); + END_PROFILE(SMBlockingX); - return ERROR(ERRDOS,ERRnoaccess); - } - - do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2); - } - END_PROFILE(SMBlockingX); - return ERROR(eclass,ecode); - } - - set_message(outbuf,2,0,True); - - DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", - fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); - - END_PROFILE(SMBlockingX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,outbuf,length,bufsize); } @@ -4411,14 +4338,13 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, /* this function doesn't seem to work - disable by default */ if (!lp_readbmpx()) { END_PROFILE(SMBreadBmpx); - return(ERROR(ERRSRV,ERRuseSTD)); + return ERROR_DOS(ERRSRV,ERRuseSTD); } outsize = set_message(outbuf,8,0,True); CHECK_FSP(fsp,conn); CHECK_READ(fsp); - CHECK_ERROR(fsp); startpos = IVAL(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); @@ -4434,7 +4360,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { END_PROFILE(SMBreadBmpx); - return(ERROR(ERRDOS,ERRlock)); + return ERROR_DOS(ERRDOS,ERRlock); } do @@ -4466,200 +4392,6 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, return(-1); } -/**************************************************************************** - reply to a SMBwritebmpx (write block multiplex primary) request -****************************************************************************/ - -int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) -{ - size_t numtowrite; - ssize_t nwritten = -1; - int outsize = 0; - SMB_OFF_T startpos; - size_t tcount; - BOOL write_through; - int smb_doff; - char *data; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBwriteBmpx); - - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); - CHECK_ERROR(fsp); - - tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); - write_through = BITSETW(inbuf+smb_vwv7,0); - numtowrite = SVAL(inbuf,smb_vwv10); - smb_doff = SVAL(inbuf,smb_vwv11); - - data = smb_base(inbuf) + smb_doff; - - /* If this fails we need to send an SMBwriteC response, - not an SMBwritebmpx - set this up now so we don't forget */ - CVAL(outbuf,smb_com) = SMBwritec; - - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) { - END_PROFILE(SMBwriteBmpx); - return(ERROR(ERRDOS,ERRlock)); - } - - nwritten = write_file(fsp,data,startpos,numtowrite); - - if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); - - if(nwritten < (ssize_t)numtowrite) { - END_PROFILE(SMBwriteBmpx); - return(UNIXERROR(ERRHRD,ERRdiskfull)); - } - - /* If the maximum to be written to this file - is greater than what we just wrote then set - up a secondary struct to be attached to this - fd, we will use this to cache error messages etc. */ - if((ssize_t)tcount > nwritten) - { - write_bmpx_struct *wbms; - if(fsp->wbmpx_ptr != NULL) - wbms = fsp->wbmpx_ptr; /* Use an existing struct */ - else - wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); - if(!wbms) - { - DEBUG(0,("Out of memory in reply_readmpx\n")); - END_PROFILE(SMBwriteBmpx); - return(ERROR(ERRSRV,ERRnoresource)); - } - wbms->wr_mode = write_through; - wbms->wr_discard = False; /* No errors yet */ - wbms->wr_total_written = nwritten; - wbms->wr_errclass = 0; - wbms->wr_error = 0; - fsp->wbmpx_ptr = wbms; - } - - /* We are returning successfully, set the message type back to - SMBwritebmpx */ - CVAL(outbuf,smb_com) = SMBwriteBmpx; - - outsize = set_message(outbuf,1,0,True); - - SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ - - DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n", - fsp->fnum, (int)numtowrite, (int)nwritten ) ); - - if (write_through && tcount==nwritten) { - /* we need to send both a primary and a secondary response */ - smb_setlen(outbuf,outsize - 4); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_writebmpx: send_smb failed.\n"); - - /* now the secondary */ - outsize = set_message(outbuf,1,0,True); - CVAL(outbuf,smb_com) = SMBwritec; - SSVAL(outbuf,smb_vwv0,nwritten); - } - - END_PROFILE(SMBwriteBmpx); - return(outsize); -} - - -/**************************************************************************** - reply to a SMBwritebs (write block multiplex secondary) request -****************************************************************************/ -int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) -{ - size_t numtowrite; - ssize_t nwritten = -1; - int outsize = 0; - SMB_OFF_T startpos; - size_t tcount; - BOOL write_through; - int smb_doff; - char *data; - write_bmpx_struct *wbms; - BOOL send_response = False; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBwriteBs); - - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); - - tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - numtowrite = SVAL(inbuf,smb_vwv6); - smb_doff = SVAL(inbuf,smb_vwv7); - - data = smb_base(inbuf) + smb_doff; - - /* We need to send an SMBwriteC response, not an SMBwritebs */ - CVAL(outbuf,smb_com) = SMBwritec; - - /* This fd should have an auxiliary struct attached, - check that it does */ - wbms = fsp->wbmpx_ptr; - if(!wbms) { - END_PROFILE(SMBwriteBs); - return(-1); - } - - /* If write through is set we can return errors, else we must - cache them */ - write_through = wbms->wr_mode; - - /* Check for an earlier error */ - if(wbms->wr_discard) { - END_PROFILE(SMBwriteBs); - return -1; /* Just discard the packet */ - } - - nwritten = write_file(fsp,data,startpos,numtowrite); - - if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); - - if (nwritten < (ssize_t)numtowrite) - { - if(write_through) - { - /* We are returning an error - we can delete the aux struct */ - if (wbms) free((char *)wbms); - fsp->wbmpx_ptr = NULL; - END_PROFILE(SMBwriteBs); - return(ERROR(ERRHRD,ERRdiskfull)); - } - END_PROFILE(SMBwriteBs); - return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); - } - - /* Increment the total written, if this matches tcount - we can discard the auxiliary struct (hurrah !) and return a writeC */ - wbms->wr_total_written += nwritten; - if(wbms->wr_total_written >= tcount) - { - if (write_through) - { - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); - send_response = True; - } - - free((char *)wbms); - fsp->wbmpx_ptr = NULL; - } - - if(send_response) { - END_PROFILE(SMBwriteBs); - return(outsize); - } - - END_PROFILE(SMBwriteBs); - return(-1); -} - /**************************************************************************** reply to a SMBsetattrE @@ -4675,7 +4407,6 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, outsize = set_message(outbuf,0,0,True); CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); /* Convert the DOS times into unix times. Ignore create time as UNIX can't set this. @@ -4708,7 +4439,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, /* Set the date on this file */ if(file_utime(conn, fsp->fsp_name, &unix_times)) { END_PROFILE(SMBsetattrE); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", @@ -4734,7 +4465,6 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, outsize = set_message(outbuf,11,0,True); CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); /* Do an fstat on this file */ if(vfs_fstat(fsp,fsp->fd, &sbuf)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 13db9948ad..cb4ca994f4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -218,7 +218,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, fname,open_mode, open_attr, open_ofun, open_size)); if (IS_IPC(conn)) { - return(ERROR(ERRSRV,ERRaccess)); + return(ERROR_DOS(ERRSRV,ERRaccess)); } /* XXXX we need to handle passed times, sattr and flags */ @@ -256,13 +256,13 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, inode = sbuf.st_ino; if (fmode & aDIR) { close_file(fsp,False); - return(ERROR(ERRDOS,ERRnoaccess)); + return(ERROR_DOS(ERRDOS,ERRnoaccess)); } /* Realloc the size of parameters and data we will return */ params = Realloc(*pparams, 28); if( params == NULL ) { - return(ERROR(ERRDOS,ERRnomem)); + return(ERROR_DOS(ERRDOS,ERRnomem)); } *pparams = params; @@ -669,7 +669,7 @@ static int call_trans2findfirst(connection_struct *conn, case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: break; default: - return(ERROR(ERRDOS,ERRunknownlevel)); + return(ERROR_DOS(ERRDOS,ERRunknownlevel)); } srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE); @@ -710,15 +710,15 @@ static int call_trans2findfirst(connection_struct *conn, pdata = Realloc(*ppdata, max_data_bytes + 1024); if( pdata == NULL ) { - return(ERROR(ERRDOS,ERRnomem)); + return(ERROR_DOS(ERRDOS,ERRnomem)); } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + 1024); /* Realloc the params space */ params = Realloc(*pparams, 10); - if( params == NULL ) { - return(ERROR(ERRDOS,ERRnomem)); + if (params == NULL) { + return ERROR_DOS(ERRDOS,ERRnomem); } *pparams = params; @@ -731,7 +731,7 @@ static int call_trans2findfirst(connection_struct *conn, if(!(wcard = strdup(mask))) { dptr_close(&dptr_num); - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } dptr_set_wcard(dptr_num, wcard); @@ -803,10 +803,9 @@ static int call_trans2findfirst(connection_struct *conn, * from observation of NT. */ - if(numentries == 0) - { - dptr_close(&dptr_num); - return(ERROR(ERRDOS,ERRbadfile)); + if(numentries == 0) { + dptr_close(&dptr_num); + return ERROR_DOS(ERRDOS,ERRbadfile); } /* At this point pdata points to numentries directory entries. */ @@ -900,12 +899,12 @@ resume_key = %d resume name = %s continue=%d level = %d\n", case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: break; default: - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); } pdata = Realloc( *ppdata, max_data_bytes + 1024); if(pdata == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + 1024); @@ -913,20 +912,20 @@ resume_key = %d resume name = %s continue=%d level = %d\n", /* Realloc the params space */ params = Realloc(*pparams, 6*SIZEOFWORD); if( params == NULL ) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *pparams = params; /* Check that the dptr is valid */ if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) - return(ERROR(ERRDOS,ERRnofiles)); + return ERROR_DOS(ERRDOS,ERRnofiles); string_set(&conn->dirpath,dptr_path(dptr_num)); /* Get the wildcard mask from the dptr */ if((p = dptr_wcard(dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); - return (ERROR(ERRDOS,ERRnofiles)); + return ERROR_DOS(ERRDOS,ERRnofiles); } pstrcpy(mask, p); pstrcpy(directory,conn->dirpath); @@ -1116,12 +1115,12 @@ static int call_trans2qfsinfo(connection_struct *conn, if(vfs_stat(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); - return (ERROR(ERRSRV,ERRinvdevice)); + return ERROR_DOS(ERRSRV,ERRinvdevice); } pdata = Realloc(*ppdata, max_data_bytes + 1024); if ( pdata == NULL ) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + 1024); @@ -1215,7 +1214,7 @@ static int call_trans2qfsinfo(connection_struct *conn, } /* drop through */ default: - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -1241,7 +1240,7 @@ static int call_trans2setfsinfo(connection_struct *conn, DEBUG(3,("call_trans2setfsinfo\n")); if (!CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); + return ERROR_DOS(ERRSRV,ERRaccess); outsize = set_message(outbuf,10,0,True); @@ -1308,7 +1307,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, * Original code - this is an open file. */ CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); pstrcpy(fname, fsp->fsp_name); if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { @@ -1361,21 +1359,21 @@ static int call_trans2qfilepathinfo(connection_struct *conn, params = Realloc(*pparams,2); if (params == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *pparams = params; memset((char *)params,'\0',2); data_size = max_data_bytes + 1024; pdata = Realloc(*ppdata, data_size); if ( pdata == NULL ) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *ppdata = pdata; if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return(ERROR(ERRDOS,ERReasnotsupported)); + return ERROR_DOS(ERRDOS,ERReasnotsupported); } memset((char *)pdata,'\0',data_size); @@ -1419,7 +1417,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case 6: - return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */ + return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */ case SMB_QUERY_FILE_BASIC_INFO: case 1004: @@ -1688,7 +1686,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, #endif default: - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); } send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size); @@ -1757,7 +1755,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * Original code - this is an open file. */ CHECK_FSP(fsp,conn); - CHECK_ERROR(fsp); pstrcpy(fname, fsp->fsp_name); fd = fsp->fd; @@ -1794,7 +1791,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } if (!CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); + return ERROR_DOS(ERRSRV,ERRaccess); DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", tran_call,fname,info_level,total_data)); @@ -1802,7 +1799,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, /* Realloc the parameter and data sizes */ params = Realloc(*pparams,2); if(params == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *pparams = params; @@ -1816,7 +1813,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (total_data > 4 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return(ERROR(ERRDOS,ERReasnotsupported)); + return ERROR_DOS(ERRDOS,ERReasnotsupported); } switch (info_level) @@ -1891,7 +1888,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)size )); @@ -1928,8 +1925,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } else { ret = vfs_allocate_file_space(fsp, size); } - if (ret == -1) - return allocate_space_error(inbuf, outbuf, errno); + if (ret == -1) return ERROR_NT(NT_STATUS_DISK_FULL); sbuf.st_size = size; } @@ -1944,7 +1940,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size )); break; @@ -1956,7 +1952,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, BOOL delete_on_close = (CVAL(pdata,0) ? True : False); if (tran_call != TRANSACT2_SETFILEINFO) - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); if (fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadfid)); @@ -1968,7 +1964,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) { DEBUG(10,("call_trans2setfilepathinfo: file %s delete on close flag set but delete access denied.\n", fsp->fsp_name )); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } if(fsp->is_directory) { @@ -1996,13 +1992,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); if (lock_share_entry_fsp(fsp) == False) - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close flag for file %s\n", fsp->fsp_name )); unlock_share_entry_fsp(fsp); - return(ERROR(ERRDOS,ERRnoaccess)); + return ERROR_DOS(ERRDOS,ERRnoaccess); } /* @@ -2039,7 +2035,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, default: { - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); } } @@ -2162,7 +2158,7 @@ static int call_trans2mkdir(connection_struct *conn, BOOL bad_path = False; if (!CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); + return ERROR_DOS(ERRSRV,ERRaccess); srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE); @@ -2186,7 +2182,7 @@ static int call_trans2mkdir(connection_struct *conn, /* Realloc the parameter and data sizes */ params = Realloc(*pparams,2); if(params == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *pparams = params; @@ -2218,13 +2214,13 @@ static int call_trans2findnotifyfirst(connection_struct *conn, case 2: break; default: - return(ERROR(ERRDOS,ERRunknownlevel)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); } /* Realloc the parameter and data sizes */ params = Realloc(*pparams,6); if(params == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *pparams = params; @@ -2258,7 +2254,7 @@ static int call_trans2findnotifynext(connection_struct *conn, /* Realloc the parameter and data sizes */ params = Realloc(*pparams,4); if(params == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *pparams = params; @@ -2286,12 +2282,12 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, DEBUG(10,("call_trans2getdfsreferral\n")); if(!lp_host_msdfs()) - return(ERROR(ERRDOS,ERRbadfunc)); + return ERROR_DOS(ERRDOS,ERRbadfunc); srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) - return(ERROR(ERRDOS,ERRbadfile)); + return ERROR_DOS(ERRDOS,ERRbadfile); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); @@ -2317,7 +2313,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { pdata = Realloc(*ppdata, 32); if(pdata == NULL) { - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } *ppdata = pdata; @@ -2331,7 +2327,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, return(-1); } else { DEBUG(2,("Unknown TRANS2_IOCTL\n")); - return(ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } } @@ -2434,7 +2430,7 @@ int reply_trans2(connection_struct *conn, if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) { END_PROFILE(SMBtrans2); - return(ERROR(ERRSRV,ERRaccess)); + return ERROR_DOS(ERRSRV,ERRaccess); } outsize = set_message(outbuf,0,0,True); @@ -2458,7 +2454,7 @@ int reply_trans2(connection_struct *conn, DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt)); DEBUG(2,("Transaction is %d\n",tran_call)); END_PROFILE(SMBtrans2); - return(ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } } @@ -2475,7 +2471,7 @@ int reply_trans2(connection_struct *conn, if(data) free(data); END_PROFILE(SMBtrans2); - return(ERROR(ERRDOS,ERRnomem)); + return ERROR_DOS(ERRDOS,ERRnomem); } /* Copy the param and data bytes sent with this request into @@ -2517,7 +2513,7 @@ int reply_trans2(connection_struct *conn, if(data) free(data); END_PROFILE(SMBtrans2); - return(ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } /* Revise total_params and total_data in case @@ -2641,7 +2637,7 @@ int reply_trans2(connection_struct *conn, if(data) free(data); END_PROFILE(SMBtrans2); - return (ERROR(ERRSRV,ERRerror)); + return ERROR_DOS(ERRSRV,ERRerror); } /* As we do not know how many data packets will need to be -- cgit From ee5f7237decfe446f4fdb08422beb2e6cb43af7f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 17:52:23 +0000 Subject: started converting NTSTATUS to be a structure on systems with gcc in order to make it type incompatible with BOOL so we catch errors sooner. This has already found a number of bugs (This used to be commit 1b778bc7d22efff3f90dc450eb12baa1241cf68f) --- source3/smbd/auth.c | 17 +++++++++-------- source3/smbd/blocking.c | 8 ++++---- source3/smbd/error.c | 10 +++++----- source3/smbd/nttrans.c | 14 +++++++------- source3/smbd/reply.c | 24 +++++++++++++----------- 5 files changed, 38 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 8ea867fe8c..ec493b7c06 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -56,10 +56,11 @@ static BOOL check_domain_match(char *user, char *domain) as it makes the calls itself when needed. ****************************************************************************/ -uint32 check_password(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_password(const auth_usersupplied_info *user_info, + auth_serversupplied_info *server_info) { - uint32 nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; DEBUG(3, ("check_password: Checking password for user %s with the new password interface\n", user_info->smb_username.str)); @@ -120,9 +121,9 @@ SMB hash return True if the password is correct, False otherwise ****************************************************************************/ -uint32 pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], - uchar *lm_pwd, int lm_pwd_len, - uchar *nt_pwd, int nt_pwd_len) +NTSTATUS pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], + uchar *lm_pwd, int lm_pwd_len, + uchar *nt_pwd, int nt_pwd_len) { auth_usersupplied_info user_info; @@ -196,9 +197,9 @@ uint32 pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], return check_password(&user_info, &server_info); } -uint32 pass_check_smb(char *user, char *domain, - uchar *lm_pwd, int lm_pwd_len, - uchar *nt_pwd, int nt_pwd_len) +NTSTATUS pass_check_smb(char *user, char *domain, + uchar *lm_pwd, int lm_pwd_len, + uchar *nt_pwd, int nt_pwd_len) { uchar chal[8]; diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 697e1df194..1365985660 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -276,7 +276,7 @@ static BOOL process_lockread(blocking_lock_record *blr) status = do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, READ_LOCK); - if (status != NT_STATUS_NOPROBLEMO) { + if (NT_STATUS_V(status)) { if ((errno != EACCES) && (errno != EAGAIN)) { /* * We have other than a "can't get lock" POSIX @@ -342,7 +342,7 @@ static BOOL process_lock(blocking_lock_record *blr) errno = 0; status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, (SMB_BIG_UINT)offset, WRITE_LOCK); - if (status != NT_STATUS_NOPROBLEMO) { + if (NT_STATUS_IS_ERR(status)) { if((errno != EACCES) && (errno != EAGAIN)) { /* * We have other than a "can't get lock" POSIX @@ -391,7 +391,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) uint16 lock_pid; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; - NTSTATUS status = 0; + NTSTATUS status = NT_STATUS_OK; data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); @@ -414,7 +414,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) errno = 0; status = do_lock(fsp,conn,count,lock_pid,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); - if (status != NT_STATUS_NOPROBLEMO) break; + if (NT_STATUS_IS_ERR(status)) break; } if(blr->lock_num == num_locks) { diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 27dacda377..f2613dc3a8 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -84,14 +84,14 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code,int line) } } - return error_packet(outbuf,0,eclass,ecode,line); + return error_packet(outbuf,NT_STATUS_OK,eclass,ecode,line); } /**************************************************************************** create an error packet. Normally called using the ERROR() macro ****************************************************************************/ -int error_packet(char *outbuf,uint32 ntstatus, +int error_packet(char *outbuf,NTSTATUS ntstatus, uint8 eclass,uint32 ecode,int line) { int outsize = set_message(outbuf,0,0,True); @@ -101,10 +101,10 @@ int error_packet(char *outbuf,uint32 ntstatus, DEBUG(3,("error string = %s\n",strerror(errno))); if (global_client_caps & CAP_STATUS32) { - if (ntstatus == 0 && eclass) { + if (NT_STATUS_V(ntstatus) == 0 && eclass) { ntstatus = dos_to_ntstatus(eclass, ecode); } - SIVAL(outbuf,smb_rcls,ntstatus); + SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus)); SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); DEBUG(3,("error packet at line %d cmd=%d (%s) %s\n", line, @@ -114,7 +114,7 @@ int error_packet(char *outbuf,uint32 ntstatus, return outsize; } - if (eclass == 0 && ntstatus) { + if (eclass == 0 && NT_STATUS_V(ntstatus)) { ntstatus_to_dos(ntstatus, &eclass, &ecode); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2981c6bfb2..8a70e69365 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -63,7 +63,7 @@ struct generic_mapping file_generic_mapping = { HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_error, char *params, +static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params, int paramsize, char *pdata, int datasize) { extern int max_send; @@ -83,7 +83,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, uint32 nt_err set_message(outbuf,18,0,True); - if(nt_error != 0) { + if (NT_STATUS_V(nt_error)) { ERROR_NT(nt_error); } @@ -937,7 +937,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(inbuf, outbuf, bufsize, 0, params, 69, *ppdata, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); return -1; } @@ -1353,7 +1353,7 @@ static int call_nt_transact_create(connection_struct *conn, DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(inbuf, outbuf, bufsize, 0, params, 69, *ppdata, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); return -1; } @@ -1450,7 +1450,7 @@ static int call_nt_transact_rename(connection_struct *conn, /* * Rename was successful. */ - send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); @@ -1570,7 +1570,7 @@ security descriptor.\n")); talloc_destroy(mem_ctx); - send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sd_size); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size); return -1; } @@ -1609,7 +1609,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code)) return ERROR_DOS(error_class, error_code); - send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 236bb48ce9..f1a83c27f0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -487,7 +487,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out if (!last_challenge(user_info.chal)) { DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); - return NT_STATUS_LOGON_FAILURE; + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } pdb_init_sam(&sam_trust_acct); @@ -789,9 +789,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int add_session_user(user); if (!guest) { - valid_password = (pass_check_smb(user, domain, - (unsigned char *)smb_apasswd, smb_apasslen, - (unsigned char *)smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO); + valid_password = NT_STATUS_IS_OK(pass_check_smb(user, domain, + (unsigned char *)smb_apasswd, + smb_apasslen, + (unsigned char *)smb_ntpasswd, + smb_ntpasslen)); /* The true branch will be executed if (1) the NT password failed (or was not tried), and @@ -2086,7 +2088,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK); - if (status != NT_STATUS_NOPROBLEMO) { + if (NT_STATUS_V(status)) { if (lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up @@ -2407,7 +2409,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos); - if (status != NT_STATUS_NOPROBLEMO) { + if (NT_STATUS_V(status)) { END_PROFILE(SMBwriteunlock); return ERROR_NT(status); } @@ -2885,8 +2887,8 @@ int reply_lock(connection_struct *conn, fsp->fd, fsp->fnum, (double)offset, (double)count)); status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK); - if (status != NT_STATUS_NOPROBLEMO) { - if (status != NT_STATUS_NOPROBLEMO && lp_blocking_locks(SNUM(conn))) { + if (NT_STATUS_V(status)) { + if (lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -2924,7 +2926,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset); - if (status != NT_STATUS_NOPROBLEMO) { + if (NT_STATUS_V(status)) { END_PROFILE(SMBunlock); return ERROR_NT(status); } @@ -4232,7 +4234,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); status = do_unlock(fsp,conn,lock_pid,count,offset); - if (status != NT_STATUS_NOPROBLEMO) { + if (NT_STATUS_V(status)) { END_PROFILE(SMBlockingX); return ERROR_NT(status); } @@ -4265,7 +4267,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); status = do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); - if (status != NT_STATUS_NOPROBLEMO) { + if (NT_STATUS_V(status)) { if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { /* * A blocking lock was requested. Package up -- cgit From b031af348c7dcc8c74bf49945211c466b8eca079 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 19:46:22 +0000 Subject: converted another bunch of stuff to NTSTATUS (This used to be commit 1d36250e338ae0ff9fbbf86019809205dd97d05e) --- source3/smbd/auth.c | 16 ++++++++-------- source3/smbd/auth_rhosts.c | 2 +- source3/smbd/auth_server.c | 2 +- source3/smbd/auth_smbpasswd.c | 8 ++++---- source3/smbd/auth_unix.c | 2 +- source3/smbd/auth_util.c | 2 +- source3/smbd/error.c | 4 ++-- source3/smbd/service.c | 44 +++++++++++++++++++++---------------------- 8 files changed, 40 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index ec493b7c06..d6bc8aeadc 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -68,15 +68,15 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, return NT_STATUS_LOGON_FAILURE; } - if (nt_status != NT_STATUS_NOPROBLEMO) { + if (nt_status != NT_STATUS_OK) { nt_status = check_rhosts_security(user_info, server_info); } - if ((lp_security() == SEC_DOMAIN) && (nt_status != NT_STATUS_NOPROBLEMO)) { + if ((lp_security() == SEC_DOMAIN) && (nt_status != NT_STATUS_OK)) { nt_status = check_domain_security(user_info, server_info); } - if ((lp_security() == SEC_SERVER) && (nt_status != NT_STATUS_NOPROBLEMO)) { + if ((lp_security() == SEC_SERVER) && (nt_status != NT_STATUS_OK)) { nt_status = check_server_security(user_info, server_info); } @@ -84,7 +84,7 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, smb_user_control(user_info->smb_username.str, nt_status); } - if (nt_status != NT_STATUS_NOPROBLEMO) { + if (nt_status != NT_STATUS_OK) { if ((user_info->plaintext_password.len > 0) && (!lp_plaintext_to_smbpasswd())) { nt_status = check_unix_security(user_info, server_info); @@ -94,14 +94,14 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, } } - if ((nt_status == NT_STATUS_NOPROBLEMO) && !done_pam) { + if ((nt_status == NT_STATUS_OK) && !done_pam) { /* We might not be root if we are an RPC call */ become_root(); nt_status = smb_pam_accountcheck(user_info->smb_username.str); unbecome_root(); } - if (nt_status == NT_STATUS_NOPROBLEMO) { + if (nt_status == NT_STATUS_OK) { DEBUG(5, ("check_password: Password for user %s suceeded\n", user_info->smb_username.str)); } else { DEBUG(3, ("check_password: Password for user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status))); @@ -233,11 +233,11 @@ BOOL password_ok(char *user, char *password, int pwlen) /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as required. */ - if (pass_check_smb(user, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen) == NT_STATUS_NOPROBLEMO) { + if (pass_check_smb(user, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen) == NT_STATUS_OK) { return True; } - if (pass_check_smb(user, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0) == NT_STATUS_NOPROBLEMO) { + if (pass_check_smb(user, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0) == NT_STATUS_OK) { return True; } diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index f11f9cf777..a4914f2ef1 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -175,7 +175,7 @@ uint32 check_rhosts_security(const auth_usersupplied_info *user_info, become_root(); if (check_hosts_equiv(user_info->smb_username.str)) { - nt_status = NT_STATUS_NOPROBLEMO; + nt_status = NT_STATUS_OK; } unbecome_root(); diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index ad66f0c4ac..9636094fa3 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -214,7 +214,7 @@ use this machine as the password server.\n")); /* Make this cli_nt_error() when the conversion is in */ nt_status = NT_STATUS_LOGON_FAILURE; } else { - nt_status = NT_STATUS_NOPROBLEMO; + nt_status = NT_STATUS_OK; } /* if logged in as guest then reject */ diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 1a5d02e4a4..5484758167 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -127,7 +127,7 @@ uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_ if (lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user_info->smb_username.str)); - return(NT_STATUS_NOPROBLEMO); + return(NT_STATUS_OK); } else { @@ -156,7 +156,7 @@ uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_ user_info->requested_domain.str, (char *)server_info->session_key)) { - return NT_STATUS_NOPROBLEMO; + return NT_STATUS_OK; } DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); @@ -169,7 +169,7 @@ uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_ nt_pw, user_info->chal, server_info->session_key)) { DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); - return NT_STATUS_NOPROBLEMO; + return NT_STATUS_OK; } else { DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); return NT_STATUS_WRONG_PASSWORD; @@ -185,7 +185,7 @@ uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_ lm_pw, user_info->chal, server_info->session_key)) { DEBUG(4,("smb_password_ok: LM password check succeeded\n")); - return NT_STATUS_NOPROBLEMO; + return NT_STATUS_OK; } else { DEBUG(4,("smb_password_ok: LM password check failed\n")); return NT_STATUS_WRONG_PASSWORD; diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 89e670747f..fda44fd91c 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -76,7 +76,7 @@ uint32 check_unix_security(const auth_usersupplied_info *user_info, auth_servers nt_status = (pass_check(user_info->smb_username.str, user_info->plaintext_password.str, user_info->plaintext_password.len, lp_update_encrypted() ? update_smbpassword_file : NULL) - ? NT_STATUS_NOPROBLEMO : NT_STATUS_LOGON_FAILURE); + ? NT_STATUS_OK : NT_STATUS_LOGON_FAILURE); unbecome_root(); return nt_status; diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 4a0f45f843..5ccf963889 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -105,7 +105,7 @@ void smb_user_control(char *unix_user, uint32 nt_status) { struct passwd *pwd=NULL; - if(nt_status == NT_STATUS_NOPROBLEMO) { + if(nt_status == NT_STATUS_OK) { /* * User validated ok against Domain controller. * If the admin wants us to try and create a UNIX diff --git a/source3/smbd/error.c b/source3/smbd/error.c index f2613dc3a8..a74b62de01 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -84,7 +84,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code,int line) } } - return error_packet(outbuf,NT_STATUS_OK,eclass,ecode,line); + return error_packet(outbuf,NT_STATUS(0),eclass,ecode,line); } @@ -119,7 +119,7 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, } SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); - SVAL(outbuf,smb_rcls) = eclass; + SSVAL(outbuf,smb_rcls,eclass); SSVAL(outbuf,smb_err,ecode); DEBUG(3,("error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", diff --git a/source3/smbd/service.c b/source3/smbd/service.c index edac97194e..df0f6f2095 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -217,14 +217,13 @@ int find_service(char *service) do some basic sainity checks on the share. This function modifies dev, ecode. ****************************************************************************/ -static BOOL share_sanity_checks(int snum, char* service, char *dev, int *ecode) +static NTSTATUS share_sanity_checks(int snum, char* service, char *dev) { if (!lp_snum_ok(snum) || !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum))) { - *ecode = ERRaccess; - return False; + return NT_STATUS_ACCESS_DENIED; } /* you can only connect to the IPC$ service as an ipc device */ @@ -243,15 +242,15 @@ static BOOL share_sanity_checks(int snum, char* service, char *dev, int *ecode) strupper(dev); if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { DEBUG(1,("Attempt to connect to non-printer as a printer\n")); - *ecode = ERRinvdevice; - return False; + return NT_STATUS_BAD_DEVICE_TYPE; } /* Behave as a printer if we are supposed to */ if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { pstrcpy(dev, "LPT1:"); } - return True; + + return NT_STATUS_OK; } @@ -319,7 +318,8 @@ static void set_admin_user(connection_struct *conn) /**************************************************************************** make a connection to a service ****************************************************************************/ -connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode) +connection_struct *make_connection(char *service,char *user,char *password, + int pwlen, char *dev,uint16 vuid, NTSTATUS *status) { int snum; struct passwd *pass = NULL; @@ -334,13 +334,13 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (snum < 0) { if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { DEBUG(3,("refusing IPC connection\n")); - *ecode = ERRnoipc; + *status = NT_STATUS_ACCESS_DENIED; return NULL; } DEBUG(0,("%s (%s) couldn't find service %s\n", remote_machine, client_addr(), service)); - *ecode = ERRnosuchshare; + *status = NT_STATUS_BAD_NETWORK_PATH; return NULL; } @@ -349,7 +349,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int fstring dos_username; fstrcpy(dos_username, user); return(make_connection(dos_username,user,password, - pwlen,dev,vuid,ecode)); + pwlen,dev,vuid,status)); } if(lp_security() != SEC_SHARE) { @@ -357,7 +357,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int fstring dos_username; fstrcpy(user,validated_username(vuid)); fstrcpy(dos_username, user); - return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); + return(make_connection(dos_username,user,password,pwlen,dev,vuid,status)); } } else { /* Security = share. Try with current_user_info.smb_name @@ -366,12 +366,12 @@ connection_struct *make_connection(char *service,char *user,char *password, int fstring dos_username; fstrcpy(user,current_user_info.smb_name); fstrcpy(dos_username, user); - return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); + return(make_connection(dos_username,user,password,pwlen,dev,vuid,status)); } } } - if (!share_sanity_checks(snum, service, dev, ecode)) { + if (NT_STATUS_IS_ERR(share_sanity_checks(snum, service, dev))) { return NULL; } @@ -387,14 +387,14 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* shall we let them in? */ if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) ); - *ecode = ERRbadpw; + *status = NT_STATUS_WRONG_PASSWORD; return NULL; } conn = conn_new(); if (!conn) { DEBUG(0,("Couldn't find free connection.\n")); - *ecode = ERRnoresource; + *status = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } @@ -403,7 +403,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (pass == NULL) { DEBUG(0,( "Couldn't find account %s\n",user)); - *ecode = ERRbaduid; + *status = NT_STATUS_NO_SUCH_USER; conn_free(conn); return NULL; } @@ -543,7 +543,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!can_write) { if (!share_access_check(conn, snum, vuid, FILE_READ_DATA)) { /* No access, read or write. */ - *ecode = ERRaccess; + *status = NT_STATUS_ACCESS_DENIED; DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", service )); conn_free(conn); @@ -567,7 +567,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int lp_max_connections(SNUM(conn)), False)) { DEBUG(1,("too many connections - rejected\n")); - *ecode = ERRnoresource; + *status = NT_STATUS_INSUFFICIENT_RESOURCES; conn_free(conn); return NULL; } @@ -585,7 +585,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); - *ecode = ERRsrverror; + *status = NT_STATUS_UNSUCCESSFUL; return NULL; } } @@ -596,7 +596,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); - *ecode = ERRbadpw; + *status = NT_STATUS_WRONG_PASSWORD; return NULL; } @@ -609,7 +609,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); - *ecode = ERRnosuchshare; + *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -638,7 +638,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int DEBUG(1,("preexec gave %d - failing connection\n", ret)); yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); - *ecode = ERRsrverror; + *status = NT_STATUS_UNSUCCESSFUL; return NULL; } } -- cgit From cb9b39dd8289d3bec54ea9033994c59086fb7eec Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 28 Aug 2001 06:34:53 +0000 Subject: Added dummy handlers for SAM_SYNC and SAM_REPL messages. (This used to be commit 08e05f1b3c2d5767e8f8f0343fc0ea90c786eac0) --- source3/smbd/server.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5bcb47393a..36c98300f0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -80,6 +80,31 @@ static void killkids(void) if(am_parent) kill(0,SIGTERM); } +/**************************************************************************** + process a sam sync message - not sure whether to do this here or + somewhere else +****************************************************************************/ +static void msg_sam_sync(int msg_type, pid_t pid, void *buf, size_t len) +{ + DEBUG(10, ("** sam sync message received, ignoring\n")); +} + +/**************************************************************************** + process a sam sync replicate message - not sure whether to do this here or + somewhere else +****************************************************************************/ +static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len) +{ + uint32 low_serial; + + if (len != sizeof(uint32)) + return; + + low_serial = *((uint32 *)buf); + + DEBUG(3, ("received sam replication message, serial = 0x%04x\n", + low_serial)); +} /**************************************************************************** open the socket communication @@ -196,6 +221,11 @@ max can be %d\n", FD_SET(s,&listen_set); } + /* Listen to messages */ + + message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); + message_register(MSG_SMB_SAM_REPL, msg_sam_repl); + /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); -- cgit From b03a2011bb5a038cf9f3fd20351516420c6fc88a Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Tue, 28 Aug 2001 16:05:55 +0000 Subject: Ouch ! I didn't think I would have to do that: add 2 new rap calls ! It's a quick and ugly hack as a proof of concept: the dell powervault 705 works with a samba PDC. I'll do a correct user enumeration later. J.F. (This used to be commit 9ec6a8735682c7dfe9f8573f063da7625d425d8a) --- source3/smbd/lanman.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 6408bbff9e..f971bf1e35 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1660,6 +1660,131 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c } +/**************************************************************************** + view list of groups available + ****************************************************************************/ +static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + char *p2; + int count=0; + int total=0,counted=0; + BOOL missed = False; + int i; + int data_len, fixed_len, string_len; + int f_len = 0, s_len = 0; + + if (!prefix_ok(str1,"WrLeh")) return False; + + /* check it's a supported variant */ + switch( uLevel ) + { + case 0: + p2 = "B21"; + break; + default: + return False; + } + + if (strcmp(p2,str2) != 0) return False; + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + + /* XXXX we need a real SAM database some day */ + pstrcpy(p,"Users"); p += 21; count++; + pstrcpy(p,"Domain Users"); p += 21; count++; + pstrcpy(p,"Guests"); p += 21; count++; + pstrcpy(p,"Domain Guests"); p += 21; count++; + + *rdata_len = PTR_DIFF(p,*rdata); + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + + SSVAL(*rparam,4,count); /* is this right?? */ + SSVAL(*rparam,6,count); /* is this right?? */ + + DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count)); + + return(True); +} + +/**************************************************************************** + view list of groups available + ****************************************************************************/ +static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + char *p2; + int count=0; + int total=0,counted=0; + BOOL missed = False; + int i; + int data_len, fixed_len, string_len; + int f_len = 0, s_len = 0; + + if (!prefix_ok(str1,"WrLeh")) return False; + + /* check it's a supported variant */ + switch( uLevel ) + { + case 0: + p2 = "B21"; + break; + default: + return False; + } + + if (strcmp(p2,str2) != 0) return False; + + *rdata_len = mdrcnt + 1024; + *rdata = REALLOC(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + + /* XXXX we need a real SAM database some day */ + pstrcpy(p,"Users"); p += 21; count++; + pstrcpy(p,"Domain Users"); p += 21; count++; + pstrcpy(p,"Guests"); p += 21; count++; + pstrcpy(p,"Domain Guests"); p += 21; count++; + + *rdata_len = PTR_DIFF(p,*rdata); + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + + SSVAL(*rparam,4,count); /* is this right?? */ + SSVAL(*rparam,6,count); /* is this right?? */ + + DEBUG(3,("api_RNetUserEnum gave %d entries\n", count)); + + return(True); +} + + /**************************************************************************** get the time of day info @@ -3262,7 +3387,9 @@ struct {"RNetShareEnum", 0, api_RNetShareEnum,0}, {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, + {"RNetGroupEnum", 47, api_RNetGroupEnum,0}, {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0}, + {"RNetUserEnum", 53, api_RNetUserEnum,0}, {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, -- cgit From 3bd7e65cac84b6d0a22936addbd6e30617c84567 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 30 Aug 2001 08:14:16 +0000 Subject: this was a stupid typo, thanks to Jochen Dolze (dolze@epcnet.de) for pointing out. (This used to be commit a554d5a99a03e6e8df7e946e5636f5ee80b21969) --- source3/smbd/blocking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 1365985660..2008598104 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -412,7 +412,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - status = do_lock(fsp,conn,count,lock_pid,offset, + status = do_lock(fsp,conn,lock_pid,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); if (NT_STATUS_IS_ERR(status)) break; } -- cgit From e555b969b2201bdb48ad9a0fc79f1e13ea25ec24 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 30 Aug 2001 18:56:35 +0000 Subject: if no ACL elements then use chmod - fixes ability to set read-only bit on files that do not have an ACL (This used to be commit 65ea13420c78cf0a8c01f14c08815e4b44ca4abc) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b87605ee07..39d0b83bf6 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2213,11 +2213,11 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) } /* - * If this is a simple 3 element ACL then it's a standard + * If this is a simple 3 element ACL or no elements then it's a standard * UNIX permission set. Just use chmod... */ - if (num_entries == 3) + if ((num_entries == 3) || (num_entries == 0)) return -1; return 0; -- cgit From 4bd774f458e0628986c8b135686238acf2ff32c9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Aug 2001 22:20:02 +0000 Subject: Fix crash bug with indirecting through null pointer on recursive delete. Jeremy. (This used to be commit a6f04d16613a06c1aafa89d7373d1e4b4a5fb45b) --- source3/smbd/reply.c | 253 ++++++++++++++++++++++++--------------------------- 1 file changed, 119 insertions(+), 134 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f1a83c27f0..deee0f88f8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3209,86 +3209,80 @@ int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring d } /**************************************************************************** - reply to a mkdir + Reply to a mkdir. ****************************************************************************/ + int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring directory; - int outsize; - START_PROFILE(SMBmkdir); + pstring directory; + int outsize; + START_PROFILE(SMBmkdir); - srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); + srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); - outsize=mkdir_internal(conn, inbuf, outbuf, directory); - if(outsize == 0) - outsize = set_message(outbuf,0,0,True); + outsize=mkdir_internal(conn, inbuf, outbuf, directory); + if(outsize == 0) + outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); + DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); - END_PROFILE(SMBmkdir); - return(outsize); + END_PROFILE(SMBmkdir); + return(outsize); } /**************************************************************************** -Static function used by reply_rmdir to delete an entire directory -tree recursively. + Static function used by reply_rmdir to delete an entire directory + tree recursively. Return False on ok, True on fail. ****************************************************************************/ static BOOL recursive_rmdir(connection_struct *conn, char *directory) { - char *dname = NULL; - BOOL ret = False; - void *dirptr = OpenDir(NULL, directory, False); + char *dname = NULL; + BOOL ret = False; + void *dirptr = OpenDir(conn, directory, False); - if(dirptr == NULL) - return True; + if(dirptr == NULL) + return True; - while((dname = ReadDirName(dirptr))) - { - pstring fullname; - SMB_STRUCT_STAT st; + while((dname = ReadDirName(dirptr))) { + pstring fullname; + SMB_STRUCT_STAT st; - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) - { - errno = ENOMEM; - ret = True; - break; - } - pstrcpy(fullname, directory); - pstrcat(fullname, "/"); - pstrcat(fullname, dname); + /* Construct the full name. */ + if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { + errno = ENOMEM; + ret = True; + break; + } - if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) - { - ret = True; - break; - } + pstrcpy(fullname, directory); + pstrcat(fullname, "/"); + pstrcat(fullname, dname); - if(st.st_mode & S_IFDIR) - { - if(recursive_rmdir(conn, fullname)!=0) - { - ret = True; - break; - } - if(vfs_rmdir(conn,fullname) != 0) - { - ret = True; - break; - } - } - else if(vfs_unlink(conn,fullname) != 0) - { - ret = True; - break; - } - } - CloseDir(dirptr); - return ret; + if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) { + ret = True; + break; + } + + if(st.st_mode & S_IFDIR) { + if(recursive_rmdir(conn, fullname)!=0) { + ret = True; + break; + } + if(vfs_rmdir(conn,fullname) != 0) { + ret = True; + break; + } + } else if(vfs_unlink(conn,fullname) != 0) { + ret = True; + break; + } + } + CloseDir(dirptr); + return ret; } /**************************************************************************** @@ -3297,86 +3291,77 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) BOOL rmdir_internals(connection_struct *conn, char *directory) { - BOOL ok; + BOOL ok; + + ok = (vfs_rmdir(conn,directory) == 0); + if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { + /* + * Check to see if the only thing in this directory are + * vetoed files/directories. If so then delete them and + * retry. If we fail to delete any of them (and we *don't* + * do a recursive delete) then fail the rmdir. + */ + BOOL all_veto_files = True; + char *dname; + void *dirptr = OpenDir(conn, directory, False); - ok = (vfs_rmdir(conn,directory) == 0); - if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) - { - /* - * Check to see if the only thing in this directory are - * vetoed files/directories. If so then delete them and - * retry. If we fail to delete any of them (and we *don't* - * do a recursive delete) then fail the rmdir. - */ - BOOL all_veto_files = True; - char *dname; - void *dirptr = OpenDir(conn, directory, False); + if(dirptr != NULL) { + int dirpos = TellDir(dirptr); + while ((dname = ReadDirName(dirptr))) { + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + if(!IS_VETO_PATH(conn, dname)) { + all_veto_files = False; + break; + } + } - if(dirptr != NULL) - { - int dirpos = TellDir(dirptr); - while ((dname = ReadDirName(dirptr))) - { - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - if(!IS_VETO_PATH(conn, dname)) - { - all_veto_files = False; - break; - } - } - if(all_veto_files) - { - SeekDir(dirptr,dirpos); - while ((dname = ReadDirName(dirptr))) - { - pstring fullname; - SMB_STRUCT_STAT st; + if(all_veto_files) { + SeekDir(dirptr,dirpos); + while ((dname = ReadDirName(dirptr))) { + pstring fullname; + SMB_STRUCT_STAT st; - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) - { - errno = ENOMEM; - break; - } - pstrcpy(fullname, directory); - pstrcat(fullname, "/"); - pstrcat(fullname, dname); + /* Construct the full name. */ + if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { + errno = ENOMEM; + break; + } + + pstrcpy(fullname, directory); + pstrcat(fullname, "/"); + pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) - break; - if(st.st_mode & S_IFDIR) - { - if(lp_recursive_veto_delete(SNUM(conn))) - { - if(recursive_rmdir(conn, fullname) != 0) - break; - } - if(vfs_rmdir(conn,fullname) != 0) - break; - } - else if(vfs_unlink(conn,fullname) != 0) - break; - } - CloseDir(dirptr); - /* Retry the rmdir */ - ok = (vfs_rmdir(conn,directory) == 0); - } - else - CloseDir(dirptr); - } - else - errno = ENOTEMPTY; - } - - if (!ok) - DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", - directory,strerror(errno))); + if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) + break; + if(st.st_mode & S_IFDIR) { + if(lp_recursive_veto_delete(SNUM(conn))) { + if(recursive_rmdir(conn, fullname) != 0) + break; + } + if(vfs_rmdir(conn,fullname) != 0) + break; + } else if(vfs_unlink(conn,fullname) != 0) + break; + } + CloseDir(dirptr); + /* Retry the rmdir */ + ok = (vfs_rmdir(conn,directory) == 0); + } else { + CloseDir(dirptr); + } + } else { + errno = ENOTEMPTY; + } + } + + if (!ok) + DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno))); - return ok; + return ok; } /**************************************************************************** -- cgit From bd7ba65ddab3df4c69ce13957fb202b993365897 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Sep 2001 23:06:57 +0000 Subject: more NTSTATUS changes (This used to be commit 8a49b2f7df46b2c990a980758fe1f3871e8b578e) --- source3/smbd/reply.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index deee0f88f8..8b392e9e0a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -155,19 +155,6 @@ int reply_special(char *inbuf,char *outbuf) } -/******************************************************************* -work out what error to give to a failed connection -********************************************************************/ - -static int connection_error(char *inbuf,char *outbuf,int ecode) -{ - if (ecode == ERRnoipc || ecode == ERRnosuchshare) - return(ERROR_DOS(ERRDOS,ecode)); - - return(ERROR_DOS(ERRSRV,ecode)); -} - - /**************************************************************************** Reply to a tcon. ****************************************************************************/ @@ -182,7 +169,7 @@ int reply_tcon(connection_struct *conn, int outsize = 0; uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; - int ecode = -1; + NTSTATUS ecode; char *p; START_PROFILE(SMBtcon); @@ -231,7 +218,7 @@ int reply_tcon(connection_struct *conn, if (!conn) { END_PROFILE(SMBtcon); - return(connection_error(inbuf,outbuf,ecode)); + return ERROR_NT(ecode); } outsize = set_message(outbuf,2,0,True); @@ -256,7 +243,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt pstring user; pstring password; pstring devicename; - int ecode = -1; + NTSTATUS ecode; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); pstring path; @@ -337,7 +324,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (!conn) { END_PROFILE(SMBtconX); - return(connection_error(inbuf,outbuf,ecode)); + return ERROR_NT(ecode); } if (Protocol < PROTOCOL_NT1) { -- cgit From 2771d77c6025dd7a1b5fbf2c0f863e334655b323 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 Sep 2001 08:54:24 +0000 Subject: tidied up some unused vars in JFs new fns (This used to be commit e26502b1f840cd0fafd700c9756b610b38709ce2) --- source3/smbd/lanman.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f971bf1e35..21d18fc88c 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1672,14 +1672,8 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); char *p2; int count=0; - int total=0,counted=0; - BOOL missed = False; - int i; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; if (!prefix_ok(str1,"WrLeh")) return False; @@ -1734,14 +1728,8 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); char *p2; int count=0; - int total=0,counted=0; - BOOL missed = False; - int i; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; if (!prefix_ok(str1,"WrLeh")) return False; -- cgit From 19fea3242cf6234786b6cbb60631e0071f31ff9f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Sep 2001 07:13:01 +0000 Subject: the next stage in the NTSTATUS/WERROR change. smbd and nmbd now compile, but the client code still needs some work (This used to be commit dcd6e735f709a9231860ceb9682db40ff26c9a66) --- source3/smbd/auth.c | 16 ++-- source3/smbd/auth_domain.c | 6 +- source3/smbd/auth_rhosts.c | 4 +- source3/smbd/auth_server.c | 7 +- source3/smbd/auth_smbpasswd.c | 8 +- source3/smbd/auth_unix.c | 4 +- source3/smbd/auth_util.c | 6 +- source3/smbd/error.c | 2 +- source3/smbd/lanman.c | 19 +++-- source3/smbd/notify.c | 2 +- source3/smbd/nttrans.c | 42 +++++----- source3/smbd/reply.c | 185 +++++++++++++++++++----------------------- 12 files changed, 143 insertions(+), 158 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index d6bc8aeadc..b707c38c62 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -68,15 +68,15 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, return NT_STATUS_LOGON_FAILURE; } - if (nt_status != NT_STATUS_OK) { + if (!NT_STATUS_IS_OK(nt_status)) { nt_status = check_rhosts_security(user_info, server_info); } - if ((lp_security() == SEC_DOMAIN) && (nt_status != NT_STATUS_OK)) { + if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_domain_security(user_info, server_info); } - if ((lp_security() == SEC_SERVER) && (nt_status != NT_STATUS_OK)) { + if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_server_security(user_info, server_info); } @@ -84,7 +84,7 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, smb_user_control(user_info->smb_username.str, nt_status); } - if (nt_status != NT_STATUS_OK) { + if (!NT_STATUS_IS_OK(nt_status)) { if ((user_info->plaintext_password.len > 0) && (!lp_plaintext_to_smbpasswd())) { nt_status = check_unix_security(user_info, server_info); @@ -94,14 +94,14 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, } } - if ((nt_status == NT_STATUS_OK) && !done_pam) { + if (NT_STATUS_IS_OK(nt_status) && !done_pam) { /* We might not be root if we are an RPC call */ become_root(); nt_status = smb_pam_accountcheck(user_info->smb_username.str); unbecome_root(); } - if (nt_status == NT_STATUS_OK) { + if (NT_STATUS_IS_OK(nt_status)) { DEBUG(5, ("check_password: Password for user %s suceeded\n", user_info->smb_username.str)); } else { DEBUG(3, ("check_password: Password for user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status))); @@ -233,11 +233,11 @@ BOOL password_ok(char *user, char *password, int pwlen) /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as required. */ - if (pass_check_smb(user, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen) == NT_STATUS_OK) { + if (NT_STATUS_IS_OK(pass_check_smb(user, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { return True; } - if (pass_check_smb(user, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0) == NT_STATUS_OK) { + if (NT_STATUS_IS_OK(pass_check_smb(user, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { return True; } diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index d9d7b6fd40..111f0f143c 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -30,10 +30,10 @@ BOOL global_machine_password_needs_changing = False; Check for a valid username and password in security=domain mode. ****************************************************************************/ -uint32 check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) +NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, + auth_serversupplied_info *server_info) { - uint32 nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; char *p, *pserver; unsigned char trust_passwd[16]; time_t last_change_time; diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index a4914f2ef1..ffb9212264 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -168,10 +168,10 @@ BOOL check_hosts_equiv(char *user) Check for a valid .rhosts/hosts.equiv entry for this user ****************************************************************************/ -uint32 check_rhosts_security(const auth_usersupplied_info *user_info, +NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { - uint32 nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; become_root(); if (check_hosts_equiv(user_info->smb_username.str)) { diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index 9636094fa3..b279152f74 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -113,14 +113,14 @@ struct cli_state *server_cryptkey(void) Validate a password with the password server. ****************************************************************************/ -static uint32 server_validate(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +static NTSTATUS server_validate(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { struct cli_state *cli; static unsigned char badpass[24]; static fstring baduser; static BOOL tested_password_server = False; static BOOL bad_password_server = False; - uint32 nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; cli = server_client(); @@ -232,14 +232,13 @@ use this machine as the password server.\n")); Check for a valid username and password in security=server mode. ****************************************************************************/ -uint32 check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { if(lp_security() != SEC_SERVER) return NT_STATUS_LOGON_FAILURE; return server_validate(user_info, server_info); - } diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 5484758167..33b0623643 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -109,7 +109,7 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -uint32 smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { uint8 *nt_pw, *lm_pw; uint16 acct_ctrl; @@ -202,11 +202,11 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -uint32 check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { SAM_ACCOUNT *sampass=NULL; BOOL ret; - uint32 nt_status; + NTSTATUS nt_status; pdb_init_sam(&sampass); @@ -220,7 +220,7 @@ uint32 check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_se { DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->smb_username.str)); pdb_free_sam(sampass); - return(NT_STATUS_NO_SUCH_USER); + return NT_STATUS_NO_SUCH_USER; } nt_status = smb_password_ok(sampass, user_info, server_info); diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index fda44fd91c..1708320961 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -68,9 +68,9 @@ check if a username/password is OK assuming the password in PLAIN TEXT ****************************************************************************/ -uint32 check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { - uint32 nt_status; + NTSTATUS nt_status; become_root(); nt_status = (pass_check(user_info->smb_username.str, user_info->plaintext_password.str, diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 5ccf963889..28f58eb8ae 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -101,11 +101,11 @@ static int smb_delete_user(char *unix_user) Add and Delete UNIX users on demand, based on NT_STATUS codes. ****************************************************************************/ -void smb_user_control(char *unix_user, uint32 nt_status) +void smb_user_control(char *unix_user, NTSTATUS nt_status) { struct passwd *pwd=NULL; - if(nt_status == NT_STATUS_OK) { + if (NT_STATUS_IS_OK(nt_status)) { /* * User validated ok against Domain controller. * If the admin wants us to try and create a UNIX @@ -127,7 +127,7 @@ void smb_user_control(char *unix_user, uint32 nt_status) smb_create_user(unix_user, pwd->pw_dir); } - } else if (nt_status == NT_STATUS_NO_SUCH_USER) { + } else if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_NO_SUCH_USER)) { /* * User failed to validate ok against Domain controller. * If the failure was "user doesn't exist" and admin diff --git a/source3/smbd/error.c b/source3/smbd/error.c index a74b62de01..6b5a4b27b1 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -84,7 +84,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code,int line) } } - return error_packet(outbuf,NT_STATUS(0),eclass,ecode,line); + return error_packet(outbuf,NT_STATUS_OK,eclass,ecode,line); } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 21d18fc88c..eb0e7154a2 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2016,6 +2016,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param char *p = skip_string(str2,1); int jobid, errcode; extern struct current_user current_user; + WERROR werr = WERR_OK; jobid = SVAL(p,0); @@ -2036,18 +2037,21 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param switch (function) { case 81: /* delete */ - if (print_job_delete(¤t_user, jobid, &errcode)) + if (print_job_delete(¤t_user, jobid, &werr)) errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(¤t_user, jobid, &errcode)) + if (print_job_pause(¤t_user, jobid, &werr)) errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(¤t_user, jobid, &errcode)) + if (print_job_resume(¤t_user, jobid, &werr)) errcode = NERR_Success; break; } + + if (!W_ERROR_IS_OK(werr)) + errcode = W_ERROR_V(werr); out: SSVAL(*rparam,0,errcode); @@ -2070,6 +2074,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param char *QueueName = skip_string(str2,1); int errcode = NERR_notsupported; int snum; + WERROR werr = WERR_OK; extern struct current_user current_user; /* check it's a supported varient */ @@ -2089,16 +2094,18 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param switch (function) { case 74: /* Pause queue */ - if (print_queue_pause(¤t_user, snum, &errcode)) errcode = NERR_Success; + if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success; break; case 75: /* Resume queue */ - if (print_queue_resume(¤t_user, snum, &errcode)) errcode = NERR_Success; + if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success; break; case 103: /* Purge */ - if (print_queue_purge(¤t_user, snum, &errcode)) errcode = NERR_Success; + if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success; break; } + if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr); + out: SSVAL(*rparam,0,errcode); SSVAL(*rparam,2,0); /* converter word */ diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index a2a979b776..5aa0b4ad3f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -47,7 +47,7 @@ static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(char *inbuf, uint32 error_code) +static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8a70e69365..aee5aa7798 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1435,37 +1435,35 @@ static int call_nt_transact_rename(connection_struct *conn, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - char *params = *ppparams; - pstring new_name; - files_struct *fsp = file_fsp(params, 0); - BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; - int outsize = 0; - - CHECK_FSP(fsp, conn); - srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE); - - outsize = rename_internals(conn, inbuf, outbuf, fsp->fsp_name, - new_name, replace_if_exists); - if(outsize == 0) { - /* - * Rename was successful. - */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + char *params = *ppparams; + pstring new_name; + files_struct *fsp = file_fsp(params, 0); + BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; + NTSTATUS status; - DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", - fsp->fsp_name, new_name)); + CHECK_FSP(fsp, conn); + srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE); - outsize = -1; + status = rename_internals(conn, fsp->fsp_name, + new_name, replace_if_exists); + if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + /* + * Rename was successful. + */ + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + + DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", + fsp->fsp_name, new_name)); + /* * Win2k needs a changenotify request response before it will * update after a rename.. */ - + process_pending_change_notify_queue((time_t)0); - } - return(outsize); + return -1; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8b392e9e0a..73cfd5ac85 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -499,7 +499,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); } - if (!smb_password_ok(sam_trust_acct, &user_info, &server_info)) { + if (!NT_STATUS_IS_OK(smb_password_ok(sam_trust_acct, &user_info, &server_info))) { DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); pdb_free_sam(sam_trust_acct); return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); @@ -1751,14 +1751,13 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) code. ****************************************************************************/ -int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, - int dirtype, char *name) +NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) { pstring directory; pstring mask; char *p; int count=0; - int error = ERRnoaccess; + NTSTATUS error = NT_STATUS_OK; BOOL has_wild; BOOL exists=False; BOOL bad_path = False; @@ -1797,7 +1796,7 @@ int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, pstrcat(directory,"/"); pstrcat(directory,mask); if (!can_delete(directory,conn,dirtype)) { - return ERROR_NT(NT_STATUS_SHARING_VIOLATION); + return NT_STATUS_SHARING_VIOLATION; } if (vfs_unlink(conn,directory) == 0) { count++; @@ -1817,7 +1816,7 @@ int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, */ if (dirptr) { - error = ERRbadfile; + error = NT_STATUS_OBJECT_NAME_NOT_FOUND; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); @@ -1828,7 +1827,7 @@ int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, if(!mask_match(fname, mask, case_sensitive)) continue; - error = ERRnoaccess; + error = NT_STATUS_ACCESS_DENIED; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); if (!can_delete(fname,conn,dirtype)) continue; if (vfs_unlink(conn,fname) == 0) count++; @@ -1838,19 +1837,11 @@ int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf, } } - if (count == 0) { - if (exists) - return ERROR_DOS(ERRDOS,error); - else { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,error)); - } + if (count == 0 && NT_STATUS_IS_OK(error)) { + error = map_nt_error_from_unix(errno); } - - return 0; + + return error; } /**************************************************************************** @@ -1863,6 +1854,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int outsize = 0; pstring name; int dirtype; + NTSTATUS status; START_PROFILE(SMBunlink); dirtype = SVAL(inbuf,smb_vwv0); @@ -1873,16 +1865,16 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name); - if(outsize == 0) { - /* - * Win2k needs a changenotify request response before it will - * update after a rename.. - */ - process_pending_change_notify_queue((time_t)0); - - outsize = set_message(outbuf,0,0,True); - } + status = unlink_internals(conn, dirtype, name); + if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + + /* + * Win2k needs a changenotify request response before it will + * update after a rename.. + */ + process_pending_change_notify_queue((time_t)0); + + outsize = set_message(outbuf,0,0,True); END_PROFILE(SMBunlink); return outsize; @@ -3171,28 +3163,22 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ The guts of the mkdir command, split out so it may be called by the NT SMB code. ****************************************************************************/ -int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory) +NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) { - BOOL bad_path = False; - SMB_STRUCT_STAT sbuf; - int ret= -1; - - unix_convert(directory,conn,0,&bad_path,&sbuf); - - if (check_name(directory, conn)) - ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); - - if (ret < 0) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - return ret; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + int ret= -1; + + unix_convert(directory,conn,0,&bad_path,&sbuf); + + if (check_name(directory, conn)) + ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); + + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + + return NT_STATUS_OK; } /**************************************************************************** @@ -3203,13 +3189,15 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring directory; int outsize; + NTSTATUS status; START_PROFILE(SMBmkdir); srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); - outsize=mkdir_internal(conn, inbuf, outbuf, directory); - if(outsize == 0) - outsize = set_message(outbuf,0,0,True); + status = mkdir_internal(conn, directory); + if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + + outsize = set_message(outbuf,0,0,True); DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); @@ -3478,9 +3466,9 @@ static BOOL can_rename(char *fname,connection_struct *conn) The guts of the rename command, split out so it may be called by the NT SMB code. ****************************************************************************/ -int rename_internals(connection_struct *conn, - char *inbuf, char *outbuf, char *name, - char *newname, BOOL replace_if_exists) +NTSTATUS rename_internals(connection_struct *conn, + char *name, + char *newname, BOOL replace_if_exists) { pstring directory; pstring mask; @@ -3490,7 +3478,7 @@ int rename_internals(connection_struct *conn, BOOL bad_path1 = False; BOOL bad_path2 = False; int count=0; - int error = ERRnoaccess; + NTSTATUS error = NT_STATUS_OK; BOOL exists=False; BOOL rc = True; SMB_STRUCT_STAT sbuf1, sbuf2; @@ -3600,13 +3588,13 @@ int rename_internals(connection_struct *conn, if(resolve_wildcards(directory,newname) && can_rename(directory,conn) && - !conn->vfs_ops.rename(conn,directory,newname)) + conn->vfs_ops.rename(conn,directory,newname) == 0) count++; } else { if (resolve_wildcards(directory,newname) && can_rename(directory,conn) && !vfs_file_exist(conn,newname,NULL) && - !conn->vfs_ops.rename(conn,directory,newname)) + conn->vfs_ops.rename(conn,directory,newname) == 0) count++; } @@ -3616,7 +3604,7 @@ int rename_internals(connection_struct *conn, if (!count) exists = vfs_file_exist(conn,directory,NULL); if (!count && exists && vfs_file_exist(conn,newname,NULL)) { exists = True; - error = ERRrename; + error = NT_STATUS_OBJECT_NAME_COLLISION; } } else { /* @@ -3630,7 +3618,7 @@ int rename_internals(connection_struct *conn, dirptr = OpenDir(conn, directory, True); if (dirptr) { - error = ERRbadfile; + error = NT_STATUS_OBJECT_NAME_NOT_FOUND; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); @@ -3643,7 +3631,7 @@ int rename_internals(connection_struct *conn, if(!mask_match(fname, mask, case_sensitive)) continue; - error = ERRnoaccess; + error = NT_STATUS_ACCESS_DENIED; slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); if (!can_rename(fname,conn)) { DEBUG(6,("rename %s refused\n", fname)); @@ -3660,7 +3648,7 @@ int rename_internals(connection_struct *conn, if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) { DEBUG(6,("file_exist %s\n", destname)); - error = 183; + error = NT_STATUS_OBJECT_NAME_COLLISION; continue; } @@ -3672,59 +3660,52 @@ int rename_internals(connection_struct *conn, } } - if (count == 0) { - if (exists) - return ERROR_DOS(ERRDOS,error); - else { - if((errno == ENOENT) && (bad_path1 || bad_path2)) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,error)); - } + if (count == 0 && NT_STATUS_IS_OK(error)) { + error = map_nt_error_from_unix(errno); } - return 0; + return error; } /**************************************************************************** Reply to a mv. ****************************************************************************/ -int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, + int dum_buffsize) { - int outsize = 0; - pstring name; - pstring newname; - char *p; - - START_PROFILE(SMBmv); - - p = smb_buf(inbuf) + 1; - p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE); - p++; - p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE); - - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + int outsize = 0; + pstring name; + pstring newname; + char *p; + NTSTATUS status; - DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); + START_PROFILE(SMBmv); - outsize = rename_internals(conn, inbuf, outbuf, name, newname, False); - if(outsize == 0) { + p = smb_buf(inbuf) + 1; + p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE); + p++; + p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE); + + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + + DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); + + status = rename_internals(conn, name, newname, False); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } /* - * Win2k needs a changenotify request response before it will - * update after a rename.. - */ - - process_pending_change_notify_queue((time_t)0); - - outsize = set_message(outbuf,0,0,True); - } + * Win2k needs a changenotify request response before it will + * update after a rename.. + */ + process_pending_change_notify_queue((time_t)0); + outsize = set_message(outbuf,0,0,True); - END_PROFILE(SMBmv); - return(outsize); + END_PROFILE(SMBmv); + return(outsize); } /******************************************************************* -- cgit From 7e75921e24dc1cca934bc5e4350137292a2f2112 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Sep 2001 19:10:30 +0000 Subject: Merge of transfer file code from 2.2, fix for readbraw. Jeremy. (This used to be commit c05e79453655abb67fd47a2d3dba88b4c5377e35) --- source3/smbd/close.c | 2 +- source3/smbd/reply.c | 534 ++++++++++++++++++++++++------------------------ source3/smbd/vfs-wrap.c | 4 +- source3/smbd/vfs.c | 96 ++------- 4 files changed, 286 insertions(+), 350 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 1a98a8bca5..f790778676 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -78,7 +78,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn) return; } - transfer_file(tmp_fd,outfd,st.st_size, NULL,0,0); + transfer_file(tmp_fd,outfd,st.st_size); close(tmp_fd); close(outfd); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 73cfd5ac85..2af1f62356 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1880,157 +1880,147 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return outsize; } +/**************************************************************************** + Fail for readbraw. +****************************************************************************/ + +void fail_readraw(void) +{ + pstring errstr; + slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)\n", + strerror(errno) ); + exit_server(errstr); +} /**************************************************************************** - reply to a readbraw (core+ protocol) + Reply to a readbraw (core+ protocol). ****************************************************************************/ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { - size_t maxcount,mincount; - size_t nread = 0; - SMB_OFF_T startpos; - char *header = outbuf; - ssize_t ret=0; - files_struct *fsp; - START_PROFILE(SMBreadbraw); + size_t maxcount,mincount; + size_t nread = 0; + SMB_OFF_T startpos; + char *header = outbuf; + ssize_t ret=0; + files_struct *fsp; + START_PROFILE(SMBreadbraw); - /* - * Special check if an oplock break has been issued - * and the readraw request croses on the wire, we must - * return a zero length response here. - */ + /* + * Special check if an oplock break has been issued + * and the readraw request croses on the wire, we must + * return a zero length response here. + */ - if(global_oplock_break) - { - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - DEBUG(5,("readbraw - oplock break finished\n")); - END_PROFILE(SMBreadbraw); - return -1; - } + if(global_oplock_break) { + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + DEBUG(5,("readbraw - oplock break finished\n")); + END_PROFILE(SMBreadbraw); + return -1; + } - fsp = file_fsp(inbuf,smb_vwv0); - - if (!FNUM_OK(fsp,conn) || !fsp->can_read) { - /* - * fsp could be NULL here so use the value from the packet. JRA. - */ - DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0))); - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - END_PROFILE(SMBreadbraw); - return(-1); - } + fsp = file_fsp(inbuf,smb_vwv0); - CHECK_FSP(fsp,conn); + if (!FNUM_OK(fsp,conn) || !fsp->can_read) { + /* + * fsp could be NULL here so use the value from the packet. JRA. + */ + DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0))); + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + END_PROFILE(SMBreadbraw); + return(-1); + } - flush_write_cache(fsp, READRAW_FLUSH); + CHECK_FSP(fsp,conn); - startpos = IVAL(inbuf,smb_vwv1); - if(CVAL(inbuf,smb_wct) == 10) { - /* - * This is a large offset (64 bit) read. - */ + flush_write_cache(fsp, READRAW_FLUSH); + + startpos = IVAL(inbuf,smb_vwv1); + if(CVAL(inbuf,smb_wct) == 10) { + /* + * This is a large offset (64 bit) read. + */ #ifdef LARGE_SMB_OFF_T - startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32); + startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32); #else /* !LARGE_SMB_OFF_T */ - /* - * Ensure we haven't been sent a >32 bit offset. - */ + /* + * Ensure we haven't been sent a >32 bit offset. + */ - if(IVAL(inbuf,smb_vwv8) != 0) { - DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ + if(IVAL(inbuf,smb_vwv8) != 0) { + DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) )); - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - END_PROFILE(SMBreadbraw); - return(-1); - } + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + END_PROFILE(SMBreadbraw); + return(-1); + } #endif /* LARGE_SMB_OFF_T */ - if(startpos < 0) { - DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", - (double)startpos )); - _smb_setlen(header,0); - transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0); - END_PROFILE(SMBreadbraw); - return(-1); - } - } - maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); - mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); + if(startpos < 0) { + DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos )); + _smb_setlen(header,0); + if (write_data(smbd_server_fd(),header,4) != 4) + fail_readraw(); + END_PROFILE(SMBreadbraw); + return(-1); + } + } + maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); + mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); - /* ensure we don't overrun the packet size */ - maxcount = MIN(65535,maxcount); - maxcount = MAX(mincount,maxcount); + /* ensure we don't overrun the packet size */ + maxcount = MIN(65535,maxcount); + maxcount = MAX(mincount,maxcount); - if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) - { - SMB_OFF_T size = fsp->size; - SMB_OFF_T sizeneeded = startpos + maxcount; - - if (size < sizeneeded) - { - SMB_STRUCT_STAT st; - if (vfs_fstat(fsp,fsp->fd,&st) == 0) - size = st.st_size; - if (!fsp->can_write) - fsp->size = size; - } + if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + SMB_OFF_T size = fsp->size; + SMB_OFF_T sizeneeded = startpos + maxcount; + + if (size < sizeneeded) { + SMB_STRUCT_STAT st; + if (vfs_fstat(fsp,fsp->fd,&st) == 0) + size = st.st_size; + if (!fsp->can_write) + fsp->size = size; + } - nread = MIN(maxcount,(size - startpos)); - } + if (startpos >= size) + nread = 0; + else + nread = MIN(maxcount,(size - startpos)); + } - if (nread < mincount) - nread = 0; + if (nread < mincount) + nread = 0; - DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", - fsp->fnum, (double)startpos, - (int)maxcount, (int)mincount, (int)nread ) ); + DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, + (int)maxcount, (int)mincount, (int)nread ) ); -#if UNSAFE_READRAW - { - BOOL seek_fail = False; - int predict=0; - _smb_setlen(header,nread); - - if ((nread-predict) > 0) { - if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) { - DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n")); - ret = 0; - seek_fail = True; - } - } - - if(!seek_fail) - ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL, - (SMB_OFF_T)(nread-predict),header,4+predict, - startpos+predict); - } - - if (ret != nread+4) - DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n", - fsp->fsp_name,startpos,nread,ret)); - -#else /* UNSAFE_READRAW */ - ret = read_file(fsp,header+4,startpos,nread); - if (ret < mincount) ret = 0; + if (nread > 0) { + ret = read_file(fsp,header+4,startpos,nread); + if (ret < mincount) + ret = 0; + } - _smb_setlen(header,ret); - transfer_file(0,smbd_server_fd(),0,header,4+ret,0); -#endif /* UNSAFE_READRAW */ + _smb_setlen(header,ret); + if (write_data(smbd_server_fd(),header,4+ret) != 4+ret) + fail_readraw(); - DEBUG(5,("readbraw finished\n")); - END_PROFILE(SMBreadbraw); - return -1; + DEBUG(5,("readbraw finished\n")); + END_PROFILE(SMBreadbraw); + return -1; } - /**************************************************************************** reply to a lockread (core+ protocol) ****************************************************************************/ @@ -2231,114 +2221,126 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - ssize_t nwritten=0; - ssize_t total_written=0; - size_t numtowrite=0; - size_t tcount; - SMB_OFF_T startpos; - char *data=NULL; - BOOL write_through; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - int outsize = 0; - START_PROFILE(SMBwritebraw); + ssize_t nwritten=0; + ssize_t total_written=0; + size_t numtowrite=0; + size_t tcount; + SMB_OFF_T startpos; + char *data=NULL; + BOOL write_through; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int outsize = 0; + START_PROFILE(SMBwritebraw); - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); - tcount = IVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); - write_through = BITSETW(inbuf+smb_vwv7,0); - - /* We have to deal with slightly different formats depending - on whether we are using the core+ or lanman1.0 protocol */ - if(Protocol <= PROTOCOL_COREPLUS) { - numtowrite = SVAL(smb_buf(inbuf),-2); - data = smb_buf(inbuf); - } else { - numtowrite = SVAL(inbuf,smb_vwv10); - data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11); - } + tcount = IVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv3); + write_through = BITSETW(inbuf+smb_vwv7,0); - /* force the error type */ - CVAL(inbuf,smb_com) = SMBwritec; - CVAL(outbuf,smb_com) = SMBwritec; + /* We have to deal with slightly different formats depending + on whether we are using the core+ or lanman1.0 protocol */ - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { - END_PROFILE(SMBwritebraw); - return ERROR_DOS(ERRDOS,ERRlock); - } + if(Protocol <= PROTOCOL_COREPLUS) { + numtowrite = SVAL(smb_buf(inbuf),-2); + data = smb_buf(inbuf); + } else { + numtowrite = SVAL(inbuf,smb_vwv10); + data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11); + } - if (numtowrite>0) - nwritten = write_file(fsp,data,startpos,numtowrite); + /* force the error type */ + CVAL(inbuf,smb_com) = SMBwritec; + CVAL(outbuf,smb_com) = SMBwritec; + + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + END_PROFILE(SMBwritebraw); + return(ERROR_DOS(ERRDOS,ERRlock)); + } + + if (numtowrite>0) + nwritten = write_file(fsp,data,startpos,numtowrite); - DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", - fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); + DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", + fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); - if (nwritten < numtowrite) { - END_PROFILE(SMBwritebraw); - return(UNIXERROR(ERRHRD,ERRdiskfull)); - } + if (nwritten < numtowrite) { + END_PROFILE(SMBwritebraw); + return(UNIXERROR(ERRHRD,ERRdiskfull)); + } - total_written = nwritten; + total_written = nwritten; - /* Return a message to the redirector to tell it - to send more bytes */ - CVAL(outbuf,smb_com) = SMBwritebraw; - SSVALS(outbuf,smb_vwv0,-1); - outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_writebraw: send_smb failed.\n"); + /* Return a message to the redirector to tell it to send more bytes */ + CVAL(outbuf,smb_com) = SMBwritebraw; + SSVALS(outbuf,smb_vwv0,-1); + outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_writebraw: send_smb failed.\n"); - /* Now read the raw data into the buffer and write it */ - if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { - exit_server("secondary writebraw failed"); - } + /* Now read the raw data into the buffer and write it */ + if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { + exit_server("secondary writebraw failed"); + } - /* Even though this is not an smb message, smb_len - returns the generic length of an smb message */ - numtowrite = smb_len(inbuf); + /* Even though this is not an smb message, smb_len returns the generic length of an smb message */ + numtowrite = smb_len(inbuf); - if (tcount > nwritten+numtowrite) { - DEBUG(3,("Client overestimated the write %d %d %d\n", - (int)tcount,(int)nwritten,(int)numtowrite)); - } + /* Set up outbuf to return the correct return */ + outsize = set_message(outbuf,1,0,True); + CVAL(outbuf,smb_com) = SMBwritec; + SSVAL(outbuf,smb_vwv0,total_written); - nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp, - (SMB_OFF_T)numtowrite,NULL,0, - startpos+nwritten); - total_written += nwritten; - - /* Set up outbuf to return the correct return */ - outsize = set_message(outbuf,1,0,True); - CVAL(outbuf,smb_com) = SMBwritec; - SSVAL(outbuf,smb_vwv0,total_written); + if (numtowrite != 0) { - if (nwritten < (ssize_t)numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; - SSVAL(outbuf,smb_err,ERRdiskfull); - } + if (numtowrite > BUFFER_SIZE) { + DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n", + (unsigned int)numtowrite )); + exit_server("secondary writebraw failed"); + } - if ((lp_syncalways(SNUM(conn)) || write_through) && - lp_strict_sync(SNUM(conn))) - sync_file(conn,fsp); + if (tcount > nwritten+numtowrite) { + DEBUG(3,("Client overestimated the write %d %d %d\n", + (int)tcount,(int)nwritten,(int)numtowrite)); + } - DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", - fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); + if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) { + DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n", + strerror(errno) )); + exit_server("secondary writebraw failed"); + } - /* we won't return a status if write through is not selected - this - follows what WfWg does */ - END_PROFILE(SMBwritebraw); - if (!write_through && total_written==tcount) { - /* - * Fix for "rabbit pellet" mode, trigger an early TCP ack by - * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA. - */ - if (!send_keepalive(smbd_server_fd())) - exit_server("reply_writebraw: send of keepalive failed"); - return(-1); - } + nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite); - return(outsize); + if (nwritten < (ssize_t)numtowrite) { + CVAL(outbuf,smb_rcls) = ERRHRD; + SSVAL(outbuf,smb_err,ERRdiskfull); + } + + if (nwritten > 0) + total_written += nwritten; + } + + if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn))) + sync_file(conn,fsp); + + DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", + fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); + + /* we won't return a status if write through is not selected - this follows what WfWg does */ + END_PROFILE(SMBwritebraw); + if (!write_through && total_written==tcount) { + /* + * Fix for "rabbit pellet" mode, trigger an early TCP ack by + * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA. + */ + if (!send_keepalive(smbd_server_fd())) + exit_server("reply_writebraw: send of keepalive failed"); + return(-1); + } + + return(outsize); } /**************************************************************************** @@ -3709,82 +3711,80 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /******************************************************************* - copy a file as part of a reply_copy - ******************************************************************/ + Copy a file as part of a reply_copy. +******************************************************************/ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory, int *err_ret) { - int Access,action; - SMB_STRUCT_STAT src_sbuf, sbuf2; - SMB_OFF_T ret=-1; - files_struct *fsp1,*fsp2; - pstring dest; + int Access,action; + SMB_STRUCT_STAT src_sbuf, sbuf2; + SMB_OFF_T ret=-1; + files_struct *fsp1,*fsp2; + pstring dest; - *err_ret = 0; + *err_ret = 0; - pstrcpy(dest,dest1); - if (target_is_directory) { - char *p = strrchr_m(src,'/'); - if (p) - p++; - else - p = src; - pstrcat(dest,"/"); - pstrcat(dest,p); - } + pstrcpy(dest,dest1); + if (target_is_directory) { + char *p = strrchr_m(src,'/'); + if (p) + p++; + else + p = src; + pstrcat(dest,"/"); + pstrcat(dest,p); + } - if (!vfs_file_exist(conn,src,&src_sbuf)) - return(False); + if (!vfs_file_exist(conn,src,&src_sbuf)) + return(False); - fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); + fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); - if (!fsp1) { - return(False); - } + if (!fsp1) + return(False); - if (!target_is_directory && count) - ofun = FILE_EXISTS_OPEN; + if (!target_is_directory && count) + ofun = FILE_EXISTS_OPEN; - vfs_stat(conn,dest,&sbuf2); - fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,src_sbuf.st_mode,0,&Access,&action); + if (vfs_stat(conn,dest,&sbuf2) == -1) + ZERO_STRUCTP(&sbuf2); - if (!fsp2) { - close_file(fsp1,False); - return(False); - } + fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + ofun,src_sbuf.st_mode,0,&Access,&action); - if ((ofun&3) == 1) { - if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) { - DEBUG(0,("copy_file: error - sys_lseek returned error %s\n", - strerror(errno) )); - /* - * Stop the copy from occurring. - */ - ret = -1; - src_sbuf.st_size = 0; - } - } + if (!fsp2) { + close_file(fsp1,False); + return(False); + } + + if ((ofun&3) == 1) { + if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) { + DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); + /* + * Stop the copy from occurring. + */ + ret = -1; + src_sbuf.st_size = 0; + } + } - if (src_sbuf.st_size) - ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0); + if (src_sbuf.st_size) + ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); - close_file(fsp1,False); - /* - * As we are opening fsp1 read-only we only expect - * an error on close on fsp2 if we are out of space. - * Thus we don't look at the error return from the - * close of fsp1. - */ - *err_ret = close_file(fsp2,False); + close_file(fsp1,False); + /* + * As we are opening fsp1 read-only we only expect + * an error on close on fsp2 if we are out of space. + * Thus we don't look at the error return from the + * close of fsp1. + */ + *err_ret = close_file(fsp2,False); - return(ret == (SMB_OFF_T)src_sbuf.st_size); + return(ret == (SMB_OFF_T)src_sbuf.st_size); } - - /**************************************************************************** reply to a file copy. ****************************************************************************/ diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 2b465dbe15..11ba30f909 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -190,7 +190,7 @@ int vfswrap_close(files_struct *fsp, int fd) return result; } -ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n) +ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) { ssize_t result; @@ -207,7 +207,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, char *data, size_t n) return result; } -ssize_t vfswrap_write(files_struct *fsp, int fd, const char *data, size_t n) +ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) { ssize_t result; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f5870a3119..fce13bf13d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -395,92 +395,28 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) } /**************************************************************************** - Transfer some data between two file_struct's. + Transfer some data (n bytes) between two file_struct's. ****************************************************************************/ -SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, - int out_fd, files_struct *out_fsp, - SMB_OFF_T n, char *header, int headlen, int align) -{ - static char *buf=NULL; - static int size=0; - char *buf1,*abuf; - SMB_OFF_T total = 0; - - DEBUG(4,("vfs_transfer_file n=%.0f (head=%d) called\n",(double)n,headlen)); - - /* Check we have at least somewhere to read from */ - - SMB_ASSERT((in_fd != -1) || (in_fsp != NULL)); - - if (size == 0) { - size = lp_readsize(); - size = MAX(size,1024); - } - - while (!buf && size>0) { - buf = (char *)Realloc(buf,size+8); - if (!buf) size /= 2; - } - - if (!buf) { - DEBUG(0,("Can't allocate transfer buffer!\n")); - exit(1); - } - - abuf = buf + (align%8); - - if (header) - n += headlen; - - while (n > 0) - { - int s = (int)MIN(n,(SMB_OFF_T)size); - int ret,ret2=0; - - ret = 0; - - if (header && (headlen >= MIN(s,1024))) { - buf1 = header; - s = headlen; - ret = headlen; - headlen = 0; - header = NULL; - } else { - buf1 = abuf; - } +static files_struct *in_fsp; +static files_struct *out_fsp; - if (header && headlen > 0) - { - ret = MIN(headlen,size); - memcpy(buf1,header,ret); - headlen -= ret; - header += ret; - if (headlen <= 0) header = NULL; - } - - if (s > ret) { - ret += in_fsp ? - in_fsp->conn->vfs_ops.read(in_fsp,in_fsp->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret); - } +static ssize_t read_fn(int fd, void *buf, size_t len) +{ + return in_fsp->conn->vfs_ops.read(in_fsp, fd, buf, len); +} - if (ret > 0) { - if (out_fsp) - ret2 = out_fsp->conn->vfs_ops.write(out_fsp,out_fsp->fd,buf1,ret); - else - ret2= (out_fd != -1) ? write_data(out_fd,buf1,ret) : ret; - } +static ssize_t write_fn(int fd, const void *buf, size_t len) +{ + return out_fsp->conn->vfs_ops.write(out_fsp, fd, buf, len); +} - if (ret2 > 0) total += ret2; - /* if we can't write then dump excess data */ - if (ret2 != ret) - vfs_transfer_file(in_fd, in_fsp, -1,NULL,n-(ret+headlen),NULL,0,0); +SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) +{ + in_fsp = in; + out_fsp = out; - if (ret <= 0 || ret2 != ret) - return(total); - n -= ret; - } - return(total); + return transfer_file_internal(in_fsp->fd, out_fsp->fd, n, read_fn, write_fn); } /******************************************************************* -- cgit From 15472c4ee7a8cf78c352ce56b48868762d68f95a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Sep 2001 19:58:01 +0000 Subject: Fixes to ensure invalid vuids cannot stop oplock breaks. This may have bearing on the Solaris fcntl spin bug. Jeremy. (This used to be commit 0f676202529cbfead629d2c228b7d5abc2dff7d6) --- source3/smbd/oplock.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index f841432960..26d193e2c2 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -630,7 +630,8 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B time_t start_time; BOOL shutdown_server = False; BOOL oplock_timeout = False; - connection_struct *saved_conn; + connection_struct *saved_user_conn; + connection_struct *saved_fsp_conn; int saved_vuid; pstring saved_dir; int timeout = (OPLOCK_BREAK_TIMEOUT * 1000); @@ -734,9 +735,10 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B * Save the information we need to re-become the * user, then unbecome the user whilst we're doing this. */ - saved_conn = fsp->conn; + saved_user_conn = current_user.conn; saved_vuid = current_user.vuid; - vfs_GetWd(saved_conn,saved_dir); + saved_fsp_conn = fsp->conn; + vfs_GetWd(saved_fsp_conn,saved_dir); unbecome_user(); /* Save the chain fnum. */ file_chain_save(); @@ -810,7 +812,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B * Go back to being the user who requested the oplock * break. */ - if(!become_user(saved_conn, saved_vuid)) + if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !become_user(saved_user_conn, saved_vuid)) { DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); DEBUGADD( 0, ( "Shutting down server\n" ) ); @@ -818,7 +820,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B exit_server("unable to re-become user"); } /* Including the directory. */ - vfs_ChDir(saved_conn,saved_dir); + vfs_ChDir(saved_fsp_conn,saved_dir); /* Restore the chain fnum. */ file_chain_restore(); -- cgit From 851a06e1fd6ac0d921f96fe9e9529129b4b4c01d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Sep 2001 10:18:58 +0000 Subject: added filename to error_packet() (This used to be commit 2c424788dec2fd6e44c243ea115d66689dfae6c0) --- source3/smbd/error.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 6b5a4b27b1..17606c62be 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -62,7 +62,8 @@ struct /**************************************************************************** create an error packet from errno ****************************************************************************/ -int unix_error_packet(char *outbuf,int def_class,uint32 def_code,int line) +int unix_error_packet(char *outbuf,int def_class,uint32 def_code, + int line, const char *file) { int eclass=def_class; int ecode=def_code; @@ -84,7 +85,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code,int line) } } - return error_packet(outbuf,NT_STATUS_OK,eclass,ecode,line); + return error_packet(outbuf,NT_STATUS_OK,eclass,ecode,line,file); } @@ -92,7 +93,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code,int line) create an error packet. Normally called using the ERROR() macro ****************************************************************************/ int error_packet(char *outbuf,NTSTATUS ntstatus, - uint8 eclass,uint32 ecode,int line) + uint8 eclass,uint32 ecode,int line, const char *file) { int outsize = set_message(outbuf,0,0,True); extern uint32 global_client_caps; @@ -106,8 +107,8 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, } SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus)); SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); - DEBUG(3,("error packet at line %d cmd=%d (%s) %s\n", - line, + DEBUG(3,("error packet at %s(%d) cmd=%d (%s) %s\n", + file, line, (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), get_nt_error_msg(ntstatus))); @@ -122,8 +123,8 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, SSVAL(outbuf,smb_rcls,eclass); SSVAL(outbuf,smb_err,ecode); - DEBUG(3,("error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - line, + DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n", + file, line, (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), eclass, -- cgit From 75287280717bc1f1411d2084d3295fffb1ccb391 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 5 Sep 2001 18:43:55 +0000 Subject: merge profile data changes from 2.2 (This used to be commit c105859304e93297fa29f346e9cbd1af0c95048b) --- source3/smbd/vfs-wrap.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 11ba30f909..eff72c1f10 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -591,30 +591,60 @@ int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_ size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) { - return get_nt_acl(fsp, ppdesc); + size_t result; + + START_PROFILE(fget_nt_acl); + result = get_nt_acl(fsp, ppdesc); + END_PROFILE(fget_nt_acl); + return result; } size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc) { - return get_nt_acl(fsp, ppdesc); + size_t result; + + START_PROFILE(get_nt_acl); + result = get_nt_acl(fsp, ppdesc); + END_PROFILE(get_nt_acl); + return result; } BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) { - return set_nt_acl(fsp, security_info_sent, psd); + BOOL result; + + START_PROFILE(fset_nt_acl); + result = set_nt_acl(fsp, security_info_sent, psd); + END_PROFILE(fset_nt_acl); + return result; } BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) { - return set_nt_acl(fsp, security_info_sent, psd); + BOOL result; + + START_PROFILE(set_nt_acl); + result = set_nt_acl(fsp, security_info_sent, psd); + END_PROFILE(set_nt_acl); + return result; } int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode) { - return chmod_acl(name, mode); + int result; + + START_PROFILE(chmod_acl); + result = chmod_acl(name, mode); + END_PROFILE(chmod_acl); + return result; } int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode) { - return fchmod_acl(fd, mode); + int result; + + START_PROFILE(fchmod_acl); + result = fchmod_acl(fd, mode); + END_PROFILE(fchmod_acl); + return result; } -- cgit From 387f1fd09ca8101f161c729394340f50e882a955 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Sep 2001 21:11:52 +0000 Subject: fixed formatting to make the code vaguely readable. It's still a dogs breakfast, but at least you can follow the indents (This used to be commit 9955ea0aaa299c6c946b4e7b7e98017c39b60bc8) --- source3/smbd/open.c | 285 ++++++++++++++++++++++++++-------------------------- 1 file changed, 143 insertions(+), 142 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6a1eac7602..145d12e3f3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -444,151 +444,151 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request, BOOL *p_all_current_opens_are_level_II) { - int i; - int num_share_modes; - int oplock_contention_count = 0; - share_mode_entry *old_shares = 0; - BOOL fcbopen = False; - BOOL broke_oplock; - - if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) - fcbopen = True; - - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - - if(num_share_modes == 0) - return 0; - - /* - * Check if the share modes will give us access. - */ - - do { - share_mode_entry broken_entry; - - broke_oplock = False; - *p_all_current_opens_are_level_II = True; - - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * By observation of NetBench, oplocks are broken *before* share - * modes are checked. This allows a file to be closed by the client - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. - */ - - if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || - (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { - - BOOL opb_ret; + int i; + int num_share_modes; + int oplock_contention_count = 0; + share_mode_entry *old_shares = 0; + BOOL fcbopen = False; + BOOL broke_oplock; + + if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) + fcbopen = True; + + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + + if(num_share_modes == 0) + return 0; + + /* + * Check if the share modes will give us access. + */ + + do { + share_mode_entry broken_entry; + + broke_oplock = False; + *p_all_current_opens_are_level_II = True; + + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + + /* + * By observation of NetBench, oplocks are broken *before* share + * modes are checked. This allows a file to be closed by the client + * if the share mode would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so we must break + * it before continuing. + */ + + if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || + (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { + + BOOL opb_ret; - DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ + DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode)); - - /* Oplock break - unlock to request it. */ - unlock_share_entry(conn, dev, inode); - - opb_ret = request_oplock_break(share_entry, dev, inode); - - /* Now relock. */ - lock_share_entry(conn, dev, inode); - - if(opb_ret == False) { - free((char *)old_shares); - DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ + + /* Oplock break - unlock to request it. */ + unlock_share_entry(conn, dev, inode); + + opb_ret = request_oplock_break(share_entry, dev, inode); + + /* Now relock. */ + lock_share_entry(conn, dev, inode); + + if(opb_ret == False) { + free((char *)old_shares); + DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return -1; - } - - broke_oplock = True; - broken_entry = *share_entry; - break; - - } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - *p_all_current_opens_are_level_II = False; - } - - /* someone else has a share lock on it, check to see - if we can too */ - - if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { - free((char *)old_shares); - errno = EACCES; - return -1; - } - - } /* end for */ - - if(broke_oplock) { - free((char *)old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - oplock_contention_count++; - - /* Paranoia check that this is no longer an exlusive entry. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - if (share_modes_identical(&broken_entry, share_entry) && - EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) { - - /* - * This should not happen. The target left this oplock - * as exlusive.... The process *must* be dead.... - */ - - DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, \ + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } + + broke_oplock = True; + broken_entry = *share_entry; + break; + + } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + *p_all_current_opens_are_level_II = False; + } + + /* someone else has a share lock on it, check to see + if we can too */ + + if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { + free((char *)old_shares); + errno = EACCES; + return -1; + } + + } /* end for */ + + if(broke_oplock) { + free((char *)old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + oplock_contention_count++; + + /* Paranoia check that this is no longer an exlusive entry. */ + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + + if (share_modes_identical(&broken_entry, share_entry) && + EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) { + + /* + * This should not happen. The target left this oplock + * as exlusive.... The process *must* be dead.... + */ + + DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, \ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); - - if (process_exists(broken_entry.pid)) { - pstring errmsg; - slprintf(errmsg, sizeof(errmsg)-1, - "open_mode_check: Existant process %d left active oplock.\n", - broken_entry.pid ); - smb_panic(errmsg); - } - - if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return -1; - } - - /* - * We must reload the share modes after deleting the - * other process's entry. - */ - - free((char *)old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - break; - } - } /* end for paranoia... */ - } /* end if broke_oplock */ - - } while(broke_oplock); - - if(old_shares != 0) - free((char *)old_shares); - - /* - * Refuse to grant an oplock in case the contention limit is - * reached when going through the lock list multiple times. - */ - - if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) { - *p_oplock_request = 0; - DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n", - oplock_contention_count )); - } - - return num_share_modes; + + if (process_exists(broken_entry.pid)) { + pstring errmsg; + slprintf(errmsg, sizeof(errmsg)-1, + "open_mode_check: Existant process %d left active oplock.\n", + broken_entry.pid ); + smb_panic(errmsg); + } + + if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } + + /* + * We must reload the share modes after deleting the + * other process's entry. + */ + + free((char *)old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + break; + } + } /* end for paranoia... */ + } /* end if broke_oplock */ + + } while(broke_oplock); + + if(old_shares != 0) + free((char *)old_shares); + + /* + * Refuse to grant an oplock in case the contention limit is + * reached when going through the lock list multiple times. + */ + + if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) { + *p_oplock_request = 0; + DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n", + oplock_contention_count )); + } + + return num_share_modes; } /**************************************************************************** @@ -613,7 +613,8 @@ static void kernel_flock(files_struct *fsp, int deny_mode) that ****************************************************************************/ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, - int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) + int share_mode,int ofun, mode_t mode,int oplock_request, + int *Access,int *action) { int flags=0; int flags2=0; -- cgit From 627b1d0a61ad8825311c860a1e76aecd29fe8f67 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Sep 2001 21:13:58 +0000 Subject: when you update the share mode in the db you must also update fsp->share_mode otherwise the check to see if the fsp share mode matches the one in the db will fail when you come to delete it, thus leaving us with a share mode on a file that isn't even open! (This used to be commit 2020738b889d8d508cf787e5c5d380af817b92f9) --- source3/smbd/trans2.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cb4ca994f4..b21cdfdab0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2001,6 +2001,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return ERROR_DOS(ERRDOS,ERRnoaccess); } + /* we have to also set the delete flag in our fsp */ + if (delete_on_close) { + fsp->share_mode |= DELETE_ON_CLOSE_FLAG; + } else { + fsp->share_mode &= ~DELETE_ON_CLOSE_FLAG; + } + /* * Release the lock. */ -- cgit From 11f0402a74640c6f32ae18c58b60d9d57932deab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Sep 2001 22:45:48 +0000 Subject: Fix I think for the fcntl spinning problem. Re-prioritize so that oplock break messages get priority over incoming client messages. Jeremy. (This used to be commit 1779f6a223dad87c3b8451d09b9808b46495a8b6) --- source3/smbd/oplock.c | 14 ++++++++++++++ source3/smbd/process.c | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 26d193e2c2..7033eddc16 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -48,6 +48,20 @@ int32 get_number_of_exclusive_open_oplocks(void) return exclusive_oplocks_open; } +/**************************************************************************** + Return True if an oplock message is pending. +****************************************************************************/ + +BOOL oplock_message_waiting(fd_set *fds) +{ + if (koplocks && koplocks->msg_waiting(fds)) + return True; + + if (FD_ISSET(oplock_sock, fds)) + return True; + + return False; +} /**************************************************************************** Read an oplock break message from either the oplock UDP fd or the diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ce1e855e29..9f23c7d3be 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -223,7 +223,13 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) return False; } - if (!FD_ISSET(smbd_server_fd(),&fds) || selrtn > 1) { + /* + * Ensure we process oplock break messages by preference. + * This is IMPORTANT ! Otherwise we can starve other processes + * sending us an oplock break message. JRA. + */ + + if (oplock_message_waiting(&fds)) { async_processing(&fds, buffer, buffer_len); if (!FD_ISSET(smbd_server_fd(),&fds)) goto again; } -- cgit From 851e60c3825c6d3398973b20374feb1806a22238 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Sep 2001 23:34:41 +0000 Subject: Removed unneeded set of delete on close in fsp->share_mode. Jeremy. (This used to be commit 7816f79075132350c910f75f9b757477a319bbae) --- source3/smbd/trans2.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b21cdfdab0..cb4ca994f4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2001,13 +2001,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return ERROR_DOS(ERRDOS,ERRnoaccess); } - /* we have to also set the delete flag in our fsp */ - if (delete_on_close) { - fsp->share_mode |= DELETE_ON_CLOSE_FLAG; - } else { - fsp->share_mode &= ~DELETE_ON_CLOSE_FLAG; - } - /* * Release the lock. */ -- cgit From 9a9ac2739bbdc993ecdfa78298bdd9c059328378 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Sep 2001 22:08:19 +0000 Subject: got rid of USE_TDB_MMAP_FLAG as its not needed any more (This used to be commit c26e0d3f27a05ecc8bd2390f9aab7f9451524e47) --- source3/smbd/connection.c | 2 +- source3/smbd/session.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index df58697917..399851302c 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -119,7 +119,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO BOOL ret = True; if (!tdb) { - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, + tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, O_RDWR | O_CREAT, 0644); } if (!tdb) diff --git a/source3/smbd/session.c b/source3/smbd/session.c index eaff78c685..6a27cd7326 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -52,7 +52,7 @@ BOOL session_claim(uint16 vuid) } if (!tdb) { - tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, + tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, O_RDWR | O_CREAT, 0644); if (!tdb) { DEBUG(1,("session_claim: failed to open sessionid tdb\n")); -- cgit From 83ebf2b6b282926930dc2c5dee3b5f18447d6e81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Sep 2001 22:43:21 +0000 Subject: Fix the 62bit locking onto 32 bit NFS mounts problem generically for HPUX. Don. please check this out. Jeremy. (This used to be commit ce9f95996498f7795aaef069e1443ea1c7d524b3) --- source3/smbd/reply.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2af1f62356..26bd0b4714 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4041,6 +4041,38 @@ SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format return count; } +/**************************************************************************** + Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). +****************************************************************************/ + +static uint32 map_lock_offset(uint32 high, uint32 low) +{ + unsigned int i; + uint32 mask = 0; + uint32 highcopy = high; + + /* + * Try and find out how many significant bits there are in high. + */ + + for(i = 0; highcopy; i++) + highcopy >>= 1; + + /* + * We use 31 bits not 32 here as POSIX + * lock offsets may not be negative. + */ + + mask = (~0) << (31 - i); + + if(low & mask) + return 0; /* Fail. */ + + high <<= (31 - i); + + return (high|low); +} + /**************************************************************************** Get a lock offset, dealing with large offset requests. ****************************************************************************/ -- cgit From 0135666934c5a8db796539b5414b72e1c2c8348d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2001 20:01:19 +0000 Subject: #ifdef out function when not used. Jeremy. (This used to be commit fa8d626a2773569a454451e77ea56c707b33b69e) --- source3/smbd/reply.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 26bd0b4714..0d1d5eed7c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4041,6 +4041,7 @@ SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format return count; } +#if !defined(HAVE_LONGLONG) /**************************************************************************** Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). ****************************************************************************/ @@ -4072,6 +4073,7 @@ static uint32 map_lock_offset(uint32 high, uint32 low) return (high|low); } +#endif /* !defined(HAVE_LONGLONG) */ /**************************************************************************** Get a lock offset, dealing with large offset requests. -- cgit From 84cca757397dba107fde479bc2043d8412713cf7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2001 20:08:16 +0000 Subject: Don't fail if no owner/group owner set. Use existing owners. Jeremy. (This used to be commit 9961c4c1a3b2dbf8d1062bc1fa103488c0d0ba79) --- source3/smbd/posix_acls.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 39d0b83bf6..48fac44bbf 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -419,7 +419,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if(security_info_sent == 0) { DEBUG(0,("unpack_nt_owners: no security info sent !\n")); - return False; + return True; } /* @@ -438,8 +438,10 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); - if (!sid_to_uid( &owner_sid, puser, &sid_type)) + if (!sid_to_uid( &owner_sid, puser, &sid_type)) { DEBUG(3,("unpack_nt_owners: unable to validate owner sid.\n")); + return False; + } } /* @@ -449,8 +451,10 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); - if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) + if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) { DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n")); + return False; + } } DEBUG(5,("unpack_nt_owners: owner_sids validated.\n")); -- cgit From 65c5a1c0ba2cc3dc8e45a499c42191016e658b20 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 8 Sep 2001 02:59:23 +0000 Subject: convert more code to using d_printf (This used to be commit 60d297303488ed583537ca2853828fccd6da2ade) --- source3/smbd/oplock_linux.c | 3 ++- source3/smbd/reply.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 39ee3eb86b..c88441c8c6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -62,7 +62,8 @@ static void signal_handler(int sig, siginfo_t *info, void *unused) /**************************************************************************** try to gain a linux capability -****************************************************************************/static void set_capability(unsigned capability) +****************************************************************************/ +static void set_capability(unsigned capability) { #ifndef _LINUX_CAPABILITY_VERSION #define _LINUX_CAPABILITY_VERSION 0x19980330 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0d1d5eed7c..c2d38a1076 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4045,7 +4045,6 @@ SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format /**************************************************************************** Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). ****************************************************************************/ - static uint32 map_lock_offset(uint32 high, uint32 low) { unsigned int i; -- cgit From b30e75692d68233448b3ad3d7ddd4b4ac423d3ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Sep 2001 11:08:57 +0000 Subject: replaced stdio in many parts of samba with a XFILE. XFILE is a cut-down replacemnt of stdio that doesn't suffer from the 8-bit filedescriptor limit that we hit with nasty consequences on some systems I would eventually prefer us to have a configure test to see if we need to replace stdio, but for now this code needs to be tested widely so I'm enabling it by default. (This used to be commit 1af8bf34f1caa3e7ec312d8109c07d32a945a448) --- source3/smbd/server.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 36c98300f0..1dfff6cafa 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -781,11 +781,6 @@ static void usage(char *pname) /* Setup the main smbd so that we can get messages. */ claim_connection(NULL,"",MAXSTATUS,True); - /* Attempt to migrate from an old 2.0.x machine account file. */ - if (!migrate_from_old_password_file(global_myworkgroup)) { - DEBUG(0,("Failed to migrate from old MAC file.\n")); - } - if (!open_sockets(is_daemon,port)) exit(1); -- cgit From 11bd06e99c34a1805a3708321997633349e2dae7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Sep 2001 11:23:41 +0000 Subject: made a couple of local fns static (This used to be commit f0851202a852bed28fbd2446b44ce2b977ddacd8) --- source3/smbd/auth_rhosts.c | 2 +- source3/smbd/chgpasswd.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index ffb9212264..b447bed5d1 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -134,7 +134,7 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) /**************************************************************************** check for a possible hosts equiv or rhosts entry for the user ****************************************************************************/ -BOOL check_hosts_equiv(char *user) +static BOOL check_hosts_equiv(char *user) { char *fname = NULL; pstring rhostsfile; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 030c69bd4a..8dff2f7d81 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -52,6 +52,12 @@ extern int DEBUGLEVEL; extern struct passdb_ops pdb_ops; +static BOOL check_oem_password(char *user, + uchar * lmdata, uchar * lmhash, + uchar * ntdata, uchar * nthash, + SAM_ACCOUNT **hnd, char *new_passwd, + int new_passwd_size); + #if ALLOW_CHANGE_PASSWORD static int findpty(char **slave) @@ -704,11 +710,11 @@ BOOL pass_oem_change(char *user, but does use the lm OEM password to check the nt hashed-hash. ************************************************************/ -BOOL check_oem_password(char *user, - uchar * lmdata, uchar * lmhash, - uchar * ntdata, uchar * nthash, - SAM_ACCOUNT **hnd, char *new_passwd, - int new_passwd_size) +static BOOL check_oem_password(char *user, + uchar * lmdata, uchar * lmhash, + uchar * ntdata, uchar * nthash, + SAM_ACCOUNT **hnd, char *new_passwd, + int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; -- cgit From 45706091f39573c01312179c48842284dc3e9012 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Sep 2001 23:03:14 +0000 Subject: Fix for second logic bug when handing oplock breaks and client messages simultaneously. Jeremy. (This used to be commit 227325b2d63dad55cbcda9608fba676fb6ce5584) --- source3/smbd/process.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9f23c7d3be..bf9e6457af 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -207,6 +207,11 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) signals */ if (selrtn == -1 && errno == EINTR) { async_processing(&fds, buffer, buffer_len); + /* + * After async processing we must go and do the select again, as + * the state of the flag in fds for the server file descriptor is + * indeterminate - we may have done I/O on it in the oplock processing. JRA. + */ goto again; } @@ -231,7 +236,12 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) if (oplock_message_waiting(&fds)) { async_processing(&fds, buffer, buffer_len); - if (!FD_ISSET(smbd_server_fd(),&fds)) goto again; + /* + * After async processing we must go and do the select again, as + * the state of the flag in fds for the server file descriptor is + * indeterminate - we may have done I/O on it in the oplock processing. JRA. + */ + goto again; } return receive_smb(smbd_server_fd(), buffer, 0); -- cgit From 39d7983a470cc3470dd7126de35697d965817cb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Sep 2001 03:08:51 +0000 Subject: - enable MSDFS by default, there seems no reason not to have it enabled by default in Samba 3.x - got rid of some unused parameters in Makefile.in - declare DEBUGLEVEL in debug.h rather than in each file (This used to be commit b8651acb9c0d7248a6a2e82c33b1e43633fd83fd) --- source3/smbd/negprot.c | 4 +--- source3/smbd/nttrans.c | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 6eda7e39db..9ebb0b7350 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -214,10 +214,8 @@ static int reply_nt1(char *outbuf) capabilities |= CAP_UNICODE; } -#ifdef WITH_MSDFS - if(lp_host_msdfs()) + if (lp_host_msdfs()) capabilities |= CAP_DFS; -#endif if (lp_security() >= SEC_USER) secword |= 1; if (doencrypt) secword |= 2; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index aee5aa7798..ca1efd0221 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -41,9 +41,7 @@ static char *known_nt_pipes[] = { "\\lsarpc", "\\winreg", "\\spoolss", -#ifdef WITH_MSDFS "\\netdfs", -#endif NULL }; -- cgit From b800a36b1c81fb37ca963acdc49978ff065fb0d7 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 12 Sep 2001 06:39:50 +0000 Subject: Some patches to authentication: - the usersupplied_info now contains a smb_username (as it comes across on the wire) and a unix_username (after being passed through mapping functions) - when doing security={server,domain} use the smb_username, otherwise use the unix_username (This used to be commit d34fd8ec0716127c7a68eeb8e77d1ae8cc07b547) --- source3/smbd/auth.c | 33 ++++++++++++++++++++------------- source3/smbd/auth_rhosts.c | 2 +- source3/smbd/auth_smbpasswd.c | 2 +- source3/smbd/auth_unix.c | 6 ++++-- source3/smbd/reply.c | 5 +++-- 5 files changed, 29 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index b707c38c62..0101aa65a2 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -63,7 +63,7 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; - DEBUG(3, ("check_password: Checking password for user %s with the new password interface\n", user_info->smb_username.str)); + DEBUG(3, ("check_password: Checking password for smb user %s with the new password interface\n", user_info->smb_username.str)); if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { return NT_STATUS_LOGON_FAILURE; } @@ -81,7 +81,7 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, } if (lp_security() >= SEC_SERVER) { - smb_user_control(user_info->smb_username.str, nt_status); + smb_user_control(user_info->unix_username.str, nt_status); } if (!NT_STATUS_IS_OK(nt_status)) { @@ -97,14 +97,14 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, if (NT_STATUS_IS_OK(nt_status) && !done_pam) { /* We might not be root if we are an RPC call */ become_root(); - nt_status = smb_pam_accountcheck(user_info->smb_username.str); + nt_status = smb_pam_accountcheck(user_info->unix_username.str); unbecome_root(); } if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: Password for user %s suceeded\n", user_info->smb_username.str)); + DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_username.str)); } else { - DEBUG(3, ("check_password: Password for user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status))); + DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status))); } return nt_status; @@ -121,14 +121,16 @@ SMB hash return True if the password is correct, False otherwise ****************************************************************************/ -NTSTATUS pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], +NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, + char *domain, uchar chal[8], uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { auth_usersupplied_info user_info; auth_serversupplied_info server_info; - AUTH_STR ourdomain, theirdomain, smb_username, wksta_name; + AUTH_STR ourdomain, theirdomain, unix_username, smb_username, + wksta_name; ZERO_STRUCT(user_info); ZERO_STRUCT(ourdomain); @@ -145,10 +147,15 @@ NTSTATUS pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], user_info.requested_domain = theirdomain; user_info.domain = ourdomain; - smb_username.str = user; + smb_username.str = smb_user; smb_username.len = strlen(smb_username.str); - user_info.requested_username = smb_username; /* For the time-being */ + /* If unix user is NULL, use smb user */ + + unix_username.str = unix_user ? unix_user : smb_user; + unix_username.len = strlen(unix_username.str); + + user_info.unix_username = unix_username; user_info.smb_username = smb_username; user_info.wksta_name.str = client_name(); @@ -197,7 +204,7 @@ NTSTATUS pass_check_smb_with_chal(char *user, char *domain, uchar chal[8], return check_password(&user_info, &server_info); } -NTSTATUS pass_check_smb(char *user, char *domain, +NTSTATUS pass_check_smb(char *smb_user, char *unix_user, char *domain, uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { @@ -207,7 +214,7 @@ NTSTATUS pass_check_smb(char *user, char *domain, generate_random_buffer( chal, 8, False); } - return pass_check_smb_with_chal(user, domain, chal, + return pass_check_smb_with_chal(smb_user, unix_user, domain, chal, lm_pwd, lm_pwd_len, nt_pwd, nt_pwd_len); @@ -233,11 +240,11 @@ BOOL password_ok(char *user, char *password, int pwlen) /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as required. */ - if (NT_STATUS_IS_OK(pass_check_smb(user, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { return True; } - if (NT_STATUS_IS_OK(pass_check_smb(user, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { return True; } diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index b447bed5d1..2492a2a68b 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -174,7 +174,7 @@ NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; become_root(); - if (check_hosts_equiv(user_info->smb_username.str)) { + if (check_hosts_equiv(user_info->unix_username.str)) { nt_status = NT_STATUS_OK; } unbecome_root(); diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 33b0623643..111a35e068 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -152,7 +152,7 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, user_info->nt_resp.len, nt_pw, - user_info->chal, user_info->requested_username.str, + user_info->chal, user_info->smb_username.str, user_info->requested_domain.str, (char *)server_info->session_key)) { diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 1708320961..ea32a65457 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -73,9 +73,11 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve NTSTATUS nt_status; become_root(); - nt_status = (pass_check(user_info->smb_username.str, user_info->plaintext_password.str, + nt_status = (pass_check(user_info->unix_username.str, + user_info->plaintext_password.str, user_info->plaintext_password.len, - lp_update_encrypted() ? update_smbpassword_file : NULL) + lp_update_encrypted() ? + update_smbpassword_file : NULL) ? NT_STATUS_OK : NT_STATUS_LOGON_FAILURE); unbecome_root(); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c2d38a1076..9e88f58fa6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -462,7 +462,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out smb_username.str = user; smb_username.len = strlen(smb_username.str); - user_info.requested_username = smb_username; /* For the time-being */ + user_info.unix_username = smb_username; /* For the time-being */ user_info.smb_username = smb_username; user_info.wksta_name = wksta_name; @@ -776,7 +776,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int add_session_user(user); if (!guest) { - valid_password = NT_STATUS_IS_OK(pass_check_smb(user, domain, + valid_password = NT_STATUS_IS_OK(pass_check_smb(orig_user, user, + domain, (unsigned char *)smb_apasswd, smb_apasslen, (unsigned char *)smb_ntpasswd, -- cgit From b7a0c132894e15712a55aaa92175df73fb8814a9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 14 Sep 2001 10:38:40 +0000 Subject: Now that we always get back an NTSTATUS code actually pass it on to the auth subsytem. Also kill off the (unneeded) wrapper fuction. Andrew Bartlett (This used to be commit 96f06b490ac5e9fd86debccf8d41675fa41f7726) --- source3/smbd/auth_server.c | 20 ++++---------------- source3/smbd/auth_util.c | 2 +- 2 files changed, 5 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index b279152f74..7ed4cf60ad 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -110,10 +110,11 @@ struct cli_state *server_cryptkey(void) /**************************************************************************** - Validate a password with the password server. + Check for a valid username and password in security=server mode. + - Validate a password with the password server. ****************************************************************************/ -static NTSTATUS server_validate(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { struct cli_state *cli; static unsigned char badpass[24]; @@ -212,7 +213,7 @@ use this machine as the password server.\n")); user_info->domain.str)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); /* Make this cli_nt_error() when the conversion is in */ - nt_status = NT_STATUS_LOGON_FAILURE; + nt_status = cli_nt_error(cli); } else { nt_status = NT_STATUS_OK; } @@ -228,17 +229,4 @@ use this machine as the password server.\n")); return(nt_status); } -/**************************************************************************** - Check for a valid username and password in security=server mode. -****************************************************************************/ - -NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) -{ - - if(lp_security() != SEC_SERVER) - return NT_STATUS_LOGON_FAILURE; - - return server_validate(user_info, server_info); -} - diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 28f58eb8ae..1967c32b9a 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -98,7 +98,7 @@ static int smb_delete_user(char *unix_user) } /**************************************************************************** - Add and Delete UNIX users on demand, based on NT_STATUS codes. + Add and Delete UNIX users on demand, based on NTSTATUS codes. ****************************************************************************/ void smb_user_control(char *unix_user, NTSTATUS nt_status) -- cgit From 1c8c7c558b563e9a3bd0a11e9bc11947f99d700a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 15 Sep 2001 01:59:44 +0000 Subject: Actually fill in the status for sainity checks Andrew Bartlett (This used to be commit d47016de52e9e5c468edf4c87dc60535a9796b99) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index df0f6f2095..62e51f797f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -371,7 +371,7 @@ connection_struct *make_connection(char *service,char *user,char *password, } } - if (NT_STATUS_IS_ERR(share_sanity_checks(snum, service, dev))) { + if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, service, dev))) { return NULL; } -- cgit From 90b5a6279ee9998fa79f9420952ff954dc50c999 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 15 Sep 2001 12:16:22 +0000 Subject: This looked suspicious now we are attempting to to NTLMv2. Andrew Bartlett (This used to be commit 21baa33946a24159ebe873ac37cf30581437aa1a) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9e88f58fa6..6a8fa104fb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -592,8 +592,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } } - if (passlen1 != 24 && passlen2 != 24) - doencrypt = False; + if (passlen1 != 24 && passlen2 <= 24) + doencrypt = False; if (passlen1 > MAX_PASS_LEN) { overflow_attack(passlen1); -- cgit From eb8a3778d0b2e76a9aa1d02eee36ab0ee589d13a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 15 Sep 2001 12:20:21 +0000 Subject: Oops... For reference, NTLMv2 passwords are > 24 chars in length, while NTLMv1 passwords (and old LM passwords) are exactly 24 in lenghth. (This used to be commit 51baa1614d1a338f50dbf8eaa5ea31ab58c11409) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6a8fa104fb..04dcf1c0a8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -592,7 +592,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } } - if (passlen1 != 24 && passlen2 <= 24) + if (passlen1 != 24 && passlen2 < 24) doencrypt = False; if (passlen1 > MAX_PASS_LEN) { -- cgit From 7892c494e7321c64b20bf7e1d794a6b6508fe84a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 15 Sep 2001 12:55:59 +0000 Subject: Kill off the //server/share%user hack in share level security. This should help make much of this code simpiler. Andrew Bartlett (This used to be commit fb0c3629c360fd0c57129500474960e6da6f9ef0) --- source3/smbd/password.c | 8 ------ source3/smbd/reply.c | 73 ++++++------------------------------------------- source3/smbd/service.c | 33 +++++++++------------- 3 files changed, 21 insertions(+), 93 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8e85ef3389..13a54cb704 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -470,14 +470,6 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, */ if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) { - /* check the given username and password */ - if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen); - if (ok) - DEBUG(3,("authorise_login: ACCEPTED: given username (%s) password ok\n", - user )); - } - /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->user.unix_name,snum) && diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 04dcf1c0a8..0b8f160854 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -163,7 +163,6 @@ int reply_tcon(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring service; - pstring user; pstring password; pstring dev; int outsize = 0; @@ -174,47 +173,19 @@ int reply_tcon(connection_struct *conn, START_PROFILE(SMBtcon); - *service = *user = *password = *dev = 0; + *service = *password = *dev = 0; p = smb_buf(inbuf)+1; p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1; p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1; p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1; - *user = 0; - p = strchr_m(service,'%'); - if (p != NULL) { - *p = 0; - fstrcpy(user,p+1); - } - p = strrchr_m(service,'\\'); if (p) { pstrcpy(service, p+1); } - /* - * If the vuid is valid, we should be using that.... - */ - - if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) { - pstrcpy(user,validated_username(vuid)); - } else { - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam( user, True); - } - - conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode); + conn = make_connection(service,password,pwlen,dev,vuid,&ecode); if (!conn) { END_PROFILE(SMBtcon); @@ -226,8 +197,8 @@ int reply_tcon(connection_struct *conn, SSVAL(outbuf,smb_vwv1,conn->cnum); SSVAL(outbuf,smb_tid,conn->cnum); - DEBUG(3,("tcon service=%s user=%s cnum=%d\n", - service, user, conn->cnum)); + DEBUG(3,("tcon service=%s cnum=%d\n", + service, conn->cnum)); END_PROFILE(SMBtcon); return(outsize); @@ -240,7 +211,6 @@ int reply_tcon(connection_struct *conn, int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { fstring service; - pstring user; pstring password; pstring devicename; NTSTATUS ecode; @@ -250,7 +220,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt char *p, *q; START_PROFILE(SMBtconX); - *service = *user = *password = *devicename = 0; + *service = *password = *devicename = 0; /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { @@ -289,38 +259,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt else fstrcpy(service,path); - q = strchr_m(service,'%'); - if (q) { - *q++ = 0; - fstrcpy(user,q); - } p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII); DEBUG(4,("Got device type %s\n",devicename)); - /* - * If the vuid is valid, we should be using that.... - */ - - if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) { - pstrcpy(user,validated_username(vuid)); - } else { - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam(user, True); - - } - - conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode); + conn = make_connection(service,password,passlen,devicename,vuid,&ecode); if (!conn) { END_PROFILE(SMBtconX); @@ -355,8 +298,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - DEBUG(3,("tconX service=%s user=%s\n", - service, user)); + DEBUG(3,("tconX service=%s \n", + service)); /* set the incoming and outgoing tid to the just created one */ SSVAL(inbuf,smb_tid,conn->cnum); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 62e51f797f..4765844460 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -318,7 +318,7 @@ static void set_admin_user(connection_struct *conn) /**************************************************************************** make a connection to a service ****************************************************************************/ -connection_struct *make_connection(char *service,char *user,char *password, +connection_struct *make_connection(char *service,char *password, int pwlen, char *dev,uint16 vuid, NTSTATUS *status) { int snum; @@ -326,7 +326,8 @@ connection_struct *make_connection(char *service,char *user,char *password, BOOL guest = False; BOOL force = False; connection_struct *conn; - int ret; + + fstring user; strlower(service); @@ -345,28 +346,20 @@ connection_struct *make_connection(char *service,char *user,char *password, } if (strequal(service,HOMES_NAME)) { - if (*user && Get_Pwnam(user,True)) { - fstring dos_username; - fstrcpy(dos_username, user); - return(make_connection(dos_username,user,password, - pwlen,dev,vuid,status)); - } - if(lp_security() != SEC_SHARE) { if (validated_username(vuid)) { - fstring dos_username; - fstrcpy(user,validated_username(vuid)); - fstrcpy(dos_username, user); - return(make_connection(dos_username,user,password,pwlen,dev,vuid,status)); + fstring unix_username; + fstrcpy(unix_username,validated_username(vuid)); + return(make_connection(unix_username,password,pwlen,dev,vuid,status)); } } else { /* Security = share. Try with current_user_info.smb_name * as the username. */ if(*current_user_info.smb_name) { - fstring dos_username; - fstrcpy(user,current_user_info.smb_name); - fstrcpy(dos_username, user); - return(make_connection(dos_username,user,password,pwlen,dev,vuid,status)); + fstring unix_username; + fstrcpy(unix_username,current_user_info.smb_name); + map_username(unix_username); + return(make_connection(unix_username,password,pwlen,dev,vuid,status)); } } } @@ -375,15 +368,13 @@ connection_struct *make_connection(char *service,char *user,char *password, return NULL; } - /* lowercase the user name */ - strlower(user); - /* add it as a possible user name if we are in share mode security */ if (lp_security() == SEC_SHARE) { add_session_user(service); } + /* shall we let them in? */ if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) ); @@ -574,6 +565,7 @@ connection_struct *make_connection(char *service,char *user,char *password, /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { + int ret; pstring cmd; pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); standard_sub_conn(conn,cmd); @@ -630,6 +622,7 @@ connection_struct *make_connection(char *service,char *user,char *password, /* execute any "preexec = " line */ if (*lp_preexec(SNUM(conn))) { + int ret; pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); standard_sub_conn(conn,cmd); -- cgit From 72c35310b2b0d39c077c50a2175c76ced5d4c662 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 15 Sep 2001 13:21:54 +0000 Subject: use variables _before_ freeing them! thanks to Andreas Moroder for spotting these two. (This used to be commit 01f30ca0ad472eaab8f80ec4278b1d391be3a1ae) --- source3/smbd/open.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 145d12e3f3..7974ea0ae0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -497,9 +497,9 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi lock_share_entry(conn, dev, inode); if(opb_ret == False) { - free((char *)old_shares); DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); + free((char *)old_shares); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -1234,11 +1234,10 @@ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (doub unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { - free((char *)old_shares); - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); + free((char *)old_shares); return False; } lock_share_entry(conn, dev, inode); -- cgit From 4d89a65a845dbf6f8fa8aa46d2631cfd3a879e0a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 16 Sep 2001 02:35:55 +0000 Subject: Start pushing the NTSTATUS stuff out to the wire for session setups. Rework the 'map to guest' code, its now possible to follow what its trying to do... Add an NT_STATUS_EQUAL(x,y) macro to make this stuff sane to look at. Andrew Bartlett (This used to be commit d618880661976644a6ee713edf969ad561e82097) --- source3/smbd/reply.c | 78 ++++++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0b8f160854..a379bf1f7f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -486,7 +486,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int pstring smb_apasswd; int smb_ntpasslen = 0; pstring smb_ntpasswd; - BOOL valid_password = False; pstring user; pstring orig_user; fstring domain; @@ -719,57 +718,34 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int add_session_user(user); if (!guest) { - valid_password = NT_STATUS_IS_OK(pass_check_smb(orig_user, user, - domain, - (unsigned char *)smb_apasswd, - smb_apasslen, - (unsigned char *)smb_ntpasswd, - smb_ntpasslen)); - - /* The true branch will be executed if - (1) the NT password failed (or was not tried), and - (2) LanMan authentication failed (or was disabled) - */ - if (!valid_password) - { - if (lp_security() >= SEC_USER) - { - if (lp_map_to_guest() == NEVER_MAP_TO_GUEST) - { - DEBUG(1,("Rejecting user '%s': authentication failed\n", user)); - END_PROFILE(SMBsesssetupX); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) - { - if (smb_getpwnam(user,True)) - { - DEBUG(1,("Rejecting user '%s': bad password\n", user)); - END_PROFILE(SMBsesssetupX); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - } - - /* - * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD - * Then always map to guest account - as done below. - */ - } - - if (*smb_apasswd || !smb_getpwnam(user,True)) - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } - } - - if (!smb_getpwnam(user,True)) { - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - pstrcpy(user,lp_guestaccount(-1)); - guest = True; + NTSTATUS nt_status; + nt_status = pass_check_smb(orig_user, user, + domain, + (unsigned char *)smb_apasswd, + smb_apasslen, + (unsigned char *)smb_ntpasswd, + smb_ntpasslen); + + if NT_STATUS_IS_OK(nt_status) { + + } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) + && lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) { + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); + pstrcpy(user,lp_guestaccount(-1)); + guest = True; + + } else if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) + || NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) + && (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + pstrcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + + } else { + return ERROR_NT(nt_status); + } } - + if (!strequal(user,lp_guestaccount(-1)) && lp_servicenumber(user) < 0) { -- cgit From dec3cbcaf097a3d6fab9359e001279447a5f4def Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 16 Sep 2001 06:35:35 +0000 Subject: Fix up workstaion and kickoff time checks, moved to auth_smbpasswd.c where they can have general effect. Fixed up workstaion support in the rest of samba, so that we can do these checks. Pass through the workstation for cli_net_logon(), if supplied. (This used to be commit 7f04a139b2ee34b4c282590509cdf21395815a7a) --- source3/smbd/auth.c | 23 ++++++++++++---------- source3/smbd/auth_smbpasswd.c | 45 ++++++++++++++++++++++++++++++++++++++++--- source3/smbd/reply.c | 11 +++++++---- 3 files changed, 62 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 0101aa65a2..5b6b2d4c42 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -25,8 +25,6 @@ extern int DEBUGLEVEL; -extern pstring global_myname; - /**************************************************************************** Check user is in correct domain if required ****************************************************************************/ @@ -63,7 +61,8 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; - DEBUG(3, ("check_password: Checking password for smb user %s with the new password interface\n", user_info->smb_username.str)); + DEBUG(3, ("check_password: Checking password for smb user %s\\%s@%s with the new password interface\n", + user_info->smb_username.str, user_info->requested_domain.str, user_info->wksta_name.str)); if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { return NT_STATUS_LOGON_FAILURE; } @@ -122,7 +121,8 @@ return True if the password is correct, False otherwise ****************************************************************************/ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, - char *domain, uchar chal[8], + char *domain, char* workstation, + uchar chal[8], uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { @@ -158,8 +158,8 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, user_info.unix_username = unix_username; user_info.smb_username = smb_username; - user_info.wksta_name.str = client_name(); - user_info.wksta_name.len = strlen(client_name()); + wksta_name.str = workstation; + wksta_name.len = strlen(workstation); user_info.wksta_name = wksta_name; @@ -204,7 +204,8 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, return check_password(&user_info, &server_info); } -NTSTATUS pass_check_smb(char *smb_user, char *unix_user, char *domain, +NTSTATUS pass_check_smb(char *smb_user, char *unix_user, + char *domain, char *workstation, uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { @@ -214,7 +215,8 @@ NTSTATUS pass_check_smb(char *smb_user, char *unix_user, char *domain, generate_random_buffer( chal, 8, False); } - return pass_check_smb_with_chal(smb_user, unix_user, domain, chal, + return pass_check_smb_with_chal(smb_user, unix_user, + domain, workstation, chal, lm_pwd, lm_pwd_len, nt_pwd, nt_pwd_len); @@ -227,6 +229,7 @@ return True if the password is correct, False otherwise ****************************************************************************/ BOOL password_ok(char *user, char *password, int pwlen) { + extern fstring remote_machine; /* * This hack must die! But until I rewrite the rest of samba @@ -240,11 +243,11 @@ BOOL password_ok(char *user, char *password, int pwlen) /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as required. */ - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { return True; } - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { return True; } diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 111a35e068..b61fde4206 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -112,9 +112,9 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { uint8 *nt_pw, *lm_pw; - uint16 acct_ctrl; - - acct_ctrl = pdb_get_acct_ctrl(sampass); + uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); + char *workstation_list; + time_t kickoff_time; /* Quit if the account was disabled. */ if(acct_ctrl & ACB_DISABLED) { @@ -122,6 +122,45 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use return(NT_STATUS_ACCOUNT_DISABLED); } + /* Test account expire time */ + + kickoff_time = pdb_get_kickoff_time(sampass); + if (kickoff_time != (time_t)-1) { + if (time(NULL) > kickoff_time) { + return NT_STATUS_ACCOUNT_EXPIRED; + } + } + + /* Test workstation. Workstation list is comma separated. */ + + workstation_list = strdup(pdb_get_workstations(sampass)); + + if (workstation_list) { + if (*workstation_list) { + BOOL invalid_ws = True; + char *s = workstation_list; + + fstring tok; + + while (next_token(&s, tok, ",", sizeof(tok))) { + DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", + tok, user_info->wksta_name.str, user_info->wksta_name.len)); + if(strequal(tok, user_info->wksta_name.str)) { + invalid_ws = False; + break; + } + } + + free(workstation_list); + if (invalid_ws) + return NT_STATUS_INVALID_WORKSTATION; + } else { + free(workstation_list); + } + } else { + return NT_STATUS_NO_MEMORY; + } + if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a379bf1f7f..1559cd30df 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3,7 +3,8 @@ Version 1.9. Main SMB reply routines Copyright (C) Andrew Tridgell 1992-1998 - + Copyright (C) Andrew Bartlett 2001 + 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 @@ -41,6 +42,8 @@ extern int global_oplock_break; uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; +extern fstring remote_machine; + /**************************************************************************** report a possible attack via the password buffer overflow bug ****************************************************************************/ @@ -66,7 +69,7 @@ int reply_special(char *inbuf,char *outbuf) int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); pstring name1,name2; - extern fstring remote_machine; + extern fstring local_machine; int len; char name_type = 0; @@ -637,7 +640,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } - DEBUG(3,("sesssetupX:name=[%s]\n",user)); + DEBUG(3,("sesssetupX:name=[%s]@[%s]\n",user, remote_machine)); /* If name ends in $ then I think it's asking about whether a */ /* computer with that name (minus the $) has access. For now */ @@ -720,7 +723,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!guest) { NTSTATUS nt_status; nt_status = pass_check_smb(orig_user, user, - domain, + domain, remote_machine, (unsigned char *)smb_apasswd, smb_apasslen, (unsigned char *)smb_ntpasswd, -- cgit From 23af0743267d250a90af77c3bbce4d5fd0cdcc00 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Sep 2001 04:23:48 +0000 Subject: fixed ctemp in server and client. It turns out that ctemp on NT is completely broken, and it's pointless to emulate their brokenness completely in this case, but at least this makes us use approximately the same packet format. The spec is complelet wrong in this case (This used to be commit 2d507ec669def6d49304559e53d6c14af9b290a9) --- source3/smbd/reply.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1559cd30df..3dca209581 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1581,13 +1581,13 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int oplock_request = CORE_OPLOCK_REQUEST(inbuf); int tmpfd; SMB_STRUCT_STAT sbuf; - char *p; + char *p, *s; START_PROFILE(SMBctemp); createmode = SVAL(inbuf,smb_vwv0); srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE); - pstrcat(fname,"/TMXXXXXX"); + pstrcat(fname,"\\TMXXXXXX"); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1626,17 +1626,28 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); - CVAL(smb_buf(outbuf),0) = 4; - p = smb_buf(outbuf) + 1; - p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - set_message_end(outbuf, p); + + /* the returned filename is relative to the directory */ + s = strrchr_m(fname, '/'); + if (!s) { + s = fname; + } else { + s++; + } + + p = smb_buf(outbuf); + SSVALS(p, 0, -1); /* what is this? not in spec */ + SSVAL(p, 2, strlen(s)); + p += 4; + p += srvstr_push(outbuf, p, s, -1, STR_ASCII); + outsize = set_message_end(outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; } - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG( 2, ( "created temp file %s\n", fname ) ); DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", -- cgit From 61b2794968faa35dc91edce17e9b91e5366c3514 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 17 Sep 2001 11:25:41 +0000 Subject: move to SAFE_FREE() (This used to be commit a95943fde0ad89ae3f2deca2f7ba9cb5ab612b74) --- source3/smbd/auth_server.c | 2 +- source3/smbd/auth_smbpasswd.c | 4 ++-- source3/smbd/blocking.c | 6 +++--- source3/smbd/close.c | 2 +- source3/smbd/conn.c | 5 ++--- source3/smbd/dir.c | 22 ++++++++++------------ source3/smbd/fileio.c | 8 +++----- source3/smbd/files.c | 2 +- source3/smbd/groupname.c | 16 ++++++---------- source3/smbd/ipc.c | 22 ++++++++-------------- source3/smbd/lanman.c | 32 ++++++++++++++------------------ source3/smbd/mangle.c | 8 ++++---- source3/smbd/notify.c | 4 ++-- source3/smbd/notify_hash.c | 2 +- source3/smbd/notify_kernel.c | 2 +- source3/smbd/nttrans.c | 33 ++++++++++++--------------------- source3/smbd/open.c | 17 ++++++++--------- source3/smbd/oplock.c | 10 ++++------ source3/smbd/password.c | 8 ++++---- source3/smbd/posix_acls.c | 20 +++++++++----------- source3/smbd/process.c | 6 +++--- source3/smbd/quotas.c | 2 +- source3/smbd/reply.c | 2 +- source3/smbd/sec_ctx.c | 16 +++++++--------- source3/smbd/session.c | 3 +-- source3/smbd/trans2.c | 24 ++++++++---------------- source3/smbd/vfs.c | 2 +- 27 files changed, 118 insertions(+), 162 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index 7ed4cf60ad..e4c91c4dcb 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -77,7 +77,7 @@ struct cli_state *server_cryptkey(void) } } - free(pserver); + SAFE_FREE(pserver); if (!connected_ok) { DEBUG(0,("password server not available\n")); diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index b61fde4206..fb77a7a5c6 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -151,11 +151,11 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use } } - free(workstation_list); + SAFE_FREE(workstation_list); if (invalid_ws) return NT_STATUS_INVALID_WORKSTATION; } else { - free(workstation_list); + SAFE_FREE(workstation_list); } } else { return NT_STATUS_NO_MEMORY; diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2008598104..cec1581254 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -46,8 +46,8 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu static void free_blocking_lock_record(blocking_lock_record *blr) { - free(blr->inbuf); - free((char *)blr); + SAFE_FREE(blr->inbuf); + SAFE_FREE(blr); } /**************************************************************************** @@ -103,7 +103,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int if((blr->inbuf = (char *)malloc(length)) == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); - free((char *)blr); + SAFE_FREE(blr); return False; } diff --git a/source3/smbd/close.c b/source3/smbd/close.c index f790778676..c92e084759 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -161,7 +161,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) ) delete_on_close = True; - safe_free(share_entry); + SAFE_FREE(share_entry); /* * NT can set delete_on_close of the last open diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index c2faa4f15a..08704927c5 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -177,8 +177,7 @@ void conn_free(connection_struct *conn) DLIST_REMOVE(Connections, conn); if (conn->ngroups && conn->groups) { - free(conn->groups); - conn->groups = NULL; + SAFE_FREE(conn->groups); conn->ngroups = 0; } @@ -196,7 +195,7 @@ void conn_free(connection_struct *conn) num_open--; ZERO_STRUCTP(conn); - free(conn); + SAFE_FREE(conn); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 9a9c745944..c0c728fe8f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -246,10 +246,9 @@ static void dptr_close_internal(dptr_struct *dptr) } /* Lanman 2 specific code */ - if (dptr->wcard) - free(dptr->wcard); + SAFE_FREE(dptr->wcard); string_set(&dptr->path,""); - free((char *)dptr); + SAFE_FREE(dptr); } /**************************************************************************** @@ -438,7 +437,7 @@ int dptr_create(connection_struct *conn,char *path, BOOL old_handle, BOOL expect if(dptr->dnum == -1 || dptr->dnum > 254) { DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); - free((char *)dptr); + SAFE_FREE(dptr); return -1; } } @@ -467,7 +466,7 @@ int dptr_create(connection_struct *conn,char *path, BOOL old_handle, BOOL expect if(dptr->dnum == -1 || dptr->dnum < 255) { DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); - free((char *)dptr); + SAFE_FREE(dptr); return -1; } } @@ -730,7 +729,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { ret = user_can_read_file(conn, entry); - free(entry); + SAFE_FREE(entry); } if (!ret) continue; } @@ -763,10 +762,9 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) void CloseDir(void *p) { - Dir *dirp = (Dir *)p; - if (!dirp) return; - if (dirp->data) free(dirp->data); - free(dirp); + if (!p) return; + SAFE_FREE(((Dir *)p)->data); + SAFE_FREE(p); } /******************************************************************* @@ -875,7 +873,7 @@ void DirCacheAdd( char *path, char *name, char *dname, int snum ) /* Free excess cache entries. */ while( DIRCACHESIZE < dir_cache->count ) - free( ubi_dlRemTail( dir_cache ) ); + safe_free( ubi_dlRemTail( dir_cache ) ); } @@ -927,7 +925,7 @@ void DirCacheFlush(int snum) NULL != entry; ) { next = ubi_dlNext( entry ); if( entry->snum == snum ) - free( ubi_dlRemThis( dir_cache, entry ) ); + safe_free( ubi_dlRemThis( dir_cache, entry ) ); entry = (dir_cache_entry *)next; } } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index c79f0aa89e..003bee84ed 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -482,10 +482,8 @@ void delete_write_cache(files_struct *fsp) SMB_ASSERT(wcp->data_size == 0); - free(wcp->data); - free(wcp); - - fsp->wcp = NULL; + SAFE_FREE(wcp->data); + SAFE_FREE(fsp->wcp); DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name )); @@ -518,7 +516,7 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) if((wcp->data = malloc(wcp->alloc_size)) == NULL) { DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", (unsigned int)wcp->alloc_size )); - free(wcp); + SAFE_FREE(wcp); return False; } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 27dfad7c48..4273c205cd 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -311,7 +311,7 @@ void file_free(files_struct *fsp) if (fsp == chain_fsp) chain_fsp = NULL; - free(fsp); + SAFE_FREE(fsp); } diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 0640d4d7b2..eb2931d2a5 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -53,11 +53,9 @@ static void delete_groupname_map_list(void) groupname_map_entry *gmep; while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) { - if(gmep->windows_name) - free(gmep->windows_name); - if(gmep->unix_name) - free(gmep->unix_name); - free((char *)gmep); + SAFE_FREE(gmep->windows_name); + SAFE_FREE(gmep->unix_name); + SAFE_FREE(gmep); } } @@ -188,11 +186,9 @@ Error was %s.\n", unixname, strerror(errno) )); if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) { DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n")); fclose(fp); - if(new_ep->windows_name != NULL) - free(new_ep->windows_name); - if(new_ep->unix_name != NULL) - free(new_ep->unix_name); - free((char *)new_ep); + SAFE_FREE(new_ep->windows_name); + SAFE_FREE(new_ep->unix_name); + SAFE_FREE(new_ep); file_lines_free(lines); return; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a323261d88..b1af01ff4c 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -175,13 +175,13 @@ static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) } if((data_len = read_from_pipe( p, rdata, p->max_trans_reply)) < 0) { - free(rdata); + SAFE_FREE(rdata); return False; } send_trans_reply(outbuf, NULL, 0, rdata, data_len, p->out_data.current_pdu_len > data_len); - free(rdata); + SAFE_FREE(rdata); return True; } @@ -434,12 +434,9 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int DEBUG(0,("reply_trans: %s in getting secondary trans response.\n", (smb_read_error == READ_ERROR) ? "error" : "timeout" )); } - if (params) - free(params); - if (data) - free(data); - if (setup) - free(setup); + SAFE_FREE(params); + SAFE_FREE(data); + SAFE_FREE(setup); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRSRV,ERRerror)); } @@ -501,12 +498,9 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } - if (data) - free(data); - if (params) - free(params); - if (setup) - free(setup); + SAFE_FREE(data); + SAFE_FREE(params); + SAFE_FREE(setup); if (close_on_completion) close_cnum(conn,vuid); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index eb0e7154a2..4d3da88783 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -945,10 +945,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); - if (queue) - free(queue); - if (tmpdata) - free (tmpdata); + SAFE_FREE(queue); + SAFE_FREE(tmpdata); return(True); } @@ -1038,7 +1036,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, } } - if (subcntarr) free(subcntarr); + SAFE_FREE(subcntarr); *rdata_len = desc.usedlen; *rparam_len = 8; @@ -1049,11 +1047,11 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, SSVAL(*rparam,6,queuecnt); for (i = 0; i < queuecnt; i++) { - if (queue && queue[i]) free(queue[i]); + if (queue) SAFE_FREE(queue[i]); } - if (queue) free(queue); - if (status) free(status); + SAFE_FREE(queue); + SAFE_FREE(status); return True; } @@ -1403,7 +1401,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param SSVAL(*rparam,4,counted); SSVAL(*rparam,6,counted+missed); - if (servers) free(servers); + SAFE_FREE(servers); DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", domain,uLevel,counted,counted+missed)); @@ -2274,7 +2272,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par pstrcpy(comment,servers[i].comment); } } - if (servers) free(servers); + SAFE_FREE(servers); SCVAL(p,0,lp_major_announce_version()); SCVAL(p,1,lp_minor_announce_version()); @@ -2939,8 +2937,8 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); - if (queue) free(queue); - if (tmpdata) free(tmpdata); + SAFE_FREE(queue); + SAFE_FREE(tmpdata); DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); return(True); @@ -3009,7 +3007,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa SSVAL(*rparam,4,succnt); SSVAL(*rparam,6,count); - if (queue) free(queue); + SAFE_FREE(queue); DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); return(True); @@ -3128,7 +3126,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par SSVAL(*rparam,4,desc.neededlen); DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); - if (tmpdata) free (tmpdata); + SAFE_FREE(tmpdata); return(True); } @@ -3478,10 +3476,8 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); - if (rdata ) - free(rdata); - if (rparam) - free(rparam); + SAFE_FREE(rdata); + SAFE_FREE(rparam); return -1; } diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 16286a8bb1..0e6689d9d2 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -451,7 +451,7 @@ static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) static void cache_free_entry( ubi_trNodePtr WarrenZevon ) { ZERO_STRUCTP(WarrenZevon); - free( WarrenZevon ); + SAFE_FREE( WarrenZevon ); } /* cache_free_entry */ /* ************************************************************************** ** @@ -618,7 +618,7 @@ BOOL check_mangled_cache( char *s ) { /* Replace the saved_ext as it was truncated. */ (void)pstrcat( s, saved_ext ); - free(saved_ext); + SAFE_FREE(saved_ext); } return( False ); } @@ -634,7 +634,7 @@ BOOL check_mangled_cache( char *s ) { /* Replace the saved_ext as it was truncated. */ (void)pstrcat( s, saved_ext ); - free(saved_ext); + SAFE_FREE(saved_ext); } DEBUG( 3, ("as %s\n", s) ); @@ -957,7 +957,7 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) if(tmp != NULL) { cache_mangled_name(OutName, tmp); - free(tmp); + SAFE_FREE(tmp); } } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5aa0b4ad3f..68b51aeabb 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -76,7 +76,7 @@ static void change_notify_remove(struct change_notify *cnbp) cnotify->remove_notify(cnbp->change_data); DLIST_REMOVE(change_notify_list, cnbp); ZERO_STRUCTP(cnbp); - free(cnbp); + SAFE_FREE(cnbp); } @@ -188,7 +188,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); if (!cnbp->change_data) { - free(cnbp); + SAFE_FREE(cnbp); return False; } diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index a0a61569a8..8157e1ff31 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -164,7 +164,7 @@ remove a change notify data structure *****************************************************************************/ static void hash_remove_notify(void *datap) { - free(datap); + SAFE_FREE(datap); } diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 11a5592458..4b84831550 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -111,7 +111,7 @@ static void kernel_remove_notify(void *datap) } close(fd); } - free(data); + SAFE_FREE(data); DEBUG(3,("removed kernel change notify fd=%d\n", fd)); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ca1efd0221..c072a38474 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1693,9 +1693,9 @@ due to being in oplock break state.\n" )); if ((total_parameter_count && !params) || (total_data_count && !data) || (setup_count && !setup)) { - safe_free(setup); - safe_free(params); - safe_free(data); + SAFE_FREE(setup); + SAFE_FREE(params); + SAFE_FREE(data); DEBUG(0,("reply_nttrans : Out of memory\n")); END_PROFILE(SMBnttrans); return ERROR_DOS(ERRDOS,ERRnomem); @@ -1745,12 +1745,9 @@ due to being in oplock break state.\n" )); DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", (smb_read_error == READ_ERROR) ? "error" : "timeout" )); } - if(params) - free(params); - if(data) - free(data); - if(setup) - free(setup); + SAFE_FREE(params); + SAFE_FREE(data); + SAFE_FREE(setup); END_PROFILE(SMBnttrans); return ERROR_DOS(ERRSRV,ERRerror); } @@ -1821,12 +1818,9 @@ due to being in oplock break state.\n" )); default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); - if(setup) - free(setup); - if(params) - free(params); - if(data) - free(data); + SAFE_FREE(setup); + SAFE_FREE(params); + SAFE_FREE(data); END_PROFILE(SMBnttrans); return ERROR_DOS(ERRSRV,ERRerror); } @@ -1838,12 +1832,9 @@ due to being in oplock break state.\n" )); an error packet. */ - if(setup) - free(setup); - if(params) - free(params); - if(data) - free(data); + SAFE_FREE(setup); + SAFE_FREE(params); + SAFE_FREE(data); END_PROFILE(SMBnttrans); return outsize; /* If a correct response was needed the call_nt_transact_xxxx calls have already sent it. If outsize != -1 then it is diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7974ea0ae0..7ac5a18609 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -499,7 +499,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi if(opb_ret == False) { DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); - free((char *)old_shares); + SAFE_FREE(old_shares); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -518,7 +518,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if we can too */ if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { - free((char *)old_shares); + SAFE_FREE(old_shares); errno = EACCES; return -1; } @@ -526,7 +526,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } /* end for */ if(broke_oplock) { - free((char *)old_shares); + SAFE_FREE(old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares); oplock_contention_count++; @@ -565,7 +565,7 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn * other process's entry. */ - free((char *)old_shares); + SAFE_FREE(old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares); break; } @@ -575,7 +575,7 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn } while(broke_oplock); if(old_shares != 0) - free((char *)old_shares); + SAFE_FREE(old_shares); /* * Refuse to grant an oplock in case the contention limit is @@ -1237,7 +1237,7 @@ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (doub DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); - free((char *)old_shares); + SAFE_FREE(old_shares); return False; } lock_share_entry(conn, dev, inode); @@ -1267,7 +1267,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { - free((char *)old_shares); + SAFE_FREE(old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares); } } while(broke_oplock); @@ -1288,7 +1288,6 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free_and_exit: unlock_share_entry(conn, dev, inode); - if(old_shares != NULL) - free((char *)old_shares); + SAFE_FREE(old_shares); return(ret); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 7033eddc16..c17e63384f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -701,8 +701,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B if((outbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - free(inbuf); - inbuf = NULL; + SAFE_FREE(inbuf); return False; } @@ -840,8 +839,8 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B file_chain_restore(); /* Free the buffers we've been using to recurse. */ - free(inbuf); - free(outbuf); + SAFE_FREE(inbuf); + SAFE_FREE(outbuf); /* We need this in case a readraw crossed on the wire. */ if(global_oplock_break) @@ -1217,8 +1216,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) } } - if (share_list) - free((char *)share_list); + SAFE_FREE(share_list); unlock_share_entry_fsp(fsp); /* Paranoia check... */ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 13a54cb704..a05735b4d7 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -71,9 +71,9 @@ void invalidate_vuid(uint16 vuid) DLIST_REMOVE(validated_users, vuser); - safe_free(vuser->groups); + SAFE_FREE(vuser->groups); delete_nt_token(&vuser->nt_user_token); - safe_free(vuser); + SAFE_FREE(vuser); num_validated_vuids--; } @@ -139,7 +139,7 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, num_sids = 5 + ngroups; if ((token->user_sids = (DOM_SID *)malloc( num_sids*sizeof(DOM_SID))) == NULL) { - free(token); + SAFE_FREE(token); return NULL; } @@ -503,7 +503,7 @@ and given password ok\n", user)); } } - free(user_list); + SAFE_FREE(user_list); } /* check for a previously validated username/password pair */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 48fac44bbf..18a635336c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -74,7 +74,7 @@ static void free_canon_ace_list( canon_ace *list_head ) while (list_head) { canon_ace *old_head = list_head; DLIST_REMOVE(list_head, list_head); - free(old_head); + SAFE_FREE(old_head); } } @@ -256,7 +256,7 @@ static void merge_aces( canon_ace **pp_list_head ) curr_ace_outer->perms |= curr_ace->perms; DLIST_REMOVE(list_head, curr_ace); - free(curr_ace); + SAFE_FREE(curr_ace); curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */ } } @@ -301,7 +301,7 @@ static void merge_aces( canon_ace **pp_list_head ) */ DLIST_REMOVE(list_head, curr_ace); - free(curr_ace); + SAFE_FREE(curr_ace); curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */ } else { @@ -317,7 +317,7 @@ static void merge_aces( canon_ace **pp_list_head ) */ DLIST_REMOVE(list_head, curr_ace_outer); - free(curr_ace_outer); + SAFE_FREE(curr_ace_outer); } } @@ -746,7 +746,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - free(current_ace); + SAFE_FREE(current_ace); DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n", sid_to_string(str, ¤t_ace->sid) )); return False; @@ -816,7 +816,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - free(current_ace); + SAFE_FREE(current_ace); return False; } @@ -867,7 +867,7 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - free(current_ace); + SAFE_FREE(current_ace); return False; } @@ -883,8 +883,7 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); * Free if ACE was not added. */ - if (current_ace) - free(current_ace); + SAFE_FREE(current_ace); } if (fsp->is_directory && all_aces_are_inherit_only) { @@ -1968,8 +1967,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) sys_acl_free_acl(dir_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - if (nt_ace_list) - free(nt_ace_list); + SAFE_FREE(nt_ace_list); return sd_size; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index bf9e6457af..acda7128ae 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -87,7 +87,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) if(msg->msg_buf == NULL) { DEBUG(0,("push_message: malloc fail (2)\n")); - free((char *)msg); + SAFE_FREE(msg); return False; } @@ -180,8 +180,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); /* Free the message we just copied. */ - free((char *)msg->msg_buf); - free((char *)msg); + SAFE_FREE(msg->msg_buf); + SAFE_FREE(msg); DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); return True; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 5d82756f24..3ef04b0692 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -413,7 +413,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize)); - safe_free(cutstr); + SAFE_FREE(cutstr); DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); return ret; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3dca209581..8527ebbe34 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3051,7 +3051,7 @@ int reply_printqueue(connection_struct *conn, SSVAL(smb_buf(outbuf),1,28*count); } - if (queue) free(queue); + SAFE_FREE(queue); DEBUG(3,("%d entries returned in queue\n",count)); } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index e0e392decc..72e23306ec 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -157,7 +157,7 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups) } if ((ngroups = sys_getgroups(ngroups,groups)) == -1) { - safe_free(groups); + SAFE_FREE(groups); return -1; } @@ -181,11 +181,10 @@ void delete_nt_token(NT_USER_TOKEN **pptoken) { if (*pptoken) { NT_USER_TOKEN *ptoken = *pptoken; - safe_free( ptoken->user_sids ); + SAFE_FREE( ptoken->user_sids ); ZERO_STRUCTP(ptoken); } - safe_free(*pptoken); - *pptoken = NULL; + SAFE_FREE(*pptoken); } /**************************************************************************** @@ -205,7 +204,7 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) ZERO_STRUCTP(token); if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) { - free(token); + SAFE_FREE(token); return NULL; } @@ -244,8 +243,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx - 1]; - safe_free(prev_ctx_p->groups); - prev_ctx_p->groups = NULL; + SAFE_FREE(prev_ctx_p->groups); prev_ctx_p->ngroups = 0; get_current_groups(&prev_ctx_p->ngroups, &prev_ctx_p->groups); @@ -336,7 +334,7 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN ctx_p->ngroups = ngroups; - safe_free(ctx_p->groups); + SAFE_FREE(ctx_p->groups); if (token && (token == ctx_p->token)) smb_panic("DUPLICATE_TOKEN"); @@ -393,7 +391,7 @@ BOOL pop_sec_ctx(void) ctx_p->uid = (uid_t)-1; ctx_p->gid = (gid_t)-1; - safe_free(ctx_p->groups); + SAFE_FREE(ctx_p->groups); ctx_p->ngroups = 0; delete_nt_token(&ctx_p->token); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 6a27cd7326..faf1bb249f 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -145,8 +145,7 @@ void session_yield(uint16 vuid) memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); - safe_free(dbuf.dptr); - dbuf.dptr = NULL; + SAFE_FREE(dbuf.dptr); #if WITH_UTMP if (lp_utmp()) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cb4ca994f4..139b97d088 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2466,10 +2466,8 @@ int reply_trans2(connection_struct *conn, if ((total_params && !params) || (total_data && !data)) { DEBUG(2,("Out of memory in reply_trans2\n")); - if(params) - free(params); - if(data) - free(data); + SAFE_FREE(params); + SAFE_FREE(data); END_PROFILE(SMBtrans2); return ERROR_DOS(ERRDOS,ERRnomem); } @@ -2508,10 +2506,8 @@ int reply_trans2(connection_struct *conn, else DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - if(params) - free(params); - if(data) - free(data); + SAFE_FREE(params); + SAFE_FREE(data); END_PROFILE(SMBtrans2); return ERROR_DOS(ERRSRV,ERRerror); } @@ -2632,10 +2628,8 @@ int reply_trans2(connection_struct *conn, default: /* Error in request */ DEBUG(2,("Unknown request %d in trans2 call\n", tran_call)); - if(params) - free(params); - if(data) - free(data); + SAFE_FREE(params); + SAFE_FREE(data); END_PROFILE(SMBtrans2); return ERROR_DOS(ERRSRV,ERRerror); } @@ -2647,10 +2641,8 @@ int reply_trans2(connection_struct *conn, an error packet. */ - if(params) - free(params); - if(data) - free(data); + SAFE_FREE(params); + SAFE_FREE(data); END_PROFILE(SMBtrans2); return outsize; /* If a correct response was needed the call_trans2xxx calls have already sent diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index fce13bf13d..60762a0155 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -572,7 +572,7 @@ static void array_promote(char *array,int elsize,int element) memcpy(p,array + element * elsize, elsize); memmove(array + elsize,array,elsize*element); memcpy(array,p,elsize); - free(p); + SAFE_FREE(p); } /******************************************************************* -- cgit From 3e9bcd111df39a5801193bd79d22f7fbacaade45 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Sep 2001 03:30:20 +0000 Subject: don't try to initgroups in non root mode (This used to be commit 1a04ea247680fa7ad1ae7dc3f9953f753d8cf955) --- source3/smbd/sec_ctx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 72e23306ec..830e759d09 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -222,6 +222,10 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) struct sec_ctx *prev_ctx_p; BOOL result = True; + if (non_root_mode()) { + return True; + } + become_root(); /* Call initgroups() to get user groups */ -- cgit From 56aa0a274d7bbe7b3a3b28a6043ec69cc97d85f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Sep 2001 04:11:23 +0000 Subject: got rid of bogus write list substitution error messages (This used to be commit 0deae6c407faa86ea871a219ad52fdd285166274) --- source3/smbd/service.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4765844460..beb2d76b44 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -259,27 +259,30 @@ static NTSTATUS share_sanity_checks(int snum, char* service, char *dev) ****************************************************************************/ static void set_read_only(connection_struct *conn) { + char **list; char *service = lp_servicename(conn->service); conn->read_only = lp_readonly(conn->service); - { - char **list; + if (!service) return; - lp_list_copy(&list, lp_readlist(conn->service)); - if(list && lp_list_substitute(list, "%S", service)) { - if (user_in_list(conn->user, list)) - conn->read_only = True; + lp_list_copy(&list, lp_readlist(conn->service)); + if (list) { + if (!lp_list_substitute(list, "%S", service)) { + DEBUG(0, ("ERROR: read list substitution failed\n")); } - else DEBUG(0, ("ERROR: read list substitution failed\n")); - if (list) lp_list_free(&list); - - lp_list_copy(&list, lp_writelist(conn->service)); - if(list && lp_list_substitute(list, "%S", service)) { - if (user_in_list(conn->user, list)) - conn->read_only = False; + if (user_in_list(conn->user, list)) + conn->read_only = True; + lp_list_free(&list); + } + + lp_list_copy(&list, lp_writelist(conn->service)); + if (list) { + if (!lp_list_substitute(list, "%S", service)) { + DEBUG(0, ("ERROR: write list substitution failed\n")); } - else DEBUG(0, ("ERROR: write list substitution failed\n")); - if (list) lp_list_free(&list); + if (user_in_list(conn->user, list)) + conn->read_only = False; + lp_list_free(&list); } } -- cgit From 6adafe50d4a9a75a6fe1f666232e0af1ac717513 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Sep 2001 05:26:11 +0000 Subject: Remove the ugly hacks to get around the Get_Pwnam() calls in pass_check.c by simply not doing Get_Pwnam() calls in pass_check.c We now make *one* sys_getpnam() call in cgi.c and we always call PAM no matter what it returns. We also no longer run the password cracker for these logins. The truly parinod will note the slight difference in call paths, in that we only call crypt for valid password structs (if not --with-pam). The truly parinoid don't run SWAT either, so I don't think this is an issue. Andrew Bartlett (This used to be commit 9020d884935243f28c19cedc88f076f0709e12cb) --- source3/smbd/auth_unix.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index ea32a65457..7c6c58cafa 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -71,13 +71,19 @@ in PLAIN TEXT NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { NTSTATUS nt_status; - + struct passwd *pass = NULL; + become_root(); - nt_status = (pass_check(user_info->unix_username.str, - user_info->plaintext_password.str, + + pass = Get_Pwnam(user_info->unix_username.str, False); + + nt_status = (pass_check(pass, + user_info->unix_username.str, + user_info->plaintext_password.str, user_info->plaintext_password.len, lp_update_encrypted() ? - update_smbpassword_file : NULL) + update_smbpassword_file : NULL, + True) ? NT_STATUS_OK : NT_STATUS_LOGON_FAILURE); unbecome_root(); -- cgit From 2bc9ef38466826ab43b747def4cf3344187ebe1f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Sep 2001 05:43:15 +0000 Subject: added a hook to reopen all tdb's after the server fork this prevents the fd seek pointer problem (This used to be commit f49518e497deeb46292456c3650769d50ec2a955) --- source3/smbd/server.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1dfff6cafa..27fd8e3015 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -309,6 +309,9 @@ max can be %d\n", done correctly in the process. */ reset_globals_after_fork(); + /* tdb needs special fork handling */ + tdb_reopen_all(); + return True; } /* The parent doesn't need this socket */ -- cgit From 01bb01b3ca0be89dacb73b5f7add2bb682735b5a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Sep 2001 06:46:35 +0000 Subject: removed anti-race code that could cause a classic ABBA deadlock I'd rather get the connection count wrong with a small probability than deadlock (This used to be commit d4e4e81328a63d6e3396306d5dae6cc45ddd35d7) --- source3/smbd/connection.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 399851302c..0f0697b1c7 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -114,8 +114,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO { struct connections_key key; struct connections_data crec; - TDB_DATA kbuf, dbuf, lockkey; - BOOL rec_locked = False; + TDB_DATA kbuf, dbuf; BOOL ret = True; if (!tdb) { @@ -137,22 +136,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO cs.name = lp_servicename(SNUM(conn)); cs.Clear = Clear; - lockkey.dptr = cs.name; - lockkey.dsize = strlen(cs.name)+1; - - /* - * Go through and count the connections with hash chain representing the service name - * locked. This is slow but removes race conditions. JRA. - */ - - if (tdb_chainlock(tdb, lockkey)) { - DEBUG(0,("claim_connection: tdb_chainlock failed %s\n", - tdb_errorstr(tdb) )); - return False; - } - - rec_locked = True; - if (tdb_traverse(tdb, count_fn, &cs) == -1) { DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", tdb_errorstr(tdb) )); @@ -205,8 +188,5 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO out: - if (rec_locked) - tdb_chainunlock(tdb, lockkey); - return ret; } -- cgit From 79a9902d39859e0b0dc9d375ffc7714faf00bbb1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Sep 2001 07:06:34 +0000 Subject: Removed unneeded variable, added comment on deadlock prevention. Jeremy. (This used to be commit 3f52632ac9c45c66613c3a2fd41f1ba73ca3fefc) --- source3/smbd/connection.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 0f0697b1c7..e1b2bc071a 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -115,7 +115,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO struct connections_key key; struct connections_data crec; TDB_DATA kbuf, dbuf; - BOOL ret = True; if (!tdb) { tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, @@ -136,18 +135,21 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO cs.name = lp_servicename(SNUM(conn)); cs.Clear = Clear; + /* + * This has a race condition, but locking the chain before hand is worse + * as it leads to deadlock. + */ + if (tdb_traverse(tdb, count_fn, &cs) == -1) { DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", tdb_errorstr(tdb) )); - ret = False; - goto out; + return False; } if (cs.curr_connections >= max_connections) { DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n", max_connections, name )); - ret = False; - goto out; + return False; } } @@ -183,10 +185,8 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { DEBUG(0,("claim_connection: tdb_store failed with error %s.\n", tdb_errorstr(tdb) )); - ret = False; + return False; } - out: - - return ret; + return True; } -- cgit From ebe02a7e8743e413113562150f40e7db3d2d378c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Sep 2001 09:37:33 +0000 Subject: printf() -> d_printf() (This used to be commit e8bd42edc05226d49ab0b6768f898d883fcf8d1a) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 27fd8e3015..4ee39a2406 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -645,7 +645,7 @@ static void usage(char *pname) break; case 'V': - printf("Version %s\n",VERSION); + d_printf("Version %s\n",VERSION); exit(0); break; default: -- cgit From 6794b58a8c5941ede29e07247bda911328cd7b20 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Sep 2001 09:44:12 +0000 Subject: Add the ability to display Samba's build options with smbd -b and as a level 4 DEBUG(). Also included are details like build date/time, location and compiler. This should get most of the options we set, except those that don't affect smbd, like WITH_PAM_SMBPASSWD or WITH_WINBINDD. This work due to Vance Lankhaar Some work needs to be done to make it only rebuild when needed (ie smbd being rebuilt) but its in pretty good shape already. Also fix up some printf() -> d_printf(). Andrew Bartlett (This used to be commit beff1d2beaf4337dba6bfc372c5e09a43cfd791a) --- source3/smbd/server.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4ee39a2406..1e89bbab7e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -560,23 +560,23 @@ usage on the program static void usage(char *pname) { - printf("Usage: %s [-DaoPh?V] [-d debuglevel] [-l log basename] [-p port]\n", pname); - printf(" [-O socket options] [-s services file]\n"); - printf("\t-D Become a daemon\n"); - printf("\t-a Append to log file (default)\n"); - printf("\t-o Overwrite log file, don't append\n"); - printf("\t-h Print usage\n"); - printf("\t-? Print usage\n"); - printf("\t-V Print version\n"); - printf("\t-d debuglevel Set the debuglevel\n"); - printf("\t-l log basename. Basename for log/debug files\n"); - printf("\t-p port Listen on the specified port\n"); - printf("\t-O socket options Socket options\n"); - printf("\t-s services file. Filename of services file\n"); - printf("\n"); + d_printf("Usage: %s [-DaoPh?Vb] [-d debuglevel] [-l log basename] [-p port]\n", pname); + d_printf(" [-O socket options] [-s services file]\n"); + d_printf("\t-D Become a daemon\n"); + d_printf("\t-a Append to log file (default)\n"); + d_printf("\t-o Overwrite log file, don't append\n"); + d_printf("\t-h Print usage\n"); + d_printf("\t-? Print usage\n"); + d_printf("\t-V Print version\n"); + d_printf("\t-b Print build options\n"); + d_printf("\t-d debuglevel Set the debuglevel\n"); + d_printf("\t-l log basename. Basename for log/debug files\n"); + d_printf("\t-p port Listen on the specified port\n"); + d_printf("\t-O socket options Socket options\n"); + d_printf("\t-s services file. Filename of services file\n"); + d_printf("\n"); } - /**************************************************************************** main program ****************************************************************************/ @@ -600,7 +600,7 @@ static void usage(char *pname) argc--; } - while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?Vaof:")) ) + while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?bVaof:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); @@ -648,6 +648,10 @@ static void usage(char *pname) d_printf("Version %s\n",VERSION); exit(0); break; + case 'b': + build_options(True); /* Display output to screen as well as debug */ + exit(0); + break; default: DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); usage(argv[0]); @@ -718,6 +722,9 @@ static void usage(char *pname) DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); + /* Output the build options to the debug log */ + build_options(False); + if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); exit(1); -- cgit From 31c44c4744be67159c7b98dc698233572febf083 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Sep 2001 10:45:33 +0000 Subject: Adding the appropirate files might help... (These are part of the build_options patch). Andrew Bartlett (This used to be commit 4e5c7724b4e4c132b7b43104d3063d2f7357bae2) --- source3/smbd/build_options.c | 714 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 714 insertions(+) create mode 100644 source3/smbd/build_options.c (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c new file mode 100644 index 0000000000..5486fae335 --- /dev/null +++ b/source3/smbd/build_options.c @@ -0,0 +1,714 @@ +/* + Unix SMB/Netbios implementation. + Version 2.2 + Build Options for Samba Suite + Copyright (C) Vance Lankhaar 2001 + Copyright (C) Andrew Bartlett 2001 + + 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 "build_env.h" + +/**************************************************************************** +helper function for build_options +****************************************************************************/ +static void output(BOOL screen, char *buffer) +{ + if (screen) { + d_printf(buffer); + } else { + DEBUG(4, (buffer)); + } +} +/**************************************************************************** +options set at build time for the samba suite +****************************************************************************/ +void build_options(BOOL screen) +{ + pstring outstring; + + if ((DEBUGLEVEL < 4) && (!screen)) { + return; + } + +#ifdef _BUILD_ENV_H + /* Output information about the build environment */ + snprintf(outstring,sizeof(outstring),"Build environment:\n"); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," Built by: %s@%s\n",BUILD_ENV_USER,BUILD_ENV_HOST); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," Built on: %s\n",BUILD_ENV_DATE); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," Built using: %s\n",BUILD_ENV_COMPILER); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," Build host: %s\n",BUILD_ENV_UNAME); + output(screen,outstring); + + snprintf(outstring,sizeof(outstring)," SRCDIR: %s\n",BUILD_ENV_SRCDIR); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," BUILDDIR: %s\n",BUILD_ENV_BUILDDIR); + output(screen,outstring); + +#endif + + /* Output various options (most correspond to --with options) */ + snprintf(outstring,sizeof(outstring),"\nBuild options:\n"); + output(screen,outstring); +#ifdef WITH_SMBWRAPPER + snprintf(outstring,sizeof(outstring)," WITH_SMBWRAPPER\n"); + output(screen,outstring); +#endif +#ifdef WITH_AFS + snprintf(outstring,sizeof(outstring)," WITH_AFS\n"); + output(screen,outstring); +#endif +#ifdef WITH_DFS + snprintf(outstring,sizeof(outstring)," WITH_DFS\n"); + output(screen,outstring); +#endif +#if defined(KRB4_AUTH) && defined(KRB4_DIR) + snprintf(outstring,sizeof(outstring)," KRB4_AUTH"); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," KRB4_DIR: %s\n",KRB4_DIR); + output(screen,outstring); +#endif +#if defined(KRB5_AUTH) && defined(KRB5_DIR) + snprintf(outstring,sizeof(outstring)," KRB5_AUTH"); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," KRB5_DIR: %s\n",KRB5_DIR); + output(screen,outstring); +#endif +#ifdef WITH_AUTOMOUNT + snprintf(outstring,sizeof(outstring)," WITH_AUTOMOUNT\n"); + output(screen,outstring); +#endif +#ifdef WITH_SMBMOUNT + snprintf(outstring,sizeof(outstring)," WITH_SMBMOUNT\n"); + output(screen,outstring); +#endif +#ifdef WITH_PAM + snprintf(outstring,sizeof(outstring)," WITH_PAM\n"); + output(screen,outstring); +#endif +#ifdef WITH_TDBSAM + snprintf(outstring,sizeof(outstring)," WITH_TDBSAM\n"); + output(screen,outstring); +#endif +#ifdef WITH_LDAP + snprintf(outstring,sizeof(outstring)," WITH_LDAP\n"); + output(screen,outstring); +#endif +#ifdef WITH_NISPLUS + snprintf(outstring,sizeof(outstring)," WITH_NISPLUS\n"); + output(screen,outstring); +#endif +#ifdef WITH_NISPLUS_HOME + snprintf(outstring,sizeof(outstring)," WITH_NISPLUS_HOME\n"); + output(screen,outstring); +#endif +#ifdef WITH_SSL + snprintf(outstring,sizeof(outstring)," WITH_SSL\n"); + output(screen,outstring); +#endif +#ifdef SSL_DIR + snprintf(outstring,sizeof(outstring)," SSL_DIR: %s\n",SSL_DIR); + output(screen,outstring); +#endif +#ifdef WITH_SYSLOG + snprintf(outstring,sizeof(outstring)," WITH_SYSLOG\n"); + output(screen,outstring); +#endif +#ifdef WITH_PROFILE + snprintf(outstring,sizeof(outstring)," WITH_PROFILE\n"); + output(screen,outstring); +#endif +#ifdef WITH_QUOTAS + snprintf(outstring,sizeof(outstring)," WITH_QUOTAS\n"); + output(screen,outstring); +#endif +#ifdef WITH_MSDFS + snprintf(outstring,sizeof(outstring)," WITH_MSDFS\n"); + output(screen,outstring); +#endif +#ifdef WITH_VFS + snprintf(outstring,sizeof(outstring)," WITH_VFS\n"); + output(screen,outstring); +#endif +#ifdef USE_SPINLOCKS + snprintf(outstring,sizeof(outstring)," USE_SPINLOCKS\n"); + output(screen,outstring); +#endif +#ifdef SPARC_SPINLOCKS + snprintf(outstring,sizeof(outstring)," SPARC_SPINLOCKS\n"); + output(screen,outstring); +#endif +#ifdef INTEL_SPINLOCKS + snprintf(outstring,sizeof(outstring)," INTEL_SPINLOCKS\n"); + output(screen,outstring); +#endif +#ifdef MIPS_SPINLOCKS + snprintf(outstring,sizeof(outstring)," MIPS_SPINLOCKS\n"); + output(screen,outstring); +#endif +#ifdef POWERPC_SPINLOCKS + snprintf(outstring,sizeof(outstring)," POWERPC_SPINLOCKS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UNIXWARE_ACLS + snprintf(outstring,sizeof(outstring)," HAVE_UNIXWARE_ACLS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SOLARIS_ACLS + snprintf(outstring,sizeof(outstring)," HAVE_SOLARIS_ACLS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_IRIX_ACLS + snprintf(outstring,sizeof(outstring)," HAVE_IRIX_ACLS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_AIX_ACLS + snprintf(outstring,sizeof(outstring)," HAVE_AIX_ACLS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_POSIX_ACLS + snprintf(outstring,sizeof(outstring)," HAVE_POSIX_ACLS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_TRU64_ACLS + snprintf(outstring,sizeof(outstring)," HAVE_TRU64_ACLS\n"); + output(screen,outstring); +#endif + +#ifdef HAVE_ACL_GET_PERM_NP + snprintf(outstring,sizeof(outstring)," HAVE_ACL_GET_PERM_NP\n"); + output(screen,outstring); +#endif +#ifdef HAVE_NO_ACLS + snprintf(outstring,sizeof(outstring)," HAVE_NO_ACLS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_LIBREADLINE + snprintf(outstring,sizeof(outstring)," HAVE_LIBREADLINE\n"); + output(screen,outstring); +#endif +#ifdef WITH_LIBICONV + snprintf(outstring,sizeof(outstring)," WITH_LIBICONV: %s\n",WITH_LIBICONV); + output(screen,outstring); +#endif + + + /* Output various paths to files and directories */ + snprintf(outstring,sizeof(outstring),"\nPaths:\n"); + output(screen,outstring); +#ifdef CONFIGFILE + snprintf(outstring,sizeof(outstring)," CONFIGFILE: %s\n",CONFIGFILE); + output(screen,outstring); +#endif +#ifdef PRIVATE_DIR + snprintf(outstring,sizeof(outstring)," PRIVATE_DIR: %s\n",PRIVATE_DIR); + output(screen,outstring); +#endif +#ifdef LMHOSTSFILE + snprintf(outstring,sizeof(outstring)," LMHOSTSFILE: %s\n",LMHOSTSFILE); + output(screen,outstring); +#endif +#ifdef SBINDIR + snprintf(outstring,sizeof(outstring)," SBINDIR: %s\n",SBINDIR); + output(screen,outstring); +#endif +#ifdef BINDIR + snprintf(outstring,sizeof(outstring)," BINDIR: %s\n",BINDIR); + output(screen,outstring); +#endif +#ifdef LOCKDIR + snprintf(outstring,sizeof(outstring)," LOCKDIR: %s\n",LOCKDIR); + output(screen,outstring); +#endif +#ifdef DRIVERFILE + snprintf(outstring,sizeof(outstring)," DRIVERFILE: %s\n",DRIVERFILE); + output(screen,outstring); +#endif +#ifdef LOGFILEBASE + snprintf(outstring,sizeof(outstring)," LOGFILEBASE: %s\n",LOGFILEBASE); + output(screen,outstring); +#endif +#ifdef FORMSFILE + snprintf(outstring,sizeof(outstring)," FORMSFILE: %s\n",FORMSFILE); + output(screen,outstring); +#endif +#ifdef NTDRIVERSDIR + snprintf(outstring,sizeof(outstring)," NTDRIVERSDIR: %s\n",NTDRIVERSDIR); + output(screen,outstring); +#endif + + /*Output various other options (most map to defines in the configure script*/ + snprintf(outstring,sizeof(outstring),"\nOther Build Options:\n"); + output(screen,outstring); +#ifdef HAVE_VOLATILE + snprintf(outstring,sizeof(outstring)," HAVE_VOLATILE\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SHADOW_H + snprintf(outstring,sizeof(outstring)," HAVE_SHADOW_H\n"); + output(screen,outstring); +#endif +#ifdef HAVE_CRYPT + snprintf(outstring,sizeof(outstring)," HAVE_CRYPT\n"); + output(screen,outstring); +#endif +#ifdef USE_BOTH_CRYPT_CALLS + snprintf(outstring,sizeof(outstring)," USE_BOTH_CRYPT_CALLS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_TRUNCATED_SALT + snprintf(outstring,sizeof(outstring)," HAVE_TRUNCATED_SALT\n"); + output(screen,outstring); +#endif +#ifdef HAVE_CUPS + snprintf(outstring,sizeof(outstring)," HAVE_CUPS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_CUPS_CUPS_H + snprintf(outstring,sizeof(outstring)," HAVE_CUPS_CUPS_H\n"); + output(screen,outstring); +#endif +#ifdef HAVE_CUPS_LANGUAGE_H + snprintf(outstring,sizeof(outstring)," HAVE_CUPS_LANGUAGE_H\n"); + output(screen,outstring); +#endif +#ifdef HAVE_LIBDL + snprintf(outstring,sizeof(outstring)," HAVE_LIBDL\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UNIXSOCKET + snprintf(outstring,sizeof(outstring)," HAVE_UNIXSOCKET\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SOCKLEN_T_TYPE + snprintf(outstring,sizeof(outstring)," HAVE_SOCKLEN_T_TYPE\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SIG_ATOMIC_T_TYPE + snprintf(outstring,sizeof(outstring)," HAVE_SIG_ATOMIC_T_TYPE\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SETRESUID + snprintf(outstring,sizeof(outstring)," HAVE_SETRESUID\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SETRESGID + snprintf(outstring,sizeof(outstring)," HAVE_SETRESGID\n"); + output(screen,outstring); +#endif +#ifdef HAVE_CONNECT + snprintf(outstring,sizeof(outstring)," HAVE_CONNECT\n"); + output(screen,outstring); +#endif +#ifdef HAVE_YP_GET_DEFAULT_DOMAIN + snprintf(outstring,sizeof(outstring)," HAVE_YP_GET_DEFAULT_DOMAIN\n"); + output(screen,outstring); +#endif +#ifdef HAVE_STAT64 + snprintf(outstring,sizeof(outstring)," HAVE_STAT64\n"); + output(screen,outstring); +#endif +#ifdef HAVE_LSTAT64 + snprintf(outstring,sizeof(outstring)," HAVE_LSTAT64\n"); + output(screen,outstring); +#endif +#ifdef HAVE_FSTAT64 + snprintf(outstring,sizeof(outstring)," HAVE_FSTAT64\n"); + output(screen,outstring); +#endif +#ifdef HAVE_STRCASECMP + snprintf(outstring,sizeof(outstring)," HAVE_STRCASECMP\n"); + output(screen,outstring); +#endif +#ifdef HAVE_MEMSET + snprintf(outstring,sizeof(outstring)," HAVE_MEMSET\n"); + output(screen,outstring); +#endif +#ifdef HAVE_LONGLONG + snprintf(outstring,sizeof(outstring)," HAVE_LONGLONG\n"); + output(screen,outstring); +#endif +#ifdef COMPILER_SUPPORTS_LL + snprintf(outstring,sizeof(outstring)," COMPILER_SUPPORTS_LL\n"); + output(screen,outstring); +#endif +#ifdef SIZEOF_OFF_T + snprintf(outstring,sizeof(outstring)," SIZEOF_OFF_T: %d\n",SIZEOF_OFF_T); + output(screen,outstring); +#endif +#ifdef HAVE_OFF64_T + snprintf(outstring,sizeof(outstring)," HAVE_OFF64_T\n"); + output(screen,outstring); +#endif +#ifdef SIZEOF_INO_T + snprintf(outstring,sizeof(outstring)," SIZEOF_INO_T: %d\n",SIZEOF_INO_T); + output(screen,outstring); +#endif +#ifdef HAVE_INO64_T + snprintf(outstring,sizeof(outstring)," HAVE_INO64_T\n"); + output(screen,outstring); +#endif +#ifdef HAVE_STRUCT_DIRENT64 + snprintf(outstring,sizeof(outstring)," HAVE_STRUCT_DIRENT64\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UNSIGNED_CHAR + snprintf(outstring,sizeof(outstring)," HAVE_UNSIGNED_CHAR\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SOCK_SIN_LEN + snprintf(outstring,sizeof(outstring)," HAVE_SOCK_SIN_LEN\n"); + output(screen,outstring); +#endif +#ifdef SEEKDIR_RETURNS_VOID + snprintf(outstring,sizeof(outstring)," SEEKDIR_RETURNS_VOID\n"); + output(screen,outstring); +#endif +#ifdef HAVE_FILE_MACRO + snprintf(outstring,sizeof(outstring)," HAVE_FILE_MACRO\n"); + output(screen,outstring); +#endif +#ifdef HAVE_FUNCTION_MACRO + snprintf(outstring,sizeof(outstring)," HAVE_FUNCTION_MACRO\n"); + output(screen,outstring); +#endif +#ifdef HAVE_GETTIMEOFDAY + snprintf(outstring,sizeof(outstring)," HAVE_GETTIMEOFDAY\n"); + output(screen,outstring); +#endif +#ifdef HAVE_C99_VSNPRINTF + snprintf(outstring,sizeof(outstring)," HAVE_C99_VSNPRINTF\n"); + output(screen,outstring); +#endif +#ifdef HAVE_BROKEN_READDIR + snprintf(outstring,sizeof(outstring)," HAVE_BROKEN_READDIR\n"); + output(screen,outstring); +#endif +#ifdef HAVE_NATIVE_ICONV + snprintf(outstring,sizeof(outstring)," HAVE_NATIVE_ICONV\n"); + output(screen,outstring); +#endif +#ifdef HAVE_KERNEL_OPLOCKS_LINUX + snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_OPLOCKS_LINUX\n"); + output(screen,outstring); +#endif +#ifdef HAVE_KERNEL_CHANGE_NOTIFY + snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_CHANGE_NOTIFY\n"); + output(screen,outstring); +#endif +#ifdef HAVE_KERNEL_SHARE_MODES + snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_SHARE_MODES\n"); + output(screen,outstring); +#endif +#ifdef HAVE_KERNEL_OPLOCKS_IRIX + snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_OPLOCKS_IRIX\n"); + output(screen,outstring); +#endif +#ifdef HAVE_IRIX_SPECIFIC_CAPABILITIES + snprintf(outstring,sizeof(outstring)," HAVE_IRIX_SPECIFIC_CAPABILITIES\n"); + output(screen,outstring); +#endif +#ifdef HAVE_INT16_FROM_RPC_RPC_H + snprintf(outstring,sizeof(outstring)," HAVE_INT16_FROM_RPC_RPC_H\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UINT16_FROM_RPC_RPC_H + snprintf(outstring,sizeof(outstring)," HAVE_UINT16_FROM_RPC_RPC_H\n"); + output(screen,outstring); +#endif +#ifdef HAVE_INT32_FROM_RPC_RPC_H + snprintf(outstring,sizeof(outstring)," HAVE_INT16_FROM_RPC_RPC_H\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UINT32_FROM_RPC_RPC_H + snprintf(outstring,sizeof(outstring)," HAVE_UINT32_FROM_RPC_RPC_H\n"); + output(screen,outstring); +#endif +#ifdef HAVE_RPC_AUTH_ERROR_CONFLICT + snprintf(outstring,sizeof(outstring)," HAVE_RPC_AUTH_ERROR_CONFLICT\n"); + output(screen,outstring); +#endif +#ifdef HAVE_FTRUNCATE_EXTEND + snprintf(outstring,sizeof(outstring)," HAVE_FTRUNCATE_EXTEND\n"); + output(screen,outstring); +#endif +#ifdef HAVE_WORKING_AF_LOCAL + snprintf(outstring,sizeof(outstring)," HAVE_WORKING_AF_LOCAL\n"); + output(screen,outstring); +#endif +#ifdef HAVE_BROKEN_GETGROUPS + snprintf(outstring,sizeof(outstring)," HAVE_BROKEN_GETGROUPS\n"); + output(screen,outstring); +#endif +#ifdef REPLACE_GETPASS + snprintf(outstring,sizeof(outstring)," REPLACE_GETPASS\n"); + output(screen,outstring); +#endif +#ifdef REPLACE_INET_NTOA + snprintf(outstring,sizeof(outstring)," REPLACE_INET_NTOA\n"); + output(screen,outstring); +#endif +#ifdef HAVE_SECURE_MKSTEMP + snprintf(outstring,sizeof(outstring)," HAVE_SECURE_MKSTEMP\n"); + output(screen,outstring); +#endif +#ifdef SYSCONF_SC_NGROUPS_MAX + snprintf(outstring,sizeof(outstring)," SYSCONF_SC_NGROUPS_MAX\n"); + output(screen,outstring); +#endif +#ifdef HAVE_IFACE_AIX + snprintf(outstring,sizeof(outstring)," HAVE_IFACE_AIX\n"); + output(screen,outstring); +#endif +#ifdef HAVE_IFACE_IFCONF + snprintf(outstring,sizeof(outstring)," HAVE_IFACE_IFCONF\n"); + output(screen,outstring); +#endif +#ifdef HAVE_IFACE_IFREQ + snprintf(outstring,sizeof(outstring)," HAVE_IFACE_IFREQ\n"); + output(screen,outstring); +#endif +#ifdef USE_SETRESUID + snprintf(outstring,sizeof(outstring)," USE_SETRESUID\n"); + output(screen,outstring); +#endif +#ifdef USE_SETRESGID + snprintf(outstring,sizeof(outstring)," USE_SETREUID\n"); + output(screen,outstring); +#endif +#ifdef USE_SETEUID + snprintf(outstring,sizeof(outstring)," USE_SETEUID\n"); + output(screen,outstring); +#endif +#ifdef USE_SETUIDX + snprintf(outstring,sizeof(outstring)," USE_SETUIDX\n"); + output(screen,outstring); +#endif +#ifdef HAVE_MMAP + snprintf(outstring,sizeof(outstring)," HAVE_MMAP\n"); + output(screen,outstring); +#endif +#ifdef MMAP_BLACKLIST + snprintf(outstring,sizeof(outstring)," MMAP_BLACKLIST\n"); + output(screen,outstring); +#endif +#ifdef FTRUNCATE_NEEDS_ROOT + snprintf(outstring,sizeof(outstring)," FTRUNCATE_NEEDS_ROOT\n"); + output(screen,outstring); +#endif +#ifdef HAVE_FCNTL_LOCK + snprintf(outstring,sizeof(outstring)," HAVE_FCNTL_LOCK\n"); + output(screen,outstring); +#endif +#ifdef HAVE_BROKEN_FCNTL64_LOCKS + snprintf(outstring,sizeof(outstring)," HAVE_BROKEN_FCNTL64_LOCKS\n"); + output(screen,outstring); +#endif +#ifdef HAVE_STRUCT_FLOCK64 + snprintf(outstring,sizeof(outstring)," HAVE_STRUCT_FLOCK64\n"); + output(screen,outstring); +#endif +#ifdef BROKEN_NISPLUS_INCLUDE_FILES + snprintf(outstring,sizeof(outstring)," BROKEN_NISPLUS_INCLUDE_FILES\n"); + output(screen,outstring); +#endif +#ifdef HAVE_LIBPAM + snprintf(outstring,sizeof(outstring)," HAVE_LIBPAM\n"); + output(screen,outstring); +#endif +#ifdef STAT_STATVFS64 + snprintf(outstring,sizeof(outstring)," STAT_STATVFS64\n"); + output(screen,outstring); +#endif +#ifdef STAT_STATVFS + snprintf(outstring,sizeof(outstring)," STAT_STATVFS\n"); + output(screen,outstring); +#endif +#ifdef STAT_STATFS3_OSF1 + snprintf(outstring,sizeof(outstring)," STAT_STATFS3_OSF1\n"); + output(screen,outstring); +#endif +#ifdef STAT_STATFS2_BSIZE + snprintf(outstring,sizeof(outstring)," STAT_STATFS2_BSIZE\n"); + output(screen,outstring); +#endif +#ifdef STAT_STATFS4 + snprintf(outstring,sizeof(outstring)," STAT_STATFS4\n"); + output(screen,outstring); +#endif +#ifdef STAT_STATFS2_FSIZE + snprintf(outstring,sizeof(outstring)," STAT_STATFS2_FSIZE\n"); + output(screen,outstring); +#endif +#ifdef STAT_STATFS2_FS_DATA + snprintf(outstring,sizeof(outstring)," STAT_STATFS2_FS_DATA\n"); + output(screen,outstring); +#endif +#ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT + snprintf(outstring,sizeof(outstring)," HAVE_EXPLICIT_LARGEFILE_SUPPORT\n"); + output(screen,outstring); +#endif + +#ifdef WITH_UTMP + /* Output UTMP Stuff */ + snprintf(outstring,sizeof(outstring),"\nUTMP Related:\n"); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," WITH_UTMP\n"); + output(screen,outstring); + +#ifdef HAVE_UTIMBUF + snprintf(outstring,sizeof(outstring)," HAVE_UTIMBUF\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_NAME + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_NAME\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_USER + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_USER\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_ID + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_ID\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_HOST + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_HOST\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_TIME + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_TIME\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_TV + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_TV\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_TYPE + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_TYPE\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_PID + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_PID\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_EXIT + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_EXIT\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UT_UT_ADDR + snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_ADDR\n"); + output(screen,outstring); +#endif +#ifdef PUTUTLINE_RETURNS_UTMP + snprintf(outstring,sizeof(outstring)," PUTUTLINE_RETURNS_UTMP\n"); + output(screen,outstring); +#endif +#ifdef HAVE_UX_UT_SYSLEN + snprintf(outstring,sizeof(outstring)," HAVE_UX_UT_SYSLEN\n"); + output(screen,outstring); +#endif +#endif + + /* Output Build OS */ + snprintf(outstring,sizeof(outstring),"\nBuilt for host os:\n"); + output(screen,outstring); +#ifdef LINUX + snprintf(outstring,sizeof(outstring)," LINUX\n"); + output(screen,outstring); +#endif +#ifdef SUNOS5 + snprintf(outstring,sizeof(outstring)," SUNOS5\n"); + output(screen,outstring); +#endif +#ifdef SUNOS4 + snprintf(outstring,sizeof(outstring)," SUNOS4\n"); + output(screen,outstring); +#endif + /* BSD Isn't Defined in the configure script, but there is something about it in include/config.h.in (and I guess acconfig.h) */ +#ifdef BSD + snprintf(outstring,sizeof(outstring)," BSD\n"); + output(screen,outstring); +#endif +#ifdef IRIX + snprintf(outstring,sizeof(outstring)," IRIX\n"); + output(screen,outstring); +#endif +#ifdef IRIX6 + snprintf(outstring,sizeof(outstring)," IRIX6\n"); + output(screen,outstring); +#endif +#ifdef AIX + snprintf(outstring,sizeof(outstring)," AIX\n"); + output(screen,outstring); +#endif +#ifdef HPUX + snprintf(outstring,sizeof(outstring)," HPUX\n"); + output(screen,outstring); +#endif +#ifdef QNX + snprintf(outstring,sizeof(outstring)," QNX\n"); + output(screen,outstring); +#endif +#ifdef OSF1 + snprintf(outstring,sizeof(outstring)," OSF1\n"); + output(screen,outstring); +#endif +#ifdef SCO + snprintf(outstring,sizeof(outstring)," SCO\n"); + output(screen,outstring); +#endif +#ifdef UNIXWARE + snprintf(outstring,sizeof(outstring)," UNIXWARE\n"); + output(screen,outstring); +#endif +#ifdef NEXT2 + snprintf(outstring,sizeof(outstring)," NEXT2\n"); + output(screen,outstring); +#endif +#ifdef RELIANTUNIX + snprintf(outstring,sizeof(outstring)," RELIANTUNIX\n"); + output(screen,outstring); +#endif + + /* Output the sizes of the various types */ + snprintf(outstring,sizeof(outstring),"\nType sizes:\n"); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(char): %d\n",sizeof(char)); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(int): %d\n",sizeof(int)); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(long): %d\n",sizeof(long)); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(uint8): %d\n",sizeof(uint8)); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(uint16): %d\n",sizeof(uint16)); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(uint32): %d\n",sizeof(uint32)); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(short): %d\n",sizeof(short)); + output(screen,outstring); + snprintf(outstring,sizeof(outstring)," sizeof(void*): %d\n",sizeof(void*)); + output(screen,outstring); +} + + + -- cgit From 158a5b8399d8c0c5877f58719cf16b4f1e59eb55 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Sep 2001 23:53:51 +0000 Subject: - Fix up to use sampass->username insted of user_info->smb_username - Fix initial lookup to use the mapped username. (This used to be commit 162b88e2313dbcf0b95300b8f18a3e9b6b6b29bd) --- source3/smbd/auth_smbpasswd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index fb77a7a5c6..2427b2d16e 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -118,7 +118,7 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use /* Quit if the account was disabled. */ if(acct_ctrl & ACB_DISABLED) { - DEBUG(1,("Account for user '%s' was disabled.\n", user_info->smb_username.str)); + DEBUG(1,("Account for user '%s' was disabled.\n", sampass->username)); return(NT_STATUS_ACCOUNT_DISABLED); } @@ -165,12 +165,12 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use { if (lp_null_passwords()) { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user_info->smb_username.str)); + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", sampass->username)); return(NT_STATUS_OK); } else { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user_info->smb_username.str)); + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username)); return(NT_STATUS_LOGON_FAILURE); } } @@ -178,7 +178,7 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use if (!user_info || !sampass) return(NT_STATUS_LOGON_FAILURE); - DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",user_info->smb_username.str)); + DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",sampass->username)); nt_pw = pdb_get_nt_passwd(sampass); @@ -191,7 +191,7 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, user_info->nt_resp.len, nt_pw, - user_info->chal, user_info->smb_username.str, + user_info->chal, sampass->username, user_info->requested_domain.str, (char *)server_info->session_key)) { @@ -252,12 +252,12 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ /* get the account information */ become_root(); - ret = pdb_getsampwnam(sampass, user_info->smb_username.str); + ret = pdb_getsampwnam(sampass, user_info->unix_username.str); unbecome_root(); if (ret == False) { - DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->smb_username.str)); + DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->unix_username.str)); pdb_free_sam(sampass); return NT_STATUS_NO_SUCH_USER; } -- cgit From 79009d6afa421b39a61050e1c970ce0b9d0474d6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 20 Sep 2001 00:19:55 +0000 Subject: Revert this one: The NTLMv2 checks need the original username as found on the wire. (This used to be commit 7c9ae76b3ff4f1ba88ddad570648f32f99e38944) --- source3/smbd/auth_smbpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 2427b2d16e..cb8d711770 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -191,7 +191,7 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, user_info->nt_resp.len, nt_pw, - user_info->chal, sampass->username, + user_info->chal, user_info->smb_username.str, user_info->requested_domain.str, (char *)server_info->session_key)) { -- cgit From 395454db5d7e911ea418b88250778749463f7247 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 20 Sep 2001 03:31:57 +0000 Subject: Fix for MiXed and UPPER case usernames with plaintext PAM passwords. (This used to be commit ba1b411f556bfac8b953c44c81257c7d8fb9817d) --- source3/smbd/auth_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 7c6c58cafa..4740f7fb0d 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -78,7 +78,7 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve pass = Get_Pwnam(user_info->unix_username.str, False); nt_status = (pass_check(pass, - user_info->unix_username.str, + pass ? pass->pw_name : user_info->unix_username.str, user_info->plaintext_password.str, user_info->plaintext_password.len, lp_update_encrypted() ? -- cgit From 8bb1479500d4c6085ef94e8ae032e1728def065f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 20 Sep 2001 07:09:28 +0000 Subject: Rearrange the ordering of the checks in make_connection(). The new order has some sainity, avoiding things like 'root preexec' when the connection would otherwise already be denied (max connections). This does change behaviour, but I think its for the best. Andrew Bartlett (This used to be commit 99e8a263ada41de2662a0290fda3dd9df3ac0cd4) --- source3/smbd/service.c | 93 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index beb2d76b44..7119aa258e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -331,10 +331,12 @@ connection_struct *make_connection(char *service,char *password, connection_struct *conn; fstring user; + ZERO_STRUCT(user); strlower(service); snum = find_service(service); + if (snum < 0) { if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { DEBUG(3,("refusing IPC connection\n")); @@ -384,6 +386,8 @@ connection_struct *make_connection(char *service,char *password, *status = NT_STATUS_WRONG_PASSWORD; return NULL; } + + add_session_user(user); conn = conn_new(); if (!conn) { @@ -423,7 +427,7 @@ connection_struct *make_connection(char *service,char *password, conn->nt_user_token = NULL; set_read_only(conn); - + set_admin_user(conn); /* @@ -555,6 +559,16 @@ connection_struct *make_connection(char *service,char *password, return NULL; } + if (!become_user(conn, conn->vuid)) { + /* No point continuing if they fail the basic checks */ + DEBUG(0,("Can't become connected user!\n")); + conn_free(conn); + *status = NT_STATUS_LOGON_FAILURE; + return NULL; + } + +/* ROOT Activities: */ + become_root(); /* check number of connections */ if (!claim_connection(conn, lp_servicename(SNUM(conn)), @@ -563,9 +577,12 @@ connection_struct *make_connection(char *service,char *password, DEBUG(1,("too many connections - rejected\n")); *status = NT_STATUS_INSUFFICIENT_RESOURCES; conn_free(conn); + unbecome_root(); + unbecome_user(); return NULL; } - + + /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { int ret; @@ -575,26 +592,40 @@ connection_struct *make_connection(char *service,char *password, DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { - DEBUG(1,("preexec gave %d - failing connection\n", ret)); + DEBUG(1,("root preexec gave %d - failing connection\n", ret)); yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); *status = NT_STATUS_UNSUCCESSFUL; + unbecome_root(); + unbecome_user(); return NULL; } } - - if (!become_user(conn, conn->vuid)) { - DEBUG(0,("Can't become connected user!\n")); - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); - conn_free(conn); - *status = NT_STATUS_WRONG_PASSWORD; - return NULL; + unbecome_root(); + +/* USER Activites: */ + /* Remember that a different vuid can connect later without these checks... */ + + /* Preexecs are done here as they might make the dir we are to ChDir to below */ + /* execute any "preexec = " line */ + if (*lp_preexec(SNUM(conn))) { + int ret; + pstring cmd; + pstrcpy(cmd,lp_preexec(SNUM(conn))); + standard_sub_conn(conn,cmd); + ret = smbrun(cmd,NULL); + if (ret != 0 && lp_preexec_close(SNUM(conn))) { + DEBUG(1,("preexec gave %d - failing connection\n", ret)); + unbecome_user(); + yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); + conn_free(conn); + *status = NT_STATUS_UNSUCCESSFUL; + return NULL; + } } - + if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", remote_machine, conn->client_address, @@ -621,40 +652,20 @@ connection_struct *make_connection(char *service,char *password, } #endif - add_session_user(user); - - /* execute any "preexec = " line */ - if (*lp_preexec(SNUM(conn))) { - int ret; - pstring cmd; - pstrcpy(cmd,lp_preexec(SNUM(conn))); - standard_sub_conn(conn,cmd); - ret = smbrun(cmd,NULL); - if (ret != 0 && lp_preexec_close(SNUM(conn))) { - DEBUG(1,("preexec gave %d - failing connection\n", ret)); - yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; - return NULL; - } - } - /* * Print out the 'connected as' stuff here as we need - * to know the effective uid and gid we will be using. + * to know the effective uid and gid we will be using + * (at least initially). */ if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { dbgtext( "%s (%s) ", remote_machine, conn->client_address ); dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); - dbgtext( "as user %s ", user ); + dbgtext( "initially as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)sys_getpid() ); } - /* we've finished with the sensitive stuff */ - unbecome_user(); - /* Add veto/hide lists */ if (!IS_IPC(conn) && !IS_PRINT(conn)) { set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn))); @@ -665,9 +676,17 @@ connection_struct *make_connection(char *service,char *password, /* Invoke VFS make connection hook */ if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn, service, user) < 0) + if (conn->vfs_ops.connect(conn, service, user) < 0) { + DEBUG(0,("make_connection: VFS make connection failed!\n")); + *status = NT_STATUS_UNSUCCESSFUL; + unbecome_user(); + conn_free(conn); return NULL; + } } + + /* we've finished with the sensitive stuff */ + unbecome_user(); return(conn); } -- cgit From 994a4497032084cb744a644382e68cde464d19be Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 20 Sep 2001 10:26:50 +0000 Subject: We are not meant to touch the username, so use the pass->pw_name output rather than Get_Pwnam(user, True). (This used to be commit bf81f0021328da97afe58cc17317b15ec1b3cc96) --- source3/smbd/auth_rhosts.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index 2492a2a68b..e319d8d5f8 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -29,7 +29,7 @@ extern int DEBUGLEVEL; allows this user from this machine. ****************************************************************************/ -static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) +static BOOL check_user_equiv(const char *user, const char *remote, const char *equiv_file) { int plus_allowed = 1; char *file_host; @@ -134,11 +134,11 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) /**************************************************************************** check for a possible hosts equiv or rhosts entry for the user ****************************************************************************/ -static BOOL check_hosts_equiv(char *user) +static BOOL check_hosts_equiv(char *user) /* should be const... */ { char *fname = NULL; pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user,True); + struct passwd *pass = Get_Pwnam(user,False); if (!pass) return(False); @@ -147,16 +147,16 @@ static BOOL check_hosts_equiv(char *user) /* note: don't allow hosts.equiv on root */ if (fname && *fname && (pass->pw_uid != 0)) { - if (check_user_equiv(user,client_name(),fname)) + if (check_user_equiv(pass->pw_name,client_name(),fname)) return(True); } if (lp_use_rhosts()) { - char *home = get_user_home_dir(user); + char *home = pass->pw_dir; if (home) { slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(user,client_name(),rhostsfile)) + if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) return(True); } } -- cgit From fa6713bf8b121a45e59235786eec3cee29e92e67 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 20 Sep 2001 13:15:35 +0000 Subject: Move pass_check.c over to NTSTATUS, allowing full NTSTATUS from PAM to wire! Add the ability for swat to run in non-root-mode (ie non-root from inetd). - we still need some of the am_root() calls fixed however. (This used to be commit 2c2317c56ee13abdbdbc866363c3b52dab826e3c) --- source3/smbd/auth_unix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 4740f7fb0d..5582682d98 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -77,14 +77,14 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve pass = Get_Pwnam(user_info->unix_username.str, False); - nt_status = (pass_check(pass, + nt_status = pass_check(pass, pass ? pass->pw_name : user_info->unix_username.str, user_info->plaintext_password.str, user_info->plaintext_password.len, lp_update_encrypted() ? update_smbpassword_file : NULL, - True) - ? NT_STATUS_OK : NT_STATUS_LOGON_FAILURE); + True); + unbecome_root(); return nt_status; -- cgit From b49a1f01b06724abb66e212f3aa641a1578d3534 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 21 Sep 2001 14:27:43 +0000 Subject: fixed the error code handling in can_delete() by converting it to NTSTATUS. This gets the right error codes in SMBunlink (This used to be commit c82f7828c05c747a5782d10c68cc2df80d4071bd) --- source3/smbd/reply.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8527ebbe34..e3c7c9b856 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1661,23 +1661,26 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /******************************************************************* check if a user is allowed to delete a file ********************************************************************/ -static BOOL can_delete(char *fname,connection_struct *conn, int dirtype) +static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) { - SMB_STRUCT_STAT sbuf; - int fmode; + SMB_STRUCT_STAT sbuf; + int fmode; - if (!CAN_WRITE(conn)) return(False); + if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False); - fmode = dos_mode(conn,fname,&sbuf); - if (fmode & aDIR) return(False); - if (!lp_delete_readonly(SNUM(conn))) { - if (fmode & aRONLY) return(False); - } - if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) - return(False); - if (!check_file_sharing(conn,fname,False)) return(False); - return(True); + if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + fmode = dos_mode(conn,fname,&sbuf); + if (fmode & aDIR) return NT_STATUS_FILE_IS_A_DIRECTORY; + if (!lp_delete_readonly(SNUM(conn))) { + if (fmode & aRONLY) return NT_STATUS_CANNOT_DELETE; + } + if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) + return NT_STATUS_CANNOT_DELETE; + + if (!check_file_sharing(conn,fname,False)) return NT_STATUS_SHARING_VIOLATION; + + return NT_STATUS_OK; } /**************************************************************************** @@ -1729,9 +1732,9 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (!can_delete(directory,conn,dirtype)) { - return NT_STATUS_SHARING_VIOLATION; - } + error = can_delete(directory,conn,dirtype); + if (!NT_STATUS_IS_OK(error)) return error; + if (vfs_unlink(conn,directory) == 0) { count++; } @@ -1761,9 +1764,9 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if(!mask_match(fname, mask, case_sensitive)) continue; - error = NT_STATUS_ACCESS_DENIED; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - if (!can_delete(fname,conn,dirtype)) continue; + error = can_delete(fname,conn,dirtype); + if (!NT_STATUS_IS_OK(error)) continue; if (vfs_unlink(conn,fname) == 0) count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } -- cgit From d76dfbb879dc49cb03742f6ed184eb5ef5b75002 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Sep 2001 22:06:03 +0000 Subject: Attempt to make quotas work with RH7.1, and with other Linuxen... This is *HARD*, dammit ! Jeremy. (This used to be commit 59a4684201fb72989698db5ac8169bd8880bd9a7) --- source3/smbd/quotas.c | 193 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 68 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 3ef04b0692..cf21fd7043 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -45,12 +45,72 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B #include #include -#include + +/* + * This shouldn't be neccessary - it should be /usr/include/sys/quota.h + * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk + * rather than the struct dqblk defined in /usr/include/sys/quota.h. + * This means we must include linux/quota.h to have a hope of working on + * RH7.1 systems. And it also means this breaks if the kernel is upgraded + * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until + * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA. + */ + +#include #include #include -_syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr); + +#define LINUX_QUOTAS_2 + +typedef struct _LINUX_SMB_DISK_QUOTA { + SMB_BIG_UINT bsize; + SMB_BIG_UINT hardlimit; /* In bsize units. */ + SMB_BIG_UINT softlimit; /* In bsize units. */ + SMB_BIG_UINT curblocks; /* In bsize units. */ + SMB_BIG_UINT ihardlimit; /* inode hard limit. */ + SMB_BIG_UINT isoftlimit; /* inode soft limit. */ + SMB_BIG_UINT curinodes; /* Current used inodes. */ +} LINUX_SMB_DISK_QUOTA; + +/**************************************************************************** + Abstract out the old and new Linux quota get calls. +****************************************************************************/ + +static int get_smb_linux_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) +{ + int ret; +#ifdef LINUX_QUOTAS_1 + struct dqblk D; + ZERO_STRUCT(D); + dp->bsize = (SMB_BIG_UINT)1024; +#else /* LINUX_QUOTAS_2 */ + struct mem_dqblk D; + ZERO_STRUCT(D); +#ifndef QUOTABLOCK_SIZE +#define QUOTABLOCK_SIZE 1024 +#endif + dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; +#endif + + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D))) + return -1; + + dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit; + dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit; + dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes; + +#ifdef LINUX_QUOTAS_1 + dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks; +#else /* LINUX_QUOTAS_2 */ + dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize; +#endif + + return 0; +} /**************************************************************************** try to get the disk space from disk quotas (LINUX version) @@ -58,81 +118,78 @@ try to get the disk space from disk quotas (LINUX version) BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - int r; - struct dqblk D; - SMB_STRUCT_STAT S; - FILE *fp; - struct mntent *mnt; - SMB_DEV_T devno; - int found; - uid_t euser_id; + int r; + SMB_STRUCT_STAT S; + FILE *fp; + LINUX_SMB_DISK_QUOTA D; + struct mntent *mnt; + SMB_DEV_T devno; + int found; + uid_t euser_id; - euser_id = geteuid(); + euser_id = geteuid(); - /* find the block device file */ + /* find the block device file */ - if ( sys_stat(path, &S) == -1 ) { - return(False) ; - } + if ( sys_stat(path, &S) == -1 ) + return(False) ; - devno = S.st_dev ; + devno = S.st_dev ; - fp = setmntent(MOUNTED,"r"); - found = False ; + fp = setmntent(MOUNTED,"r"); + found = False ; - while ((mnt = getmntent(fp))) { - if ( sys_stat(mnt->mnt_dir,&S) == -1 ) - continue ; - if (S.st_dev == devno) { - found = True ; - break ; - } - } - endmntent(fp) ; + while ((mnt = getmntent(fp))) { + if ( sys_stat(mnt->mnt_dir,&S) == -1 ) + continue ; + + if (S.st_dev == devno) { + found = True ; + break; + } + } + + endmntent(fp) ; - if (!found) { - return(False); - } + if (!found) + return(False); - save_re_uid(); - set_effective_uid(0); - r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D); - restore_re_uid(); + save_re_uid(); + set_effective_uid(0); + r=get_smb_linux_quota(mnt->mnt_fsname, euser_id, &D); + restore_re_uid(); - /* Use softlimit to determine disk space, except when it has been exceeded */ - *bsize = 1024; - if (r) - { - if (errno == EDQUOT) - { - *dfree =0; - *dsize =D.dqb_curblocks; - return (True); - } - else return(False); - } - /* Use softlimit to determine disk space, except when it has been exceeded */ - if ( - (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) || - (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) || - (D.dqb_isoftlimit && D.dqb_curinodes>=D.dqb_isoftlimit) || - (D.dqb_ihardlimit && D.dqb_curinodes>=D.dqb_ihardlimit) - ) - { - *dfree = 0; - *dsize = D.dqb_curblocks; - } - else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0) - { - return(False); - } - else { - if (D.dqb_bsoftlimit == 0) - D.dqb_bsoftlimit = D.dqb_bhardlimit; - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - *dsize = D.dqb_bsoftlimit; - } - return (True); + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = D.bsize; + if (r == -1) { + if (errno == EDQUOT) { + *dfree =0; + *dsize =D.curblocks; + return (True); + } else { + return(False); + } + } + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.softlimit && D.curblocks >= D.softlimit) || + (D.hardlimit && D.curblocks >= D.hardlimit) || + (D.isoftlimit && D.curinodes >= D.isoftlimit) || + (D.ihardlimit && D.curinodes>=D.ihardlimit) + ) { + *dfree = 0; + *dsize = D.curblocks; + } else if (D.softlimit==0 && D.hardlimit==0) { + return(False); + } else { + if (D.softlimit == 0) + D.softlimit = D.hardlimit; + *dfree = D.softlimit - D.curblocks; + *dsize = D.softlimit; + } + + return (True); } #elif defined(CRAY) -- cgit From 0492effcf36bc1229d0d2e9250b6c6c36af0b117 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Sep 2001 06:45:24 +0000 Subject: Ignore unmappable (NT Authority, BUILTIN etc.) SIDs in an ACL set. Jeremy. (This used to be commit bc7963bd643422cce081b6284e3bdd49ae3a02ab) --- source3/smbd/posix_acls.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 18a635336c..64dd51f193 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -714,6 +714,17 @@ static BOOL create_canon_ace_lists(files_struct *fsp, enum SID_NAME_USE sid_type; SEC_ACE *psa = &dacl->ace[i]; + /* + * Ignore non-mappable SIDs (NT Authority, BUILTIN etc). + */ + + if (non_mappable_sid(&psa->sid)) { + fstring str; + DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n", + sid_to_string(str, &psa->sid) )); + continue; + } + /* * Create a cannon_ace entry representing this NT DACL ACE. */ -- cgit From 4eb7ef6b612a98e1d71a2a0dfde7d695223a4360 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 23 Sep 2001 05:16:03 +0000 Subject: Fix up NT_STATUS return for session setups, Win2k objects to anything other than NT_STATUS_LOGON_FAILURE. This also brings us (almost) back in line with their implementation. Kill off SMBENCRYPT() macro Kill off 'nt smb support' paramater - tridge okayed this one. Andrew Bartlett (This used to be commit 67947bf6e31ee9758f8a2186f83031ba21b716f2) --- source3/smbd/negprot.c | 10 ++++------ source3/smbd/reply.c | 6 +++--- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 9ebb0b7350..b065cab53e 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -66,7 +66,7 @@ static int reply_lanman1(char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; - BOOL doencrypt = SMBENCRYPT(); + BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); if (lp_security()>=SEC_USER) secword |= 1; @@ -103,7 +103,7 @@ static int reply_lanman2(char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; - BOOL doencrypt = SMBENCRYPT(); + BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); struct cli_state *cli = NULL; char cryptkey[8]; @@ -162,7 +162,7 @@ static int reply_nt1(char *outbuf) CAP_LEVEL_II_OPLOCKS|CAP_STATUS32; int secword=0; - BOOL doencrypt = SMBENCRYPT(); + BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); struct cli_state *cli = NULL; char cryptkey[8]; @@ -193,9 +193,7 @@ static int reply_nt1(char *outbuf) } } - if (lp_nt_smb_support()) { - capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; - } + capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) { capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e3c7c9b856..64662a54e2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -496,7 +496,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int fstring native_lanman; BOOL guest=False; static BOOL done_sesssetup = False; - BOOL doencrypt = SMBENCRYPT(); + BOOL doencrypt = lp_encrypted_passwords(); START_PROFILE(SMBsesssetupX); *smb_apasswd = 0; @@ -745,8 +745,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int guest = True; } else { - return ERROR_NT(nt_status); - } + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } } if (!strequal(user,lp_guestaccount(-1)) && -- cgit From 5993238b0ec5baa546d0214f1a26d174563fd43e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 23 Sep 2001 22:51:27 +0000 Subject: Zero out these pstrings before we start: makes for much easier debugging. (This used to be commit d417b6b5cbdbb244cc683387d73a9200eef53427) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 64662a54e2..ac337f1712 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -499,8 +499,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int BOOL doencrypt = lp_encrypted_passwords(); START_PROFILE(SMBsesssetupX); - *smb_apasswd = 0; - *smb_ntpasswd = 0; + ZERO_STRUCT(smb_apasswd); + ZERO_STRUCT(smb_ntpasswd); smb_bufsize = SVAL(inbuf,smb_vwv2); -- cgit From 7cb54b29dc6cb3a5a021a10f34fae6ac4f43a284 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 23 Sep 2001 23:07:53 +0000 Subject: Lets call an NTSTATUS an nt_status, not an ecode. (This used to be commit b6048e28ab996ba5581cfa3b50401c0f775befdd) --- source3/smbd/reply.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ac337f1712..572ed90b32 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -171,7 +171,7 @@ int reply_tcon(connection_struct *conn, int outsize = 0; uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; - NTSTATUS ecode; + NTSTATUS nt_status; char *p; START_PROFILE(SMBtcon); @@ -188,11 +188,11 @@ int reply_tcon(connection_struct *conn, pstrcpy(service, p+1); } - conn = make_connection(service,password,pwlen,dev,vuid,&ecode); + conn = make_connection(service,password,pwlen,dev,vuid,&nt_status); if (!conn) { END_PROFILE(SMBtcon); - return ERROR_NT(ecode); + return ERROR_NT(nt_status); } outsize = set_message(outbuf,2,0,True); @@ -216,7 +216,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt fstring service; pstring password; pstring devicename; - NTSTATUS ecode; + NTSTATUS nt_status; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); pstring path; @@ -266,11 +266,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt DEBUG(4,("Got device type %s\n",devicename)); - conn = make_connection(service,password,passlen,devicename,vuid,&ecode); + conn = make_connection(service,password,passlen,devicename,vuid,&nt_status); if (!conn) { END_PROFILE(SMBtconX); - return ERROR_NT(ecode); + return ERROR_NT(nt_status); } if (Protocol < PROTOCOL_NT1) { -- cgit From abaa4ab96a192047a7f8ff6fa579f723a7b4912e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Sep 2001 23:50:28 +0000 Subject: Change log message to 2 from zero when failing to create directory. Stops spurious profile creation messages. Jeremy. (This used to be commit fa74d07207fa9024b6ebdb10686b032ef6673d18) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7ac5a18609..6e6d5e1e83 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1070,7 +1070,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, } if(vfs_mkdir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { - DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); return NULL; -- cgit From be6023b2fb65e3aa0742b2731c0c2827f9983dc8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Sep 2001 00:05:26 +0000 Subject: Log sys_acl_set_XX at level 2 not zero. Jeremy. (This used to be commit 4a54a633c59a18b387427e89266e294bdddf8574) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 64dd51f193..d42b11cb83 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1719,14 +1719,14 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if(default_ace || fsp->is_directory || fsp->fd == -1) { if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { - DEBUG(0,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", + DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", fsp->fsp_name, strerror(errno) )); goto done; } } else { if (sys_acl_set_fd(fsp->fd, the_acl) == -1) { - DEBUG(0,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", + DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); goto done; } -- cgit From 827e1897783161a2a5ba797c0ff8727bd33a6f54 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 25 Sep 2001 06:38:07 +0000 Subject: fixed a typo (This used to be commit 11a2808e10bb7885da04c19c261d3876c31ac08d) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 2e31e1252e..09aa63d56d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -3,7 +3,7 @@ Version 3.0 stat cache code Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 1999-200 + Copyright (C) Jeremy Allison 1999-2000 This program is free software; you can redistribute it and/or modify -- cgit From deed36e40fcf5ca643afe896f2235dbec82e6c7d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 25 Sep 2001 09:57:06 +0000 Subject: - the inactive core of the new mangling code that use tdb - some more utils for unicode string manipulation (This used to be commit 4ade36446e7dee1c3828d8c822f047c6e891a644) --- source3/smbd/mangle.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 357 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 0e6689d9d2..0de2188bcf 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -965,3 +965,360 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) return(True); } /* name_map_mangle */ + + + + +#if 0 + +#define MANGLE_TDB_VERSION "20010830" +#define MANGLE_TDB_FILE_NAME "mangle.tdb" +#define MANGLE_TDB_STORED_NAME "B" +#define MANGLED_PREFIX "MANGLED_" +#define LONG_PREFIX "LONG_" + +struct mt_enum_info { + TDB_CONTEXT *mangle_tdb; + TDB_DATA key; +}; + + +static struct mt_enum_info global_mt_ent = {0, 0}; + +static int POW10(unsigned int exp) +{ + int result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static BOOL init_mangle_tdb(void) +{ + pstring tdbfile; + + if (global_mt_ent.mangle_tdb == 0) + { + slprintf(tdbfile, sizeof(tdbfile)-1, "%s/%s", lp_private_dir(), MANGLE_TDB_FILE_NAME); + + /* Open tdb */ + if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) + { + DEBUG(0, ("Unable to open Mangle TDB, trying create new!\n")); + /* create a new one if it does not exist */ + if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600))) + { + DEBUG(0, ("Unable to create Mangle TDB (%s) !!!", tdbfile)); + return False; + } + } + } + + return True; +} + +/* see push_ucs2 */ +int dos_to_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, int flags) +{ + int len=0; + int src_len = strlen(src); + pstring tmpbuf; + + /* treat a pstring as "unlimited" length */ + if (dest_len == -1) { + dest_len = sizeof(pstring); + } + + if (flags & STR_UPPER) { + pstrcpy(tmpbuf, src); + strupper(tmpbuf); + src = tmpbuf; + } + + if (flags & STR_TERMINATE) { + src_len++; + } + + if (ucs2_align(base_ptr, dest, flags)) { + *(char *)dest = 0; + dest = (void *)((char *)dest + 1); + if (dest_len) dest_len--; + len++; + } + + /* ucs2 is always a multiple of 2 bytes */ + dest_len &= ~1; + + len += convert_string(CH_DOS, CH_UCS2, src, src_len, dest, dest_len); + return len; +} + +/* see pull_ucs2 */ +int ucs2_to_dos(const void *base_ptr, char *dest, const void *src, int dest_len, int src_len, int flags) +{ + int ret; + + if (dest_len == -1) { + dest_len = sizeof(pstring); + } + + if (ucs2_align(base_ptr, src, flags)) { + src = (const void *)((char *)src + 1); + if (src_len > 0) src_len--; + } + + if (flags & STR_TERMINATE) src_len = strlen_w(src)*2+2; + + /* ucs2 is always a multiple of 2 bytes */ + src_len &= ~1; + + ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len); + if (dest_len) dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + + + +/* the unicode string will be ZERO terminated */ +static smb_ucs2_t *unicode_from_buffer (uint8 *buf, uint32 size) +{ + uint32 len = 0; + uint32 lfn_len; + smb_ucs2_t *long_file_name; + + len = tdb_unpack (buf, size, MANGLE_TDB_STORED_NAME, + &lfn_len, &long_file_name); + + if (len == -1) return NULL; + else return long_file_name; +} + +/* the unicode string MUST be ZERO terminated */ +static uint32 buffer_from_unicode (uint8 **buf, smb_ucs2_t *long_file_name) +{ + uint32 buflen; + uint32 len = 0; + uint32 lfn_len = strlen_w(long_file_name)*sizeof(smb_ucs2_t)+1; + + /* one time to get the size needed */ + len = tdb_pack(NULL, 0, MANGLE_TDB_STORED_NAME, + lfn_len, long_file_name); + + /* malloc the space needed */ + if ((*buf=(uint8*)malloc(len)) == NULL) + { + DEBUG(0,("buffer_from_longname: Unable to malloc() memory for buffer!\n")); + return (-1); + } + + /* now for the real call to tdb_pack() */ + buflen = tdb_pack(*buf, 0, MANGLE_TDB_STORED_NAME, + lfn_len, long_file_name); + + /* check to make sure we got it correct */ + if (buflen != len) + { + /* error */ + free (*buf); + return (-1); + } + + return (buflen); +} + +/* mangled must contain only the file name, not a path. + and MUST be ZERO terminated */ +smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) +{ + TDB_DATA data, key; + fstring keystr; + fstring mufname; + smb_ucs2_t *retstr; + smb_ucs2_t *temp; + + if (strlen_w(mangled) > 12) return NULL; + if (!strchr_wa(mangled, '~')) return NULL; + if (!init_mangle_tdb()) return NULL; + + temp = strdup_w(mangled); + if (!temp) + { + DEBUG(0,("mangle: out of memory!\n")); + return NULL; + } + strupper_w(temp); + /* set search key */ + pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); + SAFE_FREE(temp); + slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + + /* get the record */ + data = tdb_fetch(global_mt_ent.mangle_tdb, key); + + if (!data.dptr) /* not found */ + { + DEBUG(5,("unmangle: %s\n", tdb_errorstr(global_mt_ent.mangle_tdb))); + return NULL; + } + + if (!(retstr = unicode_from_buffer (data.dptr, data.dsize))) + { + DEBUG(0,("unmangle: bad buffer returned from database!\n")); + SAFE_FREE(data.dptr); + return NULL; + } + + SAFE_FREE(data.dptr); + return retstr; +} + +/* unmangled must contain only the file name, not a path. + and MUST be ZERO terminated */ +smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) +{ + TDB_DATA data, key; + pstring keystr; + pstring longname; + fstring mufname; + BOOL db_free = False; + smb_ucs2_t *mangled; + smb_ucs2_t *um; + smb_ucs2_t *ext = NULL; + smb_ucs2_t *p; + size_t b_len; + size_t e_len; + size_t um_len; + uint32 n, c; + + + /* TODO: if it is a path return a failure */ + + um = strdup_w(unmangled); + if (!um) + { + DEBUG(0,("mangle: out of memory!\n")); + goto error; + } + um_len = strlen_w(um); + if (p = strrchr_wa(um, '.')) + { + if ((um_len - ((p - um) / sizeof(smb_ucs2_t))) < 4) /* check extension */ + { + *p = UCS2_CHAR('\0'); + ext = p++; + } + } + + /* test if the same is yet mangled */ + + /* set search key */ + pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE); + slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + + /* get the record */ + data = tdb_fetch (global_mt_ent.mangle_tdb, key); + if (!data.dptr) /* not found */ + { + if (tdb_error(global_mt_ent.mangle_tdb) != TDB_ERR_NOEXIST) + { + DEBUG(0, ("mangle: database retrieval error: %s\n", + tdb_errorstr(global_mt_ent.mangle_tdb))); + goto error; + } + + /* if not find the first free possibile mangled name */ + n = c = 1; + while (!db_free) + { + uint32 pos; + smb_ucs2_t temp[9]; + char num[7]; + + while ((int)POW10(n) <= c) n++; + pos = 7 - n; + if (pos == 0) goto error; + + strncpy_w(temp, um, pos); + strupper_w(temp); + temp[pos] = UCS2_CHAR('~'); + temp[pos+1] = 0; + snprintf(num, 7, "%d", c); + strncat_wa(temp, num, n); + + pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); + if (strlen(mufname) > 8) + { + n++; + continue; + } + + slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + if ((data.dsize=buffer_from_unicode ((uint8 **)(&data.dptr), temp)) == -1) + { + DEBUG(0,("mangle: ERROR - Unable to copy mangled name info buffer!\n")); + goto error; + } + + if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) + { + SAFE_FREE(data.dptr); + if (tdb_error(global_mt_ent.mangle_tdb) == TDB_ERR_EXISTS) + { + continue; + } + else + { + DEBUG(0, ("mangle: database retrieval error: %s\n", + tdb_errorstr(global_mt_ent.mangle_tdb))); + goto error; + } + } + else + { + db_free = True; + p = strdup_w(temp); + } + c++; + } + } + else /* FOUND */ + { + if (!(p = unicode_from_buffer (data.dptr, data.dsize))) + { + DEBUG(0,("mangle: bad buffer returned from database!\n")); + goto error; + } + } + + b_len = strlen_w(p); + if (ext) e_len = strlen_w(ext); + else e_len = 0; + mangled = (smb_ucs2_t *)malloc((b_len+e_len+2)*sizeof(smb_ucs2_t)); + strncpy_w (mangled, p, b_len+1); + strncat_w (mangled, ext, e_len); + + SAFE_FREE(p); + SAFE_FREE(um); + SAFE_FREE(data.dptr); + + return mangled; + +error: + DEBUG(10, ("mangle: failed to mangle !\n")); + SAFE_FREE(data.dptr); + SAFE_FREE(um); + return NULL; +} + +#endif /* 0 */ -- cgit From 950bae4a2232b7f5375cc3e1e062817e53ec9b34 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Sep 2001 02:30:55 +0000 Subject: Update build_options.c in line with new configure options. (This used to be commit 3f10b045666479e3e1981b09fcaa0d0810422fcb) --- source3/smbd/build_options.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 5486fae335..c3d24b69a7 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -104,16 +104,20 @@ void build_options(BOOL screen) snprintf(outstring,sizeof(outstring)," WITH_PAM\n"); output(screen,outstring); #endif -#ifdef WITH_TDBSAM - snprintf(outstring,sizeof(outstring)," WITH_TDBSAM\n"); +#ifdef WITH_TDB_SAM + snprintf(outstring,sizeof(outstring)," WITH_TDB_SAM\n"); output(screen,outstring); #endif -#ifdef WITH_LDAP - snprintf(outstring,sizeof(outstring)," WITH_LDAP\n"); +#ifdef WITH_LDAP_SAM + snprintf(outstring,sizeof(outstring)," WITH_LDAP_SAM\n"); output(screen,outstring); #endif -#ifdef WITH_NISPLUS - snprintf(outstring,sizeof(outstring)," WITH_NISPLUS\n"); +#ifdef WITH_SMBPASSWD_SAM + snprintf(outstring,sizeof(outstring)," WITH_SMBPASSWD_SAM\n"); + output(screen,outstring); +#endif +#ifdef WITH_NISPLUS_SAM + snprintf(outstring,sizeof(outstring)," WITH_NISPLUS_SAM\n"); output(screen,outstring); #endif #ifdef WITH_NISPLUS_HOME -- cgit From c907f33396ca1b16baf67e50ef8116c45bd612a5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Sep 2001 11:55:13 +0000 Subject: Update for new pdb_set_plaintext_passwd() interface. (This used to be commit ce676f8bfc6222df1e05b164420efab30eb1b2e1) --- source3/smbd/chgpasswd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 8dff2f7d81..9dbd57129c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -870,13 +870,8 @@ BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd, BOOL override) { int ret; - uchar new_nt_p16[16]; - uchar new_p16[16]; - - nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); - pdb_set_lanman_passwd (hnd, new_p16); - pdb_set_nt_passwd (hnd, new_nt_p16); + pdb_set_plaintext_passwd (hnd, new_passwd); /* Now write it into the file. */ become_root(); -- cgit From 83db39d2b5624217422b4c10509d589018f7a329 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Sep 2001 12:12:26 +0000 Subject: Fix this to use the plaintext password code directly, like SWAT does. This whole area needs to be cleaned up. Should this kind of passowrd change/check be permitted with encrypt passwords = yes? In any case I've also had trouble testing this, as I can't find the right software/configuration to exersise this behaviour. But its better than the previous situation. Any assistance greatly appriciated. Andrew Bartlett (This used to be commit 37655b42897031f754d436435e64a2548de756b5) --- source3/smbd/lanman.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4d3da88783..e9213e75a2 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1834,6 +1834,8 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param fstring user; fstring pass1,pass2; + struct passwd *passwd; + pull_ascii_fstring(user,p); p = skip_string(p,1); @@ -1863,7 +1865,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param /* * Do any UNIX username case mangling. */ - (void)Get_Pwnam( user, True); + passwd = Get_Pwnam( user, True); /* * Attempt to verify the old password against smbpasswd entries @@ -1906,13 +1908,15 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if(SVAL(*rparam,0) != NERR_Success) { - if (password_ok(user, pass1,strlen(pass1)) && - chgpasswd(user,pass1,pass2,False)) - { - SSVAL(*rparam,0,NERR_Success); - } + if NT_STATUS_IS_OK(pass_check(passwd, user, pass1, + strlen(pass1), NULL, False)) + { + if (chgpasswd(user,pass1,pass2,False)) { + SSVAL(*rparam,0,NERR_Success); + } + } } - + /* * If the plaintext change failed, attempt * the old encrypted method. NT will generate this -- cgit From 71850be47edf5e1c3d36eec45c006a9f94c7f6ce Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Sep 2001 12:28:46 +0000 Subject: Rearrange the order of the checks in auth_smbpasswd.c, always check passwords first. Add password expiry and 'must change before first logon' support. - This requires that the passdb be up to the job to supply the info. (This used to be commit 53c1c5091ea4e3ccc294f8b6f132be78c11c431f) --- source3/smbd/auth_smbpasswd.c | 184 +++++++++++++++++++++++++----------------- 1 file changed, 111 insertions(+), 73 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index cb8d711770..7a21c3111b 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -31,7 +31,7 @@ core of smb password checking routine. static BOOL smb_pwd_check_ntlmv1(const uchar *password, const uchar *part_passwd, const uchar *c8, - uchar user_sess_key[16]) + char user_sess_key[16]) { /* Finish the encryption of part_passwd. */ uchar p24[24]; @@ -45,7 +45,7 @@ static BOOL smb_pwd_check_ntlmv1(const uchar *password, SMBOWFencrypt(part_passwd, c8, p24); if (user_sess_key != NULL) { - SMBsesskeygen_ntv1(part_passwd, NULL, (char *)user_sess_key); + SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); } @@ -70,7 +70,7 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, uchar *part_passwd, uchar const *c8, const char *user, const char *domain, - char *user_sess_key) + char user_sess_key[16]) { /* Finish the encryption of part_passwd. */ uchar kr[16]; @@ -109,17 +109,104 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, char user_sess_key[16]) { uint8 *nt_pw, *lm_pw; uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); + + if (!user_info || !sampass) + return NT_STATUS_LOGON_FAILURE; + + if (acct_ctrl & ACB_PWNOTREQ) + { + if (lp_null_passwords()) + { + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", sampass->username)); + return(NT_STATUS_OK); + } + else + { + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username)); + return(NT_STATUS_LOGON_FAILURE); + } + } else { + nt_pw = pdb_get_nt_passwd(sampass); + lm_pw = pdb_get_lanman_passwd(sampass); + + if (nt_pw != NULL && user_info->nt_resp.len > 0) { + if ((user_info->nt_resp.len > 24 )) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); + if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, + user_info->nt_resp.len, + nt_pw, + user_info->chal, user_info->smb_username.str, + user_info->requested_domain.str, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; + } + + } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24)) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, + nt_pw, user_info->chal, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; + } + } else { + return NT_STATUS_LOGON_FAILURE; + } + } else if (lm_pw != NULL && user_info->lm_resp.len == 24) { + if (lp_lanman_auth()) { + DEBUG(4,("smb_password_ok: Checking LM password\n")); + if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, + lm_pw, user_info->chal, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: LM password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; + } + } + } + } + /* Should not be reached */ + return NT_STATUS_LOGON_FAILURE; +} + +/**************************************************************************** + Do a specific test for a SAM_ACCOUNT being vaild for this connection + (ie not disabled, expired and the like). +****************************************************************************/ +NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info) +{ + uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); char *workstation_list; time_t kickoff_time; + if (!user_info || !sampass) + return NT_STATUS_LOGON_FAILURE; + + DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",sampass->username)); + /* Quit if the account was disabled. */ if(acct_ctrl & ACB_DISABLED) { DEBUG(1,("Account for user '%s' was disabled.\n", sampass->username)); - return(NT_STATUS_ACCOUNT_DISABLED); + return NT_STATUS_ACCOUNT_DISABLED; } /* Test account expire time */ @@ -127,6 +214,8 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use kickoff_time = pdb_get_kickoff_time(sampass); if (kickoff_time != (time_t)-1) { if (time(NULL) > kickoff_time) { + DEBUG(1,("Account for user '%s' has expried.\n", sampass->username)); + DEBUG(3,("Account expired at '%d' unix time.\n", kickoff_time)); return NT_STATUS_ACCOUNT_EXPIRED; } } @@ -161,77 +250,21 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use return NT_STATUS_NO_MEMORY; } - if (acct_ctrl & ACB_PWNOTREQ) { - if (lp_null_passwords()) - { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", sampass->username)); - return(NT_STATUS_OK); - } - else - { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username)); - return(NT_STATUS_LOGON_FAILURE); - } - } - - if (!user_info || !sampass) - return(NT_STATUS_LOGON_FAILURE); - - DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",sampass->username)); - - nt_pw = pdb_get_nt_passwd(sampass); - - if (nt_pw != NULL) { - if ((user_info->nt_resp.len > 24 )) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, - user_info->nt_resp.len, - nt_pw, - user_info->chal, user_info->smb_username.str, - user_info->requested_domain.str, - (char *)server_info->session_key)) - { - return NT_STATUS_OK; - } - DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); - - } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24 )) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, - nt_pw, user_info->chal, - server_info->session_key)) { - DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } + time_t must_change_time = pdb_get_pass_must_change_time(sampass); + if (must_change_time == 0) { + DEBUG(1,("Account for user '%s' must change password at next logon! (ie now).\n", sampass->username)); + return NT_STATUS_PASSWORD_MUST_CHANGE; } - } - - lm_pw = pdb_get_lanman_passwd(sampass); - - if(lp_lanman_auth() && (lm_pw != NULL) && (user_info->lm_resp.len == 24 )) { - DEBUG(4,("smb_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, - lm_pw, user_info->chal, - server_info->session_key)) { - DEBUG(4,("smb_password_ok: LM password check succeeded\n")); - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: LM password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; + + if (must_change_time != (time_t)-1 && must_change_time < time(NULL)) { + DEBUG(1,("Account for user '%s' password expired!.\n", sampass->username)); + DEBUG(1,("Password expired at '%d' unix time.\n", must_change_time)); + return NT_STATUS_PASSWORD_EXPIRED; } } - return NT_STATUS_LOGON_FAILURE; + return NT_STATUS_OK; } @@ -262,10 +295,15 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return NT_STATUS_NO_SUCH_USER; } - nt_status = smb_password_ok(sampass, user_info, server_info); - + nt_status = sam_password_ok(sampass, user_info, server_info->session_key); + + if NT_STATUS_IS_OK(nt_status) { + nt_status = sam_account_ok(sampass, user_info); + } + pdb_free_sam(sampass); return nt_status; } + -- cgit From 865467c82f39a98afa3c65f25b7e24137f904e93 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Sep 2001 13:11:22 +0000 Subject: Process the workstation trust account code INSIDE the authenticaion subsystem, just like any other logon. Matching code removal in reply.c to follow. Andrew Bartlett (This used to be commit da4873d889928e9bd88e736e26e4e77e87bcd931) --- source3/smbd/auth_smbpasswd.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 7a21c3111b..567414d1a2 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -215,15 +215,15 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user if (kickoff_time != (time_t)-1) { if (time(NULL) > kickoff_time) { DEBUG(1,("Account for user '%s' has expried.\n", sampass->username)); - DEBUG(3,("Account expired at '%d' unix time.\n", kickoff_time)); + DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); return NT_STATUS_ACCOUNT_EXPIRED; } } - + /* Test workstation. Workstation list is comma separated. */ - + workstation_list = strdup(pdb_get_workstations(sampass)); - + if (workstation_list) { if (*workstation_list) { BOOL invalid_ws = True; @@ -259,10 +259,25 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user if (must_change_time != (time_t)-1 && must_change_time < time(NULL)) { DEBUG(1,("Account for user '%s' password expired!.\n", sampass->username)); - DEBUG(1,("Password expired at '%d' unix time.\n", must_change_time)); + DEBUG(1,("Password expired at '%ld' unix time.\n", (long)must_change_time)); return NT_STATUS_PASSWORD_EXPIRED; } } + + if (acct_ctrl & ACB_DOMTRUST) { + DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n", sampass->username)); + return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; + } + + if (acct_ctrl & ACB_SVRTRUST) { + DEBUG(0,("session_trust_account: Server trust account %s denied by server\n", sampass->username)); + return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; + } + + if (acct_ctrl & ACB_WSTRUST) { + DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", sampass->username)); + return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; + } return NT_STATUS_OK; } -- cgit From 41821943daef5a4fd077e38068539ae4e24121b3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Sep 2001 13:55:59 +0000 Subject: Kill of the reply.c end of the workstaion trust account mess. Fix the NT errror codes, this time in line with WinXP/2k. - Return the normal error codes, expect for bad user/bad password. These map to logon failure, as a quick security hack. We follow suit. Simplfy some of the password extraction code, the auth subsytem has the intelegence to sort this stuff out, no need to do it here. Move to 'global_encrypted_passwords_negotiated' to determine the use of unencrypted hacks, replacing the current mess. Andrew Bartlett (This used to be commit c04f063573c61d8ef3f43815bbb9b6b076dc23eb) --- source3/smbd/negprot.c | 32 ++++---- source3/smbd/reply.c | 198 +++++++++++-------------------------------------- 2 files changed, 61 insertions(+), 169 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b065cab53e..82222e6725 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -26,6 +26,7 @@ extern int Protocol; extern int max_recv; extern fstring global_myworkgroup; extern fstring remote_machine; +BOOL global_encrypted_passwords_negotiated; /**************************************************************************** reply for the core protocol @@ -66,16 +67,17 @@ static int reply_lanman1(char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; - BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; + if (global_encrypted_passwords_negotiated) secword |= 2; - set_message(outbuf,13,doencrypt?8:0,True); + set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) + if (global_encrypted_passwords_negotiated) generate_next_challenge(smb_buf(outbuf)); Protocol = PROTOCOL_LANMAN1; @@ -103,25 +105,26 @@ static int reply_lanman2(char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; - BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + if (lp_security() == SEC_SERVER) { cli = server_cryptkey(); } if (cli) { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); } if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; + if (global_encrypted_passwords_negotiated) secword |= 2; - if (doencrypt) { + if (global_encrypted_passwords_negotiated) { crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); @@ -134,7 +137,7 @@ static int reply_lanman2(char *outbuf) set_message(outbuf,13,crypt_len,True); SSVAL(outbuf,smb_vwv1,secword); SIVAL(outbuf,smb_vwv6,sys_getpid()); - if (doencrypt) + if (global_encrypted_passwords_negotiated) memcpy(smb_buf(outbuf), cryptkey, 8); Protocol = PROTOCOL_LANMAN2; @@ -162,13 +165,14 @@ static int reply_nt1(char *outbuf) CAP_LEVEL_II_OPLOCKS|CAP_STATUS32; int secword=0; - BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; char *p, *q; + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + if (lp_security() == SEC_SERVER) { DEBUG(5,("attempting password server validation\n")); cli = server_cryptkey(); @@ -178,12 +182,12 @@ static int reply_nt1(char *outbuf) if (cli) { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); } else { DEBUG(3,("not using password server validation\n")); } - if (doencrypt) { + if (global_encrypted_passwords_negotiated) { crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); @@ -216,7 +220,7 @@ static int reply_nt1(char *outbuf) capabilities |= CAP_DFS; if (lp_security() >= SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; + if (global_encrypted_passwords_negotiated) secword |= 2; set_message(outbuf,17,0,True); @@ -235,7 +239,7 @@ static int reply_nt1(char *outbuf) SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); p = q = smb_buf(outbuf); - if (doencrypt) memcpy(p, cryptkey, 8); + if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8); p += 8; p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 572ed90b32..dbd149afcf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -43,6 +43,7 @@ uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; extern fstring remote_machine; +extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** report a possible attack via the password buffer overflow bug @@ -246,7 +247,6 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt passlen = strlen(password); } - /* * the service name can be either: \\server\share * or share directly like on the DELL PowerVault 705 @@ -373,107 +373,6 @@ int reply_ioctl(connection_struct *conn, return outsize; } -/**************************************************************************** - This function breaks the authentication split. It needs sorting out. - I can't see why we can't hadle this INSIDE the check_password, as in then - end all it does it spit out an nt_status code. - ****************************************************************************/ -/**************************************************************************** - always return an error: it's just a matter of which one... - ****************************************************************************/ -static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user, - char *smb_passwd, int smb_passlen, - char *smb_nt_passwd, int smb_nt_passlen) -{ - /* check if trust account exists */ - SAM_ACCOUNT *sam_trust_acct = NULL; - uint16 acct_ctrl; - BOOL ret; - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR domain, smb_username, wksta_name; - - ZERO_STRUCT(user_info); - ZERO_STRUCT(server_info); - ZERO_STRUCT(domain); - ZERO_STRUCT(smb_username); - ZERO_STRUCT(wksta_name); - - domain.str = lp_workgroup(); - domain.len = strlen(domain.str); - - user_info.requested_domain = domain; - user_info.domain = domain; - - smb_username.str = user; - smb_username.len = strlen(smb_username.str); - - user_info.unix_username = smb_username; /* For the time-being */ - user_info.smb_username = smb_username; - - user_info.wksta_name = wksta_name; - - user_info.lm_resp.buffer = (uint8 *)smb_passwd; - user_info.lm_resp.len = smb_passlen; - user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd; - user_info.nt_resp.len = smb_nt_passlen; - - if (!last_challenge(user_info.chal)) { - DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - pdb_init_sam(&sam_trust_acct); - - if (lp_security() == SEC_USER) { - ret = pdb_getsampwnam(sam_trust_acct, user); - } else { - DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); - } - - if (ret == False) { - /* lkclXXXX: workstation entry doesn't exist */ - DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_NO_SUCH_USER)); - } else { - if ((smb_passlen != 24) || (smb_nt_passlen != 24)) { - DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); - } - - if (!NT_STATUS_IS_OK(smb_password_ok(sam_trust_acct, &user_info, &server_info))) { - DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); - } - - acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct); - pdb_free_sam(sam_trust_acct); - if (acct_ctrl & ACB_DOMTRUST) { - DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); - return(ERROR_NT(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); - } - - if (acct_ctrl & ACB_SVRTRUST) { - DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); - return(ERROR_NT(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); - } - - if (acct_ctrl & ACB_WSTRUST) { - DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); - return(ERROR_NT(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); - } - } - - /* don't know what to do: indicate logon failure */ - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); -} - - /**************************************************************************** reply to a session setup command ****************************************************************************/ @@ -496,14 +395,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int fstring native_lanman; BOOL guest=False; static BOOL done_sesssetup = False; - BOOL doencrypt = lp_encrypted_passwords(); + BOOL doencrypt = global_encrypted_passwords_negotiated; START_PROFILE(SMBsesssetupX); - ZERO_STRUCT(smb_apasswd); - ZERO_STRUCT(smb_ntpasswd); + *smb_apasswd = *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); - + if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); if (smb_apasslen > MAX_PASS_LEN) { @@ -513,7 +411,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); - + if (!doencrypt && (lp_security() != SEC_SERVER)) { smb_apasslen = strlen(smb_apasswd); } @@ -585,27 +483,22 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } } - if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { - /* Save the lanman2 password and the NT md4 password. */ - smb_apasslen = passlen1; - memcpy(smb_apasswd,p,smb_apasslen); - smb_apasswd[smb_apasslen] = 0; - smb_ntpasslen = passlen2; - memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); - smb_ntpasswd[smb_ntpasslen] = 0; - } else { - /* we use the first password that they gave */ - smb_apasslen = passlen1; - StrnCpy(smb_apasswd,p,smb_apasslen); - - /* trim the password */ - smb_apasslen = strlen(smb_apasswd); + /* Save the lanman2 password and the NT md4 password. */ + smb_apasslen = passlen1; + memcpy(smb_apasswd,p,smb_apasslen); - /* wfwg sometimes uses a space instead of a null */ - if (strequal(smb_apasswd," ")) { - smb_apasslen = 0; - *smb_apasswd = 0; - } + smb_ntpasslen = passlen2; + memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); + + if (smb_apasslen != 24 || !doencrypt) { + /* trim the password */ + smb_apasslen = strlen(smb_apasswd); + + /* wfwg sometimes uses a space instead of a null */ + if (strequal(smb_apasswd," ")) { + smb_apasslen = 0; + *smb_apasswd = 0; + } } p += passlen1 + passlen2; @@ -640,18 +533,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } - DEBUG(3,("sesssetupX:name=[%s]@[%s]\n",user, remote_machine)); - - /* If name ends in $ then I think it's asking about whether a */ - /* computer with that name (minus the $) has access. For now */ - /* say yes to everything ending in $. */ - - if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) { - END_PROFILE(SMBsesssetupX); - return session_trust_account(conn, inbuf, outbuf, user, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen); - } + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine)); if (done_sesssetup && lp_restrict_anonymous()) { /* tests show that even if browsing is done over already validated connections @@ -731,21 +613,27 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if NT_STATUS_IS_OK(nt_status) { - } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) - && lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) { - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - - } else if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) - || NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) - && (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); + pstrcpy(user,lp_guestaccount(-1)); + guest = True; + } else { + /* Match WinXP and don't give the game away */ + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + pstrcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } else { + /* Match WinXP and don't give the game away */ + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } } else { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status); } } @@ -792,10 +680,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name); + sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name); if (sess_vuid == -1) { - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -- cgit From 2c4d1d39b148b8587deb8fca2db4113354165989 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 26 Sep 2001 17:29:53 +0000 Subject: OpenSSL merge from 2.2 (This used to be commit efc6df5a3914da9e7b792ccaccd1403c72c09f78) --- source3/smbd/ssl.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index dff5f34d5d..c45afc52d5 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -29,8 +29,8 @@ #ifdef WITH_SSL /* should always be defined if this module is compiled */ -#include -#include +#include +#include BOOL sslEnabled; SSL *ssl = NULL; @@ -74,12 +74,12 @@ char buffer[256]; return ok; } -static RSA *ssl_temp_rsa_cb(SSL *ssl, int export) +static RSA *ssl_temp_rsa_cb(SSL *ssl, int is_export, int keylength) { static RSA *rsa = NULL; if(rsa == NULL) - rsa = RSA_generate_key(512, RSA_F4, NULL, NULL); + rsa = RSA_generate_key(keylength, RSA_F4, NULL, NULL); return rsa; } @@ -89,11 +89,19 @@ static RSA *rsa = NULL; */ int sslutil_init(int isServer) { -int err; +int err, entropybytes; char *certfile, *keyfile, *ciphers, *cacertDir, *cacertFile; +char *egdsocket, *entropyfile; SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); + egdsocket = lp_ssl_egdsocket(); + if (egdsocket != NULL && *egdsocket != 0) + RAND_egd(egdsocket); + entropyfile = lp_ssl_entropyfile(); + entropybytes = lp_ssl_entropybytes(); + if (entropyfile != NULL && *entropyfile != 0) + RAND_load_file(entropyfile, entropybytes); switch(lp_ssl_version()){ case SMB_SSL_V2: sslContext = SSL_CTX_new(SSLv2_method()); break; case SMB_SSL_V3: sslContext = SSL_CTX_new(SSLv3_method()); break; @@ -120,7 +128,7 @@ char *certfile, *keyfile, *ciphers, *cacertDir, *cacertFile; if(keyfile == NULL || *keyfile == 0) keyfile = certfile; if(certfile != NULL && *certfile != 0){ - if(!SSL_CTX_use_certificate_file(sslContext, certfile, SSL_FILETYPE_PEM)){ + if(!SSL_CTX_use_certificate_chain_file(sslContext, certfile)){ err = ERR_get_error(); fprintf(stderr, "SSL: error reading certificate from file %s: %s\n", certfile, ERR_error_string(err, NULL)); @@ -146,9 +154,11 @@ char *certfile, *keyfile, *ciphers, *cacertDir, *cacertFile; cacertFile = NULL; if(!SSL_CTX_load_verify_locations(sslContext, cacertFile, cacertDir)){ err = ERR_get_error(); - fprintf(stderr, "SSL: Error error setting CA cert locations: %s\n", - ERR_error_string(err, NULL)); - fprintf(stderr, "trying default locations.\n"); + if (cacertFile || cacertDir) { + fprintf(stderr, "SSL: Error error setting CA cert locations: %s\n", + ERR_error_string(err, NULL)); + fprintf(stderr, "trying default locations.\n"); + } cacertFile = cacertDir = NULL; if(!SSL_CTX_set_default_verify_paths(sslContext)){ err = ERR_get_error(); -- cgit From 59a02ecae1b0251da5cdd5e34653f7eb14704e72 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 27 Sep 2001 02:05:30 +0000 Subject: minor fixes (This used to be commit 57e639bbdd115b51362caf7e3db4ba34ccdeddc2) --- source3/smbd/mangle.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 0de2188bcf..c0a3dacf08 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1006,15 +1006,10 @@ static BOOL init_mangle_tdb(void) slprintf(tdbfile, sizeof(tdbfile)-1, "%s/%s", lp_private_dir(), MANGLE_TDB_FILE_NAME); /* Open tdb */ - if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) + if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) { - DEBUG(0, ("Unable to open Mangle TDB, trying create new!\n")); - /* create a new one if it does not exist */ - if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600))) - { - DEBUG(0, ("Unable to create Mangle TDB (%s) !!!", tdbfile)); - return False; - } + DEBUG(0, ("Unable to open Mangle TDB\n")); + return False; } } @@ -1153,7 +1148,7 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) } strupper_w(temp); /* set search key */ - pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); + ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); SAFE_FREE(temp); slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; @@ -1254,7 +1249,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) snprintf(num, 7, "%d", c); strncat_wa(temp, num, n); - pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); + ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); if (strlen(mufname) > 8) { n++; -- cgit From 31a87fa4a60a4f932aa8f2b7ed68f010a8e8923f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 27 Sep 2001 12:41:38 +0000 Subject: get out unicode_from_buffer and buffer_from_unicode, unneeded. store mangled filename in dos charset and unmangled in unicode. clean ups still lot to do. againg compiled but not yet tested. (This used to be commit 2d1aabb6d4bf23985a9ce0f7e065292aacedc80a) --- source3/smbd/mangle.c | 251 ++++++++++++++++++++++++++++---------------------- 1 file changed, 139 insertions(+), 112 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index c0a3dacf08..916e2a00b3 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -970,7 +970,6 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) #if 0 - #define MANGLE_TDB_VERSION "20010830" #define MANGLE_TDB_FILE_NAME "mangle.tdb" #define MANGLE_TDB_STORED_NAME "B" @@ -999,11 +998,11 @@ static int POW10(unsigned int exp) static BOOL init_mangle_tdb(void) { - pstring tdbfile; + char *tdbfile; if (global_mt_ent.mangle_tdb == 0) { - slprintf(tdbfile, sizeof(tdbfile)-1, "%s/%s", lp_private_dir(), MANGLE_TDB_FILE_NAME); + tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */ /* Open tdb */ if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) @@ -1077,55 +1076,42 @@ int ucs2_to_dos(const void *base_ptr, char *dest, const void *src, int dest_len, return src_len; } - - -/* the unicode string will be ZERO terminated */ -static smb_ucs2_t *unicode_from_buffer (uint8 *buf, uint32 size) -{ - uint32 len = 0; - uint32 lfn_len; - smb_ucs2_t *long_file_name; - - len = tdb_unpack (buf, size, MANGLE_TDB_STORED_NAME, - &lfn_len, &long_file_name); - - if (len == -1) return NULL; - else return long_file_name; -} - -/* the unicode string MUST be ZERO terminated */ -static uint32 buffer_from_unicode (uint8 **buf, smb_ucs2_t *long_file_name) +/* return False if something fail and + * return 2 alloced unicode strings that contain prefix and extension + */ +static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension) { - uint32 buflen; - uint32 len = 0; - uint32 lfn_len = strlen_w(long_file_name)*sizeof(smb_ucs2_t)+1; - - /* one time to get the size needed */ - len = tdb_pack(NULL, 0, MANGLE_TDB_STORED_NAME, - lfn_len, long_file_name); + size_t str_len; + smb_ucs2_t *p; - /* malloc the space needed */ - if ((*buf=(uint8*)malloc(len)) == NULL) + *extension = 0; + *prefix = strdup_w(ucs2_string); + if (!*prefix) { - DEBUG(0,("buffer_from_longname: Unable to malloc() memory for buffer!\n")); - return (-1); + DEBUG(0,("mangle_get_prefix: out of memory!\n")); + return False; } - - /* now for the real call to tdb_pack() */ - buflen = tdb_pack(*buf, 0, MANGLE_TDB_STORED_NAME, - lfn_len, long_file_name); - - /* check to make sure we got it correct */ - if (buflen != len) + str_len = strlen_w(*prefix); + if (p = strrchr_wa(*prefix, '.')) { - /* error */ - free (*buf); - return (-1); + if ((str_len - ((p - *prefix) / sizeof(smb_ucs2_t))) < 4) /* check extension */ + { + *p = 0; + p++; + *extension = strdup_w(p); + if (!*extension) + { + DEBUG(0,("mangle_get_prefix: out of memory!\n")); + SAFE_FREE(*prefix); + return False; + } + } } - return (buflen); + return True; } + /* mangled must contain only the file name, not a path. and MUST be ZERO terminated */ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) @@ -1133,24 +1119,23 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) TDB_DATA data, key; fstring keystr; fstring mufname; - smb_ucs2_t *retstr; - smb_ucs2_t *temp; + smb_ucs2_t *pref, *ext, *retstr; + size_t long_len, ext_len; + BOOL ret; if (strlen_w(mangled) > 12) return NULL; if (!strchr_wa(mangled, '~')) return NULL; if (!init_mangle_tdb()) return NULL; - temp = strdup_w(mangled); - if (!temp) - { - DEBUG(0,("mangle: out of memory!\n")); - return NULL; - } - strupper_w(temp); + ret = mangle_get_prefix(mangled, &pref, &ext); + if (!ret) return NULL; + + /* TODO: get out extension */ + strlower_w(pref); /* set search key */ - ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); - SAFE_FREE(temp); - slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); + ucs2_to_dos(NULL, mufname, pref, sizeof(mufname), 0, STR_TERMINATE); + SAFE_FREE(pref); + slprintf(keystr, sizeof(keystr) - 1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; @@ -1159,18 +1144,42 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) if (!data.dptr) /* not found */ { - DEBUG(5,("unmangle: %s\n", tdb_errorstr(global_mt_ent.mangle_tdb))); - return NULL; + DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(global_mt_ent.mangle_tdb))); + retstr = NULL; + goto done; } - - if (!(retstr = unicode_from_buffer (data.dptr, data.dsize))) + + if (ext) + { + long_len = data.dsize / 2; /* terminator counted on purpose, will contain '.' */ + ext_len = strlen_w(ext); + retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 1)*sizeof(smb_ucs2_t)); + if (!retstr) + { + DEBUG(0, ("unamngle: out of memory!\n")); + goto done; + } + strncpy_w(retstr, (smb_ucs2_t *)data.dptr, long_len); + retstr[long_len] = UCS2_CHAR('.'); + retstr[long_len + 1] = 0; + strncat_w(retstr, ext, ext_len); + } + else { - DEBUG(0,("unmangle: bad buffer returned from database!\n")); - SAFE_FREE(data.dptr); - return NULL; + retstr = strdup_w((smb_ucs2_t *)data.dptr); + if (!retstr) + { + DEBUG(0, ("unamngle: out of memory!\n")); + goto done; + } + } +done: SAFE_FREE(data.dptr); + SAFE_FREE(pref); + SAFE_FREE(ext); + return retstr; } @@ -1183,33 +1192,17 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) pstring longname; fstring mufname; BOOL db_free = False; - smb_ucs2_t *mangled; - smb_ucs2_t *um; - smb_ucs2_t *ext = NULL; - smb_ucs2_t *p; - size_t b_len; - size_t e_len; + smb_ucs2_t *mangled = NULL; + smb_ucs2_t *um, *ext, *p = NULL; + size_t pref_len, ext_len; size_t um_len; uint32 n, c; - /* TODO: if it is a path return a failure */ + /* TODO: if it is a path return a failure ?? */ + - um = strdup_w(unmangled); - if (!um) - { - DEBUG(0,("mangle: out of memory!\n")); - goto error; - } - um_len = strlen_w(um); - if (p = strrchr_wa(um, '.')) - { - if ((um_len - ((p - um) / sizeof(smb_ucs2_t))) < 4) /* check extension */ - { - *p = UCS2_CHAR('\0'); - ext = p++; - } - } + if (!mangle_get_prefix(unmangled, &um, &ext)) return NULL; /* test if the same is yet mangled */ @@ -1227,7 +1220,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) { DEBUG(0, ("mangle: database retrieval error: %s\n", tdb_errorstr(global_mt_ent.mangle_tdb))); - goto error; + goto done; } /* if not find the first free possibile mangled name */ @@ -1240,10 +1233,13 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) while ((int)POW10(n) <= c) n++; pos = 7 - n; - if (pos == 0) goto error; - + if (pos == 0) + { + DEBUG(0, ("mangle: unable to mangle file name!\n")); + goto done; + } strncpy_w(temp, um, pos); - strupper_w(temp); + strlower_w(temp); temp[pos] = UCS2_CHAR('~'); temp[pos+1] = 0; snprintf(num, 7, "%d", c); @@ -1255,19 +1251,16 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) n++; continue; } - + + /* store the mangled entries */ slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - if ((data.dsize=buffer_from_unicode ((uint8 **)(&data.dptr), temp)) == -1) - { - DEBUG(0,("mangle: ERROR - Unable to copy mangled name info buffer!\n")); - goto error; - } + data.dsize = (strlen_w(um) + 1) * sizeof (smb_ucs2_t); + data.dptr = (void *)um; if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) { - SAFE_FREE(data.dptr); if (tdb_error(global_mt_ent.mangle_tdb) == TDB_ERR_EXISTS) { continue; @@ -1276,44 +1269,78 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) { DEBUG(0, ("mangle: database retrieval error: %s\n", tdb_errorstr(global_mt_ent.mangle_tdb))); - goto error; + goto done; } } else { + /* store the mangled entry */ + pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE); + slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + data.dsize = strlen(mufname +1); + data.dptr = mufname; + if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) + { + DEBUG(0, ("mangle: store failed: %s\n", + tdb_errorstr(global_mt_ent.mangle_tdb))); + goto done; + } + db_free = True; p = strdup_w(temp); + if (!p) + { + DEBUG(0,("mangle: out of memory!\n")); + goto done; + } } c++; } } else /* FOUND */ { - if (!(p = unicode_from_buffer (data.dptr, data.dsize))) + p = (smb_ucs2_t *)malloc(data.dsize*sizeof(smb_ucs2_t)); + if (!p) { - DEBUG(0,("mangle: bad buffer returned from database!\n")); - goto error; + DEBUG(0,("mangle: out of memory!\n")); + goto done; } + dos_to_ucs2(NULL, p, data.dptr, data.dsize*sizeof(smb_ucs2_t), STR_TERMINATE); } - b_len = strlen_w(p); - if (ext) e_len = strlen_w(ext); - else e_len = 0; - mangled = (smb_ucs2_t *)malloc((b_len+e_len+2)*sizeof(smb_ucs2_t)); - strncpy_w (mangled, p, b_len+1); - strncat_w (mangled, ext, e_len); + if (ext) + { + pref_len = strlen_w(p) + 1; /* terminator counted on purpose, will contain '.' */ + ext_len = strlen_w(ext); + mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 1)*sizeof(smb_ucs2_t)); + if (!mangled) + { + DEBUG(0,("mangle: out of memory!\n")); + goto done; + } + strncpy_w (mangled, p, pref_len); + mangled[pref_len] = UCS2_CHAR('.'); + mangled[pref_len + 1] = 0; + strncat_w (mangled, ext, ext_len); + } + else + { + mangled = strdup_w(p); + if (!mangled) + { + DEBUG(0,("mangle: out of memory!\n")); + goto done; + } + } +done: SAFE_FREE(p); SAFE_FREE(um); - SAFE_FREE(data.dptr); + SAFE_FREE(ext); return mangled; - -error: - DEBUG(10, ("mangle: failed to mangle !\n")); - SAFE_FREE(data.dptr); - SAFE_FREE(um); - return NULL; } #endif /* 0 */ -- cgit From 81697d5ebe33ad95dedfc376118fcdf0367cf052 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 29 Sep 2001 13:08:26 +0000 Subject: Fix up a number of intertwined issues: The big one is a global change to allow us to NULLify the free'ed pointer to a former passdb object. This was done to allow idra's SAFE_FREE() macro to do its magic, and to satisfy the input test in pdb_init_sam() for a NULL pointer to start with. This NULL pointer test was what was breaking the adding of accounts up until now, and this code has been reworked to avoid duplicating work - I hope this will avoid a similar mess-up in future. Finally, I fixed a few nasty bugs where the pdb_ fuctions's return codes were being ignored. Some of these functions malloc() and are permitted to fail. Also, this caught a nasty bug where pdb_set_lanman_password(sam, NULL) acheived precisely didilly-squat, just returning False. Now that we check the returns this bug was spotted. This could allow different LM and NT passwords. - the pdbedit code needs to start checking these too, but I havn't had a chance to fix it. I have also fixed up where some of the password changing code was using the pdb_set functions to store *internal* data. I assume this is from a previous lot of mass conversion work... Most likally (and going on past experience) I have missed somthing, probably in the LanMan password change code which I havn't yet been able to test, but this lot is in much better shape than it was before. If all this is too much to swallow (particularly for 2.2.2) then just adding a sam_pass = NULL to the particular line of passdb.c should do the trick for the ovbious bug. Andrew Bartlett (This used to be commit 762c8758a7869809d89b4da9c2a5249678942930) --- source3/smbd/auth.c | 4 ++ source3/smbd/auth_smbpasswd.c | 4 +- source3/smbd/auth_unix.c | 32 +++++++++++---- source3/smbd/chgpasswd.c | 93 +++++++++++++++++++++---------------------- source3/smbd/lanman.c | 8 ++-- 5 files changed, 80 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 5b6b2d4c42..6aa2714b0b 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -189,6 +189,10 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, user_info.lm_resp.buffer = (uint8 *)local_lm_response; user_info.lm_resp.len = 24; + + /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. + We might want to add a check here and only do an LM in that case */ + /* This encrypts the lm_pwd feild, which actualy contains the password rather than the nt_pwd field becouse that contains nothing */ SMBNTencrypt((uchar *)lm_pwd, user_info.chal, local_nt_response); diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 567414d1a2..8159ad988f 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -306,7 +306,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ if (ret == False) { DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->unix_username.str)); - pdb_free_sam(sampass); + pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } @@ -316,7 +316,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ nt_status = sam_account_ok(sampass, user_info); } - pdb_free_sam(sampass); + pdb_free_sam(&sampass); return nt_status; } diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 5582682d98..0d73988d8a 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -31,7 +31,7 @@ this ugly hack needs to die, but not quite yet... static BOOL update_smbpassword_file(char *user, char *password) { SAM_ACCOUNT *sampass = NULL; - BOOL ret; + BOOL ret; pdb_init_sam(&sampass); @@ -41,7 +41,7 @@ static BOOL update_smbpassword_file(char *user, char *password) if(ret == False) { DEBUG(0,("pdb_getsampwnam returned NULL\n")); - pdb_free_sam(sampass); + pdb_free_sam(&sampass); return False; } @@ -49,16 +49,32 @@ static BOOL update_smbpassword_file(char *user, char *password) * Remove the account disabled flag - we are updating the * users password from a login. */ - pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED); + if (!pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED)) { + pdb_free_sam(&sampass); + return False; + } + + if (!pdb_set_plaintext_passwd (sampass, password)) { + pdb_free_sam(&sampass); + return False; + } - /* Here, the flag is one, because we want to ignore the + /* Now write it into the file. */ + become_root(); + + /* Here, the override flag is True, because we want to ignore the XXXXXXX'd out password */ - ret = change_oem_password( sampass, password, True); - if (ret == False) { - DEBUG(3,("change_oem_password returned False\n")); + ret = pdb_update_sam_account (sampass, True); + + unbecome_root(); + + if (ret) { + DEBUG(3,("pdb_update_sam_account returned %d\n",ret)); } - pdb_free_sam(sampass); + memset(password, '\0', strlen(password)); + + pdb_free_sam(&sampass); return ret; } diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 9dbd57129c..de49083960 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -557,7 +557,6 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) BOOL check_lanman_password(char *user, uchar * pass1, uchar * pass2, SAM_ACCOUNT **hnd) { - static uchar null_pw[16]; uchar unenc_new_pw[16]; uchar unenc_old_pw[16]; SAM_ACCOUNT *sampass = NULL; @@ -571,7 +570,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (ret == False) { DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); - pdb_free_sam(sampass); + pdb_free_sam(&sampass); return False; } @@ -580,20 +579,20 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); - pdb_free_sam(sampass); + pdb_free_sam(&sampass); return False; } - if ((lanman_pw == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { - uchar no_pw[14]; - memset(no_pw, '\0', 14); - E_P16(no_pw, null_pw); - pdb_set_lanman_passwd (sampass, null_pw); - } - else if (lanman_pw == NULL) { - DEBUG(0, ("check_lanman_password: no lanman password !\n")); - pdb_free_sam(sampass); - return False; + if (lanman_pw == NULL) { + if (acct_ctrl & ACB_PWNOTREQ) { + /* this saves the pointer for the caller */ + *hnd = sampass; + return True; + } else { + DEBUG(0, ("check_lanman_password: no lanman password !\n")); + pdb_free_sam(&sampass); + return False; + } } /* Get the new lanman hash. */ @@ -605,13 +604,12 @@ BOOL check_lanman_password(char *user, uchar * pass1, /* Check that the two old passwords match. */ if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); - pdb_free_sam(sampass); + pdb_free_sam(&sampass); return False; } /* this saves the pointer for the caller */ *hnd = sampass; - return True; } @@ -644,22 +642,30 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, return False; } - if ((pwd == NULL) && (acct_ctrl & ACB_PWNOTREQ)) { - uchar no_pw[14]; - memset(no_pw, '\0', 14); - E_P16(no_pw, null_pw); - pdb_set_lanman_passwd(sampass, null_pw); + if (pwd == NULL) { + if (acct_ctrl & ACB_PWNOTREQ) { + uchar no_pw[14]; + memset(no_pw, '\0', 14); + E_P16(no_pw, null_pw); + + /* Get the new lanman hash. */ + D_P16(null_pw, pass2, unenc_new_pw); + } else { + DEBUG(0,("change_lanman_password: no lanman password !\n")); + return False; + } + } else { + /* Get the new lanman hash. */ + D_P16(pwd, pass2, unenc_new_pw); } - else if (pwd == NULL) { - DEBUG(0,("change_lanman_password: no lanman password !\n")); + + if (!pdb_set_lanman_passwd(sampass, unenc_new_pw)) { return False; } - /* Get the new lanman hash. */ - D_P16(pwd, pass2, unenc_new_pw); - - pdb_set_lanman_passwd(sampass, unenc_new_pw); - pdb_set_nt_passwd (sampass, NULL); /* We lose the NT hash. Sorry. */ + if (!pdb_set_nt_passwd (sampass, NULL)) { + return False; /* We lose the NT hash. Sorry. */ + } /* Now flush the sam_passwd struct to persistent storage */ become_root(); @@ -690,15 +696,15 @@ BOOL pass_oem_change(char *user, * available. JRA. */ - if (ret && lp_unix_password_sync()) + if ((ret) && lp_unix_password_sync()) ret = chgpasswd(user, "", new_passwd, True); if (ret) - ret = change_oem_password(sampass, new_passwd, False); + ret = change_oem_password(sampass, new_passwd); memset(new_passwd, 0, sizeof(new_passwd)); - pdb_free_sam(sampass); + pdb_free_sam(&sampass); return ret; } @@ -762,23 +768,19 @@ static BOOL check_oem_password(char *user, /* check for null passwords */ if (lanman_pw == NULL) { - if (acct_ctrl & ACB_PWNOTREQ) - pdb_set_lanman_passwd(sampass, null_pw); - else { + if (!(acct_ctrl & ACB_PWNOTREQ)) { DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } } - + if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) { - if (acct_ctrl & ACB_PWNOTREQ) - pdb_set_nt_passwd(sampass, null_pw); - else { + if (!(acct_ctrl & ACB_PWNOTREQ)) { DEBUG(0,("check_oem_password: no ntlm password !\n")); return False; } } - + /* * Call the hash function to get the new password. */ @@ -862,24 +864,21 @@ static BOOL check_oem_password(char *user, /*********************************************************** Code to change the oem password. Changes both the lanman and NT hashes. - override = False, normal - override = True, override XXXXXXXXXX'd password ************************************************************/ -BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd, - BOOL override) +BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd) { - int ret; + BOOL ret; - pdb_set_plaintext_passwd (hnd, new_passwd); + if (!pdb_set_plaintext_passwd (hnd, new_passwd)) { + return False; + } /* Now write it into the file. */ become_root(); - ret = pdb_update_sam_account (hnd, override); + ret = pdb_update_sam_account (hnd, False); unbecome_root(); - memset(new_passwd, '\0', strlen(new_passwd)); - return ret; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e9213e75a2..b7acfa5f32 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1884,7 +1884,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param fstrcpy(saved_pass2, pass2); if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) && - change_oem_password(sampass,pass2,False)) + change_oem_password(sampass,pass2)) { SSVAL(*rparam,0,NERR_Success); @@ -1897,7 +1897,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) SSVAL(*rparam,0,NERR_badpass); } - pdb_free_sam(sampass); + pdb_free_sam(&sampass); } @@ -1931,12 +1931,12 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param { SAM_ACCOUNT *hnd = NULL; - if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && + if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2)) { SSVAL(*rparam,0,NERR_Success); } - pdb_free_sam(hnd); + pdb_free_sam(&hnd); } -- cgit From b01e2e7098463059efa403e88f99f47b23419fb8 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 29 Sep 2001 16:16:38 +0000 Subject: further devel and test kit. first tests show it still does not work. work in progress... (This used to be commit a4c746ac474e2e4cead78076ffe2109fab74aefe) --- source3/smbd/mangle.c | 331 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 264 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 916e2a00b3..84bf693011 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -969,12 +969,15 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) -#if 0 -#define MANGLE_TDB_VERSION "20010830" +#if 1 +#define MANGLE_TDB_VERSION "20010927" #define MANGLE_TDB_FILE_NAME "mangle.tdb" -#define MANGLE_TDB_STORED_NAME "B" #define MANGLED_PREFIX "MANGLED_" #define LONG_PREFIX "LONG_" +#define COUNTER_PREFIX "COUNTER_" +#define MANGLE_COUNTER_MAX 99 +#define MANGLE_SUFFIX_SIZE 2 + struct mt_enum_info { TDB_CONTEXT *mangle_tdb; @@ -1094,6 +1097,7 @@ static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix str_len = strlen_w(*prefix); if (p = strrchr_wa(*prefix, '.')) { + /* TODO: check it is <4 in dos charset */ if ((str_len - ((p - *prefix) / sizeof(smb_ucs2_t))) < 4) /* check extension */ { *p = 0; @@ -1187,21 +1191,24 @@ done: and MUST be ZERO terminated */ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) { - TDB_DATA data, key; + TDB_DATA data, key, klock; pstring keystr; pstring longname; + fstring keylock; fstring mufname; - BOOL db_free = False; + fstring prefix; + BOOL tclock = False; + char suffix[MANGLE_SUFFIX_SIZE + 1]; smb_ucs2_t *mangled = NULL; smb_ucs2_t *um, *ext, *p = NULL; + smb_ucs2_t temp[8]; size_t pref_len, ext_len; size_t um_len; - uint32 n, c; - + uint32 n, c, pos; + + if (!init_mangle_tdb()) return NULL; /* TODO: if it is a path return a failure ?? */ - - if (!mangle_get_prefix(unmangled, &um, &ext)) return NULL; /* test if the same is yet mangled */ @@ -1210,8 +1217,8 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE); slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - + key.dsize = strlen(keystr) + 1; + /* get the record */ data = tdb_fetch (global_mt_ent.mangle_tdb, key); if (!data.dptr) /* not found */ @@ -1222,17 +1229,14 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) tdb_errorstr(global_mt_ent.mangle_tdb))); goto done; } - + /* if not find the first free possibile mangled name */ - n = c = 1; - while (!db_free) + + n = 0; + do { - uint32 pos; - smb_ucs2_t temp[9]; - char num[7]; - - while ((int)POW10(n) <= c) n++; - pos = 7 - n; + n++; + pos = 8 - n - MANGLE_SUFFIX_SIZE; if (pos == 0) { DEBUG(0, ("mangle: unable to mangle file name!\n")); @@ -1240,64 +1244,124 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) } strncpy_w(temp, um, pos); strlower_w(temp); - temp[pos] = UCS2_CHAR('~'); - temp[pos+1] = 0; - snprintf(num, 7, "%d", c); - strncat_wa(temp, num, n); - ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); - if (strlen(mufname) > 8) - { - n++; - continue; - } + ucs2_to_dos(NULL, prefix, temp, sizeof(prefix), 0, STR_TERMINATE); + } + while (strlen(prefix) > 8 - (MANGLE_SUFFIX_SIZE + 1)); + + slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix); + klock.dptr = keylock; + klock.dsize = strlen(keylock) + 1; + + c = 0; + data.dptr = (char *)&c; + data.dsize = sizeof(uint32); + /* try to insert a new counter prefix, if it exist the call will + fail (correct) otherwise it will create a new entry with counter set + to 0 + */ + tdb_store(global_mt_ent.mangle_tdb, klock, data, TDB_INSERT); + + /* lock the mangle counter for this prefix */ + if (!tdb_chainlock(global_mt_ent.mangle_tdb, klock)) + { + DEBUG(0,("mangle: failed to lock database\n!")); + goto done; + } + tclock = True; + + data = tdb_fetch(global_mt_ent.mangle_tdb, klock); + if (!data.dptr) + { + DEBUG(0, ("mangle: database retrieval error: %s\n", + tdb_errorstr(global_mt_ent.mangle_tdb))); + goto done; + } + c = *((uint32 *)data.dptr); + c++; + + temp[pos] = UCS2_CHAR('~'); + temp[pos+1] = 0; + snprintf(suffix, MANGLE_SUFFIX_SIZE + 1, "%.6d", c); + strncat_wa(temp, &suffix[6 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE + 1); + + ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); + if (strlen(mufname) > 8) + { + DEBUG(0, ("mangle: darn, logic error aborting!\n")); + goto done; + } - /* store the mangled entries */ + /* store the long entry with mangled key */ + slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + data.dsize = (strlen_w(um) + 1) * sizeof (smb_ucs2_t); + data.dptr = (void *)um; + + if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) + { + DEBUG(0, ("mangle: database store error: %s\n", + tdb_errorstr(global_mt_ent.mangle_tdb))); + goto done; + } + + /* store the mangled entry with long key*/ + pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE); + slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + data.dsize = strlen(mufname +1); + data.dptr = mufname; + if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) + { + DEBUG(0, ("mangle: store failed: %s\n", + tdb_errorstr(global_mt_ent.mangle_tdb))); + + /* try to delete the mangled key entry to avoid later inconsistency */ slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - data.dsize = (strlen_w(um) + 1) * sizeof (smb_ucs2_t); - data.dptr = (void *)um; + if (!tdb_delete(global_mt_ent.mangle_tdb, key)) + { + DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); + } + goto done; + } - if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) + p = strdup_w(temp); + if (!p) + { + DEBUG(0,("mangle: out of memory!\n")); + goto done; + } + + data.dptr = (char *)&c; + data.dsize = sizeof(uint32); + if(!tdb_store(global_mt_ent.mangle_tdb, klock, data, TDB_INSERT)) + { + DEBUG(0, ("mangle: store failed: %s\n", + tdb_errorstr(global_mt_ent.mangle_tdb))); + /* try to delete the mangled and long key entry to avoid later inconsistency */ + slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + if (!tdb_delete(global_mt_ent.mangle_tdb, key)) { - if (tdb_error(global_mt_ent.mangle_tdb) == TDB_ERR_EXISTS) - { - continue; - } - else - { - DEBUG(0, ("mangle: database retrieval error: %s\n", - tdb_errorstr(global_mt_ent.mangle_tdb))); - goto done; - } + DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); } - else + slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); + key.dptr = keystr; + key.dsize = strlen (keystr) + 1; + if (!tdb_delete(global_mt_ent.mangle_tdb, key)) { - /* store the mangled entry */ - pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE); - slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); - key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - data.dsize = strlen(mufname +1); - data.dptr = mufname; - if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) - { - DEBUG(0, ("mangle: store failed: %s\n", - tdb_errorstr(global_mt_ent.mangle_tdb))); - goto done; - } - - db_free = True; - p = strdup_w(temp); - if (!p) - { - DEBUG(0,("mangle: out of memory!\n")); - goto done; - } + DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); } - c++; + goto done; } + + tclock = False; + tdb_chainunlock(global_mt_ent.mangle_tdb, klock); } else /* FOUND */ { @@ -1336,6 +1400,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) } done: + if (tclock) tdb_chainunlock(global_mt_ent.mangle_tdb, klock); SAFE_FREE(p); SAFE_FREE(um); SAFE_FREE(ext); @@ -1344,3 +1409,135 @@ done: } #endif /* 0 */ + +#if 1 /* TEST_MANGLE_CODE */ + +#define LONG "this_is_a_long_file_name" +#define LONGM "this_~01" +#define SHORT "short" +#define SHORTM "short~01" +#define EXT1 "ex1" +#define EXT2 "e2" +#define EXT3 "3" +#define EXTFAIL "longext" + +static void unmangle_test (char *name, char *ext) +{ + smb_ucs2_t ucs2_name[2048]; + smb_ucs2_t *retstr; + pstring unix_name; + + push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE); + if (ext) + { + strncat_wa(ucs2_name, ".", 1); + strncat_wa(ucs2_name, ext, strlen(ext)); + } + retstr = unmangle(ucs2_name); + if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE); + else unix_name[0] = 0; + if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name); + else printf ("[%s] ---> [%s]\n", name, unix_name); + SAFE_FREE(retstr); +} + +static void mangle_test (char *name, char *ext) +{ + smb_ucs2_t ucs2_name[2048]; + smb_ucs2_t *retstr; + pstring unix_name; + + push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE); + if (ext) + { + strncat_wa(ucs2_name, ".", 1); + strncat_wa(ucs2_name, ext, strlen(ext)); + } + retstr = _mangle(ucs2_name); + if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE); + else unix_name[0] = 0; + if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name); + else printf ("[%s] ---> [%s]\n", name, unix_name); + SAFE_FREE(retstr); +} + +void mangle_test_code(void) +{ + /* unmangle every */ + unmangle_test (LONG, NULL); + unmangle_test (LONG, EXT1); + unmangle_test (LONG, EXT2); + unmangle_test (LONG, EXT3); + unmangle_test (LONG, EXTFAIL); + + unmangle_test (LONGM, NULL); + unmangle_test (LONGM, EXT1); + unmangle_test (LONGM, EXT2); + unmangle_test (LONGM, EXT3); + unmangle_test (LONGM, EXTFAIL); + + unmangle_test (SHORT, NULL); + unmangle_test (SHORT, EXT1); + unmangle_test (SHORT, EXT2); + unmangle_test (SHORT, EXT3); + unmangle_test (SHORT, EXTFAIL); + + unmangle_test (SHORTM, NULL); + unmangle_test (SHORTM, EXT1); + unmangle_test (SHORTM, EXT2); + unmangle_test (SHORTM, EXT3); + unmangle_test (SHORTM, EXTFAIL); + + /* mangle every */ + mangle_test (LONG, NULL); + mangle_test (LONG, EXT1); + mangle_test (LONG, EXT2); + mangle_test (LONG, EXT3); + mangle_test (LONG, EXTFAIL); + + mangle_test (LONGM, NULL); + mangle_test (LONGM, EXT1); + mangle_test (LONGM, EXT2); + mangle_test (LONGM, EXT3); + mangle_test (LONGM, EXTFAIL); + + mangle_test (SHORT, NULL); + mangle_test (SHORT, EXT1); + mangle_test (SHORT, EXT2); + mangle_test (SHORT, EXT3); + mangle_test (SHORT, EXTFAIL); + + mangle_test (SHORTM, NULL); + mangle_test (SHORTM, EXT1); + mangle_test (SHORTM, EXT2); + mangle_test (SHORTM, EXT3); + mangle_test (SHORTM, EXTFAIL); + + /* unmangle again every */ + unmangle_test (LONG, NULL); + unmangle_test (LONG, EXT1); + unmangle_test (LONG, EXT2); + unmangle_test (LONG, EXT3); + unmangle_test (LONG, EXTFAIL); + + unmangle_test (LONGM, NULL); + unmangle_test (LONGM, EXT1); + unmangle_test (LONGM, EXT2); + unmangle_test (LONGM, EXT3); + unmangle_test (LONGM, EXTFAIL); + + unmangle_test (SHORT, NULL); + unmangle_test (SHORT, EXT1); + unmangle_test (SHORT, EXT2); + unmangle_test (SHORT, EXT3); + unmangle_test (SHORT, EXTFAIL); + + unmangle_test (SHORTM, NULL); + unmangle_test (SHORTM, EXT1); + unmangle_test (SHORTM, EXT2); + unmangle_test (SHORTM, EXT3); + unmangle_test (SHORTM, EXTFAIL); +} + +#endif /* TEST_MANGLE_CODE */ + -- cgit From 90841e8e13bd875cf419bbdfd6f2616c0673f937 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 29 Sep 2001 16:20:15 +0000 Subject: undef the code for now (This used to be commit 5ab220efd7a1532e11370cb0fc9854d610a7f3d7) --- source3/smbd/mangle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 84bf693011..ae0164e141 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -969,7 +969,7 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) -#if 1 +#if 0 #define MANGLE_TDB_VERSION "20010927" #define MANGLE_TDB_FILE_NAME "mangle.tdb" #define MANGLED_PREFIX "MANGLED_" @@ -1410,7 +1410,7 @@ done: #endif /* 0 */ -#if 1 /* TEST_MANGLE_CODE */ +#ifdef TEST_MANGLE_CODE #define LONG "this_is_a_long_file_name" #define LONGM "this_~01" -- cgit From 60d315cb725ea3dfab010808c4ff4181f1f30255 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 30 Sep 2001 04:28:43 +0000 Subject: Small changes to register_vuid ahead of a larger restructure. (This used to be commit 7802bc94e78932d24eb6658edc14d0d051246208) --- source3/smbd/password.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a05735b4d7..6f5c7508a4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -246,13 +246,13 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, /* Find all the groups this uid is in and store them. Used by become_user() */ - initialise_groups(unix_name, uid, gid); + initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid); get_current_groups( &vuser->n_groups, &vuser->groups); /* Create an NT_USER_TOKEN struct for this user. */ - vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups, guest); + vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, guest); - DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); + DEBUG(3,("uid %d registered to name %s\n",(int)vuser->uid,vuser->user.unix_name)); next_vuid++; num_validated_vuids++; -- cgit From c6d1e756649408412d72e5ad2789804b2908b6f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Oct 2001 10:54:11 +0000 Subject: - fix handling of 0 last_change_time and must_change_time - move the arbitrary 21 day timeout to local.h (This used to be commit 11075f543470c3283accce0246d0b2983420695a) --- source3/smbd/auth_smbpasswd.c | 63 ++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 8159ad988f..304e5be44b 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -204,7 +204,7 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",sampass->username)); /* Quit if the account was disabled. */ - if(acct_ctrl & ACB_DISABLED) { + if (acct_ctrl & ACB_DISABLED) { DEBUG(1,("Account for user '%s' was disabled.\n", sampass->username)); return NT_STATUS_ACCOUNT_DISABLED; } @@ -212,52 +212,53 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user /* Test account expire time */ kickoff_time = pdb_get_kickoff_time(sampass); - if (kickoff_time != (time_t)-1) { - if (time(NULL) > kickoff_time) { - DEBUG(1,("Account for user '%s' has expried.\n", sampass->username)); - DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); - return NT_STATUS_ACCOUNT_EXPIRED; - } + if (kickoff_time != 0 && time(NULL) > kickoff_time) { + DEBUG(1,("Account for user '%s' has expried.\n", sampass->username)); + DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); + return NT_STATUS_ACCOUNT_EXPIRED; } /* Test workstation. Workstation list is comma separated. */ workstation_list = strdup(pdb_get_workstations(sampass)); - if (workstation_list) { - if (*workstation_list) { - BOOL invalid_ws = True; - char *s = workstation_list; + if (!workstation_list) return NT_STATUS_NO_MEMORY; + + if (*workstation_list) { + BOOL invalid_ws = True; + char *s = workstation_list; - fstring tok; + fstring tok; - while (next_token(&s, tok, ",", sizeof(tok))) { - DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", - tok, user_info->wksta_name.str, user_info->wksta_name.len)); - if(strequal(tok, user_info->wksta_name.str)) { - invalid_ws = False; - break; - } + while (next_token(&s, tok, ",", sizeof(tok))) { + DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", + tok, user_info->wksta_name.str, user_info->wksta_name.len)); + if(strequal(tok, user_info->wksta_name.str)) { + invalid_ws = False; + break; } - - SAFE_FREE(workstation_list); - if (invalid_ws) - return NT_STATUS_INVALID_WORKSTATION; - } else { - SAFE_FREE(workstation_list); } + + SAFE_FREE(workstation_list); + if (invalid_ws) + return NT_STATUS_INVALID_WORKSTATION; } else { - return NT_STATUS_NO_MEMORY; + SAFE_FREE(workstation_list); } + { time_t must_change_time = pdb_get_pass_must_change_time(sampass); - if (must_change_time == 0) { - DEBUG(1,("Account for user '%s' must change password at next logon! (ie now).\n", sampass->username)); + time_t last_set_time = pdb_get_pass_last_set_time(sampass); + + /* check for immediate expiry "must change at next logon" */ + if (must_change_time == 0 && last_set_time != 0) { + DEBUG(1,("Account for user '%s' password must change!.\n", sampass->username)); return NT_STATUS_PASSWORD_MUST_CHANGE; } - if (must_change_time != (time_t)-1 && must_change_time < time(NULL)) { + /* check for expired password */ + if (must_change_time < time(NULL) && must_change_time != 0) { DEBUG(1,("Account for user '%s' password expired!.\n", sampass->username)); DEBUG(1,("Password expired at '%ld' unix time.\n", (long)must_change_time)); return NT_STATUS_PASSWORD_EXPIRED; @@ -265,12 +266,12 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user } if (acct_ctrl & ACB_DOMTRUST) { - DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n", sampass->username)); + DEBUG(2,("session_trust_account: Domain trust account %s denied by server\n", sampass->username)); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } if (acct_ctrl & ACB_SVRTRUST) { - DEBUG(0,("session_trust_account: Server trust account %s denied by server\n", sampass->username)); + DEBUG(2,("session_trust_account: Server trust account %s denied by server\n", sampass->username)); return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } -- cgit From cf2ec80d4e8733bbfd98d9737fa7e99712b72eb3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Oct 2001 13:07:46 +0000 Subject: honor the ACB_PWNOEXP flag in smbpasswd (This used to be commit 70b7c900c907c4620faa7d82845296298b3820ff) --- source3/smbd/auth_smbpasswd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 304e5be44b..835ade739f 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -246,8 +246,7 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user SAFE_FREE(workstation_list); } - - { + if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { time_t must_change_time = pdb_get_pass_must_change_time(sampass); time_t last_set_time = pdb_get_pass_last_set_time(sampass); -- cgit From dc1fc3ee8ec2199bc73bb5d7ec711c6800f61d65 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 2 Oct 2001 04:29:50 +0000 Subject: Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header. (This used to be commit 2d0922b0eabfdc0aaf1d0797482fef47ed7fde8e) --- source3/smbd/auth.c | 3 --- source3/smbd/auth_domain.c | 2 -- source3/smbd/auth_rhosts.c | 6 ------ source3/smbd/auth_server.c | 4 ---- source3/smbd/auth_smbpasswd.c | 5 ----- source3/smbd/auth_unix.c | 4 ---- source3/smbd/auth_util.c | 3 +-- source3/smbd/blocking.c | 2 +- source3/smbd/chgpasswd.c | 1 - source3/smbd/close.c | 2 -- source3/smbd/conn.c | 2 -- source3/smbd/connection.c | 3 --- source3/smbd/dfree.c | 3 --- source3/smbd/dir.c | 2 -- source3/smbd/dosmode.c | 2 -- source3/smbd/error.c | 2 -- source3/smbd/fileio.c | 2 -- source3/smbd/filename.c | 1 - source3/smbd/files.c | 2 -- source3/smbd/groupname.c | 2 -- source3/smbd/ipc.c | 1 - source3/smbd/lanman.c | 2 -- source3/smbd/mangle.c | 2 -- source3/smbd/message.c | 3 --- source3/smbd/negprot.c | 1 - source3/smbd/notify.c | 2 -- source3/smbd/notify_hash.c | 3 --- source3/smbd/notify_kernel.c | 1 - source3/smbd/nttrans.c | 1 - source3/smbd/open.c | 2 -- source3/smbd/oplock.c | 2 -- source3/smbd/oplock_irix.c | 1 - source3/smbd/oplock_linux.c | 2 -- source3/smbd/password.c | 1 - source3/smbd/pipes.c | 2 -- source3/smbd/process.c | 2 -- source3/smbd/quotas.c | 2 -- source3/smbd/reply.c | 1 - source3/smbd/sec_ctx.c | 1 - source3/smbd/server.c | 2 -- source3/smbd/service.c | 4 ---- source3/smbd/trans2.c | 1 - source3/smbd/uid.c | 2 -- source3/smbd/vfs.c | 2 -- 44 files changed, 2 insertions(+), 94 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 6aa2714b0b..e76324213e 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -23,8 +23,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /**************************************************************************** Check user is in correct domain if required ****************************************************************************/ @@ -257,4 +255,3 @@ BOOL password_ok(char *user, char *password, int pwlen) return False; } - diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index 111f0f143c..bcd41bacdb 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -22,8 +22,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - BOOL global_machine_password_needs_changing = False; /**************************************************************************** diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index e319d8d5f8..cd1bf57f86 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -21,9 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - - /**************************************************************************** Read the a hosts.equiv or .rhosts file and check if it allows this user from this machine. @@ -181,6 +178,3 @@ NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, return nt_status; } - - - diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index e4c91c4dcb..2574a52ef3 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -22,8 +22,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - extern pstring global_myname; /**************************************************************************** @@ -228,5 +226,3 @@ use this machine as the password server.\n")); return(nt_status); } - - diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 835ade739f..da223368b8 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -23,8 +23,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /**************************************************************************** core of smb password checking routine. ****************************************************************************/ @@ -319,6 +317,3 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ pdb_free_sam(&sampass); return nt_status; } - - - diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 0d73988d8a..2f9034e3e5 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /**************************************************************************** update the encrypted smbpasswd file from the plaintext username and password @@ -105,5 +103,3 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve return nt_status; } - - diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 1967c32b9a..d3b9aa7001 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -19,9 +19,8 @@ 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; +#include "includes.h" /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index cec1581254..a398a4c2a1 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -20,7 +20,7 @@ */ #include "includes.h" -extern int DEBUGLEVEL; + extern char *OutBuffer; /**************************************************************************** diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index de49083960..fbcefd6128 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -49,7 +49,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern struct passdb_ops pdb_ops; static BOOL check_oem_password(char *user, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c92e084759..5c8c7996f5 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /**************************************************************************** run a file if it is a magic script ****************************************************************************/ diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 08704927c5..f9d0ffc9bd 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /* set these to define the limits of the server. NOTE These are on a per-client basis. Thus any one machine can't connect to more than MAX_CONNECTIONS services, but any number of machines may connect at diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index e1b2bc071a..f6da678cb1 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -21,12 +21,9 @@ #include "includes.h" - extern fstring remote_machine; static TDB_CONTEXT *tdb; -extern int DEBUGLEVEL; - /**************************************************************************** Return the connection tdb context (used for message send all). ****************************************************************************/ diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 7848309a5e..51f0614941 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -21,9 +21,6 @@ #include "includes.h" - -extern int DEBUGLEVEL; - /**************************************************************************** normalise for DOS usage ****************************************************************************/ diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index c0c728fe8f..59c8f1e97b 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /* This module implements directory related functions for Samba. */ diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 639e365d1b..0f15ef25c2 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /**************************************************************************** change a dos mode to a unix mode base permission for files: diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 17606c62be..913f2ac266 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /* these can be set by some functions to override the error codes */ int unix_ERR_class=SMB_SUCCESS; int unix_ERR_code=0; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 003bee84ed..edf58d4a8e 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - static BOOL setup_write_cache(files_struct *, SMB_OFF_T); /**************************************************************************** diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 17fa35c0d7..5fdbef44fe 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -27,7 +27,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4273c205cd..8c7fa930e1 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - static int real_max_open_files; #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files)) diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index eb2931d2a5..7d3dce131a 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -22,10 +22,8 @@ #ifdef USING_GROUPNAME_MAP #include "includes.h" -extern int DEBUGLEVEL; extern DOM_SID global_sam_sid; - /************************************************************************** Groupname map functionality. The code loads a groupname map file and (currently) loads it into a linked list. This is slow and memory diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b1af01ff4c..93a69255c0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -28,7 +28,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern int max_send; extern fstring local_machine; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b7acfa5f32..088162c126 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -33,8 +33,6 @@ #endif #define CHECK_TYPES 0 -extern int DEBUGLEVEL; - extern fstring local_machine; extern pstring global_myname; extern fstring global_myworkgroup; diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index ae0164e141..1c46afaea2 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -52,7 +52,6 @@ * External Variables... */ -extern int DEBUGLEVEL; /* Global debug level. */ extern int case_default; /* Are conforming 8.3 names all upper or lower? */ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ @@ -1540,4 +1539,3 @@ void mangle_test_code(void) } #endif /* TEST_MANGLE_CODE */ - diff --git a/source3/smbd/message.c b/source3/smbd/message.c index f2e88352ee..7cc53e082c 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -27,9 +27,6 @@ #include "includes.h" /* look in server.c for some explanation of these variables */ -extern int DEBUGLEVEL; - - static char msgbuf[1600]; static int msgpos; static fstring msgfrom; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 82222e6725..e3a6701dce 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -21,7 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern int Protocol; extern int max_recv; extern fstring global_myworkgroup; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 68b51aeabb..999821354e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,8 +22,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - static struct cnotify_fns *cnotify; /**************************************************************************** diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 8157e1ff31..0c69dc7876 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -22,9 +22,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - - struct change_data { time_t last_check_time; /* time we last checked this entry */ time_t modify_time; /* Info from the directory we're monitoring. */ diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 4b84831550..f618700bf0 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -23,7 +23,6 @@ #if HAVE_KERNEL_CHANGE_NOTIFY -extern int DEBUGLEVEL; static VOLATILE sig_atomic_t fd_pending; static VOLATILE sig_atomic_t signals_received; static VOLATILE sig_atomic_t signals_processed; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c072a38474..2618a96913 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -21,7 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern int Protocol; extern int smb_read_error; extern int global_oplock_break; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6e6d5e1e83..3578a82f8f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -22,8 +22,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - extern userdom_struct current_user_info; extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c17e63384f..4e8e36b3aa 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /* Oplock ipc UDP socket. */ static int oplock_sock = -1; uint16 global_oplock_port = 0; diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index faf7e8e3c8..c6055fc329 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -22,7 +22,6 @@ #include "includes.h" #if HAVE_KERNEL_OPLOCKS_IRIX -extern int DEBUGLEVEL; static int oplock_pipe_write = -1; static int oplock_pipe_read = -1; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index c88441c8c6..8c4259ac53 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -23,8 +23,6 @@ #if HAVE_KERNEL_OPLOCKS_LINUX -extern int DEBUGLEVEL; - static VOLATILE sig_atomic_t signals_received; static VOLATILE sig_atomic_t signals_processed; static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal */ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6f5c7508a4..b074552567 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,7 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern struct in_addr ipzero; /* users from session setup */ diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 162ad1603d..9a911ed014 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -31,8 +31,6 @@ #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) -extern int DEBUGLEVEL; - extern struct pipe_id_info pipe_names[]; /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index acda7128ae..4b0da0b466 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - struct timeval smb_last_time; static char *InBuffer = NULL; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index cf21fd7043..76d1124aea 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -28,8 +28,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - #if defined(VXFS_QUOTA) /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dbd149afcf..334a48e338 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -29,7 +29,6 @@ /* look in server.c for some explanation of these variables */ extern int Protocol; -extern int DEBUGLEVEL; extern int max_send; extern int max_recv; extern char magic_char; diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 830e759d09..c053a611c2 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -21,7 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern struct current_user current_user; struct sec_ctx { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1e89bbab7e..a851a8656d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -34,8 +34,6 @@ int last_message = -1; /* a useful macro to debug the last message processed */ #define LAST_MESSAGE() smb_fn_name(last_message) -extern int DEBUGLEVEL; - extern pstring user_socket_options; #ifdef WITH_DFS diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 7119aa258e..69283d3bf5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - extern struct timeval smb_last_time; extern int case_default; extern BOOL case_preserve; @@ -740,5 +738,3 @@ void close_cnum(connection_struct *conn, uint16 vuid) } conn_free(conn); } - - diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 139b97d088..0941d9f692 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -23,7 +23,6 @@ #include "includes.h" -extern int DEBUGLEVEL; extern int Protocol; extern BOOL case_sensitive; extern int smb_read_error; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 9fe634a7e9..6afaf1493e 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /* what user is current? */ extern struct current_user current_user; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 60762a0155..05645f7b19 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -21,8 +21,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - /* Some structures to help us initialise the vfs operations table */ struct vfs_syminfo { -- cgit From facbdd692dc7d4b87fcc59b369ae445153146c13 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Oct 2001 21:58:09 +0000 Subject: Fixed up the change password bug when not using PAM. The problem is we were trying to use mask_match as a generic wildcard matcher for UNIX strings (like the password prompts). We can't do that - we need a unix_wild_match (re-added into lib/util.c) as the ms_fnmatch semantics for empty strings are completely wrong. This caused partial reads to be accepted as correct passwd change responses when they were not.... Also added paranioa test to stop passwd change being done as root with no %u in the passwd program string. Jeremy. (This used to be commit 9333bbeb7627c8b21a3eaeae1683c34e17d14bf0) --- source3/smbd/chgpasswd.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fbcefd6128..d2ee2f46fa 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -199,7 +199,7 @@ static int dochild(int master, char *slavedev, char *name, } stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); stermios.c_lflag |= ICANON; - stermios.c_oflag &= ~(ONLCR); + stermios.c_oflag &= ~(ONLCR); if (tcsetattr(0, TCSANOW, &stermios) < 0) { DEBUG(3, ("could not set attributes of pty\n")); @@ -231,14 +231,15 @@ static int expect(int master, char *issue, char *expected) int attempts, timeout, nread, len; BOOL match = False; - for (attempts = 0; attempts < 2; attempts++) - { - if (!strequal(issue, ".")) - { + for (attempts = 0; attempts < 2; attempts++) { + if (!strequal(issue, ".")) { if (lp_passwd_chat_debug()) DEBUG(100, ("expect: sending [%s]\n", issue)); - write(master, issue, strlen(issue)); + if ((len = write(master, issue, strlen(issue))) != strlen(issue)) { + DEBUG(2,("expect: (short) write returned %d\n", len )); + return False; + } } if (strequal(expected, ".")) @@ -250,29 +251,35 @@ static int expect(int master, char *issue, char *expected) while ((len = read_with_timeout(master, buffer + nread, 1, sizeof(buffer) - nread - 1, - timeout)) > 0) - { + timeout)) > 0) { nread += len; buffer[nread] = 0; - if ((match = (wild_match(expected, buffer) == 0))) - timeout = 200; + { + /* Eat leading/trailing whitespace before match. */ + pstring str; + pstrcpy( str, buffer); + trim_string( str, " ", " "); + + if ((match = (unix_wild_match(expected, str) == 0))) + timeout = 200; + } } if (lp_passwd_chat_debug()) - DEBUG(100, ("expect: expected [%s] received [%s]\n", - expected, buffer)); + DEBUG(100, ("expect: expected [%s] received [%s] match %s\n", + expected, buffer, match ? "yes" : "no" )); if (match) break; - if (len < 0) - { + if (len < 0) { DEBUG(2, ("expect: %s\n", strerror(errno))); return False; } } + DEBUG(10,("expect: returning %s\n", match ? "True" : "False" )); return match; } @@ -519,15 +526,24 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) pstrcpy(chatsequence, lp_passwd_chat()); if (!*chatsequence) { - DEBUG(2, ("Null chat sequence - no password changing\n")); + DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n")); return (False); } if (!*passwordprogram) { - DEBUG(2, ("Null password program - no password changing\n")); + DEBUG(2, ("chgpasswd: Null password program - no password changing\n")); return (False); } + if (as_root) { + /* The password program *must* contain the user name to work. Fail if not. */ + if (strstr(passwordprogram, "%u") == NULL) { + DEBUG(0,("chgpasswd: Running as root the 'passwd program' parameter *MUST* contain \ +the string %%u, and the given string %s does not.\n", passwordprogram )); + return False; + } + } + pstring_sub(passwordprogram, "%u", name); /* note that we do NOT substitute the %o and %n in the password program as this would open up a security hole where the user could use -- cgit From 9bcd133e9e7b0cfe974f273fb23409d660af8358 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Oct 2001 12:18:20 +0000 Subject: switched over to a new method of handling uppercase/lowercase mappings for unicode strings. The new method relies on 3 files that are mmap'd at startup to provide the mapping tables. The upcase.dat and lowcase.dat tables should be the same on all systems. The valid.dat table says what characters are valid in 8.3 names, and differs between systems. I'm committing the japanese valid.dat here, in future we need some way of automatically installing and choosing a appropriate table. This commit also adds my mini tdb based gettext replacement in intl/lang_tdb.c. I have not enabled this yet and have not removed the old gettext code as the new code is still being looked at by Monyo. Right now the code assumes that the upcase.dat, lowcase.dat and valid.dat files are installed in the Samba lib directory. That is not a good choice, but I'll leave them there until we work out the new install directory structure for Samba 3.0. simo - please look at the isvalid_w() function and think about using it in your new mangling code. That should be the final step to correctly passing the chargen test code from monyo. (This used to be commit 1c221994f118dd542a158b2db51e07d04d0e9314) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a851a8656d..f707a61376 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -663,6 +663,8 @@ static void usage(char *pname) sec_init(); + load_case_tables(); + append_log = True; TimeInit(); -- cgit From 44cc559418eec1eadc594c9bc35f00ae91ad55f9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 4 Oct 2001 08:32:29 +0000 Subject: init only in test code. remove unused structure for tdb data. fixes. (This used to be commit c82cf58ae2ae9790b8575328b419dbc8a089b60f) --- source3/smbd/mangle.c | 103 +++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 1c46afaea2..587e9cc906 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -968,7 +968,7 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) -#if 0 +#if 1 #define MANGLE_TDB_VERSION "20010927" #define MANGLE_TDB_FILE_NAME "mangle.tdb" #define MANGLED_PREFIX "MANGLED_" @@ -978,13 +978,7 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) #define MANGLE_SUFFIX_SIZE 2 -struct mt_enum_info { - TDB_CONTEXT *mangle_tdb; - TDB_DATA key; -}; - - -static struct mt_enum_info global_mt_ent = {0, 0}; +static TDB_CONTEXT *mangle_tdb; static int POW10(unsigned int exp) { @@ -998,20 +992,17 @@ static int POW10(unsigned int exp) return result; } -static BOOL init_mangle_tdb(void) +BOOL init_mangle_tdb(void) { char *tdbfile; - if (global_mt_ent.mangle_tdb == 0) - { - tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */ + tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */ - /* Open tdb */ - if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) - { - DEBUG(0, ("Unable to open Mangle TDB\n")); - return False; - } + /* Open tdb */ + if (!(mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) + { + DEBUG(0, ("Unable to open Mangle TDB\n")); + return False; } return True; @@ -1128,7 +1119,6 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) if (strlen_w(mangled) > 12) return NULL; if (!strchr_wa(mangled, '~')) return NULL; - if (!init_mangle_tdb()) return NULL; ret = mangle_get_prefix(mangled, &pref, &ext); if (!ret) return NULL; @@ -1143,11 +1133,11 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) key.dsize = strlen (keystr) + 1; /* get the record */ - data = tdb_fetch(global_mt_ent.mangle_tdb, key); + data = tdb_fetch(mangle_tdb, key); if (!data.dptr) /* not found */ { - DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(global_mt_ent.mangle_tdb))); + DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(mangle_tdb))); retstr = NULL; goto done; } @@ -1197,7 +1187,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) fstring mufname; fstring prefix; BOOL tclock = False; - char suffix[MANGLE_SUFFIX_SIZE + 1]; + char suffix[7]; smb_ucs2_t *mangled = NULL; smb_ucs2_t *um, *ext, *p = NULL; smb_ucs2_t temp[8]; @@ -1205,8 +1195,6 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) size_t um_len; uint32 n, c, pos; - if (!init_mangle_tdb()) return NULL; - /* TODO: if it is a path return a failure ?? */ if (!mangle_get_prefix(unmangled, &um, &ext)) return NULL; @@ -1219,13 +1207,13 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) key.dsize = strlen(keystr) + 1; /* get the record */ - data = tdb_fetch (global_mt_ent.mangle_tdb, key); + data = tdb_fetch (mangle_tdb, key); if (!data.dptr) /* not found */ { - if (tdb_error(global_mt_ent.mangle_tdb) != TDB_ERR_NOEXIST) + if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST) { DEBUG(0, ("mangle: database retrieval error: %s\n", - tdb_errorstr(global_mt_ent.mangle_tdb))); + tdb_errorstr(mangle_tdb))); goto done; } @@ -1242,6 +1230,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) goto done; } strncpy_w(temp, um, pos); + temp[pos] = 0; strlower_w(temp); ucs2_to_dos(NULL, prefix, temp, sizeof(prefix), 0, STR_TERMINATE); @@ -1259,29 +1248,44 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) fail (correct) otherwise it will create a new entry with counter set to 0 */ - tdb_store(global_mt_ent.mangle_tdb, klock, data, TDB_INSERT); + if(tdb_store(mangle_tdb, klock, data, TDB_INSERT) != TDB_SUCCESS) + { + if (tdb_error(mangle_tdb) != TDB_ERR_EXISTS) + { + DEBUG(0, ("mangle: database store error: %s\n", + tdb_errorstr(mangle_tdb))); + goto done; + } + } /* lock the mangle counter for this prefix */ - if (!tdb_chainlock(global_mt_ent.mangle_tdb, klock)) + if (tdb_chainlock(mangle_tdb, klock)) { DEBUG(0,("mangle: failed to lock database\n!")); goto done; } tclock = True; - data = tdb_fetch(global_mt_ent.mangle_tdb, klock); + data = tdb_fetch(mangle_tdb, klock); if (!data.dptr) { DEBUG(0, ("mangle: database retrieval error: %s\n", - tdb_errorstr(global_mt_ent.mangle_tdb))); + tdb_errorstr(mangle_tdb))); goto done; } c = *((uint32 *)data.dptr); c++; + + if (c > MANGLE_COUNTER_MAX) + { + DEBUG(0, ("mangle: error, counter overflow!\n")); + goto done; + } temp[pos] = UCS2_CHAR('~'); temp[pos+1] = 0; - snprintf(suffix, MANGLE_SUFFIX_SIZE + 1, "%.6d", c); + snprintf(suffix, 7, "%.6d", c); + printf("[%s]\n", suffix); strncat_wa(temp, &suffix[6 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE + 1); ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); @@ -1298,10 +1302,10 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) data.dsize = (strlen_w(um) + 1) * sizeof (smb_ucs2_t); data.dptr = (void *)um; - if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) + if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) { DEBUG(0, ("mangle: database store error: %s\n", - tdb_errorstr(global_mt_ent.mangle_tdb))); + tdb_errorstr(mangle_tdb))); goto done; } @@ -1312,16 +1316,16 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) key.dsize = strlen (keystr) + 1; data.dsize = strlen(mufname +1); data.dptr = mufname; - if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) + if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) { - DEBUG(0, ("mangle: store failed: %s\n", - tdb_errorstr(global_mt_ent.mangle_tdb))); + DEBUG(0, ("mangle: database store failed: %s\n", + tdb_errorstr(mangle_tdb))); /* try to delete the mangled key entry to avoid later inconsistency */ slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - if (!tdb_delete(global_mt_ent.mangle_tdb, key)) + if (!tdb_delete(mangle_tdb, key)) { DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); } @@ -1337,22 +1341,23 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) data.dptr = (char *)&c; data.dsize = sizeof(uint32); - if(!tdb_store(global_mt_ent.mangle_tdb, klock, data, TDB_INSERT)) + /* store the counter */ + if(tdb_store(mangle_tdb, klock, data, TDB_REPLACE) != TDB_SUCCESS) { - DEBUG(0, ("mangle: store failed: %s\n", - tdb_errorstr(global_mt_ent.mangle_tdb))); + DEBUG(0, ("mangle: database store failed: %s\n", + tdb_errorstr(mangle_tdb))); /* try to delete the mangled and long key entry to avoid later inconsistency */ slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - if (!tdb_delete(global_mt_ent.mangle_tdb, key)) + if (!tdb_delete(mangle_tdb, key)) { DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); } slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - if (!tdb_delete(global_mt_ent.mangle_tdb, key)) + if (!tdb_delete(mangle_tdb, key)) { DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); } @@ -1360,7 +1365,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) } tclock = False; - tdb_chainunlock(global_mt_ent.mangle_tdb, klock); + tdb_chainunlock(mangle_tdb, klock); } else /* FOUND */ { @@ -1399,7 +1404,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) } done: - if (tclock) tdb_chainunlock(global_mt_ent.mangle_tdb, klock); + if (tclock) tdb_chainunlock(mangle_tdb, klock); SAFE_FREE(p); SAFE_FREE(um); SAFE_FREE(ext); @@ -1409,7 +1414,7 @@ done: #endif /* 0 */ -#ifdef TEST_MANGLE_CODE +#if 1 /* TEST_MANGLE_CODE */ #define LONG "this_is_a_long_file_name" #define LONGM "this_~01" @@ -1430,7 +1435,7 @@ static void unmangle_test (char *name, char *ext) if (ext) { strncat_wa(ucs2_name, ".", 1); - strncat_wa(ucs2_name, ext, strlen(ext)); + strncat_wa(ucs2_name, ext, strlen(ext) + 1); } retstr = unmangle(ucs2_name); if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE); @@ -1450,7 +1455,7 @@ static void mangle_test (char *name, char *ext) if (ext) { strncat_wa(ucs2_name, ".", 1); - strncat_wa(ucs2_name, ext, strlen(ext)); + strncat_wa(ucs2_name, ext, strlen(ext) + 1); } retstr = _mangle(ucs2_name); if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE); @@ -1462,6 +1467,8 @@ static void mangle_test (char *name, char *ext) void mangle_test_code(void) { + init_mangle_tdb(); + /* unmangle every */ unmangle_test (LONG, NULL); unmangle_test (LONG, EXT1); -- cgit From 36c7d52ed8997739008156239af570c46feb3aed Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 6 Oct 2001 01:51:57 +0000 Subject: Fix up indenting in out SAM password check code. (This used to be commit ac11a23125270dd136290370b1cf0124e943a101) --- source3/smbd/auth_smbpasswd.c | 95 ++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index da223368b8..26b9001bf6 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -127,61 +127,64 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username)); return(NT_STATUS_LOGON_FAILURE); } - } else { - nt_pw = pdb_get_nt_passwd(sampass); - lm_pw = pdb_get_lanman_passwd(sampass); - - if (nt_pw != NULL && user_info->nt_resp.len > 0) { - if ((user_info->nt_resp.len > 24 )) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, - user_info->nt_resp.len, - nt_pw, - user_info->chal, user_info->smb_username.str, - user_info->requested_domain.str, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); + } + + nt_pw = pdb_get_nt_passwd(sampass); + lm_pw = pdb_get_lanman_passwd(sampass); + + if (nt_pw != NULL && user_info->nt_resp.len > 0) { + if ((user_info->nt_resp.len > 24 )) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); + if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, + user_info->nt_resp.len, + nt_pw, + user_info->chal, user_info->smb_username.str, + user_info->requested_domain.str, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); return NT_STATUS_WRONG_PASSWORD; - } + } - } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24)) { + } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24)) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, - nt_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, + nt_pw, user_info->chal, + user_sess_key)) + { + return NT_STATUS_OK; } else { - return NT_STATUS_LOGON_FAILURE; - } - } else if (lm_pw != NULL && user_info->lm_resp.len == 24) { - if (lp_lanman_auth()) { - DEBUG(4,("smb_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, - lm_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: LM password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } + DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; } + } else { + return NT_STATUS_LOGON_FAILURE; + } + } + + if (lm_pw != NULL && user_info->lm_resp.len == 24) { + if (lp_lanman_auth()) { + DEBUG(4,("smb_password_ok: Checking LM password\n")); + if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, + lm_pw, user_info->chal, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: LM password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; + } } } + /* Should not be reached */ return NT_STATUS_LOGON_FAILURE; } -- cgit From 494bb7b980a6bd5fce16097030d43cc0659594b8 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 7 Oct 2001 14:53:40 +0000 Subject: more fixing and testing. added ucs2_to_dos83 function. the code should be ok now. further test with japanese and other languages is needed at this point. (This used to be commit 74f746fee2e528e4f23192e21e1d74739dc1072e) --- source3/smbd/mangle.c | 137 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 587e9cc906..386b948899 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1008,11 +1008,11 @@ BOOL init_mangle_tdb(void) return True; } -/* see push_ucs2 */ -int dos_to_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, int flags) +/* trasform a dos charset string in a terminated unicode string */ +static int dos_to_ucs2(void *dest, const char *src, int dest_len) { int len=0; - int src_len = strlen(src); + int src_len = strlen(src) + 1; pstring tmpbuf; /* treat a pstring as "unlimited" length */ @@ -1020,55 +1020,62 @@ int dos_to_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, dest_len = sizeof(pstring); } - if (flags & STR_UPPER) { - pstrcpy(tmpbuf, src); - strupper(tmpbuf); - src = tmpbuf; - } - - if (flags & STR_TERMINATE) { - src_len++; - } - - if (ucs2_align(base_ptr, dest, flags)) { - *(char *)dest = 0; - dest = (void *)((char *)dest + 1); - if (dest_len) dest_len--; - len++; - } - /* ucs2 is always a multiple of 2 bytes */ dest_len &= ~1; - len += convert_string(CH_DOS, CH_UCS2, src, src_len, dest, dest_len); + len = convert_string(CH_DOS, CH_UCS2, src, src_len, dest, dest_len); return len; } -/* see pull_ucs2 */ -int ucs2_to_dos(const void *base_ptr, char *dest, const void *src, int dest_len, int src_len, int flags) +/* trasform a unicode string into a dos charset string */ +static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len) { - int ret; + int src_len, ret; if (dest_len == -1) { dest_len = sizeof(pstring); } - if (ucs2_align(base_ptr, src, flags)) { - src = (const void *)((char *)src + 1); - if (src_len > 0) src_len--; - } - - if (flags & STR_TERMINATE) src_len = strlen_w(src)*2+2; - - /* ucs2 is always a multiple of 2 bytes */ - src_len &= ~1; + src_len = strlen_w(src) * sizeof(smb_ucs2_t); ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len); if (dest_len) dest[MIN(ret, dest_len-1)] = 0; - return src_len; + return ret; +} + +/* trasform a ucs2 string in a dos charset string that contain only valid chars for 8.3 filenames */ +static int ucs2_to_dos83(char *dest, const smb_ucs2_t *src, int dest_len) +{ + int src_len, u2s_len, ret; + smb_ucs2_t *u2s; + + u2s = (smb_ucs2_t *)malloc((strlen_w(src) + 1) * sizeof(smb_ucs2_t)); + if (!u2s) { + DEBUG(0, ("ucs2_to_dos83: out of memory!\n")); + return 0; + } + + src_len = strlen_w(src); + + u2s[src_len] = 0; + while (src_len--) + { + smb_ucs2_t c; + + c = src[src_len]; + if (isvalid83_w(c)) u2s[src_len] = c; + else u2s[src_len] = UCS2_CHAR('_'); + } + + ret = ucs2_to_dos(dest, u2s, dest_len); + + SAFE_FREE(u2s); + + return ret; } + /* return False if something fail and * return 2 alloced unicode strings that contain prefix and extension */ @@ -1076,6 +1083,7 @@ static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix { size_t str_len; smb_ucs2_t *p; + fstring ext; *extension = 0; *prefix = strdup_w(ucs2_string); @@ -1084,14 +1092,13 @@ static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix DEBUG(0,("mangle_get_prefix: out of memory!\n")); return False; } - str_len = strlen_w(*prefix); if (p = strrchr_wa(*prefix, '.')) { - /* TODO: check it is <4 in dos charset */ - if ((str_len - ((p - *prefix) / sizeof(smb_ucs2_t))) < 4) /* check extension */ + p++; + str_len = ucs2_to_dos83(ext, p, sizeof(ext)); + if (str_len > 0 && str_len < 4) /* check extension */ { - *p = 0; - p++; + *(p - 1) = 0; *extension = strdup_w(p); if (!*extension) { @@ -1114,7 +1121,7 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) fstring keystr; fstring mufname; smb_ucs2_t *pref, *ext, *retstr; - size_t long_len, ext_len; + size_t long_len, ext_len, muf_len; BOOL ret; if (strlen_w(mangled) > 12) return NULL; @@ -1126,8 +1133,10 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) /* TODO: get out extension */ strlower_w(pref); /* set search key */ - ucs2_to_dos(NULL, mufname, pref, sizeof(mufname), 0, STR_TERMINATE); + muf_len = ucs2_to_dos(mufname, pref, sizeof(mufname)); SAFE_FREE(pref); + if (!muf_len) return NULL; + slprintf(keystr, sizeof(keystr) - 1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; @@ -1144,9 +1153,9 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) if (ext) { - long_len = data.dsize / 2; /* terminator counted on purpose, will contain '.' */ + long_len = (data.dsize / 2) - 1; ext_len = strlen_w(ext); - retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 1)*sizeof(smb_ucs2_t)); + retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 2)*sizeof(smb_ucs2_t)); if (!retstr) { DEBUG(0, ("unamngle: out of memory!\n")); @@ -1190,8 +1199,8 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) char suffix[7]; smb_ucs2_t *mangled = NULL; smb_ucs2_t *um, *ext, *p = NULL; - smb_ucs2_t temp[8]; - size_t pref_len, ext_len; + smb_ucs2_t temp[9]; + size_t pref_len, ext_len, ud83_len; size_t um_len; uint32 n, c, pos; @@ -1233,9 +1242,10 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) temp[pos] = 0; strlower_w(temp); - ucs2_to_dos(NULL, prefix, temp, sizeof(prefix), 0, STR_TERMINATE); + ud83_len = ucs2_to_dos83(prefix, temp, sizeof(prefix)); + if (!ud83_len) goto done; } - while (strlen(prefix) > 8 - (MANGLE_SUFFIX_SIZE + 1)); + while (ud83_len > 8 - (MANGLE_SUFFIX_SIZE + 1)); slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix); klock.dptr = keylock; @@ -1285,11 +1295,11 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) temp[pos] = UCS2_CHAR('~'); temp[pos+1] = 0; snprintf(suffix, 7, "%.6d", c); - printf("[%s]\n", suffix); strncat_wa(temp, &suffix[6 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE + 1); - ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); - if (strlen(mufname) > 8) + ud83_len = ucs2_to_dos(mufname, temp, sizeof(mufname)); + if (!ud83_len) goto done; + if (ud83_len > 8) { DEBUG(0, ("mangle: darn, logic error aborting!\n")); goto done; @@ -1314,7 +1324,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - data.dsize = strlen(mufname +1); + data.dsize = strlen(mufname) + 1; data.dptr = mufname; if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) { @@ -1375,14 +1385,14 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) DEBUG(0,("mangle: out of memory!\n")); goto done; } - dos_to_ucs2(NULL, p, data.dptr, data.dsize*sizeof(smb_ucs2_t), STR_TERMINATE); + dos_to_ucs2(p, data.dptr, data.dsize*sizeof(smb_ucs2_t)); } if (ext) { - pref_len = strlen_w(p) + 1; /* terminator counted on purpose, will contain '.' */ + pref_len = strlen_w(p); ext_len = strlen_w(ext); - mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 1)*sizeof(smb_ucs2_t)); + mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 2)*sizeof(smb_ucs2_t)); if (!mangled) { DEBUG(0,("mangle: out of memory!\n")); @@ -1424,6 +1434,7 @@ done: #define EXT2 "e2" #define EXT3 "3" #define EXTFAIL "longext" +#define EXTNULL "" static void unmangle_test (char *name, char *ext) { @@ -1470,79 +1481,97 @@ void mangle_test_code(void) init_mangle_tdb(); /* unmangle every */ + printf("Unmangle test 1:\n"); + unmangle_test (LONG, NULL); unmangle_test (LONG, EXT1); unmangle_test (LONG, EXT2); unmangle_test (LONG, EXT3); unmangle_test (LONG, EXTFAIL); + unmangle_test (LONG, EXTNULL); unmangle_test (LONGM, NULL); unmangle_test (LONGM, EXT1); unmangle_test (LONGM, EXT2); unmangle_test (LONGM, EXT3); unmangle_test (LONGM, EXTFAIL); + unmangle_test (LONGM, EXTNULL); unmangle_test (SHORT, NULL); unmangle_test (SHORT, EXT1); unmangle_test (SHORT, EXT2); unmangle_test (SHORT, EXT3); unmangle_test (SHORT, EXTFAIL); + unmangle_test (SHORT, EXTNULL); unmangle_test (SHORTM, NULL); unmangle_test (SHORTM, EXT1); unmangle_test (SHORTM, EXT2); unmangle_test (SHORTM, EXT3); unmangle_test (SHORTM, EXTFAIL); + unmangle_test (SHORTM, EXTNULL); /* mangle every */ + printf("Mangle test\n"); + mangle_test (LONG, NULL); mangle_test (LONG, EXT1); mangle_test (LONG, EXT2); mangle_test (LONG, EXT3); mangle_test (LONG, EXTFAIL); + mangle_test (LONG, EXTNULL); mangle_test (LONGM, NULL); mangle_test (LONGM, EXT1); mangle_test (LONGM, EXT2); mangle_test (LONGM, EXT3); mangle_test (LONGM, EXTFAIL); + mangle_test (LONGM, EXTNULL); mangle_test (SHORT, NULL); mangle_test (SHORT, EXT1); mangle_test (SHORT, EXT2); mangle_test (SHORT, EXT3); mangle_test (SHORT, EXTFAIL); + mangle_test (SHORT, EXTNULL); mangle_test (SHORTM, NULL); mangle_test (SHORTM, EXT1); mangle_test (SHORTM, EXT2); mangle_test (SHORTM, EXT3); mangle_test (SHORTM, EXTFAIL); + mangle_test (SHORTM, EXTNULL); /* unmangle again every */ + printf("Unmangle test 2:\n"); + unmangle_test (LONG, NULL); unmangle_test (LONG, EXT1); unmangle_test (LONG, EXT2); unmangle_test (LONG, EXT3); unmangle_test (LONG, EXTFAIL); + unmangle_test (LONG, EXTNULL); unmangle_test (LONGM, NULL); unmangle_test (LONGM, EXT1); unmangle_test (LONGM, EXT2); unmangle_test (LONGM, EXT3); unmangle_test (LONGM, EXTFAIL); + unmangle_test (LONGM, EXTNULL); unmangle_test (SHORT, NULL); unmangle_test (SHORT, EXT1); unmangle_test (SHORT, EXT2); unmangle_test (SHORT, EXT3); unmangle_test (SHORT, EXTFAIL); + unmangle_test (SHORT, EXTNULL); unmangle_test (SHORTM, NULL); unmangle_test (SHORTM, EXT1); unmangle_test (SHORTM, EXT2); unmangle_test (SHORTM, EXT3); unmangle_test (SHORTM, EXTFAIL); + unmangle_test (SHORTM, EXTNULL); } #endif /* TEST_MANGLE_CODE */ -- cgit From d02b5fefba169ad6cdcbbaf01769113481692f38 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 8 Oct 2001 11:58:25 +0000 Subject: tim suggested to add a copyright note :) (This used to be commit c0bb484e0fcdfece62d361aaaebd90cf15548992) --- source3/smbd/mangle.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 386b948899..b9db4b0c2d 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -966,7 +966,27 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) - +/* -------------------------------------------------------------------- */ +/* + Unix SMB/Netbios implementation. + Version 3.0 + Name mangling with persistent tdb + Copyright (C) Simo Sorce 2001 + + 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. +*/ #if 1 #define MANGLE_TDB_VERSION "20010927" -- cgit From ed94aa9d611aba4d82e717797565550a4a47270e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Oct 2001 20:54:56 +0000 Subject: Fixes from John Trostel (modified somewhat by me) to ensure that all lookup_XX functions correctly deal with the SID_NAME_TYPE. One fix for connection user lookup in LSA. Jeremy. (This used to be commit 29730027d8118ec7d207c89d0fd7fb24ac173fde) --- source3/smbd/uid.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 6afaf1493e..45ae31da2a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -277,7 +277,9 @@ BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) fstring sid; char *sep = lp_winbind_separator(); - if (!winbind_lookup_name(name, psid, name_type)) { + *name_type = SID_NAME_UNKNOWN; + + if (!winbind_lookup_name(name, psid, name_type) || (*name_type != SID_NAME_USER) ) { BOOL ret; DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name)); @@ -293,21 +295,19 @@ BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: - if (strequal(domain, global_myworkgroup)) + if (strequal(domain, global_myworkgroup)) { fstrcpy(domain, global_myname); + ret = local_lookup_name(domain, username, psid, name_type); + } /* No break is deliberate here. JRA. */ default: if (strcasecmp(global_myname, domain) != 0) { - DEBUG(5, ("domain %s is not local\n", domain)); - return False; + DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); + ret = local_lookup_name(global_myname, username, psid, name_type); } } - - ret = local_lookup_name(domain, username, psid, - name_type); } else { - ret = local_lookup_name(global_myname, name, psid, - name_type); + ret = local_lookup_name(global_myname, name, psid, name_type); } if (ret) { @@ -322,9 +322,9 @@ BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) return ret; } - DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", - name, sid_to_string(sid, psid), - (unsigned int)*name_type)); + DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", + name, sid_to_string(sid, psid), + (unsigned int)*name_type)); return True; } @@ -338,6 +338,8 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE if (!name_type) return False; + *name_type = SID_NAME_UNKNOWN; + /* Check if this is our own sid. This should perhaps be done by winbind? For the moment handle it here. */ @@ -418,7 +420,7 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) *THE CANONICAL* convert SID to uid function. Tries winbind first - then uses local lookup. Returns True if this name is a user sid and the conversion - was done correctly, False if not. + was done correctly, False if not. sidtype is set by this function. *****************************************************************/ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) @@ -432,7 +434,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) * First we must look up the name and decide if this is a user sid. */ - if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) { DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", sid_to_string(sid_str, psid) )); -- cgit From 89731dce4a84e840b384fc4c5d21e3f10cfb8d39 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 10 Oct 2001 01:01:15 +0000 Subject: Fixed some compile warnings. (This used to be commit c9b3e6c71401efe754c10f7077671f0c1cebdafb) --- source3/smbd/mangle.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index b9db4b0c2d..a28cfe0931 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1033,7 +1033,6 @@ static int dos_to_ucs2(void *dest, const char *src, int dest_len) { int len=0; int src_len = strlen(src) + 1; - pstring tmpbuf; /* treat a pstring as "unlimited" length */ if (dest_len == -1) { @@ -1067,7 +1066,7 @@ static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len) /* trasform a ucs2 string in a dos charset string that contain only valid chars for 8.3 filenames */ static int ucs2_to_dos83(char *dest, const smb_ucs2_t *src, int dest_len) { - int src_len, u2s_len, ret; + int src_len, ret; smb_ucs2_t *u2s; u2s = (smb_ucs2_t *)malloc((strlen_w(src) + 1) * sizeof(smb_ucs2_t)); @@ -1112,7 +1111,7 @@ static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix DEBUG(0,("mangle_get_prefix: out of memory!\n")); return False; } - if (p = strrchr_wa(*prefix, '.')) + if ((p = strrchr_wa(*prefix, '.'))) { p++; str_len = ucs2_to_dos83(ext, p, sizeof(ext)); @@ -1221,7 +1220,6 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) smb_ucs2_t *um, *ext, *p = NULL; smb_ucs2_t temp[9]; size_t pref_len, ext_len, ud83_len; - size_t um_len; uint32 n, c, pos; /* TODO: if it is a path return a failure ?? */ -- cgit From 76745313b16c07092b0198da4d4fc05b38e600f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Oct 2001 05:53:15 +0000 Subject: Fixed bug when status=no and max smbd processes > 0. Jeremy. (This used to be commit d1adaee373f08020d350af2aa65b7651da94bdae) --- source3/smbd/process.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4b0da0b466..4b7e80811c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -804,6 +804,12 @@ static BOOL smbd_process_limit(void) total_smbds = 1; /* In case we need to create the entry. */ + if (!conn_tdb_ctx()) { + DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \ +set. Ignoring max smbd restriction.\n")); + return False; + } + if (tdb_change_int_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1) return True; -- cgit From 81f56139b6964ddbe2c03232475f87f474136490 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Oct 2001 07:42:52 +0000 Subject: initial kerberos/ADS/SPNEGO support in libsmb and smbclient. To activate you need to: - install krb5 libraries - run configure - build smbclient - run kinit to get a TGT - run smbclient with the -k option to choose kerberos auth (This used to be commit d33057585644e1337bac743e25ed7653bfb39eef) --- source3/smbd/negprot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e3a6701dce..d20f713113 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -128,8 +128,8 @@ static int reply_lanman2(char *outbuf) if (!cli) { generate_next_challenge(cryptkey); } else { - memcpy(cryptkey, cli->cryptkey, 8); - set_challenge(cli->cryptkey); + memcpy(cryptkey, cli->secblob.data, 8); + set_challenge(cryptkey); } } @@ -191,8 +191,8 @@ static int reply_nt1(char *outbuf) if (!cli) { generate_next_challenge(cryptkey); } else { - memcpy(cryptkey, cli->cryptkey, 8); - set_challenge(cli->cryptkey); + memcpy(cryptkey, cli->secblob.data, 8); + set_challenge(cryptkey); } } -- cgit From 49307c26789b3061780d160f4c6fa4863853eddd Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 11 Oct 2001 12:33:26 +0000 Subject: remove unused function in mangle.c fix some alloc leaks spotted by andreas moroder. (This used to be commit 39409a20f69078709c63f6f867c042e66d5c7de3) --- source3/smbd/mangle.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index a28cfe0931..7d8d68c9e2 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1000,18 +1000,6 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) static TDB_CONTEXT *mangle_tdb; -static int POW10(unsigned int exp) -{ - int result = 1; - - while (exp) { - result *= 10; - exp--; - } - - return result; -} - BOOL init_mangle_tdb(void) { char *tdbfile; -- cgit From cf167fe3c5890986caea50ef2ddfabf257749058 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 11 Oct 2001 16:44:17 +0000 Subject: merge from 2.2 (This used to be commit 062bba07f2faedfce7612c8b4a16072fa200349e) --- source3/smbd/ssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index c45afc52d5..349ca34f95 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -118,13 +118,13 @@ char *egdsocket, *entropyfile; if(lp_ssl_compatibility()){ SSL_CTX_set_options(sslContext, SSL_OP_ALL); } - certfile = isServer ? lp_ssl_cert() : lp_ssl_client_cert(); + certfile = isServer ? lp_ssl_server_cert() : lp_ssl_client_cert(); if((certfile == NULL || *certfile == 0) && isServer){ fprintf(stderr, "SSL: No cert file specified in config file!\n"); fprintf(stderr, "The server MUST have a certificate!\n"); exit(1); } - keyfile = isServer ? lp_ssl_privkey() : lp_ssl_client_privkey(); + keyfile = isServer ? lp_ssl_server_privkey() : lp_ssl_client_privkey(); if(keyfile == NULL || *keyfile == 0) keyfile = certfile; if(certfile != NULL && *certfile != 0){ -- cgit From 2f7ce531ada2b7c7d09ab6a976b53ce40e6135be Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 12 Oct 2001 06:09:39 +0000 Subject: fixed compiler warning. (This used to be commit 2d5b0f7ad865f92668954f87fd3b116a7abffa10) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 45ae31da2a..39bdaaa596 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -280,7 +280,7 @@ BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) *name_type = SID_NAME_UNKNOWN; if (!winbind_lookup_name(name, psid, name_type) || (*name_type != SID_NAME_USER) ) { - BOOL ret; + BOOL ret = False; DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name)); -- cgit From 812dcab195504301faea7443f1cb900dea57a823 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Oct 2001 22:00:38 +0000 Subject: Made nt acl support a local parameter for w2ksp2 profile fix. Jeremy. (This used to be commit ebba334c15619610475a5c8242a55ed4fcdedf7c) --- source3/smbd/nttrans.c | 80 ++++++++++++++++++++++++++++++++++---------------- source3/smbd/trans2.c | 2 +- 2 files changed, 55 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2618a96913..1d8d2bae3e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1463,6 +1463,23 @@ static int call_nt_transact_rename(connection_struct *conn, return -1; } +/****************************************************************************** + Fake up a completely empty SD. +*******************************************************************************/ + +static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) +{ + extern DOM_SID global_sid_World; + size_t sd_size; + + *ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size); + if(!*ppsd) { + DEBUG(0,("get_null_nt_acl: Unable to malloc space for security descriptor.\n")); + sd_size = 0; + } + + return sd_size; +} /**************************************************************************** Reply to query a security descriptor - currently this is not implemented (it @@ -1496,12 +1513,24 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, *ppparams = params; + if ((mem_ctx = talloc_init()) == NULL) { + DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); + return ERROR_DOS(ERRDOS,ERRnomem); + } + /* * Get the permissions to return. */ - if((sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd)) == 0) + if (!lp_nt_acl_support(SNUM(conn))) + sd_size = get_null_nt_acl(mem_ctx, &psd); + else + sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + + if (sd_size == 0) { + talloc_destroy(mem_ctx); return(UNIXERROR(ERRDOS,ERRnoaccess)); + } DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size)); @@ -1511,6 +1540,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); + talloc_destroy(mem_ctx); return -1; } @@ -1520,6 +1550,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, data = Realloc(*ppdata, sd_size); if(data == NULL) { + talloc_destroy(mem_ctx); return ERROR_DOS(ERRDOS,ERRnomem); } @@ -1531,11 +1562,6 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Init the parse struct we will marshall into. */ - if ((mem_ctx = talloc_init()) == NULL) { - DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - return ERROR_DOS(ERRDOS,ERRnomem); - } - prs_init(&pd, 0, mem_ctx, MARSHALL); /* @@ -1578,34 +1604,36 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); - char *params= *ppparams; - char *data = *ppdata; - uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); - files_struct *fsp = NULL; - uint32 security_info_sent = 0; - int error_class; - uint32 error_code; + uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); + char *params= *ppparams; + char *data = *ppdata; + uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); + files_struct *fsp = NULL; + uint32 security_info_sent = 0; + int error_class; + uint32 error_code; - if(!lp_nt_acl_support()) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if(total_parameter_count < 8) + return ERROR_DOS(ERRDOS,ERRbadfunc); - if(total_parameter_count < 8) - return ERROR_DOS(ERRDOS,ERRbadfunc); + if((fsp = file_fsp(params,0)) == NULL) + return ERROR_DOS(ERRDOS,ERRbadfid); - if((fsp = file_fsp(params,0)) == NULL) - return ERROR_DOS(ERRDOS,ERRbadfid); + if(!lp_nt_acl_support(SNUM(conn))) + goto done; - security_info_sent = IVAL(params,4); + security_info_sent = IVAL(params,4); - DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, - (unsigned int)security_info_sent )); + DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, + (unsigned int)security_info_sent )); - if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code)) + if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code)) return ERROR_DOS(error_class, error_code); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); - return -1; + done: + + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + return -1; } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0941d9f692..9b0fd379cf 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1159,7 +1159,7 @@ static int call_trans2qfsinfo(connection_struct *conn, case SMB_QUERY_FS_ATTRIBUTE_INFO: SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| FILE_DEVICE_IS_MOUNTED| - (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ + (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE); SIVAL(pdata,8,len); -- cgit From b7bd7ea153bfd692a54e4eb7135c3ca33292f636 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 13 Oct 2001 12:47:59 +0000 Subject: introduce mangle backward compatibility functions add talloc_asprintf() (This used to be commit 7264d611eff871f424d449e1ff1c7ec3f5fdde40) --- source3/smbd/mangle.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 7d8d68c9e2..7139cb7f44 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -55,6 +55,7 @@ extern int case_default; /* Are conforming 8.3 names all upper or lower? */ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ + /* -------------------------------------------------------------------------- ** * Other stuff... * @@ -111,6 +112,13 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ char magic_char = '~'; + +#if 1 + + + + + static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; #define MANGLE_BASE ( (sizeof(basechars)/sizeof(char)) - 1 ) @@ -964,6 +972,9 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) return(True); } /* name_map_mangle */ +#endif + + /* -------------------------------------------------------------------- */ @@ -988,7 +999,8 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if 1 +#if 0 + #define MANGLE_TDB_VERSION "20010927" #define MANGLE_TDB_FILE_NAME "mangle.tdb" #define MANGLED_PREFIX "MANGLED_" @@ -1428,9 +1440,142 @@ done: return mangled; } + + + +/* backward compatibility functions */ + +BOOL is_mangled(char *s) +{ + smb_ucs2_t *u2, *res; + size_t u2len; + BOOL ret = False; + + u2len = (strlen(s) + 1) * sizeof(smb_ucs2_t); + u2 = (smb_ucs2_t *)malloc(u2len); + if (!u2) + { + DEBUG(0,("is_mangled: out of memory!\n")); + return ret; + } + dos_to_ucs2(u2, s, u2len); + + res = unmangle(u2); + if (res) ret = True; + SAFE_FREE(res); + SAFE_FREE(u2); + return ret; +} + +BOOL is_8_3(char *fname, BOOL check_case) +{ + smb_ucs2_t *u2, *pref = 0, *ext = 0; + char *s1 = 0, *s2; + size_t u2len; + BOOL ret = False; + + u2len = (strlen(fname) + 1) * sizeof(smb_ucs2_t); + u2 = (smb_ucs2_t *)malloc(u2len); + if (!u2) + { + DEBUG(0,("is_8_3: out of memory!\n")); + goto done; + } + s1 = (char *) malloc(u2len * 2); + if (!s1) + { + DEBUG(0,("is_8_3: out of memory!\n")); + goto done; + } + s2 = s1 + u2len; + dos_to_ucs2(u2, fname, u2len); + + + if (!mangle_get_prefix(u2, &pref, &ext)) goto done; + if (strlen_w(pref) > 8) goto done; + + ucs2_to_dos(s1, u2, u2len); + ucs2_to_dos83(s2, u2, u2len); + + if (strncmp(s1, s2, u2len)) goto done; + else ret = True; + +done: + SAFE_FREE(u2); + SAFE_FREE(s1); + SAFE_FREE(pref); + SAFE_FREE(ext); +} + +void reset_mangled_cache(void) +{ + DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n")); +} + +BOOL check_mangled_cache(char *s) +{ + smb_ucs2_t *u2, *res; + size_t slen, u2len; + BOOL ret = False; + + DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n")); + + slen = strlen(s); + u2len = (slen + 1) * sizeof(smb_ucs2_t); + u2 = (smb_ucs2_t *)malloc(u2len); + if (!u2) + { + DEBUG(0,("check_mangled_cache: out of memory!\n")); + return ret; + } + dos_to_ucs2(u2, s, u2len); + + res = unmangle(u2); + if (res) + { + ucs2_to_dos (s, res, slen); /* ugly, but must be done this way */ + ret = True; + } + SAFE_FREE(res); + SAFE_FREE(u2); + return ret; +} + +void mangle_name_83(char *s) +{ + smb_ucs2_t *u2, *res; + size_t slen, u2len; + BOOL ret = False; + + DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n")); + + slen = strlen(s); + u2len = (slen + 1) * sizeof(smb_ucs2_t); + u2 = (smb_ucs2_t *)malloc(u2len); + if (!u2) + { + DEBUG(0,("mangle_name_83: out of memory!\n")); + return; + } + dos_to_ucs2(u2, s, u2len); + + res = _mangle(u2); + if (res) ucs2_to_dos (s, res, slen); /* ugly, but must be done this way */ + SAFE_FREE(res); + SAFE_FREE(u2); +} + +BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) +{ + DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n")); + + mangle_name_83(OutName); + return True; +} + #endif /* 0 */ -#if 1 /* TEST_MANGLE_CODE */ +#if 0 /* TEST_MANGLE_CODE */ #define LONG "this_is_a_long_file_name" #define LONGM "this_~01" -- cgit From 0c0dd06dbd558254ebb048223b0396454f7ee1dd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Oct 2001 07:50:21 +0000 Subject: split session setup code out of reply.c in preparation for adding NTLMSSP and kerberos support in smbd (This used to be commit 38a43d75e25bbebe0f6cdfcf389129a842ede842) --- source3/smbd/reply.c | 345 +-------------------------------------------- source3/smbd/sesssetup.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+), 344 deletions(-) create mode 100644 source3/smbd/sesssetup.c (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 334a48e338..8b6e754549 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -44,20 +44,6 @@ unsigned int smb_echo_count = 0; extern fstring remote_machine; extern BOOL global_encrypted_passwords_negotiated; -/**************************************************************************** -report a possible attack via the password buffer overflow bug -****************************************************************************/ - -static void overflow_attack(int len) -{ - if( DEBUGLVL( 0 ) ) { - dbgtext( "ERROR: Invalid password length %d.\n", len ); - dbgtext( "Your machine may be under attack by someone " ); - dbgtext( "attempting to exploit an old bug.\n" ); - dbgtext( "Attack was from IP = %s.\n", client_addr() ); - } -} - /**************************************************************************** reply to an special message @@ -231,8 +217,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } if (passlen > MAX_PASS_LEN) { - overflow_attack(passlen); - return(ERROR_DOS(ERRDOS,ERRbuftoosmall)); + return ERROR_DOS(ERRDOS,ERRbuftoosmall); } memcpy(password,smb_buf(inbuf),passlen); @@ -372,334 +357,6 @@ int reply_ioctl(connection_struct *conn, return outsize; } -/**************************************************************************** -reply to a session setup command -****************************************************************************/ - -int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) -{ - int sess_vuid; - gid_t gid; - uid_t uid; - char* full_name; - int smb_bufsize; - int smb_apasslen = 0; - pstring smb_apasswd; - int smb_ntpasslen = 0; - pstring smb_ntpasswd; - pstring user; - pstring orig_user; - fstring domain; - fstring native_os; - fstring native_lanman; - BOOL guest=False; - static BOOL done_sesssetup = False; - BOOL doencrypt = global_encrypted_passwords_negotiated; - START_PROFILE(SMBsesssetupX); - - *smb_apasswd = *smb_ntpasswd = 0; - - smb_bufsize = SVAL(inbuf,smb_vwv2); - - if (Protocol < PROTOCOL_NT1) { - smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASS_LEN) { - overflow_attack(smb_apasslen); - return(ERROR_DOS(ERRDOS,ERRbuftoosmall)); - } - - memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); - - if (!doencrypt && (lp_security() != SEC_SERVER)) { - smb_apasslen = strlen(smb_apasswd); - } - } else { - uint16 passlen1 = SVAL(inbuf,smb_vwv7); - uint16 passlen2 = SVAL(inbuf,smb_vwv8); - enum remote_arch_types ra_type = get_remote_arch(); - char *p = smb_buf(inbuf); - - if(global_client_caps == 0) - global_client_caps = IVAL(inbuf,smb_vwv11); - - /* client_caps is used as final determination if client is NT or Win95. - This is needed to return the correct error codes in some - circumstances. - */ - - if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) { - if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) { - set_remote_arch( RA_WIN95); - } - } - - if (passlen1 != 24 && passlen2 < 24) - doencrypt = False; - - if (passlen1 > MAX_PASS_LEN) { - overflow_attack(passlen1); - return ERROR_DOS(ERRDOS,ERRbuftoosmall); - } - - passlen1 = MIN(passlen1, MAX_PASS_LEN); - passlen2 = MIN(passlen2, MAX_PASS_LEN); - - if (!doencrypt) { - /* both Win95 and WinNT stuff up the password lengths for - non-encrypting systems. Uggh. - - if passlen1==24 its a win95 system, and its setting the - password length incorrectly. Luckily it still works with the - default code because Win95 will null terminate the password - anyway - - if passlen1>0 and passlen2>0 then maybe its a NT box and its - setting passlen2 to some random value which really stuffs - things up. we need to fix that one. */ - - if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1) - passlen2 = 0; - } - - if (lp_restrict_anonymous()) { - /* there seems to be no reason behind the differences in MS clients formatting - * various info like the domain, NativeOS, and NativeLanMan fields. Win95 - * in particular seems to have an extra null byte between the username and the - * domain, or the password length calculation is wrong, which throws off the - * string extraction routines below. This makes the value of domain be the - * empty string, which fails the restrict anonymous check further down. - * This compensates for that, and allows browsing to work in mixed NT and - * win95 environments even when restrict anonymous is true. AAB - */ - dump_data(100, p, 0x70); - DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2)); - if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) { - DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n")); - DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n")); - DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n")); - passlen1 = 1; - } - } - - /* Save the lanman2 password and the NT md4 password. */ - smb_apasslen = passlen1; - memcpy(smb_apasswd,p,smb_apasslen); - - smb_ntpasslen = passlen2; - memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); - - if (smb_apasslen != 24 || !doencrypt) { - /* trim the password */ - smb_apasslen = strlen(smb_apasswd); - - /* wfwg sometimes uses a space instead of a null */ - if (strequal(smb_apasswd," ")) { - smb_apasslen = 0; - *smb_apasswd = 0; - } - } - - p += passlen1 + passlen2; - p += srvstr_pull(inbuf, user, p, sizeof(user), -1, - STR_TERMINATE); - /* - * Incoming user and domain are in DOS codepage format. Convert - * to UNIX. - */ - p += srvstr_pull(inbuf, domain, p, sizeof(domain), - -1, STR_TERMINATE); - p += srvstr_pull(inbuf, native_os, p, sizeof(native_os), - -1, STR_TERMINATE); - p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman), - -1, STR_TERMINATE); - DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - domain,native_os,native_lanman)); - } - - /* don't allow for weird usernames or domains */ - alpha_strcpy(user, user, ". _-$", sizeof(user)); - alpha_strcpy(domain, domain, ". _-", sizeof(domain)); - if (strstr(user, "..") || strstr(domain,"..")) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - if (lp_security() == SEC_SHARE) { - /* in share level we should ignore any passwords */ - smb_ntpasslen = 0; - smb_apasslen = 0; - guest = True; - } - - - DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine)); - - if (done_sesssetup && lp_restrict_anonymous()) { - /* tests show that even if browsing is done over already validated connections - * without a username and password the domain is still provided, which it - * wouldn't be if it was a purely anonymous connection. So, in order to - * restrict anonymous, we only deny connections that have no session - * information. If a domain has been provided, then it's not a purely - * anonymous connection. AAB - */ - if (!*user && !*smb_apasswd && !*domain) { - DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); - END_PROFILE(SMBsesssetupX); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } - } - - /* If no username is sent use the guest account */ - if (!*user) { - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - } - - pstrcpy(current_user_info.smb_name,user); - - reload_services(True); - - /* - * Save the username before mapping. We will use - * the original username sent to us for security=server - * and security=domain checking. - */ - - pstrcpy( orig_user, user); - - /* - * Always try the "DOMAIN\user" lookup first, as this is the most - * specific case. If this fails then try the simple "user" lookup. - * But don't do this for guests, as this is always a local user. - */ - - if (!guest) { - pstring dom_user; - - /* Work out who's who */ - - slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s", - domain, lp_winbind_separator(), user); - - if (sys_getpwnam(dom_user) != NULL) { - pstrcpy(user, dom_user); - DEBUG(3,("Using unix username %s\n", dom_user)); - } - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - smb_getpwnam(user, True); - } - - add_session_user(user); - - if (!guest) { - NTSTATUS nt_status; - nt_status = pass_check_smb(orig_user, user, - domain, remote_machine, - (unsigned char *)smb_apasswd, - smb_apasslen, - (unsigned char *)smb_ntpasswd, - smb_ntpasslen); - - if NT_STATUS_IS_OK(nt_status) { - - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { - if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || - (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - } else { - /* Match WinXP and don't give the game away */ - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { - if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } else { - /* Match WinXP and don't give the game away */ - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - } else { - return ERROR_NT(nt_status); - } - } - - if (!strequal(user,lp_guestaccount(-1)) && - lp_servicenumber(user) < 0) - { - add_home_service(user,get_user_home_dir(user)); - } - - - /* it's ok - setup a reply */ - if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,3,0,True); - } else { - char *p; - set_message(outbuf,3,0,True); - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - set_message_end(outbuf,p); - /* perhaps grab OS version here?? */ - } - - /* Set the correct uid in the outgoing and incoming packets - We will use this on future requests to determine which - user we should become. - */ - { - const struct passwd *pw = smb_getpwnam(user,False); - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n",user)); - END_PROFILE(SMBsesssetupX); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; - } - - if (guest) - SSVAL(outbuf,smb_vwv2,1); - - /* register the name and uid as being validated, so further connections - to a uid can get through without a password, on the same VC */ - - sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name); - - if (sess_vuid == -1) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - - SSVAL(outbuf,smb_uid,sess_vuid); - SSVAL(inbuf,smb_uid,sess_vuid); - - if (!done_sesssetup) - max_send = MIN(max_send,smb_bufsize); - - DEBUG(6,("Client requested max send size of %d\n", max_send)); - - done_sesssetup = True; - - END_PROFILE(SMBsesssetupX); - return chain_reply(inbuf,outbuf,length,bufsize); -} - /**************************************************************************** reply to a chkpth ****************************************************************************/ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c new file mode 100644 index 0000000000..45fa2d6a4a --- /dev/null +++ b/source3/smbd/sesssetup.c @@ -0,0 +1,355 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + handle SMBsessionsetup + Copyright (C) Andrew Tridgell 1998-2001 + Copyright (C) Andrew Bartlett 2001 + + 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" + +/**************************************************************************** +reply to a session setup command +****************************************************************************/ +int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, + int length,int bufsize) +{ + int sess_vuid; + gid_t gid; + uid_t uid; + char* full_name; + int smb_bufsize; + int smb_apasslen = 0; + pstring smb_apasswd; + int smb_ntpasslen = 0; + pstring smb_ntpasswd; + pstring user; + pstring orig_user; + fstring domain; + fstring native_os; + fstring native_lanman; + BOOL guest=False; + static BOOL done_sesssetup = False; + extern BOOL global_encrypted_passwords_negotiated; + extern uint32 global_client_caps; + extern int Protocol; + extern fstring remote_machine; + extern userdom_struct current_user_info; + extern int max_send; + BOOL doencrypt = global_encrypted_passwords_negotiated; + START_PROFILE(SMBsesssetupX); + + *smb_apasswd = *smb_ntpasswd = 0; + + smb_bufsize = SVAL(inbuf,smb_vwv2); + + if (Protocol < PROTOCOL_NT1) { + smb_apasslen = SVAL(inbuf,smb_vwv7); + if (smb_apasslen > MAX_PASS_LEN) { + return ERROR_DOS(ERRDOS,ERRbuftoosmall); + } + + memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); + srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); + + if (!doencrypt && (lp_security() != SEC_SERVER)) { + smb_apasslen = strlen(smb_apasswd); + } + } else { + uint16 passlen1 = SVAL(inbuf,smb_vwv7); + uint16 passlen2 = SVAL(inbuf,smb_vwv8); + enum remote_arch_types ra_type = get_remote_arch(); + char *p = smb_buf(inbuf); + + if(global_client_caps == 0) + global_client_caps = IVAL(inbuf,smb_vwv11); + + /* client_caps is used as final determination if client is NT or Win95. + This is needed to return the correct error codes in some + circumstances. + */ + + if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) { + if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) { + set_remote_arch( RA_WIN95); + } + } + + if (passlen1 != 24 && passlen2 < 24) + doencrypt = False; + + if (passlen1 > MAX_PASS_LEN) { + return ERROR_DOS(ERRDOS,ERRbuftoosmall); + } + + passlen1 = MIN(passlen1, MAX_PASS_LEN); + passlen2 = MIN(passlen2, MAX_PASS_LEN); + + if (!doencrypt) { + /* both Win95 and WinNT stuff up the password lengths for + non-encrypting systems. Uggh. + + if passlen1==24 its a win95 system, and its setting the + password length incorrectly. Luckily it still works with the + default code because Win95 will null terminate the password + anyway + + if passlen1>0 and passlen2>0 then maybe its a NT box and its + setting passlen2 to some random value which really stuffs + things up. we need to fix that one. */ + + if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1) + passlen2 = 0; + } + + if (lp_restrict_anonymous()) { + /* there seems to be no reason behind the + * differences in MS clients formatting + * various info like the domain, NativeOS, and + * NativeLanMan fields. Win95 in particular + * seems to have an extra null byte between + * the username and the domain, or the + * password length calculation is wrong, which + * throws off the string extraction routines + * below. This makes the value of domain be + * the empty string, which fails the restrict + * anonymous check further down. This + * compensates for that, and allows browsing + * to work in mixed NT and win95 environments + * even when restrict anonymous is true. AAB + * */ + dump_data(100, p, 0x70); + DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2)); + if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) { + DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n")); + DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n")); + DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n")); + passlen1 = 1; + } + } + + /* Save the lanman2 password and the NT md4 password. */ + smb_apasslen = passlen1; + memcpy(smb_apasswd,p,smb_apasslen); + + smb_ntpasslen = passlen2; + memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); + + if (smb_apasslen != 24 || !doencrypt) { + /* trim the password */ + smb_apasslen = strlen(smb_apasswd); + + /* wfwg sometimes uses a space instead of a null */ + if (strequal(smb_apasswd," ")) { + smb_apasslen = 0; + *smb_apasswd = 0; + } + } + + p += passlen1 + passlen2; + p += srvstr_pull(inbuf, user, p, sizeof(user), -1, + STR_TERMINATE); + p += srvstr_pull(inbuf, domain, p, sizeof(domain), + -1, STR_TERMINATE); + p += srvstr_pull(inbuf, native_os, p, sizeof(native_os), + -1, STR_TERMINATE); + p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman), + -1, STR_TERMINATE); + DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", + domain,native_os,native_lanman)); + } + + /* don't allow for weird usernames or domains */ + alpha_strcpy(user, user, ". _-$", sizeof(user)); + alpha_strcpy(domain, domain, ". _-", sizeof(domain)); + if (strstr(user, "..") || strstr(domain,"..")) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + if (lp_security() == SEC_SHARE) { + /* in share level we should ignore any passwords */ + smb_ntpasslen = 0; + smb_apasslen = 0; + guest = True; + } + + + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine)); + + if (done_sesssetup && lp_restrict_anonymous()) { + /* tests show that even if browsing is done over + * already validated connections without a username + * and password the domain is still provided, which it + * wouldn't be if it was a purely anonymous + * connection. So, in order to restrict anonymous, we + * only deny connections that have no session + * information. If a domain has been provided, then + * it's not a purely anonymous connection. AAB */ + if (!*user && !*smb_apasswd && !*domain) { + DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); + END_PROFILE(SMBsesssetupX); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + } + + /* If no username is sent use the guest account */ + if (!*user) { + pstrcpy(user,lp_guestaccount(-1)); + guest = True; + } + + pstrcpy(current_user_info.smb_name,user); + + reload_services(True); + + /* + * Save the username before mapping. We will use + * the original username sent to us for security=server + * and security=domain checking. + */ + + pstrcpy( orig_user, user); + + /* + * Always try the "DOMAIN\user" lookup first, as this is the most + * specific case. If this fails then try the simple "user" lookup. + * But don't do this for guests, as this is always a local user. + */ + + if (!guest) { + pstring dom_user; + + /* Work out who's who */ + + slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s", + domain, lp_winbind_separator(), user); + + if (sys_getpwnam(dom_user) != NULL) { + pstrcpy(user, dom_user); + DEBUG(3,("Using unix username %s\n", dom_user)); + } + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + (void)map_username(user); + + /* + * Do any UNIX username case mangling. + */ + smb_getpwnam(user, True); + } + + add_session_user(user); + + if (!guest) { + NTSTATUS nt_status; + nt_status = pass_check_smb(orig_user, user, + domain, remote_machine, + (unsigned char *)smb_apasswd, + smb_apasslen, + (unsigned char *)smb_ntpasswd, + smb_ntpasslen); + + if NT_STATUS_IS_OK(nt_status) { + + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); + pstrcpy(user,lp_guestaccount(-1)); + guest = True; + } else { + /* Match WinXP and don't give the game away */ + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + pstrcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } else { + /* Match WinXP and don't give the game away */ + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + } else { + return ERROR_NT(nt_status); + } + } + + if (!strequal(user,lp_guestaccount(-1)) && + lp_servicenumber(user) < 0) { + add_home_service(user,get_user_home_dir(user)); + } + + + /* it's ok - setup a reply */ + if (Protocol < PROTOCOL_NT1) { + set_message(outbuf,3,0,True); + } else { + char *p; + set_message(outbuf,3,0,True); + p = smb_buf(outbuf); + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); + /* perhaps grab OS version here?? */ + } + + /* Set the correct uid in the outgoing and incoming packets + We will use this on future requests to determine which + user we should become. + */ + { + const struct passwd *pw = smb_getpwnam(user,False); + if (!pw) { + DEBUG(1,("Username %s is invalid on this system\n",user)); + END_PROFILE(SMBsesssetupX); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + gid = pw->pw_gid; + uid = pw->pw_uid; + full_name = pw->pw_gecos; + } + + if (guest) + SSVAL(outbuf,smb_vwv2,1); + + /* register the name and uid as being validated, so further connections + to a uid can get through without a password, on the same VC */ + + sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name); + + if (sess_vuid == -1) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + + SSVAL(outbuf,smb_uid,sess_vuid); + SSVAL(inbuf,smb_uid,sess_vuid); + + if (!done_sesssetup) + max_send = MIN(max_send,smb_bufsize); + + done_sesssetup = True; + + END_PROFILE(SMBsesssetupX); + return chain_reply(inbuf,outbuf,length,bufsize); +} -- cgit From 7acc2b977c4829fb70df6e9a9c4ba6111366aabc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Oct 2001 08:39:43 +0000 Subject: Fix for connectinos.tdb error message from "Richard Bollinger" Jeremy. (This used to be commit f1f1a14598be64d4930049691ca970fe93506007) --- source3/smbd/connection.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index f6da678cb1..c0eaf8187d 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -55,8 +55,9 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) kbuf.dsize = sizeof(key); if (tdb_delete(tdb, kbuf) != 0) { - DEBUG(0,("yield_connection: tdb_delete for name %s failed with error %s.\n", - name, tdb_errorstr(tdb) )); + int dbg_lvl = (!conn && (tdb_error(tdb) == TDB_ERR_NOEXIST)) ? 3 : 0; + DEBUG(dbg_lvl,("yield_connection: tdb_delete for name %s failed with error %s.\n", + name, tdb_errorstr(tdb) )); return (False); } -- cgit From 3f1d1008428f9563d33dff96d1304e30dae3d0f2 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Tue, 16 Oct 2001 23:16:00 +0000 Subject: very simple asynchronous "lpq" thread patch To speed up operations with the lpq command, it's now run in a separate asynchronous process. Opening the Printers folder on NT is now fast ;-) I think even faster than with a ** server Jeremy, you should look at that patch to include it in 2.2.3 J.F. (This used to be commit 8ef9dff3074e7979579ce66a204e8ec7bf62a587) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f707a61376..4599cef41f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -791,6 +791,8 @@ static void usage(char *pname) /* Setup the main smbd so that we can get messages. */ claim_connection(NULL,"",MAXSTATUS,True); + start_background_queue(); + if (!open_sockets(is_daemon,port)) exit(1); -- cgit From d731149a41d7563ab99acd3d3d20fff899e7de8f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Oct 2001 01:38:23 +0000 Subject: Fixed inconsistent definitions of InBuf/OutBuf/last_char. Noticed by albert chin (china@thewrittenword.com) . Jeremy. (This used to be commit f5781f11eb924bdf32d20819c58a782493f4b239) --- source3/smbd/process.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4b7e80811c..ea97eea8a4 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -42,9 +42,6 @@ int max_recv = BUFFER_SIZE; extern int last_message; extern int global_oplock_break; extern userdom_struct current_user_info; -extern char *last_inbuf; -extern char *InBuffer; -extern char *OutBuffer; extern int smb_read_error; extern VOLATILE sig_atomic_t reload_after_sighup; extern BOOL global_machine_password_needs_changing; -- cgit From b728042334f67738fd1a6fdd03e619bdb78fe06a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Oct 2001 08:54:19 +0000 Subject: added basic NTLMSSP support in smbd. This is still quite rough, and loses things like username mapping. I wanted to get this in then discuss it a bit to see how we want to split up the existing session setup code (This used to be commit b74fda69bf23207c26d8b2af23910d8f2eb89875) --- source3/smbd/negprot.c | 75 +++++++++++--- source3/smbd/process.c | 37 ++++--- source3/smbd/sesssetup.c | 258 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 337 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index d20f713113..cf14640a72 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -30,7 +30,7 @@ BOOL global_encrypted_passwords_negotiated; /**************************************************************************** reply for the core protocol ****************************************************************************/ -static int reply_corep(char *outbuf) +static int reply_corep(char *inbuf, char *outbuf) { int outsize = set_message(outbuf,1,0,True); @@ -43,7 +43,7 @@ static int reply_corep(char *outbuf) /**************************************************************************** reply for the coreplus protocol ****************************************************************************/ -static int reply_coreplus(char *outbuf) +static int reply_coreplus(char *inbuf, char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int outsize = set_message(outbuf,13,0,True); @@ -62,7 +62,7 @@ static int reply_coreplus(char *outbuf) /**************************************************************************** reply for the lanman 1.0 protocol ****************************************************************************/ -static int reply_lanman1(char *outbuf) +static int reply_lanman1(char *inbuf, char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; @@ -100,7 +100,7 @@ static int reply_lanman1(char *outbuf) /**************************************************************************** reply for the lanman 2.0 protocol ****************************************************************************/ -static int reply_lanman2(char *outbuf) +static int reply_lanman2(char *inbuf, char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; @@ -154,10 +154,44 @@ static int reply_lanman2(char *outbuf) } + +/* + generate the spnego negprot reply blob. Return the number of bytes used +*/ +static int negprot_spnego(char *p, uint8 cryptkey[8]) +{ + DATA_BLOB blob; + extern pstring global_myname; + uint8 guid[16]; + const char *OIDs[] = {OID_NTLMSSP, +#if 0 + /* not till we add kerberos in the server */ + OID_KERBEROS5_OLD, +#endif + NULL}; + char *principle; + int len; + + memset(guid, 0, 16); + safe_strcpy(guid, global_myname, 16); + strlower(guid); + + asprintf(&principle, "%s$@%s", guid, lp_realm()); + blob = spnego_gen_negTokenInit(guid, OIDs, principle); + free(principle); + + memcpy(p, blob.data, blob.length); + len = blob.length; + data_blob_free(&blob); + return len; +} + + + /**************************************************************************** reply for the nt protocol ****************************************************************************/ -static int reply_nt1(char *outbuf) +static int reply_nt1(char *inbuf, char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| @@ -166,10 +200,10 @@ static int reply_nt1(char *outbuf) int secword=0; time_t t = time(NULL); struct cli_state *cli = NULL; - char cryptkey[8]; - char crypt_len = 0; + uint8 cryptkey[8]; char *p, *q; - + BOOL negotiate_spnego = False; + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); if (lp_security() == SEC_SERVER) { @@ -177,6 +211,14 @@ static int reply_nt1(char *outbuf) cli = server_cryptkey(); } else { DEBUG(5,("not attempting password server validation\n")); + /* do spnego in user level security if the client + supports it and we can do encrypted passwords */ + if (global_encrypted_passwords_negotiated && + lp_security() == SEC_USER && + (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { + negotiate_spnego = True; + capabilities |= CAP_EXTENDED_SECURITY; + } } if (cli) { @@ -187,7 +229,6 @@ static int reply_nt1(char *outbuf) } if (global_encrypted_passwords_negotiated) { - crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); } else { @@ -224,7 +265,6 @@ static int reply_nt1(char *outbuf) set_message(outbuf,17,0,True); CVAL(outbuf,smb_vwv1) = secword; - SSVALS(outbuf,smb_vwv16+1,crypt_len); Protocol = PROTOCOL_NT1; @@ -238,8 +278,15 @@ static int reply_nt1(char *outbuf) SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); p = q = smb_buf(outbuf); - if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8); - p += 8; + if (!negotiate_spnego) { + if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8); + SSVALS(outbuf,smb_vwv16+1,8); + p += 8; + } else { + int len = negprot_spnego(p, cryptkey); + SSVALS(outbuf,smb_vwv16+1,len); + p += len; + } p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); @@ -322,7 +369,7 @@ protocol [LANMAN2.1] static struct { char *proto_name; char *short_name; - int (*proto_reply_fn)(char *); + int (*proto_reply_fn)(char *, char *); int protocol_level; } supported_protocols[] = { {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, @@ -441,7 +488,7 @@ int reply_negprot(connection_struct *conn, extern fstring remote_proto; fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(True); - outsize = supported_protocols[protocol].proto_reply_fn(outbuf); + outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf); DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ea97eea8a4..cf691ce9f3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -911,25 +911,24 @@ char *smb_fn_name(int type) void construct_reply_common(char *inbuf,char *outbuf) { - memset(outbuf,'\0',smb_size); - - set_message(outbuf,0,0,True); - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); - - memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf,smb_reh) = 0; - SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set - means a reply */ - SSVAL(outbuf,smb_flg2, - (SVAL(inbuf,smb_flg2)&FLAGS2_UNICODE_STRINGS) | FLAGS2_LONG_PATH_COMPONENTS); - /* say we support long filenames */ - - SSVAL(outbuf,smb_err,SMB_SUCCESS); - SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); + memset(outbuf,'\0',smb_size); + + set_message(outbuf,0,0,True); + CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); + + memcpy(outbuf+4,inbuf+4,4); + CVAL(outbuf,smb_rcls) = SMB_SUCCESS; + CVAL(outbuf,smb_reh) = 0; + SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); + SSVAL(outbuf,smb_flg2, + FLAGS2_UNICODE_STRINGS | FLAGS2_LONG_PATH_COMPONENTS | + FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY); + + SSVAL(outbuf,smb_err,SMB_SUCCESS); + SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); + SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); + SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); + SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); } /**************************************************************************** diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 45fa2d6a4a..34b431e404 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -22,6 +22,259 @@ #include "includes.h" + +/**************************************************************************** +send a security blob via a session setup reply +****************************************************************************/ +static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, + DATA_BLOB blob) +{ + char *p; + + set_message(outbuf,4,0,True); + + /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end + that we aren't finished yet */ + + SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)); + SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ + SSVAL(outbuf, smb_vwv3, blob.length); + p = smb_buf(outbuf); + memcpy(p, blob.data, blob.length); + p += blob.length; + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); + + return send_smb(smbd_server_fd(),outbuf); +} + + + + +/**************************************************************************** +reply to a session setup spnego negotiate packet +****************************************************************************/ +static int reply_spnego_negotiate(connection_struct *conn, char *outbuf, + DATA_BLOB blob1) +{ + char *OIDs[ASN1_MAX_OIDS]; + DATA_BLOB secblob; + int i; + uint32 ntlmssp_command, neg_flags; + DATA_BLOB sess_key, chal, spnego_chal; + uint8 cryptkey[8]; + + /* parse out the OIDs and the first sec blob */ + if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + for (i=0;OIDs[i];i++) { + DEBUG(3,("Got OID %s\n", OIDs[i])); + free(OIDs[i]); + } + DEBUG(3,("Got secblob of size %d\n", secblob.length)); + + /* parse the NTLMSSP packet */ +#if 0 + file_save("secblob.dat", secblob.data, secblob.length); +#endif + + msrpc_parse(&secblob, "CddB", + "NTLMSSP", + &ntlmssp_command, + &neg_flags, + &sess_key); + + data_blob_free(&secblob); + data_blob_free(&sess_key); + + if (ntlmssp_command != NTLMSSP_NEGOTIATE) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); + + last_challenge(cryptkey); + + /* Give them the challenge. For now, ignore neg_flags and just + return the flags we want. Obviously this is not correct */ + + neg_flags = NTLMSSP_NEGOTIATE_UNICODE | + NTLMSSP_NEGOTIATE_LM_KEY | + NTLMSSP_NEGOTIATE_NTLM; + + msrpc_gen(&chal, "Cddddbdddd", + "NTLMSSP", + NTLMSSP_CHALLENGE, + 0, + 0x30, /* ?? */ + neg_flags, + cryptkey, 8, + 0, 0, 0, + 0x3000); /* ?? */ + + if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) { + DEBUG(3,("Failed to generate challenge\n")); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + /* now tell the client to send the auth packet */ + reply_sesssetup_blob(conn, outbuf, spnego_chal); + + data_blob_free(&chal); + data_blob_free(&spnego_chal); + + /* and tell smbd that we have already replied to this packet */ + return -1; +} + + +/**************************************************************************** +reply to a session setup spnego auth packet +****************************************************************************/ +static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, + int length, int bufsize, + DATA_BLOB blob1) +{ + DATA_BLOB auth; + char *workgroup, *user, *machine; + DATA_BLOB lmhash, nthash, sess_key; + uint32 ntlmssp_command, neg_flags; + NTSTATUS nt_status; + int sess_vuid; + gid_t gid; + uid_t uid; + char *full_name; + char *p; + const struct passwd *pw; + + if (!spnego_parse_auth(blob1, &auth)) { + file_save("auth.dat", blob1.data, blob1.length); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + /* now the NTLMSSP encoded auth hashes */ + if (!msrpc_parse(&auth, "CdBBUUUBd", + "NTLMSSP", + &ntlmssp_command, + &lmhash, + &nthash, + &workgroup, + &user, + &machine, + &sess_key, + &neg_flags)) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + data_blob_free(&auth); + data_blob_free(&sess_key); + + DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n", + user, workgroup, machine, lmhash.length, nthash.length)); + +#if 0 + file_save("nthash1.dat", nthash.data, nthash.length); + file_save("lmhash1.dat", lmhash.data, lmhash.length); +#endif + + nt_status = pass_check_smb(user, user, + workgroup, machine, + lmhash.data, + lmhash.length, + nthash.data, + nthash.length); + + data_blob_free(&nthash); + data_blob_free(&lmhash); + + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status); + } + + /* the password is good - let them in */ + pw = smb_getpwnam(user,False); + if (!pw) { + DEBUG(1,("Username %s is invalid on this system\n",user)); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + gid = pw->pw_gid; + uid = pw->pw_uid; + full_name = pw->pw_gecos; + + sess_vuid = register_vuid(uid,gid,user,user,workgroup,False, full_name); + + free(user); + free(workgroup); + free(machine); + + if (sess_vuid == -1) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + set_message(outbuf,4,0,True); + SSVAL(outbuf, smb_vwv3, 0); + p = smb_buf(outbuf); + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); + + SSVAL(outbuf,smb_uid,sess_vuid); + SSVAL(inbuf,smb_uid,sess_vuid); + + return chain_reply(inbuf,outbuf,length,bufsize); +} + + +/**************************************************************************** +reply to a session setup command +****************************************************************************/ +static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf, + int length,int bufsize) +{ + uint8 *p; + DATA_BLOB blob1; + extern uint32 global_client_caps; + int ret; + + chdir("/home/tridge"); + + if (global_client_caps == 0) { + global_client_caps = IVAL(inbuf,smb_vwv10); + } + + p = smb_buf(inbuf); + + /* pull the spnego blob */ + blob1 = data_blob(p, SVAL(inbuf, smb_vwv7)); + + if (blob1.data[0] == ASN1_APPLICATION(0)) { + /* its a negTokenTarg packet */ + ret = reply_spnego_negotiate(conn, outbuf, blob1); + data_blob_free(&blob1); + return ret; + } + + if (blob1.data[0] == ASN1_CONTEXT(1)) { + /* its a auth packet */ + ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1); + data_blob_free(&blob1); + return ret; + } + + /* what sort of packet is this? */ + DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n")); + + data_blob_free(&blob1); + + return ERROR_NT(NT_STATUS_LOGON_FAILURE); +} + + /**************************************************************************** reply to a session setup command ****************************************************************************/ @@ -53,6 +306,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, BOOL doencrypt = global_encrypted_passwords_negotiated; START_PROFILE(SMBsesssetupX); + if (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) { + /* it's a SPNEGO session setup */ + return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); + } + *smb_apasswd = *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); -- cgit From adfa547aab4b83deb6c30cbf0f568fef366bd9a9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Oct 2001 10:46:46 +0000 Subject: removed some debug code (This used to be commit b9e1f05393aaadf1fbe09338417977e2a3cb4559) --- source3/smbd/sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 34b431e404..a833b7e706 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -152,7 +152,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, const struct passwd *pw; if (!spnego_parse_auth(blob1, &auth)) { +#if 0 file_save("auth.dat", blob1.data, blob1.length); +#endif return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -241,8 +243,6 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha extern uint32 global_client_caps; int ret; - chdir("/home/tridge"); - if (global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv10); } -- cgit From f0e0dd6507c355103c51058642f1e4245c573413 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 18 Oct 2001 00:27:20 +0000 Subject: Renamed vfs_init() to smbd_vfs_init() to allow vfs modules to compile. (This used to be commit 7c3542ba8764be48b88255dd7f73ea6d87be10ac) --- source3/smbd/service.c | 2 +- source3/smbd/vfs.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 69283d3bf5..6f2c28d19c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -551,7 +551,7 @@ connection_struct *make_connection(char *service,char *password, } /* Initialise VFS function pointers */ - if (!vfs_init(conn)) { + if (!smbd_vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); conn_free(conn); return NULL; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 05645f7b19..7a3d23d652 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -154,7 +154,7 @@ static BOOL vfs_init_custom(connection_struct *conn) Generic VFS init. ******************************************************************/ -BOOL vfs_init(connection_struct *conn) +BOOL smbd_vfs_init(connection_struct *conn) { if (*lp_vfsobj(SNUM(conn))) { #ifdef HAVE_LIBDL @@ -162,13 +162,13 @@ BOOL vfs_init(connection_struct *conn) /* Loadable object file */ if (!vfs_init_custom(conn)) { - DEBUG(0, ("vfs_init: vfs_init_custom failed\n")); + DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed\n")); return False; } return True; #else - DEBUG(0, ("vfs_init: No libdl present - cannot use VFS objects\n")); + DEBUG(0, ("smbd_vfs_init: No libdl present - cannot use VFS objects\n")); return False; #endif } -- cgit From 5ad7448359c7bc1d3b1579f105b7324290bf21ec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Oct 2001 10:26:06 +0000 Subject: the beginnings of kerberos support in smbd. It doesn't work yet, but it should give something for others to hack on and possibly find what I'm doing wrong. (This used to be commit 353c290f059347265b9be2aa1010c2956da06485) --- source3/smbd/negprot.c | 3 -- source3/smbd/sesssetup.c | 100 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 91 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index cf14640a72..678156b528 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -164,10 +164,7 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) extern pstring global_myname; uint8 guid[16]; const char *OIDs[] = {OID_NTLMSSP, -#if 0 - /* not till we add kerberos in the server */ OID_KERBEROS5_OLD, -#endif NULL}; char *principle; int len; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a833b7e706..7eb8f4e694 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -22,6 +22,71 @@ #include "includes.h" +#if HAVE_KRB5 +/**************************************************************************** +reply to a session setup spnego negotiate packet for kerberos +****************************************************************************/ +static int reply_spnego_kerberos(connection_struct *conn, char *outbuf, + DATA_BLOB *secblob) +{ + DATA_BLOB ticket; + krb5_context context; + krb5_principal server; + krb5_auth_context auth_context = NULL; + krb5_keytab keytab = NULL; + krb5_data packet; + krb5_ticket *tkt = NULL; + int ret; + char *realm, *client; + fstring service; + extern pstring global_myname; + + realm = lp_realm(); + + if (!spnego_parse_krb5_wrap(*secblob, &ticket)) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + /* the service is the wins name lowercase with $ tacked on */ + fstrcpy(service, global_myname); + strlower(service); + fstrcat(service, "$"); + + ret = krb5_init_context(&context); + if (ret) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + ret = krb5_build_principal(context, &server, strlen(realm), + realm, service, NULL); + if (ret) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + packet.length = ticket.length; + packet.data = (krb5_pointer)ticket.data; + + if ((ret = krb5_rd_req(context, &auth_context, &packet, + server, keytab, NULL, &tkt))) { + DEBUG(3,("krb5_rd_req failed with code %08x\n", ret)); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, + &client))) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + DEBUG(3,("Ticket name is [%s]\n", client)); + + /* well, if we got a client above then I think we have authenticated the user + but fail it for now until I understand it */ + + + return ERROR_NT(NT_STATUS_LOGON_FAILURE); +} +#endif + /**************************************************************************** send a security blob via a session setup reply @@ -50,9 +115,6 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, return send_smb(smbd_server_fd(),outbuf); } - - - /**************************************************************************** reply to a session setup spnego negotiate packet ****************************************************************************/ @@ -65,6 +127,7 @@ static int reply_spnego_negotiate(connection_struct *conn, char *outbuf, uint32 ntlmssp_command, neg_flags; DATA_BLOB sess_key, chal, spnego_chal; uint8 cryptkey[8]; + BOOL got_kerberos = False; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { @@ -73,20 +136,33 @@ static int reply_spnego_negotiate(connection_struct *conn, char *outbuf, for (i=0;OIDs[i];i++) { DEBUG(3,("Got OID %s\n", OIDs[i])); + if (strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) { + got_kerberos = True; + } free(OIDs[i]); } DEBUG(3,("Got secblob of size %d\n", secblob.length)); +#if HAVE_KRB5 + if (got_kerberos) { + int ret = reply_spnego_kerberos(conn, outbuf, &secblob); + data_blob_free(&secblob); + return ret; + } +#endif + /* parse the NTLMSSP packet */ #if 0 file_save("secblob.dat", secblob.data, secblob.length); #endif - msrpc_parse(&secblob, "CddB", - "NTLMSSP", - &ntlmssp_command, - &neg_flags, - &sess_key); + if (!msrpc_parse(&secblob, "CddB", + "NTLMSSP", + &ntlmssp_command, + &neg_flags, + &sess_key)) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } data_blob_free(&secblob); data_blob_free(&sess_key); @@ -97,7 +173,9 @@ static int reply_spnego_negotiate(connection_struct *conn, char *outbuf, DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); - last_challenge(cryptkey); + if (!last_challenge(cryptkey)) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ @@ -252,6 +330,10 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha /* pull the spnego blob */ blob1 = data_blob(p, SVAL(inbuf, smb_vwv7)); +#if 0 + file_save("negotiate.dat", blob1.data, blob1.length); +#endif + if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ ret = reply_spnego_negotiate(conn, outbuf, blob1); -- cgit From 904fca76849c74665d2a7cc6c91ff3f7ed6f6c11 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Oct 2001 10:40:36 +0000 Subject: got rid of start_background_queue() THIS WAS A DISASTER! it created hundreds of processes on the build farm machines, which we can't kill. (This used to be commit 04479db879d04fb329022c3282d92bab94a48576) --- source3/smbd/server.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4599cef41f..579649cf0c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -791,7 +791,12 @@ static void usage(char *pname) /* Setup the main smbd so that we can get messages. */ claim_connection(NULL,"",MAXSTATUS,True); - start_background_queue(); + /* + DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD + THIS *killed* LOTS OF BUILD FARM MACHINES. IT CREATED HUNDREDS OF + smbd PROCESSES THAT NEVER DIE + start_background_queue(); + */ if (!open_sockets(is_daemon,port)) exit(1); -- cgit From c416ff851b4ecc7a44aee9d00d07dd481d8ae2a7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2001 20:15:12 +0000 Subject: Merge the become_XXX -> change_to_XXX fixes from 2.2.2 to HEAD. Ensure make_conection() can only be called as root. Jeremy. (This used to be commit 8d23a7441b4687458ee021bfe8880558506eddba) --- source3/smbd/blocking.c | 10 ++-- source3/smbd/notify_hash.c | 15 +++-- source3/smbd/oplock.c | 4 +- source3/smbd/password.c | 2 +- source3/smbd/process.c | 12 ++-- source3/smbd/sec_ctx.c | 4 -- source3/smbd/server.c | 9 +-- source3/smbd/service.c | 58 +++++++++--------- source3/smbd/uid.c | 142 ++++++++++++++++++++++++++++++++++++++------- 9 files changed, 180 insertions(+), 76 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index a398a4c2a1..252ae6e0ea 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -582,7 +582,7 @@ void process_blocking_lock_queue(time_t t) continue; } - if(!become_user(conn,vuid)) { + if(!change_to_user(conn,vuid)) { DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", vuid )); /* @@ -594,7 +594,7 @@ void process_blocking_lock_queue(time_t t) continue; } - if(!become_service(conn,True)) { + if(!set_current_service(conn,True)) { DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); /* * Remove the entry and return an error to the client. @@ -602,7 +602,7 @@ void process_blocking_lock_queue(time_t t) blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - unbecome_user(); + change_to_root_user(); continue; } @@ -615,11 +615,11 @@ void process_blocking_lock_queue(time_t t) if(blocking_lock_record_process(blr)) { free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - unbecome_user(); + change_to_root_user(); continue; } - unbecome_user(); + change_to_root_user(); /* * Move to the next in the list. diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 0c69dc7876..d398fac214 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -126,16 +126,19 @@ static void *hash_register_notify(connection_struct *conn, char *path, uint32 fl Check if a change notify should be issued. A time of zero means instantaneous check - don't modify the last check time. *****************************************************************************/ + static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) { struct change_data *data = (struct change_data *)datap; struct change_data data2; - if (t && t < data->last_check_time + lp_change_notify_timeout()) return False; + if (t && t < data->last_check_time + lp_change_notify_timeout()) + return False; - if (!become_user(conn,vuid)) return True; - if (!become_service(conn,True)) { - unbecome_user(); + if (!change_to_user(conn,vuid)) + return True; + if (!set_current_service(conn,True)) { + change_to_root_user(); return True; } @@ -144,14 +147,14 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, data2.status_time != data->status_time || data2.total_time != data->total_time || data2.num_entries != data->num_entries) { - unbecome_user(); + change_to_root_user(); return True; } if (t) data->last_check_time = t; - unbecome_user(); + change_to_root_user(); return False; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 4e8e36b3aa..927719ac1a 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -750,7 +750,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B saved_vuid = current_user.vuid; saved_fsp_conn = fsp->conn; vfs_GetWd(saved_fsp_conn,saved_dir); - unbecome_user(); + change_to_root_user(); /* Save the chain fnum. */ file_chain_save(); @@ -823,7 +823,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B * Go back to being the user who requested the oplock * break. */ - if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !become_user(saved_user_conn, saved_vuid)) + if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !change_to_user(saved_user_conn, saved_vuid)) { DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); DEBUGADD( 0, ( "Shutting down server\n" ) ); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b074552567..b1739d9bb6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -244,7 +244,7 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, vuser->groups = NULL; /* Find all the groups this uid is in and store them. - Used by become_user() */ + Used by change_to_user() */ initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid); get_current_groups( &vuser->n_groups, &vuser->groups); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cf691ce9f3..edcb6b345f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -120,7 +120,7 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len) /* check for sighup processing */ if (reload_after_sighup) { - unbecome_user(); + change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); reload_after_sighup = False; @@ -702,7 +702,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* does this protocol need to be run as root? */ if (!(flags & AS_USER)) - unbecome_user(); + change_to_root_user(); /* does this protocol need a valid tree connection? */ if ((flags & AS_USER) && !conn) { @@ -711,7 +711,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(conn,session_tag)) { + if ((flags & AS_USER) && !change_to_user(conn,session_tag)) { if (flags & AS_GUEST) flags &= ~AS_USER; else @@ -734,13 +734,13 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize } /* load service specific parameters */ - if (conn && !become_service(conn,(flags & AS_USER)?True:False)) { + if (conn && !set_current_service(conn,(flags & AS_USER)?True:False)) { return(ERROR_DOS(ERRSRV,ERRaccess)); } /* does this protocol need to be run as guest? */ if ((flags & AS_GUEST) && - (!become_guest() || + (!change_to_guest() || !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { return(ERROR_DOS(ERRSRV,ERRaccess)); } @@ -1096,7 +1096,7 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t last_idle_closed_check = t; /* become root again if waiting */ - unbecome_user(); + change_to_root_user(); /* check if we need to reload services */ check_reload(t); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index c053a611c2..cea39b82cb 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -59,10 +59,8 @@ static BOOL become_uid(uid_t uid) /* Set effective user id */ set_effective_uid(uid); - current_user.uid = uid; DO_PROFILE_INC(uid_changes); - return True; } @@ -88,8 +86,6 @@ static BOOL become_gid(gid_t gid) /* Set effective group id */ set_effective_gid(gid); - current_user.gid = gid; - return True; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 579649cf0c..2e0fb1868d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -247,7 +247,7 @@ max can be %d\n", /* check for sighup processing */ if (reload_after_sighup) { - unbecome_user(); + change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); reload_after_sighup = False; @@ -393,7 +393,7 @@ BOOL reload_services(BOOL test) reset_stat_cache(); /* this forces service parameters to be flushed */ - become_service(NULL,True); + set_current_service(NULL,True); return(ret); } @@ -479,10 +479,11 @@ void exit_server(char *reason) extern char *last_inbuf; - if (!firsttime) exit(0); + if (!firsttime) + exit(0); firsttime = 0; - unbecome_user(); + change_to_root_user(); DEBUG(2,("Closing connections\n")); conn_close_all(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 6f2c28d19c..9e3f3c9f11 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -34,9 +34,10 @@ extern fstring remote_machine; /**************************************************************************** -load parameters specific to a connection/service + Load parameters specific to a connection/service. ****************************************************************************/ -BOOL become_service(connection_struct *conn,BOOL do_chdir) + +BOOL set_current_service(connection_struct *conn,BOOL do_chdir) { extern char magic_char; static connection_struct *last_conn; @@ -315,10 +316,10 @@ static void set_admin_user(connection_struct *conn) #endif } - /**************************************************************************** - make a connection to a service + Make a connection to a service. ****************************************************************************/ + connection_struct *make_connection(char *service,char *password, int pwlen, char *dev,uint16 vuid, NTSTATUS *status) { @@ -327,10 +328,17 @@ connection_struct *make_connection(char *service,char *password, BOOL guest = False; BOOL force = False; connection_struct *conn; + uid_t euid; fstring user; ZERO_STRUCT(user); + /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ + if ((euid = geteuid()) != 0) { + DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); + smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); + } + strlower(service); snum = find_service(service); @@ -519,7 +527,7 @@ connection_struct *make_connection(char *service,char *password, conn->groups = NULL; /* Find all the groups this uid is in and - store them. Used by become_user() */ + store them. Used by change_to_user() */ initialise_groups(conn->user, conn->uid, conn->gid); get_current_groups(&conn->ngroups,&conn->groups); @@ -557,16 +565,7 @@ connection_struct *make_connection(char *service,char *password, return NULL; } - if (!become_user(conn, conn->vuid)) { - /* No point continuing if they fail the basic checks */ - DEBUG(0,("Can't become connected user!\n")); - conn_free(conn); - *status = NT_STATUS_LOGON_FAILURE; - return NULL; - } - /* ROOT Activities: */ - become_root(); /* check number of connections */ if (!claim_connection(conn, lp_servicename(SNUM(conn)), @@ -575,8 +574,6 @@ connection_struct *make_connection(char *service,char *password, DEBUG(1,("too many connections - rejected\n")); *status = NT_STATUS_INSUFFICIENT_RESOURCES; conn_free(conn); - unbecome_root(); - unbecome_user(); return NULL; } @@ -596,14 +593,19 @@ connection_struct *make_connection(char *service,char *password, lp_max_connections(SNUM(conn))); conn_free(conn); *status = NT_STATUS_UNSUCCESSFUL; - unbecome_root(); - unbecome_user(); return NULL; } } - unbecome_root(); /* USER Activites: */ + if (!change_to_user(conn, conn->vuid)) { + /* No point continuing if they fail the basic checks */ + DEBUG(0,("Can't become connected user!\n")); + conn_free(conn); + *status = NT_STATUS_LOGON_FAILURE; + return NULL; + } + /* Remember that a different vuid can connect later without these checks... */ /* Preexecs are done here as they might make the dir we are to ChDir to below */ @@ -616,7 +618,7 @@ connection_struct *make_connection(char *service,char *password, ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); - unbecome_user(); + change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); conn_free(conn); *status = NT_STATUS_UNSUCCESSFUL; @@ -628,7 +630,7 @@ connection_struct *make_connection(char *service,char *password, DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", remote_machine, conn->client_address, conn->connectpath,strerror(errno))); - unbecome_user(); + change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); @@ -677,14 +679,14 @@ connection_struct *make_connection(char *service,char *password, if (conn->vfs_ops.connect(conn, service, user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); *status = NT_STATUS_UNSUCCESSFUL; - unbecome_user(); + change_to_root_user(); conn_free(conn); return NULL; } } - /* we've finished with the sensitive stuff */ - unbecome_user(); + /* we've finished with the user stuff - go back to root */ + change_to_root_user(); return(conn); } @@ -697,7 +699,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) { DirCacheFlush(SNUM(conn)); - unbecome_user(); + change_to_root_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", remote_machine,conn->client_address, @@ -720,15 +722,15 @@ void close_cnum(connection_struct *conn, uint16 vuid) /* execute any "postexec = " line */ if (*lp_postexec(SNUM(conn)) && - become_user(conn, vuid)) { + change_to_user(conn, vuid)) { pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); standard_sub_conn(conn,cmd); smbrun(cmd,NULL); - unbecome_user(); + change_to_root_user(); } - unbecome_user(); + change_to_root_user(); /* execute any "root postexec = " line */ if (*lp_rootpostexec(SNUM(conn))) { pstring cmd; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 39bdaaa596..b1012c3c91 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -25,10 +25,10 @@ extern struct current_user current_user; /**************************************************************************** - Become the guest user. + Become the guest user without changing the security context stack. ****************************************************************************/ -BOOL become_guest(void) +BOOL change_to_guest(void) { static struct passwd *pass=NULL; static uid_t guest_uid = (uid_t)-1; @@ -82,10 +82,11 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) } /**************************************************************************** - Become the user of a connection number. + Become the user of a connection number without changing the security context + stack, but modify the currnet_user entries. ****************************************************************************/ -BOOL become_user(connection_struct *conn, uint16 vuid) +BOOL change_to_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; @@ -96,7 +97,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) NT_USER_TOKEN *token = NULL; if (!conn) { - DEBUG(2,("Connection not open\n")); + DEBUG(2,("change_to_user: Connection not open\n")); return(False); } @@ -109,12 +110,12 @@ BOOL become_user(connection_struct *conn, uint16 vuid) if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && (current_user.uid == conn->uid)) { - DEBUG(4,("Skipping become_user - already user\n")); + DEBUG(4,("change_to_user: Skipping user change - already user\n")); return(True); } else if ((current_user.conn == conn) && (vuser != 0) && (current_user.vuid == vuid) && (current_user.uid == vuser->uid)) { - DEBUG(4,("Skipping become_user - already user\n")); + DEBUG(4,("change_to_user: Skipping user change - already user\n")); return(True); } @@ -133,7 +134,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) token = conn->nt_user_token; } else { if (!vuser) { - DEBUG(2,("Invalid vuid used %d\n",vuid)); + DEBUG(2,("change_to_user: Invalid vuid used %d\n",vuid)); return(False); } uid = vuser->uid; @@ -196,21 +197,22 @@ BOOL become_user(connection_struct *conn, uint16 vuid) current_user.conn = conn; current_user.vuid = vuid; - DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", + DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); return(True); } /**************************************************************************** - Unbecome the user of a connection number. + Go back to being root without changing the security context stack, + but modify the current_user entries. ****************************************************************************/ -BOOL unbecome_user(void ) +BOOL change_to_root_user(void) { set_root_sec_ctx(); - DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", + DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); current_user.conn = NULL; @@ -222,16 +224,13 @@ BOOL unbecome_user(void ) /**************************************************************************** Become the user of an authenticated connected named pipe. When this is called we are currently running as the connection - user. + user. Doesn't modify current_user. ****************************************************************************/ BOOL become_authenticated_pipe_user(pipes_struct *p) { - BOOL res = push_sec_ctx(); - - if (!res) { + if (!push_sec_ctx()) return False; - } set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token); @@ -242,19 +241,93 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) /**************************************************************************** Unbecome the user of an authenticated connected named pipe. When this is called we are running as the authenticated pipe - user and need to go back to being the connection user. + user and need to go back to being the connection user. Doesn't modify + current_user. ****************************************************************************/ -BOOL unbecome_authenticated_pipe_user(pipes_struct *p) +BOOL unbecome_authenticated_pipe_user(void) { return pop_sec_ctx(); } -/* Temporarily become a root user. Must match with unbecome_root(). */ +/**************************************************************************** + Utility functions used by become_xxx/unbecome_xxx. +****************************************************************************/ + +struct conn_ctx { + connection_struct *conn; + uint16 vuid; +}; + +/* A stack of current_user connection contexts. */ + +static struct conn_ctx conn_ctx_stack[MAX_SEC_CTX_DEPTH]; +static int conn_ctx_stack_ndx; + +static void push_conn_ctx(void) +{ + struct conn_ctx *ctx_p; + + /* Check we don't overflow our stack */ + + if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) { + DEBUG(0, ("Connection context stack overflow!\n")); + smb_panic("Connection context stack overflow!\n"); + } + + /* Store previous user context */ + ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx]; + + ctx_p->conn = current_user.conn; + ctx_p->vuid = current_user.vuid; + + DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n", + (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx )); + + conn_ctx_stack_ndx++; +} + +static void pop_conn_ctx(void) +{ + struct conn_ctx *ctx_p; + + /* Check for stack underflow. */ + + if (conn_ctx_stack_ndx == 0) { + DEBUG(0, ("Connection context stack underflow!\n")); + smb_panic("Connection context stack underflow!\n"); + } + + conn_ctx_stack_ndx--; + ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx]; + + current_user.conn = ctx_p->conn; + current_user.vuid = ctx_p->vuid; + + ctx_p->conn = NULL; + ctx_p->vuid = UID_FIELD_INVALID; +} + +void init_conn_ctx(void) +{ + int i; + + /* Initialise connection context stack */ + for (i = 0; i < MAX_SEC_CTX_DEPTH; i++) { + conn_ctx_stack[i].conn = NULL; + conn_ctx_stack[i].vuid = UID_FIELD_INVALID; + } +} + +/**************************************************************************** + Temporarily become a root user. Must match with unbecome_root(). Saves and + restores the connection context. +****************************************************************************/ void become_root(void) { push_sec_ctx(); + push_conn_ctx(); set_root_sec_ctx(); } @@ -263,6 +336,35 @@ void become_root(void) void unbecome_root(void) { pop_sec_ctx(); + pop_conn_ctx(); +} + +/**************************************************************************** + Push the current security context then force a change via change_to_user(). + Saves and restores the connection context. +****************************************************************************/ + +BOOL become_user(connection_struct *conn, uint16 vuid) +{ + if (!push_sec_ctx()) + return False; + + push_conn_ctx(); + + if (!change_to_user(conn, vuid)) { + pop_sec_ctx(); + pop_conn_ctx(); + return False; + } + + return True; +} + +BOOL unbecome_user() +{ + pop_sec_ctx(); + pop_conn_ctx(); + return True; } /***************************************************************** -- cgit From b49b5b94818827da43dee53346ced84c789fd73d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2001 00:02:36 +0000 Subject: client : Fixed error return. uid.c: Added missing void. Jeremy. (This used to be commit c2e06ed2219860479868fd1ac18013ae4f891e10) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b1012c3c91..2151068de5 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -360,7 +360,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) return True; } -BOOL unbecome_user() +BOOL unbecome_user(void) { pop_sec_ctx(); pop_conn_ctx(); -- cgit From 6cc3953196e3feb340f7b9b7bb823575414c5683 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2001 00:56:03 +0000 Subject: Restored old Bmpx code - actually used by OS/2. Jeremy. (This used to be commit 7c1688fd67c1bda1477aaf870371c825280db870) --- source3/smbd/error.c | 16 +++ source3/smbd/process.c | 8 +- source3/smbd/reply.c | 304 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 267 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 913f2ac266..3c829deb09 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -25,6 +25,22 @@ int unix_ERR_class=SMB_SUCCESS; int unix_ERR_code=0; +/**************************************************************************** + Create an error packet from a cached error. +****************************************************************************/ + +int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file) +{ + write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; + + int32 eclass = wbmpx->wr_errclass; + int32 err = wbmpx->wr_error; + + /* We can now delete the auxiliary struct */ + free((char *)wbmpx); + fsp->wbmpx_ptr = NULL; + return error_packet(outbuf,NT_STATUS_OK,eclass,err,line,file); +} struct { diff --git a/source3/smbd/process.c b/source3/smbd/process.c index edcb6b345f..a0bfdbb2a2 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -361,11 +361,11 @@ struct smb_message_struct /* 0x19 */ { NULL, NULL, 0 }, /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER}, /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER}, -/* 0x1c */ { "SMBreadBs",NULL,AS_USER}, +/* 0x1c */ { "SMBreadBs",NULL,0 }, /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER}, -/* 0x1e */ { NULL,NULL,0}, -/* 0x1f */ { NULL,NULL,0}, -/* 0x20 */ { NULL,NULL,0}, +/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER}, +/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER}, +/* 0x20 */ { "SMBwritec",NULL,0}, /* 0x21 */ { NULL, NULL, 0 }, /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8b6e754549..845fabda92 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3786,84 +3786,83 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return chain_reply(inbuf,outbuf,length,bufsize); } - /**************************************************************************** - reply to a SMBreadbmpx (read block multiplex) request + Reply to a SMBreadbmpx (read block multiplex) request. ****************************************************************************/ + int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - ssize_t nread = -1; - ssize_t total_read; - char *data; - SMB_OFF_T startpos; - int outsize; - size_t maxcount; - int max_per_packet; - size_t tcount; - int pad; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBreadBmpx); + ssize_t nread = -1; + ssize_t total_read; + char *data; + SMB_OFF_T startpos; + int outsize; + size_t maxcount; + int max_per_packet; + size_t tcount; + int pad; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBreadBmpx); - /* this function doesn't seem to work - disable by default */ - if (!lp_readbmpx()) { - END_PROFILE(SMBreadBmpx); - return ERROR_DOS(ERRSRV,ERRuseSTD); - } + /* this function doesn't seem to work - disable by default */ + if (!lp_readbmpx()) { + END_PROFILE(SMBreadBmpx); + return ERROR_DOS(ERRSRV,ERRuseSTD); + } - outsize = set_message(outbuf,8,0,True); + outsize = set_message(outbuf,8,0,True); - CHECK_FSP(fsp,conn); - CHECK_READ(fsp); + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); - startpos = IVAL(inbuf,smb_vwv1); - maxcount = SVAL(inbuf,smb_vwv3); + startpos = IVAL(inbuf,smb_vwv1); + maxcount = SVAL(inbuf,smb_vwv3); - data = smb_buf(outbuf); - pad = ((long)data)%4; - if (pad) pad = 4 - pad; - data += pad; + data = smb_buf(outbuf); + pad = ((long)data)%4; + if (pad) + pad = 4 - pad; + data += pad; - max_per_packet = bufsize-(outsize+pad); - tcount = maxcount; - total_read = 0; + max_per_packet = bufsize-(outsize+pad); + tcount = maxcount; + total_read = 0; - if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { - END_PROFILE(SMBreadBmpx); - return ERROR_DOS(ERRDOS,ERRlock); - } + if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + END_PROFILE(SMBreadBmpx); + return ERROR_DOS(ERRDOS,ERRlock); + } - do - { - size_t N = MIN(max_per_packet,tcount-total_read); + do { + size_t N = MIN(max_per_packet,tcount-total_read); - nread = read_file(fsp,data,startpos,N); + nread = read_file(fsp,data,startpos,N); - if (nread <= 0) nread = 0; + if (nread <= 0) + nread = 0; - if (nread < (ssize_t)N) - tcount = total_read + nread; + if (nread < (ssize_t)N) + tcount = total_read + nread; - set_message(outbuf,8,nread,False); - SIVAL(outbuf,smb_vwv0,startpos); - SSVAL(outbuf,smb_vwv2,tcount); - SSVAL(outbuf,smb_vwv6,nread); - SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); + set_message(outbuf,8,nread,False); + SIVAL(outbuf,smb_vwv0,startpos); + SSVAL(outbuf,smb_vwv2,tcount); + SSVAL(outbuf,smb_vwv6,nread); + SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_readbmpx: send_smb failed.\n"); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_readbmpx: send_smb failed.\n"); - total_read += nread; - startpos += nread; - } - while (total_read < (ssize_t)tcount); + total_read += nread; + startpos += nread; + } while (total_read < (ssize_t)tcount); - END_PROFILE(SMBreadBmpx); - return(-1); + END_PROFILE(SMBreadBmpx); + return(-1); } - /**************************************************************************** - reply to a SMBsetattrE + Reply to a SMBsetattrE. ****************************************************************************/ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) @@ -3919,8 +3918,199 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, } +/* Back from the dead for OS/2..... JRA. */ + +/**************************************************************************** + Reply to a SMBwritebmpx (write block multiplex primary) request. +****************************************************************************/ + +int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +{ + size_t numtowrite; + ssize_t nwritten = -1; + int outsize = 0; + SMB_OFF_T startpos; + size_t tcount; + BOOL write_through; + int smb_doff; + char *data; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBwriteBmpx); + + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + CHECK_ERROR(fsp); + + tcount = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv3); + write_through = BITSETW(inbuf+smb_vwv7,0); + numtowrite = SVAL(inbuf,smb_vwv10); + smb_doff = SVAL(inbuf,smb_vwv11); + + data = smb_base(inbuf) + smb_doff; + + /* If this fails we need to send an SMBwriteC response, + not an SMBwritebmpx - set this up now so we don't forget */ + CVAL(outbuf,smb_com) = SMBwritec; + + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) { + END_PROFILE(SMBwriteBmpx); + return(ERROR_DOS(ERRDOS,ERRlock)); + } + + nwritten = write_file(fsp,data,startpos,numtowrite); + + if(lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fsp); + + if(nwritten < (ssize_t)numtowrite) { + END_PROFILE(SMBwriteBmpx); + return(UNIXERROR(ERRHRD,ERRdiskfull)); + } + + /* If the maximum to be written to this file + is greater than what we just wrote then set + up a secondary struct to be attached to this + fd, we will use this to cache error messages etc. */ + + if((ssize_t)tcount > nwritten) { + write_bmpx_struct *wbms; + if(fsp->wbmpx_ptr != NULL) + wbms = fsp->wbmpx_ptr; /* Use an existing struct */ + else + wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); + if(!wbms) { + DEBUG(0,("Out of memory in reply_readmpx\n")); + END_PROFILE(SMBwriteBmpx); + return(ERROR_DOS(ERRSRV,ERRnoresource)); + } + wbms->wr_mode = write_through; + wbms->wr_discard = False; /* No errors yet */ + wbms->wr_total_written = nwritten; + wbms->wr_errclass = 0; + wbms->wr_error = 0; + fsp->wbmpx_ptr = wbms; + } + + /* We are returning successfully, set the message type back to + SMBwritebmpx */ + CVAL(outbuf,smb_com) = SMBwriteBmpx; + + outsize = set_message(outbuf,1,0,True); + + SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ + + DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n", + fsp->fnum, (int)numtowrite, (int)nwritten ) ); + + if (write_through && tcount==nwritten) { + /* We need to send both a primary and a secondary response */ + smb_setlen(outbuf,outsize - 4); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_writebmpx: send_smb failed.\n"); + + /* Now the secondary */ + outsize = set_message(outbuf,1,0,True); + CVAL(outbuf,smb_com) = SMBwritec; + SSVAL(outbuf,smb_vwv0,nwritten); + } + + END_PROFILE(SMBwriteBmpx); + return(outsize); +} + +/**************************************************************************** + Reply to a SMBwritebs (write block multiplex secondary) request. +****************************************************************************/ + +int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +{ + size_t numtowrite; + ssize_t nwritten = -1; + int outsize = 0; + SMB_OFF_T startpos; + size_t tcount; + BOOL write_through; + int smb_doff; + char *data; + write_bmpx_struct *wbms; + BOOL send_response = False; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBwriteBs); + + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + + tcount = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + numtowrite = SVAL(inbuf,smb_vwv6); + smb_doff = SVAL(inbuf,smb_vwv7); + + data = smb_base(inbuf) + smb_doff; + + /* We need to send an SMBwriteC response, not an SMBwritebs */ + CVAL(outbuf,smb_com) = SMBwritec; + + /* This fd should have an auxiliary struct attached, + check that it does */ + wbms = fsp->wbmpx_ptr; + if(!wbms) { + END_PROFILE(SMBwriteBs); + return(-1); + } + + /* If write through is set we can return errors, else we must cache them */ + write_through = wbms->wr_mode; + + /* Check for an earlier error */ + if(wbms->wr_discard) { + END_PROFILE(SMBwriteBs); + return -1; /* Just discard the packet */ + } + + nwritten = write_file(fsp,data,startpos,numtowrite); + + if(lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fsp); + + if (nwritten < (ssize_t)numtowrite) { + if(write_through) { + /* We are returning an error - we can delete the aux struct */ + if (wbms) + free((char *)wbms); + fsp->wbmpx_ptr = NULL; + END_PROFILE(SMBwriteBs); + return(ERROR_DOS(ERRHRD,ERRdiskfull)); + } + END_PROFILE(SMBwriteBs); + return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); + } + + /* Increment the total written, if this matches tcount + we can discard the auxiliary struct (hurrah !) and return a writeC */ + wbms->wr_total_written += nwritten; + if(wbms->wr_total_written >= tcount) { + if (write_through) { + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); + send_response = True; + } + + free((char *)wbms); + fsp->wbmpx_ptr = NULL; + } + + if(send_response) { + END_PROFILE(SMBwriteBs); + return(outsize); + } + + END_PROFILE(SMBwriteBs); + return(-1); +} + /**************************************************************************** - reply to a SMBgetattrE + Reply to a SMBgetattrE. ****************************************************************************/ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) -- cgit From 4bb9cebf84e1addc135c18b1227e7c00e7c03163 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2001 08:37:32 +0000 Subject: Tidy up debug in notify code. Jeremy. (This used to be commit 7707c5e07385ce5ac3732715d586ad6c6b41de65) --- source3/smbd/notify.c | 30 ++++++++++++++++++------------ source3/smbd/notify_hash.c | 29 +++++++++++++++++------------ 2 files changed, 35 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 999821354e..d333e0f75a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -28,7 +28,7 @@ static struct cnotify_fns *cnotify; This is the structure to queue to implement NT change notify. It consists of smb_size bytes stored from the transact command (to keep the mid, tid etc around). - Plus the fid to examine and notify private data + Plus the fid to examine and notify private data. *****************************************************************************/ struct change_notify { @@ -65,10 +65,10 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) } /**************************************************************************** -remove an entry from the list and free it, also closing any -directory handle if necessary -Notice the horrible stuff we have to do because this is a singly linked list. + Remove an entry from the list and free it, also closing any + directory handle if necessary. *****************************************************************************/ + static void change_notify_remove(struct change_notify *cnbp) { cnotify->remove_notify(cnbp->change_data); @@ -77,10 +77,10 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } - /**************************************************************************** Delete entries by fnum from the change notify pending queue. *****************************************************************************/ + void remove_pending_change_notify_requests_by_fid(files_struct *fsp) { struct change_notify *cnbp, *next; @@ -96,6 +96,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp) /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ + void remove_pending_change_notify_requests_by_mid(int mid) { struct change_notify *cnbp, *next; @@ -113,6 +114,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) Delete entries by filename and cnum from the change notify pending queue. Always send reply. *****************************************************************************/ + void remove_pending_change_notify_requests_by_filename(files_struct *fsp) { struct change_notify *cnbp, *next; @@ -133,6 +135,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) /**************************************************************************** Return true if there are pending change notifies. ****************************************************************************/ + int change_notify_timeout(void) { return cnotify->select_time; @@ -143,6 +146,7 @@ int change_notify_timeout(void) Returns True if there are still outstanding change notify requests on the queue. *****************************************************************************/ + BOOL process_pending_change_notify_queue(time_t t) { struct change_notify *cnbp, *next; @@ -152,8 +156,9 @@ BOOL process_pending_change_notify_queue(time_t t) next=cnbp->next; vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - + if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); change_notify_remove(cnbp); } @@ -163,11 +168,12 @@ BOOL process_pending_change_notify_queue(time_t t) } /**************************************************************************** - * Now queue an entry on the notify change list. - * We only need to save smb_size bytes from this incoming packet - * as we will always by returning a 'read the directory yourself' - * error. + Now queue an entry on the notify change list. + We only need to save smb_size bytes from this incoming packet + as we will always by returning a 'read the directory yourself' + error. ****************************************************************************/ + BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) { struct change_notify *cnbp; @@ -195,10 +201,10 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, return True; } - /**************************************************************************** -initialise the change notify subsystem + Initialise the change notify subsystem. ****************************************************************************/ + BOOL init_change_notify(void) { #if HAVE_KERNEL_CHANGE_NOTIFY diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index d398fac214..415e4bcbda 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -30,10 +30,10 @@ struct change_data { unsigned int num_entries; /* Zero or the number of files in the directory. */ }; - /**************************************************************************** Create the hash we will use to determine if the contents changed. *****************************************************************************/ + static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, struct change_data *data, struct change_data *old_data) { @@ -47,7 +47,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, ZERO_STRUCTP(data); - if(vfs_stat(conn,path, &st) == -1) return False; + if(vfs_stat(conn,path, &st) == -1) + return False; data->modify_time = st.st_mtime; data->status_time = st.st_ctime; @@ -73,10 +74,12 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * larger than the max time_t value). */ - if (!(flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE))) return True; + if (!(flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE))) + return True; dp = OpenDir(conn, path, True); - if (dp == NULL) return False; + if (dp == NULL) + return False; data->num_entries = 0; @@ -88,7 +91,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, p = &full_name[fullname_len]; while ((fname = ReadDirName(dp))) { - if(strequal(fname, ".") || strequal(fname, "..")) continue; + if(strequal(fname, ".") || strequal(fname, "..")) + continue; data->num_entries++; safe_strcpy(p, fname, remaining_len); @@ -107,15 +111,16 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, return True; } - /**************************************************************************** -register a change notify request + Register a change notify request. *****************************************************************************/ + static void *hash_register_notify(connection_struct *conn, char *path, uint32 flags) { struct change_data data; - if (!notify_hash(conn, path, flags, &data, NULL)) return NULL; + if (!notify_hash(conn, path, flags, &data, NULL)) + return NULL; data.last_check_time = time(NULL); @@ -160,17 +165,18 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, } /**************************************************************************** -remove a change notify data structure + Remove a change notify data structure. *****************************************************************************/ + static void hash_remove_notify(void *datap) { SAFE_FREE(datap); } - /**************************************************************************** -setup hash based change notify + Setup hash based change notify. ****************************************************************************/ + struct cnotify_fns *hash_notify_init(void) { static struct cnotify_fns cnotify; @@ -183,7 +189,6 @@ struct cnotify_fns *hash_notify_init(void) return &cnotify; } - /* change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); -- cgit From f1cd7f14e2ca76a713118e0ac66e4fa89629f7f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2001 09:41:35 +0000 Subject: Fixed issues with changenotify only being called once in VC++. Jeremy. (This used to be commit ce59e4a7729c45f3a84d877e1dbdfffa984060b9) --- source3/smbd/notify_hash.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 415e4bcbda..b4edc258e9 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -28,6 +28,8 @@ struct change_data { time_t status_time; /* Info from the directory we're monitoring. */ time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ unsigned int num_entries; /* Zero or the number of files in the directory. */ + unsigned int mode_sum; + unsigned char name_hash[16]; }; /**************************************************************************** @@ -74,9 +76,6 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * larger than the max time_t value). */ - if (!(flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE))) - return True; - dp = OpenDir(conn, path, True); if (dp == NULL) return False; @@ -103,7 +102,31 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * Do the stat - but ignore errors. */ vfs_stat(conn,full_name, &st); + + /* + * Always sum the times. + */ + data->total_time += (st.st_mtime + st.st_ctime); + + /* + * If requested hash the names. + */ + + if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_FILE)) { + int i; + unsigned char tmp_hash[16]; + mdfour(tmp_hash, fname, strlen(fname)); + for (i=0;i<16;i++) + data->name_hash[i] ^= tmp_hash[i]; + } + + /* + * If requested sum the mode_t's. + */ + + if (flags & (FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SECURITY)) + data->mode_sum = st.st_mode; } CloseDir(dp); @@ -151,7 +174,9 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, data2.modify_time != data->modify_time || data2.status_time != data->status_time || data2.total_time != data->total_time || - data2.num_entries != data->num_entries) { + data2.num_entries != data->num_entries || + data2.mode_sum != data->mode_sum || + memcmp(data2.name_hash, data->name_hash, sizeof(data2.name_hash))) { change_to_root_user(); return True; } -- cgit From 4be5c040b6463b066ca5adec7a85dc6f87d9fb97 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Fri, 19 Oct 2001 17:30:05 +0000 Subject: print in a human readable format when the password expired. J.F. (This used to be commit 255b197a5c92bfc18a567613bbffb013fd0a834d) --- source3/smbd/auth_smbpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 26b9001bf6..a525248461 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -260,7 +260,7 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user /* check for expired password */ if (must_change_time < time(NULL) && must_change_time != 0) { DEBUG(1,("Account for user '%s' password expired!.\n", sampass->username)); - DEBUG(1,("Password expired at '%ld' unix time.\n", (long)must_change_time)); + DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); return NT_STATUS_PASSWORD_EXPIRED; } } -- cgit From d1006a96d075d3dca97915b5c39b58b0f48a419f Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 19 Oct 2001 19:13:11 +0000 Subject: Add RAP net share add support (This used to be commit a70bc077a1ecc4b42254f83327c8d80c618e95f6) --- source3/smbd/lanman.c | 144 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 088162c126..0d92c98628 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1655,6 +1655,87 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c return(True); } +/**************************************************************************** + Add a share + ****************************************************************************/ +static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + fstring sharename; + fstring comment; + pstring pathname; + pstring command; + int offset; + int snum; + int res; + + /* check it's a supported varient */ + if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False; + if (!check_share_info(uLevel,str2)) return False; + if (uLevel != 2) { + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + *rdata_len = 0; + SSVAL(*rparam,0,NERR_notsupported); + SSVAL(*rparam,2,0); + return True; + } + + pull_ascii_fstring(sharename,data); + snum = find_service(sharename); + if (snum >= 0) { /* already exists */ + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + SSVAL(*rparam,0,ERRfilexists); + SSVAL(*rparam,2,0); + return True; + } + + /* only support disk share adds */ + if (SVAL(data,14)!=STYPE_DISKTREE) { + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + *rdata_len = 0; + SSVAL(*rparam,0,NERR_notsupported); + SSVAL(*rparam,2,0); + return True; + } + + offset = IVAL(data, 16); + pull_ascii_fstring(comment, offset? (data+offset) : ""); + offset = IVAL(data, 26); + pull_ascii_pstring(pathname, offset? (data+offset) : ""); + + string_replace(sharename, '"', ' '); + string_replace(pathname, '"', ' '); + string_replace(comment, '"', ' '); + + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"", + lp_add_share_cmd(), CONFIGFILE, sharename, pathname, comment); + + DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); + if ((res = smbrun(command, NULL)) != 0) { + DEBUG(0,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); + return ERRnoaccess; + } else + message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False); + return True; + + *rparam_len = 6; + *rparam = REALLOC(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + *rdata_len = 0; + + return(True); +} /**************************************************************************** view list of groups available @@ -3379,37 +3460,38 @@ struct int,int,char **,char **,int *,int *); int flags; } api_commands[] = { - {"RNetShareEnum", 0, api_RNetShareEnum,0}, - {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, - {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, - {"RNetGroupEnum", 47, api_RNetGroupEnum,0}, - {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0}, - {"RNetUserEnum", 53, api_RNetUserEnum,0}, - {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, - {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, - {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, - {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, - {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, - {"WPrintQueuePause", 74, api_WPrintQueueCtrl,0}, - {"WPrintQueueResume", 75, api_WPrintQueueCtrl,0}, - {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, - {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, - {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, - {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0}, - {"RDosPrintJobResume",83, api_RDosPrintJobDel,0}, - {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, - {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, - {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, - {"WPrintQueuePurge", 103, api_WPrintQueueCtrl,0}, - {"NetServerEnum", 104, api_RNetServerEnum,0}, - {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, - {"SetUserPassword", 115, api_SetUserPassword,0}, - {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0}, - {"PrintJobInfo", 147, api_PrintJobInfo,0}, - {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0}, - {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0}, - {"WPrintPortEnum", 207, api_WPrintPortEnum,0}, - {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0}, + {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum,0}, + {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo,0}, + {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd,0}, + {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo,0}, + {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum,0}, + {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers,0}, + {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum,0}, + {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo,0}, + {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups,0}, + {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo,0}, + {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum,0}, + {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo,0}, + {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl,0}, + {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl,0}, + {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate,0}, + {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo,0}, + {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel,0}, + {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel,0}, + {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel,0}, + {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum,0}, + {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo,0}, + {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD,0}, + {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl,0}, + {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum,0}, + {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms,0}, + {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword,0}, + {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon,0}, + {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo,0}, + {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum,0}, + {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum,0}, + {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum,0}, + {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword,0}, {NULL, -1, api_Unsupported,0}}; -- cgit From 42fd55bd618fbc61769322c33eabcecb909c2d48 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 20 Oct 2001 00:48:28 +0000 Subject: quick fix for krb5 compilation. I've told vance how to fix this module properly and will wait for him to send a patch (This used to be commit 7adad774d872a3f2424f49f364416e7c42409b90) --- source3/smbd/build_options.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index c3d24b69a7..7afd2c5652 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -86,11 +86,8 @@ void build_options(BOOL screen) snprintf(outstring,sizeof(outstring)," KRB4_DIR: %s\n",KRB4_DIR); output(screen,outstring); #endif -#if defined(KRB5_AUTH) && defined(KRB5_DIR) - snprintf(outstring,sizeof(outstring)," KRB5_AUTH"); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," KRB5_DIR: %s\n",KRB5_DIR); - output(screen,outstring); +#if HAVE_KRB5 + output(screen," HAVE_KRB5"); #endif #ifdef WITH_AUTOMOUNT snprintf(outstring,sizeof(outstring)," WITH_AUTOMOUNT\n"); -- cgit From e82c34aab5f5e5e1bf7375d10ea9fa5ec578506d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 20 Oct 2001 06:29:52 +0000 Subject: add non_root_mode() check (This used to be commit 96f910bae510fb45e2f1181c1e3ad607a50a64d7) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9e3f3c9f11..a871192ad5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -334,7 +334,7 @@ connection_struct *make_connection(char *service,char *password, ZERO_STRUCT(user); /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ - if ((euid = geteuid()) != 0) { + if (!non_root_mode() && (euid = geteuid()) != 0) { DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); } -- cgit From 9884de2d3b00c560daa68930fb31cec23a0c6d44 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 20 Oct 2001 06:31:25 +0000 Subject: finished auth when we get a valid kerberos ticket smbd now works with kerberos authentication if you use a MIT KDC and smbclient. Next step is to make it work with a windows client (This used to be commit e0c99e1f3708b155b8db99950f9ac6e27763368f) --- source3/smbd/sesssetup.c | 66 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7eb8f4e694..0202a247cd 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -26,7 +26,9 @@ /**************************************************************************** reply to a session setup spnego negotiate packet for kerberos ****************************************************************************/ -static int reply_spnego_kerberos(connection_struct *conn, char *outbuf, +static int reply_spnego_kerberos(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, DATA_BLOB *secblob) { DATA_BLOB ticket; @@ -37,9 +39,15 @@ static int reply_spnego_kerberos(connection_struct *conn, char *outbuf, krb5_data packet; krb5_ticket *tkt = NULL; int ret; - char *realm, *client; + char *realm, *client, *p; fstring service; extern pstring global_myname; + const struct passwd *pw; + char *user; + gid_t gid; + uid_t uid; + char *full_name; + int sess_vuid; realm = lp_realm(); @@ -79,11 +87,48 @@ static int reply_spnego_kerberos(connection_struct *conn, char *outbuf, DEBUG(3,("Ticket name is [%s]\n", client)); - /* well, if we got a client above then I think we have authenticated the user - but fail it for now until I understand it */ + p = strchr_m(client, '@'); + if (!p) { + DEBUG(3,("Doesn't look like a valid principle\n")); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + *p = 0; + if (strcasecmp(p+1, realm) != 0) { + DEBUG(3,("Ticket for incorrect realm %s\n", p+1)); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + user = client; + + /* the password is good - let them in */ + pw = smb_getpwnam(user,False); + if (!pw) { + DEBUG(1,("Username %s is invalid on this system\n",user)); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + gid = pw->pw_gid; + uid = pw->pw_uid; + full_name = pw->pw_gecos; + sess_vuid = register_vuid(uid,gid,user,user,realm,False, full_name); + + if (sess_vuid == -1) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + set_message(outbuf,4,0,True); + SSVAL(outbuf, smb_vwv3, 0); + p = smb_buf(outbuf); + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); + + SSVAL(outbuf,smb_uid,sess_vuid); + SSVAL(inbuf,smb_uid,sess_vuid); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return chain_reply(inbuf,outbuf,length,bufsize); } #endif @@ -118,7 +163,10 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, /**************************************************************************** reply to a session setup spnego negotiate packet ****************************************************************************/ -static int reply_spnego_negotiate(connection_struct *conn, char *outbuf, +static int reply_spnego_negotiate(connection_struct *conn, + char *inbuf, + char *outbuf, + int length, int bufsize, DATA_BLOB blob1) { char *OIDs[ASN1_MAX_OIDS]; @@ -145,7 +193,8 @@ static int reply_spnego_negotiate(connection_struct *conn, char *outbuf, #if HAVE_KRB5 if (got_kerberos) { - int ret = reply_spnego_kerberos(conn, outbuf, &secblob); + int ret = reply_spnego_kerberos(conn, inbuf, outbuf, + length, bufsize, &secblob); data_blob_free(&secblob); return ret; } @@ -331,12 +380,13 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha blob1 = data_blob(p, SVAL(inbuf, smb_vwv7)); #if 0 + chdir("/home/tridge"); file_save("negotiate.dat", blob1.data, blob1.length); #endif if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ - ret = reply_spnego_negotiate(conn, outbuf, blob1); + ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1); data_blob_free(&blob1); return ret; } -- cgit From 93645be91f7fd12dfee75b6f09dda6799f0ac902 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 20 Oct 2001 06:50:24 +0000 Subject: better krb5 error handling (thanks andrewb!) (This used to be commit fd3a3daef3b8f7140e7006d30d23d739ac3aad2f) --- source3/smbd/negprot.c | 2 +- source3/smbd/sesssetup.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 678156b528..2eea6fa281 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -163,7 +163,7 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) DATA_BLOB blob; extern pstring global_myname; uint8 guid[16]; - const char *OIDs[] = {OID_NTLMSSP, + const char *OIDs[] = {OID_NTLMSSP, OID_KERBEROS5_OLD, NULL}; char *principle; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0202a247cd..c8bf2a4f94 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -62,12 +62,14 @@ static int reply_spnego_kerberos(connection_struct *conn, ret = krb5_init_context(&context); if (ret) { + DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } ret = krb5_build_principal(context, &server, strlen(realm), realm, service, NULL); if (ret) { + DEBUG(1,("krb5_build_principal failed (%s)\n", error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -76,12 +78,15 @@ static int reply_spnego_kerberos(connection_struct *conn, if ((ret = krb5_rd_req(context, &auth_context, &packet, server, keytab, NULL, &tkt))) { - DEBUG(3,("krb5_rd_req failed with code %08x\n", ret)); + DEBUG(3,("krb5_rd_req failed (%s)\n", + error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, &client))) { + DEBUG(3,("krb5_unparse_name failed (%s)\n", + error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -- cgit From 60747ab66e768ac6801838c460a1a4fc8bba32cf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 20 Oct 2001 11:47:44 +0000 Subject: crude fix for anonymous session setup with extended security negotiated (This used to be commit b3caf2109090cb2b97a829913bee7e50e7eacba8) --- source3/smbd/sesssetup.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c8bf2a4f94..1ca7066c41 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -66,8 +66,15 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } +#if 0 + ret = krb5_build_principal(context, &server, strlen(realm), + realm, "HOST", "blu", NULL); +#else ret = krb5_build_principal(context, &server, strlen(realm), realm, service, NULL); +#endif + krb5_princ_type(context, server) = KRB5_NT_PRINCIPAL; + if (ret) { DEBUG(1,("krb5_build_principal failed (%s)\n", error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); @@ -364,6 +371,55 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, } +/**************************************************************************** +reply to a session setup spnego anonymous packet +****************************************************************************/ +static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf, + int length, int bufsize) +{ + char *user; + int sess_vuid; + gid_t gid; + uid_t uid; + char *full_name; + char *p; + const struct passwd *pw; + + DEBUG(3,("Got anonymous request\n")); + + user = lp_guestaccount(-1); + + /* the password is good - let them in */ + pw = smb_getpwnam(user,False); + if (!pw) { + DEBUG(1,("Guest username %s is invalid on this system\n",user)); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + gid = pw->pw_gid; + uid = pw->pw_uid; + full_name = pw->pw_gecos; + + sess_vuid = register_vuid(uid,gid,user,user,lp_workgroup(),True,full_name); + + if (sess_vuid == -1) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + set_message(outbuf,4,0,True); + SSVAL(outbuf, smb_vwv3, 0); + p = smb_buf(outbuf); + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); + + SSVAL(outbuf,smb_uid,sess_vuid); + SSVAL(inbuf,smb_uid,sess_vuid); + + return chain_reply(inbuf,outbuf,length,bufsize); +} + + /**************************************************************************** reply to a session setup command ****************************************************************************/ @@ -381,9 +437,14 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha p = smb_buf(inbuf); + if (SVAL(inbuf, smb_vwv7) == 0) { + /* an anonymous request */ + return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize); + } + /* pull the spnego blob */ blob1 = data_blob(p, SVAL(inbuf, smb_vwv7)); - + #if 0 chdir("/home/tridge"); file_save("negotiate.dat", blob1.data, blob1.length); -- cgit From e5868e1f57c1de537a7385a81d23671a727af5f5 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Sat, 20 Oct 2001 21:50:51 +0000 Subject: Use asprintf, do bounds check, better rc logic (This used to be commit 6a734158d92663873b7a9df517bec45a27ee9790) --- source3/smbd/lanman.c | 76 +++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0d92c98628..d4d7683855 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1670,62 +1670,63 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch fstring sharename; fstring comment; pstring pathname; - pstring command; - int offset; + char *command, *cmdname; + uint offset; int snum; - int res; + int res = ERRunsup; /* check it's a supported varient */ if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False; if (!check_share_info(uLevel,str2)) return False; - if (uLevel != 2) { - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; - SSVAL(*rparam,0,NERR_notsupported); - SSVAL(*rparam,2,0); - return True; - } + if (uLevel != 2) return False; pull_ascii_fstring(sharename,data); snum = find_service(sharename); if (snum >= 0) { /* already exists */ - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,ERRfilexists); - SSVAL(*rparam,2,0); - return True; + res = ERRfilexists; + goto error_exit; } /* only support disk share adds */ - if (SVAL(data,14)!=STYPE_DISKTREE) { - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; - SSVAL(*rparam,0,NERR_notsupported); - SSVAL(*rparam,2,0); - return True; - } + if (SVAL(data,14)!=STYPE_DISKTREE) return False; offset = IVAL(data, 16); + if (offset >= mdrcnt) { + res = ERRinvalidparam; + goto error_exit; + } pull_ascii_fstring(comment, offset? (data+offset) : ""); + offset = IVAL(data, 26); + if (offset >= mdrcnt) { + res = ERRinvalidparam; + goto error_exit; + } pull_ascii_pstring(pathname, offset? (data+offset) : ""); string_replace(sharename, '"', ' '); string_replace(pathname, '"', ' '); string_replace(comment, '"', ' '); - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"", + cmdname = lp_add_share_cmd(); + + if (!cmdname || *cmdname == '\0') return False; + + asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", lp_add_share_cmd(), CONFIGFILE, sharename, pathname, comment); - DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); - if ((res = smbrun(command, NULL)) != 0) { - DEBUG(0,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); - return ERRnoaccess; - } else - message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False); - return True; + if (command) { + DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); + if ((res = smbrun(command, NULL)) != 0) { + DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); + SAFE_FREE(command); + res = ERRnoaccess; + goto error_exit; + } else { + SAFE_FREE(command); + message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False); + } + } else return False; *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); @@ -1734,7 +1735,16 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch SSVAL(*rparam,4,*rdata_len); *rdata_len = 0; - return(True); + return True; + + error_exit: + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); + *rdata_len = 0; + SSVAL(*rparam,0,res); + SSVAL(*rparam,2,0); + return True; + } /**************************************************************************** -- cgit From 88b55f47b4914f7d390939e4394ec3edd42be91f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 20 Oct 2001 21:59:34 +0000 Subject: Move from timestamp to gen count file id's for finding oplocked files in a tdb. Jeremy. (This used to be commit 058ae6b58f61ef46013dd076af3a84de5fbaaab1) --- source3/smbd/files.c | 77 +- source3/smbd/open.c | 9 +- source3/smbd/oplock.c | 1619 +++++++++++++++++++++---------------------- source3/smbd/oplock_irix.c | 179 ++--- source3/smbd/oplock_linux.c | 92 +-- 5 files changed, 983 insertions(+), 993 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 8c7fa930e1..3935a12442 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -39,8 +39,22 @@ static files_struct *oplock_save_chain_fsp = NULL; static int files_used; /**************************************************************************** - find first available file slot + Return a unique number identifying this fsp over the life of this pid. ****************************************************************************/ + +static unsigned long get_gen_count(void) +{ + static unsigned long file_gen_counter; + + if ((++file_gen_counter) == 0) + return ++file_gen_counter; + return file_gen_counter; +} + +/**************************************************************************** + Find first available file slot. +****************************************************************************/ + files_struct *file_new(connection_struct *conn) { int i; @@ -90,6 +104,8 @@ files_struct *file_new(connection_struct *conn) ZERO_STRUCTP(fsp); fsp->fd = -1; fsp->conn = conn; + fsp->file_id = get_gen_count(); + GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; @@ -109,10 +125,10 @@ files_struct *file_new(connection_struct *conn) return fsp; } - /**************************************************************************** -close all open files for a connection + Close all open files for a connection. ****************************************************************************/ + void file_close_conn(connection_struct *conn) { files_struct *fsp, *next; @@ -126,7 +142,7 @@ void file_close_conn(connection_struct *conn) } /**************************************************************************** -initialise file structures + Initialise file structures. ****************************************************************************/ #define MAX_OPEN_FUDGEFACTOR 10 @@ -162,10 +178,10 @@ open files, %d are available.\n", request_max_open_files, real_max_open_files)); set_pipe_handle_offset(real_max_open_files); } - /**************************************************************************** -close files open by a specified vuid + Close files open by a specified vuid. ****************************************************************************/ + void file_close_user(int vuid) { files_struct *fsp, *next; @@ -178,13 +194,32 @@ void file_close_user(int vuid) } } +/**************************************************************************** + Find a fsp given a file descriptor. +****************************************************************************/ + +files_struct *file_find_fd(int fd) +{ + int count=0; + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next,count++) { + if (fsp->fd == fd) { + if (count > 10) { + DLIST_PROMOTE(Files, fsp); + } + return fsp; + } + } + + return NULL; +} /**************************************************************************** - Find a fsp given a device, inode and timevalue - If this is from a kernel oplock break request then tval may be NULL. + Find a fsp given a device, inode and file_id. ****************************************************************************/ -files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) +files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id) { int count=0; files_struct *fsp; @@ -193,8 +228,7 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval if (fsp->fd != -1 && fsp->dev == dev && fsp->inode == inode && - (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) && - (tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True )) { + fsp->file_id == file_id ) { if (count > 10) { DLIST_PROMOTE(Files, fsp); } @@ -258,8 +292,9 @@ files_struct *file_find_di_next(files_struct *start_fsp) } /**************************************************************************** -find a fsp that is open for printing + Find a fsp that is open for printing. ****************************************************************************/ + files_struct *file_find_print(void) { files_struct *fsp; @@ -271,10 +306,10 @@ files_struct *file_find_print(void) return NULL; } - /**************************************************************************** -sync open files on a connection + Sync open files on a connection. ****************************************************************************/ + void file_sync_all(connection_struct *conn) { files_struct *fsp, *next; @@ -287,10 +322,10 @@ void file_sync_all(connection_struct *conn) } } - /**************************************************************************** -free up a fsp + Free up a fsp. ****************************************************************************/ + void file_free(files_struct *fsp) { DLIST_REMOVE(Files, fsp); @@ -312,16 +347,17 @@ void file_free(files_struct *fsp) SAFE_FREE(fsp); } - /**************************************************************************** -get a fsp from a packet given the offset of a 16 bit fnum + Get a fsp from a packet given the offset of a 16 bit fnum. ****************************************************************************/ + files_struct *file_fsp(char *buf, int where) { int fnum, count=0; files_struct *fsp; - if (chain_fsp) return chain_fsp; + if (chain_fsp) + return chain_fsp; fnum = SVAL(buf, where); @@ -338,7 +374,7 @@ files_struct *file_fsp(char *buf, int where) } /**************************************************************************** - Reset the chained fsp - done at the start of a packet reply + Reset the chained fsp - done at the start of a packet reply. ****************************************************************************/ void file_chain_reset(void) @@ -358,6 +394,7 @@ void file_chain_save(void) /**************************************************************************** Restore the chained fsp - done after an oplock break. ****************************************************************************/ + void file_chain_restore(void) { chain_fsp = oplock_save_chain_fsp; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3578a82f8f..325913c3d9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -181,7 +181,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; - GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; fsp->size = psbuf->st_size; fsp->pos = -1; @@ -489,7 +488,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry, dev, inode); + opb_ret = request_oplock_break(share_entry); /* Now relock. */ lock_share_entry(conn, dev, inode); @@ -946,11 +945,9 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, * Setup the files_struct for it. */ - fsp->fd = -1; fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; - GetTimeOfDay(&fsp->open_time); fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->pos = -1; @@ -1110,11 +1107,9 @@ files_struct *open_directory(connection_struct *conn, char *fname, * Setup the files_struct for it. */ - fsp->fd = -1; fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; - GetTimeOfDay(&fsp->open_time); fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->pos = -1; @@ -1230,7 +1225,7 @@ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (doub /* Oplock break.... */ unlock_share_entry(conn, dev, inode); - if(request_oplock_break(share_entry, dev, inode) == False) + if(request_oplock_break(share_entry) == False) { DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 927719ac1a..9d285d4ae3 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1,8 +1,9 @@ /* Unix SMB/Netbios implementation. - Version 1.9. + Version 2.2.x oplock processing Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998 - 2001 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 @@ -35,7 +36,7 @@ extern int smb_read_error; static struct kernel_oplocks *koplocks; -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, BOOL local); +static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local); /**************************************************************************** Get the number of current exclusive oplocks. @@ -74,97 +75,97 @@ BOOL oplock_message_waiting(fd_set *fds) BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeout) { - struct sockaddr_in from; - int fromlen = sizeof(from); - int32 msg_len = 0; - - smb_read_error = 0; - - if(timeout != 0) { - struct timeval to; - int selrtn; - int maxfd = oplock_sock; - - if (koplocks && koplocks->notification_fd != -1) { - FD_SET(koplocks->notification_fd, fds); - maxfd = MAX(maxfd, koplocks->notification_fd); - } - - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - - selrtn = sys_select(maxfd+1,fds,&to); - - if (selrtn == -1 && errno == EINTR) { - /* could be a kernel oplock interrupt */ - if (koplocks && koplocks->msg_waiting(fds)) { - return koplocks->receive_message(fds, buffer, buffer_len); - } - } - - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } - - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return False; - } - } - - if (koplocks && koplocks->msg_waiting(fds)) { - return koplocks->receive_message(fds, buffer, buffer_len); - } - - if (!FD_ISSET(oplock_sock, fds)) return False; - - /* - * From here down we deal with the smbd <--> smbd - * oplock break protocol only. - */ - - /* - * Read a loopback udp message. - */ - msg_len = recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], - buffer_len - OPBRK_CMD_HEADER_LEN, 0, - (struct sockaddr *)&from, &fromlen); - - if(msg_len < 0) { - DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); - return False; - } - - /* Validate message length. */ - if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { - DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", - msg_len, - buffer_len - OPBRK_CMD_HEADER_LEN)); - return False; - } - - /* Validate message from address (must be localhost). */ - if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { - DEBUG(0,("receive_local_message: invalid 'from' address \ -(was %lx should be 127.0.0.1\n", (long)from.sin_addr.s_addr)); - return False; - } - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,msg_len); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,ntohs(from.sin_port)); - - return True; + struct sockaddr_in from; + int fromlen = sizeof(from); + int32 msg_len = 0; + + smb_read_error = 0; + + if(timeout != 0) { + struct timeval to; + int selrtn; + int maxfd = oplock_sock; + + if (koplocks && koplocks->notification_fd != -1) { + FD_SET(koplocks->notification_fd, fds); + maxfd = MAX(maxfd, koplocks->notification_fd); + } + + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; + + selrtn = sys_select(maxfd+1,fds,&to); + + if (selrtn == -1 && errno == EINTR) { + /* could be a kernel oplock interrupt */ + if (koplocks && koplocks->msg_waiting(fds)) { + return koplocks->receive_message(fds, buffer, buffer_len); + } + } + + /* Check if error */ + if(selrtn == -1) { + /* something is wrong. Maybe the socket is dead? */ + smb_read_error = READ_ERROR; + return False; + } + + /* Did we timeout ? */ + if (selrtn == 0) { + smb_read_error = READ_TIMEOUT; + return False; + } + } + + if (koplocks && koplocks->msg_waiting(fds)) { + return koplocks->receive_message(fds, buffer, buffer_len); + } + + if (!FD_ISSET(oplock_sock, fds)) + return False; + + /* + * From here down we deal with the smbd <--> smbd + * oplock break protocol only. + */ + + /* + * Read a loopback udp message. + */ + msg_len = recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], + buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen); + + if(msg_len < 0) { + DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); + return False; + } + + /* Validate message length. */ + if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { + DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", msg_len, + buffer_len - OPBRK_CMD_HEADER_LEN)); + return False; + } + + /* Validate message from address (must be localhost). */ + if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { + DEBUG(0,("receive_local_message: invalid 'from' address \ +(was %lx should be 127.0.0.1)\n", (long)from.sin_addr.s_addr)); + return False; + } + + /* Setup the message header */ + SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,msg_len); + SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,ntohs(from.sin_port)); + + return True; } /**************************************************************************** Attempt to set an oplock on a file. Always succeeds if kernel oplocks are disabled (just sets flags). Returns True if oplock set. ****************************************************************************/ + BOOL set_file_oplock(files_struct *fsp, int oplock_type) { if (koplocks && !koplocks->set_oplock(fsp, oplock_type)) @@ -177,8 +178,9 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) else exclusive_oplocks_open++; - DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, + DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, file_id = %lu, \ +tv_sec = %x, tv_usec = %x\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); return True; @@ -190,7 +192,8 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) void release_file_oplock(files_struct *fsp) { - if (koplocks) koplocks->release_oplock(fsp); + if (koplocks) + koplocks->release_oplock(fsp); if (fsp->oplock_type == LEVEL_II_OPLOCK) level_II_oplocks_open--; @@ -209,7 +212,8 @@ void release_file_oplock(files_struct *fsp) static void downgrade_file_oplock(files_struct *fsp) { - if (koplocks) koplocks->release_oplock(fsp); + if (koplocks) + koplocks->release_oplock(fsp); fsp->oplock_type = LEVEL_II_OPLOCK; exclusive_oplocks_open--; level_II_oplocks_open++; @@ -291,161 +295,142 @@ int setup_oplock_select_set( fd_set *fds) Process an oplock break message - whether it came from the UDP socket or from the kernel. ****************************************************************************/ + BOOL process_local_message(char *buffer, int buf_size) { - int32 msg_len; - uint16 from_port; - char *msg_start; - SMB_DEV_T dev; - SMB_INO_T inode; - pid_t remotepid; - struct timeval tval; - struct timeval *ptval = NULL; - uint16 break_cmd_type; - - msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET); - from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET); - - msg_start = &buffer[OPBRK_CMD_HEADER_LEN]; - - DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", - msg_len, from_port)); - - /* - * Pull the info out of the requesting packet. - */ - - break_cmd_type = SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET); - - switch(break_cmd_type) - { - case KERNEL_OPLOCK_BREAK_CMD: - if (!koplocks) { - DEBUG(0,("unexpected kernel oplock break!\n")); - break; - } - if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev)) { - DEBUG(0,("kernel oplock break parse failure!\n")); - } - break; - - case OPLOCK_BREAK_CMD: - case LEVEL_II_OPLOCK_BREAK_CMD: - - /* Ensure that the msg length is correct. */ - if(msg_len != OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, should be %d).\n", - (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); - return False; - } - { - long usec; - time_t sec; - - memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); - memcpy((char *)&sec, msg_start+OPLOCK_BREAK_SEC_OFFSET,sizeof(sec)); - tval.tv_sec = sec; - memcpy((char *)&usec, msg_start+OPLOCK_BREAK_USEC_OFFSET, sizeof(usec)); - tval.tv_usec = usec; - - ptval = &tval; - - memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); - - DEBUG(5,("process_local_message: (%s) oplock break request from \ -pid %d, port %d, dev = %x, inode = %.0f\n", - (break_cmd_type == OPLOCK_BREAK_CMD) ? "exclusive" : "level II", - (int)remotepid, from_port, (unsigned int)dev, (double)inode)); - } - break; - - /* - * Keep this as a debug case - eventually we can remove it. - */ - case 0x8001: - DEBUG(0,("process_local_message: Received unsolicited break \ + int32 msg_len; + uint16 from_port; + char *msg_start; + pid_t remotepid; + SMB_DEV_T dev; + SMB_INO_T inode; + unsigned long file_id; + uint16 break_cmd_type; + + msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET); + from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET); + + msg_start = &buffer[OPBRK_CMD_HEADER_LEN]; + + DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", + msg_len, from_port)); + + /* + * Pull the info out of the requesting packet. + */ + + break_cmd_type = SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET); + + switch(break_cmd_type) { + case KERNEL_OPLOCK_BREAK_CMD: + if (!koplocks) { + DEBUG(0,("unexpected kernel oplock break!\n")); + break; + } + if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev, &file_id)) { + DEBUG(0,("kernel oplock break parse failure!\n")); + } + break; + + case OPLOCK_BREAK_CMD: + case LEVEL_II_OPLOCK_BREAK_CMD: + + /* Ensure that the msg length is correct. */ + if(msg_len != OPLOCK_BREAK_MSG_LEN) { + DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, should be %d).\n", + (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); + return False; + } + + memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); + memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); + memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); + memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id)); + + DEBUG(5,("process_local_message: (%s) oplock break request from \ +pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", + (break_cmd_type == OPLOCK_BREAK_CMD) ? "exclusive" : "level II", + (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); + break; + + /* + * Keep this as a debug case - eventually we can remove it. + */ + case 0x8001: + DEBUG(0,("process_local_message: Received unsolicited break \ reply - dumping info.\n")); - if(msg_len != OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: ubr: incorrect length for reply \ + if(msg_len != OPLOCK_BREAK_MSG_LEN) { + DEBUG(0,("process_local_message: ubr: incorrect length for reply \ (was %d, should be %d).\n", (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); - return False; - } - - { - memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); - memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); - - DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %.0f\n", (int)remotepid, from_port, (unsigned int)dev, (double)inode)); - - } - return False; - - default: - DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", - (unsigned int)SVAL(msg_start,0))); - return False; - } - - /* - * Now actually process the break request. - */ - - if((exclusive_oplocks_open + level_II_oplocks_open) != 0) - { - if (oplock_break(dev, inode, ptval, False) == False) - { - DEBUG(0,("process_local_message: oplock break failed.\n")); - return False; - } - } - else - { - /* - * If we have no record of any currently open oplocks, - * it's not an error, as a close command may have - * just been issued on the file that was oplocked. - * Just log a message and return success in this case. - */ - DEBUG(3,("process_local_message: oplock break requested with no outstanding \ + return False; + } + + memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); + memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); + memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); + memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id)); + + DEBUG(0,("process_local_message: unsolicited oplock break reply from \ +pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", + (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); + + return False; + + default: + DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", + (unsigned int)SVAL(msg_start,0))); + return False; + } + + /* + * Now actually process the break request. + */ + + if((exclusive_oplocks_open + level_II_oplocks_open) != 0) { + if (oplock_break(dev, inode, file_id, False) == False) { + DEBUG(0,("process_local_message: oplock break failed.\n")); + return False; + } + } else { + /* + * If we have no record of any currently open oplocks, + * it's not an error, as a close command may have + * just been issued on the file that was oplocked. + * Just log a message and return success in this case. + */ + DEBUG(3,("process_local_message: oplock break requested with no outstanding \ oplocks. Returning success.\n")); - } - - /* - * Do the appropriate reply - none in the kernel or level II case. - */ - - if(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET) == OPLOCK_BREAK_CMD) - { - struct sockaddr_in toaddr; - - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); - - memset((char *)&toaddr,'\0',sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; - - if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) - { - DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", - (int)remotepid, strerror(errno))); - return False; - } - - DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %.0f\n", - (int)remotepid, from_port, (unsigned int)dev, (double)inode)); - } - - return True; + } + + /* + * Do the appropriate reply - none in the kernel or level II case. + */ + + if(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET) == OPLOCK_BREAK_CMD) { + struct sockaddr_in toaddr; + + /* Send the message back after OR'ing in the 'REPLY' bit. */ + SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); + + memset((char *)&toaddr,'\0',sizeof(toaddr)); + toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + toaddr.sin_port = htons(from_port); + toaddr.sin_family = AF_INET; + + if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { + DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", + (int)remotepid, strerror(errno))); + return False; + } + + DEBUG(5,("process_local_message: oplock break reply sent to \ +pid %d, port %d, for file dev = %x, inode = %.0f, file_id = %lu\n", + (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); + } + + return True; } /**************************************************************************** @@ -474,81 +459,82 @@ static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) static void wait_before_sending_break(BOOL local_request) { - extern struct timeval smb_last_time; + extern struct timeval smb_last_time; - if(local_request) { - struct timeval cur_tv; - long wait_left = (long)lp_oplock_break_wait_time(); + if(local_request) { + struct timeval cur_tv; + long wait_left = (long)lp_oplock_break_wait_time(); - if (wait_left == 0) - return; + if (wait_left == 0) + return; - GetTimeOfDay(&cur_tv); + GetTimeOfDay(&cur_tv); - wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) + + wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) + ((cur_tv.tv_usec - smb_last_time.tv_usec)/1000); - if(wait_left > 0) { - wait_left = MIN(wait_left, 1000); - sys_usleep(wait_left * 1000); - } - } + if(wait_left > 0) { + wait_left = MIN(wait_left, 1000); + sys_usleep(wait_left * 1000); + } + } } /**************************************************************************** Ensure that we have a valid oplock. ****************************************************************************/ -static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) + +static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id) { - files_struct *fsp = NULL; - - if( DEBUGLVL( 3 ) ) - { - dbgtext( "initial_break_processing: called for dev = %x, inode = %.0f tv_sec = %x, tv_usec = %x.\n", - (unsigned int)dev, (double)inode, tval ? (int)tval->tv_sec : 0, - tval ? (int)tval->tv_usec : 0); - dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", - exclusive_oplocks_open, level_II_oplocks_open ); - } - - /* We need to search the file open table for the - entry containing this dev and inode, and ensure - we have an oplock on it. */ - fsp = file_find_dit(dev, inode, tval); - - if(fsp == NULL) - { - /* The file could have been closed in the meantime - return success. */ - if( DEBUGLVL( 3 ) ) - { - dbgtext( "initial_break_processing: cannot find open file with " ); - dbgtext( "dev = %x, inode = %.0f ", (unsigned int)dev, (double)inode); - dbgtext( "allowing break to succeed.\n" ); - } - return NULL; - } - - /* Ensure we have an oplock on the file */ - - /* There is a potential race condition in that an oplock could - have been broken due to another udp request, and yet there are - still oplock break messages being sent in the udp message - queue for this file. So return true if we don't have an oplock, - as we may have just freed it. - */ - - if(fsp->oplock_type == NO_OPLOCK) - { - if( DEBUGLVL( 3 ) ) - { - dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %.0f) has no oplock.\n", (unsigned int)dev, (double)inode ); - dbgtext( "Allowing break to succeed regardless.\n" ); - } - return NULL; - } - - return fsp; + files_struct *fsp = NULL; + + if( DEBUGLVL( 3 ) ) { + dbgtext( "initial_break_processing: called for dev = %x, inode = %.0f file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id); + dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", + exclusive_oplocks_open, level_II_oplocks_open ); + } + + /* + * We need to search the file open table for the + * entry containing this dev and inode, and ensure + * we have an oplock on it. + */ + + fsp = file_find_dif(dev, inode, file_id); + + if(fsp == NULL) { + /* The file could have been closed in the meantime - return success. */ + if( DEBUGLVL( 3 ) ) { + dbgtext( "initial_break_processing: cannot find open file with " ); + dbgtext( "dev = %x, inode = %.0f file_id = %lu", (unsigned int)dev, + (double)inode, file_id); + dbgtext( "allowing break to succeed.\n" ); + } + return NULL; + } + + /* Ensure we have an oplock on the file */ + + /* + * There is a potential race condition in that an oplock could + * have been broken due to another udp request, and yet there are + * still oplock break messages being sent in the udp message + * queue for this file. So return true if we don't have an oplock, + * as we may have just freed it. + */ + + if(fsp->oplock_type == NO_OPLOCK) { + if( DEBUGLVL( 3 ) ) { + dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); + dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n", + (unsigned int)dev, (double)inode, fsp->file_id ); + dbgtext( "Allowing break to succeed regardless.\n" ); + } + return NULL; + } + + return fsp; } /**************************************************************************** @@ -557,335 +543,322 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, st BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) { - extern uint32 global_client_caps; - char outbuf[128]; - BOOL got_lock = False; - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; - - /* - * We can have a level II oplock even if the client is not - * level II oplock aware. In this case just remove the - * flags and don't send the break-to-none message to - * the client. - */ - - if (global_client_caps & CAP_LEVEL_II_OPLOCKS) { - /* - * If we are sending an oplock break due to an SMB sent - * by our own client we ensure that we wait at leat - * lp_oplock_break_wait_time() milliseconds before sending - * the packet. Sending the packet sooner can break Win9x - * and has reported to cause problems on NT. JRA. - */ - - wait_before_sending_break(local_request); - - /* Prepare the SMBlockingX message. */ - - prepare_break_message( outbuf, fsp, False); - if (!send_smb(smbd_server_fd(), outbuf)) - exit_server("oplock_break_level2: send_smb failed.\n"); - } - - /* - * Now we must update the shared memory structure to tell - * everyone else we no longer have a level II oplock on - * this open file. If local_request is true then token is - * the existing lock on the shared memory area. - */ - - if(!local_request && lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); - } else { - got_lock = True; - } - - if(remove_share_oplock(fsp)==False) { - DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); - } - - if (!local_request && got_lock) - unlock_share_entry_fsp(fsp); - - fsp->oplock_type = NO_OPLOCK; - level_II_oplocks_open--; - - if(level_II_oplocks_open < 0) - { - DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", - level_II_oplocks_open)); - abort(); - } - - if( DEBUGLVL( 3 ) ) - { - dbgtext( "oplock_break_level2: returning success for " ); - dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); - dbgtext( "Current level II oplocks_open = %d\n", level_II_oplocks_open ); - } - - return True; + extern uint32 global_client_caps; + char outbuf[128]; + BOOL got_lock = False; + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; + + /* + * We can have a level II oplock even if the client is not + * level II oplock aware. In this case just remove the + * flags and don't send the break-to-none message to + * the client. + */ + + if (global_client_caps & CAP_LEVEL_II_OPLOCKS) { + /* + * If we are sending an oplock break due to an SMB sent + * by our own client we ensure that we wait at leat + * lp_oplock_break_wait_time() milliseconds before sending + * the packet. Sending the packet sooner can break Win9x + * and has reported to cause problems on NT. JRA. + */ + + wait_before_sending_break(local_request); + + /* Prepare the SMBlockingX message. */ + + prepare_break_message( outbuf, fsp, False); + if (!send_smb(smbd_server_fd(), outbuf)) + exit_server("oplock_break_level2: send_smb failed.\n"); + } + + /* + * Now we must update the shared memory structure to tell + * everyone else we no longer have a level II oplock on + * this open file. If local_request is true then token is + * the existing lock on the shared memory area. + */ + + if(!local_request && lock_share_entry_fsp(fsp) == False) { + DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); + } else { + got_lock = True; + } + + if(remove_share_oplock(fsp)==False) { + DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); + } + + if (!local_request && got_lock) + unlock_share_entry_fsp(fsp); + + fsp->oplock_type = NO_OPLOCK; + level_II_oplocks_open--; + + if(level_II_oplocks_open < 0) { + DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", + level_II_oplocks_open)); + abort(); + } + + if( DEBUGLVL( 3 ) ) { + dbgtext( "oplock_break_level2: returning success for " ); + dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, fsp->file_id ); + dbgtext( "Current level II oplocks_open = %d\n", level_II_oplocks_open ); + } + + return True; } /**************************************************************************** Process an oplock break directly. ****************************************************************************/ -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, BOOL local_request) +static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) { - extern uint32 global_client_caps; - extern struct current_user current_user; - char *inbuf = NULL; - char *outbuf = NULL; - files_struct *fsp = NULL; - time_t start_time; - BOOL shutdown_server = False; - BOOL oplock_timeout = False; - connection_struct *saved_user_conn; - connection_struct *saved_fsp_conn; - int saved_vuid; - pstring saved_dir; - int timeout = (OPLOCK_BREAK_TIMEOUT * 1000); - pstring file_name; - BOOL using_levelII; - - if((fsp = initial_break_processing(dev, inode, tval)) == NULL) - return True; - - /* - * Deal with a level II oplock going break to none separately. - */ - - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) - return oplock_break_level2(fsp, local_request, -1); - - /* Mark the oplock break as sent - we don't want to send twice! */ - if (fsp->sent_oplock_break) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); - dbgtext( "file %s ", fsp->fsp_name); - dbgtext( "(dev = %x, inode = %.0f)\n", (unsigned int)dev, (double)inode ); - } - - /* We have to fail the open here as we cannot send another oplock break on - this file whilst we are awaiting a response from the client - neither - can we allow another open to succeed while we are waiting for the - client. - */ - return False; - } - - if(global_oplock_break) { - DEBUG(0,("ABORT : ABORT : recursion in oplock_break !!!!!\n")); - abort(); - } - - /* Now comes the horrid part. We must send an oplock break to the client, - and then process incoming messages until we get a close or oplock release. - At this point we know we need a new inbuf/outbuf buffer pair. - We cannot use these staticaly as we may recurse into here due to - messages crossing on the wire. - */ - - if((inbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) - { - DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); - return False; - } - - if((outbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) - { - DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - SAFE_FREE(inbuf); - return False; - } - - /* - * If we are sending an oplock break due to an SMB sent - * by our own client we ensure that we wait at leat - * lp_oplock_break_wait_time() milliseconds before sending - * the packet. Sending the packet sooner can break Win9x - * and has reported to cause problems on NT. JRA. - */ - - wait_before_sending_break(local_request); - - /* Prepare the SMBlockingX message. */ - - if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && - !koplocks && /* NOTE: we force levelII off for kernel oplocks - - this will change when it is supported */ - lp_level2_oplocks(SNUM(fsp->conn))) { - using_levelII = True; - } else { - using_levelII = False; - } - - prepare_break_message( outbuf, fsp, using_levelII); - /* Remember if we just sent a break to level II on this file. */ - fsp->sent_oplock_break = using_levelII? - LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - - if (!send_smb(smbd_server_fd(), outbuf)) - exit_server("oplock_break: send_smb failed.\n"); - - /* We need this in case a readraw crosses on the wire. */ - global_oplock_break = True; + extern uint32 global_client_caps; + extern struct current_user current_user; + char *inbuf = NULL; + char *outbuf = NULL; + files_struct *fsp = NULL; + time_t start_time; + BOOL shutdown_server = False; + BOOL oplock_timeout = False; + connection_struct *saved_user_conn; + connection_struct *saved_fsp_conn; + int saved_vuid; + pstring saved_dir; + int timeout = (OPLOCK_BREAK_TIMEOUT * 1000); + pstring file_name; + BOOL using_levelII; + + if((fsp = initial_break_processing(dev, inode, file_id)) == NULL) + return True; + + /* + * Deal with a level II oplock going break to none separately. + */ + + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + return oplock_break_level2(fsp, local_request, -1); + + /* Mark the oplock break as sent - we don't want to send twice! */ + if (fsp->sent_oplock_break) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); + dbgtext( "file %s ", fsp->fsp_name); + dbgtext( "(dev = %x, inode = %.0f, file_id = %lu)\n", (unsigned int)dev, (double)inode, fsp->file_id ); + } + + /* + * We have to fail the open here as we cannot send another oplock break on + * this file whilst we are awaiting a response from the client - neither + * can we allow another open to succeed while we are waiting for the client. + */ + return False; + } + + if(global_oplock_break) { + DEBUG(0,("ABORT : ABORT : recursion in oplock_break !!!!!\n")); + abort(); + } + + /* + * Now comes the horrid part. We must send an oplock break to the client, + * and then process incoming messages until we get a close or oplock release. + * At this point we know we need a new inbuf/outbuf buffer pair. + * We cannot use these staticaly as we may recurse into here due to + * messages crossing on the wire. + */ + + if((inbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { + DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); + return False; + } + + if((outbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { + DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); + SAFE_FREE(inbuf); + return False; + } + + /* + * If we are sending an oplock break due to an SMB sent + * by our own client we ensure that we wait at leat + * lp_oplock_break_wait_time() milliseconds before sending + * the packet. Sending the packet sooner can break Win9x + * and has reported to cause problems on NT. JRA. + */ + + wait_before_sending_break(local_request); + + /* Prepare the SMBlockingX message. */ + + if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && + !koplocks && /* NOTE: we force levelII off for kernel oplocks - this will change when it is supported */ + lp_level2_oplocks(SNUM(fsp->conn))) { + using_levelII = True; + } else { + using_levelII = False; + } + + prepare_break_message( outbuf, fsp, using_levelII); + /* Remember if we just sent a break to level II on this file. */ + fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; + + if (!send_smb(smbd_server_fd(), outbuf)) + exit_server("oplock_break: send_smb failed.\n"); + + /* We need this in case a readraw crosses on the wire. */ + global_oplock_break = True; - /* Process incoming messages. */ - - /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT - seconds we should just die.... */ - - start_time = time(NULL); - - /* - * Save the information we need to re-become the - * user, then unbecome the user whilst we're doing this. - */ - saved_user_conn = current_user.conn; - saved_vuid = current_user.vuid; - saved_fsp_conn = fsp->conn; - vfs_GetWd(saved_fsp_conn,saved_dir); - change_to_root_user(); - /* Save the chain fnum. */ - file_chain_save(); - - /* - * From Charles Hoch . If the break processing - * code closes the file (as it often does), then the fsp pointer here - * points to free()'d memory. We *must* revalidate fsp each time - * around the loop. - */ - - pstrcpy(file_name, fsp->fsp_name); - - while((fsp = initial_break_processing(dev, inode, tval)) && - OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - { - if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) - { - /* - * Die if we got an error. - */ - - if (smb_read_error == READ_EOF) { - DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); - shutdown_server = True; - } else if (smb_read_error == READ_ERROR) { - DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); - shutdown_server = True; - } else if (smb_read_error == READ_TIMEOUT) { - DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", - OPLOCK_BREAK_TIMEOUT ) ); - oplock_timeout = True; - } - - DEBUGADD( 0, ( "oplock_break failed for file %s ", file_name ) ); - DEBUGADD( 0, ( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode)); - - break; - } - - /* - * There are certain SMB requests that we shouldn't allow - * to recurse. opens, renames and deletes are the obvious - * ones. This is handled in the switch_message() function. - * If global_oplock_break is set they will push the packet onto - * the pending smb queue and return -1 (no reply). - * JRA. - */ - - process_smb(inbuf, outbuf); - - /* - * Die if we go over the time limit. - */ - - if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "oplock_break: no break received from client " ); - dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); - dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode ); - } - oplock_timeout = True; - break; - } - } - - /* - * Go back to being the user who requested the oplock - * break. - */ - if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !change_to_user(saved_user_conn, saved_vuid)) - { - DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); - DEBUGADD( 0, ( "Shutting down server\n" ) ); - close(oplock_sock); - exit_server("unable to re-become user"); - } - /* Including the directory. */ - vfs_ChDir(saved_fsp_conn,saved_dir); - - /* Restore the chain fnum. */ - file_chain_restore(); - - /* Free the buffers we've been using to recurse. */ - SAFE_FREE(inbuf); - SAFE_FREE(outbuf); - - /* We need this in case a readraw crossed on the wire. */ - if(global_oplock_break) - global_oplock_break = False; - - /* - * If the client timed out then clear the oplock (or go to level II) - * and continue. This seems to be what NT does and is better than dropping - * the connection. - */ - - if(oplock_timeout && (fsp = initial_break_processing(dev, inode, tval)) && - OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - { - DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name)); - remove_oplock(fsp,True); - global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */ - } - - /* - * If the client had an error we must die. - */ - - if(shutdown_server) - { - DEBUG( 0, ( "oplock_break: client failure in break - " ) ); - DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); - close(oplock_sock); - exit_server("oplock break failure"); - } - - /* Santity check - remove this later. JRA */ - if(exclusive_oplocks_open < 0) - { - DEBUG(0,("oplock_break: exclusive_oplocks_open < 0 (%d). PANIC ERROR\n", - exclusive_oplocks_open)); - abort(); - } - - if( DEBUGLVL( 3 ) ) - { - dbgtext( "oplock_break: returning success for " ); - dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); - dbgtext( "Current exclusive_oplocks_open = %d\n", exclusive_oplocks_open ); - } - - return True; + /* Process incoming messages. */ + + /* + * JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT + * seconds we should just die.... + */ + + start_time = time(NULL); + + /* + * Save the information we need to re-become the + * user, then unbecome the user whilst we're doing this. + */ + saved_user_conn = current_user.conn; + saved_vuid = current_user.vuid; + saved_fsp_conn = fsp->conn; + vfs_GetWd(saved_fsp_conn,saved_dir); + change_to_root_user(); + /* Save the chain fnum. */ + file_chain_save(); + + /* + * From Charles Hoch . If the break processing + * code closes the file (as it often does), then the fsp pointer here + * points to free()'d memory. We *must* revalidate fsp each time + * around the loop. + */ + + pstrcpy(file_name, fsp->fsp_name); + + while((fsp = initial_break_processing(dev, inode, file_id)) && + OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) { + /* + * Die if we got an error. + */ + + if (smb_read_error == READ_EOF) { + DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); + shutdown_server = True; + } else if (smb_read_error == READ_ERROR) { + DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); + shutdown_server = True; + } else if (smb_read_error == READ_TIMEOUT) { + DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); + oplock_timeout = True; + } + + DEBUGADD( 0, ( "oplock_break failed for file %s ", file_name ) ); + DEBUGADD( 0, ( "(dev = %x, inode = %.0f, file_id = %lu).\n", + (unsigned int)dev, (double)inode, file_id)); + + break; + } + + /* + * There are certain SMB requests that we shouldn't allow + * to recurse. opens, renames and deletes are the obvious + * ones. This is handled in the switch_message() function. + * If global_oplock_break is set they will push the packet onto + * the pending smb queue and return -1 (no reply). + * JRA. + */ + + process_smb(inbuf, outbuf); + + /* + * Die if we go over the time limit. + */ + + if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "oplock_break: no break received from client " ); + dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); + dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); + dbgtext( "(dev = %x, inode = %.0f, file_id = %lu).\n", + (unsigned int)dev, (double)inode, file_id ); + } + oplock_timeout = True; + break; + } + } + + /* + * Go back to being the user who requested the oplock + * break. + */ + if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !change_to_user(saved_user_conn, saved_vuid)) { + DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); + DEBUGADD( 0, ( "Shutting down server\n" ) ); + close(oplock_sock); + exit_server("unable to re-become user"); + } + + /* Including the directory. */ + vfs_ChDir(saved_fsp_conn,saved_dir); + + /* Restore the chain fnum. */ + file_chain_restore(); + + /* Free the buffers we've been using to recurse. */ + SAFE_FREE(inbuf); + SAFE_FREE(outbuf); + + /* We need this in case a readraw crossed on the wire. */ + if(global_oplock_break) + global_oplock_break = False; + + /* + * If the client timed out then clear the oplock (or go to level II) + * and continue. This seems to be what NT does and is better than dropping + * the connection. + */ + + if(oplock_timeout && (fsp = initial_break_processing(dev, inode, file_id)) && + OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name)); + remove_oplock(fsp,True); + global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */ + } + + /* + * If the client had an error we must die. + */ + + if(shutdown_server) { + DEBUG( 0, ( "oplock_break: client failure in break - " ) ); + DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); + close(oplock_sock); + exit_server("oplock break failure"); + } + + /* Santity check - remove this later. JRA */ + if(exclusive_oplocks_open < 0) { + DEBUG(0,("oplock_break: exclusive_oplocks_open < 0 (%d). PANIC ERROR\n", exclusive_oplocks_open)); + abort(); + } + + if( DEBUGLVL( 3 ) ) { + dbgtext( "oplock_break: returning success for " ); + dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); + dbgtext( "Current exclusive_oplocks_open = %d\n", exclusive_oplocks_open ); + } + + return True; } /**************************************************************************** @@ -893,212 +866,187 @@ Send an oplock break message to another smbd process. If the oplock is held by the local smbd then call the oplock break function directly. ****************************************************************************/ -BOOL request_oplock_break(share_mode_entry *share_entry, - SMB_DEV_T dev, SMB_INO_T inode) +BOOL request_oplock_break(share_mode_entry *share_entry) { - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - pid_t pid = sys_getpid(); - time_t start_time; - int time_left; - long usec; - time_t sec; - - if(pid == share_entry->pid) - { - /* We are breaking our own oplock, make sure it's us. */ - if(share_entry->op_port != global_oplock_port) - { - DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ + char op_break_msg[OPLOCK_BREAK_MSG_LEN]; + struct sockaddr_in addr_out; + pid_t pid = sys_getpid(); + time_t start_time; + int time_left; + SMB_DEV_T dev = share_entry->dev; + SMB_INO_T inode = share_entry->inode; + unsigned long file_id = share_entry->share_file_id; + + if(pid == share_entry->pid) { + /* We are breaking our own oplock, make sure it's us. */ + if(share_entry->op_port != global_oplock_port) { + DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); - return False; - } + return False; + } - DEBUG(5,("request_oplock_break: breaking our own oplock\n")); + DEBUG(5,("request_oplock_break: breaking our own oplock\n")); #if 1 /* JRA PARANOIA TEST.... */ - { - files_struct *fsp = file_find_dit(dev, inode, &share_entry->time); - if (!fsp) { - DEBUG(0,("request_oplock_break: PANIC : breaking our own oplock requested for \ -dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x and no fsp found !\n", - (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, - (int)share_entry->time.tv_usec )); - smb_panic("request_oplock_break: no fsp found for our own oplock\n"); - } - } + { + files_struct *fsp = file_find_dif(dev, inode, file_id); + if (!fsp) { + DEBUG(0,("request_oplock_break: PANIC : breaking our own oplock requested for \ +dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", + (unsigned int)dev, (double)inode, file_id )); + smb_panic("request_oplock_break: no fsp found for our own oplock\n"); + } + } #endif /* END JRA PARANOIA TEST... */ - /* Call oplock break direct. */ - return oplock_break(dev, inode, &share_entry->time, True); - } - - /* We need to send a OPLOCK_BREAK_CMD message to the - port in the share mode entry. */ - - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,LEVEL_II_OPLOCK_BREAK_CMD); - } else { - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); - } - memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); - sec = (time_t)share_entry->time.tv_sec; - memcpy(op_break_msg+OPLOCK_BREAK_SEC_OFFSET,(char *)&sec,sizeof(sec)); - usec = (long)share_entry->time.tv_usec; - memcpy(op_break_msg+OPLOCK_BREAK_USEC_OFFSET,(char *)&usec,sizeof(usec)); - memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); - memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); - - /* set the address and port */ - memset((char *)&addr_out,'\0',sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; + /* Call oplock break direct. */ + return oplock_break(dev, inode, file_id, True); + } + + /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ + + if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,LEVEL_II_OPLOCK_BREAK_CMD); + } else { + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); + } + + memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); + memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); + memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); + memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); + + /* Set the address and port. */ + memset((char *)&addr_out,'\0',sizeof(addr_out)); + addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_out.sin_port = htons( share_entry->op_port ); + addr_out.sin_family = AF_INET; - if( DEBUGLVL( 3 ) ) - { - dbgtext( "request_oplock_break: sending a oplock break message to " ); - dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", - (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, - (int)share_entry->time.tv_usec ); - - } - - if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "request_oplock_break: failed when sending a oplock " ); - dbgtext( "break message to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", - (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, - (int)share_entry->time.tv_usec ); - dbgtext( "Error was %s\n", strerror(errno) ); - } - return False; - } - - /* - * If we just sent a message to a level II oplock share entry then - * we are done and may return. - */ - - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - DEBUG(3,("request_oplock_break: sent break message to level II entry.\n")); - return True; - } - - /* - * Now we must await the oplock broken message coming back - * from the target smbd process. Timeout if it fails to - * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. - * While we get messages that aren't ours, loop. - */ - - start_time = time(NULL); - time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR; - - while(time_left >= 0) - { - char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; - uint16 reply_from_port; - char *reply_msg_start; - fd_set fds; - - FD_ZERO(&fds); - FD_SET(oplock_sock,&fds); - - if (koplocks && koplocks->notification_fd != -1) { - FD_SET(koplocks->notification_fd, &fds); - } - - if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply), - time_left ? time_left * 1000 : 1) == False) - { - if(smb_read_error == READ_TIMEOUT) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "request_oplock_break: no response received to oplock " ); - dbgtext( "break request to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ); - dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", - (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, - (int)share_entry->time.tv_usec ); - } - - /* - * This is a hack to make handling of failing clients more robust. - * If a oplock break response message is not received in the timeout - * period we may assume that the smbd servicing that client holding - * the oplock has died and the client changes were lost anyway, so - * we should continue to try and open the file. - */ - break; - } - else - if( DEBUGLVL( 0 ) ) - { - dbgtext( "request_oplock_break: error in response received " ); - dbgtext( "to oplock break request to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x\n", - (unsigned int)dev, (double)inode, (int)share_entry->time.tv_sec, - (int)share_entry->time.tv_usec ); - dbgtext( "Error was (%s).\n", strerror(errno) ); - } - return False; - } - - reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET); - - reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; - - - /* - * Test to see if this is the reply we are awaiting. - */ - if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) && - ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == OPLOCK_BREAK_CMD) && - (reply_from_port == share_entry->op_port) && - (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], - &op_break_msg[OPLOCK_BREAK_PID_OFFSET], - OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) - { - /* - * This is the reply we've been waiting for. - */ - break; - } - else - { - /* - * This is another message - a break request. - * Note that both kernel oplock break requests - * and UDP inter-smbd oplock break requests will - * be processed here. - * - * Process it to prevent potential deadlock. - * Note that the code in switch_message() prevents - * us from recursing into here as any SMB requests - * we might process that would cause another oplock - * break request to be made will be queued. - * JRA. - */ - - process_local_message(op_break_reply, sizeof(op_break_reply)); - } - - time_left -= (time(NULL) - start_time); - } - - DEBUG(3,("request_oplock_break: broke oplock.\n")); - - return True; + if( DEBUGLVL( 3 ) ) { + dbgtext( "request_oplock_break: sending a oplock break message to " ); + dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + } + + if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, + (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "request_oplock_break: failed when sending a oplock " ); + dbgtext( "break message to pid %d ", (int)share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + dbgtext( "Error was %s\n", strerror(errno) ); + } + return False; + } + + /* + * If we just sent a message to a level II oplock share entry then + * we are done and may return. + */ + + if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + DEBUG(3,("request_oplock_break: sent break message to level II entry.\n")); + return True; + } + + /* + * Now we must await the oplock broken message coming back + * from the target smbd process. Timeout if it fails to + * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. + * While we get messages that aren't ours, loop. + */ + + start_time = time(NULL); + time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR; + + while(time_left >= 0) { + char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; + uint16 reply_from_port; + char *reply_msg_start; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(oplock_sock,&fds); + + if (koplocks && koplocks->notification_fd != -1) { + FD_SET(koplocks->notification_fd, &fds); + } + + if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply), + time_left ? time_left * 1000 : 1) == False) { + if(smb_read_error == READ_TIMEOUT) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "request_oplock_break: no response received to oplock " ); + dbgtext( "break request to pid %d ", (int)share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + } + + /* + * This is a hack to make handling of failing clients more robust. + * If a oplock break response message is not received in the timeout + * period we may assume that the smbd servicing that client holding + * the oplock has died and the client changes were lost anyway, so + * we should continue to try and open the file. + */ + break; + } else { + if( DEBUGLVL( 0 ) ) { + dbgtext( "request_oplock_break: error in response received " ); + dbgtext( "to oplock break request to pid %d ", (int)share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + dbgtext( "Error was (%s).\n", strerror(errno) ); + } + } + return False; + } + + reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET); + reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; + + /* + * Test to see if this is the reply we are awaiting. + */ + if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) && + ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == OPLOCK_BREAK_CMD) && + (reply_from_port == share_entry->op_port) && + (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], &op_break_msg[OPLOCK_BREAK_PID_OFFSET], + OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) { + + /* + * This is the reply we've been waiting for. + */ + break; + } else { + /* + * This is another message - a break request. + * Note that both kernel oplock break requests + * and UDP inter-smbd oplock break requests will + * be processed here. + * + * Process it to prevent potential deadlock. + * Note that the code in switch_message() prevents + * us from recursing into here as any SMB requests + * we might process that would cause another oplock + * break request to be made will be queued. + * JRA. + */ + + process_local_message(op_break_reply, sizeof(op_break_reply)); + } + + time_left -= (time(NULL) - start_time); + } + + DEBUG(3,("request_oplock_break: broke oplock.\n")); + + return True; } /**************************************************************************** @@ -1108,20 +1056,20 @@ dev = %x, inode = %.0f, tv_sec = %x, tv_usec = %x and no fsp found !\n", Used as a last ditch attempt to free a space in the file table when we have run out. ****************************************************************************/ + BOOL attempt_close_oplocked_file(files_struct *fsp) { + DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd != -1)) { - /* Try and break the oplock. */ - if (oplock_break(fsp->dev, fsp->inode, &fsp->open_time, True)) { - if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */ - return True; - } - } + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd != -1)) { + /* Try and break the oplock. */ + if (oplock_break(fsp->dev, fsp->inode, fsp->file_id, True)) { + if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */ + return True; + } + } - return False; + return False; } /**************************************************************************** @@ -1189,7 +1137,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) */ if (pid == share_entry->pid) { - files_struct *new_fsp = file_find_dit(fsp->dev, fsp->inode, &share_entry->time); + files_struct *new_fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); /* Paranoia check... */ if(new_fsp == NULL) { @@ -1210,11 +1158,11 @@ void release_level_2_oplocks_on_change(files_struct *fsp) */ DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock.\n")); - request_oplock_break(share_entry, fsp->dev, fsp->inode); + request_oplock_break(share_entry); } } - SAFE_FREE(share_list); + SAFE_FREE((char *)share_list); unlock_share_entry_fsp(fsp); /* Paranoia check... */ @@ -1227,6 +1175,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) /**************************************************************************** setup oplocks for this process ****************************************************************************/ + BOOL init_oplocks(void) { struct sockaddr_in sock_name; diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index c6055fc329..1052046175 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -27,8 +27,9 @@ static int oplock_pipe_write = -1; static int oplock_pipe_read = -1; /**************************************************************************** -test to see if IRIX kernel oplocks work + Test to see if IRIX kernel oplocks work. ****************************************************************************/ + static BOOL irix_oplocks_available(void) { int fd; @@ -81,106 +82,113 @@ Disabling kernel oplock support.\n", strerror(errno) )); return True; } - - /**************************************************************************** * Deal with the IRIX kernel <--> smbd * oplock break protocol. ****************************************************************************/ + static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) { extern int smb_read_error; - oplock_stat_t os; - SMB_DEV_T dev; - SMB_INO_T inode; - char dummy; - - /* - * Read one byte of zero to clear the - * kernel break notify message. - */ - - if(read(oplock_pipe_read, &dummy, 1) != 1) { - DEBUG(0,("receive_local_message: read of kernel notification failed. \ + oplock_stat_t os; + char dummy; + files_struct *fsp; + + /* + * Read one byte of zero to clear the + * kernel break notify message. + */ + + if(read(oplock_pipe_read, &dummy, 1) != 1) { + DEBUG(0,("receive_local_message: read of kernel notification failed. \ Error was %s.\n", strerror(errno) )); - smb_read_error = READ_ERROR; - return False; - } - - /* - * Do a query to get the - * device and inode of the file that has the break - * request outstanding. - */ - - if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { - DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ + smb_read_error = READ_ERROR; + return False; + } + + /* + * Do a query to get the + * device and inode of the file that has the break + * request outstanding. + */ + + if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { + DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ Error was %s.\n", strerror(errno) )); - if(errno == EAGAIN) { - /* - * Duplicate kernel break message - ignore. - */ - memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); - return True; - } - smb_read_error = READ_ERROR; - return False; - } - - dev = (SMB_DEV_T)os.os_dev; - inode = (SMB_INO_T)os.os_ino; - - DEBUG(5,("receive_local_message: kernel oplock break request received for \ -dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); - - /* - * Create a kernel oplock break message. - */ - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); - - buffer += OPBRK_CMD_HEADER_LEN; + if(errno == EAGAIN) { + /* + * Duplicate kernel break message - ignore. + */ + memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); + return True; + } + smb_read_error = READ_ERROR; + return False; + } + + /* + * We only have device and inode info here - we have to guess that this + * is the first fsp open with this dev,ino pair. + */ + + if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev, (SMB_INO_T)os.os_ino)) == NULL) { + DEBUG(0,("receive_local_message: unable to find open file with dev = %x, inode = %.0f\n", + (unsigned int)os.os_dev, (double)os.os_ino )); + return False; + } - SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); + DEBUG(5,("receive_local_message: kernel oplock break request received for \ +dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); + /* + * Create a kernel oplock break message. + */ + + /* Setup the message header */ + SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); + SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); + + buffer += OPBRK_CMD_HEADER_LEN; - return True; + SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); + + memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); + + return True; } - /**************************************************************************** Attempt to set an kernel oplock on a file. ****************************************************************************/ + static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) == -1) { if(errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ -inode = %.0f. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, +inode = %.0f, file_id = %ul. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, strerror(errno) )); } else { DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ -inode = %.0f. Another process had the file open.\n", - fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode )); +inode = %.0f, file_id = %ul. Another process had the file open.\n", + fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); } return False; } - DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); + DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); return True; } - /**************************************************************************** Release a kernel oplock on a file. ****************************************************************************/ + static void irix_release_kernel_oplock(files_struct *fsp) { if (DEBUGLVL(10)) { @@ -189,9 +197,9 @@ static void irix_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fd, F_OPLKACK, -1); - dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, state ); + (double)fsp->inode, fsp->file_id, state ); } /* @@ -200,18 +208,19 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { if( DEBUGLVL( 0 )) { dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", + dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, strerror(errno) ); + (double)fsp->inode, fsp->file_id, strerror(errno) ); } } } - /**************************************************************************** -parse a kernel oplock message + Parse a kernel oplock message. ****************************************************************************/ -static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode, SMB_DEV_T *dev) + +static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len, + SMB_INO_T *inode, SMB_DEV_T *dev, unsigned long *file_id) { /* Ensure that the msg length is correct. */ if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { @@ -220,36 +229,39 @@ static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *in return False; } - memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); - memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); + memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); + memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); + memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id)); - DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f\n", - (unsigned int)*dev, (double)*inode)); + DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %ul\n", + (unsigned int)*dev, (double)*inode, *file_id)); return True; } - /**************************************************************************** -set *maxfd to include oplock read pipe + Set *maxfd to include oplock read pipe. ****************************************************************************/ + static BOOL irix_oplock_msg_waiting(fd_set *fds) { - if (oplock_pipe_read == -1) return False; + if (oplock_pipe_read == -1) + return False; return FD_ISSET(oplock_pipe_read,fds); } - /**************************************************************************** -setup kernel oplocks + Setup kernel oplocks. ****************************************************************************/ + struct kernel_oplocks *irix_init_kernel_oplocks(void) { int pfd[2]; static struct kernel_oplocks koplocks; - if (!irix_oplocks_available()) return NULL; + if (!irix_oplocks_available()) + return NULL; if(pipe(pfd) != 0) { DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n", @@ -269,9 +281,6 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void) return &koplocks; } - - - #else void oplock_irix_dummy(void) {} #endif /* HAVE_KERNEL_OPLOCKS_IRIX */ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 8c4259ac53..f42d55d297 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -48,8 +48,9 @@ static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal #endif /**************************************************************************** -handle a LEASE signal, incrementing the signals_received and blocking the signal + Handle a LEASE signal, incrementing the signals_received and blocking the signal. ****************************************************************************/ + static void signal_handler(int sig, siginfo_t *info, void *unused) { BlockSignals(True, sig); @@ -59,8 +60,9 @@ static void signal_handler(int sig, siginfo_t *info, void *unused) } /**************************************************************************** -try to gain a linux capability + Try to gain a linux capability. ****************************************************************************/ + static void set_capability(unsigned capability) { #ifndef _LINUX_CAPABILITY_VERSION @@ -93,11 +95,11 @@ static void set_capability(unsigned capability) } } - /**************************************************************************** -call SETLEASE. If we get EACCES then we try setting up the right capability and -try again + Call SETLEASE. If we get EACCES then we try setting up the right capability and + try again ****************************************************************************/ + static int linux_setlease(int fd, int leasetype) { int ret; @@ -116,31 +118,27 @@ static int linux_setlease(int fd, int leasetype) return ret; } - /**************************************************************************** * Deal with the Linux kernel <--> smbd * oplock break protocol. ****************************************************************************/ + static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) { - SMB_DEV_T dev; - SMB_INO_T inode; - SMB_STRUCT_STAT sbuf; BOOL ret = True; + struct files_struct *fsp; - if (signals_received == signals_processed) return False; + if (signals_received == signals_processed) + return False; - if (sys_fstat((int)fd_pending,&sbuf) == -1) { + if ((fsp = file_find_fd(fd_pending)) == NULL) { DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd_pending)); ret = False; goto out; } - dev = sbuf.st_dev; - inode = sbuf.st_ino; - DEBUG(3,("receive_local_message: kernel oplock break request received for \ -dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); +dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode )); /* * Create a kernel oplock break message. @@ -154,8 +152,9 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&dev, sizeof(dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&inode, sizeof(inode)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); + memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); out: /* now we can receive more signals */ @@ -166,10 +165,10 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); return ret; } - /**************************************************************************** Attempt to set an kernel oplock on a file. ****************************************************************************/ + static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (linux_setlease(fsp->fd, F_WRLCK) == -1) { @@ -180,16 +179,16 @@ inode = %.0f. (%s)\n", return False; } - DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode)); + DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); return True; } - /**************************************************************************** Release a kernel oplock on a file. ****************************************************************************/ + static void linux_release_kernel_oplock(files_struct *fsp) { if (DEBUGLVL(10)) { @@ -198,9 +197,9 @@ static void linux_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fd, F_GETLEASE, 0); - dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \ + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, state ); + (double)fsp->inode, fsp->file_id, state ); } /* @@ -209,18 +208,19 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, if (linux_setlease(fsp->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n", + dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, strerror(errno) ); + (double)fsp->inode, fsp->file_id, strerror(errno) ); } } } - /**************************************************************************** -parse a kernel oplock message + Parse a kernel oplock message. ****************************************************************************/ -static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode, SMB_DEV_T *dev) + +static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode, + SMB_DEV_T *dev, unsigned long *file_id) { /* Ensure that the msg length is correct. */ if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { @@ -229,41 +229,44 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i return False; } - memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); - memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); + memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); + memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); + memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id)); - DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f\n", - (unsigned int)*dev, (double)*inode)); + DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %ul\n", + (unsigned int)*dev, (double)*inode, *file_id)); return True; } - /**************************************************************************** -see if a oplock message is waiting + See if a oplock message is waiting. ****************************************************************************/ + static BOOL linux_oplock_msg_waiting(fd_set *fds) { return signals_processed != signals_received; } /**************************************************************************** -see if the kernel supports oplocks + See if the kernel supports oplocks. ****************************************************************************/ + static BOOL linux_oplocks_available(void) { int fd, ret; fd = open("/dev/null", O_RDONLY); - if (fd == -1) return False; /* uggh! */ + if (fd == -1) + return False; /* uggh! */ ret = fcntl(fd, F_GETLEASE, 0); close(fd); return ret == F_UNLCK; } - /**************************************************************************** -setup kernel oplocks + Setup kernel oplocks. ****************************************************************************/ + struct kernel_oplocks *linux_init_kernel_oplocks(void) { static struct kernel_oplocks koplocks; @@ -274,13 +277,13 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) return NULL; } - act.sa_handler = NULL; - act.sa_sigaction = signal_handler; - act.sa_flags = SA_SIGINFO; - if (sigaction(RT_SIGNAL_LEASE, &act, NULL) != 0) { + act.sa_handler = NULL; + act.sa_sigaction = signal_handler; + act.sa_flags = SA_SIGINFO; + if (sigaction(RT_SIGNAL_LEASE, &act, NULL) != 0) { DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler\n")); return NULL; - } + } koplocks.receive_message = linux_oplock_receive_message; koplocks.set_oplock = linux_set_kernel_oplock; @@ -293,9 +296,6 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) return &koplocks; } - - - #else void oplock_linux_dummy(void) {} #endif /* HAVE_KERNEL_OPLOCKS_LINUX */ -- cgit From 7cd889f566ebe352721943e53a055db5b817f12f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sat, 20 Oct 2001 23:34:40 +0000 Subject: Converted a bunch of 0x85 constants to SMBkeepalive. (This used to be commit b16a15a13ed7d267c6366abaeeb3ccafa5776f5e) --- source3/smbd/process.c | 4 ++-- source3/smbd/reply.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a0bfdbb2a2..cf01cd2cf5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -254,7 +254,7 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) do { ret = receive_message_or_smb(inbuf,bufsize,timeout); - got_keepalive = (ret && (CVAL(inbuf,0) == 0x85)); + got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive)); } while (ret && got_keepalive); return ret; @@ -867,7 +867,7 @@ void process_smb(char *inbuf, char *outbuf) if (msg_type == 0) show_msg(inbuf); - else if(msg_type == 0x85) + else if(msg_type == SMBkeepalive) return; /* Keepalive packet. */ nread = construct_reply(inbuf,outbuf,nread,max_send); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 845fabda92..852a2d867b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -122,7 +122,7 @@ int reply_special(char *inbuf,char *outbuf) case 0x89: /* session keepalive request (some old clients produce this?) */ - CVAL(outbuf,0) = 0x85; + CVAL(outbuf,0) = SMBkeepalive; CVAL(outbuf,3) = 0; break; @@ -132,7 +132,7 @@ int reply_special(char *inbuf,char *outbuf) DEBUG(0,("Unexpected session response\n")); break; - case 0x85: /* session keepalive */ + case SMBkeepalive: /* session keepalive */ default: return(0); } -- cgit From b7331220c65747c6d7de2b05372839c20f712439 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 21 Oct 2001 00:10:16 +0000 Subject: fixed the spnego detection code in session setup this gets share mode working again (This used to be commit 8286e5307ca47f14d27ee0d9bc9700d52151d56a) --- source3/smbd/sesssetup.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1ca7066c41..3cac6f338b 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -80,6 +80,11 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } +#if 0 + chdir("/home/tridge"); + file_save("ticket.dat", ticket.data, ticket.length); +#endif + packet.length = ticket.length; packet.data = (krb5_pointer)ticket.data; @@ -196,7 +201,8 @@ static int reply_spnego_negotiate(connection_struct *conn, for (i=0;OIDs[i];i++) { DEBUG(3,("Got OID %s\n", OIDs[i])); - if (strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) { + if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 || + strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) { got_kerberos = True; } free(OIDs[i]); @@ -504,7 +510,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, BOOL doencrypt = global_encrypted_passwords_negotiated; START_PROFILE(SMBsesssetupX); - if (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) { + if (SVAL(inbuf, smb_wct) == 12) { /* it's a SPNEGO session setup */ return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } -- cgit From cbe31055f8deb5844b34e8f1b32e27c830d134ed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 21 Oct 2001 00:11:22 +0000 Subject: support both old and new kerberos OIDs (This used to be commit eac164c7e650a8f855e7b662b126a5dfc5516927) --- source3/smbd/negprot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 2eea6fa281..6926e50402 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -164,7 +164,7 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) extern pstring global_myname; uint8 guid[16]; const char *OIDs[] = {OID_NTLMSSP, - OID_KERBEROS5_OLD, + OID_KERBEROS5, NULL}; char *principle; int len; -- cgit From 42a4e6890cfb35a0a01f29a48ffa99bcf0d409a5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 21 Oct 2001 03:26:24 +0000 Subject: change smbd to use HOST/hostname principle form until I work out how to use the other form in netjoin (This used to be commit 58cfa13d6576bd34ceed7ba6ad52bced96e50544) --- source3/smbd/negprot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 6926e50402..dc19e2bdfb 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -173,7 +173,9 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) safe_strcpy(guid, global_myname, 16); strlower(guid); - asprintf(&principle, "%s$@%s", guid, lp_realm()); + /* win2000 uses host$@REALM, which we will probably use eventually, + but for now this works */ + asprintf(&principle, "HOST/%s@%s", guid, lp_realm()); blob = spnego_gen_negTokenInit(guid, OIDs, principle); free(principle); -- cgit From a0a42f2c1f7f9644d27c479951db443516a09c18 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 21 Oct 2001 03:27:13 +0000 Subject: change smbd to use HOST/hostname principle form until I work out how to use the other form in netjoin smb_wct is a char, not a word (This used to be commit 3dbb48b188980cf6c869dc762e3039dd375bf392) --- source3/smbd/sesssetup.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3cac6f338b..7f9a09c79b 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -40,7 +40,8 @@ static int reply_spnego_kerberos(connection_struct *conn, krb5_ticket *tkt = NULL; int ret; char *realm, *client, *p; - fstring service; + fstring hostname; + char *principle; extern pstring global_myname; const struct passwd *pw; char *user; @@ -55,35 +56,24 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - /* the service is the wins name lowercase with $ tacked on */ - fstrcpy(service, global_myname); - strlower(service); - fstrcat(service, "$"); - + fstrcpy(hostname, global_myname); + strlower(hostname); + asprintf(&principle, "HOST/%s@%s", hostname, realm); + ret = krb5_init_context(&context); if (ret) { DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -#if 0 - ret = krb5_build_principal(context, &server, strlen(realm), - realm, "HOST", "blu", NULL); -#else - ret = krb5_build_principal(context, &server, strlen(realm), - realm, service, NULL); -#endif - krb5_princ_type(context, server) = KRB5_NT_PRINCIPAL; - + ret = krb5_parse_name(context, principle, &server); if (ret) { - DEBUG(1,("krb5_build_principal failed (%s)\n", error_message(ret))); + DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", + principle, error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -#if 0 - chdir("/home/tridge"); - file_save("ticket.dat", ticket.data, ticket.length); -#endif + free(principle); packet.length = ticket.length; packet.data = (krb5_pointer)ticket.data; @@ -437,6 +427,8 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha extern uint32 global_client_caps; int ret; + DEBUG(3,("Doing spego session setup\n")); + if (global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv10); } @@ -509,9 +501,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern int max_send; BOOL doencrypt = global_encrypted_passwords_negotiated; START_PROFILE(SMBsesssetupX); + + DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2))); - if (SVAL(inbuf, smb_wct) == 12) { - /* it's a SPNEGO session setup */ + /* a SPNEGO session setup has 12 command words, whereas a normal + NT1 session setup has 13. See the cifs spec. */ + if (CVAL(inbuf, smb_wct) == 12 && + (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } -- cgit From 51bc5f128c870336517af9a36b5f49d83b160e45 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 21 Oct 2001 06:04:46 +0000 Subject: patch for neater output() function from vance (This used to be commit 2472ecf7fc510115489baf0a888b511446b9c1fd) --- source3/smbd/build_options.c | 544 +++++++++++++++---------------------------- 1 file changed, 193 insertions(+), 351 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 7afd2c5652..d12fe40872 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -23,692 +23,534 @@ #include "includes.h" #include "build_env.h" +static void output(BOOL screen, char *format, ...) PRINTF_ATTRIBUTE(2,3); + +/* +#define OUTPUT(x) snprintf(outstring,sizeof(outstring),x); output(screen,outstring); +*/ /**************************************************************************** helper function for build_options ****************************************************************************/ -static void output(BOOL screen, char *buffer) +static void output(BOOL screen, char *format, ...) { + char *ptr; + va_list ap; + + va_start(ap, format); + vasprintf(&ptr,format,ap); + va_end(ap); + if (screen) { - d_printf(buffer); + d_printf("%s", ptr); } else { - DEBUG(4, (buffer)); + DEBUG(4,("%s", ptr)); } + + SAFE_FREE(ptr); } + /**************************************************************************** options set at build time for the samba suite ****************************************************************************/ void build_options(BOOL screen) { - pstring outstring; - if ((DEBUGLEVEL < 4) && (!screen)) { return; } #ifdef _BUILD_ENV_H /* Output information about the build environment */ - snprintf(outstring,sizeof(outstring),"Build environment:\n"); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," Built by: %s@%s\n",BUILD_ENV_USER,BUILD_ENV_HOST); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," Built on: %s\n",BUILD_ENV_DATE); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," Built using: %s\n",BUILD_ENV_COMPILER); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," Build host: %s\n",BUILD_ENV_UNAME); - output(screen,outstring); - - snprintf(outstring,sizeof(outstring)," SRCDIR: %s\n",BUILD_ENV_SRCDIR); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," BUILDDIR: %s\n",BUILD_ENV_BUILDDIR); - output(screen,outstring); + output(screen,"Build environment:\n"); + output(screen," Built by: %s@%s\n",BUILD_ENV_USER,BUILD_ENV_HOST); + output(screen," Built on: %s\n",BUILD_ENV_DATE); + + output(screen," Built using: %s\n",BUILD_ENV_COMPILER); + output(screen," Build host: %s\n",BUILD_ENV_UNAME); + output(screen," SRCDIR: %s\n",BUILD_ENV_SRCDIR); + output(screen," BUILDDIR: %s\n",BUILD_ENV_BUILDDIR); + #endif /* Output various options (most correspond to --with options) */ - snprintf(outstring,sizeof(outstring),"\nBuild options:\n"); - output(screen,outstring); + output(screen,"\nBuild options:\n"); #ifdef WITH_SMBWRAPPER - snprintf(outstring,sizeof(outstring)," WITH_SMBWRAPPER\n"); - output(screen,outstring); + output(screen," WITH_SMBWRAPPER\n"); #endif #ifdef WITH_AFS - snprintf(outstring,sizeof(outstring)," WITH_AFS\n"); - output(screen,outstring); + output(screen," WITH_AFS\n"); #endif #ifdef WITH_DFS - snprintf(outstring,sizeof(outstring)," WITH_DFS\n"); - output(screen,outstring); + output(screen," WITH_DFS\n"); #endif -#if defined(KRB4_AUTH) && defined(KRB4_DIR) - snprintf(outstring,sizeof(outstring)," KRB4_AUTH"); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," KRB4_DIR: %s\n",KRB4_DIR); - output(screen,outstring); +#ifdef KRB4_AUTH + output(screen," KRB4_AUTH"); #endif -#if HAVE_KRB5 +#ifdef HAVE_KRB5 output(screen," HAVE_KRB5"); #endif #ifdef WITH_AUTOMOUNT - snprintf(outstring,sizeof(outstring)," WITH_AUTOMOUNT\n"); - output(screen,outstring); + output(screen," WITH_AUTOMOUNT\n"); #endif #ifdef WITH_SMBMOUNT - snprintf(outstring,sizeof(outstring)," WITH_SMBMOUNT\n"); - output(screen,outstring); + output(screen," WITH_SMBMOUNT\n"); #endif #ifdef WITH_PAM - snprintf(outstring,sizeof(outstring)," WITH_PAM\n"); - output(screen,outstring); + output(screen," WITH_PAM\n"); #endif #ifdef WITH_TDB_SAM - snprintf(outstring,sizeof(outstring)," WITH_TDB_SAM\n"); - output(screen,outstring); + output(screen," WITH_TDB_SAM\n"); #endif #ifdef WITH_LDAP_SAM - snprintf(outstring,sizeof(outstring)," WITH_LDAP_SAM\n"); - output(screen,outstring); + output(screen," WITH_LDAP_SAM\n"); #endif #ifdef WITH_SMBPASSWD_SAM - snprintf(outstring,sizeof(outstring)," WITH_SMBPASSWD_SAM\n"); - output(screen,outstring); + output(screen," WITH_SMBPASSWD_SAM\n"); #endif #ifdef WITH_NISPLUS_SAM - snprintf(outstring,sizeof(outstring)," WITH_NISPLUS_SAM\n"); - output(screen,outstring); + output(screen," WITH_NISPLUS_SAM\n"); #endif #ifdef WITH_NISPLUS_HOME - snprintf(outstring,sizeof(outstring)," WITH_NISPLUS_HOME\n"); - output(screen,outstring); + output(screen," WITH_NISPLUS_HOME\n"); #endif #ifdef WITH_SSL - snprintf(outstring,sizeof(outstring)," WITH_SSL\n"); - output(screen,outstring); + output(screen," WITH_SSL\n"); #endif #ifdef SSL_DIR - snprintf(outstring,sizeof(outstring)," SSL_DIR: %s\n",SSL_DIR); - output(screen,outstring); + output(screen," SSL_DIR: %s\n",SSL_DIR); #endif #ifdef WITH_SYSLOG - snprintf(outstring,sizeof(outstring)," WITH_SYSLOG\n"); - output(screen,outstring); + output(screen," WITH_SYSLOG\n"); #endif #ifdef WITH_PROFILE - snprintf(outstring,sizeof(outstring)," WITH_PROFILE\n"); - output(screen,outstring); + output(screen," WITH_PROFILE\n"); #endif #ifdef WITH_QUOTAS - snprintf(outstring,sizeof(outstring)," WITH_QUOTAS\n"); - output(screen,outstring); + output(screen," WITH_QUOTAS\n"); #endif #ifdef WITH_MSDFS - snprintf(outstring,sizeof(outstring)," WITH_MSDFS\n"); - output(screen,outstring); + output(screen," WITH_MSDFS\n"); #endif #ifdef WITH_VFS - snprintf(outstring,sizeof(outstring)," WITH_VFS\n"); - output(screen,outstring); + output(screen," WITH_VFS\n"); #endif #ifdef USE_SPINLOCKS - snprintf(outstring,sizeof(outstring)," USE_SPINLOCKS\n"); - output(screen,outstring); + output(screen," USE_SPINLOCKS\n"); #endif #ifdef SPARC_SPINLOCKS - snprintf(outstring,sizeof(outstring)," SPARC_SPINLOCKS\n"); - output(screen,outstring); + output(screen," SPARC_SPINLOCKS\n"); #endif #ifdef INTEL_SPINLOCKS - snprintf(outstring,sizeof(outstring)," INTEL_SPINLOCKS\n"); - output(screen,outstring); + output(screen," INTEL_SPINLOCKS\n"); #endif #ifdef MIPS_SPINLOCKS - snprintf(outstring,sizeof(outstring)," MIPS_SPINLOCKS\n"); - output(screen,outstring); + output(screen," MIPS_SPINLOCKS\n"); #endif #ifdef POWERPC_SPINLOCKS - snprintf(outstring,sizeof(outstring)," POWERPC_SPINLOCKS\n"); - output(screen,outstring); + output(screen," POWERPC_SPINLOCKS\n"); #endif #ifdef HAVE_UNIXWARE_ACLS - snprintf(outstring,sizeof(outstring)," HAVE_UNIXWARE_ACLS\n"); - output(screen,outstring); + output(screen," HAVE_UNIXWARE_ACLS\n"); #endif #ifdef HAVE_SOLARIS_ACLS - snprintf(outstring,sizeof(outstring)," HAVE_SOLARIS_ACLS\n"); - output(screen,outstring); + output(screen," HAVE_SOLARIS_ACLS\n"); #endif #ifdef HAVE_IRIX_ACLS - snprintf(outstring,sizeof(outstring)," HAVE_IRIX_ACLS\n"); - output(screen,outstring); + output(screen," HAVE_IRIX_ACLS\n"); #endif #ifdef HAVE_AIX_ACLS - snprintf(outstring,sizeof(outstring)," HAVE_AIX_ACLS\n"); - output(screen,outstring); + output(screen," HAVE_AIX_ACLS\n"); #endif #ifdef HAVE_POSIX_ACLS - snprintf(outstring,sizeof(outstring)," HAVE_POSIX_ACLS\n"); - output(screen,outstring); + output(screen," HAVE_POSIX_ACLS\n"); #endif #ifdef HAVE_TRU64_ACLS - snprintf(outstring,sizeof(outstring)," HAVE_TRU64_ACLS\n"); - output(screen,outstring); + output(screen," HAVE_TRU64_ACLS\n"); #endif #ifdef HAVE_ACL_GET_PERM_NP - snprintf(outstring,sizeof(outstring)," HAVE_ACL_GET_PERM_NP\n"); - output(screen,outstring); + output(screen," HAVE_ACL_GET_PERM_NP\n"); #endif #ifdef HAVE_NO_ACLS - snprintf(outstring,sizeof(outstring)," HAVE_NO_ACLS\n"); - output(screen,outstring); + output(screen," HAVE_NO_ACLS\n"); #endif #ifdef HAVE_LIBREADLINE - snprintf(outstring,sizeof(outstring)," HAVE_LIBREADLINE\n"); - output(screen,outstring); + output(screen," HAVE_LIBREADLINE\n"); #endif #ifdef WITH_LIBICONV - snprintf(outstring,sizeof(outstring)," WITH_LIBICONV: %s\n",WITH_LIBICONV); - output(screen,outstring); + output(screen," WITH_LIBICONV: %s\n",WITH_LIBICONV); #endif /* Output various paths to files and directories */ - snprintf(outstring,sizeof(outstring),"\nPaths:\n"); - output(screen,outstring); + output(screen,"\nPaths:\n"); #ifdef CONFIGFILE - snprintf(outstring,sizeof(outstring)," CONFIGFILE: %s\n",CONFIGFILE); - output(screen,outstring); + output(screen," CONFIGFILE: %s\n",CONFIGFILE); #endif #ifdef PRIVATE_DIR - snprintf(outstring,sizeof(outstring)," PRIVATE_DIR: %s\n",PRIVATE_DIR); - output(screen,outstring); + output(screen," PRIVATE_DIR: %s\n",PRIVATE_DIR); #endif #ifdef LMHOSTSFILE - snprintf(outstring,sizeof(outstring)," LMHOSTSFILE: %s\n",LMHOSTSFILE); - output(screen,outstring); + output(screen," LMHOSTSFILE: %s\n",LMHOSTSFILE); #endif #ifdef SBINDIR - snprintf(outstring,sizeof(outstring)," SBINDIR: %s\n",SBINDIR); - output(screen,outstring); + output(screen," SBINDIR: %s\n",SBINDIR); #endif #ifdef BINDIR - snprintf(outstring,sizeof(outstring)," BINDIR: %s\n",BINDIR); - output(screen,outstring); + output(screen," BINDIR: %s\n",BINDIR); #endif #ifdef LOCKDIR - snprintf(outstring,sizeof(outstring)," LOCKDIR: %s\n",LOCKDIR); - output(screen,outstring); + output(screen," LOCKDIR: %s\n",LOCKDIR); #endif #ifdef DRIVERFILE - snprintf(outstring,sizeof(outstring)," DRIVERFILE: %s\n",DRIVERFILE); - output(screen,outstring); + output(screen," DRIVERFILE: %s\n",DRIVERFILE); #endif #ifdef LOGFILEBASE - snprintf(outstring,sizeof(outstring)," LOGFILEBASE: %s\n",LOGFILEBASE); - output(screen,outstring); + output(screen," LOGFILEBASE: %s\n",LOGFILEBASE); #endif #ifdef FORMSFILE - snprintf(outstring,sizeof(outstring)," FORMSFILE: %s\n",FORMSFILE); - output(screen,outstring); + output(screen," FORMSFILE: %s\n",FORMSFILE); #endif #ifdef NTDRIVERSDIR - snprintf(outstring,sizeof(outstring)," NTDRIVERSDIR: %s\n",NTDRIVERSDIR); - output(screen,outstring); + output(screen," NTDRIVERSDIR: %s\n",NTDRIVERSDIR); #endif /*Output various other options (most map to defines in the configure script*/ - snprintf(outstring,sizeof(outstring),"\nOther Build Options:\n"); - output(screen,outstring); + output(screen,"\nOther Build Options:\n"); #ifdef HAVE_VOLATILE - snprintf(outstring,sizeof(outstring)," HAVE_VOLATILE\n"); - output(screen,outstring); + output(screen," HAVE_VOLATILE\n"); #endif #ifdef HAVE_SHADOW_H - snprintf(outstring,sizeof(outstring)," HAVE_SHADOW_H\n"); - output(screen,outstring); + output(screen," HAVE_SHADOW_H\n"); #endif #ifdef HAVE_CRYPT - snprintf(outstring,sizeof(outstring)," HAVE_CRYPT\n"); - output(screen,outstring); + output(screen," HAVE_CRYPT\n"); #endif #ifdef USE_BOTH_CRYPT_CALLS - snprintf(outstring,sizeof(outstring)," USE_BOTH_CRYPT_CALLS\n"); - output(screen,outstring); + output(screen," USE_BOTH_CRYPT_CALLS\n"); #endif #ifdef HAVE_TRUNCATED_SALT - snprintf(outstring,sizeof(outstring)," HAVE_TRUNCATED_SALT\n"); - output(screen,outstring); + output(screen," HAVE_TRUNCATED_SALT\n"); #endif #ifdef HAVE_CUPS - snprintf(outstring,sizeof(outstring)," HAVE_CUPS\n"); - output(screen,outstring); + output(screen," HAVE_CUPS\n"); #endif #ifdef HAVE_CUPS_CUPS_H - snprintf(outstring,sizeof(outstring)," HAVE_CUPS_CUPS_H\n"); - output(screen,outstring); + output(screen," HAVE_CUPS_CUPS_H\n"); #endif #ifdef HAVE_CUPS_LANGUAGE_H - snprintf(outstring,sizeof(outstring)," HAVE_CUPS_LANGUAGE_H\n"); - output(screen,outstring); + output(screen," HAVE_CUPS_LANGUAGE_H\n"); #endif #ifdef HAVE_LIBDL - snprintf(outstring,sizeof(outstring)," HAVE_LIBDL\n"); - output(screen,outstring); + output(screen," HAVE_LIBDL\n"); #endif #ifdef HAVE_UNIXSOCKET - snprintf(outstring,sizeof(outstring)," HAVE_UNIXSOCKET\n"); - output(screen,outstring); + output(screen," HAVE_UNIXSOCKET\n"); #endif #ifdef HAVE_SOCKLEN_T_TYPE - snprintf(outstring,sizeof(outstring)," HAVE_SOCKLEN_T_TYPE\n"); - output(screen,outstring); + output(screen," HAVE_SOCKLEN_T_TYPE\n"); #endif #ifdef HAVE_SIG_ATOMIC_T_TYPE - snprintf(outstring,sizeof(outstring)," HAVE_SIG_ATOMIC_T_TYPE\n"); - output(screen,outstring); + output(screen," HAVE_SIG_ATOMIC_T_TYPE\n"); #endif #ifdef HAVE_SETRESUID - snprintf(outstring,sizeof(outstring)," HAVE_SETRESUID\n"); - output(screen,outstring); + output(screen," HAVE_SETRESUID\n"); #endif #ifdef HAVE_SETRESGID - snprintf(outstring,sizeof(outstring)," HAVE_SETRESGID\n"); - output(screen,outstring); + output(screen," HAVE_SETRESGID\n"); #endif #ifdef HAVE_CONNECT - snprintf(outstring,sizeof(outstring)," HAVE_CONNECT\n"); - output(screen,outstring); + output(screen," HAVE_CONNECT\n"); #endif #ifdef HAVE_YP_GET_DEFAULT_DOMAIN - snprintf(outstring,sizeof(outstring)," HAVE_YP_GET_DEFAULT_DOMAIN\n"); - output(screen,outstring); + output(screen," HAVE_YP_GET_DEFAULT_DOMAIN\n"); #endif #ifdef HAVE_STAT64 - snprintf(outstring,sizeof(outstring)," HAVE_STAT64\n"); - output(screen,outstring); + output(screen," HAVE_STAT64\n"); #endif #ifdef HAVE_LSTAT64 - snprintf(outstring,sizeof(outstring)," HAVE_LSTAT64\n"); - output(screen,outstring); + output(screen," HAVE_LSTAT64\n"); #endif #ifdef HAVE_FSTAT64 - snprintf(outstring,sizeof(outstring)," HAVE_FSTAT64\n"); - output(screen,outstring); + output(screen," HAVE_FSTAT64\n"); #endif #ifdef HAVE_STRCASECMP - snprintf(outstring,sizeof(outstring)," HAVE_STRCASECMP\n"); - output(screen,outstring); + output(screen," HAVE_STRCASECMP\n"); #endif #ifdef HAVE_MEMSET - snprintf(outstring,sizeof(outstring)," HAVE_MEMSET\n"); - output(screen,outstring); + output(screen," HAVE_MEMSET\n"); #endif #ifdef HAVE_LONGLONG - snprintf(outstring,sizeof(outstring)," HAVE_LONGLONG\n"); - output(screen,outstring); + output(screen," HAVE_LONGLONG\n"); #endif #ifdef COMPILER_SUPPORTS_LL - snprintf(outstring,sizeof(outstring)," COMPILER_SUPPORTS_LL\n"); - output(screen,outstring); + output(screen," COMPILER_SUPPORTS_LL\n"); #endif #ifdef SIZEOF_OFF_T - snprintf(outstring,sizeof(outstring)," SIZEOF_OFF_T: %d\n",SIZEOF_OFF_T); - output(screen,outstring); + output(screen," SIZEOF_OFF_T: %d\n",SIZEOF_OFF_T); #endif #ifdef HAVE_OFF64_T - snprintf(outstring,sizeof(outstring)," HAVE_OFF64_T\n"); - output(screen,outstring); + output(screen," HAVE_OFF64_T\n"); #endif #ifdef SIZEOF_INO_T - snprintf(outstring,sizeof(outstring)," SIZEOF_INO_T: %d\n",SIZEOF_INO_T); - output(screen,outstring); + output(screen," SIZEOF_INO_T: %d\n",SIZEOF_INO_T); #endif #ifdef HAVE_INO64_T - snprintf(outstring,sizeof(outstring)," HAVE_INO64_T\n"); - output(screen,outstring); + output(screen," HAVE_INO64_T\n"); #endif #ifdef HAVE_STRUCT_DIRENT64 - snprintf(outstring,sizeof(outstring)," HAVE_STRUCT_DIRENT64\n"); - output(screen,outstring); + output(screen," HAVE_STRUCT_DIRENT64\n"); #endif #ifdef HAVE_UNSIGNED_CHAR - snprintf(outstring,sizeof(outstring)," HAVE_UNSIGNED_CHAR\n"); - output(screen,outstring); + output(screen," HAVE_UNSIGNED_CHAR\n"); #endif #ifdef HAVE_SOCK_SIN_LEN - snprintf(outstring,sizeof(outstring)," HAVE_SOCK_SIN_LEN\n"); - output(screen,outstring); + output(screen," HAVE_SOCK_SIN_LEN\n"); #endif #ifdef SEEKDIR_RETURNS_VOID - snprintf(outstring,sizeof(outstring)," SEEKDIR_RETURNS_VOID\n"); - output(screen,outstring); + output(screen," SEEKDIR_RETURNS_VOID\n"); #endif #ifdef HAVE_FILE_MACRO - snprintf(outstring,sizeof(outstring)," HAVE_FILE_MACRO\n"); - output(screen,outstring); + output(screen," HAVE_FILE_MACRO\n"); #endif #ifdef HAVE_FUNCTION_MACRO - snprintf(outstring,sizeof(outstring)," HAVE_FUNCTION_MACRO\n"); - output(screen,outstring); + output(screen," HAVE_FUNCTION_MACRO\n"); #endif #ifdef HAVE_GETTIMEOFDAY - snprintf(outstring,sizeof(outstring)," HAVE_GETTIMEOFDAY\n"); - output(screen,outstring); + output(screen," HAVE_GETTIMEOFDAY\n"); #endif #ifdef HAVE_C99_VSNPRINTF - snprintf(outstring,sizeof(outstring)," HAVE_C99_VSNPRINTF\n"); - output(screen,outstring); + output(screen," HAVE_C99_VSNPRINTF\n"); #endif #ifdef HAVE_BROKEN_READDIR - snprintf(outstring,sizeof(outstring)," HAVE_BROKEN_READDIR\n"); - output(screen,outstring); + output(screen," HAVE_BROKEN_READDIR\n"); #endif #ifdef HAVE_NATIVE_ICONV - snprintf(outstring,sizeof(outstring)," HAVE_NATIVE_ICONV\n"); - output(screen,outstring); + output(screen," HAVE_NATIVE_ICONV\n"); #endif #ifdef HAVE_KERNEL_OPLOCKS_LINUX - snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_OPLOCKS_LINUX\n"); - output(screen,outstring); + output(screen," HAVE_KERNEL_OPLOCKS_LINUX\n"); #endif #ifdef HAVE_KERNEL_CHANGE_NOTIFY - snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_CHANGE_NOTIFY\n"); - output(screen,outstring); + output(screen," HAVE_KERNEL_CHANGE_NOTIFY\n"); #endif #ifdef HAVE_KERNEL_SHARE_MODES - snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_SHARE_MODES\n"); - output(screen,outstring); + output(screen," HAVE_KERNEL_SHARE_MODES\n"); #endif #ifdef HAVE_KERNEL_OPLOCKS_IRIX - snprintf(outstring,sizeof(outstring)," HAVE_KERNEL_OPLOCKS_IRIX\n"); - output(screen,outstring); + output(screen," HAVE_KERNEL_OPLOCKS_IRIX\n"); #endif #ifdef HAVE_IRIX_SPECIFIC_CAPABILITIES - snprintf(outstring,sizeof(outstring)," HAVE_IRIX_SPECIFIC_CAPABILITIES\n"); - output(screen,outstring); + output(screen," HAVE_IRIX_SPECIFIC_CAPABILITIES\n"); #endif #ifdef HAVE_INT16_FROM_RPC_RPC_H - snprintf(outstring,sizeof(outstring)," HAVE_INT16_FROM_RPC_RPC_H\n"); - output(screen,outstring); + output(screen," HAVE_INT16_FROM_RPC_RPC_H\n"); #endif #ifdef HAVE_UINT16_FROM_RPC_RPC_H - snprintf(outstring,sizeof(outstring)," HAVE_UINT16_FROM_RPC_RPC_H\n"); - output(screen,outstring); + output(screen," HAVE_UINT16_FROM_RPC_RPC_H\n"); #endif #ifdef HAVE_INT32_FROM_RPC_RPC_H - snprintf(outstring,sizeof(outstring)," HAVE_INT16_FROM_RPC_RPC_H\n"); - output(screen,outstring); + output(screen," HAVE_INT16_FROM_RPC_RPC_H\n"); #endif #ifdef HAVE_UINT32_FROM_RPC_RPC_H - snprintf(outstring,sizeof(outstring)," HAVE_UINT32_FROM_RPC_RPC_H\n"); - output(screen,outstring); + output(screen," HAVE_UINT32_FROM_RPC_RPC_H\n"); #endif #ifdef HAVE_RPC_AUTH_ERROR_CONFLICT - snprintf(outstring,sizeof(outstring)," HAVE_RPC_AUTH_ERROR_CONFLICT\n"); - output(screen,outstring); + output(screen," HAVE_RPC_AUTH_ERROR_CONFLICT\n"); #endif #ifdef HAVE_FTRUNCATE_EXTEND - snprintf(outstring,sizeof(outstring)," HAVE_FTRUNCATE_EXTEND\n"); - output(screen,outstring); + output(screen," HAVE_FTRUNCATE_EXTEND\n"); #endif #ifdef HAVE_WORKING_AF_LOCAL - snprintf(outstring,sizeof(outstring)," HAVE_WORKING_AF_LOCAL\n"); - output(screen,outstring); + output(screen," HAVE_WORKING_AF_LOCAL\n"); #endif #ifdef HAVE_BROKEN_GETGROUPS - snprintf(outstring,sizeof(outstring)," HAVE_BROKEN_GETGROUPS\n"); - output(screen,outstring); + output(screen," HAVE_BROKEN_GETGROUPS\n"); #endif #ifdef REPLACE_GETPASS - snprintf(outstring,sizeof(outstring)," REPLACE_GETPASS\n"); - output(screen,outstring); + output(screen," REPLACE_GETPASS\n"); #endif #ifdef REPLACE_INET_NTOA - snprintf(outstring,sizeof(outstring)," REPLACE_INET_NTOA\n"); - output(screen,outstring); + output(screen," REPLACE_INET_NTOA\n"); #endif #ifdef HAVE_SECURE_MKSTEMP - snprintf(outstring,sizeof(outstring)," HAVE_SECURE_MKSTEMP\n"); - output(screen,outstring); + output(screen," HAVE_SECURE_MKSTEMP\n"); #endif #ifdef SYSCONF_SC_NGROUPS_MAX - snprintf(outstring,sizeof(outstring)," SYSCONF_SC_NGROUPS_MAX\n"); - output(screen,outstring); + output(screen," SYSCONF_SC_NGROUPS_MAX\n"); #endif #ifdef HAVE_IFACE_AIX - snprintf(outstring,sizeof(outstring)," HAVE_IFACE_AIX\n"); - output(screen,outstring); + output(screen," HAVE_IFACE_AIX\n"); #endif #ifdef HAVE_IFACE_IFCONF - snprintf(outstring,sizeof(outstring)," HAVE_IFACE_IFCONF\n"); - output(screen,outstring); + output(screen," HAVE_IFACE_IFCONF\n"); #endif #ifdef HAVE_IFACE_IFREQ - snprintf(outstring,sizeof(outstring)," HAVE_IFACE_IFREQ\n"); - output(screen,outstring); + output(screen," HAVE_IFACE_IFREQ\n"); #endif #ifdef USE_SETRESUID - snprintf(outstring,sizeof(outstring)," USE_SETRESUID\n"); - output(screen,outstring); + output(screen," USE_SETRESUID\n"); #endif #ifdef USE_SETRESGID - snprintf(outstring,sizeof(outstring)," USE_SETREUID\n"); - output(screen,outstring); + output(screen," USE_SETREUID\n"); #endif #ifdef USE_SETEUID - snprintf(outstring,sizeof(outstring)," USE_SETEUID\n"); - output(screen,outstring); + output(screen," USE_SETEUID\n"); #endif #ifdef USE_SETUIDX - snprintf(outstring,sizeof(outstring)," USE_SETUIDX\n"); - output(screen,outstring); + output(screen," USE_SETUIDX\n"); #endif #ifdef HAVE_MMAP - snprintf(outstring,sizeof(outstring)," HAVE_MMAP\n"); - output(screen,outstring); + output(screen," HAVE_MMAP\n"); #endif #ifdef MMAP_BLACKLIST - snprintf(outstring,sizeof(outstring)," MMAP_BLACKLIST\n"); - output(screen,outstring); + output(screen," MMAP_BLACKLIST\n"); #endif #ifdef FTRUNCATE_NEEDS_ROOT - snprintf(outstring,sizeof(outstring)," FTRUNCATE_NEEDS_ROOT\n"); - output(screen,outstring); + output(screen," FTRUNCATE_NEEDS_ROOT\n"); #endif #ifdef HAVE_FCNTL_LOCK - snprintf(outstring,sizeof(outstring)," HAVE_FCNTL_LOCK\n"); - output(screen,outstring); + output(screen," HAVE_FCNTL_LOCK\n"); #endif #ifdef HAVE_BROKEN_FCNTL64_LOCKS - snprintf(outstring,sizeof(outstring)," HAVE_BROKEN_FCNTL64_LOCKS\n"); - output(screen,outstring); + output(screen," HAVE_BROKEN_FCNTL64_LOCKS\n"); #endif #ifdef HAVE_STRUCT_FLOCK64 - snprintf(outstring,sizeof(outstring)," HAVE_STRUCT_FLOCK64\n"); - output(screen,outstring); + output(screen," HAVE_STRUCT_FLOCK64\n"); #endif #ifdef BROKEN_NISPLUS_INCLUDE_FILES - snprintf(outstring,sizeof(outstring)," BROKEN_NISPLUS_INCLUDE_FILES\n"); - output(screen,outstring); + output(screen," BROKEN_NISPLUS_INCLUDE_FILES\n"); #endif #ifdef HAVE_LIBPAM - snprintf(outstring,sizeof(outstring)," HAVE_LIBPAM\n"); - output(screen,outstring); + output(screen," HAVE_LIBPAM\n"); #endif #ifdef STAT_STATVFS64 - snprintf(outstring,sizeof(outstring)," STAT_STATVFS64\n"); - output(screen,outstring); + output(screen," STAT_STATVFS64\n"); #endif #ifdef STAT_STATVFS - snprintf(outstring,sizeof(outstring)," STAT_STATVFS\n"); - output(screen,outstring); + output(screen," STAT_STATVFS\n"); #endif #ifdef STAT_STATFS3_OSF1 - snprintf(outstring,sizeof(outstring)," STAT_STATFS3_OSF1\n"); - output(screen,outstring); + output(screen," STAT_STATFS3_OSF1\n"); #endif #ifdef STAT_STATFS2_BSIZE - snprintf(outstring,sizeof(outstring)," STAT_STATFS2_BSIZE\n"); - output(screen,outstring); + output(screen," STAT_STATFS2_BSIZE\n"); #endif #ifdef STAT_STATFS4 - snprintf(outstring,sizeof(outstring)," STAT_STATFS4\n"); - output(screen,outstring); + output(screen," STAT_STATFS4\n"); #endif #ifdef STAT_STATFS2_FSIZE - snprintf(outstring,sizeof(outstring)," STAT_STATFS2_FSIZE\n"); - output(screen,outstring); + output(screen," STAT_STATFS2_FSIZE\n"); #endif #ifdef STAT_STATFS2_FS_DATA - snprintf(outstring,sizeof(outstring)," STAT_STATFS2_FS_DATA\n"); - output(screen,outstring); + output(screen," STAT_STATFS2_FS_DATA\n"); #endif #ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT - snprintf(outstring,sizeof(outstring)," HAVE_EXPLICIT_LARGEFILE_SUPPORT\n"); - output(screen,outstring); + output(screen," HAVE_EXPLICIT_LARGEFILE_SUPPORT\n"); #endif #ifdef WITH_UTMP /* Output UTMP Stuff */ - snprintf(outstring,sizeof(outstring),"\nUTMP Related:\n"); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," WITH_UTMP\n"); - output(screen,outstring); + output(screen,"\nUTMP Related:\n"); + output(screen," WITH_UTMP\n"); #ifdef HAVE_UTIMBUF - snprintf(outstring,sizeof(outstring)," HAVE_UTIMBUF\n"); - output(screen,outstring); + output(screen," HAVE_UTIMBUF\n"); #endif #ifdef HAVE_UT_UT_NAME - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_NAME\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_NAME\n"); #endif #ifdef HAVE_UT_UT_USER - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_USER\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_USER\n"); #endif #ifdef HAVE_UT_UT_ID - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_ID\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_ID\n"); #endif #ifdef HAVE_UT_UT_HOST - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_HOST\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_HOST\n"); #endif #ifdef HAVE_UT_UT_TIME - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_TIME\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_TIME\n"); #endif #ifdef HAVE_UT_UT_TV - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_TV\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_TV\n"); #endif #ifdef HAVE_UT_UT_TYPE - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_TYPE\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_TYPE\n"); #endif #ifdef HAVE_UT_UT_PID - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_PID\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_PID\n"); #endif #ifdef HAVE_UT_UT_EXIT - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_EXIT\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_EXIT\n"); #endif #ifdef HAVE_UT_UT_ADDR - snprintf(outstring,sizeof(outstring)," HAVE_UT_UT_ADDR\n"); - output(screen,outstring); + output(screen," HAVE_UT_UT_ADDR\n"); #endif #ifdef PUTUTLINE_RETURNS_UTMP - snprintf(outstring,sizeof(outstring)," PUTUTLINE_RETURNS_UTMP\n"); - output(screen,outstring); + output(screen," PUTUTLINE_RETURNS_UTMP\n"); #endif #ifdef HAVE_UX_UT_SYSLEN - snprintf(outstring,sizeof(outstring)," HAVE_UX_UT_SYSLEN\n"); - output(screen,outstring); -#endif + output(screen," HAVE_UX_UT_SYSLEN\n"); #endif +#endif /* WITH_UTMP */ /* Output Build OS */ - snprintf(outstring,sizeof(outstring),"\nBuilt for host os:\n"); - output(screen,outstring); + output(screen,"\nBuilt for host os:\n"); #ifdef LINUX - snprintf(outstring,sizeof(outstring)," LINUX\n"); - output(screen,outstring); + output(screen," LINUX\n"); #endif #ifdef SUNOS5 - snprintf(outstring,sizeof(outstring)," SUNOS5\n"); - output(screen,outstring); + output(screen," SUNOS5\n"); #endif #ifdef SUNOS4 - snprintf(outstring,sizeof(outstring)," SUNOS4\n"); - output(screen,outstring); + output(screen," SUNOS4\n"); #endif /* BSD Isn't Defined in the configure script, but there is something about it in include/config.h.in (and I guess acconfig.h) */ #ifdef BSD - snprintf(outstring,sizeof(outstring)," BSD\n"); - output(screen,outstring); + output(screen," BSD\n"); #endif #ifdef IRIX - snprintf(outstring,sizeof(outstring)," IRIX\n"); - output(screen,outstring); + output(screen," IRIX\n"); #endif #ifdef IRIX6 - snprintf(outstring,sizeof(outstring)," IRIX6\n"); - output(screen,outstring); + output(screen," IRIX6\n"); #endif #ifdef AIX - snprintf(outstring,sizeof(outstring)," AIX\n"); - output(screen,outstring); + output(screen," AIX\n"); #endif #ifdef HPUX - snprintf(outstring,sizeof(outstring)," HPUX\n"); - output(screen,outstring); + output(screen," HPUX\n"); #endif #ifdef QNX - snprintf(outstring,sizeof(outstring)," QNX\n"); - output(screen,outstring); + output(screen," QNX\n"); #endif #ifdef OSF1 - snprintf(outstring,sizeof(outstring)," OSF1\n"); - output(screen,outstring); + output(screen," OSF1\n"); #endif #ifdef SCO - snprintf(outstring,sizeof(outstring)," SCO\n"); - output(screen,outstring); + output(screen," SCO\n"); #endif #ifdef UNIXWARE - snprintf(outstring,sizeof(outstring)," UNIXWARE\n"); - output(screen,outstring); + output(screen," UNIXWARE\n"); #endif #ifdef NEXT2 - snprintf(outstring,sizeof(outstring)," NEXT2\n"); - output(screen,outstring); + output(screen," NEXT2\n"); #endif #ifdef RELIANTUNIX - snprintf(outstring,sizeof(outstring)," RELIANTUNIX\n"); - output(screen,outstring); + output(screen," RELIANTUNIX\n"); #endif /* Output the sizes of the various types */ - snprintf(outstring,sizeof(outstring),"\nType sizes:\n"); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(char): %d\n",sizeof(char)); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(int): %d\n",sizeof(int)); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(long): %d\n",sizeof(long)); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(uint8): %d\n",sizeof(uint8)); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(uint16): %d\n",sizeof(uint16)); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(uint32): %d\n",sizeof(uint32)); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(short): %d\n",sizeof(short)); - output(screen,outstring); - snprintf(outstring,sizeof(outstring)," sizeof(void*): %d\n",sizeof(void*)); - output(screen,outstring); + output(screen,"\nType sizes:\n"); + output(screen," sizeof(char): %d\n",sizeof(char)); + output(screen," sizeof(int): %d\n",sizeof(int)); + output(screen," sizeof(long): %d\n",sizeof(long)); + output(screen," sizeof(uint8): %d\n",sizeof(uint8)); + output(screen," sizeof(uint16): %d\n",sizeof(uint16)); + output(screen," sizeof(uint32): %d\n",sizeof(uint32)); + output(screen," sizeof(short): %d\n",sizeof(short)); + output(screen," sizeof(void*): %d\n",sizeof(void*)); } -- cgit From cfd68eaac48a29dec245dc6de03aae0d58698862 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 21 Oct 2001 20:51:27 +0000 Subject: Ok, I know it's a language thing and it shouldn't matter.... but a kerberos name is a "principal", not a principle. English majors will complain :-). Jeremy. (This used to be commit b668d7d656cdd066820fb8044f24bcd4fda29524) --- source3/smbd/negprot.c | 8 ++++---- source3/smbd/sesssetup.c | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index dc19e2bdfb..ecc6e7ee51 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -166,7 +166,7 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) const char *OIDs[] = {OID_NTLMSSP, OID_KERBEROS5, NULL}; - char *principle; + char *principal; int len; memset(guid, 0, 16); @@ -175,9 +175,9 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ - asprintf(&principle, "HOST/%s@%s", guid, lp_realm()); - blob = spnego_gen_negTokenInit(guid, OIDs, principle); - free(principle); + asprintf(&principal, "HOST/%s@%s", guid, lp_realm()); + blob = spnego_gen_negTokenInit(guid, OIDs, principal); + free(principal); memcpy(p, blob.data, blob.length); len = blob.length; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7f9a09c79b..003cb0dc3d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -41,7 +41,7 @@ static int reply_spnego_kerberos(connection_struct *conn, int ret; char *realm, *client, *p; fstring hostname; - char *principle; + char *principal; extern pstring global_myname; const struct passwd *pw; char *user; @@ -58,7 +58,7 @@ static int reply_spnego_kerberos(connection_struct *conn, fstrcpy(hostname, global_myname); strlower(hostname); - asprintf(&principle, "HOST/%s@%s", hostname, realm); + asprintf(&principal, "HOST/%s@%s", hostname, realm); ret = krb5_init_context(&context); if (ret) { @@ -66,14 +66,14 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = krb5_parse_name(context, principle, &server); + ret = krb5_parse_name(context, principal, &server); if (ret) { DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", - principle, error_message(ret))); + principal, error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - free(principle); + free(principal); packet.length = ticket.length; packet.data = (krb5_pointer)ticket.data; @@ -96,7 +96,7 @@ static int reply_spnego_kerberos(connection_struct *conn, p = strchr_m(client, '@'); if (!p) { - DEBUG(3,("Doesn't look like a valid principle\n")); + DEBUG(3,("Doesn't look like a valid principal\n")); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -- cgit From fba157123ed1d6f59d40aa9161218fbfcf71253f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 22 Oct 2001 05:04:33 +0000 Subject: - fixed link order of krb5 libs - accept a wide range of principal names in session setup (This used to be commit 672df66296f540b606aa43effab5f021b8978e4b) --- source3/smbd/negprot.c | 1 + source3/smbd/sesssetup.c | 24 +++++------------------- 2 files changed, 6 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index ecc6e7ee51..097cb79e67 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -165,6 +165,7 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) uint8 guid[16]; const char *OIDs[] = {OID_NTLMSSP, OID_KERBEROS5, + OID_KERBEROS5_OLD, NULL}; char *principal; int len; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 003cb0dc3d..fc6c694d9f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -33,16 +33,12 @@ static int reply_spnego_kerberos(connection_struct *conn, { DATA_BLOB ticket; krb5_context context; - krb5_principal server; krb5_auth_context auth_context = NULL; krb5_keytab keytab = NULL; krb5_data packet; krb5_ticket *tkt = NULL; int ret; char *realm, *client, *p; - fstring hostname; - char *principal; - extern pstring global_myname; const struct passwd *pw; char *user; gid_t gid; @@ -56,30 +52,21 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - fstrcpy(hostname, global_myname); - strlower(hostname); - asprintf(&principal, "HOST/%s@%s", hostname, realm); - ret = krb5_init_context(&context); if (ret) { DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = krb5_parse_name(context, principal, &server); - if (ret) { - DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", - principal, error_message(ret))); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - free(principal); - packet.length = ticket.length; packet.data = (krb5_pointer)ticket.data; +#if 0 + file_save("/tmp/ticket.dat", ticket.data, ticket.length); +#endif + if ((ret = krb5_rd_req(context, &auth_context, &packet, - server, keytab, NULL, &tkt))) { + NULL, keytab, NULL, &tkt))) { DEBUG(3,("krb5_rd_req failed (%s)\n", error_message(ret))); return ERROR_NT(NT_STATUS_LOGON_FAILURE); @@ -444,7 +431,6 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha blob1 = data_blob(p, SVAL(inbuf, smb_vwv7)); #if 0 - chdir("/home/tridge"); file_save("negotiate.dat", blob1.data, blob1.length); #endif -- cgit From 4e5eb48b0752aa0a34b9c88b39430efb945e5535 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 22 Oct 2001 06:53:28 +0000 Subject: lets try the new mangling code all the calls go through a compatibility interface will change that soon a new mangle.tdb file will be set in the lock directory it contains a static mapping longname<->manglename (This used to be commit 1ffacd2068a896d36a9e56b6e28c63e2f7e98762) --- source3/smbd/mangle.c | 46 +++++++++++++++++++++++++++++++++++++++------- source3/smbd/server.c | 5 +++++ 2 files changed, 44 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 7139cb7f44..1e00b04b0b 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -113,7 +113,7 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ char magic_char = '~'; -#if 1 +#if 0 @@ -999,7 +999,7 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if 0 +#if 1 #define MANGLE_TDB_VERSION "20010927" #define MANGLE_TDB_FILE_NAME "mangle.tdb" @@ -1451,6 +1451,10 @@ BOOL is_mangled(char *s) size_t u2len; BOOL ret = False; + DEBUG(10,("is_mangled: testing -> [%s]\n", s)); + + if (!s || !*s) return False; + u2len = (strlen(s) + 1) * sizeof(smb_ucs2_t); u2 = (smb_ucs2_t *)malloc(u2len); if (!u2) @@ -1459,11 +1463,12 @@ BOOL is_mangled(char *s) return ret; } dos_to_ucs2(u2, s, u2len); - + res = unmangle(u2); if (res) ret = True; SAFE_FREE(res); SAFE_FREE(u2); + DEBUG(10,("is_mangled: returning -> %s\n", ret?"True":"False")); return ret; } @@ -1471,9 +1476,15 @@ BOOL is_8_3(char *fname, BOOL check_case) { smb_ucs2_t *u2, *pref = 0, *ext = 0; char *s1 = 0, *s2; - size_t u2len; + size_t u2len, plen; BOOL ret = False; + DEBUG(10,("is_8_3: testing -> [%s]\n", fname)); + + if (!fname || !*fname) return False; + + if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) return True; + u2len = (strlen(fname) + 1) * sizeof(smb_ucs2_t); u2 = (smb_ucs2_t *)malloc(u2len); if (!u2) @@ -1492,7 +1503,12 @@ BOOL is_8_3(char *fname, BOOL check_case) if (!mangle_get_prefix(u2, &pref, &ext)) goto done; - if (strlen_w(pref) > 8) goto done; + plen = strlen_w(pref); + if (plen < 1 || plen > 8) goto done; + if (ext) + if (strlen_w(ext) > 3) goto done; + + DEBUG(10,("pref len = %d, ext len = %d\n", pref?strlen_w(pref):0, ext?strlen_w(ext):0)); ucs2_to_dos(s1, u2, u2len); ucs2_to_dos83(s2, u2, u2len); @@ -1505,6 +1521,9 @@ done: SAFE_FREE(s1); SAFE_FREE(pref); SAFE_FREE(ext); + + DEBUG(10,("is_8_3: returning -> %s\n", ret?"True":"False")); + return ret; } void reset_mangled_cache(void) @@ -1519,6 +1538,9 @@ BOOL check_mangled_cache(char *s) BOOL ret = False; DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n")); + DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s)); + + if (!s || !*s) return False; slen = strlen(s); u2len = (slen + 1) * sizeof(smb_ucs2_t); @@ -1533,11 +1555,13 @@ BOOL check_mangled_cache(char *s) res = unmangle(u2); if (res) { - ucs2_to_dos (s, res, slen); /* ugly, but must be done this way */ + ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ + DEBUG(10,("check_mangled_cache: returning -> [%s]\n", s)); ret = True; } SAFE_FREE(res); SAFE_FREE(u2); + DEBUG(10,("check_mangled_cache: returning -> %s\n", ret?"True":"False")); return ret; } @@ -1548,7 +1572,10 @@ void mangle_name_83(char *s) BOOL ret = False; DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n")); + DEBUG(10,("mangle_name_83: testing -> [%s]\n", s)); + if (!s || !*s) return; + slen = strlen(s); u2len = (slen + 1) * sizeof(smb_ucs2_t); u2 = (smb_ucs2_t *)malloc(u2len); @@ -1560,7 +1587,8 @@ void mangle_name_83(char *s) dos_to_ucs2(u2, s, u2len); res = _mangle(u2); - if (res) ucs2_to_dos (s, res, slen); /* ugly, but must be done this way */ + if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ + DEBUG(10,("mangle_name_83: returning -> [%s]\n", res)); SAFE_FREE(res); SAFE_FREE(u2); } @@ -1569,6 +1597,10 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) { DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n")); + /* if (!need83) return True; */ + if (is_8_3(OutName, True)) return True; + /* Warning: we should check for invalid chars in file name and mangle + if invalid chars found --simo*/ mangle_name_83(OutName); return True; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2e0fb1868d..16a092f152 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -844,6 +844,11 @@ static void usage(char *pname) if (!init_oplocks()) { exit(1); } + + /* Setup mangle */ + if (!init_mangle_tdb()) { + exit(1); + } /* Setup change notify */ if (!init_change_notify()) { -- cgit From a443dea5d1f6b63c464711a16fbea87541621394 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Mon, 22 Oct 2001 18:14:42 +0000 Subject: server support for RAP session list function (This used to be commit d42c28fbadf577a23fb8c1da9e1c64a2f34fe133) --- source3/smbd/lanman.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/session.c | 13 ++++++ 2 files changed, 118 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d4d7683855..3150253dab 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3415,6 +3415,110 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, return(True); } +struct session_info { + char machine[31]; + char username[24]; + char clitype[24]; + int opens; + int time; +}; + +struct sessions_info { + int count; + struct session_info *session_list; +}; + +static int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +{ + struct sessions_info *sinfo = state; + struct session_info *curinfo = NULL; + struct sessionid *sessid = (struct sessionid *) dbuf.dptr; + + sinfo->count += 1; + sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info)); + + curinfo = &(sinfo->session_list[sinfo->count - 1]); + + safe_strcpy(curinfo->machine, sessid->remote_machine, + sizeof(curinfo->machine)); + safe_strcpy(curinfo->username, uidtoname(sessid->uid), + sizeof(curinfo->username)); + DEBUG(7,("gather_sessioninfo session from %s@%s\n", + curinfo->username, curinfo->machine)); + return 0; +} + +/**************************************************************************** + List open sessions + ****************************************************************************/ +static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) + +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + struct pack_desc desc; + struct sessions_info sinfo; + int i; + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel)); + DEBUG(7,("RNetSessionEnum req string=%s\n",str1)); + DEBUG(7,("RNetSessionEnum ret string=%s\n",str2)); + + /* check it's a supported varient */ + if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False; + if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False; + + sinfo.count = 0; + sinfo.session_list = NULL; + + if (!session_traverse(gather_sessioninfo, &sinfo)) { + DEBUG(4,("RNetSessionEnum session_traverse failed\n")); + return False; + } + + if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + memset((char *)&desc,'\0',sizeof(desc)); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (!init_package(&desc,sinfo.count,0)) { + return False; + } + + for(i=0; i Date: Mon, 22 Oct 2001 23:25:11 +0000 Subject: ops, some testing code in compat function let only mangled name come back. (This used to be commit e48eb7b572de10481e928fb55243f47e8a3aa446) --- source3/smbd/mangle.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 1e00b04b0b..d68d052978 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1500,14 +1500,13 @@ BOOL is_8_3(char *fname, BOOL check_case) } s2 = s1 + u2len; dos_to_ucs2(u2, fname, u2len); - if (!mangle_get_prefix(u2, &pref, &ext)) goto done; plen = strlen_w(pref); if (plen < 1 || plen > 8) goto done; if (ext) if (strlen_w(ext) > 3) goto done; - + DEBUG(10,("pref len = %d, ext len = %d\n", pref?strlen_w(pref):0, ext?strlen_w(ext):0)); ucs2_to_dos(s1, u2, u2len); @@ -1515,7 +1514,7 @@ BOOL is_8_3(char *fname, BOOL check_case) if (strncmp(s1, s2, u2len)) goto done; else ret = True; - + done: SAFE_FREE(u2); SAFE_FREE(s1); @@ -1536,7 +1535,7 @@ BOOL check_mangled_cache(char *s) smb_ucs2_t *u2, *res; size_t slen, u2len; BOOL ret = False; - + DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n")); DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s)); @@ -1551,7 +1550,7 @@ BOOL check_mangled_cache(char *s) return ret; } dos_to_ucs2(u2, s, u2len); - + res = unmangle(u2); if (res) { @@ -1570,7 +1569,7 @@ void mangle_name_83(char *s) smb_ucs2_t *u2, *res; size_t slen, u2len; BOOL ret = False; - + DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n")); DEBUG(10,("mangle_name_83: testing -> [%s]\n", s)); @@ -1585,7 +1584,7 @@ void mangle_name_83(char *s) return; } dos_to_ucs2(u2, s, u2len); - + res = _mangle(u2); if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ DEBUG(10,("mangle_name_83: returning -> [%s]\n", res)); @@ -1597,10 +1596,11 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) { DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n")); - /* if (!need83) return True; */ - if (is_8_3(OutName, True)) return True; + if (!need83) return True; + /* if (is_8_3(OutName, True)) return True; */ /* Warning: we should check for invalid chars in file name and mangle if invalid chars found --simo*/ + mangle_name_83(OutName); return True; } @@ -1665,7 +1665,7 @@ void mangle_test_code(void) /* unmangle every */ printf("Unmangle test 1:\n"); - + unmangle_test (LONG, NULL); unmangle_test (LONG, EXT1); unmangle_test (LONG, EXT2); @@ -1696,7 +1696,7 @@ void mangle_test_code(void) /* mangle every */ printf("Mangle test\n"); - + mangle_test (LONG, NULL); mangle_test (LONG, EXT1); mangle_test (LONG, EXT2); @@ -1727,7 +1727,7 @@ void mangle_test_code(void) /* unmangle again every */ printf("Unmangle test 2:\n"); - + unmangle_test (LONG, NULL); unmangle_test (LONG, EXT1); unmangle_test (LONG, EXT2); -- cgit From 2a2cccabca40af0d713a4541b4ccba0a3d97496c Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 23 Oct 2001 18:15:18 +0000 Subject: IRIX compiler dies not like casts in macro args (This used to be commit 1b3123df48ca586b3d9c86a152354690836f6beb) --- source3/smbd/oplock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 9d285d4ae3..340a0a3906 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1162,7 +1162,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) } } - SAFE_FREE((char *)share_list); + SAFE_FREE(share_list); unlock_share_entry_fsp(fsp); /* Paranoia check... */ -- cgit From 3ea349271355b39f7b877ce67530cc58e7db0ee8 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 23 Oct 2001 19:10:30 +0000 Subject: get rid of compiler warnings (casts and delete unused variables) (This used to be commit 51cb4411df61d1caec9d84809b1a53a6a632f808) --- source3/smbd/dfree.c | 2 +- source3/smbd/mangle.c | 1 - source3/smbd/negprot.c | 8 ++++---- source3/smbd/sesssetup.c | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 51f0614941..13a3e86c6e 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -121,7 +121,7 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, } else sys_fsusage(path, dfree, dsize); - if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { + if (disk_quotas((char *)path, &bsize_q, &dfree_q, &dsize_q)) { (*bsize) = bsize_q; (*dfree) = MIN(*dfree,dfree_q); (*dsize) = MIN(*dsize,dsize_q); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index d68d052978..40e66061af 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1568,7 +1568,6 @@ void mangle_name_83(char *s) { smb_ucs2_t *u2, *res; size_t slen, u2len; - BOOL ret = False; DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n")); DEBUG(10,("mangle_name_83: testing -> [%s]\n", s)); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 097cb79e67..16d315f1d8 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -129,7 +129,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) generate_next_challenge(cryptkey); } else { memcpy(cryptkey, cli->secblob.data, 8); - set_challenge(cryptkey); + set_challenge((unsigned char *)cryptkey); } } @@ -171,8 +171,8 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) int len; memset(guid, 0, 16); - safe_strcpy(guid, global_myname, 16); - strlower(guid); + safe_strcpy((char *)guid, global_myname, 16); + strlower((char *)guid); /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ @@ -230,7 +230,7 @@ static int reply_nt1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) { if (!cli) { - generate_next_challenge(cryptkey); + generate_next_challenge((char *)cryptkey); } else { memcpy(cryptkey, cli->secblob.data, 8); set_challenge(cryptkey); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index fc6c694d9f..5412cc3bad 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -420,7 +420,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha global_client_caps = IVAL(inbuf,smb_vwv10); } - p = smb_buf(inbuf); + p = (uint8 *)smb_buf(inbuf); if (SVAL(inbuf, smb_vwv7) == 0) { /* an anonymous request */ -- cgit From b8fe0f6711977412f8a7103022b01f3428d9c3a0 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 23 Oct 2001 20:39:38 +0000 Subject: more compiler warnings (This used to be commit 12c10e876ea528fdf33e8ecfe42ab0ebb346b143) --- source3/smbd/auth_rhosts.c | 2 +- source3/smbd/auth_smbpasswd.c | 2 +- source3/smbd/notify_hash.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index cd1bf57f86..d6ca01936f 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -86,7 +86,7 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e static char *mydomain = NULL; if (!mydomain) yp_get_default_domain(&mydomain); - if (mydomain && innetgr(file_host,remote,user,mydomain)) + if (mydomain && innetgr(file_host,(char *)remote,(char *)user,mydomain)) host_ok = True; } #else diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index a525248461..2070f09fd6 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -311,7 +311,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(sampass, user_info, server_info->session_key); + nt_status = sam_password_ok(sampass, user_info, (char *)(server_info->session_key)); if NT_STATUS_IS_OK(nt_status) { nt_status = sam_account_ok(sampass, user_info); diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index b4edc258e9..a8470102d5 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -116,7 +116,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_FILE)) { int i; unsigned char tmp_hash[16]; - mdfour(tmp_hash, fname, strlen(fname)); + mdfour(tmp_hash, (const unsigned char *)fname, strlen(fname)); for (i=0;i<16;i++) data->name_hash[i] ^= tmp_hash[i]; } -- cgit From fb328c9cc4d12997b7f8059ebe163482a16df77b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 24 Oct 2001 00:35:55 +0000 Subject: Made default vfs ops static so we can use this symbol in actual modules. (This used to be commit 398ced6eef7e52441ddc59fef70e4a50a96a73b7) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7a3d23d652..02a78c4cd3 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -32,7 +32,7 @@ struct vfs_syminfo { very important. They must be in the same order as defined in vfs.h. Change at your own peril. */ -struct vfs_ops default_vfs_ops = { +static struct vfs_ops default_vfs_ops = { /* Disk operations */ -- cgit From a9cf7fb2da28ad09702fda30486ae9698b2df21c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 26 Oct 2001 22:58:32 +0000 Subject: Fixed compile warning. (This used to be commit 320c21b7a9e0a914b8a9523775df8895cb41256f) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 40e66061af..01297c89a7 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1586,7 +1586,7 @@ void mangle_name_83(char *s) res = _mangle(u2); if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ - DEBUG(10,("mangle_name_83: returning -> [%s]\n", res)); + DEBUG(10,("mangle_name_83: returning -> [%s]\n", res?"True":"False")); SAFE_FREE(res); SAFE_FREE(u2); } -- cgit From b947ad3a491b6ad2c8aebd8604dee056ac874435 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 27 Oct 2001 07:17:21 +0000 Subject: smbd/notify_hash.c: Merged Herb's fix. lib/debug.c: Fix for potential null pointer access. Jeremy. (This used to be commit 5a4d22dd66ab782f6161aa5a4162c0e7f1d811fb) --- source3/smbd/notify_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index a8470102d5..178dcecc82 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -116,7 +116,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_FILE)) { int i; unsigned char tmp_hash[16]; - mdfour(tmp_hash, (const unsigned char *)fname, strlen(fname)); + mdfour(tmp_hash, (unsigned char *)fname, strlen(fname)); for (i=0;i<16;i++) data->name_hash[i] ^= tmp_hash[i]; } @@ -195,7 +195,7 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, static void hash_remove_notify(void *datap) { - SAFE_FREE(datap); + free(datap); } /**************************************************************************** -- cgit From 7433cb7c75591429cb6dcbe6fc50248d6dbfb359 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 28 Oct 2001 19:19:57 +0000 Subject: fix a logic bug on max size of a returned string, this fixes also the bug with file renaming. (This used to be commit 5246d7609c3aff658fcd08a1f1c1bb6e11509e35) --- source3/smbd/mangle.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 01297c89a7..d9843f2b42 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1055,7 +1055,7 @@ static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len) dest_len = sizeof(pstring); } - src_len = strlen_w(src) * sizeof(smb_ucs2_t); + src_len = strlen_w(src)* sizeof(smb_ucs2_t); ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len); if (dest_len) dest[MIN(ret, dest_len-1)] = 0; @@ -1554,7 +1554,13 @@ BOOL check_mangled_cache(char *s) res = unmangle(u2); if (res) { - ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ + + ucs2_to_dos (s, res, (strlen_w(res) * 2)); + /* We MUST change this brainded interface, + we do not know how many chars will be used + in dos so i guess they will be no more than + double the size of the unicode string + ---simo */ DEBUG(10,("check_mangled_cache: returning -> [%s]\n", s)); ret = True; } @@ -1586,7 +1592,7 @@ void mangle_name_83(char *s) res = _mangle(u2); if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ - DEBUG(10,("mangle_name_83: returning -> [%s]\n", res?"True":"False")); + DEBUG(10,("mangle_name_83: returning -> [%s]\n", s)); SAFE_FREE(res); SAFE_FREE(u2); } -- cgit From 67dae09cc6b124662aa514df06dd89492382e15f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Oct 2001 03:46:09 +0000 Subject: Fixed confusing debug message - it was always printing uid 0 instead of the correct uid. (This used to be commit ad30a35ebc04f6a56c3ffb28bfb793557cf1fdf7) --- source3/smbd/sec_ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index cea39b82cb..fd69521d4e 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -159,7 +159,7 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups) (*p_ngroups) = ngroups; (*p_groups) = groups; - DEBUG( 3, ( "get_current_groups: uid %u is in %u groups: ", (unsigned int)getuid() , ngroups ) ); + DEBUG( 3, ( "get_current_groups: user is in %u groups: ", ngroups)); for (i = 0; i < ngroups; i++ ) { DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) ); } -- cgit From ab5d5cfbe0aee4387ec7ae8805c69b31a1696435 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 29 Oct 2001 07:15:51 +0000 Subject: This commit is number 1 of 4. In particular this commit focusses on: Adding the new 'pass changed now' helper function. While these changes have been mildly tested, and are pretty small, any assistance in this is appreciated. (This used to be commit a8971a5448cf6d203b379c3ed01e331d5263c9ee) --- source3/smbd/chgpasswd.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d2ee2f46fa..49f87a4ca1 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -682,6 +682,12 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, return False; /* We lose the NT hash. Sorry. */ } + if (!pdb_set_pass_changed_now (sampass)) { + pdb_free_sam(&sampass); + /* Not quite sure what this one qualifies as, but this will do */ + return False; + } + /* Now flush the sam_passwd struct to persistent storage */ become_root(); ret = pdb_update_sam_account (sampass, False); -- cgit From 2038649e51f48a489aeec49947e1b791f0b3df43 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 29 Oct 2001 07:28:32 +0000 Subject: This commit is number 3 of 4. In particular this commit focuses on: Changing the Get_Pwnam code so that it can work in a const-enforced environment. While these changes have been mildly tested, and are pretty small, any assistance in this is appreciated. ---- These changes allow for 'const' in the Samba tree. There are a number of good reasons to do this: - I want to allow the SAM_ACCOUNT structure to move from wasteful pstrings and fstrings to allocated strings. We can't do that if people are modifying these outputs, as they may well make assumptions about getting pstrings and fstrings - I want --with-pam_smbpass to compile with a slightly sane volume of warnings, currently its pretty bad, even in 2.2 where is compiles at all. - Tridge assures me that he no longer opposes 'const religion' based on the ability to #define const the problem away. - Changed Get_Pwnam(x,y) into two variants (so that the const parameter can work correctly): - Get_Pwnam(const x) and Get_Pwnam_Modify(x). - Reworked smbd/chgpasswd.c to work with these mods, passing around a 'struct passwd' rather than the modified username (This used to be commit e7634f81c5116ff4addfb7e495f54b6bb78e8f77) --- source3/smbd/auth_rhosts.c | 4 ++-- source3/smbd/auth_unix.c | 2 +- source3/smbd/chgpasswd.c | 58 ++++++++++++++++++++++++++++++++-------------- source3/smbd/lanman.c | 4 ++-- source3/smbd/password.c | 4 ++-- source3/smbd/service.c | 2 +- source3/smbd/uid.c | 2 +- 7 files changed, 49 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index d6ca01936f..9f5f1e10e5 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -86,7 +86,7 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e static char *mydomain = NULL; if (!mydomain) yp_get_default_domain(&mydomain); - if (mydomain && innetgr(file_host,(char *)remote,(char *)user,mydomain)) + if (mydomain && innetgr(file_host,remote,user,mydomain)) host_ok = True; } #else @@ -135,7 +135,7 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */ { char *fname = NULL; pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user,False); + struct passwd *pass = Get_Pwnam(user); if (!pass) return(False); diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 2f9034e3e5..29a2a6eafb 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -89,7 +89,7 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve become_root(); - pass = Get_Pwnam(user_info->unix_username.str, False); + pass = Get_Pwnam(user_info->unix_username.str); nt_status = pass_check(pass, pass ? pass->pw_name : user_info->unix_username.str, diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 49f87a4ca1..132a20cf05 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -118,20 +118,18 @@ static int findpty(char **slave) return (-1); } -static int dochild(int master, char *slavedev, char *name, - char *passwordprogram, BOOL as_root) +static int dochild(int master, const char *slavedev, const struct passwd *pass, + const char *passwordprogram, BOOL as_root) { int slave; struct termios stermios; - struct passwd *pass = Get_Pwnam(name, True); gid_t gid; uid_t uid; if (pass == NULL) { DEBUG(0, - ("dochild: user name %s doesn't exist in the UNIX password database.\n", - name)); + ("dochild: user doesn't exist in the UNIX password database.\n")); return False; } @@ -318,7 +316,7 @@ static int talktochild(int master, char *seq) return (count > 0); } -static BOOL chat_with_program(char *passwordprogram, char *name, +static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, char *chatsequence, BOOL as_root) { char *slavedev; @@ -327,12 +325,19 @@ static BOOL chat_with_program(char *passwordprogram, char *name, int wstat; BOOL chstat = False; + if (pass == NULL) + { + DEBUG(0, + ("chat_with_program: user doesn't exist in the UNIX password database.\n")); + return False; + } + /* allocate a pseudo-terminal device */ if ((master = findpty(&slavedev)) < 0) { DEBUG(3, ("Cannot Allocate pty for password change: %s\n", - name)); + pass->pw_name)); return (False); } @@ -347,7 +352,7 @@ static BOOL chat_with_program(char *passwordprogram, char *name, { DEBUG(3, ("Cannot fork() child for password change: %s\n", - name)); + pass->pw_name)); close(master); CatchChild(); return (False); @@ -360,7 +365,7 @@ static BOOL chat_with_program(char *passwordprogram, char *name, { DEBUG(3, ("Child failed to change password: %s\n", - name)); + pass->pw_name)); kill(pid, SIGKILL); /* be sure to end this process */ } @@ -426,10 +431,10 @@ static BOOL chat_with_program(char *passwordprogram, char *name, become_root(); DEBUG(3, - ("Dochild for user %s (uid=%d,gid=%d)\n", name, + ("Dochild for user %s (uid=%d,gid=%d)\n", pass->pw_name, (int)getuid(), (int)getgid())); chstat = - dochild(master, slavedev, name, passwordprogram, + dochild(master, slavedev, pass, passwordprogram, as_root); if (as_root) @@ -448,19 +453,20 @@ static BOOL chat_with_program(char *passwordprogram, char *name, if (chstat) DEBUG(3, ("Password change %ssuccessful for user %s\n", - (chstat ? "" : "un"), name)); + (chstat ? "" : "un"), pass->pw_name)); return (chstat); } -BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; size_t i; size_t len; - strlower(name); + struct passwd *pass; + DEBUG(3, ("Password change for user: %s\n", name)); #if DEBUG_PASSWORD @@ -505,6 +511,8 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) return False; } } + + pass = Get_Pwnam(name); #ifdef WITH_PAM if (lp_pam_password_change()) { @@ -513,8 +521,12 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) if (as_root) become_root(); - ret = smb_pam_passchange(name, oldpass, newpass); - + if (pass) { + ret = smb_pam_passchange(pass->pw_name, oldpass, newpass); + } else { + ret = smb_pam_passchange(name, oldpass, newpass); + } + if (as_root) unbecome_root(); @@ -522,6 +534,16 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) } #endif + /* A non-PAM password change just doen't make sense without a valid local user */ + + if (pass == NULL) + { + DEBUG(0, + ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", + name)); + return False; + } + pstrcpy(passwordprogram, lp_passwd_program()); pstrcpy(chatsequence, lp_passwd_chat()); @@ -553,12 +575,12 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring)); all_string_sub(chatsequence, "%n", newpass, sizeof(pstring)); return (chat_with_program - (passwordprogram, name, chatsequence, as_root)); + (passwordprogram, pass, chatsequence, as_root)); } #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { DEBUG(0, ("Password changing not compiled in (user=%s)\n", name)); return (False); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3150253dab..7ade1e6d47 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1954,7 +1954,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param /* * Do any UNIX username case mangling. */ - passwd = Get_Pwnam( user, True); + passwd = Get_Pwnam_Modify( user ); /* * Attempt to verify the old password against smbpasswd entries @@ -2082,7 +2082,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * /* * Do any UNIX username case mangling. */ - (void)Get_Pwnam( user, True); + (void)Get_Pwnam_Modify( user ); if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b1739d9bb6..e8f40f1fa3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -276,7 +276,7 @@ void add_session_user(char *user) fstring suser; StrnCpy(suser,user,sizeof(suser)-1); - if (!Get_Pwnam(suser,True)) return; + if (!Get_Pwnam_Modify(suser)) return; if (suser && *suser && !in_list(suser,session_users,False)) { @@ -551,7 +551,7 @@ and given password ok (%s)\n", user)); if (!ok && GUEST_OK(snum)) { fstring guestname; StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); - if (Get_Pwnam(guestname,True)) { + if (Get_Pwnam(guestname)) { fstrcpy(user,guestname); ok = True; DEBUG(3,("authorise_login: ACCEPTED: guest account and guest ok (%s)\n", diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a871192ad5..37f4610b9d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -450,7 +450,7 @@ connection_struct *make_connection(char *service,char *password, /* Allow %S to be used by force user. */ pstring_sub(fuser,"%S",service); - pass2 = (struct passwd *)Get_Pwnam(fuser,True); + pass2 = (struct passwd *)Get_Pwnam_Modify(fuser); if (pass2) { conn->uid = pass2->pw_uid; conn->gid = pass2->pw_gid; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 2151068de5..ae287cca76 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -36,7 +36,7 @@ BOOL change_to_guest(void) static fstring guest_name; if (!pass) { - pass = Get_Pwnam(lp_guestaccount(-1),True); + pass = Get_Pwnam(lp_guestaccount(-1)); if (!pass) return(False); guest_uid = pass->pw_uid; -- cgit From d9d7f023d8d11943ca0375e1573e6ec9921889bc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 29 Oct 2001 07:35:11 +0000 Subject: This commit is number 4 of 4. In particular this commit focuses on: Actually adding the 'const' to the passdb interface, and the flow-on changes. Also kill off the 'disp_info' stuff, as its no longer used. While these changes have been mildly tested, and are pretty small, any assistance in this is appreciated. ---- These changes introduces a large dose of 'const' to the Samba tree. There are a number of good reasons to do this: - I want to allow the SAM_ACCOUNT structure to move from wasteful pstrings and fstrings to allocated strings. We can't do that if people are modifying these outputs, as they may well make assumptions about getting pstrings and fstrings - I want --with-pam_smbpass to compile with a slightly sane volume of warnings, currently its pretty bad, even in 2.2 where is compiles at all. - Tridge assures me that he no longer opposes 'const religion' based on the ability to #define const the problem away. - Changed Get_Pwnam(x,y) into two variants (so that the const parameter can work correctly): - Get_Pwnam(const x) and Get_Pwnam_Modify(x). - Reworked smbd/chgpasswd.c to work with these mods, passing around a 'struct passwd' rather than the modified username --- This finishes this line of commits off, your tree should now compile again :-) Andrew Bartlett (This used to be commit c95f5aeb9327347674589ae313b75bee3bf8e317) --- source3/smbd/auth_smbpasswd.c | 6 +++--- source3/smbd/chgpasswd.c | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 2070f09fd6..6bc3793666 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -65,8 +65,8 @@ static BOOL smb_pwd_check_ntlmv1(const uchar *password, core of smb password checking routine. ****************************************************************************/ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, - uchar *part_passwd, - uchar const *c8, + const uchar *part_passwd, + const uchar *c8, const char *user, const char *domain, char user_sess_key[16]) { @@ -109,7 +109,7 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, ****************************************************************************/ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, char user_sess_key[16]) { - uint8 *nt_pw, *lm_pw; + const uint8 *nt_pw, *lm_pw; uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); if (!user_info || !sampass) diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 132a20cf05..286c316b93 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -51,9 +51,9 @@ extern struct passdb_ops pdb_ops; -static BOOL check_oem_password(char *user, - uchar * lmdata, uchar * lmhash, - uchar * ntdata, uchar * nthash, +static BOOL check_oem_password(const char *user, + uchar * lmdata, const uchar * lmhash, + const uchar * ntdata, const uchar * nthash, SAM_ACCOUNT **hnd, char *new_passwd, int new_passwd_size); @@ -598,7 +598,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, uchar unenc_old_pw[16]; SAM_ACCOUNT *sampass = NULL; uint16 acct_ctrl; - uint8 *lanman_pw; + const uint8 *lanman_pw; BOOL ret; become_root(); @@ -663,7 +663,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, uchar unenc_new_pw[16]; BOOL ret; uint16 acct_ctrl; - uint8 *pwd; + const uint8 *pwd; if (sampass == NULL) { DEBUG(0,("change_lanman_password: no smb password entry.\n")); @@ -759,16 +759,16 @@ BOOL pass_oem_change(char *user, but does use the lm OEM password to check the nt hashed-hash. ************************************************************/ -static BOOL check_oem_password(char *user, - uchar * lmdata, uchar * lmhash, - uchar * ntdata, uchar * nthash, +static BOOL check_oem_password(const char *user, + uchar * lmdata, const uchar * lmhash, + const uchar * ntdata, const uchar * nthash, SAM_ACCOUNT **hnd, char *new_passwd, int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; SAM_ACCOUNT *sampass = NULL; - uint8 *lanman_pw, *nt_pw; + const uint8 *lanman_pw, *nt_pw; uint16 acct_ctrl; int new_pw_len; uchar new_ntp16[16]; @@ -827,7 +827,7 @@ static BOOL check_oem_password(char *user, /* * Call the hash function to get the new password. */ - SamOEMhash((uchar *) lmdata, (uchar *)lanman_pw, 516); + SamOEMhash( lmdata, lanman_pw, 516); /* * The length of the new password is in the last 4 bytes of -- cgit From f93a8a3f9069b8cfbb9f3e751017961f06436c63 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 29 Oct 2001 11:37:42 +0000 Subject: - fix string len for an ucs2_to_dos function as any ucs2 char may be up to 4 dos hars... - addedd ascii compatibility functions (This used to be commit 8b9302b7078f1dd5459051500ed19a696dc09ae0) --- source3/smbd/mangle.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index d9843f2b42..5c737ea656 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1206,7 +1206,7 @@ done: /* unmangled must contain only the file name, not a path. and MUST be ZERO terminated */ -smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) +smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) { TDB_DATA data, key, klock; pstring keystr; @@ -1441,6 +1441,83 @@ done: } +/* non unicode compatibility functions */ + +char *dos_mangle(char *dos_unmangled) +{ + smb_ucs2_t *in, *out; + char *dos_mangled; + size_t len; + + if (!dos_unmangled || !*dos_unmangled) return NULL; + + len = (strlen(dos_unmangled) + 1) * sizeof(smb_ucs2_t); + in = (smb_ucs2_t *)malloc(len); + if (!in) + { + DEBUG(0,("dos_mangle: out of memory!\n")); + return NULL; + } + dos_to_ucs2(in, dos_unmangled, len); + + out = mangle(in); + if (!out) + { + SAFE_FREE(in); + return NULL; + } + + dos_mangled = (char *)malloc(PSTRING_LEN); + if (!dos_mangled) + { + DEBUG(0,("dos_mangle: out of memory!\n")); + goto done; + } + ucs2_to_dos (dos_mangled, out, PSTRING_LEN); + +done: + SAFE_FREE(in); + SAFE_FREE(out); + return dos_mangled; +} + +char *dos_unmangle(char *dos_mangled) +{ + smb_ucs2_t *in, *out; + char *dos_unmangled; + size_t len; + + if (!dos_mangled || !*dos_mangled) return NULL; + + len = (strlen(dos_mangled) + 1) * sizeof(smb_ucs2_t); + in = (smb_ucs2_t *)malloc(len); + if (!in) + { + DEBUG(0,("dos_unmangle: out of memory!\n")); + return NULL; + } + dos_to_ucs2(in, dos_mangled, len); + + out = mangle(in); + if (!out) + { + SAFE_FREE(in); + return NULL; + } + + dos_unmangled = (char *)malloc(PSTRING_LEN); + if (!dos_unmangled) + { + DEBUG(0,("dos_unmangle: out of memory!\n")); + goto done; + } + ucs2_to_dos (dos_unmangled, out, PSTRING_LEN); + +done: + SAFE_FREE(in); + SAFE_FREE(out); + return dos_unmangled; +} /* backward compatibility functions */ @@ -1555,7 +1632,7 @@ BOOL check_mangled_cache(char *s) if (res) { - ucs2_to_dos (s, res, (strlen_w(res) * 2)); + ucs2_to_dos (s, res, PSTRING_LEN); /* We MUST change this brainded interface, we do not know how many chars will be used in dos so i guess they will be no more than @@ -1590,7 +1667,7 @@ void mangle_name_83(char *s) } dos_to_ucs2(u2, s, u2len); - res = _mangle(u2); + res = mangle(u2); if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ DEBUG(10,("mangle_name_83: returning -> [%s]\n", s)); SAFE_FREE(res); @@ -1656,7 +1733,7 @@ static void mangle_test (char *name, char *ext) strncat_wa(ucs2_name, ".", 1); strncat_wa(ucs2_name, ext, strlen(ext) + 1); } - retstr = _mangle(ucs2_name); + retstr = mangle(ucs2_name); if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE); else unix_name[0] = 0; if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name); -- cgit From 95aa4c6bbe99f7883bbe3a08e0072685dc04c091 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 29 Oct 2001 13:19:22 +0000 Subject: change some more functions to the new mangle interface. (This used to be commit 06a7c28ea1be81c4a53f9a5b885c37fdde31f75c) --- source3/smbd/filename.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5fdbef44fe..d1c512c251 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -76,15 +76,17 @@ static BOOL fname_equal(char *name1, char *name2) ****************************************************************************/ static BOOL mangled_equal(char *name1, char *name2) { - pstring tmpname; - - if (is_8_3(name2, True)) - return(False); - - pstrcpy(tmpname,name2); - mangle_name_83(tmpname); - - return(strequal(name1,tmpname)); + char *tmpname; + BOOL ret = False; + + if (is_8_3(name2, True)) + { + tmpname = dos_mangle(name2); + if(tmpname) + ret = strequal(name1,tmpname); + SAFE_FREE(tmpname); + } + return ret; } -- cgit From a972d2c448d0c54c0cf0319c1a0ef5fec27b68d6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 29 Oct 2001 13:21:29 +0000 Subject: another few changes to the new mangle code (This used to be commit 92f953c156a39b54230c52c6102a319a4a5ca798) --- source3/smbd/reply.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 852a2d867b..ca7bcb9c5f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3000,8 +3000,20 @@ NTSTATUS rename_internals(connection_struct *conn, * Tine Smukavec . */ +#if 0 if (!rc && is_mangled(mask)) check_mangled_cache( mask ); +#endif + if (!rc) + { + char *unmangled; + + unmangled = dos_unmangle(mask); + if (unmangled) + strncpy(mask, unmangled, strlen(unmangled) + 1); + + SAFE_FREE(unmangled); + } has_wild = ms_has_wild(mask); @@ -3350,8 +3362,21 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec . */ - if (!rc && is_mangled(mask)) - check_mangled_cache( mask ); +#if 0 + if (!rc && is_mangled(mask)) + check_mangled_cache( mask ); +#endif + if (!rc) + { + char *unmangled; + + unmangled = dos_unmangle(mask); + if (unmangled) + strncpy(mask, unmangled, strlen(unmangled) + 1); + + SAFE_FREE(unmangled); + } + has_wild = ms_has_wild(mask); -- cgit From 11dc29786ed7844440827aca6a07901ebcb56157 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 29 Oct 2001 22:28:21 +0000 Subject: Fix up auth_smbpasswd.c to use the password interface, rather than the structures directly. Andrew Bartlett (This used to be commit c2dc24ab6370236437b72b929e2a56e174163d78) --- source3/smbd/auth_smbpasswd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 6bc3793666..84ca8d03be 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -202,11 +202,11 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user if (!user_info || !sampass) return NT_STATUS_LOGON_FAILURE; - DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",sampass->username)); + DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",pdb_get_username(sampass))); /* Quit if the account was disabled. */ if (acct_ctrl & ACB_DISABLED) { - DEBUG(1,("Account for user '%s' was disabled.\n", sampass->username)); + DEBUG(1,("Account for user '%s' was disabled.\n", pdb_get_username(sampass))); return NT_STATUS_ACCOUNT_DISABLED; } @@ -214,7 +214,7 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user kickoff_time = pdb_get_kickoff_time(sampass); if (kickoff_time != 0 && time(NULL) > kickoff_time) { - DEBUG(1,("Account for user '%s' has expried.\n", sampass->username)); + DEBUG(1,("Account for user '%s' has expried.\n", pdb_get_username(sampass))); DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); return NT_STATUS_ACCOUNT_EXPIRED; } @@ -253,30 +253,30 @@ NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user /* check for immediate expiry "must change at next logon" */ if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", sampass->username)); + DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password */ if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", sampass->username)); + DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); return NT_STATUS_PASSWORD_EXPIRED; } } if (acct_ctrl & ACB_DOMTRUST) { - DEBUG(2,("session_trust_account: Domain trust account %s denied by server\n", sampass->username)); + DEBUG(2,("session_trust_account: Domain trust account %s denied by server\n", pdb_get_username(sampass))); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } if (acct_ctrl & ACB_SVRTRUST) { - DEBUG(2,("session_trust_account: Server trust account %s denied by server\n", sampass->username)); + DEBUG(2,("session_trust_account: Server trust account %s denied by server\n", pdb_get_username(sampass))); return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } if (acct_ctrl & ACB_WSTRUST) { - DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", sampass->username)); + DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", pdb_get_username(sampass))); return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } -- cgit From 1f829e19eb3b81ad1c4451fe9a90617e6cee7dd7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 30 Oct 2001 13:54:54 +0000 Subject: Spnego on the 'server' end of security=server just does not work, so set the flags so we just do a 'normal' session setup. Also add some parinoia code to detect when sombody attempts to do a 'normal' session setup when spnego had been negoitiated. Andrew Bartlett (This used to be commit 190898586fa218c952fbd5bea56155d04e6f248b) --- source3/smbd/auth_server.c | 3 +++ source3/smbd/negprot.c | 5 ++++- source3/smbd/sesssetup.c | 8 +++++++- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index 2574a52ef3..520417e3e0 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -51,6 +51,9 @@ struct cli_state *server_cryptkey(void) if (!cli_initialise(cli)) return NULL; + /* security = server just can't function with spnego */ + cli->use_spnego = False; + pserver = strdup(lp_passwordserver()); p = pserver; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 16d315f1d8..e4285cb27c 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -25,7 +25,8 @@ extern int Protocol; extern int max_recv; extern fstring global_myworkgroup; extern fstring remote_machine; -BOOL global_encrypted_passwords_negotiated; +BOOL global_encrypted_passwords_negotiated = False; +BOOL global_spnego_negotiated = False; /**************************************************************************** reply for the core protocol @@ -170,6 +171,8 @@ static int negprot_spnego(char *p, uint8 cryptkey[8]) char *principal; int len; + global_spnego_negotiated = True; + memset(guid, 0, 16); safe_strcpy((char *)guid, global_myname, 16); strlower((char *)guid); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 5412cc3bad..2d9f624b80 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -480,6 +480,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, BOOL guest=False; static BOOL done_sesssetup = False; extern BOOL global_encrypted_passwords_negotiated; + extern BOOL global_spnego_negotiated; extern uint32 global_client_caps; extern int Protocol; extern fstring remote_machine; @@ -492,11 +493,16 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* a SPNEGO session setup has 12 command words, whereas a normal NT1 session setup has 13. See the cifs spec. */ - if (CVAL(inbuf, smb_wct) == 12 && + if (CVAL(inbuf, smb_wct) == 12 && (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } + if (global_spnego_negotiated) { + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } + *smb_apasswd = *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); -- cgit From 6f0b8a38ec036a0027e9f938834e241b41db40c5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 31 Oct 2001 06:20:58 +0000 Subject: Added some extra fields to the auth_serversupplied_info structure. To obtain the full group membership of a user (i.e nested groups on a win2k native mode server) it is necessary to merge this list of groups with the groups returned by winbindd when creating an nt access token. This breaks winbindd linking while AB and I sync up our changes to the authentication subsystem. (This used to be commit 4eeb7bcd783d7cfb3ac232f1faa035773007401d) --- source3/smbd/auth.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index e76324213e..4bdbdf5555 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -129,6 +129,7 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, auth_serversupplied_info server_info; AUTH_STR ourdomain, theirdomain, unix_username, smb_username, wksta_name; + NTSTATUS result; ZERO_STRUCT(user_info); ZERO_STRUCT(ourdomain); @@ -203,7 +204,11 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, } - return check_password(&user_info, &server_info); + result = check_password(&user_info, &server_info); + + free_serversupplied_info(&server_info); /* No info needed */ + + return result; } NTSTATUS pass_check_smb(char *smb_user, char *unix_user, @@ -255,3 +260,10 @@ BOOL password_ok(char *user, char *password, int pwlen) return False; } + +/* Free a auth_serversupplied_info structure */ + +void free_serversupplied_info(auth_serversupplied_info *server_info) +{ + SAFE_FREE(server_info->group_rids); +} -- cgit From d8f0f3a6d4c6fedf5cad364afb33d9cb92bc1336 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 31 Oct 2001 06:24:25 +0000 Subject: SPNEGO works perfectly well with security=domain, so don't exclude it. (This used to be commit 26a9479ad450a5135e54b45d659bf3558892d9e6) --- source3/smbd/negprot.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e4285cb27c..045e16a9bb 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -159,7 +159,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) /* generate the spnego negprot reply blob. Return the number of bytes used */ -static int negprot_spnego(char *p, uint8 cryptkey[8]) +static int negprot_spnego(char *p) { DATA_BLOB blob; extern pstring global_myname; @@ -217,7 +217,8 @@ static int reply_nt1(char *inbuf, char *outbuf) /* do spnego in user level security if the client supports it and we can do encrypted passwords */ if (global_encrypted_passwords_negotiated && - lp_security() == SEC_USER && + (lp_security() == SEC_USER || + lp_security() == SEC_DOMAIN) && (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { negotiate_spnego = True; capabilities |= CAP_EXTENDED_SECURITY; @@ -285,10 +286,13 @@ static int reply_nt1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8); SSVALS(outbuf,smb_vwv16+1,8); p += 8; + DEBUG(3,("not using SPNEGO\n")); } else { - int len = negprot_spnego(p, cryptkey); + int len = negprot_spnego(p); + SSVALS(outbuf,smb_vwv16+1,len); p += len; + DEBUG(3,("using SPNEGO\n")); } p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); -- cgit From 60f0627afb167faad57385d44f0b587186a7ac2b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 31 Oct 2001 10:46:25 +0000 Subject: This is a farily large patch (3300 lines) and reworks most of the AuthRewrite code. In particular this assists tpot in some of his work, becouse it provides the connection between the authenticaion and the vuid generation. Major Changes: - Fully malloc'ed structures. - Massive rework of the code so that all structures are made and destroyed using malloc and free, rather than hanging around on the stack. - SAM_ACCOUNT unix uids and gids are now pointers to the same, to allow them to be declared 'invalid' without the chance that people might get ROOT by default. - kill off some of the "DOMAIN\user" lookups. These can be readded at a more appropriate place (probably domain_client_validate.c) in the future. They don't belong in session setups. - Massive introduction of DATA_BLOB structures, particularly for passwords. - Use NTLMSSP flags to tell the backend what its getting, rather than magic lenghths. - Fix winbind back up again, but tpot is redoing this soon anyway. - Abstract much of the work in srv_netlog_nt back into auth helper functions. This is a LARGE change, and any assistance is testing it is appriciated. Domain logons are still broken (as far as I can tell) but other functionality seems intact. Needs testing with a wide variety of MS clients. Andrew Bartlett (This used to be commit f70fb819b2f57bd57232b51808345e2319d52f6c) --- source3/smbd/auth.c | 263 +++++++++----------- source3/smbd/auth_domain.c | 2 +- source3/smbd/auth_rhosts.c | 40 +-- source3/smbd/auth_server.c | 27 +- source3/smbd/auth_smbpasswd.c | 228 +++++++++++------ source3/smbd/auth_unix.c | 17 +- source3/smbd/auth_util.c | 564 ++++++++++++++++++++++++++++++++++++++++-- source3/smbd/password.c | 51 ++-- source3/smbd/reply.c | 37 +-- source3/smbd/service.c | 12 +- source3/smbd/sesssetup.c | 356 ++++++++++++-------------- 11 files changed, 1086 insertions(+), 511 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 4bdbdf5555..4d1a566833 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -50,183 +50,160 @@ static BOOL check_domain_match(char *user, char *domain) This functions does NOT need to be in a become_root()/unbecome_root() pair as it makes the calls itself when needed. + + The return value takes precedence over the contents of the server_info + struct. When the return is other than NT_STATUS_NOPROBLEMO the contents + of that structure is undefined. + ****************************************************************************/ NTSTATUS check_password(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; - - DEBUG(3, ("check_password: Checking password for smb user %s\\%s@%s with the new password interface\n", - user_info->smb_username.str, user_info->requested_domain.str, user_info->wksta_name.str)); - if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { + + DEBUG(3, ("check_password: Checking password for unmapped user %s\\%s@%s with the new password interface\n", + user_info->smb_name.str, user_info->client_domain.str, user_info->wksta_name.str)); + + /* This needs to be sorted: If it doesn't match, what should we do? */ + if (!check_domain_match(user_info->smb_name.str, user_info->domain.str)) { return NT_STATUS_LOGON_FAILURE; } if (!NT_STATUS_IS_OK(nt_status)) { nt_status = check_rhosts_security(user_info, server_info); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (rhosts) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (rhosts)for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_domain_security(user_info, server_info); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (domain) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (domain) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_server_security(user_info, server_info); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (server) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (server) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } if (lp_security() >= SEC_SERVER) { - smb_user_control(user_info->unix_username.str, nt_status); + smb_user_control(user_info, *server_info, nt_status); } if (!NT_STATUS_IS_OK(nt_status)) { - if ((user_info->plaintext_password.len > 0) - && (!lp_plaintext_to_smbpasswd())) { + if (user_info->encrypted || lp_plaintext_to_smbpasswd()) { + nt_status = check_smbpasswd_security(user_info, server_info); + } else { nt_status = check_unix_security(user_info, server_info); done_pam = True; - } else { - nt_status = check_smbpasswd_security(user_info, server_info); } + + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (unix/smbpasswd) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (unix/smbpasswd) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } + if (NT_STATUS_IS_OK(nt_status) && !done_pam) { /* We might not be root if we are an RPC call */ become_root(); - nt_status = smb_pam_accountcheck(user_info->unix_username.str); + nt_status = smb_pam_accountcheck(pdb_get_username((*server_info)->sam_account)); unbecome_root(); - } + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(5, ("check_password: PAM Account for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(3, ("check_password: PAM Account for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } + } + if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_username.str)); + DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_name.str)); } else { - DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status))); - + DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + ZERO_STRUCTP(server_info); } + return nt_status; } /**************************************************************************** - COMPATABILITY INTERFACES: - ***************************************************************************/ - -/**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash -return True if the password is correct, False otherwise + Squash an NT_STATUS return in line with requirements for unauthenticated + connections. (session setups in particular) ****************************************************************************/ -NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, - char *domain, char* workstation, - uchar chal[8], - uchar *lm_pwd, int lm_pwd_len, - uchar *nt_pwd, int nt_pwd_len) +NTSTATUS nt_status_squash(NTSTATUS nt_status) { - - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR ourdomain, theirdomain, unix_username, smb_username, - wksta_name; - NTSTATUS result; + if NT_STATUS_IS_OK(nt_status) { + return nt_status; + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + /* Match WinXP and don't give the game away */ + return NT_STATUS_LOGON_FAILURE; - ZERO_STRUCT(user_info); - ZERO_STRUCT(ourdomain); - ZERO_STRUCT(theirdomain); - ZERO_STRUCT(smb_username); - ZERO_STRUCT(wksta_name); - - ourdomain.str = lp_workgroup(); - ourdomain.len = strlen(ourdomain.str); - - theirdomain.str = domain; - theirdomain.len = strlen(theirdomain.str); - - user_info.requested_domain = theirdomain; - user_info.domain = ourdomain; - - smb_username.str = smb_user; - smb_username.len = strlen(smb_username.str); - - /* If unix user is NULL, use smb user */ - - unix_username.str = unix_user ? unix_user : smb_user; - unix_username.len = strlen(unix_username.str); - - user_info.unix_username = unix_username; - user_info.smb_username = smb_username; - - wksta_name.str = workstation; - wksta_name.len = strlen(workstation); - - user_info.wksta_name = wksta_name; - - memcpy(user_info.chal, chal, 8); - - if ((lm_pwd_len >= 24 || nt_pwd_len >= 24) || - (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) { - /* if 24 bytes long assume it is an encrypted password */ - - user_info.lm_resp.buffer = (uint8 *)lm_pwd; - user_info.lm_resp.len = lm_pwd_len; - user_info.nt_resp.buffer = (uint8 *)nt_pwd; - user_info.nt_resp.len = nt_pwd_len; - + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + /* Match WinXP and don't give the game away */ + return NT_STATUS_LOGON_FAILURE; } else { - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - /* - * Not encrypted - do so. - */ - - DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); - - if (lm_pwd_len > 0) { - SMBencrypt( (uchar *)lm_pwd, user_info.chal, local_lm_response); - user_info.lm_resp.buffer = (uint8 *)local_lm_response; - user_info.lm_resp.len = 24; - - - /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. - We might want to add a check here and only do an LM in that case */ + return nt_status; + } +} - /* This encrypts the lm_pwd feild, which actualy contains the password - rather than the nt_pwd field becouse that contains nothing */ - SMBNTencrypt((uchar *)lm_pwd, user_info.chal, local_nt_response); - user_info.nt_resp.buffer = (uint8 *)local_nt_response; - user_info.nt_resp.len = 24; - } - - user_info.plaintext_password.str = (char *)lm_pwd; - user_info.plaintext_password.len = lm_pwd_len; - } - result = check_password(&user_info, &server_info); +/**************************************************************************** + COMPATABILITY INTERFACES: + ***************************************************************************/ - free_serversupplied_info(&server_info); /* No info needed */ +/**************************************************************************** +check if a username/password is OK assuming the password is a 24 byte +SMB hash +return True if the password is correct, False otherwise +****************************************************************************/ - return result; -} +static NTSTATUS pass_check_smb(char *smb_name, + char *domain, + DATA_BLOB lm_pwd, + DATA_BLOB nt_pwd, + DATA_BLOB plaintext_password, + BOOL encrypted) -NTSTATUS pass_check_smb(char *smb_user, char *unix_user, - char *domain, char *workstation, - uchar *lm_pwd, int lm_pwd_len, - uchar *nt_pwd, int nt_pwd_len) { - uchar chal[8]; - - if (!last_challenge(chal)) { - generate_random_buffer( chal, 8, False); - } - - return pass_check_smb_with_chal(smb_user, unix_user, - domain, workstation, chal, - lm_pwd, lm_pwd_len, - nt_pwd, nt_pwd_len); - + NTSTATUS nt_status; + auth_usersupplied_info *user_info = NULL; + auth_serversupplied_info *server_info = NULL; + + make_user_info_for_reply(&user_info, smb_name, + domain, + lm_pwd, + nt_pwd, + plaintext_password, + encrypted); + + nt_status = check_password(user_info, &server_info); + free_user_info(&user_info); + free_server_info(&server_info); + return nt_status; } /**************************************************************************** @@ -234,36 +211,32 @@ check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen) +BOOL password_ok(char *smb_name, DATA_BLOB password_blob) { - extern fstring remote_machine; - /* - * This hack must die! But until I rewrite the rest of samba - * it must stay - abartlet 2001-08-03 - */ - - if ((pwlen == 0) && !lp_null_passwords()) { - DEBUG(4,("Null passwords not allowed.\n")); - return False; - } - - /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as - required. */ - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { - return True; - } + DATA_BLOB null_password = data_blob(NULL, 0); + extern BOOL global_encrypted_passwords_negotiated; - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { - return True; + if (global_encrypted_passwords_negotiated) { + /* + * The password could be either NTLM or plain LM. Try NTLM first, + * but fall-through as required. + * NTLMv2 makes no sense here. + */ + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, global_encrypted_passwords_negotiated))) { + return True; + } + + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, global_encrypted_passwords_negotiated))) { + return True; + } + } else { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, global_encrypted_passwords_negotiated))) { + return True; + } } return False; } -/* Free a auth_serversupplied_info structure */ -void free_serversupplied_info(auth_serversupplied_info *server_info) -{ - SAFE_FREE(server_info->group_rids); -} diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index bcd41bacdb..f20da19607 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -29,7 +29,7 @@ BOOL global_machine_password_needs_changing = False; ****************************************************************************/ NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; char *p, *pserver; diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index 9f5f1e10e5..9c07e48a9b 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -131,11 +131,11 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e /**************************************************************************** check for a possible hosts equiv or rhosts entry for the user ****************************************************************************/ -static BOOL check_hosts_equiv(char *user) /* should be const... */ + +static BOOL check_hosts_equiv(struct passwd *pass) { char *fname = NULL; pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user); if (!pass) return(False); @@ -149,15 +149,15 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */ } if (lp_use_rhosts()) - { - char *home = pass->pw_dir; - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) - return(True); - } - } - + { + char *home = pass->pw_dir; + if (home) { + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); + if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) + return(True); + } + } + return(False); } @@ -166,15 +166,21 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */ ****************************************************************************/ NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - become_root(); - if (check_hosts_equiv(user_info->unix_username.str)) { - nt_status = NT_STATUS_OK; + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + + if (pass) { + become_root(); + if (check_hosts_equiv(pass)) { + nt_status = NT_STATUS_OK; + make_server_info_pw(server_info, pass); + } + unbecome_root(); + } else { + nt_status = NT_STATUS_NO_SUCH_USER; } - unbecome_root(); return nt_status; } diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index 520417e3e0..ddbc284d50 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -115,7 +115,7 @@ struct cli_state *server_cryptkey(void) - Validate a password with the password server. ****************************************************************************/ -NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { struct cli_state *cli; static unsigned char badpass[24]; @@ -134,8 +134,8 @@ NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_ser if(badpass[0] == 0) memset(badpass, 0x1f, sizeof(badpass)); - if((user_info->nt_resp.len == sizeof(badpass)) && - !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) { + if((user_info->nt_resp.length == sizeof(badpass)) && + !memcmp(badpass, user_info->nt_resp.data, sizeof(badpass))) { /* * Very unlikely, our random bad password is the same as the users * password. @@ -206,11 +206,11 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, user_info->smb_username.str, - (char *)user_info->lm_resp.buffer, - user_info->lm_resp.len, - (char *)user_info->nt_resp.buffer, - user_info->nt_resp.len, + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->lm_resp.data, + user_info->lm_resp.length, + (char *)user_info->nt_resp.data, + user_info->nt_resp.length, user_info->domain.str)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); /* Make this cli_nt_error() when the conversion is in */ @@ -227,5 +227,16 @@ use this machine as the password server.\n")); cli_ulogoff(cli); + if NT_STATUS_IS_OK(nt_status) { + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + if (pass) { + if (!make_server_info_pw(server_info, pass)) { + nt_status = NT_STATUS_NO_MEMORY; + } + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } + return(nt_status); } diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 84ca8d03be..d4283429ce 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -26,53 +26,65 @@ /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(const uchar *password, +static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, const uchar *part_passwd, - const uchar *c8, - char user_sess_key[16]) + DATA_BLOB sec_blob, + uint8 user_sess_key[16]) { - /* Finish the encryption of part_passwd. */ - uchar p24[24]; - - if (part_passwd == NULL) { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always false ! */ - return False; - } + /* Finish the encryption of part_passwd. */ + uchar p24[24]; + + if (part_passwd == NULL) { + DEBUG(10,("No password set - DISALLOWING access\n")); + /* No password set - always false ! */ + return False; + } + + if (sec_blob.length != 8) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challange size (%d)\n", sec_blob.length)); + return False; + } + + if (nt_response.length != 24) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response.length)); + return False; + } - SMBOWFencrypt(part_passwd, c8, p24); + SMBOWFencrypt(part_passwd, sec_blob.data, p24); if (user_sess_key != NULL) { SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); } - - - + + + #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); dump_data(100, part_passwd, 16); DEBUG(100,("Password from client was |")); - dump_data(100, password, 24); + dump_data(100, nt_response.data, nt_response.length); DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); + dump_data(100, sec_blob.data, sec_blob.length); DEBUG(100,("Value from encryption was |")); dump_data(100, p24, 24); #endif - return (memcmp(p24, password, 24) == 0); + return (memcmp(p24, nt_response.data, 24) == 0); } /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, +static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, const uchar *part_passwd, - const uchar *c8, + const DATA_BLOB sec_blob, const char *user, const char *domain, - char user_sess_key[16]) + uint8 user_sess_key[16]) { /* Finish the encryption of part_passwd. */ uchar kr[16]; - uchar resp[16]; + uchar value_from_encryption[16]; + uchar client_response[16]; + DATA_BLOB client_key_data; if (part_passwd == NULL) { @@ -81,25 +93,42 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, return False; } + if (ntv2_response.length < 16) { + /* We MUST have more than 16 bytes, or the stuff below will go + crazy... */ + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", + ntv2_response.length)); + return False; + } + + client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16); + memcpy(client_response, ntv2_response.data, ntv2_response.length); + + if (!client_key_data.data) { + return False; + } + ntv2_owf_gen(part_passwd, user, domain, kr); - SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, (char *)resp); + SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, (char *)value_from_encryption); if (user_sess_key != NULL) { - SMBsesskeygen_ntv2(kr, resp, user_sess_key); + SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); } #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); dump_data(100, part_passwd, 16); DEBUG(100,("Password from client was |")); - dump_data(100, password, pwd_len); + dump_data(100, ntv2_response.data, ntv2_response.length); + DEBUG(100,("Variable data from client was |")); + dump_data(100, ntv2_response.data, ntv2_response.length); DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); + dump_data(100, sec_blob.data, sec_blob.length); DEBUG(100,("Value from encryption was |")); - dump_data(100, resp, 16); + dump_data(100, value_from_encryption, 16); #endif - - return (memcmp(resp, password, 16) == 0); + data_blob_clear_free(&client_key_data); + return (memcmp(value_from_encryption, client_response, 16) == 0); } @@ -107,11 +136,12 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, char user_sess_key[16]) +NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, uint8 user_sess_key[16]) { const uint8 *nt_pw, *lm_pw; uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); - + uint32 ntlmssp_flags; + if (!user_info || !sampass) return NT_STATUS_LOGON_FAILURE; @@ -119,12 +149,12 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use { if (lp_null_passwords()) { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", sampass->username)); + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_OK); } else { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username)); + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_LOGON_FAILURE); } } @@ -132,61 +162,84 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use nt_pw = pdb_get_nt_passwd(sampass); lm_pw = pdb_get_lanman_passwd(sampass); - if (nt_pw != NULL && user_info->nt_resp.len > 0) { - if ((user_info->nt_resp.len > 24 )) { + ntlmssp_flags = user_info->ntlmssp_flags; + + if (nt_pw == NULL) { + DEBUG(3,("smb_password_ok: NO NT password stored for user %s.\n", + pdb_get_username(sampass))); + /* No return, we want to check the LM hash below in this case */ + ntlmssp_flags &= (~(NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2)); + } + + if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM2) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, - user_info->nt_resp.len, + if (smb_pwd_check_ntlmv2( user_info->nt_resp, nt_pw, - user_info->chal, user_info->smb_username.str, - user_info->requested_domain.str, + user_info->sec_blob, user_info->smb_name.str, + user_info->client_domain.str, user_sess_key)) { return NT_STATUS_OK; } else { - DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; + DEBUG(3,("smb_password_ok: NTLMv2 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; } - - } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24)) { + } else if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM) { + if (lp_ntlm_auth()) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, - nt_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_pwd_check_ntlmv1(user_info->nt_resp, + nt_pw, user_info->sec_blob, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(3,("smb_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; + } } else { - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; + DEBUG(2,("smb_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); + /* No return, we want to check the LM hash below in this case */ } - } else { - return NT_STATUS_LOGON_FAILURE; - } } - if (lm_pw != NULL && user_info->lm_resp.len == 24) { - if (lp_lanman_auth()) { - DEBUG(4,("smb_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, - lm_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: LM password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } + if (lm_pw == NULL) { + DEBUG(3,("smb_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass))); + ntlmssp_flags &= (~NTLMSSP_NEGOTIATE_OEM); + } + + if (ntlmssp_flags & NTLMSSP_NEGOTIATE_OEM) { + + if (user_info->lm_resp.length != 24) { + DEBUG(2,("smb_password_ok: invalid LanMan password length (%d) for user %s\n", + user_info->nt_resp.length, pdb_get_username(sampass))); } + + if (!lp_lanman_auth()) { + DEBUG(3,("smb_password_ok: Lanman passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_LOGON_FAILURE; + } + + DEBUG(4,("smb_password_ok: Checking LM password\n")); + if (smb_pwd_check_ntlmv1(user_info->lm_resp, + lm_pw, user_info->sec_blob, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: LM password check failed for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; + } } - /* Should not be reached */ - return NT_STATUS_LOGON_FAILURE; + /* Should not be reached, but if they send nothing... */ + DEBUG(3,("smb_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; } /**************************************************************************** @@ -290,33 +343,58 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { SAM_ACCOUNT *sampass=NULL; BOOL ret; NTSTATUS nt_status; + uint8 user_sess_key[16]; + const uint8* lm_hash; pdb_init_sam(&sampass); /* get the account information */ become_root(); - ret = pdb_getsampwnam(sampass, user_info->unix_username.str); + ret = pdb_getsampwnam(sampass, user_info->internal_username.str); unbecome_root(); if (ret == False) { - DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->unix_username.str)); + DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(sampass, user_info, (char *)(server_info->session_key)); + nt_status = sam_password_ok(sampass, user_info, user_sess_key); - if NT_STATUS_IS_OK(nt_status) { - nt_status = sam_account_ok(sampass, user_info); + if (!NT_STATUS_IS_OK(nt_status)) { + pdb_free_sam(&sampass); + return nt_status; } - pdb_free_sam(&sampass); + nt_status = sam_account_ok(sampass, user_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + pdb_free_sam(&sampass); + return nt_status; + } + + if (!make_server_info_sam(server_info, sampass)) { + DEBUG(0,("failed to malloc memory for server_info\n")); + return NT_STATUS_NO_MEMORY; + } + + lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account); + if (lm_hash) { + memcpy((*server_info)->first_8_lm_hash, lm_hash, 8); + } + + memcpy((*server_info)->session_key, user_sess_key, sizeof(user_sess_key)); + return nt_status; } + + + + diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 29a2a6eafb..d456da1fdf 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -82,22 +82,27 @@ check if a username/password is OK assuming the password in PLAIN TEXT ****************************************************************************/ -NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct passwd *pass = NULL; become_root(); - - pass = Get_Pwnam(user_info->unix_username.str); + pass = Get_Pwnam(user_info->internal_username.str); nt_status = pass_check(pass, - pass ? pass->pw_name : user_info->unix_username.str, - user_info->plaintext_password.str, - user_info->plaintext_password.len, + pass ? pass->pw_name : user_info->internal_username.str, + (char *)user_info->plaintext_password.data, + user_info->plaintext_password.length-1, lp_update_encrypted() ? update_smbpassword_file : NULL, True); + + if NT_STATUS_IS_OK(nt_status) { + if (pass) { + make_server_info_pw(server_info, pass); + } + } unbecome_root(); diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index d3b9aa7001..297c482af5 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -25,6 +25,8 @@ /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; static BOOL challenge_sent=False; +extern fstring remote_machine; +extern pstring global_myname; /******************************************************************* Get the next challenge value - no repeats. @@ -64,7 +66,7 @@ BOOL last_challenge(unsigned char *challenge) Create a UNIX user on demand. ****************************************************************************/ -static int smb_create_user(char *unix_user, char *homedir) +static int smb_create_user(const char *unix_user, const char *homedir) { pstring add_script; int ret; @@ -100,40 +102,560 @@ static int smb_delete_user(char *unix_user) Add and Delete UNIX users on demand, based on NTSTATUS codes. ****************************************************************************/ -void smb_user_control(char *unix_user, NTSTATUS nt_status) +void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status) { struct passwd *pwd=NULL; if (NT_STATUS_IS_OK(nt_status)) { - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - */ - if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) - smb_create_user(unix_user, NULL); - - if(lp_adduser_script() && pwd) { - SMB_STRUCT_STAT st; + if (!(server_info->sam_fill_level & SAM_FILL_UNIX)) { + /* - * Also call smb_create_user if the users home directory - * doesn't exist. Used with winbindd to allow the script to - * create the home directory for a user mapped with winbindd. + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. */ + + if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) { + smb_create_user(user_info->internal_username.str, NULL); + } + } else { + if(lp_adduser_script()) { + SMB_STRUCT_STAT st; + const char *home_dir = pdb_get_homedir(server_info->sam_account); + /* + * Also call smb_create_user if the users home directory + * doesn't exist. Used with winbindd to allow the script to + * create the home directory for a user mapped with winbindd. + */ - if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) - smb_create_user(unix_user, pwd->pw_dir); + if (home_dir && + (sys_stat(home_dir, &st) == -1) && (errno == ENOENT)) { + smb_create_user(user_info->internal_username.str, home_dir); + } + } } - - } else if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_NO_SUCH_USER)) { + } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { /* * User failed to validate ok against Domain controller. * If the failure was "user doesn't exist" and admin * wants us to try and delete that UNIX user on the fly, * do so. */ - if(lp_deluser_script() && smb_getpwnam(unix_user,True)) - smb_delete_user(unix_user); + if (lp_deluser_script()) { + smb_delete_user(user_info->internal_username.str); + } + } +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info(auth_usersupplied_info **user_info, + char *smb_name, char *internal_username, + char *client_domain, char *domain, + char *wksta_name, DATA_BLOB sec_blob, + DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, + DATA_BLOB plaintext, + uint32 ntlmssp_flags, BOOL encrypted) +{ + + DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); + + *user_info = malloc(sizeof(**user_info)); + if (!user_info) { + DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info))); + return False; + } + + ZERO_STRUCTP(*user_info); + + DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username)); + + (*user_info)->smb_name.str = strdup(smb_name); + if ((*user_info)->smb_name.str) { + (*user_info)->smb_name.len = strlen(smb_name); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->internal_username.str = strdup(internal_username); + if ((*user_info)->internal_username.str) { + (*user_info)->internal_username.len = strlen(internal_username); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->domain.str = strdup(domain); + if ((*user_info)->domain.str) { + (*user_info)->domain.len = strlen(domain); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->client_domain.str = strdup(client_domain); + if ((*user_info)->client_domain.str) { + (*user_info)->client_domain.len = strlen(client_domain); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->wksta_name.str = strdup(wksta_name); + if ((*user_info)->wksta_name.str) { + (*user_info)->wksta_name.len = strlen(wksta_name); + } else { + free_user_info(user_info); + return False; } + + DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username)); + + (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length); + (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length); + (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length); + (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length); + + (*user_info)->encrypted = encrypted; + (*user_info)->ntlmssp_flags = ntlmssp_flags; + + DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name)); + + return True; } + +/**************************************************************************** + Create an auth_usersupplied_data structure after appropriate mapping. +****************************************************************************/ + +BOOL make_user_info_map(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, DATA_BLOB sec_blob, + DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, + DATA_BLOB plaintext, + uint32 ntlmssp_flags, BOOL encrypted) +{ + char *domain; + fstring internal_username; + fstrcpy(internal_username, smb_name); + map_username(internal_username); + + if (lp_allow_trusted_domains()) { + domain = client_domain; + } else { + domain = lp_workgroup(); + } + + return make_user_info(user_info, + smb_name, internal_username, + client_domain, domain, + wksta_name, sec_blob, + lm_pwd, nt_pwd, + plaintext, + ntlmssp_flags, encrypted); + +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, uchar chal[8], + uchar *lm_network_pwd, int lm_pwd_len, + uchar *nt_network_pwd, int nt_pwd_len) +{ + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); + DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); + DATA_BLOB plaintext_blob = data_blob(NULL, 0); + uint32 ntlmssp_flags = 0; + + if (lm_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + if (nt_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + + ret = make_user_info_map(user_info, + smb_name, client_domain, + wksta_name, sec_blob, + nt_blob, lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&lm_blob); + data_blob_free(&nt_blob); + return ret; +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, + uchar *lm_interactive_pwd, int lm_pwd_len, + uchar *nt_interactive_pwd, int nt_pwd_len, + uchar *dc_sess_key) +{ + char nt_pwd[16]; + char lm_pwd[16]; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + unsigned char key[16]; + uint8 chal[8]; + uint32 ntlmssp_flags = 0; + + generate_random_buffer(chal, 8, False); + + memset(key, 0, 16); + memcpy(key, dc_sess_key, 8); + + memcpy(lm_pwd, lm_interactive_pwd, 16); + memcpy(nt_pwd, nt_interactive_pwd, 16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("key:")); + dump_data(100, (char *)key, 16); + + DEBUG(100,("lm owf password:")); + dump_data(100, lm_pwd, 16); + + DEBUG(100,("nt owf password:")); + dump_data(100, nt_pwd, 16); +#endif + + SamOEMhash((uchar *)lm_pwd, key, 16); + SamOEMhash((uchar *)nt_pwd, key, 16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("decrypt of lm owf password:")); + dump_data(100, lm_pwd, 16); + + DEBUG(100,("decrypt of nt owf password:")); + dump_data(100, nt_pwd, 16); +#endif + + generate_random_buffer(chal, 8, False); + SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); + SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); + + /* Password info parinoia */ + ZERO_STRUCT(lm_pwd); + ZERO_STRUCT(nt_pwd); + ZERO_STRUCT(key); + + { + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); + DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); + DATA_BLOB plaintext_blob = data_blob(NULL, 0); + + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; + ret = make_user_info_map(user_info, + smb_name, client_domain, + wksta_name, sec_blob, + local_nt_blob, + local_lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + return ret; + } +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info_for_winbind(auth_usersupplied_info **user_info, + char *username, + char *domain, + char *password) +{ + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + char chal[8]; + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; + DATA_BLOB plaintext_blob; + uint32 ntlmssp_flags = 0; + + /* + * Not encrypted - do so. + */ + + DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + + generate_random_buffer(chal, 8, False); + + if (*password) { + SMBencrypt( (uchar *)password, chal, local_lm_response); + + /* This encrypts the lm_pwd feild, which actualy contains the password + rather than the nt_pwd field becouse that contains nothing */ + + /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. + We might want to add a check here and only do an LM in that case */ + + SMBNTencrypt((uchar *)password, chal, local_nt_response); + + local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); + local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); + plaintext_blob = data_blob(password, strlen(password)+1); + if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) { + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + data_blob_clear_free(&plaintext_blob); + return False; + } + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; + } else { + local_lm_blob = data_blob(NULL, 0); + local_nt_blob = data_blob(NULL, 0); + plaintext_blob = data_blob(NULL, 0); + } + + { + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + + if (!sec_blob.data) { + return False; + } + + ret = make_user_info(user_info, + username, username, + domain, domain, + global_myname, sec_blob, + local_nt_blob, + local_lm_blob, + plaintext_blob, + ntlmssp_flags, False); + + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + data_blob_clear_free(&plaintext_blob); + return ret; + } +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + uchar chal[8], + uchar *lm_network_pwd, int lm_pwd_len, + uchar *nt_network_pwd, int nt_pwd_len) +{ + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); + DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); + DATA_BLOB plaintext_blob = data_blob(NULL, 0); + uint32 ntlmssp_flags = 0; + + if (lm_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + if (nt_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + + ret = make_user_info(user_info, + smb_name, smb_name, + client_domain, client_domain, + global_myname, sec_blob, + nt_blob, lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&lm_blob); + data_blob_free(&nt_blob); + return ret; +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + DATA_BLOB lm_resp, DATA_BLOB nt_resp, + DATA_BLOB plaintext_password, + BOOL encrypted) +{ + uchar chal[8]; + + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; + DATA_BLOB sec_blob; + BOOL ret = False; + uint32 ntlmssp_flags = 0; + + if (encrypted) { + DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); + if (!last_challenge(chal)) { + DEBUG(0,("Encrypted login but no challange set!\n")); + return False; + } + sec_blob = data_blob(chal, 8); + + if (lm_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + } + if (nt_resp.length == 0) { + } else if (nt_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + } else { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + + return make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, sec_blob, + lm_resp, + nt_resp, + no_plaintext_blob, + ntlmssp_flags, encrypted); + } + + generate_random_buffer(chal, 8, False); + + sec_blob = data_blob(chal, 8); + + /* + * Not encrypted - do so. + */ + + DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + + if (plaintext_password.data) { + unsigned char local_lm_response[24]; + + SMBencrypt( (uchar *)plaintext_password.data, chal, local_lm_response); + local_lm_blob = data_blob(local_lm_response, 24); + + /* We can't do an NT hash here, as the password needs to be case insensitive */ + local_nt_blob = data_blob(NULL, 0); + + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM; + } else { + local_lm_blob = data_blob(NULL, 0); + local_nt_blob = data_blob(NULL, 0); + } + + ret = make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, + sec_blob, + local_lm_blob, + local_nt_blob, + plaintext_password, + ntlmssp_flags, encrypted); + + data_blob_free(&local_lm_blob); + return ret; +} + +BOOL make_server_info(auth_serversupplied_info **server_info) +{ + *server_info = malloc(sizeof(**server_info)); + if (!*server_info) { + DEBUG(0,("make_server_info_sam: malloc failed!\n")); + return False; + } + ZERO_STRUCTP(*server_info); + return True; +} + +BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) +{ + if (!make_server_info(server_info)) { + return False; + } + + (*server_info)->sam_fill_level = SAM_FILL_ALL; + (*server_info)->sam_account = sampass; + + DEBUG(5,("make_server_info_sam: made sever info for user %s\n", + pdb_get_username((*server_info)->sam_account))); + return True; +} + +BOOL make_server_info_pw(auth_serversupplied_info **server_info, struct passwd *pwd) +{ + SAM_ACCOUNT *sampass = NULL; + if (!pdb_init_sam_pw(&sampass, pwd)) { + return False; + } + return make_server_info_sam(server_info, sampass); +} + +void free_user_info(auth_usersupplied_info **user_info) +{ + DEBUG(5,("attempting to free (and zero) a user_info structure\n")); + if (*user_info != NULL) { + if ((*user_info)->smb_name.str) { + DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str)); + } + SAFE_FREE((*user_info)->smb_name.str); + SAFE_FREE((*user_info)->internal_username.str); + SAFE_FREE((*user_info)->client_domain.str); + SAFE_FREE((*user_info)->domain.str); + data_blob_free(&(*user_info)->sec_blob); + data_blob_free(&(*user_info)->lm_resp); + data_blob_free(&(*user_info)->nt_resp); + SAFE_FREE((*user_info)->interactive_password); + data_blob_clear_free(&(*user_info)->plaintext_password); + ZERO_STRUCT(**user_info); + } + SAFE_FREE(*user_info); +} + +/*************************************************************************** + Clear out a server_info struct that has been allocated +***************************************************************************/ +void free_server_info(auth_serversupplied_info **server_info) +{ + if (*server_info != NULL) { + pdb_free_sam(&(*server_info)->sam_account); + + /* call pam_end here, unless we know we are keeping it */ + SAFE_FREE((*server_info)->group_rids); + + ZERO_STRUCT(**server_info); + } + SAFE_FREE(*server_info); +} + +/*************************************************************************** + Make a server_info struct for a guest user +***************************************************************************/ +void make_server_info_guest(auth_serversupplied_info **server_info) +{ + struct passwd *pass = sys_getpwnam(lp_guestaccount(-1)); + + if (pass) { + make_server_info_pw(server_info, pass); + } +} + diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e8f40f1fa3..01eabfda5e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -197,10 +197,11 @@ has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest, char *full_name) +int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL guest) { user_struct *vuser = NULL; + uid_t *puid; + gid_t *pgid; /* Ensure no vuid gets registered in share level security. */ if(lp_security() == SEC_SHARE) @@ -217,8 +218,14 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, ZERO_STRUCTP(vuser); - DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)uid, (unsigned int)gid, - unix_name, requested_name, domain, guest )); + puid = pdb_get_uid(server_info->sam_account); + pgid = pdb_get_gid(server_info->sam_account); + + if (!puid || !pgid) { + DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); + free(vuser); + return UID_FIELD_INVALID; + } /* Allocate a free vuid. Yes this is a linear search... :-) */ while( get_valid_user_struct(next_vuid) != NULL ) { @@ -231,13 +238,19 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid )); vuser->vuid = next_vuid; - vuser->uid = uid; - vuser->gid = gid; + vuser->uid = *puid; + vuser->gid = *pgid; vuser->guest = guest; - fstrcpy(vuser->user.unix_name,unix_name); - fstrcpy(vuser->user.smb_name,requested_name); - fstrcpy(vuser->user.domain,domain); - fstrcpy(vuser->user.full_name, full_name); + fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); + fstrcpy(vuser->user.smb_name, smb_name); + fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); + fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); + + DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", + (unsigned int)vuser->uid, + (unsigned int)vuser->gid, + vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, guest )); + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name)); vuser->n_groups = 0; @@ -332,7 +345,7 @@ BOOL user_ok(char *user,int snum) /**************************************************************************** validate a group username entry. Return the username or NULL ****************************************************************************/ -static char *validate_group(char *group,char *password,int pwlen,int snum) +static char *validate_group(char *group, DATA_BLOB password,int snum) { #ifdef HAVE_NETGROUP { @@ -341,7 +354,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen)) { + password_ok(user,password)) { endnetgrent(); return(user); } @@ -396,7 +409,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; fstrcpy(name,member); if (user_ok(name,snum) && - password_ok(name,password,pwlen)) { + password_ok(name,password)) { endgrent(); return(&name[0]); } @@ -419,7 +432,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) Note this is *NOT* used when logging on using sessionsetup_and_X. ****************************************************************************/ -BOOL authorise_login(int snum,char *user,char *password, int pwlen, +BOOL authorise_login(int snum,char *user, DATA_BLOB password, BOOL *guest,BOOL *force,uint16 vuid) { BOOL ok = False; @@ -427,7 +440,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, #if DEBUG_PASSWORD DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n", - user,password)); + user,password.data)); #endif *guest = False; @@ -472,7 +485,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->user.unix_name,snum) && - password_ok(vuser->user.unix_name, password, pwlen)) { + password_ok(vuser->user.unix_name, password)) { fstrcpy(user, vuser->user.unix_name); vuser->guest = False; DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user)); @@ -494,7 +507,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen)) { + if (password_ok(user2,password)) { ok = True; fstrcpy(user,user2); DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \ @@ -526,7 +539,7 @@ and given password ok\n", user)); for (auser=strtok(user_list,LIST_SEP); auser && !ok; auser = strtok(NULL,LIST_SEP)) { if (*auser == '@') { - auser = validate_group(auser+1,password,pwlen,snum); + auser = validate_group(auser+1,password,snum); if (auser) { ok = True; fstrcpy(user,auser); @@ -536,7 +549,7 @@ and given password ok (%s)\n", user)); } else { fstring user2; fstrcpy(user2,auser); - if (user_ok(user2,snum) && password_ok(user2,password,pwlen)) { + if (user_ok(user2,snum) && password_ok(user2,password)) { ok = True; fstrcpy(user,user2); DEBUG(3,("authorise_login: ACCEPTED: user list username \ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ca7bcb9c5f..b60738d23d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -159,14 +159,16 @@ int reply_tcon(connection_struct *conn, int pwlen=0; NTSTATUS nt_status; char *p; - + DATA_BLOB password_blob; + START_PROFILE(SMBtcon); *service = *password = *dev = 0; p = smb_buf(inbuf)+1; p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1; - p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1; + pwlen = srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1; + p += pwlen; p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1; p = strrchr_m(service,'\\'); @@ -174,7 +176,9 @@ int reply_tcon(connection_struct *conn, pstrcpy(service, p+1); } - conn = make_connection(service,password,pwlen,dev,vuid,&nt_status); + password_blob = data_blob(password, pwlen+1); + + conn = make_connection(service,password_blob,dev,vuid,&nt_status); if (!conn) { END_PROFILE(SMBtcon); @@ -200,16 +204,17 @@ int reply_tcon(connection_struct *conn, int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { fstring service; - pstring password; + DATA_BLOB password; pstring devicename; NTSTATUS nt_status; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); pstring path; char *p, *q; - START_PROFILE(SMBtconX); - - *service = *password = *devicename = 0; + extern BOOL global_encrypted_passwords_negotiated; + START_PROFILE(SMBtconX); + + *service = *devicename = 0; /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { @@ -220,17 +225,17 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_DOS(ERRDOS,ERRbuftoosmall); } - memcpy(password,smb_buf(inbuf),passlen); - password[passlen]=0; + if (global_encrypted_passwords_negotiated) { + password = data_blob(smb_buf(inbuf),passlen); + } else { + password = data_blob(smb_buf(inbuf),passlen+1); + /* Ensure correct termination */ + password.data[passlen]=0; + } + p = smb_buf(inbuf) + passlen; p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); - if (passlen != 24) { - if (strequal(password," ")) - *password = 0; - passlen = strlen(password); - } - /* * the service name can be either: \\server\share * or share directly like on the DELL PowerVault 705 @@ -250,7 +255,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt DEBUG(4,("Got device type %s\n",devicename)); - conn = make_connection(service,password,passlen,devicename,vuid,&nt_status); + conn = make_connection(service,password,devicename,vuid,&nt_status); if (!conn) { END_PROFILE(SMBtconX); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 37f4610b9d..f6296201ae 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -79,7 +79,7 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) Add a home service. Returns the new service number or -1 if fail. ****************************************************************************/ -int add_home_service(char *service, char *homedir) +int add_home_service(const char *service, const char *homedir) { int iHomeService; int iService; @@ -320,8 +320,8 @@ static void set_admin_user(connection_struct *conn) Make a connection to a service. ****************************************************************************/ -connection_struct *make_connection(char *service,char *password, - int pwlen, char *dev,uint16 vuid, NTSTATUS *status) +connection_struct *make_connection(char *service, DATA_BLOB password, + char *dev,uint16 vuid, NTSTATUS *status) { int snum; struct passwd *pass = NULL; @@ -361,7 +361,7 @@ connection_struct *make_connection(char *service,char *password, if (validated_username(vuid)) { fstring unix_username; fstrcpy(unix_username,validated_username(vuid)); - return(make_connection(unix_username,password,pwlen,dev,vuid,status)); + return(make_connection(unix_username,password,dev,vuid,status)); } } else { /* Security = share. Try with current_user_info.smb_name @@ -370,7 +370,7 @@ connection_struct *make_connection(char *service,char *password, fstring unix_username; fstrcpy(unix_username,current_user_info.smb_name); map_username(unix_username); - return(make_connection(unix_username,password,pwlen,dev,vuid,status)); + return(make_connection(unix_username,password,dev,vuid,status)); } } } @@ -387,7 +387,7 @@ connection_struct *make_connection(char *service,char *password, /* shall we let them in? */ - if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { + if (!authorise_login(snum,user,password,&guest,&force,vuid)) { DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) ); *status = NT_STATUS_WRONG_PASSWORD; return NULL; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 2d9f624b80..5331127cb5 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -264,14 +264,16 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DATA_BLOB auth; char *workgroup, *user, *machine; DATA_BLOB lmhash, nthash, sess_key; + DATA_BLOB plaintext_password = data_blob(NULL, 0); + DATA_BLOB sec_blob; uint32 ntlmssp_command, neg_flags; NTSTATUS nt_status; int sess_vuid; - gid_t gid; - uid_t uid; - char *full_name; char *p; - const struct passwd *pw; + char chal[8]; + + auth_usersupplied_info *user_info = NULL; + auth_serversupplied_info *server_info = NULL; if (!spnego_parse_auth(blob1, &auth)) { #if 0 @@ -305,36 +307,40 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, file_save("lmhash1.dat", lmhash.data, lmhash.length); #endif - nt_status = pass_check_smb(user, user, - workgroup, machine, - lmhash.data, - lmhash.length, - nthash.data, - nthash.length); - - data_blob_free(&nthash); + if (!last_challenge(chal)) { + DEBUG(0,("Encrypted login but no challange set!\n")); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + sec_blob = data_blob(chal, 8); + if (!sec_blob.data) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + if (!make_user_info_map(&user_info, + user, workgroup, + machine, sec_blob, + lmhash, nthash, + plaintext_password, + neg_flags, True)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + nt_status = check_password(user_info, &server_info); + + free_user_info(&user_info); + data_blob_free(&lmhash); - + + data_blob_free(&nthash); + if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); + return ERROR_NT(nt_status_squash(nt_status)); } - /* the password is good - let them in */ - pw = smb_getpwnam(user,False); - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n",user)); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; - - sess_vuid = register_vuid(uid,gid,user,user,workgroup,False, full_name); + sess_vuid = register_vuid(server_info, user, False); - free(user); - free(workgroup); - free(machine); - + free_server_info(&server_info); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -360,30 +366,16 @@ reply to a session setup spnego anonymous packet static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize) { - char *user; int sess_vuid; - gid_t gid; - uid_t uid; - char *full_name; char *p; - const struct passwd *pw; + auth_serversupplied_info *server_info = NULL; DEBUG(3,("Got anonymous request\n")); - user = lp_guestaccount(-1); - - /* the password is good - let them in */ - pw = smb_getpwnam(user,False); - if (!pw) { - DEBUG(1,("Guest username %s is invalid on this system\n",user)); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; - - sess_vuid = register_vuid(uid,gid,user,user,lp_workgroup(),True,full_name); - + make_server_info_guest(&server_info); + sess_vuid = register_vuid(server_info, lp_guestaccount(-1), False); + free_server_info(&server_info); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -414,7 +406,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha extern uint32 global_client_caps; int ret; - DEBUG(3,("Doing spego session setup\n")); + DEBUG(3,("Doing spnego session setup\n")); if (global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv10); @@ -464,16 +456,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, int length,int bufsize) { int sess_vuid; - gid_t gid; - uid_t uid; - char* full_name; int smb_bufsize; - int smb_apasslen = 0; - pstring smb_apasswd; - int smb_ntpasslen = 0; - pstring smb_ntpasswd; + DATA_BLOB lm_resp; + DATA_BLOB nt_resp; + DATA_BLOB plaintext_password; pstring user; - pstring orig_user; fstring domain; fstring native_os; fstring native_lanman; @@ -486,9 +473,18 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern fstring remote_machine; extern userdom_struct current_user_info; extern int max_send; + + auth_usersupplied_info *user_info = NULL; + auth_serversupplied_info *server_info = NULL; + BOOL doencrypt = global_encrypted_passwords_negotiated; + START_PROFILE(SMBsesssetupX); + ZERO_STRUCT(lm_resp); + ZERO_STRUCT(nt_resp); + ZERO_STRUCT(plaintext_password); + DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2))); /* a SPNEGO session setup has 12 command words, whereas a normal @@ -503,28 +499,35 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } - *smb_apasswd = *smb_ntpasswd = 0; - smb_bufsize = SVAL(inbuf,smb_vwv2); - + if (Protocol < PROTOCOL_NT1) { - smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASS_LEN) { + uint16 passlen1 = SVAL(inbuf,smb_vwv7); + if (passlen1 > MAX_PASS_LEN) { return ERROR_DOS(ERRDOS,ERRbuftoosmall); } - memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); - - if (!doencrypt && (lp_security() != SEC_SERVER)) { - smb_apasslen = strlen(smb_apasswd); + if (doencrypt) { + lm_resp = data_blob(smb_buf(inbuf), passlen1); + } else { + plaintext_password = data_blob(smb_buf(inbuf), passlen1+1); + if (!plaintext_password.data) { + DEBUG(0,("reply_sesssetup_and_X: malloc failed for plaintext_password!\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } else { + /* Ensure null termination */ + plaintext_password.data[passlen1] = 0; + } } + + srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE); + } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); enum remote_arch_types ra_type = get_remote_arch(); char *p = smb_buf(inbuf); - + if(global_client_caps == 0) global_client_caps = IVAL(inbuf,smb_vwv11); @@ -539,16 +542,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } } - if (passlen1 != 24 && passlen2 < 24) - doencrypt = False; - if (passlen1 > MAX_PASS_LEN) { return ERROR_DOS(ERRDOS,ERRbuftoosmall); } - + passlen1 = MIN(passlen1, MAX_PASS_LEN); passlen2 = MIN(passlen2, MAX_PASS_LEN); - + if (!doencrypt) { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. @@ -591,23 +591,20 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, passlen1 = 1; } } - + /* Save the lanman2 password and the NT md4 password. */ - smb_apasslen = passlen1; - memcpy(smb_apasswd,p,smb_apasslen); - - smb_ntpasslen = passlen2; - memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); - - if (smb_apasslen != 24 || !doencrypt) { - /* trim the password */ - smb_apasslen = strlen(smb_apasswd); - - /* wfwg sometimes uses a space instead of a null */ - if (strequal(smb_apasswd," ")) { - smb_apasslen = 0; - *smb_apasswd = 0; - } + + if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) { + doencrypt = False; + } + + if (doencrypt) { + lm_resp = data_blob(p, passlen1); + nt_resp = data_blob(p+passlen1, passlen2); + } else { + plaintext_password = data_blob(p, passlen1+1); + /* Ensure null termination */ + plaintext_password.data[passlen1] = 0; } p += passlen1 + passlen2; @@ -630,15 +627,29 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - if (lp_security() == SEC_SHARE) { - /* in share level we should ignore any passwords */ - smb_ntpasslen = 0; - smb_apasslen = 0; + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine)); + + /* If no username is sent use the guest account */ + if (!*user) { + pstrcpy(user,lp_guestaccount(-1)); guest = True; } + pstrcpy(current_user_info.smb_name,user); + + reload_services(True); + + if (lp_security() == SEC_SHARE) { + /* in share level we should ignore any passwords */ + + data_blob_free(&lm_resp); + data_blob_free(&nt_resp); + data_blob_free(&plaintext_password); - DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine)); + guest = True; + map_username(user); + add_session_user(user); + } if (done_sesssetup && lp_restrict_anonymous()) { /* tests show that even if browsing is done over @@ -649,106 +660,61 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, * only deny connections that have no session * information. If a domain has been provided, then * it's not a purely anonymous connection. AAB */ - if (!*user && !*smb_apasswd && !*domain) { + if (!*user && !*domain) { DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); + + data_blob_free(&lm_resp); + data_blob_free(&nt_resp); + data_blob_free(&plaintext_password); + END_PROFILE(SMBsesssetupX); return ERROR_DOS(ERRDOS,ERRnoaccess); } } - - /* If no username is sent use the guest account */ - if (!*user) { - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - } - - pstrcpy(current_user_info.smb_name,user); - - reload_services(True); - - /* - * Save the username before mapping. We will use - * the original username sent to us for security=server - * and security=domain checking. - */ - - pstrcpy( orig_user, user); - - /* - * Always try the "DOMAIN\user" lookup first, as this is the most - * specific case. If this fails then try the simple "user" lookup. - * But don't do this for guests, as this is always a local user. - */ if (!guest) { - pstring dom_user; - - /* Work out who's who */ - - slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s", - domain, lp_winbind_separator(), user); - - if (sys_getpwnam(dom_user) != NULL) { - pstrcpy(user, dom_user); - DEBUG(3,("Using unix username %s\n", dom_user)); + NTSTATUS nt_status; + if (!make_user_info_for_reply(&user_info, + user, domain, + lm_resp, nt_resp, + plaintext_password, doencrypt)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); } - /* - * Pass the user through the NT -> unix user mapping - * function. - */ + nt_status = check_password(user_info, &server_info); - (void)map_username(user); + free_user_info(&user_info); - /* - * Do any UNIX username case mangling. - */ - smb_getpwnam(user, True); - } - - add_session_user(user); - - if (!guest) { - NTSTATUS nt_status; - nt_status = pass_check_smb(orig_user, user, - domain, remote_machine, - (unsigned char *)smb_apasswd, - smb_apasslen, - (unsigned char *)smb_ntpasswd, - smb_ntpasslen); - - if NT_STATUS_IS_OK(nt_status) { - - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { - if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || - (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - } else { - /* Match WinXP and don't give the game away */ - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { - if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } else { + data_blob_free(&lm_resp); + data_blob_free(&nt_resp); + data_blob_free(&plaintext_password); + + if (!NT_STATUS_IS_OK(nt_status)) { + if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); + pstrcpy(user,lp_guestaccount(-1)); + guest = True; + + } + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + pstrcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } /* Match WinXP and don't give the game away */ return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - } else { - return ERROR_NT(nt_status); + + if (!guest) { + free_server_info(&server_info); + return ERROR_NT(nt_status_squash(nt_status)); + } } } - if (!strequal(user,lp_guestaccount(-1)) && - lp_servicenumber(user) < 0) { - add_home_service(user,get_user_home_dir(user)); - } - - /* it's ok - setup a reply */ if (Protocol < PROTOCOL_NT1) { set_message(outbuf,3,0,True); @@ -763,30 +729,26 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* perhaps grab OS version here?? */ } - /* Set the correct uid in the outgoing and incoming packets - We will use this on future requests to determine which - user we should become. - */ - { - const struct passwd *pw = smb_getpwnam(user,False); - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n",user)); - END_PROFILE(SMBsesssetupX); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + if (guest) { + SSVAL(outbuf,smb_vwv2,1); + free_server_info(&server_info); + make_server_info_guest(&server_info); + } else { + const char *home_dir = pdb_get_homedir(server_info->sam_account); + const char *username = pdb_get_username(server_info->sam_account); + if ((home_dir && *home_dir) + && (lp_servicenumber(username) < 0)) { + add_home_service(username, home_dir); } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; } - - if (guest) - SSVAL(outbuf,smb_vwv2,1); - + /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - - sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name); - + + sess_vuid = register_vuid(server_info, user, guest); + + free_server_info(&server_info); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -- cgit From be93100240c4d81e9465015e82d5b71a5e4bf193 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 31 Oct 2001 12:07:59 +0000 Subject: Fix up domain logons. Tested with NT4. (This used to be commit c8b2718adfe114b74a155116c5e74f014d6df887) --- source3/smbd/auth_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 297c482af5..85f01605ab 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -368,8 +368,8 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, wksta_name, sec_blob, - local_nt_blob, local_lm_blob, + local_nt_blob, plaintext_blob, ntlmssp_flags, True); -- cgit From bdca4e32aa1449385778d43102cce431c85f9e91 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 31 Oct 2001 12:28:40 +0000 Subject: When you make a data_blob() then you probably need to free it too... (This used to be commit 531e24973227ca4f1ae65ffb2454aedd5871de96) --- source3/smbd/reply.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b60738d23d..8a1fecba3f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -179,6 +179,8 @@ int reply_tcon(connection_struct *conn, password_blob = data_blob(password, pwlen+1); conn = make_connection(service,password_blob,dev,vuid,&nt_status); + + data_blob_clear_free(&password); if (!conn) { END_PROFILE(SMBtcon); @@ -257,6 +259,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt conn = make_connection(service,password,devicename,vuid,&nt_status); + data_blob_clear_free(&password); + if (!conn) { END_PROFILE(SMBtconX); return ERROR_NT(nt_status); -- cgit From f32cf6dfbadf15ed073a228e5f17f3186852d068 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 31 Oct 2001 12:37:56 +0000 Subject: This should fix up the compile with krb5. This needs to use the auth interface at some stage, but for now this will do. (This used to be commit 8dc4f2e44b150cdcdecd2f6028bf06907ff90cad) --- source3/smbd/sesssetup.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 5331127cb5..7361db0205 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -41,10 +41,8 @@ static int reply_spnego_kerberos(connection_struct *conn, char *realm, *client, *p; const struct passwd *pw; char *user; - gid_t gid; - uid_t uid; - char *full_name; int sess_vuid; + auth_serversupplied_info *server_info = NULL; realm = lp_realm(); @@ -101,11 +99,15 @@ static int reply_spnego_kerberos(connection_struct *conn, DEBUG(1,("Username %s is invalid on this system\n",user)); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; + + if (!make_server_info_pw(&server_info,pw)) { + DEBUG(1,("make_server_info_from_pw failed!\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } - sess_vuid = register_vuid(uid,gid,user,user,realm,False, full_name); + sess_vuid = register_vuid(server_info, user, False); + + free_server_info(&server_info); if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); -- cgit From acb81fe408f0e674088f0952aaba442ddb494b0c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Nov 2001 05:02:41 +0000 Subject: Various post AuthRewrite cleanups, fixups and tidyups. Zero out some of the plaintext passwords for paranoia Fix up some of the other passdb backends with the change to *uid_t rather than uid_t. Make some of the code in srv_netlog_nt.c clearer, is passing an array around, so pass its lenght in is definition, not as a seperate paramater. Use sizeof() rather than magic numbers, it makes things easier to read. Cope with a PAM authenticated user who is not in /etc/passwd - currently by saying NO_SUCH_USER, but this can change in future. Andrew Bartlett (This used to be commit 514c91b16baca639bb04638042bf9894d881172a) --- source3/smbd/auth_unix.c | 6 ++++-- source3/smbd/auth_util.c | 47 +++++++++++++++++++++++++++-------------------- source3/smbd/reply.c | 4 ++-- source3/smbd/sesssetup.c | 6 +++--- 4 files changed, 36 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index d456da1fdf..8c4a520350 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -98,13 +98,15 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve update_smbpassword_file : NULL, True); + unbecome_root(); + if NT_STATUS_IS_OK(nt_status) { if (pass) { make_server_info_pw(server_info, pass); + } else { + nt_status = NT_STATUS_NO_SUCH_USER; } } - unbecome_root(); - return nt_status; } diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 85f01605ab..9de8142578 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -282,9 +282,12 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, if (lm_pwd_len) ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - if (nt_pwd_len) + if (nt_pwd_len == 24) { ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - + } else if (nt_pwd_len != 0) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + ret = make_user_info_map(user_info, smb_name, client_domain, wksta_name, sec_blob, @@ -303,15 +306,15 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - char *wksta_name, - uchar *lm_interactive_pwd, int lm_pwd_len, - uchar *nt_interactive_pwd, int nt_pwd_len, - uchar *dc_sess_key) + char *smb_name, + char *client_domain, + char *wksta_name, + uchar lm_interactive_pwd[16], + uchar nt_interactive_pwd[16], + uchar *dc_sess_key) { - char nt_pwd[16]; char lm_pwd[16]; + char nt_pwd[16]; unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; unsigned char key[16]; @@ -320,32 +323,32 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, generate_random_buffer(chal, 8, False); - memset(key, 0, 16); + ZERO_STRUCT(key); memcpy(key, dc_sess_key, 8); - memcpy(lm_pwd, lm_interactive_pwd, 16); - memcpy(nt_pwd, nt_interactive_pwd, 16); + if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd)); + if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd)); #ifdef DEBUG_PASSWORD DEBUG(100,("key:")); - dump_data(100, (char *)key, 16); + dump_data(100, (char *)key, sizeof(key)); DEBUG(100,("lm owf password:")); - dump_data(100, lm_pwd, 16); + dump_data(100, lm_pwd, sizeof(lm_pwd)); DEBUG(100,("nt owf password:")); - dump_data(100, nt_pwd, 16); + dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - SamOEMhash((uchar *)lm_pwd, key, 16); - SamOEMhash((uchar *)nt_pwd, key, 16); + SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd)); + SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd)); #ifdef DEBUG_PASSWORD DEBUG(100,("decrypt of lm owf password:")); - dump_data(100, lm_pwd, 16); + dump_data(100, lm_pwd, sizeof(lm_pwd)); DEBUG(100,("decrypt of nt owf password:")); - dump_data(100, nt_pwd, 16); + dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif generate_random_buffer(chal, 8, False); @@ -364,7 +367,11 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); DATA_BLOB plaintext_blob = data_blob(NULL, 0); - ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; + if (lm_interactive_pwd) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + if (nt_interactive_pwd) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + ret = make_user_info_map(user_info, smb_name, client_domain, wksta_name, sec_blob, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8a1fecba3f..54238e90e7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -180,7 +180,7 @@ int reply_tcon(connection_struct *conn, conn = make_connection(service,password_blob,dev,vuid,&nt_status); - data_blob_clear_free(&password); + data_blob_clear_free(&password_blob); if (!conn) { END_PROFILE(SMBtcon); @@ -260,7 +260,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt conn = make_connection(service,password,devicename,vuid,&nt_status); data_blob_clear_free(&password); - + if (!conn) { END_PROFILE(SMBtconX); return ERROR_NT(nt_status); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7361db0205..85ffadea08 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -646,7 +646,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&lm_resp); data_blob_free(&nt_resp); - data_blob_free(&plaintext_password); + data_blob_clear_free(&plaintext_password); guest = True; map_username(user); @@ -667,7 +667,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&lm_resp); data_blob_free(&nt_resp); - data_blob_free(&plaintext_password); + data_blob_clear_free(&plaintext_password); END_PROFILE(SMBsesssetupX); return ERROR_DOS(ERRDOS,ERRnoaccess); @@ -689,7 +689,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&lm_resp); data_blob_free(&nt_resp); - data_blob_free(&plaintext_password); + data_blob_clear_free(&plaintext_password); if (!NT_STATUS_IS_OK(nt_status)) { if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { -- cgit From fdc03603c1535fc03bcc53ee3f45c85692a00c82 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 3 Nov 2001 00:19:56 +0000 Subject: Move the test for non-SPNEGO session setups when using SPNEGO, becouse its a perfectly vailid behaviour for guest logins. (This used to be commit 4db8d70ad74cdbd74c0578e66377fd0233195aaa) --- source3/smbd/sesssetup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 85ffadea08..ce0e0d585e 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -496,11 +496,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } - if (global_spnego_negotiated) { - DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); - } - smb_bufsize = SVAL(inbuf,smb_vwv2); if (Protocol < PROTOCOL_NT1) { @@ -635,6 +630,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (!*user) { pstrcpy(user,lp_guestaccount(-1)); guest = True; + } else { + if (global_spnego_negotiated) { + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } } pstrcpy(current_user_info.smb_name,user); -- cgit From b3014b1840d6a1b5d8dc595c2f9b9dd64909f83e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 3 Nov 2001 00:20:31 +0000 Subject: Minor cleanups/fixes in the NTLMv2 code (This used to be commit 253790f6d71653b572c0174113b8559820de6bdd) --- source3/smbd/auth_smbpasswd.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index d4283429ce..63c22f50b9 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -102,11 +102,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, } client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16); - memcpy(client_response, ntv2_response.data, ntv2_response.length); - - if (!client_key_data.data) { - return False; - } + memcpy(client_response, ntv2_response.data, sizeof(client_response)); ntv2_owf_gen(part_passwd, user, domain, kr); SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, (char *)value_from_encryption); @@ -121,7 +117,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, DEBUG(100,("Password from client was |")); dump_data(100, ntv2_response.data, ntv2_response.length); DEBUG(100,("Variable data from client was |")); - dump_data(100, ntv2_response.data, ntv2_response.length); + dump_data(100, client_key_data.data, client_key_data.length); DEBUG(100,("Given challenge was |")); dump_data(100, sec_blob.data, sec_blob.length); DEBUG(100,("Value from encryption was |")); -- cgit From 0e14d9bee072e73114bf0d4ccbfb4c28cf81ef76 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 3 Nov 2001 00:59:57 +0000 Subject: anonymous logins are guest logins, so mark them as such. (Otherwise they can browse non-guest shares). (This used to be commit 7131fe3be4eb2c652f3afe2f3cd99d3f82e09654) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index ce0e0d585e..c7522b3402 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -375,7 +375,7 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou DEBUG(3,("Got anonymous request\n")); make_server_info_guest(&server_info); - sess_vuid = register_vuid(server_info, lp_guestaccount(-1), False); + sess_vuid = register_vuid(server_info, lp_guestaccount(-1), True); free_server_info(&server_info); if (sess_vuid == -1) { -- cgit From f8e2baf39eb864481dd48f61404136b325cd73c2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Nov 2001 23:34:24 +0000 Subject: Added NT_USER_TOKEN into server_info to fix extra groups problem. Got "medieval on our ass" about const warnings (as many as I could :-). Jeremy. (This used to be commit ee5e7ca547eff016818ba5c43b8ea0c9fa69b808) --- source3/smbd/auth_util.c | 70 +++++++++++++++++++++++++++++++++++++++-------- source3/smbd/dfree.c | 2 +- source3/smbd/password.c | 24 ++++++++++++---- source3/smbd/quotas.c | 12 ++++---- source3/smbd/sec_ctx.c | 40 --------------------------- source3/smbd/service.c | 2 +- source3/smbd/uid.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 154 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 9de8142578..9a99b2643e 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -4,6 +4,7 @@ Authentication utility functions Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Bartlett 2001 + Copyright (C) Jeremy Allison 2000-2001 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 @@ -29,21 +30,23 @@ extern fstring remote_machine; extern pstring global_myname; /******************************************************************* -Get the next challenge value - no repeats. + Get the next challenge value - no repeats. ********************************************************************/ + void generate_next_challenge(char *challenge) { - unsigned char buf[8]; + unsigned char buf[8]; - generate_random_buffer(buf,8,False); + generate_random_buffer(buf,8,False); memcpy(saved_challenge, buf, 8); memcpy(challenge,buf,8); challenge_sent = True; } /******************************************************************* -set the last challenge sent, usually from a password server + Set the last challenge sent, usually from a password server. ********************************************************************/ + BOOL set_challenge(unsigned char *challenge) { memcpy(saved_challenge,challenge,8); @@ -52,16 +55,17 @@ BOOL set_challenge(unsigned char *challenge) } /******************************************************************* -get the last challenge sent + Get the last challenge sent. ********************************************************************/ + BOOL last_challenge(unsigned char *challenge) { - if (!challenge_sent) return(False); + if (!challenge_sent) + return(False); memcpy(challenge,saved_challenge,8); return(True); } - /**************************************************************************** Create a UNIX user on demand. ****************************************************************************/ @@ -72,7 +76,8 @@ static int smb_create_user(const char *unix_user, const char *homedir) int ret; pstrcpy(add_script, lp_adduser_script()); - if (! *add_script) return -1; + if (! *add_script) + return -1; all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); if (homedir) all_string_sub(add_script, "%H", homedir, sizeof(pstring)); @@ -91,7 +96,8 @@ static int smb_delete_user(char *unix_user) int ret; pstrcpy(del_script, lp_deluser_script()); - if (! *del_script) return -1; + if (! *del_script) + return -1; all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); ret = smbrun(del_script,NULL); DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); @@ -131,7 +137,7 @@ void smb_user_control(const auth_usersupplied_info *user_info, auth_serversuppli if (home_dir && (sys_stat(home_dir, &st) == -1) && (errno == ENOENT)) { - smb_create_user(user_info->internal_username.str, home_dir); + smb_create_user(user_info->internal_username.str, home_dir); } } } @@ -641,14 +647,14 @@ void free_user_info(auth_usersupplied_info **user_info) /*************************************************************************** Clear out a server_info struct that has been allocated ***************************************************************************/ + void free_server_info(auth_serversupplied_info **server_info) { if (*server_info != NULL) { pdb_free_sam(&(*server_info)->sam_account); /* call pam_end here, unless we know we are keeping it */ - SAFE_FREE((*server_info)->group_rids); - + delete_nt_token( &(*server_info)->ptok ); ZERO_STRUCT(**server_info); } SAFE_FREE(*server_info); @@ -657,6 +663,7 @@ void free_server_info(auth_serversupplied_info **server_info) /*************************************************************************** Make a server_info struct for a guest user ***************************************************************************/ + void make_server_info_guest(auth_serversupplied_info **server_info) { struct passwd *pass = sys_getpwnam(lp_guestaccount(-1)); @@ -666,3 +673,42 @@ void make_server_info_guest(auth_serversupplied_info **server_info) } } +/**************************************************************************** + Delete a SID token. +****************************************************************************/ + +void delete_nt_token(NT_USER_TOKEN **pptoken) +{ + if (*pptoken) { + NT_USER_TOKEN *ptoken = *pptoken; + SAFE_FREE( ptoken->user_sids ); + ZERO_STRUCTP(ptoken); + } + SAFE_FREE(*pptoken); +} + +/**************************************************************************** + Duplicate a SID token. +****************************************************************************/ + +NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) +{ + NT_USER_TOKEN *token; + + if (!ptoken) + return NULL; + + if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) + return NULL; + + ZERO_STRUCTP(token); + + if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) { + SAFE_FREE(token); + return NULL; + } + + token->num_sids = ptoken->num_sids; + + return token; +} diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 13a3e86c6e..51f0614941 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -121,7 +121,7 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, } else sys_fsusage(path, dfree, dsize); - if (disk_quotas((char *)path, &bsize_q, &dfree_q, &dsize_q)) { + if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { (*bsize) = bsize_q; (*dfree) = MIN(*dfree,dfree_q); (*dsize) = MIN(*dsize,dsize_q); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 01eabfda5e..429d72b4e5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -117,7 +117,7 @@ char *validated_domain(uint16 vuid) Create the SID list for this user. ****************************************************************************/ -NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest) +NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest, NT_USER_TOKEN *sup_tok) { extern DOM_SID global_sid_World; extern DOM_SID global_sid_Network; @@ -137,6 +137,9 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, /* We always have uid/gid plus World and Network and Authenticated Users or Guest SIDs. */ num_sids = 5 + ngroups; + if (sup_tok && sup_tok->num_sids) + num_sids += sup_tok->num_sids; + if ((token->user_sids = (DOM_SID *)malloc( num_sids*sizeof(DOM_SID))) == NULL) { SAFE_FREE(token); return NULL; @@ -149,13 +152,15 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, * se_access_check depends on this. */ - uid_to_sid( &psids[psid_ndx++], uid); + uid_to_sid( &psids[PRIMARY_USER_SID_INDEX], uid); + psid_ndx++; /* * Primary group SID is second in token. Convention. */ - gid_to_sid( &psids[psid_ndx++], gid); + gid_to_sid( &psids[PRIMARY_GROUP_SID_INDEX], gid); + psid_ndx++; /* Now add the group SIDs. */ @@ -165,6 +170,10 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, } } + /* Now add the additional SIDs from the supplimentary token. */ + for (i = 0; i < sup_tok->num_sids; i++) + sid_copy( &psids[psid_ndx++], &sup_tok->user_sids[i] ); + /* * Finally add the "standard" SIDs. * The only difference between guest and "anonymous" (which we @@ -218,8 +227,8 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL gu ZERO_STRUCTP(vuser); - puid = pdb_get_uid(server_info->sam_account); - pgid = pdb_get_gid(server_info->sam_account); + puid = pdb_get_uid(server_info->sam_account); + pgid = pdb_get_gid(server_info->sam_account); if (!puid || !pgid) { DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); @@ -261,8 +270,11 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL gu initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid); get_current_groups( &vuser->n_groups, &vuser->groups); + if (server_info->ptok) + add_supplementary_nt_login_groups(&vuser->n_groups, &vuser->groups, &server_info->ptok); + /* Create an NT_USER_TOKEN struct for this user. */ - vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, guest); + vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, guest, server_info->ptok); DEBUG(3,("uid %d registered to name %s\n",(int)vuser->uid,vuser->user.unix_name)); diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 76d1124aea..96670a985d 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -114,7 +114,7 @@ static int get_smb_linux_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA try to get the disk space from disk quotas (LINUX version) ****************************************************************************/ -BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { int r; SMB_STRUCT_STAT S; @@ -199,7 +199,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U try to get the disk space from disk quotas (CRAY VERSION) ****************************************************************************/ -BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { struct mntent *mnt; FILE *fd; @@ -479,7 +479,7 @@ try to get the disk space from disk quotas (SunOS & Solaris2 version) Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). ****************************************************************************/ -BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t euser_id; int ret; @@ -639,7 +639,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U try to get the disk space from disk quotas - OSF1 version ****************************************************************************/ -BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { int r, save_errno; struct dqblk D; @@ -705,7 +705,7 @@ try to get the disk space from disk quotas (IRIX 6.2 version) #include #include -BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t euser_id; int r; @@ -843,7 +843,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U try to get the disk space from disk quotas - default version ****************************************************************************/ -BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { int r; struct dqblk D; diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index fd69521d4e..b774947d60 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -168,46 +168,6 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups) return ngroups; } -/**************************************************************************** - Delete a SID token. -****************************************************************************/ - -void delete_nt_token(NT_USER_TOKEN **pptoken) -{ - if (*pptoken) { - NT_USER_TOKEN *ptoken = *pptoken; - SAFE_FREE( ptoken->user_sids ); - ZERO_STRUCTP(ptoken); - } - SAFE_FREE(*pptoken); -} - -/**************************************************************************** - Duplicate a SID token. -****************************************************************************/ - -NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) -{ - NT_USER_TOKEN *token; - - if (!ptoken) - return NULL; - - if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) - return NULL; - - ZERO_STRUCTP(token); - - if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) { - SAFE_FREE(token); - return NULL; - } - - token->num_sids = ptoken->num_sids; - - return token; -} - /**************************************************************************** Initialize the groups a user belongs to. ****************************************************************************/ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f6296201ae..49fbee2607 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -533,7 +533,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups, - guest); + guest, NULL); /* * New code to check if there's a share security descripter diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index ae287cca76..b33c9ede17 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -181,7 +181,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) if (vuser && vuser->guest) is_guest = True; - token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest); + token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest, NULL); must_free_token = True; } @@ -367,6 +367,75 @@ BOOL unbecome_user(void) return True; } +/***************************************************************** + Convert the suplimentary SIDs returned in a netlogon into UNIX + group gid_t's. Add to the total group array. +*****************************************************************/ + +void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER_TOKEN **pptok) +{ + int total_groups; + int current_n_groups = *n_groups; + gid_t *final_groups = NULL; + size_t i; + NT_USER_TOKEN *ptok = *pptok; + NT_USER_TOKEN *new_tok = NULL; + + if (!ptok || (ptok->num_sids == 0)) + return; + + new_tok = dup_nt_token(ptok); + if (!new_tok) { + DEBUG(0,("add_supplementary_nt_login_groups: Failed to malloc new token\n")); + return; + } + /* Leave the allocated space but empty the number of SIDs. */ + new_tok->num_sids = 0; + + total_groups = current_n_groups + ptok->num_sids; + + final_groups = (gid_t *)malloc(total_groups * sizeof(gid_t)); + if (!final_groups) { + DEBUG(0,("add_supplementary_nt_login_groups: Failed to malloc new groups.\n")); + delete_nt_token(&new_tok); + return; + } + + memcpy(final_groups, *pp_groups, current_n_groups * sizeof(gid_t)); + for (i = 0; i < ptok->num_sids; i++) { + enum SID_NAME_USE sid_type; + gid_t new_grp; + + if (sid_to_gid(&ptok->user_sids[i], &new_grp, &sid_type)) { + /* + * Don't add the gid_t if it is already in the current group + * list. Some UNIXen don't like the same group more than once. + */ + int j; + + for (j = 0; j < current_n_groups; j++) + if (final_groups[j] == new_grp) + break; + + if ( j == current_n_groups) { + /* Group not already present. */ + final_groups[current_n_groups++] = new_grp; + } + } else { + /* SID didn't map. Copy to the new token to be saved. */ + sid_copy(&new_tok->user_sids[new_tok->num_sids++], &ptok->user_sids[i]); + } + } + + SAFE_FREE(*pp_groups); + *pp_groups = final_groups; + *n_groups = current_n_groups; + + /* Replace the old token with the truncated one. */ + delete_nt_token(&ptok); + *pptok = new_tok; +} + /***************************************************************** *THE CANONICAL* convert name to SID function. Tries winbind first - then uses local lookup. -- cgit From c42bdbdacec8f9d4fe14ffba6e14778b691a6ff2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 4 Nov 2001 04:58:17 +0000 Subject: Fix segfault. sup_tok might not always be with us. (This used to be commit 1f409a1f3fb0906f1ff985b96bb7a65f56253046) --- source3/smbd/password.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 429d72b4e5..f0fec9b796 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -170,9 +170,11 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, } } - /* Now add the additional SIDs from the supplimentary token. */ - for (i = 0; i < sup_tok->num_sids; i++) - sid_copy( &psids[psid_ndx++], &sup_tok->user_sids[i] ); + if (sup_tok) { + /* Now add the additional SIDs from the supplimentary token. */ + for (i = 0; i < sup_tok->num_sids; i++) + sid_copy( &psids[psid_ndx++], &sup_tok->user_sids[i] ); + } /* * Finally add the "standard" SIDs. -- cgit From 740d6f5dd60bef72037ed5fcd7b2192af22c2e41 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 4 Nov 2001 18:26:53 +0000 Subject: a big one: - old mangle code has gone, the new one based on tdb seem resonably ok probably the valid.dat table need to be updated to treat wild chars as invalid ones (work ok without it) - a LOT of new string manipulation function for unicode, they are somewhat tested but a review would not be bad - some new function I will need for the new unix_convert function I'm writing, this will be renamed filename_convert and use only unicode strings. - charconv, I attached a comment, if someone wnat to look if I'm right or just was hacking to late in the night to make a sane one :) of course any bug is my responsibility an will be pleased to see patches if you find any. :-) Simo. (This used to be commit ee19f7efb6ea9216fc91cf112ac1afa691983e9d) --- source3/smbd/mangle.c | 1333 +++++++++---------------------------------------- 1 file changed, 249 insertions(+), 1084 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 5c737ea656..cf2964790e 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1,8 +1,8 @@ /* Unix SMB/Netbios implementation. - Version 1.9. - Name mangling - Copyright (C) Andrew Tridgell 1992-1998 + Version 3.0 + Name mangling with persistent tdb + Copyright (C) Simo Sorce 2001 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 @@ -19,31 +19,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* -------------------------------------------------------------------------- ** - * Notable problems... - * - * March/April 1998 CRH - * - Many of the functions in this module overwrite string buffers passed to - * them. This causes a variety of problems and is, generally speaking, - * dangerous and scarry. See the kludge notes in name_map_mangle() - * below. - * - It seems that something is calling name_map_mangle() twice. The - * first call is probably some sort of test. Names which contain - * illegal characters are being doubly mangled. I'm not sure, but - * I'm guessing the problem is in server.c. - * - * -------------------------------------------------------------------------- ** - */ - -/* -------------------------------------------------------------------------- ** - * History... - * - * March/April 1998 CRH - * Updated a bit. Rewrote is_mangled() to be a bit more selective. - * Rewrote the mangled name cache. Added comments here and there. - * &c. - * -------------------------------------------------------------------------- ** - */ +/**************************************************************************** + Rewritten from scrach in 2001 by Simo Sorce + ****************************************************************************/ #include "includes.h" @@ -55,951 +33,9 @@ extern int case_default; /* Are conforming 8.3 names all upper or lower? */ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ - -/* -------------------------------------------------------------------------- ** - * Other stuff... - * - * magic_char - This is the magic char used for mangling. It's - * global. There is a call to lp_magicchar() in server.c - * that is used to override the initial value. - * - * MANGLE_BASE - This is the number of characters we use for name mangling. - * - * basechars - The set characters used for name mangling. This - * is static (scope is this file only). - * - * mangle() - Macro used to select a character from basechars (i.e., - * mangle(n) will return the nth digit, modulo MANGLE_BASE). - * - * chartest - array 0..255. The index range is the set of all possible - * values of a byte. For each byte value, the content is a - * two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK, - * below. - * - * ct_initialized - False until the chartest array has been initialized via - * a call to init_chartest(). - * - * BASECHAR_MASK - Masks the upper nibble of a one-byte value. - * - * ILLEGAL_MASK - Masks the lower nibble of a one-byte value. - * - * isbasecahr() - Given a character, check the chartest array to see - * if that character is in the basechars set. This is - * faster than using strchr_m(). - * - * isillegal() - Given a character, check the chartest array to see - * if that character is in the illegal characters set. - * This is faster than using strchr_m(). - * - * mangled_cache - Cache header used for storing mangled -> original - * reverse maps. - * - * mc_initialized - False until the mangled_cache structure has been - * initialized via a call to reset_mangled_cache(). - * - * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the - * cache. A value of 0 indicates "infinite". - * - * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the - * cache. When the cache was kept as an array of 256 - * byte strings, the default cache size was 50 entries. - * This required a fixed 12.5Kbytes of memory. The - * mangled stack parameter is no longer used (though - * this might change). We're now using a fixed 16Kbyte - * maximum cache size. This will probably be much more - * than 50 entries. - */ - char magic_char = '~'; - -#if 0 - - - - - -static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; -#define MANGLE_BASE ( (sizeof(basechars)/sizeof(char)) - 1 ) - -static unsigned char chartest[256] = { 0 }; -static BOOL ct_initialized = False; - -#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) -#define BASECHAR_MASK 0xf0 -#define ILLEGAL_MASK 0x0f -#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) -#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) - -static ubi_cacheRoot mangled_cache[1] = {{ { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 }}; -static BOOL mc_initialized = False; -#define MANGLED_CACHE_MAX_ENTRIES 0 -#define MANGLED_CACHE_MAX_MEMORY 16384 - - -/* -------------------------------------------------------------------------- ** - * Functions... - */ - -/* ************************************************************************** ** - * Initialize the static character test array. - * - * Input: none - * - * Output: none - * - * Notes: This function changes (loads) the contents of the - * array. The scope of is this file. - * - * ************************************************************************** ** - */ -static void init_chartest( void ) - { - char *illegalchars = "*\\/?<>|\":"; - unsigned char *s; - - memset( (char *)chartest, '\0', 256 ); - - for( s = (unsigned char *)illegalchars; *s; s++ ) - chartest[*s] = ILLEGAL_MASK; - - for( s = (unsigned char *)basechars; *s; s++ ) - chartest[*s] |= BASECHAR_MASK; - - ct_initialized = True; - } /* init_chartest */ - -/* ************************************************************************** ** - * Return True if a name is a special msdos reserved name. - * - * Input: fname - String containing the name to be tested. - * - * Output: True, if the name matches one of the list of reserved names. - * - * Notes: This is a static function called by is_8_3(), below. - * - * ************************************************************************** ** - */ -static BOOL is_reserved_msdos( char *fname ) - { - char upperFname[13]; - char *p; - - StrnCpy (upperFname, fname, 12); - - /* lpt1.txt and con.txt etc are also illegal */ - p = strchr_m(upperFname,'.'); - if( p ) - *p = '\0'; - - strupper( upperFname ); - p = upperFname + 1; - switch( upperFname[0] ) - { - case 'A': - if( 0 == strcmp( p, "UX" ) ) - return( True ); - break; - case 'C': - if( (0 == strcmp( p, "LOCK$" )) - || (0 == strcmp( p, "ON" )) - || (0 == strcmp( p, "OM1" )) - || (0 == strcmp( p, "OM2" )) - || (0 == strcmp( p, "OM3" )) - || (0 == strcmp( p, "OM4" )) - ) - return( True ); - break; - case 'L': - if( (0 == strcmp( p, "PT1" )) - || (0 == strcmp( p, "PT2" )) - || (0 == strcmp( p, "PT3" )) - ) - return( True ); - break; - case 'N': - if( 0 == strcmp( p, "UL" ) ) - return( True ); - break; - case 'P': - if( 0 == strcmp( p, "RN" ) ) - return( True ); - break; - } - - return( False ); - } /* is_reserved_msdos */ - -/* ************************************************************************** ** - * Determine whether or not a given name contains illegal characters, even - * long names. - * - * Input: name - The name to be tested. - * - * Output: True if an illegal character was found in , else False. - * - * Notes: This is used to test a name on the host system, long or short, - * for characters that would be illegal on most client systems, - * particularly DOS and Windows systems. Unix and AmigaOS, for - * example, allow a filenames which contain such oddities as - * quotes ("). If a name is found which does contain an illegal - * character, it is mangled even if it conforms to the 8.3 - * format. - * - * ************************************************************************** ** - */ -static BOOL is_illegal_name( char *name ) - { - unsigned char *s; - - if( !name ) - return( True ); - - if( !ct_initialized ) - init_chartest(); - - s = (unsigned char *)name; - while( *s ) - { - if( *s>0x7F && isillegal( *s ) ) - return( True ); - else - s++; - } - - return( False ); - } /* is_illegal_name */ - -/* ************************************************************************** ** - * Return True if the name *could be* a mangled name. - * - * Input: s - A path name - in UNIX pathname format. - * - * Output: True if the name matches the pattern described below in the - * notes, else False. - * - * Notes: The input name is *not* tested for 8.3 compliance. This must be - * done separately. This function returns true if the name contains - * a magic character followed by excactly two characters from the - * basechars list (above), which in turn are followed either by the - * nul (end of string) byte or a dot (extension) or by a '/' (end of - * a directory name). - * - * ************************************************************************** ** - */ -BOOL is_mangled( char *s ) - { - char *magic; - - if( !ct_initialized ) - init_chartest(); - - magic = strchr_m( s, magic_char ); - while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ - { - if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ - && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ - && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ - return( True ); /* If all above, then true, */ - magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ - } - return( False ); - } /* is_mangled */ - -/* ************************************************************************** ** - * Return True if the name is a valid DOS name in 8.3 DOS format. - * - * Input: fname - File name to be checked. - * check_case - If True, and if case_mangle is True, then the - * name will be checked to see if all characters - * are the correct case. See case_mangle and - * case_default above. - * - * Output: True if the name is a valid DOS name, else FALSE. - * - * ************************************************************************** ** - */ -BOOL is_8_3( char *fname, BOOL check_case ) - { - int len; - int l; - char *p; - char *dot_pos; - char *slash_pos = strrchr_m( fname, '/' ); - - /* If there is a directory path, skip it. */ - if( slash_pos ) - fname = slash_pos + 1; - len = strlen( fname ); - - DEBUG( 5, ( "Checking %s for 8.3\n", fname ) ); - - /* Can't be 0 chars or longer than 12 chars */ - if( (len == 0) || (len > 12) ) - return( False ); - - /* Mustn't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ - if( is_reserved_msdos( fname ) ) - return( False ); - - /* Check that all characters are the correct case, if asked to do so. */ - if( check_case && case_mangle ) - { - switch( case_default ) - { - case CASE_LOWER: - if( strhasupper( fname ) ) - return(False); - break; - case CASE_UPPER: - if( strhaslower( fname ) ) - return(False); - break; - } - } - - /* Can't contain invalid dos chars */ - /* Windows use the ANSI charset. - But filenames are translated in the PC charset. - This Translation may be more or less relaxed depending - the Windows application. */ - - /* %%% A nice improvment to name mangling would be to translate - filename to ANSI charset on the smb server host */ - - p = fname; - dot_pos = NULL; - while( *p ) - { - if( *p == '.' && !dot_pos ) - dot_pos = (char *)p; - /*else - if( !isdoschar( *p ) ) - return( False );*/ - p++; - } - - /* no dot and less than 9 means OK */ - if( !dot_pos ) - return( len <= 8 ); - - l = PTR_DIFF( dot_pos, fname ); - - /* base must be at least 1 char except special cases . and .. */ - if( l == 0 ) - return( 0 == strcmp( fname, "." ) || 0 == strcmp( fname, ".." ) ); - - /* base can't be greater than 8 */ - if( l > 8 ) - return( False ); - - /* see smb.conf(5) for a description of the 'strip dot' parameter. */ - if( lp_strip_dot() - && len - l == 1 - && !strchr_m( dot_pos + 1, '.' ) ) - { - *dot_pos = 0; - return( True ); - } - - /* extension must be between 1 and 3 */ - if( (len - l < 2 ) || (len - l > 4) ) - return( False ); - - /* extensions may not have a dot */ - if( strchr_m( dot_pos+1, '.' ) ) - return( False ); - - /* must be in 8.3 format */ - return( True ); - } /* is_8_3 */ - - -/* ************************************************************************** ** - * Compare two cache keys and return a value indicating their ordinal - * relationship. - * - * Input: ItemPtr - Pointer to a comparison key. In this case, this will - * be a mangled name string. - * NodePtr - Pointer to a node in the cache. The node structure - * will be followed in memory by a mangled name string. - * - * Output: A signed integer, as follows: - * (x < 0) <==> Key1 less than Key2 - * (x == 0) <==> Key1 equals Key2 - * (x > 0) <==> Key1 greater than Key2 - * - * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for - * more info. - * - * ************************************************************************** ** - */ -static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) - { - char *Key1 = (char *)ItemPtr; - char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); - - return( StrCaseCmp( Key1, Key2 ) ); - } /* cache_compare */ - -/* ************************************************************************** ** - * Free a cache entry. - * - * Input: WarrenZevon - Pointer to the entry that is to be returned to - * Nirvana. - * Output: none. - * - * Notes: This function gets around the possibility that the standard - * free() function may be implemented as a macro, or other evil - * subversions (oh, so much fun). - * - * ************************************************************************** ** - */ -static void cache_free_entry( ubi_trNodePtr WarrenZevon ) - { - ZERO_STRUCTP(WarrenZevon); - SAFE_FREE( WarrenZevon ); - } /* cache_free_entry */ - -/* ************************************************************************** ** - * Initializes or clears the mangled cache. - * - * Input: none. - * Output: none. - * - * Notes: There is a section below that is commented out. It shows how - * one might use lp_ calls to set the maximum memory and entry size - * of the cache. You might also want to remove the constants used - * in ubi_cacheInit() and replace them with lp_ calls. If so, then - * the calls to ubi_cacheSetMax*() would be moved into the else - * clause. Another option would be to pass in the max_entries and - * max_memory values as parameters. crh 09-Apr-1998. - * - * ************************************************************************** ** - */ -void reset_mangled_cache( void ) - { - if( !mc_initialized ) - { - (void)ubi_cacheInit( mangled_cache, - cache_compare, - cache_free_entry, - MANGLED_CACHE_MAX_ENTRIES, - MANGLED_CACHE_MAX_MEMORY ); - mc_initialized = True; - } - else - { - (void)ubi_cacheClear( mangled_cache ); - } - - /* - (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); - (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); - */ - } /* reset_mangled_cache */ - - -/* ************************************************************************** ** - * Add a mangled name into the cache. - * - * Notes: If the mangled cache has not been initialized, then the - * function will simply fail. It could initialize the cache, - * but that's not the way it was done before I changed the - * cache mechanism, so I'm sticking with the old method. - * - * If the extension of the raw name maps directly to the - * extension of the mangled name, then we'll store both names - * *without* extensions. That way, we can provide consistent - * reverse mangling for all names that match. The test here is - * a bit more careful than the one done in earlier versions of - * mangle.c: - * - * - the extension must exist on the raw name, - * - it must be all lower case - * - it must match the mangled extension (to prove that no - * mangling occurred). - * - * crh 07-Apr-1998 - * - * ************************************************************************** ** - */ -static void cache_mangled_name( char *mangled_name, char *raw_name ) - { - ubi_cacheEntryPtr new_entry; - char *s1; - char *s2; - size_t mangled_len; - size_t raw_len; - size_t i; - - /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) - return; - - /* Init the string lengths. */ - mangled_len = strlen( mangled_name ); - raw_len = strlen( raw_name ); - - /* See if the extensions are unmangled. If so, store the entry - * without the extension, thus creating a "group" reverse map. - */ - s1 = strrchr_m( mangled_name, '.' ); - if( s1 && (s2 = strrchr_m( raw_name, '.' )) ) - { - i = 1; - while( s1[i] && (tolower( s1[1] ) == s2[i]) ) - i++; - if( !s1[i] && !s2[i] ) - { - mangled_len -= i; - raw_len -= i; - } - } - - /* Allocate a new cache entry. If the allocation fails, just return. */ - i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; - new_entry = malloc( i ); - if( !new_entry ) - return; - - /* Fill the new cache entry, and add it to the cache. */ - s1 = (char *)(new_entry + 1); - s2 = (char *)&(s1[mangled_len + 1]); - (void)StrnCpy( s1, mangled_name, mangled_len ); - (void)StrnCpy( s2, raw_name, raw_len ); - ubi_cachePut( mangled_cache, i, new_entry, s1 ); - } /* cache_mangled_name */ - -/* ************************************************************************** ** - * Check for a name on the mangled name stack - * - * Input: s - Input *and* output string buffer. - * - * Output: True if the name was found in the cache, else False. - * - * Notes: If a reverse map is found, the function will overwrite the string - * space indicated by the input pointer . This is frightening. - * It should be rewritten to return NULL if the long name was not - * found, and a pointer to the long name if it was found. - * - * ************************************************************************** ** - */ - -BOOL check_mangled_cache( char *s ) -{ - ubi_cacheEntryPtr FoundPtr; - char *ext_start = NULL; - char *found_name; - char *saved_ext = NULL; - - /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) - return( False ); - - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - - /* If we didn't find the name *with* the extension, try without. */ - if( !FoundPtr ) - { - ext_start = strrchr_m( s, '.' ); - if( ext_start ) - { - if((saved_ext = strdup(ext_start)) == NULL) - return False; - - *ext_start = '\0'; - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - /* - * At this point s is the name without the - * extension. We re-add the extension if saved_ext - * is not null, before freeing saved_ext. - */ - } - } - - /* Okay, if we haven't found it we're done. */ - if( !FoundPtr ) - { - if(saved_ext) - { - /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); - SAFE_FREE(saved_ext); - } - return( False ); - } - - /* If we *did* find it, we need to copy it into the string buffer. */ - found_name = (char *)(FoundPtr + 1); - found_name += (strlen( found_name ) + 1); - - DEBUG( 3, ("Found %s on mangled stack ", s) ); - - (void)pstrcpy( s, found_name ); - if( saved_ext ) - { - /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); - SAFE_FREE(saved_ext); - } - - DEBUG( 3, ("as %s\n", s) ); - - return( True ); -} /* check_mangled_cache */ - - -/* ************************************************************************** ** - * Used only in do_fwd_mangled_map(), below. - * ************************************************************************** ** - */ -static char *map_filename( char *s, /* This is null terminated */ - char *pattern, /* This isn't. */ - int len ) /* This is the length of pattern. */ - { - static pstring matching_bit; /* The bit of the string which matches */ - /* a * in pattern if indeed there is a * */ - char *sp; /* Pointer into s. */ - char *pp; /* Pointer into p. */ - char *match_start; /* Where the matching bit starts. */ - pstring pat; - - StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */ - pstrcpy( matching_bit, "" ); /* Match but no star gets this. */ - pp = pat; /* Initialize the pointers. */ - sp = s; - - if( strequal(s, ".") || strequal(s, "..")) - { - return NULL; /* Do not map '.' and '..' */ - } - - if( (len == 1) && (*pattern == '*') ) - { - return NULL; /* Impossible, too ambiguous for */ - } /* words! */ - - while( (*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp) /* The two match. */ - && (*pp != '*') ) /* No wildcard. */ - { - sp++; /* Keep looking. */ - pp++; - } - - if( !*sp && !*pp ) /* End of pattern. */ - return( matching_bit ); /* Simple match. Return empty string. */ - - if( *pp == '*' ) - { - pp++; /* Always interrested in the chacter */ - /* after the '*' */ - if( !*pp ) /* It is at the end of the pattern. */ - { - StrnCpy( matching_bit, s, sp-s ); - return( matching_bit ); - } - else - { - /* The next character in pattern must match a character further */ - /* along s than sp so look for that character. */ - match_start = sp; - while( (*sp) /* Not the end of s. */ - && (*sp != *pp) ) /* Not the same */ - sp++; /* Keep looking. */ - if( !*sp ) /* Got to the end without a match. */ - { - return( NULL ); - } /* Still hope for a match. */ - else - { - /* Now sp should point to a matching character. */ - StrnCpy(matching_bit, match_start, sp-match_start); - /* Back to needing a stright match again. */ - while( (*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp) ) /* The two match. */ - { - sp++; /* Keep looking. */ - pp++; - } - if( !*sp && !*pp ) /* Both at end so it matched */ - return( matching_bit ); - else - return( NULL ); - } - } - } - return( NULL ); /* No match. */ - } /* map_filename */ - - -/* ************************************************************************** ** - * MangledMap is a series of name pairs in () separated by spaces. - * If s matches the first of the pair then the name given is the - * second of the pair. A * means any number of any character and if - * present in the second of the pair as well as the first the - * matching part of the first string takes the place of the * in the - * second. - * - * I wanted this so that we could have RCS files which can be used - * by UNIX and DOS programs. My mapping string is (RCS rcs) which - * converts the UNIX RCS file subdirectory to lowercase thus - * preventing mangling. - * - * (I think Andrew wrote the above, but I'm not sure. -- CRH) - * - * See 'mangled map' in smb.conf(5). - * - * ************************************************************************** ** - */ -static void do_fwd_mangled_map(char *s, char *MangledMap) - { - char *start=MangledMap; /* Use this to search for mappings. */ - char *end; /* Used to find the end of strings. */ - char *match_string; - pstring new_string; /* Make up the result here. */ - char *np; /* Points into new_string. */ - - DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) ); - while( *start ) - { - while( (*start) && (*start != '(') ) - start++; - if( !*start ) - continue; /* Always check for the end. */ - start++; /* Skip the ( */ - end = start; /* Search for the ' ' or a ')' */ - DEBUG( 5, ("Start of first in pair '%s'\n", start) ); - while( (*end) && !((*end == ' ') || (*end == ')')) ) - end++; - if( !*end ) - { - start = end; - continue; /* Always check for the end. */ - } - DEBUG( 5, ("End of first in pair '%s'\n", end) ); - if( (match_string = map_filename( s, start, end-start )) ) - { - DEBUG( 5, ("Found a match\n") ); - /* Found a match. */ - start = end + 1; /* Point to start of what it is to become. */ - DEBUG( 5, ("Start of second in pair '%s'\n", start) ); - end = start; - np = new_string; - while( (*end) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*') ) /* Not a wildcard. */ - *np++ = *end++; - if( !*end ) - { - start = end; - continue; /* Always check for the end. */ - } - if( *end == '*' ) - { - pstrcpy( np, match_string ); - np += strlen( match_string ); - end++; /* Skip the '*' */ - while( (*end) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*') ) /* Not a wildcard. */ - *np++ = *end++; - } - if( !*end ) - { - start = end; - continue; /* Always check for the end. */ - } - *np++ = '\0'; /* NULL terminate it. */ - DEBUG(5,("End of second in pair '%s'\n", end)); - pstrcpy( s, new_string ); /* Substitute with the new name. */ - DEBUG( 5, ("s is now '%s'\n", s) ); - } - start = end; /* Skip a bit which cannot be wanted anymore. */ - start++; - } - } /* do_fwd_mangled_map */ - -/***************************************************************************** - * do the actual mangling to 8.3 format - * the buffer must be able to hold 13 characters (including the null) - ***************************************************************************** - */ -void mangle_name_83( char *s) - { - int csum; - char *p; - char extension[4]; - char base[9]; - int baselen = 0; - int extlen = 0; - - extension[0] = 0; - base[0] = 0; - - p = strrchr_m(s,'.'); - if( p && (strlen(p+1) < (size_t)4) ) - { - BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ - - if( all_normal && p[1] != 0 ) - { - *p = 0; - csum = str_checksum( s ); - *p = '.'; - } - else - csum = str_checksum(s); - } - else - csum = str_checksum(s); - - strupper( s ); - - DEBUG( 5, ("Mangling name %s to ",s) ); - - if( p ) - { - if( p == s ) - safe_strcpy( extension, "___", 3 ); - else - { - *p++ = 0; - while( *p && extlen < 3 ) - { - if( /*isdoschar (*p) &&*/ *p != '.' ) - extension[extlen++] = p[0]; - p++; - } - extension[extlen] = 0; - } - } - - p = s; - - while( *p && baselen < 5 ) - { - if( /*isdoschar( *p ) &&*/ *p != '.' ) - base[baselen++] = p[0]; - p++; - } - base[baselen] = 0; - - csum = csum % (MANGLE_BASE*MANGLE_BASE); - - (void)slprintf(s, 12, "%s%c%c%c", - base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); - - if( *extension ) - { - (void)pstrcat( s, "." ); - (void)pstrcat( s, extension ); - } - - DEBUG( 5, ( "%s\n", s ) ); - - } /* mangle_name_83 */ - -/***************************************************************************** - * Convert a filename to DOS format. Return True if successful. - * - * Input: OutName - Source *and* destination buffer. - * - * NOTE that OutName must point to a memory space that - * is at least 13 bytes in size! - * - * need83 - If False, name mangling will be skipped unless the - * name contains illegal characters. Mapping will still - * be done, if appropriate. This is probably used to - * signal that a client does not require name mangling, - * thus skipping the name mangling even on shares which - * have name-mangling turned on. - * cache83 - If False, the mangled name cache will not be updated. - * This is usually used to prevent that we overwrite - * a conflicting cache entry prematurely, i.e. before - * we know whether the client is really interested in the - * current name. (See PR#13758). UKD. - * snum - Share number. This identifies the share in which the - * name exists. - * - * Output: Returns False only if the name wanted mangling but the share does - * not have name mangling turned on. - * - * **************************************************************************** - */ -BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) -{ - char *map; - DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s, %d )\n", OutName, - need83 ? "TRUE" : "FALSE", cache83 ? "TRUE" : "FALSE", snum)); - -#ifdef MANGLE_LONG_FILENAMES - if( !need83 && is_illegal_name(OutName) ) - need83 = True; -#endif - - /* apply any name mappings */ - map = lp_mangled_map(snum); - - if (map && *map) { - do_fwd_mangled_map( OutName, map ); - } - - /* check if it's already in 8.3 format */ - if (need83 && !is_8_3(OutName, True)) { - char *tmp = NULL; - - if (!lp_manglednames(snum)) { - return(False); - } - - /* mangle it into 8.3 */ - if (cache83) - tmp = strdup(OutName); - - mangle_name_83(OutName); - - if(tmp != NULL) { - cache_mangled_name(OutName, tmp); - SAFE_FREE(tmp); - } - } - - DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName)); - return(True); -} /* name_map_mangle */ - -#endif - - - - /* -------------------------------------------------------------------- */ -/* - Unix SMB/Netbios implementation. - Version 3.0 - Name mangling with persistent tdb - Copyright (C) Simo Sorce 2001 - - 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. -*/ - -#if 1 #define MANGLE_TDB_VERSION "20010927" #define MANGLE_TDB_FILE_NAME "mangle.tdb" @@ -1007,7 +43,7 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) #define LONG_PREFIX "LONG_" #define COUNTER_PREFIX "COUNTER_" #define MANGLE_COUNTER_MAX 99 -#define MANGLE_SUFFIX_SIZE 2 +#define MANGLE_SUFFIX_SIZE 3 /* "~XX" */ static TDB_CONTEXT *mangle_tdb; @@ -1063,59 +99,39 @@ static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len) return ret; } -/* trasform a ucs2 string in a dos charset string that contain only valid chars for 8.3 filenames */ -static int ucs2_to_dos83(char *dest, const smb_ucs2_t *src, int dest_len) +/* trasform in a string that contain only valid chars for win filenames */ +static void strvalid(smb_ucs2_t *src) { - int src_len, ret; - smb_ucs2_t *u2s; + if (!src || !*src) return; - u2s = (smb_ucs2_t *)malloc((strlen_w(src) + 1) * sizeof(smb_ucs2_t)); - if (!u2s) { - DEBUG(0, ("ucs2_to_dos83: out of memory!\n")); - return 0; + while (*src) { + if (!isvalid83_w(*src)) *src = UCS2_CHAR('_'); + src++; } - - src_len = strlen_w(src); - - u2s[src_len] = 0; - while (src_len--) - { - smb_ucs2_t c; - - c = src[src_len]; - if (isvalid83_w(c)) u2s[src_len] = c; - else u2s[src_len] = UCS2_CHAR('_'); - } - - ret = ucs2_to_dos(dest, u2s, dest_len); - - SAFE_FREE(u2s); - - return ret; } /* return False if something fail and * return 2 alloced unicode strings that contain prefix and extension */ -static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension) +static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension) { - size_t str_len; + size_t ext_len; smb_ucs2_t *p; - fstring ext; *extension = 0; *prefix = strdup_w(ucs2_string); if (!*prefix) { DEBUG(0,("mangle_get_prefix: out of memory!\n")); - return False; + return NT_STATUS_NO_MEMORY; } - if ((p = strrchr_wa(*prefix, '.'))) + if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) { p++; - str_len = ucs2_to_dos83(ext, p, sizeof(ext)); - if (str_len > 0 && str_len < 4) /* check extension */ + ext_len = strlen_w(p); + if ((ext_len > 0) && (ext_len < 4) + && (NT_STATUS_IS_OK(has_valid_chars(p)))) /* check extension */ { *(p - 1) = 0; *extension = strdup_w(p); @@ -1123,12 +139,11 @@ static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix { DEBUG(0,("mangle_get_prefix: out of memory!\n")); SAFE_FREE(*prefix); - return False; + return NT_STATUS_NO_MEMORY; } } } - - return True; + return NT_STATUS_OK; } @@ -1144,12 +159,18 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) BOOL ret; if (strlen_w(mangled) > 12) return NULL; - if (!strchr_wa(mangled, '~')) return NULL; - - ret = mangle_get_prefix(mangled, &pref, &ext); - if (!ret) return NULL; - - /* TODO: get out extension */ + if (!strchr_w(mangled, UCS2_CHAR('~'))) return NULL; + + /* if it is a path refuse to proceed */ + if (strchr_w(mangled, UCS2_CHAR('/'))) { + DEBUG(10, ("unmangle: cannot unmangle a path\n")); + return NULL; + } + + if (NT_STATUS_IS_ERR(mangle_get_prefix(mangled, &pref, &ext))) + return NULL; + + /* mangled names are stored lowercase only */ strlower_w(pref); /* set search key */ muf_len = ucs2_to_dos(mufname, pref, sizeof(mufname)); @@ -1205,7 +226,12 @@ done: } /* unmangled must contain only the file name, not a path. - and MUST be ZERO terminated */ + and MUST be ZERO terminated. + return a new allocated string if the name is yet valid 8.3 + or is mangled successfully. + return null on error. + */ + smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) { TDB_DATA data, key, klock; @@ -1217,18 +243,26 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) BOOL tclock = False; char suffix[7]; smb_ucs2_t *mangled = NULL; - smb_ucs2_t *um, *ext, *p = NULL; - smb_ucs2_t temp[9]; + smb_ucs2_t *umpref, *ext, *p = NULL; size_t pref_len, ext_len, ud83_len; - uint32 n, c, pos; - /* TODO: if it is a path return a failure ?? */ - if (!mangle_get_prefix(unmangled, &um, &ext)) return NULL; + /* if it is a path refuse to proceed */ + if (strchr_w(unmangled, UCS2_CHAR('/'))) { + DEBUG(10, ("mangle: cannot mangle a path\n")); + return NULL; + } + + /* if it is a valid 8_3 do not mangle again */ + if (NT_STATUS_IS_OK(is_8_3_w(unmangled))) + return strdup_w(unmangled); + + if (NT_STATUS_IS_ERR(mangle_get_prefix(unmangled, &umpref, &ext))) + return NULL; /* test if the same is yet mangled */ /* set search key */ - pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE); + pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE); slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); key.dptr = keystr; key.dsize = strlen(keystr) + 1; @@ -1237,6 +271,9 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) data = tdb_fetch (mangle_tdb, key); if (!data.dptr) /* not found */ { + smb_ucs2_t temp[9]; + size_t len, n, c, pos; + if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST) { DEBUG(0, ("mangle: database retrieval error: %s\n", @@ -1246,24 +283,28 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) /* if not find the first free possibile mangled name */ - n = 0; + pos = strlen_w(umpref); + if ((8 - MANGLE_SUFFIX_SIZE) < pos) + pos = 8 - MANGLE_SUFFIX_SIZE; + pos++; do { - n++; - pos = 8 - n - MANGLE_SUFFIX_SIZE; + pos--; if (pos == 0) { DEBUG(0, ("mangle: unable to mangle file name!\n")); goto done; } - strncpy_w(temp, um, pos); + strncpy_w(temp, umpref, pos); temp[pos] = 0; strlower_w(temp); - ud83_len = ucs2_to_dos83(prefix, temp, sizeof(prefix)); + /* convert any invalid char into '_' */ + strvalid(temp); + ud83_len = ucs2_to_dos(prefix, temp, sizeof(prefix)); if (!ud83_len) goto done; } - while (ud83_len > 8 - (MANGLE_SUFFIX_SIZE + 1)); + while (ud83_len > 8 - MANGLE_SUFFIX_SIZE); slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix); klock.dptr = keylock; @@ -1313,7 +354,7 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) temp[pos] = UCS2_CHAR('~'); temp[pos+1] = 0; snprintf(suffix, 7, "%.6d", c); - strncat_wa(temp, &suffix[6 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE + 1); + strncat_wa(temp, &suffix[7 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE); ud83_len = ucs2_to_dos(mufname, temp, sizeof(mufname)); if (!ud83_len) goto done; @@ -1327,8 +368,8 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - data.dsize = (strlen_w(um) + 1) * sizeof (smb_ucs2_t); - data.dptr = (void *)um; + data.dsize = (strlen_w(umpref) + 1) * sizeof (smb_ucs2_t); + data.dptr = (void *)umpref; if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) { @@ -1338,7 +379,7 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) } /* store the mangled entry with long key*/ - pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE); + pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE); slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); key.dptr = keystr; key.dsize = strlen (keystr) + 1; @@ -1431,10 +472,14 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) } } + /* mangled name are returned in upper or lower case depending on + case_default value */ + strnorm_w(mangled); + done: if (tclock) tdb_chainunlock(mangle_tdb, klock); SAFE_FREE(p); - SAFE_FREE(um); + SAFE_FREE(umpref); SAFE_FREE(ext); return mangled; @@ -1443,7 +488,7 @@ done: /* non unicode compatibility functions */ -char *dos_mangle(char *dos_unmangled) +char *dos_mangle(const char *dos_unmangled) { smb_ucs2_t *in, *out; char *dos_mangled; @@ -1481,7 +526,7 @@ done: return dos_mangled; } -char *dos_unmangle(char *dos_mangled) +char *dos_unmangle(const char *dos_mangled) { smb_ucs2_t *in, *out; char *dos_unmangled; @@ -1519,18 +564,153 @@ done: return dos_unmangled; } +BOOL is_8_3(const char *fname, BOOL check_case) +{ + smb_ucs2_t *ucs2name; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; -/* backward compatibility functions */ + if (!fname || !*fname) return False; + + DEBUG(10,("is_8_3: testing [%s]\n", fname)); + + if (strlen(fname) > 12) return False; + + ucs2name = (smb_ucs2_t *)malloc(13 * sizeof(smb_ucs2_t)); + if (!ucs2name) + { + DEBUG(0,("is_8_3: out of memory!\n")); + goto done; + } + + push_ucs2(NULL, ucs2name, fname, 13, STR_TERMINATE); + ret = is_8_3_w(ucs2name); + +done: + SAFE_FREE(ucs2name); + + DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False")); + + if (NT_STATUS_IS_ERR(ret)) return False; + else return True; +} -BOOL is_mangled(char *s) +NTSTATUS is_8_3_w(const smb_ucs2_t *fname) +{ + smb_ucs2_t *pref = 0, *ext = 0, *p; + size_t plen; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; + + DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */ + + if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL; + + if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) + return NT_STATUS_OK; + + if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done; + + if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done; + plen = strlen_w(pref); + if (plen < 1 || plen > 8) goto done; + if (ext) if (strlen_w(ext) > 3) goto done; + + ret = NT_STATUS_OK; + +done: + SAFE_FREE(pref); + SAFE_FREE(ext); + return ret; +} + +NTSTATUS has_valid_chars(const smb_ucs2_t *s) +{ + NTSTATUS ret = NT_STATUS_OK; + + if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; + + DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */ + + /* CHECK: this should not be necessary if the ms wild chars + are not valid in valid.dat --- simo */ + if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL; + + while (*s) { + if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL; + s++; + } + + return ret; +} + +NTSTATUS is_valid_name(const smb_ucs2_t *fname) +{ + smb_ucs2_t *str, *p; + NTSTATUS ret = NT_STATUS_OK; + + if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; + + DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */ + + ret = has_valid_chars(fname); + if (NT_STATUS_IS_ERR(ret)) return ret; + + str = strdup_w(fname); + p = strchr_w(str, UCS2_CHAR('.')); + if (p) *p = 0; + strupper_w(str); + p = &(str[1]); + + switch(str[0]) + { + case UCS2_CHAR('A'): + if(strcmp_wa(p, "UX") == 0) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('C'): + if((strcmp_wa(p, "LOCK$") == 0) + || (strcmp_wa(p, "ON") == 0) + || (strcmp_wa(p, "OM1") == 0) + || (strcmp_wa(p, "OM2") == 0) + || (strcmp_wa(p, "OM3") == 0) + || (strcmp_wa(p, "OM4") == 0) + ) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('L'): + if((strcmp_wa(p, "PT1") == 0) + || (strcmp_wa(p, "PT2") == 0) + || (strcmp_wa(p, "PT3") == 0) + ) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('N'): + if(strcmp_wa(p, "UL") == 0) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('P'): + if(strcmp_wa(p, "RN") == 0) + ret = NT_STATUS_UNSUCCESSFUL; + break; + default: + break; + } + + SAFE_FREE(str); + return ret; +} + +BOOL is_mangled(const char *s) { smb_ucs2_t *u2, *res; size_t u2len; BOOL ret = False; - DEBUG(10,("is_mangled: testing -> [%s]\n", s)); + DEBUG(10,("is_mangled: testing [%s]\n", s)); if (!s || !*s) return False; + if ((strlen(s) > 12) || (!strchr(s, '~'))) return False; u2len = (strlen(s) + 1) * sizeof(smb_ucs2_t); u2 = (smb_ucs2_t *)malloc(u2len); @@ -1545,63 +725,48 @@ BOOL is_mangled(char *s) if (res) ret = True; SAFE_FREE(res); SAFE_FREE(u2); - DEBUG(10,("is_mangled: returning -> %s\n", ret?"True":"False")); + DEBUG(10,("is_mangled: returning [%s]\n", ret?"True":"False")); return ret; } -BOOL is_8_3(char *fname, BOOL check_case) +NTSTATUS is_mangled_w(const smb_ucs2_t *s) { - smb_ucs2_t *u2, *pref = 0, *ext = 0; - char *s1 = 0, *s2; - size_t u2len, plen; - BOOL ret = False; - - DEBUG(10,("is_8_3: testing -> [%s]\n", fname)); + smb_ucs2_t *res; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - if (!fname || !*fname) return False; - - if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) return True; + res = unmangle(s); + if (res) ret = NT_STATUS_OK; + SAFE_FREE(res); + return ret; +} - u2len = (strlen(fname) + 1) * sizeof(smb_ucs2_t); - u2 = (smb_ucs2_t *)malloc(u2len); - if (!u2) - { - DEBUG(0,("is_8_3: out of memory!\n")); - goto done; - } - s1 = (char *) malloc(u2len * 2); - if (!s1) - { - DEBUG(0,("is_8_3: out of memory!\n")); - goto done; +NTSTATUS path_has_mangled(const smb_ucs2_t *s) +{ + smb_ucs2_t *p, *f, *b; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; + + p = strdup_w(s); + if (!p) return NT_STATUS_NO_MEMORY; + trim_string_wa(p, "/", "/"); + f = b = p; + while (b) { + b = strchr_w(f, UCS2_CHAR('/')); + if (b) *b = 0; + if (NT_STATUS_IS_OK(is_mangled_w(f))) { + ret = NT_STATUS_OK; + goto done; + } + f = b + 1; } - s2 = s1 + u2len; - dos_to_ucs2(u2, fname, u2len); - - if (!mangle_get_prefix(u2, &pref, &ext)) goto done; - plen = strlen_w(pref); - if (plen < 1 || plen > 8) goto done; - if (ext) - if (strlen_w(ext) > 3) goto done; - - DEBUG(10,("pref len = %d, ext len = %d\n", pref?strlen_w(pref):0, ext?strlen_w(ext):0)); - - ucs2_to_dos(s1, u2, u2len); - ucs2_to_dos83(s2, u2, u2len); - - if (strncmp(s1, s2, u2len)) goto done; - else ret = True; - done: - SAFE_FREE(u2); - SAFE_FREE(s1); - SAFE_FREE(pref); - SAFE_FREE(ext); - - DEBUG(10,("is_8_3: returning -> %s\n", ret?"True":"False")); - return ret; + SAFE_FREE(p); + return ret; } +/* backward compatibility functions */ + void reset_mangled_cache(void) { DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n")); @@ -1687,7 +852,7 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) return True; } -#endif /* 0 */ + #if 0 /* TEST_MANGLE_CODE */ -- cgit From d876260d885ad991526544756609ea38e4867028 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Nov 2001 00:02:38 +0000 Subject: Don't put a \n on the end of the arg to exit_server() (This used to be commit dfb8566220c3e90ca2b757ea124f53aed103269e) --- source3/smbd/blocking.c | 4 ++-- source3/smbd/dir.c | 2 +- source3/smbd/ipc.c | 10 +++++----- source3/smbd/notify.c | 2 +- source3/smbd/nttrans.c | 10 +++++----- source3/smbd/oplock.c | 4 ++-- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 10 +++++----- source3/smbd/trans2.c | 6 +++--- 9 files changed, 25 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 252ae6e0ea..0d2a99b3f0 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -134,7 +134,7 @@ static void send_blocking_reply(char *outbuf, int outsize) smb_setlen(outbuf,outsize - 4); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_blocking_reply: send_smb failed.\n"); + exit_server("send_blocking_reply: send_smb failed."); } /**************************************************************************** @@ -178,7 +178,7 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat ERROR_NT(status); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("generic_blocking_lock_error: send_smb failed.\n"); + exit_server("generic_blocking_lock_error: send_smb failed."); } /**************************************************************************** diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 59c8f1e97b..1e2858ae26 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -58,7 +58,7 @@ void init_dptrs(void) dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); if (!dptr_bmap) - exit_server("out of memory in init_dptrs\n"); + exit_server("out of memory in init_dptrs"); dptrs_init = True; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 93a69255c0..4047ffa8d7 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -118,7 +118,7 @@ void send_trans_reply(char *outbuf, show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans_reply: send_smb failed.\n"); + exit_server("send_trans_reply: send_smb failed."); tot_data_sent = this_ldata; tot_param_sent = this_lparam; @@ -152,7 +152,7 @@ void send_trans_reply(char *outbuf, show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans_reply: send_smb failed.\n"); + exit_server("send_trans_reply: send_smb failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; @@ -377,7 +377,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE); if (dscnt > tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters\n"); + exit_server("invalid trans parameters"); } if (tdscnt) { @@ -416,7 +416,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = set_message(outbuf,0,0,True); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_trans: send_smb failed.\n"); + exit_server("reply_trans: send_smb failed."); } /* receive the rest of the trans packet */ @@ -457,7 +457,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int dscnt += dcnt; if (dscnt > tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters\n"); + exit_server("invalid trans parameters"); } if (pcnt) diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d333e0f75a..52df3558aa 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -61,7 +61,7 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) set_message(outbuf,18,0,False); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("change_notify_reply_packet: send_smb failed.\n"); + exit_server("change_notify_reply_packet: send_smb failed."); } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1d8d2bae3e..c68d5d101b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -91,7 +91,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e if(params_to_send == 0 && data_to_send == 0) { if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_nt_replies: send_smb failed.\n"); + exit_server("send_nt_replies: send_smb failed."); return 0; } @@ -221,7 +221,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e /* Send the packet */ if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_nt_replies: send_smb failed.\n"); + exit_server("send_nt_replies: send_smb failed."); pp += params_sent_thistime; pd += data_sent_thistime; @@ -1734,7 +1734,7 @@ due to being in oplock break state.\n" )); num_data_sofar = data_count; if (parameter_count > total_parameter_count || data_count > total_data_count) - exit_server("reply_nttrans: invalid sizes in packet.\n"); + exit_server("reply_nttrans: invalid sizes in packet."); if(setup) { memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); @@ -1757,7 +1757,7 @@ due to being in oplock break state.\n" )); of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_nttrans: send_smb failed.\n"); + exit_server("reply_nttrans: send_smb failed."); while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { BOOL ret; @@ -1785,7 +1785,7 @@ due to being in oplock break state.\n" )); num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount)); num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount)); if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) - exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n"); + exit_server("reply_nttrans2: data overflow in secondary nttrans packet"); memcpy( ¶ms[ IVAL(inbuf, smb_nts_ParameterDisplacement)], smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 340a0a3906..844e7d812a 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -571,7 +571,7 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) prepare_break_message( outbuf, fsp, False); if (!send_smb(smbd_server_fd(), outbuf)) - exit_server("oplock_break_level2: send_smb failed.\n"); + exit_server("oplock_break_level2: send_smb failed."); } /* @@ -709,7 +709,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; if (!send_smb(smbd_server_fd(), outbuf)) - exit_server("oplock_break: send_smb failed.\n"); + exit_server("oplock_break: send_smb failed."); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cf01cd2cf5..b020cdd5d7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -884,7 +884,7 @@ void process_smb(char *inbuf, char *outbuf) } else if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("process_smb: send_smb failed.\n"); + exit_server("process_smb: send_smb failed."); } trans_num++; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 54238e90e7..9ff74eae05 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1377,7 +1377,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size void fail_readraw(void) { pstring errstr; - slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)\n", + slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)", strerror(errno) ); exit_server(errstr); } @@ -1767,7 +1767,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SSVALS(outbuf,smb_vwv0,-1); outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_writebraw: send_smb failed.\n"); + exit_server("reply_writebraw: send_smb failed."); /* Now read the raw data into the buffer and write it */ if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { @@ -2467,7 +2467,7 @@ int reply_echo(connection_struct *conn, smb_setlen(outbuf,outsize - 4); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_echo: send_smb failed.\n"); + exit_server("reply_echo: send_smb failed."); } DEBUG(3,("echo %d times\n", smb_reverb)); @@ -3885,7 +3885,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_readbmpx: send_smb failed.\n"); + exit_server("reply_readbmpx: send_smb failed."); total_read += nread; startpos += nread; @@ -4041,7 +4041,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, /* We need to send both a primary and a secondary response */ smb_setlen(outbuf,outsize - 4); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_writebmpx: send_smb failed.\n"); + exit_server("reply_writebmpx: send_smb failed."); /* Now the secondary */ outsize = set_message(outbuf,1,0,True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9b0fd379cf..a5a54751c3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -65,7 +65,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, if(params_to_send == 0 && data_to_send == 0) { if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans2_replies: send_smb failed.\n"); + exit_server("send_trans2_replies: send_smb failed."); return 0; } @@ -161,7 +161,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, /* Send the packet */ if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans2_replies: send_smb failed.\n"); + exit_server("send_trans2_replies: send_smb failed."); pp += params_sent_thistime; pd += data_sent_thistime; @@ -2489,7 +2489,7 @@ int reply_trans2(connection_struct *conn, of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_trans2: send_smb failed.\n"); + exit_server("reply_trans2: send_smb failed."); while (num_data_sofar < total_data || num_params_sofar < total_params) { -- cgit From c159d0f47d05b1d1b1236e7d07dcf5423b60d66f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Nov 2001 00:42:33 +0000 Subject: Fixed compiler warnings. (This used to be commit 54e40b270208774ed71eff32f3c3b1d3b86b5aca) --- source3/smbd/mangle.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index cf2964790e..aa5c49c126 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -156,7 +156,6 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) fstring mufname; smb_ucs2_t *pref, *ext, *retstr; size_t long_len, ext_len, muf_len; - BOOL ret; if (strlen_w(mangled) > 12) return NULL; if (!strchr_w(mangled, UCS2_CHAR('~'))) return NULL; @@ -272,7 +271,7 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) if (!data.dptr) /* not found */ { smb_ucs2_t temp[9]; - size_t len, n, c, pos; + size_t c, pos; if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST) { @@ -596,7 +595,7 @@ done: NTSTATUS is_8_3_w(const smb_ucs2_t *fname) { - smb_ucs2_t *pref = 0, *ext = 0, *p; + smb_ucs2_t *pref = 0, *ext = 0; size_t plen; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; -- cgit From 9d56e23591f64d8b0f4378e64615fe018f3a6d68 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Nov 2001 01:04:45 +0000 Subject: Renamed make_user_info_for_winbindd() to be more consistent with the names of the other functions in this file. (This used to be commit 4880f37e4ee08b6363314a3fb67051a6708988d0) --- source3/smbd/auth_util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 9a99b2643e..421ab3f1e4 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -396,10 +396,10 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, Create an auth_usersupplied_data structure ****************************************************************************/ -BOOL make_user_info_for_winbind(auth_usersupplied_info **user_info, - char *username, - char *domain, - char *password) +BOOL make_user_info_winbind(auth_usersupplied_info **user_info, + char *username, + char *domain, + char *password) { unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; -- cgit From bdd5c8bd563b171082c5625603b5a32e2286d973 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Nov 2001 22:07:04 +0000 Subject: Fixed unsigned / long unsigned format missmatch. Jeremy (This used to be commit 86c2f9636635283beb8e496315a7bfac881355dd) --- source3/smbd/oplock_linux.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index f42d55d297..3f22956aa0 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -179,7 +179,7 @@ inode = %.0f. (%s)\n", return False; } - DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n", + DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); return True; @@ -197,7 +197,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fd, F_GETLEASE, 0); - dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul has kernel \ + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, state ); } @@ -208,7 +208,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, if (linux_setlease(fsp->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n", + dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, strerror(errno) ); } @@ -233,7 +233,7 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id)); - DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %ul\n", + DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)*dev, (double)*inode, *file_id)); return True; -- cgit From 3343d0281d460559f6893a136991ef6492639bbe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Nov 2001 23:47:20 +0000 Subject: Added debug in truncate, fixed warning with gcc3. Jeremy. (This used to be commit 970ec14b4ba1ccf66820384ced8442e1878c09cd) --- source3/smbd/vfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 02a78c4cd3..37cee4918b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -386,6 +386,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) int ret; release_level_2_oplocks_on_change(fsp); + DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); if ((ret = fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, len)) != -1) set_filelen_write_cache(fsp, len); -- cgit From 04a0293601189adca1beed189216bf2ba09aa174 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Nov 2001 00:21:26 +0000 Subject: Added more define bits. Fixed error in vol attributes. Jeremy. (This used to be commit eba8204bfadb176fafb686a35295a09f0f35b894) --- source3/smbd/trans2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a5a54751c3..0bc594cba1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1158,7 +1158,6 @@ static int call_trans2qfsinfo(connection_struct *conn, case SMB_QUERY_FS_ATTRIBUTE_INFO: SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - FILE_DEVICE_IS_MOUNTED| (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE); -- cgit From 00404139e1346f981859685c98869efc5d0737e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Nov 2001 01:49:57 +0000 Subject: Merge overdue changes from 2.2. Fix <4gb write problem. Jeremy. (This used to be commit 36ea09d3a041fab0854dfdc20f6ea8db7ccbec2e) --- source3/smbd/trans2.c | 69 ++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0bc594cba1..c4f76a9612 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1417,8 +1417,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case 6: return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */ + case SMB_FILE_BASIC_INFORMATION: case SMB_QUERY_FILE_BASIC_INFO: - case 1004: if (info_level == SMB_QUERY_FILE_BASIC_INFO) data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ @@ -1444,15 +1444,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; + case SMB_FILE_STANDARD_INFORMATION: case SMB_QUERY_FILE_STANDARD_INFO: - data_size = 22; - SOFF_T(pdata,0,size); + data_size = 24; + /* Fake up allocation size. */ + SOFF_T(pdata,0,SMB_ROUNDUP(size + 1, ((SMB_OFF_T)0x1000000))); SOFF_T(pdata,8,size); SIVAL(pdata,16,sbuf.st_nlink); CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; break; + case SMB_FILE_EA_INFORMATION: case SMB_QUERY_FILE_EA_INFO: data_size = 4; break; @@ -1492,6 +1495,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,len); break; + case SMB_FILE_ALLOCATION_INFORMATION: + case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_QUERY_FILE_ALLOCATION_INFO: case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; @@ -1530,39 +1535,19 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = PTR_DIFF(pdata,(*ppdata)); break; - /* - * Windows 2000 completely undocumented new SMB info levels. - * Thanks Microsoft.... sure you're working on making this - * protocol a standard.... sure you are... :-). - * Lying rat-bastards. JRA. - */ - - case 1005: - SIVAL(pdata,0,mode); - SIVAL(pdata,4,0); /* ??? */ - SOFF_T(pdata,8,size); - SIVAL(pdata,16,1); /* ??? */ - SIVAL(pdata,20,0); /* ??? */ - data_size = 24; - break; - - case 1006: - SIVAL(pdata,0,0x907); /* ??? */ - SIVAL(pdata,4,0x690000); /* ??? */ + case SMB_FILE_INTERNAL_INFORMATION: + /* This should be an index number - looks like dev/ino to me :-) */ + SIVAL(pdata,0,sbuf.st_dev); + SIVAL(pdata,4,sbuf.st_ino); data_size = 8; break; - case 1007: - SIVAL(pdata,0,0); /* ??? */ - data_size = 4; - break; - - case 1008: + case SMB_FILE_ACCESS_INFORMATION: SIVAL(pdata,0,0x12019F); /* ??? */ data_size = 4; break; - case 1009: + case SMB_FILE_NAME_INFORMATION: /* Pathname with leading '\'. */ { pstring new_fname; @@ -1576,19 +1561,23 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; } - case 1014: - SIVAL(pdata,0,0); /* ??? */ - SIVAL(pdata,4,0); /* ??? */ + case SMB_FILE_DISPOSITION_INFORMATION: + data_size = 1; + CVAL(pdata,0) = delete_pending; + break; + + case SMB_FILE_POSITION_INFORMATION: data_size = 8; + SOFF_T(pdata,0,pos); break; - case 1016: - SIVAL(pdata,0,0); /* ??? */ + case SMB_FILE_MODE_INFORMATION: + SIVAL(pdata,0,mode); data_size = 4; break; - case 1017: - SIVAL(pdata,0,0); /* ??? */ + case SMB_FILE_ALIGNMENT_INFORMATION: + SIVAL(pdata,0,0); /* No alignment needed. */ data_size = 4; break; @@ -1617,7 +1606,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } #endif - case 1021: + case SMB_FILE_ALTERNATE_NAME_INFORMATION: /* Last component of pathname. */ { size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False); @@ -1640,14 +1629,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } break; - case 1028: + case SMB_FILE_COMPRESSION_INFORMATION: SOFF_T(pdata,0,size); SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ data_size = 16; break; - case 1034: + case SMB_FILE_NETWORK_OPEN_INFORMATION: put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ @@ -1660,7 +1649,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 56; break; - case 1035: + case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: SIVAL(pdata,0,mode); SIVAL(pdata,4,0); data_size = 8; -- cgit From c517caf30566ee6bb1eb5e4abe7d622187c7414d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Nov 2001 02:17:03 +0000 Subject: Only 1mb allocate slop. Jeremy. (This used to be commit c339a99a891c9e4bbad59ee1243908c91f048834) --- source3/smbd/trans2.c | 111 +++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 56 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c4f76a9612..16db64406b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1256,48 +1256,47 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char **pparams,char **ppdata, int total_data) { - int max_data_bytes = SVAL(inbuf, smb_mdrcnt); - char *params = *pparams; - char *pdata = *ppdata; - uint16 tran_call = SVAL(inbuf, smb_setup0); - uint16 info_level; - int mode=0; - SMB_OFF_T size=0; - unsigned int data_size; - SMB_STRUCT_STAT sbuf; - pstring fname; - char *base_name; - char *p; - SMB_OFF_T pos = 0; - BOOL bad_path = False; - BOOL delete_pending = False; - int len; - time_t c_time; - - if (tran_call == TRANSACT2_QFILEINFO) { - files_struct *fsp = file_fsp(params,0); - info_level = SVAL(params,2); - - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", - info_level)); - - if(fsp && (fsp->is_directory || fsp->stat_open)) { - /* - * This is actually a QFILEINFO on a directory - * handle (returned from an NT SMB). NT5.0 seems - * to do this call. JRA. - */ - pstrcpy(fname, fsp->fsp_name); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } + int max_data_bytes = SVAL(inbuf, smb_mdrcnt); + char *params = *pparams; + char *pdata = *ppdata; + uint16 tran_call = SVAL(inbuf, smb_setup0); + uint16 info_level; + int mode=0; + SMB_OFF_T size=0; + unsigned int data_size; + SMB_STRUCT_STAT sbuf; + pstring fname; + char *base_name; + char *p; + SMB_OFF_T pos = 0; + BOOL bad_path = False; + BOOL delete_pending = False; + int len; + time_t c_time; + + if (tran_call == TRANSACT2_QFILEINFO) { + files_struct *fsp = file_fsp(params,0); + info_level = SVAL(params,2); + + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); + + if(fsp && (fsp->is_directory || fsp->stat_open)) { + /* + * This is actually a QFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + pstrcpy(fname, fsp->fsp_name); + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } delete_pending = fsp->directory_delete_on_close; } else { @@ -1444,21 +1443,21 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; - case SMB_FILE_STANDARD_INFORMATION: - case SMB_QUERY_FILE_STANDARD_INFO: - data_size = 24; - /* Fake up allocation size. */ - SOFF_T(pdata,0,SMB_ROUNDUP(size + 1, ((SMB_OFF_T)0x1000000))); - SOFF_T(pdata,8,size); - SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = 0; - CVAL(pdata,21) = (mode&aDIR)?1:0; - break; + case SMB_FILE_STANDARD_INFORMATION: + case SMB_QUERY_FILE_STANDARD_INFO: + data_size = 24; + /* Fake up allocation size. */ + SOFF_T(pdata,0,SMB_ROUNDUP(size + 1, ((SMB_OFF_T)0x100000))); + SOFF_T(pdata,8,size); + SIVAL(pdata,16,sbuf.st_nlink); + CVAL(pdata,20) = 0; + CVAL(pdata,21) = (mode&aDIR)?1:0; + break; - case SMB_FILE_EA_INFORMATION: - case SMB_QUERY_FILE_EA_INFO: - data_size = 4; - break; + case SMB_FILE_EA_INFORMATION: + case SMB_QUERY_FILE_EA_INFO: + data_size = 4; + break; /* Get the 8.3 name - used if NT SMB was negotiated. */ case SMB_QUERY_FILE_ALT_NAME_INFO: -- cgit From f56a3ea612beded266c614511aa4c451639cbe9a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 8 Nov 2001 04:41:13 +0000 Subject: Fixed incorrect debug message. )-: (This used to be commit a99d9cec7e090736ab49c91720cfd2b43e2a6f00) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b33c9ede17..e40b4707fc 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -689,7 +689,7 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) return False; } - DEBUG(10,("gid_to_uid: winbindd %s -> %u\n", + DEBUG(10,("sid_to_gid: winbindd %s -> %u\n", sid_to_string(sid_str, psid), (unsigned int)*pgid )); -- cgit From 55dfb66079333acd8e0aee91c0ee90d0a413a8e6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 8 Nov 2001 22:19:01 +0000 Subject: Change to guest logon code. This changes the way we process guest logons - we now treat them as normal logons, but set the 'guest' flag. In particular this is needed becouse Win2k will do an NTLMSSP login with username "", therefore missing our previous guest connection code - this is getting a pain to do as a special case all over the shop. Tridge: We don't seem to be setting a guest bit for NTLMSSP, in either the anonymous or authenticated case, can you take a look at this? Also some cleanups in the check_password() code that should make some of the debugs clearer. Various other minor cleanups: - change the session code to just take a vuser, rather than having to do a vuid lookup on vuser.vuid - Change some of the global_client_caps linking - Better debug in authorise_login(): show the vuid. Andrew Bartlett (This used to be commit 62f4e4bd0aef9ade653b3f8d575d2864c166ab4d) --- source3/smbd/auth.c | 67 ++++++++++++++++---------- source3/smbd/auth_util.c | 53 ++++++++++++++++++++- source3/smbd/password.c | 18 +++---- source3/smbd/reply.c | 2 - source3/smbd/session.c | 8 ++-- source3/smbd/sesssetup.c | 120 ++++++++++++++++++++++++----------------------- 6 files changed, 168 insertions(+), 100 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 4d1a566833..67f80afdda 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -63,9 +63,23 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; + const char *pdb_username; - DEBUG(3, ("check_password: Checking password for unmapped user %s\\%s@%s with the new password interface\n", - user_info->smb_name.str, user_info->client_domain.str, user_info->wksta_name.str)); + DEBUG(3, ("check_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", + user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str)); + + DEBUG(3, ("check_password: mapped user is: [%s]\\[%s]@[%s]\n", + user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str)); + + if (!NT_STATUS_IS_OK(nt_status)) { + nt_status = check_guest_security(user_info, server_info); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(5, ("check_password: checking guest-account for user [%s] suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(10, ("check_password: checking gusst-account for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } + } /* This needs to be sorted: If it doesn't match, what should we do? */ if (!check_domain_match(user_info->smb_name.str, user_info->domain.str)) { @@ -75,9 +89,9 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, if (!NT_STATUS_IS_OK(nt_status)) { nt_status = check_rhosts_security(user_info, server_info); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (rhosts) for user %s suceeded\n", user_info->smb_name.str)); + DEBUG(3, ("check_password: Password (rhosts) for user [%s] suceeded\n", user_info->smb_name.str)); } else { - DEBUG(5, ("check_password: Password (rhosts)for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + DEBUG(10, ("check_password: Password (rhosts) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); } } @@ -85,9 +99,9 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_domain_security(user_info, server_info); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (domain) for user %s suceeded\n", user_info->smb_name.str)); + DEBUG(7, ("check_password: Password (domain) for user [%s] suceeded\n", user_info->smb_name.str)); } else { - DEBUG(5, ("check_password: Password (domain) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + DEBUG(5, ("check_password: Password (domain) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); } } @@ -95,9 +109,9 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_server_security(user_info, server_info); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (server) for user %s suceeded\n", user_info->smb_name.str)); + DEBUG(7, ("check_password: Password (server) for user [%s] suceeded\n", user_info->smb_name.str)); } else { - DEBUG(5, ("check_password: Password (server) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + DEBUG(5, ("check_password: Password (server) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); } } @@ -115,32 +129,37 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, } if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (unix/smbpasswd) for user %s suceeded\n", user_info->smb_name.str)); + DEBUG(7, ("check_password: Password (unix/smbpasswd) for user [%s] suceeded\n", user_info->smb_name.str)); } else { - DEBUG(5, ("check_password: Password (unix/smbpasswd) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + DEBUG(5, ("check_password: Password (unix/smbpasswd) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); } } - - if (NT_STATUS_IS_OK(nt_status) && !done_pam) { - /* We might not be root if we are an RPC call */ - become_root(); - nt_status = smb_pam_accountcheck(pdb_get_username((*server_info)->sam_account)); - unbecome_root(); - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: PAM Account for user %s suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(3, ("check_password: PAM Account for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + if (NT_STATUS_IS_OK(nt_status)) { + pdb_username = pdb_get_username((*server_info)->sam_account); + if (!done_pam && !(*server_info)->guest) { + /* We might not be root if we are an RPC call */ + become_root(); + nt_status = smb_pam_accountcheck(pdb_username); + unbecome_root(); - } + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", pdb_username)); + } else { + DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", pdb_username, get_nt_error_msg(nt_status))); + } + } } if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_name.str)); + DEBUG(3, ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", + (*server_info)->guest ? "guest " : "", + user_info->smb_name.str, + user_info->internal_username.str, + pdb_username)); } else { - DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + DEBUG(3, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", user_info->smb_name.str, user_info->internal_username.str, get_nt_error_msg(nt_status))); ZERO_STRUCTP(server_info); } diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 421ab3f1e4..cfdf3a6acc 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -589,6 +589,27 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, return ret; } +/**************************************************************************** + Create a guest user_info blob, for anonymous authenticaion. +****************************************************************************/ + +BOOL make_user_info_guest(auth_usersupplied_info **user_info) +{ + DATA_BLOB sec_blob = data_blob(NULL, 0); + DATA_BLOB lm_blob = data_blob(NULL, 0); + DATA_BLOB nt_blob = data_blob(NULL, 0); + DATA_BLOB plaintext_blob = data_blob(NULL, 0); + uint32 ntlmssp_flags = 0; + + return make_user_info(user_info, + "","", + "","", + "", sec_blob, + nt_blob, lm_blob, + plaintext_blob, + ntlmssp_flags, True); +} + BOOL make_server_info(auth_serversupplied_info **server_info) { *server_info = malloc(sizeof(**server_info)); @@ -664,13 +685,19 @@ void free_server_info(auth_serversupplied_info **server_info) Make a server_info struct for a guest user ***************************************************************************/ -void make_server_info_guest(auth_serversupplied_info **server_info) +BOOL make_server_info_guest(auth_serversupplied_info **server_info) { struct passwd *pass = sys_getpwnam(lp_guestaccount(-1)); if (pass) { - make_server_info_pw(server_info, pass); + if (!make_server_info_pw(server_info, pass)) { + return False; + } + (*server_info)->guest = True; + return True; } + DEBUG(0,("make_server_info_guest: sys_getpwnam() failed on guest account!\n")); + return False; } /**************************************************************************** @@ -712,3 +739,25 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) return token; } + +/**************************************************************************** + Check for a guest logon (username = "") and if so create the required + structure. +****************************************************************************/ + +NTSTATUS check_guest_security(const auth_usersupplied_info *user_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + + if (!(user_info->internal_username.str + && *user_info->internal_username.str)) { + if (make_server_info_guest(server_info)) { + nt_status = NT_STATUS_OK; + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } + + return nt_status; +} diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f0fec9b796..cbd4d14681 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -66,7 +66,7 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; - session_yield(vuid); + session_yield(vuser); DLIST_REMOVE(validated_users, vuser); @@ -208,7 +208,7 @@ has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL guest) +int register_vuid(auth_serversupplied_info *server_info, char *smb_name) { user_struct *vuser = NULL; uid_t *puid; @@ -251,7 +251,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL gu vuser->vuid = next_vuid; vuser->uid = *puid; vuser->gid = *pgid; - vuser->guest = guest; + vuser->guest = server_info->guest; fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); fstrcpy(vuser->user.smb_name, smb_name); fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); @@ -260,7 +260,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL gu DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->uid, (unsigned int)vuser->gid, - vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, guest )); + vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest )); DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name)); @@ -276,7 +276,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL gu add_supplementary_nt_login_groups(&vuser->n_groups, &vuser->groups, &server_info->ptok); /* Create an NT_USER_TOKEN struct for this user. */ - vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, guest, server_info->ptok); + vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, vuser->guest, server_info->ptok); DEBUG(3,("uid %d registered to name %s\n",(int)vuser->uid,vuser->user.unix_name)); @@ -285,7 +285,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL gu DLIST_ADD(validated_users, vuser); - if (!session_claim(vuser->vuid)) { + if (!session_claim(vuser)) { DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid)); invalidate_vuid(vuser->vuid); return -1; @@ -453,8 +453,8 @@ BOOL authorise_login(int snum,char *user, DATA_BLOB password, user_struct *vuser = get_valid_user_struct(vuid); #if DEBUG_PASSWORD - DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n", - user,password.data)); + DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s vuid=%d\n", + user,password.data, vuid)); #endif *guest = False; @@ -501,7 +501,7 @@ BOOL authorise_login(int snum,char *user, DATA_BLOB password, if (user_ok(vuser->user.unix_name,snum) && password_ok(vuser->user.unix_name, password)) { fstrcpy(user, vuser->user.unix_name); - vuser->guest = False; + *guest = False; DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user)); ok = True; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9ff74eae05..98898a6551 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -35,10 +35,8 @@ extern char magic_char; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -extern userdom_struct current_user_info; extern pstring global_myname; extern int global_oplock_break; -uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; extern fstring remote_machine; diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 60c2a6e54d..9efc3e6b75 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -32,9 +32,8 @@ extern fstring remote_machine; static TDB_CONTEXT *tdb; /* called when a session is created */ -BOOL session_claim(uint16 vuid) +BOOL session_claim(user_struct *vuser) { - user_struct *vuser = get_valid_user_struct(vuid); int i; TDB_DATA data; struct sessionid sessionid; @@ -47,7 +46,7 @@ BOOL session_claim(uint16 vuid) /* don't register sessions for the guest user - its just too expensive to go through pam session code for browsing etc */ - if (strequal(vuser->user.unix_name,lp_guestaccount(-1))) { + if (vuser->guest) { return True; } @@ -119,9 +118,8 @@ BOOL session_claim(uint16 vuid) } /* called when a session is destroyed */ -void session_yield(uint16 vuid) +void session_yield(user_struct *vuser) { - user_struct *vuser = get_valid_user_struct(vuid); TDB_DATA dbuf; struct sessionid sessionid; TDB_DATA key; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c7522b3402..6e6d37c089 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -22,6 +22,8 @@ #include "includes.h" +uint32 global_client_caps = 0; + #if HAVE_KRB5 /**************************************************************************** reply to a session setup spnego negotiate packet for kerberos @@ -339,7 +341,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(nt_status_squash(nt_status)); } - sess_vuid = register_vuid(server_info, user, False); + sess_vuid = register_vuid(server_info, user); free_server_info(&server_info); @@ -370,12 +372,18 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou { int sess_vuid; char *p; + auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; + NTSTATUS nt_status; + DEBUG(3,("Got anonymous request\n")); - make_server_info_guest(&server_info); - sess_vuid = register_vuid(server_info, lp_guestaccount(-1), True); + make_user_info_guest(&user_info); + + nt_status = check_password(user_info, &server_info); + + sess_vuid = register_vuid(server_info, lp_guestaccount(-1)); free_server_info(&server_info); if (sess_vuid == -1) { @@ -405,7 +413,6 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha { uint8 *p; DATA_BLOB blob1; - extern uint32 global_client_caps; int ret; DEBUG(3,("Doing spnego session setup\n")); @@ -463,14 +470,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DATA_BLOB nt_resp; DATA_BLOB plaintext_password; pstring user; + pstring sub_user; /* Sainitised username for substituion */ fstring domain; fstring native_os; fstring native_lanman; - BOOL guest=False; static BOOL done_sesssetup = False; extern BOOL global_encrypted_passwords_negotiated; extern BOOL global_spnego_negotiated; - extern uint32 global_client_caps; extern int Protocol; extern fstring remote_machine; extern userdom_struct current_user_info; @@ -479,6 +485,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; + NTSTATUS nt_status; + BOOL doencrypt = global_encrypted_passwords_negotiated; START_PROFILE(SMBsesssetupX); @@ -626,18 +634,20 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine)); - /* If no username is sent use the guest account */ - if (!*user) { - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - } else { + if (*user) { if (global_spnego_negotiated) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } } - pstrcpy(current_user_info.smb_name,user); + if (*user) { + pstrcpy(sub_user, user); + } else { + pstrcpy(sub_user, lp_guestaccount(-1)); + } + + pstrcpy(current_user_info.smb_name,sub_user); reload_services(True); @@ -648,9 +658,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&nt_resp); data_blob_clear_free(&plaintext_password); - guest = True; - map_username(user); - add_session_user(user); + map_username(sub_user); + add_session_user(sub_user); + /* Then force it to null for the benfit of the code below */ + *user = 0; } if (done_sesssetup && lp_restrict_anonymous()) { @@ -673,50 +684,45 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_DOS(ERRDOS,ERRnoaccess); } } + + if (!make_user_info_for_reply(&user_info, + user, domain, + lm_resp, nt_resp, + plaintext_password, doencrypt)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } - if (!guest) { - NTSTATUS nt_status; - if (!make_user_info_for_reply(&user_info, - user, domain, - lm_resp, nt_resp, - plaintext_password, doencrypt)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - nt_status = check_password(user_info, &server_info); - - free_user_info(&user_info); - - data_blob_free(&lm_resp); - data_blob_free(&nt_resp); - data_blob_clear_free(&plaintext_password); - - if (!NT_STATUS_IS_OK(nt_status)) { - if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { - if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || - (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - - } - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { - if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } - /* Match WinXP and don't give the game away */ - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + nt_status = check_password(user_info, &server_info); + + free_user_info(&user_info); + + data_blob_free(&lm_resp); + data_blob_free(&nt_resp); + data_blob_clear_free(&plaintext_password); + + if (!NT_STATUS_IS_OK(nt_status)) { + if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); + make_server_info_guest(&server_info); + nt_status = NT_STATUS_OK; + } + + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + DEBUG(3,("Registered username %s for guest access\n",user)); + make_server_info_guest(&server_info); + nt_status = NT_STATUS_OK; } - - if (!guest) { - free_server_info(&server_info); - return ERROR_NT(nt_status_squash(nt_status)); - } } } + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status_squash(nt_status)); + } + /* it's ok - setup a reply */ if (Protocol < PROTOCOL_NT1) { set_message(outbuf,3,0,True); @@ -731,10 +737,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* perhaps grab OS version here?? */ } - if (guest) { + if (server_info->guest) { SSVAL(outbuf,smb_vwv2,1); - free_server_info(&server_info); - make_server_info_guest(&server_info); } else { const char *home_dir = pdb_get_homedir(server_info->sam_account); const char *username = pdb_get_username(server_info->sam_account); @@ -747,7 +751,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(server_info, user, guest); + sess_vuid = register_vuid(server_info, sub_user); free_server_info(&server_info); -- cgit From 50093d3bbda60634b76a7ec14ab60c76a4b83a42 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Nov 2001 02:44:49 +0000 Subject: fix the tree so it compiles again grumble, mumble, ... (This used to be commit 72c1af6f8d9893dd5b8b4d105b301d8c621749c6) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 6e6d37c089..23d99d7352 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -107,7 +107,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_NO_MEMORY); } - sess_vuid = register_vuid(server_info, user, False); + sess_vuid = register_vuid(server_info, user); free_server_info(&server_info); -- cgit From 395aa946cd4fb9d5e07dd2fee418045a8064dfab Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 9 Nov 2001 11:16:06 +0000 Subject: This change updates lp_guestaccount() to be a *global* paramater, rather than per-share. I beleive that almost all the things that this could have done on a per-share basis can be done with other tools, like 'force user'. Almost all the user's of this paramater used it as a global anyway... While this is one step at a time, I hope it will allow me to considerably simplfy the make_connection() code, particularly for the user-level security case. This already removes an absolute truckload of extra attempted password lookups on the guest account. Andrew Bartlett (This used to be commit 8e708332eded210c1d1fe0cebca3c9c19f054b71) --- source3/smbd/auth_util.c | 2 +- source3/smbd/password.c | 11 ++++++----- source3/smbd/sesssetup.c | 4 ++-- source3/smbd/uid.c | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index cfdf3a6acc..d442f73a93 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -687,7 +687,7 @@ void free_server_info(auth_serversupplied_info **server_info) BOOL make_server_info_guest(auth_serversupplied_info **server_info) { - struct passwd *pass = sys_getpwnam(lp_guestaccount(-1)); + struct passwd *pass = sys_getpwnam(lp_guestaccount()); if (pass) { if (!make_server_info_pw(server_info, pass)) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index cbd4d14681..b2687980ac 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -474,11 +474,12 @@ BOOL authorise_login(int snum,char *user, DATA_BLOB password, return False; } - if (!vuser->guest && user_ok(vuser->user.unix_name,snum)) { + if ((!vuser->guest && user_ok(vuser->user.unix_name,snum)) || + (vuser->guest && GUEST_OK(snum))) { fstrcpy(user,vuser->user.unix_name); - *guest = False; - DEBUG(3,("authorise_login: ACCEPTED: validated uid ok as non-guest \ -(user=%s)\n", user)); + *guest = vuser->guest; + DEBUG(3,("authorise_login: ACCEPTED: validated based on vuid as %sguest \ +(user=%s)\n", vuser->guest ? "" : "non-", user)); return True; } } @@ -577,7 +578,7 @@ and given password ok (%s)\n", user)); /* check for a normal guest connection */ if (!ok && GUEST_OK(snum)) { fstring guestname; - StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); + StrnCpy(guestname,lp_guestaccount(),sizeof(guestname)-1); if (Get_Pwnam(guestname)) { fstrcpy(user,guestname); ok = True; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 23d99d7352..e2edd5703e 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -383,7 +383,7 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou nt_status = check_password(user_info, &server_info); - sess_vuid = register_vuid(server_info, lp_guestaccount(-1)); + sess_vuid = register_vuid(server_info, lp_guestaccount()); free_server_info(&server_info); if (sess_vuid == -1) { @@ -644,7 +644,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (*user) { pstrcpy(sub_user, user); } else { - pstrcpy(sub_user, lp_guestaccount(-1)); + pstrcpy(sub_user, lp_guestaccount()); } pstrcpy(current_user_info.smb_name,sub_user); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index e40b4707fc..4329e3fb76 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -36,7 +36,7 @@ BOOL change_to_guest(void) static fstring guest_name; if (!pass) { - pass = Get_Pwnam(lp_guestaccount(-1)); + pass = sys_getpwnam(lp_guestaccount()); if (!pass) return(False); guest_uid = pass->pw_uid; -- cgit From 67f5bea4849dd51df0b9467d033fd000a129ce3f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Nov 2001 20:34:12 +0000 Subject: Fixup __LPID -> _LPID. Jeremy. (This used to be commit ab607cdf153d9187fe50af3377ece5a9fafde1b1) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 98898a6551..72e75281c6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3513,7 +3513,7 @@ uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format) if(!large_file_format) return SVAL(data,SMB_LPID_OFFSET(data_offset)); else - return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset)); + return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset)); } /**************************************************************************** -- cgit From 461641d0de74fbf0317079c3a91aaa55f2e91796 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Nov 2001 01:49:50 +0000 Subject: Use defined constants not integers. Jeremy. (This used to be commit d20949fe509c1496bc434f0fbf403f0b69ab9954) --- source3/smbd/trans2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 16db64406b..4de728c734 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1837,7 +1837,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; case SMB_SET_FILE_BASIC_INFO: - case 1004: + case SMB_FILE_BASIC_INFORMATION: { /* Patch to do this correctly from Paul Eggert . */ time_t write_time; @@ -2039,8 +2039,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || (info_level == SMB_SET_FILE_ALLOCATION_INFO) || - (info_level == 1019) || - (info_level == 1020))) { + (info_level == SMB_FILE_ALLOCATION_INFORMATION) || + (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) { /* * Only do this test if we are not explicitly * changing the size of a file. -- cgit From 5d152d24a39386a7b595f9fc157d86dff38c39dc Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 10 Nov 2001 15:21:54 +0000 Subject: fixed, moved and added some functions note the useful acnv_uxu2 and acnv_u2ux functions in charcnv.c (This used to be commit 64dde3b64fc091cda95fc4ed145595b5d79b2e01) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index aa5c49c126..44ffd155e4 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -253,7 +253,7 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) /* if it is a valid 8_3 do not mangle again */ if (NT_STATUS_IS_OK(is_8_3_w(unmangled))) - return strdup_w(unmangled); + return NULL; if (NT_STATUS_IS_ERR(mangle_get_prefix(unmangled, &umpref, &ext))) return NULL; -- cgit From e903a34b2ecf6bca515dbe57274f4186d7f3955e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Nov 2001 11:00:38 +0000 Subject: Minor updates. A small dose of const. (This used to be commit 80667cb0dd1a2cdef17711c8580af9f524971cea) --- source3/smbd/auth.c | 2 +- source3/smbd/auth_util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 67f80afdda..95c97182b8 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -36,7 +36,7 @@ static BOOL check_domain_match(char *user, char *domain) */ if (!lp_allow_trusted_domains() && - !strequal(lp_workgroup(), domain) ) { + (!strequal(lp_workgroup(), domain) || strequal("", domain))) { DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain)); return False; } else { diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index d442f73a93..3f03097de4 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -426,7 +426,7 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. We might want to add a check here and only do an LM in that case */ - SMBNTencrypt((uchar *)password, chal, local_nt_response); + SMBNTencrypt((const uchar *)password, chal, local_nt_response); local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); -- cgit From 2d07327a9595908370b901d52a85355fc668dcad Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Nov 2001 11:11:56 +0000 Subject: This extra check isn't needed, we can only get here if secuirty=domain (This used to be commit 600d83e43f61eb138115731ce089ba42d63e0924) --- source3/smbd/auth_domain.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index f20da19607..4ada7d4a56 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -36,9 +36,6 @@ NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, unsigned char trust_passwd[16]; time_t last_change_time; - if(lp_security() != SEC_DOMAIN) - return NT_STATUS_LOGON_FAILURE; - become_root(); /* -- cgit From 63a8a2ebe880b4cf893ac3e97a5de52b74a39e1c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Nov 2001 11:15:28 +0000 Subject: make sam_account_ok static. remove rudundent not null checks fix indenting (This used to be commit 3eada888fddb1f0cb7c0ed7037eb1c60e7988ad9) --- source3/smbd/auth_smbpasswd.c | 61 ++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 63c22f50b9..717e30eda7 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -166,44 +166,44 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use /* No return, we want to check the LM hash below in this case */ ntlmssp_flags &= (~(NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2)); } - + if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM2) { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); + if (smb_pwd_check_ntlmv2( user_info->nt_resp, + nt_pw, + user_info->sec_blob, user_info->smb_name.str, + user_info->client_domain.str, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(3,("smb_password_ok: NTLMv2 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; + } + } else if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM) { + if (lp_ntlm_auth()) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, - user_info->sec_blob, user_info->smb_name.str, - user_info->client_domain.str, - user_sess_key)) + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_pwd_check_ntlmv1(user_info->nt_resp, + nt_pw, user_info->sec_blob, + user_sess_key)) { return NT_STATUS_OK; } else { - DEBUG(3,("smb_password_ok: NTLMv2 password check failed\n")); + DEBUG(3,("smb_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); return NT_STATUS_WRONG_PASSWORD; } - } else if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM) { - if (lp_ntlm_auth()) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, user_info->sec_blob, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(3,("smb_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - } else { - DEBUG(2,("smb_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); + } else { + DEBUG(2,("smb_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); /* No return, we want to check the LM hash below in this case */ - } - } - + } + } + if (lm_pw == NULL) { DEBUG(3,("smb_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass))); ntlmssp_flags &= (~NTLMSSP_NEGOTIATE_OEM); @@ -242,15 +242,12 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use Do a specific test for a SAM_ACCOUNT being vaild for this connection (ie not disabled, expired and the like). ****************************************************************************/ -NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info) +static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info) { uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); char *workstation_list; time_t kickoff_time; - if (!user_info || !sampass) - return NT_STATUS_LOGON_FAILURE; - DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",pdb_get_username(sampass))); /* Quit if the account was disabled. */ -- cgit From 5edc5977866a5bfdf8e689e90b73483a7b1e3246 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Nov 2001 11:18:45 +0000 Subject: Add back the not null checks in a better place. Check the pdb_init_sam() for failure. (This used to be commit 1808cd5210258bddc349f13a7bcf20a3f46aa672) --- source3/smbd/auth_smbpasswd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 717e30eda7..70632fb5df 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -344,7 +344,13 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ uint8 user_sess_key[16]; const uint8* lm_hash; - pdb_init_sam(&sampass); + if (!user_info) { + return NT_STATUS_LOGON_FAILURE; + } + + if (!pdb_init_sam(&sampass)) { + return NT_STATUS_NO_MEMORY; + } /* get the account information */ -- cgit From 989e0409ba581eb2ed2031a72b9d32a41417f860 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Nov 2001 11:34:46 +0000 Subject: Fix up some DEBUG()s Add and fix comments Add 'const' to some more input paramaters. (This used to be commit 0c7eefcb5c5db63294d0584029e0d32cd1523e80) --- source3/smbd/auth_util.c | 54 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 3f03097de4..e6ce7d186e 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -158,13 +158,16 @@ void smb_user_control(const auth_usersupplied_info *user_info, auth_serversuppli Create an auth_usersupplied_data structure ****************************************************************************/ -BOOL make_user_info(auth_usersupplied_info **user_info, - char *smb_name, char *internal_username, - char *client_domain, char *domain, - char *wksta_name, DATA_BLOB sec_blob, - DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, - DATA_BLOB plaintext, - uint32 ntlmssp_flags, BOOL encrypted) +static BOOL make_user_info(auth_usersupplied_info **user_info, + const char *smb_name, + const char *internal_username, + const char *client_domain, + const char *domain, + const char *wksta_name, + DATA_BLOB sec_blob, + DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, + DATA_BLOB plaintext, + uint32 ntlmssp_flags, BOOL encrypted) { DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); @@ -239,14 +242,14 @@ BOOL make_user_info(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_map(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - char *wksta_name, DATA_BLOB sec_blob, + const char *smb_name, + const char *client_domain, + const char *wksta_name, DATA_BLOB sec_blob, DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, DATA_BLOB plaintext, uint32 ntlmssp_flags, BOOL encrypted) { - char *domain; + const char *domain; fstring internal_username; fstrcpy(internal_username, smb_name); map_username(internal_username); @@ -418,7 +421,7 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, generate_random_buffer(chal, 8, False); if (*password) { - SMBencrypt( (uchar *)password, chal, local_lm_response); + SMBencrypt( (const uchar *)password, chal, local_lm_response); /* This encrypts the lm_pwd feild, which actualy contains the password rather than the nt_pwd field becouse that contains nothing */ @@ -564,7 +567,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, if (plaintext_password.data) { unsigned char local_lm_response[24]; - SMBencrypt( (uchar *)plaintext_password.data, chal, local_lm_response); + SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); /* We can't do an NT hash here, as the password needs to be case insensitive */ @@ -604,23 +607,31 @@ BOOL make_user_info_guest(auth_usersupplied_info **user_info) return make_user_info(user_info, "","", "","", - "", sec_blob, + "", sec_blob, nt_blob, lm_blob, plaintext_blob, ntlmssp_flags, True); } +/*************************************************************************** + Make a user_info struct +***************************************************************************/ + BOOL make_server_info(auth_serversupplied_info **server_info) { *server_info = malloc(sizeof(**server_info)); if (!*server_info) { - DEBUG(0,("make_server_info_sam: malloc failed!\n")); + DEBUG(0,("make_server_info: malloc failed!\n")); return False; } ZERO_STRUCTP(*server_info); return True; } +/*************************************************************************** + Make (and fill) a user_info struct from a SAM_ACCOUNT +***************************************************************************/ + BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) { if (!make_server_info(server_info)) { @@ -630,12 +641,17 @@ BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *s (*server_info)->sam_fill_level = SAM_FILL_ALL; (*server_info)->sam_account = sampass; - DEBUG(5,("make_server_info_sam: made sever info for user %s\n", + DEBUG(5,("make_server_info_sam: made server info for user %s\n", pdb_get_username((*server_info)->sam_account))); return True; } -BOOL make_server_info_pw(auth_serversupplied_info **server_info, struct passwd *pwd) +/*************************************************************************** + Make (and fill) a user_info struct from a 'struct passwd' by conversion + to a SAM_ACCOUNT +***************************************************************************/ + +BOOL make_server_info_pw(auth_serversupplied_info **server_info, const struct passwd *pwd) { SAM_ACCOUNT *sampass = NULL; if (!pdb_init_sam_pw(&sampass, pwd)) { @@ -644,6 +660,10 @@ BOOL make_server_info_pw(auth_serversupplied_info **server_info, struct passwd * return make_server_info_sam(server_info, sampass); } +/*************************************************************************** + Free a user_info struct +***************************************************************************/ + void free_user_info(auth_usersupplied_info **user_info) { DEBUG(5,("attempting to free (and zero) a user_info structure\n")); -- cgit From 3d6154599a798e432360c001c25267e990f53d6d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Nov 2001 12:42:39 +0000 Subject: Kill off 'restrict anonymous' becouse it is useless in its current form. To be replaced with a real restriction in consultation with jra. (Hence why I've not touched loadparm.c). Andrew Bartlett (This used to be commit 95901449158a4ef7f95f75b22f63f6f8d43a01fe) --- source3/smbd/sesssetup.c | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e2edd5703e..6a2bfc2d97 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -571,32 +571,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, passlen2 = 0; } - if (lp_restrict_anonymous()) { - /* there seems to be no reason behind the - * differences in MS clients formatting - * various info like the domain, NativeOS, and - * NativeLanMan fields. Win95 in particular - * seems to have an extra null byte between - * the username and the domain, or the - * password length calculation is wrong, which - * throws off the string extraction routines - * below. This makes the value of domain be - * the empty string, which fails the restrict - * anonymous check further down. This - * compensates for that, and allows browsing - * to work in mixed NT and win95 environments - * even when restrict anonymous is true. AAB - * */ - dump_data(100, p, 0x70); - DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2)); - if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) { - DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n")); - DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n")); - DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n")); - passlen1 = 1; - } - } - /* Save the lanman2 password and the NT md4 password. */ if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) { @@ -664,27 +638,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, *user = 0; } - if (done_sesssetup && lp_restrict_anonymous()) { - /* tests show that even if browsing is done over - * already validated connections without a username - * and password the domain is still provided, which it - * wouldn't be if it was a purely anonymous - * connection. So, in order to restrict anonymous, we - * only deny connections that have no session - * information. If a domain has been provided, then - * it's not a purely anonymous connection. AAB */ - if (!*user && !*domain) { - DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); - - data_blob_free(&lm_resp); - data_blob_free(&nt_resp); - data_blob_clear_free(&plaintext_password); - - END_PROFILE(SMBsesssetupX); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } - } - if (!make_user_info_for_reply(&user_info, user, domain, lm_resp, nt_resp, -- cgit From 5abe3932cc9211263b2a93d58cdddb8de2d6f677 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 12 Nov 2001 00:08:30 +0000 Subject: Code duplication is bad. So add an add_signiture() function and just refernce that. (This used to be commit a82c8638576b2c2164eaf046aa529e233ffb71d6) --- source3/smbd/sesssetup.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 6a2bfc2d97..291685e9fc 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -24,6 +24,19 @@ uint32 global_client_caps = 0; +/**************************************************************************** + Add the standard 'Samba' signiture to the end of the session setup. +****************************************************************************/ +static void add_signiture(char *outbuf) +{ + char *p; + p = smb_buf(outbuf); + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); +} + #if HAVE_KRB5 /**************************************************************************** reply to a session setup spnego negotiate packet for kerberos @@ -117,11 +130,7 @@ static int reply_spnego_kerberos(connection_struct *conn, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - set_message_end(outbuf,p); + add_signiture(outbuf); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -273,7 +282,6 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, uint32 ntlmssp_command, neg_flags; NTSTATUS nt_status; int sess_vuid; - char *p; char chal[8]; auth_usersupplied_info *user_info = NULL; @@ -351,11 +359,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - set_message_end(outbuf,p); + add_signiture(outbuf); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -371,7 +375,6 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou int length, int bufsize) { int sess_vuid; - char *p; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; @@ -392,11 +395,7 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - set_message_end(outbuf,p); + add_signiture(outbuf); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -680,13 +679,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (Protocol < PROTOCOL_NT1) { set_message(outbuf,3,0,True); } else { - char *p; set_message(outbuf,3,0,True); - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - set_message_end(outbuf,p); + add_signiture(outbuf); /* perhaps grab OS version here?? */ } -- cgit From 84244244710790f2058ee90b2dc80e9c252841dd Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 12 Nov 2001 00:53:34 +0000 Subject: some bugfix and new functions, modified mangle.c to use mosltly acnv_????() functions. this should make also build farm happy (This used to be commit 8bb5cb27c2012b8967482255d48a1b48d3acd9db) --- source3/smbd/mangle.c | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 44ffd155e4..1b7f9d0c05 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -437,13 +437,12 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) } else /* FOUND */ { - p = (smb_ucs2_t *)malloc(data.dsize*sizeof(smb_ucs2_t)); + p = acnv_dosu2(data.dptr); if (!p) { DEBUG(0,("mangle: out of memory!\n")); goto done; } - dos_to_ucs2(p, data.dptr, data.dsize*sizeof(smb_ucs2_t)); } if (ext) @@ -491,18 +490,15 @@ char *dos_mangle(const char *dos_unmangled) { smb_ucs2_t *in, *out; char *dos_mangled; - size_t len; if (!dos_unmangled || !*dos_unmangled) return NULL; - len = (strlen(dos_unmangled) + 1) * sizeof(smb_ucs2_t); - in = (smb_ucs2_t *)malloc(len); + in = acnv_dosu2(dos_unmangled); if (!in) { DEBUG(0,("dos_mangle: out of memory!\n")); return NULL; } - dos_to_ucs2(in, dos_unmangled, len); out = mangle(in); if (!out) @@ -511,13 +507,12 @@ char *dos_mangle(const char *dos_unmangled) return NULL; } - dos_mangled = (char *)malloc(PSTRING_LEN); + dos_mangled = acnv_u2dos(out); if (!dos_mangled) { DEBUG(0,("dos_mangle: out of memory!\n")); goto done; } - ucs2_to_dos (dos_mangled, out, PSTRING_LEN); done: SAFE_FREE(in); @@ -529,18 +524,15 @@ char *dos_unmangle(const char *dos_mangled) { smb_ucs2_t *in, *out; char *dos_unmangled; - size_t len; if (!dos_mangled || !*dos_mangled) return NULL; - len = (strlen(dos_mangled) + 1) * sizeof(smb_ucs2_t); - in = (smb_ucs2_t *)malloc(len); + in = acnv_dosu2(dos_mangled); if (!in) { DEBUG(0,("dos_unmangle: out of memory!\n")); return NULL; } - dos_to_ucs2(in, dos_mangled, len); out = mangle(in); if (!out) @@ -549,13 +541,12 @@ char *dos_unmangle(const char *dos_mangled) return NULL; } - dos_unmangled = (char *)malloc(PSTRING_LEN); + dos_unmangled = acnv_u2dos(out); if (!dos_unmangled) { DEBUG(0,("dos_unmangle: out of memory!\n")); goto done; } - ucs2_to_dos (dos_unmangled, out, PSTRING_LEN); done: SAFE_FREE(in); @@ -574,14 +565,13 @@ BOOL is_8_3(const char *fname, BOOL check_case) if (strlen(fname) > 12) return False; - ucs2name = (smb_ucs2_t *)malloc(13 * sizeof(smb_ucs2_t)); + ucs2name = acnv_uxu2(fname); if (!ucs2name) { DEBUG(0,("is_8_3: out of memory!\n")); goto done; } - push_ucs2(NULL, ucs2name, fname, 13, STR_TERMINATE); ret = is_8_3_w(ucs2name); done: @@ -650,7 +640,7 @@ NTSTATUS is_valid_name(const smb_ucs2_t *fname) if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; - DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */ + DEBUG(10,("is_valid_name: testing\n")); /* [%s]\n", s)); */ ret = has_valid_chars(fname); if (NT_STATUS_IS_ERR(ret)) return ret; @@ -703,7 +693,6 @@ NTSTATUS is_valid_name(const smb_ucs2_t *fname) BOOL is_mangled(const char *s) { smb_ucs2_t *u2, *res; - size_t u2len; BOOL ret = False; DEBUG(10,("is_mangled: testing [%s]\n", s)); @@ -711,14 +700,12 @@ BOOL is_mangled(const char *s) if (!s || !*s) return False; if ((strlen(s) > 12) || (!strchr(s, '~'))) return False; - u2len = (strlen(s) + 1) * sizeof(smb_ucs2_t); - u2 = (smb_ucs2_t *)malloc(u2len); + u2 = acnv_dosu2(s); if (!u2) { DEBUG(0,("is_mangled: out of memory!\n")); return ret; } - dos_to_ucs2(u2, s, u2len); res = unmangle(u2); if (res) ret = True; @@ -774,7 +761,6 @@ void reset_mangled_cache(void) BOOL check_mangled_cache(char *s) { smb_ucs2_t *u2, *res; - size_t slen, u2len; BOOL ret = False; DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n")); @@ -782,15 +768,12 @@ BOOL check_mangled_cache(char *s) if (!s || !*s) return False; - slen = strlen(s); - u2len = (slen + 1) * sizeof(smb_ucs2_t); - u2 = (smb_ucs2_t *)malloc(u2len); + u2 = acnv_dosu2(s); if (!u2) { DEBUG(0,("check_mangled_cache: out of memory!\n")); return ret; } - dos_to_ucs2(u2, s, u2len); res = unmangle(u2); if (res) @@ -814,22 +797,18 @@ BOOL check_mangled_cache(char *s) void mangle_name_83(char *s) { smb_ucs2_t *u2, *res; - size_t slen, u2len; DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n")); DEBUG(10,("mangle_name_83: testing -> [%s]\n", s)); if (!s || !*s) return; - slen = strlen(s); - u2len = (slen + 1) * sizeof(smb_ucs2_t); - u2 = (smb_ucs2_t *)malloc(u2len); + u2 = acnv_dosu2(s); if (!u2) { DEBUG(0,("mangle_name_83: out of memory!\n")); return; } - dos_to_ucs2(u2, s, u2len); res = mangle(u2); if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ -- cgit From 22afba62c9add7efa0de76defd8abb9b352473e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Nov 2001 01:00:54 +0000 Subject: Fixed allocation bug in database prog. Some format fixes. Jeremy. (This used to be commit 9ff6b0c20cc88ef0bcd62a596fcb96f898b5b29d) --- source3/smbd/trans2.c | 1907 ++++++++++++++++++++++++------------------------- source3/smbd/vfs.c | 71 +- 2 files changed, 981 insertions(+), 997 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4de728c734..bf0be4c111 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2001 Extensively modified by Andrew Tridgell, 1995 @@ -37,6 +37,7 @@ extern pstring global_myname; set correctly for the type of call. HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ + static int send_trans2_replies(char *outbuf, int bufsize, char *params, int paramsize, char *pdata, int datasize) { @@ -181,10 +182,10 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params, return 0; } - /**************************************************************************** - reply to a TRANSACT2_OPEN + Reply to a TRANSACT2_OPEN. ****************************************************************************/ + static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, char **pparams, char **ppdata) @@ -289,21 +290,25 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, } /********************************************************* -* Routine to check if a given string matches exactly. -* as a special case a mask of "." does NOT match. That -* is required for correct wildcard semantics -* Case can be significant or not. + Routine to check if a given string matches exactly. + as a special case a mask of "." does NOT match. That + is required for correct wildcard semantics + Case can be significant or not. **********************************************************/ + static BOOL exact_match(char *str,char *mask, BOOL case_sig) { - if (mask[0] == '.' && mask[1] == 0) return False; - if (case_sig) return strcmp(str,mask)==0; + if (mask[0] == '.' && mask[1] == 0) + return False; + if (case_sig) + return strcmp(str,mask)==0; return strcasecmp(str,mask) == 0; } /**************************************************************************** - get a level dependent lanman2 dir entry. + Get a level dependent lanman2 dir entry. ****************************************************************************/ + static BOOL get_lanman2_dir_entry(connection_struct *conn, void *inbuf, void *outbuf, char *path_mask,int dirtype,int info_level, @@ -313,306 +318,296 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL *out_of_space, BOOL *got_exact_match, int *last_name_off) { - char *dname; - BOOL found = False; - SMB_STRUCT_STAT sbuf; - pstring mask; - pstring pathreal; - pstring fname; - char *p, *q, *pdata = *ppdata; - uint32 reskey=0; - int prev_dirpos=0; - int mode=0; - SMB_OFF_T size = 0; - uint32 len; - time_t mdate=0, adate=0, cdate=0; - char *nameptr; - BOOL was_8_3; - int nt_extmode; /* Used for NT connections instead of mode */ - BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - - *fname = 0; - *out_of_space = False; - *got_exact_match = False; - - if (!conn->dirptr) - return(False); - - p = strrchr_m(path_mask,'/'); - if(p != NULL) - { - if(p[1] == '\0') - pstrcpy(mask,"*.*"); - else - pstrcpy(mask, p+1); - } - else - pstrcpy(mask, path_mask); - - while (!found) - { - BOOL got_match; - - /* Needed if we run out of space */ - prev_dirpos = TellDir(conn->dirptr); - dname = ReadDirName(conn->dirptr); + char *dname; + BOOL found = False; + SMB_STRUCT_STAT sbuf; + pstring mask; + pstring pathreal; + pstring fname; + char *p, *q, *pdata = *ppdata; + uint32 reskey=0; + int prev_dirpos=0; + int mode=0; + SMB_OFF_T size = 0; + SMB_OFF_T allocation_size = 0; + uint32 len; + time_t mdate=0, adate=0, cdate=0; + char *nameptr; + BOOL was_8_3; + int nt_extmode; /* Used for NT connections instead of mode */ + BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); + + *fname = 0; + *out_of_space = False; + *got_exact_match = False; + + if (!conn->dirptr) + return(False); + + p = strrchr_m(path_mask,'/'); + if(p != NULL) { + if(p[1] == '\0') + pstrcpy(mask,"*.*"); + else + pstrcpy(mask, p+1); + } else + pstrcpy(mask, path_mask); + + while (!found) { + BOOL got_match; + + /* Needed if we run out of space */ + prev_dirpos = TellDir(conn->dirptr); + dname = ReadDirName(conn->dirptr); - /* - * Due to bugs in NT client redirectors we are not using - * resume keys any more - set them to zero. - * Check out the related comments in findfirst/findnext. - * JRA. - */ + /* + * Due to bugs in NT client redirectors we are not using + * resume keys any more - set them to zero. + * Check out the related comments in findfirst/findnext. + * JRA. + */ - reskey = 0; + reskey = 0; - DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n", - (long)conn->dirptr,TellDir(conn->dirptr))); + DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n", + (long)conn->dirptr,TellDir(conn->dirptr))); - if (!dname) - return(False); + if (!dname) + return(False); - pstrcpy(fname,dname); + pstrcpy(fname,dname); - if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) { - got_match = mask_match(fname, mask, case_sensitive); - } + if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) + got_match = mask_match(fname, mask, case_sensitive); - if(!got_match && !is_8_3(fname, False)) { + if(!got_match && !is_8_3(fname, False)) { - /* - * It turns out that NT matches wildcards against - * both long *and* short names. This may explain some - * of the wildcard wierdness from old DOS clients - * that some people have been seeing.... JRA. - */ + /* + * It turns out that NT matches wildcards against + * both long *and* short names. This may explain some + * of the wildcard wierdness from old DOS clients + * that some people have been seeing.... JRA. + */ - pstring newname; - pstrcpy( newname, fname); - name_map_mangle( newname, True, False, SNUM(conn)); - if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive))) - got_match = mask_match(newname, mask, case_sensitive); - } + pstring newname; + pstrcpy( newname, fname); + name_map_mangle( newname, True, False, SNUM(conn)); + if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive))) + got_match = mask_match(newname, mask, case_sensitive); + } - if(got_match) - { - BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); - if (dont_descend && !isdots) - continue; + if(got_match) { + BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); + if (dont_descend && !isdots) + continue; - pstrcpy(pathreal,conn->dirpath); - if(needslash) - pstrcat(pathreal,"/"); - pstrcat(pathreal,dname); - if (vfs_stat(conn,pathreal,&sbuf) != 0) - { - /* Needed to show the msdfs symlinks as directories */ - if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) - || !is_msdfs_link(conn, pathreal)) - { - DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", - pathreal,strerror(errno))); - continue; - } - else - { - DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal)); - sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; - } - } + pstrcpy(pathreal,conn->dirpath); + if(needslash) + pstrcat(pathreal,"/"); + pstrcat(pathreal,dname); + + if (vfs_stat(conn,pathreal,&sbuf) != 0) { + /* Needed to show the msdfs symlinks as directories */ + if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) + || !is_msdfs_link(conn, pathreal)) { + DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", + pathreal,strerror(errno))); + continue; + } else { + DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", + pathreal)); + sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; + } + } - mode = dos_mode(conn,pathreal,&sbuf); + mode = dos_mode(conn,pathreal,&sbuf); - if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); - continue; - } + if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) { + DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); + continue; + } - size = sbuf.st_size; - mdate = sbuf.st_mtime; - adate = sbuf.st_atime; - cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + size = sbuf.st_size; + allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size); + mdate = sbuf.st_mtime; + adate = sbuf.st_atime; + cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - if (lp_dos_filetime_resolution(SNUM(conn))) { - cdate &= ~1; - mdate &= ~1; - adate &= ~1; - } + if (lp_dos_filetime_resolution(SNUM(conn))) { + cdate &= ~1; + mdate &= ~1; + adate &= ~1; + } - if(mode & aDIR) - size = 0; + if(mode & aDIR) + size = 0; - DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); + DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); - found = True; - } - } + found = True; + } + } - name_map_mangle(fname,False,True,SNUM(conn)); + name_map_mangle(fname,False,True,SNUM(conn)); - p = pdata; - nameptr = p; + p = pdata; + nameptr = p; - nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; + nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; - switch (info_level) - { - case 1: - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - put_dos_date2(p,l1_fdateCreation,cdate); - put_dos_date2(p,l1_fdateLastAccess,adate); - put_dos_date2(p,l1_fdateLastWrite,mdate); - SIVAL(p,l1_cbFile,(uint32)size); - SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024)); - SSVAL(p,l1_attrFile,mode); - p += l1_achName; - nameptr = p; - p += align_string(outbuf, p, 0); - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SCVAL(nameptr, -1, len); - p += len; - break; + switch (info_level) { + case 1: + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + put_dos_date2(p,l1_fdateCreation,cdate); + put_dos_date2(p,l1_fdateLastAccess,adate); + put_dos_date2(p,l1_fdateLastWrite,mdate); + SIVAL(p,l1_cbFile,(uint32)size); + SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size); + SSVAL(p,l1_attrFile,mode); + p += l1_achName; + nameptr = p; + p += align_string(outbuf, p, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + SCVAL(nameptr, -1, len); + p += len; + break; - case 2: - /* info_level 2 */ - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - put_dos_date2(p,l2_fdateCreation,cdate); - put_dos_date2(p,l2_fdateLastAccess,adate); - put_dos_date2(p,l2_fdateLastWrite,mdate); - SIVAL(p,l2_cbFile,(uint32)size); - SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024)); - SSVAL(p,l2_attrFile,mode); - SIVAL(p,l2_cbList,0); /* No extended attributes */ - p += l2_achName; - nameptr = p; - len = srvstr_push(outbuf, p, fname, -1, - STR_NOALIGN); - SCVAL(p, -1, len); - p += len; - *p++ = 0; /* craig from unisys pointed out we need this */ - break; + case 2: + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + put_dos_date2(p,l2_fdateCreation,cdate); + put_dos_date2(p,l2_fdateLastAccess,adate); + put_dos_date2(p,l2_fdateLastWrite,mdate); + SIVAL(p,l2_cbFile,(uint32)size); + SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); + SSVAL(p,l2_attrFile,mode); + SIVAL(p,l2_cbList,0); /* No extended attributes */ + p += l2_achName; + nameptr = p; + len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN); + SCVAL(p, -1, len); + p += len; + *p++ = 0; /* craig from unisys pointed out we need this */ + break; - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - was_8_3 = is_8_3(fname, True); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; - SOFF_T(p,0,size); - SOFF_T(p,8,size); - p += 16; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; - SIVAL(p,0,0); p += 4; - if (!was_8_3) { - pstring mangled_name; - pstrcpy(mangled_name, fname); - name_map_mangle(mangled_name,True,True,SNUM(conn)); - mangled_name[12] = 0; - len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); - SSVAL(p, 0, len); - } else { - SSVAL(p,0,0); - *(p+2) = 0; - } - p += 2 + 24; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SIVAL(q,0,len); - p += len; - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + was_8_3 = is_8_3(fname, True); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SOFF_T(p,0,size); + SOFF_T(p,8,allocation_size); + p += 16; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; + SIVAL(p,0,0); p += 4; + if (!was_8_3) { + pstring mangled_name; + pstrcpy(mangled_name, fname); + name_map_mangle(mangled_name,True,True,SNUM(conn)); + mangled_name[12] = 0; + len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); + SSVAL(p, 0, len); + } else { + SSVAL(p,0,0); + *(p+2) = 0; + } + p += 2 + 24; + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + SIVAL(q,0,len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_FILE_DIRECTORY_INFO: - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; - SOFF_T(p,0,size); - SOFF_T(p,8,size); - p += 16; - SIVAL(p,0,nt_extmode); p += 4; - p += 4; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SIVAL(p, -4, len); - p += len; - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; - + case SMB_FIND_FILE_DIRECTORY_INFO: + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SOFF_T(p,0,size); + SOFF_T(p,8,allocation_size); + p += 16; + SIVAL(p,0,nt_extmode); p += 4; + p += 4; + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + SIVAL(p, -4, len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; - SOFF_T(p,0,size); - SOFF_T(p,8,size); - p += 16; - SIVAL(p,0,nt_extmode); p += 4; - p += 4; - SIVAL(p,0,0); p += 4; - - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SIVAL(p, -4, len); - p += len; - - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SOFF_T(p,0,size); + SOFF_T(p,8,allocation_size); + p += 16; + SIVAL(p,0,nt_extmode); p += 4; + p += 4; + SIVAL(p,0,0); p += 4; + + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + SIVAL(p, -4, len); + p += len; + + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_FILE_NAMES_INFO: - p += 4; - SIVAL(p,0,reskey); p += 4; - p += 4; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SIVAL(p, -4, len); - p += len; - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_NAMES_INFO: + p += 4; + SIVAL(p,0,reskey); p += 4; + p += 4; + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + SIVAL(p, -4, len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - default: - return(False); - } + default: + return(False); + } - if (PTR_DIFF(p,pdata) > space_remaining) { - /* Move the dirptr back to prev_dirpos */ - SeekDir(conn->dirptr, prev_dirpos); - *out_of_space = True; - DEBUG(9,("get_lanman2_dir_entry: out of space\n")); - return False; /* Not finished - just out of space */ - } + if (PTR_DIFF(p,pdata) > space_remaining) { + /* Move the dirptr back to prev_dirpos */ + SeekDir(conn->dirptr, prev_dirpos); + *out_of_space = True; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } - /* Setup the last_filename pointer, as an offset from base_data */ - *last_name_off = PTR_DIFF(nameptr,base_data); - /* Advance the data pointer to the next slot */ - *ppdata = p; + /* Setup the last_filename pointer, as an offset from base_data */ + *last_name_off = PTR_DIFF(nameptr,base_data); + /* Advance the data pointer to the next slot */ + *ppdata = p; - return(found); + return(found); } - /**************************************************************************** Reply to a TRANS2_FINDFIRST. @@ -839,10 +834,10 @@ static int call_trans2findfirst(connection_struct *conn, return(-1); } - /**************************************************************************** - reply to a TRANS2_FINDNEXT + Reply to a TRANS2_FINDNEXT. ****************************************************************************/ + static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1092,7 +1087,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", } /**************************************************************************** - reply to a TRANS2_QFSINFO (query filesystem info) + Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ static int call_trans2qfsinfo(connection_struct *conn, @@ -1225,8 +1220,9 @@ static int call_trans2qfsinfo(connection_struct *conn, } /**************************************************************************** - reply to a TRANS2_SETFSINFO (set filesystem info) + Reply to a TRANS2_SETFSINFO (set filesystem info). ****************************************************************************/ + static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1246,8 +1242,8 @@ static int call_trans2setfsinfo(connection_struct *conn, } /**************************************************************************** - Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by - file name or file id). + Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by + file name or file id). ****************************************************************************/ static int call_trans2qfilepathinfo(connection_struct *conn, @@ -1263,6 +1259,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, uint16 info_level; int mode=0; SMB_OFF_T size=0; + SMB_OFF_T allocation_size=0; unsigned int data_size; SMB_STRUCT_STAT sbuf; pstring fname; @@ -1298,287 +1295,286 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - delete_pending = fsp->directory_delete_on_close; - } else { - /* - * Original code - this is an open file. - */ - CHECK_FSP(fsp,conn); - - pstrcpy(fname, fsp->fsp_name); - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n", - fsp->fnum, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadfid)); - } - if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - delete_pending = fsp->delete_on_close; - } - } else { - /* qpathinfo */ - info_level = SVAL(params,0); - - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", - info_level)); - - srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); - - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } - } + delete_pending = fsp->directory_delete_on_close; + } else { + /* + * Original code - this is an open file. + */ + CHECK_FSP(fsp,conn); + pstrcpy(fname, fsp->fsp_name); + if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", - fname,info_level,tran_call,total_data)); + delete_pending = fsp->delete_on_close; + } + } else { + /* qpathinfo */ + info_level = SVAL(params,0); - p = strrchr_m(fname,'/'); - if (!p) { - base_name = fname; - } else { - base_name = p+1; - } + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - mode = dos_mode(conn,fname,&sbuf); - size = sbuf.st_size; - if (mode & aDIR) size = 0; + srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); - params = Realloc(*pparams,2); - if (params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *pparams = params; - memset((char *)params,'\0',2); - data_size = max_data_bytes + 1024; - pdata = Realloc(*ppdata, data_size); - if ( pdata == NULL ) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *ppdata = pdata; - - if (total_data > 0 && IVAL(pdata,0) == total_data) { - /* uggh, EAs for OS2 */ - DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return ERROR_DOS(ERRDOS,ERReasnotsupported); - } + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - memset((char *)pdata,'\0',data_size); + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + } - c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - if (lp_dos_filetime_resolution(SNUM(conn))) { - c_time &= ~1; - sbuf.st_atime &= ~1; - sbuf.st_mtime &= ~1; - sbuf.st_mtime &= ~1; - } + DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", + fname,info_level,tran_call,total_data)); - switch (info_level) - { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: - data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,c_time); - put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - SIVAL(pdata,l1_cbFile,(uint32)size); - SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024)); - SSVAL(pdata,l1_attrFile,mode); - SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ - break; + p = strrchr_m(fname,'/'); + if (!p) + base_name = fname; + else + base_name = p+1; - case SMB_INFO_QUERY_EAS_FROM_LIST: - data_size = 24; - put_dos_date2(pdata,0,c_time); - put_dos_date2(pdata,4,sbuf.st_atime); - put_dos_date2(pdata,8,sbuf.st_mtime); - SIVAL(pdata,12,(uint32)size); - SIVAL(pdata,16,SMB_ROUNDUP(size,1024)); - SIVAL(pdata,20,mode); - break; + mode = dos_mode(conn,fname,&sbuf); + size = sbuf.st_size; + allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size); + + if (mode & aDIR) + size = 0; - case SMB_INFO_QUERY_ALL_EAS: - data_size = 4; - SIVAL(pdata,0,data_size); - break; + params = Realloc(*pparams,2); + if (params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + *pparams = params; + memset((char *)params,'\0',2); + data_size = max_data_bytes + 1024; + pdata = Realloc(*ppdata, data_size); + if ( pdata == NULL ) + return ERROR_DOS(ERRDOS,ERRnomem); + *ppdata = pdata; - case 6: - return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */ + if (total_data > 0 && IVAL(pdata,0) == total_data) { + /* uggh, EAs for OS2 */ + DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } - case SMB_FILE_BASIC_INFORMATION: - case SMB_QUERY_FILE_BASIC_INFO: + memset((char *)pdata,'\0',data_size); - if (info_level == SMB_QUERY_FILE_BASIC_INFO) - data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ - else { - data_size = 40; - SIVAL(pdata,36,0); - } - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - SIVAL(pdata,32,mode); + c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - DEBUG(5,("SMB_QFBI - ")); - { - time_t create_time = c_time; - DEBUG(5,("create: %s ", ctime(&create_time))); - } - DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); - DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); - DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); - DEBUG(5,("mode: %x\n", mode)); + if (lp_dos_filetime_resolution(SNUM(conn))) { + c_time &= ~1; + sbuf.st_atime &= ~1; + sbuf.st_mtime &= ~1; + sbuf.st_mtime &= ~1; + } - break; + switch (info_level) { + case SMB_INFO_STANDARD: + case SMB_INFO_QUERY_EA_SIZE: + data_size = (info_level==1?22:26); + put_dos_date2(pdata,l1_fdateCreation,c_time); + put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); + put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ + SIVAL(pdata,l1_cbFile,(uint32)size); + SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); + SSVAL(pdata,l1_attrFile,mode); + SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ + break; - case SMB_FILE_STANDARD_INFORMATION: - case SMB_QUERY_FILE_STANDARD_INFO: - data_size = 24; - /* Fake up allocation size. */ - SOFF_T(pdata,0,SMB_ROUNDUP(size + 1, ((SMB_OFF_T)0x100000))); - SOFF_T(pdata,8,size); - SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = 0; - CVAL(pdata,21) = (mode&aDIR)?1:0; - break; + case SMB_INFO_QUERY_EAS_FROM_LIST: + data_size = 24; + put_dos_date2(pdata,0,c_time); + put_dos_date2(pdata,4,sbuf.st_atime); + put_dos_date2(pdata,8,sbuf.st_mtime); + SIVAL(pdata,12,(uint32)size); + SIVAL(pdata,16,(uint32)allocation_size); + SIVAL(pdata,20,mode); + break; - case SMB_FILE_EA_INFORMATION: - case SMB_QUERY_FILE_EA_INFO: - data_size = 4; - break; + case SMB_INFO_QUERY_ALL_EAS: + data_size = 4; + SIVAL(pdata,0,data_size); + break; - /* Get the 8.3 name - used if NT SMB was negotiated. */ - case SMB_QUERY_FILE_ALT_NAME_INFO: - { - pstring short_name; + case 6: + return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */ - pstrcpy(short_name,base_name); - /* Mangle if not already 8.3 */ - if(!is_8_3(short_name, True)) - { - if(!name_map_mangle(short_name,True,True,SNUM(conn))) - *short_name = '\0'; - } - len = srvstr_push(outbuf, pdata+4, short_name, -1, - STR_TERMINATE|STR_UPPER); - data_size = 4 + len; - SIVAL(pdata,0,len); - } - break; + case SMB_FILE_BASIC_INFORMATION: + case SMB_QUERY_FILE_BASIC_INFO: - case SMB_QUERY_FILE_NAME_INFO: - /* - * The first part of this code is essential - * to get security descriptors to work on mapped - * drives. Don't ask how I discovered this unless - * you like hearing about me suffering.... :-). JRA. - */ - if(strequal(".", fname)) { - len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE); - } else { - len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); - } - data_size = 4 + len; - SIVAL(pdata,0,len); - break; + if (info_level == SMB_QUERY_FILE_BASIC_INFO) + data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ + else { + data_size = 40; + SIVAL(pdata,36,0); + } + put_long_date(pdata,c_time); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + SIVAL(pdata,32,mode); - case SMB_FILE_ALLOCATION_INFORMATION: - case SMB_FILE_END_OF_FILE_INFORMATION: - case SMB_QUERY_FILE_ALLOCATION_INFO: - case SMB_QUERY_FILE_END_OF_FILEINFO: - data_size = 8; - SOFF_T(pdata,0,size); - break; + DEBUG(5,("SMB_QFBI - ")); + { + time_t create_time = c_time; + DEBUG(5,("create: %s ", ctime(&create_time))); + } + DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); + DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); + DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); + DEBUG(5,("mode: %x\n", mode)); - case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - SIVAL(pdata,32,mode); - pdata += 40; - SOFF_T(pdata,0,size); - SOFF_T(pdata,8,size); - SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = delete_pending; - CVAL(pdata,21) = (mode&aDIR)?1:0; - pdata += 24; - SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); - pdata += 8; /* index number */ - pdata += 4; /* EA info */ - if (mode & aRONLY) - SIVAL(pdata,0,0xA9); - else - SIVAL(pdata,0,0xd01BF); - pdata += 4; - SOFF_T(pdata,0,pos); /* current offset */ - pdata += 8; - SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ - pdata += 4; - pdata += 4; /* alignment */ - len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); - SIVAL(pdata,0,len); - pdata += 4 + len; - data_size = PTR_DIFF(pdata,(*ppdata)); - break; + break; - case SMB_FILE_INTERNAL_INFORMATION: - /* This should be an index number - looks like dev/ino to me :-) */ - SIVAL(pdata,0,sbuf.st_dev); - SIVAL(pdata,4,sbuf.st_ino); - data_size = 8; - break; + case SMB_FILE_STANDARD_INFORMATION: + case SMB_QUERY_FILE_STANDARD_INFO: + data_size = 24; + /* Fake up allocation size. */ + SOFF_T(pdata,0,allocation_size); + SOFF_T(pdata,8,size); + SIVAL(pdata,16,sbuf.st_nlink); + CVAL(pdata,20) = 0; + CVAL(pdata,21) = (mode&aDIR)?1:0; + break; - case SMB_FILE_ACCESS_INFORMATION: - SIVAL(pdata,0,0x12019F); /* ??? */ - data_size = 4; - break; + case SMB_FILE_EA_INFORMATION: + case SMB_QUERY_FILE_EA_INFO: + data_size = 4; + break; - case SMB_FILE_NAME_INFORMATION: - /* Pathname with leading '\'. */ + /* Get the 8.3 name - used if NT SMB was negotiated. */ + case SMB_QUERY_FILE_ALT_NAME_INFO: { - pstring new_fname; - size_t byte_len; + pstring short_name; - pstrcpy(new_fname, "\\"); - pstrcat(new_fname, fname); - byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False); - SIVAL(pdata,0,byte_len); - data_size = 4 + byte_len; + pstrcpy(short_name,base_name); + /* Mangle if not already 8.3 */ + if(!is_8_3(short_name, True)) { + if(!name_map_mangle(short_name,True,True,SNUM(conn))) + *short_name = '\0'; + } + len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER); + data_size = 4 + len; + SIVAL(pdata,0,len); break; } - case SMB_FILE_DISPOSITION_INFORMATION: - data_size = 1; - CVAL(pdata,0) = delete_pending; - break; + case SMB_QUERY_FILE_NAME_INFO: + /* + * The first part of this code is essential + * to get security descriptors to work on mapped + * drives. Don't ask how I discovered this unless + * you like hearing about me suffering.... :-). JRA. + */ + if(strequal(".", fname)) { + len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE); + } else { + len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); + } + data_size = 4 + len; + SIVAL(pdata,0,len); + break; - case SMB_FILE_POSITION_INFORMATION: - data_size = 8; - SOFF_T(pdata,0,pos); - break; + case SMB_FILE_END_OF_FILE_INFORMATION: + case SMB_QUERY_FILE_END_OF_FILEINFO: + data_size = 8; + SOFF_T(pdata,0,size); + break; - case SMB_FILE_MODE_INFORMATION: - SIVAL(pdata,0,mode); - data_size = 4; - break; + case SMB_FILE_ALLOCATION_INFORMATION: + case SMB_QUERY_FILE_ALLOCATION_INFO: + data_size = 8; + SOFF_T(pdata,0,allocation_size); + break; - case SMB_FILE_ALIGNMENT_INFORMATION: - SIVAL(pdata,0,0); /* No alignment needed. */ - data_size = 4; - break; + case SMB_QUERY_FILE_ALL_INFO: + put_long_date(pdata,c_time); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + SIVAL(pdata,32,mode); + pdata += 40; + SOFF_T(pdata,0,allocation_size); + SOFF_T(pdata,8,size); + SIVAL(pdata,16,sbuf.st_nlink); + CVAL(pdata,20) = delete_pending; + CVAL(pdata,21) = (mode&aDIR)?1:0; + pdata += 24; + SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); + pdata += 8; /* index number */ + pdata += 4; /* EA info */ + if (mode & aRONLY) + SIVAL(pdata,0,0xA9); + else + SIVAL(pdata,0,0xd01BF); + pdata += 4; + SOFF_T(pdata,0,pos); /* current offset */ + pdata += 8; + SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ + pdata += 4; + pdata += 4; /* alignment */ + len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); + SIVAL(pdata,0,len); + pdata += 4 + len; + data_size = PTR_DIFF(pdata,(*ppdata)); + break; + + case SMB_FILE_INTERNAL_INFORMATION: + /* This should be an index number - looks like dev/ino to me :-) */ + SIVAL(pdata,0,sbuf.st_dev); + SIVAL(pdata,4,sbuf.st_ino); + data_size = 8; + break; + + case SMB_FILE_ACCESS_INFORMATION: + SIVAL(pdata,0,0x12019F); /* ??? */ + data_size = 4; + break; + + case SMB_FILE_NAME_INFORMATION: + /* Pathname with leading '\'. */ + { + pstring new_fname; + size_t byte_len; + + pstrcpy(new_fname, "\\"); + pstrcat(new_fname, fname); + byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False); + SIVAL(pdata,0,byte_len); + data_size = 4 + byte_len; + break; + } + + case SMB_FILE_DISPOSITION_INFORMATION: + data_size = 1; + CVAL(pdata,0) = delete_pending; + break; + + case SMB_FILE_POSITION_INFORMATION: + data_size = 8; + SOFF_T(pdata,0,pos); + break; + + case SMB_FILE_MODE_INFORMATION: + SIVAL(pdata,0,mode); + data_size = 4; + break; + + case SMB_FILE_ALIGNMENT_INFORMATION: + SIVAL(pdata,0,0); /* No alignment needed. */ + data_size = 4; + break; #if 0 /* Not yet finished... JRA */ @@ -1605,534 +1601,531 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } #endif - case SMB_FILE_ALTERNATE_NAME_INFORMATION: - /* Last component of pathname. */ - { - size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False); - SIVAL(pdata,0,byte_len); - data_size = 4 + byte_len; - break; - } + case SMB_FILE_ALTERNATE_NAME_INFORMATION: + /* Last component of pathname. */ + { + size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False); + SIVAL(pdata,0,byte_len); + data_size = 4 + byte_len; + break; + } - case SMB_FILE_STREAM_INFORMATION: - if (mode & aDIR) { - data_size = 0; - } else { - size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False); - SIVAL(pdata,0,0); /* ??? */ - SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ - SOFF_T(pdata,8,size); - SIVAL(pdata,16,0x20); /* ??? */ - SIVAL(pdata,20,0); /* ??? */ - data_size = 24 + byte_len; - } - break; - - case SMB_FILE_COMPRESSION_INFORMATION: - SOFF_T(pdata,0,size); - SIVAL(pdata,8,0); /* ??? */ - SIVAL(pdata,12,0); /* ??? */ - data_size = 16; - break; + case SMB_FILE_STREAM_INFORMATION: + if (mode & aDIR) { + data_size = 0; + } else { + size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False); + SIVAL(pdata,0,0); /* ??? */ + SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ + SOFF_T(pdata,8,size); + SIVAL(pdata,16,allocation_size); + SIVAL(pdata,20,0); /* ??? */ + data_size = 24 + byte_len; + } + break; - case SMB_FILE_NETWORK_OPEN_INFORMATION: - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - SIVAL(pdata,32,0x20); /* ??? */ - SIVAL(pdata,36,0); /* ??? */ - SOFF_T(pdata,40,size); - SIVAL(pdata,48,mode); - SIVAL(pdata,52,0); /* ??? */ - data_size = 56; - break; + case SMB_FILE_COMPRESSION_INFORMATION: + SOFF_T(pdata,0,size); + SIVAL(pdata,8,0); /* ??? */ + SIVAL(pdata,12,0); /* ??? */ + data_size = 16; + break; - case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: - SIVAL(pdata,0,mode); - SIVAL(pdata,4,0); - data_size = 8; - break; + case SMB_FILE_NETWORK_OPEN_INFORMATION: + put_long_date(pdata,c_time); + put_long_date(pdata+8,sbuf.st_atime); + put_long_date(pdata+16,sbuf.st_mtime); /* write time */ + put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + SIVAL(pdata,32,allocation_size); + SOFF_T(pdata,40,size); + SIVAL(pdata,48,mode); + SIVAL(pdata,52,0); /* ??? */ + data_size = 56; + break; - /* - * End new completely undocumented info levels... JRA. - */ + case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: + SIVAL(pdata,0,mode); + SIVAL(pdata,4,0); + data_size = 8; + break; #if 0 - /* NT4 server just returns "invalid query" to this - if we try to answer - it then NTws gets a BSOD! (tridge) */ - case SMB_QUERY_FILE_STREAM_INFO: - SIVAL(pdata,0,pos); - SIVAL(pdata,4,size); - SIVAL(pdata,12,size); - len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE); - SIVAL(pdata,20,len); - data_size = 24 + len; - break; + /* NT4 server just returns "invalid query" to this - if we try to answer + it then NTws gets a BSOD! (tridge) */ + case SMB_QUERY_FILE_STREAM_INFO: + SIVAL(pdata,0,pos); + SIVAL(pdata,4,(uint32)size); + SIVAL(pdata,12,(uint32)allocation_size); + len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE); + SIVAL(pdata,20,len); + data_size = 24 + len; + break; #endif - default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); - } + default: + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size); - return(-1); + return(-1); } /**************************************************************************** - reply to a TRANS2_SETFILEINFO (set file info by fileid) + Reply to a TRANS2_SETFILEINFO (set file info by fileid). ****************************************************************************/ + static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **pparams, char **ppdata, int total_data) { - char *params = *pparams; - char *pdata = *ppdata; - uint16 tran_call = SVAL(inbuf, smb_setup0); - uint16 info_level; - int mode=0; - SMB_OFF_T size=0; - struct utimbuf tvs; - SMB_STRUCT_STAT sbuf; - pstring fname; - int fd = -1; - BOOL bad_path = False; - files_struct *fsp = NULL; - - if (tran_call == TRANSACT2_SETFILEINFO) { - fsp = file_fsp(params,0); - info_level = SVAL(params,2); + char *params = *pparams; + char *pdata = *ppdata; + uint16 tran_call = SVAL(inbuf, smb_setup0); + uint16 info_level; + int mode=0; + SMB_OFF_T size=0; + struct utimbuf tvs; + SMB_STRUCT_STAT sbuf; + pstring fname; + int fd = -1; + BOOL bad_path = False; + files_struct *fsp = NULL; - if(fsp && (fsp->is_directory || fsp->stat_open)) { - /* - * This is actually a SETFILEINFO on a directory - * handle (returned from an NT SMB). NT5.0 seems - * to do this call. JRA. - */ - pstrcpy(fname, fsp->fsp_name); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } - } else if (fsp && fsp->print_file) { - /* - * Doing a DELETE_ON_CLOSE should cancel a print job. - */ - if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) { - fsp->share_mode = FILE_DELETE_ON_CLOSE; + if (tran_call == TRANSACT2_SETFILEINFO) { + fsp = file_fsp(params,0); + info_level = SVAL(params,2); - DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", - fsp->fsp_name )); + if(fsp && (fsp->is_directory || fsp->stat_open)) { + /* + * This is actually a SETFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + pstrcpy(fname, fsp->fsp_name); + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + } else if (fsp && fsp->print_file) { + /* + * Doing a DELETE_ON_CLOSE should cancel a print job. + */ + if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) { + fsp->share_mode = FILE_DELETE_ON_CLOSE; - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - return(-1); - } - } else { - /* - * Original code - this is an open file. - */ - CHECK_FSP(fsp,conn); + DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + } else { + /* + * Original code - this is an open file. + */ + CHECK_FSP(fsp,conn); - pstrcpy(fname, fsp->fsp_name); - fd = fsp->fd; + pstrcpy(fname, fsp->fsp_name); + fd = fsp->fd; - if (vfs_fstat(fsp,fd,&sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadfid)); - } - } - } else { - /* set path info */ - info_level = SVAL(params,0); - srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if(!check_name(fname, conn)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } + if (vfs_fstat(fsp,fd,&sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + } + } else { + /* set path info */ + info_level = SVAL(params,0); + srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); + unix_convert(fname,conn,0,&bad_path,&sbuf); + if(!check_name(fname, conn)) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } - if(!VALID_STAT(sbuf)) { - DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } - } + if(!VALID_STAT(sbuf)) { + DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + } - if (!CAN_WRITE(conn)) - return ERROR_DOS(ERRSRV,ERRaccess); + if (!CAN_WRITE(conn)) + return ERROR_DOS(ERRSRV,ERRaccess); - DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", - tran_call,fname,info_level,total_data)); + DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", + tran_call,fname,info_level,total_data)); - /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,2); - if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *pparams = params; + /* Realloc the parameter and data sizes */ + params = Realloc(*pparams,2); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + *pparams = params; - SSVAL(params,0,0); + SSVAL(params,0,0); - size = sbuf.st_size; - tvs.modtime = sbuf.st_mtime; - tvs.actime = sbuf.st_atime; - mode = dos_mode(conn,fname,&sbuf); - - if (total_data > 4 && IVAL(pdata,0) == total_data) { - /* uggh, EAs for OS2 */ - DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return ERROR_DOS(ERRDOS,ERReasnotsupported); - } + size = sbuf.st_size; + tvs.modtime = sbuf.st_mtime; + tvs.actime = sbuf.st_atime; + mode = dos_mode(conn,fname,&sbuf); - switch (info_level) - { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: - { - /* access time */ - tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); + if (total_data > 4 && IVAL(pdata,0) == total_data) { + /* uggh, EAs for OS2 */ + DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } - /* write time */ - tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); + switch (info_level) { + case SMB_INFO_STANDARD: + case SMB_INFO_QUERY_EA_SIZE: + { + /* access time */ + tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); - mode = SVAL(pdata,l1_attrFile); - size = IVAL(pdata,l1_cbFile); - break; - } + /* write time */ + tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - /* XXXX um, i don't think this is right. - it's also not in the cifs6.txt spec. - */ - case SMB_INFO_QUERY_EAS_FROM_LIST: - tvs.actime = make_unix_date2(pdata+8); - tvs.modtime = make_unix_date2(pdata+12); - size = IVAL(pdata,16); - mode = IVAL(pdata,24); - break; + mode = SVAL(pdata,l1_attrFile); + size = IVAL(pdata,l1_cbFile); + break; + } - /* XXXX nor this. not in cifs6.txt, either. */ - case SMB_INFO_QUERY_ALL_EAS: - tvs.actime = make_unix_date2(pdata+8); - tvs.modtime = make_unix_date2(pdata+12); - size = IVAL(pdata,16); - mode = IVAL(pdata,24); - break; + /* XXXX um, i don't think this is right. + it's also not in the cifs6.txt spec. + */ + case SMB_INFO_QUERY_EAS_FROM_LIST: + tvs.actime = make_unix_date2(pdata+8); + tvs.modtime = make_unix_date2(pdata+12); + size = IVAL(pdata,16); + mode = IVAL(pdata,24); + break; - case SMB_SET_FILE_BASIC_INFO: - case SMB_FILE_BASIC_INFORMATION: - { - /* Patch to do this correctly from Paul Eggert . */ - time_t write_time; - time_t changed_time; + /* XXXX nor this. not in cifs6.txt, either. */ + case SMB_INFO_QUERY_ALL_EAS: + tvs.actime = make_unix_date2(pdata+8); + tvs.modtime = make_unix_date2(pdata+12); + size = IVAL(pdata,16); + mode = IVAL(pdata,24); + break; - /* Ignore create time at offset pdata. */ + case SMB_SET_FILE_BASIC_INFO: + case SMB_FILE_BASIC_INFORMATION: + { + /* Patch to do this correctly from Paul Eggert . */ + time_t write_time; + time_t changed_time; - /* access time */ - tvs.actime = interpret_long_date(pdata+8); + /* Ignore create time at offset pdata. */ - write_time = interpret_long_date(pdata+16); - changed_time = interpret_long_date(pdata+24); + /* access time */ + tvs.actime = interpret_long_date(pdata+8); - tvs.modtime = MIN(write_time, changed_time); + write_time = interpret_long_date(pdata+16); + changed_time = interpret_long_date(pdata+24); - /* Prefer a defined time to an undefined one. */ - if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) - tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1 - ? changed_time - : write_time); + tvs.modtime = MIN(write_time, changed_time); - /* attributes */ - mode = IVAL(pdata,32); - break; - } + /* Prefer a defined time to an undefined one. */ + if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) + tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1 + ? changed_time : write_time); - case 1019: - case 1020: - case SMB_SET_FILE_ALLOCATION_INFO: - { - int ret = -1; - size = IVAL(pdata,0); + /* attributes */ + mode = IVAL(pdata,32); + break; + } + + case SMB_FILE_ALLOCATION_INFORMATION: + case SMB_SET_FILE_ALLOCATION_INFO: + { + int ret = -1; + SMB_OFF_T allocation_size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T - size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); + allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (IVAL(pdata,4) != 0) /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); #endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", - fname, (double)size )); + DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", + fname, (double)allocation_size )); - if(size != sbuf.st_size) { + if(allocation_size != sbuf.st_size) { + SMB_STRUCT_STAT new_sbuf; - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", - fname, (double)size )); + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n", + fname, (double)allocation_size )); - if (fd == -1) { - files_struct *new_fsp = NULL; - int access_mode = 0; - int action = 0; + if (fd == -1) { + files_struct *new_fsp = NULL; + int access_mode = 0; + int action = 0; - if(global_oplock_break) { - /* Queue this file modify as we are the process of an oplock break. */ + if(global_oplock_break) { + /* Queue this file modify as we are the process of an oplock break. */ - DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); + DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); + DEBUGADD(2,( "in oplock break state.\n")); - push_oplock_pending_smb_message(inbuf, length); - return -1; - } + push_oplock_pending_smb_message(inbuf, length); + return -1; + } - new_fsp = open_file_shared(conn, fname, &sbuf, - SET_OPEN_MODE(DOS_OPEN_RDWR), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - 0, 0, &access_mode, &action); + new_fsp = open_file_shared(conn, fname, &sbuf, + SET_OPEN_MODE(DOS_OPEN_RDWR), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + 0, 0, &access_mode, &action); - if (new_fsp == NULL) - return(UNIXERROR(ERRDOS,ERRbadpath)); - ret = vfs_allocate_file_space(new_fsp, size); - close_file(new_fsp,True); - } else { - ret = vfs_allocate_file_space(fsp, size); - } - if (ret == -1) return ERROR_NT(NT_STATUS_DISK_FULL); + if (new_fsp == NULL) + return(UNIXERROR(ERRDOS,ERRbadpath)); + ret = vfs_allocate_file_space(new_fsp, allocation_size); + if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno))); + ret = -1; + } + close_file(new_fsp,True); + } else { + ret = vfs_allocate_file_space(fsp, size); + if (vfs_fstat(fsp,fd,&new_sbuf) != 0) { + DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); + ret = -1; + } + } + if (ret == -1) + return ERROR_NT(NT_STATUS_DISK_FULL); - sbuf.st_size = size; - } + /* Allocate can trucate size... */ + size = new_sbuf.st_size; + } - break; - } + break; + } - case SMB_SET_FILE_END_OF_FILE_INFO: - { - size = IVAL(pdata,0); + case SMB_SET_FILE_END_OF_FILE_INFO: + { + size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T - size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); + size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (IVAL(pdata,4) != 0) /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); #endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size )); - break; - } + DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size )); + break; + } - case SMB_FILE_DISPOSITION_INFORMATION: - case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ - { - BOOL delete_on_close = (CVAL(pdata,0) ? True : False); + case SMB_FILE_DISPOSITION_INFORMATION: + case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ + { + BOOL delete_on_close = (CVAL(pdata,0) ? True : False); - if (tran_call != TRANSACT2_SETFILEINFO) - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (tran_call != TRANSACT2_SETFILEINFO) + return ERROR_DOS(ERRDOS,ERRunknownlevel); - if (fsp == NULL) - return(UNIXERROR(ERRDOS,ERRbadfid)); + if (fsp == NULL) + return(UNIXERROR(ERRDOS,ERRbadfid)); - /* - * Only allow delete on close for files/directories opened with delete intent. - */ + /* + * Only allow delete on close for files/directories opened with delete intent. + */ - if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) { - DEBUG(10,("call_trans2setfilepathinfo: file %s delete on close flag set but delete access denied.\n", + if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) { + DEBUG(10,("call_trans2setfilepathinfo: file %s delete on close flag set but delete access denied.\n", fsp->fsp_name )); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - if(fsp->is_directory) { - fsp->directory_delete_on_close = delete_on_close; - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n", + if(fsp->is_directory) { + fsp->directory_delete_on_close = delete_on_close; + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n", delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } else if(fsp->stat_open) { + } else if(fsp->stat_open) { - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } else { + } else { - files_struct *iterate_fsp; + files_struct *iterate_fsp; - /* - * Modify the share mode entry for all files open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. This will be noticed - * in the close code, the last closer will delete the file - * if flag is set. - */ + /* + * Modify the share mode entry for all files open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. This will be noticed + * in the close code, the last closer will delete the file + * if flag is set. + */ - DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - if (lock_share_entry_fsp(fsp) == False) - return ERROR_DOS(ERRDOS,ERRnoaccess); + if (lock_share_entry_fsp(fsp) == False) + return ERROR_DOS(ERRDOS,ERRnoaccess); - if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close flag for file %s\n", + if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { + DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close flag for file %s\n", fsp->fsp_name )); - unlock_share_entry_fsp(fsp); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } + unlock_share_entry_fsp(fsp); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - /* - * Release the lock. - */ + /* + * Release the lock. + */ - unlock_share_entry_fsp(fsp); + unlock_share_entry_fsp(fsp); - /* - * Go through all files we have open on the same device and - * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. - * Other smbd's that have this file open will look in the share_mode on close. - * take care of this (rare) case in close_file(). See the comment there. - * NB. JRA. We don't really need to do this anymore - all should be taken - * care of in the share_mode changes in the tdb. - */ + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + * Other smbd's that have this file open will look in the share_mode on close. + * take care of this (rare) case in close_file(). See the comment there. + * NB. JRA. We don't really need to do this anymore - all should be taken + * care of in the share_mode changes in the tdb. + */ - for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode); + for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode); iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp)) - fsp->delete_on_close = delete_on_close; + fsp->delete_on_close = delete_on_close; - /* - * Set the delete on close flag in the fsp. - */ - fsp->delete_on_close = delete_on_close; + /* + * Set the delete on close flag in the fsp. + */ + fsp->delete_on_close = delete_on_close; - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + + } + break; } - break; + default: + return ERROR_DOS(ERRDOS,ERRunknownlevel); } - default: - { - return ERROR_DOS(ERRDOS,ERRunknownlevel); - } - } + /* get some defaults (no modifications) if any info is zero or -1. */ + if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1) + tvs.actime = sbuf.st_atime; - /* get some defaults (no modifications) if any info is zero or -1. */ - if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1) - tvs.actime = sbuf.st_atime; + if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) + tvs.modtime = sbuf.st_mtime; - if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) - tvs.modtime = sbuf.st_mtime; + DEBUG(6,("actime: %s " , ctime(&tvs.actime))); + DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); + DEBUG(6,("size: %.0f ", (double)size)); + DEBUG(6,("mode: %x\n" , mode)); - DEBUG(6,("actime: %s " , ctime(&tvs.actime))); - DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); - DEBUG(6,("size: %.0f ", (double)size)); - DEBUG(6,("mode: %x\n" , mode)); + if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || + (info_level == SMB_SET_FILE_ALLOCATION_INFO) || + (info_level == SMB_FILE_ALLOCATION_INFORMATION) || + (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) { - if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || - (info_level == SMB_SET_FILE_ALLOCATION_INFO) || - (info_level == SMB_FILE_ALLOCATION_INFORMATION) || - (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) { - /* - * Only do this test if we are not explicitly - * changing the size of a file. - */ - if (!size) - size = sbuf.st_size; - } + /* + * Only do this test if we are not explicitly + * changing the size of a file. + */ + if (!size) + size = sbuf.st_size; + } - /* Try and set the times, size and mode of this file - - if they are different from the current values - */ - if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { - if(fsp != NULL) { - /* - * This was a setfileinfo on an open file. - * NT does this a lot. It's actually pointless - * setting the time here, as it will be overwritten - * on the next write, so we save the request - * away and will set it on file code. JRA. - */ + /* + * Try and set the times, size and mode of this file - + * if they are different from the current values + */ + if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { + if(fsp != NULL) { + /* + * This was a setfileinfo on an open file. + * NT does this a lot. It's actually pointless + * setting the time here, as it will be overwritten + * on the next write, so we save the request + * away and will set it on file code. JRA. + */ - if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { - DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", - ctime(&tvs.modtime) )); - fsp->pending_modtime = tvs.modtime; - } + if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { + DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) )); + fsp->pending_modtime = tvs.modtime; + } - } else { + } else { - DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); + DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); - if(file_utime(conn, fname, &tvs)!=0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } + if(file_utime(conn, fname, &tvs)!=0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } - /* check the mode isn't different, before changing it */ - if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) { + /* check the mode isn't different, before changing it */ + if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) { - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", - fname, mode )); + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode )); - if(file_chmod(conn, fname, mode, NULL)) { - DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } + if(file_chmod(conn, fname, mode, NULL)) { + DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } - if(size != sbuf.st_size) { + if(size != sbuf.st_size) { - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", - fname, (double)size )); + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", + fname, (double)size )); - if (fd == -1) { - files_struct *new_fsp = NULL; - int access_mode = 0; - int action = 0; + if (fd == -1) { + files_struct *new_fsp = NULL; + int access_mode = 0; + int action = 0; - if(global_oplock_break) { - /* Queue this file modify as we are the process of an oplock break. */ + if(global_oplock_break) { + /* Queue this file modify as we are the process of an oplock break. */ - DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); + DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); + DEBUGADD(2,( "in oplock break state.\n")); - push_oplock_pending_smb_message(inbuf, length); - return -1; - } + push_oplock_pending_smb_message(inbuf, length); + return -1; + } - new_fsp = open_file_shared(conn, fname, &sbuf, - SET_OPEN_MODE(DOS_OPEN_RDWR), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - 0, 0, &access_mode, &action); + new_fsp = open_file_shared(conn, fname, &sbuf, + SET_OPEN_MODE(DOS_OPEN_RDWR), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + 0, 0, &access_mode, &action); - if (new_fsp == NULL) - return(UNIXERROR(ERRDOS,ERRbadpath)); - vfs_set_filelen(new_fsp, size); - close_file(new_fsp,True); - } else { - vfs_set_filelen(fsp, size); - } - } + if (new_fsp == NULL) + return(UNIXERROR(ERRDOS,ERRbadpath)); + vfs_set_filelen(new_fsp, size); + close_file(new_fsp,True); + } else { + vfs_set_filelen(fsp, size); + } + } - SSVAL(params,0,0); + SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - return(-1); + return(-1); } /**************************************************************************** - reply to a TRANS2_MKDIR (make directory with extended attributes). + Reply to a TRANS2_MKDIR (make directory with extended attributes). ****************************************************************************/ + static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **pparams, char **ppdata) @@ -2180,9 +2173,10 @@ static int call_trans2mkdir(connection_struct *conn, } /**************************************************************************** - reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes) - We don't actually do this - we just send a null response. + Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes). + We don't actually do this - we just send a null response. ****************************************************************************/ + static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -2225,9 +2219,10 @@ static int call_trans2findnotifyfirst(connection_struct *conn, } /**************************************************************************** - reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for - changes). Currently this does nothing. + Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for + changes). Currently this does nothing. ****************************************************************************/ + static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -2253,8 +2248,9 @@ static int call_trans2findnotifynext(connection_struct *conn, } /**************************************************************************** - reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele + Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele . ****************************************************************************/ + static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize, char** pparams, char** ppdata) @@ -2285,7 +2281,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, #define LMFUNC_GETJOBID 0x60 /**************************************************************************** - reply to a TRANS2_IOCTL - used for OS/2 printing. + Reply to a TRANS2_IOCTL - used for OS/2 printing. ****************************************************************************/ static int call_trans2ioctl(connection_struct *conn, char* inbuf, @@ -2318,8 +2314,9 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, } /**************************************************************************** - reply to a SMBfindclose (stop trans2 directory search) + Reply to a SMBfindclose (stop trans2 directory search). ****************************************************************************/ + int reply_findclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { @@ -2340,8 +2337,9 @@ int reply_findclose(connection_struct *conn, } /**************************************************************************** - reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search) + Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search). ****************************************************************************/ + int reply_findnclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { @@ -2365,10 +2363,10 @@ int reply_findnclose(connection_struct *conn, return(outsize); } - /**************************************************************************** - reply to a SMBtranss2 - just ignore it! + Reply to a SMBtranss2 - just ignore it! ****************************************************************************/ + int reply_transs2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { @@ -2379,8 +2377,9 @@ int reply_transs2(connection_struct *conn, } /**************************************************************************** - reply to a SMBtrans2 + Reply to a SMBtrans2. ****************************************************************************/ + int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 37cee4918b..256fb96f02 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -280,19 +280,20 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) { - size_t total=0; - ssize_t ret; + size_t total=0; + ssize_t ret; - while (total < N) - { - ret = fsp->conn->vfs_ops.write(fsp,fsp->fd,buffer + total,N - total); + while (total < N) { + ret = fsp->conn->vfs_ops.write(fsp,fsp->fd,buffer + total,N - total); - if (ret == -1) return -1; - if (ret == 0) return total; + if (ret == -1) + return -1; + if (ret == 0) + return total; - total += ret; - } - return (ssize_t)total; + total += ret; + } + return (ssize_t)total; } /**************************************************************************** @@ -305,11 +306,16 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) { int ret; SMB_STRUCT_STAT st; - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; + connection_struct *conn = fsp->conn; + struct vfs_ops *vfs_ops = &conn->vfs_ops; + SMB_OFF_T space_avail; + SMB_BIG_UINT bsize,dfree,dsize; +#if 0 if (!lp_strict_allocate(SNUM(fsp->conn))) return vfs_set_filelen(fsp, len); - +#endif + release_level_2_oplocks_on_change(fsp); /* @@ -337,41 +343,20 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) return ret; } - /* Grow - we need to write out the space.... */ - { - static unsigned char zero_space[65536]; - - SMB_OFF_T start_pos = st.st_size; - SMB_OFF_T len_to_write = len - st.st_size; - SMB_OFF_T retlen; - - DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f\n", - fsp->fsp_name, (double)st.st_size )); - - if ((retlen = vfs_ops->lseek(fsp, fsp->fd, start_pos, SEEK_SET)) != start_pos) - return -1; + /* Grow - we need to test if we have enough space. */ - while ( len_to_write > 0) { - SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),len_to_write); - - retlen = vfs_ops->write(fsp,fsp->fd,(const char *)zero_space,current_len_to_write); - if (retlen <= 0) { - /* Write fail - return to original size. */ - int save_errno = errno; - fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, st.st_size); - errno = save_errno; - DEBUG(10,("vfs_allocate_file_space: file %s, grow. write fail %s\n", - fsp->fsp_name, strerror(errno) )); - return -1; - } + len -= st.st_size; + len /= 1024; /* Len is now number of 1k blocks needed. */ + space_avail = (SMB_OFF_T)conn->vfs_ops.disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); - DEBUG(10,("vfs_allocate_file_space: file %s, grow. wrote %.0f\n", - fsp->fsp_name, (double)retlen )); + DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %lu, space avail = %lu\n", + fsp->fsp_name, (double)st.st_size, (unsigned long)len, (unsigned long)space_avail )); - len_to_write -= retlen; - } - set_filelen_write_cache(fsp, len); + if (len > space_avail) { + errno = ENOSPC; + return -1; } + return 0; } -- cgit From a32754589a05038423582a16f6468fbd783daed6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Nov 2001 02:03:44 +0000 Subject: Don't check space on every extend if strict allocate not set. Jeremy (This used to be commit 9391efb38ef1847ed2c3b2734c1177830d64a247) --- source3/smbd/vfs.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 256fb96f02..6d8e9cc76c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -311,11 +311,6 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) SMB_OFF_T space_avail; SMB_BIG_UINT bsize,dfree,dsize; -#if 0 - if (!lp_strict_allocate(SNUM(fsp->conn))) - return vfs_set_filelen(fsp, len); -#endif - release_level_2_oplocks_on_change(fsp); /* @@ -345,6 +340,9 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) /* Grow - we need to test if we have enough space. */ + if (!lp_strict_allocate(SNUM(fsp->conn))) + return 0; + len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ space_avail = (SMB_OFF_T)conn->vfs_ops.disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); -- cgit From e5bd418963225d355c7050979776aeb555e4e033 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 12 Nov 2001 20:14:18 +0000 Subject: Spelling fixes. (This used to be commit 5c486bd28a5d4194b7cd50fd0fe3430d0d2eaa9b) --- source3/smbd/sesssetup.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 291685e9fc..c9c91ea71c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -25,9 +25,9 @@ uint32 global_client_caps = 0; /**************************************************************************** - Add the standard 'Samba' signiture to the end of the session setup. + Add the standard 'Samba' signature to the end of the session setup. ****************************************************************************/ -static void add_signiture(char *outbuf) +static void add_signature(char *outbuf) { char *p; p = smb_buf(outbuf); @@ -130,7 +130,7 @@ static int reply_spnego_kerberos(connection_struct *conn, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - add_signiture(outbuf); + add_signature(outbuf); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -359,7 +359,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - add_signiture(outbuf); + add_signature(outbuf); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -395,7 +395,7 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - add_signiture(outbuf); + add_signature(outbuf); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -680,7 +680,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, set_message(outbuf,3,0,True); } else { set_message(outbuf,3,0,True); - add_signiture(outbuf); + add_signature(outbuf); /* perhaps grab OS version here?? */ } -- cgit From b00b04ebc6858ffa2691b4fc80b3d9600f50900c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Nov 2001 01:35:20 +0000 Subject: Formatting fixes only. Jeremy. (This used to be commit 27081355a97550b26c870907a471352a11921ffc) --- source3/smbd/close.c | 28 ++++++++-------- source3/smbd/nttrans.c | 87 +++++++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 58 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 5c8c7996f5..fae43fca5d 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -166,21 +166,21 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * reference to a file. */ - if (normal_close && delete_on_close) { - DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", - fsp->fsp_name)); + if (normal_close && delete_on_close) { + DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", + fsp->fsp_name)); if(fsp->conn->vfs_ops.unlink(conn,fsp->fsp_name) != 0) { - /* - * This call can potentially fail as another smbd may have - * had the file open with delete on close set and deleted - * it when its last reference to this file went away. Hence - * we log this but not at debug level zero. - */ - - DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \ + /* + * This call can potentially fail as another smbd may have + * had the file open with delete on close set and deleted + * it when its last reference to this file went away. Hence + * we log this but not at debug level zero. + */ + + DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \ with error %s\n", fsp->fsp_name, strerror(errno) )); - } - } + } + } unlock_share_entry_fsp(fsp); @@ -238,7 +238,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) if(ok) remove_pending_change_notify_requests_by_filename(fsp); - } + } /* * Do the code common to files and directories. diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c68d5d101b..9abc85f938 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -595,59 +595,58 @@ int reply_ntcreate_and_X(connection_struct *conn, * Get the file name. */ - if(root_dir_fid != 0) { - /* - * This filename is relative to a directory fid. - */ - files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid); - size_t dir_name_len; + if(root_dir_fid != 0) { + /* + * This filename is relative to a directory fid. + */ + files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid); + size_t dir_name_len; - if(!dir_fsp) { - END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRbadfid)); - } + if(!dir_fsp) { + END_PROFILE(SMBntcreateX); + return(ERROR_DOS(ERRDOS,ERRbadfid)); + } - if(!dir_fsp->is_directory) { - /* - * Check to see if this is a mac fork of some kind. - */ + if(!dir_fsp->is_directory) { + /* + * Check to see if this is a mac fork of some kind. + */ - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); - if( strchr_m(fname, ':')) { - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } - END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRbadfid)); - } + if( strchr_m(fname, ':')) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } + END_PROFILE(SMBntcreateX); + return(ERROR_DOS(ERRDOS,ERRbadfid)); + } - /* - * Copy in the base directory name. - */ + /* + * Copy in the base directory name. + */ - pstrcpy( fname, dir_fsp->fsp_name ); - dir_name_len = strlen(fname); + pstrcpy( fname, dir_fsp->fsp_name ); + dir_name_len = strlen(fname); - /* - * Ensure it ends in a '\'. - */ + /* + * Ensure it ends in a '\'. + */ - if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') { - pstrcat(fname, "\\"); - dir_name_len++; - } + if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') { + pstrcat(fname, "\\"); + dir_name_len++; + } - srvstr_pull(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, - -1, STR_TERMINATE); - } else { - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), - -1, STR_TERMINATE); - } + srvstr_pull(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, + -1, STR_TERMINATE); + } else { + srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); + } /* * Now contruct the smb_open_mode value from the filename, - * desired access and the share access. + * desired access and the share access. */ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -829,10 +828,10 @@ int reply_ntcreate_and_X(connection_struct *conn, * exclusive & batch here. */ - if (smb_action & EXTENDED_OPLOCK_GRANTED) - SCVAL(p,0, BATCH_OPLOCK_RETURN); + if (smb_action & EXTENDED_OPLOCK_GRANTED) + SCVAL(p,0, BATCH_OPLOCK_RETURN); else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) - SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); + SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); else SCVAL(p,0,NO_OPLOCK_RETURN); -- cgit From 1b579da9ddb4fbdcdd60ed1b50ca52b6fa1e523e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Nov 2001 02:35:56 +0000 Subject: Fix from Herb. mincount/maxcount need to be ssize_t for comparisons. Jeremy. (This used to be commit 60983782ed078593d122e0c0bc6b4e17c3e56e63) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 72e75281c6..dce5873ba8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1386,7 +1386,7 @@ void fail_readraw(void) int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { - size_t maxcount,mincount; + ssize_t maxcount,mincount; size_t nread = 0; SMB_OFF_T startpos; char *header = outbuf; -- cgit From 5302dc12184481514e143f0b3cf4167c84a32ddd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Nov 2001 01:18:10 +0000 Subject: Fix detection of RedHat 7.2. Remove unused old file. Test 42 byte reply to SMBntcreate (W2K does this). Jeremy. (This used to be commit a55a63a4ca55602ad9221af17c0bc8e185536433) --- source3/smbd/nttrans.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9abc85f938..ae18fc9a53 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -819,7 +819,12 @@ int reply_ntcreate_and_X(connection_struct *conn, if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) smb_action |= EXTENDED_OPLOCK_GRANTED; +#if 1 /* JRATEST */ + /* W2K sends back 42 words here ! */ + set_message(outbuf,42,0,True); +#else set_message(outbuf,34,0,True); +#endif p = outbuf + smb_vwv2; -- cgit From 02eda2e251e6dcb6e0db5cd9c3cbcfa765f3d630 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 Nov 2001 03:19:17 +0000 Subject: Tidyups when I was doing the big merge... Jeremy. (This used to be commit 9148bb9eaa67de60c3b0b4709a9c05a840c20c66) --- source3/smbd/reply.c | 28 ++++++++++++++++------------ source3/smbd/trans2.c | 1 + 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dce5873ba8..1412905cdf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1164,10 +1164,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* close fd from smb_mkstemp() */ close(tmpfd); - if (!fsp) - { - if((errno == ENOENT) && bad_path) - { + if (!fsp) { + if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } @@ -1208,28 +1206,33 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(outsize); } - /******************************************************************* -check if a user is allowed to delete a file + Check if a user is allowed to delete a file. ********************************************************************/ + static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) { SMB_STRUCT_STAT sbuf; int fmode; - if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; + if (!CAN_WRITE(conn)) + return NT_STATUS_MEDIA_WRITE_PROTECTED; - if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND; + if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; fmode = dos_mode(conn,fname,&sbuf); - if (fmode & aDIR) return NT_STATUS_FILE_IS_A_DIRECTORY; + if (fmode & aDIR) + return NT_STATUS_FILE_IS_A_DIRECTORY; if (!lp_delete_readonly(SNUM(conn))) { - if (fmode & aRONLY) return NT_STATUS_CANNOT_DELETE; + if (fmode & aRONLY) + return NT_STATUS_CANNOT_DELETE; } if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return NT_STATUS_CANNOT_DELETE; - if (!check_file_sharing(conn,fname,False)) return NT_STATUS_SHARING_VIOLATION; + if (!check_file_sharing(conn,fname,False)) + return NT_STATUS_SHARING_VIOLATION; return NT_STATUS_OK; } @@ -2685,7 +2688,8 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); status = mkdir_internal(conn, directory); - if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); outsize = set_message(outbuf,0,0,True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bf0be4c111..404d88260e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1913,6 +1913,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_SET_FILE_END_OF_FILE_INFO: { size = IVAL(pdata,0); -- cgit From f741f656737f4ec46cd318e986b6bf412ed309d2 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Mon, 19 Nov 2001 02:49:53 +0000 Subject: Store some path names in global variables initialized to configure default, rather than in preprocessor macros. (This used to be commit 79ec88f0da40faebe1e587f1b3e87b5f2b184f58) --- source3/smbd/build_options.c | 17 +++++------------ source3/smbd/lanman.c | 2 +- source3/smbd/server.c | 14 +++++++------- 3 files changed, 13 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index d12fe40872..8c22e95451 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -22,6 +22,7 @@ #include "includes.h" #include "build_env.h" +#include "dynconfig.h" static void output(BOOL screen, char *format, ...) PRINTF_ATTRIBUTE(2,3); @@ -184,30 +185,22 @@ void build_options(BOOL screen) /* Output various paths to files and directories */ output(screen,"\nPaths:\n"); -#ifdef CONFIGFILE - output(screen," CONFIGFILE: %s\n",CONFIGFILE); -#endif + output(screen," CONFIGFILE: %s\n", dyn_CONFIGFILE); #ifdef PRIVATE_DIR output(screen," PRIVATE_DIR: %s\n",PRIVATE_DIR); #endif #ifdef LMHOSTSFILE output(screen," LMHOSTSFILE: %s\n",LMHOSTSFILE); #endif -#ifdef SBINDIR - output(screen," SBINDIR: %s\n",SBINDIR); -#endif -#ifdef BINDIR - output(screen," BINDIR: %s\n",BINDIR); -#endif + output(screen," SBINDIR: %s\n", dyn_SBINDIR); + output(screen," BINDIR: %s\n", dyn_BINDIR); #ifdef LOCKDIR output(screen," LOCKDIR: %s\n",LOCKDIR); #endif #ifdef DRIVERFILE output(screen," DRIVERFILE: %s\n",DRIVERFILE); #endif -#ifdef LOGFILEBASE - output(screen," LOGFILEBASE: %s\n",LOGFILEBASE); -#endif + output(screen," LOGFILEBASE: %s\n", dyn_LOGFILEBASE); #ifdef FORMSFILE output(screen," FORMSFILE: %s\n",FORMSFILE); #endif diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7ade1e6d47..34dcf6c211 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1713,7 +1713,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch if (!cmdname || *cmdname == '\0') return False; asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", - lp_add_share_cmd(), CONFIGFILE, sharename, pathname, comment); + lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment); if (command) { DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 16a092f152..c48cb37615 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -21,7 +21,6 @@ #include "includes.h" -pstring servicesf = CONFIGFILE; extern pstring debugf; extern fstring global_myworkgroup; extern pstring global_myname; @@ -357,8 +356,8 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { - pstrcpy(servicesf,fname); + if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { + pstrcpy(dyn_CONFIGFILE,fname); test = False; } } @@ -370,7 +369,7 @@ BOOL reload_services(BOOL test) lp_killunused(conn_snum_used); - ret = lp_load(servicesf,False,False,True); + ret = lp_load(dyn_CONFIGFILE,False,False,True); load_printers(); @@ -588,7 +587,7 @@ static void usage(char *pname) int port = SMB_PORT; int opt; extern char *optarg; - + #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif @@ -606,7 +605,7 @@ static void usage(char *pname) break; case 's': - pstrcpy(servicesf,optarg); + pstrcpy(dyn_CONFIGFILE,optarg); break; case 'l': @@ -671,7 +670,8 @@ static void usage(char *pname) TimeInit(); if(!specified_logfile) { - slprintf(debugf, sizeof(debugf)-1, "%s/log.smbd", LOGFILEBASE); + slprintf(debugf, sizeof(debugf)-1, "%s/log.smbd", + dyn_LOGFILEBASE); } pstrcpy(remote_machine, "smbd"); -- cgit From caef2d2884fb202bd6184f9a676ecff94c7ab600 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Mon, 19 Nov 2001 03:35:27 +0000 Subject: LIBDIR and LOCKDIR are dynamically configured too. (This used to be commit 868999ad3c82ad72f11d5b3208b0e42b1ed95096) --- source3/smbd/build_options.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 8c22e95451..7ddbd2433a 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -194,9 +194,7 @@ void build_options(BOOL screen) #endif output(screen," SBINDIR: %s\n", dyn_SBINDIR); output(screen," BINDIR: %s\n", dyn_BINDIR); -#ifdef LOCKDIR - output(screen," LOCKDIR: %s\n",LOCKDIR); -#endif + output(screen," LOCKDIR: %s\n",dyn_LOCKDIR); #ifdef DRIVERFILE output(screen," DRIVERFILE: %s\n",DRIVERFILE); #endif -- cgit From 4d5175c832d905e06c0840388b925e14b58024af Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 19 Nov 2001 04:27:39 +0000 Subject: Don't resolve the hostname in smbd as we can pause for a long time while waiting for DNS timeouts to occur. The correct place to do this is in the code that displays the session information. (This used to be commit 2e89165f22d9e9c1fa749ae54957d0ec84a1497d) --- source3/smbd/session.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 9efc3e6b75..d483f12d16 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -78,9 +78,12 @@ BOOL session_claim(user_struct *vuser) return False; } - hostname = client_name(); - if (strequal(hostname,"UNKNOWN")) - hostname = client_addr(); + /* Don't resolve the hostname in smbd as we can pause for a long + time while waiting for DNS timeouts to occur. The correct + place to do this is in the code that displays the session + information. */ + + hostname = client_addr(); fstrcpy(sessionid.username, vuser->user.unix_name); fstrcpy(sessionid.hostname, hostname); -- cgit From 0085229b2a2da40867863792230c179b9287336b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 19 Nov 2001 04:35:00 +0000 Subject: Cosmetic fix for debug statement. (This used to be commit 507ef80f48a8fca762e41be5cdb80ce86544da3f) --- source3/smbd/password.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b2687980ac..510e18919d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -469,8 +469,7 @@ BOOL authorise_login(int snum,char *user, DATA_BLOB password, */ if (!vuser) { - DEBUG(1,("authorise_login: refusing user %s with no session setup\n", - user)); + DEBUG(1,("authorise_login: refusing user '%s' with no session setup\n", user)); return False; } -- cgit From 788379830166313922fa6cb56f789a6754e27614 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Mon, 19 Nov 2001 05:49:20 +0000 Subject: Move all other paths into dynconfig (This used to be commit d51ef6bfa3d194b58c3ee7706a7d475ef042676d) --- source3/smbd/build_options.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 7ddbd2433a..48261ea20a 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -195,16 +195,8 @@ void build_options(BOOL screen) output(screen," SBINDIR: %s\n", dyn_SBINDIR); output(screen," BINDIR: %s\n", dyn_BINDIR); output(screen," LOCKDIR: %s\n",dyn_LOCKDIR); -#ifdef DRIVERFILE - output(screen," DRIVERFILE: %s\n",DRIVERFILE); -#endif + output(screen," DRIVERFILE: %s\n", dyn_DRIVERFILE); output(screen," LOGFILEBASE: %s\n", dyn_LOGFILEBASE); -#ifdef FORMSFILE - output(screen," FORMSFILE: %s\n",FORMSFILE); -#endif -#ifdef NTDRIVERSDIR - output(screen," NTDRIVERSDIR: %s\n",NTDRIVERSDIR); -#endif /*Output various other options (most map to defines in the configure script*/ output(screen,"\nOther Build Options:\n"); -- cgit From c32526441668d75a8acf452e55559f00d5b87ba2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 Nov 2001 08:50:04 +0000 Subject: add a hook to save the krb5 PAC (This used to be commit 1cbc18ae732671d9a60528f8300ca7609e124d11) --- source3/smbd/sesssetup.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c9c91ea71c..b3e9b7be8f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -85,6 +85,14 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } +#if 0 + if (tkt->enc_part2) { + file_save("/tmp/authdata.dat", + tkt->enc_part2->authorization_data[0]->contents, + tkt->enc_part2->authorization_data[0]->length); + } +#endif + if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, &client))) { DEBUG(3,("krb5_unparse_name failed (%s)\n", -- cgit From 96d884cc0f42ea694f7648ae12a3643bd1322a2b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 20 Nov 2001 23:20:00 +0000 Subject: Fixed sizeof vs array length bug in make_user_info_winbind_crap() Spelling fix. (This used to be commit 3d87c1a2444c3b9267e0dda7a2da77657fba143e) --- source3/smbd/auth_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index e6ce7d186e..16efdbc54e 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -473,7 +473,7 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, /**************************************************************************** Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrupt and encrypt the passwords. + Decrypt and encrypt the passwords. ****************************************************************************/ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, @@ -484,7 +484,7 @@ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, uchar *nt_network_pwd, int nt_pwd_len) { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + DATA_BLOB sec_blob = data_blob(chal, 8); DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); DATA_BLOB plaintext_blob = data_blob(NULL, 0); -- cgit From 54432c412958ca4cafcc033c2d311cfccc1603f2 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 21 Nov 2001 20:14:25 +0000 Subject: Spelling fix, reformatted comment. (This used to be commit 096868bd35b374f97e570676fc23c006b6c7a1d3) --- source3/smbd/auth_util.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 16efdbc54e..5a86e02928 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -423,11 +423,13 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, if (*password) { SMBencrypt( (const uchar *)password, chal, local_lm_response); - /* This encrypts the lm_pwd feild, which actualy contains the password - rather than the nt_pwd field becouse that contains nothing */ + /* This encrypts the lm_pwd field, which actualy contains + the password rather than the nt_pwd field becouse that + contains nothing */ - /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. - We might want to add a check here and only do an LM in that case */ + /* WATCH OUT. This doesn't work if the incoming password is + incorrectly cased. We might want to add a check here + and only do an LM in that case */ SMBNTencrypt((const uchar *)password, chal, local_nt_response); -- cgit From 646f8ca3e822290897e6298dd16ad3b4be78c07a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 21 Nov 2001 21:10:13 +0000 Subject: More spelling fixes, comment reformatting. (This used to be commit edb556b47446f75dc4987eee15276661eb6cec8d) --- source3/smbd/auth_util.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 5a86e02928..25e0830fc7 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -130,9 +130,11 @@ void smb_user_control(const auth_usersupplied_info *user_info, auth_serversuppli SMB_STRUCT_STAT st; const char *home_dir = pdb_get_homedir(server_info->sam_account); /* - * Also call smb_create_user if the users home directory - * doesn't exist. Used with winbindd to allow the script to - * create the home directory for a user mapped with winbindd. + * Also call smb_create_user if the users + * home directory doesn't exist. Used with + * winbindd to allow the script to create + * the home directory for a user mapped + * with winbindd. */ if (home_dir && @@ -272,7 +274,7 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info, /**************************************************************************** Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrupt and encrypt the passwords. + Decrypt and encrypt the passwords. ****************************************************************************/ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, @@ -311,7 +313,7 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, /**************************************************************************** Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrupt and encrypt the passwords. + Decrypt and encrypt the passwords. ****************************************************************************/ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, @@ -423,8 +425,8 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, if (*password) { SMBencrypt( (const uchar *)password, chal, local_lm_response); - /* This encrypts the lm_pwd field, which actualy contains - the password rather than the nt_pwd field becouse that + /* This encrypts the lm_pwd field, which actually contains + the password rather than the nt_pwd field because that contains nothing */ /* WATCH OUT. This doesn't work if the incoming password is @@ -572,7 +574,8 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); - /* We can't do an NT hash here, as the password needs to be case insensitive */ + /* We can't do an NT hash here, as the password needs to be + case insensitive */ local_nt_blob = data_blob(NULL, 0); ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM; -- cgit From 11aa019becb42248aa418c3667786a4e0bc24053 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 22 Nov 2001 05:29:04 +0000 Subject: WITH_MSDFS is not define anywhere. It's built by default. (This used to be commit b51e5b07d9f7719180b28215236efc3fa09d8bea) --- source3/smbd/build_options.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 48261ea20a..9e55a29744 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -129,9 +129,6 @@ void build_options(BOOL screen) #ifdef WITH_QUOTAS output(screen," WITH_QUOTAS\n"); #endif -#ifdef WITH_MSDFS - output(screen," WITH_MSDFS\n"); -#endif #ifdef WITH_VFS output(screen," WITH_VFS\n"); #endif -- cgit From 79b34d1b11e685d068b9c0ac9a0ec06eaa263d82 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 23 Nov 2001 00:52:29 +0000 Subject: Removed TimeInit() call from every client program (except for one place in smbd/process.c where the timezone is reinitialised. Was replaced with check for a static is_initialised boolean. (This used to be commit 8fc772c9e5770cd3a8857670214dcff033ebae32) --- source3/smbd/server.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c48cb37615..b08c8e8bda 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -667,8 +667,6 @@ static void usage(char *pname) append_log = True; - TimeInit(); - if(!specified_logfile) { slprintf(debugf, sizeof(debugf)-1, "%s/log.smbd", dyn_LOGFILEBASE); -- cgit From d05bbf042209b737e42a5daa8d59236d351ec8d0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Nov 2001 11:18:20 +0000 Subject: Fixed delete on close bug. Added core dump code to winbindd. Jeremy. (This used to be commit a58d0f91f9ee7354c01a9c20cfe178d5dc02142d) --- source3/smbd/nttrans.c | 21 ++++--- source3/smbd/open.c | 23 ++++++- source3/smbd/trans2.c | 161 +++++++++++++++++++++++++++---------------------- 3 files changed, 125 insertions(+), 80 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ae18fc9a53..2c3ac06f3c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -330,7 +330,7 @@ static int map_create_disposition( uint32 create_disposition) Utility function to map share modes. ****************************************************************************/ -static int map_share_mode( BOOL *pstat_open_only, char *fname, +static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_options, uint32 desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode = -1; @@ -423,6 +423,13 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = %x\n", smb_open_mode)); } + if (create_options & FILE_DELETE_ON_CLOSE) { + /* Implicit delete access requested... */ + smb_open_mode |= DELETE_ACCESS_REQUESTED; + smb_open_mode |= DELETE_ON_CLOSE_FLAG; + DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = %x\n", smb_open_mode)); + } + /* Add in the requested share mode. */ switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) { case FILE_SHARE_READ: @@ -650,7 +657,7 @@ int reply_ntcreate_and_X(connection_struct *conn, */ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - if((smb_open_mode = map_share_mode(&stat_open_only, fname, desired_access, + if((smb_open_mode = map_share_mode(&stat_open_only, fname, create_options, desired_access, share_access, file_attributes)) == -1) { END_PROFILE(SMBntcreateX); @@ -681,7 +688,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); @@ -749,7 +756,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1157,7 +1164,7 @@ static int call_nt_transact_create(connection_struct *conn, * and the share access. */ - if((smb_open_mode = map_share_mode( &stat_open_only, fname, desired_access, + if((smb_open_mode = map_share_mode( &stat_open_only, fname, create_options, desired_access, share_access, file_attributes)) == -1) return ERROR_DOS(ERRDOS,ERRbadaccess); @@ -1190,7 +1197,7 @@ static int call_nt_transact_create(connection_struct *conn, * CreateDirectory() call. */ - fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1226,7 +1233,7 @@ static int call_nt_transact_create(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 325913c3d9..1eae228f40 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -618,6 +618,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); BOOL delete_access_requested = GET_DELETE_ACCESS_REQUESTED(share_mode); + BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; SMB_DEV_T dev = 0; @@ -905,6 +906,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", set_share_mode(fsp, port, oplock_request); + if (delete_on_close) { + NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + + if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + unlock_share_entry_fsp(fsp); + fd_close(conn,fsp); + file_free(fsp); + return NULL; + } + } + unlock_share_entry_fsp(fsp); conn->num_files_open++; @@ -1019,11 +1031,12 @@ int close_file_fchmod(files_struct *fsp) ****************************************************************************/ files_struct *open_directory(connection_struct *conn, char *fname, - SMB_STRUCT_STAT *psbuf, int smb_ofun, mode_t unixmode, int *action) + SMB_STRUCT_STAT *psbuf, int share_mode, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; BOOL got_stat = False; files_struct *fsp = file_new(conn); + BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); if(!fsp) return NULL; @@ -1126,6 +1139,14 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->conn = conn; string_set(&fsp->fsp_name,fname); + if (delete_on_close) { + NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + + if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + file_free(fsp); + return NULL; + } + } conn->num_files_open++; return fsp; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 404d88260e..0e13d8d87a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1671,6 +1671,90 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return(-1); } +/**************************************************************************** + Deal with the internal needs of setting the delete on close flag. Note that + as the tdb locking is recursive, it is safe to call this from within + open_file_shared. JRA. +****************************************************************************/ + +NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) +{ + /* + * Only allow delete on close for files/directories opened with delete intent. + */ + + if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; + } + + if(fsp->is_directory) { + fsp->directory_delete_on_close = delete_on_close; + DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + } else if(fsp->stat_open) { + + DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, stat open %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + + } else { + + files_struct *iterate_fsp; + + /* + * Modify the share mode entry for all files open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. This will be noticed + * in the close code, the last closer will delete the file + * if flag is set. + */ + + DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + + if (lock_share_entry_fsp(fsp) == False) + return NT_STATUS_ACCESS_DENIED; + + if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { + DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n", + fsp->fsp_name )); + unlock_share_entry_fsp(fsp); + return NT_STATUS_ACCESS_DENIED; + } + + /* + * Release the lock. + */ + + unlock_share_entry_fsp(fsp); + + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + * Other smbd's that have this file open will look in the share_mode on close. + * take care of this (rare) case in close_file(). See the comment there. + * NB. JRA. We don't really need to do this anymore - all should be taken + * care of in the share_mode changes in the tdb. + */ + + for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode); + iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp)) + fsp->delete_on_close = delete_on_close; + + /* + * Set the delete on close flag in the fsp. + */ + fsp->delete_on_close = delete_on_close; + + DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + + } + + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid). ****************************************************************************/ @@ -1931,6 +2015,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { BOOL delete_on_close = (CVAL(pdata,0) ? True : False); + NTSTATUS status; if (tran_call != TRANSACT2_SETFILEINFO) return ERROR_DOS(ERRDOS,ERRunknownlevel); @@ -1938,78 +2023,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadfid)); - /* - * Only allow delete on close for files/directories opened with delete intent. - */ - - if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) { - DEBUG(10,("call_trans2setfilepathinfo: file %s delete on close flag set but delete access denied.\n", - fsp->fsp_name )); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } - - if(fsp->is_directory) { - fsp->directory_delete_on_close = delete_on_close; - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } else if(fsp->stat_open) { - - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - - } else { - - files_struct *iterate_fsp; - - /* - * Modify the share mode entry for all files open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. This will be noticed - * in the close code, the last closer will delete the file - * if flag is set. - */ - - DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - - if (lock_share_entry_fsp(fsp) == False) - return ERROR_DOS(ERRDOS,ERRnoaccess); - - if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close flag for file %s\n", - fsp->fsp_name )); - unlock_share_entry_fsp(fsp); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } - - /* - * Release the lock. - */ - - unlock_share_entry_fsp(fsp); - - /* - * Go through all files we have open on the same device and - * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. - * Other smbd's that have this file open will look in the share_mode on close. - * take care of this (rare) case in close_file(). See the comment there. - * NB. JRA. We don't really need to do this anymore - all should be taken - * care of in the share_mode changes in the tdb. - */ - - for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode); - iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp)) - fsp->delete_on_close = delete_on_close; - - /* - * Set the delete on close flag in the fsp. - */ - fsp->delete_on_close = delete_on_close; - - DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - - } + status = set_delete_on_close_internal(fsp, delete_on_close); + + if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + return ERROR_NT(status); break; } -- cgit From d0a2faf78d316fec200497f5f7997df4c477a1e1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 24 Nov 2001 12:12:38 +0000 Subject: This is another rather major change to the samba authenticaion subystem. The particular aim is to modularized the interface - so that we can have arbitrary password back-ends. This code adds one such back-end, a 'winbind' module to authenticate against the winbind_auth_crap functionality. While fully-functional this code is mainly useful as a demonstration, because we don't get back the info3 as we would for direct ntdomain authentication. This commit introduced the new 'auth methods' parameter, in the spirit of the 'auth order' discussed on the lists. It is renamed because not all the methods may be consulted, even if previous methods fail - they may not have a suitable challenge for example. Also, we have a 'local' authentication method, for old-style 'unix if plaintext, sam if encrypted' authentication and a 'guest' module to handle guest logins in a single place. While this current design is not ideal, I feel that it does provide a better infrastructure than the current design, and can be built upon. The following parameters have changed: - use rhosts = This has been replaced by the 'rhosts' authentication method, and can be specified like 'auth methods = guest rhosts' - hosts equiv = This needs both this parameter and an 'auth methods' entry to be effective. (auth methods = guest hostsequiv ....) - plaintext to smbpasswd = This is replaced by specifying 'sam' rather than 'local' in the auth methods. The security = parameter is unchanged, and now provides defaults for the 'auth methods' parameter. The available auth methods are: guest rhosts hostsequiv sam (passdb direct hash access) unix (PAM, crypt() etc) local (the combination of the above, based on encryption) smbserver (old security=server) ntdomain (old security=domain) winbind (use winbind to cache DC connections) Assistance in testing, or the production of new and interesting authentication modules is always appreciated. Andrew Bartlett (This used to be commit 8d31eae52a9757739711dbb82035a4dfe6b40c99) --- source3/smbd/auth.c | 165 +++++++++++++------------ source3/smbd/auth_builtin.c | 87 +++++++++++++ source3/smbd/auth_domain.c | 18 ++- source3/smbd/auth_info.c | 279 ++++++++++++++++++++++++++++++++++++++++++ source3/smbd/auth_rhosts.c | 72 ++++++++--- source3/smbd/auth_server.c | 172 +++++++++++++++++++++----- source3/smbd/auth_smbpasswd.c | 75 +++++++----- source3/smbd/auth_unix.c | 15 ++- source3/smbd/auth_util.c | 208 ++++++++++++------------------- source3/smbd/negprot.c | 102 ++++++--------- source3/smbd/process.c | 30 +++-- source3/smbd/server.c | 4 +- source3/smbd/sesssetup.c | 123 +++++++++++++------ 13 files changed, 942 insertions(+), 408 deletions(-) create mode 100644 source3/smbd/auth_builtin.c create mode 100644 source3/smbd/auth_info.c (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 95c97182b8..c62e2ed5a0 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -58,27 +58,50 @@ static BOOL check_domain_match(char *user, char *domain) ****************************************************************************/ NTSTATUS check_password(const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - BOOL done_pam = False; const char *pdb_username; + auth_methods *auth_method; + + if (!user_info || !auth_info || !server_info) { + return NT_STATUS_LOGON_FAILURE; + } DEBUG(3, ("check_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str)); DEBUG(3, ("check_password: mapped user is: [%s]\\[%s]@[%s]\n", user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str)); - - if (!NT_STATUS_IS_OK(nt_status)) { - nt_status = check_guest_security(user_info, server_info); + DEBUG(10, ("auth_info challange created by %s\n", auth_info->challange_set_by)); + DEBUG(10, ("challange is: \n")); + dump_data(5, (auth_info)->challange.data, (auth_info)->challange.length); + +#ifdef DEBUG_PASSWORD + DEBUG(100, ("user_info has passwords of length %d and %d\n", + user_info->lm_resp.length, user_info->nt_resp.length)); + DEBUG(100, ("lm:\n")); + dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length); + DEBUG(100, ("nt:\n")); + dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length); +#endif + + for (auth_method = auth_info->auth_method_list;auth_method; auth_method = auth_method->next) + { + nt_status = auth_method->auth(auth_method->private_data, user_info, auth_info, server_info); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: checking guest-account for user [%s] suceeded\n", user_info->smb_name.str)); + DEBUG(3, ("check_password: %s authentication for user [%s] suceeded\n", + auth_method->name, user_info->smb_name.str)); } else { - DEBUG(10, ("check_password: checking gusst-account for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } + DEBUG(5, ("check_password: %s authentication for user [%s] FAILED with error %s\n", + auth_method->name, user_info->smb_name.str, get_nt_error_msg(nt_status))); + } + + if (NT_STATUS_IS_OK(nt_status)) { + break; + } } /* This needs to be sorted: If it doesn't match, what should we do? */ @@ -86,83 +109,47 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, return NT_STATUS_LOGON_FAILURE; } - if (!NT_STATUS_IS_OK(nt_status)) { - nt_status = check_rhosts_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_password: Password (rhosts) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(10, ("check_password: Password (rhosts) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - - if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) { - nt_status = check_domain_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (domain) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (domain) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - - if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) { - nt_status = check_server_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (server) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (server) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } + /* This is one of the few places the *relies* (rather than just sets defaults + on the value of lp_security(). This needs to change. A new paramater + perhaps? */ if (lp_security() >= SEC_SERVER) { smb_user_control(user_info, *server_info, nt_status); } - if (!NT_STATUS_IS_OK(nt_status)) { - if (user_info->encrypted || lp_plaintext_to_smbpasswd()) { - nt_status = check_smbpasswd_security(user_info, server_info); - } else { - nt_status = check_unix_security(user_info, server_info); - done_pam = True; - } - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (unix/smbpasswd) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (unix/smbpasswd) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - if (NT_STATUS_IS_OK(nt_status)) { pdb_username = pdb_get_username((*server_info)->sam_account); - if (!done_pam && !(*server_info)->guest) { + if (!(*server_info)->guest) { /* We might not be root if we are an RPC call */ become_root(); nt_status = smb_pam_accountcheck(pdb_username); unbecome_root(); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", pdb_username)); + DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", + pdb_username)); } else { - DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", pdb_username, get_nt_error_msg(nt_status))); + DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", + pdb_username, get_nt_error_msg(nt_status))); } } + + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG((*server_info)->guest ? 5 : 2, + ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", + (*server_info)->guest ? "guest " : "", + user_info->smb_name.str, + user_info->internal_username.str, + pdb_username)); + } } - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", - (*server_info)->guest ? "guest " : "", - user_info->smb_name.str, - user_info->internal_username.str, - pdb_username)); - } else { - DEBUG(3, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", user_info->smb_name.str, user_info->internal_username.str, get_nt_error_msg(nt_status))); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(2, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", + user_info->smb_name.str, user_info->internal_username.str, + get_nt_error_msg(nt_status))); ZERO_STRUCTP(server_info); - } - + } return nt_status; } @@ -210,16 +197,35 @@ static NTSTATUS pass_check_smb(char *smb_name, { NTSTATUS nt_status; auth_usersupplied_info *user_info = NULL; + extern auth_authsupplied_info *negprot_global_auth_info; auth_serversupplied_info *server_info = NULL; + if (encrypted) { + make_user_info_for_reply_enc(&user_info, smb_name, + domain, + lm_pwd, + nt_pwd, + plaintext_password); + nt_status = check_password(user_info, negprot_global_auth_info, &server_info); + } else { + auth_authsupplied_info *plaintext_auth_info = NULL; + DATA_BLOB chal; + if (!make_auth_info_subsystem(&plaintext_auth_info)) { + return NT_STATUS_NO_MEMORY; + } - make_user_info_for_reply(&user_info, smb_name, - domain, - lm_pwd, - nt_pwd, - plaintext_password, - encrypted); - - nt_status = check_password(user_info, &server_info); + chal = auth_get_challange(plaintext_auth_info); + + if (!make_user_info_for_reply(&user_info, + smb_name, domain, chal.data, + plaintext_password)) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = check_password(user_info, plaintext_auth_info, &server_info); + + data_blob_free(&chal); + free_auth_info(&plaintext_auth_info); + } free_user_info(&user_info); free_server_info(&server_info); return nt_status; @@ -235,22 +241,23 @@ BOOL password_ok(char *smb_name, DATA_BLOB password_blob) DATA_BLOB null_password = data_blob(NULL, 0); extern BOOL global_encrypted_passwords_negotiated; - - if (global_encrypted_passwords_negotiated) { + BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24); + + if (encrypted) { /* * The password could be either NTLM or plain LM. Try NTLM first, * but fall-through as required. * NTLMv2 makes no sense here. */ - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, global_encrypted_passwords_negotiated))) { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) { return True; } - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, global_encrypted_passwords_negotiated))) { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) { return True; } } else { - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, global_encrypted_passwords_negotiated))) { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) { return True; } } diff --git a/source3/smbd/auth_builtin.c b/source3/smbd/auth_builtin.c new file mode 100644 index 0000000000..6ea6d0bbe0 --- /dev/null +++ b/source3/smbd/auth_builtin.c @@ -0,0 +1,87 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0. + Generic authenticaion types + Copyright (C) Andrew Bartlett 2001 + + 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" + +/**************************************************************************** + Check for a guest logon (username = "") and if so create the required + structure. +****************************************************************************/ + +static NTSTATUS check_guest_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + + if (!(user_info->internal_username.str + && *user_info->internal_username.str)) { + if (make_server_info_guest(server_info)) { + nt_status = NT_STATUS_OK; + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } + + return nt_status; +} + +BOOL auth_init_guest(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_guest_security; + return True; +} + +/**************************************************************************** + Check against either sam or unix, depending on encryption. +****************************************************************************/ + +static NTSTATUS check_local_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + + if (user_info->encrypted) { + nt_status = check_sam_security(my_private_data, user_info, auth_info, server_info); + } else { + nt_status = check_unix_security(my_private_data, user_info, auth_info, server_info); + } + + return nt_status; +} + +BOOL auth_init_local(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_local_security; + return True; +} + diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index 4ada7d4a56..ef0e5b2f10 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -28,8 +28,10 @@ BOOL global_machine_password_needs_changing = False; Check for a valid username and password in security=domain mode. ****************************************************************************/ -NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) +static NTSTATUS check_ntdomain_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; char *p, *pserver; @@ -66,8 +68,18 @@ NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, if (! *pserver) pserver = "*"; p = pserver; - nt_status = domain_client_validate(user_info, server_info, + nt_status = domain_client_validate(user_info, (uchar *)auth_info->challange.data,server_info, p, trust_passwd, last_change_time); return nt_status; } + +BOOL auth_init_ntdomain(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_ntdomain_security; + return True; +} diff --git a/source3/smbd/auth_info.c b/source3/smbd/auth_info.c new file mode 100644 index 0000000000..12b843d781 --- /dev/null +++ b/source3/smbd/auth_info.c @@ -0,0 +1,279 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0. + Authentication utility functions + Copyright (C) Andrew Bartlett 2001 + + 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" + +const struct auth_init_function builtin_auth_init_functions[] = { + { "guest", auth_init_guest }, + { "rhosts", auth_init_rhosts }, + { "hostsequiv", auth_init_hostsequiv }, + { "sam", auth_init_sam }, + { "unix", auth_init_unix }, + { "local", auth_init_local }, + { "smbserver", auth_init_smbserver }, + { "ntdomain", auth_init_ntdomain }, + { "winbind", auth_init_winbind }, + { NULL, NULL} +}; + +/*************************************************************************** + Make a auth_info struct +***************************************************************************/ + +static BOOL make_auth_info(auth_authsupplied_info **auth_info) +{ + *auth_info = malloc(sizeof(**auth_info)); + if (!*auth_info) { + DEBUG(0,("make_auth_info: malloc failed!\n")); + return False; + } + ZERO_STRUCTP(*auth_info); + + return True; +} + +/*************************************************************************** + Make a auth_info struct with a specified list. +***************************************************************************/ + +BOOL make_auth_info_list(auth_authsupplied_info **auth_info, auth_methods *list) +{ + if (!make_auth_info(auth_info)) { + return False; + } + + (*auth_info)->auth_method_list = list; + + return True; +} + +/*************************************************************************** + Make a auth_info struct for the auth subsystem +***************************************************************************/ + +static BOOL make_auth_info_text_list(auth_authsupplied_info **auth_info, char **text_list) +{ + auth_methods *list = NULL; + auth_methods *t = NULL; + auth_methods *tmp; + int i; + + for (;*text_list; text_list++) + { + DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list)); + for (i = 0; builtin_auth_init_functions[i].name; i++) + { + if (strequal(builtin_auth_init_functions[i].name, *text_list)) + { + DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i)); + /* Malloc entry, fill it, link it */ + t = (auth_methods *)malloc(sizeof(*t)); + if (!t) { + DEBUG(0,("make_pw_chat: malloc failed!\n")); + return False; + } + + ZERO_STRUCTP(t); + + if (builtin_auth_init_functions[i].init(&t)) { + DEBUG(5,("auth method %s has a valid init\n", *text_list)); + t->name = builtin_auth_init_functions[i].name; + DLIST_ADD_END(list, t, tmp); + } else { + DEBUG(5,("auth method %s DOES NOT have a valid init\n", *text_list)); + } + break; + } + } + } + + make_auth_info_list(auth_info, list); + + return True; +} + +/*************************************************************************** + Make a auth_info struct for the auth subsystem +***************************************************************************/ + +BOOL make_auth_info_subsystem(auth_authsupplied_info **auth_info) +{ + char **auth_method_list = NULL; + + if (!make_auth_info(auth_info)) { + return False; + } + + if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) { + return False; + } + + if (auth_method_list == NULL) { + switch (lp_security()) + { + case SEC_DOMAIN: + DEBUG(5,("Making default auth method list for security=domain\n")); + auth_method_list = lp_list_make("guest ntdomain local"); + break; + case SEC_SERVER: + DEBUG(5,("Making default auth method list for security=server\n")); + auth_method_list = lp_list_make("guest smbserver local"); + break; + case SEC_USER: + DEBUG(5,("Making default auth method list for security=user\n")); + auth_method_list = lp_list_make("guest local"); + break; + case SEC_SHARE: + DEBUG(5,("Making default auth method list for security=share\n")); + auth_method_list = lp_list_make("guest local"); + break; + } + } else { + DEBUG(5,("Using specified auth order\n")); + } + + if (!make_auth_info_text_list(auth_info, auth_method_list)) { + lp_list_free(&auth_method_list); + return False; + } + + lp_list_free(&auth_method_list); + return True; +} + +/*************************************************************************** + Make a auth_info struct with a random challange +***************************************************************************/ + +BOOL make_auth_info_random(auth_authsupplied_info **auth_info) +{ + uchar chal[8]; + if (!make_auth_info_subsystem(auth_info)) { + return False; + } + + generate_random_buffer(chal, sizeof(chal), False); + (*auth_info)->challange = data_blob(chal, sizeof(chal)); + + (*auth_info)->challange_set_by = "random"; + + return True; +} + +/*************************************************************************** + Make a auth_info struct with a fixed challange +***************************************************************************/ + +BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) +{ + if (!make_auth_info_subsystem(auth_info)) { + return False; + } + + (*auth_info)->challange = data_blob(chal, 8); + return True; +} + +/*************************************************************************** + Clear out a auth_info struct that has been allocated +***************************************************************************/ + +void free_auth_info(auth_authsupplied_info **auth_info) +{ + auth_methods *list; + if (*auth_info != NULL) { + list = (*auth_info)->auth_method_list; + while (list) { + auth_methods *old_head = list; + if (list->free_private_data) { + list->free_private_data(&(list->private_data)); + } + DLIST_REMOVE(list, list); + SAFE_FREE(old_head); + } + + data_blob_free(&(*auth_info)->challange); + ZERO_STRUCT(**auth_info); + } + SAFE_FREE(*auth_info); +} + +/**************************************************************************** + Try to get a challange out of the various authenticaion modules. + It is up to the caller to free it. +****************************************************************************/ + +DATA_BLOB auth_get_challange(auth_authsupplied_info *auth_info) +{ + DATA_BLOB challange = data_blob(NULL, 0); + char *challange_set_by = NULL; + auth_methods *auth_method; + + if (auth_info->challange.length) { + DEBUG(5, ("auth_get_challange: returning previous challange (normal)\n")); + return data_blob(auth_info->challange.data, auth_info->challange.length); + } + + for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next) + { + if (auth_method->get_chal) { + DEBUG(5, ("auth_get_challange: getting challange from module %s\n", auth_method->name)); + if (challange_set_by) { + DEBUG(1, ("auth_get_challange: CONFIGURATION ERROR: authenticaion method %s has already specified a challange. Challange by %s ignored.\n", + challange_set_by, auth_method->name)); + } else { + challange = auth_method->get_chal(&auth_method->private_data, auth_info); + if (challange.length) { + DEBUG(5, ("auth_get_challange: sucessfully got challange from module %s\n", auth_method->name)); + auth_info->challange = challange; + challange_set_by = auth_method->name; + auth_info->challange_set_method = auth_method; + } else { + DEBUG(3, ("auth_get_challange: getting challange from authenticaion method %s FAILED.\n", + auth_method->name)); + } + } + } else { + DEBUG(5, ("auth_get_challange: module %s did not want to specify a challange\n", auth_method->name)); + } + } + + if (!challange_set_by) { + uchar chal[8]; + + generate_random_buffer(chal, sizeof(chal), False); + auth_info->challange = data_blob(chal, sizeof(chal)); + + challange_set_by = "random"; + } + + DEBUG(5, ("auth_info challange created by %s\n", challange_set_by)); + DEBUG(5, ("challange is: \n")); + dump_data(5, auth_info->challange.data, (auth_info)->challange.length); + + SMB_ASSERT(auth_info->challange.length == 8); + + auth_info->challange_set_by=challange_set_by; + + return data_blob(auth_info->challange.data, auth_info->challange.length); +} + + diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index 9c07e48a9b..2605f0770a 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -135,7 +135,6 @@ check for a possible hosts equiv or rhosts entry for the user static BOOL check_hosts_equiv(struct passwd *pass) { char *fname = NULL; - pstring rhostsfile; if (!pass) return(False); @@ -148,39 +147,82 @@ static BOOL check_hosts_equiv(struct passwd *pass) return(True); } - if (lp_use_rhosts()) - { - char *home = pass->pw_dir; - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) - return(True); - } - } - return(False); } + /**************************************************************************** Check for a valid .rhosts/hosts.equiv entry for this user ****************************************************************************/ -NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) +static NTSTATUS check_hostsequiv_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; struct passwd *pass = Get_Pwnam(user_info->internal_username.str); if (pass) { - become_root(); if (check_hosts_equiv(pass)) { nt_status = NT_STATUS_OK; make_server_info_pw(server_info, pass); } - unbecome_root(); } else { nt_status = NT_STATUS_NO_SUCH_USER; } return nt_status; } + + +/**************************************************************************** + Check for a valid .rhosts/hosts.equiv entry for this user +****************************************************************************/ + +static NTSTATUS check_rhosts_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + pstring rhostsfile; + + if (pass) { + char *home = pass->pw_dir; + if (home) { + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); + become_root(); + if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) { + nt_status = NT_STATUS_OK; + make_server_info_pw(server_info, pass); + } + unbecome_root(); + } + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + + return nt_status; +} + +BOOL auth_init_hostsequiv(auth_methods **auth_method) +{ + + if (!make_auth_methods(auth_method)) { + return False; + } + (*auth_method)->auth = check_hostsequiv_security; + return True; +} + +BOOL auth_init_rhosts(auth_methods **auth_method) +{ + + if (!make_auth_methods(auth_method)) { + return False; + } + (*auth_method)->auth = check_rhosts_security; + return True; +} diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index ddbc284d50..067b5b2997 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -24,31 +24,19 @@ extern pstring global_myname; -/**************************************************************************** - Return the client state structure. -****************************************************************************/ - -struct cli_state *server_client(void) -{ - static struct cli_state pw_cli; - return &pw_cli; -} - /**************************************************************************** Support for server level security. ****************************************************************************/ -struct cli_state *server_cryptkey(void) +static struct cli_state *server_cryptkey(void) { - struct cli_state *cli; + struct cli_state *cli = NULL; fstring desthost; struct in_addr dest_ip; char *p, *pserver; BOOL connected_ok = False; - cli = server_client(); - - if (!cli_initialise(cli)) + if (!(cli = cli_initialise(cli))) return NULL; /* security = server just can't function with spnego */ @@ -88,7 +76,11 @@ struct cli_state *server_cryptkey(void) if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) return NULL; - + + if (strequal(desthost,myhostname())) { + exit_server("Password server loop!"); + } + DEBUG(3,("got session\n")); if (!cli_negprot(cli)) { @@ -109,13 +101,82 @@ struct cli_state *server_cryptkey(void) return cli; } +/**************************************************************************** + Clean up our allocated cli. +****************************************************************************/ + +static void free_server_private_data(void **private_data_pointer) +{ + struct cli_state **cli = (struct cli_state **)private_data_pointer; + if (*cli && (*cli)->initialised) { + cli_shutdown(*cli); + + SAFE_FREE(*cli); + } +} + +/**************************************************************************** + Send a 'keepalive' packet down the cli pipe. +****************************************************************************/ + +static void send_server_keepalive(void **private_data_pointer) +{ + struct cli_state **cli = (struct cli_state **)private_data_pointer; + + /* also send a keepalive to the password server if its still + connected */ + if (cli && *cli && (*cli)->initialised) { + if (!send_keepalive((*cli)->fd)) { + DEBUG( 2, ( "password server keepalive failed.\n")); + cli_shutdown(*cli); + SAFE_FREE(*cli); + } + } +} + +/**************************************************************************** + Get the challange out of a password server. +****************************************************************************/ + +static DATA_BLOB auth_get_challange_server(void **my_private_data, const struct authsupplied_info *auth_info) +{ + struct cli_state *cli = server_cryptkey(); + + if (cli) { + DEBUG(3,("using password server validation\n")); + if ((cli->sec_mode & 2) == 0) { + /* We can't work with unencrypted password servers + unless 'encrypt passwords = no' */ + DEBUG(5,("make_auth_info_server: Server is unencrypted, no challange available..\n")); + + *my_private_data = (void *)cli; + return data_blob(NULL, 0); + + } else if (cli->secblob.length < 8) { + /* We can't do much if we don't get a full challange */ + DEBUG(2,("make_auth_info_server: Didn't receive a full challange from server\n")); + cli_shutdown(cli); + return data_blob(NULL, 0); + } + + *my_private_data = (void *)cli; + + return data_blob(cli->secblob.data,8); + } else { + return data_blob(NULL, 0); + } +} + /**************************************************************************** Check for a valid username and password in security=server mode. - Validate a password with the password server. ****************************************************************************/ -NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +static NTSTATUS check_smbserver_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { struct cli_state *cli; static unsigned char badpass[24]; @@ -123,13 +184,32 @@ NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_ser static BOOL tested_password_server = False; static BOOL bad_password_server = False; NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + BOOL locally_made_cli = False; - cli = server_client(); + cli = my_private_data; + + if (cli) { + } else { + cli = server_cryptkey(); + locally_made_cli = True; + } - if (!cli->initialised) { + if (!cli || !cli->initialised) { DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return(NT_STATUS_LOGON_FAILURE); + return NT_STATUS_LOGON_FAILURE; } + + if ((cli->sec_mode & 2) == 0) { + if (user_info->encrypted) { + DEBUG(1,("password server %s is plaintext, but we are encrypted. This just can't work :-(\n", cli->desthost)); + return NT_STATUS_LOGON_FAILURE; + } + } else { + if (memcmp(cli->secblob.data, auth_info->challange.data, 8) != 0) { + DEBUG(1,("the challange that the password server (%s) supplied us is not the one we gave our client. This just can't work :-(\n", cli->desthost)); + return NT_STATUS_LOGON_FAILURE; + } + } if(badpass[0] == 0) memset(badpass, 0x1f, sizeof(badpass)); @@ -206,17 +286,32 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, user_info->smb_name.str, - (char *)user_info->lm_resp.data, - user_info->lm_resp.length, - (char *)user_info->nt_resp.data, - user_info->nt_resp.length, - user_info->domain.str)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - /* Make this cli_nt_error() when the conversion is in */ - nt_status = cli_nt_error(cli); + if (!user_info->encrypted) { + /* Plaintext available */ + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->plaintext_password.data, + user_info->plaintext_password.length, + NULL, 0, + user_info->domain.str)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + /* Make this cli_nt_error() when the conversion is in */ + nt_status = cli_nt_error(cli); + } else { + nt_status = NT_STATUS_OK; + } } else { - nt_status = NT_STATUS_OK; + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->lm_resp.data, + user_info->lm_resp.length, + (char *)user_info->nt_resp.data, + user_info->nt_resp.length, + user_info->domain.str)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + /* Make this cli_nt_error() when the conversion is in */ + nt_status = cli_nt_error(cli); + } else { + nt_status = NT_STATUS_OK; + } } /* if logged in as guest then reject */ @@ -238,5 +333,22 @@ use this machine as the password server.\n")); } } + if (locally_made_cli) { + cli_shutdown(cli); + SAFE_FREE(cli); + } + return(nt_status); } + +BOOL auth_init_smbserver(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + (*auth_method)->auth = check_smbserver_security; + (*auth_method)->get_chal = auth_get_challange_server; + (*auth_method)->send_keepalive = send_server_keepalive; + (*auth_method)->free_private_data = free_server_private_data; + return True; +} diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 70632fb5df..24a4d4e4e4 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -96,7 +96,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, if (ntv2_response.length < 16) { /* We MUST have more than 16 bytes, or the stuff below will go crazy... */ - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", + DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", ntv2_response.length)); return False; } @@ -132,15 +132,16 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, uint8 user_sess_key[16]) +static NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + uint8 user_sess_key[16]) { + uint16 acct_ctrl; const uint8 *nt_pw, *lm_pw; - uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); uint32 ntlmssp_flags; - if (!user_info || !sampass) - return NT_STATUS_LOGON_FAILURE; - + acct_ctrl = pdb_get_acct_ctrl(sampass); if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) @@ -173,8 +174,8 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use */ DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, - user_info->sec_blob, user_info->smb_name.str, + nt_pw, auth_info->challange, + user_info->smb_name.str, user_info->client_domain.str, user_sess_key)) { @@ -190,7 +191,7 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use */ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, user_info->sec_blob, + nt_pw, auth_info->challange, user_sess_key)) { return NT_STATUS_OK; @@ -223,7 +224,7 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use DEBUG(4,("smb_password_ok: Checking LM password\n")); if (smb_pwd_check_ntlmv1(user_info->lm_resp, - lm_pw, user_info->sec_blob, + lm_pw, auth_info->challange, user_sess_key)) { return NT_STATUS_OK; @@ -265,6 +266,24 @@ static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_inf return NT_STATUS_ACCOUNT_EXPIRED; } + if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { + time_t must_change_time = pdb_get_pass_must_change_time(sampass); + time_t last_set_time = pdb_get_pass_last_set_time(sampass); + + /* check for immediate expiry "must change at next logon" */ + if (must_change_time == 0 && last_set_time != 0) { + DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); + return NT_STATUS_PASSWORD_MUST_CHANGE; + } + + /* check for expired password */ + if (must_change_time < time(NULL) && must_change_time != 0) { + DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); + DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); + return NT_STATUS_PASSWORD_EXPIRED; + } + } + /* Test workstation. Workstation list is comma separated. */ workstation_list = strdup(pdb_get_workstations(sampass)); @@ -293,24 +312,6 @@ static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_inf SAFE_FREE(workstation_list); } - if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { - time_t must_change_time = pdb_get_pass_must_change_time(sampass); - time_t last_set_time = pdb_get_pass_last_set_time(sampass); - - /* check for immediate expiry "must change at next logon" */ - if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); - return NT_STATUS_PASSWORD_MUST_CHANGE; - } - - /* check for expired password */ - if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); - DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); - return NT_STATUS_PASSWORD_EXPIRED; - } - } - if (acct_ctrl & ACB_DOMTRUST) { DEBUG(2,("session_trust_account: Domain trust account %s denied by server\n", pdb_get_username(sampass))); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; @@ -336,7 +337,10 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +NTSTATUS check_sam_security(void *my_private_dat, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { SAM_ACCOUNT *sampass=NULL; BOOL ret; @@ -344,7 +348,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ uint8 user_sess_key[16]; const uint8* lm_hash; - if (!user_info) { + if (!user_info || !auth_info) { return NT_STATUS_LOGON_FAILURE; } @@ -365,7 +369,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(sampass, user_info, user_sess_key); + nt_status = sam_password_ok(sampass, user_info, auth_info, user_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); @@ -394,6 +398,15 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return nt_status; } +BOOL auth_init_sam(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_sam_security; + return True; +} diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 8c4a520350..d134ce6909 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -82,7 +82,10 @@ check if a username/password is OK assuming the password in PLAIN TEXT ****************************************************************************/ -NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +NTSTATUS check_unix_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct passwd *pass = NULL; @@ -104,9 +107,19 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve if (pass) { make_server_info_pw(server_info, pass); } else { + /* we need to do somthing more useful here */ nt_status = NT_STATUS_NO_SUCH_USER; } } return nt_status; } + +BOOL auth_init_unix(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + (*auth_method)->auth = check_unix_security; + return True; +} diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 25e0830fc7..d1b2cc92e5 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -23,49 +23,9 @@ #include "includes.h" -/* Data to do lanman1/2 password challenge. */ -static unsigned char saved_challenge[8]; -static BOOL challenge_sent=False; extern fstring remote_machine; extern pstring global_myname; -/******************************************************************* - Get the next challenge value - no repeats. -********************************************************************/ - -void generate_next_challenge(char *challenge) -{ - unsigned char buf[8]; - - generate_random_buffer(buf,8,False); - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,8); - challenge_sent = True; -} - -/******************************************************************* - Set the last challenge sent, usually from a password server. -********************************************************************/ - -BOOL set_challenge(unsigned char *challenge) -{ - memcpy(saved_challenge,challenge,8); - challenge_sent = True; - return(True); -} - -/******************************************************************* - Get the last challenge sent. -********************************************************************/ - -BOOL last_challenge(unsigned char *challenge) -{ - if (!challenge_sent) - return(False); - memcpy(challenge,saved_challenge,8); - return(True); -} - /**************************************************************************** Create a UNIX user on demand. ****************************************************************************/ @@ -166,7 +126,6 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, const char *client_domain, const char *domain, const char *wksta_name, - DATA_BLOB sec_blob, DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, DATA_BLOB plaintext, uint32 ntlmssp_flags, BOOL encrypted) @@ -226,7 +185,6 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username)); - (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length); (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length); (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length); (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length); @@ -246,7 +204,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, BOOL make_user_info_map(auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, - const char *wksta_name, DATA_BLOB sec_blob, + const char *wksta_name, DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, DATA_BLOB plaintext, uint32 ntlmssp_flags, BOOL encrypted) @@ -265,7 +223,7 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info, return make_user_info(user_info, smb_name, internal_username, client_domain, domain, - wksta_name, sec_blob, + wksta_name, lm_pwd, nt_pwd, plaintext, ntlmssp_flags, encrypted); @@ -280,12 +238,11 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info, BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - char *wksta_name, uchar chal[8], + char *wksta_name, uchar *lm_network_pwd, int lm_pwd_len, uchar *nt_network_pwd, int nt_pwd_len) { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -301,8 +258,8 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, - wksta_name, sec_blob, - nt_blob, lm_blob, + wksta_name, + lm_blob, nt_blob, plaintext_blob, ntlmssp_flags, True); @@ -320,6 +277,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, char *wksta_name, + char chal[8], uchar lm_interactive_pwd[16], uchar nt_interactive_pwd[16], uchar *dc_sess_key) @@ -329,11 +287,8 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; unsigned char key[16]; - uint8 chal[8]; uint32 ntlmssp_flags = 0; - generate_random_buffer(chal, 8, False); - ZERO_STRUCT(key); memcpy(key, dc_sess_key, 8); @@ -362,7 +317,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - generate_random_buffer(chal, 8, False); SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); @@ -373,7 +327,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -385,7 +338,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, - wksta_name, sec_blob, + wksta_name, local_lm_blob, local_nt_blob, plaintext_blob, @@ -402,13 +355,14 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, - char *username, - char *domain, - char *password) + const char *username, + const char *domain, + const char *password, + char chal[8] /* Give winbind back the challange we used */ + ) { unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; - char chal[8]; DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; DATA_BLOB plaintext_blob; @@ -453,16 +407,11 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); - - if (!sec_blob.data) { - return False; - } ret = make_user_info(user_info, username, username, domain, domain, - global_myname, sec_blob, + global_myname, local_nt_blob, local_lm_blob, plaintext_blob, @@ -483,12 +432,10 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - uchar chal[8], uchar *lm_network_pwd, int lm_pwd_len, uchar *nt_network_pwd, int nt_pwd_len) { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, 8); DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -502,7 +449,7 @@ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, ret = make_user_info(user_info, smb_name, smb_name, client_domain, client_domain, - global_myname, sec_blob, + global_myname, nt_blob, lm_blob, plaintext_blob, ntlmssp_flags, True); @@ -517,59 +464,30 @@ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - DATA_BLOB lm_resp, DATA_BLOB nt_resp, - DATA_BLOB plaintext_password, - BOOL encrypted) + char *smb_name, + char *client_domain, + char chal[8], + DATA_BLOB plaintext_password) { - uchar chal[8]; DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; - DATA_BLOB sec_blob; BOOL ret = False; uint32 ntlmssp_flags = 0; - if (encrypted) { - DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); - if (!last_challenge(chal)) { - DEBUG(0,("Encrypted login but no challange set!\n")); - return False; - } - sec_blob = data_blob(chal, 8); - - if (lm_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - } - if (nt_resp.length == 0) { - } else if (nt_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - } else { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; - } - - return make_user_info_map(user_info, smb_name, - client_domain, - remote_machine, sec_blob, - lm_resp, - nt_resp, - no_plaintext_blob, - ntlmssp_flags, encrypted); - } - - generate_random_buffer(chal, 8, False); - - sec_blob = data_blob(chal, 8); - /* * Not encrypted - do so. */ - DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n")); if (plaintext_password.data) { unsigned char local_lm_response[24]; + +#ifdef DEBUG_PASSWORD + DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length)); + dump_data(100, plaintext_password.data, plaintext_password.length); +#endif SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); @@ -587,23 +505,54 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, remote_machine, - sec_blob, local_lm_blob, local_nt_blob, plaintext_password, - ntlmssp_flags, encrypted); + ntlmssp_flags, False); data_blob_free(&local_lm_blob); return ret; } +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info_for_reply_enc(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + DATA_BLOB lm_resp, DATA_BLOB nt_resp, + DATA_BLOB plaintext_password) +{ + uint32 ntlmssp_flags = 0; + + DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); + + if (lm_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + } + if (nt_resp.length == 0) { + } else if (nt_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + } else { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + + return make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, + lm_resp, + nt_resp, + no_plaintext_blob, + ntlmssp_flags, True); +} + /**************************************************************************** Create a guest user_info blob, for anonymous authenticaion. ****************************************************************************/ BOOL make_user_info_guest(auth_usersupplied_info **user_info) { - DATA_BLOB sec_blob = data_blob(NULL, 0); DATA_BLOB lm_blob = data_blob(NULL, 0); DATA_BLOB nt_blob = data_blob(NULL, 0); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -612,7 +561,7 @@ BOOL make_user_info_guest(auth_usersupplied_info **user_info) return make_user_info(user_info, "","", "","", - "", sec_blob, + "", nt_blob, lm_blob, plaintext_blob, ntlmssp_flags, True); @@ -680,7 +629,6 @@ void free_user_info(auth_usersupplied_info **user_info) SAFE_FREE((*user_info)->internal_username.str); SAFE_FREE((*user_info)->client_domain.str); SAFE_FREE((*user_info)->domain.str); - data_blob_free(&(*user_info)->sec_blob); data_blob_free(&(*user_info)->lm_resp); data_blob_free(&(*user_info)->nt_resp); SAFE_FREE((*user_info)->interactive_password); @@ -725,6 +673,22 @@ BOOL make_server_info_guest(auth_serversupplied_info **server_info) return False; } +/*************************************************************************** + Make an auth_methods struct +***************************************************************************/ + +BOOL make_auth_methods(auth_methods **auth_method) +{ + *auth_method = malloc(sizeof(**auth_method)); + if (!*auth_method) { + DEBUG(0,("make_auth_method: malloc failed!\n")); + return False; + } + ZERO_STRUCTP(*auth_method); + + return True; +} + /**************************************************************************** Delete a SID token. ****************************************************************************/ @@ -764,25 +728,3 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) return token; } - -/**************************************************************************** - Check for a guest logon (username = "") and if so create the required - structure. -****************************************************************************/ - -NTSTATUS check_guest_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - if (!(user_info->internal_username.str - && *user_info->internal_username.str)) { - if (make_server_info_guest(server_info)) { - nt_status = NT_STATUS_OK; - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - } - - return nt_status; -} diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 045e16a9bb..d080c23332 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -27,6 +27,7 @@ extern fstring global_myworkgroup; extern fstring remote_machine; BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; +auth_authsupplied_info *negprot_global_auth_info = NULL; /**************************************************************************** reply for the core protocol @@ -68,6 +69,7 @@ static int reply_lanman1(char *inbuf, char *outbuf) int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; time_t t = time(NULL); + DATA_BLOB cryptkey; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); @@ -77,8 +79,14 @@ static int reply_lanman1(char *inbuf, char *outbuf) set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ - if (global_encrypted_passwords_negotiated) - generate_next_challenge(smb_buf(outbuf)); + if (global_encrypted_passwords_negotiated) { + if (!make_auth_info_subsystem(&negprot_global_auth_info)) { + smb_panic("cannot make_negprot_global_auth_info!\n"); + } + cryptkey = auth_get_challange(negprot_global_auth_info); + memcpy(smb_buf(outbuf), cryptkey.data, 8); + data_blob_free(&cryptkey); + } Protocol = PROTOCOL_LANMAN1; @@ -106,40 +114,26 @@ static int reply_lanman2(char *inbuf, char *outbuf) int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; time_t t = time(NULL); - struct cli_state *cli = NULL; - char cryptkey[8]; - char crypt_len = 0; + DATA_BLOB cryptkey; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); - - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { - DEBUG(3,("using password server validation\n")); - global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); - } - + if (lp_security()>=SEC_USER) secword |= 1; if (global_encrypted_passwords_negotiated) secword |= 2; + set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); + SIVAL(outbuf,smb_vwv6,sys_getpid()); + if (global_encrypted_passwords_negotiated) { - crypt_len = 8; - if (!cli) { - generate_next_challenge(cryptkey); - } else { - memcpy(cryptkey, cli->secblob.data, 8); - set_challenge((unsigned char *)cryptkey); + if (!make_auth_info_subsystem(&negprot_global_auth_info)) { + smb_panic("cannot make_negprot_global_auth_info!\n"); } + cryptkey = auth_get_challange(negprot_global_auth_info); + memcpy(smb_buf(outbuf), cryptkey.data, 8); + data_blob_free(&cryptkey); } - set_message(outbuf,13,crypt_len,True); - SSVAL(outbuf,smb_vwv1,secword); - SIVAL(outbuf,smb_vwv6,sys_getpid()); - if (global_encrypted_passwords_negotiated) - memcpy(smb_buf(outbuf), cryptkey, 8); - Protocol = PROTOCOL_LANMAN2; /* Reply, SMBlockread, SMBwritelock supported. */ @@ -202,45 +196,22 @@ static int reply_nt1(char *inbuf, char *outbuf) int secword=0; time_t t = time(NULL); - struct cli_state *cli = NULL; - uint8 cryptkey[8]; + DATA_BLOB cryptkey; char *p, *q; BOOL negotiate_spnego = False; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); - if (lp_security() == SEC_SERVER) { - DEBUG(5,("attempting password server validation\n")); - cli = server_cryptkey(); - } else { - DEBUG(5,("not attempting password server validation\n")); - /* do spnego in user level security if the client - supports it and we can do encrypted passwords */ - if (global_encrypted_passwords_negotiated && - (lp_security() == SEC_USER || - lp_security() == SEC_DOMAIN) && - (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { - negotiate_spnego = True; - capabilities |= CAP_EXTENDED_SECURITY; - } - } + /* do spnego in user level security if the client + supports it and we can do encrypted passwords */ - if (cli) { - DEBUG(3,("using password server validation\n")); - global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); - } else { - DEBUG(3,("not using password server validation\n")); + if (global_encrypted_passwords_negotiated && + (lp_security() != SEC_SHARE) && + (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { + negotiate_spnego = True; + capabilities |= CAP_EXTENDED_SECURITY; } - if (global_encrypted_passwords_negotiated) { - if (!cli) { - generate_next_challenge((char *)cryptkey); - } else { - memcpy(cryptkey, cli->secblob.data, 8); - set_challenge(cryptkey); - } - } - capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) { @@ -283,7 +254,14 @@ static int reply_nt1(char *inbuf, char *outbuf) p = q = smb_buf(outbuf); if (!negotiate_spnego) { - if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8); + if (global_encrypted_passwords_negotiated) { + if (!make_auth_info_subsystem(&negprot_global_auth_info)) { + smb_panic("cannot make_negprot_global_auth_info!\n"); + } + cryptkey = auth_get_challange(negprot_global_auth_info); + memcpy(p, cryptkey.data, 8); + data_blob_free(&cryptkey); + } SSVALS(outbuf,smb_vwv16+1,8); p += 8; DEBUG(3,("not using SPNEGO\n")); @@ -467,11 +445,6 @@ int reply_negprot(connection_struct *conn, /* possibly reload - change of architecture */ reload_services(True); - /* a special case to stop password server loops */ - if (Index == 1 && strequal(remote_machine,myhostname()) && - (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN)) - exit_server("Password server loop!"); - /* Check for protocols, most desirable first */ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { @@ -508,3 +481,4 @@ int reply_negprot(connection_struct *conn, END_PROFILE(SMBnegprot); return(outsize); } + diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b020cdd5d7..d9322ae26c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1112,19 +1112,23 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - struct cli_state *cli = server_client(); - if (!send_keepalive(smbd_server_fd())) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return False; - } - /* also send a keepalive to the password server if its still - connected */ - if (cli && cli->initialised) - if (!send_keepalive(cli->fd)) { - DEBUG( 2, ( "password server keepalive failed.\n")); - cli_shutdown(cli); - } - last_keepalive_sent_time = t; + extern auth_authsupplied_info *negprot_global_auth_info; + if (!send_keepalive(smbd_server_fd())) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + + /* send a keepalive for a password server or the like. + This is attached to the auth_info created in the + negprot */ + if (negprot_global_auth_info + && negprot_global_auth_info->challange_set_method + && negprot_global_auth_info->challange_set_method->send_keepalive) { + negprot_global_auth_info->challange_set_method->send_keepalive + (&negprot_global_auth_info->challange_set_method->private_data); + } + + last_keepalive_sent_time = t; } /* check for connection timeouts */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b08c8e8bda..2f374e48aa 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -476,7 +476,7 @@ void exit_server(char *reason) { static int firsttime=1; extern char *last_inbuf; - + extern auth_authsupplied_info *negprot_global_auth_info; if (!firsttime) exit(0); @@ -485,6 +485,8 @@ void exit_server(char *reason) change_to_root_user(); DEBUG(2,("Closing connections\n")); + free_auth_info(&negprot_global_auth_info); + conn_close_all(); invalidate_all_vuids(); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b3e9b7be8f..c9db359569 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,6 +23,7 @@ #include "includes.h" uint32 global_client_caps = 0; +static auth_authsupplied_info *ntlmssp_auth_info; /**************************************************************************** Add the standard 'Samba' signature to the end of the session setup. @@ -37,6 +38,31 @@ static void add_signature(char *outbuf) set_message_end(outbuf,p); } +/**************************************************************************** + Do a 'guest' logon, getting back the +****************************************************************************/ +static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) +{ + + auth_authsupplied_info *auth_info; + auth_usersupplied_info *user_info = NULL; + + NTSTATUS nt_status; + char chal[8]; + + ZERO_STRUCT(chal); + + DEBUG(3,("Got anonymous request\n")); + + make_user_info_guest(&user_info); + make_auth_info_fixed(&auth_info, chal); + + nt_status = check_password(user_info, auth_info, server_info); + free_auth_info(&auth_info); + return nt_status; +} + + #if HAVE_KRB5 /**************************************************************************** reply to a session setup spnego negotiate packet for kerberos @@ -189,7 +215,7 @@ static int reply_spnego_negotiate(connection_struct *conn, int i; uint32 ntlmssp_command, neg_flags; DATA_BLOB sess_key, chal, spnego_chal; - uint8 cryptkey[8]; + DATA_BLOB cryptkey; BOOL got_kerberos = False; /* parse out the OIDs and the first sec blob */ @@ -238,10 +264,12 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); - if (!last_challenge(cryptkey)) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + if (!make_auth_info_subsystem(&ntlmssp_auth_info)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); } + cryptkey = auth_get_challange(ntlmssp_auth_info); + /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ @@ -255,7 +283,7 @@ static int reply_spnego_negotiate(connection_struct *conn, 0, 0x30, /* ?? */ neg_flags, - cryptkey, 8, + cryptkey.data, cryptkey.length, 0, 0, 0, 0x3000); /* ?? */ @@ -268,6 +296,7 @@ static int reply_spnego_negotiate(connection_struct *conn, reply_sesssetup_blob(conn, outbuf, spnego_chal); data_blob_free(&chal); + data_blob_free(&cryptkey); data_blob_free(&spnego_chal); /* and tell smbd that we have already replied to this packet */ @@ -286,11 +315,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, char *workgroup, *user, *machine; DATA_BLOB lmhash, nthash, sess_key; DATA_BLOB plaintext_password = data_blob(NULL, 0); - DATA_BLOB sec_blob; uint32 ntlmssp_command, neg_flags; NTSTATUS nt_status; int sess_vuid; - char chal[8]; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; @@ -327,26 +354,19 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, file_save("lmhash1.dat", lmhash.data, lmhash.length); #endif - if (!last_challenge(chal)) { - DEBUG(0,("Encrypted login but no challange set!\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - sec_blob = data_blob(chal, 8); - if (!sec_blob.data) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - if (!make_user_info_map(&user_info, user, workgroup, - machine, sec_blob, + machine, lmhash, nthash, plaintext_password, neg_flags, True)) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - nt_status = check_password(user_info, &server_info); + nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); + free_auth_info(&ntlmssp_auth_info); + free_user_info(&user_info); data_blob_free(&lmhash); @@ -383,18 +403,17 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou int length, int bufsize) { int sess_vuid; - auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; - NTSTATUS nt_status; - DEBUG(3,("Got anonymous request\n")); - - make_user_info_guest(&user_info); + nt_status = check_guest_password(&server_info); - nt_status = check_password(user_info, &server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status_squash(nt_status)); + } sess_vuid = register_vuid(server_info, lp_guestaccount()); + free_server_info(&server_info); if (sess_vuid == -1) { @@ -490,6 +509,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern int max_send; auth_usersupplied_info *user_info = NULL; + extern auth_authsupplied_info *negprot_global_auth_info; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; @@ -523,16 +543,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, lm_resp = data_blob(smb_buf(inbuf), passlen1); } else { plaintext_password = data_blob(smb_buf(inbuf), passlen1+1); - if (!plaintext_password.data) { - DEBUG(0,("reply_sesssetup_and_X: malloc failed for plaintext_password!\n")); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } else { - /* Ensure null termination */ - plaintext_password.data[passlen1] = 0; - } + /* Ensure null termination */ + plaintext_password.data[passlen1] = 0; } srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE); + *domain = 0; } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); @@ -645,15 +661,41 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, *user = 0; } - if (!make_user_info_for_reply(&user_info, - user, domain, - lm_resp, nt_resp, - plaintext_password, doencrypt)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + if (!*user) { + + nt_status = check_guest_password(&server_info); + + } else if (doencrypt) { + if (!make_user_info_for_reply_enc(&user_info, + user, domain, + lm_resp, nt_resp, + plaintext_password)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + nt_status = check_password(user_info, negprot_global_auth_info, &server_info); + + } else { + auth_authsupplied_info *plaintext_auth_info = NULL; + DATA_BLOB chal; + if (!make_auth_info_subsystem(&plaintext_auth_info)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + chal = auth_get_challange(plaintext_auth_info); + + if (!make_user_info_for_reply(&user_info, + user, domain, chal.data, + plaintext_password)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + nt_status = check_password(user_info, plaintext_auth_info, &server_info); + + data_blob_free(&chal); + free_auth_info(&plaintext_auth_info); } - - nt_status = check_password(user_info, &server_info); - + free_user_info(&user_info); data_blob_free(&lm_resp); @@ -726,3 +768,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, END_PROFILE(SMBsesssetupX); return chain_reply(inbuf,outbuf,length,bufsize); } + + + + + -- cgit From 4f37307452ff77e8058dd2107f0b88fe64b3ba5e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 24 Nov 2001 12:16:27 +0000 Subject: And add the winbind module I missed in the last run. (large change to modularise the auth subsystem) Andrew Bartlett (This used to be commit 324c4676280641fee0647221dba1e826e03ba9ab) --- source3/smbd/auth_winbind.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 source3/smbd/auth_winbind.c (limited to 'source3/smbd') diff --git a/source3/smbd/auth_winbind.c b/source3/smbd/auth_winbind.c new file mode 100644 index 0000000000..c29d008f4a --- /dev/null +++ b/source3/smbd/auth_winbind.c @@ -0,0 +1,111 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + + Winbind authentication mechnism + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Bartlett 2001 + + 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" + +/* Prototypes from common.h */ + +NSS_STATUS winbindd_request(int req_type, + struct winbindd_request *request, + struct winbindd_response *response); + + +/* Authenticate a user with a challenge/response */ + +static NTSTATUS check_winbind_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + struct passwd *pw; + NTSTATUS nt_status; + + if (!user_info) { + return NT_STATUS_LOGON_FAILURE; + } + + if (!auth_info) { + DEBUG(3,("Password for user %s cannot be checked becouse we have no auth_info to get the challange from.\n", + user_info->internal_username.str)); + return NT_STATUS_LOGON_FAILURE; + } + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + snprintf(request.data.auth_crap.user, sizeof(request.data.auth_crap.user), + "%s\\%s", user_info->domain.str, user_info->smb_name.str); + + memcpy(request.data.auth_crap.chal, auth_info->challange.data, sizeof(request.data.auth_crap.chal)); + + request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length, + sizeof(request.data.auth_crap.lm_resp)); + request.data.auth_crap.nt_resp_len = MIN(user_info->nt_resp.length, + sizeof(request.data.auth_crap.nt_resp)); + + memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data, + sizeof(request.data.auth_crap.lm_resp_len)); + memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data, + request.data.auth_crap.lm_resp_len); + + result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); + + if (result == NSS_STATUS_SUCCESS) { + + pw = Get_Pwnam(user_info->internal_username.str); + + if (pw) { + if (make_server_info_pw(server_info, pw)) { + nt_status = NT_STATUS_OK; + } else { + nt_status = NT_STATUS_NO_MEMORY; + } + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } else { + nt_status = NT_STATUS_LOGON_FAILURE; + } + + return nt_status; +} + +BOOL auth_init_winbind(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_winbind_security; + return True; +} + + + + -- cgit From 0ebb29e032f2cdbfdb55184c0b97fd1f71b84609 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Nov 2001 13:58:40 +0000 Subject: removed unused function (This used to be commit ad7afbfdea600a62fa1550bd354996ad38807533) --- source3/smbd/mangle.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 1b7f9d0c05..cfa2792395 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -64,24 +64,6 @@ BOOL init_mangle_tdb(void) return True; } -/* trasform a dos charset string in a terminated unicode string */ -static int dos_to_ucs2(void *dest, const char *src, int dest_len) -{ - int len=0; - int src_len = strlen(src) + 1; - - /* treat a pstring as "unlimited" length */ - if (dest_len == -1) { - dest_len = sizeof(pstring); - } - - /* ucs2 is always a multiple of 2 bytes */ - dest_len &= ~1; - - len = convert_string(CH_DOS, CH_UCS2, src, src_len, dest, dest_len); - return len; -} - /* trasform a unicode string into a dos charset string */ static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len) { -- cgit From ad2974cd05b4d08c8b92f505bf95aa8e8533235f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Nov 2001 14:16:41 +0000 Subject: added "net join" command this completes the first stage of the smbd ADS support (This used to be commit 058a5aee901e6609969ef7e1d482a720a84a4a12) --- source3/smbd/sesssetup.c | 43 +++++-------------------------------------- 1 file changed, 5 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c9db359569..854513bb47 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -73,16 +73,12 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB *secblob) { DATA_BLOB ticket; - krb5_context context; - krb5_auth_context auth_context = NULL; - krb5_keytab keytab = NULL; - krb5_data packet; - krb5_ticket *tkt = NULL; - int ret; char *realm, *client, *p; const struct passwd *pw; char *user; int sess_vuid; + NTSTATUS ret; + DATA_BLOB auth_data; auth_serversupplied_info *server_info = NULL; realm = lp_realm(); @@ -91,38 +87,9 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = krb5_init_context(&context); - if (ret) { - DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - packet.length = ticket.length; - packet.data = (krb5_pointer)ticket.data; - -#if 0 - file_save("/tmp/ticket.dat", ticket.data, ticket.length); -#endif - - if ((ret = krb5_rd_req(context, &auth_context, &packet, - NULL, keytab, NULL, &tkt))) { - DEBUG(3,("krb5_rd_req failed (%s)\n", - error_message(ret))); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - -#if 0 - if (tkt->enc_part2) { - file_save("/tmp/authdata.dat", - tkt->enc_part2->authorization_data[0]->contents, - tkt->enc_part2->authorization_data[0]->length); - } -#endif - - if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, - &client))) { - DEBUG(3,("krb5_unparse_name failed (%s)\n", - error_message(ret))); + ret = ads_verify_ticket(&ticket, &client, &auth_data); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(1,("Failed to verify incoming ticket!\n")); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -- cgit From a8982ca90cafc62da678065cdb93d60ac2033182 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 25 Nov 2001 02:23:22 +0000 Subject: I think this is a fix for the "out of space" errors with oplocks=no. Jeremy. (This used to be commit 84b62d3c8ebd78cd578ac36168631b3bbcafdd8c) --- source3/smbd/reply.c | 107 ++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1412905cdf..675c06f75f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1904,67 +1904,76 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize) { - size_t numtowrite; - ssize_t nwritten = -1; - SMB_OFF_T startpos; - char *data; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - int outsize = 0; - START_PROFILE(SMBwrite); + size_t numtowrite; + ssize_t nwritten = -1; + SMB_OFF_T startpos; + char *data; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + int outsize = 0; + START_PROFILE(SMBwrite); - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) { - END_PROFILE(SMBwrite); - return reply_pipe_write(inbuf,outbuf,size,dum_buffsize); - } + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) { + END_PROFILE(SMBwrite); + return reply_pipe_write(inbuf,outbuf,size,dum_buffsize); + } - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - data = smb_buf(inbuf) + 3; + numtowrite = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { - END_PROFILE(SMBwrite); - return ERROR_DOS(ERRDOS,ERRlock); - } + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + END_PROFILE(SMBwrite); + return ERROR_DOS(ERRDOS,ERRlock); + } - /* X/Open SMB protocol says that if smb_vwv1 is - zero then the file size should be extended or - truncated to the size given in smb_vwv[2-3] */ - if(numtowrite == 0) { - /* This is actually an allocate call, not set EOF. JRA */ - nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos); - if (nwritten < 0) { - END_PROFILE(SMBwrite); - return ERROR_NT(NT_STATUS_DISK_FULL); - } - } else - nwritten = write_file(fsp,data,startpos,numtowrite); + /* + * X/Open SMB protocol says that if smb_vwv1 is + * zero then the file size should be extended or + * truncated to the size given in smb_vwv[2-3]. + */ + + if(numtowrite == 0) { + /* + * This is actually an allocate call, and set EOF. JRA. + */ + nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos); + if (nwritten < 0) { + END_PROFILE(SMBwrite); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos); + if (nwritten < 0) { + END_PROFILE(SMBwrite); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else + nwritten = write_file(fsp,data,startpos,numtowrite); - if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); + if (lp_syncalways(SNUM(conn))) + sync_file(conn,fsp); - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { - END_PROFILE(SMBwrite); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + END_PROFILE(SMBwrite); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,nwritten); + SSVAL(outbuf,smb_vwv0,nwritten); - if (nwritten < (ssize_t)numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; - SSVAL(outbuf,smb_err,ERRdiskfull); - } + if (nwritten < (ssize_t)numtowrite) { + CVAL(outbuf,smb_rcls) = ERRHRD; + SSVAL(outbuf,smb_err,ERRdiskfull); + } - DEBUG(3,("write fnum=%d num=%d wrote=%d\n", - fsp->fnum, (int)numtowrite, (int)nwritten)); + DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); - END_PROFILE(SMBwrite); - return(outsize); + END_PROFILE(SMBwrite); + return(outsize); } -- cgit From 1b1b8e39b2ce4bf32517e7178ca18b3fd8fecd03 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 25 Nov 2001 03:01:14 +0000 Subject: Add the PDC end of the smbtorture test for creating an NT_STATUS -> DOS error map. This little authentication module is #ifdef DEVELOPER, becouse it really is of no use execept as a development tool invoke by setting: auth methods = guest sam name_to_ntstatus in the smb.conf file (the SAM and guest elements are required for the member server to authenticate itself). Andrew Bartlett (This used to be commit 9807e66f34c1088399657060977e384c5a7f0664) --- source3/smbd/auth_builtin.c | 33 +++++++++++++++++++++++++++++++++ source3/smbd/auth_info.c | 3 +++ 2 files changed, 36 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/auth_builtin.c b/source3/smbd/auth_builtin.c index 6ea6d0bbe0..482ae6dee1 100644 --- a/source3/smbd/auth_builtin.c +++ b/source3/smbd/auth_builtin.c @@ -85,3 +85,36 @@ BOOL auth_init_local(auth_methods **auth_method) return True; } +/**************************************************************************** + Return an error based on username +****************************************************************************/ + +static NTSTATUS check_name_to_ntstatus_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status; + fstring user; + long error_num; + fstrcpy(user, user_info->smb_name.str); + strlower(user); + error_num = strtoul(user, NULL, 16); + + DEBUG(5,("Error for user %s was %lx\n", user, error_num)); + + nt_status = NT_STATUS(error_num); + + return nt_status; +} + +BOOL auth_init_name_to_ntstatus(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_name_to_ntstatus_security; + return True; +} + diff --git a/source3/smbd/auth_info.c b/source3/smbd/auth_info.c index 12b843d781..b1c994d54f 100644 --- a/source3/smbd/auth_info.c +++ b/source3/smbd/auth_info.c @@ -31,6 +31,9 @@ const struct auth_init_function builtin_auth_init_functions[] = { { "smbserver", auth_init_smbserver }, { "ntdomain", auth_init_ntdomain }, { "winbind", auth_init_winbind }, +#ifdef DEVELOPER + { "name_to_ntstatus", auth_init_name_to_ntstatus }, +#endif { NULL, NULL} }; -- cgit From 391a72a95fda1a4d1841c29257b5001435c09dc1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 25 Nov 2001 08:26:37 +0000 Subject: #ifdefed DMF fix so not compiled by default. We need to look at this... Jeremy. (This used to be commit 97dca242a91c68048e510f42be53421b533183be) --- source3/smbd/fileio.c | 61 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index edf58d4a8e..38da96b741 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -91,34 +91,51 @@ read from a file ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { - ssize_t ret=0,readret; + ssize_t ret=0,readret; - /* you can't read from print files */ - if (fsp->print_file) { - return -1; - } + /* you can't read from print files */ + if (fsp->print_file) + return -1; - /* - * Serve from write cache if we can. - */ - if(read_from_write_cache(fsp, data, pos, n)) - return n; + /* + * Serve from write cache if we can. + */ - flush_write_cache(fsp, READ_FLUSH); + if(read_from_write_cache(fsp, data, pos, n)) + return n; - if (seek_file(fsp,pos) == -1) { - DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); - return(ret); - } + flush_write_cache(fsp, READ_FLUSH); + + if (seek_file(fsp,pos) == -1) { + DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); + return(ret); + } - if (n > 0) { - readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); - if (readret == -1) - return -1; - if (readret > 0) ret += readret; - } + if (n > 0) { +#ifdef DMF_FIX + int numretries = 3; +tryagain: + readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); + if (readret == -1) { + if ((errno == EAGAIN) && numretries) { + DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); + (void)sleep(10); + --numretries; + goto tryagain; + } + return -1; + } +#else /* NO DMF fix. */ + readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); + if (readret == -1) + return -1; +#endif + + if (readret > 0) + ret += readret; + } - return(ret); + return(ret); } /* how many write cache buffers have been allocated */ -- cgit From 481c644b7b32aa876c69153760fe8a460eea0e69 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 25 Nov 2001 23:05:13 +0000 Subject: added 'security=ADS' (This used to be commit 5a735a88e472a48cd4329832998dc31c1e230ecb) --- source3/smbd/negprot.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index d080c23332..8a01a59bf2 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -171,6 +171,13 @@ static int negprot_spnego(char *p) safe_strcpy((char *)guid, global_myname, 16); strlower((char *)guid); + /* strangely enough, NT does not sent the single OID NTLMSSP when + not a ADS member, it sends no OIDs at all */ + if (lp_security() != SEC_ADS) { + memcpy(p, guid, 16); + return 16; + } + /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ asprintf(&principal, "HOST/%s@%s", guid, lp_realm()); -- cgit From 03439e183686567f632fa9c085691c4bb8d3e365 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 Nov 2001 00:43:37 +0000 Subject: fixed spnego, non-kerberos negprot (This used to be commit 2e916222a915c27f919a9841bde5ba0967af2190) --- source3/smbd/negprot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 8a01a59bf2..a2666ae24e 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -271,6 +271,8 @@ static int reply_nt1(char *inbuf, char *outbuf) } SSVALS(outbuf,smb_vwv16+1,8); p += 8; + p += srvstr_push(outbuf, p, global_myworkgroup, -1, + STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); } else { int len = negprot_spnego(p); @@ -279,8 +281,6 @@ static int reply_nt1(char *inbuf, char *outbuf) p += len; DEBUG(3,("using SPNEGO\n")); } - p += srvstr_push(outbuf, p, global_myworkgroup, -1, - STR_UNICODE|STR_TERMINATE|STR_NOALIGN); SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */ set_message_end(outbuf, p); -- cgit From e75ad578d2578d756b7672fbf12d16f0823d472b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 26 Nov 2001 01:37:01 +0000 Subject: This compleats the of the authenticaion subystem into the new 'auth' subdirectory. (The insertion of these files was done with some CVS backend magic, hence the lack of a commit message). This also moves libsmb/domain_client_validate.c back into auth_domain.c, becouse we no longer share it with winbind. Andrew Bartlett (This used to be commit 782835470cb68da2188a57007d6f55c17b094d08) --- source3/smbd/auth.c | 268 ---------------- source3/smbd/auth_builtin.c | 120 ------- source3/smbd/auth_domain.c | 85 ----- source3/smbd/auth_info.c | 282 ---------------- source3/smbd/auth_rhosts.c | 228 ------------- source3/smbd/auth_server.c | 354 -------------------- source3/smbd/auth_smbpasswd.c | 412 ------------------------ source3/smbd/auth_unix.c | 125 -------- source3/smbd/auth_util.c | 730 ------------------------------------------ source3/smbd/auth_winbind.c | 111 ------- 10 files changed, 2715 deletions(-) delete mode 100644 source3/smbd/auth.c delete mode 100644 source3/smbd/auth_builtin.c delete mode 100644 source3/smbd/auth_domain.c delete mode 100644 source3/smbd/auth_info.c delete mode 100644 source3/smbd/auth_rhosts.c delete mode 100644 source3/smbd/auth_server.c delete mode 100644 source3/smbd/auth_smbpasswd.c delete mode 100644 source3/smbd/auth_unix.c delete mode 100644 source3/smbd/auth_util.c delete mode 100644 source3/smbd/auth_winbind.c (limited to 'source3/smbd') diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c deleted file mode 100644 index c62e2ed5a0..0000000000 --- a/source3/smbd/auth.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Password and authentication handling - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Andrew Bartlett 2001 - - 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" - -/**************************************************************************** - Check user is in correct domain if required -****************************************************************************/ - -static BOOL check_domain_match(char *user, char *domain) -{ - /* - * If we aren't serving to trusted domains, we must make sure that - * the validation request comes from an account in the same domain - * as the Samba server - */ - - if (!lp_allow_trusted_domains() && - (!strequal(lp_workgroup(), domain) || strequal("", domain))) { - DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain)); - return False; - } else { - return True; - } -} - -/**************************************************************************** - Check a users password, as given in the user-info struct and return various - interesting details in the server_info struct. - - This functions does NOT need to be in a become_root()/unbecome_root() pair - as it makes the calls itself when needed. - - The return value takes precedence over the contents of the server_info - struct. When the return is other than NT_STATUS_NOPROBLEMO the contents - of that structure is undefined. - -****************************************************************************/ - -NTSTATUS check_password(const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - const char *pdb_username; - auth_methods *auth_method; - - if (!user_info || !auth_info || !server_info) { - return NT_STATUS_LOGON_FAILURE; - } - - DEBUG(3, ("check_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", - user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str)); - - DEBUG(3, ("check_password: mapped user is: [%s]\\[%s]@[%s]\n", - user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str)); - DEBUG(10, ("auth_info challange created by %s\n", auth_info->challange_set_by)); - DEBUG(10, ("challange is: \n")); - dump_data(5, (auth_info)->challange.data, (auth_info)->challange.length); - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("user_info has passwords of length %d and %d\n", - user_info->lm_resp.length, user_info->nt_resp.length)); - DEBUG(100, ("lm:\n")); - dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length); - DEBUG(100, ("nt:\n")); - dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length); -#endif - - for (auth_method = auth_info->auth_method_list;auth_method; auth_method = auth_method->next) - { - nt_status = auth_method->auth(auth_method->private_data, user_info, auth_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_password: %s authentication for user [%s] suceeded\n", - auth_method->name, user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: %s authentication for user [%s] FAILED with error %s\n", - auth_method->name, user_info->smb_name.str, get_nt_error_msg(nt_status))); - } - - if (NT_STATUS_IS_OK(nt_status)) { - break; - } - } - - /* This needs to be sorted: If it doesn't match, what should we do? */ - if (!check_domain_match(user_info->smb_name.str, user_info->domain.str)) { - return NT_STATUS_LOGON_FAILURE; - } - - - /* This is one of the few places the *relies* (rather than just sets defaults - on the value of lp_security(). This needs to change. A new paramater - perhaps? */ - if (lp_security() >= SEC_SERVER) { - smb_user_control(user_info, *server_info, nt_status); - } - - if (NT_STATUS_IS_OK(nt_status)) { - pdb_username = pdb_get_username((*server_info)->sam_account); - if (!(*server_info)->guest) { - /* We might not be root if we are an RPC call */ - become_root(); - nt_status = smb_pam_accountcheck(pdb_username); - unbecome_root(); - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", - pdb_username)); - } else { - DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", - pdb_username, get_nt_error_msg(nt_status))); - } - } - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG((*server_info)->guest ? 5 : 2, - ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", - (*server_info)->guest ? "guest " : "", - user_info->smb_name.str, - user_info->internal_username.str, - pdb_username)); - } - } - - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(2, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", - user_info->smb_name.str, user_info->internal_username.str, - get_nt_error_msg(nt_status))); - ZERO_STRUCTP(server_info); - } - return nt_status; - -} - -/**************************************************************************** - Squash an NT_STATUS return in line with requirements for unauthenticated - connections. (session setups in particular) -****************************************************************************/ - -NTSTATUS nt_status_squash(NTSTATUS nt_status) -{ - if NT_STATUS_IS_OK(nt_status) { - return nt_status; - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { - /* Match WinXP and don't give the game away */ - return NT_STATUS_LOGON_FAILURE; - - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { - /* Match WinXP and don't give the game away */ - return NT_STATUS_LOGON_FAILURE; - } else { - return nt_status; - } -} - - - -/**************************************************************************** - COMPATABILITY INTERFACES: - ***************************************************************************/ - -/**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash -return True if the password is correct, False otherwise -****************************************************************************/ - -static NTSTATUS pass_check_smb(char *smb_name, - char *domain, - DATA_BLOB lm_pwd, - DATA_BLOB nt_pwd, - DATA_BLOB plaintext_password, - BOOL encrypted) - -{ - NTSTATUS nt_status; - auth_usersupplied_info *user_info = NULL; - extern auth_authsupplied_info *negprot_global_auth_info; - auth_serversupplied_info *server_info = NULL; - if (encrypted) { - make_user_info_for_reply_enc(&user_info, smb_name, - domain, - lm_pwd, - nt_pwd, - plaintext_password); - nt_status = check_password(user_info, negprot_global_auth_info, &server_info); - } else { - auth_authsupplied_info *plaintext_auth_info = NULL; - DATA_BLOB chal; - if (!make_auth_info_subsystem(&plaintext_auth_info)) { - return NT_STATUS_NO_MEMORY; - } - - chal = auth_get_challange(plaintext_auth_info); - - if (!make_user_info_for_reply(&user_info, - smb_name, domain, chal.data, - plaintext_password)) { - return NT_STATUS_NO_MEMORY; - } - - nt_status = check_password(user_info, plaintext_auth_info, &server_info); - - data_blob_free(&chal); - free_auth_info(&plaintext_auth_info); - } - free_user_info(&user_info); - free_server_info(&server_info); - return nt_status; -} - -/**************************************************************************** -check if a username/password pair is OK either via the system password -database or the encrypted SMB password database -return True if the password is correct, False otherwise -****************************************************************************/ -BOOL password_ok(char *smb_name, DATA_BLOB password_blob) -{ - - DATA_BLOB null_password = data_blob(NULL, 0); - extern BOOL global_encrypted_passwords_negotiated; - BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24); - - if (encrypted) { - /* - * The password could be either NTLM or plain LM. Try NTLM first, - * but fall-through as required. - * NTLMv2 makes no sense here. - */ - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) { - return True; - } - - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) { - return True; - } - } else { - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) { - return True; - } - } - - return False; -} - - diff --git a/source3/smbd/auth_builtin.c b/source3/smbd/auth_builtin.c deleted file mode 100644 index 482ae6dee1..0000000000 --- a/source3/smbd/auth_builtin.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0. - Generic authenticaion types - Copyright (C) Andrew Bartlett 2001 - - 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" - -/**************************************************************************** - Check for a guest logon (username = "") and if so create the required - structure. -****************************************************************************/ - -static NTSTATUS check_guest_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - if (!(user_info->internal_username.str - && *user_info->internal_username.str)) { - if (make_server_info_guest(server_info)) { - nt_status = NT_STATUS_OK; - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - } - - return nt_status; -} - -BOOL auth_init_guest(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - - (*auth_method)->auth = check_guest_security; - return True; -} - -/**************************************************************************** - Check against either sam or unix, depending on encryption. -****************************************************************************/ - -static NTSTATUS check_local_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - if (user_info->encrypted) { - nt_status = check_sam_security(my_private_data, user_info, auth_info, server_info); - } else { - nt_status = check_unix_security(my_private_data, user_info, auth_info, server_info); - } - - return nt_status; -} - -BOOL auth_init_local(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - - (*auth_method)->auth = check_local_security; - return True; -} - -/**************************************************************************** - Return an error based on username -****************************************************************************/ - -static NTSTATUS check_name_to_ntstatus_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status; - fstring user; - long error_num; - fstrcpy(user, user_info->smb_name.str); - strlower(user); - error_num = strtoul(user, NULL, 16); - - DEBUG(5,("Error for user %s was %lx\n", user, error_num)); - - nt_status = NT_STATUS(error_num); - - return nt_status; -} - -BOOL auth_init_name_to_ntstatus(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - - (*auth_method)->auth = check_name_to_ntstatus_security; - return True; -} - diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c deleted file mode 100644 index ef0e5b2f10..0000000000 --- a/source3/smbd/auth_domain.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Authenticate against a remote domain - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Andrew Bartlett 2001 - - 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" - -BOOL global_machine_password_needs_changing = False; - -/**************************************************************************** - Check for a valid username and password in security=domain mode. -****************************************************************************/ - -static NTSTATUS check_ntdomain_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - char *p, *pserver; - unsigned char trust_passwd[16]; - time_t last_change_time; - - become_root(); - - /* - * Get the machine account password for our primary domain - */ - - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) - { - DEBUG(0, ("check_domain_security: could not fetch trust account password for domain %s\n", lp_workgroup())); - unbecome_root(); - return NT_STATUS_LOGON_FAILURE; - } - - unbecome_root(); - - /* Test if machine password is expired and need to be changed */ - if (time(NULL) > last_change_time + lp_machine_password_timeout()) - { - global_machine_password_needs_changing = True; - } - - /* - * Treat each name in the 'password server =' line as a potential - * PDC/BDC. Contact each in turn and try and authenticate. - */ - - pserver = lp_passwordserver(); - if (! *pserver) pserver = "*"; - p = pserver; - - nt_status = domain_client_validate(user_info, (uchar *)auth_info->challange.data,server_info, - p, trust_passwd, last_change_time); - - return nt_status; -} - -BOOL auth_init_ntdomain(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - - (*auth_method)->auth = check_ntdomain_security; - return True; -} diff --git a/source3/smbd/auth_info.c b/source3/smbd/auth_info.c deleted file mode 100644 index b1c994d54f..0000000000 --- a/source3/smbd/auth_info.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0. - Authentication utility functions - Copyright (C) Andrew Bartlett 2001 - - 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" - -const struct auth_init_function builtin_auth_init_functions[] = { - { "guest", auth_init_guest }, - { "rhosts", auth_init_rhosts }, - { "hostsequiv", auth_init_hostsequiv }, - { "sam", auth_init_sam }, - { "unix", auth_init_unix }, - { "local", auth_init_local }, - { "smbserver", auth_init_smbserver }, - { "ntdomain", auth_init_ntdomain }, - { "winbind", auth_init_winbind }, -#ifdef DEVELOPER - { "name_to_ntstatus", auth_init_name_to_ntstatus }, -#endif - { NULL, NULL} -}; - -/*************************************************************************** - Make a auth_info struct -***************************************************************************/ - -static BOOL make_auth_info(auth_authsupplied_info **auth_info) -{ - *auth_info = malloc(sizeof(**auth_info)); - if (!*auth_info) { - DEBUG(0,("make_auth_info: malloc failed!\n")); - return False; - } - ZERO_STRUCTP(*auth_info); - - return True; -} - -/*************************************************************************** - Make a auth_info struct with a specified list. -***************************************************************************/ - -BOOL make_auth_info_list(auth_authsupplied_info **auth_info, auth_methods *list) -{ - if (!make_auth_info(auth_info)) { - return False; - } - - (*auth_info)->auth_method_list = list; - - return True; -} - -/*************************************************************************** - Make a auth_info struct for the auth subsystem -***************************************************************************/ - -static BOOL make_auth_info_text_list(auth_authsupplied_info **auth_info, char **text_list) -{ - auth_methods *list = NULL; - auth_methods *t = NULL; - auth_methods *tmp; - int i; - - for (;*text_list; text_list++) - { - DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list)); - for (i = 0; builtin_auth_init_functions[i].name; i++) - { - if (strequal(builtin_auth_init_functions[i].name, *text_list)) - { - DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i)); - /* Malloc entry, fill it, link it */ - t = (auth_methods *)malloc(sizeof(*t)); - if (!t) { - DEBUG(0,("make_pw_chat: malloc failed!\n")); - return False; - } - - ZERO_STRUCTP(t); - - if (builtin_auth_init_functions[i].init(&t)) { - DEBUG(5,("auth method %s has a valid init\n", *text_list)); - t->name = builtin_auth_init_functions[i].name; - DLIST_ADD_END(list, t, tmp); - } else { - DEBUG(5,("auth method %s DOES NOT have a valid init\n", *text_list)); - } - break; - } - } - } - - make_auth_info_list(auth_info, list); - - return True; -} - -/*************************************************************************** - Make a auth_info struct for the auth subsystem -***************************************************************************/ - -BOOL make_auth_info_subsystem(auth_authsupplied_info **auth_info) -{ - char **auth_method_list = NULL; - - if (!make_auth_info(auth_info)) { - return False; - } - - if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) { - return False; - } - - if (auth_method_list == NULL) { - switch (lp_security()) - { - case SEC_DOMAIN: - DEBUG(5,("Making default auth method list for security=domain\n")); - auth_method_list = lp_list_make("guest ntdomain local"); - break; - case SEC_SERVER: - DEBUG(5,("Making default auth method list for security=server\n")); - auth_method_list = lp_list_make("guest smbserver local"); - break; - case SEC_USER: - DEBUG(5,("Making default auth method list for security=user\n")); - auth_method_list = lp_list_make("guest local"); - break; - case SEC_SHARE: - DEBUG(5,("Making default auth method list for security=share\n")); - auth_method_list = lp_list_make("guest local"); - break; - } - } else { - DEBUG(5,("Using specified auth order\n")); - } - - if (!make_auth_info_text_list(auth_info, auth_method_list)) { - lp_list_free(&auth_method_list); - return False; - } - - lp_list_free(&auth_method_list); - return True; -} - -/*************************************************************************** - Make a auth_info struct with a random challange -***************************************************************************/ - -BOOL make_auth_info_random(auth_authsupplied_info **auth_info) -{ - uchar chal[8]; - if (!make_auth_info_subsystem(auth_info)) { - return False; - } - - generate_random_buffer(chal, sizeof(chal), False); - (*auth_info)->challange = data_blob(chal, sizeof(chal)); - - (*auth_info)->challange_set_by = "random"; - - return True; -} - -/*************************************************************************** - Make a auth_info struct with a fixed challange -***************************************************************************/ - -BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) -{ - if (!make_auth_info_subsystem(auth_info)) { - return False; - } - - (*auth_info)->challange = data_blob(chal, 8); - return True; -} - -/*************************************************************************** - Clear out a auth_info struct that has been allocated -***************************************************************************/ - -void free_auth_info(auth_authsupplied_info **auth_info) -{ - auth_methods *list; - if (*auth_info != NULL) { - list = (*auth_info)->auth_method_list; - while (list) { - auth_methods *old_head = list; - if (list->free_private_data) { - list->free_private_data(&(list->private_data)); - } - DLIST_REMOVE(list, list); - SAFE_FREE(old_head); - } - - data_blob_free(&(*auth_info)->challange); - ZERO_STRUCT(**auth_info); - } - SAFE_FREE(*auth_info); -} - -/**************************************************************************** - Try to get a challange out of the various authenticaion modules. - It is up to the caller to free it. -****************************************************************************/ - -DATA_BLOB auth_get_challange(auth_authsupplied_info *auth_info) -{ - DATA_BLOB challange = data_blob(NULL, 0); - char *challange_set_by = NULL; - auth_methods *auth_method; - - if (auth_info->challange.length) { - DEBUG(5, ("auth_get_challange: returning previous challange (normal)\n")); - return data_blob(auth_info->challange.data, auth_info->challange.length); - } - - for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next) - { - if (auth_method->get_chal) { - DEBUG(5, ("auth_get_challange: getting challange from module %s\n", auth_method->name)); - if (challange_set_by) { - DEBUG(1, ("auth_get_challange: CONFIGURATION ERROR: authenticaion method %s has already specified a challange. Challange by %s ignored.\n", - challange_set_by, auth_method->name)); - } else { - challange = auth_method->get_chal(&auth_method->private_data, auth_info); - if (challange.length) { - DEBUG(5, ("auth_get_challange: sucessfully got challange from module %s\n", auth_method->name)); - auth_info->challange = challange; - challange_set_by = auth_method->name; - auth_info->challange_set_method = auth_method; - } else { - DEBUG(3, ("auth_get_challange: getting challange from authenticaion method %s FAILED.\n", - auth_method->name)); - } - } - } else { - DEBUG(5, ("auth_get_challange: module %s did not want to specify a challange\n", auth_method->name)); - } - } - - if (!challange_set_by) { - uchar chal[8]; - - generate_random_buffer(chal, sizeof(chal), False); - auth_info->challange = data_blob(chal, sizeof(chal)); - - challange_set_by = "random"; - } - - DEBUG(5, ("auth_info challange created by %s\n", challange_set_by)); - DEBUG(5, ("challange is: \n")); - dump_data(5, auth_info->challange.data, (auth_info)->challange.length); - - SMB_ASSERT(auth_info->challange.length == 8); - - auth_info->challange_set_by=challange_set_by; - - return data_blob(auth_info->challange.data, auth_info->challange.length); -} - - diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c deleted file mode 100644 index 2605f0770a..0000000000 --- a/source3/smbd/auth_rhosts.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Main SMB reply routines - Copyright (C) Andrew Tridgell 1992-1998 - - 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" - -/**************************************************************************** - Read the a hosts.equiv or .rhosts file and check if it - allows this user from this machine. -****************************************************************************/ - -static BOOL check_user_equiv(const char *user, const char *remote, const char *equiv_file) -{ - int plus_allowed = 1; - char *file_host; - char *file_user; - char **lines = file_lines_load(equiv_file, NULL); - int i; - - DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); - if (! lines) return False; - for (i=0; lines[i]; i++) { - char *buf = lines[i]; - trim_string(buf," "," "); - - if (buf[0] != '#' && buf[0] != '\n') - { - BOOL is_group = False; - int plus = 1; - char *bp = buf; - if (strcmp(buf, "NO_PLUS\n") == 0) - { - DEBUG(6, ("check_user_equiv NO_PLUS\n")); - plus_allowed = 0; - } - else { - if (buf[0] == '+') - { - bp++; - if (*bp == '\n' && plus_allowed) - { - /* a bare plus means everbody allowed */ - DEBUG(6, ("check_user_equiv everybody allowed\n")); - file_lines_free(lines); - return True; - } - } - else if (buf[0] == '-') - { - bp++; - plus = 0; - } - if (*bp == '@') - { - is_group = True; - bp++; - } - file_host = strtok(bp, " \t\n"); - file_user = strtok(NULL, " \t\n"); - DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", - file_user ? file_user : "(null)" )); - if (file_host && *file_host) - { - BOOL host_ok = False; - -#if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN) - if (is_group) - { - static char *mydomain = NULL; - if (!mydomain) - yp_get_default_domain(&mydomain); - if (mydomain && innetgr(file_host,remote,user,mydomain)) - host_ok = True; - } -#else - if (is_group) - { - DEBUG(1,("Netgroups not configured\n")); - continue; - } -#endif - - /* is it this host */ - /* the fact that remote has come from a call of gethostbyaddr - * means that it may have the fully qualified domain name - * so we could look up the file version to get it into - * a canonical form, but I would rather just type it - * in full in the equiv file - */ - if (!host_ok && !is_group && strequal(remote, file_host)) - host_ok = True; - - if (!host_ok) - continue; - - /* is it this user */ - if (file_user == 0 || strequal(user, file_user)) - { - DEBUG(5, ("check_user_equiv matched %s%s %s\n", - (plus ? "+" : "-"), file_host, - (file_user ? file_user : ""))); - file_lines_free(lines); - return (plus ? True : False); - } - } - } - } - } - file_lines_free(lines); - return False; -} - - -/**************************************************************************** -check for a possible hosts equiv or rhosts entry for the user -****************************************************************************/ - -static BOOL check_hosts_equiv(struct passwd *pass) -{ - char *fname = NULL; - - if (!pass) - return(False); - - fname = lp_hosts_equiv(); - - /* note: don't allow hosts.equiv on root */ - if (fname && *fname && (pass->pw_uid != 0)) { - if (check_user_equiv(pass->pw_name,client_name(),fname)) - return(True); - } - - return(False); -} - - -/**************************************************************************** - Check for a valid .rhosts/hosts.equiv entry for this user -****************************************************************************/ - -static NTSTATUS check_hostsequiv_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - struct passwd *pass = Get_Pwnam(user_info->internal_username.str); - - if (pass) { - if (check_hosts_equiv(pass)) { - nt_status = NT_STATUS_OK; - make_server_info_pw(server_info, pass); - } - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - - return nt_status; -} - - -/**************************************************************************** - Check for a valid .rhosts/hosts.equiv entry for this user -****************************************************************************/ - -static NTSTATUS check_rhosts_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - struct passwd *pass = Get_Pwnam(user_info->internal_username.str); - pstring rhostsfile; - - if (pass) { - char *home = pass->pw_dir; - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - become_root(); - if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) { - nt_status = NT_STATUS_OK; - make_server_info_pw(server_info, pass); - } - unbecome_root(); - } - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - - return nt_status; -} - -BOOL auth_init_hostsequiv(auth_methods **auth_method) -{ - - if (!make_auth_methods(auth_method)) { - return False; - } - (*auth_method)->auth = check_hostsequiv_security; - return True; -} - -BOOL auth_init_rhosts(auth_methods **auth_method) -{ - - if (!make_auth_methods(auth_method)) { - return False; - } - (*auth_method)->auth = check_rhosts_security; - return True; -} diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c deleted file mode 100644 index 067b5b2997..0000000000 --- a/source3/smbd/auth_server.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Authenticate to a remote server - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Andrew Bartlett 2001 - - 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 pstring global_myname; - -/**************************************************************************** - Support for server level security. -****************************************************************************/ - -static struct cli_state *server_cryptkey(void) -{ - struct cli_state *cli = NULL; - fstring desthost; - struct in_addr dest_ip; - char *p, *pserver; - BOOL connected_ok = False; - - if (!(cli = cli_initialise(cli))) - return NULL; - - /* security = server just can't function with spnego */ - cli->use_spnego = False; - - pserver = strdup(lp_passwordserver()); - p = pserver; - - while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { - standard_sub_basic(desthost); - strupper(desthost); - - if(!resolve_name( desthost, &dest_ip, 0x20)) { - DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); - continue; - } - - if (cli_connect(cli, desthost, &dest_ip)) { - DEBUG(3,("connected to password server %s\n",desthost)); - connected_ok = True; - break; - } - } - - SAFE_FREE(pserver); - - if (!connected_ok) { - DEBUG(0,("password server not available\n")); - cli_shutdown(cli); - return NULL; - } - - if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) - return NULL; - - if (strequal(desthost,myhostname())) { - exit_server("Password server loop!"); - } - - DEBUG(3,("got session\n")); - - if (!cli_negprot(cli)) { - DEBUG(1,("%s rejected the negprot\n",desthost)); - cli_shutdown(cli); - return NULL; - } - - if (cli->protocol < PROTOCOL_LANMAN2 || - !(cli->sec_mode & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",desthost)); - cli_shutdown(cli); - return NULL; - } - - DEBUG(3,("password server OK\n")); - - return cli; -} - -/**************************************************************************** - Clean up our allocated cli. -****************************************************************************/ - -static void free_server_private_data(void **private_data_pointer) -{ - struct cli_state **cli = (struct cli_state **)private_data_pointer; - if (*cli && (*cli)->initialised) { - cli_shutdown(*cli); - - SAFE_FREE(*cli); - } -} - -/**************************************************************************** - Send a 'keepalive' packet down the cli pipe. -****************************************************************************/ - -static void send_server_keepalive(void **private_data_pointer) -{ - struct cli_state **cli = (struct cli_state **)private_data_pointer; - - /* also send a keepalive to the password server if its still - connected */ - if (cli && *cli && (*cli)->initialised) { - if (!send_keepalive((*cli)->fd)) { - DEBUG( 2, ( "password server keepalive failed.\n")); - cli_shutdown(*cli); - SAFE_FREE(*cli); - } - } -} - -/**************************************************************************** - Get the challange out of a password server. -****************************************************************************/ - -static DATA_BLOB auth_get_challange_server(void **my_private_data, const struct authsupplied_info *auth_info) -{ - struct cli_state *cli = server_cryptkey(); - - if (cli) { - DEBUG(3,("using password server validation\n")); - if ((cli->sec_mode & 2) == 0) { - /* We can't work with unencrypted password servers - unless 'encrypt passwords = no' */ - DEBUG(5,("make_auth_info_server: Server is unencrypted, no challange available..\n")); - - *my_private_data = (void *)cli; - return data_blob(NULL, 0); - - } else if (cli->secblob.length < 8) { - /* We can't do much if we don't get a full challange */ - DEBUG(2,("make_auth_info_server: Didn't receive a full challange from server\n")); - cli_shutdown(cli); - return data_blob(NULL, 0); - } - - *my_private_data = (void *)cli; - - return data_blob(cli->secblob.data,8); - } else { - return data_blob(NULL, 0); - } -} - - -/**************************************************************************** - Check for a valid username and password in security=server mode. - - Validate a password with the password server. -****************************************************************************/ - -static NTSTATUS check_smbserver_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - struct cli_state *cli; - static unsigned char badpass[24]; - static fstring baduser; - static BOOL tested_password_server = False; - static BOOL bad_password_server = False; - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - BOOL locally_made_cli = False; - - cli = my_private_data; - - if (cli) { - } else { - cli = server_cryptkey(); - locally_made_cli = True; - } - - if (!cli || !cli->initialised) { - DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return NT_STATUS_LOGON_FAILURE; - } - - if ((cli->sec_mode & 2) == 0) { - if (user_info->encrypted) { - DEBUG(1,("password server %s is plaintext, but we are encrypted. This just can't work :-(\n", cli->desthost)); - return NT_STATUS_LOGON_FAILURE; - } - } else { - if (memcmp(cli->secblob.data, auth_info->challange.data, 8) != 0) { - DEBUG(1,("the challange that the password server (%s) supplied us is not the one we gave our client. This just can't work :-(\n", cli->desthost)); - return NT_STATUS_LOGON_FAILURE; - } - } - - if(badpass[0] == 0) - memset(badpass, 0x1f, sizeof(badpass)); - - if((user_info->nt_resp.length == sizeof(badpass)) && - !memcmp(badpass, user_info->nt_resp.data, sizeof(badpass))) { - /* - * Very unlikely, our random bad password is the same as the users - * password. - */ - memset(badpass, badpass[0]+1, sizeof(badpass)); - } - - if(baduser[0] == 0) { - fstrcpy(baduser, INVALID_USER_PREFIX); - fstrcat(baduser, global_myname); - } - - /* - * Attempt a session setup with a totally incorrect password. - * If this succeeds with the guest bit *NOT* set then the password - * server is broken and is not correctly setting the guest bit. We - * need to detect this as some versions of NT4.x are broken. JRA. - */ - - /* I sure as hell hope that there arn't servers out there that take - * NTLMv2 and have this bug, as we don't test for that... - * - abartlet@samba.org - */ - - if ((!tested_password_server) && (lp_paranoid_server_security())) { - if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass), - (char *)badpass, sizeof(badpass), user_info->domain.str)) { - - /* - * We connected to the password server so we - * can say we've tested it. - */ - tested_password_server = True; - - if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { - DEBUG(0,("server_validate: password server %s allows users as non-guest \ -with a bad password.\n", cli->desthost)); - DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ -use this machine as the password server.\n")); - cli_ulogoff(cli); - - /* - * Password server has the bug. - */ - bad_password_server = True; - return NT_STATUS_LOGON_FAILURE; - } - cli_ulogoff(cli); - } - } else { - - /* - * We have already tested the password server. - * Fail immediately if it has the bug. - */ - - if(bad_password_server) { - DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \ -with a bad password.\n", cli->desthost)); - DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \ -use this machine as the password server.\n")); - return NT_STATUS_LOGON_FAILURE; - } - } - - /* - * Now we know the password server will correctly set the guest bit, or is - * not guest enabled, we can try with the real password. - */ - - if (!user_info->encrypted) { - /* Plaintext available */ - if (!cli_session_setup(cli, user_info->smb_name.str, - (char *)user_info->plaintext_password.data, - user_info->plaintext_password.length, - NULL, 0, - user_info->domain.str)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - /* Make this cli_nt_error() when the conversion is in */ - nt_status = cli_nt_error(cli); - } else { - nt_status = NT_STATUS_OK; - } - } else { - if (!cli_session_setup(cli, user_info->smb_name.str, - (char *)user_info->lm_resp.data, - user_info->lm_resp.length, - (char *)user_info->nt_resp.data, - user_info->nt_resp.length, - user_info->domain.str)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - /* Make this cli_nt_error() when the conversion is in */ - nt_status = cli_nt_error(cli); - } else { - nt_status = NT_STATUS_OK; - } - } - - /* if logged in as guest then reject */ - if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", cli->desthost)); - nt_status = NT_STATUS_LOGON_FAILURE; - } - - cli_ulogoff(cli); - - if NT_STATUS_IS_OK(nt_status) { - struct passwd *pass = Get_Pwnam(user_info->internal_username.str); - if (pass) { - if (!make_server_info_pw(server_info, pass)) { - nt_status = NT_STATUS_NO_MEMORY; - } - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - } - - if (locally_made_cli) { - cli_shutdown(cli); - SAFE_FREE(cli); - } - - return(nt_status); -} - -BOOL auth_init_smbserver(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - (*auth_method)->auth = check_smbserver_security; - (*auth_method)->get_chal = auth_get_challange_server; - (*auth_method)->send_keepalive = send_server_keepalive; - (*auth_method)->free_private_data = free_server_private_data; - return True; -} diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c deleted file mode 100644 index 24a4d4e4e4..0000000000 --- a/source3/smbd/auth_smbpasswd.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Password and authentication handling - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Andrew Bartlett 2001 - - 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" - -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, - const uchar *part_passwd, - DATA_BLOB sec_blob, - uint8 user_sess_key[16]) -{ - /* Finish the encryption of part_passwd. */ - uchar p24[24]; - - if (part_passwd == NULL) { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always false ! */ - return False; - } - - if (sec_blob.length != 8) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challange size (%d)\n", sec_blob.length)); - return False; - } - - if (nt_response.length != 24) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response.length)); - return False; - } - - SMBOWFencrypt(part_passwd, sec_blob.data, p24); - if (user_sess_key != NULL) - { - SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); - } - - - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); - dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, nt_response.data, nt_response.length); - DEBUG(100,("Given challenge was |")); - dump_data(100, sec_blob.data, sec_blob.length); - DEBUG(100,("Value from encryption was |")); - dump_data(100, p24, 24); -#endif - return (memcmp(p24, nt_response.data, 24) == 0); -} - -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, - const uchar *part_passwd, - const DATA_BLOB sec_blob, - const char *user, const char *domain, - uint8 user_sess_key[16]) -{ - /* Finish the encryption of part_passwd. */ - uchar kr[16]; - uchar value_from_encryption[16]; - uchar client_response[16]; - DATA_BLOB client_key_data; - - if (part_passwd == NULL) - { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always False */ - return False; - } - - if (ntv2_response.length < 16) { - /* We MUST have more than 16 bytes, or the stuff below will go - crazy... */ - DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", - ntv2_response.length)); - return False; - } - - client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16); - memcpy(client_response, ntv2_response.data, sizeof(client_response)); - - ntv2_owf_gen(part_passwd, user, domain, kr); - SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, (char *)value_from_encryption); - if (user_sess_key != NULL) - { - SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); - } - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); - dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, ntv2_response.data, ntv2_response.length); - DEBUG(100,("Variable data from client was |")); - dump_data(100, client_key_data.data, client_key_data.length); - DEBUG(100,("Given challenge was |")); - dump_data(100, sec_blob.data, sec_blob.length); - DEBUG(100,("Value from encryption was |")); - dump_data(100, value_from_encryption, 16); -#endif - data_blob_clear_free(&client_key_data); - return (memcmp(value_from_encryption, client_response, 16) == 0); -} - - -/**************************************************************************** - Do a specific test for an smb password being correct, given a smb_password and - the lanman and NT responses. -****************************************************************************/ -static NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - uint8 user_sess_key[16]) -{ - uint16 acct_ctrl; - const uint8 *nt_pw, *lm_pw; - uint32 ntlmssp_flags; - - acct_ctrl = pdb_get_acct_ctrl(sampass); - if (acct_ctrl & ACB_PWNOTREQ) - { - if (lp_null_passwords()) - { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", pdb_get_username(sampass))); - return(NT_STATUS_OK); - } - else - { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", pdb_get_username(sampass))); - return(NT_STATUS_LOGON_FAILURE); - } - } - - nt_pw = pdb_get_nt_passwd(sampass); - lm_pw = pdb_get_lanman_passwd(sampass); - - ntlmssp_flags = user_info->ntlmssp_flags; - - if (nt_pw == NULL) { - DEBUG(3,("smb_password_ok: NO NT password stored for user %s.\n", - pdb_get_username(sampass))); - /* No return, we want to check the LM hash below in this case */ - ntlmssp_flags &= (~(NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2)); - } - - if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM2) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, auth_info->challange, - user_info->smb_name.str, - user_info->client_domain.str, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(3,("smb_password_ok: NTLMv2 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } - } else if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM) { - if (lp_ntlm_auth()) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, auth_info->challange, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(3,("smb_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - } else { - DEBUG(2,("smb_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); - /* No return, we want to check the LM hash below in this case */ - } - } - - if (lm_pw == NULL) { - DEBUG(3,("smb_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass))); - ntlmssp_flags &= (~NTLMSSP_NEGOTIATE_OEM); - } - - if (ntlmssp_flags & NTLMSSP_NEGOTIATE_OEM) { - - if (user_info->lm_resp.length != 24) { - DEBUG(2,("smb_password_ok: invalid LanMan password length (%d) for user %s\n", - user_info->nt_resp.length, pdb_get_username(sampass))); - } - - if (!lp_lanman_auth()) { - DEBUG(3,("smb_password_ok: Lanman passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_LOGON_FAILURE; - } - - DEBUG(4,("smb_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp, - lm_pw, auth_info->challange, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: LM password check failed for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - } - - /* Should not be reached, but if they send nothing... */ - DEBUG(3,("smb_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; -} - -/**************************************************************************** - Do a specific test for a SAM_ACCOUNT being vaild for this connection - (ie not disabled, expired and the like). -****************************************************************************/ -static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info) -{ - uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); - char *workstation_list; - time_t kickoff_time; - - DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",pdb_get_username(sampass))); - - /* Quit if the account was disabled. */ - if (acct_ctrl & ACB_DISABLED) { - DEBUG(1,("Account for user '%s' was disabled.\n", pdb_get_username(sampass))); - return NT_STATUS_ACCOUNT_DISABLED; - } - - /* Test account expire time */ - - kickoff_time = pdb_get_kickoff_time(sampass); - if (kickoff_time != 0 && time(NULL) > kickoff_time) { - DEBUG(1,("Account for user '%s' has expried.\n", pdb_get_username(sampass))); - DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); - return NT_STATUS_ACCOUNT_EXPIRED; - } - - if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { - time_t must_change_time = pdb_get_pass_must_change_time(sampass); - time_t last_set_time = pdb_get_pass_last_set_time(sampass); - - /* check for immediate expiry "must change at next logon" */ - if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); - return NT_STATUS_PASSWORD_MUST_CHANGE; - } - - /* check for expired password */ - if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); - DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); - return NT_STATUS_PASSWORD_EXPIRED; - } - } - - /* Test workstation. Workstation list is comma separated. */ - - workstation_list = strdup(pdb_get_workstations(sampass)); - - if (!workstation_list) return NT_STATUS_NO_MEMORY; - - if (*workstation_list) { - BOOL invalid_ws = True; - char *s = workstation_list; - - fstring tok; - - while (next_token(&s, tok, ",", sizeof(tok))) { - DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", - tok, user_info->wksta_name.str, user_info->wksta_name.len)); - if(strequal(tok, user_info->wksta_name.str)) { - invalid_ws = False; - break; - } - } - - SAFE_FREE(workstation_list); - if (invalid_ws) - return NT_STATUS_INVALID_WORKSTATION; - } else { - SAFE_FREE(workstation_list); - } - - if (acct_ctrl & ACB_DOMTRUST) { - DEBUG(2,("session_trust_account: Domain trust account %s denied by server\n", pdb_get_username(sampass))); - return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; - } - - if (acct_ctrl & ACB_SVRTRUST) { - DEBUG(2,("session_trust_account: Server trust account %s denied by server\n", pdb_get_username(sampass))); - return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; - } - - if (acct_ctrl & ACB_WSTRUST) { - DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", pdb_get_username(sampass))); - return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; - } - - return NT_STATUS_OK; -} - - -/**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash supplied in the user_info structure -return an NT_STATUS constant. -****************************************************************************/ - -NTSTATUS check_sam_security(void *my_private_dat, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - SAM_ACCOUNT *sampass=NULL; - BOOL ret; - NTSTATUS nt_status; - uint8 user_sess_key[16]; - const uint8* lm_hash; - - if (!user_info || !auth_info) { - return NT_STATUS_LOGON_FAILURE; - } - - if (!pdb_init_sam(&sampass)) { - return NT_STATUS_NO_MEMORY; - } - - /* get the account information */ - - become_root(); - ret = pdb_getsampwnam(sampass, user_info->internal_username.str); - unbecome_root(); - - if (ret == False) - { - DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); - pdb_free_sam(&sampass); - return NT_STATUS_NO_SUCH_USER; - } - - nt_status = sam_password_ok(sampass, user_info, auth_info, user_sess_key); - - if (!NT_STATUS_IS_OK(nt_status)) { - pdb_free_sam(&sampass); - return nt_status; - } - - nt_status = sam_account_ok(sampass, user_info); - - if (!NT_STATUS_IS_OK(nt_status)) { - pdb_free_sam(&sampass); - return nt_status; - } - - if (!make_server_info_sam(server_info, sampass)) { - DEBUG(0,("failed to malloc memory for server_info\n")); - return NT_STATUS_NO_MEMORY; - } - - lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account); - if (lm_hash) { - memcpy((*server_info)->first_8_lm_hash, lm_hash, 8); - } - - memcpy((*server_info)->session_key, user_sess_key, sizeof(user_sess_key)); - - return nt_status; -} - -BOOL auth_init_sam(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - - (*auth_method)->auth = check_sam_security; - return True; -} - - - diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c deleted file mode 100644 index d134ce6909..0000000000 --- a/source3/smbd/auth_unix.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 2.2 - Password and authentication handling - Copyright (C) Andrew Bartlett 2001 - - 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" - -/**************************************************************************** -update the encrypted smbpasswd file from the plaintext username and password - -this ugly hack needs to die, but not quite yet... -*****************************************************************************/ -static BOOL update_smbpassword_file(char *user, char *password) -{ - SAM_ACCOUNT *sampass = NULL; - BOOL ret; - - pdb_init_sam(&sampass); - - become_root(); - ret = pdb_getsampwnam(sampass, user); - unbecome_root(); - - if(ret == False) { - DEBUG(0,("pdb_getsampwnam returned NULL\n")); - pdb_free_sam(&sampass); - return False; - } - - /* - * Remove the account disabled flag - we are updating the - * users password from a login. - */ - if (!pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED)) { - pdb_free_sam(&sampass); - return False; - } - - if (!pdb_set_plaintext_passwd (sampass, password)) { - pdb_free_sam(&sampass); - return False; - } - - /* Now write it into the file. */ - become_root(); - - /* Here, the override flag is True, because we want to ignore the - XXXXXXX'd out password */ - ret = pdb_update_sam_account (sampass, True); - - unbecome_root(); - - if (ret) { - DEBUG(3,("pdb_update_sam_account returned %d\n",ret)); - } - - memset(password, '\0', strlen(password)); - - pdb_free_sam(&sampass); - return ret; -} - - -/**************************************************************************** -check if a username/password is OK assuming the password -in PLAIN TEXT -****************************************************************************/ - -NTSTATUS check_unix_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status; - struct passwd *pass = NULL; - - become_root(); - pass = Get_Pwnam(user_info->internal_username.str); - - nt_status = pass_check(pass, - pass ? pass->pw_name : user_info->internal_username.str, - (char *)user_info->plaintext_password.data, - user_info->plaintext_password.length-1, - lp_update_encrypted() ? - update_smbpassword_file : NULL, - True); - - unbecome_root(); - - if NT_STATUS_IS_OK(nt_status) { - if (pass) { - make_server_info_pw(server_info, pass); - } else { - /* we need to do somthing more useful here */ - nt_status = NT_STATUS_NO_SUCH_USER; - } - } - - return nt_status; -} - -BOOL auth_init_unix(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - (*auth_method)->auth = check_unix_security; - return True; -} diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c deleted file mode 100644 index d1b2cc92e5..0000000000 --- a/source3/smbd/auth_util.c +++ /dev/null @@ -1,730 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Authentication utility functions - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Andrew Bartlett 2001 - Copyright (C) Jeremy Allison 2000-2001 - - 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 fstring remote_machine; -extern pstring global_myname; - -/**************************************************************************** - Create a UNIX user on demand. -****************************************************************************/ - -static int smb_create_user(const char *unix_user, const char *homedir) -{ - pstring add_script; - int ret; - - pstrcpy(add_script, lp_adduser_script()); - if (! *add_script) - return -1; - all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); - if (homedir) - all_string_sub(add_script, "%H", homedir, sizeof(pstring)); - ret = smbrun(add_script,NULL); - DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); - return ret; -} - -/**************************************************************************** - Delete a UNIX user on demand. -****************************************************************************/ - -static int smb_delete_user(char *unix_user) -{ - pstring del_script; - int ret; - - pstrcpy(del_script, lp_deluser_script()); - if (! *del_script) - return -1; - all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); - ret = smbrun(del_script,NULL); - DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); - return ret; -} - -/**************************************************************************** - Add and Delete UNIX users on demand, based on NTSTATUS codes. -****************************************************************************/ - -void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status) -{ - struct passwd *pwd=NULL; - - if (NT_STATUS_IS_OK(nt_status)) { - - if (!(server_info->sam_fill_level & SAM_FILL_UNIX)) { - - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - */ - - if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) { - smb_create_user(user_info->internal_username.str, NULL); - } - } else { - if(lp_adduser_script()) { - SMB_STRUCT_STAT st; - const char *home_dir = pdb_get_homedir(server_info->sam_account); - /* - * Also call smb_create_user if the users - * home directory doesn't exist. Used with - * winbindd to allow the script to create - * the home directory for a user mapped - * with winbindd. - */ - - if (home_dir && - (sys_stat(home_dir, &st) == -1) && (errno == ENOENT)) { - smb_create_user(user_info->internal_username.str, home_dir); - } - } - } - } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { - /* - * User failed to validate ok against Domain controller. - * If the failure was "user doesn't exist" and admin - * wants us to try and delete that UNIX user on the fly, - * do so. - */ - if (lp_deluser_script()) { - smb_delete_user(user_info->internal_username.str); - } - } -} - -/**************************************************************************** - Create an auth_usersupplied_data structure -****************************************************************************/ - -static BOOL make_user_info(auth_usersupplied_info **user_info, - const char *smb_name, - const char *internal_username, - const char *client_domain, - const char *domain, - const char *wksta_name, - DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, - DATA_BLOB plaintext, - uint32 ntlmssp_flags, BOOL encrypted) -{ - - DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); - - *user_info = malloc(sizeof(**user_info)); - if (!user_info) { - DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info))); - return False; - } - - ZERO_STRUCTP(*user_info); - - DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username)); - - (*user_info)->smb_name.str = strdup(smb_name); - if ((*user_info)->smb_name.str) { - (*user_info)->smb_name.len = strlen(smb_name); - } else { - free_user_info(user_info); - return False; - } - - (*user_info)->internal_username.str = strdup(internal_username); - if ((*user_info)->internal_username.str) { - (*user_info)->internal_username.len = strlen(internal_username); - } else { - free_user_info(user_info); - return False; - } - - (*user_info)->domain.str = strdup(domain); - if ((*user_info)->domain.str) { - (*user_info)->domain.len = strlen(domain); - } else { - free_user_info(user_info); - return False; - } - - (*user_info)->client_domain.str = strdup(client_domain); - if ((*user_info)->client_domain.str) { - (*user_info)->client_domain.len = strlen(client_domain); - } else { - free_user_info(user_info); - return False; - } - - (*user_info)->wksta_name.str = strdup(wksta_name); - if ((*user_info)->wksta_name.str) { - (*user_info)->wksta_name.len = strlen(wksta_name); - } else { - free_user_info(user_info); - return False; - } - - DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username)); - - (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length); - (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length); - (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length); - - (*user_info)->encrypted = encrypted; - (*user_info)->ntlmssp_flags = ntlmssp_flags; - - DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name)); - - return True; -} - -/**************************************************************************** - Create an auth_usersupplied_data structure after appropriate mapping. -****************************************************************************/ - -BOOL make_user_info_map(auth_usersupplied_info **user_info, - const char *smb_name, - const char *client_domain, - const char *wksta_name, - DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, - DATA_BLOB plaintext, - uint32 ntlmssp_flags, BOOL encrypted) -{ - const char *domain; - fstring internal_username; - fstrcpy(internal_username, smb_name); - map_username(internal_username); - - if (lp_allow_trusted_domains()) { - domain = client_domain; - } else { - domain = lp_workgroup(); - } - - return make_user_info(user_info, - smb_name, internal_username, - client_domain, domain, - wksta_name, - lm_pwd, nt_pwd, - plaintext, - ntlmssp_flags, encrypted); - -} - -/**************************************************************************** - Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrypt and encrypt the passwords. -****************************************************************************/ - -BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - char *wksta_name, - uchar *lm_network_pwd, int lm_pwd_len, - uchar *nt_network_pwd, int nt_pwd_len) -{ - BOOL ret; - DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); - DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - uint32 ntlmssp_flags = 0; - - if (lm_pwd_len) - ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - if (nt_pwd_len == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - } else if (nt_pwd_len != 0) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; - } - - ret = make_user_info_map(user_info, - smb_name, client_domain, - wksta_name, - lm_blob, nt_blob, - plaintext_blob, - ntlmssp_flags, True); - - data_blob_free(&lm_blob); - data_blob_free(&nt_blob); - return ret; -} - -/**************************************************************************** - Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrypt and encrypt the passwords. -****************************************************************************/ - -BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - char *wksta_name, - char chal[8], - uchar lm_interactive_pwd[16], - uchar nt_interactive_pwd[16], - uchar *dc_sess_key) -{ - char lm_pwd[16]; - char nt_pwd[16]; - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - unsigned char key[16]; - uint32 ntlmssp_flags = 0; - - ZERO_STRUCT(key); - memcpy(key, dc_sess_key, 8); - - if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd)); - if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd)); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("key:")); - dump_data(100, (char *)key, sizeof(key)); - - DEBUG(100,("lm owf password:")); - dump_data(100, lm_pwd, sizeof(lm_pwd)); - - DEBUG(100,("nt owf password:")); - dump_data(100, nt_pwd, sizeof(nt_pwd)); -#endif - - SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd)); - SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd)); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("decrypt of lm owf password:")); - dump_data(100, lm_pwd, sizeof(lm_pwd)); - - DEBUG(100,("decrypt of nt owf password:")); - dump_data(100, nt_pwd, sizeof(nt_pwd)); -#endif - - SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); - SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); - - /* Password info parinoia */ - ZERO_STRUCT(lm_pwd); - ZERO_STRUCT(nt_pwd); - ZERO_STRUCT(key); - - { - BOOL ret; - DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); - DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - - if (lm_interactive_pwd) - ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - if (nt_interactive_pwd) - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - - ret = make_user_info_map(user_info, - smb_name, client_domain, - wksta_name, - local_lm_blob, - local_nt_blob, - plaintext_blob, - ntlmssp_flags, True); - - data_blob_free(&local_lm_blob); - data_blob_free(&local_nt_blob); - return ret; - } -} - -/**************************************************************************** - Create an auth_usersupplied_data structure -****************************************************************************/ - -BOOL make_user_info_winbind(auth_usersupplied_info **user_info, - const char *username, - const char *domain, - const char *password, - char chal[8] /* Give winbind back the challange we used */ - ) -{ - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - DATA_BLOB local_lm_blob; - DATA_BLOB local_nt_blob; - DATA_BLOB plaintext_blob; - uint32 ntlmssp_flags = 0; - - /* - * Not encrypted - do so. - */ - - DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); - - generate_random_buffer(chal, 8, False); - - if (*password) { - SMBencrypt( (const uchar *)password, chal, local_lm_response); - - /* This encrypts the lm_pwd field, which actually contains - the password rather than the nt_pwd field because that - contains nothing */ - - /* WATCH OUT. This doesn't work if the incoming password is - incorrectly cased. We might want to add a check here - and only do an LM in that case */ - - SMBNTencrypt((const uchar *)password, chal, local_nt_response); - - local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); - local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); - plaintext_blob = data_blob(password, strlen(password)+1); - if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) { - data_blob_free(&local_lm_blob); - data_blob_free(&local_nt_blob); - data_blob_clear_free(&plaintext_blob); - return False; - } - ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; - } else { - local_lm_blob = data_blob(NULL, 0); - local_nt_blob = data_blob(NULL, 0); - plaintext_blob = data_blob(NULL, 0); - } - - { - BOOL ret; - - ret = make_user_info(user_info, - username, username, - domain, domain, - global_myname, - local_nt_blob, - local_lm_blob, - plaintext_blob, - ntlmssp_flags, False); - - data_blob_free(&local_lm_blob); - data_blob_free(&local_nt_blob); - data_blob_clear_free(&plaintext_blob); - return ret; - } -} - -/**************************************************************************** - Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrypt and encrypt the passwords. -****************************************************************************/ - -BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - uchar *lm_network_pwd, int lm_pwd_len, - uchar *nt_network_pwd, int nt_pwd_len) -{ - BOOL ret; - DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); - DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - uint32 ntlmssp_flags = 0; - - if (lm_pwd_len) - ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - if (nt_pwd_len) - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - - ret = make_user_info(user_info, - smb_name, smb_name, - client_domain, client_domain, - global_myname, - nt_blob, lm_blob, - plaintext_blob, - ntlmssp_flags, True); - - data_blob_free(&lm_blob); - data_blob_free(&nt_blob); - return ret; -} - -/**************************************************************************** - Create an auth_usersupplied_data structure -****************************************************************************/ - -BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - char chal[8], - DATA_BLOB plaintext_password) -{ - - DATA_BLOB local_lm_blob; - DATA_BLOB local_nt_blob; - BOOL ret = False; - uint32 ntlmssp_flags = 0; - - /* - * Not encrypted - do so. - */ - - DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n")); - - if (plaintext_password.data) { - unsigned char local_lm_response[24]; - -#ifdef DEBUG_PASSWORD - DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length)); - dump_data(100, plaintext_password.data, plaintext_password.length); -#endif - - SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response); - local_lm_blob = data_blob(local_lm_response, 24); - - /* We can't do an NT hash here, as the password needs to be - case insensitive */ - local_nt_blob = data_blob(NULL, 0); - - ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM; - } else { - local_lm_blob = data_blob(NULL, 0); - local_nt_blob = data_blob(NULL, 0); - } - - ret = make_user_info_map(user_info, smb_name, - client_domain, - remote_machine, - local_lm_blob, - local_nt_blob, - plaintext_password, - ntlmssp_flags, False); - - data_blob_free(&local_lm_blob); - return ret; -} - -/**************************************************************************** - Create an auth_usersupplied_data structure -****************************************************************************/ - -BOOL make_user_info_for_reply_enc(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - DATA_BLOB lm_resp, DATA_BLOB nt_resp, - DATA_BLOB plaintext_password) -{ - uint32 ntlmssp_flags = 0; - - DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); - - if (lm_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - } - if (nt_resp.length == 0) { - } else if (nt_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - } else { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; - } - - return make_user_info_map(user_info, smb_name, - client_domain, - remote_machine, - lm_resp, - nt_resp, - no_plaintext_blob, - ntlmssp_flags, True); -} - -/**************************************************************************** - Create a guest user_info blob, for anonymous authenticaion. -****************************************************************************/ - -BOOL make_user_info_guest(auth_usersupplied_info **user_info) -{ - DATA_BLOB lm_blob = data_blob(NULL, 0); - DATA_BLOB nt_blob = data_blob(NULL, 0); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - uint32 ntlmssp_flags = 0; - - return make_user_info(user_info, - "","", - "","", - "", - nt_blob, lm_blob, - plaintext_blob, - ntlmssp_flags, True); -} - -/*************************************************************************** - Make a user_info struct -***************************************************************************/ - -BOOL make_server_info(auth_serversupplied_info **server_info) -{ - *server_info = malloc(sizeof(**server_info)); - if (!*server_info) { - DEBUG(0,("make_server_info: malloc failed!\n")); - return False; - } - ZERO_STRUCTP(*server_info); - return True; -} - -/*************************************************************************** - Make (and fill) a user_info struct from a SAM_ACCOUNT -***************************************************************************/ - -BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) -{ - if (!make_server_info(server_info)) { - return False; - } - - (*server_info)->sam_fill_level = SAM_FILL_ALL; - (*server_info)->sam_account = sampass; - - DEBUG(5,("make_server_info_sam: made server info for user %s\n", - pdb_get_username((*server_info)->sam_account))); - return True; -} - -/*************************************************************************** - Make (and fill) a user_info struct from a 'struct passwd' by conversion - to a SAM_ACCOUNT -***************************************************************************/ - -BOOL make_server_info_pw(auth_serversupplied_info **server_info, const struct passwd *pwd) -{ - SAM_ACCOUNT *sampass = NULL; - if (!pdb_init_sam_pw(&sampass, pwd)) { - return False; - } - return make_server_info_sam(server_info, sampass); -} - -/*************************************************************************** - Free a user_info struct -***************************************************************************/ - -void free_user_info(auth_usersupplied_info **user_info) -{ - DEBUG(5,("attempting to free (and zero) a user_info structure\n")); - if (*user_info != NULL) { - if ((*user_info)->smb_name.str) { - DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str)); - } - SAFE_FREE((*user_info)->smb_name.str); - SAFE_FREE((*user_info)->internal_username.str); - SAFE_FREE((*user_info)->client_domain.str); - SAFE_FREE((*user_info)->domain.str); - data_blob_free(&(*user_info)->lm_resp); - data_blob_free(&(*user_info)->nt_resp); - SAFE_FREE((*user_info)->interactive_password); - data_blob_clear_free(&(*user_info)->plaintext_password); - ZERO_STRUCT(**user_info); - } - SAFE_FREE(*user_info); -} - -/*************************************************************************** - Clear out a server_info struct that has been allocated -***************************************************************************/ - -void free_server_info(auth_serversupplied_info **server_info) -{ - if (*server_info != NULL) { - pdb_free_sam(&(*server_info)->sam_account); - - /* call pam_end here, unless we know we are keeping it */ - delete_nt_token( &(*server_info)->ptok ); - ZERO_STRUCT(**server_info); - } - SAFE_FREE(*server_info); -} - -/*************************************************************************** - Make a server_info struct for a guest user -***************************************************************************/ - -BOOL make_server_info_guest(auth_serversupplied_info **server_info) -{ - struct passwd *pass = sys_getpwnam(lp_guestaccount()); - - if (pass) { - if (!make_server_info_pw(server_info, pass)) { - return False; - } - (*server_info)->guest = True; - return True; - } - DEBUG(0,("make_server_info_guest: sys_getpwnam() failed on guest account!\n")); - return False; -} - -/*************************************************************************** - Make an auth_methods struct -***************************************************************************/ - -BOOL make_auth_methods(auth_methods **auth_method) -{ - *auth_method = malloc(sizeof(**auth_method)); - if (!*auth_method) { - DEBUG(0,("make_auth_method: malloc failed!\n")); - return False; - } - ZERO_STRUCTP(*auth_method); - - return True; -} - -/**************************************************************************** - Delete a SID token. -****************************************************************************/ - -void delete_nt_token(NT_USER_TOKEN **pptoken) -{ - if (*pptoken) { - NT_USER_TOKEN *ptoken = *pptoken; - SAFE_FREE( ptoken->user_sids ); - ZERO_STRUCTP(ptoken); - } - SAFE_FREE(*pptoken); -} - -/**************************************************************************** - Duplicate a SID token. -****************************************************************************/ - -NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) -{ - NT_USER_TOKEN *token; - - if (!ptoken) - return NULL; - - if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) - return NULL; - - ZERO_STRUCTP(token); - - if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) { - SAFE_FREE(token); - return NULL; - } - - token->num_sids = ptoken->num_sids; - - return token; -} diff --git a/source3/smbd/auth_winbind.c b/source3/smbd/auth_winbind.c deleted file mode 100644 index c29d008f4a..0000000000 --- a/source3/smbd/auth_winbind.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 2.0 - - Winbind authentication mechnism - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Bartlett 2001 - - 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" - -/* Prototypes from common.h */ - -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); - - -/* Authenticate a user with a challenge/response */ - -static NTSTATUS check_winbind_security(void *my_private_data, - const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - struct passwd *pw; - NTSTATUS nt_status; - - if (!user_info) { - return NT_STATUS_LOGON_FAILURE; - } - - if (!auth_info) { - DEBUG(3,("Password for user %s cannot be checked becouse we have no auth_info to get the challange from.\n", - user_info->internal_username.str)); - return NT_STATUS_LOGON_FAILURE; - } - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - snprintf(request.data.auth_crap.user, sizeof(request.data.auth_crap.user), - "%s\\%s", user_info->domain.str, user_info->smb_name.str); - - memcpy(request.data.auth_crap.chal, auth_info->challange.data, sizeof(request.data.auth_crap.chal)); - - request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length, - sizeof(request.data.auth_crap.lm_resp)); - request.data.auth_crap.nt_resp_len = MIN(user_info->nt_resp.length, - sizeof(request.data.auth_crap.nt_resp)); - - memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data, - sizeof(request.data.auth_crap.lm_resp_len)); - memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data, - request.data.auth_crap.lm_resp_len); - - result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); - - if (result == NSS_STATUS_SUCCESS) { - - pw = Get_Pwnam(user_info->internal_username.str); - - if (pw) { - if (make_server_info_pw(server_info, pw)) { - nt_status = NT_STATUS_OK; - } else { - nt_status = NT_STATUS_NO_MEMORY; - } - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - } else { - nt_status = NT_STATUS_LOGON_FAILURE; - } - - return nt_status; -} - -BOOL auth_init_winbind(auth_methods **auth_method) -{ - if (!make_auth_methods(auth_method)) { - return False; - } - - (*auth_method)->auth = check_winbind_security; - return True; -} - - - - -- cgit From 585d0efbc6428e5876d354fee49c241c1bad809d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 26 Nov 2001 03:11:44 +0000 Subject: Got medieval on another pointless extern. Removed extern struct ipzero and replaced with two functions: void zero_ip(struct in_adder *ip); BOOL is_zero_ip(struct in_addr ip); (This used to be commit 778f5f77a66cda76348a7c6f64cd63afe2bfe077) --- source3/smbd/password.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 510e18919d..71837efdcb 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,8 +21,6 @@ #include "includes.h" -extern struct in_addr ipzero; - /* users from session setup */ static pstring session_users=""; -- cgit From 178f6a64b26d828db6b516392d7072e9c29f6233 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 26 Nov 2001 04:05:28 +0000 Subject: challange -> challenge (This used to be commit d6318add27f6bca5be00cbedf2226b642341297a) --- source3/smbd/negprot.c | 6 +++--- source3/smbd/process.c | 8 ++++---- source3/smbd/sesssetup.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index a2666ae24e..9cbe0fdb0a 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -83,7 +83,7 @@ static int reply_lanman1(char *inbuf, char *outbuf) if (!make_auth_info_subsystem(&negprot_global_auth_info)) { smb_panic("cannot make_negprot_global_auth_info!\n"); } - cryptkey = auth_get_challange(negprot_global_auth_info); + cryptkey = auth_get_challenge(negprot_global_auth_info); memcpy(smb_buf(outbuf), cryptkey.data, 8); data_blob_free(&cryptkey); } @@ -129,7 +129,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) if (!make_auth_info_subsystem(&negprot_global_auth_info)) { smb_panic("cannot make_negprot_global_auth_info!\n"); } - cryptkey = auth_get_challange(negprot_global_auth_info); + cryptkey = auth_get_challenge(negprot_global_auth_info); memcpy(smb_buf(outbuf), cryptkey.data, 8); data_blob_free(&cryptkey); } @@ -265,7 +265,7 @@ static int reply_nt1(char *inbuf, char *outbuf) if (!make_auth_info_subsystem(&negprot_global_auth_info)) { smb_panic("cannot make_negprot_global_auth_info!\n"); } - cryptkey = auth_get_challange(negprot_global_auth_info); + cryptkey = auth_get_challenge(negprot_global_auth_info); memcpy(p, cryptkey.data, 8); data_blob_free(&cryptkey); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d9322ae26c..d4881b0ba5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1122,10 +1122,10 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t This is attached to the auth_info created in the negprot */ if (negprot_global_auth_info - && negprot_global_auth_info->challange_set_method - && negprot_global_auth_info->challange_set_method->send_keepalive) { - negprot_global_auth_info->challange_set_method->send_keepalive - (&negprot_global_auth_info->challange_set_method->private_data); + && negprot_global_auth_info->challenge_set_method + && negprot_global_auth_info->challenge_set_method->send_keepalive) { + negprot_global_auth_info->challenge_set_method->send_keepalive + (&negprot_global_auth_info->challenge_set_method->private_data); } last_keepalive_sent_time = t; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 854513bb47..1b6776ed70 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -235,7 +235,7 @@ static int reply_spnego_negotiate(connection_struct *conn, return ERROR_NT(NT_STATUS_NO_MEMORY); } - cryptkey = auth_get_challange(ntlmssp_auth_info); + cryptkey = auth_get_challenge(ntlmssp_auth_info); /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ @@ -649,7 +649,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_NO_MEMORY); } - chal = auth_get_challange(plaintext_auth_info); + chal = auth_get_challenge(plaintext_auth_info); if (!make_user_info_for_reply(&user_info, user, domain, chal.data, -- cgit From 64dd6c3412f961239ad4c6989aab67250d312c9d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 26 Nov 2001 04:27:51 +0000 Subject: Another merge from appliance-head: in [ug]id_to_sid don't call the winbind function if the id is obviously going to be local. Cleanup of winbind [ug]id parameter handling. (This used to be commit 4ab9ca31a02b3388aa89a00e0390ea9e4c76283a) --- source3/smbd/uid.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 4329e3fb76..14b0290e33 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -551,16 +551,24 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) { + uid_t low, high; fstring sid; - if (!winbind_uid_to_sid(psid, uid)) { - DEBUG(10,("uid_to_sid: winbind lookup for uid %u failed - trying local.\n", (unsigned int)uid )); + if (lp_winbind_uid(&low, &high) && uid >= low && uid <= high) { + if (winbind_uid_to_sid(psid, uid)) { - return local_uid_to_sid(psid, uid); - } + DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", + (unsigned int)uid, + sid_to_string(sid, psid))); + + return psid; + } + } - DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid) )); + local_uid_to_sid(psid, uid); + + DEBUG(10,("uid_to_sid: local %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); return psid; } @@ -573,16 +581,24 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) { + gid_t low, high; fstring sid; - if (!winbind_gid_to_sid(psid, gid)) { - DEBUG(10,("gid_to_sid: winbind lookup for gid %u failed - trying local.\n", (unsigned int)gid )); - - return local_gid_to_sid(psid, gid); - } - - DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, sid_to_string(sid,psid) )); + if (lp_winbind_gid(&low, &high) && gid >= low && gid <= high) { + if (winbind_gid_to_sid(psid, gid)) { + + DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", + (unsigned int)gid, + sid_to_string(sid, psid))); + + return psid; + } + } + + local_gid_to_sid(psid, gid); + + DEBUG(10,("gid_to_sid: local %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); return psid; } -- cgit From 0b2763260e915620a6d9b1709d112b13a8566d74 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 Nov 2001 04:37:24 +0000 Subject: we can safely give NO_SUCH_USER if the ticket decodes but the local account doesn't exist (This used to be commit 477b6d27fd7281418739bc8ba0b984a53430ecda) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1b6776ed70..d49dbc15d1 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -113,7 +113,7 @@ static int reply_spnego_kerberos(connection_struct *conn, pw = smb_getpwnam(user,False); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(NT_STATUS_NO_SUCH_USER); } if (!make_server_info_pw(&server_info,pw)) { -- cgit From 1fb4d2f1b0d65e9f48081ae7a225950d4341d923 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Nov 2001 01:51:10 +0000 Subject: don't try to auto-change the trust password unless we are in domain security (This used to be commit 00e4f0c803c6376387c31efd01cf3437c589da9d) --- source3/smbd/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d4881b0ba5..bbccc67f97 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1139,7 +1139,10 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t return False; } - if(global_machine_password_needs_changing) + if(global_machine_password_needs_changing && + /* for ADS we need to do a regular ADS password change, not a domain + password change */ + lp_security() == SEC_DOMAIN) { unsigned char trust_passwd_hash[16]; time_t lct; -- cgit From 6cf3434785ec369f6edbd5b1dd4dd1c26123b7c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Nov 2001 03:34:56 +0000 Subject: more memory leak fixes (This used to be commit 5abf8442033587b79651301d39260abd44b1c3fa) --- source3/smbd/sesssetup.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index d49dbc15d1..ac8ba91ff7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -59,6 +59,7 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) nt_status = check_password(user_info, auth_info, server_info); free_auth_info(&auth_info); + SAFE_FREE(user_info); return nt_status; } @@ -279,7 +280,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DATA_BLOB blob1) { DATA_BLOB auth; - char *workgroup, *user, *machine; + char *workgroup = NULL, *user = NULL, *machine = NULL; DATA_BLOB lmhash, nthash, sess_key; DATA_BLOB plaintext_password = data_blob(NULL, 0); uint32 ntlmssp_command, neg_flags; @@ -329,6 +330,10 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, neg_flags, True)) { return ERROR_NT(NT_STATUS_NO_MEMORY); } + + SAFE_FREE(workgroup); + SAFE_FREE(user); + SAFE_FREE(machine); nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); -- cgit From 67b347378031c3f48c937eb25c6b1b25b9fb528c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Nov 2001 03:54:15 +0000 Subject: fixed another memory leak (This used to be commit 37aa2873e5f476a587316893b0ea3a6fbdfe746f) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index ac8ba91ff7..f9d52e9be4 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -59,7 +59,7 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) nt_status = check_password(user_info, auth_info, server_info); free_auth_info(&auth_info); - SAFE_FREE(user_info); + free_user_info(&user_info); return nt_status; } -- cgit From 064b3e7da7adfae06eae459e54ae0853924a4e4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Nov 2001 06:28:06 +0000 Subject: nsswitch/winbindd_group.c nsswitch/winbindd_user.c: formatting fixups. smbd/open.c: Fix "delete on close" for directories. Jeremy. (This used to be commit 014b0973a3b3b9eb22cce3053171fa55f5c16a63) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1eae228f40..7c4e69946f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1129,7 +1129,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; - fsp->share_mode = 0; + fsp->share_mode = share_mode; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; -- cgit From 01d91a82493bd025901e819d8b2626a07bc64d31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Nov 2001 23:12:25 +0000 Subject: Fix for the logic bug wrt. existant oplocks. See long message in samba-technical for explaination. Jeremy. (This used to be commit 8150f0f3f72957e77a1e6ca06760c87c516792eb) --- source3/smbd/open.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c4e69946f..67be12626b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -543,11 +543,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { - pstring errmsg; - slprintf(errmsg, sizeof(errmsg)-1, - "open_mode_check: Existant process %d left active oplock.\n", - broken_entry.pid ); - smb_panic(errmsg); + DEBUG(0,("open_mode_check: Existant process %d left active oplock.\n", + broken_entry.pid )); } if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { -- cgit From 5e25ba6fecfdd477fec046660bf20c90970c4e58 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Nov 2001 23:41:14 +0000 Subject: always send an OID list until we handle raw (unwrapped) NTLMSSP packets in session setup (This used to be commit 3b3f8a935064811906cba221d386697e699af18c) --- source3/smbd/negprot.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 9cbe0fdb0a..9a03e1ba96 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -158,10 +158,11 @@ static int negprot_spnego(char *p) DATA_BLOB blob; extern pstring global_myname; uint8 guid[16]; - const char *OIDs[] = {OID_NTLMSSP, - OID_KERBEROS5, - OID_KERBEROS5_OLD, - NULL}; + const char *OIDs_krb5[] = {OID_NTLMSSP, + OID_KERBEROS5, + OID_KERBEROS5_OLD, + NULL}; + const char *OIDs_plain[] = {OID_NTLMSSP, NULL}; char *principal; int len; @@ -171,17 +172,25 @@ static int negprot_spnego(char *p) safe_strcpy((char *)guid, global_myname, 16); strlower((char *)guid); +#if 0 /* strangely enough, NT does not sent the single OID NTLMSSP when - not a ADS member, it sends no OIDs at all */ + not a ADS member, it sends no OIDs at all + + we can't do this until we teach our sesssion setup parser to know + about raw NTLMSSP (clients send no ASN.1 wrapping if we do this) + */ if (lp_security() != SEC_ADS) { memcpy(p, guid, 16); return 16; } +#endif /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ asprintf(&principal, "HOST/%s@%s", guid, lp_realm()); - blob = spnego_gen_negTokenInit(guid, OIDs, principal); + blob = spnego_gen_negTokenInit(guid, + lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain, + principal); free(principal); memcpy(p, blob.data, blob.length); -- cgit From 1a50b36d978416e7c08423296db351e434bdea50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Nov 2001 04:47:46 +0000 Subject: Re-added "Share modes" meaning don't allow deny mode conflict. Due to user demand (don't talk to me about removing parameters.... :-). Jeremy. (This used to be commit b69127391b322d81cc648f73a601ed61e79c8a44) --- source3/smbd/open.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 67be12626b..487a8a71a8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -352,13 +352,21 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if we can open a file with a share mode ****************************************************************************/ -static int check_share_mode( share_mode_entry *share, int share_mode, +static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, const char *fname, BOOL fcbopen, int *flags) { int deny_mode = GET_DENY_MODE(share_mode); int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); + /* + * share modes = false means don't bother to check for + * DENY mode conflict. This is a *really* bad idea :-). JRA. + */ + + if(!lp_share_modes(SNUM(conn))) + return True; + /* * Don't allow any opens once the delete on close flag has been * set. @@ -514,7 +522,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou /* someone else has a share lock on it, check to see if we can too */ - if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { + if(check_share_mode(conn, share_entry, share_mode, fname, fcbopen, p_flags) == False) { SAFE_FREE(old_shares); errno = EACCES; return -1; -- cgit From a17867af97a258b9d22d6216d8de887174eaa707 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Nov 2001 05:03:37 +0000 Subject: Ensure the CAN_WRITE is checked and prevents O_CREAT and O_TRUNC from being set. Also prevent an open on a file on a readonly share from setting delete on close. Jeremy. (This used to be commit 1f3dcd99bdd36cd3ff492394e80c3e2037a9aa48) --- source3/smbd/open.c | 4 ++-- source3/smbd/trans2.c | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 487a8a71a8..1e34e0c9fe 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -683,10 +683,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S return NULL; } - if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST) + if (CAN_WRITE(conn) && (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST)) flags2 |= O_CREAT; - if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE) + if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) flags2 |= O_TRUNC; if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0e13d8d87a..aaa5aade97 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1679,6 +1679,15 @@ static int call_trans2qfilepathinfo(connection_struct *conn, NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) { + /* + * Only allow delete on close for writable shares. + */ + + if (delete_on_close && !CAN_WRITE(fsp->conn)) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; + } /* * Only allow delete on close for files/directories opened with delete intent. */ -- cgit From 59a8827f5d7174dd2d5487dda09ccaedb43a01c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Nov 2001 18:10:13 +0000 Subject: Spelling pedents strike again :-). Jeremy. (This used to be commit 0187d4ba16c794faa372bf1a50261b8f47482064) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1e34e0c9fe..03540ec7c3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -551,7 +551,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { - DEBUG(0,("open_mode_check: Existant process %d left active oplock.\n", + DEBUG(0,("open_mode_check: Existent process %d left active oplock.\n", broken_entry.pid )); } -- cgit From 7d2d605f0db0c3689a263d6857721eac66a1b9c1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Nov 2001 19:51:25 +0000 Subject: space -> tab. Jeremy. (This used to be commit c7dd0364f2b084d9a372ac885fd788bbb5113125) --- source3/smbd/uid.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 14b0290e33..524ddb15ab 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -551,24 +551,22 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) { - uid_t low, high; + uid_t low, high; fstring sid; - if (lp_winbind_uid(&low, &high) && uid >= low && uid <= high) { - if (winbind_uid_to_sid(psid, uid)) { + if (lp_winbind_uid(&low, &high) && uid >= low && uid <= high) { + if (winbind_uid_to_sid(psid, uid)) { - DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, - sid_to_string(sid, psid))); + DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); - return psid; - } - } + return psid; + } + } - local_uid_to_sid(psid, uid); + local_uid_to_sid(psid, uid); - DEBUG(10,("uid_to_sid: local %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); + DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); return psid; } @@ -581,24 +579,22 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) { - gid_t low, high; + gid_t low, high; fstring sid; - if (lp_winbind_gid(&low, &high) && gid >= low && gid <= high) { - if (winbind_gid_to_sid(psid, gid)) { + if (lp_winbind_gid(&low, &high) && gid >= low && gid <= high) { + if (winbind_gid_to_sid(psid, gid)) { - DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, - sid_to_string(sid, psid))); + DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); - return psid; - } - } + return psid; + } + } - local_gid_to_sid(psid, gid); + local_gid_to_sid(psid, gid); - DEBUG(10,("gid_to_sid: local %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); + DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); return psid; } -- cgit From f6b962fba37a1ac105301d699708e541ce34d3b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 28 Nov 2001 23:54:07 +0000 Subject: fixed some krb5 ifdefs (This used to be commit 23ef22f11700bbaa5778a9678a990a2b041fcefe) --- source3/smbd/sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index f9d52e9be4..863a509042 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -64,7 +64,7 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) } -#if HAVE_KRB5 +#ifdef HAVE_KRB5 /**************************************************************************** reply to a session setup spnego negotiate packet for kerberos ****************************************************************************/ @@ -201,7 +201,7 @@ static int reply_spnego_negotiate(connection_struct *conn, } DEBUG(3,("Got secblob of size %d\n", secblob.length)); -#if HAVE_KRB5 +#ifdef HAVE_KRB5 if (got_kerberos) { int ret = reply_spnego_kerberos(conn, inbuf, outbuf, length, bufsize, &secblob); -- cgit From fe64484824d8169bf66822ebf7f6a9180a238e6e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 29 Nov 2001 06:21:56 +0000 Subject: Make better use of the ads_init() function to get the kerberos relam etc. This allows us to use automagically obtained values in future, and the value from krb5.conf now. Also fix mem leaks etc. Andrew Bartlett (This used to be commit 8f9ce717819235d98a1463f20ac659cb4b4ebbd2) --- source3/smbd/negprot.c | 22 +++++++++++++--------- source3/smbd/sesssetup.c | 19 ++++++++++++------- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 9a03e1ba96..78d4da3a75 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -184,15 +184,19 @@ static int negprot_spnego(char *p) return 16; } #endif - - /* win2000 uses host$@REALM, which we will probably use eventually, - but for now this works */ - asprintf(&principal, "HOST/%s@%s", guid, lp_realm()); - blob = spnego_gen_negTokenInit(guid, - lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain, - principal); - free(principal); - + { + ADS_STRUCT *ads; + ads = ads_init(NULL, NULL, NULL); + + /* win2000 uses host$@REALM, which we will probably use eventually, + but for now this works */ + asprintf(&principal, "HOST/%s@%s", guid, ads->realm); + blob = spnego_gen_negTokenInit(guid, + lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain, + principal); + free(principal); + ads_destroy(&ads); + } memcpy(p, blob.data, blob.length); len = blob.length; data_blob_free(&blob); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 863a509042..35155c0dec 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -74,23 +74,25 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB *secblob) { DATA_BLOB ticket; - char *realm, *client, *p; + char *client, *p; const struct passwd *pw; char *user; int sess_vuid; NTSTATUS ret; DATA_BLOB auth_data; auth_serversupplied_info *server_info = NULL; - - realm = lp_realm(); + ADS_STRUCT *ads; if (!spnego_parse_krb5_wrap(*secblob, &ticket)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = ads_verify_ticket(&ticket, &client, &auth_data); + ads = ads_init(NULL, NULL, NULL); + + ret = ads_verify_ticket(ads, &ticket, &client, &auth_data); if (!NT_STATUS_IS_OK(ret)) { - DEBUG(1,("Failed to verify incoming ticket!\n")); + DEBUG(1,("Failed to verify incoming ticket!\n")); + ads_destroy(&ads); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -99,15 +101,18 @@ static int reply_spnego_kerberos(connection_struct *conn, p = strchr_m(client, '@'); if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); + ads_destroy(&ads); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } *p = 0; - if (strcasecmp(p+1, realm) != 0) { + if (strcasecmp(p+1, ads->realm) != 0) { DEBUG(3,("Ticket for incorrect realm %s\n", p+1)); + ads_destroy(&ads); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - + ads_destroy(&ads); + user = client; /* the password is good - let them in */ -- cgit From 6d9adfe73c04132ff162d05b0c309395c4a54485 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 30 Nov 2001 01:04:15 +0000 Subject: Renamed sid field in SEC_ACE to trustee to be more in line with MS's definitions. (This used to be commit 9712d3f15a47155f558d0034ef71fd06afb11301) --- source3/smbd/posix_acls.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d42b11cb83..b00d1810a2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -38,7 +38,7 @@ typedef struct canon_ace { struct canon_ace *next, *prev; SMB_ACL_TAG_T type; mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */ - DOM_SID sid; + DOM_SID trustee; enum ace_owner owner_type; enum ace_attribute attr; posix_id unix_ug; @@ -103,7 +103,7 @@ static void print_canon_ace(canon_ace *pace, int num) fstring str; dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" ); - dbgtext( "SID = %s ", sid_to_string( str, &pace->sid)); + dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); if (pace->owner_type == UID_ACE) { struct passwd *pass = sys_getpwuid(pace->unix_ug.uid); dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, pass ? pass->pw_name : "UNKNOWN"); @@ -243,7 +243,7 @@ static void merge_aces( canon_ace **pp_list_head ) curr_ace_next = curr_ace->next; /* Save the link in case of delete. */ - if (sid_equal(&curr_ace->sid, &curr_ace_outer->sid) && + if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) && (curr_ace->attr == curr_ace_outer->attr)) { if( DEBUGLVL( 10 )) { @@ -283,7 +283,7 @@ static void merge_aces( canon_ace **pp_list_head ) * we've put on the ACL, we know the deny must be the first one. */ - if (sid_equal(&curr_ace->sid, &curr_ace_outer->sid) && + if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) && (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) { if( DEBUGLVL( 10 )) { @@ -572,7 +572,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->type = SMB_ACL_USER_OBJ; pace->owner_type = UID_ACE; pace->unix_ug.uid = pst->st_uid; - pace->sid = *pfile_owner_sid; + pace->trustee = *pfile_owner_sid; pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); pace->attr = ALLOW_ACE; @@ -589,7 +589,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->type = SMB_ACL_GROUP_OBJ; pace->owner_type = GID_ACE; pace->unix_ug.uid = pst->st_gid; - pace->sid = *pfile_grp_sid; + pace->trustee = *pfile_grp_sid; pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); pace->attr = ALLOW_ACE; @@ -606,7 +606,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->type = SMB_ACL_OTHER; pace->owner_type = WORLD_ACE; pace->unix_ug.world = -1; - pace->sid = global_sid_World; + pace->trustee = global_sid_World; pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); pace->attr = ALLOW_ACE; @@ -688,7 +688,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, if (psa1->info.mask != psa2->info.mask) continue; - if (!sid_equal(&psa1->sid, &psa2->sid)) + if (!sid_equal(&psa1->trustee, &psa2->trustee)) continue; /* @@ -718,10 +718,10 @@ static BOOL create_canon_ace_lists(files_struct *fsp, * Ignore non-mappable SIDs (NT Authority, BUILTIN etc). */ - if (non_mappable_sid(&psa->sid)) { + if (non_mappable_sid(&psa->trustee)) { fstring str; DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n", - sid_to_string(str, &psa->sid) )); + sid_to_string(str, &psa->trustee) )); continue; } @@ -738,19 +738,19 @@ static BOOL create_canon_ace_lists(files_struct *fsp, ZERO_STRUCTP(current_ace); - sid_copy(¤t_ace->sid, &psa->sid); + sid_copy(¤t_ace->trustee, &psa->trustee); /* * Try and work out if the SID is a user or group * as we need to flag these differently for POSIX. */ - if( sid_equal(¤t_ace->sid, &global_sid_World)) { + if( sid_equal(¤t_ace->trustee, &global_sid_World)) { current_ace->owner_type = WORLD_ACE; current_ace->unix_ug.world = -1; - } else if (sid_to_uid( ¤t_ace->sid, ¤t_ace->unix_ug.uid, &sid_type)) { + } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid, &sid_type)) { current_ace->owner_type = UID_ACE; - } else if (sid_to_gid( ¤t_ace->sid, ¤t_ace->unix_ug.gid, &sid_type)) { + } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid, &sid_type)) { current_ace->owner_type = GID_ACE; } else { fstring str; @@ -759,7 +759,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, free_canon_ace_list(dir_ace); SAFE_FREE(current_ace); DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n", - sid_to_string(str, ¤t_ace->sid) )); + sid_to_string(str, ¤t_ace->trustee) )); return False; } @@ -775,15 +775,15 @@ static BOOL create_canon_ace_lists(files_struct *fsp, * Now note what kind of a POSIX ACL this should map to. */ - if(sid_equal(¤t_ace->sid, pfile_owner_sid)) { + if(sid_equal(¤t_ace->trustee, pfile_owner_sid)) { current_ace->type = SMB_ACL_USER_OBJ; - } else if( sid_equal(¤t_ace->sid, pfile_grp_sid)) { + } else if( sid_equal(¤t_ace->trustee, pfile_grp_sid)) { current_ace->type = SMB_ACL_GROUP_OBJ; - } else if( sid_equal(¤t_ace->sid, &global_sid_World)) { + } else if( sid_equal(¤t_ace->trustee, &global_sid_World)) { current_ace->type = SMB_ACL_OTHER; @@ -930,7 +930,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) /* "Everyone" always matches every uid. */ - if (sid_equal(&group_ace->sid, &global_sid_World)) + if (sid_equal(&group_ace->trustee, &global_sid_World)) return True; if (!(pass = sys_getpwuid(uid_ace->unix_ug.uid))) @@ -1067,7 +1067,7 @@ static void process_deny_list( canon_ace **pp_ace_list ) continue; } - if (!sid_equal(&curr_ace->sid, &global_sid_World)) + if (!sid_equal(&curr_ace->trustee, &global_sid_World)) continue; /* JRATEST - assert. */ @@ -1518,7 +1518,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ ace->type = tagtype; ace->perms = convert_permset_to_mode_t(permset); ace->attr = ALLOW_ACE; - ace->sid = sid; + ace->trustee = sid; ace->unix_ug = unix_ug; ace->owner_type = owner_type; @@ -1937,14 +1937,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) for (i = 0; i < num_acls; i++, ace = ace->next) { SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->sid, nt_acl_type, acc, 0); + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0); } ace = dir_ace; for (i = 0; i < num_dir_acls; i++, ace = ace->next) { SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->sid, nt_acl_type, acc, + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); } -- cgit From a9750b20061ed0862754459120043f341a1b8f50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Nov 2001 21:50:02 +0000 Subject: XFS quota patch for Linux. Jeremy. (This used to be commit ce099faf6ce07e14bd9610960bd09f56c5bee864) --- source3/smbd/quotas.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 96670a985d..73391e6c0d 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -55,6 +55,9 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B */ #include +#ifdef HAVE_LINUX_XQM_H +#include +#endif #include #include @@ -72,11 +75,36 @@ typedef struct _LINUX_SMB_DISK_QUOTA { SMB_BIG_UINT curinodes; /* Current used inodes. */ } LINUX_SMB_DISK_QUOTA; +/**************************************************************************** + Abstract out the XFS Quota Manager quota get call. +****************************************************************************/ + +static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) +{ + int ret = -1; +#ifdef HAVE_LINUX_XQM_H + struct fs_disk_quota D; + ZERO_STRUCT(D); + + if ((ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D))) + return ret; + + dp->bsize = (SMB_BIG_UINT)512; + dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit; + dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit; + dp->curinodes = (SMB_BIG_UINT)D.d_icount; + dp->curblocks = (SMB_BIG_UINT)D.d_bcount; +#endif + return ret; +} + /**************************************************************************** Abstract out the old and new Linux quota get calls. ****************************************************************************/ -static int get_smb_linux_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) +static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) { int ret; #ifdef LINUX_QUOTAS_1 @@ -154,7 +182,10 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB save_re_uid(); set_effective_uid(0); - r=get_smb_linux_quota(mnt->mnt_fsname, euser_id, &D); + if (strcmp(mnt->mnt_type, "xfs") == 0) + r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D); + else + r=get_smb_linux_vfs_quota(mnt->mnt_fsname, euser_id, &D); restore_re_uid(); /* Use softlimit to determine disk space, except when it has been exceeded */ -- cgit From cdf9b42754b7e97faa7fc4eb1ec69e32c0bfd1a0 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Mon, 3 Dec 2001 17:14:23 +0000 Subject: added a tdb to store the account policy informations. You can change them with either usermanager->policies->account or from a command prompt on NT/W2K: net accounts /domain we can add a rpc accounts to the net command. As the net_rpc.c is still empty, I did not start. How should I add command to it ? Should I take the rpcclient/cmd_xxx functions and call them from there ? alse changed the SAM_UNK_INFO_3 parser, it's an NTTIME. This one is more for jeremy ;-) J.F. (This used to be commit bc28a8eebd9245ce3004ae4b1a359db51f77bf21) --- source3/smbd/server.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2f374e48aa..df56dfe9ab 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -825,13 +825,18 @@ static void usage(char *pname) /* possibly reload the services file. */ reload_services(True); - if (init_group_mapping()==False) { - printf("Could not open tdb mapping file.\n"); + if(!pdb_generate_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); + exit(1); + } + + if (!init_group_mapping()) { + DEBUG(0,("Could not open tdb mapping file.\n")); return 0; } - if(!pdb_generate_sam_sid()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); + if (!init_account_policy()) { + DEBUG(0,("Could not open account policy tdb.\n")); exit(1); } -- cgit From c2e3d8ba018221c0a0b22a91fdb361dd740482b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Dec 2001 02:58:22 +0000 Subject: Tidyup of lib/username. Add name_is_local fn to determine if name is winbindd. Getting ready for efficiency fix in group lookups. Jeremy. (This used to be commit 8d41dfd149625e8ac53ab5e90a96e9a2daf9a629) --- source3/smbd/uid.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 524ddb15ab..9a9de0a796 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -436,6 +436,16 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER *pptok = new_tok; } +/***************************************************************** + Check if a user or group name is local (this is a *local* name for + *local* people, there's nothing for you here...). +*****************************************************************/ + +BOOL name_is_local(const char *name) +{ + return !strchr_m(name, *lp_winbind_separator()); +} + /***************************************************************** *THE CANONICAL* convert name to SID function. Tries winbind first - then uses local lookup. -- cgit From 8e99888e7b29817e2e242b8fe59a10465500807c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Dec 2001 03:47:44 +0000 Subject: Moved name_is_local to the correct place. Ooops. Jeremy. (This used to be commit 708c0a8d16ca86439e451def5f8d37f600ff15f1) --- source3/smbd/uid.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 9a9de0a796..524ddb15ab 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -436,16 +436,6 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER *pptok = new_tok; } -/***************************************************************** - Check if a user or group name is local (this is a *local* name for - *local* people, there's nothing for you here...). -*****************************************************************/ - -BOOL name_is_local(const char *name) -{ - return !strchr_m(name, *lp_winbind_separator()); -} - /***************************************************************** *THE CANONICAL* convert name to SID function. Tries winbind first - then uses local lookup. -- cgit From 36673778515e17f89eeaf2d31f85969a646b7785 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Dec 2001 03:59:18 +0000 Subject: Stop using getgrgid() - a very expensive call with winbindd, to look up a group name. Jeremy. (This used to be commit b926660e73d4c94c30ec5a365027770acdafe25e) --- source3/smbd/posix_acls.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b00d1810a2..324169a092 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -103,13 +103,13 @@ static void print_canon_ace(canon_ace *pace, int num) fstring str; dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" ); - dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); + dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); if (pace->owner_type == UID_ACE) { - struct passwd *pass = sys_getpwuid(pace->unix_ug.uid); - dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, pass ? pass->pw_name : "UNKNOWN"); + char *u_name = uidtoname(pace->unix_ug.uid); + dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name); } else if (pace->owner_type == GID_ACE) { - struct group *grp = getgrgid(pace->unix_ug.gid); - dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, grp ? grp->gr_name : "UNKNOWN"); + char *g_name = gidtoname(pace->unix_ug.gid); + dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name); } else dbgtext( "other "); switch (pace->type) { @@ -925,26 +925,23 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) { extern DOM_SID global_sid_World; - struct passwd *pass = NULL; - struct group *gptr = NULL; + fstring u_name; + fstring g_name; /* "Everyone" always matches every uid. */ if (sid_equal(&group_ace->trustee, &global_sid_World)) return True; - if (!(pass = sys_getpwuid(uid_ace->unix_ug.uid))) - return False; - - if (!(gptr = getgrgid(group_ace->unix_ug.gid))) - return False; + fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); + fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid)); /* * Due to the winbind interfaces we need to do this via names, * not uids/gids. */ - return user_in_group_list(pass->pw_name, gptr->gr_name ); + return user_in_group_list(u_name, g_name ); } /**************************************************************************** -- cgit From 922eb763d7365716fd3c20aa069746fc9bfb8ab3 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Tue, 4 Dec 2001 21:53:47 +0000 Subject: added a boolean to the group mapping functions to specify if we need or not the privileges. Usually we don't need them, so the memory is free early. lib/util_sid.c: added some helper functions to check an SID. passdb/passdb.c: renamed local_lookup_rid() to local_lookup_sid() and pass an RID all the way. If the group doesn't exist on the domain SID, don't return a faked one as it can collide with a builtin one. Some rpc structures have been badly designed, they return only rids and force the client to do subsequent lsa_lookup_sid() on the domain sid and the builtin sid ! rpc_server/srv_util.c: wrote a new version of get_domain_user_groups(). Only the samr code uses it atm. It uses the group mapping code instead of a bloody hard coded crap. The netlogon code will use it too, but I have to do some test first. J.F. (This used to be commit 6c87e96149101995b7d049657d5c26eefef37d8c) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 524ddb15ab..650d9270cb 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -524,7 +524,7 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE if (sid_equal(&global_sam_sid, &tmp_sid)) { return map_domain_sid_to_name(&tmp_sid, dom_name) && - local_lookup_rid(rid, name, name_type); + local_lookup_sid(sid, name, name_type); } } -- cgit From 61fc7b98a73351f92646613989a207908e934d99 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 4 Dec 2001 22:24:17 +0000 Subject: Merge from 2.2 If you do not have one more expect than issue when talking to the passwd program you will not send the last issue. (This used to be commit 8aafec95cba0e8a002d20c4c0055a01690879f7a) --- source3/smbd/chgpasswd.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 286c316b93..741f5ef0aa 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -312,6 +312,12 @@ static int talktochild(int master, char *seq) pwd_sub(issue); } + if (!strequal(issue, ".")) { + /* we have one final issue to send */ + fstrcpy(expected, "."); + if (!expect(master, issue, expected)) + return False; + } return (count > 0); } -- cgit From 9421ad4a7a900b219f87754bc20fa14f2f22fd35 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Dec 2001 09:46:53 +0000 Subject: added a REALLY gross hack into kerberos_kinit_password so that winbindd can do a kinit this will be removed once we have code that gets a tgt and puts it in a place where cyrus-sasl can see it (This used to be commit 7d94f1b7365215a020d3678d03d820a7d086174f) --- source3/smbd/negprot.c | 2 +- source3/smbd/sesssetup.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 78d4da3a75..b99d239540 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -186,7 +186,7 @@ static int negprot_spnego(char *p) #endif { ADS_STRUCT *ads; - ads = ads_init(NULL, NULL, NULL); + ads = ads_init(NULL, NULL, NULL, NULL); /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 35155c0dec..8e7ee38504 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -87,7 +87,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ads = ads_init(NULL, NULL, NULL); + ads = ads_init(NULL, NULL, NULL, NULL); ret = ads_verify_ticket(ads, &ticket, &client, &auth_data); if (!NT_STATUS_IS_OK(ret)) { -- cgit From 3f387d19717c31a2eec265ec790293ece3381094 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 5 Dec 2001 10:50:26 +0000 Subject: Ensure we fill in the %U for NTLMSSP connections (This used to be commit d15ea4fa8e23469f104405c197206e2779461323) --- source3/smbd/sesssetup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8e7ee38504..7190caa35b 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -337,7 +337,6 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, } SAFE_FREE(workgroup); - SAFE_FREE(user); SAFE_FREE(machine); nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); @@ -351,12 +350,15 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, data_blob_free(&nthash); if (!NT_STATUS_IS_OK(nt_status)) { + SAFE_FREE(user); return ERROR_NT(nt_status_squash(nt_status)); } sess_vuid = register_vuid(server_info, user); free_server_info(&server_info); + + SAFE_FREE(user); if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); -- cgit From e0066d2dd4d9a657d1fbcb474e66a304a64e2a31 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Thu, 6 Dec 2001 13:09:15 +0000 Subject: again an intrusive patch: - removed the ugly as hell sam_logon_in_ssb variable, I changed a bit the definition of standard_sub_basic() to cope with that. - removed the smb.conf: 'domain admin group' and 'domain guest group' parameters ! We're not playing anymore with the user's group RIDs ! - in get_domain_user_groups(), if the user's gid is a group, put it first in the group RID list. I just have to write an HOWTO now ;-) J.F. (This used to be commit fef52c4b96c987115fb1818c00c2352c67790e50) --- source3/smbd/message.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 7cc53e082c..a3625e3716 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -26,6 +26,8 @@ #include "includes.h" +extern userdom_struct current_user_info; + /* look in server.c for some explanation of these variables */ static char msgbuf[1600]; static int msgpos; @@ -84,7 +86,7 @@ static void msg_deliver(void) pstrcpy(s,lp_msg_command()); pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); - standard_sub_basic(s); + standard_sub_basic(current_user_info.smb_name, s); pstring_sub(s,"%s",name); smbrun(s,NULL); } -- cgit From 99c431695ce723fcdd77c455e8363a355519929b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Dec 2001 01:01:10 +0000 Subject: added a "use spnego" option you need to set "use spnego = no" for w2k to be able to join a samba domain. Otherwise the w2k box will assume we can do kerberos as a KDC (This used to be commit b5cb57a367a6d9a82e082e2838e83e0997eb4930) --- source3/smbd/negprot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b99d239540..d3afa19d00 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -227,6 +227,7 @@ static int reply_nt1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated && (lp_security() != SEC_SHARE) && + lp_use_spnego() && (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { negotiate_spnego = True; capabilities |= CAP_EXTENDED_SECURITY; -- cgit From 9220fd730c67352e2d0789f298e6e42063ca9e3c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 8 Dec 2001 02:12:17 +0000 Subject: Ensure that 'use spnego' restricts, rather than just advises our clients. This means that if a hole is found in the spnego code, we can tell people to just set 'use spengo' in their config file while we sort it out. Other than that, preventing 'unusual' behaviour is always a good thing. Andrew Bartlett (This used to be commit a8a53c08f7d607268a3959486a850a2df50ca7a2) --- source3/smbd/sesssetup.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7190caa35b..4c26bda4db 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -502,11 +502,16 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, ZERO_STRUCT(plaintext_password); DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2))); - + /* a SPNEGO session setup has 12 command words, whereas a normal NT1 session setup has 13. See the cifs spec. */ if (CVAL(inbuf, smb_wct) == 12 && (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { + if (!global_spnego_negotiated) { + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } + return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } -- cgit From 216f3ae90881fb1d7301920b9c30f551f24244f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Dec 2001 03:21:38 +0000 Subject: cleanup a little namespace pollution (This used to be commit e5b484451a37a9ac940b342d70791b09362070ee) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index bbccc67f97..111da3bcef 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -325,7 +325,7 @@ force write permissions on print services. functions. Any message that has a NULL function is unimplemented - please feel free to contribute implementations! */ -struct smb_message_struct +static struct smb_message_struct { char *name; int (*fn)(connection_struct *conn, char *, char *, int, int); -- cgit From e4553718bb0a35c0508fc4aedf23b1da14144451 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 12 Dec 2001 16:04:37 +0000 Subject: add *.po32 to ignore list (This used to be commit fe0db4c55f8bfc70004edd60a29359337fa40723) --- source3/smbd/.cvsignore | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/.cvsignore b/source3/smbd/.cvsignore index 6d609cec52..5f2a5c4cf7 100644 --- a/source3/smbd/.cvsignore +++ b/source3/smbd/.cvsignore @@ -1 +1,2 @@ *.po +*.po32 -- cgit From 079a02b15ed04ac5975874c1aee256855422021d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Dec 2001 23:43:15 +0000 Subject: Patch for string legths from TAKAHASHI, Motonobu(monyo). Jeremy. (This used to be commit f0d8b7573fc74004131ba0a82dbd5e0007a524bf) --- source3/smbd/utmp.c | 63 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index f79cd43c5b..cc52db8462 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -127,7 +127,7 @@ Notes: #endif /**************************************************************************** -obtain/release a small number (0 upwards) unique within and across smbds + Obtain/release a small number (0 upwards) unique within and across smbds. ****************************************************************************/ /* * Need a "small" number to represent this connection, unique within this @@ -154,8 +154,9 @@ obtain/release a small number (0 upwards) unique within and across smbds */ /**************************************************************************** -Default paths to various {u,w}tmp{,x} files + Default paths to various {u,w}tmp{,x} files. ****************************************************************************/ + #ifdef HAVE_UTMPX_H static const char *ux_pathname = @@ -260,9 +261,11 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau } #ifndef HAVE_PUTUTLINE + /**************************************************************************** -Update utmp file directly. No subroutine interface: probably a BSD system. + Update utmp file directly. No subroutine interface: probably a BSD system. ****************************************************************************/ + static void pututline_my(pstring uname, struct utmp *u, BOOL claim) { DEBUG(1,("pututline_my: not yet implemented\n")); @@ -271,10 +274,12 @@ static void pututline_my(pstring uname, struct utmp *u, BOOL claim) #endif /* HAVE_PUTUTLINE */ #ifndef HAVE_UPDWTMP + /**************************************************************************** -Update wtmp file directly. No subroutine interface: probably a BSD system. -Credit: Michail Vidiassov + Update wtmp file directly. No subroutine interface: probably a BSD system. + Credit: Michail Vidiassov ****************************************************************************/ + static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) { int fd; @@ -311,8 +316,9 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) #endif /* HAVE_UPDWTMP */ /**************************************************************************** -Update via utmp/wtmp (not utmpx/wtmpx) + Update via utmp/wtmp (not utmpx/wtmpx). ****************************************************************************/ + static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim) { pstring uname, wname; @@ -369,8 +375,26 @@ static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim) } /**************************************************************************** -Update via utmpx/wtmpx (preferred) or via utmp/wtmp + Copy a string in the utmp structure. ****************************************************************************/ + +static void utmp_strcpy(char *dest, const char *src, size_t n) +{ + size_t len; + + len = strlen(src); + if (len >= n) { + memcpy(dest, src, n); + } else { + memcpy(dest, src, len); + memset(dest + len, '\0', n - len); + } +} + +/**************************************************************************** + Update via utmpx/wtmpx (preferred) or via utmp/wtmp. +****************************************************************************/ + static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) { #if !defined(HAVE_UTMPX_H) @@ -391,10 +415,12 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) getutmpx(u, &ux); #if defined(HAVE_UX_UT_SYSLEN) - if (hostname) ux.ut_syslen = strlen(hostname) + 1; /* include end NULL */ - else ux.ut_syslen = 0; + if (hostname) + ux.ut_syslen = strlen(hostname) + 1; /* include end NULL */ + else + ux.ut_syslen = 0; #endif - safe_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)-1); + utmp_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)); uw_pathname(uname, "utmpx", ux_pathname); uw_pathname(wname, "wtmpx", wx_pathname); @@ -424,8 +450,9 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) #if defined(HAVE_UT_UT_ID) /**************************************************************************** -encode the unique connection number into "ut_id" + Encode the unique connection number into "ut_id". ****************************************************************************/ + static int ut_id_encode(int i, char *fourbyte) { int nbase; @@ -467,9 +494,9 @@ static BOOL sys_utmp_fill(struct utmp *u, * rather than to try to detect and optimise. */ #if defined(HAVE_UT_UT_USER) - safe_strcpy(u->ut_user, username, sizeof(u->ut_user)-1); + utmp_strcpy(u->ut_user, username, sizeof(u->ut_user)); #elif defined(HAVE_UT_UT_NAME) - safe_strcpy(u->ut_name, username, sizeof(u->ut_name)-1); + utmp_strcpy(u->ut_name, username, sizeof(u->ut_name)); #endif /* @@ -485,7 +512,7 @@ static BOOL sys_utmp_fill(struct utmp *u, id_str, sizeof(u->ut_line))); return False; } - memcpy(u->ut_line, id_str, sizeof(u->ut_line)); + utmp_strcpy(u->ut_line, id_str, sizeof(u->ut_line)); #if defined(HAVE_UT_UT_PID) u->ut_pid = sys_getpid(); @@ -508,7 +535,7 @@ static BOOL sys_utmp_fill(struct utmp *u, #endif #if defined(HAVE_UT_UT_HOST) - safe_strcpy(u->ut_host, hostname, sizeof(u->ut_host)-1); + utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host)); #endif #if defined(HAVE_UT_UT_ADDR) @@ -529,8 +556,9 @@ static BOOL sys_utmp_fill(struct utmp *u, } /**************************************************************************** -close a connection + Close a connection. ****************************************************************************/ + void sys_utmp_yield(const char *username, const char *hostname, const char *id_str, int id_num) { @@ -553,8 +581,9 @@ void sys_utmp_yield(const char *username, const char *hostname, } /**************************************************************************** -claim a entry in whatever utmp system the OS uses + Claim a entry in whatever utmp system the OS uses. ****************************************************************************/ + void sys_utmp_claim(const char *username, const char *hostname, const char *id_str, int id_num) { -- cgit From 0fd94a5c4b659e715e16fa4b2d5102520412ad55 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 16 Dec 2001 21:04:19 +0000 Subject: Ensured filetimes set (by name) after close. Ignore errors. This is the correct way to ensure times set in 'pending modtime' and 'time close' are always set correctly. Inspired by patch from Juergen Hasch. Jeremy. (This used to be commit 24053858543fa6c22c0c3222570109fbfdabab9e) --- source3/smbd/close.c | 13 +++++++++++-- source3/smbd/reply.c | 27 +++++++++++++-------------- 2 files changed, 24 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index fae43fca5d..879c91a81a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -119,6 +119,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) size_t share_entry_count = 0; BOOL delete_on_close = False; connection_struct *conn = fsp->conn; + time_t pending_modtime = fsp->pending_modtime; int err = 0; int err1 = 0; @@ -196,14 +197,22 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); check_magic(fsp,conn); } + /* + * Ensure pending modtime is set after close. + */ + + if(fsp->pending_modtime) { + int saved_errno = errno; + set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); + errno = saved_errno; + } DEBUG(2,("%s closed file %s (numopen=%d) %s\n", conn->user,fsp->fsp_name, conn->num_files_open, err ? strerror(err) : "")); - if (fsp->fsp_name) { + if (fsp->fsp_name) string_free(&fsp->fsp_name); - } file_free(fsp); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 675c06f75f..00e0cb8b86 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2242,21 +2242,10 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Close ordinary file. */ int close_err; + pstring file_name; - /* - * If there was a modify time outstanding, - * try and set it here. - */ - if(fsp->pending_modtime) - set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); - - /* - * Now take care of any time sent in the close. - */ - mtime = make_unix_date3(inbuf+smb_vwv1); - - /* try and set the date */ - set_filetime(conn, fsp->fsp_name,mtime); + /* Save the name for time set in close. */ + pstrcpy( file_name, fsp->fsp_name); DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", fsp->fd, fsp->fnum, @@ -2273,6 +2262,16 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, END_PROFILE(SMBclose); return (UNIXERROR(ERRHRD,ERRgeneral)); } + + /* + * Now take care of any time sent in the close. + */ + + mtime = make_unix_date3(inbuf+smb_vwv1); + + /* try and set the date */ + set_filetime(conn, file_name, mtime); + } /* We have a cached error */ -- cgit From 28df80cf68158c37fa8ddcadd0ce94dd3ef3887e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 16 Dec 2001 23:44:38 +0000 Subject: Moved fchown_acl change to the point where we *really* know if we created the file or not. Jeremy. (This used to be commit 32dffa0ba792a81d89d06b527d82820b89507efd) --- source3/smbd/open.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 03540ec7c3..72f73deb84 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -204,16 +204,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); - /* - * Take care of inherited ACLs on created files. JRA. - */ - - if ((flags & O_CREAT) && (conn->vfs_ops.fchmod_acl != NULL)) { - int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) - errno = saved_errno; /* Ignore ENOSYS */ - } - return True; } @@ -922,6 +912,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } + /* + * Take care of inherited ACLs on created files. JRA. + */ + + if (!file_existed && (conn->vfs_ops.fchmod_acl != NULL)) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + errno = saved_errno; /* Ignore ENOSYS */ + } + unlock_share_entry_fsp(fsp); conn->num_files_open++; -- cgit From ed5db6cc45aa8535e589aaef0d9bcf1075713260 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Dec 2001 11:13:03 +0000 Subject: removed unused variable (This used to be commit bed269e6d4dc4c9622ec37f9a7e9e2b4dbbaee24) --- source3/smbd/close.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 879c91a81a..b6b619dd8a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -119,7 +119,6 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) size_t share_entry_count = 0; BOOL delete_on_close = False; connection_struct *conn = fsp->conn; - time_t pending_modtime = fsp->pending_modtime; int err = 0; int err1 = 0; -- cgit From 02c3dcd8ee6f4007ea6db9fbcd75b16129a657eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Dec 2001 19:16:22 +0000 Subject: Made "hide unreadable" work much more reliably (just for Volker :-). Jeremy. (This used to be commit f6d6825bc86662d54ff3920d7d5390d151f34b0f) --- source3/smbd/dir.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 1e2858ae26..faf5bca52d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -666,12 +666,47 @@ check to see if a user can read a file. This is only approximate, it is used as part of the "hide unreadable" option. Don't use it for anything security sensitive ********************************************************************/ + static BOOL user_can_read_file(connection_struct *conn, char *name) { + extern struct current_user current_user; SMB_STRUCT_STAT ste; + SEC_DESC *psd = NULL; + size_t sd_size; + files_struct *fsp; + int smb_action; + NTSTATUS status; + uint32 access_granted; + + ZERO_STRUCT(ste); /* if we can't stat it does not show it */ - if (vfs_stat(conn, name, &ste) != 0) return False; + if (vfs_stat(conn, name, &ste) != 0) + return False; + + /* Pseudo-open the file (note - no fd's created). */ + + if(S_ISDIR(ste.st_mode)) + fsp = open_directory(conn, name, &ste, SET_DENY_MODE(DENY_NONE), FILE_OPEN, + unix_mode(conn,aRONLY|aDIR, name), &smb_action); + else + fsp = open_file_stat(conn,name,&ste,DOS_OPEN_RDONLY,&smb_action); + if (!fsp) + return False; + + /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ + sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + close_file(fsp, True); + + /* No access if SD get failed. */ + if (!sd_size) + return False; + + return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, + &access_granted, &status); + +#if 0 + /* Old - crappy check :-). JRA */ if (ste.st_uid == conn->uid) { return (ste.st_mode & S_IRUSR) == S_IRUSR; @@ -688,6 +723,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) } return (ste.st_mode & S_IROTH) == S_IROTH; +#endif } /******************************************************************* -- cgit From 0558e2c4024d419dfb7b77a2eec100f7916831d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Dec 2001 01:26:54 +0000 Subject: Fixed the bug with descending into mangled directories. The problem is that name_map_mangle can *change* the length of a patchname. Ensure that all the character pointer messing about can cope with changing sizes of components. This code is too ugly to live..... This also needs *lots* of testing. Jeremy. (This used to be commit 9f2b6a07429da5dec59e562fa5489b8079978677) --- source3/smbd/filename.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d1c512c251..f098950c44 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -283,7 +283,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } else { pstring rest; - /* Stat failed - ensure we don't use it. */ + /* Stat failed - ensure we don't use it. */ ZERO_STRUCT(st); *rest = 0; @@ -320,7 +320,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, /* * Just the last part of the name doesn't exist. - * We may need to strupper() or strlower() it in case + * We may need to strupper() or strlower() it in case * this conversion is being used for file creation * purposes. If the filename is of mixed case then * don't normalise it. @@ -343,11 +343,14 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, } /* - * Restore the rest of the string. + * Restore the rest of the string. If the string was mangled the size + * may have changed. */ if (end) { - pstrcpy(start+strlen(start)+1,rest); end = start + strlen(start); + pstrcat(start,"/"); + pstrcat(start,rest); + *end = '\0'; } } /* end else */ @@ -489,7 +492,7 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d if (!name_map_mangle(name2,False,True,SNUM(conn))) continue; - if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) { + if ((mangled && mangled_equal(name,name2)) || fname_equal(name, dname)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); -- cgit From 2a6eeff2a7a7c8c2ada79a3d1270998287d726e9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Dec 2001 02:09:57 +0000 Subject: Return NT_STATUS_OBJECT_NOT_FOUND or ERRbadpipe if pipe name not found. Jeremy. (This used to be commit d5fdb1f096e8db3e9cf7a65ddb75f7cafd1958c0) --- source3/smbd/nttrans.c | 2 +- source3/smbd/pipes.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2c3ac06f3c..457b045193 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -483,7 +483,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn, break; if ( known_nt_pipes[i] == NULL ) - return(ERROR_DOS(ERRSRV,ERRaccess)); + return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); /* Strip \\ off the name. */ fname++; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 9a911ed014..cd8a56a5d2 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -67,7 +67,7 @@ int reply_open_pipe_and_X(connection_struct *conn, break; if (pipe_names[i].client_pipe == NULL) - return(ERROR_DOS(ERRSRV,ERRaccess)); + return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); /* Strip \PIPE\ off the name. */ pstrcpy(fname, pipe_name + PIPELEN); -- cgit From ed611ffe1a83f9d08acafbe629c91300e6c5d13f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Dec 2001 08:19:02 +0000 Subject: Tidyup utmp code to cope with hostname = NULL. Jeremy (This used to be commit 2a1b531a1c4f1a4772c95c867f35eac50ed1c7fa) --- source3/smbd/utmp.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index cc52db8462..92e001cd03 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -299,8 +299,8 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) * man page appears not to specify (hints non-NULL) * A correspondent suggest at least ut_name should be NULL */ - memset((char *)&(u->ut_name), '\0', sizeof(u->ut_name)); - memset((char *)&(u->ut_host), '\0', sizeof(u->ut_host)); + memset((char *)&u->ut_name, '\0', sizeof(u->ut_name)); + memset((char *)&u->ut_host, '\0', sizeof(u->ut_host)); } /* Stolen from logwtmp function in libutil. * May be more locking/blocking is needed? @@ -319,7 +319,7 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) Update via utmp/wtmp (not utmpx/wtmpx). ****************************************************************************/ -static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim) +static void utmp_nox_update(struct utmp *u, BOOL claim) { pstring uname, wname; #if defined(PUTUTLINE_RETURNS_UTMP) @@ -380,14 +380,16 @@ static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim) static void utmp_strcpy(char *dest, const char *src, size_t n) { - size_t len; + size_t len = 0; - len = strlen(src); + memset(dest, '\0', n); + if (src) + len = strlen(src); if (len >= n) { memcpy(dest, src, n); } else { - memcpy(dest, src, len); - memset(dest + len, '\0', n - len); + if (len) + memcpy(dest, src, len); } } @@ -399,15 +401,15 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) { #if !defined(HAVE_UTMPX_H) /* No utmpx stuff. Drop to non-x stuff */ - utmp_nox_update(u, hostname, claim); + utmp_nox_update(u, claim); #elif !defined(HAVE_PUTUTXLINE) /* Odd. Have utmpx.h but no "pututxline()". Drop to non-x stuff */ DEBUG(1,("utmp_update: have utmpx.h but no pututxline() function\n")); - utmp_nox_update(u, hostname, claim); + utmp_nox_update(u, claim); #elif !defined(HAVE_GETUTMPX) /* Odd. Have utmpx.h but no "getutmpx()". Drop to non-x stuff */ DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n")); - utmp_nox_update(u, hostname, claim); + utmp_nox_update(u, claim); #else pstring uname, wname; struct utmpx ux, *uxrc; @@ -433,7 +435,7 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) * Drop to non-x method. (E.g. RH6 has good defaults in "utmp.h".) */ if ((strlen(uname) == 0) || (strlen(wname) == 0)) { - utmp_nox_update(u, hostname, claim); + utmp_nox_update(u, claim); } else { utmpxname(uname); setutxent(); -- cgit From 9126a40e2c33e0eb4cd57ab381634e08fa59e7a7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Dec 2001 09:53:30 +0000 Subject: added trusted realm support to ADS authentication the method used for checking if a domain is a trusted domain is very crude, we should really call a backend fn of some sort. For now I'm using winbindd to do the dirty work. (This used to be commit adf44a9bd0d997ba4dcfadc564a29149531525af) --- source3/smbd/sesssetup.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 4c26bda4db..60c9cd30e5 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -107,14 +107,18 @@ static int reply_spnego_kerberos(connection_struct *conn, *p = 0; if (strcasecmp(p+1, ads->realm) != 0) { - DEBUG(3,("Ticket for incorrect realm %s\n", p+1)); - ads_destroy(&ads); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); + if (!lp_allow_trusted_domains()) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + /* this gives a fully qualified user name (ie. with full realm). + that leads to very long usernames, but what else can we do? */ + asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client); + } else { + user = strdup(client); } ads_destroy(&ads); - user = client; - /* the password is good - let them in */ pw = smb_getpwnam(user,False); if (!pw) { @@ -129,6 +133,7 @@ static int reply_spnego_kerberos(connection_struct *conn, sess_vuid = register_vuid(server_info, user); + free(user); free_server_info(&server_info); if (sess_vuid == -1) { -- cgit From a784fce1090f4c67f064cb1230a32c574ecc652d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Dec 2001 17:47:19 +0000 Subject: Allow ACL set to fail gracefully on HP HFS filesystems. Jeremy. (This used to be commit 2d7b81e692ac2bcfd6e31223d3f8545c255cb47c) --- source3/smbd/posix_acls.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 324169a092..765bd0f3b2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1716,6 +1716,12 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if(default_ace || fsp->is_directory || fsp->fd == -1) { if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { + /* + * Some systems allow all the above calls and only fail with no ACL support + * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. + */ + if (errno == ENOSYS) + *pacl_set_support = False; DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", fsp->fsp_name, strerror(errno) )); @@ -1723,6 +1729,12 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau } } else { if (sys_acl_set_fd(fsp->fd, the_acl) == -1) { + /* + * Some systems allow all the above calls and only fail with no ACL support + * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. + */ + if (errno == ENOSYS) + *pacl_set_support = False; DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); goto done; -- cgit From 367c40fd876bb74b5c606f1ea985119a4ba8aca8 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 20 Dec 2001 05:10:50 +0000 Subject: Grr - numbers printed in hexadecimal should be preceeded by 0x (This used to be commit 7d8082a8ad7d5de5daf653903efd36fb84b3cedc) --- source3/smbd/nttrans.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 457b045193..7a6ea52aca 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -320,7 +320,7 @@ static int map_create_disposition( uint32 create_disposition) return -1; } - DEBUG(10,("map_create_disposition: Mapped create_disposition %lx to %x\n", + DEBUG(10,("map_create_disposition: Mapped create_disposition 0x%lx to 0x%x\n", (unsigned long)create_disposition, ret )); return ret; @@ -394,7 +394,7 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt smb_open_mode = DOS_OPEN_RDONLY; } else { - DEBUG(0,("map_share_mode: Incorrect value %lx for desired_access to file %s\n", + DEBUG(0,("map_share_mode: Incorrect value 0x%lx for desired_access to file %s\n", (unsigned long)desired_access, fname)); return -1; } @@ -408,7 +408,7 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt if(share_access & FILE_SHARE_DELETE) { smb_open_mode |= ALLOW_SHARE_DELETE; - DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = %x\n", smb_open_mode)); + DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode)); } /* @@ -420,14 +420,14 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt if(desired_access & DELETE_ACCESS) { smb_open_mode |= DELETE_ACCESS_REQUESTED; - DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = %x\n", smb_open_mode)); + DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); } if (create_options & FILE_DELETE_ON_CLOSE) { /* Implicit delete access requested... */ smb_open_mode |= DELETE_ACCESS_REQUESTED; smb_open_mode |= DELETE_ON_CLOSE_FLAG; - DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = %x\n", smb_open_mode)); + DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode)); } /* Add in the requested share mode. */ @@ -453,8 +453,8 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt if(file_attributes & FILE_FLAG_WRITE_THROUGH) smb_open_mode |= FILE_SYNC_OPENMODE; - DEBUG(10,("map_share_mode: Mapped desired access %lx, share access %lx, file attributes %lx \ -to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access, + DEBUG(10,("map_share_mode: Mapped desired access 0x%lx, share access 0x%lx, file attributes 0x%lx \ +to open_mode 0x%x\n", (unsigned long)desired_access, (unsigned long)share_access, (unsigned long)file_attributes, smb_open_mode )); return smb_open_mode; -- cgit From 2838f61540f899001b9a11928cbf6fc23d5cd5fe Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Dec 2001 06:52:45 +0000 Subject: fixed long filenames on win98 the fstype must not be null terminated or win98 doesn't recognise it (This used to be commit c8a040f2aa733e926280af010513849b6406741d) --- source3/smbd/trans2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index aaa5aade97..73496f406b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1155,7 +1155,9 @@ static int call_trans2qfsinfo(connection_struct *conn, SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ - len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE); + /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it + and will think we can't do long filenames */ + len = srvstr_push(outbuf, pdata+12, fstype, -1, 0); SIVAL(pdata,8,len); data_len = 12 + len; break; -- cgit From 1a242b6fd9c6f7dc43b629d0dc22ff42053e3c32 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Dec 2001 09:06:53 +0000 Subject: support "map to guest" with spnego (This used to be commit e873d0ff1eee9442ff6152d666b8d874b6a01972) --- source3/smbd/sesssetup.c | 64 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 60c9cd30e5..7fd0fd917a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -25,6 +25,35 @@ uint32 global_client_caps = 0; static auth_authsupplied_info *ntlmssp_auth_info; +/* + on a logon error possibly map the error to success if "map to guest" + is set approriately +*/ +static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info, + const char *user, const char *domain) +{ + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + DEBUG(3,("No such user %s [%s] - using guest account\n", + user, domain)); + make_server_info_guest(server_info); + status = NT_STATUS_OK; + } + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + DEBUG(3,("Registered username %s for guest access\n",user)); + make_server_info_guest(server_info); + status = NT_STATUS_OK; + } + } + + return status; +} + + /**************************************************************************** Add the standard 'Samba' signature to the end of the session setup. ****************************************************************************/ @@ -341,11 +370,15 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_NO_MEMORY); } + nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup); + } + SAFE_FREE(workgroup); SAFE_FREE(machine); - - nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); - + free_auth_info(&ntlmssp_auth_info); free_user_info(&user_info); @@ -353,7 +386,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, data_blob_free(&lmhash); data_blob_free(&nthash); - + if (!NT_STATUS_IS_OK(nt_status)) { SAFE_FREE(user); return ERROR_NT(nt_status_squash(nt_status)); @@ -371,6 +404,11 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); + + if (server_info->guest) { + SSVAL(outbuf,smb_vwv2,1); + } + add_signature(outbuf); SSVAL(outbuf,smb_uid,sess_vuid); @@ -663,7 +701,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } nt_status = check_password(user_info, negprot_global_auth_info, &server_info); - } else { auth_authsupplied_info *plaintext_auth_info = NULL; DATA_BLOB chal; @@ -692,22 +729,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_clear_free(&plaintext_password); if (!NT_STATUS_IS_OK(nt_status)) { - if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { - if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || - (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { - - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - make_server_info_guest(&server_info); - nt_status = NT_STATUS_OK; - } - - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { - if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { - DEBUG(3,("Registered username %s for guest access\n",user)); - make_server_info_guest(&server_info); - nt_status = NT_STATUS_OK; - } - } + nt_status = do_map_to_guest(nt_status, &server_info, user, domain); } if (!NT_STATUS_IS_OK(nt_status)) { -- cgit From 01a382480a148f70384da65b38c936bedcb4ba6b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Dec 2001 09:32:03 +0000 Subject: don't use server_info after its been freed (This used to be commit ee161a57289409e2fa43e33b045473077c7b6ba5) --- source3/smbd/sesssetup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7fd0fd917a..8424e0e186 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -325,6 +325,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, uint32 ntlmssp_command, neg_flags; NTSTATUS nt_status; int sess_vuid; + BOOL as_guest; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; @@ -392,8 +393,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(nt_status_squash(nt_status)); } - sess_vuid = register_vuid(server_info, user); + as_guest = server_info->guest; + sess_vuid = register_vuid(server_info, user); free_server_info(&server_info); SAFE_FREE(user); @@ -405,7 +407,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - if (server_info->guest) { + if (as_guest) { SSVAL(outbuf,smb_vwv2,1); } -- cgit From 9ed10f83d76eba1c4d4ac19842314f24db1c7a65 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 20 Dec 2001 22:27:05 +0000 Subject: Removed global debugf. Replaced with lp_set_logfile(name). Fixed winbindd to finally stop leaving log. file droppings :-). Jeremy. (This used to be commit 0bea6cf79a44f79fa3a4f2c8381e898e79c66509) --- source3/smbd/server.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index df56dfe9ab..c6eed4b9bb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -21,7 +21,6 @@ #include "includes.h" -extern pstring debugf; extern fstring global_myworkgroup; extern pstring global_myname; @@ -425,7 +424,7 @@ static BOOL dump_core(void) { char *p; pstring dname; - pstrcpy(dname,debugf); + pstrcpy(dname,lp_logfile()); if ((p=strrchr_m(dname,'/'))) *p=0; pstrcat(dname,"/corefiles"); mkdir(dname,0700); @@ -583,12 +582,13 @@ static void usage(char *pname) int main(int argc,char *argv[]) { extern BOOL append_log; + extern char *optarg; /* shall I run as a daemon */ BOOL is_daemon = False; BOOL specified_logfile = False; int port = SMB_PORT; int opt; - extern char *optarg; + pstring logfile; #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); @@ -612,7 +612,8 @@ static void usage(char *pname) case 'l': specified_logfile = True; - slprintf(debugf, sizeof(debugf)-1, "%s/log.smbd", optarg); + slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd", optarg); + lp_set_logfile(logfile); break; case 'a': @@ -670,8 +671,9 @@ static void usage(char *pname) append_log = True; if(!specified_logfile) { - slprintf(debugf, sizeof(debugf)-1, "%s/log.smbd", + slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd", dyn_LOGFILEBASE); + lp_set_logfile(logfile); } pstrcpy(remote_machine, "smbd"); -- cgit From 9eebd31e2c0dfb35e32c5524c21f544f89810866 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Dec 2001 23:36:39 +0000 Subject: check for a winbindd username when doing a kerberos auth (This used to be commit 39f2e2e1623a011e2c99ecca64e0643b1e450657) --- source3/smbd/sesssetup.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8424e0e186..7791637606 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -150,6 +150,17 @@ static int reply_spnego_kerberos(connection_struct *conn, /* the password is good - let them in */ pw = smb_getpwnam(user,False); + if (!pw && !strstr(user, lp_winbind_separator())) { + char *user2; + /* try it with a winbind domain prefix */ + asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user); + pw = smb_getpwnam(user2,False); + if (pw) { + free(user); + user = user2; + } + } + if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); return ERROR_NT(NT_STATUS_NO_SUCH_USER); -- cgit From bf65820af242786bd66d814fc3e9d89920a49f8e Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Fri, 21 Dec 2001 00:37:49 +0000 Subject: Add an output parameter to message_send_all that says how many messages were sent, so you know how many replies to expect. Const and doc religion. (This used to be commit 22e510ea0d69356be4fd2fa5ad9e9f4e84f62337) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 34dcf6c211..64da736ae2 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1724,7 +1724,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch goto error_exit; } else { SAFE_FREE(command); - message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False); + message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); } } else return False; -- cgit From 04aff47c716a51a1039b44a81d6ff19eeaa09017 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 27 Dec 2001 06:38:04 +0000 Subject: moving SAM_ACCOUNT to include a bit field for initialized members (such as uid and gid). This way we will be able to keep ourselves from writing out default smb.conf settings when the admin doesn't want to, That part is not done yet. Tested compiles with ldap/tdb/smbpasswd. Tested connection with smbpasswd backend. oh...and smbpasswd doesn'y automatically expire accounts after 21 days from the last password change either now. Just ifdef'd out that code in build_sam_account(). Will merge updates into 2.2 as they are necessary. jerry (This used to be commit f0d43791157d8f04a13a07d029f203ad4384d317) --- source3/smbd/password.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 71837efdcb..538225e245 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -209,8 +209,8 @@ tell random client vuid's (normally zero) from valid vuids. int register_vuid(auth_serversupplied_info *server_info, char *smb_name) { user_struct *vuser = NULL; - uid_t *puid; - gid_t *pgid; + uid_t uid; + gid_t gid; /* Ensure no vuid gets registered in share level security. */ if(lp_security() == SEC_SHARE) @@ -227,15 +227,15 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) ZERO_STRUCTP(vuser); - puid = pdb_get_uid(server_info->sam_account); - pgid = pdb_get_gid(server_info->sam_account); - - if (!puid || !pgid) { + if (!IS_SAM_UNIX_USER(server_info->sam_account)) { DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); free(vuser); return UID_FIELD_INVALID; } + uid = pdb_get_uid(server_info->sam_account); + gid = pdb_get_gid(server_info->sam_account); + /* Allocate a free vuid. Yes this is a linear search... :-) */ while( get_valid_user_struct(next_vuid) != NULL ) { next_vuid++; @@ -247,8 +247,8 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid )); vuser->vuid = next_vuid; - vuser->uid = *puid; - vuser->gid = *pgid; + vuser->uid = uid; + vuser->gid = gid; vuser->guest = server_info->guest; fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); fstrcpy(vuser->user.smb_name, smb_name); -- cgit From 4fd97a7a039b94f41e676886d810be523fe2f1e9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 29 Dec 2001 09:52:24 +0000 Subject: passing NULL to print_queue_status()'s status parameter could end in a segfault (This used to be commit 79254d2b0490ba400832ef6d460895d45cc4273f) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 00e0cb8b86..12834e63a7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2586,8 +2586,9 @@ int reply_printqueue(connection_struct *conn, { print_queue_struct *queue = NULL; + print_status_struct status; char *p = smb_buf(outbuf) + 3; - int count = print_queue_status(SNUM(conn), &queue,NULL); + int count = print_queue_status(SNUM(conn), &queue, &status); int num_to_get = ABS(max_count); int first = (max_count>0?start_index:start_index+max_count+1); int i; -- cgit From 0d6a1c09982f7497a4ea80f9c4db3bb249ccfa67 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 29 Dec 2001 21:13:53 +0000 Subject: Fixup -i interactive modes. Jeremy. (This used to be commit 9343b613d3778b0330bc4d610d3befd363797360) --- source3/smbd/server.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c6eed4b9bb..403ed12c40 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -559,10 +559,11 @@ usage on the program static void usage(char *pname) { - d_printf("Usage: %s [-DaoPh?Vb] [-d debuglevel] [-l log basename] [-p port]\n", pname); + d_printf("Usage: %s [-DaioPh?Vb] [-d debuglevel] [-l log basename] [-p port]\n", pname); d_printf(" [-O socket options] [-s services file]\n"); - d_printf("\t-D Become a daemon\n"); + d_printf("\t-D Become a daemon (default)\n"); d_printf("\t-a Append to log file (default)\n"); + d_printf("\t-i Run interactive (not a daemon)\n" ); d_printf("\t-o Overwrite log file, don't append\n"); d_printf("\t-h Print usage\n"); d_printf("\t-? Print usage\n"); @@ -585,6 +586,7 @@ static void usage(char *pname) extern char *optarg; /* shall I run as a daemon */ BOOL is_daemon = False; + BOOL interactive = False; BOOL specified_logfile = False; int port = SMB_PORT; int opt; @@ -600,7 +602,7 @@ static void usage(char *pname) argc--; } - while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?bVaof:")) ) + while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?bVaiof:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); @@ -620,6 +622,10 @@ static void usage(char *pname) append_log = True; break; + case 'i': + interactive = True; + break; + case 'o': append_log = False; break; @@ -678,7 +684,7 @@ static void usage(char *pname) pstrcpy(remote_machine, "smbd"); - setup_logging(argv[0],False); + setup_logging(argv[0],interactive); /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ @@ -720,7 +726,7 @@ static void usage(char *pname) reopen_logs(); DEBUG(1,( "smbd version %s started.\n", VERSION)); - DEBUGADD(1,( "Copyright Andrew Tridgell 1992-1998\n")); + DEBUGADD(1,( "Copyright Andrew Tridgell 1992-2002\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); @@ -774,7 +780,7 @@ static void usage(char *pname) is_daemon = True; } - if (is_daemon) { + if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(); } -- cgit From bb81e23e176ec7dfe0111b5aa2946a51239ef3b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 30 Dec 2001 01:46:38 +0000 Subject: When running interactive we want to set our own process group for signal management. Jeremy. (This used to be commit fffae94dd5699f44c0b1c8081587deafd89b3fc0) --- source3/smbd/server.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 403ed12c40..101d49c144 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -785,6 +785,15 @@ static void usage(char *pname) become_daemon(); } +#if HAVE_SETPGID + /* + * If we're interactive we want to set our own process group for + * signal management. + */ + if (interactive) + setpgid( (pid_t)0, (pid_t)0); +#endif + if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); } -- cgit From eb4e10115310b6ed23b92abac2e79454c80930b1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 31 Dec 2001 13:46:26 +0000 Subject: - portablitity fixes for cc -64 on irix - fixed gid* bug in rpc_server (This used to be commit 48aa90c48c5f0e3054c4acdc49668e222e7c0d36) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7791637606..57e0ee2f3a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -77,7 +77,7 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; - char chal[8]; + unsigned char chal[8]; ZERO_STRUCT(chal); -- cgit From 4a6d1318bd9123f5a9c1d72721a9175320356fbe Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 1 Jan 2002 03:10:32 +0000 Subject: A farily large commit: - Move rpc_client/cli_trust.c to smbd/change_trust_pw.c - It hasn't been used by anything else since smbpasswd lost its -j - Add a TALLOC_CTX to the auth subsytem. These are only valid for the length of the calls to the individual modules, if you want a longer context hide it in your private data. Similarly, all returns (like the server_info) should still be malloced. - Move the 'ntdomain' module (security=domain in oldspeak) over to use the new libsmb domain logon code. Also rework much of the code to use some better helper functions for the connection - getting us much better error returns (the new code is NTSTATUS). The only remaining thing to do is to figure out if tpot's 0xdead 0xbeef for the LUID feilds is sufficient, or if we should do random LUIDs as per the old code. Similarly, I'll move winbind over to this when I get a chance. This leaves the SPOOLSS code and some cli_pipe code as the only stuff still in rpc_client, at least as far as smbd is concerned. While I've given this a basic rundown, any testing is as always appriciated. Andrew Bartlett (This used to be commit d870edce76ecca259230fbdbdacd0c86793b4837) --- source3/smbd/change_trust_pw.c | 152 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 source3/smbd/change_trust_pw.c (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c new file mode 100644 index 0000000000..8a16793843 --- /dev/null +++ b/source3/smbd/change_trust_pw.c @@ -0,0 +1,152 @@ +/* + * Unix SMB/Netbios implementation. + * Version 3.0 + * Periodic Trust account password changing. + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * Copyright (C) Jeremy Allison 1998. + * Copyright (C) Andrew Bartlett 2001. + * + * 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 pstring global_myname; + +/********************************************************* + Change the domain password on the PDC. +**********************************************************/ + +static NTSTATUS modify_trust_password( char *domain, char *remote_machine, + unsigned char orig_trust_passwd_hash[16]) +{ + struct cli_state *cli; + DOM_SID domain_sid; + struct in_addr dest_ip; + NTSTATUS nt_status; + + /* + * Ensure we have the domain SID for this domain. + */ + + if (!secrets_fetch_domain_sid(domain, &domain_sid)) { + DEBUG(0, ("domain_client_validate: unable to fetch domain sid.\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if(!resolve_name( remote_machine, &dest_ip, 0x20)) { + DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine)); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname, remote_machine, + &dest_ip, 0, + "IPC$", "IPC", + "", "", + "", 0))) { + DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* + * Ok - we have an anonymous connection to the IPC$ share. + * Now start the NT Domain stuff :-). + */ + + if(cli_nt_session_open(cli, PIPE_NETLOGON) == False) { + DEBUG(0,("modify_trust_password: unable to open the domain client session to \ +machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli))); + cli_nt_session_close(cli); + cli_ulogoff(cli); + cli_shutdown(cli); + return NT_STATUS_UNSUCCESSFUL; + } + + nt_status = trust_pw_change_and_store_it(cli, cli->mem_ctx, + orig_trust_passwd_hash); + + cli_nt_session_close(cli); + cli_ulogoff(cli); + cli_shutdown(cli); + return nt_status; +} + +/************************************************************************ + Change the trust account password for a domain. +************************************************************************/ + +NTSTATUS change_trust_account_password( char *domain, char *remote_machine_list) +{ + fstring remote_machine; + unsigned char old_trust_passwd_hash[16]; + time_t lct; + NTSTATUS res = NT_STATUS_UNSUCCESSFUL; + + if(!secrets_fetch_trust_account_password(domain, old_trust_passwd_hash, &lct)) { + DEBUG(0,("change_trust_account_password: unable to read the machine \ +account password for domain %s.\n", domain)); + return NT_STATUS_UNSUCCESSFUL; + } + + while(remote_machine_list && + next_token(&remote_machine_list, remote_machine, + LIST_SEP, sizeof(remote_machine))) { + strupper(remote_machine); + if(strequal(remote_machine, "*")) { + + /* + * We have been asked to dynamcially determine the IP addresses of the PDC. + */ + + struct in_addr *ip_list = NULL; + int count = 0; + int i; + + /* Use the PDC *only* for this. */ + if(!get_dc_list(True, domain, &ip_list, &count)) + continue; + + /* + * Try and connect to the PDC/BDC list in turn as an IP + * address used as a string. + */ + + for(i = 0; i < count; i++) { + fstring dc_name; + if(!lookup_dc_name(global_myname, domain, &ip_list[i], dc_name)) + continue; + if(NT_STATUS_IS_OK(res = modify_trust_password( domain, dc_name, + old_trust_passwd_hash))) + break; + } + + SAFE_FREE(ip_list); + + } else { + res = modify_trust_password( domain, remote_machine, + old_trust_passwd_hash); + } + + } + + if (!NT_STATUS_IS_OK(res)) { + DEBUG(0,("%s : change_trust_account_password: Failed to change password for \ +domain %s.\n", timestring(False), domain)); + } + + return res; +} -- cgit From a3f891dbd2e9ee1681e3c8295cd62a877c727d4f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 2 Jan 2002 07:41:54 +0000 Subject: Actually enforce the passdb API. Thou shalt not reference SAM_ACCOUNT members directly - always use pdb_get/pdb_set. This is achived by making the whole of SAM_ACCOUNT have a .private member, where the real members live. This caught a pile of examples, and these have beeen fixed. The pdb_get..() functions are 'const' (have been for some time) and this required a few small changes to constify other functions. I've also added some debugs to the pdb get and set, they can be removed if requested. I've rewritten the copy_id2x_to_sam_pass() functions to use the new passdb interface, but I need the flags info to do it properly. The pdb_free_sam() funciton now blanks out the LM and NT hashes, and as such I have removed many extra 'samr_clear_sam_passwd(smbpass)' calls as a result. Finally, any and all testing is always appriciated - but the basics seem to work. Andrew Bartlett (This used to be commit d3dd28f6c443187b8d820d5a39c7c5b3be2fa95c) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 538225e245..a9d80d36fd 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -228,7 +228,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) ZERO_STRUCTP(vuser); if (!IS_SAM_UNIX_USER(server_info->sam_account)) { - DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); + DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT (flags:%x)\n", pdb_get_init_flag(server_info->sam_account))); free(vuser); return UID_FIELD_INVALID; } -- cgit From 4178f211d1d2d133b96b420361944f5e197ec556 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jan 2002 23:28:55 +0000 Subject: debug statement fixups. Merge SAFE_FREE fix in tdb from 2.2, and IRIX fix. Jeremy. (This used to be commit eb6607466565bcd5b3800492d0bc1ae8a44da4f6) --- source3/smbd/sesssetup.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 57e0ee2f3a..41a7a657e2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -792,8 +792,3 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, END_PROFILE(SMBsesssetupX); return chain_reply(inbuf,outbuf,length,bufsize); } - - - - - -- cgit From 91ec6cf19ffffce3caacea4b4489eb20761de4a5 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Thu, 3 Jan 2002 03:53:41 +0000 Subject: smbd should register to receive MSG_REQ_POOL_USAGE. Response should be information about memory usage, but this is not done yet. (This used to be commit 830a126a442bdde28fc42e23e7260c344b6534b9) --- source3/smbd/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 101d49c144..900f5b4846 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -805,6 +805,7 @@ static void usage(char *pname) if (!message_init()) { exit(1); } + register_msg_pool_usage(); /* Setup the main smbd so that we can get messages. */ claim_connection(NULL,"",MAXSTATUS,True); -- cgit From af643d5f1f9eb7e5aa10a9cfef3bd6dce38ace1d Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Thu, 3 Jan 2002 05:41:13 +0000 Subject: smbd children should also register for POOL_USAGE (This used to be commit b46d874f4736493bdc4244ec6cdf95e77347e7d5) --- source3/smbd/process.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 111da3bcef..d8d644338d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1230,6 +1230,7 @@ void smbd_process(void) /* register our message handlers */ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); + register_msg_pool_usage(); while (True) { int deadtime = lp_deadtime()*60; -- cgit From f55c47b1ff9b9b53a53de320a6f7ddc181292b27 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Thu, 3 Jan 2002 05:57:41 +0000 Subject: Fix talloc msg registration (This used to be commit 9a473ecf96fca35d146756c0c313b156aba8d9d9) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d8d644338d..af081d5059 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1230,7 +1230,7 @@ void smbd_process(void) /* register our message handlers */ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); - register_msg_pool_usage(); + talloc_init_named("dummy!"); while (True) { int deadtime = lp_deadtime()*60; -- cgit From 41dd759a50c53504efcd26771a265f34f20a1445 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Jan 2002 20:49:06 +0000 Subject: Ensure modtime is set correctly on destination files in copy command. Jeremy. (This used to be commit fb1ab02553e01df0464f0df3eea7ae6a66b4104b) --- source3/smbd/reply.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 12834e63a7..0e7eca3ac2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3287,6 +3287,10 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); close_file(fsp1,False); + + /* Ensure the modtime is set correctly on the destination file. */ + fsp2->pending_modtime = src_sbuf.st_mtime; + /* * As we are opening fsp1 read-only we only expect * an error on close on fsp2 if we are out of space. -- cgit From eb61d92ca7053bef9142a29f296aae695c47db33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2002 21:11:35 +0000 Subject: Re-wrote the guts of the rename_internals code to cope with a reported bug (renaming name -> name was failing, on W2K it succeeds). Simplified the common case, did a lot of work to ensure NT error codes are correctly reported back to client. Jeremy. (This used to be commit e6b27f3d8069ae304baaebe09341c58d46b05fe4) --- source3/smbd/nttrans.c | 3 +- source3/smbd/reply.c | 117 +++++++++++++++++++++++++++++++++---------------- source3/smbd/vfs.c | 23 ++++++++-- 3 files changed, 102 insertions(+), 41 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7a6ea52aca..464790d158 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1454,7 +1454,8 @@ static int call_nt_transact_rename(connection_struct *conn, status = rename_internals(conn, fsp->fsp_name, new_name, replace_if_exists); - if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); /* * Rename was successful. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0e7eca3ac2..9e6f8d24c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2952,26 +2952,26 @@ static BOOL resolve_wildcards(char *name1,char *name2) } /******************************************************************* -check if a user is allowed to rename a file + Check if a user is allowed to rename a file. ********************************************************************/ -static BOOL can_rename(char *fname,connection_struct *conn) + +static NTSTATUS can_rename(char *fname,connection_struct *conn) { - SMB_STRUCT_STAT sbuf; + if (!CAN_WRITE(conn)) + return NT_STATUS_ACCESS_DENIED; - if (!CAN_WRITE(conn)) return(False); + if (!check_file_sharing(conn,fname,True)) + return NT_STATUS_SHARING_VIOLATION; - if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False); - if (!check_file_sharing(conn,fname,True)) return(False); - return(True); + return NT_STATUS_OK; } /**************************************************************************** The guts of the rename command, split out so it may be called by the NT SMB code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, - char *name, - char *newname, BOOL replace_if_exists) + +NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists) { pstring directory; pstring mask; @@ -2982,7 +2982,6 @@ NTSTATUS rename_internals(connection_struct *conn, BOOL bad_path2 = False; int count=0; NTSTATUS error = NT_STATUS_OK; - BOOL exists=False; BOOL rc = True; SMB_STRUCT_STAT sbuf1, sbuf2; @@ -3056,7 +3055,8 @@ NTSTATUS rename_internals(connection_struct *conn, pstrcpy(newname, tmpstr); } - DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", + DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \ +directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", case_sensitive, case_preserve, short_case_preserve, directory, newname, newname_last_component, is_short_name)); @@ -3093,34 +3093,76 @@ NTSTATUS rename_internals(connection_struct *conn, pstrcpy(p+1, newname_last_component); } } - - if(replace_if_exists) { - /* - * NT SMB specific flag - rename can overwrite - * file with the same name so don't check for - * vfs_file_exist(). - */ + + resolve_wildcards(directory,newname); + + /* + * The source object must exist. + */ - if(resolve_wildcards(directory,newname) && - can_rename(directory,conn) && - conn->vfs_ops.rename(conn,directory,newname) == 0) - count++; - } else { - if (resolve_wildcards(directory,newname) && - can_rename(directory,conn) && - !vfs_file_exist(conn,newname,NULL) && - conn->vfs_ops.rename(conn,directory,newname) == 0) - count++; + if (!vfs_object_exist(conn, directory, NULL)) { + DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n", + directory,newname)); + + if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) { + /* + * Must return different errors depending on whether the parent + * directory existed or not. + */ + + p = strrchr_m(directory, '/'); + if (!p) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + *p = '\0'; + if (vfs_object_exist(conn, directory, NULL)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + error = map_nt_error_from_unix(errno); + DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", + get_nt_error_msg(error), directory,newname)); + + return error; } - DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", - directory,newname)); - - if (!count) exists = vfs_file_exist(conn,directory,NULL); - if (!count && exists && vfs_file_exist(conn,newname,NULL)) { - exists = True; - error = NT_STATUS_OBJECT_NAME_COLLISION; + error = can_rename(directory,conn); + + if (!NT_STATUS_IS_OK(error)) { + DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", + get_nt_error_msg(error), directory,newname)); + } + + /* + * If the src and dest names are identical - including case, + * don't do the rename, just return success. + */ + + if (strcsequal(directory, newname)) { + DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory)); + return NT_STATUS_OK; } + + if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) { + DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n", + directory,newname)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + if(conn->vfs_ops.rename(conn,directory, newname) == 0) { + DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", + directory,newname)); + return NT_STATUS_OK; + } + + if (errno == ENOTDIR || errno == EISDIR) + error = NT_STATUS_OBJECT_NAME_COLLISION; + else + error = map_nt_error_from_unix(errno); + + DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", + get_nt_error_msg(error), directory,newname)); + + return error; } else { /* * Wildcards - process each file that matches. @@ -3148,7 +3190,8 @@ NTSTATUS rename_internals(connection_struct *conn, error = NT_STATUS_ACCESS_DENIED; slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); - if (!can_rename(fname,conn)) { + error = can_rename(fname,conn); + if (!NT_STATUS_IS_OK(error)) { DEBUG(6,("rename %s refused\n", fname)); continue; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 6d8e9cc76c..afdfe8c48f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -231,10 +231,10 @@ int vfs_mkdir(connection_struct *conn, const char *name, mode_t mode) } /******************************************************************* - Check if a vfs file exists. + Check if an object exists in the vfs. ********************************************************************/ -BOOL vfs_file_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf) +BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_STAT st; @@ -243,9 +243,26 @@ BOOL vfs_file_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *s ZERO_STRUCTP(sbuf); - if (vfs_stat(conn,fname,sbuf) != 0) + if (vfs_stat(conn,fname,sbuf) == -1) return(False); + return True; +} + +/******************************************************************* + Check if a file exists in the vfs. +********************************************************************/ + +BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) +{ + SMB_STRUCT_STAT st; + + if (!sbuf) + sbuf = &st; + ZERO_STRUCTP(sbuf); + + if (vfs_stat(conn,fname,sbuf) == -1) + return False; return(S_ISREG(sbuf->st_mode)); } -- cgit From e86102e86804ec07d8dd704dac963b8b72cd0250 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2002 22:30:00 +0000 Subject: Missed error return is can_rename fails. Jeremy. (This used to be commit 2db99fa49b538e230f2c606d1004871111ea2bf6) --- source3/smbd/reply.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9e6f8d24c2..c67ce357c6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3130,6 +3130,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", if (!NT_STATUS_IS_OK(error)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", get_nt_error_msg(error), directory,newname)); + return error; } /* -- cgit From 2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 5 Jan 2002 04:55:41 +0000 Subject: I've decided to move the auth code around a bit more... The auth_authsupplied_info typedef is now just a plain struct - auth_context, but it has been modified to contain the function pointers to the rest of the auth subsystem's components. (Who needs non-static functions anyway?) In working all this mess out, I fixed a number of memory leaks and moved the entire auth subsystem over to talloc(). Note that the TALLOC_CTX attached to the auth_context can be rather long-lived, it is provided for things that are intended to live as long. (The global_negprot_auth_context lasts the whole life of the smbd). I've also adjusted a few things in auth_domain.c, mainly passing the domain as a paramater to a few functions instead of looking up lp_workgroup(). I'm hopign to make this entire thing a bit more trusted domains (as PDC) freindly in the near future. Other than that, I moved a bit of the code around, hence the rather messy diff. Andrew Bartlett (This used to be commit 12f5515f556cf39fea98134fe3e2ac4540501048) --- source3/smbd/negprot.c | 51 +++++++++++++----------- source3/smbd/process.c | 12 +++--- source3/smbd/server.c | 6 ++- source3/smbd/sesssetup.c | 101 ++++++++++++++++++++++++++--------------------- 4 files changed, 94 insertions(+), 76 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index d3afa19d00..52ba5e9789 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -27,7 +27,28 @@ extern fstring global_myworkgroup; extern fstring remote_machine; BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; -auth_authsupplied_info *negprot_global_auth_info = NULL; +struct auth_context *negprot_global_auth_context = NULL; + +static void get_challange(char buff[8]) +{ + NTSTATUS nt_status; + const uint8 *cryptkey; + + /* We might be called more than once, muliple negprots are premitted */ + if (negprot_global_auth_context) { + DEBUG(3, ("get challange: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n")); + negprot_global_auth_context->free(&negprot_global_auth_context); + } + + DEBUG(10, ("get challange: creating negprot_global_auth_context\n")); + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) { + DEBUG(0, ("make_auth_context_subsystem returned %s", get_nt_error_msg(nt_status))); + smb_panic("cannot make_negprot_global_auth_context!\n"); + } + DEBUG(10, ("get challange: getting challange\n")); + cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context); + memcpy(buff, cryptkey, 8); +} /**************************************************************************** reply for the core protocol @@ -69,7 +90,6 @@ static int reply_lanman1(char *inbuf, char *outbuf) int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; time_t t = time(NULL); - DATA_BLOB cryptkey; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); @@ -80,12 +100,7 @@ static int reply_lanman1(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - if (!make_auth_info_subsystem(&negprot_global_auth_info)) { - smb_panic("cannot make_negprot_global_auth_info!\n"); - } - cryptkey = auth_get_challenge(negprot_global_auth_info); - memcpy(smb_buf(outbuf), cryptkey.data, 8); - data_blob_free(&cryptkey); + get_challange(smb_buf(outbuf)); } Protocol = PROTOCOL_LANMAN1; @@ -114,7 +129,6 @@ static int reply_lanman2(char *inbuf, char *outbuf) int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; time_t t = time(NULL); - DATA_BLOB cryptkey; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); @@ -125,13 +139,9 @@ static int reply_lanman2(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv1,secword); SIVAL(outbuf,smb_vwv6,sys_getpid()); + /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - if (!make_auth_info_subsystem(&negprot_global_auth_info)) { - smb_panic("cannot make_negprot_global_auth_info!\n"); - } - cryptkey = auth_get_challenge(negprot_global_auth_info); - memcpy(smb_buf(outbuf), cryptkey.data, 8); - data_blob_free(&cryptkey); + get_challange(smb_buf(outbuf)); } Protocol = PROTOCOL_LANMAN2; @@ -216,7 +226,6 @@ static int reply_nt1(char *inbuf, char *outbuf) int secword=0; time_t t = time(NULL); - DATA_BLOB cryptkey; char *p, *q; BOOL negotiate_spnego = False; @@ -275,13 +284,9 @@ static int reply_nt1(char *inbuf, char *outbuf) p = q = smb_buf(outbuf); if (!negotiate_spnego) { - if (global_encrypted_passwords_negotiated) { - if (!make_auth_info_subsystem(&negprot_global_auth_info)) { - smb_panic("cannot make_negprot_global_auth_info!\n"); - } - cryptkey = auth_get_challenge(negprot_global_auth_info); - memcpy(p, cryptkey.data, 8); - data_blob_free(&cryptkey); + /* Create a token value and add it to the outgoing packet. */ + if (global_encrypted_passwords_negotiated) { + get_challange(p); } SSVALS(outbuf,smb_vwv16+1,8); p += 8; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index af081d5059..2b31a24ced 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1112,7 +1112,7 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - extern auth_authsupplied_info *negprot_global_auth_info; + extern struct auth_context *negprot_global_auth_context; if (!send_keepalive(smbd_server_fd())) { DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); return False; @@ -1121,11 +1121,11 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t /* send a keepalive for a password server or the like. This is attached to the auth_info created in the negprot */ - if (negprot_global_auth_info - && negprot_global_auth_info->challenge_set_method - && negprot_global_auth_info->challenge_set_method->send_keepalive) { - negprot_global_auth_info->challenge_set_method->send_keepalive - (&negprot_global_auth_info->challenge_set_method->private_data); + if (negprot_global_auth_context + && negprot_global_auth_context->challenge_set_method + && negprot_global_auth_context->challenge_set_method->send_keepalive) { + negprot_global_auth_context->challenge_set_method->send_keepalive + (&negprot_global_auth_context->challenge_set_method->private_data); } last_keepalive_sent_time = t; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 900f5b4846..1fab45048d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -475,7 +475,7 @@ void exit_server(char *reason) { static int firsttime=1; extern char *last_inbuf; - extern auth_authsupplied_info *negprot_global_auth_info; + extern struct auth_context *negprot_global_auth_context; if (!firsttime) exit(0); @@ -484,7 +484,9 @@ void exit_server(char *reason) change_to_root_user(); DEBUG(2,("Closing connections\n")); - free_auth_info(&negprot_global_auth_info); + if (negprot_global_auth_context) { + negprot_global_auth_context->free(&negprot_global_auth_context); + } conn_close_all(); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 41a7a657e2..737ecade7d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,7 +23,7 @@ #include "includes.h" uint32 global_client_caps = 0; -static auth_authsupplied_info *ntlmssp_auth_info; +static struct auth_context *ntlmssp_auth_context; /* on a logon error possibly map the error to success if "map to guest" @@ -72,8 +72,7 @@ static void add_signature(char *outbuf) ****************************************************************************/ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) { - - auth_authsupplied_info *auth_info; + struct auth_context *auth_context; auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; @@ -83,11 +82,17 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) DEBUG(3,("Got anonymous request\n")); - make_user_info_guest(&user_info); - make_auth_info_fixed(&auth_info, chal); + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) { + return nt_status; + } + + if (!make_user_info_guest(&user_info)) { + auth_context->free(&auth_context); + return NT_STATUS_NO_MEMORY; + } - nt_status = check_password(user_info, auth_info, server_info); - free_auth_info(&auth_info); + nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info); + auth_context->free(&auth_context); free_user_info(&user_info); return nt_status; } @@ -233,8 +238,9 @@ static int reply_spnego_negotiate(connection_struct *conn, int i; uint32 ntlmssp_command, neg_flags; DATA_BLOB sess_key, chal, spnego_chal; - DATA_BLOB cryptkey; + const uint8 *cryptkey; BOOL got_kerberos = False; + NTSTATUS nt_status; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { @@ -282,11 +288,15 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); - if (!make_auth_info_subsystem(&ntlmssp_auth_info)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + if (!ntlmssp_auth_context) { + ntlmssp_auth_context->free(&ntlmssp_auth_context); + } + + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) { + return ERROR_NT(nt_status); } - cryptkey = auth_get_challenge(ntlmssp_auth_info); + cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context); /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ @@ -301,7 +311,7 @@ static int reply_spnego_negotiate(connection_struct *conn, 0, 0x30, /* ?? */ neg_flags, - cryptkey.data, cryptkey.length, + cryptkey, sizeof(cryptkey), 0, 0, 0, 0x3000); /* ?? */ @@ -314,7 +324,6 @@ static int reply_spnego_negotiate(connection_struct *conn, reply_sesssetup_blob(conn, outbuf, spnego_chal); data_blob_free(&chal); - data_blob_free(&cryptkey); data_blob_free(&spnego_chal); /* and tell smbd that we have already replied to this packet */ @@ -382,7 +391,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_NO_MEMORY); } - nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); + nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info); if (!NT_STATUS_IS_OK(nt_status)) { nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup); @@ -391,7 +400,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, SAFE_FREE(workgroup); SAFE_FREE(machine); - free_auth_info(&ntlmssp_auth_info); + ntlmssp_auth_context->free(&ntlmssp_auth_context); free_user_info(&user_info); @@ -544,7 +553,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern int max_send; auth_usersupplied_info *user_info = NULL; - extern auth_authsupplied_info *negprot_global_auth_info; + extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; @@ -671,13 +680,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine)); - if (*user) { - if (global_spnego_negotiated) { - DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); - } - } - if (*user) { pstrcpy(sub_user, user); } else { @@ -702,37 +704,46 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } if (!*user) { + if (global_spnego_negotiated) { + + /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */ + + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } nt_status = check_guest_password(&server_info); } else if (doencrypt) { if (!make_user_info_for_reply_enc(&user_info, user, domain, - lm_resp, nt_resp, - plaintext_password)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + lm_resp, nt_resp)) { + nt_status = NT_STATUS_NO_MEMORY; + } else { + nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, + user_info, + &server_info); } - - nt_status = check_password(user_info, negprot_global_auth_info, &server_info); } else { - auth_authsupplied_info *plaintext_auth_info = NULL; - DATA_BLOB chal; - if (!make_auth_info_subsystem(&plaintext_auth_info)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - chal = auth_get_challenge(plaintext_auth_info); - - if (!make_user_info_for_reply(&user_info, - user, domain, chal.data, - plaintext_password)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - nt_status = check_password(user_info, plaintext_auth_info, &server_info); + struct auth_context *plaintext_auth_context = NULL; + const uint8 *chal; + if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) { + chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); + + if (!make_user_info_for_reply(&user_info, + user, domain, chal, + plaintext_password)) { + nt_status = NT_STATUS_NO_MEMORY; + } - data_blob_free(&chal); - free_auth_info(&plaintext_auth_info); + if (NT_STATUS_IS_OK(nt_status)) { + nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, + user_info, + &server_info); + + plaintext_auth_context->free(&plaintext_auth_context); + } + } } free_user_info(&user_info); -- cgit From 341f87090bad76c427bae85bf81798aaea6c659b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 5 Jan 2002 12:04:33 +0000 Subject: Fix up the SPNEGO segfault. (This used to be commit 17b1c83dd02035048bd38b305460c96c6c09343a) --- source3/smbd/sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 737ecade7d..8b7a29ea86 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,7 +23,7 @@ #include "includes.h" uint32 global_client_caps = 0; -static struct auth_context *ntlmssp_auth_context; +static struct auth_context *ntlmssp_auth_context = NULL; /* on a logon error possibly map the error to success if "map to guest" @@ -288,7 +288,7 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); - if (!ntlmssp_auth_context) { + if (ntlmssp_auth_context) { ntlmssp_auth_context->free(&ntlmssp_auth_context); } -- cgit From b283dba09d1ad7bcf14066071cf2df8de95a9b12 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 6 Jan 2002 00:49:23 +0000 Subject: Some more SPNEGO fixes. (This used to be commit 0e564cb32acc70c1fc43f1be5ceb3637f0dc7361) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8b7a29ea86..c6cb40fcda 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -311,7 +311,7 @@ static int reply_spnego_negotiate(connection_struct *conn, 0, 0x30, /* ?? */ neg_flags, - cryptkey, sizeof(cryptkey), + cryptkey, 8, 0, 0, 0, 0x3000); /* ?? */ -- cgit From b8b228d9615352f552a534c30076032d4e2dd3ef Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 6 Jan 2002 01:37:14 +0000 Subject: Get this code back to where it belongs... Apparently (and I will doublecheck) its legal to do an annoymous session setup when we negoitiated SPNEGO, but we can't do an authenticated one becouse we didn't give a challange. Andrew Bartlett (This used to be commit 08a5c5bf940fac7a779be01db01ae7d97df80f79) --- source3/smbd/sesssetup.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c6cb40fcda..a159111319 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -681,6 +681,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine)); if (*user) { + if (global_spnego_negotiated) { + + /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */ + + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } pstrcpy(sub_user, user); } else { pstrcpy(sub_user, lp_guestaccount()); @@ -704,13 +711,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } if (!*user) { - if (global_spnego_negotiated) { - - /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */ - - DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); - } nt_status = check_guest_password(&server_info); -- cgit From d2687a00e1fe374128a7ad5707f1f7e62d8512d9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jan 2002 02:35:08 +0000 Subject: Fixed up atomic update code. Jeremy. (This used to be commit 274b04d4a6123fbfe363afc214e908ab36c7e8a7) --- source3/smbd/process.c | 4 ++-- source3/smbd/server.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2b31a24ced..ff53acbd9e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -791,7 +791,7 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) ****************************************************************************/ static BOOL smbd_process_limit(void) { - int total_smbds; + int32 total_smbds; if (lp_max_smbd_processes()) { @@ -807,7 +807,7 @@ set. Ignoring max smbd restriction.\n")); return False; } - if (tdb_change_int_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1) + if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1) return True; return total_smbds > lp_max_smbd_processes(); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1fab45048d..08bcf22dd2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -460,11 +460,11 @@ update the current smbd process count static void decrement_smbd_process_count(void) { - int total_smbds; + int32 total_smbds; if (lp_max_smbd_processes()) { total_smbds = 0; - tdb_change_int_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1); + tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1); } } -- cgit From bb21af13e36d476e52a6151be1d7bbf9ed6e6412 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Wed, 9 Jan 2002 05:27:59 +0000 Subject: Add UNUSED(paramname) macro to be used in parameter lists, to quieten gcc warnings about unused parameters. (This used to be commit b29775d442c36f667a6db5ba9dbe47d1a133525f) --- source3/smbd/server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 08bcf22dd2..a8c1bc5c15 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -80,7 +80,8 @@ static void killkids(void) process a sam sync message - not sure whether to do this here or somewhere else ****************************************************************************/ -static void msg_sam_sync(int msg_type, pid_t pid, void *buf, size_t len) +static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), + void *UNUSED(buf), size_t UNUSED(len)) { DEBUG(10, ("** sam sync message received, ignoring\n")); } -- cgit From f5bc0e92a66b418b2bd8f3669a9642b4d46bc8d1 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Wed, 9 Jan 2002 07:52:51 +0000 Subject: Better explanation message for dmalloc. Also more insertion of parenthesis to handle struct members called 'free'. You can now get useful dmalloc output, as long as it is compatible with your C library. On RH7.1 it looks like you have to rebuild dmalloc to allow free(0) by default, because something in libcrypt does that. (sigh) (This used to be commit 391cbb690196537c8b6292b42c2e27408cc7e249) --- source3/smbd/negprot.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/sesssetup.c | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 52ba5e9789..af2f91936e 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -37,7 +37,7 @@ static void get_challange(char buff[8]) /* We might be called more than once, muliple negprots are premitted */ if (negprot_global_auth_context) { DEBUG(3, ("get challange: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n")); - negprot_global_auth_context->free(&negprot_global_auth_context); + (negprot_global_auth_context->free)(&negprot_global_auth_context); } DEBUG(10, ("get challange: creating negprot_global_auth_context\n")); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a8c1bc5c15..b523659dbf 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -486,7 +486,7 @@ void exit_server(char *reason) DEBUG(2,("Closing connections\n")); if (negprot_global_auth_context) { - negprot_global_auth_context->free(&negprot_global_auth_context); + (negprot_global_auth_context->free)(&negprot_global_auth_context); } conn_close_all(); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a159111319..f809f9ca0c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -87,12 +87,12 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) } if (!make_user_info_guest(&user_info)) { - auth_context->free(&auth_context); + (auth_context->free)(&auth_context); return NT_STATUS_NO_MEMORY; } nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info); - auth_context->free(&auth_context); + (auth_context->free)(&auth_context); free_user_info(&user_info); return nt_status; } @@ -289,7 +289,7 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); if (ntlmssp_auth_context) { - ntlmssp_auth_context->free(&ntlmssp_auth_context); + (ntlmssp_auth_context->free)(&ntlmssp_auth_context); } if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) { @@ -400,7 +400,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, SAFE_FREE(workgroup); SAFE_FREE(machine); - ntlmssp_auth_context->free(&ntlmssp_auth_context); + (ntlmssp_auth_context->free)(&ntlmssp_auth_context); free_user_info(&user_info); @@ -741,7 +741,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, user_info, &server_info); - plaintext_auth_context->free(&plaintext_auth_context); + (plaintext_auth_context->free)(&plaintext_auth_context); } } } -- cgit From 6c7050ea95001c6de6085f93e3d6332ed2c3aa60 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Wed, 9 Jan 2002 08:27:15 +0000 Subject: Add two more memory-debug smbcontrol messages: these ones should prompt dmalloc to log information about what happening, so you can see in flight why smbd is getting bloated. (This used to be commit bcb443c5c4bf97fe6b5b0993e42496c2e64f0124) --- source3/smbd/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b523659dbf..2f831cdd97 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -809,6 +809,7 @@ static void usage(char *pname) exit(1); } register_msg_pool_usage(); + register_dmalloc_msgs(); /* Setup the main smbd so that we can get messages. */ claim_connection(NULL,"",MAXSTATUS,True); -- cgit From 3454945146bdef0108f3a55fb32456cccf15f188 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Jan 2002 00:28:09 +0000 Subject: Getting ready to add UNIX extensions in HEAD also. Jeremy (This used to be commit 6210d4aa196c944e47076e316980f76ac9c6b02d) --- source3/smbd/vfs-wrap.c | 30 ++++++++++++++++++++++++++++++ source3/smbd/vfs.c | 2 ++ 2 files changed, 32 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index eff72c1f10..b2d73561af 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -589,6 +589,36 @@ int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_ return result; } +int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath) +{ + int result; + + START_PROFILE(syscall_link); + +#ifdef VFS_CHECK_NULL + if ((oldpath == NULL) || (newpath == NULL)) + smb_panic("NULL pointer passed to vfswrap_link()\n"); +#endif + result = sys_link(oldpath, newpath); + END_PROFILE(syscall_link); + return result; +} + +int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev) +{ + int result; + + START_PROFILE(syscall_mknod); + +#ifdef VFS_CHECK_NULL + if (pathname == NULL) + smb_panic("NULL pointer passed to vfswrap_mknod()\n"); +#endif + result = sys_mknod(pathname, mode, dev); + END_PROFILE(syscall_mknod); + return result; +} + size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) { size_t result; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index afdfe8c48f..2396a43d48 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -72,6 +72,8 @@ static struct vfs_ops default_vfs_ops = { vfswrap_lock, vfswrap_symlink, vfswrap_readlink, + vfswrap_link, + vfswrap_mknod, vfswrap_fget_nt_acl, vfswrap_get_nt_acl, -- cgit From a36c10bd1e801228a002b2cdbecfe1fb6c3181a2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Jan 2002 02:41:15 +0000 Subject: First part of UNIX extensions (#ifdefed out) more to follow. Jeremy. (This used to be commit 02b18f2cca6d6d046d2d8fd7375b207d44031ddc) --- source3/smbd/negprot.c | 2 +- source3/smbd/trans2.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 170 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index af2f91936e..81f035f3b6 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -242,7 +242,7 @@ static int reply_nt1(char *inbuf, char *outbuf) capabilities |= CAP_EXTENDED_SECURITY; } - capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; + capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX; if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) { capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 73496f406b..3addecb0b8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -305,6 +305,102 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) return strcasecmp(str,mask) == 0; } +#if 0 + +Not finished yet - jra. + +/**************************************************************************** + Return the filetype for UNIX extensions. +****************************************************************************/ + +static uint32 unix_filetype(mode_t mode) +{ + if(S_ISREG(mode)) + return UNIX_TYPE_FILE; + else if(S_ISDIR(mode)) + return UNIX_TYPE_DIR; +#ifdef S_ISLNK + else if(S_ISLNK(mode)) + return UNIX_TYPE_SYMLINK; +#endif +#ifdef S_ISCHR + else if(S_ISCHR(mode)) + return UNIX_TYPE_CHARDEV; +#endif +#ifdef S_ISBLK + else if(S_ISBLK(mode)) + return UNIX_TYPE_BLKDEV; +#endif +#ifdef S_ISFIFO + else if(S_ISFIFO(mode)) + return UNIX_TYPE_FIFO; +#endif +#ifdef S_ISSOCK + else if(S_ISSOCK(mode)) + return UNIX_TYPE_SOCKET; +#endif + + DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode)); + return UNIX_TYPE_UNKNOWN; +} + +/**************************************************************************** + Return the major devicenumber for UNIX extensions. +****************************************************************************/ + +static uint32 unix_dev_major(SMB_DEV_T dev) +{ +#if defined(HAVE_DEVICE_MAJOR_FN) + return (uint32)major(dev); +#else + return (uint32)(dev >> 8); +#endif +} + +/**************************************************************************** + Return the minor devicenumber for UNIX extensions. +****************************************************************************/ + +static uint32 unix_dev_minor(SMB_DEV_T dev) +{ +#if defined(HAVE_DEVICE_MINOR_FN) + return (uint32)minor(dev); +#else + return (uint32)(dev & 0xff); +#endif +} + +/**************************************************************************** + Map standard UNIX permissions onto wire representations. +****************************************************************************/ + +static uint32 unix_perms_to_wire(mode_t perms) +{ + uint ret = 0; + + ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0); + ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0); + ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0); + ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0); + ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0); + ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0); + ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0); + ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0); + ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0); +#ifdef S_ISVTX + ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0); +#endif +#ifdef S_ISGID + ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0); +#endif +#ifdef S_ISUID + ret |= ((perms & S_ISVTX) ? UNIX_SET_UID : 0); +#endif + return ret; +} + +#endif + /**************************************************************************** Get a level dependent lanman2 dir entry. ****************************************************************************/ @@ -406,7 +502,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (vfs_stat(conn,pathreal,&sbuf) != 0) { + if (INFO_LEVEL_IS_UNIX(info_level)) { + if (vfs_lstat(conn,pathreal,&sbuf) != 0) { + DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n", + pathreal,strerror(errno))); + continue; + } + } else if (vfs_stat(conn,pathreal,&sbuf) != 0) { /* Needed to show the msdfs symlinks as directories */ if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) || !is_msdfs_link(conn, pathreal)) { @@ -588,6 +690,72 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p = pdata + len; break; + /* CIFS UNIX Extension. */ + +#if 0 /* JRA - FIXME - NEEDS UNICODE CONVERSION !!! */ + case SMB_FIND_FILE_UNIX: + + len = 108+strlen(fname)+1; /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/ + /* +1 to be sure to transmit the termination of fname */ + len = (len + 3) & ~3; + + SIVAL(p,0,len); p+= 4; /* Offset from this structure to the beginning of the next one */ + SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ + + /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ + SOFF_T(p,0,sbuf.st_size); /* File size 64 Bit */ + p+= 8; + +#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) + SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */ +#else + /* Can't get the value - fake it using size. */ + SOFF_T(p,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */ +#endif + p+= 8; + + put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */ + put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */ + put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */ + p+= 24; + + SIVAL(p,0,sbuf.st_uid); /* user id for the owner */ + SIVAL(p,4,0); + p+= 8; + + SIVAL(p,0,sbuf.st_gid); /* group id of owner */ + SIVAL(p,4,0); + p+= 8; + + SIVAL(p,0,unix_filetype(sbuf.st_mode)); + p+= 4; + + SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */ + SIVAL(p,4,0); + p+= 8; + + SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */ + SIVAL(p,4,0); + p+= 8; + + SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ + p+= 8; + + SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */ + SIVAL(p,4,0); + p+= 8; + + SIVAL(p,0,sbuf.st_nlink); /* number of hard links */ + SIVAL(p,4,0); + p+= 8; + + /* End of SMB_QUERY_FILE_UNIX_BASIC */ + pstrcpy(p,fname); + p=pdata+len; + + break; +#endif + default: return(False); } -- cgit From 5047a66d39fdd56a5895037de8c519a828a03b19 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 11 Jan 2002 05:29:09 +0000 Subject: Back out the crazy notion that the NTLMSSP flags actually mean anything... Replace this with some flags that *we* define. We can do a mapping later if we actually get some more reliable info about what passwords are actually valid. Andrew Bartlett (This used to be commit 7f7a42c3e4d5798ac87ea16a42e4976c3778a76b) --- source3/smbd/sesssetup.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index f809f9ca0c..519817432d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -346,6 +346,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, NTSTATUS nt_status; int sess_vuid; BOOL as_guest; + uint32 auth_flags = AUTH_FLAG_NONE; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; @@ -382,12 +383,22 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, file_save("lmhash1.dat", lmhash.data, lmhash.length); #endif + if (lmhash.length) { + auth_flags |= AUTH_FLAG_LM_RESP; + } + + if (nthash.length == 24) { + auth_flags |= AUTH_FLAG_NTLM_RESP; + } else if (nthash.length > 24) { + auth_flags |= AUTH_FLAG_NTLMv2_RESP; + } + if (!make_user_info_map(&user_info, user, workgroup, machine, lmhash, nthash, plaintext_password, - neg_flags, True)) { + auth_flags, True)) { return ERROR_NT(NT_STATUS_NO_MEMORY); } -- cgit From b322fc3b269de783e2f6bb4b08109ceda89ac932 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 11 Jan 2002 07:48:55 +0000 Subject: Make this error match Win2k. (This used to be commit 490d3aaf20f04d04c91c4748896d7a021581a229) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 49fbee2607..8218ca2dc5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -352,7 +352,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, DEBUG(0,("%s (%s) couldn't find service %s\n", remote_machine, client_addr(), service)); - *status = NT_STATUS_BAD_NETWORK_PATH; + *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } -- cgit From a78fd0468156dd789c57adffd5e64adbabdedcc3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 11 Jan 2002 11:26:31 +0000 Subject: fixed a crash in merge_aces() when we free curr_ace_outer we need to not try to use it again :) (This used to be commit 1c5e19a418136c0ae524e62a4907501212ebac3d) --- source3/smbd/posix_acls.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 765bd0f3b2..889408b631 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -318,6 +318,7 @@ static void merge_aces( canon_ace **pp_list_head ) DLIST_REMOVE(list_head, curr_ace_outer); SAFE_FREE(curr_ace_outer); + break; } } -- cgit From d6823366b881612234ab0655adb11c594f864c4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jan 2002 19:10:25 +0000 Subject: Same fix as went into 2.2 (I'm waiting for jerry to finish some code). Jeremy. (This used to be commit 01ff6ce4963e1daff019f2b936cef218e1c93f67) --- source3/smbd/lanman.c | 16 ++++++------ source3/smbd/negprot.c | 2 +- source3/smbd/process.c | 14 +++++------ source3/smbd/reply.c | 68 +++++++++++++++++++++++++------------------------- source3/smbd/trans2.c | 10 ++++---- 5 files changed, 55 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 64da736ae2..fb8b52342a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1512,7 +1512,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, if (uLevel > 0) { int type; - CVAL(p,13) = 0; + SCVAL(p,13,0); type = STYPE_DISKTREE; if (lp_print_ok(snum)) type = STYPE_PRINTQ; if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC; @@ -1894,16 +1894,16 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch t = LocalTime(&unixdate); SIVAL(p,4,0); /* msecs ? */ - CVAL(p,8) = t->tm_hour; - CVAL(p,9) = t->tm_min; - CVAL(p,10) = t->tm_sec; - CVAL(p,11) = 0; /* hundredths of seconds */ + SCVAL(p,8,t->tm_hour); + SCVAL(p,9,t->tm_min); + SCVAL(p,10,t->tm_sec); + SCVAL(p,11,0); /* hundredths of seconds */ SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */ SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ - CVAL(p,16) = t->tm_mday; - CVAL(p,17) = t->tm_mon + 1; + SCVAL(p,16,t->tm_mday); + SCVAL(p,17,t->tm_mon + 1); SSVAL(p,18,1900+t->tm_year); - CVAL(p,20) = t->tm_wday; + SCVAL(p,20,t->tm_wday); } diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 81f035f3b6..5899f0af52 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -269,7 +269,7 @@ static int reply_nt1(char *inbuf, char *outbuf) set_message(outbuf,17,0,True); - CVAL(outbuf,smb_vwv1) = secword; + SCVAL(outbuf,smb_vwv1,secword); Protocol = PROTOCOL_NT1; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ff53acbd9e..b1fcf864e1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -914,11 +914,11 @@ void construct_reply_common(char *inbuf,char *outbuf) memset(outbuf,'\0',smb_size); set_message(outbuf,0,0,True); - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); + SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf,smb_reh) = 0; + SCVAL(outbuf,smb_rcls,SMB_SUCCESS); + SCVAL(outbuf,smb_reh,0); SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); SSVAL(outbuf,smb_flg2, FLAGS2_UNICODE_STRINGS | FLAGS2_LONG_PATH_COMPONENTS | @@ -949,7 +949,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* maybe its not chained */ if (smb_com2 == 0xFF) { - CVAL(outbuf,smb_vwv0) = 0xFF; + SCVAL(outbuf,smb_vwv0,0xFF); return outsize; } @@ -969,7 +969,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* we need to tell the client where the next part of the reply will be */ SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - CVAL(outbuf,smb_vwv0) = smb_com2; + SCVAL(outbuf,smb_vwv0,smb_com2); /* remember how much the caller added to the chain, only counting stuff after the parameter words */ @@ -991,7 +991,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) memmove(inbuf2,inbuf,smb_wct); /* create the in buffer */ - CVAL(inbuf2,smb_com) = smb_com2; + SCVAL(inbuf2,smb_com,smb_com2); /* create the out buffer */ construct_reply_common(inbuf2, outbuf2); @@ -1006,7 +1006,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* copy the new reply and request headers over the old ones, but preserve the smb_com field */ memmove(orig_outbuf,outbuf2,smb_wct); - CVAL(orig_outbuf,smb_com) = smb_com1; + SCVAL(orig_outbuf,smb_com,smb_com1); /* restore the saved data, being careful not to overwrite any data from the reply header */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c67ce357c6..03d0c18942 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -66,8 +66,8 @@ int reply_special(char *inbuf,char *outbuf) switch (msg_type) { case 0x81: /* session request */ - CVAL(outbuf,0) = 0x82; - CVAL(outbuf,3) = 0; + SCVAL(outbuf,0,0x82); + SCVAL(outbuf,3,0); if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { DEBUG(0,("Invalid name length in session request\n")); @@ -100,7 +100,7 @@ int reply_special(char *inbuf,char *outbuf) if (name_type == 'R') { /* We are being asked for a pathworks session --- no thanks! */ - CVAL(outbuf, 0) = 0x83; + SCVAL(outbuf, 0,0x83); break; } @@ -120,8 +120,8 @@ int reply_special(char *inbuf,char *outbuf) case 0x89: /* session keepalive request (some old clients produce this?) */ - CVAL(outbuf,0) = SMBkeepalive; - CVAL(outbuf,3) = 0; + SCVAL(outbuf,0,SMBkeepalive); + SCVAL(outbuf,3,0); break; case 0x82: /* positive session response */ @@ -651,7 +651,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (strlen(directory) == 0) pstrcpy(directory,"./"); memset((char *)status,'\0',21); - CVAL(status,0) = dirtype; + SCVAL(status,0,dirtype); } else { @@ -735,7 +735,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (numentries == 0 || !ok) { - CVAL(outbuf,smb_rcls) = ERRDOS; + SCVAL(outbuf,smb_rcls,ERRDOS); SSVAL(outbuf,smb_err,ERRnofiles); dptr_close(&dptr_num); } @@ -746,7 +746,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if(ok && expect_close && numentries == 0 && status_len == 0) { - CVAL(outbuf,smb_rcls) = ERRDOS; + SCVAL(outbuf,smb_rcls,ERRDOS); SSVAL(outbuf,smb_err,ERRnofiles); /* Also close the dptr - we know it's gone */ dptr_close(&dptr_num); @@ -758,7 +758,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SSVAL(outbuf,smb_vwv0,numentries); SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); - CVAL(smb_buf(outbuf),0) = 5; + SCVAL(smb_buf(outbuf),0,5); SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); if (Protocol >= PROTOCOL_NT1) { @@ -888,11 +888,11 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(outbuf,smb_vwv6,rmode); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); END_PROFILE(SMBopen); return(outsize); } @@ -988,11 +988,11 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt */ if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } set_message(outbuf,15,0,True); @@ -1103,11 +1103,11 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(outbuf,smb_vwv0,fsp->fnum); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); DEBUG( 2, ( "new file %s\n", fname ) ); DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", @@ -1192,11 +1192,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, outsize = set_message_end(outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); DEBUG( 2, ( "created temp file %s\n", fname ) ); DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", @@ -1624,7 +1624,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize += nread; SSVAL(outbuf,smb_vwv0,nread); SSVAL(outbuf,smb_vwv5,nread+3); - CVAL(smb_buf(outbuf),0) = 1; + SCVAL(smb_buf(outbuf),0,1); SSVAL(smb_buf(outbuf),1,nread); DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", @@ -1742,8 +1742,8 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, } /* force the error type */ - CVAL(inbuf,smb_com) = SMBwritec; - CVAL(outbuf,smb_com) = SMBwritec; + SCVAL(inbuf,smb_com,SMBwritec); + SCVAL(outbuf,smb_com,SMBwritec); if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwritebraw); @@ -1764,7 +1764,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, total_written = nwritten; /* Return a message to the redirector to tell it to send more bytes */ - CVAL(outbuf,smb_com) = SMBwritebraw; + SCVAL(outbuf,smb_com,SMBwritebraw); SSVALS(outbuf,smb_vwv0,-1); outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); if (!send_smb(smbd_server_fd(),outbuf)) @@ -1780,7 +1780,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, /* Set up outbuf to return the correct return */ outsize = set_message(outbuf,1,0,True); - CVAL(outbuf,smb_com) = SMBwritec; + SCVAL(outbuf,smb_com,SMBwritec); SSVAL(outbuf,smb_vwv0,total_written); if (numtowrite != 0) { @@ -1805,7 +1805,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite); if (nwritten < (ssize_t)numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; + SCVAL(outbuf,smb_rcls,ERRHRD); SSVAL(outbuf,smb_err,ERRdiskfull); } @@ -1966,7 +1966,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d SSVAL(outbuf,smb_vwv0,nwritten); if (nwritten < (ssize_t)numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; + SCVAL(outbuf,smb_rcls,ERRHRD); SSVAL(outbuf,smb_err,ERRdiskfull); } @@ -2062,7 +2062,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); if (nwritten < (ssize_t)numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; + SCVAL(outbuf,smb_rcls,ERRHRD); SSVAL(outbuf,smb_err,ERRdiskfull); } @@ -2578,7 +2578,7 @@ int reply_printqueue(connection_struct *conn, SSVAL(outbuf,smb_vwv0,0); SSVAL(outbuf,smb_vwv1,0); - CVAL(smb_buf(outbuf),0) = 1; + SCVAL(smb_buf(outbuf),0,1); SSVAL(smb_buf(outbuf),1,0); DEBUG(3,("printqueue start_index=%d max_count=%d\n", @@ -2601,10 +2601,10 @@ int reply_printqueue(connection_struct *conn, for (i=first;i0?first+count:first-1)); - CVAL(smb_buf(outbuf),0) = 1; + SCVAL(smb_buf(outbuf),0,1); SSVAL(smb_buf(outbuf),1,28*count); } @@ -3557,7 +3557,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } outsize = set_message(outbuf,0,0,True); - CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh); + SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh)); DEBUG(3,("setdir %s\n", newdir)); @@ -4044,7 +4044,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, /* If this fails we need to send an SMBwriteC response, not an SMBwritebmpx - set this up now so we don't forget */ - CVAL(outbuf,smb_com) = SMBwritec; + SCVAL(outbuf,smb_com,SMBwritec); if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) { END_PROFILE(SMBwriteBmpx); @@ -4087,7 +4087,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, /* We are returning successfully, set the message type back to SMBwritebmpx */ - CVAL(outbuf,smb_com) = SMBwriteBmpx; + SCVAL(outbuf,smb_com,SMBwriteBmpx); outsize = set_message(outbuf,1,0,True); @@ -4104,7 +4104,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, /* Now the secondary */ outsize = set_message(outbuf,1,0,True); - CVAL(outbuf,smb_com) = SMBwritec; + SCVAL(outbuf,smb_com,SMBwritec); SSVAL(outbuf,smb_vwv0,nwritten); } @@ -4142,7 +4142,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz data = smb_base(inbuf) + smb_doff; /* We need to send an SMBwriteC response, not an SMBwritebs */ - CVAL(outbuf,smb_com) = SMBwritec; + SCVAL(outbuf,smb_com,SMBwritec); /* This fd should have an auxiliary struct attached, check that it does */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3addecb0b8..60e03e002d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1614,8 +1614,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,size); SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = 0; - CVAL(pdata,21) = (mode&aDIR)?1:0; + SCVAL(pdata,20,0); + SCVAL(pdata,21,(mode&aDIR)?1:0); break; case SMB_FILE_EA_INFORMATION: @@ -1678,8 +1678,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,size); SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = delete_pending; - CVAL(pdata,21) = (mode&aDIR)?1:0; + SCVAL(pdata,20,delete_pending); + SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); pdata += 8; /* index number */ @@ -1728,7 +1728,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_DISPOSITION_INFORMATION: data_size = 1; - CVAL(pdata,0) = delete_pending; + SCVAL(pdata,0,delete_pending); break; case SMB_FILE_POSITION_INFORMATION: -- cgit From 68245b54cd561f362762a057d9b99ca43d0bf958 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 12 Jan 2002 00:50:01 +0000 Subject: Added the O_NOFOLLOW flag if follow symlinks is set off. Jeremy. (This used to be commit 4f1f5f28b514dda86f6f49465bd5887357e37bc6) --- source3/smbd/open.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 72f73deb84..b42c1bacc3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -37,6 +37,12 @@ static int fd_open(struct connection_struct *conn, char *fname, #ifdef O_NONBLOCK flags |= O_NONBLOCK; #endif + +#ifdef O_NOFOLLOW + if (!lp_symlinks(SNUM(conn))) + flags |= O_NOFOLLOW; +#endif + fd = conn->vfs_ops.open(conn,fname,flags,mode); /* Fix for files ending in '.' */ -- cgit From e895b9004e57c62d7517198618f9fd788107629e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 12 Jan 2002 23:57:10 +0000 Subject: Many thanks to Alexander Bokovoy . This work was sponsored by Optifacio Software Services, Inc. Andrew Bartlett (various e-mails announcements merged into some form of commit message below:) This patch which adds basics of universal groups support into Samba 3. Currently, only Winbind with RPC calls supports this, ADS support requires additional (possibly huge) work on KRB5 PAC. However, basic infrastructure is here. This patch adds: 1. Storing of universal groups for particular user logged into Samba software (smbd/ two winbind-pam methods) into netlogon_unigrp.tdb as array of uint32 supplemental group rids keyed as DOMAIN_SID/USER_RID in tdb. 2. Fetching of unversal groups for given user rid and domain sid from netlogon_unigrp.tdb. Since this is used in both smbd and winbindd, main code is in source/lib/netlogon_uingrp.c. Dependencies are added to AUTH_OBJ as UNIGRP_OBJ and WINBINDD_OBJ as UNIGRP_OBJ. This patch has had a few versions, the final version in particular: Many thanks to Andrew Bartlett for critics and comments, and partly rewritten code. New: - updated fetching code to changed byte order macros - moved functions to proper namespace - optimized memory usage by reusing caller's memory context - enhanced code to more follow Samba coding rules Todo: - proper universal group expiration after timeout (This used to be commit 80c2aefbe7c1aa363dd286a47d50c5d8b4595f43) --- source3/smbd/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2f831cdd97..b8e9c2beae 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -884,6 +884,7 @@ static void usage(char *pname) smbd_process(); + uni_group_cache_shutdown(); exit_server("normal exit"); return(0); } -- cgit From 9e007457e4aa0ed8656782be1b8af42fc217614b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 Jan 2002 19:34:28 +0000 Subject: Removed MAXSTATUS which was set incorrectly - thus causing tdb traversal of the connections db on smbd startup. This should fix the Solaris large load bug.... (fingers crossed). Jeremy. (This used to be commit 5b2b9c25af28543e67762805d1387524cbb6c39d) --- source3/smbd/connection.c | 2 +- source3/smbd/server.c | 25 +++++++++---------------- source3/smbd/service.c | 14 ++++---------- 3 files changed, 14 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index c0eaf8187d..da904e0a04 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -37,7 +37,7 @@ TDB_CONTEXT *conn_tdb_ctx(void) Delete a connection record. ****************************************************************************/ -BOOL yield_connection(connection_struct *conn,char *name,int max_connections) +BOOL yield_connection(connection_struct *conn,char *name) { struct connections_key key; TDB_DATA kbuf; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b8e9c2beae..330feece91 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -494,7 +494,7 @@ void exit_server(char *reason) invalidate_all_vuids(); /* delete our entry in the connections database. */ - yield_connection(NULL,"",MAXSTATUS); + yield_connection(NULL,""); respond_to_all_remaining_local_messages(); decrement_smbd_process_count(); @@ -812,7 +812,7 @@ static void usage(char *pname) register_dmalloc_msgs(); /* Setup the main smbd so that we can get messages. */ - claim_connection(NULL,"",MAXSTATUS,True); + claim_connection(NULL,"",0,True); /* DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD @@ -828,21 +828,17 @@ static void usage(char *pname) * everything after this point is run after the fork() */ - if (!locking_init(0)) { + if (!locking_init(0)) exit(1); - } - if (!print_backend_init()) { + if (!print_backend_init()) exit(1); - } - if (!share_info_db_init()) { + if (!share_info_db_init()) exit(1); - } - if(!initialize_password_db(False)) { + if(!initialize_password_db(False)) exit(1); - } /* possibly reload the services file. */ reload_services(True); @@ -868,19 +864,16 @@ static void usage(char *pname) } /* Setup oplocks */ - if (!init_oplocks()) { + if (!init_oplocks()) exit(1); - } /* Setup mangle */ - if (!init_mangle_tdb()) { + if (!init_mangle_tdb()) exit(1); - } /* Setup change notify */ - if (!init_change_notify()) { + if (!init_change_notify()) exit(1); - } smbd_process(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8218ca2dc5..120868f24a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -588,9 +588,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { DEBUG(1,("root preexec gave %d - failing connection\n", ret)); - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); + yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); *status = NT_STATUS_UNSUCCESSFUL; return NULL; @@ -619,7 +617,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); change_to_root_user(); - yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); + yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); *status = NT_STATUS_UNSUCCESSFUL; return NULL; @@ -631,9 +629,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, remote_machine, conn->client_address, conn->connectpath,strerror(errno))); change_to_root_user(); - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); + yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; @@ -713,9 +709,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) } - yield_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn))); + yield_connection(conn, lp_servicename(SNUM(conn))); file_close_conn(conn); dptr_closecnum(conn); -- cgit From 1c639ca28e65f41396925e1c2aa41fe0d60fcc47 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Tue, 15 Jan 2002 02:15:58 +0000 Subject: Convert to the new pstring interface. This diff is a pretty good example of the scope of change the new pstrings would entail: basically inserting PSTR() or FSTR() everywhere you need to coerce one to a char*. It's also a good example of the kind of bug we might catch: on about line 540, we were doing a pstrcpy into an fstring, which might overflow. It's not a problem in this particular case, but it is in general. (This used to be commit 5a403da4a735a8fb8d118a0a67f3a15127152e18) --- source3/smbd/server.c | 55 +++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 330feece91..4f3a46bca1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1,8 +1,8 @@ /* Unix SMB/Netbios implementation. - Version 1.9. Main SMB server routines - Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Martin Pool 2002 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 @@ -19,6 +19,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define PSTRING_SANCTIFY + #include "includes.h" extern fstring global_myworkgroup; @@ -117,7 +119,7 @@ static BOOL open_sockets_inetd(void) close_low_fds(); set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(),user_socket_options); + set_socket_options(smbd_server_fd(), PSTR(user_socket_options)); return True; } @@ -183,7 +185,7 @@ max can be %d\n", /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); + set_socket_options(s,PSTR(user_socket_options)); if (listen(s, 5) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); @@ -205,7 +207,7 @@ max can be %d\n", /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); + set_socket_options(s,PSTR(user_socket_options)); if (listen(s, 5) == -1) { DEBUG(0,("open_sockets: listen: %s\n", @@ -299,7 +301,7 @@ max can be %d\n", am_parent = 0; set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(),user_socket_options); + set_socket_options(smbd_server_fd(),PSTR(user_socket_options)); /* Reset global variables in util.c so that client substitutions will be @@ -356,8 +358,9 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE,fname); + if (file_exist(PSTR(fname), NULL) && + !strcsequal(PSTR(fname), PSTR(dyn_CONFIGFILE))) { + pstrcpy(dyn_CONFIGFILE, PSTR(fname)); test = False; } } @@ -369,7 +372,7 @@ BOOL reload_services(BOOL test) lp_killunused(conn_snum_used); - ret = lp_load(dyn_CONFIGFILE,False,False,True); + ret = lp_load(PSTR(dyn_CONFIGFILE), False, False, True); load_printers(); @@ -384,7 +387,7 @@ BOOL reload_services(BOOL test) { if (smbd_server_fd() != -1) { set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(),user_socket_options); + set_socket_options(smbd_server_fd(), PSTR(user_socket_options)); } } @@ -425,13 +428,14 @@ static BOOL dump_core(void) { char *p; pstring dname; + pstrcpy(dname,lp_logfile()); - if ((p=strrchr_m(dname,'/'))) *p=0; + if ((p=strrchr_m(PSTR(dname),'/'))) *p=0; pstrcat(dname,"/corefiles"); - mkdir(dname,0700); - sys_chown(dname,getuid(),getgid()); - chmod(dname,0700); - if (chdir(dname)) return(False); + mkdir(PSTR(dname),0700); + sys_chown(PSTR(dname),getuid(),getgid()); + chmod(PSTR(dname),0700); + if (chdir(PSTR(dname))) return(False); umask(~(0700)); #ifdef HAVE_GETRLIMIT @@ -449,7 +453,7 @@ static BOOL dump_core(void) #endif - DEBUG(0,("Dumping core in %s\n",dname)); + DEBUG(0,("Dumping core in %s\n", PSTR(dname))); abort(); return(True); } @@ -534,15 +538,15 @@ static void init_structs(void ) * set from the config file. */ - if (!*global_myname) { + if (!*PSTR(global_myname)) { char *p; - fstrcpy( global_myname, myhostname() ); - p = strchr_m( global_myname, '.' ); + pstrcpy( global_myname, myhostname() ); + p = strchr_m(PSTR(global_myname), '.' ); if (p) *p = 0; } - strupper( global_myname ); + strupper(PSTR_MUTABLE(global_myname)); conn_init(); @@ -617,8 +621,8 @@ static void usage(char *pname) case 'l': specified_logfile = True; - slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd", optarg); - lp_set_logfile(logfile); + pstr_sprintf(logfile, "%s/log.smbd", optarg); + lp_set_logfile(PSTR(logfile)); break; case 'a': @@ -680,12 +684,11 @@ static void usage(char *pname) append_log = True; if(!specified_logfile) { - slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd", - dyn_LOGFILEBASE); - lp_set_logfile(logfile); + pstr_sprintf(logfile, "%s/log.smbd", PSTR(dyn_LOGFILEBASE)); + lp_set_logfile(PSTR(logfile)); } - pstrcpy(remote_machine, "smbd"); + fstrcpy(remote_machine, "smbd"); setup_logging(argv[0],interactive); -- cgit From 3fee2ac712c5fe7a85b89ba3a3c19ab8801f0b22 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Wed, 16 Jan 2002 02:20:34 +0000 Subject: Roll back PSTR insertion. Just leave the fstrcpy/pstrcpy bugfix, and conversion to pstr_sprintf rather than manual calculation of length. (This used to be commit e38e7a2bdcf2901359035ac4aa79ebf33599e0c8) --- source3/smbd/server.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4f3a46bca1..08b9a63dd5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -19,8 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define PSTRING_SANCTIFY - #include "includes.h" extern fstring global_myworkgroup; @@ -119,7 +117,7 @@ static BOOL open_sockets_inetd(void) close_low_fds(); set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), PSTR(user_socket_options)); + set_socket_options(smbd_server_fd(), user_socket_options); return True; } @@ -185,7 +183,7 @@ max can be %d\n", /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,PSTR(user_socket_options)); + set_socket_options(s,user_socket_options); if (listen(s, 5) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); @@ -207,7 +205,7 @@ max can be %d\n", /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,PSTR(user_socket_options)); + set_socket_options(s,user_socket_options); if (listen(s, 5) == -1) { DEBUG(0,("open_sockets: listen: %s\n", @@ -301,7 +299,7 @@ max can be %d\n", am_parent = 0; set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(),PSTR(user_socket_options)); + set_socket_options(smbd_server_fd(),user_socket_options); /* Reset global variables in util.c so that client substitutions will be @@ -358,9 +356,9 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); - if (file_exist(PSTR(fname), NULL) && - !strcsequal(PSTR(fname), PSTR(dyn_CONFIGFILE))) { - pstrcpy(dyn_CONFIGFILE, PSTR(fname)); + if (file_exist(fname, NULL) && + !strcsequal(fname, dyn_CONFIGFILE)) { + pstrcpy(dyn_CONFIGFILE, fname); test = False; } } @@ -372,7 +370,7 @@ BOOL reload_services(BOOL test) lp_killunused(conn_snum_used); - ret = lp_load(PSTR(dyn_CONFIGFILE), False, False, True); + ret = lp_load(dyn_CONFIGFILE, False, False, True); load_printers(); @@ -387,7 +385,7 @@ BOOL reload_services(BOOL test) { if (smbd_server_fd() != -1) { set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), PSTR(user_socket_options)); + set_socket_options(smbd_server_fd(), user_socket_options); } } @@ -430,12 +428,12 @@ static BOOL dump_core(void) pstring dname; pstrcpy(dname,lp_logfile()); - if ((p=strrchr_m(PSTR(dname),'/'))) *p=0; + if ((p=strrchr_m(dname,'/'))) *p=0; pstrcat(dname,"/corefiles"); - mkdir(PSTR(dname),0700); - sys_chown(PSTR(dname),getuid(),getgid()); - chmod(PSTR(dname),0700); - if (chdir(PSTR(dname))) return(False); + mkdir(dname,0700); + sys_chown(dname,getuid(),getgid()); + chmod(dname,0700); + if (chdir(dname)) return(False); umask(~(0700)); #ifdef HAVE_GETRLIMIT @@ -453,7 +451,7 @@ static BOOL dump_core(void) #endif - DEBUG(0,("Dumping core in %s\n", PSTR(dname))); + DEBUG(0,("Dumping core in %s\n", dname)); abort(); return(True); } @@ -538,15 +536,15 @@ static void init_structs(void ) * set from the config file. */ - if (!*PSTR(global_myname)) { + if (!*global_myname) { char *p; pstrcpy( global_myname, myhostname() ); - p = strchr_m(PSTR(global_myname), '.' ); + p = strchr_m(global_myname, '.' ); if (p) *p = 0; } - strupper(PSTR_MUTABLE(global_myname)); + strupper(global_myname); conn_init(); @@ -622,7 +620,7 @@ static void usage(char *pname) case 'l': specified_logfile = True; pstr_sprintf(logfile, "%s/log.smbd", optarg); - lp_set_logfile(PSTR(logfile)); + lp_set_logfile(logfile); break; case 'a': @@ -684,8 +682,8 @@ static void usage(char *pname) append_log = True; if(!specified_logfile) { - pstr_sprintf(logfile, "%s/log.smbd", PSTR(dyn_LOGFILEBASE)); - lp_set_logfile(PSTR(logfile)); + pstr_sprintf(logfile, "%s/log.smbd", dyn_LOGFILEBASE); + lp_set_logfile(logfile); } fstrcpy(remote_machine, "smbd"); -- cgit From fed604bfa368a2bb1fed414e368d491e4c7d7005 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Wed, 16 Jan 2002 02:42:07 +0000 Subject: Roll back PSTRING_SANCTIFY patch; just leave non-controversial type and constness changes. (This used to be commit cee0ec72746122c962e6c5278a736266a7f2c424) --- source3/smbd/service.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 120868f24a..9b6f38f2ec 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -104,17 +104,19 @@ int add_home_service(const char *service, const char *homedir) if ((usr_p = strchr_m(service,*lp_winbind_separator())) != NULL) fstrcpy(new_service, usr_p+1); - lp_add_home(new_service,iHomeService,homedir); + lp_add_home(new_service, iHomeService, homedir); iService = lp_servicenumber(new_service); return iService; } -/**************************************************************************** - Find a service entry. service is always in dos codepage. -****************************************************************************/ -int find_service(char *service) +/** + * Find a service entry. service is always in dos codepage. + * + * @param service is modified (to canonical form??) + **/ +int find_service(fstring service) { int iService; @@ -158,7 +160,7 @@ int find_service(char *service) { DEBUG(3,("%s is a valid printer name\n", service)); DEBUG(3,("adding %s as a printer service\n", service)); - lp_add_printer(service,iPrinterService); + lp_add_printer(service, iPrinterService); iService = lp_servicenumber(service); if (iService < 0) DEBUG(0,("failed to add %s as a printer service!\n", service)); @@ -192,8 +194,8 @@ int find_service(char *service) iService = find_service(defservice); if (iService >= 0) { - all_string_sub(service,"_","/",0); - iService = lp_add_service(service,iService); + all_string_sub(service, "_","/",0); + iService = lp_add_service(service, iService); } } } @@ -201,7 +203,7 @@ int find_service(char *service) if (iService >= 0) if (!VALID_SNUM(iService)) { - DEBUG(0,("Invalid snum %d for %s\n",iService,service)); + DEBUG(0,("Invalid snum %d for %s\n",iService, service)); iService = -1; } @@ -216,7 +218,7 @@ int find_service(char *service) do some basic sainity checks on the share. This function modifies dev, ecode. ****************************************************************************/ -static NTSTATUS share_sanity_checks(int snum, char* service, char *dev) +static NTSTATUS share_sanity_checks(int snum, char* service, pstring dev) { if (!lp_snum_ok(snum) || @@ -229,7 +231,7 @@ static NTSTATUS share_sanity_checks(int snum, char* service, char *dev) if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) pstrcpy(dev,"IPC"); - if (*dev == '?' || !*dev) { + if (dev[0] == '?' || !dev[0]) { if (lp_print_ok(snum)) { pstrcpy(dev,"LPT1:"); } else { @@ -318,10 +320,12 @@ static void set_admin_user(connection_struct *conn) /**************************************************************************** Make a connection to a service. + * + * @param service (May be modified to canonical form???) ****************************************************************************/ connection_struct *make_connection(char *service, DATA_BLOB password, - char *dev,uint16 vuid, NTSTATUS *status) + const char *dev, uint16 vuid, NTSTATUS *status) { int snum; struct passwd *pass = NULL; @@ -361,16 +365,19 @@ connection_struct *make_connection(char *service, DATA_BLOB password, if (validated_username(vuid)) { fstring unix_username; fstrcpy(unix_username,validated_username(vuid)); - return(make_connection(unix_username,password,dev,vuid,status)); + return make_connection(unix_username, + password,dev,vuid,status); } } else { /* Security = share. Try with current_user_info.smb_name * as the username. */ - if(*current_user_info.smb_name) { + if (* current_user_info.smb_name) { fstring unix_username; - fstrcpy(unix_username,current_user_info.smb_name); + fstrcpy(unix_username, + current_user_info.smb_name); map_username(unix_username); - return(make_connection(unix_username,password,dev,vuid,status)); + return make_connection(unix_username, + password,dev,vuid,status); } } } -- cgit From 04ec469c72c6a220108312cdec3d30081cfe938a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Jan 2002 21:27:57 +0000 Subject: Fixup error mapping so we have only one table containing errno -> dos error -> NT STATUS maps. Fixes problem with disk full returning incorrect error. Jeremy. (This used to be commit 16fcbf3c1ccf1d704765653f68395dd596c0d841) --- source3/smbd/error.c | 52 ++++++++++++++-------------------------------------- 1 file changed, 14 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 3c829deb09..fc26aa4ded 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -25,6 +25,9 @@ int unix_ERR_class=SMB_SUCCESS; int unix_ERR_code=0; +/* From lib/error.c */ +extern struct unix_error_map unix_dos_nt_errmap[]; + /**************************************************************************** Create an error packet from a cached error. ****************************************************************************/ @@ -42,45 +45,16 @@ int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file return error_packet(outbuf,NT_STATUS_OK,eclass,err,line,file); } -struct -{ - int unixerror; - int smbclass; - int smbcode; -} unix_smb_errmap[] = -{ - {EPERM,ERRDOS,ERRnoaccess}, - {EACCES,ERRDOS,ERRnoaccess}, - {ENOENT,ERRDOS,ERRbadfile}, - {ENOTDIR,ERRDOS,ERRbadpath}, - {EIO,ERRHRD,ERRgeneral}, - {EBADF,ERRSRV,ERRsrverror}, - {EINVAL,ERRSRV,ERRsrverror}, - {EEXIST,ERRDOS,ERRfilexists}, - {ENFILE,ERRDOS,ERRnofids}, - {EMFILE,ERRDOS,ERRnofids}, - {ENOSPC,ERRHRD,ERRdiskfull}, -#ifdef EDQUOT - {EDQUOT,ERRHRD,ERRdiskfull}, -#endif -#ifdef ENOTEMPTY - {ENOTEMPTY,ERRDOS,ERRnoaccess}, -#endif -#ifdef EXDEV - {EXDEV,ERRDOS,ERRdiffdevice}, -#endif - {EROFS,ERRHRD,ERRnowrite}, - {0,0,0} -}; - /**************************************************************************** - create an error packet from errno + Create an error packet from errno. ****************************************************************************/ + int unix_error_packet(char *outbuf,int def_class,uint32 def_code, int line, const char *file) { int eclass=def_class; int ecode=def_code; + NTSTATUS ntstatus = NT_STATUS_OK; int i=0; if (unix_ERR_class != SMB_SUCCESS) { @@ -89,23 +63,25 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, unix_ERR_class = SMB_SUCCESS; unix_ERR_code = 0; } else { - while (unix_smb_errmap[i].smbclass != 0) { - if (unix_smb_errmap[i].unixerror == errno) { - eclass = unix_smb_errmap[i].smbclass; - ecode = unix_smb_errmap[i].smbcode; + while (unix_dos_nt_errmap[i].dos_class != 0) { + if (unix_dos_nt_errmap[i].unix_error == errno) { + eclass = unix_dos_nt_errmap[i].dos_class; + ecode = unix_dos_nt_errmap[i].dos_code; + ntstatus = unix_dos_nt_errmap[i].nt_error; break; } i++; } } - return error_packet(outbuf,NT_STATUS_OK,eclass,ecode,line,file); + return error_packet(outbuf,ntstatus,eclass,ecode,line,file); } /**************************************************************************** - create an error packet. Normally called using the ERROR() macro + Create an error packet. Normally called using the ERROR() macro. ****************************************************************************/ + int error_packet(char *outbuf,NTSTATUS ntstatus, uint8 eclass,uint32 ecode,int line, const char *file) { -- cgit From 08019e8a337c5e378ec9dfc70698adb73b9b7676 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Jan 2002 23:53:10 +0000 Subject: Separate out get_user_home_dir() from get_user_home_service_dir(). Jeremy. (This used to be commit c1b97226db63daf64359e79083a4754e7c7f8054) --- source3/smbd/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9b6f38f2ec..b25e696c8d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -127,7 +127,7 @@ int find_service(fstring service) /* now handle the special case of a home directory */ if (iService < 0) { - char *phome_dir = get_user_home_dir(service); + char *phome_dir = get_user_service_home_dir(service); if(!phome_dir) { @@ -136,7 +136,7 @@ int find_service(fstring service) * be a Windows to unix mapped user name. */ if(map_username(service)) - phome_dir = get_user_home_dir(service); + phome_dir = get_user_service_home_dir(service); } DEBUG(3,("checking for home directory %s gave %s\n",service, -- cgit From 630e0ae8ef14e8ec75ea4d38f88453084780bf56 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 17 Jan 2002 00:25:13 +0000 Subject: don't use O_NONBLOCK in open(). This was added erroneously for kernel oplocks and really shouldn't be used (This used to be commit c3a83002cfc2e0b5158cae1898eda8bafcb41e48) --- source3/smbd/open.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b42c1bacc3..589f1a32b4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -34,10 +34,6 @@ static int fd_open(struct connection_struct *conn, char *fname, int flags, mode_t mode) { int fd; -#ifdef O_NONBLOCK - flags |= O_NONBLOCK; -#endif - #ifdef O_NOFOLLOW if (!lp_symlinks(SNUM(conn))) flags |= O_NOFOLLOW; -- cgit From c311d24ce32d2a8aa244f126bcec67ec03549727 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 17 Jan 2002 08:45:58 +0000 Subject: A nice *big* change to the fundemental way we do things. Samba (ab)uses the returns from getpwnam() a lot - in particular it keeps them around for a long time - often past the next call... This adds a getpwnam_alloc and a getpwuid_alloc to the collection. These function as expected, returning a malloced structure that can be free()ed with passwd_free(&passwd). This patch also cuts down on the number of calls to getpwnam - mostly by taking advantage of the fact that the passdb interface is already case-insensiteve. With this patch most of the recursive cases have been removed (that I know of) and the problems are reduced further by not using the sys_ interface in the new code. This means that pointers to the cache won't be affected. (This is a tempoary HACK, I intend to kill the password cache entirly). The only change I'm a little worried about is the change to rpc_server/srv_samr_nt.c for private groups. In this case we are getting groups from the new group mapping DB. Do we still need to check for private groups? I've toned down the check to a case sensitve match with the new code, but we might be able to kill it entirly. I've also added a make_modifyable_passwd() function, that copies a passwd struct into the form that the old sys_getpw* code provided. As far as I can tell this is only actually used in the pass_check.c crazies, where I moved the final 'special case' for shadow passwords (out of _Get_Pwnam()). The matching case for getpwent() is dealt with already, in lib/util_getent.c Also included in here is a small change to register the [homes] share at vuid creation rather than just in one varient of the session setup. (This picks up the SPNEGO cases). The home directory is now stored on the vuid, and I am hoping this might provide a saner way to do %H substitions. TODO: Kill off remaining Get_Pwnam_Modify calls (they are not needed), change the remaining sys_getpwnam() callers to use getpwnam_alloc() and move Get_Pwnam to return an allocated struct. Andrew Bartlett (This used to be commit 1d86c7f94230bc53daebd4d2cd829da6292e05da) --- source3/smbd/chgpasswd.c | 7 +++++-- source3/smbd/password.c | 16 ++++++++++++++++ source3/smbd/sesssetup.c | 7 ------- source3/smbd/uid.c | 13 ++++--------- 4 files changed, 25 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 741f5ef0aa..b22ccacbf1 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -732,6 +732,7 @@ BOOL pass_oem_change(char *user, uchar * ntdata, uchar * nthash) { fstring new_passwd; + const char *unix_user; SAM_ACCOUNT *sampass = NULL; BOOL ret = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); @@ -745,8 +746,10 @@ BOOL pass_oem_change(char *user, * available. JRA. */ - if ((ret) && lp_unix_password_sync()) - ret = chgpasswd(user, "", new_passwd, True); + unix_user = pdb_get_username(sampass); + + if ((ret) && (unix_user) && (*unix_user) && lp_unix_password_sync()) + ret = chgpasswd(unix_user, "", new_passwd, True); if (ret) ret = change_oem_password(sampass, new_passwd); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a9d80d36fd..3e942e6f99 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -64,6 +64,8 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; + SAFE_FREE(vuser->homedir); + session_yield(vuser); DLIST_REMOVE(validated_users, vuser); @@ -255,6 +257,14 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); + { + /* Keep the homedir handy */ + const char *homedir = pdb_get_homedir(server_info->sam_account); + if (homedir) { + vuser->homedir = smb_xstrdup(homedir); + } + } + DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->uid, (unsigned int)vuser->gid, @@ -289,6 +299,12 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) return -1; } + /* Register a home dir service for this user */ + if ((!vuser->guest) && vuser->homedir && *(vuser->homedir) + && (lp_servicenumber(vuser->user.unix_name) < 0)) { + add_home_service(vuser->user.unix_name, vuser->homedir); + } + return vuser->vuid; } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 519817432d..0e5830fc24 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -782,13 +782,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (server_info->guest) { SSVAL(outbuf,smb_vwv2,1); - } else { - const char *home_dir = pdb_get_homedir(server_info->sam_account); - const char *username = pdb_get_username(server_info->sam_account); - if ((home_dir && *home_dir) - && (lp_servicenumber(username) < 0)) { - add_home_service(username, home_dir); - } } /* register the name and uid as being validated, so further connections diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 650d9270cb..8df08a0e72 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -31,26 +31,21 @@ extern struct current_user current_user; BOOL change_to_guest(void) { static struct passwd *pass=NULL; - static uid_t guest_uid = (uid_t)-1; - static gid_t guest_gid = (gid_t)-1; - static fstring guest_name; if (!pass) { - pass = sys_getpwnam(lp_guestaccount()); + /* Don't need to free() this as its stored in a static */ + pass = getpwnam_alloc(lp_guestaccount()); if (!pass) return(False); - guest_uid = pass->pw_uid; - guest_gid = pass->pw_gid; - fstrcpy(guest_name, pass->pw_name); } #ifdef AIX /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before setting IDs */ - initgroups(guest_name, guest_gid); + initgroups(pass->pw_name, pass->pw_gid); #endif - set_sec_ctx(guest_uid, guest_gid, 0, NULL, NULL); + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; -- cgit From efdb29d0e0f7737dcf21045bc560a1b9378886b4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Jan 2002 03:26:53 +0000 Subject: Ensure (C) message is output on startup. Jeremy. (This used to be commit 7d05175494227bf30d098e04ec91c4f0a7b7184c) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 08b9a63dd5..492632e7ac 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -729,8 +729,8 @@ static void usage(char *pname) reopen_logs(); - DEBUG(1,( "smbd version %s started.\n", VERSION)); - DEBUGADD(1,( "Copyright Andrew Tridgell 1992-2002\n")); + DEBUG(0,( "smbd version %s started.\n", VERSION)); + DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2002\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); -- cgit From e400bfce39dac2f4ff75184d52965aba6b9848de Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Jan 2002 21:29:20 +0000 Subject: Report write fail in smb_dump. Jeremy. (This used to be commit 832b9e7838afc0a48932dd0622c7e2f7b7e44a8f) --- source3/smbd/process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b1fcf864e1..48c0053360 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -609,7 +609,9 @@ static void smb_dump(char *name, int type, char *data, ssize_t len) if (fd != -1 || errno != EEXIST) break; } if (fd != -1) { - write(fd, data, len); + ssize_t ret = write(fd, data, len); + if (ret != len) + DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret )); close(fd); DEBUG(0,("created %s len %d\n", fname, len)); } -- cgit From 427896866af5a0047482ce7a0e8e3b69e9063fb2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 20 Jan 2002 00:04:15 +0000 Subject: Attempt to fix bugs in write cache code (yes I know it's going away :-). Jeremy. (This used to be commit ccda82b457b11ec683f404c9059b02c1214a0fd1) --- source3/smbd/fileio.c | 22 +++++++++++++++++++--- source3/smbd/vfs.c | 2 ++ 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 38da96b741..84b8e35bf0 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -419,7 +419,7 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne if ( n <= wcp->alloc_size && n > wcp->data_size) { cache_flush_needed = True; } else { - DO_PROFILE_INC(writecache_direct_writes); + DO_PROFILE_INC(writecache_direct_writes); return real_write_file(fsp, data, pos, n); } @@ -552,7 +552,13 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) { if(fsp->wcp) { - flush_write_cache(fsp, SIZECHANGE_FLUSH); + /* The cache *must* have been flushed before we do this. */ + if (fsp->wcp->data_size != 0) { + pstring msg; + slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \ +on file %s with write cache size = %u\n", fsp->fsp_name, fsp->wcp->data_size ); + smb_panic(msg); + } fsp->wcp->file_size = file_size; } } @@ -565,6 +571,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) { write_cache *wcp = fsp->wcp; size_t data_size; + ssize_t ret; if(!wcp || !wcp->data_size) return 0; @@ -582,7 +589,16 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) DO_PROFILE_INC(writecache_num_perfect_writes); #endif - return real_write_file(fsp, wcp->data, wcp->offset, data_size); + ret = real_write_file(fsp, wcp->data, wcp->offset, data_size); + + /* + * Ensure file size if kept up to date if write extends file. + */ + + if ((ret != -1) && (wcp->offset + ret >= wcp->file_size)) + wcp->file_size = wcp->offset + ret; + + return ret; } /******************************************************************* diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2396a43d48..e05b217a14 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -351,6 +351,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n", fsp->fsp_name, (double)st.st_size )); + flush_write_cache(fsp, SIZECHANGE_FLUSH); if ((ret = vfs_ops->ftruncate(fsp, fsp->fd, len)) != -1) { set_filelen_write_cache(fsp, len); } @@ -389,6 +390,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); + flush_write_cache(fsp, SIZECHANGE_FLUSH); if ((ret = fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, len)) != -1) set_filelen_write_cache(fsp, len); -- cgit From 2590721a36b2d6efd3b822312e9545548cfc96ca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 20 Jan 2002 00:43:28 +0000 Subject: Fix file size calculations for write cache code. Jeremy. (This used to be commit 71d647b6c0db8470d6144683c41ab26a7e1ef35e) --- source3/smbd/fileio.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 84b8e35bf0..6e1f5cfcf6 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -270,6 +270,13 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if(pos + data_used > wcp->offset + wcp->data_size) wcp->data_size = pos + data_used - wcp->offset; + /* + * Update the file size if changed. + */ + + if (wcp->offset + wcp->data_size > wcp->file_size) + wcp->file_size = wcp->offset + wcp->data_size; + /* * If we used all the data then * return here. @@ -312,6 +319,13 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if(pos + n > wcp->offset + wcp->data_size) wcp->data_size = pos + n - wcp->offset; + /* + * Update the file size if changed. + */ + + if (wcp->offset + wcp->data_size > wcp->file_size) + wcp->file_size = wcp->offset + wcp->data_size; + /* * We don't need to move the start of data, but we * cut down the amount left by the amount used. @@ -363,10 +377,11 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", wcp->data_size = pos + data_used - wcp->offset; /* - * Update the known file length. + * Update the file size if changed. */ - wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) + wcp->file_size = wcp->offset + wcp->data_size; /* * If we used all the data then @@ -419,8 +434,16 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne if ( n <= wcp->alloc_size && n > wcp->data_size) { cache_flush_needed = True; } else { + ssize_t ret = real_write_file(fsp, data, pos, n); + DO_PROFILE_INC(writecache_direct_writes); - return real_write_file(fsp, data, pos, n); + if (ret == -1) + return ret; + + if (pos + ret > wcp->file_size) + wcp->file_size = pos + ret; + + return ret; } write_path = 4; @@ -446,8 +469,13 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", */ if (n > wcp->alloc_size ) { - if(real_write_file(fsp, data, pos, n) == -1) + ssize_t ret = real_write_file(fsp, data, pos, n); + if (ret == -1) return -1; + + if (pos + ret > wcp->file_size) + wcp->file_size = pos + n; + DO_PROFILE_INC(writecache_direct_writes); return total_written + n; } @@ -470,7 +498,15 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", DO_PROFILE_INC(writecache_num_write_caches); } wcp->data_size += n; + + /* + * Update the file size if changed. + */ + + if (wcp->offset + wcp->data_size > wcp->file_size) + wcp->file_size = wcp->offset + wcp->data_size; DEBUG(9,("cache return %u\n", (unsigned int)n)); + total_written += n; return total_written; /* .... that's a write :) */ } @@ -595,7 +631,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) * Ensure file size if kept up to date if write extends file. */ - if ((ret != -1) && (wcp->offset + ret >= wcp->file_size)) + if ((ret != -1) && (wcp->offset + ret > wcp->file_size)) wcp->file_size = wcp->offset + ret; return ret; -- cgit From a6541401b03e0a97dc7e265b223289cad7160b75 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 20 Jan 2002 01:01:46 +0000 Subject: Ensure identical between 2.2.3 and 3.0 - no need for difference here.. Jeremy. (This used to be commit 7c5c035e417b45acebc3580c4fdc80a7ef3306ce) --- source3/smbd/fileio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 6e1f5cfcf6..9f7cb5f340 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -130,7 +130,6 @@ tryagain: if (readret == -1) return -1; #endif - if (readret > 0) ret += readret; } -- cgit From 93a8358910d2b8788ffea33c04244ffd5ffecabf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jan 2002 01:24:59 +0000 Subject: This patch makes the 'winbind use default domain' code interact better with smbd, and also makes it much cleaner inside winbindd. It is mostly my code, with a few changes and testing performed by Alexander Bokovoy . ab has tested it in security=domain and security=ads, but more testing is always appricatiated. The idea is that we no longer cart around a 'domain\user' string, we keep them seperate until the last moment - when we push that string into a pwent on onto the socket. This removes the need to be constantly parsing that string - the domain prefix is almost always already provided, (only a couple of functions actually changed arguments in all this). Some consequential changes to the RPC client code, to stop it concatonating the two strings (it now passes them both back as params). I havn't changed the cache code, however the usernames will no longer have a double domain prefix in the key string. The actual structures are unchanged - but the meaning of 'username' in the 'rid' will have changed. (The cache is invalidated at startup, so on-disk formats are not an issue here). Andrew Bartlett (This used to be commit e870f0e727952aeb8599cf93ad2650ae56eca033) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8df08a0e72..d9cedaf7b5 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -453,7 +453,7 @@ BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) /* If we are looking up a domain user, make sure it is for the local machine only */ - if (strchr_m(name, sep[0]) || strchr_m(name, '\\')) { + if (strchr_m(name, sep[0]) || strchr_m(name, '\\') || lp_winbind_use_default_domain()) { fstring domain, username; split_domain_name(name, domain, username); -- cgit From bb6af711b8f9a525b74198abbe7f1c37014ca6f7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jan 2002 02:40:05 +0000 Subject: This is the current patch from Luke Leighton to add a degree of seperation betwen reading/writing the raw NamedPipe SMB packets and the matching operations inside smbd's RPC components. This patch is designed for no change in behaviour, and my tests hold that to be true. This patch does however allow for the future loadable modules interface to specify function pointers in replacement of the fixed state. The pipes_struct has been split into two peices, with smb_np_struct taking the information that should be generic to where the data ends up. Some other minor changes are made: we get another small helper function in util_sock.c and some of the original code has better failure debugs and variable use. (As per on-list comments). Andrew Bartlett (This used to be commit 8ef13cabdddf58b741886782297fb64b2fb7e489) --- source3/smbd/ipc.c | 14 ++++++++------ source3/smbd/nttrans.c | 2 +- source3/smbd/pipes.c | 16 +++++++++------- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 4047ffa8d7..f84f3048e9 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -163,8 +163,9 @@ void send_trans_reply(char *outbuf, Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) +static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p) { + BOOL is_data_outstanding; char *rdata = malloc(p->max_trans_reply); int data_len; @@ -173,12 +174,13 @@ static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) return False; } - if((data_len = read_from_pipe( p, rdata, p->max_trans_reply)) < 0) { + if((data_len = read_from_pipe( p, rdata, p->max_trans_reply, + &is_data_outstanding)) < 0) { SAFE_FREE(rdata); return False; } - send_trans_reply(outbuf, NULL, 0, rdata, data_len, p->out_data.current_pdu_len > data_len); + send_trans_reply(outbuf, NULL, 0, rdata, data_len, is_data_outstanding); SAFE_FREE(rdata); return True; @@ -188,7 +190,7 @@ static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p) WaitNamedPipeHandleState ****************************************************************************/ -static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len) +static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len) { uint16 priority; @@ -211,7 +213,7 @@ static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len) SetNamedPipeHandleState ****************************************************************************/ -static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param, int param_len) +static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len) { uint16 id; @@ -259,7 +261,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { BOOL reply = False; - pipes_struct *p = NULL; + smb_np_struct *p = NULL; int pnum; int subcommand; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 464790d158..6e03d485d2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -466,7 +466,7 @@ to open_mode 0x%x\n", (unsigned long)desired_access, (unsigned long)share_access static int nt_open_pipe(char *fname, connection_struct *conn, char *inbuf, char *outbuf, int *ppnum) { - pipes_struct *p = NULL; + smb_np_struct *p = NULL; uint16 vuid = SVAL(inbuf, smb_uid); int i; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index cd8a56a5d2..8f6f6f39c4 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -45,7 +45,7 @@ int reply_open_pipe_and_X(connection_struct *conn, pstring fname; pstring pipe_name; uint16 vuid = SVAL(inbuf, smb_uid); - pipes_struct *p; + smb_np_struct *p; int smb_ofun = SVAL(inbuf,smb_vwv8); int size=0,fmode=0,mtime=0,rmode=0; int i; @@ -116,7 +116,7 @@ int reply_open_pipe_and_X(connection_struct *conn, ****************************************************************************/ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) { - pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); + smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); size_t numtowrite = SVAL(inbuf,smb_vwv1); int nwritten; int outsize; @@ -154,7 +154,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); + smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); size_t numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); @@ -210,11 +210,13 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) ****************************************************************************/ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); + smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); int nread = -1; char *data; + BOOL unused; + /* we don't use the offset given to use for pipe reads. This is deliberate, instead we always return the next lump of data on the pipe */ @@ -228,7 +230,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) set_message(outbuf,12,0,True); data = smb_buf(outbuf); - nread = read_from_pipe(p, data, smb_maxcnt); + nread = read_from_pipe(p, data, smb_maxcnt, &unused); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -248,7 +250,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) ****************************************************************************/ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) { - pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); + smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); int outsize = set_message(outbuf,0,0,True); if (!p) @@ -256,7 +258,7 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum)); - if (!close_rpc_pipe_hnd(p, conn)) + if (!close_rpc_pipe_hnd(p)) return ERROR_DOS(ERRDOS,ERRbadfid); return(outsize); -- cgit From f46db61068573779b56f8580c075ee143c3860d5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jan 2002 09:00:32 +0000 Subject: Kill off the old varient of 'check_plaintext_password' (new version just committed in auth/auth_compat.c and use the new version to make the plaintext password change slightly sane... (Needs testing). Andrew Bartlett (This used to be commit 996d0cd89cf9da5e9749f136f013cc4a8b977ee0) --- source3/smbd/chgpasswd.c | 48 ---------------------------- source3/smbd/lanman.c | 83 ++++++++++++++++-------------------------------- 2 files changed, 28 insertions(+), 103 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index b22ccacbf1..5e646b6225 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -934,53 +934,5 @@ BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd) return ret; } -/*********************************************************** - Code to check a plaintext password against smbpasswd entries. -***********************************************************/ - -BOOL check_plaintext_password(char *user, char *old_passwd, - int old_passwd_size, SAM_ACCOUNT **hnd) -{ - SAM_ACCOUNT *sampass = NULL; - uchar old_pw[16], old_ntpw[16]; - BOOL ret; - - pdb_init_sam(&sampass); - - become_root(); - ret = pdb_getsampwnam(sampass, user); - unbecome_root(); - - *hnd = sampass; - - if (ret == False) - { - DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); - return False; - } - - if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) - { - DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); - return (False); - } - nt_lm_owf_gen(old_passwd, old_ntpw, old_pw); -#ifdef DEBUG_PASSWORD - DEBUG(100, ("check_plaintext_password: nt_passwd \n")); - dump_data(100, pdb_get_nt_passwd(sampass), 16); - DEBUG(100, ("check_plaintext_password: old_ntpw \n")); - dump_data(100, old_ntpw, 16); - DEBUG(100, ("check_plaintext_password: lanman_passwd \n")); - dump_data(100, pdb_get_lanman_passwd(sampass), 16); - DEBUG(100, ("check_plaintext_password: old_pw\n")); - dump_data(100, old_pw, 16); -#endif - - if (memcmp(pdb_get_nt_passwd(sampass), old_ntpw, 16) - && memcmp(pdb_get_lanman_passwd(sampass), old_pw, 16)) - return (False); - else - return (True); -} diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fb8b52342a..1a5777e1d4 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1923,8 +1923,6 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param fstring user; fstring pass1,pass2; - struct passwd *passwd; - pull_ascii_fstring(user,p); p = skip_string(p,1); @@ -1944,68 +1942,43 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param DEBUG(3,("Set password for <%s>\n",user)); - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(user); - - /* - * Do any UNIX username case mangling. - */ - passwd = Get_Pwnam_Modify( user ); - /* * Attempt to verify the old password against smbpasswd entries * Win98 clients send old and new password in plaintext for this call. */ { - fstring saved_pass2; - SAM_ACCOUNT *sampass=NULL; - - /* - * Save the new password as change_oem_password overwrites it - * with zeros. - */ - - fstrcpy(saved_pass2, pass2); - - if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) && - change_oem_password(sampass,pass2)) - { - SSVAL(*rparam,0,NERR_Success); - - /* - * If unix password sync was requested, attempt to change - * the /etc/passwd database also. Return failure if this cannot - * be done. - */ - - if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) - SSVAL(*rparam,0,NERR_badpass); - } - pdb_free_sam(&sampass); - } - - - /* - * If the above failed, attempt the plaintext password change. - * This tests against the /etc/passwd database only. - */ - - if(SVAL(*rparam,0) != NERR_Success) - { - if NT_STATUS_IS_OK(pass_check(passwd, user, pass1, - strlen(pass1), NULL, False)) + auth_serversupplied_info *server_info = NULL; + DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); + if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { + if (change_oem_password(server_info->sam_account,pass2)) { - if (chgpasswd(user,pass1,pass2,False)) { - SSVAL(*rparam,0,NERR_Success); - } + SSVAL(*rparam,0,NERR_Success); } + + /* + * If unix password sync was requested, attempt to change + * the /etc/passwd database also. Return failure if this cannot + * be done. + * + * This occours regardless of the previous result, becouse + * It might not have been testing the password against the SAM backend. + * (and therefore the change_oem_password would fail). + * + * Conditional on lp_unix_password_sync() becouse we don't want + * to touch the unix db unless we have admin permission. + */ + + if(lp_unix_password_sync() && !chgpasswd(pdb_get_username(server_info->sam_account), + pass1,pass2,False)) { + SSVAL(*rparam,0,NERR_badpass); + } + + free_server_info(&server_info); + } + data_blob_clear_free(&password); } - + /* * If the plaintext change failed, attempt * the old encrypted method. NT will generate this -- cgit From 32101155d4a0c80faf392f56a6baa7b91847dd99 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jan 2002 13:26:31 +0000 Subject: Kill off another ugly wart from the side of the passdb subsystem. This time its the pdb_getsampwuid() function - which was only being used by the SAMR rpc subsystem to gain a 'user session key'. This 'user session key' is actually generated at login time, and the other changes here simply move that data around. This also means that (when I check some details) we will be able to use the user session key, even when we are not actually the DC, becouse its one of the components of the info3 struct returned on logon. Andrew Bartlett (This used to be commit 799ac01fe08a338e4e94289f5d6767ebf905c1fa) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3e942e6f99..27bc15d25a 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -265,6 +265,8 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) } } + memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key)); + DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->uid, (unsigned int)vuser->gid, -- cgit From 1a74d8d1f0758d15c5c35d20e33d9868565812cf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jan 2002 14:30:58 +0000 Subject: This is another *BIG* change... Samba now features a pluggable passdb interface, along the same lines as the one in use in the auth subsystem. In this case, only one backend may be active at a time by the 'normal' interface, and only one backend per passdb_context is permitted outside that. This pluggable interface is designed to allow any number of passdb backends to be compiled in, with the selection at runtime. The 'passdb backend' paramater has been created (and documented!) to support this. As such, configure has been modfied to allow (for example) --with-ldap and the old smbpasswd to be selected at the same time. This patch also introduces two new backends: smbpasswd_nua and tdbsam_nua. These two backends accept 'non unix accounts', where the user does *not* exist in /etc/passwd. These accounts' don't have UIDs in the unix sense, but to avoid conflicts in the algroitmic mapping of RIDs, they use the values specified in the 'non unix account range' paramter - in the same way as the winbind ranges are specifed. While I was at it, I cleaned up some of the code in pdb_tdb (code copied directly from smbpasswd and not really considered properly). Most of this was to do with % macro expansion on stored data. It isn't easy to get the macros into the tdb, and the first password change will 'expand' them. tdbsam needs to use a similar system to pdb_ldap in this regard. This patch only makes minor adjustments to pdb_nisplus and pdb_ldap, becouse I don't have the test facilities for these. I plan to incoroprate at least pdb_ldap into this scheme after consultation with Jerry. Each (converted) passdb module now no longer has any 'static' variables, and only exports 1 init function outside its .c file. The non-unix-account support in this patch has been proven! It is now possible to join a win2k machine to a Samba PDC without an account in /etc/passwd! Other changes: Minor interface adjustments: pdb_delete_sam_account() now takes a SAM_ACCOUNT, not a char*. pdb_update_sam_account() no longer takes the 'override' argument that was being ignored so often (every other passdb backend). Extra checks have been added in some places. Minor code changes: smbpasswd no longer attempts to initialise the passdb at startup, this is now done on first use. pdbedit has lost some of its 'machine account' logic, as this behaviour is now controlled by the passdb subsystem directly. The samr subsystem no longer calls 'local password change', but does the pdb interactions directly. This allow the ACB_ flags specifed to be transferred direct to the backend, without interference. Doco: I've updated the doco to reflect some of the changes, and removed some paramters no longer applicable to HEAD. (This used to be commit ff354c99c585068af6dc1ff35a1f109a806b326b) --- source3/smbd/chgpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5e646b6225..9a30838cac 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -718,7 +718,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, /* Now flush the sam_passwd struct to persistent storage */ become_root(); - ret = pdb_update_sam_account (sampass, False); + ret = pdb_update_sam_account (sampass); unbecome_root(); return ret; @@ -928,7 +928,7 @@ BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd) /* Now write it into the file. */ become_root(); - ret = pdb_update_sam_account (hnd, False); + ret = pdb_update_sam_account (hnd); unbecome_root(); return ret; -- cgit From 1f670cfb275ee34e66f504cd35b1c790840999bf Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 20 Jan 2002 22:50:23 +0000 Subject: Spelling fixes. (This used to be commit e67c7c5852624bcdd5c565ea5f00b143aaf7fee4) --- source3/smbd/negprot.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 5899f0af52..04e6eb445b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -29,23 +29,23 @@ BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; struct auth_context *negprot_global_auth_context = NULL; -static void get_challange(char buff[8]) +static void get_challenge(char buff[8]) { NTSTATUS nt_status; const uint8 *cryptkey; /* We might be called more than once, muliple negprots are premitted */ if (negprot_global_auth_context) { - DEBUG(3, ("get challange: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n")); + DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n")); (negprot_global_auth_context->free)(&negprot_global_auth_context); } - DEBUG(10, ("get challange: creating negprot_global_auth_context\n")); + DEBUG(10, ("get challenge: creating negprot_global_auth_context\n")); if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) { DEBUG(0, ("make_auth_context_subsystem returned %s", get_nt_error_msg(nt_status))); smb_panic("cannot make_negprot_global_auth_context!\n"); } - DEBUG(10, ("get challange: getting challange\n")); + DEBUG(10, ("get challenge: getting challenge\n")); cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context); memcpy(buff, cryptkey, 8); } @@ -100,7 +100,7 @@ static int reply_lanman1(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - get_challange(smb_buf(outbuf)); + get_challenge(smb_buf(outbuf)); } Protocol = PROTOCOL_LANMAN1; @@ -141,7 +141,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - get_challange(smb_buf(outbuf)); + get_challenge(smb_buf(outbuf)); } Protocol = PROTOCOL_LANMAN2; @@ -286,7 +286,7 @@ static int reply_nt1(char *inbuf, char *outbuf) if (!negotiate_spnego) { /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - get_challange(p); + get_challenge(p); } SSVALS(outbuf,smb_vwv16+1,8); p += 8; -- cgit From a03b5e3864ac6044694fe0b4e7f83098598b60dc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Jan 2002 00:32:26 +0000 Subject: One less Get_Pwnam_Modify call! (the passdb backend is case-insensitive, so there isn't any point to this). Andrew Bartlett (This used to be commit 5e868b403340d84d68c1831a09bf1a4dd710da90) --- source3/smbd/lanman.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 1a5777e1d4..d755bb42f8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2052,11 +2052,6 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * (void)map_username(user); - /* - * Do any UNIX username case mangling. - */ - (void)Get_Pwnam_Modify( user ); - if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)) { SSVAL(*rparam,0,NERR_Success); -- cgit From 2383fd87a7c05b56f98bf64fa9ef536a6217f3a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 21 Jan 2002 23:34:13 +0000 Subject: Found and fixed the logic bug in write cache code. Amazingly helpful work from Juergen.Hasch@de.bosch.com in tracking this down. Jermy. (This used to be commit 40060fe3459cf103a143c324f99c2233a8e53825) --- source3/smbd/fileio.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 9f7cb5f340..a13d05ddc4 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -240,8 +240,8 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", return real_write_file(fsp, data, pos, n); } - DEBUG(9,("write_file(fd=%d pos=%d size=%d) wofs=%d wsize=%d\n", - fsp->fd, (int)pos, (int)n, (int)wcp->offset, (int)wcp->data_size)); + DEBUG(9,("write_file(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", + fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); /* * If we have active cache and it isn't contiguous then we flush. @@ -344,12 +344,15 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", write_path = 2; } else if ( (pos >= wcp->file_size) && + (wcp->offset + wcp->data_size == wcp->file_size) && (pos > wcp->offset + wcp->data_size) && (pos < wcp->offset + wcp->alloc_size) ) { /* * Non-contiguous write part of which fits within - * the cache buffer and is extending the file. + * the cache buffer and is extending the file + * and the cache contents reflect the current + * data up to the current end of the file. */ size_t data_used; @@ -504,7 +507,8 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", if (wcp->offset + wcp->data_size > wcp->file_size) wcp->file_size = wcp->offset + wcp->data_size; - DEBUG(9,("cache return %u\n", (unsigned int)n)); + DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n", + (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n)); total_written += n; return total_written; /* .... that's a write :) */ @@ -570,6 +574,8 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) return False; } + memset(wcp->data, '\0', wcp->alloc_size ); + fsp->wcp = wcp; DO_PROFILE_INC(writecache_allocated_write_caches); allocated_write_caches++; -- cgit From 73af0a70f5c55192f48e2b0f2815ec3e0747fd90 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Jan 2002 07:24:12 +0000 Subject: Ensure fsp->size is correct so readraw's return correct data. Jeremy. (This used to be commit 443d2530a7fe32392bdb8c7d38a10b7071392b13) --- source3/smbd/fileio.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index a13d05ddc4..ba60690383 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -177,6 +177,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); + fsp->size = st.st_size; if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); } @@ -237,7 +238,10 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if(!wcp) { DO_PROFILE_INC(writecache_direct_writes); - return real_write_file(fsp, data, pos, n); + total_written = real_write_file(fsp, data, pos, n); + if ((total_written != -1) && (pos + total_written > fsp->size)) + fsp->size = pos + total_written; + return total_written; } DEBUG(9,("write_file(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", @@ -274,7 +278,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", */ if (wcp->offset + wcp->data_size > wcp->file_size) - wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; /* * If we used all the data then @@ -323,7 +327,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", */ if (wcp->offset + wcp->data_size > wcp->file_size) - wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; /* * We don't need to move the start of data, but we @@ -383,7 +387,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", */ if (wcp->offset + wcp->data_size > wcp->file_size) - wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; /* * If we used all the data then @@ -424,7 +428,7 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne */ if(pos + n > wcp->file_size) - wcp->file_size = pos + n; + fsp->size = wcp->file_size = pos + n; /* * If write would fit in the cache, and is larger than @@ -443,7 +447,7 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne return ret; if (pos + ret > wcp->file_size) - wcp->file_size = pos + ret; + fsp->size = wcp->file_size = pos + ret; return ret; } @@ -453,7 +457,7 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne } if(wcp->data_size > wcp->file_size) - wcp->file_size = wcp->data_size; + fsp->size = wcp->file_size = wcp->data_size; if (cache_flush_needed) { DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ @@ -476,7 +480,7 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", return -1; if (pos + ret > wcp->file_size) - wcp->file_size = pos + n; + fsp->size = wcp->file_size = pos + n; DO_PROFILE_INC(writecache_direct_writes); return total_written + n; @@ -506,7 +510,7 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", */ if (wcp->offset + wcp->data_size > wcp->file_size) - wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n", (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n)); @@ -592,6 +596,7 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) { + fsp->size = file_size; if(fsp->wcp) { /* The cache *must* have been flushed before we do this. */ if (fsp->wcp->data_size != 0) { -- cgit From 44dd648a646e58ad69f250dcd23fe56d7885efd2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Jan 2002 11:57:11 +0000 Subject: Change the order of this a bit - as unix password change can fail. This due for abstraction into chgpasswd.c shortly. Andrew Bartlett (This used to be commit 635942ae21793136814a84b1d344f411a5d6e242) --- source3/smbd/lanman.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d755bb42f8..f6ebbc82ad 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1951,29 +1951,30 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param auth_serversupplied_info *server_info = NULL; DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - if (change_oem_password(server_info->sam_account,pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - + /* * If unix password sync was requested, attempt to change - * the /etc/passwd database also. Return failure if this cannot + * the /etc/passwd database first. Return failure if this cannot * be done. * - * This occours regardless of the previous result, becouse - * It might not have been testing the password against the SAM backend. - * (and therefore the change_oem_password would fail). + * This occurs before the oem change, becouse we don't want to + * update it if chgpasswd failed. * * Conditional on lp_unix_password_sync() becouse we don't want * to touch the unix db unless we have admin permission. */ - if(lp_unix_password_sync() && !chgpasswd(pdb_get_username(server_info->sam_account), - pass1,pass2,False)) { + if(lp_unix_password_sync() && IS_SAM_UNIX_USER(server->sam_account) + && !chgpasswd(pdb_get_username(server_info->sam_account), + pass1,pass2,False)) { SSVAL(*rparam,0,NERR_badpass); } + if (change_oem_password(server_info->sam_account,pass2)) + { + SSVAL(*rparam,0,NERR_Success); + } + free_server_info(&server_info); } data_blob_clear_free(&password); -- cgit From 7c05db480320067d8d98b030cf4c19adedee1e43 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Jan 2002 13:44:32 +0000 Subject: Oops... (This used to be commit 9b63a872239bf7757c802bb3db3761cf3ec66e85) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f6ebbc82ad..66e4cd5bf7 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1964,7 +1964,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param * to touch the unix db unless we have admin permission. */ - if(lp_unix_password_sync() && IS_SAM_UNIX_USER(server->sam_account) + if(lp_unix_password_sync() && IS_SAM_UNIX_USER(server_info->sam_account) && !chgpasswd(pdb_get_username(server_info->sam_account), pass1,pass2,False)) { SSVAL(*rparam,0,NERR_badpass); -- cgit From 723b368dc20b6075055cc0e7177990c1b6391041 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Wed, 23 Jan 2002 18:09:56 +0000 Subject: Check request flag for unicode capability and respond accordingly, rather than only doing unicode. smbfs didn't work. (This used to be commit 95857a3515d67effb1242ca07daa5643458bb2f0) --- source3/smbd/process.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 48c0053360..5eb626db2b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -923,7 +923,8 @@ void construct_reply_common(char *inbuf,char *outbuf) SCVAL(outbuf,smb_reh,0); SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); SSVAL(outbuf,smb_flg2, - FLAGS2_UNICODE_STRINGS | FLAGS2_LONG_PATH_COMPONENTS | + (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) | + FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY); SSVAL(outbuf,smb_err,SMB_SUCCESS); -- cgit From dfed852520e3f7412576cb246198780d0993e7ea Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 24 Jan 2002 13:31:34 +0000 Subject: handle filenames like .bashrc better in the new mangling code (This used to be commit 05adb30eabceea0ebbd7a7831533e2d4f20e58c8) --- source3/smbd/mangle.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index cfa2792395..b83168712f 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -81,13 +81,14 @@ static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len) return ret; } -/* trasform in a string that contain only valid chars for win filenames */ +/* trasform in a string that contain only valid chars for win filenames, + not including a '.' */ static void strvalid(smb_ucs2_t *src) { if (!src || !*src) return; while (*src) { - if (!isvalid83_w(*src)) *src = UCS2_CHAR('_'); + if (!isvalid83_w(*src) || *src == UCS2_CHAR('.')) *src = UCS2_CHAR('_'); src++; } } @@ -110,13 +111,12 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr } if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) { - p++; - ext_len = strlen_w(p); - if ((ext_len > 0) && (ext_len < 4) - && (NT_STATUS_IS_OK(has_valid_chars(p)))) /* check extension */ + ext_len = strlen_w(p+1); + if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) && + (NT_STATUS_IS_OK(has_valid_chars(p+1)))) /* check extension */ { - *(p - 1) = 0; - *extension = strdup_w(p); + *p = 0; + *extension = strdup_w(p+1); if (!*extension) { DEBUG(0,("mangle_get_prefix: out of memory!\n")); @@ -584,6 +584,8 @@ NTSTATUS is_8_3_w(const smb_ucs2_t *fname) if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done; plen = strlen_w(pref); + + if (strchr_wa(pref, '.')) goto done; if (plen < 1 || plen > 8) goto done; if (ext) if (strlen_w(ext) > 3) goto done; @@ -623,6 +625,8 @@ NTSTATUS is_valid_name(const smb_ucs2_t *fname) if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; DEBUG(10,("is_valid_name: testing\n")); /* [%s]\n", s)); */ + + if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL; ret = has_valid_chars(fname); if (NT_STATUS_IS_ERR(ret)) return ret; -- cgit From 114eaabdcbacf626ccb452a2d4f695b183dd738b Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 25 Jan 2002 00:35:14 +0000 Subject: minor fixes (This used to be commit 04f492980b73800b60dde764fdeb43f2eab79624) --- source3/smbd/mangle.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index b83168712f..a6f63371c3 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -538,16 +538,18 @@ done: BOOL is_8_3(const char *fname, BOOL check_case) { + char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if (!fname || !*fname) return False; + if ((f = strrchr(fname, '/')) == NULL) f = fname; - DEBUG(10,("is_8_3: testing [%s]\n", fname)); + DEBUG(10,("is_8_3: testing [%s]\n", f)); - if (strlen(fname) > 12) return False; + if (strlen(f) > 12) return False; - ucs2name = acnv_uxu2(fname); + ucs2name = acnv_uxu2(f); if (!ucs2name) { DEBUG(0,("is_8_3: out of memory!\n")); -- cgit From 2836f3fbddb96397d6910ef5099213b5012d0e3e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 25 Jan 2002 09:55:29 +0000 Subject: micro fix :-) (This used to be commit 8929f07a15e7c6f6dbc72b1c50b45eb4c321d516) --- source3/smbd/mangle.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index a6f63371c3..ab8726797a 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -544,6 +544,7 @@ BOOL is_8_3(const char *fname, BOOL check_case) if (!fname || !*fname) return False; if ((f = strrchr(fname, '/')) == NULL) f = fname; + else f++; DEBUG(10,("is_8_3: testing [%s]\n", f)); -- cgit From 30802965d21b27a2100dfdf8fdc8776eb176eb2a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 25 Jan 2002 10:38:00 +0000 Subject: Fix a 'const' warning. (This used to be commit 56be51d648da971bcf1250470b29918e43dc622b) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index ab8726797a..9587d0ed14 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -538,7 +538,7 @@ done: BOOL is_8_3(const char *fname, BOOL check_case) { - char *f; + const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; -- cgit From 107b12ec11254107ce59228fe5694a9892051b24 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 25 Jan 2002 15:47:12 +0000 Subject: merge from 2.2 (This used to be commit 7dc1c34145d66f4bbc5c6ce0bca4b224088366af) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 889408b631..57a4cb1d37 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -758,9 +758,9 @@ static BOOL create_canon_ace_lists(files_struct *fsp, free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - SAFE_FREE(current_ace); DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n", sid_to_string(str, ¤t_ace->trustee) )); + SAFE_FREE(current_ace); return False; } -- cgit From 9d8ed7220fed8a3b7ff9d45b9c5902c3255956ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Jan 2002 20:16:14 +0000 Subject: Fixed display of "remote downlevel document" in old print job submission case. Jeremy. (This used to be commit 248770d73072e36fd9812ec5986dce5380dfab33) --- source3/smbd/open.c | 2 +- source3/smbd/reply.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 589f1a32b4..6a6e22353b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -632,7 +632,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S ignored */ *Access = DOS_OPEN_WRONLY; *action = FILE_WAS_CREATED; - return print_fsp_open(conn); + return print_fsp_open(conn, fname); } fsp = file_new(conn); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 03d0c18942..3233168ffc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2504,7 +2504,7 @@ int reply_printopen(connection_struct *conn, } /* Open for exclusive use, write only. */ - fsp = print_fsp_open(conn); + fsp = print_fsp_open(conn, NULL); if (!fsp) { END_PROFILE(SMBsplopen); -- cgit From 714cdd47cb3e0e1f683c0a22396f9167a85e7df3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 26 Jan 2002 06:24:53 +0000 Subject: Fix up a security issue with the way we handle domain groups retuned on the info3. These are RIDs, and it only makes sense to combine them with the domain SID returned with them. This is important for trusted domains, where that sid might be other than the one we currently reterive from the secrets.tdb. Also remove the become_root()/unbecome_root() wrapper from around both remaining TDB users: Both are now initialised at smbd startup. Andrew Bartlett (This used to be commit 554842e0a55155193f25aefca6480b89d5c512ca) --- source3/smbd/server.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 492632e7ac..44002bfc94 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -556,6 +556,7 @@ static void init_structs(void ) init_dptrs(); secrets_init(); + } /**************************************************************************** @@ -841,6 +842,8 @@ static void usage(char *pname) if(!initialize_password_db(False)) exit(1); + uni_group_cache_init(); /* Non-critical */ + /* possibly reload the services file. */ reload_services(True); -- cgit From b1da5c02535ec61991d19cf09abaf366927ef34e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 26 Jan 2002 10:05:10 +0000 Subject: Rework lookup_name() to take seperate username/domain args, and to remove varioius crazy 'if winbind didn't find it' cases. This makes winbind default domain support easier to intergrate with smbd. (This used to be commit 3e71521957d579f00249679de837490aca5ba92f) --- source3/smbd/uid.c | 55 ++++++++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index d9cedaf7b5..240b4d46bb 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -436,60 +436,52 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER Tries winbind first - then uses local lookup. *****************************************************************/ -BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) +BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern pstring global_myname; extern fstring global_myworkgroup; fstring sid; - char *sep = lp_winbind_separator(); - + *name_type = SID_NAME_UNKNOWN; - if (!winbind_lookup_name(name, psid, name_type) || (*name_type != SID_NAME_USER) ) { + if (!winbind_lookup_name(domain, name, psid, name_type) || (*name_type != SID_NAME_USER) ) { BOOL ret = False; - DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name)); + DEBUG(10, ("lookup_name: winbind lookup for [%s]\\[%s] failed - trying local\n", domain, name)); /* If we are looking up a domain user, make sure it is for the local machine only */ - - if (strchr_m(name, sep[0]) || strchr_m(name, '\\') || lp_winbind_use_default_domain()) { - fstring domain, username; - - split_domain_name(name, domain, username); - - switch (lp_server_role()) { - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: - if (strequal(domain, global_myworkgroup)) { - fstrcpy(domain, global_myname); - ret = local_lookup_name(domain, username, psid, name_type); - } - /* No break is deliberate here. JRA. */ - default: - if (strcasecmp(global_myname, domain) != 0) { - DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); - ret = local_lookup_name(global_myname, username, psid, name_type); - } + + switch (lp_server_role()) { + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + if (strequal(domain, global_myworkgroup)) { + ret = local_lookup_name(name, psid, name_type); + } + /* No break is deliberate here. JRA. */ + default: + if (ret) { + } else if (strequal(global_myname, domain)) { + ret = local_lookup_name(name, psid, name_type); + } else { + DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); } - } else { - ret = local_lookup_name(global_myname, name, psid, name_type); } if (ret) { DEBUG(10, - ("lookup_name: (local) %s -> SID %s (type %u)\n", - name, sid_to_string(sid,psid), + ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %u)\n", + domain, name, sid_to_string(sid,psid), (unsigned int)*name_type )); } else { - DEBUG(10,("lookup name: (local) %s failed.\n", name)); + DEBUG(10,("lookup name: (local) [%s]\\[%s] failed.\n", domain, name)); } return ret; } - DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", - name, sid_to_string(sid, psid), + DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", + domain, name, sid_to_string(sid, psid), (unsigned int)*name_type)); return True; } @@ -702,3 +694,4 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) return True; } + -- cgit From 59b17ff5970fd932a45ae45b4f0d4f1b2da12704 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 26 Jan 2002 12:24:18 +0000 Subject: - Provide sid->name lookup support for non-unix accounts. - Rework the name -> sid lookup function to always try local lookup first (for local domain names) before trying winbind. This seems to eliminate my winbind feedback loop problems. (I don't use winbind for nsswitch, where there are almost certainly further issues). Andrew Bartlett (This used to be commit 25cadce67bc8effd4248ab993ae78e1d8511d994) --- source3/smbd/uid.c | 69 ++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 240b4d46bb..eb1756008f 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -433,7 +433,7 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER /***************************************************************** *THE CANONICAL* convert name to SID function. - Tries winbind first - then uses local lookup. + Tries local lookup first - for local domains - then uses winbind. *****************************************************************/ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) @@ -441,54 +441,51 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N extern pstring global_myname; extern fstring global_myworkgroup; fstring sid; + BOOL ret = False; *name_type = SID_NAME_UNKNOWN; - if (!winbind_lookup_name(domain, name, psid, name_type) || (*name_type != SID_NAME_USER) ) { - BOOL ret = False; - - DEBUG(10, ("lookup_name: winbind lookup for [%s]\\[%s] failed - trying local\n", domain, name)); - - /* If we are looking up a domain user, make sure it is - for the local machine only */ - - switch (lp_server_role()) { - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: - if (strequal(domain, global_myworkgroup)) { - ret = local_lookup_name(name, psid, name_type); - } - /* No break is deliberate here. JRA. */ - default: - if (ret) { - } else if (strequal(global_myname, domain)) { - ret = local_lookup_name(name, psid, name_type); - } else { - DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); - } + /* If we are looking up a domain user, make sure it is + for the local machine only */ + + switch (lp_server_role()) { + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + if (strequal(domain, global_myworkgroup)) { + ret = local_lookup_name(name, psid, name_type); } - + /* No break is deliberate here. JRA. */ + default: if (ret) { - DEBUG(10, - ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %u)\n", - domain, name, sid_to_string(sid,psid), - (unsigned int)*name_type )); + } else if (strequal(global_myname, domain)) { + ret = local_lookup_name(name, psid, name_type); } else { - DEBUG(10,("lookup name: (local) [%s]\\[%s] failed.\n", domain, name)); + DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); } - - return ret; + } + + if (ret) { + DEBUG(10, + ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %u)\n", + domain, name, sid_to_string(sid,psid), + (unsigned int)*name_type )); + return True; + } else if (winbind_lookup_name(domain, name, psid, name_type) || (*name_type != SID_NAME_USER) ) { + + DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", + domain, name, sid_to_string(sid, psid), + (unsigned int)*name_type)); + return True; } - DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", - domain, name, sid_to_string(sid, psid), - (unsigned int)*name_type)); - return True; + DEBUG(10, ("lookup_name: winbind and local lookups for [%s]\\[%s] failed\n", domain, name)); + + return False; } /***************************************************************** *THE CANONICAL* convert SID to name function. - Tries winbind first - then uses local lookup. + Tries local lookup first - for local sids, then tries winbind. *****************************************************************/ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) -- cgit From 184cc84adab4ead8fde1b79c449ef47f23567165 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 27 Jan 2002 12:06:27 +0000 Subject: Yes, dev is an 'input/output' paramater... Andrew Bartlett (This used to be commit 8cac618174365825e8b1824f70cb42afbce5e500) --- source3/smbd/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b25e696c8d..ac2e2ee548 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -218,7 +218,7 @@ int find_service(fstring service) do some basic sainity checks on the share. This function modifies dev, ecode. ****************************************************************************/ -static NTSTATUS share_sanity_checks(int snum, char* service, pstring dev) +static NTSTATUS share_sanity_checks(int snum, const char* service, pstring dev) { if (!lp_snum_ok(snum) || @@ -325,7 +325,7 @@ static void set_admin_user(connection_struct *conn) ****************************************************************************/ connection_struct *make_connection(char *service, DATA_BLOB password, - const char *dev, uint16 vuid, NTSTATUS *status) + char *dev, uint16 vuid, NTSTATUS *status) { int snum; struct passwd *pass = NULL; -- cgit From 7b671e34f599b9d27c615c1be35db4ae10ce6481 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 27 Jan 2002 12:12:22 +0000 Subject: Some more 'winbind default domain' support patches from Alexander Bokovoy . This patch is designed to remove the 'special cases' required for this support. In particular this now kills off winbind_initgroups, as it appears no longer to be required. Andrew Bartlett (This used to be commit f1d8d509766e9169d39332559162cfec249bfc70) --- source3/smbd/sec_ctx.c | 2 +- source3/smbd/service.c | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index b774947d60..5802c97f3d 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -185,7 +185,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) /* Call initgroups() to get user groups */ - if (winbind_initgroups(user,gid) == -1) { + if (initgroups(user,gid) == -1) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); if (getuid() == 0) { if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ac2e2ee548..a9b9a9d4d9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -84,7 +84,7 @@ int add_home_service(const char *service, const char *homedir) int iHomeService; int iService; fstring new_service; - char *usr_p = NULL; + fstring domain; if (!service || !homedir) return -1; @@ -99,11 +99,7 @@ int add_home_service(const char *service, const char *homedir) * include any macros. */ - fstrcpy(new_service, service); - - if ((usr_p = strchr_m(service,*lp_winbind_separator())) != NULL) - fstrcpy(new_service, usr_p+1); - + split_domain_and_name(service, domain, new_service); lp_add_home(new_service, iHomeService, homedir); iService = lp_servicenumber(new_service); -- cgit From 86aa1d20f907babecf36660e16d6181310520764 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 29 Jan 2002 01:01:14 +0000 Subject: Since we have dynamic initialisation in the group mapping code, make init_group_mapping() a static function and don't call it from any client programs. Not sure whether I've made a bigger mess here or not... (This used to be commit 3c887d9021269aaa9fc0bc771af8589077e6208e) --- source3/smbd/server.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 44002bfc94..4d4c612b52 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -852,11 +852,6 @@ static void usage(char *pname) exit(1); } - if (!init_group_mapping()) { - DEBUG(0,("Could not open tdb mapping file.\n")); - return 0; - } - if (!init_account_policy()) { DEBUG(0,("Could not open account policy tdb.\n")); exit(1); -- cgit From 15f2c69c4f0a33134319da482b90737e4a35ad92 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Jan 2002 01:17:44 +0000 Subject: Fix "strict allocate" to write the data out on ftruncate with extend. Jeremy. (This used to be commit 48fc42c7104d118bd43c80c801866ebd03be1638) --- source3/smbd/vfs-wrap.c | 78 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index b2d73561af..48d16bdaaf 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -476,6 +476,62 @@ int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *tim return result; } +/********************************************************************* + A version of ftruncate that will write the space on disk if strict + allocate is set. +**********************************************************************/ + +static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) +{ + struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; + SMB_STRUCT_STAT st; + SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR); + unsigned char zero_space[4096]; + SMB_OFF_T space_to_write = len - st.st_size; + + if (currpos == -1) + return -1; + + if (vfs_ops->fstat(fsp, fd, &st) == -1) + return -1; + +#ifdef S_ISFIFO + if (S_ISFIFO(st.st_mode)) + return 0; +#endif + + if (st.st_size == len) + return 0; + + /* Shrink - just ftruncate. */ + if (st.st_size > len) + return sys_ftruncate(fd, len); + + /* Write out the real space on disk. */ + if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size) + return -1; + + space_to_write = len - st.st_size; + + memset(zero_space, '\0', sizeof(zero_space)); + while ( space_to_write > 0) { + SMB_OFF_T retlen; + SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); + + retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write); + if (retlen <= 0) + return -1; + + space_to_write -= retlen; + } + + /* Seek to where we were */ + if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) + return -1; + + return 0; +} + int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) { int result = -1; @@ -486,13 +542,21 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) START_PROFILE(syscall_ftruncate); + if (lp_strict_allocate(SNUM(fsp->conn))) { + result = strict_allocate_ftruncate(fsp, fd, len); + END_PROFILE(syscall_ftruncate); + return result; + } + /* we used to just check HAVE_FTRUNCATE_EXTEND and only use sys_ftruncate if the system supports it. Then I discovered that you can have some filesystems that support ftruncate expansion and some that don't! On Linux fat can't do ftruncate extend but ext2 can. */ + result = sys_ftruncate(fd, len); - if (result == 0) goto done; + if (result == 0) + goto done; /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot extend a file with ftruncate. Provide alternate implementation @@ -506,7 +570,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) size in which case the ftruncate above should have succeeded or shorter, in which case seek to len - 1 and write 1 byte of zero */ - if (vfs_ops->fstat(fsp, fd, &st) < 0) { + if (vfs_ops->fstat(fsp, fd, &st) == -1) { goto done; } @@ -527,19 +591,17 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) goto done; } - if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1) { + if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1) goto done; - } - if (vfs_ops->write(fsp, fd, &c, 1)!=1) { + if (vfs_ops->write(fsp, fd, &c, 1)!=1) goto done; - } /* Seek to where we were */ - if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) { + if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) goto done; - } result = 0; + done: END_PROFILE(syscall_ftruncate); -- cgit From c3b9cc08e878cf06ba1bb916ef243c0edd6a15d6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 30 Jan 2002 05:45:09 +0000 Subject: merge from 2.2 (This used to be commit 69a9c005c21833bdf22b72aaa3704bd14f627840) --- source3/smbd/server.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4d4c612b52..7647f45bea 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -781,7 +781,14 @@ static void usage(char *pname) DEBUG(3,( "loaded services\n")); if (!is_daemon && !is_a_socket(0)) { - DEBUG(0,("standard input is not a socket, assuming -D option\n")); + if (!interactive) + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + + /* + * Setting is_daemon here prevents us from eventually calling + * the open_sockets_inetd() + */ + is_daemon = True; } -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/smbd/blocking.c | 3 +-- source3/smbd/build_options.c | 3 +-- source3/smbd/change_trust_pw.c | 3 +-- source3/smbd/chgpasswd.c | 3 +-- source3/smbd/close.c | 3 +-- source3/smbd/conn.c | 3 +-- source3/smbd/connection.c | 3 +-- source3/smbd/dfree.c | 3 +-- source3/smbd/dir.c | 3 +-- source3/smbd/dosmode.c | 3 +-- source3/smbd/error.c | 3 +-- source3/smbd/fileio.c | 3 +-- source3/smbd/filename.c | 3 +-- source3/smbd/files.c | 3 +-- source3/smbd/groupname.c | 3 +-- source3/smbd/ipc.c | 3 +-- source3/smbd/lanman.c | 3 +-- source3/smbd/mangle.c | 3 +-- source3/smbd/message.c | 3 +-- source3/smbd/negprot.c | 3 +-- source3/smbd/noquotas.c | 3 +-- source3/smbd/notify.c | 3 +-- source3/smbd/notify_hash.c | 3 +-- source3/smbd/notify_kernel.c | 3 +-- source3/smbd/nttrans.c | 3 +-- source3/smbd/open.c | 3 +-- source3/smbd/oplock.c | 3 +-- source3/smbd/oplock_irix.c | 3 +-- source3/smbd/oplock_linux.c | 3 +-- source3/smbd/password.c | 3 +-- source3/smbd/pipes.c | 3 +-- source3/smbd/posix_acls.c | 3 +-- source3/smbd/process.c | 3 +-- source3/smbd/quotas.c | 3 +-- source3/smbd/reply.c | 3 +-- source3/smbd/sec_ctx.c | 3 +-- source3/smbd/server.c | 2 +- source3/smbd/service.c | 3 +-- source3/smbd/session.c | 3 +-- source3/smbd/sesssetup.c | 3 +-- source3/smbd/srvstr.c | 3 +-- source3/smbd/ssl.c | 3 +-- source3/smbd/statcache.c | 3 +-- source3/smbd/trans2.c | 3 +-- source3/smbd/uid.c | 3 +-- source3/smbd/utmp.c | 3 +-- source3/smbd/vfs-wrap.c | 3 +-- source3/smbd/vfs.c | 3 +-- 48 files changed, 48 insertions(+), 95 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 0d2a99b3f0..024e5b9f66 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Blocking Locking functions Copyright (C) Jeremy Allison 1998 diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 9e55a29744..1d18f534b1 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 2.2 + Unix SMB/CIFS implementation. Build Options for Samba Suite Copyright (C) Vance Lankhaar 2001 Copyright (C) Andrew Bartlett 2001 diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 8a16793843..0d80d5718f 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -1,6 +1,5 @@ /* - * Unix SMB/Netbios implementation. - * Version 3.0 + * Unix SMB/CIFS implementation. * Periodic Trust account password changing. * Copyright (C) Andrew Tridgell 1992-1997, * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 9a30838cac..eed535cf11 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/close.c b/source3/smbd/close.c index b6b619dd8a..79b627e924 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. file closing Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index f9d0ffc9bd..55b2d28272 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Manage connections_struct structures Copyright (C) Andrew Tridgell 1998 diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index da904e0a04..c9815dbf8c 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. connection claim routines Copyright (C) Andrew Tridgell 1998 diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 51f0614941..71b3f2bf77 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. functions to calculate the free disk space Copyright (C) Andrew Tridgell 1998 diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index faf5bca52d..2b2683caa5 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Directory handling routines Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 0f15ef25c2..6750649eff 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. dos mode handling functions Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/error.c b/source3/smbd/error.c index fc26aa4ded..6b3b73aa87 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. error packet handling Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index ba60690383..2aafd14c99 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. read/write to a files_struct Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f098950c44..3053e8a1d8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1999-200 diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 3935a12442..c055fb54eb 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Files[] structure handling Copyright (C) Andrew Tridgell 1998 diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 7d3dce131a..812488571a 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Groupname handling Copyright (C) Jeremy Allison 1998. diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f84f3048e9..c2f3b7b2f0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Inter-process communication and named pipe handling Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 66e4cd5bf7..128d8bea4a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Inter-process communication and named pipe handling Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 9587d0ed14..302817efb6 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. Name mangling with persistent tdb Copyright (C) Simo Sorce 2001 diff --git a/source3/smbd/message.c b/source3/smbd/message.c index a3625e3716..971834c012 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. SMB messaging Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 04e6eb445b..073edd70db 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. negprot reply code Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/noquotas.c b/source3/smbd/noquotas.c index a6951d97fc..85caef57e1 100644 --- a/source3/smbd/noquotas.c +++ b/source3/smbd/noquotas.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. No support for quotas :-). Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 52df3558aa..0895ddaf87 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. change notify handling Copyright (C) Andrew Tridgell 2000 Copyright (C) Jeremy Allison 1994-1998 diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 178dcecc82..d8b35462ac 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. change notify handling - hash based implementation Copyright (C) Jeremy Allison 1994-1998 Copyright (C) Andrew Tridgell 2000 diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index f618700bf0..19ea41e195 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. change notify handling - linux kernel based implementation Copyright (C) Andrew Tridgell 2000 diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6e03d485d2..694cfb92a3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. SMB NT transaction handling Copyright (C) Jeremy Allison 1994-1998 diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6a6e22353b..915063a5df 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 2001 diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 844e7d812a..16c7db6645 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 2.2.x + Unix SMB/CIFS implementation. oplock processing Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1998 - 2001 diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 1052046175..14f6de27c4 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 2.x + Unix SMB/CIFS implementation. IRIX kernel oplock processing Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 3f22956aa0..d946578380 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. kernel oplock processing for Linux Copyright (C) Andrew Tridgell 2000 diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 27bc15d25a..629157f22d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Password and authentication handling Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 8f6f6f39c4..6c1e6efa73 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Pipe SMB reply routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Luke Kenneth Casson Leighton 1996-1998 diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 57a4cb1d37..7d2eff8066 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. SMB NT Security Descriptor / Unix permission conversion. Copyright (C) Jeremy Allison 1994-2000 diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5eb626db2b..e7a9d0b644 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. process incoming packets - main loop Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 73391e6c0d..39cb8f2432 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. support for quotas Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3233168ffc..c7f805122d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Main SMB reply routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Bartlett 2001 diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 5802c97f3d..87bf8b1744 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. uid/user handling Copyright (C) Tim Potter 2000 diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7647f45bea..3b40cb6191 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1,5 +1,5 @@ /* - Unix SMB/Netbios implementation. + Unix SMB/CIFS implementation. Main SMB server routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a9b9a9d4d9..0ae49b7adf 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. service (connection) opening and closing Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/session.c b/source3/smbd/session.c index d483f12d16..c8f77aaa61 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 2.0 + Unix SMB/CIFS implementation. session handling for utmp and PAM Copyright (C) tridge@samba.org 2001 Copyright (C) abartlet@pcug.org.au 2001 diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0e5830fc24..899c9174b2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. handle SMBsessionsetup Copyright (C) Andrew Tridgell 1998-2001 Copyright (C) Andrew Bartlett 2001 diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 3c452653f2..90da422f13 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. server specific string routines Copyright (C) Andrew Tridgell 2001 diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c index 349ca34f95..7fcb48a954 100644 --- a/source3/smbd/ssl.c +++ b/source3/smbd/ssl.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. SSLeay utility functions Copyright (C) Christian Starkjohann 1998 diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 09aa63d56d..93782b9bb0 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2000 diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 60e03e002d..86c6252297 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. SMB transaction2 handling Copyright (C) Jeremy Allison 1994-2001 diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index eb1756008f..3a939e4fce 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. uid/user handling Copyright (C) Andrew Tridgell 1992-1998 diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 92e001cd03..6b7b0f3ad1 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 2.0 + Unix SMB/CIFS implementation. utmp routines Copyright (C) T.D.Lee@durham.ac.uk 1999 Heavily modified by Andrew Bartlett and Tridge, April 2001 diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 48d16bdaaf..50cf42e248 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Wrap disk only vfs functions to sidestep dodgy compilers. Copyright (C) Tim Potter 1998 diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index e05b217a14..c0e775268c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. VFS initialisation and support functions Copyright (C) Tim Potter 1999 -- cgit From 69adbb0ce3bb9d5bd569c13aaa3ac8f390c1586a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Jan 2002 23:26:12 +0000 Subject: Fix from Michael Steffens to make signal processing work correctly in winbindd. This is a really good patch that gives full select semantics to the Samba modified select. Jeremy. (This used to be commit 3af16ade173cac24c1ac5eff4a36b439f16ac036) --- source3/smbd/oplock.c | 2 +- source3/smbd/process.c | 2 +- source3/smbd/server.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 16c7db6645..39bcb558f1 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -93,7 +93,7 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(maxfd+1,fds,&to); + selrtn = sys_select(maxfd+1,fds,NULL,NULL,&to); if (selrtn == -1 && errno == EINTR) { /* could be a kernel oplock interrupt */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e7a9d0b644..bf1a1ca9a7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -193,7 +193,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL); + selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,timeout>0?&to:NULL); /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3b40cb6191..50f09cf6e6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -239,7 +239,7 @@ max can be %d\n", memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select(FD_SETSIZE,&lfds,NULL); + num = sys_select(FD_SETSIZE,&lfds,NULL,NULL,NULL); if (num == -1 && errno == EINTR) { extern VOLATILE sig_atomic_t reload_after_sighup; -- cgit From 407cd42143f35ea62ac9205a85263d494e494d25 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 4 Feb 2002 00:59:23 +0000 Subject: better debug messages! (This used to be commit e3bb6867454307ae592115e205d32ddd53988678) --- source3/smbd/mangle.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 302817efb6..ecdf82270c 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -421,7 +421,7 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) p = acnv_dosu2(data.dptr); if (!p) { - DEBUG(0,("mangle: out of memory!\n")); + DEBUG(0,("mangle: internal error acnv_dosu2() failed!\n")); goto done; } } @@ -477,7 +477,7 @@ char *dos_mangle(const char *dos_unmangled) in = acnv_dosu2(dos_unmangled); if (!in) { - DEBUG(0,("dos_mangle: out of memory!\n")); + DEBUG(0,("dos_mangle: internal error acnv_dosu2() failed!\n")); return NULL; } @@ -491,7 +491,7 @@ char *dos_mangle(const char *dos_unmangled) dos_mangled = acnv_u2dos(out); if (!dos_mangled) { - DEBUG(0,("dos_mangle: out of memory!\n")); + DEBUG(0,("dos_mangle: internal error acnv_u2dos() failed!\n")); goto done; } @@ -511,7 +511,7 @@ char *dos_unmangle(const char *dos_mangled) in = acnv_dosu2(dos_mangled); if (!in) { - DEBUG(0,("dos_unmangle: out of memory!\n")); + DEBUG(0,("dos_unmangle: internal error acnv_dosu2() failed!\n")); return NULL; } @@ -525,7 +525,7 @@ char *dos_unmangle(const char *dos_mangled) dos_unmangled = acnv_u2dos(out); if (!dos_unmangled) { - DEBUG(0,("dos_unmangle: out of memory!\n")); + DEBUG(0,("dos_unmangle: internal error acnv_u2dos failed!\n")); goto done; } @@ -552,7 +552,7 @@ BOOL is_8_3(const char *fname, BOOL check_case) ucs2name = acnv_uxu2(f); if (!ucs2name) { - DEBUG(0,("is_8_3: out of memory!\n")); + DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); goto done; } @@ -691,7 +691,7 @@ BOOL is_mangled(const char *s) u2 = acnv_dosu2(s); if (!u2) { - DEBUG(0,("is_mangled: out of memory!\n")); + DEBUG(0,("is_mangled: internal error acnv_dosu2() failed!!\n")); return ret; } @@ -794,7 +794,7 @@ void mangle_name_83(char *s) u2 = acnv_dosu2(s); if (!u2) { - DEBUG(0,("mangle_name_83: out of memory!\n")); + DEBUG(0,("mangle_name_83: internal error acnv_dosu2() failed!\n")); return; } -- cgit From 4ddd288f9a8abc63abe133dd41ad30bcb01ad64e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 5 Feb 2002 01:31:16 +0000 Subject: check for empty parameters in qpathinfo (This used to be commit c78b16c1f850562b65acb6143e55b1aefc075753) --- source3/smbd/trans2.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 86c6252297..6a089cc429 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1440,6 +1440,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, int len; time_t c_time; + if (!params) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + if (tran_call == TRANSACT2_QFILEINFO) { files_struct *fsp = file_fsp(params,0); info_level = SVAL(params,2); -- cgit From c1d83be9b5e8f928e2234528d5f99a771d23ca37 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 9 Feb 2002 03:29:36 +0000 Subject: Do the reverse DNS lookup, but only if 'hostname lookups = yes' Andrew Bartlett (This used to be commit dfecd6a4534743a3e140eafc9836911286793951) --- source3/smbd/session.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index c8f77aaa61..6f9d62edfd 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -77,12 +77,14 @@ BOOL session_claim(user_struct *vuser) return False; } - /* Don't resolve the hostname in smbd as we can pause for a long - time while waiting for DNS timeouts to occur. The correct - place to do this is in the code that displays the session - information. */ + /* If 'hostname lookup' == yes, then do the DNS lookup. This is + needed becouse utmp and PAM both expect DNS names */ - hostname = client_addr(); + if (lp_hostname_lookups()) { + hostname = client_name(); + } else { + hostname = client_addr(); + } fstrcpy(sessionid.username, vuser->user.unix_name); fstrcpy(sessionid.hostname, hostname); -- cgit From cd38c3a71c74d2c62c0cf25a3b6e9ea460036ef6 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 15 Feb 2002 02:46:13 +0000 Subject: Merge of smbclient print crash bug fix from app head. (This used to be commit a56298d56ae67a764e9b9a43c1c568b7125e1c18) --- source3/smbd/open.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 915063a5df..aab7b5079e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -629,8 +629,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are ignored */ - *Access = DOS_OPEN_WRONLY; - *action = FILE_WAS_CREATED; + if (Access) + *Access = DOS_OPEN_WRONLY; + if (action) + *action = FILE_WAS_CREATED; return print_fsp_open(conn, fname); } -- cgit From d04aeaace97b5328de5fb6b04b843a1f18ea30f0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 19 Feb 2002 06:13:16 +0000 Subject: in dos_unmangle() the only function call was to *mangle()*. Adding the 'un' dramaticly increses the functionality of this code :-). Andrew Bartlett (This used to be commit 15b9b63db57901fbfa3d62b64212742f361ee519) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index ecdf82270c..d396989e86 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -515,7 +515,7 @@ char *dos_unmangle(const char *dos_mangled) return NULL; } - out = mangle(in); + out = unmangle(in); if (!out) { SAFE_FREE(in); -- cgit From 93ea4825972c80957946ac5ef722853a95ccb31c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Feb 2002 04:26:32 +0000 Subject: this fixes the security tab on mapped drives for unicode clients. Jeremy, this is wrong in 2.2.x (This used to be commit 367358c7389555f413b3c690c012ef067859fc22) --- source3/smbd/trans2.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6a089cc429..84ab7286e5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1431,7 +1431,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SMB_OFF_T allocation_size=0; unsigned int data_size; SMB_STRUCT_STAT sbuf; - pstring fname; + pstring fname, dos_fname; char *base_name; char *p; SMB_OFF_T pos = 0; @@ -1552,6 +1552,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, sbuf.st_mtime &= ~1; } + /* NT expects the name to be in an exact form */ + if (strequal(fname,".")) { + pstrcpy(dos_fname, "\\"); + } else { + snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname); + } + switch (info_level) { case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: @@ -1645,16 +1652,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_NAME_INFO: /* - * The first part of this code is essential - * to get security descriptors to work on mapped - * drives. Don't ask how I discovered this unless - * you like hearing about me suffering.... :-). JRA. + this must be *exactly* right for ACLs on mapped drives to work */ - if(strequal(".", fname)) { - len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE); - } else { - len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); - } + len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE); data_size = 4 + len; SIVAL(pdata,0,len); break; @@ -1697,7 +1697,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ pdata += 4; pdata += 4; /* alignment */ - len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -1718,12 +1718,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_NAME_INFORMATION: /* Pathname with leading '\'. */ { - pstring new_fname; size_t byte_len; - - pstrcpy(new_fname, "\\"); - pstrcat(new_fname, fname); - byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False); + byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False); SIVAL(pdata,0,byte_len); data_size = 4 + byte_len; break; @@ -1753,9 +1749,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* Not yet finished... JRA */ case 1018: { - pstring new_fname; - size_t byte_len; - put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ -- cgit From 566fafdb251de4b88d2f6f71bd210d464b1d2a0a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Feb 2002 03:14:58 +0000 Subject: don't do an ADS init when not in ADS mode (This used to be commit 68693ba4e80257bf895b1c8db18c138d5d9919bb) --- source3/smbd/negprot.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 073edd70db..934d594853 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -193,16 +193,15 @@ static int negprot_spnego(char *p) return 16; } #endif - { + if (lp_security() != SEC_ADS) { + blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); + } else { ADS_STRUCT *ads; ads = ads_init(NULL, NULL, NULL, NULL); - /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ asprintf(&principal, "HOST/%s@%s", guid, ads->realm); - blob = spnego_gen_negTokenInit(guid, - lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain, - principal); + blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal); free(principal); ads_destroy(&ads); } -- cgit From c75396cf49bb3640b07f105b72b4ddad056bd7cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Feb 2002 02:12:38 +0000 Subject: This fixes 4 info levels in a trans2 find_first that should not be null terminated for the filenames. this is what caused win2k to go into a loop sending 20000 packets to set an acl on a directory. It didn't recognise ".." with a null termination as being ".." (This used to be commit a75a2e9e2f11e27ca8a7fbad8c0108a2aee0a690) --- source3/smbd/trans2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 84ab7286e5..8e2bfd14b0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -622,7 +622,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, *(p+2) = 0; } p += 2 + 24; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, p, fname, -1, 0); SIVAL(q,0,len); p += len; len = PTR_DIFF(p, pdata); @@ -643,7 +643,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 16; SIVAL(p,0,nt_extmode); p += 4; p += 4; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, p, fname, -1, 0); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); @@ -666,7 +666,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; SIVAL(p,0,0); p += 4; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, p, fname, -1, 0); SIVAL(p, -4, len); p += len; @@ -680,7 +680,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; SIVAL(p,0,reskey); p += 4; p += 4; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + /* this must *not* be null terminated or w2k gets in a loop trying to set an + acl on a dir (tridge) */ + len = srvstr_push(outbuf, p, fname, -1, 0); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); -- cgit From 97d96862ca84f599ee6fed0910389e07d46ee91d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Feb 2002 05:45:33 +0000 Subject: This is a nasty hack to fix "xcopy /o" from win2000 on a Samba share The hack passes the true ntcreate desired_access down to open_file_shared1() from the ntcreatex function. This is used to determine if share modes should be used in denying this open. This hack will become unnecessary when we redo open.c to use the proper NTCreateX semantics rather than trying to jam the ntcreate semantics into openX semantics. (This used to be commit d09ae0c667a94fcf870c0fc7f97119266a650d45) --- source3/smbd/nttrans.c | 10 ++++++--- source3/smbd/open.c | 59 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 694cfb92a3..501f0e9ab0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -717,8 +717,11 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode, - smb_ofun,unixmode, oplock_request,&rmode,&smb_action); + fsp = open_file_shared1(conn,fname,&sbuf, + desired_access, + smb_open_mode, + smb_ofun,unixmode, oplock_request, + &rmode,&smb_action); if (!fsp) { /* We cheat here. There are two cases we @@ -1213,7 +1216,8 @@ static int call_nt_transact_create(connection_struct *conn, * Ordinary file case. */ - fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode,smb_ofun,unixmode, + fsp = open_file_shared1(conn,fname,&sbuf,desired_access, + smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aab7b5079e..7396233c26 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -437,8 +437,10 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i ****************************************************************************/ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev, - SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request, - BOOL *p_all_current_opens_are_level_II) + SMB_INO_T inode, + uint32 desired_access, + int share_mode, int *p_flags, int *p_oplock_request, + BOOL *p_all_current_opens_are_level_II) { int i; int num_share_modes; @@ -510,13 +512,27 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou *p_all_current_opens_are_level_II = False; } - /* someone else has a share lock on it, check to see - if we can too */ - - if(check_share_mode(conn, share_entry, share_mode, fname, fcbopen, p_flags) == False) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; + /* this is a nasty hack, but necessary until we rewrite our open + handling to use a NTCreateX call as the basic call. + NT may open a file with neither read nor write access, and in + this case it expects the open not to conflict with any + existing deny modes. This happens (for example) during a + "xcopy /o" where the second file descriptor is used for + ACL sets + This code should be removed once we have a propoer ntcreateX + open functions + (tridge) + */ + if (desired_access == 0 || + (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE))) { + /* someone else has a share lock on it, check to see + if we can too */ + if (!check_share_mode(conn, share_entry, share_mode, + fname, fcbopen, p_flags)) { + SAFE_FREE(old_shares); + errno = EACCES; + return -1; + } } } /* end for */ @@ -608,6 +624,19 @@ static void kernel_flock(files_struct *fsp, int deny_mode) files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) +{ + return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode, + oplock_request, Access, action); +} + +/**************************************************************************** + Open a file with a share mode. On output from this open we are guarenteeing + that +****************************************************************************/ +files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, + uint32 desired_access, + int share_mode,int ofun, mode_t mode,int oplock_request, + int *Access,int *action) { int flags=0; int flags2=0; @@ -736,8 +765,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S lock_share_entry(conn, dev, inode); - num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, - &flags, &oplock_request, &all_current_opens_are_level_II); + num_share_modes = open_mode_check(conn, fname, dev, inode, + desired_access, + share_mode, + &flags, &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { /* @@ -801,8 +832,10 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", lock_share_entry_fsp(fsp); - num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, - &flags, &oplock_request, &all_current_opens_are_level_II); + num_share_modes = open_mode_check(conn, fname, dev, inode, + desired_access, + share_mode, + &flags, &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { unlock_share_entry_fsp(fsp); -- cgit From 14c6277840a7b067335122a0ae13ed390e9ab3a6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 27 Feb 2002 13:18:51 +0000 Subject: This should fix up the level 0 'convert_string' debug messages that we have been seing since the unicode conversion. It looks like a simple oversight in the move away from StrnCpy (which takes amount of space -1 as an arg) to push_ascii etc which take the absolute amount of space. Andrew Bartlett (This used to be commit 4447c6bd4d9c273ef5bf4eb23726923ee58bf38d) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 128d8bea4a..5bf7bb89e3 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -82,7 +82,7 @@ static int CopyAndAdvance(char** dst, char* src, int* n) { int l; if (!src || !dst || !n || !(*dst)) return(0); - l = push_ascii(*dst,src,*n-1, STR_TERMINATE); + l = push_ascii(*dst,src,*n, STR_TERMINATE); (*dst) += l; (*n) -= l; return l; -- cgit From 9e2a06611d5ab7e2dbba7e9fbc84e1fcae0c58ed Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 27 Feb 2002 18:06:47 +0000 Subject: Fixed usage of uninitialised variable in strict_allocate_ftruncate() (This used to be commit b1d56956fec0de0e8591d85eb5eeec939494e6d4) --- source3/smbd/vfs-wrap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 50cf42e248..15d9572d1d 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -486,7 +486,7 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) SMB_STRUCT_STAT st; SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR); unsigned char zero_space[4096]; - SMB_OFF_T space_to_write = len - st.st_size; + SMB_OFF_T space_to_write; if (currpos == -1) return -1; @@ -494,6 +494,8 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) if (vfs_ops->fstat(fsp, fd, &st) == -1) return -1; + space_to_write = len - st.st_size; + #ifdef S_ISFIFO if (S_ISFIFO(st.st_mode)) return 0; -- cgit From 2da4d64cfcf289d18d622c67d3250c51e6b88466 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Feb 2002 21:46:53 +0000 Subject: Added "nt status support" parameter. Fix offline synchronisation. Jeremy. (This used to be commit 9243a9778e52999d5c62cba484640637b24994d8) --- source3/smbd/error.c | 16 +++++++++++----- source3/smbd/negprot.c | 25 +++++++++++++------------ source3/smbd/nttrans.c | 9 ++++----- source3/smbd/reply.c | 10 ++++------ 4 files changed, 32 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 6b3b73aa87..92a7c11b15 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -90,10 +90,17 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, if (errno != 0) DEBUG(3,("error string = %s\n",strerror(errno))); - if (global_client_caps & CAP_STATUS32) { - if (NT_STATUS_V(ntstatus) == 0 && eclass) { + /* + * We can explicitly force 32 bit error codes even when the + * parameter "nt status" is set to no by pre-setting the + * FLAGS2_32_BIT_ERROR_CODES bit in the smb_flg2 outbuf. + * This is to allow work arounds for client bugs that are needed + * when talking with clients that normally expect nt status codes. JRA. + */ + + if ((lp_nt_status_support() || (SVAL(outbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) && (global_client_caps & CAP_STATUS32)) { + if (NT_STATUS_V(ntstatus) == 0 && eclass) ntstatus = dos_to_ntstatus(eclass, ecode); - } SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus)); SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); DEBUG(3,("error packet at %s(%d) cmd=%d (%s) %s\n", @@ -104,9 +111,8 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, return outsize; } - if (eclass == 0 && NT_STATUS_V(ntstatus)) { + if (eclass == 0 && NT_STATUS_V(ntstatus)) ntstatus_to_dos(ntstatus, &eclass, &ecode); - } SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); SSVAL(outbuf,smb_rcls,eclass); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 934d594853..f4ed360845 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -220,7 +220,7 @@ static int reply_nt1(char *inbuf, char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| - CAP_LEVEL_II_OPLOCKS|CAP_STATUS32; + CAP_LEVEL_II_OPLOCKS; int secword=0; time_t t = time(NULL); @@ -242,28 +242,29 @@ static int reply_nt1(char *inbuf, char *outbuf) capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX; - if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) { + if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS; - } - if (SMB_OFF_T_BITS == 64) { + if (SMB_OFF_T_BITS == 64) capabilities |= CAP_LARGE_FILES; - } - - if (lp_readraw() && lp_writeraw()) { + + if (lp_readraw() && lp_writeraw()) capabilities |= CAP_RAW_MODE; - } /* allow for disabling unicode */ - if (lp_unicode()) { + if (lp_unicode()) capabilities |= CAP_UNICODE; - } + + if (lp_nt_status_support()) + capabilities |= CAP_STATUS32; if (lp_host_msdfs()) capabilities |= CAP_DFS; - if (lp_security() >= SEC_USER) secword |= 1; - if (global_encrypted_passwords_negotiated) secword |= 2; + if (lp_security() >= SEC_USER) + secword |= 1; + if (global_encrypted_passwords_negotiated) + secword |= 2; set_message(outbuf,17,0,True); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 501f0e9ab0..d56b7fe622 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -828,8 +828,8 @@ int reply_ntcreate_and_X(connection_struct *conn, if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) smb_action |= EXTENDED_OPLOCK_GRANTED; -#if 1 /* JRATEST */ - /* W2K sends back 42 words here ! */ +#if 0 + /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */ set_message(outbuf,42,0,True); #else set_message(outbuf,34,0,True); @@ -1809,9 +1809,8 @@ due to being in oplock break state.\n" )); } } - if (Protocol >= PROTOCOL_NT1) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ - } + if (Protocol >= PROTOCOL_NT1) + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME); /* Now we must call the relevant NT_TRANS function */ switch(function_code) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c7f805122d..0a349a9c8a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -482,9 +482,8 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size put_dos_date3(outbuf,smb_vwv1,mtime); SIVAL(outbuf,smb_vwv3,(uint32)size); - if (Protocol >= PROTOCOL_NT1) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */ - } + if (Protocol >= PROTOCOL_NT1) + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); @@ -760,9 +759,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SCVAL(smb_buf(outbuf),0,5); SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); - if (Protocol >= PROTOCOL_NT1) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */ - } + if (Protocol >= PROTOCOL_NT1) + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); outsize += DIR_STRUCT_SIZE*numentries; smb_setlen(outbuf,outsize - 4); -- cgit From 276ff4df82313abcf09db2d373a4229a5b8db506 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 27 Feb 2002 23:51:25 +0000 Subject: this allows us to support foreign SIDs in winbindd and smbd this means "xcopy /o" has a chance of working with ACLs that contain ACEs that use SIDs that the Samba server has no knowledge of. It's a bit hackish, Tim, can you look at my uid.c changes? (This used to be commit fe2db3148587937aa7b674c1c99036d42a3776b3) --- source3/smbd/uid.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 3a939e4fce..f2b3bdbe6c 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -596,6 +596,11 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) *sidtype = SID_NAME_UNKNOWN; + +/* (tridge) I commented out the slab of code below in order to support foreign SIDs + Do we really need to validate the type of SID we have in this case? +*/ +#if 0 /* * First we must look up the name and decide if this is a user sid. */ @@ -616,7 +621,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) (unsigned int)name_type )); return False; } - +#endif *sidtype = SID_NAME_USER; /* @@ -658,7 +663,13 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", sid_to_string(sid_str, psid) )); - return local_sid_to_gid(pgid, psid, sidtype); + if (!local_sid_to_gid(pgid, psid, sidtype)) { + /* this was probably a foreign sid - assume its a group rid + and continue */ + name_type = SID_NAME_DOM_GRP; + } else { + return True; + } } /* -- cgit From d79e11ad6d4be78a4140d0f33acea702cbd1d944 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Mar 2002 01:24:30 +0000 Subject: Various comment fixes from Rafal Szczesniak (This used to be commit 3bf4b42771d115500941be374bfdd9b8c2fdba4a) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index bf1a1ca9a7..8c037b4706 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -818,7 +818,7 @@ set. Ignoring max smbd restriction.\n")); } /**************************************************************************** - process an smb from the client - split out from the process() code so + process an smb from the client - split out from the smbd_process() code so it can be used by the oplock break code. ****************************************************************************/ void process_smb(char *inbuf, char *outbuf) -- cgit From 0bc19c0bdbcfac2cad9029bcf36d3d00d82a074b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 2 Mar 2002 00:44:38 +0000 Subject: Fix lseek-on-pipe problem in VFS (where it belongs IMHO). Jeremy. (This used to be commit ebef2e7bc87fcbae794426c39044a7d23f43722d) --- source3/smbd/fileio.c | 14 +------------- source3/smbd/vfs-wrap.c | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 2aafd14c99..acbbb73352 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -36,19 +36,7 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos+offset,SEEK_SET); - /* - * We want to maintain the fiction that we can seek - * on a fifo for file system purposes. This allows - * people to set up UNIX fifo's that feed data to Windows - * applications. JRA. - */ - - if((seek_ret == -1) && (errno == ESPIPE)) { - seek_ret = pos+offset; - errno = 0; - } - - if((seek_ret == -1) || (seek_ret != pos+offset)) { + if(seek_ret == -1) { DEBUG(0,("seek_file: sys_lseek failed. Error was %s\n", strerror(errno) )); fsp->pos = -1; return -1; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 15d9572d1d..bb7d497274 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -225,13 +225,26 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) { - SMB_OFF_T result; + SMB_OFF_T result; - START_PROFILE(syscall_lseek); + START_PROFILE(syscall_lseek); - result = sys_lseek(filedes, offset, whence); - END_PROFILE(syscall_lseek); - return result; + result = sys_lseek(filedes, offset, whence); + + /* + * We want to maintain the fiction that we can seek + * on a fifo for file system purposes. This allows + * people to set up UNIX fifo's that feed data to Windows + * applications. JRA. + */ + + if((result == -1) && (errno == ESPIPE)) { + result = 0; + errno = 0; + } + + END_PROFILE(syscall_lseek); + return result; } int vfswrap_rename(connection_struct *conn, const char *old, const char *new) -- cgit From 076e879ac1ea1ccc33deed2b4b95534830a5832b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 4 Mar 2002 22:56:37 +0000 Subject: Canonicalise pathnames returned to Windows directory separators. Found by Andrew at connectathon with some new tests Jeremy. (This used to be commit 4aaa4f52b8fc712f5f879ae5c47ba4601281b4e8) --- source3/smbd/trans2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8e2bfd14b0..501057830a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1559,6 +1559,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pstrcpy(dos_fname, "\\"); } else { snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname); + string_replace( dos_fname, '/', '\\'); } switch (info_level) { -- cgit From 1d5fb7865d2a8441351668ea43b20a3b64ac232d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 5 Mar 2002 00:41:01 +0000 Subject: Fixed compiler warning about unused variables. (This used to be commit 7bb0dda8ee1d61a0e8448070f1a71fcd13be5d40) --- source3/smbd/uid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index f2b3bdbe6c..c3156b7b14 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -591,16 +591,16 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) { - fstring dom_name, name, sid_str; - enum SID_NAME_USE name_type; - - *sidtype = SID_NAME_UNKNOWN; - + fstring sid_str; /* (tridge) I commented out the slab of code below in order to support foreign SIDs Do we really need to validate the type of SID we have in this case? */ #if 0 + fstring dom_name, name; + enum SID_NAME_USE name_type; + + *sidtype = SID_NAME_UNKNOWN; /* * First we must look up the name and decide if this is a user sid. */ -- cgit From 5d1db25abd340c2c689f913788911b3a2f411b38 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Mar 2002 01:43:50 +0000 Subject: Mask off the aDIR on setfileinfo. Jeremy. (This used to be commit d9cb1bf20ac8a739102b03d9a70e34fe5cb2f0f7) --- source3/smbd/dosmode.c | 2 ++ source3/smbd/reply.c | 3 +++ source3/smbd/trans2.c | 5 +++++ 3 files changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 6750649eff..dcffe3aa90 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -195,6 +195,8 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * if (S_ISDIR(st->st_mode)) dosmode |= aDIR; + else + dosmode &= ~aDIR; if (dos_mode(conn,fname,st) == dosmode) return(0); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0a349a9c8a..0de0e15274 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -517,6 +517,9 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (VALID_STAT_OF_DIR(sbuf)) mode |= aDIR; + else + mode &= ~aDIR; + if (check_name(fname,conn)) ok = (file_chmod(conn,fname,mode,NULL) == 0); if (ok) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 501057830a..d08e3419f9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2225,6 +2225,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(6,("size: %.0f ", (double)size)); DEBUG(6,("mode: %x\n" , mode)); + if (S_ISDIR(sbuf.st_mode)) + mode |= aDIR; + else + mode &= ~aDIR; + if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || (info_level == SMB_SET_FILE_ALLOCATION_INFO) || (info_level == SMB_FILE_ALLOCATION_INFORMATION) || -- cgit From 095b903325bc6c54a0c7406cac2f48103805c73c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Mar 2002 21:37:50 +0000 Subject: Added Herb's fix to override log level from command line. Jeremy. (This used to be commit 439839be99e6e418eb5782a2fe0630d0ef5fb3c5) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 50f09cf6e6..02f52e2392 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -589,6 +589,7 @@ static void usage(char *pname) int main(int argc,char *argv[]) { extern BOOL append_log; + extern BOOL AllowDebugChange; extern char *optarg; /* shall I run as a daemon */ BOOL is_daemon = False; @@ -645,6 +646,7 @@ static void usage(char *pname) DEBUGLEVEL = 10000; else DEBUGLEVEL = atoi(optarg); + AllowDebugChange = False; break; case 'p': -- cgit From 9361708b20483f1090349e51090e7276985cf0be Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Mar 2002 03:50:09 +0000 Subject: Reformat preparing for changes to come... Jeremy. (This used to be commit b56df25d48a7adaa49b0bd44f8ff7be81b970da2) --- source3/smbd/nttrans.c | 310 ++++++++++++++++++++++++------------------------- 1 file changed, 155 insertions(+), 155 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d56b7fe622..e8bfe9948d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -46,10 +46,10 @@ static char *known_nt_pipes[] = { /* Map generic permissions to file object specific permissions */ struct generic_mapping file_generic_mapping = { - FILE_GENERIC_READ, - FILE_GENERIC_WRITE, - FILE_GENERIC_EXECUTE, - FILE_GENERIC_ALL + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_GENERIC_ALL }; /**************************************************************************** @@ -256,17 +256,17 @@ static BOOL saved_short_case_preserve; static void set_posix_case_semantics(uint32 file_attributes) { - if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) - return; + if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) + return; - saved_case_sensitive = case_sensitive; - saved_case_preserve = case_preserve; - saved_short_case_preserve = short_case_preserve; + saved_case_sensitive = case_sensitive; + saved_case_preserve = case_preserve; + saved_short_case_preserve = short_case_preserve; - /* Set to POSIX. */ - case_sensitive = True; - case_preserve = True; - short_case_preserve = True; + /* Set to POSIX. */ + case_sensitive = True; + case_preserve = True; + short_case_preserve = True; } /**************************************************************************** @@ -275,12 +275,12 @@ static void set_posix_case_semantics(uint32 file_attributes) static void restore_case_semantics(uint32 file_attributes) { - if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) - return; + if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) + return; - case_sensitive = saved_case_sensitive; - case_preserve = saved_case_preserve; - short_case_preserve = saved_short_case_preserve; + case_sensitive = saved_case_sensitive; + case_preserve = saved_case_preserve; + short_case_preserve = saved_short_case_preserve; } /**************************************************************************** @@ -289,40 +289,40 @@ static void restore_case_semantics(uint32 file_attributes) static int map_create_disposition( uint32 create_disposition) { - int ret; - - switch( create_disposition ) { - case FILE_CREATE: - /* create if not exist, fail if exist */ - ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL); - break; - case FILE_SUPERSEDE: - case FILE_OVERWRITE_IF: - /* create if not exist, trunc if exist */ - ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); - break; - case FILE_OPEN: - /* fail if not exist, open if exists */ - ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN); - break; - case FILE_OPEN_IF: - /* create if not exist, open if exists */ - ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_OPEN); - break; - case FILE_OVERWRITE: - /* fail if not exist, truncate if exists */ - ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); - break; - default: - DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n", - create_disposition )); - return -1; - } + int ret; - DEBUG(10,("map_create_disposition: Mapped create_disposition 0x%lx to 0x%x\n", - (unsigned long)create_disposition, ret )); + switch( create_disposition ) { + case FILE_CREATE: + /* create if not exist, fail if exist */ + ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL); + break; + case FILE_SUPERSEDE: + case FILE_OVERWRITE_IF: + /* create if not exist, trunc if exist */ + ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); + break; + case FILE_OPEN: + /* fail if not exist, open if exists */ + ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN); + break; + case FILE_OPEN_IF: + /* create if not exist, open if exists */ + ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_OPEN); + break; + case FILE_OVERWRITE: + /* fail if not exist, truncate if exists */ + ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); + break; + default: + DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n", + create_disposition )); + return -1; + } - return ret; + DEBUG(10,("map_create_disposition: Mapped create_disposition 0x%lx to 0x%x\n", + (unsigned long)create_disposition, ret )); + + return ret; } /**************************************************************************** @@ -330,133 +330,133 @@ static int map_create_disposition( uint32 create_disposition) ****************************************************************************/ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_options, - uint32 desired_access, uint32 share_access, uint32 file_attributes) + uint32 desired_access, uint32 share_access, uint32 file_attributes) { - int smb_open_mode = -1; + int smb_open_mode = -1; - *pstat_open_only = False; + *pstat_open_only = False; - /* - * Convert GENERIC bits to specific bits. - */ + /* + * Convert GENERIC bits to specific bits. + */ - se_map_generic(&desired_access, &file_generic_mapping); - - switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) { - case FILE_READ_DATA: - smb_open_mode = DOS_OPEN_RDONLY; - break; - case FILE_WRITE_DATA: - case FILE_APPEND_DATA: - case FILE_WRITE_DATA|FILE_APPEND_DATA: - smb_open_mode = DOS_OPEN_WRONLY; - break; - case FILE_READ_DATA|FILE_WRITE_DATA: - case FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA: - case FILE_READ_DATA|FILE_APPEND_DATA: - smb_open_mode = DOS_OPEN_RDWR; - break; - } + se_map_generic(&desired_access, &file_generic_mapping); - /* - * NB. For DELETE_ACCESS we should really check the - * directory permissions, as that is what controls - * delete, and for WRITE_DAC_ACCESS we should really - * check the ownership, as that is what controls the - * chmod. Note that this is *NOT* a security hole (this - * note is for you, Andrew) as we are not *allowing* - * the access at this point, the actual unlink or - * chown or chmod call would do this. We are just helping - * clients out by telling them if they have a hope - * of any of this succeeding. POSIX acls may still - * deny the real call. JRA. - */ + switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) { + case FILE_READ_DATA: + smb_open_mode = DOS_OPEN_RDONLY; + break; + case FILE_WRITE_DATA: + case FILE_APPEND_DATA: + case FILE_WRITE_DATA|FILE_APPEND_DATA: + smb_open_mode = DOS_OPEN_WRONLY; + break; + case FILE_READ_DATA|FILE_WRITE_DATA: + case FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA: + case FILE_READ_DATA|FILE_APPEND_DATA: + smb_open_mode = DOS_OPEN_RDWR; + break; + } - if (smb_open_mode == -1) { + /* + * NB. For DELETE_ACCESS we should really check the + * directory permissions, as that is what controls + * delete, and for WRITE_DAC_ACCESS we should really + * check the ownership, as that is what controls the + * chmod. Note that this is *NOT* a security hole (this + * note is for you, Andrew) as we are not *allowing* + * the access at this point, the actual unlink or + * chown or chmod call would do this. We are just helping + * clients out by telling them if they have a hope + * of any of this succeeding. POSIX acls may still + * deny the real call. JRA. + */ - if(desired_access == WRITE_DAC_ACCESS || desired_access == READ_CONTROL_ACCESS) - *pstat_open_only = True; + if (smb_open_mode == -1) { - if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| - FILE_EXECUTE|FILE_READ_ATTRIBUTES| - FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| - FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) { - smb_open_mode = DOS_OPEN_RDONLY; - } else if(desired_access == 0) { + if(desired_access == WRITE_DAC_ACCESS || desired_access == READ_CONTROL_ACCESS) + *pstat_open_only = True; - /* - * JRA - NT seems to sometimes send desired_access as zero. play it safe - * and map to a stat open. - */ + if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| + FILE_EXECUTE|FILE_READ_ATTRIBUTES| + FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| + FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) { + smb_open_mode = DOS_OPEN_RDONLY; + } else if(desired_access == 0) { - *pstat_open_only = True; - smb_open_mode = DOS_OPEN_RDONLY; + /* + * JRA - NT seems to sometimes send desired_access as zero. play it safe + * and map to a stat open. + */ - } else { - DEBUG(0,("map_share_mode: Incorrect value 0x%lx for desired_access to file %s\n", - (unsigned long)desired_access, fname)); - return -1; - } - } + *pstat_open_only = True; + smb_open_mode = DOS_OPEN_RDONLY; - /* - * Set the special bit that means allow share delete. - * This is held outside the normal share mode bits at 1<<15. - * JRA. - */ + } else { + DEBUG(0,("map_share_mode: Incorrect value 0x%lx for desired_access to file %s\n", + (unsigned long)desired_access, fname)); + return -1; + } + } - if(share_access & FILE_SHARE_DELETE) { - smb_open_mode |= ALLOW_SHARE_DELETE; - DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode)); - } + /* + * Set the special bit that means allow share delete. + * This is held outside the normal share mode bits at 1<<15. + * JRA. + */ - /* - * We need to store the intent to open for Delete. This - * is what determines if a delete on close flag can be set. - * This is the wrong way (and place) to store this, but for 2.2 this - * is the only practical way. JRA. - */ + if(share_access & FILE_SHARE_DELETE) { + smb_open_mode |= ALLOW_SHARE_DELETE; + DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode)); + } - if(desired_access & DELETE_ACCESS) { - smb_open_mode |= DELETE_ACCESS_REQUESTED; - DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); - } + /* + * We need to store the intent to open for Delete. This + * is what determines if a delete on close flag can be set. + * This is the wrong way (and place) to store this, but for 2.2 this + * is the only practical way. JRA. + */ - if (create_options & FILE_DELETE_ON_CLOSE) { - /* Implicit delete access requested... */ - smb_open_mode |= DELETE_ACCESS_REQUESTED; - smb_open_mode |= DELETE_ON_CLOSE_FLAG; - DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode)); - } + if(desired_access & DELETE_ACCESS) { + smb_open_mode |= DELETE_ACCESS_REQUESTED; + DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); + } - /* Add in the requested share mode. */ - switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) { - case FILE_SHARE_READ: - smb_open_mode |= SET_DENY_MODE(DENY_WRITE); - break; - case FILE_SHARE_WRITE: - smb_open_mode |= SET_DENY_MODE(DENY_READ); - break; - case (FILE_SHARE_READ|FILE_SHARE_WRITE): - smb_open_mode |= SET_DENY_MODE(DENY_NONE); - break; - case FILE_SHARE_NONE: - smb_open_mode |= SET_DENY_MODE(DENY_ALL); - break; - } + if (create_options & FILE_DELETE_ON_CLOSE) { + /* Implicit delete access requested... */ + smb_open_mode |= DELETE_ACCESS_REQUESTED; + smb_open_mode |= DELETE_ON_CLOSE_FLAG; + DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode)); + } - /* - * Handle an O_SYNC request. - */ + /* Add in the requested share mode. */ + switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) { + case FILE_SHARE_READ: + smb_open_mode |= SET_DENY_MODE(DENY_WRITE); + break; + case FILE_SHARE_WRITE: + smb_open_mode |= SET_DENY_MODE(DENY_READ); + break; + case (FILE_SHARE_READ|FILE_SHARE_WRITE): + smb_open_mode |= SET_DENY_MODE(DENY_NONE); + break; + case FILE_SHARE_NONE: + smb_open_mode |= SET_DENY_MODE(DENY_ALL); + break; + } + + /* + * Handle an O_SYNC request. + */ - if(file_attributes & FILE_FLAG_WRITE_THROUGH) - smb_open_mode |= FILE_SYNC_OPENMODE; + if(file_attributes & FILE_FLAG_WRITE_THROUGH) + smb_open_mode |= FILE_SYNC_OPENMODE; - DEBUG(10,("map_share_mode: Mapped desired access 0x%lx, share access 0x%lx, file attributes 0x%lx \ + DEBUG(10,("map_share_mode: Mapped desired access 0x%lx, share access 0x%lx, file attributes 0x%lx \ to open_mode 0x%x\n", (unsigned long)desired_access, (unsigned long)share_access, - (unsigned long)file_attributes, smb_open_mode )); + (unsigned long)file_attributes, smb_open_mode )); - return smb_open_mode; + return smb_open_mode; } /**************************************************************************** -- cgit From 11c0e88d9ef1728a4cfe518d85bb4cd3678edc43 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Mar 2002 04:21:12 +0000 Subject: Fixed delete on close semantics - preparing for share mode rewrite. Jeremy. (This used to be commit 25dd73be29bbf0a080fe0bcbe5c478545d1e8db7) --- source3/smbd/nttrans.c | 25 ++++++++++++------------- source3/smbd/open.c | 2 ++ 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e8bfe9948d..062047b6bd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -330,7 +330,7 @@ static int map_create_disposition( uint32 create_disposition) ****************************************************************************/ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_options, - uint32 desired_access, uint32 share_access, uint32 file_attributes) + uint32 *desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode = -1; @@ -340,9 +340,9 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt * Convert GENERIC bits to specific bits. */ - se_map_generic(&desired_access, &file_generic_mapping); + se_map_generic(desired_access, &file_generic_mapping); - switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) { + switch( *desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) { case FILE_READ_DATA: smb_open_mode = DOS_OPEN_RDONLY; break; @@ -374,15 +374,15 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt if (smb_open_mode == -1) { - if(desired_access == WRITE_DAC_ACCESS || desired_access == READ_CONTROL_ACCESS) + if(*desired_access == WRITE_DAC_ACCESS || *desired_access == READ_CONTROL_ACCESS) *pstat_open_only = True; - if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| + if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| FILE_EXECUTE|FILE_READ_ATTRIBUTES| FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) { smb_open_mode = DOS_OPEN_RDONLY; - } else if(desired_access == 0) { + } else if(*desired_access == 0) { /* * JRA - NT seems to sometimes send desired_access as zero. play it safe @@ -394,7 +394,7 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt } else { DEBUG(0,("map_share_mode: Incorrect value 0x%lx for desired_access to file %s\n", - (unsigned long)desired_access, fname)); + (unsigned long)*desired_access, fname)); return -1; } } @@ -417,14 +417,13 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt * is the only practical way. JRA. */ - if(desired_access & DELETE_ACCESS) { + if(*desired_access & DELETE_ACCESS) { smb_open_mode |= DELETE_ACCESS_REQUESTED; DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); } if (create_options & FILE_DELETE_ON_CLOSE) { - /* Implicit delete access requested... */ - smb_open_mode |= DELETE_ACCESS_REQUESTED; + /* Implicit delete access is *NOT* requested... */ smb_open_mode |= DELETE_ON_CLOSE_FLAG; DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode)); } @@ -453,7 +452,7 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt smb_open_mode |= FILE_SYNC_OPENMODE; DEBUG(10,("map_share_mode: Mapped desired access 0x%lx, share access 0x%lx, file attributes 0x%lx \ -to open_mode 0x%x\n", (unsigned long)desired_access, (unsigned long)share_access, +to open_mode 0x%x\n", (unsigned long)*desired_access, (unsigned long)share_access, (unsigned long)file_attributes, smb_open_mode )); return smb_open_mode; @@ -656,7 +655,7 @@ int reply_ntcreate_and_X(connection_struct *conn, */ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - if((smb_open_mode = map_share_mode(&stat_open_only, fname, create_options, desired_access, + if((smb_open_mode = map_share_mode(&stat_open_only, fname, create_options, &desired_access, share_access, file_attributes)) == -1) { END_PROFILE(SMBntcreateX); @@ -1166,7 +1165,7 @@ static int call_nt_transact_create(connection_struct *conn, * and the share access. */ - if((smb_open_mode = map_share_mode( &stat_open_only, fname, create_options, desired_access, + if((smb_open_mode = map_share_mode( &stat_open_only, fname, create_options, &desired_access, share_access, file_attributes)) == -1) return ERROR_DOS(ERRDOS,ERRbadaccess); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7396233c26..03646c5019 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -941,6 +941,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + /* Remember to delete the mode we just added. */ + del_share_mode(fsp, NULL); unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); -- cgit From 39e14916e48a5290e7766aa4f845900365bb42c3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 7 Mar 2002 18:53:37 +0000 Subject: get the right return code for batch vs exclusive oplocks (This used to be commit 91fc5b2de577019d7646f3c29173b27605d9ba12) --- source3/smbd/nttrans.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 062047b6bd..d9b90c14cb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -663,7 +663,9 @@ int reply_ntcreate_and_X(connection_struct *conn, } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + } /* * Ordinary file or directory. @@ -841,12 +843,17 @@ int reply_ntcreate_and_X(connection_struct *conn, * exclusive & batch here. */ - if (smb_action & EXTENDED_OPLOCK_GRANTED) - SCVAL(p,0, BATCH_OPLOCK_RETURN); - else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + if (smb_action & EXTENDED_OPLOCK_GRANTED) { + if (flags & REQUEST_BATCH_OPLOCK) { + SCVAL(p,0, BATCH_OPLOCK_RETURN); + } else { + SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN); + } + } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); - else + } else { SCVAL(p,0,NO_OPLOCK_RETURN); + } p++; SSVAL(p,0,fsp->fnum); -- cgit From e69f020d3dcba8e4dfdaba9b89ff834d43eb2afd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 9 Mar 2002 19:38:47 +0000 Subject: a more informitive debug message when a SID can't be validated (This used to be commit c55737fb25dfed4697b93a600e3bd770f84bf464) --- source3/smbd/posix_acls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7d2eff8066..ee1935a41f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -439,7 +439,8 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); if (!sid_to_uid( &owner_sid, puser, &sid_type)) { - DEBUG(3,("unpack_nt_owners: unable to validate owner sid.\n")); + DEBUG(3,("unpack_nt_owners: unable to validate owner sid for %s\n", + sid_string_static(&owner_sid))); return False; } } -- cgit From 0843c37abd0a1520fc3117f91fc6284d9475c87e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Mar 2002 23:18:44 +0000 Subject: failed timed locks always give LOCK_CONFLICT not LOCK_NOT_GRANTED (This used to be commit ec71c1a66f9fd4b9cb4cad5a9b5b17e20de7aeb1) --- source3/smbd/blocking.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 024e5b9f66..bc8c54caf7 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -175,6 +175,12 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat char *inbuf = blr->inbuf; construct_reply_common(inbuf, outbuf); + /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to + FILE_LOCK_CONFLICT! (tridge) */ + if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { + status = NT_STATUS_FILE_LOCK_CONFLICT; + } + ERROR_NT(status); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("generic_blocking_lock_error: send_smb failed."); -- cgit From 57970fd4e29ec6d90540049147e763bd69ee9e04 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Mar 2002 01:34:14 +0000 Subject: make sure we give an error for unknown lockingX locktype bits (This used to be commit 72cb43b912a4c1831f9d7b2fd23ce51aebb09c8f) --- source3/smbd/reply.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0de0e15274..9d5d34e410 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3722,6 +3722,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, CHECK_FSP(fsp,conn); data = smb_buf(inbuf); + + if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) { + /* we don't support these - and CANCEL_LOCK makes w2k + and XP reboot so I don't really want to be + compatible! (tridge) */ + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } /* Check if this is an oplock break on a file we have granted an oplock on. -- cgit From db4c62d7ed2eb5503927edf7e25c5a2fc94f4174 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Mar 2002 21:57:12 +0000 Subject: Implemented default ACL patch (set inherit acls = true on a per share basis). Based on code donated by Olaf Fr±czyk . Further commit will change to sending via vfs interface. Jeremy. (This used to be commit d85133e2697eb22f1573c78447b57791ae63dd6b) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/open.c | 14 ++++++++++++-- source3/smbd/posix_acls.c | 13 +++++++++++++ source3/smbd/vfs-wrap.c | 18 +++++++++++------- 3 files changed, 36 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 03646c5019..b284175302 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -646,6 +646,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; + BOOL def_acl = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; @@ -800,6 +801,14 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ } + /* + * Ensure we pay attention to default ACLs on directories if required. + */ + + if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && + (def_acl = directory_has_default_acl(parent_dirname(fname)))) + mode = 0777; + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); @@ -951,10 +960,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } /* - * Take care of inherited ACLs on created files. JRA. + * Take care of inherited ACLs on created files - if default ACL not + * selected. */ - if (!file_existed && (conn->vfs_ops.fchmod_acl != NULL)) { + if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ee1935a41f..34f0b77002 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2294,3 +2294,16 @@ int fchmod_acl(int fd, mode_t mode) sys_acl_free_acl(posix_acl); return ret; } + +BOOL directory_has_default_acl(const char *fname) +{ + SMB_ACL_T dir_acl = sys_acl_get_file( fname, SMB_ACL_TYPE_DEFAULT); + BOOL has_acl = False; + SMB_ACL_ENTRY_T entry; + + if (dir_acl != NULL && (sys_acl_get_entry(dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) + has_acl = True; + + sys_acl_free_acl(dir_acl); + return has_acl; +} diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index bb7d497274..78c6fb3905 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -94,19 +94,23 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) { - int result; + int result; + BOOL has_dacl = False; - START_PROFILE(syscall_mkdir); + START_PROFILE(syscall_mkdir); #ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_mkdir()\n"); - } + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_mkdir()\n"); + } #endif - result = mkdir(path, mode); + if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(parent_dirname(path)))) + mode = 0777; + + result = mkdir(path, mode); - if (result == 0) { + if (result == 0 && !has_dacl) { /* * We need to do this as the default behavior of POSIX ACLs * is to set the mask to be the requested group permission -- cgit From 3bb219161a270f12c27c3bc7e1220829c6e9f284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Mar 2002 00:08:08 +0000 Subject: Added POSIX ACL layer into the vfs. Jeremy. (This used to be commit 7d59445b6962547a8938928a9371651a09e26516) --- source3/smbd/open.c | 2 +- source3/smbd/posix_acls.c | 124 ++++++++++++++++++++++++---------------------- source3/smbd/vfs-wrap.c | 116 +++++++++++++++++++++++++++++++++++++++++-- source3/smbd/vfs.c | 25 +++++++++- 4 files changed, 202 insertions(+), 65 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b284175302..b86d9763a4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -806,7 +806,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && - (def_acl = directory_has_default_acl(parent_dirname(fname)))) + (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) mode = 0777; DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 34f0b77002..9c8835214f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -153,13 +153,13 @@ static void print_canon_ace_list(const char *name, canon_ace *ace_list) Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits). ****************************************************************************/ -static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset) +static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET_T permset) { mode_t ret = 0; - ret |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRUSR : 0); - ret |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWUSR : 0); - ret |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); + ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0); + ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0); + ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); return ret; } @@ -187,20 +187,20 @@ static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x an SMB_ACL_PERMSET_T. ****************************************************************************/ -static int map_acl_perms_to_permset(mode_t mode, SMB_ACL_PERMSET_T *p_permset) +static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset) { - if (sys_acl_clear_perms(*p_permset) == -1) + if (conn->vfs_ops.sys_acl_clear_perms(conn, *p_permset) == -1) return -1; if (mode & S_IRUSR) { - if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1) + if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_READ) == -1) return -1; } if (mode & S_IWUSR) { - if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1) + if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_WRITE) == -1) return -1; } if (mode & S_IXUSR) { - if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1) + if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_EXECUTE) == -1) return -1; } return 0; @@ -1425,6 +1425,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ DOM_SID *powner, DOM_SID *pgroup) { extern DOM_SID global_sid_World; + connection_struct *conn = fsp->conn; mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); canon_ace *list_head = NULL; canon_ace *ace = NULL; @@ -1433,7 +1434,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ SMB_ACL_ENTRY_T entry; size_t ace_count; - while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) { + while ( posix_acl && (conn->vfs_ops.sys_acl_get_entry(conn, posix_acl, entry_id, &entry) == 1)) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; DOM_SID sid; @@ -1445,10 +1446,10 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ - if (sys_acl_get_tag_type(entry, &tagtype) == -1) + if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) continue; - if (sys_acl_get_permset(entry, &permset) == -1) + if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) continue; /* Decide which SID to use based on the ACL type. */ @@ -1461,7 +1462,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_USER: { - uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry); + uid_t *puid = (uid_t *)conn->vfs_ops.sys_acl_get_qualifier(conn, entry); if (puid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get uid.\n")); continue; @@ -1469,7 +1470,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; - sys_acl_free_qualifier((void *)puid,tagtype); + conn->vfs_ops.sys_acl_free_qualifier(conn, (void *)puid,tagtype); break; } case SMB_ACL_GROUP_OBJ: @@ -1480,7 +1481,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_GROUP: { - gid_t *pgid = (gid_t *)sys_acl_get_qualifier(entry); + gid_t *pgid = (gid_t *)conn->vfs_ops.sys_acl_get_qualifier(conn, entry); if (pgid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get gid.\n")); continue; @@ -1488,11 +1489,11 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ gid_to_sid( &sid, *pgid); unix_ug.gid = *pgid; owner_type = GID_ACE; - sys_acl_free_qualifier((void *)pgid,tagtype); + conn->vfs_ops.sys_acl_free_qualifier(conn, (void *)pgid,tagtype); break; } case SMB_ACL_MASK: - acl_mask = convert_permset_to_mode_t(permset); + acl_mask = convert_permset_to_mode_t(conn, permset); continue; /* Don't count the mask as an entry. */ case SMB_ACL_OTHER: /* Use the Everyone SID */ @@ -1514,7 +1515,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ ZERO_STRUCTP(ace); ace->type = tagtype; - ace->perms = convert_permset_to_mode_t(permset); + ace->perms = convert_permset_to_mode_t(conn, permset); ace->attr = ALLOW_ACE; ace->trustee = sid; ace->unix_ug = unix_ug; @@ -1571,8 +1572,9 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, BOOL *pacl_set_support) { + connection_struct *conn = fsp->conn; BOOL ret = False; - SMB_ACL_T the_acl = sys_acl_init((int)count_canon_ace_list(the_ace) + 1); + SMB_ACL_T the_acl = conn->vfs_ops.sys_acl_init(conn, (int)count_canon_ace_list(the_ace) + 1); canon_ace *p_ace; int i; SMB_ACL_ENTRY_T mask_entry; @@ -1601,7 +1603,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Get the entry for this ACE. */ - if (sys_acl_create_entry( &the_acl, &the_entry) == -1) { + if (conn->vfs_ops.sys_acl_create_entry(conn, &the_acl, &the_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1622,7 +1624,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * First tell the entry what type of ACE this is. */ - if (sys_acl_set_tag_type(the_entry, p_ace->type) == -1) { + if (conn->vfs_ops.sys_acl_set_tag_type(conn, the_entry, p_ace->type) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1634,7 +1636,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) { - if (sys_acl_set_qualifier(the_entry,(void *)&p_ace->unix_ug.uid) == -1) { + if (conn->vfs_ops.sys_acl_set_qualifier(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1645,13 +1647,13 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Convert the mode_t perms in the canon_ace to a POSIX permset. */ - if (sys_acl_get_permset(the_entry, &the_permset) == -1) { + if (conn->vfs_ops.sys_acl_get_permset(conn, the_entry, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; } - if (map_acl_perms_to_permset(p_ace->perms, &the_permset) == -1) { + if (map_acl_perms_to_permset(conn, p_ace->perms, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n", (unsigned int)p_ace->perms, i, strerror(errno) )); goto done; @@ -1661,7 +1663,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * ..and apply them to the entry. */ - if (sys_acl_set_permset(the_entry, the_permset) == -1) { + if (conn->vfs_ops.sys_acl_set_permset(conn, the_entry, the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1675,27 +1677,27 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Add in a mask of rwx. */ - if (sys_acl_create_entry( &the_acl, &mask_entry) == -1) { + if (conn->vfs_ops.sys_acl_create_entry( conn, &the_acl, &mask_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); goto done; } - if (sys_acl_set_tag_type(mask_entry, SMB_ACL_MASK) == -1) { + if (conn->vfs_ops.sys_acl_set_tag_type(conn, mask_entry, SMB_ACL_MASK) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); goto done; } - if (sys_acl_get_permset(mask_entry, &mask_permset) == -1) { + if (conn->vfs_ops.sys_acl_get_permset(conn, mask_entry, &mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); goto done; } - if (map_acl_perms_to_permset(S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) { + if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) )); goto done; } - if (sys_acl_set_permset(mask_entry, mask_permset) == -1) { + if (conn->vfs_ops.sys_acl_set_permset(conn, mask_entry, mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); goto done; } @@ -1704,7 +1706,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Check if the ACL is valid. */ - if (sys_acl_valid(the_acl) == -1) { + if (conn->vfs_ops.sys_acl_valid(conn, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", strerror(errno) )); @@ -1716,7 +1718,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if(default_ace || fsp->is_directory || fsp->fd == -1) { - if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) { + if (conn->vfs_ops.sys_acl_set_file(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -1729,7 +1731,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } } else { - if (sys_acl_set_fd(fsp->fd, the_acl) == -1) { + if (conn->vfs_ops.sys_acl_set_fd(fsp, fsp->fd, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -1747,7 +1749,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau done: if (the_acl != NULL) - sys_acl_free_acl(the_acl); + conn->vfs_ops.sys_acl_free_acl(conn, the_acl); return ret; } @@ -1846,6 +1848,7 @@ static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2) size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { + connection_struct *conn = fsp->conn; SMB_STRUCT_STAT sbuf; SEC_ACE *nt_ace_list = NULL; DOM_SID owner_sid; @@ -1874,14 +1877,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * Get the ACL from the path. */ - posix_acl = sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS); + posix_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); /* * If it's a directory get the default POSIX ACL. */ if(fsp->is_directory) - dir_acl = sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + dir_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); } else { @@ -1892,7 +1895,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) /* * Get the ACL from the fd. */ - posix_acl = sys_acl_get_fd(fsp->fd); + posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fsp->fd); } DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", @@ -1983,9 +1986,9 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) done: if (posix_acl) - sys_acl_free_acl(posix_acl); + conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); if (dir_acl) - sys_acl_free_acl(dir_acl); + conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); SAFE_FREE(nt_ace_list); @@ -2138,7 +2141,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * No default ACL - delete one if it exists. */ - if (sys_acl_delete_def_file(fsp->fsp_name) == -1) { + if (conn->vfs_ops.sys_acl_delete_def_file(conn, fsp->fsp_name) == -1) { DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); return False; @@ -2188,13 +2191,13 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) and set the mask to rwx. Needed to preserve complex ACLs set by NT. ****************************************************************************/ -static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) +static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mode_t mode) { int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; int num_entries = 0; - while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) { + while ( conn->vfs_ops.sys_acl_get_entry(conn, posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; mode_t perms; @@ -2203,10 +2206,10 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) if (entry_id == SMB_ACL_FIRST_ENTRY) entry_id = SMB_ACL_NEXT_ENTRY; - if (sys_acl_get_tag_type(entry, &tagtype) == -1) + if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) return -1; - if (sys_acl_get_permset(entry, &permset) == -1) + if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) return -1; num_entries++; @@ -2228,10 +2231,10 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) continue; } - if (map_acl_perms_to_permset(perms, &permset) == -1) + if (map_acl_perms_to_permset(conn, perms, &permset) == -1) return -1; - if (sys_acl_set_permset(entry, permset) == -1) + if (conn->vfs_ops.sys_acl_set_permset(conn, entry, permset) == -1) return -1; } @@ -2252,22 +2255,22 @@ static int chmod_acl_internals( SMB_ACL_T posix_acl, mode_t mode) Note that name is in UNIX character set. ****************************************************************************/ -int chmod_acl(const char *name, mode_t mode) +int chmod_acl(connection_struct *conn, const char *name, mode_t mode) { SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS)) == NULL) + if ((posix_acl = conn->vfs_ops.sys_acl_get_file(conn, name, SMB_ACL_TYPE_ACCESS)) == NULL) return -1; - if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) + if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = sys_acl_set_file(name, SMB_ACL_TYPE_ACCESS, posix_acl); + ret = conn->vfs_ops.sys_acl_set_file(conn, name, SMB_ACL_TYPE_ACCESS, posix_acl); done: - sys_acl_free_acl(posix_acl); + conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); return ret; } @@ -2276,34 +2279,35 @@ int chmod_acl(const char *name, mode_t mode) and set the mask to rwx. Needed to preserve complex ACLs set by NT. ****************************************************************************/ -int fchmod_acl(int fd, mode_t mode) +int fchmod_acl(files_struct *fsp, int fd, mode_t mode) { + connection_struct *conn = fsp->conn; SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = sys_acl_get_fd(fd)) == NULL) + if ((posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fd)) == NULL) return -1; - if ((ret = chmod_acl_internals(posix_acl, mode)) == -1) + if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = sys_acl_set_fd(fd, posix_acl); + ret = conn->vfs_ops.sys_acl_set_fd(fsp, fd, posix_acl); done: - sys_acl_free_acl(posix_acl); + conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); return ret; } -BOOL directory_has_default_acl(const char *fname) +BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { - SMB_ACL_T dir_acl = sys_acl_get_file( fname, SMB_ACL_TYPE_DEFAULT); + SMB_ACL_T dir_acl = conn->vfs_ops.sys_acl_get_file( conn, fname, SMB_ACL_TYPE_DEFAULT); BOOL has_acl = False; SMB_ACL_ENTRY_T entry; - if (dir_acl != NULL && (sys_acl_get_entry(dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) + if (dir_acl != NULL && (conn->vfs_ops.sys_acl_get_entry(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) has_acl = True; - sys_acl_free_acl(dir_acl); + conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); return has_acl; } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 78c6fb3905..73b070d3f8 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -105,7 +105,7 @@ int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) } #endif - if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(parent_dirname(path)))) + if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path)))) mode = 0777; result = mkdir(path, mode); @@ -744,7 +744,7 @@ int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode) int result; START_PROFILE(chmod_acl); - result = chmod_acl(name, mode); + result = chmod_acl(conn, name, mode); END_PROFILE(chmod_acl); return result; } @@ -754,7 +754,117 @@ int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode) int result; START_PROFILE(fchmod_acl); - result = fchmod_acl(fd, mode); + result = fchmod_acl(fsp, fd, mode); END_PROFILE(fchmod_acl); return result; } + +int vfswrap_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + return sys_acl_get_entry(theacl, entry_id, entry_p); +} + +int vfswrap_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +{ + return sys_acl_get_tag_type(entry_d, tag_type_p); +} + +int vfswrap_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + return sys_acl_get_permset(entry_d, permset_p); +} + +void * vfswrap_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d) +{ + return sys_acl_get_qualifier(entry_d); +} + +SMB_ACL_T vfswrap_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) +{ + return sys_acl_get_file(path_p, type); +} + +SMB_ACL_T vfswrap_sys_acl_get_fd(struct files_struct *fsp, int fd) +{ + return sys_acl_get_fd(fd); +} + +int vfswrap_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset) +{ + return sys_acl_clear_perms(permset); +} + +int vfswrap_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return sys_acl_add_perm(permset, perm); +} + +char * vfswrap_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) +{ + return sys_acl_to_text(theacl, plen); +} + +SMB_ACL_T vfswrap_sys_acl_init(struct connection_struct *conn, int count) +{ + return sys_acl_init(count); +} + +int vfswrap_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +{ + return sys_acl_create_entry(pacl, pentry); +} + +int vfswrap_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +{ + return sys_acl_set_tag_type(entry, tagtype); +} + +int vfswrap_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) +{ + return sys_acl_set_qualifier(entry, qual); +} + +int vfswrap_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +{ + return sys_acl_set_permset(entry, permset); +} + +int vfswrap_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl ) +{ + return sys_acl_valid(theacl ); +} + +int vfswrap_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + return sys_acl_set_file(name, acltype, theacl); +} + +int vfswrap_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl) +{ + return sys_acl_set_fd(fd, theacl); +} + +int vfswrap_sys_acl_delete_def_file(struct connection_struct *conn, const char *path) +{ + return sys_acl_delete_def_file(path); +} + +int vfswrap_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return sys_acl_get_perm(permset, perm); +} + +int vfswrap_sys_acl_free_text(struct connection_struct *conn, char *text) +{ + return sys_acl_free_text(text); +} + +int vfswrap_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl) +{ + return sys_acl_free_acl(posix_acl); +} + +int vfswrap_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) +{ + return sys_acl_free_qualifier(qualifier, tagtype); +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index c0e775268c..ac342d0820 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -79,13 +79,36 @@ static struct vfs_ops default_vfs_ops = { vfswrap_fset_nt_acl, vfswrap_set_nt_acl, + /* POSIX ACL operations. */ #if defined(HAVE_NO_ACLS) NULL, - NULL + NULL, #else vfswrap_chmod_acl, vfswrap_fchmod_acl #endif + vfswrap_sys_acl_get_entry, + vfswrap_sys_acl_get_tag_type, + vfswrap_sys_acl_get_permset, + vfswrap_sys_acl_get_qualifier, + vfswrap_sys_acl_get_file, + vfswrap_sys_acl_get_fd, + vfswrap_sys_acl_clear_perms, + vfswrap_sys_acl_add_perm, + vfswrap_sys_acl_to_text, + vfswrap_sys_acl_init, + vfswrap_sys_acl_create_entry, + vfswrap_sys_acl_set_tag_type, + vfswrap_sys_acl_set_qualifier, + vfswrap_sys_acl_set_permset, + vfswrap_sys_acl_valid, + vfswrap_sys_acl_set_file, + vfswrap_sys_acl_set_fd, + vfswrap_sys_acl_delete_def_file, + vfswrap_sys_acl_get_perm, + vfswrap_sys_acl_free_text, + vfswrap_sys_acl_free_acl, + vfswrap_sys_acl_free_qualifier }; /**************************************************************************** -- cgit From b9377e811e44949070f04efe1c1cd389a7c3aef5 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 12 Mar 2002 16:32:25 +0000 Subject: Missing comma from systems that have ACLs. (This used to be commit 96e4282dca757e8621d23a54fb7203c93d2d41fc) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index ac342d0820..8d7ee2b075 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -85,7 +85,7 @@ static struct vfs_ops default_vfs_ops = { NULL, #else vfswrap_chmod_acl, - vfswrap_fchmod_acl + vfswrap_fchmod_acl, #endif vfswrap_sys_acl_get_entry, vfswrap_sys_acl_get_tag_type, -- cgit From 85d7e70d1fd5c69252310c22c60f9974cd392142 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Mar 2002 00:19:40 +0000 Subject: fixed mapping of SIDs for local users (This used to be commit df9e345366078ccaa94df7c2f2e33b292605e88a) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c3156b7b14..1946078d6e 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -631,7 +631,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) if (!winbind_sid_to_uid(puid, psid)) { DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n", sid_to_string(sid_str, psid) )); - return False; + return local_sid_to_uid(puid, psid, sidtype); } DEBUG(10,("sid_to_uid: winbindd %s -> %u\n", -- cgit From 8fe1df84e1dc83085bdc137629ca6c882c13c388 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Mar 2002 00:30:26 +0000 Subject: if we know that the SID is local then don't try via winbindd (This used to be commit 1a8f3ba3ab7717c481e3fb4f1ea8938461160d09) --- source3/smbd/uid.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 1946078d6e..864d3d6c66 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -593,6 +593,11 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) { fstring sid_str; + /* if we know its local then don't try winbindd */ + if (sid_compare_domain(&global_sam_sid, psid) == 0) { + return local_sid_to_uid(puid, psid, sidtype); + } + /* (tridge) I commented out the slab of code below in order to support foreign SIDs Do we really need to validate the type of SID we have in this case? */ -- cgit From 5e3b923124e82b1d19875746676df13cfdb0f918 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Mar 2002 20:28:19 +0000 Subject: include/smb_macros.h: Don't round up an allocation if the size is zero. "One of these locks is not like the others... One of these locks is not quite the same" :-). When is a zero timeout lock not zero ? When it's being processed by Windows 2000 of course.. This code change, ugly though it is - completely fixes the foxpro/access multi-user file system database problems that people have been having. I used a *wonderful* test program donated by "Gerald Drouillard" which allowed me to completely reproduce this problem, and to finally determine the correct fix. This also explains why Windows 2000 is *so slow* when responding to the smbtorture lock tests. I *love* it when all these things come together and finally make sense :-). Jeremy. (This used to be commit 8aa9860ea2ea7f5aed4b6aa12794fffdfa81b0d0) --- source3/smbd/blocking.c | 6 +++--- source3/smbd/reply.c | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index bc8c54caf7..d4a53d9a6d 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -279,7 +279,7 @@ static BOOL process_lockread(blocking_lock_record *blr) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - status = do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, + status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, READ_LOCK); if (NT_STATUS_V(status)) { if ((errno != EACCES) && (errno != EAGAIN)) { @@ -345,7 +345,7 @@ static BOOL process_lock(blocking_lock_record *blr) offset = IVAL(inbuf,smb_vwv3); errno = 0; - status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, + status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, (SMB_BIG_UINT)offset, WRITE_LOCK); if (NT_STATUS_IS_ERR(status)) { if((errno != EACCES) && (errno != EAGAIN)) { @@ -417,7 +417,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - status = do_lock(fsp,conn,lock_pid,count,offset, + status = do_lock_spin(fsp,conn,lock_pid,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); if (NT_STATUS_IS_ERR(status)) break; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9d5d34e410..cbcad435d2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1545,7 +1545,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * for a write lock. JRA. */ - status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), + status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK); if (NT_STATUS_V(status)) { @@ -2366,7 +2366,7 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fd, fsp->fnum, (double)offset, (double)count)); - status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK); + status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK); if (NT_STATUS_V(status)) { if (lp_blocking_locks(SNUM(conn))) { /* @@ -3808,6 +3808,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); } /* Setup the timeout in seconds. */ + lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000); /* Now do any requested locks */ @@ -3829,10 +3830,11 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR_DOS(ERRDOS,ERRnoaccess); } - DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n", - (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n", + (double)offset, (double)count, (unsigned int)lock_pid, + (int)lock_timeout, fsp->fsp_name )); - status = do_lock(fsp,conn,lock_pid, count,offset, + status = do_lock_spin(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); if (NT_STATUS_V(status)) { if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { -- cgit From 2ba1950c799137589c4111c9406f88a8f7526e0b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 13 Mar 2002 22:55:47 +0000 Subject: Fixed bodgy printf arguments in debug statment. Who would have guessed it - we now use floating point maths in Samba. (This used to be commit 6a053fa770b69f21fef52966a0b577b7ac9e817e) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cbcad435d2..8f6ff9cb34 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3832,7 +3832,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n", (double)offset, (double)count, (unsigned int)lock_pid, - (int)lock_timeout, fsp->fsp_name )); + fsp->fsp_name, (int)lock_timeout )); status = do_lock_spin(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); -- cgit From 47c2477233197e426705b0e1d28fe4ca9ae113fa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Mar 2002 00:58:53 +0000 Subject: Get the current directory after becoming root. Jeremy. (This used to be commit f032c6f710cb0edcf02f25db81c83478b9a8ab1e) --- source3/smbd/oplock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 39bcb558f1..c55c806a43 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -729,8 +729,8 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, saved_user_conn = current_user.conn; saved_vuid = current_user.vuid; saved_fsp_conn = fsp->conn; - vfs_GetWd(saved_fsp_conn,saved_dir); change_to_root_user(); + vfs_GetWd(saved_fsp_conn,saved_dir); /* Save the chain fnum. */ file_chain_save(); -- cgit From 840279f3424eb92d1c4b55e1f9a1aca938b087ca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Mar 2002 02:15:08 +0000 Subject: Now we have reliable signals take SIGTERM inband. Jeremy. (This used to be commit cad82926a8baf7605cef81f0e0d4daa8e527e6ee) --- source3/smbd/process.c | 12 +++++-- source3/smbd/server.c | 91 +++++++++++++++++++++++++++----------------------- 2 files changed, 58 insertions(+), 45 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8c037b4706..007621f6bb 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -43,6 +43,7 @@ extern int global_oplock_break; extern userdom_struct current_user_info; extern int smb_read_error; extern VOLATILE sig_atomic_t reload_after_sighup; +extern VOLATILE sig_atomic_t got_sig_term; extern BOOL global_machine_password_needs_changing; extern fstring global_myworkgroup; extern pstring global_myname; @@ -104,9 +105,10 @@ BOOL push_oplock_pending_smb_message(char *buf, int msg_len) } /**************************************************************************** -do all async processing in here. This includes UDB oplock messages, kernel -oplock messages, change notify events etc. + Do all async processing in here. This includes UDB oplock messages, kernel + oplock messages, change notify events etc. ****************************************************************************/ + static void async_processing(fd_set *fds, char *buffer, int buffer_len) { /* check for oplock messages (both UDP and kernel) */ @@ -114,6 +116,10 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len) process_local_message(buffer, buffer_len); } + if (got_sig_term) { + exit_server("Caught TERM signal"); + } + /* check for async change notify events */ process_pending_change_notify_queue(0); @@ -122,7 +128,7 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len) change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); - reload_after_sighup = False; + reload_after_sighup = 0; } } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 02f52e2392..8a5983d784 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -60,26 +60,43 @@ void smbd_set_server_fd(int fd) } /**************************************************************************** - when exiting, take the whole family + Terminate signal. ****************************************************************************/ -static void *dflt_sig(void) + +VOLATILE sig_atomic_t got_sig_term = 0; + +static void sig_term(void) +{ + got_sig_term = 1; + sys_select_signal(); +} + +/**************************************************************************** + Catch a sighup. +****************************************************************************/ + +VOLATILE sig_atomic_t reload_after_sighup = 0; + +static void sig_hup(int sig) { - exit_server("caught signal"); - return NULL; + reload_after_sighup = 1; + sys_select_signal(); } /**************************************************************************** Send a SIGTERM to our process group. *****************************************************************************/ + static void killkids(void) { if(am_parent) kill(0,SIGTERM); } /**************************************************************************** - process a sam sync message - not sure whether to do this here or - somewhere else + Process a sam sync message - not sure whether to do this here or + somewhere else. ****************************************************************************/ + static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), void *UNUSED(buf), size_t UNUSED(len)) { @@ -87,9 +104,10 @@ static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), } /**************************************************************************** - process a sam sync replicate message - not sure whether to do this here or - somewhere else + Process a sam sync replicate message - not sure whether to do this here or + somewhere else. ****************************************************************************/ + static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len) { uint32 low_serial; @@ -104,8 +122,9 @@ static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len) } /**************************************************************************** - open the socket communication + Open the socket communication - inetd. ****************************************************************************/ + static BOOL open_sockets_inetd(void) { /* Started from inetd. fd 0 is the socket. */ @@ -124,8 +143,9 @@ static BOOL open_sockets_inetd(void) /**************************************************************************** - open the socket communication + Open the socket communication. ****************************************************************************/ + static BOOL open_sockets(BOOL is_daemon,int port) { int num_interfaces = iface_count(); @@ -242,14 +262,16 @@ max can be %d\n", num = sys_select(FD_SETSIZE,&lfds,NULL,NULL,NULL); if (num == -1 && errno == EINTR) { - extern VOLATILE sig_atomic_t reload_after_sighup; + if (got_sig_term) { + exit_server("Caught TERM signal"); + } /* check for sighup processing */ if (reload_after_sighup) { change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); - reload_after_sighup = False; + reload_after_sighup = 0; } continue; @@ -347,8 +369,9 @@ max can be %d\n", } /**************************************************************************** - reload the services file - **************************************************************************/ + Reload the services file. +**************************************************************************/ + BOOL reload_services(BOOL test) { BOOL ret; @@ -398,26 +421,6 @@ BOOL reload_services(BOOL test) return(ret); } - - -/**************************************************************************** - Catch a sighup. -****************************************************************************/ - -VOLATILE sig_atomic_t reload_after_sighup = False; - -static void sig_hup(int sig) -{ - BlockSignals(True,SIGHUP); - DEBUG(0,("Got SIGHUP\n")); - - sys_select_signal(); - reload_after_sighup = True; - BlockSignals(False,SIGHUP); -} - - - #if DUMP_CORE /******************************************************************* prepare to dump a core file - carefully! @@ -472,8 +475,9 @@ static void decrement_smbd_process_count(void) } /**************************************************************************** -exit the server + Exit the server. ****************************************************************************/ + void exit_server(char *reason) { static int firsttime=1; @@ -527,8 +531,9 @@ void exit_server(char *reason) } /**************************************************************************** - initialise connect, service and file structs + Initialise connect, service and file structs. ****************************************************************************/ + static void init_structs(void ) { /* @@ -560,8 +565,9 @@ static void init_structs(void ) } /**************************************************************************** -usage on the program + Usage on the program. ****************************************************************************/ + static void usage(char *pname) { @@ -584,8 +590,9 @@ static void usage(char *pname) } /**************************************************************************** - main program + main program. ****************************************************************************/ + int main(int argc,char *argv[]) { extern BOOL append_log; @@ -704,8 +711,9 @@ static void usage(char *pname) gain_root_group_privilege(); fault_setup((void (*)(void *))exit_server); - CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig); - + CatchSignal(SIGTERM , SIGNAL_CAST sig_term); + CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); + /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); @@ -723,6 +731,7 @@ static void usage(char *pname) * these signals masked, we will have problems, as we won't recieve them. */ BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); + BlockSignals(False, SIGTERM); /* we want total control over the permissions on created files, so set our umask to 0 */ @@ -778,8 +787,6 @@ static void usage(char *pname) fstrcpy(global_myworkgroup, lp_workgroup()); - CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); - DEBUG(3,( "loaded services\n")); if (!is_daemon && !is_a_socket(0)) { -- cgit From d19e06c0c620046658621fcec7c2cda9a77ceac3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 14 Mar 2002 22:52:19 +0000 Subject: Actually include some *information* in the mangle debug messages. In particular this shows the filename, prefix and counters involved. The unicode -> unix converion only occours for the error case. Andrew Bartlett (This used to be commit 9c8de8c6cf44ead0719efa48a34c9c9d54402ac6) --- source3/smbd/mangle.c | 53 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index d396989e86..cfa71e3cf4 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Name mangling with persistent tdb Copyright (C) Simo Sorce 2001 + Copyright (C) Andrew Bartlett 2002 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 @@ -272,7 +273,10 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) pos--; if (pos == 0) { - DEBUG(0, ("mangle: unable to mangle file name!\n")); + char *unmangled_unix = acnv_u2ux(unmangled); + + DEBUG(0, ("mangle: unable to mangle file name (%s)!\n",unmangled_unix)); + SAFE_FREE(unmangled_unix); goto done; } strncpy_w(temp, umpref, pos); @@ -301,8 +305,10 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) { if (tdb_error(mangle_tdb) != TDB_ERR_EXISTS) { - DEBUG(0, ("mangle: database store error: %s\n", - tdb_errorstr(mangle_tdb))); + char *unmangled_unix = acnv_u2ux(unmangled); + DEBUG(0, ("mangle: database store error: %s for filename: %s\n", + tdb_errorstr(mangle_tdb), unmangled_unix)); + SAFE_FREE(unmangled_unix); goto done; } } @@ -310,7 +316,10 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) /* lock the mangle counter for this prefix */ if (tdb_chainlock(mangle_tdb, klock)) { - DEBUG(0,("mangle: failed to lock database\n!")); + char *unmangled_unix = acnv_u2ux(unmangled); + + DEBUG(0,("mangle: failed to lock database for filename %s\n!", unmangled_unix)); + SAFE_FREE(unmangled_unix); goto done; } tclock = True; @@ -318,8 +327,11 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) data = tdb_fetch(mangle_tdb, klock); if (!data.dptr) { - DEBUG(0, ("mangle: database retrieval error: %s\n", - tdb_errorstr(mangle_tdb))); + char *unmangled_unix = acnv_u2ux(unmangled); + + DEBUG(0, ("mangle: database retrieval error: %s for filename: %s\n", + tdb_errorstr(mangle_tdb), unmangled_unix)); + SAFE_FREE(unmangled_unix); goto done; } c = *((uint32 *)data.dptr); @@ -327,7 +339,10 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) if (c > MANGLE_COUNTER_MAX) { - DEBUG(0, ("mangle: error, counter overflow!\n")); + char *unmangled_unix = acnv_u2ux(unmangled); + + DEBUG(0, ("mangle: error, counter overflow (max=%d, counter=%d) for file: [%s] prefix (dos charset): [%s]!\n", MANGLE_COUNTER_MAX, c, unmangled_unix, prefix)); + SAFE_FREE(unmangled_unix); goto done; } @@ -340,7 +355,10 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) if (!ud83_len) goto done; if (ud83_len > 8) { - DEBUG(0, ("mangle: darn, logic error aborting!\n")); + char *unmangled_unix = acnv_u2ux(unmangled); + + DEBUG(0, ("mangle: darn, logic error aborting! Filename was %s\n", unmangled_unix)); + SAFE_FREE(unmangled_unix); goto done; } @@ -353,8 +371,11 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) { - DEBUG(0, ("mangle: database store error: %s\n", - tdb_errorstr(mangle_tdb))); + char *unmangled_unix = acnv_u2ux(unmangled); + + DEBUG(0, ("mangle: database store error: %s for filename: %s\n", + tdb_errorstr(mangle_tdb), unmangled_unix)); + SAFE_FREE(unmangled_unix); goto done; } @@ -367,8 +388,10 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) data.dptr = mufname; if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) { - DEBUG(0, ("mangle: database store failed: %s\n", - tdb_errorstr(mangle_tdb))); + char *unmangled_unix = acnv_u2ux(unmangled); + DEBUG(0, ("mangle: database store failed: %s for filename: %s\n", + tdb_errorstr(mangle_tdb), unmangled_unix)); + SAFE_FREE(unmangled_unix); /* try to delete the mangled key entry to avoid later inconsistency */ slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); @@ -393,8 +416,10 @@ smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) /* store the counter */ if(tdb_store(mangle_tdb, klock, data, TDB_REPLACE) != TDB_SUCCESS) { - DEBUG(0, ("mangle: database store failed: %s\n", - tdb_errorstr(mangle_tdb))); + char *unmangled_unix = acnv_u2ux(unmangled); + DEBUG(0, ("mangle: database store failed: %s for filename: %s\n", + tdb_errorstr(mangle_tdb), unmangled_unix)); + SAFE_FREE(unmangled_unix); /* try to delete the mangled and long key entry to avoid later inconsistency */ slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); key.dptr = keystr; -- cgit From 65c007b583e2107f5ad1ba6733d3e578a143863e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 15 Mar 2002 08:14:10 +0000 Subject: syncing up printing code with SAMBA_2_2 (already done some merges in the reverse). * add in new printer change notify code from SAMBA_2_2 * add in se_map_standard() from 2.2 in _spoolss_open_printer_ex() * sync up the _print_queue_struct in smb.h (why did someone change the user/file names in fs_user/fs_file (or vice-versa) ? ) * sync up some cli_spoolss_XXX functions (This used to be commit 5760315c1de4033fdc22684c940f18010010924f) --- source3/smbd/lanman.c | 8 ++++---- source3/smbd/reply.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 5bf7bb89e3..a218a04962 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -445,7 +445,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKI(desc,"W",queue->job); /* uJobId */ if (uLevel == 1) { - PACKS(desc,"B21",queue->user); /* szUserName */ + PACKS(desc,"B21",queue->fs_user); /* szUserName */ PACKS(desc,"B",""); /* pad */ PACKS(desc,"B16",""); /* szNotifyName */ PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ @@ -455,17 +455,17 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z",""); /* pszStatus */ PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z",queue->file); /* pszComment */ + PACKS(desc,"z",queue->fs_file); /* pszComment */ } if (uLevel == 2 || uLevel == 3 || uLevel == 4) { PACKI(desc,"W",queue->priority); /* uPriority */ - PACKS(desc,"z",queue->user); /* pszUserName */ + PACKS(desc,"z",queue->fs_user); /* pszUserName */ PACKI(desc,"W",n+1); /* uPosition */ PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z","Samba"); /* pszComment */ - PACKS(desc,"z",queue->file); /* pszDocument */ + PACKS(desc,"z",queue->fs_file); /* pszDocument */ if (uLevel == 3) { PACKS(desc,"z",""); /* pszNotifyName */ PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8f6ff9cb34..e72b6a7319 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2605,7 +2605,7 @@ int reply_printqueue(connection_struct *conn, SSVAL(p,5, queue[i].job); SIVAL(p,7,queue[i].size); SCVAL(p,11,0); - srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII); + srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII); p += 28; } -- cgit From ab13654dc9ac23872e4d1384e1c54e336f113009 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 17 Mar 2002 04:36:35 +0000 Subject: Renamed get_nt_error_msg() to nt_errstr(). (This used to be commit 1f007d3ed41c1b71a89fa6be7d173e67e927c302) --- source3/smbd/error.c | 2 +- source3/smbd/lanman.c | 2 +- source3/smbd/negprot.c | 2 +- source3/smbd/reply.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 92a7c11b15..2f993fb41e 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -107,7 +107,7 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, file, line, (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), - get_nt_error_msg(ntstatus))); + nt_errstr(ntstatus))); return outsize; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a218a04962..666bbb5f61 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1632,7 +1632,7 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c *rdata = REALLOC(*rdata,*rdata_len); memset(*rdata,0,*rdata_len); - p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */ + p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */ p = *rdata; f_len = fixed_len; s_len = string_len; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index f4ed360845..18682e6c9f 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -41,7 +41,7 @@ static void get_challenge(char buff[8]) DEBUG(10, ("get challenge: creating negprot_global_auth_context\n")); if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) { - DEBUG(0, ("make_auth_context_subsystem returned %s", get_nt_error_msg(nt_status))); + DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status))); smb_panic("cannot make_negprot_global_auth_context!\n"); } DEBUG(10, ("get challenge: getting challenge\n")); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e72b6a7319..1b7db5f0a7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3120,7 +3120,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", } error = map_nt_error_from_unix(errno); DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - get_nt_error_msg(error), directory,newname)); + nt_errstr(error), directory,newname)); return error; } @@ -3129,7 +3129,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", if (!NT_STATUS_IS_OK(error)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - get_nt_error_msg(error), directory,newname)); + nt_errstr(error), directory,newname)); return error; } @@ -3161,7 +3161,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", error = map_nt_error_from_unix(errno); DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - get_nt_error_msg(error), directory,newname)); + nt_errstr(error), directory,newname)); return error; } else { -- cgit From ffadd471b9664018b3010ab5d74e6d05b8886e66 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Mar 2002 02:32:39 +0000 Subject: Sync up vfs changes from 2.2.x. Jeremy. (This used to be commit ad1e858d8e72adf924ff435eab8da3e60842e2e6) --- source3/smbd/reply.c | 2 +- source3/smbd/vfs-wrap.c | 166 +++--------------------------------------------- source3/smbd/vfs.c | 52 ++++++++------- 3 files changed, 39 insertions(+), 181 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1b7db5f0a7..0af2ea3716 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1261,7 +1261,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) p = strrchr_m(name,'/'); if (!p) { - pstrcpy(directory,"./"); + pstrcpy(directory,"."); pstrcpy(mask,name); } else { *p = 0; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 73b070d3f8..1d94e18e5b 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -22,8 +22,6 @@ /* Check for NULL pointer parameters in vfswrap_* functions */ -#define VFS_CHECK_NULL - /* We don't want to have NULL function pointers lying around. Someone is sure to try and execute them. These stubs are used to prevent this possibility. */ @@ -44,14 +42,6 @@ SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL s { SMB_BIG_UINT result; -#ifdef VFS_CHECK_NULL - if ((path == NULL) || (bsize == NULL) || (dfree == NULL) || - (dsize == NULL)) { - - smb_panic("NULL pointer passed to vfswrap_disk_free() function\n"); - } -#endif - result = sys_disk_free(path, small_query, bsize, dfree, dsize); return result; } @@ -63,13 +53,6 @@ DIR *vfswrap_opendir(connection_struct *conn, const char *fname) DIR *result; START_PROFILE(syscall_opendir); - -#ifdef VFS_CHECK_NULL - if (fname == NULL) { - smb_panic("NULL pointer passed to vfswrap_opendir()\n"); - } -#endif - result = opendir(fname); END_PROFILE(syscall_opendir); return result; @@ -80,13 +63,6 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) struct dirent *result; START_PROFILE(syscall_readdir); - -#ifdef VFS_CHECK_NULL - if (dirp == NULL) { - smb_panic("NULL pointer passed to vfswrap_readdir()\n"); - } -#endif - result = readdir(dirp); END_PROFILE(syscall_readdir); return result; @@ -99,12 +75,6 @@ int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) START_PROFILE(syscall_mkdir); -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_mkdir()\n"); - } -#endif - if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path)))) mode = 0777; @@ -134,13 +104,6 @@ int vfswrap_rmdir(connection_struct *conn, const char *path) int result; START_PROFILE(syscall_rmdir); - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_rmdir()\n"); - } -#endif - result = rmdir(path); END_PROFILE(syscall_rmdir); return result; @@ -151,13 +114,6 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) int result; START_PROFILE(syscall_closedir); - -#ifdef VFS_CHECK_NULL - if (dirp == NULL) { - smb_panic("NULL pointer passed to vfswrap_closedir()\n"); - } -#endif - result = closedir(dirp); END_PROFILE(syscall_closedir); return result; @@ -170,13 +126,6 @@ int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t m int result; START_PROFILE(syscall_open); - -#ifdef VFS_CHECK_NULL - if (fname == NULL) { - smb_panic("NULL pointer passed to vfswrap_open()\n"); - } -#endif - result = sys_open(fname, flags, mode); END_PROFILE(syscall_open); return result; @@ -198,13 +147,6 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) ssize_t result; START_PROFILE_BYTES(syscall_read, n); - -#ifdef VFS_CHECK_NULL - if (data == NULL) { - smb_panic("NULL pointer passed to vfswrap_read()\n"); - } -#endif - result = read(fd, data, n); END_PROFILE(syscall_read); return result; @@ -215,13 +157,6 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) ssize_t result; START_PROFILE_BYTES(syscall_write, n); - -#ifdef VFS_CHECK_NULL - if (data == NULL) { - smb_panic("NULL pointer passed to vfswrap_write()\n"); - } -#endif - result = write(fd, data, n); END_PROFILE(syscall_write); return result; @@ -256,13 +191,6 @@ int vfswrap_rename(connection_struct *conn, const char *old, const char *new) int result; START_PROFILE(syscall_rename); - -#ifdef VFS_CHECK_NULL - if ((old == NULL) || (new == NULL)) { - smb_panic("NULL pointer passed to vfswrap_rename()\n"); - } -#endif - result = rename(old, new); END_PROFILE(syscall_rename); return result; @@ -288,13 +216,6 @@ int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sb int result; START_PROFILE(syscall_stat); - -#ifdef VFS_CHECK_NULL - if ((fname == NULL) || (sbuf == NULL)) { - smb_panic("NULL pointer passed to vfswrap_stat()\n"); - } -#endif - result = sys_stat(fname, sbuf); END_PROFILE(syscall_stat); return result; @@ -305,13 +226,6 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) int result; START_PROFILE(syscall_fstat); - -#ifdef VFS_CHECK_NULL - if (sbuf == NULL) { - smb_panic("NULL pointer passed to vfswrap_fstat()\n"); - } -#endif - result = sys_fstat(fd, sbuf); END_PROFILE(syscall_fstat); return result; @@ -322,13 +236,6 @@ int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sb int result; START_PROFILE(syscall_lstat); - -#ifdef VFS_CHECK_NULL - if ((path == NULL) || (sbuf == NULL)) { - smb_panic("NULL pointer passed to vfswrap_lstat()\n"); - } -#endif - result = sys_lstat(path, sbuf); END_PROFILE(syscall_lstat); return result; @@ -339,13 +246,6 @@ int vfswrap_unlink(connection_struct *conn, const char *path) int result; START_PROFILE(syscall_unlink); - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_unlink()\n"); - } -#endif - result = unlink(path); END_PROFILE(syscall_unlink); return result; @@ -357,12 +257,6 @@ int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) START_PROFILE(syscall_chmod); -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_chmod()\n"); - } -#endif - /* * We need to do this due to the fact that the default POSIX ACL * chmod modifies the ACL *mask* for the group owner, not the @@ -418,13 +312,6 @@ int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gi int result; START_PROFILE(syscall_chown); - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_chown()\n"); - } -#endif - result = sys_chown(path, uid, gid); END_PROFILE(syscall_chown); return result; @@ -446,13 +333,6 @@ int vfswrap_chdir(connection_struct *conn, const char *path) int result; START_PROFILE(syscall_chdir); - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_chdir()\n"); - } -#endif - result = chdir(path); END_PROFILE(syscall_chdir); return result; @@ -463,13 +343,6 @@ char *vfswrap_getwd(connection_struct *conn, char *path) char *result; START_PROFILE(syscall_getwd); - -#ifdef VFS_CHECK_NULL - if (path == NULL) { - smb_panic("NULL pointer passed to vfswrap_getwd()\n"); - } -#endif - result = sys_getwd(path); END_PROFILE(syscall_getwd); return result; @@ -480,13 +353,6 @@ int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *tim int result; START_PROFILE(syscall_utime); - -#ifdef VFS_CHECK_NULL - if ((path == NULL) || (times == NULL)) { - smb_panic("NULL pointer passed to vfswrap_utime()\n"); - } -#endif - result = utime(path, times); END_PROFILE(syscall_utime); return result; @@ -642,12 +508,6 @@ int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *ne int result; START_PROFILE(syscall_symlink); - -#ifdef VFS_CHECK_NULL - if ((oldpath == NULL) || (newpath == NULL)) - smb_panic("NULL pointer passed to vfswrap_symlink()\n"); -#endif - result = sys_symlink(oldpath, newpath); END_PROFILE(syscall_symlink); return result; @@ -658,12 +518,6 @@ int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_ int result; START_PROFILE(syscall_readlink); - -#ifdef VFS_CHECK_NULL - if ((path == NULL) || (buf == NULL)) - smb_panic("NULL pointer passed to vfswrap_readlink()\n"); -#endif - result = sys_readlink(path, buf, bufsiz); END_PROFILE(syscall_readlink); return result; @@ -674,11 +528,6 @@ int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpa int result; START_PROFILE(syscall_link); - -#ifdef VFS_CHECK_NULL - if ((oldpath == NULL) || (newpath == NULL)) - smb_panic("NULL pointer passed to vfswrap_link()\n"); -#endif result = sys_link(oldpath, newpath); END_PROFILE(syscall_link); return result; @@ -689,16 +538,21 @@ int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SM int result; START_PROFILE(syscall_mknod); - -#ifdef VFS_CHECK_NULL - if (pathname == NULL) - smb_panic("NULL pointer passed to vfswrap_mknod()\n"); -#endif result = sys_mknod(pathname, mode, dev); END_PROFILE(syscall_mknod); return result; } +char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved_path) +{ + char *result; + + START_PROFILE(syscall_realpath); + result = sys_realpath(path, resolved_path); + END_PROFILE(syscall_realpath); + return result; +} + size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) { size_t result; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 8d7ee2b075..6416d8e73e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1,5 +1,6 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. VFS initialisation and support functions Copyright (C) Tim Potter 1999 @@ -31,7 +32,7 @@ struct vfs_syminfo { very important. They must be in the same order as defined in vfs.h. Change at your own peril. */ -static struct vfs_ops default_vfs_ops = { +struct vfs_ops default_vfs_ops = { /* Disk operations */ @@ -73,6 +74,7 @@ static struct vfs_ops default_vfs_ops = { vfswrap_readlink, vfswrap_link, vfswrap_mknod, + vfswrap_realpath, vfswrap_fget_nt_acl, vfswrap_get_nt_acl, @@ -131,46 +133,48 @@ static BOOL vfs_init_default(connection_struct *conn) static BOOL vfs_init_custom(connection_struct *conn) { int vfs_version = -1; - struct vfs_ops *ops, *(*init_fptr)(int *, struct vfs_ops *); + struct vfs_ops *ops, *(*init_fptr)(int *, struct vfs_ops *); - DEBUG(3, ("Initialising custom vfs hooks from %s\n", - lp_vfsobj(SNUM(conn)))); + DEBUG(3, ("Initialising custom vfs hooks from %s\n", + lp_vfsobj(SNUM(conn)))); + + /* Open object file */ - /* Open object file */ - if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), - RTLD_NOW | RTLD_GLOBAL)) == NULL) { - DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), sys_dlerror())); + if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { + DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); return False; - } + } + + /* Get handle on vfs_init() symbol */ - /* Get handle on vfs_init() symbol */ - init_fptr = (struct vfs_ops *(*)(int *, struct vfs_ops *))sys_dlsym(conn->dl_handle, "vfs_init"); + init_fptr = (struct vfs_ops *(*)(int *, struct vfs_ops *))sys_dlsym(conn->dl_handle, "vfs_init"); - if (init_fptr == NULL) { + if (init_fptr == NULL) { DEBUG(0, ("No vfs_init() symbol found in %s\n", - lp_vfsobj(SNUM(conn)))); + lp_vfsobj(SNUM(conn)))); return False; - } + } + + /* Initialise vfs_ops structure */ - /* Initialise vfs_ops structure */ conn->vfs_ops = default_vfs_ops; - if ((ops = init_fptr(&vfs_version, &conn->vfs_ops)) == NULL) { - DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); + if ((ops = init_fptr(&vfs_version, &default_vfs_ops)) == NULL) { + DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); return False; - } - + } + if (vfs_version != SMB_VFS_INTERFACE_VERSION) { DEBUG(0, ("vfs_init returned wrong interface version info (was %d, should be %d)\n", - vfs_version, SMB_VFS_INTERFACE_VERSION )); + vfs_version, SMB_VFS_INTERFACE_VERSION )); return False; } - + if (ops != &conn->vfs_ops) { memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); } - return True; + return True; } #endif @@ -276,7 +280,7 @@ BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT Check if a file exists in the vfs. ********************************************************************/ -BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) +BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_STAT st; -- cgit From b9e91d2a8e41a43d7ebb7d7eed807a7d8de9b329 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Mar 2002 00:46:53 +0000 Subject: Remove the "stat open" code - make it inline. This should fix the bugs with opening and renaming mp3 files, also the word rename problems that people have had for a while. Needs a make clean :-) make. Also added JohnR's printing fix. Jeremy. (This used to be commit 504e5ef0494c54efbd0357e334cb2aa5a9eb9c14) --- source3/smbd/close.c | 30 +++------- source3/smbd/dir.c | 27 ++------- source3/smbd/fileio.c | 12 ++++ source3/smbd/nttrans.c | 53 +--------------- source3/smbd/open.c | 101 +++++++++---------------------- source3/smbd/reply.c | 156 +++++++++++++++++++++++++----------------------- source3/smbd/trans2.c | 9 +-- source3/smbd/vfs-wrap.c | 6 +- 8 files changed, 140 insertions(+), 254 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 79b627e924..dc52327cb4 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -75,7 +75,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn) return; } - transfer_file(tmp_fd,outfd,st.st_size); + transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size); close(tmp_fd); close(outfd); } @@ -90,15 +90,17 @@ static int close_filestruct(files_struct *fsp) connection_struct *conn = fsp->conn; int ret = 0; - if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) - ret = -1; + if (fsp->fd != -1) { + if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) + ret = -1; - delete_write_cache(fsp); + delete_write_cache(fsp); + } fsp->is_directory = False; - fsp->stat_open = False; conn->num_files_open--; + SAFE_FREE(fsp->wbmpx_ptr); return ret; } @@ -260,22 +262,6 @@ static int close_directory(files_struct *fsp, BOOL normal_close) return 0; } -/**************************************************************************** - Close a file opened with null permissions in order to read permissions. -****************************************************************************/ - -static int close_statfile(files_struct *fsp, BOOL normal_close) -{ - close_filestruct(fsp); - - if (fsp->fsp_name) - string_free(&fsp->fsp_name); - - file_free(fsp); - - return 0; -} - /**************************************************************************** Close a directory opened by an NT SMB call. ****************************************************************************/ @@ -284,7 +270,5 @@ int close_file(files_struct *fsp, BOOL normal_close) { if(fsp->is_directory) return close_directory(fsp, normal_close); - else if(fsp->stat_open) - return close_statfile(fsp, normal_close); return close_normal_file(fsp, normal_close); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 2b2683caa5..3a7b697d75 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -674,6 +674,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) size_t sd_size; files_struct *fsp; int smb_action; + int access_mode; NTSTATUS status; uint32 access_granted; @@ -686,10 +687,12 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) /* Pseudo-open the file (note - no fd's created). */ if(S_ISDIR(ste.st_mode)) - fsp = open_directory(conn, name, &ste, SET_DENY_MODE(DENY_NONE), FILE_OPEN, + fsp = open_directory(conn, name, &ste, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unix_mode(conn,aRONLY|aDIR, name), &smb_action); else - fsp = open_file_stat(conn,name,&ste,DOS_OPEN_RDONLY,&smb_action); + fsp = open_file_shared1(conn, name, &ste, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + if (!fsp) return False; @@ -703,26 +706,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, &access_granted, &status); - -#if 0 - /* Old - crappy check :-). JRA */ - - if (ste.st_uid == conn->uid) { - return (ste.st_mode & S_IRUSR) == S_IRUSR; - } else { - int i; - if (ste.st_gid == conn->gid) { - return (ste.st_mode & S_IRGRP) == S_IRGRP; - } - for (i=0; ingroups; i++) { - if (conn->groups[i] == ste.st_gid) { - return (ste.st_mode & S_IRGRP) == S_IRGRP; - } - } - } - - return (ste.st_mode & S_IROTH) == S_IROTH; -#endif } /******************************************************************* diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index acbbb73352..addbcb0b3c 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -645,3 +645,15 @@ void sync_file(connection_struct *conn, files_struct *fsp) conn->vfs_ops.fsync(fsp,fsp->fd); } } + +/************************************************************ + Perform a stat whether a valid fd or not. +************************************************************/ + +int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) +{ + if (fsp->fd == -1) + return vfs_stat(fsp->conn, fsp->fsp_name, pst); + else + return vfs_fstat(fsp,fsp->fd, pst); +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d9b90c14cb..fb985bb325 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -329,13 +329,11 @@ static int map_create_disposition( uint32 create_disposition) Utility function to map share modes. ****************************************************************************/ -static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_options, +static int map_share_mode( char *fname, uint32 create_options, uint32 *desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode = -1; - *pstat_open_only = False; - /* * Convert GENERIC bits to specific bits. */ @@ -374,9 +372,6 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt if (smb_open_mode == -1) { - if(*desired_access == WRITE_DAC_ACCESS || *desired_access == READ_CONTROL_ACCESS) - *pstat_open_only = True; - if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| FILE_EXECUTE|FILE_READ_ATTRIBUTES| FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| @@ -389,7 +384,6 @@ static int map_share_mode( BOOL *pstat_open_only, char *fname, uint32 create_opt * and map to a stat open. */ - *pstat_open_only = True; smb_open_mode = DOS_OPEN_RDONLY; } else { @@ -569,7 +563,6 @@ int reply_ntcreate_and_X(connection_struct *conn, BOOL bad_path = False; files_struct *fsp=NULL; char *p = NULL; - BOOL stat_open_only = False; time_t c_time; START_PROFILE(SMBntcreateX); @@ -655,7 +648,7 @@ int reply_ntcreate_and_X(connection_struct *conn, */ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - if((smb_open_mode = map_share_mode(&stat_open_only, fname, create_options, &desired_access, + if((smb_open_mode = map_share_mode(fname, create_options, &desired_access, share_access, file_attributes)) == -1) { END_PROFILE(SMBntcreateX); @@ -770,26 +763,6 @@ int reply_ntcreate_and_X(connection_struct *conn, END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } -#ifdef EROFS - } else if (((errno == EACCES) || (errno == EROFS)) && stat_open_only) { -#else /* !EROFS */ - } else if (errno == EACCES && stat_open_only) { -#endif - /* - * We couldn't open normally and all we want - * are the permissions. Try and do a stat open. - */ - - oplock_request = 0; - - fsp = open_file_stat(conn,fname,&sbuf,smb_open_mode,&smb_action); - - if(!fsp) { - restore_case_semantics(file_attributes); - END_PROFILE(SMBntcreateX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } else { if((errno == ENOENT) && bad_path) { @@ -1059,7 +1032,6 @@ static int call_nt_transact_create(connection_struct *conn, BOOL bad_path = False; files_struct *fsp = NULL; char *p = NULL; - BOOL stat_open_only = False; uint32 flags; uint32 desired_access; uint32 file_attributes; @@ -1172,7 +1144,7 @@ static int call_nt_transact_create(connection_struct *conn, * and the share access. */ - if((smb_open_mode = map_share_mode( &stat_open_only, fname, create_options, &desired_access, + if((smb_open_mode = map_share_mode( fname, create_options, &desired_access, share_access, file_attributes)) == -1) return ERROR_DOS(ERRDOS,ERRbadaccess); @@ -1252,25 +1224,6 @@ static int call_nt_transact_create(connection_struct *conn, } return(UNIXERROR(ERRDOS,ERRnoaccess)); } -#ifdef EROFS - } else if (((errno == EACCES) || (errno == EROFS)) && stat_open_only) { -#else /* !EROFS */ - } else if (errno == EACCES && stat_open_only) { -#endif - - /* - * We couldn't open normally and all we want - * are the permissions. Try and do a stat open. - */ - - oplock_request = 0; - - fsp = open_file_stat(conn,fname,&sbuf,smb_open_mode,&smb_action); - - if(!fsp) { - restore_case_semantics(file_attributes); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } } else { if((errno == ENOENT) && bad_path) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b86d9763a4..0aaf5fd1c7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -60,7 +60,7 @@ static int fd_open(struct connection_struct *conn, char *fname, int fd_close(struct connection_struct *conn, files_struct *fsp) { if (fsp->fd == -1) - return -1; + return 0; /* what we used to call a stat open. */ return fd_close_posix(conn, fsp); } @@ -87,7 +87,7 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode) + char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { extern struct current_user current_user; pstring fname; @@ -149,18 +149,30 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags &= ~O_TRUNC; - /* actually do the open */ - fsp->fd = fd_open(conn, fname, local_flags, mode); + if (desired_access == 0 || (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + (local_flags & O_CREAT)) { - if (fsp->fd == -1) { - DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", - fname,strerror(errno),local_flags,flags)); - check_for_pipe(fname); - return False; + /* actually do the open */ + fsp->fd = fd_open(conn, fname, local_flags, mode); + + if (fsp->fd == -1) { + DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", + fname,strerror(errno),local_flags,flags)); + check_for_pipe(fname); + return False; + } } + fsp->fd == -1; /* What we used to call a stat open. */ if (!VALID_STAT(*psbuf)) { - if (vfs_fstat(fsp,fsp->fd,psbuf) == -1) { + int ret; + + if (fsp->fd == -1) + ret = vfs_stat(conn, fname, psbuf); + else + ret = vfs_fstat(fsp,fsp->fd,psbuf); + + if (ret == -1) { DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); fd_close(conn, fsp); return False; @@ -194,7 +206,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; - fsp->stat_open = False; fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); @@ -783,7 +794,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ * we can do. We also ensure we're not going to create or tuncate * the file as we only want an access decision at this stage. JRA. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC|O_CREAT)),mode); + fsp_open = open_file(fsp,conn,fname,psbuf, + flags|(flags2&~(O_TRUNC|O_CREAT)),mode,desired_access); DEBUG(4,("open_file_shared : share_mode deny - calling open_file with \ flags=0x%X flags2=0x%X mode=0%o returned %d\n", @@ -816,10 +828,10 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode,desired_access); if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { - if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode)) == True) + if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode,desired_access)) == True) flags = O_RDONLY; } @@ -977,65 +989,6 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", return fsp; } -/**************************************************************************** - Open a file for permissions read only. Return a pseudo file entry - with the 'stat_open' flag set -****************************************************************************/ - -files_struct *open_file_stat(connection_struct *conn, char *fname, - SMB_STRUCT_STAT *psbuf, int smb_ofun, int *action) -{ - extern struct current_user current_user; - files_struct *fsp = NULL; - - if (!VALID_STAT(*psbuf)) { - DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); - return NULL; - } - - if(S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); - return NULL; - } - - fsp = file_new(conn); - if(!fsp) - return NULL; - - *action = FILE_WAS_OPENED; - - DEBUG(5,("open_file_stat: opening file %s as a stat entry\n", fname)); - - /* - * Setup the files_struct for it. - */ - - fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; - fsp->size = psbuf->st_size; - fsp->vuid = current_user.vuid; - fsp->pos = -1; - fsp->can_lock = False; - fsp->can_read = False; - fsp->can_write = False; - fsp->share_mode = 0; - fsp->print_file = False; - fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->is_directory = False; - fsp->stat_open = True; - fsp->directory_delete_on_close = False; - fsp->conn = conn; - string_set(&fsp->fsp_name,fname); - fsp->wcp = NULL; /* Write cache pointer. */ - - conn->num_files_open++; - - return fsp; -} - /**************************************************************************** Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ @@ -1052,7 +1005,7 @@ files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_ if(!fsp) return NULL; - fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0); + fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,0); /* * This is not a user visible file open. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0af2ea3716..4dcb674ff1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2230,10 +2230,9 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, return ERROR_DOS(ERRDOS,ERRbadfid); } - if(fsp->is_directory || fsp->stat_open) { + if(fsp->is_directory) { /* - * Special case - close NT SMB directory or stat file - * handle. + * Special case - close NT SMB directory handle. */ DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum)); close_file(fsp,True); @@ -3969,54 +3968,55 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - struct utimbuf unix_times; - int outsize = 0; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBsetattrE); + struct utimbuf unix_times; + int outsize = 0; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBsetattrE); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - CHECK_FSP(fsp,conn); + if(!fsp || (fsp->conn != conn)) { + END_PROFILE(SMBgetattrE); + return ERROR_DOS(ERRDOS,ERRbadfid); + } - /* Convert the DOS times into unix times. Ignore create - time as UNIX can't set this. - */ - unix_times.actime = make_unix_date2(inbuf+smb_vwv3); - unix_times.modtime = make_unix_date2(inbuf+smb_vwv5); + /* + * Convert the DOS times into unix times. Ignore create + * time as UNIX can't set this. + */ + + unix_times.actime = make_unix_date2(inbuf+smb_vwv3); + unix_times.modtime = make_unix_date2(inbuf+smb_vwv5); - /* - * Patch from Ray Frush - * Sometimes times are sent as zero - ignore them. - */ + /* + * Patch from Ray Frush + * Sometimes times are sent as zero - ignore them. + */ - if ((unix_times.actime == 0) && (unix_times.modtime == 0)) - { - /* Ignore request */ - if( DEBUGLVL( 3 ) ) - { - dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); - dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); - } - END_PROFILE(SMBsetattrE); - return(outsize); - } - else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) - { - /* set modify time = to access time if modify time was 0 */ - unix_times.modtime = unix_times.actime; - } + if ((unix_times.actime == 0) && (unix_times.modtime == 0)) { + /* Ignore request */ + if( DEBUGLVL( 3 ) ) { + dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); + dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); + } + END_PROFILE(SMBsetattrE); + return(outsize); + } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) { + /* set modify time = to access time if modify time was 0 */ + unix_times.modtime = unix_times.actime; + } - /* Set the date on this file */ - if(file_utime(conn, fsp->fsp_name, &unix_times)) { - END_PROFILE(SMBsetattrE); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } + /* Set the date on this file */ + if(file_utime(conn, fsp->fsp_name, &unix_times)) { + END_PROFILE(SMBsetattrE); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", - fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); + DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", + fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); - END_PROFILE(SMBsetattrE); - return(outsize); + END_PROFILE(SMBsetattrE); + return(outsize); } @@ -4217,44 +4217,48 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - SMB_STRUCT_STAT sbuf; - int outsize = 0; - int mode; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBgetattrE); + SMB_STRUCT_STAT sbuf; + int outsize = 0; + int mode; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBgetattrE); - outsize = set_message(outbuf,11,0,True); + outsize = set_message(outbuf,11,0,True); - CHECK_FSP(fsp,conn); + if(!fsp || (fsp->conn != conn)) { + END_PROFILE(SMBgetattrE); + return ERROR_DOS(ERRDOS,ERRbadfid); + } - /* Do an fstat on this file */ - if(vfs_fstat(fsp,fsp->fd, &sbuf)) { - END_PROFILE(SMBgetattrE); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + /* Do an fstat on this file */ + if(fsp_stat(fsp, &sbuf)) { + END_PROFILE(SMBgetattrE); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - mode = dos_mode(conn,fsp->fsp_name,&sbuf); + mode = dos_mode(conn,fsp->fsp_name,&sbuf); - /* Convert the times into dos times. Set create - date to be last modify date as UNIX doesn't save - this */ - put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); - put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); - put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); - if (mode & aDIR) - { - SIVAL(outbuf,smb_vwv6,0); - SIVAL(outbuf,smb_vwv8,0); - } - else - { - SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); - SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024)); - } - SSVAL(outbuf,smb_vwv10, mode); + /* + * Convert the times into dos times. Set create + * date to be last modify date as UNIX doesn't save + * this. + */ + + put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); + put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); + + if (mode & aDIR) { + SIVAL(outbuf,smb_vwv6,0); + SIVAL(outbuf,smb_vwv8,0); + } else { + SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); + SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024)); + } + SSVAL(outbuf,smb_vwv10, mode); - DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum)); + DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum)); - END_PROFILE(SMBgetattrE); - return(outsize); + END_PROFILE(SMBgetattrE); + return(outsize); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d08e3419f9..660363a7f1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1452,7 +1452,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); - if(fsp && (fsp->is_directory || fsp->stat_open)) { + if(fsp && (fsp->is_directory || fsp->fd == -1)) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems @@ -1871,11 +1871,6 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) fsp->directory_delete_on_close = delete_on_close; DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n", delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } else if(fsp->stat_open) { - - DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, stat open %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } else { files_struct *iterate_fsp; @@ -1959,7 +1954,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fsp = file_fsp(params,0); info_level = SVAL(params,2); - if(fsp && (fsp->is_directory || fsp->stat_open)) { + if(fsp && (fsp->is_directory || fsp->fd == -1)) { /* * This is actually a SETFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 1d94e18e5b..fadc435a2f 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -164,11 +164,13 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) { - SMB_OFF_T result; + SMB_OFF_T result = 0; START_PROFILE(syscall_lseek); - result = sys_lseek(filedes, offset, whence); + /* Cope with 'stat' file opens. */ + if (filedes != -1) + result = sys_lseek(filedes, offset, whence); /* * We want to maintain the fiction that we can seek -- cgit From 418d5684a2845d914ad1266bb38e68bc7e2de43a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Mar 2002 00:58:23 +0000 Subject: Ensure we get a real fd when opening for set file allocation. Jeremy. (This used to be commit 00cabb2346fb11c5568b6c7a038c313ae293a0c2) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 660363a7f1..6aee06cc00 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2140,7 +2140,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return -1; } - new_fsp = open_file_shared(conn, fname, &sbuf, + new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA, SET_OPEN_MODE(DOS_OPEN_RDWR), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action); -- cgit From 2eab97160b5934d256a34294db07eb324be17c43 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Mar 2002 19:29:06 +0000 Subject: HEAD only fix for truncate from Alexander Bokovoy . This code needs replacing with the trans2.c from 2.2.x. Jeremy. (This used to be commit bc8d4b98807ece734db3e1c3a2baabf4b28e7b4f) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6aee06cc00..185fe1c633 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2154,7 +2154,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } close_file(new_fsp,True); } else { - ret = vfs_allocate_file_space(fsp, size); + ret = vfs_allocate_file_space(fsp, allocation_size); if (vfs_fstat(fsp,fd,&new_sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); ret = -1; -- cgit From 1783dcd2f189d64514733e759bdecc68e86a95ea Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 21 Mar 2002 14:00:13 +0000 Subject: return . and .. first in readdir - this fixes masktest on IRIX which returns . then single letter files then .. then all other files. (This used to be commit d4d9361eec11f50c780ed4c79bc9775ac24d8c0e) --- source3/smbd/dir.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 3a7b697d75..40b198ed72 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -729,10 +729,22 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; - while ((n = vfs_readdirname(conn, p))) + while (True) { int l; + if (used == 0) { + n = "."; + } else if (used == 2) { + n = ".."; + } else { + n = vfs_readdirname(conn, p); + if (n == NULL) + break; + if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0)) + continue; + } + l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ -- cgit From bffc69a877497c91f3acd77a229e9840b67f9087 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Mar 2002 21:23:22 +0000 Subject: Fix stupid typo ! Jeremy. (This used to be commit d0b58f66edeac516bde2dff79ab5cf529c37954b) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0aaf5fd1c7..c36dbdd522 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -161,8 +161,8 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, check_for_pipe(fname); return False; } - } - fsp->fd == -1; /* What we used to call a stat open. */ + } else + fsp->fd = -1; /* What we used to call a stat open. */ if (!VALID_STAT(*psbuf)) { int ret; -- cgit From c90cd26e9430b2fc065f620bdb6aaf4be0372fcc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Mar 2002 02:57:44 +0000 Subject: Fix the mp3 rename bug - also tidy up our open code and remove the special cases for rename and unlink. Had to add desired_access into the share mode record. Jeremy. (This used to be commit 3b1b8ac43535fb0839c5474fa55bf7150f6cde31) --- source3/smbd/dir.c | 4 +- source3/smbd/nttrans.c | 9 +- source3/smbd/open.c | 331 ++++++++++++++++++++++++------------------------- source3/smbd/reply.c | 81 +++++++++--- source3/smbd/trans2.c | 2 +- 5 files changed, 232 insertions(+), 195 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 40b198ed72..0bf234dd3e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -687,7 +687,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) /* Pseudo-open the file (note - no fd's created). */ if(S_ISDIR(ste.st_mode)) - fsp = open_directory(conn, name, &ste, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + fsp = open_directory(conn, name, &ste, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unix_mode(conn,aRONLY|aDIR, name), &smb_action); else fsp = open_file_shared1(conn, name, &ste, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), @@ -698,7 +698,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); - close_file(fsp, True); + close_file(fsp, False); /* No access if SD get failed. */ if (!sd_size) diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fb985bb325..ba6fd3eb44 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -412,7 +412,6 @@ static int map_share_mode( char *fname, uint32 create_options, */ if(*desired_access & DELETE_ACCESS) { - smb_open_mode |= DELETE_ACCESS_REQUESTED; DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); } @@ -681,7 +680,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); @@ -752,7 +751,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1177,7 +1176,7 @@ static int call_nt_transact_create(connection_struct *conn, * CreateDirectory() call. */ - fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1214,7 +1213,7 @@ static int call_nt_transact_create(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c36dbdd522..bcb866c378 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -149,7 +149,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags &= ~O_TRUNC; - if (desired_access == 0 || (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || (local_flags & O_CREAT)) { /* actually do the open */ @@ -201,6 +201,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); fsp->share_mode = 0; + fsp->desired_access = desired_access; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; @@ -354,7 +355,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if we can open a file with a share mode ****************************************************************************/ -static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, +static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access, const char *fname, BOOL fcbopen, int *flags) { int deny_mode = GET_DENY_MODE(share_mode); @@ -382,12 +383,43 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i return False; } + /* this is a nasty hack, but necessary until we rewrite our open + handling to use a NTCreateX call as the basic call. + NT may open a file with neither read nor write access, and in + this case it expects the open not to conflict with any + existing deny modes. This happens (for example) during a + "xcopy /o" where the second file descriptor is used for + ACL sets + (tridge) + */ + + /* + * This is a bit wierd - the test for desired access not having the + * critical bits seems seems odd. Firstly, if both opens have no + * critical bits then always ignore. Then check the "allow delete" + * then check for either. This probably isn't quite right yet but + * gets us much closer. JRA. + */ + + /* + * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE + * and the existing desired_acces then share modes don't conflict. + */ + + if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) && + !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \ +and existing desired access (0x%x) are non-data opens\n", + fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); + return True; + } + /* * If delete access was requested and the existing share mode doesn't have * ALLOW_SHARE_DELETE then deny. */ - if (GET_DELETE_ACCESS_REQUESTED(share_mode) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { + if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", fname )); unix_ERR_class = ERRDOS; @@ -402,7 +434,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i * ALLOW_SHARE_DELETE then deny. */ - if (GET_DELETE_ACCESS_REQUESTED(share->share_mode) && !GET_ALLOW_SHARE_DELETE(share_mode)) { + if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", fname )); unix_ERR_class = ERRDOS; @@ -411,9 +443,21 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i return False; } + /* + * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE + * then share modes don't conflict. Likewise with existing desired access. + */ + + if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with\ +existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); + return True; + } + { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == sys_getpid()),is_executable(fname)); + (share->pid == sys_getpid()),is_executable(fname)); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || @@ -523,28 +567,13 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou *p_all_current_opens_are_level_II = False; } - /* this is a nasty hack, but necessary until we rewrite our open - handling to use a NTCreateX call as the basic call. - NT may open a file with neither read nor write access, and in - this case it expects the open not to conflict with any - existing deny modes. This happens (for example) during a - "xcopy /o" where the second file descriptor is used for - ACL sets - This code should be removed once we have a propoer ntcreateX - open functions - (tridge) - */ - if (desired_access == 0 || - (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE))) { - /* someone else has a share lock on it, check to see - if we can too */ - if (!check_share_mode(conn, share_entry, share_mode, - fname, fcbopen, p_flags)) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; - } - } + /* someone else has a share lock on it, check to see if we can too */ + if (!check_share_mode(conn, share_entry, share_mode, desired_access, + fname, fcbopen, p_flags)) { + SAFE_FREE(old_shares); + errno = EACCES; + return -1; + } } /* end for */ @@ -653,7 +682,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); - BOOL delete_access_requested = GET_DELETE_ACCESS_REQUESTED(share_mode); BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; @@ -732,16 +760,24 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ switch (GET_OPEN_MODE(share_mode)) { case DOS_OPEN_WRONLY: flags = O_WRONLY; + if (desired_access == 0) + desired_access = FILE_WRITE_DATA; break; case DOS_OPEN_FCB: fcbopen = True; flags = O_RDWR; + if (desired_access == 0) + desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; case DOS_OPEN_RDWR: flags = O_RDWR; + if (desired_access == 0) + desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; default: flags = O_RDONLY; + if (desired_access == 0) + desired_access = FILE_READ_DATA; break; } @@ -922,8 +958,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", fsp->share_mode = SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode) | - SET_ALLOW_SHARE_DELETE(allow_share_delete) | - SET_DELETE_ACCESS_REQUESTED(delete_access_requested); + SET_ALLOW_SHARE_DELETE(allow_share_delete); DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); @@ -1036,8 +1071,8 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, char *fname, - SMB_STRUCT_STAT *psbuf, int share_mode, int smb_ofun, mode_t unixmode, int *action) +files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, + uint32 desired_access, int share_mode, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; BOOL got_stat = False; @@ -1136,6 +1171,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->can_read = False; fsp->can_write = False; fsp->share_mode = share_mode; + fsp->desired_access = desired_access; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; @@ -1157,6 +1193,9 @@ files_struct *open_directory(connection_struct *conn, char *fname, return fsp; } +#if 0 + +Old code - I have replaced with correct desired_access checking. JRA. /******************************************************************* Check if the share mode on a file allows it to be deleted or unlinked. @@ -1165,149 +1204,107 @@ files_struct *open_directory(connection_struct *conn, char *fname, BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) { - int i; - int ret = False; - share_mode_entry *old_shares = 0; - int num_share_modes; - SMB_STRUCT_STAT sbuf; - pid_t pid = sys_getpid(); - SMB_DEV_T dev; - SMB_INO_T inode; - - if (vfs_stat(conn,fname,&sbuf) == -1) - return(True); - - dev = sbuf.st_dev; - inode = sbuf.st_ino; - - lock_share_entry(conn, dev, inode); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - - /* - * Check if the share modes will give us access. - */ - - if(num_share_modes != 0) - { - BOOL broke_oplock; - - do - { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * Break oplocks before checking share modes. See comment in - * open_file_shared for details. - * Check if someone has an oplock on this file. If so we must - * break it before continuing. - */ - if(BATCH_OPLOCK_TYPE(share_entry->op_type)) - { + int i; + int ret = False; + share_mode_entry *old_shares = 0; + int num_share_modes; + SMB_STRUCT_STAT sbuf; + pid_t pid = sys_getpid(); + SMB_DEV_T dev; + SMB_INO_T inode; -#if 0 + if (vfs_stat(conn,fname,&sbuf) == -1) + return(True); -/* JRA. Try removing this code to see if the new oplock changes - fix the problem. I'm dubious, but Andrew is recommending we - try this.... -*/ + dev = sbuf.st_dev; + inode = sbuf.st_ino; - /* - * It appears that the NT redirector may have a bug, in that - * it tries to do an SMBmv on a file that it has open with a - * batch oplock, and then fails to respond to the oplock break - * request. This only seems to occur when the client is doing an - * SMBmv to the smbd it is using - thus we try and detect this - * condition by checking if the file being moved is open and oplocked by - * this smbd process, and then not sending the oplock break in this - * special case. If the file was open with a deny mode that - * prevents the move the SMBmv will fail anyway with a share - * violation error. JRA. - */ - if(rename_op && (share_entry->pid == pid)) - { - - DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ -batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); - - /* - * This next line is a test that allows the deny-mode - * processing to be skipped. This seems to be needed as - * NT insists on the rename succeeding (in Office 9x no less !). - * This should be removed as soon as (a) MS fix the redirector - * bug or (b) NT SMB support in Samba makes NT not issue the - * call (as is my fervent hope). JRA. - */ - continue; - } - else -#endif /* 0 */ - { - - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ + lock_share_entry(conn, dev, inode); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + + /* + * Check if the share modes will give us access. + */ + + if(num_share_modes != 0) { + BOOL broke_oplock; + + do { + + broke_oplock = False; + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + + /* + * Break oplocks before checking share modes. See comment in + * open_file_shared for details. + * Check if someone has an oplock on this file. If so we must + * break it before continuing. + */ + if(BATCH_OPLOCK_TYPE(share_entry->op_type)) { + + DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode); - if(request_oplock_break(share_entry) == False) - { - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ + /* Oplock break.... */ + unlock_share_entry(conn, dev, inode); + + if(request_oplock_break(share_entry) == False) { + DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); - SAFE_FREE(old_shares); - return False; - } - lock_share_entry(conn, dev, inode); - broke_oplock = True; - break; - } - } - - /* - * If this is a delete request and ALLOW_SHARE_DELETE is set then allow - * this to proceed. This takes precedence over share modes. - */ - - if(!rename_op && GET_ALLOW_SHARE_DELETE(share_entry->share_mode)) - continue; - - /* - * Someone else has a share lock on it, check to see - * if we can too. - */ - - if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || - (share_entry->pid != pid)) - goto free_and_exit; - - } /* end for */ - - if(broke_oplock) - { - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - } - } while(broke_oplock); - } - - /* XXXX exactly what share mode combinations should be allowed for - deleting/renaming? */ - /* - * If we got here then either there were no share modes or - * all share modes were DENY_DOS and the pid == getpid() or - * delete access was requested and all share modes had the - * ALLOW_SHARE_DELETE bit set (takes precedence over other - * share modes). - */ - - ret = True; + SAFE_FREE(old_shares); + return False; + } + lock_share_entry(conn, dev, inode); + broke_oplock = True; + break; + } + + /* + * If this is a delete request and ALLOW_SHARE_DELETE is set then allow + * this to proceed. This takes precedence over share modes. + */ + + if(!rename_op && GET_ALLOW_SHARE_DELETE(share_entry->share_mode)) + continue; + + /* + * Someone else has a share lock on it, check to see + * if we can too. + */ + if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || + (share_entry->pid != pid)) + goto free_and_exit; + + } /* end for */ + + if(broke_oplock) { + SAFE_FREE(old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + } + } while(broke_oplock); + } + + /* + * XXXX exactly what share mode combinations should be allowed for + * deleting/renaming? + */ + + /* + * If we got here then either there were no share modes or + * all share modes were DENY_DOS and the pid == getpid() or + * delete access was requested and all share modes had the + * ALLOW_SHARE_DELETE bit set (takes precedence over other + * share modes). + */ + + ret = True; free_and_exit: - unlock_share_entry(conn, dev, inode); - SAFE_FREE(old_shares); - return(ret); + unlock_share_entry(conn, dev, inode); + SAFE_FREE(old_shares); + return(ret); } +#endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4dcb674ff1..b556862e68 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1206,6 +1206,41 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(outsize); } +/******************************************************************* + Check if a user is allowed to rename a file. +********************************************************************/ + +static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst) +{ + int smb_action; + int access_mode; + files_struct *fsp; + + if (!CAN_WRITE(conn)) + return NT_STATUS_MEDIA_WRITE_PROTECTED; + + if (S_ISDIR(pst->st_mode)) + return NT_STATUS_OK; + + /* We need a better way to return NT status codes from open... */ + unix_ERR_class = 0; + unix_ERR_code = 0; + + fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + + if (!fsp) { + NTSTATUS ret = NT_STATUS_ACCESS_DENIED; + if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) + ret = NT_STATUS_SHARING_VIOLATION; + unix_ERR_class = 0; + unix_ERR_code = 0; + return ret; + } + close_file(fsp,False); + return NT_STATUS_OK; +} + /******************************************************************* Check if a user is allowed to delete a file. ********************************************************************/ @@ -1214,6 +1249,9 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) { SMB_STRUCT_STAT sbuf; int fmode; + int smb_action; + int access_mode; + files_struct *fsp; if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; @@ -1231,9 +1269,22 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return NT_STATUS_CANNOT_DELETE; - if (!check_file_sharing(conn,fname,False)) - return NT_STATUS_SHARING_VIOLATION; + /* We need a better way to return NT status codes from open... */ + unix_ERR_class = 0; + unix_ERR_code = 0; + + fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + if (!fsp) { + NTSTATUS ret = NT_STATUS_ACCESS_DENIED; + if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) + ret = NT_STATUS_SHARING_VIOLATION; + unix_ERR_class = 0; + unix_ERR_code = 0; + return ret; + } + close_file(fsp,False); return NT_STATUS_OK; } @@ -2950,21 +3001,6 @@ static BOOL resolve_wildcards(char *name1,char *name2) return(True); } -/******************************************************************* - Check if a user is allowed to rename a file. -********************************************************************/ - -static NTSTATUS can_rename(char *fname,connection_struct *conn) -{ - if (!CAN_WRITE(conn)) - return NT_STATUS_ACCESS_DENIED; - - if (!check_file_sharing(conn,fname,True)) - return NT_STATUS_SHARING_VIOLATION; - - return NT_STATUS_OK; -} - /**************************************************************************** The guts of the rename command, split out so it may be called by the NT SMB code. @@ -3099,7 +3135,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", * The source object must exist. */ - if (!vfs_object_exist(conn, directory, NULL)) { + if (!vfs_object_exist(conn, directory, &sbuf1)) { DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n", directory,newname)); @@ -3124,7 +3160,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", return error; } - error = can_rename(directory,conn); + error = can_rename(directory,conn,&sbuf1); if (!NT_STATUS_IS_OK(error)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", @@ -3190,7 +3226,12 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", error = NT_STATUS_ACCESS_DENIED; slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); - error = can_rename(fname,conn); + if (!vfs_object_exist(conn, fname, &sbuf1)) { + error = NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error))); + continue; + } + error = can_rename(fname,conn,&sbuf1); if (!NT_STATUS_IS_OK(error)) { DEBUG(6,("rename %s refused\n", fname)); continue; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 185fe1c633..5d0ee08f42 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1861,7 +1861,7 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) * Only allow delete on close for files/directories opened with delete intent. */ - if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) { + if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) { DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n", fsp->fsp_name )); return NT_STATUS_ACCESS_DENIED; -- cgit From 1c92b99c80632bfdaeba60be2ba885ad84285460 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 23 Mar 2002 09:00:27 +0000 Subject: Correctly store the hostname of the remote machine if so configured. If the reverse DNS fails, then store the IP. (This used to be commit d97771aa80b48fbdb9cae3e9712e35fcc895b148) --- source3/smbd/session.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 6f9d62edfd..05a7b24da2 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -78,11 +78,13 @@ BOOL session_claim(user_struct *vuser) } /* If 'hostname lookup' == yes, then do the DNS lookup. This is - needed becouse utmp and PAM both expect DNS names */ + needed becouse utmp and PAM both expect DNS names + + client_name() handles this case internally. + */ - if (lp_hostname_lookups()) { - hostname = client_name(); - } else { + hostname = client_name(); + if (strcmp(hostname, "UNKNOWN") == 0) { hostname = client_addr(); } -- cgit From 81a0d5b5e92d7c8d5d426f8bd13d43ff394fe7e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Mar 2002 00:38:12 +0000 Subject: Matched W2K *insane* open semantics.... Jeremy. (This used to be commit 6819e81da490914d2db91c4d2419d408b8d4c818) --- source3/smbd/open.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bcb866c378..29a854a397 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -408,6 +408,24 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) && !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + + /* + * Wrinkle discovered by smbtorture.... + * If both are non-io open and requester is asking for delete and current open has delete access + * but neither open has allowed file share delete then deny.... this is very strange and + * seems to be the only case in which non-io opens conflict. JRA. + */ + + if ((desired_access & DELETE_ACCESS) && (share->desired_access & DELETE_ACCESS) && + (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) { + DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n", + fname )); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + return False; + } + DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \ and existing desired access (0x%x) are non-data opens\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); -- cgit From 8f9d7ebb35f40ab6bda8f1d6d940df8b6aec4126 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Mar 2002 03:07:51 +0000 Subject: Removed unused variable. Jeremy. (This used to be commit 4eb29ac559faf29b348a4097a33f9cbf4cf9d057) --- source3/smbd/reply.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b556862e68..06f068dccc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1301,7 +1301,6 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) int count=0; NTSTATUS error = NT_STATUS_OK; BOOL has_wild; - BOOL exists=False; BOOL bad_path = False; BOOL rc = True; SMB_STRUCT_STAT sbuf; @@ -1343,8 +1342,6 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (vfs_unlink(conn,directory) == 0) { count++; } - if (!count) - exists = vfs_file_exist(conn,directory,&sbuf); } else { void *dirptr = NULL; char *dname; -- cgit From 7d7c594644d9b374e522f208b1f0bd5ab8abb9ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Mar 2002 03:00:39 +0000 Subject: Removed HAVE_LIBDL from most places (except system.c). Added checks for dlopen & friends into configure.in. This should help building on *BSD where dl*** calls are in libc. Jeremy (This used to be commit ac1baba35d7a399bf800ced49a4384e39955e3eb) --- source3/smbd/conn.c | 2 - source3/smbd/vfs.c | 422 ++++++++++++++++++++++++---------------------------- 2 files changed, 194 insertions(+), 230 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 55b2d28272..f552d4a224 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -164,12 +164,10 @@ void conn_free(connection_struct *conn) { /* Free vfs_connection_struct */ -#ifdef HAVE_LIBDL if (conn->dl_handle != NULL) { /* Close dlopen() handle */ dlclose(conn->dl_handle); } -#endif /* HAVE_LIBDL */ DLIST_REMOVE(Connections, conn); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 6416d8e73e..4e2e353ed8 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -119,50 +119,47 @@ struct vfs_ops default_vfs_ops = { static BOOL vfs_init_default(connection_struct *conn) { - DEBUG(3, ("Initialising default vfs hooks\n")); + DEBUG(3, ("Initialising default vfs hooks\n")); - memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops)); - return True; + memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops)); + return True; } /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ -#ifdef HAVE_LIBDL static BOOL vfs_init_custom(connection_struct *conn) { int vfs_version = -1; - struct vfs_ops *ops, *(*init_fptr)(int *, struct vfs_ops *); + struct vfs_ops *ops, *(*init_fptr)(int *, struct vfs_ops *); - DEBUG(3, ("Initialising custom vfs hooks from %s\n", - lp_vfsobj(SNUM(conn)))); + DEBUG(3, ("Initialising custom vfs hooks from %s\n", lp_vfsobj(SNUM(conn)))); - /* Open object file */ + /* Open object file */ - if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { + if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); return False; - } + } - /* Get handle on vfs_init() symbol */ + /* Get handle on vfs_init() symbol */ - init_fptr = (struct vfs_ops *(*)(int *, struct vfs_ops *))sys_dlsym(conn->dl_handle, "vfs_init"); + init_fptr = (struct vfs_ops *(*)(int *, struct vfs_ops *))sys_dlsym(conn->dl_handle, "vfs_init"); - if (init_fptr == NULL) { - DEBUG(0, ("No vfs_init() symbol found in %s\n", - lp_vfsobj(SNUM(conn)))); + if (init_fptr == NULL) { + DEBUG(0, ("No vfs_init() symbol found in %s\n", lp_vfsobj(SNUM(conn)))); return False; - } + } - /* Initialise vfs_ops structure */ + /* Initialise vfs_ops structure */ conn->vfs_ops = default_vfs_ops; - if ((ops = init_fptr(&vfs_version, &default_vfs_ops)) == NULL) { - DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); + if ((ops = init_fptr(&vfs_version, &default_vfs_ops)) == NULL) { + DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); return False; - } + } if (vfs_version != SMB_VFS_INTERFACE_VERSION) { DEBUG(0, ("vfs_init returned wrong interface version info (was %d, should be %d)\n", @@ -174,9 +171,8 @@ static BOOL vfs_init_custom(connection_struct *conn) memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); } - return True; + return True; } -#endif /***************************************************************** Generic VFS init. @@ -185,7 +181,6 @@ static BOOL vfs_init_custom(connection_struct *conn) BOOL smbd_vfs_init(connection_struct *conn) { if (*lp_vfsobj(SNUM(conn))) { -#ifdef HAVE_LIBDL /* Loadable object file */ @@ -195,10 +190,6 @@ BOOL smbd_vfs_init(connection_struct *conn) } return True; -#else - DEBUG(0, ("smbd_vfs_init: No libdl present - cannot use VFS objects\n")); - return False; -#endif } /* Normal share - initialise with disk access functions */ @@ -305,7 +296,7 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) while (total < byte_count) { ssize_t ret = fsp->conn->vfs_ops.read(fsp, fsp->fd, buf + total, - byte_count - total); + byte_count - total); if (ret == 0) return total; if (ret == -1) { @@ -571,12 +562,11 @@ int vfs_ChDir(connection_struct *conn, char *path) /* 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 *dos_path; /* The pathname in DOS format. */ - BOOL valid; +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 *dos_path; /* The pathname in DOS format. */ + BOOL valid; } ino_list[MAX_GETWDCACHE]; extern BOOL use_getwd_cache; @@ -612,98 +602,86 @@ static void array_promote(char *array,int elsize,int element) char *vfs_GetWd(connection_struct *conn, char *path) { - pstring s; - static BOOL getwd_cache_init = False; - SMB_STRUCT_STAT st, st2; - int i; - - *s = 0; - - if (!use_getwd_cache) - return(vfs_getwd(conn,path)); - - /* init the cache */ - if (!getwd_cache_init) - { - getwd_cache_init = True; - for (i=0;i Date: Thu, 28 Mar 2002 01:00:31 +0000 Subject: Ensure that setting file length can return disk full on failure. Jeremy. (This used to be commit 14e2beca9b8fa1c8d893013f52f42b2721a82758) --- source3/smbd/trans2.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5d0ee08f42..aca7e47d48 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2279,6 +2279,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(size != sbuf.st_size) { + int ret; + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", fname, (double)size )); @@ -2304,11 +2306,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); - vfs_set_filelen(new_fsp, size); + ret = vfs_set_filelen(new_fsp, size); close_file(new_fsp,True); } else { - vfs_set_filelen(fsp, size); + ret = vfs_set_filelen(fsp, size); } + + if (ret == -1) + return (UNIXERROR(ERRHRD,ERRdiskfull)); } SSVAL(params,0,0); -- cgit From 14f0beb21cebe319c34e25dbb685c6b30fe10561 Mon Sep 17 00:00:00 2001 From: Jean-François Micouleau Date: Fri, 29 Mar 2002 14:28:38 +0000 Subject: added shutdown to smbd J.F. (This used to be commit 51a5bbfee71e064c73283a090e9e922a31b1e21b) --- source3/smbd/server.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8a5983d784..a9f3989735 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -141,6 +141,11 @@ static BOOL open_sockets_inetd(void) return True; } +static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) +{ + exit_server("Got a SHUTDOWN message"); +} + /**************************************************************************** Open the socket communication. @@ -242,6 +247,7 @@ max can be %d\n", message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); message_register(MSG_SMB_SAM_REPL, msg_sam_repl); + message_register(MSG_SHUTDOWN, msg_exit_server); /* now accept incoming connections - forking a new process for each incoming connection */ -- cgit From 2a664807c53c2af335b1473bfef1a03071e4852c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Apr 2002 19:34:36 +0000 Subject: Fixed the error bad path for recursive mkdir so mkdir \a\b\c\d works. Forward ported some of the code tidyups from 2.2. Jeremy. (This used to be commit 2475c09b354cc7b5f4ce384e4497207d30f619bb) --- source3/smbd/nttrans.c | 34 ++++++------------------------ source3/smbd/reply.c | 56 ++++++++++++-------------------------------------- source3/smbd/trans2.c | 14 +++++++++++++ 3 files changed, 33 insertions(+), 71 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ba6fd3eb44..2c0955c834 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -685,10 +685,7 @@ int reply_ntcreate_and_X(connection_struct *conn, restore_case_semantics(file_attributes); if(!fsp) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -755,22 +752,14 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!fsp) { restore_case_semantics(file_attributes); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - restore_case_semantics(file_attributes); - + set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1180,10 +1169,7 @@ static int call_nt_transact_create(connection_struct *conn, if(!fsp) { restore_case_semantics(file_attributes); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1217,21 +1203,13 @@ static int call_nt_transact_create(connection_struct *conn, if(!fsp) { restore_case_semantics(file_attributes); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - restore_case_semantics(file_attributes); - + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 06f068dccc..af582f1a41 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -463,12 +463,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!ok) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - + set_bad_path_error(errno, bad_path); END_PROFILE(SMBgetatr); return(UNIXERROR(ERRDOS,ERRbadfile)); } @@ -527,12 +522,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!ok) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - + set_bad_path_error(errno, bad_path); END_PROFILE(SMBsetatr); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -678,12 +668,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size { if(dptr_num == -2) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - END_PROFILE(SMBsearch); + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBsearch); return (UNIXERROR(ERRDOS,ERRnofids)); } END_PROFILE(SMBsearch); @@ -857,11 +843,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); END_PROFILE(SMBopen); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -951,11 +933,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (!fsp) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); END_PROFILE(SMBopenX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1090,11 +1068,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); END_PROFILE(SMBcreate); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1164,11 +1138,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* close fd from smb_mkstemp() */ close(tmpfd); - if (!fsp) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + if (!fsp) { + set_bad_path_error(errno, bad_path); END_PROFILE(SMBctemp); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2724,6 +2695,9 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret == -1) { + NTSTATUS nterr = set_bad_path_error(errno, bad_path); + if (!NT_STATUS_IS_OK(nterr)) + return nterr; return map_nt_error_from_unix(errno); } @@ -2916,11 +2890,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!ok) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); END_PROFILE(SMBrmdir); return(UNIXERROR(ERRDOS,ERRbadpath)); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index aca7e47d48..ca8ad5fa79 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1412,6 +1412,20 @@ static int call_trans2setfsinfo(connection_struct *conn, return outsize; } +/**************************************************************************** + * Utility function to set bad path error. + ****************************************************************************/ + +NTSTATUS set_bad_path_error(int err, BOOL bad_path) +{ + if((err == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by file name or file id). -- cgit From c21ff8f76209a1e7138ba06ce262a3e2c2880646 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 8 Apr 2002 01:58:44 +0000 Subject: Reintroduce the 2.2 name mangling code, until we get are more flexible solution. Even for a hash/cache setup, this code needs some more work, in particular it needs to use mangle_get_prefix() etc and to move to unicode internals. Andrew Bartlett (This used to be commit ad8aa470575c39fcbc7f1440bf1081d7ea31c0aa) --- source3/smbd/filename.c | 15 +- source3/smbd/mangle.c | 1605 +++++++++++++++++++++++------------------------ source3/smbd/reply.c | 11 +- source3/smbd/server.c | 4 - 4 files changed, 805 insertions(+), 830 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3053e8a1d8..8bd09691e4 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -75,6 +75,17 @@ static BOOL fname_equal(char *name1, char *name2) ****************************************************************************/ static BOOL mangled_equal(char *name1, char *name2) { +#if 1 + pstring tmpname; + if (is_8_3(name2, True)) { + return False; + } + + pstrcpy(tmpname, name2); + mangle_name_83(tmpname); + + return strequal(name1, tmpname); +#else char *tmpname; BOOL ret = False; @@ -86,6 +97,8 @@ static BOOL mangled_equal(char *name1, char *name2) SAFE_FREE(tmpname); } return ret; +#endif + } @@ -116,7 +129,7 @@ stat struct will be filled with zeros (and this can be detected by checking for nlinks = 0, which can never be true for any file). ****************************************************************************/ -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, +BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index cfa71e3cf4..9789f06e0c 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1,6 +1,7 @@ /* Unix SMB/CIFS implementation. - Name mangling with persistent tdb + Name mangling + Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Simo Sorce 2001 Copyright (C) Andrew Bartlett 2002 @@ -19,9 +20,31 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/**************************************************************************** - Rewritten from scrach in 2001 by Simo Sorce - ****************************************************************************/ +/* -------------------------------------------------------------------------- ** + * Notable problems... + * + * March/April 1998 CRH + * - Many of the functions in this module overwrite string buffers passed to + * them. This causes a variety of problems and is, generally speaking, + * dangerous and scarry. See the kludge notes in name_map_mangle() + * below. + * - It seems that something is calling name_map_mangle() twice. The + * first call is probably some sort of test. Names which contain + * illegal characters are being doubly mangled. I'm not sure, but + * I'm guessing the problem is in server.c. + * + * -------------------------------------------------------------------------- ** + */ + +/* -------------------------------------------------------------------------- ** + * History... + * + * March/April 1998 CRH + * Updated a bit. Rewrote is_mangled() to be a bit more selective. + * Rewrote the mangled name cache. Added comments here and there. + * &c. + * -------------------------------------------------------------------------- ** + */ #include "includes.h" @@ -33,66 +56,106 @@ extern int case_default; /* Are conforming 8.3 names all upper or lower? */ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ +/* -------------------------------------------------------------------------- ** + * Other stuff... + * + * magic_char - This is the magic char used for mangling. It's + * global. There is a call to lp_magicchar() in server.c + * that is used to override the initial value. + * + * MANGLE_BASE - This is the number of characters we use for name mangling. + * + * basechars - The set characters used for name mangling. This + * is static (scope is this file only). + * + * mangle() - Macro used to select a character from basechars (i.e., + * mangle(n) will return the nth digit, modulo MANGLE_BASE). + * + * chartest - array 0..255. The index range is the set of all possible + * values of a byte. For each byte value, the content is a + * two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK, + * below. + * + * ct_initialized - False until the chartest array has been initialized via + * a call to init_chartest(). + * + * BASECHAR_MASK - Masks the upper nibble of a one-byte value. + * + * ILLEGAL_MASK - Masks the lower nibble of a one-byte value. + * + * isbasecahr() - Given a character, check the chartest array to see + * if that character is in the basechars set. This is + * faster than using strchr_m(). + * + * isillegal() - Given a character, check the chartest array to see + * if that character is in the illegal characters set. + * This is faster than using strchr_m(). + * + * mangled_cache - Cache header used for storing mangled -> original + * reverse maps. + * + * mc_initialized - False until the mangled_cache structure has been + * initialized via a call to reset_mangled_cache(). + * + * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the + * cache. A value of 0 indicates "infinite". + * + * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the + * cache. When the cache was kept as an array of 256 + * byte strings, the default cache size was 50 entries. + * This required a fixed 12.5Kbytes of memory. The + * mangled stack parameter is no longer used (though + * this might change). We're now using a fixed 16Kbyte + * maximum cache size. This will probably be much more + * than 50 entries. + */ + char magic_char = '~'; -/* -------------------------------------------------------------------- */ +static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; +#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) -#define MANGLE_TDB_VERSION "20010927" -#define MANGLE_TDB_FILE_NAME "mangle.tdb" -#define MANGLED_PREFIX "MANGLED_" -#define LONG_PREFIX "LONG_" -#define COUNTER_PREFIX "COUNTER_" -#define MANGLE_COUNTER_MAX 99 -#define MANGLE_SUFFIX_SIZE 3 /* "~XX" */ +static unsigned char chartest[256] = { 0 }; +static BOOL ct_initialized = False; +#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) +#define BASECHAR_MASK 0xf0 +#define ILLEGAL_MASK 0x0f +#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) +#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) -static TDB_CONTEXT *mangle_tdb; +static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } }; +static BOOL mc_initialized = False; +#define MANGLED_CACHE_MAX_ENTRIES 0 +#define MANGLED_CACHE_MAX_MEMORY 16384 -BOOL init_mangle_tdb(void) -{ - char *tdbfile; - - tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */ - /* Open tdb */ - if (!(mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) - { - DEBUG(0, ("Unable to open Mangle TDB\n")); - return False; - } +/* -------------------------------------------------------------------------- ** + * External Variables... + */ - return True; -} +extern int case_default; /* Are conforming 8.3 names all upper or lower? */ +extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ -/* trasform a unicode string into a dos charset string */ -static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len) -{ - int src_len, ret; +/* -------------------------------------------------------------------- */ - if (dest_len == -1) { - dest_len = sizeof(pstring); - } +NTSTATUS has_valid_chars(const smb_ucs2_t *s) +{ + if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; - src_len = strlen_w(src)* sizeof(smb_ucs2_t); + DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */ - ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len); - if (dest_len) dest[MIN(ret, dest_len-1)] = 0; - - return ret; -} - -/* trasform in a string that contain only valid chars for win filenames, - not including a '.' */ -static void strvalid(smb_ucs2_t *src) -{ - if (!src || !*src) return; + /* CHECK: this should not be necessary if the ms wild chars + are not valid in valid.dat --- simo */ + if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL; - while (*src) { - if (!isvalid83_w(*src) || *src == UCS2_CHAR('.')) *src = UCS2_CHAR('_'); - src++; + while (*s) { + if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL; + s++; } -} + return NT_STATUS_OK; +} /* return False if something fail and * return 2 alloced unicode strings that contain prefix and extension @@ -128,523 +191,18 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr return NT_STATUS_OK; } - -/* mangled must contain only the file name, not a path. - and MUST be ZERO terminated */ -smb_ucs2_t *unmangle(const smb_ucs2_t *mangled) -{ - TDB_DATA data, key; - fstring keystr; - fstring mufname; - smb_ucs2_t *pref, *ext, *retstr; - size_t long_len, ext_len, muf_len; - - if (strlen_w(mangled) > 12) return NULL; - if (!strchr_w(mangled, UCS2_CHAR('~'))) return NULL; - - /* if it is a path refuse to proceed */ - if (strchr_w(mangled, UCS2_CHAR('/'))) { - DEBUG(10, ("unmangle: cannot unmangle a path\n")); - return NULL; - } - - if (NT_STATUS_IS_ERR(mangle_get_prefix(mangled, &pref, &ext))) - return NULL; - - /* mangled names are stored lowercase only */ - strlower_w(pref); - /* set search key */ - muf_len = ucs2_to_dos(mufname, pref, sizeof(mufname)); - SAFE_FREE(pref); - if (!muf_len) return NULL; - - slprintf(keystr, sizeof(keystr) - 1, "%s%s", MANGLED_PREFIX, mufname); - key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - - /* get the record */ - data = tdb_fetch(mangle_tdb, key); - - if (!data.dptr) /* not found */ - { - DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(mangle_tdb))); - retstr = NULL; - goto done; - } - - if (ext) - { - long_len = (data.dsize / 2) - 1; - ext_len = strlen_w(ext); - retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 2)*sizeof(smb_ucs2_t)); - if (!retstr) - { - DEBUG(0, ("unamngle: out of memory!\n")); - goto done; - } - strncpy_w(retstr, (smb_ucs2_t *)data.dptr, long_len); - retstr[long_len] = UCS2_CHAR('.'); - retstr[long_len + 1] = 0; - strncat_w(retstr, ext, ext_len); - } - else - { - retstr = strdup_w((smb_ucs2_t *)data.dptr); - if (!retstr) - { - DEBUG(0, ("unamngle: out of memory!\n")); - goto done; - } - - } - -done: - SAFE_FREE(data.dptr); - SAFE_FREE(pref); - SAFE_FREE(ext); - - return retstr; -} - -/* unmangled must contain only the file name, not a path. - and MUST be ZERO terminated. - return a new allocated string if the name is yet valid 8.3 - or is mangled successfully. - return null on error. +/* ************************************************************************** ** + * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name. + * + * Input: fname - String containing the name to be tested. + * + * Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names. + * + * Notes: This is a static function called by is_8_3(), below. + * + * ************************************************************************** ** */ - -smb_ucs2_t *mangle(const smb_ucs2_t *unmangled) -{ - TDB_DATA data, key, klock; - pstring keystr; - pstring longname; - fstring keylock; - fstring mufname; - fstring prefix; - BOOL tclock = False; - char suffix[7]; - smb_ucs2_t *mangled = NULL; - smb_ucs2_t *umpref, *ext, *p = NULL; - size_t pref_len, ext_len, ud83_len; - - /* if it is a path refuse to proceed */ - if (strchr_w(unmangled, UCS2_CHAR('/'))) { - DEBUG(10, ("mangle: cannot mangle a path\n")); - return NULL; - } - - /* if it is a valid 8_3 do not mangle again */ - if (NT_STATUS_IS_OK(is_8_3_w(unmangled))) - return NULL; - - if (NT_STATUS_IS_ERR(mangle_get_prefix(unmangled, &umpref, &ext))) - return NULL; - - /* test if the same is yet mangled */ - - /* set search key */ - pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE); - slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - /* get the record */ - data = tdb_fetch (mangle_tdb, key); - if (!data.dptr) /* not found */ - { - smb_ucs2_t temp[9]; - size_t c, pos; - - if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST) - { - DEBUG(0, ("mangle: database retrieval error: %s\n", - tdb_errorstr(mangle_tdb))); - goto done; - } - - /* if not find the first free possibile mangled name */ - - pos = strlen_w(umpref); - if ((8 - MANGLE_SUFFIX_SIZE) < pos) - pos = 8 - MANGLE_SUFFIX_SIZE; - pos++; - do - { - pos--; - if (pos == 0) - { - char *unmangled_unix = acnv_u2ux(unmangled); - - DEBUG(0, ("mangle: unable to mangle file name (%s)!\n",unmangled_unix)); - SAFE_FREE(unmangled_unix); - goto done; - } - strncpy_w(temp, umpref, pos); - temp[pos] = 0; - strlower_w(temp); - - /* convert any invalid char into '_' */ - strvalid(temp); - ud83_len = ucs2_to_dos(prefix, temp, sizeof(prefix)); - if (!ud83_len) goto done; - } - while (ud83_len > 8 - MANGLE_SUFFIX_SIZE); - - slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix); - klock.dptr = keylock; - klock.dsize = strlen(keylock) + 1; - - c = 0; - data.dptr = (char *)&c; - data.dsize = sizeof(uint32); - /* try to insert a new counter prefix, if it exist the call will - fail (correct) otherwise it will create a new entry with counter set - to 0 - */ - if(tdb_store(mangle_tdb, klock, data, TDB_INSERT) != TDB_SUCCESS) - { - if (tdb_error(mangle_tdb) != TDB_ERR_EXISTS) - { - char *unmangled_unix = acnv_u2ux(unmangled); - DEBUG(0, ("mangle: database store error: %s for filename: %s\n", - tdb_errorstr(mangle_tdb), unmangled_unix)); - SAFE_FREE(unmangled_unix); - goto done; - } - } - - /* lock the mangle counter for this prefix */ - if (tdb_chainlock(mangle_tdb, klock)) - { - char *unmangled_unix = acnv_u2ux(unmangled); - - DEBUG(0,("mangle: failed to lock database for filename %s\n!", unmangled_unix)); - SAFE_FREE(unmangled_unix); - goto done; - } - tclock = True; - - data = tdb_fetch(mangle_tdb, klock); - if (!data.dptr) - { - char *unmangled_unix = acnv_u2ux(unmangled); - - DEBUG(0, ("mangle: database retrieval error: %s for filename: %s\n", - tdb_errorstr(mangle_tdb), unmangled_unix)); - SAFE_FREE(unmangled_unix); - goto done; - } - c = *((uint32 *)data.dptr); - c++; - - if (c > MANGLE_COUNTER_MAX) - { - char *unmangled_unix = acnv_u2ux(unmangled); - - DEBUG(0, ("mangle: error, counter overflow (max=%d, counter=%d) for file: [%s] prefix (dos charset): [%s]!\n", MANGLE_COUNTER_MAX, c, unmangled_unix, prefix)); - SAFE_FREE(unmangled_unix); - goto done; - } - - temp[pos] = UCS2_CHAR('~'); - temp[pos+1] = 0; - snprintf(suffix, 7, "%.6d", c); - strncat_wa(temp, &suffix[7 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE); - - ud83_len = ucs2_to_dos(mufname, temp, sizeof(mufname)); - if (!ud83_len) goto done; - if (ud83_len > 8) - { - char *unmangled_unix = acnv_u2ux(unmangled); - - DEBUG(0, ("mangle: darn, logic error aborting! Filename was %s\n", unmangled_unix)); - SAFE_FREE(unmangled_unix); - goto done; - } - - /* store the long entry with mangled key */ - slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); - key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - data.dsize = (strlen_w(umpref) + 1) * sizeof (smb_ucs2_t); - data.dptr = (void *)umpref; - - if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) - { - char *unmangled_unix = acnv_u2ux(unmangled); - - DEBUG(0, ("mangle: database store error: %s for filename: %s\n", - tdb_errorstr(mangle_tdb), unmangled_unix)); - SAFE_FREE(unmangled_unix); - goto done; - } - - /* store the mangled entry with long key*/ - pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE); - slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); - key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - data.dsize = strlen(mufname) + 1; - data.dptr = mufname; - if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) - { - char *unmangled_unix = acnv_u2ux(unmangled); - DEBUG(0, ("mangle: database store failed: %s for filename: %s\n", - tdb_errorstr(mangle_tdb), unmangled_unix)); - SAFE_FREE(unmangled_unix); - - /* try to delete the mangled key entry to avoid later inconsistency */ - slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); - key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - if (!tdb_delete(mangle_tdb, key)) - { - DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); - } - goto done; - } - - p = strdup_w(temp); - if (!p) - { - DEBUG(0,("mangle: out of memory!\n")); - goto done; - } - - data.dptr = (char *)&c; - data.dsize = sizeof(uint32); - /* store the counter */ - if(tdb_store(mangle_tdb, klock, data, TDB_REPLACE) != TDB_SUCCESS) - { - char *unmangled_unix = acnv_u2ux(unmangled); - DEBUG(0, ("mangle: database store failed: %s for filename: %s\n", - tdb_errorstr(mangle_tdb), unmangled_unix)); - SAFE_FREE(unmangled_unix); - /* try to delete the mangled and long key entry to avoid later inconsistency */ - slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); - key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - if (!tdb_delete(mangle_tdb, key)) - { - DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); - } - slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname); - key.dptr = keystr; - key.dsize = strlen (keystr) + 1; - if (!tdb_delete(mangle_tdb, key)) - { - DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n")); - } - goto done; - } - - tclock = False; - tdb_chainunlock(mangle_tdb, klock); - } - else /* FOUND */ - { - p = acnv_dosu2(data.dptr); - if (!p) - { - DEBUG(0,("mangle: internal error acnv_dosu2() failed!\n")); - goto done; - } - } - - if (ext) - { - pref_len = strlen_w(p); - ext_len = strlen_w(ext); - mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 2)*sizeof(smb_ucs2_t)); - if (!mangled) - { - DEBUG(0,("mangle: out of memory!\n")); - goto done; - } - strncpy_w (mangled, p, pref_len); - mangled[pref_len] = UCS2_CHAR('.'); - mangled[pref_len + 1] = 0; - strncat_w (mangled, ext, ext_len); - } - else - { - mangled = strdup_w(p); - if (!mangled) - { - DEBUG(0,("mangle: out of memory!\n")); - goto done; - } - } - - /* mangled name are returned in upper or lower case depending on - case_default value */ - strnorm_w(mangled); - -done: - if (tclock) tdb_chainunlock(mangle_tdb, klock); - SAFE_FREE(p); - SAFE_FREE(umpref); - SAFE_FREE(ext); - - return mangled; -} - - -/* non unicode compatibility functions */ - -char *dos_mangle(const char *dos_unmangled) -{ - smb_ucs2_t *in, *out; - char *dos_mangled; - - if (!dos_unmangled || !*dos_unmangled) return NULL; - - in = acnv_dosu2(dos_unmangled); - if (!in) - { - DEBUG(0,("dos_mangle: internal error acnv_dosu2() failed!\n")); - return NULL; - } - - out = mangle(in); - if (!out) - { - SAFE_FREE(in); - return NULL; - } - - dos_mangled = acnv_u2dos(out); - if (!dos_mangled) - { - DEBUG(0,("dos_mangle: internal error acnv_u2dos() failed!\n")); - goto done; - } - -done: - SAFE_FREE(in); - SAFE_FREE(out); - return dos_mangled; -} - -char *dos_unmangle(const char *dos_mangled) -{ - smb_ucs2_t *in, *out; - char *dos_unmangled; - - if (!dos_mangled || !*dos_mangled) return NULL; - - in = acnv_dosu2(dos_mangled); - if (!in) - { - DEBUG(0,("dos_unmangle: internal error acnv_dosu2() failed!\n")); - return NULL; - } - - out = unmangle(in); - if (!out) - { - SAFE_FREE(in); - return NULL; - } - - dos_unmangled = acnv_u2dos(out); - if (!dos_unmangled) - { - DEBUG(0,("dos_unmangle: internal error acnv_u2dos failed!\n")); - goto done; - } - -done: - SAFE_FREE(in); - SAFE_FREE(out); - return dos_unmangled; -} - -BOOL is_8_3(const char *fname, BOOL check_case) -{ - const char *f; - smb_ucs2_t *ucs2name; - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - if (!fname || !*fname) return False; - if ((f = strrchr(fname, '/')) == NULL) f = fname; - else f++; - - DEBUG(10,("is_8_3: testing [%s]\n", f)); - - if (strlen(f) > 12) return False; - - ucs2name = acnv_uxu2(f); - if (!ucs2name) - { - DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); - goto done; - } - - ret = is_8_3_w(ucs2name); - -done: - SAFE_FREE(ucs2name); - - DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False")); - - if (NT_STATUS_IS_ERR(ret)) return False; - else return True; -} - -NTSTATUS is_8_3_w(const smb_ucs2_t *fname) -{ - smb_ucs2_t *pref = 0, *ext = 0; - size_t plen; - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; - - DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */ - - if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL; - - if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) - return NT_STATUS_OK; - - if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done; - - if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done; - plen = strlen_w(pref); - - if (strchr_wa(pref, '.')) goto done; - if (plen < 1 || plen > 8) goto done; - if (ext) if (strlen_w(ext) > 3) goto done; - - ret = NT_STATUS_OK; - -done: - SAFE_FREE(pref); - SAFE_FREE(ext); - return ret; -} - -NTSTATUS has_valid_chars(const smb_ucs2_t *s) -{ - NTSTATUS ret = NT_STATUS_OK; - - if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; - - DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */ - - /* CHECK: this should not be necessary if the ms wild chars - are not valid in valid.dat --- simo */ - if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL; - - while (*s) { - if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL; - s++; - } - - return ret; -} - -NTSTATUS is_valid_name(const smb_ucs2_t *fname) +static NTSTATUS is_valid_name(const smb_ucs2_t *fname) { smb_ucs2_t *str, *p; NTSTATUS ret = NT_STATUS_OK; @@ -703,296 +261,703 @@ NTSTATUS is_valid_name(const smb_ucs2_t *fname) return ret; } -BOOL is_mangled(const char *s) -{ - smb_ucs2_t *u2, *res; - BOOL ret = False; - - DEBUG(10,("is_mangled: testing [%s]\n", s)); - - if (!s || !*s) return False; - if ((strlen(s) > 12) || (!strchr(s, '~'))) return False; - - u2 = acnv_dosu2(s); - if (!u2) - { - DEBUG(0,("is_mangled: internal error acnv_dosu2() failed!!\n")); - return ret; - } - - res = unmangle(u2); - if (res) ret = True; - SAFE_FREE(res); - SAFE_FREE(u2); - DEBUG(10,("is_mangled: returning [%s]\n", ret?"True":"False")); - return ret; -} - -NTSTATUS is_mangled_w(const smb_ucs2_t *s) -{ - smb_ucs2_t *res; - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - res = unmangle(s); - if (res) ret = NT_STATUS_OK; - SAFE_FREE(res); - return ret; -} - -NTSTATUS path_has_mangled(const smb_ucs2_t *s) +static NTSTATUS is_8_3_w(const smb_ucs2_t *fname) { - smb_ucs2_t *p, *f, *b; + smb_ucs2_t *pref = 0, *ext = 0; + size_t plen; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; - - p = strdup_w(s); - if (!p) return NT_STATUS_NO_MEMORY; - trim_string_wa(p, "/", "/"); - f = b = p; - while (b) { - b = strchr_w(f, UCS2_CHAR('/')); - if (b) *b = 0; - if (NT_STATUS_IS_OK(is_mangled_w(f))) { - ret = NT_STATUS_OK; - goto done; - } - f = b + 1; - } -done: - SAFE_FREE(p); - return ret; -} + if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; -/* backward compatibility functions */ + DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */ -void reset_mangled_cache(void) -{ - DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n")); -} + if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL; + + if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) + return NT_STATUS_OK; -BOOL check_mangled_cache(char *s) -{ - smb_ucs2_t *u2, *res; - BOOL ret = False; + if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done; - DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n")); - DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s)); + if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done; + plen = strlen_w(pref); - if (!s || !*s) return False; + if (strchr_wa(pref, '.')) goto done; + if (plen < 1 || plen > 8) goto done; + if (ext) if (strlen_w(ext) > 3) goto done; - u2 = acnv_dosu2(s); - if (!u2) - { - DEBUG(0,("check_mangled_cache: out of memory!\n")); - return ret; - } + ret = NT_STATUS_OK; - res = unmangle(u2); - if (res) - { - - ucs2_to_dos (s, res, PSTRING_LEN); - /* We MUST change this brainded interface, - we do not know how many chars will be used - in dos so i guess they will be no more than - double the size of the unicode string - ---simo */ - DEBUG(10,("check_mangled_cache: returning -> [%s]\n", s)); - ret = True; - } - SAFE_FREE(res); - SAFE_FREE(u2); - DEBUG(10,("check_mangled_cache: returning -> %s\n", ret?"True":"False")); +done: + SAFE_FREE(pref); + SAFE_FREE(ext); return ret; } -void mangle_name_83(char *s) +BOOL is_8_3(const char *fname, BOOL check_case) { - smb_ucs2_t *u2, *res; + const char *f; + smb_ucs2_t *ucs2name; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n")); - DEBUG(10,("mangle_name_83: testing -> [%s]\n", s)); + if (!fname || !*fname) return False; + if ((f = strrchr(fname, '/')) == NULL) f = fname; + else f++; - if (!s || !*s) return; + DEBUG(10,("is_8_3: testing [%s]\n", f)); + + if (strlen(f) > 12) return False; - u2 = acnv_dosu2(s); - if (!u2) + ucs2name = acnv_uxu2(f); + if (!ucs2name) { - DEBUG(0,("mangle_name_83: internal error acnv_dosu2() failed!\n")); - return; + DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); + goto done; } - res = mangle(u2); - if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */ - DEBUG(10,("mangle_name_83: returning -> [%s]\n", s)); - SAFE_FREE(res); - SAFE_FREE(u2); -} + ret = is_8_3_w(ucs2name); -BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) -{ - DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n")); +done: + SAFE_FREE(ucs2name); - if (!need83) return True; - /* if (is_8_3(OutName, True)) return True; */ - /* Warning: we should check for invalid chars in file name and mangle - if invalid chars found --simo*/ + DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False")); - mangle_name_83(OutName); + if (!NT_STATUS_IS_OK(ret)) { + return False; + } + return True; } -#if 0 /* TEST_MANGLE_CODE */ +/* -------------------------------------------------------------------------- ** + * Functions... + */ -#define LONG "this_is_a_long_file_name" -#define LONGM "this_~01" -#define SHORT "short" -#define SHORTM "short~01" -#define EXT1 "ex1" -#define EXT2 "e2" -#define EXT3 "3" -#define EXTFAIL "longext" -#define EXTNULL "" +/* ************************************************************************** ** + * Initialize the static character test array. + * + * Input: none + * + * Output: none + * + * Notes: This function changes (loads) the contents of the + * array. The scope of is this file. + * + * ************************************************************************** ** + */ +static void init_chartest( void ) + { + char *illegalchars = "*\\/?<>|\":"; + unsigned char *s; + + memset( (char *)chartest, '\0', 256 ); + + for( s = (unsigned char *)illegalchars; *s; s++ ) + chartest[*s] = ILLEGAL_MASK; + + for( s = (unsigned char *)basechars; *s; s++ ) + chartest[*s] |= BASECHAR_MASK; + + ct_initialized = True; + } /* init_chartest */ + + +/* ************************************************************************** ** + * Return True if the name *could be* a mangled name. + * + * Input: s - A path name - in UNIX pathname format. + * + * Output: True if the name matches the pattern described below in the + * notes, else False. + * + * Notes: The input name is *not* tested for 8.3 compliance. This must be + * done separately. This function returns true if the name contains + * a magic character followed by excactly two characters from the + * basechars list (above), which in turn are followed either by the + * nul (end of string) byte or a dot (extension) or by a '/' (end of + * a directory name). + * + * ************************************************************************** ** + */ +BOOL is_mangled( char *s ) + { + char *magic; + + if( !ct_initialized ) + init_chartest(); + + magic = strchr_m( s, magic_char ); + while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ + { + if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ + && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ + && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ + return( True ); /* If all above, then true, */ + magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ + } + return( False ); + } /* is_mangled */ + + +/* ************************************************************************** ** + * Compare two cache keys and return a value indicating their ordinal + * relationship. + * + * Input: ItemPtr - Pointer to a comparison key. In this case, this will + * be a mangled name string. + * NodePtr - Pointer to a node in the cache. The node structure + * will be followed in memory by a mangled name string. + * + * Output: A signed integer, as follows: + * (x < 0) <==> Key1 less than Key2 + * (x == 0) <==> Key1 equals Key2 + * (x > 0) <==> Key1 greater than Key2 + * + * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for + * more info. + * + * ************************************************************************** ** + */ +static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) + { + char *Key1 = (char *)ItemPtr; + char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); + + return( StrCaseCmp( Key1, Key2 ) ); + } /* cache_compare */ + +/* ************************************************************************** ** + * Free a cache entry. + * + * Input: WarrenZevon - Pointer to the entry that is to be returned to + * Nirvana. + * Output: none. + * + * Notes: This function gets around the possibility that the standard + * free() function may be implemented as a macro, or other evil + * subversions (oh, so much fun). + * + * ************************************************************************** ** + */ +static void cache_free_entry( ubi_trNodePtr WarrenZevon ) + { + ZERO_STRUCTP(WarrenZevon); + SAFE_FREE( WarrenZevon ); + } /* cache_free_entry */ + +/* ************************************************************************** ** + * Initializes or clears the mangled cache. + * + * Input: none. + * Output: none. + * + * Notes: There is a section below that is commented out. It shows how + * one might use lp_ calls to set the maximum memory and entry size + * of the cache. You might also want to remove the constants used + * in ubi_cacheInit() and replace them with lp_ calls. If so, then + * the calls to ubi_cacheSetMax*() would be moved into the else + * clause. Another option would be to pass in the max_entries and + * max_memory values as parameters. crh 09-Apr-1998. + * + * ************************************************************************** ** + */ +void reset_mangled_cache( void ) + { + if( !mc_initialized ) + { + (void)ubi_cacheInit( mangled_cache, + cache_compare, + cache_free_entry, + MANGLED_CACHE_MAX_ENTRIES, + MANGLED_CACHE_MAX_MEMORY ); + mc_initialized = True; + } + else + { + (void)ubi_cacheClear( mangled_cache ); + } + + /* + (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); + (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); + */ + } /* reset_mangled_cache */ + + +/* ************************************************************************** ** + * Add a mangled name into the cache. + * + * Notes: If the mangled cache has not been initialized, then the + * function will simply fail. It could initialize the cache, + * but that's not the way it was done before I changed the + * cache mechanism, so I'm sticking with the old method. + * + * If the extension of the raw name maps directly to the + * extension of the mangled name, then we'll store both names + * *without* extensions. That way, we can provide consistent + * reverse mangling for all names that match. The test here is + * a bit more careful than the one done in earlier versions of + * mangle.c: + * + * - the extension must exist on the raw name, + * - it must be all lower case + * - it must match the mangled extension (to prove that no + * mangling occurred). + * + * crh 07-Apr-1998 + * + * ************************************************************************** ** + */ +static void cache_mangled_name( char *mangled_name, char *raw_name ) + { + ubi_cacheEntryPtr new_entry; + char *s1; + char *s2; + size_t mangled_len; + size_t raw_len; + size_t i; + + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) + return; + + /* Init the string lengths. */ + mangled_len = strlen( mangled_name ); + raw_len = strlen( raw_name ); + + /* See if the extensions are unmangled. If so, store the entry + * without the extension, thus creating a "group" reverse map. + */ + s1 = strrchr( mangled_name, '.' ); + if( s1 && (s2 = strrchr( raw_name, '.' )) ) + { + i = 1; + while( s1[i] && (tolower( s1[1] ) == s2[i]) ) + i++; + if( !s1[i] && !s2[i] ) + { + mangled_len -= i; + raw_len -= i; + } + } + + /* Allocate a new cache entry. If the allocation fails, just return. */ + i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; + new_entry = malloc( i ); + if( !new_entry ) + return; + + /* Fill the new cache entry, and add it to the cache. */ + s1 = (char *)(new_entry + 1); + s2 = (char *)&(s1[mangled_len + 1]); + (void)StrnCpy( s1, mangled_name, mangled_len ); + (void)StrnCpy( s2, raw_name, raw_len ); + ubi_cachePut( mangled_cache, i, new_entry, s1 ); + } /* cache_mangled_name */ + +/* ************************************************************************** ** + * Check for a name on the mangled name stack + * + * Input: s - Input *and* output string buffer. + * + * Output: True if the name was found in the cache, else False. + * + * Notes: If a reverse map is found, the function will overwrite the string + * space indicated by the input pointer . This is frightening. + * It should be rewritten to return NULL if the long name was not + * found, and a pointer to the long name if it was found. + * + * ************************************************************************** ** + */ -static void unmangle_test (char *name, char *ext) +BOOL check_mangled_cache( char *s ) { - smb_ucs2_t ucs2_name[2048]; - smb_ucs2_t *retstr; - pstring unix_name; + ubi_cacheEntryPtr FoundPtr; + char *ext_start = NULL; + char *found_name; + char *saved_ext = NULL; + + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) + return( False ); + + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + + /* If we didn't find the name *with* the extension, try without. */ + if( !FoundPtr ) + { + ext_start = strrchr( s, '.' ); + if( ext_start ) + { + if((saved_ext = strdup(ext_start)) == NULL) + return False; + + *ext_start = '\0'; + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + /* + * At this point s is the name without the + * extension. We re-add the extension if saved_ext + * is not null, before freeing saved_ext. + */ + } + } + + /* Okay, if we haven't found it we're done. */ + if( !FoundPtr ) + { + if(saved_ext) + { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + SAFE_FREE(saved_ext); + } + return( False ); + } + + /* If we *did* find it, we need to copy it into the string buffer. */ + found_name = (char *)(FoundPtr + 1); + found_name += (strlen( found_name ) + 1); + + DEBUG( 3, ("Found %s on mangled stack ", s) ); + + (void)pstrcpy( s, found_name ); + if( saved_ext ) + { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + SAFE_FREE(saved_ext); + } + + DEBUG( 3, ("as %s\n", s) ); + + return( True ); +} /* check_mangled_cache */ + + +/* ************************************************************************** ** + * Used only in do_fwd_mangled_map(), below. + * ************************************************************************** ** + */ +static char *map_filename( char *s, /* This is null terminated */ + char *pattern, /* This isn't. */ + int len ) /* This is the length of pattern. */ + { + static pstring matching_bit; /* The bit of the string which matches */ + /* a * in pattern if indeed there is a * */ + char *sp; /* Pointer into s. */ + char *pp; /* Pointer into p. */ + char *match_start; /* Where the matching bit starts. */ + pstring pat; + + StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */ + pstrcpy( matching_bit, "" ); /* Match but no star gets this. */ + pp = pat; /* Initialize the pointers. */ + sp = s; + + if( strequal(s, ".") || strequal(s, "..")) + { + return NULL; /* Do not map '.' and '..' */ + } + + if( (len == 1) && (*pattern == '*') ) + { + return NULL; /* Impossible, too ambiguous for */ + } /* words! */ + + while( (*sp) /* Not the end of the string. */ + && (*pp) /* Not the end of the pattern. */ + && (*sp == *pp) /* The two match. */ + && (*pp != '*') ) /* No wildcard. */ + { + sp++; /* Keep looking. */ + pp++; + } + + if( !*sp && !*pp ) /* End of pattern. */ + return( matching_bit ); /* Simple match. Return empty string. */ + + if( *pp == '*' ) + { + pp++; /* Always interrested in the chacter */ + /* after the '*' */ + if( !*pp ) /* It is at the end of the pattern. */ + { + StrnCpy( matching_bit, s, sp-s ); + return( matching_bit ); + } + else + { + /* The next character in pattern must match a character further */ + /* along s than sp so look for that character. */ + match_start = sp; + while( (*sp) /* Not the end of s. */ + && (*sp != *pp) ) /* Not the same */ + sp++; /* Keep looking. */ + if( !*sp ) /* Got to the end without a match. */ + { + return( NULL ); + } /* Still hope for a match. */ + else + { + /* Now sp should point to a matching character. */ + StrnCpy(matching_bit, match_start, sp-match_start); + /* Back to needing a stright match again. */ + while( (*sp) /* Not the end of the string. */ + && (*pp) /* Not the end of the pattern. */ + && (*sp == *pp) ) /* The two match. */ + { + sp++; /* Keep looking. */ + pp++; + } + if( !*sp && !*pp ) /* Both at end so it matched */ + return( matching_bit ); + else + return( NULL ); + } + } + } + return( NULL ); /* No match. */ + } /* map_filename */ + + +/* ************************************************************************** ** + * MangledMap is a series of name pairs in () separated by spaces. + * If s matches the first of the pair then the name given is the + * second of the pair. A * means any number of any character and if + * present in the second of the pair as well as the first the + * matching part of the first string takes the place of the * in the + * second. + * + * I wanted this so that we could have RCS files which can be used + * by UNIX and DOS programs. My mapping string is (RCS rcs) which + * converts the UNIX RCS file subdirectory to lowercase thus + * preventing mangling. + * + * (I think Andrew wrote the above, but I'm not sure. -- CRH) + * + * See 'mangled map' in smb.conf(5). + * + * ************************************************************************** ** + */ +static void do_fwd_mangled_map(char *s, char *MangledMap) + { + char *start=MangledMap; /* Use this to search for mappings. */ + char *end; /* Used to find the end of strings. */ + char *match_string; + pstring new_string; /* Make up the result here. */ + char *np; /* Points into new_string. */ + + DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) ); + while( *start ) + { + while( (*start) && (*start != '(') ) + start++; + if( !*start ) + continue; /* Always check for the end. */ + start++; /* Skip the ( */ + end = start; /* Search for the ' ' or a ')' */ + DEBUG( 5, ("Start of first in pair '%s'\n", start) ); + while( (*end) && !((*end == ' ') || (*end == ')')) ) + end++; + if( !*end ) + { + start = end; + continue; /* Always check for the end. */ + } + DEBUG( 5, ("End of first in pair '%s'\n", end) ); + if( (match_string = map_filename( s, start, end-start )) ) + { + DEBUG( 5, ("Found a match\n") ); + /* Found a match. */ + start = end + 1; /* Point to start of what it is to become. */ + DEBUG( 5, ("Start of second in pair '%s'\n", start) ); + end = start; + np = new_string; + while( (*end) /* Not the end of string. */ + && (*end != ')') /* Not the end of the pattern. */ + && (*end != '*') ) /* Not a wildcard. */ + *np++ = *end++; + if( !*end ) + { + start = end; + continue; /* Always check for the end. */ + } + if( *end == '*' ) + { + pstrcpy( np, match_string ); + np += strlen( match_string ); + end++; /* Skip the '*' */ + while( (*end) /* Not the end of string. */ + && (*end != ')') /* Not the end of the pattern. */ + && (*end != '*') ) /* Not a wildcard. */ + *np++ = *end++; + } + if( !*end ) + { + start = end; + continue; /* Always check for the end. */ + } + *np++ = '\0'; /* NULL terminate it. */ + DEBUG(5,("End of second in pair '%s'\n", end)); + pstrcpy( s, new_string ); /* Substitute with the new name. */ + DEBUG( 5, ("s is now '%s'\n", s) ); + } + start = end; /* Skip a bit which cannot be wanted anymore. */ + start++; + } + } /* do_fwd_mangled_map */ + +/***************************************************************************** + * do the actual mangling to 8.3 format + * the buffer must be able to hold 13 characters (including the null) + ***************************************************************************** + */ +void mangle_name_83( char *s) + { + int csum; + char *p; + char extension[4]; + char base[9]; + int baselen = 0; + int extlen = 0; + + extension[0] = 0; + base[0] = 0; + + p = strrchr(s,'.'); + if( p && (strlen(p+1) < (size_t)4) ) + { + BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ + + if( all_normal && p[1] != 0 ) + { + *p = 0; + csum = str_checksum( s ); + *p = '.'; + } + else + csum = str_checksum(s); + } + else + csum = str_checksum(s); + + strupper( s ); + + DEBUG( 5, ("Mangling name %s to ",s) ); + + if( p ) + { + if( p == s ) + safe_strcpy( extension, "___", 3 ); + else + { + *p++ = 0; + while( *p && extlen < 3 ) + { + if ( *p != '.') { + extension[extlen++] = p[0]; + } + p++; + } + extension[extlen] = 0; + } + } + + p = s; + + while( *p && baselen < 5 ) + { + if (*p != '.') { + base[baselen++] = p[0]; + } + p++; + } + base[baselen] = 0; + + csum = csum % (MANGLE_BASE*MANGLE_BASE); + + (void)slprintf(s, 12, "%s%c%c%c", + base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); + + if( *extension ) + { + (void)pstrcat( s, "." ); + (void)pstrcat( s, extension ); + } + + DEBUG( 5, ( "%s\n", s ) ); + + } /* mangle_name_83 */ + +/***************************************************************************** + * Convert a filename to DOS format. Return True if successful. + * + * Input: OutName - Source *and* destination buffer. + * + * NOTE that OutName must point to a memory space that + * is at least 13 bytes in size! + * + * need83 - If False, name mangling will be skipped unless the + * name contains illegal characters. Mapping will still + * be done, if appropriate. This is probably used to + * signal that a client does not require name mangling, + * thus skipping the name mangling even on shares which + * have name-mangling turned on. + * cache83 - If False, the mangled name cache will not be updated. + * This is usually used to prevent that we overwrite + * a conflicting cache entry prematurely, i.e. before + * we know whether the client is really interested in the + * current name. (See PR#13758). UKD. + * snum - Share number. This identifies the share in which the + * name exists. + * + * Output: Returns False only if the name wanted mangling but the share does + * not have name mangling turned on. + * + * **************************************************************************** + */ +BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) +{ + char *map; + smb_ucs2_t *OutName_ucs2; + DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s, %d )\n", OutName, + need83 ? "True" : "False", cache83 ? "True" : "False", snum)); + + if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) { + DEBUG(0, ("push_ucs2_allocate failed!\n")); + return False; + } - push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE); - if (ext) - { - strncat_wa(ucs2_name, ".", 1); - strncat_wa(ucs2_name, ext, strlen(ext) + 1); + /* apply any name mappings */ + map = lp_mangled_map(snum); + + if (map && *map) { + do_fwd_mangled_map( OutName, map ); } - retstr = unmangle(ucs2_name); - if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE); - else unix_name[0] = 0; - if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name); - else printf ("[%s] ---> [%s]\n", name, unix_name); - SAFE_FREE(retstr); -} -static void mangle_test (char *name, char *ext) -{ - smb_ucs2_t ucs2_name[2048]; - smb_ucs2_t *retstr; - pstring unix_name; + /* check if it's already in 8.3 format */ + if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) { + char *tmp = NULL; - push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE); - if (ext) - { - strncat_wa(ucs2_name, ".", 1); - strncat_wa(ucs2_name, ext, strlen(ext) + 1); + if (!lp_manglednames(snum)) { + return(False); + } + + /* mangle it into 8.3 */ + if (cache83) + tmp = strdup(OutName); + + mangle_name_83(OutName); + + if(tmp != NULL) { + cache_mangled_name(OutName, tmp); + SAFE_FREE(tmp); + } } - retstr = mangle(ucs2_name); - if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE); - else unix_name[0] = 0; - if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name); - else printf ("[%s] ---> [%s]\n", name, unix_name); - SAFE_FREE(retstr); -} -void mangle_test_code(void) -{ - init_mangle_tdb(); - - /* unmangle every */ - printf("Unmangle test 1:\n"); - - unmangle_test (LONG, NULL); - unmangle_test (LONG, EXT1); - unmangle_test (LONG, EXT2); - unmangle_test (LONG, EXT3); - unmangle_test (LONG, EXTFAIL); - unmangle_test (LONG, EXTNULL); - - unmangle_test (LONGM, NULL); - unmangle_test (LONGM, EXT1); - unmangle_test (LONGM, EXT2); - unmangle_test (LONGM, EXT3); - unmangle_test (LONGM, EXTFAIL); - unmangle_test (LONGM, EXTNULL); - - unmangle_test (SHORT, NULL); - unmangle_test (SHORT, EXT1); - unmangle_test (SHORT, EXT2); - unmangle_test (SHORT, EXT3); - unmangle_test (SHORT, EXTFAIL); - unmangle_test (SHORT, EXTNULL); - - unmangle_test (SHORTM, NULL); - unmangle_test (SHORTM, EXT1); - unmangle_test (SHORTM, EXT2); - unmangle_test (SHORTM, EXT3); - unmangle_test (SHORTM, EXTFAIL); - unmangle_test (SHORTM, EXTNULL); - - /* mangle every */ - printf("Mangle test\n"); - - mangle_test (LONG, NULL); - mangle_test (LONG, EXT1); - mangle_test (LONG, EXT2); - mangle_test (LONG, EXT3); - mangle_test (LONG, EXTFAIL); - mangle_test (LONG, EXTNULL); - - mangle_test (LONGM, NULL); - mangle_test (LONGM, EXT1); - mangle_test (LONGM, EXT2); - mangle_test (LONGM, EXT3); - mangle_test (LONGM, EXTFAIL); - mangle_test (LONGM, EXTNULL); - - mangle_test (SHORT, NULL); - mangle_test (SHORT, EXT1); - mangle_test (SHORT, EXT2); - mangle_test (SHORT, EXT3); - mangle_test (SHORT, EXTFAIL); - mangle_test (SHORT, EXTNULL); - - mangle_test (SHORTM, NULL); - mangle_test (SHORTM, EXT1); - mangle_test (SHORTM, EXT2); - mangle_test (SHORTM, EXT3); - mangle_test (SHORTM, EXTFAIL); - mangle_test (SHORTM, EXTNULL); - - /* unmangle again every */ - printf("Unmangle test 2:\n"); - - unmangle_test (LONG, NULL); - unmangle_test (LONG, EXT1); - unmangle_test (LONG, EXT2); - unmangle_test (LONG, EXT3); - unmangle_test (LONG, EXTFAIL); - unmangle_test (LONG, EXTNULL); - - unmangle_test (LONGM, NULL); - unmangle_test (LONGM, EXT1); - unmangle_test (LONGM, EXT2); - unmangle_test (LONGM, EXT3); - unmangle_test (LONGM, EXTFAIL); - unmangle_test (LONGM, EXTNULL); - - unmangle_test (SHORT, NULL); - unmangle_test (SHORT, EXT1); - unmangle_test (SHORT, EXT2); - unmangle_test (SHORT, EXT3); - unmangle_test (SHORT, EXTFAIL); - unmangle_test (SHORT, EXTNULL); - - unmangle_test (SHORTM, NULL); - unmangle_test (SHORTM, EXT1); - unmangle_test (SHORTM, EXT2); - unmangle_test (SHORTM, EXT3); - unmangle_test (SHORTM, EXTFAIL); - unmangle_test (SHORTM, EXTNULL); -} + DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName)); + SAFE_FREE(OutName_ucs2); + return(True); +} /* name_map_mangle */ -#endif /* TEST_MANGLE_CODE */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index af582f1a41..421f886283 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3021,10 +3021,10 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO * Tine Smukavec . */ -#if 0 +#if 1 if (!rc && is_mangled(mask)) check_mangled_cache( mask ); -#endif +#else if (!rc) { char *unmangled; @@ -3035,6 +3035,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO SAFE_FREE(unmangled); } +#endif has_wild = ms_has_wild(mask); @@ -3437,10 +3438,10 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec . */ -#if 0 +#if 1 if (!rc && is_mangled(mask)) check_mangled_cache( mask ); -#endif +#else if (!rc) { char *unmangled; @@ -3451,7 +3452,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SAFE_FREE(unmangled); } - +#endif has_wild = ms_has_wild(mask); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a9f3989735..e3912ba939 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -888,10 +888,6 @@ static void usage(char *pname) if (!init_oplocks()) exit(1); - /* Setup mangle */ - if (!init_mangle_tdb()) - exit(1); - /* Setup change notify */ if (!init_change_notify()) exit(1); -- cgit From 9c1665b2995055379c0c40a9fda485a2f164796c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 8 Apr 2002 09:29:28 +0000 Subject: a fix yet committed to 2.2 sometimes ago and reintroduced here! (This used to be commit aff7073dabb6253fea4729f52240a25f90206699) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 9789f06e0c..e50537e4cb 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -533,7 +533,7 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) if( s1 && (s2 = strrchr( raw_name, '.' )) ) { i = 1; - while( s1[i] && (tolower( s1[1] ) == s2[i]) ) + while( s1[i] && (tolower( s1[i] ) == s2[i]) ) i++; if( !s1[i] && !s2[i] ) { -- cgit From c36b31783e172e683de5bfa1c7df8158acfb2ae5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Apr 2002 18:10:09 +0000 Subject: Shirish pointed out more areas we should be doing roundups for allocation size. Jeremy. (This used to be commit cda9fccd629d084039af642d9177865d88553be6) --- source3/smbd/nttrans.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2c0955c834..ed2979b3a4 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -842,7 +842,7 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, file_len); + SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); p += 8; SOFF_T(p,0,file_len); p += 12; @@ -1293,7 +1293,7 @@ static int call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p,0,file_len); + SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); p += 8; SOFF_T(p,0,file_len); @@ -1348,29 +1348,28 @@ static int call_nt_transact_notify_change(connection_struct *conn, char **ppsetup, char **ppparams, char **ppdata) { - char *setup = *ppsetup; - files_struct *fsp; - uint32 flags; + char *setup = *ppsetup; + files_struct *fsp; + uint32 flags; - fsp = file_fsp(setup,4); - flags = IVAL(setup, 0); + fsp = file_fsp(setup,4); + flags = IVAL(setup, 0); - DEBUG(3,("call_nt_transact_notify_change\n")); + DEBUG(3,("call_nt_transact_notify_change\n")); - if(!fsp) - return ERROR_DOS(ERRDOS,ERRbadfid); + if(!fsp) + return ERROR_DOS(ERRDOS,ERRbadfid); - if((!fsp->is_directory) || (conn != fsp->conn)) - return ERROR_DOS(ERRDOS,ERRbadfid); + if((!fsp->is_directory) || (conn != fsp->conn)) + return ERROR_DOS(ERRDOS,ERRbadfid); - if (!change_notify_set(inbuf, fsp, conn, flags)) { - return(UNIXERROR(ERRDOS,ERRbadfid)); - } + if (!change_notify_set(inbuf, fsp, conn, flags)) + return(UNIXERROR(ERRDOS,ERRbadfid)); - DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ + DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ name = %s\n", fsp->fsp_name )); - return -1; + return -1; } /**************************************************************************** -- cgit From 4ad0ff29bf44e2506311f672bf912e7a2d39048a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Apr 2002 01:04:13 +0000 Subject: Added Shirish's client side caching policy change. Jeremy. (This used to be commit 16015c07eab2e57fa3771051e3e08fde21757cfa) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 421f886283..f3b3ce4a8a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -285,7 +285,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* what does setting this bit do? It is set by NT4 and may affect the ability to autorun mounted cdroms */ - SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS); + SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS| + (lp_csc_policy(SNUM(conn)) << 2)); init_dfsroot(conn, inbuf, outbuf); } -- cgit From 9cd0306baa1b3a78b40ab97b5d199b90a4c34aa6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 02:20:56 +0000 Subject: This split the mangling code up to allow for the possibility of multiple mangling implementation, selectable using "mangling method = " in smb.conf It also tidies the interface a little, although it is still nasty. (This used to be commit be23d87a178e7d0691e7d942adf89bb3d2d533c2) --- source3/smbd/dir.c | 6 +- source3/smbd/filename.c | 46 +-- source3/smbd/mangle.c | 983 ++++----------------------------------------- source3/smbd/mangle_hash.c | 775 +++++++++++++++++++++++++++++++++++ source3/smbd/mangle_map.c | 203 ++++++++++ source3/smbd/oplock.c | 2 + source3/smbd/reply.c | 43 +- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 26 +- 9 files changed, 1090 insertions(+), 996 deletions(-) create mode 100644 source3/smbd/mangle_hash.c create mode 100644 source3/smbd/mangle_map.c (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 0bf234dd3e..f56e0e9ef0 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -603,14 +603,14 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, */ if ((strcmp(mask,"*.*") == 0) || mask_match(filename,mask,False) || - (name_map_mangle(filename,True,False,SNUM(conn)) && + (mangle_map(filename,True,False,SNUM(conn)) && mask_match(filename,mask,False))) { if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) continue; - if (!is_8_3(filename, False)) { - name_map_mangle(filename,True,False,SNUM(conn)); + if (!mangle_is_8_3(filename, False)) { + mangle_map(filename,True,False,SNUM(conn)); } pstrcpy(fname,filename); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8bd09691e4..cb6a6d31a4 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -73,32 +73,16 @@ static BOOL fname_equal(char *name1, char *name2) /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(char *name1, char *name2) +static BOOL mangled_equal(char *name1, char *name2, int snum) { -#if 1 pstring tmpname; - if (is_8_3(name2, True)) { + if (mangle_is_8_3(name2, True)) { return False; } pstrcpy(tmpname, name2); - mangle_name_83(tmpname); - - return strequal(name1, tmpname); -#else - char *tmpname; - BOOL ret = False; - - if (is_8_3(name2, True)) - { - tmpname = dos_mangle(name2); - if(tmpname) - ret = strequal(name1,tmpname); - SAFE_FREE(tmpname); - } - return ret; -#endif - + return mangle_map(tmpname, True, False, snum) && + strequal(name1, tmpname); } @@ -193,7 +177,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen } if (!case_sensitive && - (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) + (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) strnorm(name); /* @@ -220,7 +204,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * stat the name - if it exists then we are all done! */ - if (vfs_stat(conn,name,&st) == 0) { +/* ZZZ: stat1 */ if (vfs_stat(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; @@ -235,7 +219,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (case_sensitive && !is_mangled(name) && + if (case_sensitive && !mangle_is_mangled(name) && !lp_strip_dot() && !use_mangled_map) return(False); @@ -246,7 +230,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * just a component. JRA. */ - if(is_mangled(start)) + if (mangle_is_mangled(start)) component_was_mangled = True; /* @@ -346,8 +330,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * base of the filename. */ - if (is_mangled(start)) { - check_mangled_cache( start ); + if (mangle_is_mangled(start)) { + mangle_check_cache( start ); } DEBUG(5,("New file %s\n",start)); @@ -468,7 +452,7 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d BOOL mangled; pstring name2; - mangled = is_mangled(name); + mangled = mangle_is_mangled(name); /* handle null paths */ if (*path == 0) @@ -482,12 +466,12 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) - * read from the directory and then mangled by the name_map_mangle() + * read from the directory and then mangled by the mangle_map() * call. We need to mangle both names or neither. * (JRA). */ if (mangled) - mangled = !check_mangled_cache( name ); + mangled = !mangle_check_cache( name ); /* open the directory */ if (!(cur_dir = OpenDir(conn, path, True))) { @@ -501,10 +485,10 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d continue; pstrcpy(name2,dname); - if (!name_map_mangle(name2,False,True,SNUM(conn))) + if (!mangle_map(name2,False,True,SNUM(conn))) continue; - if ((mangled && mangled_equal(name,name2)) || fname_equal(name, dname)) { + if ((mangled && mangled_equal(name,name2,SNUM(conn))) || fname_equal(name, dname)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index e50537e4cb..9d0641d5c8 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1,9 +1,7 @@ /* Unix SMB/CIFS implementation. - Name mangling - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Simo Sorce 2001 - Copyright (C) Andrew Bartlett 2002 + Name mangling interface + Copyright (C) Andrew Tridgell 2002 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 @@ -20,944 +18,99 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* -------------------------------------------------------------------------- ** - * Notable problems... - * - * March/April 1998 CRH - * - Many of the functions in this module overwrite string buffers passed to - * them. This causes a variety of problems and is, generally speaking, - * dangerous and scarry. See the kludge notes in name_map_mangle() - * below. - * - It seems that something is calling name_map_mangle() twice. The - * first call is probably some sort of test. Names which contain - * illegal characters are being doubly mangled. I'm not sure, but - * I'm guessing the problem is in server.c. - * - * -------------------------------------------------------------------------- ** - */ - -/* -------------------------------------------------------------------------- ** - * History... - * - * March/April 1998 CRH - * Updated a bit. Rewrote is_mangled() to be a bit more selective. - * Rewrote the mangled name cache. Added comments here and there. - * &c. - * -------------------------------------------------------------------------- ** - */ - #include "includes.h" +static struct mangle_fns *mangle_fns; -/* -------------------------------------------------------------------------- ** - * External Variables... - */ - -extern int case_default; /* Are conforming 8.3 names all upper or lower? */ -extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ - -/* -------------------------------------------------------------------------- ** - * Other stuff... - * - * magic_char - This is the magic char used for mangling. It's - * global. There is a call to lp_magicchar() in server.c - * that is used to override the initial value. - * - * MANGLE_BASE - This is the number of characters we use for name mangling. - * - * basechars - The set characters used for name mangling. This - * is static (scope is this file only). - * - * mangle() - Macro used to select a character from basechars (i.e., - * mangle(n) will return the nth digit, modulo MANGLE_BASE). - * - * chartest - array 0..255. The index range is the set of all possible - * values of a byte. For each byte value, the content is a - * two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK, - * below. - * - * ct_initialized - False until the chartest array has been initialized via - * a call to init_chartest(). - * - * BASECHAR_MASK - Masks the upper nibble of a one-byte value. - * - * ILLEGAL_MASK - Masks the lower nibble of a one-byte value. - * - * isbasecahr() - Given a character, check the chartest array to see - * if that character is in the basechars set. This is - * faster than using strchr_m(). - * - * isillegal() - Given a character, check the chartest array to see - * if that character is in the illegal characters set. - * This is faster than using strchr_m(). - * - * mangled_cache - Cache header used for storing mangled -> original - * reverse maps. - * - * mc_initialized - False until the mangled_cache structure has been - * initialized via a call to reset_mangled_cache(). - * - * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the - * cache. A value of 0 indicates "infinite". - * - * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the - * cache. When the cache was kept as an array of 256 - * byte strings, the default cache size was 50 entries. - * This required a fixed 12.5Kbytes of memory. The - * mangled stack parameter is no longer used (though - * this might change). We're now using a fixed 16Kbyte - * maximum cache size. This will probably be much more - * than 50 entries. - */ - -char magic_char = '~'; - -static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; -#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) - -static unsigned char chartest[256] = { 0 }; -static BOOL ct_initialized = False; - -#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) -#define BASECHAR_MASK 0xf0 -#define ILLEGAL_MASK 0x0f -#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) -#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) - -static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } }; -static BOOL mc_initialized = False; -#define MANGLED_CACHE_MAX_ENTRIES 0 -#define MANGLED_CACHE_MAX_MEMORY 16384 - - -/* -------------------------------------------------------------------------- ** - * External Variables... - */ - -extern int case_default; /* Are conforming 8.3 names all upper or lower? */ -extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ - -/* -------------------------------------------------------------------- */ +/* this allows us to add more mangling backends */ +static struct { + char *name; + struct mangle_fns *(*init_fn)(void); +} mangle_backends[] = { + { "hash", mangle_hash_init }, + { NULL, NULL } +}; -NTSTATUS has_valid_chars(const smb_ucs2_t *s) +/* + initialise the mangling subsystem +*/ +static void mangle_init(void) { - if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; + int i; + char *method; - DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */ - - /* CHECK: this should not be necessary if the ms wild chars - are not valid in valid.dat --- simo */ - if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL; + if (mangle_fns) return; - while (*s) { - if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL; - s++; - } - - return NT_STATUS_OK; -} + method = lp_mangling_method(); -/* return False if something fail and - * return 2 alloced unicode strings that contain prefix and extension - */ -static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension) -{ - size_t ext_len; - smb_ucs2_t *p; - - *extension = 0; - *prefix = strdup_w(ucs2_string); - if (!*prefix) - { - DEBUG(0,("mangle_get_prefix: out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) - { - ext_len = strlen_w(p+1); - if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) && - (NT_STATUS_IS_OK(has_valid_chars(p+1)))) /* check extension */ - { - *p = 0; - *extension = strdup_w(p+1); - if (!*extension) - { - DEBUG(0,("mangle_get_prefix: out of memory!\n")); - SAFE_FREE(*prefix); - return NT_STATUS_NO_MEMORY; - } + /* find the first mangling method that manages to initialise and + matches the "mangling method" parameter */ + for (i=0; mangle_backends[i].name && !mangle_fns; i++) { + if (!method || !*method || strcmp(method, mangle_backends[i].name) == 0) { + mangle_fns = mangle_backends[i].init_fn(); } } - return NT_STATUS_OK; -} - -/* ************************************************************************** ** - * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name. - * - * Input: fname - String containing the name to be tested. - * - * Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names. - * - * Notes: This is a static function called by is_8_3(), below. - * - * ************************************************************************** ** - */ -static NTSTATUS is_valid_name(const smb_ucs2_t *fname) -{ - smb_ucs2_t *str, *p; - NTSTATUS ret = NT_STATUS_OK; - - if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; - - DEBUG(10,("is_valid_name: testing\n")); /* [%s]\n", s)); */ - - if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL; - - ret = has_valid_chars(fname); - if (NT_STATUS_IS_ERR(ret)) return ret; - - str = strdup_w(fname); - p = strchr_w(str, UCS2_CHAR('.')); - if (p) *p = 0; - strupper_w(str); - p = &(str[1]); - switch(str[0]) - { - case UCS2_CHAR('A'): - if(strcmp_wa(p, "UX") == 0) - ret = NT_STATUS_UNSUCCESSFUL; - break; - case UCS2_CHAR('C'): - if((strcmp_wa(p, "LOCK$") == 0) - || (strcmp_wa(p, "ON") == 0) - || (strcmp_wa(p, "OM1") == 0) - || (strcmp_wa(p, "OM2") == 0) - || (strcmp_wa(p, "OM3") == 0) - || (strcmp_wa(p, "OM4") == 0) - ) - ret = NT_STATUS_UNSUCCESSFUL; - break; - case UCS2_CHAR('L'): - if((strcmp_wa(p, "PT1") == 0) - || (strcmp_wa(p, "PT2") == 0) - || (strcmp_wa(p, "PT3") == 0) - ) - ret = NT_STATUS_UNSUCCESSFUL; - break; - case UCS2_CHAR('N'): - if(strcmp_wa(p, "UL") == 0) - ret = NT_STATUS_UNSUCCESSFUL; - break; - case UCS2_CHAR('P'): - if(strcmp_wa(p, "RN") == 0) - ret = NT_STATUS_UNSUCCESSFUL; - break; - default: - break; + if (!mangle_fns) { + DEBUG(0,("Failed to initialise mangling system '%s'\n", method)); + exit_server("mangling init failed"); } - - SAFE_FREE(str); - return ret; } -static NTSTATUS is_8_3_w(const smb_ucs2_t *fname) -{ - smb_ucs2_t *pref = 0, *ext = 0; - size_t plen; - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; - - DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */ - - if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL; - - if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) - return NT_STATUS_OK; - if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done; - - if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done; - plen = strlen_w(pref); - - if (strchr_wa(pref, '.')) goto done; - if (plen < 1 || plen > 8) goto done; - if (ext) if (strlen_w(ext) > 3) goto done; - - ret = NT_STATUS_OK; +/* + reset the cache. This is called when smb.conf has been reloaded +*/ +void mangle_reset_cache(void) +{ + mangle_init(); -done: - SAFE_FREE(pref); - SAFE_FREE(ext); - return ret; + return mangle_fns->reset(); } -BOOL is_8_3(const char *fname, BOOL check_case) +/* + see if a filename has come out of our mangling code +*/ +BOOL mangle_is_mangled(const char *s) { - const char *f; - smb_ucs2_t *ucs2name; - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - if (!fname || !*fname) return False; - if ((f = strrchr(fname, '/')) == NULL) f = fname; - else f++; - - DEBUG(10,("is_8_3: testing [%s]\n", f)); - - if (strlen(f) > 12) return False; - - ucs2name = acnv_uxu2(f); - if (!ucs2name) - { - DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); - goto done; - } - - ret = is_8_3_w(ucs2name); - -done: - SAFE_FREE(ucs2name); - - DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False")); - - if (!NT_STATUS_IS_OK(ret)) { - return False; - } - - return True; + return mangle_fns->is_mangled(s); } - - -/* -------------------------------------------------------------------------- ** - * Functions... - */ - -/* ************************************************************************** ** - * Initialize the static character test array. - * - * Input: none - * - * Output: none - * - * Notes: This function changes (loads) the contents of the - * array. The scope of is this file. - * - * ************************************************************************** ** - */ -static void init_chartest( void ) - { - char *illegalchars = "*\\/?<>|\":"; - unsigned char *s; - - memset( (char *)chartest, '\0', 256 ); - - for( s = (unsigned char *)illegalchars; *s; s++ ) - chartest[*s] = ILLEGAL_MASK; - - for( s = (unsigned char *)basechars; *s; s++ ) - chartest[*s] |= BASECHAR_MASK; - - ct_initialized = True; - } /* init_chartest */ - - -/* ************************************************************************** ** - * Return True if the name *could be* a mangled name. - * - * Input: s - A path name - in UNIX pathname format. - * - * Output: True if the name matches the pattern described below in the - * notes, else False. - * - * Notes: The input name is *not* tested for 8.3 compliance. This must be - * done separately. This function returns true if the name contains - * a magic character followed by excactly two characters from the - * basechars list (above), which in turn are followed either by the - * nul (end of string) byte or a dot (extension) or by a '/' (end of - * a directory name). - * - * ************************************************************************** ** - */ -BOOL is_mangled( char *s ) - { - char *magic; - - if( !ct_initialized ) - init_chartest(); - - magic = strchr_m( s, magic_char ); - while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ - { - if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ - && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ - && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ - return( True ); /* If all above, then true, */ - magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ - } - return( False ); - } /* is_mangled */ - - -/* ************************************************************************** ** - * Compare two cache keys and return a value indicating their ordinal - * relationship. - * - * Input: ItemPtr - Pointer to a comparison key. In this case, this will - * be a mangled name string. - * NodePtr - Pointer to a node in the cache. The node structure - * will be followed in memory by a mangled name string. - * - * Output: A signed integer, as follows: - * (x < 0) <==> Key1 less than Key2 - * (x == 0) <==> Key1 equals Key2 - * (x > 0) <==> Key1 greater than Key2 - * - * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for - * more info. - * - * ************************************************************************** ** - */ -static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) - { - char *Key1 = (char *)ItemPtr; - char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); - - return( StrCaseCmp( Key1, Key2 ) ); - } /* cache_compare */ - -/* ************************************************************************** ** - * Free a cache entry. - * - * Input: WarrenZevon - Pointer to the entry that is to be returned to - * Nirvana. - * Output: none. - * - * Notes: This function gets around the possibility that the standard - * free() function may be implemented as a macro, or other evil - * subversions (oh, so much fun). - * - * ************************************************************************** ** - */ -static void cache_free_entry( ubi_trNodePtr WarrenZevon ) - { - ZERO_STRUCTP(WarrenZevon); - SAFE_FREE( WarrenZevon ); - } /* cache_free_entry */ - -/* ************************************************************************** ** - * Initializes or clears the mangled cache. - * - * Input: none. - * Output: none. - * - * Notes: There is a section below that is commented out. It shows how - * one might use lp_ calls to set the maximum memory and entry size - * of the cache. You might also want to remove the constants used - * in ubi_cacheInit() and replace them with lp_ calls. If so, then - * the calls to ubi_cacheSetMax*() would be moved into the else - * clause. Another option would be to pass in the max_entries and - * max_memory values as parameters. crh 09-Apr-1998. - * - * ************************************************************************** ** - */ -void reset_mangled_cache( void ) - { - if( !mc_initialized ) - { - (void)ubi_cacheInit( mangled_cache, - cache_compare, - cache_free_entry, - MANGLED_CACHE_MAX_ENTRIES, - MANGLED_CACHE_MAX_MEMORY ); - mc_initialized = True; - } - else - { - (void)ubi_cacheClear( mangled_cache ); - } - - /* - (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); - (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); - */ - } /* reset_mangled_cache */ - - -/* ************************************************************************** ** - * Add a mangled name into the cache. - * - * Notes: If the mangled cache has not been initialized, then the - * function will simply fail. It could initialize the cache, - * but that's not the way it was done before I changed the - * cache mechanism, so I'm sticking with the old method. - * - * If the extension of the raw name maps directly to the - * extension of the mangled name, then we'll store both names - * *without* extensions. That way, we can provide consistent - * reverse mangling for all names that match. The test here is - * a bit more careful than the one done in earlier versions of - * mangle.c: - * - * - the extension must exist on the raw name, - * - it must be all lower case - * - it must match the mangled extension (to prove that no - * mangling occurred). - * - * crh 07-Apr-1998 - * - * ************************************************************************** ** - */ -static void cache_mangled_name( char *mangled_name, char *raw_name ) - { - ubi_cacheEntryPtr new_entry; - char *s1; - char *s2; - size_t mangled_len; - size_t raw_len; - size_t i; - - /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) - return; - - /* Init the string lengths. */ - mangled_len = strlen( mangled_name ); - raw_len = strlen( raw_name ); - - /* See if the extensions are unmangled. If so, store the entry - * without the extension, thus creating a "group" reverse map. - */ - s1 = strrchr( mangled_name, '.' ); - if( s1 && (s2 = strrchr( raw_name, '.' )) ) - { - i = 1; - while( s1[i] && (tolower( s1[i] ) == s2[i]) ) - i++; - if( !s1[i] && !s2[i] ) - { - mangled_len -= i; - raw_len -= i; - } - } - - /* Allocate a new cache entry. If the allocation fails, just return. */ - i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; - new_entry = malloc( i ); - if( !new_entry ) - return; - - /* Fill the new cache entry, and add it to the cache. */ - s1 = (char *)(new_entry + 1); - s2 = (char *)&(s1[mangled_len + 1]); - (void)StrnCpy( s1, mangled_name, mangled_len ); - (void)StrnCpy( s2, raw_name, raw_len ); - ubi_cachePut( mangled_cache, i, new_entry, s1 ); - } /* cache_mangled_name */ - -/* ************************************************************************** ** - * Check for a name on the mangled name stack - * - * Input: s - Input *and* output string buffer. - * - * Output: True if the name was found in the cache, else False. - * - * Notes: If a reverse map is found, the function will overwrite the string - * space indicated by the input pointer . This is frightening. - * It should be rewritten to return NULL if the long name was not - * found, and a pointer to the long name if it was found. - * - * ************************************************************************** ** - */ - -BOOL check_mangled_cache( char *s ) +/* + see if a filename matches the rules of a 8.3 filename +*/ +BOOL mangle_is_8_3(const char *fname, BOOL check_case) { - ubi_cacheEntryPtr FoundPtr; - char *ext_start = NULL; - char *found_name; - char *saved_ext = NULL; - - /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) - return( False ); - - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - - /* If we didn't find the name *with* the extension, try without. */ - if( !FoundPtr ) - { - ext_start = strrchr( s, '.' ); - if( ext_start ) - { - if((saved_ext = strdup(ext_start)) == NULL) - return False; - - *ext_start = '\0'; - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - /* - * At this point s is the name without the - * extension. We re-add the extension if saved_ext - * is not null, before freeing saved_ext. - */ - } - } - - /* Okay, if we haven't found it we're done. */ - if( !FoundPtr ) - { - if(saved_ext) - { - /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); - SAFE_FREE(saved_ext); - } - return( False ); - } - - /* If we *did* find it, we need to copy it into the string buffer. */ - found_name = (char *)(FoundPtr + 1); - found_name += (strlen( found_name ) + 1); - - DEBUG( 3, ("Found %s on mangled stack ", s) ); - - (void)pstrcpy( s, found_name ); - if( saved_ext ) - { - /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); - SAFE_FREE(saved_ext); - } - - DEBUG( 3, ("as %s\n", s) ); - - return( True ); -} /* check_mangled_cache */ - - -/* ************************************************************************** ** - * Used only in do_fwd_mangled_map(), below. - * ************************************************************************** ** - */ -static char *map_filename( char *s, /* This is null terminated */ - char *pattern, /* This isn't. */ - int len ) /* This is the length of pattern. */ - { - static pstring matching_bit; /* The bit of the string which matches */ - /* a * in pattern if indeed there is a * */ - char *sp; /* Pointer into s. */ - char *pp; /* Pointer into p. */ - char *match_start; /* Where the matching bit starts. */ - pstring pat; - - StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */ - pstrcpy( matching_bit, "" ); /* Match but no star gets this. */ - pp = pat; /* Initialize the pointers. */ - sp = s; - - if( strequal(s, ".") || strequal(s, "..")) - { - return NULL; /* Do not map '.' and '..' */ - } - - if( (len == 1) && (*pattern == '*') ) - { - return NULL; /* Impossible, too ambiguous for */ - } /* words! */ - - while( (*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp) /* The two match. */ - && (*pp != '*') ) /* No wildcard. */ - { - sp++; /* Keep looking. */ - pp++; - } - - if( !*sp && !*pp ) /* End of pattern. */ - return( matching_bit ); /* Simple match. Return empty string. */ - - if( *pp == '*' ) - { - pp++; /* Always interrested in the chacter */ - /* after the '*' */ - if( !*pp ) /* It is at the end of the pattern. */ - { - StrnCpy( matching_bit, s, sp-s ); - return( matching_bit ); - } - else - { - /* The next character in pattern must match a character further */ - /* along s than sp so look for that character. */ - match_start = sp; - while( (*sp) /* Not the end of s. */ - && (*sp != *pp) ) /* Not the same */ - sp++; /* Keep looking. */ - if( !*sp ) /* Got to the end without a match. */ - { - return( NULL ); - } /* Still hope for a match. */ - else - { - /* Now sp should point to a matching character. */ - StrnCpy(matching_bit, match_start, sp-match_start); - /* Back to needing a stright match again. */ - while( (*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp) ) /* The two match. */ - { - sp++; /* Keep looking. */ - pp++; - } - if( !*sp && !*pp ) /* Both at end so it matched */ - return( matching_bit ); - else - return( NULL ); - } - } - } - return( NULL ); /* No match. */ - } /* map_filename */ - - -/* ************************************************************************** ** - * MangledMap is a series of name pairs in () separated by spaces. - * If s matches the first of the pair then the name given is the - * second of the pair. A * means any number of any character and if - * present in the second of the pair as well as the first the - * matching part of the first string takes the place of the * in the - * second. - * - * I wanted this so that we could have RCS files which can be used - * by UNIX and DOS programs. My mapping string is (RCS rcs) which - * converts the UNIX RCS file subdirectory to lowercase thus - * preventing mangling. - * - * (I think Andrew wrote the above, but I'm not sure. -- CRH) - * - * See 'mangled map' in smb.conf(5). - * - * ************************************************************************** ** - */ -static void do_fwd_mangled_map(char *s, char *MangledMap) - { - char *start=MangledMap; /* Use this to search for mappings. */ - char *end; /* Used to find the end of strings. */ - char *match_string; - pstring new_string; /* Make up the result here. */ - char *np; /* Points into new_string. */ - - DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) ); - while( *start ) - { - while( (*start) && (*start != '(') ) - start++; - if( !*start ) - continue; /* Always check for the end. */ - start++; /* Skip the ( */ - end = start; /* Search for the ' ' or a ')' */ - DEBUG( 5, ("Start of first in pair '%s'\n", start) ); - while( (*end) && !((*end == ' ') || (*end == ')')) ) - end++; - if( !*end ) - { - start = end; - continue; /* Always check for the end. */ - } - DEBUG( 5, ("End of first in pair '%s'\n", end) ); - if( (match_string = map_filename( s, start, end-start )) ) - { - DEBUG( 5, ("Found a match\n") ); - /* Found a match. */ - start = end + 1; /* Point to start of what it is to become. */ - DEBUG( 5, ("Start of second in pair '%s'\n", start) ); - end = start; - np = new_string; - while( (*end) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*') ) /* Not a wildcard. */ - *np++ = *end++; - if( !*end ) - { - start = end; - continue; /* Always check for the end. */ - } - if( *end == '*' ) - { - pstrcpy( np, match_string ); - np += strlen( match_string ); - end++; /* Skip the '*' */ - while( (*end) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*') ) /* Not a wildcard. */ - *np++ = *end++; - } - if( !*end ) - { - start = end; - continue; /* Always check for the end. */ - } - *np++ = '\0'; /* NULL terminate it. */ - DEBUG(5,("End of second in pair '%s'\n", end)); - pstrcpy( s, new_string ); /* Substitute with the new name. */ - DEBUG( 5, ("s is now '%s'\n", s) ); - } - start = end; /* Skip a bit which cannot be wanted anymore. */ - start++; - } - } /* do_fwd_mangled_map */ - -/***************************************************************************** - * do the actual mangling to 8.3 format - * the buffer must be able to hold 13 characters (including the null) - ***************************************************************************** - */ -void mangle_name_83( char *s) - { - int csum; - char *p; - char extension[4]; - char base[9]; - int baselen = 0; - int extlen = 0; - - extension[0] = 0; - base[0] = 0; - - p = strrchr(s,'.'); - if( p && (strlen(p+1) < (size_t)4) ) - { - BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ - - if( all_normal && p[1] != 0 ) - { - *p = 0; - csum = str_checksum( s ); - *p = '.'; - } - else - csum = str_checksum(s); - } - else - csum = str_checksum(s); - - strupper( s ); - - DEBUG( 5, ("Mangling name %s to ",s) ); - - if( p ) - { - if( p == s ) - safe_strcpy( extension, "___", 3 ); - else - { - *p++ = 0; - while( *p && extlen < 3 ) - { - if ( *p != '.') { - extension[extlen++] = p[0]; - } - p++; - } - extension[extlen] = 0; - } - } - - p = s; - - while( *p && baselen < 5 ) - { - if (*p != '.') { - base[baselen++] = p[0]; - } - p++; - } - base[baselen] = 0; - - csum = csum % (MANGLE_BASE*MANGLE_BASE); - - (void)slprintf(s, 12, "%s%c%c%c", - base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); - - if( *extension ) - { - (void)pstrcat( s, "." ); - (void)pstrcat( s, extension ); - } - - DEBUG( 5, ( "%s\n", s ) ); + return mangle_fns->is_8_3(fname, check_case); +} - } /* mangle_name_83 */ +/* + try to reverse map a 8.3 name to the original filename. This doesn't have to + always succeed, as the directory handling code in smbd will scan the directory + looking for a matching name if it doesn't. It should succeed most of the time + or there will be a huge performance penalty +*/ +BOOL mangle_check_cache(char *s) +{ + return mangle_fns->check_cache(s); +} -/***************************************************************************** - * Convert a filename to DOS format. Return True if successful. - * - * Input: OutName - Source *and* destination buffer. - * - * NOTE that OutName must point to a memory space that - * is at least 13 bytes in size! - * - * need83 - If False, name mangling will be skipped unless the - * name contains illegal characters. Mapping will still - * be done, if appropriate. This is probably used to - * signal that a client does not require name mangling, - * thus skipping the name mangling even on shares which - * have name-mangling turned on. - * cache83 - If False, the mangled name cache will not be updated. - * This is usually used to prevent that we overwrite - * a conflicting cache entry prematurely, i.e. before - * we know whether the client is really interested in the - * current name. (See PR#13758). UKD. - * snum - Share number. This identifies the share in which the - * name exists. - * - * Output: Returns False only if the name wanted mangling but the share does - * not have name mangling turned on. - * - * **************************************************************************** +/* + map a long filename to a 8.3 name. */ -BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum) +BOOL mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum) { - char *map; - smb_ucs2_t *OutName_ucs2; - DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s, %d )\n", OutName, - need83 ? "True" : "False", cache83 ? "True" : "False", snum)); - - if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) { - DEBUG(0, ("push_ucs2_allocate failed!\n")); - return False; - } - - /* apply any name mappings */ - map = lp_mangled_map(snum); - - if (map && *map) { - do_fwd_mangled_map( OutName, map ); - } - - /* check if it's already in 8.3 format */ - if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) { - char *tmp = NULL; - - if (!lp_manglednames(snum)) { - return(False); - } - - /* mangle it into 8.3 */ - if (cache83) - tmp = strdup(OutName); - - mangle_name_83(OutName); - - if(tmp != NULL) { - cache_mangled_name(OutName, tmp); - SAFE_FREE(tmp); + /* name mangling can be disabled for speed, in which case + we just truncate the string */ + if (!lp_manglednames(snum)) { + if (need83) { + string_truncate(OutName, 12); } + return True; } - DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName)); - SAFE_FREE(OutName_ucs2); - return(True); -} /* name_map_mangle */ + /* invoke the inane "mangled map" code */ + mangle_map_filename(OutName, snum); + return mangle_fns->name_map(OutName, need83, cache83); +} diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c new file mode 100644 index 0000000000..f38c2ae2c4 --- /dev/null +++ b/source3/smbd/mangle_hash.c @@ -0,0 +1,775 @@ +/* + Unix SMB/CIFS implementation. + Name mangling + Copyright (C) Andrew Tridgell 1992-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Andrew Bartlett 2002 + + 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. +*/ + + +/* -------------------------------------------------------------------------- ** + * Notable problems... + * + * March/April 1998 CRH + * - Many of the functions in this module overwrite string buffers passed to + * them. This causes a variety of problems and is, generally speaking, + * dangerous and scarry. See the kludge notes in name_map() + * below. + * - It seems that something is calling name_map() twice. The + * first call is probably some sort of test. Names which contain + * illegal characters are being doubly mangled. I'm not sure, but + * I'm guessing the problem is in server.c. + * + * -------------------------------------------------------------------------- ** + */ + +/* -------------------------------------------------------------------------- ** + * History... + * + * March/April 1998 CRH + * Updated a bit. Rewrote is_mangled() to be a bit more selective. + * Rewrote the mangled name cache. Added comments here and there. + * &c. + * -------------------------------------------------------------------------- ** + */ + +#include "includes.h" + + +/* -------------------------------------------------------------------------- ** + * External Variables... + */ + +extern int case_default; /* Are conforming 8.3 names all upper or lower? */ +extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ + +/* -------------------------------------------------------------------------- ** + * Other stuff... + * + * magic_char - This is the magic char used for mangling. It's + * global. There is a call to lp_magicchar() in server.c + * that is used to override the initial value. + * + * MANGLE_BASE - This is the number of characters we use for name mangling. + * + * basechars - The set characters used for name mangling. This + * is static (scope is this file only). + * + * mangle() - Macro used to select a character from basechars (i.e., + * mangle(n) will return the nth digit, modulo MANGLE_BASE). + * + * chartest - array 0..255. The index range is the set of all possible + * values of a byte. For each byte value, the content is a + * two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK, + * below. + * + * ct_initialized - False until the chartest array has been initialized via + * a call to init_chartest(). + * + * BASECHAR_MASK - Masks the upper nibble of a one-byte value. + * + * ILLEGAL_MASK - Masks the lower nibble of a one-byte value. + * + * isbasecahr() - Given a character, check the chartest array to see + * if that character is in the basechars set. This is + * faster than using strchr_m(). + * + * isillegal() - Given a character, check the chartest array to see + * if that character is in the illegal characters set. + * This is faster than using strchr_m(). + * + * mangled_cache - Cache header used for storing mangled -> original + * reverse maps. + * + * mc_initialized - False until the mangled_cache structure has been + * initialized via a call to reset_mangled_cache(). + * + * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the + * cache. A value of 0 indicates "infinite". + * + * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the + * cache. When the cache was kept as an array of 256 + * byte strings, the default cache size was 50 entries. + * This required a fixed 12.5Kbytes of memory. The + * mangled stack parameter is no longer used (though + * this might change). We're now using a fixed 16Kbyte + * maximum cache size. This will probably be much more + * than 50 entries. + */ + +char magic_char = '~'; + +static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; +#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) + +static unsigned char chartest[256] = { 0 }; +static BOOL ct_initialized = False; + +#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) +#define BASECHAR_MASK 0xf0 +#define ILLEGAL_MASK 0x0f +#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) +#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) + +static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } }; +static BOOL mc_initialized = False; +#define MANGLED_CACHE_MAX_ENTRIES 0 +#define MANGLED_CACHE_MAX_MEMORY 16384 + + +/* -------------------------------------------------------------------------- ** + * External Variables... + */ + +extern int case_default; /* Are conforming 8.3 names all upper or lower? */ +extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ + +/* -------------------------------------------------------------------- */ + +static NTSTATUS has_valid_chars(const smb_ucs2_t *s) +{ + if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; + + /* CHECK: this should not be necessary if the ms wild chars + are not valid in valid.dat --- simo */ + if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL; + + while (*s) { + if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL; + s++; + } + + return NT_STATUS_OK; +} + +/* return False if something fail and + * return 2 alloced unicode strings that contain prefix and extension + */ +static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension) +{ + size_t ext_len; + smb_ucs2_t *p; + + *extension = 0; + *prefix = strdup_w(ucs2_string); + if (!*prefix) { + return NT_STATUS_NO_MEMORY; + } + if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) + { + ext_len = strlen_w(p+1); + if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) && + (NT_STATUS_IS_OK(has_valid_chars(p+1)))) /* check extension */ + { + *p = 0; + *extension = strdup_w(p+1); + if (!*extension) { + SAFE_FREE(*prefix); + return NT_STATUS_NO_MEMORY; + } + } + } + return NT_STATUS_OK; +} + +/* ************************************************************************** ** + * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name. + * + * Input: fname - String containing the name to be tested. + * + * Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names. + * + * Notes: This is a static function called by is_8_3(), below. + * + * ************************************************************************** ** + */ +static NTSTATUS is_valid_name(const smb_ucs2_t *fname) +{ + smb_ucs2_t *str, *p; + NTSTATUS ret = NT_STATUS_OK; + + if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; + + if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL; + + ret = has_valid_chars(fname); + if (NT_STATUS_IS_ERR(ret)) return ret; + + str = strdup_w(fname); + p = strchr_w(str, UCS2_CHAR('.')); + if (p) *p = 0; + strupper_w(str); + p = &(str[1]); + + switch(str[0]) + { + case UCS2_CHAR('A'): + if(strcmp_wa(p, "UX") == 0) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('C'): + if((strcmp_wa(p, "LOCK$") == 0) + || (strcmp_wa(p, "ON") == 0) + || (strcmp_wa(p, "OM1") == 0) + || (strcmp_wa(p, "OM2") == 0) + || (strcmp_wa(p, "OM3") == 0) + || (strcmp_wa(p, "OM4") == 0) + ) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('L'): + if((strcmp_wa(p, "PT1") == 0) + || (strcmp_wa(p, "PT2") == 0) + || (strcmp_wa(p, "PT3") == 0) + ) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('N'): + if(strcmp_wa(p, "UL") == 0) + ret = NT_STATUS_UNSUCCESSFUL; + break; + case UCS2_CHAR('P'): + if(strcmp_wa(p, "RN") == 0) + ret = NT_STATUS_UNSUCCESSFUL; + break; + default: + break; + } + + SAFE_FREE(str); + return ret; +} + +static NTSTATUS is_8_3_w(const smb_ucs2_t *fname) +{ + smb_ucs2_t *pref = 0, *ext = 0; + size_t plen; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; + + if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL; + + if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) + return NT_STATUS_OK; + + if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done; + + if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done; + plen = strlen_w(pref); + + if (strchr_wa(pref, '.')) goto done; + if (plen < 1 || plen > 8) goto done; + if (ext) if (strlen_w(ext) > 3) goto done; + + ret = NT_STATUS_OK; + +done: + SAFE_FREE(pref); + SAFE_FREE(ext); + return ret; +} + +static BOOL is_8_3(const char *fname, BOOL check_case) +{ + const char *f; + smb_ucs2_t *ucs2name; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if (!fname || !*fname) return False; + if ((f = strrchr(fname, '/')) == NULL) f = fname; + else f++; + + if (strlen(f) > 12) return False; + + ucs2name = acnv_uxu2(f); + if (!ucs2name) + { + DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); + goto done; + } + + ret = is_8_3_w(ucs2name); + +done: + SAFE_FREE(ucs2name); + + if (!NT_STATUS_IS_OK(ret)) { + return False; + } + + return True; +} + + + +/* -------------------------------------------------------------------------- ** + * Functions... + */ + +/* ************************************************************************** ** + * Initialize the static character test array. + * + * Input: none + * + * Output: none + * + * Notes: This function changes (loads) the contents of the + * array. The scope of is this file. + * + * ************************************************************************** ** + */ +static void init_chartest( void ) + { + char *illegalchars = "*\\/?<>|\":"; + unsigned char *s; + + memset( (char *)chartest, '\0', 256 ); + + for( s = (unsigned char *)illegalchars; *s; s++ ) + chartest[*s] = ILLEGAL_MASK; + + for( s = (unsigned char *)basechars; *s; s++ ) + chartest[*s] |= BASECHAR_MASK; + + ct_initialized = True; + } /* init_chartest */ + + +/* ************************************************************************** ** + * Return True if the name *could be* a mangled name. + * + * Input: s - A path name - in UNIX pathname format. + * + * Output: True if the name matches the pattern described below in the + * notes, else False. + * + * Notes: The input name is *not* tested for 8.3 compliance. This must be + * done separately. This function returns true if the name contains + * a magic character followed by excactly two characters from the + * basechars list (above), which in turn are followed either by the + * nul (end of string) byte or a dot (extension) or by a '/' (end of + * a directory name). + * + * ************************************************************************** ** + */ +static BOOL is_mangled(const char *s) + { + char *magic; + + if( !ct_initialized ) + init_chartest(); + + magic = strchr_m( s, magic_char ); + while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ + { + if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ + && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ + && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ + return( True ); /* If all above, then true, */ + magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ + } + return( False ); + } /* is_mangled */ + + +/* ************************************************************************** ** + * Compare two cache keys and return a value indicating their ordinal + * relationship. + * + * Input: ItemPtr - Pointer to a comparison key. In this case, this will + * be a mangled name string. + * NodePtr - Pointer to a node in the cache. The node structure + * will be followed in memory by a mangled name string. + * + * Output: A signed integer, as follows: + * (x < 0) <==> Key1 less than Key2 + * (x == 0) <==> Key1 equals Key2 + * (x > 0) <==> Key1 greater than Key2 + * + * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for + * more info. + * + * ************************************************************************** ** + */ +static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) + { + char *Key1 = (char *)ItemPtr; + char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); + + return( StrCaseCmp( Key1, Key2 ) ); + } /* cache_compare */ + +/* ************************************************************************** ** + * Free a cache entry. + * + * Input: WarrenZevon - Pointer to the entry that is to be returned to + * Nirvana. + * Output: none. + * + * Notes: This function gets around the possibility that the standard + * free() function may be implemented as a macro, or other evil + * subversions (oh, so much fun). + * + * ************************************************************************** ** + */ +static void cache_free_entry( ubi_trNodePtr WarrenZevon ) + { + ZERO_STRUCTP(WarrenZevon); + SAFE_FREE( WarrenZevon ); + } /* cache_free_entry */ + +/* ************************************************************************** ** + * Initializes or clears the mangled cache. + * + * Input: none. + * Output: none. + * + * Notes: There is a section below that is commented out. It shows how + * one might use lp_ calls to set the maximum memory and entry size + * of the cache. You might also want to remove the constants used + * in ubi_cacheInit() and replace them with lp_ calls. If so, then + * the calls to ubi_cacheSetMax*() would be moved into the else + * clause. Another option would be to pass in the max_entries and + * max_memory values as parameters. crh 09-Apr-1998. + * + * ************************************************************************** ** + */ +static void mangle_reset( void ) + { + if( !mc_initialized ) + { + (void)ubi_cacheInit( mangled_cache, + cache_compare, + cache_free_entry, + MANGLED_CACHE_MAX_ENTRIES, + MANGLED_CACHE_MAX_MEMORY ); + mc_initialized = True; + } + else + { + (void)ubi_cacheClear( mangled_cache ); + } + + /* + (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); + (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); + */ + } /* reset_mangled_cache */ + + +/* ************************************************************************** ** + * Add a mangled name into the cache. + * + * Notes: If the mangled cache has not been initialized, then the + * function will simply fail. It could initialize the cache, + * but that's not the way it was done before I changed the + * cache mechanism, so I'm sticking with the old method. + * + * If the extension of the raw name maps directly to the + * extension of the mangled name, then we'll store both names + * *without* extensions. That way, we can provide consistent + * reverse mangling for all names that match. The test here is + * a bit more careful than the one done in earlier versions of + * mangle.c: + * + * - the extension must exist on the raw name, + * - it must be all lower case + * - it must match the mangled extension (to prove that no + * mangling occurred). + * + * crh 07-Apr-1998 + * + * ************************************************************************** ** + */ +static void cache_mangled_name( char *mangled_name, char *raw_name ) + { + ubi_cacheEntryPtr new_entry; + char *s1; + char *s2; + size_t mangled_len; + size_t raw_len; + size_t i; + + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) + return; + + /* Init the string lengths. */ + mangled_len = strlen( mangled_name ); + raw_len = strlen( raw_name ); + + /* See if the extensions are unmangled. If so, store the entry + * without the extension, thus creating a "group" reverse map. + */ + s1 = strrchr( mangled_name, '.' ); + if( s1 && (s2 = strrchr( raw_name, '.' )) ) + { + i = 1; + while( s1[i] && (tolower( s1[i] ) == s2[i]) ) + i++; + if( !s1[i] && !s2[i] ) + { + mangled_len -= i; + raw_len -= i; + } + } + + /* Allocate a new cache entry. If the allocation fails, just return. */ + i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; + new_entry = malloc( i ); + if( !new_entry ) + return; + + /* Fill the new cache entry, and add it to the cache. */ + s1 = (char *)(new_entry + 1); + s2 = (char *)&(s1[mangled_len + 1]); + (void)StrnCpy( s1, mangled_name, mangled_len ); + (void)StrnCpy( s2, raw_name, raw_len ); + ubi_cachePut( mangled_cache, i, new_entry, s1 ); + } /* cache_mangled_name */ + +/* ************************************************************************** ** + * Check for a name on the mangled name stack + * + * Input: s - Input *and* output string buffer. + * + * Output: True if the name was found in the cache, else False. + * + * Notes: If a reverse map is found, the function will overwrite the string + * space indicated by the input pointer . This is frightening. + * It should be rewritten to return NULL if the long name was not + * found, and a pointer to the long name if it was found. + * + * ************************************************************************** ** + */ + +static BOOL check_cache( char *s ) +{ + ubi_cacheEntryPtr FoundPtr; + char *ext_start = NULL; + char *found_name; + char *saved_ext = NULL; + + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) + return( False ); + + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + + /* If we didn't find the name *with* the extension, try without. */ + if( !FoundPtr ) + { + ext_start = strrchr( s, '.' ); + if( ext_start ) + { + if((saved_ext = strdup(ext_start)) == NULL) + return False; + + *ext_start = '\0'; + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + /* + * At this point s is the name without the + * extension. We re-add the extension if saved_ext + * is not null, before freeing saved_ext. + */ + } + } + + /* Okay, if we haven't found it we're done. */ + if( !FoundPtr ) + { + if(saved_ext) + { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + SAFE_FREE(saved_ext); + } + return( False ); + } + + /* If we *did* find it, we need to copy it into the string buffer. */ + found_name = (char *)(FoundPtr + 1); + found_name += (strlen( found_name ) + 1); + + (void)pstrcpy( s, found_name ); + if( saved_ext ) + { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + SAFE_FREE(saved_ext); + } + + return( True ); +} /* check_mangled_cache */ + + +/***************************************************************************** + * do the actual mangling to 8.3 format + * the buffer must be able to hold 13 characters (including the null) + ***************************************************************************** + */ +static void to_8_3(char *s) + { + int csum; + char *p; + char extension[4]; + char base[9]; + int baselen = 0; + int extlen = 0; + + extension[0] = 0; + base[0] = 0; + + p = strrchr(s,'.'); + if( p && (strlen(p+1) < (size_t)4) ) + { + BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ + + if( all_normal && p[1] != 0 ) + { + *p = 0; + csum = str_checksum( s ); + *p = '.'; + } + else + csum = str_checksum(s); + } + else + csum = str_checksum(s); + + strupper( s ); + + if( p ) + { + if( p == s ) + safe_strcpy( extension, "___", 3 ); + else + { + *p++ = 0; + while( *p && extlen < 3 ) + { + if ( *p != '.') { + extension[extlen++] = p[0]; + } + p++; + } + extension[extlen] = 0; + } + } + + p = s; + + while( *p && baselen < 5 ) + { + if (*p != '.') { + base[baselen++] = p[0]; + } + p++; + } + base[baselen] = 0; + + csum = csum % (MANGLE_BASE*MANGLE_BASE); + + (void)slprintf(s, 12, "%s%c%c%c", + base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); + + if( *extension ) + { + (void)pstrcat( s, "." ); + (void)pstrcat( s, extension ); + } + + } /* mangle_name_83 */ + +/***************************************************************************** + * Convert a filename to DOS format. Return True if successful. + * + * Input: OutName - Source *and* destination buffer. + * + * NOTE that OutName must point to a memory space that + * is at least 13 bytes in size! + * + * need83 - If False, name mangling will be skipped unless the + * name contains illegal characters. Mapping will still + * be done, if appropriate. This is probably used to + * signal that a client does not require name mangling, + * thus skipping the name mangling even on shares which + * have name-mangling turned on. + * cache83 - If False, the mangled name cache will not be updated. + * This is usually used to prevent that we overwrite + * a conflicting cache entry prematurely, i.e. before + * we know whether the client is really interested in the + * current name. (See PR#13758). UKD. + * + * Output: Returns False only if the name wanted mangling but the share does + * not have name mangling turned on. + * + * **************************************************************************** + */ +static BOOL name_map(char *OutName, BOOL need83, BOOL cache83) +{ + smb_ucs2_t *OutName_ucs2; + DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, + need83 ? "True" : "False", cache83 ? "True" : "False")); + + if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) { + DEBUG(0, ("push_ucs2_allocate failed!\n")); + return False; + } + + /* check if it's already in 8.3 format */ + if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) { + char *tmp = NULL; + + /* mangle it into 8.3 */ + if (cache83) + tmp = strdup(OutName); + + to_8_3(OutName); + + if(tmp != NULL) { + cache_mangled_name(OutName, tmp); + SAFE_FREE(tmp); + } + } + + DEBUG(5,("name_map() ==> [%s]\n", OutName)); + SAFE_FREE(OutName_ucs2); + return(True); +} /* name_map */ + + +/* + the following provides the abstraction layer to make it easier + to drop in an alternative mangling implementation +*/ +static struct mangle_fns mangle_fns = { + is_mangled, + is_8_3, + mangle_reset, + check_cache, + name_map +}; + +/* return the methods for this mangling implementation */ +struct mangle_fns *mangle_hash_init(void) +{ + mangle_reset(); + + return &mangle_fns; +} diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c new file mode 100644 index 0000000000..71d9340718 --- /dev/null +++ b/source3/smbd/mangle_map.c @@ -0,0 +1,203 @@ +/* + Unix SMB/CIFS implementation. + Name mapping code + Copyright (C) Jeremy Allison 1998 + Copyright (C) Andrew Tridgell 2002 + + 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" + + +/* ************************************************************************** ** + * Used only in do_fwd_mangled_map(), below. + * ************************************************************************** ** + */ +static char *map_filename( char *s, /* This is null terminated */ + const char *pattern, /* This isn't. */ + int len ) /* This is the length of pattern. */ + { + static pstring matching_bit; /* The bit of the string which matches */ + /* a * in pattern if indeed there is a * */ + char *sp; /* Pointer into s. */ + char *pp; /* Pointer into p. */ + char *match_start; /* Where the matching bit starts. */ + pstring pat; + + StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */ + pstrcpy( matching_bit, "" ); /* Match but no star gets this. */ + pp = pat; /* Initialize the pointers. */ + sp = s; + + if( strequal(s, ".") || strequal(s, "..")) + { + return NULL; /* Do not map '.' and '..' */ + } + + if( (len == 1) && (*pattern == '*') ) + { + return NULL; /* Impossible, too ambiguous for */ + } /* words! */ + + while( (*sp) /* Not the end of the string. */ + && (*pp) /* Not the end of the pattern. */ + && (*sp == *pp) /* The two match. */ + && (*pp != '*') ) /* No wildcard. */ + { + sp++; /* Keep looking. */ + pp++; + } + + if( !*sp && !*pp ) /* End of pattern. */ + return( matching_bit ); /* Simple match. Return empty string. */ + + if( *pp == '*' ) + { + pp++; /* Always interrested in the chacter */ + /* after the '*' */ + if( !*pp ) /* It is at the end of the pattern. */ + { + StrnCpy( matching_bit, s, sp-s ); + return( matching_bit ); + } + else + { + /* The next character in pattern must match a character further */ + /* along s than sp so look for that character. */ + match_start = sp; + while( (*sp) /* Not the end of s. */ + && (*sp != *pp) ) /* Not the same */ + sp++; /* Keep looking. */ + if( !*sp ) /* Got to the end without a match. */ + { + return( NULL ); + } /* Still hope for a match. */ + else + { + /* Now sp should point to a matching character. */ + StrnCpy(matching_bit, match_start, sp-match_start); + /* Back to needing a stright match again. */ + while( (*sp) /* Not the end of the string. */ + && (*pp) /* Not the end of the pattern. */ + && (*sp == *pp) ) /* The two match. */ + { + sp++; /* Keep looking. */ + pp++; + } + if( !*sp && !*pp ) /* Both at end so it matched */ + return( matching_bit ); + else + return( NULL ); + } + } + } + return( NULL ); /* No match. */ + } /* map_filename */ + + +/* ************************************************************************** ** + * MangledMap is a series of name pairs in () separated by spaces. + * If s matches the first of the pair then the name given is the + * second of the pair. A * means any number of any character and if + * present in the second of the pair as well as the first the + * matching part of the first string takes the place of the * in the + * second. + * + * I wanted this so that we could have RCS files which can be used + * by UNIX and DOS programs. My mapping string is (RCS rcs) which + * converts the UNIX RCS file subdirectory to lowercase thus + * preventing mangling. + * + * See 'mangled map' in smb.conf(5). + * + * ************************************************************************** ** + */ +static void mangled_map(char *s, const char *MangledMap) +{ + char *start=MangledMap; /* Use this to search for mappings. */ + char *end; /* Used to find the end of strings. */ + char *match_string; + pstring new_string; /* Make up the result here. */ + char *np; /* Points into new_string. */ + + DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) ); + while( *start ) { + while( (*start) && (*start != '(') ) + start++; + if( !*start ) + continue; /* Always check for the end. */ + start++; /* Skip the ( */ + end = start; /* Search for the ' ' or a ')' */ + DEBUG( 5, ("Start of first in pair '%s'\n", start) ); + while( (*end) && !((*end == ' ') || (*end == ')')) ) + end++; + if( !*end ) { + start = end; + continue; /* Always check for the end. */ + } + DEBUG( 5, ("End of first in pair '%s'\n", end) ); + if( (match_string = map_filename( s, start, end-start )) ) { + DEBUG( 5, ("Found a match\n") ); + /* Found a match. */ + start = end + 1; /* Point to start of what it is to become. */ + DEBUG( 5, ("Start of second in pair '%s'\n", start) ); + end = start; + np = new_string; + while( (*end) /* Not the end of string. */ + && (*end != ')') /* Not the end of the pattern. */ + && (*end != '*') ) /* Not a wildcard. */ + *np++ = *end++; + + if( !*end ) { + start = end; + continue; /* Always check for the end. */ + } + if( *end == '*' ) { + pstrcpy( np, match_string ); + np += strlen( match_string ); + end++; /* Skip the '*' */ + while ((*end) /* Not the end of string. */ + && (*end != ')') /* Not the end of the pattern. */ + && (*end != '*'))/* Not a wildcard. */ + *np++ = *end++; + } + if (!*end) { + start = end; + continue; /* Always check for the end. */ + } + *np++ = '\0'; /* NULL terminate it. */ + DEBUG(5,("End of second in pair '%s'\n", end)); + pstrcpy( s, new_string ); /* Substitute with the new name. */ + DEBUG( 5, ("s is now '%s'\n", s) ); + } + start = end; /* Skip a bit which cannot be wanted anymore. */ + start++; + } +} + +/* + front end routine to the mangled map code + personally I think that the whole idea of "mangled map" is completely bogus +*/ +void mangle_map_filename(char *fname, int snum) +{ + char *map; + + map = lp_mangled_map(snum); + if (!map || !*map) return; + + mangled_map(fname, map); +} diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c55c806a43..23606f1d14 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -831,7 +831,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name)); remove_oplock(fsp,True); +#if FASCIST_OPLOCK_BACKOFF global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */ +#endif } /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f3b3ce4a8a..fbb981781f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1300,8 +1300,8 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) * Tine Smukavec . */ - if (!rc && is_mangled(mask)) - check_mangled_cache( mask ); + if (!rc && mangle_is_mangled(mask)) + mangle_check_cache( mask ); has_wild = ms_has_wild(mask); @@ -1842,12 +1842,15 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, /* we won't return a status if write through is not selected - this follows what WfWg does */ END_PROFILE(SMBwritebraw); if (!write_through && total_written==tcount) { + +#if RABBIT_PELLET_FIX /* * Fix for "rabbit pellet" mode, trigger an early TCP ack by * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA. */ if (!send_keepalive(smbd_server_fd())) exit_server("reply_writebraw: send of keepalive failed"); +#endif return(-1); } @@ -3022,21 +3025,8 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO * Tine Smukavec . */ -#if 1 - if (!rc && is_mangled(mask)) - check_mangled_cache( mask ); -#else - if (!rc) - { - char *unmangled; - - unmangled = dos_unmangle(mask); - if (unmangled) - strncpy(mask, unmangled, strlen(unmangled) + 1); - - SAFE_FREE(unmangled); - } -#endif + if (!rc && mangle_is_mangled(mask)) + mangle_check_cache( mask ); has_wild = ms_has_wild(mask); @@ -3044,7 +3034,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO /* * No wildcards - just process the one file. */ - BOOL is_short_name = is_8_3(name, True); + BOOL is_short_name = mangle_is_8_3(name, True); /* Add a terminating '/' to the directory name. */ pstrcat(directory,"/"); @@ -3439,21 +3429,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec . */ -#if 1 - if (!rc && is_mangled(mask)) - check_mangled_cache( mask ); -#else - if (!rc) - { - char *unmangled; - - unmangled = dos_unmangle(mask); - if (unmangled) - strncpy(mask, unmangled, strlen(unmangled) + 1); - - SAFE_FREE(unmangled); - } -#endif + if (!rc && mangle_is_mangled(mask)) + mangle_check_cache( mask ); has_wild = ms_has_wild(mask); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e3912ba939..c759f56e0c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -418,7 +418,7 @@ BOOL reload_services(BOOL test) } } - reset_mangled_cache(); + mangle_reset_cache(); reset_stat_cache(); /* this forces service parameters to be flushed */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ca8ad5fa79..1972e9c8c8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -475,7 +475,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) got_match = mask_match(fname, mask, case_sensitive); - if(!got_match && !is_8_3(fname, False)) { + if(!got_match && !mangle_is_8_3(fname, False)) { /* * It turns out that NT matches wildcards against @@ -486,7 +486,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstring newname; pstrcpy( newname, fname); - name_map_mangle( newname, True, False, SNUM(conn)); + mangle_map( newname, True, False, SNUM(conn)); if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive))) got_match = mask_match(newname, mask, case_sensitive); } @@ -549,7 +549,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } } - name_map_mangle(fname,False,True,SNUM(conn)); + mangle_map(fname,False,True,SNUM(conn)); p = pdata; nameptr = p; @@ -597,7 +597,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - was_8_3 = is_8_3(fname, True); + was_8_3 = mangle_is_8_3(fname, True); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; @@ -613,7 +613,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (!was_8_3) { pstring mangled_name; pstrcpy(mangled_name, fname); - name_map_mangle(mangled_name,True,True,SNUM(conn)); + mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); SSVAL(p, 0, len); @@ -997,8 +997,8 @@ static int call_trans2findfirst(connection_struct *conn, * (see PR#13758). JRA. */ - if(!is_8_3( mask, False)) - name_map_mangle(mask, True, True, SNUM(conn)); + if(!mangle_is_8_3( mask, False)) + mangle_map(mask, True, True, SNUM(conn)); return(-1); } @@ -1142,14 +1142,14 @@ resume_key = %d resume name = %s continue=%d level = %d\n", dname = ReadDirName(dirptr); /* - * Remember, name_map_mangle is called by + * Remember, mangle_map is called by * get_lanman2_dir_entry(), so the resume name * could be mangled. Ensure we do the same * here. */ if(dname != NULL) - name_map_mangle( dname, False, True, SNUM(conn)); + mangle_map( dname, False, True, SNUM(conn)); if(dname && strcsequal( resume_name, dname)) { @@ -1170,14 +1170,14 @@ resume_key = %d resume name = %s continue=%d level = %d\n", for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) { /* - * Remember, name_map_mangle is called by + * Remember, mangle_map is called by * get_lanman2_dir_entry(), so the resume name * could be mangled. Ensure we do the same * here. */ if(dname != NULL) - name_map_mangle( dname, False, True, SNUM(conn)); + mangle_map( dname, False, True, SNUM(conn)); if(dname && strcsequal( resume_name, dname)) { @@ -1657,8 +1657,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pstrcpy(short_name,base_name); /* Mangle if not already 8.3 */ - if(!is_8_3(short_name, True)) { - if(!name_map_mangle(short_name,True,True,SNUM(conn))) + if(!mangle_is_8_3(short_name, True)) { + if(!mangle_map(short_name,True,True,SNUM(conn))) *short_name = '\0'; } len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER); -- cgit From 714518e550f3c6ee36fa6e3e2447b943898a2ac5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 09:56:38 +0000 Subject: this adds a completely new hash based mangling scheme the hash for this scheme is *much* larger (approximately 31 bits) and the code is written to be very fast, correctly handling multibyte while not doing any actual multi-byte conversions in the vast majority of cases you can select this scheme using "mangling method = hash2", although I may make it the default if it works out well. (This used to be commit bb173c1a7e2408ced967ebac40b5e3f852ccd3a1) --- source3/smbd/mangle.c | 1 + source3/smbd/mangle_hash2.c | 510 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 511 insertions(+) create mode 100644 source3/smbd/mangle_hash2.c (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 9d0641d5c8..6bf60f0543 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -28,6 +28,7 @@ static struct { struct mangle_fns *(*init_fn)(void); } mangle_backends[] = { { "hash", mangle_hash_init }, + { "hash2", mangle_hash2_init }, { NULL, NULL } }; diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c new file mode 100644 index 0000000000..661ae7eb44 --- /dev/null +++ b/source3/smbd/mangle_hash2.c @@ -0,0 +1,510 @@ +/* + Unix SMB/CIFS implementation. + new hash based name mangling implementation + Copyright (C) Andrew Tridgell 2002 + + 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. +*/ + +/* + this mangling scheme uses the following format + + Annnn~n.AAA + + where nnnnn is a base 36 hash, and A represents characters from the original string + + The hash is taken of the leading part of the long filename, in uppercase + + for simplicity, we only allow ascii characters in 8.3 names + */ + + +/* + =============================================================================== + NOTE NOTE NOTE!!! + + This file deliberately uses non-multibyte string functions in many places. This + is *not* a mistake. This code is multi-byte safe, but it gets this property + through some very subtle knowledge of the way multi-byte strings are encoded + and the fact that this mangling algorithm only supports ascii characters in + 8.3 names. + + please don't convert this file to use the *_m() functions!! + =============================================================================== +*/ + + +#include "includes.h" + + +#define FLAG_BASECHAR 1 +#define FLAG_ASCII 2 +#define FLAG_ILLEGAL 4 +#define FLAG_POSSIBLE1 8 +#define FLAG_POSSIBLE2 16 +#define FLAG_POSSIBLE3 32 + +#define CACHE_SIZE 8192 + +/* these tables are used to provide fast tests for characters */ +static unsigned char char_flags[256]; + +/* we will use a very simple direct mapped prefix cache. The big + advantage of this cache structure is speed and low memory usage + + The cache is indexed by the low-order bits of the hash, and confirmed by + hashing the resulting cache entry to match the known hash +*/ +static char **prefix_cache; + +/* these are the characters we use in the 8.3 hash. Must be 36 chars long */ +const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static unsigned char base_reverse[256]; +#define base_forward(v) basechars[v] + +/* the list of reserved dos names - all of these are illegal */ +const char *reserved_names[] = { "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4", + "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }; + +/* + hash a string of the specified length. The string does not need to be + null terminated + + this hash needs to be fast with a low collision rate (what hash doesn't?) +*/ +static u32 mangle_hash(const char *key, unsigned length) +{ + u32 value; + u32 i; + fstring str; + + strncpy(str, key, length); + str[length] = 0; + strupper_m(str); + + /* the length of a multi-byte string can change after a strupper */ + length = strlen(str); + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * length, i=0; i < length; i++) { + value = (value + (((unsigned char)str[i]) << (i*5 % 24))); + } + + return (1103515243 * value + 12345); +} + +/* + initialise the prefix cache + */ +static BOOL cache_init(void) +{ + if (prefix_cache) return True; + + prefix_cache = malloc(sizeof(char *) * CACHE_SIZE); + if (!prefix_cache) return False; + + memset(prefix_cache, 0, sizeof(char *) * CACHE_SIZE); + return True; +} + +/* + insert an entry into the prefix cache. The string may not be null terminated +*/ +static void cache_insert(const char *prefix, int length, u32 hash) +{ + int i = hash % CACHE_SIZE; + + if (prefix_cache[i]) { + free(prefix_cache[i]); + } + + prefix_cache[i] = strndup(prefix, length); +} + +/* + lookup an entry in the prefix cache. Return NULL if not found. +*/ +static const char *cache_lookup(u32 hash) +{ + int i = hash % CACHE_SIZE; + + if (!prefix_cache[i]) return NULL; + + /* we have a possible match - compute the hash to confirm */ + if (hash != mangle_hash(prefix_cache[i], strlen(prefix_cache[i]))) { + return NULL; + } + + /* yep, it matched */ + return prefix_cache[i]; +} + + +/* + determine if a string is possibly in a mangled format, ignoring + case + + In this algorithm, mangled names use only pure ascii characters (no + multi-byte) so we can avoid doing a UCS2 conversion +*/ +static BOOL is_mangled(const char *name) +{ + /* the best distinguishing characteristic is the ~ */ + if (name[6] != '~') return False; + + /* check extension */ + /* check first character */ + /* check rest of hash */ + + return True; +} + + +/* + see if a filename is an allowable 8.3 name. + + we are only going to allow ascii characters in 8.3 names, as this + simplifies things greatly (it means that we know the string won't + get larger when converted from UNIX to DOS formats) +*/ +static BOOL is_8_3(const char *name, BOOL check_case) +{ + int len, i; + char *dot_p; + + /* as a special case, the names '.' and '..' are allowable 8.3 names */ + if (name[0] == '.') { + if (!name[1] || (name[1] == '.' && !name[2])) { + return True; + } + } + + /* the simplest test is on the overall length of the + filename. Note that we deliberately use the ascii string + length (not the multi-byte one) as it is faster, and gives us + the result we need in this case. Using strlen_m would not + only be slower, it would be incorrect */ + len = strlen(name); + if (len > 12) return False; + + /* find the '.'. Note that once again we use the non-multibyte + function */ + dot_p = strchr(name, '.'); + + if (!dot_p) { + /* if the name doesn't contain a '.' then its length + must be less than 8 */ + if (len > 8) { + return False; + } + } else { + int prefix_len, suffix_len; + + /* if it does contain a dot then the prefix must be <= + 8 and the suffix <= 3 in length */ + prefix_len = PTR_DIFF(dot_p, name); + suffix_len = len - (prefix_len+1); + + if (prefix_len > 8 || suffix_len > 3) { + return False; + } + + /* a 8.3 name cannot contain more than 1 '.' */ + if (strchr(dot_p+1, '.')) { + return False; + } + } + + /* the length are all OK. Now check to see if the characters themselves are OK */ + for (i=0; name[i]; i++) { + if (!(char_flags[(unsigned)(name[i])] & FLAG_ASCII)) { + return False; + } + } + + /* it is a good 8.3 name */ + return True; +} + + +/* + reset the mangling cache on a smb.conf reload. This only really makes sense for + mangling backends that have parameters in smb.conf, and as this backend doesn't + this is a NULL operation +*/ +static void mangle_reset(void) +{ + /* noop */ +} + + +/* + try to find a 8.3 name in the cache, and if found then + replace the string with the original long name. + + The filename must be able to hold at least sizeof(fstring) +*/ +static BOOL check_cache(char *name) +{ + u32 hash, multiplier; + int i; + const char *prefix; + char extension[4]; + + /* make sure that this is a mangled name from this cache */ + if (!is_mangled(name)) { + return False; + } + + /* we need to extract the hash from the 8.3 name */ + hash = base_reverse[(unsigned char)name[7]]; + for (multiplier=36, i=5;i>=1;i--) { + u32 v = base_reverse[(unsigned char)name[i]]; + hash += multiplier * v; + multiplier *= 36; + } + + /* now look in the prefix cache for that hash */ + prefix = cache_lookup(hash); + if (!prefix) { + return False; + } + + /* we found it - construct the full name */ + strncpy(extension, name+9, 3); + + if (extension[0]) { + slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); + } else { + fstrcpy(name, prefix); + } + return True; +} + + +/* + look for a DOS reserved name +*/ +static BOOL is_reserved_name(const char *name) +{ + if ((char_flags[(unsigned char)name[0]] & FLAG_POSSIBLE1) && + (char_flags[(unsigned char)name[1]] & FLAG_POSSIBLE2) && + (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3)) { + /* a likely match, scan the lot */ + int i; + for (i=0; reserved_names[i]; i++) { + int len = strlen(reserved_names[i]); + /* note that we match on COM1 as well as COM1.foo */ + if (strncasecmp(name, reserved_names[i], len) == 0 && + (name[len] == '.' || name[len] == 0)) { + return True; + } + } + } + + return False; +} + +/* + see if a filename is a legal long filename +*/ +static BOOL is_legal_name(const char *name) +{ + while (*name) { + if (char_flags[(unsigned char)*name] & FLAG_ILLEGAL) { + return False; + } + name++; + } + + return True; +} + +/* + the main forward mapping function, which converts a long filename to + a 8.3 name + + if need83 is not set then we only do the mangling if the name is illegal + as a long name + + if cache83 is not set then we don't cache the result + + the name parameter must be able to hold 13 bytes +*/ +static BOOL name_map(char *name, BOOL need83, BOOL cache83) +{ + char *dot_p; + char lead_char; + char extension[4]; + int extension_length, i; + int prefix_len; + u32 hash, v; + char new_name[13]; + + /* reserved names are handled specially */ + if (!is_reserved_name(name)) { + /* if the name is already a valid 8.3 name then we don't need to + do anything */ + if (is_8_3(name, False)) { + return True; + } + + /* if the caller doesn't strictly need 8.3 then just check for illegal + filenames */ + if (!need83 && is_legal_name(name)) { + return True; + } + } + + /* find the '.' if any */ + dot_p = strchr(name, '.'); + + /* the leading character in the mangled name is taken from + the first character of the name, if it is ascii + otherwise '_' is used + */ + lead_char = name[0]; + if (! (char_flags[(unsigned char)lead_char] & FLAG_ASCII)) { + lead_char = '_'; + } + + /* the prefix is anything up to the first dot */ + if (dot_p) { + prefix_len = PTR_DIFF(dot_p, name); + } else { + prefix_len = strlen(name); + } + + /* the extension of the mangled name is taken from the first 3 + ascii chars after the dot */ + extension_length = 0; + if (dot_p) { + for (i=1; extension_length < 3 && dot_p[i]; i++) { + char c = dot_p[i]; + if (char_flags[(unsigned char)c] & FLAG_ASCII) { + extension[extension_length++] = c; + } + } + } + + /* find the hash for this prefix */ + v = hash = mangle_hash(name, prefix_len); + + /* now form the mangled name */ + new_name[0] = lead_char; + new_name[7] = base_forward(v % 36); + new_name[6] = '~'; + for (i=5; i>=1; i--) { + v = v / 36; + new_name[i] = base_forward(v % 36); + } + + /* add the extension */ + if (extension_length) { + new_name[8] = '.'; + memcpy(&new_name[9], extension, extension_length); + new_name[9+extension_length] = 0; + } else { + new_name[8] = 0; + } + + if (cache83) { + /* put it in the cache */ + cache_insert(name, prefix_len, hash); + } + + /* and overwrite the old name */ + fstrcpy(name, new_name); + + /* all done, we've managed to mangle it */ + return True; +} + + +/* initialise the flags table + + we allow only a very restricted set of characters as 'ascii' in this + mangling backend. This isn't a significant problem as modern clients + use the 'long' filenames anyway, and those don't have these + restrictions. +*/ +static void init_tables(void) +{ + int i; + + memset(char_flags, 0, sizeof(char_flags)); + + for (i=0;i<128;i++) { + if ((i >= '0' && i <= '9') || + (i >= 'a' && i <= 'z') || + (i >= 'A' && i <= 'Z')) { + char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); + } + if (strchr("._-$~", i)) { + char_flags[i] |= FLAG_ASCII; + } + + if (strchr("*\\/?<>|\":", i)) { + char_flags[i] |= FLAG_ILLEGAL; + } + } + + memset(base_reverse, 0, sizeof(base_reverse)); + for (i=0;i<36;i++) { + base_reverse[(unsigned char)base_forward(i)] = i; + } + + /* fill in the reserved names flags. These are used as a very + fast filter for finding possible DOS reserved filenames */ + for (i=0; reserved_names[i]; i++) { + unsigned char c1, c2, c3; + + c1 = (unsigned char)reserved_names[i][0]; + c2 = (unsigned char)reserved_names[i][1]; + c3 = (unsigned char)reserved_names[i][2]; + + char_flags[c1] |= FLAG_POSSIBLE1; + char_flags[c2] |= FLAG_POSSIBLE2; + char_flags[c3] |= FLAG_POSSIBLE3; + char_flags[tolower(c1)] |= FLAG_POSSIBLE1; + char_flags[tolower(c2)] |= FLAG_POSSIBLE2; + char_flags[tolower(c3)] |= FLAG_POSSIBLE3; + } +} + + +/* + the following provides the abstraction layer to make it easier + to drop in an alternative mangling implementation */ +static struct mangle_fns mangle_fns = { + is_mangled, + is_8_3, + mangle_reset, + check_cache, + name_map +}; + +/* return the methods for this mangling implementation */ +struct mangle_fns *mangle_hash2_init(void) +{ + init_tables(); + mangle_reset(); + + if (!cache_init()) { + return NULL; + } + + return &mangle_fns; +} -- cgit From b1f04740ad705249cc783e8a084ca2d70fd8f3a7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 10:52:59 +0000 Subject: some optimisations to the new mangling system (This used to be commit 30b35d0c1f41f72ebe230905f76db8807802a6cc) --- source3/smbd/mangle_hash2.c | 60 +++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 661ae7eb44..88b9ba20cb 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -48,15 +48,24 @@ #include "includes.h" +#if 0 +#define M_DEBUG(level, x) DEBUG(level, x) +#else +#define M_DEBUG(level, x) +#endif #define FLAG_BASECHAR 1 #define FLAG_ASCII 2 #define FLAG_ILLEGAL 4 -#define FLAG_POSSIBLE1 8 -#define FLAG_POSSIBLE2 16 -#define FLAG_POSSIBLE3 32 +#define FLAG_WILDCARD 8 +#define FLAG_POSSIBLE1 16 +#define FLAG_POSSIBLE2 32 +#define FLAG_POSSIBLE3 64 +#define FLAG_POSSIBLE4 128 -#define CACHE_SIZE 8192 +#ifndef MANGLE_CACHE_SIZE +#define MANGLE_CACHE_SIZE 4096 +#endif /* these tables are used to provide fast tests for characters */ static unsigned char char_flags[256]; @@ -68,6 +77,7 @@ static unsigned char char_flags[256]; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; +static u32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -112,10 +122,14 @@ static BOOL cache_init(void) { if (prefix_cache) return True; - prefix_cache = malloc(sizeof(char *) * CACHE_SIZE); + prefix_cache = malloc(sizeof(char *) * MANGLE_CACHE_SIZE); if (!prefix_cache) return False; - memset(prefix_cache, 0, sizeof(char *) * CACHE_SIZE); + prefix_cache_hashes = malloc(sizeof(u32) * MANGLE_CACHE_SIZE); + if (!prefix_cache_hashes) return False; + + memset(prefix_cache, 0, sizeof(char *) * MANGLE_CACHE_SIZE); + memset(prefix_cache_hashes, 0, sizeof(char *) * MANGLE_CACHE_SIZE); return True; } @@ -124,13 +138,14 @@ static BOOL cache_init(void) */ static void cache_insert(const char *prefix, int length, u32 hash) { - int i = hash % CACHE_SIZE; + int i = hash % MANGLE_CACHE_SIZE; if (prefix_cache[i]) { free(prefix_cache[i]); } prefix_cache[i] = strndup(prefix, length); + prefix_cache_hashes[i] = hash; } /* @@ -138,12 +153,9 @@ static void cache_insert(const char *prefix, int length, u32 hash) */ static const char *cache_lookup(u32 hash) { - int i = hash % CACHE_SIZE; - - if (!prefix_cache[i]) return NULL; + int i = hash % MANGLE_CACHE_SIZE; - /* we have a possible match - compute the hash to confirm */ - if (hash != mangle_hash(prefix_cache[i], strlen(prefix_cache[i]))) { + if (!prefix_cache[i] || hash != prefix_cache_hashes[i]) { return NULL; } @@ -229,7 +241,7 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { - if (!(char_flags[(unsigned)(name[i])] & FLAG_ASCII)) { + if (!(char_flags[(unsigned)(name[i])] & (FLAG_ASCII|FLAG_WILDCARD))) { return False; } } @@ -286,10 +298,13 @@ static BOOL check_cache(char *name) strncpy(extension, name+9, 3); if (extension[0]) { + M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); } else { + M_DEBUG(0,("check_cache: %s -> %s\n", name, prefix)); fstrcpy(name, prefix); } + return True; } @@ -301,7 +316,8 @@ static BOOL is_reserved_name(const char *name) { if ((char_flags[(unsigned char)name[0]] & FLAG_POSSIBLE1) && (char_flags[(unsigned char)name[1]] & FLAG_POSSIBLE2) && - (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3)) { + (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3) && + (char_flags[(unsigned char)name[3]] & FLAG_POSSIBLE4)) { /* a likely match, scan the lot */ int i; for (i=0; reserved_names[i]; i++) { @@ -379,6 +395,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) if (! (char_flags[(unsigned char)lead_char] & FLAG_ASCII)) { lead_char = '_'; } + lead_char = toupper(lead_char); /* the prefix is anything up to the first dot */ if (dot_p) { @@ -394,7 +411,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; if (char_flags[(unsigned char)c] & FLAG_ASCII) { - extension[extension_length++] = c; + extension[extension_length++] = toupper(c); } } } @@ -425,6 +442,8 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) cache_insert(name, prefix_len, hash); } + M_DEBUG(0,("name_map: %s -> %s\n", name, new_name)); + /* and overwrite the old name */ fstrcpy(name, new_name); @@ -459,6 +478,10 @@ static void init_tables(void) if (strchr("*\\/?<>|\":", i)) { char_flags[i] |= FLAG_ILLEGAL; } + + if (strchr("*?\"<>", i)) { + char_flags[i] |= FLAG_WILDCARD; + } } memset(base_reverse, 0, sizeof(base_reverse)); @@ -469,18 +492,23 @@ static void init_tables(void) /* fill in the reserved names flags. These are used as a very fast filter for finding possible DOS reserved filenames */ for (i=0; reserved_names[i]; i++) { - unsigned char c1, c2, c3; + unsigned char c1, c2, c3, c4; c1 = (unsigned char)reserved_names[i][0]; c2 = (unsigned char)reserved_names[i][1]; c3 = (unsigned char)reserved_names[i][2]; + c4 = (unsigned char)reserved_names[i][3]; char_flags[c1] |= FLAG_POSSIBLE1; char_flags[c2] |= FLAG_POSSIBLE2; char_flags[c3] |= FLAG_POSSIBLE3; + char_flags[c4] |= FLAG_POSSIBLE4; char_flags[tolower(c1)] |= FLAG_POSSIBLE1; char_flags[tolower(c2)] |= FLAG_POSSIBLE2; char_flags[tolower(c3)] |= FLAG_POSSIBLE3; + char_flags[tolower(c4)] |= FLAG_POSSIBLE4; + + char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; } } -- cgit From ef88357403280922dc5fa707f6d58c7255083902 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 11:46:42 +0000 Subject: added some more comments (This used to be commit 8d6f2e239940cbac44f6f0e9d584a47553acbc56) --- source3/smbd/mangle_hash2.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 88b9ba20cb..28200eb3ee 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -54,15 +54,21 @@ #define M_DEBUG(level, x) #endif +/* these flags are used to mark characters in as having particular + properties */ #define FLAG_BASECHAR 1 #define FLAG_ASCII 2 #define FLAG_ILLEGAL 4 #define FLAG_WILDCARD 8 + +/* the "possible" flags are used as a fast way to find possible DOS + reserved filenames */ #define FLAG_POSSIBLE1 16 #define FLAG_POSSIBLE2 32 #define FLAG_POSSIBLE3 64 #define FLAG_POSSIBLE4 128 +/* by default have a max of 4096 entries in the cache. */ #ifndef MANGLE_CACHE_SIZE #define MANGLE_CACHE_SIZE 4096 #endif @@ -100,11 +106,15 @@ static u32 mangle_hash(const char *key, unsigned length) u32 i; fstring str; + /* we have to uppercase here to ensure that the mangled name + doesn't depend on the case of the long name. Note that this + is the only place where we need to use a multi-byte string + function */ strncpy(str, key, length); str[length] = 0; strupper_m(str); - /* the length of a multi-byte string can change after a strupper */ + /* the length of a multi-byte string can change after a strupper_m */ length = strlen(str); /* Set the initial value from the key size. */ @@ -116,7 +126,7 @@ static u32 mangle_hash(const char *key, unsigned length) } /* - initialise the prefix cache + initialise (ie. allocate) the prefix cache */ static BOOL cache_init(void) { @@ -134,8 +144,8 @@ static BOOL cache_init(void) } /* - insert an entry into the prefix cache. The string may not be null terminated -*/ + insert an entry into the prefix cache. The string might not be null + terminated */ static void cache_insert(const char *prefix, int length, u32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -419,7 +429,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) /* find the hash for this prefix */ v = hash = mangle_hash(name, prefix_len); - /* now form the mangled name */ + /* now form the mangled name. */ new_name[0] = lead_char; new_name[7] = base_forward(v % 36); new_name[6] = '~'; -- cgit From bf9cb3c5f3c5096bcf25a16f63ae18dad73bbef7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 12:14:55 +0000 Subject: - tidier flag checking code - finished the is_mangled() function (This used to be commit 128bec2071d640c775b58322256ac6bb03363741) --- source3/smbd/mangle_hash2.c | 48 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 28200eb3ee..0bd538d2f4 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -76,6 +76,8 @@ /* these tables are used to provide fast tests for characters */ static unsigned char char_flags[256]; +#define FLAG_CHECK(c, flag) (char_flags[(unsigned char)(c)] & (flag)) + /* we will use a very simple direct mapped prefix cache. The big advantage of this cache structure is speed and low memory usage @@ -183,12 +185,41 @@ static const char *cache_lookup(u32 hash) */ static BOOL is_mangled(const char *name) { + int len, i; + + M_DEBUG(0,("is_mangled %s\n", name)); + /* the best distinguishing characteristic is the ~ */ if (name[6] != '~') return False; + /* check the length */ + len = strlen(name); + if (len > 12 || len < 8) return False; + /* check extension */ + if (len > 8) { + if (name[8] != '.') return False; + for (i=9; name[i]; i++) { + if (! FLAG_CHECK(name[i], FLAG_ASCII)) { + return False; + } + } + } + /* check first character */ + if (! FLAG_CHECK(name[0], FLAG_ASCII)) { + return False; + } + /* check rest of hash */ + if (! FLAG_CHECK(name[7], FLAG_BASECHAR)) { + return False; + } + for (i=1;i<6;i++) { + if (! FLAG_CHECK(name[i], FLAG_BASECHAR)) { + return False; + } + } return True; } @@ -251,7 +282,8 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { - if (!(char_flags[(unsigned)(name[i])] & (FLAG_ASCII|FLAG_WILDCARD))) { + /* note that we allow wildcard petterns! */ + if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD)) { return False; } } @@ -324,10 +356,10 @@ static BOOL check_cache(char *name) */ static BOOL is_reserved_name(const char *name) { - if ((char_flags[(unsigned char)name[0]] & FLAG_POSSIBLE1) && - (char_flags[(unsigned char)name[1]] & FLAG_POSSIBLE2) && - (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3) && - (char_flags[(unsigned char)name[3]] & FLAG_POSSIBLE4)) { + if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) && + FLAG_CHECK(name[1], FLAG_POSSIBLE2) && + FLAG_CHECK(name[2], FLAG_POSSIBLE3) && + FLAG_CHECK(name[3], FLAG_POSSIBLE4)) { /* a likely match, scan the lot */ int i; for (i=0; reserved_names[i]; i++) { @@ -349,7 +381,7 @@ static BOOL is_reserved_name(const char *name) static BOOL is_legal_name(const char *name) { while (*name) { - if (char_flags[(unsigned char)*name] & FLAG_ILLEGAL) { + if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } name++; @@ -402,7 +434,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) otherwise '_' is used */ lead_char = name[0]; - if (! (char_flags[(unsigned char)lead_char] & FLAG_ASCII)) { + if (! FLAG_CHECK(lead_char, FLAG_ASCII)) { lead_char = '_'; } lead_char = toupper(lead_char); @@ -420,7 +452,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) if (dot_p) { for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; - if (char_flags[(unsigned char)c] & FLAG_ASCII) { + if (FLAG_CHECK(c, FLAG_ASCII)) { extension[extension_length++] = toupper(c); } } -- cgit From 4c889cb8b6ebaf73fd4034c590b758c367b69bae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 13:35:28 +0000 Subject: don't treat '.' as FLAG_ASCII, instead handle it separately (This used to be commit ecdddd674f2ffad16eaa01a68c9c91ff3b355b3f) --- source3/smbd/mangle_hash2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0bd538d2f4..8b4b0f478d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -283,7 +283,7 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { /* note that we allow wildcard petterns! */ - if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD)) { + if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD) && name[i] != '.') { return False; } } @@ -513,7 +513,7 @@ static void init_tables(void) (i >= 'A' && i <= 'Z')) { char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); } - if (strchr("._-$~", i)) { + if (strchr("_-$~", i)) { char_flags[i] |= FLAG_ASCII; } -- cgit From 1ed0c5ea704a64a5ace6ba9ad600cb320c7d7ea4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 14:03:30 +0000 Subject: a few debug statements (disabled) (This used to be commit 582f753eac7a111a93a8d6c049398a0998af848f) --- source3/smbd/mangle_hash2.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 8b4b0f478d..0ecea59caf 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -187,7 +187,7 @@ static BOOL is_mangled(const char *name) { int len, i; - M_DEBUG(0,("is_mangled %s\n", name)); + M_DEBUG(0,("is_mangled %s ?\n", name)); /* the best distinguishing characteristic is the ~ */ if (name[6] != '~') return False; @@ -221,6 +221,8 @@ static BOOL is_mangled(const char *name) } } + M_DEBUG(0,("is_mangled %s -> yes\n", name)); + return True; } @@ -319,6 +321,7 @@ static BOOL check_cache(char *name) /* make sure that this is a mangled name from this cache */ if (!is_mangled(name)) { + M_DEBUG(0,("check_cache: %s -> not mangled\n", name)); return False; } @@ -333,6 +336,7 @@ static BOOL check_cache(char *name) /* now look in the prefix cache for that hash */ prefix = cache_lookup(hash); if (!prefix) { + M_DEBUG(0,("check_cache: %s -> %08X -> not found\n", name, hash)); return False; } @@ -484,7 +488,8 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) cache_insert(name, prefix_len, hash); } - M_DEBUG(0,("name_map: %s -> %s\n", name, new_name)); + M_DEBUG(0,("name_map: %s -> %08X -> %s (cache=%d)\n", + name, hash, new_name, cache83)); /* and overwrite the old name */ fstrcpy(name, new_name); -- cgit From 5c0e682c4a2e8bb91911064c51bf4c690555cb33 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 14:20:18 +0000 Subject: - the 36^6 hash space gives 31 bits, not 32 bits. We need to mask the hash to suit - the prefix ends at the last dot, not the first (This used to be commit 91a3ccd3e790f980421c1ee93388e19e87026b29) --- source3/smbd/mangle_hash2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0ecea59caf..96ca7360b8 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -124,7 +124,9 @@ static u32 mangle_hash(const char *key, unsigned length) value = (value + (((unsigned char)str[i]) << (i*5 % 24))); } - return (1103515243 * value + 12345); + /* note that we force it to a 31 bit hash, to keep within the limits + of the 36^6 mangle space */ + return (1103515243 * value + 12345) & ~0x80000000; } /* @@ -431,7 +433,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) } /* find the '.' if any */ - dot_p = strchr(name, '.'); + dot_p = strrchr(name, '.'); /* the leading character in the mangled name is taken from the first character of the name, if it is ascii -- cgit From 41b81371697de322789e50ae25e742025ca408ca Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 14:59:27 +0000 Subject: don't try to return a void (This used to be commit 51b4de0ae3b05c4f34a645ae9c6e395bc37226e6) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 6bf60f0543..20b2b419cf 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -66,7 +66,7 @@ void mangle_reset_cache(void) { mangle_init(); - return mangle_fns->reset(); + mangle_fns->reset(); } /* -- cgit From 4023a61892278c9e09acd035166a55ff2b3d4f30 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Apr 2002 10:18:46 +0000 Subject: merged the mangling test and passdb bugfixes into SAMBA_3_0 (This used to be commit 97eb3a121d33200ee7559b2413d6252efc04ebaf) --- source3/smbd/mangle_hash2.c | 14 ++++++++++++++ source3/smbd/uid.c | 20 +++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 96ca7360b8..959a93e07b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -344,6 +344,7 @@ static BOOL check_cache(char *name) /* we found it - construct the full name */ strncpy(extension, name+9, 3); + extension[3] = 0; if (extension[0]) { M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); @@ -435,6 +436,19 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) /* find the '.' if any */ dot_p = strrchr(name, '.'); + if (dot_p) { + /* if the extension contains any illegal characters or + is too long or zero length then we treat it as part + of the prefix */ + for (i=0; i<4 && dot_p[i+1]; i++) { + if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) { + dot_p = NULL; + break; + } + } + if (i == 0 || i == 4) dot_p = NULL; + } + /* the leading character in the mangled name is taken from the first character of the name, if it is ascii otherwise '_' is used diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 864d3d6c66..ac0b535c13 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -546,9 +546,12 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) return psid; } } + + /* Make sure we report failure, (when psid == NULL) */ + become_root(); + psid = local_uid_to_sid(psid, uid); + unbecome_root(); - local_uid_to_sid(psid, uid); - DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); return psid; @@ -611,10 +614,14 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) */ if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) { + BOOL result; DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", sid_to_string(sid_str, psid) )); - return local_sid_to_uid(puid, psid, sidtype); + become_root(); + result = local_sid_to_uid(puid, psid, sidtype); + unbecome_root(); + return result; } /* @@ -634,9 +641,13 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) */ if (!winbind_sid_to_uid(puid, psid)) { + BOOL result; DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n", sid_to_string(sid_str, psid) )); - return local_sid_to_uid(puid, psid, sidtype); + become_root(); + result = local_sid_to_uid(puid, psid, sidtype); + unbecome_root(); + return result; } DEBUG(10,("sid_to_uid: winbindd %s -> %u\n", @@ -667,7 +678,6 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", sid_to_string(sid_str, psid) )); - if (!local_sid_to_gid(pgid, psid, sidtype)) { /* this was probably a foreign sid - assume its a group rid and continue */ -- cgit From 33640a748455bd77696c5e296eb62e11b7711820 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 15 Apr 2002 13:52:26 +0000 Subject: merge from SAMBA_2_2 (This used to be commit 305ff4203e7313c7869305c63290b1964ac17f2e) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ed2979b3a4..edee14513c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -467,7 +467,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn, /* See if it is one we want to handle. */ if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) - return(ERROR_DOS(ERRSRV,ERRaccess)); + return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); for( i = 0; known_nt_pipes[i]; i++ ) if( strequal(fname,known_nt_pipes[i])) -- cgit From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/smbd/build_options.c | 28 +- source3/smbd/change_trust_pw.c | 10 +- source3/smbd/chgpasswd.c | 4 + source3/smbd/conn.c | 2 +- source3/smbd/dir.c | 156 +-- source3/smbd/fileio.c | 779 ++++++------ source3/smbd/filename.c | 760 ++++++------ source3/smbd/groupname.c | 5 +- source3/smbd/ipc.c | 2 +- source3/smbd/lanman.c | 424 ++++--- source3/smbd/mangle.c | 21 +- source3/smbd/mangle_hash.c | 534 ++++---- source3/smbd/mangle_hash2.c | 110 +- source3/smbd/mangle_map.c | 4 +- source3/smbd/message.c | 10 +- source3/smbd/negprot.c | 380 +++--- source3/smbd/notify_kernel.c | 109 +- source3/smbd/nttrans.c | 568 ++++----- source3/smbd/open.c | 18 +- source3/smbd/oplock.c | 79 +- source3/smbd/oplock_irix.c | 30 +- source3/smbd/oplock_linux.c | 57 +- source3/smbd/password.c | 182 ++- source3/smbd/pipes.c | 2 +- source3/smbd/posix_acls.c | 180 ++- source3/smbd/process.c | 65 +- source3/smbd/reply.c | 93 +- source3/smbd/sec_ctx.c | 39 +- source3/smbd/server.c | 23 +- source3/smbd/service.c | 393 ++++-- source3/smbd/session.c | 52 +- source3/smbd/sesssetup.c | 88 +- source3/smbd/srvstr.c | 9 + source3/smbd/trans2.c | 2625 +++++++++++++++++++++++----------------- source3/smbd/uid.c | 15 +- source3/smbd/vfs-wrap.c | 4 +- source3/smbd/vfs.c | 8 +- 37 files changed, 4407 insertions(+), 3461 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 1d18f534b1..f52c53dda5 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -89,6 +89,12 @@ void build_options(BOOL screen) #ifdef HAVE_KRB5 output(screen," HAVE_KRB5"); #endif +#ifdef HAVE_GSSAPI + output(screen," HAVE_GSSAPI"); +#endif +#ifdef HAVE_LDAP + output(screen," HAVE_LDAP"); +#endif #ifdef WITH_AUTOMOUNT output(screen," WITH_AUTOMOUNT\n"); #endif @@ -101,9 +107,6 @@ void build_options(BOOL screen) #ifdef WITH_TDB_SAM output(screen," WITH_TDB_SAM\n"); #endif -#ifdef WITH_LDAP_SAM - output(screen," WITH_LDAP_SAM\n"); -#endif #ifdef WITH_SMBPASSWD_SAM output(screen," WITH_SMBPASSWD_SAM\n"); #endif @@ -113,12 +116,6 @@ void build_options(BOOL screen) #ifdef WITH_NISPLUS_HOME output(screen," WITH_NISPLUS_HOME\n"); #endif -#ifdef WITH_SSL - output(screen," WITH_SSL\n"); -#endif -#ifdef SSL_DIR - output(screen," SSL_DIR: %s\n",SSL_DIR); -#endif #ifdef WITH_SYSLOG output(screen," WITH_SYSLOG\n"); #endif @@ -220,8 +217,17 @@ void build_options(BOOL screen) #ifdef HAVE_CUPS_LANGUAGE_H output(screen," HAVE_CUPS_LANGUAGE_H\n"); #endif -#ifdef HAVE_LIBDL - output(screen," HAVE_LIBDL\n"); +#ifdef HAVE_DLOPEN + output(screen," HAVE_DLOPEN\n"); +#endif +#ifdef HAVE_DLCLOSE + output(screen," HAVE_DLCLOSE\n"); +#endif +#ifdef HAVE_DLSYM + output(screen," HAVE_DLSYM\n"); +#endif +#ifdef HAVE_DLERROR + output(screen," HAVE_DLERROR\n"); #endif #ifdef HAVE_UNIXSOCKET output(screen," HAVE_UNIXSOCKET\n"); diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 0d80d5718f..0c468699b4 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -35,7 +35,6 @@ static NTSTATUS modify_trust_password( char *domain, char *remote_machine, { struct cli_state *cli; DOM_SID domain_sid; - struct in_addr dest_ip; NTSTATUS nt_status; /* @@ -43,17 +42,12 @@ static NTSTATUS modify_trust_password( char *domain, char *remote_machine, */ if (!secrets_fetch_domain_sid(domain, &domain_sid)) { - DEBUG(0, ("domain_client_validate: unable to fetch domain sid.\n")); + DEBUG(0, ("modify_trust_password: unable to fetch domain sid.\n")); return NT_STATUS_UNSUCCESSFUL; } - if(!resolve_name( remote_machine, &dest_ip, 0x20)) { - DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine)); - return NT_STATUS_UNSUCCESSFUL; - } - if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname, remote_machine, - &dest_ip, 0, + NULL, 0, "IPC$", "IPC", "", "", "", 0))) { diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index eed535cf11..68871deb90 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -472,6 +472,10 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL struct passwd *pass; + if (!name) { + DEBUG(1, ("NULL username specfied to chgpasswd()!\n")); + } + DEBUG(3, ("Password change for user: %s\n", name)); #if DEBUG_PASSWORD diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index f552d4a224..c0aa447016 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -166,7 +166,7 @@ void conn_free(connection_struct *conn) if (conn->dl_handle != NULL) { /* Close dlopen() handle */ - dlclose(conn->dl_handle); + sys_dlclose(conn->dl_handle); } DLIST_REMOVE(Connections, conn); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f56e0e9ef0..7dd425ef8a 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -558,6 +558,12 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int di return True; } +static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask) +{ + mangle_map(filename,True,False,SNUM(conn)); + return mask_match(filename,mask,False); +} + /**************************************************************************** Get an 8.3 directory entry. ****************************************************************************/ @@ -603,8 +609,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, */ if ((strcmp(mask,"*.*") == 0) || mask_match(filename,mask,False) || - (mangle_map(filename,True,False,SNUM(conn)) && - mask_match(filename,mask,False))) + mangle_mask_match(conn,filename,mask)) { if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) continue; @@ -680,7 +685,15 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) ZERO_STRUCT(ste); - /* if we can't stat it does not show it */ + /* + * If user is a member of the Admin group + * we never hide files from them. + */ + + if (conn->admin_user) + return True; + + /* If we can't stat it does not show it */ if (vfs_stat(conn, name, &ste) != 0) return False; @@ -714,73 +727,80 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { - Dir *dirp; - char *n; - DIR *p = conn->vfs_ops.opendir(conn,name); - int used=0; - - if (!p) return(NULL); - dirp = (Dir *)malloc(sizeof(Dir)); - if (!dirp) { - DEBUG(0,("Out of memory in OpenDir\n")); - conn->vfs_ops.closedir(conn,p); - return(NULL); - } - dirp->pos = dirp->numentries = dirp->mallocsize = 0; - dirp->data = dirp->current = NULL; - - while (True) - { - int l; - - if (used == 0) { - n = "."; - } else if (used == 2) { - n = ".."; - } else { - n = vfs_readdirname(conn, p); - if (n == NULL) - break; - if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0)) - continue; - } - - l = strlen(n)+1; - - /* If it's a vetoed file, pretend it doesn't even exist */ - if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; - - /* Honour _hide unreadable_ option */ - if (conn && lp_hideunreadable(SNUM(conn))) { - char *entry; - int ret=0; + Dir *dirp; + char *n; + DIR *p = conn->vfs_ops.opendir(conn,name); + int used=0; + + if (!p) + return(NULL); + dirp = (Dir *)malloc(sizeof(Dir)); + if (!dirp) { + DEBUG(0,("Out of memory in OpenDir\n")); + conn->vfs_ops.closedir(conn,p); + return(NULL); + } + dirp->pos = dirp->numentries = dirp->mallocsize = 0; + dirp->data = dirp->current = NULL; + + while (True) { + int l; + BOOL normal_entry = True; + + if (used == 0) { + n = "."; + normal_entry = False; + } else if (used == 2) { + n = ".."; + normal_entry = False; + } else { + n = vfs_readdirname(conn, p); + if (n == NULL) + break; + if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0)) + continue; + normal_entry = True; + } + + l = strlen(n)+1; + + /* If it's a vetoed file, pretend it doesn't even exist */ + if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n)) + continue; + + /* Honour _hide unreadable_ option */ + if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) { + char *entry; + int ret=0; - if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = user_can_read_file(conn, entry); - SAFE_FREE(entry); - } - if (!ret) continue; - } - - if (used + l > dirp->mallocsize) { - int s = MAX(used+l,used+2000); - char *r; - r = (char *)Realloc(dirp->data,s); - if (!r) { - DEBUG(0,("Out of memory in OpenDir\n")); - break; - } - dirp->data = r; - dirp->mallocsize = s; - dirp->current = dirp->data; - } - pstrcpy(dirp->data+used,n); - used += l; - dirp->numentries++; - } + if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { + ret = user_can_read_file(conn, entry); + SAFE_FREE(entry); + } + if (!ret) + continue; + } + + if (used + l > dirp->mallocsize) { + int s = MAX(used+l,used+2000); + char *r; + r = (char *)Realloc(dirp->data,s); + if (!r) { + DEBUG(0,("Out of memory in OpenDir\n")); + break; + } + dirp->data = r; + dirp->mallocsize = s; + dirp->current = dirp->data; + } + + pstrcpy(dirp->data+used,n); + used += l; + dirp->numentries++; + } - conn->vfs_ops.closedir(conn,p); - return((void *)dirp); + conn->vfs_ops.closedir(conn,p); + return((void *)dirp); } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index addbcb0b3c..710ba396d8 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -1,7 +1,9 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. read/write to a files_struct Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2000-2002. - write cache. 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 @@ -23,31 +25,32 @@ static BOOL setup_write_cache(files_struct *, SMB_OFF_T); /**************************************************************************** -seek a file. Try to avoid the seek if possible + Seek a file. Try to avoid the seek if possible. ****************************************************************************/ -SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) +static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { - SMB_OFF_T offset = 0; - SMB_OFF_T seek_ret; + SMB_OFF_T offset = 0; + SMB_OFF_T seek_ret; - if (fsp->print_file && lp_postscript(fsp->conn->service)) - offset = 3; + if (fsp->print_file && lp_postscript(fsp->conn->service)) + offset = 3; - seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos+offset,SEEK_SET); + seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos+offset,SEEK_SET); - if(seek_ret == -1) { - DEBUG(0,("seek_file: sys_lseek failed. Error was %s\n", strerror(errno) )); - fsp->pos = -1; - return -1; - } + if(seek_ret == -1) { + DEBUG(0,("seek_file: (%s) sys_lseek failed. Error was %s\n", + fsp->fsp_name, strerror(errno) )); + fsp->pos = -1; + return -1; + } - fsp->pos = seek_ret - offset; + fsp->pos = seek_ret - offset; - DEBUG(10,("seek_file: requested pos = %.0f, new pos = %.0f\n", - (double)(pos+offset), (double)fsp->pos )); + DEBUG(10,("seek_file (%s): requested pos = %.0f, new pos = %.0f\n", + fsp->fsp_name, (double)(pos+offset), (double)fsp->pos )); - return(fsp->pos); + return(fsp->pos); } /**************************************************************************** @@ -55,25 +58,25 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) ****************************************************************************/ -BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) +static BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { - write_cache *wcp = fsp->wcp; + write_cache *wcp = fsp->wcp; - if(!wcp) - return False; + if(!wcp) + return False; - if(n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size) - return False; + if(n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size) + return False; - memcpy(data, wcp->data + (pos - wcp->offset), n); + memcpy(data, wcp->data + (pos - wcp->offset), n); - DO_PROFILE_INC(writecache_read_hits); + DO_PROFILE_INC(writecache_read_hits); - return True; + return True; } /**************************************************************************** -read from a file + Read from a file. ****************************************************************************/ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) @@ -121,6 +124,9 @@ tryagain: ret += readret; } + DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", + fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); + return(ret); } @@ -133,10 +139,17 @@ static unsigned int allocated_write_caches; static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_t n) { - if ((pos != -1) && (seek_file(fsp,pos) == -1)) - return -1; + ssize_t ret; + + if ((pos != -1) && (seek_file(fsp,pos) == -1)) + return -1; + + ret = vfs_write_data(fsp,data,n); + + DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", + fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); - return vfs_write_data(fsp,data,n); + return ret; } /**************************************************************************** @@ -145,367 +158,365 @@ write to a file ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) { - write_cache *wcp = fsp->wcp; - ssize_t total_written = 0; - int write_path = -1; - - if (fsp->print_file) { - return print_job_write(fsp->print_jobid, data, n); - } - - if (!fsp->can_write) { - errno = EPERM; - return(0); - } - - if (!fsp->modified) { - SMB_STRUCT_STAT st; - fsp->modified = True; - - if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { - int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); - fsp->size = st.st_size; - if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { - file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); - } - - /* - * If this is the first write and we have an exclusive oplock then setup - * the write cache. - */ - - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { - setup_write_cache(fsp, st.st_size); - wcp = fsp->wcp; - } - } - } + write_cache *wcp = fsp->wcp; + ssize_t total_written = 0; + int write_path = -1; + + if (fsp->print_file) + return print_job_write(fsp->print_jobid, data, n); + + if (!fsp->can_write) { + errno = EPERM; + return(0); + } + + if (!fsp->modified) { + SMB_STRUCT_STAT st; + fsp->modified = True; + + if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { + int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); + fsp->size = st.st_size; + if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) + file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); + + /* + * If this is the first write and we have an exclusive oplock then setup + * the write cache. + */ + + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { + setup_write_cache(fsp, st.st_size); + wcp = fsp->wcp; + } + } + } #ifdef WITH_PROFILE - DO_PROFILE_INC(writecache_total_writes); - if (!fsp->oplock_type) { - DO_PROFILE_INC(writecache_non_oplock_writes); - } + DO_PROFILE_INC(writecache_total_writes); + if (!fsp->oplock_type) { + DO_PROFILE_INC(writecache_non_oplock_writes); + } #endif - /* - * If this file is level II oplocked then we need - * to grab the shared memory lock and inform all - * other files with a level II lock that they need - * to flush their read caches. We keep the lock over - * the shared memory area whilst doing this. - */ + /* + * If this file is level II oplocked then we need + * to grab the shared memory lock and inform all + * other files with a level II lock that they need + * to flush their read caches. We keep the lock over + * the shared memory area whilst doing this. + */ - release_level_2_oplocks_on_change(fsp); + release_level_2_oplocks_on_change(fsp); #ifdef WITH_PROFILE - if (profile_p && profile_p->writecache_total_writes % 500 == 0) { - DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \ + if (profile_p && profile_p->writecache_total_writes % 500 == 0) { + DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", - profile_p->writecache_init_writes, - profile_p->writecache_abutted_writes, - profile_p->writecache_total_writes, - profile_p->writecache_non_oplock_writes, - profile_p->writecache_allocated_write_caches, - profile_p->writecache_num_write_caches, - profile_p->writecache_direct_writes, - profile_p->writecache_num_perfect_writes, - profile_p->writecache_read_hits )); - - DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", - profile_p->writecache_flushed_writes[SEEK_FLUSH], - profile_p->writecache_flushed_writes[READ_FLUSH], - profile_p->writecache_flushed_writes[WRITE_FLUSH], - profile_p->writecache_flushed_writes[READRAW_FLUSH], - profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH], - profile_p->writecache_flushed_writes[CLOSE_FLUSH], - profile_p->writecache_flushed_writes[SYNC_FLUSH] )); - } + profile_p->writecache_init_writes, + profile_p->writecache_abutted_writes, + profile_p->writecache_total_writes, + profile_p->writecache_non_oplock_writes, + profile_p->writecache_allocated_write_caches, + profile_p->writecache_num_write_caches, + profile_p->writecache_direct_writes, + profile_p->writecache_num_perfect_writes, + profile_p->writecache_read_hits )); + + DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", + profile_p->writecache_flushed_writes[SEEK_FLUSH], + profile_p->writecache_flushed_writes[READ_FLUSH], + profile_p->writecache_flushed_writes[WRITE_FLUSH], + profile_p->writecache_flushed_writes[READRAW_FLUSH], + profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH], + profile_p->writecache_flushed_writes[CLOSE_FLUSH], + profile_p->writecache_flushed_writes[SYNC_FLUSH] )); + } #endif - if(!wcp) { - DO_PROFILE_INC(writecache_direct_writes); - total_written = real_write_file(fsp, data, pos, n); - if ((total_written != -1) && (pos + total_written > fsp->size)) - fsp->size = pos + total_written; - return total_written; - } + if(!wcp) { + DO_PROFILE_INC(writecache_direct_writes); + total_written = real_write_file(fsp, data, pos, n); + if ((total_written != -1) && (pos + total_written > fsp->size)) + fsp->size = pos + total_written; + return total_written; + } - DEBUG(9,("write_file(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", - fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); + DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", + fsp->fsp_name, fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); - /* - * If we have active cache and it isn't contiguous then we flush. - * NOTE: There is a small problem with running out of disk .... - */ + /* + * If we have active cache and it isn't contiguous then we flush. + * NOTE: There is a small problem with running out of disk .... + */ - if (wcp->data_size) { + if (wcp->data_size) { - BOOL cache_flush_needed = False; + BOOL cache_flush_needed = False; - if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) { + if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) { - /* - * Start of write overlaps or abutts the existing data. - */ + /* + * Start of write overlaps or abutts the existing data. + */ - size_t data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), n); + size_t data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), n); - memcpy(wcp->data + (pos - wcp->offset), data, data_used); + memcpy(wcp->data + (pos - wcp->offset), data, data_used); - /* - * Update the current buffer size with the new data. - */ + /* + * Update the current buffer size with the new data. + */ - if(pos + data_used > wcp->offset + wcp->data_size) - wcp->data_size = pos + data_used - wcp->offset; + if(pos + data_used > wcp->offset + wcp->data_size) + wcp->data_size = pos + data_used - wcp->offset; - /* - * Update the file size if changed. - */ + /* + * Update the file size if changed. + */ - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; - /* - * If we used all the data then - * return here. - */ + /* + * If we used all the data then + * return here. + */ - if(n == data_used) - return n; - else - cache_flush_needed = True; + if(n == data_used) + return n; + else + cache_flush_needed = True; - /* - * Move the start of data forward by the amount used, - * cut down the amount left by the same amount. - */ + /* + * Move the start of data forward by the amount used, + * cut down the amount left by the same amount. + */ - data += data_used; - pos += data_used; - n -= data_used; + data += data_used; + pos += data_used; + n -= data_used; - DO_PROFILE_INC(writecache_abutted_writes); - total_written = data_used; + DO_PROFILE_INC(writecache_abutted_writes); + total_written = data_used; - write_path = 1; + write_path = 1; - } else if ((pos < wcp->offset) && (pos + n > wcp->offset) && - (pos + n <= wcp->offset + wcp->alloc_size)) { + } else if ((pos < wcp->offset) && (pos + n > wcp->offset) && + (pos + n <= wcp->offset + wcp->alloc_size)) { - /* - * End of write overlaps the existing data. - */ + /* + * End of write overlaps the existing data. + */ - size_t data_used = pos + n - wcp->offset; + size_t data_used = pos + n - wcp->offset; - memcpy(wcp->data, data + n - data_used, data_used); + memcpy(wcp->data, data + n - data_used, data_used); - /* - * Update the current buffer size with the new data. - */ + /* + * Update the current buffer size with the new data. + */ - if(pos + n > wcp->offset + wcp->data_size) - wcp->data_size = pos + n - wcp->offset; + if(pos + n > wcp->offset + wcp->data_size) + wcp->data_size = pos + n - wcp->offset; - /* - * Update the file size if changed. - */ + /* + * Update the file size if changed. + */ - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; - /* - * We don't need to move the start of data, but we - * cut down the amount left by the amount used. - */ + /* + * We don't need to move the start of data, but we + * cut down the amount left by the amount used. + */ - n -= data_used; + n -= data_used; - /* - * We cannot have used all the data here. - */ + /* + * We cannot have used all the data here. + */ - cache_flush_needed = True; + cache_flush_needed = True; - DO_PROFILE_INC(writecache_abutted_writes); - total_written = data_used; + DO_PROFILE_INC(writecache_abutted_writes); + total_written = data_used; - write_path = 2; + write_path = 2; - } else if ( (pos >= wcp->file_size) && - (wcp->offset + wcp->data_size == wcp->file_size) && - (pos > wcp->offset + wcp->data_size) && - (pos < wcp->offset + wcp->alloc_size) ) { + } else if ( (pos >= wcp->file_size) && + (wcp->offset + wcp->data_size == wcp->file_size) && + (pos > wcp->offset + wcp->data_size) && + (pos < wcp->offset + wcp->alloc_size) ) { - /* - * Non-contiguous write part of which fits within - * the cache buffer and is extending the file - * and the cache contents reflect the current - * data up to the current end of the file. - */ + /* + * Non-contiguous write part of which fits within + * the cache buffer and is extending the file + * and the cache contents reflect the current + * data up to the current end of the file. + */ - size_t data_used; + size_t data_used; - if(pos + n <= wcp->offset + wcp->alloc_size) - data_used = n; - else - data_used = wcp->offset + wcp->alloc_size - pos; + if(pos + n <= wcp->offset + wcp->alloc_size) + data_used = n; + else + data_used = wcp->offset + wcp->alloc_size - pos; - /* - * Fill in the non-continuous area with zeros. - */ + /* + * Fill in the non-continuous area with zeros. + */ - memset(wcp->data + wcp->data_size, '\0', - pos - (wcp->offset + wcp->data_size) ); + memset(wcp->data + wcp->data_size, '\0', + pos - (wcp->offset + wcp->data_size) ); - memcpy(wcp->data + (pos - wcp->offset), data, data_used); + memcpy(wcp->data + (pos - wcp->offset), data, data_used); - /* - * Update the current buffer size with the new data. - */ + /* + * Update the current buffer size with the new data. + */ - if(pos + data_used > wcp->offset + wcp->data_size) - wcp->data_size = pos + data_used - wcp->offset; + if(pos + data_used > wcp->offset + wcp->data_size) + wcp->data_size = pos + data_used - wcp->offset; - /* - * Update the file size if changed. - */ + /* + * Update the file size if changed. + */ - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; - /* - * If we used all the data then - * return here. - */ + /* + * If we used all the data then + * return here. + */ - if(n == data_used) - return n; - else - cache_flush_needed = True; + if(n == data_used) + return n; + else + cache_flush_needed = True; - /* - * Move the start of data forward by the amount used, - * cut down the amount left by the same amount. - */ + /* + * Move the start of data forward by the amount used, + * cut down the amount left by the same amount. + */ - data += data_used; - pos += data_used; - n -= data_used; + data += data_used; + pos += data_used; + n -= data_used; - DO_PROFILE_INC(writecache_abutted_writes); - total_written = data_used; + DO_PROFILE_INC(writecache_abutted_writes); + total_written = data_used; - write_path = 3; + write_path = 3; - } else { + } else { - /* - * Write is bigger than buffer, or there is no overlap on the - * low or high ends. - */ + /* + * Write is bigger than buffer, or there is no overlap on the + * low or high ends. + */ - DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \ + DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); - /* - * Update the file size if needed. - */ + /* + * Update the file size if needed. + */ - if(pos + n > wcp->file_size) - fsp->size = wcp->file_size = pos + n; + if(pos + n > wcp->file_size) + fsp->size = wcp->file_size = pos + n; - /* - * If write would fit in the cache, and is larger than - * the data already in the cache, flush the cache and - * preferentially copy the data new data into it. Otherwise - * just write the data directly. - */ + /* + * If write would fit in the cache, and is larger than + * the data already in the cache, flush the cache and + * preferentially copy the data new data into it. Otherwise + * just write the data directly. + */ - if ( n <= wcp->alloc_size && n > wcp->data_size) { - cache_flush_needed = True; - } else { - ssize_t ret = real_write_file(fsp, data, pos, n); + if ( n <= wcp->alloc_size && n > wcp->data_size) { + cache_flush_needed = True; + } else { + ssize_t ret = real_write_file(fsp, data, pos, n); - DO_PROFILE_INC(writecache_direct_writes); - if (ret == -1) - return ret; + DO_PROFILE_INC(writecache_direct_writes); + if (ret == -1) + return ret; - if (pos + ret > wcp->file_size) - fsp->size = wcp->file_size = pos + ret; + if (pos + ret > wcp->file_size) + fsp->size = wcp->file_size = pos + ret; - return ret; - } + return ret; + } - write_path = 4; + write_path = 4; - } + } - if(wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->data_size; + if(wcp->data_size > wcp->file_size) + fsp->size = wcp->file_size = wcp->data_size; - if (cache_flush_needed) { - DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ + if (cache_flush_needed) { + DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", - write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, - (double)wcp->offset, (unsigned int)wcp->data_size )); + write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, + (double)wcp->offset, (unsigned int)wcp->data_size )); - flush_write_cache(fsp, WRITE_FLUSH); - } - } + flush_write_cache(fsp, WRITE_FLUSH); + } + } - /* - * If the write request is bigger than the cache - * size, write it all out. - */ + /* + * If the write request is bigger than the cache + * size, write it all out. + */ - if (n > wcp->alloc_size ) { - ssize_t ret = real_write_file(fsp, data, pos, n); - if (ret == -1) - return -1; + if (n > wcp->alloc_size ) { + ssize_t ret = real_write_file(fsp, data, pos, n); + if (ret == -1) + return -1; - if (pos + ret > wcp->file_size) - fsp->size = wcp->file_size = pos + n; + if (pos + ret > wcp->file_size) + fsp->size = wcp->file_size = pos + n; - DO_PROFILE_INC(writecache_direct_writes); - return total_written + n; - } + DO_PROFILE_INC(writecache_direct_writes); + return total_written + n; + } - /* - * If there's any data left, cache it. - */ + /* + * If there's any data left, cache it. + */ - if (n) { + if (n) { #ifdef WITH_PROFILE - if (wcp->data_size) { - DO_PROFILE_INC(writecache_abutted_writes); - } else { - DO_PROFILE_INC(writecache_init_writes); - } + if (wcp->data_size) { + DO_PROFILE_INC(writecache_abutted_writes); + } else { + DO_PROFILE_INC(writecache_init_writes); + } #endif - memcpy(wcp->data+wcp->data_size, data, n); - if (wcp->data_size == 0) { - wcp->offset = pos; - DO_PROFILE_INC(writecache_num_write_caches); - } - wcp->data_size += n; - - /* - * Update the file size if changed. - */ - - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; - DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n", - (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n)); - - total_written += n; - return total_written; /* .... that's a write :) */ - } + memcpy(wcp->data+wcp->data_size, data, n); + if (wcp->data_size == 0) { + wcp->offset = pos; + DO_PROFILE_INC(writecache_num_write_caches); + } + wcp->data_size += n; + + /* + * Update the file size if changed. + */ + + if (wcp->offset + wcp->data_size > wcp->file_size) + fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n", + (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n)); + + total_written += n; + return total_written; /* .... that's a write :) */ + } - return total_written; + return total_written; } /**************************************************************************** @@ -514,24 +525,23 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", void delete_write_cache(files_struct *fsp) { - write_cache *wcp; - - if(!fsp) - return; + write_cache *wcp; - if(!(wcp = fsp->wcp)) - return; + if(!fsp) + return; - DO_PROFILE_DEC(writecache_allocated_write_caches); - allocated_write_caches--; + if(!(wcp = fsp->wcp)) + return; - SMB_ASSERT(wcp->data_size == 0); + DO_PROFILE_DEC(writecache_allocated_write_caches); + allocated_write_caches--; - SAFE_FREE(wcp->data); - SAFE_FREE(fsp->wcp); + SMB_ASSERT(wcp->data_size == 0); - DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name )); + SAFE_FREE(wcp->data); + SAFE_FREE(fsp->wcp); + DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name )); } /**************************************************************************** @@ -540,41 +550,41 @@ void delete_write_cache(files_struct *fsp) static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) { - ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); - write_cache *wcp; - - if (allocated_write_caches >= MAX_WRITE_CACHES) - return False; - - if(alloc_size == 0 || fsp->wcp) - return False; - - if((wcp = (write_cache *)malloc(sizeof(write_cache))) == NULL) { - DEBUG(0,("setup_write_cache: malloc fail.\n")); - return False; - } - - wcp->file_size = file_size; - wcp->offset = 0; - wcp->alloc_size = alloc_size; - wcp->data_size = 0; - if((wcp->data = malloc(wcp->alloc_size)) == NULL) { - DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", - (unsigned int)wcp->alloc_size )); - SAFE_FREE(wcp); - return False; - } - - memset(wcp->data, '\0', wcp->alloc_size ); - - fsp->wcp = wcp; - DO_PROFILE_INC(writecache_allocated_write_caches); - allocated_write_caches++; - - DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n", + ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); + write_cache *wcp; + + if (allocated_write_caches >= MAX_WRITE_CACHES) + return False; + + if(alloc_size == 0 || fsp->wcp) + return False; + + if((wcp = (write_cache *)malloc(sizeof(write_cache))) == NULL) { + DEBUG(0,("setup_write_cache: malloc fail.\n")); + return False; + } + + wcp->file_size = file_size; + wcp->offset = 0; + wcp->alloc_size = alloc_size; + wcp->data_size = 0; + if((wcp->data = malloc(wcp->alloc_size)) == NULL) { + DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", + (unsigned int)wcp->alloc_size )); + SAFE_FREE(wcp); + return False; + } + + memset(wcp->data, '\0', wcp->alloc_size ); + + fsp->wcp = wcp; + DO_PROFILE_INC(writecache_allocated_write_caches); + allocated_write_caches++; + + DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n", fsp->fsp_name, wcp->alloc_size )); - return True; + return True; } /**************************************************************************** @@ -583,17 +593,17 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) { - fsp->size = file_size; - if(fsp->wcp) { - /* The cache *must* have been flushed before we do this. */ - if (fsp->wcp->data_size != 0) { - pstring msg; - slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \ + fsp->size = file_size; + if(fsp->wcp) { + /* The cache *must* have been flushed before we do this. */ + if (fsp->wcp->data_size != 0) { + pstring msg; + slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \ on file %s with write cache size = %u\n", fsp->fsp_name, fsp->wcp->data_size ); - smb_panic(msg); - } - fsp->wcp->file_size = file_size; - } + smb_panic(msg); + } + fsp->wcp->file_size = file_size; + } } /******************************************************************* @@ -602,36 +612,36 @@ on file %s with write cache size = %u\n", fsp->fsp_name, fsp->wcp->data_size ); ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) { - write_cache *wcp = fsp->wcp; - size_t data_size; - ssize_t ret; + write_cache *wcp = fsp->wcp; + size_t data_size; + ssize_t ret; - if(!wcp || !wcp->data_size) - return 0; + if(!wcp || !wcp->data_size) + return 0; - data_size = wcp->data_size; - wcp->data_size = 0; + data_size = wcp->data_size; + wcp->data_size = 0; - DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]); + DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]); - DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", - fsp->fd, (double)wcp->offset, (unsigned int)data_size)); + DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", + fsp->fd, (double)wcp->offset, (unsigned int)data_size)); #ifdef WITH_PROFILE - if(data_size == wcp->alloc_size) - DO_PROFILE_INC(writecache_num_perfect_writes); + if(data_size == wcp->alloc_size) + DO_PROFILE_INC(writecache_num_perfect_writes); #endif - ret = real_write_file(fsp, wcp->data, wcp->offset, data_size); + ret = real_write_file(fsp, wcp->data, wcp->offset, data_size); - /* - * Ensure file size if kept up to date if write extends file. - */ + /* + * Ensure file size if kept up to date if write extends file. + */ - if ((ret != -1) && (wcp->offset + ret > wcp->file_size)) - wcp->file_size = wcp->offset + ret; + if ((ret != -1) && (wcp->offset + ret > wcp->file_size)) + wcp->file_size = wcp->offset + ret; - return ret; + return ret; } /******************************************************************* @@ -640,12 +650,13 @@ sync a file void sync_file(connection_struct *conn, files_struct *fsp) { - if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { - flush_write_cache(fsp, SYNC_FLUSH); - conn->vfs_ops.fsync(fsp,fsp->fd); - } + if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { + flush_write_cache(fsp, SYNC_FLUSH); + conn->vfs_ops.fsync(fsp,fsp->fd); + } } + /************************************************************ Perform a stat whether a valid fd or not. ************************************************************/ diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index cb6a6d31a4..e5f9b7a0ae 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -38,54 +38,29 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d Check if two filenames are equal. This needs to be careful about whether we are case sensitive. ****************************************************************************/ + static BOOL fname_equal(char *name1, char *name2) { - int l1 = strlen(name1); - int l2 = strlen(name2); - - /* handle filenames ending in a single dot */ - if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name1[l1-1] = 0; - ret = fname_equal(name1,name2); - name1[l1-1] = '.'; - return(ret); - } - - if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name2[l2-1] = 0; - ret = fname_equal(name1,name2); - name2[l2-1] = '.'; - return(ret); - } - - /* now normal filename handling */ - if (case_sensitive) - return(strcmp(name1,name2) == 0); - - return(strequal(name1,name2)); -} + /* Normal filename handling */ + if (case_sensitive) + return(strcmp(name1,name2) == 0); + return(strequal(name1,name2)); +} /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(char *name1, char *name2, int snum) + +static BOOL mangled_equal(char *name1, const char *name2, int snum) { pstring tmpname; - if (mangle_is_8_3(name2, True)) { - return False; - } pstrcpy(tmpname, name2); - return mangle_map(tmpname, True, False, snum) && - strequal(name1, tmpname); + mangle_map(tmpname, True, False, snum); + return strequal(name1, tmpname); } - /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -116,388 +91,391 @@ for nlinks = 0, which can never be true for any file). BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst) { - SMB_STRUCT_STAT st; - char *start, *end; - pstring dirpath; - pstring orig_path; - BOOL component_was_mangled = False; - BOOL name_has_wildcard = False; - - ZERO_STRUCTP(pst); - - *dirpath = 0; - *bad_path = False; - if(saved_last_component) - *saved_last_component = 0; - - if (conn->printer) { - /* we don't ever use the filenames on a printer share as a - filename - so don't convert them */ - return True; - } - - DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); - - /* - * Convert to basic unix format - removing \ chars and cleaning it up. - */ - - unix_format(name); - unix_clean_name(name); - - /* - * Names must be relative to the root of the service - trim any leading /. - * also trim trailing /'s. - */ - - trim_string(name,"/","/"); - - /* - * If we trimmed down to a single '\0' character - * then we should use the "." directory to avoid - * searching the cache, but not if we are in a - * printing share. - */ - - if (!*name) { - name[0] = '.'; - name[1] = '\0'; - } - - /* - * Ensure saved_last_component is valid even if file exists. - */ - - if(saved_last_component) { - end = strrchr_m(name, '/'); - if(end) - pstrcpy(saved_last_component, end + 1); - else - pstrcpy(saved_last_component, name); - } - - if (!case_sensitive && - (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) - strnorm(name); - - /* - * If we trimmed down to a single '\0' character - * then we will be using the "." directory. - * As we know this is valid we can return true here. - */ - - if(!*name) - return(True); - - start = name; - while (strncmp(start,"./",2) == 0) - start += 2; - - pstrcpy(orig_path, name); - - if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { - *pst = st; - return True; - } - - /* - * stat the name - if it exists then we are all done! - */ - -/* ZZZ: stat1 */ if (vfs_stat(conn,name,&st) == 0) { - stat_cache_add(orig_path, name); - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - *pst = st; - return(True); - } - - DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", - name, dirpath, start)); - - /* - * A special case - if we don't have any mangling chars and are case - * sensitive then searching won't help. - */ - - if (case_sensitive && !mangle_is_mangled(name) && - !lp_strip_dot() && !use_mangled_map) - return(False); - - name_has_wildcard = ms_has_wild(start); - - /* - * is_mangled() was changed to look at an entire pathname, not - * just a component. JRA. - */ - - if (mangle_is_mangled(start)) - component_was_mangled = True; - - /* - * Now we need to recursively match the name against the real - * directory structure. - */ - - /* - * Match each part of the path name separately, trying the names - * as is first, then trying to scan the directory for matching names. - */ - - for (; start ; start = (end?end+1:(char *)NULL)) { - /* - * Pinpoint the end of this section of the filename. - */ - end = strchr_m(start, '/'); - - /* - * Chop the name at this point. - */ - if (end) - *end = 0; - - if(saved_last_component != 0) - pstrcpy(saved_last_component, end ? end + 1 : start); - - /* - * Check if the name exists up to this point. - */ - - if (vfs_stat(conn,name, &st) == 0) { - /* - * It exists. it must either be a directory or this must be - * the last part of the path for it to be OK. - */ - if (end && !(st.st_mode & S_IFDIR)) { - /* - * An intermediate part of the name isn't a directory. - */ - DEBUG(5,("Not a dir %s\n",start)); - *end = '/'; - return(False); - } - - } else { - pstring rest; - - /* Stat failed - ensure we don't use it. */ - ZERO_STRUCT(st); - *rest = 0; - - /* - * Remember the rest of the pathname so it can be restored - * later. - */ - - if (end) - pstrcpy(rest,end+1); - - /* - * Try to find this part of the path in the directory. - */ - - if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { - if (end) { - /* - * An intermediate part of the name can't be found. - */ - DEBUG(5,("Intermediate not found %s\n",start)); - *end = '/'; - - /* - * We need to return the fact that the intermediate - * name resolution failed. This is used to return an - * error of ERRbadpath rather than ERRbadfile. Some - * Windows applications depend on the difference between - * these two errors. - */ - *bad_path = True; - return(False); - } + SMB_STRUCT_STAT st; + char *start, *end; + pstring dirpath; + pstring orig_path; + BOOL component_was_mangled = False; + BOOL name_has_wildcard = False; + + ZERO_STRUCTP(pst); + + *dirpath = 0; + *bad_path = False; + if(saved_last_component) + *saved_last_component = 0; + + if (conn->printer) { + /* we don't ever use the filenames on a printer share as a + filename - so don't convert them */ + return True; + } + + DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); + + /* + * Convert to basic unix format - removing \ chars and cleaning it up. + */ + + unix_format(name); + unix_clean_name(name); + + /* + * Names must be relative to the root of the service - trim any leading /. + * also trim trailing /'s. + */ + + trim_string(name,"/","/"); + + /* + * If we trimmed down to a single '\0' character + * then we should use the "." directory to avoid + * searching the cache, but not if we are in a + * printing share. + */ + + if (!*name) { + name[0] = '.'; + name[1] = '\0'; + } + + /* + * Ensure saved_last_component is valid even if file exists. + */ + + if(saved_last_component) { + end = strrchr_m(name, '/'); + if(end) + pstrcpy(saved_last_component, end + 1); + else + pstrcpy(saved_last_component, name); + } + + if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) + strnorm(name); + + /* + * If we trimmed down to a single '\0' character + * then we will be using the "." directory. + * As we know this is valid we can return true here. + */ + + if(!*name) + return(True); + + start = name; + while (strncmp(start,"./",2) == 0) + start += 2; + + pstrcpy(orig_path, name); + + if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { + *pst = st; + return True; + } + + /* + * stat the name - if it exists then we are all done! + */ + + if (vfs_stat(conn,name,&st) == 0) { + stat_cache_add(orig_path, name); + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + *pst = st; + return(True); + } + + DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); + + /* + * A special case - if we don't have any mangling chars and are case + * sensitive then searching won't help. + */ + + if (case_sensitive && !mangle_is_mangled(name) && !use_mangled_map) + return(False); + + name_has_wildcard = ms_has_wild(start); + + /* + * is_mangled() was changed to look at an entire pathname, not + * just a component. JRA. + */ + + if (mangle_is_mangled(start)) + component_was_mangled = True; + + /* + * Now we need to recursively match the name against the real + * directory structure. + */ + + /* + * Match each part of the path name separately, trying the names + * as is first, then trying to scan the directory for matching names. + */ + + for (; start ; start = (end?end+1:(char *)NULL)) { + /* + * Pinpoint the end of this section of the filename. + */ + end = strchr_m(start, '/'); + + /* + * Chop the name at this point. + */ + if (end) + *end = 0; + + if(saved_last_component != 0) + pstrcpy(saved_last_component, end ? end + 1 : start); + + /* + * Check if the name exists up to this point. + */ + + if (vfs_stat(conn,name, &st) == 0) { + /* + * It exists. it must either be a directory or this must be + * the last part of the path for it to be OK. + */ + if (end && !(st.st_mode & S_IFDIR)) { + /* + * An intermediate part of the name isn't a directory. + */ + DEBUG(5,("Not a dir %s\n",start)); + *end = '/'; + return(False); + } + + } else { + pstring rest; + + /* Stat failed - ensure we don't use it. */ + ZERO_STRUCT(st); + *rest = 0; + + /* + * Remember the rest of the pathname so it can be restored + * later. + */ + + if (end) + pstrcpy(rest,end+1); + + /* + * Try to find this part of the path in the directory. + */ + + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { + if (end) { + /* + * An intermediate part of the name can't be found. + */ + DEBUG(5,("Intermediate not found %s\n",start)); + *end = '/'; + + /* + * We need to return the fact that the intermediate + * name resolution failed. This is used to return an + * error of ERRbadpath rather than ERRbadfile. Some + * Windows applications depend on the difference between + * these two errors. + */ + *bad_path = True; + return(False); + } - /* - * Just the last part of the name doesn't exist. - * We may need to strupper() or strlower() it in case - * this conversion is being used for file creation - * purposes. If the filename is of mixed case then - * don't normalise it. - */ - - if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) - strnorm(start); - - /* - * check on the mangled stack to see if we can recover the - * base of the filename. - */ - - if (mangle_is_mangled(start)) { - mangle_check_cache( start ); - } - - DEBUG(5,("New file %s\n",start)); - return(True); - } - - /* - * Restore the rest of the string. If the string was mangled the size - * may have changed. - */ - if (end) { - end = start + strlen(start); - pstrcat(start,"/"); - pstrcat(start,rest); - *end = '\0'; - } - } /* end else */ - - /* - * Add to the dirpath that we have resolved so far. - */ - if (*dirpath) - pstrcat(dirpath,"/"); - - pstrcat(dirpath,start); - - /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. - */ - - if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, dirpath); - - /* - * Restore the / that we wiped out earlier. - */ - if (end) - *end = '/'; - } + /* + * Just the last part of the name doesn't exist. + * We may need to strupper() or strlower() it in case + * this conversion is being used for file creation + * purposes. If the filename is of mixed case then + * don't normalise it. + */ + + if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) + strnorm(start); + + /* + * check on the mangled stack to see if we can recover the + * base of the filename. + */ + + if (mangle_is_mangled(start)) { + mangle_check_cache( start ); + } + + DEBUG(5,("New file %s\n",start)); + return(True); + } + + /* + * Restore the rest of the string. If the string was mangled the size + * may have changed. + */ + if (end) { + end = start + strlen(start); + pstrcat(start,"/"); + pstrcat(start,rest); + *end = '\0'; + } + } /* end else */ + + /* + * Add to the dirpath that we have resolved so far. + */ + if (*dirpath) + pstrcat(dirpath,"/"); + + pstrcat(dirpath,start); + + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ + + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, dirpath); + + /* + * Restore the / that we wiped out earlier. + */ + if (end) + *end = '/'; + } - /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. - */ + /* + * Don't cache a name with mangled or wildcard components + * as this can change the size. + */ - if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, name); + if(!component_was_mangled && !name_has_wildcard) + stat_cache_add(orig_path, name); - /* - * If we ended up resolving the entire path then return a valid - * stat struct if we got one. - */ + /* + * If we ended up resolving the entire path then return a valid + * stat struct if we got one. + */ - if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) - *pst = st; + if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) + *pst = st; - /* - * The name has been resolved. - */ + /* + * The name has been resolved. + */ - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - return(True); + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + return(True); } - /**************************************************************************** -check a filename - possibly caling reducename - -This is called by every routine before it allows an operation on a filename. -It does any final confirmation necessary to ensure that the filename is -a valid one for the user to access. + Check a filename - possibly caling reducename. + This is called by every routine before it allows an operation on a filename. + It does any final confirmation necessary to ensure that the filename is + a valid one for the user to access. ****************************************************************************/ + BOOL check_name(char *name,connection_struct *conn) { - BOOL ret; + BOOL ret; - errno = 0; + errno = 0; - if (IS_VETO_PATH(conn, name)) { - DEBUG(5,("file path name %s vetoed\n",name)); - return(0); - } + if (IS_VETO_PATH(conn, name)) { + if(strcmp(name, ".") && strcmp(name, "..")) { + DEBUG(5,("file path name %s vetoed\n",name)); + return(0); + } + } - ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); + ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); - /* Check if we are allowing users to follow symlinks */ - /* Patch from David Clerc - University of Geneva */ + /* Check if we are allowing users to follow symlinks */ + /* Patch from David Clerc + University of Geneva */ #ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) { - SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) { - DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - ret=0; - } - } + if (!lp_symlinks(SNUM(conn))) { + SMB_STRUCT_STAT statbuf; + if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && + (S_ISLNK(statbuf.st_mode)) ) { + DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); + ret=0; + } + } #endif - if (!ret) - DEBUG(5,("check_name on %s failed\n",name)); + if (!ret) + DEBUG(5,("check_name on %s failed\n",name)); - return(ret); + return(ret); } - /**************************************************************************** -scan a directory to find a filename, matching without case sensitivity - -If the name looks like a mangled name then try via the mangling functions + Scan a directory to find a filename, matching without case sensitivity. + If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ + static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) { - void *cur_dir; - char *dname; - BOOL mangled; - pstring name2; - - mangled = mangle_is_mangled(name); - - /* handle null paths */ - if (*path == 0) - path = "."; - - if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { - pstrcpy(name, dname); - return(True); - } - - /* - * The incoming name can be mangled, and if we de-mangle it - * here it will not compare correctly against the filename (name2) - * read from the directory and then mangled by the mangle_map() - * call. We need to mangle both names or neither. - * (JRA). - */ - if (mangled) - mangled = !mangle_check_cache( name ); - - /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) { - DEBUG(3,("scan dir didn't open dir [%s]\n",path)); - return(False); - } - - /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) { - if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) - continue; - - pstrcpy(name2,dname); - if (!mangle_map(name2,False,True,SNUM(conn))) - continue; - - if ((mangled && mangled_equal(name,name2,SNUM(conn))) || fname_equal(name, dname)) { - /* we've found the file, change it's name and return */ - if (docache) - DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); - CloseDir(cur_dir); - return(True); - } - } - - CloseDir(cur_dir); - return(False); + void *cur_dir; + char *dname; + BOOL mangled; + + mangled = mangle_is_mangled(name); + + /* handle null paths */ + if (*path == 0) + path = "."; + + if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { + pstrcpy(name, dname); + return(True); + } + + /* + * The incoming name can be mangled, and if we de-mangle it + * here it will not compare correctly against the filename (name2) + * read from the directory and then mangled by the mangle_map() + * call. We need to mangle both names or neither. + * (JRA). + */ + if (mangled) + mangled = !mangle_check_cache( name ); + + /* open the directory */ + if (!(cur_dir = OpenDir(conn, path, True))) { + DEBUG(3,("scan dir didn't open dir [%s]\n",path)); + return(False); + } + + /* now scan for matching names */ + while ((dname = ReadDirName(cur_dir))) { + if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) + continue; + + /* + * At this point dname is the unmangled name. + * name is either mangled or not, depending on the state of the "mangled" + * variable. JRA. + */ + + /* + * Check mangled name against mangled name, or unmangled name + * against unmangled name. + */ + + if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname)) { + /* we've found the file, change it's name and return */ + if (docache) + DirCacheAdd(path,name,dname,SNUM(conn)); + pstrcpy(name, dname); + CloseDir(cur_dir); + return(True); + } + } + + CloseDir(cur_dir); + return(False); } diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c index 812488571a..5147ae4b95 100644 --- a/source3/smbd/groupname.c +++ b/source3/smbd/groupname.c @@ -21,7 +21,6 @@ #ifdef USING_GROUPNAME_MAP #include "includes.h" -extern DOM_SID global_sam_sid; /************************************************************************** Groupname map functionality. The code loads a groupname map file and @@ -160,7 +159,7 @@ Error was %s.\n", unixname, strerror(errno) )); * It's not a well known name, convert the UNIX gid_t * to a rid within this domain SID. */ - tmp_sid = global_sam_sid; + sid_copy(&tmp_sid,get_global_sam_sid()); tmp_sid.sub_auths[tmp_sid.num_auths++] = pdb_gid_to_group_rid(gid); } @@ -228,7 +227,7 @@ void map_gid_to_sid( gid_t gid, DOM_SID *psid) * If there's no map, convert the UNIX gid_t * to a rid within this domain SID. */ - *psid = global_sam_sid; + sid_copy(psid,get_global_sam_sid()); psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid); return; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c2f3b7b2f0..91b221968f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -375,7 +375,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int START_PROFILE(SMBtrans); memset(name, '\0',sizeof(name)); - srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, name, smb_buf(inbuf), sizeof(name), STR_TERMINATE); if (dscnt > tdscnt || pscnt > tpscnt) { exit_server("invalid trans parameters"); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 666bbb5f61..217bb6a613 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -71,7 +71,7 @@ static int CopyExpanded(connection_struct *conn, StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); + standard_sub_conn(conn,buf,sizeof(buf)); l = push_ascii(*dst,buf,*n-1, STR_TERMINATE); (*dst) += l; (*n) -= l; @@ -94,7 +94,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char* s) if (!s) return(0); StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); + standard_sub_conn(conn,buf,sizeof(buf)); return strlen(buf) + 1; } @@ -104,7 +104,7 @@ static char* Expand(connection_struct *conn, int snum, char* s) if (!s) return(NULL); StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); + standard_sub_conn(conn,buf,sizeof(buf)); return &buf[0]; } @@ -1670,7 +1670,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch fstring comment; pstring pathname; char *command, *cmdname; - uint offset; + unsigned int offset; int snum; int res = ERRunsup; @@ -1754,82 +1754,104 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c char **rdata,char **rparam, int *rdata_len,int *rparam_len) { + int i; + int errflags=0; + int resume_context, cli_buf_size; char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - char *p2; - int count=0; - if (!prefix_ok(str1,"WrLeh")) return False; - - /* check it's a supported variant */ - switch( uLevel ) - { - case 0: - p2 = "B21"; - break; - default: - return False; + GROUP_MAP *group_list; + int num_entries; + + if (strcmp(str1,"WrLeh") != 0) + return False; + + /* parameters + * W-> resume context (number of users to skip) + * r -> return parameter pointer to receive buffer + * L -> length of receive buffer + * e -> return parameter number of entries + * h -> return parameter total number of users + */ + if (strcmp("B21",str2) != 0) + return False; + + /* get list of domain groups SID_DOMAIN_GRP=2 */ + if(!enum_group_mapping(2 , &group_list, &num_entries, False, False)) { + DEBUG(3,("api_RNetGroupEnum:failed to get group list")); + return False; } - if (strcmp(p2,str2) != 0) return False; + resume_context = SVAL(p,0); + cli_buf_size=SVAL(p+2,0); + DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); - *rdata_len = mdrcnt + 1024; + *rdata_len = cli_buf_size; *rdata = REALLOC(*rdata,*rdata_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - p = *rdata; - /* XXXX we need a real SAM database some day */ - pstrcpy(p,"Users"); p += 21; count++; - pstrcpy(p,"Domain Users"); p += 21; count++; - pstrcpy(p,"Guests"); p += 21; count++; - pstrcpy(p,"Domain Guests"); p += 21; count++; + for(i=resume_context; i resume context (number of users to skip) + * r -> return parameter pointer to receive buffer + * L -> length of receive buffer + * e -> return parameter number of entries + * h -> return parameter total number of users + */ + + resume_context = SVAL(p,0); + cli_buf_size=SVAL(p+2,0); + DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); + *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,4,count); /* is this right?? */ - SSVAL(*rparam,6,count); /* is this right?? */ + /* check it's a supported varient */ + if (strcmp("B21",str2) != 0) + return False; - DEBUG(3,("api_RNetUserEnum gave %d entries\n", count)); + *rdata_len = cli_buf_size; + *rdata = REALLOC(*rdata,*rdata_len); - return(True); + p = *rdata; + + /* to get user list enumerations for NetUserEnum in B21 format */ + pdb_init_sam(&pwd); + + /* Open the passgrp file - not for update. */ + become_root(); + if(!pdb_setsampwent(False)) { + DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n")); + unbecome_root(); + return False; + } + errflags=NERR_Success; + + while ( pdb_getsampwent(pwd) ) { + const char *name=pdb_get_username(pwd); + if ((name) && (*(name+strlen(name)-1)!='$')) { + count_total++; + if(count_total>=resume_context) { + if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) { + pstrcpy(p,name); + DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p)); + p += 21; + count_sent++; + } else { + /* set overflow error */ + DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name)); + errflags=234; + break; + } + } + } + } ; + + pdb_endsampwent(); + unbecome_root(); + + pdb_free_sam(&pwd); + + *rdata_len = PTR_DIFF(p,*rdata); + + SSVAL(*rparam,0,errflags); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,count_sent); /* is this right?? */ + SSVAL(*rparam,6,count_total); /* is this right?? */ + + return True; } @@ -2343,7 +2451,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par SIVAL(p,6,0); } else { SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub_conn(conn,comment); + standard_sub_conn(conn,comment,sizeof(comment)); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); p2 = skip_string(p2,1); } @@ -2685,8 +2793,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - pstrcpy(p2, lp_logon_home()); - standard_sub_conn(conn, p2); + pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); @@ -2722,15 +2829,13 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(p,42, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - pstrcpy(p2,lp_logon_home()); - standard_sub_conn(conn, p2); + pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ - pstrcpy(p2,lp_logon_script()); - standard_sub_conn( conn, p2 ); + pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); p2 = skip_string(p2,1); if (uLevel == 2) { @@ -2755,7 +2860,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVALS(p,104,-1); /* num_logons */ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ pstrcpy(p2,"\\\\%L"); - standard_sub_conn(conn, p2); + standard_sub_conn(conn, p2,0); p2 = skip_string(p2,1); SSVAL(p,110,49); /* country_code */ SSVAL(p,112,860); /* code page */ @@ -2769,56 +2874,6 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param return(True); } -/******************************************************************* - get groups that a user is a member of - ******************************************************************/ -static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *UserName = skip_string(str2,1); - char *p = skip_string(UserName,1); - int uLevel = SVAL(p,0); - char *p2; - int count=0; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLeh") != 0) return False; - switch( uLevel ) { - case 0: p2 = "B21"; break; - default: return False; - } - if (strcmp(p2,str2) != 0) return False; - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - - /* XXXX we need a real SAM database some day */ - pstrcpy(p,"Users"); p += 21; count++; - pstrcpy(p,"Domain Users"); p += 21; count++; - pstrcpy(p,"Guests"); p += 21; count++; - pstrcpy(p,"Domain Guests"); p += 21; count++; - - *rdata_len = PTR_DIFF(p,*rdata); - - SSVAL(*rparam,4,count); /* is this right?? */ - SSVAL(*rparam,6,count); /* is this right?? */ - - return(True); -} - - static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2830,6 +2885,12 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param int uLevel; struct pack_desc desc; char* name; + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ + user_struct *vuser = get_valid_user_struct(vuid); + if(vuser != NULL) + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, + vuser->user.unix_name)); uLevel = SVAL(p,0); name = p + 2; @@ -2873,15 +2934,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param } PACKS(&desc,"z",global_myworkgroup);/* domain */ -/* JHT - By calling lp_logon_script() and standard_sub() we have */ -/* made sure all macros are fully substituted and available */ - { - pstring logon_script; - pstrcpy(logon_script,lp_logon_script()); - standard_sub_conn( conn, logon_script ); - PACKS(&desc,"z", logon_script); /* script path */ - } -/* End of JHT mods */ + PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */ PACKI(&desc,"D",0x00000000); /* reserved */ } @@ -3030,7 +3083,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); - /* check it's a supported varient */ + /* check it's a supported variant */ if (strcmp(str1,"zWrLeh") != 0) return False; if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */ if (!check_printjob_info(&desc,uLevel,str2)) return False; @@ -3383,38 +3436,6 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, return(True); } -struct session_info { - char machine[31]; - char username[24]; - char clitype[24]; - int opens; - int time; -}; - -struct sessions_info { - int count; - struct session_info *session_list; -}; - -static int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) -{ - struct sessions_info *sinfo = state; - struct session_info *curinfo = NULL; - struct sessionid *sessid = (struct sessionid *) dbuf.dptr; - - sinfo->count += 1; - sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info)); - - curinfo = &(sinfo->session_list[sinfo->count - 1]); - - safe_strcpy(curinfo->machine, sessid->remote_machine, - sizeof(curinfo->machine)); - safe_strcpy(curinfo->username, uidtoname(sessid->uid), - sizeof(curinfo->username)); - DEBUG(7,("gather_sessioninfo session from %s@%s\n", - curinfo->username, curinfo->machine)); - return 0; -} /**************************************************************************** List open sessions @@ -3430,8 +3451,8 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param char *p = skip_string(str2,1); int uLevel; struct pack_desc desc; - struct sessions_info sinfo; - int i; + struct sessionid *session_list; + int i, num_sessions; memset((char *)&desc,'\0',sizeof(desc)); @@ -3445,26 +3466,20 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False; if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False; - sinfo.count = 0; - sinfo.session_list = NULL; - - if (!session_traverse(gather_sessioninfo, &sinfo)) { - DEBUG(4,("RNetSessionEnum session_traverse failed\n")); - return False; - } + num_sessions = list_sessions(&session_list); if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); memset((char *)&desc,'\0',sizeof(desc)); desc.base = *rdata; desc.buflen = mdrcnt; desc.format = str2; - if (!init_package(&desc,sinfo.count,0)) { + if (!init_package(&desc,num_sessions,0)) { return False; } - for(i=0; iguest) + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + rdata = (char *)malloc(1024); if (rdata) memset(rdata,'\0',1024); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 20b2b419cf..392e48afc1 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -29,6 +29,7 @@ static struct { } mangle_backends[] = { { "hash", mangle_hash_init }, { "hash2", mangle_hash2_init }, + /*{ "tdb", mangle_tdb_init }, */ { NULL, NULL } }; @@ -40,11 +41,12 @@ static void mangle_init(void) int i; char *method; - if (mangle_fns) return; + if (mangle_fns) + return; method = lp_mangling_method(); - /* find the first mangling method that manages to initialise and + /* find the first mangling method that manages to initialise and matches the "mangling method" parameter */ for (i=0; mangle_backends[i].name && !mangle_fns; i++) { if (!method || !*method || strcmp(method, mangle_backends[i].name) == 0) { @@ -82,7 +84,12 @@ BOOL mangle_is_mangled(const char *s) */ BOOL mangle_is_8_3(const char *fname, BOOL check_case) { - return mangle_fns->is_8_3(fname, check_case); + return mangle_fns->is_8_3(fname, check_case, False); +} + +BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case) +{ + return mangle_fns->is_8_3(fname, check_case, True); } /* @@ -99,7 +106,8 @@ BOOL mangle_check_cache(char *s) /* map a long filename to a 8.3 name. */ -BOOL mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum) + +void mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum) { /* name mangling can be disabled for speed, in which case we just truncate the string */ @@ -107,11 +115,10 @@ BOOL mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum) if (need83) { string_truncate(OutName, 12); } - return True; + return; } /* invoke the inane "mangled map" code */ mangle_map_filename(OutName, snum); - - return mangle_fns->name_map(OutName, need83, cache83); + mangle_fns->name_map(OutName, need83, cache83); } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index f38c2ae2c4..1d4697474c 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -127,9 +127,8 @@ static BOOL ct_initialized = False; static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } }; static BOOL mc_initialized = False; -#define MANGLED_CACHE_MAX_ENTRIES 0 -#define MANGLED_CACHE_MAX_MEMORY 16384 - +#define MANGLED_CACHE_MAX_ENTRIES 1024 +#define MANGLED_CACHE_MAX_MEMORY 0 /* -------------------------------------------------------------------------- ** * External Variables... @@ -140,16 +139,19 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ /* -------------------------------------------------------------------- */ -static NTSTATUS has_valid_chars(const smb_ucs2_t *s) +static NTSTATUS has_valid_chars(const smb_ucs2_t *s, BOOL allow_wildcards) { - if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; + if (!s || !*s) + return NT_STATUS_INVALID_PARAMETER; /* CHECK: this should not be necessary if the ms wild chars are not valid in valid.dat --- simo */ - if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL; + if (!allow_wildcards && ms_has_wild_w(s)) + return NT_STATUS_UNSUCCESSFUL; while (*s) { - if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL; + if(!isvalid83_w(*s)) + return NT_STATUS_UNSUCCESSFUL; s++; } @@ -159,7 +161,9 @@ static NTSTATUS has_valid_chars(const smb_ucs2_t *s) /* return False if something fail and * return 2 alloced unicode strings that contain prefix and extension */ -static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension) + +static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, + smb_ucs2_t **extension, BOOL allow_wildcards) { size_t ext_len; smb_ucs2_t *p; @@ -169,12 +173,10 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr if (!*prefix) { return NT_STATUS_NO_MEMORY; } - if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) - { + if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) { ext_len = strlen_w(p+1); if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) && - (NT_STATUS_IS_OK(has_valid_chars(p+1)))) /* check extension */ - { + (NT_STATUS_IS_OK(has_valid_chars(p+1,allow_wildcards)))) /* check extension */ { *p = 0; *extension = strdup_w(p+1); if (!*extension) { @@ -197,20 +199,34 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr * * ************************************************************************** ** */ -static NTSTATUS is_valid_name(const smb_ucs2_t *fname) + +static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards) { smb_ucs2_t *str, *p; NTSTATUS ret = NT_STATUS_OK; - if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; + if (!fname || !*fname) + return NT_STATUS_INVALID_PARAMETER; - if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL; + /* . and .. are valid names. */ + if (strcmp_wa(fname, ".")==0 || strcmp_wa(fname, "..")==0) + return NT_STATUS_OK; + + /* Name cannot start with '.' */ + if (*fname == UCS2_CHAR('.')) + return NT_STATUS_UNSUCCESSFUL; - ret = has_valid_chars(fname); - if (NT_STATUS_IS_ERR(ret)) return ret; + ret = has_valid_chars(fname, allow_wildcards); + if (NT_STATUS_IS_ERR(ret)) + return ret; str = strdup_w(fname); p = strchr_w(str, UCS2_CHAR('.')); + if (p && p[1] == UCS2_CHAR(0)) { + /* Name cannot end in '.' */ + SAFE_FREE(str); + return NT_STATUS_UNSUCCESSFUL; + } if (p) *p = 0; strupper_w(str); p = &(str[1]); @@ -254,27 +270,34 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname) return ret; } -static NTSTATUS is_8_3_w(const smb_ucs2_t *fname) +static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards) { smb_ucs2_t *pref = 0, *ext = 0; size_t plen; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER; + if (!fname || !*fname) + return NT_STATUS_INVALID_PARAMETER; - if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL; + if (strlen_w(fname) > 12) + return NT_STATUS_UNSUCCESSFUL; if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) return NT_STATUS_OK; - if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done; + if (NT_STATUS_IS_ERR(is_valid_name(fname, allow_wildcards))) + goto done; - if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done; + if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext, allow_wildcards))) + goto done; plen = strlen_w(pref); - if (strchr_wa(pref, '.')) goto done; - if (plen < 1 || plen > 8) goto done; - if (ext) if (strlen_w(ext) > 3) goto done; + if (strchr_wa(pref, '.')) + goto done; + if (plen < 1 || plen > 8) + goto done; + if (ext && (strlen_w(ext) > 3)) + goto done; ret = NT_STATUS_OK; @@ -284,26 +307,29 @@ done: return ret; } -static BOOL is_8_3(const char *fname, BOOL check_case) +static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) { const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - if (!fname || !*fname) return False; - if ((f = strrchr(fname, '/')) == NULL) f = fname; - else f++; + if (!fname || !*fname) + return False; + if ((f = strrchr(fname, '/')) == NULL) + f = fname; + else + f++; - if (strlen(f) > 12) return False; + if (strlen(f) > 12) + return False; ucs2name = acnv_uxu2(f); - if (!ucs2name) - { + if (!ucs2name) { DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); goto done; } - ret = is_8_3_w(ucs2name); + ret = is_8_3_w(ucs2name, allow_wildcards); done: SAFE_FREE(ucs2name); @@ -334,21 +360,20 @@ done: * ************************************************************************** ** */ static void init_chartest( void ) - { - char *illegalchars = "*\\/?<>|\":"; - unsigned char *s; +{ + char *illegalchars = "*\\/?<>|\":"; + unsigned char *s; - memset( (char *)chartest, '\0', 256 ); - - for( s = (unsigned char *)illegalchars; *s; s++ ) - chartest[*s] = ILLEGAL_MASK; + memset( (char *)chartest, '\0', 256 ); - for( s = (unsigned char *)basechars; *s; s++ ) - chartest[*s] |= BASECHAR_MASK; + for( s = (unsigned char *)illegalchars; *s; s++ ) + chartest[*s] = ILLEGAL_MASK; - ct_initialized = True; - } /* init_chartest */ + for( s = (unsigned char *)basechars; *s; s++ ) + chartest[*s] |= BASECHAR_MASK; + ct_initialized = True; +} /* ************************************************************************** ** * Return True if the name *could be* a mangled name. @@ -368,24 +393,22 @@ static void init_chartest( void ) * ************************************************************************** ** */ static BOOL is_mangled(const char *s) - { - char *magic; - - if( !ct_initialized ) - init_chartest(); - - magic = strchr_m( s, magic_char ); - while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */ - { - if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ - && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ - && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ - return( True ); /* If all above, then true, */ - magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ - } - return( False ); - } /* is_mangled */ - +{ + char *magic; + + if( !ct_initialized ) + init_chartest(); + + magic = strchr_m( s, magic_char ); + while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */ + if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ + && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ + && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ + return( True ); /* If all above, then true, */ + magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ + } + return( False ); +} /* ************************************************************************** ** * Compare two cache keys and return a value indicating their ordinal @@ -407,12 +430,12 @@ static BOOL is_mangled(const char *s) * ************************************************************************** ** */ static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) - { - char *Key1 = (char *)ItemPtr; - char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); +{ + char *Key1 = (char *)ItemPtr; + char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); - return( StrCaseCmp( Key1, Key2 ) ); - } /* cache_compare */ + return( StrCaseCmp( Key1, Key2 ) ); +} /* ************************************************************************** ** * Free a cache entry. @@ -428,10 +451,10 @@ static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) * ************************************************************************** ** */ static void cache_free_entry( ubi_trNodePtr WarrenZevon ) - { - ZERO_STRUCTP(WarrenZevon); - SAFE_FREE( WarrenZevon ); - } /* cache_free_entry */ +{ + ZERO_STRUCTP(WarrenZevon); + SAFE_FREE( WarrenZevon ); +} /* ************************************************************************** ** * Initializes or clears the mangled cache. @@ -449,28 +472,25 @@ static void cache_free_entry( ubi_trNodePtr WarrenZevon ) * * ************************************************************************** ** */ + static void mangle_reset( void ) - { - if( !mc_initialized ) - { - (void)ubi_cacheInit( mangled_cache, - cache_compare, - cache_free_entry, - MANGLED_CACHE_MAX_ENTRIES, - MANGLED_CACHE_MAX_MEMORY ); - mc_initialized = True; - } - else - { - (void)ubi_cacheClear( mangled_cache ); - } - - /* - (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); - (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); - */ - } /* reset_mangled_cache */ +{ + if( !mc_initialized ) { + (void)ubi_cacheInit( mangled_cache, + cache_compare, + cache_free_entry, + MANGLED_CACHE_MAX_ENTRIES, + MANGLED_CACHE_MAX_MEMORY ); + mc_initialized = True; + } else { + (void)ubi_cacheClear( mangled_cache ); + } + /* + (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); + (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); + */ +} /* ************************************************************************** ** * Add a mangled name into the cache. @@ -497,51 +517,49 @@ static void mangle_reset( void ) * ************************************************************************** ** */ static void cache_mangled_name( char *mangled_name, char *raw_name ) - { - ubi_cacheEntryPtr new_entry; - char *s1; - char *s2; - size_t mangled_len; - size_t raw_len; - size_t i; - - /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) - return; - - /* Init the string lengths. */ - mangled_len = strlen( mangled_name ); - raw_len = strlen( raw_name ); - - /* See if the extensions are unmangled. If so, store the entry - * without the extension, thus creating a "group" reverse map. - */ - s1 = strrchr( mangled_name, '.' ); - if( s1 && (s2 = strrchr( raw_name, '.' )) ) - { - i = 1; - while( s1[i] && (tolower( s1[i] ) == s2[i]) ) - i++; - if( !s1[i] && !s2[i] ) - { - mangled_len -= i; - raw_len -= i; - } - } - - /* Allocate a new cache entry. If the allocation fails, just return. */ - i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; - new_entry = malloc( i ); - if( !new_entry ) - return; - - /* Fill the new cache entry, and add it to the cache. */ - s1 = (char *)(new_entry + 1); - s2 = (char *)&(s1[mangled_len + 1]); - (void)StrnCpy( s1, mangled_name, mangled_len ); - (void)StrnCpy( s2, raw_name, raw_len ); - ubi_cachePut( mangled_cache, i, new_entry, s1 ); - } /* cache_mangled_name */ +{ + ubi_cacheEntryPtr new_entry; + char *s1; + char *s2; + size_t mangled_len; + size_t raw_len; + size_t i; + + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) + return; + + /* Init the string lengths. */ + mangled_len = strlen( mangled_name ); + raw_len = strlen( raw_name ); + + /* See if the extensions are unmangled. If so, store the entry + * without the extension, thus creating a "group" reverse map. + */ + s1 = strrchr( mangled_name, '.' ); + if( s1 && (s2 = strrchr( raw_name, '.' )) ) { + i = 1; + while( s1[i] && (tolower( s1[i] ) == s2[i]) ) + i++; + if( !s1[i] && !s2[i] ) { + mangled_len -= i; + raw_len -= i; + } + } + + /* Allocate a new cache entry. If the allocation fails, just return. */ + i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; + new_entry = malloc( i ); + if( !new_entry ) + return; + + /* Fill the new cache entry, and add it to the cache. */ + s1 = (char *)(new_entry + 1); + s2 = (char *)&(s1[mangled_len + 1]); + (void)StrnCpy( s1, mangled_name, mangled_len ); + (void)StrnCpy( s2, raw_name, raw_len ); + ubi_cachePut( mangled_cache, i, new_entry, s1 ); +} /* ************************************************************************** ** * Check for a name on the mangled name stack @@ -560,63 +578,57 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) static BOOL check_cache( char *s ) { - ubi_cacheEntryPtr FoundPtr; - char *ext_start = NULL; - char *found_name; - char *saved_ext = NULL; - - /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) - return( False ); - - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - - /* If we didn't find the name *with* the extension, try without. */ - if( !FoundPtr ) - { - ext_start = strrchr( s, '.' ); - if( ext_start ) - { - if((saved_ext = strdup(ext_start)) == NULL) - return False; - - *ext_start = '\0'; - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); - /* - * At this point s is the name without the - * extension. We re-add the extension if saved_ext - * is not null, before freeing saved_ext. - */ - } - } - - /* Okay, if we haven't found it we're done. */ - if( !FoundPtr ) - { - if(saved_ext) - { - /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); - SAFE_FREE(saved_ext); - } - return( False ); - } - - /* If we *did* find it, we need to copy it into the string buffer. */ - found_name = (char *)(FoundPtr + 1); - found_name += (strlen( found_name ) + 1); - - (void)pstrcpy( s, found_name ); - if( saved_ext ) - { - /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); - SAFE_FREE(saved_ext); - } - - return( True ); -} /* check_mangled_cache */ + ubi_cacheEntryPtr FoundPtr; + char *ext_start = NULL; + char *found_name; + char *saved_ext = NULL; + + /* If the cache isn't initialized, give up. */ + if( !mc_initialized ) + return( False ); + + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + + /* If we didn't find the name *with* the extension, try without. */ + if( !FoundPtr ) { + ext_start = strrchr( s, '.' ); + if( ext_start ) { + if((saved_ext = strdup(ext_start)) == NULL) + return False; + + *ext_start = '\0'; + FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + /* + * At this point s is the name without the + * extension. We re-add the extension if saved_ext + * is not null, before freeing saved_ext. + */ + } + } + + /* Okay, if we haven't found it we're done. */ + if( !FoundPtr ) { + if(saved_ext) { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + SAFE_FREE(saved_ext); + } + return( False ); + } + + /* If we *did* find it, we need to copy it into the string buffer. */ + found_name = (char *)(FoundPtr + 1); + found_name += (strlen( found_name ) + 1); + + (void)pstrcpy( s, found_name ); + if( saved_ext ) { + /* Replace the saved_ext as it was truncated. */ + (void)pstrcat( s, saved_ext ); + SAFE_FREE(saved_ext); + } + return( True ); +} /***************************************************************************** * do the actual mangling to 8.3 format @@ -624,77 +636,67 @@ static BOOL check_cache( char *s ) ***************************************************************************** */ static void to_8_3(char *s) - { - int csum; - char *p; - char extension[4]; - char base[9]; - int baselen = 0; - int extlen = 0; - - extension[0] = 0; - base[0] = 0; - - p = strrchr(s,'.'); - if( p && (strlen(p+1) < (size_t)4) ) - { - BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ - - if( all_normal && p[1] != 0 ) - { - *p = 0; - csum = str_checksum( s ); - *p = '.'; - } - else - csum = str_checksum(s); - } - else - csum = str_checksum(s); - - strupper( s ); - - if( p ) - { - if( p == s ) - safe_strcpy( extension, "___", 3 ); - else - { - *p++ = 0; - while( *p && extlen < 3 ) - { - if ( *p != '.') { - extension[extlen++] = p[0]; - } - p++; - } - extension[extlen] = 0; - } - } - - p = s; - - while( *p && baselen < 5 ) - { - if (*p != '.') { - base[baselen++] = p[0]; - } - p++; - } - base[baselen] = 0; +{ + int csum; + char *p; + char extension[4]; + char base[9]; + int baselen = 0; + int extlen = 0; + + extension[0] = 0; + base[0] = 0; + + p = strrchr(s,'.'); + if( p && (strlen(p+1) < (size_t)4) ) { + BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ + + if( all_normal && p[1] != 0 ) { + *p = 0; + csum = str_checksum( s ); + *p = '.'; + } else + csum = str_checksum(s); + } else + csum = str_checksum(s); + + strupper( s ); + + if( p ) { + if( p == s ) + safe_strcpy( extension, "___", 3 ); + else { + *p++ = 0; + while( *p && extlen < 3 ) { + if ( *p != '.') { + extension[extlen++] = p[0]; + } + p++; + } + extension[extlen] = 0; + } + } - csum = csum % (MANGLE_BASE*MANGLE_BASE); + p = s; + + while( *p && baselen < 5 ) { + if (*p != '.') { + base[baselen++] = p[0]; + } + p++; + } + base[baselen] = 0; - (void)slprintf(s, 12, "%s%c%c%c", - base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); + csum = csum % (MANGLE_BASE*MANGLE_BASE); - if( *extension ) - { - (void)pstrcat( s, "." ); - (void)pstrcat( s, extension ); - } + (void)slprintf(s, 12, "%s%c%c%c", + base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); - } /* mangle_name_83 */ + if( *extension ) { + (void)pstrcat( s, "." ); + (void)pstrcat( s, extension ); + } +} /***************************************************************************** * Convert a filename to DOS format. Return True if successful. @@ -721,7 +723,8 @@ static void to_8_3(char *s) * * **************************************************************************** */ -static BOOL name_map(char *OutName, BOOL need83, BOOL cache83) + +static void name_map(char *OutName, BOOL need83, BOOL cache83) { smb_ucs2_t *OutName_ucs2; DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, @@ -729,11 +732,14 @@ static BOOL name_map(char *OutName, BOOL need83, BOOL cache83) if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) { DEBUG(0, ("push_ucs2_allocate failed!\n")); - return False; + return; } + if( !need83 && NT_STATUS_IS_ERR(is_valid_name(OutName_ucs2, False))) + need83 = True; + /* check if it's already in 8.3 format */ - if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) { + if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2, False))) { char *tmp = NULL; /* mangle it into 8.3 */ @@ -750,9 +756,7 @@ static BOOL name_map(char *OutName, BOOL need83, BOOL cache83) DEBUG(5,("name_map() ==> [%s]\n", OutName)); SAFE_FREE(OutName_ucs2); - return(True); -} /* name_map */ - +} /* the following provides the abstraction layer to make it easier diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 959a93e07b..e2c4b43bc3 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. new hash based name mangling implementation Copyright (C) Andrew Tridgell 2002 + Copyright (C) Simo Sorce 2002 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 @@ -30,6 +31,10 @@ for simplicity, we only allow ascii characters in 8.3 names */ + /* hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce). + * see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a + * discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors + */ /* =============================================================================== @@ -73,6 +78,10 @@ #define MANGLE_CACHE_SIZE 4096 #endif +#define FNV1_PRIME 0x01000193 +/*the following number is a fnv1 of the string: idra@samba.org 2002 */ +#define FNV1_INIT 0xa6b93095 + /* these tables are used to provide fast tests for characters */ static unsigned char char_flags[256]; @@ -88,13 +97,14 @@ static char **prefix_cache; static u32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ -const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static unsigned char base_reverse[256]; #define base_forward(v) basechars[v] /* the list of reserved dos names - all of these are illegal */ -const char *reserved_names[] = { "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4", - "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }; +static const char *reserved_names[] = +{ "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4", + "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }; /* hash a string of the specified length. The string does not need to be @@ -120,13 +130,14 @@ static u32 mangle_hash(const char *key, unsigned length) length = strlen(str); /* Set the initial value from the key size. */ - for (value = 0x238F13AF * length, i=0; i < length; i++) { - value = (value + (((unsigned char)str[i]) << (i*5 % 24))); - } + for (value = FNV1_INIT, i=0; i < length; i++) { + value *= (u32)FNV1_PRIME; + value ^= (u32)(str[i]); + } /* note that we force it to a 31 bit hash, to keep within the limits of the 36^6 mangle space */ - return (1103515243 * value + 12345) & ~0x80000000; + return value & ~0x80000000; } /* @@ -184,12 +195,12 @@ static const char *cache_lookup(u32 hash) In this algorithm, mangled names use only pure ascii characters (no multi-byte) so we can avoid doing a UCS2 conversion -*/ -static BOOL is_mangled(const char *name) + */ +static BOOL is_mangled_component(const char *name) { int len, i; - M_DEBUG(0,("is_mangled %s ?\n", name)); + M_DEBUG(0,("is_mangled_component %s ?\n", name)); /* the best distinguishing characteristic is the ~ */ if (name[6] != '~') return False; @@ -229,6 +240,39 @@ static BOOL is_mangled(const char *name) } + +/* + determine if a string is possibly in a mangled format, ignoring + case + + In this algorithm, mangled names use only pure ascii characters (no + multi-byte) so we can avoid doing a UCS2 conversion + + NOTE! This interface must be able to handle a path with unix + directory separators. It should return true if any component is + mangled + */ +static BOOL is_mangled(const char *name) +{ + const char *p; + const char *s; + + M_DEBUG(0,("is_mangled %s ?\n", name)); + + for (s=name; (p=strchr(s, '/')); s=p+1) { + char *component = strndup(s, PTR_DIFF(p, s)); + if (is_mangled_component(component)) { + free(component); + return True; + } + free(component); + } + + /* and the last part ... */ + return is_mangled_component(s); +} + + /* see if a filename is an allowable 8.3 name. @@ -236,7 +280,7 @@ static BOOL is_mangled(const char *name) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case) +static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) { int len, i; char *dot_p; @@ -286,8 +330,8 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { - /* note that we allow wildcard petterns! */ - if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD) && name[i] != '.') { + /* note that we may allow wildcard petterns! */ + if (!FLAG_CHECK(name[i], FLAG_ASCII|(allow_wildcards ? FLAG_WILDCARD : 0)) && name[i] != '.') { return False; } } @@ -343,8 +387,12 @@ static BOOL check_cache(char *name) } /* we found it - construct the full name */ - strncpy(extension, name+9, 3); - extension[3] = 0; + if (name[8] == '.') { + strncpy(extension, name+9, 3); + extension[3] = 0; + } else { + extension[0] = 0; + } if (extension[0]) { M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); @@ -383,17 +431,38 @@ static BOOL is_reserved_name(const char *name) } /* - see if a filename is a legal long filename + See if a filename is a legal long filename. + A filename ending in a '.' is not legal unless it's "." or "..". JRA. */ + static BOOL is_legal_name(const char *name) { + const char *dot_pos = NULL; + BOOL alldots = True; + size_t numdots = 0; + while (*name) { if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } + if (name[0] == '.') { + dot_pos = name; + numdots++; + } else { + alldots = False; + } name++; } + if (dot_pos) { + if (alldots && (numdots == 1 || numdots == 2)) + return True; /* . or .. is a valid name */ + + /* A valid long name cannot end in '.' */ + if (dot_pos[1] == '\0') + return False; + } + return True; } @@ -408,7 +477,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static BOOL name_map(char *name, BOOL need83, BOOL cache83) +static void name_map(char *name, BOOL need83, BOOL cache83) { char *dot_p; char lead_char; @@ -422,14 +491,14 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) if (!is_reserved_name(name)) { /* if the name is already a valid 8.3 name then we don't need to do anything */ - if (is_8_3(name, False)) { - return True; + if (is_8_3(name, False, False)) { + return; } /* if the caller doesn't strictly need 8.3 then just check for illegal filenames */ if (!need83 && is_legal_name(name)) { - return True; + return; } } @@ -511,7 +580,6 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) fstrcpy(name, new_name); /* all done, we've managed to mangle it */ - return True; } diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c index 71d9340718..553e3d949d 100644 --- a/source3/smbd/mangle_map.c +++ b/source3/smbd/mangle_map.c @@ -127,8 +127,8 @@ static char *map_filename( char *s, /* This is null terminated */ */ static void mangled_map(char *s, const char *MangledMap) { - char *start=MangledMap; /* Use this to search for mappings. */ - char *end; /* Used to find the end of strings. */ + const char *start=MangledMap; /* Use this to search for mappings. */ + const char *end; /* Used to find the end of strings. */ char *match_string; pstring new_string; /* Make up the result here. */ char *np; /* Points into new_string. */ diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 971834c012..ba646f12aa 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -85,7 +85,7 @@ static void msg_deliver(void) pstrcpy(s,lp_msg_command()); pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); - standard_sub_basic(current_user_info.smb_name, s); + standard_sub_basic(current_user_info.smb_name, s, sizeof(s)); pstring_sub(s,"%s",name); smbrun(s,NULL); } @@ -118,8 +118,8 @@ int reply_sends(connection_struct *conn, outsize = set_message(outbuf,0,0,True); p = smb_buf(inbuf)+1; - p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE) + 1; - p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_TERMINATE) + 1; msg = p; @@ -160,8 +160,8 @@ int reply_sendstrt(connection_struct *conn, msgpos = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE) + 1; - p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_TERMINATE) + 1; DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 18682e6c9f..81c2427a00 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -50,8 +50,9 @@ static void get_challenge(char buff[8]) } /**************************************************************************** -reply for the core protocol + Reply for the core protocol. ****************************************************************************/ + static int reply_corep(char *inbuf, char *outbuf) { int outsize = set_message(outbuf,1,0,True); @@ -61,107 +62,110 @@ static int reply_corep(char *inbuf, char *outbuf) return outsize; } - /**************************************************************************** -reply for the coreplus protocol + Reply for the coreplus protocol. ****************************************************************************/ + static int reply_coreplus(char *inbuf, char *outbuf) { - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int outsize = set_message(outbuf,13,0,True); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support - readbraw and writebraw (possibly) */ - /* Reply, SMBlockread, SMBwritelock supported. */ - SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */ + int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); + int outsize = set_message(outbuf,13,0,True); + SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support + readbraw and writebraw (possibly) */ + /* Reply, SMBlockread, SMBwritelock supported. */ + SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); + SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */ - Protocol = PROTOCOL_COREPLUS; + Protocol = PROTOCOL_COREPLUS; - return outsize; + return outsize; } - /**************************************************************************** -reply for the lanman 1.0 protocol + Reply for the lanman 1.0 protocol. ****************************************************************************/ + static int reply_lanman1(char *inbuf, char *outbuf) { - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int secword=0; - time_t t = time(NULL); + int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); + int secword=0; + time_t t = time(NULL); - global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); - if (lp_security()>=SEC_USER) secword |= 1; - if (global_encrypted_passwords_negotiated) secword |= 2; + if (lp_security()>=SEC_USER) + secword |= NEGOTIATE_SECURITY_USER_LEVEL; + if (global_encrypted_passwords_negotiated) + secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; - set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); - /* Create a token value and add it to the outgoing packet. */ - if (global_encrypted_passwords_negotiated) { - get_challenge(smb_buf(outbuf)); - } + set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); + /* Create a token value and add it to the outgoing packet. */ + if (global_encrypted_passwords_negotiated) { + get_challenge(smb_buf(outbuf)); + } - Protocol = PROTOCOL_LANMAN1; + Protocol = PROTOCOL_LANMAN1; - /* Reply, SMBlockread, SMBwritelock supported. */ - SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support - readbraw writebraw (possibly) */ - SIVAL(outbuf,smb_vwv6,sys_getpid()); - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); + /* Reply, SMBlockread, SMBwritelock supported. */ + SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); + SSVAL(outbuf,smb_vwv2,max_recv); + SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ + SSVAL(outbuf,smb_vwv4,1); + SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support + readbraw writebraw (possibly) */ + SIVAL(outbuf,smb_vwv6,sys_getpid()); + SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); - put_dos_date(outbuf,smb_vwv8,t); + put_dos_date(outbuf,smb_vwv8,t); - return (smb_len(outbuf)+4); + return (smb_len(outbuf)+4); } - /**************************************************************************** -reply for the lanman 2.0 protocol + Reply for the lanman 2.0 protocol. ****************************************************************************/ + static int reply_lanman2(char *inbuf, char *outbuf) { - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int secword=0; - time_t t = time(NULL); + int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); + int secword=0; + time_t t = time(NULL); - global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); - if (lp_security()>=SEC_USER) secword |= 1; - if (global_encrypted_passwords_negotiated) secword |= 2; - - set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); - SIVAL(outbuf,smb_vwv6,sys_getpid()); - - /* Create a token value and add it to the outgoing packet. */ - if (global_encrypted_passwords_negotiated) { - get_challenge(smb_buf(outbuf)); - } - - Protocol = PROTOCOL_LANMAN2; - - /* Reply, SMBlockread, SMBwritelock supported. */ - SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); - put_dos_date(outbuf,smb_vwv8,t); - - return (smb_len(outbuf)+4); -} + if (lp_security()>=SEC_USER) + secword |= NEGOTIATE_SECURITY_USER_LEVEL; + if (global_encrypted_passwords_negotiated) + secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; + set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); + SIVAL(outbuf,smb_vwv6,sys_getpid()); + /* Create a token value and add it to the outgoing packet. */ + if (global_encrypted_passwords_negotiated) { + get_challenge(smb_buf(outbuf)); + } + + Protocol = PROTOCOL_LANMAN2; + + /* Reply, SMBlockread, SMBwritelock supported. */ + SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); + SSVAL(outbuf,smb_vwv2,max_recv); + SSVAL(outbuf,smb_vwv3,lp_maxmux()); + SSVAL(outbuf,smb_vwv4,1); + SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ + SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); + put_dos_date(outbuf,smb_vwv8,t); + + return (smb_len(outbuf)+4); +} + +/**************************************************************************** + Generate the spnego negprot reply blob. Return the number of bytes used. +****************************************************************************/ -/* - generate the spnego negprot reply blob. Return the number of bytes used -*/ static int negprot_spnego(char *p) { DATA_BLOB blob; @@ -197,7 +201,7 @@ static int negprot_spnego(char *p) blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); } else { ADS_STRUCT *ads; - ads = ads_init(NULL, NULL, NULL, NULL); + ads = ads_init_simple(); /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ asprintf(&principal, "HOST/%s@%s", guid, ads->realm); @@ -211,11 +215,10 @@ static int negprot_spnego(char *p) return len; } - - /**************************************************************************** -reply for the nt protocol + Reply for the nt protocol. ****************************************************************************/ + static int reply_nt1(char *inbuf, char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ @@ -262,9 +265,9 @@ static int reply_nt1(char *inbuf, char *outbuf) capabilities |= CAP_DFS; if (lp_security() >= SEC_USER) - secword |= 1; + secword |= NEGOTIATE_SECURITY_USER_LEVEL; if (global_encrypted_passwords_negotiated) - secword |= 2; + secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; set_message(outbuf,17,0,True); @@ -377,133 +380,128 @@ protocol [LANMAN2.1] /* List of supported protocols, most desired first */ static struct { - char *proto_name; - char *short_name; - int (*proto_reply_fn)(char *, char *); - int protocol_level; + char *proto_name; + char *short_name; + int (*proto_reply_fn)(char *, char *); + int protocol_level; } supported_protocols[] = { - {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, - {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, - {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, - {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, - {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS}, - {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE}, - {NULL,NULL,NULL,0}, + {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, + {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, + {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, + {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, + {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, + {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS}, + {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE}, + {NULL,NULL,NULL,0}, }; - /**************************************************************************** - reply to a negprot + Reply to a negprot. ****************************************************************************/ + int reply_negprot(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,1,0,True); - int Index=0; - int choice= -1; - int protocol; - char *p; - int bcc = SVAL(smb_buf(inbuf),-2); - int arch = ARCH_ALL; - START_PROFILE(SMBnegprot); - - p = smb_buf(inbuf)+1; - while (p < (smb_buf(inbuf) + bcc)) - { - Index++; - DEBUG(3,("Requested protocol [%s]\n",p)); - if (strcsequal(p,"Windows for Workgroups 3.1a")) - arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); - else if (strcsequal(p,"DOS LM1.2X002")) - arch &= ( ARCH_WFWG | ARCH_WIN95 ); - else if (strcsequal(p,"DOS LANMAN2.1")) - arch &= ( ARCH_WFWG | ARCH_WIN95 ); - else if (strcsequal(p,"NT LM 0.12")) - arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); - else if (strcsequal(p,"LANMAN2.1")) - arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); - else if (strcsequal(p,"LM1.2X002")) - arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); - else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) - arch &= ARCH_WINNT; - else if (strcsequal(p,"XENIX CORE")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); - else if (strcsequal(p,"Samba")) { - arch = ARCH_SAMBA; - break; - } + int outsize = set_message(outbuf,1,0,True); + int Index=0; + int choice= -1; + int protocol; + char *p; + int bcc = SVAL(smb_buf(inbuf),-2); + int arch = ARCH_ALL; + START_PROFILE(SMBnegprot); + + p = smb_buf(inbuf)+1; + while (p < (smb_buf(inbuf) + bcc)) { + Index++; + DEBUG(3,("Requested protocol [%s]\n",p)); + if (strcsequal(p,"Windows for Workgroups 3.1a")) + arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); + else if (strcsequal(p,"DOS LM1.2X002")) + arch &= ( ARCH_WFWG | ARCH_WIN95 ); + else if (strcsequal(p,"DOS LANMAN2.1")) + arch &= ( ARCH_WFWG | ARCH_WIN95 ); + else if (strcsequal(p,"NT LM 0.12")) + arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); + else if (strcsequal(p,"LANMAN2.1")) + arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); + else if (strcsequal(p,"LM1.2X002")) + arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); + else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) + arch &= ARCH_WINNT; + else if (strcsequal(p,"XENIX CORE")) + arch &= ( ARCH_WINNT | ARCH_OS2 ); + else if (strcsequal(p,"Samba")) { + arch = ARCH_SAMBA; + break; + } - p += strlen(p) + 2; - } + p += strlen(p) + 2; + } - switch ( arch ) { - case ARCH_SAMBA: - set_remote_arch(RA_SAMBA); - break; - case ARCH_WFWG: - set_remote_arch(RA_WFWG); - break; - case ARCH_WIN95: - set_remote_arch(RA_WIN95); - break; - case ARCH_WINNT: - if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE) - set_remote_arch(RA_WIN2K); - else - set_remote_arch(RA_WINNT); - break; - case ARCH_WIN2K: - set_remote_arch(RA_WIN2K); - break; - case ARCH_OS2: - set_remote_arch(RA_OS2); - break; - default: - set_remote_arch(RA_UNKNOWN); - break; - } + switch ( arch ) { + case ARCH_SAMBA: + set_remote_arch(RA_SAMBA); + break; + case ARCH_WFWG: + set_remote_arch(RA_WFWG); + break; + case ARCH_WIN95: + set_remote_arch(RA_WIN95); + break; + case ARCH_WINNT: + if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE) + set_remote_arch(RA_WIN2K); + else + set_remote_arch(RA_WINNT); + break; + case ARCH_WIN2K: + set_remote_arch(RA_WIN2K); + break; + case ARCH_OS2: + set_remote_arch(RA_OS2); + break; + default: + set_remote_arch(RA_UNKNOWN); + break; + } - /* possibly reload - change of architecture */ - reload_services(True); + /* possibly reload - change of architecture */ + reload_services(True); - /* Check for protocols, most desirable first */ - for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) - { - p = smb_buf(inbuf)+1; - Index = 0; - if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) && - (supported_protocols[protocol].protocol_level >= lp_minprotocol())) - while (p < (smb_buf(inbuf) + bcc)) - { - if (strequal(p,supported_protocols[protocol].proto_name)) - choice = Index; - Index++; - p += strlen(p) + 2; - } - if(choice != -1) - break; - } + /* Check for protocols, most desirable first */ + for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { + p = smb_buf(inbuf)+1; + Index = 0; + if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) && + (supported_protocols[protocol].protocol_level >= lp_minprotocol())) + while (p < (smb_buf(inbuf) + bcc)) { + if (strequal(p,supported_protocols[protocol].proto_name)) + choice = Index; + Index++; + p += strlen(p) + 2; + } + if(choice != -1) + break; + } - SSVAL(outbuf,smb_vwv0,choice); - if(choice != -1) { - extern fstring remote_proto; - fstrcpy(remote_proto,supported_protocols[protocol].short_name); - reload_services(True); - outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf); - DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); - } - else { - DEBUG(0,("No protocol supported !\n")); - } - SSVAL(outbuf,smb_vwv0,choice); + SSVAL(outbuf,smb_vwv0,choice); + if(choice != -1) { + extern fstring remote_proto; + fstrcpy(remote_proto,supported_protocols[protocol].short_name); + reload_services(True); + outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf); + DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); + } else { + DEBUG(0,("No protocol supported !\n")); + } + SSVAL(outbuf,smb_vwv0,choice); - DEBUG( 5, ( "negprot index=%d\n", choice ) ); + DEBUG( 5, ( "negprot index=%d\n", choice ) ); - END_PROFILE(SMBnegprot); - return(outsize); + END_PROFILE(SMBnegprot); + return(outsize); } - diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 19ea41e195..8454917163 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -1,5 +1,6 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 3.0 change notify handling - linux kernel based implementation Copyright (C) Andrew Tridgell 2000 @@ -22,9 +23,9 @@ #if HAVE_KERNEL_CHANGE_NOTIFY -static VOLATILE sig_atomic_t fd_pending; -static VOLATILE sig_atomic_t signals_received; -static VOLATILE sig_atomic_t signals_processed; +#define FD_PENDING_SIZE 20 +static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; +static SIG_ATOMIC_T signals_received; #ifndef DN_ACCESS #define DN_ACCESS 0x00000001 /* File accessed in directory */ @@ -53,84 +54,114 @@ static VOLATILE sig_atomic_t signals_processed; This is the structure to keep the information needed to determine if a directory has changed. *****************************************************************************/ + struct change_data { int directory_handle; }; /**************************************************************************** -the signal handler for change notify + The signal handler for change notify. + The Linux kernel has a bug in that we should be able to block any + further delivery of RT signals until the kernel_check_notify() function + unblocks them, but it seems that any signal mask we're setting here is + being overwritten on exit from this handler. I should create a standalone + test case for the kernel hackers. JRA. *****************************************************************************/ + static void signal_handler(int sig, siginfo_t *info, void *unused) { - BlockSignals(True, sig); - fd_pending = (sig_atomic_t)info->si_fd; - signals_received++; + if (signals_received < FD_PENDING_SIZE - 1) { + fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd; + signals_received++; + } /* Else signal is lost. */ sys_select_signal(); } - - /**************************************************************************** Check if a change notify should be issued. time non-zero means timeout check (used for hash). Ignore this (async method where time is zero will be used instead). *****************************************************************************/ + static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) { struct change_data *data = (struct change_data *)datap; + int i; + BOOL ret = False; if (t) return False; - if (data->directory_handle != (int)fd_pending) return False; - - DEBUG(3,("kernel change notify on %s fd=%d\n", path, (int)fd_pending)); - - close((int)fd_pending); - fd_pending = (sig_atomic_t)-1; - data->directory_handle = -1; - signals_processed++; + BlockSignals(True, RT_SIGNAL_NOTIFY); + for (i = 0; i < signals_received; i++) { + if (data->directory_handle == (int)fd_pending_array[i]) { + DEBUG(3,("kernel_check_notify: kernel change notify on %s fd[%d]=%d (signals_received=%d)\n", + path, i, (int)fd_pending_array[i], (int)signals_received )); + + close((int)fd_pending_array[i]); + fd_pending_array[i] = (SIG_ATOMIC_T)-1; + if (signals_received - i - 1) { + memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + } + data->directory_handle = -1; + signals_received--; + ret = True; + break; + } + } BlockSignals(False, RT_SIGNAL_NOTIFY); - return True; + return ret; } /**************************************************************************** -remove a change notify data structure + Remove a change notify data structure. *****************************************************************************/ + static void kernel_remove_notify(void *datap) { struct change_data *data = (struct change_data *)datap; int fd = data->directory_handle; if (fd != -1) { - if (fd == (int)fd_pending) { - fd_pending = (sig_atomic_t)-1; - signals_processed++; - BlockSignals(False, RT_SIGNAL_NOTIFY); + int i; + BlockSignals(True, RT_SIGNAL_NOTIFY); + for (i = 0; i < signals_received; i++) { + if (fd == (int)fd_pending_array[i]) { + close(fd); + fd_pending_array[i] = (SIG_ATOMIC_T)-1; + if (signals_received - i - 1) { + memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + } + data->directory_handle = -1; + signals_received--; + break; + } } - close(fd); + BlockSignals(False, RT_SIGNAL_NOTIFY); } SAFE_FREE(data); - DEBUG(3,("removed kernel change notify fd=%d\n", fd)); + DEBUG(3,("kernel_remove_notify: fd=%d\n", fd)); } - /**************************************************************************** -register a change notify request + Register a change notify request. *****************************************************************************/ + static void *kernel_register_notify(connection_struct *conn, char *path, uint32 flags) { struct change_data data; int fd; unsigned long kernel_flags; - fd = conn->vfs_ops.open(conn, path, O_RDONLY, 0); + fd = sys_open(path,O_RDONLY, 0); if (fd == -1) { DEBUG(3,("Failed to open directory %s for change notify\n", path)); return NULL; } - if (fcntl(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) { + if (sys_fcntl_long(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) { DEBUG(3,("Failed to set signal handler for change notify\n")); return NULL; } @@ -147,7 +178,7 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 if (flags & FILE_NOTIFY_CHANGE_EA) kernel_flags |= DN_ATTRIB; if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE; - if (fcntl(fd, F_NOTIFY, kernel_flags) == -1) { + if (sys_fcntl_long(fd, F_NOTIFY, kernel_flags) == -1) { DEBUG(3,("Failed to set async flag for change notify\n")); return NULL; } @@ -161,22 +192,24 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 } /**************************************************************************** -see if the kernel supports change notify + See if the kernel supports change notify. ****************************************************************************/ + static BOOL kernel_notify_available(void) { int fd, ret; fd = open("/tmp", O_RDONLY); - if (fd == -1) return False; /* uggh! */ - ret = fcntl(fd, F_NOTIFY, 0); + if (fd == -1) + return False; /* uggh! */ + ret = sys_fcntl_long(fd, F_NOTIFY, 0); close(fd); return ret == 0; } - /**************************************************************************** -setup kernel based change notify + Setup kernel based change notify. ****************************************************************************/ + struct cnotify_fns *kernel_notify_init(void) { static struct cnotify_fns cnotify; @@ -190,7 +223,8 @@ struct cnotify_fns *kernel_notify_init(void) return NULL; } - if (!kernel_notify_available()) return NULL; + if (!kernel_notify_available()) + return NULL; cnotify.register_notify = kernel_register_notify; cnotify.check_notify = kernel_check_notify; @@ -200,7 +234,6 @@ struct cnotify_fns *kernel_notify_init(void) return &cnotify; } - #else void notify_kernel_dummy(void) {} #endif /* HAVE_KERNEL_CHANGE_NOTIFY */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index edee14513c..e0a0da7a75 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -454,6 +454,7 @@ to open_mode 0x%x\n", (unsigned long)*desired_access, (unsigned long)share_acces /**************************************************************************** Reply to an NT create and X call on a pipe. ****************************************************************************/ + static int nt_open_pipe(char *fname, connection_struct *conn, char *inbuf, char *outbuf, int *ppnum) { @@ -502,7 +503,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, int pnum = -1; char *p = NULL; - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -605,12 +606,13 @@ int reply_ntcreate_and_X(connection_struct *conn, } if(!dir_fsp->is_directory) { + + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + /* * Check to see if this is a mac fork of some kind. */ - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); - if( strchr_m(fname, ':')) { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); @@ -635,10 +637,18 @@ int reply_ntcreate_and_X(connection_struct *conn, dir_name_len++; } - srvstr_pull(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, - -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE); } else { - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + + /* + * Check to see if this is a mac fork of some kind. + */ + + if( strchr_m(fname, ':')) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } } /* @@ -880,29 +890,29 @@ static int do_nt_transact_create_pipe( connection_struct *conn, return ERROR_DOS(ERRDOS,ERRbadaccess); } - srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); - - if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) - return ret; + srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) + return ret; + /* Realloc the size of parameters and data we will return */ params = Realloc(*ppparams, 69); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); - + *ppparams = params; - + memset((char *)params,'\0',69); - + p = params; SCVAL(p,0,NO_OPLOCK_RETURN); - + p += 2; SSVAL(p,0,pnum); p += 2; SIVAL(p,0,FILE_WAS_OPENED); p += 8; - + p += 32; SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ p += 20; @@ -910,12 +920,12 @@ static int do_nt_transact_create_pipe( connection_struct *conn, SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); /* Device state. */ SSVAL(p,2, 0x5FF); /* ? */ - + DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); - + /* Send the required number of replies */ send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); - + return -1; } @@ -923,17 +933,15 @@ static int do_nt_transact_create_pipe( connection_struct *conn, Internal fn to set security descriptors. ****************************************************************************/ -static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent, int *pdef_class,uint32 *pdef_code) +static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent) { prs_struct pd; SEC_DESC *psd = NULL; TALLOC_CTX *mem_ctx; BOOL ret; - + if (sd_len == 0) { - *pdef_class = ERRDOS; - *pdef_code = ERRbadaccess; - return False; + return NT_STATUS_OK; } /* @@ -942,9 +950,7 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security if ((mem_ctx = talloc_init()) == NULL) { DEBUG(0,("set_sd: talloc_init failed.\n")); - *pdef_class = ERRDOS; - *pdef_code = ERRnomem; - return False; + return NT_STATUS_NO_MEMORY; } prs_init(&pd, 0, mem_ctx, UNMARSHALL); @@ -966,11 +972,9 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security * Return access denied for want of a better error message.. */ talloc_destroy(mem_ctx); - *pdef_class = ERRDOS; - *pdef_code = ERRnomem; - return False; + return NT_STATUS_NO_MEMORY; } - + if (psd->off_owner_sid==0) security_info_sent &= ~OWNER_SECURITY_INFORMATION; if (psd->off_grp_sid==0) @@ -981,19 +985,15 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security security_info_sent &= ~DACL_SECURITY_INFORMATION; ret = fsp->conn->vfs_ops.fset_nt_acl( fsp, fsp->fd, security_info_sent, psd); - + if (!ret) { talloc_destroy(mem_ctx); - *pdef_class = ERRDOS; - *pdef_code = ERRnoaccess; - return False; + return NT_STATUS_ACCESS_DENIED; } - + talloc_destroy(mem_ctx); - - *pdef_class = 0; - *pdef_code = 0; - return True; + + return NT_STATUS_OK; } /**************************************************************************** @@ -1005,304 +1005,307 @@ static int call_nt_transact_create(connection_struct *conn, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - pstring fname; - char *params = *ppparams; - char *data = *ppdata; - int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); - /* Breakout the oplock request bits so we can set the - reply bits separately. */ - int oplock_request = 0; - mode_t unixmode; - int fmode=0,rmode=0; - SMB_OFF_T file_len = 0; - SMB_STRUCT_STAT sbuf; - int smb_action = 0; - BOOL bad_path = False; - files_struct *fsp = NULL; - char *p = NULL; - uint32 flags; - uint32 desired_access; - uint32 file_attributes; - uint32 share_access; - uint32 create_disposition; - uint32 create_options; - uint32 sd_len; - uint16 root_dir_fid; - int smb_ofun; - int smb_open_mode; - int smb_attr; - int error_class; - uint32 error_code; - time_t c_time; - - DEBUG(5,("call_nt_transact_create\n")); + pstring fname; + char *params = *ppparams; + char *data = *ppdata; + int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); + /* Breakout the oplock request bits so we can set the reply bits separately. */ + int oplock_request = 0; + mode_t unixmode; + int fmode=0,rmode=0; + SMB_OFF_T file_len = 0; + SMB_STRUCT_STAT sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp = NULL; + char *p = NULL; + uint32 flags; + uint32 desired_access; + uint32 file_attributes; + uint32 share_access; + uint32 create_disposition; + uint32 create_options; + uint32 sd_len; + uint16 root_dir_fid; + int smb_ofun; + int smb_open_mode; + int smb_attr; + time_t c_time; + NTSTATUS nt_status; - /* - * If it's an IPC, use the pipe handler. - */ + DEBUG(5,("call_nt_transact_create\n")); + + /* + * If it's an IPC, use the pipe handler. + */ - if (IS_IPC(conn)) { + if (IS_IPC(conn)) { if (lp_nt_pipe_support()) return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, bufsize, ppsetup, ppparams, ppdata); else return ERROR_DOS(ERRDOS,ERRbadaccess); - } + } - /* - * Ensure minimum number of parameters sent. - */ + /* + * Ensure minimum number of parameters sent. + */ - if(total_parameter_count < 54) { - DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); - return ERROR_DOS(ERRDOS,ERRbadaccess); - } + if(total_parameter_count < 54) { + DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); + return ERROR_DOS(ERRDOS,ERRbadaccess); + } - flags = IVAL(params,0); - desired_access = IVAL(params,8); - file_attributes = IVAL(params,20); - share_access = IVAL(params,24); - create_disposition = IVAL(params,28); - create_options = IVAL(params,32); - sd_len = IVAL(params,36); - root_dir_fid = (uint16)IVAL(params,4); - smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); + flags = IVAL(params,0); + desired_access = IVAL(params,8); + file_attributes = IVAL(params,20); + share_access = IVAL(params,24); + create_disposition = IVAL(params,28); + create_options = IVAL(params,32); + sd_len = IVAL(params,36); + root_dir_fid = (uint16)IVAL(params,4); + smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); - /* - * We need to construct the open_and_X ofun value from the - * NT values, as that's what our code is structured to accept. - */ + /* + * We need to construct the open_and_X ofun value from the + * NT values, as that's what our code is structured to accept. + */ - if((smb_ofun = map_create_disposition( create_disposition )) == -1) - return ERROR_DOS(ERRDOS,ERRbadmem); + if((smb_ofun = map_create_disposition( create_disposition )) == -1) + return ERROR_DOS(ERRDOS,ERRbadmem); - /* - * Get the file name. - */ + /* + * Get the file name. + */ - if(root_dir_fid != 0) { - /* - * This filename is relative to a directory fid. - */ + if(root_dir_fid != 0) { + /* + * This filename is relative to a directory fid. + */ - files_struct *dir_fsp = file_fsp(params,4); - size_t dir_name_len; + files_struct *dir_fsp = file_fsp(params,4); + size_t dir_name_len; - if(!dir_fsp) - return ERROR_DOS(ERRDOS,ERRbadfid); + if(!dir_fsp) + return ERROR_DOS(ERRDOS,ERRbadfid); - if(!dir_fsp->is_directory) { - /* - * Check to see if this is a mac fork of some kind. - */ + if(!dir_fsp->is_directory) { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); - if( strchr_m(fname, ':')) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } + /* + * Check to see if this is a mac fork of some kind. + */ - return ERROR_DOS(ERRDOS,ERRbadfid); - } + if( strchr_m(fname, ':')) + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - /* - * Copy in the base directory name. - */ + return ERROR_DOS(ERRDOS,ERRbadfid); + } - pstrcpy( fname, dir_fsp->fsp_name ); - dir_name_len = strlen(fname); + /* + * Copy in the base directory name. + */ - /* - * Ensure it ends in a '\'. - */ + pstrcpy( fname, dir_fsp->fsp_name ); + dir_name_len = strlen(fname); - if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { - pstrcat(fname, "\\"); - dir_name_len++; - } + /* + * Ensure it ends in a '\'. + */ - srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, - -1, STR_TERMINATE); - } else { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE); - } + if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { + pstrcat(fname, "\\"); + dir_name_len++; + } - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ + srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, + total_parameter_count-53, STR_TERMINATE); + } else { + srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + + /* + * Check to see if this is a mac fork of some kind. + */ - if((smb_open_mode = map_share_mode( fname, create_options, &desired_access, - share_access, file_attributes)) == -1) - return ERROR_DOS(ERRDOS,ERRbadaccess); + if( strchr_m(fname, ':')) + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + /* + * Now contruct the smb_open_mode value from the desired access + * and the share access. + */ - /* - * Check if POSIX semantics are wanted. - */ + if((smb_open_mode = map_share_mode( fname, create_options, &desired_access, + share_access, file_attributes)) == -1) + return ERROR_DOS(ERRDOS,ERRbadaccess); - set_posix_case_semantics(file_attributes); + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + + /* + * Check if POSIX semantics are wanted. + */ + + set_posix_case_semantics(file_attributes); - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); + unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,smb_attr | aARCH, fname); + unixmode = unix_mode(conn,smb_attr | aARCH, fname); - /* - * If it's a request for a directory open, deal with it separately. - */ + /* + * If it's a request for a directory open, deal with it separately. + */ - if(create_options & FILE_DIRECTORY_FILE) { + if(create_options & FILE_DIRECTORY_FILE) { - oplock_request = 0; + oplock_request = 0; - /* - * We will get a create directory here if the Win32 - * app specified a security descriptor in the - * CreateDirectory() call. - */ + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); - if(!fsp) { - restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if(!fsp) { + restore_case_semantics(file_attributes); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - } else { + } else { - /* - * Ordinary file case. - */ + /* + * Ordinary file case. + */ - fsp = open_file_shared1(conn,fname,&sbuf,desired_access, - smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + fsp = open_file_shared1(conn,fname,&sbuf,desired_access, + smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); - if (!fsp) { + if (!fsp) { - if(errno == EISDIR) { + if(errno == EISDIR) { - /* - * Fail the open if it was explicitly a non-directory file. - */ + /* + * Fail the open if it was explicitly a non-directory file. + */ - if (create_options & FILE_NON_DIRECTORY_FILE) { - restore_case_semantics(file_attributes); - SSVAL(outbuf, smb_flg2, - SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); - } + if (create_options & FILE_NON_DIRECTORY_FILE) { + restore_case_semantics(file_attributes); + SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); + } - oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); + oplock_request = 0; + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); - if(!fsp) { + if(!fsp) { + restore_case_semantics(file_attributes); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { restore_case_semantics(file_attributes); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - } else { - - restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } + } - file_len = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) - fmode = FILE_ATTRIBUTE_NORMAL; + file_len = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + if(fmode == 0) + fmode = FILE_ATTRIBUTE_NORMAL; - if (fmode & aDIR) { - close_file(fsp,False); - restore_case_semantics(file_attributes); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } + if (fmode & aDIR) { + close_file(fsp,False); + restore_case_semantics(file_attributes); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ - if (oplock_request && lp_fake_oplocks(SNUM(conn))) - smb_action |= EXTENDED_OPLOCK_GRANTED; + if (oplock_request && lp_fake_oplocks(SNUM(conn))) + smb_action |= EXTENDED_OPLOCK_GRANTED; - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - smb_action |= EXTENDED_OPLOCK_GRANTED; - } - - /* - * Now try and apply the desired SD. - */ + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + smb_action |= EXTENDED_OPLOCK_GRANTED; + } - if (!set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION, &error_class, &error_code)) { - close_file(fsp,False); - restore_case_semantics(file_attributes); - return ERROR_DOS(error_class, error_code); - } + /* + * Now try and apply the desired SD. + */ - restore_case_semantics(file_attributes); + if (sd_len && !NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { + close_file(fsp,False); + restore_case_semantics(file_attributes); + return ERROR_NT(nt_status); + } + + restore_case_semantics(file_attributes); - /* Realloc the size of parameters and data we will return */ - params = Realloc(*ppparams, 69); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + /* Realloc the size of parameters and data we will return */ + params = Realloc(*ppparams, 69); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; + *ppparams = params; - memset((char *)params,'\0',69); + memset((char *)params,'\0',69); - p = params; - if (smb_action & EXTENDED_OPLOCK_GRANTED) - SCVAL(p,0, BATCH_OPLOCK_RETURN); - else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) - SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); - else - SCVAL(p,0,NO_OPLOCK_RETURN); + p = params; + if (smb_action & EXTENDED_OPLOCK_GRANTED) + SCVAL(p,0, BATCH_OPLOCK_RETURN); + else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); + else + SCVAL(p,0,NO_OPLOCK_RETURN); - p += 2; - SSVAL(p,0,fsp->fnum); - p += 2; - SIVAL(p,0,smb_action); - p += 8; - - /* Create time. */ - c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - - if (lp_dos_filetime_resolution(SNUM(conn))) { - c_time &= ~1; - sbuf.st_atime &= ~1; - sbuf.st_mtime &= ~1; - sbuf.st_mtime &= ~1; - } + p += 2; + SSVAL(p,0,fsp->fnum); + p += 2; + SIVAL(p,0,smb_action); + p += 8; - put_long_date(p,c_time); - p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ - p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ - p += 4; - SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); - p += 8; - SOFF_T(p,0,file_len); - - DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); - - /* Send the required number of replies */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); + /* Create time. */ + c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - return -1; + if (lp_dos_filetime_resolution(SNUM(conn))) { + c_time &= ~1; + sbuf.st_atime &= ~1; + sbuf.st_mtime &= ~1; + sbuf.st_mtime &= ~1; + } + + put_long_date(p,c_time); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fmode); /* File Attributes. */ + p += 4; + SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); + p += 8; + SOFF_T(p,0,file_len); + + DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); + + /* Send the required number of replies */ + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); + + return -1; } /**************************************************************************** @@ -1560,8 +1563,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); files_struct *fsp = NULL; uint32 security_info_sent = 0; - int error_class; - uint32 error_code; + NTSTATUS nt_status; if(total_parameter_count < 8) return ERROR_DOS(ERRDOS,ERRbadfunc); @@ -1577,8 +1579,11 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, (unsigned int)security_info_sent )); - if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code)) - return ERROR_DOS(error_class, error_code); + if (total_data_count == 0) + return ERROR_DOS(ERRDOS, ERRbadaccess); + + if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, total_data_count, security_info_sent))) + return ERROR_NT(nt_status); done: @@ -1589,18 +1594,19 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, /**************************************************************************** Reply to IOCTL - not implemented - no plans. ****************************************************************************/ + static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - static BOOL logged_message = False; + static BOOL logged_message = False; - if(!logged_message) { - DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n")); - logged_message = True; /* Only print this once... */ - } - return ERROR_DOS(ERRSRV,ERRnosupport); + if(!logged_message) { + DEBUG(3,("call_nt_transact_ioctl: Currently not implemented.\n")); + logged_message = True; /* Only print this once... */ + } + return ERROR_DOS(ERRSRV,ERRnosupport); } /**************************************************************************** diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 29a854a397..8c6e8ed805 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -87,7 +87,7 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) + const char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { extern struct current_user current_user; pstring fname; @@ -169,11 +169,15 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, if (fsp->fd == -1) ret = vfs_stat(conn, fname, psbuf); - else + else { ret = vfs_fstat(fsp,fsp->fd,psbuf); + /* If we have an fd, this stat should succeed. */ + if (ret == -1) + DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); + } + /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { - DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); fd_close(conn, fsp); return False; } @@ -1046,7 +1050,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ -files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) +files_struct *open_file_fchmod(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { files_struct *fsp = NULL; BOOL fsp_open; @@ -1058,7 +1062,9 @@ files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_ if(!fsp) return NULL; - fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,0); + /* note! we must use a non-zero desired access or we don't get + a real file descriptor. Oh what a twisted web we weave. */ + fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1158,7 +1164,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST */ if(!got_stat) { - DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", + DEBUG(3,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); return NULL; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 23606f1d14..14b243b36e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -72,34 +72,69 @@ BOOL oplock_message_waiting(fd_set *fds) ****************************************************************************/ -BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeout) +BOOL receive_local_message( char *buffer, int buffer_len, int timeout) { struct sockaddr_in from; - int fromlen = sizeof(from); + socklen_t fromlen = sizeof(from); int32 msg_len = 0; + fd_set fds; + int selrtn = -1; + FD_ZERO(&fds); smb_read_error = 0; - if(timeout != 0) { + /* + * We need to check for kernel oplocks before going into the select + * here, as the EINTR generated by the linux kernel oplock may have + * already been eaten. JRA. + */ + + if (koplocks && koplocks->msg_waiting(&fds)) { + return koplocks->receive_message(&fds, buffer, buffer_len); + } + + while (timeout > 0 && selrtn == -1) { struct timeval to; - int selrtn; int maxfd = oplock_sock; + time_t starttime = time(NULL); - if (koplocks && koplocks->notification_fd != -1) { - FD_SET(koplocks->notification_fd, fds); - maxfd = MAX(maxfd, koplocks->notification_fd); - } + FD_ZERO(&fds); + maxfd = setup_oplock_select_set(&fds); to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(maxfd+1,fds,NULL,NULL,&to); + DEBUG(5,("receive_local_message: doing select with timeout of %d ms\n", timeout)); + + selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); if (selrtn == -1 && errno == EINTR) { + /* could be a kernel oplock interrupt */ - if (koplocks && koplocks->msg_waiting(fds)) { - return koplocks->receive_message(fds, buffer, buffer_len); + if (koplocks && koplocks->msg_waiting(&fds)) { + return koplocks->receive_message(&fds, buffer, buffer_len); + } + + /* + * Linux 2.0.x seems to have a bug in that + * it can return -1, EINTR with a timeout of zero. + * Make sure we bail out here with a read timeout + * if we got EINTR on a timeout of 1 or less. + */ + + if (timeout <= 1) { + smb_read_error = READ_TIMEOUT; + return False; } + + /* Not a kernel interrupt - could be a SIGUSR1 message. We must restart. */ + /* We need to decrement the timeout here. */ + timeout -= ((time(NULL) - starttime)*1000); + if (timeout < 0) + timeout = 1; + + DEBUG(5,("receive_local_message: EINTR : new timeout %d ms\n", timeout)); + continue; } /* Check if error */ @@ -116,11 +151,11 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou } } - if (koplocks && koplocks->msg_waiting(fds)) { - return koplocks->receive_message(fds, buffer, buffer_len); + if (koplocks && koplocks->msg_waiting(&fds)) { + return koplocks->receive_message(&fds, buffer, buffer_len); } - if (!FD_ISSET(oplock_sock, fds)) + if (!FD_ISSET(oplock_sock, &fds)) return False; /* @@ -131,7 +166,7 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou /* * Read a loopback udp message. */ - msg_len = recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], + msg_len = sys_recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen); if(msg_len < 0) { @@ -417,7 +452,7 @@ oplocks. Returning success.\n")); toaddr.sin_port = htons(from_port); toaddr.sin_family = AF_INET; - if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", (int)remotepid, strerror(errno))); @@ -930,7 +965,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", (unsigned int)dev, (double)inode, file_id ); } - if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, + if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { if( DEBUGLVL( 0 ) ) { dbgtext( "request_oplock_break: failed when sending a oplock " ); @@ -967,16 +1002,8 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; uint16 reply_from_port; char *reply_msg_start; - fd_set fds; - - FD_ZERO(&fds); - FD_SET(oplock_sock,&fds); - - if (koplocks && koplocks->notification_fd != -1) { - FD_SET(koplocks->notification_fd, &fds); - } - if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply), + if(receive_local_message(op_break_reply, sizeof(op_break_reply), time_left ? time_left * 1000 : 1) == False) { if(smb_read_error == READ_TIMEOUT) { if( DEBUGLVL( 0 ) ) { diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 14f6de27c4..ffcf3d0af4 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -56,7 +56,7 @@ static BOOL irix_oplocks_available(void) unlink(tmpname); - if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) { + if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) { DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ Disabling kernel oplock support.\n" )); close(pfd[0]); @@ -65,7 +65,7 @@ Disabling kernel oplock support.\n" )); return False; } - if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) { + if(sys_fcntl_long(fd, F_OPLKACK, OP_REVOKE) < 0 ) { DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ Disabling kernel oplock support.\n", strerror(errno) )); close(pfd[0]); @@ -99,7 +99,7 @@ static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_le */ if(read(oplock_pipe_read, &dummy, 1) != 1) { - DEBUG(0,("receive_local_message: read of kernel notification failed. \ + DEBUG(0,("irix_oplock_receive_message: read of kernel notification failed. \ Error was %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return False; @@ -111,8 +111,8 @@ Error was %s.\n", strerror(errno) )); * request outstanding. */ - if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { - DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \ + if(sys_fcntl_ptr(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { + DEBUG(0,("irix_oplock_receive_message: fcntl of kernel notification failed. \ Error was %s.\n", strerror(errno) )); if(errno == EAGAIN) { /* @@ -131,12 +131,12 @@ Error was %s.\n", strerror(errno) )); */ if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev, (SMB_INO_T)os.os_ino)) == NULL) { - DEBUG(0,("receive_local_message: unable to find open file with dev = %x, inode = %.0f\n", + DEBUG(0,("irix_oplock_receive_message: unable to find open file with dev = %x, inode = %.0f\n", (unsigned int)os.os_dev, (double)os.os_ino )); return False; } - DEBUG(5,("receive_local_message: kernel oplock break request received for \ + DEBUG(5,("irix_oplock_receive_message: kernel oplock break request received for \ dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); /* @@ -164,21 +164,21 @@ dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->i static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) == -1) { + if (sys_fcntl_long(fsp->fd, F_OPLKREG, oplock_pipe_write) == -1) { if(errno != EAGAIN) { - DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ + DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f, file_id = %ul. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, strerror(errno) )); } else { - DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ + DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f, file_id = %ul. Another process had the file open.\n", fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); } return False; } - DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n", + DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); return True; @@ -195,8 +195,8 @@ static void irix_release_kernel_oplock(files_struct *fsp) * Check and print out the current kernel * oplock state of this file. */ - int state = fcntl(fsp->fd, F_OPLKACK, -1); - dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \ + int state = sys_fcntl_long(fsp->fd, F_OPLKACK, -1); + dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, state ); } @@ -204,9 +204,9 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /* * Remove the kernel oplock on this file. */ - if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { + if(sys_fcntl_long(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { if( DEBUGLVL( 0 )) { - dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); + dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, strerror(errno) ); diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index d946578380..85f89c12a0 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -22,9 +22,9 @@ #if HAVE_KERNEL_OPLOCKS_LINUX -static VOLATILE sig_atomic_t signals_received; -static VOLATILE sig_atomic_t signals_processed; -static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal */ +static SIG_ATOMIC_T signals_received; +#define FD_PENDING_SIZE 100 +static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; #ifndef F_SETLEASE #define F_SETLEASE 1024 @@ -52,9 +52,10 @@ static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal static void signal_handler(int sig, siginfo_t *info, void *unused) { - BlockSignals(True, sig); - fd_pending = (sig_atomic_t)info->si_fd; - signals_received++; + if (signals_received < FD_PENDING_SIZE - 1) { + fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd; + signals_received++; + } /* Else signal is lost. */ sys_select_signal(); } @@ -124,20 +125,28 @@ static int linux_setlease(int fd, int leasetype) static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) { - BOOL ret = True; + int fd; struct files_struct *fsp; - if (signals_received == signals_processed) - return False; + BlockSignals(True, RT_SIGNAL_LEASE); + fd = fd_pending_array[0]; + fsp = file_find_fd(fd); + fd_pending_array[0] = (SIG_ATOMIC_T)-1; + if (signals_received > 1) + memmove((void *)&fd_pending_array[0], (void *)&fd_pending_array[1], + sizeof(SIG_ATOMIC_T)*(signals_received-1)); + signals_received--; + /* now we can receive more signals */ + BlockSignals(False, RT_SIGNAL_LEASE); - if ((fsp = file_find_fd(fd_pending)) == NULL) { - DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd_pending)); - ret = False; - goto out; + if (fsp == NULL) { + DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd)); + return False; } - DEBUG(3,("receive_local_message: kernel oplock break request received for \ -dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode )); + DEBUG(3,("linux_oplock_receive_message: kernel oplock break request received for \ +dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (double)fsp->inode, + fd, fsp->file_id)); /* * Create a kernel oplock break message. @@ -155,13 +164,7 @@ dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode )); memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); - out: - /* now we can receive more signals */ - fd_pending = (sig_atomic_t)-1; - signals_processed++; - BlockSignals(False, RT_SIGNAL_LEASE); - - return ret; + return True; } /**************************************************************************** @@ -171,14 +174,14 @@ dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode )); static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (linux_setlease(fsp->fd, F_WRLCK) == -1) { - DEBUG(3,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ + DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno))); return False; } - DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n", + DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); return True; @@ -196,7 +199,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fd, F_GETLEASE, 0); - dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ + dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, state ); } @@ -206,7 +209,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, */ if (linux_setlease(fsp->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { - dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); + dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, strerror(errno) ); @@ -244,7 +247,7 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i static BOOL linux_oplock_msg_waiting(fd_set *fds) { - return signals_processed != signals_received; + return signals_received != 0; } /**************************************************************************** diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 629157f22d..82c0cef77d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -259,9 +259,19 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) { /* Keep the homedir handy */ const char *homedir = pdb_get_homedir(server_info->sam_account); + const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); + const char *logon_script = pdb_get_logon_script(server_info->sam_account); if (homedir) { vuser->homedir = smb_xstrdup(homedir); } + + if (unix_homedir) { + vuser->unix_homedir = smb_xstrdup(unix_homedir); + } + + if (logon_script) { + vuser->logon_script = smb_xstrdup(logon_script); + } } memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key)); @@ -279,7 +289,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) /* Find all the groups this uid is in and store them. Used by change_to_user() */ initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid); - get_current_groups( &vuser->n_groups, &vuser->groups); + get_current_groups(vuser->gid, &vuser->n_groups, &vuser->groups); if (server_info->ptok) add_supplementary_nt_login_groups(&vuser->n_groups, &vuser->groups, &server_info->ptok); @@ -301,9 +311,11 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) } /* Register a home dir service for this user */ - if ((!vuser->guest) && vuser->homedir && *(vuser->homedir) + if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir) && (lp_servicenumber(vuser->user.unix_name) < 0)) { - add_home_service(vuser->user.unix_name, vuser->homedir); + vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir); + } else { + vuser->homes_snum = -1; } return vuser->vuid; @@ -336,7 +348,7 @@ void add_session_user(char *user) /**************************************************************************** check if a username is valid ****************************************************************************/ -BOOL user_ok(char *user,int snum) +BOOL user_ok(const char *user,int snum) { char **valid, **invalid; BOOL ret; @@ -345,27 +357,27 @@ BOOL user_ok(char *user,int snum) ret = True; if (lp_invalid_users(snum)) { - lp_list_copy(&invalid, lp_invalid_users(snum)); - if (invalid && lp_list_substitute(invalid, "%S", lp_servicename(snum))) { + str_list_copy(&invalid, lp_invalid_users(snum)); + if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { ret = !user_in_list(user, invalid); } } - if (invalid) lp_list_free (&invalid); + if (invalid) str_list_free (&invalid); if (ret && lp_valid_users(snum)) { - lp_list_copy(&valid, lp_valid_users(snum)); - if (valid && lp_list_substitute(valid, "%S", lp_servicename(snum))) { + str_list_copy(&valid, lp_valid_users(snum)); + if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) { ret = user_in_list(user,valid); } } - if (valid) lp_list_free (&valid); + if (valid) str_list_free (&valid); if (ret && lp_onlyuser(snum)) { - char **user_list = lp_list_make (lp_username(snum)); - if (user_list && lp_list_substitute(user_list, "%S", lp_servicename(snum))) { + char **user_list = str_list_make (lp_username(snum)); + if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) { ret = user_in_list(user, user_list); } - if (user_list) lp_list_free (&user_list); + if (user_list) str_list_free (&user_list); } return(ret); @@ -462,42 +474,17 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) ****************************************************************************/ BOOL authorise_login(int snum,char *user, DATA_BLOB password, - BOOL *guest,BOOL *force,uint16 vuid) + BOOL *guest) { BOOL ok = False; - user_struct *vuser = get_valid_user_struct(vuid); - + #if DEBUG_PASSWORD - DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s vuid=%d\n", - user,password.data, vuid)); + DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n", + user,password.data)); #endif *guest = False; - if (GUEST_ONLY(snum)) - *force = True; - - if (!GUEST_ONLY(snum) && (lp_security() > SEC_SHARE)) { - - /* - * We should just use the given vuid from a sessionsetup_and_X. - */ - - if (!vuser) { - DEBUG(1,("authorise_login: refusing user '%s' with no session setup\n", user)); - return False; - } - - if ((!vuser->guest && user_ok(vuser->user.unix_name,snum)) || - (vuser->guest && GUEST_OK(snum))) { - fstrcpy(user,vuser->user.unix_name); - *guest = vuser->guest; - DEBUG(3,("authorise_login: ACCEPTED: validated based on vuid as %sguest \ -(user=%s)\n", vuser->guest ? "" : "non-", user)); - return True; - } - } - /* there are several possibilities: 1) login as the given user with given password 2) login as a previously registered username with the given password @@ -510,84 +497,61 @@ BOOL authorise_login(int snum,char *user, DATA_BLOB password, if the service is guest_only then steps 1 to 5 are skipped */ - if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) { - /* check for a previously registered guest username */ - if (!ok && (vuser != 0) && vuser->guest) { - if (user_ok(vuser->user.unix_name,snum) && - password_ok(vuser->user.unix_name, password)) { - fstrcpy(user, vuser->user.unix_name); - *guest = False; - DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user)); + /* now check the list of session users */ + if (!ok) { + char *auser; + char *user_list = strdup(session_users); + if (!user_list) + return(False); + + for (auser=strtok(user_list,LIST_SEP); !ok && auser; + auser = strtok(NULL,LIST_SEP)) { + fstring user2; + fstrcpy(user2,auser); + if (!user_ok(user2,snum)) + continue; + + if (password_ok(user2,password)) { ok = True; + fstrcpy(user,user2); + DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \ +and given password ok\n", user)); } } - - /* now check the list of session users */ - if (!ok) { - char *auser; - char *user_list = strdup(session_users); - if (!user_list) - return(False); - - for (auser=strtok(user_list,LIST_SEP); !ok && auser; - auser = strtok(NULL,LIST_SEP)) { + + SAFE_FREE(user_list); + } + + /* check the user= fields and the given password */ + if (!ok && lp_username(snum)) { + char *auser; + pstring user_list; + StrnCpy(user_list,lp_username(snum),sizeof(pstring)); + + pstring_sub(user_list,"%S",lp_servicename(snum)); + + for (auser=strtok(user_list,LIST_SEP); auser && !ok; + auser = strtok(NULL,LIST_SEP)) { + if (*auser == '@') { + auser = validate_group(auser+1,password,snum); + if (auser) { + ok = True; + fstrcpy(user,auser); + DEBUG(3,("authorise_login: ACCEPTED: group username \ +and given password ok (%s)\n", user)); + } + } else { fstring user2; fstrcpy(user2,auser); - if (!user_ok(user2,snum)) - continue; - - if (password_ok(user2,password)) { + if (user_ok(user2,snum) && password_ok(user2,password)) { ok = True; fstrcpy(user,user2); - DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \ -and given password ok\n", user)); - } - } - - SAFE_FREE(user_list); - } - - /* check for a previously validated username/password pair */ - if (!ok && (lp_security() > SEC_SHARE) && (vuser != 0) && !vuser->guest && - user_ok(vuser->user.unix_name,snum)) { - fstrcpy(user,vuser->user.unix_name); - *guest = False; - DEBUG(3,("authorise_login: ACCEPTED: validated uid (%s) as non-guest\n", - user)); - ok = True; - } - - /* check the user= fields and the given password */ - if (!ok && lp_username(snum)) { - char *auser; - pstring user_list; - StrnCpy(user_list,lp_username(snum),sizeof(pstring)); - - pstring_sub(user_list,"%S",lp_servicename(snum)); - - for (auser=strtok(user_list,LIST_SEP); auser && !ok; - auser = strtok(NULL,LIST_SEP)) { - if (*auser == '@') { - auser = validate_group(auser+1,password,snum); - if (auser) { - ok = True; - fstrcpy(user,auser); - DEBUG(3,("authorise_login: ACCEPTED: group username \ + DEBUG(3,("authorise_login: ACCEPTED: user list username \ and given password ok (%s)\n", user)); - } - } else { - fstring user2; - fstrcpy(user2,auser); - if (user_ok(user2,snum) && password_ok(user2,password)) { - ok = True; - fstrcpy(user,user2); - DEBUG(3,("authorise_login: ACCEPTED: user list username \ -and given password ok (%s)\n", user)); - } } } } - } /* not guest only */ + } /* check for a normal guest connection */ if (!ok && GUEST_OK(snum)) { diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 6c1e6efa73..f7e9c595c1 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -50,7 +50,7 @@ int reply_open_pipe_and_X(connection_struct *conn, int i; /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9c8835214f..85818d524a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -104,7 +104,7 @@ static void print_canon_ace(canon_ace *pace, int num) dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" ); dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); if (pace->owner_type == UID_ACE) { - char *u_name = uidtoname(pace->unix_ug.uid); + const char *u_name = uidtoname(pace->unix_ug.uid); dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name); } else if (pace->owner_type == GID_ACE) { char *g_name = gidtoname(pace->unix_ug.gid); @@ -439,9 +439,15 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); if (!sid_to_uid( &owner_sid, puser, &sid_type)) { +#if ACL_FORCE_UNMAPPABLE + /* this allows take ownership to work reasonably */ + extern struct current_user current_user; + *puser = current_user.uid; +#else DEBUG(3,("unpack_nt_owners: unable to validate owner sid for %s\n", sid_string_static(&owner_sid))); return False; +#endif } } @@ -453,8 +459,14 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) { +#if ACL_FORCE_UNMAPPABLE + /* this allows take group ownership to work reasonably */ + extern struct current_user current_user; + *pgrp = current_user.gid; +#else DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n")); return False; +#endif } } @@ -467,7 +479,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, Ensure the enforced permissions for this share apply. ****************************************************************************/ -static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type) +static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type) { int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; @@ -486,6 +498,10 @@ static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type) /* Now bounce them into the S_USR space. */ switch(type) { case S_IRUSR: + /* Ensure owner has read access. */ + pace->perms |= S_IRUSR; + if (fsp->is_directory) + pace->perms |= (S_IWUSR|S_IXUSR); and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR); or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR); break; @@ -499,7 +515,34 @@ static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type) break; } - return ((perms & and_bits)|or_bits); + pace->perms = ((pace->perms & and_bits)|or_bits); +} + +/**************************************************************************** + Check if a given uid/SID is in a group gid/SID. This is probably very + expensive and will need optimisation. A *lot* of optimisation :-). JRA. +****************************************************************************/ + +static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) +{ + extern DOM_SID global_sid_World; + fstring u_name; + fstring g_name; + + /* "Everyone" always matches every uid. */ + + if (sid_equal(&group_ace->trustee, &global_sid_World)) + return True; + + fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); + fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid)); + + /* + * Due to the winbind interfaces we need to do this via names, + * not uids/gids. + */ + + return user_in_group_list(u_name, g_name ); } /**************************************************************************** @@ -524,24 +567,16 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, BOOL got_user = False; BOOL got_grp = False; BOOL got_other = False; + canon_ace *pace_other = NULL; + canon_ace *pace_group = NULL; for (pace = *pp_ace; pace; pace = pace->next) { if (pace->type == SMB_ACL_USER_OBJ) { - if (setting_acl) { - /* Ensure owner has read access. */ - pace->perms |= S_IRUSR; - if (fsp->is_directory) - pace->perms |= (S_IWUSR|S_IXUSR); - - /* - * Ensure create mask/force create mode is respected on set. - */ - - pace->perms = apply_default_perms(fsp, pace->perms, S_IRUSR); - } - + if (setting_acl) + apply_default_perms(fsp, pace, S_IRUSR); got_user = True; + } else if (pace->type == SMB_ACL_GROUP_OBJ) { /* @@ -549,8 +584,10 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, */ if (setting_acl) - pace->perms = apply_default_perms(fsp, pace->perms, S_IRGRP); + apply_default_perms(fsp, pace, S_IRGRP); got_grp = True; + pace_group = pace; + } else if (pace->type == SMB_ACL_OTHER) { /* @@ -558,8 +595,9 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, */ if (setting_acl) - pace->perms = apply_default_perms(fsp, pace->perms, S_IROTH); + apply_default_perms(fsp, pace, S_IROTH); got_other = True; + pace_other = pace; } } @@ -574,9 +612,21 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->owner_type = UID_ACE; pace->unix_ug.uid = pst->st_uid; pace->trustee = *pfile_owner_sid; - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); pace->attr = ALLOW_ACE; + if (setting_acl) { + /* If we only got an "everyone" perm, just use that. */ + if (!got_grp && got_other) + pace->perms = pace_other->perms; + else if (got_grp && uid_entry_in_group(pace, pace_group)) + pace->perms = pace_group->perms; + else + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); + apply_default_perms(fsp, pace, S_IRUSR); + } else { + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); + } + DLIST_ADD(*pp_ace, pace); } @@ -591,8 +641,17 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->owner_type = GID_ACE; pace->unix_ug.uid = pst->st_gid; pace->trustee = *pfile_grp_sid; - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); pace->attr = ALLOW_ACE; + if (setting_acl) { + /* If we only got an "everyone" perm, just use that. */ + if (got_other) + pace->perms = pace_other->perms; + else + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); + apply_default_perms(fsp, pace, S_IRGRP); + } else { + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); + } DLIST_ADD(*pp_ace, pace); } @@ -608,8 +667,9 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->owner_type = WORLD_ACE; pace->unix_ug.world = -1; pace->trustee = global_sid_World; - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); pace->attr = ALLOW_ACE; + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); + apply_default_perms(fsp, pace, S_IROTH); DLIST_ADD(*pp_ace, pace); } @@ -918,33 +978,6 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); return True; } -/**************************************************************************** - Check if a given uid/SID is in a group gid/SID. This is probably very - expensive and will need optimisation. A *lot* of optimisation :-). JRA. -****************************************************************************/ - -static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) -{ - extern DOM_SID global_sid_World; - fstring u_name; - fstring g_name; - - /* "Everyone" always matches every uid. */ - - if (sid_equal(&group_ace->trustee, &global_sid_World)) - return True; - - fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); - fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid)); - - /* - * Due to the winbind interfaces we need to do this via names, - * not uids/gids. - */ - - return user_in_group_list(u_name, g_name ); -} - /**************************************************************************** ASCII art time again... JRA :-). @@ -1996,6 +2029,52 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) return sd_size; } +/* + try to chown a file. We will be able to chown it under the following conditions + + 1) if we have root privileges, then it will just work + 2) if we have write permission to the file and dos_filemodes is set + then allow chown to the currently authenticated user. + + */ +static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) +{ + int ret; + extern struct current_user current_user; + files_struct *fsp; + SMB_STRUCT_STAT st; + + /* try the direct way first */ + ret = vfs_chown(conn, fname, uid, gid); + if (ret == 0) + return 0; + + if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) + return -1; + + if (vfs_stat(conn,fname,&st)) + return -1; + + fsp = open_file_fchmod(conn,fname,&st); + if (!fsp) + return -1; + + /* only allow chown to the current user. This is more secure, + and also copes with the case where the SID in a take ownership ACL is + a local SID on the users workstation + */ + uid = current_user.uid; + + become_root(); + /* Keep the current file gid the same. */ + ret = vfswrap_fchown(fsp, fsp->fd, uid, (gid_t)-1); + unbecome_root(); + + close_file_fchmod(fsp); + + return ret; +} + /**************************************************************************** Reply to set a security descriptor on an fsp. security_info_sent is the description of the following NT ACL. @@ -2052,7 +2131,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { + if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); return False; @@ -2308,6 +2387,7 @@ BOOL directory_has_default_acl(connection_struct *conn, const char *fname) if (dir_acl != NULL && (conn->vfs_ops.sys_acl_get_entry(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) has_acl = True; - conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); + if (dir_acl) + conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); return has_acl; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 007621f6bb..43d3c6c531 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -42,8 +42,8 @@ extern int last_message; extern int global_oplock_break; extern userdom_struct current_user_info; extern int smb_read_error; -extern VOLATILE sig_atomic_t reload_after_sighup; -extern VOLATILE sig_atomic_t got_sig_term; +SIG_ATOMIC_T reload_after_sighup; +SIG_ATOMIC_T got_sig_term; extern BOOL global_machine_password_needs_changing; extern fstring global_myworkgroup; extern pstring global_myname; @@ -109,10 +109,12 @@ BOOL push_oplock_pending_smb_message(char *buf, int msg_len) oplock messages, change notify events etc. ****************************************************************************/ -static void async_processing(fd_set *fds, char *buffer, int buffer_len) +static void async_processing(char *buffer, int buffer_len) { + DEBUG(10,("async_processing: Doing async processing.\n")); + /* check for oplock messages (both UDP and kernel) */ - if (receive_local_message(fds, buffer, buffer_len, 0)) { + if (receive_local_message(buffer, buffer_len, 1)) { process_local_message(buffer, buffer_len); } @@ -193,6 +195,27 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ FD_ZERO(&fds); + + /* + * Ensure we process oplock break messages by preference. + * We have to do this before the select, after the select + * and if the select returns EINTR. This is due to the fact + * that the selects called from async_processing can eat an EINTR + * caused by a signal (we can't take the break message there). + * This is hideously complex - *MUST* be simplified for 3.0 ! JRA. + */ + + if (oplock_message_waiting(&fds)) { + DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n")); + async_processing(buffer, buffer_len); + /* + * After async processing we must go and do the select again, as + * the state of the flag in fds for the server file descriptor is + * indeterminate - we may have done I/O on it in the oplock processing. JRA. + */ + goto again; + } + FD_SET(smbd_server_fd(),&fds); maxfd = setup_oplock_select_set(&fds); @@ -206,7 +229,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) is the best we can do until the oplock code knows more about signals */ if (selrtn == -1 && errno == EINTR) { - async_processing(&fds, buffer, buffer_len); + async_processing(buffer, buffer_len); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -235,7 +258,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ if (oplock_message_waiting(&fds)) { - async_processing(&fds, buffer, buffer_len); + async_processing(buffer, buffer_len); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -275,7 +298,6 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) void respond_to_all_remaining_local_messages(void) { char buffer[1024]; - fd_set fds; /* * Assert we have no exclusive open oplocks. @@ -287,24 +309,13 @@ void respond_to_all_remaining_local_messages(void) return; } - /* - * Setup the select read fd set. - */ - - FD_ZERO(&fds); - if(!setup_oplock_select_set(&fds)) - return; - /* * Keep doing receive_local_message with a 1 ms timeout until * we have no more messages. */ - while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) { + while(receive_local_message(buffer, sizeof(buffer), 1)) { /* Deal with oplock break requests from other smbd's. */ process_local_message(buffer, sizeof(buffer)); - - FD_ZERO(&fds); - (void)setup_oplock_select_set(&fds); } return; @@ -829,10 +840,6 @@ set. Ignoring max smbd restriction.\n")); ****************************************************************************/ void process_smb(char *inbuf, char *outbuf) { -#ifdef WITH_SSL - extern BOOL sslEnabled; /* don't use function for performance reasons */ - static int sslConnected = 0; -#endif /* WITH_SSL */ static int trans_num; int msg_type = CVAL(inbuf,0); int32 len = smb_len(inbuf); @@ -860,18 +867,6 @@ void process_smb(char *inbuf, char *outbuf) DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); -#ifdef WITH_SSL - if(sslEnabled && !sslConnected){ - sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type); - if(sslConnected < 0){ /* an error occured */ - exit_server("SSL negotiation failed"); - }else if(sslConnected){ - trans_num++; - return; - } - } -#endif /* WITH_SSL */ - if (msg_type == 0) show_msg(inbuf); else if(msg_type == SMBkeepalive) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fbb981781f..0ccdf7c241 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -163,10 +163,10 @@ int reply_tcon(connection_struct *conn, *service = *password = *dev = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1; - pwlen = srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, service, p, sizeof(service), STR_TERMINATE) + 1; + pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1; p += pwlen; - p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1; p = strrchr_m(service,'\\'); if (p) { @@ -233,7 +233,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } p = smb_buf(inbuf) + passlen; - p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); /* * the service name can be either: \\server\share @@ -377,7 +377,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT sbuf; START_PROFILE(SMBchkpth); - srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); @@ -429,7 +429,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBgetatr); p = smb_buf(inbuf) + 1; - p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -505,7 +505,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBsetatr); p = smb_buf(inbuf) + 1; - p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); unix_convert(fname,conn,0,&bad_path,&sbuf); mode = SVAL(inbuf,smb_vwv0); @@ -542,23 +542,46 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ****************************************************************************/ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = 0; - SMB_BIG_UINT dfree,dsize,bsize; - START_PROFILE(SMBdskattr); - - conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize); - - outsize = set_message(outbuf,5,0,True); + int outsize = 0; + SMB_BIG_UINT dfree,dsize,bsize; + START_PROFILE(SMBdskattr); + + conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize); - SSVAL(outbuf,smb_vwv0,dsize); - SSVAL(outbuf,smb_vwv1,bsize/512); - SSVAL(outbuf,smb_vwv2,512); - SSVAL(outbuf,smb_vwv3,dfree); + outsize = set_message(outbuf,5,0,True); + + if (Protocol <= PROTOCOL_LANMAN2) { + double total_space, free_space; + /* we need to scale this to a number that DOS6 can handle. We + use floating point so we can handle large drives on systems + that don't have 64 bit integers - DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree)); + we end up displaying a maximum of 2G to DOS systems + */ + total_space = dsize * (double)bsize; + free_space = dfree * (double)bsize; - END_PROFILE(SMBdskattr); - return(outsize); + dsize = (total_space+63*512) / (64*512); + dfree = (free_space+63*512) / (64*512); + + if (dsize > 0xFFFF) dsize = 0xFFFF; + if (dfree > 0xFFFF) dfree = 0xFFFF; + + SSVAL(outbuf,smb_vwv0,dsize); + SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */ + SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */ + SSVAL(outbuf,smb_vwv3,dfree); + } else { + SSVAL(outbuf,smb_vwv0,dsize); + SSVAL(outbuf,smb_vwv1,bsize/512); + SSVAL(outbuf,smb_vwv2,512); + SSVAL(outbuf,smb_vwv3,dfree); + } + + DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree)); + + END_PROFILE(SMBdskattr); + return(outsize); } @@ -602,7 +625,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); p = smb_buf(inbuf) + 1; - p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); p++; status_len = SVAL(p, 0); p += 2; @@ -783,7 +806,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(outbuf,1,0,True); p = smb_buf(inbuf) + 1; - p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); p++; status_len = SVAL(p,0); p += 2; @@ -831,7 +854,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); - srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -921,7 +944,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1040,7 +1063,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); createmode = SVAL(inbuf,smb_vwv0); - srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1112,7 +1135,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBctemp); createmode = SVAL(inbuf,smb_vwv0); - srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); pstrcat(fname,"\\TMXXXXXX"); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1370,7 +1393,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dirtype = SVAL(inbuf,smb_vwv0); - srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); @@ -2719,7 +2742,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBmkdir); - srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE); status = mkdir_internal(conn, directory); if (!NT_STATUS_IS_OK(status)) @@ -2880,7 +2903,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SMB_STRUCT_STAT sbuf; START_PROFILE(SMBrmdir); - srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE); RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) @@ -3241,9 +3264,9 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBmv); p = smb_buf(inbuf) + 1; - p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE); p++; - p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); @@ -3373,8 +3396,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, *directory = *mask = 0; p = smb_buf(inbuf); - p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE); - p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE); DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); @@ -3526,7 +3549,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE); if (strlen(newdir) == 0) { ok = True; diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 87bf8b1744..bdcdce6e14 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -132,29 +132,39 @@ static void gain_root(void) Get the list of current groups. ****************************************************************************/ -int get_current_groups(int *p_ngroups, gid_t **p_groups) +int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups) { int i; gid_t grp; - int ngroups = sys_getgroups(0,&grp); - gid_t *groups; + int ngroups; + gid_t *groups = NULL; (*p_ngroups) = 0; (*p_groups) = NULL; - if (ngroups <= 0) - return -1; + /* this looks a little strange, but is needed to cope with + systems that put the current egid in the group list + returned from getgroups() (tridge) */ + save_re_gid(); + set_effective_gid(gid); + setgid(gid); - if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) { + ngroups = sys_getgroups(0,&grp); + if (ngroups <= 0) { + goto fail; + } + + if((groups = (gid_t *)malloc(sizeof(gid_t)*(ngroups+1))) == NULL) { DEBUG(0,("setup_groups malloc fail !\n")); - return -1; + goto fail; } if ((ngroups = sys_getgroups(ngroups,groups)) == -1) { - SAFE_FREE(groups); - return -1; + goto fail; } + restore_re_gid(); + (*p_ngroups) = ngroups; (*p_groups) = groups; @@ -164,7 +174,12 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups) } DEBUG( 3, ( "\n" ) ); - return ngroups; + return ngroups; + +fail: + SAFE_FREE(groups); + restore_re_gid(); + return -1; } /**************************************************************************** @@ -204,7 +219,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) SAFE_FREE(prev_ctx_p->groups); prev_ctx_p->ngroups = 0; - get_current_groups(&prev_ctx_p->ngroups, &prev_ctx_p->groups); + get_current_groups(gid, &prev_ctx_p->ngroups, &prev_ctx_p->groups); done: unbecome_root(); @@ -404,7 +419,7 @@ void init_sec_ctx(void) ctx_p->uid = geteuid(); ctx_p->gid = getegid(); - get_current_groups(&ctx_p->ngroups, &ctx_p->groups); + get_current_groups(ctx_p->gid, &ctx_p->ngroups, &ctx_p->groups); ctx_p->token = NULL; /* Maps to guest user. */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c759f56e0c..6f0d0238b0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -53,7 +53,7 @@ int smbd_server_fd(void) return server_fd; } -void smbd_set_server_fd(int fd) +static void smbd_set_server_fd(int fd) { server_fd = fd; client_setfd(fd); @@ -63,7 +63,7 @@ void smbd_set_server_fd(int fd) Terminate signal. ****************************************************************************/ -VOLATILE sig_atomic_t got_sig_term = 0; +SIG_ATOMIC_T got_sig_term = 0; static void sig_term(void) { @@ -75,7 +75,7 @@ static void sig_term(void) Catch a sighup. ****************************************************************************/ -VOLATILE sig_atomic_t reload_after_sighup = 0; +SIG_ATOMIC_T reload_after_sighup = 0; static void sig_hup(int sig) { @@ -382,6 +382,8 @@ BOOL reload_services(BOOL test) { BOOL ret; + set_register_printer_fn(); + if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); @@ -531,6 +533,7 @@ void exit_server(char *reason) } locking_end(); + printing_end(); DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); exit(0); @@ -782,15 +785,6 @@ static void usage(char *pname) } #endif -#ifdef WITH_SSL - { - extern BOOL sslEnabled; - sslEnabled = lp_ssl_enabled(); - if(sslEnabled) - sslutil_init(True); - } -#endif /* WITH_SSL */ - fstrcpy(global_myworkgroup, lp_workgroup()); DEBUG(3,( "loaded services\n")); @@ -861,6 +855,9 @@ static void usage(char *pname) if (!share_info_db_init()) exit(1); + if (!init_registry()) + exit(1); + if(!initialize_password_db(False)) exit(1); @@ -869,7 +866,7 @@ static void usage(char *pname) /* possibly reload the services file. */ reload_services(True); - if(!pdb_generate_sam_sid()) { + if(!get_global_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0ae49b7adf..9ac610ab5a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -78,12 +78,9 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) Add a home service. Returns the new service number or -1 if fail. ****************************************************************************/ -int add_home_service(const char *service, const char *homedir) +int add_home_service(const char *service, const char *username, const char *homedir) { int iHomeService; - int iService; - fstring new_service; - fstring domain; if (!service || !homedir) return -1; @@ -98,11 +95,19 @@ int add_home_service(const char *service, const char *homedir) * include any macros. */ - split_domain_and_name(service, domain, new_service); - lp_add_home(new_service, iHomeService, homedir); - iService = lp_servicenumber(new_service); + { + const char *p = strchr(service,*lp_winbind_separator()); + + /* We only want the 'user' part of the string */ + if (p) { + service = p + 1; + } + } + + lp_add_home(service, iHomeService, username, homedir); + + return lp_servicenumber(service); - return iService; } @@ -122,7 +127,7 @@ int find_service(fstring service) /* now handle the special case of a home directory */ if (iService < 0) { - char *phome_dir = get_user_service_home_dir(service); + char *phome_dir = get_user_home_dir(service); if(!phome_dir) { @@ -131,13 +136,13 @@ int find_service(fstring service) * be a Windows to unix mapped user name. */ if(map_username(service)) - phome_dir = get_user_service_home_dir(service); + phome_dir = get_user_home_dir(service); } DEBUG(3,("checking for home directory %s gave %s\n",service, phome_dir?phome_dir:"(NULL)")); - iService = add_home_service(service,phome_dir); + iService = add_home_service(service,service /* 'username' */, phome_dir); } /* If we still don't have a service, attempt to add it as a printer. */ @@ -213,7 +218,7 @@ int find_service(fstring service) do some basic sainity checks on the share. This function modifies dev, ecode. ****************************************************************************/ -static NTSTATUS share_sanity_checks(int snum, const char* service, pstring dev) +static NTSTATUS share_sanity_checks(int snum, pstring dev) { if (!lp_snum_ok(snum) || @@ -223,7 +228,7 @@ static NTSTATUS share_sanity_checks(int snum, const char* service, pstring dev) } /* you can only connect to the IPC$ service as an ipc device */ - if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) + if (strequal(lp_fstype(snum), "IPC")) pstrcpy(dev,"IPC"); if (dev[0] == '?' || !dev[0]) { @@ -261,24 +266,24 @@ static void set_read_only(connection_struct *conn) if (!service) return; - lp_list_copy(&list, lp_readlist(conn->service)); + str_list_copy(&list, lp_readlist(conn->service)); if (list) { - if (!lp_list_substitute(list, "%S", service)) { + if (!str_list_substitute(list, "%S", service)) { DEBUG(0, ("ERROR: read list substitution failed\n")); } if (user_in_list(conn->user, list)) conn->read_only = True; - lp_list_free(&list); + str_list_free(&list); } - lp_list_copy(&list, lp_writelist(conn->service)); + str_list_copy(&list, lp_writelist(conn->service)); if (list) { - if (!lp_list_substitute(list, "%S", service)) { + if (!str_list_substitute(list, "%S", service)) { DEBUG(0, ("ERROR: write list substitution failed\n")); } if (user_in_list(conn->user, list)) conn->read_only = False; - lp_list_free(&list); + str_list_free(&list); } } @@ -314,89 +319,26 @@ static void set_admin_user(connection_struct *conn) } /**************************************************************************** - Make a connection to a service. - * - * @param service (May be modified to canonical form???) + Make a connection, given the snum to connect to, and the vuser of the + connecting user if appropriate. ****************************************************************************/ -connection_struct *make_connection(char *service, DATA_BLOB password, - char *dev, uint16 vuid, NTSTATUS *status) +static connection_struct *make_connection_snum(int snum, user_struct *vuser, + DATA_BLOB password, + char *dev, NTSTATUS *status) { - int snum; struct passwd *pass = NULL; BOOL guest = False; BOOL force = False; connection_struct *conn; - uid_t euid; - + struct stat st; fstring user; - ZERO_STRUCT(user); - - /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ - if (!non_root_mode() && (euid = geteuid()) != 0) { - DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); - smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); - } - - strlower(service); - - snum = find_service(service); - - if (snum < 0) { - if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { - DEBUG(3,("refusing IPC connection\n")); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - - DEBUG(0,("%s (%s) couldn't find service %s\n", - remote_machine, client_addr(), service)); - *status = NT_STATUS_BAD_NETWORK_NAME; - return NULL; - } - - if (strequal(service,HOMES_NAME)) { - if(lp_security() != SEC_SHARE) { - if (validated_username(vuid)) { - fstring unix_username; - fstrcpy(unix_username,validated_username(vuid)); - return make_connection(unix_username, - password,dev,vuid,status); - } - } else { - /* Security = share. Try with current_user_info.smb_name - * as the username. */ - if (* current_user_info.smb_name) { - fstring unix_username; - fstrcpy(unix_username, - current_user_info.smb_name); - map_username(unix_username); - return make_connection(unix_username, - password,dev,vuid,status); - } - } - } + *user = 0; - if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, service, dev))) { + if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { return NULL; } - /* add it as a possible user name if we - are in share mode security */ - if (lp_security() == SEC_SHARE) { - add_session_user(service); - } - - - /* shall we let them in? */ - if (!authorise_login(snum,user,password,&guest,&force,vuid)) { - DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) ); - *status = NT_STATUS_WRONG_PASSWORD; - return NULL; - } - - add_session_user(user); - conn = conn_new(); if (!conn) { DEBUG(0,("Couldn't find free connection.\n")); @@ -404,20 +346,72 @@ connection_struct *make_connection(char *service, DATA_BLOB password, return NULL; } - /* find out some info about the user */ - pass = smb_getpwnam(user,True); + if (lp_guest_only(snum)) { + char *guestname = lp_guestaccount(); + guest = True; + force = True; + pass = getpwnam_alloc(guestname); + if (!pass) { + DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname)); + conn_free(conn); + *status = NT_STATUS_NO_SUCH_USER; + return NULL; + } + fstrcpy(user,pass->pw_name); + conn->force_user = True; + string_set(&conn->user,pass->pw_name); + passwd_free(&pass); + DEBUG(3,("Guest only user %s\n",user)); + } else if (vuser) { + if (vuser->guest) { + if (!lp_guest_ok(snum)) { + DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)", lp_servicename(snum))); + conn_free(conn); + *status = NT_STATUS_ACCESS_DENIED; + return NULL; + } + } else { + if (!user_ok(vuser->user.unix_name, snum)) { + DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)", vuser->user.unix_name, lp_servicename(snum))); + conn_free(conn); + *status = NT_STATUS_ACCESS_DENIED; + return NULL; + } + } + conn->vuid = vuser->vuid; + conn->uid = vuser->uid; + conn->gid = vuser->gid; + string_set(&conn->user,vuser->user.unix_name); + fstrcpy(user,vuser->user.unix_name); + guest = vuser->guest; + } else if (lp_security() == SEC_SHARE) { + /* add it as a possible user name if we + are in share mode security */ + add_session_user(lp_servicename(snum)); + /* shall we let them in? */ + if (!authorise_login(snum,user,password,&guest)) { + DEBUG( 2, ( "Invalid username/password for [%s]\n", + lp_servicename(snum)) ); + conn_free(conn); + *status = NT_STATUS_WRONG_PASSWORD; + return NULL; + } + pass = Get_Pwnam(user); + conn->force_user = force; + conn->uid = pass->pw_uid; + conn->gid = pass->pw_gid; + string_set(&conn->user, pass->pw_name); + fstrcpy(user, pass->pw_name); - if (pass == NULL) { - DEBUG(0,( "Couldn't find account %s\n",user)); - *status = NT_STATUS_NO_SUCH_USER; + } else { + DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); conn_free(conn); + *status = NT_STATUS_ACCESS_DENIED; return NULL; } - conn->force_user = force; - conn->vuid = vuid; - conn->uid = pass->pw_uid; - conn->gid = pass->pw_gid; + add_session_user(user); + safe_strcpy(conn->client_address, client_addr(), sizeof(conn->client_address)-1); conn->num_files_open = 0; @@ -450,18 +444,21 @@ connection_struct *make_connection(char *service, DATA_BLOB password, pstrcpy(fuser,lp_force_user(snum)); /* Allow %S to be used by force user. */ - pstring_sub(fuser,"%S",service); + pstring_sub(fuser,"%S",lp_servicename(snum)); - pass2 = (struct passwd *)Get_Pwnam_Modify(fuser); + pass2 = (struct passwd *)Get_Pwnam(fuser); if (pass2) { conn->uid = pass2->pw_uid; conn->gid = pass2->pw_gid; - string_set(&conn->user,fuser); - fstrcpy(user,fuser); + string_set(&conn->user,pass2->pw_name); + fstrcpy(user,pass2->pw_name); conn->force_user = True; - DEBUG(3,("Forced user %s\n",fuser)); + DEBUG(3,("Forced user %s\n",user)); } else { DEBUG(1,("Couldn't find user %s\n",fuser)); + conn_free(conn); + *status = NT_STATUS_NO_SUCH_USER; + return NULL; } } @@ -483,7 +480,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, BOOL user_must_be_member = False; StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1); - + if (tmp_gname[0] == '+') { user_must_be_member = True; StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2); @@ -491,7 +488,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, StrnCpy(gname,tmp_gname,sizeof(pstring)-1); } /* default service may be a group name */ - pstring_sub(gname,"%S",service); + pstring_sub(gname,"%S",lp_servicename(snum)); gid = nametogid(gname); if (gid != (gid_t)-1) { @@ -512,6 +509,9 @@ connection_struct *make_connection(char *service, DATA_BLOB password, } } else { DEBUG(1,("Couldn't find group %s\n",gname)); + conn_free(conn); + *status = NT_STATUS_NO_SUCH_GROUP; + return NULL; } } #endif /* HAVE_GETGRNAM */ @@ -519,7 +519,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, { pstring s; pstrcpy(s,lp_pathname(snum)); - standard_sub_conn(conn,s); + standard_sub_conn(conn,s,sizeof(s)); string_set(&conn->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); } @@ -531,7 +531,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, /* Find all the groups this uid is in and store them. Used by change_to_user() */ initialise_groups(conn->user, conn->uid, conn->gid); - get_current_groups(&conn->ngroups,&conn->groups); + get_current_groups(conn->gid, &conn->ngroups,&conn->groups); conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups, @@ -544,15 +544,15 @@ connection_struct *make_connection(char *service, DATA_BLOB password, */ { - BOOL can_write = share_access_check(conn, snum, vuid, FILE_WRITE_DATA); + BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(conn, snum, vuid, FILE_READ_DATA)) { + if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) { /* No access, read or write. */ - *status = NT_STATUS_ACCESS_DENIED; DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", - service )); + lp_servicename(snum))); conn_free(conn); + *status = NT_STATUS_ACCESS_DENIED; return NULL; } else { conn->read_only = True; @@ -564,6 +564,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, if (!smbd_vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); conn_free(conn); + *status = NT_STATUS_UNSUCCESSFUL; return NULL; } @@ -574,8 +575,8 @@ connection_struct *make_connection(char *service, DATA_BLOB password, lp_max_connections(SNUM(conn)), False)) { DEBUG(1,("too many connections - rejected\n")); - *status = NT_STATUS_INSUFFICIENT_RESOURCES; conn_free(conn); + *status = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } @@ -585,7 +586,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password, int ret; pstring cmd; pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); - standard_sub_conn(conn,cmd); + standard_sub_conn(conn,cmd,sizeof(cmd)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { @@ -605,16 +606,16 @@ connection_struct *make_connection(char *service, DATA_BLOB password, *status = NT_STATUS_LOGON_FAILURE; return NULL; } - + /* Remember that a different vuid can connect later without these checks... */ - + /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "preexec = " line */ if (*lp_preexec(SNUM(conn))) { int ret; pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); - standard_sub_conn(conn,cmd); + standard_sub_conn(conn,cmd,sizeof(cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); @@ -625,7 +626,12 @@ connection_struct *make_connection(char *service, DATA_BLOB password, return NULL; } } - + +#if CHECK_PATH_ON_TCONX + /* win2000 does not check the permissions on the directory + during the tree connect, instead relying on permission + check during individual operations. To match this behaviour + I have disabled this chdir check (tridge) */ if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", remote_machine, conn->client_address, @@ -636,12 +642,23 @@ connection_struct *make_connection(char *service, DATA_BLOB password, *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } +#else + /* the alternative is just to check the directory exists */ + if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { + DEBUG(0,("%s is not a directory\n", conn->connectpath)); + change_to_root_user(); + yield_connection(conn, lp_servicename(SNUM(conn))); + conn_free(conn); + *status = NT_STATUS_BAD_NETWORK_NAME; + return NULL; + } +#endif string_set(&conn->origpath,conn->connectpath); #if SOFTLINK_OPTIMISATION - /* resolve any soft links early */ - { + /* resolve any soft links early if possible */ + if (vfs_ChDir(conn,conn->connectpath) == 0) { pstring s; pstrcpy(s,conn->connectpath); vfs_GetWd(conn,s); @@ -674,11 +691,11 @@ connection_struct *make_connection(char *service, DATA_BLOB password, /* Invoke VFS make connection hook */ if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn, service, user) < 0) { + if (conn->vfs_ops.connect(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); - *status = NT_STATUS_UNSUCCESSFUL; change_to_root_user(); conn_free(conn); + *status = NT_STATUS_UNSUCCESSFUL; return NULL; } } @@ -689,6 +706,130 @@ connection_struct *make_connection(char *service, DATA_BLOB password, return(conn); } +/*************************************************************************************** + Simple wrapper function for make_connection() to include a call to + vfs_chdir() + **************************************************************************************/ + +connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password, + char *dev, uint16 vuid, NTSTATUS *status) +{ + connection_struct *conn = NULL; + + conn = make_connection(service_in, password, dev, vuid, status); + + /* + * make_connection() does not change the directory for us any more + * so we have to do it as a separate step --jerry + */ + + if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { + DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n", + conn->connectpath,strerror(errno))); + yield_connection(conn, lp_servicename(SNUM(conn))); + conn_free(conn); + *status = NT_STATUS_UNSUCCESSFUL; + return NULL; + } + + return conn; +} + +/**************************************************************************** + Make a connection to a service. + * + * @param service +****************************************************************************/ + +connection_struct *make_connection(const char *service_in, DATA_BLOB password, + char *dev, uint16 vuid, NTSTATUS *status) +{ + uid_t euid; + user_struct *vuser = NULL; + pstring service; + int snum = -1; + + /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ + if (!non_root_mode() && (euid = geteuid()) != 0) { + DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); + smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); + } + + if(lp_security() != SEC_SHARE) { + vuser = get_valid_user_struct(vuid); + if (!vuser) { + DEBUG(1,("make_connection: refusing to connect with no session setup\n")); + return NULL; + } + } + + /* Logic to try and connect to the correct [homes] share, preferably without too many + getpwnam() lookups. This is particulary nasty for winbind usernames, where the + share name isn't the same as unix username. + + The snum of the homes share is stored on the vuser at session setup time. + */ + + if (strequal(service_in,HOMES_NAME)) { + if(lp_security() != SEC_SHARE) { + DATA_BLOB no_pw = data_blob(NULL, 0); + if (vuser->homes_snum != -1) { + DEBUG(5, ("making a connection to [homes] service created at session setup time\n")); + return make_connection_snum(vuser->homes_snum, + vuser, no_pw, + dev, status); + } + } else { + /* Security = share. Try with current_user_info.smb_name + * as the username. */ + if (*current_user_info.smb_name) { + fstring unix_username; + fstrcpy(unix_username, + current_user_info.smb_name); + map_username(unix_username); + snum = find_service(unix_username); + } + if (snum != -1) { + DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in)); + return make_connection_snum(snum, NULL, + password, + dev, status); + } + } + } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) + && strequal(service, lp_servicename(vuser->homes_snum))) { + DATA_BLOB no_pw = data_blob(NULL, 0); + DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service)); + return make_connection_snum(vuser->homes_snum, + vuser, no_pw, + dev, status); + } + + pstrcpy(service, service_in); + + strlower(service); + + snum = find_service(service); + + if (snum < 0) { + if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { + DEBUG(3,("refusing IPC connection to %s\n", service)); + *status = NT_STATUS_ACCESS_DENIED; + return NULL; + } + + DEBUG(0,("%s (%s) couldn't find service %s\n", + remote_machine, client_addr(), service)); + *status = NT_STATUS_BAD_NETWORK_NAME; + return NULL; + } + + DEBUG(5, ("making a connection to 'normal' service %s\n", service)); + + return make_connection_snum(snum, vuser, + password, + dev, status); +} /**************************************************************************** close a cnum @@ -721,7 +862,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_user(conn, vuid)) { pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); - standard_sub_conn(conn,cmd); + standard_sub_conn(conn,cmd,sizeof(cmd)); smbrun(cmd,NULL); change_to_root_user(); } @@ -731,8 +872,12 @@ void close_cnum(connection_struct *conn, uint16 vuid) if (*lp_rootpostexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); - standard_sub_conn(conn,cmd); + standard_sub_conn(conn,cmd,sizeof(cmd)); smbrun(cmd,NULL); } + + /* make sure we leave the directory available for unmount */ + vfs_ChDir(conn, "/"); + conn_free(conn); } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 05a7b24da2..dade953ec1 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -163,16 +163,54 @@ void session_yield(user_struct *vuser) tdb_delete(tdb, key); } -BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state) +static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state) { - if (!tdb) { - DEBUG(3, ("No tdb opened\n")); - return False; - } + if (!tdb) { + DEBUG(3, ("No tdb opened\n")); + return False; + } - tdb_traverse(tdb, fn, state); - return True; + tdb_traverse(tdb, fn, state); + return True; } +struct session_list { + int count; + struct sessionid *sessions; +}; + +static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *state) +{ + struct session_list *sesslist = (struct session_list *) state; + const struct sessionid *current = (const struct sessionid *) dbuf.dptr; + + sesslist->count += 1; + sesslist->sessions = REALLOC(sesslist->sessions, sesslist->count * + sizeof(struct sessionid)); + + memcpy(&sesslist->sessions[sesslist->count - 1], current, + sizeof(struct sessionid)); + DEBUG(7,("gather_sessioninfo session from %s@%s\n", + current->username, current->remote_machine)); + return 0; +} +int list_sessions(struct sessionid **session_list) +{ + struct session_list sesslist; + + sesslist.count = 0; + sesslist.sessions = NULL; + + if (!session_traverse(gather_sessioninfo, (void *) &sesslist)) { + DEBUG(3, ("Session traverse failed\n")); + SAFE_FREE(sesslist.sessions); + *session_list = NULL; + return 0; + } + *session_list = sesslist.sessions; + return sesslist.count; +} + diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 899c9174b2..867b00ff5c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -120,7 +120,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ads = ads_init(NULL, NULL, NULL, NULL); + ads = ads_init_simple(); ret = ads_verify_ticket(ads, &ticket, &client, &auth_data); if (!NT_STATUS_IS_OK(ret)) { @@ -235,11 +235,12 @@ static int reply_spnego_negotiate(connection_struct *conn, char *OIDs[ASN1_MAX_OIDS]; DATA_BLOB secblob; int i; - uint32 ntlmssp_command, neg_flags; - DATA_BLOB sess_key, chal, spnego_chal; + uint32 ntlmssp_command, neg_flags, chal_flags; + DATA_BLOB chal, spnego_chal, extra_data; const uint8 *cryptkey; BOOL got_kerberos = False; NTSTATUS nt_status; + extern pstring global_myname; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { @@ -274,18 +275,23 @@ static int reply_spnego_negotiate(connection_struct *conn, "NTLMSSP", &ntlmssp_command, &neg_flags, - &sess_key)) { + &extra_data)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + + DEBUG(5, ("Extra data: \n")); + dump_data(5, extra_data.data, extra_data.length); data_blob_free(&secblob); - data_blob_free(&sess_key); + data_blob_free(&extra_data); if (ntlmssp_command != NTLMSSP_NEGOTIATE) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); + DEBUG(3,("Got neg_flags=0x%08x\n", neg_flags)); + + debug_ntlmssp_flags(neg_flags); if (ntlmssp_auth_context) { (ntlmssp_auth_context->free)(&ntlmssp_auth_context); @@ -300,22 +306,47 @@ static int reply_spnego_negotiate(connection_struct *conn, /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ - neg_flags = NTLMSSP_NEGOTIATE_UNICODE | + chal_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_LM_KEY | - NTLMSSP_NEGOTIATE_NTLM; - - msrpc_gen(&chal, "Cddddbdddd", - "NTLMSSP", - NTLMSSP_CHALLENGE, - 0, - 0x30, /* ?? */ - neg_flags, - cryptkey, 8, - 0, 0, 0, - 0x3000); /* ?? */ + NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_CHAL_TARGET_INFO; + + { + DATA_BLOB domain_blob, netbios_blob, realm_blob; + + msrpc_gen(&domain_blob, + "U", + lp_workgroup()); + + msrpc_gen(&netbios_blob, + "U", + global_myname); + + msrpc_gen(&realm_blob, + "U", + lp_realm()); + + + msrpc_gen(&chal, "CddddbBBBB", + "NTLMSSP", + NTLMSSP_CHALLENGE, + 0, + 0x30, /* ?? */ + chal_flags, + cryptkey, 8, + domain_blob.data, domain_blob.length, + domain_blob.data, domain_blob.length, + netbios_blob.data, netbios_blob.length, + realm_blob.data, realm_blob.length); + + data_blob_free(&domain_blob); + data_blob_free(&netbios_blob); + data_blob_free(&realm_blob); + } if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) { DEBUG(3,("Failed to generate challenge\n")); + data_blob_free(&chal); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -346,10 +377,15 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, int sess_vuid; BOOL as_guest; uint32 auth_flags = AUTH_FLAG_NONE; - auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; + /* we must have setup the auth context by now */ + if (!ntlmssp_auth_context) { + DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n")); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + if (!spnego_parse_auth(blob1, &auth)) { #if 0 file_save("auth.dat", blob1.data, blob1.length); @@ -606,7 +642,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, plaintext_password.data[passlen1] = 0; } - srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE); + srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE); *domain = 0; } else { @@ -669,14 +705,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } p += passlen1 + passlen2; - p += srvstr_pull(inbuf, user, p, sizeof(user), -1, - STR_TERMINATE); - p += srvstr_pull(inbuf, domain, p, sizeof(domain), - -1, STR_TERMINATE); - p += srvstr_pull(inbuf, native_os, p, sizeof(native_os), - -1, STR_TERMINATE); - p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman), - -1, STR_TERMINATE); + p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", domain,native_os,native_lanman)); } diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 90da422f13..36fecf5bd2 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -30,3 +30,12 @@ int srvstr_pull(void *base_ptr, char *dest, const void *src, int dest_len, int s { return pull_string(base_ptr, dest, src, dest_len, src_len, flags); } + +/* pull a string from the smb_buf part of a packet. In this case the + string can either be null terminated or it can be terminated by the + end of the smbbuf area +*/ +int srvstr_pull_buf(void *inbuf, char *dest, const void *src, int dest_len, int flags) +{ + return pull_string(inbuf, dest, src, dest_len, smb_bufrem(inbuf, src), flags); +} diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1972e9c8c8..f1dfb39aac 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -37,255 +37,261 @@ extern pstring global_myname; HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_trans2_replies(char *outbuf, int bufsize, char *params, - int paramsize, char *pdata, int datasize) +static int send_trans2_replies(char *outbuf, + int bufsize, + char *params, + int paramsize, + char *pdata, + int datasize) { - /* As we are using a protocol > LANMAN1 then the max_send - variable must have been set in the sessetupX call. - This takes precedence over the max_xmit field in the - global struct. These different max_xmit variables should - be merged as this is now too confusing */ - - extern int max_send; - int data_to_send = datasize; - int params_to_send = paramsize; - int useable_space; - char *pp = params; - char *pd = pdata; - int params_sent_thistime, data_sent_thistime, total_sent_thistime; - int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */ - int data_alignment_offset = 0; - - /* Initially set the wcnt area to be 10 - this is true for all - trans2 replies */ - set_message(outbuf,10,0,True); - - /* If there genuinely are no parameters or data to send just send - the empty packet */ - if(params_to_send == 0 && data_to_send == 0) - { - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans2_replies: send_smb failed."); - return 0; - } - - /* When sending params and data ensure that both are nicely aligned */ - /* Only do this alignment when there is also data to send - else - can cause NT redirector problems. */ - if (((params_to_send % 4) != 0) && (data_to_send != 0)) - data_alignment_offset = 4 - (params_to_send % 4); - - /* Space is bufsize minus Netbios over TCP header minus SMB header */ - /* The alignment_offset is to align the param bytes on an even byte - boundary. NT 4.0 Beta needs this to work correctly. */ - useable_space = bufsize - ((smb_buf(outbuf)+ - alignment_offset+data_alignment_offset) - - outbuf); - - /* useable_space can never be more than max_send minus the - alignment offset. */ - useable_space = MIN(useable_space, - max_send - (alignment_offset+data_alignment_offset)); - - - while (params_to_send || data_to_send) - { - /* Calculate whether we will totally or partially fill this packet */ - total_sent_thistime = params_to_send + data_to_send + - alignment_offset + data_alignment_offset; - /* We can never send more than useable_space */ - /* - * Note that 'useable_space' does not include the alignment offsets, - * but we must include the alignment offsets in the calculation of - * the length of the data we send over the wire, as the alignment offsets - * are sent here. Fix from Marc_Jacobsen@hp.com. - */ - total_sent_thistime = MIN(total_sent_thistime, useable_space+ - alignment_offset + data_alignment_offset); - - set_message(outbuf, 10, total_sent_thistime, True); - - /* Set total params and data to be sent */ - SSVAL(outbuf,smb_tprcnt,paramsize); - SSVAL(outbuf,smb_tdrcnt,datasize); - - /* Calculate how many parameters and data we can fit into - this packet. Parameters get precedence */ - - params_sent_thistime = MIN(params_to_send,useable_space); - data_sent_thistime = useable_space - params_sent_thistime; - data_sent_thistime = MIN(data_sent_thistime,data_to_send); - - SSVAL(outbuf,smb_prcnt, params_sent_thistime); - - /* smb_proff is the offset from the start of the SMB header to the - parameter bytes, however the first 4 bytes of outbuf are - the Netbios over TCP header. Thus use smb_base() to subtract - them from the calculation */ - - SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); - - if(params_sent_thistime == 0) - SSVAL(outbuf,smb_prdisp,0); - else - /* Absolute displacement of param bytes sent in this packet */ - SSVAL(outbuf,smb_prdisp,pp - params); - - SSVAL(outbuf,smb_drcnt, data_sent_thistime); - if(data_sent_thistime == 0) - { - SSVAL(outbuf,smb_droff,0); - SSVAL(outbuf,smb_drdisp, 0); - } - else - { - /* The offset of the data bytes is the offset of the - parameter bytes plus the number of parameters being sent this time */ - SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - - smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); - SSVAL(outbuf,smb_drdisp, pd - pdata); - } - - /* Copy the param bytes into the packet */ - if(params_sent_thistime) - memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); - /* Copy in the data bytes */ - if(data_sent_thistime) - memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ - data_alignment_offset,pd,data_sent_thistime); - - DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", - params_sent_thistime, data_sent_thistime, useable_space)); - DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", - params_to_send, data_to_send, paramsize, datasize)); - - /* Send the packet */ - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans2_replies: send_smb failed."); - - pp += params_sent_thistime; - pd += data_sent_thistime; - - params_to_send -= params_sent_thistime; - data_to_send -= data_sent_thistime; - - /* Sanity check */ - if(params_to_send < 0 || data_to_send < 0) - { - DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!", - params_to_send, data_to_send)); - return -1; - } - } - - return 0; + /* As we are using a protocol > LANMAN1 then the max_send + variable must have been set in the sessetupX call. + This takes precedence over the max_xmit field in the + global struct. These different max_xmit variables should + be merged as this is now too confusing */ + + extern int max_send; + int data_to_send = datasize; + int params_to_send = paramsize; + int useable_space; + char *pp = params; + char *pd = pdata; + int params_sent_thistime, data_sent_thistime, total_sent_thistime; + int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */ + int data_alignment_offset = 0; + + /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */ + + set_message(outbuf,10,0,True); + + /* If there genuinely are no parameters or data to send just send the empty packet */ + + if(params_to_send == 0 && data_to_send == 0) { + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans2_replies: send_smb failed."); + return 0; + } + + /* When sending params and data ensure that both are nicely aligned */ + /* Only do this alignment when there is also data to send - else + can cause NT redirector problems. */ + + if (((params_to_send % 4) != 0) && (data_to_send != 0)) + data_alignment_offset = 4 - (params_to_send % 4); + + /* Space is bufsize minus Netbios over TCP header minus SMB header */ + /* The alignment_offset is to align the param bytes on an even byte + boundary. NT 4.0 Beta needs this to work correctly. */ + + useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf); + + /* useable_space can never be more than max_send minus the alignment offset. */ + + useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset)); + + while (params_to_send || data_to_send) { + /* Calculate whether we will totally or partially fill this packet */ + + total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset; + + /* We can never send more than useable_space */ + /* + * Note that 'useable_space' does not include the alignment offsets, + * but we must include the alignment offsets in the calculation of + * the length of the data we send over the wire, as the alignment offsets + * are sent here. Fix from Marc_Jacobsen@hp.com. + */ + + total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset); + + set_message(outbuf, 10, total_sent_thistime, True); + + /* Set total params and data to be sent */ + SSVAL(outbuf,smb_tprcnt,paramsize); + SSVAL(outbuf,smb_tdrcnt,datasize); + + /* Calculate how many parameters and data we can fit into + * this packet. Parameters get precedence + */ + + params_sent_thistime = MIN(params_to_send,useable_space); + data_sent_thistime = useable_space - params_sent_thistime; + data_sent_thistime = MIN(data_sent_thistime,data_to_send); + + SSVAL(outbuf,smb_prcnt, params_sent_thistime); + + /* smb_proff is the offset from the start of the SMB header to the + parameter bytes, however the first 4 bytes of outbuf are + the Netbios over TCP header. Thus use smb_base() to subtract + them from the calculation */ + + SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + + if(params_sent_thistime == 0) + SSVAL(outbuf,smb_prdisp,0); + else + /* Absolute displacement of param bytes sent in this packet */ + SSVAL(outbuf,smb_prdisp,pp - params); + + SSVAL(outbuf,smb_drcnt, data_sent_thistime); + if(data_sent_thistime == 0) { + SSVAL(outbuf,smb_droff,0); + SSVAL(outbuf,smb_drdisp, 0); + } else { + /* The offset of the data bytes is the offset of the + parameter bytes plus the number of parameters being sent this time */ + SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - + smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); + SSVAL(outbuf,smb_drdisp, pd - pdata); + } + + /* Copy the param bytes into the packet */ + + if(params_sent_thistime) + memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + + /* Copy in the data bytes */ + if(data_sent_thistime) + memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ + data_alignment_offset,pd,data_sent_thistime); + + DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", + params_sent_thistime, data_sent_thistime, useable_space)); + DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", + params_to_send, data_to_send, paramsize, datasize)); + + /* Send the packet */ + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans2_replies: send_smb failed."); + + pp += params_sent_thistime; + pd += data_sent_thistime; + + params_to_send -= params_sent_thistime; + data_to_send -= data_sent_thistime; + + /* Sanity check */ + if(params_to_send < 0 || data_to_send < 0) { + DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!", + params_to_send, data_to_send)); + return -1; + } + } + + return 0; } /**************************************************************************** Reply to a TRANSACT2_OPEN. ****************************************************************************/ -static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, - int bufsize, - char **pparams, char **ppdata) +static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - char *params = *pparams; - int16 open_mode = SVAL(params, 2); - int16 open_attr = SVAL(params,6); - BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1)); + char *params = *pparams; + int16 open_mode; + int16 open_attr; + BOOL oplock_request; #if 0 - BOOL return_additional_info = BITSETW(params,0); - int16 open_sattr = SVAL(params, 4); - time_t open_time = make_unix_date3(params+8); + BOOL return_additional_info; + int16 open_sattr; + time_t open_time; #endif - int16 open_ofun = SVAL(params,12); - int32 open_size = IVAL(params,14); - char *pname = ¶ms[28]; - pstring fname; - mode_t unixmode; - SMB_OFF_T size=0; - int fmode=0,mtime=0,rmode; - SMB_INO_T inode = 0; - SMB_STRUCT_STAT sbuf; - int smb_action = 0; - BOOL bad_path = False; - files_struct *fsp; - - srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE); - - DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", - fname,open_mode, open_attr, open_ofun, open_size)); - - if (IS_IPC(conn)) { + int16 open_ofun; + int32 open_size; + char *pname; + pstring fname; + mode_t unixmode; + SMB_OFF_T size=0; + int fmode=0,mtime=0,rmode; + SMB_INO_T inode = 0; + SMB_STRUCT_STAT sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp; + + /* + * Ensure we have enough parameters to perform the operation. + */ + + if (total_params < 29) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + open_mode = SVAL(params, 2); + open_attr = SVAL(params,6); + oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1)); +#if 0 + return_additional_info = BITSETW(params,0); + open_sattr = SVAL(params, 4); + open_time = make_unix_date3(params+8); +#endif + open_ofun = SVAL(params,12); + open_size = IVAL(params,14); + pname = ¶ms[28]; + + srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE); + + DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", + fname,open_mode, open_attr, open_ofun, open_size)); + + if (IS_IPC(conn)) return(ERROR_DOS(ERRSRV,ERRaccess)); - } - /* XXXX we need to handle passed times, sattr and flags */ + /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,conn,0,&bad_path,&sbuf); + unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - unixmode = unix_mode(conn,open_attr | aARCH, fname); + if (!check_name(fname,conn)) { + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + unixmode = unix_mode(conn,open_attr | aARCH, fname); - fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode, - oplock_request, &rmode,&smb_action); + fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode, + oplock_request, &rmode,&smb_action); - if (!fsp) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - size = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - mtime = sbuf.st_mtime; - inode = sbuf.st_ino; - if (fmode & aDIR) { - close_file(fsp,False); - return(ERROR_DOS(ERRDOS,ERRnoaccess)); - } - - /* Realloc the size of parameters and data we will return */ - params = Realloc(*pparams, 28); - if( params == NULL ) { - return(ERROR_DOS(ERRDOS,ERRnomem)); - } - *pparams = params; - - memset((char *)params,'\0',28); - SSVAL(params,0,fsp->fnum); - SSVAL(params,2,fmode); - put_dos_date2(params,4, mtime); - SIVAL(params,8, (uint32)size); - SSVAL(params,12,rmode); - - if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - } - - SSVAL(params,18,smb_action); - /* - * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes. - */ - SIVAL(params,20,inode); + if (!fsp) { + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + mtime = sbuf.st_mtime; + inode = sbuf.st_ino; + if (fmode & aDIR) { + close_file(fsp,False); + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + } + + /* Realloc the size of parameters and data we will return */ + params = Realloc(*pparams, 28); + if( params == NULL ) + return(ERROR_DOS(ERRDOS,ERRnomem)); + *pparams = params; + + memset((char *)params,'\0',28); + SSVAL(params,0,fsp->fnum); + SSVAL(params,2,fmode); + put_dos_date2(params,4, mtime); + SIVAL(params,8, (uint32)size); + SSVAL(params,12,rmode); + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) + smb_action |= EXTENDED_OPLOCK_GRANTED; + + SSVAL(params,18,smb_action); + + /* + * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes. + */ + SIVAL(params,20,inode); - /* Send the required number of replies */ - send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0); + /* Send the required number of replies */ + send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0); - return -1; + return -1; } /********************************************************* @@ -304,10 +310,6 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) return strcasecmp(str,mask) == 0; } -#if 0 - -Not finished yet - jra. - /**************************************************************************** Return the filetype for UNIX extensions. ****************************************************************************/ @@ -370,35 +372,63 @@ static uint32 unix_dev_minor(SMB_DEV_T dev) } /**************************************************************************** - Map standard UNIX permissions onto wire representations. + Map wire perms onto standard UNIX permissions. Obey share restrictions. ****************************************************************************/ -static uint32 unix_perms_to_wire(mode_t perms) +static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms) { - uint ret = 0; - - ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0); - ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0); - ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0); - ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0); - ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0); - ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0); - ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0); - ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0); - ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0); + mode_t ret = 0; + + if (perms == SMB_MODE_NO_CHANGE) + return pst->st_mode; + + ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0); + ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0); + ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0); + ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0); + ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0); + ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0); + ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0); + ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0); + ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0); #ifdef S_ISVTX - ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0); + ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0); #endif #ifdef S_ISGID - ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0); + ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0); #endif #ifdef S_ISUID - ret |= ((perms & S_ISVTX) ? UNIX_SET_UID : 0); + ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0); #endif + + if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) { + ret &= lp_dir_mask(SNUM(conn)); + /* Add in force bits */ + ret |= lp_force_dir_mode(SNUM(conn)); + } else { + /* Apply mode mask */ + ret &= lp_create_mask(SNUM(conn)); + /* Add in force bits */ + ret |= lp_force_create_mode(SNUM(conn)); + } + return ret; } -#endif +/**************************************************************************** +checks for SMB_TIME_NO_CHANGE and if not found +calls interpret_long_date +****************************************************************************/ +time_t interpret_long_unix_date(char *p) +{ + DEBUG(1,("interpret_long_unix_date\n")); + if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO && + IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) { + return -1; + } else { + return interpret_long_date(p); + } +} /**************************************************************************** Get a level dependent lanman2 dir entry. @@ -508,16 +538,23 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, continue; } } else if (vfs_stat(conn,pathreal,&sbuf) != 0) { - /* Needed to show the msdfs symlinks as directories */ - if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) - || !is_msdfs_link(conn, pathreal)) { + + /* Needed to show the msdfs symlinks as + * directories */ + + if(lp_host_msdfs() && + lp_msdfs_root(SNUM(conn)) && + is_msdfs_link(conn, pathreal, NULL, NULL, + &sbuf)) { + + DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal)); + sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; + + } else { + DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", - pathreal,strerror(errno))); + pathreal,strerror(errno))); continue; - } else { - DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", - pathreal)); - sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; } } @@ -557,7 +594,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) { - case 1: + case SMB_INFO_STANDARD: if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -576,7 +613,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += len; break; - case 2: + case SMB_INFO_QUERY_EA_SIZE: if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -693,14 +730,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, /* CIFS UNIX Extension. */ -#if 0 /* JRA - FIXME - NEEDS UNICODE CONVERSION !!! */ case SMB_FIND_FILE_UNIX: - - len = 108+strlen(fname)+1; /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/ - /* +1 to be sure to transmit the termination of fname */ - len = (len + 3) & ~3; - - SIVAL(p,0,len); p+= 4; /* Offset from this structure to the beginning of the next one */ + p+= 4; SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ @@ -750,12 +781,16 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,4,0); p+= 8; + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + p += len; + + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */ + p = pdata + len; /* End of SMB_QUERY_FILE_UNIX_BASIC */ - pstrcpy(p,fname); - p=pdata+len; break; -#endif default: return(False); @@ -782,612 +817,664 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, Reply to a TRANS2_FINDFIRST. ****************************************************************************/ -static int call_trans2findfirst(connection_struct *conn, - char *inbuf, char *outbuf, int bufsize, - char **pparams, char **ppdata) +static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - /* We must be careful here that we don't return more than the - allowed number of data bytes. If this means returning fewer than - maxentries then so be it. We assume that the redirector has - enough room for the fixed number of parameter bytes it has - requested. */ - uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt); - char *params = *pparams; - char *pdata = *ppdata; - int dirtype = SVAL(params,0); - int maxentries = SVAL(params,2); - BOOL close_after_first = BITSETW(params+4,0); - BOOL close_if_end = BITSETW(params+4,1); - BOOL requires_resume_key = BITSETW(params+4,2); - int info_level = SVAL(params,6); - pstring directory; - pstring mask; - char *p, *wcard; - int last_name_off=0; - int dptr_num = -1; - int numentries = 0; - int i; - BOOL finished = False; - BOOL dont_descend = False; - BOOL out_of_space = False; - int space_remaining; - BOOL bad_path = False; - SMB_STRUCT_STAT sbuf; - - *directory = *mask = 0; - - DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", - dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, - info_level, max_data_bytes)); + /* We must be careful here that we don't return more than the + allowed number of data bytes. If this means returning fewer than + maxentries then so be it. We assume that the redirector has + enough room for the fixed number of parameter bytes it has + requested. */ + uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt); + char *params = *pparams; + char *pdata = *ppdata; + int dirtype = SVAL(params,0); + int maxentries = SVAL(params,2); + BOOL close_after_first = BITSETW(params+4,0); + BOOL close_if_end = BITSETW(params+4,1); + BOOL requires_resume_key = BITSETW(params+4,2); + int info_level = SVAL(params,6); + pstring directory; + pstring mask; + char *p, *wcard; + int last_name_off=0; + int dptr_num = -1; + int numentries = 0; + int i; + BOOL finished = False; + BOOL dont_descend = False; + BOOL out_of_space = False; + int space_remaining; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + + if (total_params < 12) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + *directory = *mask = 0; + + DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \ +close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", + dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, + info_level, max_data_bytes)); - switch (info_level) - { - case 1: - case 2: - case 3: - case 4: - case SMB_FIND_FILE_DIRECTORY_INFO: - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - case SMB_FIND_FILE_NAMES_INFO: - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - break; - default: - return(ERROR_DOS(ERRDOS,ERRunknownlevel)); - } - - srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE); - - RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); - - unix_convert(directory,conn,0,&bad_path,&sbuf); - if(!check_name(directory,conn)) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + switch (info_level) { + case SMB_INFO_STANDARD: + case SMB_INFO_QUERY_EA_SIZE: + case SMB_FIND_FILE_DIRECTORY_INFO: + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + case SMB_FIND_FILE_NAMES_INFO: + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + break; + case SMB_FIND_FILE_UNIX: + if (!lp_unix_extensions()) + return(ERROR_DOS(ERRDOS,ERRunknownlevel)); + break; + default: + return(ERROR_DOS(ERRDOS,ERRunknownlevel)); + } -#if 0 - /* Ugly - NT specific hack - maybe not needed ? (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } -#endif - - return(UNIXERROR(ERRDOS,ERRbadpath)); - } - - p = strrchr_m(directory,'/'); - if(p == NULL) { - pstrcpy(mask,directory); - pstrcpy(directory,"./"); - } else { - pstrcpy(mask,p+1); - *p = 0; - } - - DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); - - pdata = Realloc(*ppdata, max_data_bytes + 1024); - if( pdata == NULL ) { - return(ERROR_DOS(ERRDOS,ERRnomem)); - } - *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); - - /* Realloc the params space */ - params = Realloc(*pparams, 10); - if (params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *pparams = params; - - dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) - return(UNIXERROR(ERRDOS,ERRbadfile)); - - /* Save the wildcard match and attribs we are using on this directory - - needed as lanman2 assumes these are being saved between calls */ - - if(!(wcard = strdup(mask))) { - dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRnomem); - } - - dptr_set_wcard(dptr_num, wcard); - dptr_set_attr(dptr_num, dirtype); - - DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype)); - - /* We don't need to check for VOL here as this is returned by - a different TRANS2 call. */ + srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE); + + RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); + + unix_convert(directory,conn,0,&bad_path,&sbuf); + if(!check_name(directory,conn)) { + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + + p = strrchr_m(directory,'/'); + if(p == NULL) { + pstrcpy(mask,directory); + pstrcpy(directory,"./"); + } else { + pstrcpy(mask,p+1); + *p = 0; + } + + DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); + + pdata = Realloc(*ppdata, max_data_bytes + 1024); + if( pdata == NULL ) + return(ERROR_DOS(ERRDOS,ERRnomem)); + + *ppdata = pdata; + memset((char *)pdata,'\0',max_data_bytes + 1024); + + /* Realloc the params space */ + params = Realloc(*pparams, 10); + if (params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + *pparams = params; + + dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); + if (dptr_num < 0) + return(UNIXERROR(ERRDOS,ERRbadfile)); + + /* Save the wildcard match and attribs we are using on this directory - + needed as lanman2 assumes these are being saved between calls */ + + if(!(wcard = strdup(mask))) { + dptr_close(&dptr_num); + return ERROR_DOS(ERRDOS,ERRnomem); + } + + dptr_set_wcard(dptr_num, wcard); + dptr_set_attr(dptr_num, dirtype); + + DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype)); + + /* We don't need to check for VOL here as this is returned by + a different TRANS2 call. */ - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) - dont_descend = True; + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) + dont_descend = True; - p = pdata; - space_remaining = max_data_bytes; - out_of_space = False; - - for (i=0;(i 0) - { - out_of_space = True; - finished = False; - } - else - { - finished = !get_lanman2_dir_entry(conn, + p = pdata; + space_remaining = max_data_bytes; + out_of_space = False; + + for (i=0;(i 0) { + out_of_space = True; + finished = False; + } else { + finished = !get_lanman2_dir_entry(conn, inbuf, outbuf, mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, &last_name_off); - } + } - if (finished && out_of_space) - finished = False; + if (finished && out_of_space) + finished = False; - if (!finished && !out_of_space) - numentries++; + if (!finished && !out_of_space) + numentries++; - /* - * As an optimisation if we know we aren't looking - * for a wildcard name (ie. the name matches the wildcard exactly) - * then we can finish on any (first) match. - * This speeds up large directory searches. JRA. - */ + /* + * As an optimisation if we know we aren't looking + * for a wildcard name (ie. the name matches the wildcard exactly) + * then we can finish on any (first) match. + * This speeds up large directory searches. JRA. + */ - if(got_exact_match) - finished = True; + if(got_exact_match) + finished = True; - space_remaining = max_data_bytes - PTR_DIFF(p,pdata); - } + space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + } - /* Check if we can close the dirptr */ - if(close_after_first || (finished && close_if_end)) - { - DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); - dptr_close(&dptr_num); - } - - /* - * If there are no matching entries we must return ERRDOS/ERRbadfile - - * from observation of NT. - */ - - if(numentries == 0) { - dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRbadfile); - } - - /* At this point pdata points to numentries directory entries. */ - - /* Set up the return parameter block */ - SSVAL(params,0,dptr_num); - SSVAL(params,2,numentries); - SSVAL(params,4,finished); - SSVAL(params,6,0); /* Never an EA error */ - SSVAL(params,8,last_name_off); - - send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); - - if ((! *directory) && dptr_path(dptr_num)) - slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - - DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", - smb_fn_name(CVAL(inbuf,smb_com)), - mask, directory, dirtype, numentries ) ); - - /* - * Force a name mangle here to ensure that the - * mask as an 8.3 name is top of the mangled cache. - * The reasons for this are subtle. Don't remove - * this code unless you know what you are doing - * (see PR#13758). JRA. - */ - - if(!mangle_is_8_3( mask, False)) - mangle_map(mask, True, True, SNUM(conn)); - - return(-1); + /* Check if we can close the dirptr */ + if(close_after_first || (finished && close_if_end)) { + DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); + dptr_close(&dptr_num); + } + + /* + * If there are no matching entries we must return ERRDOS/ERRbadfile - + * from observation of NT. + */ + + if(numentries == 0) { + dptr_close(&dptr_num); + return ERROR_DOS(ERRDOS,ERRbadfile); + } + + /* At this point pdata points to numentries directory entries. */ + + /* Set up the return parameter block */ + SSVAL(params,0,dptr_num); + SSVAL(params,2,numentries); + SSVAL(params,4,finished); + SSVAL(params,6,0); /* Never an EA error */ + SSVAL(params,8,last_name_off); + + send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); + + if ((! *directory) && dptr_path(dptr_num)) + slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); + + DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", + smb_fn_name(CVAL(inbuf,smb_com)), + mask, directory, dirtype, numentries ) ); + + /* + * Force a name mangle here to ensure that the + * mask as an 8.3 name is top of the mangled cache. + * The reasons for this are subtle. Don't remove + * this code unless you know what you are doing + * (see PR#13758). JRA. + */ + + if(!mangle_is_8_3_wildcards( mask, False)) + mangle_map(mask, True, True, SNUM(conn)); + + return(-1); } /**************************************************************************** Reply to a TRANS2_FINDNEXT. ****************************************************************************/ -static int call_trans2findnext(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **pparams, char **ppdata) +static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - /* We must be careful here that we don't return more than the - allowed number of data bytes. If this means returning fewer than - maxentries then so be it. We assume that the redirector has - enough room for the fixed number of parameter bytes it has - requested. */ - int max_data_bytes = SVAL(inbuf, smb_mdrcnt); - char *params = *pparams; - char *pdata = *ppdata; - int dptr_num = SVAL(params,0); - int maxentries = SVAL(params,2); - uint16 info_level = SVAL(params,4); - uint32 resume_key = IVAL(params,6); - BOOL close_after_request = BITSETW(params+10,0); - BOOL close_if_end = BITSETW(params+10,1); - BOOL requires_resume_key = BITSETW(params+10,2); - BOOL continue_bit = BITSETW(params+10,3); - pstring resume_name; - pstring mask; - pstring directory; - char *p; - uint16 dirtype; - int numentries = 0; - int i, last_name_off=0; - BOOL finished = False; - BOOL dont_descend = False; - BOOL out_of_space = False; - int space_remaining; - - *mask = *directory = *resume_name = 0; - - srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE); - - DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \ + /* We must be careful here that we don't return more than the + allowed number of data bytes. If this means returning fewer than + maxentries then so be it. We assume that the redirector has + enough room for the fixed number of parameter bytes it has + requested. */ + int max_data_bytes = SVAL(inbuf, smb_mdrcnt); + char *params = *pparams; + char *pdata = *ppdata; + int dptr_num = SVAL(params,0); + int maxentries = SVAL(params,2); + uint16 info_level = SVAL(params,4); + uint32 resume_key = IVAL(params,6); + BOOL close_after_request = BITSETW(params+10,0); + BOOL close_if_end = BITSETW(params+10,1); + BOOL requires_resume_key = BITSETW(params+10,2); + BOOL continue_bit = BITSETW(params+10,3); + pstring resume_name; + pstring mask; + pstring directory; + char *p; + uint16 dirtype; + int numentries = 0; + int i, last_name_off=0; + BOOL finished = False; + BOOL dont_descend = False; + BOOL out_of_space = False; + int space_remaining; + + if (total_params < 12) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + *mask = *directory = *resume_name = 0; + + srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE); + + DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \ close_after_request=%d, close_if_end = %d requires_resume_key = %d \ resume_key = %d resume name = %s continue=%d level = %d\n", - dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, - requires_resume_key, resume_key, resume_name, continue_bit, info_level)); - - switch (info_level) - { - case 1: - case 2: - case 3: - case 4: - case SMB_FIND_FILE_DIRECTORY_INFO: - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - case SMB_FIND_FILE_NAMES_INFO: - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - break; - default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); - } - - pdata = Realloc( *ppdata, max_data_bytes + 1024); - if(pdata == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); - - /* Realloc the params space */ - params = Realloc(*pparams, 6*SIZEOFWORD); - if( params == NULL ) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *pparams = params; - - /* Check that the dptr is valid */ - if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) - return ERROR_DOS(ERRDOS,ERRnofiles); - - string_set(&conn->dirpath,dptr_path(dptr_num)); - - /* Get the wildcard mask from the dptr */ - if((p = dptr_wcard(dptr_num))== NULL) { - DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); - return ERROR_DOS(ERRDOS,ERRnofiles); - } - pstrcpy(mask, p); - pstrcpy(directory,conn->dirpath); - - /* Get the attr mask from the dptr */ - dirtype = dptr_attr(dptr_num); - - DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n", - dptr_num, mask, dirtype, - (long)conn->dirptr, - TellDir(conn->dirptr))); - - /* We don't need to check for VOL here as this is returned by - a different TRANS2 call. */ - - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) - dont_descend = True; + dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, + requires_resume_key, resume_key, resume_name, continue_bit, info_level)); + + switch (info_level) { + case SMB_INFO_STANDARD: + case SMB_INFO_QUERY_EA_SIZE: + case SMB_FIND_FILE_DIRECTORY_INFO: + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + case SMB_FIND_FILE_NAMES_INFO: + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + break; + case SMB_FIND_FILE_UNIX: + if (!lp_unix_extensions()) + return(ERROR_DOS(ERRDOS,ERRunknownlevel)); + break; + default: + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + pdata = Realloc( *ppdata, max_data_bytes + 1024); + if(pdata == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + *ppdata = pdata; + memset((char *)pdata,'\0',max_data_bytes + 1024); + + /* Realloc the params space */ + params = Realloc(*pparams, 6*SIZEOFWORD); + if( params == NULL ) + return ERROR_DOS(ERRDOS,ERRnomem); + + *pparams = params; + + /* Check that the dptr is valid */ + if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) + return ERROR_DOS(ERRDOS,ERRnofiles); + + string_set(&conn->dirpath,dptr_path(dptr_num)); + + /* Get the wildcard mask from the dptr */ + if((p = dptr_wcard(dptr_num))== NULL) { + DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); + return ERROR_DOS(ERRDOS,ERRnofiles); + } + + pstrcpy(mask, p); + pstrcpy(directory,conn->dirpath); + + /* Get the attr mask from the dptr */ + dirtype = dptr_attr(dptr_num); + + DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n", + dptr_num, mask, dirtype, + (long)conn->dirptr, + TellDir(conn->dirptr))); + + /* We don't need to check for VOL here as this is returned by + a different TRANS2 call. */ + + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) + dont_descend = True; - p = pdata; - space_remaining = max_data_bytes; - out_of_space = False; - - /* - * Seek to the correct position. We no longer use the resume key but - * depend on the last file name instead. - */ - if(requires_resume_key && *resume_name && !continue_bit) - { - /* - * Fix for NT redirector problem triggered by resume key indexes - * changing between directory scans. We now return a resume key of 0 - * and instead look for the filename to continue from (also given - * to us by NT/95/smbfs/smbclient). If no other scans have been done between the - * findfirst/findnext (as is usual) then the directory pointer - * should already be at the correct place. Check this by scanning - * backwards looking for an exact (ie. case sensitive) filename match. - * If we get to the beginning of the directory and haven't found it then scan - * forwards again looking for a match. JRA. - */ - - int current_pos, start_pos; - char *dname = NULL; - void *dirptr = conn->dirptr; - start_pos = TellDir(dirptr); - for(current_pos = start_pos; current_pos >= 0; current_pos--) - { - DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos)); - - SeekDir(dirptr, current_pos); - dname = ReadDirName(dirptr); - - /* - * Remember, mangle_map is called by - * get_lanman2_dir_entry(), so the resume name - * could be mangled. Ensure we do the same - * here. - */ - - if(dname != NULL) - mangle_map( dname, False, True, SNUM(conn)); - - if(dname && strcsequal( resume_name, dname)) - { - SeekDir(dirptr, current_pos+1); - DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); - break; - } - } - - /* - * Scan forward from start if not found going backwards. - */ - - if(current_pos < 0) - { - DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos)); - SeekDir(dirptr, start_pos); - for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) - { - /* - * Remember, mangle_map is called by - * get_lanman2_dir_entry(), so the resume name - * could be mangled. Ensure we do the same - * here. - */ - - if(dname != NULL) - mangle_map( dname, False, True, SNUM(conn)); - - if(dname && strcsequal( resume_name, dname)) - { - SeekDir(dirptr, current_pos+1); - DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); - break; - } - } /* end for */ - } /* end if current_pos */ - } /* end if requires_resume_key && !continue_bit */ - - for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) - { - BOOL got_exact_match = False; - - /* this is a heuristic to avoid seeking the dirptr except when - absolutely necessary. It allows for a filename of about 40 chars */ - if (space_remaining < DIRLEN_GUESS && numentries > 0) - { - out_of_space = True; - finished = False; - } - else - { - finished = !get_lanman2_dir_entry(conn, - inbuf, outbuf, - mask,dirtype,info_level, - requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_name_off); - } + p = pdata; + space_remaining = max_data_bytes; + out_of_space = False; - if (finished && out_of_space) - finished = False; + /* + * Seek to the correct position. We no longer use the resume key but + * depend on the last file name instead. + */ - if (!finished && !out_of_space) - numentries++; + if(requires_resume_key && *resume_name && !continue_bit) { - /* - * As an optimisation if we know we aren't looking - * for a wildcard name (ie. the name matches the wildcard exactly) - * then we can finish on any (first) match. - * This speeds up large directory searches. JRA. - */ + /* + * Fix for NT redirector problem triggered by resume key indexes + * changing between directory scans. We now return a resume key of 0 + * and instead look for the filename to continue from (also given + * to us by NT/95/smbfs/smbclient). If no other scans have been done between the + * findfirst/findnext (as is usual) then the directory pointer + * should already be at the correct place. Check this by scanning + * backwards looking for an exact (ie. case sensitive) filename match. + * If we get to the beginning of the directory and haven't found it then scan + * forwards again looking for a match. JRA. + */ + + int current_pos, start_pos; + char *dname = NULL; + void *dirptr = conn->dirptr; + start_pos = TellDir(dirptr); + for(current_pos = start_pos; current_pos >= 0; current_pos--) { + DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos)); + + SeekDir(dirptr, current_pos); + dname = ReadDirName(dirptr); + + /* + * Remember, mangle_map is called by + * get_lanman2_dir_entry(), so the resume name + * could be mangled. Ensure we do the same + * here. + */ + + if(dname != NULL) + mangle_map( dname, False, True, SNUM(conn)); + + if(dname && strcsequal( resume_name, dname)) { + SeekDir(dirptr, current_pos+1); + DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); + break; + } + } + + /* + * Scan forward from start if not found going backwards. + */ + + if(current_pos < 0) { + DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos)); + SeekDir(dirptr, start_pos); + for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) { + + /* + * Remember, mangle_map is called by + * get_lanman2_dir_entry(), so the resume name + * could be mangled. Ensure we do the same + * here. + */ + + if(dname != NULL) + mangle_map( dname, False, True, SNUM(conn)); + + if(dname && strcsequal( resume_name, dname)) { + SeekDir(dirptr, current_pos+1); + DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); + break; + } + } /* end for */ + } /* end if current_pos */ + } /* end if requires_resume_key && !continue_bit */ + + for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { + BOOL got_exact_match = False; + + /* this is a heuristic to avoid seeking the dirptr except when + absolutely necessary. It allows for a filename of about 40 chars */ + if (space_remaining < DIRLEN_GUESS && numentries > 0) { + out_of_space = True; + finished = False; + } else { + finished = !get_lanman2_dir_entry(conn, + inbuf, outbuf, + mask,dirtype,info_level, + requires_resume_key,dont_descend, + &p,pdata,space_remaining, &out_of_space, &got_exact_match, + &last_name_off); + } - if(got_exact_match) - finished = True; + if (finished && out_of_space) + finished = False; - space_remaining = max_data_bytes - PTR_DIFF(p,pdata); - } + if (!finished && !out_of_space) + numentries++; + + /* + * As an optimisation if we know we aren't looking + * for a wildcard name (ie. the name matches the wildcard exactly) + * then we can finish on any (first) match. + * This speeds up large directory searches. JRA. + */ + + if(got_exact_match) + finished = True; + + space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + } - /* Check if we can close the dirptr */ - if(close_after_request || (finished && close_if_end)) - { - DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); - dptr_close(&dptr_num); /* This frees up the saved mask */ - } + /* Check if we can close the dirptr */ + if(close_after_request || (finished && close_if_end)) { + DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); + dptr_close(&dptr_num); /* This frees up the saved mask */ + } - /* Set up the return parameter block */ - SSVAL(params,0,numentries); - SSVAL(params,2,finished); - SSVAL(params,4,0); /* Never an EA error */ - SSVAL(params,6,last_name_off); + /* Set up the return parameter block */ + SSVAL(params,0,numentries); + SSVAL(params,2,finished); + SSVAL(params,4,0); /* Never an EA error */ + SSVAL(params,6,last_name_off); - send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); + send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); - if ((! *directory) && dptr_path(dptr_num)) - slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); + if ((! *directory) && dptr_path(dptr_num)) + slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", - smb_fn_name(CVAL(inbuf,smb_com)), - mask, directory, dirtype, numentries ) ); + DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", + smb_fn_name(CVAL(inbuf,smb_com)), + mask, directory, dirtype, numentries ) ); - return(-1); + return(-1); } /**************************************************************************** Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ -static int call_trans2qfsinfo(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **pparams, char **ppdata) +static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, + int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - int max_data_bytes = SVAL(inbuf, smb_mdrcnt); - char *pdata = *ppdata; - char *params = *pparams; - uint16 info_level = SVAL(params,0); - int data_len, len; - SMB_STRUCT_STAT st; - char *vname = volume_label(SNUM(conn)); - int snum = SNUM(conn); - char *fstype = lp_fstype(SNUM(conn)); - - DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - - if(vfs_stat(conn,".",&st)!=0) { - DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); - return ERROR_DOS(ERRSRV,ERRinvdevice); - } - - pdata = Realloc(*ppdata, max_data_bytes + 1024); - if ( pdata == NULL ) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); - - switch (info_level) - { - case 1: - { - SMB_BIG_UINT dfree,dsize,bsize; - data_len = 18; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); - SIVAL(pdata,l1_idFileSystem,st.st_dev); - SIVAL(pdata,l1_cSectorUnit,bsize/512); - SIVAL(pdata,l1_cUnit,dsize); - SIVAL(pdata,l1_cUnitAvail,dfree); - SSVAL(pdata,l1_cbSector,512); - DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n", - (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize, - (unsigned int)dfree, 512)); - break; - } - case 2: - /* Return volume name */ - /* - * Add volume serial number - hash of a combination of - * the called hostname and the service name. - */ - SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, - STR_TERMINATE); - SCVAL(pdata,l2_vol_cch,len); - data_len = l2_vol_szVolLabel + len; - DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", - (unsigned)st.st_ctime, len, vname)); - break; + int max_data_bytes = SVAL(inbuf, smb_mdrcnt); + char *pdata = *ppdata; + char *params = *pparams; + uint16 info_level = SVAL(params,0); + int data_len, len; + SMB_STRUCT_STAT st; + char *vname = volume_label(SNUM(conn)); + int snum = SNUM(conn); + char *fstype = lp_fstype(SNUM(conn)); + + DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); + + if(vfs_stat(conn,".",&st)!=0) { + DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); + return ERROR_DOS(ERRSRV,ERRinvdevice); + } - case SMB_QUERY_FS_ATTRIBUTE_INFO: - SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ - SIVAL(pdata,4,255); /* Max filename component length */ - /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it - and will think we can't do long filenames */ - len = srvstr_push(outbuf, pdata+12, fstype, -1, 0); - SIVAL(pdata,8,len); - data_len = 12 + len; - break; + pdata = Realloc(*ppdata, max_data_bytes + 1024); + if ( pdata == NULL ) + return ERROR_DOS(ERRDOS,ERRnomem); - case SMB_QUERY_FS_LABEL_INFO: - len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE); - data_len = 4 + len; - SIVAL(pdata,0,len); - break; - case SMB_QUERY_FS_VOLUME_INFO: - /* - * Add volume serial number - hash of a combination of - * the called hostname and the service name. - */ - SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ - (str_checksum(local_machine)<<16)); - - len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE); - SIVAL(pdata,12,len); - data_len = 18+len; - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", - (int)strlen(vname),vname, lp_servicename(snum))); - break; - case SMB_QUERY_FS_SIZE_INFO: - { - SMB_BIG_UINT dfree,dsize,bsize; - data_len = 24; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); - SBIG_UINT(pdata,0,dsize); - SBIG_UINT(pdata,8,dfree); - SIVAL(pdata,16,bsize/512); - SIVAL(pdata,20,512); - break; - } - case SMB_QUERY_FS_DEVICE_INFO: - data_len = 8; - SIVAL(pdata,0,0); /* dev type */ - SIVAL(pdata,4,0); /* characteristics */ - break; - case SMB_MAC_QUERY_FS_INFO: - /* - * Thursby MAC extension... ONLY on NTFS filesystems - * once we do streams then we don't need this - */ - if (strequal(lp_fstype(SNUM(conn)),"NTFS")) { - data_len = 88; - SIVAL(pdata,84,0x100); /* Don't support mac... */ - break; - } - /* drop through */ - default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); - } - - - send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len); - - DEBUG( 4, ( "%s info_level = %d\n", - smb_fn_name(CVAL(inbuf,smb_com)), info_level) ); - - return -1; + *ppdata = pdata; + memset((char *)pdata,'\0',max_data_bytes + 1024); + + switch (info_level) { + case SMB_INFO_ALLOCATION: + { + SMB_BIG_UINT dfree,dsize,bsize; + data_len = 18; + conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + SIVAL(pdata,l1_idFileSystem,st.st_dev); + SIVAL(pdata,l1_cSectorUnit,bsize/512); + SIVAL(pdata,l1_cUnit,dsize); + SIVAL(pdata,l1_cUnitAvail,dfree); + SSVAL(pdata,l1_cbSector,512); + DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n", + (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize, + (unsigned int)dfree, 512)); + break; + } + + case SMB_INFO_VOLUME: + /* Return volume name */ + /* + * Add volume serial number - hash of a combination of + * the called hostname and the service name. + */ + SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE); + SCVAL(pdata,l2_vol_cch,len); + data_len = l2_vol_szVolLabel + len; + DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", + (unsigned)st.st_ctime, len, vname)); + break; + + case SMB_QUERY_FS_ATTRIBUTE_INFO: + case SMB_FS_ATTRIBUTE_INFORMATION: + + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| + (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ + SIVAL(pdata,4,255); /* Max filename component length */ + /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it + and will think we can't do long filenames */ + len = srvstr_push(outbuf, pdata+12, fstype, -1, 0); + SIVAL(pdata,8,len); + data_len = 12 + len; + break; + + case SMB_QUERY_FS_LABEL_INFO: + case SMB_FS_LABEL_INFORMATION: + len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE); + data_len = 4 + len; + SIVAL(pdata,0,len); + break; + + case SMB_QUERY_FS_VOLUME_INFO: + case SMB_FS_VOLUME_INFORMATION: + + /* + * Add volume serial number - hash of a combination of + * the called hostname and the service name. + */ + SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ + (str_checksum(local_machine)<<16)); + + len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE); + SIVAL(pdata,12,len); + data_len = 18+len; + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", + (int)strlen(vname),vname, lp_servicename(snum))); + break; + + case SMB_QUERY_FS_SIZE_INFO: + case SMB_FS_SIZE_INFORMATION: + { + SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; + data_len = 24; + conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + block_size = lp_block_size(snum); + if (bsize < block_size) { + SMB_BIG_UINT factor = block_size/bsize; + bsize = block_size; + dsize /= factor; + dfree /= factor; + } + if (bsize > block_size) { + SMB_BIG_UINT factor = bsize/block_size; + bsize = block_size; + dsize *= factor; + dfree *= factor; + } + bytes_per_sector = 512; + sectors_per_unit = bsize/bytes_per_sector; + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \ +cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit, + (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree)); + SBIG_UINT(pdata,0,dsize); + SBIG_UINT(pdata,8,dfree); + SIVAL(pdata,16,sectors_per_unit); + SIVAL(pdata,20,bytes_per_sector); + break; + } + + case SMB_FS_FULL_SIZE_INFORMATION: + { + SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; + data_len = 32; + conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + block_size = lp_block_size(snum); + if (bsize < block_size) { + SMB_BIG_UINT factor = block_size/bsize; + bsize = block_size; + dsize /= factor; + dfree /= factor; + } + if (bsize > block_size) { + SMB_BIG_UINT factor = bsize/block_size; + bsize = block_size; + dsize *= factor; + dfree *= factor; + } + bytes_per_sector = 512; + sectors_per_unit = bsize/bytes_per_sector; + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \ +cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit, + (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree)); + SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */ + SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */ + SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */ + SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */ + SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */ + break; + } + + case SMB_QUERY_FS_DEVICE_INFO: + case SMB_FS_DEVICE_INFORMATION: + data_len = 8; + SIVAL(pdata,0,0); /* dev type */ + SIVAL(pdata,4,0); /* characteristics */ + break; + + case SMB_FS_OBJECTID_INFORMATION: + data_len = 64; + break; + + /* + * Query the version and capabilities of the CIFS UNIX extensions + * in use. + */ + + case SMB_QUERY_CIFS_UNIX_INFO: + if (!lp_unix_extensions()) + return ERROR_DOS(ERRDOS,ERRunknownlevel); + data_len = 12; + SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); + SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); + SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */ + break; + + case SMB_MAC_QUERY_FS_INFO: + /* + * Thursby MAC extension... ONLY on NTFS filesystems + * once we do streams then we don't need this + */ + if (strequal(lp_fstype(SNUM(conn)),"NTFS")) { + data_len = 88; + SIVAL(pdata,84,0x100); /* Don't support mac... */ + break; + } + /* drop through */ + default: + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + + send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len); + + DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) ); + + return -1; } /**************************************************************************** @@ -1395,21 +1482,20 @@ static int call_trans2qfsinfo(connection_struct *conn, ****************************************************************************/ static int call_trans2setfsinfo(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **pparams, char **ppdata) + char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - /* Just say yes we did it - there is nothing that - can be set here so it doesn't matter. */ - int outsize; - DEBUG(3,("call_trans2setfsinfo\n")); + /* Just say yes we did it - there is nothing that + can be set here so it doesn't matter. */ + int outsize; + DEBUG(3,("call_trans2setfsinfo\n")); - if (!CAN_WRITE(conn)) - return ERROR_DOS(ERRSRV,ERRaccess); + if (!CAN_WRITE(conn)) + return ERROR_DOS(ERRSRV,ERRaccess); - outsize = set_message(outbuf,10,0,True); + outsize = set_message(outbuf,10,0,True); - return outsize; + return outsize; } /**************************************************************************** @@ -1434,8 +1520,7 @@ NTSTATUS set_bad_path_error(int err, BOOL bad_path) static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams,char **ppdata, - int total_data) + char **pparams, int total_params, char **ppdata, int total_data) { int max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *params = *pparams; @@ -1448,6 +1533,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unsigned int data_size; SMB_STRUCT_STAT sbuf; pstring fname, dos_fname; + char *fullpathname; char *base_name; char *p; SMB_OFF_T pos = 0; @@ -1456,9 +1542,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, int len; time_t c_time; - if (!params) { + if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } if (tran_call == TRANSACT2_QFILEINFO) { files_struct *fsp = file_fsp(params,0); @@ -1474,16 +1559,25 @@ static int call_trans2qfilepathinfo(connection_struct *conn, */ pstrcpy(fname, fsp->fsp_name); unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + if (!check_name(fname,conn)) { + DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (vfs_lstat(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + delete_pending = fsp->directory_delete_on_close; } else { /* @@ -1503,6 +1597,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } } else { /* qpathinfo */ + if (total_params < 6) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + info_level = SVAL(params,0); DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); @@ -1511,18 +1608,29 @@ static int call_trans2qfilepathinfo(connection_struct *conn, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn)) { + DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (vfs_lstat(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRbadpath)); } + } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } } + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) + return ERROR_DOS(ERRDOS,ERRunknownlevel); DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", fname,info_level,tran_call,total_data)); @@ -1534,9 +1642,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, base_name = p+1; mode = dos_mode(conn,fname,&sbuf); + fullpathname = fname; size = sbuf.st_size; allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size); - if (mode & aDIR) size = 0; @@ -1568,12 +1676,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, sbuf.st_mtime &= ~1; } - /* NT expects the name to be in an exact form */ - if (strequal(fname,".")) { + /* NT expects the name to be in an exact form of the *full* + filename. See the trans2 torture test */ + if (strequal(base_name,".")) { pstrcpy(dos_fname, "\\"); } else { snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname); - string_replace( dos_fname, '/', '\\'); + string_replace(dos_fname, '/', '\\'); } switch (info_level) { @@ -1636,6 +1745,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_STANDARD_INFORMATION: case SMB_QUERY_FILE_STANDARD_INFO: + data_size = 24; /* Fake up allocation size. */ SOFF_T(pdata,0,allocation_size); @@ -1658,8 +1768,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pstrcpy(short_name,base_name); /* Mangle if not already 8.3 */ if(!mangle_is_8_3(short_name, True)) { - if(!mangle_map(short_name,True,True,SNUM(conn))) - *short_name = '\0'; + mangle_map(short_name,True,True,SNUM(conn)); } len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER); data_size = 4 + len; @@ -1676,18 +1785,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,len); break; - case SMB_FILE_END_OF_FILE_INFORMATION: - case SMB_QUERY_FILE_END_OF_FILEINFO: - data_size = 8; - SOFF_T(pdata,0,size); - break; - case SMB_FILE_ALLOCATION_INFORMATION: case SMB_QUERY_FILE_ALLOCATION_INFO: data_size = 8; SOFF_T(pdata,0,allocation_size); break; + case SMB_FILE_END_OF_FILE_INFORMATION: + case SMB_QUERY_FILE_END_OF_FILEINFO: + data_size = 8; + SOFF_T(pdata,0,size); + break; + case SMB_QUERY_FILE_ALL_INFO: put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); @@ -1793,6 +1902,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; } +#if 0 + /* + * NT4 server just returns "invalid query" to this - if we try to answer + * it then NTws gets a BSOD! (tridge). + * W2K seems to want this. JRA. + */ + case SMB_QUERY_FILE_STREAM_INFO: +#endif case SMB_FILE_STREAM_INFORMATION: if (mode & aDIR) { data_size = 0; @@ -1832,18 +1949,92 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 8; break; -#if 0 - /* NT4 server just returns "invalid query" to this - if we try to answer - it then NTws gets a BSOD! (tridge) */ - case SMB_QUERY_FILE_STREAM_INFO: - SIVAL(pdata,0,pos); - SIVAL(pdata,4,(uint32)size); - SIVAL(pdata,12,(uint32)allocation_size); - len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE); - SIVAL(pdata,20,len); - data_size = 24 + len; + /* + * CIFS UNIX Extensions. + */ + + case SMB_QUERY_FILE_UNIX_BASIC: + + DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode)); + + SOFF_T(pdata,0,sbuf.st_size); /* File size 64 Bit */ + pdata += 8; + +#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) + SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */ +#else + /* Can't get the value - fake it using size. */ + SOFF_T(pdata,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */ +#endif + pdata += 8; + + put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */ + put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */ + put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */ + pdata += 24; + + SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,unix_filetype(sbuf.st_mode)); + pdata += 4; + + SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */ + SIVAL(pdata,4,0); + pdata += 8; + + SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ + pdata += 8; + + SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */ + SIVAL(pdata,4,0); + pdata += 8+1; + data_size = PTR_DIFF(pdata,(*ppdata)); + + { + int i; + DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC")); + + for (i=0; i<100; i++) + DEBUG(4,("%d=%x, ",i, (*ppdata)[i])); + DEBUG(4,("\n")); + } + break; + + case SMB_QUERY_FILE_UNIX_LINK: + { + pstring buffer; + +#ifdef S_ISLNK + if(!S_ISLNK(sbuf.st_mode)) + return(UNIXERROR(ERRSRV,ERRbadlink)); +#else + return(UNIXERROR(ERRDOS,ERRbadlink)); #endif + len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ + if (len == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + buffer[len] = 0; + len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE); + pdata += len; + data_size = PTR_DIFF(pdata,(*ppdata)); + + break; + } default: return ERROR_DOS(ERRDOS,ERRunknownlevel); @@ -1942,20 +2133,79 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) return NT_STATUS_OK; } +/**************************************************************************** + Returns true if this pathname is within the share, and thus safe. +****************************************************************************/ + +static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out) +{ +#ifdef PATH_MAX + char resolved_name[PATH_MAX+1]; +#else + pstring resolved_name; +#endif + fstring last_component; + pstring link_dest; + pstring link_test; + char *p; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + + pstrcpy(link_dest, link_dest_in); + unix_convert(link_dest,conn,0,&bad_path,&sbuf); + + /* Store the UNIX converted path. */ + pstrcpy(link_dest_out, link_dest); + + p = strrchr(link_dest, '/'); + if (p) { + fstrcpy(last_component, p+1); + *p = '\0'; + } else { + fstrcpy(last_component, link_dest); + pstrcpy(link_dest, "./"); + } + + if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL) + return -1; + + pstrcpy(link_dest, resolved_name); + pstrcat(link_dest, "/"); + pstrcat(link_dest, last_component); + + if (*link_dest != '/') { + /* Relative path. */ + pstrcpy(link_test, conn->connectpath); + pstrcat(link_test, "/"); + pstrcat(link_test, link_dest); + } else { + pstrcpy(link_test, link_dest); + } + + /* + * Check if the link is within the share. + */ + + if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) { + errno = EACCES; + return -1; + } + return 0; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid). ****************************************************************************/ static int call_trans2setfilepathinfo(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, char **pparams, - char **ppdata, int total_data) + char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { char *params = *pparams; char *pdata = *ppdata; uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; - int mode=0; + int dosmode=0; SMB_OFF_T size=0; struct utimbuf tvs; SMB_STRUCT_STAT sbuf; @@ -1963,6 +2213,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, int fd = -1; BOOL bad_path = False; files_struct *fsp = NULL; + uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; + gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; + mode_t unixmode = 0; if (tran_call == TRANSACT2_SETFILEINFO) { fsp = file_fsp(params,0); @@ -1977,11 +2230,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, pstrcpy(fname, fsp->fsp_name); unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } } else if (fsp && fsp->print_file) { @@ -2007,29 +2257,30 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fd = fsp->fd; if (vfs_fstat(fsp,fd,&sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); + DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } } } else { /* set path info */ + if (total_params < 6) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + info_level = SVAL(params,0); srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); unix_convert(fname,conn,0,&bad_path,&sbuf); if(!check_name(fname, conn)) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } - - if(!VALID_STAT(sbuf)) { - DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } + + /* + * For CIFS UNIX extensions the target name may not exist. + */ + + if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { + DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); + set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } } @@ -2037,6 +2288,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) + return ERROR_DOS(ERRDOS,ERRunknownlevel); + + if (VALID_STAT(sbuf)) + unixmode = sbuf.st_mode; + DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", tran_call,fname,info_level,total_data)); @@ -2048,29 +2305,36 @@ static int call_trans2setfilepathinfo(connection_struct *conn, SSVAL(params,0,0); + if (fsp) { + /* the pending modtime overrides the current modtime */ + sbuf.st_mtime = fsp->pending_modtime; + } + size = sbuf.st_size; tvs.modtime = sbuf.st_mtime; tvs.actime = sbuf.st_atime; - mode = dos_mode(conn,fname,&sbuf); + dosmode = dos_mode(conn,fname,&sbuf); + unixmode = sbuf.st_mode; - if (total_data > 4 && IVAL(pdata,0) == total_data) { - /* uggh, EAs for OS2 */ - DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return ERROR_DOS(ERRDOS,ERReasnotsupported); - } + set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE; + set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE; switch (info_level) { case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: { + if (total_data < l1_cbFile+4) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + /* access time */ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); /* write time */ tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - mode = SVAL(pdata,l1_attrFile); + dosmode = SVAL(pdata,l1_attrFile); size = IVAL(pdata,l1_cbFile); + break; } @@ -2078,18 +2342,24 @@ static int call_trans2setfilepathinfo(connection_struct *conn, it's also not in the cifs6.txt spec. */ case SMB_INFO_QUERY_EAS_FROM_LIST: + if (total_data < 28) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); size = IVAL(pdata,16); - mode = IVAL(pdata,24); + dosmode = IVAL(pdata,24); break; /* XXXX nor this. not in cifs6.txt, either. */ case SMB_INFO_QUERY_ALL_EAS: + if (total_data < 28) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); size = IVAL(pdata,16); - mode = IVAL(pdata,24); + dosmode = IVAL(pdata,24); break; case SMB_SET_FILE_BASIC_INFO: @@ -2099,6 +2369,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, time_t write_time; time_t changed_time; + if (total_data < 36) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + /* Ignore create time at offset pdata. */ /* access time */ @@ -2109,21 +2382,28 @@ static int call_trans2setfilepathinfo(connection_struct *conn, tvs.modtime = MIN(write_time, changed_time); + if (write_time > tvs.modtime && write_time != 0xffffffff) { + tvs.modtime = write_time; + } /* Prefer a defined time to an undefined one. */ if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1 ? changed_time : write_time); /* attributes */ - mode = IVAL(pdata,32); + dosmode = IVAL(pdata,32); break; } - case SMB_FILE_ALLOCATION_INFORMATION: + case SMB_FILE_ALLOCATION_INFORMATION: case SMB_SET_FILE_ALLOCATION_INFO: { int ret = -1; SMB_OFF_T allocation_size = IVAL(pdata,0); + + if (total_data < 8) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + #ifdef LARGE_SMB_OFF_T allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ @@ -2163,14 +2443,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); ret = vfs_allocate_file_space(new_fsp, allocation_size); if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno))); + DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", + new_fsp->fnum, strerror(errno))); ret = -1; } close_file(new_fsp,True); } else { ret = vfs_allocate_file_space(fsp, allocation_size); if (vfs_fstat(fsp,fd,&new_sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); + DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", + fsp->fnum, strerror(errno))); ret = -1; } } @@ -2184,9 +2466,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } - case SMB_FILE_END_OF_FILE_INFORMATION: + case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_SET_FILE_END_OF_FILE_INFO: { + if (total_data < 8) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); @@ -2204,6 +2489,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, BOOL delete_on_close = (CVAL(pdata,0) ? True : False); NTSTATUS status; + if (total_data < 1) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (tran_call != TRANSACT2_SETFILEINFO) return ERROR_DOS(ERRDOS,ERRunknownlevel); @@ -2218,6 +2506,183 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + /* + * CIFS UNIX extensions. + */ + + case SMB_SET_FILE_UNIX_BASIC: + { + uint32 raw_unixmode; + + if (total_data < 100) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && + IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { + size=IVAL(pdata,0); /* first 8 Bytes are size */ +#ifdef LARGE_SMB_OFF_T + size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); +#endif /* LARGE_SMB_OFF_T */ + } + pdata+=24; /* ctime & st_blocks are not changed */ + tvs.actime = interpret_long_unix_date(pdata); /* access_time */ + tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */ + pdata+=16; + set_owner = (uid_t)IVAL(pdata,0); + pdata += 8; + set_grp = (gid_t)IVAL(pdata,0); + pdata += 8; + raw_unixmode = IVAL(pdata,28); + unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode); + dosmode = 0; /* Ensure dos mode change doesn't override this. */ + + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \ +size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", + fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode)); + + if (!VALID_STAT(sbuf)) { + + /* + * The only valid use of this is to create character and block + * devices, and named pipes. This is deprecated (IMHO) and + * a new info level should be used for mknod. JRA. + */ + +#if !defined(HAVE_MAKEDEV_FN) + return(ERROR_DOS(ERRDOS,ERRnoaccess)); +#else /* HAVE_MAKEDEV_FN */ + uint32 file_type = IVAL(pdata,0); + uint32 dev_major = IVAL(pdata,4); + uint32 dev_minor = IVAL(pdata,12); + + uid_t myuid = geteuid(); + gid_t mygid = getegid(); + SMB_DEV_T dev; + + if (tran_call == TRANSACT2_SETFILEINFO) + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + + if (raw_unixmode == SMB_MODE_NO_CHANGE) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + dev = makedev(dev_major, dev_minor); + + /* We can only create as the owner/group we are. */ + + if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE)) + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE)) + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + + if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV && + file_type != UNIX_TYPE_FIFO) + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ +0%o for file %s\n", (double)dev, unixmode, fname )); + + /* Ok - do the mknod. */ + if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); +#endif /* HAVE_MAKEDEV_FN */ + + } + + /* + * Deal with the UNIX specific mode set. + */ + + if (raw_unixmode != SMB_MODE_NO_CHANGE) { + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", + (unsigned int)unixmode, fname )); + if (vfs_chmod(conn,fname,unixmode) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* + * Deal with the UNIX specific uid set. + */ + + if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) { + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", + (unsigned int)set_owner, fname )); + if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* + * Deal with the UNIX specific gid set. + */ + + if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) { + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", + (unsigned int)set_owner, fname )); + if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + break; + } + + case SMB_SET_FILE_UNIX_LINK: + { + pstring link_dest; + /* Set a symbolic link. */ + /* Don't allow this if follow links is false. */ + + if (!lp_symlinks(SNUM(conn))) + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + + /* Disallow if already exists. */ + if (VALID_STAT(sbuf)) + return(ERROR_DOS(ERRDOS,ERRbadpath)); + + srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE); + + if (ensure_link_is_safe(conn, link_dest, link_dest) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", + fname, link_dest )); + + if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + + case SMB_SET_FILE_UNIX_HLINK: + { + pstring link_dest; + + /* Set a hard link. */ + + /* Disallow if already exists. */ + if (VALID_STAT(sbuf)) + return(ERROR_DOS(ERRDOS,ERRbadpath)); + + srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE); + + if (ensure_link_is_safe(conn, link_dest, link_dest) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", + fname, link_dest )); + + if (conn->vfs_ops.link(conn,link_dest,fname) != 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + default: return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -2232,17 +2697,18 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); DEBUG(6,("size: %.0f ", (double)size)); - DEBUG(6,("mode: %x\n" , mode)); if (S_ISDIR(sbuf.st_mode)) - mode |= aDIR; + dosmode |= aDIR; else - mode &= ~aDIR; + dosmode &= ~aDIR; + + DEBUG(6,("dosmode: %x\n" , dosmode)); if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || (info_level == SMB_SET_FILE_ALLOCATION_INFO) || (info_level == SMB_FILE_ALLOCATION_INFORMATION) || - (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) { + (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) { /* * Only do this test if we are not explicitly @@ -2263,7 +2729,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * NT does this a lot. It's actually pointless * setting the time here, as it will be overwritten * on the next write, so we save the request - * away and will set it on file code. JRA. + * away and will set it on file close. JRA. */ if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { @@ -2281,11 +2747,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } /* check the mode isn't different, before changing it */ - if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) { + if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) { - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode )); + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode )); - if(file_chmod(conn, fname, mode, NULL)) { + if(file_chmod(conn, fname, dosmode, NULL)) { DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2331,7 +2797,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); @@ -2343,48 +2808,45 @@ static int call_trans2setfilepathinfo(connection_struct *conn, static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, char **ppdata) + char **pparams, int total_params, char **ppdata, int total_data) { - char *params = *pparams; - pstring directory; - int ret = -1; - SMB_STRUCT_STAT sbuf; - BOOL bad_path = False; + char *params = *pparams; + pstring directory; + int ret = -1; + SMB_STRUCT_STAT sbuf; + BOOL bad_path = False; + + if (!CAN_WRITE(conn)) + return ERROR_DOS(ERRSRV,ERRaccess); - if (!CAN_WRITE(conn)) - return ERROR_DOS(ERRSRV,ERRaccess); + if (total_params < 4) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); - srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE); + srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE); - DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); + DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,conn,0,&bad_path,&sbuf); - if (check_name(directory,conn)) - ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); + unix_convert(directory,conn,0,&bad_path,&sbuf); + if (check_name(directory,conn)) + ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); - if(ret < 0) - { - DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,2); - if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *pparams = params; - - SSVAL(params,0,0); - - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + if(ret < 0) { + DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* Realloc the parameter and data sizes */ + params = Realloc(*pparams,2); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + *pparams = params; + + SSVAL(params,0,0); + + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - return(-1); + return(-1); } /**************************************************************************** @@ -2393,44 +2855,45 @@ static int call_trans2mkdir(connection_struct *conn, ****************************************************************************/ static int call_trans2findnotifyfirst(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **pparams, char **ppdata) + char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - static uint16 fnf_handle = 257; - char *params = *pparams; - uint16 info_level = SVAL(params,4); - - DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level)); - - switch (info_level) - { - case 1: - case 2: - break; - default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); - } - - /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,6); - if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *pparams = params; - - SSVAL(params,0,fnf_handle); - SSVAL(params,2,0); /* No changes */ - SSVAL(params,4,0); /* No EA errors */ - - fnf_handle++; - - if(fnf_handle == 0) - fnf_handle = 257; - - send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0); + static uint16 fnf_handle = 257; + char *params = *pparams; + uint16 info_level; + + if (total_params < 6) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + info_level = SVAL(params,4); + DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level)); + + switch (info_level) { + case 1: + case 2: + break; + default: + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* Realloc the parameter and data sizes */ + params = Realloc(*pparams,6); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + *pparams = params; + + SSVAL(params,0,fnf_handle); + SSVAL(params,2,0); /* No changes */ + SSVAL(params,4,0); /* No EA errors */ + + fnf_handle++; + + if(fnf_handle == 0) + fnf_handle = 257; + + send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0); - return(-1); + return(-1); } /**************************************************************************** @@ -2439,27 +2902,25 @@ static int call_trans2findnotifyfirst(connection_struct *conn, ****************************************************************************/ static int call_trans2findnotifynext(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **pparams, char **ppdata) + char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - char *params = *pparams; + char *params = *pparams; - DEBUG(3,("call_trans2findnotifynext\n")); + DEBUG(3,("call_trans2findnotifynext\n")); - /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,4); - if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *pparams = params; + /* Realloc the parameter and data sizes */ + params = Realloc(*pparams,4); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + *pparams = params; - SSVAL(params,0,0); /* No changes */ - SSVAL(params,2,0); /* No EA errors */ + SSVAL(params,0,0); /* No changes */ + SSVAL(params,2,0); /* No EA errors */ - send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0); - return(-1); + return(-1); } /**************************************************************************** @@ -2467,29 +2928,33 @@ static int call_trans2findnotifynext(connection_struct *conn, ****************************************************************************/ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, - char* outbuf, int length, int bufsize, - char** pparams, char** ppdata) + char* outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - char *params = *pparams; - pstring pathname; - int reply_size = 0; - int max_referral_level = SVAL(params,0); + char *params = *pparams; + pstring pathname; + int reply_size = 0; + int max_referral_level; + DEBUG(10,("call_trans2getdfsreferral\n")); - DEBUG(10,("call_trans2getdfsreferral\n")); + if (total_params < 2) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); - if(!lp_host_msdfs()) - return ERROR_DOS(ERRDOS,ERRbadfunc); + max_referral_level = SVAL(params,0); - srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); + if(!lp_host_msdfs()) + return ERROR_DOS(ERRDOS,ERRbadfunc); - if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) - return ERROR_DOS(ERRDOS,ERRbadfile); + srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); + + if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) + return ERROR_DOS(ERRDOS,ERRbadfile); - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); - send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); + send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); - return(-1); + return(-1); } #define LMCAT_SPL 0x53 @@ -2500,32 +2965,31 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, ****************************************************************************/ static int call_trans2ioctl(connection_struct *conn, char* inbuf, - char* outbuf, int length, int bufsize, - char** pparams, char** ppdata) + char* outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data) { - char *pdata = *ppdata; - files_struct *fsp = file_fsp(inbuf,smb_vwv15); - - if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && - (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { - pdata = Realloc(*ppdata, 32); - if(pdata == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); - } - *ppdata = pdata; - - /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 - CAN ACCEPT THIS IN UNICODE. JRA. */ - - SSVAL(pdata,0,fsp->print_jobid); /* Job number */ - srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ - srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ - send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); - return(-1); - } else { - DEBUG(2,("Unknown TRANS2_IOCTL\n")); - return ERROR_DOS(ERRSRV,ERRerror); - } + char *pdata = *ppdata; + files_struct *fsp = file_fsp(inbuf,smb_vwv15); + + if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && + (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + pdata = Realloc(*ppdata, 32); + if(pdata == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + *ppdata = pdata; + + /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 + CAN ACCEPT THIS IN UNICODE. JRA. */ + + SSVAL(pdata,0,fsp->print_jobid); /* Job number */ + srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ + srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ + send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); + return(-1); + } else { + DEBUG(2,("Unknown TRANS2_IOCTL\n")); + return ERROR_DOS(ERRSRV,ERRerror); + } } /**************************************************************************** @@ -2736,93 +3200,84 @@ int reply_trans2(connection_struct *conn, switch(tran_call) { case TRANSACT2_OPEN: START_PROFILE_NESTED(Trans2_open); - outsize = call_trans2open(conn, - inbuf, outbuf, bufsize, - ¶ms, &data); + outsize = call_trans2open(conn, inbuf, outbuf, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_open); break; case TRANSACT2_FINDFIRST: START_PROFILE_NESTED(Trans2_findfirst); - outsize = call_trans2findfirst(conn, inbuf, outbuf, - bufsize, ¶ms, &data); + outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_findfirst); break; case TRANSACT2_FINDNEXT: START_PROFILE_NESTED(Trans2_findnext); - outsize = call_trans2findnext(conn, inbuf, outbuf, - length, bufsize, - ¶ms, &data); + outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_findnext); break; case TRANSACT2_QFSINFO: START_PROFILE_NESTED(Trans2_qfsinfo); - outsize = call_trans2qfsinfo(conn, inbuf, outbuf, - length, bufsize, ¶ms, - &data); + outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_qfsinfo); break; case TRANSACT2_SETFSINFO: START_PROFILE_NESTED(Trans2_setfsinfo); - outsize = call_trans2setfsinfo(conn, inbuf, outbuf, - length, bufsize, - ¶ms, &data); + outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_setfsinfo); break; case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: START_PROFILE_NESTED(Trans2_qpathinfo); - outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, - length, bufsize, - ¶ms, &data, total_data); + outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_qpathinfo); break; case TRANSACT2_SETPATHINFO: case TRANSACT2_SETFILEINFO: START_PROFILE_NESTED(Trans2_setpathinfo); - outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, - length, bufsize, - ¶ms, &data, - total_data); + outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_setpathinfo); break; case TRANSACT2_FINDNOTIFYFIRST: START_PROFILE_NESTED(Trans2_findnotifyfirst); - outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, - length, bufsize, - ¶ms, &data); + outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_findnotifyfirst); break; case TRANSACT2_FINDNOTIFYNEXT: START_PROFILE_NESTED(Trans2_findnotifynext); - outsize = call_trans2findnotifynext(conn, inbuf, outbuf, - length, bufsize, - ¶ms, &data); + outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_findnotifynext); break; case TRANSACT2_MKDIR: START_PROFILE_NESTED(Trans2_mkdir); - outsize = call_trans2mkdir(conn, inbuf, outbuf, length, - bufsize, ¶ms, &data); + outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_mkdir); break; case TRANSACT2_GET_DFS_REFERRAL: START_PROFILE_NESTED(Trans2_get_dfs_referral); - outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, - bufsize, ¶ms, &data); + outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_get_dfs_referral); break; case TRANSACT2_IOCTL: START_PROFILE_NESTED(Trans2_ioctl); - outsize = call_trans2ioctl(conn,inbuf,outbuf,length, - bufsize,¶ms,&data); + outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize, + ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_ioctl); break; default: diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index ac0b535c13..a18f62c9cc 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -465,11 +465,11 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N if (ret) { DEBUG(10, - ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %u)\n", + ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", domain, name, sid_to_string(sid,psid), - (unsigned int)*name_type )); + sid_type_lookup(*name_type), (unsigned int)*name_type)); return True; - } else if (winbind_lookup_name(domain, name, psid, name_type) || (*name_type != SID_NAME_USER) ) { + } else if (winbind_lookup_name(domain, name, psid, name_type)) { DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", domain, name, sid_to_string(sid, psid), @@ -504,7 +504,7 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE sid_copy(&tmp_sid, sid); sid_split_rid(&tmp_sid, &rid); - if (sid_equal(&global_sam_sid, &tmp_sid)) { + if (sid_equal(get_global_sam_sid(), &tmp_sid)) { return map_domain_sid_to_name(&tmp_sid, dom_name) && local_lookup_sid(sid, name, name_type); @@ -521,7 +521,7 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE sid_copy(&tmp_sid, sid); sid_split_rid(&tmp_sid, &rid); return map_domain_sid_to_name(&tmp_sid, dom_name) && - lookup_known_rid(&tmp_sid, rid, name, name_type); + lookup_known_rid(&tmp_sid, rid, name, name_type); } return True; } @@ -578,7 +578,8 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) } } - local_gid_to_sid(psid, gid); + /* Make sure we report failure, (when psid == NULL) */ + psid = local_gid_to_sid(psid, gid); DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); @@ -597,7 +598,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) fstring sid_str; /* if we know its local then don't try winbindd */ - if (sid_compare_domain(&global_sam_sid, psid) == 0) { + if (sid_compare_domain(get_global_sam_sid(), psid) == 0) { return local_sid_to_uid(puid, psid, sidtype); } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index fadc435a2f..394086dc07 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -147,7 +147,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) ssize_t result; START_PROFILE_BYTES(syscall_read, n); - result = read(fd, data, n); + result = sys_read(fd, data, n); END_PROFILE(syscall_read); return result; } @@ -157,7 +157,7 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) ssize_t result; START_PROFILE_BYTES(syscall_write, n); - result = write(fd, data, n); + result = sys_write(fd, data, n); END_PROFILE(syscall_write); return result; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 4e2e353ed8..5e1dc68bdb 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -32,7 +32,7 @@ struct vfs_syminfo { very important. They must be in the same order as defined in vfs.h. Change at your own peril. */ -struct vfs_ops default_vfs_ops = { +static struct vfs_ops default_vfs_ops = { /* Disk operations */ @@ -139,7 +139,7 @@ static BOOL vfs_init_custom(connection_struct *conn) /* Open object file */ if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { - DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror())); + DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), sys_dlerror())); return False; } @@ -222,7 +222,7 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ /******************************************************************* vfs getwd wrapper ********************************************************************/ -char *vfs_getwd(connection_struct *conn, char *path) +static char *vfs_getwd(connection_struct *conn, char *path) { return conn->vfs_ops.getwd(conn,path); } @@ -562,7 +562,7 @@ int vfs_ChDir(connection_struct *conn, char *path) /* number of list structures for a caching GetWd function. */ #define MAX_GETWDCACHE (50) -struct { +static 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 *dos_path; /* The pathname in DOS format. */ -- cgit From b0b28531c8cd76d3fcd95da08389d8a4d2e631a3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 11:16:26 +0000 Subject: more bug updates from head (This used to be commit 8b769bf5bbbe54b1a39fd85cc24db09c1ab7faab) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 217bb6a613..996a17e932 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1778,7 +1778,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c return False; /* get list of domain groups SID_DOMAIN_GRP=2 */ - if(!enum_group_mapping(2 , &group_list, &num_entries, False, False)) { + if(!enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) { DEBUG(3,("api_RNetGroupEnum:failed to get group list")); return False; } -- cgit From 127e77e6e334fdc33086bffcbe00d340c0ba0097 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Aug 2002 15:27:10 +0000 Subject: Sync 3.0 branch with head (This used to be commit 42615b945e2e48e53a21ea47f2e45407913a6a1e) --- source3/smbd/blocking.c | 23 +- source3/smbd/chgpasswd.c | 8 +- source3/smbd/conn.c | 23 +- source3/smbd/connection.c | 8 +- source3/smbd/dir.c | 69 ++++ source3/smbd/dosmode.c | 92 ++--- source3/smbd/fileio.c | 2 +- source3/smbd/filename.c | 1 - source3/smbd/lanman.c | 41 +- source3/smbd/mangle_hash2.c | 6 +- source3/smbd/negprot.c | 21 +- source3/smbd/nttrans.c | 960 +++++++++++++++++++++++--------------------- source3/smbd/password.c | 36 +- source3/smbd/posix_acls.c | 2 +- source3/smbd/process.c | 21 +- source3/smbd/reply.c | 53 ++- source3/smbd/server.c | 157 +++++--- source3/smbd/service.c | 36 +- source3/smbd/session.c | 74 ++-- source3/smbd/sesssetup.c | 119 +++--- source3/smbd/trans2.c | 88 ++-- source3/smbd/uid.c | 86 ++-- source3/smbd/vfs.c | 147 +++++-- 23 files changed, 1188 insertions(+), 885 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index d4a53d9a6d..6623c6df64 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -282,9 +282,10 @@ static BOOL process_lockread(blocking_lock_record *blr) status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, READ_LOCK); if (NT_STATUS_V(status)) { - if ((errno != EACCES) && (errno != EAGAIN)) { + if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && + !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { /* - * We have other than a "can't get lock" POSIX + * We have other than a "can't get lock" * error. Send an error. * Return True so we get dequeued. */ @@ -348,9 +349,10 @@ static BOOL process_lock(blocking_lock_record *blr) status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, (SMB_BIG_UINT)offset, WRITE_LOCK); if (NT_STATUS_IS_ERR(status)) { - if((errno != EACCES) && (errno != EAGAIN)) { + if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && + !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { /* - * We have other than a "can't get lock" POSIX + * We have other than a "can't get lock" * error. Send an error. * Return True so we get dequeued. */ @@ -432,12 +434,13 @@ static BOOL process_lockingX(blocking_lock_record *blr) reply_lockingX_success(blr); return True; - } else if ((errno != EACCES) && (errno != EAGAIN)) { - /* - * We have other than a "can't get lock" POSIX - * error. Free any locks we had and return an error. - * Return True so we get dequeued. - */ + } else if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && + !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { + /* + * We have other than a "can't get lock" + * error. Free any locks we had and return an error. + * Return True so we get dequeued. + */ blocking_lock_reply_error(blr, status); return True; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 68871deb90..9e593b022e 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -167,17 +167,17 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, /* Make slave stdin/out/err of child. */ - if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) + if (sys_dup2(slave, STDIN_FILENO) != STDIN_FILENO) { DEBUG(3, ("Could not re-direct stdin\n")); return (False); } - if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) + if (sys_dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) { DEBUG(3, ("Could not re-direct stdout\n")); return (False); } - if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) + if (sys_dup2(slave, STDERR_FILENO) != STDERR_FILENO) { DEBUG(3, ("Could not re-direct stderr\n")); return (False); @@ -196,7 +196,9 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, } stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); stermios.c_lflag |= ICANON; +#ifdef ONLCR stermios.c_oflag &= ~(ONLCR); +#endif if (tcsetattr(0, TCSANOW, &stermios) < 0) { DEBUG(3, ("could not set attributes of pty\n")); diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index c0aa447016..d70e50f899 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Manage connections_struct structures Copyright (C) Andrew Tridgell 1998 + Copyright (C) Alexander Bokovoy 2002 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 @@ -162,11 +163,25 @@ BOOL conn_idle_all(time_t t, int deadtime) void conn_free(connection_struct *conn) { + smb_vfs_handle_struct *handle, *thandle; + void (*done_fptr)(connection_struct *the_conn); + /* Free vfs_connection_struct */ - - if (conn->dl_handle != NULL) { - /* Close dlopen() handle */ - sys_dlclose(conn->dl_handle); + handle = conn->vfs_private; + while(handle) { + /* Close dlopen() handle */ + done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done"); + + if (done_fptr == NULL) { + DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle)); + } else { + done_fptr(conn); + } + sys_dlclose(handle->handle); + DLIST_REMOVE(conn->vfs_private, handle); + thandle = handle->next; + SAFE_FREE(handle); + handle = thandle; } DLIST_REMOVE(Connections, conn); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index c9815dbf8c..5609c2963d 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -20,7 +20,6 @@ #include "includes.h" -extern fstring remote_machine; static TDB_CONTEXT *tdb; /**************************************************************************** @@ -29,6 +28,11 @@ static TDB_CONTEXT *tdb; TDB_CONTEXT *conn_tdb_ctx(void) { + if (!tdb) { + tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644); + } + return tdb; } @@ -173,7 +177,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO } crec.start = time(NULL); - StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); + StrnCpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1); StrnCpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1); dbuf.dptr = (char *)&crec; diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7dd425ef8a..1a18476b75 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -721,6 +721,62 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) &access_granted, &status); } +/******************************************************************* +check to see if a user can write a file (and only files, we do not +check dirs on this one). This is only approximate, +it is used as part of the "hide unwriteable" option. Don't +use it for anything security sensitive +********************************************************************/ + +static BOOL user_can_write_file(connection_struct *conn, char *name) +{ + extern struct current_user current_user; + SMB_STRUCT_STAT ste; + SEC_DESC *psd = NULL; + size_t sd_size; + files_struct *fsp; + int smb_action; + int access_mode; + NTSTATUS status; + uint32 access_granted; + + ZERO_STRUCT(ste); + + /* + * If user is a member of the Admin group + * we never hide files from them. + */ + + if (conn->admin_user) + return True; + + /* If we can't stat it does not show it */ + if (vfs_stat(conn, name, &ste) != 0) + return False; + + /* Pseudo-open the file (note - no fd's created). */ + + if(S_ISDIR(ste.st_mode)) + return True; + else + fsp = open_file_shared1(conn, name, &ste, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + + if (!fsp) + return False; + + /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ + sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + close_file(fsp, False); + + /* No access if SD get failed. */ + if (!sd_size) + return False; + + return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA, + &access_granted, &status); +} + /******************************************************************* Open a directory. ********************************************************************/ @@ -781,6 +837,19 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) continue; } + /* Honour _hide unwriteable_ option */ + if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) { + char *entry; + int ret=0; + + if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { + ret = user_can_write_file(conn, entry); + SAFE_FREE(entry); + } + if (!ret) + continue; + } + if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index dcffe3aa90..77d8c9cc92 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -115,65 +115,67 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) /**************************************************************************** change a unix mode to a dos mode ****************************************************************************/ -int dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) +uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) { - int result = 0; + int result = 0; - DEBUG(8,("dos_mode: %s\n", path)); + DEBUG(8,("dos_mode: %s\n", path)); - if ((sbuf->st_mode & S_IWUSR) == 0) - result |= aRONLY; + if ((sbuf->st_mode & S_IWUSR) == 0) + result |= aRONLY; + + if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) + result |= aARCH; - if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) - result |= aARCH; - - if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) - result |= aSYSTEM; - - if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) - result |= aHIDDEN; + if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) + result |= aSYSTEM; + + if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) + result |= aHIDDEN; - if (S_ISDIR(sbuf->st_mode)) - result = aDIR | (result & aRONLY); + if (S_ISDIR(sbuf->st_mode)) + result = aDIR | (result & aRONLY); + + if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)sbuf->st_blksize) { + result |= FILE_ATTRIBUTE_SPARSE; + } #ifdef S_ISLNK #if LINKS_READ_ONLY - if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) - result |= aRONLY; + if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) + result |= aRONLY; #endif #endif - /* hide files with a name starting with a . */ - if (lp_hide_dot_files(SNUM(conn))) - { - char *p = strrchr_m(path,'/'); - if (p) - p++; - else - p = path; - - if (p[0] == '.' && p[1] != '.' && p[1] != 0) - result |= aHIDDEN; - } - - /* Optimization : Only call is_hidden_path if it's not already - hidden. */ - if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) - { - result |= aHIDDEN; - } - - DEBUG(8,("dos_mode returning ")); + /* hide files with a name starting with a . */ + if (lp_hide_dot_files(SNUM(conn))) { + char *p = strrchr_m(path,'/'); + if (p) + p++; + else + p = path; + + if (p[0] == '.' && p[1] != '.' && p[1] != 0) + result |= aHIDDEN; + } + + /* Optimization : Only call is_hidden_path if it's not already + hidden. */ + if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { + result |= aHIDDEN; + } - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); + DEBUG(8,("dos_mode returning ")); - DEBUG(8,("\n")); + if (result & aHIDDEN) DEBUG(8, ("h")); + if (result & aRONLY ) DEBUG(8, ("r")); + if (result & aSYSTEM) DEBUG(8, ("s")); + if (result & aDIR ) DEBUG(8, ("d")); + if (result & aARCH ) DEBUG(8, ("a")); + + DEBUG(8,("\n")); - return(result); + return(result); } /******************************************************************* diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 710ba396d8..89f05092b4 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -163,7 +163,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) int write_path = -1; if (fsp->print_file) - return print_job_write(fsp->print_jobid, data, n); + return print_job_write(SNUM(fsp->conn), fsp->print_jobid, data, n); if (!fsp->can_write) { errno = EPERM; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index e5f9b7a0ae..ce98af4ace 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -29,7 +29,6 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -extern fstring remote_machine; extern BOOL use_mangled_map; static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 996a17e932..8bfad4ab33 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -443,7 +443,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, /* the client expects localtime */ t -= TimeDiff(t); - PACKI(desc,"W",queue->job); /* uJobId */ + PACKI(desc,"W",pjobid_to_rap(snum,queue->job)); /* uJobId */ if (uLevel == 1) { PACKS(desc,"B21",queue->fs_user); /* szUserName */ PACKS(desc,"B",""); /* pad */ @@ -933,7 +933,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, if (!mdrcnt && lp_disable_spoolss()) desc.errcode = ERRbuftoosmall; - *rdata_len = desc.usedlen; + *rdata_len = desc.usedlen; *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); @@ -2181,11 +2181,14 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int jobid, errcode; + uint32 jobid; + int snum; + int errcode; extern struct current_user current_user; WERROR werr = WERR_OK; - jobid = SVAL(p,0); + if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid)) + return False; /* check it's a supported varient */ if (!(strcsequal(str1,"W") && strcsequal(str2,""))) @@ -2195,7 +2198,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param *rparam = REALLOC(*rparam,*rparam_len); *rdata_len = 0; - if (!print_job_exists(jobid)) { + if (!print_job_exists(snum, jobid)) { errcode = NERR_JobNotFound; goto out; } @@ -2204,15 +2207,15 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param switch (function) { case 81: /* delete */ - if (print_job_delete(¤t_user, jobid, &werr)) + if (print_job_delete(¤t_user, snum, jobid, &werr)) errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(¤t_user, jobid, &werr)) + if (print_job_pause(¤t_user, snum, jobid, &werr)) errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(¤t_user, jobid, &werr)) + if (print_job_resume(¤t_user, snum, jobid, &werr)) errcode = NERR_Success; break; } @@ -2313,12 +2316,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int jobid; + uint32 jobid; + int snum; int uLevel = SVAL(p,2); int function = SVAL(p,4); int place, errcode; - jobid = SVAL(p,0); + if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid)) + return False; *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); @@ -2329,7 +2334,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha (!check_printjob_info(&desc,uLevel,str2))) return(False); - if (!print_job_exists(jobid)) { + if (!print_job_exists(snum, jobid)) { errcode=NERR_JobNotFound; goto out; } @@ -2341,14 +2346,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha /* change job place in the queue, data gives the new place */ place = SVAL(data,0); - if (print_job_set_place(jobid, place)) { + if (print_job_set_place(snum, jobid, place)) { errcode=NERR_Success; } break; case 0xb: /* change print job name, data gives the name */ - if (print_job_set_name(jobid, data)) { + if (print_job_set_name(snum, jobid, data)) { errcode=NERR_Success; } break; @@ -2994,7 +2999,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para int count; int i; int snum; - int job; + uint32 jobid; struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; @@ -3011,14 +3016,14 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para if (strcmp(str1,"WWrLh") != 0) return False; if (!check_printjob_info(&desc,uLevel,str2)) return False; - job = SVAL(p,0); - snum = print_job_snum(job); + if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid)) + return False; if (snum < 0 || !VALID_SNUM(snum)) return(False); count = print_queue_status(snum,&queue,&status); for (i = 0; i < count; i++) { - if (queue[i].job == job) break; + if (queue[i].job == jobid) break; } if (mdrcnt > 0) { @@ -3549,7 +3554,7 @@ static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,cha -struct +const static struct { char *name; int id; diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index e2c4b43bc3..6b53cc72aa 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -202,13 +202,13 @@ static BOOL is_mangled_component(const char *name) M_DEBUG(0,("is_mangled_component %s ?\n", name)); - /* the best distinguishing characteristic is the ~ */ - if (name[6] != '~') return False; - /* check the length */ len = strlen(name); if (len > 12 || len < 8) return False; + /* the best distinguishing characteristic is the ~ */ + if (name[6] != '~') return False; + /* check extension */ if (len > 8) { if (name[8] != '.') return False; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 81c2427a00..2be04fd686 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -23,7 +23,6 @@ extern int Protocol; extern int max_recv; extern fstring global_myworkgroup; -extern fstring remote_machine; BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; struct auth_context *negprot_global_auth_context = NULL; @@ -200,14 +199,11 @@ static int negprot_spnego(char *p) if (lp_security() != SEC_ADS) { blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); } else { - ADS_STRUCT *ads; - ads = ads_init_simple(); /* win2000 uses host$@REALM, which we will probably use eventually, but for now this works */ - asprintf(&principal, "HOST/%s@%s", guid, ads->realm); + asprintf(&principal, "HOST/%s@%s", guid, lp_realm()); blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal); free(principal); - ads_destroy(&ads); } memcpy(p, blob.data, blob.length); len = blob.length; @@ -288,10 +284,12 @@ static int reply_nt1(char *inbuf, char *outbuf) if (!negotiate_spnego) { /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { + /* note that we do not send a challenge at all if + we are using plaintext */ get_challenge(p); + SSVALS(outbuf,smb_vwv16+1,8); + p += 8; } - SSVALS(outbuf,smb_vwv16+1,8); - p += 8; p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); @@ -412,8 +410,17 @@ int reply_negprot(connection_struct *conn, char *p; int bcc = SVAL(smb_buf(inbuf),-2); int arch = ARCH_ALL; + + static BOOL done_negprot = False; + START_PROFILE(SMBnegprot); + if (done_negprot) { + END_PROFILE(SMBnegprot); + exit_server("multiple negprot's are not permitted"); + } + done_negprot = True; + p = smb_buf(inbuf)+1; while (p < (smb_buf(inbuf) + bcc)) { Index++; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e0a0da7a75..cf69dfddb0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -28,19 +28,19 @@ extern BOOL case_preserve; extern BOOL short_case_preserve; static char *known_nt_pipes[] = { - "\\LANMAN", - "\\srvsvc", - "\\samr", - "\\wkssvc", - "\\NETLOGON", - "\\ntlsa", - "\\ntsvcs", - "\\lsass", - "\\lsarpc", - "\\winreg", - "\\spoolss", - "\\netdfs", - NULL + "\\LANMAN", + "\\srvsvc", + "\\samr", + "\\wkssvc", + "\\NETLOGON", + "\\ntlsa", + "\\ntsvcs", + "\\lsass", + "\\lsarpc", + "\\winreg", + "\\spoolss", + "\\netdfs", + NULL }; /* Map generic permissions to file object specific permissions */ @@ -62,184 +62,183 @@ struct generic_mapping file_generic_mapping = { static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params, int paramsize, char *pdata, int datasize) { - extern int max_send; - int data_to_send = datasize; - int params_to_send = paramsize; - int useable_space; - char *pp = params; - char *pd = pdata; - int params_sent_thistime, data_sent_thistime, total_sent_thistime; - int alignment_offset = 3; - int data_alignment_offset = 0; - - /* - * Initially set the wcnt area to be 18 - this is true for all - * transNT replies. - */ - - set_message(outbuf,18,0,True); - - if (NT_STATUS_V(nt_error)) { - ERROR_NT(nt_error); - } - - /* - * If there genuinely are no parameters or data to send just send - * the empty packet. - */ - - if(params_to_send == 0 && data_to_send == 0) { - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_nt_replies: send_smb failed."); - return 0; - } - - /* - * When sending params and data ensure that both are nicely aligned. - * Only do this alignment when there is also data to send - else - * can cause NT redirector problems. - */ - - if (((params_to_send % 4) != 0) && (data_to_send != 0)) - data_alignment_offset = 4 - (params_to_send % 4); - - /* - * Space is bufsize minus Netbios over TCP header minus SMB header. - * The alignment_offset is to align the param bytes on a four byte - * boundary (2 bytes for data len, one byte pad). - * NT needs this to work correctly. - */ - - useable_space = bufsize - ((smb_buf(outbuf)+ - alignment_offset+data_alignment_offset) - - outbuf); - - /* - * useable_space can never be more than max_send minus the - * alignment offset. - */ - - useable_space = MIN(useable_space, - max_send - (alignment_offset+data_alignment_offset)); - - - while (params_to_send || data_to_send) { - - /* - * Calculate whether we will totally or partially fill this packet. - */ - - total_sent_thistime = params_to_send + data_to_send + - alignment_offset + data_alignment_offset; - - /* - * We can never send more than useable_space. - */ - - total_sent_thistime = MIN(total_sent_thistime, useable_space); - - set_message(outbuf, 18, total_sent_thistime, True); - - /* - * Set total params and data to be sent. - */ - - SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize); - SIVAL(outbuf,smb_ntr_TotalDataCount,datasize); - - /* - * Calculate how many parameters and data we can fit into - * this packet. Parameters get precedence. - */ - - params_sent_thistime = MIN(params_to_send,useable_space); - data_sent_thistime = useable_space - params_sent_thistime; - data_sent_thistime = MIN(data_sent_thistime,data_to_send); - - SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime); - - if(params_sent_thistime == 0) { - SIVAL(outbuf,smb_ntr_ParameterOffset,0); - SIVAL(outbuf,smb_ntr_ParameterDisplacement,0); - } else { - /* - * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the - * parameter bytes, however the first 4 bytes of outbuf are - * the Netbios over TCP header. Thus use smb_base() to subtract - * them from the calculation. - */ - - SIVAL(outbuf,smb_ntr_ParameterOffset, - ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); - /* - * Absolute displacement of param bytes sent in this packet. - */ - - SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params); - } - - /* - * Deal with the data portion. - */ - - SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime); - - if(data_sent_thistime == 0) { - SIVAL(outbuf,smb_ntr_DataOffset,0); - SIVAL(outbuf,smb_ntr_DataDisplacement, 0); - } else { - /* - * The offset of the data bytes is the offset of the - * parameter bytes plus the number of parameters being sent this time. - */ - - SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) - - smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); - SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata); - } + extern int max_send; + int data_to_send = datasize; + int params_to_send = paramsize; + int useable_space; + char *pp = params; + char *pd = pdata; + int params_sent_thistime, data_sent_thistime, total_sent_thistime; + int alignment_offset = 3; + int data_alignment_offset = 0; - /* - * Copy the param bytes into the packet. - */ + /* + * Initially set the wcnt area to be 18 - this is true for all + * transNT replies. + */ + + set_message(outbuf,18,0,True); + + if (NT_STATUS_V(nt_error)) + ERROR_NT(nt_error); + + /* + * If there genuinely are no parameters or data to send just send + * the empty packet. + */ + + if(params_to_send == 0 && data_to_send == 0) { + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_nt_replies: send_smb failed."); + return 0; + } + + /* + * When sending params and data ensure that both are nicely aligned. + * Only do this alignment when there is also data to send - else + * can cause NT redirector problems. + */ + + if (((params_to_send % 4) != 0) && (data_to_send != 0)) + data_alignment_offset = 4 - (params_to_send % 4); + + /* + * Space is bufsize minus Netbios over TCP header minus SMB header. + * The alignment_offset is to align the param bytes on a four byte + * boundary (2 bytes for data len, one byte pad). + * NT needs this to work correctly. + */ + + useable_space = bufsize - ((smb_buf(outbuf)+ + alignment_offset+data_alignment_offset) - + outbuf); + + /* + * useable_space can never be more than max_send minus the + * alignment offset. + */ + + useable_space = MIN(useable_space, + max_send - (alignment_offset+data_alignment_offset)); - if(params_sent_thistime) - memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); - - /* - * Copy in the data bytes - */ - if(data_sent_thistime) - memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ - data_alignment_offset,pd,data_sent_thistime); + while (params_to_send || data_to_send) { + + /* + * Calculate whether we will totally or partially fill this packet. + */ + + total_sent_thistime = params_to_send + data_to_send + + alignment_offset + data_alignment_offset; + + /* + * We can never send more than useable_space. + */ + + total_sent_thistime = MIN(total_sent_thistime, useable_space); + + set_message(outbuf, 18, total_sent_thistime, True); + + /* + * Set total params and data to be sent. + */ + + SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize); + SIVAL(outbuf,smb_ntr_TotalDataCount,datasize); + + /* + * Calculate how many parameters and data we can fit into + * this packet. Parameters get precedence. + */ + + params_sent_thistime = MIN(params_to_send,useable_space); + data_sent_thistime = useable_space - params_sent_thistime; + data_sent_thistime = MIN(data_sent_thistime,data_to_send); + + SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime); + + if(params_sent_thistime == 0) { + SIVAL(outbuf,smb_ntr_ParameterOffset,0); + SIVAL(outbuf,smb_ntr_ParameterDisplacement,0); + } else { + /* + * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the + * parameter bytes, however the first 4 bytes of outbuf are + * the Netbios over TCP header. Thus use smb_base() to subtract + * them from the calculation. + */ + + SIVAL(outbuf,smb_ntr_ParameterOffset, + ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + /* + * Absolute displacement of param bytes sent in this packet. + */ + + SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params); + } + + /* + * Deal with the data portion. + */ + + SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime); + + if(data_sent_thistime == 0) { + SIVAL(outbuf,smb_ntr_DataOffset,0); + SIVAL(outbuf,smb_ntr_DataDisplacement, 0); + } else { + /* + * The offset of the data bytes is the offset of the + * parameter bytes plus the number of parameters being sent this time. + */ + + SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) - + smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); + SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata); + } + + /* + * Copy the param bytes into the packet. + */ + + if(params_sent_thistime) + memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + + /* + * Copy in the data bytes + */ + + if(data_sent_thistime) + memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ + data_alignment_offset,pd,data_sent_thistime); - DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", - params_sent_thistime, data_sent_thistime, useable_space)); - DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", - params_to_send, data_to_send, paramsize, datasize)); + DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", + params_sent_thistime, data_sent_thistime, useable_space)); + DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", + params_to_send, data_to_send, paramsize, datasize)); - /* Send the packet */ - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_nt_replies: send_smb failed."); + /* Send the packet */ + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_nt_replies: send_smb failed."); - pp += params_sent_thistime; - pd += data_sent_thistime; + pp += params_sent_thistime; + pd += data_sent_thistime; - params_to_send -= params_sent_thistime; - data_to_send -= data_sent_thistime; + params_to_send -= params_sent_thistime; + data_to_send -= data_sent_thistime; - /* - * Sanity check - */ + /* + * Sanity check + */ - if(params_to_send < 0 || data_to_send < 0) { - DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!", - params_to_send, data_to_send)); - return -1; - } - } + if(params_to_send < 0 || data_to_send < 0) { + DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!", + params_to_send, data_to_send)); + return -1; + } + } - return 0; + return 0; } /**************************************************************************** @@ -852,7 +851,7 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); + SOFF_T(p, 0, get_allocation_size(&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 12; @@ -1296,7 +1295,7 @@ static int call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); + SOFF_T(p, 0, get_allocation_size(&sbuf)); p += 8; SOFF_T(p,0,file_len); @@ -1311,6 +1310,7 @@ static int call_nt_transact_create(connection_struct *conn, /**************************************************************************** Reply to a NT CANCEL request. ****************************************************************************/ + int reply_ntcancel(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { @@ -1332,6 +1332,7 @@ int reply_ntcancel(connection_struct *conn, /**************************************************************************** Reply to an unsolicited SMBNTtranss - just ignore it! ****************************************************************************/ + int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { @@ -1345,6 +1346,7 @@ int reply_nttranss(connection_struct *conn, Reply to a notify change - queue the request and don't allow a directory to be opened. ****************************************************************************/ + static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1445,107 +1447,107 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, int length, int bufsize, char **ppsetup, char **ppparams, char **ppdata) { - uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); - char *params = *ppparams; - char *data = *ppdata; - prs_struct pd; - SEC_DESC *psd = NULL; - size_t sd_size; - TALLOC_CTX *mem_ctx; + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); + char *params = *ppparams; + char *data = *ppdata; + prs_struct pd; + SEC_DESC *psd = NULL; + size_t sd_size; + TALLOC_CTX *mem_ctx; - files_struct *fsp = file_fsp(params,0); + files_struct *fsp = file_fsp(params,0); - if(!fsp) - return ERROR_DOS(ERRDOS,ERRbadfid); + if(!fsp) + return ERROR_DOS(ERRDOS,ERRbadfid); - DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); + DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); - params = Realloc(*ppparams, 4); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + params = Realloc(*ppparams, 4); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; + *ppparams = params; - if ((mem_ctx = talloc_init()) == NULL) { - DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - return ERROR_DOS(ERRDOS,ERRnomem); - } + if ((mem_ctx = talloc_init()) == NULL) { + DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); + return ERROR_DOS(ERRDOS,ERRnomem); + } - /* - * Get the permissions to return. - */ + /* + * Get the permissions to return. + */ - if (!lp_nt_acl_support(SNUM(conn))) - sd_size = get_null_nt_acl(mem_ctx, &psd); - else - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + if (!lp_nt_acl_support(SNUM(conn))) + sd_size = get_null_nt_acl(mem_ctx, &psd); + else + sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); - if (sd_size == 0) { - talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if (sd_size == 0) { + talloc_destroy(mem_ctx); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size)); + DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size)); - SIVAL(params,0,(uint32)sd_size); + SIVAL(params,0,(uint32)sd_size); - if(max_data_count < sd_size) { + if(max_data_count < sd_size) { - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, - params, 4, *ppdata, 0); - talloc_destroy(mem_ctx); - return -1; - } + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, + params, 4, *ppdata, 0); + talloc_destroy(mem_ctx); + return -1; + } - /* - * Allocate the data we will point this at. - */ + /* + * Allocate the data we will point this at. + */ - data = Realloc(*ppdata, sd_size); - if(data == NULL) { - talloc_destroy(mem_ctx); - return ERROR_DOS(ERRDOS,ERRnomem); - } + data = Realloc(*ppdata, sd_size); + if(data == NULL) { + talloc_destroy(mem_ctx); + return ERROR_DOS(ERRDOS,ERRnomem); + } - *ppdata = data; + *ppdata = data; - memset(data, '\0', sd_size); + memset(data, '\0', sd_size); - /* - * Init the parse struct we will marshall into. - */ + /* + * Init the parse struct we will marshall into. + */ - prs_init(&pd, 0, mem_ctx, MARSHALL); + prs_init(&pd, 0, mem_ctx, MARSHALL); - /* - * Setup the prs_struct to point at the memory we just - * allocated. - */ + /* + * Setup the prs_struct to point at the memory we just + * allocated. + */ - prs_give_memory( &pd, data, (uint32)sd_size, False); + prs_give_memory( &pd, data, (uint32)sd_size, False); - /* - * Finally, linearize into the outgoing buffer. - */ + /* + * Finally, linearize into the outgoing buffer. + */ - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ + if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ security descriptor.\n")); - /* - * Return access denied for want of a better error message.. - */ - talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + /* + * Return access denied for want of a better error message.. + */ + talloc_destroy(mem_ctx); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - /* - * Now we can delete the security descriptor. - */ + /* + * Now we can delete the security descriptor. + */ - talloc_destroy(mem_ctx); + talloc_destroy(mem_ctx); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size); - return -1; + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size); + return -1; } /**************************************************************************** @@ -1592,233 +1594,263 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, } /**************************************************************************** - Reply to IOCTL - not implemented - no plans. + Reply to NT IOCTL ****************************************************************************/ - static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, char **ppparams, char **ppdata) + char **ppsetup, int setup_count, + char **ppparams, int parameter_count, + char **ppdata, int data_count) { - static BOOL logged_message = False; + unsigned fnum, control; + static BOOL logged_message; - if(!logged_message) { - DEBUG(3,("call_nt_transact_ioctl: Currently not implemented.\n")); - logged_message = True; /* Only print this once... */ + if (setup_count != 8) { + DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count)); + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - return ERROR_DOS(ERRSRV,ERRnosupport); + + fnum = SVAL(*ppsetup, 4); + control = IVAL(*ppsetup, 0); + + DEBUG(6,("call_nt_transact_ioctl: fnum=%d control=0x%x\n", + fnum, control)); + + switch (control) { + case NTIOCTL_SET_SPARSE: + /* pretend this succeeded - tho strictly we should + mark the file sparse (if the local fs supports it) + so we can know if we need to pre-allocate or not */ + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + return -1; + + default: + if (!logged_message) { + logged_message = True; /* Only print this once... */ + DEBUG(3,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", + control)); + } + } + + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } /**************************************************************************** Reply to a SMBNTtrans. ****************************************************************************/ + int reply_nttrans(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) + char *inbuf,char *outbuf,int length,int bufsize) { - int outsize = 0; + int outsize = 0; #if 0 /* Not used. */ - uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); - uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount); - uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); + uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); + uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount); + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); #endif /* Not used. */ - uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); - uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount); - uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount); - uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset); - uint32 data_count = IVAL(inbuf,smb_nt_DataCount); - uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset); - uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */ - uint16 function_code = SVAL( inbuf, smb_nt_Function); - char *params = NULL, *data = NULL, *setup = NULL; - uint32 num_params_sofar, num_data_sofar; - START_PROFILE(SMBnttrans); - - if(global_oplock_break && (function_code == NT_TRANSACT_CREATE)) { - /* - * Queue this open message as we are the process of an oplock break. - */ - - DEBUG(2,("reply_nttrans: queueing message NT_TRANSACT_CREATE \ -due to being in oplock break state.\n" )); - - push_oplock_pending_smb_message( inbuf, length); - END_PROFILE(SMBnttrans); - return -1; - } - - if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { - END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRaccess); - } - - outsize = set_message(outbuf,0,0,True); - - /* - * All nttrans messages we handle have smb_wct == 19 + setup_count. - * Ensure this is so as a sanity check. - */ - - if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) { - DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", - CVAL(inbuf, smb_wct), 19 + (setup_count/2))); - END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRerror); - } + uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); + uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount); + uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount); + uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset); + uint32 data_count = IVAL(inbuf,smb_nt_DataCount); + uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset); + uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */ + uint16 function_code = SVAL( inbuf, smb_nt_Function); + char *params = NULL, *data = NULL, *setup = NULL; + uint32 num_params_sofar, num_data_sofar; + START_PROFILE(SMBnttrans); + + if(global_oplock_break && + ((function_code == NT_TRANSACT_CREATE) || + (function_code == NT_TRANSACT_RENAME))) { + /* + * Queue this open message as we are the process of an oplock break. + */ + + DEBUG(2,("reply_nttrans: queueing message code 0x%x \ +due to being in oplock break state.\n", (unsigned int)function_code )); + + push_oplock_pending_smb_message( inbuf, length); + END_PROFILE(SMBnttrans); + return -1; + } + + if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRSRV,ERRaccess); + } + + outsize = set_message(outbuf,0,0,True); + + /* + * All nttrans messages we handle have smb_wct == 19 + setup_count. + * Ensure this is so as a sanity check. + */ + + if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) { + DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", + CVAL(inbuf, smb_wct), 19 + (setup_count/2))); + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRSRV,ERRerror); + } - /* Allocate the space for the setup, the maximum needed parameters and data */ - - if(setup_count > 0) - setup = (char *)malloc(setup_count); - if (total_parameter_count > 0) - params = (char *)malloc(total_parameter_count); - if (total_data_count > 0) - data = (char *)malloc(total_data_count); + /* Allocate the space for the setup, the maximum needed parameters and data */ + + if(setup_count > 0) + setup = (char *)malloc(setup_count); + if (total_parameter_count > 0) + params = (char *)malloc(total_parameter_count); + if (total_data_count > 0) + data = (char *)malloc(total_data_count); - if ((total_parameter_count && !params) || (total_data_count && !data) || - (setup_count && !setup)) { + if ((total_parameter_count && !params) || (total_data_count && !data) || + (setup_count && !setup)) { + SAFE_FREE(setup); + SAFE_FREE(params); + SAFE_FREE(data); + DEBUG(0,("reply_nttrans : Out of memory\n")); + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRDOS,ERRnomem); + } + + /* Copy the param and data bytes sent with this request into the params buffer */ + num_params_sofar = parameter_count; + num_data_sofar = data_count; + + if (parameter_count > total_parameter_count || data_count > total_data_count) + exit_server("reply_nttrans: invalid sizes in packet."); + + if(setup) { + memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); + DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count)); + dump_data(10, setup, setup_count); + } + if(params) { + memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); + DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count)); + dump_data(10, params, parameter_count); + } + if(data) { + memcpy( data, smb_base(inbuf) + data_offset, data_count); + DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); + dump_data(10, data, data_count); + } + + if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_nttrans: send_smb failed."); + + while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { + BOOL ret; + + ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + + if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) { + outsize = set_message(outbuf,0,0,True); + if(ret) { + DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n")); + } else { + DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); + } + SAFE_FREE(params); + SAFE_FREE(data); + SAFE_FREE(setup); + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRSRV,ERRerror); + } + + /* Revise total_params and total_data in case they have changed downwards */ + total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); + total_data_count = IVAL(inbuf, smb_nts_TotalDataCount); + num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount)); + num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount)); + if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) + exit_server("reply_nttrans2: data overflow in secondary nttrans packet"); + + memcpy( ¶ms[ IVAL(inbuf, smb_nts_ParameterDisplacement)], + smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count); + memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)], + smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count); + } + } + + if (Protocol >= PROTOCOL_NT1) + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME); + + /* Now we must call the relevant NT_TRANS function */ + switch(function_code) { + case NT_TRANSACT_CREATE: + START_PROFILE_NESTED(NT_transact_create); + outsize = call_nt_transact_create(conn, inbuf, outbuf, + length, bufsize, + &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_create); + break; + case NT_TRANSACT_IOCTL: + START_PROFILE_NESTED(NT_transact_ioctl); + outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, + length, bufsize, + &setup, setup_count, + ¶ms, parameter_count, + &data, data_count); + END_PROFILE_NESTED(NT_transact_ioctl); + break; + case NT_TRANSACT_SET_SECURITY_DESC: + START_PROFILE_NESTED(NT_transact_set_security_desc); + outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, + length, bufsize, + &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_set_security_desc); + break; + case NT_TRANSACT_NOTIFY_CHANGE: + START_PROFILE_NESTED(NT_transact_notify_change); + outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, + length, bufsize, + &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_notify_change); + break; + case NT_TRANSACT_RENAME: + START_PROFILE_NESTED(NT_transact_rename); + outsize = call_nt_transact_rename(conn, inbuf, outbuf, + length, bufsize, + &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_rename); + break; + + case NT_TRANSACT_QUERY_SECURITY_DESC: + START_PROFILE_NESTED(NT_transact_query_security_desc); + outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, + length, bufsize, + &setup, ¶ms, &data); + END_PROFILE_NESTED(NT_transact_query_security_desc); + break; + default: + /* Error in request */ + DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); + SAFE_FREE(setup); + SAFE_FREE(params); + SAFE_FREE(data); + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRSRV,ERRerror); + } + + /* As we do not know how many data packets will need to be + returned here the various call_nt_transact_xxxx calls + must send their own. Thus a call_nt_transact_xxxx routine only + returns a value other than -1 when it wants to send + an error packet. + */ + SAFE_FREE(setup); SAFE_FREE(params); SAFE_FREE(data); - DEBUG(0,("reply_nttrans : Out of memory\n")); - END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRDOS,ERRnomem); - } - - /* Copy the param and data bytes sent with this request into - the params buffer */ - num_params_sofar = parameter_count; - num_data_sofar = data_count; - - if (parameter_count > total_parameter_count || data_count > total_data_count) - exit_server("reply_nttrans: invalid sizes in packet."); - - if(setup) { - memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); - DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count)); - dump_data(10, setup, setup_count); - } - if(params) { - memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); - DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count)); - dump_data(10, params, parameter_count); - } - if(data) { - memcpy( data, smb_base(inbuf) + data_offset, data_count); - DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); - dump_data(10, data, data_count); - } - - if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_nttrans: send_smb failed."); - - while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { - BOOL ret; - - ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); - - if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) { - outsize = set_message(outbuf,0,0,True); - if(ret) { - DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n")); - } else { - DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", - (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - } - SAFE_FREE(params); - SAFE_FREE(data); - SAFE_FREE(setup); END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRerror); - } - - /* Revise total_params and total_data in case they have changed downwards */ - total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); - total_data_count = IVAL(inbuf, smb_nts_TotalDataCount); - num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount)); - num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount)); - if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) - exit_server("reply_nttrans2: data overflow in secondary nttrans packet"); - - memcpy( ¶ms[ IVAL(inbuf, smb_nts_ParameterDisplacement)], - smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count); - memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)], - smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count); - } - } - - if (Protocol >= PROTOCOL_NT1) - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME); - - /* Now we must call the relevant NT_TRANS function */ - switch(function_code) { - case NT_TRANSACT_CREATE: - START_PROFILE_NESTED(NT_transact_create); - outsize = call_nt_transact_create(conn, inbuf, outbuf, length, bufsize, - &setup, ¶ms, &data); - END_PROFILE_NESTED(NT_transact_create); - break; - case NT_TRANSACT_IOCTL: - START_PROFILE_NESTED(NT_transact_ioctl); - outsize = call_nt_transact_ioctl(conn, - inbuf, outbuf, length, bufsize, - &setup, ¶ms, &data); - END_PROFILE_NESTED(NT_transact_ioctl); - break; - case NT_TRANSACT_SET_SECURITY_DESC: - START_PROFILE_NESTED(NT_transact_set_security_desc); - outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); - END_PROFILE_NESTED(NT_transact_set_security_desc); - break; - case NT_TRANSACT_NOTIFY_CHANGE: - START_PROFILE_NESTED(NT_transact_notify_change); - outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); - END_PROFILE_NESTED(NT_transact_notify_change); - break; - case NT_TRANSACT_RENAME: - START_PROFILE_NESTED(NT_transact_rename); - outsize = call_nt_transact_rename(conn, inbuf, outbuf, length, - bufsize, - &setup, ¶ms, &data); - END_PROFILE_NESTED(NT_transact_rename); - break; - - case NT_TRANSACT_QUERY_SECURITY_DESC: - START_PROFILE_NESTED(NT_transact_query_security_desc); - outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); - END_PROFILE_NESTED(NT_transact_query_security_desc); - break; - default: - /* Error in request */ - DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); - SAFE_FREE(setup); - SAFE_FREE(params); - SAFE_FREE(data); - END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRerror); - } - - /* As we do not know how many data packets will need to be - returned here the various call_nt_transact_xxxx calls - must send their own. Thus a call_nt_transact_xxxx routine only - returns a value other than -1 when it wants to send - an error packet. - */ - - SAFE_FREE(setup); - SAFE_FREE(params); - SAFE_FREE(data); - END_PROFILE(SMBnttrans); - return outsize; /* If a correct response was needed the call_nt_transact_xxxx - calls have already sent it. If outsize != -1 then it is - returning an error packet. */ + return outsize; /* If a correct response was needed the call_nt_transact_xxxx + calls have already sent it. If outsize != -1 then it is + returning an error packet. */ } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 82c0cef77d..cfac7cf695 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -89,29 +89,6 @@ void invalidate_all_vuids(void) } } -/**************************************************************************** -return a validated username -****************************************************************************/ -char *validated_username(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - if (vuser == NULL) - return 0; - return(vuser->user.unix_name); -} - -/**************************************************************************** -return a validated domain -****************************************************************************/ -char *validated_domain(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - if (vuser == NULL) - return 0; - return(vuser->user.domain); -} - - /**************************************************************************** Create the SID list for this user. ****************************************************************************/ @@ -207,7 +184,7 @@ has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -int register_vuid(auth_serversupplied_info *server_info, char *smb_name) +int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) { user_struct *vuser = NULL; uid_t uid; @@ -297,7 +274,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) /* Create an NT_USER_TOKEN struct for this user. */ vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, vuser->guest, server_info->ptok); - DEBUG(3,("uid %d registered to name %s\n",(int)vuser->uid,vuser->user.unix_name)); + DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid)); next_vuid++; num_validated_vuids++; @@ -311,8 +288,9 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) } /* Register a home dir service for this user */ - if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir) - && (lp_servicenumber(vuser->user.unix_name) < 0)) { + if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { + DEBUG(3, ("Adding/updating homes service for user '%s' using home direcotry: '%s'\n", + vuser->user.unix_name, vuser->unix_homedir)); vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir); } else { vuser->homes_snum = -1; @@ -325,7 +303,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) /**************************************************************************** add a name to the session users list ****************************************************************************/ -void add_session_user(char *user) +void add_session_user(const char *user) { fstring suser; StrnCpy(suser,user,sizeof(suser)-1); @@ -373,7 +351,7 @@ BOOL user_ok(const char *user,int snum) if (valid) str_list_free (&valid); if (ret && lp_onlyuser(snum)) { - char **user_list = str_list_make (lp_username(snum)); + char **user_list = str_list_make (lp_username(snum), NULL); if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) { ret = user_in_list(user, user_list); } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 85818d524a..043e33e836 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2296,7 +2296,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo switch(tagtype) { case SMB_ACL_USER_OBJ: perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR); - break; + break; case SMB_ACL_GROUP_OBJ: perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); break; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 43d3c6c531..55234ec896 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -152,7 +152,7 @@ static void async_processing(char *buffer, int buffer_len) Returns False on timeout or error. Else returns True. -The timeout is in milli seconds +The timeout is in milliseconds ****************************************************************************/ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) @@ -341,9 +341,9 @@ force write permissions on print services. functions. Any message that has a NULL function is unimplemented - please feel free to contribute implementations! */ -static struct smb_message_struct +const static struct smb_message_struct { - char *name; + const char *name; int (*fn)(connection_struct *conn, char *, char *, int, int); int flags; } @@ -386,7 +386,7 @@ static struct smb_message_struct /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER }, -/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, +/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC }, /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",reply_ioctl,0}, /* 0x28 */ { "SMBioctls",NULL,AS_USER}, @@ -399,7 +399,7 @@ static struct smb_message_struct /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, /* 0x30 */ { NULL, NULL, 0 }, /* 0x31 */ { NULL, NULL, 0 }, -/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC }, +/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC }, /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER}, /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER}, /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER}, @@ -611,7 +611,7 @@ static struct smb_message_struct /******************************************************************* dump a prs to a file ********************************************************************/ -static void smb_dump(char *name, int type, char *data, ssize_t len) +static void smb_dump(const char *name, int type, char *data, ssize_t len) { int fd, i; pstring fname; @@ -896,7 +896,7 @@ void process_smb(char *inbuf, char *outbuf) /**************************************************************************** return a string containing the function name of a SMB command ****************************************************************************/ -char *smb_fn_name(int type) +const char *smb_fn_name(int type) { static char *unknown_name = "SMBunknown"; @@ -1228,13 +1228,6 @@ void smbd_process(void) max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); - /* re-initialise the timezone */ - TimeInit(); - - /* register our message handlers */ - message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); - talloc_init_named("dummy!"); - while (True) { int deadtime = lp_deadtime()*60; int select_timeout = setup_select_timeout(); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0ccdf7c241..c6a082d7d8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -38,7 +38,6 @@ extern pstring global_myname; extern int global_oplock_break; unsigned int smb_echo_count = 0; -extern fstring remote_machine; extern BOOL global_encrypted_passwords_negotiated; @@ -53,10 +52,11 @@ int reply_special(char *inbuf,char *outbuf) int msg_flags = CVAL(inbuf,1); pstring name1,name2; - extern fstring local_machine; int len; char name_type = 0; + static BOOL already_got_session = False; + *name1 = *name2 = 0; memset(outbuf,'\0',smb_size); @@ -65,6 +65,11 @@ int reply_special(char *inbuf,char *outbuf) switch (msg_type) { case 0x81: /* session request */ + + if (already_got_session) { + exit_server("multiple session request not permitted"); + } + SCVAL(outbuf,0,0x82); SCVAL(outbuf,3,0); if (name_len(inbuf+4) > 50 || @@ -77,24 +82,19 @@ int reply_special(char *inbuf,char *outbuf) DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - fstrcpy(remote_machine,name2); - remote_machine[15] = 0; - trim_string(remote_machine," "," "); - strlower(remote_machine); - alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); + name1[15] = 0; - fstrcpy(local_machine,name1); - len = strlen(local_machine); + len = strlen(name2); if (len == 16) { - name_type = local_machine[15]; - local_machine[15] = 0; + name_type = name2[15]; + name2[15] = 0; } - trim_string(local_machine," "," "); - strlower(local_machine); - alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); + + set_local_machine_name(name1); + set_remote_machine_name(name2); DEBUG(2,("netbios connect: local=%s remote=%s\n", - local_machine, remote_machine )); + get_local_machine_name(), get_remote_machine_name() )); if (name_type == 'R') { /* We are being asked for a pathworks session --- @@ -107,7 +107,7 @@ int reply_special(char *inbuf,char *outbuf) of possibly valid usernames if we are operating in share mode security */ if (lp_security() == SEC_SHARE) { - add_session_user(remote_machine); + add_session_user(get_remote_machine_name()); } reload_services(True); @@ -115,6 +115,7 @@ int reply_special(char *inbuf,char *outbuf) claim_connection(NULL,"",MAXSTATUS,True); + already_got_session = True; break; case 0x89: /* session keepalive request @@ -148,7 +149,8 @@ int reply_special(char *inbuf,char *outbuf) int reply_tcon(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring service; + const char *service; + pstring service_buf; pstring password; pstring dev; int outsize = 0; @@ -160,17 +162,19 @@ int reply_tcon(connection_struct *conn, START_PROFILE(SMBtcon); - *service = *password = *dev = 0; + *service_buf = *password = *dev = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, service, p, sizeof(service), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1; pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1; p += pwlen; p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1; - p = strrchr_m(service,'\\'); + p = strrchr_m(service_buf,'\\'); if (p) { - pstrcpy(service, p+1); + service = p+1; + } else { + service = service_buf; } password_blob = data_blob(password, pwlen+1); @@ -354,10 +358,13 @@ int reply_ioctl(connection_struct *conn, switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: - SSVAL(p,0,fsp->print_jobid); /* Job number */ + { + uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); + SSVAL(p,0,rap_jobid); /* Job number */ srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII); srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); break; + } } END_PROFILE(SMBioctl); @@ -2744,6 +2751,8 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE); + RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); + status = mkdir_internal(conn, directory); if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6f0d0238b0..b2b905cec3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -38,8 +38,6 @@ extern pstring user_socket_options; extern int dcelogin_atmost_once; #endif /* WITH_DFS */ -extern fstring remote_machine; - /* really we should have a top level context structure that has the client file descriptor as an element. That would require a major rewrite :( @@ -133,7 +131,7 @@ static BOOL open_sockets_inetd(void) smbd_set_server_fd(dup(0)); /* close our standard file descriptors */ - close_low_fds(); + close_low_fds(False); /* Don't close stderr */ set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); set_socket_options(smbd_server_fd(), user_socket_options); @@ -151,13 +149,15 @@ static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) Open the socket communication. ****************************************************************************/ -static BOOL open_sockets(BOOL is_daemon,int port) +static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) { int num_interfaces = iface_count(); + int num_sockets = 0; int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; int i; + char *ports; if (!is_daemon) { return open_sockets_inetd(); @@ -176,73 +176,106 @@ static BOOL open_sockets(BOOL is_daemon,int port) /* Stop zombies */ CatchChild(); - - + FD_ZERO(&listen_set); - if(lp_interfaces() && lp_bind_interfaces_only()) { + /* use a reasonable default set of ports - listing on 445 and 139 */ + if (!smb_ports) { + ports = lp_smb_ports(); + if (!ports || !*ports) { + ports = SMB_PORTS; + } + ports = strdup(ports); + } else { + ports = strdup(smb_ports); + } + + if (lp_interfaces() && lp_bind_interfaces_only()) { /* We have been given an interfaces line, and been told to only bind to those interfaces. Create a socket per interface and bind to only these. */ - if(num_interfaces > FD_SETSIZE) { - DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \ -max can be %d\n", - num_interfaces, FD_SETSIZE)); - return False; - } - /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { struct in_addr *ifip = iface_n_ip(i); - + fstring tok; + char *ptr; + if(ifip == NULL) { - DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i)); + DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); continue; } - s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); - if(s == -1) - return False; - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); + for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0) continue; + s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + if(s == -1) + return False; + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); - if (listen(s, 5) == -1) { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; + if (listen(s, 5) == -1) { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } + FD_SET(s,&listen_set); + + num_sockets++; + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } } - FD_SET(s,&listen_set); } } else { /* Just bind to 0.0.0.0 - accept connections from anywhere. */ + + fstring tok; + char *ptr; + num_interfaces = 1; - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()),True); - if (s == -1) - return(False); + for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0) continue; + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address()),True); + if (s == -1) + return(False); - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - if (listen(s, 5) == -1) { - DEBUG(0,("open_sockets: listen: %s\n", - strerror(errno))); - close(s); - return False; + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + if (listen(s, 5) == -1) { + DEBUG(0,("open_sockets_smbd: listen: %s\n", + strerror(errno))); + close(s); + return False; + } + + fd_listenset[num_sockets] = s; + FD_SET(s,&listen_set); + + num_sockets++; + + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } } - - fd_listenset[0] = s; - FD_SET(s,&listen_set); } + SAFE_FREE(ports); + /* Listen to messages */ message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); @@ -293,7 +326,7 @@ max can be %d\n", socklen_t in_addrlen = sizeof(addr); s = -1; - for(i = 0; i < num_interfaces; i++) { + for(i = 0; i < num_sockets; i++) { if(FD_ISSET(fd_listenset[i],&lfds)) { s = fd_listenset[i]; /* Clear this so we don't look @@ -309,7 +342,7 @@ max can be %d\n", continue; if (smbd_server_fd() == -1) { - DEBUG(0,("open_sockets: accept: %s\n", + DEBUG(0,("open_sockets_smbd: accept: %s\n", strerror(errno))); continue; } @@ -318,17 +351,21 @@ max can be %d\n", /* Child code ... */ /* close the listening socket(s) */ - for(i = 0; i < num_interfaces; i++) + for(i = 0; i < num_sockets; i++) close(fd_listenset[i]); /* close our standard file descriptors */ - close_low_fds(); + close_low_fds(False); am_parent = 0; set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); set_socket_options(smbd_server_fd(),user_socket_options); + /* this is needed so that we get decent entries + in smbstatus for port 445 connects */ + set_remote_machine_name(get_socket_addr(smbd_server_fd())); + /* Reset global variables in util.c so that client substitutions will be done correctly in the process. */ @@ -382,8 +419,6 @@ BOOL reload_services(BOOL test) { BOOL ret; - set_register_printer_fn(); - if (lp_loaded()) { pstring fname; pstrcpy(fname,lp_configfile()); @@ -611,7 +646,7 @@ static void usage(char *pname) BOOL is_daemon = False; BOOL interactive = False; BOOL specified_logfile = False; - int port = SMB_PORT; + char *ports = NULL; int opt; pstring logfile; @@ -666,7 +701,7 @@ static void usage(char *pname) break; case 'p': - port = atoi(optarg); + ports = optarg; break; case 'h': @@ -705,7 +740,7 @@ static void usage(char *pname) lp_set_logfile(logfile); } - fstrcpy(remote_machine, "smbd"); + set_remote_machine_name("smbd"); setup_logging(argv[0],interactive); @@ -773,11 +808,6 @@ static void usage(char *pname) init_structs(); - /* don't call winbind for our domain if we are the DC */ - if (lp_domain_logons()) { - winbind_exclude_domain(lp_workgroup()); - } - #ifdef WITH_PROFILE if (!profile_setup(False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); @@ -839,13 +869,15 @@ static void usage(char *pname) start_background_queue(); */ - if (!open_sockets(is_daemon,port)) + if (!open_sockets_smbd(is_daemon,ports)) exit(1); /* * everything after this point is run after the fork() */ + namecache_enable(); + if (!locking_init(0)) exit(1); @@ -889,6 +921,13 @@ static void usage(char *pname) if (!init_change_notify()) exit(1); + /* re-initialise the timezone */ + TimeInit(); + + /* register our message handlers */ + message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); + talloc_init_named("dummy!"); + smbd_process(); uni_group_cache_shutdown(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9ac610ab5a..6f83a2d3b7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -27,9 +27,7 @@ extern BOOL short_case_preserve; extern BOOL case_mangle; extern BOOL case_sensitive; extern BOOL use_mangled_map; -extern fstring remote_machine; extern userdom_struct current_user_info; -extern fstring remote_machine; /**************************************************************************** @@ -104,7 +102,9 @@ int add_home_service(const char *service, const char *username, const char *home } } - lp_add_home(service, iHomeService, username, homedir); + if (!lp_add_home(service, iHomeService, username, homedir)) { + return -1; + } return lp_servicenumber(service); @@ -347,7 +347,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } if (lp_guest_only(snum)) { - char *guestname = lp_guestaccount(); + const char *guestname = lp_guestaccount(); guest = True; force = True; pass = getpwnam_alloc(guestname); @@ -521,7 +521,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstrcpy(s,lp_pathname(snum)); standard_sub_conn(conn,s,sizeof(s)); string_set(&conn->connectpath,s); - DEBUG(3,("Connect path is %s\n",s)); + DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); } /* groups stuff added by ih */ @@ -634,7 +634,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, I have disabled this chdir check (tridge) */ if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", - remote_machine, conn->client_address, + get_remote_machine_name(), conn->client_address, conn->connectpath,strerror(errno))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); @@ -645,7 +645,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, #else /* the alternative is just to check the directory exists */ if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { - DEBUG(0,("%s is not a directory\n", conn->connectpath)); + DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); @@ -674,7 +674,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { - dbgtext( "%s (%s) ", remote_machine, conn->client_address ); + dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); dbgtext( "initially as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); @@ -759,6 +759,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, vuser = get_valid_user_struct(vuid); if (!vuser) { DEBUG(1,("make_connection: refusing to connect with no session setup\n")); + *status = NT_STATUS_ACCESS_DENIED; return NULL; } } @@ -773,12 +774,15 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, if (strequal(service_in,HOMES_NAME)) { if(lp_security() != SEC_SHARE) { DATA_BLOB no_pw = data_blob(NULL, 0); - if (vuser->homes_snum != -1) { - DEBUG(5, ("making a connection to [homes] service created at session setup time\n")); - return make_connection_snum(vuser->homes_snum, - vuser, no_pw, - dev, status); + if (vuser->homes_snum == -1) { + DEBUG(2, ("[homes] share not available for this user becouse it was not found or created at session setup time\n")); + *status = NT_STATUS_BAD_NETWORK_NAME; + return NULL; } + DEBUG(5, ("making a connection to [homes] service created at session setup time\n")); + return make_connection_snum(vuser->homes_snum, + vuser, no_pw, + dev, status); } else { /* Security = share. Try with current_user_info.smb_name * as the username. */ @@ -797,7 +801,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } } } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) - && strequal(service, lp_servicename(vuser->homes_snum))) { + && strequal(service_in, lp_servicename(vuser->homes_snum))) { DATA_BLOB no_pw = data_blob(NULL, 0); DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service)); return make_connection_snum(vuser->homes_snum, @@ -819,7 +823,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } DEBUG(0,("%s (%s) couldn't find service %s\n", - remote_machine, client_addr(), service)); + get_remote_machine_name(), client_addr(), service)); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -841,7 +845,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_root_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", - remote_machine,conn->client_address, + get_remote_machine_name(),conn->client_address, lp_servicename(SNUM(conn)))); if (conn->vfs_ops.disconnect != NULL) { diff --git a/source3/smbd/session.c b/source3/smbd/session.c index dade953ec1..54b7a24b07 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -27,21 +27,22 @@ #include "includes.h" -extern fstring remote_machine; - static TDB_CONTEXT *tdb; /* called when a session is created */ BOOL session_claim(user_struct *vuser) { - int i; + int i = 0; TDB_DATA data; struct sessionid sessionid; uint32 pid = (uint32)sys_getpid(); TDB_DATA key; fstring keystr; char * hostname; + int tdb_store_flag; /* If using utmp, we do an inital 'lock hold' store, + but we don't need this if we are just using the + (unique) pid/vuid combination */ - vuser->session_id = 0; + vuser->session_keystr = NULL; /* don't register sessions for the guest user - its just too expensive to go through pam session code for browsing etc */ @@ -63,18 +64,37 @@ BOOL session_claim(user_struct *vuser) data.dptr = NULL; data.dsize = 0; - for (i=1;ivuid); + slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, + SESSION_TEMPLATE, (long unsigned int)sys_getpid(), + vuser->vuid); + key.dptr = keystr; key.dsize = strlen(keystr)+1; - - if (tdb_store(tdb, key, data, TDB_INSERT) == 0) break; - } - - if (i == MAX_SESSION_ID) { - DEBUG(1,("session_claim: out of session IDs (max is %d)\n", - MAX_SESSION_ID)); - return False; + + tdb_store_flag = TDB_REPLACE; } /* If 'hostname lookup' == yes, then do the DNS lookup. This is @@ -90,24 +110,25 @@ BOOL session_claim(user_struct *vuser) fstrcpy(sessionid.username, vuser->user.unix_name); fstrcpy(sessionid.hostname, hostname); - slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_TEMPLATE, i); - sessionid.id_num = i; + sessionid.id_num = i; /* Only valid for utmp sessions */ sessionid.pid = pid; sessionid.uid = vuser->uid; sessionid.gid = vuser->gid; - fstrcpy(sessionid.remote_machine, remote_machine); + fstrcpy(sessionid.remote_machine, get_remote_machine_name()); fstrcpy(sessionid.ip_addr, client_addr()); if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", sessionid.username, sessionid.id_str)); - tdb_delete(tdb, key); + if (tdb_store_flag == TDB_MODIFY) { + tdb_delete(tdb, key); + } return False; } data.dptr = (char *)&sessionid; data.dsize = sizeof(sessionid); - if (tdb_store(tdb, key, data, TDB_MODIFY) != 0) { + if (tdb_store(tdb, key, data, tdb_store_flag) != 0) { DEBUG(1,("session_claim: unable to create session id record\n")); return False; } @@ -119,7 +140,11 @@ BOOL session_claim(user_struct *vuser) } #endif - vuser->session_id = i; + vuser->session_keystr = strdup(keystr); + if (!vuser->session_keystr) { + DEBUG(0, ("session_claim: strdup() failed for session_keystr\n")); + return False; + } return True; } @@ -129,18 +154,15 @@ void session_yield(user_struct *vuser) TDB_DATA dbuf; struct sessionid sessionid; TDB_DATA key; - fstring keystr; if (!tdb) return; - if (vuser->session_id == 0) { + if (!vuser->session_keystr) { return; } - slprintf(keystr, sizeof(keystr)-1, "ID/%d", vuser->session_id); - - key.dptr = keystr; - key.dsize = strlen(keystr)+1; + key.dptr = vuser->session_keystr; + key.dsize = strlen(vuser->session_keystr)+1; dbuf = tdb_fetch(tdb, key); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 867b00ff5c..77f93812dd 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -3,6 +3,7 @@ handle SMBsessionsetup Copyright (C) Andrew Tridgell 1998-2001 Copyright (C) Andrew Bartlett 2001 + Copyright (C) Jim McDonough 2002 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 @@ -122,6 +123,12 @@ static int reply_spnego_kerberos(connection_struct *conn, ads = ads_init_simple(); + if (!ads) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + ads->auth.realm = strdup(lp_realm()); + ret = ads_verify_ticket(ads, &ticket, &client, &auth_data); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); @@ -139,7 +146,7 @@ static int reply_spnego_kerberos(connection_struct *conn, } *p = 0; - if (strcasecmp(p+1, ads->realm) != 0) { + if (strcasecmp(p+1, ads->auth.realm) != 0) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); @@ -200,7 +207,7 @@ static int reply_spnego_kerberos(connection_struct *conn, send a security blob via a session setup reply ****************************************************************************/ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, - DATA_BLOB blob) + DATA_BLOB blob, uint32 errcode) { char *p; @@ -209,7 +216,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end that we aren't finished yet */ - SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)); + SIVAL(outbuf, smb_rcls, errcode); SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ SSVAL(outbuf, smb_vwv3, blob.length); p = smb_buf(outbuf); @@ -236,11 +243,12 @@ static int reply_spnego_negotiate(connection_struct *conn, DATA_BLOB secblob; int i; uint32 ntlmssp_command, neg_flags, chal_flags; - DATA_BLOB chal, spnego_chal, extra_data; + DATA_BLOB chal, spnego_chal; const uint8 *cryptkey; BOOL got_kerberos = False; NTSTATUS nt_status; extern pstring global_myname; + char *cliname=NULL, *domname=NULL; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { @@ -258,7 +266,7 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got secblob of size %d\n", secblob.length)); #ifdef HAVE_KRB5 - if (got_kerberos) { + if (got_kerberos && (SEC_ADS == lp_security())) { int ret = reply_spnego_kerberos(conn, inbuf, outbuf, length, bufsize, &secblob); data_blob_free(&secblob); @@ -271,19 +279,16 @@ static int reply_spnego_negotiate(connection_struct *conn, file_save("secblob.dat", secblob.data, secblob.length); #endif - if (!msrpc_parse(&secblob, "CddB", + if (!msrpc_parse(&secblob, "CddAA", "NTLMSSP", &ntlmssp_command, &neg_flags, - &extra_data)) { + &cliname, + &domname)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - DEBUG(5, ("Extra data: \n")); - dump_data(5, extra_data.data, extra_data.length); - data_blob_free(&secblob); - data_blob_free(&extra_data); if (ntlmssp_command != NTLMSSP_NEGOTIATE) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); @@ -307,41 +312,44 @@ static int reply_spnego_negotiate(connection_struct *conn, return the flags we want. Obviously this is not correct */ chal_flags = NTLMSSP_NEGOTIATE_UNICODE | - NTLMSSP_NEGOTIATE_LM_KEY | + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_CHAL_TARGET_INFO; { - DATA_BLOB domain_blob, netbios_blob, realm_blob; + DATA_BLOB domain_blob, struct_blob; + fstring dnsname, dnsdomname; msrpc_gen(&domain_blob, "U", lp_workgroup()); - msrpc_gen(&netbios_blob, - "U", - global_myname); - - msrpc_gen(&realm_blob, - "U", - lp_realm()); - + fstrcpy(dnsdomname, lp_realm()); + strlower(dnsdomname); + + fstrcpy(dnsname, global_myname); + fstrcat(dnsname, "."); + fstrcat(dnsname, lp_realm()); + strlower(dnsname); - msrpc_gen(&chal, "CddddbBBBB", + msrpc_gen(&struct_blob, "aaaaa", + 2, lp_workgroup(), + 1, global_myname, + 4, dnsdomname, + 3, dnsname, + 0, ""); + + msrpc_gen(&chal, "CdUdbddB", "NTLMSSP", NTLMSSP_CHALLENGE, - 0, - 0x30, /* ?? */ + lp_workgroup(), chal_flags, cryptkey, 8, - domain_blob.data, domain_blob.length, - domain_blob.data, domain_blob.length, - netbios_blob.data, netbios_blob.length, - realm_blob.data, realm_blob.length); + 0, 0, + struct_blob.data, struct_blob.length); data_blob_free(&domain_blob); - data_blob_free(&netbios_blob); - data_blob_free(&realm_blob); + data_blob_free(&struct_blob); } if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) { @@ -351,7 +359,7 @@ static int reply_spnego_negotiate(connection_struct *conn, } /* now tell the client to send the auth packet */ - reply_sesssetup_blob(conn, outbuf, spnego_chal); + reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)); data_blob_free(&chal); data_blob_free(&spnego_chal); @@ -368,7 +376,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, DATA_BLOB blob1) { - DATA_BLOB auth; + DATA_BLOB auth, response; char *workgroup = NULL, *user = NULL, *machine = NULL; DATA_BLOB lmhash, nthash, sess_key; DATA_BLOB plaintext_password = data_blob(NULL, 0); @@ -413,6 +421,13 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n", user, workgroup, machine, lmhash.length, nthash.length)); + /* the client has given us its machine name (which we otherwise would not get on port 445). + we need to possibly reload smb.conf if smb.conf includes depend on the machine name */ + + set_remote_machine_name(machine); + + reload_services(True); + #if 0 file_save("nthash1.dat", nthash.data, nthash.length); file_save("lmhash1.dat", lmhash.data, lmhash.length); @@ -481,8 +496,12 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); - - return chain_reply(inbuf,outbuf,length,bufsize); + + response = spnego_gen_auth_response(); + reply_sesssetup_blob(conn, outbuf, response, 0); + + /* and tell smbd that we have already replied to this packet */ + return -1; } @@ -594,7 +613,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern BOOL global_encrypted_passwords_negotiated; extern BOOL global_spnego_negotiated; extern int Protocol; - extern fstring remote_machine; extern userdom_struct current_user_info; extern int max_send; @@ -630,8 +648,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (Protocol < PROTOCOL_NT1) { uint16 passlen1 = SVAL(inbuf,smb_vwv7); - if (passlen1 > MAX_PASS_LEN) { - return ERROR_DOS(ERRDOS,ERRbuftoosmall); + if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (doencrypt) { @@ -665,13 +683,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } } - if (passlen1 > MAX_PASS_LEN) { - return ERROR_DOS(ERRDOS,ERRbuftoosmall); - } - - passlen1 = MIN(passlen1, MAX_PASS_LEN); - passlen2 = MIN(passlen2, MAX_PASS_LEN); - if (!doencrypt) { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. @@ -689,19 +700,29 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, passlen2 = 0; } + /* check for nasty tricks */ + if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + /* Save the lanman2 password and the NT md4 password. */ if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) { doencrypt = False; } - + if (doencrypt) { lm_resp = data_blob(p, passlen1); nt_resp = data_blob(p+passlen1, passlen2); } else { - plaintext_password = data_blob(p, passlen1+1); - /* Ensure null termination */ - plaintext_password.data[passlen1] = 0; + pstring pass; + srvstr_pull(inbuf, pass, smb_buf(inbuf), + sizeof(pass), passlen1, STR_TERMINATE); + plaintext_password = data_blob(pass, strlen(pass)+1); } p += passlen1 + passlen2; @@ -720,7 +741,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine)); + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name())); if (*user) { if (global_spnego_negotiated) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f1dfb39aac..a66c029286 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -30,6 +30,19 @@ extern int global_oplock_break; extern uint32 global_client_caps; extern pstring global_myname; +/* given a stat buffer return the allocated size on disk, taking into + account sparse files */ +SMB_OFF_T get_allocation_size(SMB_STRUCT_STAT *sbuf) +{ + SMB_OFF_T ret; + ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks; + ret = SMB_ROUNDUP_ALLOCATION(ret); + return ret; +} + +#define get_file_size(sbuf) (sbuf.st_size) + + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -256,7 +269,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return(UNIXERROR(ERRDOS,ERRnoaccess)); } - size = sbuf.st_size; + size = get_file_size(sbuf); fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; inode = sbuf.st_ino; @@ -453,7 +466,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint32 reskey=0; int prev_dirpos=0; int mode=0; - SMB_OFF_T size = 0; + SMB_OFF_T file_size = 0; SMB_OFF_T allocation_size = 0; uint32 len; time_t mdate=0, adate=0, cdate=0; @@ -565,8 +578,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, continue; } - size = sbuf.st_size; - allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size); + file_size = get_file_size(sbuf); + allocation_size = get_allocation_size(&sbuf); mdate = sbuf.st_mtime; adate = sbuf.st_atime; cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); @@ -578,7 +591,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } if(mode & aDIR) - size = 0; + file_size = 0; DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); @@ -602,7 +615,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,l1_fdateCreation,cdate); put_dos_date2(p,l1_fdateLastAccess,adate); put_dos_date2(p,l1_fdateLastWrite,mdate); - SIVAL(p,l1_cbFile,(uint32)size); + SIVAL(p,l1_cbFile,(uint32)file_size); SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(p,l1_attrFile,mode); p += l1_achName; @@ -621,7 +634,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, put_dos_date2(p,l2_fdateCreation,cdate); put_dos_date2(p,l2_fdateLastAccess,adate); put_dos_date2(p,l2_fdateLastWrite,mdate); - SIVAL(p,l2_cbFile,(uint32)size); + SIVAL(p,l2_cbFile,(uint32)file_size); SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); SSVAL(p,l2_attrFile,mode); SIVAL(p,l2_cbList,0); /* No extended attributes */ @@ -641,7 +654,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,size); + SOFF_T(p,0,file_size); SOFF_T(p,8,allocation_size); p += 16; SIVAL(p,0,nt_extmode); p += 4; @@ -675,7 +688,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,size); + SOFF_T(p,0,file_size); SOFF_T(p,8,allocation_size); p += 16; SIVAL(p,0,nt_extmode); p += 4; @@ -696,7 +709,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,size); + SOFF_T(p,0,file_size); SOFF_T(p,8,allocation_size); p += 16; SIVAL(p,0,nt_extmode); p += 4; @@ -735,14 +748,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ - SOFF_T(p,0,sbuf.st_size); /* File size 64 Bit */ + SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */ p+= 8; #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */ #else /* Can't get the value - fake it using size. */ - SOFF_T(p,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(p,0,get_file_size(sbuf)); /* Number of bytes used on disk - 64 Bit */ #endif p+= 8; @@ -1528,7 +1541,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; int mode=0; - SMB_OFF_T size=0; + SMB_OFF_T file_size=0; SMB_OFF_T allocation_size=0; unsigned int data_size; SMB_STRUCT_STAT sbuf; @@ -1643,10 +1656,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, mode = dos_mode(conn,fname,&sbuf); fullpathname = fname; - size = sbuf.st_size; - allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size); + file_size = get_file_size(sbuf); + allocation_size = get_allocation_size(&sbuf); if (mode & aDIR) - size = 0; + file_size = 0; params = Realloc(*pparams,2); if (params == NULL) @@ -1692,7 +1705,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,l1_fdateCreation,c_time); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - SIVAL(pdata,l1_cbFile,(uint32)size); + SIVAL(pdata,l1_cbFile,(uint32)file_size); SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(pdata,l1_attrFile,mode); SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ @@ -1703,7 +1716,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,0,c_time); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); - SIVAL(pdata,12,(uint32)size); + SIVAL(pdata,12,(uint32)file_size); SIVAL(pdata,16,(uint32)allocation_size); SIVAL(pdata,20,mode); break; @@ -1747,9 +1760,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_STANDARD_INFO: data_size = 24; - /* Fake up allocation size. */ SOFF_T(pdata,0,allocation_size); - SOFF_T(pdata,8,size); + SOFF_T(pdata,8,file_size); SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,0); SCVAL(pdata,21,(mode&aDIR)?1:0); @@ -1794,7 +1806,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; - SOFF_T(pdata,0,size); + SOFF_T(pdata,0,file_size); break; case SMB_QUERY_FILE_ALL_INFO: @@ -1805,7 +1817,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,32,mode); pdata += 40; SOFF_T(pdata,0,allocation_size); - SOFF_T(pdata,8,size); + SOFF_T(pdata,8,file_size); SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); @@ -1917,7 +1929,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False); SIVAL(pdata,0,0); /* ??? */ SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ - SOFF_T(pdata,8,size); + SOFF_T(pdata,8,file_size); SIVAL(pdata,16,allocation_size); SIVAL(pdata,20,0); /* ??? */ data_size = 24 + byte_len; @@ -1925,7 +1937,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_FILE_COMPRESSION_INFORMATION: - SOFF_T(pdata,0,size); + SOFF_T(pdata,0,allocation_size); SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ data_size = 16; @@ -1937,7 +1949,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,allocation_size); - SOFF_T(pdata,40,size); + SOFF_T(pdata,40,file_size); SIVAL(pdata,48,mode); SIVAL(pdata,52,0); /* ??? */ data_size = 56; @@ -1957,14 +1969,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode)); - SOFF_T(pdata,0,sbuf.st_size); /* File size 64 Bit */ + SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */ pdata += 8; #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */ #else /* Can't get the value - fake it using size. */ - SOFF_T(pdata,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(pdata,0,get_file_size(sbuf)); /* Number of bytes used on disk - 64 Bit */ #endif pdata += 8; @@ -2246,7 +2258,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); - } + } else + return (UNIXERROR(ERRDOS,ERRbadpath)); } else { /* * Original code - this is an open file. @@ -2310,7 +2323,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, sbuf.st_mtime = fsp->pending_modtime; } - size = sbuf.st_size; + size = get_file_size(sbuf); tvs.modtime = sbuf.st_mtime; tvs.actime = sbuf.st_atime; dosmode = dos_mode(conn,fname,&sbuf); @@ -2413,7 +2426,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)allocation_size )); - if(allocation_size != sbuf.st_size) { + if(allocation_size != get_file_size(sbuf)) { SMB_STRUCT_STAT new_sbuf; DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n", @@ -2459,8 +2472,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (ret == -1) return ERROR_NT(NT_STATUS_DISK_FULL); - /* Allocate can trucate size... */ - size = new_sbuf.st_size; + /* Allocate can truncate size... */ + size = get_file_size(new_sbuf); } break; @@ -2715,7 +2728,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * changing the size of a file. */ if (!size) - size = sbuf.st_size; + size = get_file_size(sbuf); } /* @@ -2757,7 +2770,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } } - if(size != sbuf.st_size) { + if (size != get_file_size(sbuf)) { int ret; @@ -2970,9 +2983,11 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, { char *pdata = *ppdata; files_struct *fsp = file_fsp(inbuf,smb_vwv15); - + if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + uint16 rap_jobid; + pdata = Realloc(*ppdata, 32); if(pdata == NULL) return ERROR_DOS(ERRDOS,ERRnomem); @@ -2981,7 +2996,8 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 CAN ACCEPT THIS IN UNICODE. JRA. */ - SSVAL(pdata,0,fsp->print_jobid); /* Job number */ + rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */ + SSVAL(pdata,0,rap_jobid); /* Job number */ srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index a18f62c9cc..c0bacf8f91 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -440,44 +440,43 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N extern pstring global_myname; extern fstring global_myworkgroup; fstring sid; - BOOL ret = False; + BOOL local_lookup = False; *name_type = SID_NAME_UNKNOWN; /* If we are looking up a domain user, make sure it is for the local machine only */ - switch (lp_server_role()) { - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: + if (strequal(global_myname, domain)) { + local_lookup = True; + } else if (lp_server_role() == ROLE_DOMAIN_PDC || + lp_server_role() == ROLE_DOMAIN_PDC) { if (strequal(domain, global_myworkgroup)) { - ret = local_lookup_name(name, psid, name_type); - } - /* No break is deliberate here. JRA. */ - default: - if (ret) { - } else if (strequal(global_myname, domain)) { - ret = local_lookup_name(name, psid, name_type); - } else { - DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); + local_lookup = True; } } - - if (ret) { - DEBUG(10, - ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", - domain, name, sid_to_string(sid,psid), - sid_type_lookup(*name_type), (unsigned int)*name_type)); - return True; - } else if (winbind_lookup_name(domain, name, psid, name_type)) { - DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", - domain, name, sid_to_string(sid, psid), - (unsigned int)*name_type)); - return True; + if (local_lookup) { + if (local_lookup_name(name, psid, name_type)) { + DEBUG(10, + ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", + domain, name, sid_to_string(sid,psid), + sid_type_lookup(*name_type), (unsigned int)*name_type)); + return True; + } + } else { + /* Remote */ + if (winbind_lookup_name(domain, name, psid, name_type)) { + + DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", + domain, name, sid_to_string(sid, psid), + (unsigned int)*name_type)); + return True; + } } - - DEBUG(10, ("lookup_name: winbind and local lookups for [%s]\\[%s] failed\n", domain, name)); + + DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n", + local_lookup ? "local" : "winbind", domain, name)); return False; } @@ -593,13 +592,17 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) was done correctly, False if not. sidtype is set by this function. *****************************************************************/ -BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) +BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) { fstring sid_str; /* if we know its local then don't try winbindd */ if (sid_compare_domain(get_global_sam_sid(), psid) == 0) { - return local_sid_to_uid(puid, psid, sidtype); + BOOL result; + become_root(); + result = local_sid_to_uid(puid, psid, sidtype); + unbecome_root(); + return result; } /* (tridge) I commented out the slab of code below in order to support foreign SIDs @@ -665,7 +668,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) was done correctly, False if not. *****************************************************************/ -BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) +BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) { fstring dom_name, name, sid_str; enum SID_NAME_USE name_type; @@ -676,16 +679,21 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) * First we must look up the name and decide if this is a group sid. */ + /* if we know its local then don't try winbindd */ + if (sid_compare_domain(get_global_sam_sid(), psid) == 0) { + BOOL result; + become_root(); + result = local_sid_to_gid(pgid, psid, sidtype); + unbecome_root(); + return result; + } + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { - DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n", sid_to_string(sid_str, psid) )); - if (!local_sid_to_gid(pgid, psid, sidtype)) { - /* this was probably a foreign sid - assume its a group rid - and continue */ - name_type = SID_NAME_DOM_GRP; - } else { - return True; - } + /* this was probably a foreign sid - assume its a group rid + and continue */ + name_type = SID_NAME_DOM_GRP; } /* @@ -696,7 +704,7 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", (unsigned int)name_type )); - return local_sid_to_gid(pgid, psid, sidtype); + return False; } *sidtype = name_type; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5e1dc68bdb..a2291eba08 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -3,6 +3,7 @@ Version 1.9. VFS initialisation and support functions Copyright (C) Tim Potter 1999 + Copyright (C) Alexander Bokovoy 2002 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 @@ -17,6 +18,8 @@ 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. + + This work was sponsored by Optifacio Software Services, Inc. */ #include "includes.h" @@ -28,6 +31,12 @@ struct vfs_syminfo { void *fptr; }; +/* + Opaque (final) vfs operations. This is a combination of first-met opaque vfs operations + across all currently processed modules. */ + +static vfs_op_tuple vfs_opaque_ops[SMB_VFS_OP_LAST]; + /* Default vfs hooks. WARNING: The order of these initialisers is very important. They must be in the same order as defined in vfs.h. Change at your own peril. */ @@ -117,58 +126,75 @@ static struct vfs_ops default_vfs_ops = { initialise default vfs hooks ****************************************************************************/ -static BOOL vfs_init_default(connection_struct *conn) +static void vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops)); - return True; + conn->vfs_private = NULL; } /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ -static BOOL vfs_init_custom(connection_struct *conn) +static BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) { int vfs_version = -1; - struct vfs_ops *ops, *(*init_fptr)(int *, struct vfs_ops *); + vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *); + int i; - DEBUG(3, ("Initialising custom vfs hooks from %s\n", lp_vfsobj(SNUM(conn)))); + DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object)); /* Open object file */ - if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) { - DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), sys_dlerror())); + if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) { + DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror())); return False; } /* Get handle on vfs_init() symbol */ - init_fptr = (struct vfs_ops *(*)(int *, struct vfs_ops *))sys_dlsym(conn->dl_handle, "vfs_init"); + init_fptr = (vfs_op_tuple *(*)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *))sys_dlsym(conn->vfs_private->handle, "vfs_init"); if (init_fptr == NULL) { - DEBUG(0, ("No vfs_init() symbol found in %s\n", lp_vfsobj(SNUM(conn)))); + DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object)); return False; } /* Initialise vfs_ops structure */ - conn->vfs_ops = default_vfs_ops; - - if ((ops = init_fptr(&vfs_version, &default_vfs_ops)) == NULL) { - DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn)))); - return False; - } - - if (vfs_version != SMB_VFS_INTERFACE_VERSION) { - DEBUG(0, ("vfs_init returned wrong interface version info (was %d, should be %d)\n", - vfs_version, SMB_VFS_INTERFACE_VERSION )); - return False; - } - - if (ops != &conn->vfs_ops) { - memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops)); + if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) { + DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object)); + return False; + } + + if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) { + DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", + vfs_version, SMB_VFS_INTERFACE_VERSION )); + return False; + } + + if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) { + DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ +Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", + vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version )); + return False; + } + + for(i=0; ops[i].op != NULL; i++) { + DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); + if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { + /* Check whether this operation was already made opaque by different module */ + if(vfs_opaque_ops[ops[i].type].op == ((void**)&default_vfs_ops)[ops[i].type]) { + /* No, it isn't overloaded yet. Overload. */ + DEBUG(3, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); + vfs_opaque_ops[ops[i].type] = ops[i]; + } + } + /* Change current VFS disposition*/ + DEBUG(3, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); + ((void**)&conn->vfs_ops)[ops[i].type] = ops[i].op; } return True; @@ -180,21 +206,70 @@ static BOOL vfs_init_custom(connection_struct *conn) BOOL smbd_vfs_init(connection_struct *conn) { + char **vfs_objects, *vfsobj, *vfs_module, *vfs_path; + int nobj, i; + struct smb_vfs_handle_struct *handle; + + /* Normal share - initialise with disk access functions */ + vfs_init_default(conn); + + /* Override VFS functions if 'vfs object' was specified*/ if (*lp_vfsobj(SNUM(conn))) { - - /* Loadable object file */ - - if (!vfs_init_custom(conn)) { - DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed\n")); - return False; + vfsobj = NULL; + for(i=0; ivfs_private = NULL; + for(i=nobj-1; i>=0; i--) { + handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct)); + /* Loadable object file */ + handle->handle = NULL; + DLIST_ADD(conn->vfs_private, handle) + vfs_module = NULL; + if (vfs_path) { + asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[i]); + } else { + asprintf(&vfs_module, "%s", vfs_objects[i]); + } + if (!vfs_init_custom(conn, vfs_module)) { + DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module)); + string_free(&vfsobj); + SAFE_FREE(vfs_module); + return False; + } + SAFE_FREE(vfs_module); + } + } + string_free(&vfsobj); + return True; } - - return True; } - - /* Normal share - initialise with disk access functions */ - - return vfs_init_default(conn); + return True; +} + +/******************************************************************* + Create vfs_ops reflecting current vfs_opaque_ops +*******************************************************************/ +struct vfs_ops *smb_vfs_get_opaque_ops(void) +{ + int i; + struct vfs_ops *ops; + + ops = smb_xmalloc(sizeof(struct vfs_ops)); + + for(i=0; i Date: Wed, 25 Sep 2002 15:19:00 +0000 Subject: sync'ing up for 3.0alpha20 release (This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139) --- source3/smbd/blocking.c | 34 ++- source3/smbd/conn.c | 24 +- source3/smbd/connection.c | 84 +++++-- source3/smbd/dir.c | 121 +++++++--- source3/smbd/filename.c | 2 +- source3/smbd/mangle_hash.c | 2 +- source3/smbd/mangle_hash2.c | 16 +- source3/smbd/negprot.c | 14 +- source3/smbd/nttrans.c | 108 +++++++-- source3/smbd/open.c | 65 +++++- source3/smbd/password.c | 162 ++++--------- source3/smbd/posix_acls.c | 30 ++- source3/smbd/process.c | 288 +++++++++++------------ source3/smbd/reply.c | 547 +++++++++++++++++++++++++++----------------- source3/smbd/sec_ctx.c | 13 +- source3/smbd/server.c | 10 +- source3/smbd/service.c | 39 ++-- source3/smbd/sesssetup.c | 40 ++-- source3/smbd/trans2.c | 69 ++++-- source3/smbd/uid.c | 42 ++-- source3/smbd/vfs-wrap.c | 15 ++ source3/smbd/vfs.c | 9 +- 22 files changed, 1049 insertions(+), 685 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 6623c6df64..9d411711cb 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -531,13 +531,33 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); } /**************************************************************************** - Return True if the blocking lock queue has entries. + Return the number of seconds to the next blocking locks timeout, or default_timeout *****************************************************************************/ - -BOOL blocking_locks_pending(void) +unsigned blocking_locks_timeout(unsigned default_timeout) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - return (blr == NULL ? False : True); + unsigned timeout = default_timeout; + time_t t; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue); + + /* note that we avoid the time() syscall if there are no blocking locks */ + if (!blr) { + return timeout; + } + + t = time(NULL); + + while (blr) { + if (timeout > (blr->expire_time - t)) { + timeout = blr->expire_time - t; + } + blr = (blocking_lock_record *)ubi_slNext(blr); + } + + if (timeout < 1) { + timeout = 1; + } + + return timeout; } /**************************************************************************** @@ -576,7 +596,7 @@ void process_blocking_lock_queue(time_t t) DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", fsp->fnum, fsp->fsp_name )); - if((blr->expire_time != -1) && (blr->expire_time > t)) { + if((blr->expire_time != -1) && (blr->expire_time <= t)) { /* * Lock expired - throw away all previously * obtained locks and return lock error. @@ -584,7 +604,7 @@ void process_blocking_lock_queue(time_t t) DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", fsp->fnum, fsp->fsp_name )); - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index d70e50f899..22407348e8 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -131,7 +131,7 @@ void conn_close_all(void) connection_struct *conn, *next; for (conn=Connections;conn;conn=next) { next=conn->next; - close_cnum(conn, (uint16)-1); + close_cnum(conn, conn->vuid); } } @@ -157,6 +157,27 @@ BOOL conn_idle_all(time_t t, int deadtime) return allidle; } +/**************************************************************************** +clear a vuid out of the validity cache, and as the 'owner' of a connection. +****************************************************************************/ +void conn_clear_vuid_cache(uint16 vuid) +{ + connection_struct *conn; + int i; + + for (conn=Connections;conn;conn=conn->next) { + if (conn->vuid == vuid) { + conn->vuid = UID_FIELD_INVALID; + } + + for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { + if (conn->vuid_cache.list[i] == vuid) { + conn->vuid_cache.list[i] = UID_FIELD_INVALID; + } + } + } +} + /**************************************************************************** Free a conn structure. ****************************************************************************/ @@ -191,7 +212,6 @@ void conn_free(connection_struct *conn) conn->ngroups = 0; } - delete_nt_token(&conn->nt_user_token); free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5609c2963d..ad394a01ca 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -28,14 +28,24 @@ static TDB_CONTEXT *tdb; TDB_CONTEXT *conn_tdb_ctx(void) { - if (!tdb) { + if (!tdb) tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, O_RDWR | O_CREAT, 0644); - } return tdb; } +static void make_conn_key(connection_struct *conn,char *name, TDB_DATA *pkbuf, struct connections_key *pkey) +{ + ZERO_STRUCTP(pkey); + pkey->pid = sys_getpid(); + pkey->cnum = conn?conn->cnum:-1; + fstrcpy(pkey->name, name); + + pkbuf->dptr = (char *)pkey; + pkbuf->dsize = sizeof(*pkey); +} + /**************************************************************************** Delete a connection record. ****************************************************************************/ @@ -45,17 +55,12 @@ BOOL yield_connection(connection_struct *conn,char *name) struct connections_key key; TDB_DATA kbuf; - if (!tdb) return False; + if (!tdb) + return False; DEBUG(3,("Yielding connection to %s\n",name)); - ZERO_STRUCT(key); - key.pid = sys_getpid(); - key.cnum = conn?conn->cnum:-1; - fstrcpy(key.name, name); - - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); + make_conn_key(conn, name, &kbuf, &key); if (tdb_delete(tdb, kbuf) != 0) { int dbg_lvl = (!conn && (tdb_error(tdb) == TDB_ERR_NOEXIST)) ? 3 : 0; @@ -88,7 +93,7 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u memcpy(&crec, dbuf.dptr, sizeof(crec)); - if (crec.cnum == -1) + if (crec.cnum == -1) return 0; /* If the pid was not found delete the entry from connections.tdb */ @@ -111,16 +116,16 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u Claim an entry in the connections database. ****************************************************************************/ -BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear) +BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear, uint32 msg_flags) { struct connections_key key; struct connections_data crec; TDB_DATA kbuf, dbuf; - if (!tdb) { + if (!tdb) tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, O_RDWR | O_CREAT, 0644); - } + if (!tdb) return False; @@ -156,13 +161,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO DEBUG(5,("claiming %s %d\n",name,max_connections)); - ZERO_STRUCT(key); - key.pid = sys_getpid(); - key.cnum = conn?conn->cnum:-1; - fstrcpy(key.name, name); - - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); + make_conn_key(conn, name, &kbuf, &key); /* fill in the crec */ ZERO_STRUCT(crec); @@ -176,6 +175,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO lp_servicename(SNUM(conn)),sizeof(crec.name)-1); } crec.start = time(NULL); + crec.bcast_msg_flags = msg_flags; StrnCpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1); StrnCpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1); @@ -191,3 +191,45 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO return True; } + +BOOL register_message_flags(BOOL doreg, uint32 msg_flags) +{ + struct connections_key key; + struct connections_data *pcrec; + TDB_DATA kbuf, dbuf; + + if (!tdb) + return False; + + DEBUG(10,("register_message_flags: %s flags 0x%x\n", + doreg ? "adding" : "removing", + (unsigned int)msg_flags )); + + make_conn_key(NULL, "", &kbuf, &key); + + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) { + DEBUG(0,("register_message_flags: tdb_fetch failed\n")); + return False; + } + + pcrec = (struct connections_data *)dbuf.dptr; + pcrec->bcast_msg_flags = msg_flags; + if (doreg) + pcrec->bcast_msg_flags |= msg_flags; + else + pcrec->bcast_msg_flags &= ~msg_flags; + + if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { + DEBUG(0,("register_message_flags: tdb_store failed with error %s.\n", + tdb_errorstr(tdb) )); + SAFE_FREE(dbuf.dptr); + return False; + } + + DEBUG(10,("register_message_flags: new flags 0x%x\n", + (unsigned int)pcrec->bcast_msg_flags )); + + SAFE_FREE(dbuf.dptr); + return True; +} diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 1a18476b75..396ecd98c4 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -553,9 +553,24 @@ void *dptr_fetch_lanman2(int dptr_num) BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype) { - if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) - return False; - return True; + int mask; + + /* Check the "may have" search bits. */ + if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) + return False; + + /* Check the "must have" bits, which are the may have bits shifted eight */ + /* If must have bit is set, the file/dir can not be returned in search unless the matching + file attribute is set */ + mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */ + if(mask) { + if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */ + return True; + else + return False; + } + + return True; } static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask) @@ -663,18 +678,15 @@ typedef struct char *current; } Dir; - - /******************************************************************* -check to see if a user can read a file. This is only approximate, -it is used as part of the "hide unreadable" option. Don't -use it for anything security sensitive + Check to see if a user can read a file. This is only approximate, + it is used as part of the "hide unreadable" option. Don't + use it for anything security sensitive. ********************************************************************/ -static BOOL user_can_read_file(connection_struct *conn, char *name) +static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { extern struct current_user current_user; - SMB_STRUCT_STAT ste; SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; @@ -683,8 +695,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) NTSTATUS status; uint32 access_granted; - ZERO_STRUCT(ste); - /* * If user is a member of the Admin group * we never hide files from them. @@ -694,16 +704,16 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) return True; /* If we can't stat it does not show it */ - if (vfs_stat(conn, name, &ste) != 0) + if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ - if(S_ISDIR(ste.st_mode)) - fsp = open_directory(conn, name, &ste, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + if(S_ISDIR(pst->st_mode)) + fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unix_mode(conn,aRONLY|aDIR, name), &smb_action); else - fsp = open_file_shared1(conn, name, &ste, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), + fsp = open_file_shared1(conn, name, pst, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); if (!fsp) @@ -722,16 +732,15 @@ static BOOL user_can_read_file(connection_struct *conn, char *name) } /******************************************************************* -check to see if a user can write a file (and only files, we do not -check dirs on this one). This is only approximate, -it is used as part of the "hide unwriteable" option. Don't -use it for anything security sensitive + Check to see if a user can write a file (and only files, we do not + check dirs on this one). This is only approximate, + it is used as part of the "hide unwriteable" option. Don't + use it for anything security sensitive. ********************************************************************/ -static BOOL user_can_write_file(connection_struct *conn, char *name) +static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { extern struct current_user current_user; - SMB_STRUCT_STAT ste; SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; @@ -740,8 +749,6 @@ static BOOL user_can_write_file(connection_struct *conn, char *name) NTSTATUS status; uint32 access_granted; - ZERO_STRUCT(ste); - /* * If user is a member of the Admin group * we never hide files from them. @@ -751,15 +758,15 @@ static BOOL user_can_write_file(connection_struct *conn, char *name) return True; /* If we can't stat it does not show it */ - if (vfs_stat(conn, name, &ste) != 0) + if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ - if(S_ISDIR(ste.st_mode)) + if(S_ISDIR(pst->st_mode)) return True; else - fsp = open_file_shared1(conn, name, &ste, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), + fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); if (!fsp) @@ -777,6 +784,30 @@ static BOOL user_can_write_file(connection_struct *conn, char *name) &access_granted, &status); } +/******************************************************************* + Is a file a "special" type ? +********************************************************************/ + +static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) +{ + /* + * If user is a member of the Admin group + * we never hide files from them. + */ + + if (conn->admin_user) + return True; + + /* If we can't stat it does not show it */ + if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + return True; + + if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) + return False; + + return True; +} + /******************************************************************* Open a directory. ********************************************************************/ @@ -802,6 +833,8 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) while (True) { int l; BOOL normal_entry = True; + SMB_STRUCT_STAT st; + char *entry = NULL; if (used == 0) { n = "."; @@ -818,6 +851,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) normal_entry = True; } + ZERO_STRUCT(st); l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ @@ -826,30 +860,45 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) /* Honour _hide unreadable_ option */ if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) { - char *entry; int ret=0; - if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = user_can_read_file(conn, entry); - SAFE_FREE(entry); + if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { + ret = user_can_read_file(conn, entry, &st); } - if (!ret) + if (!ret) { + SAFE_FREE(entry); continue; + } } /* Honour _hide unwriteable_ option */ if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) { - char *entry; int ret=0; - if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = user_can_write_file(conn, entry); + if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { + ret = user_can_write_file(conn, entry, &st); + } + if (!ret) { SAFE_FREE(entry); + continue; + } + } + + /* Honour _hide_special_ option */ + if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) { + int ret=0; + + if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { + ret = file_is_special(conn, entry, &st); } - if (!ret) + if (ret) { + SAFE_FREE(entry); continue; + } } + SAFE_FREE(entry); + if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ce98af4ace..d343db26f6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -168,7 +168,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(orig_path, name); - if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { *pst = st; return True; } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 1d4697474c..0446a953ff 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -730,7 +730,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83) DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, need83 ? "True" : "False", cache83 ? "True" : "False")); - if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) { + if (push_ucs2_allocate(&OutName_ucs2, OutName) < 0) { DEBUG(0, ("push_ucs2_allocate failed!\n")); return; } diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 6b53cc72aa..a0a3d51139 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -200,7 +200,7 @@ static BOOL is_mangled_component(const char *name) { int len, i; - M_DEBUG(0,("is_mangled_component %s ?\n", name)); + M_DEBUG(10,("is_mangled_component %s ?\n", name)); /* check the length */ len = strlen(name); @@ -234,7 +234,7 @@ static BOOL is_mangled_component(const char *name) } } - M_DEBUG(0,("is_mangled %s -> yes\n", name)); + M_DEBUG(10,("is_mangled %s -> yes\n", name)); return True; } @@ -257,7 +257,7 @@ static BOOL is_mangled(const char *name) const char *p; const char *s; - M_DEBUG(0,("is_mangled %s ?\n", name)); + M_DEBUG(10,("is_mangled %s ?\n", name)); for (s=name; (p=strchr(s, '/')); s=p+1) { char *component = strndup(s, PTR_DIFF(p, s)); @@ -367,7 +367,7 @@ static BOOL check_cache(char *name) /* make sure that this is a mangled name from this cache */ if (!is_mangled(name)) { - M_DEBUG(0,("check_cache: %s -> not mangled\n", name)); + M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } @@ -382,7 +382,7 @@ static BOOL check_cache(char *name) /* now look in the prefix cache for that hash */ prefix = cache_lookup(hash); if (!prefix) { - M_DEBUG(0,("check_cache: %s -> %08X -> not found\n", name, hash)); + M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash)); return False; } @@ -395,10 +395,10 @@ static BOOL check_cache(char *name) } if (extension[0]) { - M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); + M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); } else { - M_DEBUG(0,("check_cache: %s -> %s\n", name, prefix)); + M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); fstrcpy(name, prefix); } @@ -573,7 +573,7 @@ static void name_map(char *name, BOOL need83, BOOL cache83) cache_insert(name, prefix_len, hash); } - M_DEBUG(0,("name_map: %s -> %08X -> %s (cache=%d)\n", + M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", name, hash, new_name, cache83)); /* and overwrite the old name */ diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 2be04fd686..16427b00d7 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -170,9 +170,9 @@ static int negprot_spnego(char *p) DATA_BLOB blob; extern pstring global_myname; uint8 guid[16]; - const char *OIDs_krb5[] = {OID_NTLMSSP, - OID_KERBEROS5, + const char *OIDs_krb5[] = {OID_KERBEROS5, OID_KERBEROS5_OLD, + OID_NTLMSSP, NULL}; const char *OIDs_plain[] = {OID_NTLMSSP, NULL}; char *principal; @@ -199,9 +199,7 @@ static int negprot_spnego(char *p) if (lp_security() != SEC_ADS) { blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); } else { - /* win2000 uses host$@REALM, which we will probably use eventually, - but for now this works */ - asprintf(&principal, "HOST/%s@%s", guid, lp_realm()); + asprintf(&principal, "%s$@%s", guid, lp_realm()); blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal); free(principal); } @@ -239,7 +237,11 @@ static int reply_nt1(char *inbuf, char *outbuf) capabilities |= CAP_EXTENDED_SECURITY; } - capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX; + capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; + + if (lp_unix_extensions()) { + capabilities |= CAP_UNIX; + } if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index cf69dfddb0..1f3bbd488e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -371,7 +371,7 @@ static int map_share_mode( char *fname, uint32 create_options, if (smb_open_mode == -1) { - if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS| + if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS| FILE_EXECUTE|FILE_READ_ATTRIBUTES| FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) { @@ -548,6 +548,7 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); + SMB_OFF_T allocation_size = 0; int smb_ofun; int smb_open_mode; int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); @@ -563,8 +564,16 @@ int reply_ntcreate_and_X(connection_struct *conn, files_struct *fsp=NULL; char *p = NULL; time_t c_time; + BOOL extended_oplock_granted = False; + START_PROFILE(SMBntcreateX); + DEBUG(10,("reply_ntcreateX: flags = 0x%x, desired_access = 0x%x \ +file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \ +create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attributes, + share_access, create_disposition, + create_options, root_dir_fid )); + /* If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { @@ -573,10 +582,14 @@ int reply_ntcreate_and_X(connection_struct *conn, return do_ntcreate_pipe_open(conn,inbuf,outbuf,length,bufsize); } else { END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + return(ERROR_DOS(ERRDOS,ERRnoaccess)); } } + if (create_options & FILE_OPEN_BY_FILE_ID) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } /* * We need to construct the open_and_X ofun value from the @@ -585,7 +598,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if((smb_ofun = map_create_disposition( create_disposition )) == -1) { END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + return(ERROR_DOS(ERRDOS,ERRnoaccess)); } /* @@ -660,7 +673,7 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, file_attributes)) == -1) { END_PROFILE(SMBntcreateX); - return ERROR_DOS(ERRDOS,ERRbadaccess); + return ERROR_DOS(ERRDOS,ERRnoaccess); } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -689,6 +702,12 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; + /* Can't open a temp directory. IFS kit test. */ + if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); @@ -787,6 +806,22 @@ int reply_ntcreate_and_X(connection_struct *conn, return ERROR_DOS(ERRDOS,ERRnoaccess); } + /* Save the requested allocation size. */ + allocation_size = IVAL(inbuf,smb_ntcreate_AllocationSize); +#ifdef LARGE_SMB_OFF_T + allocation_size |= (((SMB_OFF_T)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); +#endif + if (allocation_size && (allocation_size > file_len)) { + fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else { + fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE); + } + /* * If the caller set the extended oplock request bit * and we granted one (by whatever means) - set the @@ -794,10 +829,10 @@ int reply_ntcreate_and_X(connection_struct *conn, */ if (oplock_request && lp_fake_oplocks(SNUM(conn))) - smb_action |= EXTENDED_OPLOCK_GRANTED; + extended_oplock_granted = True; if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - smb_action |= EXTENDED_OPLOCK_GRANTED; + extended_oplock_granted = True; #if 0 /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */ @@ -813,7 +848,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * exclusive & batch here. */ - if (smb_action & EXTENDED_OPLOCK_GRANTED) { + if (extended_oplock_granted) { if (flags & REQUEST_BATCH_OPLOCK) { SCVAL(p,0, BATCH_OPLOCK_RETURN); } else { @@ -828,7 +863,10 @@ int reply_ntcreate_and_X(connection_struct *conn, p++; SSVAL(p,0,fsp->fnum); p += 2; - SIVAL(p,0,smb_action); + if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN)) + SIVAL(p,0,FILE_WAS_SUPERSEDED); + else + SIVAL(p,0,smb_action); p += 4; /* Create time. */ @@ -851,7 +889,7 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(&sbuf)); + SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 12; @@ -886,7 +924,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, if(total_parameter_count < 54) { DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); - return ERROR_DOS(ERRDOS,ERRbadaccess); + return ERROR_DOS(ERRDOS,ERRnoaccess); } srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); @@ -1018,6 +1056,7 @@ static int call_nt_transact_create(connection_struct *conn, BOOL bad_path = False; files_struct *fsp = NULL; char *p = NULL; + BOOL extended_oplock_granted = False; uint32 flags; uint32 desired_access; uint32 file_attributes; @@ -1026,6 +1065,7 @@ static int call_nt_transact_create(connection_struct *conn, uint32 create_options; uint32 sd_len; uint16 root_dir_fid; + SMB_OFF_T allocation_size = 0; int smb_ofun; int smb_open_mode; int smb_attr; @@ -1043,7 +1083,7 @@ static int call_nt_transact_create(connection_struct *conn, return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, bufsize, ppsetup, ppparams, ppdata); else - return ERROR_DOS(ERRDOS,ERRbadaccess); + return ERROR_DOS(ERRDOS,ERRnoaccess); } /* @@ -1052,7 +1092,7 @@ static int call_nt_transact_create(connection_struct *conn, if(total_parameter_count < 54) { DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); - return ERROR_DOS(ERRDOS,ERRbadaccess); + return ERROR_DOS(ERRDOS,ERRnoaccess); } flags = IVAL(params,0); @@ -1065,6 +1105,11 @@ static int call_nt_transact_create(connection_struct *conn, root_dir_fid = (uint16)IVAL(params,4); smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); + if (create_options & FILE_OPEN_BY_FILE_ID) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } + /* * We need to construct the open_and_X ofun value from the * NT values, as that's what our code is structured to accept. @@ -1138,7 +1183,7 @@ static int call_nt_transact_create(connection_struct *conn, if((smb_open_mode = map_share_mode( fname, create_options, &desired_access, share_access, file_attributes)) == -1) - return ERROR_DOS(ERRDOS,ERRbadaccess); + return ERROR_DOS(ERRDOS,ERRnoaccess); oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; @@ -1161,6 +1206,12 @@ static int call_nt_transact_create(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { + /* Can't open a temp directory. IFS kit test. */ + if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + oplock_request = 0; /* @@ -1234,10 +1285,10 @@ static int call_nt_transact_create(connection_struct *conn, */ if (oplock_request && lp_fake_oplocks(SNUM(conn))) - smb_action |= EXTENDED_OPLOCK_GRANTED; + extended_oplock_granted = True; if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - smb_action |= EXTENDED_OPLOCK_GRANTED; + extended_oplock_granted = True; } /* @@ -1252,6 +1303,22 @@ static int call_nt_transact_create(connection_struct *conn, restore_case_semantics(file_attributes); + /* Save the requested allocation size. */ + allocation_size = IVAL(params,12); +#ifdef LARGE_SMB_OFF_T + allocation_size |= (((SMB_OFF_T)IVAL(params,16)) << 32); +#endif + if (allocation_size && (allocation_size > file_len)) { + fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else { + fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE); + } + /* Realloc the size of parameters and data we will return */ params = Realloc(*ppparams, 69); if(params == NULL) @@ -1262,7 +1329,7 @@ static int call_nt_transact_create(connection_struct *conn, memset((char *)params,'\0',69); p = params; - if (smb_action & EXTENDED_OPLOCK_GRANTED) + if (extended_oplock_granted) SCVAL(p,0, BATCH_OPLOCK_RETURN); else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); @@ -1272,7 +1339,10 @@ static int call_nt_transact_create(connection_struct *conn, p += 2; SSVAL(p,0,fsp->fnum); p += 2; - SIVAL(p,0,smb_action); + if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN)) + SIVAL(p,0,FILE_WAS_SUPERSEDED); + else + SIVAL(p,0,smb_action); p += 8; /* Create time. */ @@ -1295,7 +1365,7 @@ static int call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(&sbuf)); + SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); @@ -1582,7 +1652,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, (unsigned int)security_info_sent )); if (total_data_count == 0) - return ERROR_DOS(ERRDOS, ERRbadaccess); + return ERROR_DOS(ERRDOS, ERRnoaccess); if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, total_data_count, security_info_sent))) return ERROR_NT(nt_status); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8c6e8ed805..a95793a050 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -139,18 +139,31 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * as we always opened files read-write in that release. JRA. */ - if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) + if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { + DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname )); local_flags = (flags & ~O_ACCMODE)|O_RDWR; + } - /* - * We can't actually truncate here as the file may be locked. - * open_file_shared will take care of the truncate later. JRA. - */ + if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + (local_flags & O_CREAT) || ((local_flags & O_TRUNC) == O_TRUNC) ) { - local_flags &= ~O_TRUNC; + /* + * We can't actually truncate here as the file may be locked. + * open_file_shared will take care of the truncate later. JRA. + */ - if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || - (local_flags & O_CREAT)) { + local_flags &= ~O_TRUNC; + +#if defined(O_NONBLOCK) && defined(S_ISFIFO) + /* + * We would block on opening a FIFO with no one else on the + * other end. Do what we used to do and add O_NONBLOCK to the + * open flags. JRA. + */ + + if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode)) + local_flags |= O_NONBLOCK; +#endif /* actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); @@ -679,6 +692,31 @@ static void kernel_flock(files_struct *fsp, int deny_mode) } +static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, mode_t new_mode) +{ + uint32 old_dos_mode, new_dos_mode; + SMB_STRUCT_STAT sbuf; + + ZERO_STRUCT(sbuf); + + sbuf.st_mode = existing_mode; + old_dos_mode = dos_mode(conn, path, &sbuf); + + sbuf.st_mode = new_mode; + new_dos_mode = dos_mode(conn, path, &sbuf); + + /* If we're mapping SYSTEM and HIDDEN ensure they match. */ + if (lp_map_system(SNUM(conn))) { + if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) != (new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) + return False; + } + if (lp_map_hidden(SNUM(conn))) { + if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) != (new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) + return False; + } + return True; +} + /**************************************************************************** Open a file with a share mode. On output from this open we are guarenteeing that @@ -773,6 +811,17 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) flags2 |= O_TRUNC; + /* We only care about matching attributes on file exists and truncate. */ + if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { + if (!open_match_attributes(conn, fname, psbuf->st_mode, mode)) { + DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", + fname, psbuf->st_mode, mode )); + file_free(fsp); + errno = EACCES; + return NULL; + } + } + if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) flags2 |= O_EXCL; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index cfac7cf695..f2956237dd 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -69,6 +69,10 @@ void invalidate_vuid(uint16 vuid) DLIST_REMOVE(validated_users, vuser); + /* clear the vuid from the 'cache' on each connection, and + from the vuid 'owner' of connections */ + conn_clear_vuid_cache(vuid); + SAFE_FREE(vuser->groups); delete_nt_token(&vuser->nt_user_token); SAFE_FREE(vuser); @@ -89,95 +93,6 @@ void invalidate_all_vuids(void) } } -/**************************************************************************** - Create the SID list for this user. -****************************************************************************/ - -NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest, NT_USER_TOKEN *sup_tok) -{ - extern DOM_SID global_sid_World; - extern DOM_SID global_sid_Network; - extern DOM_SID global_sid_Builtin_Guests; - extern DOM_SID global_sid_Authenticated_Users; - NT_USER_TOKEN *token; - DOM_SID *psids; - int i, psid_ndx = 0; - size_t num_sids = 0; - fstring sid_str; - - if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) - return NULL; - - ZERO_STRUCTP(token); - - /* We always have uid/gid plus World and Network and Authenticated Users or Guest SIDs. */ - num_sids = 5 + ngroups; - - if (sup_tok && sup_tok->num_sids) - num_sids += sup_tok->num_sids; - - if ((token->user_sids = (DOM_SID *)malloc( num_sids*sizeof(DOM_SID))) == NULL) { - SAFE_FREE(token); - return NULL; - } - - psids = token->user_sids; - - /* - * Note - user SID *MUST* be first in token ! - * se_access_check depends on this. - */ - - uid_to_sid( &psids[PRIMARY_USER_SID_INDEX], uid); - psid_ndx++; - - /* - * Primary group SID is second in token. Convention. - */ - - gid_to_sid( &psids[PRIMARY_GROUP_SID_INDEX], gid); - psid_ndx++; - - /* Now add the group SIDs. */ - - for (i = 0; i < ngroups; i++) { - if (groups[i] != gid) { - gid_to_sid( &psids[psid_ndx++], groups[i]); - } - } - - if (sup_tok) { - /* Now add the additional SIDs from the supplimentary token. */ - for (i = 0; i < sup_tok->num_sids; i++) - sid_copy( &psids[psid_ndx++], &sup_tok->user_sids[i] ); - } - - /* - * Finally add the "standard" SIDs. - * The only difference between guest and "anonymous" (which we - * don't really support) is the addition of Authenticated_Users. - */ - - sid_copy( &psids[psid_ndx++], &global_sid_World); - sid_copy( &psids[psid_ndx++], &global_sid_Network); - - if (is_guest) - sid_copy( &psids[psid_ndx++], &global_sid_Builtin_Guests); - else - sid_copy( &psids[psid_ndx++], &global_sid_Authenticated_Users); - - token->num_sids = psid_ndx; - - /* Dump list of sids in token */ - - for (i = 0; i < token->num_sids; i++) { - DEBUG(5, ("user token sid %s\n", - sid_to_string(sid_str, &token->user_sids[i]))); - } - - return token; -} - /**************************************************************************** register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to @@ -187,8 +102,6 @@ tell random client vuid's (normally zero) from valid vuids. int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) { user_struct *vuser = NULL; - uid_t uid; - gid_t gid; /* Ensure no vuid gets registered in share level security. */ if(lp_security() == SEC_SHARE) @@ -205,15 +118,6 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) ZERO_STRUCTP(vuser); - if (!IS_SAM_UNIX_USER(server_info->sam_account)) { - DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT (flags:%x)\n", pdb_get_init_flag(server_info->sam_account))); - free(vuser); - return UID_FIELD_INVALID; - } - - uid = pdb_get_uid(server_info->sam_account); - gid = pdb_get_gid(server_info->sam_account); - /* Allocate a free vuid. Yes this is a linear search... :-) */ while( get_valid_user_struct(next_vuid) != NULL ) { next_vuid++; @@ -225,18 +129,38 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid )); vuser->vuid = next_vuid; - vuser->uid = uid; - vuser->gid = gid; + + /* the next functions should be done by a SID mapping system (SMS) as + * the new real sam db won't have reference to unix uids or gids + */ + if (!IS_SAM_UNIX_USER(server_info->sam_account)) { + DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT (flags:%x)\n", pdb_get_init_flag(server_info->sam_account))); + free(vuser); + return UID_FIELD_INVALID; + } + + vuser->uid = pdb_get_uid(server_info->sam_account); + vuser->gid = pdb_get_gid(server_info->sam_account); + + vuser->n_groups = server_info->n_groups; + if (vuser->n_groups) { + if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { + DEBUG(0,("register_vuid: failed to memdup vuser->groups\n")); + free(vuser); + return UID_FIELD_INVALID; + } + } + vuser->guest = server_info->guest; - fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); - fstrcpy(vuser->user.smb_name, smb_name); + fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); + fstrcpy(vuser->user.smb_name, smb_name); fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); { /* Keep the homedir handy */ const char *homedir = pdb_get_homedir(server_info->sam_account); - const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); + const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); /* should be optained by SMS */ const char *logon_script = pdb_get_logon_script(server_info->sam_account); if (homedir) { vuser->homedir = smb_xstrdup(homedir); @@ -260,19 +184,13 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name)); - vuser->n_groups = 0; - vuser->groups = NULL; - - /* Find all the groups this uid is in and store them. - Used by change_to_user() */ - initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid); - get_current_groups(vuser->gid, &vuser->n_groups, &vuser->groups); - - if (server_info->ptok) - add_supplementary_nt_login_groups(&vuser->n_groups, &vuser->groups, &server_info->ptok); - - /* Create an NT_USER_TOKEN struct for this user. */ - vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, vuser->guest, server_info->ptok); + if (server_info->ptok) { + vuser->nt_user_token = dup_nt_token(server_info->ptok); + } else { + DEBUG(1, ("server_info does not contain a user_token - cannot continue\n")); + free(vuser); + return UID_FIELD_INVALID; + } DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid)); @@ -306,9 +224,11 @@ add a name to the session users list void add_session_user(const char *user) { fstring suser; - StrnCpy(suser,user,sizeof(suser)-1); + struct passwd *passwd; + + if (!(passwd = Get_Pwnam(user))) return; - if (!Get_Pwnam_Modify(suser)) return; + StrnCpy(suser,passwd->pw_name,sizeof(suser)-1); if (suser && *suser && !in_list(suser,session_users,False)) { @@ -451,7 +371,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) Note this is *NOT* used when logging on using sessionsetup_and_X. ****************************************************************************/ -BOOL authorise_login(int snum,char *user, DATA_BLOB password, +BOOL authorise_login(int snum, fstring user, DATA_BLOB password, BOOL *guest) { BOOL ok = False; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 043e33e836..e6ae1c7d79 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1881,6 +1881,8 @@ static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2) size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { + extern DOM_SID global_sid_Builtin_Administrators; + extern DOM_SID global_sid_Builtin_Users; connection_struct *conn = fsp->conn; SMB_STRUCT_STAT sbuf; SEC_ACE *nt_ace_list = NULL; @@ -1895,6 +1897,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) SMB_ACL_T dir_acl = NULL; canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; + size_t num_profile_acls = 0; *ppdesc = NULL; @@ -1939,7 +1942,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * Get the owner, group and world SIDs. */ - create_file_sids(&sbuf, &owner_sid, &group_sid); + if (lp_profile_acls(SNUM(fsp->conn))) { + /* For WXP SP1 the owner must be administrators. */ + sid_copy(&owner_sid, &global_sid_Builtin_Administrators); + sid_copy(&group_sid, &global_sid_Builtin_Users); + num_profile_acls = 2; + } else { + create_file_sids(&sbuf, &owner_sid, &group_sid); + } /* Create the canon_ace lists. */ file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid); @@ -1963,7 +1973,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); goto done; } @@ -1986,6 +1996,13 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0); } + /* The User must have access to a profile share - even if we can't map the SID. */ + if (lp_profile_acls(SNUM(fsp->conn))) { + SEC_ACCESS acc; + init_sec_access(&acc,FILE_GENERIC_ALL); + init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, 0); + } + ace = dir_ace; for (i = 0; i < num_dir_acls; i++, ace = ace->next) { @@ -1994,6 +2011,15 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); } + /* The User must have access to a profile share - even if we can't map the SID. */ + if (lp_profile_acls(SNUM(fsp->conn))) { + SEC_ACCESS acc; + init_sec_access(&acc,FILE_GENERIC_ALL); + init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY); + } + /* * Sort to force deny entries to the front. */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 55234ec896..0f7cfd0e9c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -42,8 +42,8 @@ extern int last_message; extern int global_oplock_break; extern userdom_struct current_user_info; extern int smb_read_error; -SIG_ATOMIC_T reload_after_sighup; -SIG_ATOMIC_T got_sig_term; +SIG_ATOMIC_T reload_after_sighup = 0; +SIG_ATOMIC_T got_sig_term = 0; extern BOOL global_machine_password_needs_changing; extern fstring global_myworkgroup; extern pstring global_myname; @@ -609,8 +609,9 @@ const static struct smb_message_struct }; /******************************************************************* -dump a prs to a file - ********************************************************************/ + Dump a packet to a file. +********************************************************************/ + static void smb_dump(const char *name, int type, char *data, ssize_t len) { int fd, i; @@ -635,178 +636,171 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len) /**************************************************************************** -do a switch on the message type, and return the response size + Do a switch on the message type, and return the response size ****************************************************************************/ + static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize) { - static pid_t pid= (pid_t)-1; - int outsize = 0; - extern uint16 global_smbpid; - - type &= 0xff; + static pid_t pid= (pid_t)-1; + int outsize = 0; + extern uint16 global_smbpid; - if (pid == (pid_t)-1) - pid = sys_getpid(); + type &= 0xff; - errno = 0; - last_message = type; - - /* make sure this is an SMB packet */ - if (strncmp(smb_base(inbuf),"\377SMB",4) != 0) - { - DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf))); - return(-1); - } + if (pid == (pid_t)-1) + pid = sys_getpid(); - /* yuck! this is an interim measure before we get rid of our - current inbuf/outbuf system */ - global_smbpid = SVAL(inbuf,smb_pid); + errno = 0; + last_message = type; - if (smb_messages[type].fn == NULL) - { - DEBUG(0,("Unknown message type %d!\n",type)); - smb_dump("Unknown", 1, inbuf, size); - outsize = reply_unknown(inbuf,outbuf); - } - else - { - int flags = smb_messages[type].flags; - static uint16 last_session_tag = UID_FIELD_INVALID; - /* In share mode security we must ignore the vuid. */ - uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */ + if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) { + DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf))); + exit_server("Non-SMB packet"); + return(-1); + } - DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid)); + /* yuck! this is an interim measure before we get rid of our + current inbuf/outbuf system */ + global_smbpid = SVAL(inbuf,smb_pid); + + if (smb_messages[type].fn == NULL) { + DEBUG(0,("Unknown message type %d!\n",type)); + smb_dump("Unknown", 1, inbuf, size); + outsize = reply_unknown(inbuf,outbuf); + } else { + int flags = smb_messages[type].flags; + static uint16 last_session_tag = UID_FIELD_INVALID; + /* In share mode security we must ignore the vuid. */ + uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + + DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid)); + + smb_dump(smb_fn_name(type), 1, inbuf, size); + if(global_oplock_break) { + if(flags & QUEUE_IN_OPLOCK) { + /* + * Queue this message as we are the process of an oplock break. + */ + + DEBUG( 2, ( "switch_message: queueing message due to being in " ) ); + DEBUGADD( 2, ( "oplock break state.\n" ) ); + + push_oplock_pending_smb_message( inbuf, size ); + return -1; + } + } - smb_dump(smb_fn_name(type), 1, inbuf, size); - if(global_oplock_break) - { - if(flags & QUEUE_IN_OPLOCK) - { - /* - * Queue this message as we are the process of an oplock break. - */ - - DEBUG( 2, ( "switch_message: queueing message due to being in " ) ); - DEBUGADD( 2, ( "oplock break state.\n" ) ); - - push_oplock_pending_smb_message( inbuf, size ); - return -1; - } - } + /* Ensure this value is replaced in the incoming packet. */ + SSVAL(inbuf,smb_uid,session_tag); - /* Ensure this value is replaced in the incoming packet. */ - SSVAL(inbuf,smb_uid,session_tag); + /* + * Ensure the correct username is in current_user_info. + * This is a really ugly bugfix for problems with + * multiple session_setup_and_X's being done and + * allowing %U and %G substitutions to work correctly. + * There is a reason this code is done here, don't + * move it unless you know what you're doing... :-). + * JRA. + */ - /* - * Ensure the correct username is in current_user_info. - * This is a really ugly bugfix for problems with - * multiple session_setup_and_X's being done and - * allowing %U and %G substitutions to work correctly. - * There is a reason this code is done here, don't - * move it unless you know what you're doing... :-). - * JRA. - */ + if (session_tag != last_session_tag) { + user_struct *vuser = NULL; - if (session_tag != last_session_tag) { - user_struct *vuser = NULL; + last_session_tag = session_tag; + if(session_tag != UID_FIELD_INVALID) + vuser = get_valid_user_struct(session_tag); + if(vuser != NULL) + current_user_info = vuser->user; + } - last_session_tag = session_tag; - if(session_tag != UID_FIELD_INVALID) - vuser = get_valid_user_struct(session_tag); - if(vuser != NULL) - current_user_info = vuser->user; - } + /* does this protocol need to be run as root? */ + if (!(flags & AS_USER)) + change_to_root_user(); - /* does this protocol need to be run as root? */ - if (!(flags & AS_USER)) - change_to_root_user(); + /* does this protocol need a valid tree connection? */ + if ((flags & AS_USER) && !conn) + return ERROR_DOS(ERRSRV, ERRinvnid); - /* does this protocol need a valid tree connection? */ - if ((flags & AS_USER) && !conn) { - return ERROR_DOS(ERRSRV, ERRinvnid); - } + /* does this protocol need to be run as the connected user? */ + if ((flags & AS_USER) && !change_to_user(conn,session_tag)) { + if (flags & AS_GUEST) + flags &= ~AS_USER; + else + return(ERROR_DOS(ERRSRV,ERRaccess)); + } - /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !change_to_user(conn,session_tag)) { - if (flags & AS_GUEST) - flags &= ~AS_USER; - else - return(ERROR_DOS(ERRSRV,ERRaccess)); - } - - /* this code is to work around a bug is MS client 3 without - introducing a security hole - it needs to be able to do - print queue checks as guest if it isn't logged in properly */ - if (flags & AS_USER) - flags &= ~AS_GUEST; + /* this code is to work around a bug is MS client 3 without + introducing a security hole - it needs to be able to do + print queue checks as guest if it isn't logged in properly */ + if (flags & AS_USER) + flags &= ~AS_GUEST; - /* does it need write permission? */ - if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) - return(ERROR_DOS(ERRSRV,ERRaccess)); + /* does it need write permission? */ + if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) + return(ERROR_DOS(ERRSRV,ERRaccess)); - /* ipc services are limited */ - if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) { - return(ERROR_DOS(ERRSRV,ERRaccess)); - } + /* ipc services are limited */ + if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) + return(ERROR_DOS(ERRSRV,ERRaccess)); - /* load service specific parameters */ - if (conn && !set_current_service(conn,(flags & AS_USER)?True:False)) { - return(ERROR_DOS(ERRSRV,ERRaccess)); - } + /* load service specific parameters */ + if (conn && !set_current_service(conn,(flags & AS_USER)?True:False)) + return(ERROR_DOS(ERRSRV,ERRaccess)); - /* does this protocol need to be run as guest? */ - if ((flags & AS_GUEST) && - (!change_to_guest() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { - return(ERROR_DOS(ERRSRV,ERRaccess)); - } + /* does this protocol need to be run as guest? */ + if ((flags & AS_GUEST) && (!change_to_guest() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) + return(ERROR_DOS(ERRSRV,ERRaccess)); - last_inbuf = inbuf; + last_inbuf = inbuf; - outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); - } + outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); + } - smb_dump(smb_fn_name(type), 0, outbuf, outsize); + smb_dump(smb_fn_name(type), 0, outbuf, outsize); - return(outsize); + return(outsize); } /**************************************************************************** - construct a reply to the incoming packet + Construct a reply to the incoming packet. ****************************************************************************/ + static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) { - int type = CVAL(inbuf,smb_com); - int outsize = 0; - int msg_type = CVAL(inbuf,0); + int type = CVAL(inbuf,smb_com); + int outsize = 0; + int msg_type = CVAL(inbuf,0); - GetTimeOfDay(&smb_last_time); + GetTimeOfDay(&smb_last_time); - chain_size = 0; - file_chain_reset(); - reset_chain_p(); + chain_size = 0; + file_chain_reset(); + reset_chain_p(); - if (msg_type != 0) - return(reply_special(inbuf,outbuf)); + if (msg_type != 0) + return(reply_special(inbuf,outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common(inbuf, outbuf); - outsize = switch_message(type,inbuf,outbuf,size,bufsize); + outsize = switch_message(type,inbuf,outbuf,size,bufsize); - outsize += chain_size; + outsize += chain_size; - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); - return(outsize); + if(outsize > 4) + smb_setlen(outbuf,outsize - 4); + return(outsize); } /**************************************************************************** - Keep track of the number of running smbd's. This functionality is used to - 'hard' limit Samba overhead on resource constrained systems. + Keep track of the number of running smbd's. This functionality is used to + 'hard' limit Samba overhead on resource constrained systems. ****************************************************************************/ + static BOOL smbd_process_limit(void) { int32 total_smbds; @@ -1032,16 +1026,15 @@ static int setup_select_timeout(void) int select_timeout; int t; - /* - * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we - * have removed any blocking locks. JRA. - */ - - select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 : - SMBD_SELECT_TIMEOUT*1000; + select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT); + select_timeout *= 1000; t = change_notify_timeout(); - if (t != -1) select_timeout = MIN(select_timeout, t*1000); + if (t != -1) + select_timeout = MIN(select_timeout, t*1000); + + if (print_notify_messages_pending()) + select_timeout = MIN(select_timeout, 1000); return select_timeout; } @@ -1161,9 +1154,16 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t * First, open the machine password file with an exclusive lock. */ + if (secrets_lock_trust_account_password(global_myworkgroup, True) == False) { + DEBUG(0,("process: unable to lock the machine account password for \ +machine %s in domain %s.\n", global_myname, global_myworkgroup )); + return True; + } + if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) { DEBUG(0,("process: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname, global_myworkgroup )); + secrets_lock_trust_account_password(global_myworkgroup, False); return True; } @@ -1173,6 +1173,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); if(t < lct + lp_machine_password_timeout()) { global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(global_myworkgroup, False); return True; } @@ -1180,6 +1181,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); change_trust_account_password( global_myworkgroup, remote_machine_list); global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(global_myworkgroup, False); } /* @@ -1201,6 +1203,10 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); force_check_log_size(); check_log_size(); + /* Send any queued printer notify message to interested smbd's. */ + + print_notify_send_messages(); + /* * Modify the select timeout depending upon * what we have remaining in our queues. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c6a082d7d8..a881e135c0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -23,7 +23,6 @@ makes to handle specific protocols */ - #include "includes.h" /* look in server.c for some explanation of these variables */ @@ -40,9 +39,8 @@ unsigned int smb_echo_count = 0; extern BOOL global_encrypted_passwords_negotiated; - /**************************************************************************** - reply to an special message + Reply to an special message. ****************************************************************************/ int reply_special(char *inbuf,char *outbuf) @@ -113,7 +111,7 @@ int reply_special(char *inbuf,char *outbuf) reload_services(True); reopen_logs(); - claim_connection(NULL,"",MAXSTATUS,True); + claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); already_got_session = True; break; @@ -141,7 +139,6 @@ int reply_special(char *inbuf,char *outbuf) return(outsize); } - /**************************************************************************** Reply to a tcon. ****************************************************************************/ @@ -307,10 +304,10 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return chain_reply(inbuf,outbuf,length,bufsize); } - /**************************************************************************** - reply to an unknown type + Reply to an unknown type. ****************************************************************************/ + int reply_unknown(char *inbuf,char *outbuf) { int type; @@ -322,10 +319,10 @@ int reply_unknown(char *inbuf,char *outbuf) return(ERROR_DOS(ERRSRV,ERRunknownsmb)); } - /**************************************************************************** - reply to an ioctl + Reply to an ioctl. ****************************************************************************/ + int reply_ioctl(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { @@ -339,8 +336,7 @@ int reply_ioctl(connection_struct *conn, DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); - switch (ioctl_code) - { + switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: replysize = 32; break; @@ -355,16 +351,15 @@ int reply_ioctl(connection_struct *conn, SSVAL(outbuf,smb_vwv6,52); /* Offset to data */ p = smb_buf(outbuf) + 1; /* Allow for alignment */ - switch (ioctl_code) - { - case IOCTL_QUERY_JOB_INFO: - { - uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); - SSVAL(p,0,rap_jobid); /* Job number */ - srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII); - srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); - break; - } + switch (ioctl_code) { + case IOCTL_QUERY_JOB_INFO: + { + uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); + SSVAL(p,0,rap_jobid); /* Job number */ + srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII); + srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); + break; + } } END_PROFILE(SMBioctl); @@ -372,56 +367,56 @@ int reply_ioctl(connection_struct *conn, } /**************************************************************************** - reply to a chkpth + Reply to a chkpth. ****************************************************************************/ + int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = 0; - int mode; - pstring name; - BOOL ok = False; - BOOL bad_path = False; - SMB_STRUCT_STAT sbuf; - START_PROFILE(SMBchkpth); + int outsize = 0; + int mode; + pstring name; + BOOL ok = False; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + START_PROFILE(SMBchkpth); - srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); + srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - unix_convert(name,conn,0,&bad_path,&sbuf); + unix_convert(name,conn,0,&bad_path,&sbuf); - mode = SVAL(inbuf,smb_vwv0); + mode = SVAL(inbuf,smb_vwv0); - if (check_name(name,conn)) { - if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0) - ok = S_ISDIR(sbuf.st_mode); - } + if (check_name(name,conn)) { + if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0) + ok = S_ISDIR(sbuf.st_mode); + } - if (!ok) { - /* We special case this - as when a Windows machine - is parsing a path is steps through the components - one at a time - if a component fails it expects - ERRbadpath, not ERRbadfile. - */ - if(errno == ENOENT) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } + if (!ok) { + /* We special case this - as when a Windows machine + is parsing a path is steps through the components + one at a time - if a component fails it expects + ERRbadpath, not ERRbadfile. + */ + if(errno == ENOENT) + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - return(UNIXERROR(ERRDOS,ERRbadpath)); - } + return(UNIXERROR(ERRDOS,ERRbadpath)); + } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - DEBUG(3,("chkpth %s mode=%d\n", name, mode)); + DEBUG(3,("chkpth %s mode=%d\n", name, mode)); - END_PROFILE(SMBchkpth); - return(outsize); + END_PROFILE(SMBchkpth); + return(outsize); } - /**************************************************************************** - reply to a getatr + Reply to a getatr. ****************************************************************************/ + int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; @@ -494,10 +489,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } - /**************************************************************************** - reply to a setatr + Reply to a setatr. ****************************************************************************/ + int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; @@ -543,10 +538,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } - /**************************************************************************** - reply to a dskattr + Reply to a dskattr. ****************************************************************************/ + int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; @@ -591,11 +586,11 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz return(outsize); } - /**************************************************************************** - reply to a search - Can be called from SMBsearch, SMBffirst or SMBfunique. + Reply to a search. + Can be called from SMBsearch, SMBffirst or SMBfunique. ****************************************************************************/ + int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring mask; @@ -673,12 +668,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (strlen(directory) == 0) pstrcpy(directory,"./"); memset((char *)status,'\0',21); - SCVAL(status,0,dirtype); + SCVAL(status,0,(dirtype & 0x1F)); } else { + int status_dirtype; memcpy(status,p,21); - dirtype = CVAL(status,0) & 0x1F; + status_dirtype = CVAL(status,0) & 0x1F; + if (status_dirtype != (dirtype & 0x1F)) + dirtype = status_dirtype; + conn->dirptr = dptr_fetch(status+12,&dptr_num); if (!conn->dirptr) goto SearchEmpty; @@ -796,10 +795,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } - /**************************************************************************** - reply to a fclose (stop directory search) + Reply to a fclose (stop directory search). ****************************************************************************/ + int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; @@ -838,9 +837,8 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } - /**************************************************************************** - reply to an open + Reply to an open. ****************************************************************************/ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) @@ -910,10 +908,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(outsize); } - /**************************************************************************** - reply to an open and X + Reply to an open and X. ****************************************************************************/ + int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; @@ -1019,10 +1017,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return chain_reply(inbuf,outbuf,length,bufsize); } - /**************************************************************************** - reply to a SMBulogoffX + Reply to a SMBulogoffX. ****************************************************************************/ + int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 vuid = SVAL(inbuf,smb_uid); @@ -1049,10 +1047,10 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, return chain_reply(inbuf,outbuf,length,bufsize); } - /**************************************************************************** - reply to a mknew or a create + Reply to a mknew or a create. ****************************************************************************/ + int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; @@ -1122,10 +1120,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(outsize); } - /**************************************************************************** - reply to a create temporary file + Reply to a create temporary file. ****************************************************************************/ + int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { pstring fname; @@ -1433,6 +1431,59 @@ void fail_readraw(void) exit_server(errstr); } +/**************************************************************************** + Use sendfile in readbraw. +****************************************************************************/ + +void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread, + ssize_t mincount, char *outbuf) +{ + ssize_t ret=0; + +#if defined(WITH_SENDFILE) + /* + * We can only use sendfile on a non-chained packet and on a file + * that is exclusively oplocked. reply_readbraw has already checked the length. + */ + + if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && + EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) { + DATA_BLOB header; + + _smb_setlen(outbuf,nread); + header.data = outbuf; + header.length = 4; + header.free = NULL; + + if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { + /* + * Special hack for broken Linux with no 64 bit clean sendfile. If we + * return ENOSYS then pretend we just got a normal read. + */ + if (errno == ENOSYS) + goto normal_read; + + DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n", + fsp->fsp_name, strerror(errno) )); + exit_server("send_file_readbraw sendfile failed"); + } + + } + + normal_read: +#endif + + if (nread > 0) { + ret = read_file(fsp,outbuf+4,startpos,nread); + if (ret < mincount) + ret = 0; + } + + _smb_setlen(outbuf,ret); + if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret) + fail_readraw(); +} + /**************************************************************************** Reply to a readbraw (core+ protocol). ****************************************************************************/ @@ -1443,7 +1494,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s size_t nread = 0; SMB_OFF_T startpos; char *header = outbuf; - ssize_t ret=0; files_struct *fsp; START_PROFILE(SMBreadbraw); @@ -1547,15 +1597,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, (int)maxcount, (int)mincount, (int)nread ) ); - if (nread > 0) { - ret = read_file(fsp,header+4,startpos,nread); - if (ret < mincount) - ret = 0; - } - - _smb_setlen(header,ret); - if (write_data(smbd_server_fd(),header,4+ret) != 4+ret) - fail_readraw(); + send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf); DEBUG(5,("readbraw finished\n")); END_PROFILE(SMBreadbraw); @@ -1563,8 +1605,9 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s } /**************************************************************************** - reply to a lockread (core+ protocol) + Reply to a lockread (core+ protocol). ****************************************************************************/ + int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz) { ssize_t nread = -1; @@ -1599,15 +1642,16 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK); if (NT_STATUS_V(status)) { - if (lp_blocking_locks(SNUM(conn))) { + if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, -1, 0)) + if(push_blocking_lock_request(inbuf, length, -1, 0)) { END_PROFILE(SMBlockread); - return -1; + return -1; + } } END_PROFILE(SMBlockread); return ERROR_NT(status); @@ -1632,132 +1676,209 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length return(outsize); } - /**************************************************************************** - reply to a read + Reply to a read. ****************************************************************************/ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - size_t numtoread; - ssize_t nread = 0; - char *data; - SMB_OFF_T startpos; - int outsize = 0; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBread); - - CHECK_FSP(fsp,conn); - CHECK_READ(fsp); + size_t numtoread; + ssize_t nread = 0; + char *data; + SMB_OFF_T startpos; + int outsize = 0; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBread); - numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); + numtoread = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); - outsize = set_message(outbuf,5,3,True); - numtoread = MIN(BUFFER_SIZE-outsize,numtoread); - data = smb_buf(outbuf) + 3; + outsize = set_message(outbuf,5,3,True); + numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + data = smb_buf(outbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { - END_PROFILE(SMBread); - return ERROR_DOS(ERRDOS,ERRlock); - } + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + END_PROFILE(SMBread); + return ERROR_DOS(ERRDOS,ERRlock); + } - if (numtoread > 0) - nread = read_file(fsp,data,startpos,numtoread); + if (numtoread > 0) + nread = read_file(fsp,data,startpos,numtoread); - if (nread < 0) { - END_PROFILE(SMBread); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if (nread < 0) { + END_PROFILE(SMBread); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - SCVAL(smb_buf(outbuf),0,1); - SSVAL(smb_buf(outbuf),1,nread); + outsize += nread; + SSVAL(outbuf,smb_vwv0,nread); + SSVAL(outbuf,smb_vwv5,nread+3); + SCVAL(smb_buf(outbuf),0,1); + SSVAL(smb_buf(outbuf),1,nread); - DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", - fsp->fnum, (int)numtoread, (int)nread ) ); + DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", + fsp->fnum, (int)numtoread, (int)nread ) ); - END_PROFILE(SMBread); - return(outsize); + END_PROFILE(SMBread); + return(outsize); } +/**************************************************************************** + Reply to a read and X - possibly using sendfile. +****************************************************************************/ + +int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, + files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) +{ + ssize_t nread = -1; + char *data = smb_buf(outbuf); + +#if defined(WITH_SENDFILE) + /* + * We can only use sendfile on a non-chained packet and on a file + * that is exclusively oplocked. + */ + + if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && + lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) { + SMB_STRUCT_STAT sbuf; + DATA_BLOB header; + + if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + if (startpos > sbuf.st_size) + goto normal_read; + + if (smb_maxcnt > (sbuf.st_size - startpos)) + smb_maxcnt = (sbuf.st_size - startpos); + + if (smb_maxcnt == 0) + goto normal_read; + + /* + * Set up the packet header before send. We + * assume here the sendfile will work (get the + * correct amount of data). + */ + + SSVAL(outbuf,smb_vwv5,smb_maxcnt); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(smb_buf(outbuf),-2,smb_maxcnt); + SCVAL(outbuf,smb_vwv0,0xFF); + set_message(outbuf,12,smb_maxcnt,False); + header.data = outbuf; + header.length = data - outbuf; + header.free = NULL; + + if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { + /* + * Special hack for broken Linux with no 64 bit clean sendfile. If we + * return ENOSYS then pretend we just got a normal read. + */ + if (errno == ENOSYS) + goto normal_read; + + DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", + fsp->fsp_name, strerror(errno) )); + exit_server("send_file_readX sendfile failed"); + } + + DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n", + fsp->fnum, (int)smb_maxcnt, (int)nread ) ); + return -1; + } + + normal_read: + +#endif + + nread = read_file(fsp,data,startpos,smb_maxcnt); + + if (nread < 0) { + END_PROFILE(SMBreadX); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(smb_buf(outbuf),-2,nread); + + DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", + fsp->fnum, (int)smb_maxcnt, (int)nread ) ); + + return nread; +} /**************************************************************************** - reply to a read and X + Reply to a read and X. ****************************************************************************/ + int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = file_fsp(inbuf,smb_vwv2); - SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); - size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); - size_t smb_mincnt = SVAL(inbuf,smb_vwv6); - ssize_t nread = -1; - char *data; - START_PROFILE(SMBreadX); + files_struct *fsp = file_fsp(inbuf,smb_vwv2); + SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); + ssize_t nread = -1; + size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); +#if 0 + size_t smb_mincnt = SVAL(inbuf,smb_vwv6); +#endif - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) { - END_PROFILE(SMBreadX); - return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); - } + START_PROFILE(SMBreadX); - CHECK_FSP(fsp,conn); - CHECK_READ(fsp); + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) { + END_PROFILE(SMBreadX); + return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); + } + + CHECK_FSP(fsp,conn); + CHECK_READ(fsp); - set_message(outbuf,12,0,True); - data = smb_buf(outbuf); + set_message(outbuf,12,0,True); - if(CVAL(inbuf,smb_wct) == 12) { + if(CVAL(inbuf,smb_wct) == 12) { #ifdef LARGE_SMB_OFF_T - /* - * This is a large offset (64 bit) read. - */ - startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); + /* + * This is a large offset (64 bit) read. + */ + startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); #else /* !LARGE_SMB_OFF_T */ - /* - * Ensure we haven't been sent a >32 bit offset. - */ + /* + * Ensure we haven't been sent a >32 bit offset. + */ - if(IVAL(inbuf,smb_vwv10) != 0) { - DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \ + if(IVAL(inbuf,smb_vwv10) != 0) { + DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) )); - END_PROFILE(SMBreadX); - return ERROR_DOS(ERRDOS,ERRbadaccess); - } + END_PROFILE(SMBreadX); + return ERROR_DOS(ERRDOS,ERRbadaccess); + } #endif /* LARGE_SMB_OFF_T */ - } + } - if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { - END_PROFILE(SMBreadX); - return ERROR_DOS(ERRDOS,ERRlock); - } - nread = read_file(fsp,data,startpos,smb_maxcnt); + if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + END_PROFILE(SMBreadX); + return ERROR_DOS(ERRDOS,ERRlock); + } - if (nread < 0) { - END_PROFILE(SMBreadX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - SSVAL(outbuf,smb_vwv5,nread); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); - SSVAL(smb_buf(outbuf),-2,nread); - - DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n", - fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) ); + nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt); + if (nread != -1) + nread = chain_reply(inbuf,outbuf,length,bufsize); - END_PROFILE(SMBreadX); - return chain_reply(inbuf,outbuf,length,bufsize); + END_PROFILE(SMBreadX); + return nread; } /**************************************************************************** - reply to a writebraw (core+ or LANMAN1.0 protocol) + Reply to a writebraw (core+ or LANMAN1.0 protocol). ****************************************************************************/ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) @@ -1888,7 +2009,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, } /**************************************************************************** - reply to a writeunlock (core+) + Reply to a writeunlock (core+). ****************************************************************************/ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, @@ -1950,7 +2071,6 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, return outsize; } - /**************************************************************************** Reply to a write. ****************************************************************************/ @@ -2029,10 +2149,10 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d return(outsize); } - /**************************************************************************** - reply to a write and X + Reply to a write and X. ****************************************************************************/ + int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); @@ -2129,9 +2249,8 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng return chain_reply(inbuf,outbuf,length,bufsize); } - /**************************************************************************** - reply to a lseek + Reply to a lseek. ****************************************************************************/ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) @@ -2212,7 +2331,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } /**************************************************************************** - reply to a flush + Reply to a flush. ****************************************************************************/ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) @@ -2234,10 +2353,10 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int return(outsize); } - /**************************************************************************** - reply to a exit + Reply to a exit. ****************************************************************************/ + int reply_exit(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { @@ -2251,10 +2370,10 @@ int reply_exit(connection_struct *conn, return(outsize); } - /**************************************************************************** Reply to a close - has to deal with closing a directory opened by NT SMB's. ****************************************************************************/ + int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { @@ -2336,9 +2455,8 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, return(outsize); } - /**************************************************************************** - reply to a writeclose (Core+ protocol) + Reply to a writeclose (Core+ protocol). ****************************************************************************/ int reply_writeclose(connection_struct *conn, @@ -2395,10 +2513,10 @@ int reply_writeclose(connection_struct *conn, return(outsize); } - /**************************************************************************** - reply to a lock + Reply to a lock. ****************************************************************************/ + int reply_lock(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsize) { @@ -2420,7 +2538,7 @@ int reply_lock(connection_struct *conn, status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK); if (NT_STATUS_V(status)) { - if (lp_blocking_locks(SNUM(conn))) { + if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -2439,10 +2557,10 @@ int reply_lock(connection_struct *conn, return(outsize); } - /**************************************************************************** - reply to a unlock + Reply to a unlock. ****************************************************************************/ + int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { @@ -2470,10 +2588,10 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, return(outsize); } - /**************************************************************************** - reply to a tdis + Reply to a tdis. ****************************************************************************/ + int reply_tdis(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { @@ -2497,11 +2615,10 @@ int reply_tdis(connection_struct *conn, return outsize; } - - /**************************************************************************** - reply to a echo + Reply to a echo. ****************************************************************************/ + int reply_echo(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { @@ -2539,10 +2656,10 @@ int reply_echo(connection_struct *conn, return -1; } - /**************************************************************************** - reply to a printopen + Reply to a printopen. ****************************************************************************/ + int reply_printopen(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { @@ -2573,9 +2690,8 @@ int reply_printopen(connection_struct *conn, return(outsize); } - /**************************************************************************** - reply to a printclose + Reply to a printclose. ****************************************************************************/ int reply_printclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) @@ -2607,10 +2723,10 @@ int reply_printclose(connection_struct *conn, return(outsize); } - /**************************************************************************** - reply to a printqueue + Reply to a printqueue. ****************************************************************************/ + int reply_printqueue(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { @@ -2678,10 +2794,10 @@ int reply_printqueue(connection_struct *conn, return(outsize); } - /**************************************************************************** - reply to a printwrite + Reply to a printwrite. ****************************************************************************/ + int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int numtowrite; @@ -2712,11 +2828,11 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ return(outsize); } - /**************************************************************************** The guts of the mkdir command, split out so it may be called by the NT SMB code. ****************************************************************************/ + NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) { BOOL bad_path = False; @@ -2939,10 +3055,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(outsize); } - /******************************************************************* -resolve wildcards in a filename rename + Resolve wildcards in a filename rename. ********************************************************************/ + static BOOL resolve_wildcards(char *name1,char *name2) { fstring root1,root2; @@ -3378,8 +3494,9 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } /**************************************************************************** - reply to a file copy. - ****************************************************************************/ + Reply to a file copy. +****************************************************************************/ + int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; @@ -3542,8 +3659,9 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /**************************************************************************** - reply to a setdir + Reply to a setdir. ****************************************************************************/ + int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int snum; @@ -3637,6 +3755,7 @@ SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format /**************************************************************************** Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). ****************************************************************************/ + static uint32 map_lock_offset(uint32 high, uint32 low) { unsigned int i; @@ -3716,7 +3835,7 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma } /**************************************************************************** - reply to a lockingX request + Reply to a lockingX request. ****************************************************************************/ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) @@ -3827,7 +3946,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* Setup the timeout in seconds. */ - lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000); + lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000); /* Now do any requested locks */ data += ((large_file_format ? 20 : 10)*num_ulocks); @@ -3855,7 +3974,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); status = do_lock_spin(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); if (NT_STATUS_V(status)) { - if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) { + if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index bdcdce6e14..411ece5249 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -287,17 +287,8 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", (unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx)); - if (ngroups) { - int i; - - DEBUG(3, ("%d user groups: \n", ngroups)); - for (i = 0; i < ngroups; i++) { - DEBUGADD(3, ("%u ", (unsigned int)groups[i])); - } - - DEBUG(3, ("\n")); - } - + debug_nt_user_token(DBGC_CLASS, 5, token); + debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups); gain_root(); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b2b905cec3..39d5e3bcd3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -33,6 +33,8 @@ int last_message = -1; #define LAST_MESSAGE() smb_fn_name(last_message) extern pstring user_socket_options; +extern SIG_ATOMIC_T got_sig_term; +extern SIG_ATOMIC_T reload_after_sighup; #ifdef WITH_DFS extern int dcelogin_atmost_once; @@ -61,8 +63,6 @@ static void smbd_set_server_fd(int fd) Terminate signal. ****************************************************************************/ -SIG_ATOMIC_T got_sig_term = 0; - static void sig_term(void) { got_sig_term = 1; @@ -73,8 +73,6 @@ static void sig_term(void) Catch a sighup. ****************************************************************************/ -SIG_ATOMIC_T reload_after_sighup = 0; - static void sig_hup(int sig) { reload_after_sighup = 1; @@ -542,6 +540,8 @@ void exit_server(char *reason) invalidate_all_vuids(); + print_notify_send_messages(); + /* delete our entry in the connections database. */ yield_connection(NULL,""); @@ -860,7 +860,7 @@ static void usage(char *pname) register_dmalloc_msgs(); /* Setup the main smbd so that we can get messages. */ - claim_connection(NULL,"",0,True); + claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); /* DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 6f83a2d3b7..a8a590da80 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -305,6 +305,7 @@ static void set_admin_user(connection_struct *conn) #endif ) { conn->admin_user = True; + conn->force_user = True; /* Admin users are effectivly 'forced' */ DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user)); } else { conn->admin_user = False; @@ -329,7 +330,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, { struct passwd *pass = NULL; BOOL guest = False; - BOOL force = False; connection_struct *conn; struct stat st; fstring user; @@ -349,7 +349,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (lp_guest_only(snum)) { const char *guestname = lp_guestaccount(); guest = True; - force = True; pass = getpwnam_alloc(guestname); if (!pass) { DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname)); @@ -397,7 +396,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } pass = Get_Pwnam(user); - conn->force_user = force; + conn->force_user = True; conn->uid = pass->pw_uid; conn->gid = pass->pw_gid; string_set(&conn->user, pass->pw_name); @@ -434,7 +433,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* * If force user is true, then store the - * given userid and also the primary groupid + * given userid and also the groups * of the user we're forcing. */ @@ -492,6 +491,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, gid = nametogid(gname); if (gid != (gid_t)-1) { + /* * If the user has been forced and the forced group starts * with a '+', then we only set the group to be the forced @@ -507,6 +507,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->gid = gid; DEBUG(3,("Forced group %s\n",gname)); } + conn->force_group = True; } else { DEBUG(1,("Couldn't find group %s\n",gname)); conn_free(conn); @@ -524,23 +525,27 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); } - /* groups stuff added by ih */ - conn->ngroups = 0; - conn->groups = NULL; - - /* Find all the groups this uid is in and - store them. Used by change_to_user() */ - initialise_groups(conn->user, conn->uid, conn->gid); - get_current_groups(conn->gid, &conn->ngroups,&conn->groups); + if (conn->force_user || conn->force_group) { + + /* groups stuff added by ih */ + conn->ngroups = 0; + conn->groups = NULL; + + /* Find all the groups this uid is in and + store them. Used by change_to_user() */ + initialise_groups(conn->user, conn->uid, conn->gid); + get_current_groups(conn->gid, &conn->ngroups,&conn->groups); - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, - conn->ngroups, conn->groups, - guest, NULL); + conn->nt_user_token = create_nt_token(conn->uid, conn->gid, + conn->ngroups, conn->groups, + guest); + } /* * New code to check if there's a share security descripter * added from NT server manager. This is done after the * smb.conf checks are done as we need a uid and token. JRA. + * */ { @@ -573,7 +578,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (!claim_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn)), - False)) { + False,0)) { DEBUG(1,("too many connections - rejected\n")); conn_free(conn); *status = NT_STATUS_INSUFFICIENT_RESOURCES; @@ -803,7 +808,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) && strequal(service_in, lp_servicename(vuser->homes_snum))) { DATA_BLOB no_pw = data_blob(NULL, 0); - DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service)); + DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in)); return make_connection_snum(vuser->homes_snum, vuser, no_pw, dev, status); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 77f93812dd..b9af720008 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -160,12 +160,12 @@ static int reply_spnego_kerberos(connection_struct *conn, ads_destroy(&ads); /* the password is good - let them in */ - pw = smb_getpwnam(user,False); + pw = Get_Pwnam(user); if (!pw && !strstr(user, lp_winbind_separator())) { char *user2; /* try it with a winbind domain prefix */ asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user); - pw = smb_getpwnam(user2,False); + pw = Get_Pwnam(user2); if (pw) { free(user); user = user2; @@ -177,9 +177,9 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_NO_SUCH_USER); } - if (!make_server_info_pw(&server_info,pw)) { + if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return ERROR_NT(ret); } sess_vuid = register_vuid(server_info, user); @@ -294,8 +294,6 @@ static int reply_spnego_negotiate(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - DEBUG(3,("Got neg_flags=0x%08x\n", neg_flags)); - debug_ntlmssp_flags(neg_flags); if (ntlmssp_auth_context) { @@ -324,12 +322,12 @@ static int reply_spnego_negotiate(connection_struct *conn, "U", lp_workgroup()); - fstrcpy(dnsdomname, lp_realm()); + fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():""); strlower(dnsdomname); fstrcpy(dnsname, global_myname); fstrcat(dnsname, "."); - fstrcat(dnsname, lp_realm()); + fstrcat(dnsname, dnsdomname); strlower(dnsname); msrpc_gen(&struct_blob, "aaaaa", @@ -441,14 +439,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, auth_flags |= AUTH_FLAG_NTLM_RESP; } else if (nthash.length > 24) { auth_flags |= AUTH_FLAG_NTLMv2_RESP; - } + }; + + nt_status = make_user_info_map(&user_info, user, workgroup, machine, + lmhash, nthash, plaintext_password, + auth_flags, True); - if (!make_user_info_map(&user_info, - user, workgroup, - machine, - lmhash, nthash, - plaintext_password, - auth_flags, True)) { + /* it looks a bit weird, but this function returns int type... */ + if (!NT_STATUS_IS_OK(nt_status)) { return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -623,7 +621,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, NTSTATUS nt_status; BOOL doencrypt = global_encrypted_passwords_negotiated; - + START_PROFILE(SMBsesssetupX); ZERO_STRUCT(lm_resp); @@ -736,7 +734,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* don't allow for weird usernames or domains */ alpha_strcpy(user, user, ". _-$", sizeof(user)); - alpha_strcpy(domain, domain, ". _-", sizeof(domain)); + alpha_strcpy(domain, domain, ". _-@", sizeof(domain)); if (strstr(user, "..") || strstr(domain,"..")) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -778,11 +776,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, nt_status = check_guest_password(&server_info); } else if (doencrypt) { - if (!make_user_info_for_reply_enc(&user_info, - user, domain, - lm_resp, nt_resp)) { - nt_status = NT_STATUS_NO_MEMORY; - } else { + nt_status = make_user_info_for_reply_enc(&user_info, user, domain, + lm_resp, nt_resp); + if (NT_STATUS_IS_OK(nt_status)) { nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, user_info, &server_info); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a66c029286..de65cda2d0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -30,19 +30,26 @@ extern int global_oplock_break; extern uint32 global_client_caps; extern pstring global_myname; +#define get_file_size(sbuf) (sbuf.st_size) + /* given a stat buffer return the allocated size on disk, taking into account sparse files */ -SMB_OFF_T get_allocation_size(SMB_STRUCT_STAT *sbuf) +SMB_OFF_T get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) { SMB_OFF_T ret; +#if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS) ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks; - ret = SMB_ROUNDUP_ALLOCATION(ret); +#elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) + ret = (SMB_OFF_T)STAT_ST_BLOCKSIZE * (SMB_OFF_T)sbuf->st_blocks; +#else + ret = get_file_size(*sbuf); +#endif + if (!ret && fsp && fsp->initial_allocation_size) + ret = fsp->initial_allocation_size; + ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE); return ret; } -#define get_file_size(sbuf) (sbuf.st_size) - - /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -579,7 +586,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(&sbuf); + allocation_size = get_allocation_size(NULL,&sbuf); mdate = sbuf.st_mtime; adate = sbuf.st_atime; cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); @@ -660,6 +667,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,nt_extmode); p += 4; q = p; p += 4; SIVAL(p,0,0); p += 4; + /* Clear the short name buffer. This is + * IMPORTANT as not doing so will trigger + * a Win2k client bug. JRA. + */ + memset(p,'\0',26); if (!was_8_3) { pstring mangled_name; pstrcpy(mangled_name, fname); @@ -751,12 +763,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */ p+= 8; -#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */ -#else - /* Can't get the value - fake it using size. */ - SOFF_T(p,0,get_file_size(sbuf)); /* Number of bytes used on disk - 64 Bit */ -#endif + SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ p+= 8; put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */ @@ -899,7 +906,11 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", p = strrchr_m(directory,'/'); if(p == NULL) { - pstrcpy(mask,directory); + /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */ + if((directory[0] == '.') && (directory[1] == '\0')) + pstrcpy(mask,"*"); + else + pstrcpy(mask,directory); pstrcpy(directory,"./"); } else { pstrcpy(mask,p+1); @@ -1554,12 +1565,16 @@ static int call_trans2qfilepathinfo(connection_struct *conn, BOOL delete_pending = False; int len; time_t c_time; + files_struct *fsp = NULL; if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); if (tran_call == TRANSACT2_QFILEINFO) { - files_struct *fsp = file_fsp(params,0); + if (total_params < 4) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + fsp = file_fsp(params,0); info_level = SVAL(params,2); DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); @@ -1657,7 +1672,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, mode = dos_mode(conn,fname,&sbuf); fullpathname = fname; file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(&sbuf); + allocation_size = get_allocation_size(fsp,&sbuf); if (mode & aDIR) file_size = 0; @@ -1842,7 +1857,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_FILE_INTERNAL_INFORMATION: - /* This should be an index number - looks like dev/ino to me :-) */ + /* This should be an index number - looks like + dev/ino to me :-) + + I think this causes us to fail the IFSKIT + BasicFileInformationTest. -tpot */ + SIVAL(pdata,0,sbuf.st_dev); SIVAL(pdata,4,sbuf.st_ino); data_size = 8; @@ -1972,12 +1992,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */ pdata += 8; -#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */ -#else - /* Can't get the value - fake it using size. */ - SOFF_T(pdata,0,get_file_size(sbuf)); /* Number of bytes used on disk - 64 Bit */ -#endif + SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */ @@ -2334,7 +2349,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, switch (info_level) { case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: { if (total_data < l1_cbFile+4) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); @@ -2351,6 +2365,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + case SMB_INFO_SET_EA: + return(ERROR_DOS(ERRDOS,ERReasnotsupported)); + /* XXXX um, i don't think this is right. it's also not in the cifs6.txt spec. */ @@ -2412,11 +2429,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_ALLOCATION_INFO: { int ret = -1; - SMB_OFF_T allocation_size = IVAL(pdata,0); + SMB_OFF_T allocation_size; if (total_data < 8) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + allocation_size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ @@ -2426,6 +2444,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)allocation_size )); + if (allocation_size) + allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + if(allocation_size != get_file_size(sbuf)) { SMB_STRUCT_STAT new_sbuf; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c0bacf8f91..2bda26aa51 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -59,18 +59,26 @@ BOOL change_to_guest(void) static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { int i; - for (i=0;iuid_cache.entries;i++) - if (conn->uid_cache.list[i] == vuser->uid) + for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) + if (conn->vuid_cache.list[i] == vuser->vuid) return(True); + if ((conn->force_user || conn->force_group) + && (conn->vuid != vuser->vuid)) { + return False; + } + if (!user_ok(vuser->user.unix_name,snum)) return(False); - i = conn->uid_cache.entries % UID_CACHE_SIZE; - conn->uid_cache.list[i] = vuser->uid; + if (!share_access_check(conn, snum, vuser, conn->read_only ? FILE_READ_DATA : FILE_WRITE_DATA)) { + return False; + } + + i = conn->vuid_cache.entries % VUID_CACHE_SIZE; + conn->vuid_cache.list[i] = vuser->vuid; - if (conn->uid_cache.entries < UID_CACHE_SIZE) - conn->uid_cache.entries++; + conn->vuid_cache.entries++; return(True); } @@ -115,27 +123,21 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) snum = SNUM(conn); - if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) - return False; - - if (conn->force_user || - conn->admin_user || - (lp_security() == SEC_SHARE)) { + if (conn->force_user) /* security = share sets this too */ { uid = conn->uid; gid = conn->gid; current_user.groups = conn->groups; current_user.ngroups = conn->ngroups; token = conn->nt_user_token; - } else { - if (!vuser) { - DEBUG(2,("change_to_user: Invalid vuid used %d\n",vuid)); - return(False); - } + } else if ((vuser) && check_user_ok(conn, vuser, snum)) { uid = vuser->uid; gid = vuser->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; token = vuser->nt_user_token; + } else { + DEBUG(2,("change_to_user: Invalid vuid used %d or vuid not permitted access to share.\n",vuid)); + return False; } /* @@ -175,7 +177,11 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) if (vuser && vuser->guest) is_guest = True; - token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest, NULL); + token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest); + if (!token) { + DEBUG(1, ("change_to_user: create_nt_token failed!\n")); + return False; + } must_free_token = True; } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 394086dc07..bae304096c 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -20,6 +20,10 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + + /* Check for NULL pointer parameters in vfswrap_* functions */ /* We don't want to have NULL function pointers lying around. Someone @@ -188,6 +192,17 @@ SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int wh return result; } +ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const DATA_BLOB *hdr, + SMB_OFF_T offset, size_t n) +{ + ssize_t result; + + START_PROFILE_BYTES(syscall_sendfile, n); + result = sys_sendfile(tofd, fromfd, hdr, offset, n); + END_PROFILE(syscall_sendfile); + return result; +} + int vfswrap_rename(connection_struct *conn, const char *old, const char *new) { int result; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a2291eba08..a0a7b920b8 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -24,6 +24,10 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + + /* Some structures to help us initialise the vfs operations table */ struct vfs_syminfo { @@ -64,6 +68,7 @@ static struct vfs_ops default_vfs_ops = { vfswrap_read, vfswrap_write, vfswrap_lseek, + vfswrap_sendfile, vfswrap_rename, vfswrap_fsync, vfswrap_stat, @@ -138,7 +143,7 @@ static void vfs_init_default(connection_struct *conn) initialise custom vfs hooks ****************************************************************************/ -static BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) +BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) { int vfs_version = -1; vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *); @@ -259,6 +264,7 @@ BOOL smbd_vfs_init(connection_struct *conn) /******************************************************************* Create vfs_ops reflecting current vfs_opaque_ops *******************************************************************/ + struct vfs_ops *smb_vfs_get_opaque_ops(void) { int i; @@ -297,6 +303,7 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ /******************************************************************* vfs getwd wrapper ********************************************************************/ + static char *vfs_getwd(connection_struct *conn, char *path) { return conn->vfs_ops.getwd(conn,path); -- cgit From ef6f8197a3071996591f74f6d7b9d36dbcb19dc7 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 26 Sep 2002 18:53:51 +0000 Subject: remove files not in HEAD (This used to be commit 9d9f7bbf87bf9a0e003e6da482615fe040d00852) --- source3/smbd/ssl.c | 286 ----------------------------------------------------- 1 file changed, 286 deletions(-) delete mode 100644 source3/smbd/ssl.c (limited to 'source3/smbd') diff --git a/source3/smbd/ssl.c b/source3/smbd/ssl.c deleted file mode 100644 index 7fcb48a954..0000000000 --- a/source3/smbd/ssl.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SSLeay utility functions - Copyright (C) Christian Starkjohann 1998 - - 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. -*/ - -/* - * since includes.h pulls in config.h which is were WITH_SSL will be - * defined, we want to include includes.h before testing for WITH_SSL - * RJS 26-Jan-1999 - */ - -#include "includes.h" - -#ifdef WITH_SSL /* should always be defined if this module is compiled */ - -#include -#include - -BOOL sslEnabled; -SSL *ssl = NULL; -int sslFd = -1; -static SSL_CTX *sslContext = NULL; -extern int DEBUGLEVEL; - -static int ssl_verify_cb(int ok, X509_STORE_CTX *ctx) -{ -char buffer[256]; - - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), - buffer, sizeof(buffer)); - if(ok){ - DEBUG(0, ("SSL: Certificate OK: %s\n", buffer)); - }else{ - switch (ctx->error){ - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - DEBUG(0, ("SSL: Cert error: CA not known: %s\n", buffer)); - break; - case X509_V_ERR_CERT_NOT_YET_VALID: - DEBUG(0, ("SSL: Cert error: Cert not yet valid: %s\n", buffer)); - break; - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - DEBUG(0, ("SSL: Cert error: illegal \'not before\' field: %s\n", - buffer)); - break; - case X509_V_ERR_CERT_HAS_EXPIRED: - DEBUG(0, ("SSL: Cert error: Cert expired: %s\n", buffer)); - break; - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - DEBUG(0, ("SSL: Cert error: invalid \'not after\' field: %s\n", - buffer)); - break; - default: - DEBUG(0, ("SSL: Cert error: unknown error %d in %s\n", ctx->error, - buffer)); - break; - } - } - return ok; -} - -static RSA *ssl_temp_rsa_cb(SSL *ssl, int is_export, int keylength) -{ -static RSA *rsa = NULL; - - if(rsa == NULL) - rsa = RSA_generate_key(keylength, RSA_F4, NULL, NULL); - return rsa; -} - -/* This is called before we fork. It should ask the user for the pass phrase - * if necessary. Error output can still go to stderr because the process - * has a terminal. - */ -int sslutil_init(int isServer) -{ -int err, entropybytes; -char *certfile, *keyfile, *ciphers, *cacertDir, *cacertFile; -char *egdsocket, *entropyfile; - - SSL_load_error_strings(); - SSLeay_add_ssl_algorithms(); - egdsocket = lp_ssl_egdsocket(); - if (egdsocket != NULL && *egdsocket != 0) - RAND_egd(egdsocket); - entropyfile = lp_ssl_entropyfile(); - entropybytes = lp_ssl_entropybytes(); - if (entropyfile != NULL && *entropyfile != 0) - RAND_load_file(entropyfile, entropybytes); - switch(lp_ssl_version()){ - case SMB_SSL_V2: sslContext = SSL_CTX_new(SSLv2_method()); break; - case SMB_SSL_V3: sslContext = SSL_CTX_new(SSLv3_method()); break; - default: - case SMB_SSL_V23: sslContext = SSL_CTX_new(SSLv23_method()); break; - case SMB_SSL_TLS1: sslContext = SSL_CTX_new(TLSv1_method()); break; - } - if(sslContext == NULL){ - err = ERR_get_error(); - fprintf(stderr, "SSL: Error allocating context: %s\n", - ERR_error_string(err, NULL)); - exit(1); - } - if(lp_ssl_compatibility()){ - SSL_CTX_set_options(sslContext, SSL_OP_ALL); - } - certfile = isServer ? lp_ssl_server_cert() : lp_ssl_client_cert(); - if((certfile == NULL || *certfile == 0) && isServer){ - fprintf(stderr, "SSL: No cert file specified in config file!\n"); - fprintf(stderr, "The server MUST have a certificate!\n"); - exit(1); - } - keyfile = isServer ? lp_ssl_server_privkey() : lp_ssl_client_privkey(); - if(keyfile == NULL || *keyfile == 0) - keyfile = certfile; - if(certfile != NULL && *certfile != 0){ - if(!SSL_CTX_use_certificate_chain_file(sslContext, certfile)){ - err = ERR_get_error(); - fprintf(stderr, "SSL: error reading certificate from file %s: %s\n", - certfile, ERR_error_string(err, NULL)); - exit(1); - } - if(!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)){ - err = ERR_get_error(); - fprintf(stderr, "SSL: error reading private key from file %s: %s\n", - keyfile, ERR_error_string(err, NULL)); - exit(1); - } - if(!SSL_CTX_check_private_key(sslContext)){ - err = ERR_get_error(); - fprintf(stderr, "SSL: Private key does not match public key in cert!\n"); - exit(1); - } - } - cacertDir = lp_ssl_cacertdir(); - cacertFile = lp_ssl_cacertfile(); - if(cacertDir != NULL && *cacertDir == 0) - cacertDir = NULL; - if(cacertFile != NULL && *cacertFile == 0) - cacertFile = NULL; - if(!SSL_CTX_load_verify_locations(sslContext, cacertFile, cacertDir)){ - err = ERR_get_error(); - if (cacertFile || cacertDir) { - fprintf(stderr, "SSL: Error error setting CA cert locations: %s\n", - ERR_error_string(err, NULL)); - fprintf(stderr, "trying default locations.\n"); - } - cacertFile = cacertDir = NULL; - if(!SSL_CTX_set_default_verify_paths(sslContext)){ - err = ERR_get_error(); - fprintf(stderr, "SSL: Error error setting default CA cert location: %s\n", - ERR_error_string(err, NULL)); - exit(1); - } - } - SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb); - if((ciphers = lp_ssl_ciphers()) != NULL && *ciphers != 0) - SSL_CTX_set_cipher_list(sslContext, ciphers); - if((isServer && lp_ssl_reqClientCert()) || (!isServer && lp_ssl_reqServerCert())){ - SSL_CTX_set_verify(sslContext, - SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); - }else{ - SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, ssl_verify_cb); - } -#if 1 /* don't know what this is good for, but s_server in SSLeay does it, too */ - if(isServer){ - SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(certfile)); - } -#endif - return 0; -} - -int sslutil_accept(int fd) -{ -int err; - - if(ssl != NULL){ - DEBUG(0, ("SSL: internal error: more than one SSL connection (server)\n")); - return -1; - } - if((ssl = SSL_new(sslContext)) == NULL){ - err = ERR_get_error(); - DEBUG(0, ("SSL: Error allocating handle: %s\n", - ERR_error_string(err, NULL))); - return -1; - } - SSL_set_fd(ssl, fd); - sslFd = fd; - if(SSL_accept(ssl) <= 0){ - err = ERR_get_error(); - DEBUG(0, ("SSL: Error accepting on socket: %s\n", - ERR_error_string(err, NULL))); - return -1; - } - DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl))); - return 0; -} - -int sslutil_fd_is_ssl(int fd) -{ - return fd == sslFd; -} - -int sslutil_connect(int fd) -{ -int err; - - if(ssl != NULL){ - DEBUG(0, ("SSL: internal error: more than one SSL connection (client)\n")); - return -1; - } - if((ssl = SSL_new(sslContext)) == NULL){ - err = ERR_get_error(); - DEBUG(0, ("SSL: Error allocating handle: %s\n", - ERR_error_string(err, NULL))); - return -1; - } - SSL_set_fd(ssl, fd); - sslFd = fd; - if(SSL_connect(ssl) <= 0){ - err = ERR_get_error(); - DEBUG(0, ("SSL: Error conencting socket: %s\n", - ERR_error_string(err, NULL))); - return -1; - } - DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl))); - return 0; -} - -int sslutil_disconnect(int fd) -{ - if(fd == sslFd && ssl != NULL){ - SSL_free(ssl); - ssl = NULL; - sslFd = -1; - } - return 0; -} - -int sslutil_negotiate_ssl(int fd, int msg_type) -{ -unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; -char *reqHosts, *resignHosts; - - reqHosts = lp_ssl_hosts(); - resignHosts = lp_ssl_hosts_resign(); - if(!allow_access(resignHosts, reqHosts, get_socket_name(fd), get_socket_addr(fd))){ - sslEnabled = False; - return 0; - } - if(msg_type != 0x81){ /* first packet must be a session request */ - DEBUG( 0, ( "Client %s did not use session setup; access denied\n", - client_addr() ) ); - if (!send_smb(fd, (char *)buf)) - DEBUG(0, ("sslutil_negotiate_ssl: send_smb failed.\n")); - return -1; - } - buf[4] = 0x8e; /* negative session response: use SSL */ - if (!send_smb(fd, (char *)buf)) { - DEBUG(0,("sslutil_negotiate_ssl: send_smb failed.\n")); - return -1; - } - if(sslutil_accept(fd) != 0){ - DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr() ) ); - return -1; - } - return 1; -} - -#else /* WITH_SSL */ - void ssl_dummy(void); - void ssl_dummy(void) {;} /* So some compilers don't complain. */ -#endif /* WITH_SSL */ -- cgit From a4f7b7bec191c1603f004a14d5b8b49e99305f48 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Oct 2002 18:10:59 +0000 Subject: Write cache bugfix from Rasmus Borup Hansen, system adm. Email: rbh@math.ku.dk Jeremy. (This used to be commit d40a14dbb0ec233f7a2190df1845b039072c4b84) --- source3/smbd/fileio.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 89f05092b4..a29336d3a2 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -440,6 +440,19 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne } else { ssize_t ret = real_write_file(fsp, data, pos, n); + /* + * If the write overlaps the entire cache, then + * discard the current contents of the cache. + * Fix from Rasmus Borup Hansen rbh@math.ku.dk. + */ + + if ((pos <= wcp->offset) && + (pos + n >= wcp->offset + wcp->data_size) ) { + DEBUG(9,("write_file: discarding overwritten write \ +cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned int)wcp->data_size )); + wcp->data_size = 0; + } + DO_PROFILE_INC(writecache_direct_writes); if (ret == -1) return ret; -- cgit From 474340e4403648812e7d8eb9eeb4c4111afbf725 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Oct 2002 19:05:36 +0000 Subject: Added ASCII art to make this clearer. Jeremy. (This used to be commit 31c0dd7e213509c3bed1061f140f2ea9c6e95a9d) --- source3/smbd/fileio.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index a29336d3a2..d5df9826df 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -256,6 +256,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) { + /* ASCII art.... JRA. + + +--------------+----- + | Cached data | Rest of allocated cache buffer.... + +--------------+----- + + +-------------------+ + | Data to write | + +-------------------+ + + */ + /* * Start of write overlaps or abutts the existing data. */ @@ -305,6 +317,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", } else if ((pos < wcp->offset) && (pos + n > wcp->offset) && (pos + n <= wcp->offset + wcp->alloc_size)) { + /* ASCII art.... JRA. + + +---------------+ + | Cache buffer | + +---------------+ + + +-------------------+ + | Data to write | + +-------------------+ + + */ + /* * End of write overlaps the existing data. */ @@ -350,6 +374,20 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", (pos > wcp->offset + wcp->data_size) && (pos < wcp->offset + wcp->alloc_size) ) { + /* ASCII art.... JRA. + + End of file ---->| + + +---------------+---------------+ + | Cached data | Cache buffer | + +---------------+---------------+ + + +-------------------+ + | Data to write | + +-------------------+ + + */ + /* * Non-contiguous write part of which fits within * the cache buffer and is extending the file @@ -413,7 +451,41 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", } else { - /* + /* ASCII art..... JRA. + + Case 1). + + +---------------+---------------+ + | Cached data | Cache buffer | + +---------------+---------------+ + + +-------------------+ + | Data to write | + +-------------------+ + + Case 2). + + +---------------+---------------+ + | Cached data | Cache buffer | + +---------------+---------------+ + + +-------------------+ + | Data to write | + +-------------------+ + + Case 3). + + +---------------+---------------+ + | Cached data | Cache buffer | + +---------------+---------------+ + + +-----------------------------------------------------+ + | Data to write | + +-----------------------------------------------------+ + + */ + + /* * Write is bigger than buffer, or there is no overlap on the * low or high ends. */ -- cgit From 36ef82a52953384acedbd51f54ded9357fa8ca3e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 4 Oct 2002 04:10:23 +0000 Subject: merge of new client side support the Win2k LSARPC UUID in rpcbind from APP_HEAD (This used to be commit 1cfd2ee433305e91e87804dd55d10e025d30a69e) --- source3/smbd/change_trust_pw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 0c468699b4..4b2944a96f 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -60,7 +60,7 @@ static NTSTATUS modify_trust_password( char *domain, char *remote_machine, * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(cli, PIPE_NETLOGON) == False) { + if(cli_nt_session_open(cli, PI_NETLOGON) == False) { DEBUG(0,("modify_trust_password: unable to open the domain client session to \ machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli))); cli_nt_session_close(cli); -- cgit From 2d5d51e9f3df7013b5993f889d4c85c2a722e511 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Oct 2002 18:09:29 +0000 Subject: Fix from Andreas Gruenbacher to prevent ACL set on read-only share. Jeremy. (This used to be commit 9b8f362abc5abf25f02718774a8aa1f4574f19ff) --- source3/smbd/posix_acls.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index e6ae1c7d79..6b1b62417a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2124,6 +2124,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); + if (!CAN_WRITE(conn)) { + DEBUG(10,("set acl rejected on read-only share\n")); + return False; + } + /* * Get the current state of the file. */ -- cgit From 06b5917af4a21f6026fea647f005cdb9b4db8123 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Oct 2002 00:20:17 +0000 Subject: Fix based on Jim McDonough's code for ACL inheritance problem. Jeremy. (This used to be commit 3343efaaa8b80d5bc549afebbc06e02e125a6af9) --- source3/smbd/posix_acls.c | 69 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6b1b62417a..87ebddf35a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1872,6 +1872,45 @@ static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2) return 1; } +/**************************************************************************** + Incoming NT ACLs on a directory can be split into a default POSIX acl (CI|OI|IO) and + a normal POSIX acl. Win2k needs these split acls re-merging into one ACL + with CI|OI set so it is inherited and also applies to the directory. + Based on code from "Jim McDonough" . +****************************************************************************/ + +static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) +{ + size_t i, j; + + for (i = 0; i < num_aces; i++) { + for (j = i+1; j < num_aces; j++) { + /* We know the lower number ACE's are file entries. */ + if ((nt_ace_list[i].type == nt_ace_list[j].type) && + (nt_ace_list[i].size == nt_ace_list[j].size) && + (nt_ace_list[i].info.mask == nt_ace_list[j].info.mask) && + sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) && + (nt_ace_list[i].flags == 0) && + (nt_ace_list[j].flags == (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY))) { + /* + * These are identical except for the flags. + * Merge the inherited ACE onto the non-inherited ACE. + */ + + nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT; + if (num_aces - j - 1 > 0) + memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) * + sizeof(SEC_ACE)); + num_aces--; + break; + } + } + } + + return num_aces; +} /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns the size needed to return the @@ -1978,7 +2017,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) goto done; } - memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + memset(nt_ace_list, '\0', (num_acls + num_profile_acls + num_dir_acls) * sizeof(SEC_ACE) ); /* * Create the NT ACE list from the canonical ace lists. @@ -2020,15 +2059,23 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) SEC_ACE_FLAG_INHERIT_ONLY); } + /* + * Merge POSIX default ACLs and normal ACLs into one NT ACE. + * Win2K needs this to get the inheritance correct when replacing ACLs + * on a directory tree. Based on work by Jim @ IBM. + */ + + num_aces = merge_default_aces(nt_ace_list, num_aces); + /* * Sort to force deny entries to the front. */ - if (num_acls + num_dir_acls) - qsort( nt_ace_list, num_acls + num_dir_acls, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp); + if (num_aces) + qsort( nt_ace_list, num_aces, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp); } - if (num_acls) { + if (num_aces) { if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); goto done; @@ -2055,14 +2102,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) return sd_size; } -/* - try to chown a file. We will be able to chown it under the following conditions +/**************************************************************************** + Try to chown a file. We will be able to chown it under the following conditions. - 1) if we have root privileges, then it will just work - 2) if we have write permission to the file and dos_filemodes is set + 1) If we have root privileges, then it will just work. + 2) If we have write permission to the file and dos_filemodes is set then allow chown to the currently authenticated user. +****************************************************************************/ - */ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; @@ -2409,6 +2456,10 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) return ret; } +/**************************************************************************** + Check for an existing default POSIX ACL on a directory. +****************************************************************************/ + BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { SMB_ACL_T dir_acl = conn->vfs_ops.sys_acl_get_file( conn, fname, SMB_ACL_TYPE_DEFAULT); -- cgit From d0a99a261d31f39c2d30a067d3d7efb80282a15a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Oct 2002 01:19:00 +0000 Subject: Turns out with Win9x, we could occasionally return from unix_convert() given a mangled name without a valid stat struct if the file existed. This would then cause open_file_shared1() to erroneously think the file open was new, thus not check for oplock break, thus causing a spurious EAGAIN reply to the open on a file we already had kernel oplocked.... (phew - that was fun to track down :-). Jeremy. (This used to be commit af80b033a5374da9163e3484f7d8707813490597) --- source3/smbd/filename.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d343db26f6..202bd75d4c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -318,6 +318,18 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcat(start,"/"); pstrcat(start,rest); *end = '\0'; + } else { + /* + * We just scanned for, and found the end of the path. + * We must return a valid stat struct if it exists. + * JRA. + */ + + if (vfs_stat(conn,name, &st) == 0) { + *pst = st; + } else { + ZERO_STRUCT(st); + } } } /* end else */ -- cgit From b8e4a3331ddcda9339b2508e1ef24a1c2eab19cb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Oct 2002 05:58:32 +0000 Subject: Merge Anton's 64-bit fix. Jeremy. (This used to be commit 0644f6a68e5c1d9a2c236ab0f90d4801848a9b33) --- source3/smbd/mangle_hash2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index a0a3d51139..5adde19eea 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -147,14 +147,12 @@ static BOOL cache_init(void) { if (prefix_cache) return True; - prefix_cache = malloc(sizeof(char *) * MANGLE_CACHE_SIZE); + prefix_cache = calloc(MANGLE_CACHE_SIZE, sizeof(char *)); if (!prefix_cache) return False; - prefix_cache_hashes = malloc(sizeof(u32) * MANGLE_CACHE_SIZE); + prefix_cache_hashes = calloc(MANGLE_CACHE_SIZE, sizeof(u32)); if (!prefix_cache_hashes) return False; - memset(prefix_cache, 0, sizeof(char *) * MANGLE_CACHE_SIZE); - memset(prefix_cache_hashes, 0, sizeof(char *) * MANGLE_CACHE_SIZE); return True; } -- cgit From 3d8274df34a9f7d2a1f221534f7c32bfb4450f87 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Oct 2002 21:35:46 +0000 Subject: Change default of max_xmit to match W2K. Ensure NT negprot uses it. Jeremy. (This used to be commit 0bf7187e3ba57ee2422a0f6f736266a55502123c) --- source3/smbd/negprot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 16427b00d7..06a55cb33e 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -275,7 +275,7 @@ static int reply_nt1(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ - SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ + SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */ SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */ SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ -- cgit From c53eb2ed540e79d6deae5f41e17febc5bf5dbf57 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Oct 2002 17:10:24 +0000 Subject: Added new error codes. Fix up connection code to retry in the same way that app-head does. Jeremy. (This used to be commit ec7953f20145799f6286a295472df4826bfdfb8f) --- source3/smbd/change_trust_pw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 4b2944a96f..5da735e875 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -50,7 +50,7 @@ static NTSTATUS modify_trust_password( char *domain, char *remote_machine, NULL, 0, "IPC$", "IPC", "", "", - "", 0))) { + "", 0, NULL))) { DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); return NT_STATUS_UNSUCCESSFUL; } -- cgit From 6ce3e3b10c30946ebe6ce25b5be0ca03e9d5617f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 21 Oct 2002 20:11:12 +0000 Subject: removed the following parameters * postscript * printer driver * printer driver location * printer driver file also removed the get_a_printer_driver_9x_compatible() function (This used to be commit 743f2b8025effe57d8f075ff14a9357123c507a8) --- source3/smbd/fileio.c | 10 +- source3/smbd/lanman.c | 309 +++++++++++++++----------------------------------- 2 files changed, 94 insertions(+), 225 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index d5df9826df..6bae1df996 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -30,13 +30,9 @@ static BOOL setup_write_cache(files_struct *, SMB_OFF_T); static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { - SMB_OFF_T offset = 0; SMB_OFF_T seek_ret; - if (fsp->print_file && lp_postscript(fsp->conn->service)) - offset = 3; - - seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos+offset,SEEK_SET); + seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos,SEEK_SET); if(seek_ret == -1) { DEBUG(0,("seek_file: (%s) sys_lseek failed. Error was %s\n", @@ -45,10 +41,10 @@ static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) return -1; } - fsp->pos = seek_ret - offset; + fsp->pos = seek_ret; DEBUG(10,("seek_file (%s): requested pos = %.0f, new pos = %.0f\n", - fsp->fsp_name, (double)(pos+offset), (double)fsp->pos )); + fsp->fsp_name, (double)pos, (double)fsp->pos )); return(fsp->pos); } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 8bfad4ab33..0db1af6032 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -494,7 +494,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, /******************************************************************** Return a driver name given an snum. - Looks in a tdb first. Returns True if from tdb, False otherwise. + Returns True if from tdb, False otherwise. ********************************************************************/ static BOOL get_driver_name(int snum, pstring drivername) @@ -507,8 +507,6 @@ static BOOL get_driver_name(int snum, pstring drivername) pstrcpy( drivername, info->info_2->drivername); in_tdb = True; free_a_printer(&info, 2); - } else { - pstrcpy( drivername, lp_printerdriver(snum)); } return in_tdb; @@ -518,162 +516,83 @@ static BOOL get_driver_name(int snum, pstring drivername) Respond to the DosPrintQInfo command with a level of 52 This is used to get printer driver information for Win9x clients ********************************************************************/ -static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc, - int count, print_queue_struct* queue, - print_status_struct* status) +static void fill_printq_info_52(connection_struct *conn, int snum, + struct pack_desc* desc, int count ) { - int i; - BOOL ok = False; - pstring tok,driver,datafile,langmon,helpfile,datatype; - char *p; - char **lines = NULL; - pstring gen_line; - BOOL in_tdb = False; - fstring location; - pstring drivername; - - /* - * Check in the tdb *first* before checking the legacy - * files. This allows an NT upload to take precedence over - * the existing fileset. JRA. - * - * we need to lookup the driver name prior to making the call - * to get_a_printer_driver_9x_compatible() and not rely on the - * 'print driver' parameter --jerry - */ - - - if ((get_driver_name(snum,drivername)) && - ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True)) - { - in_tdb = True; - p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line)); - } - else - { - /* didn't find driver in tdb */ - - DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", - snum, drivername, lp_driverfile(snum))); - - lines = file_lines_load(lp_driverfile(snum),NULL); - if (!lines) - { - DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum), - strerror(errno))); - desc->errcode=NERR_notsupported; - goto done; - } - - /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) - { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(drivername) == strlen(tok)) && - (!strncmp(tok,drivername,strlen(drivername)))) - { - ok = True; - } - } + int i; + fstring location; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + NT_PRINTER_INFO_LEVEL *printer = NULL; + + if ( !W_ERROR_IS_OK(get_a_printer( &printer, 2, lp_servicename(snum))) ) { + DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", + lp_servicename(snum))); + goto err; } - - if (ok) + + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, + "Windows 4.0", 0)) ) { - /* driver file name */ - if (!next_token(&p,driver,":",sizeof(driver))) - goto err; - - /* data file name */ - if (!next_token(&p,datafile,":",sizeof(datafile))) - goto err; - - /* - * for the next tokens - which may be empty - I have - * to check for empty tokens first because the - * next_token function will skip all empty token - * fields */ + DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", + printer->info_2->drivername)); + goto err; + } - /* help file */ - if (*p == ':') - { - *helpfile = '\0'; - p++; - } - else if (!next_token(&p,helpfile,":",sizeof(helpfile))) - goto err; + trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0); + trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0); + trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0); - /* language monitor */ - if (*p == ':') - { - *langmon = '\0'; - p++; - } - else if (!next_token(&p,langmon,":",sizeof(langmon))) - goto err; + PACKI(desc, "W", 0x0400); /* don't know */ + PACKS(desc, "z", driver.info_3->name); /* long printer name */ + PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */ + PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */ + PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ - /* default data type */ - if (!next_token(&p,datatype,":",sizeof(datatype))) - goto err; + fstrcpy(location, "\\\\"); + fstrcat(location, get_called_name()); + fstrcat(location, "\\print$\\WIN40\\0"); + PACKS(desc,"z", location); /* share to retrieve files */ - PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",drivername); /* long printer name */ - PACKS(desc,"z",driver); /* Driverfile Name */ - PACKS(desc,"z",datafile); /* Datafile name */ - PACKS(desc,"z",langmon); /* language monitor */ - if (in_tdb) - { - fstrcpy(location, "\\\\"); - fstrcat(location, global_myname); - fstrcat(location, "\\print$\\WIN40\\0"); - PACKS(desc,"z",location); /* share to retrieve files */ - } - else - { - PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */ - } - PACKS(desc,"z",datatype); /* default data type */ - PACKS(desc,"z",helpfile); /* helpfile name */ - PACKS(desc,"z",driver); /* driver name */ - - DEBUG(3,("printerdriver:%s:\n",drivername)); - DEBUG(3,("Driver:%s:\n",driver)); - DEBUG(3,("Data File:%s:\n",datafile)); - DEBUG(3,("Language Monitor:%s:\n",langmon)); - if (in_tdb) - DEBUG(3,("lp_driverlocation:%s:\n",location)); - else - DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum))); - DEBUG(3,("Data Type:%s:\n",datatype)); - DEBUG(3,("Help File:%s:\n",helpfile)); - PACKI(desc,"N",count); /* number of files to copy */ - - for (i=0;i gave %d entries\n", - SERVICE(snum),count)); - - desc->errcode=NERR_Success; - goto done; + PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ + PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */ + PACKS(desc,"z", driver.info_3->driverpath); /* driver name */ + + DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name)); + DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath)); + DEBUG(3,("Data File: %s:\n",driver.info_3->datafile)); + DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname)); + DEBUG(3,("Driver Location: %s:\n",location)); + DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype)); + DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile)); + PACKI(desc,"N",count); /* number of files to copy */ + + for ( i=0; idependentfiles && *driver.info_3->dependentfiles[i]; i++) + { + trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0); + PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */ + DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i])); } + + /* sanity check */ + if ( i != count ) + DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n", + count, i)); + + DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i)); - err: + desc->errcode=NERR_Success; + goto done; +err: DEBUG(3,("fill_printq_info: Can't supply driver files\n")); desc->errcode=NERR_notsupported; - done: - file_lines_free(lines); +done: + if ( printer ) + free_a_printer( &printer, 2 ); + + if ( driver.info_3 ) + free_a_printer_driver( driver, 3 ); } @@ -751,88 +670,42 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i); } - if (uLevel==52) { - fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status); - } + if (uLevel==52) + fill_printq_info_52( conn, snum, desc, count ); } /* This function returns the number of files for a given driver */ static int get_printerdrivernumber(int snum) { - int i, result = 0; - BOOL ok = False; - pstring tok; - char *p; - char **lines = NULL; - pstring gen_line; - pstring drivername; - - /* - * Check in the tdb *first* before checking the legacy - * files. This allows an NT upload to take precedence over - * the existing fileset. JRA. - * - * we need to lookup the driver name prior to making the call - * to get_a_printer_driver_9x_compatible() and not rely on the - * 'print driver' parameter --jerry - */ - - if ((get_driver_name(snum,drivername)) && - (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True)) - { - p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line)); - } - else - { - /* didn't find driver in tdb */ - - DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", - snum, drivername, lp_driverfile(snum))); - - lines = file_lines_load(lp_driverfile(snum), NULL); - if (!lines) - { - DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - goto done; - } + int result = 0; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + NT_PRINTER_INFO_LEVEL *printer = NULL; - /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) - { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(drivername) == strlen(tok)) && - (!strncmp(tok,drivername,strlen(drivername)))) - { - ok = True; - } - } + if ( !W_ERROR_IS_OK(get_a_printer( &printer, 2, lp_servicename(snum))) ) { + DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", + lp_servicename(snum))); + goto done; } - - if( ok ) - { - /* skip 5 fields */ - i = 5; - while (*p && i) { - if (*p++ == ':') i--; - } - if (!*p || i) { - DEBUG(3,("Can't determine number of printer driver files\n")); - goto done; - } - /* count the number of files */ - while (next_token(&p,tok,",",sizeof(tok))) - i++; - - result = i; + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, + "Windows 4.0", 0)) ) + { + DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n", + printer->info_2->drivername)); + goto done; } - + + /* count the number of files */ + while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] ) + result++; + \ done: - - file_lines_free(lines); - + if ( printer ) + free_a_printer( &printer, 2 ); + + if ( driver.info_3 ) + free_a_printer_driver( driver, 3 ); + return result; } -- cgit From 1ef283d5c34d58389309a86e768ba52413943e9d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 21 Oct 2002 20:40:23 +0000 Subject: Merge mangle prefix code. Jeremy. (This used to be commit 83261f43326ae65af498399b5c933dfb20df1df7) --- source3/smbd/mangle_hash2.c | 57 ++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 5adde19eea..bbc9020eab 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -87,6 +87,13 @@ static unsigned char char_flags[256]; #define FLAG_CHECK(c, flag) (char_flags[(unsigned char)(c)] & (flag)) +/* + this determines how many characters are used from the original filename + in the 8.3 mangled name. A larger value leads to a weaker hash and more collisions. + The largest possible value is 6. +*/ +static unsigned mangle_prefix; + /* we will use a very simple direct mapped prefix cache. The big advantage of this cache structure is speed and low memory usage @@ -217,16 +224,18 @@ static BOOL is_mangled_component(const char *name) } } - /* check first character */ - if (! FLAG_CHECK(name[0], FLAG_ASCII)) { - return False; + /* check lead characters */ + for (i=0;i=1;i--) { + for (multiplier=36, i=5;i>=mangle_prefix;i--) { u32 v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; @@ -478,7 +487,7 @@ static BOOL is_legal_name(const char *name) static void name_map(char *name, BOOL need83, BOOL cache83) { char *dot_p; - char lead_char; + char lead_chars[7]; char extension[4]; int extension_length, i; int prefix_len; @@ -516,15 +525,20 @@ static void name_map(char *name, BOOL need83, BOOL cache83) if (i == 0 || i == 4) dot_p = NULL; } - /* the leading character in the mangled name is taken from - the first character of the name, if it is ascii - otherwise '_' is used + /* the leading characters in the mangled name is taken from + the first characters of the name, if they are ascii otherwise + '_' is used */ - lead_char = name[0]; - if (! FLAG_CHECK(lead_char, FLAG_ASCII)) { - lead_char = '_'; + for (i=0;i=1; i--) { + for (i=5; i>=mangle_prefix; i--) { v = v / 36; new_name[i] = base_forward(v % 36); } @@ -594,7 +610,7 @@ static void init_tables(void) memset(char_flags, 0, sizeof(char_flags)); - for (i=0;i<128;i++) { + for (i=1;i<128;i++) { if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) { @@ -656,6 +672,15 @@ static struct mangle_fns mangle_fns = { /* return the methods for this mangling implementation */ struct mangle_fns *mangle_hash2_init(void) { + /* the mangle prefix can only be in the mange 1 to 6 */ + mangle_prefix = lp_mangle_prefix(); + if (mangle_prefix > 6) { + mangle_prefix = 6; + } + if (mangle_prefix < 1) { + mangle_prefix = 1; + } + init_tables(); mangle_reset(); -- cgit From 83219da3028a0341a9c7b2db38738ca30288686b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Oct 2002 22:17:29 +0000 Subject: Fix for systems that allow more than 65536 open files per process. Jeremy. (This used to be commit 947a56ce00e552e8b8d2ed64435eabde6225f044) --- source3/smbd/files.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index c055fb54eb..d926718c5d 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -112,6 +112,8 @@ files_struct *file_new(connection_struct *conn) files_used++; fsp->fnum = i + FILE_HANDLE_OFFSET; + SMB_ASSERT(fsp->fnum < 65536); + string_set(&fsp->fsp_name,""); DLIST_ADD(Files, fsp); @@ -144,7 +146,7 @@ void file_close_conn(connection_struct *conn) Initialise file structures. ****************************************************************************/ -#define MAX_OPEN_FUDGEFACTOR 10 +#define MAX_OPEN_FUDGEFACTOR 20 void file_init(void) { @@ -160,11 +162,16 @@ void file_init(void) real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR; + if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) + real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES; + if(real_max_open_files != request_max_open_files) { DEBUG(1,("file_init: Information only: requested %d \ open files, %d are available.\n", request_max_open_files, real_max_open_files)); } + SMB_ASSERT(real_max_open_files > 100); + file_bmap = bitmap_allocate(real_max_open_files); if (!file_bmap) { -- cgit From f735551b9edef66b152261cf6eb2f29b7b69d65b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Oct 2002 01:22:32 +0000 Subject: First cut of new ACL mapping code from Andreas Gruenbacher . This is not 100% the same as what SuSE shipped in their Samba, there is a crash bug fix, a race condition fix, and a few logic changes I'd like to discuss with Andreas. Added Andreas to (C) notices for posix_acls.c Jeremy. (This used to be commit 40eafb9dde113af9f7f1808fda22908953f7e8c3) --- source3/smbd/open.c | 6 +- source3/smbd/posix_acls.c | 525 ++++++++++++++++++++++++++++++++++++---------- source3/smbd/trans2.c | 2 + source3/smbd/uid.c | 2 +- source3/smbd/vfs.c | 3 + 5 files changed, 430 insertions(+), 108 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a95793a050..417a9dd039 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -165,9 +165,13 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags |= O_NONBLOCK; #endif - /* actually do the open */ + /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); + /* Inherit the ACL if the file was created. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) + inherit_access_acl(conn, fname, mode); + if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", fname,strerror(errno),local_flags,flags)); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 87ebddf35a..22bb7fe76b 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. SMB NT Security Descriptor / Unix permission conversion. - Copyright (C) Jeremy Allison 1994-2000 + Copyright (C) Jeremy Allison 1994-2000. + Copyright (C) Andreas Gruenbacher 2002. 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 @@ -329,6 +330,24 @@ static void merge_aces( canon_ace **pp_list_head ) *pp_list_head = list_head; } +/**************************************************************************** + Check if we need to return NT4.x compatible ACL entries. +****************************************************************************/ + +static BOOL nt4_compatible_acls(void) +{ + const char *compat = lp_acl_compatibility(); + + if (*compat == '\0') { + enum remote_arch_types ra_type = get_remote_arch(); + + /* Automatically adapt to client */ + return (ra_type <= RA_WINNT); + } else + return (strequal(compat, "winnt")); +} + + /**************************************************************************** Map canon_ace perms to permission bits NT. The attr element is not used here - we only process deny entries on set, @@ -345,7 +364,19 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon if ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS) { nt_mask = UNIX_ACCESS_RWX; } else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) { - nt_mask = UNIX_ACCESS_NONE; + /* + * Windows NT refuses to display ACEs with no permissions in them (but + * they are perfectly legal with Windows 2000). If the ACE has empty + * permissions we cannot use 0, so we use the otherwise unused + * WRITE_OWNER permission, which we ignore when we set an ACL. + * We abstract this into a #define of UNIX_ACCESS_NONE to allow this + * to be changed in the future. + */ + + if (nt4_compatible_acls()) + nt_mask = UNIX_ACCESS_NONE; + else + nt_mask = 0; } else { nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); @@ -621,7 +652,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, else if (got_grp && uid_entry_in_group(pace, pace_group)) pace->perms = pace_group->perms; else - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); + pace->perms = 0; apply_default_perms(fsp, pace, S_IRUSR); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); @@ -668,7 +699,10 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->unix_ug.world = -1; pace->trustee = global_sid_World; pace->attr = ALLOW_ACE; - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); + if (setting_acl) + pace->perms = 0; + else + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); apply_default_perms(fsp, pace, S_IROTH); DLIST_ADD(*pp_ace, pace); @@ -677,6 +711,51 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, return True; } +/**************************************************************************** + Check if a POSIX ACL has the required SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries. + If it does not have them, check if there are any entries where the trustee is the + file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ. +****************************************************************************/ + +static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid) +{ + BOOL got_user_obj, got_group_obj; + canon_ace *current_ace; + int i, entries; + + entries = count_canon_ace_list(ace); + got_user_obj = False; + got_group_obj = False; + + for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) { + if (current_ace->type == SMB_ACL_USER_OBJ) + got_user_obj = True; + else if (current_ace->type == SMB_ACL_GROUP_OBJ) + got_group_obj = True; + } + if (got_user_obj && got_group_obj) { + DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n")); + return; + } + + for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) { + if (!got_user_obj && current_ace->owner_type == UID_ACE && + sid_equal(¤t_ace->trustee, pfile_owner_sid)) { + current_ace->type = SMB_ACL_USER_OBJ; + got_user_obj = True; + } + if (!got_group_obj && current_ace->owner_type == GID_ACE && + sid_equal(¤t_ace->trustee, pfile_grp_sid)) { + current_ace->type = SMB_ACL_GROUP_OBJ; + got_group_obj = True; + } + } + if (!got_user_obj) + DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n")); + if (!got_group_obj) + DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n")); +} + /**************************************************************************** Unpack a SEC_DESC into two canonical ace lists. ****************************************************************************/ @@ -687,6 +766,8 @@ static BOOL create_canon_ace_lists(files_struct *fsp, canon_ace **ppfile_ace, canon_ace **ppdir_ace, SEC_ACL *dacl) { + extern DOM_SID global_sid_Creator_Owner; + extern DOM_SID global_sid_Creator_Group; extern DOM_SID global_sid_World; extern struct generic_mapping file_generic_mapping; BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); @@ -713,23 +794,25 @@ static BOOL create_canon_ace_lists(files_struct *fsp, return False; } - /* - * The security mask may be UNIX_ACCESS_NONE which should map into - * no permissions (we overload the WRITE_OWNER bit for this) or it - * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this - * to be so. Any other bits override the UNIX_ACCESS_NONE bit. - */ + if (nt4_compatible_acls()) { + /* + * The security mask may be UNIX_ACCESS_NONE which should map into + * no permissions (we overload the WRITE_OWNER bit for this) or it + * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this + * to be so. Any other bits override the UNIX_ACCESS_NONE bit. + */ - /* - * Convert GENERIC bits to specific bits. - */ + /* + * Convert GENERIC bits to specific bits. + */ - se_map_generic(&psa->info.mask, &file_generic_mapping); + se_map_generic(&psa->info.mask, &file_generic_mapping); - psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS); + psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS); - if(psa->info.mask != UNIX_ACCESS_NONE) - psa->info.mask &= ~UNIX_ACCESS_NONE; + if(psa->info.mask != UNIX_ACCESS_NONE) + psa->info.mask &= ~UNIX_ACCESS_NONE; + } } /* @@ -804,15 +887,45 @@ static BOOL create_canon_ace_lists(files_struct *fsp, /* * Try and work out if the SID is a user or group * as we need to flag these differently for POSIX. + * Note what kind of a POSIX ACL this should map to. */ if( sid_equal(¤t_ace->trustee, &global_sid_World)) { current_ace->owner_type = WORLD_ACE; current_ace->unix_ug.world = -1; + current_ace->type = SMB_ACL_OTHER; + } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) { + current_ace->owner_type = UID_ACE; + current_ace->unix_ug.world = -1; + current_ace->type = SMB_ACL_USER_OBJ; + + /* + * The Creator Owner entry only specifies inheritable permissions, + * never access permissions. WinNT doesn't always set the ACE to + *INHERIT_ONLY, though. + */ + + if (nt4_compatible_acls()) + psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; + } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) { + current_ace->owner_type = GID_ACE; + current_ace->unix_ug.world = -1; + current_ace->type = SMB_ACL_GROUP_OBJ; + + /* + * The Creator Group entry only specifies inheritable permissions, + * never access permissions. WinNT doesn't always set the ACE to + *INHERIT_ONLY, though. + */ + if (nt4_compatible_acls()) + psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; + } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid, &sid_type)) { current_ace->owner_type = UID_ACE; + current_ace->type = SMB_ACL_USER; } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid, &sid_type)) { current_ace->owner_type = GID_ACE; + current_ace->type = SMB_ACL_GROUP; } else { fstring str; @@ -832,31 +945,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE; - /* - * Now note what kind of a POSIX ACL this should map to. - */ - - if(sid_equal(¤t_ace->trustee, pfile_owner_sid)) { - - current_ace->type = SMB_ACL_USER_OBJ; - - } else if( sid_equal(¤t_ace->trustee, pfile_grp_sid)) { - - current_ace->type = SMB_ACL_GROUP_OBJ; - - } else if( sid_equal(¤t_ace->trustee, &global_sid_World)) { - - current_ace->type = SMB_ACL_OTHER; - - } else { - /* - * Could be a SMB_ACL_USER or SMB_ACL_GROUP. Check by - * looking at owner_type. - */ - - current_ace->type = (current_ace->owner_type == UID_ACE) ? SMB_ACL_USER : SMB_ACL_GROUP; - } - /* * Now add the created ace to either the file list, the directory * list, or both. We *MUST* preserve the order here (hence we use @@ -970,6 +1058,15 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); free_canon_ace_list(dir_ace); file_ace = NULL; dir_ace = NULL; + } else { + /* + * Check if we have SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries in each + * ACL. If we don't have them, check if any SMB_ACL_USER/SMB_ACL_GROUP + * entries can be converted to *_OBJ. Usually we will already have these + * entries in the Default ACL, and the Access ACL will not have them. + */ + check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid); + check_owning_objs(dir_ace, pfile_owner_sid, pfile_grp_sid); } *ppfile_ace = file_ace; @@ -1375,7 +1472,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, pst->st_mode = create_default_mode(fsp, True); - if (!ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { + if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -1398,14 +1495,13 @@ static BOOL unpack_canon_ace(files_struct *fsp, Note that this doesn't exactly match the NT semantics for an ACL. As POSIX entries are not ordered, and match on the most specific entry rather than walking a list, - then a simple POSIX permission of rw-r--r-- should really map to 6 entries, + then a simple POSIX permission of rw-r--r-- should really map to 5 entries, Entry 0: owner : deny all except read and write. Entry 1: group : deny all except read. - Entry 2: Everyone : deny all except read. - Entry 3: owner : allow read and write. - Entry 4: group : allow read. - Entry 5: Everyone : allow read. + Entry 2: owner : allow read and write. + Entry 3: group : allow read. + Entry 4: Everyone : allow read. But NT cannot display this in their ACL editor ! ********************************************************************************/ @@ -1455,7 +1551,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) ****************************************************************************/ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup) + DOM_SID *powner, DOM_SID *pgroup, SMB_ACL_TYPE_T acl_type) { extern DOM_SID global_sid_World; connection_struct *conn = fsp->conn; @@ -1489,7 +1585,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ switch(tagtype) { case SMB_ACL_USER_OBJ: /* Get the SID from the owner. */ - uid_to_sid( &sid, psbuf->st_uid ); + sid_copy(&sid, powner); unix_ug.uid = psbuf->st_uid; owner_type = UID_ACE; break; @@ -1500,6 +1596,15 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ DEBUG(0,("canonicalise_acl: Failed to get uid.\n")); continue; } + /* + * A SMB_ACL_USER entry for the owner is shadowed by the + * SMB_ACL_USER_OBJ entry and Windows also cannot represent + * that entry, so we ignore it. We also don't create such + * entries out of the blue when setting ACLs, so a get/set + * cycle will drop them. + */ + if (acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) + continue; uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; @@ -1508,7 +1613,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ } case SMB_ACL_GROUP_OBJ: /* Get the SID from the owning group. */ - gid_to_sid( &sid, psbuf->st_gid ); + sid_copy(&sid, pgroup); unix_ug.gid = psbuf->st_gid; owner_type = GID_ACE; break; @@ -1611,8 +1716,11 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau canon_ace *p_ace; int i; SMB_ACL_ENTRY_T mask_entry; + BOOL got_mask_entry = False; SMB_ACL_PERMSET_T mask_permset; SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS); + BOOL needs_mask = False; + mode_t mask_perms = 0; if (the_acl == NULL) { @@ -1632,6 +1740,20 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau SMB_ACL_ENTRY_T the_entry; SMB_ACL_PERMSET_T the_permset; + /* + * ACLs only "need" an ACL_MASK entry if there are any named user or + * named group entries. But if there is an ACL_MASK entry, it applies + * to ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries. Set the mask + * so that it doesn't deny (i.e., mask off) any permissions. + */ + + if (p_ace->type == SMB_ACL_USER || p_ace->type == SMB_ACL_GROUP) { + needs_mask = True; + mask_perms |= p_ace->perms; + } else if (p_ace->type == SMB_ACL_GROUP_OBJ) { + mask_perms |= p_ace->perms; + } + /* * Get the entry for this ACE. */ @@ -1642,6 +1764,11 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } + if (p_ace->type == SMB_ACL_MASK) { + mask_entry = the_entry; + got_mask_entry = True; + } + /* * Ok - we now know the ACL calls should be working, don't * allow fallback to chmod. @@ -1706,33 +1833,31 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau print_canon_ace( p_ace, i); } - /* - * Add in a mask of rwx. - */ - - if (conn->vfs_ops.sys_acl_create_entry( conn, &the_acl, &mask_entry) == -1) { - DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); - goto done; - } + if (needs_mask && !got_mask_entry) { + if (conn->vfs_ops.sys_acl_create_entry(conn, &the_acl, &mask_entry) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); + goto done; + } - if (conn->vfs_ops.sys_acl_set_tag_type(conn, mask_entry, SMB_ACL_MASK) == -1) { - DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); - goto done; - } + if (conn->vfs_ops.sys_acl_set_tag_type(conn, mask_entry, SMB_ACL_MASK) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); + goto done; + } - if (conn->vfs_ops.sys_acl_get_permset(conn, mask_entry, &mask_permset) == -1) { - DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); - goto done; - } + if (conn->vfs_ops.sys_acl_get_permset(conn, mask_entry, &mask_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); + goto done; + } - if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) { - DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) )); - goto done; - } + if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) )); + goto done; + } - if (conn->vfs_ops.sys_acl_set_permset(conn, mask_entry, mask_permset) == -1) { - DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); - goto done; + if (conn->vfs_ops.sys_acl_set_permset(conn, mask_entry, mask_permset) == -1) { + DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); + goto done; + } } /* @@ -1758,6 +1883,12 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if (errno == ENOSYS) *pacl_set_support = False; + +#ifdef ENOTSUP + if (errno == ENOTSUP) + *pacl_set_support = False; +#endif + DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", fsp->fsp_name, strerror(errno) )); @@ -1771,6 +1902,12 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if (errno == ENOSYS) *pacl_set_support = False; + +#ifdef ENOTSUP + if (errno == ENOTSUP) + *pacl_set_support = False; +#endif + DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); goto done; @@ -1787,6 +1924,39 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau return ret; } +/**************************************************************************** + Find a particular canon_ace entry. +****************************************************************************/ + +static struct canon_ace *canon_ace_entry_for(struct canon_ace *list, SMB_ACL_TAG_T type, posix_id *id) +{ + while (list) { + if (list->type == type && ((type != SMB_ACL_USER && type != SMB_ACL_GROUP) || + (type == SMB_ACL_USER && id && id->uid == list->unix_ug.uid) || + (type == SMB_ACL_GROUP && id && id->gid == list->unix_ug.gid))) + break; + list = list->next; + } + return list; +} + +/**************************************************************************** + +****************************************************************************/ + +SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T acl) +{ + SMB_ACL_ENTRY_T entry; + + if (!acl) + return NULL; + if (conn->vfs_ops.sys_acl_get_entry(conn, acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { + conn->vfs_ops.sys_acl_free_acl(conn, acl); + return NULL; + } + return acl; +} + /**************************************************************************** Convert a canon_ace to a generic 3 element permission - if possible. ****************************************************************************/ @@ -1922,6 +2092,8 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { extern DOM_SID global_sid_Builtin_Administrators; extern DOM_SID global_sid_Builtin_Users; + extern DOM_SID global_sid_Creator_Owner; + extern DOM_SID global_sid_Creator_Group; connection_struct *conn = fsp->conn; SMB_STRUCT_STAT sbuf; SEC_ACE *nt_ace_list = NULL; @@ -1958,8 +2130,10 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * If it's a directory get the default POSIX ACL. */ - if(fsp->is_directory) + if(fsp->is_directory) { dir_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + dir_acl = free_empty_sys_acl(conn, dir_acl); + } } else { @@ -1990,35 +2164,31 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); } + /* + * In the optimum case Creator Owner and Creator Group would be used for + * the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this + * would lead to usability problems under Windows: The Creator entries + * are only available in browse lists of directories and not for files; + * additionally the identity of the owning group couldn't be determined. + * We therefore use those identities only for Default ACLs. + */ + /* Create the canon_ace lists. */ - file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid); - num_acls = count_canon_ace_list(file_ace); + file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, SMB_ACL_TYPE_ACCESS ); /* We must have *some* ACLS. */ - if (num_acls == 0) { + if (count_canon_ace_list(file_ace) == 0) { DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); return 0; } - if (fsp->is_directory) { - /* - * If we have to fake a default ACL then this is the mode to use. - */ - sbuf.st_mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - - dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, &owner_sid, &group_sid); - num_dir_acls = count_canon_ace_list(dir_ace); - } - - /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); - goto done; + if (fsp->is_directory && dir_acl) { + dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, + &global_sid_Creator_Owner, + &global_sid_Creator_Group, SMB_ACL_TYPE_DEFAULT ); } - memset(nt_ace_list, '\0', (num_acls + num_profile_acls + num_dir_acls) * sizeof(SEC_ACE) ); - /* * Create the NT ACE list from the canonical ace lists. */ @@ -2028,16 +2198,112 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) int nt_acl_type; int i; + if (nt4_compatible_acls()) { + /* + * NT 4 chokes if an ACL contains an INHERIT_ONLY entry + * but no non-INHERIT_ONLY entry for one SID. So we only + * remove entries from the Access ACL if the + * corresponding Default ACL entries have also been + * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP + * are exceptions. We can do nothing + * intelligent if the Default ACL contains entries that + * are not also contained in the Access ACL, so this + * case will still fail under NT 4. + */ + + if (!dir_ace) + goto simplify_file_ace_only; + + ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + + ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } + } + + /* + * WinNT doesn't usually have Creator Group + * in browse lists, so we send this entry to + * WinNT even if it contains no relevant + * permissions. Once we can add + * Creator Group to browse lists we can + * re-enable this. + */ + +#if 0 + ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + } +#endif + + ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } + } else { + + ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + } + ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + } + + simplify_file_ace_only: + + ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } + + ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } + } + + num_acls = count_canon_ace_list(file_ace); + num_dir_acls = count_canon_ace_list(dir_ace); + + /* Allocate the ace list. */ + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); + goto done; + } + + memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + + /* + * Create the NT ACE list from the canonical ace lists. + */ + ace = file_ace; for (i = 0; i < num_acls; i++, ace = ace->next) { - SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + SEC_ACCESS acc; + + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0); } /* The User must have access to a profile share - even if we can't map the SID. */ if (lp_profile_acls(SNUM(fsp->conn))) { SEC_ACCESS acc; + init_sec_access(&acc,FILE_GENERIC_ALL); init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, 0); } @@ -2045,14 +2311,17 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) ace = dir_ace; for (i = 0; i < num_dir_acls; i++, ace = ace->next) { - SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, + SEC_ACCESS acc; + + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); } /* The User must have access to a profile share - even if we can't map the SID. */ if (lp_profile_acls(SNUM(fsp->conn))) { SEC_ACCESS acc; + init_sec_access(&acc,FILE_GENERIC_ALL); init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| @@ -2087,11 +2356,22 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) if(!*ppdesc) { DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); sd_size = 0; + } else { + /* + * Windows 2000: The DACL_PROTECTED flag in the security + * descriptor marks the ACL as non-inheriting, i.e., no + * ACEs from higher level directories propagate to this + * ACL. In the POSIX ACL model permissions are only + * inherited at file create time, so ACLs never contain + * any ACEs that are inherited dynamically. The DACL_PROTECTED + * flag doesn't seem to bother Windows NT. + */ + (*ppdesc)->type |= SE_DESC_DACL_PROTECTED; } - done: + done: - if (posix_acl) + if (posix_acl) conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); if (dir_acl) conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); @@ -2379,6 +2659,12 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP); break; case SMB_ACL_MASK: + /* + * FIXME: The ACL_MASK entry permissions should really be set to + * the union of the permissions of all ACL_USER, + * ACL_GROUP_OBJ, and ACL_GROUP entries. That's what + * acl_calc_mask() does, but Samba ACLs doesn't provide it. + */ perms = S_IRUSR|S_IWUSR|S_IXUSR; break; case SMB_ACL_OTHER: @@ -2407,30 +2693,57 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo } /**************************************************************************** - Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL - and set the mask to rwx. Needed to preserve complex ACLs set by NT. - Note that name is in UNIX character set. + Get the access ACL of FROM, do a chmod by setting the ACL USER_OBJ, + GROUP_OBJ and OTHER bits in an ACL and set the mask to rwx. Set the + resulting ACL on TO. Note that name is in UNIX character set. ****************************************************************************/ -int chmod_acl(connection_struct *conn, const char *name, mode_t mode) +static int copy_access_acl(connection_struct *conn, const char *from, const char *to, mode_t mode) { SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = conn->vfs_ops.sys_acl_get_file(conn, name, SMB_ACL_TYPE_ACCESS)) == NULL) + if ((posix_acl = conn->vfs_ops.sys_acl_get_file(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = conn->vfs_ops.sys_acl_set_file(conn, name, SMB_ACL_TYPE_ACCESS, posix_acl); + ret = conn->vfs_ops.sys_acl_set_file(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl); - done: + done: conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); return ret; } +/**************************************************************************** + Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL + and set the mask to rwx. Needed to preserve complex ACLs set by NT. + Note that name is in UNIX character set. +****************************************************************************/ + +int chmod_acl(connection_struct *conn, const char *name, mode_t mode) +{ + return copy_access_acl(conn, name, name, mode); +} + +/**************************************************************************** + If "inherit permissions" is set and the parent directory has no default + ACL but it does have an Access ACL, inherit this Access ACL to file name. +****************************************************************************/ + +int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode) +{ + pstring dirname; + pstrcpy(dirname, parent_dirname(name)); + + if (!lp_inherit_perms(SNUM(conn)) || directory_has_default_acl(conn, dirname)) + return 0; + + return copy_access_acl(conn, dirname, name, mode); +} + /**************************************************************************** Do an fchmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL and set the mask to rwx. Needed to preserve complex ACLs set by NT. diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index de65cda2d0..8b9728d513 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2622,6 +2622,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); + inherit_access_acl(conn, fname, unixmode); + SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 2bda26aa51..9a38d6e9e2 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -456,7 +456,7 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N if (strequal(global_myname, domain)) { local_lookup = True; } else if (lp_server_role() == ROLE_DOMAIN_PDC || - lp_server_role() == ROLE_DOMAIN_PDC) { + lp_server_role() == ROLE_DOMAIN_BDC) { if (strequal(domain, global_myworkgroup)) { local_lookup = True; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a0a7b920b8..f6dad7b6e7 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -319,6 +319,9 @@ int vfs_mkdir(connection_struct *conn, const char *name, mode_t mode) SMB_STRUCT_STAT sbuf; if(!(ret=conn->vfs_ops.mkdir(conn,name,mode))) { + + inherit_access_acl(conn, name, mode); + /* * Check if high bits should have been set, * then (if bits are missing): add them. -- cgit From 0fff69f974ac8add92da2ee3e0e08084c09e6e9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Oct 2002 22:04:14 +0000 Subject: Fix fd leak with kernel change notify. Jeremy. (This used to be commit a2043390734b38cab8fe2f013960272c0e202b99) --- source3/smbd/notify_kernel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 8454917163..df553721ef 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -127,7 +127,6 @@ static void kernel_remove_notify(void *datap) BlockSignals(True, RT_SIGNAL_NOTIFY); for (i = 0; i < signals_received; i++) { if (fd == (int)fd_pending_array[i]) { - close(fd); fd_pending_array[i] = (SIG_ATOMIC_T)-1; if (signals_received - i - 1) { memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], @@ -138,6 +137,7 @@ static void kernel_remove_notify(void *datap) break; } } + close(fd); BlockSignals(False, RT_SIGNAL_NOTIFY); } SAFE_FREE(data); -- cgit From a63844e10e3e498c1c1e8457d50eb6ab1e6510cf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Oct 2002 23:41:00 +0000 Subject: Fix slowdown because of enumerating all print queues on every smbd startup. Jeremy. (This used to be commit 6efd17ef78ebcfed1130312fa019d674e4663a00) --- source3/smbd/server.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 39d5e3bcd3..ad00794bd7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -370,7 +370,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) reset_globals_after_fork(); /* tdb needs special fork handling */ - tdb_reopen_all(); + if (tdb_reopen_all() == -1) { + DEBUG(0,("tdb_reopen_all failed.\n")); + return False; + } return True; } @@ -859,6 +862,9 @@ static void usage(char *pname) register_msg_pool_usage(); register_dmalloc_msgs(); + if (!print_backend_init()) + exit(1); + /* Setup the main smbd so that we can get messages. */ claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); @@ -881,9 +887,6 @@ static void usage(char *pname) if (!locking_init(0)) exit(1); - if (!print_backend_init()) - exit(1); - if (!share_info_db_init()) exit(1); -- cgit From 56dc17378b978f02f8397071021be5bf9a88b6a4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Nov 2002 22:17:19 +0000 Subject: Merges from HEAD: - off-by-one fix - fixes warnings about insufficent space in buffer. - fix a memleak in uid.c - we forgot to free() the allocated struct. (This used to be commit b8951a6551b352e4aac7e8b0ecf7fec3f2d9634e) --- source3/smbd/lanman.c | 2 +- source3/smbd/uid.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0db1af6032..d8c1cc6f60 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -72,7 +72,7 @@ static int CopyExpanded(connection_struct *conn, StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub_conn(conn,buf,sizeof(buf)); - l = push_ascii(*dst,buf,*n-1, STR_TERMINATE); + l = push_ascii(*dst,buf,*n, STR_TERMINATE); (*dst) += l; (*n) -= l; return l; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 9a38d6e9e2..48b9768358 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -49,6 +49,8 @@ BOOL change_to_guest(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; + passwd_free(&pass); + return True; } -- cgit From 6d7195d1d79c43f5ccc8dc4a9215c02177d5fa89 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 2 Nov 2002 03:47:48 +0000 Subject: Merge passdb from HEAD -> 3.0 The work here includes: - metze' set/changed patch, which avoids making changes to ldap on unmodified attributes. - volker's group mapping in passdb patch - volker's samsync stuff - volkers SAMR changes. - mezte's connection caching patch - my recent changes (fix magic root check, ldap ssl) Andrew Bartlett (This used to be commit 2044d60bbe0043cdbb9aba931115672bde975d2f) --- source3/smbd/chgpasswd.c | 4 ++-- source3/smbd/lanman.c | 2 +- source3/smbd/password.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 9e593b022e..a5274862fc 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -707,11 +707,11 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, D_P16(pwd, pass2, unenc_new_pw); } - if (!pdb_set_lanman_passwd(sampass, unenc_new_pw)) { + if (!pdb_set_lanman_passwd(sampass, unenc_new_pw, PDB_CHANGED)) { return False; } - if (!pdb_set_nt_passwd (sampass, NULL)) { + if (!pdb_set_nt_passwd (sampass, NULL, PDB_CHANGED)) { return False; /* We lose the NT hash. Sorry. */ } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d8c1cc6f60..7ab1be9dd9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1651,7 +1651,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c return False; /* get list of domain groups SID_DOMAIN_GRP=2 */ - if(!enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) { + if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) { DEBUG(3,("api_RNetGroupEnum:failed to get group list")); return False; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f2956237dd..1e87065e31 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -134,7 +134,7 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) * the new real sam db won't have reference to unix uids or gids */ if (!IS_SAM_UNIX_USER(server_info->sam_account)) { - DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT (flags:%x)\n", pdb_get_init_flag(server_info->sam_account))); + DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); free(vuser); return UID_FIELD_INVALID; } -- cgit From b51160452eb992fd15bf45b9616a56bae9d16e37 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Nov 2002 21:47:03 +0000 Subject: Fix to correctly return NT_STATUS_DELETE_PENDING. Jeremy. (This used to be commit 4ec381d64249203e0924b86600fe8e67ada1cb5b) --- source3/smbd/error.c | 3 +++ source3/smbd/open.c | 1 + 2 files changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 2f993fb41e..9d0e34bf52 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -23,6 +23,7 @@ /* these can be set by some functions to override the error codes */ int unix_ERR_class=SMB_SUCCESS; int unix_ERR_code=0; +NTSTATUS unix_ERR_ntstatus = NT_STATUS_OK; /* From lib/error.c */ extern struct unix_error_map unix_dos_nt_errmap[]; @@ -59,8 +60,10 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, if (unix_ERR_class != SMB_SUCCESS) { eclass = unix_ERR_class; ecode = unix_ERR_code; + ntstatus = unix_ERR_ntstatus; unix_ERR_class = SMB_SUCCESS; unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; } else { while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 417a9dd039..94a705e6b6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -401,6 +401,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRnoaccess; + unix_ERR_ntstatus = NT_STATUS_DELETE_PENDING; return False; } -- cgit From 66b62281e285ae53c63e43ff074f57053b3e91ae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Nov 2002 22:49:07 +0000 Subject: Ensure can_delete returns the correct error code. Jeremy. (This used to be commit 52af4ed9ecd8ef5f31ce00c94bc55d6013a7f65a) --- source3/smbd/reply.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a881e135c0..3371d9b544 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1278,10 +1278,13 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if (!fsp) { NTSTATUS ret = NT_STATUS_ACCESS_DENIED; - if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) + if (!NT_STATUS_IS_OK(unix_ERR_ntstatus)) + ret = unix_ERR_ntstatus; + else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) ret = NT_STATUS_SHARING_VIOLATION; unix_ERR_class = 0; unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; return ret; } close_file(fsp,False); -- cgit From ab1cf8d1cf447e85063b43b65fa05c8b4bfde2a9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 6 Nov 2002 05:14:15 +0000 Subject: Merge of get_dc_list() api change from HEAD. (This used to be commit 6ba7847ce2756fde94e530fd0bf2a055f3e27373) --- source3/smbd/change_trust_pw.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 5da735e875..7cb9084072 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -105,12 +105,11 @@ account password for domain %s.\n", domain)); * We have been asked to dynamcially determine the IP addresses of the PDC. */ - struct in_addr *ip_list = NULL; - int count = 0; - int i; + struct in_addr pdc_ip; + fstring dc_name; /* Use the PDC *only* for this. */ - if(!get_dc_list(True, domain, &ip_list, &count)) + if(!get_pdc_ip(domain, &pdc_ip)) continue; /* @@ -118,16 +117,11 @@ account password for domain %s.\n", domain)); * address used as a string. */ - for(i = 0; i < count; i++) { - fstring dc_name; - if(!lookup_dc_name(global_myname, domain, &ip_list[i], dc_name)) + if(!lookup_dc_name(global_myname, domain, &pdc_ip, dc_name)) continue; if(NT_STATUS_IS_OK(res = modify_trust_password( domain, dc_name, old_trust_passwd_hash))) break; - } - - SAFE_FREE(ip_list); } else { res = modify_trust_password( domain, remote_machine, -- cgit From 1486559181b6c0dd2a02bf05115d5903e2489367 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 7 Nov 2002 14:46:24 +0000 Subject: Stop using hardcoded smbtrans subcommands (This used to be commit 117077b172acbdf0e059feb0d598e99cec481291) --- source3/smbd/ipc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 91b221968f..7fe02dbccf 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -293,17 +293,17 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply)); switch (subcommand) { - case 0x26: + case TRANSACT_DCERPCCMD: /* dce/rpc command */ reply = write_to_pipe(p, data, tdscnt); if (reply) reply = api_rpc_trans_reply(outbuf, p); break; - case 0x53: + case TRANSACT_WAITNAMEDPIPEHANDLESTATE: /* Wait Named Pipe Handle state */ reply = api_WNPHS(outbuf, p, params, tpscnt); break; - case 0x01: + case TRANSACT_SETNAMEDPIPEHANDLESTATE: /* Set Named Pipe Handle state */ reply = api_SNPHS(outbuf, p, params, tpscnt); break; -- cgit From f09109c7bc32966bb464df0712583b30602d6ad0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 9 Nov 2002 17:08:58 +0000 Subject: Last sync with HEAD (This used to be commit 1175b62337f5c29954cd5e8dfdc2327c9c80748c) --- source3/smbd/server.c | 132 +++++++++++--------------------------------------- 1 file changed, 27 insertions(+), 105 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ad00794bd7..3d9a4675b2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3,6 +3,7 @@ Main SMB server routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 + Copyright (C) Jelmer Vernooij 2002 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 @@ -611,121 +612,49 @@ static void init_structs(void ) } -/**************************************************************************** - Usage on the program. -****************************************************************************/ - -static void usage(char *pname) -{ - - d_printf("Usage: %s [-DaioPh?Vb] [-d debuglevel] [-l log basename] [-p port]\n", pname); - d_printf(" [-O socket options] [-s services file]\n"); - d_printf("\t-D Become a daemon (default)\n"); - d_printf("\t-a Append to log file (default)\n"); - d_printf("\t-i Run interactive (not a daemon)\n" ); - d_printf("\t-o Overwrite log file, don't append\n"); - d_printf("\t-h Print usage\n"); - d_printf("\t-? Print usage\n"); - d_printf("\t-V Print version\n"); - d_printf("\t-b Print build options\n"); - d_printf("\t-d debuglevel Set the debuglevel\n"); - d_printf("\t-l log basename. Basename for log/debug files\n"); - d_printf("\t-p port Listen on the specified port\n"); - d_printf("\t-O socket options Socket options\n"); - d_printf("\t-s services file. Filename of services file\n"); - d_printf("\n"); -} - /**************************************************************************** main program. ****************************************************************************/ - int main(int argc,char *argv[]) + int main(int argc,const char *argv[]) { - extern BOOL append_log; - extern BOOL AllowDebugChange; - extern char *optarg; /* shall I run as a daemon */ - BOOL is_daemon = False; - BOOL interactive = False; - BOOL specified_logfile = False; - char *ports = NULL; + static BOOL is_daemon = False; + static BOOL interactive = False; + static char *ports = NULL; int opt; - pstring logfile; + poptContext pc; + + struct poptOption long_options[] = { + POPT_AUTOHELP + {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, + {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, + {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, + {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, + {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug}, + {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile}, + {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_socket_options}, + {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_log_base}, + {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version}, + { NULL } + }; #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif - /* this is for people who can't start the program correctly */ - while (argc > 1 && (*argv[1] != '-')) { - argv++; - argc--; - } - - while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?bVaiof:")) ) + pc = poptGetContext("smbd", argc, argv, long_options, 0); + + while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { - case 'O': - pstrcpy(user_socket_options,optarg); - break; - - case 's': - pstrcpy(dyn_CONFIGFILE,optarg); - break; - - case 'l': - specified_logfile = True; - pstr_sprintf(logfile, "%s/log.smbd", optarg); - lp_set_logfile(logfile); - break; - - case 'a': - append_log = True; - break; - - case 'i': - interactive = True; - break; - - case 'o': - append_log = False; - break; - - case 'D': - is_daemon = True; - break; - - case 'd': - if (*optarg == 'A') - DEBUGLEVEL = 10000; - else - DEBUGLEVEL = atoi(optarg); - AllowDebugChange = False; - break; - - case 'p': - ports = optarg; - break; - - case 'h': - case '?': - usage(argv[0]); - exit(0); - break; - - case 'V': - d_printf("Version %s\n",VERSION); - exit(0); - break; case 'b': - build_options(True); /* Display output to screen as well as debug */ + build_options(True); /* Display output to screen as well as debug */ exit(0); break; - default: - DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); - usage(argv[0]); - exit(1); } + } + + poptFreeContext(pc); #ifdef HAVE_SETLUID /* needed for SecureWare on SCO */ @@ -736,13 +665,6 @@ static void usage(char *pname) load_case_tables(); - append_log = True; - - if(!specified_logfile) { - pstr_sprintf(logfile, "%s/log.smbd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - } - set_remote_machine_name("smbd"); setup_logging(argv[0],interactive); -- cgit From 2f194322d419350f35a48dff750066894d68eccf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Nov 2002 23:20:50 +0000 Subject: Removed global_myworkgroup, global_myname, global_myscope. Added liberal dashes of const. This is a rather large check-in, some things may break. It does compile though :-). Jeremy. (This used to be commit f755711df8f74f9b8e8c1a2b0d07d02a931eeb89) --- source3/smbd/change_trust_pw.c | 10 ++++------ source3/smbd/chgpasswd.c | 2 +- source3/smbd/lanman.c | 18 ++++++++---------- source3/smbd/negprot.c | 6 ++---- source3/smbd/password.c | 12 +++++++----- source3/smbd/process.c | 18 ++++++++---------- source3/smbd/reply.c | 3 +-- source3/smbd/server.c | 23 ++++++----------------- source3/smbd/service.c | 4 ++-- source3/smbd/sesssetup.c | 5 ++--- source3/smbd/trans2.c | 3 +-- source3/smbd/uid.c | 6 ++---- 12 files changed, 44 insertions(+), 66 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 7cb9084072..e4a7fbae6b 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -24,13 +24,11 @@ #include "includes.h" -extern pstring global_myname; - /********************************************************* Change the domain password on the PDC. **********************************************************/ -static NTSTATUS modify_trust_password( char *domain, char *remote_machine, +static NTSTATUS modify_trust_password( const char *domain, const char *remote_machine, unsigned char orig_trust_passwd_hash[16]) { struct cli_state *cli; @@ -46,7 +44,7 @@ static NTSTATUS modify_trust_password( char *domain, char *remote_machine, return NT_STATUS_UNSUCCESSFUL; } - if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname, remote_machine, + if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine, NULL, 0, "IPC$", "IPC", "", "", @@ -82,7 +80,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli))); Change the trust account password for a domain. ************************************************************************/ -NTSTATUS change_trust_account_password( char *domain, char *remote_machine_list) +NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine_list) { fstring remote_machine; unsigned char old_trust_passwd_hash[16]; @@ -117,7 +115,7 @@ account password for domain %s.\n", domain)); * address used as a string. */ - if(!lookup_dc_name(global_myname, domain, &pdc_ip, dc_name)) + if(!lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name)) continue; if(NT_STATUS_IS_OK(res = modify_trust_password( domain, dc_name, old_trust_passwd_hash))) diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a5274862fc..c2a82d1eb6 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -290,7 +290,7 @@ static void pwd_sub(char *buf) all_string_sub(buf, "\\t", "\t", 0); } -static int talktochild(int master, char *seq) +static int talktochild(int master, const char *seq) { int count = 0; fstring issue, expected; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7ab1be9dd9..6a031dde6f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -33,8 +33,6 @@ #define CHECK_TYPES 0 extern fstring local_machine; -extern pstring global_myname; -extern fstring global_myworkgroup; #define NERR_Success 0 #define NERR_badpass 86 @@ -960,7 +958,7 @@ struct srv_info_struct ******************************************************************/ static int get_server_info(uint32 servertype, struct srv_info_struct **servers, - char *domain) + const char *domain) { int count=0; int alloced=0; @@ -985,7 +983,7 @@ static int get_server_info(uint32 servertype, for (i=0;lines[i];i++) { fstring stype; struct srv_info_struct *s; - char *ptr = lines[i]; + const char *ptr = lines[i]; BOOL ok = True; if (!*ptr) continue; @@ -1010,7 +1008,7 @@ static int get_server_info(uint32 servertype, if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue; if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) { /* this allows us to cope with an old nmbd */ - pstrcpy(s->domain,global_myworkgroup); + pstrcpy(s->domain,lp_workgroup()); } if (sscanf(stype,"%X",&s->type) != 1) { @@ -1206,7 +1204,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param if (strcmp(str1, "WrLehDz") == 0) { pull_ascii_fstring(domain, p); } else { - fstrcpy(domain, global_myworkgroup); + fstrcpy(domain, lp_workgroup()); } if (lp_browse_list()) @@ -2311,7 +2309,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); - if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;ilogon_script ? vuser->logon_script :""); /* script path */ diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 06a55cb33e..b91c0c0866 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -22,7 +22,6 @@ extern int Protocol; extern int max_recv; -extern fstring global_myworkgroup; BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; struct auth_context *negprot_global_auth_context = NULL; @@ -168,7 +167,6 @@ static int reply_lanman2(char *inbuf, char *outbuf) static int negprot_spnego(char *p) { DATA_BLOB blob; - extern pstring global_myname; uint8 guid[16]; const char *OIDs_krb5[] = {OID_KERBEROS5, OID_KERBEROS5_OLD, @@ -181,7 +179,7 @@ static int negprot_spnego(char *p) global_spnego_negotiated = True; memset(guid, 0, 16); - safe_strcpy((char *)guid, global_myname, 16); + safe_strcpy((char *)guid, global_myname(), 16); strlower((char *)guid); #if 0 @@ -292,7 +290,7 @@ static int reply_nt1(char *inbuf, char *outbuf) SSVALS(outbuf,smb_vwv16+1,8); p += 8; } - p += srvstr_push(outbuf, p, global_myworkgroup, -1, + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); } else { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1e87065e31..4ce99e96bb 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -257,23 +257,25 @@ BOOL user_ok(const char *user,int snum) if (lp_invalid_users(snum)) { str_list_copy(&invalid, lp_invalid_users(snum)); if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { - ret = !user_in_list(user, invalid); + ret = !user_in_list(user, (const char **)invalid); } } - if (invalid) str_list_free (&invalid); + if (invalid) + str_list_free (&invalid); if (ret && lp_valid_users(snum)) { str_list_copy(&valid, lp_valid_users(snum)); if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) { - ret = user_in_list(user,valid); + ret = user_in_list(user, (const char **)valid); } } - if (valid) str_list_free (&valid); + if (valid) + str_list_free (&valid); if (ret && lp_onlyuser(snum)) { char **user_list = str_list_make (lp_username(snum), NULL); if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) { - ret = user_in_list(user, user_list); + ret = user_in_list(user, (const char **)user_list); } if (user_list) str_list_free (&user_list); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0f7cfd0e9c..c46c4c5509 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -45,8 +45,6 @@ extern int smb_read_error; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; extern BOOL global_machine_password_needs_changing; -extern fstring global_myworkgroup; -extern pstring global_myname; extern int max_send; /**************************************************************************** @@ -1154,16 +1152,16 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t * First, open the machine password file with an exclusive lock. */ - if (secrets_lock_trust_account_password(global_myworkgroup, True) == False) { + if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { DEBUG(0,("process: unable to lock the machine account password for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); +machine %s in domain %s.\n", global_myname(), lp_workgroup() )); return True; } - if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) { + if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct)) { DEBUG(0,("process: unable to read the machine account password for \ -machine %s in domain %s.\n", global_myname, global_myworkgroup )); - secrets_lock_trust_account_password(global_myworkgroup, False); +machine %s in domain %s.\n", global_myname(), lp_workgroup() )); + secrets_lock_trust_account_password(lp_workgroup(), False); return True; } @@ -1173,15 +1171,15 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); if(t < lct + lp_machine_password_timeout()) { global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(global_myworkgroup, False); + secrets_lock_trust_account_password(lp_workgroup(), False); return True; } pstrcpy(remote_machine_list, lp_passwordserver()); - change_trust_account_password( global_myworkgroup, remote_machine_list); + change_trust_account_password( lp_workgroup(), remote_machine_list); global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(global_myworkgroup, False); + secrets_lock_trust_account_password(lp_workgroup(), False); } /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3371d9b544..2c29ffdf51 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -33,7 +33,6 @@ extern char magic_char; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -extern pstring global_myname; extern int global_oplock_break; unsigned int smb_echo_count = 0; @@ -356,7 +355,7 @@ int reply_ioctl(connection_struct *conn, { uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); SSVAL(p,0,rap_jobid); /* Job number */ - srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII); + srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII); srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); break; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3d9a4675b2..342c7c85cf 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,9 +22,6 @@ #include "includes.h" -extern fstring global_myworkgroup; -extern pstring global_myname; - int am_parent = 1; /* the last message the was processed */ @@ -200,7 +197,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) for(i = 0; i < num_interfaces; i++) { struct in_addr *ifip = iface_n_ip(i); fstring tok; - char *ptr; + const char *ptr; if(ifip == NULL) { DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); @@ -237,7 +234,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) from anywhere. */ fstring tok; - char *ptr; + const char *ptr; num_interfaces = 1; @@ -582,22 +579,15 @@ void exit_server(char *reason) Initialise connect, service and file structs. ****************************************************************************/ -static void init_structs(void ) +static BOOL init_structs(void ) { /* * Set the machine NETBIOS name if not already * set from the config file. */ - if (!*global_myname) { - char *p; - pstrcpy( global_myname, myhostname() ); - p = strchr_m(global_myname, '.' ); - if (p) - *p = 0; - } - - strupper(global_myname); + if (!init_names()) + return False; conn_init(); @@ -610,6 +600,7 @@ static void init_structs(void ) secrets_init(); + return True; } /**************************************************************************** @@ -740,8 +731,6 @@ static void init_structs(void ) } #endif - fstrcpy(global_myworkgroup, lp_workgroup()); - DEBUG(3,( "loaded services\n")); if (!is_daemon && !is_a_socket(0)) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a8a590da80..16e0ad4160 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -271,7 +271,7 @@ static void set_read_only(connection_struct *conn) if (!str_list_substitute(list, "%S", service)) { DEBUG(0, ("ERROR: read list substitution failed\n")); } - if (user_in_list(conn->user, list)) + if (user_in_list(conn->user, (const char **)list)) conn->read_only = True; str_list_free(&list); } @@ -281,7 +281,7 @@ static void set_read_only(connection_struct *conn) if (!str_list_substitute(list, "%S", service)) { DEBUG(0, ("ERROR: write list substitution failed\n")); } - if (user_in_list(conn->user, list)) + if (user_in_list(conn->user, (const char **)list)) conn->read_only = False; str_list_free(&list); } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b9af720008..4ab1063217 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -247,7 +247,6 @@ static int reply_spnego_negotiate(connection_struct *conn, const uint8 *cryptkey; BOOL got_kerberos = False; NTSTATUS nt_status; - extern pstring global_myname; char *cliname=NULL, *domname=NULL; /* parse out the OIDs and the first sec blob */ @@ -325,14 +324,14 @@ static int reply_spnego_negotiate(connection_struct *conn, fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():""); strlower(dnsdomname); - fstrcpy(dnsname, global_myname); + fstrcpy(dnsname, global_myname()); fstrcat(dnsname, "."); fstrcat(dnsname, dnsdomname); strlower(dnsname); msrpc_gen(&struct_blob, "aaaaa", 2, lp_workgroup(), - 1, global_myname, + 1, global_myname(), 4, dnsdomname, 3, dnsname, 0, ""); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8b9728d513..a2627021d9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -28,7 +28,6 @@ extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; extern uint32 global_client_caps; -extern pstring global_myname; #define get_file_size(sbuf) (sbuf.st_size) @@ -3021,7 +3020,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */ SSVAL(pdata,0,rap_jobid); /* Job number */ - srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ + srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); return(-1); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 48b9768358..e2cc26e0ae 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -445,8 +445,6 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { - extern pstring global_myname; - extern fstring global_myworkgroup; fstring sid; BOOL local_lookup = False; @@ -455,11 +453,11 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N /* If we are looking up a domain user, make sure it is for the local machine only */ - if (strequal(global_myname, domain)) { + if (strequal(global_myname(), domain)) { local_lookup = True; } else if (lp_server_role() == ROLE_DOMAIN_PDC || lp_server_role() == ROLE_DOMAIN_BDC) { - if (strequal(domain, global_myworkgroup)) { + if (strequal(domain, lp_workgroup())) { local_lookup = True; } } -- cgit From 7cfe3919f3703eb5aad838b34ceba472865cf081 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 13 Nov 2002 21:54:31 +0000 Subject: small patch to makesure we fallback to if doesn't exist (e.g. in SuSE 8.1) (by Metze) (This used to be commit da8794afe8ca8f454937f06d1c43cc5d844b6037) --- source3/smbd/quotas.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 39cb8f2432..90fd4bbdac 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -56,6 +56,11 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B #include #ifdef HAVE_LINUX_XQM_H #include +#else +#ifdef HAVE_XFS_XQM_H +#include +#define HAVE_LINUX_XQM_H +#endif #endif #include -- cgit From c64d762997c80bd9ad2d47d1799cf9ec870d455a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 15 Nov 2002 21:43:57 +0000 Subject: Updates from HEAD: - const for PACKS() in lanman.c - change auth to 'account before password' - add help to net rpc {vampire,samsync} - configure updates for sun workshop cc - become_root() around pdb_ calls in auth_util for guest login. Andrew Bartlett (This used to be commit 43e90eb6e331d478013a9c038292f245edc51bd0) --- source3/smbd/lanman.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 6a031dde6f..43b5d9e55f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -218,7 +218,7 @@ static int package(struct pack_desc* p, ...) { va_list args; int needed=0, stringneeded; - char* str=NULL; + const char* str=NULL; int is_string=0, stringused; int32 temp; @@ -334,7 +334,7 @@ static void PACKI(struct pack_desc* desc,char *t,int v) PACK(desc,t,v); } -static void PACKS(struct pack_desc* desc,char *t,char *v) +static void PACKS(struct pack_desc* desc,const char *t,const char *v) { PACK(desc,t,v); } -- cgit From ae94f2eaa5bf01e0f4b40883b0782ae3fa1086d9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Nov 2002 06:12:47 +0000 Subject: Samba janitor... Merging tridge's change to 3.0. Original commit message : the change in the way %U is handled to use current_user has broken some basic usages like 'include = smb.conf.%U' This changes fixes things again, by checking for reload after we setup current_user in tconx. (This used to be commit 64b2243ccd984e0d69d8bb7421d43f1f1f84b017) --- source3/smbd/service.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 16e0ad4160..fe55345938 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -611,6 +611,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *status = NT_STATUS_LOGON_FAILURE; return NULL; } + + /* the %U substitution may have changed */ + reload_services(True); /* Remember that a different vuid can connect later without these checks... */ -- cgit From faf1f0df4d8f047fb2dcbd27305c61a1e70a8db3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Nov 2002 01:46:10 +0000 Subject: Very curious. It turns out attribute matching on truncate only matters when opening truncate with current SYSTEM|HIDDEN -> NONE. It's fine to truncate on open with current NONE -> SYSTEM | HIDDEN. Jeremy. (This used to be commit 3bf21ca936973efcd74b826bc750131c6ab2c701) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 94a705e6b6..cee2b37184 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -712,11 +712,11 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex /* If we're mapping SYSTEM and HIDDEN ensure they match. */ if (lp_map_system(SNUM(conn))) { - if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) != (new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) + if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) return False; } if (lp_map_hidden(SNUM(conn))) { - if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) != (new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) + if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; } return True; -- cgit From 91b7ac9fb955124263d0e86801db972590dabfb9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Nov 2002 00:53:24 +0000 Subject: merged the %U changes to 3.0 (This used to be commit 58fa6bfee8ba35cc182c18c980e0a4040ddd7d09) --- source3/smbd/service.c | 3 --- source3/smbd/sesssetup.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index fe55345938..1f168dd3ff 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -612,9 +612,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - /* the %U substitution may have changed */ - reload_services(True); - /* Remember that a different vuid can connect later without these checks... */ /* Preexecs are done here as they might make the dir we are to ChDir to below */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 4ab1063217..9d708bd5a0 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -159,6 +159,11 @@ static int reply_spnego_kerberos(connection_struct *conn, } ads_destroy(&ads); + /* setup the string used by %U */ + sub_set_smb_name(user); + + reload_services(True); + /* the password is good - let them in */ pw = Get_Pwnam(user); if (!pw && !strstr(user, lp_winbind_separator())) { @@ -423,6 +428,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, set_remote_machine_name(machine); + /* setup the string used by %U */ + sub_set_smb_name(user); + reload_services(True); #if 0 @@ -749,6 +757,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } pstrcpy(sub_user, user); + + /* setup the string used by %U */ + sub_set_smb_name(user); } else { pstrcpy(sub_user, lp_guestaccount()); } -- cgit From f3e3a56ea9085b186af24b0b4e911863fd9ceacc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 29 Nov 2002 02:58:59 +0000 Subject: Merge a bunch of trivial changes from HEAD. The difference remaining should actual functional differences between HEAD and 3.0. - Mostly reformatting - Removal of unecessary #include "smb.h" - Merge of dyn_DRIVERFILE removal - Silly bug fix for python code (This used to be commit d3998307adc50ba50defe610cb656c73799ae3b9) --- source3/smbd/build_options.c | 1 - source3/smbd/change_trust_pw.c | 1 - 2 files changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index f52c53dda5..8129f22898 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -188,7 +188,6 @@ void build_options(BOOL screen) output(screen," SBINDIR: %s\n", dyn_SBINDIR); output(screen," BINDIR: %s\n", dyn_BINDIR); output(screen," LOCKDIR: %s\n",dyn_LOCKDIR); - output(screen," DRIVERFILE: %s\n", dyn_DRIVERFILE); output(screen," LOGFILEBASE: %s\n", dyn_LOGFILEBASE); /*Output various other options (most map to defines in the configure script*/ diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index e4a7fbae6b..28a004eba8 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -120,7 +120,6 @@ account password for domain %s.\n", domain)); if(NT_STATUS_IS_OK(res = modify_trust_password( domain, dc_name, old_trust_passwd_hash))) break; - } else { res = modify_trust_password( domain, remote_machine, old_trust_passwd_hash); -- cgit From 6a019636b980857cf896f250841de757644ba9dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Dec 2002 08:02:41 +0000 Subject: Fixed nasty bug where file writes with start offsets in the range 0x80000000 -> 0xFFFFFFFF would fail as they were being cast from IVAL (uint32) to SMB_OFF_T (off_t or off64_t, both *signed* types). The sign extension would cause the offset to be treated as negative. Thanks to Herb for helping me track this one down (IRIX is good for large file tests :-). Jeremy. PS. That horrid EXEXIST thing has broken configure..... (This used to be commit 2d14c442bc601a277458b69f05a763aa2a1ab3b7) --- source3/smbd/blocking.c | 16 ++++++++-------- source3/smbd/nttrans.c | 4 ++-- source3/smbd/reply.c | 27 ++++++++++++++------------- 3 files changed, 24 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 9d411711cb..14239272c2 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -267,20 +267,20 @@ static BOOL process_lockread(blocking_lock_record *blr) ssize_t nread = -1; char *data, *p; int outsize = 0; - SMB_OFF_T startpos; + SMB_BIG_UINT startpos; size_t numtoread; NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, - (SMB_BIG_UINT)startpos, READ_LOCK); + startpos, READ_LOCK); if (NT_STATUS_V(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { @@ -337,17 +337,17 @@ static BOOL process_lock(blocking_lock_record *blr) char *outbuf = OutBuffer; char *inbuf = blr->inbuf; int outsize; - SMB_OFF_T count = 0, offset = 0; + SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); + count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); + offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); errno = 0; - status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, - (SMB_BIG_UINT)offset, WRITE_LOCK); + status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, + offset, WRITE_LOCK); if (NT_STATUS_IS_ERR(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1f3bbd488e..8aecd63de0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1304,9 +1304,9 @@ static int call_nt_transact_create(connection_struct *conn, restore_case_semantics(file_attributes); /* Save the requested allocation size. */ - allocation_size = IVAL(params,12); + allocation_size = IVAL_TO_SMB_OFF_T(params,12); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_OFF_T)IVAL(params,16)) << 32); + allocation_size |= ((IVAL_TO_SMB_OFF_T(params,16)) << 32); #endif if (allocation_size && (allocation_size > file_len)) { fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2c29ffdf51..f320bf8ff5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1532,7 +1532,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s flush_write_cache(fsp, READRAW_FLUSH); - startpos = IVAL(inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); if(CVAL(inbuf,smb_wct) == 10) { /* * This is a large offset (64 bit) read. @@ -1627,7 +1627,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length release_level_2_oplocks_on_change(fsp); numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); outsize = set_message(outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); @@ -1696,7 +1696,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int CHECK_READ(fsp); numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); outsize = set_message(outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); @@ -1822,7 +1822,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); - SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); + SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); ssize_t nread = -1; size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); #if 0 @@ -1900,7 +1900,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_WRITE(fsp); tcount = IVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); write_through = BITSETW(inbuf+smb_vwv7,0); /* We have to deal with slightly different formats depending @@ -2030,7 +2030,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, CHECK_WRITE(fsp); numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, @@ -2097,7 +2097,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d CHECK_WRITE(fsp); numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { @@ -2158,7 +2158,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); - SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); + SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); size_t numtowrite = SVAL(inbuf,smb_vwv10); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); ssize_t nwritten = -1; @@ -2269,7 +2269,8 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int flush_write_cache(fsp, SEEK_FLUSH); mode = SVAL(inbuf,smb_vwv1) & 3; - startpos = IVALS(inbuf,smb_vwv2); + /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ + startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2); switch (mode) { case 0: umode = SEEK_SET; break; @@ -2478,7 +2479,7 @@ int reply_writeclose(connection_struct *conn, CHECK_WRITE(fsp); numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; @@ -4056,7 +4057,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, CHECK_FSP(fsp,conn); CHECK_READ(fsp); - startpos = IVAL(inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); data = smb_buf(outbuf); @@ -4184,7 +4185,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_ERROR(fsp); tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); write_through = BITSETW(inbuf+smb_vwv7,0); numtowrite = SVAL(inbuf,smb_vwv10); smb_doff = SVAL(inbuf,smb_vwv11); @@ -4284,7 +4285,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz CHECK_WRITE(fsp); tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); numtowrite = SVAL(inbuf,smb_vwv6); smb_doff = SVAL(inbuf,smb_vwv7); -- cgit From 5ed2d4a1d386d42920bdf97e139eea9bbaaa274b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Dec 2002 23:57:45 +0000 Subject: Reformat of reply.c before Volker's patch. Jeremy. (This used to be commit c3877cfb9c9f3f9f86e32169cbb69c3c5bb2e3db) --- source3/smbd/reply.c | 2088 +++++++++++++++++++++++++------------------------- 1 file changed, 1029 insertions(+), 1059 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f320bf8ff5..adcc8c989d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -418,74 +418,69 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring fname; - int outsize = 0; - SMB_STRUCT_STAT sbuf; - BOOL ok = False; - int mode=0; - SMB_OFF_T size=0; - time_t mtime=0; - BOOL bad_path = False; - char *p; - START_PROFILE(SMBgetatr); - - p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); - - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + pstring fname; + int outsize = 0; + SMB_STRUCT_STAT sbuf; + BOOL ok = False; + int mode=0; + SMB_OFF_T size=0; + time_t mtime=0; + BOOL bad_path = False; + char *p; + START_PROFILE(SMBgetatr); + + p = smb_buf(inbuf) + 1; + p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - /* dos smetimes asks for a stat of "" - it returns a "hidden directory" - under WfWg - weird! */ - if (! (*fname)) - { - mode = aHIDDEN | aDIR; - if (!CAN_WRITE(conn)) mode |= aRONLY; - size = 0; - mtime = 0; - ok = True; - } - else - { - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (check_name(fname,conn)) - { - if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) - { - mode = dos_mode(conn,fname,&sbuf); - size = sbuf.st_size; - mtime = sbuf.st_mtime; - if (mode & aDIR) - size = 0; - ok = True; - } - else - DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); - } - } + /* dos smetimes asks for a stat of "" - it returns a "hidden directory" + under WfWg - weird! */ + if (! (*fname)) { + mode = aHIDDEN | aDIR; + if (!CAN_WRITE(conn)) + mode |= aRONLY; + size = 0; + mtime = 0; + ok = True; + } else { + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (check_name(fname,conn)) { + if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) { + mode = dos_mode(conn,fname,&sbuf); + size = sbuf.st_size; + mtime = sbuf.st_mtime; + if (mode & aDIR) + size = 0; + ok = True; + } else { + DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); + } + } + } - if (!ok) - { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBgetatr); - return(UNIXERROR(ERRDOS,ERRbadfile)); - } + if (!ok) { + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBgetatr); + return(UNIXERROR(ERRDOS,ERRbadfile)); + } - outsize = set_message(outbuf,10,0,True); + outsize = set_message(outbuf,10,0,True); - SSVAL(outbuf,smb_vwv0,mode); - if(lp_dos_filetime_resolution(SNUM(conn)) ) - put_dos_date3(outbuf,smb_vwv1,mtime & ~1); - else - put_dos_date3(outbuf,smb_vwv1,mtime); - SIVAL(outbuf,smb_vwv3,(uint32)size); + SSVAL(outbuf,smb_vwv0,mode); + if(lp_dos_filetime_resolution(SNUM(conn)) ) + put_dos_date3(outbuf,smb_vwv1,mtime & ~1); + else + put_dos_date3(outbuf,smb_vwv1,mtime); + SIVAL(outbuf,smb_vwv3,(uint32)size); - if (Protocol >= PROTOCOL_NT1) - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); + if (Protocol >= PROTOCOL_NT1) + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); - DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); + DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); - END_PROFILE(SMBgetatr); - return(outsize); + END_PROFILE(SMBgetatr); + return(outsize); } /**************************************************************************** @@ -494,47 +489,46 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring fname; - int outsize = 0; - BOOL ok=False; - int mode; - time_t mtime; - SMB_STRUCT_STAT sbuf; - BOOL bad_path = False; - char *p; - - START_PROFILE(SMBsetatr); - - p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); - unix_convert(fname,conn,0,&bad_path,&sbuf); - - mode = SVAL(inbuf,smb_vwv0); - mtime = make_unix_date3(inbuf+smb_vwv1); + pstring fname; + int outsize = 0; + BOOL ok=False; + int mode; + time_t mtime; + SMB_STRUCT_STAT sbuf; + BOOL bad_path = False; + char *p; + + START_PROFILE(SMBsetatr); + + p = smb_buf(inbuf) + 1; + p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); + unix_convert(fname,conn,0,&bad_path,&sbuf); + + mode = SVAL(inbuf,smb_vwv0); + mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(sbuf)) - mode |= aDIR; - else - mode &= ~aDIR; - - if (check_name(fname,conn)) - ok = (file_chmod(conn,fname,mode,NULL) == 0); - if (ok) - ok = set_filetime(conn,fname,mtime); + if (VALID_STAT_OF_DIR(sbuf)) + mode |= aDIR; + else + mode &= ~aDIR; + + if (check_name(fname,conn)) + ok = (file_chmod(conn,fname,mode,NULL) == 0); + if (ok) + ok = set_filetime(conn,fname,mtime); - if (!ok) - { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBsetatr); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if (!ok) { + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBsetatr); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); + DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); - END_PROFILE(SMBsetatr); - return(outsize); + END_PROFILE(SMBsetatr); + return(outsize); } /**************************************************************************** @@ -592,206 +586,187 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring mask; - pstring directory; - pstring fname; - SMB_OFF_T size; - int mode; - time_t date; - int dirtype; - int outsize = 0; - int numentries = 0; - BOOL finished = False; - int maxentries; - int i; - char *p; - BOOL ok = False; - int status_len; - pstring path; - char status[21]; - int dptr_num= -1; - BOOL check_descend = False; - BOOL expect_close = False; - BOOL can_open = True; - BOOL bad_path = False; - START_PROFILE(SMBsearch); - - *mask = *directory = *fname = 0; - - /* If we were called as SMBffirst then we must expect close. */ - if(CVAL(inbuf,smb_com) == SMBffirst) - expect_close = True; - - outsize = set_message(outbuf,1,3,True); - maxentries = SVAL(inbuf,smb_vwv0); - dirtype = SVAL(inbuf,smb_vwv1); - p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); - p++; - status_len = SVAL(p, 0); - p += 2; + pstring mask; + pstring directory; + pstring fname; + SMB_OFF_T size; + int mode; + time_t date; + int dirtype; + int outsize = 0; + int numentries = 0; + BOOL finished = False; + int maxentries; + int i; + char *p; + BOOL ok = False; + int status_len; + pstring path; + char status[21]; + int dptr_num= -1; + BOOL check_descend = False; + BOOL expect_close = False; + BOOL can_open = True; + BOOL bad_path = False; + START_PROFILE(SMBsearch); + + *mask = *directory = *fname = 0; + + /* If we were called as SMBffirst then we must expect close. */ + if(CVAL(inbuf,smb_com) == SMBffirst) + expect_close = True; - /* dirtype &= ~aDIR; */ + outsize = set_message(outbuf,1,3,True); + maxentries = SVAL(inbuf,smb_vwv0); + dirtype = SVAL(inbuf,smb_vwv1); + p = smb_buf(inbuf) + 1; + p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); + p++; + status_len = SVAL(p, 0); + p += 2; - if (status_len == 0) - { - SMB_STRUCT_STAT sbuf; - pstring dir2; - - pstrcpy(directory,path); - pstrcpy(dir2,path); - unix_convert(directory,conn,0,&bad_path,&sbuf); - unix_format(dir2); - - if (!check_name(directory,conn)) - can_open = False; - - p = strrchr_m(dir2,'/'); - if (p == NULL) - { - pstrcpy(mask,dir2); - *dir2 = 0; - } - else - { - *p = 0; - pstrcpy(mask,p+1); - } - - p = strrchr_m(directory,'/'); - if (!p) - *directory = 0; - else - *p = 0; - - if (strlen(directory) == 0) - pstrcpy(directory,"./"); - memset((char *)status,'\0',21); - SCVAL(status,0,(dirtype & 0x1F)); - } - else - { - int status_dirtype; - memcpy(status,p,21); - status_dirtype = CVAL(status,0) & 0x1F; - if (status_dirtype != (dirtype & 0x1F)) - dirtype = status_dirtype; - - conn->dirptr = dptr_fetch(status+12,&dptr_num); - if (!conn->dirptr) - goto SearchEmpty; - string_set(&conn->dirpath,dptr_path(dptr_num)); - fstrcpy(mask, dptr_wcard(dptr_num)); - } - - if (can_open) - { - p = smb_buf(outbuf) + 3; - - ok = True; + /* dirtype &= ~aDIR; */ + + if (status_len == 0) { + SMB_STRUCT_STAT sbuf; + pstring dir2; + + pstrcpy(directory,path); + pstrcpy(dir2,path); + unix_convert(directory,conn,0,&bad_path,&sbuf); + unix_format(dir2); + + if (!check_name(directory,conn)) + can_open = False; + + p = strrchr_m(dir2,'/'); + if (p == NULL) { + pstrcpy(mask,dir2); + *dir2 = 0; + } else { + *p = 0; + pstrcpy(mask,p+1); + } + + p = strrchr_m(directory,'/'); + if (!p) + *directory = 0; + else + *p = 0; + + if (strlen(directory) == 0) + pstrcpy(directory,"./"); + memset((char *)status,'\0',21); + SCVAL(status,0,(dirtype & 0x1F)); + } else { + int status_dirtype; + + memcpy(status,p,21); + status_dirtype = CVAL(status,0) & 0x1F; + if (status_dirtype != (dirtype & 0x1F)) + dirtype = status_dirtype; + + conn->dirptr = dptr_fetch(status+12,&dptr_num); + if (!conn->dirptr) + goto SearchEmpty; + string_set(&conn->dirpath,dptr_path(dptr_num)); + fstrcpy(mask, dptr_wcard(dptr_num)); + } + + if (can_open) { + p = smb_buf(outbuf) + 3; + ok = True; - if (status_len == 0) - { - dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) - { - if(dptr_num == -2) - { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBsearch); - return (UNIXERROR(ERRDOS,ERRnofids)); - } - END_PROFILE(SMBsearch); - return ERROR_DOS(ERRDOS,ERRnofids); - } - dptr_set_wcard(dptr_num, strdup(mask)); - } - - DEBUG(4,("dptr_num is %d\n",dptr_num)); - - if (ok) - { - if ((dirtype&0x1F) == aVOLID) - { - memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); - dptr_fill(p+12,dptr_num); - if (dptr_zero(p+12) && (status_len==0)) - numentries = 1; - else - numentries = 0; - p += DIR_STRUCT_SIZE; - } - else - { - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) - check_descend = True; - - for (i=numentries;(i dontdescend=<%s>\n", + conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) + check_descend = True; + + for (i=numentries;(i= 0 && CVAL(inbuf,smb_com) == SMBfunique) - dptr_close(&dptr_num); - - SSVAL(outbuf,smb_vwv0,numentries); - SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); - SCVAL(smb_buf(outbuf),0,5); - SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); - - if (Protocol >= PROTOCOL_NT1) - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); + if (numentries == 0 || !ok) { + SCVAL(outbuf,smb_rcls,ERRDOS); + SSVAL(outbuf,smb_err,ERRnofiles); + dptr_close(&dptr_num); + } + + /* If we were called as SMBffirst with smb_search_id == NULL + and no entries were found then return error and close dirptr + (X/Open spec) */ + + if(ok && expect_close && numentries == 0 && status_len == 0) { + SCVAL(outbuf,smb_rcls,ERRDOS); + SSVAL(outbuf,smb_err,ERRnofiles); + /* Also close the dptr - we know it's gone */ + dptr_close(&dptr_num); + } + + /* If we were called as SMBfunique, then we can close the dirptr now ! */ + if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) + dptr_close(&dptr_num); + + SSVAL(outbuf,smb_vwv0,numentries); + SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); + SCVAL(smb_buf(outbuf),0,5); + SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); + + if (Protocol >= PROTOCOL_NT1) + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); - outsize += DIR_STRUCT_SIZE*numentries; - smb_setlen(outbuf,outsize - 4); + outsize += DIR_STRUCT_SIZE*numentries; + smb_setlen(outbuf,outsize - 4); - if ((! *directory) && dptr_path(dptr_num)) - slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); + if ((! *directory) && dptr_path(dptr_num)) + slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n", - smb_fn_name(CVAL(inbuf,smb_com)), - mask, directory, dirtype, numentries, maxentries ) ); + DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n", + smb_fn_name(CVAL(inbuf,smb_com)), + mask, directory, dirtype, numentries, maxentries ) ); - END_PROFILE(SMBsearch); - return(outsize); + END_PROFILE(SMBsearch); + return(outsize); } /**************************************************************************** @@ -800,40 +775,40 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = 0; - int status_len; - pstring path; - char status[21]; - int dptr_num= -2; - char *p; + int outsize = 0; + int status_len; + pstring path; + char status[21]; + int dptr_num= -2; + char *p; - START_PROFILE(SMBfclose); + START_PROFILE(SMBfclose); - outsize = set_message(outbuf,1,0,True); - p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); - p++; - status_len = SVAL(p,0); - p += 2; + outsize = set_message(outbuf,1,0,True); + p = smb_buf(inbuf) + 1; + p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); + p++; + status_len = SVAL(p,0); + p += 2; - if (status_len == 0) { - END_PROFILE(SMBfclose); - return ERROR_DOS(ERRSRV,ERRsrverror); - } + if (status_len == 0) { + END_PROFILE(SMBfclose); + return ERROR_DOS(ERRSRV,ERRsrverror); + } - memcpy(status,p,21); + memcpy(status,p,21); - if(dptr_fetch(status+12,&dptr_num)) { - /* Close the dptr - we know it's gone */ - dptr_close(&dptr_num); - } + if(dptr_fetch(status+12,&dptr_num)) { + /* Close the dptr - we know it's gone */ + dptr_close(&dptr_num); + } - SSVAL(outbuf,smb_vwv0,0); + SSVAL(outbuf,smb_vwv0,0); - DEBUG(3,("search close\n")); + DEBUG(3,("search close\n")); - END_PROFILE(SMBfclose); - return(outsize); + END_PROFILE(SMBfclose); + return(outsize); } /**************************************************************************** @@ -842,69 +817,67 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring fname; - int outsize = 0; - int fmode=0; - int share_mode; - SMB_OFF_T size = 0; - time_t mtime=0; - mode_t unixmode; - int rmode=0; - SMB_STRUCT_STAT sbuf; - BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - START_PROFILE(SMBopen); + pstring fname; + int outsize = 0; + int fmode=0; + int share_mode; + SMB_OFF_T size = 0; + time_t mtime=0; + mode_t unixmode; + int rmode=0; + SMB_STRUCT_STAT sbuf; + BOOL bad_path = False; + files_struct *fsp; + int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + START_PROFILE(SMBopen); - share_mode = SVAL(inbuf,smb_vwv0); + share_mode = SVAL(inbuf,smb_vwv0); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); + unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,aARCH,fname); + unixmode = unix_mode(conn,aARCH,fname); - fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - unixmode, oplock_request,&rmode,NULL); - - if (!fsp) - { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBopen); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - size = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - mtime = sbuf.st_mtime; - - if (fmode & aDIR) { - DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fsp,False); - END_PROFILE(SMBopen); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } + fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + unixmode, oplock_request,&rmode,NULL); + + if (!fsp) { + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBopen); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + mtime = sbuf.st_mtime; + + if (fmode & aDIR) { + DEBUG(3,("attempt to open a directory %s\n",fname)); + close_file(fsp,False); + END_PROFILE(SMBopen); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - outsize = set_message(outbuf,7,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); - SSVAL(outbuf,smb_vwv1,fmode); - if(lp_dos_filetime_resolution(SNUM(conn)) ) - put_dos_date3(outbuf,smb_vwv2,mtime & ~1); - else - put_dos_date3(outbuf,smb_vwv2,mtime); - SIVAL(outbuf,smb_vwv4,(uint32)size); - SSVAL(outbuf,smb_vwv6,rmode); - - if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - } + outsize = set_message(outbuf,7,0,True); + SSVAL(outbuf,smb_vwv0,fsp->fnum); + SSVAL(outbuf,smb_vwv1,fmode); + if(lp_dos_filetime_resolution(SNUM(conn)) ) + put_dos_date3(outbuf,smb_vwv2,mtime & ~1); + else + put_dos_date3(outbuf,smb_vwv2,mtime); + SIVAL(outbuf,smb_vwv4,(uint32)size); + SSVAL(outbuf,smb_vwv6,rmode); + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - END_PROFILE(SMBopen); - return(outsize); + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + END_PROFILE(SMBopen); + return(outsize); } /**************************************************************************** @@ -913,107 +886,102 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - pstring fname; - int smb_mode = SVAL(inbuf,smb_vwv3); - int smb_attr = SVAL(inbuf,smb_vwv5); - /* Breakout the oplock request bits so we can set the - reply bits separately. */ - BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); - BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); - BOOL oplock_request = ex_oplock_request | core_oplock_request; + pstring fname; + int smb_mode = SVAL(inbuf,smb_vwv3); + int smb_attr = SVAL(inbuf,smb_vwv5); + /* Breakout the oplock request bits so we can set the + reply bits separately. */ + BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); + BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); + BOOL oplock_request = ex_oplock_request | core_oplock_request; #if 0 - int open_flags = SVAL(inbuf,smb_vwv2); - int smb_sattr = SVAL(inbuf,smb_vwv4); - uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); + int open_flags = SVAL(inbuf,smb_vwv2); + int smb_sattr = SVAL(inbuf,smb_vwv4); + uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); #endif - int smb_ofun = SVAL(inbuf,smb_vwv8); - mode_t unixmode; - SMB_OFF_T size=0; - int fmode=0,mtime=0,rmode=0; - SMB_STRUCT_STAT sbuf; - int smb_action = 0; - BOOL bad_path = False; - files_struct *fsp; - START_PROFILE(SMBopenX); - - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) { - if (lp_nt_pipe_support()) { - END_PROFILE(SMBopenX); - return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); - } else { - END_PROFILE(SMBopenX); - return ERROR_DOS(ERRSRV,ERRaccess); - } - } + int smb_ofun = SVAL(inbuf,smb_vwv8); + mode_t unixmode; + SMB_OFF_T size=0; + int fmode=0,mtime=0,rmode=0; + SMB_STRUCT_STAT sbuf; + int smb_action = 0; + BOOL bad_path = False; + files_struct *fsp; + START_PROFILE(SMBopenX); + + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) { + if (lp_nt_pipe_support()) { + END_PROFILE(SMBopenX); + return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); + } else { + END_PROFILE(SMBopenX); + return ERROR_DOS(ERRSRV,ERRaccess); + } + } - /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + /* XXXX we need to handle passed times, sattr and flags */ + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); + unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,smb_attr | aARCH, fname); + unixmode = unix_mode(conn,smb_attr | aARCH, fname); - fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode, - oplock_request, &rmode,&smb_action); + fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode, + oplock_request, &rmode,&smb_action); - if (!fsp) - { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBopenX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - size = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - mtime = sbuf.st_mtime; - if (fmode & aDIR) { - close_file(fsp,False); - END_PROFILE(SMBopenX); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } - - /* If the caller set the extended oplock request bit - and we granted one (by whatever means) - set the - correct bit for extended oplock reply. - */ - - if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - } - - if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - } - - /* If the caller set the core oplock request bit - and we granted one (by whatever means) - set the - correct bit for core oplock reply. - */ - - if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - } - - if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - } - - set_message(outbuf,15,0,True); - SSVAL(outbuf,smb_vwv2,fsp->fnum); - SSVAL(outbuf,smb_vwv3,fmode); - if(lp_dos_filetime_resolution(SNUM(conn)) ) - put_dos_date3(outbuf,smb_vwv4,mtime & ~1); - else - put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,(uint32)size); - SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,smb_action); - - END_PROFILE(SMBopenX); - return chain_reply(inbuf,outbuf,length,bufsize); + if (!fsp) { + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBopenX); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + size = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + mtime = sbuf.st_mtime; + if (fmode & aDIR) { + close_file(fsp,False); + END_PROFILE(SMBopenX); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + /* If the caller set the extended oplock request bit + and we granted one (by whatever means) - set the + correct bit for extended oplock reply. + */ + + if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) + smb_action |= EXTENDED_OPLOCK_GRANTED; + + if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + smb_action |= EXTENDED_OPLOCK_GRANTED; + + /* If the caller set the core oplock request bit + and we granted one (by whatever means) - set the + correct bit for core oplock reply. + */ + + if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + + if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + + set_message(outbuf,15,0,True); + SSVAL(outbuf,smb_vwv2,fsp->fnum); + SSVAL(outbuf,smb_vwv3,fmode); + if(lp_dos_filetime_resolution(SNUM(conn)) ) + put_dos_date3(outbuf,smb_vwv4,mtime & ~1); + else + put_dos_date3(outbuf,smb_vwv4,mtime); + SIVAL(outbuf,smb_vwv6,(uint32)size); + SSVAL(outbuf,smb_vwv8,rmode); + SSVAL(outbuf,smb_vwv11,smb_action); + + END_PROFILE(SMBopenX); + return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** @@ -1022,28 +990,26 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - uint16 vuid = SVAL(inbuf,smb_uid); - user_struct *vuser = get_valid_user_struct(vuid); - START_PROFILE(SMBulogoffX); + uint16 vuid = SVAL(inbuf,smb_uid); + user_struct *vuser = get_valid_user_struct(vuid); + START_PROFILE(SMBulogoffX); - if(vuser == 0) { - DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); - } + if(vuser == 0) + DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); - /* in user level security we are supposed to close any files - open by this user */ - if ((vuser != 0) && (lp_security() != SEC_SHARE)) { - file_close_user(vuid); - } + /* in user level security we are supposed to close any files + open by this user */ + if ((vuser != 0) && (lp_security() != SEC_SHARE)) + file_close_user(vuid); - invalidate_vuid(vuid); + invalidate_vuid(vuid); - set_message(outbuf,2,0,True); + set_message(outbuf,2,0,True); - DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); + DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); - END_PROFILE(SMBulogoffX); - return chain_reply(inbuf,outbuf,length,bufsize); + END_PROFILE(SMBulogoffX); + return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** @@ -1052,71 +1018,64 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring fname; - int com; - int outsize = 0; - int createmode; - mode_t unixmode; - int ofun = 0; - BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - SMB_STRUCT_STAT sbuf; - START_PROFILE(SMBcreate); + pstring fname; + int com; + int outsize = 0; + int createmode; + mode_t unixmode; + int ofun = 0; + BOOL bad_path = False; + files_struct *fsp; + int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + SMB_STRUCT_STAT sbuf; + START_PROFILE(SMBcreate); - com = SVAL(inbuf,smb_com); + com = SVAL(inbuf,smb_com); - createmode = SVAL(inbuf,smb_vwv0); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE); + createmode = SVAL(inbuf,smb_vwv0); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE); - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); + unix_convert(fname,conn,0,&bad_path,&sbuf); - if (createmode & aVOLID) { - DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); - } + if (createmode & aVOLID) + DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); - unixmode = unix_mode(conn,createmode,fname); + unixmode = unix_mode(conn,createmode,fname); - if(com == SMBmknew) - { - /* We should fail if file exists. */ - ofun = FILE_CREATE_IF_NOT_EXIST; - } - else - { - /* SMBcreate - Create if file doesn't exist, truncate if it does. */ - ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE; - } - - /* Open file in dos compatibility share mode. */ - fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - ofun, unixmode, oplock_request, NULL, NULL); + if(com == SMBmknew) { + /* We should fail if file exists. */ + ofun = FILE_CREATE_IF_NOT_EXIST; + } else { + /* SMBcreate - Create if file doesn't exist, truncate if it does. */ + ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE; + } + + /* Open file in dos compatibility share mode. */ + fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + ofun, unixmode, oplock_request, NULL, NULL); - if (!fsp) - { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBcreate); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if (!fsp) { + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBcreate); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,fsp->fnum); - if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - } + if (oplock_request && lp_fake_oplocks(SNUM(conn))) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - DEBUG( 2, ( "new file %s\n", fname ) ); - DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", - fname, fsp->fd, createmode, (int)unixmode ) ); + DEBUG( 2, ( "new file %s\n", fname ) ); + DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) ); - END_PROFILE(SMBcreate); - return(outsize); + END_PROFILE(SMBcreate); + return(outsize); } /**************************************************************************** @@ -1125,84 +1084,82 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring fname; - int outsize = 0; - int createmode; - mode_t unixmode; - BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - int tmpfd; - SMB_STRUCT_STAT sbuf; - char *p, *s; - - START_PROFILE(SMBctemp); - - createmode = SVAL(inbuf,smb_vwv0); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); - pstrcat(fname,"\\TMXXXXXX"); - - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - - unix_convert(fname,conn,0,&bad_path,&sbuf); + pstring fname; + int outsize = 0; + int createmode; + mode_t unixmode; + BOOL bad_path = False; + files_struct *fsp; + int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + int tmpfd; + SMB_STRUCT_STAT sbuf; + char *p, *s; + + START_PROFILE(SMBctemp); + + createmode = SVAL(inbuf,smb_vwv0); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); + pstrcat(fname,"\\TMXXXXXX"); + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + + unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,createmode,fname); + unixmode = unix_mode(conn,createmode,fname); - tmpfd = smb_mkstemp(fname); - if (tmpfd == -1) { - END_PROFILE(SMBctemp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - vfs_stat(conn,fname,&sbuf); - - /* Open file in dos compatibility share mode. */ - /* We should fail if file does not exist. */ - fsp = open_file_shared(conn,fname,&sbuf, - SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST, - unixmode, oplock_request, NULL, NULL); - - /* close fd from smb_mkstemp() */ - close(tmpfd); - - if (!fsp) { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBctemp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); - - /* the returned filename is relative to the directory */ - s = strrchr_m(fname, '/'); - if (!s) { - s = fname; - } else { - s++; - } - - p = smb_buf(outbuf); - SSVALS(p, 0, -1); /* what is this? not in spec */ - SSVAL(p, 2, strlen(s)); - p += 4; - p += srvstr_push(outbuf, p, s, -1, STR_ASCII); - outsize = set_message_end(outbuf, p); - - if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - } + tmpfd = smb_mkstemp(fname); + if (tmpfd == -1) { + END_PROFILE(SMBctemp); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + vfs_stat(conn,fname,&sbuf); + + /* Open file in dos compatibility share mode. */ + /* We should fail if file does not exist. */ + fsp = open_file_shared(conn,fname,&sbuf, + SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST, + unixmode, oplock_request, NULL, NULL); + + /* close fd from smb_mkstemp() */ + close(tmpfd); + + if (!fsp) { + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBctemp); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,fsp->fnum); + + /* the returned filename is relative to the directory */ + s = strrchr_m(fname, '/'); + if (!s) + s = fname; + else + s++; + + p = smb_buf(outbuf); + SSVALS(p, 0, -1); /* what is this? not in spec */ + SSVAL(p, 2, strlen(s)); + p += 4; + p += srvstr_push(outbuf, p, s, -1, STR_ASCII); + outsize = set_message_end(outbuf, p); + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); - DEBUG( 2, ( "created temp file %s\n", fname ) ); - DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", - fname, fsp->fd, createmode, (int)unixmode ) ); + DEBUG( 2, ( "created temp file %s\n", fname ) ); + DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", + fname, fsp->fd, createmode, (int)unixmode ) ); - END_PROFILE(SMBctemp); - return(outsize); + END_PROFILE(SMBctemp); + return(outsize); } /******************************************************************* @@ -2157,98 +2114,99 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = file_fsp(inbuf,smb_vwv2); - SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); - size_t numtowrite = SVAL(inbuf,smb_vwv10); - BOOL write_through = BITSETW(inbuf+smb_vwv7,0); - ssize_t nwritten = -1; - unsigned int smb_doff = SVAL(inbuf,smb_vwv11); - unsigned int smblen = smb_len(inbuf); - char *data; - BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); - START_PROFILE(SMBwriteX); - - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) { - END_PROFILE(SMBwriteX); - return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize); - } - - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); - - /* Deal with possible LARGE_WRITEX */ - if (large_writeX) - numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); - - if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { - END_PROFILE(SMBwriteX); - return ERROR_DOS(ERRDOS,ERRbadmem); - } - - data = smb_base(inbuf) + smb_doff; - - if(CVAL(inbuf,smb_wct) == 14) { + files_struct *fsp = file_fsp(inbuf,smb_vwv2); + SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); + size_t numtowrite = SVAL(inbuf,smb_vwv10); + BOOL write_through = BITSETW(inbuf+smb_vwv7,0); + ssize_t nwritten = -1; + unsigned int smb_doff = SVAL(inbuf,smb_vwv11); + unsigned int smblen = smb_len(inbuf); + char *data; + BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); + START_PROFILE(SMBwriteX); + + /* If it's an IPC, pass off the pipe handler. */ + if (IS_IPC(conn)) { + END_PROFILE(SMBwriteX); + return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize); + } + + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); + + /* Deal with possible LARGE_WRITEX */ + if (large_writeX) + numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); + + if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { + END_PROFILE(SMBwriteX); + return ERROR_DOS(ERRDOS,ERRbadmem); + } + + data = smb_base(inbuf) + smb_doff; + + if(CVAL(inbuf,smb_wct) == 14) { #ifdef LARGE_SMB_OFF_T - /* - * This is a large offset (64 bit) write. - */ - startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); + /* + * This is a large offset (64 bit) write. + */ + startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); #else /* !LARGE_SMB_OFF_T */ - /* - * Ensure we haven't been sent a >32 bit offset. - */ + /* + * Ensure we haven't been sent a >32 bit offset. + */ - if(IVAL(inbuf,smb_vwv12) != 0) { - DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \ + if(IVAL(inbuf,smb_vwv12) != 0) { + DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \ 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) )); - END_PROFILE(SMBwriteX); - return ERROR_DOS(ERRDOS,ERRbadaccess); - } + END_PROFILE(SMBwriteX); + return ERROR_DOS(ERRDOS,ERRbadaccess); + } #endif /* LARGE_SMB_OFF_T */ - } - - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { - END_PROFILE(SMBwriteX); - return ERROR_DOS(ERRDOS,ERRlock); - } - - /* X/Open SMB protocol says that, unlike SMBwrite - if the length is zero then NO truncation is - done, just a write of zero. To truncate a file, - use SMBwrite. */ - if(numtowrite == 0) - nwritten = 0; - else - nwritten = write_file(fsp,data,startpos,numtowrite); + } + + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + END_PROFILE(SMBwriteX); + return ERROR_DOS(ERRDOS,ERRlock); + } + + /* X/Open SMB protocol says that, unlike SMBwrite + if the length is zero then NO truncation is + done, just a write of zero. To truncate a file, + use SMBwrite. */ + + if(numtowrite == 0) + nwritten = 0; + else + nwritten = write_file(fsp,data,startpos,numtowrite); - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { - END_PROFILE(SMBwriteX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + END_PROFILE(SMBwriteX); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - set_message(outbuf,6,0,True); + set_message(outbuf,6,0,True); - SSVAL(outbuf,smb_vwv2,nwritten); - if (large_writeX) - SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); + SSVAL(outbuf,smb_vwv2,nwritten); + if (large_writeX) + SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); - if (nwritten < (ssize_t)numtowrite) { - SCVAL(outbuf,smb_rcls,ERRHRD); - SSVAL(outbuf,smb_err,ERRdiskfull); - } + if (nwritten < (ssize_t)numtowrite) { + SCVAL(outbuf,smb_rcls,ERRHRD); + SSVAL(outbuf,smb_err,ERRdiskfull); + } - DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", - fsp->fnum, (int)numtowrite, (int)nwritten)); + DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", + fsp->fnum, (int)numtowrite, (int)nwritten)); - if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + if (lp_syncalways(SNUM(conn)) || write_through) + sync_file(conn,fsp); - END_PROFILE(SMBwriteX); - return chain_reply(inbuf,outbuf,length,bufsize); + END_PROFILE(SMBwriteX); + return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** @@ -2257,80 +2215,87 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - SMB_OFF_T startpos; - SMB_OFF_T res= -1; - int mode,umode; - int outsize = 0; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBlseek); + SMB_OFF_T startpos; + SMB_OFF_T res= -1; + int mode,umode; + int outsize = 0; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + START_PROFILE(SMBlseek); - CHECK_FSP(fsp,conn); + CHECK_FSP(fsp,conn); - flush_write_cache(fsp, SEEK_FLUSH); + flush_write_cache(fsp, SEEK_FLUSH); - mode = SVAL(inbuf,smb_vwv1) & 3; - /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ - startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2); + mode = SVAL(inbuf,smb_vwv1) & 3; + /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ + startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2); - switch (mode) { - case 0: umode = SEEK_SET; break; - case 1: umode = SEEK_CUR; break; - case 2: umode = SEEK_END; break; - default: - umode = SEEK_SET; break; - } + switch (mode) { + case 0: + umode = SEEK_SET; + break; + case 1: + umode = SEEK_CUR; + break; + case 2: + umode = SEEK_END; + break; + default: + umode = SEEK_SET; + break; + } - if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) { - /* - * Check for the special case where a seek before the start - * of the file sets the offset to zero. Added in the CIFS spec, - * section 4.2.7. - */ + if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) { + /* + * Check for the special case where a seek before the start + * of the file sets the offset to zero. Added in the CIFS spec, + * section 4.2.7. + */ - if(errno == EINVAL) { - SMB_OFF_T current_pos = startpos; + if(errno == EINVAL) { + SMB_OFF_T current_pos = startpos; - if(umode == SEEK_CUR) { + if(umode == SEEK_CUR) { - if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) { - END_PROFILE(SMBlseek); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) { + END_PROFILE(SMBlseek); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - current_pos += startpos; + current_pos += startpos; - } else if (umode == SEEK_END) { + } else if (umode == SEEK_END) { - SMB_STRUCT_STAT sbuf; + SMB_STRUCT_STAT sbuf; - if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) { - END_PROFILE(SMBlseek); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) { + END_PROFILE(SMBlseek); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - current_pos += sbuf.st_size; - } + current_pos += sbuf.st_size; + } - if(current_pos < 0) - res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET); - } + if(current_pos < 0) + res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET); + } - if(res == -1) { - END_PROFILE(SMBlseek); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } + if(res == -1) { + END_PROFILE(SMBlseek); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } - fsp->pos = res; + fsp->pos = res; - outsize = set_message(outbuf,2,0,True); - SIVAL(outbuf,smb_vwv0,res); + outsize = set_message(outbuf,2,0,True); + SIVAL(outbuf,smb_vwv0,res); - DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n", - fsp->fnum, (double)startpos, (double)res, mode)); + DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n", + fsp->fnum, (double)startpos, (double)res, mode)); - END_PROFILE(SMBlseek); - return(outsize); + END_PROFILE(SMBlseek); + return(outsize); } /**************************************************************************** @@ -2696,6 +2661,7 @@ int reply_printopen(connection_struct *conn, /**************************************************************************** Reply to a printclose. ****************************************************************************/ + int reply_printclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { @@ -2803,32 +2769,33 @@ int reply_printqueue(connection_struct *conn, int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int numtowrite; - int outsize = set_message(outbuf,0,0,True); - char *data; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); - START_PROFILE(SMBsplwr); + int numtowrite; + int outsize = set_message(outbuf,0,0,True); + char *data; + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + + START_PROFILE(SMBsplwr); - if (!CAN_PRINT(conn)) { - END_PROFILE(SMBsplwr); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } + if (!CAN_PRINT(conn)) { + END_PROFILE(SMBsplwr); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + CHECK_FSP(fsp,conn); + CHECK_WRITE(fsp); - numtowrite = SVAL(smb_buf(inbuf),1); - data = smb_buf(inbuf) + 3; + numtowrite = SVAL(smb_buf(inbuf),1); + data = smb_buf(inbuf) + 3; - if (write_file(fsp,data,-1,numtowrite) != numtowrite) { - END_PROFILE(SMBsplwr); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if (write_file(fsp,data,-1,numtowrite) != numtowrite) { + END_PROFILE(SMBsplwr); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); + DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); - END_PROFILE(SMBsplwr); - return(outsize); + END_PROFILE(SMBsplwr); + return(outsize); } /**************************************************************************** @@ -3024,38 +2991,36 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - pstring directory; - int outsize = 0; - BOOL ok = False; - BOOL bad_path = False; - SMB_STRUCT_STAT sbuf; - START_PROFILE(SMBrmdir); + pstring directory; + int outsize = 0; + BOOL ok = False; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + START_PROFILE(SMBrmdir); - srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE); + srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE); - RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) + RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) - unix_convert(directory,conn, NULL,&bad_path,&sbuf); + unix_convert(directory,conn, NULL,&bad_path,&sbuf); - if (check_name(directory,conn)) - { - dptr_closepath(directory,SVAL(inbuf,smb_pid)); - ok = rmdir_internals(conn, directory); - } + if (check_name(directory,conn)) { + dptr_closepath(directory,SVAL(inbuf,smb_pid)); + ok = rmdir_internals(conn, directory); + } - if (!ok) - { - set_bad_path_error(errno, bad_path); - END_PROFILE(SMBrmdir); - return(UNIXERROR(ERRDOS,ERRbadpath)); - } + if (!ok) { + set_bad_path_error(errno, bad_path); + END_PROFILE(SMBrmdir); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - DEBUG( 3, ( "rmdir %s\n", directory ) ); + DEBUG( 3, ( "rmdir %s\n", directory ) ); - END_PROFILE(SMBrmdir); - return(outsize); + END_PROFILE(SMBrmdir); + return(outsize); } /******************************************************************* @@ -3064,63 +3029,66 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, static BOOL resolve_wildcards(char *name1,char *name2) { - fstring root1,root2; - fstring ext1,ext2; - char *p,*p2; + fstring root1,root2; + fstring ext1,ext2; + char *p,*p2; - name1 = strrchr_m(name1,'/'); - name2 = strrchr_m(name2,'/'); + name1 = strrchr_m(name1,'/'); + name2 = strrchr_m(name2,'/'); - if (!name1 || !name2) return(False); + if (!name1 || !name2) + return(False); - fstrcpy(root1,name1); - fstrcpy(root2,name2); - p = strrchr_m(root1,'.'); - if (p) { - *p = 0; - fstrcpy(ext1,p+1); - } else { - fstrcpy(ext1,""); - } - p = strrchr_m(root2,'.'); - if (p) { - *p = 0; - fstrcpy(ext2,p+1); - } else { - fstrcpy(ext2,""); - } - - p = root1; - p2 = root2; - while (*p2) { - if (*p2 == '?') { - *p2 = *p; - p2++; - } else { - p2++; - } - if (*p) p++; - } - - p = ext1; - p2 = ext2; - while (*p2) { - if (*p2 == '?') { - *p2 = *p; - p2++; - } else { - p2++; - } - if (*p) p++; - } - - pstrcpy(name2,root2); - if (ext2[0]) { - pstrcat(name2,"."); - pstrcat(name2,ext2); - } - - return(True); + fstrcpy(root1,name1); + fstrcpy(root2,name2); + p = strrchr_m(root1,'.'); + if (p) { + *p = 0; + fstrcpy(ext1,p+1); + } else { + fstrcpy(ext1,""); + } + p = strrchr_m(root2,'.'); + if (p) { + *p = 0; + fstrcpy(ext2,p+1); + } else { + fstrcpy(ext2,""); + } + + p = root1; + p2 = root2; + while (*p2) { + if (*p2 == '?') { + *p2 = *p; + p2++; + } else { + p2++; + } + if (*p) + p++; + } + + p = ext1; + p2 = ext2; + while (*p2) { + if (*p2 == '?') { + *p2 = *p; + p2++; + } else { + p2++; + } + if (*p) + p++; + } + + pstrcpy(name2,root2); + if (ext2[0]) { + pstrcat(name2,"."); + pstrcat(name2,ext2); + } + + return(True); } /**************************************************************************** @@ -3502,163 +3470,165 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = 0; - pstring name; - pstring directory; - pstring mask,newname; - char *p; - int count=0; - int error = ERRnoaccess; - int err = 0; - BOOL has_wild; - BOOL exists=False; - int tid2 = SVAL(inbuf,smb_vwv0); - int ofun = SVAL(inbuf,smb_vwv1); - int flags = SVAL(inbuf,smb_vwv2); - BOOL target_is_directory=False; - BOOL bad_path1 = False; - BOOL bad_path2 = False; - BOOL rc = True; - SMB_STRUCT_STAT sbuf1, sbuf2; - START_PROFILE(SMBcopy); - - *directory = *mask = 0; - - p = smb_buf(inbuf); - p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE); + int outsize = 0; + pstring name; + pstring directory; + pstring mask,newname; + char *p; + int count=0; + int error = ERRnoaccess; + int err = 0; + BOOL has_wild; + BOOL exists=False; + int tid2 = SVAL(inbuf,smb_vwv0); + int ofun = SVAL(inbuf,smb_vwv1); + int flags = SVAL(inbuf,smb_vwv2); + BOOL target_is_directory=False; + BOOL bad_path1 = False; + BOOL bad_path2 = False; + BOOL rc = True; + SMB_STRUCT_STAT sbuf1, sbuf2; + + START_PROFILE(SMBcopy); + + *directory = *mask = 0; + + p = smb_buf(inbuf); + p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE); - DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); + DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); - if (tid2 != conn->cnum) { - /* can't currently handle inter share copies XXXX */ - DEBUG(3,("Rejecting inter-share copy\n")); - END_PROFILE(SMBcopy); - return ERROR_DOS(ERRSRV,ERRinvdevice); - } - - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); - - rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); - unix_convert(newname,conn,0,&bad_path2,&sbuf2); - - target_is_directory = VALID_STAT_OF_DIR(sbuf2); - - if ((flags&1) && target_is_directory) { - END_PROFILE(SMBcopy); - return ERROR_DOS(ERRDOS,ERRbadfile); - } - - if ((flags&2) && !target_is_directory) { - END_PROFILE(SMBcopy); - return ERROR_DOS(ERRDOS,ERRbadpath); - } - - if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) { - /* wants a tree copy! XXXX */ - DEBUG(3,("Rejecting tree copy\n")); - END_PROFILE(SMBcopy); - return ERROR_DOS(ERRSRV,ERRerror); - } - - p = strrchr_m(name,'/'); - if (!p) { - pstrcpy(directory,"./"); - pstrcpy(mask,name); - } else { - *p = 0; - pstrcpy(directory,name); - pstrcpy(mask,p+1); - } - - /* - * We should only check the mangled cache - * here if unix_convert failed. This means - * that the path in 'mask' doesn't exist - * on the file system and so we need to look - * for a possible mangle. This patch from - * Tine Smukavec . - */ - - if (!rc && mangle_is_mangled(mask)) - mangle_check_cache( mask ); - - has_wild = ms_has_wild(mask); - - if (!has_wild) { - pstrcat(directory,"/"); - pstrcat(directory,mask); - if (resolve_wildcards(directory,newname) && - copy_file(directory,newname,conn,ofun, - count,target_is_directory,&err)) count++; - if(!count && err) { - errno = err; + if (tid2 != conn->cnum) { + /* can't currently handle inter share copies XXXX */ + DEBUG(3,("Rejecting inter-share copy\n")); END_PROFILE(SMBcopy); - return(UNIXERROR(ERRHRD,ERRgeneral)); + return ERROR_DOS(ERRSRV,ERRinvdevice); } - if (!count) exists = vfs_file_exist(conn,directory,NULL); - } else { - void *dirptr = NULL; - char *dname; - pstring destname; - if (check_name(directory,conn)) - dirptr = OpenDir(conn, directory, True); + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); - if (dirptr) { - error = ERRbadfile; + rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); + unix_convert(newname,conn,0,&bad_path2,&sbuf2); - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); + target_is_directory = VALID_STAT_OF_DIR(sbuf2); - while ((dname = ReadDirName(dirptr))) { - pstring fname; - pstrcpy(fname,dname); - - if(!mask_match(fname, mask, case_sensitive)) - continue; + if ((flags&1) && target_is_directory) { + END_PROFILE(SMBcopy); + return ERROR_DOS(ERRDOS,ERRbadfile); + } - error = ERRnoaccess; - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - pstrcpy(destname,newname); - if (resolve_wildcards(fname,destname) && - copy_file(fname,destname,conn,ofun, - count,target_is_directory,&err)) count++; - DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); - } - CloseDir(dirptr); - } - } + if ((flags&2) && !target_is_directory) { + END_PROFILE(SMBcopy); + return ERROR_DOS(ERRDOS,ERRbadpath); + } + + if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) { + /* wants a tree copy! XXXX */ + DEBUG(3,("Rejecting tree copy\n")); + END_PROFILE(SMBcopy); + return ERROR_DOS(ERRSRV,ERRerror); + } + + p = strrchr_m(name,'/'); + if (!p) { + pstrcpy(directory,"./"); + pstrcpy(mask,name); + } else { + *p = 0; + pstrcpy(directory,name); + pstrcpy(mask,p+1); + } + + /* + * We should only check the mangled cache + * here if unix_convert failed. This means + * that the path in 'mask' doesn't exist + * on the file system and so we need to look + * for a possible mangle. This patch from + * Tine Smukavec . + */ + + if (!rc && mangle_is_mangled(mask)) + mangle_check_cache( mask ); + + has_wild = ms_has_wild(mask); + + if (!has_wild) { + pstrcat(directory,"/"); + pstrcat(directory,mask); + if (resolve_wildcards(directory,newname) && + copy_file(directory,newname,conn,ofun, count,target_is_directory,&err)) + count++; + if(!count && err) { + errno = err; + END_PROFILE(SMBcopy); + return(UNIXERROR(ERRHRD,ERRgeneral)); + } + if (!count) { + exists = vfs_file_exist(conn,directory,NULL); + } + } else { + void *dirptr = NULL; + char *dname; + pstring destname; + + if (check_name(directory,conn)) + dirptr = OpenDir(conn, directory, True); + + if (dirptr) { + error = ERRbadfile; + + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + + while ((dname = ReadDirName(dirptr))) { + pstring fname; + pstrcpy(fname,dname); + + if(!mask_match(fname, mask, case_sensitive)) + continue; + + error = ERRnoaccess; + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + pstrcpy(destname,newname); + if (resolve_wildcards(fname,destname) && + copy_file(fname,destname,conn,ofun, + count,target_is_directory,&err)) + count++; + DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); + } + CloseDir(dirptr); + } + } - if (count == 0) { - if(err) { - /* Error on close... */ - errno = err; - END_PROFILE(SMBcopy); - return(UNIXERROR(ERRHRD,ERRgeneral)); - } - - if (exists) { - END_PROFILE(SMBcopy); - return ERROR_DOS(ERRDOS,error); - } else - { - if((errno == ENOENT) && (bad_path1 || bad_path2)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - END_PROFILE(SMBcopy); - return(UNIXERROR(ERRDOS,error)); - } - } + if (count == 0) { + if(err) { + /* Error on close... */ + errno = err; + END_PROFILE(SMBcopy); + return(UNIXERROR(ERRHRD,ERRgeneral)); + } + + if (exists) { + END_PROFILE(SMBcopy); + return ERROR_DOS(ERRDOS,error); + } else { + if((errno == ENOENT) && (bad_path1 || bad_path2)) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + END_PROFILE(SMBcopy); + return(UNIXERROR(ERRDOS,error)); + } + } - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,count); + outsize = set_message(outbuf,1,0,True); + SSVAL(outbuf,smb_vwv0,count); - END_PROFILE(SMBcopy); - return(outsize); + END_PROFILE(SMBcopy); + return(outsize); } /**************************************************************************** @@ -3667,41 +3637,41 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int snum; - int outsize = 0; - BOOL ok = False; - pstring newdir; - START_PROFILE(pathworks_setdir); + int snum; + int outsize = 0; + BOOL ok = False; + pstring newdir; + + START_PROFILE(pathworks_setdir); - snum = SNUM(conn); - if (!CAN_SETDIR(snum)) { - END_PROFILE(pathworks_setdir); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } + snum = SNUM(conn); + if (!CAN_SETDIR(snum)) { + END_PROFILE(pathworks_setdir); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } - srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE); + srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE); - if (strlen(newdir) == 0) { - ok = True; - } else { - ok = vfs_directory_exist(conn,newdir,NULL); - if (ok) { - string_set(&conn->connectpath,newdir); - } - } + if (strlen(newdir) == 0) { + ok = True; + } else { + ok = vfs_directory_exist(conn,newdir,NULL); + if (ok) + string_set(&conn->connectpath,newdir); + } - if (!ok) { - END_PROFILE(pathworks_setdir); - return ERROR_DOS(ERRDOS,ERRbadpath); - } + if (!ok) { + END_PROFILE(pathworks_setdir); + return ERROR_DOS(ERRDOS,ERRbadpath); + } - outsize = set_message(outbuf,0,0,True); - SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh)); + outsize = set_message(outbuf,0,0,True); + SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh)); - DEBUG(3,("setdir %s\n", newdir)); + DEBUG(3,("setdir %s\n", newdir)); - END_PROFILE(pathworks_setdir); - return(outsize); + END_PROFILE(pathworks_setdir); + return(outsize); } /**************************************************************************** @@ -3722,36 +3692,36 @@ uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format) SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format) { - SMB_BIG_UINT count = 0; + SMB_BIG_UINT count = 0; - if(!large_file_format) { - count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset)); - } else { + if(!large_file_format) { + count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset)); + } else { #if defined(HAVE_LONGLONG) - count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) | - ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset))); + count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) | + ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset))); #else /* HAVE_LONGLONG */ - /* - * NT4.x seems to be broken in that it sends large file (64 bit) - * lockingX calls even if the CAP_LARGE_FILES was *not* - * negotiated. For boxes without large unsigned ints truncate the - * lock count by dropping the top 32 bits. - */ - - if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) { - DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n", - (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)), - (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) )); - SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0); - } - - count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); + /* + * NT4.x seems to be broken in that it sends large file (64 bit) + * lockingX calls even if the CAP_LARGE_FILES was *not* + * negotiated. For boxes without large unsigned ints truncate the + * lock count by dropping the top 32 bits. + */ + + if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) { + DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n", + (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)), + (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) )); + SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0); + } + + count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); #endif /* HAVE_LONGLONG */ - } + } - return count; + return count; } #if !defined(HAVE_LONGLONG) @@ -3794,47 +3764,47 @@ static uint32 map_lock_offset(uint32 high, uint32 low) SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err) { - SMB_BIG_UINT offset = 0; + SMB_BIG_UINT offset = 0; - *err = False; + *err = False; - if(!large_file_format) { - offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset)); - } else { + if(!large_file_format) { + offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset)); + } else { #if defined(HAVE_LONGLONG) - offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) | - ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset))); + offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) | + ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset))); #else /* HAVE_LONGLONG */ - /* - * NT4.x seems to be broken in that it sends large file (64 bit) - * lockingX calls even if the CAP_LARGE_FILES was *not* - * negotiated. For boxes without large unsigned ints mangle the - * lock offset by mapping the top 32 bits onto the lower 32. - */ + /* + * NT4.x seems to be broken in that it sends large file (64 bit) + * lockingX calls even if the CAP_LARGE_FILES was *not* + * negotiated. For boxes without large unsigned ints mangle the + * lock offset by mapping the top 32 bits onto the lower 32. + */ - if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) { - uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); - uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)); - uint32 new_low = 0; - - if((new_low = map_lock_offset(high, low)) == 0) { - *err = True; - return (SMB_BIG_UINT)-1; - } - - DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n", - (unsigned int)high, (unsigned int)low, (unsigned int)new_low )); - SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0); - SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low); - } - - offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); + if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) { + uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); + uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)); + uint32 new_low = 0; + + if((new_low = map_lock_offset(high, low)) == 0) { + *err = True; + return (SMB_BIG_UINT)-1; + } + + DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n", + (unsigned int)high, (unsigned int)low, (unsigned int)new_low )); + SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0); + SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low); + } + + offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); #endif /* HAVE_LONGLONG */ - } + } - return offset; + return offset; } /**************************************************************************** -- cgit From ce4628c199f8e8ac84aa7f2afe2de1d9d23e6fab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Dec 2002 03:12:09 +0000 Subject: Fix for 64 bit issues with oplocks and allocation size. Jeremy. (This used to be commit 379e719e983fb71f94cd2b691f8b194c109496c3) --- source3/smbd/fileio.c | 56 ++++++++++++++++++++++++++++++++------------------ source3/smbd/nttrans.c | 18 ++++++++-------- source3/smbd/trans2.c | 20 +++++++++--------- source3/smbd/vfs.c | 21 +++++++++++-------- 4 files changed, 68 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 6bae1df996..9e37b951e5 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -172,7 +172,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); - fsp->size = st.st_size; + fsp->size = (SMB_BIG_UINT)st.st_size; if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); @@ -233,8 +233,8 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if(!wcp) { DO_PROFILE_INC(writecache_direct_writes); total_written = real_write_file(fsp, data, pos, n); - if ((total_written != -1) && (pos + total_written > fsp->size)) - fsp->size = pos + total_written; + if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size)) + fsp->size = (SMB_BIG_UINT)(pos + total_written); return total_written; } @@ -283,8 +283,10 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * Update the file size if changed. */ - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) { + wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } /* * If we used all the data then @@ -344,8 +346,10 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * Update the file size if changed. */ - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) { + wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } /* * We don't need to move the start of data, but we @@ -418,8 +422,10 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * Update the file size if changed. */ - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) { + wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } /* * If we used all the data then @@ -493,8 +499,10 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne * Update the file size if needed. */ - if(pos + n > wcp->file_size) - fsp->size = wcp->file_size = pos + n; + if(pos + n > wcp->file_size) { + wcp->file_size = pos + n; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } /* * If write would fit in the cache, and is larger than @@ -525,8 +533,10 @@ cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned in if (ret == -1) return ret; - if (pos + ret > wcp->file_size) - fsp->size = wcp->file_size = pos + ret; + if (pos + ret > wcp->file_size) { + wcp->file_size = pos + ret; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } return ret; } @@ -535,8 +545,10 @@ cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned in } - if(wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->data_size; + if(wcp->data_size > wcp->file_size) { + wcp->file_size = wcp->data_size; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } if (cache_flush_needed) { DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ @@ -558,8 +570,10 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", if (ret == -1) return -1; - if (pos + ret > wcp->file_size) - fsp->size = wcp->file_size = pos + n; + if (pos + ret > wcp->file_size) { + wcp->file_size = pos + n; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } DO_PROFILE_INC(writecache_direct_writes); return total_written + n; @@ -588,8 +602,10 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", * Update the file size if changed. */ - if (wcp->offset + wcp->data_size > wcp->file_size) - fsp->size = wcp->file_size = wcp->offset + wcp->data_size; + if (wcp->offset + wcp->data_size > wcp->file_size) { + wcp->file_size = wcp->offset + wcp->data_size; + fsp->size = (SMB_BIG_UINT)wcp->file_size; + } DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n", (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n)); @@ -674,7 +690,7 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) { - fsp->size = file_size; + fsp->size = (SMB_BIG_UINT)file_size; if(fsp->wcp) { /* The cache *must* have been flushed before we do this. */ if (fsp->wcp->data_size != 0) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8aecd63de0..bdefa6c4c1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -548,7 +548,7 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); - SMB_OFF_T allocation_size = 0; + SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); @@ -807,11 +807,11 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib } /* Save the requested allocation size. */ - allocation_size = IVAL(inbuf,smb_ntcreate_AllocationSize); + allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_OFF_T)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif - if (allocation_size && (allocation_size > file_len)) { + if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,False); @@ -819,7 +819,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE); + fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE); } /* @@ -1065,7 +1065,7 @@ static int call_nt_transact_create(connection_struct *conn, uint32 create_options; uint32 sd_len; uint16 root_dir_fid; - SMB_OFF_T allocation_size = 0; + SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; int smb_attr; @@ -1304,9 +1304,9 @@ static int call_nt_transact_create(connection_struct *conn, restore_case_semantics(file_attributes); /* Save the requested allocation size. */ - allocation_size = IVAL_TO_SMB_OFF_T(params,12); + allocation_size = (SMB_BIG_UINT)IVAL(params,12); #ifdef LARGE_SMB_OFF_T - allocation_size |= ((IVAL_TO_SMB_OFF_T(params,16)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif if (allocation_size && (allocation_size > file_len)) { fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); @@ -1316,7 +1316,7 @@ static int call_nt_transact_create(connection_struct *conn, return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE); + fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE); } /* Realloc the size of parameters and data we will return */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a2627021d9..33828c32bd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -33,15 +33,15 @@ extern uint32 global_client_caps; /* given a stat buffer return the allocated size on disk, taking into account sparse files */ -SMB_OFF_T get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) +SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) { - SMB_OFF_T ret; + SMB_BIG_UINT ret; #if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS) - ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks; + ret = (SMB_BIG_UINT)sbuf->st_blksize * (SMB_BIG_UINT)sbuf->st_blocks; #elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - ret = (SMB_OFF_T)STAT_ST_BLOCKSIZE * (SMB_OFF_T)sbuf->st_blocks; + ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks; #else - ret = get_file_size(*sbuf); + ret = (SMB_BIG_UINT)get_file_size(*sbuf); #endif if (!ret && fsp && fsp->initial_allocation_size) ret = fsp->initial_allocation_size; @@ -473,7 +473,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, int prev_dirpos=0; int mode=0; SMB_OFF_T file_size = 0; - SMB_OFF_T allocation_size = 0; + SMB_BIG_UINT allocation_size = 0; uint32 len; time_t mdate=0, adate=0, cdate=0; char *nameptr; @@ -1552,7 +1552,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, uint16 info_level; int mode=0; SMB_OFF_T file_size=0; - SMB_OFF_T allocation_size=0; + SMB_BIG_UINT allocation_size=0; unsigned int data_size; SMB_STRUCT_STAT sbuf; pstring fname, dos_fname; @@ -2428,14 +2428,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_ALLOCATION_INFO: { int ret = -1; - SMB_OFF_T allocation_size; + SMB_BIG_UINT allocation_size; if (total_data < 8) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); - allocation_size = IVAL(pdata,0); + allocation_size = (SMB_BIG_UINT)IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) /* more than 32 bits? */ return ERROR_DOS(ERRDOS,ERRunknownlevel); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f6dad7b6e7..7e60d3dacb 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -423,13 +423,13 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) Returns 0 on success, -1 on failure. ****************************************************************************/ -int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) +int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) { int ret; SMB_STRUCT_STAT st; connection_struct *conn = fsp->conn; struct vfs_ops *vfs_ops = &conn->vfs_ops; - SMB_OFF_T space_avail; + SMB_BIG_UINT space_avail; SMB_BIG_UINT bsize,dfree,dsize; release_level_2_oplocks_on_change(fsp); @@ -440,21 +440,26 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp->fsp_name, (double)len )); + if (((SMB_OFF_T)len) < 0) { + DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name )); + return -1; + } + ret = vfs_fstat(fsp,fsp->fd,&st); if (ret == -1) return ret; - if (len == st.st_size) + if (len == (SMB_BIG_UINT)st.st_size) return 0; - if (len < st.st_size) { + if (len < (SMB_BIG_UINT)st.st_size) { /* Shrink - use ftruncate. */ DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n", fsp->fsp_name, (double)st.st_size )); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = vfs_ops->ftruncate(fsp, fsp->fd, len)) != -1) { + if ((ret = vfs_ops->ftruncate(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { set_filelen_write_cache(fsp, len); } return ret; @@ -467,10 +472,10 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_OFF_T len) len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ - space_avail = (SMB_OFF_T)conn->vfs_ops.disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); + space_avail = conn->vfs_ops.disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); - DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %lu, space avail = %lu\n", - fsp->fsp_name, (double)st.st_size, (unsigned long)len, (unsigned long)space_avail )); + DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", + fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail )); if (len > space_avail) { errno = ENOSPC; -- cgit From 821e3d19f0d0dc09c903cab991dc79eb04a5ec95 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Dec 2002 03:21:21 +0000 Subject: Missed the removal of the incorrect ifdef. Jeremy. (This used to be commit f9cef6f42193b3ae70569e2c7584f088fb53a51c) --- source3/smbd/trans2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 33828c32bd..cd15a8f6fd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -36,9 +36,7 @@ extern uint32 global_client_caps; SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) { SMB_BIG_UINT ret; -#if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS) - ret = (SMB_BIG_UINT)sbuf->st_blksize * (SMB_BIG_UINT)sbuf->st_blocks; -#elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) +#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks; #else ret = (SMB_BIG_UINT)get_file_size(*sbuf); -- cgit From f60f763a2dddaa6ab355c66dc2f86831b36dd278 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Dec 2002 18:45:25 +0000 Subject: Need brackets around macro args. Spotted by Patrick Welche . Jeremy. (This used to be commit 2b9d35cf3f91e9488a55e0a73150d4c18b998afe) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cd15a8f6fd..d83596d68f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -29,7 +29,7 @@ extern fstring local_machine; extern int global_oplock_break; extern uint32 global_client_caps; -#define get_file_size(sbuf) (sbuf.st_size) +#define get_file_size(sbuf) ((sbuf).st_size) /* given a stat buffer return the allocated size on disk, taking into account sparse files */ -- cgit From 612e1ffdba747c969525be760f8783c946960812 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 4 Dec 2002 20:57:48 +0000 Subject: merges from HEAD - change_trust_account_password() must always talk to PDC (This used to be commit af2fa4385015dce8dedafe80e02a0115892e508e) --- source3/smbd/change_trust_pw.c | 162 ++++++++++++++++++++--------------------- source3/smbd/process.c | 6 +- 2 files changed, 80 insertions(+), 88 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 28a004eba8..a140978733 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -31,106 +31,98 @@ static NTSTATUS modify_trust_password( const char *domain, const char *remote_machine, unsigned char orig_trust_passwd_hash[16]) { - struct cli_state *cli; - DOM_SID domain_sid; - NTSTATUS nt_status; + struct cli_state *cli; + DOM_SID domain_sid; + NTSTATUS nt_status; - /* - * Ensure we have the domain SID for this domain. - */ + /* + * Ensure we have the domain SID for this domain. + */ - if (!secrets_fetch_domain_sid(domain, &domain_sid)) { - DEBUG(0, ("modify_trust_password: unable to fetch domain sid.\n")); - return NT_STATUS_UNSUCCESSFUL; - } + if (!secrets_fetch_domain_sid(domain, &domain_sid)) { + DEBUG(0, ("modify_trust_password: unable to fetch domain sid.\n")); + return NT_STATUS_UNSUCCESSFUL; + } - if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine, + if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine, NULL, 0, "IPC$", "IPC", "", "", - "", 0, NULL))) { - DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); - return NT_STATUS_UNSUCCESSFUL; - } + "", 0, NULL))) + { + DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); + return NT_STATUS_UNSUCCESSFUL; + } - /* - * Ok - we have an anonymous connection to the IPC$ share. - * Now start the NT Domain stuff :-). - */ - - if(cli_nt_session_open(cli, PI_NETLOGON) == False) { - DEBUG(0,("modify_trust_password: unable to open the domain client session to \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli))); - cli_nt_session_close(cli); - cli_ulogoff(cli); - cli_shutdown(cli); - return NT_STATUS_UNSUCCESSFUL; - } - - nt_status = trust_pw_change_and_store_it(cli, cli->mem_ctx, + /* + * Ok - we have an anonymous connection to the IPC$ share. + * Now start the NT Domain stuff :-). + */ + + if(cli_nt_session_open(cli, PI_NETLOGON) == False) { + DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", + remote_machine, cli_errstr(cli))); + cli_nt_session_close(cli); + cli_ulogoff(cli); + cli_shutdown(cli); + return NT_STATUS_UNSUCCESSFUL; + } + + nt_status = trust_pw_change_and_store_it(cli, cli->mem_ctx, orig_trust_passwd_hash); - cli_nt_session_close(cli); - cli_ulogoff(cli); - cli_shutdown(cli); - return nt_status; + cli_nt_session_close(cli); + cli_ulogoff(cli); + cli_shutdown(cli); + + return nt_status; } /************************************************************************ Change the trust account password for a domain. ************************************************************************/ -NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine_list) +NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine) { - fstring remote_machine; - unsigned char old_trust_passwd_hash[16]; - time_t lct; - NTSTATUS res = NT_STATUS_UNSUCCESSFUL; - - if(!secrets_fetch_trust_account_password(domain, old_trust_passwd_hash, &lct)) { - DEBUG(0,("change_trust_account_password: unable to read the machine \ -account password for domain %s.\n", domain)); - return NT_STATUS_UNSUCCESSFUL; - } - - while(remote_machine_list && - next_token(&remote_machine_list, remote_machine, - LIST_SEP, sizeof(remote_machine))) { - strupper(remote_machine); - if(strequal(remote_machine, "*")) { - - /* - * We have been asked to dynamcially determine the IP addresses of the PDC. - */ - - struct in_addr pdc_ip; - fstring dc_name; - - /* Use the PDC *only* for this. */ - if(!get_pdc_ip(domain, &pdc_ip)) - continue; - - /* - * Try and connect to the PDC/BDC list in turn as an IP - * address used as a string. - */ - - if(!lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name)) - continue; - if(NT_STATUS_IS_OK(res = modify_trust_password( domain, dc_name, - old_trust_passwd_hash))) - break; - } else { - res = modify_trust_password( domain, remote_machine, - old_trust_passwd_hash); - } - - } - - if (!NT_STATUS_IS_OK(res)) { - DEBUG(0,("%s : change_trust_account_password: Failed to change password for \ -domain %s.\n", timestring(False), domain)); - } + unsigned char old_trust_passwd_hash[16]; + time_t lct; + NTSTATUS res = NT_STATUS_UNSUCCESSFUL; + struct in_addr pdc_ip; + fstring dc_name; + + + if(!secrets_fetch_trust_account_password(domain, old_trust_passwd_hash, &lct)) { + DEBUG(0,("change_trust_account_password: unable to read the machine account password for domain %s.\n", + domain)); + return NT_STATUS_UNSUCCESSFUL; + } + + if (remote_machine == NULL || !strcmp(remote_machine, "*")) { + /* Use the PDC *only* for this */ + + if ( !get_pdc_ip(domain, &pdc_ip) ) { + DEBUG(0,("Can't get IP for PDC for domain %s\n", domain)); + goto failed; + } + + if ( !lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name) ) + goto failed; + } + /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ + else { + fstrcpy( dc_name, remote_machine ); + } + + /* if this next call fails, then give up. We can't do + password changes on BDC's --jerry */ + + res = modify_trust_password(domain, dc_name, old_trust_passwd_hash); + +failed: + if (!NT_STATUS_IS_OK(res)) { + DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", + timestring(False), domain)); + } - return res; + return res; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c46c4c5509..3b0619b7d0 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1175,9 +1175,9 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); return True; } - pstrcpy(remote_machine_list, lp_passwordserver()); - - change_trust_account_password( lp_workgroup(), remote_machine_list); + /* always just contact the PDC here */ + + change_trust_account_password( lp_workgroup(), NULL); global_machine_password_needs_changing = False; secrets_lock_trust_account_password(lp_workgroup(), False); } -- cgit From d4103a09918bf375804bb102ac29237345f59978 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Dec 2002 22:48:13 +0000 Subject: Added Volker's directory fix - save the attributes from the first call. Jeremy. (This used to be commit b60a441b91dccdeadc125476ac3306b938941057) --- source3/smbd/reply.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index adcc8c989d..6c2698c297 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -689,6 +689,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRnofids); } dptr_set_wcard(dptr_num, strdup(mask)); + dptr_set_attr(dptr_num, dirtype); + } else { + dirtype = dptr_attr(dptr_num); } DEBUG(4,("dptr_num is %d\n",dptr_num)); -- cgit From 00a20ce45f11e62470e60a8d5fcacc6b0b1f90a2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Dec 2002 04:00:16 +0000 Subject: The element in fsp->print_job should be a RAP jobid, not a uint32 RPC jobid. This was causing Win9x client "set name" calls to fail. Still need one cleanup fix to finish. Jeremy. (This used to be commit 6c23d2030ab8dddff4c849903c529f0012b94027) --- source3/smbd/fileio.c | 15 +++++++++++++-- source3/smbd/reply.c | 3 +-- source3/smbd/trans2.c | 5 +---- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 9e37b951e5..b612b1a451 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -158,8 +158,19 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) ssize_t total_written = 0; int write_path = -1; - if (fsp->print_file) - return print_job_write(SNUM(fsp->conn), fsp->print_jobid, data, n); + if (fsp->print_file) { + int snum; + uint32 jobid; + + if (!rap_to_pjobid(fsp->rap_print_jobid, &snum, &jobid)) { + DEBUG(3,("write_file: Unable to map RAP jobid %u to jobid.\n", + (unsigned int)fsp->rap_print_jobid )); + errno = EBADF; + return -1; + } + + return print_job_write(SNUM(fsp->conn), jobid, data, n); + } if (!fsp->can_write) { errno = EPERM; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6c2698c297..96b7692b1a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -353,8 +353,7 @@ int reply_ioctl(connection_struct *conn, switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: { - uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); - SSVAL(p,0,rap_jobid); /* Job number */ + SSVAL(p,0,fsp->rap_print_jobid); /* Job number */ srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII); srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); break; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d83596d68f..872e33c832 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3006,8 +3006,6 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { - uint16 rap_jobid; - pdata = Realloc(*ppdata, 32); if(pdata == NULL) return ERROR_DOS(ERRDOS,ERRnomem); @@ -3016,8 +3014,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 CAN ACCEPT THIS IN UNICODE. JRA. */ - rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */ - SSVAL(pdata,0,rap_jobid); /* Job number */ + SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */ srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); -- cgit From 2c5e33b7f2e372b348c4aa97824078f7b62db8ff Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 5 Dec 2002 23:30:49 +0000 Subject: Merge from HEAD: >Remove FILE_MACRO as __FILE__ is ANSI C. (This used to be commit 21eb4b5a2dd2f9a6a0d3cd94408bb52359d2e926) --- source3/smbd/build_options.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 8129f22898..085f287446 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -294,9 +294,6 @@ void build_options(BOOL screen) #ifdef SEEKDIR_RETURNS_VOID output(screen," SEEKDIR_RETURNS_VOID\n"); #endif -#ifdef HAVE_FILE_MACRO - output(screen," HAVE_FILE_MACRO\n"); -#endif #ifdef HAVE_FUNCTION_MACRO output(screen," HAVE_FUNCTION_MACRO\n"); #endif -- cgit From 39c78bf516f4db59fd3c218f67d13dd658daf558 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Dec 2002 23:54:40 +0000 Subject: Fixed auth module code. Added VALGRIND defines to reduce spurious warnings. Jeremy. (This used to be commit ec4ed45563f9d8e25fcfd88840944a90b3139c3e) --- source3/smbd/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3b0619b7d0..923b20ad66 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1140,7 +1140,6 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t { unsigned char trust_passwd_hash[16]; time_t lct; - pstring remote_machine_list; /* * We're in domain level security, and the code that -- cgit From d0fe43f918eae56d60398231f53266698d732fd7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Dec 2002 02:01:56 +0000 Subject: Added "kernel change notify" boolean to allow easier valgrind testing. Jeremy. (This used to be commit faf89f214f326bc07f728b354062b2287cda1208) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 0895ddaf87..de1b331778 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -207,7 +207,8 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, BOOL init_change_notify(void) { #if HAVE_KERNEL_CHANGE_NOTIFY - cnotify = kernel_notify_init(); + if (lp_kernel_change_notify()) + cnotify = kernel_notify_init(); #endif if (!cnotify) cnotify = hash_notify_init(); -- cgit From ce2b200add7129eb67da18afc7f44f0cf93c33ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Dec 2002 19:07:37 +0000 Subject: Fix for old DOS client when veto files is set to /.*/ Jeremy. (This used to be commit 8e9f3b1574cd51d6b9880d9c8a676e695cd86062) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 96b7692b1a..de15faec81 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -654,7 +654,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size *p = 0; if (strlen(directory) == 0) - pstrcpy(directory,"./"); + pstrcpy(directory,"."); memset((char *)status,'\0',21); SCVAL(status,0,(dirtype & 0x1F)); } else { -- cgit From ef8bd7c4f7ae8192ea05db070962ecf0ff3615f3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Dec 2002 20:21:31 +0000 Subject: Forward port the change to talloc_init() to make all talloc contexts named. Ensure we can query them. Jeremy. (This used to be commit 09a218a9f6fb0bd922940467bf8500eb4f1bcf84) --- source3/smbd/nttrans.c | 4 ++-- source3/smbd/server.c | 31 ++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bdefa6c4c1..740f450db6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -985,7 +985,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu * Init the parse struct we will unmarshall from. */ - if ((mem_ctx = talloc_init()) == NULL) { + if ((mem_ctx = talloc_init("set_sd")) == NULL) { DEBUG(0,("set_sd: talloc_init failed.\n")); return NT_STATUS_NO_MEMORY; } @@ -1538,7 +1538,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, *ppparams = params; - if ((mem_ctx = talloc_init()) == NULL) { + if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) { DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); return ERROR_DOS(ERRDOS,ERRnomem); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 342c7c85cf..7581eb6001 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -463,6 +463,25 @@ BOOL reload_services(BOOL test) return(ret); } +/******************************************************************* + Print out all talloc memory info. +********************************************************************/ + +void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len) +{ + TALLOC_CTX *ctx = talloc_init("info context"); + char *info = NULL; + + if (!ctx) + return; + + info = talloc_describe_all(ctx); + if (info) + DEBUG(10,(info)); + message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1 : 0, True); + talloc_destroy(ctx); +} + #if DUMP_CORE /******************************************************************* prepare to dump a core file - carefully! @@ -759,19 +778,18 @@ static BOOL init_structs(void ) setpgid( (pid_t)0, (pid_t)0); #endif - if (!directory_exist(lp_lockdir(), NULL)) { + if (!directory_exist(lp_lockdir(), NULL)) mkdir(lp_lockdir(), 0755); - } - if (is_daemon) { + if (is_daemon) pidfile_create("smbd"); - } - if (!message_init()) { + if (!message_init()) exit(1); - } + register_msg_pool_usage(); register_dmalloc_msgs(); + message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info); if (!print_backend_init()) exit(1); @@ -840,7 +858,6 @@ static BOOL init_structs(void ) /* register our message handlers */ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); - talloc_init_named("dummy!"); smbd_process(); -- cgit From 6b7f50594b56a1357b1c95a974e4750d7390cc17 Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Fri, 27 Dec 2002 23:03:22 +0000 Subject: Add check to prevent non-Dfs clients from connecting to an msdfs proxy. (This used to be commit 2a665ab60a07fd64665cb791e6616479f3239cbb) --- source3/smbd/service.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1f168dd3ff..d00c908a1a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -833,6 +833,13 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, return NULL; } + /* Handle non-Dfs clients attempting connections to msdfs proxy */ + if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) { + DEBUG(3, ("refusing connection to dfs proxy '%s'\n", service)); + *status = NT_STATUS_BAD_NETWORK_NAME; + return NULL; + } + DEBUG(5, ("making a connection to 'normal' service %s\n", service)); return make_connection_snum(snum, vuser, -- cgit From 0747016dfc280d9eac3e388f7b705a4351b55513 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 31 Dec 2002 10:25:11 +0000 Subject: from HEAD: fix for bad check spotted by Ray Simard (This used to be commit bcc633c4097661447731bda24a38be62c69bbed5) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index de15faec81..4335728afc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1888,7 +1888,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); - if (nwritten < numtowrite) { + if (nwritten < (ssize_t)numtowrite) { END_PROFILE(SMBwritebraw); return(UNIXERROR(ERRHRD,ERRdiskfull)); } -- cgit From da41ac6e6b893566738e10f5ed076ac8e99ffe9e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jan 2003 19:25:28 +0000 Subject: Merge Andrew Bartletts (size_t)-1 checks. Jeremy. (This used to be commit 339f4fe15efbf67157c8e61b98c6ea983e6b4674) --- source3/smbd/mangle_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 0446a953ff..d1c5cf1b5c 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -730,7 +730,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83) DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, need83 ? "True" : "False", cache83 ? "True" : "False")); - if (push_ucs2_allocate(&OutName_ucs2, OutName) < 0) { + if (push_ucs2_allocate(&OutName_ucs2, OutName) == (size_t)-1) { DEBUG(0, ("push_ucs2_allocate failed!\n")); return; } -- cgit From 95ce704fe6aab58ac68940ee3a25fb8e0796caba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jan 2003 20:43:17 +0000 Subject: pstring/fstring missmatches found by Andrew Bartlett. Jeremy. (This used to be commit 666861b1e263370f6ba8fa4108842f52a81d8b83) --- source3/smbd/sesssetup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9d708bd5a0..f8e8e017e0 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -609,8 +609,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DATA_BLOB lm_resp; DATA_BLOB nt_resp; DATA_BLOB plaintext_password; - pstring user; - pstring sub_user; /* Sainitised username for substituion */ + fstring user; + fstring sub_user; /* Sainitised username for substituion */ fstring domain; fstring native_os; fstring native_lanman; @@ -756,15 +756,15 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } - pstrcpy(sub_user, user); + fstrcpy(sub_user, user); /* setup the string used by %U */ sub_set_smb_name(user); } else { - pstrcpy(sub_user, lp_guestaccount()); + fstrcpy(sub_user, lp_guestaccount()); } - pstrcpy(current_user_info.smb_name,sub_user); + fstrcpy(current_user_info.smb_name,sub_user); reload_services(True); -- cgit From 634c54310c92c48dd4eceec602e230a021bdcfc5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Jan 2003 08:28:12 +0000 Subject: Merge from HEAD - make Samba compile with -Wwrite-strings without additional warnings. (Adds a lot of const). Andrew Bartlett (This used to be commit 3a7458f9472432ef12c43008414925fd1ce8ea0c) --- source3/smbd/build_options.c | 4 ++-- source3/smbd/connection.c | 6 +++--- source3/smbd/dir.c | 21 +++++++++++++-------- source3/smbd/filename.c | 6 +++--- source3/smbd/lanman.c | 37 +++++++++++++++++++------------------ source3/smbd/mangle.c | 4 ++-- source3/smbd/mangle_hash.c | 8 ++++---- source3/smbd/negprot.c | 6 +++--- source3/smbd/nttrans.c | 2 +- source3/smbd/process.c | 4 ++-- source3/smbd/reply.c | 2 +- source3/smbd/server.c | 9 +++++---- source3/smbd/utmp.c | 2 +- source3/smbd/vfs.c | 2 +- 14 files changed, 60 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index 085f287446..da5accebab 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -23,7 +23,7 @@ #include "build_env.h" #include "dynconfig.h" -static void output(BOOL screen, char *format, ...) PRINTF_ATTRIBUTE(2,3); +static void output(BOOL screen, const char *format, ...) PRINTF_ATTRIBUTE(2,3); /* #define OUTPUT(x) snprintf(outstring,sizeof(outstring),x); output(screen,outstring); @@ -31,7 +31,7 @@ static void output(BOOL screen, char *format, ...) PRINTF_ATTRIBUTE(2,3); /**************************************************************************** helper function for build_options ****************************************************************************/ -static void output(BOOL screen, char *format, ...) +static void output(BOOL screen, const char *format, ...) { char *ptr; va_list ap; diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index ad394a01ca..a7636e889e 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -35,7 +35,7 @@ TDB_CONTEXT *conn_tdb_ctx(void) return tdb; } -static void make_conn_key(connection_struct *conn,char *name, TDB_DATA *pkbuf, struct connections_key *pkey) +static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey) { ZERO_STRUCTP(pkey); pkey->pid = sys_getpid(); @@ -50,7 +50,7 @@ static void make_conn_key(connection_struct *conn,char *name, TDB_DATA *pkbuf, s Delete a connection record. ****************************************************************************/ -BOOL yield_connection(connection_struct *conn,char *name) +BOOL yield_connection(connection_struct *conn, const char *name) { struct connections_key key; TDB_DATA kbuf; @@ -116,7 +116,7 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u Claim an entry in the connections database. ****************************************************************************/ -BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear, uint32 msg_flags) +BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags) { struct connections_key key; struct connections_data crec; diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 396ecd98c4..d3c71ad24e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -327,15 +327,20 @@ void dptr_closepath(char *path,uint16 spid) Start a directory listing. ****************************************************************************/ -static BOOL start_dir(connection_struct *conn,char *directory) +static BOOL start_dir(connection_struct *conn, pstring directory) { + const char *dir2; + DEBUG(5,("start_dir dir=%s\n",directory)); if (!check_name(directory,conn)) return(False); + + /* use a const pointer from here on */ + dir2 = directory; - if (! *directory) - directory = "."; + if (! *dir2) + dir2 = "."; conn->dirptr = OpenDir(conn, directory, True); if (conn->dirptr) { @@ -392,7 +397,7 @@ static void dptr_close_oldest(BOOL old) me at Andrew's knee.... :-) :-). JRA. ****************************************************************************/ -int dptr_create(connection_struct *conn,char *path, BOOL old_handle, BOOL expect_close,uint16 spid) +int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid) { dptr_struct *dptr; @@ -812,10 +817,10 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT Open a directory. ********************************************************************/ -void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) +void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) { Dir *dirp; - char *n; + const char *n; DIR *p = conn->vfs_ops.opendir(conn,name); int used=0; @@ -1009,7 +1014,7 @@ static ubi_dlNewList( dir_cache ); Output: None. *****************************************************************************/ -void DirCacheAdd( char *path, char *name, char *dname, int snum ) +void DirCacheAdd( const char *path, char *name, char *dname, int snum ) { int pathlen; int namelen; @@ -1056,7 +1061,7 @@ void DirCacheAdd( char *path, char *name, char *dname, int snum ) for large caches. *****************************************************************************/ -char *DirCacheCheck( char *path, char *name, int snum ) +char *DirCacheCheck( const char *path, const char *name, int snum ) { dir_cache_entry *entry; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 202bd75d4c..bcfd366741 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -31,7 +31,7 @@ extern BOOL case_preserve; extern BOOL short_case_preserve; extern BOOL use_mangled_map; -static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache); +static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache); /**************************************************************************** Check if two filenames are equal. @@ -387,7 +387,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen a valid one for the user to access. ****************************************************************************/ -BOOL check_name(char *name,connection_struct *conn) +BOOL check_name(pstring name,connection_struct *conn) { BOOL ret; @@ -428,7 +428,7 @@ BOOL check_name(char *name,connection_struct *conn) If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache) +static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache) { void *cur_dir; char *dname; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 43b5d9e55f..7a667c378d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -109,14 +109,14 @@ static char* Expand(connection_struct *conn, int snum, char* s) /******************************************************************* check a API string for validity when we only need to check the prefix ******************************************************************/ -static BOOL prefix_ok(char *str,char *prefix) +static BOOL prefix_ok(const char *str, const char *prefix) { return(strncmp(str,prefix,strlen(prefix)) == 0); } struct pack_desc { - char* format; /* formatstring for structure */ - char* subformat; /* subformat for structure */ + const char* format; /* formatstring for structure */ + const char* subformat; /* subformat for structure */ char* base; /* baseaddress of buffer */ int buflen; /* remaining size for fixed part; on init: length of base */ int subcount; /* count of substructures */ @@ -125,11 +125,11 @@ struct pack_desc { char* stringbuf; /* pointer into buffer for remaining variable part */ int neededlen; /* total needed size */ int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ - char* curpos; /* current position; pointer into format or subformat */ + const char* curpos; /* current position; pointer into format or subformat */ int errcode; }; -static int get_counter(char** p) +static int get_counter(const char** p) { int i, n; if (!p || !(*p)) return(1); @@ -144,7 +144,7 @@ static int get_counter(char** p) } } -static int getlen(char* p) +static int getlen(const char* p) { int n = 0; if (!p) return(0); @@ -329,7 +329,7 @@ static int package(struct pack_desc* p, ...) #define PACKl(desc,t,v,l) package(desc,v,l) #endif -static void PACKI(struct pack_desc* desc,char *t,int v) +static void PACKI(struct pack_desc* desc, const char *t,int v) { PACK(desc,t,v); } @@ -1704,7 +1704,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para char *UserName = skip_string(str2,1); char *p = skip_string(UserName,1); int uLevel = SVAL(p,0); - char *p2; + const char *level_string; int count=0; *rparam_len = 8; @@ -1715,13 +1715,13 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para return False; switch( uLevel ) { case 0: - p2 = "B21"; + level_string = "B21"; break; default: return False; } - if (strcmp(p2,str2) != 0) + if (strcmp(level_string,str2) != 0) return False; *rdata_len = mdrcnt + 1024; @@ -2602,6 +2602,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param char *p = skip_string(UserName,1); int uLevel = SVAL(p,0); char *p2; + const char *level_string; /* get NIS home of a previously validated user - simeon */ /* With share level security vuid will always be zero. @@ -2620,15 +2621,15 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param if (strcmp(str1,"zWrLh") != 0) return False; switch( uLevel ) { - case 0: p2 = "B21"; break; - case 1: p2 = "B21BB16DWzzWz"; break; - case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; - case 10: p2 = "B21Bzzz"; break; - case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break; + case 0: level_string = "B21"; break; + case 1: level_string = "B21BB16DWzzWz"; break; + case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; + case 10: level_string = "B21Bzzz"; break; + case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break; default: return False; } - if (strcmp(p2,str2) != 0) return False; + if (strcmp(level_string,str2) != 0) return False; *rdata_len = mdrcnt + 1024; *rdata = REALLOC(*rdata,*rdata_len); @@ -3425,9 +3426,9 @@ static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,cha -const static struct +static const struct { - char *name; + const char *name; int id; BOOL (*fn)(connection_struct *,uint16,char *,char *, int,int,char **,char **,int *,int *); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 392e48afc1..f5c703a5bf 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -23,8 +23,8 @@ static struct mangle_fns *mangle_fns; /* this allows us to add more mangling backends */ -static struct { - char *name; +static const struct { + const char *name; struct mangle_fns *(*init_fn)(void); } mangle_backends[] = { { "hash", mangle_hash_init }, diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index d1c5cf1b5c..e220d2f6d2 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -361,15 +361,15 @@ done: */ static void init_chartest( void ) { - char *illegalchars = "*\\/?<>|\":"; - unsigned char *s; + const char *illegalchars = "*\\/?<>|\":"; + const unsigned char *s; memset( (char *)chartest, '\0', 256 ); - for( s = (unsigned char *)illegalchars; *s; s++ ) + for( s = (const unsigned char *)illegalchars; *s; s++ ) chartest[*s] = ILLEGAL_MASK; - for( s = (unsigned char *)basechars; *s; s++ ) + for( s = (const unsigned char *)basechars; *s; s++ ) chartest[*s] |= BASECHAR_MASK; ct_initialized = True; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b91c0c0866..c8f023514e 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -377,9 +377,9 @@ protocol [LANMAN2.1] #define ARCH_ALL 0x3F /* List of supported protocols, most desired first */ -static struct { - char *proto_name; - char *short_name; +static const struct { + const char *proto_name; + const char *short_name; int (*proto_reply_fn)(char *, char *); int protocol_level; } supported_protocols[] = { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 740f450db6..29ebdce5a8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -27,7 +27,7 @@ extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -static char *known_nt_pipes[] = { +static const char *known_nt_pipes[] = { "\\LANMAN", "\\srvsvc", "\\samr", diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 923b20ad66..7421c16b40 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -339,7 +339,7 @@ force write permissions on print services. functions. Any message that has a NULL function is unimplemented - please feel free to contribute implementations! */ -const static struct smb_message_struct +static const struct smb_message_struct { const char *name; int (*fn)(connection_struct *conn, char *, char *, int, int); @@ -890,7 +890,7 @@ return a string containing the function name of a SMB command ****************************************************************************/ const char *smb_fn_name(int type) { - static char *unknown_name = "SMBunknown"; + const char *unknown_name = "SMBunknown"; if (smb_messages[type].name == NULL) return(unknown_name); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4335728afc..beccc1bba6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -271,7 +271,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message_end(outbuf,p); } else { /* NT sets the fstype of IPC$ to the null string */ - char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); + const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); set_message(outbuf,3,0,True); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7581eb6001..94849f9f5c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -179,11 +179,12 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) if (!smb_ports) { ports = lp_smb_ports(); if (!ports || !*ports) { - ports = SMB_PORTS; + ports = smb_xstrdup(SMB_PORTS); + } else { + ports = smb_xstrdup(ports); } - ports = strdup(ports); } else { - ports = strdup(smb_ports); + ports = smb_xstrdup(smb_ports); } if (lp_interfaces() && lp_bind_interfaces_only()) { @@ -539,7 +540,7 @@ static void decrement_smbd_process_count(void) Exit the server. ****************************************************************************/ -void exit_server(char *reason) +void exit_server(const char *reason) { static int firsttime=1; extern char *last_inbuf; diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 6b7b0f3ad1..6c12cfac62 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -457,7 +457,7 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) static int ut_id_encode(int i, char *fourbyte) { int nbase; - char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; fourbyte[0] = 'S'; fourbyte[1] = 'M'; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7e60d3dacb..7b8d9d7e9e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -781,7 +781,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) Widelinks are allowed if widelinks is true. ********************************************************************/ -BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks) +BOOL reduce_name(connection_struct *conn, pstring s, const char *dir,BOOL widelinks) { #ifndef REDUCE_PATHS return True; -- cgit From f5d5df9644abc08ae1b16a0826eb8cf5c3de54d1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Jan 2003 17:39:30 +0000 Subject: patch to include support for daemontools from Michael Handler (This used to be commit a8db1b611d83bfd8dcf60f1e6d8fcbf57c798528) --- source3/smbd/server.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 94849f9f5c..c5474a46b8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -632,6 +632,8 @@ static BOOL init_structs(void ) /* shall I run as a daemon */ static BOOL is_daemon = False; static BOOL interactive = False; + static BOOL Fork = True; + static BOOL log_stdout = False; static char *ports = NULL; int opt; poptContext pc; @@ -640,6 +642,8 @@ static BOOL init_structs(void ) POPT_AUTOHELP {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, + {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" }, + {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug}, @@ -678,7 +682,17 @@ static BOOL init_structs(void ) set_remote_machine_name("smbd"); - setup_logging(argv[0],interactive); + if (interactive) { + Fork = False; + log_stdout = True; + } + + if (log_stdout && Fork) { + DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); + exit(1); + } + + setup_logging(argv[0],log_stdout); /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ @@ -767,7 +781,7 @@ static BOOL init_structs(void ) if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(); + become_daemon(Fork); } #if HAVE_SETPGID -- cgit From 20f1cf6cdcf9fc74d18fb9401e627a3455183ef3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Jan 2003 18:50:13 +0000 Subject: Fix problem with "hide unreadable". stat file opens are baaack :-). Jeremy. (This used to be commit 62038a0abf193d4dc4f37c31ac77216a10f6f326) --- source3/smbd/close.c | 125 ++++---- source3/smbd/dir.c | 857 +++++++++++++++++++++++++-------------------------- source3/smbd/open.c | 144 +++------ 3 files changed, 542 insertions(+), 584 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index dc52327cb4..b0620febef 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -21,64 +21,65 @@ #include "includes.h" /**************************************************************************** -run a file if it is a magic script + Run a file if it is a magic script. ****************************************************************************/ + static void check_magic(files_struct *fsp,connection_struct *conn) { - if (!*lp_magicscript(SNUM(conn))) - return; - - DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); - - { - char *p; - if (!(p = strrchr_m(fsp->fsp_name,'/'))) - p = fsp->fsp_name; - else - p++; - - if (!strequal(lp_magicscript(SNUM(conn)),p)) - return; - } - - { - int ret; - pstring magic_output; - pstring fname; - SMB_STRUCT_STAT st; - int tmp_fd, outfd; - - pstrcpy(fname,fsp->fsp_name); - if (*lp_magicoutput(SNUM(conn))) - pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); - else - slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); - - chmod(fname,0755); - ret = smbrun(fname,&tmp_fd); - DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); - unlink(fname); - if (ret != 0 || tmp_fd == -1) { - if (tmp_fd != -1) - close(tmp_fd); - return; - } - outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); - if (outfd == -1) { - close(tmp_fd); + if (!*lp_magicscript(SNUM(conn))) return; + + DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); + + { + char *p; + if (!(p = strrchr_m(fsp->fsp_name,'/'))) + p = fsp->fsp_name; + else + p++; + + if (!strequal(lp_magicscript(SNUM(conn)),p)) + return; } - if (sys_fstat(tmp_fd,&st) == -1) { + { + int ret; + pstring magic_output; + pstring fname; + SMB_STRUCT_STAT st; + int tmp_fd, outfd; + + pstrcpy(fname,fsp->fsp_name); + if (*lp_magicoutput(SNUM(conn))) + pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); + else + slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); + + chmod(fname,0755); + ret = smbrun(fname,&tmp_fd); + DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); + unlink(fname); + if (ret != 0 || tmp_fd == -1) { + if (tmp_fd != -1) + close(tmp_fd); + return; + } + outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); + if (outfd == -1) { + close(tmp_fd); + return; + } + + if (sys_fstat(tmp_fd,&st) == -1) { + close(tmp_fd); + close(outfd); + return; + } + + transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size); close(tmp_fd); close(outfd); - return; } - - transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size); - close(tmp_fd); - close(outfd); - } } /**************************************************************************** @@ -97,8 +98,6 @@ static int close_filestruct(files_struct *fsp) delete_write_cache(fsp); } - fsp->is_directory = False; - conn->num_files_open--; SAFE_FREE(fsp->wbmpx_ptr); @@ -258,17 +257,37 @@ static int close_directory(files_struct *fsp, BOOL normal_close) string_free(&fsp->fsp_name); file_free(fsp); + return 0; +} +/**************************************************************************** + Close a 'stat file' opened internally. +****************************************************************************/ + +static int close_stat(files_struct *fsp) +{ + /* + * Do the code common to files and directories. + */ + close_filestruct(fsp); + + if (fsp->fsp_name) + string_free(&fsp->fsp_name); + + file_free(fsp); return 0; } /**************************************************************************** - Close a directory opened by an NT SMB call. + Close a files_struct. ****************************************************************************/ int close_file(files_struct *fsp, BOOL normal_close) { if(fsp->is_directory) return close_directory(fsp, normal_close); - return close_normal_file(fsp, normal_close); + else if (fsp->is_stat) + return close_stat(fsp); + else + return close_normal_file(fsp, normal_close); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index d3c71ad24e..4aa132d110 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -49,17 +49,17 @@ static int dptrs_open = 0; void init_dptrs(void) { - static BOOL dptrs_init=False; + static BOOL dptrs_init=False; - if (dptrs_init) - return; + if (dptrs_init) + return; - dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); + dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); - if (!dptr_bmap) - exit_server("out of memory in init_dptrs"); + if (!dptr_bmap) + exit_server("out of memory in init_dptrs"); - dptrs_init = True; + dptrs_init = True; } /**************************************************************************** @@ -68,12 +68,12 @@ void init_dptrs(void) static void dptr_idle(dptr_struct *dptr) { - if (dptr->ptr) { - DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); - dptrs_open--; - CloseDir(dptr->ptr); - dptr->ptr = NULL; - } + if (dptr->ptr) { + DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); + dptrs_open--; + CloseDir(dptr->ptr); + dptr->ptr = NULL; + } } /**************************************************************************** @@ -82,29 +82,29 @@ static void dptr_idle(dptr_struct *dptr) static void dptr_idleoldest(void) { - dptr_struct *dptr; - - /* - * Go to the end of the list. - */ - for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) - ; - - if(!dptr) { - DEBUG(0,("No dptrs available to idle ?\n")); - return; - } - - /* - * Idle the oldest pointer. - */ - - for(; dptr; dptr = dptr->prev) { - if (dptr->ptr) { - dptr_idle(dptr); - return; - } - } + dptr_struct *dptr; + + /* + * Go to the end of the list. + */ + for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) + ; + + if(!dptr) { + DEBUG(0,("No dptrs available to idle ?\n")); + return; + } + + /* + * Idle the oldest pointer. + */ + + for(; dptr; dptr = dptr->prev) { + if (dptr->ptr) { + dptr_idle(dptr); + return; + } + } } /**************************************************************************** @@ -113,22 +113,22 @@ static void dptr_idleoldest(void) static dptr_struct *dptr_get(int key, BOOL forclose) { - dptr_struct *dptr; - - for(dptr = dirptrs; dptr; dptr = dptr->next) { - if(dptr->dnum == key) { - if (!forclose && !dptr->ptr) { - if (dptrs_open >= MAX_OPEN_DIRECTORIES) - dptr_idleoldest(); - DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True))) - dptrs_open++; - } - DLIST_PROMOTE(dirptrs,dptr); - return dptr; - } - } - return(NULL); + dptr_struct *dptr; + + for(dptr = dirptrs; dptr; dptr = dptr->next) { + if(dptr->dnum == key) { + if (!forclose && !dptr->ptr) { + if (dptrs_open >= MAX_OPEN_DIRECTORIES) + dptr_idleoldest(); + DEBUG(4,("Reopening dptr key %d\n",key)); + if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True))) + dptrs_open++; + } + DLIST_PROMOTE(dirptrs,dptr); + return dptr; + } + } + return(NULL); } /**************************************************************************** @@ -137,11 +137,11 @@ static dptr_struct *dptr_get(int key, BOOL forclose) static void *dptr_ptr(int key) { - dptr_struct *dptr = dptr_get(key, False); + dptr_struct *dptr = dptr_get(key, False); - if (dptr) - return(dptr->ptr); - return(NULL); + if (dptr) + return(dptr->ptr); + return(NULL); } /**************************************************************************** @@ -150,11 +150,11 @@ static void *dptr_ptr(int key) char *dptr_path(int key) { - dptr_struct *dptr = dptr_get(key, False); + dptr_struct *dptr = dptr_get(key, False); - if (dptr) - return(dptr->path); - return(NULL); + if (dptr) + return(dptr->path); + return(NULL); } /**************************************************************************** @@ -163,11 +163,11 @@ char *dptr_path(int key) char *dptr_wcard(int key) { - dptr_struct *dptr = dptr_get(key, False); + dptr_struct *dptr = dptr_get(key, False); - if (dptr) - return(dptr->wcard); - return(NULL); + if (dptr) + return(dptr->wcard); + return(NULL); } /**************************************************************************** @@ -177,13 +177,13 @@ char *dptr_wcard(int key) BOOL dptr_set_wcard(int key, char *wcard) { - dptr_struct *dptr = dptr_get(key, False); + dptr_struct *dptr = dptr_get(key, False); - if (dptr) { - dptr->wcard = wcard; - return True; - } - return False; + if (dptr) { + dptr->wcard = wcard; + return True; + } + return False; } /**************************************************************************** @@ -193,13 +193,13 @@ BOOL dptr_set_wcard(int key, char *wcard) BOOL dptr_set_attr(int key, uint16 attr) { - dptr_struct *dptr = dptr_get(key, False); + dptr_struct *dptr = dptr_get(key, False); - if (dptr) { - dptr->attr = attr; - return True; - } - return False; + if (dptr) { + dptr->attr = attr; + return True; + } + return False; } /**************************************************************************** @@ -208,11 +208,11 @@ BOOL dptr_set_attr(int key, uint16 attr) uint16 dptr_attr(int key) { - dptr_struct *dptr = dptr_get(key, False); + dptr_struct *dptr = dptr_get(key, False); - if (dptr) - return(dptr->attr); - return(0); + if (dptr) + return(dptr->attr); + return(0); } /**************************************************************************** @@ -221,31 +221,31 @@ uint16 dptr_attr(int key) static void dptr_close_internal(dptr_struct *dptr) { - DEBUG(4,("closing dptr key %d\n",dptr->dnum)); + DEBUG(4,("closing dptr key %d\n",dptr->dnum)); - DLIST_REMOVE(dirptrs, dptr); + DLIST_REMOVE(dirptrs, dptr); - /* - * Free the dnum in the bitmap. Remember the dnum value is always - * biased by one with respect to the bitmap. - */ + /* + * Free the dnum in the bitmap. Remember the dnum value is always + * biased by one with respect to the bitmap. + */ - if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) { - DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n", + if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) { + DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n", dptr->dnum )); - } + } - bitmap_clear(dptr_bmap, dptr->dnum - 1); + bitmap_clear(dptr_bmap, dptr->dnum - 1); - if (dptr->ptr) { - CloseDir(dptr->ptr); - dptrs_open--; - } + if (dptr->ptr) { + CloseDir(dptr->ptr); + dptrs_open--; + } - /* Lanman 2 specific code */ - SAFE_FREE(dptr->wcard); - string_set(&dptr->path,""); - SAFE_FREE(dptr); + /* Lanman 2 specific code */ + SAFE_FREE(dptr->wcard); + string_set(&dptr->path,""); + SAFE_FREE(dptr); } /**************************************************************************** @@ -254,32 +254,32 @@ static void dptr_close_internal(dptr_struct *dptr) void dptr_close(int *key) { - dptr_struct *dptr; + dptr_struct *dptr; - if(*key == INVALID_DPTR_KEY) - return; + if(*key == INVALID_DPTR_KEY) + return; - /* OS/2 seems to use -1 to indicate "close all directories" */ - if (*key == -1) { - dptr_struct *next; - for(dptr = dirptrs; dptr; dptr = next) { - next = dptr->next; - dptr_close_internal(dptr); - } - *key = INVALID_DPTR_KEY; - return; - } + /* OS/2 seems to use -1 to indicate "close all directories" */ + if (*key == -1) { + dptr_struct *next; + for(dptr = dirptrs; dptr; dptr = next) { + next = dptr->next; + dptr_close_internal(dptr); + } + *key = INVALID_DPTR_KEY; + return; + } - dptr = dptr_get(*key, True); + dptr = dptr_get(*key, True); - if (!dptr) { - DEBUG(0,("Invalid key %d given to dptr_close\n", *key)); - return; - } + if (!dptr) { + DEBUG(0,("Invalid key %d given to dptr_close\n", *key)); + return; + } - dptr_close_internal(dptr); + dptr_close_internal(dptr); - *key = INVALID_DPTR_KEY; + *key = INVALID_DPTR_KEY; } /**************************************************************************** @@ -288,12 +288,12 @@ void dptr_close(int *key) void dptr_closecnum(connection_struct *conn) { - dptr_struct *dptr, *next; - for(dptr = dirptrs; dptr; dptr = next) { - next = dptr->next; - if (dptr->conn == conn) - dptr_close_internal(dptr); - } + dptr_struct *dptr, *next; + for(dptr = dirptrs; dptr; dptr = next) { + next = dptr->next; + if (dptr->conn == conn) + dptr_close_internal(dptr); + } } /**************************************************************************** @@ -302,11 +302,11 @@ void dptr_closecnum(connection_struct *conn) void dptr_idlecnum(connection_struct *conn) { - dptr_struct *dptr; - for(dptr = dirptrs; dptr; dptr = dptr->next) { - if (dptr->conn == conn && dptr->ptr) - dptr_idle(dptr); - } + dptr_struct *dptr; + for(dptr = dirptrs; dptr; dptr = dptr->next) { + if (dptr->conn == conn && dptr->ptr) + dptr_idle(dptr); + } } /**************************************************************************** @@ -315,12 +315,12 @@ void dptr_idlecnum(connection_struct *conn) void dptr_closepath(char *path,uint16 spid) { - dptr_struct *dptr, *next; - for(dptr = dirptrs; dptr; dptr = next) { - next = dptr->next; - if (spid == dptr->spid && strequal(dptr->path,path)) - dptr_close_internal(dptr); - } + dptr_struct *dptr, *next; + for(dptr = dirptrs; dptr; dptr = next) { + next = dptr->next; + if (spid == dptr->spid && strequal(dptr->path,path)) + dptr_close_internal(dptr); + } } /**************************************************************************** @@ -329,27 +329,27 @@ void dptr_closepath(char *path,uint16 spid) static BOOL start_dir(connection_struct *conn, pstring directory) { - const char *dir2; + const char *dir2; - DEBUG(5,("start_dir dir=%s\n",directory)); + DEBUG(5,("start_dir dir=%s\n",directory)); - if (!check_name(directory,conn)) - return(False); + if (!check_name(directory,conn)) + return(False); - /* use a const pointer from here on */ - dir2 = directory; + /* use a const pointer from here on */ + dir2 = directory; - if (! *dir2) - dir2 = "."; - - conn->dirptr = OpenDir(conn, directory, True); - if (conn->dirptr) { - dptrs_open++; - string_set(&conn->dirpath,directory); - return(True); - } + if (! *dir2) + dir2 = "."; + + conn->dirptr = OpenDir(conn, directory, True); + if (conn->dirptr) { + dptrs_open++; + string_set(&conn->dirpath,directory); + return(True); + } - return(False); + return(False); } /**************************************************************************** @@ -360,32 +360,32 @@ static BOOL start_dir(connection_struct *conn, pstring directory) static void dptr_close_oldest(BOOL old) { - dptr_struct *dptr; - - /* - * Go to the end of the list. - */ - for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) - ; - - if(!dptr) { - DEBUG(0,("No old dptrs available to close oldest ?\n")); - return; - } - - /* - * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that - * does not have expect_close set. If 'old' is false, close - * one of the new dnum handles. - */ - - for(; dptr; dptr = dptr->prev) { - if ((old && (dptr->dnum < 256) && !dptr->expect_close) || - (!old && (dptr->dnum > 255))) { - dptr_close_internal(dptr); - return; - } - } + dptr_struct *dptr; + + /* + * Go to the end of the list. + */ + for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) + ; + + if(!dptr) { + DEBUG(0,("No old dptrs available to close oldest ?\n")); + return; + } + + /* + * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that + * does not have expect_close set. If 'old' is false, close + * one of the new dnum handles. + */ + + for(; dptr; dptr = dptr->prev) { + if ((old && (dptr->dnum < 256) && !dptr->expect_close) || + (!old && (dptr->dnum > 255))) { + dptr_close_internal(dptr); + return; + } + } } /**************************************************************************** @@ -399,99 +399,98 @@ static void dptr_close_oldest(BOOL old) int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid) { - dptr_struct *dptr; - - if (!start_dir(conn,path)) - return(-2); /* Code to say use a unix error return code. */ + dptr_struct *dptr; - if (dptrs_open >= MAX_OPEN_DIRECTORIES) - dptr_idleoldest(); + if (!start_dir(conn,path)) + return(-2); /* Code to say use a unix error return code. */ - dptr = (dptr_struct *)malloc(sizeof(dptr_struct)); - if(!dptr) { - DEBUG(0,("malloc fail in dptr_create.\n")); - return -1; - } + if (dptrs_open >= MAX_OPEN_DIRECTORIES) + dptr_idleoldest(); - ZERO_STRUCTP(dptr); + dptr = (dptr_struct *)malloc(sizeof(dptr_struct)); + if(!dptr) { + DEBUG(0,("malloc fail in dptr_create.\n")); + return -1; + } - if(old_handle) { + ZERO_STRUCTP(dptr); - /* - * This is an old-style SMBsearch request. Ensure the - * value we return will fit in the range 1-255. - */ + if(old_handle) { - dptr->dnum = bitmap_find(dptr_bmap, 0); + /* + * This is an old-style SMBsearch request. Ensure the + * value we return will fit in the range 1-255. + */ - if(dptr->dnum == -1 || dptr->dnum > 254) { + dptr->dnum = bitmap_find(dptr_bmap, 0); - /* - * Try and close the oldest handle not marked for - * expect close in the hope that the client has - * finished with that one. - */ + if(dptr->dnum == -1 || dptr->dnum > 254) { - dptr_close_oldest(True); + /* + * Try and close the oldest handle not marked for + * expect close in the hope that the client has + * finished with that one. + */ - /* Now try again... */ - dptr->dnum = bitmap_find(dptr_bmap, 0); + dptr_close_oldest(True); - if(dptr->dnum == -1 || dptr->dnum > 254) { - DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); - SAFE_FREE(dptr); - return -1; - } - } - } else { + /* Now try again... */ + dptr->dnum = bitmap_find(dptr_bmap, 0); + if(dptr->dnum == -1 || dptr->dnum > 254) { + DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); + SAFE_FREE(dptr); + return -1; + } + } + } else { - /* - * This is a new-style trans2 request. Allocate from - * a range that will return 256 - MAX_DIRECTORY_HANDLES. - */ + /* + * This is a new-style trans2 request. Allocate from + * a range that will return 256 - MAX_DIRECTORY_HANDLES. + */ - dptr->dnum = bitmap_find(dptr_bmap, 255); + dptr->dnum = bitmap_find(dptr_bmap, 255); - if(dptr->dnum == -1 || dptr->dnum < 255) { + if(dptr->dnum == -1 || dptr->dnum < 255) { - /* - * Try and close the oldest handle close in the hope that - * the client has finished with that one. This will only - * happen in the case of the Win98 client bug where it leaks - * directory handles. - */ + /* + * Try and close the oldest handle close in the hope that + * the client has finished with that one. This will only + * happen in the case of the Win98 client bug where it leaks + * directory handles. + */ - dptr_close_oldest(False); + dptr_close_oldest(False); - /* Now try again... */ - dptr->dnum = bitmap_find(dptr_bmap, 255); + /* Now try again... */ + dptr->dnum = bitmap_find(dptr_bmap, 255); - if(dptr->dnum == -1 || dptr->dnum < 255) { - DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); - SAFE_FREE(dptr); - return -1; - } - } - } + if(dptr->dnum == -1 || dptr->dnum < 255) { + DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); + SAFE_FREE(dptr); + return -1; + } + } + } - bitmap_set(dptr_bmap, dptr->dnum); + bitmap_set(dptr_bmap, dptr->dnum); - dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ + dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ - dptr->ptr = conn->dirptr; - string_set(&dptr->path,path); - dptr->conn = conn; - dptr->spid = spid; - dptr->expect_close = expect_close; - dptr->wcard = NULL; /* Only used in lanman2 searches */ - dptr->attr = 0; /* Only used in lanman2 searches */ + dptr->ptr = conn->dirptr; + string_set(&dptr->path,path); + dptr->conn = conn; + dptr->spid = spid; + dptr->expect_close = expect_close; + dptr->wcard = NULL; /* Only used in lanman2 searches */ + dptr->attr = 0; /* Only used in lanman2 searches */ - DLIST_ADD(dirptrs, dptr); + DLIST_ADD(dirptrs, dptr); - DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", - dptr->dnum,path,expect_close)); + DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", + dptr->dnum,path,expect_close)); - return(dptr->dnum); + return(dptr->dnum); } /**************************************************************************** @@ -500,19 +499,19 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp BOOL dptr_fill(char *buf1,unsigned int key) { - unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_ptr(key); - uint32 offset; - if (!p) { - DEBUG(1,("filling null dirptr %d\n",key)); - return(False); - } - offset = TellDir(p); - DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, - (long)p,(int)offset)); - buf[0] = key; - SIVAL(buf,1,offset | DPTR_MASK); - return(True); + unsigned char *buf = (unsigned char *)buf1; + void *p = dptr_ptr(key); + uint32 offset; + if (!p) { + DEBUG(1,("filling null dirptr %d\n",key)); + return(False); + } + offset = TellDir(p); + DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, + (long)p,(int)offset)); + buf[0] = key; + SIVAL(buf,1,offset | DPTR_MASK); + return(True); } /**************************************************************************** @@ -521,19 +520,20 @@ BOOL dptr_fill(char *buf1,unsigned int key) void *dptr_fetch(char *buf,int *num) { - unsigned int key = *(unsigned char *)buf; - void *p = dptr_ptr(key); - uint32 offset; - if (!p) { - DEBUG(3,("fetched null dirptr %d\n",key)); - return(NULL); - } - *num = key; - offset = IVAL(buf,1)&~DPTR_MASK; - SeekDir(p,offset); - DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", - key,dptr_path(key),offset)); - return(p); + unsigned int key = *(unsigned char *)buf; + void *p = dptr_ptr(key); + uint32 offset; + + if (!p) { + DEBUG(3,("fetched null dirptr %d\n",key)); + return(NULL); + } + *num = key; + offset = IVAL(buf,1)&~DPTR_MASK; + SeekDir(p,offset); + DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", + key,dptr_path(key),offset)); + return(p); } /**************************************************************************** @@ -542,14 +542,14 @@ void *dptr_fetch(char *buf,int *num) void *dptr_fetch_lanman2(int dptr_num) { - void *p = dptr_ptr(dptr_num); - - if (!p) { - DEBUG(3,("fetched null dirptr %d\n",dptr_num)); - return(NULL); - } - DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); - return(p); + void *p = dptr_ptr(dptr_num); + + if (!p) { + DEBUG(3,("fetched null dirptr %d\n",dptr_num)); + return(NULL); + } + DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); + return(p); } /**************************************************************************** @@ -591,96 +591,88 @@ static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mas BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) { - char *dname; - BOOL found = False; - SMB_STRUCT_STAT sbuf; - pstring path; - pstring pathreal; - BOOL isrootdir; - pstring filename; - BOOL needslash; - - *path = *pathreal = *filename = 0; - - isrootdir = (strequal(conn->dirpath,"./") || - strequal(conn->dirpath,".") || - strequal(conn->dirpath,"/")); + char *dname; + BOOL found = False; + SMB_STRUCT_STAT sbuf; + pstring path; + pstring pathreal; + BOOL isrootdir; + pstring filename; + BOOL needslash; + + *path = *pathreal = *filename = 0; + + isrootdir = (strequal(conn->dirpath,"./") || + strequal(conn->dirpath,".") || + strequal(conn->dirpath,"/")); - needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); + needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - if (!conn->dirptr) - return(False); + if (!conn->dirptr) + return(False); - while (!found) - { - dname = ReadDirName(conn->dirptr); + while (!found) { + dname = ReadDirName(conn->dirptr); - DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n", - (long)conn->dirptr,TellDir(conn->dirptr))); + DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n", + (long)conn->dirptr,TellDir(conn->dirptr))); - if (dname == NULL) - return(False); + if (dname == NULL) + return(False); - pstrcpy(filename,dname); - - /* notice the special *.* handling. This appears to be the only difference - between the wildcard handling in this routine and in the trans2 routines. - see masktest for a demo - */ - if ((strcmp(mask,"*.*") == 0) || - mask_match(filename,mask,False) || - mangle_mask_match(conn,filename,mask)) - { - if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) - continue; - - if (!mangle_is_8_3(filename, False)) { - mangle_map(filename,True,False,SNUM(conn)); - } - - pstrcpy(fname,filename); - *path = 0; - pstrcpy(path,conn->dirpath); - if(needslash) - pstrcat(path,"/"); - pstrcpy(pathreal,path); - pstrcat(path,fname); - pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0) - { - DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); - continue; - } + pstrcpy(filename,dname); + + /* notice the special *.* handling. This appears to be the only difference + between the wildcard handling in this routine and in the trans2 routines. + see masktest for a demo + */ + if ((strcmp(mask,"*.*") == 0) || + mask_match(filename,mask,False) || + mangle_mask_match(conn,filename,mask)) { + if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) + continue; + + if (!mangle_is_8_3(filename, False)) + mangle_map(filename,True,False,SNUM(conn)); + + pstrcpy(fname,filename); + *path = 0; + pstrcpy(path,conn->dirpath); + if(needslash) + pstrcat(path,"/"); + pstrcpy(pathreal,path); + pstrcat(path,fname); + pstrcat(pathreal,dname); + if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0) { + DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); + continue; + } - *mode = dos_mode(conn,pathreal,&sbuf); + *mode = dos_mode(conn,pathreal,&sbuf); - if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) - { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); - continue; - } + if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) { + DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); + continue; + } - *size = sbuf.st_size; - *date = sbuf.st_mtime; + *size = sbuf.st_size; + *date = sbuf.st_mtime; - DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); - - found = True; - } - } - - return(found); -} + DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); + found = True; + } + } + return(found); +} -typedef struct -{ - int pos; - int numentries; - int mallocsize; - char *data; - char *current; +typedef struct { + int pos; + int numentries; + int mallocsize; + char *data; + char *current; } Dir; /******************************************************************* @@ -718,15 +710,14 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unix_mode(conn,aRONLY|aDIR, name), &smb_action); else - fsp = open_file_shared1(conn, name, pst, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + fsp = open_file_stat(conn, name, pst); if (!fsp) return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); - close_file(fsp, False); + close_file(fsp, True); /* No access if SD get failed. */ if (!sd_size) @@ -933,9 +924,10 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) void CloseDir(void *p) { - if (!p) return; - SAFE_FREE(((Dir *)p)->data); - SAFE_FREE(p); + if (!p) + return; + SAFE_FREE(((Dir *)p)->data); + SAFE_FREE(p); } /******************************************************************* @@ -944,37 +936,39 @@ void CloseDir(void *p) char *ReadDirName(void *p) { - char *ret; - Dir *dirp = (Dir *)p; + char *ret; + Dir *dirp = (Dir *)p; - if (!dirp || !dirp->current || dirp->pos >= dirp->numentries) return(NULL); + if (!dirp || !dirp->current || dirp->pos >= dirp->numentries) + return(NULL); - ret = dirp->current; - dirp->current = skip_string(dirp->current,1); - dirp->pos++; + ret = dirp->current; + dirp->current = skip_string(dirp->current,1); + dirp->pos++; - return(ret); + return(ret); } - /******************************************************************* Seek a dir. ********************************************************************/ BOOL SeekDir(void *p,int pos) { - Dir *dirp = (Dir *)p; + Dir *dirp = (Dir *)p; - if (!dirp) return(False); + if (!dirp) + return(False); - if (pos < dirp->pos) { - dirp->current = dirp->data; - dirp->pos = 0; - } + if (pos < dirp->pos) { + dirp->current = dirp->data; + dirp->pos = 0; + } - while (dirp->pos < pos && ReadDirName(p)) ; + while (dirp->pos < pos && ReadDirName(p)) + ; - return(dirp->pos == pos); + return (dirp->pos == pos); } /******************************************************************* @@ -983,11 +977,12 @@ BOOL SeekDir(void *p,int pos) int TellDir(void *p) { - Dir *dirp = (Dir *)p; + Dir *dirp = (Dir *)p; - if (!dirp) return(-1); + if (!dirp) + return(-1); - return(dirp->pos); + return(dirp->pos); } /******************************************************************************* @@ -996,11 +991,11 @@ int TellDir(void *p) ********************************************************************************/ typedef struct { - ubi_dlNode node; - char *path; - char *name; - char *dname; - int snum; + ubi_dlNode node; + char *path; + char *name; + char *dname; + int snum; } dir_cache_entry; static ubi_dlNewList( dir_cache ); @@ -1016,36 +1011,36 @@ static ubi_dlNewList( dir_cache ); void DirCacheAdd( const char *path, char *name, char *dname, int snum ) { - int pathlen; - int namelen; - dir_cache_entry *entry; - - /* Allocate the structure & string space in one go so that it can be freed - * in one call to free(). - */ - pathlen = strlen( path ) +1; /* Bytes required to store path (with nul). */ - namelen = strlen( name ) +1; /* Bytes required to store name (with nul). */ - entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry ) - + pathlen - + namelen - + strlen( dname ) +1 ); - if( NULL == entry ) /* Not adding to the cache is not fatal, */ - return; /* so just return as if nothing happened. */ - - /* Set pointers correctly and load values. */ - entry->path = pstrcpy( (char *)&entry[1], path); - entry->name = pstrcpy( &(entry->path[pathlen]), name); - entry->dname = pstrcpy( &(entry->name[namelen]), dname); - entry->snum = snum; - - /* Add the new entry to the linked list. */ - (void)ubi_dlAddHead( dir_cache, entry ); - DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) ); - - /* Free excess cache entries. */ - while( DIRCACHESIZE < dir_cache->count ) - safe_free( ubi_dlRemTail( dir_cache ) ); + int pathlen; + int namelen; + dir_cache_entry *entry; + /* + * Allocate the structure & string space in one go so that it can be freed + * in one call to free(). + */ + pathlen = strlen(path) + 1; /* Bytes required to store path (with nul). */ + namelen = strlen(name) + 1; /* Bytes required to store name (with nul). */ + entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry ) + + pathlen + + namelen + + strlen( dname ) +1 ); + if( NULL == entry ) /* Not adding to the cache is not fatal, */ + return; /* so just return as if nothing happened. */ + + /* Set pointers correctly and load values. */ + entry->path = pstrcpy( (char *)&entry[1], path); + entry->name = pstrcpy( &(entry->path[pathlen]), name); + entry->dname = pstrcpy( &(entry->name[namelen]), dname); + entry->snum = snum; + + /* Add the new entry to the linked list. */ + (void)ubi_dlAddHead( dir_cache, entry ); + DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) ); + + /* Free excess cache entries. */ + while( DIRCACHESIZE < dir_cache->count ) + safe_free( ubi_dlRemTail( dir_cache ) ); } /***************************************************************************** @@ -1063,22 +1058,20 @@ void DirCacheAdd( const char *path, char *name, char *dname, int snum ) char *DirCacheCheck( const char *path, const char *name, int snum ) { - dir_cache_entry *entry; - - for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); - NULL != entry; - entry = (dir_cache_entry *)ubi_dlNext( entry ) ) - { - if( entry->snum == snum - && 0 == strcmp( name, entry->name ) - && 0 == strcmp( path, entry->path ) ) - { - DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); - return( entry->dname ); - } - } - - return(NULL); + dir_cache_entry *entry; + + for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); + NULL != entry; + entry = (dir_cache_entry *)ubi_dlNext( entry ) ) { + if( entry->snum == snum + && 0 == strcmp( name, entry->name ) + && 0 == strcmp( path, entry->path ) ) { + DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); + return( entry->dname ); + } + } + + return(NULL); } /***************************************************************************** diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cee2b37184..d5521f7f47 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -228,6 +228,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; + fsp->is_stat = False; fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); @@ -1255,6 +1256,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; + fsp->is_stat = False; fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); @@ -1271,118 +1273,62 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return fsp; } -#if 0 -Old code - I have replaced with correct desired_access checking. JRA. - -/******************************************************************* - Check if the share mode on a file allows it to be deleted or unlinked. - Return True if sharing doesn't prevent the operation. -********************************************************************/ +/**************************************************************************** + Open a pseudo-file (no locking checks - a 'stat' open). +****************************************************************************/ -BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) +files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) { - int i; - int ret = False; - share_mode_entry *old_shares = 0; - int num_share_modes; - SMB_STRUCT_STAT sbuf; - pid_t pid = sys_getpid(); - SMB_DEV_T dev; - SMB_INO_T inode; - - if (vfs_stat(conn,fname,&sbuf) == -1) - return(True); - - dev = sbuf.st_dev; - inode = sbuf.st_ino; - - lock_share_entry(conn, dev, inode); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - - /* - * Check if the share modes will give us access. - */ - - if(num_share_modes != 0) { - BOOL broke_oplock; - - do { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * Break oplocks before checking share modes. See comment in - * open_file_shared for details. - * Check if someone has an oplock on this file. If so we must - * break it before continuing. - */ - if(BATCH_OPLOCK_TYPE(share_entry->op_type)) { - - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + extern struct current_user current_user; + BOOL got_stat = False; + files_struct *fsp = NULL; - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode); + if (!VALID_STAT(*psbuf)) + return NULL; - if(request_oplock_break(share_entry) == False) { - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); + /* Can't 'stat' open directories. */ + if(S_ISDIR(psbuf->st_mode)) + return NULL; - SAFE_FREE(old_shares); - return False; - } - lock_share_entry(conn, dev, inode); - broke_oplock = True; - break; - } + fsp = file_new(conn); + if(!fsp) + return NULL; - /* - * If this is a delete request and ALLOW_SHARE_DELETE is set then allow - * this to proceed. This takes precedence over share modes. - */ - - if(!rename_op && GET_ALLOW_SHARE_DELETE(share_entry->share_mode)) - continue; - - /* - * Someone else has a share lock on it, check to see - * if we can too. - */ - if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || - (share_entry->pid != pid)) - goto free_and_exit; - - } /* end for */ + fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - if(broke_oplock) { - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - } - } while(broke_oplock); - } + DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); /* - * XXXX exactly what share mode combinations should be allowed for - * deleting/renaming? + * Setup the files_struct for it. */ - + + fsp->mode = psbuf->st_mode; /* - * If we got here then either there were no share modes or - * all share modes were DENY_DOS and the pid == getpid() or - * delete access was requested and all share modes had the - * ALLOW_SHARE_DELETE bit set (takes precedence over other - * share modes). + * Don't store dev or inode, we don't want any iterator + * to see this. */ + fsp->inode = (SMB_INO_T)0; + fsp->dev = (SMB_DEV_T)0; + fsp->size = psbuf->st_size; + fsp->vuid = current_user.vuid; + fsp->pos = -1; + fsp->can_lock = False; + fsp->can_read = False; + fsp->can_write = False; + fsp->share_mode = 0; + fsp->desired_access = 0; + fsp->print_file = False; + fsp->modified = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->is_directory = False; + fsp->is_stat = True; + fsp->directory_delete_on_close = False; + fsp->conn = conn; + string_set(&fsp->fsp_name,fname); - ret = True; - -free_and_exit: + conn->num_files_open++; - unlock_share_entry(conn, dev, inode); - SAFE_FREE(old_shares); - return(ret); + return fsp; } -#endif -- cgit From e3ed8eaa2fd47a72c7b89d769ee594f238130ff7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 4 Jan 2003 08:45:17 +0000 Subject: Merge from HEAD - move user password changes into the NTSTATUS era, and add suppport for the 'min password age' and 'min passwd len' concepts. (This used to be commit d9417b08d1b649e598b44135bc57008f4e4f7769) --- source3/smbd/chgpasswd.c | 112 +++++++++++++++++++++++++++++++++++------------ source3/smbd/lanman.c | 22 +--------- 2 files changed, 87 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index c2a82d1eb6..80b412af49 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Bartlett 2001-2002 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 @@ -50,7 +51,7 @@ extern struct passdb_ops pdb_ops; -static BOOL check_oem_password(const char *user, +static NTSTATUS check_oem_password(const char *user, uchar * lmdata, const uchar * lmhash, const uchar * ntdata, const uchar * nthash, SAM_ACCOUNT **hnd, char *new_passwd, @@ -478,6 +479,10 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL DEBUG(1, ("NULL username specfied to chgpasswd()!\n")); } + if (!oldpass) { + oldpass = ""; + } + DEBUG(3, ("Password change for user: %s\n", name)); #if DEBUG_PASSWORD @@ -732,15 +737,19 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, /*********************************************************** Code to check and change the OEM hashed password. ************************************************************/ -BOOL pass_oem_change(char *user, - uchar * lmdata, uchar * lmhash, - uchar * ntdata, uchar * nthash) +NTSTATUS pass_oem_change(char *user, + uchar * lmdata, uchar * lmhash, + uchar * ntdata, uchar * nthash) { fstring new_passwd; const char *unix_user; SAM_ACCOUNT *sampass = NULL; - BOOL ret = check_oem_password(user, lmdata, lmhash, ntdata, nthash, - &sampass, new_passwd, sizeof(new_passwd)); + NTSTATUS nt_status + = check_oem_password(user, lmdata, lmhash, ntdata, nthash, + &sampass, new_passwd, sizeof(new_passwd)); + + if (NT_STATUS_IS_OK(nt_status)) + return nt_status; /* * At this point we have the new case-sensitive plaintext @@ -753,17 +762,13 @@ BOOL pass_oem_change(char *user, unix_user = pdb_get_username(sampass); - if ((ret) && (unix_user) && (*unix_user) && lp_unix_password_sync()) - ret = chgpasswd(unix_user, "", new_passwd, True); - - if (ret) - ret = change_oem_password(sampass, new_passwd); + nt_status = change_oem_password(sampass, NULL, new_passwd); memset(new_passwd, 0, sizeof(new_passwd)); pdb_free_sam(&sampass); - return ret; + return nt_status; } /*********************************************************** @@ -773,7 +778,7 @@ BOOL pass_oem_change(char *user, but does use the lm OEM password to check the nt hashed-hash. ************************************************************/ -static BOOL check_oem_password(const char *user, +static NTSTATUS check_oem_password(const char *user, uchar * lmdata, const uchar * lmhash, const uchar * ntdata, const uchar * nthash, SAM_ACCOUNT **hnd, char *new_passwd, @@ -802,7 +807,11 @@ static BOOL check_oem_password(const char *user, if (ret == False) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); - return False; + return NT_STATUS_WRONG_PASSWORD; + /* + TODO: check what Win2k returns for this: + return NT_STATUS_NO_SUCH_USER; + */ } *hnd = sampass; @@ -811,7 +820,7 @@ static BOOL check_oem_password(const char *user, if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); - return False; + return NT_STATUS_ACCOUNT_DISABLED; } /* construct a null password (in case one is needed */ @@ -827,14 +836,14 @@ static BOOL check_oem_password(const char *user, if (lanman_pw == NULL) { if (!(acct_ctrl & ACB_PWNOTREQ)) { DEBUG(0,("check_oem_password: no lanman password !\n")); - return False; + return NT_STATUS_WRONG_PASSWORD; } } if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) { if (!(acct_ctrl & ACB_PWNOTREQ)) { DEBUG(0,("check_oem_password: no ntlm password !\n")); - return False; + return NT_STATUS_WRONG_PASSWORD; } } @@ -851,7 +860,7 @@ static BOOL check_oem_password(const char *user, new_pw_len = IVAL(lmdata, 512); if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); - return False; + return NT_STATUS_WRONG_PASSWORD; } if (nt_pass_set) { @@ -884,14 +893,14 @@ static BOOL check_oem_password(const char *user, if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); - return False; + return NT_STATUS_WRONG_PASSWORD; } #ifdef DEBUG_PASSWORD DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); #endif - return True; + return NT_STATUS_OK; } /* @@ -904,31 +913,76 @@ static BOOL check_oem_password(const char *user, if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); - return False; + return NT_STATUS_WRONG_PASSWORD; } if (memcmp(nt_pw, unenc_old_ntpw, 16)) { DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); - return False; + return NT_STATUS_WRONG_PASSWORD; } #ifdef DEBUG_PASSWORD DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); #endif - return True; + return NT_STATUS_OK; } /*********************************************************** Code to change the oem password. Changes both the lanman - and NT hashes. + and NT hashes. Old_passwd is almost always NULL. ************************************************************/ -BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd) +NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd) { BOOL ret; + uint32 min_len; + + if (time(NULL) < pdb_get_pass_can_change_time(hnd)) { + DEBUG(1, ("user %s cannot change password now, must wait until %s\n", + pdb_get_username(hnd), http_timestring(pdb_get_pass_can_change_time(hnd)))); + return NT_STATUS_PASSWORD_RESTRICTION; + } + + if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (strlen(new_passwd) < min_len)) { + DEBUG(1, ("user %s cannot change password - password too short\n", + pdb_get_username(hnd))); + DEBUGADD(1, (" account policy min password len = %d\n", min_len)); + return NT_STATUS_PASSWORD_RESTRICTION; +/* return NT_STATUS_PWD_TOO_SHORT; */ + } + + /* Take the passed information and test it for minimum criteria */ + /* Minimum password length */ + if (strlen(new_passwd) < lp_min_passwd_length()) { + /* too short, must be at least MINPASSWDLENGTH */ + DEBUG(1, ("Password Change: user %s, New password is shorter than minimum password length = %d\n", + pdb_get_username(hnd), lp_min_passwd_length())); + return NT_STATUS_PASSWORD_RESTRICTION; +/* return NT_STATUS_PWD_TOO_SHORT; */ + } + + /* TODO: Add cracklib support here */ + + /* + * If unix password sync was requested, attempt to change + * the /etc/passwd database first. Return failure if this cannot + * be done. + * + * This occurs before the oem change, becouse we don't want to + * update it if chgpasswd failed. + * + * Conditional on lp_unix_password_sync() becouse we don't want + * to touch the unix db unless we have admin permission. + */ + + if(lp_unix_password_sync() && IS_SAM_UNIX_USER(hnd) + && !chgpasswd(pdb_get_username(hnd), + old_passwd, new_passwd, False)) { + return NT_STATUS_ACCESS_DENIED; + } if (!pdb_set_plaintext_passwd (hnd, new_passwd)) { - return False; + return NT_STATUS_ACCESS_DENIED; } /* Now write it into the file. */ @@ -936,7 +990,11 @@ BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd) ret = pdb_update_sam_account (hnd); unbecome_root(); - return ret; + if (!ret) { + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7a667c378d..61288e0167 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1930,25 +1930,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - /* - * If unix password sync was requested, attempt to change - * the /etc/passwd database first. Return failure if this cannot - * be done. - * - * This occurs before the oem change, becouse we don't want to - * update it if chgpasswd failed. - * - * Conditional on lp_unix_password_sync() becouse we don't want - * to touch the unix db unless we have admin permission. - */ - - if(lp_unix_password_sync() && IS_SAM_UNIX_USER(server_info->sam_account) - && !chgpasswd(pdb_get_username(server_info->sam_account), - pass1,pass2,False)) { - SSVAL(*rparam,0,NERR_badpass); - } - - if (change_oem_password(server_info->sam_account,pass2)) + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) { SSVAL(*rparam,0,NERR_Success); } @@ -2031,7 +2013,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * (void)map_username(user); - if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)) + if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) { SSVAL(*rparam,0,NERR_Success); } -- cgit From 6233651ca12946c6a17632517c16bccf92b69b4a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 5 Jan 2003 05:11:02 +0000 Subject: Merge from HEAD - get the test the right way around, so that we can change passwords over RAP again. (found by the build farm) Andrew Bartlett (This used to be commit 4b1a316e79ba87cb35a019a2089e6469ad9a3c3e) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 80b412af49..a9729da799 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -748,7 +748,7 @@ NTSTATUS pass_oem_change(char *user, = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); - if (NT_STATUS_IS_OK(nt_status)) + if (!NT_STATUS_IS_OK(nt_status)) return nt_status; /* -- cgit From 0ba7c143b32da62ee83e5757f6933ab8be000ffd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 6 Jan 2003 07:40:39 +0000 Subject: Merge from HEAD - handle VFS module load failures, change some error returns to avoid sending NT_STATUS_UNSUCCESSFUL. Andrew Bartlett (This used to be commit 7b95151ddcb1e4abd592e72d509ec24c5d160511) --- source3/smbd/service.c | 6 +++--- source3/smbd/vfs.c | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d00c908a1a..dd427c2ae8 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -569,7 +569,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (!smbd_vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; + *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -598,7 +598,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(1,("root preexec gave %d - failing connection\n", ret)); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; + *status = NT_STATUS_ACCESS_DENIED; return NULL; } } @@ -627,7 +627,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; + *status = NT_STATUS_ACCESS_DENIED; return NULL; } } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7b8d9d7e9e..de7b90df72 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -164,6 +164,7 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) if (init_fptr == NULL) { DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object)); + sys_dlclose(conn->vfs_private->handle); return False; } @@ -171,12 +172,14 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) { DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object)); + sys_dlclose(conn->vfs_private->handle); return False; } if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) { DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", vfs_version, SMB_VFS_INTERFACE_VERSION )); + sys_dlclose(conn->vfs_private->handle); return False; } @@ -184,6 +187,7 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version )); + sys_dlclose(conn->vfs_private->handle); return False; } @@ -249,6 +253,8 @@ BOOL smbd_vfs_init(connection_struct *conn) DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module)); string_free(&vfsobj); SAFE_FREE(vfs_module); + DLIST_REMOVE(conn->vfs_private, handle); + SAFE_FREE(handle); return False; } SAFE_FREE(vfs_module); -- cgit From ebf35917bc0d21d8dcf7b9f0119762e1350382ff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Jan 2003 21:48:46 +0000 Subject: Fix memory leaks in pdb_ code. Jeremy. (This used to be commit 44ab8dc55e3c37a0fc01529084bcacfc84c1dcee) --- source3/smbd/chgpasswd.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a9729da799..aad62d8a98 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -778,6 +778,7 @@ NTSTATUS pass_oem_change(char *user, but does use the lm OEM password to check the nt hashed-hash. ************************************************************/ + static NTSTATUS check_oem_password(const char *user, uchar * lmdata, const uchar * lmhash, const uchar * ntdata, const uchar * nthash, @@ -807,6 +808,7 @@ static NTSTATUS check_oem_password(const char *user, if (ret == False) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; /* TODO: check what Win2k returns for this: @@ -820,6 +822,7 @@ static NTSTATUS check_oem_password(const char *user, if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + pdb_free_sam(&sampass); return NT_STATUS_ACCOUNT_DISABLED; } @@ -830,12 +833,13 @@ static NTSTATUS check_oem_password(const char *user, /* save pointers to passwords so we don't have to keep looking them up */ lanman_pw = pdb_get_lanman_passwd(sampass); - nt_pw = pdb_get_nt_passwd (sampass); + nt_pw = pdb_get_nt_passwd(sampass); /* check for null passwords */ if (lanman_pw == NULL) { if (!(acct_ctrl & ACB_PWNOTREQ)) { DEBUG(0,("check_oem_password: no lanman password !\n")); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } } @@ -843,6 +847,7 @@ static NTSTATUS check_oem_password(const char *user, if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) { if (!(acct_ctrl & ACB_PWNOTREQ)) { DEBUG(0,("check_oem_password: no ntlm password !\n")); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } } @@ -860,6 +865,7 @@ static NTSTATUS check_oem_password(const char *user, new_pw_len = IVAL(lmdata, 512); if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -893,6 +899,7 @@ static NTSTATUS check_oem_password(const char *user, if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -900,6 +907,7 @@ static NTSTATUS check_oem_password(const char *user, DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); #endif + pdb_free_sam(&sampass); return NT_STATUS_OK; } @@ -913,17 +921,21 @@ static NTSTATUS check_oem_password(const char *user, if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } if (memcmp(nt_pw, unenc_old_ntpw, 16)) { DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } #ifdef DEBUG_PASSWORD DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); #endif + + pdb_free_sam(&sampass); return NT_STATUS_OK; } -- cgit From 7f4177aa9e85c5d801aefabf39e08e40bce04f7d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jan 2003 02:09:18 +0000 Subject: Fix open problem with changing attributes on an existing file - based on work by . Jeremy. (This used to be commit 1cff725e37d04e25d2cd5523683b35c82d5040fa) --- source3/smbd/open.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d5521f7f47..5c3359fc6b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -698,7 +698,8 @@ static void kernel_flock(files_struct *fsp, int deny_mode) } -static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, mode_t new_mode) +static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, + mode_t new_mode, mode_t *returned_mode) { uint32 old_dos_mode, new_dos_mode; SMB_STRUCT_STAT sbuf; @@ -711,22 +712,33 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex sbuf.st_mode = new_mode; new_dos_mode = dos_mode(conn, path, &sbuf); + /* + * We only set returned mode to be the same as new_mode if + * the file attributes need to be changed. + */ + + *returned_mode = (mode_t)0; + /* If we're mapping SYSTEM and HIDDEN ensure they match. */ if (lp_map_system(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) return False; + if (!(old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && (new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) + *returned_mode = new_mode; } if (lp_map_hidden(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; + if (!(old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && (new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) + *returned_mode = new_mode; } return True; } /**************************************************************************** - Open a file with a share mode. On output from this open we are guarenteeing - that + Open a file with a share mode. ****************************************************************************/ + files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) @@ -736,9 +748,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S } /**************************************************************************** - Open a file with a share mode. On output from this open we are guarenteeing - that + Open a file with a share mode. ****************************************************************************/ + files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, int share_mode,int ofun, mode_t mode,int oplock_request, @@ -760,6 +772,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ files_struct *fsp = NULL; int open_mode=0; uint16 port = 0; + mode_t new_mode = (mode_t)0; if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are @@ -819,7 +832,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* We only care about matching attributes on file exists and truncate. */ if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { - if (!open_match_attributes(conn, fname, psbuf->st_mode, mode)) { + if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", fname, psbuf->st_mode, mode )); file_free(fsp); @@ -1089,11 +1102,36 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ + + } else if (new_mode) { + + int ret = -1; + + /* Attributes need changing. File already existed. */ + + if (conn->vfs_ops.fchmod_acl != NULL) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + ret = conn->vfs_ops.fchmod_acl(fsp, fsp->fd, new_mode); + + if (ret == -1 && errno == ENOSYS) { + errno = saved_errno; /* Ignore ENOSYS */ + } else { + DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", + fname, (int)new_mode)); + ret = 0; /* Don't do the fchmod below. */ + } + } + + if ((ret == -1) && (conn->vfs_ops.fchmod(fsp, fsp->fd, new_mode) == -1)) + DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", + fname, (int)new_mode)); } - + unlock_share_entry_fsp(fsp); conn->num_files_open++; @@ -1281,7 +1319,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) { extern struct current_user current_user; - BOOL got_stat = False; files_struct *fsp = NULL; if (!VALID_STAT(*psbuf)) -- cgit From 82ecfb97475e8c7a524acc43f8232a8dcd3c120c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jan 2003 07:02:21 +0000 Subject: Fix erroneous free of SAM_ACCOUNT (make clearer when allocated memory is being returned). Jeremy. (This used to be commit 48774e77ac8e43682f216dea970f8860cecb3818) --- source3/smbd/chgpasswd.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index aad62d8a98..cc130d16c2 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -800,6 +800,8 @@ static NTSTATUS check_oem_password(const char *user, BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); + *hnd = NULL; + pdb_init_sam(&sampass); become_root(); @@ -816,8 +818,6 @@ static NTSTATUS check_oem_password(const char *user, */ } - *hnd = sampass; - acct_ctrl = pdb_get_acct_ctrl(sampass); if (acct_ctrl & ACB_DISABLED) { @@ -888,16 +888,14 @@ static NTSTATUS check_oem_password(const char *user, nt_lm_owf_gen(new_passwd, new_ntp16, new_p16); - if (!nt_pass_set) - { + if (!nt_pass_set) { /* * Now use new_p16 as the key to see if the old * password matches. */ D_P16(new_p16, lmhash, unenc_old_pw); - if (memcmp(lanman_pw, unenc_old_pw, 16)) - { + if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; @@ -907,7 +905,7 @@ static NTSTATUS check_oem_password(const char *user, DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); #endif - pdb_free_sam(&sampass); + *hnd = sampass; return NT_STATUS_OK; } @@ -918,15 +916,13 @@ static NTSTATUS check_oem_password(const char *user, D_P16(new_ntp16, lmhash, unenc_old_pw); D_P16(new_ntp16, nthash, unenc_old_ntpw); - if (memcmp(lanman_pw, unenc_old_pw, 16)) - { + if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } - if (memcmp(nt_pw, unenc_old_ntpw, 16)) - { + if (memcmp(nt_pw, unenc_old_ntpw, 16)) { DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; @@ -935,7 +931,7 @@ static NTSTATUS check_oem_password(const char *user, DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); #endif - pdb_free_sam(&sampass); + *hnd = sampass; return NT_STATUS_OK; } @@ -1008,6 +1004,3 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw return NT_STATUS_OK; } - - - -- cgit From 38aee23f807dad93fb832d97deac57d528a2a175 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jan 2003 21:42:53 +0000 Subject: Ensure we don't get an invalid number for total smbd's if the tdb update fails. Jeremy. (This used to be commit e0482594724ebba801bbc39a90a73fafa54f8b9e) --- source3/smbd/process.c | 6 +----- source3/smbd/server.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7421c16b40..03b1e007ba 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -809,17 +809,13 @@ static BOOL smbd_process_limit(void) * subtracts one. */ - total_smbds = 1; /* In case we need to create the entry. */ - if (!conn_tdb_ctx()) { DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \ set. Ignoring max smbd restriction.\n")); return False; } - if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1) - return True; - + total_smbds = increment_smbd_process_count(); return total_smbds > lp_max_smbd_processes(); } else diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c5474a46b8..6ed2cdac96 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -526,12 +526,28 @@ static BOOL dump_core(void) update the current smbd process count ****************************************************************************/ -static void decrement_smbd_process_count(void) +static BOOL process_count_update_successful = False; + +int32 increment_smbd_process_count(void) { int32 total_smbds; if (lp_max_smbd_processes()) { total_smbds = 0; + if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1) == -1) + return 1; + process_count_update_successful = True; + return total_smbds + 1; + } + return 1; +} + +static void decrement_smbd_process_count(void) +{ + int32 total_smbds; + + if (lp_max_smbd_processes() && process_count_update_successful) { + total_smbds = 1; tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1); } } -- cgit From a2cce2f0757413a117f6f69568c0b392ecf3079c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jan 2003 23:49:21 +0000 Subject: Ensure we return disk full by default on short writes. Jeremy. (This used to be commit 2a974bc284b9d193c24972d073b966eb9b3b3ad0) --- source3/smbd/reply.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index beccc1bba6..ef5a090243 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2011,7 +2011,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwriteunlock); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRHRD,ERRdiskfull)); } status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, @@ -2092,7 +2092,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwrite); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRHRD,ERRdiskfull)); } outsize = set_message(outbuf,1,0,True); @@ -2187,7 +2187,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwriteX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRHRD,ERRdiskfull)); } set_message(outbuf,6,0,True); @@ -2465,9 +2465,9 @@ int reply_writeclose(connection_struct *conn, fsp->fnum, (int)numtowrite, (int)nwritten, conn->num_files_open)); - if (nwritten <= 0) { + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwriteclose); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRHRD,ERRdiskfull)); } if(close_err != 0) { @@ -2791,7 +2791,7 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ if (write_file(fsp,data,-1,numtowrite) != numtowrite) { END_PROFILE(SMBsplwr); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRHRD,ERRdiskfull)); } DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); -- cgit From 195ec103d6c0f8470141014dbfe365996fa0f4a7 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 9 Jan 2003 06:26:04 +0000 Subject: Moved smbd process counting functions from smbd/server.c to smbd/process.c so that bin/vfstest can link. merge from head (This used to be commit 9151cd7d64a1ee1277cbcfb3e7ed61c32c1037cf) --- source3/smbd/process.c | 26 ++++++++++++++++++++++++++ source3/smbd/server.c | 30 ------------------------------ 2 files changed, 26 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 03b1e007ba..06cedea573 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -799,6 +799,32 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) 'hard' limit Samba overhead on resource constrained systems. ****************************************************************************/ +static BOOL process_count_update_successful = False; + +static int32 increment_smbd_process_count(void) +{ + int32 total_smbds; + + if (lp_max_smbd_processes()) { + total_smbds = 0; + if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1) == -1) + return 1; + process_count_update_successful = True; + return total_smbds + 1; + } + return 1; +} + +void decrement_smbd_process_count(void) +{ + int32 total_smbds; + + if (lp_max_smbd_processes() && process_count_update_successful) { + total_smbds = 1; + tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1); + } +} + static BOOL smbd_process_limit(void) { int32 total_smbds; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6ed2cdac96..0b2fa2a1ba 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -522,36 +522,6 @@ static BOOL dump_core(void) } #endif -/**************************************************************************** -update the current smbd process count -****************************************************************************/ - -static BOOL process_count_update_successful = False; - -int32 increment_smbd_process_count(void) -{ - int32 total_smbds; - - if (lp_max_smbd_processes()) { - total_smbds = 0; - if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1) == -1) - return 1; - process_count_update_successful = True; - return total_smbds + 1; - } - return 1; -} - -static void decrement_smbd_process_count(void) -{ - int32 total_smbds; - - if (lp_max_smbd_processes() && process_count_update_successful) { - total_smbds = 1; - tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1); - } -} - /**************************************************************************** Exit the server. ****************************************************************************/ -- cgit From 071af8f007efc20c23959d140a87cc09363aae83 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 11 Jan 2003 02:38:36 +0000 Subject: [merge] make sure to update print queue cache during timeout_processing() to send notify events; CR 1491 (This used to be commit f8a915b14d63e4fdb99235053eeb896ef9492068) --- source3/smbd/process.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 06cedea573..ff84dc8e1a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1209,6 +1209,10 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); */ process_blocking_lock_queue(t); + /* update printer queue caches if necessary */ + + update_monitored_printq_cache(); + /* * Check to see if we have any change notifies * outstanding on the queue. -- cgit From 42d9c734240574247cf3363a5d8ee67a17c668bc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jan 2003 03:02:18 +0000 Subject: merge alt_name patch from head (This used to be commit 20ebdee36d5351731698bdef6602fc73a45b1651) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 872e33c832..b9956370c2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1794,7 +1794,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if(!mangle_is_8_3(short_name, True)) { mangle_map(short_name,True,True,SNUM(conn)); } - len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER); + len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE); data_size = 4 + len; SIVAL(pdata,0,len); break; -- cgit From 212077afa275b7111e2a28798affa9689dede2ba Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 14 Jan 2003 07:26:12 +0000 Subject: Merge indirection, signed/unsigned and uninitialiased-value fixes from HEAD. Andrew Bartlett (This used to be commit 2a1adb8f81d8966e8919fffb9b4c69f3e6acd44f) --- source3/smbd/notify_kernel.c | 2 ++ source3/smbd/oplock_linux.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index df553721ef..8b7ff21ecb 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -215,6 +215,8 @@ struct cnotify_fns *kernel_notify_init(void) static struct cnotify_fns cnotify; struct sigaction act; + ZERO_STRUCT(act); + act.sa_handler = NULL; act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 85f89c12a0..deed0c5107 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -279,6 +279,8 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) return NULL; } + ZERO_STRUCT(act); + act.sa_handler = NULL; act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; -- cgit From 61b65aad1361e221828c7eabfdd16b42b1643eb3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 14 Jan 2003 07:49:15 +0000 Subject: Merge from HEAD - eliminated unused arguments. Andrew Bartlett (This used to be commit 6dd474d8451d39e580834089d7c3614059558354) --- source3/smbd/chgpasswd.c | 3 +-- source3/smbd/lanman.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index cc130d16c2..cf5a0fc142 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -672,8 +672,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, no longer be valid. ************************************************************/ -BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, - uchar * pass2) +BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) { static uchar null_pw[16]; uchar unenc_new_pw[16]; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 61288e0167..b1dfa68fec 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1955,7 +1955,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param SAM_ACCOUNT *hnd = NULL; if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && - change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2)) + change_lanman_password(hnd,pass2)) { SSVAL(*rparam,0,NERR_Success); } -- cgit From 27b7e51a3cc619f879655a3230611457ac43b9e7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 14 Jan 2003 08:53:59 +0000 Subject: Merge from HEAD: - fstring/pstring mixups - the detection code that found them (disabled) - a bit of whitespace - a static Andrew Bartlett (This used to be commit 9b70fa868e7d9481f584c83fc4046174e1dedfd9) --- source3/smbd/lanman.c | 2 +- source3/smbd/reply.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b1dfa68fec..25f390be55 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1008,7 +1008,7 @@ static int get_server_info(uint32 servertype, if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue; if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) { /* this allows us to cope with an old nmbd */ - pstrcpy(s->domain,lp_workgroup()); + fstrcpy(s->domain,lp_workgroup()); } if (sscanf(stype,"%X",&s->type) != 1) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ef5a090243..580878fe32 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -669,7 +669,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!conn->dirptr) goto SearchEmpty; string_set(&conn->dirpath,dptr_path(dptr_num)); - fstrcpy(mask, dptr_wcard(dptr_num)); + pstrcpy(mask, dptr_wcard(dptr_num)); } if (can_open) { -- cgit From 90a241264290cf9976e2bd144c0f57a26a01fbda Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 14 Jan 2003 15:52:14 +0000 Subject: make -i flag work lik eit did in 2.2 (This used to be commit 5d821c0e23f96f4da6a29a6bebf800532fcf1aa6) --- source3/smbd/server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0b2fa2a1ba..1d1061f6d8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -145,7 +145,7 @@ static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) Open the socket communication. ****************************************************************************/ -static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) +static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) { int num_interfaces = iface_count(); int num_sockets = 0; @@ -343,6 +343,9 @@ static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports) strerror(errno))); continue; } + + if (smbd_server_fd() != -1 && interactive) + return True; if (smbd_server_fd() != -1 && sys_fork()==0) { /* Child code ... */ @@ -805,7 +808,7 @@ static BOOL init_structs(void ) start_background_queue(); */ - if (!open_sockets_smbd(is_daemon,ports)) + if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); /* -- cgit From 55b8c949aa4220c266b55a9fa07797d0abf917e7 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 14 Jan 2003 23:52:42 +0000 Subject: removing unused variable and unused file (This used to be commit c8266011b7afc2d6bcb8638c2a5ed3f9116cd88a) --- source3/smbd/dir.c | 1 - source3/smbd/groupname.c | 237 ----------------------------------------------- 2 files changed, 238 deletions(-) delete mode 100644 source3/smbd/groupname.c (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 4aa132d110..9e8de2979b 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -688,7 +688,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S size_t sd_size; files_struct *fsp; int smb_action; - int access_mode; NTSTATUS status; uint32 access_granted; diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c deleted file mode 100644 index 5147ae4b95..0000000000 --- a/source3/smbd/groupname.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Groupname handling - Copyright (C) Jeremy Allison 1998. - - 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. -*/ - -#ifdef USING_GROUPNAME_MAP - -#include "includes.h" - -/************************************************************************** - Groupname map functionality. The code loads a groupname map file and - (currently) loads it into a linked list. This is slow and memory - hungry, but can be changed into a more efficient storage format - if the demands on it become excessive. -***************************************************************************/ - -typedef struct groupname_map { - ubi_slNode next; - - char *windows_name; - DOM_SID windows_sid; - char *unix_name; - gid_t unix_gid; -} groupname_map_entry; - -static ubi_slList groupname_map_list; - -/************************************************************************** - Delete all the entries in the groupname map list. -***************************************************************************/ - -static void delete_groupname_map_list(void) -{ - groupname_map_entry *gmep; - - while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) { - SAFE_FREE(gmep->windows_name); - SAFE_FREE(gmep->unix_name); - SAFE_FREE(gmep); - } -} - -/************************************************************************** - Load a groupname map file. Sets last accessed timestamp. -***************************************************************************/ - -void load_groupname_map(void) -{ - static time_t groupmap_file_last_modified = (time_t)0; - static BOOL initialized = False; - char *groupname_map_file = lp_groupname_map(); - SMB_STRUCT_STAT st; - char **lines; - int i; - groupname_map_entry *new_ep; - - if(!initialized) { - ubi_slInitList( &groupname_map_list ); - initialized = True; - } - - if (!*groupname_map_file) - return; - - if(sys_stat(groupname_map_file, &st) != 0) { - DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n", - groupname_map_file, strerror(errno) )); - return; - } - - /* - * Check if file has changed. - */ - if( st.st_mtime <= groupmap_file_last_modified) - return; - - groupmap_file_last_modified = st.st_mtime; - - /* - * Load the file. - */ - - lines = file_lines_load(groupname_map_file,NULL,False); - if (!lines) { - DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n", - groupname_map_file, strerror(errno))); - return; - } - file_lines_slashcont(lines); - - /* - * Throw away any previous list. - */ - delete_groupname_map_list(); - - DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file)); - - for (i=0; lines[i]; i++) { - pstring unixname; - pstring windows_name; - gid_t gid; - DOM_SID tmp_sid; - char *s = lines[i]; - - DEBUG(10,("load_groupname_map: Read line |%s|\n", s)); - - if (!*s || strchr_m("#;",*s)) - continue; - - if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname))) - continue; - - if(!next_token(&s,windows_name, "\t\n\r=", sizeof(windows_name))) - continue; - - trim_string(unixname, " ", " "); - trim_string(windows_name, " ", " "); - - if (!*windows_name) - continue; - - if(!*unixname) - continue; - - DEBUG(5,("load_groupname_map: unixname = %s, windowsname = %s.\n", - unixname, windows_name)); - - /* - * Attempt to get the unix gid_t for this name. - */ - - if ((gid = nametogid(unixname)) == (gid_t)-1) - DEBUG(0,("load_groupname_map: nametogid for group %s failed.\ -Error was %s.\n", unixname, strerror(errno) )); - continue; - } - - /* - * Now map to an NT SID. - */ - - if(!lookup_wellknown_sid_from_name(windows_name, &tmp_sid)) { - /* - * It's not a well known name, convert the UNIX gid_t - * to a rid within this domain SID. - */ - sid_copy(&tmp_sid,get_global_sam_sid()); - tmp_sid.sub_auths[tmp_sid.num_auths++] = - pdb_gid_to_group_rid(gid); - } - - /* - * Create the list entry and add it onto the list. - */ - - if((new_ep = (groupname_map_entry *)malloc( sizeof(groupname_map_entry) ))== NULL) { - DEBUG(0,("load_groupname_map: malloc fail for groupname_map_entry.\n")); - fclose(fp); - return; - } - - new_ep->unix_gid = gid; - new_ep->windows_sid = tmp_sid; - new_ep->windows_name = strdup( windows_name ); - new_ep->unix_name = strdup( unixname ); - - if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) { - DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n")); - fclose(fp); - SAFE_FREE(new_ep->windows_name); - SAFE_FREE(new_ep->unix_name); - SAFE_FREE(new_ep); - file_lines_free(lines); - return; - } - memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) ); - - ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep); - } - - DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n", - ubi_slCount(&groupname_map_list))); - - file_lines_free(lines); -} - -/*********************************************************** - Lookup a SID entry by gid_t. -************************************************************/ - -void map_gid_to_sid( gid_t gid, DOM_SID *psid) -{ - groupname_map_entry *gmep; - - /* - * Initialize and load if not already loaded. - */ - load_groupname_map(); - - for( gmep = (groupname_map_entry *)ubi_slFirst( &groupname_map_list); - gmep; gmep = (groupname_map_entry *)ubi_slNext( gmep )) { - - if( gmep->unix_gid == gid) { - *psid = gmep->windows_sid; - DEBUG(7,("map_gid_to_sid: Mapping unix group %s to windows group %s.\n", - gmep->unix_name, gmep->windows_name )); - return; - } - } - - /* - * If there's no map, convert the UNIX gid_t - * to a rid within this domain SID. - */ - sid_copy(psid,get_global_sam_sid()); - psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid); - - return; -} -#else /* USING_GROUPNAME_MAP */ - void load_groupname_map(void) {;} -#endif /* USING_GROUPNAME_MAP */ -- cgit From 99cdb462083381c88689a4e698ca48b6ed4cf5ac Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 15 Jan 2003 18:57:41 +0000 Subject: *lots of small merges form HEAD *sync up configure.in *don't build torture tools in make all *make sure to remove torture tools as part of make clean (This used to be commit 0fb724b3216eeeb97e61ff12755ca3a31bcad6ef) --- source3/smbd/chgpasswd.c | 10 +++++++--- source3/smbd/service.c | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index cf5a0fc142..1c31d9757a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -249,9 +249,9 @@ static int expect(int master, char *issue, char *expected) nread = 0; buffer[nread] = 0; - while ((len = read_with_timeout(master, buffer + nread, 1, - sizeof(buffer) - nread - 1, - timeout)) > 0) { + while ((len = read_socket_with_timeout(master, buffer + nread, 1, + sizeof(buffer) - nread - 1, + timeout)) > 0) { nread += len; buffer[nread] = 0; @@ -862,6 +862,10 @@ static NTSTATUS check_oem_password(const char *user, */ new_pw_len = IVAL(lmdata, 512); + + DEBUG(0, ("** new_pw_len = %d, new_passwd_size = %d\n", + new_pw_len, new_passwd_size)); + if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); pdb_free_sam(&sampass); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index dd427c2ae8..2a41a6db1c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -155,7 +155,7 @@ int find_service(fstring service) char *pszTemp; DEBUG(3,("checking whether %s is a valid printer name...\n", service)); - pszTemp = PRINTCAP; + pszTemp = lp_printcapname(); if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) { DEBUG(3,("%s is a valid printer name\n", service)); @@ -751,7 +751,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, { uid_t euid; user_struct *vuser = NULL; - pstring service; + fstring service; int snum = -1; /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ @@ -814,7 +814,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, dev, status); } - pstrcpy(service, service_in); + fstrcpy(service, service_in); strlower(service); -- cgit From 3a5a4159882635800b57fc766c7d4e2ec0297bb9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 15 Jan 2003 22:20:16 +0000 Subject: Remove debugging stmt. (This used to be commit d74382ccfe7e96e20816dd2d481b79fb66f2f243) --- source3/smbd/chgpasswd.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 1c31d9757a..401ab131ad 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -863,9 +863,6 @@ static NTSTATUS check_oem_password(const char *user, new_pw_len = IVAL(lmdata, 512); - DEBUG(0, ("** new_pw_len = %d, new_passwd_size = %d\n", - new_pw_len, new_passwd_size)); - if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); pdb_free_sam(&sampass); -- cgit From 2b79854f068c99b2881a02371b4bc7dd00a4e5aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Jan 2003 06:34:22 +0000 Subject: Fix reference count bug where smbd's would not terminate with no open resources. Jeremy. (This used to be commit b7e5a2c5474e9edd8fa783462af8986b6bd426a5) --- source3/smbd/conn.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 22407348e8..c771f1254b 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -136,10 +136,12 @@ void conn_close_all(void) } /**************************************************************************** -idle inactive connections + Idle inactive connections. ****************************************************************************/ + BOOL conn_idle_all(time_t t, int deadtime) { + pipes_struct *plist = NULL; BOOL allidle = True; connection_struct *conn, *next; @@ -154,6 +156,15 @@ BOOL conn_idle_all(time_t t, int deadtime) allidle = False; } + /* + * Check all pipes for any open handles. We cannot + * idle with a handle open. + */ + + for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) + if (plist->pipe_handles && plist->pipe_handles->count) + allidle = False; + return allidle; } -- cgit From dd072d240b9bca25e6e7394353cacf778847f86e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 24 Jan 2003 19:05:32 +0000 Subject: Fixed typo found by tpot. Jeremy. (This used to be commit 7e2bc1fe58f5da437e55867d1205ca6ceade4c74) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ff84dc8e1a..8018d5f6f6 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -807,7 +807,7 @@ static int32 increment_smbd_process_count(void) if (lp_max_smbd_processes()) { total_smbds = 0; - if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1) == -1) + if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1) return 1; process_count_update_successful = True; return total_smbds + 1; -- cgit From db56e6f8f0520547dc9cedcf76120fe404f20a16 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 28 Jan 2003 02:15:11 +0000 Subject: performance patch from HP-UX folks (cant remember who) (This used to be commit d6c22e693efee88c17f1f0f6c861e7101b3fec99) --- source3/smbd/quotas.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 90fd4bbdac..9d3bfe2d64 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -886,10 +886,21 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) char dev_disk[256]; SMB_STRUCT_STAT S; + /* find the block device file */ - if ((sys_stat(path, &S)<0) || - (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); -#endif + +#ifdef HPUX + /* Need to set the cache flag to 1 for HPUX. Seems + * to have a significant performance boost when + * lstat calls on /dev access this function. + */ + if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0)) +#else + if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) + return (False); +#endif /* ifdef HPUX */ + +#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */ euser_id = geteuid(); -- cgit From 1cba0a757970ffd8b81d61c88965010968ab3eff Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 28 Jan 2003 12:07:02 +0000 Subject: Merge from HEAD: - NTLMSSP over SPENGO (sesssion-setup-and-x) cleanup and code refactor. - also consequential changes to the NTLMSSP and SPNEGO parsing functions - and the client code that uses the same functions - Add ntlm_auth, a NTLMSSP authentication interface for use by applications like Squid and Apache. - also consquential changes to use common code for base64 encode/decode. - Winbind changes to support ntlm_auth (I don't want this program to need to read smb.conf, instead getting all it's details over the pipe). - nmbd changes for fstrcat() instead of fstrcpy(). Andrew Bartlett (This used to be commit fbb46da79cf322570a7e3318100c304bbf33409e) --- source3/smbd/sesssetup.c | 371 ++++++++++++++--------------------------------- 1 file changed, 109 insertions(+), 262 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index f8e8e017e0..679f040b2c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,7 +23,8 @@ #include "includes.h" uint32 global_client_caps = 0; -static struct auth_context *ntlmssp_auth_context = NULL; + +static struct auth_ntlmssp_state *global_ntlmssp_state; /* on a logon error possibly map the error to success if "map to guest" @@ -67,6 +68,37 @@ static void add_signature(char *outbuf) set_message_end(outbuf,p); } +/**************************************************************************** +send a security blob via a session setup reply +****************************************************************************/ +static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, + DATA_BLOB blob, NTSTATUS nt_status) +{ + char *p; + + set_message(outbuf,4,0,True); + + /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end + that we aren't finished yet */ + + nt_status = nt_status_squash(nt_status); + SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status)); + SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ + SSVAL(outbuf, smb_vwv3, blob.length); + p = smb_buf(outbuf); + + /* should we cap this? */ + memcpy(p, blob.data, blob.length); + p += blob.length; + + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); + + return send_smb(smbd_server_fd(),outbuf); +} + /**************************************************************************** Do a 'guest' logon, getting back the ****************************************************************************/ @@ -209,30 +241,54 @@ static int reply_spnego_kerberos(connection_struct *conn, /**************************************************************************** -send a security blob via a session setup reply -****************************************************************************/ -static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, - DATA_BLOB blob, uint32 errcode) + send a session setup reply, wrapped in SPNEGO. + get vuid and check first. + end the NTLMSSP exchange context if we are OK/complete fail +***************************************************************************/ +static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state, + DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) { - char *p; + BOOL ret; + DATA_BLOB response; + struct auth_serversupplied_info *server_info; + server_info = (*auth_ntlmssp_state)->server_info; - set_message(outbuf,4,0,True); + if (!NT_STATUS_IS_OK(nt_status)) { + nt_status = do_map_to_guest(nt_status, + &server_info, + (*auth_ntlmssp_state)->ntlmssp_state->user, + (*auth_ntlmssp_state)->ntlmssp_state->domain); + } - /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end - that we aren't finished yet */ + if (NT_STATUS_IS_OK(nt_status)) { + int sess_vuid; + sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user /* check this for weird */); + + if (sess_vuid == -1) { + nt_status = NT_STATUS_LOGON_FAILURE; + } else { + + set_message(outbuf,4,0,True); + SSVAL(outbuf, smb_vwv3, 0); + + if ((*auth_ntlmssp_state)->server_info->guest) { + SSVAL(outbuf,smb_vwv2,1); + } + + SSVAL(outbuf,smb_uid,sess_vuid); + } + } - SIVAL(outbuf, smb_rcls, errcode); - SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ - SSVAL(outbuf, smb_vwv3, blob.length); - p = smb_buf(outbuf); - memcpy(p, blob.data, blob.length); - p += blob.length; - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - set_message_end(outbuf,p); - - return send_smb(smbd_server_fd(),outbuf); + response = spnego_gen_auth_response(ntlmssp_blob, nt_status); + ret = reply_sesssetup_blob(conn, outbuf, response, nt_status); + data_blob_free(&response); + + if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + auth_ntlmssp_end(&global_ntlmssp_state); + } + + return ret; } /**************************************************************************** @@ -247,12 +303,9 @@ static int reply_spnego_negotiate(connection_struct *conn, char *OIDs[ASN1_MAX_OIDS]; DATA_BLOB secblob; int i; - uint32 ntlmssp_command, neg_flags, chal_flags; - DATA_BLOB chal, spnego_chal; - const uint8 *cryptkey; + DATA_BLOB chal; BOOL got_kerberos = False; NTSTATUS nt_status; - char *cliname=NULL, *domname=NULL; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { @@ -278,95 +331,26 @@ static int reply_spnego_negotiate(connection_struct *conn, } #endif - /* parse the NTLMSSP packet */ -#if 0 - file_save("secblob.dat", secblob.data, secblob.length); -#endif - - if (!msrpc_parse(&secblob, "CddAA", - "NTLMSSP", - &ntlmssp_command, - &neg_flags, - &cliname, - &domname)) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - data_blob_free(&secblob); - - if (ntlmssp_command != NTLMSSP_NEGOTIATE) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - debug_ntlmssp_flags(neg_flags); - - if (ntlmssp_auth_context) { - (ntlmssp_auth_context->free)(&ntlmssp_auth_context); + if (global_ntlmssp_state) { + auth_ntlmssp_end(&global_ntlmssp_state); } - if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) { + nt_status = auth_ntlmssp_start(&global_ntlmssp_state); + if (!NT_STATUS_IS_OK(nt_status)) { return ERROR_NT(nt_status); } - cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context); - - /* Give them the challenge. For now, ignore neg_flags and just - return the flags we want. Obviously this is not correct */ - - chal_flags = NTLMSSP_NEGOTIATE_UNICODE | - NTLMSSP_NEGOTIATE_128 | - NTLMSSP_NEGOTIATE_NTLM | - NTLMSSP_CHAL_TARGET_INFO; - - { - DATA_BLOB domain_blob, struct_blob; - fstring dnsname, dnsdomname; - - msrpc_gen(&domain_blob, - "U", - lp_workgroup()); - - fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():""); - strlower(dnsdomname); - - fstrcpy(dnsname, global_myname()); - fstrcat(dnsname, "."); - fstrcat(dnsname, dnsdomname); - strlower(dnsname); - - msrpc_gen(&struct_blob, "aaaaa", - 2, lp_workgroup(), - 1, global_myname(), - 4, dnsdomname, - 3, dnsname, - 0, ""); - - msrpc_gen(&chal, "CdUdbddB", - "NTLMSSP", - NTLMSSP_CHALLENGE, - lp_workgroup(), - chal_flags, - cryptkey, 8, - 0, 0, - struct_blob.data, struct_blob.length); - - data_blob_free(&domain_blob); - data_blob_free(&struct_blob); - } - - if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) { - DEBUG(3,("Failed to generate challenge\n")); - data_blob_free(&chal); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } + nt_status = auth_ntlmssp_update(global_ntlmssp_state, + secblob, &chal); - /* now tell the client to send the auth packet */ - reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)); + data_blob_free(&secblob); + reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + &chal, nt_status); + data_blob_free(&chal); - data_blob_free(&spnego_chal); - /* and tell smbd that we have already replied to this packet */ + /* already replied */ return -1; } @@ -378,23 +362,8 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, DATA_BLOB blob1) { - DATA_BLOB auth, response; - char *workgroup = NULL, *user = NULL, *machine = NULL; - DATA_BLOB lmhash, nthash, sess_key; - DATA_BLOB plaintext_password = data_blob(NULL, 0); - uint32 ntlmssp_command, neg_flags; + DATA_BLOB auth, auth_reply; NTSTATUS nt_status; - int sess_vuid; - BOOL as_guest; - uint32 auth_flags = AUTH_FLAG_NONE; - auth_usersupplied_info *user_info = NULL; - auth_serversupplied_info *server_info = NULL; - - /* we must have setup the auth context by now */ - if (!ntlmssp_auth_context) { - DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } if (!spnego_parse_auth(blob1, &auth)) { #if 0 @@ -403,157 +372,32 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - /* now the NTLMSSP encoded auth hashes */ - if (!msrpc_parse(&auth, "CdBBUUUBd", - "NTLMSSP", - &ntlmssp_command, - &lmhash, - &nthash, - &workgroup, - &user, - &machine, - &sess_key, - &neg_flags)) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } + nt_status = auth_ntlmssp_update(global_ntlmssp_state, + auth, &auth_reply); data_blob_free(&auth); - data_blob_free(&sess_key); - - DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n", - user, workgroup, machine, lmhash.length, nthash.length)); - - /* the client has given us its machine name (which we otherwise would not get on port 445). - we need to possibly reload smb.conf if smb.conf includes depend on the machine name */ - - set_remote_machine_name(machine); - - /* setup the string used by %U */ - sub_set_smb_name(user); - - reload_services(True); - -#if 0 - file_save("nthash1.dat", nthash.data, nthash.length); - file_save("lmhash1.dat", lmhash.data, lmhash.length); -#endif - - if (lmhash.length) { - auth_flags |= AUTH_FLAG_LM_RESP; - } - - if (nthash.length == 24) { - auth_flags |= AUTH_FLAG_NTLM_RESP; - } else if (nthash.length > 24) { - auth_flags |= AUTH_FLAG_NTLMv2_RESP; - }; - - nt_status = make_user_info_map(&user_info, user, workgroup, machine, - lmhash, nthash, plaintext_password, - auth_flags, True); - - /* it looks a bit weird, but this function returns int type... */ - if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info); - - if (!NT_STATUS_IS_OK(nt_status)) { - nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup); - } - - SAFE_FREE(workgroup); - SAFE_FREE(machine); - - (ntlmssp_auth_context->free)(&ntlmssp_auth_context); - - free_user_info(&user_info); - - data_blob_free(&lmhash); - - data_blob_free(&nthash); - - if (!NT_STATUS_IS_OK(nt_status)) { - SAFE_FREE(user); - return ERROR_NT(nt_status_squash(nt_status)); - } - - as_guest = server_info->guest; - - sess_vuid = register_vuid(server_info, user); - free_server_info(&server_info); - - SAFE_FREE(user); - - if (sess_vuid == -1) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - set_message(outbuf,4,0,True); - SSVAL(outbuf, smb_vwv3, 0); - if (as_guest) { - SSVAL(outbuf,smb_vwv2,1); - } - - add_signature(outbuf); - - SSVAL(outbuf,smb_uid,sess_vuid); - SSVAL(inbuf,smb_uid,sess_vuid); - - response = spnego_gen_auth_response(); - reply_sesssetup_blob(conn, outbuf, response, 0); + reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + &auth_reply, nt_status); + + data_blob_free(&auth_reply); /* and tell smbd that we have already replied to this packet */ return -1; } -/**************************************************************************** -reply to a session setup spnego anonymous packet -****************************************************************************/ -static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf, - int length, int bufsize) -{ - int sess_vuid; - auth_serversupplied_info *server_info = NULL; - NTSTATUS nt_status; - - nt_status = check_guest_password(&server_info); - - if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status_squash(nt_status)); - } - - sess_vuid = register_vuid(server_info, lp_guestaccount()); - - free_server_info(&server_info); - - if (sess_vuid == -1) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - set_message(outbuf,4,0,True); - SSVAL(outbuf, smb_vwv3, 0); - add_signature(outbuf); - - SSVAL(outbuf,smb_uid,sess_vuid); - SSVAL(inbuf,smb_uid,sess_vuid); - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - /**************************************************************************** reply to a session setup command ****************************************************************************/ -static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf, +static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, + char *outbuf, int length,int bufsize) { uint8 *p; DATA_BLOB blob1; int ret; + size_t bufrem; DEBUG(3,("Doing spnego session setup\n")); @@ -564,12 +408,13 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha p = (uint8 *)smb_buf(inbuf); if (SVAL(inbuf, smb_vwv7) == 0) { - /* an anonymous request */ - return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize); + /* an invalid request */ + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + bufrem = smb_bufrem(inbuf, p); /* pull the spnego blob */ - blob1 = data_blob(p, SVAL(inbuf, smb_vwv7)); + blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7))); #if 0 file_save("negotiate.dat", blob1.data, blob1.length); @@ -786,6 +631,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, nt_status = check_guest_password(&server_info); } else if (doencrypt) { + if (!negprot_global_auth_context) { + DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n")); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } nt_status = make_user_info_for_reply_enc(&user_info, user, domain, lm_resp, nt_resp); if (NT_STATUS_IS_OK(nt_status)) { @@ -830,10 +679,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } /* it's ok - setup a reply */ - if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,3,0,True); - } else { - set_message(outbuf,3,0,True); + set_message(outbuf,3,0,True); + if (Protocol >= PROTOCOL_NT1) { add_signature(outbuf); /* perhaps grab OS version here?? */ } -- cgit From b61f89826f2b7ee8ca7bd388b66c3f5b78ed3e60 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Jan 2003 01:41:46 +0000 Subject: Fix for interesting resource constraint condition. When all opens are level 2 and a request for open with no oplock is received then the smbd should send *synchronous* break messages, not asynchronous, otherwise it spins very rapidly, releasing the lock, sending the 'break to none' messages and then re-acquiring the lock before any other process has a chance to get the lock and remove it's own oplock (at least on linux). Jeremy (This used to be commit 33e3e863eb7f35b852384e689f3272784261fc39) --- source3/smbd/open.c | 2 +- source3/smbd/oplock.c | 33 ++++++++++++++++++--------------- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5c3359fc6b..29048bca02 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -585,7 +585,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry); + opb_ret = request_oplock_break(share_entry, False); /* Now relock. */ lock_share_entry(conn, dev, inode); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 14b243b36e..f5c19bcf62 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -368,6 +368,7 @@ BOOL process_local_message(char *buffer, int buf_size) case OPLOCK_BREAK_CMD: case LEVEL_II_OPLOCK_BREAK_CMD: + case ASYNC_LEVEL_II_OPLOCK_BREAK_CMD: /* Ensure that the msg length is correct. */ if(msg_len != OPLOCK_BREAK_MSG_LEN) { @@ -438,14 +439,14 @@ oplocks. Returning success.\n")); } /* - * Do the appropriate reply - none in the kernel or level II case. + * Do the appropriate reply - none in the kernel or async level II case. */ - if(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET) == OPLOCK_BREAK_CMD) { + if(break_cmd_type == OPLOCK_BREAK_CMD || break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD) { struct sockaddr_in toaddr; /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); + SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY); memset((char *)&toaddr,'\0',sizeof(toaddr)); toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); @@ -902,7 +903,7 @@ Send an oplock break message to another smbd process. If the oplock is held by the local smbd then call the oplock break function directly. ****************************************************************************/ -BOOL request_oplock_break(share_mode_entry *share_entry) +BOOL request_oplock_break(share_mode_entry *share_entry, BOOL async) { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; @@ -912,6 +913,7 @@ BOOL request_oplock_break(share_mode_entry *share_entry) SMB_DEV_T dev = share_entry->dev; SMB_INO_T inode = share_entry->inode; unsigned long file_id = share_entry->share_file_id; + uint16 break_cmd_type; if(pid == share_entry->pid) { /* We are breaking our own oplock, make sure it's us. */ @@ -942,11 +944,12 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,LEVEL_II_OPLOCK_BREAK_CMD); + break_cmd_type = async ? ASYNC_LEVEL_II_OPLOCK_BREAK_CMD : LEVEL_II_OPLOCK_BREAK_CMD; } else { - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); + break_cmd_type = OPLOCK_BREAK_CMD; } + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type); memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); @@ -959,7 +962,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", addr_out.sin_family = AF_INET; if( DEBUGLVL( 3 ) ) { - dbgtext( "request_oplock_break: sending a oplock break message to " ); + dbgtext( "request_oplock_break: sending a %s oplock break message to ", async ? "asynchronous" : "synchronous" ); dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); @@ -972,19 +975,19 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", dbgtext( "break message to pid %d ", (int)share_entry->pid ); dbgtext( "on port %d ", share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); + (unsigned int)dev, (double)inode, file_id ); dbgtext( "Error was %s\n", strerror(errno) ); } return False; } /* - * If we just sent a message to a level II oplock share entry then + * If we just sent a message to a level II oplock share entry in async mode then * we are done and may return. */ - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - DEBUG(3,("request_oplock_break: sent break message to level II entry.\n")); + if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type) && async) { + DEBUG(3,("request_oplock_break: sent async break message to level II entry.\n")); return True; } @@ -1039,10 +1042,10 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; /* - * Test to see if this is the reply we are awaiting. + * Test to see if this is the reply we are awaiting (ie. the one we sent with the CMD_REPLY flag OR'ed in). */ if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) && - ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == OPLOCK_BREAK_CMD) && + ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == break_cmd_type) && (reply_from_port == share_entry->op_port) && (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], &op_break_msg[OPLOCK_BREAK_PID_OFFSET], OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) { @@ -1185,8 +1188,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp) * message. */ - DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock.\n")); - request_oplock_break(share_entry); + DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock (async).\n")); + request_oplock_break(share_entry, True); } } -- cgit From 142837e5d3bd9d3d853fc1c2eb181fea87a38d3a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 30 Jan 2003 04:38:39 +0000 Subject: Merge of controversial 'max log size' fix. (This used to be commit 71e2b60d8f784174cd2a75c5e03bf2a6ab353900) --- source3/smbd/process.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8018d5f6f6..98ec6ce184 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1314,5 +1314,17 @@ void smbd_process(void) last_timeout_processing_time = new_check_time; /* Reset time. */ } } + + /* The timeout_processing function isn't run nearly + often enough to implement 'max log size' without + overrunning the size of the file by many megabytes. + This is especially true if we are running at debug + level 10. Checking every 50 SMBs is a nice + tradeoff of performance vs log file size overrun. */ + + if ((num_smbs % 50) == 0 && need_to_check_log_size()) { + change_to_root_user(); + check_log_size(); + } } } -- cgit From bbf9f09ee5c58e348eef33448d2c38e588adb66a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Jan 2003 23:55:58 +0000 Subject: Add 3 second timeout when terminating server and sending print notify messages. Stops build-up of large numbers of smbd's waiting to terminate on large print throughput. Jeremy. (This used to be commit 07efebb98473cb3d4adc6b2e0afef3f06dcc99b8) --- source3/smbd/process.c | 2 +- source3/smbd/server.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 98ec6ce184..c002abad16 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1228,7 +1228,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); /* Send any queued printer notify message to interested smbd's. */ - print_notify_send_messages(); + print_notify_send_messages(0); /* * Modify the select timeout depending upon diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1d1061f6d8..e3cf9b92fd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -550,7 +550,7 @@ void exit_server(const char *reason) invalidate_all_vuids(); - print_notify_send_messages(); + print_notify_send_messages(3); /* 3 second timeout. */ /* delete our entry in the connections database. */ yield_connection(NULL,""); -- cgit From 3b2244526c7ae64f744539154681b9883daebc3f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 1 Feb 2003 07:25:53 +0000 Subject: Merge of signed/unsigned fixes from HEAD. (This used to be commit e9f56a157bd472914eebf64fde586104d8274717) --- source3/smbd/conn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index c771f1254b..38fa2e0237 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -68,7 +68,7 @@ BOOL conn_snum_used(int snum) /**************************************************************************** find a conn given a cnum ****************************************************************************/ -connection_struct *conn_find(int cnum) +connection_struct *conn_find(unsigned cnum) { int count=0; connection_struct *conn; @@ -174,7 +174,7 @@ clear a vuid out of the validity cache, and as the 'owner' of a connection. void conn_clear_vuid_cache(uint16 vuid) { connection_struct *conn; - int i; + unsigned int i; for (conn=Connections;conn;conn=conn->next) { if (conn->vuid == vuid) { -- cgit From df6d278785def44a7e66cdad1b5adbc691cc496d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 2 Feb 2003 18:08:37 +0000 Subject: untest fix from HEAD/2.2 for wide links parameter bug. it work properly on 2.2 and the patch apply so I think it should be ok. (This used to be commit 8498503f1d59636959fe9f97601c55d82a776199) --- source3/smbd/vfs.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index de7b90df72..6574a34eaa 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -780,6 +780,63 @@ char *vfs_GetWd(connection_struct *conn, char *path) return (path); } + +/* check if the file 'nmae' is a symlink, in that case check that it point to + a file that reside under the 'dir' tree */ + +static BOOL readlink_check(connection_struct *conn, char *dir, char *name) +{ + BOOL ret = True; + pstring flink; + pstring cleanlink; + pstring savedir; + pstring realdir; + size_t reallen; + + if (!vfs_GetWd(conn, savedir)) { + DEBUG(0,("couldn't vfs_GetWd for %s %s\n", name, dir)); + return False; + } + + if (vfs_ChDir(conn, dir) != 0) { + DEBUG(0,("couldn't vfs_ChDir to %s\n", dir)); + return False; + } + + if (!vfs_GetWd(conn, realdir)) { + DEBUG(0,("couldn't vfs_GetWd for %s\n", dir)); + vfs_ChDir(conn, savedir); + return(False); + } + + reallen = strlen(realdir); + if (realdir[reallen -1] == '/') { + reallen--; + realdir[reallen] = 0; + } + + if (conn->vfs_ops.readlink(conn, name, flink, sizeof(pstring) -1) != -1) { + DEBUG(3,("reduce_name: file path name %s is a symlink\nChecking it's path\n", name)); + if (*flink == '/') { + pstrcpy(cleanlink, flink); + } else { + pstrcpy(cleanlink, realdir); + pstrcat(cleanlink, "/"); + pstrcat(cleanlink, flink); + } + unix_clean_name(cleanlink); + + if (strncmp(cleanlink, realdir, reallen) != 0) { + DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n", name, realdir, cleanlink, (int)reallen)); + ret = False; + } + } + + vfs_ChDir(conn, savedir); + + return ret; +} + /******************************************************************* Reduce a file name, removing .. elements and checking that it is below dir in the heirachy. This uses vfs_GetWd() and so must be run @@ -824,7 +881,7 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir,BOOL wideli p = strrchr_m(base_name,'/'); if (!p) - return(True); + return readlink_check(conn, dir, s); if (!vfs_GetWd(conn,wd)) { DEBUG(0,("couldn't vfs_GetWd for %s %s\n",s,dir)); @@ -858,7 +915,7 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir,BOOL wideli if (!vfs_GetWd(conn,newname)) { vfs_ChDir(conn,wd); - DEBUG(2,("couldn't get vfs_GetWd for %s %s\n",s,dir2)); + DEBUG(2,("couldn't get vfs_GetWd for %s %s\n",s,base_name)); return(False); } @@ -878,6 +935,11 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir,BOOL wideli return(False); } + if (!readlink_check(conn, dir, newname)) { + DEBUG(2, ("Bad access attemt? %s is a symlink outside the share path", s)); + return(False); + } + if (relative) { if (newname[l] == '/') pstrcpy(s,newname + l + 1); @@ -896,3 +958,4 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir,BOOL wideli return(True); #endif } + -- cgit From 70a03079a78d8305221106a4c21102fd088a4362 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Feb 2003 01:11:56 +0000 Subject: Ensure Samba passes the open attribute truncate tests in smbtorture. Jeremy. (This used to be commit b3df40bc803e7dc3b66a95eccb335e2b1775560e) --- source3/smbd/open.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 29048bca02..dea7edc528 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -702,6 +702,7 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex mode_t new_mode, mode_t *returned_mode) { uint32 old_dos_mode, new_dos_mode; + uint32 noarch_old_dos_mode, noarch_new_dos_mode; SMB_STRUCT_STAT sbuf; ZERO_STRUCT(sbuf); @@ -712,25 +713,27 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex sbuf.st_mode = new_mode; new_dos_mode = dos_mode(conn, path, &sbuf); - /* - * We only set returned mode to be the same as new_mode if - * the file attributes need to be changed. - */ + noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); + noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); + + if((noarch_old_dos_mode == 0 && noarch_new_dos_mode != 0) || + (noarch_old_dos_mode != 0 && ((noarch_old_dos_mode & noarch_new_dos_mode) == noarch_old_dos_mode))) + *returned_mode = new_mode; + else + *returned_mode = (mode_t)0; - *returned_mode = (mode_t)0; + DEBUG(10,("open_match_attributes: file %s old_dos_mode = 0x%x, existing_mode = 0%o, new_dos_mode = 0x%x returned_mode = 0%o\n", + path, + old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode )); /* If we're mapping SYSTEM and HIDDEN ensure they match. */ if (lp_map_system(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) return False; - if (!(old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && (new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) - *returned_mode = new_mode; } if (lp_map_hidden(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; - if (!(old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && (new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) - *returned_mode = new_mode; } return True; } -- cgit From ce85e52eff9d8a61a58c559bdf4beb5e1284060d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Feb 2003 01:43:10 +0000 Subject: Ensure we only ever set fsp->conn in one place. Jeremy. (This used to be commit d8a42753cc1e1a94aa6b816222343e1569521f14) --- source3/smbd/open.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dea7edc528..6570745816 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -230,7 +230,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->is_directory = False; fsp->is_stat = False; fsp->directory_delete_on_close = False; - fsp->conn = conn; string_set(&fsp->fsp_name,fname); fsp->wcp = NULL; /* Write cache pointer. */ @@ -1202,8 +1201,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST if(!fsp) return NULL; - fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - if (VALID_STAT(*psbuf)) got_stat = True; @@ -1299,7 +1296,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->is_directory = True; fsp->is_stat = False; fsp->directory_delete_on_close = False; - fsp->conn = conn; string_set(&fsp->fsp_name,fname); if (delete_on_close) { @@ -1335,8 +1331,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST if(!fsp) return NULL; - fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); /* @@ -1365,7 +1359,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->is_directory = False; fsp->is_stat = True; fsp->directory_delete_on_close = False; - fsp->conn = conn; string_set(&fsp->fsp_name,fname); conn->num_files_open++; -- cgit From 1fb6f689e7d2534a5fe0a1232be7ea30be8f515e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 4 Feb 2003 08:27:02 +0000 Subject: Merge from HEAD: avoid braindead #define on Tru64. (This used to be commit 299233fbf2328d08546b3b03dceca67083b68493) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 22bb7fe76b..5069db8097 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1551,7 +1551,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) ****************************************************************************/ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup, SMB_ACL_TYPE_T acl_type) + DOM_SID *powner, DOM_SID *pgroup, SMB_ACL_TYPE_T the_acl_type) { extern DOM_SID global_sid_World; connection_struct *conn = fsp->conn; @@ -1603,7 +1603,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * entries out of the blue when setting ACLs, so a get/set * cycle will drop them. */ - if (acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) + if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) continue; uid_to_sid( &sid, *puid); unix_ug.uid = *puid; -- cgit From 35a8dceb20c201826409fbcb1c540ce2e4e2e764 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Feb 2003 21:16:55 +0000 Subject: Check for too many processes *before* the fork. Jeremy. (This used to be commit be54b1b831b0bd6c428558131ea600c46433c090) --- source3/smbd/server.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e3cf9b92fd..f8bfe90ea9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -141,6 +141,40 @@ static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) } +/**************************************************************************** + Have we reached the process limit ? +****************************************************************************/ + +BOOL allowable_number_of_smbd_processes(void) +{ + int max_processes = lp_max_smbd_processes(); + + if (!max_processes) + return True; + + { + TDB_CONTEXT *tdb = conn_tdb_ctx(); + int32 val; + if (!tdb) { + DEBUG(0,("allowable_number_of_smbd_processes: can't open connection tdb.\n" )); + return False; + } + + val = tdb_fetch_int32(tdb, "INFO/total_smbds"); + if (val == -1 && (tdb_error(tdb) != TDB_ERR_NOEXIST)) { + DEBUG(0,("allowable_number_of_smbd_processes: can't fetch INFO/total_smbds. Error %s\n", + tdb_errorstr(tdb) )); + return False; + } + if (val > max_processes) { + DEBUG(0,("allowable_number_of_smbd_processes: number of processes (%d) is over allowed limit (%d)\n", + val, max_processes )); + return False; + } + } + return True; +} + /**************************************************************************** Open the socket communication. ****************************************************************************/ @@ -321,7 +355,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ for( ; num > 0; num--) { struct sockaddr addr; socklen_t in_addrlen = sizeof(addr); - + s = -1; for(i = 0; i < num_sockets; i++) { if(FD_ISSET(fd_listenset[i],&lfds)) { @@ -347,7 +381,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ if (smbd_server_fd() != -1 && interactive) return True; - if (smbd_server_fd() != -1 && sys_fork()==0) { + if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && sys_fork()==0) { /* Child code ... */ /* close the listening socket(s) */ -- cgit From 50edc1a8310c18ffc09cbd5dcc285122a638a4d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Feb 2003 04:11:36 +0000 Subject: merge from head (This used to be commit fd3216dbcbaec7d64dd24fe2af6c4156935c47e9) --- source3/smbd/filename.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index bcfd366741..7d3527402e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -31,7 +31,8 @@ extern BOOL case_preserve; extern BOOL short_case_preserve; extern BOOL use_mangled_map; -static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache); +static BOOL scan_directory(const char *path, char *name,size_t maxlength, + connection_struct *conn,BOOL docache); /**************************************************************************** Check if two filenames are equal. @@ -266,7 +267,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Try to find this part of the path in the directory. */ - if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { + if (ms_has_wild(start) || + !scan_directory(dirpath, start, + sizeof(pstring) - 1 - (start - name), + conn, + end?True:False)) { if (end) { /* * An intermediate part of the name can't be found. @@ -315,8 +320,10 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (end) { end = start + strlen(start); - pstrcat(start,"/"); - pstrcat(start,rest); + if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) || + !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) { + return False; + } *end = '\0'; } else { /* @@ -428,7 +435,8 @@ BOOL check_name(pstring name,connection_struct *conn) If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(const char *path, pstring name,connection_struct *conn,BOOL docache) +static BOOL scan_directory(const char *path, char *name, size_t maxlength, + connection_struct *conn,BOOL docache) { void *cur_dir; char *dname; @@ -441,7 +449,7 @@ static BOOL scan_directory(const char *path, pstring name,connection_struct *con path = "."; if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { - pstrcpy(name, dname); + safe_strcpy(name, dname, maxlength); return(True); } @@ -481,7 +489,7 @@ static BOOL scan_directory(const char *path, pstring name,connection_struct *con /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); + safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); return(True); } -- cgit From 67acaa00264e40f92dc06855a913138df676abe5 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 7 Feb 2003 16:20:42 +0000 Subject: check pointer before dereferencing it (This used to be commit 8712bd1f8eb5321278e7c57bfdc7bdddbdaf1424) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 679f040b2c..bb7d17be56 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -272,7 +272,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - if ((*auth_ntlmssp_state)->server_info->guest) { + if ((*auth_ntlmssp_state)->server_info && (*auth_ntlmssp_state)->server_info->guest) { SSVAL(outbuf,smb_vwv2,1); } -- cgit From 8a20407442efa0f9fe43e1b1c61140a0771c6ff8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 10 Feb 2003 11:47:21 +0000 Subject: Cleanups: (merge from HEAD) - use safe_strcpy() instead of pstrcpy() for malloc()ed strings - CUPS: a failure in an attempt to automaticly add a printer is not level 0 stuff. - Fix up a possible Realloc() failure segfault Andrew Bartlett (This used to be commit c1cfc296c2efdb2b5972202146e80f0e3b6a3da4) --- source3/smbd/dir.c | 2 +- source3/smbd/statcache.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 9e8de2979b..e022d26ea3 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -907,7 +907,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp->current = dirp->data; } - pstrcpy(dirp->data+used,n); + safe_strcpy(dirp->data+used,n, dirp->mallocsize - used - 1); used += l; dirp->numentries++; } diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 93782b9bb0..f4b613428a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -122,8 +122,8 @@ void stat_cache_add( char *full_orig_name, char *orig_translated_path) DEBUG(0,("stat_cache_add: Out of memory !\n")); return; } - pstrcpy(scp->names, orig_name); - pstrcpy(scp->names+namelen+1, translated_path); + safe_strcpy(scp->names, orig_name, namelen); + safe_strcpy(scp->names+namelen+1, translated_path, namelen); scp->name_len = namelen; hash_insert(&stat_cache, (char *)scp, orig_name); } -- cgit From e6ac820d81e632997726aab5b1937f71138f490a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Feb 2003 02:24:51 +0000 Subject: Fix delete on close semantics to match W2K. I (think:-) I understand it now :-). Thanks to Nir Livni for giving me the test case to track it down. Jeremy. (This used to be commit 41894489e82a474f4f8f66aa2c7a117ed05b33e1) --- source3/smbd/close.c | 16 +++++++++++ source3/smbd/trans2.c | 75 +++++++++++++++++++++------------------------------ 2 files changed, 46 insertions(+), 45 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index b0620febef..4798d62db8 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -145,6 +145,22 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) */ lock_share_entry_fsp(fsp); + + if (fsp->delete_on_close) { + + /* + * Modify the share mode entry for all files open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. The last closer will delete the file + * if flag is set. + */ + + NTSTATUS status =set_delete_on_close_over_all(fsp, fsp->delete_on_close); + if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + DEBUG(0,("close_normal_file: failed to change delete on close flag for file %s\n", + fsp->fsp_name )); + } + share_entry_count = del_share_mode(fsp, &share_entry); DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n", diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b9956370c2..155c996314 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2101,59 +2101,39 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n", delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); } else { + fsp->delete_on_close = delete_on_close; + DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + } - files_struct *iterate_fsp; - - /* - * Modify the share mode entry for all files open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. This will be noticed - * in the close code, the last closer will delete the file - * if flag is set. - */ - - DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + return NT_STATUS_OK; +} - if (lock_share_entry_fsp(fsp) == False) - return NT_STATUS_ACCESS_DENIED; +/**************************************************************************** + Sets the delete on close flag over all share modes on this file. + Modify the share mode entry for all files open + on this device and inode to tell other smbds we have + changed the delete on close flag. This will be noticed + in the close code, the last closer will delete the file + if flag is set. +****************************************************************************/ - if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n", - fsp->fsp_name )); - unlock_share_entry_fsp(fsp); - return NT_STATUS_ACCESS_DENIED; - } +NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) +{ + DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); - /* - * Release the lock. - */ + if (lock_share_entry_fsp(fsp) == False) + return NT_STATUS_ACCESS_DENIED; + if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { + DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n", + fsp->fsp_name )); unlock_share_entry_fsp(fsp); - - /* - * Go through all files we have open on the same device and - * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. - * Other smbd's that have this file open will look in the share_mode on close. - * take care of this (rare) case in close_file(). See the comment there. - * NB. JRA. We don't really need to do this anymore - all should be taken - * care of in the share_mode changes in the tdb. - */ - - for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode); - iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp)) - fsp->delete_on_close = delete_on_close; - - /* - * Set the delete on close flag in the fsp. - */ - fsp->delete_on_close = delete_on_close; - - DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - + return NT_STATUS_ACCESS_DENIED; } + unlock_share_entry_fsp(fsp); return NT_STATUS_OK; } @@ -2531,6 +2511,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, status = set_delete_on_close_internal(fsp, delete_on_close); + if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + return ERROR_NT(status); + + /* The set is across all open files on this dev/inode pair. */ + status =set_delete_on_close_over_all(fsp, delete_on_close); if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) return ERROR_NT(status); -- cgit From dc1f0fd79ad7037cb32d8f08f6e353000ae52d0b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Feb 2003 01:06:52 +0000 Subject: Ensure we are not forgetting our janitorial duties... Jeremy. (This used to be commit 7812370cabd4a8809eed1eb4968d552bcb0df2f5) --- source3/smbd/nttrans.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 29ebdce5a8..bfac4e82e3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -629,6 +629,16 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } + + + /* + we need to handle the case when we get a + relative open relative to a file and the + pathname is blank - this is a reopen! + (hint from demyn plantenberg) + */ + + END_PROFILE(SMBntcreateX); return(ERROR_DOS(ERRDOS,ERRbadfid)); } -- cgit From 7d4eef34e3a1eb080c580385ef68892180b6847b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Feb 2003 01:13:35 +0000 Subject: Correctly return access denied on share mode deny when we can't open the file. This is a regression that was damaged by other code. Jeremy. (This used to be commit 7844a53df72af8fd2f70d51b784352aeb1298ed2) --- source3/smbd/open.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6570745816..6b3dcbe71b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -79,6 +79,7 @@ static void check_for_pipe(char *fname) DEBUG(3,("Rejecting named pipe open for %s\n",fname)); unix_ERR_class = ERRSRV; unix_ERR_code = ERRaccess; + unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; } } @@ -255,6 +256,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; + unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); return -1; } else { return conn->vfs_ops.ftruncate(fsp,fsp->fd,0); @@ -399,9 +401,10 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i if (GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRnoaccess; - unix_ERR_ntstatus = NT_STATUS_DELETE_PENDING; + /* Use errno to map to correct error. */ + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; return False; } @@ -444,6 +447,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -464,6 +468,7 @@ and existing desired access (0x%x) are non-data opens\n", fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -479,6 +484,7 @@ and existing desired access (0x%x) are non-data opens\n", fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -510,6 +516,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -596,6 +603,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return -1; } @@ -646,6 +654,7 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return -1; } @@ -922,6 +931,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ * we can do. We also ensure we're not going to create or tuncate * the file as we only want an access decision at this stage. JRA. */ + errno = 0; fsp_open = open_file(fsp,conn,fname,psbuf, flags|(flags2&~(O_TRUNC|O_CREAT)),mode,desired_access); @@ -929,6 +939,12 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ flags=0x%X flags2=0x%X mode=0%o returned %d\n", flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); + if (!fsp_open && errno) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRnoaccess; + unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + } + unlock_share_entry(conn, dev, inode); if (fsp_open) fd_close(conn, fsp); -- cgit From 33eb26ba5e847db1585b234a6b2cbd8c54865426 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Feb 2003 23:51:08 +0000 Subject: Added code based on Michael Steffens uid/gid caching code. Reduces load on winbindd. Probably should be moved to use gencache at some future date. Jeremy. (This used to be commit f2674d1ac94fd5928754b8176cdd65eda50bf66e) --- source3/smbd/uid.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index e2cc26e0ae..e7c00ba456 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -531,6 +531,183 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE return True; } +/***************************************************************** + Id mapping cache. This is to avoid Winbind mappings already + seen by smbd to be queried too frequently, keeping winbindd + busy, and blocking smbd while winbindd is busy with other + stuff. Written by Michael Steffens , + modified to use linked lists by jra. +*****************************************************************/ + +#define MAX_UID_SID_CACHE_SIZE 100 +#define TURNOVER_UID_SID_CACHE_SIZE 10 +#define MAX_GID_SID_CACHE_SIZE 100 +#define TURNOVER_GID_SID_CACHE_SIZE 10 + +static size_t n_uid_sid_cache = 0; +static size_t n_gid_sid_cache = 0; + +static struct uid_sid_cache { + struct uid_sid_cache *next, *prev; + uid_t uid; + DOM_SID sid; +} *uid_sid_cache_head; + +static struct gid_sid_cache { + struct gid_sid_cache *next, *prev; + gid_t gid; + DOM_SID sid; +} *gid_sid_cache_head; + +/***************************************************************** + Find a SID given a uid. +*****************************************************************/ + +static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (pc->uid == uid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from uid cache %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a uid given a SID. +*****************************************************************/ + +static BOOL fetch_uid_from_cache(uid_t *puid, const DOM_SID *psid) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *puid = pc->uid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*puid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store uid to SID mapping in cache. +*****************************************************************/ + +static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */ + struct uid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(uid_sid_cache_head,pc); + SAFE_FREE(pc); + n_uid_sid_cache--; + } + } + + pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache)); + if (!pc) + return; + pc->uid = uid; + sid_copy(&pc->sid, psid); + DLIST_ADD(uid_sid_cache_head, pc); + n_uid_sid_cache++; +} + +/***************************************************************** + Find a SID given a gid. +*****************************************************************/ + +static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (pc->gid == gid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from gid cache %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a gid given a SID. +*****************************************************************/ + +static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *pgid = pc->gid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*pgid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store gid to SID mapping in cache. +*****************************************************************/ + +static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ + struct gid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(gid_sid_cache_head,pc); + SAFE_FREE(pc); + n_gid_sid_cache--; + } + } + + pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); + if (!pc) + return; + pc->gid = gid; + sid_copy(&pc->sid, psid); + DLIST_ADD(gid_sid_cache_head, pc); + n_gid_sid_cache++; +} + + /***************************************************************** *THE CANONICAL* convert uid_t to SID function. Tries winbind first - then uses local lookup. @@ -542,12 +719,17 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) uid_t low, high; fstring sid; + if (fetch_sid_from_uid_cache(psid, uid)) + return psid; + if (lp_winbind_uid(&low, &high) && uid >= low && uid <= high) { if (winbind_uid_to_sid(psid, uid)) { DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); + if (psid) + store_uid_sid_cache(psid, uid); return psid; } } @@ -558,6 +740,8 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) unbecome_root(); DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); + if (psid) + store_uid_sid_cache(psid, uid); return psid; } @@ -573,20 +757,26 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) gid_t low, high; fstring sid; + if (fetch_sid_from_gid_cache(psid, gid)) + return psid; + if (lp_winbind_gid(&low, &high) && gid >= low && gid <= high) { if (winbind_gid_to_sid(psid, gid)) { DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); + if (psid) + store_gid_sid_cache(psid, gid); return psid; } } /* Make sure we report failure, (when psid == NULL) */ psid = local_gid_to_sid(psid, gid); - DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); + if (psid) + store_gid_sid_cache(psid, gid); return psid; } @@ -602,12 +792,17 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) { fstring sid_str; + if (fetch_uid_from_cache(puid, psid)) + return True; + /* if we know its local then don't try winbindd */ if (sid_compare_domain(get_global_sam_sid(), psid) == 0) { BOOL result; become_root(); result = local_sid_to_uid(puid, psid, sidtype); unbecome_root(); + if (result) + store_uid_sid_cache(psid, *puid); return result; } @@ -657,6 +852,8 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) become_root(); result = local_sid_to_uid(puid, psid, sidtype); unbecome_root(); + if (result) + store_uid_sid_cache(psid, *puid); return result; } @@ -664,6 +861,7 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) sid_to_string(sid_str, psid), (unsigned int)*puid )); + store_uid_sid_cache(psid, *puid); return True; } @@ -681,6 +879,9 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) *sidtype = SID_NAME_UNKNOWN; + if (fetch_gid_from_cache(pgid, psid)) + return True; + /* * First we must look up the name and decide if this is a group sid. */ @@ -691,6 +892,8 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) become_root(); result = local_sid_to_gid(pgid, psid, sidtype); unbecome_root(); + if (result) + store_gid_sid_cache(psid, *pgid); return result; } @@ -729,6 +932,7 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) sid_to_string(sid_str, psid), (unsigned int)*pgid )); + store_gid_sid_cache(psid, *pgid); return True; } -- cgit From 96cafdd7c735338da0616e0ad638282095f4c4d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Feb 2003 02:34:44 +0000 Subject: Fix from Corny.Bondad@hp.com for missing if (setting_acls) on default perms. Jeremy. (This used to be commit 793609cbc2f657b91a59aec4a3f403bf826c7156) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 5069db8097..0c8b08e4d5 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -699,11 +699,11 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->unix_ug.world = -1; pace->trustee = global_sid_World; pace->attr = ALLOW_ACE; - if (setting_acl) + if (setting_acl) { pace->perms = 0; - else + apply_default_perms(fsp, pace, S_IROTH); + } else pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); - apply_default_perms(fsp, pace, S_IROTH); DLIST_ADD(*pp_ace, pace); } -- cgit From 3fd3bb38e24d39cae58894ce2b6bcb750b9de1b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Feb 2003 22:31:05 +0000 Subject: Fix inspired by Stefan (metze) Metzmacher - cache the sidtype also. Jeremy. (This used to be commit efc92697801f5e62a89eda33e1826094c096900f) --- source3/smbd/uid.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index e7c00ba456..7c0d3805e7 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -551,19 +551,21 @@ static struct uid_sid_cache { struct uid_sid_cache *next, *prev; uid_t uid; DOM_SID sid; + enum SID_NAME_USE sidtype; } *uid_sid_cache_head; static struct gid_sid_cache { struct gid_sid_cache *next, *prev; gid_t gid; DOM_SID sid; + enum SID_NAME_USE sidtype; } *gid_sid_cache_head; /***************************************************************** Find a SID given a uid. *****************************************************************/ -static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) +static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, enum SID_NAME_USE *psidtype, uid_t uid) { struct uid_sid_cache *pc; @@ -571,6 +573,7 @@ static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) if (pc->uid == uid) { fstring sid; *psid = pc->sid; + *psidtype = pc->sidtype; DEBUG(3,("fetch sid from uid cache %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); DLIST_PROMOTE(uid_sid_cache_head, pc); @@ -584,7 +587,7 @@ static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) Find a uid given a SID. *****************************************************************/ -static BOOL fetch_uid_from_cache(uid_t *puid, const DOM_SID *psid) +static BOOL fetch_uid_from_cache(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE sidtype) { struct uid_sid_cache *pc; @@ -605,7 +608,7 @@ static BOOL fetch_uid_from_cache(uid_t *puid, const DOM_SID *psid) Store uid to SID mapping in cache. *****************************************************************/ -static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) +static void store_uid_sid_cache(const DOM_SID *psid, const enum SID_NAME_USE sidtype, uid_t uid) { struct uid_sid_cache *pc; @@ -629,6 +632,7 @@ static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) return; pc->uid = uid; sid_copy(&pc->sid, psid); + pc->sidtype = sidtype; DLIST_ADD(uid_sid_cache_head, pc); n_uid_sid_cache++; } @@ -637,7 +641,7 @@ static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) Find a SID given a gid. *****************************************************************/ -static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) +static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, enum SID_NAME_USE *psidtype, gid_t gid) { struct gid_sid_cache *pc; @@ -645,6 +649,7 @@ static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) if (pc->gid == gid) { fstring sid; *psid = pc->sid; + *psidtype = pc->sidtype; DEBUG(3,("fetch sid from gid cache %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); DLIST_PROMOTE(gid_sid_cache_head, pc); @@ -658,7 +663,7 @@ static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) Find a gid given a SID. *****************************************************************/ -static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) +static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE sidtype) { struct gid_sid_cache *pc; @@ -679,7 +684,7 @@ static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) Store gid to SID mapping in cache. *****************************************************************/ -static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) +static void store_gid_sid_cache(const DOM_SID *psid, const enum SID_NAME_USE sidtype, gid_t gid) { struct gid_sid_cache *pc; @@ -703,6 +708,7 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) return; pc->gid = gid; sid_copy(&pc->sid, psid); + pc->sidtype = sidtype; DLIST_ADD(gid_sid_cache_head, pc); n_gid_sid_cache++; } @@ -717,9 +723,10 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) { uid_t low, high; + enum SID_NAME_USE sidtype; fstring sid; - if (fetch_sid_from_uid_cache(psid, uid)) + if (fetch_sid_from_uid_cache(psid, &sidtype, uid)) return psid; if (lp_winbind_uid(&low, &high) && uid >= low && uid <= high) { @@ -729,7 +736,7 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) (unsigned int)uid, sid_to_string(sid, psid))); if (psid) - store_uid_sid_cache(psid, uid); + store_uid_sid_cache(psid, SID_NAME_USER, uid); return psid; } } @@ -741,7 +748,7 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); if (psid) - store_uid_sid_cache(psid, uid); + store_uid_sid_cache(psid, SID_NAME_USER, uid); return psid; } @@ -755,9 +762,10 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) { gid_t low, high; + enum SID_NAME_USE sidtype; fstring sid; - if (fetch_sid_from_gid_cache(psid, gid)) + if (fetch_sid_from_gid_cache(psid, &sidtype, gid)) return psid; if (lp_winbind_gid(&low, &high) && gid >= low && gid <= high) { @@ -767,7 +775,7 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) (unsigned int)gid, sid_to_string(sid, psid))); if (psid) - store_gid_sid_cache(psid, gid); + store_gid_sid_cache(psid, SID_NAME_DOM_GRP, gid); return psid; } } @@ -776,7 +784,7 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) psid = local_gid_to_sid(psid, gid); DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); if (psid) - store_gid_sid_cache(psid, gid); + store_gid_sid_cache(psid, SID_NAME_DOM_GRP, gid); return psid; } @@ -792,7 +800,7 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) { fstring sid_str; - if (fetch_uid_from_cache(puid, psid)) + if (fetch_uid_from_cache(puid, psid, *sidtype)) return True; /* if we know its local then don't try winbindd */ @@ -802,7 +810,7 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) result = local_sid_to_uid(puid, psid, sidtype); unbecome_root(); if (result) - store_uid_sid_cache(psid, *puid); + store_uid_sid_cache(psid, *sidtype, *puid); return result; } @@ -853,7 +861,7 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) result = local_sid_to_uid(puid, psid, sidtype); unbecome_root(); if (result) - store_uid_sid_cache(psid, *puid); + store_uid_sid_cache(psid, *sidtype, *puid); return result; } @@ -861,7 +869,7 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) sid_to_string(sid_str, psid), (unsigned int)*puid )); - store_uid_sid_cache(psid, *puid); + store_uid_sid_cache(psid, *sidtype, *puid); return True; } @@ -879,7 +887,7 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) *sidtype = SID_NAME_UNKNOWN; - if (fetch_gid_from_cache(pgid, psid)) + if (fetch_gid_from_cache(pgid, psid, *sidtype)) return True; /* @@ -893,7 +901,7 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) result = local_sid_to_gid(pgid, psid, sidtype); unbecome_root(); if (result) - store_gid_sid_cache(psid, *pgid); + store_gid_sid_cache(psid, *sidtype, *pgid); return result; } @@ -932,7 +940,7 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) sid_to_string(sid_str, psid), (unsigned int)*pgid )); - store_gid_sid_cache(psid, *pgid); + store_gid_sid_cache(psid, *sidtype, *pgid); return True; } -- cgit From 486fa37dc67b5b3a9534479fed55ae9298fb2097 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Feb 2003 06:25:58 +0000 Subject: Added comments to make it clearer when we're assigning a pointer that it must not be freed afterwards. Jeremy. (This used to be commit 4015e39d3666dbe240808c9007a8b8faca012a3d) --- source3/smbd/posix_acls.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0c8b08e4d5..ee8a4430e1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1000,8 +1000,16 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); return False; } + /* + * We must not free current_ace here as its + * pointer is now owned by the dir_ace list. + */ current_ace = dup_ace; } else { + /* + * We must not free current_ace here as its + * pointer is now owned by the dir_ace list. + */ current_ace = NULL; } } @@ -1036,6 +1044,10 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); print_canon_ace( current_ace, 0); } all_aces_are_inherit_only = False; + /* + * We must not free current_ace here as its + * pointer is now owned by the file_ace list. + */ current_ace = NULL; } -- cgit From e72ecdc862804339912325fe848401e8ec57cde7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Feb 2003 02:35:54 +0000 Subject: Merge of server-side authentication changes to 3.0: - user_ok() and user_in_group() now take a list of groups, instead of looking for the user in the members of all groups. - The 'server_info' returned from the authentication is now kept around - in future we won't copy the sesion key, username etc, we will just referece them directly. - rhosts upgraded to use the SAM if possible, otherwise fake up based on getpwnam(). - auth_util code to deal with groups upgraded to deal with non-winbind domain members again. Andrew Bartlett (This used to be commit 74b5436c75114170ce7c780c19226103d0df9060) --- source3/smbd/password.c | 59 +++++++++++++++++++++++++++++++--------------- source3/smbd/posix_acls.c | 2 +- source3/smbd/service.c | 22 ++++++++--------- source3/smbd/sesssetup.c | 60 ++++++++++++++++++++--------------------------- source3/smbd/uid.c | 4 ++-- 5 files changed, 79 insertions(+), 68 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 4ce99e96bb..784c1525c8 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -62,11 +62,15 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; - + SAFE_FREE(vuser->homedir); - + SAFE_FREE(vuser->unix_homedir); + SAFE_FREE(vuser->logon_script); + session_yield(vuser); + free_server_info(&vuser->server_info); + DLIST_REMOVE(validated_users, vuser); /* clear the vuid from the 'cache' on each connection, and @@ -93,11 +97,15 @@ void invalidate_all_vuids(void) } } -/**************************************************************************** -register a uid/name pair as being valid and that a valid password -has been given. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. -****************************************************************************/ +/** + * register that a valid login has been performed, establish 'session'. + * @param server_info The token returned from the authentication process. + * (now 'owned' by register_vuid) + * + * @return Newly allocated vuid, biased by an offset. (This allows us to + * tell random client vuid's (normally zero) from valid vuids.) + * + */ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) { @@ -136,6 +144,7 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) if (!IS_SAM_UNIX_USER(server_info->sam_account)) { DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); free(vuser); + free_server_info(&server_info); return UID_FIELD_INVALID; } @@ -147,20 +156,24 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { DEBUG(0,("register_vuid: failed to memdup vuser->groups\n")); free(vuser); + free_server_info(&server_info); return UID_FIELD_INVALID; } } vuser->guest = server_info->guest; fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); - fstrcpy(vuser->user.smb_name, smb_name); + + /* This is a potentially untrusted username */ + alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name)); + fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); { /* Keep the homedir handy */ const char *homedir = pdb_get_homedir(server_info->sam_account); - const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); /* should be optained by SMS */ + const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); const char *logon_script = pdb_get_logon_script(server_info->sam_account); if (homedir) { vuser->homedir = smb_xstrdup(homedir); @@ -188,10 +201,18 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) vuser->nt_user_token = dup_nt_token(server_info->ptok); } else { DEBUG(1, ("server_info does not contain a user_token - cannot continue\n")); - free(vuser); + free_server_info(&server_info); + SAFE_FREE(vuser->homedir); + SAFE_FREE(vuser->unix_homedir); + SAFE_FREE(vuser->logon_script); + + SAFE_FREE(vuser); return UID_FIELD_INVALID; } + /* use this to keep tabs on all our info from the authentication */ + vuser->server_info = server_info; + DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid)); next_vuid++; @@ -246,7 +267,7 @@ void add_session_user(const char *user) /**************************************************************************** check if a username is valid ****************************************************************************/ -BOOL user_ok(const char *user,int snum) +BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) { char **valid, **invalid; BOOL ret; @@ -257,7 +278,7 @@ BOOL user_ok(const char *user,int snum) if (lp_invalid_users(snum)) { str_list_copy(&invalid, lp_invalid_users(snum)); if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { - ret = !user_in_list(user, (const char **)invalid); + ret = !user_in_list(user, (const char **)invalid, groups, n_groups); } } if (invalid) @@ -266,7 +287,7 @@ BOOL user_ok(const char *user,int snum) if (ret && lp_valid_users(snum)) { str_list_copy(&valid, lp_valid_users(snum)); if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) { - ret = user_in_list(user, (const char **)valid); + ret = user_in_list(user, (const char **)valid, groups, n_groups); } } if (valid) @@ -275,7 +296,7 @@ BOOL user_ok(const char *user,int snum) if (ret && lp_onlyuser(snum)) { char **user_list = str_list_make (lp_username(snum), NULL); if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) { - ret = user_in_list(user, (const char **)user_list); + ret = user_in_list(user, (const char **)user_list, groups, n_groups); } if (user_list) str_list_free (&user_list); } @@ -294,7 +315,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) setnetgrent(group); while (getnetgrent(&host, &user, &domain)) { if (user) { - if (user_ok(user, snum) && + if (user_ok(user, snum, NULL, 0) && password_ok(user,password)) { endnetgrent(); return(user); @@ -349,7 +370,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) while (*member) { static fstring name; fstrcpy(name,member); - if (user_ok(name,snum) && + if (user_ok(name,snum, NULL, 0) && password_ok(name,password)) { endgrent(); return(&name[0]); @@ -408,7 +429,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, auser = strtok(NULL,LIST_SEP)) { fstring user2; fstrcpy(user2,auser); - if (!user_ok(user2,snum)) + if (!user_ok(user2,snum, NULL, 0)) continue; if (password_ok(user2,password)) { @@ -443,7 +464,7 @@ and given password ok (%s)\n", user)); } else { fstring user2; fstrcpy(user2,auser); - if (user_ok(user2,snum) && password_ok(user2,password)) { + if (user_ok(user2,snum, NULL, 0) && password_ok(user2,password)) { ok = True; fstrcpy(user,user2); DEBUG(3,("authorise_login: ACCEPTED: user list username \ @@ -468,7 +489,7 @@ and given password ok (%s)\n", user)); *guest = True; } - if (ok && !user_ok(user,snum)) { + if (ok && !user_ok(user, snum, NULL, 0)) { DEBUG(0,("authorise_login: rejected invalid user %s\n",user)); ok = False; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ee8a4430e1..93a57925f1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -573,7 +573,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) * not uids/gids. */ - return user_in_group_list(u_name, g_name ); + return user_in_group_list(u_name, g_name, NULL, 0); } /**************************************************************************** diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2a41a6db1c..1c7e4017b0 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -258,7 +258,7 @@ static NTSTATUS share_sanity_checks(int snum, pstring dev) /**************************************************************************** readonly share? ****************************************************************************/ -static void set_read_only(connection_struct *conn) +static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_groups) { char **list; char *service = lp_servicename(conn->service); @@ -271,7 +271,7 @@ static void set_read_only(connection_struct *conn) if (!str_list_substitute(list, "%S", service)) { DEBUG(0, ("ERROR: read list substitution failed\n")); } - if (user_in_list(conn->user, (const char **)list)) + if (user_in_list(conn->user, (const char **)list, groups, n_groups)) conn->read_only = True; str_list_free(&list); } @@ -281,7 +281,7 @@ static void set_read_only(connection_struct *conn) if (!str_list_substitute(list, "%S", service)) { DEBUG(0, ("ERROR: write list substitution failed\n")); } - if (user_in_list(conn->user, (const char **)list)) + if (user_in_list(conn->user, (const char **)list, groups, n_groups)) conn->read_only = False; str_list_free(&list); } @@ -291,7 +291,7 @@ static void set_read_only(connection_struct *conn) /**************************************************************************** admin user check ****************************************************************************/ -static void set_admin_user(connection_struct *conn) +static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_groups) { /* admin user check */ @@ -299,7 +299,7 @@ static void set_admin_user(connection_struct *conn) marked read_only. Changed as I don't think this is needed, but old code left in case there is a problem here. */ - if (user_in_list(conn->user,lp_admin_users(conn->service)) + if (user_in_list(conn->user,lp_admin_users(conn->service), groups, n_groups) #if 0 && !conn->read_only #endif @@ -364,14 +364,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } else if (vuser) { if (vuser->guest) { if (!lp_guest_ok(snum)) { - DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)", lp_servicename(snum))); + DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; } } else { - if (!user_ok(vuser->user.unix_name, snum)) { - DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)", vuser->user.unix_name, lp_servicename(snum))); + if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) { + DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; @@ -427,9 +427,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, string_set(&conn->user,user); conn->nt_user_token = NULL; - set_read_only(conn); + set_read_only(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0); - set_admin_user(conn); + set_admin_user(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0); /* * If force user is true, then store the @@ -499,7 +499,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * Otherwise, the meaning of the '+' would be ignored. */ if (conn->force_user && user_must_be_member) { - if (user_in_group_list( user, gname )) { + if (user_in_group_list( user, gname, NULL, 0)) { conn->gid = gid; DEBUG(3,("Forced group %s for member %s\n",gname,user)); } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index bb7d17be56..eafe805aba 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -148,6 +148,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB auth_data; auth_serversupplied_info *server_info = NULL; ADS_STRUCT *ads; + BOOL foreign = False; if (!spnego_parse_krb5_wrap(*secblob, &ticket)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); @@ -168,6 +169,8 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + data_blob_free(&auth_data); + DEBUG(3,("Ticket name is [%s]\n", client)); p = strchr_m(client, '@'); @@ -183,12 +186,20 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!lp_allow_trusted_domains()) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - /* this gives a fully qualified user name (ie. with full realm). - that leads to very long usernames, but what else can we do? */ - asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client); - } else { - user = strdup(client); + foreign = True; + } + + /* this gives a fully qualified user name (ie. with full realm). + that leads to very long usernames, but what else can we do? */ + asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client); + + pw = Get_Pwnam(user); + if (!pw && !foreign) { + pw = Get_Pwnam(client); + SAFE_FREE(user); + user = smb_xstrdup(client); } + ads_destroy(&ads); /* setup the string used by %U */ @@ -196,19 +207,6 @@ static int reply_spnego_kerberos(connection_struct *conn, reload_services(True); - /* the password is good - let them in */ - pw = Get_Pwnam(user); - if (!pw && !strstr(user, lp_winbind_separator())) { - char *user2; - /* try it with a winbind domain prefix */ - asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user); - pw = Get_Pwnam(user2); - if (pw) { - free(user); - user = user2; - } - } - if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); return ERROR_NT(NT_STATUS_NO_SUCH_USER); @@ -219,10 +217,10 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(ret); } + /* register_vuid keeps the server info */ sess_vuid = register_vuid(server_info, user); free(user); - free_server_info(&server_info); if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); @@ -263,8 +261,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; - sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user /* check this for weird */); - + /* register_vuid keeps the server info */ + sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user); + (*auth_ntlmssp_state)->server_info = NULL; + if (sess_vuid == -1) { nt_status = NT_STATUS_LOGON_FAILURE; } else { @@ -272,7 +272,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); - if ((*auth_ntlmssp_state)->server_info && (*auth_ntlmssp_state)->server_info->guest) { + if (server_info->guest) { SSVAL(outbuf,smb_vwv2,1); } @@ -285,7 +285,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, data_blob_free(&response); if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - auth_ntlmssp_end(&global_ntlmssp_state); + auth_ntlmssp_end(auth_ntlmssp_state); } return ret; @@ -463,7 +463,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern BOOL global_encrypted_passwords_negotiated; extern BOOL global_spnego_negotiated; extern int Protocol; - extern userdom_struct current_user_info; extern int max_send; auth_usersupplied_info *user_info = NULL; @@ -584,13 +583,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, domain,native_os,native_lanman)); } - /* don't allow for weird usernames or domains */ - alpha_strcpy(user, user, ". _-$", sizeof(user)); - alpha_strcpy(domain, domain, ". _-@", sizeof(domain)); - if (strstr(user, "..") || strstr(domain,"..")) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name())); if (*user) { @@ -609,7 +601,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, fstrcpy(sub_user, lp_guestaccount()); } - fstrcpy(current_user_info.smb_name,sub_user); + sub_set_smb_name(sub_user); reload_services(True); @@ -692,15 +684,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ + /* register_vuid keeps the server info */ sess_vuid = register_vuid(server_info, sub_user); - - free_server_info(&server_info); if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 7c0d3805e7..6ac3528b1a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -60,7 +60,7 @@ BOOL change_to_guest(void) static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { - int i; + unsigned i; for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) if (conn->vuid_cache.list[i] == vuser->vuid) return(True); @@ -70,7 +70,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) return False; } - if (!user_ok(vuser->user.unix_name,snum)) + if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups)) return(False); if (!share_access_check(conn, snum, vuser, conn->read_only ? FILE_READ_DATA : FILE_WRITE_DATA)) { -- cgit From 266ec4aac04cb8666234f18baa38ff6387f40cb3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Feb 2003 03:09:08 +0000 Subject: Merge doxygen, signed/unsigned, const and other small fixes from HEAD to 3.0. Andrew Bartlett (This used to be commit 9ef0d40c3f8aef52ab321dc065264c42065bc876) --- source3/smbd/dosmode.c | 2 +- source3/smbd/mangle_hash2.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 77d8c9cc92..6c21dc04d0 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -181,7 +181,7 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) /******************************************************************* chmod a file - but preserve some bits ********************************************************************/ -int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *st) +int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_STAT *st) { SMB_STRUCT_STAT st1; int mask=0; diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index bbc9020eab..eda509214d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -203,7 +203,7 @@ static const char *cache_lookup(u32 hash) */ static BOOL is_mangled_component(const char *name) { - int len, i; + unsigned int len, i; M_DEBUG(10,("is_mangled_component %s ?\n", name)); @@ -368,7 +368,7 @@ static void mangle_reset(void) static BOOL check_cache(char *name) { u32 hash, multiplier; - int i; + unsigned int i; const char *prefix; char extension[4]; @@ -489,8 +489,8 @@ static void name_map(char *name, BOOL need83, BOOL cache83) char *dot_p; char lead_chars[7]; char extension[4]; - int extension_length, i; - int prefix_len; + unsigned int extension_length, i; + unsigned int prefix_len; u32 hash, v; char new_name[13]; -- cgit From 23b3b29eec61860155404333f6e70ebd24b50940 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 25 Feb 2003 20:53:53 +0000 Subject: Progress on CR 601 cache the printer_info_2 with the open printer handle. cache is invalidated on a mod_a_printer() call **on that smbd**. Yes, this means that the window for admins to step on each other from different clients just got larger, but since handles a generally short lived this is probably ok. (This used to be commit 31272d3b6bb9ec62fd666301c7adfa0c1720a99b) --- source3/smbd/lanman.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 25f390be55..98857c6d32 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -500,7 +500,7 @@ static BOOL get_driver_name(int snum, pstring drivername) NT_PRINTER_INFO_LEVEL *info = NULL; BOOL in_tdb = False; - get_a_printer (&info, 2, lp_servicename(snum)); + get_a_printer (NULL, &info, 2, lp_servicename(snum)); if (info != NULL) { pstrcpy( drivername, info->info_2->drivername); in_tdb = True; @@ -522,7 +522,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, NT_PRINTER_DRIVER_INFO_LEVEL driver; NT_PRINTER_INFO_LEVEL *printer = NULL; - if ( !W_ERROR_IS_OK(get_a_printer( &printer, 2, lp_servicename(snum))) ) { + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", lp_servicename(snum))); goto err; @@ -679,7 +679,7 @@ static int get_printerdrivernumber(int snum) NT_PRINTER_DRIVER_INFO_LEVEL driver; NT_PRINTER_INFO_LEVEL *printer = NULL; - if ( !W_ERROR_IS_OK(get_a_printer( &printer, 2, lp_servicename(snum))) ) { + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", lp_servicename(snum))); goto done; -- cgit From fb3e4b87973e9ad0c818e8d9dd60329c47f22afe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Feb 2003 01:04:34 +0000 Subject: Fix to allow blocking lock notification to be done rapidly (no wait for smb -> smb lock release). Adds new PENDING_LOCK type to lockdb (does not interfere with existing locks). Jeremy. (This used to be commit 766928bbba1e597c9c2b12458dd8d37e6080593e) --- source3/smbd/blocking.c | 78 ++++++++++++++++++++++++++++++++++++++++++++----- source3/smbd/process.c | 7 +++++ source3/smbd/reply.c | 7 +++-- 3 files changed, 82 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 14239272c2..581ce43f91 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. Blocking Locking functions - Copyright (C) Jeremy Allison 1998 + Copyright (C) Jeremy Allison 1998-2003 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 @@ -33,6 +33,9 @@ typedef struct { files_struct *fsp; time_t expire_time; int lock_num; + SMB_BIG_UINT offset; + SMB_BIG_UINT count; + uint16 lock_pid; char *inbuf; int length; } blocking_lock_record; @@ -77,13 +80,18 @@ static BOOL in_chained_smb(void) return (chain_size != 0); } +static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); + /**************************************************************************** Function to push a blocking lock request onto the lock queue. ****************************************************************************/ -BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) +BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, + int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { + static BOOL set_lock_msg; blocking_lock_record *blr; + NTSTATUS status; if(in_chained_smb() ) { DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); @@ -110,11 +118,31 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int blr->fsp = get_fsp_from_pkt(inbuf); blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; blr->lock_num = lock_num; + blr->lock_pid = lock_pid; + blr->offset = offset; + blr->count = count; memcpy(blr->inbuf, inbuf, length); blr->length = length; + /* Add a pending lock record for this. */ + status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + lock_pid, sys_getpid(), blr->fsp->conn->cnum, + offset, count, + PENDING_LOCK); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); + free_blocking_lock_record(blr); + return False; + } + ubi_slAddTail(&blocking_lock_queue, blr); + /* Ensure we'll receive messages when this is unlocked. */ + if (!set_lock_msg) { + message_register(MSG_SMB_UNLOCK, received_unlock_msg); + set_lock_msg = True; + } DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, @@ -493,6 +521,10 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -520,6 +552,9 @@ void remove_pending_lock_requests_by_mid(int mid) file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -530,9 +565,20 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); } } +/**************************************************************************** + Set a flag as an unlock request affects one of our pending locks. +*****************************************************************************/ + +static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len) +{ + DEBUG(10,("received_unlock_msg\n")); + process_blocking_lock_queue(time(NULL)); +} + /**************************************************************************** Return the number of seconds to the next blocking locks timeout, or default_timeout *****************************************************************************/ + unsigned blocking_locks_timeout(unsigned default_timeout) { unsigned timeout = default_timeout; @@ -540,22 +586,21 @@ unsigned blocking_locks_timeout(unsigned default_timeout) blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue); /* note that we avoid the time() syscall if there are no blocking locks */ - if (!blr) { + if (!blr) return timeout; - } t = time(NULL); while (blr) { - if (timeout > (blr->expire_time - t)) { + if ((blr->expire_time != (time_t)-1) && + (timeout > (blr->expire_time - t))) { timeout = blr->expire_time - t; } blr = (blocking_lock_record *)ubi_slNext(blr); } - if (timeout < 1) { + if (timeout < 1) timeout = 1; - } return timeout; } @@ -604,6 +649,10 @@ void process_blocking_lock_queue(time_t t) DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", fsp->fnum, fsp->fsp_name )); + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True); + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); @@ -617,6 +666,11 @@ void process_blocking_lock_queue(time_t t) * Remove the entry and return an error to the client. */ blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -628,6 +682,11 @@ void process_blocking_lock_queue(time_t t) * Remove the entry and return an error to the client. */ blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); change_to_root_user(); @@ -641,6 +700,11 @@ void process_blocking_lock_queue(time_t t) */ if(blocking_lock_record_process(blr)) { + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); change_to_root_user(); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c002abad16..57bc236eef 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1271,6 +1271,13 @@ void smbd_process(void) lp_talloc_free(); main_loop_talloc_free(); + /* Did someone ask for immediate checks on things like blocking locks ? */ + if (select_timeout == 0) { + if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + return; + num_smbs = 0; /* Reset smb counter. */ + } + while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) return; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 580878fe32..71e880476c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1609,7 +1609,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, -1, 0)) { + if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos, + (SMB_BIG_UINT)numtoread)) { END_PROFILE(SMBlockread); return -1; } @@ -2514,7 +2515,7 @@ int reply_lock(connection_struct *conn, * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, -1, 0)) { + if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) { END_PROFILE(SMBlock); return -1; } @@ -3955,7 +3956,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) { + if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) { END_PROFILE(SMBlockingX); return -1; } -- cgit From 0d30cdf66c4e186e20a09e1e8b39d501e662ae50 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 27 Feb 2003 21:22:36 +0000 Subject: additional fix for CR 601 * distinguish WinXP from Win2k * add a 1/3 of a second delay in OpenPrinter in order to trigger a LAN/WAN optimization in 2k clients. (This used to be commit c7712fa054d21b4884a78b7ea6c0fb8b3d637c6b) --- source3/smbd/sesssetup.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index eafe805aba..b0ef78f447 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -581,6 +581,21 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", domain,native_os,native_lanman)); + + /* + * we distinguish between 2K and XP by the "Native Lan Manager" string + * WinXP => "Windows 2002 5.1" + * Win2k => "Windows 2000 5.0" + * NT4 => "Windows NT 4.0" + * Win9x => "Windows 4.0" + */ + + if ( ra_type == RA_WIN2K ) { + if ( 0 == strcmp( native_lanman, "Windows 2002 5.1" ) ) + set_remote_arch( RA_WINXP ); + } + + } DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name())); -- cgit From 1738f7c2b7b0d2bdfa6414267d20b2c08e204f78 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 27 Feb 2003 21:37:30 +0000 Subject: don't pass NULL pointers to strcmp() (This used to be commit 9b0a49a0bc177f9637f197b3ab4613f25db1b43d) --- source3/smbd/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index e022d26ea3..2a5f7ffd71 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1063,8 +1063,8 @@ char *DirCacheCheck( const char *path, const char *name, int snum ) NULL != entry; entry = (dir_cache_entry *)ubi_dlNext( entry ) ) { if( entry->snum == snum - && 0 == strcmp( name, entry->name ) - && 0 == strcmp( path, entry->path ) ) { + && entry->name && 0 == strcmp( name, entry->name ) + && entry->path && 0 == strcmp( path, entry->path ) ) { DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); return( entry->dname ); } -- cgit From e4c8e7ad8a154d9806a7b1214adb9982dc28f4b1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 27 Feb 2003 23:21:37 +0000 Subject: and the winner of "i should have just written it in assembly is..." don't use pstrcpy() when you are not dealing with pstrings. (This used to be commit e1b21381f3b5cf6f97c101642e9286df9987998e) --- source3/smbd/dir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 2a5f7ffd71..10241e88d9 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1028,9 +1028,9 @@ void DirCacheAdd( const char *path, char *name, char *dname, int snum ) return; /* so just return as if nothing happened. */ /* Set pointers correctly and load values. */ - entry->path = pstrcpy( (char *)&entry[1], path); - entry->name = pstrcpy( &(entry->path[pathlen]), name); - entry->dname = pstrcpy( &(entry->name[namelen]), dname); + entry->path = memcpy( (char *)&entry[1], path, strlen(path) ); + entry->name = memcpy( &(entry->path[pathlen]), name, strlen(name) ); + entry->dname = memcpy( &(entry->name[namelen]), dname, strlen(dname) ); entry->snum = snum; /* Add the new entry to the linked list. */ -- cgit From 19995a40c15b33fe82a3d2399de00f8972325d1e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 27 Feb 2003 23:54:58 +0000 Subject: don't forget the NULL (This used to be commit 4aa611958ebedfafbb9bfc1070b7d632272e1aaf) --- source3/smbd/dir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 10241e88d9..95acf4a262 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1028,9 +1028,9 @@ void DirCacheAdd( const char *path, char *name, char *dname, int snum ) return; /* so just return as if nothing happened. */ /* Set pointers correctly and load values. */ - entry->path = memcpy( (char *)&entry[1], path, strlen(path) ); - entry->name = memcpy( &(entry->path[pathlen]), name, strlen(name) ); - entry->dname = memcpy( &(entry->name[namelen]), dname, strlen(dname) ); + entry->path = memcpy( (char *)&entry[1], path, strlen(path)+1 ); + entry->name = memcpy( &(entry->path[pathlen]), name, strlen(name)+1 ); + entry->dname = memcpy( &(entry->name[namelen]), dname, strlen(dname)+1 ); entry->snum = snum; /* Add the new entry to the linked list. */ -- cgit From 28074d957aa7ee5b4df60e2e553ba1212f217572 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Mar 2003 20:12:37 +0000 Subject: Const warning fixes. Jeremy. (This used to be commit 30e8ae8e030b5dccaef9612dca24907be547acdf) --- source3/smbd/vfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 6574a34eaa..533c64b229 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -636,7 +636,7 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr) A wrapper for vfs_chdir(). ********************************************************************/ -int vfs_ChDir(connection_struct *conn, char *path) +int vfs_ChDir(connection_struct *conn, const char *path) { int res; static pstring LastDir=""; @@ -784,7 +784,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) /* check if the file 'nmae' is a symlink, in that case check that it point to a file that reside under the 'dir' tree */ -static BOOL readlink_check(connection_struct *conn, char *dir, char *name) +static BOOL readlink_check(connection_struct *conn, const char *dir, char *name) { BOOL ret = True; pstring flink; -- cgit From 442a55b6b480a9d594ee0641f46b838cdc209377 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Mar 2003 00:30:47 +0000 Subject: Found at Connectathon, .NET RC1 arranges trans/trans2/nttrans parameters differently to W2K, cope with this. Jeremy. (This used to be commit 5e2755508f08ecf561348d4edf0a4064732c5213) --- source3/smbd/ipc.c | 101 +++++++++++++++++++++++++++++++++++------------- source3/smbd/nttrans.c | 102 ++++++++++++++++++++++++++++++++++++++----------- source3/smbd/trans2.c | 93 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 227 insertions(+), 69 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7fe02dbccf..08337c2901 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -360,52 +360,66 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int uint16 *setup=NULL; int outsize = 0; uint16 vuid = SVAL(inbuf,smb_uid); - int tpscnt = SVAL(inbuf,smb_vwv0); - int tdscnt = SVAL(inbuf,smb_vwv1); - int mprcnt = SVAL(inbuf,smb_vwv2); - int mdrcnt = SVAL(inbuf,smb_vwv3); - int msrcnt = CVAL(inbuf,smb_vwv4); + unsigned int tpscnt = SVAL(inbuf,smb_vwv0); + unsigned int tdscnt = SVAL(inbuf,smb_vwv1); + unsigned int mprcnt = SVAL(inbuf,smb_vwv2); + unsigned int mdrcnt = SVAL(inbuf,smb_vwv3); + unsigned int msrcnt = CVAL(inbuf,smb_vwv4); BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); BOOL one_way = BITSETW(inbuf+smb_vwv5,1); - int pscnt = SVAL(inbuf,smb_vwv9); - int psoff = SVAL(inbuf,smb_vwv10); - int dscnt = SVAL(inbuf,smb_vwv11); - int dsoff = SVAL(inbuf,smb_vwv12); - int suwcnt = CVAL(inbuf,smb_vwv13); + unsigned int pscnt = SVAL(inbuf,smb_vwv9); + unsigned int psoff = SVAL(inbuf,smb_vwv10); + unsigned int dscnt = SVAL(inbuf,smb_vwv11); + unsigned int dsoff = SVAL(inbuf,smb_vwv12); + unsigned int suwcnt = CVAL(inbuf,smb_vwv13); START_PROFILE(SMBtrans); memset(name, '\0',sizeof(name)); srvstr_pull_buf(inbuf, name, smb_buf(inbuf), sizeof(name), STR_TERMINATE); - if (dscnt > tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters"); - } + if (dscnt > tdscnt || pscnt > tpscnt) + goto bad_param; if (tdscnt) { if((data = (char *)malloc(tdscnt)) == NULL) { - DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt)); + DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt)); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } + if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) + goto bad_param; + if (smb_base(inbuf)+dsoff+dscnt > inbuf + size) + goto bad_param; + memcpy(data,smb_base(inbuf)+dsoff,dscnt); } if (tpscnt) { if((params = (char *)malloc(tpscnt)) == NULL) { - DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt)); + DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt)); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } + if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) + goto bad_param; + if (smb_base(inbuf)+psoff+pscnt > inbuf + size) + goto bad_param; + memcpy(params,smb_base(inbuf)+psoff,pscnt); } if (suwcnt) { int i; if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { - DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16)))); - END_PROFILE(SMBtrans); - return(ERROR_DOS(ERRDOS,ERRnomem)); - } + DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16)))); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size) + goto bad_param; + if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD))) + goto bad_param; + for (i=0;i tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters"); - } + if (dscnt > tdscnt || pscnt > tpscnt) + goto bad_param; - if (pcnt) + if (pcnt) { + if (pdisp+pcnt >= tpscnt) + goto bad_param; + if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) + goto bad_param; + if (smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) + goto bad_param; + if (params + pdisp < params) + goto bad_param; + memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); - if (dcnt) + } + + if (dcnt) { + if (ddisp+dcnt >= tdscnt) + goto bad_param; + if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) + goto bad_param; + if (smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) + goto bad_param; + if (data + ddisp < data) + goto bad_param; + memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); + } } @@ -517,4 +554,14 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int END_PROFILE(SMBtrans); return(outsize); + + + bad_param: + + DEBUG(0,("reply_trans: invalid trans parameters\n")); + SAFE_FREE(data); + SAFE_FREE(params); + SAFE_FREE(setup); + END_PROFILE(SMBtrans); + return ERROR_DOS(ERRDOS,ERRinvalidparam); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bfac4e82e3..375c6c44f6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1771,8 +1771,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) { DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", CVAL(inbuf, smb_wct), 19 + (setup_count/2))); - END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRerror); + goto bad_param; } /* Allocate the space for the setup, the maximum needed parameters and data */ @@ -1799,21 +1798,38 @@ due to being in oplock break state.\n", (unsigned int)function_code )); num_data_sofar = data_count; if (parameter_count > total_parameter_count || data_count > total_data_count) - exit_server("reply_nttrans: invalid sizes in packet."); + goto bad_param; if(setup) { - memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count)); + if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) || + (smb_nt_SetupStart + setup_count < setup_count)) + goto bad_param; + if (smb_nt_SetupStart + setup_count > length) + goto bad_param; + + memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); dump_data(10, setup, setup_count); } if(params) { - memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count)); + if ((parameter_offset + parameter_count < parameter_offset) || + (parameter_offset + parameter_count < parameter_count)) + goto bad_param; + if (smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) + goto bad_param; + + memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); dump_data(10, params, parameter_count); } if(data) { - memcpy( data, smb_base(inbuf) + data_offset, data_count); DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); + if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) + goto bad_param; + if (smb_base(inbuf) + data_offset + data_count > inbuf + length) + goto bad_param; + + memcpy( data, smb_base(inbuf) + data_offset, data_count); dump_data(10, data, data_count); } @@ -1826,6 +1842,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { BOOL ret; + uint32 parameter_displacement; + uint32 data_displacement; ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); @@ -1837,25 +1855,57 @@ due to being in oplock break state.\n", (unsigned int)function_code )); DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", (smb_read_error == READ_ERROR) ? "error" : "timeout" )); } - SAFE_FREE(params); - SAFE_FREE(data); - SAFE_FREE(setup); - END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRerror); + goto bad_param; } /* Revise total_params and total_data in case they have changed downwards */ - total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); - total_data_count = IVAL(inbuf, smb_nts_TotalDataCount); - num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount)); - num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount)); - if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) - exit_server("reply_nttrans2: data overflow in secondary nttrans packet"); - - memcpy( ¶ms[ IVAL(inbuf, smb_nts_ParameterDisplacement)], - smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count); - memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)], - smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count); + if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) + total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); + if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) + total_data_count = IVAL(inbuf, smb_nts_TotalDataCount); + + parameter_count = IVAL(inbuf,smb_nts_ParameterCount); + parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset); + parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement); + num_params_sofar += parameter_count; + + data_count = IVAL(inbuf, smb_nts_DataCount); + data_displacement = IVAL(inbuf, smb_nts_DataDisplacement); + data_offset = IVAL(inbuf, smb_nts_DataDisplacement); + num_data_sofar += data_count; + + if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) { + DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet")); + goto bad_param; + } + + if (parameter_count) { + if (parameter_displacement + parameter_count >= total_parameter_count) + goto bad_param; + if ((parameter_displacement + parameter_count < parameter_displacement) || + (parameter_displacement + parameter_count < parameter_count)) + goto bad_param; + if (smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) + goto bad_param; + if (parameter_displacement + params < params) + goto bad_param; + + memcpy( ¶ms[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count); + } + + if (data_count) { + if (data_displacement + data_count >= total_data_count) + goto bad_param; + if ((data_displacement + data_count < data_displacement) || + (data_displacement + data_count < data_count)) + goto bad_param; + if (smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) + goto bad_param; + if (data_displacement + data < data) + goto bad_param; + + memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count); + } } } @@ -1933,4 +1983,12 @@ due to being in oplock break state.\n", (unsigned int)function_code )); return outsize; /* If a correct response was needed the call_nt_transact_xxxx calls have already sent it. If outsize != -1 then it is returning an error packet. */ + + bad_param: + + SAFE_FREE(params); + SAFE_FREE(data); + SAFE_FREE(setup); + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRDOS,ERRinvalidparam); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 155c996314..d57a29ff77 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3094,7 +3094,7 @@ int reply_trans2(connection_struct *conn, unsigned int suwcnt = SVAL(inbuf, smb_suwcnt); unsigned int tran_call = SVAL(inbuf, smb_setup0); char *params = NULL, *data = NULL; - int num_params, num_params_sofar, num_data, num_data_sofar; + unsigned int num_params, num_params_sofar, num_data, num_data_sofar; START_PROFILE(SMBtrans2); if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) { @@ -3133,10 +3133,10 @@ int reply_trans2(connection_struct *conn, (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { DEBUG(2,("Got Trans2 DevIOctl jobid\n")); } else { - DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt)); + DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt)); DEBUG(2,("Transaction is %d\n",tran_call)); END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRSRV,ERRerror); + ERROR_DOS(ERRDOS,ERRinvalidparam); } } @@ -3162,10 +3162,22 @@ int reply_trans2(connection_struct *conn, if (num_params > total_params || num_data > total_data) exit_server("invalid params in reply_trans2"); - if(params) - memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); - if(data) - memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); + if(params) { + unsigned int psoff = SVAL(inbuf, smb_psoff); + if ((psoff + num_params < psoff) || (psoff + num_params < num_params)) + goto bad_param; + if (smb_base(inbuf) + psoff + num_params > inbuf + length) + goto bad_param; + memcpy( params, smb_base(inbuf) + psoff, num_params); + } + if(data) { + unsigned int dsoff = SVAL(inbuf, smb_dsoff); + if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data)) + goto bad_param; + if (smb_base(inbuf) + dsoff + num_data > inbuf + length) + goto bad_param; + memcpy( data, smb_base(inbuf) + dsoff, num_data); + } if(num_data_sofar < total_data || num_params_sofar < total_params) { /* We need to send an interim response then receive the rest @@ -3177,6 +3189,10 @@ int reply_trans2(connection_struct *conn, while (num_data_sofar < total_data || num_params_sofar < total_params) { BOOL ret; + unsigned int param_disp; + unsigned int param_off; + unsigned int data_disp; + unsigned int data_off; ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); @@ -3188,25 +3204,55 @@ int reply_trans2(connection_struct *conn, else DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - SAFE_FREE(params); - SAFE_FREE(data); - END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRSRV,ERRerror); + goto bad_param; } /* Revise total_params and total_data in case they have changed downwards */ - total_params = SVAL(inbuf, smb_tpscnt); - total_data = SVAL(inbuf, smb_tdscnt); - num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt)); - num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt)); + if (SVAL(inbuf, smb_tpscnt) < total_params) + total_params = SVAL(inbuf, smb_tpscnt); + if (SVAL(inbuf, smb_tdscnt) < total_data) + total_data = SVAL(inbuf, smb_tdscnt); + + num_params = SVAL(inbuf,smb_spscnt); + param_off = SVAL(inbuf, smb_spsoff); + param_disp = SVAL(inbuf, smb_spsdisp); + num_params_sofar += num_params; + + num_data = SVAL(inbuf, smb_sdscnt); + data_off = SVAL(inbuf, smb_sdsoff); + data_disp = SVAL(inbuf, smb_sdsdisp); + num_data_sofar += num_data; + if (num_params_sofar > total_params || num_data_sofar > total_data) - exit_server("data overflow in trans2"); + goto bad_param; - memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], - smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params); - memcpy( &data[SVAL(inbuf, smb_sdsdisp)], - smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data); + if (num_params) { + if (param_disp + num_params >= total_params) + goto bad_param; + if ((param_disp + num_params < param_disp) || + (param_disp + num_params < num_params)) + goto bad_param; + if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) + goto bad_param; + if (params + param_disp < params) + goto bad_param; + + memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params); + } + if (num_data) { + if (data_disp + num_data >= total_data) + goto bad_param; + if ((data_disp + num_data < data_disp) || + (data_disp + num_data < num_data)) + goto bad_param; + if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) + goto bad_param; + if (data + data_disp < data) + goto bad_param; + + memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data); + } } } @@ -3320,4 +3366,11 @@ int reply_trans2(connection_struct *conn, return outsize; /* If a correct response was needed the call_trans2xxx calls have already sent it. If outsize != -1 then it is returning */ + + bad_param: + + SAFE_FREE(params); + SAFE_FREE(data); + END_PROFILE(SMBtrans2); + return ERROR_DOS(ERRDOS,ERRinvalidparam); } -- cgit From 97d25a7374e03b4411debe0d9301326ab2df709f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Mar 2003 00:35:24 +0000 Subject: Fix noticed by Corny.Bondad@hp.com. Ensure we free up memory on error exit. Jeremy. (This used to be commit 05a8a61af83a6d85ddbb70749c8cd0abe9eb8180) --- source3/smbd/ipc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 08337c2901..67c5da01f3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -397,6 +397,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (tpscnt) { if((params = (char *)malloc(tpscnt)) == NULL) { DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt)); + SAFE_FREE(data); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } @@ -412,6 +413,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int int i; if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16)))); + SAFE_FREE(data); + SAFE_FREE(params); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } -- cgit From e9f51a6e38eb270c0d3643292978410e048ca173 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Mar 2003 19:37:31 +0000 Subject: Patch from Michael Steffens. In his own words : ------------------------------------------------------------------------- I think there are basically two problem: 1. Windows clients do not always send ACEs for SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, and SMB_ACL_OTHER. The function ensure_canon_entry_valid() is prepared for that, but tries to "guess" values from group or other permissions, respectively, otherwise falling back to minimum r-- for the owner. Even if the owner had full permissions before setting ACL. This is the problem with W2k clients. 2. Function set_nt_acl() always chowns *before* attempting to set POSIX ACLs. This is ok in a take-ownership situation, but must fail if the file is to be given away. This is the problem with XP clients, trying to transfer ownership of the original file to the temp file. The problem with NT4 clients (no ACEs are transferred to the temp file, thus are lost after moving the temp file to the original name) is a client problem. It simply doesn't attempt to. I have played around with that using posic_acls.c from 3.0 merged into 2.2. As a result I can now present two patches, one for each branch. They basically modify: 1. Interpret missing SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, or SMB_ACL_OTHER as "preserve current value" instead of attempting to build one ourself. The original code is still in, but only as fallback in case current values can't be retrieved. 2. Rearrange set_nt_acl() such that chown is only done before setting ACLs if there is either no change of owning user, or change of owning user is towards the current user. Otherwise chown is done after setting ACLs. It now seems to produce reasonable results. (Well, as far as it can. If NT4 doesn't even try to transfer ACEs, only deliberate use of named default ACEs and/or "force group" or the crystal ball can help :) ------------------------------------------------------------------------- Jeremy. (This used to be commit 1d3b8c528bebfa1971d1affe454a03453335786e) --- source3/smbd/posix_acls.c | 277 +++++++++++++++++++++++++++++++++------------- 1 file changed, 199 insertions(+), 78 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 93a57925f1..2aea3a2c90 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -559,12 +559,18 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) extern DOM_SID global_sid_World; fstring u_name; fstring g_name; + extern struct current_user current_user; /* "Everyone" always matches every uid. */ if (sid_equal(&group_ace->trustee, &global_sid_World)) return True; + /* Assume that the current user is in the current group (force group) */ + + if (uid_ace->unix_ug.uid == current_user.uid && group_ace->unix_ug.gid == current_user.gid) + return True; + fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid)); @@ -600,6 +606,14 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, BOOL got_other = False; canon_ace *pace_other = NULL; canon_ace *pace_group = NULL; + connection_struct *conn = fsp->conn; + SMB_ACL_T current_posix_acl = NULL; + mode_t current_user_perms = 0; + mode_t current_grp_perms = 0; + mode_t current_other_perms = 0; + BOOL got_current_user = False; + BOOL got_current_grp = False; + BOOL got_current_other = False; for (pace = *pp_ace; pace; pace = pace->next) { if (pace->type == SMB_ACL_USER_OBJ) { @@ -632,6 +646,62 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, } } + /* + * When setting ACLs and missing one out of SMB_ACL_USER_OBJ, + * SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER, try to retrieve current + * values. For user and other a simple vfs_stat would do, but + * we would get mask instead of group. Let's do it via ACL. + */ + + if (setting_acl && (!got_user || !got_grp || !got_other)) { + + SMB_ACL_ENTRY_T entry; + int entry_id = SMB_ACL_FIRST_ENTRY; + + if(fsp->is_directory || fsp->fd == -1) { + current_posix_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); + } else { + current_posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fsp->fd); + } + + if (current_posix_acl) { + while (conn->vfs_ops.sys_acl_get_entry(conn, current_posix_acl, entry_id, &entry) == 1) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; + + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) + entry_id = SMB_ACL_NEXT_ENTRY; + + /* Is this a MASK entry ? */ + if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) + continue; + + if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) + continue; + + switch(tagtype) { + case SMB_ACL_USER_OBJ: + current_user_perms = convert_permset_to_mode_t(conn, permset); + got_current_user = True; + break; + case SMB_ACL_GROUP_OBJ: + current_grp_perms = convert_permset_to_mode_t(conn, permset); + got_current_grp = True; + break; + case SMB_ACL_OTHER: + current_other_perms = convert_permset_to_mode_t(conn, permset); + got_current_other = True; + break; + } + } + conn->vfs_ops.sys_acl_free_acl(conn, current_posix_acl); + } else { + DEBUG(10,("ensure_canon_entry_valid: failed to retrieve current ACL of %s\n", + fsp->fsp_name)); + } + } + if (!got_user) { if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); @@ -646,13 +716,19 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->attr = ALLOW_ACE; if (setting_acl) { - /* If we only got an "everyone" perm, just use that. */ - if (!got_grp && got_other) - pace->perms = pace_other->perms; - else if (got_grp && uid_entry_in_group(pace, pace_group)) - pace->perms = pace_group->perms; - else - pace->perms = 0; + if (got_current_user) { + pace->perms = current_user_perms; + } else { + /* If we only got an "everyone" perm, just use that. */ + if (!got_grp && got_other) + pace->perms = pace_other->perms; + else if (got_grp && uid_entry_in_group(pace, pace_group)) + pace->perms = pace_group->perms; + else + pace->perms = 0; + + } + apply_default_perms(fsp, pace, S_IRUSR); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); @@ -674,11 +750,15 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->trustee = *pfile_grp_sid; pace->attr = ALLOW_ACE; if (setting_acl) { - /* If we only got an "everyone" perm, just use that. */ - if (got_other) - pace->perms = pace_other->perms; - else - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); + if (got_current_grp) { + pace->perms = current_grp_perms; + } else { + /* If we only got an "everyone" perm, just use that. */ + if (got_other) + pace->perms = pace_other->perms; + else + pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); + } apply_default_perms(fsp, pace, S_IRGRP); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); @@ -700,7 +780,10 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->trustee = global_sid_World; pace->attr = ALLOW_ACE; if (setting_acl) { - pace->perms = 0; + if (got_current_other) + pace->perms = current_other_perms; + else + pace->perms = 0; apply_default_perms(fsp, pace, S_IROTH); } else pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); @@ -1734,6 +1817,11 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau BOOL needs_mask = False; mode_t mask_perms = 0; +#if defined(POSIX_ACL_NEEDS_MASK) + /* HP-UX always wants to have a mask (called "class" there). */ + needs_mask = True; +#endif + if (the_acl == NULL) { if (errno != ENOSYS) { @@ -1748,6 +1836,13 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau return False; } + if( DEBUGLVL( 10 )) { + dbgtext("set_canon_ace_list: setting ACL:\n"); + for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) { + print_canon_ace( p_ace, i); + } + } + for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) { SMB_ACL_ENTRY_T the_entry; SMB_ACL_PERMSET_T the_permset; @@ -2460,6 +2555,8 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) mode_t orig_mode = (mode_t)0; uid_t orig_uid; gid_t orig_gid; + BOOL need_chown = False; + extern struct current_user current_user; DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -2496,7 +2593,15 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Do we need to chown ? */ - if((user != (uid_t)-1 || grp != (uid_t)-1) && (orig_uid != user || orig_gid != grp)) { + need_chown = (user != (uid_t)-1 && orig_uid != user || grp != (uid_t)-1 && orig_gid != grp); + + /* + * Chown before setting ACL only if we don't change the user, or + * if we change to the current user, but not if we want to give away + * the file. + */ + + if (need_chown && (user == (uid_t)-1 || user == current_user.uid)) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); @@ -2533,6 +2638,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) orig_mode = sbuf.st_mode; orig_uid = sbuf.st_uid; orig_gid = sbuf.st_gid; + + /* We did it, don't try again */ + need_chown = False; } create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); @@ -2540,97 +2648,110 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); - if ((file_ace_list == NULL) && (dir_ace_list == NULL)) { - /* W2K traverse DACL set - ignore. */ - return True; - } - - if (!acl_perms) { - DEBUG(3,("set_nt_acl: cannot set permissions\n")); - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - return False; - } + /* Ignore W2K traverse DACL set. */ + if (file_ace_list || dir_ace_list) { - /* - * Only change security if we got a DACL. - */ - - if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) { - - BOOL acl_set_support = False; - BOOL ret = False; + if (!acl_perms) { + DEBUG(3,("set_nt_acl: cannot set permissions\n")); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } /* - * Try using the POSIX ACL set first. Fall back to chmod if - * we have no ACL support on this filesystem. + * Only change security if we got a DACL. */ - if (acl_perms && file_ace_list) { - ret = set_canon_ace_list(fsp, file_ace_list, False, &acl_set_support); - if (acl_set_support && ret == False) { - DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) )); - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - return False; - } - } + if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) { - if (acl_perms && acl_set_support && fsp->is_directory) { - if (dir_ace_list) { - if (!set_canon_ace_list(fsp, dir_ace_list, True, &acl_set_support)) { - DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - return False; - } - } else { + BOOL acl_set_support = False; + BOOL ret = False; - /* - * No default ACL - delete one if it exists. - */ + /* + * Try using the POSIX ACL set first. Fall back to chmod if + * we have no ACL support on this filesystem. + */ - if (conn->vfs_ops.sys_acl_delete_def_file(conn, fsp->fsp_name) == -1) { - DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); + if (acl_perms && file_ace_list) { + ret = set_canon_ace_list(fsp, file_ace_list, False, &acl_set_support); + if (acl_set_support && ret == False) { + DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) )); free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); return False; } } - } - /* - * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. - */ + if (acl_perms && acl_set_support && fsp->is_directory) { + if (dir_ace_list) { + if (!set_canon_ace_list(fsp, dir_ace_list, True, &acl_set_support)) { + DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } + } else { - if(!acl_set_support && acl_perms) { - mode_t posix_perms; + /* + * No default ACL - delete one if it exists. + */ - if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) { - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n", - fsp->fsp_name )); - return False; + if (conn->vfs_ops.sys_acl_delete_def_file(conn, fsp->fsp_name) == -1) { + DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } + } } - if (orig_mode != posix_perms) { + /* + * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. + */ - DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", - fsp->fsp_name, (unsigned int)posix_perms )); + if(!acl_set_support && acl_perms) { + mode_t posix_perms; - if(conn->vfs_ops.chmod(conn,fsp->fsp_name, posix_perms) == -1) { - DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); + if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) { free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); + DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n", + fsp->fsp_name )); return False; } + + if (orig_mode != posix_perms) { + + DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", + fsp->fsp_name, (unsigned int)posix_perms )); + + if(conn->vfs_ops.chmod(conn,fsp->fsp_name, posix_perms) == -1) { + DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } + } } } + + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); } - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); + /* Any chown pending? */ + if (need_chown) { + + DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); + + if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { + DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); + return False; + } + } return True; } -- cgit From 0f30afc9128f661226c8d20ce4e447e3715703c8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Mar 2003 19:46:00 +0000 Subject: Missed parentheses around complex logic. Jeremy. (This used to be commit 7f8d3a49b2cebab4b94db3cda54b3923442378c8) --- source3/smbd/posix_acls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2aea3a2c90..01e3c31ba7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2593,7 +2593,8 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Do we need to chown ? */ - need_chown = (user != (uid_t)-1 && orig_uid != user || grp != (uid_t)-1 && orig_gid != grp); + if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (uid_t)-1) && (orig_gid != grp))) + need_chown = True; /* * Chown before setting ACL only if we don't change the user, or -- cgit From 2fd693e13e8168210eb991392f011cf4e1983376 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Mar 2003 23:34:51 +0000 Subject: Use ERROR_NT, not ERROR_DOS as Andrew Bartlett pointed out. Jeremy. (This used to be commit 723e9ee31cc1f5eb4b7aefefd58f7f13d0abda05) --- source3/smbd/ipc.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/trans2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 67c5da01f3..da30ec7440 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -566,5 +566,5 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int SAFE_FREE(params); SAFE_FREE(setup); END_PROFILE(SMBtrans); - return ERROR_DOS(ERRDOS,ERRinvalidparam); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 375c6c44f6..e6884cbb1e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1990,5 +1990,5 @@ due to being in oplock break state.\n", (unsigned int)function_code )); SAFE_FREE(data); SAFE_FREE(setup); END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRDOS,ERRinvalidparam); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d57a29ff77..bea09e9e37 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3372,5 +3372,5 @@ int reply_trans2(connection_struct *conn, SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRDOS,ERRinvalidparam); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } -- cgit From e613c18ee77c1561efbf56dd7c8a54cab3a87a2b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 8 Mar 2003 01:16:33 +0000 Subject: Fix typo in earlier fix, caught by Ranjit @ HP. Jeremy. (This used to be commit 11077368ec30313c2e7ee1d23f9f348910aa36bf) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e6884cbb1e..6d9c649045 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1871,7 +1871,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); data_count = IVAL(inbuf, smb_nts_DataCount); data_displacement = IVAL(inbuf, smb_nts_DataDisplacement); - data_offset = IVAL(inbuf, smb_nts_DataDisplacement); + data_offset = IVAL(inbuf, smb_nts_DataOffset); num_data_sofar += data_count; if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) { -- cgit From 71708c9c077704f7aeadd2abf2b543f4dbec1b40 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2003 18:10:27 +0000 Subject: Fix up zero termination. Spotted by Sebastian Krahmer . Jeremy. (This used to be commit 289e2e25b91da20ac02b90e5a9d6de3619ad308d) --- source3/smbd/quotas.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 9d3bfe2d64..c2f001423e 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -413,10 +413,11 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B len=strcspn(mnttype, ":"); pathname=strstr(mnttype, ":"); - cutstr = (char *) malloc(sizeof(char) * len ); + cutstr = (char *) malloc(len+1); if (!cutstr) return False; + memset(cutstr, '\0', len+1); host = strncat(cutstr,mnttype, sizeof(char) * len ); DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); -- cgit From 834da49f63976c9c39b0d976e9cbc981a80821e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2003 20:58:10 +0000 Subject: We use unsigned now, so use %u. Jeremy. (This used to be commit 65c2a361a4a3461ccbed9b5c968f95281295faab) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index da30ec7440..c8bb0c2505 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -508,7 +508,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } - DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n", + DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", name,tdscnt,tpscnt,suwcnt)); /* -- cgit From fd56ede2b6c6590616d66b524734dacfaf1a8f1b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 12 Mar 2003 15:41:39 +0000 Subject: adding some initiaial code to sert %a to Win2K3 (using Native LanMan string from .NET RC2) (This used to be commit e074cab810f9299d0b27881cddf8a74f10fe233e) --- source3/smbd/sesssetup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b0ef78f447..7e28592eeb 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -593,6 +593,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if ( ra_type == RA_WIN2K ) { if ( 0 == strcmp( native_lanman, "Windows 2002 5.1" ) ) set_remote_arch( RA_WINXP ); + else if ( 0 == strcmp( native_lanman, "Windows .NET 5.2" ) ) + set_remote_arch( RA_WIN2K3 ); } -- cgit From a03a4db8aee986eb49837040e7712a73e3224447 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Mar 2003 19:07:49 +0000 Subject: Ensure we count the length correctly in mangle_map. Jeremy. (This used to be commit 8e956bc1d63425b0e1ca9410bf82a0a5d3e36ac7) --- source3/smbd/mangle_map.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c index 553e3d949d..5ae3ebd174 100644 --- a/source3/smbd/mangle_map.c +++ b/source3/smbd/mangle_map.c @@ -150,36 +150,45 @@ static void mangled_map(char *s, const char *MangledMap) } DEBUG( 5, ("End of first in pair '%s'\n", end) ); if( (match_string = map_filename( s, start, end-start )) ) { + int size_left = sizeof(new_string) - 1; DEBUG( 5, ("Found a match\n") ); /* Found a match. */ start = end + 1; /* Point to start of what it is to become. */ DEBUG( 5, ("Start of second in pair '%s'\n", start) ); end = start; np = new_string; - while( (*end) /* Not the end of string. */ + while( (*end && size_left > 0) /* Not the end of string. */ && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*') ) /* Not a wildcard. */ + && (*end != '*') ) { /* Not a wildcard. */ *np++ = *end++; + size_left--; + } if( !*end ) { start = end; continue; /* Always check for the end. */ } if( *end == '*' ) { - pstrcpy( np, match_string ); + if (size_left > 0 ) + safe_strcpy( np, match_string, size_left ); np += strlen( match_string ); + size_left -= strlen( match_string ); end++; /* Skip the '*' */ - while ((*end) /* Not the end of string. */ + while ((*end && size_left > 0) /* Not the end of string. */ && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*'))/* Not a wildcard. */ + && (*end != '*')) { /* Not a wildcard. */ *np++ = *end++; + size_left--; + } } if (!*end) { start = end; continue; /* Always check for the end. */ } - *np++ = '\0'; /* NULL terminate it. */ + if (size_left > 0) + *np++ = '\0'; /* NULL terminate it. */ DEBUG(5,("End of second in pair '%s'\n", end)); + new_string[sizeof(new_string)-1] = '\0'; pstrcpy( s, new_string ); /* Substitute with the new name. */ DEBUG( 5, ("s is now '%s'\n", s) ); } -- cgit From 128e7edaaf7cf6ed590c8b7260303520f7b773a0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 14 Mar 2003 23:06:06 +0000 Subject: fix WinXP & Win2K3 remote_arch and check pointer in ntlmssp code before dereferencing (This used to be commit 7bc5fc729f67ae16e09ea67efa9e2b8e2ba41c8f) --- source3/smbd/sesssetup.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7e28592eeb..7f125de583 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -372,8 +372,10 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - nt_status = auth_ntlmssp_update(global_ntlmssp_state, - auth, &auth_reply); + if ( global_ntlmssp_state ) { + nt_status = auth_ntlmssp_update(global_ntlmssp_state, + auth, &auth_reply); + } data_blob_free(&auth); @@ -398,6 +400,10 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, DATA_BLOB blob1; int ret; size_t bufrem; + fstring native_os, native_lanman; + char *p2; + uint16 data_blob_len = SVAL(inbuf, smb_vwv7); + enum remote_arch_types ra_type = get_remote_arch(); DEBUG(3,("Doing spnego session setup\n")); @@ -407,19 +413,27 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, p = (uint8 *)smb_buf(inbuf); - if (SVAL(inbuf, smb_vwv7) == 0) { + if (data_blob_len == 0) { /* an invalid request */ return ERROR_NT(NT_STATUS_LOGON_FAILURE); } bufrem = smb_bufrem(inbuf, p); /* pull the spnego blob */ - blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7))); + blob1 = data_blob(p, MIN(bufrem, data_blob_len)); #if 0 file_save("negotiate.dat", blob1.data, blob1.length); #endif + p2 = inbuf + smb_vwv13 + data_blob_len; + p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE); + p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE); + DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s]\n", native_os, native_lanman)); + + if ( ra_type == RA_WIN2K ) + ra_lanman_string( native_lanman ); + if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1); @@ -582,21 +596,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", domain,native_os,native_lanman)); - /* - * we distinguish between 2K and XP by the "Native Lan Manager" string - * WinXP => "Windows 2002 5.1" - * Win2k => "Windows 2000 5.0" - * NT4 => "Windows NT 4.0" - * Win9x => "Windows 4.0" - */ - - if ( ra_type == RA_WIN2K ) { - if ( 0 == strcmp( native_lanman, "Windows 2002 5.1" ) ) - set_remote_arch( RA_WINXP ); - else if ( 0 == strcmp( native_lanman, "Windows .NET 5.2" ) ) - set_remote_arch( RA_WIN2K3 ); - } - + if ( ra_type == RA_WIN2K ) + ra_lanman_string( native_lanman ); } -- cgit From c320f72f430d09bddbbf640feb8ee64b13e66f73 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 17 Mar 2003 22:23:51 +0000 Subject: Merge new statcache.c from HEAD. (This used to be commit 3b9db928fcaec322698d046db3a8a042b9a1d30c) --- source3/smbd/statcache.c | 187 +++++++++++++++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index f4b613428a..0f42a3a83f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -3,7 +3,7 @@ stat cache code Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2000 - + Copyright (C) Andrew Bartlett 2003 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 @@ -30,30 +30,41 @@ extern BOOL case_sensitive; *****************************************************************************/ typedef struct { - int name_len; - char names[2]; /* This is extended via malloc... */ + char *original_path; + char *translated_path; + size_t translated_path_length; + char names[2]; /* This is extended via malloc... */ } stat_cache_entry; #define INIT_STAT_CACHE_SIZE 512 static hash_table stat_cache; -/**************************************************************************** - Add an entry into the stat cache. -*****************************************************************************/ +/** + * Add an entry into the stat cache. + * + * @param full_orig_name The original name as specified by the client + * @param orig_translated_path The name on our filesystem. + * + * @note Only the first strlen(orig_translated_path) characters are stored + * into the cache. This means that full_orig_name will be internally + * truncated. + * + */ -void stat_cache_add( char *full_orig_name, char *orig_translated_path) +void stat_cache_add( const char *full_orig_name, const char *orig_translated_path) { stat_cache_entry *scp; stat_cache_entry *found_scp; - pstring orig_name; - pstring translated_path; - int namelen; + char *translated_path; + size_t translated_path_length; + + char *original_path; + size_t original_path_length; + hash_element *hash_elem; if (!lp_stat_cache()) return; - namelen = strlen(orig_translated_path); - /* * Don't cache trivial valid directory entries. */ @@ -62,7 +73,7 @@ void stat_cache_add( char *full_orig_name, char *orig_translated_path) return; /* - * If we are in case insentive mode, we need to + * If we are in case insentive mode, we don't need to * store names that need no translation - else, it * would be a waste. */ @@ -75,74 +86,126 @@ void stat_cache_add( char *full_orig_name, char *orig_translated_path) * translated path. */ - pstrcpy(translated_path, orig_translated_path); - if(translated_path[namelen-1] == '/') { - translated_path[namelen-1] = '\0'; - namelen--; + translated_path = strdup(orig_translated_path); + if (!translated_path) + return; + + translated_path_length = strlen(translated_path); + + if(translated_path[translated_path_length-1] == '/') { + translated_path[translated_path_length-1] = '\0'; + translated_path_length--; } + original_path = strdup(full_orig_name); + if (!original_path) { + SAFE_FREE(translated_path); + return; + } + + original_path_length = strlen(original_path); + + if(original_path[original_path_length-1] == '/') { + original_path[original_path_length-1] = '\0'; + original_path_length--; + } + + if(!case_sensitive) + strupper(original_path); + + if (original_path_length != translated_path_length) { + if (original_path_length < translated_path_length) { + DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + /* we only want to store the first part of original_path, + up to the length of translated_path */ + + original_path[translated_path_length] = '\0'; + original_path_length = translated_path_length; + } + +#if 0 /* * We will only replace namelen characters * of full_orig_name. * StrnCpy always null terminates. */ - StrnCpy(orig_name, full_orig_name, namelen); + smbStrnCpy(orig_name, full_orig_name, namelen); if(!case_sensitive) strupper( orig_name ); +#endif /* * Check this name doesn't exist in the cache before we * add it. */ - if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { - return; - } else { - hash_remove(&stat_cache, hash_elem); - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - pstrcpy(scp->names, orig_name); - pstrcpy((scp->names+namelen+1), translated_path); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } - return; - } else { + if ((hash_elem = hash_lookup(&stat_cache, original_path))) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { + /* already in hash table */ + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + /* hash collision - remove before we re-add */ + hash_remove(&stat_cache, hash_elem); + } + + /* + * New entry. + */ + + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) + +original_path_length + +translated_path_length)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } - /* - * New entry. - */ + scp->original_path = scp->names; + scp->translated_path = scp->names + original_path_length + 1; + safe_strcpy(scp->original_path, original_path, original_path_length); + safe_strcpy(scp->translated_path, translated_path, translated_path_length); + scp->translated_path_length = translated_path_length; - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - safe_strcpy(scp->names, orig_name, namelen); - safe_strcpy(scp->names+namelen+1, translated_path, namelen); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } + hash_insert(&stat_cache, (char *)scp, original_path); - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); } -/**************************************************************************** - Look through the stat cache for an entry - promote it to the top if found. - Return True if we translated (and did a scuccessful stat on) the entire name. -*****************************************************************************/ +/** + * Look through the stat cache for an entry + * + * The hash-table's internals will promote it to the top if found. + * + * @param conn A connection struct to do the stat() with. + * @param name The path we are attempting to cache, modified by this routine + * to be correct as far as the cache can tell us + * @param dirpath The path as far as the stat cache told us. + * @param start A pointer into name, for where to 'start' in fixing the rest of the name up. + * @param psd A stat buffer, NOT from the cache, but just a side-effect. + * + * @return True if we translated (and did a scuccessful stat on) the entire name. + * + */ -BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, +BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - char *trans_name; pstring chk_name; - int namelen; + size_t namelen; hash_element *hash_elem; char *sp; @@ -191,18 +254,20 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, } else { scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); - trans_name = scp->names+scp->name_len+1; - if(vfs_stat(conn,trans_name, pst) != 0) { + if(vfs_stat(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; } - memcpy(name, trans_name, scp->name_len); - *start = &name[scp->name_len]; + memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + + /* set pointer for 'where to start' on fixing the rest of the name */ + *start = &name[scp->translated_path_length]; if(**start == '/') ++*start; - StrnCpy( dirpath, trans_name, name - (*start)); - return (namelen == scp->name_len); + + pstrcpy(dirpath, scp->translated_path); + return (namelen == scp->translated_path_length); } } } -- cgit From ec458fa87e3ee858be39671f575e21a9350674b6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 17 Mar 2003 22:45:16 +0000 Subject: Merge from HEAD - sync up SessionSetup code to HEAD, including Luke Howard's session key and auth verifier patches. Andrew Bartlett (This used to be commit 3f9616a68a855acbae3f405c27ee2358fbe7ba2c) --- source3/smbd/sesssetup.c | 82 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7f125de583..e36760c148 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1998-2001 Copyright (C) Andrew Bartlett 2001 Copyright (C) Jim McDonough 2002 + Copyright (C) Luke Howard 2003 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 @@ -38,16 +39,14 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { DEBUG(3,("No such user %s [%s] - using guest account\n", user, domain)); - make_server_info_guest(server_info); - status = NT_STATUS_OK; + status = make_server_info_guest(server_info); } } if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) { if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { DEBUG(3,("Registered username %s for guest access\n",user)); - make_server_info_guest(server_info); - status = NT_STATUS_OK; + status = make_server_info_guest(server_info); } } @@ -146,11 +145,14 @@ static int reply_spnego_kerberos(connection_struct *conn, int sess_vuid; NTSTATUS ret; DATA_BLOB auth_data; + DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; ADS_STRUCT *ads; + uint8 session_key[16]; + uint8 tok_id[2]; BOOL foreign = False; - if (!spnego_parse_krb5_wrap(*secblob, &ticket)) { + if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -162,7 +164,7 @@ static int reply_spnego_kerberos(connection_struct *conn, ads->auth.realm = strdup(lp_realm()); - ret = ads_verify_ticket(ads, &ticket, &client, &auth_data); + ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); ads_destroy(&ads); @@ -177,6 +179,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); ads_destroy(&ads); + data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -184,6 +187,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (strcasecmp(p+1, ads->auth.realm) != 0) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { + data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } foreign = True; @@ -209,31 +213,51 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); + data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_NO_SUCH_USER); } if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); + data_blob_free(&ap_rep); return ERROR_NT(ret); } - + + /* Copy out the session key from the AP_REQ. */ + memcpy(server_info->session_key, session_key, sizeof(session_key)); + /* register_vuid keeps the server info */ sess_vuid = register_vuid(server_info, user); free(user); if (sess_vuid == -1) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + ret = NT_STATUS_LOGON_FAILURE; + } else { + set_message(outbuf,4,0,True); + SSVAL(outbuf, smb_vwv3, 0); + + if (server_info->guest) { + SSVAL(outbuf,smb_vwv2,1); + } + + SSVAL(outbuf, smb_uid, sess_vuid); } - set_message(outbuf,4,0,True); - SSVAL(outbuf, smb_vwv3, 0); - add_signature(outbuf); - - SSVAL(outbuf,smb_uid,sess_vuid); - SSVAL(inbuf,smb_uid,sess_vuid); - - return chain_reply(inbuf,outbuf,length,bufsize); + /* wrap that up in a nice GSS-API wrapping */ + if (NT_STATUS_IS_OK(ret)) { + ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); + } else { + ap_rep_wrapped = data_blob(NULL, 0); + } + response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); + reply_sesssetup_blob(conn, outbuf, response, ret); + + data_blob_free(&ap_rep); + data_blob_free(&ap_rep_wrapped); + data_blob_free(&response); + + return -1; /* already replied */ } #endif @@ -249,10 +273,11 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, { BOOL ret; DATA_BLOB response; - struct auth_serversupplied_info *server_info; - server_info = (*auth_ntlmssp_state)->server_info; + struct auth_serversupplied_info *server_info = NULL; - if (!NT_STATUS_IS_OK(nt_status)) { + if (NT_STATUS_IS_OK(nt_status)) { + server_info = (*auth_ntlmssp_state)->server_info; + } else { nt_status = do_map_to_guest(nt_status, &server_info, (*auth_ntlmssp_state)->ntlmssp_state->user, @@ -280,7 +305,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, } } - response = spnego_gen_auth_response(ntlmssp_blob, nt_status); + response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP); ret = reply_sesssetup_blob(conn, outbuf, response, nt_status); data_blob_free(&response); @@ -363,19 +388,22 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DATA_BLOB blob1) { DATA_BLOB auth, auth_reply; - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; if (!spnego_parse_auth(blob1, &auth)) { #if 0 file_save("auth.dat", blob1.data, blob1.length); #endif - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - - if ( global_ntlmssp_state ) { - nt_status = auth_ntlmssp_update(global_ntlmssp_state, - auth, &auth_reply); + + if (!global_ntlmssp_state) { + /* auth before negotiatiate? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + + nt_status = auth_ntlmssp_update(global_ntlmssp_state, + auth, &auth_reply); data_blob_free(&auth); @@ -545,7 +573,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, set_remote_arch( RA_WIN95); } } - + if (!doencrypt) { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. -- cgit From ad0d6509a761154c113e040a82ad78e72a3ccf30 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 17 Mar 2003 22:56:13 +0000 Subject: Merge from HEAD: - Make ReadDirName return a const char*. - Consequential changes from that - mark our fstring/pstring assumptions in function prototypes Andrew Bartlett (This used to be commit 10b53d7c6fd77f23433dd2ef12bb14b227147a48) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/dir.c | 12 ++++++------ source3/smbd/filename.c | 6 +++--- source3/smbd/mangle.c | 2 +- source3/smbd/mangle_hash2.c | 2 +- source3/smbd/mangle_map.c | 2 +- source3/smbd/reply.c | 10 +++++----- source3/smbd/trans2.c | 27 +++++++++++++++++---------- 8 files changed, 35 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 401ab131ad..31c4fa7cc9 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -64,7 +64,7 @@ static int findpty(char **slave) int master; static fstring line; DIR *dirp; - char *dpname; + const char *dpname; #if defined(HAVE_GRANTPT) /* Try to open /dev/ptmx. If that fails, fall through to old method. */ diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 95acf4a262..3f29ac892c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -578,7 +578,7 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int di return True; } -static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask) +static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask) { mangle_map(filename,True,False,SNUM(conn)); return mask_match(filename,mask,False); @@ -588,10 +588,10 @@ static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mas Get an 8.3 directory entry. ****************************************************************************/ -BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, +BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname, SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) { - char *dname; + const char *dname; BOOL found = False; SMB_STRUCT_STAT sbuf; pstring path; @@ -907,7 +907,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp->current = dirp->data; } - safe_strcpy(dirp->data+used,n, dirp->mallocsize - used - 1); + safe_strcpy_base(dirp->data+used,n, dirp->data, dirp->mallocsize); used += l; dirp->numentries++; } @@ -933,7 +933,7 @@ void CloseDir(void *p) Read from a directory. ********************************************************************/ -char *ReadDirName(void *p) +const char *ReadDirName(void *p) { char *ret; Dir *dirp = (Dir *)p; @@ -1008,7 +1008,7 @@ static ubi_dlNewList( dir_cache ); Output: None. *****************************************************************************/ -void DirCacheAdd( const char *path, char *name, char *dname, int snum ) +void DirCacheAdd( const char *path, const char *name, const char *dname, int snum ) { int pathlen; int namelen; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7d3527402e..ad707a2b9d 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -39,7 +39,7 @@ static BOOL scan_directory(const char *path, char *name,size_t maxlength, This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(char *name1, char *name2) +static BOOL fname_equal(const char *name1, const char *name2) { /* Normal filename handling */ if (case_sensitive) @@ -52,7 +52,7 @@ static BOOL fname_equal(char *name1, char *name2) Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(char *name1, const char *name2, int snum) +static BOOL mangled_equal(const char *name1, const char *name2, int snum) { pstring tmpname; @@ -439,7 +439,7 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, connection_struct *conn,BOOL docache) { void *cur_dir; - char *dname; + const char *dname; BOOL mangled; mangled = mangle_is_mangled(name); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index f5c703a5bf..c5d7582c03 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -107,7 +107,7 @@ BOOL mangle_check_cache(char *s) map a long filename to a 8.3 name. */ -void mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum) +void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) { /* name mangling can be disabled for speed, in which case we just truncate the string */ diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index eda509214d..cdce28e1bd 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -484,7 +484,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(char *name, BOOL need83, BOOL cache83) +static void name_map(fstring name, BOOL need83, BOOL cache83) { char *dot_p; char lead_chars[7]; diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c index 5ae3ebd174..9e798fd41b 100644 --- a/source3/smbd/mangle_map.c +++ b/source3/smbd/mangle_map.c @@ -201,7 +201,7 @@ static void mangled_map(char *s, const char *MangledMap) front end routine to the mangled map code personally I think that the whole idea of "mangled map" is completely bogus */ -void mangle_map_filename(char *fname, int snum) +void mangle_map_filename(fstring fname, int snum) { char *map; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 71e880476c..ff1c0e5a52 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1305,7 +1305,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) } } else { void *dirptr = NULL; - char *dname; + const char *dname; if (check_name(directory,conn)) dirptr = OpenDir(conn, directory, True); @@ -2861,7 +2861,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, static BOOL recursive_rmdir(connection_struct *conn, char *directory) { - char *dname = NULL; + const char *dname = NULL; BOOL ret = False; void *dirptr = OpenDir(conn, directory, False); @@ -2926,7 +2926,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) * do a recursive delete) then fail the rmdir. */ BOOL all_veto_files = True; - char *dname; + const char *dname; void *dirptr = OpenDir(conn, directory, False); if(dirptr != NULL) { @@ -3285,7 +3285,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", * Wildcards - process each file that matches. */ void *dirptr = NULL; - char *dname; + const char *dname; pstring destname; if (check_name(directory,conn)) @@ -3574,7 +3574,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } } else { void *dirptr = NULL; - char *dname; + const char *dname; pstring destname; if (check_name(directory,conn)) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bea09e9e37..5d85cae907 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -460,7 +460,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL *out_of_space, BOOL *got_exact_match, int *last_name_off) { - char *dname; + const char *dname; BOOL found = False; SMB_STRUCT_STAT sbuf; pstring mask; @@ -1173,7 +1173,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", */ int current_pos, start_pos; - char *dname = NULL; + const char *dname = NULL; + pstring dname_pstring; void *dirptr = conn->dirptr; start_pos = TellDir(dirptr); for(current_pos = start_pos; current_pos >= 0; current_pos--) { @@ -1181,7 +1182,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", SeekDir(dirptr, current_pos); dname = ReadDirName(dirptr); - + if (dname) { /* * Remember, mangle_map is called by * get_lanman2_dir_entry(), so the resume name @@ -1189,15 +1190,18 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * here. */ - if(dname != NULL) - mangle_map( dname, False, True, SNUM(conn)); + /* make sure we get a copy that mangle_map can modify */ + + pstrcpy(dname_pstring, dname); + mangle_map( dname_pstring, False, True, SNUM(conn)); - if(dname && strcsequal( resume_name, dname)) { + if(strcsequal( resume_name, dname_pstring)) { SeekDir(dirptr, current_pos+1); DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); break; } } + } /* * Scan forward from start if not found going backwards. @@ -1215,14 +1219,18 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * here. */ - if(dname != NULL) - mangle_map( dname, False, True, SNUM(conn)); + if(dname) { + /* make sure we get a copy that mangle_map can modify */ - if(dname && strcsequal( resume_name, dname)) { + pstrcpy(dname_pstring, dname); + mangle_map(dname_pstring, False, True, SNUM(conn)); + + if(strcsequal( resume_name, dname_pstring)) { SeekDir(dirptr, current_pos+1); DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); break; } + } } /* end for */ } /* end if current_pos */ } /* end if requires_resume_key && !continue_bit */ @@ -1269,7 +1277,6 @@ resume_key = %d resume name = %s continue=%d level = %d\n", dptr_close(&dptr_num); /* This frees up the saved mask */ } - /* Set up the return parameter block */ SSVAL(params,0,numentries); SSVAL(params,2,finished); -- cgit From cdc6fc8acb24645ccd0f2862741c9ea9e1c02829 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 18 Mar 2003 09:52:55 +0000 Subject: Add an extra parameter to our 'set_remote_machine_name' and 'set_local_machine_name' so that the client can't change it from under us. (.NET RC2 and WinXP install calls the machine 'machinename' during NTLMSSP on the domain join). Andrew Bartlett (This used to be commit 4c7163e7c2cc09bd95faa05156ee480957a7a4d8) --- source3/smbd/reply.c | 4 ++-- source3/smbd/server.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ff1c0e5a52..a738baa9ff 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -87,8 +87,8 @@ int reply_special(char *inbuf,char *outbuf) name2[15] = 0; } - set_local_machine_name(name1); - set_remote_machine_name(name2); + set_local_machine_name(name1, True); + set_remote_machine_name(name2, True); DEBUG(2,("netbios connect: local=%s remote=%s\n", get_local_machine_name(), get_remote_machine_name() )); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f8bfe90ea9..4a79916efe 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -398,7 +398,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* this is needed so that we get decent entries in smbstatus for port 445 connects */ - set_remote_machine_name(get_socket_addr(smbd_server_fd())); + set_remote_machine_name(get_socket_addr(smbd_server_fd()), False); /* Reset global variables in util.c so that client substitutions will be @@ -703,7 +703,7 @@ static BOOL init_structs(void ) load_case_tables(); - set_remote_machine_name("smbd"); + set_remote_machine_name("smbd", False); if (interactive) { Fork = False; -- cgit From b01a915b64560ee8acf957f91abed4687a93dcba Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 18 Mar 2003 10:42:41 +0000 Subject: Merge whitespace to match HEAD. (This used to be commit 454fb434195b8d46cbcbaee6a200070e5bcd7364) --- source3/smbd/trans2.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5d85cae907..4129852f77 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1183,25 +1183,25 @@ resume_key = %d resume name = %s continue=%d level = %d\n", SeekDir(dirptr, current_pos); dname = ReadDirName(dirptr); if (dname) { - /* - * Remember, mangle_map is called by - * get_lanman2_dir_entry(), so the resume name - * could be mangled. Ensure we do the same - * here. - */ - + /* + * Remember, mangle_map is called by + * get_lanman2_dir_entry(), so the resume name + * could be mangled. Ensure we do the same + * here. + */ + /* make sure we get a copy that mangle_map can modify */ pstrcpy(dname_pstring, dname); mangle_map( dname_pstring, False, True, SNUM(conn)); - + if(strcsequal( resume_name, dname_pstring)) { - SeekDir(dirptr, current_pos+1); - DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); - break; + SeekDir(dirptr, current_pos+1); + DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); + break; + } } } - } /* * Scan forward from start if not found going backwards. @@ -1221,15 +1221,15 @@ resume_key = %d resume name = %s continue=%d level = %d\n", if(dname) { /* make sure we get a copy that mangle_map can modify */ - + pstrcpy(dname_pstring, dname); mangle_map(dname_pstring, False, True, SNUM(conn)); if(strcsequal( resume_name, dname_pstring)) { - SeekDir(dirptr, current_pos+1); - DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); - break; - } + SeekDir(dirptr, current_pos+1); + DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); + break; + } } } /* end for */ } /* end if current_pos */ -- cgit From 5452ecebc7d89fac6e1047b92b77be47fe85914c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 18 Mar 2003 11:18:27 +0000 Subject: Merge signed/unsigned fix from HEAD. (This used to be commit 196628432130f826505187a27207a7b947e034cf) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c8bb0c2505..c4a12ab531 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -410,7 +410,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if (suwcnt) { - int i; + unsigned int i; if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16)))); SAFE_FREE(data); -- cgit From d5ee9b2f480ddbda0b8f69409698d27c99384f9c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 18 Mar 2003 11:22:52 +0000 Subject: Jeremy merged across my string parinoia fixes, but forgot to enable them! :-) This patch catches up on the rest of the work - as much string checking as is possible is done at compile time, and the rest at runtime. Lots of code converted to pstrcpy() etc, and other code reworked to correctly call sizeof(). Andrew Bartlett (This used to be commit c5b604e2ee67d74241ae2fa07ae904647d35a2be) --- source3/smbd/negprot.c | 6 +++--- source3/smbd/reply.c | 2 +- source3/smbd/srvstr.c | 41 ----------------------------------------- 3 files changed, 4 insertions(+), 45 deletions(-) delete mode 100644 source3/smbd/srvstr.c (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index c8f023514e..db0694a840 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -167,7 +167,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) static int negprot_spnego(char *p) { DATA_BLOB blob; - uint8 guid[16]; + uint8 guid[17]; const char *OIDs_krb5[] = {OID_KERBEROS5, OID_KERBEROS5_OLD, OID_NTLMSSP, @@ -178,8 +178,8 @@ static int negprot_spnego(char *p) global_spnego_negotiated = True; - memset(guid, 0, 16); - safe_strcpy((char *)guid, global_myname(), 16); + ZERO_STRUCT(guid); + safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1); strlower((char *)guid); #if 0 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a738baa9ff..775b617df5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -161,7 +161,7 @@ int reply_tcon(connection_struct *conn, *service_buf = *password = *dev = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1; pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1; p += pwlen; p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1; diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c deleted file mode 100644 index 36fecf5bd2..0000000000 --- a/source3/smbd/srvstr.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - Unix SMB/CIFS implementation. - server specific string routines - Copyright (C) Andrew Tridgell 2001 - - 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" - -int srvstr_push(void *base_ptr, void *dest, const char *src, int dest_len, int flags) -{ - return push_string(base_ptr, dest, src, dest_len, flags); -} - -int srvstr_pull(void *base_ptr, char *dest, const void *src, int dest_len, int src_len, - int flags) -{ - return pull_string(base_ptr, dest, src, dest_len, src_len, flags); -} - -/* pull a string from the smb_buf part of a packet. In this case the - string can either be null terminated or it can be terminated by the - end of the smbbuf area -*/ -int srvstr_pull_buf(void *inbuf, char *dest, const void *src, int dest_len, int flags) -{ - return pull_string(inbuf, dest, src, dest_len, smb_bufrem(inbuf, src), flags); -} -- cgit From 4e8d7b3e8ed045f6a110889c5e31f2c5170b68a7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Mar 2003 23:49:03 +0000 Subject: Ensure dev in make_connection is const. Jeremy. (This used to be commit 1c6ea31b8f48b93606f4c5b6a0472571dc8a471e) --- source3/smbd/service.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1c7e4017b0..0f178b8ffc 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -218,7 +218,7 @@ int find_service(fstring service) do some basic sainity checks on the share. This function modifies dev, ecode. ****************************************************************************/ -static NTSTATUS share_sanity_checks(int snum, pstring dev) +static NTSTATUS share_sanity_checks(int snum, fstring dev) { if (!lp_snum_ok(snum) || @@ -326,14 +326,17 @@ static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_grou static connection_struct *make_connection_snum(int snum, user_struct *vuser, DATA_BLOB password, - char *dev, NTSTATUS *status) + const char *pdev, NTSTATUS *status) { struct passwd *pass = NULL; BOOL guest = False; connection_struct *conn; struct stat st; fstring user; + fstring dev; + *user = 0; + fstrcpy(dev, pdev); if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { return NULL; @@ -717,7 +720,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, **************************************************************************************/ connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password, - char *dev, uint16 vuid, NTSTATUS *status) + const char *dev, uint16 vuid, NTSTATUS *status) { connection_struct *conn = NULL; @@ -747,12 +750,15 @@ connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB ****************************************************************************/ connection_struct *make_connection(const char *service_in, DATA_BLOB password, - char *dev, uint16 vuid, NTSTATUS *status) + const char *pdev, uint16 vuid, NTSTATUS *status) { uid_t euid; user_struct *vuser = NULL; fstring service; + fstring dev; int snum = -1; + + fstrcpy(dev, pdev); /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ if (!non_root_mode() && (euid = geteuid()) != 0) { -- cgit From 7e958f092a146190e7899482f26e13b480f83986 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Mar 2003 02:01:11 +0000 Subject: Doin't pstrcpy into fstring. Jeremy. (This used to be commit e619c50834a06b3026dc6b8603d1f88268bbdbc1) --- source3/smbd/service.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0f178b8ffc..a5e1ec4e93 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -229,13 +229,13 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) /* you can only connect to the IPC$ service as an ipc device */ if (strequal(lp_fstype(snum), "IPC")) - pstrcpy(dev,"IPC"); + fstrcpy(dev,"IPC"); if (dev[0] == '?' || !dev[0]) { if (lp_print_ok(snum)) { - pstrcpy(dev,"LPT1:"); + fstrcpy(dev,"LPT1:"); } else { - pstrcpy(dev,"A:"); + fstrcpy(dev,"A:"); } } @@ -248,7 +248,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) /* Behave as a printer if we are supposed to */ if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { - pstrcpy(dev, "LPT1:"); + fstrcpy(dev, "LPT1:"); } return NT_STATUS_OK; -- cgit From 0b72dd8325bc5c78de56039942acc175d28042a7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 20 Mar 2003 16:44:14 +0000 Subject: Patch from Samuel Thibault to convert messages from dos to unix charset when sending(and vice versa when receiving). (This used to be commit 5310447ec6e0df1c000e3ee14572f5b7fee31f28) --- source3/smbd/message.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index ba646f12aa..233848d2d6 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -41,6 +41,8 @@ static void msg_deliver(void) pstring name; int i; int fd; + char *msg; + int len; if (! (*lp_msg_command())) { @@ -61,16 +63,23 @@ static void msg_deliver(void) /* * Incoming message is in DOS codepage format. Convert to UNIX. */ - - if(msgpos > 0) { - msgbuf[msgpos] = '\0'; /* Ensure null terminated. */ - } - - for (i=0;i Date: Thu, 20 Mar 2003 18:13:27 +0000 Subject: Merge from HEAD (This used to be commit d59a7bea6b22a4c3e6cacd1a4c5ee95f42b13a26) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 775b617df5..7990585ef4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -276,7 +276,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,3,0,True); p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, devicename, -1, + p += srvstr_push(outbuf, p, IS_IPC(conn) ? "IPC" : devicename, -1, STR_TERMINATE|STR_ASCII); p += srvstr_push(outbuf, p, fsname, -1, STR_TERMINATE); -- cgit From 1f499a79f5468e87d26b60ffe3aa375b91cadbef Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 22 Mar 2003 13:47:42 +0000 Subject: (merge from HEAD) Small clenaup patches: - safe_string.h - don't assume that __FUNCTION__ is available - process.c - use new workaround from safe_string.h for the same - util.c - Show how many bytes we smb_panic()ed trying to smb_xmalloc() - gencache.c - Keep valgrind quiet by always null terminating. - clistr.c - Add copyright - srvstr.h - move srvstr_push into a .c file again, as a real function. - srvstr.c - revive, with 'safe' checked srvstr_push - loadparm.c - set a default for the display charset. - connection.c - use safe_strcpy() Andrew Bartlett (This used to be commit c91e76bddbe1244ddc8d12b092eba875834029ac) --- source3/smbd/connection.c | 6 +++--- source3/smbd/process.c | 12 ++++++++++-- source3/smbd/srvstr.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 source3/smbd/srvstr.c (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index a7636e889e..17b5be8a7b 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -171,14 +171,14 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti if (conn) { crec.uid = conn->uid; crec.gid = conn->gid; - StrnCpy(crec.name, + safe_strcpy(crec.name, lp_servicename(SNUM(conn)),sizeof(crec.name)-1); } crec.start = time(NULL); crec.bcast_msg_flags = msg_flags; - StrnCpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1); - StrnCpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1); + safe_strcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1); + safe_strcpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1); dbuf.dptr = (char *)&crec; dbuf.dsize = sizeof(crec); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 57bc236eef..16ef30c46c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1249,12 +1249,16 @@ void smbd_process(void) extern int smb_echo_count; time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; + const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN; - InBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); - OutBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); + InBuffer = (char *)malloc(total_buffer_size); + OutBuffer = (char *)malloc(total_buffer_size); if ((InBuffer == NULL) || (OutBuffer == NULL)) return; + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); + max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); while (True) { @@ -1278,6 +1282,8 @@ void smbd_process(void) num_smbs = 0; /* Reset smb counter. */ } + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); + while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) return; @@ -1295,6 +1301,8 @@ void smbd_process(void) */ num_echos = smb_echo_count; + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); + process_smb(InBuffer, OutBuffer); if (smb_echo_count != num_echos) { diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c new file mode 100644 index 0000000000..409fd30a67 --- /dev/null +++ b/source3/smbd/srvstr.c @@ -0,0 +1,44 @@ +/* + Unix SMB/CIFS implementation. + server specific string routines + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2003 + + 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 max_send; + +/* Make sure we can't write a string past the end of the buffer */ + +size_t srvstr_push_fn(const char *function, unsigned int line, + const char *base_ptr, void *dest, + const char *src, int dest_len, int flags) +{ + size_t buf_used = PTR_DIFF(dest, base_ptr); + if (dest_len == -1) { + if (((ptrdiff_t)dest < (ptrdiff_t)base_ptr) || (buf_used > (size_t)max_send)) { +#if 0 + DEBUG(0, ("Pushing string of 'unlimited' length into non-SMB buffer!\n")); +#endif + return push_string_fn(function, line, base_ptr, dest, src, -1, flags); + } + return push_string_fn(function, line, base_ptr, dest, src, max_send - buf_used, flags); + } + + /* 'normal' push into size-specified buffer */ + return push_string_fn(function, line, base_ptr, dest, src, dest_len, flags); +} -- cgit From 8460dc43406db90c169232ca5562d9bf4c7d34e8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 25 Mar 2003 04:14:54 +0000 Subject: win9x was suffered a case of the blues during a domain logon. For some reason, explicitly setting the service type during the tcon&X fixes this. (This used to be commit 4dd81caeff96d2b7f08b4846a524f917a85407a4) --- source3/smbd/reply.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7990585ef4..052884480b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -272,11 +272,20 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } else { /* NT sets the fstype of IPC$ to the null string */ const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); + const char *devicetype; + set_message(outbuf,3,0,True); + if ( IS_IPC(conn) ) + devicetype = "IPC"; + else if ( IS_PRINT(conn) ) + devicetype = "LPT:"; + else + devicetype = "A:"; + p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, IS_IPC(conn) ? "IPC" : devicename, -1, + p += srvstr_push(outbuf, p, IS_IPC(conn) ? "IPC" : devicetype, -1, STR_TERMINATE|STR_ASCII); p += srvstr_push(outbuf, p, fsname, -1, STR_TERMINATE); -- cgit From fa4b83ce922314892c90caaf5c7216be5e73ccd7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Mar 2003 22:15:21 +0000 Subject: Fix DOS del command with widelinks = False. Jeremy. (This used to be commit ef1782121bc4ebcdd2731fd6863209352f815dbe) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 052884480b..acd8dbbc7c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -397,7 +397,8 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (check_name(name,conn)) { if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0) - ok = S_ISDIR(sbuf.st_mode); + if (!(ok = S_ISDIR(sbuf.st_mode))) + errno = ENOTDIR; } if (!ok) { -- cgit From 560d83be393eadaa885f03ce17286c897913897f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 27 Mar 2003 22:01:22 +0000 Subject: pdb_ldap may require ROOT privilages to access the group mapping. (yes, it's ugly :-) Andrew Bartlett (This used to be commit 12579a62945d0d475b53c4ab49761a01be9e8394) --- source3/smbd/uid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 6ac3528b1a..b9cf0de3bd 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -781,7 +781,9 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) } /* Make sure we report failure, (when psid == NULL) */ + become_root(); psid = local_gid_to_sid(psid, gid); + unbecome_root(); DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); if (psid) store_gid_sid_cache(psid, SID_NAME_DOM_GRP, gid); -- cgit From 9676bf7e5c400dab8ee806ea77459e313fdbfe95 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 27 Mar 2003 22:27:53 +0000 Subject: cleanup the IPC/LPT:/A: mess I started (This used to be commit e6034a03d543d8672303f2b24982cfc03b124391) --- source3/smbd/reply.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index acd8dbbc7c..77f4c6783f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -204,16 +204,21 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt { fstring service; DATA_BLOB password; - pstring devicename; + + /* what the cleint thinks the device is */ + fstring client_devicetype; + /* what the server tells the client the share represents */ + const char *server_devicetype; NTSTATUS nt_status; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); pstring path; char *p, *q; extern BOOL global_encrypted_passwords_negotiated; + START_PROFILE(SMBtconX); - *service = *devicename = 0; + *service = *client_devicetype = 0; /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { @@ -250,11 +255,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt else fstrcpy(service,path); - p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII); + p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII); - DEBUG(4,("Got device type %s\n",devicename)); + DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service)); - conn = make_connection(service,password,devicename,vuid,&nt_status); + conn = make_connection(service,password,client_devicetype,vuid,&nt_status); data_blob_clear_free(&password); @@ -263,29 +268,27 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_NT(nt_status); } + if ( IS_IPC(conn) ) + server_devicetype = "IPC"; + else if ( IS_PRINT(conn) ) + server_devicetype = "LPT:"; + else + server_devicetype = "A:"; + if (Protocol < PROTOCOL_NT1) { set_message(outbuf,2,0,True); p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, devicename, -1, + p += srvstr_push(outbuf, p, server_devicetype, -1, STR_TERMINATE|STR_ASCII); set_message_end(outbuf,p); } else { /* NT sets the fstype of IPC$ to the null string */ const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); - const char *devicetype; - set_message(outbuf,3,0,True); - if ( IS_IPC(conn) ) - devicetype = "IPC"; - else if ( IS_PRINT(conn) ) - devicetype = "LPT:"; - else - devicetype = "A:"; - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, IS_IPC(conn) ? "IPC" : devicetype, -1, + p += srvstr_push(outbuf, p, server_devicetype, -1, STR_TERMINATE|STR_ASCII); p += srvstr_push(outbuf, p, fsname, -1, STR_TERMINATE); -- cgit From 567fcd81ed7e8cda0640d100f501083632b130f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 Mar 2003 01:07:05 +0000 Subject: merged real time signal fixes from head (This used to be commit 03a5e62300f3cfb96d14570b73a758e6fa64c449) --- source3/smbd/notify_kernel.c | 5 ++++- source3/smbd/oplock_linux.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 8b7ff21ecb..efe93de5af 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -39,7 +39,7 @@ static SIG_ATOMIC_T signals_received; #ifndef RT_SIGNAL_NOTIFY -#define RT_SIGNAL_NOTIFY 34 +#define RT_SIGNAL_NOTIFY (SIGRTMIN+2) #endif #ifndef F_SETSIG @@ -233,6 +233,9 @@ struct cnotify_fns *kernel_notify_init(void) cnotify.remove_notify = kernel_remove_notify; cnotify.select_time = -1; + /* the signal can start off blocked due to a bug in bash */ + BlockSignals(False, RT_SIGNAL_NOTIFY); + return &cnotify; } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index deed0c5107..84083dffc9 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -39,7 +39,7 @@ static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; #endif #ifndef RT_SIGNAL_LEASE -#define RT_SIGNAL_LEASE 33 +#define RT_SIGNAL_LEASE (SIGRTMIN+1) #endif #ifndef F_SETSIG @@ -296,6 +296,9 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) koplocks.msg_waiting = linux_oplock_msg_waiting; koplocks.notification_fd = -1; + /* the signal can start off blocked due to a bug in bash */ + BlockSignals(False, RT_SIGNAL_LEASE); + DEBUG(3,("Linux kernel oplocks enabled\n")); return &koplocks; -- cgit From 5fd03bffd3754c1f7ac2a63bcd14afd850a2e45c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 30 Mar 2003 16:37:10 +0000 Subject: This changes our handling of invalid service types that the client requested on tconx. We now return the same error code like NT4SP6 and W2kSP3 return. TCONDEV is a little test for this. Volker (This used to be commit 6f94ab8ed50ad171f25e9538417c5074feba164d) --- source3/smbd/service.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a5e1ec4e93..080e2f76df 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -227,22 +227,27 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_ACCESS_DENIED; } - /* you can only connect to the IPC$ service as an ipc device */ - if (strequal(lp_fstype(snum), "IPC")) - fstrcpy(dev,"IPC"); - if (dev[0] == '?' || !dev[0]) { if (lp_print_ok(snum)) { fstrcpy(dev,"LPT1:"); + } else if (strequal(lp_fstype(snum), "IPC")) { + fstrcpy(dev, "IPC"); } else { fstrcpy(dev,"A:"); } } - /* if the request is as a printer and you can't print then refuse */ strupper(dev); - if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { - DEBUG(1,("Attempt to connect to non-printer as a printer\n")); + + if (lp_print_ok(snum)) { + if (!strequal(dev, "LPT:")) { + return NT_STATUS_BAD_DEVICE_TYPE; + } + } else if (strequal(lp_fstype(snum), "IPC")) { + if (!strequal(dev, "IPC")) { + return NT_STATUS_BAD_DEVICE_TYPE; + } + } else if (!strequal(dev, "A:")) { return NT_STATUS_BAD_DEVICE_TYPE; } -- cgit From 744aa7208537374c33f7a0129c20c5c665d3d933 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sun, 30 Mar 2003 23:03:11 +0000 Subject: update copyright notice since it we are now almost 4 months into 2003 (This used to be commit 0751d2f117b4274dd19388d856de75d9fc739865) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4a79916efe..056231c344 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -759,7 +759,7 @@ static BOOL init_structs(void ) reopen_logs(); DEBUG(0,( "smbd version %s started.\n", VERSION)); - DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2002\n")); + DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2003\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); -- cgit From d8c1c54d3e8e75df4fc363b7bd0bc11d8bbe53ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Apr 2003 18:12:06 +0000 Subject: Doing janitor work for tridge. "changed the order of checking whether a SID is a UID or a GID in posix acls. This is needed because sid_to_uid always claims that the sid is a user, due ot a change I made some months back. This change was suggested by Chere Zhou, but is really an interim measure. Chere is looking at a longer term solution." REMEMBER - 3.0 is the one we will SHIP ! Jeremy. (This used to be commit a4d7496994b740e074398d98c999a803afff4404) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 01e3c31ba7..d4d966a636 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1003,12 +1003,12 @@ static BOOL create_canon_ace_lists(files_struct *fsp, if (nt4_compatible_acls()) psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid, &sid_type)) { - current_ace->owner_type = UID_ACE; - current_ace->type = SMB_ACL_USER; } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid, &sid_type)) { current_ace->owner_type = GID_ACE; current_ace->type = SMB_ACL_GROUP; + } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid, &sid_type)) { + current_ace->owner_type = UID_ACE; + current_ace->type = SMB_ACL_USER; } else { fstring str; -- cgit From 34226f1bd4d90ffe0f324277b11bbc4f2b575740 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Apr 2003 20:38:12 +0000 Subject: Fix for very subtle POSIX lock interaction race condition found by Herb. We need to unlock POSIX locks before notifying pending lock processes. Jeremy. (This used to be commit 6999eef51c3e597b3b2cd9cc26138acdfbb6a23a) --- source3/smbd/blocking.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 581ce43f91..2802fbb151 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -523,7 +523,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True); + blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); @@ -554,7 +554,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True); + blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -651,7 +651,7 @@ void process_blocking_lock_queue(time_t t) brl_unlock(fsp->dev, fsp->inode, fsp->fnum, blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True); + blr->offset, blr->count, True, NULL, NULL); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); @@ -669,7 +669,7 @@ void process_blocking_lock_queue(time_t t) brl_unlock(fsp->dev, fsp->inode, fsp->fnum, blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True); + blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); @@ -685,7 +685,7 @@ void process_blocking_lock_queue(time_t t) brl_unlock(fsp->dev, fsp->inode, fsp->fnum, blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True); + blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); @@ -703,7 +703,7 @@ void process_blocking_lock_queue(time_t t) brl_unlock(fsp->dev, fsp->inode, fsp->fnum, blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True); + blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); -- cgit From d5f235912fe5802a0698f0b56328a9a3b5f903fc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Apr 2003 21:58:55 +0000 Subject: Re-fix regression noticed by Tom Schaefer due to correct delete on close semantics change. Jeremy. (This used to be commit 7a45b45490e6001c17fc89aabfa802f76fa3fe5e) --- source3/smbd/close.c | 2 ++ source3/smbd/trans2.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4798d62db8..9cb191c4e2 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -196,6 +196,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \ with error %s\n", fsp->fsp_name, strerror(errno) )); } + process_pending_change_notify_queue((time_t)0); } unlock_share_entry_fsp(fsp); @@ -262,6 +263,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) if(ok) remove_pending_change_notify_requests_by_filename(fsp); + process_pending_change_notify_queue((time_t)0); } /* diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4129852f77..7b8b7e3a4f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2130,6 +2130,9 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n", delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + if (fsp->is_directory || fsp->is_stat) + return NT_STATUS_OK; + if (lock_share_entry_fsp(fsp) == False) return NT_STATUS_ACCESS_DENIED; -- cgit From 045db5d0458b331e987d82d6e9a61a0b85957d17 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Apr 2003 22:31:37 +0000 Subject: Ensure we have WinXP-like semantics for checking TIDs and FIDs. Jeremy. (This used to be commit 52e44dde4ef9717eae7cf454f56d309fdd4b7d1f) --- source3/smbd/reply.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 77f4c6783f..7da5c877a7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1464,6 +1464,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { + extern struct current_user current_user; ssize_t maxcount,mincount; size_t nread = 0; SMB_OFF_T startpos; @@ -2361,6 +2362,7 @@ int reply_exit(connection_struct *conn, int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { + extern struct current_user current_user; int outsize = 0; time_t mtime; int32 eclass = 0, err = 0; @@ -2381,7 +2383,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * We can only use CHECK_FSP if we know it's not a directory. */ - if(!fsp || (fsp->conn != conn)) { + if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) { END_PROFILE(SMBclose); return ERROR_DOS(ERRDOS,ERRbadfid); } -- cgit From 9bf3d3cb039d5304a70d1844b262c23489aa3227 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Apr 2003 22:34:30 +0000 Subject: Fix from Steve Langasek for non-RPC printing. Jeremy. (This used to be commit cfbd02b170ab7d9c5c9cc9dbab0a094faa15c518) --- source3/smbd/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 080e2f76df..eee17eda8c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -229,7 +229,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) if (dev[0] == '?' || !dev[0]) { if (lp_print_ok(snum)) { - fstrcpy(dev,"LPT1:"); + fstrcpy(dev,"LPT:"); } else if (strequal(lp_fstype(snum), "IPC")) { fstrcpy(dev, "IPC"); } else { @@ -253,7 +253,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) /* Behave as a printer if we are supposed to */ if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { - fstrcpy(dev, "LPT1:"); + fstrcpy(dev, "LPT:"); } return NT_STATUS_OK; -- cgit From 14e03aed2970d75cba216741d74363fc353955d2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 11 Apr 2003 23:28:15 +0000 Subject: cleanup lanman printing= for win98; device type is LPT1:; patch by Steve L. (This used to be commit 36d62e5667f3b9e39362fb3907bf69697fca3ea6) --- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7da5c877a7..c4147f78b1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -271,7 +271,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if ( IS_IPC(conn) ) server_devicetype = "IPC"; else if ( IS_PRINT(conn) ) - server_devicetype = "LPT:"; + server_devicetype = "LPT1:"; else server_devicetype = "A:"; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index eee17eda8c..67eea806c4 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -229,7 +229,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) if (dev[0] == '?' || !dev[0]) { if (lp_print_ok(snum)) { - fstrcpy(dev,"LPT:"); + fstrcpy(dev,"LPT1:"); } else if (strequal(lp_fstype(snum), "IPC")) { fstrcpy(dev, "IPC"); } else { @@ -240,7 +240,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) strupper(dev); if (lp_print_ok(snum)) { - if (!strequal(dev, "LPT:")) { + if (!strequal(dev, "LPT1:")) { return NT_STATUS_BAD_DEVICE_TYPE; } } else if (strequal(lp_fstype(snum), "IPC")) { @@ -253,7 +253,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) /* Behave as a printer if we are supposed to */ if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { - fstrcpy(dev, "LPT:"); + fstrcpy(dev, "LPT1:"); } return NT_STATUS_OK; -- cgit From e1ea87ff03f7029f309a119e6be726a11000ab34 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 11 Apr 2003 23:48:24 +0000 Subject: * We must return 0x2 as the majorversion for nt4 to upload drivers * fix bug found by clobber_region() (This used to be commit b2e29c7bd45f8f33d9ed58fe75bbf5ffc78350f5) --- source3/smbd/reply.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c4147f78b1..0ccb4d0e9d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3045,20 +3045,22 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Resolve wildcards in a filename rename. ********************************************************************/ -static BOOL resolve_wildcards(char *name1,char *name2) +static BOOL resolve_wildcards(const char *name1, char *name2) { fstring root1,root2; fstring ext1,ext2; - char *p,*p2; + char *p,*p2, *pname1, *pname2; + int available_space; + - name1 = strrchr_m(name1,'/'); - name2 = strrchr_m(name2,'/'); + pname1 = strrchr_m(name1,'/'); + pname2 = strrchr_m(name2,'/'); - if (!name1 || !name2) + if (!pname1 || !pname2) return(False); - fstrcpy(root1,name1); - fstrcpy(root2,name2); + fstrcpy(root1,pname1); + fstrcpy(root2,pname2); p = strrchr_m(root1,'.'); if (p) { *p = 0; @@ -3100,10 +3102,13 @@ static BOOL resolve_wildcards(char *name1,char *name2) p++; } - pstrcpy(name2,root2); + available_space = sizeof(pstring) - PTR_DIFF(pname2, name2); + + StrnCpy(pname2, root2, available_space-1); + available_space -= strlen(root2); if (ext2[0]) { - pstrcat(name2,"."); - pstrcat(name2,ext2); + strncat(pname2, ".", available_space-1); + strncat(pname2, ext2, available_space-2); } return(True); -- cgit From c8cc8bb60c77a4908be2757c78972c51c2ff700d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 13 Apr 2003 23:45:35 +0000 Subject: Merge of Simo's strncat -> StrnCpy fix. (This used to be commit a2b1a7533ed997848f9dc0fcd1ffc3d4b4e8117d) --- source3/smbd/reply.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0ccb4d0e9d..d655184042 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3104,11 +3104,10 @@ static BOOL resolve_wildcards(const char *name1, char *name2) available_space = sizeof(pstring) - PTR_DIFF(pname2, name2); - StrnCpy(pname2, root2, available_space-1); - available_space -= strlen(root2); if (ext2[0]) { - strncat(pname2, ".", available_space-1); - strncat(pname2, ext2, available_space-2); + snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); + } else { + StrnCpy(pname2, root2, available_space - 1); } return(True); -- cgit From 3b865c73989e7f13e3a6453f9f9c9a7aca74b129 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 14 Apr 2003 02:08:03 +0000 Subject: Merge of rpcecho pipe for testing large dcerpc requests and responses. Only compiled in when --enable-developer argument passed to configure. (This used to be commit 017da9393bab276543d0d5c50df8c760780f2450) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6d9c649045..9f7fabb75e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -40,6 +40,7 @@ static const char *known_nt_pipes[] = { "\\winreg", "\\spoolss", "\\netdfs", + "\\rpcecho", NULL }; -- cgit From 63cbbe26923b8f6bbed11428a3a218a88d17ffe7 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 14 Apr 2003 03:30:20 +0000 Subject: Merge Jelmer's popt updates from HEAD. (This used to be commit 98e84b3e83d2a365c818ea64f9418edb29d690f2) --- source3/smbd/server.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 056231c344..70925254e4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3,7 +3,7 @@ Main SMB server routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 - Copyright (C) Jelmer Vernooij 2002 + Copyright (C) Jelmer Vernooij 2002-2003 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 @@ -669,11 +669,7 @@ static BOOL init_structs(void ) {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug}, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile}, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_socket_options}, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_log_base}, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version}, + POPT_COMMON_SAMBA { NULL } }; -- cgit From bdb7a74419356f4b6064d928636c8f295e8b7230 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 14 Apr 2003 03:48:26 +0000 Subject: Whitespace syncup. (This used to be commit 8fe5bab565cdcf498e4d0f5cca31f799d249e3b3) --- source3/smbd/connection.c | 2 +- source3/smbd/dir.c | 4 ++-- source3/smbd/ipc.c | 6 +++--- source3/smbd/service.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 17b5be8a7b..5547309a81 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -172,7 +172,7 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti crec.uid = conn->uid; crec.gid = conn->gid; safe_strcpy(crec.name, - lp_servicename(SNUM(conn)),sizeof(crec.name)-1); + lp_servicename(SNUM(conn)),sizeof(crec.name)-1); } crec.start = time(NULL); crec.bcast_msg_flags = msg_flags; diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 3f29ac892c..6cf56fd373 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -627,8 +627,8 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname see masktest for a demo */ if ((strcmp(mask,"*.*") == 0) || - mask_match(filename,mask,False) || - mangle_mask_match(conn,filename,mask)) { + mask_match(filename,mask,False) || + mangle_mask_match(conn,filename,mask)) { if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) continue; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c4a12ab531..85e28f5d17 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -138,9 +138,9 @@ void send_trans_reply(char *outbuf, set_message(outbuf,10,1+this_ldata+this_lparam+align,False); copy_trans_params_and_data(outbuf, align, - rparam, tot_param_sent, this_lparam, - rdata, tot_data_sent, this_ldata); - + rparam, tot_param_sent, this_lparam, + rdata, tot_data_sent, this_ldata); + SSVAL(outbuf,smb_vwv3,this_lparam); SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); SSVAL(outbuf,smb_vwv5,tot_param_sent); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 67eea806c4..18a92bc82f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -762,7 +762,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstring service; fstring dev; int snum = -1; - + fstrcpy(dev, pdev); /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ -- cgit From c89a7057e5334ab8dadb4a847c2dc74434c1cc49 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 14 Apr 2003 03:54:31 +0000 Subject: Merge: - debugging tdb messages now initialised and handled in lib/messages.c (This used to be commit 380875de779f2519d9ce8735362484021388b4eb) --- source3/smbd/server.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 70925254e4..a6d3d92a8a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -501,25 +501,6 @@ BOOL reload_services(BOOL test) return(ret); } -/******************************************************************* - Print out all talloc memory info. -********************************************************************/ - -void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len) -{ - TALLOC_CTX *ctx = talloc_init("info context"); - char *info = NULL; - - if (!ctx) - return; - - info = talloc_describe_all(ctx); - if (info) - DEBUG(10,(info)); - message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1 : 0, True); - talloc_destroy(ctx); -} - #if DUMP_CORE /******************************************************************* prepare to dump a core file - carefully! @@ -821,10 +802,6 @@ static BOOL init_structs(void ) if (!message_init()) exit(1); - register_msg_pool_usage(); - register_dmalloc_msgs(); - message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info); - if (!print_backend_init()) exit(1); -- cgit From 7e4e1d70497973905cae4aa5fcd86ca1aa505542 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 15 Apr 2003 17:05:30 +0000 Subject: Print out information about statically linked in modules (This used to be commit 9ef6f917f964e6b514fb95e4da75a57cbad6a233) --- source3/smbd/build_options.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c index da5accebab..43335666a6 100644 --- a/source3/smbd/build_options.c +++ b/source3/smbd/build_options.c @@ -104,15 +104,6 @@ void build_options(BOOL screen) #ifdef WITH_PAM output(screen," WITH_PAM\n"); #endif -#ifdef WITH_TDB_SAM - output(screen," WITH_TDB_SAM\n"); -#endif -#ifdef WITH_SMBPASSWD_SAM - output(screen," WITH_SMBPASSWD_SAM\n"); -#endif -#ifdef WITH_NISPLUS_SAM - output(screen," WITH_NISPLUS_SAM\n"); -#endif #ifdef WITH_NISPLUS_HOME output(screen," WITH_NISPLUS_HOME\n"); #endif @@ -532,6 +523,9 @@ void build_options(BOOL screen) output(screen," sizeof(uint32): %d\n",sizeof(uint32)); output(screen," sizeof(short): %d\n",sizeof(short)); output(screen," sizeof(void*): %d\n",sizeof(void*)); + + output(screen,"\nBuiltin modules:\n"); + output(screen,"%s\n", STRING_STATIC_MODULES); } -- cgit From a8c95d79f83b4097ee20d5f3f1005c38ccf00186 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 16 Apr 2003 12:13:07 +0000 Subject: Add support for the new modules system to auth/ (merge from HEAD) (This used to be commit c7a1de090db35835be1a1623bfc80c04065c5dd9) --- source3/smbd/process.c | 2 +- source3/smbd/server.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 16ef30c46c..de1bea493f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -44,7 +44,7 @@ extern userdom_struct current_user_info; extern int smb_read_error; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; -extern BOOL global_machine_password_needs_changing; +BOOL global_machine_password_needs_changing = False; extern int max_send; /**************************************************************************** diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a6d3d92a8a..5c59dce4df 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -836,6 +836,10 @@ static BOOL init_structs(void ) if(!initialize_password_db(False)) exit(1); + static_init_rpc; + + init_modules(); + uni_group_cache_init(); /* Non-critical */ /* possibly reload the services file. */ -- cgit From ddf662d11886189151dca188a2eb4f6bd602caa0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 16 Apr 2003 14:45:11 +0000 Subject: More merges from HEAD: - Stephan Kulow's changes (fixing warnings in libsmbclient) - VFS modules - Seperating libs (This used to be commit 6e9b7802335428c88ecf4e44a0e2395ac58e96b5) --- source3/smbd/conn.c | 21 +++-- source3/smbd/vfs.c | 233 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 175 insertions(+), 79 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 38fa2e0237..b6c7aa1076 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -201,15 +201,18 @@ void conn_free(connection_struct *conn) /* Free vfs_connection_struct */ handle = conn->vfs_private; while(handle) { - /* Close dlopen() handle */ - done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done"); - - if (done_fptr == NULL) { - DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle)); - } else { - done_fptr(conn); - } - sys_dlclose(handle->handle); + /* Only call dlclose for the old modules */ + if (handle->handle) { + /* Close dlopen() handle */ + done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done"); + + if (done_fptr == NULL) { + DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle)); + } else { + done_fptr(conn); + } + sys_dlclose(handle->handle); + } DLIST_REMOVE(conn->vfs_private, handle); thandle = handle->next; SAFE_FREE(handle); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 533c64b229..06aca51322 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -27,6 +27,13 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS +struct vfs_init_function_entry { + char *name; + vfs_op_tuple *ops, *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *); + struct vfs_init_function_entry *prev, *next; +}; + +static struct vfs_init_function_entry *backends = NULL; /* Some structures to help us initialise the vfs operations table */ @@ -127,6 +134,59 @@ static struct vfs_ops default_vfs_ops = { vfswrap_sys_acl_free_qualifier }; +/**************************************************************************** + maintain the list of available backends +****************************************************************************/ + +static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) +{ + struct vfs_init_function_entry *entry = backends; + pstring stripped; + + module_path_get_name(name, stripped); + + while(entry) { + if (strequal(entry->name, stripped)) return entry; + entry = entry->next; + } + + return NULL; +} + +BOOL smb_register_vfs(const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *), int version) +{ + struct vfs_init_function_entry *entry = backends; + + if ((version < SMB_VFS_INTERFACE_CASCADED)) { + DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", + version, SMB_VFS_INTERFACE_VERSION )); + return False; + } + + if ((version < SMB_VFS_INTERFACE_VERSION)) { + DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ + Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", + version, SMB_VFS_INTERFACE_VERSION, version )); + return False; + } + + while(entry) { + if (strequal(entry->name, name)) { + DEBUG(0,("VFS module %s already loaded!\n", name)); + return False; + } + entry = entry->next; + } + + entry = smb_xmalloc(sizeof(struct vfs_init_function_entry)); + entry->name = smb_xstrdup(name); + entry->init = init; + + DLIST_ADD(backends, entry); + DEBUG(5, ("Successfully added vfs backend '%s'\n", name)); + return True; +} + /**************************************************************************** initialise default vfs hooks ****************************************************************************/ @@ -139,23 +199,19 @@ static void vfs_init_default(connection_struct *conn) conn->vfs_private = NULL; } -/**************************************************************************** - initialise custom vfs hooks -****************************************************************************/ +/*************************************************************************** + Function to load old VFS modules. Should go away after a while. + **************************************************************************/ -BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) +static vfs_op_tuple *vfs_load_old_plugin(connection_struct *conn, const char *vfs_object) { int vfs_version = -1; - vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *); - int i; - - DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object)); - + vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *); /* Open object file */ if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) { DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror())); - return False; + return NULL; } /* Get handle on vfs_init() symbol */ @@ -165,32 +221,73 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) if (init_fptr == NULL) { DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object)); sys_dlclose(conn->vfs_private->handle); - return False; + return NULL; } /* Initialise vfs_ops structure */ - - if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) { - DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object)); + if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) { + DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object)); sys_dlclose(conn->vfs_private->handle); - return False; - } - - if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) { - DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", - vfs_version, SMB_VFS_INTERFACE_VERSION )); + return NULL; + } + + if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) { + DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", + vfs_version, SMB_VFS_INTERFACE_VERSION )); sys_dlclose(conn->vfs_private->handle); - return False; - } - - if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) { - DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ -Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", - vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version )); + return NULL; + } + + if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) { + DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ + Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", + vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version )); sys_dlclose(conn->vfs_private->handle); - return False; - } - + return NULL; + } + + return ops; +} + + + +/**************************************************************************** + initialise custom vfs hooks + ****************************************************************************/ + +BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) +{ + vfs_op_tuple *ops; + int i; + struct vfs_init_function_entry *entry; + + DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object)); + + if(!backends) static_init_vfs; + + /* First, try to load the module with the new module system */ + if((entry = vfs_find_backend_entry(vfs_object)) || + (smb_probe_module("vfs", vfs_object) && + (entry = vfs_find_backend_entry(vfs_object)))) { + + DEBUG(3,("Successfully loaded %s with the new modules system\n", vfs_object)); + + if ((ops = entry->init(&conn->vfs_ops, conn->vfs_private)) == NULL) { + DEBUG(0, ("vfs init function from %s failed\n", vfs_object)); + return False; + } + } else { + /* If that doesn't work, fall back to the old system + * (This part should go away after a while, it's only here + * for backwards compatibility) */ + DEBUG(2, ("Can't load module %s with new modules system, falling back to compatibility\n", + vfs_object)); + if ((ops = vfs_load_old_plugin(conn, vfs_object)) == NULL) { + DEBUG(0, ("vfs init function from %s failed\n", vfs_object)); + return False; + } + } + for(i=0; ops[i].op != NULL; i++) { DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { @@ -215,54 +312,50 @@ Proceeding in compatibility mode, new operations (since version #%d) will fallba BOOL smbd_vfs_init(connection_struct *conn) { - char **vfs_objects, *vfsobj, *vfs_module, *vfs_path; - int nobj, i; + const char **vfs_objects; + char *vfs_module, *vfs_path; + unsigned int i = 0; + int j = 0; struct smb_vfs_handle_struct *handle; /* Normal share - initialise with disk access functions */ vfs_init_default(conn); + vfs_objects = lp_vfsobj(SNUM(conn)); /* Override VFS functions if 'vfs object' was specified*/ - if (*lp_vfsobj(SNUM(conn))) { - vfsobj = NULL; - for(i=0; i= 0; j--) { + conn->vfs_private = NULL; + handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct)); + /* Loadable object file */ + handle->handle = NULL; + DLIST_ADD(conn->vfs_private, handle); + vfs_module = NULL; + if (vfs_path && *vfs_path) { + asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[j]); + } else { + asprintf(&vfs_module, "%s", vfs_objects[j]); } - if (string_set(&vfsobj, lp_vfsobj(SNUM(conn)))) { - /* Parse passed modules specification to array of modules */ - set_first_token(vfsobj); - /* We are using default separators: ' \t\r\n' */ - vfs_objects = toktocliplist(&nobj, NULL); - if (vfs_objects) { - vfs_path = lp_vfs_path(SNUM(conn)); - conn->vfs_private = NULL; - for(i=nobj-1; i>=0; i--) { - handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct)); - /* Loadable object file */ - handle->handle = NULL; - DLIST_ADD(conn->vfs_private, handle) - vfs_module = NULL; - if (vfs_path) { - asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[i]); - } else { - asprintf(&vfs_module, "%s", vfs_objects[i]); - } - if (!vfs_init_custom(conn, vfs_module)) { - DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module)); - string_free(&vfsobj); - SAFE_FREE(vfs_module); - DLIST_REMOVE(conn->vfs_private, handle); - SAFE_FREE(handle); - return False; - } - SAFE_FREE(vfs_module); - } - } - string_free(&vfsobj); - return True; + if (!vfs_init_custom(conn, vfs_module)) { + DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module)); + SAFE_FREE(vfs_module); + DLIST_REMOVE(conn->vfs_private, handle); + SAFE_FREE(handle); + return False; } + SAFE_FREE(vfs_module); } return True; } -- cgit From 7706e98d9d170dd9dde398b0a5c67790e29d803b Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 19 Apr 2003 15:31:40 +0000 Subject: use gid_t for gids not uid_t (This used to be commit a369c2ff2637dc808035217eaada4cf923c5cf6d) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d4d966a636..a38acc437d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2593,7 +2593,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Do we need to chown ? */ - if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (uid_t)-1) && (orig_gid != grp))) + if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) need_chown = True; /* -- cgit From f071020f5e49837154581c97c5af5f84d0e2de89 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Apr 2003 14:09:03 +0000 Subject: Merge from HEAD - save the type of channel used to contact the DC. This allows us to join as a BDC, without appearing on the network as one until we have the database replicated, and the admin changes the configuration. This also change the SID retreval order from secrets.tdb, so we no longer require a 'net rpc getsid' - the sid fetch during the domain join is sufficient. Also minor fixes to 'net'. Andrew Bartlett (This used to be commit 876e00fd112e4aaf7519eec27f382eb99ec7562a) --- source3/smbd/change_trust_pw.c | 95 ++++++++++++++---------------------------- source3/smbd/process.c | 6 ++- 2 files changed, 36 insertions(+), 65 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index a140978733..8aff96d0d6 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -24,26 +24,36 @@ #include "includes.h" -/********************************************************* - Change the domain password on the PDC. -**********************************************************/ +/************************************************************************ + Change the trust account password for a domain. +************************************************************************/ -static NTSTATUS modify_trust_password( const char *domain, const char *remote_machine, - unsigned char orig_trust_passwd_hash[16]) +NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine) { + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct in_addr pdc_ip; + fstring dc_name; struct cli_state *cli; - DOM_SID domain_sid; - NTSTATUS nt_status; - /* - * Ensure we have the domain SID for this domain. - */ + if (remote_machine == NULL || !strcmp(remote_machine, "*")) { + /* Use the PDC *only* for this */ + + if ( !get_pdc_ip(domain, &pdc_ip) ) { + DEBUG(0,("Can't get IP for PDC for domain %s\n", domain)); + goto failed; + } - if (!secrets_fetch_domain_sid(domain, &domain_sid)) { - DEBUG(0, ("modify_trust_password: unable to fetch domain sid.\n")); - return NT_STATUS_UNSUCCESSFUL; + if ( !lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name) ) + goto failed; } - + /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ + else { + fstrcpy( dc_name, remote_machine ); + } + + /* if this next call fails, then give up. We can't do + password changes on BDC's --jerry */ + if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine, NULL, 0, "IPC$", "IPC", @@ -51,7 +61,8 @@ static NTSTATUS modify_trust_password( const char *domain, const char *remote_ma "", 0, NULL))) { DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); - return NT_STATUS_UNSUCCESSFUL; + nt_status = NT_STATUS_UNSUCCESSFUL; + goto failed; } /* @@ -65,64 +76,22 @@ static NTSTATUS modify_trust_password( const char *domain, const char *remote_ma cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); - return NT_STATUS_UNSUCCESSFUL; + nt_status = NT_STATUS_UNSUCCESSFUL; + goto failed; } - nt_status = trust_pw_change_and_store_it(cli, cli->mem_ctx, - orig_trust_passwd_hash); + nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, + domain); cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); - return nt_status; -} - -/************************************************************************ - Change the trust account password for a domain. -************************************************************************/ - -NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine) -{ - unsigned char old_trust_passwd_hash[16]; - time_t lct; - NTSTATUS res = NT_STATUS_UNSUCCESSFUL; - struct in_addr pdc_ip; - fstring dc_name; - - - if(!secrets_fetch_trust_account_password(domain, old_trust_passwd_hash, &lct)) { - DEBUG(0,("change_trust_account_password: unable to read the machine account password for domain %s.\n", - domain)); - return NT_STATUS_UNSUCCESSFUL; - } - - if (remote_machine == NULL || !strcmp(remote_machine, "*")) { - /* Use the PDC *only* for this */ - - if ( !get_pdc_ip(domain, &pdc_ip) ) { - DEBUG(0,("Can't get IP for PDC for domain %s\n", domain)); - goto failed; - } - - if ( !lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name) ) - goto failed; - } - /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ - else { - fstrcpy( dc_name, remote_machine ); - } - - /* if this next call fails, then give up. We can't do - password changes on BDC's --jerry */ - - res = modify_trust_password(domain, dc_name, old_trust_passwd_hash); - failed: - if (!NT_STATUS_IS_OK(res)) { + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", timestring(False), domain)); } - return res; + return nt_status; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index de1bea493f..54fd4a90d9 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1179,9 +1179,11 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); return True; } - if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct)) { + if(!secrets_fetch_trust_account_password(lp_workgroup(), + trust_passwd_hash, + &lct, NULL)) { DEBUG(0,("process: unable to read the machine account password for \ -machine %s in domain %s.\n", global_myname(), lp_workgroup() )); +machine %s in domain %s.\n", global_myname(), lp_workgroup())); secrets_lock_trust_account_password(lp_workgroup(), False); return True; } -- cgit From 79d3731d98836e6a502eb21d3d50df381b67600c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 21 Apr 2003 19:43:25 +0000 Subject: * fix segfault when no vfs objects defined * add "sid=..." to 'net groupmap add' (This used to be commit e5f6676639b5552f7dec90091c53cf14e78088ee) --- source3/smbd/vfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 06aca51322..75bcb09917 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -322,8 +322,8 @@ BOOL smbd_vfs_init(connection_struct *conn) vfs_init_default(conn); vfs_objects = lp_vfsobj(SNUM(conn)); - /* Override VFS functions if 'vfs object' was specified*/ - if (!vfs_objects) + /* Override VFS functions if 'vfs object' was not specified*/ + if (!vfs_objects || !vfs_objects[0]) return True; for(i=0; i Date: Tue, 22 Apr 2003 01:12:52 +0000 Subject: Tidyups of some dubious logic discovered whilst trying to track down a strange oplock related issue on the PSA. Jeremy. (This used to be commit 1dd274bf61aaaad3c475de93f53aac176678bc7c) --- source3/smbd/close.c | 2 +- source3/smbd/oplock.c | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 9cb191c4e2..5cca85500f 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -201,7 +201,7 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); unlock_share_entry_fsp(fsp); - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(fsp->oplock_type) release_file_oplock(fsp); locking_close_file(fsp); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index f5c19bcf62..8525687793 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -226,12 +226,12 @@ tv_sec = %x, tv_usec = %x\n", void release_file_oplock(files_struct *fsp) { - if (koplocks) + if ((fsp->oplock_type != NO_OPLOCK) && koplocks) koplocks->release_oplock(fsp); if (fsp->oplock_type == LEVEL_II_OPLOCK) level_II_oplocks_open--; - else + else if (fsp->oplock_type) exclusive_oplocks_open--; fsp->oplock_type = NO_OPLOCK; @@ -270,7 +270,7 @@ BOOL remove_oplock(files_struct *fsp, BOOL break_to_none) if (lock_share_entry_fsp(fsp) == False) { DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", fsp->fsp_name )); - ret = False; + return False; } if (fsp->sent_oplock_break == EXCLUSIVE_BREAK_SENT || break_to_none) { @@ -626,12 +626,11 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); } + release_file_oplock(fsp); + if (!local_request && got_lock) unlock_share_entry_fsp(fsp); - fsp->oplock_type = NO_OPLOCK; - level_II_oplocks_open--; - if(level_II_oplocks_open < 0) { DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", level_II_oplocks_open)); -- cgit From cb380f13f7957cd0c04f9bad73c42ae9576ed892 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 22 Apr 2003 12:28:30 +0000 Subject: Merge comment with HEAD (This used to be commit 8f8d819d5814c2a538b5b906014ff0c354625450) --- source3/smbd/sesssetup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e36760c148..25f9d424ab 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -77,9 +77,6 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, set_message(outbuf,4,0,True); - /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end - that we aren't finished yet */ - nt_status = nt_status_squash(nt_status); SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status)); SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ @@ -309,6 +306,9 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, ret = reply_sesssetup_blob(conn, outbuf, response, nt_status); data_blob_free(&response); + /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us, + and the other end, that we are not finished yet. */ + if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { auth_ntlmssp_end(auth_ntlmssp_state); } -- cgit From 2aa7b1573c940d7a0381ac33f97ee5bd185c16bd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Apr 2003 17:30:53 +0000 Subject: Add runtime tests for "impossible" case with -DDEVELOPER. Trying to catch logic error on Linux. Jeremy. (This used to be commit 546d1a941b63a538702f2fb668019d2b89f63bdc) --- source3/smbd/open.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6b3dcbe71b..5e4f3caca7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -532,6 +532,29 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign return True; } + +#if defined(DEVELOPER) +static void validate_my_share_entries(share_mode_entry *share_entry) +{ + files_struct *fsp; + + if (share_entry->pid != sys_getpid()) + return; + + fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); + if (!fsp) { + smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); + } + + if (((uint16)fsp->oplock_type) != share_entry->op_type) { + pstring str; + slprintf(str, sizeof(str)-1, "validate_my_share_entries: file %s, oplock_type = 0x%x, op_type = 0x%x\n", + fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); + smb_panic(str); + } +} +#endif + /**************************************************************************** Deal with open deny mode and oplock break processing. Invarient: Share mode must be locked on entry and exit. @@ -572,6 +595,10 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &old_shares[i]; +#if defined(DEVELOPER) + validate_my_share_entries(share_entry); +#endif + /* * By observation of NetBench, oplocks are broken *before* share * modes are checked. This allows a file to be closed by the client -- cgit From 0e26a6d3f5fc7616ca5caacf3ed39c8c40091c99 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 01:05:26 +0000 Subject: Don't leak the session identifier string when we shut down a vuid. Andrew Bartlett (This used to be commit 33189b4be0ac79d5e7bc2606f40187118ee506a4) --- source3/smbd/password.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 784c1525c8..b47dcc0a97 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -68,6 +68,7 @@ void invalidate_vuid(uint16 vuid) SAFE_FREE(vuser->logon_script); session_yield(vuser); + SAFE_FREE(vuser->session_keystr); free_server_info(&vuser->server_info); -- cgit From be86f6555a74ca8eb321e25aef618f6e9ced731c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 11:11:02 +0000 Subject: Make the variable name match the comment. Andrew Bartlett (This used to be commit 5a577f8cafa7375bd8485763f163de939ddc4a39) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d655184042..3bb161e0cb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -283,14 +283,14 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message_end(outbuf,p); } else { /* NT sets the fstype of IPC$ to the null string */ - const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); + const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); set_message(outbuf,3,0,True); p = smb_buf(outbuf); p += srvstr_push(outbuf, p, server_devicetype, -1, STR_TERMINATE|STR_ASCII); - p += srvstr_push(outbuf, p, fsname, -1, + p += srvstr_push(outbuf, p, fstype, -1, STR_TERMINATE); set_message_end(outbuf,p); -- cgit From 1a9394195d0c53c23b9377ce122f399fa914f58c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 11:54:56 +0000 Subject: Merge HEAD's winbind into 3.0. This includes the 'SIDs Rule' patch, mimir's trusted domains cacheing code, the winbind_idmap abstraction (not idmap proper, but the stuff that held up the winbind LDAP backend in HEAD). Andrew Bartlett (This used to be commit d4d5e6c2ee6383c6cceb5d449aa2ba6c83eb0666) --- source3/smbd/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5c59dce4df..ffffa3cce3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -877,6 +877,7 @@ static BOOL init_structs(void ) smbd_process(); uni_group_cache_shutdown(); + namecache_shutdown(); exit_server("normal exit"); return(0); } -- cgit From 2a3a9f0bf43c3bf99a71f7296bb5ff6199893fea Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 13:27:35 +0000 Subject: Merge the 'safe' parts of my StrnCpy patch - many of the users really wanted a pstrcpy/fstrcpy or at most a safe_strcpy(). These have the advantage of being compiler-verifiable. Get these out of the way, along with a rewrite of 'get_short_archi' in the spoolss client and server. (This pushes around const string pointers, rather than copied strings). Andrew Bartlett (This used to be commit 32fb801ddc035e8971e9911ed4b6e51892e9d1cc) --- source3/smbd/open.c | 2 +- source3/smbd/password.c | 6 +++--- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 7 ++++--- source3/smbd/statcache.c | 12 ------------ 5 files changed, 9 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5e4f3caca7..9e49a0bc22 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -73,7 +73,7 @@ static void check_for_pipe(char *fname) { /* special case of pipe opens */ char s[10]; - StrnCpy(s,fname,sizeof(s)-1); + safe_strcpy(s,fname,sizeof(s)-1); strlower(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b47dcc0a97..8dff42471f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -250,7 +250,7 @@ void add_session_user(const char *user) if (!(passwd = Get_Pwnam(user))) return; - StrnCpy(suser,passwd->pw_name,sizeof(suser)-1); + fstrcpy(suser,passwd->pw_name); if (suser && *suser && !in_list(suser,session_users,False)) { @@ -448,7 +448,7 @@ and given password ok\n", user)); if (!ok && lp_username(snum)) { char *auser; pstring user_list; - StrnCpy(user_list,lp_username(snum),sizeof(pstring)); + pstrcpy(user_list,lp_username(snum)); pstring_sub(user_list,"%S",lp_servicename(snum)); @@ -478,7 +478,7 @@ and given password ok (%s)\n", user)); /* check for a normal guest connection */ if (!ok && GUEST_OK(snum)) { fstring guestname; - StrnCpy(guestname,lp_guestaccount(),sizeof(guestname)-1); + fstrcpy(guestname,lp_guestaccount()); if (Get_Pwnam(guestname)) { fstrcpy(user,guestname); ok = True; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3bb161e0cb..9577196bfe 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3107,7 +3107,7 @@ static BOOL resolve_wildcards(const char *name1, char *name2) if (ext2[0]) { snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); } else { - StrnCpy(pname2, root2, available_space - 1); + pstrcpy_base(pname2, root2, name2); } return(True); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 18a92bc82f..cfb5e0e414 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -486,13 +486,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring tmp_gname; BOOL user_must_be_member = False; - StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1); + pstrcpy(tmp_gname,lp_force_group(snum)); if (tmp_gname[0] == '+') { user_must_be_member = True; - StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2); + /* even now, tmp_gname is null terminated */ + pstrcpy(gname,&tmp_gname[1]); } else { - StrnCpy(gname,tmp_gname,sizeof(pstring)-1); + pstrcpy(gname,tmp_gname); } /* default service may be a group name */ pstring_sub(gname,"%S",lp_servicename(snum)); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 0f42a3a83f..44bae48990 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -128,18 +128,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat original_path_length = translated_path_length; } -#if 0 - /* - * We will only replace namelen characters - * of full_orig_name. - * StrnCpy always null terminates. - */ - - smbStrnCpy(orig_name, full_orig_name, namelen); - if(!case_sensitive) - strupper( orig_name ); -#endif - /* * Check this name doesn't exist in the cache before we * add it. -- cgit From 7ae247719739d0026849ee6b615f13b154b6bf3a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 13:35:10 +0000 Subject: StrnCpy -> safe_strcpy() on a over-malloced struct. Andrew Bartlett (This used to be commit e4f1171d57a6186f85b87586a525b3bbaf601974) --- source3/smbd/mangle_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index e220d2f6d2..d2eb996899 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -556,8 +556,8 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) /* Fill the new cache entry, and add it to the cache. */ s1 = (char *)(new_entry + 1); s2 = (char *)&(s1[mangled_len + 1]); - (void)StrnCpy( s1, mangled_name, mangled_len ); - (void)StrnCpy( s2, raw_name, raw_len ); + safe_strcpy( s1, mangled_name, mangled_len ); + safe_strcpy( s2, raw_name, raw_len ); ubi_cachePut( mangled_cache, i, new_entry, s1 ); } -- cgit From 53004910ebe729809e7d3c9724f338d1b763be9b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 14:19:03 +0000 Subject: Patch by Vance Lankhaar to automaticly regenerate the build options, so we will always have the right values for how and when an smbd was built. In particular, this is indended to address bitrot caused by configure.in changes. Andrew Bartlett (This used to be commit 2be258071c71986ba9af01e9a09ec49909a620dd) --- source3/smbd/.cvsignore | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/.cvsignore b/source3/smbd/.cvsignore index 5f2a5c4cf7..d2b1fd5b2e 100644 --- a/source3/smbd/.cvsignore +++ b/source3/smbd/.cvsignore @@ -1,2 +1,3 @@ *.po *.po32 +build_options.c -- cgit From 14a317010ca8393c0148b0f21d701bb32dd68ab2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 14:31:23 +0000 Subject: Thanks to a reminder from vance - delete build_options.c from CVS, now it's autogenerated. (This used to be commit 1cbc66e2e35342980f27151622658e2f2f498245) --- source3/smbd/build_options.c | 532 ------------------------------------------- 1 file changed, 532 deletions(-) delete mode 100644 source3/smbd/build_options.c (limited to 'source3/smbd') diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c deleted file mode 100644 index 43335666a6..0000000000 --- a/source3/smbd/build_options.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Build Options for Samba Suite - Copyright (C) Vance Lankhaar 2001 - Copyright (C) Andrew Bartlett 2001 - - 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 "build_env.h" -#include "dynconfig.h" - -static void output(BOOL screen, const char *format, ...) PRINTF_ATTRIBUTE(2,3); - -/* -#define OUTPUT(x) snprintf(outstring,sizeof(outstring),x); output(screen,outstring); -*/ -/**************************************************************************** -helper function for build_options -****************************************************************************/ -static void output(BOOL screen, const char *format, ...) -{ - char *ptr; - va_list ap; - - va_start(ap, format); - vasprintf(&ptr,format,ap); - va_end(ap); - - if (screen) { - d_printf("%s", ptr); - } else { - DEBUG(4,("%s", ptr)); - } - - SAFE_FREE(ptr); -} - -/**************************************************************************** -options set at build time for the samba suite -****************************************************************************/ -void build_options(BOOL screen) -{ - if ((DEBUGLEVEL < 4) && (!screen)) { - return; - } - -#ifdef _BUILD_ENV_H - /* Output information about the build environment */ - output(screen,"Build environment:\n"); - output(screen," Built by: %s@%s\n",BUILD_ENV_USER,BUILD_ENV_HOST); - output(screen," Built on: %s\n",BUILD_ENV_DATE); - - output(screen," Built using: %s\n",BUILD_ENV_COMPILER); - output(screen," Build host: %s\n",BUILD_ENV_UNAME); - output(screen," SRCDIR: %s\n",BUILD_ENV_SRCDIR); - output(screen," BUILDDIR: %s\n",BUILD_ENV_BUILDDIR); - - -#endif - - /* Output various options (most correspond to --with options) */ - output(screen,"\nBuild options:\n"); -#ifdef WITH_SMBWRAPPER - output(screen," WITH_SMBWRAPPER\n"); -#endif -#ifdef WITH_AFS - output(screen," WITH_AFS\n"); -#endif -#ifdef WITH_DFS - output(screen," WITH_DFS\n"); -#endif -#ifdef KRB4_AUTH - output(screen," KRB4_AUTH"); -#endif -#ifdef HAVE_KRB5 - output(screen," HAVE_KRB5"); -#endif -#ifdef HAVE_GSSAPI - output(screen," HAVE_GSSAPI"); -#endif -#ifdef HAVE_LDAP - output(screen," HAVE_LDAP"); -#endif -#ifdef WITH_AUTOMOUNT - output(screen," WITH_AUTOMOUNT\n"); -#endif -#ifdef WITH_SMBMOUNT - output(screen," WITH_SMBMOUNT\n"); -#endif -#ifdef WITH_PAM - output(screen," WITH_PAM\n"); -#endif -#ifdef WITH_NISPLUS_HOME - output(screen," WITH_NISPLUS_HOME\n"); -#endif -#ifdef WITH_SYSLOG - output(screen," WITH_SYSLOG\n"); -#endif -#ifdef WITH_PROFILE - output(screen," WITH_PROFILE\n"); -#endif -#ifdef WITH_QUOTAS - output(screen," WITH_QUOTAS\n"); -#endif -#ifdef WITH_VFS - output(screen," WITH_VFS\n"); -#endif -#ifdef USE_SPINLOCKS - output(screen," USE_SPINLOCKS\n"); -#endif -#ifdef SPARC_SPINLOCKS - output(screen," SPARC_SPINLOCKS\n"); -#endif -#ifdef INTEL_SPINLOCKS - output(screen," INTEL_SPINLOCKS\n"); -#endif -#ifdef MIPS_SPINLOCKS - output(screen," MIPS_SPINLOCKS\n"); -#endif -#ifdef POWERPC_SPINLOCKS - output(screen," POWERPC_SPINLOCKS\n"); -#endif -#ifdef HAVE_UNIXWARE_ACLS - output(screen," HAVE_UNIXWARE_ACLS\n"); -#endif -#ifdef HAVE_SOLARIS_ACLS - output(screen," HAVE_SOLARIS_ACLS\n"); -#endif -#ifdef HAVE_IRIX_ACLS - output(screen," HAVE_IRIX_ACLS\n"); -#endif -#ifdef HAVE_AIX_ACLS - output(screen," HAVE_AIX_ACLS\n"); -#endif -#ifdef HAVE_POSIX_ACLS - output(screen," HAVE_POSIX_ACLS\n"); -#endif -#ifdef HAVE_TRU64_ACLS - output(screen," HAVE_TRU64_ACLS\n"); -#endif - -#ifdef HAVE_ACL_GET_PERM_NP - output(screen," HAVE_ACL_GET_PERM_NP\n"); -#endif -#ifdef HAVE_NO_ACLS - output(screen," HAVE_NO_ACLS\n"); -#endif -#ifdef HAVE_LIBREADLINE - output(screen," HAVE_LIBREADLINE\n"); -#endif -#ifdef WITH_LIBICONV - output(screen," WITH_LIBICONV: %s\n",WITH_LIBICONV); -#endif - - - /* Output various paths to files and directories */ - output(screen,"\nPaths:\n"); - output(screen," CONFIGFILE: %s\n", dyn_CONFIGFILE); -#ifdef PRIVATE_DIR - output(screen," PRIVATE_DIR: %s\n",PRIVATE_DIR); -#endif -#ifdef LMHOSTSFILE - output(screen," LMHOSTSFILE: %s\n",LMHOSTSFILE); -#endif - output(screen," SBINDIR: %s\n", dyn_SBINDIR); - output(screen," BINDIR: %s\n", dyn_BINDIR); - output(screen," LOCKDIR: %s\n",dyn_LOCKDIR); - output(screen," LOGFILEBASE: %s\n", dyn_LOGFILEBASE); - - /*Output various other options (most map to defines in the configure script*/ - output(screen,"\nOther Build Options:\n"); -#ifdef HAVE_VOLATILE - output(screen," HAVE_VOLATILE\n"); -#endif -#ifdef HAVE_SHADOW_H - output(screen," HAVE_SHADOW_H\n"); -#endif -#ifdef HAVE_CRYPT - output(screen," HAVE_CRYPT\n"); -#endif -#ifdef USE_BOTH_CRYPT_CALLS - output(screen," USE_BOTH_CRYPT_CALLS\n"); -#endif -#ifdef HAVE_TRUNCATED_SALT - output(screen," HAVE_TRUNCATED_SALT\n"); -#endif -#ifdef HAVE_CUPS - output(screen," HAVE_CUPS\n"); -#endif -#ifdef HAVE_CUPS_CUPS_H - output(screen," HAVE_CUPS_CUPS_H\n"); -#endif -#ifdef HAVE_CUPS_LANGUAGE_H - output(screen," HAVE_CUPS_LANGUAGE_H\n"); -#endif -#ifdef HAVE_DLOPEN - output(screen," HAVE_DLOPEN\n"); -#endif -#ifdef HAVE_DLCLOSE - output(screen," HAVE_DLCLOSE\n"); -#endif -#ifdef HAVE_DLSYM - output(screen," HAVE_DLSYM\n"); -#endif -#ifdef HAVE_DLERROR - output(screen," HAVE_DLERROR\n"); -#endif -#ifdef HAVE_UNIXSOCKET - output(screen," HAVE_UNIXSOCKET\n"); -#endif -#ifdef HAVE_SOCKLEN_T_TYPE - output(screen," HAVE_SOCKLEN_T_TYPE\n"); -#endif -#ifdef HAVE_SIG_ATOMIC_T_TYPE - output(screen," HAVE_SIG_ATOMIC_T_TYPE\n"); -#endif -#ifdef HAVE_SETRESUID - output(screen," HAVE_SETRESUID\n"); -#endif -#ifdef HAVE_SETRESGID - output(screen," HAVE_SETRESGID\n"); -#endif -#ifdef HAVE_CONNECT - output(screen," HAVE_CONNECT\n"); -#endif -#ifdef HAVE_YP_GET_DEFAULT_DOMAIN - output(screen," HAVE_YP_GET_DEFAULT_DOMAIN\n"); -#endif -#ifdef HAVE_STAT64 - output(screen," HAVE_STAT64\n"); -#endif -#ifdef HAVE_LSTAT64 - output(screen," HAVE_LSTAT64\n"); -#endif -#ifdef HAVE_FSTAT64 - output(screen," HAVE_FSTAT64\n"); -#endif -#ifdef HAVE_STRCASECMP - output(screen," HAVE_STRCASECMP\n"); -#endif -#ifdef HAVE_MEMSET - output(screen," HAVE_MEMSET\n"); -#endif -#ifdef HAVE_LONGLONG - output(screen," HAVE_LONGLONG\n"); -#endif -#ifdef COMPILER_SUPPORTS_LL - output(screen," COMPILER_SUPPORTS_LL\n"); -#endif -#ifdef SIZEOF_OFF_T - output(screen," SIZEOF_OFF_T: %d\n",SIZEOF_OFF_T); -#endif -#ifdef HAVE_OFF64_T - output(screen," HAVE_OFF64_T\n"); -#endif -#ifdef SIZEOF_INO_T - output(screen," SIZEOF_INO_T: %d\n",SIZEOF_INO_T); -#endif -#ifdef HAVE_INO64_T - output(screen," HAVE_INO64_T\n"); -#endif -#ifdef HAVE_STRUCT_DIRENT64 - output(screen," HAVE_STRUCT_DIRENT64\n"); -#endif -#ifdef HAVE_UNSIGNED_CHAR - output(screen," HAVE_UNSIGNED_CHAR\n"); -#endif -#ifdef HAVE_SOCK_SIN_LEN - output(screen," HAVE_SOCK_SIN_LEN\n"); -#endif -#ifdef SEEKDIR_RETURNS_VOID - output(screen," SEEKDIR_RETURNS_VOID\n"); -#endif -#ifdef HAVE_FUNCTION_MACRO - output(screen," HAVE_FUNCTION_MACRO\n"); -#endif -#ifdef HAVE_GETTIMEOFDAY - output(screen," HAVE_GETTIMEOFDAY\n"); -#endif -#ifdef HAVE_C99_VSNPRINTF - output(screen," HAVE_C99_VSNPRINTF\n"); -#endif -#ifdef HAVE_BROKEN_READDIR - output(screen," HAVE_BROKEN_READDIR\n"); -#endif -#ifdef HAVE_NATIVE_ICONV - output(screen," HAVE_NATIVE_ICONV\n"); -#endif -#ifdef HAVE_KERNEL_OPLOCKS_LINUX - output(screen," HAVE_KERNEL_OPLOCKS_LINUX\n"); -#endif -#ifdef HAVE_KERNEL_CHANGE_NOTIFY - output(screen," HAVE_KERNEL_CHANGE_NOTIFY\n"); -#endif -#ifdef HAVE_KERNEL_SHARE_MODES - output(screen," HAVE_KERNEL_SHARE_MODES\n"); -#endif -#ifdef HAVE_KERNEL_OPLOCKS_IRIX - output(screen," HAVE_KERNEL_OPLOCKS_IRIX\n"); -#endif -#ifdef HAVE_IRIX_SPECIFIC_CAPABILITIES - output(screen," HAVE_IRIX_SPECIFIC_CAPABILITIES\n"); -#endif -#ifdef HAVE_INT16_FROM_RPC_RPC_H - output(screen," HAVE_INT16_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_UINT16_FROM_RPC_RPC_H - output(screen," HAVE_UINT16_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_INT32_FROM_RPC_RPC_H - output(screen," HAVE_INT16_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_UINT32_FROM_RPC_RPC_H - output(screen," HAVE_UINT32_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_RPC_AUTH_ERROR_CONFLICT - output(screen," HAVE_RPC_AUTH_ERROR_CONFLICT\n"); -#endif -#ifdef HAVE_FTRUNCATE_EXTEND - output(screen," HAVE_FTRUNCATE_EXTEND\n"); -#endif -#ifdef HAVE_WORKING_AF_LOCAL - output(screen," HAVE_WORKING_AF_LOCAL\n"); -#endif -#ifdef HAVE_BROKEN_GETGROUPS - output(screen," HAVE_BROKEN_GETGROUPS\n"); -#endif -#ifdef REPLACE_GETPASS - output(screen," REPLACE_GETPASS\n"); -#endif -#ifdef REPLACE_INET_NTOA - output(screen," REPLACE_INET_NTOA\n"); -#endif -#ifdef HAVE_SECURE_MKSTEMP - output(screen," HAVE_SECURE_MKSTEMP\n"); -#endif -#ifdef SYSCONF_SC_NGROUPS_MAX - output(screen," SYSCONF_SC_NGROUPS_MAX\n"); -#endif -#ifdef HAVE_IFACE_AIX - output(screen," HAVE_IFACE_AIX\n"); -#endif -#ifdef HAVE_IFACE_IFCONF - output(screen," HAVE_IFACE_IFCONF\n"); -#endif -#ifdef HAVE_IFACE_IFREQ - output(screen," HAVE_IFACE_IFREQ\n"); -#endif -#ifdef USE_SETRESUID - output(screen," USE_SETRESUID\n"); -#endif -#ifdef USE_SETRESGID - output(screen," USE_SETREUID\n"); -#endif -#ifdef USE_SETEUID - output(screen," USE_SETEUID\n"); -#endif -#ifdef USE_SETUIDX - output(screen," USE_SETUIDX\n"); -#endif -#ifdef HAVE_MMAP - output(screen," HAVE_MMAP\n"); -#endif -#ifdef MMAP_BLACKLIST - output(screen," MMAP_BLACKLIST\n"); -#endif -#ifdef FTRUNCATE_NEEDS_ROOT - output(screen," FTRUNCATE_NEEDS_ROOT\n"); -#endif -#ifdef HAVE_FCNTL_LOCK - output(screen," HAVE_FCNTL_LOCK\n"); -#endif -#ifdef HAVE_BROKEN_FCNTL64_LOCKS - output(screen," HAVE_BROKEN_FCNTL64_LOCKS\n"); -#endif -#ifdef HAVE_STRUCT_FLOCK64 - output(screen," HAVE_STRUCT_FLOCK64\n"); -#endif -#ifdef BROKEN_NISPLUS_INCLUDE_FILES - output(screen," BROKEN_NISPLUS_INCLUDE_FILES\n"); -#endif -#ifdef HAVE_LIBPAM - output(screen," HAVE_LIBPAM\n"); -#endif -#ifdef STAT_STATVFS64 - output(screen," STAT_STATVFS64\n"); -#endif -#ifdef STAT_STATVFS - output(screen," STAT_STATVFS\n"); -#endif -#ifdef STAT_STATFS3_OSF1 - output(screen," STAT_STATFS3_OSF1\n"); -#endif -#ifdef STAT_STATFS2_BSIZE - output(screen," STAT_STATFS2_BSIZE\n"); -#endif -#ifdef STAT_STATFS4 - output(screen," STAT_STATFS4\n"); -#endif -#ifdef STAT_STATFS2_FSIZE - output(screen," STAT_STATFS2_FSIZE\n"); -#endif -#ifdef STAT_STATFS2_FS_DATA - output(screen," STAT_STATFS2_FS_DATA\n"); -#endif -#ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT - output(screen," HAVE_EXPLICIT_LARGEFILE_SUPPORT\n"); -#endif - -#ifdef WITH_UTMP - /* Output UTMP Stuff */ - output(screen,"\nUTMP Related:\n"); - output(screen," WITH_UTMP\n"); - -#ifdef HAVE_UTIMBUF - output(screen," HAVE_UTIMBUF\n"); -#endif -#ifdef HAVE_UT_UT_NAME - output(screen," HAVE_UT_UT_NAME\n"); -#endif -#ifdef HAVE_UT_UT_USER - output(screen," HAVE_UT_UT_USER\n"); -#endif -#ifdef HAVE_UT_UT_ID - output(screen," HAVE_UT_UT_ID\n"); -#endif -#ifdef HAVE_UT_UT_HOST - output(screen," HAVE_UT_UT_HOST\n"); -#endif -#ifdef HAVE_UT_UT_TIME - output(screen," HAVE_UT_UT_TIME\n"); -#endif -#ifdef HAVE_UT_UT_TV - output(screen," HAVE_UT_UT_TV\n"); -#endif -#ifdef HAVE_UT_UT_TYPE - output(screen," HAVE_UT_UT_TYPE\n"); -#endif -#ifdef HAVE_UT_UT_PID - output(screen," HAVE_UT_UT_PID\n"); -#endif -#ifdef HAVE_UT_UT_EXIT - output(screen," HAVE_UT_UT_EXIT\n"); -#endif -#ifdef HAVE_UT_UT_ADDR - output(screen," HAVE_UT_UT_ADDR\n"); -#endif -#ifdef PUTUTLINE_RETURNS_UTMP - output(screen," PUTUTLINE_RETURNS_UTMP\n"); -#endif -#ifdef HAVE_UX_UT_SYSLEN - output(screen," HAVE_UX_UT_SYSLEN\n"); -#endif -#endif /* WITH_UTMP */ - - /* Output Build OS */ - output(screen,"\nBuilt for host os:\n"); -#ifdef LINUX - output(screen," LINUX\n"); -#endif -#ifdef SUNOS5 - output(screen," SUNOS5\n"); -#endif -#ifdef SUNOS4 - output(screen," SUNOS4\n"); -#endif - /* BSD Isn't Defined in the configure script, but there is something about it in include/config.h.in (and I guess acconfig.h) */ -#ifdef BSD - output(screen," BSD\n"); -#endif -#ifdef IRIX - output(screen," IRIX\n"); -#endif -#ifdef IRIX6 - output(screen," IRIX6\n"); -#endif -#ifdef AIX - output(screen," AIX\n"); -#endif -#ifdef HPUX - output(screen," HPUX\n"); -#endif -#ifdef QNX - output(screen," QNX\n"); -#endif -#ifdef OSF1 - output(screen," OSF1\n"); -#endif -#ifdef SCO - output(screen," SCO\n"); -#endif -#ifdef UNIXWARE - output(screen," UNIXWARE\n"); -#endif -#ifdef NEXT2 - output(screen," NEXT2\n"); -#endif -#ifdef RELIANTUNIX - output(screen," RELIANTUNIX\n"); -#endif - - /* Output the sizes of the various types */ - output(screen,"\nType sizes:\n"); - output(screen," sizeof(char): %d\n",sizeof(char)); - output(screen," sizeof(int): %d\n",sizeof(int)); - output(screen," sizeof(long): %d\n",sizeof(long)); - output(screen," sizeof(uint8): %d\n",sizeof(uint8)); - output(screen," sizeof(uint16): %d\n",sizeof(uint16)); - output(screen," sizeof(uint32): %d\n",sizeof(uint32)); - output(screen," sizeof(short): %d\n",sizeof(short)); - output(screen," sizeof(void*): %d\n",sizeof(void*)); - - output(screen,"\nBuiltin modules:\n"); - output(screen,"%s\n", STRING_STATIC_MODULES); -} - - - -- cgit From 29133d967761908a0f1492c1b907350a076f4a01 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 24 Apr 2003 05:43:45 +0000 Subject: This is really trying to be a StrnCpy (most names will overflow the 10 char limit) (This used to be commit 0e04761abe375bfea48fa2c9ba9e1dc0d56d39f7) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9e49a0bc22..5e4f3caca7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -73,7 +73,7 @@ static void check_for_pipe(char *fname) { /* special case of pipe opens */ char s[10]; - safe_strcpy(s,fname,sizeof(s)-1); + StrnCpy(s,fname,sizeof(s)-1); strlower(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); -- cgit From 596de71fc60b622d7a9d5e12baf234db0bf22499 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 24 Apr 2003 09:52:29 +0000 Subject: When possible, store the IP address of the connecting client, not just the hostname. This makes 'last -i' show the IP. Thanks to Philip Anderson for the idea. Andrew Bartlett (This used to be commit 107731c080da1e3e4e13e966f8b79bfd2692a952) --- source3/smbd/session.c | 11 ++++++++++- source3/smbd/utmp.c | 10 +++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 54b7a24b07..2478b34d6e 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -33,6 +33,8 @@ BOOL session_claim(user_struct *vuser) { int i = 0; TDB_DATA data; + struct sockaddr sa; + struct in_addr *client_ip; struct sessionid sessionid; uint32 pid = (uint32)sys_getpid(); TDB_DATA key; @@ -117,6 +119,8 @@ BOOL session_claim(user_struct *vuser) fstrcpy(sessionid.remote_machine, get_remote_machine_name()); fstrcpy(sessionid.ip_addr, client_addr()); + client_ip = client_inaddr(&sa); + if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", sessionid.username, sessionid.id_str)); @@ -136,6 +140,7 @@ BOOL session_claim(user_struct *vuser) #if WITH_UTMP if (lp_utmp()) { sys_utmp_claim(sessionid.username, sessionid.hostname, + client_ip, sessionid.id_str, sessionid.id_num); } #endif @@ -153,7 +158,8 @@ void session_yield(user_struct *vuser) { TDB_DATA dbuf; struct sessionid sessionid; - TDB_DATA key; + struct in_addr client_ip; + TDB_DATA key; if (!tdb) return; @@ -171,11 +177,14 @@ void session_yield(user_struct *vuser) memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); + inet_pton(AF_INET, sessionid.ip_addr, &client_ip); + SAFE_FREE(dbuf.dptr); #if WITH_UTMP if (lp_utmp()) { sys_utmp_yield(sessionid.username, sessionid.hostname, + &client_ip, sessionid.id_str, sessionid.id_num); } #endif diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 6c12cfac62..84ec364654 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -484,6 +484,7 @@ static int ut_id_encode(int i, char *fourbyte) */ static BOOL sys_utmp_fill(struct utmp *u, const char *username, const char *hostname, + struct in_addr *ipaddr, const char *id_str, int id_num) { struct timeval timeval; @@ -538,8 +539,9 @@ static BOOL sys_utmp_fill(struct utmp *u, #if defined(HAVE_UT_UT_HOST) utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host)); #endif - #if defined(HAVE_UT_UT_ADDR) + if (ipaddr) + u->ut_addr = ipaddr->s_addr; /* * "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20. * Volunteer to implement, please ... @@ -561,6 +563,7 @@ static BOOL sys_utmp_fill(struct utmp *u, ****************************************************************************/ void sys_utmp_yield(const char *username, const char *hostname, + struct in_addr *ipaddr, const char *id_str, int id_num) { struct utmp u; @@ -576,7 +579,7 @@ void sys_utmp_yield(const char *username, const char *hostname, u.ut_type = DEAD_PROCESS; #endif - if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return; + if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return; sys_utmp_update(&u, NULL, False); } @@ -586,6 +589,7 @@ void sys_utmp_yield(const char *username, const char *hostname, ****************************************************************************/ void sys_utmp_claim(const char *username, const char *hostname, + struct in_addr *ipaddr, const char *id_str, int id_num) { struct utmp u; @@ -596,7 +600,7 @@ void sys_utmp_claim(const char *username, const char *hostname, u.ut_type = USER_PROCESS; #endif - if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return; + if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return; sys_utmp_update(&u, hostname, True); } -- cgit From f870072e5c6f0224ea7994387582373645c5ed86 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 24 Apr 2003 18:58:26 +0000 Subject: Fix length in findfirst2 responses, fix os/2 clients (This used to be commit c12feff680b183a22d933bab65b5c095c0548e7e) --- source3/smbd/trans2.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7b8b7e3a4f..0bfb145c10 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -626,7 +626,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, nameptr = p; p += align_string(outbuf, p, 0); len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - SCVAL(nameptr, -1, len); + if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) + SCVAL(nameptr, -1, len-2); + else + SCVAL(nameptr, -1, len-1); p += len; break; @@ -644,10 +647,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,l2_cbList,0); /* No extended attributes */ p += l2_achName; nameptr = p; - len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN); - SCVAL(p, -1, len); + p += align_string(outbuf, p, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) + SCVAL(nameptr, -1, len-2); + else + SCVAL(nameptr, -1, len-1); p += len; - *p++ = 0; /* craig from unisys pointed out we need this */ break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: -- cgit From 4121d1611da65e13e0285a8714f21d6d6be2d4d7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 28 Apr 2003 09:19:09 +0000 Subject: inet_pton isn't portable, so use interpret_addr2. (This used to be commit 04d27381325561038bee1c27f10c748b9aaf447d) --- source3/smbd/session.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 2478b34d6e..ac06b9872d 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -158,7 +158,7 @@ void session_yield(user_struct *vuser) { TDB_DATA dbuf; struct sessionid sessionid; - struct in_addr client_ip; + struct in_addr *client_ip; TDB_DATA key; if (!tdb) return; @@ -177,14 +177,14 @@ void session_yield(user_struct *vuser) memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); - inet_pton(AF_INET, sessionid.ip_addr, &client_ip); + client_ip = interpret_addr2(sessionid.ip_addr); SAFE_FREE(dbuf.dptr); #if WITH_UTMP if (lp_utmp()) { sys_utmp_yield(sessionid.username, sessionid.hostname, - &client_ip, + client_ip, sessionid.id_str, sessionid.id_num); } #endif -- cgit From 17a3acafa89bfc6090b0767d05a00a7505003fcc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 28 Apr 2003 17:48:48 +0000 Subject: Use NTSTATUS as return value for smb_register_*() functions and init_module() function. Patch by metze with some minor modifications. (This used to be commit bc4b51bcb2daa7271c884cb83bf8bdba6d3a9b6d) --- source3/smbd/vfs.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 75bcb09917..e33a8ccbe7 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -153,29 +153,30 @@ static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) return NULL; } -BOOL smb_register_vfs(const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *), int version) +NTSTATUS smb_register_vfs(uint16 version, const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *)) { struct vfs_init_function_entry *entry = backends; - + if ((version < SMB_VFS_INTERFACE_CASCADED)) { DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", version, SMB_VFS_INTERFACE_VERSION )); - return False; + return NT_STATUS_OBJECT_TYPE_MISMATCH; } if ((version < SMB_VFS_INTERFACE_VERSION)) { DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", version, SMB_VFS_INTERFACE_VERSION, version )); - return False; + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !init) { + return NT_STATUS_INVALID_PARAMETER; } - while(entry) { - if (strequal(entry->name, name)) { + if (vfs_find_backend_entry(name)) { DEBUG(0,("VFS module %s already loaded!\n", name)); - return False; - } - entry = entry->next; + return NT_STATUS_OBJECT_NAME_COLLISION; } entry = smb_xmalloc(sizeof(struct vfs_init_function_entry)); @@ -184,7 +185,7 @@ BOOL smb_register_vfs(const char *name, vfs_op_tuple *(*init)(const struct vfs_o DLIST_ADD(backends, entry); DEBUG(5, ("Successfully added vfs backend '%s'\n", name)); - return True; + return NT_STATUS_OK; } /**************************************************************************** @@ -267,7 +268,7 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) /* First, try to load the module with the new module system */ if((entry = vfs_find_backend_entry(vfs_object)) || - (smb_probe_module("vfs", vfs_object) && + (NT_STATUS_IS_OK(smb_probe_module("vfs", vfs_object)) && (entry = vfs_find_backend_entry(vfs_object)))) { DEBUG(3,("Successfully loaded %s with the new modules system\n", vfs_object)); -- cgit From ad9a3848a8288803fa752b86fd2aea1a46cf4a7d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 29 Apr 2003 13:28:48 +0000 Subject: add version back to lanman string in sessetup reply (This used to be commit dade462a168abe721c70022546109074961969b6) --- source3/smbd/sesssetup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 25f9d424ab..3fa3fa411f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -60,9 +60,13 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv static void add_signature(char *outbuf) { char *p; + fstring lanman; + + snprintf( lanman, sizeof(lanman), "Samba %s", VERSION ); + p = smb_buf(outbuf); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); set_message_end(outbuf,p); } -- cgit From d2373e7dce03a933be465cfd006c20d2bcc6e758 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 30 Apr 2003 23:06:44 +0000 Subject: Make the version numbers ints (patch from metze) (This used to be commit dbe36b4c43dceddea9f14161c6cf7b34709287c8) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index e33a8ccbe7..5fcf9a575e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -153,7 +153,7 @@ static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) return NULL; } -NTSTATUS smb_register_vfs(uint16 version, const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *)) +NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *)) { struct vfs_init_function_entry *entry = backends; -- cgit From bac83636a5993dbcd1c0beefd628044771603523 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 May 2003 11:02:54 +0000 Subject: Fix disk quotas support on HP/UX (patch by David Nixon) (This used to be commit a2c315dea6910e3f83ba2e9bad4312cf35f608da) --- source3/smbd/quotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index c2f001423e..5b843bd09a 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -898,8 +898,8 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0)) #else if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) - return (False); #endif /* ifdef HPUX */ + return (False); #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */ -- cgit From 7ce38082f3dcf01dd9818757f32658adf609d830 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 May 2003 17:45:38 +0000 Subject: Fix for bugid 51 from Dragan Krnic. Jeremy. (This used to be commit a2af45154d0e1bb76e78fbde1572d4fcd1ba0da2) --- source3/smbd/open.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5e4f3caca7..906c4b40d9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -168,17 +168,17 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); - - /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) - inherit_access_acl(conn, fname, mode); - if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", fname,strerror(errno),local_flags,flags)); check_for_pipe(fname); return False; } + + /* Inherit the ACL if the file was created. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) + inherit_access_acl(conn, fname, mode); + } else fsp->fd = -1; /* What we used to call a stat open. */ -- cgit From 269a48fedc03f8351384c7d1eeb89d7fbc4e084e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 May 2003 18:11:24 +0000 Subject: Fix uninitialized blobs reported by Luke Howard. Jeremy. (This used to be commit 8dcc00899977a126d5782e44bdae74175ecc0d93) --- source3/smbd/sesssetup.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3fa3fa411f..a9842424a5 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -153,6 +153,12 @@ static int reply_spnego_kerberos(connection_struct *conn, uint8 tok_id[2]; BOOL foreign = False; + ZERO_STRUCT(ticket); + ZERO_STRUCT(auth_data); + ZERO_STRUCT(ap_rep); + ZERO_STRUCT(ap_rep_wrapped); + ZERO_STRUCT(response); + if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -- cgit From 06551c644c75ab2aa14a3cc3c4afbcbb08369133 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 6 May 2003 02:34:59 +0000 Subject: Patch from metze to add exit and interval events. Useful for modules (This used to be commit 3033a63cefb5f28d4460885f7f4e4ecaed95443c) --- source3/smbd/process.c | 7 +++++++ source3/smbd/server.c | 3 +++ 2 files changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 54fd4a90d9..18acb35f7a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1114,6 +1114,9 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t /* become root again if waiting */ change_to_root_user(); + /* run all registered idle events */ + smb_run_idle_events(t); + /* check if we need to reload services */ check_reload(t); @@ -1277,6 +1280,10 @@ void smbd_process(void) lp_talloc_free(); main_loop_talloc_free(); + /* run all registered idle events */ + smb_run_idle_events(time(NULL)); + + /* Did someone ask for immediate checks on things like blocking locks ? */ if (select_timeout == 0) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ffffa3cce3..d46be42eba 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -567,6 +567,9 @@ void exit_server(const char *reason) print_notify_send_messages(3); /* 3 second timeout. */ + /* run all registered exit events */ + smb_run_exit_events(); + /* delete our entry in the connections database. */ yield_connection(NULL,""); -- cgit From fae80fe1a050b36dbf862ae1ac9170fea247b0a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 May 2003 18:28:24 +0000 Subject: Make fchown, fchmod conditional for systems that don't have them. Jeremy. (This used to be commit cf78b1e7fe72aec72d03c86c46a8ca49df539c11) --- source3/smbd/vfs-wrap.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index bae304096c..491fa70e68 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -298,10 +298,10 @@ int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) { - int result; + int result; struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; - START_PROFILE(syscall_fchmod); + START_PROFILE(syscall_fchmod); /* * We need to do this due to the fact that the default POSIX ACL @@ -319,9 +319,15 @@ int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) errno = saved_errno; } - result = fchmod(fd, mode); - END_PROFILE(syscall_fchmod); - return result; +#if defined(HAVE_FCHMOD) + result = fchmod(fd, mode); +#else + result = -1; + errno = ENOSYS; +#endif + + END_PROFILE(syscall_fchmod); + return result; } int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid) @@ -336,6 +342,7 @@ int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gi int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) { +#ifdef HAVE_FCHOWN int result; START_PROFILE(syscall_fchown); @@ -343,6 +350,10 @@ int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) result = fchown(fd, uid, gid); END_PROFILE(syscall_fchown); return result; +#else + errno = ENOSYS; + return -1; +#endif } int vfswrap_chdir(connection_struct *conn, const char *path) -- cgit From 2746a909b229a6c889ed510defcc53e1b22750c8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 May 2003 22:19:43 +0000 Subject: SMB_QUERY_FILE_ALT_NAME_INFO and SMB_FILE_ALTERNATE_NAME_INFORMATION are identical - noticed by "Dr. Tilo Levante" . Jeremy. (This used to be commit f6d7c279bc8354202f2a9b39fec4a4c8ace368a3) --- source3/smbd/trans2.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0bfb145c10..de598d6713 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1799,6 +1799,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* Get the 8.3 name - used if NT SMB was negotiated. */ case SMB_QUERY_FILE_ALT_NAME_INFO: + case SMB_FILE_ALTERNATE_NAME_INFORMATION: { pstring short_name; @@ -1935,15 +1936,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } #endif - case SMB_FILE_ALTERNATE_NAME_INFORMATION: - /* Last component of pathname. */ - { - size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False); - SIVAL(pdata,0,byte_len); - data_size = 4 + byte_len; - break; - } - #if 0 /* * NT4 server just returns "invalid query" to this - if we try to answer -- cgit From f359b4bdf6134dbd6542a66cecd311cf91d9a074 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 May 2003 01:06:27 +0000 Subject: Fix nasty bug pointed out by samba-technical poster. If name is mangled then we weren't always correctly detecting that it had a valid stat struct and so might now return a 'file existed'. Finally realized this when installing the W2K resource kit as a test case. Jeremy. (This used to be commit d48069ccd8351e4bff097a7f7500c738870a413d) --- source3/smbd/filename.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ad707a2b9d..9dd1523c73 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -248,6 +248,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(False); } + if (!end) { + /* + * We just scanned for, and found the end of the path. + * We must return the valid stat struct. + * JRA. + */ + + *pst = st; + } + } else { pstring rest; @@ -373,7 +383,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen /* * If we ended up resolving the entire path then return a valid - * stat struct if we got one. + * stat struct if we got one. Note this doesn't catch mangled paths, + * but the check in the for loop above will do that. JRA. */ if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) -- cgit From 2d7a8480cf3e58d10c9a11e161a8fe6c91a59039 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 May 2003 00:35:38 +0000 Subject: Optimisation. We don't need to do 2 strlen's when we're setting the stat struct in the correct place. Jeremy. (This used to be commit 4cd8b276715f7e019fcee8fc3ebb2855610c4751) --- source3/smbd/filename.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9dd1523c73..b9e33e8f93 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -381,15 +381,6 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if(!component_was_mangled && !name_has_wildcard) stat_cache_add(orig_path, name); - /* - * If we ended up resolving the entire path then return a valid - * stat struct if we got one. Note this doesn't catch mangled paths, - * but the check in the for loop above will do that. JRA. - */ - - if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) - *pst = st; - /* * The name has been resolved. */ -- cgit From c507ebe56741d773bf6e7ad547863a2da1aee687 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 10 May 2003 10:53:48 +0000 Subject: Patch from metze and me that adds dummy smb_register_*() functions so that is now possible to, for example, load a module which contains an auth method into a binary without the auth/ subsystem built in. (This used to be commit 74d9ecfe2dd7364643d32acb62ade957bd71cd0d) --- source3/smbd/server.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d46be42eba..e933c4d3d4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,6 +22,13 @@ #include "includes.h" +#define HAVE_SMB_REGISTER_AUTH +#define HAVE_SMB_REGISTER_PASSDB +#define HAVE_RPC_PIPE_REGISTER_COMMANDS +#define HAVE_SMB_REGISTER_VFS +#include "module_dummy.h" + + int am_parent = 1; /* the last message the was processed */ -- cgit From 0914e541f5480834c1b0ddc98b5f71f7f7abf9cb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 10 May 2003 11:49:51 +0000 Subject: Reverse previous patch from Stefan and me after comments by Andrew Bartlett (This used to be commit d817eaf0ecca2d878ab1ffcf7a747a02d71c811e) --- source3/smbd/server.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e933c4d3d4..d46be42eba 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,13 +22,6 @@ #include "includes.h" -#define HAVE_SMB_REGISTER_AUTH -#define HAVE_SMB_REGISTER_PASSDB -#define HAVE_RPC_PIPE_REGISTER_COMMANDS -#define HAVE_SMB_REGISTER_VFS -#include "module_dummy.h" - - int am_parent = 1; /* the last message the was processed */ -- cgit From e7c8c15888454043c73967635deb4d3419a489e9 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sun, 11 May 2003 23:34:18 +0000 Subject: Fix VFS layer: 1. Finally work with cascaded modules with private data storage per module 2. Convert VFS API to macro calls to simplify cascading 3. Add quota support to VFS layer (prepare to NT quota support) Patch by Stefan (metze) Metzemacher, with review of Jelmer and me Tested in past few weeks. Documentation to new VFS API for third-party developers to follow (This used to be commit 91984ef5caa2d13c5d52e1f535bd3bbbae1ec978) --- source3/smbd/close.c | 2 +- source3/smbd/conn.c | 39 ++-- source3/smbd/dir.c | 18 +- source3/smbd/dosmode.c | 14 +- source3/smbd/fileio.c | 14 +- source3/smbd/filename.c | 8 +- source3/smbd/notify_hash.c | 4 +- source3/smbd/nttrans.c | 4 +- source3/smbd/open.c | 26 +-- source3/smbd/posix_acls.c | 134 +++++------ source3/smbd/reply.c | 56 ++--- source3/smbd/service.c | 23 +- source3/smbd/statcache.c | 2 +- source3/smbd/trans2.c | 56 ++--- source3/smbd/vfs-wrap.c | 176 +++++++------- source3/smbd/vfs.c | 566 +++++++++++++++++---------------------------- 16 files changed, 500 insertions(+), 642 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 5cca85500f..a5d74cedb1 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -185,7 +185,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (normal_close && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(fsp->conn->vfs_ops.unlink(conn,fsp->fsp_name) != 0) { + if(VFS_UNLINK(conn,fsp->fsp_name) != 0) { /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index b6c7aa1076..eb2d2bbcbf 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -93,6 +93,7 @@ thinking the server is still available. ****************************************************************************/ connection_struct *conn_new(void) { + TALLOC_CTX *mem_ctx; connection_struct *conn; int i; @@ -103,10 +104,16 @@ connection_struct *conn_new(void) return NULL; } - conn = (connection_struct *)malloc(sizeof(*conn)); - if (!conn) return NULL; + if ((mem_ctx=talloc_init("connection_struct"))==NULL) { + DEBUG(0,("talloc_init(connection_struct) failed!\n")); + return NULL; + } - ZERO_STRUCTP(conn); + if ((conn=(connection_struct *)talloc_zero(mem_ctx, sizeof(*conn)))==NULL) { + DEBUG(0,("talloc_zero() failed!\n")); + return NULL; + } + conn->mem_ctx = mem_ctx; conn->cnum = i; bitmap_set(bmap, i); @@ -195,27 +202,16 @@ void conn_clear_vuid_cache(uint16 vuid) void conn_free(connection_struct *conn) { - smb_vfs_handle_struct *handle, *thandle; - void (*done_fptr)(connection_struct *the_conn); + vfs_handle_struct *handle = NULL, *thandle = NULL; + TALLOC_CTX *mem_ctx = NULL; /* Free vfs_connection_struct */ - handle = conn->vfs_private; + handle = conn->vfs_handles; while(handle) { - /* Only call dlclose for the old modules */ - if (handle->handle) { - /* Close dlopen() handle */ - done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done"); - - if (done_fptr == NULL) { - DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle)); - } else { - done_fptr(conn); - } - sys_dlclose(handle->handle); - } - DLIST_REMOVE(conn->vfs_private, handle); + DLIST_REMOVE(conn->vfs_handles, handle); thandle = handle->next; - SAFE_FREE(handle); + if (handle->free_data) + handle->free_data(&handle->data); handle = thandle; } @@ -238,8 +234,9 @@ void conn_free(connection_struct *conn) bitmap_clear(bmap, conn->cnum); num_open--; + mem_ctx = conn->mem_ctx; ZERO_STRUCTP(conn); - SAFE_FREE(conn); + talloc_destroy(mem_ctx); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 6cf56fd373..48ddf86837 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -643,7 +643,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0) { + if (VFS_STAT(conn, pathreal, &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; } @@ -700,7 +700,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (VFS_STAT(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ @@ -715,7 +715,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + sd_size = VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); close_file(fsp, True); /* No access if SD get failed. */ @@ -753,7 +753,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (VFS_STAT(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ @@ -768,7 +768,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + sd_size = VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); close_file(fsp, False); /* No access if SD get failed. */ @@ -794,7 +794,7 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (VFS_STAT(conn, name, pst) != 0)) return True; if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) @@ -811,7 +811,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) { Dir *dirp; const char *n; - DIR *p = conn->vfs_ops.opendir(conn,name); + DIR *p = VFS_OPENDIR(conn,name); int used=0; if (!p) @@ -819,7 +819,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { DEBUG(0,("Out of memory in OpenDir\n")); - conn->vfs_ops.closedir(conn,p); + VFS_CLOSEDIR(conn,p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; @@ -912,7 +912,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp->numentries++; } - conn->vfs_ops.closedir(conn,p); + VFS_CLOSEDIR(conn,p); return((void *)dirp); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 6c21dc04d0..6365db8f1e 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -56,7 +56,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) dname = parent_dirname(fname); DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (vfs_stat(conn,dname,&sbuf) != 0) { + if (VFS_STAT(conn,dname,&sbuf) != 0) { DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); return(0); /* *** shouldn't happen! *** */ } @@ -191,7 +191,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST if (!st) { st = &st1; - if (vfs_stat(conn,fname,st)) + if (VFS_STAT(conn,fname,st)) return(-1); } @@ -235,7 +235,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if ((ret = vfs_chmod(conn,fname,unixmode)) == 0) + if ((ret = VFS_CHMOD(conn,fname,unixmode)) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -262,7 +262,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST if (!fsp) return -1; become_root(); - ret = conn->vfs_ops.fchmod(fsp, fsp->fd, unixmode); + ret = VFS_FCHMOD(fsp, fsp->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); } @@ -283,7 +283,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(conn->vfs_ops.utime(conn,fname, times) == 0) + if(VFS_UTIME(conn,fname, times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -298,7 +298,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(vfs_stat(conn,fname,&sb) != 0) + if(VFS_STAT(conn,fname,&sb) != 0) return -1; /* Check if we have write access. */ @@ -311,7 +311,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = conn->vfs_ops.utime(conn,fname, times); + ret = VFS_UTIME(conn,fname, times); unbecome_root(); } } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index b612b1a451..5021f54fb4 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -32,7 +32,7 @@ static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { SMB_OFF_T seek_ret; - seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos,SEEK_SET); + seek_ret = VFS_LSEEK(fsp,fsp->fd,pos,SEEK_SET); if(seek_ret == -1) { DEBUG(0,("seek_file: (%s) sys_lseek failed. Error was %s\n", @@ -101,7 +101,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #ifdef DMF_FIX int numretries = 3; tryagain: - readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); + readret = VFS_READ(fsp,fsp->fd,data,n); if (readret == -1) { if ((errno == EAGAIN) && numretries) { DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); @@ -112,7 +112,7 @@ tryagain: return -1; } #else /* NO DMF fix. */ - readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); + readret = VFS_READ(fsp,fsp->fd,data,n); if (readret == -1) return -1; #endif @@ -181,7 +181,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) SMB_STRUCT_STAT st; fsp->modified = True; - if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { + if (VFS_FSTAT(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); fsp->size = (SMB_BIG_UINT)st.st_size; if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) @@ -760,7 +760,7 @@ void sync_file(connection_struct *conn, files_struct *fsp) { if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { flush_write_cache(fsp, SYNC_FLUSH); - conn->vfs_ops.fsync(fsp,fsp->fd); + VFS_FSYNC(fsp,fsp->fd); } } @@ -772,7 +772,7 @@ void sync_file(connection_struct *conn, files_struct *fsp) int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) { if (fsp->fd == -1) - return vfs_stat(fsp->conn, fsp->fsp_name, pst); + return VFS_STAT(fsp->conn, fsp->fsp_name, pst); else - return vfs_fstat(fsp,fsp->fd, pst); + return VFS_FSTAT(fsp,fsp->fd, pst); } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b9e33e8f93..6622a6ba63 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -178,7 +178,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * stat the name - if it exists then we are all done! */ - if (vfs_stat(conn,name,&st) == 0) { + if (VFS_STAT(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; @@ -234,7 +234,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Check if the name exists up to this point. */ - if (vfs_stat(conn,name, &st) == 0) { + if (VFS_STAT(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -342,7 +342,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * JRA. */ - if (vfs_stat(conn,name, &st) == 0) { + if (VFS_STAT(conn,name, &st) == 0) { *pst = st; } else { ZERO_STRUCT(st); @@ -418,7 +418,7 @@ BOOL check_name(pstring name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && + if ( (VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index d8b35462ac..913a4973f8 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -48,7 +48,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, ZERO_STRUCTP(data); - if(vfs_stat(conn,path, &st) == -1) + if(VFS_STAT(conn,path, &st) == -1) return False; data->modify_time = st.st_mtime; @@ -100,7 +100,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, /* * Do the stat - but ignore errors. */ - vfs_stat(conn,full_name, &st); + VFS_STAT(conn,full_name, &st); /* * Always sum the times. diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9f7fabb75e..38de5586ea 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1032,7 +1032,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu if (psd->off_dacl==0) security_info_sent &= ~DACL_SECURITY_INFORMATION; - ret = fsp->conn->vfs_ops.fset_nt_acl( fsp, fsp->fd, security_info_sent, psd); + ret = VFS_FSET_NT_ACL( fsp, fsp->fd, security_info_sent, psd); if (!ret) { talloc_destroy(mem_ctx); @@ -1561,7 +1561,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if (!lp_nt_acl_support(SNUM(conn))) sd_size = get_null_nt_acl(mem_ctx, &psd); else - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + sd_size = VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); if (sd_size == 0) { talloc_destroy(mem_ctx); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 906c4b40d9..412a0dfc50 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,13 +38,13 @@ static int fd_open(struct connection_struct *conn, char *fname, flags |= O_NOFOLLOW; #endif - fd = conn->vfs_ops.open(conn,fname,flags,mode); + fd = VFS_OPEN(conn,fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr_m(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(conn,fname,flags,mode); + fd = VFS_OPEN(conn,fname,flags,mode); } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, @@ -186,9 +186,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, int ret; if (fsp->fd == -1) - ret = vfs_stat(conn, fname, psbuf); + ret = VFS_STAT(conn, fname, psbuf); else { - ret = vfs_fstat(fsp,fsp->fd,psbuf); + ret = VFS_FSTAT(fsp,fsp->fd,psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); @@ -259,7 +259,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); return -1; } else { - return conn->vfs_ops.ftruncate(fsp,fsp->fd,0); + return VFS_FTRUNCATE(fsp,fsp->fd,0); } } @@ -1071,7 +1071,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* * We are modifing the file after open - update the stat struct.. */ - if ((truncate_unless_locked(conn,fsp) == -1) || (vfs_fstat(fsp,fsp->fd,psbuf)==-1)) { + if ((truncate_unless_locked(conn,fsp) == -1) || (VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1146,11 +1146,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * selected. */ - if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { + if (!file_existed && !def_acl && (conn->vfs.ops.fchmod_acl != NULL)) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + if (VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ } else if (new_mode) { @@ -1159,9 +1159,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* Attributes need changing. File already existed. */ - if (conn->vfs_ops.fchmod_acl != NULL) { + if (conn->vfs.ops.fchmod_acl != NULL) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - ret = conn->vfs_ops.fchmod_acl(fsp, fsp->fd, new_mode); + ret = VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ @@ -1172,7 +1172,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } - if ((ret == -1) && (conn->vfs_ops.fchmod(fsp, fsp->fd, new_mode) == -1)) + if ((ret == -1) && (VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", fname, (int)new_mode)); } @@ -1278,14 +1278,14 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } - if(vfs_mkdir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); return NULL; } - if(vfs_stat(conn,fname, psbuf) != 0) { + if(VFS_STAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a38acc437d..34c33af473 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -158,9 +158,9 @@ static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET { mode_t ret = 0; - ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0); - ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0); - ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); + ret |= (VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0); + ret |= (VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0); + ret |= (VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); return ret; } @@ -190,18 +190,18 @@ static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset) { - if (conn->vfs_ops.sys_acl_clear_perms(conn, *p_permset) == -1) + if (VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1) return -1; if (mode & S_IRUSR) { - if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_READ) == -1) + if (VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) return -1; } if (mode & S_IWUSR) { - if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_WRITE) == -1) + if (VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) return -1; } if (mode & S_IXUSR) { - if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_EXECUTE) == -1) + if (VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) return -1; } return 0; @@ -649,7 +649,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, /* * When setting ACLs and missing one out of SMB_ACL_USER_OBJ, * SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER, try to retrieve current - * values. For user and other a simple vfs_stat would do, but + * values. For user and other a simple VFS_STAT would do, but * we would get mask instead of group. Let's do it via ACL. */ @@ -659,13 +659,13 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, int entry_id = SMB_ACL_FIRST_ENTRY; if(fsp->is_directory || fsp->fd == -1) { - current_posix_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); + current_posix_acl = VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); } else { - current_posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fsp->fd); + current_posix_acl = VFS_SYS_ACL_GET_FD(fsp, fsp->fd); } if (current_posix_acl) { - while (conn->vfs_ops.sys_acl_get_entry(conn, current_posix_acl, entry_id, &entry) == 1) { + while (VFS_SYS_ACL_GET_ENTRY(conn, current_posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; @@ -674,10 +674,10 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ - if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) + if (VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) continue; - if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) + if (VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) continue; switch(tagtype) { @@ -695,7 +695,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, break; } } - conn->vfs_ops.sys_acl_free_acl(conn, current_posix_acl); + VFS_SYS_ACL_FREE_ACL(conn, current_posix_acl); } else { DEBUG(10,("ensure_canon_entry_valid: failed to retrieve current ACL of %s\n", fsp->fsp_name)); @@ -1658,7 +1658,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ SMB_ACL_ENTRY_T entry; size_t ace_count; - while ( posix_acl && (conn->vfs_ops.sys_acl_get_entry(conn, posix_acl, entry_id, &entry) == 1)) { + while ( posix_acl && (VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; DOM_SID sid; @@ -1670,10 +1670,10 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ - if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) + if (VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) continue; - if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) + if (VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) continue; /* Decide which SID to use based on the ACL type. */ @@ -1686,7 +1686,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_USER: { - uid_t *puid = (uid_t *)conn->vfs_ops.sys_acl_get_qualifier(conn, entry); + uid_t *puid = (uid_t *)VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (puid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get uid.\n")); continue; @@ -1703,7 +1703,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; - conn->vfs_ops.sys_acl_free_qualifier(conn, (void *)puid,tagtype); + VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); break; } case SMB_ACL_GROUP_OBJ: @@ -1714,7 +1714,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_GROUP: { - gid_t *pgid = (gid_t *)conn->vfs_ops.sys_acl_get_qualifier(conn, entry); + gid_t *pgid = (gid_t *)VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (pgid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get gid.\n")); continue; @@ -1722,7 +1722,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ gid_to_sid( &sid, *pgid); unix_ug.gid = *pgid; owner_type = GID_ACE; - conn->vfs_ops.sys_acl_free_qualifier(conn, (void *)pgid,tagtype); + VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype); break; } case SMB_ACL_MASK: @@ -1807,7 +1807,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau { connection_struct *conn = fsp->conn; BOOL ret = False; - SMB_ACL_T the_acl = conn->vfs_ops.sys_acl_init(conn, (int)count_canon_ace_list(the_ace) + 1); + SMB_ACL_T the_acl = VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1); canon_ace *p_ace; int i; SMB_ACL_ENTRY_T mask_entry; @@ -1865,7 +1865,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Get the entry for this ACE. */ - if (conn->vfs_ops.sys_acl_create_entry(conn, &the_acl, &the_entry) == -1) { + if (VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1891,7 +1891,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * First tell the entry what type of ACE this is. */ - if (conn->vfs_ops.sys_acl_set_tag_type(conn, the_entry, p_ace->type) == -1) { + if (VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1903,7 +1903,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) { - if (conn->vfs_ops.sys_acl_set_qualifier(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { + if (VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1914,7 +1914,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Convert the mode_t perms in the canon_ace to a POSIX permset. */ - if (conn->vfs_ops.sys_acl_get_permset(conn, the_entry, &the_permset) == -1) { + if (VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1930,7 +1930,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * ..and apply them to the entry. */ - if (conn->vfs_ops.sys_acl_set_permset(conn, the_entry, the_permset) == -1) { + if (VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1941,17 +1941,17 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau } if (needs_mask && !got_mask_entry) { - if (conn->vfs_ops.sys_acl_create_entry(conn, &the_acl, &mask_entry) == -1) { + if (VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); goto done; } - if (conn->vfs_ops.sys_acl_set_tag_type(conn, mask_entry, SMB_ACL_MASK) == -1) { + if (VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); goto done; } - if (conn->vfs_ops.sys_acl_get_permset(conn, mask_entry, &mask_permset) == -1) { + if (VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); goto done; } @@ -1961,7 +1961,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } - if (conn->vfs_ops.sys_acl_set_permset(conn, mask_entry, mask_permset) == -1) { + if (VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); goto done; } @@ -1971,7 +1971,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Check if the ACL is valid. */ - if (conn->vfs_ops.sys_acl_valid(conn, the_acl) == -1) { + if (VFS_SYS_ACL_VALID(conn, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", strerror(errno) )); @@ -1983,7 +1983,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if(default_ace || fsp->is_directory || fsp->fd == -1) { - if (conn->vfs_ops.sys_acl_set_file(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { + if (VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2002,7 +2002,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } } else { - if (conn->vfs_ops.sys_acl_set_fd(fsp, fsp->fd, the_acl) == -1) { + if (VFS_SYS_ACL_SET_FD(fsp, fsp->fd, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2026,7 +2026,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau done: if (the_acl != NULL) - conn->vfs_ops.sys_acl_free_acl(conn, the_acl); + VFS_SYS_ACL_FREE_ACL(conn, the_acl); return ret; } @@ -2057,8 +2057,8 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T acl) if (!acl) return NULL; - if (conn->vfs_ops.sys_acl_get_entry(conn, acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { - conn->vfs_ops.sys_acl_free_acl(conn, acl); + if (VFS_SYS_ACL_GET_ENTRY(conn, acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { + VFS_SYS_ACL_FREE_ACL(conn, acl); return NULL; } return acl; @@ -2224,34 +2224,34 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) if(fsp->is_directory || fsp->fd == -1) { /* Get the stat struct for the owner info. */ - if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { + if(VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; } /* * Get the ACL from the path. */ - posix_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); + posix_acl = VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); /* * If it's a directory get the default POSIX ACL. */ if(fsp->is_directory) { - dir_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + dir_acl = VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); dir_acl = free_empty_sys_acl(conn, dir_acl); } } else { /* Get the stat struct for the owner info. */ - if(vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { + if(VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { return 0; } /* * Get the ACL from the fd. */ - posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fsp->fd); + posix_acl = VFS_SYS_ACL_GET_FD(fsp, fsp->fd); } DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", @@ -2479,9 +2479,9 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) done: if (posix_acl) - conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); + VFS_SYS_ACL_FREE_ACL(conn, posix_acl); if (dir_acl) - conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); + VFS_SYS_ACL_FREE_ACL(conn, dir_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); SAFE_FREE(nt_ace_list); @@ -2505,14 +2505,14 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ SMB_STRUCT_STAT st; /* try the direct way first */ - ret = vfs_chown(conn, fname, uid, gid); + ret = VFS_CHOWN(conn, fname, uid, gid); if (ret == 0) return 0; if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) return -1; - if (vfs_stat(conn,fname,&st)) + if (VFS_STAT(conn,fname,&st)) return -1; fsp = open_file_fchmod(conn,fname,&st); @@ -2527,7 +2527,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ become_root(); /* Keep the current file gid the same. */ - ret = vfswrap_fchown(fsp, fsp->fd, uid, (gid_t)-1); + ret = VFS_FCHOWN(fsp, fsp->fd, uid, (gid_t)-1); unbecome_root(); close_file_fchmod(fsp); @@ -2570,10 +2570,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory || fsp->fd == -1) { - if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) + if(VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - if(vfs_fstat(fsp,fsp->fd,&sbuf) != 0) + if(VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) return False; } @@ -2619,7 +2619,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { + if(VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) { return False; } } else { @@ -2627,9 +2627,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) int ret; if(fsp->fd == -1) - ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); + ret = VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf); else - ret = vfs_fstat(fsp,fsp->fd,&sbuf); + ret = VFS_FSTAT(fsp,fsp->fd,&sbuf); if(ret != 0) return False; @@ -2697,7 +2697,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * No default ACL - delete one if it exists. */ - if (conn->vfs_ops.sys_acl_delete_def_file(conn, fsp->fsp_name) == -1) { + if (VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) { DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); @@ -2726,7 +2726,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)posix_perms )); - if(conn->vfs_ops.chmod(conn,fsp->fsp_name, posix_perms) == -1) { + if(VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) { DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); free_canon_ace_list(file_ace_list); @@ -2768,7 +2768,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo SMB_ACL_ENTRY_T entry; int num_entries = 0; - while ( conn->vfs_ops.sys_acl_get_entry(conn, posix_acl, entry_id, &entry) == 1) { + while ( VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; mode_t perms; @@ -2777,10 +2777,10 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo if (entry_id == SMB_ACL_FIRST_ENTRY) entry_id = SMB_ACL_NEXT_ENTRY; - if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) + if (VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) return -1; - if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) + if (VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) return -1; num_entries++; @@ -2811,7 +2811,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo if (map_acl_perms_to_permset(conn, perms, &permset) == -1) return -1; - if (conn->vfs_ops.sys_acl_set_permset(conn, entry, permset) == -1) + if (VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1) return -1; } @@ -2837,17 +2837,17 @@ static int copy_access_acl(connection_struct *conn, const char *from, const char SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = conn->vfs_ops.sys_acl_get_file(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL) + if ((posix_acl = VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = conn->vfs_ops.sys_acl_set_file(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl); + ret = VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl); done: - conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); + VFS_SYS_ACL_FREE_ACL(conn, posix_acl); return ret; } @@ -2889,17 +2889,17 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fd)) == NULL) + if ((posix_acl = VFS_SYS_ACL_GET_FD(fsp, fd)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = conn->vfs_ops.sys_acl_set_fd(fsp, fd, posix_acl); + ret = VFS_SYS_ACL_SET_FD(fsp, fd, posix_acl); done: - conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); + VFS_SYS_ACL_FREE_ACL(conn, posix_acl); return ret; } @@ -2909,14 +2909,14 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { - SMB_ACL_T dir_acl = conn->vfs_ops.sys_acl_get_file( conn, fname, SMB_ACL_TYPE_DEFAULT); + SMB_ACL_T dir_acl = VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); BOOL has_acl = False; SMB_ACL_ENTRY_T entry; - if (dir_acl != NULL && (conn->vfs_ops.sys_acl_get_entry(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) + if (dir_acl != NULL && (VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) has_acl = True; if (dir_acl) - conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); + VFS_SYS_ACL_FREE_ACL(conn, dir_acl); return has_acl; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9577196bfe..49a9b934b0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -399,7 +399,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); if (check_name(name,conn)) { - if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0) + if (VALID_STAT(sbuf) || VFS_STAT(conn,name,&sbuf) == 0) if (!(ok = S_ISDIR(sbuf.st_mode))) errno = ENOTDIR; } @@ -458,7 +458,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) { + if (VALID_STAT(sbuf) || VFS_STAT(conn,fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; mtime = sbuf.st_mtime; @@ -553,7 +553,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz SMB_BIG_UINT dfree,dsize,bsize; START_PROFILE(SMBdskattr); - conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize); + VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -1128,7 +1128,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - vfs_stat(conn,fname,&sbuf); + VFS_STAT(conn,fname,&sbuf); /* Open file in dos compatibility share mode. */ /* We should fail if file does not exist. */ @@ -1227,7 +1227,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) + if (VFS_LSTAT(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND; fmode = dos_mode(conn,fname,&sbuf); @@ -1313,7 +1313,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) error = can_delete(directory,conn,dirtype); if (!NT_STATUS_IS_OK(error)) return error; - if (vfs_unlink(conn,directory) == 0) { + if (VFS_UNLINK(conn,directory) == 0) { count++; } } else { @@ -1343,7 +1343,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype); if (!NT_STATUS_IS_OK(error)) continue; - if (vfs_unlink(conn,fname) == 0) count++; + if (VFS_UNLINK(conn,fname) == 0) count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dirptr); @@ -1429,7 +1429,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st header.length = 4; header.free = NULL; - if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { + if ( VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { /* * Special hack for broken Linux with no 64 bit clean sendfile. If we * return ENOSYS then pretend we just got a normal read. @@ -1554,7 +1554,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (vfs_fstat(fsp,fsp->fd,&st) == 0) + if (VFS_FSTAT(fsp,fsp->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -1723,7 +1723,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length SMB_STRUCT_STAT sbuf; DATA_BLOB header; - if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) + if(VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); if (startpos > sbuf.st_size) @@ -1750,7 +1750,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length header.length = data - outbuf; header.free = NULL; - if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { + if ( VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { /* * Special hack for broken Linux with no 64 bit clean sendfile. If we * return ENOSYS then pretend we just got a normal read. @@ -2262,7 +2262,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int break; } - if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) { + if((res = VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { /* * Check for the special case where a seek before the start * of the file sets the offset to zero. Added in the CIFS spec, @@ -2274,7 +2274,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int if(umode == SEEK_CUR) { - if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) { + if((current_pos = VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) { END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2285,7 +2285,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; - if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) { + if(VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2294,7 +2294,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if(current_pos < 0) - res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET); + res = VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); } if(res == -1) { @@ -2830,7 +2830,7 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory, conn)) - ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret == -1) { NTSTATUS nterr = set_bad_path_error(errno, bad_path); @@ -2901,7 +2901,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) { + if(VFS_LSTAT(conn,fullname, &st) != 0) { ret = True; break; } @@ -2911,11 +2911,11 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) ret = True; break; } - if(vfs_rmdir(conn,fullname) != 0) { + if(VFS_RMDIR(conn,fullname) != 0) { ret = True; break; } - } else if(vfs_unlink(conn,fullname) != 0) { + } else if(VFS_UNLINK(conn,fullname) != 0) { ret = True; break; } @@ -2932,7 +2932,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) { BOOL ok; - ok = (vfs_rmdir(conn,directory) == 0); + ok = (VFS_RMDIR(conn,directory) == 0); if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { /* * Check to see if the only thing in this directory are @@ -2974,21 +2974,21 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) + if(VFS_LSTAT(conn,fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) { if(lp_recursive_veto_delete(SNUM(conn))) { if(recursive_rmdir(conn, fullname) != 0) break; } - if(vfs_rmdir(conn,fullname) != 0) + if(VFS_RMDIR(conn,fullname) != 0) break; - } else if(vfs_unlink(conn,fullname) != 0) + } else if(VFS_UNLINK(conn,fullname) != 0) break; } CloseDir(dirptr); /* Retry the rmdir */ - ok = (vfs_rmdir(conn,directory) == 0); + ok = (VFS_RMDIR(conn,directory) == 0); } else { CloseDir(dirptr); } @@ -3284,7 +3284,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_NAME_COLLISION; } - if(conn->vfs_ops.rename(conn,directory, newname) == 0) { + if(VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); return NT_STATUS_OK; @@ -3351,7 +3351,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", continue; } - if (!conn->vfs_ops.rename(conn,fname,destname)) + if (!VFS_RENAME(conn,fname,destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3445,7 +3445,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!target_is_directory && count) ofun = FILE_EXISTS_OPEN; - if (vfs_stat(conn,dest,&sbuf2) == -1) + if (VFS_STAT(conn,dest,&sbuf2) == -1) ZERO_STRUCTP(&sbuf2); fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), @@ -3457,7 +3457,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) { + if(VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); /* * Stop the copy from occurring. diff --git a/source3/smbd/service.c b/source3/smbd/service.c index cfb5e0e414..0e4c87c7fb 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -704,14 +704,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Invoke VFS make connection hook */ - if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn, lp_servicename(snum), user) < 0) { - DEBUG(0,("make_connection: VFS make connection failed!\n")); - change_to_root_user(); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; - return NULL; - } + if (VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { + DEBUG(0,("make_connection: VFS make connection failed!\n")); + change_to_root_user(); + conn_free(conn); + *status = NT_STATUS_UNSUCCESSFUL; + return NULL; } /* we've finished with the user stuff - go back to root */ @@ -872,13 +870,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) get_remote_machine_name(),conn->client_address, lp_servicename(SNUM(conn)))); - if (conn->vfs_ops.disconnect != NULL) { - - /* Call VFS disconnect hook */ - - conn->vfs_ops.disconnect(conn); - - } + /* Call VFS disconnect hook */ + VFS_DISCONNECT(conn); yield_connection(conn, lp_servicename(SNUM(conn))); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 44bae48990..5c77474fec 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -242,7 +242,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } else { scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); - if(vfs_stat(conn,scp->translated_path, pst) != 0) { + if(VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index de598d6713..c9eef637d9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -549,12 +549,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcat(pathreal,dname); if (INFO_LEVEL_IS_UNIX(info_level)) { - if (vfs_lstat(conn,pathreal,&sbuf) != 0) { + if (VFS_LSTAT(conn,pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n", pathreal,strerror(errno))); continue; } - } else if (vfs_stat(conn,pathreal,&sbuf) != 0) { + } else if (VFS_STAT(conn,pathreal,&sbuf) != 0) { /* Needed to show the msdfs symlinks as * directories */ @@ -1321,7 +1321,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(vfs_stat(conn,".",&st)!=0) { + if(VFS_STAT(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return ERROR_DOS(ERRSRV,ERRinvdevice); } @@ -1338,7 +1338,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); SIVAL(pdata,l1_cSectorUnit,bsize/512); SIVAL(pdata,l1_cUnit,dsize); @@ -1406,7 +1406,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1436,7 +1436,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1605,13 +1605,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ - if (vfs_lstat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno))); + if (VFS_LSTAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } - } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno))); + } else if (!VALID_STAT(sbuf) && VFS_STAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -1624,11 +1624,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_FSP(fsp,conn); pstrcpy(fname, fsp->fsp_name); - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { + if (VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) + if((pos = VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); delete_pending = fsp->delete_on_close; @@ -1655,13 +1655,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ - if (vfs_lstat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno))); + if (VFS_LSTAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } - } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno))); + } else if (!VALID_STAT(sbuf) && VFS_STAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -2054,7 +2054,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, #else return(UNIXERROR(ERRDOS,ERRbadlink)); #endif - len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ + len = VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ if (len == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); buffer[len] = 0; @@ -2178,7 +2178,7 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in pstrcpy(link_dest, "./"); } - if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL) + if (VFS_REALPATH(conn,link_dest,resolved_name) == NULL) return -1; pstrcpy(link_dest, resolved_name); @@ -2269,7 +2269,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, pstrcpy(fname, fsp->fsp_name); fd = fsp->fd; - if (vfs_fstat(fsp,fd,&sbuf) != 0) { + if (VFS_FSTAT(fsp,fd,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -2461,7 +2461,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); ret = vfs_allocate_file_space(new_fsp, allocation_size); - if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) { + if (VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", new_fsp->fnum, strerror(errno))); ret = -1; @@ -2469,7 +2469,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, close_file(new_fsp,True); } else { ret = vfs_allocate_file_space(fsp, allocation_size); - if (vfs_fstat(fsp,fd,&new_sbuf) != 0) { + if (VFS_FSTAT(fsp,fd,&new_sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); ret = -1; @@ -2609,7 +2609,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", 0%o for file %s\n", (double)dev, unixmode, fname )); /* Ok - do the mknod. */ - if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0) + if (VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); inherit_access_acl(conn, fname, unixmode); @@ -2628,7 +2628,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (raw_unixmode != SMB_MODE_NO_CHANGE) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", (unsigned int)unixmode, fname )); - if (vfs_chmod(conn,fname,unixmode) != 0) + if (VFS_CHMOD(conn,fname,unixmode) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2639,7 +2639,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", (unsigned int)set_owner, fname )); - if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0) + if (VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2650,7 +2650,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", (unsigned int)set_owner, fname )); - if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0) + if (VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } break; @@ -2677,7 +2677,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", fname, link_dest )); - if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0) + if (VFS_SYMLINK(conn,link_dest,fname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); @@ -2702,7 +2702,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, link_dest )); - if (conn->vfs_ops.link(conn,link_dest,fname) != 0) + if (VFS_LINK(conn,link_dest,fname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); @@ -2854,7 +2854,7 @@ static int call_trans2mkdir(connection_struct *conn, unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory,conn)) - ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if(ret < 0) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 491fa70e68..4422666006 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -30,18 +30,18 @@ is sure to try and execute them. These stubs are used to prevent this possibility. */ -int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user) +int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user) { return 0; /* Return >= 0 for success */ } -void vfswrap_dummy_disconnect(connection_struct *conn) +void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn) { } /* Disk operations */ -SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, +SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { SMB_BIG_UINT result; @@ -52,7 +52,7 @@ SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL s /* Directory operations */ -DIR *vfswrap_opendir(connection_struct *conn, const char *fname) +DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) { DIR *result; @@ -62,7 +62,7 @@ DIR *vfswrap_opendir(connection_struct *conn, const char *fname) return result; } -struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) +struct dirent *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { struct dirent *result; @@ -72,7 +72,7 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) return result; } -int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) +int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { int result; BOOL has_dacl = False; @@ -93,8 +93,8 @@ int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) * mess up any inherited ACL bits that were set. JRA. */ int saved_errno = errno; /* We may get ENOSYS */ - if (conn->vfs_ops.chmod_acl != NULL) { - if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS)) + if (conn->vfs.ops.chmod_acl != NULL) { + if ((VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) errno = saved_errno; } } @@ -103,7 +103,7 @@ int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) return result; } -int vfswrap_rmdir(connection_struct *conn, const char *path) +int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { int result; @@ -113,7 +113,7 @@ int vfswrap_rmdir(connection_struct *conn, const char *path) return result; } -int vfswrap_closedir(connection_struct *conn, DIR *dirp) +int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { int result; @@ -125,7 +125,7 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) /* File operations */ -int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode) +int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) { int result; @@ -135,7 +135,7 @@ int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t m return result; } -int vfswrap_close(files_struct *fsp, int fd) +int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd) { int result; @@ -146,7 +146,7 @@ int vfswrap_close(files_struct *fsp, int fd) return result; } -ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) +ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n) { ssize_t result; @@ -156,7 +156,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) return result; } -ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) +ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) { ssize_t result; @@ -166,7 +166,7 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) return result; } -SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) +SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) { SMB_OFF_T result = 0; @@ -192,7 +192,7 @@ SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int wh return result; } -ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const DATA_BLOB *hdr, +ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr, SMB_OFF_T offset, size_t n) { ssize_t result; @@ -203,7 +203,7 @@ ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const D return result; } -int vfswrap_rename(connection_struct *conn, const char *old, const char *new) +int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new) { int result; @@ -213,7 +213,7 @@ int vfswrap_rename(connection_struct *conn, const char *old, const char *new) return result; } -int vfswrap_fsync(files_struct *fsp, int fd) +int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) { #ifdef HAVE_FSYNC int result; @@ -228,7 +228,7 @@ int vfswrap_fsync(files_struct *fsp, int fd) #endif } -int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) +int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) { int result; @@ -238,7 +238,7 @@ int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sb return result; } -int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) +int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) { int result; @@ -248,7 +248,7 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) return result; } -int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) +int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { int result; @@ -258,7 +258,7 @@ int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sb return result; } -int vfswrap_unlink(connection_struct *conn, const char *path) +int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) { int result; @@ -268,7 +268,7 @@ int vfswrap_unlink(connection_struct *conn, const char *path) return result; } -int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) +int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { int result; @@ -281,9 +281,9 @@ int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) */ - if (conn->vfs_ops.chmod_acl != NULL) { + if (conn->vfs.ops.chmod_acl != NULL) { int saved_errno = errno; /* We might get ENOSYS */ - if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) { + if ((result = VFS_CHMOD_ACL(conn, path, mode)) == 0) { END_PROFILE(syscall_chmod); return result; } @@ -296,10 +296,10 @@ int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) return result; } -int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) +int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { int result; - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; + struct vfs_ops *vfs_ops = &fsp->conn->vfs; START_PROFILE(syscall_fchmod); @@ -309,9 +309,9 @@ int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) * group owner bits directly. JRA. */ - if (vfs_ops->fchmod_acl != NULL) { + if (vfs_ops->ops.fchmod_acl != NULL) { int saved_errno = errno; /* We might get ENOSYS */ - if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) { + if ((result = VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { END_PROFILE(syscall_chmod); return result; } @@ -330,7 +330,7 @@ int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) return result; } -int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid) +int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) { int result; @@ -340,7 +340,7 @@ int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gi return result; } -int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) +int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid) { #ifdef HAVE_FCHOWN int result; @@ -356,7 +356,7 @@ int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) #endif } -int vfswrap_chdir(connection_struct *conn, const char *path) +int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { int result; @@ -366,7 +366,7 @@ int vfswrap_chdir(connection_struct *conn, const char *path) return result; } -char *vfswrap_getwd(connection_struct *conn, char *path) +char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path) { char *result; @@ -376,7 +376,7 @@ char *vfswrap_getwd(connection_struct *conn, char *path) return result; } -int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times) +int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) { int result; @@ -391,18 +391,17 @@ int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *tim allocate is set. **********************************************************************/ -static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) +static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) { - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; SMB_STRUCT_STAT st; - SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR); + SMB_OFF_T currpos = VFS_LSEEK(fsp, fd, 0, SEEK_CUR); unsigned char zero_space[4096]; SMB_OFF_T space_to_write; if (currpos == -1) return -1; - if (vfs_ops->fstat(fsp, fd, &st) == -1) + if (VFS_FSTAT(fsp, fd, &st) == -1) return -1; space_to_write = len - st.st_size; @@ -420,7 +419,7 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) return sys_ftruncate(fd, len); /* Write out the real space on disk. */ - if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size) + if (VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) return -1; space_to_write = len - st.st_size; @@ -430,7 +429,7 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) SMB_OFF_T retlen; SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); - retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write); + retlen = VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write); if (retlen <= 0) return -1; @@ -438,16 +437,15 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) } /* Seek to where we were */ - if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) + if (VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) return -1; return 0; } -int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) +int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) { int result = -1; - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; SMB_STRUCT_STAT st; char c = 0; SMB_OFF_T currpos; @@ -455,7 +453,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) START_PROFILE(syscall_ftruncate); if (lp_strict_allocate(SNUM(fsp->conn))) { - result = strict_allocate_ftruncate(fsp, fd, len); + result = strict_allocate_ftruncate(handle, fsp, fd, len); END_PROFILE(syscall_ftruncate); return result; } @@ -473,7 +471,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot extend a file with ftruncate. Provide alternate implementation for this */ - currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR); + currpos = VFS_LSEEK(fsp, fd, 0, SEEK_CUR); if (currpos == -1) { goto done; } @@ -482,7 +480,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) size in which case the ftruncate above should have succeeded or shorter, in which case seek to len - 1 and write 1 byte of zero */ - if (vfs_ops->fstat(fsp, fd, &st) == -1) { + if (VFS_FSTAT(fsp, fd, &st) == -1) { goto done; } @@ -503,14 +501,14 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) goto done; } - if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1) + if (VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) goto done; - if (vfs_ops->write(fsp, fd, &c, 1)!=1) + if (VFS_WRITE(fsp, fd, &c, 1)!=1) goto done; /* Seek to where we were */ - if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) + if (VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) goto done; result = 0; @@ -520,7 +518,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) return result; } -BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { BOOL result; @@ -531,7 +529,7 @@ BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T return result; } -int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath) +int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) { int result; @@ -541,7 +539,7 @@ int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *ne return result; } -int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz) +int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) { int result; @@ -551,7 +549,7 @@ int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_ return result; } -int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath) +int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) { int result; @@ -561,7 +559,7 @@ int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpa return result; } -int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev) +int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev) { int result; @@ -571,7 +569,7 @@ int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SM return result; } -char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved_path) +char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path) { char *result; @@ -581,7 +579,7 @@ char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved return result; } -size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) +size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, SEC_DESC **ppdesc) { size_t result; @@ -591,7 +589,7 @@ size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) return result; } -size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc) +size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, SEC_DESC **ppdesc) { size_t result; @@ -601,7 +599,7 @@ size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc return result; } -BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) +BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) { BOOL result; @@ -611,7 +609,7 @@ BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, S return result; } -BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) +BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) { BOOL result; @@ -621,7 +619,7 @@ BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_inf return result; } -int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode) +int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode) { int result; @@ -631,7 +629,7 @@ int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode) return result; } -int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode) +int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { int result; @@ -641,112 +639,124 @@ int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode) return result; } -int vfswrap_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) { return sys_acl_get_entry(theacl, entry_id, entry_p); } -int vfswrap_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) { return sys_acl_get_tag_type(entry_d, tag_type_p); } -int vfswrap_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) { return sys_acl_get_permset(entry_d, permset_p); } -void * vfswrap_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d) +void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d) { return sys_acl_get_qualifier(entry_d); } -SMB_ACL_T vfswrap_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) +SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) { return sys_acl_get_file(path_p, type); } -SMB_ACL_T vfswrap_sys_acl_get_fd(struct files_struct *fsp, int fd) +SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { return sys_acl_get_fd(fd); } -int vfswrap_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset) +int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset) { return sys_acl_clear_perms(permset); } -int vfswrap_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { return sys_acl_add_perm(permset, perm); } -char * vfswrap_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) +char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) { return sys_acl_to_text(theacl, plen); } -SMB_ACL_T vfswrap_sys_acl_init(struct connection_struct *conn, int count) +SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count) { return sys_acl_init(count); } -int vfswrap_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) { return sys_acl_create_entry(pacl, pentry); } -int vfswrap_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) { return sys_acl_set_tag_type(entry, tagtype); } -int vfswrap_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) +int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) { return sys_acl_set_qualifier(entry, qual); } -int vfswrap_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) { return sys_acl_set_permset(entry, permset); } -int vfswrap_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl ) +int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl ) { return sys_acl_valid(theacl ); } -int vfswrap_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) { return sys_acl_set_file(name, acltype, theacl); } -int vfswrap_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl) +int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl) { return sys_acl_set_fd(fd, theacl); } -int vfswrap_sys_acl_delete_def_file(struct connection_struct *conn, const char *path) +int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path) { return sys_acl_delete_def_file(path); } -int vfswrap_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { return sys_acl_get_perm(permset, perm); } -int vfswrap_sys_acl_free_text(struct connection_struct *conn, char *text) +int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text) { return sys_acl_free_text(text); } -int vfswrap_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl) +int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl) { return sys_acl_free_acl(posix_acl); } -int vfswrap_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) +int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) { return sys_acl_free_qualifier(qualifier, tagtype); } + +int vfswrap_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ + errno = ENOSYS; + return -1; +} + +int vfswrap_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ + errno = ENOSYS; + return -1; +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5fcf9a575e..7bae2ccc80 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -28,9 +28,9 @@ #define DBGC_CLASS DBGC_VFS struct vfs_init_function_entry { - char *name; - vfs_op_tuple *ops, *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *); - struct vfs_init_function_entry *prev, *next; + char *name; + vfs_op_tuple *vfs_op_tuples; + struct vfs_init_function_entry *prev, *next; }; static struct vfs_init_function_entry *backends = NULL; @@ -42,96 +42,94 @@ struct vfs_syminfo { void *fptr; }; -/* - Opaque (final) vfs operations. This is a combination of first-met opaque vfs operations - across all currently processed modules. */ - -static vfs_op_tuple vfs_opaque_ops[SMB_VFS_OP_LAST]; - /* Default vfs hooks. WARNING: The order of these initialisers is very important. They must be in the same order as defined in vfs.h. Change at your own peril. */ -static struct vfs_ops default_vfs_ops = { - - /* Disk operations */ - - vfswrap_dummy_connect, - vfswrap_dummy_disconnect, - vfswrap_disk_free, - - /* Directory operations */ - - vfswrap_opendir, - vfswrap_readdir, - vfswrap_mkdir, - vfswrap_rmdir, - vfswrap_closedir, - - /* File operations */ - - vfswrap_open, - vfswrap_close, - vfswrap_read, - vfswrap_write, - vfswrap_lseek, - vfswrap_sendfile, - vfswrap_rename, - vfswrap_fsync, - vfswrap_stat, - vfswrap_fstat, - vfswrap_lstat, - vfswrap_unlink, - vfswrap_chmod, - vfswrap_fchmod, - vfswrap_chown, - vfswrap_fchown, - vfswrap_chdir, - vfswrap_getwd, - vfswrap_utime, - vfswrap_ftruncate, - vfswrap_lock, - vfswrap_symlink, - vfswrap_readlink, - vfswrap_link, - vfswrap_mknod, - vfswrap_realpath, - - vfswrap_fget_nt_acl, - vfswrap_get_nt_acl, - vfswrap_fset_nt_acl, - vfswrap_set_nt_acl, - - /* POSIX ACL operations. */ +static struct vfs_ops default_vfs = { + + ops: { + /* Disk operations */ + + vfswrap_dummy_connect, + vfswrap_dummy_disconnect, + vfswrap_disk_free, + vfswrap_get_quota, + vfswrap_set_quota, + + /* Directory operations */ + + vfswrap_opendir, + vfswrap_readdir, + vfswrap_mkdir, + vfswrap_rmdir, + vfswrap_closedir, + + /* File operations */ + + vfswrap_open, + vfswrap_close, + vfswrap_read, + vfswrap_write, + vfswrap_lseek, + vfswrap_sendfile, + vfswrap_rename, + vfswrap_fsync, + vfswrap_stat, + vfswrap_fstat, + vfswrap_lstat, + vfswrap_unlink, + vfswrap_chmod, + vfswrap_fchmod, + vfswrap_chown, + vfswrap_fchown, + vfswrap_chdir, + vfswrap_getwd, + vfswrap_utime, + vfswrap_ftruncate, + vfswrap_lock, + vfswrap_symlink, + vfswrap_readlink, + vfswrap_link, + vfswrap_mknod, + vfswrap_realpath, + + vfswrap_fget_nt_acl, + vfswrap_get_nt_acl, + vfswrap_fset_nt_acl, + vfswrap_set_nt_acl, + + /* POSIX ACL operations. */ #if defined(HAVE_NO_ACLS) - NULL, - NULL, + NULL, + NULL, #else - vfswrap_chmod_acl, - vfswrap_fchmod_acl, + vfswrap_chmod_acl, + vfswrap_fchmod_acl, #endif - vfswrap_sys_acl_get_entry, - vfswrap_sys_acl_get_tag_type, - vfswrap_sys_acl_get_permset, - vfswrap_sys_acl_get_qualifier, - vfswrap_sys_acl_get_file, - vfswrap_sys_acl_get_fd, - vfswrap_sys_acl_clear_perms, - vfswrap_sys_acl_add_perm, - vfswrap_sys_acl_to_text, - vfswrap_sys_acl_init, - vfswrap_sys_acl_create_entry, - vfswrap_sys_acl_set_tag_type, - vfswrap_sys_acl_set_qualifier, - vfswrap_sys_acl_set_permset, - vfswrap_sys_acl_valid, - vfswrap_sys_acl_set_file, - vfswrap_sys_acl_set_fd, - vfswrap_sys_acl_delete_def_file, - vfswrap_sys_acl_get_perm, - vfswrap_sys_acl_free_text, - vfswrap_sys_acl_free_acl, - vfswrap_sys_acl_free_qualifier + vfswrap_sys_acl_get_entry, + vfswrap_sys_acl_get_tag_type, + vfswrap_sys_acl_get_permset, + vfswrap_sys_acl_get_qualifier, + vfswrap_sys_acl_get_file, + vfswrap_sys_acl_get_fd, + vfswrap_sys_acl_clear_perms, + vfswrap_sys_acl_add_perm, + vfswrap_sys_acl_to_text, + vfswrap_sys_acl_init, + vfswrap_sys_acl_create_entry, + vfswrap_sys_acl_set_tag_type, + vfswrap_sys_acl_set_qualifier, + vfswrap_sys_acl_set_permset, + vfswrap_sys_acl_valid, + vfswrap_sys_acl_set_file, + vfswrap_sys_acl_set_fd, + vfswrap_sys_acl_delete_def_file, + vfswrap_sys_acl_get_perm, + vfswrap_sys_acl_free_text, + vfswrap_sys_acl_free_acl, + vfswrap_sys_acl_free_qualifier + } }; /**************************************************************************** @@ -140,52 +138,49 @@ static struct vfs_ops default_vfs_ops = { static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) { - struct vfs_init_function_entry *entry = backends; - pstring stripped; - - module_path_get_name(name, stripped); + struct vfs_init_function_entry *entry = backends; + pstring stripped; - while(entry) { - if (strequal(entry->name, stripped)) return entry; - entry = entry->next; - } + module_path_get_name(name, stripped); + + while(entry) { + if (strequal(entry->name, stripped)) return entry; + entry = entry->next; + } - return NULL; + return NULL; } -NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *)) +NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples) { - struct vfs_init_function_entry *entry = backends; - - if ((version < SMB_VFS_INTERFACE_CASCADED)) { - DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", - version, SMB_VFS_INTERFACE_VERSION )); - return NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - if ((version < SMB_VFS_INTERFACE_VERSION)) { - DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ - Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", - version, SMB_VFS_INTERFACE_VERSION, version )); - return NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - if (!name || !init) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (vfs_find_backend_entry(name)) { - DEBUG(0,("VFS module %s already loaded!\n", name)); - return NT_STATUS_OBJECT_NAME_COLLISION; - } - - entry = smb_xmalloc(sizeof(struct vfs_init_function_entry)); - entry->name = smb_xstrdup(name); - entry->init = init; - - DLIST_ADD(backends, entry); - DEBUG(5, ("Successfully added vfs backend '%s'\n", name)); - return NT_STATUS_OK; + struct vfs_init_function_entry *entry = backends; + + if ((version != SMB_VFS_INTERFACE_VERSION)) { + DEBUG(0, ("Failed to register vfs module.\n" + "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n" + "current SMB_VFS_INTERFACE_VERSION is %d.\n" + "Please recompile against the current Samba Version!\n", + version, SMB_VFS_INTERFACE_VERSION)); + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !name[0] || !vfs_op_tuples) { + DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (vfs_find_backend_entry(name)) { + DEBUG(0,("VFS module %s already loaded!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = smb_xmalloc(sizeof(struct vfs_init_function_entry)); + entry->name = smb_xstrdup(name); + entry->vfs_op_tuples = vfs_op_tuples; + + DLIST_ADD(backends, entry); + DEBUG(5, ("Successfully added vfs backend '%s'\n", name)); + return NT_STATUS_OK; } /**************************************************************************** @@ -196,62 +191,10 @@ static void vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); - memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops)); - conn->vfs_private = NULL; + memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops)); + memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops)); } -/*************************************************************************** - Function to load old VFS modules. Should go away after a while. - **************************************************************************/ - -static vfs_op_tuple *vfs_load_old_plugin(connection_struct *conn, const char *vfs_object) -{ - int vfs_version = -1; - vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *); - /* Open object file */ - - if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) { - DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror())); - return NULL; - } - - /* Get handle on vfs_init() symbol */ - - init_fptr = (vfs_op_tuple *(*)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *))sys_dlsym(conn->vfs_private->handle, "vfs_init"); - - if (init_fptr == NULL) { - DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object)); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - /* Initialise vfs_ops structure */ - if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) { - DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object)); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) { - DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", - vfs_version, SMB_VFS_INTERFACE_VERSION )); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) { - DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ - Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", - vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version )); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - return ops; -} - - - /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ @@ -259,51 +202,82 @@ static vfs_op_tuple *vfs_load_old_plugin(connection_struct *conn, const char *vf BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) { vfs_op_tuple *ops; + char *module_name = NULL; + char *module_param = NULL, *p; int i; + vfs_handle_struct *handle; struct vfs_init_function_entry *entry; - - DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object)); + + if (!conn||!vfs_object||!vfs_object[0]) { + DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n")); + return False; + } if(!backends) static_init_vfs; + DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object)); + + module_name = smb_xstrdup(vfs_object); + + p = strchr(module_name, ':'); + + if (p) { + *p = 0; + module_param = p+1; + trim_string(module_param, " ", " "); + } + + trim_string(module_name, " ", " "); + /* First, try to load the module with the new module system */ - if((entry = vfs_find_backend_entry(vfs_object)) || - (NT_STATUS_IS_OK(smb_probe_module("vfs", vfs_object)) && - (entry = vfs_find_backend_entry(vfs_object)))) { + if((entry = vfs_find_backend_entry(module_name)) || + (NT_STATUS_IS_OK(smb_probe_module("vfs", module_name)) && + (entry = vfs_find_backend_entry(module_name)))) { - DEBUG(3,("Successfully loaded %s with the new modules system\n", vfs_object)); + DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object)); - if ((ops = entry->init(&conn->vfs_ops, conn->vfs_private)) == NULL) { - DEBUG(0, ("vfs init function from %s failed\n", vfs_object)); - return False; - } + if ((ops = entry->vfs_op_tuples) == NULL) { + DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object)); + SAFE_FREE(module_name); + return False; + } } else { - /* If that doesn't work, fall back to the old system - * (This part should go away after a while, it's only here - * for backwards compatibility) */ - DEBUG(2, ("Can't load module %s with new modules system, falling back to compatibility\n", - vfs_object)); - if ((ops = vfs_load_old_plugin(conn, vfs_object)) == NULL) { - DEBUG(0, ("vfs init function from %s failed\n", vfs_object)); - return False; - } + DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object)); + SAFE_FREE(module_name); + return False; + } + + handle = (vfs_handle_struct *)talloc_zero(conn->mem_ctx,sizeof(vfs_handle_struct)); + if (!handle) { + DEBUG(0,("talloc_zero() failed!\n")); + SAFE_FREE(module_name); + return False; } + memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops)); + handle->conn = conn; + if (module_param) { + handle->param = talloc_strdup(conn->mem_ctx, module_param); + } + DLIST_ADD(conn->vfs_handles, handle); for(i=0; ops[i].op != NULL; i++) { - DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); + DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { /* Check whether this operation was already made opaque by different module */ - if(vfs_opaque_ops[ops[i].type].op == ((void**)&default_vfs_ops)[ops[i].type]) { + if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { /* No, it isn't overloaded yet. Overload. */ - DEBUG(3, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); - vfs_opaque_ops[ops[i].type] = ops[i]; + DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); + ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; + ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; } } /* Change current VFS disposition*/ - DEBUG(3, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs_ops)[ops[i].type] = ops[i].op; + DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); + ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; + ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; } + SAFE_FREE(module_name); return True; } @@ -314,70 +288,30 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) BOOL smbd_vfs_init(connection_struct *conn) { const char **vfs_objects; - char *vfs_module, *vfs_path; unsigned int i = 0; int j = 0; - struct smb_vfs_handle_struct *handle; /* Normal share - initialise with disk access functions */ vfs_init_default(conn); - vfs_objects = lp_vfsobj(SNUM(conn)); + vfs_objects = lp_vfs_objects(SNUM(conn)); /* Override VFS functions if 'vfs object' was not specified*/ if (!vfs_objects || !vfs_objects[0]) return True; - - for(i=0; i= 0; j--) { - conn->vfs_private = NULL; - handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct)); - /* Loadable object file */ - handle->handle = NULL; - DLIST_ADD(conn->vfs_private, handle); - vfs_module = NULL; - if (vfs_path && *vfs_path) { - asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[j]); - } else { - asprintf(&vfs_module, "%s", vfs_objects[j]); - } - if (!vfs_init_custom(conn, vfs_module)) { - DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module)); - SAFE_FREE(vfs_module); - DLIST_REMOVE(conn->vfs_private, handle); - SAFE_FREE(handle); + if (!vfs_init_custom(conn, vfs_objects[j])) { + DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j])); return False; } - SAFE_FREE(vfs_module); } return True; } -/******************************************************************* - Create vfs_ops reflecting current vfs_opaque_ops -*******************************************************************/ - -struct vfs_ops *smb_vfs_get_opaque_ops(void) -{ - int i; - struct vfs_ops *ops; - - ops = smb_xmalloc(sizeof(struct vfs_ops)); - - for(i=0; ist_mode); @@ -400,25 +334,16 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ return ret; } -/******************************************************************* - vfs getwd wrapper -********************************************************************/ - -static char *vfs_getwd(connection_struct *conn, char *path) -{ - return conn->vfs_ops.getwd(conn,path); -} - /******************************************************************* vfs mkdir wrapper ********************************************************************/ -int vfs_mkdir(connection_struct *conn, const char *name, mode_t mode) +int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode) { int ret; SMB_STRUCT_STAT sbuf; - if(!(ret=conn->vfs_ops.mkdir(conn,name,mode))) { + if(!(ret=VFS_MKDIR(conn, name, mode))) { inherit_access_acl(conn, name, mode); @@ -428,8 +353,8 @@ int vfs_mkdir(connection_struct *conn, const char *name, mode_t mode) * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir. */ if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && - !vfs_stat(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) - vfs_chmod(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); + !VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) + VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); } return ret; } @@ -447,7 +372,7 @@ BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT ZERO_STRUCTP(sbuf); - if (vfs_stat(conn,fname,sbuf) == -1) + if (VFS_STAT(conn,fname,sbuf) == -1) return(False); return True; } @@ -465,7 +390,7 @@ BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT * ZERO_STRUCTP(sbuf); - if (vfs_stat(conn,fname,sbuf) == -1) + if (VFS_STAT(conn,fname,sbuf) == -1) return False; return(S_ISREG(sbuf->st_mode)); } @@ -480,7 +405,7 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) while (total < byte_count) { - ssize_t ret = fsp->conn->vfs_ops.read(fsp, fsp->fd, buf + total, + ssize_t ret = VFS_READ(fsp, fsp->fd, buf + total, byte_count - total); if (ret == 0) return total; @@ -505,7 +430,7 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) ssize_t ret; while (total < N) { - ret = fsp->conn->vfs_ops.write(fsp,fsp->fd,buffer + total,N - total); + ret = VFS_WRITE(fsp,fsp->fd,buffer + total,N - total); if (ret == -1) return -1; @@ -528,7 +453,6 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) int ret; SMB_STRUCT_STAT st; connection_struct *conn = fsp->conn; - struct vfs_ops *vfs_ops = &conn->vfs_ops; SMB_BIG_UINT space_avail; SMB_BIG_UINT bsize,dfree,dsize; @@ -545,7 +469,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) return -1; } - ret = vfs_fstat(fsp,fsp->fd,&st); + ret = VFS_FSTAT(fsp,fsp->fd,&st); if (ret == -1) return ret; @@ -559,7 +483,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) fsp->fsp_name, (double)st.st_size )); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = vfs_ops->ftruncate(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { + if ((ret = VFS_FTRUNCATE(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { set_filelen_write_cache(fsp, len); } return ret; @@ -572,7 +496,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ - space_avail = conn->vfs_ops.disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); + space_avail = VFS_DISK_FREE(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail )); @@ -598,7 +522,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, len)) != -1) + if ((ret = VFS_FTRUNCATE(fsp, fsp->fd, len)) != -1) set_filelen_write_cache(fsp, len); return ret; @@ -613,12 +537,12 @@ static files_struct *out_fsp; static ssize_t read_fn(int fd, void *buf, size_t len) { - return in_fsp->conn->vfs_ops.read(in_fsp, fd, buf, len); + return VFS_READ(in_fsp, fd, buf, len); } static ssize_t write_fn(int fd, const void *buf, size_t len) { - return out_fsp->conn->vfs_ops.write(out_fsp, fd, buf, len); + return VFS_WRITE(out_fsp, fd, buf, len); } SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) @@ -635,13 +559,13 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) char *vfs_readdirname(connection_struct *conn, void *p) { - struct dirent *ptr; + struct dirent *ptr= NULL; char *dname; if (!p) return(NULL); - ptr = (struct dirent *)conn->vfs_ops.readdir(conn,p); + ptr = (struct dirent *)VFS_READDIR(conn,p); if (!ptr) return(NULL); @@ -660,72 +584,6 @@ char *vfs_readdirname(connection_struct *conn, void *p) return(dname); } -/* VFS options not quite working yet */ - -#if 0 - -/*************************************************************************** - handle the interpretation of the vfs option parameter - *************************************************************************/ -static BOOL handle_vfs_option(char *pszParmValue, char **ptr) -{ - struct vfs_options *new_option, **options = (struct vfs_options **)ptr; - int i; - - /* Create new vfs option */ - - new_option = (struct vfs_options *)malloc(sizeof(*new_option)); - if (new_option == NULL) { - return False; - } - - ZERO_STRUCTP(new_option); - - /* Get name and value */ - - new_option->name = strtok(pszParmValue, "="); - - if (new_option->name == NULL) { - return False; - } - - while(isspace(*new_option->name)) { - new_option->name++; - } - - for (i = strlen(new_option->name); i > 0; i--) { - if (!isspace(new_option->name[i - 1])) break; - } - - new_option->name[i] = '\0'; - new_option->name = strdup(new_option->name); - - new_option->value = strtok(NULL, "="); - - if (new_option->value != NULL) { - - while(isspace(*new_option->value)) { - new_option->value++; - } - - for (i = strlen(new_option->value); i > 0; i--) { - if (!isspace(new_option->value[i - 1])) break; - } - - new_option->value[i] = '\0'; - new_option->value = strdup(new_option->value); - } - - /* Add to list */ - - DLIST_ADD(*options, new_option); - - return True; -} - -#endif - - /******************************************************************* A wrapper for vfs_chdir(). ********************************************************************/ @@ -741,9 +599,9 @@ int vfs_ChDir(connection_struct *conn, const char *path) if (*path == '/' && strcsequal(LastDir,path)) return(0); - DEBUG(3,("vfs_ChDir to %s\n",path)); + DEBUG(4,("vfs_ChDir to %s\n",path)); - res = vfs_chdir(conn,path); + res = VFS_CHDIR(conn,path); if (!res) pstrcpy(LastDir,path); return(res); @@ -800,7 +658,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) *s = 0; if (!use_getwd_cache) - return(vfs_getwd(conn,path)); + return(VFS_GETWD(conn,path)); /* init the cache */ if (!getwd_cache_init) { @@ -814,9 +672,9 @@ char *vfs_GetWd(connection_struct *conn, char *path) /* Get the inode of the current directory, if this doesn't work we're in trouble :-) */ - if (vfs_stat(conn, ".",&st) == -1) { + if (VFS_STAT(conn, ".",&st) == -1) { DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path)); - return(vfs_getwd(conn,path)); + return(VFS_GETWD(conn,path)); } @@ -830,7 +688,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) the same...) */ if (st.st_ino == ino_list[i].inode && st.st_dev == ino_list[i].dev) { - if (vfs_stat(conn,ino_list[i].dos_path,&st2) == 0) { + if (VFS_STAT(conn,ino_list[i].dos_path,&st2) == 0) { if (st.st_ino == st2.st_ino && st.st_dev == st2.st_dev && (st2.st_mode & S_IFMT) == S_IFDIR) { pstrcpy (path, ino_list[i].dos_path); @@ -852,8 +710,8 @@ char *vfs_GetWd(connection_struct *conn, char *path) The very slow getcwd, which spawns a process on some systems, or the not quite so bad getwd. */ - if (!vfs_getwd(conn,s)) { - DEBUG(0,("vfs_GetWd: vfs_getwd call failed, errno %s\n",strerror(errno))); + if (!VFS_GETWD(conn,s)) { + DEBUG(0,("vfs_GetWd: VFS_GETWD call failed, errno %s\n",strerror(errno))); return (NULL); } @@ -909,7 +767,7 @@ static BOOL readlink_check(connection_struct *conn, const char *dir, char *name) realdir[reallen] = 0; } - if (conn->vfs_ops.readlink(conn, name, flink, sizeof(pstring) -1) != -1) { + if (VFS_READLINK(conn, name, flink, sizeof(pstring) -1) != -1) { DEBUG(3,("reduce_name: file path name %s is a symlink\nChecking it's path\n", name)); if (*flink == '/') { pstrcpy(cleanlink, flink); -- cgit From e8573c8fa928602fd979d5ac45c692e7464f0aad Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 01:20:17 +0000 Subject: Add NT quota support. Patch from Stefan (metze) Metzemacher 1. Allows to change quota settings for shared mount points from Win2K and WinXP from Explorer properties tab 2. Disabled by default and when requested, will be probed and enabled only on Linux where it works 3. Was tested for approx. two weeks now on Linux by two independent QA teams, have not found any bugs so far Documentation to follow (This used to be commit 4bf022ce9e45be85609426762ba2644ac2031326) --- source3/smbd/dfree.c | 12 +- source3/smbd/fake_file.c | 166 ++++++++++++++ source3/smbd/files.c | 4 + source3/smbd/ntquotas.c | 259 ++++++++++++++++++++++ source3/smbd/nttrans.c | 553 ++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/quotas.c | 109 ++++++++++ source3/smbd/trans2.c | 197 ++++++++++++++++- source3/smbd/vfs-wrap.c | 20 +- 8 files changed, 1274 insertions(+), 46 deletions(-) create mode 100644 source3/smbd/fake_file.c create mode 100644 source3/smbd/ntquotas.c (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 71b3f2bf77..f93cdf3791 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -80,7 +80,7 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, dfree_command = lp_dfree_command(); if (dfree_command && *dfree_command) { - char *p; + const char *p; char **lines; pstring syscmd; @@ -93,15 +93,15 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, DEBUG (3, ("Read input from dfree, \"%s\"\n", line)); - *dsize = (SMB_BIG_UINT)strtoul(line, &p, 10); - while (p && *p & isspace(*p)) + *dsize = STR_TO_SMB_BIG_UINT(line, &p); + while (p && *p && isspace(*p)) p++; if (p && *p) - *dfree = (SMB_BIG_UINT)strtoul(p, &p, 10); - while (p && *p & isspace(*p)) + *dfree = STR_TO_SMB_BIG_UINT(p, &p); + while (p && *p && isspace(*p)) p++; if (p && *p) - *bsize = (SMB_BIG_UINT)strtoul(p, NULL, 10); + *bsize = STR_TO_SMB_BIG_UINT(p, NULL); else *bsize = 1024; file_lines_free(lines); diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c new file mode 100644 index 0000000000..86d78e039a --- /dev/null +++ b/source3/smbd/fake_file.c @@ -0,0 +1,166 @@ +/* + Unix SMB/CIFS implementation. + FAKE FILE suppport, for faking up special files windows want access to + Copyright (C) Stefan (metze) Metzmacher 2003 + + 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" + +/**************************************************************************** + Open a file with a share mode. +****************************************************************************/ +files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 desired_access, + int share_mode,int ofun, mode_t mode,int oplock_request, + int *Access,int *action) +{ + extern struct current_user current_user; + int flags=0; + files_struct *fsp = NULL; + + if (fake_file_type == 0) { + return open_file_shared1(conn,fname,psbuf,desired_access, + share_mode,ofun,mode, + oplock_request,Access,action); + } + + /* access check */ + if (conn->admin_user != True) { + DEBUG(1,("access_denied to service[%s] file[%s] user[%s]\n", + lp_servicename(SNUM(conn)),fname,conn->user)); + errno = EACCES; + return NULL; + } + + fsp = file_new(conn); + if(!fsp) + return NULL; + + DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", + fname, fsp->fnum, share_mode, ofun, (int)mode, oplock_request )); + + if (!check_name(fname,conn)) { + file_free(fsp); + return NULL; + } + + fsp->fd = -1; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; + fsp->vuid = current_user.vuid; + fsp->size = psbuf->st_size; + fsp->pos = -1; + fsp->can_lock = True; + fsp->can_read = ((flags & O_WRONLY)==0); + fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + fsp->share_mode = 0; + fsp->desired_access = desired_access; + fsp->print_file = False; + fsp->modified = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->is_directory = False; + fsp->is_stat = False; + fsp->directory_delete_on_close = False; + fsp->conn = conn; + string_set(&fsp->fsp_name,fname); + fsp->wcp = NULL; /* Write cache pointer. */ + + fsp->fake_file_handle = init_fake_file_handle(fake_file_type); + + if (fsp->fake_file_handle==NULL) { + file_free(fsp); + return NULL; + } + + conn->num_files_open++; + return fsp; +} + +static FAKE_FILE fake_files[] = { +#ifdef WITH_QUOTAS + {FAKE_FILE_NAME_QUOTA, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle}, +#endif /* WITH_QUOTAS */ + {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL } +}; + +int is_fake_file(char *fname) +{ + int i; + + if (!fname) + return 0; + + for (i=0;fake_files[i].name!=NULL;i++) { + if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) { + DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname)); + return fake_files[i].type; + } + } + + return FAKE_FILE_TYPE_NONE; +} + +struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) +{ + TALLOC_CTX *mem_ctx = NULL; + FAKE_FILE_HANDLE *fh = NULL; + int i; + + for (i=0;fake_files[i].name!=NULL;i++) { + if (fake_files[i].type==type) { + DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name)); + + if ((mem_ctx=talloc_init("fake_file_handle"))==NULL) { + DEBUG(0,("talloc_init(fake_file_handle) failed.\n")); + return NULL; + } + + if ((fh =(FAKE_FILE_HANDLE *)talloc_zero(mem_ctx, sizeof(FAKE_FILE_HANDLE)))==NULL) { + DEBUG(0,("talloc_zero() failed.\n")); + talloc_destroy(mem_ctx); + return NULL; + } + + fh->type = type; + fh->mem_ctx = mem_ctx; + + if (fake_files[i].init_pd) + fh->pd = fake_files[i].init_pd(fh->mem_ctx); + + fh->free_pd = fake_files[i].free_pd; + + return fh; + } + } + + return NULL; +} + +void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) +{ + if (!fh||!(*fh)) + return ; + + if ((*fh)->free_pd) + (*fh)->free_pd(&(*fh)->pd); + + talloc_destroy((*fh)->mem_ctx); + (*fh) = NULL; +} diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d926718c5d..4d1409feac 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -338,6 +338,10 @@ void file_free(files_struct *fsp) string_free(&fsp->fsp_name); + if (fsp->fake_file_handle) { + destroy_fake_file_handle(&fsp->fake_file_handle); + } + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c new file mode 100644 index 0000000000..85e1e137d9 --- /dev/null +++ b/source3/smbd/ntquotas.c @@ -0,0 +1,259 @@ +/* + Unix SMB/CIFS implementation. + NT QUOTA suppport + Copyright (C) Stefan (metze) Metzmacher 2003 + + 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" + +static SMB_BIG_UINT limit_nt2unix(SMB_BIG_UINT in, SMB_BIG_UINT bsize) +{ + SMB_BIG_UINT ret = (SMB_BIG_UINT)0; + + ret = (SMB_BIG_UINT)(in/bsize); + if (in>0 && ret==0) { + /* we have to make sure that a overflow didn't set NO_LIMIT */ + ret = (SMB_BIG_UINT)1; + } + + if (in == SMB_NTQUOTAS_NO_LIMIT) + ret = SMB_QUOTAS_NO_LIMIT; + else if (in == SMB_NTQUOTAS_NO_SPACE) + ret = SMB_QUOTAS_NO_SPACE; + else if (in == SMB_NTQUOTAS_NO_ENTRY) + ret = SMB_QUOTAS_NO_LIMIT; + + return ret; +} + +static SMB_BIG_UINT limit_unix2nt(SMB_BIG_UINT in, SMB_BIG_UINT bsize) +{ + SMB_BIG_UINT ret = (SMB_BIG_UINT)0; + + ret = (SMB_BIG_UINT)(in*bsize); + + if (ret < in) { + /* we overflow */ + ret = SMB_NTQUOTAS_NO_LIMIT; + } + + if (in == SMB_QUOTAS_NO_LIMIT) + ret = SMB_NTQUOTAS_NO_LIMIT; + + return ret; +} + +static SMB_BIG_UINT limit_blk2inodes(SMB_BIG_UINT in) +{ + SMB_BIG_UINT ret = (SMB_BIG_UINT)0; + + ret = (SMB_BIG_UINT)(in/2); + + if (ret == 0 && in != 0) + ret = (SMB_BIG_UINT)1; + + return ret; +} + +int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, SMB_NTQUOTA_STRUCT *qt) +{ + int ret; + SMB_DISK_QUOTA D; + unid_t id; + enum SID_NAME_USE sid_use = SID_NAME_USE_NONE; + + ZERO_STRUCT(D); + + if (!fsp||!fsp->conn||!qt) + return (-1); + + ZERO_STRUCT(*qt); + + id.uid = -1; + + if (psid && !sid_to_uid(psid, &id.uid, &sid_use)) { + DEBUG(0,("sid_to_uid: failed, SID[%s]\n", + sid_string_static(psid))); + } + + ret = VFS_GET_QUOTA(fsp->conn, qtype, id, &D); + + if (psid) + qt->sid = *psid; + + if (ret!=0) { + return ret; + } + + qt->usedspace = (SMB_BIG_UINT)D.curblocks*D.bsize; + qt->softlim = limit_unix2nt(D.softlimit, D.bsize); + qt->hardlim = limit_unix2nt(D.hardlimit, D.bsize); + qt->qflags = D.qflags; + + + return 0; +} + +int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, SMB_NTQUOTA_STRUCT *qt) +{ + int ret; + SMB_DISK_QUOTA D; + unid_t id; + enum SID_NAME_USE sid_use = SID_NAME_USE_NONE; + ZERO_STRUCT(D); + + if (!fsp||!fsp->conn||!qt) + return (-1); + + id.uid = -1; + + D.bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; + D.softlimit = limit_nt2unix(qt->softlim,D.bsize); + D.hardlimit = limit_nt2unix(qt->hardlim,D.bsize); + D.qflags = qt->qflags; + + D.isoftlimit = limit_blk2inodes(D.softlimit); + D.ihardlimit = limit_blk2inodes(D.hardlimit); + + if (psid && !sid_to_uid(psid, &id.uid, &sid_use)) { + DEBUG(0,("sid_to_uid: failed, SID[%s]\n", + sid_string_static(psid))); + } + + ret = VFS_SET_QUOTA(fsp->conn, qtype, id, &D); + + return ret; +} + +static BOOL allready_in_quota_list(SMB_NTQUOTA_LIST *qt_list, uid_t uid) +{ + SMB_NTQUOTA_LIST *tmp_list = NULL; + + if (!qt_list) + return False; + + for (tmp_list=qt_list;tmp_list!=NULL;tmp_list=tmp_list->next) { + if (tmp_list->uid == uid) { + return True; + } + } + + return False; +} + +int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) +{ + struct passwd *usr; + TALLOC_CTX *mem_ctx = NULL; + + if (!fsp||!fsp->conn||!qt_list) + return (-1); + + *qt_list = NULL; + + if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) { + DEBUG(0,("talloc_init() failed\n")); + return (-1); + } + + sys_setpwent(); + while ((usr = sys_getpwent()) != NULL) { + SMB_NTQUOTA_STRUCT tmp_qt; + SMB_NTQUOTA_LIST *tmp_list_ent; + DOM_SID sid; + + ZERO_STRUCT(tmp_qt); + + if (allready_in_quota_list((*qt_list),usr->pw_uid)) { + DEBUG(5,("record for uid[%d] allready in the list\n",usr->pw_uid)); + continue; + } + + if (uid_to_sid(&sid,usr->pw_uid)==NULL) { + DEBUG(0,("uid_to_sid failed for %d\n",usr->pw_uid)); + continue; + } + + if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) { + DEBUG(1,("no quota entry for sid[%s] path[%s]\n", + sid_string_static(&sid),fsp->conn->connectpath)); + continue; + } + + DEBUG(15,("quota entry for id[%s] path[%s]\n", + sid_string_static(&sid),fsp->conn->connectpath)); + + if ((tmp_list_ent=(SMB_NTQUOTA_LIST *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_LIST)))==NULL) { + DEBUG(0,("talloc_zero() failed\n")); + *qt_list = NULL; + talloc_destroy(mem_ctx); + return (-1); + } + + if ((tmp_list_ent->quotas=(SMB_NTQUOTA_STRUCT *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_STRUCT)))==NULL) { + DEBUG(0,("talloc_zero() failed\n")); + *qt_list = NULL; + talloc_destroy(mem_ctx); + return (-1); + } + + tmp_list_ent->uid = usr->pw_uid; + memcpy(tmp_list_ent->quotas,&tmp_qt,sizeof(tmp_qt)); + tmp_list_ent->mem_ctx = mem_ctx; + + DLIST_ADD((*qt_list),tmp_list_ent); + + } + sys_endpwent(); + + return 0; +} + +void *init_quota_handle(TALLOC_CTX *mem_ctx) +{ + SMB_NTQUOTA_HANDLE *qt_handle; + + if (!mem_ctx) + return False; + + qt_handle = (SMB_NTQUOTA_HANDLE *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_HANDLE)); + if (qt_handle==NULL) { + DEBUG(0,("talloc_zero() failed\n")); + return NULL; + } + + return (void *)qt_handle; +} + +void destroy_quota_handle(void **pqt_handle) +{ + SMB_NTQUOTA_HANDLE *qt_handle = NULL; + if (!pqt_handle||!(*pqt_handle)) + return; + + qt_handle = (*pqt_handle); + + + if (qt_handle->quota_list) + free_ntquota_list(&qt_handle->quota_list); + + qt_handle->quota_list = NULL; + qt_handle->tmp_list = NULL; + qt_handle = NULL; + + return; +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 38de5586ea..c026ee9f58 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. SMB NT transaction handling - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Stefan (metze) Metzmacher 2003 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 @@ -26,6 +27,7 @@ extern int global_oplock_break; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; +extern struct current_user current_user; static const char *known_nt_pipes[] = { "\\LANMAN", @@ -53,6 +55,24 @@ struct generic_mapping file_generic_mapping = { FILE_GENERIC_ALL }; +char *nttrans_realloc(char **ptr, size_t size) +{ + char *tptr = NULL; + if (ptr==NULL) + smb_panic("nttrans_realloc() called with NULL ptr\n"); + + tptr = Realloc_zero(*ptr, size); + if(tptr == NULL) { + *ptr = NULL; + return NULL; + } + + *ptr = tptr; + + return tptr; +} + + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -542,6 +562,7 @@ int reply_ntcreate_and_X(connection_struct *conn, { int result; pstring fname; + enum FAKE_FILE_TYPE fake_file_type = 0; uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); @@ -669,8 +690,21 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib */ if( strchr_m(fname, ':')) { - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + + if ((fake_file_type=is_fake_file(fname))!=0) { + /* + * here we go! support for changing the disk quotas --metze + * + * we need to fake up to open this MAGIC QUOTA file + * and return a valid FID + * + * w2k close this file directly after openening + * xp also tries a QUERY_FILE_INFO on the file and then close it + */ + } else { + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } } } @@ -746,12 +780,21 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_shared1(conn,fname,&sbuf, + if (fake_file_type==0) { + fsp = open_file_shared1(conn,fname,&sbuf, desired_access, smb_open_mode, smb_ofun,unixmode, oplock_request, &rmode,&smb_action); - + } else { + /* to open a fake_file --metze */ + fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf, + desired_access, + smb_open_mode, + smb_ofun,unixmode, oplock_request, + &rmode,&smb_action); + } + if (!fsp) { /* We cheat here. There are two cases we * care about. One is a directory rename, @@ -944,14 +987,10 @@ static int do_nt_transact_create_pipe( connection_struct *conn, return ret; /* Realloc the size of parameters and data we will return */ - params = Realloc(*ppparams, 69); + params = nttrans_realloc(ppparams, 69); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; - - memset((char *)params,'\0',69); - p = params; SCVAL(p,0,NO_OPLOCK_RETURN); @@ -1331,14 +1370,10 @@ static int call_nt_transact_create(connection_struct *conn, } /* Realloc the size of parameters and data we will return */ - params = Realloc(*ppparams, 69); + params = nttrans_realloc(ppparams, 69); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; - - memset((char *)params,'\0',69); - p = params; if (extended_oplock_granted) SCVAL(p,0, BATCH_OPLOCK_RETURN); @@ -1543,12 +1578,10 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); - params = Realloc(*ppparams, 4); + params = nttrans_realloc(ppparams, 4); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; - if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) { DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); return ERROR_DOS(ERRDOS,ERRnomem); @@ -1584,16 +1617,12 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Allocate the data we will point this at. */ - data = Realloc(*ppdata, sd_size); + data = nttrans_realloc(ppdata, sd_size); if(data == NULL) { talloc_destroy(mem_ctx); return ERROR_DOS(ERRDOS,ERRnomem); } - *ppdata = data; - - memset(data, '\0', sd_size); - /* * Init the parse struct we will marshall into. */ @@ -1686,6 +1715,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, { unsigned fnum, control; static BOOL logged_message; + char *pdata = *ppdata; if (setup_count != 8) { DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count)); @@ -1695,28 +1725,479 @@ static int call_nt_transact_ioctl(connection_struct *conn, fnum = SVAL(*ppsetup, 4); control = IVAL(*ppsetup, 0); - DEBUG(6,("call_nt_transact_ioctl: fnum=%d control=0x%x\n", + DEBUG(10,("call_nt_transact_ioctl: fnum=%d control=0x%08x\n", fnum, control)); switch (control) { - case NTIOCTL_SET_SPARSE: + case FSCTL_SET_SPARSE: /* pretend this succeeded - tho strictly we should mark the file sparse (if the local fs supports it) so we can know if we need to pre-allocate or not */ + + DEBUG(10,("FSCTL_SET_SPARSE: fnum=%d control=0x%08x\n",fnum,control)); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + return -1; + + case FSCTL_0x000900C0: + /* pretend this succeeded - don't know what this really is + but works ok like this --metze + */ + + DEBUG(1,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; + case FSCTL_GET_REPARSE_POINT: + /* pretend this fail - my winXP does it like this + * --metze + */ + + DEBUG(1,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); + return -1; + + case FSCTL_SET_REPARSE_POINT: + /* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case. + * --metze + */ + + DEBUG(1,("FSCTL_SET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); + return -1; + + case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */ + { + /* pretend this succeeded - + * + * we have to send back a list with all files owned by this SID + * + * but I have to check that --metze + */ + + DOM_SID sid; + uid_t uid; + enum SID_NAME_USE sid_use = 0; + size_t sid_len=SID_MAX_SIZE; + + DEBUG(1,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control)); + + /* this is not the length of the sid :-( so unknown 4 bytes */ + /*sid_len = IVAL(pdata,0); + DEBUGADD(0,("sid_len: (%u)\n",sid_len));*/ + + sid_parse(pdata+4,sid_len,&sid); + DEBUGADD(2,("SID: %s\n",sid_string_static(&sid))); + + if (!sid_to_uid(&sid, &uid, &sid_use) + ||sid_use!=SID_NAME_USER) { + DEBUG(0,("sid_to_uid: failed, sid[%s] sid_use: %d\n", + sid_string_static(&sid),sid_use)); + uid = (-1); + } + + /* we can take a look at the find source :-) + * + * find ./ -uid $uid -name '*' is what we need here + * + * + * and send 4bytes len and then NULL terminated unicode strings + * for each file + * + * but I don't know how to deal with the paged results + * + * we don't send all files at once + * and at the next we should *not* start from the beginning, + * so we have to cache the result + * + * --metze + */ + + /* this works for now... */ + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + return -1; + } default: if (!logged_message) { logged_message = True; /* Only print this once... */ - DEBUG(3,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", + DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", control)); } } return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - + + +/**************************************************************************** + Reply to get user quota +****************************************************************************/ + +static int call_nt_transact_get_user_quota(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, + char **ppsetup, int setup_count, + char **ppparams, int params_count, + char **ppdata, int data_count) +{ + NTSTATUS nt_status = NT_STATUS_OK; + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); + char *params = *ppparams; + char *pdata = *ppdata; + char *entry; + int data_len=0,param_len=0; + int qt_len=0; + int entry_len = 0; + files_struct *fsp = NULL; + uint16 level = 0; + size_t sid_len; + DOM_SID sid; + BOOL start_enum = True; + SMB_NTQUOTA_STRUCT qt; + SMB_NTQUOTA_LIST *tmp_list; + SMB_NTQUOTA_HANDLE *qt_handle = NULL; + + ZERO_STRUCT(qt); + + /* access check */ + if (conn->admin_user != True) { + DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + /* + * Ensure minimum number of parameters sent. + */ + + if (params_count < 4) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",params_count)); + return ERROR_DOS(ERRDOS,ERRinvalidparam); + } + + /* maybe we can check the quota_fnum */ + fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + /* the NULL pointer cheking for fsp->fake_file_handle->pd + * is done by CHECK_NTQUOTA_HANDLE_OK() + */ + qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd; + + level = SVAL(params,2); + + /* unknown 12 bytes leading in params */ + + switch (level) { + case TRANSACT_GET_USER_QUOTA_LIST_CONTINUE: + /* seems that we should continue with the enum here --metze */ + + if (qt_handle->quota_list!=NULL && + qt_handle->tmp_list==NULL) { + + /* free the list */ + free_ntquota_list(&(qt_handle->quota_list)); + + /* Realloc the size of parameters and data we will return */ + param_len = 4; + params = nttrans_realloc(ppparams, param_len); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + data_len = 0; + SIVAL(params,0,data_len); + + break; + } + + start_enum = False; + + case TRANSACT_GET_USER_QUOTA_LIST_START: + + if (qt_handle->quota_list==NULL && + qt_handle->tmp_list==NULL) { + start_enum = True; + } + + if (start_enum && vfs_get_user_ntquota_list(fsp,&(qt_handle->quota_list))!=0) + return ERROR_DOS(ERRSRV,ERRerror); + + /* Realloc the size of parameters and data we will return */ + param_len = 4; + params = nttrans_realloc(ppparams, param_len); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + /* we should not trust the value in max_data_count*/ + max_data_count = MIN(max_data_count,2048); + + pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/ + if(pdata == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + entry = pdata; + + + /* set params Size of returned Quota Data 4 bytes*/ + /* but set it later when we know it */ + + /* for each entry push the data */ + + if (start_enum) { + qt_handle->tmp_list = qt_handle->quota_list; + } + + tmp_list = qt_handle->tmp_list; + + for (;((tmp_list!=NULL)&&((qt_len +40+SID_MAX_SIZE)next,entry+=entry_len,qt_len+=entry_len) { + + sid_len = sid_size(&tmp_list->quotas->sid); + entry_len = 40 + sid_len; + + /* nextoffset entry 4 bytes */ + SIVAL(entry,0,entry_len); + + /* then the len of the SID 4 bytes */ + SIVAL(entry,4,sid_len); + + /* unknown data 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-metze*/ + + /* the used disk space 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,16,tmp_list->quotas->usedspace); + + /* the soft quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,24,tmp_list->quotas->softlim); + + /* the hard quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,32,tmp_list->quotas->hardlim); + + /* and now the SID */ + sid_linearize(entry+40, sid_len, &tmp_list->quotas->sid); + } + + qt_handle->tmp_list = tmp_list; + + /* overwrite the offset of the last entry */ + SIVAL(entry-entry_len,0,0); + + data_len = 4+qt_len; + /* overwrite the params quota_data_len */ + SIVAL(params,0,data_len); + + break; + + case TRANSACT_GET_USER_QUOTA_FOR_SID: + + /* unknown 4 bytes IVAL(pdata,0) */ + + if (data_count < 8) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + sid_len = IVAL(pdata,4); + + if (data_count < 8+sid_len) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8+sid_len)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + data_len = 4+40+sid_len; + + if (max_data_count < data_len) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: max_data_count(%d) < data_len(%d)\n", + max_data_count, data_len)); + param_len = 4; + SIVAL(params,0,data_len); + data_len = 0; + nt_status = NT_STATUS_BUFFER_TOO_SMALL; + break; + } + + sid_parse(pdata+8,sid_len,&sid); + + + if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) { + ZERO_STRUCT(qt); + /* + * we have to return zero's in all fields + * instead of returning an error here + * --metze + */ + } + + /* Realloc the size of parameters and data we will return */ + param_len = 4; + params = nttrans_realloc(ppparams, param_len); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + pdata = nttrans_realloc(ppdata, data_len); + if(pdata == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + entry = pdata; + + /* set params Size of returned Quota Data 4 bytes*/ + SIVAL(params,0,data_len); + + /* nextoffset entry 4 bytes */ + SIVAL(entry,0,0); + + /* then the len of the SID 4 bytes */ + SIVAL(entry,4,sid_len); + + /* unknown data 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-mezte*/ + + /* the used disk space 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,16,qt.usedspace); + + /* the soft quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,24,qt.softlim); + + /* the hard quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,32,qt.hardlim); + + /* and now the SID */ + sid_linearize(entry+40, sid_len, &sid); + + break; + + default: + DEBUG(0,("do_nt_transact_get_user_quota: fnum %d unknown level 0x%04hX\n",fsp->fnum,level)); + return ERROR_DOS(ERRSRV,ERRerror); + break; + } + + send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len, pdata, data_len); + + return -1; +} + +/**************************************************************************** + Reply to set user quota +****************************************************************************/ + +static int call_nt_transact_set_user_quota(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int bufsize, + char **ppsetup, int setup_count, + char **ppparams, int params_count, + char **ppdata, int data_count) +{ + char *params = *ppparams; + char *pdata = *ppdata; + int data_len=0,param_len=0; + SMB_NTQUOTA_STRUCT qt; + size_t sid_len; + DOM_SID sid; + files_struct *fsp = NULL; + + ZERO_STRUCT(qt); + + /* access check */ + if (conn->admin_user != True) { + DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + /* + * Ensure minimum number of parameters sent. + */ + + if (params_count < 2) { + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",params_count)); + return ERROR_DOS(ERRDOS,ERRinvalidparam); + } + + /* maybe we can check the quota_fnum */ + fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + if (data_count < 40) { + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* offset to next quota record. + * 4 bytes IVAL(pdata,0) + * unused here... + */ + + /* sid len */ + sid_len = IVAL(pdata,4); + + if (data_count < 40+sid_len) { + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40+sid_len)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* unknown 8 bytes in pdata + * maybe its the change time in NTTIME + */ + + /* the used space 8 bytes (SMB_BIG_UINT)*/ + qt.usedspace = (SMB_BIG_UINT)IVAL(pdata,16); +#ifdef LARGE_SMB_OFF_T + qt.usedspace |= (((SMB_BIG_UINT)IVAL(pdata,20)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,20) != 0)&& + ((qt.usedspace != 0xFFFFFFFF)|| + (IVAL(pdata,20)!=0xFFFFFFFF)))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* the soft quotas 8 bytes (SMB_BIG_UINT)*/ + qt.softlim = (SMB_BIG_UINT)IVAL(pdata,24); +#ifdef LARGE_SMB_OFF_T + qt.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,28) != 0)&& + ((qt.softlim != 0xFFFFFFFF)|| + (IVAL(pdata,28)!=0xFFFFFFFF)))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* the hard quotas 8 bytes (SMB_BIG_UINT)*/ + qt.hardlim = (SMB_BIG_UINT)IVAL(pdata,32); +#ifdef LARGE_SMB_OFF_T + qt.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,36) != 0)&& + ((qt.hardlim != 0xFFFFFFFF)|| + (IVAL(pdata,36)!=0xFFFFFFFF)))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + sid_parse(pdata+40,sid_len,&sid); + DEBUGADD(8,("SID: %s\n",sid_string_static(&sid))); + + /* 44 unknown bytes left... */ + + if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) { + return ERROR_DOS(ERRSRV,ERRerror); + } + + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, pdata, data_len); + + return -1; +} + /**************************************************************************** Reply to a SMBNTtrans. ****************************************************************************/ @@ -1960,6 +2441,24 @@ due to being in oplock break state.\n", (unsigned int)function_code )); &setup, ¶ms, &data); END_PROFILE_NESTED(NT_transact_query_security_desc); break; + case NT_TRANSACT_GET_USER_QUOTA: + START_PROFILE_NESTED(NT_transact_get_user_quota); + outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, + length, bufsize, + &setup, setup_count, + ¶ms, parameter_count, + &data, data_count); + END_PROFILE_NESTED(NT_transact_get_user_quota); + break; + case NT_TRANSACT_SET_USER_QUOTA: + START_PROFILE_NESTED(NT_transact_set_user_quota); + outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, + length, bufsize, + &setup, setup_count, + ¶ms, parameter_count, + &data, data_count); + END_PROFILE_NESTED(NT_transact_set_user_quota); + break; default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 5b843bd09a..0163120ee5 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -27,6 +27,10 @@ #include "includes.h" +#ifndef HAVE_SYS_QUOTAS + +#ifdef WITH_QUOTAS + #if defined(VXFS_QUOTA) /* @@ -1112,3 +1116,108 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B #endif /* SUNOS5 || ... */ #endif /* VXFS_QUOTA */ + +#else /* WITH_QUOTAS */ + +BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +{ + (*bsize) = 512; /* This value should be ignored */ + + /* And just to be sure we set some values that hopefully */ + /* will be larger that any possible real-world value */ + (*dfree) = (SMB_BIG_UINT)-1; + (*dsize) = (SMB_BIG_UINT)-1; + + /* As we have select not to use quotas, allways fail */ + return False; +} +#endif /* WITH_QUOTAS */ + +#else /* HAVE_SYS_QUOTAS */ +/* wrapper to the new sys_quota interface + this file should be removed later + */ +BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +{ + int r; + SMB_DISK_QUOTA D; + unid_t id; + + id.uid = geteuid(); + + r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = D.bsize; + if (r == -1) { + if (errno == EDQUOT) { + *dfree =0; + *dsize =D.curblocks; + return (True); + } else { + goto try_group_quota; + } + } + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.softlimit && D.curblocks >= D.softlimit) || + (D.hardlimit && D.curblocks >= D.hardlimit) || + (D.isoftlimit && D.curinodes >= D.isoftlimit) || + (D.ihardlimit && D.curinodes>=D.ihardlimit) + ) { + *dfree = 0; + *dsize = D.curblocks; + } else if (D.softlimit==0 && D.hardlimit==0) { + goto try_group_quota; + } else { + if (D.softlimit == 0) + D.softlimit = D.hardlimit; + *dfree = D.softlimit - D.curblocks; + *dsize = D.softlimit; + } + + return True; + +try_group_quota: +#ifdef HAVE_GROUP_QUOTA + id.gid = getegid(); + + r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = D.bsize; + if (r == -1) { + if (errno == EDQUOT) { + *dfree =0; + *dsize =D.curblocks; + return (True); + } else { + return False; + } + } + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.softlimit && D.curblocks >= D.softlimit) || + (D.hardlimit && D.curblocks >= D.hardlimit) || + (D.isoftlimit && D.curinodes >= D.isoftlimit) || + (D.ihardlimit && D.curinodes>=D.ihardlimit) + ) { + *dfree = 0; + *dsize = D.curblocks; + } else if (D.softlimit==0 && D.hardlimit==0) { + return False; + } else { + if (D.softlimit == 0) + D.softlimit = D.hardlimit; + *dfree = D.softlimit - D.curblocks; + *dsize = D.softlimit; + } + + return (True); +#else /* HAVE_GROUP_QUOTA */ + return False; +#endif /* HAVE_GROUP_QUOTA */ +} +#endif /* HAVE_SYS_QUOTAS */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c9eef637d9..ea53059279 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-2001 + Copyright (C) Jeremy Allison 1994-2001 + Copyright (C) Stefan (metze) Metzmacher 2003 Extensively modified by Andrew Tridgell, 1995 @@ -28,6 +29,7 @@ extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; extern uint32 global_client_caps; +extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) @@ -1368,7 +1370,9 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf case SMB_FS_ATTRIBUTE_INFORMATION: SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ + (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| + (HAVE_SYS_QUOTAS ? FILE_VOLUME_QUOTAS: 0)); /* FS ATTRIBUTES */ + SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it and will think we can't do long filenames */ @@ -1470,6 +1474,76 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SIVAL(pdata,4,0); /* characteristics */ break; + case SMB_FS_QUOTA_INFORMATION: + /* + * what we have to send --metze: + * + * Unknown1: 24 NULL bytes + * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so + * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so + * Quota Flags: 2 byte : + * Unknown3: 6 NULL bytes + * + * 48 bytes total + * + * details for Quota Flags: + * + * 0x0020 Log Limit: log if the user exceeds his Hard Quota + * 0x0010 Log Warn: log if the user exceeds his Soft Quota + * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota + * 0x0001 Enable Quotas: enable quota for this fs + * + */ + { + /* we need to fake up a fsp here, + * because its not send in this call + */ + files_struct fsp; + SMB_NTQUOTA_STRUCT quotas; + + ZERO_STRUCT(fsp); + ZERO_STRUCT(quotas); + + fsp.conn = conn; + fsp.fnum = -1; + fsp.fd = -1; + + /* access check */ + if (conn->admin_user != True) { + DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { + DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); + return ERROR_DOS(ERRSRV,ERRerror); + } + + data_len = 48; + + DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn)))); + + /* Unknown1 24 NULL bytes*/ + SBIG_UINT(pdata,0,(SMB_BIG_UINT)0); + SBIG_UINT(pdata,8,(SMB_BIG_UINT)0); + SBIG_UINT(pdata,16,(SMB_BIG_UINT)0); + + /* Default Soft Quota 8 bytes */ + SBIG_UINT(pdata,24,quotas.softlim); + + /* Default Hard Quota 8 bytes */ + SBIG_UINT(pdata,32,quotas.hardlim); + + /* Quota flag 2 bytes */ + SSVAL(pdata,40,quotas.qflags); + + /* Unknown3 6 NULL bytes */ + SSVAL(pdata,42,0); + SIVAL(pdata,44,0); + + break; + } case SMB_FS_OBJECTID_INFORMATION: data_len = 64; break; @@ -1519,14 +1593,104 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **pparams, int total_params, char **ppdata, int total_data) { - /* Just say yes we did it - there is nothing that - can be set here so it doesn't matter. */ + char *pdata = *ppdata; + char *params = *pparams; + files_struct *fsp = NULL; + uint16 info_level; int outsize; - DEBUG(3,("call_trans2setfsinfo\n")); + SMB_NTQUOTA_STRUCT quotas; + + ZERO_STRUCT(quotas); - if (!CAN_WRITE(conn)) + DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn)))); + + /* access check */ + if ((conn->admin_user != True)||!CAN_WRITE(conn)) { + DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRSRV,ERRaccess); + } + + /* */ + if (total_params < 4) { + DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n", + total_params)); + return ERROR_DOS(ERRDOS,ERRinvalidparam); + } + fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + info_level = SVAL(params,2); + + switch(info_level) { + case SMB_FS_QUOTA_INFORMATION: + /* note: normaly there're 48 bytes, + * but we didn't use the last 6 bytes for now + * --metze + */ + if (total_data < 42) { + DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n", + total_data)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* unknown_1 24 NULL bytes in pdata*/ + + /* the soft quotas 8 bytes (SMB_BIG_UINT)*/ + quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24); +#ifdef LARGE_SMB_OFF_T + quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,28) != 0)&& + ((quotas.softlim != 0xFFFFFFFF)|| + (IVAL(pdata,28)!=0xFFFFFFFF)))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* the hard quotas 8 bytes (SMB_BIG_UINT)*/ + quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32); +#ifdef LARGE_SMB_OFF_T + quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,36) != 0)&& + ((quotas.hardlim != 0xFFFFFFFF)|| + (IVAL(pdata,36)!=0xFFFFFFFF)))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* quota_flags 2 bytes **/ + quotas.qflags = SVAL(pdata,40); + + /* unknown_2 6 NULL bytes follow*/ + + /* now set the quotas */ + if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { + DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); + return ERROR_DOS(ERRSRV,ERRerror); + } + + break; + default: + DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n", + info_level)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + break; + } + + /* + * sending this reply works fine, + * but I'm not sure it's the same + * like windows do... + * --metze + */ outsize = set_message(outbuf,10,0,True); return outsize; @@ -1589,7 +1753,20 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); - if(fsp && (fsp->is_directory || fsp->fd == -1)) { + if(fsp && (fsp->fake_file_handle)) { + /* + * This is actually for the QUOTA_FAKE_FILE --metze + */ + + pstrcpy(fname, fsp->fsp_name); + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn)) { + DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + + } else if(fsp && (fsp->is_directory || fsp->fd == -1)) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems @@ -2229,7 +2406,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; mode_t unixmode = 0; + if (!params) + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if (tran_call == TRANSACT2_SETFILEINFO) { + if (total_params < 4) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + fsp = file_fsp(params,0); info_level = SVAL(params,2); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 4422666006..dd8aad1170 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -749,14 +749,22 @@ int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct return sys_acl_free_qualifier(qualifier, tagtype); } -int vfswrap_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) { - errno = ENOSYS; - return -1; + int result; + + START_PROFILE(syscall_get_quota); + result = sys_get_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_get_quota); + return result; } -int vfswrap_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) { - errno = ENOSYS; - return -1; + int result; + + START_PROFILE(syscall_set_quota); + result = sys_set_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_set_quota); + return result; } -- cgit From e102cdf58eb19e3d375f2ef02c0f7a4f340f4970 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 01:43:59 +0000 Subject: Small fix for HAVE_SYS_QUOTAS usage, spotted by build farm (This used to be commit ee5fa840686a1d9789688e7c0f1c3ca8d0175e94) --- source3/smbd/trans2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ea53059279..771e2ff444 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1371,7 +1371,12 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| - (HAVE_SYS_QUOTAS ? FILE_VOLUME_QUOTAS: 0)); /* FS ATTRIBUTES */ +#if defined(HAVE_SYS_QUOTAS) + FILE_VOLUME_QUOTAS +#else + 0 +#if + ); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it -- cgit From f9c23432aeb573cb971c7a87adc6ca952ce30d2f Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 02:01:31 +0000 Subject: Small fix for HAVE_SYS_QUOTAS usage, spotted by build farm (This used to be commit 01cff3e2e4e2724ed112fa62a775055192a2207b) --- source3/smbd/trans2.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 771e2ff444..9604017d74 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1320,6 +1320,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); + int quota_flag = 0; DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); @@ -1369,14 +1370,14 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf case SMB_QUERY_FS_ATTRIBUTE_INFO: case SMB_FS_ATTRIBUTE_INFORMATION: + +#if defined(HAVE_SYS_QUOTAS) + quota_flag = FILE_VOLUME_QUOTAS; +#endif + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| -#if defined(HAVE_SYS_QUOTAS) - FILE_VOLUME_QUOTAS -#else - 0 -#if - ); /* FS ATTRIBUTES */ + quota_flag); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it -- cgit From 92c8ca92c3015e1449a1c7c62bedb5f2fbbcff73 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 02:23:50 +0000 Subject: Better isolate quota stuff (This used to be commit 73de13159c57de21a59d2e32216812f5d9d2292e) --- source3/smbd/ntquotas.c | 4 ++++ source3/smbd/nttrans.c | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 85e1e137d9..d4e165e5ac 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -20,6 +20,8 @@ #include "includes.h" +#ifdef WITH_QUOTAS + static SMB_BIG_UINT limit_nt2unix(SMB_BIG_UINT in, SMB_BIG_UINT bsize) { SMB_BIG_UINT ret = (SMB_BIG_UINT)0; @@ -257,3 +259,5 @@ void destroy_quota_handle(void **pqt_handle) return; } + +#endif /* WITH_QUOTAS */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c026ee9f58..e7c834f531 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -691,6 +691,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if( strchr_m(fname, ':')) { +#ifdef WITH_QUOTAS if ((fake_file_type=is_fake_file(fname))!=0) { /* * here we go! support for changing the disk quotas --metze @@ -702,9 +703,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * xp also tries a QUERY_FILE_INFO on the file and then close it */ } else { +#endif END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); +#ifdef WITH_QUOTAS } +#endif } } @@ -1828,6 +1832,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, } +#ifdef WITH_QUOTAS /**************************************************************************** Reply to get user quota ****************************************************************************/ @@ -2197,6 +2202,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, return -1; } +#endif /* WITH_QUOTAS */ /**************************************************************************** Reply to a SMBNTtrans. @@ -2441,6 +2447,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); &setup, ¶ms, &data); END_PROFILE_NESTED(NT_transact_query_security_desc); break; +#ifdef WITH_QUOTAS case NT_TRANSACT_GET_USER_QUOTA: START_PROFILE_NESTED(NT_transact_get_user_quota); outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, @@ -2459,6 +2466,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); &data, data_count); END_PROFILE_NESTED(NT_transact_set_user_quota); break; +#endif /* WITH_QUOTAS */ default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); -- cgit From eeac7cc99d0ecd817470ad5237b141106331fec3 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 02:53:17 +0000 Subject: Wrap into WITH_QUOTAS yet another place in trans2 (This used to be commit fea5d85d947965bd4789ab31607fd48d78403696) --- source3/smbd/trans2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9604017d74..2f2820e76b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1480,6 +1480,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SIVAL(pdata,4,0); /* characteristics */ break; +#ifdef WITH_QUOTAS case SMB_FS_QUOTA_INFORMATION: /* * what we have to send --metze: @@ -1550,6 +1551,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned break; } +#endif /* WITH_QUOTAS */ case SMB_FS_OBJECTID_INFORMATION: data_len = 64; break; @@ -1591,6 +1593,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return -1; } +#ifdef WITH_QUOTAS /**************************************************************************** Reply to a TRANS2_SETFSINFO (set filesystem info). ****************************************************************************/ @@ -1625,6 +1628,7 @@ static int call_trans2setfsinfo(connection_struct *conn, } fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); return ERROR_NT(NT_STATUS_INVALID_HANDLE); @@ -1701,6 +1705,7 @@ static int call_trans2setfsinfo(connection_struct *conn, return outsize; } +#endif /* WITH_QUOTAS */ /**************************************************************************** * Utility function to set bad path error. @@ -3487,13 +3492,14 @@ int reply_trans2(connection_struct *conn, END_PROFILE_NESTED(Trans2_qfsinfo); break; +#ifdef WITH_QUOTAS case TRANSACT2_SETFSINFO: START_PROFILE_NESTED(Trans2_setfsinfo); outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_setfsinfo); break; - +#endif case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: START_PROFILE_NESTED(Trans2_qpathinfo); -- cgit From fe3b05eec41e25e97da3eca87ee372c82df32796 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 03:13:41 +0000 Subject: Fix a wrong define check. (This used to be commit f1c4f65ae019c61f4a8178bee094dd66506dbcae) --- source3/smbd/ntquotas.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index d4e165e5ac..f34d61541c 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -20,8 +20,6 @@ #include "includes.h" -#ifdef WITH_QUOTAS - static SMB_BIG_UINT limit_nt2unix(SMB_BIG_UINT in, SMB_BIG_UINT bsize) { SMB_BIG_UINT ret = (SMB_BIG_UINT)0; @@ -123,7 +121,11 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, id.uid = -1; +#if defined(QUOTABLOCK_SIZE) D.bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; +#else + D.bsize = (SMB_BIG_UINT)1024; +#endif D.softlimit = limit_nt2unix(qt->softlim,D.bsize); D.hardlimit = limit_nt2unix(qt->hardlim,D.bsize); D.qflags = qt->qflags; @@ -260,4 +262,3 @@ void destroy_quota_handle(void **pqt_handle) return; } -#endif /* WITH_QUOTAS */ -- cgit From 6e4c1e4e4d30105558e8351501400a41b8372892 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Mon, 12 May 2003 06:57:32 +0000 Subject: A small patch from metze to fix builds on some platforms ... http://lists.samba.org/pipermail/samba-technical/attachments/20030512/0332258a/vfs-fix-01.obj (This used to be commit 5d643b9d03135effa5c8fd84bf1e54a7bd075e2a) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7bae2ccc80..de682793d5 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -48,7 +48,7 @@ struct vfs_syminfo { static struct vfs_ops default_vfs = { - ops: { + .ops = { /* Disk operations */ vfswrap_dummy_connect, -- cgit From ed1c7282e45b9b962bc2e77a544719bbc506f294 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 09:01:50 +0000 Subject: GCC accepts unnamed initalization of sub-structure. Let's see how AIX behave with this. Previous fix was incorrect. (This used to be commit 13e1bbd803111361bcd9c28b5086277c912c59a6) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index de682793d5..92342a673b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -48,7 +48,7 @@ struct vfs_syminfo { static struct vfs_ops default_vfs = { - .ops = { + { /* Disk operations */ vfswrap_dummy_connect, -- cgit From c9bfb7660bf60d32c51bfe368ce874770adb6f10 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 16:03:16 +0000 Subject: Eliminate NULL pointers from VFS interface. All hooks now really callable, producing either correct result or returning error if the feature isn't supported in the configuration (This used to be commit af0a17349e6986eef2e2fd07b4b9f0bcd33bbe1f) --- source3/smbd/open.c | 4 ++-- source3/smbd/vfs-wrap.c | 20 ++++++++++++++------ source3/smbd/vfs.c | 6 +----- 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 412a0dfc50..959439a1b2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1146,7 +1146,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * selected. */ - if (!file_existed && !def_acl && (conn->vfs.ops.fchmod_acl != NULL)) { + if (!file_existed && !def_acl) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ @@ -1159,7 +1159,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* Attributes need changing. File already existed. */ - if (conn->vfs.ops.fchmod_acl != NULL) { + { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ ret = VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index dd8aad1170..e170effd4e 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -93,10 +93,8 @@ int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char * mess up any inherited ACL bits that were set. JRA. */ int saved_errno = errno; /* We may get ENOSYS */ - if (conn->vfs.ops.chmod_acl != NULL) { - if ((VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) - errno = saved_errno; - } + if ((VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) + errno = saved_errno; } END_PROFILE(syscall_mkdir); @@ -281,7 +279,7 @@ int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char */ - if (conn->vfs.ops.chmod_acl != NULL) { + { int saved_errno = errno; /* We might get ENOSYS */ if ((result = VFS_CHMOD_ACL(conn, path, mode)) == 0) { END_PROFILE(syscall_chmod); @@ -309,7 +307,7 @@ int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t * group owner bits directly. JRA. */ - if (vfs_ops->ops.fchmod_acl != NULL) { + { int saved_errno = errno; /* We might get ENOSYS */ if ((result = VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { END_PROFILE(syscall_chmod); @@ -621,22 +619,32 @@ BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode) { +#ifdef HAVE_NO_ACL + errno = ENOSYS; + return -1; +#else int result; START_PROFILE(chmod_acl); result = chmod_acl(conn, name, mode); END_PROFILE(chmod_acl); return result; +#endif } int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { +#ifdef HAVE_NO_ACL + errno = ENOSYS; + return -1; +#else int result; START_PROFILE(fchmod_acl); result = fchmod_acl(fsp, fd, mode); END_PROFILE(fchmod_acl); return result; +#endif } int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 92342a673b..9f37622c8c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -100,13 +100,9 @@ static struct vfs_ops default_vfs = { vfswrap_set_nt_acl, /* POSIX ACL operations. */ -#if defined(HAVE_NO_ACLS) - NULL, - NULL, -#else vfswrap_chmod_acl, vfswrap_fchmod_acl, -#endif + vfswrap_sys_acl_get_entry, vfswrap_sys_acl_get_tag_type, vfswrap_sys_acl_get_permset, -- cgit From 9308eaf77d53b2d86c071ef07a8e32d9d83b6d12 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 12 May 2003 16:06:05 +0000 Subject: fixing typos in debug statements (This used to be commit f59bcb51cfe4e268ba43245d401d212aefdf2b72) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8dff42471f..415025f649 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -229,7 +229,7 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) /* Register a home dir service for this user */ if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { - DEBUG(3, ("Adding/updating homes service for user '%s' using home direcotry: '%s'\n", + DEBUG(3, ("Adding/updating homes service for user '%s' using home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir); } else { -- cgit From c823b191ab476fc2583d6d6aaa1e2edb09cbb88e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 12 May 2003 18:12:31 +0000 Subject: And finally IDMAP in 3_0 We really need idmap_ldap to have a good solution with ldapsam, porting it from the prvious code is beeing made, the code is really simple to do so I am confident it is not a problem to commit this code in. Not committing it would have been worst. I really would have been able to finish also the group code, maybe we can put it into a followin release after 3.0.0 even if it may be an upgrade problem. The code has been tested and seem to work right, more testing is needed for corner cases. Currently winbind pdc (working only for users and not for groups) is disabled as I was not able to make a complete group code replacement that works somewhat in a week (I have a complete patch, but there are bugs) Simo. (This used to be commit 0e58085978f984436815114a2ec347cf7899a89d) --- source3/smbd/chgpasswd.c | 13 +- source3/smbd/ntquotas.c | 8 +- source3/smbd/nttrans.c | 8 +- source3/smbd/password.c | 11 +- source3/smbd/posix_acls.c | 10 +- source3/smbd/server.c | 6 + source3/smbd/uid.c | 419 +--------------------------------------------- 7 files changed, 27 insertions(+), 448 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 31c4fa7cc9..3d25f33f45 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -478,6 +478,12 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL if (!name) { DEBUG(1, ("NULL username specfied to chgpasswd()!\n")); } + + pass = Get_Pwnam(name); + if (!pass) { + DEBUG(1, ("Username does not exist in system passwd!\n")); + return False; + } if (!oldpass) { oldpass = ""; @@ -528,8 +534,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL } } - pass = Get_Pwnam(name); - #ifdef WITH_PAM if (lp_pam_password_change()) { BOOL ret; @@ -983,9 +987,8 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw * to touch the unix db unless we have admin permission. */ - if(lp_unix_password_sync() && IS_SAM_UNIX_USER(hnd) - && !chgpasswd(pdb_get_username(hnd), - old_passwd, new_passwd, False)) { + if(lp_unix_password_sync() && + !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, False)) { return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index f34d61541c..a23b480627 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -74,7 +74,6 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, int ret; SMB_DISK_QUOTA D; unid_t id; - enum SID_NAME_USE sid_use = SID_NAME_USE_NONE; ZERO_STRUCT(D); @@ -85,7 +84,7 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, id.uid = -1; - if (psid && !sid_to_uid(psid, &id.uid, &sid_use)) { + if (psid && NT_STATUS_IS_ERR(sid_to_uid(psid, &id.uid))) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", sid_string_static(psid))); } @@ -113,7 +112,6 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, int ret; SMB_DISK_QUOTA D; unid_t id; - enum SID_NAME_USE sid_use = SID_NAME_USE_NONE; ZERO_STRUCT(D); if (!fsp||!fsp->conn||!qt) @@ -133,7 +131,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, D.isoftlimit = limit_blk2inodes(D.softlimit); D.ihardlimit = limit_blk2inodes(D.hardlimit); - if (psid && !sid_to_uid(psid, &id.uid, &sid_use)) { + if (psid && NT_STATUS_IS_ERR(sid_to_uid(psid, &id.uid))) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", sid_string_static(psid))); } @@ -187,7 +185,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) continue; } - if (uid_to_sid(&sid,usr->pw_uid)==NULL) { + if (NT_STATUS_IS_ERR(uid_to_sid(&sid, usr->pw_uid))) { DEBUG(0,("uid_to_sid failed for %d\n",usr->pw_uid)); continue; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e7c834f531..fef176cae1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1780,7 +1780,6 @@ static int call_nt_transact_ioctl(connection_struct *conn, DOM_SID sid; uid_t uid; - enum SID_NAME_USE sid_use = 0; size_t sid_len=SID_MAX_SIZE; DEBUG(1,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control)); @@ -1792,10 +1791,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, sid_parse(pdata+4,sid_len,&sid); DEBUGADD(2,("SID: %s\n",sid_string_static(&sid))); - if (!sid_to_uid(&sid, &uid, &sid_use) - ||sid_use!=SID_NAME_USER) { - DEBUG(0,("sid_to_uid: failed, sid[%s] sid_use: %d\n", - sid_string_static(&sid),sid_use)); + if (NT_STATUS_IS_ERR(sid_to_uid(&sid, &uid))) { + DEBUG(0,("sid_to_uid: failed, sid[%s]\n", + sid_string_static(&sid))); uid = (-1); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 415025f649..81849b709a 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -68,7 +68,6 @@ void invalidate_vuid(uint16 vuid) SAFE_FREE(vuser->logon_script); session_yield(vuser); - SAFE_FREE(vuser->session_keystr); free_server_info(&vuser->server_info); @@ -142,15 +141,9 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) /* the next functions should be done by a SID mapping system (SMS) as * the new real sam db won't have reference to unix uids or gids */ - if (!IS_SAM_UNIX_USER(server_info->sam_account)) { - DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); - free(vuser); - free_server_info(&server_info); - return UID_FIELD_INVALID; - } - vuser->uid = pdb_get_uid(server_info->sam_account); - vuser->gid = pdb_get_gid(server_info->sam_account); + vuser->uid = server_info->uid; + vuser->gid = server_info->gid; vuser->n_groups = server_info->n_groups; if (vuser->n_groups) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 34c33af473..228322dc42 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -443,7 +443,6 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, { DOM_SID owner_sid; DOM_SID grp_sid; - enum SID_NAME_USE sid_type; *puser = (uid_t)-1; *pgrp = (gid_t)-1; @@ -469,7 +468,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); - if (!sid_to_uid( &owner_sid, puser, &sid_type)) { + if (NT_STATUS_IS_ERR(sid_to_uid(&owner_sid, puser))) { #if ACL_FORCE_UNMAPPABLE /* this allows take ownership to work reasonably */ extern struct current_user current_user; @@ -489,7 +488,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); - if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) { + if (NT_STATUS_IS_ERR(sid_to_gid( &grp_sid, pgrp))) { #if ACL_FORCE_UNMAPPABLE /* this allows take group ownership to work reasonably */ extern struct current_user current_user; @@ -938,7 +937,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, } for(i = 0; i < dacl->num_aces; i++) { - enum SID_NAME_USE sid_type; SEC_ACE *psa = &dacl->ace[i]; /* @@ -1003,10 +1001,10 @@ static BOOL create_canon_ace_lists(files_struct *fsp, if (nt4_compatible_acls()) psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid, &sid_type)) { + } else if (NT_STATUS_IS_OK(sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid))) { current_ace->owner_type = GID_ACE; current_ace->type = SMB_ACL_GROUP; - } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid, &sid_type)) { + } else if (NT_STATUS_IS_OK(sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid))) { current_ace->owner_type = UID_ACE; current_ace->type = SMB_ACL_USER; } else { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d46be42eba..edc7b57ba3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -839,6 +839,12 @@ static BOOL init_structs(void ) if(!initialize_password_db(False)) exit(1); + if (!idmap_init()) + exit(1); + + if (!idmap_init_wellknown_sids()) + exit(1); + static_init_rpc; init_modules(); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b9cf0de3bd..c68d00025c 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -405,10 +405,9 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER memcpy(final_groups, *pp_groups, current_n_groups * sizeof(gid_t)); for (i = 0; i < ptok->num_sids; i++) { - enum SID_NAME_USE sid_type; gid_t new_grp; - if (sid_to_gid(&ptok->user_sids[i], &new_grp, &sid_type)) { + if (NT_STATUS_IS_OK(sid_to_gid(&ptok->user_sids[i], &new_grp))) { /* * Don't add the gid_t if it is already in the current group * list. Some UNIXen don't like the same group more than once. @@ -530,419 +529,3 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE } return True; } - -/***************************************************************** - Id mapping cache. This is to avoid Winbind mappings already - seen by smbd to be queried too frequently, keeping winbindd - busy, and blocking smbd while winbindd is busy with other - stuff. Written by Michael Steffens , - modified to use linked lists by jra. -*****************************************************************/ - -#define MAX_UID_SID_CACHE_SIZE 100 -#define TURNOVER_UID_SID_CACHE_SIZE 10 -#define MAX_GID_SID_CACHE_SIZE 100 -#define TURNOVER_GID_SID_CACHE_SIZE 10 - -static size_t n_uid_sid_cache = 0; -static size_t n_gid_sid_cache = 0; - -static struct uid_sid_cache { - struct uid_sid_cache *next, *prev; - uid_t uid; - DOM_SID sid; - enum SID_NAME_USE sidtype; -} *uid_sid_cache_head; - -static struct gid_sid_cache { - struct gid_sid_cache *next, *prev; - gid_t gid; - DOM_SID sid; - enum SID_NAME_USE sidtype; -} *gid_sid_cache_head; - -/***************************************************************** - Find a SID given a uid. -*****************************************************************/ - -static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, enum SID_NAME_USE *psidtype, uid_t uid) -{ - struct uid_sid_cache *pc; - - for (pc = uid_sid_cache_head; pc; pc = pc->next) { - if (pc->uid == uid) { - fstring sid; - *psid = pc->sid; - *psidtype = pc->sidtype; - DEBUG(3,("fetch sid from uid cache %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); - DLIST_PROMOTE(uid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Find a uid given a SID. -*****************************************************************/ - -static BOOL fetch_uid_from_cache(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE sidtype) -{ - struct uid_sid_cache *pc; - - for (pc = uid_sid_cache_head; pc; pc = pc->next) { - if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; - *puid = pc->uid; - DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*puid, sid_to_string(sid, psid))); - DLIST_PROMOTE(uid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Store uid to SID mapping in cache. -*****************************************************************/ - -static void store_uid_sid_cache(const DOM_SID *psid, const enum SID_NAME_USE sidtype, uid_t uid) -{ - struct uid_sid_cache *pc; - - if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) { - /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */ - struct uid_sid_cache *pc_next; - size_t i; - - for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next) - ; - for(; pc; pc = pc_next) { - pc_next = pc->next; - DLIST_REMOVE(uid_sid_cache_head,pc); - SAFE_FREE(pc); - n_uid_sid_cache--; - } - } - - pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache)); - if (!pc) - return; - pc->uid = uid; - sid_copy(&pc->sid, psid); - pc->sidtype = sidtype; - DLIST_ADD(uid_sid_cache_head, pc); - n_uid_sid_cache++; -} - -/***************************************************************** - Find a SID given a gid. -*****************************************************************/ - -static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, enum SID_NAME_USE *psidtype, gid_t gid) -{ - struct gid_sid_cache *pc; - - for (pc = gid_sid_cache_head; pc; pc = pc->next) { - if (pc->gid == gid) { - fstring sid; - *psid = pc->sid; - *psidtype = pc->sidtype; - DEBUG(3,("fetch sid from gid cache %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); - DLIST_PROMOTE(gid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Find a gid given a SID. -*****************************************************************/ - -static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE sidtype) -{ - struct gid_sid_cache *pc; - - for (pc = gid_sid_cache_head; pc; pc = pc->next) { - if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; - *pgid = pc->gid; - DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*pgid, sid_to_string(sid, psid))); - DLIST_PROMOTE(gid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Store gid to SID mapping in cache. -*****************************************************************/ - -static void store_gid_sid_cache(const DOM_SID *psid, const enum SID_NAME_USE sidtype, gid_t gid) -{ - struct gid_sid_cache *pc; - - if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { - /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ - struct gid_sid_cache *pc_next; - size_t i; - - for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) - ; - for(; pc; pc = pc_next) { - pc_next = pc->next; - DLIST_REMOVE(gid_sid_cache_head,pc); - SAFE_FREE(pc); - n_gid_sid_cache--; - } - } - - pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); - if (!pc) - return; - pc->gid = gid; - sid_copy(&pc->sid, psid); - pc->sidtype = sidtype; - DLIST_ADD(gid_sid_cache_head, pc); - n_gid_sid_cache++; -} - - -/***************************************************************** - *THE CANONICAL* convert uid_t to SID function. - Tries winbind first - then uses local lookup. - Returns SID pointer. -*****************************************************************/ - -DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) -{ - uid_t low, high; - enum SID_NAME_USE sidtype; - fstring sid; - - if (fetch_sid_from_uid_cache(psid, &sidtype, uid)) - return psid; - - if (lp_winbind_uid(&low, &high) && uid >= low && uid <= high) { - if (winbind_uid_to_sid(psid, uid)) { - - DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); - - if (psid) - store_uid_sid_cache(psid, SID_NAME_USER, uid); - return psid; - } - } - - /* Make sure we report failure, (when psid == NULL) */ - become_root(); - psid = local_uid_to_sid(psid, uid); - unbecome_root(); - - DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); - if (psid) - store_uid_sid_cache(psid, SID_NAME_USER, uid); - - return psid; -} - -/***************************************************************** - *THE CANONICAL* convert gid_t to SID function. - Tries winbind first - then uses local lookup. - Returns SID pointer. -*****************************************************************/ - -DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) -{ - gid_t low, high; - enum SID_NAME_USE sidtype; - fstring sid; - - if (fetch_sid_from_gid_cache(psid, &sidtype, gid)) - return psid; - - if (lp_winbind_gid(&low, &high) && gid >= low && gid <= high) { - if (winbind_gid_to_sid(psid, gid)) { - - DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); - - if (psid) - store_gid_sid_cache(psid, SID_NAME_DOM_GRP, gid); - return psid; - } - } - - /* Make sure we report failure, (when psid == NULL) */ - become_root(); - psid = local_gid_to_sid(psid, gid); - unbecome_root(); - DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); - if (psid) - store_gid_sid_cache(psid, SID_NAME_DOM_GRP, gid); - - return psid; -} - -/***************************************************************** - *THE CANONICAL* convert SID to uid function. - Tries winbind first - then uses local lookup. - Returns True if this name is a user sid and the conversion - was done correctly, False if not. sidtype is set by this function. -*****************************************************************/ - -BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) -{ - fstring sid_str; - - if (fetch_uid_from_cache(puid, psid, *sidtype)) - return True; - - /* if we know its local then don't try winbindd */ - if (sid_compare_domain(get_global_sam_sid(), psid) == 0) { - BOOL result; - become_root(); - result = local_sid_to_uid(puid, psid, sidtype); - unbecome_root(); - if (result) - store_uid_sid_cache(psid, *sidtype, *puid); - return result; - } - -/* (tridge) I commented out the slab of code below in order to support foreign SIDs - Do we really need to validate the type of SID we have in this case? -*/ -#if 0 - fstring dom_name, name; - enum SID_NAME_USE name_type; - - *sidtype = SID_NAME_UNKNOWN; - /* - * First we must look up the name and decide if this is a user sid. - */ - - if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) { - BOOL result; - DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", - sid_to_string(sid_str, psid) )); - - become_root(); - result = local_sid_to_uid(puid, psid, sidtype); - unbecome_root(); - return result; - } - - /* - * Ensure this is a user sid. - */ - - if (name_type != SID_NAME_USER) { - DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n", - (unsigned int)name_type )); - return False; - } -#endif - *sidtype = SID_NAME_USER; - - /* - * Get the uid for this SID. - */ - - if (!winbind_sid_to_uid(puid, psid)) { - BOOL result; - DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n", - sid_to_string(sid_str, psid) )); - become_root(); - result = local_sid_to_uid(puid, psid, sidtype); - unbecome_root(); - if (result) - store_uid_sid_cache(psid, *sidtype, *puid); - return result; - } - - DEBUG(10,("sid_to_uid: winbindd %s -> %u\n", - sid_to_string(sid_str, psid), - (unsigned int)*puid )); - - store_uid_sid_cache(psid, *sidtype, *puid); - return True; -} - -/***************************************************************** - *THE CANONICAL* convert SID to gid function. - Tries winbind first - then uses local lookup. - Returns True if this name is a user sid and the conversion - was done correctly, False if not. -*****************************************************************/ - -BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) -{ - fstring dom_name, name, sid_str; - enum SID_NAME_USE name_type; - - *sidtype = SID_NAME_UNKNOWN; - - if (fetch_gid_from_cache(pgid, psid, *sidtype)) - return True; - - /* - * First we must look up the name and decide if this is a group sid. - */ - - /* if we know its local then don't try winbindd */ - if (sid_compare_domain(get_global_sam_sid(), psid) == 0) { - BOOL result; - become_root(); - result = local_sid_to_gid(pgid, psid, sidtype); - unbecome_root(); - if (result) - store_gid_sid_cache(psid, *sidtype, *pgid); - return result; - } - - if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { - DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n", - sid_to_string(sid_str, psid) )); - /* this was probably a foreign sid - assume its a group rid - and continue */ - name_type = SID_NAME_DOM_GRP; - } - - /* - * Ensure this is a group sid. - */ - - if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { - DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", - (unsigned int)name_type )); - - return False; - } - - *sidtype = name_type; - - /* - * Get the gid for this SID. - */ - - if (!winbind_sid_to_gid(pgid, psid)) { - DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n", - sid_to_string(sid_str, psid) )); - return False; - } - - DEBUG(10,("sid_to_gid: winbindd %s -> %u\n", - sid_to_string(sid_str, psid), - (unsigned int)*pgid )); - - store_gid_sid_cache(psid, *sidtype, *pgid); - return True; -} - -- cgit From 6abef0810007c317c3ee866eb3933ce2c696085f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 May 2003 21:27:54 +0000 Subject: Fix obvious compiler warnings. Jeremy. (This used to be commit 2a6d0c2481c3c34351e57c30a85004babdbf99b0) --- source3/smbd/vfs-wrap.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index e170effd4e..9f0995d398 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -297,7 +297,6 @@ int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { int result; - struct vfs_ops *vfs_ops = &fsp->conn->vfs; START_PROFILE(syscall_fchmod); -- cgit From b47963ae5a90ac54c021c9dd6528079180174cc4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 13 May 2003 15:29:23 +0000 Subject: Restore a number of fixes that idra removed when he merged his idmap-and-the-rest from HEAD. These are correctness fixes that were already in 3.0, and a memory leak fix. The pdb_ldap changes are held back at jerry's request (he is also playing with pdb_ldap ATM). Andrew Bartlett (This used to be commit c7d5e336bd91514a02974044742b058be387e490) --- source3/smbd/password.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 81849b709a..283eed73ef 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -68,6 +68,7 @@ void invalidate_vuid(uint16 vuid) SAFE_FREE(vuser->logon_script); session_yield(vuser); + SAFE_FREE(vuser->session_keystr); free_server_info(&vuser->server_info); -- cgit From 402fbc518a5489b33f1c5eafb8e6acb9ee5addbd Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 14 May 2003 00:46:43 +0000 Subject: spelling (This used to be commit 865c11275685c85124b506c9bbd2a8bde2e760b9) --- source3/smbd/chgpasswd.c | 4 ++-- source3/smbd/service.c | 2 +- source3/smbd/session.c | 2 +- source3/smbd/sesssetup.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 3d25f33f45..5c1d9a79a6 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -980,10 +980,10 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw * the /etc/passwd database first. Return failure if this cannot * be done. * - * This occurs before the oem change, becouse we don't want to + * This occurs before the oem change, because we don't want to * update it if chgpasswd failed. * - * Conditional on lp_unix_password_sync() becouse we don't want + * Conditional on lp_unix_password_sync() because we don't want * to touch the unix db unless we have admin permission. */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0e4c87c7fb..4d515e90f5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -790,7 +790,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, if(lp_security() != SEC_SHARE) { DATA_BLOB no_pw = data_blob(NULL, 0); if (vuser->homes_snum == -1) { - DEBUG(2, ("[homes] share not available for this user becouse it was not found or created at session setup time\n")); + DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n")); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index ac06b9872d..b7f3bc43e7 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -100,7 +100,7 @@ BOOL session_claim(user_struct *vuser) } /* If 'hostname lookup' == yes, then do the DNS lookup. This is - needed becouse utmp and PAM both expect DNS names + needed because utmp and PAM both expect DNS names client_name() handles this case internally. */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a9842424a5..fc223ecf37 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -644,7 +644,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (*user) { if (global_spnego_negotiated) { - /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */ + /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); return ERROR_NT(NT_STATUS_UNSUCCESSFUL); -- cgit From bc2a3748e9caa8f60f7c2387e7eecd7fb3fae899 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 14 May 2003 10:59:01 +0000 Subject: Prefix VFS API macros with SMB_ for consistency and to avoid problems with VFS_ macros at system side. We currently have one clash with AIX and its VFS_LOCK. Compiled and tested -- no new functionality or code, just plain rename of macros for yet-unreleased VFS API version. Needs to be done before a24 is out (This used to be commit c2689ed118b490e49497a76ed6a2251262018769) --- source3/smbd/close.c | 2 +- source3/smbd/dir.c | 18 +++--- source3/smbd/dosmode.c | 14 ++--- source3/smbd/fileio.c | 14 ++--- source3/smbd/filename.c | 8 +-- source3/smbd/notify_hash.c | 4 +- source3/smbd/ntquotas.c | 4 +- source3/smbd/nttrans.c | 4 +- source3/smbd/open.c | 20 +++---- source3/smbd/posix_acls.c | 134 ++++++++++++++++++++++----------------------- source3/smbd/reply.c | 54 +++++++++--------- source3/smbd/service.c | 4 +- source3/smbd/statcache.c | 2 +- source3/smbd/trans2.c | 54 +++++++++--------- source3/smbd/vfs-wrap.c | 26 ++++----- source3/smbd/vfs.c | 46 ++++++++-------- 16 files changed, 204 insertions(+), 204 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index a5d74cedb1..1be13270ba 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -185,7 +185,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (normal_close && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(VFS_UNLINK(conn,fsp->fsp_name) != 0) { + if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 48ddf86837..910ab35de8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -643,7 +643,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (VFS_STAT(conn, pathreal, &sbuf) != 0) { + if (SMB_VFS_STAT(conn, pathreal, &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; } @@ -700,7 +700,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (VFS_STAT(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ @@ -715,7 +715,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); close_file(fsp, True); /* No access if SD get failed. */ @@ -753,7 +753,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (VFS_STAT(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ @@ -768,7 +768,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); close_file(fsp, False); /* No access if SD get failed. */ @@ -794,7 +794,7 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (VFS_STAT(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) return True; if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) @@ -811,7 +811,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) { Dir *dirp; const char *n; - DIR *p = VFS_OPENDIR(conn,name); + DIR *p = SMB_VFS_OPENDIR(conn,name); int used=0; if (!p) @@ -819,7 +819,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { DEBUG(0,("Out of memory in OpenDir\n")); - VFS_CLOSEDIR(conn,p); + SMB_VFS_CLOSEDIR(conn,p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; @@ -912,7 +912,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp->numentries++; } - VFS_CLOSEDIR(conn,p); + SMB_VFS_CLOSEDIR(conn,p); return((void *)dirp); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 6365db8f1e..aaee41b546 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -56,7 +56,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) dname = parent_dirname(fname); DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (VFS_STAT(conn,dname,&sbuf) != 0) { + if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) { DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); return(0); /* *** shouldn't happen! *** */ } @@ -191,7 +191,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST if (!st) { st = &st1; - if (VFS_STAT(conn,fname,st)) + if (SMB_VFS_STAT(conn,fname,st)) return(-1); } @@ -235,7 +235,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if ((ret = VFS_CHMOD(conn,fname,unixmode)) == 0) + if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -262,7 +262,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST if (!fsp) return -1; become_root(); - ret = VFS_FCHMOD(fsp, fsp->fd, unixmode); + ret = SMB_VFS_FCHMOD(fsp, fsp->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); } @@ -283,7 +283,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(VFS_UTIME(conn,fname, times) == 0) + if(SMB_VFS_UTIME(conn,fname, times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -298,7 +298,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(VFS_STAT(conn,fname,&sb) != 0) + if(SMB_VFS_STAT(conn,fname,&sb) != 0) return -1; /* Check if we have write access. */ @@ -311,7 +311,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = VFS_UTIME(conn,fname, times); + ret = SMB_VFS_UTIME(conn,fname, times); unbecome_root(); } } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 5021f54fb4..6be5f6af7d 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -32,7 +32,7 @@ static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { SMB_OFF_T seek_ret; - seek_ret = VFS_LSEEK(fsp,fsp->fd,pos,SEEK_SET); + seek_ret = SMB_VFS_LSEEK(fsp,fsp->fd,pos,SEEK_SET); if(seek_ret == -1) { DEBUG(0,("seek_file: (%s) sys_lseek failed. Error was %s\n", @@ -101,7 +101,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #ifdef DMF_FIX int numretries = 3; tryagain: - readret = VFS_READ(fsp,fsp->fd,data,n); + readret = SMB_VFS_READ(fsp,fsp->fd,data,n); if (readret == -1) { if ((errno == EAGAIN) && numretries) { DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); @@ -112,7 +112,7 @@ tryagain: return -1; } #else /* NO DMF fix. */ - readret = VFS_READ(fsp,fsp->fd,data,n); + readret = SMB_VFS_READ(fsp,fsp->fd,data,n); if (readret == -1) return -1; #endif @@ -181,7 +181,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) SMB_STRUCT_STAT st; fsp->modified = True; - if (VFS_FSTAT(fsp,fsp->fd,&st) == 0) { + if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); fsp->size = (SMB_BIG_UINT)st.st_size; if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) @@ -760,7 +760,7 @@ void sync_file(connection_struct *conn, files_struct *fsp) { if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { flush_write_cache(fsp, SYNC_FLUSH); - VFS_FSYNC(fsp,fsp->fd); + SMB_VFS_FSYNC(fsp,fsp->fd); } } @@ -772,7 +772,7 @@ void sync_file(connection_struct *conn, files_struct *fsp) int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) { if (fsp->fd == -1) - return VFS_STAT(fsp->conn, fsp->fsp_name, pst); + return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst); else - return VFS_FSTAT(fsp,fsp->fd, pst); + return SMB_VFS_FSTAT(fsp,fsp->fd, pst); } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 6622a6ba63..ad107f9c3e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -178,7 +178,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * stat the name - if it exists then we are all done! */ - if (VFS_STAT(conn,name,&st) == 0) { + if (SMB_VFS_STAT(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; @@ -234,7 +234,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Check if the name exists up to this point. */ - if (VFS_STAT(conn,name, &st) == 0) { + if (SMB_VFS_STAT(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -342,7 +342,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * JRA. */ - if (VFS_STAT(conn,name, &st) == 0) { + if (SMB_VFS_STAT(conn,name, &st) == 0) { *pst = st; } else { ZERO_STRUCT(st); @@ -418,7 +418,7 @@ BOOL check_name(pstring name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (VFS_LSTAT(conn,name,&statbuf) != -1) && + if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 913a4973f8..810e5079ba 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -48,7 +48,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, ZERO_STRUCTP(data); - if(VFS_STAT(conn,path, &st) == -1) + if(SMB_VFS_STAT(conn,path, &st) == -1) return False; data->modify_time = st.st_mtime; @@ -100,7 +100,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, /* * Do the stat - but ignore errors. */ - VFS_STAT(conn,full_name, &st); + SMB_VFS_STAT(conn,full_name, &st); /* * Always sum the times. diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index a23b480627..f6f1479481 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -89,7 +89,7 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, sid_string_static(psid))); } - ret = VFS_GET_QUOTA(fsp->conn, qtype, id, &D); + ret = SMB_VFS_GET_QUOTA(fsp->conn, qtype, id, &D); if (psid) qt->sid = *psid; @@ -136,7 +136,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, sid_string_static(psid))); } - ret = VFS_SET_QUOTA(fsp->conn, qtype, id, &D); + ret = SMB_VFS_SET_QUOTA(fsp->conn, qtype, id, &D); return ret; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fef176cae1..3ddf191ef6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1075,7 +1075,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu if (psd->off_dacl==0) security_info_sent &= ~DACL_SECURITY_INFORMATION; - ret = VFS_FSET_NT_ACL( fsp, fsp->fd, security_info_sent, psd); + ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fd, security_info_sent, psd); if (!ret) { talloc_destroy(mem_ctx); @@ -1598,7 +1598,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if (!lp_nt_acl_support(SNUM(conn))) sd_size = get_null_nt_acl(mem_ctx, &psd); else - sd_size = VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); if (sd_size == 0) { talloc_destroy(mem_ctx); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 959439a1b2..e3bd530c17 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,13 +38,13 @@ static int fd_open(struct connection_struct *conn, char *fname, flags |= O_NOFOLLOW; #endif - fd = VFS_OPEN(conn,fname,flags,mode); + fd = SMB_VFS_OPEN(conn,fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr_m(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = VFS_OPEN(conn,fname,flags,mode); + fd = SMB_VFS_OPEN(conn,fname,flags,mode); } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, @@ -186,9 +186,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, int ret; if (fsp->fd == -1) - ret = VFS_STAT(conn, fname, psbuf); + ret = SMB_VFS_STAT(conn, fname, psbuf); else { - ret = VFS_FSTAT(fsp,fsp->fd,psbuf); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); @@ -259,7 +259,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); return -1; } else { - return VFS_FTRUNCATE(fsp,fsp->fd,0); + return SMB_VFS_FTRUNCATE(fsp,fsp->fd,0); } } @@ -1071,7 +1071,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* * We are modifing the file after open - update the stat struct.. */ - if ((truncate_unless_locked(conn,fsp) == -1) || (VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { + if ((truncate_unless_locked(conn,fsp) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1150,7 +1150,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - if (VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ } else if (new_mode) { @@ -1161,7 +1161,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - ret = VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); + ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ @@ -1172,7 +1172,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } - if ((ret == -1) && (VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) + if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", fname, (int)new_mode)); } @@ -1285,7 +1285,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } - if(VFS_STAT(conn,fname, psbuf) != 0) { + if(SMB_VFS_STAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 228322dc42..aaf71c82ca 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -158,9 +158,9 @@ static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET { mode_t ret = 0; - ret |= (VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0); - ret |= (VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0); - ret |= (VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); + ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0); + ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0); + ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); return ret; } @@ -190,18 +190,18 @@ static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset) { - if (VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1) + if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1) return -1; if (mode & S_IRUSR) { - if (VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) return -1; } if (mode & S_IWUSR) { - if (VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) return -1; } if (mode & S_IXUSR) { - if (VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) return -1; } return 0; @@ -648,7 +648,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, /* * When setting ACLs and missing one out of SMB_ACL_USER_OBJ, * SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER, try to retrieve current - * values. For user and other a simple VFS_STAT would do, but + * values. For user and other a simple SMB_VFS_STAT would do, but * we would get mask instead of group. Let's do it via ACL. */ @@ -658,13 +658,13 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, int entry_id = SMB_ACL_FIRST_ENTRY; if(fsp->is_directory || fsp->fd == -1) { - current_posix_acl = VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); + current_posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); } else { - current_posix_acl = VFS_SYS_ACL_GET_FD(fsp, fsp->fd); + current_posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); } if (current_posix_acl) { - while (VFS_SYS_ACL_GET_ENTRY(conn, current_posix_acl, entry_id, &entry) == 1) { + while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, current_posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; @@ -673,10 +673,10 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ - if (VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) continue; - if (VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) continue; switch(tagtype) { @@ -694,7 +694,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, break; } } - VFS_SYS_ACL_FREE_ACL(conn, current_posix_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, current_posix_acl); } else { DEBUG(10,("ensure_canon_entry_valid: failed to retrieve current ACL of %s\n", fsp->fsp_name)); @@ -1656,7 +1656,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ SMB_ACL_ENTRY_T entry; size_t ace_count; - while ( posix_acl && (VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) { + while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; DOM_SID sid; @@ -1668,10 +1668,10 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ - if (VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) continue; - if (VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) continue; /* Decide which SID to use based on the ACL type. */ @@ -1684,7 +1684,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_USER: { - uid_t *puid = (uid_t *)VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (puid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get uid.\n")); continue; @@ -1701,7 +1701,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; - VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); + SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); break; } case SMB_ACL_GROUP_OBJ: @@ -1712,7 +1712,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_GROUP: { - gid_t *pgid = (gid_t *)VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (pgid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get gid.\n")); continue; @@ -1720,7 +1720,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ gid_to_sid( &sid, *pgid); unix_ug.gid = *pgid; owner_type = GID_ACE; - VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype); + SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype); break; } case SMB_ACL_MASK: @@ -1805,7 +1805,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau { connection_struct *conn = fsp->conn; BOOL ret = False; - SMB_ACL_T the_acl = VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1); + SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1); canon_ace *p_ace; int i; SMB_ACL_ENTRY_T mask_entry; @@ -1863,7 +1863,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Get the entry for this ACE. */ - if (VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) { + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1889,7 +1889,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * First tell the entry what type of ACE this is. */ - if (VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) { + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1901,7 +1901,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) { - if (VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { + if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1912,7 +1912,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Convert the mode_t perms in the canon_ace to a POSIX permset. */ - if (VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) { + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1928,7 +1928,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * ..and apply them to the entry. */ - if (VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) { + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1939,17 +1939,17 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau } if (needs_mask && !got_mask_entry) { - if (VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) { + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); goto done; } - if (VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) { + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); goto done; } - if (VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) { + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); goto done; } @@ -1959,7 +1959,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } - if (VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) { + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); goto done; } @@ -1969,7 +1969,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Check if the ACL is valid. */ - if (VFS_SYS_ACL_VALID(conn, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_VALID(conn, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", strerror(errno) )); @@ -1981,7 +1981,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if(default_ace || fsp->is_directory || fsp->fd == -1) { - if (VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2000,7 +2000,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } } else { - if (VFS_SYS_ACL_SET_FD(fsp, fsp->fd, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fd, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2024,7 +2024,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau done: if (the_acl != NULL) - VFS_SYS_ACL_FREE_ACL(conn, the_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); return ret; } @@ -2055,8 +2055,8 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T acl) if (!acl) return NULL; - if (VFS_SYS_ACL_GET_ENTRY(conn, acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { - VFS_SYS_ACL_FREE_ACL(conn, acl); + if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, acl); return NULL; } return acl; @@ -2222,34 +2222,34 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) if(fsp->is_directory || fsp->fd == -1) { /* Get the stat struct for the owner info. */ - if(VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { + if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; } /* * Get the ACL from the path. */ - posix_acl = VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); + posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); /* * If it's a directory get the default POSIX ACL. */ if(fsp->is_directory) { - dir_acl = VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); dir_acl = free_empty_sys_acl(conn, dir_acl); } } else { /* Get the stat struct for the owner info. */ - if(VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { + if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { return 0; } /* * Get the ACL from the fd. */ - posix_acl = VFS_SYS_ACL_GET_FD(fsp, fsp->fd); + posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); } DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", @@ -2477,9 +2477,9 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) done: if (posix_acl) - VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); if (dir_acl) - VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); SAFE_FREE(nt_ace_list); @@ -2503,14 +2503,14 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ SMB_STRUCT_STAT st; /* try the direct way first */ - ret = VFS_CHOWN(conn, fname, uid, gid); + ret = SMB_VFS_CHOWN(conn, fname, uid, gid); if (ret == 0) return 0; if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) return -1; - if (VFS_STAT(conn,fname,&st)) + if (SMB_VFS_STAT(conn,fname,&st)) return -1; fsp = open_file_fchmod(conn,fname,&st); @@ -2525,7 +2525,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ become_root(); /* Keep the current file gid the same. */ - ret = VFS_FCHOWN(fsp, fsp->fd, uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, fsp->fd, uid, (gid_t)-1); unbecome_root(); close_file_fchmod(fsp); @@ -2568,10 +2568,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory || fsp->fd == -1) { - if(VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) + if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - if(VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) + if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) return False; } @@ -2617,7 +2617,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) { + if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) { return False; } } else { @@ -2625,9 +2625,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) int ret; if(fsp->fd == -1) - ret = VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf); + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf); else - ret = VFS_FSTAT(fsp,fsp->fd,&sbuf); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf); if(ret != 0) return False; @@ -2695,7 +2695,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * No default ACL - delete one if it exists. */ - if (VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) { + if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) { DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); @@ -2724,7 +2724,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)posix_perms )); - if(VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) { + if(SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) { DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); free_canon_ace_list(file_ace_list); @@ -2766,7 +2766,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo SMB_ACL_ENTRY_T entry; int num_entries = 0; - while ( VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { + while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; mode_t perms; @@ -2775,10 +2775,10 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo if (entry_id == SMB_ACL_FIRST_ENTRY) entry_id = SMB_ACL_NEXT_ENTRY; - if (VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) return -1; - if (VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) return -1; num_entries++; @@ -2809,7 +2809,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo if (map_acl_perms_to_permset(conn, perms, &permset) == -1) return -1; - if (VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1) + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1) return -1; } @@ -2835,17 +2835,17 @@ static int copy_access_acl(connection_struct *conn, const char *from, const char SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL) + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl); + ret = SMB_VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl); done: - VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); return ret; } @@ -2887,17 +2887,17 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = VFS_SYS_ACL_GET_FD(fsp, fd)) == NULL) + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fd)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = VFS_SYS_ACL_SET_FD(fsp, fd, posix_acl); + ret = SMB_VFS_SYS_ACL_SET_FD(fsp, fd, posix_acl); done: - VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); return ret; } @@ -2907,14 +2907,14 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { - SMB_ACL_T dir_acl = VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); + SMB_ACL_T dir_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); BOOL has_acl = False; SMB_ACL_ENTRY_T entry; - if (dir_acl != NULL && (VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) + if (dir_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) has_acl = True; if (dir_acl) - VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); return has_acl; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 49a9b934b0..7a0cc0287a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -399,7 +399,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); if (check_name(name,conn)) { - if (VALID_STAT(sbuf) || VFS_STAT(conn,name,&sbuf) == 0) + if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) if (!(ok = S_ISDIR(sbuf.st_mode))) errno = ENOTDIR; } @@ -458,7 +458,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || VFS_STAT(conn,fname,&sbuf) == 0) { + if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; mtime = sbuf.st_mtime; @@ -553,7 +553,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz SMB_BIG_UINT dfree,dsize,bsize; START_PROFILE(SMBdskattr); - VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -1128,7 +1128,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - VFS_STAT(conn,fname,&sbuf); + SMB_VFS_STAT(conn,fname,&sbuf); /* Open file in dos compatibility share mode. */ /* We should fail if file does not exist. */ @@ -1227,7 +1227,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - if (VFS_LSTAT(conn,fname,&sbuf) != 0) + if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND; fmode = dos_mode(conn,fname,&sbuf); @@ -1313,7 +1313,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) error = can_delete(directory,conn,dirtype); if (!NT_STATUS_IS_OK(error)) return error; - if (VFS_UNLINK(conn,directory) == 0) { + if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; } } else { @@ -1343,7 +1343,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype); if (!NT_STATUS_IS_OK(error)) continue; - if (VFS_UNLINK(conn,fname) == 0) count++; + if (SMB_VFS_UNLINK(conn,fname) == 0) count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dirptr); @@ -1429,7 +1429,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st header.length = 4; header.free = NULL; - if ( VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { + if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { /* * Special hack for broken Linux with no 64 bit clean sendfile. If we * return ENOSYS then pretend we just got a normal read. @@ -1554,7 +1554,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (VFS_FSTAT(fsp,fsp->fd,&st) == 0) + if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -1723,7 +1723,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length SMB_STRUCT_STAT sbuf; DATA_BLOB header; - if(VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) + if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); if (startpos > sbuf.st_size) @@ -1750,7 +1750,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length header.length = data - outbuf; header.free = NULL; - if ( VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { + if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { /* * Special hack for broken Linux with no 64 bit clean sendfile. If we * return ENOSYS then pretend we just got a normal read. @@ -2262,7 +2262,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int break; } - if((res = VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { + if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { /* * Check for the special case where a seek before the start * of the file sets the offset to zero. Added in the CIFS spec, @@ -2274,7 +2274,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int if(umode == SEEK_CUR) { - if((current_pos = VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) { + if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) { END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2285,7 +2285,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; - if(VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { + if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2294,7 +2294,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if(current_pos < 0) - res = VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); + res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); } if(res == -1) { @@ -2901,7 +2901,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(VFS_LSTAT(conn,fullname, &st) != 0) { + if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) { ret = True; break; } @@ -2911,11 +2911,11 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) ret = True; break; } - if(VFS_RMDIR(conn,fullname) != 0) { + if(SMB_VFS_RMDIR(conn,fullname) != 0) { ret = True; break; } - } else if(VFS_UNLINK(conn,fullname) != 0) { + } else if(SMB_VFS_UNLINK(conn,fullname) != 0) { ret = True; break; } @@ -2932,7 +2932,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) { BOOL ok; - ok = (VFS_RMDIR(conn,directory) == 0); + ok = (SMB_VFS_RMDIR(conn,directory) == 0); if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { /* * Check to see if the only thing in this directory are @@ -2974,21 +2974,21 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(VFS_LSTAT(conn,fullname, &st) != 0) + if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) { if(lp_recursive_veto_delete(SNUM(conn))) { if(recursive_rmdir(conn, fullname) != 0) break; } - if(VFS_RMDIR(conn,fullname) != 0) + if(SMB_VFS_RMDIR(conn,fullname) != 0) break; - } else if(VFS_UNLINK(conn,fullname) != 0) + } else if(SMB_VFS_UNLINK(conn,fullname) != 0) break; } CloseDir(dirptr); /* Retry the rmdir */ - ok = (VFS_RMDIR(conn,directory) == 0); + ok = (SMB_VFS_RMDIR(conn,directory) == 0); } else { CloseDir(dirptr); } @@ -3284,7 +3284,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_NAME_COLLISION; } - if(VFS_RENAME(conn,directory, newname) == 0) { + if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); return NT_STATUS_OK; @@ -3351,7 +3351,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", continue; } - if (!VFS_RENAME(conn,fname,destname)) + if (!SMB_VFS_RENAME(conn,fname,destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3445,7 +3445,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!target_is_directory && count) ofun = FILE_EXISTS_OPEN; - if (VFS_STAT(conn,dest,&sbuf2) == -1) + if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) ZERO_STRUCTP(&sbuf2); fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), @@ -3457,7 +3457,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) { + if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); /* * Stop the copy from occurring. diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4d515e90f5..31bb343474 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -704,7 +704,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Invoke VFS make connection hook */ - if (VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); change_to_root_user(); conn_free(conn); @@ -871,7 +871,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) lp_servicename(SNUM(conn)))); /* Call VFS disconnect hook */ - VFS_DISCONNECT(conn); + SMB_VFS_DISCONNECT(conn); yield_connection(conn, lp_servicename(SNUM(conn))); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 5c77474fec..79758bcfe2 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -242,7 +242,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } else { scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); - if(VFS_STAT(conn,scp->translated_path, pst) != 0) { + if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2f2820e76b..731fb9643b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -551,12 +551,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcat(pathreal,dname); if (INFO_LEVEL_IS_UNIX(info_level)) { - if (VFS_LSTAT(conn,pathreal,&sbuf) != 0) { + if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n", pathreal,strerror(errno))); continue; } - } else if (VFS_STAT(conn,pathreal,&sbuf) != 0) { + } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { /* Needed to show the msdfs symlinks as * directories */ @@ -1324,7 +1324,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(VFS_STAT(conn,".",&st)!=0) { + if(SMB_VFS_STAT(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return ERROR_DOS(ERRSRV,ERRinvdevice); } @@ -1341,7 +1341,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; - VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); SIVAL(pdata,l1_cSectorUnit,bsize/512); SIVAL(pdata,l1_cUnit,dsize); @@ -1416,7 +1416,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; - VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1446,7 +1446,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; - VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1793,13 +1793,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ - if (VFS_LSTAT(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); + if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } - } else if (!VALID_STAT(sbuf) && VFS_STAT(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -1812,11 +1812,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_FSP(fsp,conn); pstrcpy(fname, fsp->fsp_name); - if (VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) + if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); delete_pending = fsp->delete_on_close; @@ -1843,13 +1843,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ - if (VFS_LSTAT(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); + if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } - } else if (!VALID_STAT(sbuf) && VFS_STAT(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -2242,7 +2242,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, #else return(UNIXERROR(ERRDOS,ERRbadlink)); #endif - len = VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ + len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ if (len == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); buffer[len] = 0; @@ -2366,7 +2366,7 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in pstrcpy(link_dest, "./"); } - if (VFS_REALPATH(conn,link_dest,resolved_name) == NULL) + if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL) return -1; pstrcpy(link_dest, resolved_name); @@ -2463,7 +2463,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, pstrcpy(fname, fsp->fsp_name); fd = fsp->fd; - if (VFS_FSTAT(fsp,fd,&sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -2655,7 +2655,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); ret = vfs_allocate_file_space(new_fsp, allocation_size); - if (VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) { + if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", new_fsp->fnum, strerror(errno))); ret = -1; @@ -2663,7 +2663,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, close_file(new_fsp,True); } else { ret = vfs_allocate_file_space(fsp, allocation_size); - if (VFS_FSTAT(fsp,fd,&new_sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); ret = -1; @@ -2803,7 +2803,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", 0%o for file %s\n", (double)dev, unixmode, fname )); /* Ok - do the mknod. */ - if (VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0) + if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); inherit_access_acl(conn, fname, unixmode); @@ -2822,7 +2822,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (raw_unixmode != SMB_MODE_NO_CHANGE) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", (unsigned int)unixmode, fname )); - if (VFS_CHMOD(conn,fname,unixmode) != 0) + if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2833,7 +2833,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", (unsigned int)set_owner, fname )); - if (VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) + if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2844,7 +2844,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", (unsigned int)set_owner, fname )); - if (VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) + if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } break; @@ -2871,7 +2871,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", fname, link_dest )); - if (VFS_SYMLINK(conn,link_dest,fname) != 0) + if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); @@ -2896,7 +2896,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, link_dest )); - if (VFS_LINK(conn,link_dest,fname) != 0) + if (SMB_VFS_LINK(conn,link_dest,fname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 9f0995d398..64e29bbe43 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -93,7 +93,7 @@ int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char * mess up any inherited ACL bits that were set. JRA. */ int saved_errno = errno; /* We may get ENOSYS */ - if ((VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) + if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) errno = saved_errno; } @@ -281,7 +281,7 @@ int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char { int saved_errno = errno; /* We might get ENOSYS */ - if ((result = VFS_CHMOD_ACL(conn, path, mode)) == 0) { + if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) { END_PROFILE(syscall_chmod); return result; } @@ -308,7 +308,7 @@ int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t { int saved_errno = errno; /* We might get ENOSYS */ - if ((result = VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { + if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { END_PROFILE(syscall_chmod); return result; } @@ -391,14 +391,14 @@ int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) { SMB_STRUCT_STAT st; - SMB_OFF_T currpos = VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); unsigned char zero_space[4096]; SMB_OFF_T space_to_write; if (currpos == -1) return -1; - if (VFS_FSTAT(fsp, fd, &st) == -1) + if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) return -1; space_to_write = len - st.st_size; @@ -416,7 +416,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs return sys_ftruncate(fd, len); /* Write out the real space on disk. */ - if (VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) + if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) return -1; space_to_write = len - st.st_size; @@ -426,7 +426,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs SMB_OFF_T retlen; SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); - retlen = VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write); + retlen = SMB_VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write); if (retlen <= 0) return -1; @@ -434,7 +434,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs } /* Seek to where we were */ - if (VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) + if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) return -1; return 0; @@ -468,7 +468,7 @@ int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot extend a file with ftruncate. Provide alternate implementation for this */ - currpos = VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); if (currpos == -1) { goto done; } @@ -477,7 +477,7 @@ int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ size in which case the ftruncate above should have succeeded or shorter, in which case seek to len - 1 and write 1 byte of zero */ - if (VFS_FSTAT(fsp, fd, &st) == -1) { + if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) { goto done; } @@ -498,14 +498,14 @@ int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ goto done; } - if (VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) + if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) goto done; - if (VFS_WRITE(fsp, fd, &c, 1)!=1) + if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1) goto done; /* Seek to where we were */ - if (VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) + if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) goto done; result = 0; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9f37622c8c..62f03f0cd6 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -320,7 +320,7 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ if (!st) st = &st2; - if (VFS_STAT(conn,dname,st) != 0) + if (SMB_VFS_STAT(conn,dname,st) != 0) return(False); ret = S_ISDIR(st->st_mode); @@ -339,7 +339,7 @@ int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode) int ret; SMB_STRUCT_STAT sbuf; - if(!(ret=VFS_MKDIR(conn, name, mode))) { + if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) { inherit_access_acl(conn, name, mode); @@ -349,8 +349,8 @@ int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode) * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir. */ if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && - !VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) - VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); + !SMB_VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) + SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); } return ret; } @@ -368,7 +368,7 @@ BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT ZERO_STRUCTP(sbuf); - if (VFS_STAT(conn,fname,sbuf) == -1) + if (SMB_VFS_STAT(conn,fname,sbuf) == -1) return(False); return True; } @@ -386,7 +386,7 @@ BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT * ZERO_STRUCTP(sbuf); - if (VFS_STAT(conn,fname,sbuf) == -1) + if (SMB_VFS_STAT(conn,fname,sbuf) == -1) return False; return(S_ISREG(sbuf->st_mode)); } @@ -401,7 +401,7 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) while (total < byte_count) { - ssize_t ret = VFS_READ(fsp, fsp->fd, buf + total, + ssize_t ret = SMB_VFS_READ(fsp, fsp->fd, buf + total, byte_count - total); if (ret == 0) return total; @@ -426,7 +426,7 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) ssize_t ret; while (total < N) { - ret = VFS_WRITE(fsp,fsp->fd,buffer + total,N - total); + ret = SMB_VFS_WRITE(fsp,fsp->fd,buffer + total,N - total); if (ret == -1) return -1; @@ -465,7 +465,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) return -1; } - ret = VFS_FSTAT(fsp,fsp->fd,&st); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,&st); if (ret == -1) return ret; @@ -479,7 +479,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) fsp->fsp_name, (double)st.st_size )); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = VFS_FTRUNCATE(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { + if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { set_filelen_write_cache(fsp, len); } return ret; @@ -492,7 +492,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ - space_avail = VFS_DISK_FREE(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); + space_avail = SMB_VFS_DISK_FREE(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail )); @@ -518,7 +518,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = VFS_FTRUNCATE(fsp, fsp->fd, len)) != -1) + if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, len)) != -1) set_filelen_write_cache(fsp, len); return ret; @@ -533,12 +533,12 @@ static files_struct *out_fsp; static ssize_t read_fn(int fd, void *buf, size_t len) { - return VFS_READ(in_fsp, fd, buf, len); + return SMB_VFS_READ(in_fsp, fd, buf, len); } static ssize_t write_fn(int fd, const void *buf, size_t len) { - return VFS_WRITE(out_fsp, fd, buf, len); + return SMB_VFS_WRITE(out_fsp, fd, buf, len); } SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) @@ -561,7 +561,7 @@ char *vfs_readdirname(connection_struct *conn, void *p) if (!p) return(NULL); - ptr = (struct dirent *)VFS_READDIR(conn,p); + ptr = (struct dirent *)SMB_VFS_READDIR(conn,p); if (!ptr) return(NULL); @@ -597,7 +597,7 @@ int vfs_ChDir(connection_struct *conn, const char *path) DEBUG(4,("vfs_ChDir to %s\n",path)); - res = VFS_CHDIR(conn,path); + res = SMB_VFS_CHDIR(conn,path); if (!res) pstrcpy(LastDir,path); return(res); @@ -654,7 +654,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) *s = 0; if (!use_getwd_cache) - return(VFS_GETWD(conn,path)); + return(SMB_VFS_GETWD(conn,path)); /* init the cache */ if (!getwd_cache_init) { @@ -668,9 +668,9 @@ char *vfs_GetWd(connection_struct *conn, char *path) /* Get the inode of the current directory, if this doesn't work we're in trouble :-) */ - if (VFS_STAT(conn, ".",&st) == -1) { + if (SMB_VFS_STAT(conn, ".",&st) == -1) { DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path)); - return(VFS_GETWD(conn,path)); + return(SMB_VFS_GETWD(conn,path)); } @@ -684,7 +684,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) the same...) */ if (st.st_ino == ino_list[i].inode && st.st_dev == ino_list[i].dev) { - if (VFS_STAT(conn,ino_list[i].dos_path,&st2) == 0) { + if (SMB_VFS_STAT(conn,ino_list[i].dos_path,&st2) == 0) { if (st.st_ino == st2.st_ino && st.st_dev == st2.st_dev && (st2.st_mode & S_IFMT) == S_IFDIR) { pstrcpy (path, ino_list[i].dos_path); @@ -706,8 +706,8 @@ char *vfs_GetWd(connection_struct *conn, char *path) The very slow getcwd, which spawns a process on some systems, or the not quite so bad getwd. */ - if (!VFS_GETWD(conn,s)) { - DEBUG(0,("vfs_GetWd: VFS_GETWD call failed, errno %s\n",strerror(errno))); + if (!SMB_VFS_GETWD(conn,s)) { + DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n",strerror(errno))); return (NULL); } @@ -763,7 +763,7 @@ static BOOL readlink_check(connection_struct *conn, const char *dir, char *name) realdir[reallen] = 0; } - if (VFS_READLINK(conn, name, flink, sizeof(pstring) -1) != -1) { + if (SMB_VFS_READLINK(conn, name, flink, sizeof(pstring) -1) != -1) { DEBUG(3,("reduce_name: file path name %s is a symlink\nChecking it's path\n", name)); if (*flink == '/') { pstrcpy(cleanlink, flink); -- cgit From 2c01eef4d7ea9ed57ea5f68a0e75559e101fd26f Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 14 May 2003 14:38:11 +0000 Subject: Evolve quotas configure check more. Patch from Stefan (metze) Metzemacher. Now we are defaulting to --with-quotas=no but anyway trying to test them in configure. This is done to get information about as much quota API variations as possible -- when --with-quotas=no this does not affect build but provides us with more detailed information on build farm. (This used to be commit 3786695c72e6ff6a52a527382ac77142e236971b) --- source3/smbd/ntquotas.c | 5 +---- source3/smbd/nttrans.c | 12 ++++++------ source3/smbd/quotas.c | 5 +++++ source3/smbd/trans2.c | 10 +++++----- source3/smbd/vfs-wrap.c | 14 ++++++++++++-- 5 files changed, 29 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index f6f1479481..8685560897 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -119,11 +119,8 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, id.uid = -1; -#if defined(QUOTABLOCK_SIZE) D.bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; -#else - D.bsize = (SMB_BIG_UINT)1024; -#endif + D.softlimit = limit_nt2unix(qt->softlim,D.bsize); D.hardlimit = limit_nt2unix(qt->hardlim,D.bsize); D.qflags = qt->qflags; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3ddf191ef6..3bf162f763 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -691,7 +691,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if( strchr_m(fname, ':')) { -#ifdef WITH_QUOTAS +#ifdef HAVE_SYS_QUOTAS if ((fake_file_type=is_fake_file(fname))!=0) { /* * here we go! support for changing the disk quotas --metze @@ -706,7 +706,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib #endif END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); -#ifdef WITH_QUOTAS +#ifdef HAVE_SYS_QUOTAS } #endif } @@ -1830,7 +1830,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, } -#ifdef WITH_QUOTAS +#ifdef HAVE_SYS_QUOTAS /**************************************************************************** Reply to get user quota ****************************************************************************/ @@ -2200,7 +2200,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, return -1; } -#endif /* WITH_QUOTAS */ +#endif /* HAVE_SYS_QUOTAS */ /**************************************************************************** Reply to a SMBNTtrans. @@ -2445,7 +2445,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); &setup, ¶ms, &data); END_PROFILE_NESTED(NT_transact_query_security_desc); break; -#ifdef WITH_QUOTAS +#ifdef HAVE_SYS_QUOTAS case NT_TRANSACT_GET_USER_QUOTA: START_PROFILE_NESTED(NT_transact_get_user_quota); outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, @@ -2464,7 +2464,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); &data, data_count); END_PROFILE_NESTED(NT_transact_set_user_quota); break; -#endif /* WITH_QUOTAS */ +#endif /* HAVE_SYS_QUOTAS */ default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 0163120ee5..91c952aa90 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -29,6 +29,11 @@ #ifndef HAVE_SYS_QUOTAS +/* just a quick hack because sysquotas.h is included before linux/quota.h */ +#ifdef QUOTABLOCK_SIZE +#undef QUOTABLOCK_SIZE +#endif + #ifdef WITH_QUOTAS #if defined(VXFS_QUOTA) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 731fb9643b..0bf9580798 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1480,7 +1480,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SIVAL(pdata,4,0); /* characteristics */ break; -#ifdef WITH_QUOTAS +#ifdef HAVE_SYS_QUOTAS case SMB_FS_QUOTA_INFORMATION: /* * what we have to send --metze: @@ -1551,7 +1551,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned break; } -#endif /* WITH_QUOTAS */ +#endif /* HAVE_SYS_QUOTAS */ case SMB_FS_OBJECTID_INFORMATION: data_len = 64; break; @@ -1593,7 +1593,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return -1; } -#ifdef WITH_QUOTAS +#ifdef HAVE_SYS_QUOTAS /**************************************************************************** Reply to a TRANS2_SETFSINFO (set filesystem info). ****************************************************************************/ @@ -1705,7 +1705,7 @@ static int call_trans2setfsinfo(connection_struct *conn, return outsize; } -#endif /* WITH_QUOTAS */ +#endif /* HAVE_SYS_QUOTAS */ /**************************************************************************** * Utility function to set bad path error. @@ -3492,7 +3492,7 @@ int reply_trans2(connection_struct *conn, END_PROFILE_NESTED(Trans2_qfsinfo); break; -#ifdef WITH_QUOTAS +#ifdef HAVE_SYS_QUOTAS case TRANSACT2_SETFSINFO: START_PROFILE_NESTED(Trans2_setfsinfo); outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 64e29bbe43..2160bca9f7 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -758,20 +758,30 @@ int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) { +#ifdef HAVE_SYS_QUOTAS int result; START_PROFILE(syscall_get_quota); result = sys_get_quota(conn->connectpath, qtype, id, qt); END_PROFILE(syscall_get_quota); - return result; + return result; +#else + errno = ENOSYS; + return -1; +#endif } int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) { +#ifdef HAVE_SYS_QUOTAS int result; START_PROFILE(syscall_set_quota); result = sys_set_quota(conn->connectpath, qtype, id, qt); END_PROFILE(syscall_set_quota); - return result; + return result; +#else + errno = ENOSYS; + return -1; +#endif } -- cgit From 7f256452c1571db0babe9dbbf7dda9bdd050d557 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 14 May 2003 20:22:48 +0000 Subject: fix quota build on non-64bit systems (This used to be commit 227ac953386d0040c661cde85a5b23e10529fb0c) --- source3/smbd/nttrans.c | 6 +++--- source3/smbd/trans2.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3bf162f763..d0066c367c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2155,7 +2155,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, #else /* LARGE_SMB_OFF_T */ if ((IVAL(pdata,20) != 0)&& ((qt.usedspace != 0xFFFFFFFF)|| - (IVAL(pdata,20)!=0xFFFFFFFF)))) { + (IVAL(pdata,20)!=0xFFFFFFFF))) { /* more than 32 bits? */ return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -2168,7 +2168,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, #else /* LARGE_SMB_OFF_T */ if ((IVAL(pdata,28) != 0)&& ((qt.softlim != 0xFFFFFFFF)|| - (IVAL(pdata,28)!=0xFFFFFFFF)))) { + (IVAL(pdata,28)!=0xFFFFFFFF))) { /* more than 32 bits? */ return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -2181,7 +2181,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, #else /* LARGE_SMB_OFF_T */ if ((IVAL(pdata,36) != 0)&& ((qt.hardlim != 0xFFFFFFFF)|| - (IVAL(pdata,36)!=0xFFFFFFFF)))) { + (IVAL(pdata,36)!=0xFFFFFFFF))) { /* more than 32 bits? */ return ERROR_DOS(ERRDOS,ERRunknownlevel); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0bf9580798..f43a65af5c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1657,7 +1657,7 @@ static int call_trans2setfsinfo(connection_struct *conn, #else /* LARGE_SMB_OFF_T */ if ((IVAL(pdata,28) != 0)&& ((quotas.softlim != 0xFFFFFFFF)|| - (IVAL(pdata,28)!=0xFFFFFFFF)))) { + (IVAL(pdata,28)!=0xFFFFFFFF))) { /* more than 32 bits? */ return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -1670,7 +1670,7 @@ static int call_trans2setfsinfo(connection_struct *conn, #else /* LARGE_SMB_OFF_T */ if ((IVAL(pdata,36) != 0)&& ((quotas.hardlim != 0xFFFFFFFF)|| - (IVAL(pdata,36)!=0xFFFFFFFF)))) { + (IVAL(pdata,36)!=0xFFFFFFFF))) { /* more than 32 bits? */ return ERROR_DOS(ERRDOS,ERRunknownlevel); } -- cgit From 3ededa5f7bd8c039346841d7902b5344604a9d9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 May 2003 17:37:52 +0000 Subject: Fix from Steve G . Ensure sigemptyset is called on the sa_mask to prevent valgrind complaints. Jeremy. (This used to be commit e065c3a58f5c7f2612596574046a73869183dbd3) --- source3/smbd/notify_kernel.c | 11 ++++++----- source3/smbd/oplock_linux.c | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index efe93de5af..8fcc18a09f 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -217,13 +217,14 @@ struct cnotify_fns *kernel_notify_init(void) ZERO_STRUCT(act); - act.sa_handler = NULL; - act.sa_sigaction = signal_handler; - act.sa_flags = SA_SIGINFO; - if (sigaction(RT_SIGNAL_NOTIFY, &act, NULL) != 0) { + act.sa_handler = NULL; + act.sa_sigaction = signal_handler; + act.sa_flags = SA_SIGINFO; + sigemptyset( &act.sa_mask ); + if (sigaction(RT_SIGNAL_NOTIFY, &act, NULL) != 0) { DEBUG(0,("Failed to setup RT_SIGNAL_NOTIFY handler\n")); return NULL; - } + } if (!kernel_notify_available()) return NULL; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 84083dffc9..ac9cf5b8a6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -284,6 +284,7 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) act.sa_handler = NULL; act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; + sigemptyset( &act.sa_mask ); if (sigaction(RT_SIGNAL_LEASE, &act, NULL) != 0) { DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler\n")); return NULL; -- cgit From 9e9849c0ee5cfc79dc51e29c8015d9c53fa4bfcc Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 16 May 2003 06:20:57 +0000 Subject: add metze's patch for smb_register functions (This used to be commit 1480c7e8c7a84c34181118c449c50ca99fdcbc6b) --- source3/smbd/vfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 62f03f0cd6..d24ae54d42 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -135,12 +135,9 @@ static struct vfs_ops default_vfs = { static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) { struct vfs_init_function_entry *entry = backends; - pstring stripped; - - module_path_get_name(name, stripped); while(entry) { - if (strequal(entry->name, stripped)) return entry; + if (strcmp(entry->name, name)==0) return entry; entry = entry->next; } -- cgit From a9336d841156d3bbcb702778b3a03512a1820962 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 16 May 2003 12:15:04 +0000 Subject: David Lee provides some corrections to the comments in the UTMP code. Andrew Bartlett (This used to be commit f0cff106cb6c8993eb31f589106d845261c1f8e9) --- source3/smbd/utmp.c | 44 +++++--------------------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 84ec364654..2c5a1abc82 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -81,11 +81,11 @@ lastlog: Notes: Each connection requires a small number (starting at 0, working up) - to represent the line (unum). This must be unique within and across - all smbd processes. + to represent the line. This must be unique within and across all + smbd processes. It is the 'id_num' from Samba's session.c code. The 4 byte 'ut_id' component is vital to distinguish connections, - of which there could be several hundered or even thousand. + of which there could be several hundred or even thousand. Entries seem to be printable characters, with optional NULL pads. We need to be distinct from other entries in utmp/wtmp. @@ -105,11 +105,8 @@ Notes: Arbitrarily I have chosen to use a distinctive 'SM' for the first two bytes. - The remaining two encode the "unum" (see above). - - For "utmp consolidate" the suggestion was made to encode the pid into - those remaining two bytes (16 bits). But recent UNIX (e.g Solaris 8) - is migrating to pids > 16 bits, so we ought not to do this. + The remaining two bytes encode the session 'id_num' (see above). + Our caller (session.c) should note our 16-bit limitation. ****************************************************************************/ @@ -125,33 +122,6 @@ Notes: #include #endif -/**************************************************************************** - Obtain/release a small number (0 upwards) unique within and across smbds. -****************************************************************************/ -/* - * Need a "small" number to represent this connection, unique within this - * smbd and across all smbds. - * - * claim: - * Start at 0, hunt up for free, unique number "unum" by attempting to - * store it as a key in a tdb database: - * key: unum data: pid+conn - * Also store its inverse, ready for yield function: - * key: pid+conn data: unum - * - * yield: - * Find key: pid+conn; data is unum; delete record - * Find key: unum ; delete record. - * - * Comment: - * The claim algorithm (a "for" loop attempting to store numbers in a tdb - * database) will be increasingly inefficient with larger numbers of - * connections. Is it possible to write a suitable primitive within tdb? - * - * However, by also storing the inverse key/data pair, we at least make - * the yield algorithm efficient. - */ - /**************************************************************************** Default paths to various {u,w}tmp{,x} files. ****************************************************************************/ @@ -504,10 +474,6 @@ static BOOL sys_utmp_fill(struct utmp *u, /* * ut_line: * If size limit proves troublesome, then perhaps use "ut_id_encode()". - * - * Temporary variable "line_tmp" avoids trouble: - * o with unwanted trailing NULL if ut_line full; - * o with overflow if ut_line would be more than full. */ if (strlen(id_str) > sizeof(u->ut_line)) { DEBUG(1,("id_str [%s] is too long for %d char utmp field\n", -- cgit From 1854e7b8e56a907d25a0614288d21a5f223cb279 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 May 2003 00:46:28 +0000 Subject: Cope with cumulative permissions sets. This code is #ifdef'ed out at the moment as I don't think cumulative permission sets make sense in POSIX even though that's the way Windows works.... Jeremy. (This used to be commit 6ddd5b6ca7dde45ce866f852861e143434c84c7e) --- source3/smbd/posix_acls.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index aaf71c82ca..3824afe3c4 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1171,7 +1171,7 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); /**************************************************************************** ASCII art time again... JRA :-). - We have 3 cases to process when moving from an NT ACL to a POSIX ACL. Firstly, + We have 4 cases to process when moving from an NT ACL to a POSIX ACL. Firstly, we insist the ACL is in canonical form (ie. all DENY entries preceede ALLOW entries). Secondly, the merge code has ensured that all duplicate SID entries for allow or deny have been merged, so the same SID can only appear once in the deny @@ -1244,6 +1244,15 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); best we can do and has the advantage of failing closed rather than open. --------------------------------------------------------------------------- + Fourth pass - cope with cumulative permissions. + + for all allow user entries, if there exists an allow group entry with + more permissive permissions, and the user is in that group, rewrite the + allow user permissions to contain both sets of permissions. + + Currently the code for this is #ifdef'ed out as these semantics make + no sense to me. JRA. + --------------------------------------------------------------------------- Note we *MUST* do the deny user pass first as this will convert deny user entries into allow user entries which can then be processed by the deny @@ -1433,6 +1442,45 @@ static void process_deny_list( canon_ace **pp_ace_list ) } + /* Doing this fourth pass allows Windows semantics to be layered + * on top of POSIX semantics. I'm not sure if this is desirable. + * For example, in W2K ACLs there is no way to say, "Group X no + * access, user Y full access" if user Y is a member of group X. + * This seems completely broken semantics to me.... JRA. + */ + +#if 0 + /* Pass 4 above - deal with allow entries. */ + + for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) { + canon_ace *allow_ace_p; + + curr_ace_next = curr_ace->next; /* So we can't lose the link. */ + + if (curr_ace->attr != ALLOW_ACE) + continue; + + if (curr_ace->owner_type != UID_ACE) + continue; + + for (allow_ace_p = ace_list; allow_ace_p; allow_ace_p = allow_ace_p->next) { + + if (allow_ace_p->attr != ALLOW_ACE) + continue; + + /* We process GID_ACE entries only. */ + + if (allow_ace_p->owner_type != GID_ACE) + continue; + + /* OR in the group perms. */ + + if (uid_entry_in_group( curr_ace, allow_ace_p)) + curr_ace->perms |= allow_ace_p->perms; + } + } +#endif + *pp_ace_list = ace_list; } -- cgit From 273dbfd9c61ddeb2cce87c0bf72cdb0b0e297972 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 20 May 2003 22:54:58 +0000 Subject: really make sure to include the version in the lanman string; tested spnego using smbclient (This used to be commit d7ca85613b6acf60e29cc118435db2c075995edb) --- source3/smbd/sesssetup.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index fc223ecf37..8840d4e759 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -57,18 +57,18 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv /**************************************************************************** Add the standard 'Samba' signature to the end of the session setup. ****************************************************************************/ -static void add_signature(char *outbuf) +static int add_signature(char *outbuf) { - char *p; + char *p = outbuf; fstring lanman; snprintf( lanman, sizeof(lanman), "Samba %s", VERSION ); - p = smb_buf(outbuf); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - set_message_end(outbuf,p); + + return PTR_DIFF(p, outbuf); } /**************************************************************************** @@ -91,9 +91,8 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, memcpy(p, blob.data, blob.length); p += blob.length; - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + p += add_signature( p ); + set_message_end(outbuf,p); return send_smb(smbd_server_fd(),outbuf); @@ -729,7 +728,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { - add_signature(outbuf); + char *p = smb_buf( outbuf ); + p += add_signature( p ); + set_message_end( outbuf, p ); /* perhaps grab OS version here?? */ } -- cgit From c9d0ee977c929f6a46905ff74cc221aaa028af74 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 May 2003 05:20:54 +0000 Subject: merge LANMAN1/LANMAN2.1 fixes from head (This used to be commit 73c686ab771b6c3e9a9335032f851083d44701c7) --- source3/smbd/negprot.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index db0694a840..bd1b9b0d57 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -101,6 +101,7 @@ static int reply_lanman1(char *inbuf, char *outbuf) /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { get_challenge(smb_buf(outbuf)); + SSVAL(outbuf,smb_vwv11, 8); } Protocol = PROTOCOL_LANMAN1; @@ -144,6 +145,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { get_challenge(smb_buf(outbuf)); + SSVAL(outbuf,smb_vwv11, 8); } Protocol = PROTOCOL_LANMAN2; -- cgit From c52ee09afe06dce29118356078cc4c26b126afc6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 21 May 2003 16:12:07 +0000 Subject: fix for UNICODE plaintext passwords (bug #59) and fix smbclient to send the unicode plain text password if negoitated (This used to be commit e7d635af80c844f17ff9f34c26c1e9c978951ce1) --- source3/smbd/sesssetup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8840d4e759..44131b1752 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -620,8 +620,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, nt_resp = data_blob(p+passlen1, passlen2); } else { pstring pass; + BOOL unic; + unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS; srvstr_pull(inbuf, pass, smb_buf(inbuf), - sizeof(pass), passlen1, STR_TERMINATE); + sizeof(pass), unic ? passlen2 : passlen1, + STR_TERMINATE); plaintext_password = data_blob(pass, strlen(pass)+1); } -- cgit From 4f7e6108bdbb6da29f7d75851e3be5c4567b6fb0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2003 18:45:24 +0000 Subject: Add more info to debug info... Jeremy. (This used to be commit 6d3b72b4994a5115a1e7f0ca3912692a33fc690e) --- source3/smbd/open.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e3bd530c17..55fbee372c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -543,7 +543,11 @@ static void validate_my_share_entries(share_mode_entry *share_entry) fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); if (!fsp) { - smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); + pstring str; + slprintf(str, sizeof(str)-1, "validate_my_share_entries: Cannot match a share entry with an open file \ +dev = %x, inode = %.0f file_id = %u\n", (unsigned int)share_entry->dev, (double)share_entry->inode, + (unsigned int)share_entry->share_file_id ); + smb_panic(str); } if (((uint16)fsp->oplock_type) != share_entry->op_type) { -- cgit From 78a4f6fc4b8938fcab5bb3b7ae9c3a151f7070f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2003 18:56:51 +0000 Subject: More fixes for debug log to catch logic error. Jeremy. (This used to be commit 84a7714eba801fefa7ad56493f20813de3943bc5) --- source3/smbd/open.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 55fbee372c..15171ce9e3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -534,7 +534,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign #if defined(DEVELOPER) -static void validate_my_share_entries(share_mode_entry *share_entry) +static void validate_my_share_entries(int num, share_mode_entry *share_entry) { files_struct *fsp; @@ -543,15 +543,13 @@ static void validate_my_share_entries(share_mode_entry *share_entry) fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); if (!fsp) { - pstring str; - slprintf(str, sizeof(str)-1, "validate_my_share_entries: Cannot match a share entry with an open file \ -dev = %x, inode = %.0f file_id = %u\n", (unsigned int)share_entry->dev, (double)share_entry->inode, - (unsigned int)share_entry->share_file_id ); - smb_panic(str); + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); + smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); } if (((uint16)fsp->oplock_type) != share_entry->op_type) { pstring str; + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); slprintf(str, sizeof(str)-1, "validate_my_share_entries: file %s, oplock_type = 0x%x, op_type = 0x%x\n", fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); smb_panic(str); @@ -600,7 +598,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T share_mode_entry *share_entry = &old_shares[i]; #if defined(DEVELOPER) - validate_my_share_entries(share_entry); + validate_my_share_entries(i, share_entry); #endif /* -- cgit From f161839a7493602ee4e9be2459230634ddfbb2b1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2003 20:31:35 +0000 Subject: Stat opens can have fsp->fd == -1 and will have a share entry. Ensure that file_find_dif will find them. Fixes a core dump in smbd/open.c. Jeremy. (This used to be commit 0e2165630d2ce31076fef6d7098e45c8fd327e23) --- source3/smbd/files.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4d1409feac..f0fd6b7a73 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -231,13 +231,21 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { - if (fsp->fd != -1 && - fsp->dev == dev && + /* We can have a fsp->fd == -1 here as it could be a stat open. */ + if (fsp->dev == dev && fsp->inode == inode && fsp->file_id == file_id ) { if (count > 10) { DLIST_PROMOTE(Files, fsp); } + /* Paranoia check. */ + if (fsp->fd == -1 && fsp->oplock_type != NO_OPLOCK) { + DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \ +oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, (unsigned int)fsp->file_id, + (unsigned int)fsp->oplock_type )); + smb_panic("file_find_dif\n"); + } return fsp; } } -- cgit From 4e8052640e4029938111d5a1af16865c67e21bf9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 27 May 2003 02:35:53 +0000 Subject: More fixes for builddir != srcdir. - Use absolute directories for $builddir and $srcdir in the Makefile - Don't try and combine source files in $builddir and $srcdir to build proto.h. It's just too hard to get it right across all targets we wish to compile on. Use a hand created prototype for the single function in smbd/build_options.c that we need. This allows us to ditch all the extra sed work that was causing problems: \t not portable - hah! - Fix bogus delheaders target to remove the correct files This appears to work quite nicely now. Let's see how it goes on the buildfarm machines. (This used to be commit 456184463d35c18840c39cb3483b7136247ea764) --- source3/smbd/server.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index edc7b57ba3..07723cc20e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -634,6 +634,12 @@ static BOOL init_structs(void ) main program. ****************************************************************************/ +/* Declare prototype for build_options() to avoid having to run it through + mkproto.h. Mixing $(builddir) and $(srcdir) source files in the current + prototype generation system is too complicated. */ + +void build_options(BOOL screen); + int main(int argc,const char *argv[]) { /* shall I run as a daemon */ -- cgit From b68e0b3aaea800ac668f9ee22b42fae6a783c8b5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 27 May 2003 06:55:06 +0000 Subject: Fix shadow parameter warning in free_empty_sys_acl() (This used to be commit 1b2b7766c8fa89f46f4d1c881ee91c4b0b15773a) --- source3/smbd/posix_acls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 3824afe3c4..8da12b9b68 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2097,17 +2097,17 @@ static struct canon_ace *canon_ace_entry_for(struct canon_ace *list, SMB_ACL_TAG ****************************************************************************/ -SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T acl) +SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl) { SMB_ACL_ENTRY_T entry; - if (!acl) + if (!the_acl) return NULL; - if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, acl); + if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); return NULL; } - return acl; + return the_acl; } /**************************************************************************** -- cgit From d542a9cabbd37cffc7d2c3e1bca8fc17ea7124da Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 27 May 2003 07:13:28 +0000 Subject: Fix printf warnings in debug statments. (This used to be commit d594e60f926e5618cd61585383bee315757ba73a) --- source3/smbd/ntquotas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 8685560897..6a217a3258 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -178,12 +178,12 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) ZERO_STRUCT(tmp_qt); if (allready_in_quota_list((*qt_list),usr->pw_uid)) { - DEBUG(5,("record for uid[%d] allready in the list\n",usr->pw_uid)); + DEBUG(5,("record for uid[%ld] allready in the list\n",(long)usr->pw_uid)); continue; } if (NT_STATUS_IS_ERR(uid_to_sid(&sid, usr->pw_uid))) { - DEBUG(0,("uid_to_sid failed for %d\n",usr->pw_uid)); + DEBUG(0,("uid_to_sid failed for %ld\n",(long)usr->pw_uid)); continue; } -- cgit From 090d70fc3f49c5b79492861227c515dcd899bc08 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 27 May 2003 16:30:02 +0000 Subject: volker's add_signature() fix; must pass the beginning on the outbuf to get the flags field (This used to be commit 48c8211084503172f053ad23b308901628f8a978) --- source3/smbd/sesssetup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 44131b1752..64984d4809 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -57,9 +57,9 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv /**************************************************************************** Add the standard 'Samba' signature to the end of the session setup. ****************************************************************************/ -static int add_signature(char *outbuf) +static int add_signature(char *outbuf, char *p) { - char *p = outbuf; + char *start = p; fstring lanman; snprintf( lanman, sizeof(lanman), "Samba %s", VERSION ); @@ -68,7 +68,7 @@ static int add_signature(char *outbuf) p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); - return PTR_DIFF(p, outbuf); + return PTR_DIFF(p, start); } /**************************************************************************** @@ -91,7 +91,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, memcpy(p, blob.data, blob.length); p += blob.length; - p += add_signature( p ); + p += add_signature( outbuf, p ); set_message_end(outbuf,p); @@ -732,7 +732,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { char *p = smb_buf( outbuf ); - p += add_signature( p ); + p += add_signature( outbuf, p ); set_message_end( outbuf, p ); /* perhaps grab OS version here?? */ } -- cgit From a11797cda2c1b81771edfdbd467ab36af121b6eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 May 2003 21:55:10 +0000 Subject: Correct (?) handling for VC = 0. Trying to fix XP logoff leaving resources around. Jeremy. (This used to be commit bf0916e1da442606311c74ac73ccec2e9710d663) --- source3/smbd/sesssetup.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 64984d4809..15d816bd6d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -493,6 +493,16 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } +/**************************************************************************** + On new VC == 0, shutdown *all* old connections and users. +****************************************************************************/ + +static void setup_new_vc_session(void) +{ + DEBUG(2,("setup_new_vc_session: New VC == 0, closing all old resources.\n")); + conn_close_all(); + invalidate_all_vuids(); +} /**************************************************************************** reply to a session setup command @@ -541,6 +551,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } + if (SVAL(inbuf,smb_vwv4) == 0) { + setup_new_vc_session(); + } return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } @@ -562,7 +575,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE); *domain = 0; - + } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); @@ -641,6 +654,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } + if (SVAL(inbuf,smb_vwv4) == 0) { + setup_new_vc_session(); + } + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name())); if (*user) { -- cgit From 03f046dd9920b3f3c00e97afc06d1857297583ee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 May 2003 01:00:58 +0000 Subject: It seems only NT4 does the VC == 0 session drop code. Jeremy. (This used to be commit 30bbf4c8c4cbed0f7980237ea9b78baa785dec3d) --- source3/smbd/sesssetup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 15d816bd6d..2631961739 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -495,13 +495,17 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, /**************************************************************************** On new VC == 0, shutdown *all* old connections and users. + It seems that only NT4.x does this. At W2K and above (XP etc.). + a new session setup with VC==0 is ignored. ****************************************************************************/ static void setup_new_vc_session(void) { - DEBUG(2,("setup_new_vc_session: New VC == 0, closing all old resources.\n")); + DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n")); +#if 0 conn_close_all(); invalidate_all_vuids(); +#endif } /**************************************************************************** -- cgit From 24497516cb115b62c5161a053f9025a9c711b114 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 May 2003 20:25:31 +0000 Subject: Fix bug brought up by Ken Cross that empty ACE's cause existing ACE's to be applied to new ACE set calls. This is incorrect. Don't think this has a bugzilla id. Jeremy. (This used to be commit cb70d8c9e87801c314d1b926d4e43ee451c04135) --- source3/smbd/posix_acls.c | 121 ++++++---------------------------------------- 1 file changed, 14 insertions(+), 107 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 8da12b9b68..d775a82d2d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -605,14 +605,6 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, BOOL got_other = False; canon_ace *pace_other = NULL; canon_ace *pace_group = NULL; - connection_struct *conn = fsp->conn; - SMB_ACL_T current_posix_acl = NULL; - mode_t current_user_perms = 0; - mode_t current_grp_perms = 0; - mode_t current_other_perms = 0; - BOOL got_current_user = False; - BOOL got_current_grp = False; - BOOL got_current_other = False; for (pace = *pp_ace; pace; pace = pace->next) { if (pace->type == SMB_ACL_USER_OBJ) { @@ -645,62 +637,6 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, } } - /* - * When setting ACLs and missing one out of SMB_ACL_USER_OBJ, - * SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER, try to retrieve current - * values. For user and other a simple SMB_VFS_STAT would do, but - * we would get mask instead of group. Let's do it via ACL. - */ - - if (setting_acl && (!got_user || !got_grp || !got_other)) { - - SMB_ACL_ENTRY_T entry; - int entry_id = SMB_ACL_FIRST_ENTRY; - - if(fsp->is_directory || fsp->fd == -1) { - current_posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); - } else { - current_posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); - } - - if (current_posix_acl) { - while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, current_posix_acl, entry_id, &entry) == 1) { - SMB_ACL_TAG_T tagtype; - SMB_ACL_PERMSET_T permset; - - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; - - /* Is this a MASK entry ? */ - if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) - continue; - - if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) - continue; - - switch(tagtype) { - case SMB_ACL_USER_OBJ: - current_user_perms = convert_permset_to_mode_t(conn, permset); - got_current_user = True; - break; - case SMB_ACL_GROUP_OBJ: - current_grp_perms = convert_permset_to_mode_t(conn, permset); - got_current_grp = True; - break; - case SMB_ACL_OTHER: - current_other_perms = convert_permset_to_mode_t(conn, permset); - got_current_other = True; - break; - } - } - SMB_VFS_SYS_ACL_FREE_ACL(conn, current_posix_acl); - } else { - DEBUG(10,("ensure_canon_entry_valid: failed to retrieve current ACL of %s\n", - fsp->fsp_name)); - } - } - if (!got_user) { if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); @@ -715,18 +651,13 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->attr = ALLOW_ACE; if (setting_acl) { - if (got_current_user) { - pace->perms = current_user_perms; - } else { - /* If we only got an "everyone" perm, just use that. */ - if (!got_grp && got_other) - pace->perms = pace_other->perms; - else if (got_grp && uid_entry_in_group(pace, pace_group)) - pace->perms = pace_group->perms; - else - pace->perms = 0; - - } + /* If we only got an "everyone" perm, just use that. */ + if (!got_grp && got_other) + pace->perms = pace_other->perms; + else if (got_grp && uid_entry_in_group(pace, pace_group)) + pace->perms = pace_group->perms; + else + pace->perms = 0; apply_default_perms(fsp, pace, S_IRUSR); } else { @@ -749,15 +680,11 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->trustee = *pfile_grp_sid; pace->attr = ALLOW_ACE; if (setting_acl) { - if (got_current_grp) { - pace->perms = current_grp_perms; - } else { - /* If we only got an "everyone" perm, just use that. */ - if (got_other) - pace->perms = pace_other->perms; - else - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); - } + /* If we only got an "everyone" perm, just use that. */ + if (got_other) + pace->perms = pace_other->perms; + else + pace->perms = 0; apply_default_perms(fsp, pace, S_IRGRP); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); @@ -779,10 +706,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->trustee = global_sid_World; pace->attr = ALLOW_ACE; if (setting_acl) { - if (got_current_other) - pace->perms = current_other_perms; - else - pace->perms = 0; + pace->perms = 0; apply_default_perms(fsp, pace, S_IROTH); } else pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); @@ -2351,7 +2275,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) int nt_acl_type; int i; - if (nt4_compatible_acls()) { + if (nt4_compatible_acls() && dir_ace) { /* * NT 4 chokes if an ACL contains an INHERIT_ONLY entry * but no non-INHERIT_ONLY entry for one SID. So we only @@ -2364,9 +2288,6 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * case will still fail under NT 4. */ - if (!dir_ace) - goto simplify_file_ace_only; - ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); if (ace && !ace->perms) { DLIST_REMOVE(dir_ace, ace); @@ -2413,20 +2334,6 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) DLIST_REMOVE(dir_ace, ace); SAFE_FREE(ace); } - - simplify_file_ace_only: - - ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(file_ace, ace); - SAFE_FREE(ace); - } - - ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(file_ace, ace); - SAFE_FREE(ace); - } } num_acls = count_canon_ace_list(file_ace); -- cgit From 545e8d499947fec55832352d741e8a904122d564 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 May 2003 23:49:31 +0000 Subject: Change get_nt_acl() to include security_info wanted. Only return this. This gets us closer to W2k+ in what we return for file ACLs. Fix horribly broken make_sec_desc() that screwed up the size when given a SD with no owner or group (how did it get this bad... ?). Jeremy. (This used to be commit 183c9ed4052ab14e269ed1234ca557053f77e77a) --- source3/smbd/dir.c | 6 +- source3/smbd/nttrans.c | 194 ++++++++++++++++--------------- source3/smbd/posix_acls.c | 283 ++++++++++++++++++++++++---------------------- source3/smbd/vfs-wrap.c | 8 +- 4 files changed, 256 insertions(+), 235 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 910ab35de8..94b605ee8f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -715,7 +715,8 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, + (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, True); /* No access if SD get failed. */ @@ -768,7 +769,8 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, + (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, False); /* No access if SD get failed. */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d0066c367c..fa7b78ecc2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -964,13 +964,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib Reply to a NT_TRANSACT_CREATE call to open a pipe. ****************************************************************************/ -static int do_nt_transact_create_pipe( connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, char **ppsetup, char **ppparams, - char **ppdata) +static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { pstring fname; - int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); char *params = *ppparams; int ret; int pnum = -1; @@ -980,12 +979,12 @@ static int do_nt_transact_create_pipe( connection_struct *conn, * Ensure minimum number of parameters sent. */ - if(total_parameter_count < 54) { - DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); + if(parameter_count < 54) { + DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count)); return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -1091,15 +1090,14 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ -static int call_nt_transact_create(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, char **ppsetup, char **ppparams, - char **ppdata) +static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { pstring fname; char *params = *ppparams; char *data = *ppdata; - int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; mode_t unixmode; @@ -1135,7 +1133,10 @@ static int call_nt_transact_create(connection_struct *conn, if (IS_IPC(conn)) { if (lp_nt_pipe_support()) return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, - bufsize, ppsetup, ppparams, ppdata); + bufsize, + ppsetup, setup_count, + ppparams, parameter_count, + ppdata, data_count); else return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1144,8 +1145,8 @@ static int call_nt_transact_create(connection_struct *conn, * Ensure minimum number of parameters sent. */ - if(total_parameter_count < 54) { - DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); + if(parameter_count < 54) { + DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count)); return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1189,7 +1190,7 @@ static int call_nt_transact_create(connection_struct *conn, if(!dir_fsp->is_directory) { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); /* * Check to see if this is a mac fork of some kind. @@ -1218,9 +1219,9 @@ static int call_nt_transact_create(connection_struct *conn, } srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, - total_parameter_count-53, STR_TERMINATE); + parameter_count-53, STR_TERMINATE); } else { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); /* * Check to see if this is a mac fork of some kind. @@ -1467,11 +1468,10 @@ int reply_nttranss(connection_struct *conn, don't allow a directory to be opened. ****************************************************************************/ -static int call_nt_transact_notify_change(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, - char **ppparams, char **ppdata) +static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { char *setup = *ppsetup; files_struct *fsp; @@ -1501,17 +1501,22 @@ name = %s\n", fsp->fsp_name )); Reply to an NT transact rename command. ****************************************************************************/ -static int call_nt_transact_rename(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, char **ppparams, char **ppdata) +static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { char *params = *ppparams; pstring new_name; - files_struct *fsp = file_fsp(params, 0); - BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; + files_struct *fsp = NULL; + BOOL replace_if_exists = False; NTSTATUS status; + if(parameter_count < 4) + return ERROR_DOS(ERRDOS,ERRbadfunc); + + fsp = file_fsp(params, 0); + replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE); @@ -1557,15 +1562,13 @@ static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) } /**************************************************************************** - Reply to query a security descriptor - currently this is not implemented (it - is planned to be though). Right now it just returns the same thing NT would - when queried on a FAT filesystem. JRA. + Reply to query a security descriptor. ****************************************************************************/ -static int call_nt_transact_query_security_desc(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **ppsetup, char **ppparams, char **ppdata) +static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); char *params = *ppparams; @@ -1573,13 +1576,19 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, prs_struct pd; SEC_DESC *psd = NULL; size_t sd_size; + uint32 security_info_wanted; TALLOC_CTX *mem_ctx; + files_struct *fsp = NULL; - files_struct *fsp = file_fsp(params,0); + if(parameter_count < 8) + return ERROR_DOS(ERRDOS,ERRbadfunc); + fsp = file_fsp(params,0); if(!fsp) return ERROR_DOS(ERRDOS,ERRbadfid); + security_info_wanted = IVAL(params,4); + DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); params = nttrans_realloc(ppparams, 4); @@ -1598,7 +1607,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if (!lp_nt_acl_support(SNUM(conn))) sd_size = get_null_nt_acl(mem_ctx, &psd); else - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, security_info_wanted, &psd); if (sd_size == 0) { talloc_destroy(mem_ctx); @@ -1665,23 +1674,21 @@ security descriptor.\n")); } /**************************************************************************** - Reply to set a security descriptor. Map to UNIX perms. + Reply to set a security descriptor. Map to UNIX perms or POSIX ACLs. ****************************************************************************/ -static int call_nt_transact_set_security_desc(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, char **ppsetup, - char **ppparams, char **ppdata) +static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { - uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); char *params= *ppparams; char *data = *ppdata; - uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); files_struct *fsp = NULL; uint32 security_info_sent = 0; NTSTATUS nt_status; - if(total_parameter_count < 8) + if(parameter_count < 8) return ERROR_DOS(ERRDOS,ERRbadfunc); if((fsp = file_fsp(params,0)) == NULL) @@ -1695,10 +1702,10 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, (unsigned int)security_info_sent )); - if (total_data_count == 0) + if (data_count == 0) return ERROR_DOS(ERRDOS, ERRnoaccess); - if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, total_data_count, security_info_sent))) + if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) return ERROR_NT(nt_status); done: @@ -1710,12 +1717,11 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, /**************************************************************************** Reply to NT IOCTL ****************************************************************************/ -static int call_nt_transact_ioctl(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, int setup_count, - char **ppparams, int parameter_count, - char **ppdata, int data_count) + +static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { unsigned fnum, control; static BOOL logged_message; @@ -1835,12 +1841,10 @@ static int call_nt_transact_ioctl(connection_struct *conn, Reply to get user quota ****************************************************************************/ -static int call_nt_transact_get_user_quota(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **ppsetup, int setup_count, - char **ppparams, int params_count, - char **ppdata, int data_count) +static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { NTSTATUS nt_status = NT_STATUS_OK; uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); @@ -1872,8 +1876,8 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, * Ensure minimum number of parameters sent. */ - if (params_count < 4) { - DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",params_count)); + if (parameter_count < 4) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",parameter_count)); return ERROR_DOS(ERRDOS,ERRinvalidparam); } @@ -2086,12 +2090,10 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, Reply to set user quota ****************************************************************************/ -static int call_nt_transact_set_user_quota(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **ppsetup, int setup_count, - char **ppparams, int params_count, - char **ppdata, int data_count) +static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { char *params = *ppparams; char *pdata = *ppdata; @@ -2114,8 +2116,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, * Ensure minimum number of parameters sent. */ - if (params_count < 2) { - DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",params_count)); + if (parameter_count < 2) { + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count)); return ERROR_DOS(ERRDOS,ERRinvalidparam); } @@ -2403,8 +2405,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); case NT_TRANSACT_CREATE: START_PROFILE_NESTED(NT_transact_create); outsize = call_nt_transact_create(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_create); break; case NT_TRANSACT_IOCTL: @@ -2412,56 +2416,64 @@ due to being in oplock break state.\n", (unsigned int)function_code )); outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, length, bufsize, &setup, setup_count, - ¶ms, parameter_count, - &data, data_count); + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_ioctl); break; case NT_TRANSACT_SET_SECURITY_DESC: START_PROFILE_NESTED(NT_transact_set_security_desc); outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_set_security_desc); break; case NT_TRANSACT_NOTIFY_CHANGE: START_PROFILE_NESTED(NT_transact_notify_change); outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_notify_change); break; case NT_TRANSACT_RENAME: START_PROFILE_NESTED(NT_transact_rename); outsize = call_nt_transact_rename(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_rename); break; case NT_TRANSACT_QUERY_SECURITY_DESC: START_PROFILE_NESTED(NT_transact_query_security_desc); outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_query_security_desc); break; #ifdef HAVE_SYS_QUOTAS case NT_TRANSACT_GET_USER_QUOTA: START_PROFILE_NESTED(NT_transact_get_user_quota); outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, parameter_count, - &data, data_count); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_get_user_quota); break; case NT_TRANSACT_SET_USER_QUOTA: START_PROFILE_NESTED(NT_transact_set_user_quota); outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, parameter_count, - &data, data_count); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_set_user_quota); break; #endif /* HAVE_SYS_QUOTAS */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d775a82d2d..9773076a46 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2165,7 +2165,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) the UNIX style get ACL. ****************************************************************************/ -size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) +size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) { extern DOM_SID global_sid_Builtin_Administrators; extern DOM_SID global_sid_Builtin_Users; @@ -2241,177 +2241,184 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); } - /* - * In the optimum case Creator Owner and Creator Group would be used for - * the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this - * would lead to usability problems under Windows: The Creator entries - * are only available in browse lists of directories and not for files; - * additionally the identity of the owning group couldn't be determined. - * We therefore use those identities only for Default ACLs. - */ - - /* Create the canon_ace lists. */ - file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, SMB_ACL_TYPE_ACCESS ); + if (security_info & DACL_SECURITY_INFORMATION) { - /* We must have *some* ACLS. */ + /* + * In the optimum case Creator Owner and Creator Group would be used for + * the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this + * would lead to usability problems under Windows: The Creator entries + * are only available in browse lists of directories and not for files; + * additionally the identity of the owning group couldn't be determined. + * We therefore use those identities only for Default ACLs. + */ - if (count_canon_ace_list(file_ace) == 0) { - DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); - return 0; - } + /* Create the canon_ace lists. */ + file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, SMB_ACL_TYPE_ACCESS ); - if (fsp->is_directory && dir_acl) { - dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, - &global_sid_Creator_Owner, - &global_sid_Creator_Group, SMB_ACL_TYPE_DEFAULT ); - } + /* We must have *some* ACLS. */ + + if (count_canon_ace_list(file_ace) == 0) { + DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); + return 0; + } - /* - * Create the NT ACE list from the canonical ace lists. - */ + if (fsp->is_directory && dir_acl) { + dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, + &global_sid_Creator_Owner, + &global_sid_Creator_Group, SMB_ACL_TYPE_DEFAULT ); + } - { - canon_ace *ace; - int nt_acl_type; - int i; + /* + * Create the NT ACE list from the canonical ace lists. + */ - if (nt4_compatible_acls() && dir_ace) { - /* - * NT 4 chokes if an ACL contains an INHERIT_ONLY entry - * but no non-INHERIT_ONLY entry for one SID. So we only - * remove entries from the Access ACL if the - * corresponding Default ACL entries have also been - * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP - * are exceptions. We can do nothing - * intelligent if the Default ACL contains entries that - * are not also contained in the Access ACL, so this - * case will still fail under NT 4. - */ + { + canon_ace *ace; + int nt_acl_type; + int i; - ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); + if (nt4_compatible_acls() && dir_ace) { + /* + * NT 4 chokes if an ACL contains an INHERIT_ONLY entry + * but no non-INHERIT_ONLY entry for one SID. So we only + * remove entries from the Access ACL if the + * corresponding Default ACL entries have also been + * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP + * are exceptions. We can do nothing + * intelligent if the Default ACL contains entries that + * are not also contained in the Access ACL, so this + * case will still fail under NT 4. + */ - ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL); + ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); if (ace && !ace->perms) { - DLIST_REMOVE(file_ace, ace); + DLIST_REMOVE(dir_ace, ace); SAFE_FREE(ace); + + ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } } - } - /* - * WinNT doesn't usually have Creator Group - * in browse lists, so we send this entry to - * WinNT even if it contains no relevant - * permissions. Once we can add - * Creator Group to browse lists we can - * re-enable this. - */ + /* + * WinNT doesn't usually have Creator Group + * in browse lists, so we send this entry to + * WinNT even if it contains no relevant + * permissions. Once we can add + * Creator Group to browse lists we can + * re-enable this. + */ #if 0 - ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); - } + ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + } #endif - ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(file_ace, ace); - SAFE_FREE(ace); + ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } + } else { + + ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + } + ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + } } - } else { + + num_acls = count_canon_ace_list(file_ace); + num_dir_acls = count_canon_ace_list(dir_ace); - ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); - } - ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); + /* Allocate the ace list. */ + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); + goto done; } - } - - num_acls = count_canon_ace_list(file_ace); - num_dir_acls = count_canon_ace_list(dir_ace); - - /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); - goto done; - } - memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); - - /* - * Create the NT ACE list from the canonical ace lists. - */ - - ace = file_ace; - - for (i = 0; i < num_acls; i++, ace = ace->next) { - SEC_ACCESS acc; + memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + + /* + * Create the NT ACE list from the canonical ace lists. + */ + + ace = file_ace; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0); - } + for (i = 0; i < num_acls; i++, ace = ace->next) { + SEC_ACCESS acc; - /* The User must have access to a profile share - even if we can't map the SID. */ - if (lp_profile_acls(SNUM(fsp->conn))) { - SEC_ACCESS acc; + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0); + } - init_sec_access(&acc,FILE_GENERIC_ALL); - init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, 0); - } + /* The User must have access to a profile share - even if we can't map the SID. */ + if (lp_profile_acls(SNUM(fsp->conn))) { + SEC_ACCESS acc; - ace = dir_ace; + init_sec_access(&acc,FILE_GENERIC_ALL); + init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, 0); + } - for (i = 0; i < num_dir_acls; i++, ace = ace->next) { - SEC_ACCESS acc; + ace = dir_ace; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, - SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - } + for (i = 0; i < num_dir_acls; i++, ace = ace->next) { + SEC_ACCESS acc; + + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + } - /* The User must have access to a profile share - even if we can't map the SID. */ - if (lp_profile_acls(SNUM(fsp->conn))) { - SEC_ACCESS acc; + /* The User must have access to a profile share - even if we can't map the SID. */ + if (lp_profile_acls(SNUM(fsp->conn))) { + SEC_ACCESS acc; - init_sec_access(&acc,FILE_GENERIC_ALL); - init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, - SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY); - } - - /* - * Merge POSIX default ACLs and normal ACLs into one NT ACE. - * Win2K needs this to get the inheritance correct when replacing ACLs - * on a directory tree. Based on work by Jim @ IBM. - */ + init_sec_access(&acc,FILE_GENERIC_ALL); + init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY); + } - num_aces = merge_default_aces(nt_ace_list, num_aces); + /* + * Merge POSIX default ACLs and normal ACLs into one NT ACE. + * Win2K needs this to get the inheritance correct when replacing ACLs + * on a directory tree. Based on work by Jim @ IBM. + */ - /* - * Sort to force deny entries to the front. - */ + num_aces = merge_default_aces(nt_ace_list, num_aces); - if (num_aces) - qsort( nt_ace_list, num_aces, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp); - } + /* + * Sort to force deny entries to the front. + */ + + if (num_aces) + qsort( nt_ace_list, num_aces, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp); + } - if (num_aces) { - if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); - goto done; + if (num_aces) { + if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); + goto done; + } } - } + } /* security_info & DACL_SECURITY_INFORMATION */ - *ppdesc = make_standard_sec_desc( main_loop_talloc_get(), &owner_sid, &group_sid, psa, &sd_size); + *ppdesc = make_standard_sec_desc( main_loop_talloc_get(), + (security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL, + (security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL, + psa, + &sd_size); if(!*ppdesc) { DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 2160bca9f7..f923d22aea 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -576,22 +576,22 @@ char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const return result; } -size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, SEC_DESC **ppdesc) +size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc) { size_t result; START_PROFILE(fget_nt_acl); - result = get_nt_acl(fsp, ppdesc); + result = get_nt_acl(fsp, security_info, ppdesc); END_PROFILE(fget_nt_acl); return result; } -size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, SEC_DESC **ppdesc) +size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc) { size_t result; START_PROFILE(get_nt_acl); - result = get_nt_acl(fsp, ppdesc); + result = get_nt_acl(fsp, security_info, ppdesc); END_PROFILE(get_nt_acl); return result; } -- cgit From 974d402d6dec202109a3fb7896e52581ebb5d4ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 May 2003 23:07:33 +0000 Subject: Ensure 'blank' entries show up in both default and normal entries to allow them to be changed. Works well with W2K and above. Jeremy. (This used to be commit 685e4e518236079f201650f26152f6f9ad3c61ab) --- source3/smbd/posix_acls.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9773076a46..12eef46595 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2324,20 +2324,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) DLIST_REMOVE(file_ace, ace); SAFE_FREE(ace); } - } else { - - ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); - } - ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); - } } - + num_acls = count_canon_ace_list(file_ace); num_dir_acls = count_canon_ace_list(dir_ace); @@ -2424,6 +2412,11 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); sd_size = 0; } else { +#if 1 + /* + * JRA. Setting this flag causes W2K clients not to + * propagate ACL sets down a directory tree correctly. + */ /* * Windows 2000: The DACL_PROTECTED flag in the security * descriptor marks the ACL as non-inheriting, i.e., no @@ -2434,6 +2427,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) * flag doesn't seem to bother Windows NT. */ (*ppdesc)->type |= SE_DESC_DACL_PROTECTED; +#endif } done: -- cgit From 1fdbe30685501362fc90bdd968453f726e18c6eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 31 May 2003 01:48:59 +0000 Subject: Fixes to stop valgrind complaining about uninitialised memory when it's copying clobbered buffer areas and doing hashes on them and sending them onto the wire. Jeremy. (This used to be commit 7dfcf714ae2e81fece489640e2341f132c9f567d) --- source3/smbd/connection.c | 7 +++++++ source3/smbd/negprot.c | 9 +++++++++ 2 files changed, 16 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5547309a81..92aaebab1f 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -41,6 +41,13 @@ static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *p pkey->pid = sys_getpid(); pkey->cnum = conn?conn->cnum:-1; fstrcpy(pkey->name, name); +#ifdef DEVELOPER + { + size_t sl = strlen(pkey->name); + if (sizeof(fstring)-sl) + memset(&pkey->name[sl], '\0', sizeof(fstring)-sl); + } +#endif pkbuf->dptr = (char *)pkey; pkbuf->dsize = sizeof(*pkey); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index bd1b9b0d57..648801e955 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -182,6 +182,15 @@ static int negprot_spnego(char *p) ZERO_STRUCT(guid); safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1); + +#ifdef DEVELOPER + { + size_t sl = strlen(guid); + if (sizeof(guid)-sl) + memset(&guid[sl], '\0', sizeof(guid)-sl); + } +#endif + strlower((char *)guid); #if 0 -- cgit From 0899066fd6afc0fa8617d9e8c6dc5f6a7ece1dc5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 31 May 2003 02:03:58 +0000 Subject: Got us happy running under valgrind again :-). Jeremy. (This used to be commit b6ab9d73610861d225d72845d4df7cf970155e39) --- source3/smbd/connection.c | 1 + source3/smbd/negprot.c | 1 + source3/smbd/trans2.c | 8 ++++++++ 3 files changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 92aaebab1f..5bb76eb3bd 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -42,6 +42,7 @@ static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *p pkey->cnum = conn?conn->cnum:-1; fstrcpy(pkey->name, name); #ifdef DEVELOPER + /* valgrind fixer... */ { size_t sl = strlen(pkey->name); if (sizeof(fstring)-sl) diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 648801e955..2a2ca25532 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -184,6 +184,7 @@ static int negprot_spnego(char *p) safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1); #ifdef DEVELOPER + /* valgrind fixer... */ { size_t sl = strlen(guid); if (sizeof(guid)-sl) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f43a65af5c..161dc629dc 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -683,6 +683,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); +#ifdef DEVELOPER + /* valgrind fixer... */ + { + size_t sl = strlen(p+2); + if (24-sl) + memset(&p[sl+2], '\0', 24-sl); + } +#endif SSVAL(p, 0, len); } else { SSVAL(p,0,0); -- cgit From 71b0b6007e54da1be7f7fe5fc6401c36a05e217e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 1 Jun 2003 13:25:16 +0000 Subject: fixed the ALL_INFO and ALL_INFORMATION trans2 QFILEINFO levels. The structure we were using was completely wrong after the first few parameters. found by samba4 testsuite. Lots of other stuff also fails, but is harder to fix. (This used to be commit 6f34bd423ebb805e1e5a3b61bb5b2ca8530ce69d) --- source3/smbd/trans2.c | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 161dc629dc..a911bb5dde 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2032,6 +2032,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_QUERY_FILE_ALL_INFO: + case SMB_FILE_ALL_INFORMATION: put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ @@ -2044,19 +2045,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; - SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); - pdata += 8; /* index number */ pdata += 4; /* EA info */ - if (mode & aRONLY) - SIVAL(pdata,0,0xA9); - else - SIVAL(pdata,0,0xd01BF); - pdata += 4; - SOFF_T(pdata,0,pos); /* current offset */ - pdata += 8; - SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ - pdata += 4; - pdata += 4; /* alignment */ len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE); SIVAL(pdata,0,len); pdata += 4 + len; @@ -2110,28 +2099,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 4; break; -#if 0 - /* Not yet finished... JRA */ - case 1018: - { - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - SIVAL(pdata,32,mode); - SIVAL(pdata,36,0); /* ??? */ - SIVAL(pdata,40,0x20); /* ??? */ - SIVAL(pdata,44,0); /* ??? */ - SOFF_T(pdata,48,size); - SIVAL(pdata,56,0x1); /* ??? */ - SIVAL(pdata,60,0); /* ??? */ - SIVAL(pdata,64,0); /* ??? */ - SIVAL(pdata,68,length); /* Following string length in bytes. */ - dos_PutUniCode(pdata+72,,False); - break; - } -#endif - #if 0 /* * NT4 server just returns "invalid query" to this - if we try to answer @@ -2155,7 +2122,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_FILE_COMPRESSION_INFORMATION: - SOFF_T(pdata,0,allocation_size); + SOFF_T(pdata,0,file_size); SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ data_size = 16; -- cgit From 3db0d893f3d3b16cf0402c049e0534a23d9ccd75 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 1 Jun 2003 13:43:21 +0000 Subject: added the COMPRESSION_INFO trans2 QFILEINFO level and fixed the IS_NAME_VALID QPATHINFO level (This used to be commit 1634346e2a6e73af80d4e68d50c6398fb24869a5) --- source3/smbd/trans2.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a911bb5dde..8364c4b509 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1932,6 +1932,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ break; + case SMB_INFO_IS_NAME_VALID: + if (tran_call == TRANSACT2_QFILEINFO) { + /* os/2 needs this ? really ?*/ + return ERROR_DOS(ERRDOS,ERRbadfunc); + } + data_size = 0; + break; + case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; put_dos_date2(pdata,0,c_time); @@ -1947,9 +1955,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,data_size); break; - case 6: - return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */ - case SMB_FILE_BASIC_INFORMATION: case SMB_QUERY_FILE_BASIC_INFO: @@ -2121,6 +2126,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } break; + case SMB_QUERY_COMPRESSION_INFO: case SMB_FILE_COMPRESSION_INFORMATION: SOFF_T(pdata,0,file_size); SIVAL(pdata,8,0); /* ??? */ -- cgit From 878944f1ec521eb70f3e28cd12abef4c21edcbf6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jun 2003 05:45:40 +0000 Subject: shouldn't null terminate trans2 qfileinfo all_info/name (This used to be commit f7cd16ab58753be25bc9c7b487289361e3882da3) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8364c4b509..dcbb543c64 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2051,7 +2051,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; pdata += 4; /* EA info */ - len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+4, dos_fname, -1, 0); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); -- cgit From b6cb0e914d10524721d51fb01fcd84d476f30157 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jun 2003 06:03:21 +0000 Subject: fixed the termination of several trans2 strings (This used to be commit 8f23ad3054febe47b667172d680d2d19ad141416) --- source3/smbd/trans2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dcbb543c64..4498f0727b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1368,7 +1368,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf * the called hostname and the service name. */ SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 0); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", @@ -1397,7 +1397,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf case SMB_QUERY_FS_LABEL_INFO: case SMB_FS_LABEL_INFORMATION: - len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+4, vname, -1, 0); data_len = 4 + len; SIVAL(pdata,0,len); break; @@ -1412,7 +1412,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16)); - len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+18, vname, -1, 0); SIVAL(pdata,12,len); data_len = 18+len; DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", -- cgit From 6fe5940109c587a2a1dbb63db331f0d6b34bd41b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Jun 2003 00:04:27 +0000 Subject: Added EA operations to VFS layer. Jeremy. (This used to be commit 024de9213e414659296cb518a6753e510c64f614) --- source3/smbd/vfs-wrap.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/vfs.c | 18 +++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index f923d22aea..8d44a1a0fa 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -785,3 +785,67 @@ int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct return -1; #endif } + +/**************************************************************** + Extended attribute operations. +*****************************************************************/ + +ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) +{ + return sys_getxattr(path, name, value, size); +} + +ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) +{ + return sys_lgetxattr(path, name, value, size); +} + +ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) +{ + return sys_fgetxattr(fd, name, value, size); +} + +ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +{ + return sys_listxattr(path, list, size); +} + +ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +{ + return sys_llistxattr(path, list, size); +} + +ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size) +{ + return sys_flistxattr(fd, list, size); +} + +int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +{ + return sys_removexattr(path, name); +} + +int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +{ + return sys_lremovexattr(path, name); +} + +int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name) +{ + return sys_fremovexattr(fd, name); +} + +int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +{ + return sys_setxattr(path, name, value, size, flags); +} + +int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +{ + return sys_lsetxattr(path, name, value, size, flags); +} + +int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags) +{ + return sys_fsetxattr(fd, name, value, size, flags); +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index d24ae54d42..5f3abe7efe 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -94,6 +94,7 @@ static struct vfs_ops default_vfs = { vfswrap_mknod, vfswrap_realpath, + /* Windows ACL operations. */ vfswrap_fget_nt_acl, vfswrap_get_nt_acl, vfswrap_fset_nt_acl, @@ -124,7 +125,22 @@ static struct vfs_ops default_vfs = { vfswrap_sys_acl_get_perm, vfswrap_sys_acl_free_text, vfswrap_sys_acl_free_acl, - vfswrap_sys_acl_free_qualifier + vfswrap_sys_acl_free_qualifier, + + /* EA operations. */ + vfswrap_getxattr, + vfswrap_lgetxattr, + vfswrap_fgetxattr, + vfswrap_listxattr, + vfswrap_llistxattr, + vfswrap_flistxattr, + vfswrap_removexattr, + vfswrap_lremovexattr, + vfswrap_fremovexattr, + vfswrap_setxattr, + vfswrap_lsetxattr, + vfswrap_fsetxattr + } }; -- cgit From 7d4b53c2aaef07f03b5d4a066ea8b2abb10926f9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 04:21:43 +0000 Subject: removed the 'valgrind fix' that (although it may well remove a valgrind warning) causes us to return a completely wrong 8.3 filename in directory searches! come on guys, this close to a release you need to TEST CODE BEFORE COMMITTING (This used to be commit 381cea68b81aeb42b088677d2a8bfd410a7da329) --- source3/smbd/trans2.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4498f0727b..70e41010a1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -683,14 +683,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); -#ifdef DEVELOPER - /* valgrind fixer... */ - { - size_t sl = strlen(p+2); - if (24-sl) - memset(&p[sl+2], '\0', 24-sl); - } -#endif SSVAL(p, 0, len); } else { SSVAL(p,0,0); -- cgit From d51b463b3fa8915c99857a5cb0a051e2fb957e74 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 04:29:41 +0000 Subject: fixed the layout of the FULL_DIRECTORY_INFO trans2 findfirst level found by samba4 smbtorture SEARCH test (This used to be commit 5a5f59cf5eec39394b8aec4aab7f2c347d617255) --- source3/smbd/trans2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 70e41010a1..0aa0087c26 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -729,13 +729,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,file_size); SOFF_T(p,8,allocation_size); p += 16; - SIVAL(p,0,nt_extmode); p += 4; + SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,0); p += 4; - len = srvstr_push(outbuf, p, fname, -1, 0); - SIVAL(p, -4, len); - p += len; + SIVAL(p,4,0); /* ea size */ + len = srvstr_push(outbuf, p+8, fname, -1, 0); + SIVAL(p, 0, len); + p += 8 + len; len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; -- cgit From 32bf831e25718653c955fea10d4f6b1b8ca7a192 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 04:31:48 +0000 Subject: fixed the string alignment of the QUERY_EA_SIZE trans2 findfirst level (This used to be commit ff5e37ed293b61c2585c66e7366fae478754cca1) --- source3/smbd/trans2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0aa0087c26..fa64883620 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -649,8 +649,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,l2_cbList,0); /* No extended attributes */ p += l2_achName; nameptr = p; - p += align_string(outbuf, p, 0); - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN); if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) SCVAL(nameptr, -1, len-2); else -- cgit From 6b943b5b2188314739f4f36541f1ef469ba9a3b3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 05:15:28 +0000 Subject: - the 8.3 name in BOTH_DIRECTORY_INFO is supposed to be always unicode (to match win2003 behaviour) - added the STR_TERMINATE_ASCII flag from samba4 so we can get the string termination right for the case where it is supposed to be non-terminated for UCS2 and terminated when ASCII (This used to be commit 791a4cc7cf84eca77116bca00aeb5f95560f6705) --- source3/smbd/trans2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fa64883620..b20ec84eea 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -681,14 +681,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(mangled_name, fname); mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; - len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); + len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); } else { SSVAL(p,0,0); *(p+2) = 0; } p += 2 + 24; - len = srvstr_push(outbuf, p, fname, -1, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; len = PTR_DIFF(p, pdata); @@ -709,7 +709,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 16; SIVAL(p,0,nt_extmode); p += 4; p += 4; - len = srvstr_push(outbuf, p, fname, -1, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); @@ -732,7 +732,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; SIVAL(p,4,0); /* ea size */ - len = srvstr_push(outbuf, p+8, fname, -1, 0); + len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, 0, len); p += 8 + len; @@ -748,7 +748,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; /* this must *not* be null terminated or w2k gets in a loop trying to set an acl on a dir (tridge) */ - len = srvstr_push(outbuf, p, fname, -1, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); -- cgit From e35917bb9337200edd0d92044f4d4817e9feb891 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 05:32:36 +0000 Subject: make the allocation_size consistent between trans2 QFILEINFO and SMBgetattrE (This used to be commit 59f1a5e6fd783b977f787dae4ba4bb8b65c41e43) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7a0cc0287a..7f0ffd7577 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4385,8 +4385,9 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, SIVAL(outbuf,smb_vwv6,0); SIVAL(outbuf,smb_vwv8,0); } else { + uint32 allocation_size = get_allocation_size(fsp, &sbuf); SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); - SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024)); + SIVAL(outbuf,smb_vwv8,allocation_size); } SSVAL(outbuf,smb_vwv10, mode); -- cgit From dc5f0b28cf8c90a1cda08955c4029b2d3902420e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 05:34:02 +0000 Subject: - the ALL_INFO trans2 QFILEINFO level uses a forced UCS2 name - win2003 returns 0 for ea_size when there are no EAs (This used to be commit 83e0c21831f32aad2dfb6ebe4a27c7a0d2adb692) --- source3/smbd/trans2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b20ec84eea..ba6162833b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1920,7 +1920,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,l1_cbFile,(uint32)file_size); SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(pdata,l1_attrFile,mode); - SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ + SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */ break; case SMB_INFO_IS_NAME_VALID: @@ -1943,7 +1943,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_INFO_QUERY_ALL_EAS: data_size = 4; - SIVAL(pdata,0,data_size); + SIVAL(pdata,0,0); /* ea size */ break; case SMB_FILE_BASIC_INFORMATION: @@ -2042,7 +2042,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; pdata += 4; /* EA info */ - len = srvstr_push(outbuf, pdata+4, dos_fname, -1, 0); + len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); -- cgit From 7e82bf284c71665f2038e5f6b64ffce9c1d73092 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 06:01:45 +0000 Subject: 2 more places where win2003 forces UCS2 (This used to be commit b64f6e52ec8aa0892b405d3360079ababc8527f4) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ba6162833b..2bf250a980 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1381,7 +1381,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it and will think we can't do long filenames */ - len = srvstr_push(outbuf, pdata+12, fstype, -1, 0); + len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE); SIVAL(pdata,8,len); data_len = 12 + len; break; @@ -1403,7 +1403,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16)); - len = srvstr_push(outbuf, pdata+18, vname, -1, 0); + len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE); SIVAL(pdata,12,len); data_len = 18+len; DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", -- cgit From 53f8d3f01aed0118bafa36c8eabfc558e29f91dd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2003 10:42:16 +0000 Subject: SMBlockingX timeouts are in units of 2 milliseconds, not 1 (This used to be commit 999cde3227210c90132ade3812e964087f04e541) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7f0ffd7577..be51a32891 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3941,7 +3941,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* Setup the timeout in seconds. */ - lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000); + lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500); /* Now do any requested locks */ data += ((large_file_format ? 20 : 10)*num_ulocks); -- cgit From 71298881c4a630666c1a14be99048f8f86e48162 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 6 Jun 2003 22:33:43 +0000 Subject: * add in David Lee's utmp patch (defaults to on if available) * one more try at fixing builds when --with-ldap=no (This used to be commit b516ab7bdef6b6b2b7f0df8966dbd4c329f46a92) --- source3/smbd/session.c | 6 ------ source3/smbd/utmp.c | 23 ++++++++++++++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index b7f3bc43e7..4d8826d332 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -66,7 +66,6 @@ BOOL session_claim(user_struct *vuser) data.dptr = NULL; data.dsize = 0; -#if WITH_UTMP if (lp_utmp()) { for (i=1;isession_keystr = strdup(keystr); if (!vuser->session_keystr) { @@ -181,13 +177,11 @@ void session_yield(user_struct *vuser) SAFE_FREE(dbuf.dptr); -#if WITH_UTMP if (lp_utmp()) { sys_utmp_yield(sessionid.username, sessionid.hostname, client_ip, sessionid.id_str, sessionid.id_num); } -#endif smb_pam_close_session(sessionid.username, sessionid.id_str, sessionid.hostname); diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 2c5a1abc82..9833a11f2d 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -21,8 +21,6 @@ #include "includes.h" -#ifdef WITH_UTMP - /**************************************************************************** Reflect connection status in utmp/wtmp files. T.D.Lee@durham.ac.uk September 1999 @@ -110,6 +108,23 @@ Notes: ****************************************************************************/ +#ifndef WITH_UTMP +/* + * Not WITH_UTMP? Simply supply dummy routines. + */ + +void sys_utmp_claim(const char *username, const char *hostname, + struct in_addr *ipaddr, + const char *id_str, int id_num) +{} + +void sys_utmp_yield(const char *username, const char *hostname, + struct in_addr *ipaddr, + const char *id_str, int id_num) +{} + +#else /* WITH_UTMP */ + #include #ifdef HAVE_UTMPX_H @@ -571,6 +586,4 @@ void sys_utmp_claim(const char *username, const char *hostname, sys_utmp_update(&u, hostname, True); } -#else /* WITH_UTMP */ - void dummy_utmp(void) {} -#endif +#endif /* WITH_UTMP */ -- cgit From 1079bd40c50b75324464ea059141656b23ccf31a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 7 Jun 2003 03:20:09 +0000 Subject: Don't assume that the SAM knows the unix home directory - look it up by getpwnam() if need be. Fixes bug #130 Andrew Bartlett (This used to be commit a4bc789a3993be4b25955c729b533b86dba666f4) --- source3/smbd/password.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 283eed73ef..9560449aa5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -168,16 +168,24 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) { /* Keep the homedir handy */ const char *homedir = pdb_get_homedir(server_info->sam_account); - const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); const char *logon_script = pdb_get_logon_script(server_info->sam_account); + + if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) { + const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); + if (unix_homedir) { + vuser->unix_homedir = smb_xstrdup(unix_homedir); + } + } else { + struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name); + if (passwd) { + vuser->unix_homedir = smb_xstrdup(passwd->pw_dir); + passwd_free(&passwd); + } + } + if (homedir) { vuser->homedir = smb_xstrdup(homedir); } - - if (unix_homedir) { - vuser->unix_homedir = smb_xstrdup(unix_homedir); - } - if (logon_script) { vuser->logon_script = smb_xstrdup(logon_script); } -- cgit From 3d0d8f609d08a41faa8607fa374816bcde48a62e Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 13 Jun 2003 17:49:03 +0000 Subject: Fix an spelling mistake. (This used to be commit 8e37c1d579ed801fd602d698174f981deff435d9) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index be51a32891..e7f01ad02f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -39,7 +39,7 @@ unsigned int smb_echo_count = 0; extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** - Reply to an special message. + Reply to a special message. ****************************************************************************/ int reply_special(char *inbuf,char *outbuf) -- cgit From 75a5c0b307a79536316b651273d3f6983323f5ce Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 18 Jun 2003 15:24:10 +0000 Subject: Ok, this patch removes the privilege stuff we had in, unused, for some time. The code was nice, but put in the wrong place (group mapping) and not supported by most of the code, thus useless. We will put back most of the code when our infrastructure will be changed so that privileges actually really make sense to be set. This is a first patch of a set to enhance all our mapping code cleaness and stability towards a sane next beta for 3.0 code base Simo. (This used to be commit e341e7c49f8c17a9ee30ca3fab3aa0397c1f0c7e) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 98857c6d32..6976a06684 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1649,7 +1649,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c return False; /* get list of domain groups SID_DOMAIN_GRP=2 */ - if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) { + if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False)) { DEBUG(3,("api_RNetGroupEnum:failed to get group list")); return False; } -- cgit From 9251afe35bc402bbab816d7c33673d4ef3fb0351 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Jun 2003 01:12:20 +0000 Subject: Mapping of Windows ACL inheritance and protected bits onto extended attributes if available. Adds new parameter "map acl inheritance" (docs coming soon) off by default. Allows W2K acl inheritance dialogs to work correctly on POSIX acls. Jeremy. (This used to be commit a83595e80ae539135fa1a65d6066b10ac94fbad1) --- source3/smbd/posix_acls.c | 477 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 461 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 12eef46595..9f15bf1560 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -42,10 +42,446 @@ typedef struct canon_ace { enum ace_owner owner_type; enum ace_attribute attr; posix_id unix_ug; + BOOL inherited; } canon_ace; #define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR) +/* + * EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance) + * attribute on disk. + * + * | 1 | 1 | 2 | 2 | .... + * +------+------+-------------+---------------------+-------------+--------------------+ + * | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... | + * +------+------+-------------+---------------------+-------------+--------------------+ + */ + +#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI" + +#define PAI_VERSION_OFFSET 0 +#define PAI_FLAG_OFFSET 1 +#define PAI_NUM_ENTRIES_OFFSET 2 +#define PAI_NUM_DEFAULT_ENTRIES_OFFSET 4 +#define PAI_ENTRIES_BASE 6 + +#define PAI_VERSION 1 +#define PAI_ACL_FLAG_PROTECTED 0x1 +#define PAI_ENTRY_LENGTH 5 + +/* + * In memory format of user.SAMBA_PAI attribute. + */ + +struct pai_entry { + struct pai_entry *next, *prev; + enum ace_owner owner_type; + posix_id unix_ug; +}; + +struct pai_val { + BOOL protected; + unsigned int num_entries; + struct pai_entry *entry_list; + unsigned int num_def_entries; + struct pai_entry *def_entry_list; +}; + +/************************************************************************ + Return a uint32 of the pai_entry principal. +************************************************************************/ + +static uint32 get_pai_entry_val(struct pai_entry *paie) +{ + switch (paie->owner_type) { + case UID_ACE: + DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid )); + return (uint32)paie->unix_ug.uid; + case GID_ACE: + DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid )); + return (uint32)paie->unix_ug.gid; + case WORLD_ACE: + default: + DEBUG(10,("get_pai_entry_val: world ace\n")); + return (uint32)-1; + } +} + +/************************************************************************ + Return a uint32 of the entry principal. +************************************************************************/ + +static uint32 get_entry_val(canon_ace *ace_entry) +{ + switch (ace_entry->owner_type) { + case UID_ACE: + DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid )); + return (uint32)ace_entry->unix_ug.uid; + case GID_ACE: + DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid )); + return (uint32)ace_entry->unix_ug.gid; + case WORLD_ACE: + default: + DEBUG(10,("get_entry_val: world ace\n")); + return (uint32)-1; + } +} + +/************************************************************************ + Count the inherited entries. +************************************************************************/ + +static unsigned int num_inherited_entries(canon_ace *ace_list) +{ + unsigned int num_entries = 0; + + for (; ace_list; ace_list = ace_list->next) + if (ace_list->inherited) + num_entries++; + return num_entries; +} + +/************************************************************************ + Create the on-disk format. Caller must free. +************************************************************************/ + +static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL protected, size_t *store_size) +{ + char *pai_buf = NULL; + canon_ace *ace_list = NULL; + char *entry_offset = NULL; + unsigned int num_entries = 0; + unsigned int num_def_entries = 0; + + for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) + if (ace_list->inherited) + num_entries++; + + for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) + if (ace_list->inherited) + num_def_entries++; + + *store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH); + + pai_buf = malloc(*store_size); + if (!pai_buf) { + return NULL; + } + + /* Set up the header. */ + memset(pai_buf, '\0', PAI_ENTRIES_BASE); + SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_VERSION); + SCVAL(pai_buf,PAI_FLAG_OFFSET,(protected ? PAI_ACL_FLAG_PROTECTED : 0)); + SSVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET,num_entries); + SSVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries); + + entry_offset = pai_buf + PAI_ENTRIES_BASE; + + for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) { + if (ace_list->inherited) { + uint8 type_val = (unsigned char)ace_list->owner_type; + uint32 entry_val = get_entry_val(ace_list); + + SCVAL(entry_offset,0,type_val); + SIVAL(entry_offset,1,entry_val); + entry_offset += PAI_ENTRY_LENGTH; + } + } + + for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) { + if (ace_list->inherited) { + uint8 type_val = (unsigned char)ace_list->owner_type; + uint32 entry_val = get_entry_val(ace_list); + + SCVAL(entry_offset,0,type_val); + SIVAL(entry_offset,1,entry_val); + entry_offset += PAI_ENTRY_LENGTH; + } + } + + return pai_buf; +} + +/************************************************************************ + Store the user.SAMBA_PAI attribute on disk. +************************************************************************/ + +static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list, + canon_ace *dir_ace_list, BOOL protected) +{ + int ret; + size_t store_size; + char *pai_buf; + + if (!lp_map_acl_inherit(SNUM(fsp->conn))) + return; + + /* + * Don't store if this ACL isn't protected and + * none of the entries in it are marked as inherited. + */ + + if (!protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) { + /* Instead just remove the attribute if it exists. */ + if (fsp->fd != -1) + SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME); + else + SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME); + return; + } + + pai_buf = create_pai_buf(file_ace_list, dir_ace_list, protected, &store_size); + + if (fsp->fd != -1) + ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, store_size, 0); + else + ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, store_size, 0); + + SAFE_FREE(pai_buf); + + DEBUG(10,("store_inheritance_attribute:%s for file %s\n", protected ? " (protected)" : "", fsp->fsp_name)); + if (ret == -1 && errno != ENOSYS) + DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) )); +} + +/************************************************************************ + Delete the in memory inheritance info. +************************************************************************/ + +static void free_inherited_info(struct pai_val *pal) +{ + if (pal) { + struct pai_entry *paie, *paie_next; + for (paie = pal->entry_list; paie; paie = paie_next) { + paie_next = paie->next; + SAFE_FREE(paie); + } + for (paie = pal->def_entry_list; paie; paie = paie_next) { + paie_next = paie->next; + SAFE_FREE(paie); + } + SAFE_FREE(pal); + } +} + +/************************************************************************ + Was this ACL protected ? +************************************************************************/ + +static BOOL get_protected_flag(struct pai_val *pal) +{ + if (!pal) + return False; + return pal->protected; +} + +/************************************************************************ + Was this ACE inherited ? +************************************************************************/ + +static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL default_ace) +{ + struct pai_entry *paie; + + if (!pal) + return False; + + /* If the entry exists it is inherited. */ + for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) { + if (ace_entry->owner_type == paie->owner_type && + get_entry_val(ace_entry) == get_pai_entry_val(paie)) + return True; + } + return False; +} + +/************************************************************************ + Ensure an attribute just read is valid. +************************************************************************/ + +static BOOL check_pai_ok(char *pai_buf, size_t pai_buf_data_size) +{ + uint16 num_entries; + uint16 num_def_entries; + + if (pai_buf_data_size < PAI_ENTRIES_BASE) { + /* Corrupted - too small. */ + return False; + } + + if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_VERSION) + return False; + + num_entries = SVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET); + num_def_entries = SVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET); + + /* Check the entry lists match. */ + /* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */ + + if (((num_entries + num_def_entries)*PAI_ENTRY_LENGTH) + PAI_ENTRIES_BASE != pai_buf_data_size) + return False; + + return True; +} + + +/************************************************************************ + Convert to in-memory format. +************************************************************************/ + +static struct pai_val *create_pai_val(char *buf, size_t size) +{ + char *entry_offset; + struct pai_val *paiv = NULL; + int i; + + if (!check_pai_ok(buf, size)) + return NULL; + + paiv = malloc(sizeof(struct pai_val)); + if (!paiv) + return NULL; + + memset(paiv, '\0', sizeof(struct pai_val)); + + paiv->protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED); + + paiv->num_entries = SVAL(buf,PAI_NUM_ENTRIES_OFFSET); + paiv->num_def_entries = SVAL(buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET); + + entry_offset = buf + PAI_ENTRIES_BASE; + + DEBUG(10,("create_pai_val:%s num_entries = %u, num_def_entries = %u\n", + paiv->protected ? " (protected)" : "", paiv->num_entries, paiv->num_def_entries )); + + for (i = 0; i < paiv->num_entries; i++) { + struct pai_entry *paie; + + paie = malloc(sizeof(struct pai_entry)); + if (!paie) { + free_inherited_info(paiv); + return NULL; + } + + paie->owner_type = (enum ace_owner)CVAL(entry_offset,0); + switch( paie->owner_type) { + case UID_ACE: + paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: uid = %u\n", (unsigned int)paie->unix_ug.uid )); + break; + case GID_ACE: + paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: gid = %u\n", (unsigned int)paie->unix_ug.gid )); + break; + case WORLD_ACE: + paie->unix_ug.world = -1; + DEBUG(10,("create_pai_val: world ace\n")); + break; + default: + free_inherited_info(paiv); + return NULL; + } + entry_offset += PAI_ENTRY_LENGTH; + DLIST_ADD(paiv->entry_list, paie); + } + + for (i = 0; i < paiv->num_def_entries; i++) { + struct pai_entry *paie; + + paie = malloc(sizeof(struct pai_entry)); + if (!paie) { + free_inherited_info(paiv); + return NULL; + } + + paie->owner_type = (enum ace_owner)CVAL(entry_offset,0); + switch( paie->owner_type) { + case UID_ACE: + paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: (def) uid = %u\n", (unsigned int)paie->unix_ug.uid )); + break; + case GID_ACE: + paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: (def) gid = %u\n", (unsigned int)paie->unix_ug.gid )); + break; + case WORLD_ACE: + paie->unix_ug.world = -1; + DEBUG(10,("create_pai_val: (def) world ace\n")); + break; + default: + free_inherited_info(paiv); + return NULL; + } + entry_offset += PAI_ENTRY_LENGTH; + DLIST_ADD(paiv->def_entry_list, paie); + } + + return paiv; +} + +/************************************************************************ + Load the user.SAMBA_PAI attribute. +************************************************************************/ + +static struct pai_val *load_inherited_info(files_struct *fsp) +{ + char *pai_buf; + size_t pai_buf_size = 1024; + struct pai_val *paiv = NULL; + ssize_t ret; + + if (!lp_map_acl_inherit(SNUM(fsp->conn))) + return NULL; + + if ((pai_buf = malloc(pai_buf_size)) == NULL) + return NULL; + + do { + if (fsp->fd != -1) + ret = SMB_VFS_FGETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, pai_buf_size); + else + ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, pai_buf_size); + + if (ret == -1) { + if (errno != ERANGE) { + break; + } + /* Buffer too small - enlarge it. */ + pai_buf_size *= 2; + SAFE_FREE(pai_buf); + if ((pai_buf = malloc(pai_buf_size)) == NULL) + return NULL; + } + } while (ret == -1); + + DEBUG(10,("load_inherited_info: ret = %d for file %s\n", ret, fsp->fsp_name)); + + if (ret == -1) { + /* No attribute or not supported. */ +#if defined(ENOATTR) + if (errno != ENOATTR) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#else + if (errno != ENOSYS) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#endif + SAFE_FREE(pai_buf); + return NULL; + } + + paiv = create_pai_val(pai_buf, ret); + + if (paiv && paiv->protected) + DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fsp->fsp_name)); + + SAFE_FREE(pai_buf); + return paiv; +} + /**************************************************************************** Functions to manipulate the internal ACE format. ****************************************************************************/ @@ -106,7 +542,7 @@ static void print_canon_ace(canon_ace *pace, int num) dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); if (pace->owner_type == UID_ACE) { const char *u_name = uidtoname(pace->unix_ug.uid); - dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name); + dbgtext( "uid %u (%s) %s", (unsigned int)pace->unix_ug.uid, u_name, pace->inherited ? "(inherited) " : ""); } else if (pace->owner_type == GID_ACE) { char *g_name = gidtoname(pace->unix_ug.gid); dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name); @@ -949,6 +1385,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE; + current_ace->inherited = ((psa->flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False); /* * Now add the created ace to either the file list, the directory @@ -1616,7 +2053,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) ****************************************************************************/ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup, SMB_ACL_TYPE_T the_acl_type) + DOM_SID *powner, DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { extern DOM_SID global_sid_World; connection_struct *conn = fsp->conn; @@ -1723,6 +2160,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ ace->trustee = sid; ace->unix_ug = unix_ug; ace->owner_type = owner_type; + ace->inherited = get_inherited_flag(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT)); DLIST_ADD(list_head, ace); } @@ -1908,6 +2346,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if( DEBUGLVL( 10 )) print_canon_ace( p_ace, i); + } if (needs_mask && !got_mask_entry) { @@ -2186,6 +2625,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; size_t num_profile_acls = 0; + struct pai_val *pal = NULL; *ppdesc = NULL; @@ -2228,6 +2668,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) posix_acl ? "present" : "absent", dir_acl ? "present" : "absent" )); + pal = load_inherited_info(fsp); + /* * Get the owner, group and world SIDs. */ @@ -2241,7 +2683,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); } - if (security_info & DACL_SECURITY_INFORMATION) { + if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) { /* * In the optimum case Creator Owner and Creator Group would be used for @@ -2253,7 +2695,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) */ /* Create the canon_ace lists. */ - file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, SMB_ACL_TYPE_ACCESS ); + file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS ); /* We must have *some* ACLS. */ @@ -2265,7 +2707,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) if (fsp->is_directory && dir_acl) { dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, &global_sid_Creator_Owner, - &global_sid_Creator_Group, SMB_ACL_TYPE_DEFAULT ); + &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT ); } /* @@ -2347,7 +2789,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) SEC_ACCESS acc; acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0); + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0); } /* The User must have access to a profile share - even if we can't map the SID. */ @@ -2355,7 +2797,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) SEC_ACCESS acc; init_sec_access(&acc,FILE_GENERIC_ALL); - init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, 0); + init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, + acc, 0); } ace = dir_ace; @@ -2365,7 +2808,9 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, - SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY| + (ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0)); } /* The User must have access to a profile share - even if we can't map the SID. */ @@ -2375,7 +2820,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) init_sec_access(&acc,FILE_GENERIC_ALL); init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY); + SEC_ACE_FLAG_INHERIT_ONLY|0); } /* @@ -2412,11 +2857,6 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); sd_size = 0; } else { -#if 1 - /* - * JRA. Setting this flag causes W2K clients not to - * propagate ACL sets down a directory tree correctly. - */ /* * Windows 2000: The DACL_PROTECTED flag in the security * descriptor marks the ACL as non-inheriting, i.e., no @@ -2426,8 +2866,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) * any ACEs that are inherited dynamically. The DACL_PROTECTED * flag doesn't seem to bother Windows NT. */ - (*ppdesc)->type |= SE_DESC_DACL_PROTECTED; -#endif + if (get_protected_flag(pal)) + (*ppdesc)->type |= SE_DESC_DACL_PROTECTED; } done: @@ -2438,6 +2878,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); + free_inherited_info(pal); SAFE_FREE(nt_ace_list); return sd_size; @@ -2660,6 +3101,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) } } + if (acl_set_support) + store_inheritance_attributes(fsp, file_ace_list, dir_ace_list, + (psd->type & SE_DESC_DACL_PROTECTED) ? True : False); + /* * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. */ -- cgit From deef8647c7f8f7ce286d92ff373812f9607b7375 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Jun 2003 20:07:13 +0000 Subject: Fixed sorting algorithm to prevent problems with W2K clients. Jeremy. (This used to be commit fa8ca20ed440673d02ac5669f8d4c6623c1fdb6d) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9f15bf1560..396b955843 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2172,8 +2172,6 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf, False)) goto fail; - arrange_posix_perms(fsp->fsp_name,&list_head ); - /* * Now go through the list, masking the permissions with the * acl_mask. Ensure all DENY Entries are at the start of the list. @@ -2197,6 +2195,8 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ } } + arrange_posix_perms(fsp->fsp_name,&list_head ); + print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head ); return list_head; -- cgit From 93bcb9963bef53b91a0b16c6389cefdb7bea2b0e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 21 Jun 2003 04:05:01 +0000 Subject: merge of the netsamlogon caching code from APPLIANCE_HEAD This replaces the universal group caching code (was originally based on that code). Only applies to the the RPC code. One comment: domain local groups don't show up in 'getent group' that's easy to fix. Code has been tested against 2k domain but doesn't change anything with respect to NT4 domains. netsamlogon caching works pretty much like the universal group caching code did but has had much more testing and puts winbind mostly back in sync between branches. (This used to be commit aac01dc7bc95c20ee21c93f3581e2375d9a894e1) --- source3/smbd/server.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 07723cc20e..24cfed5be9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -855,8 +855,6 @@ void build_options(BOOL screen); init_modules(); - uni_group_cache_init(); /* Non-critical */ - /* possibly reload the services file. */ reload_services(True); @@ -891,7 +889,6 @@ void build_options(BOOL screen); smbd_process(); - uni_group_cache_shutdown(); namecache_shutdown(); exit_server("normal exit"); return(0); -- cgit From 3f5dc144578cfaa58e227177c780d4261c9242d2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 21 Jun 2003 07:54:03 +0000 Subject: Always initialize. (This used to be commit 75081860af5ace873f53c361ec34d029b7864ff7) --- source3/smbd/service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 31bb343474..11659f2870 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -366,6 +366,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } fstrcpy(user,pass->pw_name); conn->force_user = True; + conn->uid = pass->pw_uid; + conn->gid = pass->pw_gid; string_set(&conn->user,pass->pw_name); passwd_free(&pass); DEBUG(3,("Guest only user %s\n",user)); -- cgit From f5974dfaae680d98b78d600cd1f1aaece332a085 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 22 Jun 2003 10:09:52 +0000 Subject: Found out a good number of NT_STATUS_IS_ERR used the wrong way. As abartlet rememberd me NT_STATUS_IS_ERR != !NT_STATUS_IS_OK This patch will cure the problem. Working on this one I found 16 functions where I think NT_STATUS_IS_ERR() is used correctly, but I'm not 100% sure, coders should check the use of NT_STATUS_IS_ERR() in samba is ok now. Simo. (This used to be commit c501e84d412563eb3f674f76038ec48c2b458687) --- source3/smbd/mangle_hash.c | 8 ++++---- source3/smbd/ntquotas.c | 6 +++--- source3/smbd/nttrans.c | 2 +- source3/smbd/posix_acls.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index d2eb996899..d4cf369f28 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -217,7 +217,7 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards) return NT_STATUS_UNSUCCESSFUL; ret = has_valid_chars(fname, allow_wildcards); - if (NT_STATUS_IS_ERR(ret)) + if (!NT_STATUS_IS_OK(ret)) return ret; str = strdup_w(fname); @@ -285,10 +285,10 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards) if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) return NT_STATUS_OK; - if (NT_STATUS_IS_ERR(is_valid_name(fname, allow_wildcards))) + if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards))) goto done; - if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext, allow_wildcards))) + if (!NT_STATUS_IS_OK(mangle_get_prefix(fname, &pref, &ext, allow_wildcards))) goto done; plen = strlen_w(pref); @@ -735,7 +735,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83) return; } - if( !need83 && NT_STATUS_IS_ERR(is_valid_name(OutName_ucs2, False))) + if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False))) need83 = True; /* check if it's already in 8.3 format */ diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 6a217a3258..2e865000ec 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -84,7 +84,7 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, id.uid = -1; - if (psid && NT_STATUS_IS_ERR(sid_to_uid(psid, &id.uid))) { + if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", sid_string_static(psid))); } @@ -128,7 +128,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, D.isoftlimit = limit_blk2inodes(D.softlimit); D.ihardlimit = limit_blk2inodes(D.hardlimit); - if (psid && NT_STATUS_IS_ERR(sid_to_uid(psid, &id.uid))) { + if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", sid_string_static(psid))); } @@ -182,7 +182,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) continue; } - if (NT_STATUS_IS_ERR(uid_to_sid(&sid, usr->pw_uid))) { + if (!NT_STATUS_IS_OK(uid_to_sid(&sid, usr->pw_uid))) { DEBUG(0,("uid_to_sid failed for %ld\n",(long)usr->pw_uid)); continue; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fa7b78ecc2..0030acc78b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1797,7 +1797,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou sid_parse(pdata+4,sid_len,&sid); DEBUGADD(2,("SID: %s\n",sid_string_static(&sid))); - if (NT_STATUS_IS_ERR(sid_to_uid(&sid, &uid))) { + if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) { DEBUG(0,("sid_to_uid: failed, sid[%s]\n", sid_string_static(&sid))); uid = (-1); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 396b955843..c52139495c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -904,7 +904,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); - if (NT_STATUS_IS_ERR(sid_to_uid(&owner_sid, puser))) { + if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) { #if ACL_FORCE_UNMAPPABLE /* this allows take ownership to work reasonably */ extern struct current_user current_user; @@ -924,7 +924,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); - if (NT_STATUS_IS_ERR(sid_to_gid( &grp_sid, pgrp))) { + if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) { #if ACL_FORCE_UNMAPPABLE /* this allows take group ownership to work reasonably */ extern struct current_user current_user; -- cgit From 951710b60de02e7ed75ba8481b914b0277fdcfb0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Jun 2003 20:24:08 +0000 Subject: Fixed the merge_default_aces() code to work correctly with inheritance. Hopefully will fix jcmd bugs :-). Jeremy. (This used to be commit 482e6c79edefc8aaacbb37f807d2076e59b40e26) --- source3/smbd/posix_acls.c | 49 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c52139495c..209387f422 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2177,7 +2177,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * acl_mask. Ensure all DENY Entries are at the start of the list. */ - DEBUG(10,("canonicalise_acl: ace entries before arrange :\n")); + DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" )); for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { next_ace = ace->next; @@ -2571,24 +2571,51 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) for (i = 0; i < num_aces; i++) { for (j = i+1; j < num_aces; j++) { + uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE); + uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE); + BOOL i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; + BOOL j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; + /* We know the lower number ACE's are file entries. */ if ((nt_ace_list[i].type == nt_ace_list[j].type) && (nt_ace_list[i].size == nt_ace_list[j].size) && (nt_ace_list[i].info.mask == nt_ace_list[j].info.mask) && sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) && - (nt_ace_list[i].flags == 0) && - (nt_ace_list[j].flags == (SEC_ACE_FLAG_OBJECT_INHERIT| - SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY))) { + (i_inh == j_inh) && + (i_flags_ni == 0) && + (j_flags_ni == (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY))) { /* - * These are identical except for the flags. - * Merge the inherited ACE onto the non-inherited ACE. + * W2K wants to have access allowed zero access ACE's + * at the end of the list. If the mask is zero, merge + * the non-inherited ACE onto the inherited ACE. */ - nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT; - if (num_aces - j - 1 > 0) - memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) * - sizeof(SEC_ACE)); + if (nt_ace_list[i].info.mask == 0) { + nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0); + if (num_aces - i - 1 > 0) + memmove(&nt_ace_list[i], &nt_ace_list[i+1], (num_aces-i-1) * + sizeof(SEC_ACE)); + + DEBUG(10,("merge_default_aces: Merging zero access ACE %u onto ACE %u.\n", + (unsigned int)i, (unsigned int)j )); + } else { + /* + * These are identical except for the flags. + * Merge the inherited ACE onto the non-inherited ACE. + */ + + nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0); + if (num_aces - j - 1 > 0) + memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) * + sizeof(SEC_ACE)); + + DEBUG(10,("merge_default_aces: Merging ACE %u onto ACE %u.\n", + (unsigned int)j, (unsigned int)i )); + } num_aces--; break; } -- cgit From f51d769dd303027a3dbf46fc89a482933988e866 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 25 Jun 2003 17:41:05 +0000 Subject: large change: *) consolidates the dc location routines again (dns and netbios) get_dc_list() or get_sorted_dc_list() is the authoritative means of locating DC's again. (also inludes a flag to get_dc_list() to define if this should be a DNS only lookup or not) (however, if you set "name resolve order = hosts wins" you could still get DNS queries for domain name IFF ldap_domain2hostlist() fails. The answer? Fix your DNS setup) *) enabled DOMAIN<0x1c> lookups to be funneled through resolve_hosts resulting in a call to ldap_domain2hostlist() if lp_security() == SEC_ADS *) enables name cache for winbind ADS backend *) enable the negative connection cache for winbind ADS backend *) removes some old dead code *) consolidates some duplicate code *) moves the internal_name_resolve() to use an IP/port pair to deal with SRV RR dns replies. The namecache code also supports the IP:port syntax now as well. *) removes 'ads server' and moves the functionality back into 'password server' (which can support "hostname:port" syntax now but works fine with defaults depending on the value of lp_security()) (This used to be commit d7f7fcda425bef380441509734eca33da943c091) --- source3/smbd/change_trust_pw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 8aff96d0d6..4993e285ca 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -43,7 +43,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m goto failed; } - if ( !lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name) ) + if ( !name_status_find( domain, 0x1b, 0x20, pdc_ip, dc_name) ) goto failed; } /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ -- cgit From 0e983b32fd309de24b923a5c4928635c6c03e89f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Jun 2003 20:55:48 +0000 Subject: Some const correctness. Stop tdb being used as a remote backend. If an idmap backend is specified cause smbd to ask winbindd (use winbindd if you want a consistant remote backend solution). Should work well enough for next beta now... Jeremy. (This used to be commit 8f830c509af5976d988a30f0b0aee4ec61dd97a3) --- source3/smbd/nttrans.c | 10 +++++----- source3/smbd/server.c | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0030acc78b..13692d3c2c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1753,7 +1753,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou but works ok like this --metze */ - DEBUG(1,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; @@ -1762,7 +1762,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * --metze */ - DEBUG(1,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; @@ -1771,7 +1771,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * --metze */ - DEBUG(1,("FSCTL_SET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_SET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; @@ -1788,14 +1788,14 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou uid_t uid; size_t sid_len=SID_MAX_SIZE; - DEBUG(1,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control)); /* this is not the length of the sid :-( so unknown 4 bytes */ /*sid_len = IVAL(pdata,0); DEBUGADD(0,("sid_len: (%u)\n",sid_len));*/ sid_parse(pdata+4,sid_len,&sid); - DEBUGADD(2,("SID: %s\n",sid_string_static(&sid))); + DEBUGADD(10,("SID: %s\n",sid_string_static(&sid))); if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) { DEBUG(0,("sid_to_uid: failed, sid[%s]\n", diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 24cfed5be9..a767014232 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -845,8 +845,12 @@ void build_options(BOOL screen); if(!initialize_password_db(False)) exit(1); - if (!idmap_init()) - exit(1); + { + const char *idmap_back = lp_idmap_backend(); + + if (!idmap_init((idmap_back && *idmap_back) ? "winbind" : NULL)) + exit(1); + } if (!idmap_init_wellknown_sids()) exit(1); -- cgit From 9fda812d01d899603f7a6f7470e57de53f5c0593 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Jun 2003 18:53:48 +0000 Subject: Finally ! Fixed the ACL ordering bug reported by jcmd. I realised we were not sorting returned ACE's correctly w.r.t. W2K - implemented the correct algorithm. Jeremy. (This used to be commit fa23a4158ec23c0b8dbdc6c53f29958243107dee) --- source3/smbd/posix_acls.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 209387f422..f429fcb852 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2548,16 +2548,6 @@ posix perms.\n", fsp->fsp_name )); return True; } -static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2) -{ - if (a1->type == a2->type) - return 0; - - if (a1->type == SEC_ACE_TYPE_ACCESS_DENIED && a2->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - return -1; - return 1; -} - /**************************************************************************** Incoming NT ACLs on a directory can be split into a default POSIX acl (CI|OI|IO) and a normal POSIX acl. Win2k needs these split acls re-merging into one ACL @@ -2653,7 +2643,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) canon_ace *dir_ace = NULL; size_t num_profile_acls = 0; struct pai_val *pal = NULL; - + SEC_DESC *psd = NULL; + *ppdesc = NULL; DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -2858,12 +2849,6 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) num_aces = merge_default_aces(nt_ace_list, num_aces); - /* - * Sort to force deny entries to the front. - */ - - if (num_aces) - qsort( nt_ace_list, num_aces, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp); } if (num_aces) { @@ -2874,13 +2859,13 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } } /* security_info & DACL_SECURITY_INFORMATION */ - *ppdesc = make_standard_sec_desc( main_loop_talloc_get(), + psd = make_standard_sec_desc( main_loop_talloc_get(), (security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL, (security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL, psa, &sd_size); - if(!*ppdesc) { + if(!psd) { DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); sd_size = 0; } else { @@ -2894,9 +2879,14 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) * flag doesn't seem to bother Windows NT. */ if (get_protected_flag(pal)) - (*ppdesc)->type |= SE_DESC_DACL_PROTECTED; + psd->type |= SE_DESC_DACL_PROTECTED; } + if (psd->dacl) + dacl_sort_into_canonical_order(psd->dacl->ace, (unsigned int)psd->dacl->num_aces); + + *ppdesc = psd; + done: if (posix_acl) -- cgit From 8d4a397d858b1eeb349ddc35fc2cc7d50c79f62f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Jul 2003 00:35:11 +0000 Subject: Fixed the latest complaint from jcmd :-). We were storing -1 for the CREATOR_OWNER/CREATOR_GROUP uid/gid entries in the SAMBA_PAI attribute. Creator Owner and Creator group now show up as inherited correctly (I think :-). Jim please test. Jeremy. (This used to be commit dbbd8dd15582f95fb9c160c6c42ce9f0971ac4b7) --- source3/smbd/posix_acls.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f429fcb852..95b45fcc99 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -161,6 +161,8 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B if (ace_list->inherited) num_def_entries++; + DEBUG(10,("create_pai_buf: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries )); + *store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH); pai_buf = malloc(*store_size); @@ -542,10 +544,10 @@ static void print_canon_ace(canon_ace *pace, int num) dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); if (pace->owner_type == UID_ACE) { const char *u_name = uidtoname(pace->unix_ug.uid); - dbgtext( "uid %u (%s) %s", (unsigned int)pace->unix_ug.uid, u_name, pace->inherited ? "(inherited) " : ""); + dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name ); } else if (pace->owner_type == GID_ACE) { char *g_name = gidtoname(pace->unix_ug.gid); - dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name); + dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name ); } else dbgtext( "other "); switch (pace->type) { @@ -565,6 +567,8 @@ static void print_canon_ace(canon_ace *pace, int num) dbgtext( "SMB_ACL_OTHER "); break; } + if (pace->inherited) + dbgtext( "(inherited) "); dbgtext( "perms "); dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-'); dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-'); @@ -1202,7 +1206,7 @@ static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID Unpack a SEC_DESC into two canonical ace lists. ****************************************************************************/ -static BOOL create_canon_ace_lists(files_struct *fsp, +static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, canon_ace **ppfile_ace, canon_ace **ppdir_ace, @@ -1337,7 +1341,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, current_ace->type = SMB_ACL_OTHER; } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) { current_ace->owner_type = UID_ACE; - current_ace->unix_ug.world = -1; + current_ace->unix_ug.uid = pst->st_uid; current_ace->type = SMB_ACL_USER_OBJ; /* @@ -1350,7 +1354,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) { current_ace->owner_type = GID_ACE; - current_ace->unix_ug.world = -1; + current_ace->unix_ug.gid = pst->st_gid; current_ace->type = SMB_ACL_GROUP_OBJ; /* @@ -1910,7 +1914,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, * Now go through the DACL and create the canon_ace lists. */ - if (!create_canon_ace_lists( fsp, pfile_owner_sid, pfile_grp_sid, + if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid, &file_ace, &dir_ace, psd->dacl)) return False; -- cgit From b32d48533f3ad9e8a510c83c8acf4d543556549d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Jul 2003 22:07:27 +0000 Subject: Fix for bug 189 from MORIYAMA Masayuki . Incorrect call for Japanese characters. Jeremy. (This used to be commit c6de5df01d470c2dab48cdd6298f450fa94f9a8e) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2bf250a980..bdcd04443e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -326,7 +326,7 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) return False; if (case_sig) return strcmp(str,mask)==0; - return strcasecmp(str,mask) == 0; + return StrCaseCmp(str,mask) == 0; } /**************************************************************************** -- cgit From b55b664539eec149ea912d22de8fe0969f0a43cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jul 2003 00:08:29 +0000 Subject: Whitespace reformat before applying a patch. Jeremy. (This used to be commit bbe1276b516e1803a4a9285691674784b989b72f) --- source3/smbd/statcache.c | 371 ++++++++++++++++++++++++----------------------- 1 file changed, 187 insertions(+), 184 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 79758bcfe2..0d55c22f7a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -24,7 +24,6 @@ extern BOOL case_sensitive; - /**************************************************************************** Stat cache code used in unix_convert. *****************************************************************************/ @@ -53,123 +52,126 @@ static hash_table stat_cache; void stat_cache_add( const char *full_orig_name, const char *orig_translated_path) { - stat_cache_entry *scp; - stat_cache_entry *found_scp; - char *translated_path; - size_t translated_path_length; - - char *original_path; - size_t original_path_length; - - hash_element *hash_elem; - - if (!lp_stat_cache()) return; - - /* - * Don't cache trivial valid directory entries. - */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) - return; - - /* - * If we are in case insentive mode, we don't need to - * store names that need no translation - else, it - * would be a waste. - */ - - if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) - return; - - /* - * Remove any trailing '/' characters from the - * translated path. - */ - - translated_path = strdup(orig_translated_path); - if (!translated_path) - return; - - translated_path_length = strlen(translated_path); - - if(translated_path[translated_path_length-1] == '/') { - translated_path[translated_path_length-1] = '\0'; - translated_path_length--; - } - - original_path = strdup(full_orig_name); - if (!original_path) { - SAFE_FREE(translated_path); - return; - } - - original_path_length = strlen(original_path); - - if(original_path[original_path_length-1] == '/') { - original_path[original_path_length-1] = '\0'; - original_path_length--; - } - - if(!case_sensitive) - strupper(original_path); - - if (original_path_length != translated_path_length) { - if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - /* we only want to store the first part of original_path, - up to the length of translated_path */ - - original_path[translated_path_length] = '\0'; - original_path_length = translated_path_length; - } - - /* - * Check this name doesn't exist in the cache before we - * add it. - */ - - if ((hash_elem = hash_lookup(&stat_cache, original_path))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { - /* already in hash table */ - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - /* hash collision - remove before we re-add */ - hash_remove(&stat_cache, hash_elem); - } + stat_cache_entry *scp; + stat_cache_entry *found_scp; + char *translated_path; + size_t translated_path_length; + + char *original_path; + size_t original_path_length; + + hash_element *hash_elem; + + if (!lp_stat_cache()) + return; + + /* + * Don't cache trivial valid directory entries. + */ + + if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || + (strcmp(full_orig_name, "..") == 0)) + return; + + /* + * If we are in case insentive mode, we don't need to + * store names that need no translation - else, it + * would be a waste. + */ + + if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + return; + + /* + * Remove any trailing '/' characters from the + * translated path. + */ + + translated_path = strdup(orig_translated_path); + if (!translated_path) + return; + + translated_path_length = strlen(translated_path); + + if(translated_path[translated_path_length-1] == '/') { + translated_path[translated_path_length-1] = '\0'; + translated_path_length--; + } + + original_path = strdup(full_orig_name); + if (!original_path) { + SAFE_FREE(translated_path); + return; + } + + original_path_length = strlen(original_path); + + if(original_path[original_path_length-1] == '/') { + original_path[original_path_length-1] = '\0'; + original_path_length--; + } + + if(!case_sensitive) + strupper(original_path); + + if (original_path_length != translated_path_length) { + if (original_path_length < translated_path_length) { + DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", + original_path, original_path_length, translated_path, translated_path_length)); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + /* we only want to store the first part of original_path, + up to the length of translated_path */ + + original_path[translated_path_length] = '\0'; + original_path_length = translated_path_length; + } + + /* + * Check this name doesn't exist in the cache before we + * add it. + */ + + if ((hash_elem = hash_lookup(&stat_cache, original_path))) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { + /* already in hash table */ + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + /* hash collision - remove before we re-add */ + hash_remove(&stat_cache, hash_elem); + } - /* - * New entry. - */ + /* + * New entry. + */ - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) - +original_path_length - +translated_path_length)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - scp->original_path = scp->names; - scp->translated_path = scp->names + original_path_length + 1; - safe_strcpy(scp->original_path, original_path, original_path_length); - safe_strcpy(scp->translated_path, translated_path, translated_path_length); - scp->translated_path_length = translated_path_length; - - hash_insert(&stat_cache, (char *)scp, original_path); - - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) + +original_path_length + +translated_path_length)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + scp->original_path = scp->names; + scp->translated_path = scp->names + original_path_length + 1; + safe_strcpy(scp->original_path, original_path, original_path_length); + safe_strcpy(scp->translated_path, translated_path, translated_path_length); + scp->translated_path_length = translated_path_length; + + hash_insert(&stat_cache, (char *)scp, original_path); + + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); } /** @@ -191,73 +193,73 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { - stat_cache_entry *scp; - pstring chk_name; - size_t namelen; - hash_element *hash_elem; - char *sp; - - if (!lp_stat_cache()) - return False; + stat_cache_entry *scp; + pstring chk_name; + size_t namelen; + hash_element *hash_elem; + char *sp; + + if (!lp_stat_cache()) + return False; - namelen = strlen(name); - - *start = name; - - DO_PROFILE_INC(statcache_lookups); - - /* - * Don't lookup trivial valid directory entries. - */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - return False; - } - - pstrcpy(chk_name, name); - if(!case_sensitive) - strupper( chk_name ); - - while (1) { - hash_elem = hash_lookup(&stat_cache, chk_name); - if(hash_elem == NULL) { - /* - * Didn't find it - remove last component for next try. - */ - sp = strrchr_m(chk_name, '/'); - if (sp) { - *sp = '\0'; - } else { - /* - * We reached the end of the name - no match. - */ - DO_PROFILE_INC(statcache_misses); - return False; - } - if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) - || (strcmp(chk_name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - return False; - } - } else { - scp = (stat_cache_entry *)(hash_elem->value); - DO_PROFILE_INC(statcache_hits); - if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { - /* Discard this entry - it doesn't exist in the filesystem. */ - hash_remove(&stat_cache, hash_elem); - return False; - } - memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); - - /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[scp->translated_path_length]; - if(**start == '/') - ++*start; - - pstrcpy(dirpath, scp->translated_path); - return (namelen == scp->translated_path_length); - } - } + namelen = strlen(name); + + *start = name; + + DO_PROFILE_INC(statcache_lookups); + + /* + * Don't lookup trivial valid directory entries. + */ + if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { + DO_PROFILE_INC(statcache_misses); + return False; + } + + pstrcpy(chk_name, name); + if(!case_sensitive) + strupper( chk_name ); + + while (1) { + hash_elem = hash_lookup(&stat_cache, chk_name); + if(hash_elem == NULL) { + /* + * Didn't find it - remove last component for next try. + */ + sp = strrchr_m(chk_name, '/'); + if (sp) { + *sp = '\0'; + } else { + /* + * We reached the end of the name - no match. + */ + DO_PROFILE_INC(statcache_misses); + return False; + } + if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) + || (strcmp(chk_name, "..") == 0)) { + DO_PROFILE_INC(statcache_misses); + return False; + } + } else { + scp = (stat_cache_entry *)(hash_elem->value); + DO_PROFILE_INC(statcache_hits); + if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + hash_remove(&stat_cache, hash_elem); + return False; + } + memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + + /* set pointer for 'where to start' on fixing the rest of the name */ + *start = &name[scp->translated_path_length]; + if(**start == '/') + ++*start; + + pstrcpy(dirpath, scp->translated_path); + return (namelen == scp->translated_path_length); + } + } } /*************************************************************************** ** @@ -271,7 +273,8 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, BOOL reset_stat_cache( void ) { static BOOL initialised; - if (!lp_stat_cache()) return True; + if (!lp_stat_cache()) + return True; if (initialised) { hash_clear(&stat_cache); @@ -280,4 +283,4 @@ BOOL reset_stat_cache( void ) initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); return initialised; -} /* reset_stat_cache */ +} -- cgit From af4d65889420eb3bb71be67d619dbc0c62e21101 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jul 2003 20:01:51 +0000 Subject: Added fix for Japanese case names in statcache - these can change size on upper casing. Based on patch from monyo@home.monyo.com. Jeremy. (This used to be commit 72e382e99b92666acdaf50a040b14aa16d48b80d) --- source3/smbd/statcache.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 0d55c22f7a..593df745cc 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -198,6 +198,8 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, size_t namelen; hash_element *hash_elem; char *sp; + BOOL sizechanged = False; + unsigned int num_components = 0; if (!lp_stat_cache()) return False; @@ -217,8 +219,17 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } pstrcpy(chk_name, name); - if(!case_sensitive) + + if(!case_sensitive) { strupper( chk_name ); + /* + * In some language encodings the length changes + * if we uppercase. We need to treat this differently + * below. + */ + if (strlen(chk_name) != namelen) + sizechanged = True; + } while (1) { hash_elem = hash_lookup(&stat_cache, chk_name); @@ -229,6 +240,13 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, sp = strrchr_m(chk_name, '/'); if (sp) { *sp = '\0'; + /* + * Count the number of times we have done this, + * we'll need it when reconstructing the string. + */ + if (sizechanged) + num_components++; + } else { /* * We reached the end of the name - no match. @@ -249,7 +267,20 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, hash_remove(&stat_cache, hash_elem); return False; } - memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + + if (!sizechanged) { + memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + } else { + pstring last_component; + sp = strnrchr_m(name, '/', num_components); + if (!sp) { + /* Logic error. */ + smb_panic("logic error in stat_cache_lookup\n"); + } + pstrcpy(last_component, sp); + pstrcpy(name, scp->translated_path); + pstrcat(name, last_component); + } /* set pointer for 'where to start' on fixing the rest of the name */ *start = &name[scp->translated_path_length]; -- cgit From 936d8e4a3508c5d7ec77cd325331161236b53cbc Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Wed, 2 Jul 2003 21:15:59 +0000 Subject: Fixing problems in the iconv discovery stuff in configure.in. This is the first part of the fix that at least allows configure to walk the list of supplied locations where libiconv etc might be found. aclocal.m4 also needs a fix, as does a later test. (This used to be commit 20786543139c546d112f8f6b6d4d796ee7fed609) --- source3/smbd/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a767014232..e2fe2ac819 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -867,6 +867,7 @@ void build_options(BOOL screen); exit(1); } + if (!init_account_policy()) { DEBUG(0,("Could not open account policy tdb.\n")); exit(1); -- cgit From 6dc3885999b6b69bf9960fda012bece214e27ad5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 3 Jul 2003 14:56:04 +0000 Subject: Missed this in the previous patch - we now have a seperate idea of the 'unix username' from the NT username, in the auth subsystem at least. Andrew Bartlett (This used to be commit df1aa2a669edc9f26007595411720742d7dff5d9) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9560449aa5..e2c143f1e2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -157,7 +157,7 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) } vuser->guest = server_info->guest; - fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); + fstrcpy(vuser->user.unix_name, server_info->unix_name); /* This is a potentially untrusted username */ alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name)); -- cgit From ce72beb2b558d86fb49063c6b1fa00e07952ce56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Jul 2003 19:11:31 +0000 Subject: Removed strupper/strlower macros that automatically map to strupper_m/strlower_m. I really want people to think about when they're using multibyte strings. Jeremy. (This used to be commit ff222716a08af65d26ad842ce4c2841cc6540959) --- source3/smbd/lanman.c | 8 ++++---- source3/smbd/mangle_hash.c | 5 +++-- source3/smbd/negprot.c | 2 +- source3/smbd/open.c | 2 +- source3/smbd/service.c | 4 ++-- source3/smbd/statcache.c | 4 ++-- 6 files changed, 13 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 6976a06684..04d6a9a8a8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2367,7 +2367,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ pstrcpy(p2,local_machine); - strupper(p2); + strupper_m(p2); p2 = skip_string(p2,1); p += 4; @@ -2378,7 +2378,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ pstrcpy(p2,lp_workgroup()); - strupper(p2); + strupper_m(p2); p2 = skip_string(p2,1); p += 4; @@ -2788,7 +2788,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param fstring mypath; fstrcpy(mypath,"\\\\"); fstrcat(mypath,local_machine); - strupper(mypath); + strupper_m(mypath); PACKS(&desc,"z",mypath); /* computer */ } PACKS(&desc,"z",lp_workgroup());/* domain */ @@ -3007,7 +3007,7 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, char buf[100]; strncpy(buf,SERVICE(snum),sizeof(buf)-1); buf[sizeof(buf)-1] = 0; - strupper(buf); + strupper_m(buf); if (uLevel <= 1) { PACKS(desc,"B9",buf); /* szName */ if (uLevel == 1) { diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index d4cf369f28..ac8e425fd3 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -227,7 +227,8 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards) SAFE_FREE(str); return NT_STATUS_UNSUCCESSFUL; } - if (p) *p = 0; + if (p) + *p = 0; strupper_w(str); p = &(str[1]); @@ -660,7 +661,7 @@ static void to_8_3(char *s) } else csum = str_checksum(s); - strupper( s ); + strupper_m( s ); if( p ) { if( p == s ) diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 2a2ca25532..f452dd845b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -192,7 +192,7 @@ static int negprot_spnego(char *p) } #endif - strlower((char *)guid); + strlower_m((char *)guid); #if 0 /* strangely enough, NT does not sent the single OID NTLMSSP when diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 15171ce9e3..85d115a3bf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -74,7 +74,7 @@ static void check_for_pipe(char *fname) /* special case of pipe opens */ char s[10]; StrnCpy(s,fname,sizeof(s)-1); - strlower(s); + strlower_m(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); unix_ERR_class = ERRSRV; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 11659f2870..6a23e38bbd 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -237,7 +237,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) } } - strupper(dev); + strupper_m(dev); if (lp_print_ok(snum)) { if (!strequal(dev, "LPT1:")) { @@ -828,7 +828,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstrcpy(service, service_in); - strlower(service); + strlower_m(service); snum = find_service(service); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 593df745cc..5d54a5c4ff 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -112,7 +112,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } if(!case_sensitive) - strupper(original_path); + strupper_m(original_path); if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { @@ -221,7 +221,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, pstrcpy(chk_name, name); if(!case_sensitive) { - strupper( chk_name ); + strupper_m( chk_name ); /* * In some language encodings the length changes * if we uppercase. We need to treat this differently -- cgit From 4168d61fb22e19a248a6c3d3ad43e2f73e37fc6a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 4 Jul 2003 13:29:42 +0000 Subject: This patch cleans up some of our ldap code, for better behaviour: We now always read the Domain SID out of LDAP. If the local secrets.tdb is ever different to LDAP, it is overwritten out of LDAP. We also store the 'algorithmic rid base' into LDAP, and assert if it changes. (This ensures cross-host synchronisation, and allows for possible integration with idmap). If we fail to read/add the domain entry, we just fallback to the old behaviour. We always use an existing DN when adding IDMAP entries to LDAP, unless no suitable entry is available. This means that a user's posixAccount will have a SID added to it, or a user's sambaSamAccount will have a UID added. Where we cannot us an existing DN, we use 'sambaSid=S-x-y-z,....' as the DN. The code now allows modifications to the ID mapping in many cases. Likewise, we now check more carefully when adding new user entires to LDAP, to not duplicate SIDs (for users, at this stage), and to add the sambaSamAccount onto the idmap entry for that user, if it is already established (ensuring we do not duplicate sambaSid entries in the directory). The allocated UID code has been expanded to take into account the space between '1000 - algorithmic rid base'. This much better fits into what an NT4 does - allocating in the bottom part of the RID range. On the code cleanup side of things, we now share as much code as possible between idmap_ldap and pdb_ldap. We also no longer use the race-prone 'enumerate all users' method for finding the next RID to allocate. Instead, we just start at the bottom of the range, and increment again if the user already exists. The first time this is run, it may well take a long time, but next time will just be able to use the next Rid. Thanks to metze and AB for double-checking parts of this. Andrew Bartlett (This used to be commit 9c595c8c2327b92a86901d84c3f2c284dabd597e) --- source3/smbd/server.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e2fe2ac819..6f549aab1c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -842,9 +842,19 @@ void build_options(BOOL screen); if (!init_registry()) exit(1); + /* Initialise the password backed before idmap and the global_sam_sid + to ensure that we fetch from ldap before we make a domain sid up */ + if(!initialize_password_db(False)) exit(1); + if(!get_global_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); + exit(1); + } + + static_init_auth; + { const char *idmap_back = lp_idmap_backend(); @@ -852,8 +862,10 @@ void build_options(BOOL screen); exit(1); } - if (!idmap_init_wellknown_sids()) + if (!idmap_init_wellknown_sids()) { + DEBUG(0,("ERROR: Samba failed to initialize it's 'well known' SID -> ID mapping tables.\n")); exit(1); + } static_init_rpc; @@ -862,12 +874,6 @@ void build_options(BOOL screen); /* possibly reload the services file. */ reload_services(True); - if(!get_global_sam_sid()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); - exit(1); - } - - if (!init_account_policy()) { DEBUG(0,("Could not open account policy tdb.\n")); exit(1); -- cgit From b475d0b88924a0af4a8519a2e7bc183945de0f9c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 6 Jul 2003 05:51:20 +0000 Subject: This changes our Unix primary GID behaviour back to what most people expect: Samba will now use the user's UNIX primary group, as the primary group when dealing with the filesystem. The NT primary group is ignored in unix. For the NT_TOKEN, the primary group is the NT priamry group, and the unix primary group is added to the NT_TOKEN as a supplementary group. This should fix bug #109, but will need to be revisited when we get a full NT group database. Also in this commit: - Fix debug statements in service.c - Make idmap_ldap show if it's adding, or modifying an existing DN - Make idmap_ldap show both the error message and error string (This used to be commit 32e455a714b2090fcfd1f6d73daccf600c15d51b) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 6a23e38bbd..63991904ff 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -359,7 +359,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, guest = True; pass = getpwnam_alloc(guestname); if (!pass) { - DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname)); + DEBUG(0,("make_conncection_snum: Invalid guest account %s??\n",guestname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_USER; return NULL; -- cgit From 0b18acb841f6a372b3aa285d4734875e5e35fe3b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 7 Jul 2003 05:11:10 +0000 Subject: and so it begins.... * remove idmap_XX_to_XX calls from smbd. Move back to the the winbind_XXX and local_XXX calls used in 2.2 * all uid/gid allocation must involve winbindd now * move flags field around in winbindd_request struct * add WBFLAG_QUERY_ONLY option to winbindd_sid_to_[ug]id() to prevent automatic allocation for unknown SIDs * add 'winbind trusted domains only' parameter to force a domain member server to use matching users names from /etc/passwd for its domain (needed for domain member of a Samba domain) * rename 'idmap only' to 'enable rid algorithm' for better clarity (defaults to "yes") code has been tested on * domain member of native mode 2k domain * ads domain member of native mode 2k domain * domain member of NT4 domain * domain member of Samba domain * Samba PDC running winbindd with trusts Logons tested using 2k clients and smbclient as domain users and trusted users. Tested both 'winbind trusted domains only = [yes|no]' This will be a long week of changes. The next item on the list is winbindd_passdb.c & machine trust accounts not in /etc/passwd (done via winbindd_passdb) (This used to be commit 8266dffab4aedba12a33289ff32880037ce950a8) --- source3/smbd/server.c | 14 +- source3/smbd/uid.c | 408 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 409 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6f549aab1c..0906e3b9d8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -842,7 +842,7 @@ void build_options(BOOL screen); if (!init_registry()) exit(1); - /* Initialise the password backed before idmap and the global_sam_sid + /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ if(!initialize_password_db(False)) @@ -855,18 +855,6 @@ void build_options(BOOL screen); static_init_auth; - { - const char *idmap_back = lp_idmap_backend(); - - if (!idmap_init((idmap_back && *idmap_back) ? "winbind" : NULL)) - exit(1); - } - - if (!idmap_init_wellknown_sids()) { - DEBUG(0,("ERROR: Samba failed to initialize it's 'well known' SID -> ID mapping tables.\n")); - exit(1); - } - static_init_rpc; init_modules(); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c68d00025c..04ff0faa28 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -529,3 +529,411 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE } return True; } + + +/***************************************************************** + Id mapping cache. This is to avoid Winbind mappings already + seen by smbd to be queried too frequently, keeping winbindd + busy, and blocking smbd while winbindd is busy with other + stuff. Written by Michael Steffens , + modified to use linked lists by jra. +*****************************************************************/ + +#define MAX_UID_SID_CACHE_SIZE 100 +#define TURNOVER_UID_SID_CACHE_SIZE 10 +#define MAX_GID_SID_CACHE_SIZE 100 +#define TURNOVER_GID_SID_CACHE_SIZE 10 + +static size_t n_uid_sid_cache = 0; +static size_t n_gid_sid_cache = 0; + +static struct uid_sid_cache { + struct uid_sid_cache *next, *prev; + uid_t uid; + DOM_SID sid; + enum SID_NAME_USE sidtype; +} *uid_sid_cache_head; + +static struct gid_sid_cache { + struct gid_sid_cache *next, *prev; + gid_t gid; + DOM_SID sid; + enum SID_NAME_USE sidtype; +} *gid_sid_cache_head; + +/***************************************************************** + Find a SID given a uid. +*****************************************************************/ + +static BOOL fetch_sid_from_uid_cache(const DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (pc->uid == uid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from uid cache %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a uid given a SID. +*****************************************************************/ + +static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid ) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *puid = pc->uid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*puid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store uid to SID mapping in cache. +*****************************************************************/ + +static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */ + struct uid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(uid_sid_cache_head,pc); + SAFE_FREE(pc); + n_uid_sid_cache--; + } + } + + pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache)); + if (!pc) + return; + pc->uid = uid; + sid_copy(&pc->sid, psid); + DLIST_ADD(uid_sid_cache_head, pc); + n_uid_sid_cache++; +} + +/***************************************************************** + Find a SID given a gid. +*****************************************************************/ + +static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (pc->gid == gid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from gid cache %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a gid given a SID. +*****************************************************************/ + +static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *pgid = pc->gid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*pgid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store gid to SID mapping in cache. +*****************************************************************/ + +static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ + struct gid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(gid_sid_cache_head,pc); + SAFE_FREE(pc); + n_gid_sid_cache--; + } + } + + pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); + if (!pc) + return; + pc->gid = gid; + sid_copy(&pc->sid, psid); + DLIST_ADD(gid_sid_cache_head, pc); + n_gid_sid_cache++; +} + +/***************************************************************** + *THE CANONICAL* convert uid_t to SID function. + check idmap if uid is in idmap range, otherwise falls back to + the legacy algorithmic mapping. + A special cache is used for uids that maps to Wellknown SIDs + Returns SID pointer. +*****************************************************************/ + +NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) +{ + uid_t low, high; + fstring sid; + + if (fetch_sid_from_uid_cache(psid, uid)) + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + + if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) { + if (winbind_uid_to_sid(psid, uid)) { + + DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); + + if (psid) + store_uid_sid_cache(psid, uid); + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + } + } + + local_uid_to_sid(psid, uid); + + DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); + + if (psid) + store_uid_sid_cache(psid, uid); + + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); +} + +/***************************************************************** + *THE CANONICAL* convert gid_t to SID function. + check idmap if gid is in idmap range, otherwise falls back to + the legacy algorithmic mapping. + Group mapping is used for gids that maps to Wellknown SIDs + Returns SID pointer. +*****************************************************************/ + +NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) +{ + gid_t low, high; + fstring sid; + + if (fetch_sid_from_gid_cache(psid, gid)) + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + + if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) { + if (winbind_gid_to_sid(psid, gid)) { + + DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); + + if (psid) + store_gid_sid_cache(psid, gid); + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + } + } + + local_gid_to_sid(psid, gid); + + DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); + + if (psid) + store_gid_sid_cache(psid, gid); + + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); +} + +/***************************************************************** + *THE CANONICAL* convert SID to uid function. + if it is a foreign sid or it is in idmap rid range check idmap, + otherwise falls back to the legacy algorithmic mapping. + A special cache is used for uids that maps to Wellknown SIDs + Returns True if this name is a user sid and the conversion + was done correctly, False if not. +*****************************************************************/ + +NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + BOOL ret; + + if (fetch_uid_from_cache(puid, psid)) + return NT_STATUS_OK; + + /* + * First we must look up the name and decide if this is a user sid. + */ + + if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) { + DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + ret = local_sid_to_uid(puid, psid, &name_type); + if (ret) + store_uid_sid_cache(psid, *puid); + return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); + } + + /* + * Ensure this is a user sid. + */ + + if (name_type != SID_NAME_USER) { + DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n", + (unsigned int)name_type )); + return NT_STATUS_INVALID_PARAMETER; + } + + /* query only first */ + + if ( !winbind_sid_to_uid_query(puid, psid) ) + { + DEBUG(10,("sid_to_uid: winbind query for sid %s failed.\n", + sid_to_string(sid_str, psid) )); + + /* see if we have a local mapping */ + + if ( local_sid_to_uid(puid, psid, &name_type) ) { + store_uid_sid_cache(psid, *puid); + return NT_STATUS_OK; + } + + /* Call back to winbind to allocate a new uid */ + + if ( !winbind_sid_to_uid(puid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; + } + } + + DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), + (unsigned int)*puid )); + + store_uid_sid_cache(psid, *puid); + + return NT_STATUS_OK; +} +/***************************************************************** + *THE CANONICAL* convert SID to gid function. + if it is a foreign sid or it is in idmap rid range check idmap, + otherwise falls back to the legacy algorithmic mapping. + Group mapping is used for gids that maps to Wellknown SIDs + Returns True if this name is a user sid and the conversion + was done correctly, False if not. +*****************************************************************/ + +NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + BOOL ret; + + if (fetch_gid_from_cache(pgid, psid)) + return NT_STATUS_OK; + + /* + * First we must look up the name and decide if this is a group sid. + */ + + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + ret = local_sid_to_gid(pgid, psid, &name_type); + if (ret) + store_gid_sid_cache(psid, *pgid); + + return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); + } + + /* + * Ensure this is a group sid. + */ + + if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { + DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", + (unsigned int)name_type )); + + ret = local_sid_to_gid(pgid, psid, &name_type); + if (ret) + store_gid_sid_cache(psid, *pgid); + return (ret ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER); + } + + /* query only first */ + + if ( !winbind_sid_to_gid_query(pgid, psid) ) + { + DEBUG(10,("sid_to_gid: winbind query for sid %s failed.\n", + sid_to_string(sid_str, psid) )); + + /* see if we have a local mapping */ + + if ( local_sid_to_gid(pgid, psid, &name_type) ) { + store_gid_sid_cache(psid, *pgid); + return NT_STATUS_OK; + } + + /* Call back to winbind to allocate a new uid */ + + if ( !winbind_sid_to_gid(pgid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; + } + else + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), + (unsigned int)*pgid )); + + store_gid_sid_cache(psid, *pgid); + + return NT_STATUS_OK; +} + -- cgit From 436555aaa7fc1ba7459d25c2514c847cd127b13b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2003 17:04:48 +0000 Subject: Fixed a couple of const issues with the new code. Jeremy. (This used to be commit e9fb6e45086a6170b6f6d5d3295398708ab1af58) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 04ff0faa28..6d67a63ccd 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -565,7 +565,7 @@ static struct gid_sid_cache { Find a SID given a uid. *****************************************************************/ -static BOOL fetch_sid_from_uid_cache(const DOM_SID *psid, uid_t uid) +static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) { struct uid_sid_cache *pc; -- cgit From 45ac30db09332bc5de20ea15cc07c25ebc6fb6f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2003 20:22:35 +0000 Subject: Fix from MORIYAMA Masayuki for new MB statcache code. Bug #185. Jeremy. (This used to be commit 7a1ac7be42dfb90fd44f2c51810eedcea052386b) --- source3/smbd/statcache.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 5d54a5c4ff..22b8a33a1e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -270,16 +270,18 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if (!sizechanged) { memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + } else if (num_components == 0) { + pstrcpy(name, scp->translated_path); } else { - pstring last_component; sp = strnrchr_m(name, '/', num_components); - if (!sp) { - /* Logic error. */ - smb_panic("logic error in stat_cache_lookup\n"); + if (sp) { + pstring last_component; + pstrcpy(last_component, sp); + pstrcpy(name, scp->translated_path); + pstrcat(name, last_component); + } else { + pstrcpy(name, scp->translated_path); } - pstrcpy(last_component, sp); - pstrcpy(name, scp->translated_path); - pstrcat(name, last_component); } /* set pointer for 'where to start' on fixing the rest of the name */ -- cgit From e5aa73dab14634fa7741aeb41f7f811f0ab241b3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2003 22:29:40 +0000 Subject: Fix spotted by Nadav Danieli - ensure dev and inode to fix open mode race condition. Jeremy. (This used to be commit cbde1c8dfcd9d3bef956fe073e7108a54b48844b) --- source3/smbd/open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 85d115a3bf..6d03eaa29a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1024,6 +1024,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (!file_existed) { + /* + * Now the file exists and fsp is successfully opened, + * fsp->dev and fsp->inode are valid and should replace the + * dev=0,inode=0 from a non existent file. Spotted by + * Nadav Danieli . JRA. + */ + + dev = fsp->dev; + inode = fsp->inode; + lock_share_entry_fsp(fsp); num_share_modes = open_mode_check(conn, fname, dev, inode, -- cgit From e4bfa0a4608d794fd0c6228b58469ddf5473b7b4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jul 2003 21:58:29 +0000 Subject: Moved SAM_ACCOUNT marshall/unmarshall functions to make them externally available. Removed extra auth_init (thanks metze). Jeremy. (This used to be commit 88135fbc4998c266052647f8b8e437ac01cf50ae) --- source3/smbd/server.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0906e3b9d8..453ff54e4b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -853,8 +853,6 @@ void build_options(BOOL screen); exit(1); } - static_init_auth; - static_init_rpc; init_modules(); -- cgit From 4f0b771af0b1d0ccbe8a4a6009c382a27661ad7e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jul 2003 00:01:40 +0000 Subject: Ensure we correctly test for errors in uid/gid_to sid. Jeremy. (This used to be commit f3c2e73a8c1c592d407542c12c0a445103415bc0) --- source3/smbd/uid.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 6d67a63ccd..320f8eb980 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -737,14 +737,15 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) } } - local_uid_to_sid(psid, uid); + if (!local_uid_to_sid(psid, uid)) { + DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid )); + return NT_STATUS_UNSUCCESSFUL; + } DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); - if (psid) - store_uid_sid_cache(psid, uid); - - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + store_uid_sid_cache(psid, uid); + return NT_STATUS_OK; } /***************************************************************** @@ -775,14 +776,15 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) } } - local_gid_to_sid(psid, gid); + if (!local_gid_to_sid(psid, gid)) { + DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid )); + return NT_STATUS_UNSUCCESSFUL; + } DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); - if (psid) - store_gid_sid_cache(psid, gid); - - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + store_gid_sid_cache(psid, gid); + return NT_STATUS_OK; } /***************************************************************** @@ -829,8 +831,7 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) /* query only first */ - if ( !winbind_sid_to_uid_query(puid, psid) ) - { + if ( !winbind_sid_to_uid_query(puid, psid) ) { DEBUG(10,("sid_to_uid: winbind query for sid %s failed.\n", sid_to_string(sid_str, psid) )); @@ -906,8 +907,7 @@ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) /* query only first */ - if ( !winbind_sid_to_gid_query(pgid, psid) ) - { + if ( !winbind_sid_to_gid_query(pgid, psid) ) { DEBUG(10,("sid_to_gid: winbind query for sid %s failed.\n", sid_to_string(sid_str, psid) )); @@ -936,4 +936,3 @@ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) return NT_STATUS_OK; } - -- cgit From 4072006fecf56bebf113fe1d4566156c0d89bacc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jul 2003 00:23:42 +0000 Subject: Get rid of DISP_USER_INFO/DISP_GROUP_INFO as they serve no useful purpose. Replace with an array of SAM_ACCOUNT/DOMAIN_GRP entries. ZERO struct's in smbd/uid.c stops core dumps when sid_to_XX functions fail. Getting ready to add caching. Jeremy. (This used to be commit 9d0692a54fe2cb087f25796ec2ab5e1d8433e388) --- source3/smbd/uid.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 320f8eb980..6ca2aa336d 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -722,6 +722,8 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) uid_t low, high; fstring sid; + ZERO_STRUCTP(psid); + if (fetch_sid_from_uid_cache(psid, uid)) return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); @@ -761,6 +763,8 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) gid_t low, high; fstring sid; + ZERO_STRUCTP(psid); + if (fetch_sid_from_gid_cache(psid, gid)) return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); -- cgit From 16ff7b26f6b9d288cbd1d39e075b637e24da13a6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 9 Jul 2003 16:44:47 +0000 Subject: Large set of changes to add UNIX account/group management to winbindd. See README.idmap-and-winbind-changes for details. (This used to be commit 1111bc7b0c7165e1cdf8d90eb49f4c368d2eded6) --- source3/smbd/uid.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 6ca2aa336d..8d8ce136a9 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -809,17 +809,28 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) if (fetch_uid_from_cache(puid, psid)) return NT_STATUS_OK; - /* - * First we must look up the name and decide if this is a user sid. - */ + /* if this is our DIS then go straight to a local lookup */ + + if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) { + DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n", + sid_string_static(psid) )); + + if ( (ret = local_sid_to_uid(puid, psid, &name_type)) == True ) + store_uid_sid_cache(psid, *puid); + + return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); + } + + + /* look up the name and decide if this is a user sid */ if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) { DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", - sid_to_string(sid_str, psid) )); + sid_string_static(psid) )); - ret = local_sid_to_uid(puid, psid, &name_type); - if (ret) + if ( (ret = local_sid_to_uid(puid, psid, &name_type)) == True ) store_uid_sid_cache(psid, *puid); + return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); } -- cgit From a7ef6aac3a78e7d98956d64ea6f858b1f20d0a19 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Wed, 9 Jul 2003 23:01:08 +0000 Subject: Fix a small spelling mistake and push out the new version of aclocal.m4 to properly handle iconv on FreeBSD ... It works on Linux and FreeBSD ... (This used to be commit 9302401f543bd3684657b38f046dc52a5a732035) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 63991904ff..18e0887071 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -359,7 +359,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, guest = True; pass = getpwnam_alloc(guestname); if (!pass) { - DEBUG(0,("make_conncection_snum: Invalid guest account %s??\n",guestname)); + DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_USER; return NULL; -- cgit From 5359b8dc97d325ce8eae80cd2c21c4520a99d358 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 11 Jul 2003 14:33:13 +0000 Subject: use names from enumerated type to get rid of compiler warnings (This used to be commit c9d6782e091406ed105b7dc34c8c83e53bfe515e) --- source3/smbd/nttrans.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 13692d3c2c..c574d9d563 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -562,7 +562,7 @@ int reply_ntcreate_and_X(connection_struct *conn, { int result; pstring fname; - enum FAKE_FILE_TYPE fake_file_type = 0; + enum FAKE_FILE_TYPE fake_file_type = FAKE_FILE_TYPE_NONE; uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); @@ -692,7 +692,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if( strchr_m(fname, ':')) { #ifdef HAVE_SYS_QUOTAS - if ((fake_file_type=is_fake_file(fname))!=0) { + if ((fake_file_type=is_fake_file(fname))!=FAKE_FILE_TYPE_NONE) { /* * here we go! support for changing the disk quotas --metze * @@ -784,7 +784,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * before issuing an oplock break request to * our client. JRA. */ - if (fake_file_type==0) { + if (fake_file_type==FAKE_FILE_TYPE_NONE) { fsp = open_file_shared1(conn,fname,&sbuf, desired_access, smb_open_mode, -- cgit From 733f767b9465c53822af99bb0cc761ba745c96b6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 11 Jul 2003 16:37:23 +0000 Subject: fix sid_to_[uid|gid] (spotted by Volker). Still testing this, but I'm checking it in so Volker can test it as well. Should be right. (This used to be commit 8edf193722f699cc33baed410917a78a5e28d0a4) --- source3/smbd/uid.c | 124 ++++++++++++++++------------------------------------- 1 file changed, 37 insertions(+), 87 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8d8ce136a9..8d3e7cd9be 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -711,10 +711,6 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) /***************************************************************** *THE CANONICAL* convert uid_t to SID function. - check idmap if uid is in idmap range, otherwise falls back to - the legacy algorithmic mapping. - A special cache is used for uids that maps to Wellknown SIDs - Returns SID pointer. *****************************************************************/ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) @@ -752,10 +748,6 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) /***************************************************************** *THE CANONICAL* convert gid_t to SID function. - check idmap if gid is in idmap range, otherwise falls back to - the legacy algorithmic mapping. - Group mapping is used for gids that maps to Wellknown SIDs - Returns SID pointer. *****************************************************************/ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) @@ -793,79 +785,56 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) /***************************************************************** *THE CANONICAL* convert SID to uid function. - if it is a foreign sid or it is in idmap rid range check idmap, - otherwise falls back to the legacy algorithmic mapping. - A special cache is used for uids that maps to Wellknown SIDs - Returns True if this name is a user sid and the conversion - was done correctly, False if not. *****************************************************************/ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) { fstring dom_name, name, sid_str; enum SID_NAME_USE name_type; - BOOL ret; if (fetch_uid_from_cache(puid, psid)) return NT_STATUS_OK; - /* if this is our DIS then go straight to a local lookup */ + /* if this is our SID then go straight to a local lookup */ if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) { DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n", sid_string_static(psid) )); - if ( (ret = local_sid_to_uid(puid, psid, &name_type)) == True ) - store_uid_sid_cache(psid, *puid); + if ( local_sid_to_uid(puid, psid, &name_type) ) + goto success; + + DEBUG(10,("sid_to_uid: local lookup failed\n")); - return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); + return NT_STATUS_UNSUCCESSFUL; } + /* If it is not our local domain, only hope is winbindd */ - /* look up the name and decide if this is a user sid */ - - if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) { - DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", + if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) { + DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n", sid_string_static(psid) )); - - if ( (ret = local_sid_to_uid(puid, psid, &name_type)) == True ) - store_uid_sid_cache(psid, *puid); - - return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); + + return NT_STATUS_UNSUCCESSFUL; } - /* - * Ensure this is a user sid. - */ + /* If winbindd does know the SID, ensure this is a user */ if (name_type != SID_NAME_USER) { - DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n", + DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n", (unsigned int)name_type )); return NT_STATUS_INVALID_PARAMETER; } - /* query only first */ - - if ( !winbind_sid_to_uid_query(puid, psid) ) { - DEBUG(10,("sid_to_uid: winbind query for sid %s failed.\n", - sid_to_string(sid_str, psid) )); - - /* see if we have a local mapping */ - - if ( local_sid_to_uid(puid, psid, &name_type) ) { - store_uid_sid_cache(psid, *puid); - return NT_STATUS_OK; - } - - /* Call back to winbind to allocate a new uid */ + /* get the uid. Has to work or else we are dead in the water */ - if ( !winbind_sid_to_uid(puid, psid) ) { - DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", - sid_to_string(sid_str, psid) )); - return NT_STATUS_UNSUCCESSFUL; - } + if ( !winbind_sid_to_uid(puid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; } +success: DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), (unsigned int)*puid )); @@ -875,75 +844,56 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) } /***************************************************************** *THE CANONICAL* convert SID to gid function. - if it is a foreign sid or it is in idmap rid range check idmap, - otherwise falls back to the legacy algorithmic mapping. Group mapping is used for gids that maps to Wellknown SIDs - Returns True if this name is a user sid and the conversion - was done correctly, False if not. *****************************************************************/ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) { fstring dom_name, name, sid_str; enum SID_NAME_USE name_type; - BOOL ret; if (fetch_gid_from_cache(pgid, psid)) return NT_STATUS_OK; /* * First we must look up the name and decide if this is a group sid. + * Group mapping can deal with foreign SIDs */ if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", sid_to_string(sid_str, psid) )); - ret = local_sid_to_gid(pgid, psid, &name_type); - if (ret) - store_gid_sid_cache(psid, *pgid); + if ( local_sid_to_gid(pgid, psid, &name_type) ) + goto success; - return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); + DEBUG(10,("sid_to_gid: no one knows this SID\n")); + + return NT_STATUS_UNSUCCESSFUL; } - /* - * Ensure this is a group sid. - */ + /* winbindd knows it; Ensure this is a group sid */ if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", (unsigned int)name_type )); - ret = local_sid_to_gid(pgid, psid, &name_type); - if (ret) - store_gid_sid_cache(psid, *pgid); - return (ret ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER); + /* winbindd is running and knows about this SID. Just the wrong type. + Don't fallback to a local lookup here */ + + return NT_STATUS_INVALID_PARAMETER; } - - /* query only first */ - if ( !winbind_sid_to_gid_query(pgid, psid) ) { - DEBUG(10,("sid_to_gid: winbind query for sid %s failed.\n", - sid_to_string(sid_str, psid) )); - - /* see if we have a local mapping */ - - if ( local_sid_to_gid(pgid, psid, &name_type) ) { - store_gid_sid_cache(psid, *pgid); - return NT_STATUS_OK; - } - - /* Call back to winbind to allocate a new uid */ + /* winbindd knows it and it is a type of group; sid_to_gid must succeed + or we are dead in the water */ - if ( !winbind_sid_to_gid(pgid, psid) ) { - DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n", - sid_to_string(sid_str, psid) )); - return NT_STATUS_UNSUCCESSFUL; - } - else - return NT_STATUS_UNSUCCESSFUL; + if ( !winbind_sid_to_gid(pgid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; } +success: DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), (unsigned int)*pgid )); -- cgit From c44a9d25a2bfff9d5ebede80f30e13e41aca797c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Jul 2003 23:05:57 +0000 Subject: Added the "required" keyword to the "client signing" parameter to force it on. Fail if missmatch. Small format tidyups in smbd/sesssetup.c. Preparing to add signing on server side. Jeremy. (This used to be commit c390b3e4cd68cfc233ddf14d139e25d40f050f27) --- source3/smbd/sesssetup.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 2631961739..7d77ed3071 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -53,10 +53,10 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv return status; } - /**************************************************************************** Add the standard 'Samba' signature to the end of the session setup. ****************************************************************************/ + static int add_signature(char *outbuf, char *p) { char *start = p; @@ -72,8 +72,9 @@ static int add_signature(char *outbuf, char *p) } /**************************************************************************** -send a security blob via a session setup reply + Send a security blob via a session setup reply. ****************************************************************************/ + static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, DATA_BLOB blob, NTSTATUS nt_status) { @@ -101,6 +102,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, /**************************************************************************** Do a 'guest' logon, getting back the ****************************************************************************/ + static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) { struct auth_context *auth_context; @@ -267,12 +269,12 @@ static int reply_spnego_kerberos(connection_struct *conn, } #endif - /**************************************************************************** - send a session setup reply, wrapped in SPNEGO. - get vuid and check first. - end the NTLMSSP exchange context if we are OK/complete fail + Send a session setup reply, wrapped in SPNEGO. + Get vuid and check first. + End the NTLMSSP exchange context if we are OK/complete fail ***************************************************************************/ + static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) @@ -326,8 +328,9 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, } /**************************************************************************** -reply to a session setup spnego negotiate packet + Reply to a session setup spnego negotiate packet. ****************************************************************************/ + static int reply_spnego_negotiate(connection_struct *conn, char *inbuf, char *outbuf, @@ -387,11 +390,11 @@ static int reply_spnego_negotiate(connection_struct *conn, /* already replied */ return -1; } - /**************************************************************************** -reply to a session setup spnego auth packet + Reply to a session setup spnego auth packet. ****************************************************************************/ + static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, DATA_BLOB blob1) @@ -425,10 +428,10 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return -1; } - /**************************************************************************** -reply to a session setup command + Reply to a session setup command. ****************************************************************************/ + static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, char *outbuf, int length,int bufsize) @@ -509,8 +512,9 @@ static void setup_new_vc_session(void) } /**************************************************************************** -reply to a session setup command + Reply to a session setup command. ****************************************************************************/ + int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, int length,int bufsize) { -- cgit From 1eff0523002319b2606466d3624e3a4612dbab6d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Jul 2003 18:06:27 +0000 Subject: Reformatting fixes to bring in line with the rest of the source. Jeremy. (This used to be commit 3c11d9362379f16bb0d14449f64e731efad97ffe) --- source3/smbd/process.c | 663 ++++++++++++++++++++++++------------------------- 1 file changed, 325 insertions(+), 338 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 18acb35f7a..b025503da4 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -53,9 +53,9 @@ extern int max_send; ****************************************************************************/ typedef struct { - ubi_slNode msg_next; - char *msg_buf; - int msg_len; + ubi_slNode msg_next; + char *msg_buf; + int msg_len; } pending_message_list; static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0}; @@ -67,29 +67,27 @@ static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) { - pending_message_list *msg = (pending_message_list *) + pending_message_list *msg = (pending_message_list *) malloc(sizeof(pending_message_list)); - if(msg == NULL) - { - DEBUG(0,("push_message: malloc fail (1)\n")); - return False; - } + if(msg == NULL) { + DEBUG(0,("push_message: malloc fail (1)\n")); + return False; + } - msg->msg_buf = (char *)malloc(msg_len); - if(msg->msg_buf == NULL) - { - DEBUG(0,("push_message: malloc fail (2)\n")); - SAFE_FREE(msg); - return False; - } + msg->msg_buf = (char *)malloc(msg_len); + if(msg->msg_buf == NULL) { + DEBUG(0,("push_message: malloc fail (2)\n")); + SAFE_FREE(msg); + return False; + } - memcpy(msg->msg_buf, buf, msg_len); - msg->msg_len = msg_len; + memcpy(msg->msg_buf, buf, msg_len); + msg->msg_len = msg_len; - ubi_slAddTail( list_head, msg); + ubi_slAddTail( list_head, msg); - return True; + return True; } /**************************************************************************** @@ -295,28 +293,29 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) void respond_to_all_remaining_local_messages(void) { - char buffer[1024]; - - /* - * Assert we have no exclusive open oplocks. - */ - - if(get_number_of_exclusive_open_oplocks()) { - DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", - get_number_of_exclusive_open_oplocks() )); - return; - } - - /* - * Keep doing receive_local_message with a 1 ms timeout until - * we have no more messages. - */ - while(receive_local_message(buffer, sizeof(buffer), 1)) { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(buffer, sizeof(buffer)); - } - - return; + char buffer[1024]; + + /* + * Assert we have no exclusive open oplocks. + */ + + if(get_number_of_exclusive_open_oplocks()) { + DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", + get_number_of_exclusive_open_oplocks() )); + return; + } + + /* + * Keep doing receive_local_message with a 1 ms timeout until + * we have no more messages. + */ + + while(receive_local_message(buffer, sizeof(buffer), 1)) { + /* Deal with oplock break requests from other smbd's. */ + process_local_message(buffer, sizeof(buffer)); + } + + return; } @@ -339,13 +338,11 @@ force write permissions on print services. functions. Any message that has a NULL function is unimplemented - please feel free to contribute implementations! */ -static const struct smb_message_struct -{ - const char *name; - int (*fn)(connection_struct *conn, char *, char *, int, int); - int flags; -} - smb_messages[256] = { +static const struct smb_message_struct { + const char *name; + int (*fn)(connection_struct *conn, char *, char *, int, int); + int flags; +} smb_messages[256] = { /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, @@ -849,67 +846,62 @@ set. Ignoring max smbd restriction.\n")); } /**************************************************************************** - process an smb from the client - split out from the smbd_process() code so - it can be used by the oplock break code. + Process an smb from the client - split out from the smbd_process() code so + it can be used by the oplock break code. ****************************************************************************/ + void process_smb(char *inbuf, char *outbuf) { - static int trans_num; - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; - - DO_PROFILE_INC(smb_count); - - if (trans_num == 0) { - /* on the first packet, check the global hosts allow/ hosts - deny parameters before doing any parsing of the packet - passed to us by the client. This prevents attacks on our - parsing code from hosts not in the hosts allow list */ - if (smbd_process_limit() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { - /* send a negative session response "not listening on calling - name" */ - static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG( 1, ( "Connection denied from %s\n", - client_addr() ) ); - (void)send_smb(smbd_server_fd(),(char *)buf); - exit_server("connection denied"); - } - } - - DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); - DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); - - if (msg_type == 0) - show_msg(inbuf); - else if(msg_type == SMBkeepalive) - return; /* Keepalive packet. */ - - nread = construct_reply(inbuf,outbuf,nread,max_send); + static int trans_num; + int msg_type = CVAL(inbuf,0); + int32 len = smb_len(inbuf); + int nread = len + 4; + + DO_PROFILE_INC(smb_count); + + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (smbd_process_limit() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { + /* send a negative session response "not listening on calling name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) ); + (void)send_smb(smbd_server_fd(),(char *)buf); + exit_server("connection denied"); + } + } + + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); + + if (msg_type == 0) + show_msg(inbuf); + else if(msg_type == SMBkeepalive) + return; /* Keepalive packet. */ + + nread = construct_reply(inbuf,outbuf,nread,max_send); - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); + if(nread > 0) { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("process_smb: send_smb failed."); - } - trans_num++; + if (nread != smb_len(outbuf) + 4) { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(outbuf))); + } else if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("process_smb: send_smb failed."); + } + } + trans_num++; } - - /**************************************************************************** -return a string containing the function name of a SMB command + Return a string containing the function name of a SMB command. ****************************************************************************/ + const char *smb_fn_name(int type) { const char *unknown_name = "SMBunknown"; @@ -949,92 +941,94 @@ void construct_reply_common(char *inbuf,char *outbuf) } /**************************************************************************** - construct a chained reply and add it to the already made reply - **************************************************************************/ + Construct a chained reply and add it to the already made reply +****************************************************************************/ + int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) { - static char *orig_inbuf; - static char *orig_outbuf; - int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); - unsigned smb_off2 = SVAL(inbuf,smb_vwv1); - char *inbuf2, *outbuf2; - int outsize2; - char inbuf_saved[smb_wct]; - char outbuf_saved[smb_wct]; - int wct = CVAL(outbuf,smb_wct); - int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); - - /* maybe its not chained */ - if (smb_com2 == 0xFF) { - SCVAL(outbuf,smb_vwv0,0xFF); - return outsize; - } - - if (chain_size == 0) { - /* this is the first part of the chain */ - orig_inbuf = inbuf; - orig_outbuf = outbuf; - } - - /* - * The original Win95 redirector dies on a reply to - * a lockingX and read chain unless the chain reply is - * 4 byte aligned. JRA. - */ - - outsize = (outsize + 3) & ~3; - - /* we need to tell the client where the next part of the reply will be */ - SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - SCVAL(outbuf,smb_vwv0,smb_com2); - - /* remember how much the caller added to the chain, only counting stuff - after the parameter words */ - chain_size += outsize - smb_wct; - - /* work out pointers into the original packets. The - headers on these need to be filled in */ - inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; - outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; - - /* remember the original command type */ - smb_com1 = CVAL(orig_inbuf,smb_com); - - /* save the data which will be overwritten by the new headers */ - memcpy(inbuf_saved,inbuf2,smb_wct); - memcpy(outbuf_saved,outbuf2,smb_wct); - - /* give the new packet the same header as the last part of the SMB */ - memmove(inbuf2,inbuf,smb_wct); - - /* create the in buffer */ - SCVAL(inbuf2,smb_com,smb_com2); - - /* create the out buffer */ - construct_reply_common(inbuf2, outbuf2); - - DEBUG(3,("Chained message\n")); - show_msg(inbuf2); - - /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, - bufsize-chain_size); - - /* copy the new reply and request headers over the old ones, but - preserve the smb_com field */ - memmove(orig_outbuf,outbuf2,smb_wct); - SCVAL(orig_outbuf,smb_com,smb_com1); - - /* restore the saved data, being careful not to overwrite any - data from the reply header */ - memcpy(inbuf2,inbuf_saved,smb_wct); - { - int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) ofs = 0; - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); - } - - return outsize2; + static char *orig_inbuf; + static char *orig_outbuf; + int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); + unsigned smb_off2 = SVAL(inbuf,smb_vwv1); + char *inbuf2, *outbuf2; + int outsize2; + char inbuf_saved[smb_wct]; + char outbuf_saved[smb_wct]; + int wct = CVAL(outbuf,smb_wct); + int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); + + /* maybe its not chained */ + if (smb_com2 == 0xFF) { + SCVAL(outbuf,smb_vwv0,0xFF); + return outsize; + } + + if (chain_size == 0) { + /* this is the first part of the chain */ + orig_inbuf = inbuf; + orig_outbuf = outbuf; + } + + /* + * The original Win95 redirector dies on a reply to + * a lockingX and read chain unless the chain reply is + * 4 byte aligned. JRA. + */ + + outsize = (outsize + 3) & ~3; + + /* we need to tell the client where the next part of the reply will be */ + SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); + SCVAL(outbuf,smb_vwv0,smb_com2); + + /* remember how much the caller added to the chain, only counting stuff + after the parameter words */ + chain_size += outsize - smb_wct; + + /* work out pointers into the original packets. The + headers on these need to be filled in */ + inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; + outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; + + /* remember the original command type */ + smb_com1 = CVAL(orig_inbuf,smb_com); + + /* save the data which will be overwritten by the new headers */ + memcpy(inbuf_saved,inbuf2,smb_wct); + memcpy(outbuf_saved,outbuf2,smb_wct); + + /* give the new packet the same header as the last part of the SMB */ + memmove(inbuf2,inbuf,smb_wct); + + /* create the in buffer */ + SCVAL(inbuf2,smb_com,smb_com2); + + /* create the out buffer */ + construct_reply_common(inbuf2, outbuf2); + + DEBUG(3,("Chained message\n")); + show_msg(inbuf2); + + /* process the request */ + outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, + bufsize-chain_size); + + /* copy the new reply and request headers over the old ones, but + preserve the smb_com field */ + memmove(orig_outbuf,outbuf2,smb_wct); + SCVAL(orig_outbuf,smb_com,smb_com1); + + /* restore the saved data, being careful not to overwrite any + data from the reply header */ + memcpy(inbuf2,inbuf_saved,smb_wct); + + { + int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); + if (ofs < 0) ofs = 0; + memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); + } + + return outsize2; } /**************************************************************************** @@ -1065,17 +1059,16 @@ static int setup_select_timeout(void) void check_reload(int t) { - static time_t last_smb_conf_reload_time = 0; + static time_t last_smb_conf_reload_time = 0; - if(last_smb_conf_reload_time == 0) - last_smb_conf_reload_time = t; + if(last_smb_conf_reload_time == 0) + last_smb_conf_reload_time = t; - if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) - { - reload_services(True); - reload_after_sighup = False; - last_smb_conf_reload_time = t; - } + if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { + reload_services(True); + reload_after_sighup = False; + last_smb_conf_reload_time = t; + } } /**************************************************************************** @@ -1084,165 +1077,159 @@ void check_reload(int t) static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time) { - static time_t last_keepalive_sent_time = 0; - static time_t last_idle_closed_check = 0; - time_t t; - BOOL allidle = True; - extern int keepalive; - - if (smb_read_error == READ_EOF) - { - DEBUG(3,("end of file from client\n")); - return False; - } - - if (smb_read_error == READ_ERROR) - { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return False; - } - - *last_timeout_processing_time = t = time(NULL); - - if(last_keepalive_sent_time == 0) - last_keepalive_sent_time = t; - - if(last_idle_closed_check == 0) - last_idle_closed_check = t; - - /* become root again if waiting */ - change_to_root_user(); - - /* run all registered idle events */ - smb_run_idle_events(t); - - /* check if we need to reload services */ - check_reload(t); - - /* automatic timeout if all connections are closed */ - if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) - { - DEBUG( 2, ( "Closing idle connection\n" ) ); - return False; - } - else - last_idle_closed_check = t; - - if (keepalive && (t - last_keepalive_sent_time)>keepalive) - { - extern struct auth_context *negprot_global_auth_context; - if (!send_keepalive(smbd_server_fd())) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return False; - } - - /* send a keepalive for a password server or the like. - This is attached to the auth_info created in the - negprot */ - if (negprot_global_auth_context - && negprot_global_auth_context->challenge_set_method - && negprot_global_auth_context->challenge_set_method->send_keepalive) { - negprot_global_auth_context->challenge_set_method->send_keepalive - (&negprot_global_auth_context->challenge_set_method->private_data); - } - - last_keepalive_sent_time = t; - } - - /* check for connection timeouts */ - allidle = conn_idle_all(t, deadtime); - - if (allidle && conn_num_open()>0) { - DEBUG(2,("Closing idle connection 2.\n")); - return False; - } - - if(global_machine_password_needs_changing && - /* for ADS we need to do a regular ADS password change, not a domain - password change */ - lp_security() == SEC_DOMAIN) - { - unsigned char trust_passwd_hash[16]; - time_t lct; - - /* - * We're in domain level security, and the code that - * read the machine password flagged that the machine - * password needs changing. - */ - - /* - * First, open the machine password file with an exclusive lock. - */ - - if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { - DEBUG(0,("process: unable to lock the machine account password for \ + static time_t last_keepalive_sent_time = 0; + static time_t last_idle_closed_check = 0; + time_t t; + BOOL allidle = True; + extern int keepalive; + + if (smb_read_error == READ_EOF) { + DEBUG(3,("end of file from client\n")); + return False; + } + + if (smb_read_error == READ_ERROR) { + DEBUG(3,("receive_smb error (%s) exiting\n", + strerror(errno))); + return False; + } + + *last_timeout_processing_time = t = time(NULL); + + if(last_keepalive_sent_time == 0) + last_keepalive_sent_time = t; + + if(last_idle_closed_check == 0) + last_idle_closed_check = t; + + /* become root again if waiting */ + change_to_root_user(); + + /* run all registered idle events */ + smb_run_idle_events(t); + + /* check if we need to reload services */ + check_reload(t); + + /* automatic timeout if all connections are closed */ + if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) { + DEBUG( 2, ( "Closing idle connection\n" ) ); + return False; + } else { + last_idle_closed_check = t; + } + + if (keepalive && (t - last_keepalive_sent_time)>keepalive) { + extern struct auth_context *negprot_global_auth_context; + if (!send_keepalive(smbd_server_fd())) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + + /* send a keepalive for a password server or the like. + This is attached to the auth_info created in the + negprot */ + if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method + && negprot_global_auth_context->challenge_set_method->send_keepalive) { + + negprot_global_auth_context->challenge_set_method->send_keepalive + (&negprot_global_auth_context->challenge_set_method->private_data); + } + + last_keepalive_sent_time = t; + } + + /* check for connection timeouts */ + allidle = conn_idle_all(t, deadtime); + + if (allidle && conn_num_open()>0) { + DEBUG(2,("Closing idle connection 2.\n")); + return False; + } + + if(global_machine_password_needs_changing && + /* for ADS we need to do a regular ADS password change, not a domain + password change */ + lp_security() == SEC_DOMAIN) { + + unsigned char trust_passwd_hash[16]; + time_t lct; + + /* + * We're in domain level security, and the code that + * read the machine password flagged that the machine + * password needs changing. + */ + + /* + * First, open the machine password file with an exclusive lock. + */ + + if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { + DEBUG(0,("process: unable to lock the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); - return True; - } + return True; + } - if(!secrets_fetch_trust_account_password(lp_workgroup(), - trust_passwd_hash, - &lct, NULL)) { - DEBUG(0,("process: unable to read the machine account password for \ + if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) { + DEBUG(0,("process: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup())); - secrets_lock_trust_account_password(lp_workgroup(), False); - return True; - } + secrets_lock_trust_account_password(lp_workgroup(), False); + return True; + } - /* - * Make sure someone else hasn't already done this. - */ + /* + * Make sure someone else hasn't already done this. + */ - if(t < lct + lp_machine_password_timeout()) { - global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); - return True; - } + if(t < lct + lp_machine_password_timeout()) { + global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(lp_workgroup(), False); + return True; + } - /* always just contact the PDC here */ + /* always just contact the PDC here */ - change_trust_account_password( lp_workgroup(), NULL); - global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); - } - - /* - * Check to see if we have any blocking locks - * outstanding on the queue. - */ - process_blocking_lock_queue(t); - - /* update printer queue caches if necessary */ + change_trust_account_password( lp_workgroup(), NULL); + global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(lp_workgroup(), False); + } + + /* + * Check to see if we have any blocking locks + * outstanding on the queue. + */ + process_blocking_lock_queue(t); + + /* update printer queue caches if necessary */ - update_monitored_printq_cache(); + update_monitored_printq_cache(); - /* - * Check to see if we have any change notifies - * outstanding on the queue. - */ - process_pending_change_notify_queue(t); + /* + * Check to see if we have any change notifies + * outstanding on the queue. + */ + process_pending_change_notify_queue(t); - /* - * Now we are root, check if the log files need pruning. - * Force a log file check. - */ - force_check_log_size(); - check_log_size(); + /* + * Now we are root, check if the log files need pruning. + * Force a log file check. + */ + force_check_log_size(); + check_log_size(); - /* Send any queued printer notify message to interested smbd's. */ + /* Send any queued printer notify message to interested smbd's. */ - print_notify_send_messages(0); + print_notify_send_messages(0); - /* - * Modify the select timeout depending upon - * what we have remaining in our queues. - */ + /* + * Modify the select timeout depending upon + * what we have remaining in our queues. + */ - *select_timeout = setup_select_timeout(); + *select_timeout = setup_select_timeout(); - return True; + return True; } /**************************************************************************** -- cgit From 4fbbaff415dbb8f1d06b6213e394860bf07a6b6d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Jul 2003 21:06:21 +0000 Subject: Add API framework for server SMB signing. Jeremy. (This used to be commit 61fc9a7b2eafdf8cbed1f8d9aae016b828c91a08) --- source3/smbd/oplock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8525687793..bd52b0066d 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -742,8 +742,12 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Remember if we just sent a break to level II on this file. */ fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - if (!send_smb(smbd_server_fd(), outbuf)) + srv_disable_signing(); + if (!send_smb(smbd_server_fd(), outbuf)) { + srv_enable_signing(); exit_server("oplock_break: send_smb failed."); + } + srv_enable_signing(); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; -- cgit From f1b6cd794dd5de853c4b068361a326160a3d0384 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Jul 2003 00:48:21 +0000 Subject: Putting the framework for server signing in place. Ensure we don't use sendfile when signing (I need to add this for readbraw/writebraw too...). Jeremy. (This used to be commit f2e84f1ba67b13ff29e24a38099b559d9033a680) --- source3/smbd/negprot.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index f452dd845b..0b58eb3eb2 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -277,6 +277,14 @@ static int reply_nt1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; + if (lp_server_signing()) { + secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; + /* No raw mode with smb signing. */ + capabilities &= ~CAP_RAW_MODE; + if (lp_server_signing() == Required) + secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; + } + set_message(outbuf,17,0,True); SCVAL(outbuf,smb_vwv1,secword); @@ -521,6 +529,10 @@ int reply_negprot(connection_struct *conn, DEBUG( 5, ( "negprot index=%d\n", choice ) ); + if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) { + exit_server("SMB signing is required and client negotiated a downlevel protocol"); + } + END_PROFILE(SMBnegprot); return(outsize); } -- cgit From 9ad4fbcf75df4ed89893ffb0379d95685560e466 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Jul 2003 00:53:37 +0000 Subject: Don't allow read/write raw when signing is active. Jeremy. (This used to be commit 8d2a848052df03dad7bfeb5e7be96f8e9a509bbf) --- source3/smbd/reply.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e7f01ad02f..61323e8b56 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1472,6 +1472,10 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s files_struct *fsp; START_PROFILE(SMBreadbraw); + if (srv_signing_active()) { + exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + } + /* * Special check if an oplock break has been issued * and the readraw request croses on the wire, we must @@ -1870,6 +1874,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = 0; START_PROFILE(SMBwritebraw); + if (srv_signing_active()) { + exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + } + CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); -- cgit From 583fc850781148b15f8fe20d9567ca840fb722d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Jul 2003 00:58:14 +0000 Subject: Correctly toggle the signing state to what it was previosly when sending an oplock break. Jeremy. (This used to be commit 9515de83a864250c417cf490b7be714c8e1e127e) --- source3/smbd/oplock.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index bd52b0066d..ab7c6e8344 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -660,6 +660,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, time_t start_time; BOOL shutdown_server = False; BOOL oplock_timeout = False; + BOOL sign_state; connection_struct *saved_user_conn; connection_struct *saved_fsp_conn; int saved_vuid; @@ -742,12 +743,16 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Remember if we just sent a break to level II on this file. */ fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - srv_disable_signing(); + /* Save the server smb signing state. */ + sign_state = srv_oplock_set_signing(False); + if (!send_smb(smbd_server_fd(), outbuf)) { - srv_enable_signing(); + srv_oplock_set_signing(sign_state); exit_server("oplock_break: send_smb failed."); } - srv_enable_signing(); + + /* Restore the sign state to what it was. */ + srv_oplock_set_signing(sign_state); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; -- cgit From 5b4a2dfd2b7fdc5006452126f3b1b8b4f1bc7fe2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Jul 2003 18:55:40 +0000 Subject: Formatting tidyups to match the rest of the source. Jeremy. (This used to be commit 86c5ebcf8f5eb57e9885627b3da4e486ee3f62d9) --- source3/smbd/password.c | 56 +++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e2c143f1e2..9930fc8c33 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -29,10 +29,11 @@ static int next_vuid = VUID_OFFSET; static int num_validated_vuids; /**************************************************************************** -check if a uid has been validated, and return an pointer to the user_struct -if it has. NULL if not. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. + Check if a uid has been validated, and return an pointer to the user_struct + if it has. NULL if not. vuid is biased by an offset. This allows us to + tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ + user_struct *get_valid_user_struct(uint16 vuid) { user_struct *usp; @@ -54,8 +55,9 @@ user_struct *get_valid_user_struct(uint16 vuid) } /**************************************************************************** -invalidate a uid + Invalidate a uid. ****************************************************************************/ + void invalidate_vuid(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); @@ -85,8 +87,9 @@ void invalidate_vuid(uint16 vuid) } /**************************************************************************** -invalidate all vuid entries for this process + Invalidate all vuid entries for this process. ****************************************************************************/ + void invalidate_all_vuids(void) { user_struct *usp, *next=NULL; @@ -238,38 +241,44 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) vuser->homes_snum = -1; } +#if 0 /* JRATEST. */ + if (lp_server_signing() && !vuser->guest && !srv_signing_active()) { + /* Try and turn on server signing on the first non-guest sessionsetup. */ + srv_set_signing(session_key.data, nt_response); + } +#endif + return vuser->vuid; } - /**************************************************************************** -add a name to the session users list + Add a name to the session users list. ****************************************************************************/ + void add_session_user(const char *user) { - fstring suser; - struct passwd *passwd; + fstring suser; + struct passwd *passwd; - if (!(passwd = Get_Pwnam(user))) return; + if (!(passwd = Get_Pwnam(user))) + return; - fstrcpy(suser,passwd->pw_name); + fstrcpy(suser,passwd->pw_name); - if (suser && *suser && !in_list(suser,session_users,False)) - { - if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) - DEBUG(1,("Too many session users??\n")); - else - { - pstrcat(session_users," "); - pstrcat(session_users,suser); + if (suser && *suser && !in_list(suser,session_users,False)) { + if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) { + DEBUG(1,("Too many session users??\n")); + } else { + pstrcat(session_users," "); + pstrcat(session_users,suser); + } } - } } - /**************************************************************************** -check if a username is valid + Check if a username is valid. ****************************************************************************/ + BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) { char **valid, **invalid; @@ -308,8 +317,9 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) } /**************************************************************************** -validate a group username entry. Return the username or NULL + Validate a group username entry. Return the username or NULL. ****************************************************************************/ + static char *validate_group(char *group, DATA_BLOB password,int snum) { #ifdef HAVE_NETGROUP -- cgit From 814e987c6241601fb03335b2ba9a633d65cc5e23 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Jul 2003 00:53:34 +0000 Subject: Signing so far... the client code fails on a SMBtrans2 secondary transaction I think (my changes haven't affected this I believe). Initial support on the server side for smbclient. Still doesn't work for w2k clients I think... Work in progress..... (don't change). Jeremy. (This used to be commit e5714edc233424c2f74edb6d658f32f8e0ec9275) --- source3/smbd/negprot.c | 18 +++++++++++++----- source3/smbd/password.c | 8 +++----- source3/smbd/reply.c | 4 ++-- source3/smbd/sesssetup.c | 35 ++++++++++++++++++++++++++--------- 4 files changed, 44 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 0b58eb3eb2..28e3cf97d1 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -278,11 +278,19 @@ static int reply_nt1(char *inbuf, char *outbuf) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; if (lp_server_signing()) { - secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; - /* No raw mode with smb signing. */ - capabilities &= ~CAP_RAW_MODE; - if (lp_server_signing() == Required) - secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; + if (lp_security() >= SEC_USER) { + secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; + /* No raw mode with smb signing. */ + capabilities &= ~CAP_RAW_MODE; + if (lp_server_signing() == Required) + secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; + srv_set_signing_negotiated(); + } else { + DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n")); + if (lp_server_signing() == Required) { + exit_server("reply_nt1: smb signing required and share level security selected."); + } + } } set_message(outbuf,17,0,True); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9930fc8c33..b988f2ec74 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -111,7 +111,7 @@ void invalidate_all_vuids(void) * */ -int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) +int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name) { user_struct *vuser = NULL; @@ -241,12 +241,10 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) vuser->homes_snum = -1; } -#if 0 /* JRATEST. */ - if (lp_server_signing() && !vuser->guest && !srv_signing_active()) { + if (lp_server_signing() && !vuser->guest && !srv_is_signing_active()) { /* Try and turn on server signing on the first non-guest sessionsetup. */ - srv_set_signing(session_key.data, nt_response); + srv_set_signing(vuser->session_key, response_blob); } -#endif return vuser->vuid; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 61323e8b56..44633b1db6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1472,7 +1472,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s files_struct *fsp; START_PROFILE(SMBreadbraw); - if (srv_signing_active()) { + if (srv_is_signing_active()) { exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); } @@ -1874,7 +1874,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = 0; START_PROFILE(SMBwritebraw); - if (srv_signing_active()) { + if (srv_is_signing_active()) { exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7d77ed3071..9ec5433b02 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -153,6 +153,7 @@ static int reply_spnego_kerberos(connection_struct *conn, uint8 session_key[16]; uint8 tok_id[2]; BOOL foreign = False; + DATA_BLOB nullblob = data_blob(NULL, 0); ZERO_STRUCT(ticket); ZERO_STRUCT(auth_data); @@ -235,7 +236,7 @@ static int reply_spnego_kerberos(connection_struct *conn, memcpy(server_info->session_key, session_key, sizeof(session_key)); /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, user); + sess_vuid = register_vuid(server_info, nullblob, user); free(user); @@ -250,6 +251,10 @@ static int reply_spnego_kerberos(connection_struct *conn, } SSVAL(outbuf, smb_uid, sess_vuid); + + if (!server_info->guest && !srv_check_sign_mac(inbuf)) { + exit_server("reply_spnego_kerberos: bad smb signature"); + } } /* wrap that up in a nice GSS-API wrapping */ @@ -275,7 +280,7 @@ static int reply_spnego_kerberos(connection_struct *conn, End the NTLMSSP exchange context if we are OK/complete fail ***************************************************************************/ -static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, +static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) { @@ -294,8 +299,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; + DATA_BLOB nullblob = data_blob(NULL, 0); + /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user); + sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); (*auth_ntlmssp_state)->server_info = NULL; if (sess_vuid == -1) { @@ -310,6 +317,11 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, } SSVAL(outbuf,smb_uid,sess_vuid); + + if (!server_info->guest && !srv_check_sign_mac(inbuf)) { + exit_server("reply_spnego_ntlmssp: bad smb signature"); + } + } } @@ -382,7 +394,7 @@ static int reply_spnego_negotiate(connection_struct *conn, data_blob_free(&secblob); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, &chal, nt_status); data_blob_free(&chal); @@ -419,7 +431,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, data_blob_free(&auth); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, &auth_reply, nt_status); data_blob_free(&auth_reply); @@ -742,7 +754,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, free_user_info(&user_info); data_blob_free(&lm_resp); - data_blob_free(&nt_resp); data_blob_clear_free(&plaintext_password); if (!NT_STATUS_IS_OK(nt_status)) { @@ -750,9 +761,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } if (!NT_STATUS_IS_OK(nt_status)) { + data_blob_free(&nt_resp); return ERROR_NT(nt_status_squash(nt_status)); } - + /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { @@ -770,12 +782,17 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, to a uid can get through without a password, on the same VC */ /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, sub_user); - + sess_vuid = register_vuid(server_info, nt_resp, sub_user); + data_blob_free(&nt_resp); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + if (!server_info->guest && !srv_check_sign_mac(inbuf)) { + exit_server("reply_sesssetup_and_X: bad smb signature"); + } + SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From 14f3c7507020d77bc92ae00614b6af8f24784925 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Jul 2003 06:48:28 +0000 Subject: this fixes a bug where Samba would under some circumstances return incomplete directory listings. The problem was the exact_match optimisation that short circuited directory listings on exact matches. This optimisation doesn't work when the unix filename contains Microsoft wildcard characters. (This used to be commit 84cee2c3fcc34fe6356e842821a5f0a361477637) --- source3/smbd/trans2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bdcd04443e..398646a6cd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -326,7 +326,13 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) return False; if (case_sig) return strcmp(str,mask)==0; - return StrCaseCmp(str,mask) == 0; + if (StrCaseCmp(str,mask) != 0) { + return False; + } + if (ms_has_wild(str)) { + return False; + } + return True; } /**************************************************************************** -- cgit From 5e252c86bd97305f3c6578afb29ccd148f985e60 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Jul 2003 07:07:29 +0000 Subject: make sure we don't allow the creation of directories containing wildcard characters. I've only put this in mkdir at the moment, but I suspect this will apply to all places that can create new filenames. We need to allow the opening of existing filenames that contain wildcards, but not allow the creation of new ones. (This used to be commit 2fd5569938b8970f3e9d761eecad5bc0b8bb267e) --- source3/smbd/reply.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 44633b1db6..5f3d6fa10e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2836,7 +2836,11 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) int ret= -1; unix_convert(directory,conn,0,&bad_path,&sbuf); - + + if (ms_has_wild(directory)) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + if (check_name(directory, conn)) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); -- cgit From f746a68030609aa6239a25664360913805abd78d Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Mon, 21 Jul 2003 20:20:09 +0000 Subject: Clarify a debug log a little. The path might not exist, so say so. (This used to be commit 8409cf3e470df79f219f9a21c0cb780e9257186c) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 18e0887071..c2855487a5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -661,7 +661,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, #else /* the alternative is just to check the directory exists */ if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); + DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); -- cgit From 80c1f1d865b13a63c7a60876b63458119566e044 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 22 Jul 2003 04:31:20 +0000 Subject: Fixup a bunch of printf-style functions and debugs to use unsigned long when displaying pid_t, uid_t and gid_t values. This removes a whole lot of warnings on some of the 64-bit build farm machines as well as help us out when 64-bit uid/gid/pid values come along. (This used to be commit f93528ba007c8800a850678f35f499fb7360fb9a) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6d03eaa29a..5f6ed74f09 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -675,8 +675,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { - DEBUG(0,("open_mode_check: Existent process %d left active oplock.\n", - broken_entry.pid )); + DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n", + (unsigned long)broken_entry.pid )); } if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { @@ -874,7 +874,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", - fname, psbuf->st_mode, mode )); + fname, (int)psbuf->st_mode, (int)mode )); file_free(fsp); errno = EACCES; return NULL; -- cgit From 3a5dc7c2ecacecf7dd0cfd71ff1bb298d70b391b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 23 Jul 2003 12:33:59 +0000 Subject: convert snprintf() calls using pstrings & fstrings to pstr_sprintf() and fstr_sprintf() to try to standardize. lots of snprintf() calls were using len-1; some were using len. At least this helps to be consistent. (This used to be commit 9f835b85dd38cbe655eb19021ff763f31886ac00) --- source3/smbd/sesssetup.c | 2 +- source3/smbd/trans2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9ec5433b02..767bf84154 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -62,7 +62,7 @@ static int add_signature(char *outbuf, char *p) char *start = p; fstring lanman; - snprintf( lanman, sizeof(lanman), "Samba %s", VERSION ); + fstr_sprintf( lanman, "Samba %s", VERSION ); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 398646a6cd..9998887793 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1912,7 +1912,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (strequal(base_name,".")) { pstrcpy(dos_fname, "\\"); } else { - snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname); + pstr_sprintf(dos_fname, "\\%s", fname); string_replace(dos_fname, '/', '\\'); } -- cgit From 79e2d7c24ebc06a485d8a26c1e58c684237ef533 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 04:25:37 +0000 Subject: Server side NTLM signing works - until the first async packet. Working on this next.... Jeremy. (This used to be commit eff74a1fcc597497a4c70589a44c1b70e93ab549) --- source3/smbd/sesssetup.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 767bf84154..689059a3ca 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -318,8 +318,14 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out SSVAL(outbuf,smb_uid,sess_vuid); - if (!server_info->guest && !srv_check_sign_mac(inbuf)) { - exit_server("reply_spnego_ntlmssp: bad smb signature"); + if (!server_info->guest) { + /* We need to start the signing engine + * here but a W2K client sends the old + * "BSRSPYL " signature instead of the + * correct one. Subsequent packets will + * be correct. + */ + srv_check_sign_mac(inbuf); } } -- cgit From 08634e26e45d3dd935727e43587a137c72417cd3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 06:19:37 +0000 Subject: SMB signing is now working with change notify. Need to fix the disconnect when bad signature received, plus check the oplock breaks.... Jermey. (This used to be commit dd83931a00ec0a2c4b78b939c54bc101ec82312f) --- source3/smbd/notify.c | 2 +- source3/smbd/nttrans.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index de1b331778..a0398d5a10 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -178,7 +178,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, struct change_notify *cnbp; if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { - DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); + DEBUG(0,("change_notify_set: malloc fail !\n" )); return -1; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c574d9d563..a2c29620c9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1494,6 +1494,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ name = %s\n", fsp->fsp_name )); + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + return -1; } -- cgit From 0c9433c03188a2d1b49318dd8535d10b7805ce42 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 06:56:56 +0000 Subject: Ensure everywhere we defer an incoming SMB request (blocking lock queue, in oplock break state, change notify queue) we also push the MID onto the deferred signing queue. Tomorrow I will test this with valgrind and oplock tests. Jeremy. (This used to be commit 33a377f3726c85379ba5b962dd7c8ead337b892f) --- source3/smbd/blocking.c | 498 ++++++++++++++++++++++++------------------------ source3/smbd/notify.c | 3 + source3/smbd/nttrans.c | 2 - source3/smbd/process.c | 3 + 4 files changed, 256 insertions(+), 250 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2802fbb151..fed3a51b88 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -28,16 +28,16 @@ extern char *OutBuffer; *****************************************************************************/ typedef struct { - ubi_slNode msg_next; - int com_type; - files_struct *fsp; - time_t expire_time; - int lock_num; - SMB_BIG_UINT offset; - SMB_BIG_UINT count; - uint16 lock_pid; - char *inbuf; - int length; + ubi_slNode msg_next; + int com_type; + files_struct *fsp; + time_t expire_time; + int lock_num; + SMB_BIG_UINT offset; + SMB_BIG_UINT count; + uint16 lock_pid; + char *inbuf; + int length; } blocking_lock_record; static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; @@ -48,8 +48,8 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu static void free_blocking_lock_record(blocking_lock_record *blr) { - SAFE_FREE(blr->inbuf); - SAFE_FREE(blr); + SAFE_FREE(blr->inbuf); + SAFE_FREE(blr); } /**************************************************************************** @@ -58,17 +58,17 @@ static void free_blocking_lock_record(blocking_lock_record *blr) static files_struct *get_fsp_from_pkt(char *inbuf) { - switch(CVAL(inbuf,smb_com)) { - case SMBlock: - case SMBlockread: - return file_fsp(inbuf,smb_vwv0); - case SMBlockingX: - return file_fsp(inbuf,smb_vwv2); - default: - DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return NULL; /* Keep compiler happy. */ + switch(CVAL(inbuf,smb_com)) { + case SMBlock: + case SMBlockread: + return file_fsp(inbuf,smb_vwv0); + case SMBlockingX: + return file_fsp(inbuf,smb_vwv2); + default: + DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return NULL; /* Keep compiler happy. */ } /**************************************************************************** @@ -77,7 +77,7 @@ static files_struct *get_fsp_from_pkt(char *inbuf) static BOOL in_chained_smb(void) { - return (chain_size != 0); + return (chain_size != 0); } static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); @@ -89,66 +89,68 @@ static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { - static BOOL set_lock_msg; - blocking_lock_record *blr; - NTSTATUS status; - - if(in_chained_smb() ) { - DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); - return False; - } - - /* - * Now queue an entry on the blocking lock queue. We setup - * the expiration time here. - */ - - if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); - return False; - } - - if((blr->inbuf = (char *)malloc(length)) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); - SAFE_FREE(blr); - return False; - } - - blr->com_type = CVAL(inbuf,smb_com); - blr->fsp = get_fsp_from_pkt(inbuf); - blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; - blr->lock_num = lock_num; - blr->lock_pid = lock_pid; - blr->offset = offset; - blr->count = count; - memcpy(blr->inbuf, inbuf, length); - blr->length = length; - - /* Add a pending lock record for this. */ - status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - lock_pid, sys_getpid(), blr->fsp->conn->cnum, - offset, count, - PENDING_LOCK); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); - free_blocking_lock_record(blr); - return False; - } + static BOOL set_lock_msg; + blocking_lock_record *blr; + NTSTATUS status; + + if(in_chained_smb() ) { + DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); + return False; + } + + /* + * Now queue an entry on the blocking lock queue. We setup + * the expiration time here. + */ - ubi_slAddTail(&blocking_lock_queue, blr); + if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); + return False; + } + + if((blr->inbuf = (char *)malloc(length)) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); + SAFE_FREE(blr); + return False; + } - /* Ensure we'll receive messages when this is unlocked. */ - if (!set_lock_msg) { - message_register(MSG_SMB_UNLOCK, received_unlock_msg); - set_lock_msg = True; - } + blr->com_type = CVAL(inbuf,smb_com); + blr->fsp = get_fsp_from_pkt(inbuf); + blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + blr->lock_num = lock_num; + blr->lock_pid = lock_pid; + blr->offset = offset; + blr->count = count; + memcpy(blr->inbuf, inbuf, length); + blr->length = length; + + /* Add a pending lock record for this. */ + status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + lock_pid, sys_getpid(), blr->fsp->conn->cnum, + offset, count, PENDING_LOCK); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); + free_blocking_lock_record(blr); + return False; + } + + ubi_slAddTail(&blocking_lock_queue, blr); + + /* Ensure we'll receive messages when this is unlocked. */ + if (!set_lock_msg) { + message_register(MSG_SMB_UNLOCK, received_unlock_msg); + set_lock_msg = True; + } - DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, - blr->fsp->fnum, blr->fsp->fsp_name )); + blr->fsp->fnum, blr->fsp->fsp_name )); - return True; + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + + return True; } /**************************************************************************** @@ -170,27 +172,27 @@ static void send_blocking_reply(char *outbuf, int outsize) static void reply_lockingX_success(blocking_lock_record *blr) { - char *outbuf = OutBuffer; - int bufsize = BUFFER_SIZE; - char *inbuf = blr->inbuf; - int outsize = 0; + char *outbuf = OutBuffer; + int bufsize = BUFFER_SIZE; + char *inbuf = blr->inbuf; + int outsize = 0; - construct_reply_common(inbuf, outbuf); - set_message(outbuf,2,0,True); + construct_reply_common(inbuf, outbuf); + set_message(outbuf,2,0,True); - /* - * As this message is a lockingX call we must handle - * any following chained message correctly. - * This is normally handled in construct_reply(), - * but as that calls switch_message, we can't use - * that here and must set up the chain info manually. - */ + /* + * As this message is a lockingX call we must handle + * any following chained message correctly. + * This is normally handled in construct_reply(), + * but as that calls switch_message, we can't use + * that here and must set up the chain info manually. + */ - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); + outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); - outsize += chain_size; + outsize += chain_size; - send_blocking_reply(outbuf,outsize); + send_blocking_reply(outbuf,outsize); } /**************************************************************************** @@ -492,18 +494,18 @@ Waiting....\n", static BOOL blocking_lock_record_process(blocking_lock_record *blr) { - switch(blr->com_type) { - case SMBlock: - return process_lock(blr); - case SMBlockread: - return process_lockread(blr); - case SMBlockingX: - return process_lockingX(blr); - default: - DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return False; /* Keep compiler happy. */ + switch(blr->com_type) { + case SMBlock: + return process_lock(blr); + case SMBlockread: + return process_lockread(blr); + case SMBlockingX: + return process_lockingX(blr); + default: + DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return False; /* Keep compiler happy. */ } /**************************************************************************** @@ -512,27 +514,27 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) void remove_pending_lock_requests_by_fid(files_struct *fsp) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - while(blr != NULL) { - if(blr->fsp->fnum == fsp->fnum) { + while(blr != NULL) { + if(blr->fsp->fnum == fsp->fnum) { - DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ + DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } /**************************************************************************** @@ -541,28 +543,28 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); void remove_pending_lock_requests_by_mid(int mid) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - while(blr != NULL) { - if(SVAL(blr->inbuf,smb_mid) == mid) { - files_struct *fsp = blr->fsp; + while(blr != NULL) { + if(SVAL(blr->inbuf,smb_mid) == mid) { + files_struct *fsp = blr->fsp; - DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ + DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } - - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } /**************************************************************************** @@ -611,112 +613,112 @@ unsigned blocking_locks_timeout(unsigned default_timeout) void process_blocking_lock_queue(time_t t) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; - - if(blr == NULL) - return; - - /* - * Go through the queue and see if we can get any of the locks. - */ - - while(blr != NULL) { - connection_struct *conn = NULL; - uint16 vuid; - files_struct *fsp = NULL; - - /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - file_chain_reset(); - fsp = blr->fsp; - - conn = conn_find(SVAL(blr->inbuf,smb_tid)); - vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(blr->inbuf,smb_uid); - - DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", - fsp->fnum, fsp->fsp_name )); - - if((blr->expire_time != -1) && (blr->expire_time <= t)) { - /* - * Lock expired - throw away all previously - * obtained locks and return lock error. - */ - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } - - if(!change_to_user(conn,vuid)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; - } - - if(!set_current_service(conn,True)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - change_to_root_user(); - continue; - } - - /* - * Go through the remaining locks and try and obtain them. - * The call returns True if all locks were obtained successfully - * and False if we still need to wait. - */ - - if(blocking_lock_record_process(blr)) { - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - change_to_root_user(); - continue; - } - - change_to_root_user(); - - /* - * Move to the next in the list. - */ - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + if(blr == NULL) + return; + + /* + * Go through the queue and see if we can get any of the locks. + */ + + while(blr != NULL) { + connection_struct *conn = NULL; + uint16 vuid; + files_struct *fsp = NULL; + + /* + * Ensure we don't have any old chain_fsp values + * sitting around.... + */ + chain_size = 0; + file_chain_reset(); + fsp = blr->fsp; + + conn = conn_find(SVAL(blr->inbuf,smb_tid)); + vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(blr->inbuf,smb_uid); + + DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", + fsp->fnum, fsp->fsp_name )); + + if((blr->expire_time != -1) && (blr->expire_time <= t)) { + /* + * Lock expired - throw away all previously + * obtained locks and return lock error. + */ + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fsp->fnum, fsp->fsp_name )); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + if(!change_to_user(conn,vuid)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; + } + + if(!set_current_service(conn,True)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + change_to_root_user(); + continue; + } + + /* + * Go through the remaining locks and try and obtain them. + * The call returns True if all locks were obtained successfully + * and False if we still need to wait. + */ + + if(blocking_lock_record_process(blr)) { + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + change_to_root_user(); + continue; + } + + change_to_root_user(); + + /* + * Move to the next in the list. + */ + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index a0398d5a10..e7903719ad 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -197,6 +197,9 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + return True; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a2c29620c9..c574d9d563 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1494,8 +1494,6 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ name = %s\n", fsp->fsp_name )); - srv_defer_sign_response(SVAL(inbuf,smb_mid)); - return -1; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b025503da4..fb85f38119 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -87,6 +87,9 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) ubi_slAddTail( list_head, msg); + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(buf,smb_mid)); + return True; } -- cgit From ae6a63fa469e77746003d7a3d2bd3df49426ffb4 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 24 Jul 2003 11:37:11 +0000 Subject: Rise debug level to 5 for not-found-nt-quota message (quota setting for user wasn't found) (This used to be commit 422dffdc40742091df027fcffbc074eb2b1396dc) --- source3/smbd/ntquotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 2e865000ec..88d7c4e164 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -188,7 +188,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) } if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) { - DEBUG(1,("no quota entry for sid[%s] path[%s]\n", + DEBUG(5,("no quota entry for sid[%s] path[%s]\n", sid_string_static(&sid),fsp->conn->connectpath)); continue; } -- cgit From ceb68ee051e97afb1cb08e6f458e23e8f475504e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 19:05:32 +0000 Subject: Fix packet signing with asynchronous oplock breaks. Removed bad error message due to w2k bug. I think this code is now working.... Need more testing of course but works on all the obvious cases I can think of. Jeremy. (This used to be commit a6e537f6611cc1357fffea0b69901fba7c9ad6ea) --- source3/smbd/process.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index fb85f38119..dce1c4bc03 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1087,16 +1087,21 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t extern int keepalive; if (smb_read_error == READ_EOF) { - DEBUG(3,("end of file from client\n")); + DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); return False; } if (smb_read_error == READ_ERROR) { - DEBUG(3,("receive_smb error (%s) exiting\n", + DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", strerror(errno))); return False; } + if (smb_read_error == READ_BAD_SIG) { + DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); + return False; + } + *last_timeout_processing_time = t = time(NULL); if(last_keepalive_sent_time == 0) -- cgit From 60097e0d8d3db07eecf1773d74f8376ea4059b05 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 19:10:52 +0000 Subject: Fix from matt.zinkevicius@hp.com to stop files being created on read-only shares in some circumstances. Jeremy. (This used to be commit b826e8c8980d26e932da55384f109f0fe6a124c7) --- source3/smbd/open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5f6ed74f09..8f83983023 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -125,6 +125,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, directory. */ flags &= ~O_CREAT; + local_flags &= ~O_CREAT; } } -- cgit From 77373f1f8e3b2f61e9bbcd9fadfb83257d390cf2 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 24 Jul 2003 23:46:27 +0000 Subject: More printf fixes - size_t is long on some architectures. (This used to be commit ba4d334b822248d8ab929c9568533431603d967e) --- source3/smbd/close.c | 2 +- source3/smbd/sesssetup.c | 2 +- source3/smbd/utmp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 1be13270ba..c2db901ea7 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -163,7 +163,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) share_entry_count = del_share_mode(fsp, &share_entry); - DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n", + DEBUG(10,("close_normal_file: share_entry_count = %l for file %s\n", share_entry_count, fsp->fsp_name )); /* diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 689059a3ca..8e02f65951 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -375,7 +375,7 @@ static int reply_spnego_negotiate(connection_struct *conn, } free(OIDs[i]); } - DEBUG(3,("Got secblob of size %d\n", secblob.length)); + DEBUG(3,("Got secblob of size %l\n", secblob.length)); #ifdef HAVE_KRB5 if (got_kerberos && (SEC_ADS == lp_security())) { diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 9833a11f2d..aaf081a21e 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -491,7 +491,7 @@ static BOOL sys_utmp_fill(struct utmp *u, * If size limit proves troublesome, then perhaps use "ut_id_encode()". */ if (strlen(id_str) > sizeof(u->ut_line)) { - DEBUG(1,("id_str [%s] is too long for %d char utmp field\n", + DEBUG(1,("id_str [%s] is too long for %l char utmp field\n", id_str, sizeof(u->ut_line))); return False; } -- cgit From 7d833de662b83f026b54a236588da27dd8899630 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 25 Jul 2003 04:24:40 +0000 Subject: More printf portability fixes. Got caught out by some gcc'isms last time. )-: (This used to be commit 59dae1da66a5eb7e128263bd578f167d8746e9f0) --- source3/smbd/close.c | 4 ++-- source3/smbd/sesssetup.c | 2 +- source3/smbd/utmp.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c2db901ea7..0700aeaa0a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -163,8 +163,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) share_entry_count = del_share_mode(fsp, &share_entry); - DEBUG(10,("close_normal_file: share_entry_count = %l for file %s\n", - share_entry_count, fsp->fsp_name )); + DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n", + (unsigned long)share_entry_count, fsp->fsp_name )); /* * We delete on close if it's the last open, and the diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8e02f65951..bc3ac6ac64 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -375,7 +375,7 @@ static int reply_spnego_negotiate(connection_struct *conn, } free(OIDs[i]); } - DEBUG(3,("Got secblob of size %l\n", secblob.length)); + DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 if (got_kerberos && (SEC_ADS == lp_security())) { diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index aaf081a21e..6ff2f586ba 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -491,8 +491,8 @@ static BOOL sys_utmp_fill(struct utmp *u, * If size limit proves troublesome, then perhaps use "ut_id_encode()". */ if (strlen(id_str) > sizeof(u->ut_line)) { - DEBUG(1,("id_str [%s] is too long for %l char utmp field\n", - id_str, sizeof(u->ut_line))); + DEBUG(1,("id_str [%s] is too long for %lu char utmp field\n", + id_str, (unsigned long)sizeof(u->ut_line))); return False; } utmp_strcpy(u->ut_line, id_str, sizeof(u->ut_line)); -- cgit From 559439e1f4d3ba3444213cbf64a1ede5f9d51906 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Jul 2003 23:43:22 +0000 Subject: Start the packet signing engine in the kerberos case in the same place as the ntlmssp case. Jeremy. (This used to be commit 79e0bf829875fc985f1940dc31ee418aad910ed6) --- source3/smbd/sesssetup.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index bc3ac6ac64..ccd7214251 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -252,8 +252,14 @@ static int reply_spnego_kerberos(connection_struct *conn, SSVAL(outbuf, smb_uid, sess_vuid); - if (!server_info->guest && !srv_check_sign_mac(inbuf)) { - exit_server("reply_spnego_kerberos: bad smb signature"); + if (!server_info->guest) { + /* We need to start the signing engine + * here but a W2K client sends the old + * "BSRSPYL " signature instead of the + * correct one. Subsequent packets will + * be correct. + */ + srv_check_sign_mac(inbuf); } } @@ -327,7 +333,6 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out */ srv_check_sign_mac(inbuf); } - } } -- cgit From 455bb6de903ca3950d965b29190c09f116d91889 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 27 Jul 2003 02:28:25 +0000 Subject: Some small fixes to our charset conversion code: - Treat the NMB names in the 'session request' packet as 'ASCII'. This means that we do not get invalid multibyte from the wire, even if we truncate in the conversion. (Otherwise we panic when we try to strupper_m it). - Remove acnv_uxu2(), as it was duplicated by push_ucs2_allocate() - Remove acnv_dosu2(), as it is not used. - In push_ucs2(), with the STR_UPPER flag, do the case conversion *after* the UCS2 conversion, when it we know that the length can't change. Also faster, as we don't need to do another 2 UCS2 conversions. Andrew Bartlett (This used to be commit 912035af1178424583d0bf887a391a0cac2acd87) --- source3/smbd/mangle_hash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index ac8e425fd3..ac2d7681e8 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -313,6 +313,7 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + size_t size; if (!fname || !*fname) return False; @@ -324,9 +325,9 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) if (strlen(f) > 12) return False; - ucs2name = acnv_uxu2(f); - if (!ucs2name) { - DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); + size = push_ucs2_allocate(&ucs2name, f); + if (size == (size_t)-1) { + DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n")); goto done; } -- cgit From 1478bcd847cfe0fe8374f403f20761675d944413 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 27 Jul 2003 03:29:40 +0000 Subject: Try again to fix up 'session request' name exchange. This time we actualy get the names... Andrew Bartlett (This used to be commit 7c9e204f7eb15139532f2cc522ed87d0ac34d118) --- source3/smbd/reply.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5f3d6fa10e..eaaa4e2730 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -75,23 +75,16 @@ int reply_special(char *inbuf,char *outbuf) return(0); } name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); + name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2); DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - name1[15] = 0; - - len = strlen(name2); - if (len == 16) { - name_type = name2[15]; - name2[15] = 0; - } - set_local_machine_name(name1, True); set_remote_machine_name(name2, True); - DEBUG(2,("netbios connect: local=%s remote=%s\n", - get_local_machine_name(), get_remote_machine_name() )); + DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n", + get_local_machine_name(), get_remote_machine_name(), + name_type)); if (name_type == 'R') { /* We are being asked for a pathworks session --- -- cgit From 5b84b13a1e2f47fbd5ca710721cdb9b3f10727e1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 27 Jul 2003 03:40:45 +0000 Subject: Allow the stat cache to better handle invalid multibyte strings, by using strdup_upper(). This function may fail - and we can just drop out of using the cache in that case. (Rather than panicing). This also should get us closer to supporting all of the weird 'longer/shorter' on uppercase/lowercase. Andrew Bartlett (This used to be commit d4c9261725578231079ed83e8e6584f12bd1cc43) --- source3/smbd/statcache.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 22b8a33a1e..fbebdb240f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -98,7 +98,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat translated_path_length--; } - original_path = strdup(full_orig_name); + if(case_sensitive) { + original_path = strdup(full_orig_name); + } else { + original_path = strdup_upper(full_orig_name); + } + if (!original_path) { SAFE_FREE(translated_path); return; @@ -111,9 +116,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat original_path_length--; } - if(!case_sensitive) - strupper_m(original_path); - if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", @@ -161,6 +163,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } scp->original_path = scp->names; + /* pointer into the structure... */ scp->translated_path = scp->names + original_path_length + 1; safe_strcpy(scp->original_path, original_path, original_path_length); safe_strcpy(scp->translated_path, translated_path, translated_path_length); @@ -194,7 +197,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - pstring chk_name; + char *chk_name; size_t namelen; hash_element *hash_elem; char *sp; @@ -218,10 +221,20 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; } - pstrcpy(chk_name, name); + if (case_sensitive) { + chk_name = strdup(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); + return False; + } + + } else { + chk_name = strdup_upper(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n")); + return False; + } - if(!case_sensitive) { - strupper_m( chk_name ); /* * In some language encodings the length changes * if we uppercase. We need to treat this differently @@ -252,11 +265,13 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, * We reached the end of the name - no match. */ DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) || (strcmp(chk_name, "..") == 0)) { DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } } else { @@ -265,6 +280,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); + SAFE_FREE(chk_name); return False; } @@ -290,6 +306,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, ++*start; pstrcpy(dirpath, scp->translated_path); + SAFE_FREE(chk_name); return (namelen == scp->translated_path_length); } } -- cgit From 79a5d2e31bd1d5711d4fe7f9161abfc4ff81e7af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Jul 2003 17:34:20 +0000 Subject: Finish tridge's patch as referenced here : make sure we don't allow the creation of directories containing wildcard characters. I've only put this in mkdir at the moment, but I suspect this will apply to all places that can create new filenames. We need to allow the opening of existing filenames that contain wildcards, but not allow the creation of new ones. Jeremy. (This used to be commit 7f111e545d198faa5fa89f6d360db0d5c32a8bd7) --- source3/smbd/open.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8f83983023..5f49640aa4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -167,6 +167,14 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags |= O_NONBLOCK; #endif + /* Don't create files with Microsoft wildcard characters. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return False; + } + /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { @@ -1291,6 +1299,15 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } + if (ms_has_wild(fname)) { + file_free(fsp); + DEBUG(5,("open_directory: failing create on filename %s with wildcards\n", fname)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return NULL; + } + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); -- cgit From 6070a519c2058224d6703e1b7fdff54986c621f5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Jul 2003 19:16:59 +0000 Subject: Fix bug #226. Stop unmangle of name into a wildcard name from deleting more than was intended. Jeremy. (This used to be commit e2742e0d897a35820a7d8f184292c32a4c3952e3) --- source3/smbd/reply.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eaaa4e2730..71312295f4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -48,8 +48,6 @@ int reply_special(char *inbuf,char *outbuf) int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); pstring name1,name2; - - int len; char name_type = 0; static BOOL already_got_session = False; @@ -1274,6 +1272,16 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) *directory = *mask = 0; + /* We must check for wildcards in the name given + * directly by the client - before any unmangling. + * This prevents an unmangling of a UNIX name containing + * a DOS wildcard like '*' or '?' from unmangling into + * a wildcard delete which was not intended. + * FIX for #226. JRA. + */ + + has_wild = ms_has_wild(name); + rc = unix_convert(name,conn,0,&bad_path,&sbuf); p = strrchr_m(name,'/'); @@ -1298,13 +1306,12 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (!rc && mangle_is_mangled(mask)) mangle_check_cache( mask ); - has_wild = ms_has_wild(mask); - if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); error = can_delete(directory,conn,dirtype); - if (!NT_STATUS_IS_OK(error)) return error; + if (!NT_STATUS_IS_OK(error)) + return error; if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; @@ -1331,12 +1338,15 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive)) continue; + if(!mask_match(fname, mask, case_sensitive)) + continue; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype); - if (!NT_STATUS_IS_OK(error)) continue; - if (SMB_VFS_UNLINK(conn,fname) == 0) count++; + if (!NT_STATUS_IS_OK(error)) + continue; + if (SMB_VFS_UNLINK(conn,fname) == 0) + count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dirptr); @@ -1372,7 +1382,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); status = unlink_internals(conn, dirtype, name); - if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); /* * Win2k needs a changenotify request response before it will -- cgit From 29ca70cd34d3ba927ea1a9915ebd247f64965bd5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Jul 2003 23:49:29 +0000 Subject: Add a command line option (-S on|off|required) to enable signing on client connections. Overrides smb.conf parameter if set. Jeremy. (This used to be commit 879309671df6b530e0bff69559422a417da4a307) --- source3/smbd/change_trust_pw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 4993e285ca..2eff77b1f7 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -58,7 +58,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m NULL, 0, "IPC$", "IPC", "", "", - "", 0, NULL))) + "", 0, Undefined, NULL))) { DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); nt_status = NT_STATUS_UNSUCCESSFUL; -- cgit From ba12e6bb5fcfbf4bdba8f2c38978d38e1f857286 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Jul 2003 01:33:44 +0000 Subject: Wrap calls to change_oem_password() in become_root()/unbecome_root() pairs to allow UNIX password change scripts to work correctly. This is safe as the old password has been checked as correct before invoking this. Jeremy. (This used to be commit 1734d43eb55561d46a6ffb5d806afedfd3746f9f) --- source3/smbd/chgpasswd.c | 15 ++++--- source3/smbd/lanman.c | 112 ++++++++++++++++++++++++----------------------- 2 files changed, 66 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5c1d9a79a6..6bc8626d81 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -674,6 +674,8 @@ BOOL check_lanman_password(char *user, uchar * pass1, Code to change the lanman hashed password. It nulls out the NT hashed password as it will no longer be valid. + NOTE this function is designed to be called as root. Check the old password + is correct before calling. JRA. ************************************************************/ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) @@ -730,9 +732,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) } /* Now flush the sam_passwd struct to persistent storage */ - become_root(); ret = pdb_update_sam_account (sampass); - unbecome_root(); return ret; } @@ -740,6 +740,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) /*********************************************************** Code to check and change the OEM hashed password. ************************************************************/ + NTSTATUS pass_oem_change(char *user, uchar * lmdata, uchar * lmhash, uchar * ntdata, uchar * nthash) @@ -747,8 +748,7 @@ NTSTATUS pass_oem_change(char *user, fstring new_passwd; const char *unix_user; SAM_ACCOUNT *sampass = NULL; - NTSTATUS nt_status - = check_oem_password(user, lmdata, lmhash, ntdata, nthash, + NTSTATUS nt_status = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); if (!NT_STATUS_IS_OK(nt_status)) @@ -765,7 +765,10 @@ NTSTATUS pass_oem_change(char *user, unix_user = pdb_get_username(sampass); + /* We've already checked the old password here.... */ + become_root(); nt_status = change_oem_password(sampass, NULL, new_passwd); + unbecome_root(); memset(new_passwd, 0, sizeof(new_passwd)); @@ -942,6 +945,8 @@ static NTSTATUS check_oem_password(const char *user, /*********************************************************** Code to change the oem password. Changes both the lanman and NT hashes. Old_passwd is almost always NULL. + NOTE this function is designed to be called as root. Check the old password + is correct before calling. JRA. ************************************************************/ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd) @@ -997,9 +1002,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw } /* Now write it into the file. */ - become_root(); ret = pdb_update_sam_account (hnd); - unbecome_root(); if (!ret) { return NT_STATUS_ACCESS_DENIED; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 04d6a9a8a8..a5f7a7b2ea 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1897,76 +1897,78 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *p = skip_string(param+2,2); - fstring user; - fstring pass1,pass2; + char *p = skip_string(param+2,2); + fstring user; + fstring pass1,pass2; - pull_ascii_fstring(user,p); + pull_ascii_fstring(user,p); - p = skip_string(p,1); + p = skip_string(p,1); - memset(pass1,'\0',sizeof(pass1)); - memset(pass2,'\0',sizeof(pass2)); - memcpy(pass1,p,16); - memcpy(pass2,p+16,16); + memset(pass1,'\0',sizeof(pass1)); + memset(pass2,'\0',sizeof(pass2)); + memcpy(pass1,p,16); + memcpy(pass2,p+16,16); - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); - SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,2,0); /* converter word */ - DEBUG(3,("Set password for <%s>\n",user)); + DEBUG(3,("Set password for <%s>\n",user)); - /* - * Attempt to verify the old password against smbpasswd entries - * Win98 clients send old and new password in plaintext for this call. - */ + /* + * Attempt to verify the old password against smbpasswd entries + * Win98 clients send old and new password in plaintext for this call. + */ - { - auth_serversupplied_info *server_info = NULL; - DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); - if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - - if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) - { - SSVAL(*rparam,0,NERR_Success); - } - - free_server_info(&server_info); - } - data_blob_clear_free(&password); - } + { + auth_serversupplied_info *server_info = NULL; + DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); - /* - * If the plaintext change failed, attempt - * the old encrypted method. NT will generate this - * after trying the samr method. Note that this - * method is done as a last resort as this - * password change method loses the NT password hash - * and cannot change the UNIX password as no plaintext - * is received. - */ + if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - if(SVAL(*rparam,0) != NERR_Success) - { - SAM_ACCOUNT *hnd = NULL; + become_root(); + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); - if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && - change_lanman_password(hnd,pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - pdb_free_sam(&hnd); - } + free_server_info(&server_info); + } + data_blob_clear_free(&password); + } + /* + * If the plaintext change failed, attempt + * the old encrypted method. NT will generate this + * after trying the samr method. Note that this + * method is done as a last resort as this + * password change method loses the NT password hash + * and cannot change the UNIX password as no plaintext + * is received. + */ + + if(SVAL(*rparam,0) != NERR_Success) { + SAM_ACCOUNT *hnd = NULL; - memset((char *)pass1,'\0',sizeof(fstring)); - memset((char *)pass2,'\0',sizeof(fstring)); + if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { + become_root(); + if (change_lanman_password(hnd,pass2)) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); + pdb_free_sam(&hnd); + } + } + + memset((char *)pass1,'\0',sizeof(fstring)); + memset((char *)pass2,'\0',sizeof(fstring)); - return(True); + return(True); } /**************************************************************************** -- cgit From 0da36b22ff3382f2e4a86f4090ad8097a2dd8a32 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 31 Jul 2003 19:01:22 +0000 Subject: only honor the first OID in the sessetup snego negotiate. Deviates from RFC but I'm smelling a client bug here. /* only look at the first OID for determining the mechToken -- accoirding to RFC2478, we should choose the one we want and renegotiate, but i smell a client bug here.. Problem observed when connecting to a member (samba box) of an AD domain as a user in a Samba domain. Samba member server sent back krb5/mskrb5/ntlmssp as mechtypes, but the client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an NTLMSSP mechtoken. --jerry */ (This used to be commit 731420b03dbc15977822f74047e931dc62284fc0) --- source3/smbd/sesssetup.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index ccd7214251..c585ac1e67 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -371,13 +371,24 @@ static int reply_spnego_negotiate(connection_struct *conn, if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + + /* only look at the first OID for determining the mechToken -- + accoirding to RFC2478, we should choose the one we want + and renegotiate, but i smell a client bug here.. + + Problem observed when connecting to a member (samba box) + of an AD domain as a user in a Samba domain. Samba member + server sent back krb5/mskrb5/ntlmssp as mechtypes, but the + client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an + NTLMSSP mechtoken. --jerry */ + if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || + strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { + got_kerberos = True; + } + for (i=0;OIDs[i];i++) { DEBUG(3,("Got OID %s\n", OIDs[i])); - if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 || - strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) { - got_kerberos = True; - } free(OIDs[i]); } DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); -- cgit From 8c64504f7c58b05769ec1014242c15a2eb93ca84 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 1 Aug 2003 15:30:44 +0000 Subject: Update my copyrights according to my agreement with IBM (This used to be commit a2bd8f0bfa12f2a1e33c96bc9dabcc0e2171700d) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c585ac1e67..88b442215d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -3,7 +3,7 @@ handle SMBsessionsetup Copyright (C) Andrew Tridgell 1998-2001 Copyright (C) Andrew Bartlett 2001 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 2002 Copyright (C) Luke Howard 2003 This program is free software; you can redistribute it and/or modify -- cgit From 760e58cf807e099b450c83fbdb8d393d53b9dca3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 2 Aug 2003 03:06:07 +0000 Subject: Add the same signing code to the server. Ensure we use identical session numbers and MIDs when in trans/trans2/nttrans code. Jeremy. (This used to be commit 901544b29b4d815709b3dbad3012f1d2c419d904) --- source3/smbd/ipc.c | 6 ++++++ source3/smbd/nttrans.c | 6 ++++++ source3/smbd/trans2.c | 6 ++++++ 3 files changed, 18 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 85e28f5d17..f0b5c4a92f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -428,6 +428,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if (pscnt < tpscnt || dscnt < tdscnt) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -455,6 +457,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int SAFE_FREE(data); SAFE_FREE(setup); END_PROFILE(SMBtrans); + srv_signing_trans_stop(); return(ERROR_DOS(ERRSRV,ERRerror)); } @@ -542,6 +545,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int SAFE_FREE(params); SAFE_FREE(setup); + srv_signing_trans_stop(); + if (close_on_completion) close_cnum(conn,vuid); @@ -561,6 +566,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bad_param: + srv_signing_trans_stop(); DEBUG(0,("reply_trans: invalid trans parameters\n")); SAFE_FREE(data); SAFE_FREE(params); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c574d9d563..1506877aff 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2321,6 +2321,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); dump_data(10, data, data_count); } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -2484,6 +2486,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBnttrans); + srv_signing_trans_stop(); return ERROR_DOS(ERRSRV,ERRerror); } @@ -2494,6 +2497,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); an error packet. */ + srv_signing_trans_stop(); + SAFE_FREE(setup); SAFE_FREE(params); SAFE_FREE(data); @@ -2504,6 +2509,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); bad_param: + srv_signing_trans_stop(); SAFE_FREE(params); SAFE_FREE(data); SAFE_FREE(setup); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9998887793..86906fa5be 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3359,6 +3359,8 @@ int reply_trans2(connection_struct *conn, memcpy( data, smb_base(inbuf) + dsoff, num_data); } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if(num_data_sofar < total_data || num_params_sofar < total_params) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -3531,6 +3533,7 @@ int reply_trans2(connection_struct *conn, SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); + srv_signing_trans_stop(); return ERROR_DOS(ERRSRV,ERRerror); } @@ -3541,6 +3544,8 @@ int reply_trans2(connection_struct *conn, an error packet. */ + srv_signing_trans_stop(); + SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); @@ -3550,6 +3555,7 @@ int reply_trans2(connection_struct *conn, bad_param: + srv_signing_trans_stop(); SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); -- cgit From 099bd33a9999718e6cfe6cb387c8845805b67284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 2 Aug 2003 07:07:38 +0000 Subject: More fixes for client and server side signing. Ensure sequence numbers are updated correctly on returning an error for server trans streams. Ensure we turn off client trans streams on error. Jeremy. (This used to be commit 3a789cb7f01115c37404e5a696de363287cb0e5f) --- source3/smbd/ipc.c | 5 ++--- source3/smbd/oplock.c | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f0b5c4a92f..39072f9b91 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -509,11 +509,10 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); } } - - + DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", name,tdscnt,tpscnt,suwcnt)); - + /* * WinCE wierdness.... */ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ab7c6e8344..19e6956d9e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -800,6 +800,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, } else if (smb_read_error == READ_ERROR) { DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); shutdown_server = True; + } else if (smb_read_error == READ_BAD_SIG) { + DEBUG( 0, ("oplock_break: bad signature from client\n" )); + shutdown_server = True; } else if (smb_read_error == READ_TIMEOUT) { DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); oplock_timeout = True; -- cgit From b925d197f5c1829f7bb8c18de2557c0ccc2d94a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 2 Aug 2003 08:48:01 +0000 Subject: Ensure we don't leak any sign records on cancel of pending requests. Jeremy. (This used to be commit 9a8ffc239c0f1aada713de7e9e007066738d8874) --- source3/smbd/notify.c | 1 + source3/smbd/nttrans.c | 1 + 2 files changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index e7903719ad..9adf827c79 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -44,6 +44,7 @@ static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ + static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1506877aff..3ffa6efa77 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1443,6 +1443,7 @@ int reply_ntcancel(connection_struct *conn, START_PROFILE(SMBntcancel); remove_pending_change_notify_requests_by_mid(mid); remove_pending_lock_requests_by_mid(mid); + srv_cancel_sign_response(mid); DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); -- cgit From 8d992a710285e208b6ba31dc018fb4744e708aaa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 3 Aug 2003 07:20:05 +0000 Subject: Output message saying "signed connect" instead of just connect when signing is active. Jeremy. (This used to be commit c6674fa62865b64aa788a1903db118e4d773bcae) --- source3/smbd/service.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c2855487a5..f75c920069 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -691,6 +691,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); + dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); dbgtext( "initially as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); -- cgit From 99a4bb07a9a1664cd0eeb1b5de370b21fb926dc2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 3 Aug 2003 18:50:00 +0000 Subject: Fix up #defines around utmp_host and utmp_name. Noticed by Cord.Hockemeyer@uni-graz.at Jeremy. (This used to be commit 07c5ecb945c1189fd6e8628f5e989b90dd15163b) --- source3/smbd/utmp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 6ff2f586ba..d57e475ce2 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -283,8 +283,12 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) * man page appears not to specify (hints non-NULL) * A correspondent suggest at least ut_name should be NULL */ +#if defined(HAVE_UT_UT_NAME) memset((char *)&u->ut_name, '\0', sizeof(u->ut_name)); +#endif +#if defined(HAVE_UT_UT_HOST) memset((char *)&u->ut_host, '\0', sizeof(u->ut_host)); +#endif } /* Stolen from logwtmp function in libutil. * May be more locking/blocking is needed? @@ -406,7 +410,9 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) else ux.ut_syslen = 0; #endif +#if defined(HAVE_UT_UT_HOST) utmp_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)); +#endif uw_pathname(uname, "utmpx", ux_pathname); uw_pathname(wname, "wtmpx", wx_pathname); -- cgit From 74be920b0ee236d577cb357fcb34dd462300444d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 6 Aug 2003 01:14:51 +0000 Subject: Spelling. (This used to be commit 7d009ebf66c82b254828bac267102eb6e6a4a75e) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8d3e7cd9be..b12fcca4b0 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -370,7 +370,7 @@ BOOL unbecome_user(void) } /***************************************************************** - Convert the suplimentary SIDs returned in a netlogon into UNIX + Convert the supplementary SIDs returned in a netlogon into UNIX group gid_t's. Add to the total group array. *****************************************************************/ -- cgit From 110abf10d208769bf6bcfc0604874cb1bed0406a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Aug 2003 02:59:52 +0000 Subject: Turns out I had my packet sequences wrong for oplock break code. I was storing the mid of the oplock break - I should have been storing the mid from the open. There are thus 2 types of deferred packet sequence returns - ones that increment the sequence number (returns from oplock causing opens) and ones that don't (change notify returns etc). Running with signing forced on does lead to some interesting tests :-). Jeremy. (This used to be commit 85907f02cec566502d9e4adabbd414020a26064d) --- source3/smbd/blocking.c | 2 +- source3/smbd/notify.c | 2 +- source3/smbd/oplock.c | 4 ++++ source3/smbd/process.c | 11 ++++++++++- 4 files changed, 16 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index fed3a51b88..8fa2a6494e 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -148,7 +148,7 @@ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(inbuf,smb_mid), True); return True; } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9adf827c79..ca6f2b783f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -199,7 +199,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(inbuf,smb_mid), True); return True; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 19e6956d9e..49a1b7d8cf 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -743,6 +743,10 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Remember if we just sent a break to level II on this file. */ fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; + /* Ensure the reply for the open uses the correct sequence number. */ + /* This isn't a real deferred packet as it's response will also increment + * the sequence. */ + srv_defer_sign_response(get_current_mid(), False); /* Save the server smb signing state. */ sign_state = srv_oplock_set_signing(False); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dce1c4bc03..373c2f16ae 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -47,6 +47,15 @@ SIG_ATOMIC_T got_sig_term = 0; BOOL global_machine_password_needs_changing = False; extern int max_send; +/**************************************************************************** + Function to return the current request mid from Inbuffer. +****************************************************************************/ + +uint16 get_current_mid(void) +{ + return SVAL(InBuffer,smb_mid); +} + /**************************************************************************** structure to hold a linked list of queued messages. for processing. @@ -88,7 +97,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) ubi_slAddTail( list_head, msg); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(buf,smb_mid)); + srv_defer_sign_response(SVAL(buf,smb_mid), True); return True; } -- cgit From 3bbe9c0869ea8653f684afa9a1345f6fa2f80b4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Aug 2003 05:36:08 +0000 Subject: An oplock break reply from the client causes the sequence number to be updated by 2 if there is no open reply outstanding, else by one.... Yes - this makes no sense.... Jeremy. (This used to be commit b43ce1ff6109f6422a621329ceb713b42df40040) --- source3/smbd/open.c | 6 ++++++ source3/smbd/oplock.c | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5f49640aa4..2c9d3290d8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -626,6 +626,12 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + /* Ensure the reply for the open uses the correct sequence number. */ + /* This isn't a real deferred packet as it's response will also increment + * the sequence. + */ + srv_defer_sign_response(get_current_mid(), False); + /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 49a1b7d8cf..19e6956d9e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -743,10 +743,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Remember if we just sent a break to level II on this file. */ fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - /* Ensure the reply for the open uses the correct sequence number. */ - /* This isn't a real deferred packet as it's response will also increment - * the sequence. */ - srv_defer_sign_response(get_current_mid(), False); /* Save the server smb signing state. */ sign_state = srv_oplock_set_signing(False); -- cgit From a83bac7571d067b672a181942c8fea6ffbfcc33f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Aug 2003 21:47:46 +0000 Subject: Shadow copy API - Original work by "Ken Cross" , adapted into a patch by "Stefan (metze) Metzmacher" . Jeremy. (This used to be commit ce5c91d35dabc5ff6fb3df2b259ed186d6a7e0da) --- source3/smbd/nttrans.c | 171 +++++++++++++++++++++++++++++++++++++++++------- source3/smbd/vfs-wrap.c | 66 ++++++++++--------- source3/smbd/vfs.c | 2 +- 3 files changed, 186 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3ffa6efa77..7a58e83877 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1724,7 +1724,11 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count) { - unsigned fnum, control; + uint32 function; + uint16 fidnum; + files_struct *fsp; + uint8 isFSctl; + uint8 compfilter; static BOOL logged_message; char *pdata = *ppdata; @@ -1733,19 +1737,26 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - fnum = SVAL(*ppsetup, 4); - control = IVAL(*ppsetup, 0); + function = IVAL(*ppsetup, 0); + fidnum = SVAL(*ppsetup, 4); + isFSctl = CVAL(*ppsetup, 6); + compfilter = CVAL(*ppsetup, 7); + + DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", + function, fidnum, isFSctl, compfilter)); - DEBUG(10,("call_nt_transact_ioctl: fnum=%d control=0x%08x\n", - fnum, control)); + fsp=file_fsp(*ppsetup, 4); + /* this check is done in each implemented function case for now + because I don't want to break anything... --metze + FSP_BELONGS_CONN(fsp,conn);*/ - switch (control) { + switch (function) { case FSCTL_SET_SPARSE: /* pretend this succeeded - tho strictly we should mark the file sparse (if the local fs supports it) so we can know if we need to pre-allocate or not */ - DEBUG(10,("FSCTL_SET_SPARSE: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; @@ -1754,7 +1765,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou but works ok like this --metze */ - DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; @@ -1763,7 +1774,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * --metze */ - DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; @@ -1772,10 +1783,125 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * --metze */ - DEBUG(10,("FSCTL_SET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; + case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ + { + /* + * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots) + * and return their volume names. If max_data_count is 16, then it is just + * asking for the number of volumes and length of the combined names. + * + * pdata is the data allocated by our caller, but that uses + * total_data_count (which is 0 in our case) rather than max_data_count. + * Allocate the correct amount and return the pointer to let + * it be deallocated when we return. + */ + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); + SHADOW_COPY_DATA *shadow_data = NULL; + TALLOC_CTX *shadow_mem_ctx = NULL; + BOOL labels = False; + uint32 labels_data_count = 0; + uint32 i; + char *cur_pdata; + + FSP_BELONGS_CONN(fsp,conn); + + if (max_data_count < 16) { + DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n", + max_data_count)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (max_data_count > 16) { + labels = True; + } + + shadow_mem_ctx = talloc_init("SHADOW_COPY_DATA"); + if (shadow_mem_ctx == NULL) { + DEBUG(0,("talloc_init(SHADOW_COPY_DATA) failed!\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + shadow_data = (SHADOW_COPY_DATA *)talloc_zero(shadow_mem_ctx,sizeof(SHADOW_COPY_DATA)); + if (shadow_data == NULL) { + DEBUG(0,("talloc_zero() failed!\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + shadow_data->mem_ctx = shadow_mem_ctx; + + /* + * Call the VFS routine to actually do the work. + */ + if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) { + talloc_destroy(shadow_data->mem_ctx); + if (errno == ENOSYS) { + DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", + conn->connectpath)); + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } else { + DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n", + conn->connectpath)); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } + } + + labels_data_count = (shadow_data->num_volumes*2*sizeof(SHADOW_COPY_LABEL))+2; + + if (!labels) { + data_count = 16; + } else { + data_count = 12+labels_data_count+4; + } + + if (max_data_countmem_ctx); + return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); + } + + pdata = nttrans_realloc(ppdata, data_count); + if (pdata == NULL) { + talloc_destroy(shadow_data->mem_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + cur_pdata = pdata; + + /* num_volumes 4 bytes */ + SIVAL(pdata,0,shadow_data->num_volumes); + + if (labels) { + /* num_labels 4 bytes */ + SIVAL(pdata,4,shadow_data->num_volumes); + } + + /* needed_data_count 4 bytes */ + SIVAL(pdata,8,labels_data_count); + + cur_pdata+=12; + + DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n", + shadow_data->num_volumes,fsp->fsp_name)); + if (labels && shadow_data->labels) { + for (i=0;inum_volumes;i++) { + srvstr_push(outbuf, cur_pdata, shadow_data->labels[i], 2*sizeof(SHADOW_COPY_LABEL), STR_UNICODE|STR_TERMINATE); + cur_pdata+=2*sizeof(SHADOW_COPY_LABEL); + DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i])); + } + } + + talloc_destroy(shadow_data->mem_ctx); + + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); + + return -1; + } + case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */ { /* pretend this succeeded - @@ -1783,24 +1909,24 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * we have to send back a list with all files owned by this SID * * but I have to check that --metze - */ - + */ DOM_SID sid; uid_t uid; - size_t sid_len=SID_MAX_SIZE; - - DEBUG(10,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control)); + size_t sid_len = MIN(data_count-4,SID_MAX_SIZE); - /* this is not the length of the sid :-( so unknown 4 bytes */ - /*sid_len = IVAL(pdata,0); - DEBUGADD(0,("sid_len: (%u)\n",sid_len));*/ + DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum)); + + FSP_BELONGS_CONN(fsp,conn); + + /* unknown 4 bytes: this is not the length of the sid :-( */ + /*unknown = IVAL(pdata,0);*/ sid_parse(pdata+4,sid_len,&sid); - DEBUGADD(10,("SID: %s\n",sid_string_static(&sid))); + DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid))); if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) { - DEBUG(0,("sid_to_uid: failed, sid[%s]\n", - sid_string_static(&sid))); + DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%u]\n", + sid_string_static(&sid),sid_len)); uid = (-1); } @@ -1813,6 +1939,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * for each file * * but I don't know how to deal with the paged results + * (maybe we can hang the result anywhere in the fsp struct) * * we don't send all files at once * and at the next we should *not* start from the beginning, @@ -1829,7 +1956,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou if (!logged_message) { logged_message = True; /* Only print this once... */ DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", - control)); + function)); } } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 8d44a1a0fa..a76a7a6abd 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -49,6 +49,42 @@ SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *con result = sys_disk_free(path, small_query, bsize, dfree, dsize); return result; } + +int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_get_quota); + result = sys_get_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_get_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_set_quota); + result = sys_set_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_set_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels) +{ + errno = ENOSYS; + return -1; /* Not implemented. */ +} /* Directory operations */ @@ -756,36 +792,6 @@ int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct return sys_acl_free_qualifier(qualifier, tagtype); } -int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_get_quota); - result = sys_get_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_get_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_set_quota); - result = sys_set_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_set_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - /**************************************************************** Extended attribute operations. *****************************************************************/ diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5f3abe7efe..58a8a38792 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -56,6 +56,7 @@ static struct vfs_ops default_vfs = { vfswrap_disk_free, vfswrap_get_quota, vfswrap_set_quota, + vfswrap_get_shadow_copy_data, /* Directory operations */ @@ -140,7 +141,6 @@ static struct vfs_ops default_vfs = { vfswrap_setxattr, vfswrap_lsetxattr, vfswrap_fsetxattr - } }; -- cgit From c1bc3a7841890d8af470863e018721c035754999 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 9 Aug 2003 23:12:35 +0000 Subject: fix for BUG #267 (problem with supplementary groups). Use winbindd to get the group list if possible since we already know it from netsamlogon_cache.tdb. More effecient than letting libc call getgrent() to get seconary groups. Tested by Ken Cross. (This used to be commit 3c537c906f29a08e75895c8c8e3ed5c5abaaa940) --- source3/smbd/sec_ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 411ece5249..8a85792ead 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -199,7 +199,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) /* Call initgroups() to get user groups */ - if (initgroups(user,gid) == -1) { + if (winbind_initgroups(user,gid) == -1) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); if (getuid() == 0) { if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { -- cgit From 4511b334a8f68048d176dd381b9f1a3530a0a8cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Aug 2003 04:28:22 +0000 Subject: Test invalid map system, map hidden, create mask, force create mask parameters. Fix return code for Samba 4 torture tester. Jeremy. (This used to be commit c043835c878ff062cb6eede02334f9e0ebb01050) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 71312295f4..869123a1fe 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1229,7 +1229,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) return NT_STATUS_CANNOT_DELETE; } if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) - return NT_STATUS_CANNOT_DELETE; + return NT_STATUS_NO_SUCH_FILE; /* We need a better way to return NT status codes from open... */ unix_ERR_class = 0; -- cgit From df35fb074527d030a8758880b6c0f9960f4df205 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Aug 2003 04:52:11 +0000 Subject: Fix another error code return against Samba4 test suite... Don't allow a path above root. Jeremy. (This used to be commit 9bc0e4fe04c4134add428c889d316bd5ee4fb6e9) --- source3/smbd/reply.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 869123a1fe..4ea1792885 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1218,6 +1218,10 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; + /* Can't delete the root. */ + if (strequal(fname, "./..") || strequal(fname, "./../")) + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND; -- cgit From a9975acc9255f1e047f680e424607479fcca6516 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Aug 2003 00:31:23 +0000 Subject: Ensure we pass the Samba4 unlink test ! Jeremy. (This used to be commit 73aaf8094c2fed76b6650afbd8ff4f050f5e52d2) --- source3/smbd/reply.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4ea1792885..dcb07ab509 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1215,6 +1215,9 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) int access_mode; files_struct *fsp; + DEBUG(10,("can_delete: %s, dirtype = %d\n", + fname, dirtype )); + if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; @@ -1226,8 +1229,13 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) return NT_STATUS_OBJECT_NAME_NOT_FOUND; fmode = dos_mode(conn,fname,&sbuf); + + /* Can't delete a directory. */ if (fmode & aDIR) return NT_STATUS_FILE_IS_A_DIRECTORY; + else if (dirtype & aDIR) /* Asked for a directory and it isn't. */ + return NT_STATUS_OBJECT_NAME_INVALID; + if (!lp_delete_readonly(SNUM(conn))) { if (fmode & aRONLY) return NT_STATUS_CANNOT_DELETE; @@ -1333,7 +1341,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) */ if (dirptr) { - error = NT_STATUS_OBJECT_NAME_NOT_FOUND; + error = NT_STATUS_NO_SUCH_FILE; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); -- cgit From db58f5141612ed8a3d3ae03cda03cb44cd22d6de Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Aug 2003 02:31:22 +0000 Subject: More chkpth fixes from Samba4 tests. Jeremy. (This used to be commit a62cf6bf16e2f435f504e936c31992f5697a309a) --- source3/smbd/reply.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dcb07ab509..4f3c12e984 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -401,8 +401,21 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size one at a time - if a component fails it expects ERRbadpath, not ERRbadfile. */ - if(errno == ENOENT) - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + if(errno == ENOENT) { + /* + * Windows returns different error codes if + * the parent directory is valid but not the + * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND + * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND + * if the path is invalid. + */ + if (bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } else { + return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); + } + } else if (errno == ENOTDIR) + return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY); return(UNIXERROR(ERRDOS,ERRbadpath)); } -- cgit From 405135fdebd122d480130d0ce65a1536a57129f5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Aug 2003 03:28:06 +0000 Subject: Better path checking for chkpth. We now pass Samba4 chkpath and unlink. Jeremy. (This used to be commit 00a57b0953c40a0ad6780eae84b4c558e21dbcfd) --- source3/smbd/reply.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4f3c12e984..8347daf26b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -38,6 +38,21 @@ unsigned int smb_echo_count = 0; extern BOOL global_encrypted_passwords_negotiated; +/**************************************************************************** + Ensure we check the path in the same way as W2K. +****************************************************************************/ + +static NTSTATUS check_path_syntax(const char *name) +{ + while (*name == '\\') + name++; + if (strequal(name, ".")) + return NT_STATUS_OBJECT_NAME_INVALID; + else if (strequal(name, "..")) + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a special message. ****************************************************************************/ @@ -379,10 +394,16 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok = False; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + NTSTATUS status; + START_PROFILE(SMBchkpth); srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); + status = check_path_syntax(name); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); unix_convert(name,conn,0,&bad_path,&sbuf); @@ -1234,10 +1255,6 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - /* Can't delete the root. */ - if (strequal(fname, "./..") || strequal(fname, "./../")) - return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -1402,6 +1419,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); + status = check_path_syntax(name); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); DEBUG(3,("reply_unlink : %s\n",name)); -- cgit From c41fad7647c2d7e23ab7ceb6df18d9b8bbc13df4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Aug 2003 03:49:43 +0000 Subject: Query volume info level 2 fix - found by Samba4 tester. Jeremy. (This used to be commit fd86e2a38766af1cf01667c6f6248af7572b278f) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 86906fa5be..f81486b1ad 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1365,7 +1365,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf * the called hostname and the service name. */ SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 0); + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", -- cgit From bb6dff2cb1599882ed6142c3617560b6e9755841 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Aug 2003 21:07:49 +0000 Subject: In ads_verify_realm, all we use in the ADS_STRUCT is the auth.realm. So directly pass that instead of setting up and tearing down the ADS_STRUCT. Volker (This used to be commit ce5b8d2ec20fe1f4d3d1956020d88272fb84124a) --- source3/smbd/sesssetup.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 88b442215d..0b3d42302a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -149,7 +149,6 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB auth_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; - ADS_STRUCT *ads; uint8 session_key[16]; uint8 tok_id[2]; BOOL foreign = False; @@ -165,18 +164,9 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ads = ads_init_simple(); - - if (!ads) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - ads->auth.realm = strdup(lp_realm()); - - ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key); + ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); - ads_destroy(&ads); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -187,13 +177,12 @@ static int reply_spnego_kerberos(connection_struct *conn, p = strchr_m(client, '@'); if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); - ads_destroy(&ads); data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } *p = 0; - if (strcasecmp(p+1, ads->auth.realm) != 0) { + if (strcasecmp(p+1, lp_realm()) != 0) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); @@ -213,8 +202,6 @@ static int reply_spnego_kerberos(connection_struct *conn, user = smb_xstrdup(client); } - ads_destroy(&ads); - /* setup the string used by %U */ sub_set_smb_name(user); -- cgit From 4e8b36a5749f4801022617b8fec1fe5d48529fef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Aug 2003 21:16:06 +0000 Subject: Fix SMBseek and get/set position information SMBs. Works against Samba4 tester. You will need a make clean; make all after this ! Jeremy. (This used to be commit 10d90171ed58bee3e5ab6476341059b585034134) --- source3/smbd/fileio.c | 22 ++++++++++++++++++++-- source3/smbd/open.c | 3 --- source3/smbd/reply.c | 33 +++++++++------------------------ source3/smbd/trans2.c | 25 ++++++++++++++++++++++--- 4 files changed, 51 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 6be5f6af7d..6cf7014846 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -87,8 +87,11 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) * Serve from write cache if we can. */ - if(read_from_write_cache(fsp, data, pos, n)) + if(read_from_write_cache(fsp, data, pos, n)) { + fsp->pos = pos + n; + fsp->position_information = fsp->pos; return n; + } flush_write_cache(fsp, READ_FLUSH); @@ -123,6 +126,9 @@ tryagain: DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); + fsp->pos += ret; + fsp->position_information = fsp->pos; + return(ret); } @@ -145,6 +151,16 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); + if (ret != -1) { + fsp->pos += ret; + +/* Yes - this is correct - writes don't update this. JRA. */ +/* Found by Samba4 tests. */ +#if 0 + fsp->position_information = fsp->pos; +#endif + } + return ret; } @@ -244,7 +260,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if(!wcp) { DO_PROFILE_INC(writecache_direct_writes); total_written = real_write_file(fsp, data, pos, n); - if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size)) + if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size)) fsp->size = (SMB_BIG_UINT)(pos + total_written); return total_written; } @@ -252,6 +268,8 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", fsp->fsp_name, fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); + fsp->pos = pos + n; + /* * If we have active cache and it isn't contiguous then we flush. * NOTE: There is a small problem with running out of disk .... diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2c9d3290d8..06f1ddfcf2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -227,7 +227,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->size = psbuf->st_size; - fsp->pos = -1; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); @@ -1362,7 +1361,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = psbuf->st_dev; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->pos = -1; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; @@ -1425,7 +1423,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = (SMB_DEV_T)0; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->pos = -1; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8347daf26b..8df118ab16 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2308,39 +2308,25 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int switch (mode) { case 0: umode = SEEK_SET; + res = startpos; break; case 1: umode = SEEK_CUR; + res = fsp->pos + startpos; break; case 2: umode = SEEK_END; break; default: umode = SEEK_SET; + res = startpos; break; } - if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { - /* - * Check for the special case where a seek before the start - * of the file sets the offset to zero. Added in the CIFS spec, - * section 4.2.7. - */ - - if(errno == EINVAL) { - SMB_OFF_T current_pos = startpos; - - if(umode == SEEK_CUR) { - - if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) { - END_PROFILE(SMBlseek); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - current_pos += startpos; - - } else if (umode == SEEK_END) { - + if (umode == SEEK_END) { + if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { + if(errno == EINVAL) { + SMB_OFF_T current_pos = startpos; SMB_STRUCT_STAT sbuf; if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { @@ -2349,10 +2335,9 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } current_pos += sbuf.st_size; + if(current_pos < 0) + res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); } - - if(current_pos < 0) - res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); } if(res == -1) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f81486b1ad..8adac1930f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1821,9 +1821,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - + pos = fsp->position_information; delete_pending = fsp->delete_on_close; } } else { @@ -2702,6 +2700,27 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + case SMB_FILE_POSITION_INFORMATION: + { + SMB_BIG_UINT position_information; + + if (total_data < 8) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + position_information = (SMB_BIG_UINT)IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); +#endif /* LARGE_SMB_OFF_T */ + DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", + fname, (double)position_information )); + if (fsp) + fsp->position_information = position_information; + break; + } + /* * CIFS UNIX extensions. */ -- cgit From 1699fadcdb86462c0b36f0479317dc52ae8a263a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Aug 2003 23:15:02 +0000 Subject: Fix changing of attributes via setattr. Samba4 test fixes. Jeremy. (This used to be commit 97e1d5c9573513c9c9be9a709341bda54fbe44be) --- source3/smbd/reply.c | 17 +++++++++++------ source3/smbd/trans2.c | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8df118ab16..35d07d5bf7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -544,13 +544,18 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(sbuf)) - mode |= aDIR; - else - mode &= ~aDIR; + if (mode != FILE_ATTRIBUTE_NORMAL) { + if (VALID_STAT_OF_DIR(sbuf)) + mode |= aDIR; + else + mode &= ~aDIR; + + if (check_name(fname,conn)) + ok = (file_chmod(conn,fname,mode,NULL) == 0); + } else { + ok = True; + } - if (check_name(fname,conn)) - ok = (file_chmod(conn,fname,mode,NULL) == 0); if (ok) ok = set_filetime(conn,fname,mtime); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8adac1930f..efce768177 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1871,6 +1871,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, base_name = p+1; mode = dos_mode(conn,fname,&sbuf); + if (!mode) + mode = FILE_ATTRIBUTE_NORMAL; + fullpathname = fname; file_size = get_file_size(sbuf); allocation_size = get_allocation_size(fsp,&sbuf); @@ -2915,10 +2918,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); DEBUG(6,("size: %.0f ", (double)size)); - if (S_ISDIR(sbuf.st_mode)) - dosmode |= aDIR; - else - dosmode &= ~aDIR; + if (dosmode == FILE_ATTRIBUTE_NORMAL) + dosmode = 0; + + if (dosmode) { + if (S_ISDIR(sbuf.st_mode)) + dosmode |= aDIR; + else + dosmode &= ~aDIR; + } DEBUG(6,("dosmode: %x\n" , dosmode)); -- cgit From 6a0c1d0baf2f185e0a8bf739af20c54472626678 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Aug 2003 23:40:45 +0000 Subject: Fix setfileinfo level 1 - it only takes 12 bytes. Found by Samba4 torture tester. Jeremy. (This used to be commit 273ebfceb3142f485c2874f84114600d4a58c523) --- source3/smbd/trans2.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index efce768177..feb78e512f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2508,18 +2508,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, switch (info_level) { case SMB_INFO_STANDARD: { - if (total_data < l1_cbFile+4) + if (total_data < 12) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); /* access time */ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); - /* write time */ tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - - dosmode = SVAL(pdata,l1_attrFile); - size = IVAL(pdata,l1_cbFile); - break; } -- cgit From 5a8c2f5a442de7979a60a7b716801be85c2e434f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Aug 2003 23:47:12 +0000 Subject: nlink field should decrement when delete pending is set. Found by Samba4. Jeremy. (This used to be commit fbdf276e36b66e9ae65cb3f127ed80cfe9a43cac) --- source3/smbd/trans2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index feb78e512f..b1658032f3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1986,7 +1986,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,sbuf.st_nlink); + if (delete_pending & sbuf.st_nlink) + SIVAL(pdata,16,sbuf.st_nlink - 1); + else + SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,0); SCVAL(pdata,21,(mode&aDIR)?1:0); break; @@ -2044,7 +2047,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,sbuf.st_nlink); + if (delete_pending && sbuf.st_nlink) + SIVAL(pdata,16,sbuf.st_nlink - 1); + else + SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; -- cgit From 8ceb628d5c09a393d7cc4f1e4301566dc9094282 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Aug 2003 00:42:16 +0000 Subject: Ignore silently set disposition information when set on a path. Samba4 tester. Jeremy. (This used to be commit e9cef615550fc2dc4a8a84ca080f13dc39d5b292) --- source3/smbd/trans2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b1658032f3..00e182b5b0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2685,8 +2685,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (total_data < 1) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + /* Just ignore this set on a path. */ if (tran_call != TRANSACT2_SETFILEINFO) - return ERROR_DOS(ERRDOS,ERRunknownlevel); + break; if (fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadfid)); -- cgit From 87a672067de2cec9faccdbb4b99a74b78e9980f1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Aug 2003 01:22:01 +0000 Subject: Fix attribute set using setfileinfo - Samba4 found. Jeremy. (This used to be commit 309835deacea9e49a8867cc981e78e6ae3efe42b) --- source3/smbd/trans2.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 00e182b5b0..3716378b37 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2920,9 +2920,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); DEBUG(6,("size: %.0f ", (double)size)); - if (dosmode == FILE_ATTRIBUTE_NORMAL) - dosmode = 0; - if (dosmode) { if (S_ISDIR(sbuf.st_mode)) dosmode |= aDIR; -- cgit From cc865e1edc57052877ae542058d62dfd16152369 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 15 Aug 2003 01:36:35 +0000 Subject: get rid of unused call (This used to be commit 244c61b1dd52121109e6fd7c3514d1a73d1fa303) --- source3/smbd/chgpasswd.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 6bc8626d81..3ed94ef740 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -746,7 +746,6 @@ NTSTATUS pass_oem_change(char *user, uchar * ntdata, uchar * nthash) { fstring new_passwd; - const char *unix_user; SAM_ACCOUNT *sampass = NULL; NTSTATUS nt_status = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); @@ -754,17 +753,6 @@ NTSTATUS pass_oem_change(char *user, if (!NT_STATUS_IS_OK(nt_status)) return nt_status; - /* - * At this point we have the new case-sensitive plaintext - * password in the fstring new_passwd. If we wanted to synchronise - * with UNIX passwords we would call a UNIX password changing - * function here. However it would have to be done as root - * as the plaintext of the old users password is not - * available. JRA. - */ - - unix_user = pdb_get_username(sampass); - /* We've already checked the old password here.... */ become_root(); nt_status = change_oem_password(sampass, NULL, new_passwd); -- cgit From 062f89bc2833bf49f873a7fd5c2624babd702db0 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 15 Aug 2003 01:42:30 +0000 Subject: get rid of some sompiler warnings on IRIX (This used to be commit a6a39c61e8228c8b3b7552ab3c61ec3a6a639143) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a5f7a7b2ea..7fcf25d7c9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1957,7 +1957,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { become_root(); - if (change_lanman_password(hnd,pass2)) { + if (change_lanman_password(hnd,(uchar *)pass2)) { SSVAL(*rparam,0,NERR_Success); } unbecome_root(); -- cgit From c9aa836204eb722890cbd4d64248ff7ef1a50e60 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 15 Aug 2003 01:46:09 +0000 Subject: Fix memleaks. Currently I'm compiling against MIT Kerberos 1.2.8. Anthony, you said you have a heimdal installation available. Could you please compile this stuff with krb and check it with valgrind? Thanks, Volker (This used to be commit d8ab44685994b302bb46eed9001c72c194d13dc8) --- source3/smbd/sesssetup.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0b3d42302a..1435c38c99 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -171,6 +171,7 @@ static int reply_spnego_kerberos(connection_struct *conn, } data_blob_free(&auth_data); + data_blob_free(&ticket); DEBUG(3,("Ticket name is [%s]\n", client)); @@ -178,6 +179,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); data_blob_free(&ap_rep); + SAFE_FREE(client); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -186,6 +188,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); + SAFE_FREE(client); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } foreign = True; @@ -202,6 +205,8 @@ static int reply_spnego_kerberos(connection_struct *conn, user = smb_xstrdup(client); } + SAFE_FREE(client); + /* setup the string used by %U */ sub_set_smb_name(user); -- cgit From 3a052c9e0a62c1f8ddf4c2e509cff52a4d157d21 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 16 Aug 2003 02:34:03 +0000 Subject: Implemented the level 1010 NT rename level. Many fixes for Samba4 test correctness. Jeremy. (This used to be commit f57429befa43d63ed9a6e19b854e22fd4151db40) --- source3/smbd/files.c | 12 ++++ source3/smbd/nttrans.c | 18 ++---- source3/smbd/reply.c | 170 +++++++++++++++++++++++++++++++++++++++++++------ source3/smbd/trans2.c | 127 ++++++++++++++++++++++++------------ 4 files changed, 256 insertions(+), 71 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index f0fd6b7a73..186fa96d7d 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -200,6 +200,18 @@ void file_close_user(int vuid) } } +void file_dump_open_table(void) +{ + int count=0; + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next,count++) { + DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n", + count, fsp->fnum, fsp->fsp_name, fsp->fd, (unsigned long)fsp->file_id, + (unsigned int)fsp->dev, (double)fsp->inode )); + } +} + /**************************************************************************** Find a fsp given a file descriptor. ****************************************************************************/ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7a58e83877..f8bd3ae15f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -762,9 +762,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib restore_case_semantics(file_attributes); if(!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { /* @@ -838,16 +837,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if(!fsp) { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } } @@ -1279,8 +1276,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(!fsp) { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { @@ -1312,13 +1308,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(!fsp) { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 35d07d5bf7..34200b0cab 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -497,9 +497,8 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } if (!ok) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBgetatr); - return(UNIXERROR(ERRDOS,ERRbadfile)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile); } outsize = set_message(outbuf,10,0,True); @@ -560,9 +559,8 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ok = set_filetime(conn,fname,mtime); if (!ok) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBsetatr); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,0,0,True); @@ -723,9 +721,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid)); if (dptr_num < 0) { if(dptr_num == -2) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBsearch); - return (UNIXERROR(ERRDOS,ERRnofids)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids); } END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); @@ -890,9 +887,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode, oplock_request,&rmode,NULL); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBopen); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } size = sbuf.st_size; @@ -978,9 +974,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt oplock_request, &rmode,&smb_action); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBopenX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } size = sbuf.st_size; @@ -1102,9 +1097,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, ofun, unixmode, oplock_request, NULL, NULL); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBcreate); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,1,0,True); @@ -1171,9 +1165,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, close(tmpfd); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBctemp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,1,0,True); @@ -1268,8 +1261,10 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) /* Can't delete a directory. */ if (fmode & aDIR) return NT_STATUS_FILE_IS_A_DIRECTORY; +#if 0 /* JRATEST */ else if (dirtype & aDIR) /* Asked for a directory and it isn't. */ return NT_STATUS_OBJECT_NAME_INVALID; +#endif /* JRATEST */ if (!lp_delete_readonly(SNUM(conn))) { if (fmode & aRONLY) @@ -2885,7 +2880,17 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret == -1) { - NTSTATUS nterr = set_bad_path_error(errno, bad_path); + NTSTATUS nterr = NT_STATUS_OK; + if(errno == ENOENT) { + unix_ERR_class = ERRDOS; + if (bad_path) { + unix_ERR_code = ERRbadpath; + nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else { + unix_ERR_code = ERRbadfile; + nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + } if (!NT_STATUS_IS_OK(nterr)) return nterr; return map_nt_error_from_unix(errno); @@ -3080,9 +3085,8 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } if (!ok) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBrmdir); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath); } outsize = set_message(outbuf,0,0,True); @@ -3165,6 +3169,130 @@ static BOOL resolve_wildcards(const char *name1, char *name2) return(True); } +/**************************************************************************** + Ensure open files have their names updates. +****************************************************************************/ + +static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname) +{ + files_struct *fsp; + BOOL did_rename = False; + + for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", + fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode, + fsp->fsp_name, newname )); + string_set(&fsp->fsp_name, newname); + did_rename = True; + } + + if (!did_rename) + DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n", + (unsigned int)dev, (double)inode, newname )); +} + +/**************************************************************************** + Rename an open file - given an fsp. +****************************************************************************/ + +NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists) +{ + SMB_STRUCT_STAT sbuf; + BOOL bad_path = False; + pstring newname_last_component; + NTSTATUS error = NT_STATUS_OK; + BOOL dest_exists; + + ZERO_STRUCT(sbuf); + unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); + + /* Ensure newname contains a '/' */ + if(strrchr_m(newname,'/') == 0) { + pstring tmpstr; + + pstrcpy(tmpstr, "./"); + pstrcat(tmpstr, newname); + pstrcpy(newname, tmpstr); + } + + /* + * Check for special case with case preserving and not + * case sensitive. If the old last component differs from the original + * last component only by case, then we should allow + * the rename (user is trying to change the case of the + * filename). + */ + + if((case_sensitive == False) && (case_preserve == True) && + strequal(newname, fsp->fsp_name)) { + char *p; + pstring newname_modified_last_component; + + /* + * Get the last component of the modified name. + * Note that we guarantee that newname contains a '/' + * character above. + */ + p = strrchr_m(newname,'/'); + pstrcpy(newname_modified_last_component,p+1); + + if(strcsequal(newname_modified_last_component, + newname_last_component) == False) { + /* + * Replace the modified last component with + * the original. + */ + pstrcpy(p+1, newname_last_component); + } + } + + /* + * If the src and dest names are identical - including case, + * don't do the rename, just return success. + */ + + if (strcsequal(fsp->fsp_name, newname)) { + DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n", + newname)); + return NT_STATUS_OK; + } + + dest_exists = vfs_object_exist(conn,newname,NULL); + + if(!replace_if_exists && dest_exists) { + DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n", + fsp->fsp_name,newname)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + error = can_rename(newname,conn,&sbuf); + + if (dest_exists && !NT_STATUS_IS_OK(error)) { + DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", + nt_errstr(error), fsp->fsp_name,newname)); + if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION)) + error = NT_STATUS_ACCESS_DENIED; + return error; + } + + if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { + DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", + fsp->fsp_name,newname)); + rename_open_files(conn, fsp->dev, fsp->inode, newname); + return NT_STATUS_OK; + } + + if (errno == ENOTDIR || errno == EISDIR) + error = NT_STATUS_OBJECT_NAME_COLLISION; + else + error = map_nt_error_from_unix(errno); + + DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", + nt_errstr(error), fsp->fsp_name,newname)); + + return error; +} + /**************************************************************************** The guts of the rename command, split out so it may be called by the NT SMB code. @@ -3186,6 +3314,8 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO *directory = *mask = 0; + ZERO_STRUCT(sbuf1); + ZERO_STRUCT(sbuf2); rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); @@ -3326,6 +3456,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", */ if (strcsequal(directory, newname)) { + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory)); return NT_STATUS_OK; } @@ -3339,6 +3470,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); return NT_STATUS_OK; } @@ -3403,8 +3535,10 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", continue; } - if (!SMB_VFS_RENAME(conn,fname,destname)) + if (!SMB_VFS_RENAME(conn,fname,destname)) { + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); count++; + } DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } CloseDir(dirptr); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3716378b37..f56d2dff22 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-2001 + Copyright (C) Jeremy Allison 1994-2003 Copyright (C) Stefan (metze) Metzmacher 2003 Extensively modified by Andrew Tridgell, 1995 @@ -261,8 +261,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } unixmode = unix_mode(conn,open_attr | aARCH, fname); @@ -271,8 +270,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i oplock_request, &rmode,&smb_action); if (!fsp) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } size = get_file_size(sbuf); @@ -441,9 +439,9 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps } /**************************************************************************** -checks for SMB_TIME_NO_CHANGE and if not found -calls interpret_long_date + Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date. ****************************************************************************/ + time_t interpret_long_unix_date(char *p) { DEBUG(1,("interpret_long_unix_date\n")); @@ -910,8 +908,7 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", unix_convert(directory,conn,0,&bad_path,&sbuf); if(!check_name(directory,conn)) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } p = strrchr_m(directory,'/'); @@ -1716,14 +1713,22 @@ static int call_trans2setfsinfo(connection_struct *conn, * Utility function to set bad path error. ****************************************************************************/ -NTSTATUS set_bad_path_error(int err, BOOL bad_path) +int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code) { - if((err == ENOENT) && bad_path) { + DEBUG(10,("set_bad_path_error: err = %dm bad_path = %d\n", + err, (int)bad_path )); + + if(err == ENOENT) { unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + if (bad_path) { + unix_ERR_code = ERRbadpath; + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } else { + unix_ERR_code = ERRbadfile; + return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); + } } - return NT_STATUS_OK; + return UNIXERROR(def_class,def_code); } /**************************************************************************** @@ -1778,8 +1783,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if(fsp && (fsp->is_directory || fsp->fd == -1)) { @@ -1792,21 +1796,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } delete_pending = fsp->directory_delete_on_close; @@ -1840,29 +1841,26 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) return ERROR_DOS(ERRDOS,ERRunknownlevel); - DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", - fname,info_level,tran_call,total_data)); + DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n", + fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data)); p = strrchr_m(fname,'/'); if (!p) @@ -2422,8 +2420,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if (fsp && fsp->print_file) { /* @@ -2462,8 +2459,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); unix_convert(fname,conn,0,&bad_path,&sbuf); if(!check_name(fname, conn)) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } /* @@ -2472,8 +2468,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); } } @@ -2486,8 +2481,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (VALID_STAT(sbuf)) unixmode = sbuf.st_mode; - DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", - tran_call,fname,info_level,total_data)); + DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", + tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); /* Realloc the parameter and data sizes */ params = Realloc(*pparams,2); @@ -2679,12 +2674,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_FILE_DISPOSITION_INFORMATION: case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { - BOOL delete_on_close = (CVAL(pdata,0) ? True : False); + BOOL delete_on_close; NTSTATUS status; if (total_data < 1) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + delete_on_close = (CVAL(pdata,0) ? True : False); + /* Just ignore this set on a path. */ if (tran_call != TRANSACT2_SETFILEINFO) break; @@ -2905,6 +2902,55 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return(-1); } + case SMB_FILE_RENAME_INFORMATION: + { + BOOL overwrite; + uint32 root_fid; + uint32 len; + pstring newname; + pstring base_name; + char *p; + NTSTATUS status; + + if (total_data < 12) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + overwrite = (CVAL(pdata,0) ? True : False); + root_fid = IVAL(pdata,4); + len = IVAL(pdata,8); + srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0); + + /* Check the new name has no '\' characters. */ + if (strchr_m(newname, '\\') || strchr_m(newname, '/')) + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + + /* Create the base directory. */ + pstrcpy(base_name, fname); + p = strrchr_m(base_name, '/'); + if (p) + *p = '\0'; + /* Append the new name. */ + pstrcat(base_name, "/"); + pstrcat(base_name, newname); + + if (fsp) { + DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", + fsp->fnum, fsp->fsp_name, base_name )); + status = rename_internals_fsp(conn, fsp, base_name, overwrite); + } else { + DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n", + fname, newname )); + status = rename_internals(conn, fname, base_name, overwrite); + } + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); + process_pending_change_notify_queue((time_t)0); + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } default: return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -3056,8 +3102,7 @@ static int call_trans2mkdir(connection_struct *conn, if(ret < 0) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } /* Realloc the parameter and data sizes */ -- cgit From fdf78a499750a439701068c7a11a65482af2103c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Aug 2003 21:38:33 +0000 Subject: Add level 261 to search. Found using Samba4 tester. Jeremy. (This used to be commit 4ee99d1c412ecc77541c988f6795ae3cb89907b8) --- source3/smbd/trans2.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f56d2dff22..56c9de2b14 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -761,6 +761,27 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p = pdata + len; break; + case SMB_FIND_FILE_LEVEL_261: + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SOFF_T(p,0,file_size); + SOFF_T(p,8,allocation_size); + p += 16; + SIVAL(p,0,nt_extmode); + p += 4; + len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII); + SIVAL(p, 0, len); + p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; + /* CIFS UNIX Extension. */ case SMB_FIND_FILE_UNIX: @@ -893,6 +914,7 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + case SMB_FIND_FILE_LEVEL_261: break; case SMB_FIND_FILE_UNIX: if (!lp_unix_extensions()) -- cgit From 1f438cbfbfe1c4c04185c1a927b70f008ea0dea0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Aug 2003 21:54:42 +0000 Subject: Added level 262. Found by Samba4 torture tester. Jeremy. (This used to be commit 12d8863be3045efa33ece1aa17073b21aecb2e97) --- source3/smbd/trans2.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 56c9de2b14..7e46a6b6ab 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -775,6 +775,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, 0, len); + memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */ p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; @@ -782,6 +783,48 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p = pdata + len; break; + case SMB_FIND_FILE_LEVEL_262: + was_8_3 = mangle_is_8_3(fname, True); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SOFF_T(p,0,file_size); + SOFF_T(p,8,allocation_size); + p += 16; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; + SIVAL(p,0,0); p += 4; + /* Clear the short name buffer. This is + * IMPORTANT as not doing so will trigger + * a Win2k client bug. JRA. + */ + memset(p,'\0',26); + if (!was_8_3) { + pstring mangled_name; + pstrcpy(mangled_name, fname); + mangle_map(mangled_name,True,True,SNUM(conn)); + mangled_name[12] = 0; + len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); + SSVAL(p, 0, len); + } else { + SSVAL(p,0,0); + *(p+2) = 0; + } + p += 2 + 24; + memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */ + p += 10; + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + SIVAL(q,0,len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; + /* CIFS UNIX Extension. */ case SMB_FIND_FILE_UNIX: @@ -915,6 +958,7 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", case SMB_FIND_FILE_NAMES_INFO: case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: case SMB_FIND_FILE_LEVEL_261: + case SMB_FIND_FILE_LEVEL_262: break; case SMB_FIND_FILE_UNIX: if (!lp_unix_extensions()) -- cgit From c236ac83c8ba6fc8d57542bad5bb4685838948e8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 18 Aug 2003 23:48:03 +0000 Subject: Win2k never returns 'no such user' here, so when we do it, the clients freak out. Return the standard 'logon failure' instead. Andrew Bartlett (This used to be commit a83506802fd331af78d2fd6e6a5cd507b5a40ca3) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1435c38c99..242b39d8d7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -215,7 +215,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); data_blob_free(&ap_rep); - return ERROR_NT(NT_STATUS_NO_SUCH_USER); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { -- cgit From e83a8a40c89491764d0658122800e05f3f75a7cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Aug 2003 01:02:41 +0000 Subject: Don't return DOS error on SMBsearch return if using NT error codes (NT1 protocol level). Fix for Samba4 tester. Jeremy. (This used to be commit 74486ab9efbb555f830b0e5d1c88f7bf065ae039) --- source3/smbd/reply.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 34200b0cab..32b9c39aed 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -768,21 +768,23 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SearchEmpty: - if (numentries == 0 || !ok) { - SCVAL(outbuf,smb_rcls,ERRDOS); - SSVAL(outbuf,smb_err,ERRnofiles); - dptr_close(&dptr_num); - } - /* If we were called as SMBffirst with smb_search_id == NULL and no entries were found then return error and close dirptr (X/Open spec) */ if(ok && expect_close && numentries == 0 && status_len == 0) { - SCVAL(outbuf,smb_rcls,ERRDOS); - SSVAL(outbuf,smb_err,ERRnofiles); + if (Protocol < PROTOCOL_NT1) { + SCVAL(outbuf,smb_rcls,ERRDOS); + SSVAL(outbuf,smb_err,ERRnofiles); + } /* Also close the dptr - we know it's gone */ dptr_close(&dptr_num); + } else if (numentries == 0 || !ok) { + if (Protocol < PROTOCOL_NT1) { + SCVAL(outbuf,smb_rcls,ERRDOS); + SSVAL(outbuf,smb_err,ERRnofiles); + } + dptr_close(&dptr_num); } /* If we were called as SMBfunique, then we can close the dirptr now ! */ -- cgit From c0236e8ae32af5480b14ac57677dc983e786d3d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Aug 2003 01:26:43 +0000 Subject: Fix flush of 0xFFFF - found by Samba4 tester. Jeremy. (This used to be commit 8a5c97fa07eacd4cecb5afd9c197352dfa613b9f) --- source3/smbd/reply.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 32b9c39aed..9577375475 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2367,10 +2367,12 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); + uint16 fnum = SVAL(inbuf,smb_vwv0); files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBflush); - CHECK_FSP(fsp,conn); + if (fnum != 0xFFFF) + CHECK_FSP(fsp,conn); if (!fsp) { file_sync_all(conn); @@ -2737,7 +2739,7 @@ int reply_printclose(connection_struct *conn, if (!CAN_PRINT(conn)) { END_PROFILE(SMBsplclose); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } DEBUG(3,("printclose fd=%d fnum=%d\n", -- cgit From 6d6401a67a9985c8c51175db520114dc2ef421ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Aug 2003 01:53:45 +0000 Subject: Implement SMBexit properly. Found by Samba4 tester. You must do a make clean proto all; after this commit. Jeremy. (This used to be commit 27af1f9feab12542dc538bfceac4593e644ba3b4) --- source3/smbd/files.c | 16 ++++++++++++++++ source3/smbd/open.c | 4 ++++ source3/smbd/reply.c | 3 +++ 3 files changed, 23 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 186fa96d7d..1fe6f250e5 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -142,6 +142,22 @@ void file_close_conn(connection_struct *conn) } } +/**************************************************************************** + Close all open files for a pid. +****************************************************************************/ + +void file_close_pid(uint16 smbpid) +{ + files_struct *fsp, *next; + + for (fsp=Files;fsp;fsp=next) { + next = fsp->next; + if (fsp->file_pid == smbpid) { + close_file(fsp,False); + } + } +} + /**************************************************************************** Initialise file structures. ****************************************************************************/ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 06f1ddfcf2..71af23aaf9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -23,6 +23,7 @@ extern userdom_struct current_user_info; extern uint16 global_oplock_port; +extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; /**************************************************************************** @@ -226,6 +227,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; + fsp->file_pid = global_smbpid; fsp->size = psbuf->st_size; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); @@ -1361,6 +1363,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = psbuf->st_dev; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; + fsp->file_pid = global_smbpid; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; @@ -1423,6 +1426,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = (SMB_DEV_T)0; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; + fsp->file_pid = global_smbpid; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9577375475..5f2dd91232 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2394,6 +2394,9 @@ int reply_exit(connection_struct *conn, { int outsize; START_PROFILE(SMBexit); + + file_close_pid(SVAL(inbuf,smb_pid)); + outsize = set_message(outbuf,0,0,True); DEBUG(3,("exit\n")); -- cgit From 49e66508f271c5d548a045a1297652ed5b03494c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 19 Aug 2003 04:17:21 +0000 Subject: Fix BUG #314: api_netUserGetGRoups() was failing prematurely (also fixed the call to return the real groups and not a mocked up list) Fixed simple compiler warning in srv_lsa_ds.c (This used to be commit 6b0e38e01a44d87b844d973318accc456abef857) --- source3/smbd/lanman.c | 66 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7fcf25d7c9..0d5bc3a9ab 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1706,13 +1706,24 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para int uLevel = SVAL(p,0); const char *level_string; int count=0; + SAM_ACCOUNT *sampw = NULL; + BOOL ret = False; + DOM_GID *gids = NULL; + int num_groups = 0; + int i; + fstring grp_domain; + fstring grp_name; + enum SID_NAME_USE grp_type; + DOM_SID sid, dom_sid; *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); /* check it's a supported varient */ - if (!strcmp(str1,"zWrLeh")) + + if ( strcmp(str1,"zWrLeh") != 0 ) return False; + switch( uLevel ) { case 0: level_string = "B21"; @@ -1732,18 +1743,59 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para p = *rdata; - /* XXXX we need a real SAM database some day */ - pstrcpy(p,"Users"); p += 21; count++; - pstrcpy(p,"Domain Users"); p += 21; count++; - pstrcpy(p,"Guests"); p += 21; count++; - pstrcpy(p,"Domain Guests"); p += 21; count++; + /* Lookup the user information; This should only be one of + our accounts (not remote domains) */ + + pdb_init_sam( &sampw ); + + become_root(); /* ROOT BLOCK */ + + if ( !pdb_getsampwnam(sampw, UserName) ) + goto out; + /* this next set of code is horribly inefficient, but since + it is rarely called, I'm going to leave it like this since + it easier to follow --jerry */ + + /* get the list of group SIDs */ + + if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) { + DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n")); + goto out; + } + + /* convert to names (we don't support universal groups so the domain + can only be ours) */ + + sid_copy( &dom_sid, get_global_sam_sid() ); + for (i=0; i Date: Wed, 20 Aug 2003 17:13:38 +0000 Subject: metze's autogenerate patch for version.h (This used to be commit ae452e51b02672a56adf18aa7a7e365eeaba9272) --- source3/smbd/server.c | 2 +- source3/smbd/sesssetup.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 453ff54e4b..8b890549ea 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -744,7 +744,7 @@ void build_options(BOOL screen); reopen_logs(); - DEBUG(0,( "smbd version %s started.\n", VERSION)); + DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING)); DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2003\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 242b39d8d7..e7fc6254e5 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -62,7 +62,7 @@ static int add_signature(char *outbuf, char *p) char *start = p; fstring lanman; - fstr_sprintf( lanman, "Samba %s", VERSION ); + fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); -- cgit From ecddae8bf012c6b9dc4e99c788c14adde64baba8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Aug 2003 22:06:19 +0000 Subject: Attempt to fix the charcnv issues causing nmbd to crash. If we get a failed conversion simply copy as is. Also fixed the horrid malloc-twice-copy code in the convert alloc path. Jeremy. (This used to be commit cfde7477fd12caef943a9422b52174438092a135) --- source3/smbd/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 233848d2d6..88f833e468 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -64,7 +64,7 @@ static void msg_deliver(void) * Incoming message is in DOS codepage format. Convert to UNIX. */ - if ((len = convert_string_allocate(CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) { + if ((len = convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) { DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); for (i = 0; i < msgpos;) { if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { -- cgit From f474b7fb4e24b790a64178b044e6a8f7caab9a95 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Aug 2003 09:13:54 +0000 Subject: Fix memleak. (This used to be commit afbf15f94189f50cd447d9bcdebbc4886800b05a) --- source3/smbd/sesssetup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e7fc6254e5..427caa3ba1 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -165,13 +165,15 @@ static int reply_spnego_kerberos(connection_struct *conn, } ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key); + + data_blob_free(&ticket); + if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } data_blob_free(&auth_data); - data_blob_free(&ticket); DEBUG(3,("Ticket name is [%s]\n", client)); -- cgit From 399ac9a7031a5c52377832330ac36a58e8047112 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 26 Aug 2003 03:13:39 +0000 Subject: adding some debugs while tracking down a bug (This used to be commit 627ff578613b8762415cc03cbbaff68e70f96dbf) --- source3/smbd/change_trust_pw.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 2eff77b1f7..80c9fcb258 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -35,6 +35,9 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m fstring dc_name; struct cli_state *cli; + DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n", + domain)); + if (remote_machine == NULL || !strcmp(remote_machine, "*")) { /* Use the PDC *only* for this */ @@ -92,6 +95,8 @@ failed: DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", timestring(False), domain)); } + else + DEBUG(5,("change_trust_account_password: sucess!\n")); return nt_status; } -- cgit From 8df07f37a280a15e16423006e3d2cc66f03cd787 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2003 18:17:33 +0000 Subject: Remove completely unneeded malloc/free out of this codepath. Jeremy. (This used to be commit fda254169778cc3fa9c226473b5a1f95c17c99a7) --- source3/smbd/mangle_hash2.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index cdce28e1bd..27d044f56d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -201,22 +201,24 @@ static const char *cache_lookup(u32 hash) In this algorithm, mangled names use only pure ascii characters (no multi-byte) so we can avoid doing a UCS2 conversion */ -static BOOL is_mangled_component(const char *name) +static BOOL is_mangled_component(const char *name, size_t len) { - unsigned int len, i; + unsigned int i; M_DEBUG(10,("is_mangled_component %s ?\n", name)); /* check the length */ - len = strlen(name); - if (len > 12 || len < 8) return False; + if (len > 12 || len < 8) + return False; /* the best distinguishing characteristic is the ~ */ - if (name[6] != '~') return False; + if (name[6] != '~') + return False; /* check extension */ if (len > 8) { - if (name[8] != '.') return False; + if (name[8] != '.') + return False; for (i=9; name[i]; i++) { if (! FLAG_CHECK(name[i], FLAG_ASCII)) { return False; @@ -241,7 +243,7 @@ static BOOL is_mangled_component(const char *name) } } - M_DEBUG(10,("is_mangled %s -> yes\n", name)); + M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len)); return True; } @@ -267,16 +269,13 @@ static BOOL is_mangled(const char *name) M_DEBUG(10,("is_mangled %s ?\n", name)); for (s=name; (p=strchr(s, '/')); s=p+1) { - char *component = strndup(s, PTR_DIFF(p, s)); - if (is_mangled_component(component)) { - free(component); + if (is_mangled_component(s, PTR_DIFF(p, s))) { return True; } - free(component); } /* and the last part ... */ - return is_mangled_component(s); + return is_mangled_component(s,strlen(s)); } -- cgit From 9511c987df258a9c558f9ade18c5e5549c24eafb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2003 18:21:26 +0000 Subject: Fix initial debug. Jeremy. (This used to be commit bd40da06352184ed1c4bcaf3449dcdc7fdc59bbd) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 27d044f56d..ee0ef69feb 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -205,7 +205,7 @@ static BOOL is_mangled_component(const char *name, size_t len) { unsigned int i; - M_DEBUG(10,("is_mangled_component %s ?\n", name)); + M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len)); /* check the length */ if (len > 12 || len < 8) -- cgit From 46765d97fae2930836582a2590a4bfb9f2a78e9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2003 19:01:55 +0000 Subject: Check for embedded mb chars when testing for illegal characters like /. Should fix mangling for Japanese language. Jeremy. (This used to be commit a238bcc440e310a9ea7800e4fb0b4d39c1f0a0d7) --- source3/smbd/mangle_hash2.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index ee0ef69feb..9cd0438d51 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -304,7 +304,8 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) the result we need in this case. Using strlen_m would not only be slower, it would be incorrect */ len = strlen(name); - if (len > 12) return False; + if (len > 12) + return False; /* find the '.'. Note that once again we use the non-multibyte function */ @@ -448,6 +449,27 @@ static BOOL is_legal_name(const char *name) size_t numdots = 0; while (*name) { + if (((unsigned int)name[0]) > 128 && (name[1] != 0)) { + /* Possible start of mb character. */ + char mbc[2]; + /* + * We know the following will return 2 bytes. What + * we need to know was if errno was set. + * Note that if CH_UNIX is utf8 a string may be 3 + * bytes, but this is ok as mb utf8 characters don't + * contain embedded ascii bytes. We are really checking + * for mb UNIX asian characters like Japanese (SJIS) here. + * JRA. + */ + errno = 0; + convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2); + if (!errno) { + /* Was a good mb string. */ + name += 2; + continue; + } + } + if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } -- cgit From c2983f9323099019d77b9480e884707e26895c5d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 27 Aug 2003 20:52:56 +0000 Subject: Fix bug 327 (again and I think for the last time). Make sure that pam_smbpass.so will load ok. Had to move some functions around to work around dependency problems (hence the new passdb/lookup_sid.c) Also make sure that libsmbclient.a is built and installed when we support shared libraries. (This used to be commit 780055f4422f11fb0524ac1f003cdc5f317f8b19) --- source3/smbd/uid.c | 463 ----------------------------------------------------- 1 file changed, 463 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b12fcca4b0..7979ffe854 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -437,467 +437,4 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER *pptok = new_tok; } -/***************************************************************** - *THE CANONICAL* convert name to SID function. - Tries local lookup first - for local domains - then uses winbind. -*****************************************************************/ - -BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) -{ - fstring sid; - BOOL local_lookup = False; - - *name_type = SID_NAME_UNKNOWN; - - /* If we are looking up a domain user, make sure it is - for the local machine only */ - - if (strequal(global_myname(), domain)) { - local_lookup = True; - } else if (lp_server_role() == ROLE_DOMAIN_PDC || - lp_server_role() == ROLE_DOMAIN_BDC) { - if (strequal(domain, lp_workgroup())) { - local_lookup = True; - } - } - - if (local_lookup) { - if (local_lookup_name(name, psid, name_type)) { - DEBUG(10, - ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", - domain, name, sid_to_string(sid,psid), - sid_type_lookup(*name_type), (unsigned int)*name_type)); - return True; - } - } else { - /* Remote */ - if (winbind_lookup_name(domain, name, psid, name_type)) { - - DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", - domain, name, sid_to_string(sid, psid), - (unsigned int)*name_type)); - return True; - } - } - - DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n", - local_lookup ? "local" : "winbind", domain, name)); - - return False; -} - -/***************************************************************** - *THE CANONICAL* convert SID to name function. - Tries local lookup first - for local sids, then tries winbind. -*****************************************************************/ - -BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) -{ - if (!name_type) - return False; - - *name_type = SID_NAME_UNKNOWN; - - /* Check if this is our own sid. This should perhaps be done by - winbind? For the moment handle it here. */ - - if (sid->num_auths == 5) { - DOM_SID tmp_sid; - uint32 rid; - - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - - if (sid_equal(get_global_sam_sid(), &tmp_sid)) { - - return map_domain_sid_to_name(&tmp_sid, dom_name) && - local_lookup_sid(sid, name, name_type); - } - } - - if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { - fstring sid_str; - DOM_SID tmp_sid; - uint32 rid; - - DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); - - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - return map_domain_sid_to_name(&tmp_sid, dom_name) && - lookup_known_rid(&tmp_sid, rid, name, name_type); - } - return True; -} - - -/***************************************************************** - Id mapping cache. This is to avoid Winbind mappings already - seen by smbd to be queried too frequently, keeping winbindd - busy, and blocking smbd while winbindd is busy with other - stuff. Written by Michael Steffens , - modified to use linked lists by jra. -*****************************************************************/ - -#define MAX_UID_SID_CACHE_SIZE 100 -#define TURNOVER_UID_SID_CACHE_SIZE 10 -#define MAX_GID_SID_CACHE_SIZE 100 -#define TURNOVER_GID_SID_CACHE_SIZE 10 - -static size_t n_uid_sid_cache = 0; -static size_t n_gid_sid_cache = 0; - -static struct uid_sid_cache { - struct uid_sid_cache *next, *prev; - uid_t uid; - DOM_SID sid; - enum SID_NAME_USE sidtype; -} *uid_sid_cache_head; - -static struct gid_sid_cache { - struct gid_sid_cache *next, *prev; - gid_t gid; - DOM_SID sid; - enum SID_NAME_USE sidtype; -} *gid_sid_cache_head; - -/***************************************************************** - Find a SID given a uid. -*****************************************************************/ - -static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) -{ - struct uid_sid_cache *pc; - - for (pc = uid_sid_cache_head; pc; pc = pc->next) { - if (pc->uid == uid) { - fstring sid; - *psid = pc->sid; - DEBUG(3,("fetch sid from uid cache %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); - DLIST_PROMOTE(uid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Find a uid given a SID. -*****************************************************************/ - -static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid ) -{ - struct uid_sid_cache *pc; - - for (pc = uid_sid_cache_head; pc; pc = pc->next) { - if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; - *puid = pc->uid; - DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*puid, sid_to_string(sid, psid))); - DLIST_PROMOTE(uid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Store uid to SID mapping in cache. -*****************************************************************/ - -static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) -{ - struct uid_sid_cache *pc; - - if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) { - /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */ - struct uid_sid_cache *pc_next; - size_t i; - - for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next) - ; - for(; pc; pc = pc_next) { - pc_next = pc->next; - DLIST_REMOVE(uid_sid_cache_head,pc); - SAFE_FREE(pc); - n_uid_sid_cache--; - } - } - - pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache)); - if (!pc) - return; - pc->uid = uid; - sid_copy(&pc->sid, psid); - DLIST_ADD(uid_sid_cache_head, pc); - n_uid_sid_cache++; -} - -/***************************************************************** - Find a SID given a gid. -*****************************************************************/ - -static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) -{ - struct gid_sid_cache *pc; - - for (pc = gid_sid_cache_head; pc; pc = pc->next) { - if (pc->gid == gid) { - fstring sid; - *psid = pc->sid; - DEBUG(3,("fetch sid from gid cache %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); - DLIST_PROMOTE(gid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Find a gid given a SID. -*****************************************************************/ - -static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) -{ - struct gid_sid_cache *pc; - - for (pc = gid_sid_cache_head; pc; pc = pc->next) { - if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; - *pgid = pc->gid; - DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*pgid, sid_to_string(sid, psid))); - DLIST_PROMOTE(gid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Store gid to SID mapping in cache. -*****************************************************************/ -static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) -{ - struct gid_sid_cache *pc; - - if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { - /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ - struct gid_sid_cache *pc_next; - size_t i; - - for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) - ; - for(; pc; pc = pc_next) { - pc_next = pc->next; - DLIST_REMOVE(gid_sid_cache_head,pc); - SAFE_FREE(pc); - n_gid_sid_cache--; - } - } - - pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); - if (!pc) - return; - pc->gid = gid; - sid_copy(&pc->sid, psid); - DLIST_ADD(gid_sid_cache_head, pc); - n_gid_sid_cache++; -} - -/***************************************************************** - *THE CANONICAL* convert uid_t to SID function. -*****************************************************************/ - -NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) -{ - uid_t low, high; - fstring sid; - - ZERO_STRUCTP(psid); - - if (fetch_sid_from_uid_cache(psid, uid)) - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - - if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) { - if (winbind_uid_to_sid(psid, uid)) { - - DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); - - if (psid) - store_uid_sid_cache(psid, uid); - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - } - } - - if (!local_uid_to_sid(psid, uid)) { - DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid )); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); - - store_uid_sid_cache(psid, uid); - return NT_STATUS_OK; -} - -/***************************************************************** - *THE CANONICAL* convert gid_t to SID function. -*****************************************************************/ - -NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) -{ - gid_t low, high; - fstring sid; - - ZERO_STRUCTP(psid); - - if (fetch_sid_from_gid_cache(psid, gid)) - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - - if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) { - if (winbind_gid_to_sid(psid, gid)) { - - DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); - - if (psid) - store_gid_sid_cache(psid, gid); - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - } - } - - if (!local_gid_to_sid(psid, gid)) { - DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid )); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); - - store_gid_sid_cache(psid, gid); - return NT_STATUS_OK; -} - -/***************************************************************** - *THE CANONICAL* convert SID to uid function. -*****************************************************************/ - -NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) -{ - fstring dom_name, name, sid_str; - enum SID_NAME_USE name_type; - - if (fetch_uid_from_cache(puid, psid)) - return NT_STATUS_OK; - - /* if this is our SID then go straight to a local lookup */ - - if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) { - DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n", - sid_string_static(psid) )); - - if ( local_sid_to_uid(puid, psid, &name_type) ) - goto success; - - DEBUG(10,("sid_to_uid: local lookup failed\n")); - - return NT_STATUS_UNSUCCESSFUL; - } - - /* If it is not our local domain, only hope is winbindd */ - - if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) { - DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n", - sid_string_static(psid) )); - - return NT_STATUS_UNSUCCESSFUL; - } - - /* If winbindd does know the SID, ensure this is a user */ - - if (name_type != SID_NAME_USER) { - DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n", - (unsigned int)name_type )); - return NT_STATUS_INVALID_PARAMETER; - } - - /* get the uid. Has to work or else we are dead in the water */ - - if ( !winbind_sid_to_uid(puid, psid) ) { - DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", - sid_to_string(sid_str, psid) )); - return NT_STATUS_UNSUCCESSFUL; - } - -success: - DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), - (unsigned int)*puid )); - - store_uid_sid_cache(psid, *puid); - - return NT_STATUS_OK; -} -/***************************************************************** - *THE CANONICAL* convert SID to gid function. - Group mapping is used for gids that maps to Wellknown SIDs -*****************************************************************/ - -NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) -{ - fstring dom_name, name, sid_str; - enum SID_NAME_USE name_type; - - if (fetch_gid_from_cache(pgid, psid)) - return NT_STATUS_OK; - - /* - * First we must look up the name and decide if this is a group sid. - * Group mapping can deal with foreign SIDs - */ - - if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { - DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", - sid_to_string(sid_str, psid) )); - - if ( local_sid_to_gid(pgid, psid, &name_type) ) - goto success; - - DEBUG(10,("sid_to_gid: no one knows this SID\n")); - - return NT_STATUS_UNSUCCESSFUL; - } - - /* winbindd knows it; Ensure this is a group sid */ - - if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { - DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", - (unsigned int)name_type )); - - /* winbindd is running and knows about this SID. Just the wrong type. - Don't fallback to a local lookup here */ - - return NT_STATUS_INVALID_PARAMETER; - } - - /* winbindd knows it and it is a type of group; sid_to_gid must succeed - or we are dead in the water */ - - if ( !winbind_sid_to_gid(pgid, psid) ) { - DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n", - sid_to_string(sid_str, psid) )); - return NT_STATUS_UNSUCCESSFUL; - } - -success: - DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), - (unsigned int)*pgid )); - - store_gid_sid_cache(psid, *pgid); - - return NT_STATUS_OK; -} -- cgit From fcdebdae6fb69575bbe6e622b112d2e61f972898 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Aug 2003 23:57:34 +0000 Subject: Fix bug found by tridge in 2.2.x. Ensure that %U substitution is restored on next valid packet if a logon fails. This has relevence if people are using su.exe within logon scripts ! Jeremy. (This used to be commit d405a93a9d3f9a1d93bb3289b00683fba3160bbe) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 373c2f16ae..457ba8cc63 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -719,7 +719,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if(session_tag != UID_FIELD_INVALID) vuser = get_valid_user_struct(session_tag); if(vuser != NULL) - current_user_info = vuser->user; + set_current_user_info(&vuser->user); } /* does this protocol need to be run as root? */ -- cgit From 245fbf7efbc42530c81d5aac66681bb892c97557 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Sep 2003 01:12:39 +0000 Subject: Used cachegrind to track down some bottlenecks. Removed calls to clobber_region when not compiling with developer as they were hiding speed problems. Added fast path to convert_string() when dealing with ascii -> ascii, ucs2-le to ascii and ascii to ucs2-le with values <= 0x7F. This gives a speedup of 22% on my nbench tests. Next I will do this on convert_string_allocate. Jeremy. (This used to be commit ef140d15ea0d76a3e7cdcadbfd3e917c210a9411) --- source3/smbd/process.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 457ba8cc63..3c15cd1833 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1265,8 +1265,10 @@ void smbd_process(void) if ((InBuffer == NULL) || (OutBuffer == NULL)) return; +#if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); +#endif max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); @@ -1295,7 +1297,9 @@ void smbd_process(void) num_smbs = 0; /* Reset smb counter. */ } +#if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); +#endif while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) -- cgit From 3c1c2ddf9a2f7017bf683071caccb48573d4b5b7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Sep 2003 18:02:17 +0000 Subject: Fix UNIX passwd sync properly. I've finally understood the as_root parameter has bugger all to do with who you *currently* are, and everything to do with who you run the script as. Doh ! Jeremy. (This used to be commit 17a241d9f788b63fec091001cb72d34c09cf32a4) --- source3/smbd/chgpasswd.c | 99 ++++++++++++++++-------------------------------- source3/smbd/lanman.c | 63 +++++++++++++++--------------- 2 files changed, 63 insertions(+), 99 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 3ed94ef740..0009f09028 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -333,19 +333,14 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, int wstat; BOOL chstat = False; - if (pass == NULL) - { - DEBUG(0, - ("chat_with_program: user doesn't exist in the UNIX password database.\n")); + if (pass == NULL) { + DEBUG(0, ("chat_with_program: user doesn't exist in the UNIX password database.\n")); return False; } /* allocate a pseudo-terminal device */ - if ((master = findpty(&slavedev)) < 0) - { - DEBUG(3, - ("Cannot Allocate pty for password change: %s\n", - pass->pw_name)); + if ((master = findpty(&slavedev)) < 0) { + DEBUG(3, ("Cannot Allocate pty for password change: %s\n", pass->pw_name)); return (False); } @@ -356,39 +351,29 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, CatchChildLeaveStatus(); - if ((pid = sys_fork()) < 0) - { - DEBUG(3, - ("Cannot fork() child for password change: %s\n", - pass->pw_name)); + if ((pid = sys_fork()) < 0) { + DEBUG(3, ("Cannot fork() child for password change: %s\n", pass->pw_name)); close(master); CatchChild(); return (False); } /* we now have a pty */ - if (pid > 0) - { /* This is the parent process */ - if ((chstat = talktochild(master, chatsequence)) == False) - { - DEBUG(3, - ("Child failed to change password: %s\n", - pass->pw_name)); + if (pid > 0) { /* This is the parent process */ + if ((chstat = talktochild(master, chatsequence)) == False) { + DEBUG(3, ("Child failed to change password: %s\n", pass->pw_name)); kill(pid, SIGKILL); /* be sure to end this process */ } - while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) - { - if (errno == EINTR) - { + while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { + if (errno == EINTR) { errno = 0; continue; } break; } - if (wpid < 0) - { + if (wpid < 0) { DEBUG(3, ("The process is no longer waiting!\n\n")); close(master); CatchChild(); @@ -402,29 +387,21 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, close(master); - if (pid != wpid) - { - DEBUG(3, - ("We were waiting for the wrong process ID\n")); + if (pid != wpid) { + DEBUG(3, ("We were waiting for the wrong process ID\n")); return (False); } - if (WIFEXITED(wstat) == 0) - { - DEBUG(3, - ("The process exited while we were waiting\n")); + if (WIFEXITED(wstat) == 0) { + DEBUG(3, ("The process exited while we were waiting\n")); return (False); } - if (WEXITSTATUS(wstat) != 0) - { - DEBUG(3, - ("The status of the process exiting was %d\n", + if (WEXITSTATUS(wstat) != 0) { + DEBUG(3, ("The status of the process exiting was %d\n", wstat)); return (False); } - } - else - { + } else { /* CHILD */ /* @@ -438,12 +415,9 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, if (as_root) become_root(); - DEBUG(3, - ("Dochild for user %s (uid=%d,gid=%d)\n", pass->pw_name, - (int)getuid(), (int)getgid())); - chstat = - dochild(master, slavedev, pass, passwordprogram, - as_root); + DEBUG(3, ("Dochild for user %s (uid=%d,gid=%d) (as_root = %s)\n", pass->pw_name, + (int)getuid(), (int)getgid(), BOOLSTR(as_root) )); + chstat = dochild(master, slavedev, pass, passwordprogram, as_root); if (as_root) unbecome_root(); @@ -452,20 +426,16 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, * The child should never return from dochild() .... */ - DEBUG(0, - ("chat_with_program: Error: dochild() returned %d\n", - chstat)); + DEBUG(0, ("chat_with_program: Error: dochild() returned %d\n", chstat)); exit(1); } if (chstat) - DEBUG(3, - ("Password change %ssuccessful for user %s\n", + DEBUG(3, ("Password change %ssuccessful for user %s\n", (chstat ? "" : "un"), pass->pw_name)); return (chstat); } - BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { pstring passwordprogram; @@ -489,7 +459,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL oldpass = ""; } - DEBUG(3, ("Password change for user: %s\n", name)); + DEBUG(3, ("Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name)); #if DEBUG_PASSWORD DEBUG(100, ("Passwords: old=%s new=%s\n", oldpass, newpass)); @@ -519,8 +489,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL len = strlen(oldpass); for (i = 0; i < len; i++) { if (iscntrl((int)oldpass[i])) { - DEBUG(0, - ("chat_with_program: oldpass contains control characters (disallowed).\n")); + DEBUG(0, ("chat_with_program: oldpass contains control characters (disallowed).\n")); return False; } } @@ -528,8 +497,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL len = strlen(newpass); for (i = 0; i < len; i++) { if (iscntrl((int)newpass[i])) { - DEBUG(0, - ("chat_with_program: newpass contains control characters (disallowed).\n")); + DEBUG(0, ("chat_with_program: newpass contains control characters (disallowed).\n")); return False; } } @@ -556,11 +524,8 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL /* A non-PAM password change just doen't make sense without a valid local user */ - if (pass == NULL) - { - DEBUG(0, - ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", - name)); + if (pass == NULL) { + DEBUG(0, ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", name)); return False; } @@ -755,7 +720,7 @@ NTSTATUS pass_oem_change(char *user, /* We've already checked the old password here.... */ become_root(); - nt_status = change_oem_password(sampass, NULL, new_passwd); + nt_status = change_oem_password(sampass, NULL, new_passwd, True); unbecome_root(); memset(new_passwd, 0, sizeof(new_passwd)); @@ -937,7 +902,7 @@ static NTSTATUS check_oem_password(const char *user, is correct before calling. JRA. ************************************************************/ -NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd) +NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { BOOL ret; uint32 min_len; @@ -981,7 +946,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw */ if(lp_unix_password_sync() && - !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, False)) { + !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) { return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0d5bc3a9ab..b27ccc23ef 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1984,7 +1984,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { become_root(); - if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) { + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) { SSVAL(*rparam,0,NERR_Success); } unbecome_root(); @@ -2032,47 +2032,46 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - fstring user; - char *p = param + 2; - *rparam_len = 2; - *rparam = REALLOC(*rparam,*rparam_len); + fstring user; + char *p = param + 2; + *rparam_len = 2; + *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,0,NERR_badpass); - /* - * Check the parameter definition is correct. - */ - if(!strequal(param + 2, "zsT")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); - return False; - } - p = skip_string(p, 1); + /* + * Check the parameter definition is correct. + */ - if(!strequal(p, "B516B16")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); - return False; - } - p = skip_string(p,1); + if(!strequal(param + 2, "zsT")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); + return False; + } + p = skip_string(p, 1); - p += pull_ascii_fstring(user,p); + if(!strequal(p, "B516B16")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); + return False; + } + p = skip_string(p,1); + p += pull_ascii_fstring(user,p); - DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); + DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); - /* - * Pass the user through the NT -> unix user mapping - * function. - */ + /* + * Pass the user through the NT -> unix user mapping + * function. + */ - (void)map_username(user); + (void)map_username(user); - if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) - { - SSVAL(*rparam,0,NERR_Success); - } + if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) { + SSVAL(*rparam,0,NERR_Success); + } - return(True); + return(True); } /**************************************************************************** -- cgit From 5a74bdd7aaf644fc3de94b26d3c85e088211067a Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 5 Sep 2003 05:32:32 +0000 Subject: fix bug 397: use a variant of alloc_sub_basic() for string lists. (This used to be commit 62d5611df0cf86c267d7fe820822d4d019ae28bd) --- source3/smbd/password.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b988f2ec74..32c24b3d67 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -28,6 +28,9 @@ static user_struct *validated_users; static int next_vuid = VUID_OFFSET; static int num_validated_vuids; +extern userdom_struct current_user_info; + + /**************************************************************************** Check if a uid has been validated, and return an pointer to the user_struct if it has. NULL if not. vuid is biased by an offset. This allows us to @@ -296,7 +299,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (ret && lp_valid_users(snum)) { str_list_copy(&valid, lp_valid_users(snum)); - if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) { + if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { ret = user_in_list(user, (const char **)valid, groups, n_groups); } } -- cgit From 94f59f54921174fc156fade575ca114d331b1bd8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2003 19:59:55 +0000 Subject: More tuning from cachegrind. Change most trim_string() calls to trim_char(0, as that's what they do. Fix string_replace() to fast-path ascii. Jeremy. (This used to be commit f35e9a8b909d3c74be47083ccc4a4e91a14938db) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/filename.c | 4 ++-- source3/smbd/statcache.c | 7 ++++--- source3/smbd/utmp.c | 4 ++-- source3/smbd/vfs.c | 4 ++-- 5 files changed, 11 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 0009f09028..d99570ff7c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -259,7 +259,7 @@ static int expect(int master, char *issue, char *expected) /* Eat leading/trailing whitespace before match. */ pstring str; pstrcpy( str, buffer); - trim_string( str, " ", " "); + trim_char( str, ' ', ' '); if ((match = (unix_wild_match(expected, str) == 0))) timeout = 200; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ad107f9c3e..643e315c06 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -125,7 +125,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * also trim trailing /'s. */ - trim_string(name,"/","/"); + trim_char(name,'/','/'); /* * If we trimmed down to a single '\0' character @@ -164,7 +164,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(True); start = name; - while (strncmp(start,"./",2) == 0) + while (start[0] == '.' && start[1] == '/') start += 2; pstrcpy(orig_path, name); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index fbebdb240f..28915a30a0 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -66,11 +66,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat return; /* - * Don't cache trivial valid directory entries. + * Don't cache trivial valid directory entries such as . and .. */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) + if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && + ((full_orig_name[1] == '\0') || + (full_orig_name[1] == '.' && full_orig_name[1] == '\0')))) return; /* diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index d57e475ce2..a521d0113d 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -217,13 +217,13 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau /* For w-files, first look for explicit "wtmp dir" */ if (uw_name[0] == 'w') { pstrcpy(dirname,lp_wtmpdir()); - trim_string(dirname,"","/"); + trim_char(dirname,'\0','/'); } /* For u-files and non-explicit w-dir, look for "utmp dir" */ if (dirname == 0 || strlen(dirname) == 0) { pstrcpy(dirname,lp_utmpdir()); - trim_string(dirname,"","/"); + trim_char(dirname,'\0','/'); } /* If explicit directory above, use it */ diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 58a8a38792..753db4cece 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -233,10 +233,10 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) if (p) { *p = 0; module_param = p+1; - trim_string(module_param, " ", " "); + trim_char(module_param, ' ', ' '); } - trim_string(module_name, " ", " "); + trim_char(module_name, ' ', ' '); /* First, try to load the module with the new module system */ if((entry = vfs_find_backend_entry(module_name)) || -- cgit From 966b0fc7c96b1dba63fa755312a2be64e18ff471 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2003 21:30:50 +0000 Subject: More cachegrind tuning, plus fix an error message. Jeremy. (This used to be commit 8cb9ec5d533085d40fc6bfe4ca9647d80bf41ac7) --- source3/smbd/statcache.c | 8 +++++--- source3/smbd/trans2.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 28915a30a0..948173687d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -217,10 +217,10 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, /* * Don't lookup trivial valid directory entries. */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); + if((*name == '\0') || (name[0] == '.' && + ((name[1] == '\0') || + (name[1] == '.' && name[1] == '\0')))) return False; - } if (case_sensitive) { chk_name = strdup(name); @@ -248,6 +248,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, while (1) { hash_elem = hash_lookup(&stat_cache, chk_name); if(hash_elem == NULL) { + DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); /* * Didn't find it - remove last component for next try. */ @@ -277,6 +278,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } else { scp = (stat_cache_entry *)(hash_elem->value); + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path )); DO_PROFILE_INC(statcache_hits); if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7e46a6b6ab..033e76a33e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1781,7 +1781,7 @@ static int call_trans2setfsinfo(connection_struct *conn, int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code) { - DEBUG(10,("set_bad_path_error: err = %dm bad_path = %d\n", + DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n", err, (int)bad_path )); if(err == ENOENT) { -- cgit From 1c38391c704756c31c1d8d7f84f9ac6ffcaeda34 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 7 Sep 2003 16:36:13 +0000 Subject: Nobody complained on the team-list, so commit it ... This implements some kind of improved AFS support for Samba on Linux with OpenAFS 1.2.10. ./configure --with-fake-kaserver assumes that you have OpenAFS on your machine. To use this, you have to put the AFS server's KeyFile into secrets.tdb with 'net afskey'. If this is done, on each tree connect smbd creates a Kerberos V4 ticket suitable for use by the AFS client and gives it to the kernel via the AFS syscall. This is meant to be very light-weight, so I did not link in a whole lot of libraries to be more platform-independent using the ka_SetToken function call. Volker (This used to be commit 5775690ee8e17d3e98355b5147e4aed47e8dc213) --- source3/smbd/service.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f75c920069..f9f264c270 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -642,6 +642,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } } + +#ifdef WITH_FAKE_KASERVER + afs_login(user); +#endif #if CHECK_PATH_ON_TCONX /* win2000 does not check the permissions on the directory -- cgit From e56192d0cff52a6976d75e5c2b8c25f89f5879c6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 8 Sep 2003 15:24:01 +0000 Subject: make sure we substitute basic variables in read/write list (This used to be commit 52bea54d35e7fb32c7ed7b067c13afe53761affb) --- source3/smbd/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f9f264c270..70126b9e7f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -273,7 +273,7 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group str_list_copy(&list, lp_readlist(conn->service)); if (list) { - if (!str_list_substitute(list, "%S", service)) { + if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: read list substitution failed\n")); } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) @@ -283,7 +283,7 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group str_list_copy(&list, lp_writelist(conn->service)); if (list) { - if (!str_list_substitute(list, "%S", service)) { + if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: write list substitution failed\n")); } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) -- cgit From 5daacc87b514ec4fe2e50f159a6a422a85a77324 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 8 Sep 2003 20:27:28 +0000 Subject: Protect against core dump if ioctl for print job sends invalid fid. Found by Iskantharajah T . Jeremy. (This used to be commit a9f9dd71da41801c975303a385ff229788c9498a) --- source3/smbd/reply.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5f2dd91232..6ac4cffddb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -348,7 +348,6 @@ int reply_ioctl(connection_struct *conn, uint32 ioctl_code = (device << 16) + function; int replysize, outsize; char *p; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBioctl); DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); @@ -371,6 +370,11 @@ int reply_ioctl(connection_struct *conn, switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: { + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + if (!fsp) { + END_PROFILE(SMBioctl); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } SSVAL(p,0,fsp->rap_print_jobid); /* Job number */ srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII); srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); -- cgit From b5f07b9ca802747816c407e9c79bcfb4009d605f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Sep 2003 18:34:57 +0000 Subject: Fix for bug #273 - smbd crash on machine account change. Someone only half changed the code to use dc_name instead of remote machine... Found via back trace from Dariush Forouher . Jeremy. (This used to be commit 963b24ac1a721a8b0d348b578f25b1d8cb7e2124) --- source3/smbd/change_trust_pw.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 80c9fcb258..1178400e4d 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -48,22 +48,20 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m if ( !name_status_find( domain, 0x1b, 0x20, pdc_ip, dc_name) ) goto failed; - } - /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ - else { + } else { + /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ fstrcpy( dc_name, remote_machine ); } /* if this next call fails, then give up. We can't do password changes on BDC's --jerry */ - if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine, + if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), dc_name, NULL, 0, "IPC$", "IPC", "", "", - "", 0, Undefined, NULL))) - { - DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); + "", 0, Undefined, NULL))) { + DEBUG(0,("modify_trust_password: Connection to %s failed!\n", dc_name)); nt_status = NT_STATUS_UNSUCCESSFUL; goto failed; } @@ -75,7 +73,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m if(cli_nt_session_open(cli, PI_NETLOGON) == False) { DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", - remote_machine, cli_errstr(cli))); + dc_name, cli_errstr(cli))); cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); @@ -83,8 +81,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m goto failed; } - nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, - domain); + nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, domain); cli_nt_session_close(cli); cli_ulogoff(cli); -- cgit From abdc2695e21285816bbcbf829560023a36b26ee8 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 12:22:34 +0000 Subject: Fixed typo in debug. (This used to be commit e2b5dd7d9b351984c40876f3c86f2a006e0eec42) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 948173687d..76406f208e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -119,7 +119,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", + DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); SAFE_FREE(original_path); SAFE_FREE(translated_path); -- cgit From dd50c0ed68457ac8118b00e568a30ae4abf5d33b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Sep 2003 18:53:01 +0000 Subject: A *curse* upon the person who #ifdefed out the mangle debug statements by default ! This is code that really needs to be able to be looked at on a customer system if it's misbehaving ! Jeremy (This used to be commit d512650340b3d28db763d018a6b05f6edf165bf0) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 9cd0438d51..351461f11f 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -53,7 +53,7 @@ #include "includes.h" -#if 0 +#if 1 #define M_DEBUG(level, x) DEBUG(level, x) #else #define M_DEBUG(level, x) -- cgit From 9b8cbdfc2b0a601da1424784fbf02b705cc3fc8d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Sep 2003 21:19:43 +0000 Subject: Fix OOPS when dealing with mangled names reported by several users. This was my bug when removing a redundant strlen. Jerry - last showstopper I knew about. Jeremy. (This used to be commit 6e6769c20643f784d1b5023df3071a35d2e5bf89) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 351461f11f..e0efb3e41b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -219,7 +219,7 @@ static BOOL is_mangled_component(const char *name, size_t len) if (len > 8) { if (name[8] != '.') return False; - for (i=9; name[i]; i++) { + for (i=9; name[i] && i < len; i++) { if (! FLAG_CHECK(name[i], FLAG_ASCII)) { return False; } -- cgit From 273479391f0c6e008c1e01a7f3ffa2de1862b9fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Sep 2003 19:36:38 +0000 Subject: Fix coredump from Samba4 torture suite. Jeremy. (This used to be commit 9c1bab944526270d2ad79c75894c33f58f8e3845) --- source3/smbd/files.c | 2 ++ source3/smbd/nttrans.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 1fe6f250e5..80544c9a30 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -405,6 +405,8 @@ files_struct *file_fsp(char *buf, int where) if (chain_fsp) return chain_fsp; + if (!buf) + return NULL; fnum = SVAL(buf, where); for (fsp=Files;fsp;fsp=fsp->next, count++) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f8bd3ae15f..1c50744947 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1472,6 +1472,9 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, files_struct *fsp; uint32 flags; + if(setup_count < 6) + return ERROR_DOS(ERRDOS,ERRbadfunc); + fsp = file_fsp(setup,4); flags = IVAL(setup, 0); -- cgit From c716385220f5ce63fafffd4cff1e9480c5991d02 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 23 Sep 2003 14:52:21 +0000 Subject: This only touches the fake kaserver support. It adds two parameters: afs share -- this is an AFS share, do AFS magic things afs username map -- We need a way to specify the cell and possibly weird username codings for several windows domains in the afs cell Volker (This used to be commit 4a3f7a9356cd5068d9ed4fd6e2336d9bf7923fbd) --- source3/smbd/service.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 70126b9e7f..44d73b2ab2 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -644,7 +644,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #ifdef WITH_FAKE_KASERVER - afs_login(user); + if (lp_afs_share(SNUM(conn))) { + afs_login(conn); + } #endif #if CHECK_PATH_ON_TCONX -- cgit From 26e4e6208ae5f0cd4eccbef4fa97446d4f750f00 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 2003 19:28:20 +0000 Subject: Fix for valid users = %S in homes share. Jeremy. (This used to be commit c7f4e56ad5c25d477f20944e5b404ebafda9e1a8) --- source3/smbd/password.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 32c24b3d67..958ed663e6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -291,7 +291,9 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (lp_invalid_users(snum)) { str_list_copy(&invalid, lp_invalid_users(snum)); if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { - ret = !user_in_list(user, (const char **)invalid, groups, n_groups); + if ( invalid && str_list_sub_basic(invalid, current_user_info.smb_name) ) { + ret = !user_in_list(user, (const char **)invalid, groups, n_groups); + } } } if (invalid) @@ -299,8 +301,10 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (ret && lp_valid_users(snum)) { str_list_copy(&valid, lp_valid_users(snum)); - if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { - ret = user_in_list(user, (const char **)valid, groups, n_groups); + if ( valid && str_list_substitute(valid, "%S", lp_servicename(snum)) ) { + if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { + ret = user_in_list(user, (const char **)valid, groups, n_groups); + } } } if (valid) -- cgit From 05b178ab82748872bf9dc49887239ddf66ab49b2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 2003 21:03:32 +0000 Subject: Ensure %S gets expanded in read/write lists. Jeremy. (This used to be commit 7d7096fc3a899349b46691dcc30b86b04964fe52) --- source3/smbd/service.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 44d73b2ab2..e4c3890f86 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -259,23 +259,27 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } - /**************************************************************************** readonly share? ****************************************************************************/ + static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_groups) { char **list; - char *service = lp_servicename(conn->service); + const char *service = lp_servicename(conn->service); conn->read_only = lp_readonly(conn->service); - if (!service) return; + if (!service) + return; str_list_copy(&list, lp_readlist(conn->service)); if (list) { - if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { + if (!str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: read list substitution failed\n")); } + if (!str_list_substitute(list, "%S", service)) { + DEBUG(0, ("ERROR: read list service substitution failed\n")); + } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) conn->read_only = True; str_list_free(&list); @@ -283,19 +287,22 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group str_list_copy(&list, lp_writelist(conn->service)); if (list) { - if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { + if (!str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: write list substitution failed\n")); } + if (!str_list_substitute(list, "%S", service)) { + DEBUG(0, ("ERROR: write list service substitution failed\n")); + } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) conn->read_only = False; str_list_free(&list); } } - /**************************************************************************** admin user check ****************************************************************************/ + static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_groups) { /* admin user check */ -- cgit From 57c863190db9ac80529866ec6408bb03ef5e514c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 29 Sep 2003 23:35:41 +0000 Subject: Take care of condition where DOS and NT error codes must differ. Found by DOS program test by Amir Hardon . Jeremy. (This used to be commit c11a7e5846002b16d0cb2991b5a7df0636b070d5) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6ac4cffddb..303e33cc48 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -417,7 +417,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (check_name(name,conn)) { if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) if (!(ok = S_ISDIR(sbuf.st_mode))) - errno = ENOTDIR; + return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); } if (!ok) { -- cgit From c5b34aa7e6fb81068a303fb1b1d2d2b789eeda06 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 2003 00:55:22 +0000 Subject: Fix for not opening Excel 2000 files that are read-only. Needs tidying up but works for now. Jeremy. (This used to be commit 9ad9e0dfafed4558e5ab215991d9912cd44f1127) --- source3/smbd/error.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 9d0e34bf52..7eec5e25df 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -61,9 +61,6 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, eclass = unix_ERR_class; ecode = unix_ERR_code; ntstatus = unix_ERR_ntstatus; - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; } else { while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { @@ -93,6 +90,10 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, if (errno != 0) DEBUG(3,("error string = %s\n",strerror(errno))); + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; + /* * We can explicitly force 32 bit error codes even when the * parameter "nt status" is set to no by pre-setting the -- cgit From b1ca1d9134a159c4d5d15eee3012cdc49f71bdb2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 2003 17:26:42 +0000 Subject: Correct fix for excel read-only bug. Add panic for logic error in developer mode. Jeremy. (This used to be commit f00af98f379463829b1ef62d78dda0365c1d7997) --- source3/smbd/error.c | 10 +++++++--- source3/smbd/trans2.c | 3 --- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 7eec5e25df..795bf0949c 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -61,6 +61,9 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, eclass = unix_ERR_class; ecode = unix_ERR_code; ntstatus = unix_ERR_ntstatus; + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; } else { while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { @@ -90,9 +93,10 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, if (errno != 0) DEBUG(3,("error string = %s\n",strerror(errno))); - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; +#if defined(DEVELOPER) + if (unix_ERR_class != SMB_SUCCESS || unix_ERR_code != 0 || !NT_STATUS_IS_OK(unix_ERR_ntstatus)) + smb_panic("logic error in error processing"); +#endif /* * We can explicitly force 32 bit error codes even when the diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 033e76a33e..ee63220d18 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1785,12 +1785,9 @@ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint err, (int)bad_path )); if(err == ENOENT) { - unix_ERR_class = ERRDOS; if (bad_path) { - unix_ERR_code = ERRbadpath; return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } else { - unix_ERR_code = ERRbadfile; return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); } } -- cgit From cd141e33fa51058a66a56a2cbd021f5e08e216d5 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Oct 2003 15:11:24 +0000 Subject: cleaning out patch list; patch from Steve L. to change the cwd before the postexec script (This used to be commit 497e14ba19f4f637e1203d73981ea1c401a19542) --- source3/smbd/service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e4c3890f86..e5655bd9f4 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -894,6 +894,9 @@ void close_cnum(connection_struct *conn, uint16 vuid) file_close_conn(conn); dptr_closecnum(conn); + /* make sure we leave the directory available for unmount */ + vfs_ChDir(conn, "/"); + /* execute any "postexec = " line */ if (*lp_postexec(SNUM(conn)) && change_to_user(conn, vuid)) { @@ -913,8 +916,5 @@ void close_cnum(connection_struct *conn, uint16 vuid) smbrun(cmd,NULL); } - /* make sure we leave the directory available for unmount */ - vfs_ChDir(conn, "/"); - conn_free(conn); } -- cgit From f5aefbf7f84c211ee7c6aab874a4966821e4b87a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 2003 21:49:40 +0000 Subject: Fix for bug #562 (incorrect mode sum) by h-yamasaki@pd.jp.nec.com. Jeremy. (This used to be commit 7fb8a1bd3880b093a884749fc496cd702480752c) --- source3/smbd/notify_hash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 810e5079ba..ec414454f9 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -41,7 +41,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, SMB_STRUCT_STAT st; pstring full_name; char *p; - char *fname; + const char *fname; size_t remaining_len; size_t fullname_len; void *dp; @@ -115,7 +115,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_FILE)) { int i; unsigned char tmp_hash[16]; - mdfour(tmp_hash, (unsigned char *)fname, strlen(fname)); + mdfour(tmp_hash, (const unsigned char *)fname, strlen(fname)); for (i=0;i<16;i++) data->name_hash[i] ^= tmp_hash[i]; } @@ -125,7 +125,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, */ if (flags & (FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SECURITY)) - data->mode_sum = st.st_mode; + data->mode_sum += st.st_mode; } CloseDir(dp); -- cgit From 2511ee970bdaaa3d766d8a5649b2208ce31852e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Oct 2003 00:06:01 +0000 Subject: Version of patch from nick@isilon.com (Nicholas Kirsch) for bug #564. Canonicalise SMB_INFO_ALLOCATION in the same was as SMB_FS_FULL_SIZE_INFORMATION. Jeremy. (This used to be commit 166efa30d2d680d8c19529c46ace3db115b43532) --- source3/smbd/trans2.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ee63220d18..3d53387c9f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1407,17 +1407,34 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf switch (info_level) { case SMB_INFO_ALLOCATION: { - SMB_BIG_UINT dfree,dsize,bsize; + SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 18; SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); + block_size = lp_block_size(snum); + if (bsize < block_size) { + SMB_BIG_UINT factor = block_size/bsize; + bsize = block_size; + dsize /= factor; + dfree /= factor; + } + if (bsize > block_size) { + SMB_BIG_UINT factor = bsize/block_size; + bsize = block_size; + dsize *= factor; + dfree *= factor; + } + bytes_per_sector = 512; + sectors_per_unit = bsize/bytes_per_sector; + + DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \ +cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit, + (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree)); + SIVAL(pdata,l1_idFileSystem,st.st_dev); - SIVAL(pdata,l1_cSectorUnit,bsize/512); + SIVAL(pdata,l1_cSectorUnit,sectors_per_unit); SIVAL(pdata,l1_cUnit,dsize); SIVAL(pdata,l1_cUnitAvail,dfree); - SSVAL(pdata,l1_cbSector,512); - DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n", - (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize, - (unsigned int)dfree, 512)); + SSVAL(pdata,l1_cbSector,bytes_per_sector); break; } -- cgit From 52f63783bcc42cc4a1351ad9176d24a73a26c5eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Oct 2003 23:21:36 +0000 Subject: Fixup error code returns from Samba4 tester. Ensure invalid paths are validated the same way. Jeremy. (This used to be commit 6ad2f0ba27566ab3928ccbbbb3c3a64b09ca139c) --- source3/smbd/nttrans.c | 48 ++++++++++++--- source3/smbd/reply.c | 160 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 169 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1c50744947..b4e7a70088 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -522,8 +522,11 @@ static int do_ntcreate_pipe_open(connection_struct *conn, int ret; int pnum = -1; char *p = NULL; + NTSTATUS status; - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -587,6 +590,7 @@ int reply_ntcreate_and_X(connection_struct *conn, char *p = NULL; time_t c_time; BOOL extended_oplock_granted = False; + NTSTATUS status; START_PROFILE(SMBntcreateX); @@ -641,7 +645,11 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if(!dir_fsp->is_directory) { - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(status); + } /* * Check to see if this is a mac fork of some kind. @@ -681,9 +689,17 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib dir_name_len++; } - srvstr_pull_buf(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE); + srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(status); + } } else { - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBntcreateX); + return ERROR_NT(status); + } /* * Check to see if this is a mac fork of some kind. @@ -971,6 +987,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha int ret; int pnum = -1; char *p = NULL; + NTSTATUS status; /* * Ensure minimum number of parameters sent. @@ -982,6 +999,10 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha } srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); + status = check_path_syntax(fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; @@ -1158,7 +1179,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); if (create_options & FILE_OPEN_BY_FILE_ID) { - END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } @@ -1188,6 +1208,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(!dir_fsp->is_directory) { srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); + nt_status = check_path_syntax(fname); + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status); + } /* * Check to see if this is a mac fork of some kind. @@ -1217,8 +1241,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, parameter_count-53, STR_TERMINATE); + nt_status = check_path_syntax(fname); + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status); + } } else { srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); + nt_status = check_path_syntax(fname); + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status); + } /* * Check to see if this is a mac fork of some kind. @@ -1260,7 +1292,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1361,7 +1392,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,False); - END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_DISK_FULL); } } else { @@ -1517,6 +1547,10 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE); + status = check_path_syntax(new_name); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } status = rename_internals(conn, fsp->fsp_name, new_name, replace_if_exists); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 303e33cc48..2c8b768d70 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -39,20 +39,32 @@ unsigned int smb_echo_count = 0; extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** - Ensure we check the path in the same way as W2K. + Ensure we check the path in *exactly* the same way as W2K. ****************************************************************************/ -static NTSTATUS check_path_syntax(const char *name) +NTSTATUS check_path_syntax(const char *name) { - while (*name == '\\') + while (*name == '\\' || *name == '/') name++; - if (strequal(name, ".")) + if (name[0] == '.' && name[1] == '\0') return NT_STATUS_OBJECT_NAME_INVALID; - else if (strequal(name, "..")) + else if (name[0] == '.' && name[1] == '.' && + (name[2] == '\\' || name [2] == '/' || name[2] == '\0')) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; return NT_STATUS_OK; } +/**************************************************************************** + Pull a string and check the path - provide for error return. +****************************************************************************/ + +size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, int flags, NTSTATUS *err) +{ + size_t ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); + *err = check_path_syntax(dest); + return ret; +} + /**************************************************************************** Reply to a special message. ****************************************************************************/ @@ -402,11 +414,11 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBchkpth); - srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); - - status = check_path_syntax(name); - if (!NT_STATUS_IS_OK(status)) + srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBchkpth); return ERROR_NT(status); + } RESOLVE_DFSPATH(name, conn, inbuf, outbuf); @@ -416,8 +428,10 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (check_name(name,conn)) { if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) - if (!(ok = S_ISDIR(sbuf.st_mode))) + if (!(ok = S_ISDIR(sbuf.st_mode))) { + END_PROFILE(SMBchkpth); return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); + } } if (!ok) { @@ -435,13 +449,18 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size * if the path is invalid. */ if (bad_path) { + END_PROFILE(SMBchkpth); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } else { + END_PROFILE(SMBchkpth); return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); } - } else if (errno == ENOTDIR) + } else if (errno == ENOTDIR) { + END_PROFILE(SMBchkpth); return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY); + } + END_PROFILE(SMBchkpth); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -468,10 +487,16 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size time_t mtime=0; BOOL bad_path = False; char *p; + NTSTATUS status; + START_PROFILE(SMBgetatr); p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBgetatr); + return ERROR_NT(status); + } RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -537,11 +562,17 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT sbuf; BOOL bad_path = False; char *p; + NTSTATUS status; START_PROFILE(SMBsetatr); p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBsetatr); + return ERROR_NT(status); + } + unix_convert(fname,conn,0,&bad_path,&sbuf); mode = SVAL(inbuf,smb_vwv0); @@ -652,6 +683,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL expect_close = False; BOOL can_open = True; BOOL bad_path = False; + NTSTATUS nt_status; START_PROFILE(SMBsearch); *mask = *directory = *fname = 0; @@ -664,7 +696,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); + p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status); + if (!NT_STATUS_IS_OK(nt_status)) { + END_PROFILE(SMBsearch); + return ERROR_NT(nt_status); + } p++; status_len = SVAL(p, 0); p += 2; @@ -829,12 +865,17 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size char status[21]; int dptr_num= -2; char *p; + NTSTATUS err; START_PROFILE(SMBfclose); outsize = set_message(outbuf,1,0,True); p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); + p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err); + if (!NT_STATUS_IS_OK(err)) { + END_PROFILE(SMBfclose); + return ERROR_NT(err); + } p++; status_len = SVAL(p,0); p += 2; @@ -877,11 +918,16 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + NTSTATUS status; START_PROFILE(SMBopen); share_mode = SVAL(inbuf,smb_vwv0); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBopen); + return ERROR_NT(status); + } RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -954,6 +1000,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int smb_action = 0; BOOL bad_path = False; files_struct *fsp; + NTSTATUS status; START_PROFILE(SMBopenX); /* If it's an IPC, pass off the pipe handler. */ @@ -968,7 +1015,11 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBopenX); + return ERROR_NT(status); + } RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1074,12 +1125,17 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); SMB_STRUCT_STAT sbuf; + NTSTATUS status; START_PROFILE(SMBcreate); com = SVAL(inbuf,smb_com); createmode = SVAL(inbuf,smb_vwv0); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE); + srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcreate); + return ERROR_NT(status); + } RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1139,11 +1195,16 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int tmpfd; SMB_STRUCT_STAT sbuf; char *p, *s; + NTSTATUS status; START_PROFILE(SMBctemp); createmode = SVAL(inbuf,smb_vwv0); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBctemp); + return ERROR_NT(status); + } pstrcat(fname,"\\TMXXXXXX"); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1235,6 +1296,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT ret = NT_STATUS_SHARING_VIOLATION; unix_ERR_class = 0; unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; return ret; } close_file(fsp,False); @@ -1423,12 +1485,12 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dirtype = SVAL(inbuf,smb_vwv0); - srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); - - status = check_path_syntax(name); - if (!NT_STATUS_IS_OK(status)) + srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBunlink); return ERROR_NT(status); - + } + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); DEBUG(3,("reply_unlink : %s\n",name)); @@ -2921,13 +2983,19 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBmkdir); - srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBmkdir); + return ERROR_NT(status); + } RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); status = mkdir_internal(conn, directory); - if (!NT_STATUS_IS_OK(status)) + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBmkdir); return ERROR_NT(status); + } outsize = set_message(outbuf,0,0,True); @@ -3082,9 +3150,14 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL ok = False; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + NTSTATUS status; START_PROFILE(SMBrmdir); - srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBrmdir); + return ERROR_NT(status); + } RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) @@ -3579,9 +3652,17 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBmv); p = smb_buf(inbuf) + 1; - p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE); + p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBmv); + return ERROR_NT(status); + } p++; - p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBmv); + return ERROR_NT(status); + } RESOLVE_DFSPATH(name, conn, inbuf, outbuf); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); @@ -3590,6 +3671,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = rename_internals(conn, name, newname, False); if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBmv); return ERROR_NT(status); } @@ -3707,14 +3789,23 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path2 = False; BOOL rc = True; SMB_STRUCT_STAT sbuf1, sbuf2; + NTSTATUS status; START_PROFILE(SMBcopy); *directory = *mask = 0; p = smb_buf(inbuf); - p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE); + p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcopy); + return ERROR_NT(status); + } + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcopy); + return ERROR_NT(status); + } DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); @@ -3860,6 +3951,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int outsize = 0; BOOL ok = False; pstring newdir; + NTSTATUS status; START_PROFILE(pathworks_setdir); @@ -3869,7 +3961,11 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE); + srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(pathworks_setdir); + return ERROR_NT(status); + } if (strlen(newdir) == 0) { ok = True; -- cgit From 22c024157129e287a6e4bb4bc7232144c36d9604 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Oct 2003 01:46:01 +0000 Subject: Changes to allow Samba3 to pass the Samba4 RAW-READ tests. Jeremy. (This used to be commit e7565dbba696adbb0fd8cca6b86a1a7e5a655f2e) --- source3/smbd/blocking.c | 14 ++++++++------ source3/smbd/reply.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 8fa2a6494e..5c6ddbc6b7 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -91,6 +91,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, { static BOOL set_lock_msg; blocking_lock_record *blr; + BOOL my_lock_ctx = False; NTSTATUS status; if(in_chained_smb() ) { @@ -127,7 +128,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, /* Add a pending lock record for this. */ status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, lock_pid, sys_getpid(), blr->fsp->conn->cnum, - offset, count, PENDING_LOCK); + offset, count, PENDING_LOCK, &my_lock_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -302,6 +303,7 @@ static BOOL process_lockread(blocking_lock_record *blr) NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; + BOOL my_lock_ctx = False; numtoread = SVAL(inbuf,smb_vwv1); startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2); @@ -309,8 +311,7 @@ static BOOL process_lockread(blocking_lock_record *blr) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, - startpos, READ_LOCK); + status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx); if (NT_STATUS_V(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { @@ -371,13 +372,13 @@ static BOOL process_lock(blocking_lock_record *blr) NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; + BOOL my_lock_ctx = False; count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); errno = 0; - status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, - offset, WRITE_LOCK); + status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); if (NT_STATUS_IS_ERR(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { @@ -428,6 +429,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) uint16 lock_pid; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; + BOOL my_lock_ctx = False; NTSTATUS status = NT_STATUS_OK; data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); @@ -450,7 +452,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) */ errno = 0; status = do_lock_spin(fsp,conn,lock_pid,count,offset, - ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); + ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx); if (NT_STATUS_IS_ERR(status)) break; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2c8b768d70..5c1d7915c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1567,8 +1567,13 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st if (nread > 0) { ret = read_file(fsp,outbuf+4,startpos,nread); +#if 0 /* mincount appears to be ignored in a W2K server. JRA. */ if (ret < mincount) ret = 0; +#else + if (ret < nread) + ret = 0; +#endif } _smb_setlen(outbuf,ret); @@ -1668,7 +1673,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); - maxcount = MAX(mincount,maxcount); if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { SMB_OFF_T size = fsp->size; @@ -1688,8 +1692,10 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s nread = MIN(maxcount,(size - startpos)); } +#if 0 /* mincount appears to be ignored in a W2K server. JRA. */ if (nread < mincount) nread = 0; +#endif DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, (int)maxcount, (int)mincount, (int)nread ) ); @@ -1714,6 +1720,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length size_t numtoread; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + BOOL my_lock_ctx = False; START_PROFILE(SMBlockread); CHECK_FSP(fsp,conn); @@ -1733,13 +1740,21 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * protocol request that predates the read/write lock concept. * Thus instead of asking for a read lock here we need to ask * for a write lock. JRA. + * Note that the requested lock size is unaffected by max_recv. */ status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), - (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK); + (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx); if (NT_STATUS_V(status)) { - if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { +#if 0 + /* + * We used to make lockread a blocking lock. It turns out + * that this isn't on W2k. Found by the Samba 4 RAW-READ torture + * tester. JRA. + */ + + if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -1751,10 +1766,16 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length return -1; } } +#endif END_PROFILE(SMBlockread); return ERROR_NT(status); } + /* + * However the requested READ size IS affected by max_recv. Insanity.... JRA. + */ + + numtoread = MIN(numtoread,max_recv); nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) { @@ -1796,6 +1817,11 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = set_message(outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + /* + * The requested read size cannot be greater than max_recv. JRA. + */ + numtoread = MIN(numtoread,max_recv); + data = smb_buf(outbuf) + 3; if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { @@ -1863,6 +1889,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length * correct amount of data). */ + SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,smb_maxcnt); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,smb_maxcnt); @@ -1901,6 +1928,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length return(UNIXERROR(ERRDOS,ERRnoaccess)); } + SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); @@ -1993,7 +2021,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, START_PROFILE(SMBwritebraw); if (srv_is_signing_active()) { - exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed."); } CHECK_FSP(fsp,conn); @@ -2626,6 +2654,8 @@ int reply_lock(connection_struct *conn, SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + BOOL my_lock_ctx = False; + START_PROFILE(SMBlock); CHECK_FSP(fsp,conn); @@ -2638,9 +2668,9 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fd, fsp->fnum, (double)offset, (double)count)); - status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK); + status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); if (NT_STATUS_V(status)) { - if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { + if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -4140,6 +4170,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, char *data; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; BOOL err; + BOOL my_lock_ctx = False; NTSTATUS status; START_PROFILE(SMBlockingX); @@ -4260,9 +4291,9 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); fsp->fsp_name, (int)lock_timeout )); status = do_lock_spin(fsp,conn,lock_pid, count,offset, - ((locktype & 1) ? READ_LOCK : WRITE_LOCK)); + ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx); if (NT_STATUS_V(status)) { - if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { + if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it -- cgit From e74b6f41cffcb134e77edb75346af3148262401b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Oct 2003 19:01:31 +0000 Subject: At least give a message if we're returning a short read for W2K compatibility. Jeremy. (This used to be commit 84c993d9cd0bc57a8b8b9aa716af1336620e2c87) --- source3/smbd/reply.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5c1d7915c2..5c9451cf37 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1775,7 +1775,12 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * However the requested READ size IS affected by max_recv. Insanity.... JRA. */ - numtoread = MIN(numtoread,max_recv); + if (numtoread > max_recv) { + DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \ +Returning short read of maximum allowed for compatibility with Windows 2000.\n", + (unsigned int)numtoread, (unsigned int)max_recv )); + numtoread = MIN(numtoread,max_recv); + } nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) { @@ -1820,7 +1825,12 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int /* * The requested read size cannot be greater than max_recv. JRA. */ - numtoread = MIN(numtoread,max_recv); + if (numtoread > max_recv) { + DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \ +Returning short read of maximum allowed for compatibility with Windows 2000.\n", + (unsigned int)numtoread, (unsigned int)max_recv )); + numtoread = MIN(numtoread,max_recv); + } data = smb_buf(outbuf) + 3; -- cgit From 90b147022effcca1087a9963d46c250638bf8c46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Oct 2003 21:04:48 +0000 Subject: Match W2K insanty w.r.t. writelock and writeclose. Samba4 torture tester. Jeremy. (This used to be commit c682fae16a2fa18f951c69ba29b1a576f4e27d6b) --- source3/smbd/reply.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5c9451cf37..89bb5eeb94 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2159,7 +2159,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, size_t numtowrite; SMB_OFF_T startpos; char *data; - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; START_PROFILE(SMBwriteunlock); @@ -2171,7 +2171,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, + if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwriteunlock); return ERROR_DOS(ERRDOS,ERRlock); @@ -2193,11 +2193,13 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, return(UNIXERROR(ERRHRD,ERRdiskfull)); } - status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, - (SMB_BIG_UINT)startpos); - if (NT_STATUS_V(status)) { - END_PROFILE(SMBwriteunlock); - return ERROR_NT(status); + if (numtowrite) { + status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, + (SMB_BIG_UINT)startpos); + if (NT_STATUS_V(status)) { + END_PROFILE(SMBwriteunlock); + return ERROR_NT(status); + } } outsize = set_message(outbuf,1,0,True); @@ -2620,7 +2622,7 @@ int reply_writeclose(connection_struct *conn, mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { END_PROFILE(SMBwriteclose); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2629,7 +2631,16 @@ int reply_writeclose(connection_struct *conn, set_filetime(conn, fsp->fsp_name,mtime); - close_err = close_file(fsp,True); + /* + * More insanity. W2K only closes the file if writelen > 0. + * JRA. + */ + + if (numtowrite) { + DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n", + fsp->fsp_name )); + close_err = close_file(fsp,True); + } DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n", fsp->fnum, (int)numtowrite, (int)nwritten, -- cgit From e7d1e9a9b68d3bd7ad7328ed7dda6735eba025ae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Oct 2003 01:53:38 +0000 Subject: Make us pass Samba4 lock tester (with one different error message). Jeremy. (This used to be commit 7622a9dbbded8d07f976ec965adca5e92de3d2b0) --- source3/smbd/reply.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 89bb5eeb94..ec63be32b4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2691,6 +2691,8 @@ int reply_lock(connection_struct *conn, status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); if (NT_STATUS_V(status)) { +#if 0 + /* Tests using Samba4 against W2K show this call never creates a blocking lock. */ if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up @@ -2702,6 +2704,7 @@ int reply_lock(connection_struct *conn, return -1; } } +#endif END_PROFILE(SMBlock); return ERROR_NT(status); } -- cgit From 6af214dbb0bf9505483fd225b097ad695eed9361 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Oct 2003 02:02:05 +0000 Subject: Ensure cancelling a blocking lock returns the correct error message. Testing with Samba4 RAW-MUX code. Jeremy. (This used to be commit 533847c95d475921b0421ae113f52c44979939d2) --- source3/smbd/blocking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 5c6ddbc6b7..f43790bfe0 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -555,7 +555,7 @@ void remove_pending_lock_requests_by_mid(int mid) DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); -- cgit From ec890d5c0fcb0ac9b3680d3c930614c726535d0a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 14 Oct 2003 03:56:42 +0000 Subject: Enclose usage of st_blksize and st_blocks struct stat members in #ifdef HAVE_STAT_ST_BLKSIZE and #ifdef HAVE_STAT_ST_BLOCKS, respectively. Fixes bug 550 reported by Joachim Schmitz . (This used to be commit 18adfdbe0c6ed79ba8ac07956b1e7abc226556c3) --- source3/smbd/dosmode.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index aaee41b546..f88964123e 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -136,9 +136,11 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) if (S_ISDIR(sbuf->st_mode)) result = aDIR | (result & aRONLY); +#if defined (HAVE_STAT_ST_BLOCKS) && defined (HAVE_STAT_ST_BLKSIZE) if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)sbuf->st_blksize) { result |= FILE_ATTRIBUTE_SPARSE; } +#endif #ifdef S_ISLNK #if LINKS_READ_ONLY -- cgit From c19e1d51e041e298cb7241cde4c635a003a66391 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Oct 2003 00:45:17 +0000 Subject: Ensure error code path doesn't free unmalloced memory. Bug #628. Jeremy. (This used to be commit d817716519e1b2a619a46563ca44812a020a769a) --- source3/smbd/lanman.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b27ccc23ef..30934d0b3a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -522,6 +522,8 @@ static void fill_printq_info_52(connection_struct *conn, int snum, NT_PRINTER_DRIVER_INFO_LEVEL driver; NT_PRINTER_INFO_LEVEL *printer = NULL; + ZERO_STRUCT(driver); + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", lp_servicename(snum))); @@ -679,6 +681,8 @@ static int get_printerdrivernumber(int snum) NT_PRINTER_DRIVER_INFO_LEVEL driver; NT_PRINTER_INFO_LEVEL *printer = NULL; + ZERO_STRUCT(driver); + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", lp_servicename(snum))); -- cgit From 3a9510acaed2d5e28b17934a2d110998232565e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Oct 2003 18:17:44 +0000 Subject: Fix buggy data_len calculation in echo. Add paranoia debug message. Jeremy. (This used to be commit 5332af1124077f49e84836f5cedfbde98336b142) --- source3/smbd/reply.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec63be32b4..011186ba89 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2784,7 +2784,11 @@ int reply_echo(connection_struct *conn, int outsize = set_message(outbuf,1,data_len,True); START_PROFILE(SMBecho); - data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf))); + if (data_len > BUFFER_SIZE) { + DEBUG(0,("reply_echo: data_len too large.\n")); + END_PROFILE(SMBecho); + return -1; + } /* copy any incoming data back out */ if (data_len > 0) -- cgit From 450bc69ab36aff1e3011beaacced84de1a57a72a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Oct 2003 20:44:43 +0000 Subject: Tidyup wrap checking. Jeremy. (This used to be commit 41d1870a51c259f0cf17caf59928a3b38b21ea11) --- source3/smbd/ipc.c | 20 ++++++++++++++------ source3/smbd/nttrans.c | 16 ++++++++++++---- source3/smbd/trans2.c | 16 ++++++++++++---- 3 files changed, 38 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 39072f9b91..9bdd02b059 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -388,7 +388,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; - if (smb_base(inbuf)+dsoff+dscnt > inbuf + size) + if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || + (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) goto bad_param; memcpy(data,smb_base(inbuf)+dsoff,dscnt); @@ -402,8 +403,9 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int return(ERROR_DOS(ERRDOS,ERRnomem)); } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) - goto bad_param; - if (smb_base(inbuf)+psoff+pscnt > inbuf + size) + goto bad_param; + if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || + (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))); goto bad_param; memcpy(params,smb_base(inbuf)+psoff,pscnt); @@ -487,8 +489,11 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (pdisp+pcnt >= tpscnt) goto bad_param; if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) - goto bad_param; - if (smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) + goto bad_param; + if (pdisp > tpscnt) + goto bad_param; + if ((smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) || + (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) goto bad_param; if (params + pdisp < params) goto bad_param; @@ -501,7 +506,10 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int goto bad_param; if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) goto bad_param; - if (smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) + if (ddisp > tdscnt) + goto bad_param; + if ((smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) || + (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) goto bad_param; if (data + ddisp < data) goto bad_param; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b4e7a70088..19af61f190 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2463,7 +2463,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if ((parameter_offset + parameter_count < parameter_offset) || (parameter_offset + parameter_count < parameter_count)) goto bad_param; - if (smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) + if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)|| + (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) goto bad_param; memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); @@ -2473,7 +2474,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) goto bad_param; - if (smb_base(inbuf) + data_offset + data_count > inbuf + length) + if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || + (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) goto bad_param; memcpy( data, smb_base(inbuf) + data_offset, data_count); @@ -2534,7 +2536,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if ((parameter_displacement + parameter_count < parameter_displacement) || (parameter_displacement + parameter_count < parameter_count)) goto bad_param; - if (smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) + if (parameter_displacement > total_parameter_count) + goto bad_param; + if ((smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) || + (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) goto bad_param; if (parameter_displacement + params < params) goto bad_param; @@ -2548,7 +2553,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if ((data_displacement + data_count < data_displacement) || (data_displacement + data_count < data_count)) goto bad_param; - if (smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) + if (data_displacement > total_data_count) + goto bad_param; + if ((smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) || + (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) goto bad_param; if (data_displacement + data < data) goto bad_param; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3d53387c9f..0f02403184 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3497,7 +3497,8 @@ int reply_trans2(connection_struct *conn, unsigned int psoff = SVAL(inbuf, smb_psoff); if ((psoff + num_params < psoff) || (psoff + num_params < num_params)) goto bad_param; - if (smb_base(inbuf) + psoff + num_params > inbuf + length) + if ((smb_base(inbuf) + psoff + num_params > inbuf + length) || + (smb_base(inbuf) + psoff + num_params < smb_base(inbuf))) goto bad_param; memcpy( params, smb_base(inbuf) + psoff, num_params); } @@ -3505,7 +3506,8 @@ int reply_trans2(connection_struct *conn, unsigned int dsoff = SVAL(inbuf, smb_dsoff); if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data)) goto bad_param; - if (smb_base(inbuf) + dsoff + num_data > inbuf + length) + if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) || + (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf))) goto bad_param; memcpy( data, smb_base(inbuf) + dsoff, num_data); } @@ -3566,7 +3568,10 @@ int reply_trans2(connection_struct *conn, if ((param_disp + num_params < param_disp) || (param_disp + num_params < num_params)) goto bad_param; - if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) + if (param_disp > total_params) + goto bad_param; + if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) || + (smb_base(inbuf) + param_off + num_params < smb_base(inbuf))) goto bad_param; if (params + param_disp < params) goto bad_param; @@ -3579,7 +3584,10 @@ int reply_trans2(connection_struct *conn, if ((data_disp + num_data < data_disp) || (data_disp + num_data < num_data)) goto bad_param; - if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) + if (data_disp > total_data) + goto bad_param; + if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) || + (smb_base(inbuf) + data_off + num_data < smb_base(inbuf))) goto bad_param; if (data + data_disp < data) goto bad_param; -- cgit From 8c4e25a331bb9e72374202378340b2acd525adce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Oct 2003 21:19:15 +0000 Subject: Typo broke win9x logins. Jeremy. (This used to be commit 4e00cad645635af66b62c6a5568264a09cf340f3) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9bdd02b059..bc828d2e8e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -405,7 +405,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || - (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))); + (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) goto bad_param; memcpy(params,smb_base(inbuf)+psoff,pscnt); -- cgit From 3fb80f1926e1770f650bca1485c21cf5ee6b9c4f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 20 Oct 2003 16:49:45 +0000 Subject: more 2.2.x compatibility fixes - allow user looksup in the kerb5 sesssetup to fall back to 'user' instaed of failing is REA.LM\user doesn't exist. also fix include line in smb_acls.h as requested by metze (This used to be commit 62ed2598b3441b3c198872df8eb55e594332807b) --- source3/smbd/sesssetup.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 427caa3ba1..945855b832 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -198,28 +198,25 @@ static int reply_spnego_kerberos(connection_struct *conn, /* this gives a fully qualified user name (ie. with full realm). that leads to very long usernames, but what else can we do? */ - asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client); + + asprintf(&user, "%s%c%s", p+1, *lp_winbind_separator(), client); - pw = Get_Pwnam(user); - if (!pw && !foreign) { - pw = Get_Pwnam(client); - SAFE_FREE(user); - user = smb_xstrdup(client); - } - + pw = smb_getpwnam( user ); + + SAFE_FREE(user); SAFE_FREE(client); - /* setup the string used by %U */ - sub_set_smb_name(user); - - reload_services(True); - if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + /* setup the string used by %U */ + + sub_set_smb_name(pw->pw_name); + reload_services(True); + if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); data_blob_free(&ap_rep); -- cgit From 3fe18a46a33cc1c0a0ecfefc61618356d7746a15 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 17:40:58 +0000 Subject: Fix signing miss-sequence noticed by Stefan Metzmacher Jeremy. (This used to be commit 63f331564396e7a4f16dce95bb98d3b6c4b75351) --- source3/smbd/notify.c | 2 +- source3/smbd/open.c | 2 +- source3/smbd/process.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ca6f2b783f..9adf827c79 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -199,7 +199,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid), True); + srv_defer_sign_response(SVAL(inbuf,smb_mid)); return True; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 71af23aaf9..ef7ace862a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -631,7 +631,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* This isn't a real deferred packet as it's response will also increment * the sequence. */ - srv_defer_sign_response(get_current_mid(), False); + srv_defer_sign_response(get_current_mid()); /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3c15cd1833..43ffb82bd7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -97,7 +97,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) ubi_slAddTail( list_head, msg); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(buf,smb_mid), True); + srv_defer_sign_response(SVAL(buf,smb_mid)); return True; } -- cgit From f589164ed94d79161d0798296c325b81c5eadbc7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 21:19:00 +0000 Subject: Patch from Stefan Metzmacher to fix signing problems when reverse connecting back to a client for printer notify. Jeremy. (This used to be commit 06aa434c3fdb139e3f3143d19413556945cbcd4f) --- source3/smbd/blocking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index f43790bfe0..c0512d5539 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -149,7 +149,7 @@ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid), True); + srv_defer_sign_response(SVAL(inbuf,smb_mid)); return True; } -- cgit From 5114dee2716f9703f2eee07a891d77a15f4b6a82 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 23:14:41 +0000 Subject: Fix for bug #64, Win9x Nexus tools not working against Samba3.0. Missing map in errormap for ERROR_MORE_DATA -> ERRDOS, ERRmoredata. Jeremy. (This used to be commit 7eaae388b35cb3d20cdd968b00d65c88fcee5878) --- source3/smbd/ipc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index bc828d2e8e..86d982b022 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -96,7 +96,7 @@ void send_trans_reply(char *outbuf, align = ((this_lparam)%4); if (buffer_too_large) { - ERROR_NT(STATUS_BUFFER_OVERFLOW); + ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata); } set_message(outbuf,10,1+align+this_ldata+this_lparam,True); @@ -281,6 +281,14 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, subcommand = ((int)setup[0]) & 0xFFFF; if(!(p = get_rpc_pipe(pnum))) { + if (subcommand == TRANSACT_WAITNAMEDPIPEHANDLESTATE) { + /* Win9x does this call with a unicode pipe name, not a pnum. */ + /* Just return success for now... */ + DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n")); + send_trans_reply(outbuf, NULL, 0, NULL, 0, False); + return -1; + } + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); return api_no_reply(outbuf, mdrcnt); } -- cgit From bb0598faf58679a7ad26a1caab8eadb154a07ae2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Oct 2003 23:38:20 +0000 Subject: Put strcasecmp/strncasecmp on the banned list (except for needed calls in iconv.c and nsswitch/). Using them means you're not thinking about multibyte at all and I really want to discourage that. Jeremy. (This used to be commit d7e35dfb9283d560d0ed2ab231f36ed92767dace) --- source3/smbd/mangle_hash2.c | 2 +- source3/smbd/sesssetup.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index e0efb3e41b..7e7bc8c68c 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -427,7 +427,7 @@ static BOOL is_reserved_name(const char *name) for (i=0; reserved_names[i]; i++) { int len = strlen(reserved_names[i]); /* note that we match on COM1 as well as COM1.foo */ - if (strncasecmp(name, reserved_names[i], len) == 0 && + if (strnequal(name, reserved_names[i], len) && (name[len] == '.' || name[len] == 0)) { return True; } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 945855b832..314ffbb4a9 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -186,7 +186,7 @@ static int reply_spnego_kerberos(connection_struct *conn, } *p = 0; - if (strcasecmp(p+1, lp_realm()) != 0) { + if (!strequal(p+1, lp_realm())) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); -- cgit From 472df57e7b525b4e2d453a19d26800fcfb3d1aa6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Oct 2003 20:09:15 +0000 Subject: Missing UNIX -> DOS codepage conversion. Fix from Alexander Bokovoy . Jeremy. (This used to be commit 8b9b635bd2759642c25fe0cea5eefbbe5af44193) --- source3/smbd/lanman.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 30934d0b3a..3ea6ab483b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2346,15 +2346,15 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par pstring comment; uint32 servertype= lp_default_server_announce(); - pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); + push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE); if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { - for (i=0;i Date: Tue, 28 Oct 2003 00:51:21 +0000 Subject: Fix for bug #667. DFS filenames can now have arbitrary case. Jeremy. (This used to be commit 74148111e16a863d5a33511e5b15632a736d7e99) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0f02403184..5677fb9a41 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3297,7 +3297,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); - if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0) + if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0) return ERROR_DOS(ERRDOS,ERRbadfile); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); -- cgit From 2e46c7648b7297345e1f8871a0acca75a21bbbc3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Oct 2003 18:32:03 +0000 Subject: Don't log at level zero when chdir fails. Ensure correct error message is returned. Jeremy. (This used to be commit 26bfe37a10f7337acb8c5ac0e04fac7a8dddc769) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5677fb9a41..394adeeb6f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3298,7 +3298,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0) - return ERROR_DOS(ERRDOS,ERRbadfile); + return UNIXERROR(ERRDOS,ERRbadfile); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); -- cgit From 059181a169e17da053b04553cfb7151985b56b32 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Oct 2003 04:58:48 +0000 Subject: parameterise the listen backlog in smbd and make it larger by default. A backlog of 5 is way too small these days. (This used to be commit bbb92d2b0ea6bc10c71bed62924bfc95c11172a5) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8b890549ea..af39bcb757 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -250,7 +250,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); - if (listen(s, 5) == -1) { + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); close(s); return False; @@ -286,7 +286,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); - if (listen(s, 5) == -1) { + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("open_sockets_smbd: listen: %s\n", strerror(errno))); close(s); -- cgit From 231124ced9237cdbc3732a722c8f373ee760927b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Oct 2003 21:28:00 +0000 Subject: Fixes to check for wraps which could cause coredumps. Jeremy. (This used to be commit ad06edd1bb58cc5e2c38a364b1af96a933b770af) --- source3/smbd/reply.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 011186ba89..3752507493 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -669,10 +669,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size time_t date; int dirtype; int outsize = 0; - int numentries = 0; + unsigned int numentries = 0; + unsigned int maxentries = 0; BOOL finished = False; - int maxentries; - int i; char *p; BOOL ok = False; int status_len; @@ -786,6 +785,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size numentries = 0; p += DIR_STRUCT_SIZE; } else { + unsigned int i; + maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE)); + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn)))); if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) @@ -845,7 +847,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if ((! *directory) && dptr_path(dptr_num)) slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n", + DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n", smb_fn_name(CVAL(inbuf,smb_com)), mask, directory, dirtype, numentries, maxentries ) ); -- cgit From 057c031d06a4c58a6a66fc71ea8c33f9b0913a0a Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 30 Oct 2003 15:57:52 +0000 Subject: bug 696; check for an invalid fid before dereferencing the fsp pointer (This used to be commit f5229d5d62510f981bd08ad8139675b50421e042) --- source3/smbd/trans2.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 394adeeb6f..56d1aae3a2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3319,7 +3319,12 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, { char *pdata = *ppdata; files_struct *fsp = file_fsp(inbuf,smb_vwv15); + + /* check for an invalid fid before proceeding */ + if (!fsp) + return(ERROR_DOS(ERRDOS,ERRbadfid)); + if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { pdata = Realloc(*ppdata, 32); -- cgit From c8e84154af5027f1c20329597851d451764f4869 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 2 Nov 2003 17:10:12 +0000 Subject: Printf fixes for 64-bit size_t. (This used to be commit 8e2c543ebf65e24e73433f69b1c281e1558e9080) --- source3/smbd/fileio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 6cf7014846..84339c3a6f 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -707,8 +707,8 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) DO_PROFILE_INC(writecache_allocated_write_caches); allocated_write_caches++; - DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n", - fsp->fsp_name, wcp->alloc_size )); + DEBUG(10,("setup_write_cache: File %s allocated write cache size %lu\n", + fsp->fsp_name, (unsigned long)wcp->alloc_size )); return True; } @@ -725,7 +725,7 @@ void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) if (fsp->wcp->data_size != 0) { pstring msg; slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \ -on file %s with write cache size = %u\n", fsp->fsp_name, fsp->wcp->data_size ); +on file %s with write cache size = %lu\n", fsp->fsp_name, (unsigned long)fsp->wcp->data_size ); smb_panic(msg); } fsp->wcp->file_size = file_size; -- cgit From fbb8f131c2336e921677f41e9fb8bce7406f3336 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 3 Nov 2003 14:34:25 +0000 Subject: Fix more 64-bit printf warnings. (This used to be commit 23443e3aa079710221557e18158d0ddb8ff48a36) --- source3/smbd/nttrans.c | 8 ++++---- source3/smbd/oplock_linux.c | 4 ++-- source3/smbd/posix_acls.c | 2 +- source3/smbd/process.c | 2 +- source3/smbd/statcache.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 19af61f190..4093e6c135 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1956,8 +1956,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid))); if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) { - DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%u]\n", - sid_string_static(&sid),sid_len)); + DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n", + sid_string_static(&sid),(unsigned long)sid_len)); uid = (-1); } @@ -2168,7 +2168,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, sid_len = IVAL(pdata,4); if (data_count < 8+sid_len) { - DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8+sid_len)); + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long(8+sid_len))); return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -2301,7 +2301,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, sid_len = IVAL(pdata,4); if (data_count < 40+sid_len) { - DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40+sid_len)); + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data\n",data_count,(unsigned long)40+sid_len)); return ERROR_DOS(ERRDOS,ERRunknownlevel); } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index ac9cf5b8a6..5de9dd56e6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -226,8 +226,8 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i { /* Ensure that the msg length is correct. */ if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %d).\n", - msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); + DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %lu).\n", + msg_len, (unsigned long)KERNEL_OPLOCK_BREAK_MSG_LEN)); return False; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 95b45fcc99..aa1d25c483 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -460,7 +460,7 @@ static struct pai_val *load_inherited_info(files_struct *fsp) } } while (ret == -1); - DEBUG(10,("load_inherited_info: ret = %d for file %s\n", ret, fsp->fsp_name)); + DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fsp->fsp_name)); if (ret == -1) { /* No attribute or not supported. */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 43ffb82bd7..ee81404a6f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -637,7 +637,7 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len) if (ret != len) DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret )); close(fd); - DEBUG(0,("created %s len %d\n", fname, len)); + DEBUG(0,("created %s len %ul\n", fname, (unsigned long)len)); } } diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 76406f208e..d996f5e493 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -119,8 +119,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %u and [%s] %u)!\n", - original_path, original_path_length, translated_path, translated_path_length)); + DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %lu and [%s] %lu)!\n", + original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); SAFE_FREE(original_path); SAFE_FREE(translated_path); return; -- cgit From e4f1a321a4a7153d3e8adebea274c1ba0011c1b0 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 4 Nov 2003 14:59:27 +0000 Subject: Fix missing bracket in quota quote - my fault. (This used to be commit fc30b6b5473124bad9c2c30b604bc21c9de258c1) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4093e6c135..80297daaef 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2168,7 +2168,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, sid_len = IVAL(pdata,4); if (data_count < 8+sid_len) { - DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long(8+sid_len))); + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len))); return ERROR_DOS(ERRDOS,ERRunknownlevel); } -- cgit From 9c8d23e5d5da06e661fa1548eea7a1e44f5f6d3a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Nov 2003 00:16:01 +0000 Subject: Fix debug message warning. Jeremy. (This used to be commit 154793981a1b2aea2703ef4da4764a322bf90ca0) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ee81404a6f..8a90a15d29 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -637,7 +637,7 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len) if (ret != len) DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret )); close(fd); - DEBUG(0,("created %s len %ul\n", fname, (unsigned long)len)); + DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len)); } } -- cgit From d5573ccde3b5c39eb9a4637d5a9d7a95b66d86e3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Nov 2003 09:03:02 +0000 Subject: Simple rename of get_socket_addr to get_peer_addr and get_socket_name to get_peer_name. This is to get closer to the getsockname/getpeername system functions. Next step will be the %i macro for the local IP address. I still want to play %L-games in times of port 445. Volker (This used to be commit d7162122eaf5d897e5de51604e431bfbaa20e905) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index af39bcb757..89d6f92e98 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -398,7 +398,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* this is needed so that we get decent entries in smbstatus for port 445 connects */ - set_remote_machine_name(get_socket_addr(smbd_server_fd()), False); + set_remote_machine_name(get_peer_addr(smbd_server_fd()), False); /* Reset global variables in util.c so that client substitutions will be -- cgit From 7b39861342279a3ecfb4b2b854162f2ec602afbd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Nov 2003 01:47:27 +0000 Subject: Ensure we mangle names ending in '.' in hash2 mangling method. Jeremy. (This used to be commit fc2af591f5a2b08caa7389150c8cc5e298bd0ed4) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 7e7bc8c68c..8dfa84d054 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -325,7 +325,7 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) prefix_len = PTR_DIFF(dot_p, name); suffix_len = len - (prefix_len+1); - if (prefix_len > 8 || suffix_len > 3) { + if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) { return False; } -- cgit From 013a0511030729bf84f4c703dca3fa39ded5fe12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Nov 2003 02:06:41 +0000 Subject: Remove unneeded second open for filename ending in '.' now we know it's a mangled name. Added const. Fix inspired by Andrew Bartlett ideas. Jeremy. (This used to be commit 87eb336d659dfa5e92b495dd76a0f2e534931293) --- source3/smbd/open.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ef7ace862a..3807c18e78 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,7 +30,7 @@ extern BOOL global_client_failed_oplock_break; fd support routines - attempt to do a dos_open. ****************************************************************************/ -static int fd_open(struct connection_struct *conn, char *fname, +static int fd_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode) { int fd; @@ -41,13 +41,6 @@ static int fd_open(struct connection_struct *conn, char *fname, fd = SMB_VFS_OPEN(conn,fname,flags,mode); - /* Fix for files ending in '.' */ - if((fd == -1) && (errno == ENOENT) && - (strchr_m(fname,'.')==NULL)) { - pstrcat(fname,"."); - fd = SMB_VFS_OPEN(conn,fname,flags,mode); - } - DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" )); @@ -70,7 +63,7 @@ int fd_close(struct connection_struct *conn, files_struct *fsp) Check a filename for the pipe string. ****************************************************************************/ -static void check_for_pipe(char *fname) +static void check_for_pipe(const char *fname) { /* special case of pipe opens */ char s[10]; @@ -89,10 +82,9 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - const char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) + const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { extern struct current_user current_user; - pstring fname; int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -100,8 +92,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->oplock_type = NO_OPLOCK; errno = EPERM; - pstrcpy(fname,fname1); - /* Check permissions */ /* -- cgit From 2d41ca7198a5a490c45a08953d16df86f36724de Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Nov 2003 02:19:34 +0000 Subject: Group quotas patch from "Heinreichsberger, Helmut" Jeremy. (This used to be commit 06c9e9163010a1035f448f76c4084228dc95334f) --- source3/smbd/quotas.c | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 91c952aa90..46f688a219 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -94,23 +94,30 @@ typedef struct _LINUX_SMB_DISK_QUOTA { static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) { - int ret = -1; + int ret = -1; #ifdef HAVE_LINUX_XQM_H - struct fs_disk_quota D; - ZERO_STRUCT(D); - - if ((ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D))) - return ret; - - dp->bsize = (SMB_BIG_UINT)512; - dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit; - dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit; - dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit; - dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit; - dp->curinodes = (SMB_BIG_UINT)D.d_icount; - dp->curblocks = (SMB_BIG_UINT)D.d_bcount; + struct fs_disk_quota D; + + ZERO_STRUCT(D); + + ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); + + /* As XFS has group quotas, if getting the user quota fails, try getting the group instead. */ + if (ret) { + ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D); + if (ret) + return ret; + } + + dp->bsize = (SMB_BIG_UINT)512; + dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit; + dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit; + dp->curinodes = (SMB_BIG_UINT)D.d_icount; + dp->curblocks = (SMB_BIG_UINT)D.d_bcount; #endif - return ret; + return ret; } /**************************************************************************** @@ -119,7 +126,7 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) { - int ret; + int ret = 0; #ifdef LINUX_QUOTAS_1 struct dqblk D; ZERO_STRUCT(D); @@ -133,8 +140,14 @@ static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; #endif - if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D))) - return -1; + ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); + + /* Linux can have group quotas, if getting the user quota fails, try getting the group instead. */ + if (ret) { + ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D); + if (ret) + return ret; + } dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit; dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit; @@ -148,7 +161,7 @@ static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize; #endif - return 0; + return ret; } /**************************************************************************** -- cgit From d66def408ea394fe6475e87cd2405173eb7c8c8c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Nov 2003 23:01:37 +0000 Subject: Fix for rename across filesystems. Noticed by Rainer Link . Jeremy. (This used to be commit 598d9d3e5f612133e0528a1a8907745d715b61ed) --- source3/smbd/vfs-wrap.c | 100 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index a76a7a6abd..378a0a1e53 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -237,14 +237,104 @@ ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, return result; } +/********************************************************* + For rename across filesystems Patch from Warren Birnbaum + +**********************************************************/ + +static int copy_reg(const char *source, const char *dest) +{ + SMB_STRUCT_STAT source_stats; + int saved_errno; + int ifd = -1; + int ofd = -1; + + if (sys_lstat (source, &source_stats) == -1) + return -1; + + if (!S_ISREG (source_stats.st_mode)) + return -1; + + if((ifd = sys_open (source, O_RDONLY, 0)) < 0) + return -1; + + if (unlink (dest) && errno != ENOENT) + return -1; + +#ifdef O_NOFOLLOW + if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 ) +#else + if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 ) +#endif + goto err; + + if (transfer_file(ifd, ofd, (size_t)-1) == -1) + goto err; + + /* + * Try to preserve ownership. For non-root it might fail, but that's ok. + * But root probably wants to know, e.g. if NFS disallows it. + */ + + if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) + goto err; + + /* + * fchown turns off set[ug]id bits for non-root, + * so do the chmod last. + */ + +#if defined(HAVE_FCHMOD) + if (fchmod (ofd, source_stats.st_mode & 07777)) +#else + if (chmod (dest, source_stats.st_mode & 07777)) +#endif + goto err; + + if (close (ifd) == -1) + goto err; + + if (close (ofd) == -1) + return -1; + + /* Try to copy the old file's modtime and access time. */ + { + struct utimbuf tv; + + tv.actime = source_stats.st_atime; + tv.modtime = source_stats.st_mtime; + utime(dest, &tv); + } + + if (unlink (source) == -1) + return -1; + + return 0; + + err: + + saved_errno = errno; + if (ifd != -1) + close(ifd); + if (ofd != -1) + close(ofd); + errno = saved_errno; + return -1; +} + int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new) { - int result; + int result; - START_PROFILE(syscall_rename); - result = rename(old, new); - END_PROFILE(syscall_rename); - return result; + START_PROFILE(syscall_rename); + result = rename(old, new); + if (errno == EXDEV) { + /* Rename across filesystems needed. */ + result = copy_reg(old, new); + } + + END_PROFILE(syscall_rename); + return result; } int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) -- cgit From fcbfc7ad0669009957c65fa61bb20df75a9701b4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 22 Nov 2003 13:19:38 +0000 Subject: Changes all over the shop, but all towards: - NTLM2 support in the server - KEY_EXCH support in the server - variable length session keys. In detail: - NTLM2 is an extension of NTLMv1, that is compatible with existing domain controllers (unlike NTLMv2, which requires a DC upgrade). * This is known as 'NTLMv2 session security' * (This is not yet implemented on the RPC pipes however, so there may well still be issues for PDC setups, particuarly around password changes. We do not fully understand the sign/seal implications of NTLM2 on RPC pipes.) This requires modifications to our authentication subsystem, as we must handle the 'challege' input into the challenge-response algorithm being changed. This also needs to be turned off for 'security=server', which does not support this. - KEY_EXCH is another 'security' mechanism, whereby the session key actually used by the server is sent by the client, rather than being the shared-secret directly or indirectly. - As both these methods change the session key, the auth subsystem needed to be changed, to 'override' session keys provided by the backend. - There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation. - The 'names blob' in NTLMSSP is always in unicode - never in ascii. Don't make an ascii version ever. - The other big change is to allow variable length session keys. We have always assumed that session keys are 16 bytes long - and padded to this length if shorter. However, Kerberos session keys are 8 bytes long, when the krb5 login uses DES. * This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. * - Add better DEBUG() messages to ntlm_auth, warning administrators of misconfigurations that prevent access to the privileged pipe. This should help reduce some of the 'it just doesn't work' issues. - Fix data_blob_talloc() to behave the same way data_blob() does when passed a NULL data pointer. (just allocate) REMEMBER to make clean after this commit - I have changed plenty of data structures... (This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc) --- source3/smbd/password.c | 23 +++++++++++++++++++---- source3/smbd/sesssetup.c | 32 +++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 958ed663e6..494d9ecd43 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -77,6 +77,8 @@ void invalidate_vuid(uint16 vuid) free_server_info(&vuser->server_info); + data_blob_free(&vuser->session_key); + DLIST_REMOVE(validated_users, vuser); /* clear the vuid from the 'cache' on each connection, and @@ -109,25 +111,36 @@ void invalidate_all_vuids(void) * @param server_info The token returned from the authentication process. * (now 'owned' by register_vuid) * + * @param session_key The User session key for the login session (now also 'owned' by register_vuid) + * + * @param respose_blob The NT challenge-response, if available. (May be freed after this call) + * + * @param smb_name The untranslated name of the user + * * @return Newly allocated vuid, biased by an offset. (This allows us to * tell random client vuid's (normally zero) from valid vuids.) * */ -int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name) +int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name) { user_struct *vuser = NULL; /* Ensure no vuid gets registered in share level security. */ - if(lp_security() == SEC_SHARE) + if(lp_security() == SEC_SHARE) { + data_blob_free(&session_key); return UID_FIELD_INVALID; + } /* Limit allowed vuids to 16bits - VUID_OFFSET. */ - if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) + if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) { + data_blob_free(&session_key); return UID_FIELD_INVALID; + } if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) { DEBUG(0,("Failed to malloc users struct!\n")); + data_blob_free(&session_key); return UID_FIELD_INVALID; } @@ -156,6 +169,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob if (vuser->n_groups) { if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { DEBUG(0,("register_vuid: failed to memdup vuser->groups\n")); + data_blob_free(&session_key); free(vuser); free_server_info(&server_info); return UID_FIELD_INVALID; @@ -197,7 +211,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob } } - memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key)); + vuser->session_key = session_key; DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->uid, @@ -211,6 +225,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob } else { DEBUG(1, ("server_info does not contain a user_token - cannot continue\n")); free_server_info(&server_info); + data_blob_free(&session_key); SAFE_FREE(vuser->homedir); SAFE_FREE(vuser->unix_homedir); SAFE_FREE(vuser->logon_script); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 314ffbb4a9..64c25db2ab 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -149,7 +149,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB auth_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; - uint8 session_key[16]; + DATA_BLOB session_key; uint8 tok_id[2]; BOOL foreign = False; DATA_BLOB nullblob = data_blob(NULL, 0); @@ -164,7 +164,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key); + ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key); data_blob_free(&ticket); @@ -223,11 +223,8 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(ret); } - /* Copy out the session key from the AP_REQ. */ - memcpy(server_info->session_key, session_key, sizeof(session_key)); - /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, nullblob, user); + sess_vuid = register_vuid(server_info, session_key, nullblob, user); free(user); @@ -297,9 +294,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; DATA_BLOB nullblob = data_blob(NULL, 0); + DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); + sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); (*auth_ntlmssp_state)->server_info = NULL; if (sess_vuid == -1) { @@ -566,6 +564,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, NTSTATUS nt_status; BOOL doencrypt = global_encrypted_passwords_negotiated; + + DATA_BLOB session_key; START_PROFILE(SMBsesssetupX); @@ -766,18 +766,28 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, free_user_info(&user_info); - data_blob_free(&lm_resp); - data_blob_clear_free(&plaintext_password); - if (!NT_STATUS_IS_OK(nt_status)) { nt_status = do_map_to_guest(nt_status, &server_info, user, domain); } if (!NT_STATUS_IS_OK(nt_status)) { data_blob_free(&nt_resp); + data_blob_free(&lm_resp); + data_blob_clear_free(&plaintext_password); return ERROR_NT(nt_status_squash(nt_status)); } + if (server_info->nt_session_key.data) { + session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length); + } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) { + session_key = data_blob(NULL, 16); + SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data, + session_key.data); + } + + data_blob_free(&lm_resp); + data_blob_clear_free(&plaintext_password); + /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { @@ -795,7 +805,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, to a uid can get through without a password, on the same VC */ /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, nt_resp, sub_user); + sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user); data_blob_free(&nt_resp); if (sess_vuid == -1) { -- cgit From c39f5fea4ad7b57ee8ad4d2b115163f76753f853 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 24 Nov 2003 17:31:38 +0000 Subject: more access fixes for group enumeration in LDAP; bug 281 (This used to be commit 68283407e0f366d8315f4be6caed67eb6fe84b85) --- source3/smbd/lanman.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3ea6ab483b..c53889a7a4 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1635,6 +1635,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); + BOOL ret; GROUP_MAP *group_list; int num_entries; @@ -1653,8 +1654,12 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c return False; /* get list of domain groups SID_DOMAIN_GRP=2 */ - if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False)) { - DEBUG(3,("api_RNetGroupEnum:failed to get group list")); + become_root(); + ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False); + unbecome_root(); + + if( !ret ) { + DEBUG(3,("api_RNetGroupEnum:failed to get group list")); return False; } -- cgit From 73034f91166ca6ebb1bf11532eb2a99b95967636 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Nov 2003 20:18:47 +0000 Subject: Added "passwd chat timeout" parameter. Docs to follow. Jeremy. (This used to be commit 16097f2072085432f4c669d9e008023f36f7afbb) --- source3/smbd/chgpasswd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d99570ff7c..5caf78e41a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -245,7 +245,8 @@ static int expect(int master, char *issue, char *expected) if (strequal(expected, ".")) return True; - timeout = 2000; + /* Initial timeout. */ + timeout = lp_passwd_chat_timeout() * 1000; nread = 0; buffer[nread] = 0; @@ -261,8 +262,10 @@ static int expect(int master, char *issue, char *expected) pstrcpy( str, buffer); trim_char( str, ' ', ' '); - if ((match = (unix_wild_match(expected, str) == 0))) - timeout = 200; + if ((match = (unix_wild_match(expected, str) == 0))) { + /* Now data has started to return, lower timeout. */ + timeout = lp_passwd_chat_timeout() * 100; + } } } -- cgit From 09a708815625f4c9e656cdbbf148a2ca2de73bc7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Nov 2003 23:25:42 +0000 Subject: Patch from Jim McDonough for bug #802. Retrieve the correct ACL group bits if the file has an ACL. Jeremy. (This used to be commit 7bf5ed30ce74ba658ca35059955748c1d8cbd6d2) --- source3/smbd/dosmode.c | 3 +++ source3/smbd/posix_acls.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index f88964123e..fb72a2eafc 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -183,6 +183,7 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) /******************************************************************* chmod a file - but preserve some bits ********************************************************************/ + int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_STAT *st) { SMB_STRUCT_STAT st1; @@ -197,6 +198,8 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST return(-1); } + get_acl_group_bits(conn, fname, &st->st_mode); + if (S_ISDIR(st->st_mode)) dosmode |= aDIR; else diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index aa1d25c483..8033c694f5 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3177,6 +3177,48 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) return True; } +/**************************************************************************** + Get the actual group bits stored on a file with an ACL. Has no effect if + the file has no ACL. Needed in dosmode code where the stat() will return + the mask bits, not the real group bits, for a file with an ACL. +****************************************************************************/ + +int get_acl_group_bits( connection_struct *conn, char *fname, mode_t *mode ) +{ + int entry_id = SMB_ACL_FIRST_ENTRY; + SMB_ACL_ENTRY_T entry; + SMB_ACL_T posix_acl; + + posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS); + if (posix_acl == (SMB_ACL_T)NULL) + return -1; + + while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; + + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) + entry_id = SMB_ACL_NEXT_ENTRY; + + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1) + return -1; + + if (tagtype == SMB_ACL_GROUP_OBJ) { + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { + return -1; + } else { + *mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP); + *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRGRP : 0); + *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWGRP : 0); + *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0); + return 0;; + } + } + } + return -1; +} + /**************************************************************************** Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL and set the mask to rwx. Needed to preserve complex ACLs set by NT. -- cgit From 6bb8f54e018db066d93f960ec0f257a77671b593 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 1 Dec 2003 02:25:56 +0000 Subject: Don't automatically set nt status code flag unless client tells us it can cope. Jeremy. (This used to be commit 0d82ac57a59276adb403f8e023578c2d6d5136e4) --- source3/smbd/process.c | 15 ++++++++++----- source3/smbd/sesssetup.c | 28 +++++++++++++++++++--------- 2 files changed, 29 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8a90a15d29..d93826bc7e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -924,11 +924,17 @@ const char *smb_fn_name(int type) return(smb_messages[type].name); } - /**************************************************************************** - Helper function for contruct_reply. + Helper functions for contruct_reply. ****************************************************************************/ +static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY; + +void add_to_common_flags2(uint32 v) +{ + common_flags2 |= v; +} + void construct_reply_common(char *inbuf,char *outbuf) { memset(outbuf,'\0',smb_size); @@ -941,9 +947,8 @@ void construct_reply_common(char *inbuf,char *outbuf) SCVAL(outbuf,smb_reh,0); SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); SSVAL(outbuf,smb_flg2, - (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) | - FLAGS2_LONG_PATH_COMPONENTS | - FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY); + (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) | + common_flags2); SSVAL(outbuf,smb_err,SMB_SUCCESS); SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 64c25db2ab..fb0744bb73 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -472,6 +472,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, if (global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv10); + + if (global_client_caps & CAP_STATUS32) { + add_to_common_flags2(FLAGS2_32_BIT_ERROR_CODES); + } + } p = (uint8 *)smb_buf(inbuf); @@ -615,17 +620,22 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, enum remote_arch_types ra_type = get_remote_arch(); char *p = smb_buf(inbuf); - if(global_client_caps == 0) + if(global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv11); - /* client_caps is used as final determination if client is NT or Win95. - This is needed to return the correct error codes in some - circumstances. - */ + if (global_client_caps & CAP_STATUS32) { + add_to_common_flags2(FLAGS2_32_BIT_ERROR_CODES); + } + + /* client_caps is used as final determination if client is NT or Win95. + This is needed to return the correct error codes in some + circumstances. + */ - if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) { - if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) { - set_remote_arch( RA_WIN95); + if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) { + if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) { + set_remote_arch( RA_WIN95); + } } } @@ -686,7 +696,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, ra_lanman_string( native_lanman ); } - + if (SVAL(inbuf,smb_vwv4) == 0) { setup_new_vc_session(); } -- cgit From 27891bdef10069e70e240bbea53f75359cec78eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 1 Dec 2003 06:19:17 +0000 Subject: Subtract NT_STATUS from common flag, don't add it... Jeremy. (This used to be commit 4e73faa7b4af7f73bdce9fcc2ee1825249dc7da7) --- source3/smbd/process.c | 6 +++--- source3/smbd/sesssetup.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d93826bc7e..5206dc70f8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -928,11 +928,11 @@ const char *smb_fn_name(int type) Helper functions for contruct_reply. ****************************************************************************/ -static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY; +static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES; -void add_to_common_flags2(uint32 v) +void remove_from_common_flags2(uint32 v) { - common_flags2 |= v; + common_flags2 &= ~v; } void construct_reply_common(char *inbuf,char *outbuf) diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index fb0744bb73..ec01a330ee 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -473,8 +473,8 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, if (global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv10); - if (global_client_caps & CAP_STATUS32) { - add_to_common_flags2(FLAGS2_32_BIT_ERROR_CODES); + if (!(global_client_caps & CAP_STATUS32)) { + remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); } } @@ -623,8 +623,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if(global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv11); - if (global_client_caps & CAP_STATUS32) { - add_to_common_flags2(FLAGS2_32_BIT_ERROR_CODES); + if (!(global_client_caps & CAP_STATUS32)) { + remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); } /* client_caps is used as final determination if client is NT or Win95. -- cgit From 570f2b73b4c0088fea929bcb6beb1a17b3c1aba3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 1 Dec 2003 06:53:10 +0000 Subject: Ensure the server can cope with multiple secondary trans requests when signing is turned on. Jeremy. (This used to be commit 206464a748a59b1d485d4d3d0cb4d257d60fbd00) --- source3/smbd/ipc.c | 8 ++++++++ source3/smbd/nttrans.c | 8 ++++++++ source3/smbd/trans2.c | 8 ++++++++ 3 files changed, 24 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 86d982b022..dd92cc4e4d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -445,6 +445,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); show_msg(outbuf); + srv_signing_trans_stop(); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_trans: send_smb failed."); } @@ -456,6 +457,13 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + /* + * The sequence number for the trans reply is always + * based on the last secondary received. + */ + + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) { if(ret) { DEBUG(0,("reply_trans: Invalid secondary trans packet\n")); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 80297daaef..767df0b725 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2488,6 +2488,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); /* We need to send an interim response then receive the rest of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); + srv_signing_trans_stop(); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_nttrans: send_smb failed."); @@ -2498,6 +2499,13 @@ due to being in oplock break state.\n", (unsigned int)function_code )); ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + /* + * The sequence number for the trans reply is always + * based on the last secondary received. + */ + + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) { outsize = set_message(outbuf,0,0,True); if(ret) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 56d1aae3a2..525b015379 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3523,6 +3523,7 @@ int reply_trans2(connection_struct *conn, /* We need to send an interim response then receive the rest of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); + srv_signing_trans_stop(); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_trans2: send_smb failed."); @@ -3536,6 +3537,13 @@ int reply_trans2(connection_struct *conn, ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + /* + * The sequence number for the trans reply is always + * based on the last secondary received. + */ + + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if ((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) { outsize = set_message(outbuf,0,0,True); -- cgit From 8a31a346ef1c42f868a4b7a4f667e6eb56c4a7a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 Dec 2003 23:16:27 +0000 Subject: Fix for "hash" (not hash2) type mangling. Noticed by "Forrest W. Christian" Jeremy. (This used to be commit 3a8fe3b2ef30cbe0cf441d6c4ffa9c309dc71e54) --- source3/smbd/mangle_hash.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index ac2d7681e8..16722ae6e9 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -139,7 +139,7 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ /* -------------------------------------------------------------------- */ -static NTSTATUS has_valid_chars(const smb_ucs2_t *s, BOOL allow_wildcards) +static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, BOOL allow_wildcards) { if (!s || !*s) return NT_STATUS_INVALID_PARAMETER; @@ -176,7 +176,7 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) { ext_len = strlen_w(p+1); if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) && - (NT_STATUS_IS_OK(has_valid_chars(p+1,allow_wildcards)))) /* check extension */ { + (NT_STATUS_IS_OK(has_valid_83_chars(p+1,allow_wildcards)))) /* check extension */ { *p = 0; *extension = strdup_w(p+1); if (!*extension) { @@ -200,7 +200,7 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr * ************************************************************************** ** */ -static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards) +static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOOL only_8_3) { smb_ucs2_t *str, *p; NTSTATUS ret = NT_STATUS_OK; @@ -216,9 +216,11 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards) if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL; - ret = has_valid_chars(fname, allow_wildcards); - if (!NT_STATUS_IS_OK(ret)) - return ret; + if (only_8_3) { + ret = has_valid_83_chars(fname, allow_wildcards); + if (!NT_STATUS_IS_OK(ret)) + return ret; + } str = strdup_w(fname); p = strchr_w(str, UCS2_CHAR('.')); @@ -286,7 +288,7 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards) if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) return NT_STATUS_OK; - if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards))) + if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards, True))) goto done; if (!NT_STATUS_IS_OK(mangle_get_prefix(fname, &pref, &ext, allow_wildcards))) @@ -737,7 +739,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83) return; } - if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False))) + if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False, False))) need83 = True; /* check if it's already in 8.3 format */ -- cgit From 4b1e15a4f2a9bac1fd6b3a800dc642dfe69f2d2a Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 5 Dec 2003 21:51:51 +0000 Subject: fix %a variable for Windows 2003 -> Win2K3 (This used to be commit 2f43a1c166dfc8679a9d03bd0f3cf9303aafcf74) --- source3/smbd/sesssetup.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index ec01a330ee..da48c81fc1 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -463,7 +463,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, DATA_BLOB blob1; int ret; size_t bufrem; - fstring native_os, native_lanman; + fstring native_os, native_lanman, primary_domain; char *p2; uint16 data_blob_len = SVAL(inbuf, smb_vwv7); enum remote_arch_types ra_type = get_remote_arch(); @@ -497,11 +497,20 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, p2 = inbuf + smb_vwv13 + data_blob_len; p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE); p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE); - DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s]\n", native_os, native_lanman)); - - if ( ra_type == RA_WIN2K ) - ra_lanman_string( native_lanman ); + p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE); + DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", + native_os, native_lanman, primary_domain)); + if ( ra_type == RA_WIN2K ) { + /* Windows 2003 doesn't set the native lanman string, + but does set primary domain which is a bug I think */ + + if ( !strlen(native_lanman) ) + ra_lanman_string( primary_domain ); + else + ra_lanman_string( native_lanman ); + } + if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1); @@ -556,6 +565,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, fstring domain; fstring native_os; fstring native_lanman; + fstring primary_domain; static BOOL done_sesssetup = False; extern BOOL global_encrypted_passwords_negotiated; extern BOOL global_spnego_negotiated; @@ -619,6 +629,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, uint16 passlen2 = SVAL(inbuf,smb_vwv8); enum remote_arch_types ra_type = get_remote_arch(); char *p = smb_buf(inbuf); + char *save_p = smb_buf(inbuf); + uint16 byte_count; + if(global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv11); @@ -689,11 +702,28 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE); p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE); p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); - DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - domain,native_os,native_lanman)); - if ( ra_type == RA_WIN2K ) - ra_lanman_string( native_lanman ); + /* not documented or decoded by Ethereal but there is one more string + in the extra bytes which is the same as the PrimaryDomain when using + extended security. Windows NT 4 and 2003 use this string to store + the native lanman string. Windows 9x does not include a string here + at all so we have to check if we have any extra bytes left */ + + byte_count = SVAL(inbuf, smb_vwv13); + if ( PTR_DIFF(p, save_p) < byte_count) + p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); + else + fstrcpy( primary_domain, "null" ); + + DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", + domain, native_os, native_lanman, primary_domain)); + + if ( ra_type == RA_WIN2K ) { + if ( strlen(native_lanman) == 0 ) + ra_lanman_string( primary_domain ); + else + ra_lanman_string( native_lanman ); + } } -- cgit From b05b6046fc790329d6b301aafb7ddb0b64ce00ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Dec 2003 20:00:16 +0000 Subject: Patch from James Peach . Remove the MAX_CONNECTIONS limit by increasing bitmap size. Limited by "max connections" parameter. Bug #716. Jeremy. (This used to be commit fbbeb55b230ffc477f5563af66ab65eb6598e025) --- source3/smbd/conn.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index eb2d2bbcbf..289b7d611d 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -21,11 +21,11 @@ #include "includes.h" -/* set these to define the limits of the server. NOTE These are on a - per-client basis. Thus any one machine can't connect to more than - MAX_CONNECTIONS services, but any number of machines may connect at - one time. */ -#define MAX_CONNECTIONS 128 +/* The connections bitmap is expanded in increments of BITMAP_BLOCK_SZ. The + * maximum size of the bitmap is the largest positive integer, but you will hit + * the "max connections" limit, looong before that. + */ +#define BITMAP_BLOCK_SZ 128 static connection_struct *Connections; @@ -38,7 +38,7 @@ init the conn structures ****************************************************************************/ void conn_init(void) { - bmap = bitmap_allocate(MAX_CONNECTIONS); + bmap = bitmap_allocate(BITMAP_BLOCK_SZ); } /**************************************************************************** @@ -96,12 +96,35 @@ connection_struct *conn_new(void) TALLOC_CTX *mem_ctx; connection_struct *conn; int i; + int find_offset = 1; - i = bitmap_find(bmap, 1); +find_again: + i = bitmap_find(bmap, find_offset); if (i == -1) { - DEBUG(1,("ERROR! Out of connection structures\n")); - return NULL; + /* Expand the connections bitmap. */ + int oldsz = bmap->n; + int newsz = bmap->n + BITMAP_BLOCK_SZ; + struct bitmap * nbmap; + + if (newsz <= 0) { + /* Integer wrap. */ + DEBUG(0,("ERROR! Out of connection structures\n")); + return NULL; + } + + DEBUG(4,("resizing connections bitmap from %d to %d\n", + oldsz, newsz)); + + nbmap = bitmap_allocate(newsz); + + bitmap_copy(nbmap, bmap); + bitmap_free(bmap); + + bmap = nbmap; + find_offset = oldsz; /* Start next search in the new portion. */ + + goto find_again; } if ((mem_ctx=talloc_init("connection_struct"))==NULL) { -- cgit From c4f1b6cf3af731750bf0dfe2311514576197e4e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Dec 2003 22:54:43 +0000 Subject: Fix for bug #815. Make plaintext unicode passwords work with NT4.x Jeremy. (This used to be commit ba0b5b8c9be9bfeba5e0b3f930ca0463d1e78c9c) --- source3/smbd/sesssetup.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index da48c81fc1..e9cfa47d0c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -689,11 +689,17 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, nt_resp = data_blob(p+passlen1, passlen2); } else { pstring pass; - BOOL unic; - unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS; - srvstr_pull(inbuf, pass, smb_buf(inbuf), - sizeof(pass), unic ? passlen2 : passlen1, - STR_TERMINATE); + BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS; + + if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) { + /* NT4.0 stuffs up plaintext unicode password lengths... */ + srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1, + sizeof(pass), passlen1, STR_TERMINATE); + } else { + srvstr_pull(inbuf, pass, smb_buf(inbuf), + sizeof(pass), unic ? passlen2 : passlen1, + STR_TERMINATE); + } plaintext_password = data_blob(pass, strlen(pass)+1); } -- cgit From 033fc98a6e340c3a87c20cc117384caa4ed36a30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Dec 2003 07:33:42 +0000 Subject: Fix for special files being hidden from admins by Dmitry Butskoj Jeremy. (This used to be commit bee4b3348e5052cc927c837c2a21b4c90db980fc) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 94b605ee8f..bbd79e1659 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -793,7 +793,7 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT */ if (conn->admin_user) - return True; + return False; /* If we can't stat it does not show it */ if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) -- cgit From fd35232584d34c3250094572393b3a64fc87cef9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2004 11:51:31 +0000 Subject: Commit the translation of the realm to the netbios domain name in the kerberos session setup. After talking to jht and abartlet I made this unconditional, no additional parameter. Jerry: This is a change in behaviour, but I think it is necessary. Volker (This used to be commit 3ce6c9f27368cfb278007fe660a0e44a84d67f8f) --- source3/smbd/sesssetup.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e9cfa47d0c..2c38cd3eb3 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -141,7 +141,8 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB *secblob) { DATA_BLOB ticket; - char *client, *p; + char *client, *p, *domain; + fstring netbios_domain_name; const struct passwd *pw; char *user; int sess_vuid; @@ -198,8 +199,45 @@ static int reply_spnego_kerberos(connection_struct *conn, /* this gives a fully qualified user name (ie. with full realm). that leads to very long usernames, but what else can we do? */ - - asprintf(&user, "%s%c%s", p+1, *lp_winbind_separator(), client); + + domain = p+1; + + { + /* If we have winbind running, we can (and must) shorten the + username by using the short netbios name. Otherwise we will + have inconsistent user names. With Kerberos, we get the + fully qualified realm, with ntlmssp we get the short + name. And even w2k3 does use ntlmssp if you for example + connect to an ip address. */ + + struct winbindd_request wb_request; + struct winbindd_response wb_response; + NSS_STATUS wb_result; + + ZERO_STRUCT(wb_request); + ZERO_STRUCT(wb_response); + + DEBUG(10, ("Mapping [%s] to short name\n", domain)); + + fstrcpy(wb_request.domain_name, domain); + + wb_result = winbindd_request(WINBINDD_DOMAIN_INFO, + &wb_request, &wb_response); + + if (wb_result == NSS_STATUS_SUCCESS) { + + fstrcpy(netbios_domain_name, + wb_response.data.domain_info.name); + domain = netbios_domain_name; + + DEBUG(10, ("Mapped to [%s]\n", domain)); + } else { + DEBUG(3, ("Could not find short name -- winbind " + "not running?\n")); + } + } + + asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client); pw = smb_getpwnam( user ); -- cgit From 31876a8478fc16dc7ac62ca835714098398f56e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Jan 2004 19:36:02 +0000 Subject: Patch from Stefan (metze) Metzmacher to revert to 2.2.x quota methods. :-). "here's a patch which ports the samba 2.2 samba_linux_quota.h stuff to 3_0. This is needed because of so many broken quota files outthere. Please, test this with old, new kernels (strucr dqblk, struct mem_dqblk, and struct if_dqblk) , quota.user, aquota.user formats what is when a user is over soft quota and over hard quotas..." Jeremy. (This used to be commit 4350aa6ce6cfdaf71cdcfd2aebcdc9560fa7efcf) --- source3/smbd/quotas.c | 159 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 63 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 46f688a219..19f225e973 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -50,33 +50,16 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B #ifdef LINUX #include -#include +#include /* * This shouldn't be neccessary - it should be /usr/include/sys/quota.h - * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk - * rather than the struct dqblk defined in /usr/include/sys/quota.h. - * This means we must include linux/quota.h to have a hope of working on - * RH7.1 systems. And it also means this breaks if the kernel is upgraded - * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until - * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA. + * So we include all the files has *should* be in the system into a large, + * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA. */ -#include -#ifdef HAVE_LINUX_XQM_H -#include -#else -#ifdef HAVE_XFS_XQM_H -#include -#define HAVE_LINUX_XQM_H -#endif -#endif - -#include -#include - - -#define LINUX_QUOTAS_2 +#include "samba_linux_quota.h" +#include "samba_xfs_quota.h" typedef struct _LINUX_SMB_DISK_QUOTA { SMB_BIG_UINT bsize; @@ -92,22 +75,20 @@ typedef struct _LINUX_SMB_DISK_QUOTA { Abstract out the XFS Quota Manager quota get call. ****************************************************************************/ -static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) +static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) { - int ret = -1; -#ifdef HAVE_LINUX_XQM_H struct fs_disk_quota D; + int ret; ZERO_STRUCT(D); - ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); + ret = quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), path, euser_id, (caddr_t)&D); - /* As XFS has group quotas, if getting the user quota fails, try getting the group instead. */ - if (ret) { - ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D); - if (ret) - return ret; - } + if (ret) + ret = quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), path, egrp_id, (caddr_t)&D); + + if (ret) + return ret; dp->bsize = (SMB_BIG_UINT)512; dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit; @@ -116,7 +97,7 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit; dp->curinodes = (SMB_BIG_UINT)D.d_icount; dp->curblocks = (SMB_BIG_UINT)D.d_bcount; -#endif + return ret; } @@ -124,48 +105,90 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU Abstract out the old and new Linux quota get calls. ****************************************************************************/ -static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp) +static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) { - int ret = 0; -#ifdef LINUX_QUOTAS_1 - struct dqblk D; + struct v1_kern_dqblk D; + int ret; + ZERO_STRUCT(D); - dp->bsize = (SMB_BIG_UINT)1024; -#else /* LINUX_QUOTAS_2 */ - struct mem_dqblk D; + + ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); + + if (ret && errno != EDQUOT) + ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); + + if (ret && errno != EDQUOT) + return ret; + + dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; + dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit; + dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit; + dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes; + dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks; + + return ret; +} + +static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) +{ + struct v2_kern_dqblk D; + int ret; + ZERO_STRUCT(D); -#ifndef QUOTABLOCK_SIZE -#define QUOTABLOCK_SIZE 1024 -#endif + + ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); + + if (ret && errno != EDQUOT) + ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); + + if (ret && errno != EDQUOT) + return ret; + dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; -#endif + dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit; + dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit; + dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes; + dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize; + + return ret; +} + +/**************************************************************************** + Brand-new generic quota interface. +****************************************************************************/ + +static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) +{ + struct if_dqblk D; + int ret; + + ZERO_STRUCT(D); ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); - /* Linux can have group quotas, if getting the user quota fails, try getting the group instead. */ - if (ret) { - ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D); - if (ret) - return ret; - } + if (ret && errno != EDQUOT) + ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); + if (ret && errno != EDQUOT) + return ret; + + dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit; dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit; dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit; dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit; dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes; - -#ifdef LINUX_QUOTAS_1 - dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks; -#else /* LINUX_QUOTAS_2 */ - dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize; -#endif + dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize; return ret; } /**************************************************************************** -try to get the disk space from disk quotas (LINUX version) + Try to get the disk space from disk quotas (LINUX version). ****************************************************************************/ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) @@ -178,9 +201,11 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB SMB_DEV_T devno; int found; uid_t euser_id; + gid_t egrp_id; euser_id = geteuid(); - + egrp_id = getegid(); + /* find the block device file */ if ( sys_stat(path, &S) == -1 ) @@ -208,10 +233,18 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB save_re_uid(); set_effective_uid(0); - if (strcmp(mnt->mnt_type, "xfs") == 0) - r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D); - else - r=get_smb_linux_vfs_quota(mnt->mnt_fsname, euser_id, &D); + + if (strcmp(mnt->mnt_type, "xfs")==0) { + r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); + } else { + r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); + if (r == -1 && errno != EDQUOT) { + r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); + if (r == -1 && errno != EDQUOT) + r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); + } + } + restore_re_uid(); /* Use softlimit to determine disk space, except when it has been exceeded */ @@ -920,8 +953,8 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0)) #else if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) -#endif /* ifdef HPUX */ return (False); +#endif /* ifdef HPUX */ #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */ -- cgit From 0d44747df99f2168a063feedad5039f222746f61 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Jan 2004 01:22:14 +0000 Subject: Patch based on work from James Peach to convert over to using pread/pwrite. Modified a little to ensure fsp->pos is correct. Fix for #889. Jeremy. (This used to be commit 019aaaf0df091c3f67048f591e70d4353a02bb9b) --- source3/smbd/fileio.c | 23 ++-- source3/smbd/vfs-wrap.c | 320 ++++++++++++++++++++++++++++++------------------ source3/smbd/vfs.c | 43 +++++++ 3 files changed, 255 insertions(+), 131 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 84339c3a6f..f395954d05 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -95,16 +95,14 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) flush_write_cache(fsp, READ_FLUSH); - if (seek_file(fsp,pos) == -1) { - DEBUG(3,("read_file: Failed to seek to %.0f\n",(double)pos)); - return(ret); - } - + fsp->pos = pos; + if (n > 0) { #ifdef DMF_FIX int numretries = 3; tryagain: - readret = SMB_VFS_READ(fsp,fsp->fd,data,n); + readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos); + if (readret == -1) { if ((errno == EAGAIN) && numretries) { DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); @@ -115,7 +113,8 @@ tryagain: return -1; } #else /* NO DMF fix. */ - readret = SMB_VFS_READ(fsp,fsp->fd,data,n); + readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos); + if (readret == -1) return -1; #endif @@ -143,10 +142,12 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ { ssize_t ret; - if ((pos != -1) && (seek_file(fsp,pos) == -1)) - return -1; - - ret = vfs_write_data(fsp,data,n); + if (pos == -1) + ret = vfs_write_data(fsp, data, n); + else { + fsp->pos = pos; + ret = vfs_pwrite_data(fsp, data, n, pos); + } DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 378a0a1e53..4f2d82734f 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -44,10 +44,10 @@ void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - SMB_BIG_UINT result; + SMB_BIG_UINT result; - result = sys_disk_free(path, small_query, bsize, dfree, dsize); - return result; + result = sys_disk_free(path, small_query, bsize, dfree, dsize); + return result; } int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) @@ -90,22 +90,22 @@ int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_ DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) { - DIR *result; + DIR *result; - START_PROFILE(syscall_opendir); - result = opendir(fname); - END_PROFILE(syscall_opendir); - return result; + START_PROFILE(syscall_opendir); + result = opendir(fname); + END_PROFILE(syscall_opendir); + return result; } struct dirent *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { - struct dirent *result; + struct dirent *result; - START_PROFILE(syscall_readdir); - result = readdir(dirp); - END_PROFILE(syscall_readdir); - return result; + START_PROFILE(syscall_readdir); + result = readdir(dirp); + END_PROFILE(syscall_readdir); + return result; } int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) @@ -133,71 +133,154 @@ int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char errno = saved_errno; } - END_PROFILE(syscall_mkdir); - return result; + END_PROFILE(syscall_mkdir); + return result; } int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result; + int result; - START_PROFILE(syscall_rmdir); - result = rmdir(path); - END_PROFILE(syscall_rmdir); - return result; + START_PROFILE(syscall_rmdir); + result = rmdir(path); + END_PROFILE(syscall_rmdir); + return result; } int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { - int result; + int result; - START_PROFILE(syscall_closedir); - result = closedir(dirp); - END_PROFILE(syscall_closedir); - return result; + START_PROFILE(syscall_closedir); + result = closedir(dirp); + END_PROFILE(syscall_closedir); + return result; } /* File operations */ int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) { - int result; + int result; - START_PROFILE(syscall_open); - result = sys_open(fname, flags, mode); - END_PROFILE(syscall_open); - return result; + START_PROFILE(syscall_open); + result = sys_open(fname, flags, mode); + END_PROFILE(syscall_open); + return result; } int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd) { - int result; + int result; - START_PROFILE(syscall_close); + START_PROFILE(syscall_close); - result = close(fd); - END_PROFILE(syscall_close); - return result; + result = close(fd); + END_PROFILE(syscall_close); + return result; } ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n) { - ssize_t result; + ssize_t result; - START_PROFILE_BYTES(syscall_read, n); - result = sys_read(fd, data, n); - END_PROFILE(syscall_read); - return result; + START_PROFILE_BYTES(syscall_read, n); + result = sys_read(fd, data, n); + END_PROFILE(syscall_read); + return result; +} + +ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, + size_t n, SMB_OFF_T offset) +{ + ssize_t result; + +#if defined(HAVE_PREAD) || defined(HAVE_PREAD64) + START_PROFILE_BYTES(syscall_pread, n); + result = sys_pread(fd, data, n, offset); + END_PROFILE(syscall_pread); + + if (result == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be seeked (sought?) on. */ + result = SMB_VFS_READ(fsp, fd, data, n); + fsp->pos = 0; + } + +#else /* HAVE_PREAD */ + SMB_OFF_T curr; + int lerrno; + + curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (curr == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be seeked (sought?) on. */ + result = SMB_VFS_READ(fsp, fd, data, n); + fsp->pos = 0; + return result; + } + + if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { + return -1; + } + + errno = 0; + result = SMB_VFS_READ(fsp, fd, data, n); + lerrno = errno; + + SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); + errno = lerrno; + +#endif /* HAVE_PREAD */ + + return result; } ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) { - ssize_t result; + ssize_t result; + + START_PROFILE_BYTES(syscall_write, n); + result = sys_write(fd, data, n); + END_PROFILE(syscall_write); + return result; +} + +ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, + size_t n, SMB_OFF_T offset) +{ + ssize_t result; + +#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64) + START_PROFILE_BYTES(syscall_pwrite, n); + result = sys_pwrite(fd, data, n, offset); + END_PROFILE(syscall_pwrite); + + if (result == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be sought on. */ + result = SMB_VFS_WRITE(fsp, fd, data, n); + } + +#else /* HAVE_PWRITE */ + SMB_OFF_T curr; + int lerrno; - START_PROFILE_BYTES(syscall_write, n); - result = sys_write(fd, data, n); - END_PROFILE(syscall_write); - return result; + curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (curr == -1) { + return -1; + } + + if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { + return -1; + } + + result = SMB_VFS_WRITE(fsp, fd, data, n); + lerrno = errno; + + SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); + errno = lerrno; + +#endif /* HAVE_PWRITE */ + + return result; } SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) @@ -340,13 +423,12 @@ int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const cha int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) { #ifdef HAVE_FSYNC - int result; - - START_PROFILE(syscall_fsync); + int result; - result = fsync(fd); - END_PROFILE(syscall_fsync); - return result; + START_PROFILE(syscall_fsync); + result = fsync(fd); + END_PROFILE(syscall_fsync); + return result; #else return 0; #endif @@ -354,49 +436,49 @@ int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) { - int result; + int result; - START_PROFILE(syscall_stat); - result = sys_stat(fname, sbuf); - END_PROFILE(syscall_stat); - return result; + START_PROFILE(syscall_stat); + result = sys_stat(fname, sbuf); + END_PROFILE(syscall_stat); + return result; } int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) { - int result; + int result; - START_PROFILE(syscall_fstat); - result = sys_fstat(fd, sbuf); - END_PROFILE(syscall_fstat); - return result; + START_PROFILE(syscall_fstat); + result = sys_fstat(fd, sbuf); + END_PROFILE(syscall_fstat); + return result; } int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { - int result; + int result; - START_PROFILE(syscall_lstat); - result = sys_lstat(path, sbuf); - END_PROFILE(syscall_lstat); - return result; + START_PROFILE(syscall_lstat); + result = sys_lstat(path, sbuf); + END_PROFILE(syscall_lstat); + return result; } int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result; + int result; - START_PROFILE(syscall_unlink); - result = unlink(path); - END_PROFILE(syscall_unlink); - return result; + START_PROFILE(syscall_unlink); + result = unlink(path); + END_PROFILE(syscall_unlink); + return result; } int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { - int result; + int result; - START_PROFILE(syscall_chmod); + START_PROFILE(syscall_chmod); /* * We need to do this due to the fact that the default POSIX ACL @@ -415,9 +497,9 @@ int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char errno = saved_errno; } - result = chmod(path, mode); - END_PROFILE(syscall_chmod); - return result; + result = chmod(path, mode); + END_PROFILE(syscall_chmod); + return result; } int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) @@ -455,58 +537,57 @@ int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) { - int result; + int result; - START_PROFILE(syscall_chown); - result = sys_chown(path, uid, gid); - END_PROFILE(syscall_chown); - return result; + START_PROFILE(syscall_chown); + result = sys_chown(path, uid, gid); + END_PROFILE(syscall_chown); + return result; } int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid) { #ifdef HAVE_FCHOWN - int result; - - START_PROFILE(syscall_fchown); + int result; - result = fchown(fd, uid, gid); - END_PROFILE(syscall_fchown); - return result; + START_PROFILE(syscall_fchown); + result = fchown(fd, uid, gid); + END_PROFILE(syscall_fchown); + return result; #else - errno = ENOSYS; - return -1; + errno = ENOSYS; + return -1; #endif } int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result; + int result; - START_PROFILE(syscall_chdir); - result = chdir(path); - END_PROFILE(syscall_chdir); - return result; + START_PROFILE(syscall_chdir); + result = chdir(path); + END_PROFILE(syscall_chdir); + return result; } char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path) { - char *result; + char *result; - START_PROFILE(syscall_getwd); - result = sys_getwd(path); - END_PROFILE(syscall_getwd); - return result; + START_PROFILE(syscall_getwd); + result = sys_getwd(path); + END_PROFILE(syscall_getwd); + return result; } int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) { - int result; + int result; - START_PROFILE(syscall_utime); - result = utime(path, times); - END_PROFILE(syscall_utime); - return result; + START_PROFILE(syscall_utime); + result = utime(path, times); + END_PROFILE(syscall_utime); + return result; } /********************************************************************* @@ -643,33 +724,32 @@ int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { - BOOL result; - - START_PROFILE(syscall_fcntl_lock); + BOOL result; - result = fcntl_lock(fd, op, offset, count,type); - END_PROFILE(syscall_fcntl_lock); - return result; + START_PROFILE(syscall_fcntl_lock); + result = fcntl_lock(fd, op, offset, count,type); + END_PROFILE(syscall_fcntl_lock); + return result; } int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) { - int result; + int result; - START_PROFILE(syscall_symlink); - result = sys_symlink(oldpath, newpath); - END_PROFILE(syscall_symlink); - return result; + START_PROFILE(syscall_symlink); + result = sys_symlink(oldpath, newpath); + END_PROFILE(syscall_symlink); + return result; } int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) { - int result; + int result; - START_PROFILE(syscall_readlink); - result = sys_readlink(path, buf, bufsiz); - END_PROFILE(syscall_readlink); - return result; + START_PROFILE(syscall_readlink); + result = sys_readlink(path, buf, bufsiz); + END_PROFILE(syscall_readlink); + return result; } int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 753db4cece..2f981c743f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -71,7 +71,9 @@ static struct vfs_ops default_vfs = { vfswrap_open, vfswrap_close, vfswrap_read, + vfswrap_pread, vfswrap_write, + vfswrap_pwrite, vfswrap_lseek, vfswrap_sendfile, vfswrap_rename, @@ -429,6 +431,28 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) return (ssize_t)total; } +ssize_t vfs_pread_data(files_struct *fsp, char *buf, + size_t byte_count, SMB_OFF_T offset) +{ + size_t total=0; + + while (total < byte_count) + { + ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fd, buf + total, + byte_count - total, offset + total); + + if (ret == 0) return total; + if (ret == -1) { + if (errno == EINTR) + continue; + else + return -1; + } + total += ret; + } + return (ssize_t)total; +} + /**************************************************************************** Write data to a fd on the vfs. ****************************************************************************/ @@ -451,6 +475,25 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) return (ssize_t)total; } +ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer, + size_t N, SMB_OFF_T offset) +{ + size_t total=0; + ssize_t ret; + + while (total < N) { + ret = SMB_VFS_PWRITE(fsp, fsp->fd, buffer + total, + N - total, offset + total); + + if (ret == -1) + return -1; + if (ret == 0) + return total; + + total += ret; + } + return (ssize_t)total; +} /**************************************************************************** An allocate file space call using the vfs interface. Allocates space for a file from a filedescriptor. -- cgit From d86628d0628a064f58e3ce9fbaf55ad9d5a92540 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 6 Jan 2004 19:57:14 +0000 Subject: remove unused seek_file(); don't hardcode '\' when printing the auth-user (This used to be commit fac5e05ca1b56cb6e3ab6537d0848fa373c00831) --- source3/smbd/fileio.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index f395954d05..3462a3b9fa 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -24,31 +24,6 @@ static BOOL setup_write_cache(files_struct *, SMB_OFF_T); -/**************************************************************************** - Seek a file. Try to avoid the seek if possible. -****************************************************************************/ - -static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) -{ - SMB_OFF_T seek_ret; - - seek_ret = SMB_VFS_LSEEK(fsp,fsp->fd,pos,SEEK_SET); - - if(seek_ret == -1) { - DEBUG(0,("seek_file: (%s) sys_lseek failed. Error was %s\n", - fsp->fsp_name, strerror(errno) )); - fsp->pos = -1; - return -1; - } - - fsp->pos = seek_ret; - - DEBUG(10,("seek_file (%s): requested pos = %.0f, new pos = %.0f\n", - fsp->fsp_name, (double)pos, (double)fsp->pos )); - - return(fsp->pos); -} - /**************************************************************************** Read from write cache if we can. ****************************************************************************/ -- cgit From 12c97a786edcf6d2365fe36a58bcbd513605df1d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Jan 2004 22:34:06 +0000 Subject: Patch penguin. Cleaning out old mbp patch. Jeremy. (This used to be commit d75db0bf1eee9c4341a3ec14c05f82b364a202b3) --- source3/smbd/chgpasswd.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5caf78e41a..e6117245e7 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -343,7 +343,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, /* allocate a pseudo-terminal device */ if ((master = findpty(&slavedev)) < 0) { - DEBUG(3, ("Cannot Allocate pty for password change: %s\n", pass->pw_name)); + DEBUG(3, ("chat_with_program: Cannot Allocate pty for password change: %s\n", pass->pw_name)); return (False); } @@ -355,7 +355,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, CatchChildLeaveStatus(); if ((pid = sys_fork()) < 0) { - DEBUG(3, ("Cannot fork() child for password change: %s\n", pass->pw_name)); + DEBUG(3, ("chat_with_program: Cannot fork() child for password change: %s\n", pass->pw_name)); close(master); CatchChild(); return (False); @@ -364,7 +364,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, /* we now have a pty */ if (pid > 0) { /* This is the parent process */ if ((chstat = talktochild(master, chatsequence)) == False) { - DEBUG(3, ("Child failed to change password: %s\n", pass->pw_name)); + DEBUG(3, ("chat_with_program: Child failed to change password: %s\n", pass->pw_name)); kill(pid, SIGKILL); /* be sure to end this process */ } @@ -377,7 +377,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, } if (wpid < 0) { - DEBUG(3, ("The process is no longer waiting!\n\n")); + DEBUG(3, ("chat_with_program: The process is no longer waiting!\n\n")); close(master); CatchChild(); return (False); @@ -391,19 +391,21 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, close(master); if (pid != wpid) { - DEBUG(3, ("We were waiting for the wrong process ID\n")); + DEBUG(3, ("chat_with_program: We were waiting for the wrong process ID\n")); return (False); } - if (WIFEXITED(wstat) == 0) { - DEBUG(3, ("The process exited while we were waiting\n")); + if (WIFEXITED(wstat) && (WEXITSTATUS(wstat) != 0)) { + DEBUG(3, ("chat_with_program: The process exited with status %d \ +while we were waiting\n", WEXITSTATUS(wstat))); return (False); } - if (WEXITSTATUS(wstat) != 0) { - DEBUG(3, ("The status of the process exiting was %d\n", - wstat)); +#if defined(WIFSIGNALLED) && defined(WTERMSIG) + else if (WIFSIGNALLED(wstat)) { + DEBUG(3, ("chat_with_program: The process was killed by signal %d \ +while we were waiting\n", WTERMSIG(wstat))); return (False); } - +#endif } else { /* CHILD */ @@ -418,7 +420,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, if (as_root) become_root(); - DEBUG(3, ("Dochild for user %s (uid=%d,gid=%d) (as_root = %s)\n", pass->pw_name, + DEBUG(3, ("chat_with_program: Dochild for user %s (uid=%d,gid=%d) (as_root = %s)\n", pass->pw_name, (int)getuid(), (int)getgid(), BOOLSTR(as_root) )); chstat = dochild(master, slavedev, pass, passwordprogram, as_root); @@ -434,7 +436,7 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, } if (chstat) - DEBUG(3, ("Password change %ssuccessful for user %s\n", + DEBUG(3, ("chat_with_program: Password change %ssuccessful for user %s\n", (chstat ? "" : "un"), pass->pw_name)); return (chstat); } @@ -449,12 +451,12 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL struct passwd *pass; if (!name) { - DEBUG(1, ("NULL username specfied to chgpasswd()!\n")); + DEBUG(1, ("chgpasswd: NULL username specfied !\n")); } pass = Get_Pwnam(name); if (!pass) { - DEBUG(1, ("Username does not exist in system passwd!\n")); + DEBUG(1, ("chgpasswd: Username does not exist in system !\n")); return False; } @@ -462,17 +464,17 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL oldpass = ""; } - DEBUG(3, ("Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name)); + DEBUG(3, ("chgpasswd: Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name)); #if DEBUG_PASSWORD - DEBUG(100, ("Passwords: old=%s new=%s\n", oldpass, newpass)); + DEBUG(100, ("chgpasswd: Passwords: old=%s new=%s\n", oldpass, newpass)); #endif /* Take the passed information and test it for minimum criteria */ /* Minimum password length */ if (strlen(newpass) < lp_min_passwd_length()) { /* too short, must be at least MINPASSWDLENGTH */ - DEBUG(0, ("Password Change: user %s, New password is shorter than minimum password length = %d\n", + DEBUG(0, ("chgpasswd: Password Change: user %s, New password is shorter than minimum password length = %d\n", name, lp_min_passwd_length())); return (False); /* inform the user */ } @@ -480,7 +482,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL /* Password is same as old password */ if (strcmp(oldpass, newpass) == 0) { /* don't allow same password */ - DEBUG(2, ("Password Change: %s, New password is same as old\n", name)); /* log the attempt */ + DEBUG(2, ("chgpasswd: Password Change: %s, New password is same as old\n", name)); /* log the attempt */ return (False); /* inform the user */ } @@ -492,7 +494,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL len = strlen(oldpass); for (i = 0; i < len; i++) { if (iscntrl((int)oldpass[i])) { - DEBUG(0, ("chat_with_program: oldpass contains control characters (disallowed).\n")); + DEBUG(0, ("chgpasswd: oldpass contains control characters (disallowed).\n")); return False; } } @@ -500,7 +502,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL len = strlen(newpass); for (i = 0; i < len; i++) { if (iscntrl((int)newpass[i])) { - DEBUG(0, ("chat_with_program: newpass contains control characters (disallowed).\n")); + DEBUG(0, ("chgpasswd: newpass contains control characters (disallowed).\n")); return False; } } @@ -570,7 +572,7 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { - DEBUG(0, ("Password changing not compiled in (user=%s)\n", name)); + DEBUG(0, ("chgpasswd: Password changing not compiled in (user=%s)\n", name)); return (False); } #endif /* ALLOW_CHANGE_PASSWORD */ -- cgit From e41a67a18839ea8a5e1bd5403f3668e7f2b374b7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Jan 2004 19:55:01 +0000 Subject: Fix from Luke Howard for incorrect early free(). Jeremy. (This used to be commit 8e20c06ed31d9ec10ff0155b1624eee3d60cd006) --- source3/smbd/sesssetup.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 2c38cd3eb3..80be9da53b 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -241,11 +241,10 @@ static int reply_spnego_kerberos(connection_struct *conn, pw = smb_getpwnam( user ); - SAFE_FREE(user); - SAFE_FREE(client); - if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); + SAFE_FREE(user); + SAFE_FREE(client); data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -257,14 +256,17 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); + SAFE_FREE(user); + SAFE_FREE(client); data_blob_free(&ap_rep); return ERROR_NT(ret); } /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, session_key, nullblob, user); + sess_vuid = register_vuid(server_info, session_key, nullblob, client); - free(user); + SAFE_FREE(user); + SAFE_FREE(client); if (sess_vuid == -1) { ret = NT_STATUS_LOGON_FAILURE; -- cgit From 86450924a0ed5ea721eb8555c5192978e875bbbe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 11 Jan 2004 13:23:50 +0000 Subject: update copyright to -2004 metze (This used to be commit 12d6bc3bd0684646e990c2fc6485fe1a92ac98fb) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 89d6f92e98..e7aa41e343 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -745,7 +745,7 @@ void build_options(BOOL screen); reopen_logs(); DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING)); - DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2003\n")); + DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2004\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); -- cgit From b75b755a2ba78ad323d6a87fdbee78b1829f864f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 12 Jan 2004 12:18:11 +0000 Subject: First stab at cracklib support (password quality checking) in Samba 3.0 This adds a configure test, that tries to find out if we have a working cracklib installation, and tries to pick up the debian hints on where the dictionary might be found. Default is per my Fedora Core 1 system - I'm not sure how much it changes. Andrew Bartlett (This used to be commit bc770edb788f0b6f719011cda683f045b76b7ba5) --- source3/smbd/chgpasswd.c | 79 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e6117245e7..07def7549e 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -49,6 +49,14 @@ #include "includes.h" +#include + +#ifndef HAVE_CRACKLIB_DICTPATH +#ifndef CRACKLIB_DICTPATH +#define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH +#endif +#endif + extern struct passdb_ops pdb_ops; static NTSTATUS check_oem_password(const char *user, @@ -441,25 +449,14 @@ while we were waiting\n", WTERMSIG(wstat))); return (chstat); } -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; size_t i; size_t len; - struct passwd *pass; - - if (!name) { - DEBUG(1, ("chgpasswd: NULL username specfied !\n")); - } - - pass = Get_Pwnam(name); - if (!pass) { - DEBUG(1, ("chgpasswd: Username does not exist in system !\n")); - return False; - } - if (!oldpass) { oldpass = ""; } @@ -471,13 +468,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL #endif /* Take the passed information and test it for minimum criteria */ - /* Minimum password length */ - if (strlen(newpass) < lp_min_passwd_length()) { - /* too short, must be at least MINPASSWDLENGTH */ - DEBUG(0, ("chgpasswd: Password Change: user %s, New password is shorter than minimum password length = %d\n", - name, lp_min_passwd_length())); - return (False); /* inform the user */ - } /* Password is same as old password */ if (strcmp(oldpass, newpass) == 0) { @@ -570,7 +560,8 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, BOOL as_root) { DEBUG(0, ("chgpasswd: Password changing not compiled in (user=%s)\n", name)); return (False); @@ -909,6 +900,8 @@ static NTSTATUS check_oem_password(const char *user, NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { + struct passwd *pass; + BOOL ret; uint32 min_len; @@ -936,7 +929,47 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw /* return NT_STATUS_PWD_TOO_SHORT; */ } - /* TODO: Add cracklib support here */ + pass = Get_Pwnam(pdb_get_username(hnd)); + if (!pass) { + DEBUG(1, ("check_oem_password: Username does not exist in system !?!\n")); + } + +#ifdef HAVE_WORKING_CRACKLIB + if (pass) { + /* if we can, become the user to overcome internal cracklib sillyness */ + if (!push_sec_ctx()) + return NT_STATUS_UNSUCCESSFUL; + + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); + set_re_uid(); + } + + if (lp_use_cracklib()) { + const char *crack_check_reason; + DEBUG(4, ("change_oem_password: Checking password for user [%s]" + " against cracklib. \n", pdb_get_username(hnd))); + DEBUGADD(4, ("If this is your last message, then something is " + "wrong with cracklib, it might be missing it's " + "dictionaries at %s\n", + CRACKLIB_DICTPATH)); + dbgflush(); + + crack_check_reason = FascistCheck(new_passwd, (char *)CRACKLIB_DICTPATH); + if (crack_check_reason) { + DEBUG(1, ("Password Change: user [%s], " + "New password failed cracklib test - %s\n", + pdb_get_username(hnd), crack_check_reason)); + + /* get back to where we should be */ + if (pass) + pop_sec_ctx(); + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + + if (pass) + pop_sec_ctx(); +#endif /* * If unix password sync was requested, attempt to change @@ -951,7 +984,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw */ if(lp_unix_password_sync() && - !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) { + !chgpasswd(pdb_get_username(hnd), pass, old_passwd, new_passwd, as_root)) { return NT_STATUS_ACCESS_DENIED; } -- cgit From f203358fdb456c6b4626324ef47698d0ccdc08a5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 12 Jan 2004 21:12:47 +0000 Subject: On systems without a working cracklib, ensure we don't include the header (the actual call to crack was already in this #ifdef) Andrew Bartlett (This used to be commit 4a01f3dbb4a2e744b48bdb86c4d91ee4692d38e5) --- source3/smbd/chgpasswd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 07def7549e..692e82680d 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -49,6 +49,7 @@ #include "includes.h" +#ifdef HAVE_WORKING_CRACKLIB #include #ifndef HAVE_CRACKLIB_DICTPATH @@ -56,6 +57,7 @@ #define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH #endif #endif +#endif extern struct passdb_ops pdb_ops; -- cgit From 1dce4ebed861a6dfbd19da20601d92bc9be3484a Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 14 Jan 2004 17:34:41 +0000 Subject: revert the cracklib changes until post 3.0.2 (This used to be commit 6202e0fa727a4307f51bf42f5ced401a7c7b8214) --- source3/smbd/chgpasswd.c | 81 ++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 58 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 692e82680d..e6117245e7 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -49,16 +49,6 @@ #include "includes.h" -#ifdef HAVE_WORKING_CRACKLIB -#include - -#ifndef HAVE_CRACKLIB_DICTPATH -#ifndef CRACKLIB_DICTPATH -#define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH -#endif -#endif -#endif - extern struct passdb_ops pdb_ops; static NTSTATUS check_oem_password(const char *user, @@ -451,14 +441,25 @@ while we were waiting\n", WTERMSIG(wstat))); return (chstat); } -BOOL chgpasswd(const char *name, const struct passwd *pass, - const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; size_t i; size_t len; + struct passwd *pass; + + if (!name) { + DEBUG(1, ("chgpasswd: NULL username specfied !\n")); + } + + pass = Get_Pwnam(name); + if (!pass) { + DEBUG(1, ("chgpasswd: Username does not exist in system !\n")); + return False; + } + if (!oldpass) { oldpass = ""; } @@ -470,6 +471,13 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, #endif /* Take the passed information and test it for minimum criteria */ + /* Minimum password length */ + if (strlen(newpass) < lp_min_passwd_length()) { + /* too short, must be at least MINPASSWDLENGTH */ + DEBUG(0, ("chgpasswd: Password Change: user %s, New password is shorter than minimum password length = %d\n", + name, lp_min_passwd_length())); + return (False); /* inform the user */ + } /* Password is same as old password */ if (strcmp(oldpass, newpass) == 0) { @@ -562,8 +570,7 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(const char *name, const struct passwd *pass, - const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { DEBUG(0, ("chgpasswd: Password changing not compiled in (user=%s)\n", name)); return (False); @@ -902,8 +909,6 @@ static NTSTATUS check_oem_password(const char *user, NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { - struct passwd *pass; - BOOL ret; uint32 min_len; @@ -931,47 +936,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw /* return NT_STATUS_PWD_TOO_SHORT; */ } - pass = Get_Pwnam(pdb_get_username(hnd)); - if (!pass) { - DEBUG(1, ("check_oem_password: Username does not exist in system !?!\n")); - } - -#ifdef HAVE_WORKING_CRACKLIB - if (pass) { - /* if we can, become the user to overcome internal cracklib sillyness */ - if (!push_sec_ctx()) - return NT_STATUS_UNSUCCESSFUL; - - set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); - set_re_uid(); - } - - if (lp_use_cracklib()) { - const char *crack_check_reason; - DEBUG(4, ("change_oem_password: Checking password for user [%s]" - " against cracklib. \n", pdb_get_username(hnd))); - DEBUGADD(4, ("If this is your last message, then something is " - "wrong with cracklib, it might be missing it's " - "dictionaries at %s\n", - CRACKLIB_DICTPATH)); - dbgflush(); - - crack_check_reason = FascistCheck(new_passwd, (char *)CRACKLIB_DICTPATH); - if (crack_check_reason) { - DEBUG(1, ("Password Change: user [%s], " - "New password failed cracklib test - %s\n", - pdb_get_username(hnd), crack_check_reason)); - - /* get back to where we should be */ - if (pass) - pop_sec_ctx(); - return NT_STATUS_PASSWORD_RESTRICTION; - } - } - - if (pass) - pop_sec_ctx(); -#endif + /* TODO: Add cracklib support here */ /* * If unix password sync was requested, attempt to change @@ -986,7 +951,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw */ if(lp_unix_password_sync() && - !chgpasswd(pdb_get_username(hnd), pass, old_passwd, new_passwd, as_root)) { + !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) { return NT_STATUS_ACCESS_DENIED; } -- cgit From 9343c89cb4a1b9f47c38d00b12f3e9058d15b18d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Jan 2004 08:49:30 +0000 Subject: * Fix XFS quotas: XFS_USER_QUOTA -> USRQUOTA XFS_GROUP_QUOTA -> GRPQUOTA * Fix disk_free calculation with group quotas. * Add debug class 'quota' and a lot of DEBUG()'s to the quota code. metze (This used to be commit e9e5e2036f13ff847aa3ef52e8be657bef7d5774) --- source3/smbd/ntquotas.c | 3 +++ source3/smbd/quotas.c | 17 +++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 88d7c4e164..555f32d773 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -20,6 +20,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_QUOTA + static SMB_BIG_UINT limit_nt2unix(SMB_BIG_UINT in, SMB_BIG_UINT bsize) { SMB_BIG_UINT ret = (SMB_BIG_UINT)0; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 19f225e973..c0b2db6173 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -27,6 +27,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_QUOTA + #ifndef HAVE_SYS_QUOTAS /* just a quick hack because sysquotas.h is included before linux/quota.h */ @@ -82,10 +85,10 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LI ZERO_STRUCT(D); - ret = quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), path, euser_id, (caddr_t)&D); + ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); if (ret) - ret = quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), path, egrp_id, (caddr_t)&D); + ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); if (ret) return ret; @@ -1195,7 +1198,8 @@ BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BI unid_t id; id.uid = geteuid(); - + + ZERO_STRUCT(D); r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D); /* Use softlimit to determine disk space, except when it has been exceeded */ @@ -1231,9 +1235,9 @@ BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BI return True; try_group_quota: -#ifdef HAVE_GROUP_QUOTA id.gid = getegid(); - + + ZERO_STRUCT(D); r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D); /* Use softlimit to determine disk space, except when it has been exceeded */ @@ -1267,8 +1271,5 @@ try_group_quota: } return (True); -#else /* HAVE_GROUP_QUOTA */ - return False; -#endif /* HAVE_GROUP_QUOTA */ } #endif /* HAVE_SYS_QUOTAS */ -- cgit From 55d6877f0f9708c80aeb94d1d145441833cb26b9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 15 Jan 2004 17:17:58 +0000 Subject: reply_spnego_kerberos did not set the domain of the user handed to register_vuid correctly. We ended up with the local netbios name in substitutions for %D later. Volker P.S: Tridge, I can *really* see why you want to get rid of global variables :-) (This used to be commit 3d9931fe291559a907c3e172a66fbce1155497a3) --- source3/smbd/sesssetup.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 80be9da53b..9405c065e1 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -262,6 +262,13 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(ret); } + /* make_server_info_pw does not set the domain. Without this we end up + * with the local netbios name in substitutions for %D. */ + + if (server_info->sam_account != NULL) { + pdb_set_domain(server_info->sam_account, domain, PDB_SET); + } + /* register_vuid keeps the server info */ sess_vuid = register_vuid(server_info, session_key, nullblob, client); -- cgit From c26e4057ae1ada769555079738f09f9cea1614b9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 26 Jan 2004 02:19:44 +0000 Subject: Patch by Luca Bolcioni . Ensure we always initialise the session key. Fixes segfaults with security=server, and encrypt passwords = no. Andrew Bartlett (This used to be commit 493ac5ce98fa3fcddb596139240dd762e70d4ac3) --- source3/smbd/sesssetup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9405c065e1..c42a35e809 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -876,6 +876,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, session_key = data_blob(NULL, 16); SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data, session_key.data); + } else { + session_key = data_blob(NULL, 0); } data_blob_free(&lm_resp); -- cgit From 36abff1609ad7f537494d08c321c0bf853d6ca9e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 26 Jan 2004 09:03:09 +0000 Subject: Revise our server-side password change code to cope with the various different feilds that different clients send. (For example, not all clients send both password types). This also cleans up the code to make it clearer what is really going on, and to make better use of common functions. Andrew Bartlett (This used to be commit 934e9f3bd0e8a938263978ffcd1fef51e42fa5e4) --- source3/smbd/chgpasswd.c | 267 ++++++++++++++++++++++++++++------------------- 1 file changed, 158 insertions(+), 109 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e6117245e7..a452575af3 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Andrew Bartlett 2001-2002 + Copyright (C) Andrew Bartlett 2001-2004 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 @@ -19,6 +19,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* These comments regard the code to change the user's unix password: */ + /* fork a child process to exec passwd and write to its * tty to change a users password. This is running as the * user who is attempting to change the password. @@ -30,9 +32,6 @@ * was included as a client to change passwords using the 'passwd' program * on the remote machine. * - * This routine is called by set_user_password() in password.c only if ALLOW_PASSWORD_CHANGE - * is defined in the compiler directives located in the Makefile. - * * This code has been hacked by Bob Nance (nance@niehs.nih.gov) and Evan Patterson * (patters2@niehs.nih.gov) at the National Institute of Environmental Health Sciences * and rights to modify, distribute or incorporate this change to the CAP suite or @@ -52,10 +51,12 @@ extern struct passdb_ops pdb_ops; static NTSTATUS check_oem_password(const char *user, - uchar * lmdata, const uchar * lmhash, - const uchar * ntdata, const uchar * nthash, - SAM_ACCOUNT **hnd, char *new_passwd, - int new_passwd_size); + uchar password_encrypted_with_lm_hash[516], + const uchar old_lm_hash_encrypted[16], + uchar password_encrypted_with_nt_hash[516], + const uchar old_nt_hash_encrypted[16], + SAM_ACCOUNT **hnd, char *new_passwd, + int new_passwd_size); #if ALLOW_CHANGE_PASSWORD @@ -572,7 +573,7 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { - DEBUG(0, ("chgpasswd: Password changing not compiled in (user=%s)\n", name)); + DEBUG(0, ("chgpasswd: Unix Password changing not compiled in (user=%s)\n", name)); return (False); } #endif /* ALLOW_CHANGE_PASSWORD */ @@ -712,14 +713,19 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) ************************************************************/ NTSTATUS pass_oem_change(char *user, - uchar * lmdata, uchar * lmhash, - uchar * ntdata, uchar * nthash) + uchar password_encrypted_with_lm_hash[516], + const uchar old_lm_hash_encrypted[16], + uchar password_encrypted_with_nt_hash[516], + const uchar old_nt_hash_encrypted[16]) { - fstring new_passwd; + pstring new_passwd; SAM_ACCOUNT *sampass = NULL; - NTSTATUS nt_status = check_oem_password(user, lmdata, lmhash, ntdata, nthash, - &sampass, new_passwd, sizeof(new_passwd)); - + NTSTATUS nt_status = check_oem_password(user, password_encrypted_with_lm_hash, + old_lm_hash_encrypted, + password_encrypted_with_nt_hash, + old_nt_hash_encrypted, + &sampass, new_passwd, sizeof(new_passwd)); + if (!NT_STATUS_IS_OK(nt_status)) return nt_status; @@ -736,33 +742,42 @@ NTSTATUS pass_oem_change(char *user, } /*********************************************************** - Code to check the OEM hashed password. + Decrypt and verify a user password change. - this function ignores the 516 byte nt OEM hashed password - but does use the lm OEM password to check the nt hashed-hash. + The 516 byte long buffers are encrypted with the old NT and + old LM passwords, and if the NT passwords are present, both + buffers contain a unicode string. + After decrypting the buffers, check the password is correct by + matching the old hashed passwords with the passwords in the passdb. + ************************************************************/ static NTSTATUS check_oem_password(const char *user, - uchar * lmdata, const uchar * lmhash, - const uchar * ntdata, const uchar * nthash, - SAM_ACCOUNT **hnd, char *new_passwd, - int new_passwd_size) + uchar password_encrypted_with_lm_hash[516], + const uchar old_lm_hash_encrypted[16], + uchar password_encrypted_with_nt_hash[516], + const uchar old_nt_hash_encrypted[16], + SAM_ACCOUNT **hnd, char *new_passwd, + int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; SAM_ACCOUNT *sampass = NULL; + char *password_encrypted; + const char *encryption_key; const uint8 *lanman_pw, *nt_pw; uint16 acct_ctrl; - int new_pw_len; - uchar new_ntp16[16]; - uchar unenc_old_ntpw[16]; - uchar new_p16[16]; - uchar unenc_old_pw[16]; + uint32 new_pw_len; + uchar new_nt_hash[16]; + uchar old_nt_hash_plain[16]; + uchar new_lm_hash[16]; + uchar old_lm_hash_plain[16]; char no_pw[2]; BOOL ret; - BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); + BOOL nt_pass_set = (password_encrypted_with_nt_hash && old_nt_hash_encrypted); + BOOL lm_pass_set = (password_encrypted_with_lm_hash && old_lm_hash_encrypted); *hnd = NULL; @@ -775,97 +790,152 @@ static NTSTATUS check_oem_password(const char *user, if (ret == False) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); pdb_free_sam(&sampass); - return NT_STATUS_WRONG_PASSWORD; - /* - TODO: check what Win2k returns for this: - return NT_STATUS_NO_SUCH_USER; - */ + return NT_STATUS_NO_SUCH_USER; } acct_ctrl = pdb_get_acct_ctrl(sampass); if (acct_ctrl & ACB_DISABLED) { - DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + DEBUG(2,("check_lanman_password: account %s disabled.\n", user)); pdb_free_sam(&sampass); return NT_STATUS_ACCOUNT_DISABLED; } - /* construct a null password (in case one is needed */ - no_pw[0] = 0; - no_pw[1] = 0; - nt_lm_owf_gen(no_pw, null_ntpw, null_pw); - - /* save pointers to passwords so we don't have to keep looking them up */ - lanman_pw = pdb_get_lanman_passwd(sampass); - nt_pw = pdb_get_nt_passwd(sampass); + if (acct_ctrl & ACB_PWNOTREQ && lp_null_passwords()) { + /* construct a null password (in case one is needed */ + no_pw[0] = 0; + no_pw[1] = 0; + nt_lm_owf_gen(no_pw, null_ntpw, null_pw); + lanman_pw = null_pw; + nt_pw = null_pw; - /* check for null passwords */ - if (lanman_pw == NULL) { - if (!(acct_ctrl & ACB_PWNOTREQ)) { - DEBUG(0,("check_oem_password: no lanman password !\n")); - pdb_free_sam(&sampass); - return NT_STATUS_WRONG_PASSWORD; + } else { + /* save pointers to passwords so we don't have to keep looking them up */ + if (lp_lanman_auth()) { + lanman_pw = pdb_get_lanman_passwd(sampass); + } else { + lanman_pw = NULL; } + nt_pw = pdb_get_nt_passwd(sampass); } - - if (pdb_get_nt_passwd(sampass) == NULL && nt_pass_set) { - if (!(acct_ctrl & ACB_PWNOTREQ)) { - DEBUG(0,("check_oem_password: no ntlm password !\n")); - pdb_free_sam(&sampass); - return NT_STATUS_WRONG_PASSWORD; - } + + if (nt_pw && nt_pass_set) { + /* IDEAL Case: passwords are in unicode, and we can + * read use the password encrypted with the NT hash + */ + password_encrypted = password_encrypted_with_nt_hash; + encryption_key = nt_pw; + } else if (lanman_pw && lm_pass_set) { + /* password may still be in unicode, but use LM hash version */ + password_encrypted = password_encrypted_with_lm_hash; + encryption_key = lanman_pw; + } else if (nt_pass_set) { + DEBUG(1, ("NT password change supplied for user %s, but we have no NT password to check it with\n", + user)); + pdb_free_sam(&sampass); + return NT_STATUS_WRONG_PASSWORD; + } else if (lm_pass_set) { + DEBUG(1, ("LM password change supplied for user %s, but we have no LanMan password to check it with\n", + user)); + pdb_free_sam(&sampass); + return NT_STATUS_WRONG_PASSWORD; + } else { + DEBUG(1, ("password change requested for user %s, but no password supplied!\n", + user)); + pdb_free_sam(&sampass); + return NT_STATUS_WRONG_PASSWORD; } - - /* - * Call the hash function to get the new password. - */ - SamOEMhash( lmdata, lanman_pw, 516); /* - * The length of the new password is in the last 4 bytes of - * the data buffer. + * Decrypt the password with the key */ + SamOEMhash( password_encrypted, encryption_key, 516); - new_pw_len = IVAL(lmdata, 512); - - if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); + if ( !decode_pw_buffer(password_encrypted, new_passwd, new_passwd_size, &new_pw_len, + nt_pass_set ? STR_UNICODE : STR_ASCII)) { pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } - if (nt_pass_set) { - /* - * nt passwords are in unicode - */ - pull_ucs2(NULL, new_passwd, - (const smb_ucs2_t *)&lmdata[512 - new_pw_len], - new_passwd_size, new_pw_len, 0); - } else { - memcpy(new_passwd, &lmdata[512 - new_pw_len], new_pw_len); - new_passwd[new_pw_len] = 0; - } - /* * To ensure we got the correct new password, hash it and * use it as a key to test the passed old password. */ - nt_lm_owf_gen(new_passwd, new_ntp16, new_p16); + if (nt_pass_set) { + /* NT passwords, verify the NT hash. */ + + /* Calculate the MD4 hash (NT compatible) of the password */ + memset(new_nt_hash, '\0', 16); + E_md4hash(new_passwd, new_nt_hash); + + if (nt_pw) { + /* + * Now use new_nt_hash as the key to see if the old + * password matches. + */ + D_P16(new_nt_hash, old_nt_hash_encrypted, old_nt_hash_plain); + + if (memcmp(nt_pw, old_nt_hash_plain, 16)) { + DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + pdb_free_sam(&sampass); + return NT_STATUS_WRONG_PASSWORD; + } + + /* We could check the LM password here, but there is + * little point, we already know the password is + * correct, and the LM password might not even be + * present. */ + + /* Further, LM hash generation algorithms + * differ with charset, so we could + * incorrectly fail a perfectly valid password + * change */ +#ifdef DEBUG_PASSWORD + DEBUG(100, + ("check_oem_password: password %s ok\n", new_passwd)); +#endif + *hnd = sampass; + return NT_STATUS_OK; + } + + if (lanman_pw) { + /* + * Now use new_nt_hash as the key to see if the old + * LM password matches. + */ + D_P16(new_nt_hash, old_lm_hash_encrypted, old_lm_hash_plain); + + if (memcmp(lanman_pw, old_lm_hash_plain, 16)) { + DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); + pdb_free_sam(&sampass); + return NT_STATUS_WRONG_PASSWORD; + } +#ifdef DEBUG_PASSWORD + DEBUG(100, + ("check_oem_password: password %s ok\n", new_passwd)); +#endif + *hnd = sampass; + return NT_STATUS_OK; + } + } + + if (lanman_pw && lm_pass_set) { + + E_deshash(new_passwd, new_lm_hash); - if (!nt_pass_set) { /* - * Now use new_p16 as the key to see if the old + * Now use new_lm_hash as the key to see if the old * password matches. */ - D_P16(new_p16, lmhash, unenc_old_pw); - - if (memcmp(lanman_pw, unenc_old_pw, 16)) { + D_P16(new_lm_hash, old_lm_hash_encrypted, old_lm_hash_plain); + + if (memcmp(lanman_pw, old_lm_hash_plain, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } - + #ifdef DEBUG_PASSWORD DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); @@ -874,30 +944,9 @@ static NTSTATUS check_oem_password(const char *user, return NT_STATUS_OK; } - /* - * Now use new_p16 as the key to see if the old - * password matches. - */ - D_P16(new_ntp16, lmhash, unenc_old_pw); - D_P16(new_ntp16, nthash, unenc_old_ntpw); - - if (memcmp(lanman_pw, unenc_old_pw, 16)) { - DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); - pdb_free_sam(&sampass); - return NT_STATUS_WRONG_PASSWORD; - } - - if (memcmp(nt_pw, unenc_old_ntpw, 16)) { - DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); - pdb_free_sam(&sampass); - return NT_STATUS_WRONG_PASSWORD; - } -#ifdef DEBUG_PASSWORD - DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd)); -#endif - - *hnd = sampass; - return NT_STATUS_OK; + /* should not be reached */ + pdb_free_sam(&sampass); + return NT_STATUS_WRONG_PASSWORD; } /*********************************************************** -- cgit From f104d75026957981b944b52eb33f7947f4b42fb8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 27 Jan 2004 15:28:33 +0000 Subject: bug 977 - don't create a homes share for a user if a static share already exists by the same name (This used to be commit 6b89a76aa7efaa0ad7a0139aeb3e4ebf5c01cdcb) --- source3/smbd/password.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 494d9ecd43..36e3fb4738 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -254,7 +254,13 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { DEBUG(3, ("Adding/updating homes service for user '%s' using home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); - vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir); + + /* only add the home directory if there doesn't exist a static share by that name */ + if ( lp_servicenumber(vuser->user.unix_name) == -1 ) { + vuser->homes_snum = add_home_service(vuser->user.unix_name, + vuser->user.unix_name, vuser->unix_homedir); + } + } else { vuser->homes_snum = -1; } -- cgit From a0cefa62e68212165d41aebca4d807c3c38529f9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Jan 2004 23:41:55 +0000 Subject: Merge of Chris's fix. Jeremy. (This used to be commit 1a7714ea32300ba0e48f275addcf2e1f272a96ed) --- source3/smbd/lanman.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index c53889a7a4..c4df84e76c 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1465,12 +1465,24 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para } /**************************************************************************** - view list of shares available - ****************************************************************************/ -static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) + View the list of available shares. + + This function is the server side of the NetShareEnum() RAP call. + It fills the return buffer with share names and share comments. + Note that the return buffer normally (in all known cases) allows only + twelve byte strings for share names (plus one for a nul terminator). + Share names longer than 12 bytes must be skipped. + ****************************************************************************/ +static BOOL api_RNetShareEnum( connection_struct *conn, + uint16 vuid, + char *param, + char *data, + int mdrcnt, + int mprcnt, + char **rdata, + char **rparam, + int *rdata_len, + int *rparam_len ) { char *str1 = param+2; char *str2 = skip_string(str1,1); @@ -1490,7 +1502,9 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c data_len = fixed_len = string_len = 0; for (i=0;i Date: Sat, 31 Jan 2004 14:44:27 +0000 Subject: cleanup patch for bug 977 so we don't display incorrect debug messages (This used to be commit 11093ecfb7bab1ecb16d19ac00b3e7e38dff43e2) --- source3/smbd/password.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 36e3fb4738..10c6aadb1f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -250,17 +250,21 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, return -1; } - /* Register a home dir service for this user */ - if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { - DEBUG(3, ("Adding/updating homes service for user '%s' using home directory: '%s'\n", - vuser->user.unix_name, vuser->unix_homedir)); + /* Register a home dir service for this user iff + (a) This is not a guest connection, + (b) we have a home directory defined, and + (c) there s not an existing static share by that name */ + + if ( (!vuser->guest) + && vuser->unix_homedir + && *(vuser->unix_homedir) + && (lp_servicenumber(vuser->user.unix_name) == -1) ) + { + DEBUG(3, ("Adding/updating homes service for user '%s' using home directory: '%s'\n", + vuser->user.unix_name, vuser->unix_homedir)); - /* only add the home directory if there doesn't exist a static share by that name */ - if ( lp_servicenumber(vuser->user.unix_name) == -1 ) { vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir); - } - } else { vuser->homes_snum = -1; } -- cgit From 575bc995c0d6d1381c02deebc1c45c0fd644f1c2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 31 Jan 2004 18:25:57 +0000 Subject: * BUG 101: patch from j.lu@tiesse.com to set the SV_TYPE_PRINTQ_SERVER; * don't set the unix_ERR_XX code in mkdir_internal, let the error mapping handle it. (This used to be commit 87343fc15a385153c2205bd8bfe876504d38d9a1) --- source3/smbd/reply.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3752507493..c4ff77bd86 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3013,19 +3013,12 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret == -1) { - NTSTATUS nterr = NT_STATUS_OK; if(errno == ENOENT) { - unix_ERR_class = ERRDOS; - if (bad_path) { - unix_ERR_code = ERRbadpath; - nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } else { - unix_ERR_code = ERRbadfile; - nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + if (bad_path) + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + else + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (!NT_STATUS_IS_OK(nterr)) - return nterr; return map_nt_error_from_unix(errno); } -- cgit From 19cc1a9f202551fdaca39d67d926bb77e32d085c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 2 Feb 2004 00:08:35 +0000 Subject: remerge andrew's cracklib patch from HEAD and fix a compile warnings (This used to be commit b60f6ec30d05e4e5bba9934a416ddc8bc089824f) --- source3/smbd/chgpasswd.c | 81 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a452575af3..e3df8a11d0 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -48,6 +48,16 @@ #include "includes.h" +#ifdef HAVE_WORKING_CRACKLIB +#include + +#ifndef HAVE_CRACKLIB_DICTPATH +#ifndef CRACKLIB_DICTPATH +#define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH +#endif +#endif +#endif + extern struct passdb_ops pdb_ops; static NTSTATUS check_oem_password(const char *user, @@ -442,25 +452,14 @@ while we were waiting\n", WTERMSIG(wstat))); return (chstat); } -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; size_t i; size_t len; - struct passwd *pass; - - if (!name) { - DEBUG(1, ("chgpasswd: NULL username specfied !\n")); - } - - pass = Get_Pwnam(name); - if (!pass) { - DEBUG(1, ("chgpasswd: Username does not exist in system !\n")); - return False; - } - if (!oldpass) { oldpass = ""; } @@ -472,13 +471,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL #endif /* Take the passed information and test it for minimum criteria */ - /* Minimum password length */ - if (strlen(newpass) < lp_min_passwd_length()) { - /* too short, must be at least MINPASSWDLENGTH */ - DEBUG(0, ("chgpasswd: Password Change: user %s, New password is shorter than minimum password length = %d\n", - name, lp_min_passwd_length())); - return (False); /* inform the user */ - } /* Password is same as old password */ if (strcmp(oldpass, newpass) == 0) { @@ -571,7 +563,8 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, BOOL as_root) { DEBUG(0, ("chgpasswd: Unix Password changing not compiled in (user=%s)\n", name)); return (False); @@ -958,6 +951,8 @@ static NTSTATUS check_oem_password(const char *user, NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { + struct passwd *pass; + BOOL ret; uint32 min_len; @@ -985,7 +980,47 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw /* return NT_STATUS_PWD_TOO_SHORT; */ } - /* TODO: Add cracklib support here */ + pass = Get_Pwnam(pdb_get_username(hnd)); + if (!pass) { + DEBUG(1, ("check_oem_password: Username does not exist in system !?!\n")); + } + +#ifdef HAVE_WORKING_CRACKLIB + if (pass) { + /* if we can, become the user to overcome internal cracklib sillyness */ + if (!push_sec_ctx()) + return NT_STATUS_UNSUCCESSFUL; + + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); + set_re_uid(); + } + + if (lp_use_cracklib()) { + const char *crack_check_reason; + DEBUG(4, ("change_oem_password: Checking password for user [%s]" + " against cracklib. \n", pdb_get_username(hnd))); + DEBUGADD(4, ("If this is your last message, then something is " + "wrong with cracklib, it might be missing it's " + "dictionaries at %s\n", + CRACKLIB_DICTPATH)); + dbgflush(); + + crack_check_reason = FascistCheck(new_passwd, (char *)CRACKLIB_DICTPATH); + if (crack_check_reason) { + DEBUG(1, ("Password Change: user [%s], " + "New password failed cracklib test - %s\n", + pdb_get_username(hnd), crack_check_reason)); + + /* get back to where we should be */ + if (pass) + pop_sec_ctx(); + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + + if (pass) + pop_sec_ctx(); +#endif /* * If unix password sync was requested, attempt to change @@ -1000,7 +1035,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw */ if(lp_unix_password_sync() && - !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) { + !chgpasswd(pdb_get_username(hnd), pass, old_passwd, new_passwd, as_root)) { return NT_STATUS_ACCESS_DENIED; } -- cgit From ae2c8656b22ca855aaf1ab7382a92996b362a900 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 8 Feb 2004 07:17:30 +0000 Subject: Samba hasn't used this function for ages - it's now handled deep in the auth subsystem. Andrew Bartlett (This used to be commit 5693730594b1a861c7916cac7d156cf6a9d913cd) --- source3/smbd/uid.c | 69 ------------------------------------------------------ 1 file changed, 69 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 7979ffe854..09cf899522 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -369,72 +369,3 @@ BOOL unbecome_user(void) return True; } -/***************************************************************** - Convert the supplementary SIDs returned in a netlogon into UNIX - group gid_t's. Add to the total group array. -*****************************************************************/ - -void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER_TOKEN **pptok) -{ - int total_groups; - int current_n_groups = *n_groups; - gid_t *final_groups = NULL; - size_t i; - NT_USER_TOKEN *ptok = *pptok; - NT_USER_TOKEN *new_tok = NULL; - - if (!ptok || (ptok->num_sids == 0)) - return; - - new_tok = dup_nt_token(ptok); - if (!new_tok) { - DEBUG(0,("add_supplementary_nt_login_groups: Failed to malloc new token\n")); - return; - } - /* Leave the allocated space but empty the number of SIDs. */ - new_tok->num_sids = 0; - - total_groups = current_n_groups + ptok->num_sids; - - final_groups = (gid_t *)malloc(total_groups * sizeof(gid_t)); - if (!final_groups) { - DEBUG(0,("add_supplementary_nt_login_groups: Failed to malloc new groups.\n")); - delete_nt_token(&new_tok); - return; - } - - memcpy(final_groups, *pp_groups, current_n_groups * sizeof(gid_t)); - for (i = 0; i < ptok->num_sids; i++) { - gid_t new_grp; - - if (NT_STATUS_IS_OK(sid_to_gid(&ptok->user_sids[i], &new_grp))) { - /* - * Don't add the gid_t if it is already in the current group - * list. Some UNIXen don't like the same group more than once. - */ - int j; - - for (j = 0; j < current_n_groups; j++) - if (final_groups[j] == new_grp) - break; - - if ( j == current_n_groups) { - /* Group not already present. */ - final_groups[current_n_groups++] = new_grp; - } - } else { - /* SID didn't map. Copy to the new token to be saved. */ - sid_copy(&new_tok->user_sids[new_tok->num_sids++], &ptok->user_sids[i]); - } - } - - SAFE_FREE(*pp_groups); - *pp_groups = final_groups; - *n_groups = current_n_groups; - - /* Replace the old token with the truncated one. */ - delete_nt_token(&ptok); - *pptok = new_tok; -} - - -- cgit From d198c5587774808823aa09e997ff492826738c51 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 8 Feb 2004 08:38:42 +0000 Subject: Make more functions static, and remove duplication in the use of functions in lib/smbpasswd.c that were exact duplicates of functions in passdb/passdb.c (These should perhaps be pulled back out to smbpasswd.c, but that can occour later). Andrew Bartlett (This used to be commit fcdc5efb1e245c8fa95cd031f67ec56093b9056e) --- source3/smbd/nttrans.c | 5 +++-- source3/smbd/server.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 767df0b725..92629faa9e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -55,7 +55,7 @@ struct generic_mapping file_generic_mapping = { FILE_GENERIC_ALL }; -char *nttrans_realloc(char **ptr, size_t size) +static char *nttrans_realloc(char **ptr, size_t size) { char *tptr = NULL; if (ptr==NULL) @@ -2021,11 +2021,12 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, SMB_NTQUOTA_STRUCT qt; SMB_NTQUOTA_LIST *tmp_list; SMB_NTQUOTA_HANDLE *qt_handle = NULL; + extern struct current_user current_user; ZERO_STRUCT(qt); /* access check */ - if (conn->admin_user != True) { + if (current_user.uid != 0) { DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRDOS,ERRnoaccess); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e7aa41e343..26e4021443 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -145,7 +145,7 @@ static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) Have we reached the process limit ? ****************************************************************************/ -BOOL allowable_number_of_smbd_processes(void) +static BOOL allowable_number_of_smbd_processes(void) { int max_processes = lp_max_smbd_processes(); -- cgit From 8a547323d26a0350eb0a2bfc4d9ebeaade7baacc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 8 Feb 2004 11:00:25 +0000 Subject: More 'static' work. Andrew Bartlett (This used to be commit 25a09004e8a51eb3192adbb580239427bfee0ec9) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 26e4021443..e2ffe8cc9f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,7 +22,7 @@ #include "includes.h" -int am_parent = 1; +static int am_parent = 1; /* the last message the was processed */ int last_message = -1; -- cgit From 0f1dcf9839676aa6ae2d6121ed5233f8f4101384 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 8 Feb 2004 11:26:46 +0000 Subject: nsswitch/winbindd_util.c: add static smbd/uid.c: remove unused function Andrew Bartlett (This used to be commit ab25af0e18d883757775a85f005775a79a86dcc8) --- source3/smbd/uid.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 09cf899522..f3d9004dd9 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -310,17 +310,6 @@ static void pop_conn_ctx(void) ctx_p->vuid = UID_FIELD_INVALID; } -void init_conn_ctx(void) -{ - int i; - - /* Initialise connection context stack */ - for (i = 0; i < MAX_SEC_CTX_DEPTH; i++) { - conn_ctx_stack[i].conn = NULL; - conn_ctx_stack[i].vuid = UID_FIELD_INVALID; - } -} - /**************************************************************************** Temporarily become a root user. Must match with unbecome_root(). Saves and restores the connection context. -- cgit From df6d2db4ced5586320804950da58a62248db4d56 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 12 Feb 2004 05:24:02 +0000 Subject: merge from old APP_HEAD * remove corrupt tdb and shutdown (only for printing tdbs, connections, sessionid & locking) * decrement smbd counter in connections.tdb in smb_panic() * various Makefile hack to get things to link 'max smbd processes' looks like it might be broken. The counter KEY is not being set. Will look into that tomorrow. (This used to be commit 6e22c5da929b6d9a4e32dc704c83112b2ad8fcfd) --- source3/smbd/connection.c | 8 ++--- source3/smbd/server.c | 2 ++ source3/smbd/session.c | 4 +-- source3/smbd/tdbutil.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 source3/smbd/tdbutil.c (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5bb76eb3bd..a9ab142461 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -29,8 +29,8 @@ static TDB_CONTEXT *tdb; TDB_CONTEXT *conn_tdb_ctx(void) { if (!tdb) - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644); + tdb = tdb_open_ex(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644, smbd_tdb_log); return tdb; } @@ -131,8 +131,8 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti TDB_DATA kbuf, dbuf; if (!tdb) - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644); + tdb = tdb_open_ex(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644, smbd_tdb_log); if (!tdb) return False; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e2ffe8cc9f..be59e92cd7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -501,6 +501,7 @@ BOOL reload_services(BOOL test) return(ret); } + #if DUMP_CORE /******************************************************************* prepare to dump a core file - carefully! @@ -890,3 +891,4 @@ void build_options(BOOL screen); exit_server("normal exit"); return(0); } + diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 4d8826d332..a811a6e305 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -53,8 +53,8 @@ BOOL session_claim(user_struct *vuser) } if (!tdb) { - tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644); + tdb = tdb_open_ex(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644, smbd_tdb_log); if (!tdb) { DEBUG(1,("session_claim: failed to open sessionid tdb\n")); return False; diff --git a/source3/smbd/tdbutil.c b/source3/smbd/tdbutil.c new file mode 100644 index 0000000000..cafcde2037 --- /dev/null +++ b/source3/smbd/tdbutil.c @@ -0,0 +1,85 @@ +/* + Unix SMB/CIFS implementation. + Main SMB server routines + Copyright (C) Jeremy Allison 2003 + Copyright (C) Gerald (Jerry) Carter 2004 + + 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" + + +/********************************************************************** + logging function used by smbd to detect and remove corrupted tdb's +**********************************************************************/ + +void smbd_tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + BOOL decrement_smbd_count; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (!ptr || !*ptr) + return; + + DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); + + if (tdb->ecode == TDB_ERR_CORRUPT) { + int ret; + + DEBUG(0,("tdb_log: TDB %s is corrupt. Removing file and stopping this process.\n", + tdb->name )); + + become_root(); + ret = unlink(tdb->name); + if ( ret ) { + DEBUG(0,("ERROR: %s\n", strerror(errno))); + } + unbecome_root(); + + + /* if its not connections.tdb, then make sure we decrement the + smbd count. If connections.tdb is bad, there's nothing we + can do and everything will eventually shut down or clean + up anyways */ + + if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) + decrement_smbd_count = False; + else + decrement_smbd_count = True; + + /* now die */ + + smb_panic2("corrupt tdb\n", decrement_smbd_count ); + } + + if (tdb->ecode == TDB_ERR_IO) + { + if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) + decrement_smbd_count = False; + else + decrement_smbd_count = True; + + smb_panic2( "i/o error on tdb.\n", decrement_smbd_count ); + } + + SAFE_FREE(ptr); +} + -- cgit From b545a8de0a605edda11cab322dab0ad26b6cebd1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Feb 2004 19:05:25 +0000 Subject: Fixup the 'multiple-vuids' bugs. Jeremy. (This used to be commit f0f7a48327ba1808088bc8c4e5d48b5cbeaeb4e3) --- source3/smbd/conn.c | 10 ++++-- source3/smbd/service.c | 84 ++--------------------------------------------- source3/smbd/uid.c | 88 +++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 86 insertions(+), 96 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 289b7d611d..9bac0acdb9 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -199,8 +199,9 @@ BOOL conn_idle_all(time_t t, int deadtime) } /**************************************************************************** -clear a vuid out of the validity cache, and as the 'owner' of a connection. + Clear a vuid out of the validity cache, and as the 'owner' of a connection. ****************************************************************************/ + void conn_clear_vuid_cache(uint16 vuid) { connection_struct *conn; @@ -212,8 +213,11 @@ void conn_clear_vuid_cache(uint16 vuid) } for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { - if (conn->vuid_cache.list[i] == vuid) { - conn->vuid_cache.list[i] = UID_FIELD_INVALID; + if (conn->vuid_cache.array[i].vuid == vuid) { + struct vuid_cache_entry *ent = &conn->vuid_cache.array[i]; + ent->vuid = UID_FIELD_INVALID; + ent->read_only = False; + ent->admin_user = False; } } } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e5655bd9f4..78b610ae37 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -259,78 +259,6 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } -/**************************************************************************** - readonly share? -****************************************************************************/ - -static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_groups) -{ - char **list; - const char *service = lp_servicename(conn->service); - conn->read_only = lp_readonly(conn->service); - - if (!service) - return; - - str_list_copy(&list, lp_readlist(conn->service)); - if (list) { - if (!str_list_sub_basic(list, current_user_info.smb_name) ) { - DEBUG(0, ("ERROR: read list substitution failed\n")); - } - if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("ERROR: read list service substitution failed\n")); - } - if (user_in_list(conn->user, (const char **)list, groups, n_groups)) - conn->read_only = True; - str_list_free(&list); - } - - str_list_copy(&list, lp_writelist(conn->service)); - if (list) { - if (!str_list_sub_basic(list, current_user_info.smb_name) ) { - DEBUG(0, ("ERROR: write list substitution failed\n")); - } - if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("ERROR: write list service substitution failed\n")); - } - if (user_in_list(conn->user, (const char **)list, groups, n_groups)) - conn->read_only = False; - str_list_free(&list); - } -} - -/**************************************************************************** - admin user check -****************************************************************************/ - -static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_groups) -{ - /* admin user check */ - - /* JRA - original code denied admin user if the share was - marked read_only. Changed as I don't think this is needed, - but old code left in case there is a problem here. - */ - if (user_in_list(conn->user,lp_admin_users(conn->service), groups, n_groups) -#if 0 - && !conn->read_only -#endif - ) { - conn->admin_user = True; - conn->force_user = True; /* Admin users are effectivly 'forced' */ - DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user)); - } else { - conn->admin_user = False; - } - -#if 0 /* This done later, for now */ - /* admin users always run as uid=0 */ - if (conn->admin_user) { - conn->uid = 0; - } -#endif -} - /**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the connecting user if appropriate. @@ -443,10 +371,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, string_set(&conn->dirpath,""); string_set(&conn->user,user); conn->nt_user_token = NULL; - - set_read_only(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0); - - set_admin_user(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0); + + conn->read_only = lp_readonly(conn->service); + conn->admin_user = False; /* * If force user is true, then store the @@ -478,11 +405,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } } - /* admin users always run as uid=0 */ - if (conn->admin_user) { - conn->uid = 0; - } - #ifdef HAVE_GETGRNAM /* * If force group is true, then override diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index f3d9004dd9..3859298055 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -54,33 +54,97 @@ BOOL change_to_guest(void) return True; } +/**************************************************************************** + Readonly share for this user ? +****************************************************************************/ + +static BOOL is_share_read_only_for_user(connection_struct *conn, user_struct *vuser) +{ + char **list; + const char *service = lp_servicename(conn->service); + BOOL read_only_ret = lp_readonly(conn->service); + + if (!service) + return read_only_ret; + + str_list_copy(&list, lp_readlist(conn->service)); + if (list) { + if (!str_list_sub_basic(list, vuser->user.smb_name) ) { + DEBUG(0, ("is_share_read_only_for_user: ERROR: read list substitution failed\n")); + } + if (!str_list_substitute(list, "%S", service)) { + DEBUG(0, ("is_share_read_only_for_user: ERROR: read list service substitution failed\n")); + } + if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) { + read_only_ret = True; + } + str_list_free(&list); + } + + str_list_copy(&list, lp_writelist(conn->service)); + if (list) { + if (!str_list_sub_basic(list, vuser->user.smb_name) ) { + DEBUG(0, ("is_share_read_only_for_user: ERROR: write list substitution failed\n")); + } + if (!str_list_substitute(list, "%S", service)) { + DEBUG(0, ("is_share_read_only_for_user: ERROR: write list service substitution failed\n")); + } + if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) { + read_only_ret = False; + } + str_list_free(&list); + } + + DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user %s\n", + service, read_only_ret ? "read-only" : "read-write", vuser->user.unix_name )); + + return read_only_ret; +} + /******************************************************************* Check if a username is OK. ********************************************************************/ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { - unsigned i; - for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) - if (conn->vuid_cache.list[i] == vuser->vuid) + unsigned int i; + struct vuid_cache_entry *ent = NULL; + BOOL readonly_share; + + for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { + if (conn->vuid_cache.array[i].vuid == vuser->vuid) { + ent = &conn->vuid_cache.array[i]; + conn->read_only = ent->read_only; + conn->admin_user = ent->admin_user; return(True); - - if ((conn->force_user || conn->force_group) - && (conn->vuid != vuser->vuid)) { - return False; + } } - + if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups)) return(False); - if (!share_access_check(conn, snum, vuser, conn->read_only ? FILE_READ_DATA : FILE_WRITE_DATA)) { + readonly_share = is_share_read_only_for_user(conn, vuser); + + if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { return False; } i = conn->vuid_cache.entries % VUID_CACHE_SIZE; - conn->vuid_cache.list[i] = vuser->vuid; + if (conn->vuid_cache.entries < VUID_CACHE_SIZE) + conn->vuid_cache.entries++; + + ent = &conn->vuid_cache.array[i]; + ent->vuid = vuser->vuid; + ent->read_only = readonly_share; + + if (user_in_list(vuser->user.unix_name ,lp_admin_users(conn->service), vuser->groups, vuser->n_groups)) { + ent->admin_user = True; + } else { + ent->admin_user = False; + } - conn->vuid_cache.entries++; + conn->read_only = ent->read_only; + conn->admin_user = ent->admin_user; return(True); } @@ -132,7 +196,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) current_user.ngroups = conn->ngroups; token = conn->nt_user_token; } else if ((vuser) && check_user_ok(conn, vuser, snum)) { - uid = vuser->uid; + uid = conn->admin_user ? 0 : vuser->uid; gid = vuser->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; -- cgit From 8eec62ebfb238133d95d7247b7126292f47c7093 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Feb 2004 01:55:24 +0000 Subject: Fix the "too many fcntl locks" scalability problem raised by tridge. I've now tested this in daemon mode and also on xinetd and I'm pretty sure it's working. Jeremy. (This used to be commit 14dee038019b11300466b148c53515fc76e5e870) --- source3/smbd/server.c | 34 ++++++++++++++++++++-------------- source3/smbd/session.c | 29 +++++++++++++++++++---------- 2 files changed, 39 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index be59e92cd7..1de33739b2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -405,10 +405,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ done correctly in the process. */ reset_globals_after_fork(); - /* tdb needs special fork handling */ + /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */ if (tdb_reopen_all() == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); - return False; + smb_panic("tdb_reopen_all failed."); } return True; @@ -809,9 +809,27 @@ void build_options(BOOL screen); if (is_daemon) pidfile_create("smbd"); + /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (!message_init()) exit(1); + if (!session_init()) + exit(1); + + if (conn_tdb_ctx() == NULL) + exit(1); + + if (!locking_init(0)) + exit(1); + + if (!share_info_db_init()) + exit(1); + + namecache_enable(); + + if (!init_registry()) + exit(1); + if (!print_backend_init()) exit(1); @@ -832,17 +850,6 @@ void build_options(BOOL screen); * everything after this point is run after the fork() */ - namecache_enable(); - - if (!locking_init(0)) - exit(1); - - if (!share_info_db_init()) - exit(1); - - if (!init_registry()) - exit(1); - /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ @@ -891,4 +898,3 @@ void build_options(BOOL screen); exit_server("normal exit"); return(0); } - diff --git a/source3/smbd/session.c b/source3/smbd/session.c index a811a6e305..61118f13dd 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -28,6 +28,22 @@ #include "includes.h" static TDB_CONTEXT *tdb; + +BOOL session_init(void) +{ + if (tdb) + return True; + + tdb = tdb_open_ex(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644, smbd_tdb_log); + if (!tdb) { + DEBUG(1,("session_init: failed to open sessionid tdb\n")); + return False; + } + + return True; +} + /* called when a session is created */ BOOL session_claim(user_struct *vuser) { @@ -52,14 +68,8 @@ BOOL session_claim(user_struct *vuser) return True; } - if (!tdb) { - tdb = tdb_open_ex(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644, smbd_tdb_log); - if (!tdb) { - DEBUG(1,("session_claim: failed to open sessionid tdb\n")); - return False; - } - } + if (!session_init()) + return False; ZERO_STRUCT(sessionid); @@ -190,7 +200,7 @@ void session_yield(user_struct *vuser) static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state) { - if (!tdb) { + if (!session_init()) { DEBUG(3, ("No tdb opened\n")); return False; } @@ -238,4 +248,3 @@ int list_sessions(struct sessionid **session_list) *session_list = sesslist.sessions; return sesslist.count; } - -- cgit From 7d7849b18a625820b1fba05bd17a718c7f98837e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Feb 2004 22:45:53 +0000 Subject: Make us bug-for-bug compatible with W2K3 - to get delete on close semantics on an initial open the desired_access field *must* contain DELETE_ACCESS, simply having it map from a GENERIC_ALL won't do. Fixes delete on close test. Jeremy. (This used to be commit 5c6f8b1053fd1f170fbb76640649653f8aa80f18) --- source3/smbd/nttrans.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 92629faa9e..3127134458 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -353,6 +353,7 @@ static int map_share_mode( char *fname, uint32 create_options, uint32 *desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode = -1; + uint32 original_desired_access = *desired_access; /* * Convert GENERIC bits to specific bits. @@ -424,6 +425,10 @@ static int map_share_mode( char *fname, uint32 create_options, DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode)); } + if(*desired_access & DELETE_ACCESS) { + DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); + } + /* * We need to store the intent to open for Delete. This * is what determines if a delete on close flag can be set. @@ -431,11 +436,19 @@ static int map_share_mode( char *fname, uint32 create_options, * is the only practical way. JRA. */ - if(*desired_access & DELETE_ACCESS) { - DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); - } - if (create_options & FILE_DELETE_ON_CLOSE) { + /* + * W2K3 bug compatibility mode... To set delete on close + * the redirector must have *specifically* set DELETE_ACCESS + * in the desired_access field. Just asking for GENERIC_ALL won't do. JRA. + */ + + if (!(original_desired_access & DELETE_ACCESS)) { + DEBUG(5,("map_share_mode: FILE_DELETE_ON_CLOSE requested without \ +DELETE_ACCESS for file %s. (desired_access = 0x%lx)\n", + fname, (unsigned long)*desired_access)); + return -1; + } /* Implicit delete access is *NOT* requested... */ smb_open_mode |= DELETE_ON_CLOSE_FLAG; DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode)); @@ -738,7 +751,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib share_access, file_attributes)) == -1) { END_PROFILE(SMBntcreateX); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -1267,7 +1280,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if((smb_open_mode = map_share_mode( fname, create_options, &desired_access, share_access, file_attributes)) == -1) - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; -- cgit From ef8f8274492c142765a94cc453d3da640c9fef91 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Feb 2004 23:19:39 +0000 Subject: Make SMB_FILE_ACCESS_INFORMATION call work correctly. Jeremy. (This used to be commit 0ea0ada6c609e1bb0fb4aace24e1beb7197495b5) --- source3/smbd/trans2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 525b015379..605169277d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1841,6 +1841,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, int len; time_t c_time; files_struct *fsp = NULL; + uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -1904,6 +1905,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } pos = fsp->position_information; delete_pending = fsp->delete_on_close; + desired_access = fsp->desired_access; } } else { /* qpathinfo */ @@ -2152,7 +2154,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_FILE_ACCESS_INFORMATION: - SIVAL(pdata,0,0x12019F); /* ??? */ + SIVAL(pdata,0,desired_access); data_size = 4; break; -- cgit From 13dd3e60bdf9ea799a1c56ca7467f323922e636d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Feb 2004 00:03:18 +0000 Subject: Fixup correct timeout values for blocking lock timeouts (tested at connectathon by Herb). Jeremy. (This used to be commit b38b3a554221a234127c740e6432048e69b7f5a3) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c4ff77bd86..ee47485126 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4288,7 +4288,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); /* Setup the timeout in seconds. */ - lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500); + lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000); /* Now do any requested locks */ data += ((large_file_format ? 20 : 10)*num_ulocks); -- cgit From b88f446352b27d71a71d61a7151694c468cfe609 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Feb 2004 00:06:08 +0000 Subject: Added NTrename SMB (0xA5) - how did we miss this.... ? Jeremy. (This used to be commit dfd7d1c2b7b577a084a94926abfce82c91f20b7e) --- source3/smbd/nttrans.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/process.c | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3127134458..2831f75933 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1488,6 +1488,56 @@ int reply_ntcancel(connection_struct *conn, return(-1); } +/**************************************************************************** + Reply to a NT rename request. +****************************************************************************/ + +int reply_ntrename(connection_struct *conn, + char *inbuf,char *outbuf,int length,int bufsize) +{ + int outsize = 0; + pstring name; + pstring newname; + char *p; + NTSTATUS status; + + START_PROFILE(SMBntrename); + + p = smb_buf(inbuf) + 1; + p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBntrename); + return ERROR_NT(status); + } + p++; + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBntrename); + return ERROR_NT(status); + } + + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + + DEBUG(3,("reply_ntrename : %s -> %s\n",name,newname)); + + status = rename_internals(conn, name, newname, False); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBntrename); + return ERROR_NT(status); + } + + /* + * Win2k needs a changenotify request response before it will + * update after a rename.. + */ + process_pending_change_notify_queue((time_t)0); + outsize = set_message(outbuf,0,0,True); + + END_PROFILE(SMBntrename); + return(outsize); +} + /**************************************************************************** Reply to an unsolicited SMBNTtranss - just ignore it! ****************************************************************************/ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5206dc70f8..718d1bb67b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -521,7 +521,7 @@ static const struct smb_message_struct { /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, /* 0xa3 */ { NULL, NULL, 0 }, /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 }, -/* 0xa5 */ { NULL, NULL, 0 }, +/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, /* 0xa6 */ { NULL, NULL, 0 }, /* 0xa7 */ { NULL, NULL, 0 }, /* 0xa8 */ { NULL, NULL, 0 }, -- cgit From 69058407ef0079bf919c4ffb0b8464a986772536 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Feb 2004 00:38:39 +0000 Subject: Fixup bad-path error found by gentest. Jeremy. (This used to be commit 63d47f336464080e20e68f21d826e82786b9719e) --- source3/smbd/trans2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 605169277d..63130aa8d8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2540,9 +2540,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); unix_convert(fname,conn,0,&bad_path,&sbuf); - if(!check_name(fname, conn)) { - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); - } /* * For CIFS UNIX extensions the target name may not exist. @@ -2550,8 +2547,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); - return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } + + if(!check_name(fname, conn)) { + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + } + } if (!CAN_WRITE(conn)) -- cgit From 5447f1f4677bd4a3b9da43a835dd8c662ed86bfa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Feb 2004 00:55:05 +0000 Subject: More gentest error fixups. Jeremy. (This used to be commit 00f71fc8361919b87b62389ada8bd9a73f9f98b5) --- source3/smbd/nttrans.c | 2 -- source3/smbd/open.c | 9 +++++++++ source3/smbd/reply.c | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2831f75933..a432e2aaea 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -673,14 +673,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - /* we need to handle the case when we get a relative open relative to a file and the pathname is blank - this is a reopen! (hint from demyn plantenberg) */ - END_PROFILE(SMBntcreateX); return(ERROR_DOS(ERRDOS,ERRbadfid)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3807c18e78..dd10a87055 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1305,6 +1305,15 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } + if( strchr_m(fname, ':')) { + file_free(fsp); + DEBUG(5,("open_directory: failing create on filename %s with colon in name\n", fname)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_NOT_A_DIRECTORY; + return NULL; + } + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ee47485126..26c107e17a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3005,6 +3005,10 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) unix_convert(directory,conn,0,&bad_path,&sbuf); + if( strchr_m(directory, ':')) { + return NT_STATUS_NOT_A_DIRECTORY; + } + if (ms_has_wild(directory)) { return NT_STATUS_OBJECT_NAME_INVALID; } -- cgit From f96e84c682bac64713841c8008193de5baf59993 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Feb 2004 01:46:24 +0000 Subject: Ensure '.' and '..' don't match in delete requests. Jeremy. (This used to be commit 1b0d54170a2e3e61fc9bdedec6b10c8b7728a395) --- source3/smbd/reply.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 26c107e17a..0fe3be0752 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1449,7 +1449,10 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) while ((dname = ReadDirName(dirptr))) { pstring fname; pstrcpy(fname,dname); - + + if((strcmp(fname, ".") == 0) || (strcmp(fname, "..")==0)) + continue; + if(!mask_match(fname, mask, case_sensitive)) continue; -- cgit From 01cb68643c129729f3df2bdfcdc81bd3c7fef71a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Feb 2004 00:48:35 +0000 Subject: More gentest fixes. Jeremy. (This used to be commit d34785194cbd7132fc3ca1f4d5561c2eee6009ab) --- source3/smbd/reply.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0fe3be0752..d0888fc682 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1309,7 +1309,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT Check if a user is allowed to delete a file. ********************************************************************/ -static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) +static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path) { SMB_STRUCT_STAT sbuf; int fmode; @@ -1323,8 +1323,15 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) { + if(errno == ENOENT) { + if (bad_path) + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + else + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + return map_nt_error_from_unix(errno); + } fmode = dos_mode(conn,fname,&sbuf); @@ -1421,7 +1428,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - error = can_delete(directory,conn,dirtype); + error = can_delete(directory,conn,dirtype,bad_path); if (!NT_STATUS_IS_OK(error)) return error; @@ -1457,7 +1464,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) continue; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - error = can_delete(fname,conn,dirtype); + error = can_delete(fname,conn,dirtype,bad_path); if (!NT_STATUS_IS_OK(error)) continue; if (SMB_VFS_UNLINK(conn,fname) == 0) @@ -3639,7 +3646,8 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", dirptr = OpenDir(conn, directory, True); if (dirptr) { - error = NT_STATUS_OBJECT_NAME_NOT_FOUND; + error = NT_STATUS_NO_SUCH_FILE; +/* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); @@ -3649,6 +3657,9 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", pstrcpy(fname,dname); + if((strcmp(fname, ".") == 0) || (strcmp(fname, "..")==0)) + continue; + if(!mask_match(fname, mask, case_sensitive)) continue; -- cgit From 1d9f07735c67a29f4cf56aa376d7a1f034c967f6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Feb 2004 01:35:14 +0000 Subject: More gentest fun :-). NB. I'm not fixing OpenX breakage 'cos if you look at what W2K3 accepts here it's COMPLETELY BROKEN ! :-). Jeremy. (This used to be commit 5107f6ee70a9300678ccb7b3c812e23ddf795c22) --- source3/smbd/reply.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d0888fc682..c729f22728 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1457,8 +1457,12 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) pstring fname; pstrcpy(fname,dname); - if((strcmp(fname, ".") == 0) || (strcmp(fname, "..")==0)) - continue; + /* Quick check for "." and ".." */ + if (fname[0] == '.') { + if (!fname[1] || (fname[1] == '.' && !fname[2])) { + continue; + } + } if(!mask_match(fname, mask, case_sensitive)) continue; @@ -3357,6 +3361,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * ZERO_STRUCT(sbuf); unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); + /* Quick check for "." and ".." */ + if (newname_last_component[0] == '.') { + if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { + return NT_STATUS_ACCESS_DENIED; + } + } + /* Ensure newname contains a '/' */ if(strrchr_m(newname,'/') == 0) { pstring tmpstr; @@ -3470,6 +3481,13 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); + /* Quick check for "." and ".." */ + if (newname_last_component[0] == '.') { + if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { + return NT_STATUS_ACCESS_DENIED; + } + } + /* * Split the old name into directory and last component * strings. Note that unix_convert may have stripped off a @@ -3478,7 +3496,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO * name and newname contain a / character or neither of them do * as this is checked in resolve_wildcards(). */ - + p = strrchr_m(name,'/'); if (!p) { pstrcpy(directory,"."); @@ -3657,8 +3675,12 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", pstrcpy(fname,dname); - if((strcmp(fname, ".") == 0) || (strcmp(fname, "..")==0)) - continue; + /* Quick check for "." and ".." */ + if (fname[0] == '.') { + if (!fname[1] || (fname[1] == '.' && !fname[2])) { + continue; + } + } if(!mask_match(fname, mask, case_sensitive)) continue; -- cgit From a45d29049bf6f6060d1a7bf95a38ff3f37ed96cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Feb 2004 02:15:34 +0000 Subject: Figured out a new flags bit with gentest and ethereal.... Jeremy. (This used to be commit b4b684f1155b1abccb69cca7bca9819625dbfead) --- source3/smbd/nttrans.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a432e2aaea..8c3d1eefba 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -974,9 +974,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); - p += 12; + p += 8; + if (flags & EXTENDED_RESPONSE_REQUIRED) + SSVAL(p,2,0x7); + p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); - + DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); result = chain_reply(inbuf,outbuf,length,bufsize); @@ -1454,6 +1457,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); + p += 8; + if (flags & EXTENDED_RESPONSE_REQUIRED) + SSVAL(p,2,0x7); + p += 4; + SCVAL(p,0,fsp->is_directory ? 1 : 0); DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); -- cgit From fd6b9c02b91ea39e8c7575e1f5f106509940ba1f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Feb 2004 21:37:22 +0000 Subject: Fixup strange rename error case (gentest). Jeremy. (This used to be commit d448fb801e175e11cfc0118325043eef836103f0) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c729f22728..49f4e97028 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3482,8 +3482,9 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); /* Quick check for "." and ".." */ - if (newname_last_component[0] == '.') { + if (!bad_path2 && newname_last_component[0] == '.') { if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { + DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n")); return NT_STATUS_ACCESS_DENIED; } } -- cgit From fa81d1d7e7a86d13d10550aa20b07c7300d7b324 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Feb 2004 01:31:10 +0000 Subject: Interesting fact found by IFSTEST /t LockOverlappedTest... Even if it's our own lock context, we need to wait here as there may be an unlock on the way. So I removed a "&& !my_lock_ctx" from the following if statement. if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { Jeremy. (This used to be commit 3f35e3975f1c46daad1456bc82163acd049d7be8) --- source3/smbd/reply.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 49f4e97028..643b7c2d08 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4357,7 +4357,14 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); status = do_lock_spin(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx); if (NT_STATUS_V(status)) { - if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { + /* + * Interesting fact found by IFSTEST /t LockOverlappedTest... + * Even if it's our own lock context, we need to wait here as + * there may be an unlock on the way. + * So I removed a "&& !my_lock_ctx" from the following + * if statement. JRA. + */ + if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it -- cgit From 3c1d00d12a2e3ef2c685c47313487dccae755294 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 28 Feb 2004 00:56:42 +0000 Subject: More gentest fixes. Fix up regression in IS_NAME_VALID and renames. Jeremy. (This used to be commit 367f5c3bc27aafb04f7589b3d4ac5b58189909fb) --- source3/smbd/reply.c | 41 ++++++++++++++++++++++++++++++----------- source3/smbd/trans2.c | 6 ++++-- 2 files changed, 34 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 643b7c2d08..836f95e179 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3357,16 +3357,20 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * pstring newname_last_component; NTSTATUS error = NT_STATUS_OK; BOOL dest_exists; + BOOL rcdest = True; ZERO_STRUCT(sbuf); - unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); + rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); /* Quick check for "." and ".." */ - if (newname_last_component[0] == '.') { + if (!bad_path && newname_last_component[0] == '.') { if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { return NT_STATUS_ACCESS_DENIED; } } + if (!rcdest && bad_path) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } /* Ensure newname contains a '/' */ if(strrchr_m(newname,'/') == 0) { @@ -3472,6 +3476,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO int count=0; NTSTATUS error = NT_STATUS_OK; BOOL rc = True; + BOOL rcdest = True; SMB_STRUCT_STAT sbuf1, sbuf2; *directory = *mask = 0; @@ -3479,15 +3484,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); - unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); - - /* Quick check for "." and ".." */ - if (!bad_path2 && newname_last_component[0] == '.') { - if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { - DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n")); - return NT_STATUS_ACCESS_DENIED; - } - } + rcdest = unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); /* * Split the old name into directory and last component @@ -3612,6 +3609,17 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", return error; } + /* Quick check for "." and ".." */ + if (!bad_path2 && newname_last_component[0] == '.') { + if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { + DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n")); + return NT_STATUS_ACCESS_DENIED; + } + } + if (!rcdest && bad_path2) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + error = can_rename(directory,conn,&sbuf1); if (!NT_STATUS_IS_OK(error)) { @@ -3661,6 +3669,17 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", const char *dname; pstring destname; + /* Quick check for "." and ".." */ + if (!bad_path2 && newname_last_component[0] == '.') { + if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { + DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n")); + return NT_STATUS_ACCESS_DENIED; + } + } + if (!rcdest && bad_path2) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + if (check_name(directory,conn)) dirptr = OpenDir(conn, directory, True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 63130aa8d8..5fbc5ce6ee 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1830,6 +1830,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SMB_OFF_T file_size=0; SMB_BIG_UINT allocation_size=0; unsigned int data_size; + unsigned int param_size = 2; SMB_STRUCT_STAT sbuf; pstring fname, dos_fname; char *fullpathname; @@ -1932,7 +1933,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } @@ -2016,6 +2017,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return ERROR_DOS(ERRDOS,ERRbadfunc); } data_size = 0; + param_size = 0; break; case SMB_INFO_QUERY_EAS_FROM_LIST: @@ -2322,7 +2324,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return ERROR_DOS(ERRDOS,ERRunknownlevel); } - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size); + send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size); return(-1); } -- cgit From 3fb52e5cc0fe632584704e807dde5f0ae6612413 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 28 Feb 2004 01:53:30 +0000 Subject: Can't set allocation size on directories, return correct error code on fail if file exists and target is a directory. gentest. Jeremy. (This used to be commit f4a7ea6dc2b9f379a9c735670a49ac63818754c7) --- source3/smbd/nttrans.c | 12 ++++++++++++ source3/smbd/open.c | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8c3d1eefba..7b02c60001 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -895,6 +895,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib #endif if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + if (fsp->is_directory) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + /* Can't set allocation size on a directory. */ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -1404,6 +1410,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o #endif if (allocation_size && (allocation_size > file_len)) { fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + if (fsp->is_directory) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + /* Can't set allocation size on a directory. */ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,False); return ERROR_NT(NT_STATUS_DISK_FULL); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd10a87055..e688f8de48 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -866,7 +866,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", fname )); file_free(fsp); - errno = EEXIST; + if (S_ISDIR(psbuf->st_mode)) { + errno = EISDIR; + } else { + errno = EEXIST; + } return NULL; } -- cgit From fba5a722497c1e4577aa463921a0fec5f6d5fe55 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 Mar 2004 20:55:59 +0000 Subject: Use a common function to parse all pathnames from the wire. This allows much closer emulation of Win2k3 error return codes. Jeremy. (This used to be commit c9f31fafeda6ad79e590276f36e03ecd2e93f818) --- source3/smbd/filename.c | 27 ++---- source3/smbd/nttrans.c | 69 +++++++------ source3/smbd/reply.c | 253 ++++++++++++++++++++++++++++++++++++------------ source3/smbd/trans2.c | 69 ++++++++++--- 4 files changed, 290 insertions(+), 128 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 643e315c06..a71e8a806c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -114,29 +114,30 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); /* - * Convert to basic unix format - removing \ chars and cleaning it up. + * Conversion to basic unix format is already done in check_path_syntax(). */ - unix_format(name); - unix_clean_name(name); - /* - * Names must be relative to the root of the service - trim any leading /. - * also trim trailing /'s. + * Names must be relative to the root of the service - any leading /. + * and trailing /'s should have been trimmed by check_path_syntax(). */ - trim_char(name,'/','/'); +#ifdef DEVELOPER + SMB_ASSERT(*name != '/'); +#endif /* * If we trimmed down to a single '\0' character * then we should use the "." directory to avoid * searching the cache, but not if we are in a * printing share. + * As we know this is valid we can return true here. */ if (!*name) { name[0] = '.'; name[1] = '\0'; + return(True); } /* @@ -154,19 +155,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) strnorm(name); - /* - * If we trimmed down to a single '\0' character - * then we will be using the "." directory. - * As we know this is valid we can return true here. - */ - - if(!*name) - return(True); - start = name; - while (start[0] == '.' && start[1] == '/') - start += 2; - pstrcpy(orig_path, name); if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7b02c60001..9a0063481a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -537,7 +537,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, char *p = NULL; NTSTATUS status; - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); @@ -658,7 +658,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -700,13 +700,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib dir_name_len++; } - srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE,&status); + srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } } else { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -1018,8 +1018,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); - status = check_path_syntax(fname); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1160,7 +1159,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o int smb_open_mode; int smb_attr; time_t c_time; - NTSTATUS nt_status; + NTSTATUS status; DEBUG(5,("call_nt_transact_create\n")); @@ -1226,11 +1225,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_DOS(ERRDOS,ERRbadfid); if(!dir_fsp->is_directory) { - - srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); - nt_status = check_path_syntax(fname); - if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } /* @@ -1259,17 +1256,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o dir_name_len++; } - srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, - parameter_count-53, STR_TERMINATE); - nt_status = check_path_syntax(fname); - if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); + { + pstring tmpname; + srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + pstrcat(fname, tmpname); } } else { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); - nt_status = check_path_syntax(fname); - if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } /* @@ -1395,10 +1393,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Now try and apply the desired SD. */ - if (sd_len && !NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { + if (sd_len && !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { close_file(fsp,False); restore_case_semantics(file_attributes); - return ERROR_NT(nt_status); + return ERROR_NT(status); } restore_case_semantics(file_attributes); @@ -1518,17 +1516,31 @@ int reply_ntrename(connection_struct *conn, pstring newname; char *p; NTSTATUS status; + uint16 attrs = SVAL(inbuf,smb_vwv0); + uint16 rename_type = SVAL(inbuf,smb_vwv1); START_PROFILE(SMBntrename); + if (rename_type != RENAME_FLAG_RENAME) { + END_PROFILE(SMBntrename); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); } + + if( strchr_m(name, ':')) { + /* Can't rename a stream. */ + END_PROFILE(SMBntrename); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1539,7 +1551,7 @@ int reply_ntrename(connection_struct *conn, DEBUG(3,("reply_ntrename : %s -> %s\n",name,newname)); - status = rename_internals(conn, name, newname, False); + status = rename_internals(conn, name, newname, attrs, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1627,14 +1639,13 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o fsp = file_fsp(params, 0); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); - srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE); - status = check_path_syntax(new_name); + srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } status = rename_internals(conn, fsp->fsp_name, - new_name, replace_if_exists); + new_name, 0, replace_if_exists); if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 836f95e179..051aaafb45 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -40,28 +40,117 @@ extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** Ensure we check the path in *exactly* the same way as W2K. + We're assuming here that '/' is not the second byte in any multibyte char + set (a safe assumption). '\\' *may* be the second byte in a multibyte char + set. ****************************************************************************/ -NTSTATUS check_path_syntax(const char *name) +static NTSTATUS check_path_syntax(pstring destname, const pstring srcname) { - while (*name == '\\' || *name == '/') - name++; - if (name[0] == '.' && name[1] == '\0') - return NT_STATUS_OBJECT_NAME_INVALID; - else if (name[0] == '.' && name[1] == '.' && - (name[2] == '\\' || name [2] == '/' || name[2] == '\0')) - return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - return NT_STATUS_OK; + char *d = destname; + const char *s = srcname; + NTSTATUS ret = NT_STATUS_OK; + + while (*s) { + if (IS_DIRECTORY_SEP(*s)) { + /* + * Safe to assume is not the second part of a mb char as this is handled below. + */ + /* Eat multiple '/' or '\\' */ + while (IS_DIRECTORY_SEP(*s)) { + s++; + } + if ((d != destname) && (*s != '\0')) { + /* We only care about non-leading or trailing '/' or '\\' */ + *d++ = '/'; + } + } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { + /* Uh oh - "../" or "..\\" or "..\0" ! */ + + /* + * No mb char starts with '.' so we're safe checking the directory separator here. + */ + + /* If we just added a '/', delete it. */ + + if ((d > destname) && (*(d-1) == '/')) { + *(d-1) = '\0'; + if (d == (destname + 1)) { + d--; + } else { + d -= 2; + } + } + /* Are we at the start ? Can't go back further if so. */ + if (d == destname) { + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + } + /* Go back one level... */ + while (d > destname) { + if (*d == '/') + break; + d--; + } + s += 3; + } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) { + + /* + * No mb char starts with '.' so we're safe checking the directory separator here. + */ + + /* "./" or ".\\" fails with a different error depending on where it is... */ + + if (s == srcname) { + ret = NT_STATUS_OBJECT_NAME_INVALID; + } else { + if (s[2] == '\0') { + return NT_STATUS_INVALID_PARAMETER; + } + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + s++; + } else { + if ((*s & 0x80) && IS_DIRECTORY_SEP(s[1])) { + /* + * Potential mb char with second char a directory separator. + * All the encodings we care about are 2 byte only, so do a + * conversion to unicode. If the 2 byte char won't convert then + * it's probably a one byte char with a real directory separator + * following, so only copy one byte. If it will convert then + * copy both bytes. + */ + uint16 ucs2_val; + if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) { + *d++ = *s++; + } + } + /* Just copy the char (or the second byte of the mb char). */ + *d++ = *s++; + } + } + *d = '\0'; + return ret; } /**************************************************************************** Pull a string and check the path - provide for error return. ****************************************************************************/ -size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, int flags, NTSTATUS *err) +size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err) { - size_t ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); - *err = check_path_syntax(dest); + pstring tmppath; + char *tmppath_ptr = tmppath; +#ifdef DEVELOPER + SMB_ASSERT(dest_len == sizeof(pstring)); +#endif + size_t ret; + + if (src_len == 0) { + ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags); + } else { + ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); + } + *err = check_path_syntax(dest, tmppath); return ret; } @@ -414,7 +503,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBchkpth); - srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE, &status); + srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBchkpth); return ERROR_NT(status); @@ -492,7 +581,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBgetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBgetatr); return ERROR_NT(status); @@ -567,7 +656,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBsetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsetatr); return ERROR_NT(status); @@ -695,7 +784,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status); + p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status); if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); return ERROR_NT(nt_status); @@ -873,7 +962,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(outbuf,1,0,True); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err); + p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err); if (!NT_STATUS_IS_OK(err)) { END_PROFILE(SMBfclose); return ERROR_NT(err); @@ -925,7 +1014,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); return ERROR_NT(status); @@ -1017,7 +1106,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); return ERROR_NT(status); @@ -1133,7 +1222,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); createmode = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); return ERROR_NT(status); @@ -1202,7 +1291,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBctemp); createmode = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); return ERROR_NT(status); @@ -1456,17 +1545,27 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) while ((dname = ReadDirName(dirptr))) { pstring fname; pstrcpy(fname,dname); + BOOL sys_direntry = False; /* Quick check for "." and ".." */ if (fname[0] == '.') { if (!fname[1] || (fname[1] == '.' && !fname[2])) { - continue; + if ((dirtype & aDIR)) { + sys_direntry = True; + } else { + continue; + } } } if(!mask_match(fname, mask, case_sensitive)) continue; + if (sys_direntry) { + error = NT_STATUS_OBJECT_NAME_INVALID; + continue; + } + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype,bad_path); if (!NT_STATUS_IS_OK(error)) @@ -1501,7 +1600,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dirtype = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status); + srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBunlink); return ERROR_NT(status); @@ -3054,7 +3153,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBmkdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); return ERROR_NT(status); @@ -3224,7 +3323,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBrmdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); return ERROR_NT(status); @@ -3464,15 +3563,16 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists) +NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists) { pstring directory; pstring mask; - pstring newname_last_component; + pstring last_component_src; + pstring last_component_dest; char *p; BOOL has_wild; - BOOL bad_path1 = False; - BOOL bad_path2 = False; + BOOL bad_path_src = False; + BOOL bad_path_dest = False; int count=0; NTSTATUS error = NT_STATUS_OK; BOOL rc = True; @@ -3483,8 +3583,29 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); - rcdest = unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); + + rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1); + if (!rc && bad_path_src) { + if (ms_has_wild(last_component_src)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* Quick check for "." and ".." */ + if (last_component_src[0] == '.') { + if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2); + + /* Quick check for "." and ".." */ + if (last_component_dest[0] == '.') { + if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + } /* * Split the old name into directory and last component @@ -3540,9 +3661,9 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO } DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \ -directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", +directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", case_sensitive, case_preserve, short_case_preserve, directory, - newname, newname_last_component, is_short_name)); + newname, last_component_dest, is_short_name)); /* * Check for special case with case preserving and not @@ -3558,7 +3679,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", ((short_case_preserve == True) && (is_short_name == True))) && strcsequal(directory, newname)) { - pstring newname_modified_last_component; + pstring modified_last_component; /* * Get the last component of the modified name. @@ -3566,15 +3687,15 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", * character above. */ p = strrchr_m(newname,'/'); - pstrcpy(newname_modified_last_component,p+1); + pstrcpy(modified_last_component,p+1); - if(strcsequal(newname_modified_last_component, - newname_last_component) == False) { + if(strcsequal(modified_last_component, + last_component_dest) == False) { /* * Replace the modified last component with * the original. */ - pstrcpy(p+1, newname_last_component); + pstrcpy(p+1, last_component_dest); } } @@ -3609,14 +3730,9 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", return error; } - /* Quick check for "." and ".." */ - if (!bad_path2 && newname_last_component[0] == '.') { - if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { - DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n")); - return NT_STATUS_ACCESS_DENIED; - } - } - if (!rcdest && bad_path2) { + if (!rcdest && bad_path_dest) { + if (ms_has_wild(last_component_dest)) + return NT_STATUS_OBJECT_NAME_INVALID; return NT_STATUS_OBJECT_PATH_NOT_FOUND; } @@ -3669,17 +3785,6 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", const char *dname; pstring destname; - /* Quick check for "." and ".." */ - if (!bad_path2 && newname_last_component[0] == '.') { - if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { - DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n")); - return NT_STATUS_ACCESS_DENIED; - } - } - if (!rcdest && bad_path2) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - if (check_name(directory,conn)) dirptr = OpenDir(conn, directory, True); @@ -3692,19 +3797,29 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", while ((dname = ReadDirName(dirptr))) { pstring fname; + BOOL sysdir_entry = False; pstrcpy(fname,dname); /* Quick check for "." and ".." */ if (fname[0] == '.') { if (!fname[1] || (fname[1] == '.' && !fname[2])) { - continue; + if (attrs & aDIR) { + sysdir_entry = True; + } else { + continue; + } } } if(!mask_match(fname, mask, case_sensitive)) continue; + if (sysdir_entry) { + error = NT_STATUS_OBJECT_NAME_INVALID; + continue; + } + error = NT_STATUS_ACCESS_DENIED; slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); if (!vfs_object_exist(conn, fname, &sbuf1)) { @@ -3735,11 +3850,20 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", if (!SMB_VFS_RENAME(conn,fname,destname)) { rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); count++; + error = NT_STATUS_OK; } DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } CloseDir(dirptr); } + + if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) { + if (!rcdest && bad_path_dest) { + if (ms_has_wild(last_component_dest)) + return NT_STATUS_OBJECT_NAME_INVALID; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } } if (count == 0 && NT_STATUS_IS_OK(error)) { @@ -3760,18 +3884,19 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring name; pstring newname; char *p; + uint16 attrs = SVAL(inbuf,smb_vwv0); NTSTATUS status; START_PROFILE(SMBmv); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); } p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); @@ -3782,7 +3907,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - status = rename_internals(conn, name, newname, False); + status = rename_internals(conn, name, newname, attrs, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); @@ -3909,12 +4034,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, *directory = *mask = 0; p = smb_buf(inbuf); - p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); } - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); @@ -4074,7 +4199,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status); + srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(pathworks_setdir); return ERROR_NT(status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5fbc5ce6ee..1d580e6f5b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -228,6 +228,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i int smb_action = 0; BOOL bad_path = False; files_struct *fsp; + NTSTATUS status; /* * Ensure we have enough parameters to perform the operation. @@ -248,7 +249,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i open_size = IVAL(params,14); pname = ¶ms[28]; - srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE); + srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", fname,open_mode, open_attr, open_ofun, open_size)); @@ -939,6 +943,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb int space_remaining; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + NTSTATUS ntstatus = NT_STATUS_OK; if (total_params < 12) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); @@ -968,7 +973,10 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", return(ERROR_DOS(ERRDOS,ERRunknownlevel)); } - srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE); + srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus); + if (!NT_STATUS_IS_OK(ntstatus)) { + return ERROR_NT(ntstatus); + } RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); @@ -1151,13 +1159,17 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu BOOL dont_descend = False; BOOL out_of_space = False; int space_remaining; + NTSTATUS ntstatus = NT_STATUS_OK; if (total_params < 12) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); *mask = *directory = *resume_name = 0; - srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE); + srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus); + if (!NT_STATUS_IS_OK(ntstatus)) { + return ERROR_NT(ntstatus); + } DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \ close_after_request=%d, close_if_end = %d requires_resume_key = %d \ @@ -1909,6 +1921,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, desired_access = fsp->desired_access; } } else { + NTSTATUS status = NT_STATUS_OK; + /* qpathinfo */ if (total_params < 6) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); @@ -1917,7 +1931,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -2483,6 +2500,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; mode_t unixmode = 0; + NTSTATUS status = NT_STATUS_OK; if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -2540,7 +2558,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(ERROR_DOS(ERRDOS,ERRinvalidparam)); info_level = SVAL(params,0); - srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } unix_convert(fname,conn,0,&bad_path,&sbuf); /* @@ -2761,7 +2782,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { BOOL delete_on_close; - NTSTATUS status; if (total_data < 1) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); @@ -2948,7 +2968,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (VALID_STAT(sbuf)) return(ERROR_DOS(ERRDOS,ERRbadpath)); - srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE); + srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } if (ensure_link_is_safe(conn, link_dest, link_dest) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2973,7 +2996,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (VALID_STAT(sbuf)) return(ERROR_DOS(ERRDOS,ERRbadpath)); - srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE); + srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } if (ensure_link_is_safe(conn, link_dest, link_dest) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2996,7 +3022,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstring newname; pstring base_name; char *p; - NTSTATUS status; if (total_data < 12) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); @@ -3004,10 +3029,13 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", overwrite = (CVAL(pdata,0) ? True : False); root_fid = IVAL(pdata,4); len = IVAL(pdata,8); - srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0); + srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } - /* Check the new name has no '\' characters. */ - if (strchr_m(newname, '\\') || strchr_m(newname, '/')) + /* Check the new name has no '/' characters. */ + if (strchr_m(newname, '/')) return ERROR_NT(NT_STATUS_NOT_SUPPORTED); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); @@ -3028,10 +3056,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } else { DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, newname )); - status = rename_internals(conn, fname, base_name, overwrite); + status = rename_internals(conn, fname, base_name, 0, overwrite); } - if (!NT_STATUS_IS_OK(status)) + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); + } process_pending_change_notify_queue((time_t)0); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); @@ -3171,6 +3200,7 @@ static int call_trans2mkdir(connection_struct *conn, int ret = -1; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; + NTSTATUS status = NT_STATUS_OK; if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); @@ -3178,7 +3208,10 @@ static int call_trans2mkdir(connection_struct *conn, if (total_params < 4) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); - srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE); + srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); @@ -3290,6 +3323,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, pstring pathname; int reply_size = 0; int max_referral_level; + NTSTATUS status = NT_STATUS_OK; DEBUG(10,("call_trans2getdfsreferral\n")); @@ -3301,7 +3335,10 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, if(!lp_host_msdfs()) return ERROR_DOS(ERRDOS,ERRbadfunc); - srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); + srvstr_get_path(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0) return UNIXERROR(ERRDOS,ERRbadfile); -- cgit From f0039da19654f0d75617e96d67054d1d1990515d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 Mar 2004 23:14:23 +0000 Subject: Added client "hardlink" commant to test doing NT rename with hard links. Added hardlink_internals() code - UNIX extensions now use this too. Jeremy. (This used to be commit aad6eb2240393931940c982e25a981ce32264f38) --- source3/smbd/nttrans.c | 9 +++-- source3/smbd/trans2.c | 95 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9a0063481a..11518c24f7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1521,7 +1521,7 @@ int reply_ntrename(connection_struct *conn, START_PROFILE(SMBntrename); - if (rename_type != RENAME_FLAG_RENAME) { + if ((rename_type != RENAME_FLAG_RENAME) && (rename_type != RENAME_FLAG_HARD_LINK)) { END_PROFILE(SMBntrename); return ERROR_NT(NT_STATUS_ACCESS_DENIED); } @@ -1551,7 +1551,12 @@ int reply_ntrename(connection_struct *conn, DEBUG(3,("reply_ntrename : %s -> %s\n",name,newname)); - status = rename_internals(conn, name, newname, attrs, False); + if (rename_type == RENAME_FLAG_RENAME) { + status = rename_internals(conn, name, newname, attrs, False); + } else { + status = hardlink_internals(conn, name, newname); + } + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1d580e6f5b..e2df517f40 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2477,6 +2477,82 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in return 0; } +/**************************************************************************** + Set a hard link (called by UNIX extensions and by NT rename with HARD link + code. +****************************************************************************/ + +NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname) +{ + BOOL bad_path_src = False; + BOOL bad_path_dest = False; + SMB_STRUCT_STAT sbuf1, sbuf2; + BOOL rc, rcdest; + pstring last_component_src; + pstring last_component_dest; + NTSTATUS status = NT_STATUS_OK; + + ZERO_STRUCT(sbuf1); + ZERO_STRUCT(sbuf2); + + /* No wildcards. */ + if (ms_has_wild(name) || ms_has_wild(newname)) { + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1); + if (!rc && bad_path_src) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* Quick check for "." and ".." */ + if (last_component_src[0] == '.') { + if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + /* source must already exist. */ + if (!VALID_STAT(sbuf1)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2); + if (!rcdest && bad_path_dest) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* Quick check for "." and ".." */ + if (last_component_dest[0] == '.') { + if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + /* Disallow if already exists. */ + if (VALID_STAT(sbuf2)) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + /* No links from a directory. */ + if (S_ISDIR(sbuf1.st_mode)) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + + if (ensure_link_is_safe(conn, newname, newname) != 0) + return NT_STATUS_ACCESS_DENIED; + + DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", name, newname )); + + if (SMB_VFS_LINK(conn,name,newname) != 0) { + status = map_nt_error_from_unix(errno); + DEBUG(3,("hardlink_internals: Error %s link %s -> %s\n", + nt_errstr(status), name,newname)); + } + + return status; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid). ****************************************************************************/ @@ -2964,10 +3040,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (!lp_symlinks(SNUM(conn))) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - /* Disallow if already exists. */ - if (VALID_STAT(sbuf)) - return(ERROR_DOS(ERRDOS,ERRbadpath)); - srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); @@ -2991,24 +3063,19 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstring link_dest; /* Set a hard link. */ - - /* Disallow if already exists. */ - if (VALID_STAT(sbuf)) - return(ERROR_DOS(ERRDOS,ERRbadpath)); - srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - if (ensure_link_is_safe(conn, link_dest, link_dest) != 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, link_dest )); - if (SMB_VFS_LINK(conn,link_dest,fname) != 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + status = hardlink_internals(conn, fname, link_dest); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); -- cgit From 7dc6dd58843cf1332964b7119fb683310fc4e3c7 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 4 Mar 2004 16:24:13 +0000 Subject: Fix build farm, older compilers won't let you declare variables right in the middle of the code. I just love catching jra on stuff like this, after all the crap I've done. :-) (This used to be commit dc7dc5175847243d821dd33c1678af1b785dfaf7) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 051aaafb45..c0d5234f47 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1544,8 +1544,8 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) while ((dname = ReadDirName(dirptr))) { pstring fname; - pstrcpy(fname,dname); BOOL sys_direntry = False; + pstrcpy(fname,dname); /* Quick check for "." and ".." */ if (fname[0] == '.') { -- cgit From 4020fadb1af8823d9341faa58920477485d888e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Mar 2004 18:55:37 +0000 Subject: Fix my breakage of NT pipes from the previous patch (sorry). Use the original srvstr_pull_buf() function to get the pipename not srvstr_get_path(). Jeremy. (This used to be commit 2a263873fd6bbbf03a32136981e433dc43374da9) --- source3/smbd/nttrans.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 11518c24f7..21b6db8b46 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -535,11 +535,8 @@ static int do_ntcreate_pipe_open(connection_struct *conn, int ret; int pnum = -1; char *p = NULL; - NTSTATUS status; - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) - return ERROR_NT(status); + srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; -- cgit From 893d5eba5d17a1efe600d67c0e82b401ead248ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Mar 2004 01:37:12 +0000 Subject: all_string_sub() is broken as it doesn't handle mb chars correctly (and so breaks when substitution '/' and '\'). It's used by unix_clean_name(), which is used by reduce_name, which is used by check_name() (phew!). Now that we know all filenames passed to check_name() are in a "good" format (no double slashes, all '\\' chars translated to '/' etc.) due to the new check_path_syntax() we can avoid calling reduce_name unless widelinks are denied. After this check-in I can fix all_string_sub() to handle mb chars correctly as it won't be in the direct path in the main path handling code. Jeremy. (This used to be commit 6080186fc4c2e7c59dd12a177539bfb77eb525cb) --- source3/smbd/filename.c | 6 ++++-- source3/smbd/vfs.c | 17 +---------------- 2 files changed, 5 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a71e8a806c..8300674d61 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -387,7 +387,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen BOOL check_name(pstring name,connection_struct *conn) { - BOOL ret; + BOOL ret = True; errno = 0; @@ -398,7 +398,9 @@ BOOL check_name(pstring name,connection_struct *conn) } } - ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); + if (!lp_widelinks(SNUM(conn))) { + ret = reduce_name(conn,name,conn->connectpath); + } /* Check if we are allowing users to follow symlinks */ /* Patch from David Clerc diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2f981c743f..284e24e7b1 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -845,10 +845,9 @@ static BOOL readlink_check(connection_struct *conn, const char *dir, char *name) Reduce a file name, removing .. elements and checking that it is below dir in the heirachy. This uses vfs_GetWd() and so must be run on the system that has the referenced file system. - Widelinks are allowed if widelinks is true. ********************************************************************/ -BOOL reduce_name(connection_struct *conn, pstring s, const char *dir,BOOL widelinks) +BOOL reduce_name(connection_struct *conn, pstring s, const char *dir) { #ifndef REDUCE_PATHS return True; @@ -862,20 +861,6 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir,BOOL wideli *dir2 = *wd = *base_name = *newname = 0; - if (widelinks) { - unix_clean_name(s); - /* can't have a leading .. */ - if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/')) { - DEBUG(3,("Illegal file name? (%s)\n",s)); - return(False); - } - - if (strlen(s) == 0) - pstrcpy(s,"./"); - - return(True); - } - DEBUG(3,("reduce_name [%s] [%s]\n",s,dir)); /* remove any double slashes */ -- cgit From 48eb635f31a09fa0822d95d3e895255ef8a6d5e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Mar 2004 22:32:45 +0000 Subject: Several mb tidyups - getting ready to address the XXX_sub function. Jeremy. (This used to be commit 92c3ae3458177ec7f721598311a8ad04b2db5138) --- source3/smbd/filename.c | 14 ++-- source3/smbd/service.c | 180 +++++++++++++++++++++++------------------------- source3/smbd/trans2.c | 6 +- source3/smbd/vfs.c | 13 ++-- 4 files changed, 105 insertions(+), 108 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8300674d61..805af9c494 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1999-200 + Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Ying Chen 2000 This program is free software; you can redistribute it and/or modify @@ -392,9 +392,10 @@ BOOL check_name(pstring name,connection_struct *conn) errno = 0; if (IS_VETO_PATH(conn, name)) { - if(strcmp(name, ".") && strcmp(name, "..")) { + /* Is it not dot or dot dot. */ + if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { DEBUG(5,("file path name %s vetoed\n",name)); - return(0); + return False; } } @@ -412,7 +413,7 @@ BOOL check_name(pstring name,connection_struct *conn) if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - ret=0; + ret = False; } } #endif @@ -464,8 +465,11 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, /* now scan for matching names */ while ((dname = ReadDirName(cur_dir))) { - if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) + + /* Is it dot or dot dot. */ + if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { continue; + } /* * At this point dname is the unmangled name. diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 78b610ae37..a53b9267b7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -112,105 +112,96 @@ int add_home_service(const char *service, const char *username, const char *home /** - * Find a service entry. service is always in dos codepage. + * Find a service entry. * * @param service is modified (to canonical form??) **/ + int find_service(fstring service) { - int iService; - - all_string_sub(service,"\\","/",0); - - iService = lp_servicenumber(service); - - /* now handle the special case of a home directory */ - if (iService < 0) - { - char *phome_dir = get_user_home_dir(service); - - if(!phome_dir) - { - /* - * Try mapping the servicename, it may - * be a Windows to unix mapped user name. - */ - if(map_username(service)) - phome_dir = get_user_home_dir(service); - } - - DEBUG(3,("checking for home directory %s gave %s\n",service, - phome_dir?phome_dir:"(NULL)")); - - iService = add_home_service(service,service /* 'username' */, phome_dir); - } - - /* If we still don't have a service, attempt to add it as a printer. */ - if (iService < 0) - { - int iPrinterService; - - if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) - { - char *pszTemp; - - DEBUG(3,("checking whether %s is a valid printer name...\n", service)); - pszTemp = lp_printcapname(); - if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) - { - DEBUG(3,("%s is a valid printer name\n", service)); - DEBUG(3,("adding %s as a printer service\n", service)); - lp_add_printer(service, iPrinterService); - iService = lp_servicenumber(service); - if (iService < 0) - DEBUG(0,("failed to add %s as a printer service!\n", service)); - } - else - DEBUG(3,("%s is not a valid printer name\n", service)); - } - } - - /* Check for default vfs service? Unsure whether to implement this */ - if (iService < 0) - { - } - - /* just possibly it's a default service? */ - if (iService < 0) - { - char *pdefservice = lp_defaultservice(); - if (pdefservice && *pdefservice && - !strequal(pdefservice,service) && - !strstr(service,"..")) - { - /* - * We need to do a local copy here as lp_defaultservice() - * returns one of the rotating lp_string buffers that - * could get overwritten by the recursive find_service() call - * below. Fix from Josef Hinteregger . - */ - pstring defservice; - pstrcpy(defservice, pdefservice); - iService = find_service(defservice); - if (iService >= 0) - { - all_string_sub(service, "_","/",0); - iService = lp_add_service(service, iService); - } - } - } - - if (iService >= 0) - if (!VALID_SNUM(iService)) - { - DEBUG(0,("Invalid snum %d for %s\n",iService, service)); - iService = -1; - } - - if (iService < 0) - DEBUG(3,("find_service() failed to find service %s\n", service)); - - return (iService); + int iService; + + all_string_sub(service,"\\","/",0); + + iService = lp_servicenumber(service); + + /* now handle the special case of a home directory */ + if (iService < 0) { + char *phome_dir = get_user_home_dir(service); + + if(!phome_dir) { + /* + * Try mapping the servicename, it may + * be a Windows to unix mapped user name. + */ + if(map_username(service)) + phome_dir = get_user_home_dir(service); + } + + DEBUG(3,("checking for home directory %s gave %s\n",service, + phome_dir?phome_dir:"(NULL)")); + + iService = add_home_service(service,service /* 'username' */, phome_dir); + } + + /* If we still don't have a service, attempt to add it as a printer. */ + if (iService < 0) { + int iPrinterService; + + if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) { + char *pszTemp; + + DEBUG(3,("checking whether %s is a valid printer name...\n", service)); + pszTemp = lp_printcapname(); + if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) { + DEBUG(3,("%s is a valid printer name\n", service)); + DEBUG(3,("adding %s as a printer service\n", service)); + lp_add_printer(service, iPrinterService); + iService = lp_servicenumber(service); + if (iService < 0) { + DEBUG(0,("failed to add %s as a printer service!\n", service)); + } + } else { + DEBUG(3,("%s is not a valid printer name\n", service)); + } + } + } + + /* Check for default vfs service? Unsure whether to implement this */ + if (iService < 0) { + } + + /* just possibly it's a default service? */ + if (iService < 0) { + char *pdefservice = lp_defaultservice(); + if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr(service,"..")) { + /* + * We need to do a local copy here as lp_defaultservice() + * returns one of the rotating lp_string buffers that + * could get overwritten by the recursive find_service() call + * below. Fix from Josef Hinteregger . + */ + pstring defservice; + pstrcpy(defservice, pdefservice); + iService = find_service(defservice); + if (iService >= 0) { + all_string_sub(service, "_","/",0); + iService = lp_add_service(service, iService); + } + } + } + + if (iService >= 0) { + if (!VALID_SNUM(iService)) { + DEBUG(0,("Invalid snum %d for %s\n",iService, service)); + iService = -1; + } + } + + if (iService < 0) + DEBUG(3,("find_service() failed to find service %s\n", service)); + + return (iService); } @@ -218,6 +209,7 @@ int find_service(fstring service) do some basic sainity checks on the share. This function modifies dev, ecode. ****************************************************************************/ + static NTSTATUS share_sanity_checks(int snum, fstring dev) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e2df517f40..38fed4beae 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -249,6 +249,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i open_size = IVAL(params,14); pname = ¶ms[28]; + if (IS_IPC(conn)) + return(ERROR_DOS(ERRSRV,ERRaccess)); + srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); @@ -257,9 +260,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", fname,open_mode, open_attr, open_ofun, open_size)); - if (IS_IPC(conn)) - return(ERROR_DOS(ERRSRV,ERRaccess)); - /* XXXX we need to handle passed times, sattr and flags */ unix_convert(fname,conn,0,&bad_path,&sbuf); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 284e24e7b1..4f3234775a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -863,8 +863,8 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir) DEBUG(3,("reduce_name [%s] [%s]\n",s,dir)); - /* remove any double slashes */ - all_string_sub(s,"//","/",0); + /* We know there are no double slashes as this comes from srvstr_get_path(). + and has gone through check_path_syntax(). JRA */ pstrcpy(base_name,s); p = strrchr_m(base_name,'/'); @@ -915,17 +915,19 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir) { size_t l = strlen(dir2); - if (dir2[l-1] == '/') + char *last_slash = strrchr_m(dir2, '/'); + + if (last_slash && (last_slash[1] == '\0')) l--; if (strncmp(newname,dir2,l) != 0) { vfs_ChDir(conn,wd); - DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l)); + DEBUG(2,("Bad access attempt: s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l)); return(False); } if (!readlink_check(conn, dir, newname)) { - DEBUG(2, ("Bad access attemt? %s is a symlink outside the share path", s)); + DEBUG(2, ("Bad access attemt: %s is a symlink outside the share path", s)); return(False); } @@ -947,4 +949,3 @@ BOOL reduce_name(connection_struct *conn, pstring s, const char *dir) return(True); #endif } - -- cgit From 5e412188e9b9f29f52c45ac276934f1a6be3b3a8 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 7 Mar 2004 00:50:37 +0000 Subject: Merge from HEAD. (This used to be commit 89f3173f4f4e9a16f24b25f550065b50577f3f4c) --- source3/smbd/vfs-wrap.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 4f2d82734f..5393dfc755 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -359,7 +359,11 @@ static int copy_reg(const char *source, const char *dest) * But root probably wants to know, e.g. if NFS disallows it. */ +#ifdef HAVE_FCHOWN if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) +#else + if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) +#endif goto err; /* -- cgit From 3f14e8eb9dd9893ed195853dd7cf46ee5c2d5133 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 8 Mar 2004 21:54:54 +0000 Subject: Fix assumption about following directory sep in check_path_syntax(). We need to try and convert 1 byte, then 2 bytes if that fails. Fixes bug reported by Simo. Jeremy. (This used to be commit 8702d0089619c7321b93e59d35f43ef32dce7b78) --- source3/smbd/reply.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c0d5234f47..1ff969493e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -114,14 +114,20 @@ static NTSTATUS check_path_syntax(pstring destname, const pstring srcname) /* * Potential mb char with second char a directory separator. * All the encodings we care about are 2 byte only, so do a - * conversion to unicode. If the 2 byte char won't convert then - * it's probably a one byte char with a real directory separator - * following, so only copy one byte. If it will convert then - * copy both bytes. + * conversion to unicode. If the one byte char converts then + * it really is a directory separator following. Otherwise if + * the two byte character converts (and it should or our assumption + * about character sets is broken and we panic) then copy both + * bytes as it's a MB character, not a directory separator. */ + uint16 ucs2_val; - if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) { + if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2) == 2) { + ; + } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) { *d++ = *s++; + } else { + smb_panic("check_path_syntax: directory separator assumptions invalid !\n"); } } /* Just copy the char (or the second byte of the mb char). */ -- cgit From c9b7cbbfa572512cd0348817965b99fd1df01285 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Mar 2004 00:17:14 +0000 Subject: Added strstr_m() function. Use in all places where we might run into mb (should fix the mb service name problem, can't remember the bugid). Jeremy. (This used to be commit 94a272b9a881ec0004c5da2a7242b0a818da5630) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/service.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e3df8a11d0..d928445d94 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -542,7 +542,7 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, if (as_root) { /* The password program *must* contain the user name to work. Fail if not. */ - if (strstr(passwordprogram, "%u") == NULL) { + if (strstr_m(passwordprogram, "%u") == NULL) { DEBUG(0,("chgpasswd: Running as root the 'passwd program' parameter *MUST* contain \ the string %%u, and the given string %s does not.\n", passwordprogram )); return False; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a53b9267b7..08b6648249 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -174,7 +174,7 @@ int find_service(fstring service) /* just possibly it's a default service? */ if (iService < 0) { char *pdefservice = lp_defaultservice(); - if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr(service,"..")) { + if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) { /* * We need to do a local copy here as lp_defaultservice() * returns one of the rotating lp_string buffers that -- cgit From f089f978c22513fd88216b83a1b877cb8798c834 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 9 Mar 2004 15:29:16 +0000 Subject: fix build with gcc 2.96 and --with-developer (This used to be commit 11fc4da07f232c38e04c6443e5d0f829e16b0a18) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1ff969493e..5bf8ca0a2d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -146,10 +146,10 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len { pstring tmppath; char *tmppath_ptr = tmppath; + size_t ret; #ifdef DEVELOPER SMB_ASSERT(dest_len == sizeof(pstring)); #endif - size_t ret; if (src_len == 0) { ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags); -- cgit From addfc95df264a4af55516620d79c995e8279793d Mon Sep 17 00:00:00 2001 From: Rafal Szczesniak Date: Tue, 9 Mar 2004 21:47:49 +0000 Subject: Yet another '\n' termination of debug message. rafal (This used to be commit 3e57c2c6850655da77e25de4cb047cc27741ca9c) --- source3/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index dd92cc4e4d..e5465b902c 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -293,7 +293,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, return api_no_reply(outbuf, mdrcnt); } - DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum)); + DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum)); /* record maximum data length that can be transmitted in an SMBtrans */ p->max_trans_reply = mdrcnt; -- cgit From 46a718189c261b1c4969faf1feae79b9feb6f1f0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Mar 2004 23:26:58 +0000 Subject: Fix dfs referrals - don't use check_path_syntax. Also use mb char calls in dfs code. Jeremy. (This used to be commit 42175b4518764e484d33d9fbfba3b78ba4102ead) --- source3/smbd/trans2.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 38fed4beae..19269cbc6c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3390,7 +3390,6 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, pstring pathname; int reply_size = 0; int max_referral_level; - NTSTATUS status = NT_STATUS_OK; DEBUG(10,("call_trans2getdfsreferral\n")); @@ -3402,11 +3401,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, if(!lp_host_msdfs()) return ERROR_DOS(ERRDOS,ERRbadfunc); - srvstr_get_path(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - + srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0) return UNIXERROR(ERRDOS,ERRbadfile); -- cgit From 83560bfcfae6d2de0c29b7ac4e012e4bbe911c8f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Mar 2004 00:31:47 +0000 Subject: Fix processing of pathnames with embedded '\\' characters (0x5c) in CP932 character set. Because of the allowing of "broken conversions" for people who have broken iconv libraries we can't rely on the return from convert_string() to be valid - we must check errno instead. This is ripe for revisiting at some stage. I prefer adding a bool parameter to all convert_string_XX varients to specify if we will allow broken conversions or not. With "allow_broken_conversions" set to false we could then rely on the return from convert_string rather than checking errno. Jeremy. (This used to be commit 74722f28659ac369676e898fda48d3d9ab265045) --- source3/smbd/reply.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5bf8ca0a2d..dc9f0be401 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -45,7 +45,7 @@ extern BOOL global_encrypted_passwords_negotiated; set. ****************************************************************************/ -static NTSTATUS check_path_syntax(pstring destname, const pstring srcname) +NTSTATUS check_path_syntax(pstring destname, const pstring srcname) { char *d = destname; const char *s = srcname; @@ -122,12 +122,30 @@ static NTSTATUS check_path_syntax(pstring destname, const pstring srcname) */ uint16 ucs2_val; - if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2) == 2) { + + /* + * We know the following will return 2 bytes. What + * we need to know was if errno was set. + * Note that if CH_UNIX is utf8 a string may be 3 + * bytes, but this is ok as mb utf8 characters don't + * contain embedded directory separators. We are really checking + * for mb UNIX asian characters like Japanese (SJIS) here. + * JRA. + */ + + errno = 0; + convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2); + if (errno == 0) { ; - } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) { - *d++ = *s++; } else { - smb_panic("check_path_syntax: directory separator assumptions invalid !\n"); + errno = 0; + convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2); + if (errno == 0) { + *d++ = *s++; + } else { + DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n")); + return NT_STATUS_INVALID_PARAMETER; + } } } /* Just copy the char (or the second byte of the mb char). */ -- cgit From e3f5b542707e2328030b9d5eff0836a904eccde5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Mar 2004 22:48:24 +0000 Subject: Restore the contract on all convert_stringXX() interfaces. Add a "allow_bad_conv" boolean parameter that allows broken iconv conversions to work. Gets rid of the nasty errno checks in mangle_hash2 and check_path_syntax and allows correct return code checking. Jeremy. (This used to be commit 7b96765c23637613f079d37566d95d5edd511f05) --- source3/smbd/mangle_hash2.c | 6 +----- source3/smbd/message.c | 2 +- source3/smbd/reply.c | 28 ++++++---------------------- 3 files changed, 8 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 8dfa84d054..62087e7e59 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -453,17 +453,13 @@ static BOOL is_legal_name(const char *name) /* Possible start of mb character. */ char mbc[2]; /* - * We know the following will return 2 bytes. What - * we need to know was if errno was set. * Note that if CH_UNIX is utf8 a string may be 3 * bytes, but this is ok as mb utf8 characters don't * contain embedded ascii bytes. We are really checking * for mb UNIX asian characters like Japanese (SJIS) here. * JRA. */ - errno = 0; - convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2); - if (!errno) { + if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) { /* Was a good mb string. */ name += 2; continue; diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 88f833e468..f853a91475 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -64,7 +64,7 @@ static void msg_deliver(void) * Incoming message is in DOS codepage format. Convert to UNIX. */ - if ((len = convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) { + if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg, True)) < 0 || !msg) { DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); for (i = 0; i < msgpos;) { if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dc9f0be401..4a0c06f442 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -117,35 +117,19 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) * conversion to unicode. If the one byte char converts then * it really is a directory separator following. Otherwise if * the two byte character converts (and it should or our assumption - * about character sets is broken and we panic) then copy both + * about character sets is broken and we return an error) then copy both * bytes as it's a MB character, not a directory separator. */ uint16 ucs2_val; - /* - * We know the following will return 2 bytes. What - * we need to know was if errno was set. - * Note that if CH_UNIX is utf8 a string may be 3 - * bytes, but this is ok as mb utf8 characters don't - * contain embedded directory separators. We are really checking - * for mb UNIX asian characters like Japanese (SJIS) here. - * JRA. - */ - - errno = 0; - convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2); - if (errno == 0) { + if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2, False) == 2) { ; + } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2, False) == 2) { + *d++ = *s++; } else { - errno = 0; - convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2); - if (errno == 0) { - *d++ = *s++; - } else { - DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n")); - return NT_STATUS_INVALID_PARAMETER; - } + DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n")); + return NT_STATUS_INVALID_PARAMETER; } } /* Just copy the char (or the second byte of the mb char). */ -- cgit From 6011a89e240ba8a51163baee51da98d2b32ab98c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Fri, 12 Mar 2004 14:37:37 +0000 Subject: Fix problems with very long filenames in both smbd and smbclient. It appears that we pass filename through resolve_wildcards() as pstring and use fstring temporary buffer there. As result, a long filename in unix charset (UTF-8 by default) can easily expand over 255 bytes while Windows is able to send to us such names (e.g. Japanese name of ~190 mb chars) which we unable to process through this small fstring buffer. Tested with W2K and smbclient, Japanese and Cyrillics. (This used to be commit 83dac6571f99b854ac607d4313cc3f742c1fae2e) --- source3/smbd/reply.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4a0c06f442..aeac9e4c84 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3361,14 +3361,18 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /******************************************************************* Resolve wildcards in a filename rename. + Note that name is in UNIX charset and thus potentially can be more + than fstring buffer (255 bytes) especially in default UTF-8 case. + Therefore, we use pstring inside and all calls should ensure that + name2 is at least pstring-long (they do already) ********************************************************************/ static BOOL resolve_wildcards(const char *name1, char *name2) { - fstring root1,root2; - fstring ext1,ext2; + pstring root1,root2; + pstring ext1,ext2; char *p,*p2, *pname1, *pname2; - int available_space; + int available_space, actual_space; pname1 = strrchr_m(name1,'/'); @@ -3377,21 +3381,21 @@ static BOOL resolve_wildcards(const char *name1, char *name2) if (!pname1 || !pname2) return(False); - fstrcpy(root1,pname1); - fstrcpy(root2,pname2); + pstrcpy(root1,pname1); + pstrcpy(root2,pname2); p = strrchr_m(root1,'.'); if (p) { *p = 0; - fstrcpy(ext1,p+1); + pstrcpy(ext1,p+1); } else { - fstrcpy(ext1,""); + pstrcpy(ext1,""); } p = strrchr_m(root2,'.'); if (p) { *p = 0; - fstrcpy(ext2,p+1); + pstrcpy(ext2,p+1); } else { - fstrcpy(ext2,""); + pstrcpy(ext2,""); } p = root1; @@ -3423,7 +3427,11 @@ static BOOL resolve_wildcards(const char *name1, char *name2) available_space = sizeof(pstring) - PTR_DIFF(pname2, name2); if (ext2[0]) { - snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); + actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); + if (actual_space >= available_space - 1) { + DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n", + actual_space - available_space)); + } } else { pstrcpy_base(pname2, root2, name2); } -- cgit From 95fee5e3bf509eee1a546ebdd23f6bdfd0cf7a20 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Mar 2004 20:24:05 +0000 Subject: Fix from Robert.Dahlem@gmx.net (Robert Dahlem) for bugid #1048 when mangled names are turned off. Jeremy. (This used to be commit 29909ce26ac9a0d8e631b1ed884c525674ee5606) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 19269cbc6c..2f164dafa2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -684,7 +684,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, * a Win2k client bug. JRA. */ memset(p,'\0',26); - if (!was_8_3) { + if (!was_8_3 && lp_manglednames(SNUM(conn))) { pstring mangled_name; pstrcpy(mangled_name, fname); mangle_map(mangled_name,True,True,SNUM(conn)); @@ -806,7 +806,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, * a Win2k client bug. JRA. */ memset(p,'\0',26); - if (!was_8_3) { + if (!was_8_3 && lp_manglednames(SNUM(conn))) { pstring mangled_name; pstrcpy(mangled_name, fname); mangle_map(mangled_name,True,True,SNUM(conn)); -- cgit From fd2d4f87d440f24df0adc4cc29f22051536b0dee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Mar 2004 00:28:53 +0000 Subject: First part of patch from moriyama@miraclelinux.com (MORIYAMA Masayuki) to fix up netbios names with mb strings. Includes reformat of libsmb/nmblib.c so it's readable. Jeremy. (This used to be commit 966e49a48c352563cdd7f75fe2768f2d6612ec7e) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index aeac9e4c84..bca7a75fbb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -171,7 +171,7 @@ int reply_special(char *inbuf,char *outbuf) int outsize = 4; int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); - pstring name1,name2; + fstring name1,name2; char name_type = 0; static BOOL already_got_session = False; -- cgit From 6b9dbbcd249360fb9acd61d6900baccf621c9cce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Mar 2004 02:16:21 +0000 Subject: Modified fix for bugid #784. Based on a patch from moriyama@miraclelinux.com (MORIYAMA Masayuki). Don't use nstrings to hold workgroup and netbios names. The problem with them is that MB netbios and workgroup names in unix charset (particularly utf8) may be up to 3x bigger than the name when represented in dos charset (ie. cp932). So go back to using fstrings for these but translate into nstrings (ie. 16 byte length values) for transport on the wire. Jeremy. (This used to be commit b4ea493599ab414f7828b83f40a5a8b43479ff64) --- source3/smbd/negprot.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 28e3cf97d1..96961368fb 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -169,6 +169,8 @@ static int reply_lanman2(char *inbuf, char *outbuf) static int negprot_spnego(char *p) { DATA_BLOB blob; + nstring dos_name; + fstring unix_name; uint8 guid[17]; const char *OIDs_krb5[] = {OID_KERBEROS5, OID_KERBEROS5_OLD, @@ -181,7 +183,11 @@ static int negprot_spnego(char *p) global_spnego_negotiated = True; ZERO_STRUCT(guid); - safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1); + + safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1); + strlower_m(unix_name); + push_ascii_nstring(dos_name, unix_name); + safe_strcpy((char *)guid, dos_name, sizeof(guid)-1); #ifdef DEVELOPER /* valgrind fixer... */ @@ -192,8 +198,6 @@ static int negprot_spnego(char *p) } #endif - strlower_m((char *)guid); - #if 0 /* strangely enough, NT does not sent the single OID NTLMSSP when not a ADS member, it sends no OIDs at all -- cgit From d24b8a2032a2e92d954781e610ab535361fefd88 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 16 Mar 2004 16:41:54 +0000 Subject: BUG 1165, 1126: Fix bug with secondary groups (security = ads) and winbind use default domain = yes (This used to be commit f2eaa14b1eb7e89c945b2b06a48e17998c75d620) --- source3/smbd/sesssetup.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c42a35e809..d91aa94728 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -143,7 +143,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB ticket; char *client, *p, *domain; fstring netbios_domain_name; - const struct passwd *pw; + struct passwd *pw; char *user; int sess_vuid; NTSTATUS ret; @@ -154,6 +154,7 @@ static int reply_spnego_kerberos(connection_struct *conn, uint8 tok_id[2]; BOOL foreign = False; DATA_BLOB nullblob = data_blob(NULL, 0); + fstring real_username; ZERO_STRUCT(ticket); ZERO_STRUCT(auth_data); @@ -239,7 +240,9 @@ static int reply_spnego_kerberos(connection_struct *conn, asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client); - pw = smb_getpwnam( user ); + /* lookup the passwd struct, create a new user if necessary */ + + pw = smb_getpwnam( user, real_username, True ); if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); @@ -251,10 +254,11 @@ static int reply_spnego_kerberos(connection_struct *conn, /* setup the string used by %U */ - sub_set_smb_name(pw->pw_name); + sub_set_smb_name( real_username ); reload_services(True); - if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { + if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) + { DEBUG(1,("make_server_info_from_pw failed!\n")); SAFE_FREE(user); SAFE_FREE(client); -- cgit From e2fd98af575a5c240593f21df442eb035f35e892 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 16 Mar 2004 17:18:57 +0000 Subject: Fix check_path_syntax() for multibyte encodings which have no '\' as second byte. This is intermediate fix as discussed with Jeremy until we move check_path_syntax() to UCS2 internally where all ambiguity is resolved. Please add other encodings into charcnv.c with such property.' ' (This used to be commit 2c404f6ba988d68c6f44df9409c0de319553de10) --- source3/smbd/reply.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bca7a75fbb..48894308d1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -33,6 +33,7 @@ extern char magic_char; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; +extern BOOL is_unix_charset_unsafe; extern int global_oplock_break; unsigned int smb_echo_count = 0; @@ -110,7 +111,8 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) } s++; } else { - if ((*s & 0x80) && IS_DIRECTORY_SEP(s[1])) { + /* Activate this codepath only if we know that Unix charset may contain unsafe '\\' */ + if ((is_unix_charset_unsafe == True) && ((*s & 0x80) && IS_DIRECTORY_SEP(s[1]))) { /* * Potential mb char with second char a directory separator. * All the encodings we care about are 2 byte only, so do a -- cgit From 9073c95b97386ad2a3d1f90bc41b735f4a53ed3d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 16 Mar 2004 19:06:03 +0000 Subject: BUG 979 -- fix quota display on AIX; patch from Heinrich.Mislik@univie.ac.at (Heinrich Mislik) (This used to be commit 760b63496ccc908c76ea5d3ed474cbbca268ad61) --- source3/smbd/quotas.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index c0b2db6173..e439c1e571 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -994,7 +994,11 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #elif defined(AIX) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ + save_re_uid(); + if (set_re_uid() != 0) + return False; r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); + restore_re_uid(); #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ -- cgit From acad182a3f13e55c2156994e599eb0b1e0f1960e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Mar 2004 21:59:11 +0000 Subject: Add function next_mb_char_size() that returns a size_t of the number of bytes in the mb character at a pointer. Will be useful in fixing check_path_syntax() to not use a "blacklist". Also re-added my (C) to reply.c. I mean, really - I've been adding code to the file for over 10 years and I recognise many of the fuctions as mine ! :-). Jeremy. (This used to be commit d2b2a39fd2f2e06cc4aebf081876985f0b28b477) --- source3/smbd/reply.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 48894308d1..c470d15645 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3,6 +3,7 @@ Main SMB reply routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Bartlett 2001 + Copyright (C) Jeremy Allison 1992-2004. 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 -- cgit From aa2e306a015ad070cf4bf8eb531f1871803bb016 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Mar 2004 02:08:31 +0000 Subject: Change check_path_syntax() to use the new next_mb_char_size() function to make it generic. Remove the mb-codepage "blacklist". Alexander, please check this fix as it reverts your blacklist changes, but I'm hoping it fixes the problem in a more generic way for all charsets. I'm not trying to trample on your (excellent!) work here, just make things more generic without special cases. Jeremy. (This used to be commit 5a9324525acc02e6bf14528679816b35929a564e) --- source3/smbd/reply.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c470d15645..0fe73cddc2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -34,7 +34,6 @@ extern char magic_char; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; -extern BOOL is_unix_charset_unsafe; extern int global_oplock_break; unsigned int smb_echo_count = 0; @@ -88,6 +87,8 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } /* Go back one level... */ + /* We know this is safe as '/' cannot be part of a mb sequence. */ + /* NOTE - if this assumption is invalid we are not in good shape... */ while (d > destname) { if (*d == '/') break; @@ -112,31 +113,20 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) } s++; } else { - /* Activate this codepath only if we know that Unix charset may contain unsafe '\\' */ - if ((is_unix_charset_unsafe == True) && ((*s & 0x80) && IS_DIRECTORY_SEP(s[1]))) { - /* - * Potential mb char with second char a directory separator. - * All the encodings we care about are 2 byte only, so do a - * conversion to unicode. If the one byte char converts then - * it really is a directory separator following. Otherwise if - * the two byte character converts (and it should or our assumption - * about character sets is broken and we return an error) then copy both - * bytes as it's a MB character, not a directory separator. - */ - - uint16 ucs2_val; - - if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2, False) == 2) { - ; - } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2, False) == 2) { + switch(next_mb_char_size(s)) { + case 4: *d++ = *s++; - } else { - DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n")); + case 3: + *d++ = *s++; + case 2: + *d++ = *s++; + case 1: + *d++ = *s++; + break; + default: + DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); return NT_STATUS_INVALID_PARAMETER; - } } - /* Just copy the char (or the second byte of the mb char). */ - *d++ = *s++; } } *d = '\0'; -- cgit From 41ea0d35aeb984cbd3bc3baf96594ab6b67c70e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Mar 2004 19:23:48 +0000 Subject: Remove excess logging when probing for the length of the next mb char. Jeremy. (This used to be commit 6339c4690aef7692571dd4c65dd0a12d56a7ffab) --- source3/smbd/reply.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0fe73cddc2..f5c4f25e40 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -113,19 +113,23 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) } s++; } else { - switch(next_mb_char_size(s)) { - case 4: - *d++ = *s++; - case 3: - *d++ = *s++; - case 2: - *d++ = *s++; - case 1: - *d++ = *s++; - break; - default: - DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); - return NT_STATUS_INVALID_PARAMETER; + if (!(*s & 0x80)) { + *d++ = *s++; + } else { + switch(next_mb_char_size(s)) { + case 4: + *d++ = *s++; + case 3: + *d++ = *s++; + case 2: + *d++ = *s++; + case 1: + *d++ = *s++; + break; + default: + DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); + return NT_STATUS_INVALID_PARAMETER; + } } } } -- cgit From c24dccd413c41ed81454bc204c59d1fc17a54a33 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 19 Mar 2004 22:06:54 +0000 Subject: BUG 417: fix %UuGg variables expansion in include lines setging the current_user_info struct in register_vuid() -- shouldn't be any more broken than we were (This used to be commit a90c3bd281e7a62bb8482e42aa3b674eeeb5995a) --- source3/smbd/password.c | 4 ++++ source3/smbd/sesssetup.c | 9 +++++++++ 2 files changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 10c6aadb1f..9449113ddc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -273,6 +273,10 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, /* Try and turn on server signing on the first non-guest sessionsetup. */ srv_set_signing(vuser->session_key, response_blob); } + + /* fill in the current_user_info struct */ + set_current_user_info( &vuser->user ); + return vuser->vuid; } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index d91aa94728..244db6d2c1 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -282,6 +282,9 @@ static int reply_spnego_kerberos(connection_struct *conn, if (sess_vuid == -1) { ret = NT_STATUS_LOGON_FAILURE; } else { + /* current_user_info is changed on new vuid */ + reload_services( True ); + set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); @@ -355,6 +358,9 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out nt_status = NT_STATUS_LOGON_FAILURE; } else { + /* current_user_info is changed on new vuid */ + reload_services( True ); + set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); @@ -911,6 +917,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + /* current_user_info is changed on new vuid */ + reload_services( True ); + if (!server_info->guest && !srv_check_sign_mac(inbuf)) { exit_server("reply_sesssetup_and_X: bad smb signature"); } -- cgit From 7cea655424467770600a7866eb3ac909ddf8fcab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Mar 2004 23:46:48 +0000 Subject: Fix for #1064 - ensure truncate attribute checking is done correctly on "hidden" dot files. Jeremy. (This used to be commit a6045c904fbe7df111c520134581bfd4f1ca67a8) --- source3/smbd/dosmode.c | 30 ++++++++++++++++++++++++++---- source3/smbd/open.c | 3 ++- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index fb72a2eafc..8353baeb21 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -111,16 +111,14 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) return(result); } - /**************************************************************************** change a unix mode to a dos mode ****************************************************************************/ -uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) + +uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf) { int result = 0; - DEBUG(8,("dos_mode: %s\n", path)); - if ((sbuf->st_mode & S_IWUSR) == 0) result |= aRONLY; @@ -149,6 +147,30 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) #endif #endif + DEBUG(8,("dos_mode_from_sbuf returning ")); + + if (result & aHIDDEN) DEBUG(8, ("h")); + if (result & aRONLY ) DEBUG(8, ("r")); + if (result & aSYSTEM) DEBUG(8, ("s")); + if (result & aDIR ) DEBUG(8, ("d")); + if (result & aARCH ) DEBUG(8, ("a")); + + DEBUG(8,("\n")); + return result; +} + +/**************************************************************************** + change a unix mode to a dos mode +****************************************************************************/ +uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) +{ + int result = 0; + + DEBUG(8,("dos_mode: %s\n", path)); + + result = dos_mode_from_sbuf(conn, sbuf); + + /* Now do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { char *p = strrchr_m(path,'/'); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e688f8de48..084ae9a1bf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -754,7 +754,8 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex old_dos_mode = dos_mode(conn, path, &sbuf); sbuf.st_mode = new_mode; - new_dos_mode = dos_mode(conn, path, &sbuf); + /* The new mode conversion shouldn't look at pathname. */ + new_dos_mode = dos_mode_from_sbuf(conn, &sbuf); noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); -- cgit From 8d6aee954a62575e71f8c0d97429e09eaec4c132 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Mar 2004 23:02:53 +0000 Subject: Fix bug #1211. Ensure accept socket is in non-blocking state in case of network error after select() returns true. (See accept man page on Linux). Patch from rabies@meep.org (Richard Garnish). Jeremy. (This used to be commit 6ca158291cf1f533ef18b542c84f22e9780c0966) --- source3/smbd/server.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1de33739b2..53d07fd905 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -249,7 +249,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); - + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); close(s); @@ -286,6 +289,9 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("open_sockets_smbd: listen: %s\n", strerror(errno))); @@ -378,6 +384,9 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ continue; } + /* Ensure child is set to blocking mode */ + set_blocking(smbd_server_fd(),True); + if (smbd_server_fd() != -1 && interactive) return True; -- cgit From deee8fae47be8722f737d4a2583e93f85658c126 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Mar 2004 05:38:20 +0000 Subject: As I raised (without objection) on the mailing list a while back, this patch removes the 'unicode' smb.conf option. Clients are as always free not to negotiate unicode, but Samba will always accept unicode in smbd. Setting 'unicode = no' caused me more client BSODs than any other option I have seen, and I really want to protect some of our more silly users, who will, no matter what, select and change every option... Andrew Bartlett (This used to be commit 3f9177bd5df68809294335a36919994893ff8ead) --- source3/smbd/negprot.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 96961368fb..1843c174bb 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -251,7 +251,7 @@ static int reply_nt1(char *inbuf, char *outbuf) capabilities |= CAP_EXTENDED_SECURITY; } - capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; + capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE; if (lp_unix_extensions()) { capabilities |= CAP_UNIX; @@ -266,10 +266,6 @@ static int reply_nt1(char *inbuf, char *outbuf) if (lp_readraw() && lp_writeraw()) capabilities |= CAP_RAW_MODE; - /* allow for disabling unicode */ - if (lp_unicode()) - capabilities |= CAP_UNICODE; - if (lp_nt_status_support()) capabilities |= CAP_STATUS32; -- cgit From e9a7e67e01c115328f95690cbf63ca1ef0b4d408 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Mar 2004 07:33:59 +0000 Subject: Merge from HEAD the SMB signing patch that I developed a couple of weeks ago. This patch re-adds support for 'optional' SMB signing. It also ensures that we are much more careful about when we enable signing, particularly with on-the-fly smb.conf reloads. The client code will now attempt to use smb signing by default, and disable it if the server doesn't correctly support it. Andrew Bartlett (This used to be commit e27b5cbe75d89ec839dafd52dd33101885a4c263) --- source3/smbd/password.c | 2 +- source3/smbd/sesssetup.c | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9449113ddc..ef5d0a97ac 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -269,7 +269,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, vuser->homes_snum = -1; } - if (lp_server_signing() && !vuser->guest && !srv_is_signing_active()) { + if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) { /* Try and turn on server signing on the first non-guest sessionsetup. */ srv_set_signing(vuser->session_key, response_blob); } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 244db6d2c1..b8777be697 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -294,14 +294,14 @@ static int reply_spnego_kerberos(connection_struct *conn, SSVAL(outbuf, smb_uid, sess_vuid); - if (!server_info->guest) { + if (!server_info->guest && !srv_signing_started()) { /* We need to start the signing engine * here but a W2K client sends the old * "BSRSPYL " signature instead of the * correct one. Subsequent packets will * be correct. */ - srv_check_sign_mac(inbuf); + srv_check_sign_mac(inbuf, False); } } @@ -370,14 +370,15 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out SSVAL(outbuf,smb_uid,sess_vuid); - if (!server_info->guest) { + if (!server_info->guest && !srv_signing_started()) { /* We need to start the signing engine * here but a W2K client sends the old * "BSRSPYL " signature instead of the * correct one. Subsequent packets will * be correct. */ - srv_check_sign_mac(inbuf); + + srv_check_sign_mac(inbuf, False); } } } @@ -920,7 +921,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* current_user_info is changed on new vuid */ reload_services( True ); - if (!server_info->guest && !srv_check_sign_mac(inbuf)) { + if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) { exit_server("reply_sesssetup_and_X: bad smb signature"); } -- cgit From 578d7157558e4303bfed583cded4c4f35b4e2911 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 29 Mar 2004 23:39:13 +0000 Subject: Setting EA's to zero length deletes them. Jeremy. (This used to be commit 01fb8717628d1daad19725a97f6ae2d729afcac2) --- source3/smbd/trans2.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2f164dafa2..9f5ef09454 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -49,6 +49,16 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) return ret; } +/**************************************************************************** + Utility functions for dealing with extended attributes. +****************************************************************************/ + +struct ea_list { + struct ea_list *next, *prev; + struct ea_struct ea; +}; + +static /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are -- cgit From 1a643a6fe9aded2530cf10177b527071b34db95f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 29 Mar 2004 23:42:48 +0000 Subject: Committed test code by mistake... removing. Jeremy. (This used to be commit 73433dc349698b1b1f128439ab40eea6cbfa1187) --- source3/smbd/trans2.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9f5ef09454..2f164dafa2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -49,16 +49,6 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) return ret; } -/**************************************************************************** - Utility functions for dealing with extended attributes. -****************************************************************************/ - -struct ea_list { - struct ea_list *next, *prev; - struct ea_struct ea; -}; - -static /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are -- cgit From d113219e78c4c03375ad03595603ece6dff94461 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Mar 2004 02:20:16 +0000 Subject: Added support for OS/2 EA's in smbd server. Test with smbtorture eatest. New protocol option "ea support" to turn them on (off by default). Conrad at Apple may like this as it allows MacOS resource forks to be stored on a file. Passes valgrind. Documentation to follow. Jeremy. (This used to be commit 8cc10a6c0550c017a62e8a3790afd2172d173e00) --- source3/smbd/posix_acls.c | 2 - source3/smbd/trans2.c | 331 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 328 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 8033c694f5..ee370437ec 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -57,8 +57,6 @@ typedef struct canon_ace { * +------+------+-------------+---------------------+-------------+--------------------+ */ -#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI" - #define PAI_VERSION_OFFSET 0 #define PAI_FLAG_OFFSET 1 #define PAI_NUM_ENTRIES_OFFSET 2 diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2f164dafa2..b1807705a0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -49,6 +49,324 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) return ret; } +/**************************************************************************** + Utility functions for dealing with extended attributes. +****************************************************************************/ + +static const char *prohibited_ea_names[] = { + SAMBA_POSIX_INHERITANCE_EA_NAME, + NULL +}; + +/**************************************************************************** + Refuse to allow clients to overwrite our private xattrs. +****************************************************************************/ + +static BOOL samba_private_attr_name(const char *unix_ea_name) +{ + int i; + + for (i = 0; prohibited_ea_names[i]; i++) { + if (strequal( prohibited_ea_names[i], unix_ea_name)) + return True; + } + return False; +} + +struct ea_list { + struct ea_list *next, *prev; + struct ea_struct ea; +}; + +/**************************************************************************** + Get one EA value. Fill in a struct ea_struct. +****************************************************************************/ + +static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, + const char *fname, char *ea_name, struct ea_struct *pea) +{ + /* Get the value of this xattr. Max size is 64k. */ + size_t attr_size = 256; + char *val = NULL; + ssize_t sizeret; + + again: + + val = talloc_realloc(mem_ctx, val, attr_size); + if (!val) { + return False; + } + + if (fsp && fsp->fd != -1) { + sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size); + } else { + sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size); + } + + if (sizeret == -1 && errno == ERANGE && attr_size != 65536) { + attr_size = 65536; + goto again; + } + + if (sizeret == -1) { + return False; + } + + DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret)); + dump_data(10, val, sizeret); + + pea->flags = 0; + if (strnequal(ea_name, "user.", 5)) { + pea->name = &ea_name[5]; + } else { + pea->name = ea_name; + } + pea->value.data = val; + pea->value.length = (size_t)sizeret; + return True; +} + +/**************************************************************************** + Return a linked list of the total EA's. Plus a guess as to the total size + (NB. The is not the total size on the wire - we need to convert to DOS + codepage for that). +****************************************************************************/ + +static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len) +{ + /* Get a list of all xattrs. Max namesize is 64k. */ + size_t ea_namelist_size = 1024; + char *ea_namelist; + char *p; + ssize_t sizeret; + int i; + struct ea_list *ea_list_head = NULL; + + if (pea_total_len) { + *pea_total_len = 0; + } + + if (!lp_ea_support(SNUM(conn))) { + return NULL; + } + + for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6; + ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) { + if (fsp && fsp->fd != -1) { + sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size); + } else { + sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size); + } + + if (sizeret == -1 && errno == ERANGE) { + ea_namelist_size *= 2; + } else { + break; + } + } + + if (sizeret == -1) + return NULL; + + DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret )); + + if (sizeret) { + for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { + struct ea_list *listp, *tmp; + + if (strnequal(p, "system.", 7) || samba_private_attr_name(p)) + continue; + + listp = talloc(mem_ctx, sizeof(struct ea_list)); + if (!listp) + return NULL; + + if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) { + return NULL; + } + + if (pea_total_len) { + *pea_total_len += 4 + strlen(p) + 1 + listp->ea.value.length; + } + DLIST_ADD_END(ea_list_head, listp, tmp); + } + } + + /* Add on 4 for total length. */ + if (pea_total_len) { + *pea_total_len += 4; + } + return ea_list_head; +} + +/**************************************************************************** + Fill a qfilepathinfo buffer with EA's. +****************************************************************************/ + +static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, + connection_struct *conn, files_struct *fsp, const char *fname) +{ + unsigned int ret_data_size = 4; + char *p = pdata; + size_t total_ea_len; + TALLOC_CTX *mem_ctx = talloc_init("fill_ea_buffer"); + struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + + SMB_ASSERT(total_data_size >= 4); + + SIVAL(pdata,0,0); + if (!mem_ctx) { + return 4; + } + + if (!ea_list) { + talloc_destroy(mem_ctx); + return 4; + } + + if (total_ea_len > total_data_size) { + talloc_destroy(mem_ctx); + return 4; + } + + total_data_size -= 4; + for (p = pdata + 4; ea_list; ea_list = ea_list->next) { + size_t dos_namelen; + fstring dos_ea_name; + push_ascii_fstring(dos_ea_name, ea_list->ea.name); + dos_namelen = strlen(dos_ea_name); + if (dos_namelen > 255 || dos_namelen == 0) { + break; + } + if (ea_list->ea.value.length > 65535) { + break; + } + if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) { + break; + } + + /* We know we have room. */ + SCVAL(p,0,ea_list->ea.flags); + SCVAL(p,1,dos_namelen); + SSVAL(p,2,ea_list->ea.value.length); + fstrcpy(p+4, dos_ea_name); + memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length); + + total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length; + p += 4 + dos_namelen + 1 + ea_list->ea.value.length; + } + + ret_data_size = PTR_DIFF(p, pdata); + talloc_destroy(mem_ctx); + SIVAL(pdata,0,ret_data_size); + return ret_data_size; +} + +static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname) +{ + size_t total_ea_len = 0; + TALLOC_CTX *mem_ctx = talloc_init("estimate_ea_size"); + + (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + talloc_destroy(mem_ctx); + return total_ea_len; +} + +/**************************************************************************** + Set or delete an extended attribute. +****************************************************************************/ + +static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, + char *pdata, int total_data) +{ + unsigned int namelen; + unsigned int ealen; + int ret; + fstring unix_ea_name; + + if (!lp_ea_support(SNUM(conn))) { + return NT_STATUS_EAS_NOT_SUPPORTED; + } + + if (total_data < 8) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); + return NT_STATUS_INVALID_PARAMETER; + } + + pdata += 4; + namelen = CVAL(pdata,1); + ealen = SVAL(pdata,2); + pdata += 4; + if (total_data < 8 + namelen + 1 + ealen) { + DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n", + (unsigned int)total_data, namelen, ealen)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (pdata[namelen] != '\0') { + DEBUG(10,("set_ea: ea name not null terminated\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ + pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE); + pdata += (namelen + 1); + + DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen)); + if (ealen) { + DEBUG(10,("set_ea: data :\n")); + dump_data(10, pdata, ealen); + } + + if (samba_private_attr_name(unix_ea_name)) { + DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); + return NT_STATUS_ACCESS_DENIED; + } + + if (ealen == 0) { + /* Remove the attribute. */ + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); + } else { + DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); + } +#ifdef ENOATTR + /* Removing a non existent attribute always succeeds. */ + DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name)); + if (ret == -1 && errno == ENOATTR) { + ret = 0; + } +#endif + } else { + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0); + } else { + DEBUG(10,("set_ea: setting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0); + } + } + + if (ret == -1) { + if (errno == ENOTSUP) { + return NT_STATUS_EAS_NOT_SUPPORTED; + } + return map_nt_error_from_unix(errno); + } + + return NT_STATUS_OK; +} + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -2048,8 +2366,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_INFO_QUERY_ALL_EAS: - data_size = 4; - SIVAL(pdata,0,0); /* ea size */ + /* We have data_size bytes to put EA's into. */ + data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname); break; case SMB_FILE_BASIC_INFORMATION: @@ -2095,8 +2413,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_EA_INFORMATION: case SMB_QUERY_FILE_EA_INFO: + { + unsigned int ea_size = estimate_ea_size(conn, fsp, fname); data_size = 4; + SIVAL(pdata,0,ea_size); break; + } /* Get the 8.3 name - used if NT SMB was negotiated. */ case SMB_QUERY_FILE_ALT_NAME_INFO: @@ -2703,7 +3025,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } case SMB_INFO_SET_EA: - return(ERROR_DOS(ERRDOS,ERReasnotsupported)); + status = set_ea(conn, fsp, fname, pdata, total_data); + if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + return ERROR_NT(status); + break; /* XXXX um, i don't think this is right. it's also not in the cifs6.txt spec. -- cgit From e86972742066783406acc598cc21661e3b09d78e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Mar 2004 22:46:15 +0000 Subject: Reformat in preparation for EA dosmode attributes. Jeremy (This used to be commit de2f149e9e687fc8cba6870d921341a6a1fd9c13) --- source3/smbd/dosmode.c | 248 +++++++++++++++++++++++++------------------------ 1 file changed, 125 insertions(+), 123 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 8353baeb21..1369c46b2f 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -21,8 +21,8 @@ #include "includes.h" /**************************************************************************** - change a dos mode to a unix mode - base permission for files: + Change a dos mode to a unix mode. + Base permission for files: if inheriting apply read/write bits from parent directory. else @@ -35,84 +35,84 @@ Then apply create mask, then add force bits. } - base permission for directories: + Base permission for directories: dos directory is represented in unix by unix's dir bit and the exec bit if !inheriting { Then apply create mask, then add force bits. } ****************************************************************************/ -mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) + +mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname) { - mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); - mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ - - if ( !IS_DOS_READONLY(dosmode) ) - result |= (S_IWUSR | S_IWGRP | S_IWOTH); - - if (fname && lp_inherit_perms(SNUM(conn))) { - char *dname; - SMB_STRUCT_STAT sbuf; - - dname = parent_dirname(fname); - DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) { - DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); - return(0); /* *** shouldn't happen! *** */ - } - - /* Save for later - but explicitly remove setuid bit for safety. */ - dir_mode = sbuf.st_mode & ~S_ISUID; - DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode)); - /* Clear "result" */ - result = 0; - } - - if (IS_DOS_DIR(dosmode)) { - /* We never make directories read only for the owner as under DOS a user - can always create a file in a read-only directory. */ - result |= (S_IFDIR | S_IWUSR); - - if (dir_mode) { - /* Inherit mode of parent directory. */ - result |= dir_mode; - } else { - /* Provisionally add all 'x' bits */ - result |= (S_IXUSR | S_IXGRP | S_IXOTH); - - /* Apply directory mask */ - result &= lp_dir_mask(SNUM(conn)); - /* Add in force bits */ - result |= lp_force_dir_mode(SNUM(conn)); - } - } else { - if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode)) - result |= S_IXUSR; - - if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode)) - result |= S_IXGRP; + mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); + mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ + + if ( !IS_DOS_READONLY(dosmode) ) + result |= (S_IWUSR | S_IWGRP | S_IWOTH); + + if (fname && lp_inherit_perms(SNUM(conn))) { + char *dname; + SMB_STRUCT_STAT sbuf; + + dname = parent_dirname(fname); + DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); + if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) { + DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); + return(0); /* *** shouldn't happen! *** */ + } + + /* Save for later - but explicitly remove setuid bit for safety. */ + dir_mode = sbuf.st_mode & ~S_ISUID; + DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode)); + /* Clear "result" */ + result = 0; + } + + if (IS_DOS_DIR(dosmode)) { + /* We never make directories read only for the owner as under DOS a user + can always create a file in a read-only directory. */ + result |= (S_IFDIR | S_IWUSR); + + if (dir_mode) { + /* Inherit mode of parent directory. */ + result |= dir_mode; + } else { + /* Provisionally add all 'x' bits */ + result |= (S_IXUSR | S_IXGRP | S_IXOTH); + + /* Apply directory mask */ + result &= lp_dir_mask(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_dir_mode(SNUM(conn)); + } + } else { + if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode)) + result |= S_IXUSR; + + if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode)) + result |= S_IXGRP; - if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode)) - result |= S_IXOTH; - - if (dir_mode) { - /* Inherit 666 component of parent directory mode */ - result |= dir_mode - & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); - } else { - /* Apply mode mask */ - result &= lp_create_mask(SNUM(conn)); - /* Add in force bits */ - result |= lp_force_create_mode(SNUM(conn)); - } - } - - DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result )); - return(result); + if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode)) + result |= S_IXOTH; + + if (dir_mode) { + /* Inherit 666 component of parent directory mode */ + result |= dir_mode & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); + } else { + /* Apply mode mask */ + result &= lp_create_mask(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_create_mode(SNUM(conn)); + } + } + + DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result )); + return(result); } /**************************************************************************** - change a unix mode to a dos mode + Change a unix mode to a dos mode. ****************************************************************************/ uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf) @@ -160,8 +160,9 @@ uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf) } /**************************************************************************** - change a unix mode to a dos mode + Change a unix mode to a dos mode. ****************************************************************************/ + uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) { int result = 0; @@ -203,7 +204,7 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) } /******************************************************************* -chmod a file - but preserve some bits + chmod a file - but preserve some bits. ********************************************************************/ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_STAT *st) @@ -297,70 +298,71 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST return( ret ); } - /******************************************************************* -Wrapper around dos_utime that possibly allows DOS semantics rather -than POSIX. + Wrapper around dos_utime that possibly allows DOS semantics rather + than POSIX. *******************************************************************/ + int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) { - extern struct current_user current_user; - SMB_STRUCT_STAT sb; - int ret = -1; - - errno = 0; - - if(SMB_VFS_UTIME(conn,fname, times) == 0) - return 0; - - if((errno != EPERM) && (errno != EACCES)) - return -1; - - if(!lp_dos_filetimes(SNUM(conn))) - return -1; - - /* We have permission (given by the Samba admin) to - break POSIX semantics and allow a user to change - the time on a file they don't own but can write to - (as DOS does). - */ - - if(SMB_VFS_STAT(conn,fname,&sb) != 0) - return -1; - - /* Check if we have write access. */ - if (CAN_WRITE(conn)) { - if (((sb.st_mode & S_IWOTH) || - conn->admin_user || - ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || - ((sb.st_mode & S_IWGRP) && - in_group(sb.st_gid,current_user.gid, - current_user.ngroups,current_user.groups)))) { - /* We are allowed to become root and change the filetime. */ - become_root(); - ret = SMB_VFS_UTIME(conn,fname, times); - unbecome_root(); - } - } - - return ret; + extern struct current_user current_user; + SMB_STRUCT_STAT sb; + int ret = -1; + + errno = 0; + + if(SMB_VFS_UTIME(conn,fname, times) == 0) + return 0; + + if((errno != EPERM) && (errno != EACCES)) + return -1; + + if(!lp_dos_filetimes(SNUM(conn))) + return -1; + + /* We have permission (given by the Samba admin) to + break POSIX semantics and allow a user to change + the time on a file they don't own but can write to + (as DOS does). + */ + + if(SMB_VFS_STAT(conn,fname,&sb) != 0) + return -1; + + /* Check if we have write access. */ + if (CAN_WRITE(conn)) { + if (((sb.st_mode & S_IWOTH) || conn->admin_user || + ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || + ((sb.st_mode & S_IWGRP) && + in_group(sb.st_gid,current_user.gid, + current_user.ngroups,current_user.groups)))) { + /* We are allowed to become root and change the filetime. */ + become_root(); + ret = SMB_VFS_UTIME(conn,fname, times); + unbecome_root(); + } + } + + return ret; } /******************************************************************* -Change a filetime - possibly allowing DOS semantics. + Change a filetime - possibly allowing DOS semantics. *******************************************************************/ + BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) { - struct utimbuf times; + struct utimbuf times; - if (null_mtime(mtime)) return(True); + if (null_mtime(mtime)) + return(True); - times.modtime = times.actime = mtime; + times.modtime = times.actime = mtime; - if (file_utime(conn, fname, ×)) { - DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); - return False; - } + if (file_utime(conn, fname, ×)) { + DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); + return False; + } - return(True); + return(True); } -- cgit From 722aa118c66b020c2b9f2b595e1af50429f13986 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Apr 2004 18:46:19 +0000 Subject: Added per-share parameter "store dos attributes". When set, will store dos attributes in an EA. Based on an original patch from tridge, but modified somewhat to cover all cases. Jeremy. (This used to be commit ed653cd468213e0be901bc654aa3748ce5837947) --- source3/smbd/dir.c | 4 +- source3/smbd/dosmode.c | 129 +++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/fake_file.c | 8 +-- source3/smbd/fileio.c | 5 +- source3/smbd/nttrans.c | 23 +++------ source3/smbd/open.c | 81 ++++++++++++++++------------- source3/smbd/posix_acls.c | 2 +- source3/smbd/reply.c | 48 +++++++---------- source3/smbd/trans2.c | 16 +++--- 9 files changed, 213 insertions(+), 103 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index bbd79e1659..06ef23ab8c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -707,7 +707,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S if(S_ISDIR(pst->st_mode)) fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - unix_mode(conn,aRONLY|aDIR, name), &smb_action); + &smb_action); else fsp = open_file_stat(conn, name, pst); @@ -763,7 +763,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return True; else fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); if (!fsp) return False; diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 1369c46b2f..d7dc63bb2f 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -45,11 +45,12 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname) { - mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); + mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ - if ( !IS_DOS_READONLY(dosmode) ) - result |= (S_IWUSR | S_IWGRP | S_IWOTH); + if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) { + result &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + } if (fname && lp_inherit_perms(SNUM(conn))) { char *dname; @@ -159,22 +160,130 @@ uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf) return result; } +/**************************************************************************** + Get DOS attributes from an EA. +****************************************************************************/ + +static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr) +{ + ssize_t sizeret; + fstring attrstr; + unsigned int dosattr; + + if (!lp_store_dos_attributes(SNUM(conn))) { + return False; + } + + *pattr = 0; + + sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); + if (sizeret == -1) { +#if defined(ENOTSUP) && defined(ENOATTR) + if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES)) { + DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n", + path, strerror(errno) )); + } +#endif + return False; + } + /* Null terminate string. */ + attrstr[sizeret] = 0; + DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr)); + + if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' || + sscanf(attrstr, "%x", &dosattr) != 1) { + DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr)); + return False; + } + + if (S_ISDIR(sbuf->st_mode)) { + dosattr |= aDIR; + } + *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK); + + DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr)); + + if (dosattr & aHIDDEN) DEBUG(8, ("h")); + if (dosattr & aRONLY ) DEBUG(8, ("r")); + if (dosattr & aSYSTEM) DEBUG(8, ("s")); + if (dosattr & aDIR ) DEBUG(8, ("d")); + if (dosattr & aARCH ) DEBUG(8, ("a")); + + DEBUG(8,("\n")); + + return True; +} + +/**************************************************************************** + Set DOS attributes in an EA. +****************************************************************************/ + +static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode) +{ + fstring attrstr; + files_struct *fsp = NULL; + BOOL ret = False; + + snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK); + if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) { + if((errno != EPERM) && (errno != EACCES)) { + return False; + } + + /* We want DOS semantics, ie allow non owner with write permission to change the + bits on a file. Just like file_utime below. + */ + + /* Check if we have write access. */ + if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) + return False; + + /* + * We need to open the file with write access whilst + * still in our current user context. This ensures we + * are not violating security in doing the setxattr. + */ + + fsp = open_file_fchmod(conn,path,sbuf); + if (!fsp) + return ret; + become_root(); + if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) { + ret = True; + } + unbecome_root(); + close_file_fchmod(fsp); + return ret; + } + DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path)); + return True; +} + /**************************************************************************** Change a unix mode to a dos mode. ****************************************************************************/ -uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) +uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) { - int result = 0; + uint32 result = 0; DEBUG(8,("dos_mode: %s\n", path)); + if (!VALID_STAT(*sbuf)) { + return 0; + } + + /* Get the DOS attributes from an EA by preference. */ + if (get_ea_dos_attribute(conn, path, sbuf, &result)) { + return result; + } + result = dos_mode_from_sbuf(conn, sbuf); /* Now do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { - char *p = strrchr_m(path,'/'); + const char *p = strrchr_m(path,'/'); if (p) p++; else @@ -207,7 +316,7 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) chmod a file - but preserve some bits. ********************************************************************/ -int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_STAT *st) +int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st) { SMB_STRUCT_STAT st1; int mask=0; @@ -215,6 +324,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST mode_t unixmode; int ret = -1; + DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname)); if (!st) { st = &st1; if (SMB_VFS_STAT(conn,fname,st)) @@ -231,6 +341,11 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST if (dos_mode(conn,fname,st) == dosmode) return(0); + /* Store the DOS attributes in an EA by preference. */ + if (set_ea_dos_attribute(conn, fname, st, dosmode)) { + return 0; + } + unixmode = unix_mode(conn,dosmode,fname); /* preserve the s bits */ diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 86d78e039a..5ccb548ba5 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -26,7 +26,7 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, - int share_mode,int ofun, mode_t mode,int oplock_request, + int share_mode,int ofun, uint32 new_dos_attr, int oplock_request, int *Access,int *action) { extern struct current_user current_user; @@ -35,7 +35,7 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect if (fake_file_type == 0) { return open_file_shared1(conn,fname,psbuf,desired_access, - share_mode,ofun,mode, + share_mode,ofun,new_dos_attr, oplock_request,Access,action); } @@ -51,8 +51,8 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect if(!fsp) return NULL; - DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", - fname, fsp->fnum, share_mode, ofun, (int)mode, oplock_request )); + DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, oplock request = %d\n", + fname, fsp->fnum, share_mode, ofun, oplock_request )); if (!check_name(fname,conn)) { file_free(fsp); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 3462a3b9fa..c2fb6e3456 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -176,8 +176,9 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); fsp->size = (SMB_BIG_UINT)st.st_size; - if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) - file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); + if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { + file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); + } /* * If this is the first write and we have an exclusive oplock then setup diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 21b6db8b46..c9cc44627d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -586,11 +586,9 @@ int reply_ntcreate_and_X(connection_struct *conn, SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; - int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - mode_t unixmode; int fmode=0,rmode=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; @@ -766,8 +764,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,smb_attr | aARCH, fname); - /* * If it's a request for a directory open, deal with it separately. */ @@ -781,7 +777,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); restore_case_semantics(file_attributes); @@ -811,14 +807,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib fsp = open_file_shared1(conn,fname,&sbuf, desired_access, smb_open_mode, - smb_ofun,unixmode, oplock_request, + smb_ofun,file_attributes,oplock_request, &rmode,&smb_action); } else { /* to open a fake_file --metze */ fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf, desired_access, smb_open_mode, - smb_ofun,unixmode, oplock_request, + smb_ofun,file_attributes, oplock_request, &rmode,&smb_action); } @@ -857,7 +853,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1134,7 +1130,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o char *data = *ppdata; /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - mode_t unixmode; int fmode=0,rmode=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; @@ -1154,7 +1149,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; - int smb_attr; time_t c_time; NTSTATUS status; @@ -1192,7 +1186,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o create_options = IVAL(params,32); sd_len = IVAL(params,36); root_dir_fid = (uint16)IVAL(params,4); - smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); if (create_options & FILE_OPEN_BY_FILE_ID) { return ERROR_NT(NT_STATUS_NOT_SUPPORTED); @@ -1297,8 +1290,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,smb_attr | aARCH, fname); - /* * If it's a request for a directory open, deal with it separately. */ @@ -1318,7 +1309,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * CreateDirectory() call. */ - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1332,7 +1323,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ fsp = open_file_shared1(conn,fname,&sbuf,desired_access, - smb_open_mode,smb_ofun,unixmode, + smb_open_mode,smb_ofun,file_attributes, oplock_request,&rmode,&smb_action); if (!fsp) { @@ -1350,7 +1341,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 084ae9a1bf..8ab5dab6ac 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -741,21 +741,10 @@ static void kernel_flock(files_struct *fsp, int deny_mode) } -static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, - mode_t new_mode, mode_t *returned_mode) +static BOOL open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_mode, uint32 new_dos_mode, + mode_t existing_mode, mode_t new_mode, mode_t *returned_mode) { - uint32 old_dos_mode, new_dos_mode; uint32 noarch_old_dos_mode, noarch_new_dos_mode; - SMB_STRUCT_STAT sbuf; - - ZERO_STRUCT(sbuf); - - sbuf.st_mode = existing_mode; - old_dos_mode = dos_mode(conn, path, &sbuf); - - sbuf.st_mode = new_mode; - /* The new mode conversion shouldn't look at pathname. */ - new_dos_mode = dos_mode_from_sbuf(conn, &sbuf); noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); @@ -771,11 +760,11 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode )); /* If we're mapping SYSTEM and HIDDEN ensure they match. */ - if (lp_map_system(SNUM(conn))) { + if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) return False; } - if (lp_map_hidden(SNUM(conn))) { + if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; } @@ -787,10 +776,10 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex ****************************************************************************/ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, - int share_mode,int ofun, mode_t mode,int oplock_request, + int share_mode,int ofun, uint32 new_dos_mode, int oplock_request, int *Access,int *action) { - return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode, + return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, new_dos_mode, oplock_request, Access, action); } @@ -800,8 +789,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, - int share_mode,int ofun, mode_t mode,int oplock_request, - int *Access,int *action) + int share_mode,int ofun, uint32 new_dos_mode, + int oplock_request, + int *Access,int *paction) { int flags=0; int flags2=0; @@ -820,6 +810,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ int open_mode=0; uint16 port = 0; mode_t new_mode = (mode_t)0; + int action; + uint32 existing_dos_mode = 0; + /* We add aARCH to this as this mode is only used if the file is created new. */ + mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname); if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are @@ -827,7 +821,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (Access) *Access = DOS_OPEN_WRONLY; if (action) - *action = FILE_WAS_CREATED; + *paction = FILE_WAS_CREATED; return print_fsp_open(conn, fname); } @@ -835,14 +829,19 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if(!fsp) return NULL; - DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", - fname, share_mode, ofun, (int)mode, oplock_request )); + DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", + fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); if (!check_name(fname,conn)) { file_free(fsp); return NULL; } + new_dos_mode &= SAMBA_ATTRIBUTES_MASK; + if (file_existed) { + existing_dos_mode = dos_mode(conn, fname, psbuf); + } + /* ignore any oplock requests if oplocks are disabled */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { oplock_request = 0; @@ -883,9 +882,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* We only care about matching attributes on file exists and truncate. */ if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { - if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { - DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", - fname, (int)psbuf->st_mode, (int)mode )); + if (!open_match_attributes(conn, fname, existing_dos_mode, new_dos_mode, + psbuf->st_mode, mode, &new_mode)) { + DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n", + fname, existing_dos_mode, new_dos_mode, + (int)psbuf->st_mode, (int)mode )); file_free(fsp); errno = EACCES; return NULL; @@ -929,7 +930,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ #endif /* O_SYNC */ if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,psbuf)))) { + (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_mode))) { if (!fcbopen) { DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); @@ -1120,16 +1121,19 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); - if (Access) + if (Access) { (*Access) = open_mode; + } - if (action) { - if (file_existed && !(flags2 & O_TRUNC)) - *action = FILE_WAS_OPENED; - if (!file_existed) - *action = FILE_WAS_CREATED; - if (file_existed && (flags2 & O_TRUNC)) - *action = FILE_WAS_OVERWRITTEN; + if (file_existed && !(flags2 & O_TRUNC)) + action = FILE_WAS_OPENED; + if (file_existed && (flags2 & O_TRUNC)) + action = FILE_WAS_OVERWRITTEN; + if (!file_existed) + action = FILE_WAS_CREATED; + + if (paction) { + *paction = action; } /* @@ -1164,6 +1168,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } + if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { + /* Files should be initially set as archive */ + if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { + file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL); + } + } + /* * Take care of inherited ACLs on created files - if default ACL not * selected. @@ -1257,7 +1268,7 @@ int close_file_fchmod(files_struct *fsp) ****************************************************************************/ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, - uint32 desired_access, int share_mode, int smb_ofun, mode_t unixmode, int *action) + uint32 desired_access, int share_mode, int smb_ofun, int *action) { extern struct current_user current_user; BOOL got_stat = False; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ee370437ec..620e123e14 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3181,7 +3181,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) the mask bits, not the real group bits, for a file with an ACL. ****************************************************************************/ -int get_acl_group_bits( connection_struct *conn, char *fname, mode_t *mode ) +int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode ) { int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f5c4f25e40..fde4ee627f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -678,8 +678,9 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size else mode &= ~aDIR; - if (check_name(fname,conn)) - ok = (file_chmod(conn,fname,mode,NULL) == 0); + if (check_name(fname,conn)) { + ok = (file_set_dosmode(conn,fname,mode,NULL) == 0); + } } else { ok = True; } @@ -1008,12 +1009,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int share_mode; SMB_OFF_T size = 0; time_t mtime=0; - mode_t unixmode; int rmode=0; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + uint16 dos_attr = SVAL(inbuf,smb_vwv1); NTSTATUS status; START_PROFILE(SMBopen); @@ -1029,10 +1030,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,aARCH,fname); - fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - unixmode, oplock_request,&rmode,NULL); + (uint32)dos_attr, oplock_request,&rmode,NULL); if (!fsp) { END_PROFILE(SMBopen); @@ -1089,7 +1088,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); #endif int smb_ofun = SVAL(inbuf,smb_vwv8); - mode_t unixmode; SMB_OFF_T size=0; int fmode=0,mtime=0,rmode=0; SMB_STRUCT_STAT sbuf; @@ -1121,9 +1119,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,smb_attr | aARCH, fname); - - fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr, oplock_request, &rmode,&smb_action); if (!fsp) { @@ -1215,7 +1211,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int com; int outsize = 0; int createmode; - mode_t unixmode; int ofun = 0; BOOL bad_path = False; files_struct *fsp; @@ -1240,8 +1235,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (createmode & aVOLID) DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); - unixmode = unix_mode(conn,createmode,fname); - if(com == SMBmknew) { /* We should fail if file exists. */ ofun = FILE_CREATE_IF_NOT_EXIST; @@ -1252,7 +1245,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* Open file in dos compatibility share mode. */ fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - ofun, unixmode, oplock_request, NULL, NULL); + ofun, (uint32)createmode, oplock_request, NULL, NULL); if (!fsp) { END_PROFILE(SMBcreate); @@ -1269,7 +1262,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); DEBUG( 2, ( "new file %s\n", fname ) ); - DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) ); + DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) ); END_PROFILE(SMBcreate); return(outsize); @@ -1283,8 +1276,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring fname; int outsize = 0; - int createmode; - mode_t unixmode; + int createattr; BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); @@ -1295,7 +1287,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBctemp); - createmode = SVAL(inbuf,smb_vwv0); + createattr = SVAL(inbuf,smb_vwv0); srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); @@ -1307,8 +1299,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(fname,conn,0,&bad_path,&sbuf); - unixmode = unix_mode(conn,createmode,fname); - tmpfd = smb_mkstemp(fname); if (tmpfd == -1) { END_PROFILE(SMBctemp); @@ -1322,7 +1312,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, fsp = open_file_shared(conn,fname,&sbuf, SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST, - unixmode, oplock_request, NULL, NULL); + (uint32)createattr, oplock_request, NULL, NULL); /* close fd from smb_mkstemp() */ close(tmpfd); @@ -1356,8 +1346,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); DEBUG( 2, ( "created temp file %s\n", fname ) ); - DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n", - fname, fsp->fd, createmode, (int)unixmode ) ); + DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n", + fname, fsp->fd, sbuf.st_mode ) ); END_PROFILE(SMBctemp); return(outsize); @@ -1384,7 +1374,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT unix_ERR_code = 0; fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); if (!fsp) { NTSTATUS ret = NT_STATUS_ACCESS_DENIED; @@ -1449,7 +1439,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOO unix_ERR_code = 0; fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); if (!fsp) { NTSTATUS ret = NT_STATUS_ACCESS_DENIED; @@ -3949,7 +3939,8 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, SMB_OFF_T ret=-1; files_struct *fsp1,*fsp2; pstring dest; - + uint32 dosattrs; + *err_ret = 0; pstrcpy(dest,dest1); @@ -3967,7 +3958,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, return(False); fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action); if (!fsp1) return(False); @@ -3975,11 +3966,12 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!target_is_directory && count) ofun = FILE_EXISTS_OPEN; + dosattrs = dos_mode(conn, src, &src_sbuf); if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) ZERO_STRUCTP(&sbuf2); fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,src_sbuf.st_mode,0,&Access,&action); + ofun,dosattrs,0,&Access,&action); if (!fsp2) { close_file(fsp1,False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b1807705a0..a88722edde 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -55,6 +55,7 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) static const char *prohibited_ea_names[] = { SAMBA_POSIX_INHERITANCE_EA_NAME, + SAMBA_XATTR_DOS_ATTRIB, NULL }; @@ -538,7 +539,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i int32 open_size; char *pname; pstring fname; - mode_t unixmode; SMB_OFF_T size=0; int fmode=0,mtime=0,rmode; SMB_INO_T inode = 0; @@ -586,9 +586,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } - unixmode = unix_mode(conn,open_attr | aARCH, fname); - - fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr, oplock_request, &rmode,&smb_action); if (!fsp) { @@ -3133,7 +3131,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA, SET_OPEN_MODE(DOS_OPEN_RDWR), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - 0, 0, &access_mode, &action); + FILE_ATTRIBUTE_NORMAL, + 0, &access_mode, &action); if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); @@ -3528,8 +3527,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode )); - if(file_chmod(conn, fname, dosmode, NULL)) { - DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); + if(file_set_dosmode(conn, fname, dosmode, NULL)) { + DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno))); return(UNIXERROR(ERRDOS,ERRnoaccess)); } } @@ -3559,7 +3558,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", new_fsp = open_file_shared(conn, fname, &sbuf, SET_OPEN_MODE(DOS_OPEN_RDWR), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - 0, 0, &access_mode, &action); + FILE_ATTRIBUTE_NORMAL, + 0, &access_mode, &action); if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); -- cgit From ff469fb2b26e4edb52dd808e9d07c6cd51d2aab9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Apr 2004 19:05:57 +0000 Subject: check_path improvements found by samba4 raw-checkpath tests. Jeremy. (This used to be commit 4081f7ce514635f3500d29a73a44bff2661b76b1) --- source3/smbd/reply.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fde4ee627f..3a11f162d2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -61,6 +61,10 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) while (IS_DIRECTORY_SEP(*s)) { s++; } + if ((s[0] == '.') && (s[1] == '\0')) { + ret = NT_STATUS_OBJECT_NAME_INVALID; + break; + } if ((d != destname) && (*s != '\0')) { /* We only care about non-leading or trailing '/' or '\\' */ *d++ = '/'; @@ -84,7 +88,8 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) } /* Are we at the start ? Can't go back further if so. */ if (d == destname) { - return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + break; } /* Go back one level... */ /* We know this is safe as '/' cannot be part of a mb sequence. */ @@ -95,7 +100,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) d--; } s += 3; - } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) { + } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || s[2] == '\0')) { /* * No mb char starts with '.' so we're safe checking the directory separator here. @@ -105,11 +110,14 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) if (s == srcname) { ret = NT_STATUS_OBJECT_NAME_INVALID; + break; } else { - if (s[2] == '\0') { - return NT_STATUS_INVALID_PARAMETER; + if (s[1] != '\0' && s[2] == '\0') { + ret = NT_STATUS_INVALID_PARAMETER; + break; } ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + break; } s++; } else { @@ -128,6 +136,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) break; default: DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); + *d = '\0'; return NT_STATUS_INVALID_PARAMETER; } } -- cgit From becfb420f743183caa49ff135948c13861fcc379 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Apr 2004 19:51:27 +0000 Subject: Fix wildcard identical rename. Jeremy. (This used to be commit 610ae1126e227f45a1affa1030ee833a341a687f) --- source3/smbd/reply.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3a11f162d2..9f311c6d57 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3852,6 +3852,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", continue; } + if (strcsequal(fname,destname)) { + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); + DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); + count++; + error = NT_STATUS_OK; + continue; + } + if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) { DEBUG(6,("file_exist %s\n", destname)); -- cgit From f16c79732e263020af94aeed0fd03835921ea29a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Apr 2004 22:11:08 +0000 Subject: Fix reply_ctemp - make compatible with w2k3. Jeremy. (This used to be commit ddb40a6b1cfed9022dadc627b38d3c3938e8e6b4) --- source3/smbd/reply.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9f311c6d57..130601cd9c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1293,6 +1293,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SMB_STRUCT_STAT sbuf; char *p, *s; NTSTATUS status; + unsigned int namelen; START_PROFILE(SMBctemp); @@ -1302,7 +1303,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBctemp); return ERROR_NT(status); } - pstrcat(fname,"\\TMXXXXXX"); + if (*fname) { + pstrcat(fname,"/TMXXXXXX"); + } else { + pstrcat(fname,"TMXXXXXX"); + } RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1342,10 +1347,13 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, s++; p = smb_buf(outbuf); +#if 0 + /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only + thing in the byte section. JRA */ SSVALS(p, 0, -1); /* what is this? not in spec */ - SSVAL(p, 2, strlen(s)); - p += 4; - p += srvstr_push(outbuf, p, s, -1, STR_ASCII); +#endif + namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE); + p += namelen; outsize = set_message_end(outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) -- cgit From db44caf191157b5a223b6bb5f6636d6e530a69c9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Apr 2004 00:04:31 +0000 Subject: Fix typo in check_path_syntax. Jeremy. (This used to be commit 018db85de4f380da9f8318ab72371185bb2ac5b4) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 130601cd9c..7498821185 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -100,7 +100,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) d--; } s += 3; - } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || s[2] == '\0')) { + } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) { /* * No mb char starts with '.' so we're safe checking the directory separator here. -- cgit From 3d5fdced72a70a658f684da2430e6b625c80540a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Apr 2004 00:17:18 +0000 Subject: Fix wildcard unlink. Jeremy. (This used to be commit 6e9b4c57ccb385acb9feaf9f7412778474231a92) --- source3/smbd/reply.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7498821185..42167c6e81 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1575,13 +1575,14 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (sys_direntry) { error = NT_STATUS_OBJECT_NAME_INVALID; - continue; + break; } slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype,bad_path); - if (!NT_STATUS_IS_OK(error)) + if (!NT_STATUS_IS_OK(error)) { continue; + } if (SMB_VFS_UNLINK(conn,fname) == 0) count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); -- cgit From c2699d25462e8684bded32adada78addf88b6df5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Apr 2004 01:21:13 +0000 Subject: Fix wildcard src with wildcard dest renames. Jeremy. (This used to be commit 58b39942444e62c9d0f98c2ba6f434d74c244a2b) --- source3/smbd/reply.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 42167c6e81..ac239c7e04 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3409,6 +3409,9 @@ static BOOL resolve_wildcards(const char *name1, char *name2) if (*p2 == '?') { *p2 = *p; p2++; + } else if (*p2 == '*') { + pstrcpy(p2, p); + break; } else { p2++; } @@ -3422,6 +3425,9 @@ static BOOL resolve_wildcards(const char *name1, char *name2) if (*p2 == '?') { *p2 = *p; p2++; + } else if (*p2 == '*') { + pstrcpy(p2, p); + break; } else { p2++; } @@ -3838,7 +3844,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", if (sysdir_entry) { error = NT_STATUS_OBJECT_NAME_INVALID; - continue; + break; } error = NT_STATUS_ACCESS_DENIED; -- cgit From 931df5850e326ad0639fe317e0ca82e6d820a68e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 5 Apr 2004 12:19:50 +0000 Subject: r39: * importing .cvsignore files * updateing WHATSNEW with vl's change (This used to be commit a7e2730ec4389e0c249886a8bfe1ee14c5abac41) --- source3/smbd/.cvsignore | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 source3/smbd/.cvsignore (limited to 'source3/smbd') diff --git a/source3/smbd/.cvsignore b/source3/smbd/.cvsignore deleted file mode 100644 index d2b1fd5b2e..0000000000 --- a/source3/smbd/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -*.po -*.po32 -build_options.c -- cgit From 991112a73cf2abd1761c0680b737fa724666820b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 5 Apr 2004 14:27:23 +0000 Subject: r49: Support SMB signing on connections using only the LANMAN password. This also corrects the 'session key' for these connections. (This used to be commit 26d8791ddedb7964c219067480cf4a7d61877765) --- source3/smbd/sesssetup.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b8777be697..902db2d288 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -881,17 +881,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(nt_status_squash(nt_status)); } - if (server_info->nt_session_key.data) { - session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length); - } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) { - session_key = data_blob(NULL, 16); - SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data, - session_key.data); + if (server_info->user_session_key.data) { + session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); } else { session_key = data_blob(NULL, 0); } - data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); /* it's ok - setup a reply */ @@ -911,8 +906,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, to a uid can get through without a password, on the same VC */ /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user); + sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user); data_blob_free(&nt_resp); + data_blob_free(&lm_resp); if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); -- cgit From bca29e537741da5a361bb28b0246d1bfac326434 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Apr 2004 14:27:48 +0000 Subject: r50: Fix bug 1139 as per fix suggested by jdev@panix.com, swap lookups for user and group - group will do an algorithmic lookup if it fails, user won't. Jeremy. (This used to be commit a205c56a75c93c82796fd68687e8c0db26459073) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 620e123e14..25e8fd802b 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1363,12 +1363,12 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, if (nt4_compatible_acls()) psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } else if (NT_STATUS_IS_OK(sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid))) { - current_ace->owner_type = GID_ACE; - current_ace->type = SMB_ACL_GROUP; } else if (NT_STATUS_IS_OK(sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid))) { current_ace->owner_type = UID_ACE; current_ace->type = SMB_ACL_USER; + } else if (NT_STATUS_IS_OK(sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid))) { + current_ace->owner_type = GID_ACE; + current_ace->type = SMB_ACL_GROUP; } else { fstring str; -- cgit From a5dde6c5cc2fce655ed1dd7c701fdaf5ed96edfc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Apr 2004 16:57:40 +0000 Subject: r59: revert session key problem (This used to be commit 40b5794ae0919c6c6f1b8a451871dcc95bbab5cc) --- source3/smbd/sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 902db2d288..abb9c24d41 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -881,8 +881,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(nt_status_squash(nt_status)); } - if (server_info->user_session_key.data) { - session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); + if (server_info->nt_session_key.data) { + session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length); } else { session_key = data_blob(NULL, 0); } -- cgit From d17425ed52b086b7046708a207e849271cedc804 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 6 Apr 2004 08:11:16 +0000 Subject: r69: Global rename of 'nt_session_key' -> 'user_session_key'. The session key could be anything, and may not be based on anything 'NT'. This is also what microsoft calls it. (This used to be commit 724e8d3f33719543146280062435c69a835c491e) --- source3/smbd/sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index abb9c24d41..902db2d288 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -881,8 +881,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(nt_status_squash(nt_status)); } - if (server_info->nt_session_key.data) { - session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length); + if (server_info->user_session_key.data) { + session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); } else { session_key = data_blob(NULL, 0); } -- cgit From bd0407258598839cbda81e1c21a5c5d8320d232a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Apr 2004 14:24:13 +0000 Subject: r81: Make EA's case independent - fix smbtorture to test for this. Jeremy. (This used to be commit 0661357484a33329c75457527416667feaf57ef9) --- source3/smbd/trans2.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a88722edde..1e7d845714 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -273,6 +273,27 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, return total_ea_len; } +/**************************************************************************** + Ensure the EA name is case insensitive by matching any existing EA name. +****************************************************************************/ + +static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name) +{ + size_t total_ea_len; + TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name"); + struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + + for (; ea_list; ea_list = ea_list->next) { + if (strequal(&unix_ea_name[5], ea_list->ea.name)) { + DEBUG(10,("canonicalize_ea_name: %s -> %s\n", + &unix_ea_name[5], ea_list->ea.name)); + safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6); + break; + } + } + talloc_destroy(mem_ctx); +} + /**************************************************************************** Set or delete an extended attribute. ****************************************************************************/ @@ -317,6 +338,8 @@ static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *f pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE); pdata += (namelen + 1); + canonicalize_ea_name(conn, fsp, fname, unix_ea_name); + DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen)); if (ealen) { DEBUG(10,("set_ea: data :\n")); @@ -341,8 +364,8 @@ static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *f } #ifdef ENOATTR /* Removing a non existent attribute always succeeds. */ - DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name)); if (ret == -1 && errno == ENOATTR) { + DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name)); ret = 0; } #endif -- cgit From 1db9257c953c93c3f26596a535e4f26b609e7955 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Apr 2004 23:01:09 +0000 Subject: r96: Stupid f&%'n UNIX extensions.... SETPATHINFO normally takes as it's param entry the filename to be acted upon.... Unless it's UNIX extensions create hardlink, or UNIX extensions create symlink. Then it's param -> newfile name data -> oldfile name. This caused me to stuff them up in 3.0.2 (and the client commands link and symlink). Fixed them, everything is now called oldname and newname - thus specifying which name should already exist (hint - the old one...) and which will be created (newname). Jeremy. (This used to be commit 21cc6ab7e8a41160a3e2970623ade7445b5214d6) --- source3/smbd/nttrans.c | 14 ++++++------ source3/smbd/trans2.c | 61 ++++++++++++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c9cc44627d..6ba74d5d50 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1500,7 +1500,7 @@ int reply_ntrename(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { int outsize = 0; - pstring name; + pstring oldname; pstring newname; char *p; NTSTATUS status; @@ -1515,13 +1515,13 @@ int reply_ntrename(connection_struct *conn, } p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); } - if( strchr_m(name, ':')) { + if( strchr_m(oldname, ':')) { /* Can't rename a stream. */ END_PROFILE(SMBntrename); return ERROR_NT(NT_STATUS_ACCESS_DENIED); @@ -1534,15 +1534,15 @@ int reply_ntrename(connection_struct *conn, return ERROR_NT(status); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH(oldname, conn, inbuf, outbuf); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); - DEBUG(3,("reply_ntrename : %s -> %s\n",name,newname)); + DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); if (rename_type == RENAME_FLAG_RENAME) { - status = rename_internals(conn, name, newname, attrs, False); + status = rename_internals(conn, oldname, newname, attrs, False); } else { - status = hardlink_internals(conn, name, newname); + status = hardlink_internals(conn, oldname, newname); } if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1e7d845714..30d6845509 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2825,32 +2825,32 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in code. ****************************************************************************/ -NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname) +NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname) { - BOOL bad_path_src = False; - BOOL bad_path_dest = False; + BOOL bad_path_oldname = False; + BOOL bad_path_newname = False; SMB_STRUCT_STAT sbuf1, sbuf2; BOOL rc, rcdest; - pstring last_component_src; - pstring last_component_dest; + pstring last_component_oldname; + pstring last_component_newname; NTSTATUS status = NT_STATUS_OK; ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); /* No wildcards. */ - if (ms_has_wild(name) || ms_has_wild(newname)) { + if (ms_has_wild(newname) || ms_has_wild(oldname)) { return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } - rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1); - if (!rc && bad_path_src) { + rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1); + if (!rc && bad_path_oldname) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } /* Quick check for "." and ".." */ - if (last_component_src[0] == '.') { - if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) { + if (last_component_oldname[0] == '.') { + if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) { return NT_STATUS_OBJECT_NAME_INVALID; } } @@ -2860,19 +2860,19 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname) return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2); - if (!rcdest && bad_path_dest) { + rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); + if (!rcdest && bad_path_newname) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } /* Quick check for "." and ".." */ - if (last_component_dest[0] == '.') { - if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) { + if (last_component_newname[0] == '.') { + if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) { return NT_STATUS_OBJECT_NAME_INVALID; } } - /* Disallow if already exists. */ + /* Disallow if newname already exists. */ if (VALID_STAT(sbuf2)) { return NT_STATUS_OBJECT_NAME_COLLISION; } @@ -2882,15 +2882,15 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname) return NT_STATUS_FILE_IS_A_DIRECTORY; } - if (ensure_link_is_safe(conn, newname, newname) != 0) + if (ensure_link_is_safe(conn, oldname, oldname) != 0) return NT_STATUS_ACCESS_DENIED; - DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", name, newname )); + DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname )); - if (SMB_VFS_LINK(conn,name,newname) != 0) { + if (SMB_VFS_LINK(conn,oldname,newname) != 0) { status = map_nt_error_from_unix(errno); - DEBUG(3,("hardlink_internals: Error %s link %s -> %s\n", - nt_errstr(status), name,newname)); + DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n", + nt_errstr(status), newname, oldname)); } return status; @@ -3380,25 +3380,27 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_SET_FILE_UNIX_LINK: { - pstring link_dest; + pstring oldname; + char *newname = fname; + /* Set a symbolic link. */ /* Don't allow this if follow links is false. */ if (!lp_symlinks(SNUM(conn))) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - if (ensure_link_is_safe(conn, link_dest, link_dest) != 0) + if (ensure_link_is_safe(conn, oldname, oldname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", - fname, link_dest )); + fname, oldname )); - if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0) + if (SMB_VFS_SYMLINK(conn,oldname,newname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); @@ -3407,18 +3409,19 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_SET_FILE_UNIX_HLINK: { - pstring link_dest; + pstring oldname; + char *newname = fname; /* Set a hard link. */ - srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", - fname, link_dest )); + fname, oldname)); - status = hardlink_internals(conn, fname, link_dest); + status = hardlink_internals(conn, oldname, newname); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } -- cgit From cd9b973b176f50ba0082305ffb0f63067f36e7d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Apr 2004 20:02:46 +0000 Subject: r150: Make 3.x pass the Samba 4.x RAW-SEARCH tests - except for the UNIX info levels, and the short case preserve names. Tested with NT - needs more testing. Will work on this more on Monday. Jeremy. (This used to be commit 88a9bca9aade3ee0ce9713857becfe0a13bbfd07) --- source3/smbd/trans2.c | 250 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 175 insertions(+), 75 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 30d6845509..16c2d83aa2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -128,9 +128,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str } /**************************************************************************** - Return a linked list of the total EA's. Plus a guess as to the total size - (NB. The is not the total size on the wire - we need to convert to DOS - codepage for that). + Return a linked list of the total EA's. Plus the total size ****************************************************************************/ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len) @@ -143,9 +141,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, int i; struct ea_list *ea_list_head = NULL; - if (pea_total_len) { - *pea_total_len = 0; - } + *pea_total_len = 0; if (!lp_ea_support(SNUM(conn))) { return NULL; @@ -186,22 +182,29 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, return NULL; } - if (pea_total_len) { - *pea_total_len += 4 + strlen(p) + 1 + listp->ea.value.length; + { + fstring dos_ea_name; + push_ascii_fstring(dos_ea_name, listp->ea.name); + *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; + DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n", + *pea_total_len, dos_ea_name, + (unsigned int)listp->ea.value.length )); } DLIST_ADD_END(ea_list_head, listp, tmp); } + /* Add on 4 for total length. */ + if (*pea_total_len) { + *pea_total_len += 4; + } } - /* Add on 4 for total length. */ - if (pea_total_len) { - *pea_total_len += 4; - } + DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len)); return ea_list_head; } /**************************************************************************** - Fill a qfilepathinfo buffer with EA's. + Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer + that was filled. ****************************************************************************/ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, @@ -210,16 +213,21 @@ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, unsigned int ret_data_size = 4; char *p = pdata; size_t total_ea_len; - TALLOC_CTX *mem_ctx = talloc_init("fill_ea_buffer"); - struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + TALLOC_CTX *mem_ctx; + struct ea_list *ea_list; SMB_ASSERT(total_data_size >= 4); SIVAL(pdata,0,0); + if (!lp_ea_support(SNUM(conn))) { + return 4; + } + mem_ctx = talloc_init("fill_ea_buffer"); if (!mem_ctx) { return 4; } + ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); if (!ea_list) { talloc_destroy(mem_ctx); return 4; @@ -230,7 +238,6 @@ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, return 4; } - total_data_size -= 4; for (p = pdata + 4; ea_list; ea_list = ea_list->next) { size_t dos_namelen; fstring dos_ea_name; @@ -258,6 +265,8 @@ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, } ret_data_size = PTR_DIFF(p, pdata); + DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n", + ret_data_size, total_ea_len )); talloc_destroy(mem_ctx); SIVAL(pdata,0,ret_data_size); return ret_data_size; @@ -266,8 +275,12 @@ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname) { size_t total_ea_len = 0; - TALLOC_CTX *mem_ctx = talloc_init("estimate_ea_size"); + TALLOC_CTX *mem_ctx = NULL; + if (!lp_ea_support(SNUM(conn))) { + return 0; + } + mem_ctx = talloc_init("estimate_ea_size"); (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); talloc_destroy(mem_ctx); return total_ea_len; @@ -961,6 +974,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, switch (info_level) { case SMB_INFO_STANDARD: + DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n")); if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -975,14 +989,24 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, nameptr = p; p += align_string(outbuf, p, 0); len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); - if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) - SCVAL(nameptr, -1, len-2); - else - SCVAL(nameptr, -1, len-1); + if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + SCVAL(nameptr, -1, len - 2); + } else { + SCVAL(nameptr, -1, 0); + } + } else { + if (len > 1) { + SCVAL(nameptr, -1, len - 1); + } else { + SCVAL(nameptr, -1, 0); + } + } p += len; break; case SMB_INFO_QUERY_EA_SIZE: + DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n")); if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -993,18 +1017,33 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,l2_cbFile,(uint32)file_size); SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); SSVAL(p,l2_attrFile,mode); - SIVAL(p,l2_cbList,0); /* No extended attributes */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + SIVAL(p,l2_cbList,ea_size); /* Extended attributes */ + } p += l2_achName; - nameptr = p; + nameptr = p - 1; len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN); - if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) - SCVAL(nameptr, -1, len-2); - else - SCVAL(nameptr, -1, len-1); + if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; + } + } else { + if (len > 1) { + len -= 1; + } else { + len = 0; + } + } + SCVAL(nameptr,0,len); p += len; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); was_8_3 = mangle_is_8_3(fname, True); p += 4; SIVAL(p,0,reskey); p += 4; @@ -1012,12 +1051,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,file_size); - SOFF_T(p,8,allocation_size); - p += 16; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; - SIVAL(p,0,0); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + SIVAL(p,0,ea_size); /* Extended attributes */ + p += 4; + } /* Clear the short name buffer. This is * IMPORTANT as not doing so will trigger * a Win2k client bug. JRA. @@ -1045,20 +1087,19 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, break; case SMB_FIND_FILE_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,file_size); - SOFF_T(p,8,allocation_size); - p += 16; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; - p += 4; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); - SIVAL(p, -4, len); - p += len; + len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII); + SIVAL(p,0,len); + p += 4 + len; len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); @@ -1066,22 +1107,25 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, break; case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,file_size); - SOFF_T(p,8,allocation_size); - p += 16; - SIVAL(p,0,nt_extmode); - p += 4; - - SIVAL(p,4,0); /* ea size */ - len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII); - SIVAL(p, 0, len); - p += 8 + len; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + SIVAL(q, 0, len); + p += len; len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; @@ -1090,6 +1134,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, break; case SMB_FIND_FILE_NAMES_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; p += 4; @@ -1104,29 +1149,37 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p = pdata + len; break; - case SMB_FIND_FILE_LEVEL_261: + case SMB_FIND_ID_FULL_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,file_size); - SOFF_T(p,8,allocation_size); - p += 16; - SIVAL(p,0,nt_extmode); - p += 4; - len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII); - SIVAL(p, 0, len); - memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */ - p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */ + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ + SIVAL(p,0,sbuf.st_dev); p += 4; + SIVAL(p,0,sbuf.st_ino); p += 4; + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + SIVAL(q, 0, len); + p += len; len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); p = pdata + len; break; - case SMB_FIND_FILE_LEVEL_262: + case SMB_FIND_ID_BOTH_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); was_8_3 = mangle_is_8_3(fname, True); p += 4; SIVAL(p,0,reskey); p += 4; @@ -1134,12 +1187,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SOFF_T(p,0,file_size); - SOFF_T(p,8,allocation_size); - p += 16; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; - SIVAL(p,0,0); p += 4; + q = p; p += 4; /* q is placeholder for name length */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } /* Clear the short name buffer. This is * IMPORTANT as not doing so will trigger * a Win2k client bug. JRA. @@ -1156,9 +1212,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,0,0); *(p+2) = 0; } - p += 2 + 24; - memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */ - p += 10; + p += 26; + SSVAL(p,0,0); p += 2; /* Reserved ? */ + SIVAL(p,0,sbuf.st_dev); p += 4; + SIVAL(p,0,sbuf.st_ino); p += 4; len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; @@ -1171,6 +1228,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, /* CIFS UNIX Extension. */ case SMB_FIND_FILE_UNIX: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); p+= 4; SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ @@ -1301,8 +1359,8 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - case SMB_FIND_FILE_LEVEL_261: - case SMB_FIND_FILE_LEVEL_262: + case SMB_FIND_ID_FULL_DIRECTORY_INFO: + case SMB_FIND_ID_BOTH_DIRECTORY_INFO: break; case SMB_FIND_FILE_UNIX: if (!lp_unix_extensions()) @@ -2356,18 +2414,33 @@ static int call_trans2qfilepathinfo(connection_struct *conn, switch (info_level) { case SMB_INFO_STANDARD: + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n")); + data_size = 22; + put_dos_date2(pdata,l1_fdateCreation,c_time); + put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); + put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ + SIVAL(pdata,l1_cbFile,(uint32)file_size); + SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); + SSVAL(pdata,l1_attrFile,mode); + break; + case SMB_INFO_QUERY_EA_SIZE: - data_size = (info_level==1?22:26); + { + unsigned int ea_size = estimate_ea_size(conn, fsp, fname); + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n")); + data_size = 26; put_dos_date2(pdata,l1_fdateCreation,c_time); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,(uint32)file_size); SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(pdata,l1_attrFile,mode); - SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */ + SIVAL(pdata,l1_attrFile+2,ea_size); break; + } case SMB_INFO_IS_NAME_VALID: + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n")); if (tran_call == TRANSACT2_QFILEINFO) { /* os/2 needs this ? really ?*/ return ERROR_DOS(ERRDOS,ERRbadfunc); @@ -2377,6 +2450,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_INFO_QUERY_EAS_FROM_LIST: + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); data_size = 24; put_dos_date2(pdata,0,c_time); put_dos_date2(pdata,4,sbuf.st_atime); @@ -2387,6 +2461,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_INFO_QUERY_ALL_EAS: + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); /* We have data_size bytes to put EA's into. */ data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname); break; @@ -2394,9 +2469,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_BASIC_INFORMATION: case SMB_QUERY_FILE_BASIC_INFO: - if (info_level == SMB_QUERY_FILE_BASIC_INFO) + if (info_level == SMB_QUERY_FILE_BASIC_INFO) { + DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n")); data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ - else { + } else { + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n")); data_size = 40; SIVAL(pdata,36,0); } @@ -2421,6 +2498,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_STANDARD_INFORMATION: case SMB_QUERY_FILE_STANDARD_INFO: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n")); data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); @@ -2436,6 +2514,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_EA_INFO: { unsigned int ea_size = estimate_ea_size(conn, fsp, fname); + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n")); data_size = 4; SIVAL(pdata,0,ea_size); break; @@ -2447,6 +2526,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, { pstring short_name; + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n")); pstrcpy(short_name,base_name); /* Mangle if not already 8.3 */ if(!mangle_is_8_3(short_name, True)) { @@ -2463,24 +2543,30 @@ static int call_trans2qfilepathinfo(connection_struct *conn, this must be *exactly* right for ACLs on mapped drives to work */ len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE); + DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n")); data_size = 4 + len; SIVAL(pdata,0,len); break; case SMB_FILE_ALLOCATION_INFORMATION: case SMB_QUERY_FILE_ALLOCATION_INFO: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n")); data_size = 8; SOFF_T(pdata,0,allocation_size); break; case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_QUERY_FILE_END_OF_FILEINFO: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n")); data_size = 8; SOFF_T(pdata,0,file_size); break; case SMB_QUERY_FILE_ALL_INFO: case SMB_FILE_ALL_INFORMATION: + { + unsigned int ea_size = estimate_ea_size(conn, fsp, fname); + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n")); put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ @@ -2496,13 +2582,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; + SIVAL(pdata,0,ea_size); pdata += 4; /* EA info */ len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); break; - + } case SMB_FILE_INTERNAL_INFORMATION: /* This should be an index number - looks like dev/ino to me :-) @@ -2510,12 +2597,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, I think this causes us to fail the IFSKIT BasicFileInformationTest. -tpot */ + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); SIVAL(pdata,0,sbuf.st_dev); SIVAL(pdata,4,sbuf.st_ino); data_size = 8; break; case SMB_FILE_ACCESS_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n")); SIVAL(pdata,0,desired_access); data_size = 4; break; @@ -2525,27 +2614,32 @@ static int call_trans2qfilepathinfo(connection_struct *conn, { size_t byte_len; byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False); + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n")); SIVAL(pdata,0,byte_len); data_size = 4 + byte_len; break; } case SMB_FILE_DISPOSITION_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n")); data_size = 1; SCVAL(pdata,0,delete_pending); break; case SMB_FILE_POSITION_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n")); data_size = 8; SOFF_T(pdata,0,pos); break; case SMB_FILE_MODE_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n")); SIVAL(pdata,0,mode); data_size = 4; break; case SMB_FILE_ALIGNMENT_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n")); SIVAL(pdata,0,0); /* No alignment needed. */ data_size = 4; break; @@ -2559,6 +2653,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_STREAM_INFO: #endif case SMB_FILE_STREAM_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n")); if (mode & aDIR) { data_size = 0; } else { @@ -2574,6 +2669,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_COMPRESSION_INFO: case SMB_FILE_COMPRESSION_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n")); SOFF_T(pdata,0,file_size); SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ @@ -2581,6 +2677,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_FILE_NETWORK_OPEN_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n")); put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ @@ -2593,6 +2690,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: + DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n")); SIVAL(pdata,0,mode); SIVAL(pdata,4,0); data_size = 8; @@ -2604,6 +2702,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_UNIX_BASIC: + DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n")); DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode)); SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */ @@ -2663,6 +2762,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, { pstring buffer; + DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK if(!S_ISLNK(sbuf.st_mode)) return(UNIXERROR(ERRSRV,ERRbadlink)); -- cgit From 5573a9ed661b5b07f52e90516edb3fbe210c9c87 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Apr 2004 22:35:28 +0000 Subject: r225: Patch from Pat.Hayward@propero.net to make the session_users list dynamic. I restricted it to 128k max to prevent DOS attacks. Jeremy. (This used to be commit 70fb2a196d83c4bde11d27608da27f956f3f19b8) --- source3/smbd/password.c | 36 ++++++++++++++++++++++++++++-------- source3/smbd/trans2.c | 2 +- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ef5d0a97ac..d15970cbef 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,7 +21,8 @@ #include "includes.h" /* users from session setup */ -static pstring session_users=""; +static char *session_userlist = NULL; +static int len_session_userlist = 0; /* this holds info on user ids that are already validated for this VC */ static user_struct *validated_users; @@ -295,14 +296,33 @@ void add_session_user(const char *user) fstrcpy(suser,passwd->pw_name); - if (suser && *suser && !in_list(suser,session_users,False)) { - if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) { - DEBUG(1,("Too many session users??\n")); - } else { - pstrcat(session_users," "); - pstrcat(session_users,suser); + if(!*suser) + return; + + if( session_userlist && in_list(suser,session_userlist,False) ) + return; + + if( !session_userlist || (strlen(suser) + strlen(session_userlist) + 2 >= len_session_userlist) ) { + char *newlist; + + if (len_session_userlist > 128 * PSTRING_LEN) { + DEBUG(3,("add_session_user: session userlist already too large.\n")); + return; + } + newlist = Realloc( session_userlist, len_session_userlist + PSTRING_LEN ); + if( newlist == NULL ) { + DEBUG(1,("Unable to resize session_userlist\n")); + return; } + if (!session_userlist) { + *newlist = '\0'; + } + session_userlist = newlist; + len_session_userlist += PSTRING_LEN; } + + safe_strcat(session_userlist," ",len_session_userlist-1); + safe_strcat(session_userlist,suser,len_session_userlist-1); } /**************************************************************************** @@ -468,7 +488,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, /* now check the list of session users */ if (!ok) { char *auser; - char *user_list = strdup(session_users); + char *user_list = strdup(session_userlist); if (!user_list) return(False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 16c2d83aa2..1d07e7851d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1239,7 +1239,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ p+= 8; - put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */ + put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */ put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */ put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */ p+= 24; -- cgit From 4938095e77b0b5334935833b34e23bde74c6849d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Apr 2004 23:08:41 +0000 Subject: r247: Fixup a couple of debug messages. Jeremy. (This used to be commit c664a277b428c036510966734ba71e43112c1cac) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1d07e7851d..a1d068e38f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -800,7 +800,7 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps time_t interpret_long_unix_date(char *p) { - DEBUG(1,("interpret_long_unix_date\n")); + DEBUG(10,("interpret_long_unix_date\n")); if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO && IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) { return -1; @@ -1348,7 +1348,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb *directory = *mask = 0; DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \ -close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", +close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, info_level, max_data_bytes)); -- cgit From 335b10ef10f9825ad52501c77bc6b77cdad39067 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 19 Apr 2004 17:05:31 +0000 Subject: r283: removing --with-cracklib after discussion with abartklet @ sambaXP (This used to be commit df94b0471eb0628aa27f534134d60b62ed123688) --- source3/smbd/chgpasswd.c | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d928445d94..ca13a167fb 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -48,16 +48,6 @@ #include "includes.h" -#ifdef HAVE_WORKING_CRACKLIB -#include - -#ifndef HAVE_CRACKLIB_DICTPATH -#ifndef CRACKLIB_DICTPATH -#define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH -#endif -#endif -#endif - extern struct passdb_ops pdb_ops; static NTSTATUS check_oem_password(const char *user, @@ -985,43 +975,6 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw DEBUG(1, ("check_oem_password: Username does not exist in system !?!\n")); } -#ifdef HAVE_WORKING_CRACKLIB - if (pass) { - /* if we can, become the user to overcome internal cracklib sillyness */ - if (!push_sec_ctx()) - return NT_STATUS_UNSUCCESSFUL; - - set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); - set_re_uid(); - } - - if (lp_use_cracklib()) { - const char *crack_check_reason; - DEBUG(4, ("change_oem_password: Checking password for user [%s]" - " against cracklib. \n", pdb_get_username(hnd))); - DEBUGADD(4, ("If this is your last message, then something is " - "wrong with cracklib, it might be missing it's " - "dictionaries at %s\n", - CRACKLIB_DICTPATH)); - dbgflush(); - - crack_check_reason = FascistCheck(new_passwd, (char *)CRACKLIB_DICTPATH); - if (crack_check_reason) { - DEBUG(1, ("Password Change: user [%s], " - "New password failed cracklib test - %s\n", - pdb_get_username(hnd), crack_check_reason)); - - /* get back to where we should be */ - if (pass) - pop_sec_ctx(); - return NT_STATUS_PASSWORD_RESTRICTION; - } - } - - if (pass) - pop_sec_ctx(); -#endif - /* * If unix password sync was requested, attempt to change * the /etc/passwd database first. Return failure if this cannot -- cgit From f789481101d38de5376254e62735891c17fbf07b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 26 Apr 2004 13:11:59 +0000 Subject: r370: The 'it does never happen -- error on close()' does happen when you exceed your quota on an AFS file system. The specific errno was thrown away by close_normal_file(). Thus we returned NT_STATUS_UNSUCCESSFUL and not NT_STATUS_DISK_FULL as we should. Fix that. (Not that this gives more sane Windows app behaviour.... :-( ) Jerry, jra, could you please look over this one, it's been quite a while since I touch file server code. Volker (This used to be commit 588351d1b37a900eb90eddd80882170c201e9162) --- source3/smbd/close.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 0700aeaa0a..8b3010c1b2 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -233,7 +233,7 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); file_free(fsp); if (err == -1 || err1 == -1) - return -1; + return errno; else return 0; } -- cgit From 77182a81f0e370584d37dc9368f0697b8cf69afd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Apr 2004 17:19:42 +0000 Subject: r408: - replace (conn->admin_user != True) with (current_user.uid != 0) because someone changed it in all other places too - fix quotas support from windows explorer we now got the unix file name of a fake_file metze (This used to be commit 87e97d7723674e3835578ef080ce554d9c5537ac) --- source3/smbd/fake_file.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/trans2.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 5ccb548ba5..d3660addf1 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -40,7 +40,7 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect } /* access check */ - if (conn->admin_user != True) { + if (current_user.uid != 0) { DEBUG(1,("access_denied to service[%s] file[%s] user[%s]\n", lp_servicename(SNUM(conn)),fname,conn->user)); errno = EACCES; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6ba74d5d50..e4ffec339b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2351,7 +2351,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, ZERO_STRUCT(qt); /* access check */ - if (conn->admin_user != True) { + if (current_user.uid != 0) { DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRDOS,ERRnoaccess); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a1d068e38f..0d84c40065 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2010,7 +2010,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned fsp.fd = -1; /* access check */ - if (conn->admin_user != True) { + if (current_user.uid != 0) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRDOS,ERRnoaccess); @@ -2108,7 +2108,7 @@ static int call_trans2setfsinfo(connection_struct *conn, DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn)))); /* access check */ - if ((conn->admin_user != True)||!CAN_WRITE(conn)) { + if ((current_user.uid != 0)||!CAN_WRITE(conn)) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRSRV,ERRaccess); -- cgit From 9b4e6c7ea6f9be7b7a29a9a467c7131342caa6b1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Apr 2004 20:47:48 +0000 Subject: r410: merge tpot's changeset 353 from trunk: Move msdfs.c into the source/smbd directory and remove source/msdfs. metze (This used to be commit 88e6e6d29ca14e0cddbc1df611051a96568dc0c9) --- source3/smbd/msdfs.c | 1019 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1019 insertions(+) create mode 100644 source3/smbd/msdfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c new file mode 100644 index 0000000000..c66f0477a8 --- /dev/null +++ b/source3/smbd/msdfs.c @@ -0,0 +1,1019 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + MSDfs services for Samba + Copyright (C) Shirish Kalele 2000 + + 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 fstring local_machine; +extern uint32 global_client_caps; + +/********************************************************************** + Parse the pathname of the form \hostname\service\reqpath + into the dfs_path structure + **********************************************************************/ + +static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) +{ + pstring pathname_local; + char* p,*temp; + + pstrcpy(pathname_local,pathname); + p = temp = pathname_local; + + ZERO_STRUCTP(pdp); + + trim_char(temp,'\\','\\'); + DEBUG(10,("temp in parse_dfs_path: .%s. after trimming \\'s\n",temp)); + + /* now tokenize */ + /* parse out hostname */ + p = strchr_m(temp,'\\'); + if(p == NULL) + return False; + *p = '\0'; + pstrcpy(pdp->hostname,temp); + DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); + + /* parse out servicename */ + temp = p+1; + p = strchr_m(temp,'\\'); + if(p == NULL) { + pstrcpy(pdp->servicename,temp); + pdp->reqpath[0] = '\0'; + return True; + } + *p = '\0'; + pstrcpy(pdp->servicename,temp); + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + + /* rest is reqpath */ + check_path_syntax(pdp->reqpath, p+1); + + DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); + return True; +} + +/********************************************************************** + Parse the pathname of the form /hostname/service/reqpath + into the dfs_path structure + **********************************************************************/ + +static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) +{ + pstring pathname_local; + char* p,*temp; + + pstrcpy(pathname_local,pathname); + p = temp = pathname_local; + + ZERO_STRUCTP(pdp); + + trim_char(temp,'/','/'); + DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp)); + + /* now tokenize */ + /* parse out hostname */ + p = strchr_m(temp,'/'); + if(p == NULL) + return False; + *p = '\0'; + pstrcpy(pdp->hostname,temp); + DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname)); + + /* parse out servicename */ + temp = p+1; + p = strchr_m(temp,'/'); + if(p == NULL) { + pstrcpy(pdp->servicename,temp); + pdp->reqpath[0] = '\0'; + return True; + } + *p = '\0'; + pstrcpy(pdp->servicename,temp); + DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); + + /* rest is reqpath */ + check_path_syntax(pdp->reqpath, p+1); + + DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); + return True; +} + +/******************************************************** + Fake up a connection struct for the VFS layer. + Note this CHANGES CWD !!!! JRA. +*********************************************************/ + +static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) +{ + ZERO_STRUCTP(conn); + conn->service = snum; + conn->connectpath = path; + pstring_sub(conn->connectpath , "%S", lp_servicename(snum)); + + /* needed for smbd_vfs_init() */ + + if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) { + DEBUG(0,("talloc_init(connection_struct) failed!\n")); + return False; + } + + if (!smbd_vfs_init(conn)) { + DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); + talloc_destroy( conn->mem_ctx ); + return False; + } + + /* + * Windows seems to insist on doing trans2getdfsreferral() calls on the IPC$ + * share as the anonymous user. If we try to chdir as that user we will + * fail.... WTF ? JRA. + */ + + if (vfs_ChDir(conn,conn->connectpath) != 0) { + DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", + conn->connectpath, strerror(errno) )); + talloc_destroy( conn->mem_ctx ); + return False; + } + return True; +} + + +/********************************************************************** + Parse the contents of a symlink to verify if it is an msdfs referral + A valid referral is of the form: msdfs:server1\share1,server2\share2 + **********************************************************************/ + +static BOOL parse_symlink(char* buf,struct referral** preflist, + int* refcount) +{ + pstring temp; + char* prot; + char* alt_path[MAX_REFERRAL_COUNT]; + int count=0, i; + struct referral* reflist; + + pstrcpy(temp,buf); + + prot = strtok(temp,":"); + + if (!strequal(prot, "msdfs")) + return False; + + /* No referral list requested. Just yes/no. */ + if (!preflist) + return True; + + /* parse out the alternate paths */ + while(((alt_path[count] = strtok(NULL,",")) != NULL) && countst_mode)) { + /* open the link and read it */ + referral_len = SMB_VFS_READLINK(conn, path, referral, + sizeof(pstring)); + if (referral_len == -1) { + DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno))); + return False; + } + + referral[referral_len] = '\0'; + DEBUG(5,("is_msdfs_link: %s -> %s\n",path,referral)); + if (parse_symlink(referral, reflistp, refcnt)) + return True; + } + return False; +} + +/***************************************************************** + Used by other functions to decide if a dfs path is remote, +and to get the list of referred locations for that remote path. + +findfirst_flag: For findfirsts, dfs links themselves are not +redirected, but paths beyond the links are. For normal smb calls, +even dfs links need to be redirected. + +self_referralp: clients expect a dfs referral for the same share when +they request referrals for dfs roots on a server. + +consumedcntp: how much of the dfs path is being redirected. the client +should try the remaining path on the redirected server. + +*****************************************************************/ + +static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, + connection_struct* conn, + BOOL findfirst_flag, + struct referral** reflistpp, int* refcntp, + BOOL* self_referralp, int* consumedcntp) +{ + pstring localpath; + int consumed_level = 1; + char *p; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + pstring reqpath; + + if (!dp || !conn) { + DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n")); + return False; + } + + if (dp->reqpath[0] == '\0') { + if (self_referralp) { + DEBUG(6,("resolve_dfs_path: self-referral. returning False\n")); + *self_referralp = True; + } + return False; + } + + DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); + + unix_convert(dp->reqpath,conn,0,&bad_path,&sbuf); + /* JRA... should we strlower the last component here.... ? */ + pstrcpy(localpath, dp->reqpath); + + /* check if need to redirect */ + if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + if (findfirst_flag) { + DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " + "for dfs link %s.\n", dfspath)); + return False; + } else { + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", + dfspath)); + if (consumedcntp) + *consumedcntp = strlen(dfspath); + return True; + } + } + + /* redirect if any component in the path is a link */ + pstrcpy(reqpath, dp->reqpath); + p = strrchr_m(reqpath, '/'); + while (p) { + *p = '\0'; + pstrcpy(localpath, reqpath); + if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); + + /* To find the path consumed, we truncate the original + DFS pathname passed to use to remove the last + component. The length of the resulting string is + the path consumed + */ + if (consumedcntp) { + char *q; + pstring buf; + pstrcpy(buf, dfspath); + trim_char(buf, '\0', '\\'); + for (; consumed_level; consumed_level--) { + q = strrchr_m(buf, '\\'); + if (q) + *q = 0; + } + *consumedcntp = strlen(buf); + DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp)); + } + + return True; + } + p = strrchr_m(reqpath, '/'); + consumed_level++; + } + + return False; +} + +/***************************************************************** + Decides if a dfs pathname should be redirected or not. + If not, the pathname is converted to a tcon-relative local unix path +*****************************************************************/ + +BOOL dfs_redirect(pstring pathname, connection_struct* conn, + BOOL findfirst_flag) +{ + struct dfs_path dp; + + if (!conn || !pathname) + return False; + + parse_processed_dfs_path(pathname, &dp); + + /* if dfs pathname for a non-dfs share, convert to tcon-relative + path and return false */ + if (!lp_msdfs_root(SNUM(conn))) { + pstrcpy(pathname, dp.reqpath); + return False; + } + + if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) + return False; + + if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, + NULL, NULL, NULL, NULL)) { + DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); + return True; + } else { + DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname)); + + /* Form non-dfs tcon-relative path */ + pstrcpy(pathname, dp.reqpath); + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", + pathname)); + return False; + } + + /* never reached */ +} + +/********************************************************************** + Return a self referral. +**********************************************************************/ + +static BOOL self_ref(char *pathname, struct junction_map *jucn, + int *consumedcntp, BOOL *self_referralp) +{ + struct referral *ref; + + if (self_referralp != NULL) + *self_referralp = True; + + jucn->referral_count = 1; + if((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + DEBUG(0,("self_ref: malloc failed for referral\n")); + return False; + } + + pstrcpy(ref->alternate_path,pathname); + ref->proximity = 0; + ref->ttl = REFERRAL_TTL; + jucn->referral_list = ref; + if (consumedcntp) + *consumedcntp = strlen(pathname); + + return True; +} + +/********************************************************************** + Gets valid referrals for a dfs path and fills up the + junction_map structure +**********************************************************************/ + +BOOL get_referred_path(char *pathname, struct junction_map *jucn, + int *consumedcntp, BOOL *self_referralp) +{ + struct dfs_path dp; + + struct connection_struct conns; + struct connection_struct* conn = &conns; + pstring conn_path; + int snum; + BOOL ret = False; + BOOL self_referral = False; + + if (!pathname || !jucn) + return False; + + ZERO_STRUCT(conns); + + if (self_referralp) + *self_referralp = False; + else + self_referralp = &self_referral; + + parse_dfs_path(pathname, &dp); + + /* Verify hostname in path */ + if (local_machine && (!strequal(local_machine, dp.hostname))) { + /* Hostname mismatch, check if one of our IP addresses */ + if (!ismyip(*interpret_addr2(dp.hostname))) { + DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", + dp.hostname, pathname)); + return False; + } + } + + pstrcpy(jucn->service_name, dp.servicename); + pstrcpy(jucn->volume_name, dp.reqpath); + + /* Verify the share is a dfs root */ + snum = lp_servicenumber(jucn->service_name); + if(snum < 0) { + if ((snum = find_service(jucn->service_name)) < 0) + return False; + } + + if (!lp_msdfs_root(snum)) { + DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n", + dp.servicename, pathname)); + goto out; + } + + /* + * Self referrals are tested with a anonymous IPC connection and + * a GET_DFS_REFERRAL call to \\server\share. (which means dp.reqpath[0] points + * to an empty string). create_conn_struct cd's into the directory and will + * fail if it cannot (as the anonymous user). Cope with this. + */ + + if (dp.reqpath[0] == '\0') { + + struct referral* ref; + + if (*lp_msdfs_proxy(snum) == '\0') + return self_ref(pathname, jucn, consumedcntp, + self_referralp); + + jucn->referral_count = 1; + if ((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + DEBUG(0, ("malloc failed for referral\n")); + goto out; + } + + pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); + if (dp.reqpath[0] != '\0') + pstrcat(ref->alternate_path, dp.reqpath); + ref->proximity = 0; + ref->ttl = REFERRAL_TTL; + jucn->referral_list = ref; + if (consumedcntp) + *consumedcntp = strlen(pathname); + ret = True; + goto out; + } + + pstrcpy(conn_path, lp_pathname(snum)); + if (!create_conn_struct(conn, snum, conn_path)) + return False; + + /* If not remote & not a self referral, return False */ + if (!resolve_dfs_path(pathname, &dp, conn, False, + &jucn->referral_list, &jucn->referral_count, + self_referralp, consumedcntp)) { + if (!*self_referralp) { + DEBUG(3,("get_referred_path: No valid referrals for path %s\n", pathname)); + goto out; + } + } + + /* if self_referral, fill up the junction map */ + if (*self_referralp) { + if (self_ref(pathname, jucn, consumedcntp, self_referralp) == False) { + goto out; + } + } + + ret = True; + +out: + if (conn->mem_ctx) + talloc_destroy( conn->mem_ctx ); + + return ret; +} + +static int setup_ver2_dfs_referral(char* pathname, char** ppdata, + struct junction_map* junction, + int consumedcnt, + BOOL self_referral) +{ + char* pdata = *ppdata; + + unsigned char uni_requestedpath[1024]; + int uni_reqpathoffset1,uni_reqpathoffset2; + int uni_curroffset; + int requestedpathlen=0; + int offset; + int reply_size = 0; + int i=0; + + DEBUG(10,("setting up version2 referral\nRequested path:\n")); + + requestedpathlen = rpcstr_push(uni_requestedpath, pathname, -1, + STR_TERMINATE); + + dump_data(10, (const char *) uni_requestedpath,requestedpathlen); + + DEBUG(10,("ref count = %u\n",junction->referral_count)); + + uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + + VERSION2_REFERRAL_SIZE * junction->referral_count; + + uni_reqpathoffset2 = uni_reqpathoffset1 + requestedpathlen; + + uni_curroffset = uni_reqpathoffset2 + requestedpathlen; + + reply_size = REFERRAL_HEADER_SIZE + VERSION2_REFERRAL_SIZE*junction->referral_count + + 2 * requestedpathlen; + DEBUG(10,("reply_size: %u\n",reply_size)); + + /* add up the unicode lengths of all the referral paths */ + for(i=0;ireferral_count;i++) { + DEBUG(10,("referral %u : %s\n",i,junction->referral_list[i].alternate_path)); + reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; + } + + DEBUG(10,("reply_size = %u\n",reply_size)); + /* add the unexplained 0x16 bytes */ + reply_size += 0x16; + + pdata = Realloc(pdata,reply_size); + if(pdata == NULL) { + DEBUG(0,("malloc failed for Realloc!\n")); + return -1; + } else + *ppdata = pdata; + + /* copy in the dfs requested paths.. required for offset calculations */ + memcpy(pdata+uni_reqpathoffset1,uni_requestedpath,requestedpathlen); + memcpy(pdata+uni_reqpathoffset2,uni_requestedpath,requestedpathlen); + + /* create the header */ + SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ + SSVAL(pdata,2,junction->referral_count); /* number of referral in this pkt */ + if(self_referral) + SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); + else + SIVAL(pdata,4,DFSREF_STORAGE_SERVER); + + offset = 8; + /* add the referral elements */ + for(i=0;ireferral_count;i++) { + struct referral* ref = &junction->referral_list[i]; + int unilen; + + SSVAL(pdata,offset,2); /* version 2 */ + SSVAL(pdata,offset+2,VERSION2_REFERRAL_SIZE); + if(self_referral) + SSVAL(pdata,offset+4,1); + else + SSVAL(pdata,offset+4,0); + SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ + SIVAL(pdata,offset+8,ref->proximity); + SIVAL(pdata,offset+12,ref->ttl); + + SSVAL(pdata,offset+16,uni_reqpathoffset1-offset); + SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); + /* copy referred path into current offset */ + unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, + -1, STR_UNICODE); + + SSVAL(pdata,offset+20,uni_curroffset-offset); + + uni_curroffset += unilen; + offset += VERSION2_REFERRAL_SIZE; + } + /* add in the unexplained 22 (0x16) bytes at the end */ + memset(pdata+uni_curroffset,'\0',0x16); + return reply_size; +} + +static int setup_ver3_dfs_referral(char* pathname, char** ppdata, + struct junction_map* junction, + int consumedcnt, + BOOL self_referral) +{ + char* pdata = *ppdata; + + unsigned char uni_reqpath[1024]; + int uni_reqpathoffset1, uni_reqpathoffset2; + int uni_curroffset; + int reply_size = 0; + + int reqpathlen = 0; + int offset,i=0; + + DEBUG(10,("setting up version3 referral\n")); + + reqpathlen = rpcstr_push(uni_reqpath, pathname, -1, STR_TERMINATE); + + dump_data(10, (char *) uni_reqpath,reqpathlen); + + uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count; + uni_reqpathoffset2 = uni_reqpathoffset1 + reqpathlen; + reply_size = uni_curroffset = uni_reqpathoffset2 + reqpathlen; + + for(i=0;ireferral_count;i++) { + DEBUG(10,("referral %u : %s\n",i,junction->referral_list[i].alternate_path)); + reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; + } + + pdata = Realloc(pdata,reply_size); + if(pdata == NULL) { + DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); + return -1; + } else + *ppdata = pdata; + + /* create the header */ + SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ + SSVAL(pdata,2,junction->referral_count); /* number of referral */ + if(self_referral) + SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); + else + SIVAL(pdata,4,DFSREF_STORAGE_SERVER); + + /* copy in the reqpaths */ + memcpy(pdata+uni_reqpathoffset1,uni_reqpath,reqpathlen); + memcpy(pdata+uni_reqpathoffset2,uni_reqpath,reqpathlen); + + offset = 8; + for(i=0;ireferral_count;i++) { + struct referral* ref = &(junction->referral_list[i]); + int unilen; + + SSVAL(pdata,offset,3); /* version 3 */ + SSVAL(pdata,offset+2,VERSION3_REFERRAL_SIZE); + if(self_referral) + SSVAL(pdata,offset+4,1); + else + SSVAL(pdata,offset+4,0); + + SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ + SIVAL(pdata,offset+8,ref->ttl); + + SSVAL(pdata,offset+12,uni_reqpathoffset1-offset); + SSVAL(pdata,offset+14,uni_reqpathoffset2-offset); + /* copy referred path into current offset */ + unilen = rpcstr_push(pdata+uni_curroffset,ref->alternate_path, + -1, STR_UNICODE | STR_TERMINATE); + SSVAL(pdata,offset+16,uni_curroffset-offset); + /* copy 0x10 bytes of 00's in the ServiceSite GUID */ + memset(pdata+offset+18,'\0',16); + + uni_curroffset += unilen; + offset += VERSION3_REFERRAL_SIZE; + } + return reply_size; +} + +/****************************************************************** + * Set up the Dfs referral for the dfs pathname + ******************************************************************/ + +int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char** ppdata) +{ + struct junction_map junction; + int consumedcnt; + BOOL self_referral = False; + pstring buf; + int reply_size = 0; + char *pathnamep = pathname; + + ZERO_STRUCT(junction); + + /* get the junction entry */ + if (!pathnamep) + return -1; + + /* Trim pathname sent by client so it begins with only one backslash. + Two backslashes confuse some dfs clients + */ + while (pathnamep[0] == '\\' && pathnamep[1] == '\\') + pathnamep++; + + pstrcpy(buf, pathnamep); + /* The following call can change cwd. */ + if (!get_referred_path(buf, &junction, &consumedcnt, &self_referral)) { + vfs_ChDir(orig_conn,orig_conn->connectpath); + return -1; + } + vfs_ChDir(orig_conn,orig_conn->connectpath); + + if (!self_referral) { + pathnamep[consumedcnt] = '\0'; + + if( DEBUGLVL( 3 ) ) { + int i=0; + dbgtext("setup_dfs_referral: Path %s to alternate path(s):",pathnamep); + for(i=0;i3) + max_referral_level = 2; + + switch(max_referral_level) { + case 2: + reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, &junction, + consumedcnt, self_referral); + SAFE_FREE(junction.referral_list); + break; + case 3: + reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, &junction, + consumedcnt, self_referral); + SAFE_FREE(junction.referral_list); + break; + default: + DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); + return -1; + } + + DEBUG(10,("DFS Referral pdata:\n")); + dump_data(10,*ppdata,reply_size); + return reply_size; +} + +/********************************************************************** + The following functions are called by the NETDFS RPC pipe functions + **********************************************************************/ + +/********************************************************************** + Creates a junction structure from a Dfs pathname + **********************************************************************/ +BOOL create_junction(char* pathname, struct junction_map* jucn) +{ + struct dfs_path dp; + + parse_dfs_path(pathname,&dp); + + /* check if path is dfs : validate first token */ + if (local_machine && (!strequal(local_machine,dp.hostname))) { + + /* Hostname mismatch, check if one of our IP addresses */ + if (!ismyip(*interpret_addr2(dp.hostname))) { + DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", + dp.hostname, pathname)); + return False; + } + } + + /* Check for a non-DFS share */ + if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { + DEBUG(4,("create_junction: %s is not an msdfs root.\n", + dp.servicename)); + return False; + } + + pstrcpy(jucn->service_name,dp.servicename); + pstrcpy(jucn->volume_name,dp.reqpath); + return True; +} + +/********************************************************************** + Forms a valid Unix pathname from the junction + **********************************************************************/ + +static BOOL junction_to_local_path(struct junction_map* jucn, char* path, + int max_pathlen, connection_struct *conn) +{ + int snum; + pstring conn_path; + + if(!path || !jucn) + return False; + + snum = lp_servicenumber(jucn->service_name); + if(snum < 0) + return False; + + safe_strcpy(path, lp_pathname(snum), max_pathlen-1); + safe_strcat(path, "/", max_pathlen-1); + safe_strcat(path, jucn->volume_name, max_pathlen-1); + + pstrcpy(conn_path, lp_pathname(snum)); + if (!create_conn_struct(conn, snum, conn_path)) + return False; + + return True; +} + +BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) +{ + pstring path; + pstring msdfs_link; + connection_struct conns; + connection_struct *conn = &conns; + int i=0; + BOOL insert_comma = False; + BOOL ret = False; + + if(!junction_to_local_path(jucn, path, sizeof(path), conn)) + return False; + + /* form the msdfs_link contents */ + pstrcpy(msdfs_link, "msdfs:"); + for(i=0; ireferral_count; i++) { + char* refpath = jucn->referral_list[i].alternate_path; + + trim_char(refpath, '\\', '\\'); + if(*refpath == '\0') { + if (i == 0) + insert_comma = False; + continue; + } + if (i > 0 && insert_comma) + pstrcat(msdfs_link, ","); + + pstrcat(msdfs_link, refpath); + if (!insert_comma) + insert_comma = True; + + } + + DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); + + if(exists) + if(SMB_VFS_UNLINK(conn,path)!=0) + goto out; + + if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { + DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n", + path, msdfs_link, strerror(errno))); + goto out; + } + + + ret = True; + +out: + talloc_destroy( conn->mem_ctx ); + return ret; +} + +BOOL remove_msdfs_link(struct junction_map* jucn) +{ + pstring path; + connection_struct conns; + connection_struct *conn = &conns; + BOOL ret = False; + + if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { + if( SMB_VFS_UNLINK(conn, path) == 0 ) + ret = True; + + talloc_destroy( conn->mem_ctx ); + } + + return ret; +} + +static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) +{ + int cnt = *jn_count; + DIR *dirp; + char* dname; + pstring connect_path; + char* service_name = lp_servicename(snum); + connection_struct conns; + connection_struct *conn = &conns; + struct referral *ref = NULL; + BOOL ret = False; + + pstrcpy(connect_path,lp_pathname(snum)); + + if(*connect_path == '\0') + return False; + + /* + * Fake up a connection struct for the VFS layer. + */ + + if (!create_conn_struct(conn, snum, connect_path)) + return False; + + /* form a junction for the msdfs root - convention + DO NOT REMOVE THIS: NT clients will not work with us + if this is not present + */ + pstrcpy(jucn[cnt].service_name, service_name); + jucn[cnt].volume_name[0] = '\0'; + jucn[cnt].referral_count = 1; + + ref = jucn[cnt].referral_list + = (struct referral*) malloc(sizeof(struct referral)); + if (jucn[cnt].referral_list == NULL) { + DEBUG(0, ("Malloc failed!\n")); + goto out; + } + + ref->proximity = 0; + ref->ttl = REFERRAL_TTL; + if (*lp_msdfs_proxy(snum) != '\0') { + pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); + *jn_count = ++cnt; + ret = True; + goto out; + } + + slprintf(ref->alternate_path, sizeof(pstring)-1, + "\\\\%s\\%s", local_machine, service_name); + cnt++; + + /* Now enumerate all dfs links */ + dirp = SMB_VFS_OPENDIR(conn, "."); + if(!dirp) + goto out; + + while((dname = vfs_readdirname(conn, dirp)) != NULL) { + if (is_msdfs_link(conn, dname, &(jucn[cnt].referral_list), + &(jucn[cnt].referral_count), NULL)) { + pstrcpy(jucn[cnt].service_name, service_name); + pstrcpy(jucn[cnt].volume_name, dname); + cnt++; + } + } + + SMB_VFS_CLOSEDIR(conn,dirp); + *jn_count = cnt; +out: + talloc_destroy(conn->mem_ctx); + return ret; +} + +int enum_msdfs_links(struct junction_map* jucn) +{ + int i=0; + int jn_count = 0; + + if(!lp_host_msdfs()) + return 0; + + for(i=0;i < lp_numservices();i++) { + if(lp_msdfs_root(i)) + form_junctions(i,jucn,&jn_count); + } + return jn_count; +} -- cgit From 848b86290d6539f250572e348973fc8aa6b627fd Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 30 Apr 2004 06:33:58 +0000 Subject: r421: Fix debug message. Closes bugzilla #1305. (This used to be commit 6654b03cbd08e8bbf3f9cae117b84a820c8857b2) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 4f3234775a..533220e7df 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -820,7 +820,7 @@ static BOOL readlink_check(connection_struct *conn, const char *dir, char *name) } if (SMB_VFS_READLINK(conn, name, flink, sizeof(pstring) -1) != -1) { - DEBUG(3,("reduce_name: file path name %s is a symlink\nChecking it's path\n", name)); + DEBUG(3,("readlink_check: file path name %s is a symlink\nChecking it's path\n", name)); if (*flink == '/') { pstrcpy(cleanlink, flink); } else { -- cgit From 0e551158b7d36d75819c36ef6570c115f6efcdcf Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 30 Apr 2004 07:53:52 +0000 Subject: r422: Compile fix for OpenBSD (ENOTSUP not supported - ha ha). From Eric Mertens. (This used to be commit d98a36b4596d1de979adab6c476022eb95474c48) --- source3/smbd/trans2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0d84c40065..0c6026392c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -395,9 +395,11 @@ static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *f } if (ret == -1) { +#ifdef ENOTSUP if (errno == ENOTSUP) { return NT_STATUS_EAS_NOT_SUPPORTED; } +#endif return map_nt_error_from_unix(errno); } -- cgit From fc52c330aed4bbfd406d96cccc273c8e551255c2 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 30 Apr 2004 14:28:38 +0000 Subject: r428: add acls debug class (This used to be commit b7703799f8899affda205eacb0bf79cf8e2b9362) --- source3/smbd/posix_acls.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 25e8fd802b..158f1a0ede 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -21,6 +21,9 @@ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ACLS + /**************************************************************************** Data structures representing the internal ACE format. ****************************************************************************/ -- cgit From 1843f6905caf30de6493de07316a416696394d3e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 May 2004 23:01:00 +0000 Subject: r478: Added Volkers fix to be able to force DOS errors when needed. Jeremy. (This used to be commit a9d1738ebab42ab9bab73f18341d79e086e290b3) --- source3/smbd/error.c | 8 ++++---- source3/smbd/process.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 795bf0949c..9c81d465e7 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -42,7 +42,7 @@ int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file /* We can now delete the auxiliary struct */ free((char *)wbmpx); fsp->wbmpx_ptr = NULL; - return error_packet(outbuf,NT_STATUS_OK,eclass,err,line,file); + return error_packet(outbuf,NT_STATUS_OK,eclass,err,False,line,file); } /**************************************************************************** @@ -76,7 +76,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, } } - return error_packet(outbuf,ntstatus,eclass,ecode,line,file); + return error_packet(outbuf,ntstatus,eclass,ecode,False,line,file); } @@ -85,7 +85,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, ****************************************************************************/ int error_packet(char *outbuf,NTSTATUS ntstatus, - uint8 eclass,uint32 ecode,int line, const char *file) + uint8 eclass,uint32 ecode,BOOL force_dos, int line, const char *file) { int outsize = set_message(outbuf,0,0,True); extern uint32 global_client_caps; @@ -106,7 +106,7 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, * when talking with clients that normally expect nt status codes. JRA. */ - if ((lp_nt_status_support() || (SVAL(outbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) && (global_client_caps & CAP_STATUS32)) { + if ((lp_nt_status_support() || (SVAL(outbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) && (global_client_caps & CAP_STATUS32) && (!force_dos)) { if (NT_STATUS_V(ntstatus) == 0 && eclass) ntstatus = dos_to_ntstatus(eclass, ecode); SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 718d1bb67b..966bb63c1e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -736,7 +736,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if (flags & AS_GUEST) flags &= ~AS_USER; else - return(ERROR_DOS(ERRSRV,ERRaccess)); + return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid)); } /* this code is to work around a bug is MS client 3 without -- cgit From 34facd7e6935749291d64f37ae95b84ded792fb8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 May 2004 01:06:23 +0000 Subject: r481: Fix up assert caught by check_path_syntax. Jeremy. (This used to be commit 8a58bd39da596cac68abc0143cdb17981642daf6) --- source3/smbd/nttrans.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e4ffec339b..7e4cac7b38 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -643,6 +643,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib /* * This filename is relative to a directory fid. */ + pstring rel_fname; files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid); size_t dir_name_len; @@ -695,11 +696,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib dir_name_len++; } - srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } + pstrcat(fname, rel_fname); } else { srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -1207,7 +1209,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* * This filename is relative to a directory fid. */ - files_struct *dir_fsp = file_fsp(params,4); size_t dir_name_len; -- cgit From 9294acabb403d0309c408f84fee5878100481da4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 May 2004 01:13:48 +0000 Subject: r483: Fix typo of appending '\\' instead of '/' now we're using check_path_syntax. Jeremy. (This used to be commit 50ce579322ae394cb7c7a27e06f4ff08499b77b3) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7e4cac7b38..e4ddda104e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -692,7 +692,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib */ if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') { - pstrcat(fname, "\\"); + pstrcat(fname, "/"); dir_name_len++; } @@ -1243,7 +1243,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { - pstrcat(fname, "\\"); + pstrcat(fname, "/"); dir_name_len++; } -- cgit From c2c069d4b0fc6e29194a8ba8d12b8aba59dae4c2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 5 May 2004 02:58:43 +0000 Subject: r486: BUG 1309: fix seg fault caused by trying to strdup() a NULL pointer (This used to be commit 0e1a6b34f2690da32bf568330575651988d0c965) --- source3/smbd/password.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index d15970cbef..72292de422 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -488,7 +488,11 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, /* now check the list of session users */ if (!ok) { char *auser; - char *user_list = strdup(session_userlist); + char *user_list = NULL; + + if ( session_userlist ) + user_list = strdup(session_userlist); + if (!user_list) return(False); -- cgit From ad770b098c5079accc9d64c28855daca3c2bbfa1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 6 May 2004 15:29:02 +0000 Subject: r519: fix bug in authorise_login() that broke security = share (This used to be commit b27192d8e7a4a1fd0cd737b4fd9190bcecfbb507) --- source3/smbd/password.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 72292de422..b2dbde151d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -492,6 +492,8 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, if ( session_userlist ) user_list = strdup(session_userlist); + else + user_list = strdup(""); if (!user_list) return(False); -- cgit From e0da56a84808c522bc7324b5d636f1cbd317a2c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 May 2004 18:37:47 +0000 Subject: r570: Remove lots of globals to handle case issues - move them to connection struct entries (as they should have been from the start). Jerry, once you've cut over to 3.0.4 release branch I'll add this to 3.0 also. - Jerry cut over :-). Jeremy. (This used to be commit 578a508509d21226ad3332fc54c3ab54cd8ae452) --- source3/smbd/filename.c | 31 +++++++++++++------------- source3/smbd/mangle.c | 2 +- source3/smbd/mangle_hash.c | 22 ++++--------------- source3/smbd/mangle_hash2.c | 2 +- source3/smbd/nttrans.c | 53 +++++++++++++++++++++------------------------ source3/smbd/reply.c | 23 +++++++++----------- source3/smbd/service.c | 18 +++++---------- source3/smbd/statcache.c | 6 ++--- source3/smbd/trans2.c | 13 +++++------ 9 files changed, 70 insertions(+), 100 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 805af9c494..692c7f7610 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,11 +26,6 @@ #include "includes.h" -extern BOOL case_sensitive; -extern BOOL case_preserve; -extern BOOL short_case_preserve; -extern BOOL use_mangled_map; - static BOOL scan_directory(const char *path, char *name,size_t maxlength, connection_struct *conn,BOOL docache); @@ -39,7 +34,7 @@ static BOOL scan_directory(const char *path, char *name,size_t maxlength, This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(const char *name1, const char *name2) +static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) { /* Normal filename handling */ if (case_sensitive) @@ -152,13 +147,17 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } - if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve))) - strnorm(name); +#if 1 + if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)) +#else + if (!conn->case_sensitive && (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve))) +#endif + strnorm(name, lp_defaultcase(SNUM(conn))); start = name; pstrcpy(orig_path, name); - if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { *pst = st; return True; } @@ -168,7 +167,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (SMB_VFS_STAT(conn,name,&st) == 0) { - stat_cache_add(orig_path, name); + stat_cache_add(orig_path, name, conn->case_sensitive); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; return(True); @@ -181,7 +180,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (case_sensitive && !mangle_is_mangled(name) && !use_mangled_map) + if (conn->case_sensitive && !mangle_is_mangled(name) && !*lp_mangled_map(SNUM(conn))) return(False); name_has_wildcard = ms_has_wild(start); @@ -297,8 +296,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * don't normalise it. */ - if (!case_preserve && (!strhasupper(start) || !strhaslower(start))) - strnorm(start); + if (!conn->case_preserve && (!strhasupper(start) || !strhaslower(start))) + strnorm(start, lp_defaultcase(SNUM(conn))); /* * check on the mangled stack to see if we can recover the @@ -353,7 +352,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, dirpath); + stat_cache_add(orig_path, dirpath, conn->case_sensitive); /* * Restore the / that we wiped out earlier. @@ -368,7 +367,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if(!component_was_mangled && !name_has_wildcard) - stat_cache_add(orig_path, name); + stat_cache_add(orig_path, name, conn->case_sensitive); /* * The name has been resolved. @@ -482,7 +481,7 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, * against unmangled name. */ - if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname)) { + if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index c5d7582c03..b77fe601b6 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -120,5 +120,5 @@ void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) /* invoke the inane "mangled map" code */ mangle_map_filename(OutName, snum); - mangle_fns->name_map(OutName, need83, cache83); + mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum)); } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 16722ae6e9..7b8cbdbddb 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -50,13 +50,6 @@ #include "includes.h" -/* -------------------------------------------------------------------------- ** - * External Variables... - */ - -extern int case_default; /* Are conforming 8.3 names all upper or lower? */ -extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ - /* -------------------------------------------------------------------------- ** * Other stuff... * @@ -130,13 +123,6 @@ static BOOL mc_initialized = False; #define MANGLED_CACHE_MAX_ENTRIES 1024 #define MANGLED_CACHE_MAX_MEMORY 0 -/* -------------------------------------------------------------------------- ** - * External Variables... - */ - -extern int case_default; /* Are conforming 8.3 names all upper or lower? */ -extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */ - /* -------------------------------------------------------------------- */ static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, BOOL allow_wildcards) @@ -639,7 +625,7 @@ static BOOL check_cache( char *s ) * the buffer must be able to hold 13 characters (including the null) ***************************************************************************** */ -static void to_8_3(char *s) +static void to_8_3(char *s, int default_case) { int csum; char *p; @@ -653,7 +639,7 @@ static void to_8_3(char *s) p = strrchr(s,'.'); if( p && (strlen(p+1) < (size_t)4) ) { - BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */ + BOOL all_normal = ( strisnormal(p+1, default_case) ); /* XXXXXXXXX */ if( all_normal && p[1] != 0 ) { *p = 0; @@ -728,7 +714,7 @@ static void to_8_3(char *s) * **************************************************************************** */ -static void name_map(char *OutName, BOOL need83, BOOL cache83) +static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case) { smb_ucs2_t *OutName_ucs2; DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, @@ -750,7 +736,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83) if (cache83) tmp = strdup(OutName); - to_8_3(OutName); + to_8_3(OutName, default_case); if(tmp != NULL) { cache_mangled_name(OutName, tmp); diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 62087e7e59..dcfd7663ba 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -501,7 +501,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(fstring name, BOOL need83, BOOL cache83) +static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case) { char *dot_p; char lead_chars[7]; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e4ddda104e..26be4434fd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -24,9 +24,6 @@ extern int Protocol; extern int smb_read_error; extern int global_oplock_break; -extern BOOL case_sensitive; -extern BOOL case_preserve; -extern BOOL short_case_preserve; extern struct current_user current_user; static const char *known_nt_pipes[] = { @@ -274,33 +271,33 @@ static BOOL saved_short_case_preserve; Save case semantics. ****************************************************************************/ -static void set_posix_case_semantics(uint32 file_attributes) +static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes) { if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) return; - saved_case_sensitive = case_sensitive; - saved_case_preserve = case_preserve; - saved_short_case_preserve = short_case_preserve; + saved_case_sensitive = conn->case_sensitive; + saved_case_preserve = conn->case_preserve; + saved_short_case_preserve = conn->short_case_preserve; /* Set to POSIX. */ - case_sensitive = True; - case_preserve = True; - short_case_preserve = True; + conn->case_sensitive = True; + conn->case_preserve = True; + conn->short_case_preserve = True; } /**************************************************************************** Restore case semantics. ****************************************************************************/ -static void restore_case_semantics(uint32 file_attributes) +static void restore_case_semantics(connection_struct *conn, uint32 file_attributes) { if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) return; - case_sensitive = saved_case_sensitive; - case_preserve = saved_case_preserve; - short_case_preserve = saved_short_case_preserve; + conn->case_sensitive = saved_case_sensitive; + conn->case_preserve = saved_case_preserve; + conn->short_case_preserve = saved_short_case_preserve; } /**************************************************************************** @@ -762,7 +759,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * Check if POSIX semantics are wanted. */ - set_posix_case_semantics(file_attributes); + set_posix_case_semantics(conn, file_attributes); unix_convert(fname,conn,0,&bad_path,&sbuf); @@ -781,7 +778,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); if(!fsp) { END_PROFILE(SMBntcreateX); @@ -847,7 +844,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib */ if (create_options & FILE_NON_DIRECTORY_FILE) { - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); @@ -858,20 +855,20 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } } - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); file_len = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); @@ -1285,7 +1282,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Check if POSIX semantics are wanted. */ - set_posix_case_semantics(file_attributes); + set_posix_case_semantics(conn, file_attributes); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1313,7 +1310,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } @@ -1336,7 +1333,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ if (create_options & FILE_NON_DIRECTORY_FILE) { - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } @@ -1345,11 +1342,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } @@ -1361,7 +1358,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (fmode & aDIR) { close_file(fsp,False); - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1384,11 +1381,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (sd_len && !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { close_file(fsp,False); - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } - restore_case_semantics(file_attributes); + restore_case_semantics(conn, file_attributes); /* Save the requested allocation size. */ allocation_size = (SMB_BIG_UINT)IVAL(params,12); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ac239c7e04..2046f2370a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -31,9 +31,6 @@ extern int Protocol; extern int max_send; extern int max_recv; extern char magic_char; -extern BOOL case_sensitive; -extern BOOL case_preserve; -extern BOOL short_case_preserve; extern int global_oplock_break; unsigned int smb_echo_count = 0; @@ -881,7 +878,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (ok) { if ((dirtype&0x1F) == aVOLID) { memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); + make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive); dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; @@ -901,7 +898,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend); if (!finished) { memcpy(p,status,21); - make_dir_struct(p,mask,fname,size,mode,date); + make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive); dptr_fill(p+12,dptr_num); numentries++; } @@ -1570,7 +1567,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) } } - if(!mask_match(fname, mask, case_sensitive)) + if(!mask_match(fname, mask, conn->case_sensitive)) continue; if (sys_direntry) { @@ -3515,7 +3512,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * * filename). */ - if((case_sensitive == False) && (case_preserve == True) && + if((conn->case_sensitive == False) && (conn->case_preserve == True) && strequal(newname, fsp->fsp_name)) { char *p; pstring newname_modified_last_component; @@ -3689,7 +3686,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", - case_sensitive, case_preserve, short_case_preserve, directory, + conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, newname, last_component_dest, is_short_name)); /* @@ -3700,10 +3697,10 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", * the rename (user is trying to change the case of the * filename). */ - if((case_sensitive == False) && - (((case_preserve == True) && + if((conn->case_sensitive == False) && + (((conn->case_preserve == True) && (is_short_name == False)) || - ((short_case_preserve == True) && + ((conn->short_case_preserve == True) && (is_short_name == True))) && strcsequal(directory, newname)) { pstring modified_last_component; @@ -3839,7 +3836,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } } - if(!mask_match(fname, mask, case_sensitive)) + if(!mask_match(fname, mask, conn->case_sensitive)) continue; if (sysdir_entry) { @@ -4172,7 +4169,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive)) + if(!mask_match(fname, mask, conn->case_sensitive)) continue; error = ERRnoaccess; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 08b6648249..93b017e94c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -21,12 +21,6 @@ #include "includes.h" extern struct timeval smb_last_time; -extern int case_default; -extern BOOL case_preserve; -extern BOOL short_case_preserve; -extern BOOL case_mangle; -extern BOOL case_sensitive; -extern BOOL use_mangled_map; extern userdom_struct current_user_info; @@ -62,13 +56,7 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) last_conn = conn; - case_default = lp_defaultcase(snum); - case_preserve = lp_preservecase(snum); - short_case_preserve = lp_shortpreservecase(snum); - case_mangle = lp_casemangle(snum); - case_sensitive = lp_casesensitive(snum); magic_char = lp_magicchar(snum); - use_mangled_map = (*lp_mangled_map(snum) ? True:False); return(True); } @@ -357,6 +345,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->printer = (strncmp(dev,"LPT",3) == 0); conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$")); conn->dirptr = NULL; + + /* Case options for the share. */ + conn->case_sensitive = lp_casesensitive(snum); + conn->case_preserve = lp_preservecase(snum); + conn->short_case_preserve = lp_shortpreservecase(snum); + conn->veto_list = NULL; conn->hide_list = NULL; conn->veto_oplock_list = NULL; diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index d996f5e493..5e78e9a499 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -22,8 +22,6 @@ #include "includes.h" -extern BOOL case_sensitive; - /**************************************************************************** Stat cache code used in unix_convert. *****************************************************************************/ @@ -50,7 +48,7 @@ static hash_table stat_cache; * */ -void stat_cache_add( const char *full_orig_name, const char *orig_translated_path) +void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive) { stat_cache_entry *scp; stat_cache_entry *found_scp; @@ -222,7 +220,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, (name[1] == '.' && name[1] == '\0')))) return False; - if (case_sensitive) { + if (conn->case_sensitive) { chk_name = strdup(name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0c6026392c..25954d4433 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -24,7 +24,6 @@ #include "includes.h" extern int Protocol; -extern BOOL case_sensitive; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; @@ -883,8 +882,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(fname,dname); - if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) - got_match = mask_match(fname, mask, case_sensitive); + if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive))) + got_match = mask_match(fname, mask, conn->case_sensitive); if(!got_match && !mangle_is_8_3(fname, False)) { @@ -898,8 +897,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstring newname; pstrcpy( newname, fname); mangle_map( newname, True, False, SNUM(conn)); - if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive))) - got_match = mask_match(newname, mask, case_sensitive); + if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive))) + got_match = mask_match(newname, mask, conn->case_sensitive); } if(got_match) { @@ -1433,7 +1432,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", a different TRANS2 call. */ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) + if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; p = pdata; @@ -1633,7 +1632,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", a different TRANS2 call. */ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive)) + if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; p = pdata; -- cgit From 9aeff8d280875ae573e7b6a92df8e2b39a96b502 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 May 2004 23:04:31 +0000 Subject: r640: Make cifsvfs symlinks work with paths within and external to the share. Store external paths prefixed with smbln:. Jeremy. (This used to be commit 14a9997b2eb394174ccb36d2a10a755279740cba) --- source3/smbd/trans2.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 25954d4433..825bae86bb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2762,6 +2762,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_UNIX_LINK: { pstring buffer; + char *bufp = buffer; DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK @@ -2774,7 +2775,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (len == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); buffer[len] = 0; - len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE); + if (strncmp(buffer, CIFS_CLIENT_SYMLINK_STRING, strlen(CIFS_CLIENT_SYMLINK_STRING)) == 0) { + bufp += strlen(CIFS_CLIENT_SYMLINK_STRING); + } + + len = srvstr_push(outbuf, pdata, bufp, -1, STR_TERMINATE); pdata += len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -2885,7 +2890,7 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in /* Store the UNIX converted path. */ pstrcpy(link_dest_out, link_dest); - p = strrchr(link_dest, '/'); + p = strrchr_m(link_dest, '/'); if (p) { fstrcpy(last_component, p+1); *p = '\0'; @@ -2897,6 +2902,9 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL) return -1; + DEBUG(10,("ensure_link_is_safe: realpath: link_dest (%s) -> real name (%s)\n", + link_dest, resolved_name )); + pstrcpy(link_dest, resolved_name); pstrcat(link_dest, "/"); pstrcat(link_dest, last_component); @@ -2910,6 +2918,9 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in pstrcpy(link_test, link_dest); } + DEBUG(10,("ensure_link_is_safe: connectpath = %s, absolute resolved path = %s\n", + conn->connectpath, link_test )); + /* * Check if the link is within the share. */ @@ -3483,6 +3494,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", { pstring oldname; char *newname = fname; + BOOL cifs_client_link = False; /* Set a symbolic link. */ /* Don't allow this if follow links is false. */ @@ -3490,13 +3502,35 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (!lp_symlinks(SNUM(conn))) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + srvstr_pull(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE); + unix_format(oldname); + + if (*oldname == '/') { + /* Absolute paths are automatically a client resolved link. */ + cifs_client_link = True; + } else { + pstring rel_name; + char *last_dirp = NULL; + + pstrcpy(rel_name, newname); + last_dirp = strrchr_m(rel_name, '/'); + if (last_dirp) { + last_dirp[1] = '\0'; + } else { + pstrcpy(rel_name, "./"); + } + pstrcat(rel_name, oldname); + if (ensure_link_is_safe(conn, rel_name, rel_name) != 0) + cifs_client_link = True; + } - if (ensure_link_is_safe(conn, oldname, oldname) != 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if (cifs_client_link) { + pstring tmp_name; + pstrcpy(tmp_name, CIFS_CLIENT_SYMLINK_STRING); + pstrcat(tmp_name, oldname); + pstrcpy(oldname, tmp_name); + } DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", fname, oldname )); -- cgit From 372dac6c982ac52926c268df71bf6fb4ca2d155b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 May 2004 01:05:59 +0000 Subject: r645: Patch from kawasa_r@itg.hitachi.co.jp to correctly enable core dumps. Jeremy. (This used to be commit ea41d694270264557f740cd40ccc69b4acaa57e9) --- source3/smbd/server.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 53d07fd905..f25d42711d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -545,6 +545,10 @@ static BOOL dump_core(void) DEBUG(0,("Dumping core in %s\n", dname)); + /* Ensure we don't have a signal handler for abort. */ +#ifdef SIGABRT + CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); +#endif abort(); return(True); } -- cgit From 327f9b9636dd468822625103c6feed5fc952cc7b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 May 2004 00:35:43 +0000 Subject: r653: Ok, so tridge convinced me. Allow full UNIX path symlinks to anywhere on the server filesystem so long as widelinks is set to true.... :-). Jeremy. (This used to be commit ba9809fcd493a53b33c3a24c9f91b0c1d9bd9726) --- source3/smbd/trans2.c | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 825bae86bb..a0e00cfcfe 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2762,7 +2762,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_UNIX_LINK: { pstring buffer; - char *bufp = buffer; DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK @@ -2775,11 +2774,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (len == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); buffer[len] = 0; - if (strncmp(buffer, CIFS_CLIENT_SYMLINK_STRING, strlen(CIFS_CLIENT_SYMLINK_STRING)) == 0) { - bufp += strlen(CIFS_CLIENT_SYMLINK_STRING); - } - - len = srvstr_push(outbuf, pdata, bufp, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE); pdata += len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -2929,6 +2924,7 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in errno = EACCES; return -1; } + return 0; } @@ -2972,6 +2968,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_OBJECT_NAME_NOT_FOUND; } + if (!check_name(oldname,conn)) { + return NT_STATUS_ACCESS_DENIED; + } + rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); if (!rcdest && bad_path_newname) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; @@ -2989,6 +2989,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_OBJECT_NAME_COLLISION; } + if (!check_name(newname,conn)) { + return NT_STATUS_ACCESS_DENIED; + } + /* No links from a directory. */ if (S_ISDIR(sbuf1.st_mode)) { return NT_STATUS_FILE_IS_A_DIRECTORY; @@ -3492,9 +3496,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_SET_FILE_UNIX_LINK: { - pstring oldname; + pstring link_target; char *newname = fname; - BOOL cifs_client_link = False; /* Set a symbolic link. */ /* Don't allow this if follow links is false. */ @@ -3502,16 +3505,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (!lp_symlinks(SNUM(conn))) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - srvstr_pull(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE); - unix_format(oldname); + srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE); - if (*oldname == '/') { - /* Absolute paths are automatically a client resolved link. */ - cifs_client_link = True; - } else { + /* !widelinks forces the target path to be within the share. */ + if (!lp_widelinks(SNUM(conn))) { pstring rel_name; char *last_dirp = NULL; + unix_format(link_target); + pstrcpy(rel_name, newname); last_dirp = strrchr_m(rel_name, '/'); if (last_dirp) { @@ -3519,23 +3521,20 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } else { pstrcpy(rel_name, "./"); } - pstrcat(rel_name, oldname); - if (ensure_link_is_safe(conn, rel_name, rel_name) != 0) - cifs_client_link = True; - - } + pstrcat(rel_name, link_target); + if (ensure_link_is_safe(conn, rel_name, rel_name) != 0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - if (cifs_client_link) { - pstring tmp_name; - pstrcpy(tmp_name, CIFS_CLIENT_SYMLINK_STRING); - pstrcat(tmp_name, oldname); - pstrcpy(oldname, tmp_name); + if (check_name(link_target, conn)) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", - fname, oldname )); + fname, link_target )); - if (SMB_VFS_SYMLINK(conn,oldname,newname) != 0) + if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); -- cgit From effc7c0487da4212003e52aab71d1fb727a5aa77 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Wed, 12 May 2004 07:06:05 +0000 Subject: r654: There is no point in having two lines of: sbuf.st_mtime &= ~1; So I had one refer to st_ctime. (This used to be commit cf7a64c05dbc281802a2dc97a182b530fb925db9) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a0e00cfcfe..f221262282 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2400,7 +2400,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (lp_dos_filetime_resolution(SNUM(conn))) { c_time &= ~1; sbuf.st_atime &= ~1; - sbuf.st_mtime &= ~1; + sbuf.st_ctime &= ~1; sbuf.st_mtime &= ~1; } -- cgit From 89db7e100193c3b895180730f49061424a806c8e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 May 2004 00:20:50 +0000 Subject: r656: Make widelinks use realpath(). Tidy up cases where we need to become a service. Jeremy. (This used to be commit a03b6a05e02ec8415efc0e8ceade102e06f8fffe) --- source3/smbd/conn.c | 1 + source3/smbd/filename.c | 2 +- source3/smbd/process.c | 7 +- source3/smbd/service.c | 6 +- source3/smbd/vfs.c | 237 ++++++++++++++++++++---------------------------- 5 files changed, 105 insertions(+), 148 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 9bac0acdb9..e083e14426 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -161,6 +161,7 @@ void conn_close_all(void) connection_struct *conn, *next; for (conn=Connections;conn;conn=next) { next=conn->next; + set_current_service(conn, True); close_cnum(conn, conn->vuid); } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 692c7f7610..a7223e7527 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -399,7 +399,7 @@ BOOL check_name(pstring name,connection_struct *conn) } if (!lp_widelinks(SNUM(conn))) { - ret = reduce_name(conn,name,conn->connectpath); + ret = reduce_name(conn,name); } /* Check if we are allowing users to follow symlinks */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 966bb63c1e..d0dfc6dd7d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -344,6 +344,7 @@ force write permissions on print services. #define CAN_IPC (1<<3) #define AS_GUEST (1<<5) #define QUEUE_IN_OPLOCK (1<<6) +#define DO_CHDIR (1<<7) /* define a list of possible SMB messages and their corresponding @@ -373,7 +374,7 @@ static const struct smb_message_struct { /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER}, -/* 0x11 */ { "SMBexit",reply_exit,0}, +/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR}, /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER}, /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER}, /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER}, @@ -469,7 +470,7 @@ static const struct smb_message_struct { /* 0x6e */ { NULL, NULL, 0 }, /* 0x6f */ { NULL, NULL, 0 }, /* 0x70 */ { "SMBtcon",reply_tcon,0}, -/* 0x71 */ { "SMBtdis",reply_tdis,0}, +/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR}, /* 0x72 */ { "SMBnegprot",reply_negprot,0}, /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0}, /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ @@ -754,7 +755,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(ERROR_DOS(ERRSRV,ERRaccess)); /* load service specific parameters */ - if (conn && !set_current_service(conn,(flags & AS_USER)?True:False)) + if (conn && !set_current_service(conn,(flags & (AS_USER|DO_CHDIR)?True:False))) return(ERROR_DOS(ERRSRV,ERRaccess)); /* does this protocol need to be run as guest? */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 93b017e94c..04cade9577 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -788,6 +788,9 @@ void close_cnum(connection_struct *conn, uint16 vuid) { DirCacheFlush(SNUM(conn)); + file_close_conn(conn); + dptr_closecnum(conn); + change_to_root_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", @@ -799,9 +802,6 @@ void close_cnum(connection_struct *conn, uint16 vuid) yield_connection(conn, lp_servicename(SNUM(conn))); - file_close_conn(conn); - dptr_closecnum(conn); - /* make sure we leave the directory available for unmount */ vfs_ChDir(conn, "/"); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 533220e7df..0f3d591ebb 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -784,168 +784,123 @@ char *vfs_GetWd(connection_struct *conn, char *path) return (path); } - -/* check if the file 'nmae' is a symlink, in that case check that it point to - a file that reside under the 'dir' tree */ - -static BOOL readlink_check(connection_struct *conn, const char *dir, char *name) -{ - BOOL ret = True; - pstring flink; - pstring cleanlink; - pstring savedir; - pstring realdir; - size_t reallen; - - if (!vfs_GetWd(conn, savedir)) { - DEBUG(0,("couldn't vfs_GetWd for %s %s\n", name, dir)); - return False; - } - - if (vfs_ChDir(conn, dir) != 0) { - DEBUG(0,("couldn't vfs_ChDir to %s\n", dir)); - return False; - } - - if (!vfs_GetWd(conn, realdir)) { - DEBUG(0,("couldn't vfs_GetWd for %s\n", dir)); - vfs_ChDir(conn, savedir); - return(False); - } - - reallen = strlen(realdir); - if (realdir[reallen -1] == '/') { - reallen--; - realdir[reallen] = 0; - } - - if (SMB_VFS_READLINK(conn, name, flink, sizeof(pstring) -1) != -1) { - DEBUG(3,("readlink_check: file path name %s is a symlink\nChecking it's path\n", name)); - if (*flink == '/') { - pstrcpy(cleanlink, flink); - } else { - pstrcpy(cleanlink, realdir); - pstrcat(cleanlink, "/"); - pstrcat(cleanlink, flink); - } - unix_clean_name(cleanlink); - - if (strncmp(cleanlink, realdir, reallen) != 0) { - DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n", name, realdir, cleanlink, (int)reallen)); - ret = False; - } - } - - vfs_ChDir(conn, savedir); - - return ret; -} - /******************************************************************* Reduce a file name, removing .. elements and checking that - it is below dir in the heirachy. This uses vfs_GetWd() and so must be run - on the system that has the referenced file system. + it is below dir in the heirachy. This uses realpath. ********************************************************************/ -BOOL reduce_name(connection_struct *conn, pstring s, const char *dir) +BOOL reduce_name(connection_struct *conn, pstring fname) { -#ifndef REDUCE_PATHS - return True; +#ifdef REALPATH_TAKES_NULL + BOOL free_resolved_name = True; #else - pstring dir2; - pstring wd; - pstring base_name; - pstring newname; - char *p=NULL; - BOOL relative = (*s != '/'); - - *dir2 = *wd = *base_name = *newname = 0; - - DEBUG(3,("reduce_name [%s] [%s]\n",s,dir)); - - /* We know there are no double slashes as this comes from srvstr_get_path(). - and has gone through check_path_syntax(). JRA */ - - pstrcpy(base_name,s); - p = strrchr_m(base_name,'/'); +#ifdef PATH_MAX + char resolved_name_buf[PATH_MAX+1]; +#else + pstring resolved_name_buf; +#endif + BOOL free_resolved_name = False; +#endif + char *resolved_name = NULL; + size_t con_path_len = strlen(conn->connectpath); + char *p = NULL; - if (!p) - return readlink_check(conn, dir, s); + DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath)); - if (!vfs_GetWd(conn,wd)) { - DEBUG(0,("couldn't vfs_GetWd for %s %s\n",s,dir)); - return(False); - } +#ifdef REALPATH_TAKES_NULL + resolved_name = SMB_VFS_REALPATH(conn,fname,NULL); +#else + resolved_name = SMB_VFS_REALPATH(conn,fname,resolved_name_buf); +#endif - if (vfs_ChDir(conn,dir) != 0) { - DEBUG(0,("couldn't vfs_ChDir to %s\n",dir)); - return(False); + if (!resolved_name) { + switch (errno) { + case ENOTDIR: + DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname)); + return False; + case ENOENT: + { + pstring tmp_fname; + fstring last_component; + /* Last component didn't exist. Remove it and try and canonicalise the directory. */ + + pstrcpy(tmp_fname, fname); + p = strrchr_m(tmp_fname, '/'); + if (p) { + *p++ = '\0'; + fstrcpy(last_component, p); + } +#ifdef REALPATH_TAKES_NULL + resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,NULL); +#else + resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,resolved_name_buf); +#endif + if (!resolved_name) { + DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname)); + return False; + } + pstrcpy(tmp_fname, resolved_name); + pstrcat(tmp_fname, "/"); + pstrcat(tmp_fname, last_component); +#ifdef REALPATH_TAKES_NULL + SAFE_FREE(resolved_name); + resolved_name = strdup(tmp_fname); + if (!resolved_name) { + DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname)); + return False; + } +#else +#ifdef PATH_MAX + safe_strcpy(resolved_name_buf, tmp_fname, PATH_MAX); +#else + pstrcpy(pstring resolved_name_buf, tmp_fname); +#endif + resolved_name = resolved_name_buf; +#endif + break; + } + default: + DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname)); + return False; + } } - if (!vfs_GetWd(conn,dir2)) { - DEBUG(0,("couldn't vfs_GetWd for %s\n",dir)); - vfs_ChDir(conn,wd); - return(False); - } + DEBUG(10,("reduce_name realpath [%s] -> [%s]\n", fname, resolved_name)); - if (p && (p != base_name)) { - *p = 0; - if (strcmp(p+1,".")==0) - p[1]=0; - if (strcmp(p+1,"..")==0) - *p = '/'; + if (*resolved_name != '/') { + DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n")); + if (free_resolved_name) + SAFE_FREE(resolved_name); + return False; } - if (vfs_ChDir(conn,base_name) != 0) { - vfs_ChDir(conn,wd); - DEBUG(3,("couldn't vfs_ChDir for %s %s basename=%s\n",s,dir,base_name)); - return(False); + if (strncmp(conn->connectpath, resolved_name, con_path_len) != 0) { + DEBUG(2, ("reduce_name: Bad access attemt: %s is a symlink outside the share path", fname)); + if (free_resolved_name) + SAFE_FREE(resolved_name); + return False; } - if (!vfs_GetWd(conn,newname)) { - vfs_ChDir(conn,wd); - DEBUG(2,("couldn't get vfs_GetWd for %s %s\n",s,base_name)); - return(False); + /* Move path the connect path to the last part of the filename. */ + p = resolved_name + con_path_len; + if (*p == '/') { + p++; } - if (p && (p != base_name)) { - pstrcat(newname,"/"); - pstrcat(newname,p+1); + if (!*p) { + pstrcpy(resolved_name, "."); + p = resolved_name; } - { - size_t l = strlen(dir2); - char *last_slash = strrchr_m(dir2, '/'); - - if (last_slash && (last_slash[1] == '\0')) - l--; - - if (strncmp(newname,dir2,l) != 0) { - vfs_ChDir(conn,wd); - DEBUG(2,("Bad access attempt: s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l)); - return(False); - } - - if (!readlink_check(conn, dir, newname)) { - DEBUG(2, ("Bad access attemt: %s is a symlink outside the share path", s)); - return(False); - } - - if (relative) { - if (newname[l] == '/') - pstrcpy(s,newname + l + 1); - else - pstrcpy(s,newname+l); - } else - pstrcpy(s,newname); + if (!lp_symlinks(SNUM(conn)) && (strcmp(fname, p)!=0)) { + DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",fname)); + if (free_resolved_name) + SAFE_FREE(resolved_name); + return False; } - vfs_ChDir(conn,wd); - - if (strlen(s) == 0) - pstrcpy(s,"./"); - - DEBUG(3,("reduced to %s\n",s)); + DEBUG(3,("reduce_name: %s reduced to %s\n", fname, p)); + if (free_resolved_name) + SAFE_FREE(resolved_name); return(True); -#endif } -- cgit From cddd47d2cdf0b25ec0d308f2a775e7a371d28718 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 May 2004 00:56:00 +0000 Subject: r658: Oops - make smbclient work again with widelinks = no :-). Jeremy. (This used to be commit a6979417063e0f0067004dc6207e8e78aa41a58f) --- source3/smbd/trans2.c | 10 ++++------ source3/smbd/vfs.c | 4 ++++ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f221262282..91196766d1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2865,7 +2865,7 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) Returns true if this pathname is within the share, and thus safe. ****************************************************************************/ -static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out) +static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in) { #ifdef PATH_MAX char resolved_name[PATH_MAX+1]; @@ -2882,9 +2882,6 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in pstrcpy(link_dest, link_dest_in); unix_convert(link_dest,conn,0,&bad_path,&sbuf); - /* Store the UNIX converted path. */ - pstrcpy(link_dest_out, link_dest); - p = strrchr_m(link_dest, '/'); if (p) { fstrcpy(last_component, p+1); @@ -2998,7 +2995,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_FILE_IS_A_DIRECTORY; } - if (ensure_link_is_safe(conn, oldname, oldname) != 0) + /* Ensure this is within the share. */ + if (!reduce_name(conn, oldname) != 0) return NT_STATUS_ACCESS_DENIED; DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname )); @@ -3522,7 +3520,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstrcpy(rel_name, "./"); } pstrcat(rel_name, link_target); - if (ensure_link_is_safe(conn, rel_name, rel_name) != 0) { + if (ensure_link_is_safe(conn, rel_name) != 0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 0f3d591ebb..a415e0470e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -829,7 +829,11 @@ BOOL reduce_name(connection_struct *conn, pstring fname) if (p) { *p++ = '\0'; fstrcpy(last_component, p); + } else { + fstrcpy(last_component, tmp_fname); + pstrcpy(tmp_fname, "."); } + #ifdef REALPATH_TAKES_NULL resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,NULL); #else -- cgit From 8fd6298df0c219c522e2262e16eaf97c47f3799f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 May 2004 18:37:54 +0000 Subject: r698: Now wb pipe is non-blocking remember to read in non-blocking mode... Jeremy. (This used to be commit 3399727864f3aa8981f022254dfed622fcb50c49) --- source3/smbd/trans2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 91196766d1..ba2931d809 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3506,12 +3506,17 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE); /* !widelinks forces the target path to be within the share. */ + /* This means we can interpret the target as a pathname. */ if (!lp_widelinks(SNUM(conn))) { pstring rel_name; char *last_dirp = NULL; - unix_format(link_target); - + srvstr_get_path(inbuf, link_target, pdata, sizeof(link_target), + -1, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + unix_convert(link_target,conn,0,&bad_path,&sbuf); pstrcpy(rel_name, newname); last_dirp = strrchr_m(rel_name, '/'); if (last_dirp) { @@ -3520,6 +3525,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstrcpy(rel_name, "./"); } pstrcat(rel_name, link_target); + if (ensure_link_is_safe(conn, rel_name) != 0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } -- cgit From d7af7a26195da2146a16bf9950abcac716079fd7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 May 2004 21:23:40 +0000 Subject: r706: Fix erroneous commit... I've not finished testing the symlink stuff yet. Noticed by Stefan (metze). Jeremy. (This used to be commit 389ad1a05b2197edb20eda270fbd5c7eed7bb2f3) --- source3/smbd/trans2.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ba2931d809..f948b06718 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2400,7 +2400,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (lp_dos_filetime_resolution(SNUM(conn))) { c_time &= ~1; sbuf.st_atime &= ~1; - sbuf.st_ctime &= ~1; + sbuf.st_mtime &= ~1; sbuf.st_mtime &= ~1; } @@ -3506,17 +3506,12 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE); /* !widelinks forces the target path to be within the share. */ - /* This means we can interpret the target as a pathname. */ if (!lp_widelinks(SNUM(conn))) { pstring rel_name; char *last_dirp = NULL; - srvstr_get_path(inbuf, link_target, pdata, sizeof(link_target), - -1, STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - unix_convert(link_target,conn,0,&bad_path,&sbuf); + unix_format(link_target); + pstrcpy(rel_name, newname); last_dirp = strrchr_m(rel_name, '/'); if (last_dirp) { @@ -3525,7 +3520,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstrcpy(rel_name, "./"); } pstrcat(rel_name, link_target); - if (ensure_link_is_safe(conn, rel_name) != 0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } -- cgit From 5cc86fe405ba6d0d241270942bc0988db7efd053 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 May 2004 23:34:00 +0000 Subject: r710: Fix smbclient symlink command when widelinks = no. Jeremy. (This used to be commit ed699a73f899b3212185ecf52d1c4cd59cc8a7ea) --- source3/smbd/trans2.c | 77 +++++---------------------------------------------- 1 file changed, 7 insertions(+), 70 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f948b06718..23272752c6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2400,7 +2400,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (lp_dos_filetime_resolution(SNUM(conn))) { c_time &= ~1; sbuf.st_atime &= ~1; - sbuf.st_mtime &= ~1; + sbuf.st_ctime &= ~1; sbuf.st_mtime &= ~1; } @@ -2861,70 +2861,6 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) return NT_STATUS_OK; } -/**************************************************************************** - Returns true if this pathname is within the share, and thus safe. -****************************************************************************/ - -static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in) -{ -#ifdef PATH_MAX - char resolved_name[PATH_MAX+1]; -#else - pstring resolved_name; -#endif - fstring last_component; - pstring link_dest; - pstring link_test; - char *p; - BOOL bad_path = False; - SMB_STRUCT_STAT sbuf; - - pstrcpy(link_dest, link_dest_in); - unix_convert(link_dest,conn,0,&bad_path,&sbuf); - - p = strrchr_m(link_dest, '/'); - if (p) { - fstrcpy(last_component, p+1); - *p = '\0'; - } else { - fstrcpy(last_component, link_dest); - pstrcpy(link_dest, "./"); - } - - if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL) - return -1; - - DEBUG(10,("ensure_link_is_safe: realpath: link_dest (%s) -> real name (%s)\n", - link_dest, resolved_name )); - - pstrcpy(link_dest, resolved_name); - pstrcat(link_dest, "/"); - pstrcat(link_dest, last_component); - - if (*link_dest != '/') { - /* Relative path. */ - pstrcpy(link_test, conn->connectpath); - pstrcat(link_test, "/"); - pstrcat(link_test, link_dest); - } else { - pstrcpy(link_test, link_dest); - } - - DEBUG(10,("ensure_link_is_safe: connectpath = %s, absolute resolved path = %s\n", - conn->connectpath, link_test )); - - /* - * Check if the link is within the share. - */ - - if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) { - errno = EACCES; - return -1; - } - - return 0; -} - /**************************************************************************** Set a hard link (called by UNIX extensions and by NT rename with HARD link code. @@ -3506,12 +3442,16 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE); /* !widelinks forces the target path to be within the share. */ + /* This means we can interpret the target as a pathname. */ if (!lp_widelinks(SNUM(conn))) { pstring rel_name; char *last_dirp = NULL; unix_format(link_target); - + if (*link_target == '/') { + /* No absolute paths allowed. */ + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } pstrcpy(rel_name, newname); last_dirp = strrchr_m(rel_name, '/'); if (last_dirp) { @@ -3520,11 +3460,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstrcpy(rel_name, "./"); } pstrcat(rel_name, link_target); - if (ensure_link_is_safe(conn, rel_name) != 0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - if (check_name(link_target, conn)) { + if (!check_name(rel_name, conn)) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } } -- cgit From 400bed7a68ccdeeb8c50326e817788e01b155907 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 May 2004 01:22:17 +0000 Subject: r716: Fix for bugid #1345 (Macromedia Homesite cannot connect anymore after upgrade to 3.0.4). Cause was premature optimization in unix_convert(). My fault, sorry. Jeremy. (This used to be commit e5438f0a841e8ea57b515544cbf638c38405ed55) --- source3/smbd/filename.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a7223e7527..5e5f572691 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -132,6 +132,10 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (!*name) { name[0] = '.'; name[1] = '\0'; + if (SMB_VFS_STAT(conn,name,&st) == 0) { + *pst = st; + } + DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); return(True); } -- cgit From 80f72a63009eac05a91877893a802cf1a8a62d98 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 14 May 2004 20:58:26 +0000 Subject: r740: Fix Bug #1301. Return NT_STATUS_SHARING_VIOLATION when share mode locking requests fail. (This used to be commit 5082eb30d0d7c3a4c79b7578457682523a4e80a3) --- source3/smbd/open.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8ab5dab6ac..235a455f30 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -990,6 +990,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (fsp_open) fd_close(conn, fsp); file_free(fsp); + /* + * We have detected a sharing violation here + * so return the correct error code + */ + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return NULL; } @@ -1057,6 +1064,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); + /* + * We have detected a sharing violation here, so + * return the correct code. + */ + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return NULL; } -- cgit From 8b9a044b58cfcf070d5158ffc4533d2a27226e44 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 May 2004 22:08:19 +0000 Subject: r742: Volker discovered that we can truncate a locked file. Well I never ! :-). Jeremy (This used to be commit 1099d60113c2d7b2e5a27a10666cdf885c668778) --- source3/smbd/open.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 235a455f30..f072dc4be4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -242,30 +242,10 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return True; } -/**************************************************************************** - C. Hoch 11/22/95 - Helper for open_file_shared. - Truncate a file after checking locking; close file if locked. - **************************************************************************/ - -static int truncate_unless_locked(struct connection_struct *conn, files_struct *fsp) -{ - SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; - - if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK,True)){ - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRlock; - unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); - return -1; - } else { - return SMB_VFS_FTRUNCATE(fsp,fsp->fd,0); - } -} - /******************************************************************* return True if the filename is one of the special executable types ********************************************************************/ + static BOOL is_executable(const char *fname) { if ((fname = strrchr_m(fname,'.'))) { @@ -1109,7 +1089,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* * We are modifing the file after open - update the stat struct.. */ - if ((truncate_unless_locked(conn,fsp) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { + if ((SMB_VFS_FTRUNCATE(fsp,fsp->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); -- cgit From 49f95e6d27ac9476e8308e53629e8ae4908957c6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 May 2004 00:26:06 +0000 Subject: r762: Fix for #1319 when security > share. Jeremy. (This used to be commit 9fe2240d6b68a2f8a495df585d69ae20c9825d77) --- source3/smbd/uid.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 3859298055..e1864c74ca 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -189,20 +189,26 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) snum = SNUM(conn); + if ((vuser) && !check_user_ok(conn, vuser, snum)) { + DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) not permitted access to share %s.\n", + vuser->user.smb_name, vuser->user.unix_name, vuid, lp_servicename(snum))); + return False; + } + if (conn->force_user) /* security = share sets this too */ { uid = conn->uid; gid = conn->gid; current_user.groups = conn->groups; current_user.ngroups = conn->ngroups; token = conn->nt_user_token; - } else if ((vuser) && check_user_ok(conn, vuser, snum)) { + } else if (vuser) { uid = conn->admin_user ? 0 : vuser->uid; gid = vuser->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; token = vuser->nt_user_token; } else { - DEBUG(2,("change_to_user: Invalid vuid used %d or vuid not permitted access to share.\n",vuid)); + DEBUG(2,("change_to_user: Invalid vuid used %d in accessing share %s.\n",vuid, lp_servicename(snum) )); return False; } -- cgit From 28cbc5f8f9489673b0c766f450a681659a2a0387 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 May 2004 02:25:48 +0000 Subject: r779: Fix specific case of open that doesn't cause oplock break, or share mode check. Test case provided by Volker will be added later. There may be other tests needed. Jeremy. (This used to be commit 1f8e7946edbb2930ba5f9738688dc843bc368fbf) --- source3/smbd/open.c | 27 +++++++++++++++++++++------ source3/smbd/trans2.c | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f072dc4be4..3b4f50b065 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -805,6 +805,25 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } + if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && + ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + oplock_request = 0; + fsp = open_file_stat(conn, fname, psbuf); + if (!fsp) + return NULL; + + fsp->desired_access = desired_access; + if (Access) + *Access = DOS_OPEN_RDONLY; + if (paction) + *paction = FILE_WAS_OPENED; + + DEBUG(10,("open_file_shared: stat open for fname = %s share_mode = %x\n", + fname, share_mode )); + return fsp; + } + fsp = file_new(conn); if(!fsp) return NULL; @@ -1427,12 +1446,8 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST */ fsp->mode = psbuf->st_mode; - /* - * Don't store dev or inode, we don't want any iterator - * to see this. - */ - fsp->inode = (SMB_INO_T)0; - fsp->dev = (SMB_DEV_T)0; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 23272752c6..738d12e020 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2302,7 +2302,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - delete_pending = fsp->directory_delete_on_close; + delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0; } else { /* * Original code - this is an open file. -- cgit From 8c0db1bbc469932694ed877eebecffa3d1948abd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 May 2004 21:49:58 +0000 Subject: r786: Memory leak fixes in (mostly) error code paths from kawasa_r@itg.hitachi.co.jp. A couple of mem leak fixes in mainline code paths though :-). Jeremy. (This used to be commit 4695cc95fe576b6da0d0cb0686f208fc306b2646) --- source3/smbd/posix_acls.c | 4 +++- source3/smbd/sesssetup.c | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 158f1a0ede..584164e930 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2110,8 +2110,10 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * entries out of the blue when setting ACLs, so a get/set * cycle will drop them. */ - if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) + if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) { + SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); continue; + } uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 902db2d288..8a56478929 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -150,7 +150,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB auth_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; - DATA_BLOB session_key; + DATA_BLOB session_key = data_blob(NULL, 0); uint8 tok_id[2]; BOOL foreign = False; DATA_BLOB nullblob = data_blob(NULL, 0); @@ -183,6 +183,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); data_blob_free(&ap_rep); + data_blob_free(&session_key); SAFE_FREE(client); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -192,6 +193,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); + data_blob_free(&session_key); SAFE_FREE(client); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -249,6 +251,7 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(user); SAFE_FREE(client); data_blob_free(&ap_rep); + data_blob_free(&session_key); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -263,6 +266,7 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(user); SAFE_FREE(client); data_blob_free(&ap_rep); + data_blob_free(&session_key); return ERROR_NT(ret); } @@ -274,6 +278,8 @@ static int reply_spnego_kerberos(connection_struct *conn, } /* register_vuid keeps the server info */ + /* register_vuid takes ownership of session_key, no need to free after this. + A better interface would copy it.... */ sess_vuid = register_vuid(server_info, session_key, nullblob, client); SAFE_FREE(user); -- cgit From 67d474861d34490f6a8064d3eadc716d5a3a6020 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 20 May 2004 16:23:17 +0000 Subject: r799: BUG 1259 -- add 'printcap cache time' patch from Lars (This used to be commit fac90741139b953d0e88d050dd457657f0b9c9f3) --- source3/smbd/process.c | 28 +++++++++++++++++++++++++++- source3/smbd/service.c | 24 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d0dfc6dd7d..283b791afd 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1078,15 +1078,41 @@ static int setup_select_timeout(void) void check_reload(int t) { static time_t last_smb_conf_reload_time = 0; + static time_t last_load_printers_reload_time = 0; + time_t printcap_cache_time = (time_t)lp_printcap_cache_time(); - if(last_smb_conf_reload_time == 0) + if(last_smb_conf_reload_time == 0) { last_smb_conf_reload_time = t; + /* Our printing subsystem might not be ready at smbd start up. + Then no printer is available till the first printers check + is performed. A lower initial interval circumvents this. */ + if ( printcap_cache_time > 60 ) + last_load_printers_reload_time = t - printcap_cache_time + 60; + else + last_load_printers_reload_time = t; + } if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { reload_services(True); reload_after_sighup = False; last_smb_conf_reload_time = t; } + + /* 'printcap cache time = 0' disable the feature */ + + if ( printcap_cache_time != 0 ) + { + /* see if it's time to reload or if the clock has been set back */ + + if ( (t >= last_load_printers_reload_time+printcap_cache_time) + || (t-last_load_printers_reload_time < 0) ) + { + DEBUG( 3,( "Printcap cache time expired.\n")); + remove_stale_printers(); + load_printers(); + last_load_printers_reload_time = t; + } + } } /**************************************************************************** diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 04cade9577..c74537c299 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -826,3 +826,27 @@ void close_cnum(connection_struct *conn, uint16 vuid) conn_free(conn); } + +/**************************************************************************** + Remove stale printers +****************************************************************************/ + +void remove_stale_printers( void ) +{ + int snum, iNumServices, printersServiceNum; + const char *pname; + + iNumServices = lp_numservices(); + printersServiceNum = lp_servicenumber( PRINTERS_NAME); + for( snum = 0; snum < iNumServices; snum++) { + /* Never remove PRINTERS_NAME */ + if ( snum == printersServiceNum) + continue; + pname = lp_printername( snum); + /* Is snum a print service and still in the printing subsystem? */ + if ( lp_print_ok( snum) && !pcap_printername_ok( pname, NULL)) { + DEBUG( 3, ( "Removing printer: %s\n", pname)); + lp_killservice( snum); + } + } +} -- cgit From 99d8aa8b17d6b6babdffbaf4f343375d58a88b5b Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Sat, 22 May 2004 05:01:25 +0000 Subject: r814: conn is 0 during ioctl (at least during smbtorture IOCTL test) fix smbd panic (This used to be commit 61da0bb1f6ea22df78ea7bd22a740c5868f62591) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 283b791afd..12fd809b78 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -683,7 +683,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid)); + DEBUG(3,("switch message %s (pid %d) conn 0x%x\n",smb_fn_name(type),(int)pid,(unsigned int)conn)); smb_dump(smb_fn_name(type), 1, inbuf, size); if(global_oplock_break) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2046f2370a..560208ae15 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -489,7 +489,9 @@ int reply_ioctl(connection_struct *conn, } SSVAL(p,0,fsp->rap_print_jobid); /* Job number */ srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII); - srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); + if (conn) { + srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); + } break; } } -- cgit From 7959cba656133840c37d293ffab6831f3097016f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 27 May 2004 15:38:54 +0000 Subject: r925: add changes frpm trunk (r841 and r842) -- enable background queue update process and allow printers to have different sharenames from printernames (This used to be commit 066b9c4276a968788a03709a00d4f672ac032df7) --- source3/smbd/server.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f25d42711d..343a835be8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -849,12 +849,13 @@ void build_options(BOOL screen); /* Setup the main smbd so that we can get messages. */ claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); - /* - DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD - THIS *killed* LOTS OF BUILD FARM MACHINES. IT CREATED HUNDREDS OF - smbd PROCESSES THAT NEVER DIE - start_background_queue(); - */ + /* only start the background queue daemon if we are + running as a daemon -- bad things will happen if + smbd is launched via inetd and we fork a copy of + ourselves here */ + + if ( is_daemon ) + start_background_queue(); if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); -- cgit From 0823cb35175929b0c1dd00369037441293b89ec9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 May 2004 00:41:08 +0000 Subject: r931: Ensure we push 16 bytes (including null termination) not 15. (This used to be commit 1d3fd1a58e0a8b08fe028ceee03618180c7d4b97) --- source3/smbd/lanman.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index c4df84e76c..dd9708356e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1121,11 +1121,11 @@ static int fill_srv_info(struct srv_info_struct *service, switch (uLevel) { case 0: - push_ascii(p,service->name, 15, STR_TERMINATE); + push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE); break; case 1: - push_ascii(p,service->name,15, STR_TERMINATE); + push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE); SIVAL(p,18,service->type); SIVAL(p,22,PTR_DIFF(p2,baseaddr)); len += CopyAndAdvance(&p2,service->comment,&l2); -- cgit From cb03592c067a8e475a5f96f72aa0e84ba176a747 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 May 2004 01:54:01 +0000 Subject: r933: When using widelinks = no, use realpath to canonicalize the connection path on connection create for the user. We'll be checking all symlinked paths are below this directory. Jeremy. (This used to be commit b562fe9fbca4971059b913959bbaca02af42c1a4) --- source3/smbd/filename.c | 2 +- source3/smbd/service.c | 14 ++++++++++++++ source3/smbd/vfs.c | 27 ++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5e5f572691..67329b51e6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -135,7 +135,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; } - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + DEBUG(5,("conversion finished \"\" -> %s\n",name)); return(True); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c74537c299..192a043bf5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -499,6 +499,20 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } + /* + * If widelinks are disallowed we need to canonicalise the + * connect path here to ensure we don't have any symlinks in + * the connectpath. We will be checking all paths on this + * connection are below this directory. We must do this after + * the VFS init as we depend on the realpath() pointer in the vfs table. JRA. + */ + if (!lp_widelinks(snum)) { + pstring s; + pstrcpy(s,conn->connectpath); + canonicalize_path(conn, s); + string_set(&conn->connectpath,s); + } + /* ROOT Activities: */ /* check number of connections */ if (!claim_connection(conn, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a415e0470e..86f180e543 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -784,6 +784,31 @@ char *vfs_GetWd(connection_struct *conn, char *path) return (path); } +BOOL canonicalize_path(connection_struct *conn, pstring path) +{ +#ifdef REALPATH_TAKES_NULL + char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL); + if (!resolved_name) { + return False; + } + pstrcpy(path, resolved_name); + SAFE_FREE(resolved_name); + return True; +#else +#ifdef PATH_MAX + char resolved_name_buf[PATH_MAX+1]; +#else + pstring resolved_name_buf; +#endif + char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf); + if (!resolved_name) { + return False; + } + pstrcpy(path, resolved_name); + return True; +#endif /* REALPATH_TAKES_NULL */ +} + /******************************************************************* Reduce a file name, removing .. elements and checking that it is below dir in the heirachy. This uses realpath. @@ -879,7 +904,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) } if (strncmp(conn->connectpath, resolved_name, con_path_len) != 0) { - DEBUG(2, ("reduce_name: Bad access attemt: %s is a symlink outside the share path", fname)); + DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname)); if (free_resolved_name) SAFE_FREE(resolved_name); return False; -- cgit From 004618ffccbd679f3a2e3532871e8bac3be8f7da Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 28 May 2004 19:15:11 +0000 Subject: r942: If using DOS error codes, we need to return ERRDOS/ERRbadpath for chkpth even if only the last component failed. I'm not sure if all the other cases of NT_STATUS_OBJECT_NAME_NOT_FOUND also need to be fixed, this at least helps with 'copy test1.txt test2.txt' from DOS within a subdirectory. Yes, I do have someone who needs this :-) Jeremy, could you take a look at this? Thanks, Volker (This used to be commit 3093ab100653782bd8e029170d315c68b7f271af) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 560208ae15..fff5385171 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -555,7 +555,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } else { END_PROFILE(SMBchkpth); - return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); + return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); } } else if (errno == ENOTDIR) { END_PROFILE(SMBchkpth); -- cgit From e003407584a82bd9752b7191f1ed27b5e89e524c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 30 May 2004 07:21:50 +0000 Subject: r945: "Correct" (as in, more correct) way to handle stat opens. Doesn't regress the torture tester. Passes OPEN tests in Samba3 and Samba4 and oplock tests in Samba4. Last thing to check, can an "attribute only" open actually create a file. I think it can.... Jeremy. (This used to be commit d8177a42d4a2a2b6df5d0593f2f92bddc29ffe94) --- source3/smbd/open.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3b4f50b065..cc6f014ceb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -555,7 +555,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T share_mode_entry *old_shares = 0; BOOL fcbopen = False; BOOL broke_oplock; - + if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) fcbopen = True; @@ -564,6 +564,13 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T if(num_share_modes == 0) return 0; + if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && + ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + *p_oplock_request = 0; + return num_share_modes; + } + /* * Check if the share modes will give us access. */ @@ -781,6 +788,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; BOOL def_acl = False; + BOOL add_share_mode = True; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; @@ -805,25 +813,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } - if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && - ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { - /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - oplock_request = 0; - fsp = open_file_stat(conn, fname, psbuf); - if (!fsp) - return NULL; - - fsp->desired_access = desired_access; - if (Access) - *Access = DOS_OPEN_RDONLY; - if (paction) - *paction = FILE_WAS_OPENED; - - DEBUG(10,("open_file_shared: stat open for fname = %s share_mode = %x\n", - fname, share_mode )); - return fsp; - } - fsp = file_new(conn); if(!fsp) return NULL; @@ -947,6 +936,16 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return NULL; } + if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && + ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + oplock_request = 0; + add_share_mode = False; + if (file_existed) { + flags2 &= ~O_CREAT; + } + } + if (file_existed) { dev = psbuf->st_dev; @@ -1166,14 +1165,18 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", oplock_request = 0; } - set_share_mode(fsp, port, oplock_request); + if (add_share_mode) { + set_share_mode(fsp, port, oplock_request); + } if (delete_on_close) { NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { /* Remember to delete the mode we just added. */ - del_share_mode(fsp, NULL); + if (add_share_mode) { + del_share_mode(fsp, NULL); + } unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); -- cgit From 6798fd8e3c764f46f9993bb7c986b2454b2aab42 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Jun 2004 04:55:42 +0000 Subject: r957: Fixup moribund unix extensions mknod code path. Don't add in configure test yet. Also allow unix domain socket create. Jeremy. (This used to be commit 2db0c4ca7b23cdd1dbf83d4de58acbf4dc118df2) --- source3/smbd/trans2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 738d12e020..02a6bf6e4b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3374,14 +3374,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return(ERROR_DOS(ERRDOS,ERRnoaccess)); if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV && - file_type != UNIX_TYPE_FIFO) + file_type != UNIX_TYPE_FIFO && + file_type != UNIX_TYPE_SOCKET) return(ERROR_DOS(ERRDOS,ERRnoaccess)); DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ 0%o for file %s\n", (double)dev, unixmode, fname )); /* Ok - do the mknod. */ - if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0) + if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); inherit_access_acl(conn, fname, unixmode); -- cgit From 03d4344432c6aa75d400afc501aec1a14070f35d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Jun 2004 20:43:32 +0000 Subject: r971: Auto remove store dos attributes if underlying filesystem doesn't support EA's. Jeremy. (This used to be commit 9de6b25c9e9abe982e21b0229df520802cafbfd8) --- source3/smbd/dosmode.c | 13 +++++++++++++ source3/smbd/process.c | 24 +++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index d7dc63bb2f..33c75fffd5 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -182,6 +182,7 @@ static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES)) { DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n", path, strerror(errno) )); + set_store_dos_attributes(SNUM(conn), False); } #endif return False; @@ -224,9 +225,21 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ files_struct *fsp = NULL; BOOL ret = False; + if (!lp_store_dos_attributes(SNUM(conn))) { + return False; + } + snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK); if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) { if((errno != EPERM) && (errno != EACCES)) { + if (errno == ENOSYS +#if defined(ENOTSUP) + || errno == ENOTSUP) { +#else + ) { +#endif + set_store_dos_attributes(SNUM(conn), False); + } return False; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 12fd809b78..efbc66a0ac 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -61,23 +61,24 @@ uint16 get_current_mid(void) for processing. ****************************************************************************/ -typedef struct { - ubi_slNode msg_next; +struct pending_message_list { + struct pending_message_list *next, *prev; char *msg_buf; int msg_len; -} pending_message_list; +}; -static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0}; +static struct pending_message_list *smb_oplock_queue; /**************************************************************************** Function to push a message onto the tail of a linked list of smb messages ready for processing. ****************************************************************************/ -static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) +static BOOL push_message(struct pending_message_list *list_head, char *buf, int msg_len) { - pending_message_list *msg = (pending_message_list *) - malloc(sizeof(pending_message_list)); + struct pending_message_list *tmp_msg; + struct pending_message_list *msg = (struct pending_message_list *) + malloc(sizeof(struct pending_message_list)); if(msg == NULL) { DEBUG(0,("push_message: malloc fail (1)\n")); @@ -94,7 +95,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) memcpy(msg->msg_buf, buf, msg_len); msg->msg_len = msg_len; - ubi_slAddTail( list_head, msg); + DLIST_ADD_END(list_head, msg, tmp_msg); /* Push the MID of this packet on the signing queue. */ srv_defer_sign_response(SVAL(buf,smb_mid)); @@ -109,7 +110,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) BOOL push_oplock_pending_smb_message(char *buf, int msg_len) { - return push_message(&smb_oplock_queue, buf, msg_len); + return push_message(smb_oplock_queue, buf, msg_len); } /**************************************************************************** @@ -185,11 +186,12 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) * Check to see if we already have a message on the smb queue. * If so - copy and return it. */ - if(ubi_slCount(&smb_oplock_queue) != 0) { - pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue); + if(smb_oplock_queue != NULL) { + struct pending_message_list *msg = smb_oplock_queue; memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); /* Free the message we just copied. */ + DLIST_REMOVE(smb_oplock_queue, msg); SAFE_FREE(msg->msg_buf); SAFE_FREE(msg); -- cgit From efc96df3d5b415ca9c19527a44d0619992712b6d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jun 2004 02:12:54 +0000 Subject: r974: Fix open code to pass more torture tests. We now pass the Samba4 oplock test. We do this be changing the algorithm when breaking oplocks slightly. Previously we broke an oplock, then re-loaded the share modes and re-iterated. Now we break all oplocks, then re-load the share modes and check the share details - then iterate. This seems to match the way Win2k3 does it. Jeremy. (This used to be commit 5ec4f4e4e6596ea0f52aca5c9e1a75bf35612e37) --- source3/smbd/open.c | 115 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cc6f014ceb..ab5ea236fa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -364,6 +364,8 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i int deny_mode = GET_DENY_MODE(share_mode); int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); + BOOL non_io_open_request; + BOOL non_io_open_existing; /* * share modes = false means don't bother to check for @@ -373,6 +375,18 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i if(!lp_share_modes(SNUM(conn))) return True; + if (desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + non_io_open_request = False; + } else { + non_io_open_request = True; + } + + if (share->desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + non_io_open_existing = False; + } else { + non_io_open_existing = True; + } + /* * Don't allow any opens once the delete on close flag has been * set. @@ -411,8 +425,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i * and the existing desired_acces then share modes don't conflict. */ - if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) && - !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + if (non_io_open_request && non_io_open_existing) { /* * Wrinkle discovered by smbtorture.... @@ -436,6 +449,13 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i and existing desired access (0x%x) are non-data opens\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); return True; + } else if (non_io_open_request || non_io_open_existing) { + /* + * If either are non-io opens then share modes don't conflict. + */ + DEBUG(5,("check_share_mode: One non-io open. Allowing open on file %s as desired access (0x%x) doesn't conflict with\ +existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); + return True; } /* @@ -537,6 +557,20 @@ static void validate_my_share_entries(int num, share_mode_entry *share_entry) } #endif +struct share_mode_entry_list { + struct share_mode_entry_list *next, *prev; + share_mode_entry entry; +}; + +static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_list) +{ + while (broken_entry_list) { + struct share_mode_entry_list *broken_entry = broken_entry_list; + DLIST_REMOVE(broken_entry_list, broken_entry); + SAFE_FREE(broken_entry); + } +} + /**************************************************************************** Deal with open deny mode and oplock break processing. Invarient: Share mode must be locked on entry and exit. @@ -554,7 +588,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T int oplock_contention_count = 0; share_mode_entry *old_shares = 0; BOOL fcbopen = False; - BOOL broke_oplock; + BOOL broke_oplock; if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) fcbopen = True; @@ -567,7 +601,6 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - *p_oplock_request = 0; return num_share_modes; } @@ -576,12 +609,14 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T */ do { - share_mode_entry broken_entry; - + struct share_mode_entry_list *broken_entry_list = NULL; + struct share_mode_entry_list *broken_entry = NULL; + broke_oplock = False; *p_all_current_opens_are_level_II = True; for(i = 0; i < num_share_modes; i++) { + BOOL cause_oplock_break = False; share_mode_entry *share_entry = &old_shares[i]; #if defined(DEVELOPER) @@ -596,9 +631,17 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T * it before continuing. */ - if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || + /* Was this a delete this file request ? */ + if (!*p_oplock_request && desired_access == DELETE_ACCESS && + !BATCH_OPLOCK_TYPE(share_entry->op_type)) { + /* Don't break the oplock in this case. */ + cause_oplock_break = False; + } else if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { - + cause_oplock_break = True; + } + + if(cause_oplock_break) { BOOL opb_ret; DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ @@ -629,50 +672,65 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou return -1; } + broken_entry = malloc(sizeof(struct share_mode_entry_list)); + if (!broken_entry) { + smb_panic("open_mode_check: malloc fail.\n"); + } + broken_entry->entry = *share_entry; + DLIST_ADD(broken_entry_list, broken_entry); broke_oplock = True; - broken_entry = *share_entry; - break; } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { *p_all_current_opens_are_level_II = False; } - + } /* end for */ + + if (broke_oplock) { + /* Update the current open table. */ + SAFE_FREE(old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + } + + /* Now we check the share modes, after any oplock breaks. */ + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + /* someone else has a share lock on it, check to see if we can too */ if (!check_share_mode(conn, share_entry, share_mode, desired_access, fname, fcbopen, p_flags)) { SAFE_FREE(old_shares); + free_broken_entry_list(broken_entry_list); errno = EACCES; return -1; } - - } /* end for */ - - if(broke_oplock) { - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + } + + for(broken_entry = broken_entry_list; broken_entry; broken_entry = broken_entry->next) { oplock_contention_count++; /* Paranoia check that this is no longer an exlusive entry. */ for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &old_shares[i]; - if (share_modes_identical(&broken_entry, share_entry) && - EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) { + if (share_modes_identical(&broken_entry->entry, share_entry) && + EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) { /* * This should not happen. The target left this oplock * as exlusive.... The process *must* be dead.... */ - DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, \ -dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); + DEBUG(0,("open_mode_check: exlusive oplock left by process %d \ +after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n", + (int)broken_entry->entry.pid, fname, (unsigned int)dev, (double)inode)); - if (process_exists(broken_entry.pid)) { + if (process_exists(broken_entry->entry.pid)) { DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n", - (unsigned long)broken_entry.pid )); + (unsigned long)broken_entry->entry.pid )); } - if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { + if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) { + free_broken_entry_list(broken_entry_list); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -690,8 +748,8 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn break; } } /* end for paranoia... */ - } /* end if broke_oplock */ - + } /* end for broken_entry */ + free_broken_entry_list(broken_entry_list); } while(broke_oplock); if(old_shares != 0) @@ -939,9 +997,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - oplock_request = 0; - add_share_mode = False; + deny_mode = DENY_NONE; if (file_existed) { + oplock_request = 0; + add_share_mode = False; flags2 &= ~O_CREAT; } } -- cgit From b7ac82294f83b4b60d23b5ddf2ffe2caf5aef1a6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jun 2004 00:09:57 +0000 Subject: r996: Fix error in change to queuing code (dlink). Jeremy. (This used to be commit 6bd6359090b59d48370e16bb0ddc267a51b361c7) --- source3/smbd/process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index efbc66a0ac..72df91a21d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -74,7 +74,7 @@ static struct pending_message_list *smb_oplock_queue; for processing. ****************************************************************************/ -static BOOL push_message(struct pending_message_list *list_head, char *buf, int msg_len) +static BOOL push_message(struct pending_message_list **pplist_head, char *buf, int msg_len) { struct pending_message_list *tmp_msg; struct pending_message_list *msg = (struct pending_message_list *) @@ -95,7 +95,7 @@ static BOOL push_message(struct pending_message_list *list_head, char *buf, int memcpy(msg->msg_buf, buf, msg_len); msg->msg_len = msg_len; - DLIST_ADD_END(list_head, msg, tmp_msg); + DLIST_ADD_END(*pplist_head, msg, tmp_msg); /* Push the MID of this packet on the signing queue. */ srv_defer_sign_response(SVAL(buf,smb_mid)); @@ -110,7 +110,7 @@ static BOOL push_message(struct pending_message_list *list_head, char *buf, int BOOL push_oplock_pending_smb_message(char *buf, int msg_len) { - return push_message(smb_oplock_queue, buf, msg_len); + return push_message(&smb_oplock_queue, buf, msg_len); } /**************************************************************************** -- cgit From a6f5c88563c2169ce125be4e84f6980714f7e1ff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jun 2004 00:20:58 +0000 Subject: r998: Arrrgggh. Do it right this time :-(. Jeremy. (This used to be commit 7ac7cd41629779c877b62ebd54b965980f4dc7bf) --- source3/smbd/process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 72df91a21d..ccebd2b86c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -74,7 +74,7 @@ static struct pending_message_list *smb_oplock_queue; for processing. ****************************************************************************/ -static BOOL push_message(struct pending_message_list **pplist_head, char *buf, int msg_len) +static BOOL push_message(char *buf, int msg_len) { struct pending_message_list *tmp_msg; struct pending_message_list *msg = (struct pending_message_list *) @@ -95,7 +95,7 @@ static BOOL push_message(struct pending_message_list **pplist_head, char *buf, i memcpy(msg->msg_buf, buf, msg_len); msg->msg_len = msg_len; - DLIST_ADD_END(*pplist_head, msg, tmp_msg); + DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg); /* Push the MID of this packet on the signing queue. */ srv_defer_sign_response(SVAL(buf,smb_mid)); @@ -110,7 +110,7 @@ static BOOL push_message(struct pending_message_list **pplist_head, char *buf, i BOOL push_oplock_pending_smb_message(char *buf, int msg_len) { - return push_message(&smb_oplock_queue, buf, msg_len); + return push_message(buf, msg_len); } /**************************************************************************** -- cgit From 386a11f49eff2ec60d75b9966ecdc5627b259f0d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 4 Jun 2004 17:26:09 +0000 Subject: r1011: fix bad merge (from a few months ago) and ensure that we always use tdb_open_log() instead of tdb_open_ex() (This used to be commit e65564ab4aa1240e84b8d272510aa770cad0ed0e) --- source3/smbd/connection.c | 8 ++++---- source3/smbd/session.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index a9ab142461..5bb76eb3bd 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -29,8 +29,8 @@ static TDB_CONTEXT *tdb; TDB_CONTEXT *conn_tdb_ctx(void) { if (!tdb) - tdb = tdb_open_ex(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644, smbd_tdb_log); + tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644); return tdb; } @@ -131,8 +131,8 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti TDB_DATA kbuf, dbuf; if (!tdb) - tdb = tdb_open_ex(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644, smbd_tdb_log); + tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644); if (!tdb) return False; diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 61118f13dd..91ebaeb830 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -34,8 +34,8 @@ BOOL session_init(void) if (tdb) return True; - tdb = tdb_open_ex(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644, smbd_tdb_log); + tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644); if (!tdb) { DEBUG(1,("session_init: failed to open sessionid tdb\n")); return False; -- cgit From 2fc57c9a2ce3a266534dd20e6fed4883e052c557 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jun 2004 16:14:31 +0000 Subject: r1085: Now it's had some proper user testing, merge in the deferred open fix. I'm still doing more testing, but it fixes a behaviour that we've been wrong on ever since the start of Samba. Jeremy. (This used to be commit 894cc6d16296b934c112786eec896846156aee5d) --- source3/smbd/close.c | 30 +++++++ source3/smbd/dir.c | 3 +- source3/smbd/nttrans.c | 8 ++ source3/smbd/open.c | 200 ++++++++++++++++++++++++++++++++++++++++----- source3/smbd/oplock.c | 70 +++++++++++++++- source3/smbd/process.c | 217 ++++++++++++++++++++++++++++++++++++++++++++----- source3/smbd/reply.c | 32 +++++++- source3/smbd/trans2.c | 8 +- 8 files changed, 521 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 8b3010c1b2..305377dfc6 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. file closing Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1992-2004. 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 @@ -104,6 +105,32 @@ static int close_filestruct(files_struct *fsp) return ret; } +/**************************************************************************** + If any deferred opens are waiting on this close, notify them. +****************************************************************************/ + +static void notify_deferred_opens(files_struct *fsp) +{ + deferred_open_entry *de_array = NULL; + int num_de_entries, i; + pid_t mypid = sys_getpid(); + + num_de_entries = get_deferred_opens(fsp->conn, fsp->dev, fsp->inode, &de_array); + for (i = 0; i < num_de_entries; i++) { + deferred_open_entry *entry = &de_array[i]; + if (entry->pid == mypid) { + /* + * We need to notify ourself to retry the open. + * Do this by finding the queued SMB record, moving it + * to the head of the queue and changing the wait time to zero. + */ + schedule_sharing_violation_open_smb_message(entry->mid); + } else { + send_deferred_open_retry_message(entry); + } + } +} + /**************************************************************************** Close a file. @@ -177,6 +204,9 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) SAFE_FREE(share_entry); + /* Notify any deferred opens waiting on this close. */ + notify_deferred_opens(fsp); + /* * NT can set delete_on_close of the last open * reference to a file. diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 06ef23ab8c..b88f687766 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -763,7 +763,8 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return True; else fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, + &access_mode, &smb_action); if (!fsp) return False; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 26be4434fd..e540db234a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -863,6 +863,10 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } @@ -1347,6 +1351,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } else { restore_case_semantics(conn, file_attributes); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ab5ea236fa..04e074d56e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 2001 + Copyright (C) Jeremy Allison 2001-2004 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 @@ -26,6 +26,11 @@ extern uint16 global_oplock_port; extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; +struct dev_inode_bundle { + SMB_DEV_T dev; + SMB_INO_T inode; +}; + /**************************************************************************** fd support routines - attempt to do a dos_open. ****************************************************************************/ @@ -243,7 +248,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, } /******************************************************************* -return True if the filename is one of the special executable types + Return True if the filename is one of the special executable types. ********************************************************************/ static BOOL is_executable(const char *fname) @@ -262,12 +267,13 @@ static BOOL is_executable(const char *fname) enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* -reproduce the share mode access table -this is horrendoously complex, and really can't be justified on any -rational grounds except that this is _exactly_ what NT does. See -the DENY1 and DENY2 tests in smbtorture for a comprehensive set of -test routines. + Reproduce the share mode access table. + This is horrendoously complex, and really can't be justified on any + rational grounds except that this is _exactly_ what NT does. See + the DENY1 and DENY2 tests in smbtorture for a comprehensive set of + test routines. ********************************************************************/ + static int access_table(int new_deny,int old_deny,int old_mode, BOOL same_pid, BOOL isexe) { @@ -353,9 +359,8 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } - /**************************************************************************** -check if we can open a file with a share mode + Check if we can open a file with a share mode. ****************************************************************************/ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access, @@ -770,9 +775,101 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" } /**************************************************************************** -set a kernel flock on a file for NFS interoperability -this requires a patch to Linux + Delete the record for a handled deferred open entry. +****************************************************************************/ + +static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) +{ + uint16 mid = get_current_mid(); + pid_t mypid = sys_getpid(); + deferred_open_entry *de_array = NULL; + int num_de_entries, i; + + num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); + for (i = 0; i < num_de_entries; i++) { + deferred_open_entry *entry = &de_array[i]; + if (entry->pid == mypid && entry->mid == mid && entry->dev == dev && + entry->inode == inode) { + + /* Remove the deferred open entry from the array. */ + delete_deferred_open_entry(entry); + SAFE_FREE(de_array); + return; + } + } + SAFE_FREE(de_array); +} + +/**************************************************************************** + Handle the 1 second delay in returning a SHARING_VIOLATION error. +****************************************************************************/ + +void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, + char *fname, SMB_DEV_T dev, SMB_INO_T inode) +{ + uint16 mid = get_current_mid(); + pid_t mypid = sys_getpid(); + deferred_open_entry *de_array = NULL; + int num_de_entries, i; + struct dev_inode_bundle dib; + + dib.dev = dev; + dib.inode = inode; + + num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); + for (i = 0; i < num_de_entries; i++) { + deferred_open_entry *entry = &de_array[i]; + if (entry->pid == mypid && entry->mid == mid) { + /* + * Check if a 1 second timeout has expired. + */ + if (usec_time_diff(ptv, &entry->time) > SHARING_VIOLATION_USEC_WAIT) { + DEBUG(10,("defer_open_sharing_error: Deleting deferred open entry for mid %u, \ +file %s\n", + (unsigned int)mid, fname )); + + /* Expired, return a real error. */ + /* Remove the deferred open entry from the array. */ + + delete_deferred_open_entry(entry); + SAFE_FREE(de_array); + return; + } + /* + * If the timeout hasn't expired yet and we still have a sharing violation, + * just leave the entry in the deferred open array alone. We do need to + * reschedule this open call though (with the original created time). + */ + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] updating \ +deferred open entry for mid %u, file %s\n", + (unsigned int)entry->time.tv_sec, + (unsigned int)entry->time.tv_usec, + (unsigned int)mid, fname )); + + push_sharing_violation_open_smb_message(&entry->time, (char *)&dib, sizeof(dib)); + SAFE_FREE(de_array); + return; + } + } + + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred open entry for mid %u, file %s\n", + (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, (unsigned int)mid, fname )); + + if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) { + SAFE_FREE(de_array); + return; + } + if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) { + remove_sharing_violation_open_smb_message(mid); + } + SAFE_FREE(de_array); +} + +/**************************************************************************** + Set a kernel flock on a file for NFS interoperability. + This requires a patch to Linux. ****************************************************************************/ + static void kernel_flock(files_struct *fsp, int deny_mode) { #if HAVE_KERNEL_SHARE_MODES @@ -847,6 +944,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL fcbopen = False; BOOL def_acl = False; BOOL add_share_mode = True; + BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; @@ -858,9 +956,50 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ mode_t new_mode = (mode_t)0; int action; uint32 existing_dos_mode = 0; + struct pending_message_list *pml = NULL; + uint16 mid = get_current_mid(); /* We add aARCH to this as this mode is only used if the file is created new. */ mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname); + if (oplock_request == INTERNAL_OPEN_ONLY) { + internal_only_open = True; + oplock_request = 0; + } + + if ((pml = get_open_deferred_message(mid)) != NULL) { + struct dev_inode_bundle dib; + + memcpy(&dib, pml->private_data.data, sizeof(dib)); + + /* There could be a race condition where the dev/inode pair + has changed since we deferred the message. If so, just + remove the deferred open entry and return sharing violation. */ + + /* If the timeout value is non-zero, we need to just + return sharing violation. Don't retry the open + as we were not notified of a close and we don't want to + trigger another spurious oplock break. */ + + if (!file_existed || dib.dev != psbuf->st_dev || dib.inode != psbuf->st_ino || + pml->msg_time.tv_sec || pml->msg_time.tv_usec) { + /* Ensure we don't reprocess this message. */ + remove_sharing_violation_open_smb_message(mid); + + /* Now remove the deferred open entry under lock. */ + lock_share_entry(conn, dib.dev, dib.inode); + delete_defered_open_entry_record(conn, dib.dev, dib.inode); + unlock_share_entry(conn, dib.dev, dib.inode); + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + return NULL; + } + /* Ensure we don't reprocess this message. */ + remove_sharing_violation_open_smb_message(mid); + + } + if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are ignored */ @@ -1043,17 +1182,28 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; } + /* + * If we're returning a share violation, ensure we cope with + * the braindead 1 second delay. + */ + + if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { + /* The fsp->open_time here represents the current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + } + unlock_share_entry(conn, dev, inode); - if (fsp_open) + if (fsp_open) { fd_close(conn, fsp); + /* + * We have detected a sharing violation here + * so return the correct error code + */ + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + } file_free(fsp); - /* - * We have detected a sharing violation here - * so return the correct error code - */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return NULL; } @@ -1118,6 +1268,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", &flags, &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { + /* + * If we're returning a share violation, ensure we cope with + * the braindead 1 second delay. + */ + + if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { + /* The fsp->open_time here represents the current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + } + unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1286,6 +1446,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", fname, (int)new_mode)); } + /* If this is a successful open, we must remove any deferred open records. */ + delete_defered_open_entry_record(conn, fsp->dev, fsp->inode); unlock_share_entry_fsp(fsp); conn->num_files_open++; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 19e6956d9e..6739f5654f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -388,6 +388,30 @@ pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); break; + case RETRY_DEFERRED_OPEN_CMD: + + /* Request to retry and open that would return SHARING_VIOLATION. */ + if (msg_len != DEFERRED_OPEN_MSG_LEN) { + DEBUG(0,("process_local_message: incorrect length for RETRY_DEFERRED_OPEN_CMD (was %d, should be %d).\n", + (int)msg_len, (int)DEFERRED_OPEN_MSG_LEN)); + return False; + } + { + uint16 mid; + + memcpy((char *)&remotepid, msg_start+DEFERRED_OPEN_PID_OFFSET,sizeof(remotepid)); + memcpy((char *)&inode, msg_start+DEFERRED_OPEN_INODE_OFFSET,sizeof(inode)); + memcpy((char *)&dev, msg_start+DEFERRED_OPEN_DEV_OFFSET,sizeof(dev)); + memcpy((char *)&mid, msg_start+DEFERRED_OPEN_MID_OFFSET,sizeof(mid)); + + DEBUG(5,("process_local_message: RETRY_DEFERRED_OPEN from \ +pid %d, port %d, dev = %x, inode = %.0f, mid = %u\n", + (int)remotepid, from_port, (unsigned int)dev, (double)inode, (unsigned int)mid)); + + schedule_sharing_violation_open_smb_message(mid); + } + break; + /* * Keep this as a debug case - eventually we can remove it. */ @@ -1215,7 +1239,51 @@ void release_level_2_oplocks_on_change(files_struct *fsp) } /**************************************************************************** -setup oplocks for this process + Send a 'retry your open' message to a process with a deferred open entry. +****************************************************************************/ + +BOOL send_deferred_open_retry_message(deferred_open_entry *entry) +{ + char de_msg[DEFERRED_OPEN_MSG_LEN]; + struct sockaddr_in addr_out; + pid_t pid = sys_getpid(); + + memset(de_msg, '\0', DEFERRED_OPEN_MSG_LEN); + SSVAL(de_msg,DEFERRED_OPEN_CMD_OFFSET,RETRY_DEFERRED_OPEN_CMD); + memcpy(de_msg+DEFERRED_OPEN_PID_OFFSET,(char *)&pid,sizeof(pid)); + memcpy(de_msg+DEFERRED_OPEN_DEV_OFFSET,(char *)&entry->dev,sizeof(entry->dev)); + memcpy(de_msg+DEFERRED_OPEN_INODE_OFFSET,(char *)&entry->inode,sizeof(entry->inode)); + memcpy(de_msg+DEFERRED_OPEN_MID_OFFSET,(char *)&entry->mid,sizeof(entry->mid)); + + /* Set the address and port. */ + memset((char *)&addr_out,'\0',sizeof(addr_out)); + addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_out.sin_port = htons( entry->port ); + addr_out.sin_family = AF_INET; + + if( DEBUGLVL( 3 ) ) { + dbgtext( "send_deferred_open_retry_message: sending a message to "); + dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port ); + dbgtext( "for dev = %x, inode = %.0f, mid = %u\n", + (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid ); + } + + if(sys_sendto(oplock_sock,de_msg,DEFERRED_OPEN_MSG_LEN,0, + (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "send_deferred_open_retry_message: failed sending a message to "); + dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port ); + dbgtext( "for dev = %x, inode = %.0f, mid = %u\n", + (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid ); + dbgtext( "Error was %s\n", strerror(errno) ); + } + return False; + } + return True; +} + +/**************************************************************************** + Setup oplocks for this process. ****************************************************************************/ BOOL init_oplocks(void) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ccebd2b86c..698c8475f7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -61,20 +61,28 @@ uint16 get_current_mid(void) for processing. ****************************************************************************/ -struct pending_message_list { - struct pending_message_list *next, *prev; - char *msg_buf; - int msg_len; -}; - static struct pending_message_list *smb_oplock_queue; +static struct pending_message_list *smb_sharing_violation_queue; + +enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE }; + +/**************************************************************************** + Free up a message. +****************************************************************************/ + +static void free_queued_message(struct pending_message_list *msg) +{ + data_blob_free(&msg->buf); + data_blob_free(&msg->private_data); + SAFE_FREE(msg); +} /**************************************************************************** Function to push a message onto the tail of a linked list of smb messages ready for processing. ****************************************************************************/ -static BOOL push_message(char *buf, int msg_len) +static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private, size_t private_len) { struct pending_message_list *tmp_msg; struct pending_message_list *msg = (struct pending_message_list *) @@ -85,32 +93,159 @@ static BOOL push_message(char *buf, int msg_len) return False; } - msg->msg_buf = (char *)malloc(msg_len); - if(msg->msg_buf == NULL) { + memset(msg,'\0',sizeof(*msg)); + + msg->buf = data_blob(buf, msg_len); + if(msg->buf.data == NULL) { DEBUG(0,("push_message: malloc fail (2)\n")); SAFE_FREE(msg); return False; } - memcpy(msg->msg_buf, buf, msg_len); - msg->msg_len = msg_len; + if (ptv) { + msg->msg_time = *ptv; + } - DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg); + if (private) { + msg->private_data = data_blob(private, private_len); + if (msg->private_data.data == NULL) { + DEBUG(0,("push_message: malloc fail (3)\n")); + data_blob_free(&msg->buf); + SAFE_FREE(msg); + } + } + + if (qt == OPLOCK_QUEUE) { + DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg); + } else { + DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg); + } /* Push the MID of this packet on the signing queue. */ srv_defer_sign_response(SVAL(buf,smb_mid)); + DEBUG(10,("push_message: pushed message length %u on queue %s\n", + (unsigned int)msg_len, + qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" )); + return True; } /**************************************************************************** - Function to push a smb message onto a linked list of local smb messages ready + Function to push an oplock smb message onto a linked list of local smb messages ready for processing. ****************************************************************************/ BOOL push_oplock_pending_smb_message(char *buf, int msg_len) { - return push_message(buf, msg_len); + return push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0); +} + +/**************************************************************************** + Function to delete a sharing violation open message by mid. +****************************************************************************/ + +void remove_sharing_violation_open_smb_message(uint16 mid) +{ + struct pending_message_list *pml; + + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + if (mid == SVAL(pml->buf.data,smb_mid)) { + DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n", + (unsigned int)mid, (unsigned int)pml->buf.length )); + DLIST_REMOVE(smb_sharing_violation_queue, pml); + free_queued_message(pml); + return; + } + } +} + +/**************************************************************************** + Move a sharing violation open retry message to the front of the list and + schedule it for immediate processing. +****************************************************************************/ + +void schedule_sharing_violation_open_smb_message(uint16 mid) +{ + struct pending_message_list *pml; + int i = 0; + + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + uint16 msg_mid = SVAL(pml->buf.data,smb_mid); + DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++, + (unsigned int)msg_mid )); + if (mid == msg_mid) { + DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n", + mid )); + pml->msg_time.tv_sec = 0; + pml->msg_time.tv_usec = 0; + DLIST_PROMOTE(smb_sharing_violation_queue, pml); + return; + } + } + + DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n", + mid )); +} + +/**************************************************************************** + Return true if this mid is on the deferred queue. +****************************************************************************/ + +BOOL open_was_deferred(uint16 mid) +{ + struct pending_message_list *pml; + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + if (SVAL(pml->buf.data,smb_mid) == mid) { + return True; + } + } + return False; +} + +/**************************************************************************** + Return the message queued by this mid. +****************************************************************************/ + +struct pending_message_list *get_open_deferred_message(uint16 mid) +{ + struct pending_message_list *pml; + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + if (SVAL(pml->buf.data,smb_mid) == mid) { + return pml; + } + } + return NULL; +} + +/**************************************************************************** + Function to push a sharing violation open smb message onto a linked list of local smb messages ready + for processing. +****************************************************************************/ + +BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, size_t priv_len) +{ + uint16 mid = SVAL(InBuffer,smb_mid); + struct timeval tv; + SMB_BIG_INT tdif; + + tv = *ptv; + tdif = tv.tv_sec; + tdif *= 1000000; + tdif += tv.tv_usec; + + /* Add on the timeout. */ + tdif += SHARING_VIOLATION_USEC_WAIT; + + tv.tv_sec = tdif / 1000000; + tv.tv_usec = tdif % 1000000; + + DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\ + timeout time [%u.%06u]\n", (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid, + (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec)); + + return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer, + smb_len(InBuffer)+4, &tv, private, priv_len); } /**************************************************************************** @@ -169,12 +304,17 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) fd_set fds; int selrtn; struct timeval to; + struct timeval *pto; int maxfd; smb_read_error = 0; again: + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; + pto = timeout > 0 ? &to : NULL; + /* * Note that this call must be before processing any SMB * messages as we need to synchronously process any messages @@ -188,17 +328,55 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ if(smb_oplock_queue != NULL) { struct pending_message_list *msg = smb_oplock_queue; - memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); + memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length)); /* Free the message we just copied. */ DLIST_REMOVE(smb_oplock_queue, msg); - SAFE_FREE(msg->msg_buf); - SAFE_FREE(msg); + free_queued_message(msg); DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); return True; } + /* + * Check to see if we already have a message on the deferred open queue + * and it's time to schedule. + */ + if(smb_sharing_violation_queue != NULL) { + BOOL pop_message = False; + struct pending_message_list *msg = smb_sharing_violation_queue; + + if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) { + pop_message = True; + } else { + struct timeval tv; + SMB_BIG_INT tdif; + + GetTimeOfDay(&tv); + tdif = usec_time_diff(&msg->msg_time, &tv); + if (tdif <= 0) { + /* Timed out. Schedule...*/ + pop_message = True; + DEBUG(10,("receive_message_or_smb: queued message timed out.\n")); + } else { + /* Make a more accurate select timeout. */ + to.tv_sec = tdif / 1000000; + to.tv_usec = tdif % 1000000; + pto = &to; + DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n", + (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec )); + } + } + + if (pop_message) { + memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length)); + + /* We leave this message on the queue so the open code can + know this is a retry. */ + DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n")); + return True; + } + } /* * Setup the select read fd set. @@ -229,10 +407,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) FD_SET(smbd_server_fd(),&fds); maxfd = setup_oplock_select_set(&fds); - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - - selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,timeout>0?&to:NULL); + selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto); /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fff5385171..bf208b0fa4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1043,6 +1043,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { END_PROFILE(SMBopen); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } @@ -1132,6 +1136,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (!fsp) { END_PROFILE(SMBopenX); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } @@ -1257,6 +1265,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { END_PROFILE(SMBcreate); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } @@ -1332,6 +1344,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!fsp) { END_PROFILE(SMBctemp); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } @@ -1623,8 +1639,13 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); status = unlink_internals(conn, dirtype, name); - if (!NT_STATUS_IS_OK(status)) + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return ERROR_NT(status); + } /* * Win2k needs a changenotify request response before it will @@ -3944,6 +3965,10 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = rename_internals(conn, name, newname, attrs, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return ERROR_NT(status); } @@ -3989,7 +4014,8 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, return(False); fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action); + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY, + &Access,&action); if (!fsp1) return(False); @@ -4002,7 +4028,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, ZERO_STRUCTP(&sbuf2); fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,dosattrs,0,&Access,&action); + ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action); if (!fsp2) { close_file(fsp1,False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 02a6bf6e4b..0ba26a9147 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -627,6 +627,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i oplock_request, &rmode,&smb_action); if (!fsp) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } @@ -3205,7 +3209,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, SET_OPEN_MODE(DOS_OPEN_RDWR), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, - 0, &access_mode, &action); + INTERNAL_OPEN_ONLY, &access_mode, &action); if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); @@ -3655,7 +3659,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", SET_OPEN_MODE(DOS_OPEN_RDWR), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, - 0, &access_mode, &action); + INTERNAL_OPEN_ONLY, &access_mode, &action); if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); -- cgit From effd4a33856bf315122df9e4fbbb241a161caa62 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jun 2004 22:13:59 +0000 Subject: r1089: Removed spurious oplock message in deferred open processing. Fix smb signing sequence counts. Jeremy. (This used to be commit 7e2a5c36614282b6bd50b60360f443549426dd4b) --- source3/smbd/open.c | 10 ++++++++++ source3/smbd/oplock.c | 2 +- source3/smbd/process.c | 10 ++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 04e074d56e..aca9756628 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -862,6 +862,16 @@ deferred open entry for mid %u, file %s\n", if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) { remove_sharing_violation_open_smb_message(mid); } + + /* + * Push the MID of this packet on the signing queue. + * We only do this once, the first time we push the packet + * onto the deferred open queue, as this has a side effect + * of incrementing the response sequence number. + */ + + srv_defer_sign_response(mid); + SAFE_FREE(de_array); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 6739f5654f..c34fa60954 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -410,7 +410,7 @@ pid %d, port %d, dev = %x, inode = %.0f, mid = %u\n", schedule_sharing_violation_open_smb_message(mid); } - break; + return True; /* * Keep this as a debug case - eventually we can remove it. diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 698c8475f7..05e4d0b1d9 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -121,9 +121,6 @@ static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct t DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg); } - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(buf,smb_mid)); - DEBUG(10,("push_message: pushed message length %u on queue %s\n", (unsigned int)msg_len, qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" )); @@ -138,7 +135,12 @@ static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct t BOOL push_oplock_pending_smb_message(char *buf, int msg_len) { - return push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0); + BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0); + if (ret) { + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(buf,smb_mid)); + } + return ret; } /**************************************************************************** -- cgit From b28d08cc14bd37c6263ed029a57f390687746bb9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jun 2004 00:43:43 +0000 Subject: r1093: Ensure we clear any cached errors on a deferred open call so we don't return the wrong error code on the next packet. Jeremy. (This used to be commit c1b06deb574d7b8e746bdf0d6f0eab16848a6cc1) --- source3/smbd/error.c | 11 +++++++++++ source3/smbd/nttrans.c | 2 ++ source3/smbd/reply.c | 6 ++++++ source3/smbd/trans2.c | 1 + 4 files changed, 20 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 9c81d465e7..d611e0ef87 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -28,6 +28,17 @@ NTSTATUS unix_ERR_ntstatus = NT_STATUS_OK; /* From lib/error.c */ extern struct unix_error_map unix_dos_nt_errmap[]; +/**************************************************************************** + Ensure we don't have any errors cached. +****************************************************************************/ + +void clear_cached_errors(void) +{ + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; +} + /**************************************************************************** Create an error packet from a cached error. ****************************************************************************/ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e540db234a..25ed08650a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -865,6 +865,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib END_PROFILE(SMBntcreateX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); @@ -1353,6 +1354,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o restore_case_semantics(conn, file_attributes); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bf208b0fa4..5b30fe5b75 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1045,6 +1045,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBopen); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1138,6 +1139,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt END_PROFILE(SMBopenX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1267,6 +1269,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBcreate); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1346,6 +1349,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBctemp); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1642,6 +1646,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return ERROR_NT(status); @@ -3967,6 +3972,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBmv); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return ERROR_NT(status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0ba26a9147..a399a12a66 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -629,6 +629,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i if (!fsp) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ + clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); -- cgit From 459cb00785c1eb71a1886c5960b5176e85c48d57 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jun 2004 21:03:50 +0000 Subject: r1097: Fix errno being incorrectly set. Noticed by Richard. Jeremy. (This used to be commit c8a55e92dd9622fa2a408b5a16f1adcf22253fc5) --- source3/smbd/open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aca9756628..330080353c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -244,6 +244,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); + errno = 0; return True; } -- cgit From fddef6fc201ed127eaac737e725d1c2dd8c6926e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jun 2004 17:54:23 +0000 Subject: r1115: Fix for #1427. Catch bad path errors at the right point. Ensure all our pathname parsing is consistent. Jeremy. (This used to be commit 5e8237e306f0bb0e492f10fb6487938132899384) --- source3/smbd/filename.c | 25 +++++++++-- source3/smbd/msdfs.c | 4 +- source3/smbd/nttrans.c | 42 +++++++++++++----- source3/smbd/reply.c | 114 +++++++++++++++++++++++++++++++++--------------- source3/smbd/trans2.c | 61 +++++++++++++++----------- source3/smbd/vfs.c | 9 ++++ 6 files changed, 177 insertions(+), 78 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 67329b51e6..ab75d9c06a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -237,6 +237,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ DEBUG(5,("Not a dir %s\n",start)); *end = '/'; + /* + * We need to return the fact that the intermediate + * name resolution failed. This is used to return an + * error of ERRbadpath rather than ERRbadfile. Some + * Windows applications depend on the difference between + * these two errors. + */ + errno = ENOTDIR; + *bad_path = True; return(False); } @@ -265,6 +274,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (end) pstrcpy(rest,end+1); + /* Reset errno so we can detect directory open errors. */ + errno = 0; + /* * Try to find this part of the path in the directory. */ @@ -292,6 +304,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(False); } + if (errno == ENOTDIR) { + *bad_path = True; + return(False); + } + /* * Just the last part of the name doesn't exist. * We may need to strupper() or strlower() it in case @@ -392,12 +409,11 @@ BOOL check_name(pstring name,connection_struct *conn) { BOOL ret = True; - errno = 0; - if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { DEBUG(5,("file path name %s vetoed\n",name)); + errno = ENOENT; return False; } } @@ -416,13 +432,15 @@ BOOL check_name(pstring name,connection_struct *conn) if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); + errno = EACCES; ret = False; } } #endif - if (!ret) + if (!ret) { DEBUG(5,("check_name on %s failed\n",name)); + } return(ret); } @@ -496,5 +514,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, } CloseDir(cur_dir); + errno = ENOENT; return(False); } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c66f0477a8..6c132897f9 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -65,7 +65,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + check_path_syntax(pdp->reqpath, p+1,True); DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -111,7 +111,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + check_path_syntax(pdp->reqpath, p+1,True); DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 25ed08650a..2f498b7c94 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -651,7 +651,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -693,14 +693,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib dir_name_len++; } - srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status,False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } pstrcat(fname, rel_fname); } else { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -762,7 +762,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib set_posix_case_semantics(conn, file_attributes); unix_convert(fname,conn,0,&bad_path,&sbuf); - + if (bad_path) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } + /* All file access must go through check_name() */ + if (!check_name(fname,conn)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + } + /* * If it's a request for a directory open, deal with it separately. */ @@ -1015,7 +1026,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1218,7 +1229,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_DOS(ERRDOS,ERRbadfid); if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1251,14 +1262,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o { pstring tmpname; - srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } pstrcat(fname, tmpname); } } else { - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1292,6 +1303,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } + /* All file access must go through check_name() */ + if (!check_name(fname,conn)) { + restore_case_semantics(conn, file_attributes); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + } /* * If it's a request for a directory open, deal with it separately. @@ -1523,7 +1543,7 @@ int reply_ntrename(connection_struct *conn, } p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1536,7 +1556,7 @@ int reply_ntrename(connection_struct *conn, } p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1640,7 +1660,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o fsp = file_fsp(params, 0); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); - srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5b30fe5b75..961f4d7f55 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -43,7 +43,7 @@ extern BOOL global_encrypted_passwords_negotiated; set. ****************************************************************************/ -NTSTATUS check_path_syntax(pstring destname, const pstring srcname) +NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names) { char *d = destname; const char *s = srcname; @@ -119,7 +119,21 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) s++; } else { if (!(*s & 0x80)) { - *d++ = *s++; + if (allow_wcard_names) { + *d++ = *s++; + } else { + switch (*s) { + case '*': + case '?': + case '<': + case '>': + case '"': + return NT_STATUS_OBJECT_NAME_INVALID; + default: + *d++ = *s++; + break; + } + } } else { switch(next_mb_char_size(s)) { case 4: @@ -147,7 +161,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) Pull a string and check the path - provide for error return. ****************************************************************************/ -size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err) +size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names) { pstring tmppath; char *tmppath_ptr = tmppath; @@ -161,7 +175,7 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } else { ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); } - *err = check_path_syntax(dest, tmppath); + *err = check_path_syntax(dest, tmppath, allow_wcard_names); return ret; } @@ -516,7 +530,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBchkpth); - srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBchkpth); return ERROR_NT(status); @@ -525,6 +539,10 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size RESOLVE_DFSPATH(name, conn, inbuf, outbuf); unix_convert(name,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBchkpth); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } mode = SVAL(inbuf,smb_vwv0); @@ -548,18 +566,11 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size * the parent directory is valid but not the * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND - * if the path is invalid. + * if the path is invalid. This is different from set_bad_path_error() + * in the non-NT error case. */ - if (bad_path) { - END_PROFILE(SMBchkpth); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } else { - END_PROFILE(SMBchkpth); - return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); - } - } else if (errno == ENOTDIR) { END_PROFILE(SMBchkpth); - return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY); + return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); } END_PROFILE(SMBchkpth); @@ -594,7 +605,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBgetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBgetatr); return ERROR_NT(status); @@ -613,6 +624,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ok = True; } else { unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBgetatr); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } if (check_name(fname,conn)) { if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); @@ -669,13 +684,17 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBsetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsetatr); return ERROR_NT(status); } unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBsetatr); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); @@ -798,7 +817,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status); + p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True); if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); return ERROR_NT(nt_status); @@ -976,7 +995,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(outbuf,1,0,True); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err); + p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True); if (!NT_STATUS_IS_OK(err)) { END_PROFILE(SMBfclose); return ERROR_NT(err); @@ -1028,7 +1047,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); return ERROR_NT(status); @@ -1037,6 +1056,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBopen); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), (uint32)dos_attr, oplock_request,&rmode,NULL); @@ -1122,7 +1145,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); return ERROR_NT(status); @@ -1131,6 +1154,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBopenX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr, oplock_request, &rmode,&smb_action); @@ -1240,7 +1267,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); createmode = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); return ERROR_NT(status); @@ -1249,6 +1276,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBcreate); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } if (createmode & aVOLID) DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); @@ -1312,7 +1343,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBctemp); createattr = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); return ERROR_NT(status); @@ -1326,6 +1357,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBctemp); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } tmpfd = smb_mkstemp(fname); if (tmpfd == -1) { @@ -1581,7 +1616,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) /* Quick check for "." and ".." */ if (fname[0] == '.') { if (!fname[1] || (fname[1] == '.' && !fname[2])) { - if ((dirtype & aDIR)) { + if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) { sys_direntry = True; } else { continue; @@ -1594,6 +1629,8 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (sys_direntry) { error = NT_STATUS_OBJECT_NAME_INVALID; + DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n", + fname, mask)); break; } @@ -1632,7 +1669,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dirtype = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBunlink); return ERROR_NT(status); @@ -3164,15 +3201,16 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) return NT_STATUS_OBJECT_NAME_INVALID; } + if (bad_path) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + if (check_name(directory, conn)) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret == -1) { if(errno == ENOENT) { - if (bad_path) - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - else - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } return map_nt_error_from_unix(errno); } @@ -3191,7 +3229,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBmkdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); return ERROR_NT(status); @@ -3361,7 +3399,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBrmdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); return ERROR_NT(status); @@ -3370,6 +3408,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) unix_convert(directory,conn, NULL,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBrmdir); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } if (check_name(directory,conn)) { dptr_closepath(directory,SVAL(inbuf,smb_pid)); @@ -3950,13 +3992,13 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBmv); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); } p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); @@ -4102,12 +4144,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, *directory = *mask = 0; p = smb_buf(inbuf); - p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); } - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); @@ -4267,7 +4309,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(pathworks_setdir); return ERROR_NT(status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a399a12a66..d69fe0700f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -607,7 +607,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i if (IS_IPC(conn)) return(ERROR_DOS(ERRSRV,ERRaccess)); - srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -618,6 +618,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i /* XXXX we need to handle passed times, sattr and flags */ unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } if (!check_name(fname,conn)) { return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); @@ -1376,7 +1379,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return(ERROR_DOS(ERRDOS,ERRunknownlevel)); } - srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus); + srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True); if (!NT_STATUS_IS_OK(ntstatus)) { return ERROR_NT(ntstatus); } @@ -1384,6 +1387,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); + if (bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } if(!check_name(directory,conn)) { return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } @@ -1569,7 +1575,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu *mask = *directory = *resume_name = 0; - srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus); + srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True); if (!NT_STATUS_IS_OK(ntstatus)) { return ERROR_NT(ntstatus); } @@ -2262,6 +2268,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + ZERO_STRUCT(sbuf); + if (tran_call == TRANSACT2_QFILEINFO) { if (total_params < 4) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); @@ -2277,11 +2285,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, */ pstrcpy(fname, fsp->fsp_name); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn)) { - DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); - } + /* We know this name is ok, it's already passed the checks. */ } else if(fsp && (fsp->is_directory || fsp->fd == -1)) { /* @@ -2289,12 +2293,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, * handle (returned from an NT SMB). NT5.0 seems * to do this call. JRA. */ + /* We know this name is ok, it's already passed the checks. */ pstrcpy(fname, fsp->fsp_name); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn)) { - DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); - } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ @@ -2302,7 +2302,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { + } else if (SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } @@ -2334,7 +2334,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -2342,6 +2342,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); @@ -2876,7 +2879,6 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam BOOL bad_path_oldname = False; BOOL bad_path_newname = False; SMB_STRUCT_STAT sbuf1, sbuf2; - BOOL rc, rcdest; pstring last_component_oldname; pstring last_component_newname; NTSTATUS status = NT_STATUS_OK; @@ -2889,8 +2891,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } - rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1); - if (!rc && bad_path_oldname) { + unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1); + if (bad_path_oldname) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } @@ -2910,8 +2912,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_ACCESS_DENIED; } - rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); - if (!rcdest && bad_path_newname) { + unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); + if (bad_path_newname) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } @@ -2979,6 +2981,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + ZERO_STRUCT(sbuf); + if (tran_call == TRANSACT2_SETFILEINFO) { if (total_params < 4) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); @@ -2993,8 +2997,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * to do this call. JRA. */ pstrcpy(fname, fsp->fsp_name); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { + if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } @@ -3032,11 +3035,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(ERROR_DOS(ERRDOS,ERRinvalidparam)); info_level = SVAL(params,0); - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } unix_convert(fname,conn,0,&bad_path,&sbuf); + if (bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } /* * For CIFS UNIX extensions the target name may not exist. @@ -3488,7 +3494,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", char *newname = fname; /* Set a hard link. */ - srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -3521,7 +3527,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", overwrite = (CVAL(pdata,0) ? True : False); root_fid = IVAL(pdata,4); len = IVAL(pdata,8); - srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); + srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -3701,7 +3707,7 @@ static int call_trans2mkdir(connection_struct *conn, if (total_params < 4) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); - srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -3709,6 +3715,9 @@ static int call_trans2mkdir(connection_struct *conn, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); unix_convert(directory,conn,0,&bad_path,&sbuf); + if (bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } if (check_name(directory,conn)) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 86f180e543..13cfdac0f3 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -829,6 +829,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) char *resolved_name = NULL; size_t con_path_len = strlen(conn->connectpath); char *p = NULL; + int saved_errno = errno; DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath)); @@ -842,6 +843,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) switch (errno) { case ENOTDIR: DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname)); + errno = saved_errno; return False; case ENOENT: { @@ -866,6 +868,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) #endif if (!resolved_name) { DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname)); + errno = saved_errno; return False; } pstrcpy(tmp_fname, resolved_name); @@ -876,6 +879,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) resolved_name = strdup(tmp_fname); if (!resolved_name) { DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname)); + errno = saved_errno; return False; } #else @@ -890,6 +894,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) } default: DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname)); + errno = saved_errno; return False; } } @@ -900,6 +905,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n")); if (free_resolved_name) SAFE_FREE(resolved_name); + errno = saved_errno; return False; } @@ -907,6 +913,7 @@ BOOL reduce_name(connection_struct *conn, pstring fname) DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname)); if (free_resolved_name) SAFE_FREE(resolved_name); + errno = EACCES; return False; } @@ -925,11 +932,13 @@ BOOL reduce_name(connection_struct *conn, pstring fname) DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",fname)); if (free_resolved_name) SAFE_FREE(resolved_name); + errno = EACCES; return False; } DEBUG(3,("reduce_name: %s reduced to %s\n", fname, p)); if (free_resolved_name) SAFE_FREE(resolved_name); + errno = saved_errno; return(True); } -- cgit From 58686e844f30e0c1712ec87d7f1b3e743d09be96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jun 2004 23:54:52 +0000 Subject: r1117: Doh ! Remember to turn off signing when sending a "break to level II" oplock message, or we mess up the signing sequence number.... Also improve sign error reporting. Also when deferring an open that had been deferred due to an oplock break, don't re-add the mid to the pending sign queue or we increment the sequence number twice and mess up signing again... I can now bounce between 2 WinXP/Win2003 boxes opening Excel spreadsheets with signing turned on and get correct "file in use" messages. Jeremy. (This used to be commit 1745ce4e2cf7fcb4c27c077973258d157cd241b1) --- source3/smbd/oplock.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c34fa60954..1ffc798b1f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -616,6 +616,8 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) */ if (global_client_caps & CAP_LEVEL_II_OPLOCKS) { + BOOL sign_state; + /* * If we are sending an oplock break due to an SMB sent * by our own client we ensure that we wait at leat @@ -627,10 +629,16 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) wait_before_sending_break(local_request); /* Prepare the SMBlockingX message. */ - prepare_break_message( outbuf, fsp, False); + + /* Save the server smb signing state. */ + sign_state = srv_oplock_set_signing(False); + if (!send_smb(smbd_server_fd(), outbuf)) exit_server("oplock_break_level2: send_smb failed."); + + /* Restore the sign state to what it was. */ + srv_oplock_set_signing(sign_state); } /* -- cgit From 3542b99cf1408b075353efe1cbfb30569104dfba Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 13 Jun 2004 23:13:22 +0000 Subject: r1122: As spotted by lha@stacken.kth.se we don't actually use this variable any more. Andrew Bartlett (This used to be commit 9d5821d5ee5e9f666dfbe75419e97508af9cad5e) --- source3/smbd/sesssetup.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8a56478929..49acd371a5 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -152,7 +152,6 @@ static int reply_spnego_kerberos(connection_struct *conn, auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob(NULL, 0); uint8 tok_id[2]; - BOOL foreign = False; DATA_BLOB nullblob = data_blob(NULL, 0); fstring real_username; @@ -197,7 +196,6 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - foreign = True; } /* this gives a fully qualified user name (ie. with full realm). -- cgit From 2acd0848663f28afedff9b11b738e048f5ead2cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Jun 2004 18:36:45 +0000 Subject: r1154: Change default setting for case sensitivity to "auto". If set to auto then is the client supports it (current clients supported are Samba and CIFSVFS - detected by the negprot strings "Samba", "POSIX 2" and a bare "NT LM 0.12" string) then the setting of the per packet flag smb_flag FLAG_CASELESS_PATHNAMES is taken into account per packet. This allows the linux CIFS client to use Samba in a case sensitive manner. Additional command in smbclient "case_sensitive", toggles the flag in subsequent packets. Docs to follow. Jeremy. (This used to be commit cf84c0fe1a061acc0313f7db124b8f947cdf623d) --- source3/smbd/blocking.c | 2 +- source3/smbd/conn.c | 2 +- source3/smbd/negprot.c | 19 ++++++++++++++++--- source3/smbd/notify_hash.c | 2 +- source3/smbd/process.c | 2 +- source3/smbd/server.c | 10 ++++------ source3/smbd/service.c | 27 ++++++++++++++++++++++++--- 7 files changed, 48 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index c0512d5539..3983a4cbdf 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -680,7 +680,7 @@ void process_blocking_lock_queue(time_t t) continue; } - if(!set_current_service(conn,True)) { + if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); /* * Remove the entry and return an error to the client. diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index e083e14426..34e19a3ca6 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -161,7 +161,7 @@ void conn_close_all(void) connection_struct *conn, *next; for (conn=Connections;conn;conn=next) { next=conn->next; - set_current_service(conn, True); + set_current_service(conn, 0, True); close_cnum(conn, conn->vuid); } } diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 1843c174bb..5ff53f6300 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -401,8 +401,9 @@ protocol [LANMAN2.1] #define ARCH_WIN2K 0xC /* Win2K is like NT */ #define ARCH_OS2 0x14 /* Again OS/2 is like NT */ #define ARCH_SAMBA 0x20 +#define ARCH_CIFSFS 0x40 -#define ARCH_ALL 0x3F +#define ARCH_ALL 0x7F /* List of supported protocols, most desired first */ static const struct { @@ -413,6 +414,7 @@ static const struct { } supported_protocols[] = { {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, + {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1}, {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, @@ -460,7 +462,7 @@ int reply_negprot(connection_struct *conn, else if (strcsequal(p,"DOS LANMAN2.1")) arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(p,"NT LM 0.12")) - arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); + arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS); else if (strcsequal(p,"LANMAN2.1")) arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(p,"LM1.2X002")) @@ -472,12 +474,23 @@ int reply_negprot(connection_struct *conn, else if (strcsequal(p,"Samba")) { arch = ARCH_SAMBA; break; + } else if (strcsequal(p,"POSIX 2")) { + arch = ARCH_CIFSFS; + break; } p += strlen(p) + 2; } - + + /* CIFSFS can send one arch only, NT LM 0.12. */ + if (Index == 1 && (arch & ARCH_CIFSFS)) { + arch = ARCH_CIFSFS; + } + switch ( arch ) { + case ARCH_CIFSFS: + set_remote_arch(RA_CIFSFS); + break; case ARCH_SAMBA: set_remote_arch(RA_SAMBA); break; diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index ec414454f9..843580f6ed 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -164,7 +164,7 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, if (!change_to_user(conn,vuid)) return True; - if (!set_current_service(conn,True)) { + if (!set_current_service(conn,FLAG_CASELESS_PATHNAMES,True)) { change_to_root_user(); return True; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 05e4d0b1d9..72a604811b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -934,7 +934,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(ERROR_DOS(ERRSRV,ERRaccess)); /* load service specific parameters */ - if (conn && !set_current_service(conn,(flags & (AS_USER|DO_CHDIR)?True:False))) + if (conn && !set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) return(ERROR_DOS(ERRSRV,ERRaccess)); /* does this protocol need to be run as guest? */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 343a835be8..c3e0da542e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -494,18 +494,16 @@ BOOL reload_services(BOOL test) load_interfaces(); - { - if (smbd_server_fd() != -1) { - set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), user_socket_options); - } + if (smbd_server_fd() != -1) { + set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); + set_socket_options(smbd_server_fd(), user_socket_options); } mangle_reset_cache(); reset_stat_cache(); /* this forces service parameters to be flushed */ - set_current_service(NULL,True); + set_current_service(NULL,0,True); return(ret); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 192a043bf5..3b499d5cc1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -28,10 +28,11 @@ extern userdom_struct current_user_info; Load parameters specific to a connection/service. ****************************************************************************/ -BOOL set_current_service(connection_struct *conn,BOOL do_chdir) +BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir) { extern char magic_char; static connection_struct *last_conn; + static uint16 last_flags; int snum; if (!conn) { @@ -51,10 +52,24 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) return(False); } - if (conn == last_conn) + if ((conn == last_conn) && (last_flags == flags)) { return(True); + } last_conn = conn; + last_flags = flags; + + /* Obey the client case sensitivity requests - only for clients that support it. */ + if (lp_casesensitive(snum) == Auto) { + /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */ + enum remote_arch_types ra_type = get_remote_arch(); + if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { + /* Client can't support per-packet case sensitive pathnames. */ + conn->case_sensitive = False; + } else { + conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES); + } + } magic_char = lp_magicchar(snum); return(True); @@ -347,7 +362,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->dirptr = NULL; /* Case options for the share. */ - conn->case_sensitive = lp_casesensitive(snum); + if (lp_casesensitive(snum) == Auto) { + /* We will be setting this per packet. Set to be case insensitive for now. */ + conn->case_sensitive = False; + } else { + conn->case_sensitive = (BOOL)lp_casesensitive(snum); + } + conn->case_preserve = lp_preservecase(snum); conn->short_case_preserve = lp_shortpreservecase(snum); -- cgit From 073c542c5135d78f0ff5755ed62daf230292cec0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Jun 2004 21:33:21 +0000 Subject: r1255: Ensure we check attributes correctly on rename request. Gets us further with Samba4 RAW-RENAME test. Jeremy. (This used to be commit f17382ad8ad7211bbd34c823d88936a83dceb940) --- source3/smbd/reply.c | 17 +++++++++++------ source3/smbd/trans2.c | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 961f4d7f55..6c20b97c4e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1428,15 +1428,20 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Check if a user is allowed to rename a file. ********************************************************************/ -static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst) +static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst) { int smb_action; int access_mode; files_struct *fsp; + uint16 fmode; if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - + + fmode = dos_mode(conn,fname,pst); + if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) + return NT_STATUS_NO_SUCH_FILE; + if (S_ISDIR(pst->st_mode)) return NT_STATUS_OK; @@ -3543,7 +3548,7 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T Rename an open file - given an fsp. ****************************************************************************/ -NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists) +NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists) { SMB_STRUCT_STAT sbuf; BOOL bad_path = False; @@ -3624,7 +3629,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * return NT_STATUS_OBJECT_NAME_COLLISION; } - error = can_rename(newname,conn,&sbuf); + error = can_rename(newname,conn,attrs,&sbuf); if (dest_exists && !NT_STATUS_IS_OK(error)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", @@ -3830,7 +3835,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - error = can_rename(directory,conn,&sbuf1); + error = can_rename(directory,conn,attrs,&sbuf1); if (!NT_STATUS_IS_OK(error)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", @@ -3921,7 +3926,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error))); continue; } - error = can_rename(fname,conn,&sbuf1); + error = can_rename(fname,conn,attrs,&sbuf1); if (!NT_STATUS_IS_OK(error)) { DEBUG(6,("rename %s refused\n", fname)); continue; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d69fe0700f..a7db9daf7d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3550,7 +3550,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (fsp) { DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", fsp->fnum, fsp->fsp_name, base_name )); - status = rename_internals_fsp(conn, fsp, base_name, overwrite); + status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite); } else { DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, newname )); -- cgit From efd2a065947547c46d0d62fb7fe1114935613311 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Jun 2004 22:37:50 +0000 Subject: r1257: Ensure we deferr a sharing violation on rename correctly. Jeremy. (This used to be commit b52a04a5cdcea83c99805181241c8c0760bcc22e) --- source3/smbd/nttrans.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2f498b7c94..3e5b07b887 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1555,8 +1555,13 @@ int reply_ntrename(connection_struct *conn, return ERROR_NT(NT_STATUS_ACCESS_DENIED); } + if (ms_has_wild(oldname)) { + END_PROFILE(SMBntrename); + return ERROR_NT(NT_STATUS_OBJECT_PATH_SYNTAX_BAD); + } + p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1575,6 +1580,11 @@ int reply_ntrename(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + clear_cached_errors(); + return -1; + } return ERROR_NT(status); } -- cgit From e13ba6ebd51c1a34fab07368bc45fa165eaa6b95 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Jun 2004 23:48:23 +0000 Subject: r1259: Ensure we pass Samba4 RAW-RENAME test. Jeremy. (This used to be commit 756a00431105cf6349feb80a46b6f55a30eb3973) --- source3/smbd/nttrans.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 165 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3e5b07b887..f717efac63 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1520,6 +1520,155 @@ int reply_ntcancel(connection_struct *conn, return(-1); } +/**************************************************************************** + Copy a file. +****************************************************************************/ + +static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint16 attrs) +{ + BOOL bad_path_oldname = False; + BOOL bad_path_newname = False; + SMB_STRUCT_STAT sbuf1, sbuf2; + pstring last_component_oldname; + pstring last_component_newname; + files_struct *fsp1,*fsp2; + uint16 fmode; + int access_mode; + int smb_action; + SMB_OFF_T ret=-1; + int close_ret; + NTSTATUS status = NT_STATUS_OK; + + ZERO_STRUCT(sbuf1); + ZERO_STRUCT(sbuf2); + + /* No wildcards. */ + if (ms_has_wild(newname) || ms_has_wild(oldname)) { + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + if (!CAN_WRITE(conn)) + return NT_STATUS_MEDIA_WRITE_PROTECTED; + + unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1); + if (bad_path_oldname) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* Quick check for "." and ".." */ + if (last_component_oldname[0] == '.') { + if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + /* Source must already exist. */ + if (!VALID_STAT(sbuf1)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + if (!check_name(oldname,conn)) { + return NT_STATUS_ACCESS_DENIED; + } + + /* Ensure attributes match. */ + fmode = dos_mode(conn,oldname,&sbuf1); + if ((fmode & ~attrs) & (aHIDDEN | aSYSTEM)) + return NT_STATUS_NO_SUCH_FILE; + + unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); + if (bad_path_newname) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* Quick check for "." and ".." */ + if (last_component_newname[0] == '.') { + if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + /* Disallow if newname already exists. */ + if (VALID_STAT(sbuf2)) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + if (!check_name(newname,conn)) { + return NT_STATUS_ACCESS_DENIED; + } + + /* No links from a directory. */ + if (S_ISDIR(sbuf1.st_mode)) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + + /* Ensure this is within the share. */ + if (!reduce_name(conn, oldname) != 0) { + return NT_STATUS_ACCESS_DENIED; + } + + DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); + + fsp1 = open_file_shared1(conn,oldname,&sbuf1,FILE_READ_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0, + &access_mode,&smb_action); + + if (!fsp1) { + status = NT_STATUS_ACCESS_DENIED; + if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) + status = NT_STATUS_SHARING_VIOLATION; + unix_ERR_class = 0; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; + return status; + } + + fsp2 = open_file_shared1(conn,newname,&sbuf2,FILE_WRITE_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL),fmode,INTERNAL_OPEN_ONLY, + &access_mode,&smb_action); + + if (!fsp2) { + status = NT_STATUS_ACCESS_DENIED; + if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) + status = NT_STATUS_SHARING_VIOLATION; + unix_ERR_class = 0; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; + close_file(fsp1,False); + return status; + } + + if (sbuf1.st_size) + ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size); + + /* + * As we are opening fsp1 read-only we only expect + * an error on close on fsp2 if we are out of space. + * Thus we don't look at the error return from the + * close of fsp1. + */ + close_file(fsp1,False); + + /* Ensure the modtime is set correctly on the destination file. */ + fsp2->pending_modtime = sbuf1.st_mtime; + + close_ret = close_file(fsp2,False); + + /* Grrr. We have to do this as open_file_shared1 adds aARCH when it + creates the file. This isn't the correct thing to do in the copy case. JRA */ + file_set_dosmode(conn, newname, fmode, &sbuf2); + + if (ret < (SMB_OFF_T)sbuf1.st_size) { + return NT_STATUS_DISK_FULL; + } + + if (close_ret != 0) { + status = map_nt_error_from_unix(close_ret); + DEBUG(3,("copy_internals: Error %s copy file %s to %s\n", + nt_errstr(status), oldname, newname)); + } + return status; +} + /**************************************************************************** Reply to a NT rename request. ****************************************************************************/ @@ -1537,11 +1686,6 @@ int reply_ntrename(connection_struct *conn, START_PROFILE(SMBntrename); - if ((rename_type != RENAME_FLAG_RENAME) && (rename_type != RENAME_FLAG_HARD_LINK)) { - END_PROFILE(SMBntrename); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } - p = smb_buf(inbuf) + 1; p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, True); if (!NT_STATUS_IS_OK(status)) { @@ -1572,10 +1716,22 @@ int reply_ntrename(connection_struct *conn, DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); - if (rename_type == RENAME_FLAG_RENAME) { - status = rename_internals(conn, oldname, newname, attrs, False); - } else { - status = hardlink_internals(conn, oldname, newname); + switch(rename_type) { + case RENAME_FLAG_RENAME: + status = rename_internals(conn, oldname, newname, attrs, False); + break; + case RENAME_FLAG_HARD_LINK: + status = hardlink_internals(conn, oldname, newname); + break; + case RENAME_FLAG_COPY: + status = copy_internals(conn, oldname, newname, attrs); + break; + case RENAME_FLAG_MOVE_CLUSTER_INFORMATION: + status = NT_STATUS_INVALID_PARAMETER; + break; + default: + status = NT_STATUS_ACCESS_DENIED; /* Default error. */ + break; } if (!NT_STATUS_IS_OK(status)) { -- cgit From 7f05a7d0c85fd3deaf5e3e263cf8b0f05d4a7f01 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 Jun 2004 00:47:58 +0000 Subject: r1260: Added new parameter in the protocol section. "defer sharing violations", by default set to "yes" (to correctly emulate Windows). I've added this to ensure if we find a critical problem with this new code when 3.0.5 ships it can be turned off to test for bugs. Jeremy. (This used to be commit bee0619cc476335e19a5f76179832802587563d1) --- source3/smbd/open.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 330080353c..119eb04e09 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -786,6 +786,10 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T deferred_open_entry *de_array = NULL; int num_de_entries, i; + if (!lp_defer_sharing_violations(SNUM(conn))) { + return; + } + num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); for (i = 0; i < num_de_entries; i++) { deferred_open_entry *entry = &de_array[i]; @@ -814,6 +818,10 @@ void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, int num_de_entries, i; struct dev_inode_bundle dib; + if (!lp_defer_sharing_violations(SNUM(conn))) { + return; + } + dib.dev = dev; dib.inode = inode; -- cgit From 3e0f586298125bbda80b8edcced49d5bbb424b0d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 Jun 2004 01:04:02 +0000 Subject: r1263: Make "defer sharing violations" a global parameter. Jeremy. (This used to be commit 42cdeccc36dc5f4bd133b84d4eaeb76f42f8043b) --- source3/smbd/close.c | 4 ++++ source3/smbd/open.c | 4 ++-- source3/smbd/process.c | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 305377dfc6..6de2774644 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -115,6 +115,10 @@ static void notify_deferred_opens(files_struct *fsp) int num_de_entries, i; pid_t mypid = sys_getpid(); + if (!lp_defer_sharing_violations()) { + return; + } + num_de_entries = get_deferred_opens(fsp->conn, fsp->dev, fsp->inode, &de_array); for (i = 0; i < num_de_entries; i++) { deferred_open_entry *entry = &de_array[i]; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 119eb04e09..d38d94e5aa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -786,7 +786,7 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T deferred_open_entry *de_array = NULL; int num_de_entries, i; - if (!lp_defer_sharing_violations(SNUM(conn))) { + if (!lp_defer_sharing_violations()) { return; } @@ -818,7 +818,7 @@ void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, int num_de_entries, i; struct dev_inode_bundle dib; - if (!lp_defer_sharing_violations(SNUM(conn))) { + if (!lp_defer_sharing_violations()) { return; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 72a604811b..60ce1499e8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -151,6 +151,10 @@ void remove_sharing_violation_open_smb_message(uint16 mid) { struct pending_message_list *pml; + if (!lp_defer_sharing_violations()) { + return; + } + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n", @@ -172,6 +176,10 @@ void schedule_sharing_violation_open_smb_message(uint16 mid) struct pending_message_list *pml; int i = 0; + if (!lp_defer_sharing_violations()) { + return; + } + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { uint16 msg_mid = SVAL(pml->buf.data,smb_mid); DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++, @@ -197,6 +205,11 @@ void schedule_sharing_violation_open_smb_message(uint16 mid) BOOL open_was_deferred(uint16 mid) { struct pending_message_list *pml; + + if (!lp_defer_sharing_violations()) { + return False; + } + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { return True; @@ -212,6 +225,11 @@ BOOL open_was_deferred(uint16 mid) struct pending_message_list *get_open_deferred_message(uint16 mid) { struct pending_message_list *pml; + + if (!lp_defer_sharing_violations()) { + return NULL; + } + for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { return pml; @@ -231,6 +249,10 @@ BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, struct timeval tv; SMB_BIG_INT tdif; + if (!lp_defer_sharing_violations()) { + return True; + } + tv = *ptv; tdif = tv.tv_sec; tdif *= 1000000; -- cgit From b04c782281bcb6a9b13168dacdae59898dd9fe7f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Jun 2004 20:41:29 +0000 Subject: r1301: Fix bogus error message when using "mangling method = hash" rather than hash2. We are already calculating lengths so just use memcpy not safe_strcpy(). Jeremy. (This used to be commit a5a3df78531dc5400088e1746d6a7cd29f56a714) --- source3/smbd/mangle_hash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 7b8cbdbddb..d7239b82a7 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -546,8 +546,10 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) /* Fill the new cache entry, and add it to the cache. */ s1 = (char *)(new_entry + 1); s2 = (char *)&(s1[mangled_len + 1]); - safe_strcpy( s1, mangled_name, mangled_len ); - safe_strcpy( s2, raw_name, raw_len ); + memcpy( s1, mangled_name, mangled_len ); + s1[mangled_len] = '\0'; + memcpy( s2, raw_name, raw_len ); + s2[raw_len] = '\0'; ubi_cachePut( mangled_cache, i, new_entry, s1 ); } -- cgit From 57c07e27853442e95e19c7f746ef1f4681bda48a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Jun 2004 01:35:01 +0000 Subject: r1304: Turns out non-io opens that cause oplock breaks are a *different* set of desired access flags from those that cause sharing violations. Oplock breaks are caused by : ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES) Sharing violations are caused by : ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES) We now pass the torture rename test again. I still need to work out if subsequent opens will cause sharing violations with an existing open mode of SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES; Jeremy. (This used to be commit 38002bfc1c0981a2dba3f2319624c1ef055a3648) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d38d94e5aa..65500c65ce 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -381,13 +381,13 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i if(!lp_share_modes(SNUM(conn))) return True; - if (desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + if (desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { non_io_open_request = False; } else { non_io_open_request = True; } - if (share->desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + if (share->desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { non_io_open_existing = False; } else { non_io_open_existing = True; -- cgit From a003d0e5d258572aa135ccbbc91882df68c1b51b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Jun 2004 23:00:40 +0000 Subject: r1311: Turn on sendfile for non-oplocked files. tridge proved this is the correct thing to do on a train in Germany :-). Turn on sendfile by default ! It's about time..... Jeremy. (This used to be commit ec614a8f7d158b57f5981c1515962aca3c3e6ef4) --- source3/smbd/reply.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6c20b97c4e..71efb793af 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1729,12 +1729,13 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st #if defined(WITH_SENDFILE) /* - * We can only use sendfile on a non-chained packet and on a file - * that is exclusively oplocked. reply_readbraw has already checked the length. + * We can only use sendfile on a non-chained packet + * but we can use on a non-oplocked file. tridge proved this + * on a train in Germany :-). JRA. + * reply_readbraw has already checked the length. */ - if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && - EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) { + if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) { DATA_BLOB header; _smb_setlen(outbuf,nread); @@ -2067,12 +2068,13 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length #if defined(WITH_SENDFILE) /* - * We can only use sendfile on a non-chained packet and on a file - * that is exclusively oplocked. + * We can only use sendfile on a non-chained packet + * but we can use on a non-oplocked file. tridge proved this + * on a train in Germany :-). JRA. */ - if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && - lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) { + if ((CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && + (lp_write_cache_size(SNUM(conn)) == 0) ) { SMB_STRUCT_STAT sbuf; DATA_BLOB header; -- cgit From aa9be75d8a836106037389cb3d774d38d1397ea5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Jul 2004 14:49:44 +0000 Subject: r1314: Restore the 2.2 'force unknown acl user' parameter. When getting a security descriptor for a file, if the owner sid is not known, the owner uid is set to the current uid. Same for group sid. This makes xcopy /o possible for files that are owned by local users/groups (local administrators for example). Thanks to Guenther for his persistence :-) Volker (This used to be commit 80e57d27909a9a1edad962e3f43c2178d2da2a92) --- source3/smbd/posix_acls.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 584164e930..2d9591e6ba 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -880,7 +880,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ -static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) { DOM_SID owner_sid; DOM_SID grp_sid; @@ -910,15 +910,17 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) { -#if ACL_FORCE_UNMAPPABLE - /* this allows take ownership to work reasonably */ - extern struct current_user current_user; - *puser = current_user.uid; -#else - DEBUG(3,("unpack_nt_owners: unable to validate owner sid for %s\n", - sid_string_static(&owner_sid))); - return False; -#endif + if (lp_force_unknown_acl_user(snum)) { + /* this allows take ownership to work + * reasonably */ + extern struct current_user current_user; + *puser = current_user.uid; + } else { + DEBUG(3,("unpack_nt_owners: unable to validate" + " owner sid for %s\n", + sid_string_static(&owner_sid))); + return False; + } } } @@ -930,14 +932,16 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) { -#if ACL_FORCE_UNMAPPABLE - /* this allows take group ownership to work reasonably */ - extern struct current_user current_user; - *pgrp = current_user.gid; -#else - DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n")); - return False; -#endif + if (lp_force_unknown_acl_user(snum)) { + /* this allows take group ownership to work + * reasonably */ + extern struct current_user current_user; + *pgrp = current_user.gid; + } else { + DEBUG(3,("unpack_nt_owners: unable to validate" + " group sid.\n")); + return False; + } } } @@ -3005,7 +3009,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( &sbuf, &user, &grp, security_info_sent, psd)) + if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) return False; /* -- cgit From c531f726c4431dc7bdeaf53864bfe30347e426f1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Jul 2004 22:55:38 +0000 Subject: r1325: Always use GetTimeOfDay() (wrapper). Ensure ldap replication sleep time is not more than 5 seconds. Should fix issue reported by Chris Garrigues . Jeremy. (This used to be commit fbc06831d3a7e8645409158ee1ae1f9f192913a7) --- source3/smbd/utmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index a521d0113d..b1735dfcc4 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -514,10 +514,10 @@ static BOOL sys_utmp_fill(struct utmp *u, * But note that we do the more precise ut_tv as the final assignment. */ #if defined(HAVE_UT_UT_TIME) - gettimeofday(&timeval, NULL); + GetTimeOfDay(&timeval); u->ut_time = timeval.tv_sec; #elif defined(HAVE_UT_UT_TV) - gettimeofday(&timeval, NULL); + GetTimeOfDay(&timeval); u->ut_tv = timeval; #else #error "with-utmp must have UT_TIME or UT_TV" -- cgit From 7b4151e173323e6ebc05a7ccc1671ab88f4e1660 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Sat, 3 Jul 2004 23:53:36 +0000 Subject: r1333: NFS Quota support from Dan Peterson. (This used to be commit 609828444d9126d8a6e8ff43e4b3c19079a9eb56) --- source3/smbd/quotas.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 203 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index e439c1e571..3c4d4319f6 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -933,6 +933,176 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #include #endif +#if defined(__FreeBSD__) + +#include +#include +#include +#include +#include + +static int quotastat; + +static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) +{ + if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN )) + return(0); + if (!xdr_int(xdrsp, &args->gqa_uid)) + return(0); + return (1); +} + +static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) +{ + if (!xdr_int(xdrsp, "astat)) { + DEBUG(6,("nfs_quotas: Status bad or zero\n")); + return 0; + } + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { + DEBUG(6,("nfs_quotas: Block size bad or zero\n")); + return 0; + } + if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) { + DEBUG(6,("nfs_quotas: Active bad or zero\n")); + return 0; + } + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { + DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); + return 0; + } + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { + DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); + return 0; + } + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { + DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); + return 0; + } + return (1); +} + +/* Works on FreeBSD, too. :-) */ +static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + uid_t uid = euser_id; + struct dqblk D; + char *mnttype = nfspath; + CLIENT *clnt; + struct getquota_rslt gqr; + struct getquota_args args; + char *cutstr, *pathname, *host, *testpath; + int len; + static struct timeval timeout = {2,0}; + enum clnt_stat clnt_stat; + BOOL ret = True; + + *bsize = *dfree = *dsize = (SMB_BIG_UINT)0; + + len=strcspn(mnttype, ":"); + pathname=strstr(mnttype, ":"); + cutstr = (char *) malloc(len+1); + if (!cutstr) + return False; + + memset(cutstr, '\0', len+1); + host = strncat(cutstr,mnttype, sizeof(char) * len ); + DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); + DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); + testpath=strchr_m(mnttype, ':'); + args.gqa_pathp = testpath+1; + args.gqa_uid = uid; + + DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp")); + + if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) { + ret = False; + goto out; + } + + clnt->cl_auth = authunix_create_default(); + DEBUG(9,("nfs_quotas: auth_success\n")); + + clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, (const xdrproc_t) my_xdr_getquota_args, (caddr_t)&args, (const xdrproc_t) my_xdr_getquota_rslt, (caddr_t)&gqr, timeout); + + if (clnt_stat != RPC_SUCCESS) { + DEBUG(9,("nfs_quotas: clnt_call fail\n")); + ret = False; + goto out; + } + + /* + * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is + * no quota set, and 3 if no permission to get the quota. If 0 or 3 return + * something sensible. + */ + + switch ( quotastat ) { + case 0: + DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); + ret = False; + goto out; + + case 1: + DEBUG(9,("nfs_quotas: Good quota data\n")); + D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; + D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; + D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; + break; + + case 2: + case 3: + D.dqb_bsoftlimit = 1; + D.dqb_curblocks = 1; + DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat )); + break; + + default: + DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat )); + break; + } + + DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", + quotastat, + gqr.getquota_rslt_u.gqr_rquota.rq_bsize, + gqr.getquota_rslt_u.gqr_rquota.rq_active, + gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit, + gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit, + gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)); + + if (D.dqb_bsoftlimit == 0) + D.dqb_bsoftlimit = D.dqb_bhardlimit; + if (D.dqb_bsoftlimit == 0) + return False; + + *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize; + *dsize = D.dqb_bsoftlimit; + + if (D.dqb_curblocks == D.dqb_curblocks == 1) + *bsize = DEV_BSIZE; + + if (D.dqb_curblocks > D.dqb_bsoftlimit) { + *dfree = 0; + *dsize = D.dqb_curblocks; + } else + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + + out: + + if (clnt) { + if (clnt->cl_auth) + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + } + + DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize)); + + SAFE_FREE(cutstr); + DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); + return ret; +} + +#endif + /**************************************************************************** try to get the disk space from disk quotas - default version ****************************************************************************/ @@ -976,10 +1146,42 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB { /* FreeBSD patches from Marty Moll */ gid_t egrp_id; - +#if defined(__FreeBSD__) + SMB_DEV_T devno; + struct statfs *mnts; + SMB_STRUCT_STAT st; + int mntsize, i; + + if (sys_stat(path,&st) < 0) + return False; + devno = st.st_dev; + + mntsize = getmntinfo(&mnts,MNT_NOWAIT); + if (mntsize <= 0) + return False; + + for (i = 0; i < mntsize; i++) { + if (sys_stat(mnts[i].f_mntonname,&st) < 0) + return False; + if (st.st_dev == devno) + break; + } + if (i == mntsize) + return False; +#endif + save_re_uid(); set_effective_uid(0); +#if defined(__FreeBSD__) + if (strcmp(mnts[i].f_fstypename,"nfs") == 0) { + BOOL retval; + retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize); + restore_re_uid(); + return retval; + } +#endif + egrp_id = getegid(); r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); -- cgit From 600e904aa1ddf620df2ed6e5a02d0fe00e627dbb Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 6 Jul 2004 21:43:12 +0000 Subject: r1370: BUG 1297 - prevent map_username() from being called twice during logon (This used to be commit e1364ff774b62f46c0f50864695da49972352126) --- source3/smbd/sesssetup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 49acd371a5..0122b662eb 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -242,6 +242,8 @@ static int reply_spnego_kerberos(connection_struct *conn, /* lookup the passwd struct, create a new user if necessary */ + map_username( user ); + pw = smb_getpwnam( user, real_username, True ); if (!pw) { -- cgit From 5aadb88b537e8beb994b9c7e063b1725d41fad8f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 Jul 2004 13:13:15 +0000 Subject: r1375: When setting writable=yes in smb.conf and only allow read access in the security descriptor, allow read access. The code failed in this case. Jeremy, could you please cross-check this? The way I understood your code it could only work if smb.conf and secdesc said the same. This made the use of srvmgr a bit difficult.... What was your intention on how to use the share_info.tdb? The current code might check the secdesc twice, but I don't see any decent way around it that does not completely clutter the code. Volker (This used to be commit 7c673bd910e1fcbbf07198f38ceddd81e9064c11) --- source3/smbd/uid.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index e1864c74ca..de2f96450f 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -125,6 +125,13 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) readonly_share = is_share_read_only_for_user(conn, vuser); + if (!readonly_share && + !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) { + /* smb.conf allows r/w, but the security descriptor denies + * write. Fall back to looking at readonly. */ + readonly_share = True; + } + if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { return False; } -- cgit From 1c5867502a47371e24519ffeb4165c69cab63482 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Jul 2004 22:46:51 +0000 Subject: r1388: Adding password history code for ldap backend, based on a patch from "Jianliang Lu" . Multi-string attribute changed to linearised pstring due to ordering issues. A few other changes to fix race conditions. I will add the tdb backend code next. This code compiles but has not yet been tested with password history policy set to greater than zero. Targeted for 3.0.6. Jeremy. (This used to be commit dd54b2a3c45e202e504ad69d170eb798da4e6fc9) --- source3/smbd/chgpasswd.c | 85 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index ca13a167fb..a1b90c8fed 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -932,6 +932,65 @@ static NTSTATUS check_oem_password(const char *user, return NT_STATUS_WRONG_PASSWORD; } +/*********************************************************** + This routine takes the given password and checks it against + the password history. Returns True if this password has been + found in the history list. +************************************************************/ + +static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) +{ + uchar new_nt_p16[NT_HASH_LEN]; + uchar zero_nt_pw[NT_HASH_LEN]; + const uint8 *nt_pw; + const uint8 *pwhistory; + BOOL found = False; + int i, pwHisLen, curr_pwHisLen; + + account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); + if (pwHisLen == 0) { + return False; + } + + pwhistory = pdb_get_pw_history(sampass, &curr_pwHisLen); + if (!pwhistory || curr_pwHisLen == 0) { + return False; + } + + /* Only examine the minimum of the current history len and + the stored history len. Avoids race conditions. */ + pwHisLen = MIN(pwHisLen,curr_pwHisLen); + + nt_pw = pdb_get_nt_passwd(sampass); + + E_md4hash(plaintext, new_nt_p16); + + if (!memcmp(nt_pw, new_nt_p16, NT_HASH_LEN)) { + DEBUG(10,("check_passwd_history: proposed new password for user %s is the same as the current password !\n", + pdb_get_username(sampass) )); + return True; + } + + dump_data(100, new_nt_p16, NT_HASH_LEN); + dump_data(100, pwhistory, NT_HASH_LEN*pwHisLen); + + memset(zero_nt_pw, '\0', NT_HASH_LEN); + for (i=0; i Date: Fri, 9 Jul 2004 00:13:55 +0000 Subject: r1414: Memory leak fixes found by valgrind whilst checking the password history code. Error code paths were not freeing up some memory. Jeremy. (This used to be commit 7c4666e56c2c281e023c6483459cb9e8d4787d36) --- source3/smbd/service.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 3b499d5cc1..794b5332ac 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -823,8 +823,12 @@ void close_cnum(connection_struct *conn, uint16 vuid) { DirCacheFlush(SNUM(conn)); - file_close_conn(conn); - dptr_closecnum(conn); + if (IS_IPC(conn)) { + pipe_close_conn(conn); + } else { + file_close_conn(conn); + dptr_closecnum(conn); + } change_to_root_user(); -- cgit From f9e72f1a419b011b9660474552adee47b51a765e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Jul 2004 22:44:02 +0000 Subject: r1472: Make mknod work again for the CIFS client. Still needs some client changes. With this, storing home directories on a Samba share that require unix domain socket entries should work. Jeremy. (This used to be commit da943b5b72090e23c1cf67c3449b8e33344643f8) --- source3/smbd/trans2.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a7db9daf7d..f3176940c2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3358,16 +3358,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * a new info level should be used for mknod. JRA. */ -#if !defined(HAVE_MAKEDEV_FN) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); -#else /* HAVE_MAKEDEV_FN */ uint32 file_type = IVAL(pdata,0); +#if defined(HAVE_MAKEDEV) uint32 dev_major = IVAL(pdata,4); uint32 dev_minor = IVAL(pdata,12); +#endif uid_t myuid = geteuid(); gid_t mygid = getegid(); - SMB_DEV_T dev; + SMB_DEV_T dev = (SMB_DEV_T)0; if (tran_call == TRANSACT2_SETFILEINFO) return(ERROR_DOS(ERRDOS,ERRnoaccess)); @@ -3375,7 +3374,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (raw_unixmode == SMB_MODE_NO_CHANGE) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); +#if defined(HAVE_MAKEDEV) dev = makedev(dev_major, dev_minor); +#endif /* We can only create as the owner/group we are. */ @@ -3384,10 +3385,30 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE)) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV && - file_type != UNIX_TYPE_FIFO && - file_type != UNIX_TYPE_SOCKET) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); + switch (file_type) { +#if defined(S_IFIFO) + case UNIX_TYPE_FIFO: + unixmode |= S_IFIFO; + break; +#endif +#if defined(S_IFSOCK) + case UNIX_TYPE_SOCKET: + unixmode |= S_IFSOCK; + break; +#endif +#if defined(S_IFCHR) + case UNIX_TYPE_CHARDEV: + unixmode |= S_IFCHR; + break; +#endif +#if defined(S_IFBLK) + case UNIX_TYPE_BLKDEV: + unixmode |= S_IFBLK; + break; +#endif + default: + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + } DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ 0%o for file %s\n", (double)dev, unixmode, fname )); @@ -3401,8 +3422,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); -#endif /* HAVE_MAKEDEV_FN */ - } /* -- cgit From 9d0783bf211dffe58845b36b0669f05bf8bf25b5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 14 Jul 2004 04:36:01 +0000 Subject: r1492: Rework our random number generation system. On systems with /dev/urandom, this avoids a change to secrets.tdb for every fork(). For other systems, we now only re-seed after a fork, and on startup. No need to do it per-operation. This removes the 'need_reseed' parameter from generate_random_buffer(). Andrew Bartlett (This used to be commit 36741d3cf53a7bd17d361251f2bb50851cdb035f) --- source3/smbd/server.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c3e0da542e..16281dd86c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -409,11 +409,12 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ in smbstatus for port 445 connects */ set_remote_machine_name(get_peer_addr(smbd_server_fd()), False); - /* Reset global variables in util.c so - that client substitutions will be - done correctly in the process. */ - reset_globals_after_fork(); + /* Reset the state of the random + * number generation system, so + * children do not get the same random + * numbers as each other */ + set_need_random_reseed(); /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */ if (tdb_reopen_all() == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); @@ -717,7 +718,7 @@ void build_options(BOOL screen); /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ - generate_random_buffer(NULL, 0, False); + generate_random_buffer(NULL, 0); /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ -- cgit From f7463e1bcd956305efe187b958bbd479cca4a820 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Jul 2004 00:58:35 +0000 Subject: r1506: Fix inspired by patches from Michael Collin Nielsen - ensure home directory service number is correctly reused. Jeremy. (This used to be commit 9d6347be8580d092cda0357b5d1a81fc6876ac1f) --- source3/smbd/password.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b2dbde151d..3be1516cf0 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -253,19 +253,23 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, /* Register a home dir service for this user iff (a) This is not a guest connection, - (b) we have a home directory defined, and - (c) there s not an existing static share by that name */ - - if ( (!vuser->guest) - && vuser->unix_homedir - && *(vuser->unix_homedir) - && (lp_servicenumber(vuser->user.unix_name) == -1) ) - { - DEBUG(3, ("Adding/updating homes service for user '%s' using home directory: '%s'\n", + (b) we have a home directory defined + If a share exists by this name (autoloaded or not) reuse it so + long as the home directory is the same as the share directory. */ + + if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { + int servicenumber = lp_servicenumber(vuser->user.unix_name); + if ( servicenumber == -1 ) { + DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); - vuser->homes_snum = add_home_service(vuser->user.unix_name, - vuser->user.unix_name, vuser->unix_homedir); + vuser->user.unix_name, vuser->unix_homedir); + } else if (strcmp(lp_pathname(servicenumber),vuser->unix_homedir) == 0) { + DEBUG(3, ("Reusing homes service for user '%s' using home directory: '%s'\n", + vuser->user.unix_name, vuser->unix_homedir)); + + vuser->homes_snum = servicenumber; + } } else { vuser->homes_snum = -1; } -- cgit From b2701e8c726c55becb47498b48cb8619eb48a82b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Jul 2004 10:02:20 +0000 Subject: r1531: smbd/tdbutil.c isn't used anymore. Bug 1443 is suspected to be a tdb corruption problem, and smbd_log_tdb happily destoyed the evidence .... Volker (This used to be commit 359b9dcffeb66146c5405f8022d5d4e4a833aa51) --- source3/smbd/tdbutil.c | 85 -------------------------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 source3/smbd/tdbutil.c (limited to 'source3/smbd') diff --git a/source3/smbd/tdbutil.c b/source3/smbd/tdbutil.c deleted file mode 100644 index cafcde2037..0000000000 --- a/source3/smbd/tdbutil.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Main SMB server routines - Copyright (C) Jeremy Allison 2003 - Copyright (C) Gerald (Jerry) Carter 2004 - - 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" - - -/********************************************************************** - logging function used by smbd to detect and remove corrupted tdb's -**********************************************************************/ - -void smbd_tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) -{ - va_list ap; - char *ptr = NULL; - BOOL decrement_smbd_count; - - va_start(ap, format); - vasprintf(&ptr, format, ap); - va_end(ap); - - if (!ptr || !*ptr) - return; - - DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); - - if (tdb->ecode == TDB_ERR_CORRUPT) { - int ret; - - DEBUG(0,("tdb_log: TDB %s is corrupt. Removing file and stopping this process.\n", - tdb->name )); - - become_root(); - ret = unlink(tdb->name); - if ( ret ) { - DEBUG(0,("ERROR: %s\n", strerror(errno))); - } - unbecome_root(); - - - /* if its not connections.tdb, then make sure we decrement the - smbd count. If connections.tdb is bad, there's nothing we - can do and everything will eventually shut down or clean - up anyways */ - - if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) - decrement_smbd_count = False; - else - decrement_smbd_count = True; - - /* now die */ - - smb_panic2("corrupt tdb\n", decrement_smbd_count ); - } - - if (tdb->ecode == TDB_ERR_IO) - { - if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) - decrement_smbd_count = False; - else - decrement_smbd_count = True; - - smb_panic2( "i/o error on tdb.\n", decrement_smbd_count ); - } - - SAFE_FREE(ptr); -} - -- cgit From 0c6d7f28d6c1066cc6b3055ebf6a8fcf685ca1f6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 22 Jul 2004 13:39:43 +0000 Subject: r1570: merging changes from 3.0.5 (This used to be commit 430cf63b9148441bce42bfb15a8045de5da108f4) --- source3/smbd/filename.c | 4 ++-- source3/smbd/mangle.c | 4 ++-- source3/smbd/mangle_hash.c | 10 +++++----- source3/smbd/mangle_hash2.c | 8 +++----- source3/smbd/reply.c | 6 +++--- 5 files changed, 15 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ab75d9c06a..cc1c0a40b6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -326,7 +326,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (mangle_is_mangled(start)) { - mangle_check_cache( start ); + mangle_check_cache( start, sizeof(pstring) - 1 - (start - name) ); } DEBUG(5,("New file %s\n",start)); @@ -476,7 +476,7 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, * (JRA). */ if (mangled) - mangled = !mangle_check_cache( name ); + mangled = !mangle_check_cache( name, maxlength ); /* open the directory */ if (!(cur_dir = OpenDir(conn, path, True))) { diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index b77fe601b6..43becff69d 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -98,9 +98,9 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case) looking for a matching name if it doesn't. It should succeed most of the time or there will be a huge performance penalty */ -BOOL mangle_check_cache(char *s) +BOOL mangle_check_cache(char *s, size_t maxlen) { - return mangle_fns->check_cache(s); + return mangle_fns->check_cache(s, maxlen); } /* diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index d7239b82a7..13ec99a917 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -557,7 +557,7 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) * Check for a name on the mangled name stack * * Input: s - Input *and* output string buffer. - * + * maxlen - space in i/o string buffer. * Output: True if the name was found in the cache, else False. * * Notes: If a reverse map is found, the function will overwrite the string @@ -568,7 +568,7 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) * ************************************************************************** ** */ -static BOOL check_cache( char *s ) +static BOOL check_cache( char *s, size_t maxlen ) { ubi_cacheEntryPtr FoundPtr; char *ext_start = NULL; @@ -602,7 +602,7 @@ static BOOL check_cache( char *s ) if( !FoundPtr ) { if(saved_ext) { /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); + (void)safe_strcat( s, saved_ext, maxlen ); SAFE_FREE(saved_ext); } return( False ); @@ -612,10 +612,10 @@ static BOOL check_cache( char *s ) found_name = (char *)(FoundPtr + 1); found_name += (strlen( found_name ) + 1); - (void)pstrcpy( s, found_name ); + (void)safe_strcpy( s, found_name, maxlen ); if( saved_ext ) { /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); + (void)safe_strcat( s, saved_ext, maxlen ); SAFE_FREE(saved_ext); } diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index dcfd7663ba..f68873687b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -362,10 +362,8 @@ static void mangle_reset(void) /* try to find a 8.3 name in the cache, and if found then replace the string with the original long name. - - The filename must be able to hold at least sizeof(fstring) */ -static BOOL check_cache(char *name) +static BOOL check_cache(char *name, size_t maxlen) { u32 hash, multiplier; unsigned int i; @@ -403,10 +401,10 @@ static BOOL check_cache(char *name) if (extension[0]) { M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); - slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); + slprintf(name, maxlen, "%s.%s", prefix, extension); } else { M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); - fstrcpy(name, prefix); + safe_strcpy(name, prefix, maxlen); } return True; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 71efb793af..f3ab709df4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1583,7 +1583,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) */ if (!rc && mangle_is_mangled(mask)) - mangle_check_cache( mask ); + mangle_check_cache( mask, sizeof(pstring)-1 ); if (!has_wild) { pstrcat(directory,"/"); @@ -3738,7 +3738,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui */ if (!rc && mangle_is_mangled(mask)) - mangle_check_cache( mask ); + mangle_check_cache( mask, sizeof(pstring)-1 ); has_wild = ms_has_wild(mask); @@ -4216,7 +4216,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, */ if (!rc && mangle_is_mangled(mask)) - mangle_check_cache( mask ); + mangle_check_cache( mask, sizeof(pstring)-1 ); has_wild = ms_has_wild(mask); -- cgit From 2723be12397c1ddadecac501fb2484c5aa56a564 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Aug 2004 19:57:41 +0000 Subject: r1661: Changed the password history format so that each history entry consists of a 16 byte salt, followed by the 16 byte MD5 hash of the concatination of the salt plus the NThash of the historical password. Allows these to be exposed in LDAP without security issues. Jeremy. (This used to be commit 82e4036aaa2d283534a5bd8149857320fcf0d0dc) --- source3/smbd/chgpasswd.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a1b90c8fed..5c1d66abc4 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -941,7 +941,7 @@ static NTSTATUS check_oem_password(const char *user, static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) { uchar new_nt_p16[NT_HASH_LEN]; - uchar zero_nt_pw[NT_HASH_LEN]; + uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN]; const uint8 *nt_pw; const uint8 *pwhistory; BOOL found = False; @@ -972,22 +972,28 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) } dump_data(100, new_nt_p16, NT_HASH_LEN); - dump_data(100, pwhistory, NT_HASH_LEN*pwHisLen); + dump_data(100, pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen); - memset(zero_nt_pw, '\0', NT_HASH_LEN); + memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN); for (i=0; i Date: Fri, 6 Aug 2004 17:49:00 +0000 Subject: r1665: Patch from James Peach @ SGI to stop using sendfile if it isn't supported by the underlying OS. Jeremy. (This used to be commit 1b0c70cf97aa45093fe5ef866a351b47ef1a5879) --- source3/smbd/reply.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f3ab709df4..4125d71b84 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1748,8 +1748,10 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st * Special hack for broken Linux with no 64 bit clean sendfile. If we * return ENOSYS then pretend we just got a normal read. */ - if (errno == ENOSYS) + if (errno == ENOSYS) { + set_use_sendfile(SNUM(conn), False); goto normal_read; + } DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n", fsp->fsp_name, strerror(errno) )); @@ -2111,8 +2113,10 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length * Special hack for broken Linux with no 64 bit clean sendfile. If we * return ENOSYS then pretend we just got a normal read. */ - if (errno == ENOSYS) + if (errno == ENOSYS) { + set_use_sendfile(SNUM(conn), False); goto normal_read; + } DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", fsp->fsp_name, strerror(errno) )); -- cgit From 532431d49357334febb45bc07524f28052752f9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 10 Aug 2004 01:22:23 +0000 Subject: r1681: Ensure we return the same ACL revision on the wire that W2K3 does. Jeremy. (This used to be commit 31505acf033c7d76592bb5b4ef80b29a00658c49) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2d9591e6ba..95938b1e15 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2863,7 +2863,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } if (num_aces) { - if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) { + if((psa = make_sec_acl( main_loop_talloc_get(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); goto done; } -- cgit From f17922d537213fe1d15cebcd78a8df4068801e7f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Aug 2004 21:27:26 +0000 Subject: r1841: Fix for #1606, can't launch dos exe's. 2 related problems - 1). DOS uses chained commands - when we are replying with sendfile we neglect to send the chained header. 2). Win9x and DOS TCP stacks blow up when getting data back from a Linux sendfile - "The engines canna take the strain cap'n". Don't use sendfile for anything less than NT1. Jeremy. (This used to be commit 3cd88f48afa589a189bb728d2d2660d058203d4d) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4125d71b84..74872eeea9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1735,7 +1735,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st * reply_readbraw has already checked the length. */ - if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) { + if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) { DATA_BLOB header; _smb_setlen(outbuf,nread); @@ -2075,7 +2075,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length * on a train in Germany :-). JRA. */ - if ((CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && + if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) { SMB_STRUCT_STAT sbuf; DATA_BLOB header; -- cgit From 27dedb3b9d6c638e8c7e6d180ec1f53b0499186b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Aug 2004 18:59:13 +0000 Subject: r1866: Fix for bug #1602 reported by . Access to a share with wide links = No follow symlinks = No Was failing with access denied. Jeremy. (This used to be commit c137accb25c928551ce666e8c7cfbbcaa60ad771) --- source3/smbd/vfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 13cfdac0f3..a47f040f6a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -814,7 +814,7 @@ BOOL canonicalize_path(connection_struct *conn, pstring path) it is below dir in the heirachy. This uses realpath. ********************************************************************/ -BOOL reduce_name(connection_struct *conn, pstring fname) +BOOL reduce_name(connection_struct *conn, const pstring fname) { #ifdef REALPATH_TAKES_NULL BOOL free_resolved_name = True; @@ -924,7 +924,11 @@ BOOL reduce_name(connection_struct *conn, pstring fname) } if (!*p) { - pstrcpy(resolved_name, "."); + if (fname[0] == '.' && fname[1] == '/' && fname[2] == '\0') { + pstrcpy(resolved_name, "./"); + } else { + pstrcpy(resolved_name, "."); + } p = resolved_name; } -- cgit From 1842fde7d10a6faccae1a24ebc67f8452a5a828e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 18 Aug 2004 13:55:58 +0000 Subject: r1885: tighten the cache consistency with the ntprinters.tdb entry an the in memory cache associated with open printer handles; also make sure that register_messages_flags() doesn't overwrite the originally registers flags (This used to be commit 540daf71d8ad189af5dd6d45aa1ce2b3d67da752) --- source3/smbd/connection.c | 1 - source3/smbd/reply.c | 2 +- source3/smbd/server.c | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5bb76eb3bd..fc5fe9d741 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -222,7 +222,6 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) } pcrec = (struct connections_data *)dbuf.dptr; - pcrec->bcast_msg_flags = msg_flags; if (doreg) pcrec->bcast_msg_flags |= msg_flags; else diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 74872eeea9..611fb04c19 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -242,7 +242,7 @@ int reply_special(char *inbuf,char *outbuf) reload_services(True); reopen_logs(); - claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); + claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); already_got_session = True; break; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 16281dd86c..0fe633bb96 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -846,6 +846,8 @@ void build_options(BOOL screen); exit(1); /* Setup the main smbd so that we can get messages. */ + /* don't worry about general printing messages here */ + claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); /* only start the background queue daemon if we are -- cgit From 6219c997cbe49952213460f1e100004d32469132 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Aug 2004 20:03:41 +0000 Subject: r1936: Fix bug noticed by Steve - ensure extended security bit is on only if we negotiated extended security. Do not merge for 3.0.6. Works with W2K but needs further testing. Jeremy. (This used to be commit 284689aa18d2711a9041598cdf490359466f7f77) --- source3/smbd/negprot.c | 1 + source3/smbd/process.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 5ff53f6300..5ee8abbe6b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -249,6 +249,7 @@ static int reply_nt1(char *inbuf, char *outbuf) (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { negotiate_spnego = True; capabilities |= CAP_EXTENDED_SECURITY; + add_to_common_flags2(FLAGS2_EXTENDED_SECURITY); } capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 60ce1499e8..5be68d9f0a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1130,7 +1130,12 @@ const char *smb_fn_name(int type) Helper functions for contruct_reply. ****************************************************************************/ -static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES; +static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES; + +void add_to_common_flags2(uint32 v) +{ + common_flags2 |= v; +} void remove_from_common_flags2(uint32 v) { -- cgit From b4470656298303f477798929d44556f3926bb2aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Aug 2004 22:47:05 +0000 Subject: r1939: Ensure with my new change we set extended security in flags2 in the negprot reply. Jeremy. (This used to be commit 8b80b46b8b76ead72c17dc65f2de4c0cc0b263c7) --- source3/smbd/negprot.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 5ee8abbe6b..447073acd8 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -250,6 +250,9 @@ static int reply_nt1(char *inbuf, char *outbuf) negotiate_spnego = True; capabilities |= CAP_EXTENDED_SECURITY; add_to_common_flags2(FLAGS2_EXTENDED_SECURITY); + /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already + partially constructed. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY); } capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE; -- cgit From 4e02b70863f6dac8cf7995010af12d94a372749c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Aug 2004 23:39:29 +0000 Subject: r1976: Simplify, use standard dlist interface. Jeremy. (This used to be commit 776c28133dfa29320608829f15da2f1056454e4c) --- source3/smbd/blocking.c | 73 ++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 3983a4cbdf..b4feef459b 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -27,8 +27,9 @@ extern char *OutBuffer; notify. It consists of the requesting SMB and the expiry time. *****************************************************************************/ -typedef struct { - ubi_slNode msg_next; +typedef struct _blocking_lock_record { + struct _blocking_lock_record *next; + struct _blocking_lock_record *prev; int com_type; files_struct *fsp; time_t expire_time; @@ -40,7 +41,7 @@ typedef struct { int length; } blocking_lock_record; -static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; +static blocking_lock_record *blocking_lock_queue; /**************************************************************************** Destructor for the above structure. @@ -90,7 +91,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { static BOOL set_lock_msg; - blocking_lock_record *blr; + blocking_lock_record *blr, *tmp; BOOL my_lock_ctx = False; NTSTATUS status; @@ -136,7 +137,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, return False; } - ubi_slAddTail(&blocking_lock_queue, blr); + DLIST_ADD_END(blocking_lock_queue, blr, tmp); /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { @@ -516,10 +517,10 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) void remove_pending_lock_requests_by_fid(files_struct *fsp) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr, *next = NULL; - while(blr != NULL) { + for(blr = blocking_lock_queue; blr; blr = next) { + next = blr->next; if(blr->fsp->fnum == fsp->fnum) { DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ @@ -529,13 +530,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; + free_blocking_lock_record(blr); } - - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); } } @@ -545,10 +541,10 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); void remove_pending_lock_requests_by_mid(int mid) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr, *next = NULL; - while(blr != NULL) { + for(blr = blocking_lock_queue; blr; blr = next) { + next = blr->next; if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; @@ -559,13 +555,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; + free_blocking_lock_record(blr); } - - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); } } @@ -587,7 +578,7 @@ unsigned blocking_locks_timeout(unsigned default_timeout) { unsigned timeout = default_timeout; time_t t; - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue); + blocking_lock_record *blr = blocking_lock_queue; /* note that we avoid the time() syscall if there are no blocking locks */ if (!blr) @@ -595,12 +586,11 @@ unsigned blocking_locks_timeout(unsigned default_timeout) t = time(NULL); - while (blr) { + for (; blr; blr = blr->next) { if ((blr->expire_time != (time_t)-1) && (timeout > (blr->expire_time - t))) { timeout = blr->expire_time - t; } - blr = (blocking_lock_record *)ubi_slNext(blr); } if (timeout < 1) @@ -615,21 +605,19 @@ unsigned blocking_locks_timeout(unsigned default_timeout) void process_blocking_lock_queue(time_t t) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; - - if(blr == NULL) - return; + blocking_lock_record *blr, *next = NULL; /* * Go through the queue and see if we can get any of the locks. */ - while(blr != NULL) { + for (blr = blocking_lock_queue; blr; blr = next) { connection_struct *conn = NULL; uint16 vuid; files_struct *fsp = NULL; + next = blr->next; + /* * Ensure we don't have any old chain_fsp values * sitting around.... @@ -658,8 +646,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, True, NULL, NULL); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + free_blocking_lock_record(blr); continue; } @@ -675,8 +662,7 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + free_blocking_lock_record(blr); continue; } @@ -691,8 +677,7 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + free_blocking_lock_record(blr); change_to_root_user(); continue; } @@ -709,18 +694,8 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - change_to_root_user(); - continue; + free_blocking_lock_record(blr); } - change_to_root_user(); - - /* - * Move to the next in the list. - */ - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); } } -- cgit From d792569de6123562f929a3e18ce670d6296c98d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Aug 2004 23:46:18 +0000 Subject: r1978: Roll it back until I do it right.... :-). Jeremy. (This used to be commit f16aa99f8c2f8a31f82e2aedfe3ea6a7276db504) --- source3/smbd/blocking.c | 73 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index b4feef459b..3983a4cbdf 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -27,9 +27,8 @@ extern char *OutBuffer; notify. It consists of the requesting SMB and the expiry time. *****************************************************************************/ -typedef struct _blocking_lock_record { - struct _blocking_lock_record *next; - struct _blocking_lock_record *prev; +typedef struct { + ubi_slNode msg_next; int com_type; files_struct *fsp; time_t expire_time; @@ -41,7 +40,7 @@ typedef struct _blocking_lock_record { int length; } blocking_lock_record; -static blocking_lock_record *blocking_lock_queue; +static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; /**************************************************************************** Destructor for the above structure. @@ -91,7 +90,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { static BOOL set_lock_msg; - blocking_lock_record *blr, *tmp; + blocking_lock_record *blr; BOOL my_lock_ctx = False; NTSTATUS status; @@ -137,7 +136,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, return False; } - DLIST_ADD_END(blocking_lock_queue, blr, tmp); + ubi_slAddTail(&blocking_lock_queue, blr); /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { @@ -517,10 +516,10 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) void remove_pending_lock_requests_by_fid(files_struct *fsp) { - blocking_lock_record *blr, *next = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - for(blr = blocking_lock_queue; blr; blr = next) { - next = blr->next; + while(blr != NULL) { if(blr->fsp->fnum == fsp->fnum) { DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ @@ -530,8 +529,13 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; } + + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); } } @@ -541,10 +545,10 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); void remove_pending_lock_requests_by_mid(int mid) { - blocking_lock_record *blr, *next = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - for(blr = blocking_lock_queue; blr; blr = next) { - next = blr->next; + while(blr != NULL) { if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; @@ -555,8 +559,13 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + continue; } + + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); } } @@ -578,7 +587,7 @@ unsigned blocking_locks_timeout(unsigned default_timeout) { unsigned timeout = default_timeout; time_t t; - blocking_lock_record *blr = blocking_lock_queue; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue); /* note that we avoid the time() syscall if there are no blocking locks */ if (!blr) @@ -586,11 +595,12 @@ unsigned blocking_locks_timeout(unsigned default_timeout) t = time(NULL); - for (; blr; blr = blr->next) { + while (blr) { if ((blr->expire_time != (time_t)-1) && (timeout > (blr->expire_time - t))) { timeout = blr->expire_time - t; } + blr = (blocking_lock_record *)ubi_slNext(blr); } if (timeout < 1) @@ -605,19 +615,21 @@ unsigned blocking_locks_timeout(unsigned default_timeout) void process_blocking_lock_queue(time_t t) { - blocking_lock_record *blr, *next = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + if(blr == NULL) + return; /* * Go through the queue and see if we can get any of the locks. */ - for (blr = blocking_lock_queue; blr; blr = next) { + while(blr != NULL) { connection_struct *conn = NULL; uint16 vuid; files_struct *fsp = NULL; - next = blr->next; - /* * Ensure we don't have any old chain_fsp values * sitting around.... @@ -646,7 +658,8 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, True, NULL, NULL); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); - free_blocking_lock_record(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; } @@ -662,7 +675,8 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; } @@ -677,7 +691,8 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); change_to_root_user(); continue; } @@ -694,8 +709,18 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record(blr); + free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); + blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + change_to_root_user(); + continue; } + change_to_root_user(); + + /* + * Move to the next in the list. + */ + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); } } -- cgit From 2ea1c9de9fe30a8c1929f7cc8c907f6242ea7fd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 21 Aug 2004 00:43:21 +0000 Subject: r1980: Re-apply (remember to remove entry from list on delete this time :-). Jeremy. (This used to be commit 275a0010f487a06b3bc86f82e45d08c821a51b0e) --- source3/smbd/blocking.c | 74 +++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 3983a4cbdf..e143999a78 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -27,8 +27,9 @@ extern char *OutBuffer; notify. It consists of the requesting SMB and the expiry time. *****************************************************************************/ -typedef struct { - ubi_slNode msg_next; +typedef struct _blocking_lock_record { + struct _blocking_lock_record *next; + struct _blocking_lock_record *prev; int com_type; files_struct *fsp; time_t expire_time; @@ -40,7 +41,7 @@ typedef struct { int length; } blocking_lock_record; -static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; +static blocking_lock_record *blocking_lock_queue; /**************************************************************************** Destructor for the above structure. @@ -48,6 +49,7 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu static void free_blocking_lock_record(blocking_lock_record *blr) { + DLIST_REMOVE(blocking_lock_queue, blr); SAFE_FREE(blr->inbuf); SAFE_FREE(blr); } @@ -90,7 +92,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { static BOOL set_lock_msg; - blocking_lock_record *blr; + blocking_lock_record *blr, *tmp; BOOL my_lock_ctx = False; NTSTATUS status; @@ -136,7 +138,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, return False; } - ubi_slAddTail(&blocking_lock_queue, blr); + DLIST_ADD_END(blocking_lock_queue, blr, tmp); /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { @@ -516,10 +518,10 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) void remove_pending_lock_requests_by_fid(files_struct *fsp) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr, *next = NULL; - while(blr != NULL) { + for(blr = blocking_lock_queue; blr; blr = next) { + next = blr->next; if(blr->fsp->fnum == fsp->fnum) { DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ @@ -529,13 +531,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; + free_blocking_lock_record(blr); } - - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); } } @@ -545,10 +542,10 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); void remove_pending_lock_requests_by_mid(int mid) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr, *next = NULL; - while(blr != NULL) { + for(blr = blocking_lock_queue; blr; blr = next) { + next = blr->next; if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; @@ -559,13 +556,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - continue; + free_blocking_lock_record(blr); } - - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); } } @@ -587,7 +579,7 @@ unsigned blocking_locks_timeout(unsigned default_timeout) { unsigned timeout = default_timeout; time_t t; - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue); + blocking_lock_record *blr = blocking_lock_queue; /* note that we avoid the time() syscall if there are no blocking locks */ if (!blr) @@ -595,12 +587,11 @@ unsigned blocking_locks_timeout(unsigned default_timeout) t = time(NULL); - while (blr) { + for (; blr; blr = blr->next) { if ((blr->expire_time != (time_t)-1) && (timeout > (blr->expire_time - t))) { timeout = blr->expire_time - t; } - blr = (blocking_lock_record *)ubi_slNext(blr); } if (timeout < 1) @@ -615,21 +606,19 @@ unsigned blocking_locks_timeout(unsigned default_timeout) void process_blocking_lock_queue(time_t t) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; - - if(blr == NULL) - return; + blocking_lock_record *blr, *next = NULL; /* * Go through the queue and see if we can get any of the locks. */ - while(blr != NULL) { + for (blr = blocking_lock_queue; blr; blr = next) { connection_struct *conn = NULL; uint16 vuid; files_struct *fsp = NULL; + next = blr->next; + /* * Ensure we don't have any old chain_fsp values * sitting around.... @@ -658,8 +647,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, True, NULL, NULL); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + free_blocking_lock_record(blr); continue; } @@ -675,8 +663,7 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + free_blocking_lock_record(blr); continue; } @@ -691,8 +678,7 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); + free_blocking_lock_record(blr); change_to_root_user(); continue; } @@ -709,18 +695,8 @@ void process_blocking_lock_queue(time_t t) blr->lock_pid, sys_getpid(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); - free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); - blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); - change_to_root_user(); - continue; + free_blocking_lock_record(blr); } - change_to_root_user(); - - /* - * Move to the next in the list. - */ - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); } } -- cgit From 3be4c47b905468e541a3fd0491c3eb9ea538ef0b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 24 Aug 2004 12:38:00 +0000 Subject: r2013: BUG 1658: little bit of const (patch from : Helmut Heinreichsberger ) (This used to be commit 22cde8f665f7ed52785699a1d58db3271125ab89) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5c1d66abc4..8ea5b9c60a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -328,7 +328,7 @@ static int talktochild(int master, const char *seq) return (count > 0); } -static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, +static BOOL chat_with_program(char *passwordprogram, const struct passwd *pass, char *chatsequence, BOOL as_root) { char *slavedev; -- cgit From e091cd81480ca14118dab1ae76c37f7bf891c295 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 24 Aug 2004 13:26:31 +0000 Subject: r2016: Add message to ease access-control-debugging. Guenther (This used to be commit bc64bb0d206c54487e372824a14c38a4ba8f3c5a) --- source3/smbd/uid.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index de2f96450f..77dc19b87b 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -130,6 +130,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) /* smb.conf allows r/w, but the security descriptor denies * write. Fall back to looking at readonly. */ readonly_share = True; + DEBUG(5,("falling back to read-only access-evaluation due to security descriptor\n")); } if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { -- cgit From fcbb2d3132df36057da73701f7e23f434034e6b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Aug 2004 22:48:49 +0000 Subject: r2026: Simplify statcache to use an in-memory tdb. Modify tdb to use a customer hash function for this tdb (yes it does make a difference on benchmarks). Remove the no longer used hash.c code. Jeremy. (This used to be commit 3fbadac85b8cad89b93d295968e99c38c8677575) --- source3/smbd/statcache.c | 140 ++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 75 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 5e78e9a499..07a9e3ca85 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -26,15 +26,7 @@ Stat cache code used in unix_convert. *****************************************************************************/ -typedef struct { - char *original_path; - char *translated_path; - size_t translated_path_length; - char names[2]; /* This is extended via malloc... */ -} stat_cache_entry; - -#define INIT_STAT_CACHE_SIZE 512 -static hash_table stat_cache; +static TDB_CONTEXT *tdb_stat_cache; /** * Add an entry into the stat cache. @@ -50,19 +42,17 @@ static hash_table stat_cache; void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive) { - stat_cache_entry *scp; - stat_cache_entry *found_scp; char *translated_path; size_t translated_path_length; - + TDB_DATA data_val; char *original_path; size_t original_path_length; - hash_element *hash_elem; - if (!lp_stat_cache()) return; + ZERO_STRUCT(data_val); + /* * Don't cache trivial valid directory entries such as . and .. */ @@ -124,7 +114,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat return; } - /* we only want to store the first part of original_path, + /* we only want to index by the first part of original_path, up to the length of translated_path */ original_path[translated_path_length] = '\0'; @@ -132,55 +122,26 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } /* - * Check this name doesn't exist in the cache before we - * add it. - */ - - if ((hash_elem = hash_lookup(&stat_cache, original_path))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { - /* already in hash table */ - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - /* hash collision - remove before we re-add */ - hash_remove(&stat_cache, hash_elem); - } - - /* - * New entry. + * New entry or replace old entry. */ - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) - +original_path_length - +translated_path_length)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - scp->original_path = scp->names; - /* pointer into the structure... */ - scp->translated_path = scp->names + original_path_length + 1; - safe_strcpy(scp->original_path, original_path, original_path_length); - safe_strcpy(scp->translated_path, translated_path, translated_path_length); - scp->translated_path_length = translated_path_length; + data_val.dsize = translated_path_length + 1; + data_val.dptr = translated_path; - hash_insert(&stat_cache, (char *)scp, original_path); + if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { + DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); + } else { + DEBUG(5,("stat_cache_add: Added entry (%x:size%x) %s -> %s\n", + (unsigned int)data_val.dptr, data_val.dsize, original_path, translated_path)); + } SAFE_FREE(original_path); SAFE_FREE(translated_path); - - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); } /** * Look through the stat cache for an entry * - * The hash-table's internals will promote it to the top if found. - * * @param conn A connection struct to do the stat() with. * @param name The path we are attempting to cache, modified by this routine * to be correct as far as the cache can tell us @@ -195,11 +156,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { - stat_cache_entry *scp; char *chk_name; size_t namelen; - hash_element *hash_elem; - char *sp; BOOL sizechanged = False; unsigned int num_components = 0; @@ -244,8 +202,11 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } while (1) { - hash_elem = hash_lookup(&stat_cache, chk_name); - if(hash_elem == NULL) { + TDB_DATA data_val; + char *sp; + + data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name); + if(data_val.dptr == NULL || data_val.dsize == 0) { DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); /* * Didn't find it - remove last component for next try. @@ -275,44 +236,71 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; } } else { - scp = (stat_cache_entry *)(hash_elem->value); - DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path )); + BOOL retval; + char *translated_path = data_val.dptr; + size_t translated_path_length = data_val.dsize - 1; + + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path )); DO_PROFILE_INC(statcache_hits); - if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { + if(SMB_VFS_STAT(conn,translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ - hash_remove(&stat_cache, hash_elem); + tdb_delete_bystring(tdb_stat_cache, chk_name); SAFE_FREE(chk_name); + SAFE_FREE(data_val.dptr); return False; } if (!sizechanged) { - memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length)); } else if (num_components == 0) { - pstrcpy(name, scp->translated_path); + pstrcpy(name, translated_path); } else { sp = strnrchr_m(name, '/', num_components); if (sp) { pstring last_component; pstrcpy(last_component, sp); - pstrcpy(name, scp->translated_path); + pstrcpy(name, translated_path); pstrcat(name, last_component); } else { - pstrcpy(name, scp->translated_path); + pstrcpy(name, translated_path); } } /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[scp->translated_path_length]; + *start = &name[translated_path_length]; if(**start == '/') ++*start; - pstrcpy(dirpath, scp->translated_path); + pstrcpy(dirpath, translated_path); + retval = (namelen == translated_path_length) ? True : False; SAFE_FREE(chk_name); - return (namelen == scp->translated_path_length); + SAFE_FREE(data_val.dptr); + return retval; } } } +/* + ************************************************************** + * Compute a hash value based on a string key value. + * Make the string key into an array of int's if possible. + * For the last few chars that cannot be int'ed, use char instead. + * The function returns the bucket index number for the hashed + * key. + * JRA. Use a djb-algorithm hash for speed. + ************************************************************** + */ + +static u32 string_hash(TDB_DATA *key) +{ + u32 n = 0; + const char *p; + for (p = key->dptr; *p != '\0'; p++) { + n = ((n << 5) + n) ^ (u32)(*p); + } + return n; +} + /*************************************************************************** ** * Initializes or clears the stat cache. * @@ -323,15 +311,17 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, */ BOOL reset_stat_cache( void ) { - static BOOL initialised; if (!lp_stat_cache()) return True; - if (initialised) { - hash_clear(&stat_cache); + if (tdb_stat_cache) { + tdb_close(tdb_stat_cache); } - initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, - (compare_function)(strcmp)); - return initialised; + /* Create the in-memory tdb. */ + tdb_stat_cache = tdb_open_log("statcache", 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644); + if (!tdb_stat_cache) + return False; + tdb_set_hash_function(tdb_stat_cache, string_hash); + return True; } -- cgit From a96dfe038e98234698e1967c54be5f4a2a47fa09 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Aug 2004 23:36:33 +0000 Subject: r2027: Fix for but #1657, used initialized variable, from Helmut Heinreichsberger . Jeremy. (This used to be commit 07f7aa6afb0945bb0e108981c4984a6c04c42a53) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 65500c65ce..b08ca0f58b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1024,7 +1024,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ ignored */ if (Access) *Access = DOS_OPEN_WRONLY; - if (action) + if (paction) *paction = FILE_WAS_CREATED; return print_fsp_open(conn, fname); } -- cgit From f98af01f43d37d9d633ec8861232fc1c7f66d3f9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Aug 2004 01:04:02 +0000 Subject: r2032: If you're selecting a hash algorithm for tdb, you need to do it at open time, it doesn't make sense anywhere else. Jeremy. (This used to be commit d7ea1ea8fb3420ca1ad8d95acdc43313898200ff) --- source3/smbd/statcache.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 07a9e3ca85..dfc1a6ed95 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 1999-2000 + Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Andrew Bartlett 2003 This program is free software; you can redistribute it and/or modify @@ -280,16 +280,11 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } -/* - ************************************************************** - * Compute a hash value based on a string key value. - * Make the string key into an array of int's if possible. - * For the last few chars that cannot be int'ed, use char instead. - * The function returns the bucket index number for the hashed - * key. - * JRA. Use a djb-algorithm hash for speed. - ************************************************************** - */ +/*************************************************************** + Compute a hash value based on a string key value. + The function returns the bucket index number for the hashed key. + JRA. Use a djb-algorithm hash for speed. +***************************************************************/ static u32 string_hash(TDB_DATA *key) { @@ -301,14 +296,10 @@ static u32 string_hash(TDB_DATA *key) return n; } -/*************************************************************************** ** - * Initializes or clears the stat cache. - * - * Input: none. - * Output: none. - * - * ************************************************************************** ** - */ +/*************************************************************************** + Initializes or clears the stat cache. +**************************************************************************/ + BOOL reset_stat_cache( void ) { if (!lp_stat_cache()) @@ -318,10 +309,11 @@ BOOL reset_stat_cache( void ) tdb_close(tdb_stat_cache); } - /* Create the in-memory tdb. */ - tdb_stat_cache = tdb_open_log("statcache", 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644); + /* Create the in-memory tdb using our custom hash function. */ + tdb_stat_cache = tdb_open_ex("statcache", 0, TDB_INTERNAL, + (O_RDWR|O_CREAT), 0644, NULL, string_hash); + if (!tdb_stat_cache) return False; - tdb_set_hash_function(tdb_stat_cache, string_hash); return True; } -- cgit From db2ffe10f9283c86f95ae76d38c21916065a4b87 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Aug 2004 23:20:47 +0000 Subject: r2076: Removed old dir caching code - not being used now we have the statcache anyway. New dir caching will be done on nanosecond timestamps. Jeremy. (This used to be commit ba473a580245430009245a4c8b8dcaf9fc4b6406) --- source3/smbd/dir.c | 109 ------------------------------------------------ source3/smbd/filename.c | 18 ++------ source3/smbd/service.c | 2 - 3 files changed, 3 insertions(+), 126 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index b88f687766..2bda42f76d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -986,112 +986,3 @@ int TellDir(void *p) return(dirp->pos); } - -/******************************************************************************* - This section manages a global directory cache. - (It should probably be split into a separate module. crh) -********************************************************************************/ - -typedef struct { - ubi_dlNode node; - char *path; - char *name; - char *dname; - int snum; -} dir_cache_entry; - -static ubi_dlNewList( dir_cache ); - -/***************************************************************************** - Add an entry to the directory cache. - Input: path - - name - - dname - - snum - - Output: None. -*****************************************************************************/ - -void DirCacheAdd( const char *path, const char *name, const char *dname, int snum ) -{ - int pathlen; - int namelen; - dir_cache_entry *entry; - - /* - * Allocate the structure & string space in one go so that it can be freed - * in one call to free(). - */ - pathlen = strlen(path) + 1; /* Bytes required to store path (with nul). */ - namelen = strlen(name) + 1; /* Bytes required to store name (with nul). */ - entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry ) - + pathlen - + namelen - + strlen( dname ) +1 ); - if( NULL == entry ) /* Not adding to the cache is not fatal, */ - return; /* so just return as if nothing happened. */ - - /* Set pointers correctly and load values. */ - entry->path = memcpy( (char *)&entry[1], path, strlen(path)+1 ); - entry->name = memcpy( &(entry->path[pathlen]), name, strlen(name)+1 ); - entry->dname = memcpy( &(entry->name[namelen]), dname, strlen(dname)+1 ); - entry->snum = snum; - - /* Add the new entry to the linked list. */ - (void)ubi_dlAddHead( dir_cache, entry ); - DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) ); - - /* Free excess cache entries. */ - while( DIRCACHESIZE < dir_cache->count ) - safe_free( ubi_dlRemTail( dir_cache ) ); -} - -/***************************************************************************** - Search for an entry to the directory cache. - Input: path - - name - - snum - - Output: The dname string of the located entry, or NULL if the entry was - not found. - - Notes: This uses a linear search, which is is okay because of - the small size of the cache. Use a splay tree or hash - for large caches. -*****************************************************************************/ - -char *DirCacheCheck( const char *path, const char *name, int snum ) -{ - dir_cache_entry *entry; - - for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); - NULL != entry; - entry = (dir_cache_entry *)ubi_dlNext( entry ) ) { - if( entry->snum == snum - && entry->name && 0 == strcmp( name, entry->name ) - && entry->path && 0 == strcmp( path, entry->path ) ) { - DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); - return( entry->dname ); - } - } - - return(NULL); -} - -/***************************************************************************** - Remove all cache entries which have an snum that matches the input. - Input: snum - - Output: None. -*****************************************************************************/ - -void DirCacheFlush(int snum) -{ - dir_cache_entry *entry; - ubi_dlNodePtr next; - - for(entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); - NULL != entry; ) { - next = ubi_dlNext( entry ); - if( entry->snum == snum ) - safe_free( ubi_dlRemThis( dir_cache, entry ) ); - entry = (dir_cache_entry *)next; - } -} diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index cc1c0a40b6..e12cfb1388 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,8 +26,7 @@ #include "includes.h" -static BOOL scan_directory(const char *path, char *name,size_t maxlength, - connection_struct *conn,BOOL docache); +static BOOL scan_directory(connection_struct *conn, const char *path, char *name,size_t maxlength); /**************************************************************************** Check if two filenames are equal. @@ -282,10 +281,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (ms_has_wild(start) || - !scan_directory(dirpath, start, - sizeof(pstring) - 1 - (start - name), - conn, - end?True:False)) { + !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) { if (end) { /* * An intermediate part of the name can't be found. @@ -450,8 +446,7 @@ BOOL check_name(pstring name,connection_struct *conn) If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(const char *path, char *name, size_t maxlength, - connection_struct *conn,BOOL docache) +static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength) { void *cur_dir; const char *dname; @@ -463,11 +458,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, if (*path == 0) path = "."; - if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) { - safe_strcpy(name, dname, maxlength); - return(True); - } - /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) @@ -505,8 +495,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength, if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ - if (docache) - DirCacheAdd(path,name,dname,SNUM(conn)); safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); return(True); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 794b5332ac..5ebd772aa1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -821,8 +821,6 @@ close a cnum ****************************************************************************/ void close_cnum(connection_struct *conn, uint16 vuid) { - DirCacheFlush(SNUM(conn)); - if (IS_IPC(conn)) { pipe_close_conn(conn); } else { -- cgit From df5ee6a6ba2ebe445c8889625c2ee36eea81fcc8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 26 Aug 2004 20:47:58 +0000 Subject: r2077: fix logic bug in the check for creating a user's home directory in register_vuid(); add a few extra debug lines (This used to be commit 02571e7f5040a577840c969ff9c46a1e533edc21) --- source3/smbd/password.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 3be1516cf0..decac845ac 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -252,27 +252,30 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, } /* Register a home dir service for this user iff + (a) This is not a guest connection, (b) we have a home directory defined - If a share exists by this name (autoloaded or not) reuse it so - long as the home directory is the same as the share directory. */ + (c) there s not an existing static share by that name + + If a share exists by this name (autoloaded or not) reuse it . */ + + vuser->homes_snum = -1; - if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { + if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) + { int servicenumber = lp_servicenumber(vuser->user.unix_name); + if ( servicenumber == -1 ) { DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir); - } else if (strcmp(lp_pathname(servicenumber),vuser->unix_homedir) == 0) { - DEBUG(3, ("Reusing homes service for user '%s' using home directory: '%s'\n", - vuser->user.unix_name, vuser->unix_homedir)); - + } else { + DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n", + vuser->user.unix_name, lp_path(servicenumber) )); vuser->homes_snum = servicenumber; } - } else { - vuser->homes_snum = -1; - } + } if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) { /* Try and turn on server signing on the first non-guest sessionsetup. */ -- cgit From 5ef08833b8aea6fffe19173349c0ac9b50994b5f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Aug 2004 21:39:10 +0000 Subject: r2082: lp_path should be lp_pathname. Paranoia fix on mangle prefix. Jeremy. (This used to be commit cc91bbe20d9cb26e52ad417f279e2d60c85af2dc) --- source3/smbd/mangle_hash2.c | 3 ++- source3/smbd/password.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index f68873687b..c6ad1215b0 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -119,7 +119,7 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static u32 mangle_hash(const char *key, unsigned length) +static u32 mangle_hash(const char *key, unsigned int length) { u32 value; u32 i; @@ -129,6 +129,7 @@ static u32 mangle_hash(const char *key, unsigned length) doesn't depend on the case of the long name. Note that this is the only place where we need to use a multi-byte string function */ + length = MIN(length,sizeof(fstring)-1); strncpy(str, key, length); str[length] = 0; strupper_m(str); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index decac845ac..cf3c3d64d2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -272,7 +272,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, vuser->user.unix_name, vuser->unix_homedir); } else { DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n", - vuser->user.unix_name, lp_path(servicenumber) )); + vuser->user.unix_name, lp_pathname(servicenumber) )); vuser->homes_snum = servicenumber; } } -- cgit From 69e87ef8c3005c1cdf23e0ac46beb718986d7daa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Aug 2004 01:16:25 +0000 Subject: r2083: Fix memleak on return code path. Jeremy. (This used to be commit b0af241fd1fc58c1cbaadcbf6832b608923382ff) --- source3/smbd/open.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b08ca0f58b..6d559ac828 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -592,7 +592,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T int i; int num_share_modes; int oplock_contention_count = 0; - share_mode_entry *old_shares = 0; + share_mode_entry *old_shares = NULL; BOOL fcbopen = False; BOOL broke_oplock; @@ -601,12 +601,15 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - if(num_share_modes == 0) + if(num_share_modes == 0) { + SAFE_FREE(old_shares); return 0; + } if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + SAFE_FREE(old_shares); return num_share_modes; } @@ -758,9 +761,6 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" free_broken_entry_list(broken_entry_list); } while(broke_oplock); - if(old_shares != 0) - SAFE_FREE(old_shares); - /* * Refuse to grant an oplock in case the contention limit is * reached when going through the lock list multiple times. @@ -772,6 +772,7 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" oplock_contention_count )); } + SAFE_FREE(old_shares); return num_share_modes; } -- cgit From f1688d61df13aacb0e512fd16504cc94f803d808 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Aug 2004 20:19:40 +0000 Subject: r2112: Simplify the mangle hash code to use an in-memory tdb. Should be ready for the new directory code now... Jeremy. (This used to be commit c2eff8ef1b65570d2e590f62f026cc18f9142652) --- source3/smbd/mangle_hash.c | 218 ++++++++++++--------------------------------- source3/smbd/statcache.c | 4 +- 2 files changed, 57 insertions(+), 165 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 13ec99a917..26ddf1b3a3 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -85,23 +85,6 @@ * if that character is in the illegal characters set. * This is faster than using strchr_m(). * - * mangled_cache - Cache header used for storing mangled -> original - * reverse maps. - * - * mc_initialized - False until the mangled_cache structure has been - * initialized via a call to reset_mangled_cache(). - * - * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the - * cache. A value of 0 indicates "infinite". - * - * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the - * cache. When the cache was kept as an array of 256 - * byte strings, the default cache size was 50 entries. - * This required a fixed 12.5Kbytes of memory. The - * mangled stack parameter is no longer used (though - * this might change). We're now using a fixed 16Kbyte - * maximum cache size. This will probably be much more - * than 50 entries. */ char magic_char = '~'; @@ -118,10 +101,7 @@ static BOOL ct_initialized = False; #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) #define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) -static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } }; -static BOOL mc_initialized = False; -#define MANGLED_CACHE_MAX_ENTRIES 1024 -#define MANGLED_CACHE_MAX_MEMORY 0 +static TDB_CONTEXT *tdb_mangled_cache; /* -------------------------------------------------------------------- */ @@ -400,157 +380,69 @@ static BOOL is_mangled(const char *s) return( False ); } -/* ************************************************************************** ** - * Compare two cache keys and return a value indicating their ordinal - * relationship. - * - * Input: ItemPtr - Pointer to a comparison key. In this case, this will - * be a mangled name string. - * NodePtr - Pointer to a node in the cache. The node structure - * will be followed in memory by a mangled name string. - * - * Output: A signed integer, as follows: - * (x < 0) <==> Key1 less than Key2 - * (x == 0) <==> Key1 equals Key2 - * (x > 0) <==> Key1 greater than Key2 - * - * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for - * more info. - * - * ************************************************************************** ** - */ -static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr ) -{ - char *Key1 = (char *)ItemPtr; - char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1); - - return( StrCaseCmp( Key1, Key2 ) ); -} - -/* ************************************************************************** ** - * Free a cache entry. - * - * Input: WarrenZevon - Pointer to the entry that is to be returned to - * Nirvana. - * Output: none. - * - * Notes: This function gets around the possibility that the standard - * free() function may be implemented as a macro, or other evil - * subversions (oh, so much fun). - * - * ************************************************************************** ** - */ -static void cache_free_entry( ubi_trNodePtr WarrenZevon ) -{ - ZERO_STRUCTP(WarrenZevon); - SAFE_FREE( WarrenZevon ); -} - -/* ************************************************************************** ** - * Initializes or clears the mangled cache. - * - * Input: none. - * Output: none. - * - * Notes: There is a section below that is commented out. It shows how - * one might use lp_ calls to set the maximum memory and entry size - * of the cache. You might also want to remove the constants used - * in ubi_cacheInit() and replace them with lp_ calls. If so, then - * the calls to ubi_cacheSetMax*() would be moved into the else - * clause. Another option would be to pass in the max_entries and - * max_memory values as parameters. crh 09-Apr-1998. - * - * ************************************************************************** ** - */ +/*************************************************************************** + Initializes or clears the mangled cache. +***************************************************************************/ static void mangle_reset( void ) { - if( !mc_initialized ) { - (void)ubi_cacheInit( mangled_cache, - cache_compare, - cache_free_entry, - MANGLED_CACHE_MAX_ENTRIES, - MANGLED_CACHE_MAX_MEMORY ); - mc_initialized = True; - } else { - (void)ubi_cacheClear( mangled_cache ); - } - - /* - (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() ); - (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() ); - */ + /* We could close and re-open the tdb here... should we ? The old code did + the equivalent... JRA. */ } -/* ************************************************************************** ** - * Add a mangled name into the cache. - * - * Notes: If the mangled cache has not been initialized, then the - * function will simply fail. It could initialize the cache, - * but that's not the way it was done before I changed the - * cache mechanism, so I'm sticking with the old method. - * - * If the extension of the raw name maps directly to the - * extension of the mangled name, then we'll store both names - * *without* extensions. That way, we can provide consistent - * reverse mangling for all names that match. The test here is - * a bit more careful than the one done in earlier versions of - * mangle.c: - * - * - the extension must exist on the raw name, - * - it must be all lower case - * - it must match the mangled extension (to prove that no - * mangling occurred). - * - * crh 07-Apr-1998 - * - * ************************************************************************** ** - */ -static void cache_mangled_name( char *mangled_name, char *raw_name ) +/*************************************************************************** + Add a mangled name into the cache. + If the extension of the raw name maps directly to the + extension of the mangled name, then we'll store both names + *without* extensions. That way, we can provide consistent + reverse mangling for all names that match. The test here is + a bit more careful than the one done in earlier versions of + mangle.c: + + - the extension must exist on the raw name, + - it must be all lower case + - it must match the mangled extension (to prove that no + mangling occurred). + crh 07-Apr-1998 +**************************************************************************/ + +static void cache_mangled_name( const char mangled_name[13], char *raw_name ) { - ubi_cacheEntryPtr new_entry; - char *s1; - char *s2; - size_t mangled_len; - size_t raw_len; - size_t i; + TDB_DATA data_val; + char mangled_name_key[13]; + char *s1; + char *s2; /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) + if( !tdb_mangled_cache ) return; /* Init the string lengths. */ - mangled_len = strlen( mangled_name ); - raw_len = strlen( raw_name ); + safe_strcpy(mangled_name_key, mangled_name, sizeof(mangled_name_key)-1); /* See if the extensions are unmangled. If so, store the entry * without the extension, thus creating a "group" reverse map. */ - s1 = strrchr( mangled_name, '.' ); + s1 = strrchr( mangled_name_key, '.' ); if( s1 && (s2 = strrchr( raw_name, '.' )) ) { - i = 1; + size_t i = 1; while( s1[i] && (tolower( s1[i] ) == s2[i]) ) i++; if( !s1[i] && !s2[i] ) { - mangled_len -= i; - raw_len -= i; + /* Truncate at the '.' */ + *s1 = '\0'; + *s2 = '\0'; } } /* Allocate a new cache entry. If the allocation fails, just return. */ - i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2; - new_entry = malloc( i ); - if( !new_entry ) - return; - - /* Fill the new cache entry, and add it to the cache. */ - s1 = (char *)(new_entry + 1); - s2 = (char *)&(s1[mangled_len + 1]); - memcpy( s1, mangled_name, mangled_len ); - s1[mangled_len] = '\0'; - memcpy( s2, raw_name, raw_len ); - s2[raw_len] = '\0'; - ubi_cachePut( mangled_cache, i, new_entry, s1 ); + data_val.dptr = raw_name; + data_val.dsize = strlen(raw_name)+1; + if (tdb_store_bystring(tdb_mangled_cache, mangled_name_key, data_val, TDB_REPLACE) != 0) { + DEBUG(0,("cache_mangled_name: Error storing entry %s -> %s\n", mangled_name_key, raw_name)); + } else { + DEBUG(5,("cache_mangled_name: Stored entry %s -> %s\n", mangled_name_key, raw_name)); + } } /* ************************************************************************** ** @@ -570,26 +462,25 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) static BOOL check_cache( char *s, size_t maxlen ) { - ubi_cacheEntryPtr FoundPtr; - char *ext_start = NULL; - char *found_name; - char *saved_ext = NULL; + TDB_DATA data_val; + char *ext_start = NULL; + char *saved_ext = NULL; /* If the cache isn't initialized, give up. */ - if( !mc_initialized ) + if( !tdb_mangled_cache ) return( False ); - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + data_val = tdb_fetch_bystring(tdb_mangled_cache, s); /* If we didn't find the name *with* the extension, try without. */ - if( !FoundPtr ) { + if(data_val.dptr == NULL || data_val.dsize == 0) { ext_start = strrchr( s, '.' ); if( ext_start ) { if((saved_ext = strdup(ext_start)) == NULL) return False; *ext_start = '\0'; - FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s ); + data_val = tdb_fetch_bystring(tdb_mangled_cache, s); /* * At this point s is the name without the * extension. We re-add the extension if saved_ext @@ -599,7 +490,7 @@ static BOOL check_cache( char *s, size_t maxlen ) } /* Okay, if we haven't found it we're done. */ - if( !FoundPtr ) { + if(data_val.dptr == NULL || data_val.dsize == 0) { if(saved_ext) { /* Replace the saved_ext as it was truncated. */ (void)safe_strcat( s, saved_ext, maxlen ); @@ -609,16 +500,13 @@ static BOOL check_cache( char *s, size_t maxlen ) } /* If we *did* find it, we need to copy it into the string buffer. */ - found_name = (char *)(FoundPtr + 1); - found_name += (strlen( found_name ) + 1); - - (void)safe_strcpy( s, found_name, maxlen ); + (void)safe_strcpy( s, data_val.dptr, maxlen ); if( saved_ext ) { /* Replace the saved_ext as it was truncated. */ (void)safe_strcat( s, saved_ext, maxlen ); SAFE_FREE(saved_ext); } - + SAFE_FREE(data_val.dptr); return( True ); } @@ -767,5 +655,9 @@ struct mangle_fns *mangle_hash_init(void) { mangle_reset(); + /* Create the in-memory tdb using our custom hash function. */ + tdb_mangled_cache = tdb_open_ex("mangled_cache", 1031, TDB_INTERNAL, + (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); + return &mangle_fns; } diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index dfc1a6ed95..03adf32e09 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -286,7 +286,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -static u32 string_hash(TDB_DATA *key) +u32 fast_string_hash(TDB_DATA *key) { u32 n = 0; const char *p; @@ -311,7 +311,7 @@ BOOL reset_stat_cache( void ) /* Create the in-memory tdb using our custom hash function. */ tdb_stat_cache = tdb_open_ex("statcache", 0, TDB_INTERNAL, - (O_RDWR|O_CREAT), 0644, NULL, string_hash); + (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); if (!tdb_stat_cache) return False; -- cgit From 1d7f22c9ae9c18854fe47f7bd51355fced76201c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Aug 2004 22:25:36 +0000 Subject: r2116: Ensure statcache has large enough tdb memory hash size (1031). Jeremy. (This used to be commit dad4d65787df7bd28351cb8f8724d3ae5387ca12) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 03adf32e09..ba37d4927c 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -310,7 +310,7 @@ BOOL reset_stat_cache( void ) } /* Create the in-memory tdb using our custom hash function. */ - tdb_stat_cache = tdb_open_ex("statcache", 0, TDB_INTERNAL, + tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); if (!tdb_stat_cache) -- cgit From e197fb368afd2e22d8a481b0d1adfbb74093ef06 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 31 Aug 2004 21:29:50 +0000 Subject: r2150: Fix parsing of names ending in dot and a few other error returns (commit to Samba4 smbtorture will exercise these fixes). Jeremy. (This used to be commit ff20dacc68c78b8d30993712366af30a64e960aa) --- source3/smbd/reply.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 611fb04c19..30616a66fb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -97,26 +97,25 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w d--; } s += 3; - } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) { - + } else if ((s[0] == '.') && (s[1] == '\0')) { + if (s == srcname) { + ret = NT_STATUS_OBJECT_NAME_INVALID; + break; + } + *d++ = *s++; + } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) { /* * No mb char starts with '.' so we're safe checking the directory separator here. */ - /* "./" or ".\\" fails with a different error depending on where it is... */ + /* "./" or ".\\" fails with a different error depending on what is after it... */ - if (s == srcname) { + if (s[2] == '\0') { ret = NT_STATUS_OBJECT_NAME_INVALID; - break; } else { - if (s[1] != '\0' && s[2] == '\0') { - ret = NT_STATUS_INVALID_PARAMETER; - break; - } ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; - break; } - s++; + break; } else { if (!(*s & 0x80)) { if (allow_wcard_names) { @@ -521,7 +520,6 @@ int reply_ioctl(connection_struct *conn, int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; - int mode; pstring name; BOOL ok = False; BOOL bad_path = False; @@ -544,8 +542,6 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - mode = SVAL(inbuf,smb_vwv0); - if (check_name(name,conn)) { if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) if (!(ok = S_ISDIR(sbuf.st_mode))) { @@ -578,8 +574,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("chkpth %s mode=%d\n", name, mode)); + DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); END_PROFILE(SMBchkpth); return(outsize); -- cgit From 3f9bc7fe07364af205741efcbfd3295fc4b81b46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 31 Aug 2004 22:52:05 +0000 Subject: r2152: Fix for bug #1674, move the symlinks checks into reduce_name(). Jeremy. (This used to be commit 341771857fecf9ef72a436c42e0571d486fa0dde) --- source3/smbd/filename.c | 18 +----------------- source3/smbd/vfs.c | 42 +++++++++++++++++++----------------------- 2 files changed, 20 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index e12cfb1388..279c9dd3c4 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -414,26 +414,10 @@ BOOL check_name(pstring name,connection_struct *conn) } } - if (!lp_widelinks(SNUM(conn))) { + if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { ret = reduce_name(conn,name); } - /* Check if we are allowing users to follow symlinks */ - /* Patch from David Clerc - University of Geneva */ - -#ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) { - SMB_STRUCT_STAT statbuf; - if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) { - DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - errno = EACCES; - ret = False; - } - } -#endif - if (!ret) { DEBUG(5,("check_name on %s failed\n",name)); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a47f040f6a..0328558fe8 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -909,7 +909,8 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) return False; } - if (strncmp(conn->connectpath, resolved_name, con_path_len) != 0) { + /* Check for widelinks allowed. */ + if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) { DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname)); if (free_resolved_name) SAFE_FREE(resolved_name); @@ -917,28 +918,23 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) return False; } - /* Move path the connect path to the last part of the filename. */ - p = resolved_name + con_path_len; - if (*p == '/') { - p++; - } - - if (!*p) { - if (fname[0] == '.' && fname[1] == '/' && fname[2] == '\0') { - pstrcpy(resolved_name, "./"); - } else { - pstrcpy(resolved_name, "."); - } - p = resolved_name; - } - - if (!lp_symlinks(SNUM(conn)) && (strcmp(fname, p)!=0)) { - DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",fname)); - if (free_resolved_name) - SAFE_FREE(resolved_name); - errno = EACCES; - return False; - } + /* Check if we are allowing users to follow symlinks */ + /* Patch from David Clerc + University of Geneva */ + +#ifdef S_ISLNK + if (!lp_symlinks(SNUM(conn))) { + SMB_STRUCT_STAT statbuf; + if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) && + (S_ISLNK(statbuf.st_mode)) ) { + if (free_resolved_name) + SAFE_FREE(resolved_name); + DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name)); + errno = EACCES; + return False; + } + } +#endif DEBUG(3,("reduce_name: %s reduced to %s\n", fname, p)); if (free_resolved_name) -- cgit From 649e1274c7e5992b34125c5df507d5f50903729d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Sep 2004 22:35:36 +0000 Subject: r2194: Here is the efforts of much pain reproducing W2K3 pathname parsing. :-(. One more check for CreateFile() needed. Jeremy. (This used to be commit 294e2021b34c806900ec65ecbf17d9038ac6229a) --- source3/smbd/reply.c | 154 +++++++++++++++++++++++++++----------------------- source3/smbd/trans2.c | 5 ++ 2 files changed, 87 insertions(+), 72 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 30616a66fb..b20b0fe922 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -48,6 +48,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w char *d = destname; const char *s = srcname; NTSTATUS ret = NT_STATUS_OK; + BOOL start_of_name_component = True; while (*s) { if (IS_DIRECTORY_SEP(*s)) { @@ -58,100 +59,109 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w while (IS_DIRECTORY_SEP(*s)) { s++; } - if ((s[0] == '.') && (s[1] == '\0')) { - ret = NT_STATUS_OBJECT_NAME_INVALID; - break; - } if ((d != destname) && (*s != '\0')) { /* We only care about non-leading or trailing '/' or '\\' */ *d++ = '/'; } - } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { - /* Uh oh - "../" or "..\\" or "..\0" ! */ - /* - * No mb char starts with '.' so we're safe checking the directory separator here. - */ + start_of_name_component = True; + continue; + } - /* If we just added a '/', delete it. */ + if (start_of_name_component) { + if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { + /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */ - if ((d > destname) && (*(d-1) == '/')) { - *(d-1) = '\0'; - if (d == (destname + 1)) { + /* + * No mb char starts with '.' so we're safe checking the directory separator here. + */ + + /* If we just added a '/' - delete it */ + if ((d > destname) && (*(d-1) == '/')) { + *(d-1) = '\0'; d--; - } else { - d -= 2; } - } - /* Are we at the start ? Can't go back further if so. */ - if (d == destname) { - ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - break; - } - /* Go back one level... */ - /* We know this is safe as '/' cannot be part of a mb sequence. */ - /* NOTE - if this assumption is invalid we are not in good shape... */ - while (d > destname) { - if (*d == '/') + + /* Are we at the start ? Can't go back further if so. */ + if (d <= destname) { + ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; break; - d--; - } - s += 3; - } else if ((s[0] == '.') && (s[1] == '\0')) { - if (s == srcname) { - ret = NT_STATUS_OBJECT_NAME_INVALID; + } + /* Go back one level... */ + /* We know this is safe as '/' cannot be part of a mb sequence. */ + /* NOTE - if this assumption is invalid we are not in good shape... */ + /* Decrement d first as d points to the *next* char to write into. */ + for (d--; d > destname; d--) { + if (*d == '/') + break; + } + s += 2; /* Else go past the .. */ + /* We're still at the start of a name component, just the previous one. */ + continue; + + } else if ((s[0] == '.') && (s[1] == '\0')) { + /* Component of pathname can't be "." only. */ + ret = NT_STATUS_OBJECT_NAME_INVALID; break; - } - *d++ = *s++; - } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) { - /* - * No mb char starts with '.' so we're safe checking the directory separator here. - */ + } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) { + /* + * No mb char starts with '.' so we're safe checking the directory separator here. + */ - /* "./" or ".\\" fails with a different error depending on what is after it... */ + /* Component of pathname can't be ".\\ANYTHING". */ - if (s[2] == '\0') { - ret = NT_STATUS_OBJECT_NAME_INVALID; - } else { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - break; - } else { - if (!(*s & 0x80)) { - if (allow_wcard_names) { - *d++ = *s++; + /* "/./" or "\\.\\" fails with a different error depending on what is after it... */ + + /* Eat multiple '/' or '\\' */ + for (s++; IS_DIRECTORY_SEP(*s); s++) { + ; + } + + if (*s == '\0') { + ret = NT_STATUS_OBJECT_NAME_INVALID; } else { - switch (*s) { - case '*': - case '?': - case '<': - case '>': - case '"': - return NT_STATUS_OBJECT_NAME_INVALID; - default: - *d++ = *s++; - break; - } + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; } + break; + } + } + + if (!(*s & 0x80)) { + if (allow_wcard_names) { + *d++ = *s++; } else { - switch(next_mb_char_size(s)) { - case 4: - *d++ = *s++; - case 3: - *d++ = *s++; - case 2: - *d++ = *s++; - case 1: + switch (*s) { + case '*': + case '?': + case '<': + case '>': + case '"': + return NT_STATUS_OBJECT_NAME_INVALID; + default: *d++ = *s++; break; - default: - DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); - *d = '\0'; - return NT_STATUS_INVALID_PARAMETER; } } + } else { + switch(next_mb_char_size(s)) { + case 4: + *d++ = *s++; + case 3: + *d++ = *s++; + case 2: + *d++ = *s++; + case 1: + *d++ = *s++; + break; + default: + DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); + *d = '\0'; + return NT_STATUS_INVALID_PARAMETER; + } } + start_of_name_component = False; } + *d = '\0'; return ret; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f3176940c2..0a6ff04ad2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1381,6 +1381,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True); if (!NT_STATUS_IS_OK(ntstatus)) { + /* W2k3 never seems to return OBJECT_PATH_NOT_FOUND on a + bad pathname parse in a findfirst, but always OBJECT_NAME_INVALID. JRA */ + /* It remains to be seen what it does on CreateFile(). JRA. (ie. I need to check) */ + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,ntstatus)) + return ERROR_NT(NT_STATUS_OBJECT_NAME_INVALID); return ERROR_NT(ntstatus); } -- cgit From 51336f27516c2a7d1ece507efeb14054f3cd9e7e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Sep 2004 22:48:35 +0000 Subject: r2196: This error code change is incorrect. Still working on it... Jeremy. (This used to be commit 3dbd822f5e4a241ac12fa6c75de93013f80f00f4) --- source3/smbd/trans2.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0a6ff04ad2..f3176940c2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1381,11 +1381,6 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True); if (!NT_STATUS_IS_OK(ntstatus)) { - /* W2k3 never seems to return OBJECT_PATH_NOT_FOUND on a - bad pathname parse in a findfirst, but always OBJECT_NAME_INVALID. JRA */ - /* It remains to be seen what it does on CreateFile(). JRA. (ie. I need to check) */ - if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,ntstatus)) - return ERROR_NT(NT_STATUS_OBJECT_NAME_INVALID); return ERROR_NT(ntstatus); } -- cgit From a34e4db047ae457fb79a84a520fc802b70268f4f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Sep 2004 20:05:29 +0000 Subject: r2215: I think I'm really close now. The key is to count the number of bad components once you've hit one, and keep track of how many there are (going up a level removes one - maybe it needs to be ./ in order to be removed, need to check). And remember to change the error code return depending on whether you're called from ff or chkpath. Jeremy. (This used to be commit beda1aee795971fa600af65caa749694bb0dfea5) --- source3/smbd/reply.c | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b20b0fe922..d26ab654fa 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -49,6 +49,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w const char *s = srcname; NTSTATUS ret = NT_STATUS_OK; BOOL start_of_name_component = True; + unsigned int num_bad_components = 0; while (*s) { if (IS_DIRECTORY_SEP(*s)) { @@ -97,32 +98,21 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w } s += 2; /* Else go past the .. */ /* We're still at the start of a name component, just the previous one. */ + + if (num_bad_components) { + /* Hmmm. Should we only decrement the bad_components if + we're removing a bad component ? Need to check this. JRA. */ + num_bad_components--; + } + continue; - } else if ((s[0] == '.') && (s[1] == '\0')) { + } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) { /* Component of pathname can't be "." only. */ ret = NT_STATUS_OBJECT_NAME_INVALID; - break; - } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) { - /* - * No mb char starts with '.' so we're safe checking the directory separator here. - */ - - /* Component of pathname can't be ".\\ANYTHING". */ - - /* "/./" or "\\.\\" fails with a different error depending on what is after it... */ - - /* Eat multiple '/' or '\\' */ - for (s++; IS_DIRECTORY_SEP(*s); s++) { - ; - } - - if (*s == '\0') { - ret = NT_STATUS_OBJECT_NAME_INVALID; - } else { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - break; + num_bad_components++; + *d++ = *s++; + continue; } } @@ -160,6 +150,23 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w } } start_of_name_component = False; + if (num_bad_components) { + num_bad_components++; + } + } + + if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { + /* For some strange reason being called from findfirst changes + the num_components number to cause the error return to change. JRA. */ + if (allow_wcard_names) { + if (num_bad_components > 2) { + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } else { + if (num_bad_components > 1) { + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } } *d = '\0'; -- cgit From b755bdaa8eb7428e5da376762cd88ca416220682 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Sep 2004 20:30:31 +0000 Subject: r2219: Remember to count bad_components only on pathname boundaries. Jeremy. (This used to be commit ee8ac9e51a0aefd41df56de4d6deac522bdee4a3) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d26ab654fa..565046061c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -149,10 +149,10 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w return NT_STATUS_INVALID_PARAMETER; } } - start_of_name_component = False; - if (num_bad_components) { + if (start_of_name_component && num_bad_components) { num_bad_components++; } + start_of_name_component = False; } if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { -- cgit From 410a6c72eafbb7fb1ecc9bf89310842ea8027494 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 14 Sep 2004 00:21:11 +0000 Subject: r2331: check password script code and example from trunk (This used to be commit f836be323a233f3a28cbaa04c532e83ea98ead89) --- source3/smbd/chgpasswd.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 8ea5b9c60a..7d3ffedec0 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1046,6 +1046,19 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw return NT_STATUS_ACCESS_DENIED; } + /* Use external script to check password complexity */ + if (lp_check_password_script()) { + int check_ret; + + check_ret = smbrunsecret(lp_check_password_script(), new_passwd); + DEBUG(5, ("change_oem_password: check password script (%s) returned [%d]\n", lp_check_password_script(), check_ret)); + + if (check_ret != 0) { + DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n")); + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + /* * If unix password sync was requested, attempt to change * the /etc/passwd database first. Return failure if this cannot -- cgit From 5e2bac3df484d666f9623948a3fb8bcfe7172b1f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 14 Sep 2004 01:11:01 +0000 Subject: r2333: check the script is not a 0 lenght string (This used to be commit 05a80c37375b3186b02b8430033796ab7a7d68bb) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 7d3ffedec0..af363d75a3 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1047,7 +1047,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw } /* Use external script to check password complexity */ - if (lp_check_password_script()) { + if (lp_check_password_script() && *(lp_check_password_script())) { int check_ret; check_ret = smbrunsecret(lp_check_password_script(), new_passwd); -- cgit From 10e4a96b5399a7ecbc893d2493a9ceb3ec66c8ed Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 17 Sep 2004 15:09:20 +0000 Subject: r2388: fix client quota support for the client we need the windows path and for server we need unix path metze (This used to be commit 54fd28f5e7b70ce2b192c2037ce28da3fea9ef92) --- source3/smbd/fake_file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index d3660addf1..fc874dc086 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -95,9 +95,9 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect static FAKE_FILE fake_files[] = { #ifdef WITH_QUOTAS - {FAKE_FILE_NAME_QUOTA, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle}, + {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle}, #endif /* WITH_QUOTAS */ - {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL } + {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL } }; int is_fake_file(char *fname) @@ -156,7 +156,7 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) { if (!fh||!(*fh)) - return ; + return; if ((*fh)->free_pd) (*fh)->free_pd(&(*fh)->pd); -- cgit From dac628429dd50c6b51327925cd95d6396c5332c8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Sep 2004 19:58:27 +0000 Subject: r2395: Patch from "Stefan (metze) Metzmacher" to fix opening of quota file. Jeremy. (This used to be commit 9a6e331639d7aace294dd663de7d27912fcae146) --- source3/smbd/nttrans.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f717efac63..5e17f76e69 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -762,16 +762,21 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib set_posix_case_semantics(conn, file_attributes); unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { - restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } - /* All file access must go through check_name() */ - if (!check_name(fname,conn)) { - restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + + /* FAKE_FILE is a special case */ + if (fake_file_type == FAKE_FILE_TYPE_NONE) { + /* Normal file. */ + if (bad_path) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } + /* All file access must go through check_name() */ + if (!check_name(fname,conn)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + } } /* -- cgit From 3de9b11601fb85209fd3a799da2f3a4a6cd41624 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 21 Sep 2004 13:04:35 +0000 Subject: r2475: A more helpful debug-message when a connection to a dfs-proxy-share is failing. Guenther (This used to be commit 486bcff17faf8c7ecd9bf4bb9af244bc4bcdf843) --- source3/smbd/service.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 5ebd772aa1..4d111e0ea3 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -804,7 +804,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, /* Handle non-Dfs clients attempting connections to msdfs proxy */ if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) { - DEBUG(3, ("refusing connection to dfs proxy '%s'\n", service)); + DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n", + service, lp_msdfs_proxy(snum))); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } -- cgit From 5c34aebc0f48bdaf7b8f020ef78424f391efb04e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Sep 2004 00:19:18 +0000 Subject: r2548: Fix for bug reported by Edward Spragins - don't try to set security descriptors on shares where this has been turned off. Jeremy. (This used to be commit 9cbe685d02fa1d3778958a3ade4965b64e5d0169) --- source3/smbd/nttrans.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5e17f76e69..d9e321fd96 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1080,7 +1080,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu TALLOC_CTX *mem_ctx; BOOL ret; - if (sd_len == 0) { + if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) { return NT_STATUS_OK; } @@ -1414,7 +1414,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Now try and apply the desired SD. */ - if (sd_len && !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { + if (lp_nt_acl_support(SNUM(conn)) && sd_len && + !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { close_file(fsp,False); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); -- cgit From e8e5e99309ce89e4b75646fb5e8cb3cc6d048eb9 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 23 Sep 2004 12:18:33 +0000 Subject: r2564: resurrecting smbd/tdbutil.c (This used to be commit e61986a11ec69e2510ae1de38ea9c5df4d4804d9) --- source3/smbd/tdbutil.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 source3/smbd/tdbutil.c (limited to 'source3/smbd') diff --git a/source3/smbd/tdbutil.c b/source3/smbd/tdbutil.c new file mode 100644 index 0000000000..cafcde2037 --- /dev/null +++ b/source3/smbd/tdbutil.c @@ -0,0 +1,85 @@ +/* + Unix SMB/CIFS implementation. + Main SMB server routines + Copyright (C) Jeremy Allison 2003 + Copyright (C) Gerald (Jerry) Carter 2004 + + 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" + + +/********************************************************************** + logging function used by smbd to detect and remove corrupted tdb's +**********************************************************************/ + +void smbd_tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + BOOL decrement_smbd_count; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (!ptr || !*ptr) + return; + + DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); + + if (tdb->ecode == TDB_ERR_CORRUPT) { + int ret; + + DEBUG(0,("tdb_log: TDB %s is corrupt. Removing file and stopping this process.\n", + tdb->name )); + + become_root(); + ret = unlink(tdb->name); + if ( ret ) { + DEBUG(0,("ERROR: %s\n", strerror(errno))); + } + unbecome_root(); + + + /* if its not connections.tdb, then make sure we decrement the + smbd count. If connections.tdb is bad, there's nothing we + can do and everything will eventually shut down or clean + up anyways */ + + if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) + decrement_smbd_count = False; + else + decrement_smbd_count = True; + + /* now die */ + + smb_panic2("corrupt tdb\n", decrement_smbd_count ); + } + + if (tdb->ecode == TDB_ERR_IO) + { + if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) + decrement_smbd_count = False; + else + decrement_smbd_count = True; + + smb_panic2( "i/o error on tdb.\n", decrement_smbd_count ); + } + + SAFE_FREE(ptr); +} + -- cgit From 8875124a61c63d2def8ec193a98732f6fcfaa6a1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 24 Sep 2004 00:55:46 +0000 Subject: r2575: Return correct error codes on old SEARCH call (from Samba4 torture tester). Jeremy. (This used to be commit fc51c97ea86bd1a86830d4ab2c6c7c4ec9fccc88) --- source3/smbd/reply.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 565046061c..cdf607e273 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -934,8 +934,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive); dptr_fill(p+12,dptr_num); numentries++; + p += DIR_STRUCT_SIZE; } - p += DIR_STRUCT_SIZE; } } } /* if (ok ) */ @@ -949,18 +949,12 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size (X/Open spec) */ if(ok && expect_close && numentries == 0 && status_len == 0) { - if (Protocol < PROTOCOL_NT1) { - SCVAL(outbuf,smb_rcls,ERRDOS); - SSVAL(outbuf,smb_err,ERRnofiles); - } - /* Also close the dptr - we know it's gone */ + /* Close the dptr - we know it's gone */ dptr_close(&dptr_num); + return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); } else if (numentries == 0 || !ok) { - if (Protocol < PROTOCOL_NT1) { - SCVAL(outbuf,smb_rcls,ERRDOS); - SSVAL(outbuf,smb_err,ERRnofiles); - } dptr_close(&dptr_num); + return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); } /* If we were called as SMBfunique, then we can close the dirptr now ! */ -- cgit From 761dfdabfa306dd8044761b294c5a5f957f5119e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Sep 2004 22:18:46 +0000 Subject: r2637: Fix the roundup problem (returning 1mb roundup) for non-Windows clients. This upsets the smb client in the Linux kernel (and Linus :-). Jeremy. (This used to be commit dad699ce0b36d23b80fe70b74d5e98df568a0495) --- source3/smbd/nttrans.c | 8 ++++---- source3/smbd/trans2.c | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d9e321fd96..eaaf68d689 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -907,7 +907,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + fsp->initial_allocation_size = smb_roundup(allocation_size); if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -920,7 +920,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE); + fsp->initial_allocation_size = smb_roundup((SMB_BIG_UINT)file_len); } /* @@ -1429,7 +1429,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif if (allocation_size && (allocation_size > file_len)) { - fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + fsp->initial_allocation_size = smb_roundup(allocation_size); if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -1441,7 +1441,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE); + fsp->initial_allocation_size = smb_roundup((SMB_BIG_UINT)file_len); } /* Realloc the size of parameters and data we will return */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f3176940c2..a7bc2efb4a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -31,20 +31,43 @@ extern uint32 global_client_caps; extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) +#define DIR_ENTRY_SAFETY_MARGIN 4096 + +/******************************************************************** + Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary. + Only do this for Windows clients. +********************************************************************/ + +SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val) +{ + /* Only roundup for Windows clients. */ + enum remote_arch_types ra_type = get_remote_arch(); + if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { + val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE); + } + return val; +} + +/******************************************************************** + Given a stat buffer return the allocated size on disk, taking into + account sparse files. +********************************************************************/ -/* given a stat buffer return the allocated size on disk, taking into - account sparse files */ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) { SMB_BIG_UINT ret; + #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks; #else ret = (SMB_BIG_UINT)get_file_size(*sbuf); #endif + if (!ret && fsp && fsp->initial_allocation_size) ret = fsp->initial_allocation_size; - ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE); + + ret = smb_roundup(ret); + return ret; } @@ -1409,12 +1432,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); - pdata = Realloc(*ppdata, max_data_bytes + 1024); + pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if( pdata == NULL ) return(ERROR_DOS(ERRDOS,ERRnomem)); *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); + memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = Realloc(*pparams, 10); @@ -1602,12 +1625,12 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return ERROR_DOS(ERRDOS,ERRunknownlevel); } - pdata = Realloc( *ppdata, max_data_bytes + 1024); + pdata = Realloc( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(pdata == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); + memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = Realloc(*pparams, 6*SIZEOFWORD); @@ -1818,12 +1841,12 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf return ERROR_DOS(ERRSRV,ERRinvdevice); } - pdata = Realloc(*ppdata, max_data_bytes + 1024); + pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if ( pdata == NULL ) return ERROR_DOS(ERRDOS,ERRnomem); *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); + memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); switch (info_level) { case SMB_INFO_ALLOCATION: @@ -2389,7 +2412,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; memset((char *)params,'\0',2); - data_size = max_data_bytes + 1024; + data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; pdata = Realloc(*ppdata, data_size); if ( pdata == NULL ) return ERROR_DOS(ERRDOS,ERRnomem); @@ -3189,7 +3212,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname, (double)allocation_size )); if (allocation_size) - allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + allocation_size = smb_roundup(allocation_size); if(allocation_size != get_file_size(sbuf)) { SMB_STRUCT_STAT new_sbuf; -- cgit From eb9a09954b97f78768f07cbb921c05b06321d5ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 26 Sep 2004 06:27:54 +0000 Subject: r2651: Added 'stat' command to smbclient to exercise the UNIX_FILE_BASIC info level. Outputs data on the file in the same format the the stat command in Linux. Should be useful to people wanting to learn how to parse the UNIX extension output. Yes I will add the docs later :-). Jeremy. (This used to be commit b25cc596417d29815814c3968ac2627bf59ffc0b) --- source3/smbd/trans2.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a7bc2efb4a..825481984d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -756,32 +756,6 @@ static uint32 unix_filetype(mode_t mode) return UNIX_TYPE_UNKNOWN; } -/**************************************************************************** - Return the major devicenumber for UNIX extensions. -****************************************************************************/ - -static uint32 unix_dev_major(SMB_DEV_T dev) -{ -#if defined(HAVE_DEVICE_MAJOR_FN) - return (uint32)major(dev); -#else - return (uint32)(dev >> 8); -#endif -} - -/**************************************************************************** - Return the minor devicenumber for UNIX extensions. -****************************************************************************/ - -static uint32 unix_dev_minor(SMB_DEV_T dev) -{ -#if defined(HAVE_DEVICE_MINOR_FN) - return (uint32)minor(dev); -#else - return (uint32)(dev & 0xff); -#endif -} - /**************************************************************************** Map wire perms onto standard UNIX permissions. Obey share restrictions. ****************************************************************************/ -- cgit From 2d5bf9ec40dbae68ced924604e180f6669b80670 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Mon, 27 Sep 2004 17:07:28 +0000 Subject: r2697: Fix for bugzilla #1732, patch by Satoh Fumiyasu, fumiya@samba.gr.jp Limit share names returned by RAP based on windows character width, not unix character width. (This used to be commit 5d57058d912a42d55879352e904f0bcaa6531075) --- source3/smbd/lanman.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index dd9708356e..524c982998 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1501,10 +1501,12 @@ static BOOL api_RNetShareEnum( connection_struct *conn, if (!check_share_info(uLevel,str2)) return False; data_len = fixed_len = string_len = 0; - for (i=0;i Date: Mon, 27 Sep 2004 23:57:59 +0000 Subject: r2700: Fix bug where we could incorrectly set sparse attribute. Don't use st_blksize, it isn't what you think.... Jeremy. --his line, and those below, will be ignored-- M source/smbd/dosmode.c (This used to be commit 0a40c1a50f0e4b1b7efc9a53d22ceac14841bccf) --- source3/smbd/dosmode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 33c75fffd5..7199b3ebbf 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -135,8 +135,8 @@ uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf) if (S_ISDIR(sbuf->st_mode)) result = aDIR | (result & aRONLY); -#if defined (HAVE_STAT_ST_BLOCKS) && defined (HAVE_STAT_ST_BLKSIZE) - if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)sbuf->st_blksize) { +#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) + if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) { result |= FILE_ATTRIBUTE_SPARSE; } #endif -- cgit From 39efdab4c150f1a6dc1fec1ce26cb0bf1e53669b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Sep 2004 05:33:30 +0000 Subject: r2708: Don't look for bzero, we don't use it. Samba4 torture tester treates maxentries = 0 as maxentries ==1. Jeremy. (This used to be commit 38f3d3e263f59f94f243907447b5a82f67d3e3f7) --- source3/smbd/trans2.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 825481984d..31a74ae482 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1357,7 +1357,12 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, info_level, max_data_bytes)); - + + if (!maxentries) { + /* W2K3 seems to treat zero as 1. */ + maxentries = 1; + } + switch (info_level) { case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: @@ -1583,6 +1588,11 @@ resume_key = %d resume name = %s continue=%d level = %d\n", dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, requires_resume_key, resume_key, resume_name, continue_bit, info_level)); + if (!maxentries) { + /* W2K3 seems to treat zero as 1. */ + maxentries = 1; + } + switch (info_level) { case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: -- cgit From 31441aaa137145511a2c09dd540d46876df56701 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 1 Oct 2004 20:34:12 +0000 Subject: r2768: BUG 1519: save the hostname used in the open_printer_ex() for later reuse when filling in the spolss replies (also gets rid of get_called_name() (This used to be commit 57db8ca91f52329c7f8985c04463b6b69015b0c4) --- source3/smbd/lanman.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 524c982998..8b07f0e305 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -548,9 +548,8 @@ static void fill_printq_info_52(connection_struct *conn, int snum, PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */ PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ - fstrcpy(location, "\\\\"); - fstrcat(location, get_called_name()); - fstrcat(location, "\\print$\\WIN40\\0"); + fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); + standard_sub_basic( NULL, location, sizeof(location)-1 ); PACKS(desc,"z", location); /* share to retrieve files */ PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ -- cgit From 96876f696eed81327d32b92ee7160c9048d39388 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 2 Oct 2004 00:13:21 +0000 Subject: r2772: Check correct string length when verifying password-policies. Do not allow e.g. two umlauts and one ascii char to comply with account-policy "min password length" of 5. Thanks to Uwe Morgenroth from CC Compunet and Volker. TODO: we do check the length against AP_MIN_PASSWORD_LEN *and* lp_min_passwd_length() - both can have differing values. (This used to be commit d03683772942e8c32507be210b8fd35bfba2c048) --- source3/smbd/chgpasswd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index af363d75a3..f8636be351 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1018,7 +1018,8 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw return NT_STATUS_ACCOUNT_RESTRICTION; } - if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (strlen(new_passwd) < min_len)) { + /* FIXME: AP_MIN_PASSWORD_LEN and lp_min_passwd_length() need to be merged - gd */ + if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { DEBUG(1, ("user %s cannot change password - password too short\n", username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); @@ -1028,7 +1029,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw /* Take the passed information and test it for minimum criteria */ /* Minimum password length */ - if (strlen(new_passwd) < lp_min_passwd_length()) { + if (str_charnum(new_passwd) < lp_min_passwd_length()) { /* too short, must be at least MINPASSWDLENGTH */ DEBUG(1, ("Password Change: user %s, New password is shorter than minimum password length = %d\n", username, lp_min_passwd_length())); -- cgit From 8f49721fef2dfa66ac13ec7b860a3315019240da Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 11 Oct 2004 00:32:31 +0000 Subject: r2899: Change some #if DEBUG_PASSWORD's to #ifdef DEBUG_PASSWORD. Bugzilla #1903. (This used to be commit 1327d83d902b6a39096d387d734e73d85ed53f85) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/password.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index f8636be351..c91f8599c9 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -456,7 +456,7 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, DEBUG(3, ("chgpasswd: Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name)); -#if DEBUG_PASSWORD +#ifdef DEBUG_PASSWORD DEBUG(100, ("chgpasswd: Passwords: old=%s new=%s\n", oldpass, newpass)); #endif diff --git a/source3/smbd/password.c b/source3/smbd/password.c index cf3c3d64d2..eb389d7013 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -473,7 +473,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, { BOOL ok = False; -#if DEBUG_PASSWORD +#ifdef DEBUG_PASSWORD DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n", user,password.data)); #endif -- cgit From 2efbc238d4f32e810f42393ea2f1f022030d97c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 16 Oct 2004 03:04:40 +0000 Subject: r3002: Fix for bug #1886 - prevent delete on close being set for readonly files (and return the correct error code). We now pass the Samba4 test suite on this. Jeremy. (This used to be commit 6ae417f12cc6f8d2ad00bea27ce0a20242f76325) --- source3/smbd/open.c | 16 ++++++++++++++-- source3/smbd/trans2.c | 45 +++++++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6d559ac828..55970493fa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1409,9 +1409,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } if (delete_on_close) { - NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + uint32 dosmode = existing_dos_mode; + NTSTATUS result; + + if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { + dosmode = new_dos_mode; + } + result = set_delete_on_close_internal(fsp, delete_on_close, dosmode); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + uint8 u_e_c; + uint32 u_e_code; /* Remember to delete the mode we just added. */ if (add_share_mode) { del_share_mode(fsp, NULL); @@ -1419,6 +1427,10 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); + ntstatus_to_dos(result, &u_e_c, &u_e_code); + unix_ERR_ntstatus = result; + unix_ERR_class = u_e_c; + unix_ERR_code = u_e_code; return NULL; } } @@ -1651,7 +1663,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST string_set(&fsp->fsp_name,fname); if (delete_on_close) { - NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close, 0); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { file_free(fsp); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 31a74ae482..9b1f2aa210 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2811,25 +2811,38 @@ static int call_trans2qfilepathinfo(connection_struct *conn, open_file_shared. JRA. ****************************************************************************/ -NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) +NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode) { - /* - * Only allow delete on close for writable shares. - */ + if (delete_on_close) { + /* + * Only allow delete on close for writable files. + */ - if (delete_on_close && !CAN_WRITE(fsp->conn)) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n", + if (dosmode & aRONLY) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n", fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } - /* - * Only allow delete on close for files/directories opened with delete intent. - */ + return NT_STATUS_CANNOT_DELETE; + } + + /* + * Only allow delete on close for writable shares. + */ - if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n", + if (!CAN_WRITE(fsp->conn)) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n", fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_ACCESS_DENIED; + } + + /* + * Only allow delete on close for files/directories opened with delete intent. + */ + + if (!(fsp->desired_access & DELETE_ACCESS)) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; + } } if(fsp->is_directory) { @@ -2866,7 +2879,7 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) return NT_STATUS_ACCESS_DENIED; if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n", + DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n", fsp->fsp_name )); unlock_share_entry_fsp(fsp); return NT_STATUS_ACCESS_DENIED; @@ -3286,7 +3299,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadfid)); - status = set_delete_on_close_internal(fsp, delete_on_close); + status = set_delete_on_close_internal(fsp, delete_on_close, dosmode); if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) return ERROR_NT(status); -- cgit From c53e6401eb3de7fa4abc85c25f8672b624cf2c66 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 18 Oct 2004 19:57:03 +0000 Subject: r3049: fixing some calls in the printing code to stanard_sub_basic(); fix standard_sub_snum() to use the current user's gid; add some (snum == -1) checks to standard_sub_advanced() (This used to be commit 8c3fd1908d201e9891878ff4c3259ed9690dff97) --- source3/smbd/lanman.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 8b07f0e305..610ee45120 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -441,7 +441,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, /* the client expects localtime */ t -= TimeDiff(t); - PACKI(desc,"W",pjobid_to_rap(snum,queue->job)); /* uJobId */ + PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */ if (uLevel == 1) { PACKS(desc,"B21",queue->fs_user); /* szUserName */ PACKS(desc,"B",""); /* pad */ @@ -549,7 +549,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); - standard_sub_basic( NULL, location, sizeof(location)-1 ); + standard_sub_basic( "", location, sizeof(location)-1 ); PACKS(desc,"z", location); /* share to retrieve files */ PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ @@ -2122,11 +2122,12 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param char *p = skip_string(str2,1); uint32 jobid; int snum; + fstring sharename; int errcode; extern struct current_user current_user; WERROR werr = WERR_OK; - if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid)) + if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; /* check it's a supported varient */ @@ -2137,7 +2138,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param *rparam = REALLOC(*rparam,*rparam_len); *rdata_len = 0; - if (!print_job_exists(snum, jobid)) { + if (!print_job_exists(sharename, jobid)) { errcode = NERR_JobNotFound; goto out; } @@ -2257,11 +2258,12 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha char *p = skip_string(str2,1); uint32 jobid; int snum; + fstring sharename; int uLevel = SVAL(p,2); int function = SVAL(p,4); int place, errcode; - if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid)) + if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); @@ -2273,7 +2275,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha (!check_printjob_info(&desc,uLevel,str2))) return(False); - if (!print_job_exists(snum, jobid)) { + if (!print_job_exists(sharename, jobid)) { errcode=NERR_JobNotFound; goto out; } @@ -2939,6 +2941,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para int count; int i; int snum; + fstring sharename; uint32 jobid; struct pack_desc desc; print_queue_struct *queue=NULL; @@ -2956,7 +2959,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para if (strcmp(str1,"WWrLh") != 0) return False; if (!check_printjob_info(&desc,uLevel,str2)) return False; - if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid)) + if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; if (snum < 0 || !VALID_SNUM(snum)) return(False); -- cgit From 8c1c918c94b443c7154d535b1f99201dc1767f97 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Oct 2004 22:01:10 +0000 Subject: r3050: Steal from Samba4 :-). Make us pass most of the new lock tests (except for the cancel lock which I have to add). Jeremy. (This used to be commit cf7f89999e0c6becd4617c812400d1e71b9c0a30) --- source3/smbd/files.c | 46 ++++++++++++++++++++++++---------------------- source3/smbd/reply.c | 7 ++++++- 2 files changed, 30 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 80544c9a30..580dc54545 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -289,12 +289,12 @@ files_struct *file_find_fsp(files_struct *orig_fsp) { files_struct *fsp; - for (fsp=Files;fsp;fsp=fsp->next) { - if (fsp == orig_fsp) - return fsp; - } + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp == orig_fsp) + return fsp; + } - return NULL; + return NULL; } /**************************************************************************** @@ -303,16 +303,16 @@ files_struct *file_find_fsp(files_struct *orig_fsp) files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) { - files_struct *fsp; + files_struct *fsp; - for (fsp=Files;fsp;fsp=fsp->next) { - if ( fsp->fd != -1 && - fsp->dev == dev && - fsp->inode == inode ) - return fsp; - } + for (fsp=Files;fsp;fsp=fsp->next) { + if ( fsp->fd != -1 && + fsp->dev == dev && + fsp->inode == inode ) + return fsp; + } - return NULL; + return NULL; } /**************************************************************************** @@ -321,16 +321,16 @@ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) files_struct *file_find_di_next(files_struct *start_fsp) { - files_struct *fsp; + files_struct *fsp; - for (fsp = start_fsp->next;fsp;fsp=fsp->next) { - if ( fsp->fd != -1 && - fsp->dev == start_fsp->dev && - fsp->inode == start_fsp->inode ) - return fsp; - } + for (fsp = start_fsp->next;fsp;fsp=fsp->next) { + if ( fsp->fd != -1 && + fsp->dev == start_fsp->dev && + fsp->inode == start_fsp->inode ) + return fsp; + } - return NULL; + return NULL; } /**************************************************************************** @@ -388,7 +388,9 @@ void file_free(files_struct *fsp) information */ ZERO_STRUCTP(fsp); - if (fsp == chain_fsp) chain_fsp = NULL; + if (fsp == chain_fsp) { + chain_fsp = NULL; + } SAFE_FREE(fsp); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cdf607e273..845f058867 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4514,13 +4514,18 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, data = smb_buf(inbuf); - if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) { + if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) { /* we don't support these - and CANCEL_LOCK makes w2k and XP reboot so I don't really want to be compatible! (tridge) */ return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } + if (locktype & LOCKING_ANDX_CANCEL_LOCK) { + /* Need to make this like a cancel.... JRA. */ + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } + /* Check if this is an oplock break on a file we have granted an oplock on. */ -- cgit From 293136c04b7eb5293ef18273e13fca00c85bb5f0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 19 Oct 2004 17:05:01 +0000 Subject: r3067: patch based on volker's initial work in trunk that fixes the queu update problem when using the background daemon (This used to be commit de7af09e727e744aa27af85ef7c0f73ed5c1550a) --- source3/smbd/fileio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index c2fb6e3456..b9fe1ad1cf 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -151,10 +151,10 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) int write_path = -1; if (fsp->print_file) { - int snum; + fstring sharename; uint32 jobid; - if (!rap_to_pjobid(fsp->rap_print_jobid, &snum, &jobid)) { + if (!rap_to_pjobid(fsp->rap_print_jobid, sharename, &jobid)) { DEBUG(3,("write_file: Unable to map RAP jobid %u to jobid.\n", (unsigned int)fsp->rap_print_jobid )); errno = EBADF; -- cgit From 677c218f3f63565c5b3ca6b19db0aa900115c561 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Oct 2004 17:22:35 +0000 Subject: r3117: Fix from Tom Lackemann for bug #1954. Memory leak in posix acl code. Jeremy. (This used to be commit c97aab7ee6bf1f385b445b4b0eb0e1df7e9a56f5) --- source3/smbd/posix_acls.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 95938b1e15..ab32d0591e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3195,6 +3195,7 @@ int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; SMB_ACL_T posix_acl; + int result = -1; posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS); if (posix_acl == (SMB_ACL_T)NULL) @@ -3209,20 +3210,22 @@ int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode entry_id = SMB_ACL_NEXT_ENTRY; if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1) - return -1; + break; if (tagtype == SMB_ACL_GROUP_OBJ) { if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { - return -1; + break; } else { *mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP); *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRGRP : 0); *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWGRP : 0); *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0); - return 0;; + result = 0; + break; } } } + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); return -1; } -- cgit From 7eec693863ec2aa95bd94469f9319ac507d28ce4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Oct 2004 19:51:33 +0000 Subject: r3121: Bug #1956. Ensure errno is saved and restored consistently on a normal_close. Jeremy. (This used to be commit f08f437c736e44913b3eeb16d6e32da8975442a7) --- source3/smbd/close.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 6de2774644..4445f2516b 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -150,6 +150,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) size_t share_entry_count = 0; BOOL delete_on_close = False; connection_struct *conn = fsp->conn; + int saved_errno = 0; int err = 0; int err1 = 0; @@ -160,8 +161,10 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * error here, we must remember this. */ - if (close_filestruct(fsp) == -1) + if (close_filestruct(fsp) == -1) { + saved_errno = errno; err1 = -1; + } if (fsp->print_file) { print_fsp_end(fsp, normal_close); @@ -242,6 +245,12 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); err = fd_close(conn, fsp); + /* Only save errno if fd_close failed and we don't already + have an errno saved from a flush call. */ + if ((err1 != -1) && (err == -1)) { + saved_errno = errno; + } + /* check for magic scripts */ if (normal_close) { check_magic(fsp,conn); @@ -252,24 +261,25 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); */ if(fsp->pending_modtime) { - int saved_errno = errno; set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); - errno = saved_errno; } DEBUG(2,("%s closed file %s (numopen=%d) %s\n", - conn->user,fsp->fsp_name, - conn->num_files_open, err ? strerror(err) : "")); + conn->user,fsp->fsp_name, + conn->num_files_open, + (err == -1 || err1 == -1) ? strerror(saved_errno) : "")); if (fsp->fsp_name) string_free(&fsp->fsp_name); file_free(fsp); - if (err == -1 || err1 == -1) - return errno; - else + if (err == -1 || err1 == -1) { + errno = saved_errno; + return saved_errno; + } else { return 0; + } } /**************************************************************************** -- cgit From 2d32a937252483c74c8489dd3e8be2c2d9cbd763 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Oct 2004 23:39:01 +0000 Subject: r3225: Fix correct use of resume name. Cope with the resume name not existing. Found using Samba4 RAW-SEARCH. Jeremy. (This used to be commit 74dd2b33ff1ecba752682937c792628e081f17f5) --- source3/smbd/trans2.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9b1f2aa210..ac282ed95f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1662,7 +1662,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * depend on the last file name instead. */ - if(requires_resume_key && *resume_name && !continue_bit) { + if(*resume_name && !continue_bit) { /* * Fix for NT redirector problem triggered by resume key indexes @@ -1714,7 +1714,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", if(current_pos < 0) { DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos)); SeekDir(dirptr, start_pos); - for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) { + for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) { /* * Remember, mangle_map is called by @@ -1737,7 +1737,11 @@ resume_key = %d resume name = %s continue=%d level = %d\n", } } /* end for */ } /* end if current_pos */ - } /* end if requires_resume_key && !continue_bit */ + /* Can't find the name. Just resume from where we were... */ + if (dname == 0) { + SeekDir(dirptr, start_pos); + } + } /* end if resume_name && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { BOOL got_exact_match = False; -- cgit From e62d9c3b87d267782ce8e79c6e15613075408333 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Oct 2004 18:11:41 +0000 Subject: r3296: Fix to ensure entries are stored in correct order. Bug #1498. Patch from SATOH Fumiyasu . Jeremy. (This used to be commit 7e35900bc6894d69f83c99ac6eb260d7cc35683a) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ab32d0591e..66103fda5c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -180,7 +180,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B entry_offset = pai_buf + PAI_ENTRIES_BASE; - for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) { + for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) { if (ace_list->inherited) { uint8 type_val = (unsigned char)ace_list->owner_type; uint32 entry_val = get_entry_val(ace_list); @@ -191,7 +191,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B } } - for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) { + for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) { if (ace_list->inherited) { uint8 type_val = (unsigned char)ace_list->owner_type; uint32 entry_val = get_entry_val(ace_list); -- cgit From 193e82b0563da1a5b913432953f236d36008ef34 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 3 Nov 2004 00:32:08 +0000 Subject: r3496: Fix calling of get_acl_group_bits(). Guenther (This used to be commit 3acc74eef5dae16d7e2792206640904265c42494) --- source3/smbd/dosmode.c | 4 +++- source3/smbd/posix_acls.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 7199b3ebbf..3a3a6e6fdb 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -344,7 +344,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, return(-1); } - get_acl_group_bits(conn, fname, &st->st_mode); + if (!get_acl_group_bits(conn, fname, &st->st_mode)) { + return(-1); + } if (S_ISDIR(st->st_mode)) dosmode |= aDIR; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 66103fda5c..be7f828b67 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3226,7 +3226,7 @@ int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode } } SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); - return -1; + return result; } /**************************************************************************** -- cgit From baf1ae1b0e86e16cc1364d64463d654e297fa221 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Nov 2004 21:45:02 +0000 Subject: r3559: If called interactively, on shutdown dump the talloc contexts left. Idea stolen from samba4 ... ;-) Volker (This used to be commit b111bb46afc247e034a11e953b9d243cde69cc07) --- source3/smbd/server.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0fe633bb96..bf1da1a0c8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -910,6 +910,15 @@ void build_options(BOOL screen); smbd_process(); namecache_shutdown(); + + if (interactive) { + TALLOC_CTX *mem_ctx = talloc_init("end_description"); + char *description = talloc_describe_all(mem_ctx); + + DEBUG(3, ("tallocs left:\n%s\n", description)); + talloc_destroy(mem_ctx); + } + exit_server("normal exit"); return(0); } -- cgit From 55fe875a44bd63de766d4fbdb91bcc26be146a21 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Nov 2004 22:53:35 +0000 Subject: r3563: During a typical logon a modern workstation makes a lot of anonymous session setups on its way to open a pipe. This gets rid of many round-trips to the LDAP server during logon by setting up the server_info_guest once and not asking the LDAP server and nss every time. Make sure that the ldap connection is reopened in the child. (I did not look at the sql backends.) Volker (This used to be commit 3298f6105e6a88c9390cac02245c8f2eee1e5046) --- source3/smbd/server.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bf1da1a0c8..82da85767b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -780,6 +780,9 @@ void build_options(BOOL screen); init_structs(); + if (!init_guest_info()) + return -1; + #ifdef WITH_PROFILE if (!profile_setup(False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); -- cgit From c0406ae1b04a60318ba18abb168b610d8c223005 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Nov 2004 22:49:28 +0000 Subject: r3642: Extend vfs to add seekdir/telldir/rewinddir. Yes I know I have to fix the modules too... First step in fixing out large directories problem. Jeremy. (This used to be commit 344e9dd33a936b429fefb67cd748ac009a1bab10) --- source3/smbd/trans2.c | 16 +++++++++------- source3/smbd/vfs-wrap.c | 31 +++++++++++++++++++++++++++---- source3/smbd/vfs.c | 7 +++++-- 3 files changed, 41 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ac282ed95f..4c0d5731eb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1329,9 +1329,10 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb char *pdata = *ppdata; int dirtype = SVAL(params,0); int maxentries = SVAL(params,2); - BOOL close_after_first = BITSETW(params+4,0); - BOOL close_if_end = BITSETW(params+4,1); - BOOL requires_resume_key = BITSETW(params+4,2); + uint16 findfirst_flags = SVAL(params,4); + BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE); + BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); + BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); int info_level = SVAL(params,6); pstring directory; pstring mask; @@ -1555,10 +1556,11 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu int maxentries = SVAL(params,2); uint16 info_level = SVAL(params,4); uint32 resume_key = IVAL(params,6); - BOOL close_after_request = BITSETW(params+10,0); - BOOL close_if_end = BITSETW(params+10,1); - BOOL requires_resume_key = BITSETW(params+10,2); - BOOL continue_bit = BITSETW(params+10,3); + uint16 findnext_flags = SVAL(params,10); + BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE); + BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); + BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); + BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); pstring resume_name; pstring mask; pstring directory; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 5393dfc755..1444d0e875 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -93,21 +93,44 @@ DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const c DIR *result; START_PROFILE(syscall_opendir); - result = opendir(fname); + result = sys_opendir(fname); END_PROFILE(syscall_opendir); return result; } -struct dirent *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { struct dirent *result; START_PROFILE(syscall_readdir); - result = readdir(dirp); + result = sys_readdir(dirp); END_PROFILE(syscall_readdir); return result; } +void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp, long offset) +{ + START_PROFILE(syscall_seekdir); + sys_seekdir(dirp, offset); + END_PROFILE(syscall_seekdir); +} + +long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +{ + long result; + START_PROFILE(syscall_telldir); + result = sys_telldir(dirp); + END_PROFILE(syscall_telldir); + return result; +} + +void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +{ + START_PROFILE(syscall_rewinddir); + sys_rewinddir(dirp); + END_PROFILE(syscall_rewinddir); +} + int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { int result; @@ -152,7 +175,7 @@ int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *di int result; START_PROFILE(syscall_closedir); - result = closedir(dirp); + result = sys_closedir(dirp); END_PROFILE(syscall_closedir); return result; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 0328558fe8..f30a555900 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -62,6 +62,9 @@ static struct vfs_ops default_vfs = { vfswrap_opendir, vfswrap_readdir, + vfswrap_seekdir, + vfswrap_telldir, + vfswrap_rewinddir, vfswrap_mkdir, vfswrap_rmdir, vfswrap_closedir, @@ -611,13 +614,13 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) char *vfs_readdirname(connection_struct *conn, void *p) { - struct dirent *ptr= NULL; + SMB_STRUCT_DIRENT *ptr= NULL; char *dname; if (!p) return(NULL); - ptr = (struct dirent *)SMB_VFS_READDIR(conn,p); + ptr = SMB_VFS_READDIR(conn,p); if (!ptr) return(NULL); -- cgit From 70696e4c1c6ac475c8feafdf22cf799b2ea16ec8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Nov 2004 19:34:50 +0000 Subject: r3663: Fix too tight checking of incoming secondary trans2 requests. Found by Stefan Esser . Jeremy. (This used to be commit 44132c39ecbf055b897b1aa7bfca4eb1731badbf) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4c0d5731eb..ca2c8a060d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4161,7 +4161,7 @@ int reply_trans2(connection_struct *conn, goto bad_param; if (num_params) { - if (param_disp + num_params >= total_params) + if (param_disp + num_params > total_params) goto bad_param; if ((param_disp + num_params < param_disp) || (param_disp + num_params < num_params)) @@ -4177,7 +4177,7 @@ int reply_trans2(connection_struct *conn, memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params); } if (num_data) { - if (data_disp + num_data >= total_data) + if (data_disp + num_data > total_data) goto bad_param; if ((data_disp + num_data < data_disp) || (data_disp + num_data < num_data)) -- cgit From 17c8907d9c2a89a1f3d271aa58a5d4494a0d4653 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Nov 2004 20:37:14 +0000 Subject: r3666: Generalise fix for trans and nttrans multi-fragment requests. Jeremy (This used to be commit 10b2489e3b2345a8532098523ebcebb73665a76f) --- source3/smbd/ipc.c | 4 ++-- source3/smbd/nttrans.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e5465b902c..35e670c9fa 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -502,7 +502,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int goto bad_param; if (pcnt) { - if (pdisp+pcnt >= tpscnt) + if (pdisp+pcnt > tpscnt) goto bad_param; if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) goto bad_param; @@ -518,7 +518,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if (dcnt) { - if (ddisp+dcnt >= tdscnt) + if (ddisp+dcnt > tdscnt) goto bad_param; if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) goto bad_param; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index eaaf68d689..e20e433abc 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2825,7 +2825,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); } if (parameter_count) { - if (parameter_displacement + parameter_count >= total_parameter_count) + if (parameter_displacement + parameter_count > total_parameter_count) goto bad_param; if ((parameter_displacement + parameter_count < parameter_displacement) || (parameter_displacement + parameter_count < parameter_count)) @@ -2842,7 +2842,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); } if (data_count) { - if (data_displacement + data_count >= total_data_count) + if (data_displacement + data_count > total_data_count) goto bad_param; if ((data_displacement + data_count < data_displacement) || (data_displacement + data_count < data_count)) -- cgit From e87470fa3fa557c3fbf0f59f4c3a91d9a468fa0e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Nov 2004 23:02:48 +0000 Subject: r3670: Warning fixes from Rob Foehl . Jeremy. (This used to be commit 54da75ca4cc27dfb0012fd17047702ec2f39cae9) --- source3/smbd/vfs-wrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 1444d0e875..abc17a37a2 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -100,7 +100,7 @@ DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const c SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { - struct dirent *result; + SMB_STRUCT_DIRENT *result; START_PROFILE(syscall_readdir); result = sys_readdir(dirp); -- cgit From c0cad75f09ad393fc12a5e49abfac17d678c8ff2 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 10 Nov 2004 23:12:02 +0000 Subject: r3673: Do not fail on setting file attributes with acl support enabled. Rolling back r3496 (close #2015). Guenther (This used to be commit e88ac807847bd016f9c921f01f788708b1564b5c) --- source3/smbd/dosmode.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 3a3a6e6fdb..7199b3ebbf 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -344,9 +344,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, return(-1); } - if (!get_acl_group_bits(conn, fname, &st->st_mode)) { - return(-1); - } + get_acl_group_bits(conn, fname, &st->st_mode); if (S_ISDIR(st->st_mode)) dosmode |= aDIR; -- cgit From 4a69011a632fc6c0d2c1a428b5f812dd4e5084a0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Nov 2004 23:43:52 +0000 Subject: r3674: Stefan Esser pointed out that the max data value is only valid on the initial trans/trans2/nttrans request, so if there are secondary requests we can't read it from them. Read it from the initial request and pass as a parameter for those functions that need it. Jeremy. (This used to be commit e007845e67e0604321fb36b216a98e4fca1c98e1) --- source3/smbd/nttrans.c | 37 +++++++++----------- source3/smbd/trans2.c | 94 ++++++++++++++++++++++++-------------------------- 2 files changed, 63 insertions(+), 68 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e20e433abc..4c17396eb4 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1143,7 +1143,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { pstring fname; char *params = *ppparams; @@ -1782,7 +1782,7 @@ int reply_nttranss(connection_struct *conn, static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { char *setup = *ppsetup; files_struct *fsp; @@ -1818,7 +1818,7 @@ name = %s\n", fsp->fsp_name )); static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { char *params = *ppparams; pstring new_name; @@ -1885,9 +1885,8 @@ static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { - uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); char *params = *ppparams; char *data = *ppdata; prs_struct pd; @@ -1997,7 +1996,7 @@ security descriptor.\n")); static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { char *params= *ppparams; char *data = *ppdata; @@ -2038,7 +2037,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { uint32 function; uint16 fidnum; @@ -2115,7 +2114,6 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * Allocate the correct amount and return the pointer to let * it be deallocated when we return. */ - uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); SHADOW_COPY_DATA *shadow_data = NULL; TALLOC_CTX *shadow_mem_ctx = NULL; BOOL labels = False; @@ -2288,10 +2286,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { NTSTATUS nt_status = NT_STATUS_OK; - uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); char *params = *ppparams; char *pdata = *ppdata; char *entry; @@ -2538,7 +2535,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) + char **ppdata, uint32 data_count, uint32 max_data_count) { char *params = *ppparams; char *pdata = *ppdata; @@ -2657,10 +2654,10 @@ int reply_nttrans(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { int outsize = 0; + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); #if 0 /* Not used. */ uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount); - uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); #endif /* Not used. */ uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount); @@ -2871,7 +2868,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_create); break; case NT_TRANSACT_IOCTL: @@ -2880,7 +2877,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_ioctl); break; case NT_TRANSACT_SET_SECURITY_DESC: @@ -2889,7 +2886,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_set_security_desc); break; case NT_TRANSACT_NOTIFY_CHANGE: @@ -2898,7 +2895,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_notify_change); break; case NT_TRANSACT_RENAME: @@ -2907,7 +2904,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_rename); break; @@ -2917,7 +2914,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_query_security_desc); break; #ifdef HAVE_SYS_QUOTAS @@ -2927,7 +2924,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_get_user_quota); break; case NT_TRANSACT_SET_USER_QUOTA: @@ -2936,7 +2933,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); length, bufsize, &setup, setup_count, ¶ms, total_parameter_count, - &data, total_data_count); + &data, total_data_count, max_data_count); END_PROFILE_NESTED(NT_transact_set_user_quota); break; #endif /* HAVE_SYS_QUOTAS */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ca2c8a060d..b61839df07 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -584,7 +584,8 @@ static int send_trans2_replies(char *outbuf, ****************************************************************************/ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; int16 open_mode; @@ -1317,14 +1318,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, ****************************************************************************/ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { /* We must be careful here that we don't return more than the allowed number of data bytes. If this means returning fewer than maxentries then so be it. We assume that the redirector has enough room for the fixed number of parameter bytes it has requested. */ - uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *params = *pparams; char *pdata = *ppdata; int dirtype = SVAL(params,0); @@ -1542,14 +1543,14 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", ****************************************************************************/ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { /* We must be careful here that we don't return more than the allowed number of data bytes. If this means returning fewer than maxentries then so be it. We assume that the redirector has enough room for the fixed number of parameter bytes it has requested. */ - int max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *params = *pparams; char *pdata = *ppdata; int dptr_num = SVAL(params,0); @@ -1809,11 +1810,10 @@ resume_key = %d resume name = %s continue=%d level = %d\n", Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ -static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, - int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { - int max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *pdata = *ppdata; char *params = *pparams; uint16 info_level = SVAL(params,0); @@ -2117,9 +2117,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned Reply to a TRANS2_SETFSINFO (set filesystem info). ****************************************************************************/ -static int call_trans2setfsinfo(connection_struct *conn, - char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { char *pdata = *ppdata; char *params = *pparams; @@ -2250,12 +2250,10 @@ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint file name or file id). ****************************************************************************/ -static int call_trans2qfilepathinfo(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { - int max_data_bytes = SVAL(inbuf, smb_mdrcnt); char *params = *pparams; char *pdata = *ppdata; uint16 tran_call = SVAL(inbuf, smb_setup0); @@ -2983,9 +2981,9 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam Reply to a TRANS2_SETFILEINFO (set file info by fileid). ****************************************************************************/ -static int call_trans2setfilepathinfo(connection_struct *conn, - char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; @@ -3735,9 +3733,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", Reply to a TRANS2_MKDIR (make directory with extended attributes). ****************************************************************************/ -static int call_trans2mkdir(connection_struct *conn, - char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; pstring directory; @@ -3789,9 +3787,9 @@ static int call_trans2mkdir(connection_struct *conn, We don't actually do this - we just send a null response. ****************************************************************************/ -static int call_trans2findnotifyfirst(connection_struct *conn, - char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { static uint16 fnf_handle = 257; char *params = *pparams; @@ -3836,9 +3834,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, changes). Currently this does nothing. ****************************************************************************/ -static int call_trans2findnotifynext(connection_struct *conn, - char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; @@ -3862,9 +3860,9 @@ static int call_trans2findnotifynext(connection_struct *conn, Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele . ****************************************************************************/ -static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, - char* outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; pstring pathname; @@ -3898,9 +3896,9 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, Reply to a TRANS2_IOCTL - used for OS/2 printing. ****************************************************************************/ -static int call_trans2ioctl(connection_struct *conn, char* inbuf, - char* outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data) +static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) { char *pdata = *ppdata; files_struct *fsp = file_fsp(inbuf,smb_vwv15); @@ -4004,9 +4002,9 @@ int reply_trans2(connection_struct *conn, int outsize = 0; unsigned int total_params = SVAL(inbuf, smb_tpscnt); unsigned int total_data =SVAL(inbuf, smb_tdscnt); + unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt); #if 0 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt); - unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt); unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt); BOOL close_tid = BITSETW(inbuf+smb_flags,0); BOOL no_final_response = BITSETW(inbuf+smb_flags,1); @@ -4204,28 +4202,28 @@ int reply_trans2(connection_struct *conn, case TRANSACT2_OPEN: START_PROFILE_NESTED(Trans2_open); outsize = call_trans2open(conn, inbuf, outbuf, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_open); break; case TRANSACT2_FINDFIRST: START_PROFILE_NESTED(Trans2_findfirst); outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_findfirst); break; case TRANSACT2_FINDNEXT: START_PROFILE_NESTED(Trans2_findnext); outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_findnext); break; case TRANSACT2_QFSINFO: START_PROFILE_NESTED(Trans2_qfsinfo); outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_qfsinfo); break; @@ -4233,7 +4231,7 @@ int reply_trans2(connection_struct *conn, case TRANSACT2_SETFSINFO: START_PROFILE_NESTED(Trans2_setfsinfo); outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_setfsinfo); break; #endif @@ -4241,47 +4239,47 @@ int reply_trans2(connection_struct *conn, case TRANSACT2_QFILEINFO: START_PROFILE_NESTED(Trans2_qpathinfo); outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_qpathinfo); break; case TRANSACT2_SETPATHINFO: case TRANSACT2_SETFILEINFO: START_PROFILE_NESTED(Trans2_setpathinfo); outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_setpathinfo); break; case TRANSACT2_FINDNOTIFYFIRST: START_PROFILE_NESTED(Trans2_findnotifyfirst); outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_findnotifyfirst); break; case TRANSACT2_FINDNOTIFYNEXT: START_PROFILE_NESTED(Trans2_findnotifynext); outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_findnotifynext); break; case TRANSACT2_MKDIR: START_PROFILE_NESTED(Trans2_mkdir); outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_mkdir); break; case TRANSACT2_GET_DFS_REFERRAL: START_PROFILE_NESTED(Trans2_get_dfs_referral); outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_get_dfs_referral); break; case TRANSACT2_IOCTL: START_PROFILE_NESTED(Trans2_ioctl); outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize, - ¶ms, total_params, &data, total_data); + ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_ioctl); break; default: -- cgit From a4fab4d51a1c201810414a5b21b9d7bec4442646 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 11 Nov 2004 17:40:49 +0000 Subject: r3682: fix seg fault in lanman printing code caused by uninitialized variable (This used to be commit c52e663c4a32b975796383834b2c04796daf8f29) --- source3/smbd/lanman.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 610ee45120..e7aa05b54a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2267,6 +2267,12 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha return False; *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); + + if ( (snum = lp_servicenumber(sharename)) == -1 ) { + DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n", + sharename)); + return False; + } *rdata_len = 0; -- cgit From ecd1b0fffd414b7b6e28a741e9367eb92dd031d4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Nov 2004 02:16:00 +0000 Subject: r3693: Correctly detect errno for no acl/ea support. Jeremy (This used to be commit 089a76f611187e2ba4c3363b657905d04576109e) --- source3/smbd/posix_acls.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index be7f828b67..0ba4437303 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -245,7 +245,7 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ SAFE_FREE(pai_buf); DEBUG(10,("store_inheritance_attribute:%s for file %s\n", protected ? " (protected)" : "", fsp->fsp_name)); - if (ret == -1 && errno != ENOSYS) + if (ret == -1 && !no_acl_syscall_error(errno)) DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) )); } @@ -2243,7 +2243,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (the_acl == NULL) { - if (errno != ENOSYS) { + if (!no_acl_syscall_error(errno)) { /* * Only print this error message if we have some kind of ACL * support that's not working. Otherwise we would always get this. @@ -2408,13 +2408,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. */ - if (errno == ENOSYS) + if (no_acl_syscall_error(errno)) { *pacl_set_support = False; - -#ifdef ENOTSUP - if (errno == ENOTSUP) - *pacl_set_support = False; -#endif + } DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", @@ -2427,13 +2423,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. */ - if (errno == ENOSYS) + if (no_acl_syscall_error(errno)) { *pacl_set_support = False; - -#ifdef ENOTSUP - if (errno == ENOTSUP) - *pacl_set_support = False; -#endif + } DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); -- cgit From f9e87b9ba65f37bafa45eacb1a6c9b8c5483d46b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 12 Nov 2004 15:49:47 +0000 Subject: r3705: Nobody has commented, so I'll take this as an ack... abartlet, I'd like to ask you to take a severe look at this! We have solved the problem to find the global groups a user is in twice: Once in auth_util.c and another time for the corresponding samr call. The attached patch unifies these and sends them through the passdb backend (new function pdb_enum_group_memberships). Thus it gives pdb_ldap.c the chance to further optimize the corresponding call if the samba and posix accounts are unified by issuing a specialized ldap query. The parameter to activate this ldapsam behaviour is ldapsam:trusted = yes Volker (This used to be commit b94838aff1a009f8d8c2c3efd48756a5b8f3f989) --- source3/smbd/lanman.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e7aa05b54a..1379877efc 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1741,13 +1741,15 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para int count=0; SAM_ACCOUNT *sampw = NULL; BOOL ret = False; - DOM_GID *gids = NULL; - int num_groups = 0; + DOM_SID *sids; + gid_t *gids; + int num_groups; int i; fstring grp_domain; fstring grp_name; enum SID_NAME_USE grp_type; - DOM_SID sid, dom_sid; + struct passwd *passwd; + NTSTATUS result; *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); @@ -1778,6 +1780,11 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para /* Lookup the user information; This should only be one of our accounts (not remote domains) */ + + passwd = getpwnam_alloc(UserName); + + if (passwd == NULL) + return False; pdb_init_sam( &sampw ); @@ -1786,35 +1793,26 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para if ( !pdb_getsampwnam(sampw, UserName) ) goto out; - /* this next set of code is horribly inefficient, but since - it is rarely called, I'm going to leave it like this since - it easier to follow --jerry */ - - /* get the list of group SIDs */ - - if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) { - DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n")); + sids = NULL; + num_groups = 0; + + result = pdb_enum_group_memberships(pdb_get_username(sampw), + passwd->pw_gid, + &sids, &gids, &num_groups); + + if (!NT_STATUS_IS_OK(result)) goto out; - } - /* convert to names (we don't support universal groups so the domain - can only be ours) */ - - sid_copy( &dom_sid, get_global_sam_sid() ); for (i=0; i Date: Fri, 12 Nov 2004 17:39:32 +0000 Subject: r3708: BUG 1838: patch from Gavrie Philipson to remove stale printers when reloading after a sighup (This used to be commit bcb9105c5488a97944d2dfee8681d662e9c9b818) --- source3/smbd/server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 82da85767b..e40d1f8bc7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -482,9 +482,10 @@ BOOL reload_services(BOOL test) return(True); lp_killunused(conn_snum_used); - + ret = lp_load(dyn_CONFIGFILE, False, False, True); + remove_stale_printers(); load_printers(); /* perhaps the config filename is now set */ -- cgit From f995b164b98221e224661e370d61ad08dadb2986 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Nov 2004 23:42:12 +0000 Subject: r3713: Implementation of get posix acls in UNIX extensions. Passes valgrind. Need to add printout functions in client and set posix acl in server. SteveF - take a look at this for the cifsfs client ! Once this is working and tested the next step is to write this up for the UNIX extensions spec. documents. Jeremy. (This used to be commit 1bd3f133442a472b4718b94a636f2fec89a2e0dc) --- source3/smbd/trans2.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 194 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b61839df07..a129227215 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2086,7 +2086,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned data_len = 12; SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); - SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */ + SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */ break; case SMB_MAC_QUERY_FS_INFO: @@ -2227,8 +2227,8 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb #endif /* HAVE_SYS_QUOTAS */ /**************************************************************************** - * Utility function to set bad path error. - ****************************************************************************/ + Utility function to set bad path error. +****************************************************************************/ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code) { @@ -2245,6 +2245,120 @@ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint return UNIXERROR(def_class,def_code); } +/**************************************************************************** + Utility function to count the number of entries in a POSIX acl. +****************************************************************************/ + +static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl) +{ + unsigned int ace_count = 0; + int entry_id = SMB_ACL_FIRST_ENTRY; + SMB_ACL_ENTRY_T entry; + + while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) { + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) { + entry_id = SMB_ACL_NEXT_ENTRY; + } + ace_count++; + } + return ace_count; +} + +/**************************************************************************** + Utility function to marshall a POSIX acl into wire format. +****************************************************************************/ + +static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl) +{ + int entry_id = SMB_ACL_FIRST_ENTRY; + SMB_ACL_ENTRY_T entry; + + while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; + unsigned char perms = 0; + unsigned int own_grp; + + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) { + entry_id = SMB_ACL_NEXT_ENTRY; + } + + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) { + DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n")); + return False; + } + + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { + DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n")); + return False; + } + + perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0); + perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0); + perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0); + + SCVAL(pdata,1,perms); + + switch (tagtype) { + case SMB_ACL_USER_OBJ: + SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ); + own_grp = (unsigned int)pst->st_uid; + SIVAL(pdata,2,own_grp); + SIVAL(pdata,6,0); + break; + case SMB_ACL_USER: + { + uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + if (!puid) { + DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n")); + } + own_grp = (unsigned int)*puid; + SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); + SCVAL(pdata,0,SMB_POSIX_ACL_USER); + SIVAL(pdata,2,own_grp); + SIVAL(pdata,6,0); + break; + } + case SMB_ACL_GROUP_OBJ: + SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ); + own_grp = (unsigned int)pst->st_gid; + SIVAL(pdata,2,own_grp); + SIVAL(pdata,6,0); + break; + case SMB_ACL_GROUP: + { + gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + if (!pgid) { + DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n")); + } + own_grp = (unsigned int)*pgid; + SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype); + SCVAL(pdata,0,SMB_POSIX_ACL_GROUP); + SIVAL(pdata,2,own_grp); + SIVAL(pdata,6,0); + break; + } + case SMB_ACL_MASK: + SCVAL(pdata,0,SMB_POSIX_ACL_MASK); + SIVAL(pdata,2,0xFFFFFFFF); + SIVAL(pdata,6,0xFFFFFFFF); + break; + case SMB_ACL_OTHER: + SCVAL(pdata,0,SMB_POSIX_ACL_OTHER); + SIVAL(pdata,2,0xFFFFFFFF); + SIVAL(pdata,6,0xFFFFFFFF); + break; + default: + DEBUG(0,("marshall_posix_acl: unknown tagtype.\n")); + return False; + } + } + + return True; +} + /**************************************************************************** Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by file name or file id). @@ -2800,6 +2914,83 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * break; } + case SMB_QUERY_POSIX_ACL: + { + SMB_ACL_T file_acl = NULL; + SMB_ACL_T dir_acl = NULL; + uint16 num_file_acls = 0; + uint16 num_dir_acls = 0; + + if (fsp && !fsp->is_directory && (fsp->fd != -1)) { + file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); + } else { + file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS); + } + + if (file_acl == NULL && no_acl_syscall_error(errno)) { + DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n", + fname )); + return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED); + } + + if (S_ISDIR(sbuf.st_mode)) { + if (fsp && fsp->is_directory) { + dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + } else { + dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT); + } + dir_acl = free_empty_sys_acl(conn, dir_acl); + } + + num_file_acls = count_acl_entries(conn, file_acl); + num_dir_acls = count_acl_entries(conn, dir_acl); + + if ( data_size < (num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) { + DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n", + data_size, + (unsigned int)((num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + + SMB_POSIX_ACL_HEADER_SIZE) )); + if (file_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + } + if (dir_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + } + return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); + } + + SSVAL(pdata,0,SMB_POSIX_ACL_VERSION); + SSVAL(pdata,2,num_file_acls); + SSVAL(pdata,4,num_dir_acls); + if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) { + if (file_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + } + if (dir_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + } + return ERROR_NT(NT_STATUS_INTERNAL_ERROR); + } + if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, dir_acl)) { + if (file_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + } + if (dir_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + } + return ERROR_NT(NT_STATUS_INTERNAL_ERROR); + } + + if (file_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + } + if (dir_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + } + data_size = (num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE; + break; + } + default: return ERROR_DOS(ERRDOS,ERRunknownlevel); } -- cgit From 1b31f46f22831781b9ec5592da189a5210cfbc45 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Nov 2004 00:35:31 +0000 Subject: r3714: Getfacl now seems to work on files and directories. Next do setfacl and port to Samba4. Jeremy. (This used to be commit 4d52bf7c8b3147dd4f0d3081fbf9a1f5ebd246a1) --- source3/smbd/trans2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a129227215..c401ae5722 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2354,6 +2354,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ DEBUG(0,("marshall_posix_acl: unknown tagtype.\n")); return False; } + pdata += SMB_POSIX_ACL_ENTRY_SIZE; } return True; -- cgit From 6192b3121f36ce23dbcbf51209014cc37aa6d49d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Nov 2004 01:35:35 +0000 Subject: r3794: Added set posix acl functionality into the UNIX extensions code. One part missing - delete file acl (to be added asap). No client code yet, also needs testing with valgrind. Jeremy. (This used to be commit 6101ec2247c182fde6ea3e7e1f64a92b353ec4e8) --- source3/smbd/posix_acls.c | 241 ++++++++++++++++++++++++++++++++++++++++++++-- source3/smbd/trans2.c | 38 ++++++++ 2 files changed, 273 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0ba4437303..c650243f23 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3373,14 +3373,243 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { - SMB_ACL_T dir_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); - BOOL has_acl = False; - SMB_ACL_ENTRY_T entry; + SMB_ACL_T dir_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); + BOOL has_acl = False; + SMB_ACL_ENTRY_T entry; - if (dir_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) - has_acl = True; + if (dir_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { + has_acl = True; + } - if (dir_acl) + if (dir_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + } return has_acl; } + +/**************************************************************************** + Map from wire type to permset. +****************************************************************************/ + +static BOOL unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset) +{ + if (wire_perm & ~(SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE)) { + return False; + } + + if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1) { + return False; + } + + if (wire_perm & SMB_POSIX_ACL_READ) { + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) { + return False; + } + } + if (wire_perm & SMB_POSIX_ACL_WRITE) { + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) { + return False; + } + } + if (wire_perm & SMB_POSIX_ACL_EXECUTE) { + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) { + return False; + } + } + return True; +} + +/**************************************************************************** + Map from wire type to tagtype. +****************************************************************************/ + +static BOOL unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt) +{ + switch (wire_tt) { + case SMB_POSIX_ACL_USER_OBJ: + *p_tt = SMB_ACL_USER_OBJ; + break; + case SMB_POSIX_ACL_USER: + *p_tt = SMB_ACL_USER; + break; + case SMB_POSIX_ACL_GROUP_OBJ: + *p_tt = SMB_ACL_GROUP_OBJ; + break; + case SMB_POSIX_ACL_GROUP: + *p_tt = SMB_ACL_GROUP; + break; + case SMB_POSIX_ACL_MASK: + *p_tt = SMB_ACL_MASK; + break; + case SMB_POSIX_ACL_OTHER: + *p_tt = SMB_ACL_OTHER; + break; + default: + return False; + } + return True; +} + +/**************************************************************************** + Create a new POSIX acl from wire permissions. +****************************************************************************/ + +static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_acls, const char *pdata) +{ + unsigned int i; + SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, num_acls); + + if (the_acl == NULL) { + return NULL; + } + + for (i = 0; i < num_acls; i++) { + SMB_ACL_ENTRY_T the_entry; + SMB_ACL_PERMSET_T the_permset; + SMB_ACL_TAG_T tag_type; + + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) { + DEBUG(0,("create_posix_acl_from_wire: Failed to create entry %u. (%s)\n", + i, strerror(errno) )); + goto fail; + } + + if (!unix_ex_wire_to_tagtype(CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), &tag_type)) { + DEBUG(0,("create_posix_acl_from_wire: invalid wire tagtype %u on entry %u.\n", + CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), i )); + goto fail; + } + + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, tag_type) == -1) { + DEBUG(0,("create_posix_acl_from_wire: Failed to set tagtype on entry %u. (%s)\n", + i, strerror(errno) )); + goto fail; + } + + if (!unix_ex_wire_to_permset(conn, CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+1), &the_permset)) { + DEBUG(0,("create_posix_acl_from_wire: invalid permset %u on entry %u.\n", + CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE) + 1), i )); + goto fail; + } + + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) { + DEBUG(0,("create_posix_acl_from_wire: Failed to add permset on entry %u. (%s)\n", + i, strerror(errno) )); + goto fail; + } + + if (tag_type == SMB_ACL_USER) { + uint32 uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2); + uid_t uid = (uid_t)uidval; + if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&uid) == -1) { + DEBUG(0,("create_posix_acl_from_wire: Failed to set uid %u on entry %u. (%s)\n", + (unsigned int)uid, i, strerror(errno) )); + goto fail; + } + } + + if (tag_type == SMB_ACL_GROUP) { + uint32 gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2); + gid_t gid = (uid_t)gidval; + if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&gid) == -1) { + DEBUG(0,("create_posix_acl_from_wire: Failed to set gid %u on entry %u. (%s)\n", + (unsigned int)gid, i, strerror(errno) )); + goto fail; + } + } + } + + return the_acl; + + fail: + + if (the_acl != NULL) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); + } + return NULL; +} + +/**************************************************************************** + Calls from UNIX extensions - Default POSIX ACL set. + If num_dir_acls == 0 and not a directory just return. If it is a directory + and num_dir_acls == 0 then remove the default acl. Else set the default acl + on the directory. +****************************************************************************/ + +BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, + uint16 num_dir_acls, const char *pdata) +{ + SMB_ACL_T dir_acl = NULL; + + if (num_dir_acls && !S_ISDIR(psbuf->st_mode)) { + DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname )); + errno = EISDIR; + return False; + } + + if (!num_dir_acls) { + /* Remove the default ACL. */ + if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) { + DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n", + fname, strerror(errno) )); + return False; + } + return True; + } + + if ((dir_acl = create_posix_acl_from_wire(conn, num_dir_acls, pdata)) == NULL) { + return False; + } + + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, dir_acl) == -1) { + DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n", + fname, strerror(errno) )); + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + return False; + } + + DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname )); + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + return True; +} + +/**************************************************************************** + Calls from UNIX extensions - POSIX ACL set. + If num_dir_acls == 0 then read/modify/write acl after removing all entries + except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER. +****************************************************************************/ + +BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata) +{ + SMB_ACL_T file_acl = NULL; + + if (!num_acls) { + /* TODO !!! */ + /* Remove the default ACL. */ + } + + if ((file_acl = create_posix_acl_from_wire(conn, num_acls, pdata)) == NULL) { + return False; + } + + if (fsp && fsp->fd != -1) { + /* The preferred way - use an open fd. */ + if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fd, file_acl) == -1) { + DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n", + fname, strerror(errno) )); + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + return False; + } + } else { + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, file_acl) == -1) { + DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n", + fname, strerror(errno) )); + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + return False; + } + } + + DEBUG(10,("set_unix_posix_acl: set acl for file %s\n", fname )); + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + return True; +} diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c401ae5722..931b58f389 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3799,6 +3799,44 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); } + + case SMB_SET_POSIX_ACL: + { + uint16 posix_acl_version; + uint16 num_file_acls; + uint16 num_dir_acls; + + if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + } + posix_acl_version = SVAL(pdata,0); + num_file_acls = SVAL(pdata,2); + num_dir_acls = SVAL(pdata,4); + + if (posix_acl_version != SMB_POSIX_ACL_VERSION) { + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + } + + if (total_data < SMB_POSIX_ACL_HEADER_SIZE + + (num_file_acls+num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + } + + if (!set_unix_posix_default_acl(conn, fname, &sbuf, num_dir_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE + + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if (!set_unix_posix_acl(conn, fsp, fname, num_file_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE)) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + default: return ERROR_DOS(ERRDOS,ERRunknownlevel); } -- cgit From 99dd85abe9b96ee78421430f837c97703f09be0f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Nov 2004 15:56:47 +0000 Subject: r3811: Believe it or not, but this patch seems to be necessary. If someone sets a folder icon in the start menu and saves the profile on a samba server, after logging in again this setting is gone. Why is this? The folder for which the icon is set must have the read only flag set. If it is not set, the desktop.ini file (the file containing the icon reference) inside that folder is ignored. lp_profile_acls is a hack for such a situation, so overload this parameter with another profile-related hack. Volker (This used to be commit b8d888000eb7456c7620e9a783d6f1b3ba4c8985) --- source3/smbd/trans2.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 931b58f389..31a3961550 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -963,8 +963,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, adate &= ~1; } - if(mode & aDIR) + if(mode & aDIR) { + /* This is necessary, as otherwise the + * desktop.ini file in this folder is + * ignored */ + mode |= (lp_profile_acls(SNUM(conn)) ? 1 : 0); file_size = 0; + } DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); @@ -2507,8 +2512,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * fullpathname = fname; file_size = get_file_size(sbuf); allocation_size = get_allocation_size(fsp,&sbuf); - if (mode & aDIR) + if (mode & aDIR) { + /* This is necessary, as otherwise the desktop.ini file in + * this folder is ignored */ + mode |= (lp_profile_acls(SNUM(conn)) ? 1 : 0); file_size = 0; + } params = Realloc(*pparams,2); if (params == NULL) -- cgit From 672b22ae43682b752a6af1b8aabf996a9823e4b8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Nov 2004 17:51:27 +0000 Subject: r3814: At least use a proper constant name (aRONLY :-) not a number. That way we can at least remember why we did this :-). Jeremy. (This used to be commit d84f5f8cc10f89d5fbd6cfb694bccfbd1c3d8a3f) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 31a3961550..afe4d352ff 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -967,7 +967,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, /* This is necessary, as otherwise the * desktop.ini file in this folder is * ignored */ - mode |= (lp_profile_acls(SNUM(conn)) ? 1 : 0); + mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0); file_size = 0; } @@ -2515,7 +2515,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (mode & aDIR) { /* This is necessary, as otherwise the desktop.ini file in * this folder is ignored */ - mode |= (lp_profile_acls(SNUM(conn)) ? 1 : 0); + mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0); file_size = 0; } -- cgit From 7eaba1f52881b8595ca2cfe750cf5d6c62de4cda Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Nov 2004 18:56:48 +0000 Subject: r3816: Added fn to remove an ACL from a file. Now need client code to test this. How do the share mask/modes fit into this code... Need to think about this. Jeremy. (This used to be commit 1aa1c2f489f5b92c3696e7b9123061d91babc34e) --- source3/smbd/posix_acls.c | 130 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c650243f23..9b7c39c00e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3452,6 +3452,7 @@ static BOOL unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt) /**************************************************************************** Create a new POSIX acl from wire permissions. + FIXME ! How does the share mask/mode fit into this.... ? ****************************************************************************/ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_acls, const char *pdata) @@ -3573,6 +3574,131 @@ BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_ return True; } +/**************************************************************************** + Remove an ACL from a file. As we don't have acl_delete_entry() available + we must read the current acl and copy all entries except MASK, USER and GROUP + to a new acl, then set that. This (at least on Linux) causes any ACL to be + removed. + FIXME ! How does the share mask/mode fit into this.... ? +****************************************************************************/ + +static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname) +{ + SMB_ACL_T file_acl = NULL; + int entry_id = SMB_ACL_FIRST_ENTRY; + SMB_ACL_ENTRY_T entry; + BOOL ret = False; + /* Create a new ACL with only 3 entries, u/g/w. */ + SMB_ACL_T new_file_acl = SMB_VFS_SYS_ACL_INIT(conn, 3); + SMB_ACL_ENTRY_T user_ent = NULL; + SMB_ACL_ENTRY_T group_ent = NULL; + SMB_ACL_ENTRY_T other_ent = NULL; + + if (new_file_acl == NULL) { + DEBUG(5,("remove_posix_acl: failed to init new ACL with 3 entries for file %s.\n", fname)); + return False; + } + + /* Now create the u/g/w entries. */ + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &user_ent) == -1) { + DEBUG(5,("remove_posix_acl: Failed to create user entry for file %s. (%s)\n", + fname, strerror(errno) )); + goto done; + } + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, user_ent, SMB_ACL_USER_OBJ) == -1) { + DEBUG(5,("remove_posix_acl: Failed to set user entry for file %s. (%s)\n", + fname, strerror(errno) )); + goto done; + } + + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &group_ent) == -1) { + DEBUG(5,("remove_posix_acl: Failed to create group entry for file %s. (%s)\n", + fname, strerror(errno) )); + goto done; + } + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, group_ent, SMB_ACL_GROUP_OBJ) == -1) { + DEBUG(5,("remove_posix_acl: Failed to set group entry for file %s. (%s)\n", + fname, strerror(errno) )); + goto done; + } + + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &other_ent) == -1) { + DEBUG(5,("remove_posix_acl: Failed to create other entry for file %s. (%s)\n", + fname, strerror(errno) )); + goto done; + } + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, other_ent, SMB_ACL_OTHER) == -1) { + DEBUG(5,("remove_posix_acl: Failed to set other entry for file %s. (%s)\n", + fname, strerror(errno) )); + goto done; + } + + /* Get the current file ACL. */ + if (fsp && fsp->fd != -1) { + file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); + } else { + file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS); + } + + if (file_acl == NULL) { + /* This is only returned if an error occurred. Even for a file with + no acl a u/g/w acl should be returned. */ + DEBUG(5,("remove_posix_acl: failed to get ACL from file %s (%s).\n", + fname, strerror(errno) )); + goto done; + } + + while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, file_acl, entry_id, &entry) == 1) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; + + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) + entry_id = SMB_ACL_NEXT_ENTRY; + + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) { + DEBUG(5,("remove_posix_acl: failed to get tagtype from ACL on file %s (%s).\n", + fname, strerror(errno) )); + goto done; + } + + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { + DEBUG(5,("remove_posix_acl: failed to get permset from ACL on file %s (%s).\n", + fname, strerror(errno) )); + goto done; + } + + if (tagtype == SMB_ACL_USER_OBJ) { + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, user_ent, permset) == -1) { + DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n", + fname, strerror(errno) )); + } + } else if (tagtype == SMB_ACL_GROUP_OBJ) { + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, group_ent, permset) == -1) { + DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n", + fname, strerror(errno) )); + } + } else if (tagtype == SMB_ACL_OTHER) { + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, other_ent, permset) == -1) { + DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n", + fname, strerror(errno) )); + } + } + } + + ret = True; + + done: + + if (file_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); + } + if (new_file_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, new_file_acl); + } + return ret; +} + /**************************************************************************** Calls from UNIX extensions - POSIX ACL set. If num_dir_acls == 0 then read/modify/write acl after removing all entries @@ -3584,8 +3710,8 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * SMB_ACL_T file_acl = NULL; if (!num_acls) { - /* TODO !!! */ - /* Remove the default ACL. */ + /* Remove the ACL from the file. */ + return remove_posix_acl(conn, fsp, fname); } if ((file_acl = create_posix_acl_from_wire(conn, num_acls, pdata)) == NULL) { -- cgit From d12a7fdee2d7267ea9b9d7b5b3359015258ace4e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Nov 2004 19:52:26 +0000 Subject: r3817: Fix from Lars Müller for bug #2050, calculate max_fd for select correctly. Jeremy. (This used to be commit eb0b1f757d814e01980cd9c5fc4918791ce1e54d) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/server.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e40d1f8bc7..5f2713bb83 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -186,6 +186,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; + int max_fd = 0; int i; char *ports; @@ -241,11 +242,16 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) { unsigned port = atoi(tok); - if (port == 0) continue; + if (port == 0) { + continue; + } s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); if(s == -1) return False; + if (max_fd < s) + max_fd = s; + /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); @@ -335,7 +341,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select(FD_SETSIZE,&lfds,NULL,NULL,NULL); + num = sys_select(max_fd+1,&lfds,NULL,NULL,NULL); if (num == -1 && errno == EINTR) { if (got_sig_term) { -- cgit From 00f6baa15ae29e04f8d298dd5bbb81719cc912a7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Nov 2004 21:05:47 +0000 Subject: r3823: Fix bug reported by Tom Dickson with follow symlinks = no reporting an incorrect error when it should be access denied. Jeremy. (This used to be commit 5a103f4abff0503740822c8ed75d9102ee51e8f0) --- source3/smbd/vfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f30a555900..10599c50a1 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -897,7 +897,8 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) } default: DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname)); - errno = saved_errno; + /* Don't restore the saved errno. We need to return the error that + realpath caused here as it was not one of the cases we handle. JRA. */ return False; } } -- cgit From 0c639097cf033b25c956222c72622e6b97695f59 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Nov 2004 21:22:35 +0000 Subject: r3824: Fix crash in api_RNetShareEnum. ServicePtrs[] may contain invalid entries. Happened after rev3708 removed non-existing cups printers. Volker (This used to be commit 60998d9d2f6272e383304da2b1d568a4b65f8787) --- source3/smbd/lanman.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 1379877efc..aeea9de9ca 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1502,6 +1502,8 @@ static BOOL api_RNetShareEnum( connection_struct *conn, data_len = fixed_len = string_len = 0; for (i=0;i Date: Thu, 18 Nov 2004 15:13:58 +0000 Subject: r3848: Fix for bug 2057. Only partially applied the patch, the second part seems not necessary. I'm using gcc 3.4.1, this does not detect the possibly uninitialized variable. Does anybody know how to get 3.4.1 to warn me? Volker (This used to be commit 8b6f8f93a0f30be0184e6044a499c1ef8f7b247e) --- source3/smbd/lanman.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index aeea9de9ca..5f4c0cec52 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2146,6 +2146,12 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param goto out; } + snum = lp_servicenumber( sharename); + if (snum == -1) { + errcode = NERR_DestNotFound; + goto out; + } + errcode = NERR_notsupported; switch (function) { @@ -2971,6 +2977,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; + snum = lp_servicenumber( sharename); if (snum < 0 || !VALID_SNUM(snum)) return(False); count = print_queue_status(snum,&queue,&status); -- cgit From ea9f97886b8b76bc0d74f10eb7dfa53323b7e159 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 18 Nov 2004 16:14:13 +0000 Subject: r3853: Fix an uninitialized variable warning. Jeremy, there are some of these in charcnv.c. Volker (This used to be commit 650d52648dbf67f71d7619ffb8bf32d93a15ae9c) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 55970493fa..1b5ba1228f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1376,6 +1376,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", (*Access) = open_mode; } + action = 0; + if (file_existed && !(flags2 & O_TRUNC)) action = FILE_WAS_OPENED; if (file_existed && (flags2 & O_TRUNC)) -- cgit From 2f167e909e08aac3b5ef7e20fe1b264f3c90382f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Nov 2004 19:36:50 +0000 Subject: r3859: Ensure if num_acls is set to 0xFFFF this field is ignored. Use def_acl everywhere instead of dir_acl. Jeremy. (This used to be commit d28611c960f87830aa8449725951984aa155b089) --- source3/smbd/posix_acls.c | 56 +++++++++++++++++++-------------------- source3/smbd/trans2.c | 67 ++++++++++++++++++++++++++++------------------- 2 files changed, 68 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9b7c39c00e..7e20313b76 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2638,10 +2638,10 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) size_t sd_size = 0; SEC_ACL *psa = NULL; size_t num_acls = 0; - size_t num_dir_acls = 0; + size_t num_def_acls = 0; size_t num_aces = 0; SMB_ACL_T posix_acl = NULL; - SMB_ACL_T dir_acl = NULL; + SMB_ACL_T def_acl = NULL; canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; size_t num_profile_acls = 0; @@ -2669,8 +2669,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) */ if(fsp->is_directory) { - dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); - dir_acl = free_empty_sys_acl(conn, dir_acl); + def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + def_acl = free_empty_sys_acl(conn, def_acl); } } else { @@ -2687,7 +2687,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", posix_acl ? "present" : "absent", - dir_acl ? "present" : "absent" )); + def_acl ? "present" : "absent" )); pal = load_inherited_info(fsp); @@ -2725,8 +2725,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) return 0; } - if (fsp->is_directory && dir_acl) { - dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, + if (fsp->is_directory && def_acl) { + dir_ace = canonicalise_acl(fsp, def_acl, &sbuf, &global_sid_Creator_Owner, &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT ); } @@ -2790,15 +2790,15 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } num_acls = count_canon_ace_list(file_ace); - num_dir_acls = count_canon_ace_list(dir_ace); + num_def_acls = count_canon_ace_list(dir_ace); /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_def_acls)* sizeof(SEC_ACE))) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); goto done; } - memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(SEC_ACE) ); /* * Create the NT ACE list from the canonical ace lists. @@ -2824,7 +2824,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) ace = dir_ace; - for (i = 0; i < num_dir_acls; i++, ace = ace->next) { + for (i = 0; i < num_def_acls; i++, ace = ace->next) { SEC_ACCESS acc; acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); @@ -2894,8 +2894,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) if (posix_acl) SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); - if (dir_acl) - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); free_inherited_info(pal); @@ -3373,16 +3373,16 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { - SMB_ACL_T dir_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); + SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); BOOL has_acl = False; SMB_ACL_ENTRY_T entry; - if (dir_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { + if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { has_acl = True; } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return has_acl; } @@ -3532,23 +3532,23 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_ /**************************************************************************** Calls from UNIX extensions - Default POSIX ACL set. - If num_dir_acls == 0 and not a directory just return. If it is a directory - and num_dir_acls == 0 then remove the default acl. Else set the default acl + If num_def_acls == 0 and not a directory just return. If it is a directory + and num_def_acls == 0 then remove the default acl. Else set the default acl on the directory. ****************************************************************************/ BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, - uint16 num_dir_acls, const char *pdata) + uint16 num_def_acls, const char *pdata) { - SMB_ACL_T dir_acl = NULL; + SMB_ACL_T def_acl = NULL; - if (num_dir_acls && !S_ISDIR(psbuf->st_mode)) { + if (num_def_acls && !S_ISDIR(psbuf->st_mode)) { DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname )); errno = EISDIR; return False; } - if (!num_dir_acls) { + if (!num_def_acls) { /* Remove the default ACL. */ if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) { DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n", @@ -3558,19 +3558,19 @@ BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_ return True; } - if ((dir_acl = create_posix_acl_from_wire(conn, num_dir_acls, pdata)) == NULL) { + if ((def_acl = create_posix_acl_from_wire(conn, num_def_acls, pdata)) == NULL) { return False; } - if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, dir_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) { DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n", fname, strerror(errno) )); - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); return False; } DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname )); - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); return True; } @@ -3701,7 +3701,7 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c /**************************************************************************** Calls from UNIX extensions - POSIX ACL set. - If num_dir_acls == 0 then read/modify/write acl after removing all entries + If num_def_acls == 0 then read/modify/write acl after removing all entries except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER. ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index afe4d352ff..b4140eeafe 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2927,9 +2927,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * case SMB_QUERY_POSIX_ACL: { SMB_ACL_T file_acl = NULL; - SMB_ACL_T dir_acl = NULL; + SMB_ACL_T def_acl = NULL; uint16 num_file_acls = 0; - uint16 num_dir_acls = 0; + uint16 num_def_acls = 0; if (fsp && !fsp->is_directory && (fsp->fd != -1)) { file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); @@ -2945,48 +2945,48 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (S_ISDIR(sbuf.st_mode)) { if (fsp && fsp->is_directory) { - dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); } else { - dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT); + def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT); } - dir_acl = free_empty_sys_acl(conn, dir_acl); + def_acl = free_empty_sys_acl(conn, def_acl); } num_file_acls = count_acl_entries(conn, file_acl); - num_dir_acls = count_acl_entries(conn, dir_acl); + num_def_acls = count_acl_entries(conn, def_acl); - if ( data_size < (num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) { + if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) { DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n", data_size, - (unsigned int)((num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + + (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) )); if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); } SSVAL(pdata,0,SMB_POSIX_ACL_VERSION); SSVAL(pdata,2,num_file_acls); - SSVAL(pdata,4,num_dir_acls); + SSVAL(pdata,4,num_def_acls); if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) { if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return ERROR_NT(NT_STATUS_INTERNAL_ERROR); } - if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, dir_acl)) { + if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) { if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return ERROR_NT(NT_STATUS_INTERNAL_ERROR); } @@ -2994,10 +2994,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - data_size = (num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE; + data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE; break; } @@ -3813,34 +3813,47 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", { uint16 posix_acl_version; uint16 num_file_acls; - uint16 num_dir_acls; + uint16 num_def_acls; + BOOL valid_file_acls = True; + BOOL valid_def_acls = True; if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { return(ERROR_DOS(ERRDOS,ERRinvalidparam)); } posix_acl_version = SVAL(pdata,0); num_file_acls = SVAL(pdata,2); - num_dir_acls = SVAL(pdata,4); + num_def_acls = SVAL(pdata,4); + + if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { + valid_file_acls = False; + num_file_acls = 0; + } + + if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { + valid_def_acls = False; + num_def_acls = 0; + } if (posix_acl_version != SMB_POSIX_ACL_VERSION) { return(ERROR_DOS(ERRDOS,ERRinvalidparam)); } if (total_data < SMB_POSIX_ACL_HEADER_SIZE + - (num_file_acls+num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { + (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { return(ERROR_DOS(ERRDOS,ERRinvalidparam)); } - if (!set_unix_posix_default_acl(conn, fname, &sbuf, num_dir_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE + - (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { + if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE)) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (!set_unix_posix_acl(conn, fsp, fname, num_file_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE)) { + if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE + + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } + SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); -- cgit From a68172ce7cc6c3c9cb02c1b07add9ad1c9c50bbe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Nov 2004 19:32:31 +0000 Subject: r3877: Final (I hope :-) fix for #2050 from Lars Müller for select maxfd's. Jeremy. (This used to be commit 65fc39fc388244923d1e36076b5a4116aa434be5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/server.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5f2713bb83..156755a5b8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -186,7 +186,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; - int max_fd = 0; + int maxfd = 0; int i; char *ports; @@ -249,9 +249,6 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ if(s == -1) return False; - if (max_fd < s) - max_fd = s; - /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); @@ -265,6 +262,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ return False; } FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); num_sockets++; if (num_sockets >= FD_SETSIZE) { @@ -307,6 +305,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ fd_listenset[num_sockets] = s; FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); num_sockets++; @@ -341,7 +340,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - num = sys_select(max_fd+1,&lfds,NULL,NULL,NULL); + num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL); if (num == -1 && errno == EINTR) { if (got_sig_term) { -- cgit From 5a83636948cd82c2bf3c5399eed6a9205b6adfac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 20 Nov 2004 02:48:34 +0000 Subject: r3889: Only set mtime from pending_modtime if it's not already zero... Jeremy. (This used to be commit 984c3506351ba97f74813d678424858508c4197a) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b4140eeafe..633325638a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3304,7 +3304,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char SSVAL(params,0,0); - if (fsp) { + if (fsp && fsp->pending_modtime) { /* the pending modtime overrides the current modtime */ sbuf.st_mtime = fsp->pending_modtime; } -- cgit From 9038a56f82e1352c9d7956af08b70a0b8d3cc773 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 20 Nov 2004 21:24:52 +0000 Subject: r3895: Fix for bug #2045. May also fix other timestamp bugs with Excel (Volker please test). Setting a last write timestamp from Windows overrides any subsequent write timestamp changes and must be immediately seen by and findfirst/findnexts. This is a racy solution, but should work most of the time. This may also fix #1061, not sure. Jeremy. (This used to be commit 47bab92c0b062f3fefbb4fd4a09852e1c829a7f9) --- source3/smbd/fileio.c | 14 ++++++++++++++ source3/smbd/trans2.c | 20 +++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index b9fe1ad1cf..dde254644f 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -130,6 +130,20 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ if (ret != -1) { fsp->pos += ret; + /* + * It turns out that setting the last write time from a Windows + * client stops any subsequent writes from updating the write time. + * Doing this after the write gives a race condition here where + * a stat may see the changed write time before we reset it here, + * but it's cheaper than having to store the write time in shared + * memory and look it up using dev/inode across all running smbd's. + * The 99% solution will hopefully be good enough in this case. JRA. + */ + + if (fsp->pending_modtime) { + set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime); + } + /* Yes - this is correct - writes don't update this. JRA. */ /* Found by Samba4 tests. */ #if 0 diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 633325638a..b877f7c518 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2540,6 +2540,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + if (fsp && fsp->pending_modtime) { + /* the pending modtime overrides the current modtime */ + sbuf.st_mtime = fsp->pending_modtime; + } + if (lp_dos_filetime_resolution(SNUM(conn))) { c_time &= ~1; sbuf.st_atime &= ~1; @@ -3904,10 +3909,12 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if(fsp != NULL) { /* * This was a setfileinfo on an open file. - * NT does this a lot. It's actually pointless - * setting the time here, as it will be overwritten - * on the next write, so we save the request - * away and will set it on file close. JRA. + * NT does this a lot. We also need to + * set the time here, as it can be read by + * FindFirst/FindNext and with the patch for bug #2045 + * in smbd/fileio.c it ensures that this timestamp is + * kept sticky even after a write. We save the request + * away and will set it on file close and after a write. JRA. */ if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { @@ -3915,12 +3922,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", fsp->pending_modtime = tvs.modtime; } - } else { - DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); - if(file_utime(conn, fname, &tvs)!=0) + if(file_utime(conn, fname, &tvs)!=0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } } -- cgit From 44b5067e326fd26e5348495063045241d65293a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Nov 2004 03:42:01 +0000 Subject: r3934: Correctly check for the top length bit in LARGE_READX. Jeremy. (This used to be commit f9effa2af90245c0fe090d730c86a2a60d8570dc) --- source3/smbd/reply.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 845f058867..5d493d8716 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -33,6 +33,7 @@ extern int max_recv; extern char magic_char; extern int global_oplock_break; unsigned int smb_echo_count = 0; +extern uint32 global_client_caps; extern BOOL global_encrypted_passwords_negotiated; @@ -2183,6 +2184,10 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,12,0,True); + if (global_client_caps & CAP_LARGE_READX) { + smb_maxcnt |= ((((size_t)SVAL(inbuf,smb_vwv7)) & 1 )<<16); + } + if(CVAL(inbuf,smb_wct) == 12) { #ifdef LARGE_SMB_OFF_T /* -- cgit From 97bb32d61f825c524bd0e4caecce056088e13a6d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Nov 2004 05:24:38 +0000 Subject: r3936: Ensure LARGE_READX response must fit within reply buffer. Jeremy. (This used to be commit 5541001cf98aa9afb8f98ebeb91561348d3f5d74) --- source3/smbd/reply.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5d493d8716..a3bb412578 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2186,6 +2186,12 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (global_client_caps & CAP_LARGE_READX) { smb_maxcnt |= ((((size_t)SVAL(inbuf,smb_vwv7)) & 1 )<<16); + if (smb_maxcnt > BUFFER_SIZE) { + DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n", + (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE)); + END_PROFILE(SMBreadX); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } } if(CVAL(inbuf,smb_wct) == 12) { -- cgit From 314ec086f3a015f97cc5dafc3038b3bf782d92af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Nov 2004 22:05:59 +0000 Subject: r3944: Fix the problem we get on Linux where sendfile fails, but we've already sent the header using send(). As our implementation of sendfile can't return EINTR (it restarts in that case) use an errno of EINTR to signal the linux sendfile fail after header case. When that happens send the rest of the data and then turn off sendfile. Sendfile should be safe to enable on all systems now (even though it may not help in all performance cases). Jeremy. (This used to be commit 78236382f7ffe08d7924907be49493779521837f) --- source3/smbd/reply.c | 82 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a3bb412578..f8f6a14067 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1717,7 +1717,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size Fail for readbraw. ****************************************************************************/ -void fail_readraw(void) +static void fail_readraw(void) { pstring errstr; slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)", @@ -1725,12 +1725,46 @@ void fail_readraw(void) exit_server(errstr); } +#if defined(WITH_SENDFILE) +/**************************************************************************** + Fake (read/write) sendfile. Returns -1 on read or write fail. +****************************************************************************/ + +static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize) +{ + ssize_t ret=0; + + /* Paranioa check... */ + if (nread > bufsize) { + fail_readraw(); + } + + if (nread > 0) { + ret = read_file(fsp,buf,startpos,nread); + if (ret == -1) { + return -1; + } + } + + /* If we had a short read, fill with zeros. */ + if (ret < nread) { + memset(buf, '\0', nread - ret); + } + + if (write_data(smbd_server_fd(),buf,nread) != nread) { + return -1; + } + + return (ssize_t)nread; +} +#endif + /**************************************************************************** Use sendfile in readbraw. ****************************************************************************/ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread, - ssize_t mincount, char *outbuf) + ssize_t mincount, char *outbuf, int out_buffsize) { ssize_t ret=0; @@ -1752,12 +1786,21 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { /* - * Special hack for broken Linux with no 64 bit clean sendfile. If we - * return ENOSYS then pretend we just got a normal read. + * Special hack for broken Linux with no working sendfile. If we + * return EINTR we sent the header but not the rest of the data. + * Fake this up by doing read/write calls. */ - if (errno == ENOSYS) { + if (errno == EINTR) { + /* Ensure we don't do this again. */ set_use_sendfile(SNUM(conn), False); - goto normal_read; + DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n")); + + if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) { + DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n", + fsp->fsp_name, strerror(errno) )); + exit_server("send_file_readbraw fake_sendfile failed"); + } + return; } DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n", @@ -1767,7 +1810,6 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st } - normal_read: #endif if (nread > 0) { @@ -1790,7 +1832,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st Reply to a readbraw (core+ protocol). ****************************************************************************/ -int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) +int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize) { extern struct current_user current_user; ssize_t maxcount,mincount; @@ -1905,7 +1947,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, (int)maxcount, (int)mincount, (int)nread ) ); - send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf); + send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize); DEBUG(5,("readbraw finished\n")); END_PROFILE(SMBreadbraw); @@ -2069,7 +2111,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Reply to a read and X - possibly using sendfile. ****************************************************************************/ -int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, +int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) { ssize_t nread = -1; @@ -2117,12 +2159,22 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { /* - * Special hack for broken Linux with no 64 bit clean sendfile. If we - * return ENOSYS then pretend we just got a normal read. + * Special hack for broken Linux with no working sendfile. If we + * return EINTR we sent the header but not the rest of the data. + * Fake this up by doing read/write calls. */ - if (errno == ENOSYS) { + if (errno == EINTR) { + /* Ensure we don't do this again. */ set_use_sendfile(SNUM(conn), False); - goto normal_read; + DEBUG(0,("send_file_readX: sendfile not available. Faking..\n")); + + if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data, + len_outbuf - (data-outbuf))) == -1) { + DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", + fsp->fsp_name, strerror(errno) )); + exit_server("send_file_readX: fake_sendfile failed"); + } + return nread; } DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", @@ -2223,7 +2275,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_DOS(ERRDOS,ERRlock); } - nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt); + nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); if (nread != -1) nread = chain_reply(inbuf,outbuf,length,bufsize); -- cgit From 482f14871d568a24006fec5af68d722b5fa70a0d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 Nov 2004 00:07:01 +0000 Subject: r3946: Fix for bugid #2085 reported by Jason Mader . Use consistent enum type for Protocol extern. Jeremy. (This used to be commit 65dfae7ea45d4c9452b2a08efa09b01d870142f3) --- source3/smbd/negprot.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/reply.c | 2 +- source3/smbd/sesssetup.c | 2 +- source3/smbd/trans2.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 447073acd8..7da9d1281e 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -20,7 +20,7 @@ #include "includes.h" -extern int Protocol; +extern enum protocol_types Protocol; extern int max_recv; BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4c17396eb4..8e62a0f8bf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -21,7 +21,7 @@ #include "includes.h" -extern int Protocol; +extern enum protocol_types Protocol; extern int smb_read_error; extern int global_oplock_break; extern struct current_user current_user; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f8f6a14067..376ef24ff7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -27,7 +27,7 @@ #include "includes.h" /* look in server.c for some explanation of these variables */ -extern int Protocol; +extern enum protocol_types Protocol; extern int max_send; extern int max_recv; extern char magic_char; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0122b662eb..cff7d7371c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -633,7 +633,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, static BOOL done_sesssetup = False; extern BOOL global_encrypted_passwords_negotiated; extern BOOL global_spnego_negotiated; - extern int Protocol; + extern enum protocol_types Protocol; extern int max_send; auth_usersupplied_info *user_info = NULL; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b877f7c518..81ffe1dbe0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -23,7 +23,7 @@ #include "includes.h" -extern int Protocol; +extern enum protocol_types Protocol; extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; -- cgit From f3cb4f31a20c01f34d92a4d0a6f76c8ea920af8b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 Nov 2004 00:59:44 +0000 Subject: r3951: Fix for bugid #2081 reported by John Janosik - ensure SE_DESC_DACL_PROTECTED is set if "map acl inherit = no". Jeremy. (This used to be commit 934c41b474c8959310389378bfa7d3332bd5ec79) --- source3/smbd/posix_acls.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7e20313b76..d2e12fc82a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2880,9 +2880,11 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) * inherited at file create time, so ACLs never contain * any ACEs that are inherited dynamically. The DACL_PROTECTED * flag doesn't seem to bother Windows NT. + * Always set this if map acl inherit is turned off. */ - if (get_protected_flag(pal)) + if (get_protected_flag(pal) || !lp_map_acl_inherit(SNUM(conn))) { psd->type |= SE_DESC_DACL_PROTECTED; + } } if (psd->dacl) -- cgit From c3a798cb7a11f95fc4a96b88eaa6b03581ccf409 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 25 Nov 2004 04:10:19 +0000 Subject: r3954: bring Samba3 into line with the Samba4 password change code (This used to be commit 04a6573f894800b9d939d9b4be48790437352804) --- source3/smbd/chgpasswd.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index c91f8599c9..cc27d3baca 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -753,9 +753,8 @@ static NTSTATUS check_oem_password(const char *user, uint16 acct_ctrl; uint32 new_pw_len; uchar new_nt_hash[16]; - uchar old_nt_hash_plain[16]; uchar new_lm_hash[16]; - uchar old_lm_hash_plain[16]; + uchar verifier[16]; char no_pw[2]; BOOL ret; @@ -784,7 +783,7 @@ static NTSTATUS check_oem_password(const char *user, return NT_STATUS_ACCOUNT_DISABLED; } - if (acct_ctrl & ACB_PWNOTREQ && lp_null_passwords()) { + if ((acct_ctrl & ACB_PWNOTREQ) && lp_null_passwords()) { /* construct a null password (in case one is needed */ no_pw[0] = 0; no_pw[1] = 0; @@ -854,12 +853,10 @@ static NTSTATUS check_oem_password(const char *user, if (nt_pw) { /* - * Now use new_nt_hash as the key to see if the old - * password matches. + * check the NT verifier */ - D_P16(new_nt_hash, old_nt_hash_encrypted, old_nt_hash_plain); - - if (memcmp(nt_pw, old_nt_hash_plain, 16)) { + E_old_pw_hash(new_nt_hash, nt_pw, verifier); + if (memcmp(verifier, old_nt_hash_encrypted, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; @@ -884,12 +881,10 @@ static NTSTATUS check_oem_password(const char *user, if (lanman_pw) { /* - * Now use new_nt_hash as the key to see if the old - * LM password matches. + * check the lm verifier */ - D_P16(new_nt_hash, old_lm_hash_encrypted, old_lm_hash_plain); - - if (memcmp(lanman_pw, old_lm_hash_plain, 16)) { + E_old_pw_hash(new_nt_hash, lanman_pw, verifier); + if (memcmp(verifier, old_lm_hash_encrypted, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; @@ -908,12 +903,10 @@ static NTSTATUS check_oem_password(const char *user, E_deshash(new_passwd, new_lm_hash); /* - * Now use new_lm_hash as the key to see if the old - * password matches. + * check the lm verifier */ - D_P16(new_lm_hash, old_lm_hash_encrypted, old_lm_hash_plain); - - if (memcmp(lanman_pw, old_lm_hash_plain, 16)) { + E_old_pw_hash(new_lm_hash, lanman_pw, verifier); + if (memcmp(verifier, old_lm_hash_encrypted, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; -- cgit From 46f546571bc2429c4ee6ef86866520c4b5d4bcc7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Nov 2004 00:22:04 +0000 Subject: r4007: Fix bug #2088 - ensure inherit permissions is only applied on a new file, not an existing one. Jeremy. (This used to be commit fbbdb72cf1adfe567112556626f26b031747f440) --- source3/smbd/dosmode.c | 12 ++++++------ source3/smbd/fileio.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/open.c | 6 +++--- source3/smbd/posix_acls.c | 2 +- source3/smbd/reply.c | 4 ++-- source3/smbd/trans2.c | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 7199b3ebbf..fefcaca09d 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -23,7 +23,7 @@ /**************************************************************************** Change a dos mode to a unix mode. Base permission for files: - if inheriting + if creating file and inheriting apply read/write bits from parent directory. else everybody gets read bit set @@ -43,7 +43,7 @@ } ****************************************************************************/ -mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname) +mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL creating_file) { mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ @@ -52,7 +52,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname) result &= ~(S_IWUSR | S_IWGRP | S_IWOTH); } - if (fname && lp_inherit_perms(SNUM(conn))) { + if (fname && creating_file && lp_inherit_perms(SNUM(conn))) { char *dname; SMB_STRUCT_STAT sbuf; @@ -329,7 +329,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) chmod a file - but preserve some bits. ********************************************************************/ -int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st) +int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, BOOL creating_file) { SMB_STRUCT_STAT st1; int mask=0; @@ -338,7 +338,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, int ret = -1; DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname)); - if (!st) { + if (!st || (st && !VALID_STAT(*st))) { st = &st1; if (SMB_VFS_STAT(conn,fname,st)) return(-1); @@ -359,7 +359,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, return 0; } - unixmode = unix_mode(conn,dosmode,fname); + unixmode = unix_mode(conn,dosmode,fname, creating_file); /* preserve the s bits */ mask |= (S_ISUID | S_ISGID); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index dde254644f..060fbb124d 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -191,7 +191,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); fsp->size = (SMB_BIG_UINT)st.st_size; if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { - file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); + file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st, False); } /* diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8e62a0f8bf..42953a1b7a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1661,7 +1661,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new /* Grrr. We have to do this as open_file_shared1 adds aARCH when it creates the file. This isn't the correct thing to do in the copy case. JRA */ - file_set_dosmode(conn, newname, fmode, &sbuf2); + file_set_dosmode(conn, newname, fmode, &sbuf2, True); if (ret < (SMB_OFF_T)sbuf1.st_size) { return NT_STATUS_DISK_FULL; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1b5ba1228f..7cadf5adba 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -979,7 +979,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ struct pending_message_list *pml = NULL; uint16 mid = get_current_mid(); /* We add aARCH to this as this mode is only used if the file is created new. */ - mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname); + mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname, True); if (oplock_request == INTERNAL_OPEN_ONLY) { internal_only_open = True; @@ -1440,7 +1440,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL); + file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL, True); } } @@ -1601,7 +1601,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } - if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname, True)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d2e12fc82a..ab46bae346 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1864,7 +1864,7 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; mode_t or_bits = (mode_t)0; - mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name) : S_IRUSR; + mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, False) : S_IRUSR; if (fsp->is_directory) mode |= (S_IWUSR|S_IXUSR); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 376ef24ff7..2806b796b3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -719,7 +719,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode &= ~aDIR; if (check_name(fname,conn)) { - ok = (file_set_dosmode(conn,fname,mode,NULL) == 0); + ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0); } } else { ok = True; @@ -3286,7 +3286,7 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) } if (check_name(directory, conn)) - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); if (ret == -1) { if(errno == ENOENT) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 81ffe1dbe0..4a10511a0e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3935,7 +3935,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode )); - if(file_set_dosmode(conn, fname, dosmode, NULL)) { + if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) { DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno))); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -4020,7 +4020,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } if (check_name(directory,conn)) - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); if(ret < 0) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); -- cgit From 01533404b11661d1cfa74b73d6bc4def1ba0bb8d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Nov 2004 06:41:38 +0000 Subject: r4016: Fix for bug found by Steve French client code (cifsfs) on POSIX ACL set. You need to *get* a permset_t pointer from the entry before any of the permset code will accept it as a valid value Jeremy. (This used to be commit 7e78059948612fa9f5d179a1e3f5f59e7ad5e456) --- source3/smbd/posix_acls.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ab46bae346..d30cf62e7c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3489,12 +3489,21 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_ goto fail; } + /* Get the permset pointer from the new ACL entry. */ + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) { + DEBUG(0,("create_posix_acl_from_wire: Failed to get permset on entry %u. (%s)\n", + i, strerror(errno) )); + goto fail; + } + + /* Map from wire to permissions. */ if (!unix_ex_wire_to_permset(conn, CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+1), &the_permset)) { DEBUG(0,("create_posix_acl_from_wire: invalid permset %u on entry %u.\n", CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE) + 1), i )); goto fail; } + /* Now apply to the new ACL entry. */ if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) { DEBUG(0,("create_posix_acl_from_wire: Failed to add permset on entry %u. (%s)\n", i, strerror(errno) )); -- cgit From 2fffc40b1ddcd8a89160db877bd868f6e7fa8b72 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 30 Nov 2004 15:52:46 +0000 Subject: r4018: * move claim_connection from the netbios session request reply code to the negprot reply code to cope with client connections on port 445. Fixes the spurious "register_message_flags: tdb fetch failed" errors. * don't run the backgroup LPQ daemon when we are running in interactive mode. (This used to be commit 88747a7da351261185222e78e9c8d470ff53a246) --- source3/smbd/negprot.c | 6 ++++++ source3/smbd/reply.c | 2 -- source3/smbd/server.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 7da9d1281e..9aaa818c62 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -523,6 +523,12 @@ int reply_negprot(connection_struct *conn, /* possibly reload - change of architecture */ reload_services(True); + + /* moved from the netbios session setup code since we don't have that + when the client connects to port 445. Of course there is a small + window where we are listening to messages -- jerry */ + + claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); /* Check for protocols, most desirable first */ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2806b796b3..eda523e73a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -259,8 +259,6 @@ int reply_special(char *inbuf,char *outbuf) reload_services(True); reopen_logs(); - claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); - already_got_session = True; break; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 156755a5b8..724a49321a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -864,7 +864,7 @@ void build_options(BOOL screen); smbd is launched via inetd and we fork a copy of ourselves here */ - if ( is_daemon ) + if ( is_daemon && !interactive ) start_background_queue(); if (!open_sockets_smbd(is_daemon, interactive, ports)) -- cgit From 5f67f0125831b2a70605b2661585311633b244aa Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 30 Nov 2004 15:55:27 +0000 Subject: r4019: better error logging in register_message_flags() from Rob (This used to be commit 5fc0f838e7ec8b29d7987caafe9ffbb8724a3176) --- source3/smbd/connection.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index fc5fe9d741..32e2f058fc 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -217,7 +217,8 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) dbuf = tdb_fetch(tdb, kbuf); if (!dbuf.dptr) { - DEBUG(0,("register_message_flags: tdb_fetch failed\n")); + DEBUG(0,("register_message_flags: tdb_fetch failed: %s\n", + tdb_errorstr(tdb))); return False; } @@ -228,7 +229,7 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) pcrec->bcast_msg_flags &= ~msg_flags; if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { - DEBUG(0,("register_message_flags: tdb_store failed with error %s.\n", + DEBUG(0,("register_message_flags: tdb_store failed: %s.\n", tdb_errorstr(tdb) )); SAFE_FREE(dbuf.dptr); return False; -- cgit From 57c468bbf1dd124f568c5beb1fb4a7d3c09dda71 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 2 Dec 2004 17:11:18 +0000 Subject: r4043: BUG 2091: don't remove statically defined printers in remove_stale_printers() (This used to be commit c24a3c49ce20797c0f9172e503e34770d00842ec) --- source3/smbd/service.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4d111e0ea3..3dcd803a7c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -152,10 +152,9 @@ int find_service(fstring service) int iPrinterService; if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) { - char *pszTemp; + const char *pszTemp = lp_printcapname(); DEBUG(3,("checking whether %s is a valid printer name...\n", service)); - pszTemp = lp_printcapname(); if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) { DEBUG(3,("%s is a valid printer name\n", service)); DEBUG(3,("adding %s as a printer service\n", service)); @@ -877,12 +876,21 @@ void remove_stale_printers( void ) iNumServices = lp_numservices(); printersServiceNum = lp_servicenumber( PRINTERS_NAME); for( snum = 0; snum < iNumServices; snum++) { + /* Never remove PRINTERS_NAME */ + if ( snum == printersServiceNum) continue; pname = lp_printername( snum); - /* Is snum a print service and still in the printing subsystem? */ - if ( lp_print_ok( snum) && !pcap_printername_ok( pname, NULL)) { + + /* Is snum an autoloaded print service and still + in the printing subsystem? */ + + if ( lp_snum_ok(snum) + && lp_print_ok(snum) + && lp_autoloaded(snum) + && !pcap_printername_ok( pname, NULL)) + { DEBUG( 3, ( "Removing printer: %s\n", pname)); lp_killservice( snum); } -- cgit From 3bd3be97dc8a581c0502410453091c195e322766 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 6 Dec 2004 19:25:25 +0000 Subject: r4083: consolidate printer searches to use find_service rather than for loops (This used to be commit 12440744ba36445186042c8c254785766cce5385) --- source3/smbd/lanman.c | 52 +++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 5f4c0cec52..7d5e0f5ad2 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -760,18 +760,10 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, return(True); } - snum = lp_servicenumber(QueueName); - if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } - - if (snum < 0 || !VALID_SNUM(snum)) - return(False); - + snum = find_service(QueueName); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) + return False; + if (uLevel==52) { count = get_printerdrivernumber(snum); DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); @@ -3048,20 +3040,18 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); /* check it's a supported variant */ - if (strcmp(str1,"zWrLeh") != 0) return False; - if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */ - if (!check_printjob_info(&desc,uLevel,str2)) return False; - - snum = lp_servicenumber(name); - if (snum < 0 && pcap_printername_ok(name,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(name,pnum); - snum = lp_servicenumber(name); - } - } + if (strcmp(str1,"zWrLeh") != 0) + return False; + + if (uLevel > 2) + return False; /* defined only for uLevel 0,1,2 */ + + if (!check_printjob_info(&desc,uLevel,str2)) + return False; - if (snum < 0 || !VALID_SNUM(snum)) return(False); + snum = find_service(name); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) + return False; count = print_queue_status(snum,&queue,&status); if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); @@ -3164,16 +3154,8 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par if (strcmp(str1,"zWrLh") != 0) return False; if (!check_printdest_info(&desc,uLevel,str2)) return False; - snum = lp_servicenumber(PrinterName); - if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(PrinterName,pnum); - snum = lp_servicenumber(PrinterName); - } - } - - if (snum < 0) { + snum = find_service(PrinterName); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { *rdata_len = 0; desc.errcode = NERR_DestNotFound; desc.neededlen = 0; -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/smbd/blocking.c | 4 +- source3/smbd/conn.c | 2 +- source3/smbd/dir.c | 6 +-- source3/smbd/fake_file.c | 2 +- source3/smbd/fileio.c | 4 +- source3/smbd/files.c | 2 +- source3/smbd/ipc.c | 8 +-- source3/smbd/lanman.c | 129 ++++++++++++++++++++++---------------------- source3/smbd/mangle_hash.c | 4 +- source3/smbd/mangle_hash2.c | 18 ++++--- source3/smbd/msdfs.c | 13 +++-- source3/smbd/notify.c | 2 +- source3/smbd/ntquotas.c | 6 +-- source3/smbd/nttrans.c | 23 +++++--- source3/smbd/open.c | 2 +- source3/smbd/oplock.c | 4 +- source3/smbd/password.c | 8 +-- source3/smbd/posix_acls.c | 29 +++++----- source3/smbd/process.c | 7 ++- source3/smbd/reply.c | 4 +- source3/smbd/sec_ctx.c | 4 +- source3/smbd/session.c | 6 +-- source3/smbd/statcache.c | 6 +-- source3/smbd/trans2.c | 40 +++++++------- source3/smbd/vfs.c | 8 +-- 25 files changed, 179 insertions(+), 162 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index e143999a78..0e71174a2e 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -106,12 +106,12 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, * the expiration time here. */ - if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { + if((blr = SMB_MALLOC_P(blocking_lock_record)) == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); return False; } - if((blr->inbuf = (char *)malloc(length)) == NULL) { + if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); SAFE_FREE(blr); return False; diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 34e19a3ca6..6b5942f7f6 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -132,7 +132,7 @@ find_again: return NULL; } - if ((conn=(connection_struct *)talloc_zero(mem_ctx, sizeof(*conn)))==NULL) { + if ((conn=TALLOC_ZERO_P(mem_ctx, connection_struct))==NULL) { DEBUG(0,("talloc_zero() failed!\n")); return NULL; } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 2bda42f76d..f721bf3ba8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -407,7 +407,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); - dptr = (dptr_struct *)malloc(sizeof(dptr_struct)); + dptr = SMB_MALLOC_P(dptr_struct); if(!dptr) { DEBUG(0,("malloc fail in dptr_create.\n")); return -1; @@ -819,7 +819,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) if (!p) return(NULL); - dirp = (Dir *)malloc(sizeof(Dir)); + dirp = SMB_MALLOC_P(Dir); if (!dirp) { DEBUG(0,("Out of memory in OpenDir\n")); SMB_VFS_CLOSEDIR(conn,p); @@ -900,7 +900,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; - r = (char *)Realloc(dirp->data,s); + r = (char *)SMB_REALLOC(dirp->data,s); if (!r) { DEBUG(0,("Out of memory in OpenDir\n")); break; diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index fc874dc086..53aac1e036 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -132,7 +132,7 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) return NULL; } - if ((fh =(FAKE_FILE_HANDLE *)talloc_zero(mem_ctx, sizeof(FAKE_FILE_HANDLE)))==NULL) { + if ((fh =TALLOC_ZERO_P(mem_ctx, FAKE_FILE_HANDLE))==NULL) { DEBUG(0,("talloc_zero() failed.\n")); talloc_destroy(mem_ctx); return NULL; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 060fbb124d..a21bd69a36 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -676,7 +676,7 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) if(alloc_size == 0 || fsp->wcp) return False; - if((wcp = (write_cache *)malloc(sizeof(write_cache))) == NULL) { + if((wcp = SMB_MALLOC_P(write_cache)) == NULL) { DEBUG(0,("setup_write_cache: malloc fail.\n")); return False; } @@ -685,7 +685,7 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) wcp->offset = 0; wcp->alloc_size = alloc_size; wcp->data_size = 0; - if((wcp->data = malloc(wcp->alloc_size)) == NULL) { + if((wcp->data = SMB_MALLOC(wcp->alloc_size)) == NULL) { DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", (unsigned int)wcp->alloc_size )); SAFE_FREE(wcp); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 580dc54545..ecf39c2b54 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -93,7 +93,7 @@ files_struct *file_new(connection_struct *conn) return NULL; } - fsp = (files_struct *)malloc(sizeof(*fsp)); + fsp = SMB_MALLOC_P(files_struct); if (!fsp) { unix_ERR_class = ERRSRV; unix_ERR_code = ERRnofids; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 35e670c9fa..9fcd39b500 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -165,7 +165,7 @@ void send_trans_reply(char *outbuf, static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p) { BOOL is_data_outstanding; - char *rdata = malloc(p->max_trans_reply); + char *rdata = SMB_MALLOC(p->max_trans_reply); int data_len; if(rdata == NULL) { @@ -389,7 +389,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int goto bad_param; if (tdscnt) { - if((data = (char *)malloc(tdscnt)) == NULL) { + if((data = (char *)SMB_MALLOC(tdscnt)) == NULL) { DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt)); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); @@ -404,7 +404,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if (tpscnt) { - if((params = (char *)malloc(tpscnt)) == NULL) { + if((params = (char *)SMB_MALLOC(tpscnt)) == NULL) { DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt)); SAFE_FREE(data); END_PROFILE(SMBtrans); @@ -421,7 +421,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (suwcnt) { unsigned int i; - if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { + if((setup = SMB_MALLOC_ARRAY(uint16,suwcnt)) == NULL) { DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16)))); SAFE_FREE(data); SAFE_FREE(params); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7d5e0f5ad2..4af11da784 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -753,7 +753,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, */ *rdata_len = 0; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,ERRunknownlevel); SSVAL(*rparam,2,0); SSVAL(*rparam,4,0); @@ -772,7 +772,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, } if (mdrcnt > 0) { - *rdata = REALLOC(*rdata,mdrcnt); + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; } else { @@ -781,7 +781,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, * init_package will return wrong size if buflen=0 */ desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *) malloc (desc.buflen); + desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen); } if (init_package(&desc,1,count)) { @@ -801,7 +801,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, *rdata_len = desc.usedlen; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -849,7 +849,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, */ *rdata_len = 0; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,ERRunknownlevel); SSVAL(*rparam,2,0); SSVAL(*rparam,4,0); @@ -861,17 +861,17 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) queuecnt++; if (uLevel > 0) { - if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) { + if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) { DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); return False; } memset(queue,0,queuecnt*sizeof(print_queue_struct*)); - if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) { + if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) { DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); return False; } memset(status,0,queuecnt*sizeof(print_status_struct)); - if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) { + if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) { DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); return False; } @@ -884,7 +884,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, n++; } } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; @@ -903,7 +903,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -987,8 +987,7 @@ static int get_server_info(uint32 servertype, struct srv_info_struct *ts; alloced += 10; - ts = (struct srv_info_struct *) - Realloc(*servers,sizeof(**servers)*alloced); + ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); if (!ts) { DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); return(0); @@ -1234,7 +1233,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param } *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); memset(*rdata,'\0',*rdata_len); p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ @@ -1258,7 +1257,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param } *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); @@ -1295,7 +1294,7 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa *rdata_len = 0; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVAL(*rparam,0,0x08AC); /* informational warning message */ SSVAL(*rparam,2,0); @@ -1441,13 +1440,13 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para if (!prefix_ok(str1,"zWrLh")) return False; if (!check_share_info(uLevel,str2)) return False; - *rdata = REALLOC(*rdata,mdrcnt); + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); p = *rdata; *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); if (*rdata_len < 0) return False; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); @@ -1514,7 +1513,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, } } *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); memset(*rdata,0,*rdata_len); p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */ @@ -1537,7 +1536,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, } *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); @@ -1623,7 +1622,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch } else return False; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); @@ -1633,7 +1632,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch error_exit: *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 0; SSVAL(*rparam,0,res); SSVAL(*rparam,2,0); @@ -1688,7 +1687,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); *rdata_len = cli_buf_size; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); p = *rdata; @@ -1710,7 +1709,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c *rdata_len = PTR_DIFF(p,*rdata); *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVAL(*rparam, 0, errflags); SSVAL(*rparam, 2, 0); /* converter word */ @@ -1748,7 +1747,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para NTSTATUS result; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); /* check it's a supported varient */ @@ -1767,7 +1766,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para return False; *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -1859,14 +1858,14 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); /* check it's a supported varient */ if (strcmp("B21",str2) != 0) return False; *rdata_len = cli_buf_size; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); p = *rdata; @@ -1929,10 +1928,10 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch { char *p; *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 21; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -1991,7 +1990,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param memcpy(pass2,p+16,16); *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 0; @@ -2063,7 +2062,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * fstring user; char *p = param + 2; *rparam_len = 2; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 0; @@ -2130,7 +2129,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param return(False); *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 0; if (!print_job_exists(sharename, jobid)) { @@ -2193,7 +2192,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param return(False); *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 0; snum = print_queue_snum(QueueName); @@ -2267,7 +2266,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if ( (snum = lp_servicenumber(sharename)) == -1 ) { DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n", @@ -2368,7 +2367,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par } *rdata_len = mdrcnt; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); p = *rdata; p2 = p + struct_len; @@ -2417,7 +2416,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par *rdata_len = PTR_DIFF(p2,*rdata); *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); @@ -2444,14 +2443,14 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param DEBUG(4,("NetWkstaGetInfo level %d\n",level)); *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); /* check it's a supported varient */ if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) return(False); *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -2690,7 +2689,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param vuser->user.unix_name)); *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); @@ -2709,7 +2708,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param if (strcmp(level_string,str2) != 0) return False; *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -2856,7 +2855,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param /* check it's a supported varient */ if (strcmp(str1,"OOWb54WrLh") != 0) return False; if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; desc.subformat = NULL; @@ -2895,7 +2894,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param *rdata_len = desc.usedlen; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -2925,7 +2924,7 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p if (strcmp(str2,"") != 0) return False; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,0); /* errorcode */ SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,0x7f); /* permission flags */ @@ -2978,7 +2977,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para } if (mdrcnt > 0) { - *rdata = REALLOC(*rdata,mdrcnt); + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; } else { @@ -2987,7 +2986,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para * init_package will return wrong size if buflen=0 */ desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *)malloc ( desc.buflen ); + desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); } if (init_package(&desc,1,0)) { @@ -3002,7 +3001,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para } *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -3054,7 +3053,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa return False; count = print_queue_status(snum,&queue,&status); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; @@ -3069,7 +3068,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3162,7 +3161,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par } else { if (mdrcnt > 0) { - *rdata = REALLOC(*rdata,mdrcnt); + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; } else { @@ -3171,7 +3170,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par * init_package will return wrong size if buflen=0 */ desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *)malloc ( desc.buflen ); + desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); } if (init_package(&desc,1,0)) { fill_printdest_info(conn,snum,uLevel,&desc); @@ -3180,7 +3179,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par } *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -3219,7 +3218,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) queuecnt++; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; if (init_package(&desc,queuecnt,0)) { @@ -3237,7 +3236,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3269,7 +3268,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para if (strcmp(str1,"WrLeh") != 0) return False; if (uLevel != 0 || strcmp(str2,"B41") != 0) return False; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; if (init_package(&desc,1,0)) { @@ -3281,7 +3280,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3313,7 +3312,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param if (strcmp(str1,"WrLeh") != 0) return False; if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; desc.format = str2; @@ -3326,7 +3325,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3358,7 +3357,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, if (strcmp(str1,"WrLeh") != 0) return False; if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); memset((char *)&desc,'\0',sizeof(desc)); desc.base = *rdata; desc.buflen = mdrcnt; @@ -3372,7 +3371,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3414,7 +3413,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param num_sessions = list_sessions(&session_list); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); + if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); memset((char *)&desc,'\0',sizeof(desc)); desc.base = *rdata; desc.buflen = mdrcnt; @@ -3438,7 +3437,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); /* converter */ SSVAL(*rparam,4,num_sessions); /* count */ @@ -3458,7 +3457,7 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char * int *rdata_len,int *rparam_len) { *rparam_len = MIN(*rparam_len,mprcnt); - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 0; @@ -3480,7 +3479,7 @@ static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,cha int *rdata_len,int *rparam_len) { *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); *rdata_len = 0; @@ -3587,11 +3586,11 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * return ERROR_NT(NT_STATUS_ACCESS_DENIED); } - rdata = (char *)malloc(1024); + rdata = (char *)SMB_MALLOC(1024); if (rdata) memset(rdata,'\0',1024); - rparam = (char *)malloc(1024); + rparam = (char *)SMB_MALLOC(1024); if (rparam) memset(rparam,'\0',1024); diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 26ddf1b3a3..0067023e61 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -476,7 +476,7 @@ static BOOL check_cache( char *s, size_t maxlen ) if(data_val.dptr == NULL || data_val.dsize == 0) { ext_start = strrchr( s, '.' ); if( ext_start ) { - if((saved_ext = strdup(ext_start)) == NULL) + if((saved_ext = SMB_STRDUP(ext_start)) == NULL) return False; *ext_start = '\0'; @@ -624,7 +624,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case) /* mangle it into 8.3 */ if (cache83) - tmp = strdup(OutName); + tmp = SMB_STRDUP(OutName); to_8_3(OutName, default_case); diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index c6ad1215b0..4896cfb17b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -153,13 +153,19 @@ static u32 mangle_hash(const char *key, unsigned int length) */ static BOOL cache_init(void) { - if (prefix_cache) return True; + if (prefix_cache) { + return True; + } - prefix_cache = calloc(MANGLE_CACHE_SIZE, sizeof(char *)); - if (!prefix_cache) return False; + prefix_cache = SMB_CALLOC_ARRAY(char *,MANGLE_CACHE_SIZE); + if (!prefix_cache) { + return False; + } - prefix_cache_hashes = calloc(MANGLE_CACHE_SIZE, sizeof(u32)); - if (!prefix_cache_hashes) return False; + prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); + if (!prefix_cache_hashes) { + return False; + } return True; } @@ -175,7 +181,7 @@ static void cache_insert(const char *prefix, int length, u32 hash) free(prefix_cache[i]); } - prefix_cache[i] = strndup(prefix, length); + prefix_cache[i] = SMB_STRNDUP(prefix, length); prefix_cache_hashes[i] = hash; } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6c132897f9..b5ae7486d3 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -189,7 +189,7 @@ static BOOL parse_symlink(char* buf,struct referral** preflist, DEBUG(10,("parse_symlink: count=%d\n", count)); - reflist = *preflist = (struct referral*) malloc(count * sizeof(struct referral)); + reflist = *preflist = SMB_MALLOC_ARRAY(struct referral, count); if(reflist == NULL) { DEBUG(0,("parse_symlink: Malloc failed!\n")); return False; @@ -417,7 +417,7 @@ static BOOL self_ref(char *pathname, struct junction_map *jucn, *self_referralp = True; jucn->referral_count = 1; - if((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + if((ref = SMB_MALLOC_P(struct referral)) == NULL) { DEBUG(0,("self_ref: malloc failed for referral\n")); return False; } @@ -503,7 +503,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, self_referralp); jucn->referral_count = 1; - if ((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + if ((ref = SMB_MALLOC_P(struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); goto out; } @@ -595,7 +595,7 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, /* add the unexplained 0x16 bytes */ reply_size += 0x16; - pdata = Realloc(pdata,reply_size); + pdata = SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; @@ -676,7 +676,7 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; } - pdata = Realloc(pdata,reply_size); + pdata = SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; @@ -962,8 +962,7 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) jucn[cnt].volume_name[0] = '\0'; jucn[cnt].referral_count = 1; - ref = jucn[cnt].referral_list - = (struct referral*) malloc(sizeof(struct referral)); + ref = jucn[cnt].referral_list = SMB_MALLOC_P(struct referral); if (jucn[cnt].referral_list == NULL) { DEBUG(0, ("Malloc failed!\n")); goto out; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9adf827c79..92b86f350c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -178,7 +178,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, { struct change_notify *cnbp; - if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { + if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); return -1; } diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 555f32d773..8fbf858008 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -199,14 +199,14 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) DEBUG(15,("quota entry for id[%s] path[%s]\n", sid_string_static(&sid),fsp->conn->connectpath)); - if ((tmp_list_ent=(SMB_NTQUOTA_LIST *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_LIST)))==NULL) { + if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) { DEBUG(0,("talloc_zero() failed\n")); *qt_list = NULL; talloc_destroy(mem_ctx); return (-1); } - if ((tmp_list_ent->quotas=(SMB_NTQUOTA_STRUCT *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_STRUCT)))==NULL) { + if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) { DEBUG(0,("talloc_zero() failed\n")); *qt_list = NULL; talloc_destroy(mem_ctx); @@ -232,7 +232,7 @@ void *init_quota_handle(TALLOC_CTX *mem_ctx) if (!mem_ctx) return False; - qt_handle = (SMB_NTQUOTA_HANDLE *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_HANDLE)); + qt_handle = TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_HANDLE); if (qt_handle==NULL) { DEBUG(0,("talloc_zero() failed\n")); return NULL; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 42953a1b7a..2395d0d8db 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -58,11 +58,12 @@ static char *nttrans_realloc(char **ptr, size_t size) if (ptr==NULL) smb_panic("nttrans_realloc() called with NULL ptr\n"); - tptr = Realloc_zero(*ptr, size); + tptr = SMB_REALLOC(*ptr, size); if(tptr == NULL) { *ptr = NULL; return NULL; } + memset(tptr,'\0',size); *ptr = tptr; @@ -2139,7 +2140,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou return ERROR_NT(NT_STATUS_NO_MEMORY); } - shadow_data = (SHADOW_COPY_DATA *)talloc_zero(shadow_mem_ctx,sizeof(SHADOW_COPY_DATA)); + shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA); if (shadow_data == NULL) { DEBUG(0,("talloc_zero() failed!\n")); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -2449,6 +2450,10 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, } sid_len = IVAL(pdata,4); + /* Ensure this is less than 1mb. */ + if (sid_len > (1024*1024)) { + return ERROR_DOS(ERRDOS,ERRnomem); + } if (data_count < 8+sid_len) { DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len))); @@ -2703,15 +2708,21 @@ due to being in oplock break state.\n", (unsigned int)function_code )); CVAL(inbuf, smb_wct), 19 + (setup_count/2))); goto bad_param; } - + + /* Don't allow more than 128mb for each value. */ + if ((total_parameter_count > (1024*1024*128)) || (total_data_count > (1024*1024*128))) { + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRDOS,ERRnomem); + } + /* Allocate the space for the setup, the maximum needed parameters and data */ if(setup_count > 0) - setup = (char *)malloc(setup_count); + setup = (char *)SMB_MALLOC(setup_count); if (total_parameter_count > 0) - params = (char *)malloc(total_parameter_count); + params = (char *)SMB_MALLOC(total_parameter_count); if (total_data_count > 0) - data = (char *)malloc(total_data_count); + data = (char *)SMB_MALLOC(total_data_count); if ((total_parameter_count && !params) || (total_data_count && !data) || (setup_count && !setup)) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7cadf5adba..bf3fbf7fec 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -681,7 +681,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou return -1; } - broken_entry = malloc(sizeof(struct share_mode_entry_list)); + broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); if (!broken_entry) { smb_panic("open_mode_check: malloc fail.\n"); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1ffc798b1f..3ebf93e560 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -740,12 +740,12 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * messages crossing on the wire. */ - if((inbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { + if((inbuf = (char *)SMB_MALLOC(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); return False; } - if((outbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { + if((outbuf = (char *)SMB_MALLOC(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); SAFE_FREE(inbuf); return False; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index eb389d7013..213ef98ea3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -139,7 +139,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, return UID_FIELD_INVALID; } - if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) { + if((vuser = SMB_MALLOC_P(user_struct)) == NULL) { DEBUG(0,("Failed to malloc users struct!\n")); data_blob_free(&session_key); return UID_FIELD_INVALID; @@ -316,7 +316,7 @@ void add_session_user(const char *user) DEBUG(3,("add_session_user: session userlist already too large.\n")); return; } - newlist = Realloc( session_userlist, len_session_userlist + PSTRING_LEN ); + newlist = SMB_REALLOC( session_userlist, len_session_userlist + PSTRING_LEN ); if( newlist == NULL ) { DEBUG(1,("Unable to resize session_userlist\n")); return; @@ -498,9 +498,9 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, char *user_list = NULL; if ( session_userlist ) - user_list = strdup(session_userlist); + user_list = SMB_STRDUP(session_userlist); else - user_list = strdup(""); + user_list = SMB_STRDUP(""); if (!user_list) return(False); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d30cf62e7c..903b943522 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -166,7 +166,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B *store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH); - pai_buf = malloc(*store_size); + pai_buf = SMB_MALLOC(*store_size); if (!pai_buf) { return NULL; } @@ -343,7 +343,7 @@ static struct pai_val *create_pai_val(char *buf, size_t size) if (!check_pai_ok(buf, size)) return NULL; - paiv = malloc(sizeof(struct pai_val)); + paiv = SMB_MALLOC_P(struct pai_val); if (!paiv) return NULL; @@ -362,7 +362,7 @@ static struct pai_val *create_pai_val(char *buf, size_t size) for (i = 0; i < paiv->num_entries; i++) { struct pai_entry *paie; - paie = malloc(sizeof(struct pai_entry)); + paie = SMB_MALLOC_P(struct pai_entry); if (!paie) { free_inherited_info(paiv); return NULL; @@ -393,7 +393,7 @@ static struct pai_val *create_pai_val(char *buf, size_t size) for (i = 0; i < paiv->num_def_entries; i++) { struct pai_entry *paie; - paie = malloc(sizeof(struct pai_entry)); + paie = SMB_MALLOC_P(struct pai_entry); if (!paie) { free_inherited_info(paiv); return NULL; @@ -438,7 +438,7 @@ static struct pai_val *load_inherited_info(files_struct *fsp) if (!lp_map_acl_inherit(SNUM(fsp->conn))) return NULL; - if ((pai_buf = malloc(pai_buf_size)) == NULL) + if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL) return NULL; do { @@ -456,7 +456,10 @@ static struct pai_val *load_inherited_info(files_struct *fsp) /* Buffer too small - enlarge it. */ pai_buf_size *= 2; SAFE_FREE(pai_buf); - if ((pai_buf = malloc(pai_buf_size)) == NULL) + if (pai_buf_size > 1024*1024) { + return NULL; /* Limit malloc to 1mb. */ + } + if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL) return NULL; } } while (ret == -1); @@ -523,7 +526,7 @@ static void free_canon_ace_list( canon_ace *list_head ) static canon_ace *dup_canon_ace( canon_ace *src_ace) { - canon_ace *dst_ace = (canon_ace *)malloc(sizeof(canon_ace)); + canon_ace *dst_ace = SMB_MALLOC_P(canon_ace); if (dst_ace == NULL) return NULL; @@ -1083,7 +1086,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, } if (!got_user) { - if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); return False; } @@ -1113,7 +1116,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, } if (!got_grp) { - if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); return False; } @@ -1139,7 +1142,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, } if (!got_other) { - if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); return False; } @@ -1323,7 +1326,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, * Create a cannon_ace entry representing this NT DACL ACE. */ - if ((current_ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { + if ((current_ace = SMB_MALLOC_P(canon_ace)) == NULL) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); DEBUG(0,("create_canon_ace_lists: malloc fail.\n")); @@ -2161,7 +2164,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * Add this entry to the list. */ - if ((ace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) + if ((ace = SMB_MALLOC_P(canon_ace)) == NULL) goto fail; ZERO_STRUCTP(ace); @@ -2793,7 +2796,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) num_def_acls = count_canon_ace_list(dir_ace); /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_def_acls)* sizeof(SEC_ACE))) == NULL) { + if ((nt_ace_list = SMB_MALLOC_ARRAY(SEC_ACE,num_acls + num_profile_acls + num_def_acls)) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); goto done; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5be68d9f0a..8adc5c2e66 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -85,8 +85,7 @@ static void free_queued_message(struct pending_message_list *msg) static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private, size_t private_len) { struct pending_message_list *tmp_msg; - struct pending_message_list *msg = (struct pending_message_list *) - malloc(sizeof(struct pending_message_list)); + struct pending_message_list *msg = SMB_MALLOC_P(struct pending_message_list); if(msg == NULL) { DEBUG(0,("push_message: malloc fail (1)\n")); @@ -1498,8 +1497,8 @@ void smbd_process(void) unsigned int num_smbs = 0; const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN; - InBuffer = (char *)malloc(total_buffer_size); - OutBuffer = (char *)malloc(total_buffer_size); + InBuffer = (char *)SMB_MALLOC(total_buffer_size); + OutBuffer = (char *)SMB_MALLOC(total_buffer_size); if ((InBuffer == NULL) || (OutBuffer == NULL)) return; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eda523e73a..23657d3f1f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -899,7 +899,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); } - dptr_set_wcard(dptr_num, strdup(mask)); + dptr_set_wcard(dptr_num, SMB_STRDUP(mask)); dptr_set_attr(dptr_num, dirtype); } else { dirtype = dptr_attr(dptr_num); @@ -4945,7 +4945,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, if(fsp->wbmpx_ptr != NULL) wbms = fsp->wbmpx_ptr; /* Use an existing struct */ else - wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); + wbms = SMB_MALLOC_P(write_bmpx_struct); if(!wbms) { DEBUG(0,("Out of memory in reply_readmpx\n")); END_PROFILE(SMBwriteBmpx); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 8a85792ead..a5411b94a1 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -154,7 +154,7 @@ int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups) goto fail; } - if((groups = (gid_t *)malloc(sizeof(gid_t)*(ngroups+1))) == NULL) { + if((groups = SMB_MALLOC_ARRAY(gid_t, ngroups+1)) == NULL) { DEBUG(0,("setup_groups malloc fail !\n")); goto fail; } @@ -260,7 +260,7 @@ BOOL push_sec_ctx(void) ctx_p->ngroups = sys_getgroups(0, NULL); if (ctx_p->ngroups != 0) { - if (!(ctx_p->groups = malloc(ctx_p->ngroups * sizeof(gid_t)))) { + if (!(ctx_p->groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ngroups))) { DEBUG(0, ("Out of memory in push_sec_ctx()\n")); delete_nt_token(&ctx_p->token); return False; diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 91ebaeb830..9a9a0d90b2 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -151,7 +151,7 @@ BOOL session_claim(user_struct *vuser) sessionid.id_str, sessionid.id_num); } - vuser->session_keystr = strdup(keystr); + vuser->session_keystr = SMB_STRDUP(keystr); if (!vuser->session_keystr) { DEBUG(0, ("session_claim: strdup() failed for session_keystr\n")); return False; @@ -221,8 +221,8 @@ static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, const struct sessionid *current = (const struct sessionid *) dbuf.dptr; sesslist->count += 1; - sesslist->sessions = REALLOC(sesslist->sessions, sesslist->count * - sizeof(struct sessionid)); + sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, + sesslist->count); memcpy(&sesslist->sessions[sesslist->count - 1], current, sizeof(struct sessionid)); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index ba37d4927c..cfc5286327 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -76,7 +76,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * translated path. */ - translated_path = strdup(orig_translated_path); + translated_path = SMB_STRDUP(orig_translated_path); if (!translated_path) return; @@ -88,7 +88,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } if(case_sensitive) { - original_path = strdup(full_orig_name); + original_path = SMB_STRDUP(full_orig_name); } else { original_path = strdup_upper(full_orig_name); } @@ -179,7 +179,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; if (conn->case_sensitive) { - chk_name = strdup(name); + chk_name = SMB_STRDUP(name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); return False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4a10511a0e..7269ab9157 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -115,7 +115,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str again: - val = talloc_realloc(mem_ctx, val, attr_size); + val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size); if (!val) { return False; } @@ -169,8 +169,8 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, return NULL; } - for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6; - ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) { + for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6; + ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { if (fsp && fsp->fd != -1) { sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size); } else { @@ -196,7 +196,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, if (strnequal(p, "system.", 7) || samba_private_attr_name(p)) continue; - listp = talloc(mem_ctx, sizeof(struct ea_list)); + listp = TALLOC_P(mem_ctx, struct ea_list); if (!listp) return NULL; @@ -672,7 +672,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } /* Realloc the size of parameters and data we will return */ - params = Realloc(*pparams, 28); + params = SMB_REALLOC(*pparams, 28); if( params == NULL ) return(ERROR_DOS(ERRDOS,ERRnomem)); *pparams = params; @@ -1418,7 +1418,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); - pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if( pdata == NULL ) return(ERROR_DOS(ERRDOS,ERRnomem)); @@ -1426,7 +1426,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ - params = Realloc(*pparams, 10); + params = SMB_REALLOC(*pparams, 10); if (params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; @@ -1438,7 +1438,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ - if(!(wcard = strdup(mask))) { + if(!(wcard = SMB_STRDUP(mask))) { dptr_close(&dptr_num); return ERROR_DOS(ERRDOS,ERRnomem); } @@ -1617,7 +1617,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return ERROR_DOS(ERRDOS,ERRunknownlevel); } - pdata = Realloc( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(pdata == NULL) return ERROR_DOS(ERRDOS,ERRnomem); @@ -1625,7 +1625,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ - params = Realloc(*pparams, 6*SIZEOFWORD); + params = SMB_REALLOC(*pparams, 6*SIZEOFWORD); if( params == NULL ) return ERROR_DOS(ERRDOS,ERRnomem); @@ -1836,7 +1836,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf return ERROR_DOS(ERRSRV,ERRinvdevice); } - pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if ( pdata == NULL ) return ERROR_DOS(ERRDOS,ERRnomem); @@ -2519,13 +2519,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * file_size = 0; } - params = Realloc(*pparams,2); + params = SMB_REALLOC(*pparams,2); if (params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; memset((char *)params,'\0',2); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; - pdata = Realloc(*ppdata, data_size); + pdata = SMB_REALLOC(*ppdata, data_size); if ( pdata == NULL ) return ERROR_DOS(ERRDOS,ERRnomem); *ppdata = pdata; @@ -3302,7 +3302,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,2); + params = SMB_REALLOC(*pparams,2); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; @@ -4028,7 +4028,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, } /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,2); + params = SMB_REALLOC(*pparams,2); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; @@ -4068,7 +4068,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char } /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,6); + params = SMB_REALLOC(*pparams,6); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; @@ -4101,7 +4101,7 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2findnotifynext\n")); /* Realloc the parameter and data sizes */ - params = Realloc(*pparams,4); + params = SMB_REALLOC(*pparams,4); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; @@ -4168,7 +4168,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { - pdata = Realloc(*ppdata, 32); + pdata = SMB_REALLOC(*ppdata, 32); if(pdata == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *ppdata = pdata; @@ -4319,9 +4319,9 @@ int reply_trans2(connection_struct *conn, /* Allocate the space for the maximum needed parameters and data */ if (total_params > 0) - params = (char *)malloc(total_params); + params = (char *)SMB_MALLOC(total_params); if (total_data > 0) - data = (char *)malloc(total_data); + data = (char *)SMB_MALLOC(total_data); if ((total_params && !params) || (total_data && !data)) { DEBUG(2,("Out of memory in reply_trans2\n")); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 10599c50a1..0102739fe3 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -188,7 +188,7 @@ NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tu return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = smb_xmalloc(sizeof(struct vfs_init_function_entry)); + entry = SMB_XMALLOC_P(struct vfs_init_function_entry); entry->name = smb_xstrdup(name); entry->vfs_op_tuples = vfs_op_tuples; @@ -261,7 +261,7 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) return False; } - handle = (vfs_handle_struct *)talloc_zero(conn->mem_ctx,sizeof(vfs_handle_struct)); + handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct); if (!handle) { DEBUG(0,("talloc_zero() failed!\n")); SAFE_FREE(module_name); @@ -684,7 +684,7 @@ static void array_promote(char *array,int elsize,int element) if (element == 0) return; - p = (char *)malloc(elsize); + p = (char *)SMB_MALLOC(elsize); if (!p) { DEBUG(5,("array_promote: malloc fail\n")); @@ -879,7 +879,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) pstrcat(tmp_fname, last_component); #ifdef REALPATH_TAKES_NULL SAFE_FREE(resolved_name); - resolved_name = strdup(tmp_fname); + resolved_name = SMB_STRDUP(tmp_fname); if (!resolved_name) { DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname)); errno = saved_errno; -- cgit From 695188cc262c08807760670c2b6d8c70deda2cdc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Dec 2004 01:07:06 +0000 Subject: r4108: As check_self is *always* False in every invokation, remove the logic for it. We still pass Samba4 RAW-LOCK test. Jeremy. (This used to be commit 596f23051363f8cc8896119b3eca0663a61a38c3) --- source3/smbd/reply.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 23657d3f1f..507e4c1c37 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1919,7 +1919,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); - if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { SMB_OFF_T size = fsp->size; SMB_OFF_T sizeneeded = startpos + maxcount; @@ -2079,7 +2079,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", data = smb_buf(outbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBread); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2268,7 +2268,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2324,7 +2324,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SCVAL(inbuf,smb_com,SMBwritec); SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwritebraw); return(ERROR_DOS(ERRDOS,ERRlock)); } @@ -2439,8 +2439,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, - WRITE_LOCK,False)) { + if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteunlock); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2508,7 +2507,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwrite); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2619,7 +2618,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2890,7 +2889,7 @@ int reply_writeclose(connection_struct *conn, mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { + if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteclose); return ERROR_DOS(ERRDOS,ERRlock); } @@ -4794,7 +4793,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadBmpx); return ERROR_DOS(ERRDOS,ERRlock); } @@ -4920,7 +4919,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) { + if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { END_PROFILE(SMBwriteBmpx); return(ERROR_DOS(ERRDOS,ERRlock)); } -- cgit From 934566332835eed5a3b768e07642c569eca37001 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 11 Dec 2004 00:30:28 +0000 Subject: r4143: Make strict locking an enum. Auto means use oplock optimization. Jeremy. (This used to be commit 0dd4adeae2042d0ea64398a78b3f48eb0150c133) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 507e4c1c37..825f76fcd5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4578,7 +4578,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, /* we don't support these - and CANCEL_LOCK makes w2k and XP reboot so I don't really want to be compatible! (tridge) */ - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } if (locktype & LOCKING_ANDX_CANCEL_LOCK) { -- cgit From 5b713a206bf9c05faad750512886f4bbeebb21f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Dec 2004 00:25:11 +0000 Subject: r4186: Fix client & server to allow 127k READX calls. Jeremy. (This used to be commit 831cb21a874601e4536c2cf76c5351e1d0defcb5) --- source3/smbd/process.c | 3 +-- source3/smbd/reply.c | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8adc5c2e66..aa1f574767 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1177,8 +1177,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) int outsize2; char inbuf_saved[smb_wct]; char outbuf_saved[smb_wct]; - int wct = CVAL(outbuf,smb_wct); - int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); + int outsize = smb_len(outbuf); /* maybe its not chained */ if (smb_com2 == 0xFF) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 825f76fcd5..3dae67efef 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2148,6 +2148,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,smb_maxcnt); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,smb_maxcnt); SCVAL(outbuf,smb_vwv0,0xFF); set_message(outbuf,12,smb_maxcnt,False); @@ -2196,9 +2197,11 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length return(UNIXERROR(ERRDOS,ERRnoaccess)); } + set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", -- cgit From 32f9ee7c206138b2f26254d9b4b7b45f4490ef38 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Dec 2004 01:11:22 +0000 Subject: r4190: When changing length calculations, get them right...... Jeremy. (This used to be commit 63cfa904ad186bb9d793584d319bd4a7107cc8b9) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index aa1f574767..1372ebbf45 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1177,7 +1177,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) int outsize2; char inbuf_saved[smb_wct]; char outbuf_saved[smb_wct]; - int outsize = smb_len(outbuf); + int outsize = smb_len(outbuf) + 4; /* maybe its not chained */ if (smb_com2 == 0xFF) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3dae67efef..eead0bc1a1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2112,6 +2112,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) { + int outsize = 0; ssize_t nread = -1; char *data = smb_buf(outbuf); @@ -2197,7 +2198,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length return(UNIXERROR(ERRDOS,ERRnoaccess)); } - set_message(outbuf,12,nread,False); + outsize = set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -2207,7 +2208,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); - return nread; + return outsize; } /**************************************************************************** -- cgit From 9e3453459c9166e71f483d67c04be2e49da6c561 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Dec 2004 01:25:24 +0000 Subject: r4212: Ensure we only look at the bottom bit of large_readx. Set the 14 word version of write if size > 0xffff as well as 64-bit offset. Jeremy. (This used to be commit 94779ccb39560bf5eecab77d70f1fa04bfcf1456) --- source3/smbd/reply.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eead0bc1a1..22cbf45e21 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2239,7 +2239,9 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,12,0,True); if (global_client_caps & CAP_LARGE_READX) { - smb_maxcnt |= ((((size_t)SVAL(inbuf,smb_vwv7)) & 1 )<<16); + if (SVAL(inbuf,smb_vwv7) == 1) { + smb_maxcnt |= (1<<16); + } if (smb_maxcnt > BUFFER_SIZE) { DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n", (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE)); -- cgit From 50f3d8f249401f7c142ca785ef0f20585a38d3a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Dec 2004 22:01:42 +0000 Subject: r4293: Fix inspired by debug trace from Rob Foehl - catch sendfile errors correctly and return the correct values we want the caller to return (-1 meaning none in correct cases). Jeremy. (This used to be commit 139c1c3488237d710ceda394c028b8dc9007bff1) --- source3/smbd/reply.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 22cbf45e21..c5ed0eb8ba 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1783,6 +1783,11 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st header.free = NULL; if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { + /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ + if (errno == ENOSYS) { + goto normal_readbraw; + } + /* * Special hack for broken Linux with no working sendfile. If we * return EINTR we sent the header but not the rest of the data. @@ -1808,6 +1813,8 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st } + normal_readbraw: + #endif if (nread > 0) { @@ -2157,12 +2164,18 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length header.length = data - outbuf; header.free = NULL; - if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { + if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) { + /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ + if (errno == ENOSYS) { + goto normal_read; + } + /* * Special hack for broken Linux with no working sendfile. If we * return EINTR we sent the header but not the rest of the data. * Fake this up by doing read/write calls. */ + if (errno == EINTR) { /* Ensure we don't do this again. */ set_use_sendfile(SNUM(conn), False); @@ -2174,7 +2187,10 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length fsp->fsp_name, strerror(errno) )); exit_server("send_file_readX: fake_sendfile failed"); } - return nread; + DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n", + fsp->fnum, (int)smb_maxcnt, (int)(nread + (data - outbuf)) ) ); + /* Returning -1 here means successful sendfile. */ + return -1; } DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", @@ -2184,6 +2200,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); + /* Returning -1 here means successful sendfile. */ return -1; } @@ -2208,6 +2225,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); + /* Returning the number of bytes we want to send back - including header. */ return outsize; } -- cgit From 52d377b75f7740b529c337c2e8585826246bc148 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Dec 2004 22:04:53 +0000 Subject: r4295: Don't include header len in data write debug. Jeremy. (This used to be commit 473babfecac87a7e1068246bddc171a464be59e5) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c5ed0eb8ba..26a0c9e7a9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2188,7 +2188,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length exit_server("send_file_readX: fake_sendfile failed"); } DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n", - fsp->fnum, (int)smb_maxcnt, (int)(nread + (data - outbuf)) ) ); + fsp->fnum, (int)smb_maxcnt, (int)nread ) ); /* Returning -1 here means successful sendfile. */ return -1; } -- cgit From ad94eabdc643c2f980bd664231d1ec6216a215cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Dec 2004 01:04:11 +0000 Subject: r4301: One more *alloc -> SMB_MALLOC (not compiled by default). Jeremy. (This used to be commit 235a0c1698db48583a6860a3a9fca9f261544365) --- source3/smbd/quotas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 3c4d4319f6..a96f50ad02 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -471,7 +471,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B len=strcspn(mnttype, ":"); pathname=strstr(mnttype, ":"); - cutstr = (char *) malloc(len+1); + cutstr = (char *) SMB_MALLOC(len+1); if (!cutstr) return False; @@ -1000,7 +1000,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B len=strcspn(mnttype, ":"); pathname=strstr(mnttype, ":"); - cutstr = (char *) malloc(len+1); + cutstr = (char *) SMB_MALLOC(len+1); if (!cutstr) return False; -- cgit From 3312191867e97a7cf3d485c050c1e689ea574f6d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Dec 2004 23:14:20 +0000 Subject: r4330: Fix for bug found by Rob Foehl . Remember to add in the bcc length for readX on named pipes. Jeremy. (This used to be commit 1168395e6a543c51f684280b00fb8c9b8bbc6ec0) --- source3/smbd/pipes.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index f7e9c595c1..6c7faa4c05 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -241,6 +241,8 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); + /* Ensure we set up the message length to include the data length read. */ + set_message_bcc(outbuf,nread); return chain_reply(inbuf,outbuf,length,bufsize); } -- cgit From 5d08f59463cf286d2b0547e6b6c44425ae8a48eb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 23 Dec 2004 02:16:57 +0000 Subject: r4337: Produce a slightly different error message is lanman authentication is disabled, rather than simply unavailable. Andrew Bartlett (This used to be commit 1c70583a19c9f741a41d08c0b994fccb66eeb0bf) --- source3/smbd/chgpasswd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index cc27d3baca..540acfc225 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -817,9 +817,14 @@ static NTSTATUS check_oem_password(const char *user, pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } else if (lm_pass_set) { - DEBUG(1, ("LM password change supplied for user %s, but we have no LanMan password to check it with\n", - user)); - pdb_free_sam(&sampass); + if (lp_lanman_auth()) { + DEBUG(1, ("LM password change supplied for user %s, but we have no LanMan password to check it with\n", + user)); + } else { + DEBUG(1, ("LM password change supplied for user %s, but we have disabled LanMan authentication\n", + user)); + } + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } else { DEBUG(1, ("password change requested for user %s, but no password supplied!\n", -- cgit From d097ea490525e7a35739dae6a295fd03ba52cfc0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 5 Jan 2005 16:20:35 +0000 Subject: r4539: patch from Rob -- adding real printcap name cache function to speed up printcap reloads (This used to be commit 1cad5250932b963c2eb9b775221b13db386d601b) --- source3/smbd/process.c | 15 +++++++-------- source3/smbd/server.c | 36 ++++++++++++++++++++++++++++++++++-- source3/smbd/service.c | 37 +------------------------------------ 3 files changed, 42 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1372ebbf45..54837c3b9a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1282,7 +1282,7 @@ static int setup_select_timeout(void) void check_reload(int t) { static time_t last_smb_conf_reload_time = 0; - static time_t last_load_printers_reload_time = 0; + static time_t last_printer_reload_time = 0; time_t printcap_cache_time = (time_t)lp_printcap_cache_time(); if(last_smb_conf_reload_time == 0) { @@ -1291,9 +1291,9 @@ void check_reload(int t) Then no printer is available till the first printers check is performed. A lower initial interval circumvents this. */ if ( printcap_cache_time > 60 ) - last_load_printers_reload_time = t - printcap_cache_time + 60; + last_printer_reload_time = t - printcap_cache_time + 60; else - last_load_printers_reload_time = t; + last_printer_reload_time = t; } if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { @@ -1308,13 +1308,12 @@ void check_reload(int t) { /* see if it's time to reload or if the clock has been set back */ - if ( (t >= last_load_printers_reload_time+printcap_cache_time) - || (t-last_load_printers_reload_time < 0) ) + if ( (t >= last_printer_reload_time+printcap_cache_time) + || (t-last_printer_reload_time < 0) ) { DEBUG( 3,( "Printcap cache time expired.\n")); - remove_stale_printers(); - load_printers(); - last_load_printers_reload_time = t; + reload_printers(); + last_printer_reload_time = t; } } } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 724a49321a..7f7d55c7e3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -463,6 +463,39 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* NOTREACHED return True; */ } +/**************************************************************************** + Reload printers +**************************************************************************/ +void reload_printers(void) +{ + int snum; + int n_services = lp_numservices(); + int pnum = lp_servicenumber(PRINTERS_NAME); + const char *pname; + + pcap_cache_reload(); + + /* remove stale printers */ + for (snum = 0; snum < n_services; snum++) { + /* avoid removing PRINTERS_NAME or non-autoloaded printers */ + if (snum == pnum || !(lp_snum_ok(snum) && lp_print_ok(snum) && + lp_autoloaded(snum))) + continue; + + pname = lp_printername(snum); + if (!pcap_printername_ok(pname)) { + DEBUG(3, ("removing stale printer %s\n", pname)); + + if (is_printer_published(NULL, snum, NULL)) + nt_printer_publish(NULL, snum, SPOOL_DS_UNPUBLISH); + del_a_printer(pname); + lp_killservice(snum); + } + } + + load_printers(); +} + /**************************************************************************** Reload the services file. **************************************************************************/ @@ -490,8 +523,7 @@ BOOL reload_services(BOOL test) ret = lp_load(dyn_CONFIGFILE, False, False, True); - remove_stale_printers(); - load_printers(); + reload_printers(); /* perhaps the config filename is now set */ if (!test) diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 3dcd803a7c..2e60adc636 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -152,10 +152,8 @@ int find_service(fstring service) int iPrinterService; if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) { - const char *pszTemp = lp_printcapname(); - DEBUG(3,("checking whether %s is a valid printer name...\n", service)); - if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) { + if (pcap_printername_ok(service)) { DEBUG(3,("%s is a valid printer name\n", service)); DEBUG(3,("adding %s as a printer service\n", service)); lp_add_printer(service, iPrinterService); @@ -863,36 +861,3 @@ void close_cnum(connection_struct *conn, uint16 vuid) conn_free(conn); } - -/**************************************************************************** - Remove stale printers -****************************************************************************/ - -void remove_stale_printers( void ) -{ - int snum, iNumServices, printersServiceNum; - const char *pname; - - iNumServices = lp_numservices(); - printersServiceNum = lp_servicenumber( PRINTERS_NAME); - for( snum = 0; snum < iNumServices; snum++) { - - /* Never remove PRINTERS_NAME */ - - if ( snum == printersServiceNum) - continue; - pname = lp_printername( snum); - - /* Is snum an autoloaded print service and still - in the printing subsystem? */ - - if ( lp_snum_ok(snum) - && lp_print_ok(snum) - && lp_autoloaded(snum) - && !pcap_printername_ok( pname, NULL)) - { - DEBUG( 3, ( "Removing printer: %s\n", pname)); - lp_killservice( snum); - } - } -} -- cgit From 94b88f8f26342b6ca4afecec459235c523355f6c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 12 Jan 2005 09:54:50 +0000 Subject: r4704: Fix encoding while receiving of a message which was actually sent using STR_ASCII. Patch from Grigory Batalov (This used to be commit dddd5726462c13374788713ad5ddcbdf9ee7b439) --- source3/smbd/message.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index f853a91475..5af7d3e451 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -127,8 +127,8 @@ int reply_sends(connection_struct *conn, outsize = set_message(outbuf,0,0,True); p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; msg = p; @@ -169,8 +169,8 @@ int reply_sendstrt(connection_struct *conn, msgpos = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); -- cgit From c3ba8b9a53617c75ffbcfa8ef32044cb1691d693 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 14 Jan 2005 19:26:13 +0000 Subject: r4736: small set of merges from rtunk to minimize the diffs (This used to be commit 4b351f2fcc365a7b7f8c22b5139c299aa54c9458) --- source3/smbd/conn.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 6b5942f7f6..26529c77a1 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -250,6 +250,10 @@ void conn_free(connection_struct *conn) conn->ngroups = 0; } + if (conn->nt_user_token) { + delete_nt_token(&(conn->nt_user_token)); + } + free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); -- cgit From d33c5aa71fb42a0fe87281812af7508bbc2a2f51 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Jan 2005 22:40:49 +0000 Subject: r4830: Fix for problem noticed by Guy Harris , return correct DOS/NT error code on transact named pipe on closed pipe handle. Jeremy. (This used to be commit 599c281464fa96725c3ee6dd3c5ee03ea81314ea) --- source3/smbd/ipc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9fcd39b500..3f21a2ac6a 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -269,7 +269,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, /* First find out the name of this file. */ if (suwcnt != 2) { DEBUG(0,("Unexpected named pipe transaction.\n")); - return(-1); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } /* Get the file handle and hence the file name. */ @@ -290,7 +290,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, } DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); - return api_no_reply(outbuf, mdrcnt); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); } DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum)); @@ -315,6 +315,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, /* Set Named Pipe Handle state */ reply = api_SNPHS(outbuf, p, params, tpscnt); break; + default: + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (!reply) -- cgit From 1ed62fde09f382342a396a047975fdeeea7113bb Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 19 Jan 2005 16:13:26 +0000 Subject: r4847: Hand over a acb_mask to pdb_setsampwent in load_sampwd_entries(). This allows the ldap-backend to search much more effeciently. Machines will be searched in the ldap_machine_suffix and users in the ldap_users_suffix. (Note that we already use the ldap_group_suffix in ldapsam_setsamgrent for quite some time). Using the specific ldap-bases becomes notably important in large domains: On my testmachine "net rpc trustdom list" has to search through 40k accounts just to list 3 interdomain-trust-accounts, similiar effects show up the non-user query_dispinfo-calls, etc. Also renamed all_machines to only_machines in load_sampwd_entries() since that reflects better what is really meant. Guenther (This used to be commit 6394257cc721ca739bda0e320375f04506913533) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4af11da784..9f2cd21425 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1874,7 +1874,7 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch /* Open the passgrp file - not for update. */ become_root(); - if(!pdb_setsampwent(False)) { + if(!pdb_setsampwent(False, 0)) { DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n")); unbecome_root(); return False; -- cgit From b4afdc08d5336e4a337e453443d7af1d8655a31a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 22 Jan 2005 03:37:09 +0000 Subject: r4925: Migrate Account Policies to passdb (esp. replicating ldapsam). Does automated migration from account_policy.tdb v1 and v2 and offers a pdbedit-Migration interface. Jerry, please feel free to revert that if you have other plans. Guenther (This used to be commit 75af83dfcd8ef365b4b1180453060ae5176389f5) --- source3/smbd/chgpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 540acfc225..3765b7d38f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -945,7 +945,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) BOOL found = False; int i, pwHisLen, curr_pwHisLen; - account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen); if (pwHisLen == 0) { return False; } @@ -1017,7 +1017,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw } /* FIXME: AP_MIN_PASSWORD_LEN and lp_min_passwd_length() need to be merged - gd */ - if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { + if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { DEBUG(1, ("user %s cannot change password - password too short\n", username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); -- cgit From d728056203c31a877a2e1ebf42b094c964bbd4ea Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jan 2005 00:13:15 +0000 Subject: r5002: Ensure we can't remove a level II oplock without having the shared memory area locked. This need to be in 3.0.11. Pointed out by Nadav Danieli . Jeremy. (This used to be commit 47ed16aefbdcb6257101c6b78c93eeb7cf048185) --- source3/smbd/oplock.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 3ebf93e560..8d1b6911e7 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -598,13 +598,13 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un /**************************************************************************** Process a level II oplock break directly. + We must call this function with the share mode entry locked. ****************************************************************************/ -BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) +static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) { extern uint32 global_client_caps; char outbuf[128]; - BOOL got_lock = False; SMB_DEV_T dev = fsp->dev; SMB_INO_T inode = fsp->inode; @@ -644,25 +644,16 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) /* * Now we must update the shared memory structure to tell * everyone else we no longer have a level II oplock on - * this open file. If local_request is true then token is - * the existing lock on the shared memory area. + * this open file. We must call this function with the share mode + * entry locked so we can change the entry directly. */ - if(!local_request && lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); - } else { - got_lock = True; - } - if(remove_share_oplock(fsp)==False) { DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); } release_file_oplock(fsp); - if (!local_request && got_lock) - unlock_share_entry_fsp(fsp); - if(level_II_oplocks_open < 0) { DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", level_II_oplocks_open)); @@ -680,6 +671,7 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) /**************************************************************************** Process an oplock break directly. + This is always called with the share mode lock *NOT* held. ****************************************************************************/ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) @@ -708,8 +700,18 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * Deal with a level II oplock going break to none separately. */ - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) - return oplock_break_level2(fsp, local_request, -1); + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + BOOL ret; + /* We must always call oplock_break_level2() with + the share mode entry locked. */ + if (lock_share_entry_fsp(fsp) == False) { + DEBUG(0,("oplock_break: unable to lock share entry for file %s\n", fsp->fsp_name )); + return False; + } + ret = oplock_break_level2(fsp, local_request); + unlock_share_entry_fsp(fsp); + return ret; + } /* Mark the oplock break as sent - we don't want to send twice! */ if (fsp->sent_oplock_break) { @@ -944,6 +946,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /**************************************************************************** Send an oplock break message to another smbd process. If the oplock is held by the local smbd then call the oplock break function directly. +Note this function is always called with the share mode lock *NOT* held. ****************************************************************************/ BOOL request_oplock_break(share_mode_entry *share_entry, BOOL async) @@ -1155,7 +1158,6 @@ void release_level_2_oplocks_on_change(files_struct *fsp) { share_mode_entry *share_list = NULL; pid_t pid = sys_getpid(); - int token = -1; int num_share_modes = 0; int i; @@ -1222,7 +1224,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) DEBUG(10,("release_level_2_oplocks_on_change: breaking our own oplock.\n")); - oplock_break_level2(new_fsp, True, token); + oplock_break_level2(new_fsp, True); } else { -- cgit From 02c25a2683204d8b20a1e69ea354b9e08b0fd94d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jan 2005 20:01:21 +0000 Subject: r5014: Split out the request to send an async level II oplock break into a new function to make it clear when it's called. Remove async parameter that had been overloaded into request_oplock_break. Inspired by work from Nadav Danieli . Jeremy. (This used to be commit 05697fb50236dfc28e81f8b3900eac17cace57c1) --- source3/smbd/open.c | 2 +- source3/smbd/oplock.c | 75 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 59 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bf3fbf7fec..70632a20eb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -665,7 +665,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry, False); + opb_ret = request_oplock_break(share_entry); /* Now relock. */ lock_share_entry(conn, dev, inode); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8d1b6911e7..a55d5443d5 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -944,12 +944,12 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, } /**************************************************************************** -Send an oplock break message to another smbd process. If the oplock is held -by the local smbd then call the oplock break function directly. -Note this function is always called with the share mode lock *NOT* held. + Send an oplock break message to another smbd process. If the oplock is held + by the local smbd then call the oplock break function directly. + This function is called with no share locks held. ****************************************************************************/ -BOOL request_oplock_break(share_mode_entry *share_entry, BOOL async) +BOOL request_oplock_break(share_mode_entry *share_entry) { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; @@ -990,7 +990,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - break_cmd_type = async ? ASYNC_LEVEL_II_OPLOCK_BREAK_CMD : LEVEL_II_OPLOCK_BREAK_CMD; + break_cmd_type = LEVEL_II_OPLOCK_BREAK_CMD; } else { break_cmd_type = OPLOCK_BREAK_CMD; } @@ -1008,7 +1008,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", addr_out.sin_family = AF_INET; if( DEBUGLVL( 3 ) ) { - dbgtext( "request_oplock_break: sending a %s oplock break message to ", async ? "asynchronous" : "synchronous" ); + dbgtext( "request_oplock_break: sending a synchronous oplock break message to " ); dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); @@ -1027,16 +1027,6 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", return False; } - /* - * If we just sent a message to a level II oplock share entry in async mode then - * we are done and may return. - */ - - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type) && async) { - DEBUG(3,("request_oplock_break: sent async break message to level II entry.\n")); - return True; - } - /* * Now we must await the oplock broken message coming back * from the target smbd process. Timeout if it fails to @@ -1149,6 +1139,57 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) return False; } +/**************************************************************************** + Send an asynchronous oplock break message to another smbd process. +****************************************************************************/ + +static BOOL request_remote_level2_async_oplock_break(share_mode_entry *share_entry) +{ + char op_break_msg[OPLOCK_BREAK_MSG_LEN]; + struct sockaddr_in addr_out; + pid_t pid = sys_getpid(); + SMB_DEV_T dev = share_entry->dev; + SMB_INO_T inode = share_entry->inode; + unsigned long file_id = share_entry->share_file_id; + + /* We need to send a ASYNC_LEVEL_II_OPLOCK_BREAK_CMD message to the port in the share mode entry. */ + + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,ASYNC_LEVEL_II_OPLOCK_BREAK_CMD); + memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); + memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); + memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); + memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); + + /* Set the address and port. */ + memset((char *)&addr_out,'\0',sizeof(addr_out)); + addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_out.sin_port = htons( share_entry->op_port ); + addr_out.sin_family = AF_INET; + + if( DEBUGLVL( 3 ) ) { + dbgtext( "request_remote_level2_async_oplock_break: sending an asynchronous oplock break message to "); + dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + } + + if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, + (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "request_remote_level2_async_oplock_break: failed when sending a oplock " ); + dbgtext( "break message to pid %d ", (int)share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + dbgtext( "Error was %s\n", strerror(errno) ); + } + return False; + } + + DEBUG(3,("request_remote_level2_async_oplock_break: sent async break message to level II entry.\n")); + return True; +} + /**************************************************************************** This function is called on any file modification or lock request. If a file is level 2 oplocked then it must tell all other level 2 holders to break to none. @@ -1234,7 +1275,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) */ DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock (async).\n")); - request_oplock_break(share_entry, True); + request_remote_level2_async_oplock_break(share_entry); } } -- cgit From de728fa81ae549b496f2ff26ebb082092aae2204 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jan 2005 21:01:58 +0000 Subject: r5063: Shamelessly steal the Samba4 logic (and some code :-) for directory evaluation. This stops us from reading the entire directory into memory at one go, and allows partial reads. It also keeps almost the same interface to the OpenDir/ReadDir etc. code (sorry James :-). Next I will optimise the findfirst with exact match code. This speeds up our interactive response for large directories, but not when a missing (ie. negative) findfirst is done. Jeremy (This used to be commit 0af1d2f6f24f238cb05e10d7d53dcd5b5e0f5f5d) --- source3/smbd/dir.c | 350 ++++++++++++++++++++++++++++----------------- source3/smbd/filename.c | 4 +- source3/smbd/notify_hash.c | 4 +- source3/smbd/reply.c | 20 +-- source3/smbd/trans2.c | 94 +++--------- 5 files changed, 251 insertions(+), 221 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f721bf3ba8..ff240b7e5a 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -612,9 +612,10 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname return(False); while (!found) { - dname = ReadDirName(conn->dirptr); + long curoff = TellDir(conn->dirptr); + dname = ReadDirName(conn->dirptr, &curoff); - DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n", + DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", (long)conn->dirptr,TellDir(conn->dirptr))); if (dname == NULL) @@ -667,14 +668,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname return(found); } -typedef struct { - int pos; - int numentries; - int mallocsize; - char *data; - char *current; -} Dir; - /******************************************************************* Check to see if a user can read a file. This is only approximate, it is used as part of the "hide unreadable" option. Don't @@ -806,117 +799,74 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT return True; } +#define NAME_CACHE_SIZE 100 + +struct name_cache_entry { + char *name; + long offset; +}; + +typedef struct { + connection_struct *conn; + DIR *dir; + long offset; + char *dir_path; + struct name_cache_entry *name_cache; + unsigned int name_cache_index; + BOOL hide_unreadable; + BOOL hide_unwriteable; + BOOL hide_special; + BOOL use_veto; + BOOL finished; +} Dir; + /******************************************************************* Open a directory. ********************************************************************/ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) { - Dir *dirp; - const char *n; - DIR *p = SMB_VFS_OPENDIR(conn,name); - int used=0; - - if (!p) - return(NULL); - dirp = SMB_MALLOC_P(Dir); + Dir *dirp = SMB_MALLOC_P(Dir); if (!dirp) { - DEBUG(0,("Out of memory in OpenDir\n")); - SMB_VFS_CLOSEDIR(conn,p); - return(NULL); + return NULL; } - dirp->pos = dirp->numentries = dirp->mallocsize = 0; - dirp->data = dirp->current = NULL; - - while (True) { - int l; - BOOL normal_entry = True; - SMB_STRUCT_STAT st; - char *entry = NULL; - - if (used == 0) { - n = "."; - normal_entry = False; - } else if (used == 2) { - n = ".."; - normal_entry = False; - } else { - n = vfs_readdirname(conn, p); - if (n == NULL) - break; - if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0)) - continue; - normal_entry = True; - } + ZERO_STRUCTP(dirp); - ZERO_STRUCT(st); - l = strlen(n)+1; + dirp->conn = conn; + dirp->use_veto = use_veto; - /* If it's a vetoed file, pretend it doesn't even exist */ - if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n)) - continue; + dirp->dir_path = SMB_STRDUP(name); + if (!dirp->dir_path) { + goto fail; + } + dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path); + if (!dirp->dir) { + DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); + goto fail; + } - /* Honour _hide unreadable_ option */ - if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) { - int ret=0; - - if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = user_can_read_file(conn, entry, &st); - } - if (!ret) { - SAFE_FREE(entry); - continue; - } - } + dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE); + if (!dirp->name_cache) { + goto fail; + } - /* Honour _hide unwriteable_ option */ - if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) { - int ret=0; - - if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = user_can_write_file(conn, entry, &st); - } - if (!ret) { - SAFE_FREE(entry); - continue; - } - } + dirp->hide_unreadable = lp_hideunreadable(SNUM(conn)); + dirp->hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); + dirp->hide_special = lp_hide_special_files(SNUM(conn)); - /* Honour _hide_special_ option */ - if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) { - int ret=0; - - if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = file_is_special(conn, entry, &st); - } - if (ret) { - SAFE_FREE(entry); - continue; - } - } + return((void *)dirp); - SAFE_FREE(entry); + fail: - if (used + l > dirp->mallocsize) { - int s = MAX(used+l,used+2000); - char *r; - r = (char *)SMB_REALLOC(dirp->data,s); - if (!r) { - DEBUG(0,("Out of memory in OpenDir\n")); - break; - } - dirp->data = r; - dirp->mallocsize = s; - dirp->current = dirp->data; + if (dirp) { + if (dirp->dir) { + SMB_VFS_CLOSEDIR(conn,dirp->dir); } - - safe_strcpy_base(dirp->data+used,n, dirp->data, dirp->mallocsize); - used += l; - dirp->numentries++; + SAFE_FREE(dirp->dir_path); + SAFE_FREE(dirp->name_cache); + SAFE_FREE(dirp); } - - SMB_VFS_CLOSEDIR(conn,p); - return((void *)dirp); + return NULL; } @@ -924,65 +874,195 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) Close a directory. ********************************************************************/ -void CloseDir(void *p) +int CloseDir(void *p) { - if (!p) - return; - SAFE_FREE(((Dir *)p)->data); - SAFE_FREE(p); + int i, ret = 0; + Dir *dirp = (Dir *)p; + + if (dirp->dir) { + ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); + } + SAFE_FREE(dirp->dir_path); + if (dirp->name_cache) { + for (i = 0; i < NAME_CACHE_SIZE; i++) { + SAFE_FREE(dirp->name_cache[i].name); + } + } + SAFE_FREE(dirp->name_cache); + SAFE_FREE(dirp); + return ret; } /******************************************************************* - Read from a directory. + Set a directory into an inactive state. ********************************************************************/ -const char *ReadDirName(void *p) +static void SleepDir(Dir *dirp) { - char *ret; - Dir *dirp = (Dir *)p; - - if (!dirp || !dirp->current || dirp->pos >= dirp->numentries) - return(NULL); + if (dirp->dir) { + SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); + dirp->dir = 0; + } + dirp->offset = 0; +} - ret = dirp->current; - dirp->current = skip_string(dirp->current,1); - dirp->pos++; +/******************************************************************* + Wake a directory into a known state. +********************************************************************/ - return(ret); +static int WakeDir(Dir *dirp, long offset) +{ + if (!dirp->dir) { + dirp->dir = SMB_VFS_OPENDIR(dirp->conn, dirp->dir_path); + if (!dirp->dir) { + DEBUG(0,("WakeDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); + dirp->finished = True; + return -1; + } + } + if (offset != dirp->offset) { + SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); + dirp->offset = SMB_VFS_TELLDIR(dirp->conn, dirp->dir); + if (dirp->offset != offset) { + DEBUG(0,("WakeDir: in path %s. offset changed %ld -> %ld\n", + dirp->dir_path, offset, dirp->offset )); + return -1; + } + } + return 0; } /******************************************************************* - Seek a dir. + Read from a directory. Also return current offset. ********************************************************************/ -BOOL SeekDir(void *p,int pos) +const char *ReadDirName(void *p, long *poffset) { + const char *n; Dir *dirp = (Dir *)p; + connection_struct *conn = dirp->conn; - if (!dirp) - return(False); + if (WakeDir(dirp, *poffset) == -1) { + return NULL; + } + + while ((n = vfs_readdirname(conn, dirp->dir))) { + struct name_cache_entry *e; + + if (!((strcmp(".",n) == 0) || (strcmp("..",n) == 0))) { + /* If it's a vetoed file, pretend it doesn't even exist */ + if (dirp->use_veto && IS_VETO_PATH(conn, n)) { + continue; + } + + if (dirp->hide_unreadable || dirp->hide_unwriteable || dirp->hide_special) { + SMB_STRUCT_STAT st; + ZERO_STRUCT(st); + char *entry = NULL; + + if (asprintf(&entry, "%s/%s/%s", conn->origpath, dirp->dir_path, n) == -1) { + return NULL; + } + /* Honour _hide unreadable_ option */ + if (dirp->hide_unreadable && !user_can_read_file(conn, entry, &st)) { + SAFE_FREE(entry); + continue; + } + /* Honour _hide unwriteable_ option */ + if (dirp->hide_unwriteable && !user_can_write_file(conn, entry, &st)) { + SAFE_FREE(entry); + continue; + } + /* Honour _hide_special_ option */ + if (dirp->hide_special && !file_is_special(conn, entry, &st)) { + SAFE_FREE(entry); + continue; + } + SAFE_FREE(entry); + } + } + + dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); + if (dirp->offset == -1) { + return NULL; + } + dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; - if (pos < dirp->pos) { - dirp->current = dirp->data; - dirp->pos = 0; + e = &dirp->name_cache[dirp->name_cache_index]; + SAFE_FREE(e->name); + e->name = SMB_STRDUP(n); + *poffset = e->offset= dirp->offset; + return e->name; } - while (dirp->pos < pos && ReadDirName(p)) - ; + dirp->finished = True; + SleepDir(dirp); + return NULL; +} + +/******************************************************************* + Seek a dir. +********************************************************************/ - return (dirp->pos == pos); +BOOL SeekDir(void *p,long offset) +{ + Dir *dirp = (Dir *)p; + return (WakeDir(dirp, offset) != -1); } /******************************************************************* Tell a dir position. ********************************************************************/ -int TellDir(void *p) +long TellDir(void *p) { Dir *dirp = (Dir *)p; + return(dirp->offset); +} - if (!dirp) - return(-1); - - return(dirp->pos); +/******************************************************************* + Find an entry by name. Leave us at the offset after it. +********************************************************************/ + +BOOL SearchDir(void *p, const char *name, long *poffset, BOOL case_sensitive) +{ + int i; + Dir *dirp = (Dir *)p; + const char *entry; + connection_struct *conn = dirp->conn; + + /* Re-create dir but don't seek. */ + if (WakeDir(dirp, dirp->offset) == -1) { + return False; + } + + /* Search back in the name cache. */ + for (i = dirp->name_cache_index; i >= 0; i--) { + struct name_cache_entry *e = &dirp->name_cache[i]; + if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { + *poffset = e->offset; + WakeDir(dirp, e->offset); + return True; + } + } + for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) { + struct name_cache_entry *e = &dirp->name_cache[i]; + if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { + *poffset = e->offset; + WakeDir(dirp, e->offset); + return True; + } + } + + /* Not found in the name cache. Rewind directory and start from scratch. */ + SMB_VFS_REWINDDIR(conn, dirp->dir); + *poffset = 0; + while ((entry = ReadDirName(dirp, poffset))) { + if (case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { + return True; + } + } + + SleepDir(dirp); + return False; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 279c9dd3c4..fa8ddfd6ca 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -435,6 +435,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name void *cur_dir; const char *dname; BOOL mangled; + long curpos; mangled = mangle_is_mangled(name); @@ -459,7 +460,8 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name } /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) { + curpos = 0; + while ((dname = ReadDirName(cur_dir, &curpos))) { /* Is it dot or dot dot. */ if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 843580f6ed..80e8fee54a 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -45,6 +45,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, size_t remaining_len; size_t fullname_len; void *dp; + long offset; ZERO_STRUCTP(data); @@ -88,7 +89,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, remaining_len = sizeof(full_name) - fullname_len - 1; p = &full_name[fullname_len]; - while ((fname = ReadDirName(dp))) { + offset = 0; + while ((fname = ReadDirName(dp, &offset))) { if(strequal(fname, ".") || strequal(fname, "..")) continue; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 26a0c9e7a9..86ee331e6b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1614,11 +1614,12 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (dirptr) { error = NT_STATUS_NO_SUCH_FILE; - + long offset = 0; + if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr))) { + while ((dname = ReadDirName(dirptr, &offset))) { pstring fname; BOOL sys_direntry = False; pstrcpy(fname,dname); @@ -3361,12 +3362,13 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) { const char *dname = NULL; BOOL ret = False; + long offset = 0; void *dirptr = OpenDir(conn, directory, False); if(dirptr == NULL) return True; - while((dname = ReadDirName(dirptr))) { + while((dname = ReadDirName(dirptr, &offset))) { pstring fullname; SMB_STRUCT_STAT st; @@ -3428,8 +3430,8 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) void *dirptr = OpenDir(conn, directory, False); if(dirptr != NULL) { - int dirpos = TellDir(dirptr); - while ((dname = ReadDirName(dirptr))) { + long dirpos = TellDir(dirptr); + while ((dname = ReadDirName(dirptr,&dirpos))) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; if(!IS_VETO_PATH(conn, dname)) { @@ -3440,7 +3442,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) if(all_veto_files) { SeekDir(dirptr,dirpos); - while ((dname = ReadDirName(dirptr))) { + while ((dname = ReadDirName(dirptr,&dirpos))) { pstring fullname; SMB_STRUCT_STAT st; @@ -3984,13 +3986,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", dirptr = OpenDir(conn, directory, True); if (dirptr) { + long offset = 0; error = NT_STATUS_NO_SUCH_FILE; /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr))) { + while ((dname = ReadDirName(dirptr, &offset))) { pstring fname; BOOL sysdir_entry = False; @@ -4337,12 +4340,13 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, dirptr = OpenDir(conn, directory, True); if (dirptr) { + long offset = 0; error = ERRbadfile; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr))) { + while ((dname = ReadDirName(dirptr, &offset))) { pstring fname; pstrcpy(fname,dname); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7269ab9157..8d3055f6cf 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -837,7 +837,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstring fname; char *p, *q, *pdata = *ppdata; uint32 reskey=0; - int prev_dirpos=0; + long prev_dirpos=0; int mode=0; SMB_OFF_T file_size = 0; SMB_BIG_UINT allocation_size = 0; @@ -866,10 +866,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, while (!found) { BOOL got_match; - /* Needed if we run out of space */ - prev_dirpos = TellDir(conn->dirptr); - dname = ReadDirName(conn->dirptr); + long curr_dirpos = prev_dirpos = TellDir(conn->dirptr); + dname = ReadDirName(conn->dirptr,&curr_dirpos); /* * Due to bugs in NT client redirectors we are not using @@ -880,8 +879,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, reskey = 0; - DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n", - (long)conn->dirptr,TellDir(conn->dirptr))); + DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n", + (long)conn->dirptr,curr_dirpos)); if (!dname) return(False); @@ -1649,7 +1648,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", /* Get the attr mask from the dptr */ dirtype = dptr_attr(dptr_num); - DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n", + DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n", dptr_num, mask, dirtype, (long)conn->dirptr, TellDir(conn->dirptr))); @@ -1671,6 +1670,16 @@ resume_key = %d resume name = %s continue=%d level = %d\n", */ if(*resume_name && !continue_bit) { + long current_pos = 0; + /* + * Remember, mangle_map is called by + * get_lanman2_dir_entry(), so the resume name + * could be mangled. Ensure we check the unmangled name. + */ + + if (mangle_is_mangled(resume_name)) { + mangle_check_cache(resume_name, sizeof(resume_name)-1); + } /* * Fix for NT redirector problem triggered by resume key indexes @@ -1678,77 +1687,10 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * and instead look for the filename to continue from (also given * to us by NT/95/smbfs/smbclient). If no other scans have been done between the * findfirst/findnext (as is usual) then the directory pointer - * should already be at the correct place. Check this by scanning - * backwards looking for an exact (ie. case sensitive) filename match. - * If we get to the beginning of the directory and haven't found it then scan - * forwards again looking for a match. JRA. + * should already be at the correct place. */ - int current_pos, start_pos; - const char *dname = NULL; - pstring dname_pstring; - void *dirptr = conn->dirptr; - start_pos = TellDir(dirptr); - for(current_pos = start_pos; current_pos >= 0; current_pos--) { - DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos)); - - SeekDir(dirptr, current_pos); - dname = ReadDirName(dirptr); - if (dname) { - /* - * Remember, mangle_map is called by - * get_lanman2_dir_entry(), so the resume name - * could be mangled. Ensure we do the same - * here. - */ - - /* make sure we get a copy that mangle_map can modify */ - - pstrcpy(dname_pstring, dname); - mangle_map( dname_pstring, False, True, SNUM(conn)); - - if(strcsequal( resume_name, dname_pstring)) { - SeekDir(dirptr, current_pos+1); - DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); - break; - } - } - } - - /* - * Scan forward from start if not found going backwards. - */ - - if(current_pos < 0) { - DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos)); - SeekDir(dirptr, start_pos); - for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) { - - /* - * Remember, mangle_map is called by - * get_lanman2_dir_entry(), so the resume name - * could be mangled. Ensure we do the same - * here. - */ - - if(dname) { - /* make sure we get a copy that mangle_map can modify */ - - pstrcpy(dname_pstring, dname); - mangle_map(dname_pstring, False, True, SNUM(conn)); - - if(strcsequal( resume_name, dname_pstring)) { - SeekDir(dirptr, current_pos+1); - DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 )); - break; - } - } - } /* end for */ - } /* end if current_pos */ - /* Can't find the name. Just resume from where we were... */ - if (dname == 0) { - SeekDir(dirptr, start_pos); - } + finished = !SearchDir(conn->dirptr, resume_name, ¤t_pos, True); } /* end if resume_name && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { -- cgit From e612109aced3284033fc2e9170bbc290d8b5d6c6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jan 2005 23:17:12 +0000 Subject: r5069: Ensure we return the correct errors for old-style search requests. Jeremy. (This used to be commit ef73dfe0d6c3b7f71109e32115d528ecdbe562ea) --- source3/smbd/reply.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 86ee331e6b..85e66d5971 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -947,18 +947,21 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size and no entries were found then return error and close dirptr (X/Open spec) */ - if(ok && expect_close && numentries == 0 && status_len == 0) { - /* Close the dptr - we know it's gone */ + if (numentries == 0 || !ok) { dptr_close(&dptr_num); - return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); - } else if (numentries == 0 || !ok) { + } else if(ok && expect_close && status_len == 0) { + /* Close the dptr - we know it's gone */ dptr_close(&dptr_num); - return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); } /* If we were called as SMBfunique, then we can close the dirptr now ! */ - if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) + if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) { dptr_close(&dptr_num); + } + + if ((numentries == 0) && !ms_has_wild(mask)) { + return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); + } SSVAL(outbuf,smb_vwv0,numentries); SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); -- cgit From 0dc388a8370c5d7852f09327fa76fe16fd0a496c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 29 Jan 2005 09:38:15 +0000 Subject: r5096: Attempt to fix the build (This used to be commit 5f34139b68460f6fb1046e2b97f16dbeff3fb136) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ff240b7e5a..4d41f88f35 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -957,8 +957,8 @@ const char *ReadDirName(void *p, long *poffset) if (dirp->hide_unreadable || dirp->hide_unwriteable || dirp->hide_special) { SMB_STRUCT_STAT st; - ZERO_STRUCT(st); char *entry = NULL; + ZERO_STRUCT(st); if (asprintf(&entry, "%s/%s/%s", conn->origpath, dirp->dir_path, n) == -1) { return NULL; -- cgit From d225b74b6dd4fa4cc0795f3b46d34187ffc63a43 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 29 Jan 2005 10:05:46 +0000 Subject: r5098: Next round build-fixing (This used to be commit 175ec3ed518704920c7c55b050ec1cc00da7f560) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 85e66d5971..81e579e97c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1616,8 +1616,8 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) */ if (dirptr) { - error = NT_STATUS_NO_SUCH_FILE; long offset = 0; + error = NT_STATUS_NO_SUCH_FILE; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); -- cgit From 91bf6cb6bfbc519773d0ffcd1d41100f14247d18 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 30 Jan 2005 00:36:19 +0000 Subject: r5100: We should only care about case-sensitivity when *reading* an incoming filename, not returning one. Makes us pass one more Samba4 RAW-SEARCH test. Jeremy. (This used to be commit 228d1e1649a0b4952eb5603cb5e1851cdc8f0c72) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 81e579e97c..56d4271213 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -910,7 +910,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (ok) { if ((dirtype&0x1F) == aVOLID) { memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive); + make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; @@ -930,7 +930,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend); if (!finished) { memcpy(p,status,21); - make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive); + make_dir_struct(p,mask,fname,size,mode,date); dptr_fill(p+12,dptr_num); numentries++; p += DIR_STRUCT_SIZE; -- cgit From 784adfbcbb7f3e85b81b3df5a5c8823663bac8d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Feb 2005 00:28:20 +0000 Subject: r5152: Restructure the directory handling code, stop using void * pointers that just allow the wrong pointer to be assigned :-) and make the interface more consistent. Fix the FreeBSD directory problem. Last thing to do is to add the "singleton" directory concept from James Peach's code. Jeremy. (This used to be commit cfa8150fd9932470cb8f3b5e14c0156dda67125d) --- source3/smbd/dir.c | 382 +++++++++++++++++++-------------------------- source3/smbd/filename.c | 2 +- source3/smbd/notify_hash.c | 2 +- source3/smbd/reply.c | 57 ++++--- source3/smbd/trans2.c | 13 +- 5 files changed, 198 insertions(+), 258 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 4d41f88f35..7f1237cb29 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -24,21 +24,43 @@ This module implements directory related functions for Samba. */ -typedef struct _dptr_struct { - struct _dptr_struct *next, *prev; +/* Make directory handle internals available. */ + +#define NAME_CACHE_SIZE 100 + +struct name_cache_entry { + char *name; + long offset; +}; + +struct smb_Dir { + connection_struct *conn; + DIR *dir; + long offset; + char *dir_path; + struct name_cache_entry *name_cache; + unsigned int name_cache_index; + BOOL hide_unreadable; + BOOL hide_unwriteable; + BOOL hide_special; + BOOL use_veto; +}; + +struct dptr_struct { + struct dptr_struct *next, *prev; int dnum; uint16 spid; - connection_struct *conn; - void *ptr; + struct connection_struct *conn; + struct smb_Dir *dir_hnd; BOOL expect_close; - char *wcard; /* Field only used for trans2_ searches */ - uint16 attr; /* Field only used for trans2_ searches */ + char *wcard; + uint16 attr; char *path; -} dptr_struct; + BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ +}; static struct bitmap *dptr_bmap; -static dptr_struct *dirptrs; - +static struct dptr_struct *dirptrs; static int dptrs_open = 0; #define INVALID_DPTR_KEY (-3) @@ -66,13 +88,12 @@ void init_dptrs(void) Idle a dptr - the directory is closed but the control info is kept. ****************************************************************************/ -static void dptr_idle(dptr_struct *dptr) +static void dptr_idle(struct dptr_struct *dptr) { - if (dptr->ptr) { + if (dptr->dir_hnd) { DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); - dptrs_open--; - CloseDir(dptr->ptr); - dptr->ptr = NULL; + CloseDir(dptr->dir_hnd); + dptr->dir_hnd = NULL; } } @@ -82,7 +103,7 @@ static void dptr_idle(dptr_struct *dptr) static void dptr_idleoldest(void) { - dptr_struct *dptr; + struct dptr_struct *dptr; /* * Go to the end of the list. @@ -100,7 +121,7 @@ static void dptr_idleoldest(void) */ for(; dptr; dptr = dptr->prev) { - if (dptr->ptr) { + if (dptr->dir_hnd) { dptr_idle(dptr); return; } @@ -108,21 +129,24 @@ static void dptr_idleoldest(void) } /**************************************************************************** - Get the dptr_struct for a dir index. + Get the struct dptr_struct for a dir index. ****************************************************************************/ -static dptr_struct *dptr_get(int key, BOOL forclose) +static struct dptr_struct *dptr_get(int key, BOOL forclose) { - dptr_struct *dptr; + struct dptr_struct *dptr; for(dptr = dirptrs; dptr; dptr = dptr->next) { if(dptr->dnum == key) { - if (!forclose && !dptr->ptr) { + if (!forclose && !dptr->dir_hnd) { if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); - DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True))) - dptrs_open++; + DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); + if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, True))) { + DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, + strerror(errno))); + return False; + } } DLIST_PROMOTE(dirptrs,dptr); return dptr; @@ -131,95 +155,65 @@ static dptr_struct *dptr_get(int key, BOOL forclose) return(NULL); } -/**************************************************************************** - Get the dptr ptr for a dir index. -****************************************************************************/ - -static void *dptr_ptr(int key) -{ - dptr_struct *dptr = dptr_get(key, False); - - if (dptr) - return(dptr->ptr); - return(NULL); -} - /**************************************************************************** Get the dir path for a dir index. ****************************************************************************/ char *dptr_path(int key) { - dptr_struct *dptr = dptr_get(key, False); - + struct dptr_struct *dptr = dptr_get(key, False); if (dptr) return(dptr->path); return(NULL); } /**************************************************************************** - Get the dir wcard for a dir index (lanman2 specific). + Get the dir wcard for a dir index. ****************************************************************************/ char *dptr_wcard(int key) { - dptr_struct *dptr = dptr_get(key, False); - + struct dptr_struct *dptr = dptr_get(key, False); if (dptr) return(dptr->wcard); return(NULL); } /**************************************************************************** - Set the dir wcard for a dir index (lanman2 specific). - Returns 0 on ok, 1 on fail. + Get the dir attrib for a dir index. ****************************************************************************/ -BOOL dptr_set_wcard(int key, char *wcard) +uint16 dptr_attr(int key) { - dptr_struct *dptr = dptr_get(key, False); - - if (dptr) { - dptr->wcard = wcard; - return True; - } - return False; + struct dptr_struct *dptr = dptr_get(key, False); + if (dptr) + return(dptr->attr); + return(0); } /**************************************************************************** - Set the dir attrib for a dir index (lanman2 specific). + Set the dir wcard for a dir index. Returns 0 on ok, 1 on fail. ****************************************************************************/ -BOOL dptr_set_attr(int key, uint16 attr) +BOOL dptr_set_wcard_and_attributes(int key, char *wcard, uint16 attr) { - dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(key, False); if (dptr) { dptr->attr = attr; + dptr->wcard = wcard; + dptr->has_wild = ms_has_wild(wcard); return True; } return False; } -/**************************************************************************** - Get the dir attrib for a dir index (lanman2 specific) -****************************************************************************/ - -uint16 dptr_attr(int key) -{ - dptr_struct *dptr = dptr_get(key, False); - - if (dptr) - return(dptr->attr); - return(0); -} - /**************************************************************************** Close a dptr (internal func). ****************************************************************************/ -static void dptr_close_internal(dptr_struct *dptr) +static void dptr_close_internal(struct dptr_struct *dptr) { DEBUG(4,("closing dptr key %d\n",dptr->dnum)); @@ -237,9 +231,8 @@ static void dptr_close_internal(dptr_struct *dptr) bitmap_clear(dptr_bmap, dptr->dnum - 1); - if (dptr->ptr) { - CloseDir(dptr->ptr); - dptrs_open--; + if (dptr->dir_hnd) { + CloseDir(dptr->dir_hnd); } /* Lanman 2 specific code */ @@ -254,14 +247,14 @@ static void dptr_close_internal(dptr_struct *dptr) void dptr_close(int *key) { - dptr_struct *dptr; + struct dptr_struct *dptr; if(*key == INVALID_DPTR_KEY) return; /* OS/2 seems to use -1 to indicate "close all directories" */ if (*key == -1) { - dptr_struct *next; + struct dptr_struct *next; for(dptr = dirptrs; dptr; dptr = next) { next = dptr->next; dptr_close_internal(dptr); @@ -288,7 +281,7 @@ void dptr_close(int *key) void dptr_closecnum(connection_struct *conn) { - dptr_struct *dptr, *next; + struct dptr_struct *dptr, *next; for(dptr = dirptrs; dptr; dptr = next) { next = dptr->next; if (dptr->conn == conn) @@ -302,9 +295,9 @@ void dptr_closecnum(connection_struct *conn) void dptr_idlecnum(connection_struct *conn) { - dptr_struct *dptr; + struct dptr_struct *dptr; for(dptr = dirptrs; dptr; dptr = dptr->next) { - if (dptr->conn == conn && dptr->ptr) + if (dptr->conn == conn && dptr->dir_hnd) dptr_idle(dptr); } } @@ -315,7 +308,7 @@ void dptr_idlecnum(connection_struct *conn) void dptr_closepath(char *path,uint16 spid) { - dptr_struct *dptr, *next; + struct dptr_struct *dptr, *next; for(dptr = dirptrs; dptr; dptr = next) { next = dptr->next; if (spid == dptr->spid && strequal(dptr->path,path)) @@ -323,35 +316,6 @@ void dptr_closepath(char *path,uint16 spid) } } -/**************************************************************************** - Start a directory listing. -****************************************************************************/ - -static BOOL start_dir(connection_struct *conn, pstring directory) -{ - const char *dir2; - - DEBUG(5,("start_dir dir=%s\n",directory)); - - if (!check_name(directory,conn)) - return(False); - - /* use a const pointer from here on */ - dir2 = directory; - - if (! *dir2) - dir2 = "."; - - conn->dirptr = OpenDir(conn, directory, True); - if (conn->dirptr) { - dptrs_open++; - string_set(&conn->dirpath,directory); - return(True); - } - - return(False); -} - /**************************************************************************** Try and close the oldest handle not marked for expect close in the hope that the client has @@ -360,7 +324,7 @@ static BOOL start_dir(connection_struct *conn, pstring directory) static void dptr_close_oldest(BOOL old) { - dptr_struct *dptr; + struct dptr_struct *dptr; /* * Go to the end of the list. @@ -393,23 +357,39 @@ static void dptr_close_oldest(BOOL old) from the bitmap range 0 - 255 as old SMBsearch directory handles are only one byte long. If old_handle is false we allocate from the range 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure - a directory handle is never zero. All the above is folklore taught to - me at Andrew's knee.... :-) :-). JRA. + a directory handle is never zero. ****************************************************************************/ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid) { - dptr_struct *dptr; + struct dptr_struct *dptr = NULL; + struct smb_Dir *dir_hnd; + const char *dir2; + + DEBUG(5,("dptr_create dir=%s\n", path)); - if (!start_dir(conn,path)) + if (!check_name(path,conn)) return(-2); /* Code to say use a unix error return code. */ + /* use a const pointer from here on */ + dir2 = path; + if (!*dir2) + dir2 = "."; + + dir_hnd = OpenDir(conn, dir2, True); + if (!dir_hnd) { + return (-2); + } + + string_set(&conn->dirpath,dir2); + if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); - dptr = SMB_MALLOC_P(dptr_struct); + dptr = SMB_MALLOC_P(struct dptr_struct); if(!dptr) { DEBUG(0,("malloc fail in dptr_create.\n")); + CloseDir(dir_hnd); return -1; } @@ -439,6 +419,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp if(dptr->dnum == -1 || dptr->dnum > 254) { DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); + CloseDir(dir_hnd); return -1; } } @@ -468,6 +449,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp if(dptr->dnum == -1 || dptr->dnum < 255) { DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); + CloseDir(dir_hnd); return -1; } } @@ -477,22 +459,55 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ - dptr->ptr = conn->dirptr; - string_set(&dptr->path,path); + string_set(&dptr->path,dir2); dptr->conn = conn; + dptr->dir_hnd = dir_hnd; dptr->spid = spid; dptr->expect_close = expect_close; dptr->wcard = NULL; /* Only used in lanman2 searches */ dptr->attr = 0; /* Only used in lanman2 searches */ + dptr->has_wild = True; /* Only used in lanman2 searches */ DLIST_ADD(dirptrs, dptr); DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", dptr->dnum,path,expect_close)); + conn->dirptr = dptr; + return(dptr->dnum); } + +/**************************************************************************** + Wrapper functions to access the lower level directory handles. +****************************************************************************/ + +int dptr_CloseDir(struct dptr_struct *dptr) +{ + return CloseDir(dptr->dir_hnd); +} + +const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset) +{ + return ReadDirName(dptr->dir_hnd, poffset); +} + +void dptr_SeekDir(struct dptr_struct *dptr, long offset) +{ + SeekDir(dptr->dir_hnd, offset); +} + +long dptr_TellDir(struct dptr_struct *dptr) +{ + return TellDir(dptr->dir_hnd); +} + +BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, BOOL case_sensitive) +{ + return SearchDir(dptr->dir_hnd, name, poffset, case_sensitive); +} + /**************************************************************************** Fill the 5 byte server reserved dptr field. ****************************************************************************/ @@ -500,15 +515,15 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp BOOL dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_ptr(key); + struct dptr_struct *dptr = dptr_get(key, False); uint32 offset; - if (!p) { + if (!dptr) { DEBUG(1,("filling null dirptr %d\n",key)); return(False); } - offset = TellDir(p); + offset = TellDir(dptr->dir_hnd); DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, - (long)p,(int)offset)); + (long)dptr->dir_hnd,(int)offset)); buf[0] = key; SIVAL(buf,1,offset | DPTR_MASK); return(True); @@ -518,38 +533,38 @@ BOOL dptr_fill(char *buf1,unsigned int key) Fetch the dir ptr and seek it given the 5 byte server field. ****************************************************************************/ -void *dptr_fetch(char *buf,int *num) +struct dptr_struct *dptr_fetch(char *buf,int *num) { unsigned int key = *(unsigned char *)buf; - void *p = dptr_ptr(key); + struct dptr_struct *dptr = dptr_get(key, False); uint32 offset; - if (!p) { + if (!dptr) { DEBUG(3,("fetched null dirptr %d\n",key)); return(NULL); } *num = key; offset = IVAL(buf,1)&~DPTR_MASK; - SeekDir(p,offset); + SeekDir(dptr->dir_hnd,(long)offset); DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", key,dptr_path(key),offset)); - return(p); + return(dptr); } /**************************************************************************** Fetch the dir ptr. ****************************************************************************/ -void *dptr_fetch_lanman2(int dptr_num) +struct dptr_struct *dptr_fetch_lanman2(int dptr_num) { - void *p = dptr_ptr(dptr_num); + struct dptr_struct *dptr = dptr_get(dptr_num, False); - if (!p) { + if (!dptr) { DEBUG(3,("fetched null dirptr %d\n",dptr_num)); return(NULL); } DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); - return(p); + return(dptr); } /**************************************************************************** @@ -612,11 +627,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname return(False); while (!found) { - long curoff = TellDir(conn->dirptr); - dname = ReadDirName(conn->dirptr, &curoff); + long curoff = TellDir(conn->dirptr->dir_hnd); + dname = ReadDirName(conn->dirptr->dir_hnd, &curoff); DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", - (long)conn->dirptr,TellDir(conn->dirptr))); + (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd))); if (dname == NULL) return(False); @@ -799,34 +814,13 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT return True; } -#define NAME_CACHE_SIZE 100 - -struct name_cache_entry { - char *name; - long offset; -}; - -typedef struct { - connection_struct *conn; - DIR *dir; - long offset; - char *dir_path; - struct name_cache_entry *name_cache; - unsigned int name_cache_index; - BOOL hide_unreadable; - BOOL hide_unwriteable; - BOOL hide_special; - BOOL use_veto; - BOOL finished; -} Dir; - /******************************************************************* Open a directory. ********************************************************************/ -void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) +struct smb_Dir *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) { - Dir *dirp = SMB_MALLOC_P(Dir); + struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir); if (!dirp) { return NULL; } @@ -854,7 +848,8 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp->hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); dirp->hide_special = lp_hide_special_files(SNUM(conn)); - return((void *)dirp); + dptrs_open++; + return dirp; fail: @@ -874,10 +869,9 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) Close a directory. ********************************************************************/ -int CloseDir(void *p) +int CloseDir(struct smb_Dir *dirp) { int i, ret = 0; - Dir *dirp = (Dir *)p; if (dirp->dir) { ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); @@ -890,62 +884,20 @@ int CloseDir(void *p) } SAFE_FREE(dirp->name_cache); SAFE_FREE(dirp); + dptrs_open--; return ret; } -/******************************************************************* - Set a directory into an inactive state. -********************************************************************/ - -static void SleepDir(Dir *dirp) -{ - if (dirp->dir) { - SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); - dirp->dir = 0; - } - dirp->offset = 0; -} - -/******************************************************************* - Wake a directory into a known state. -********************************************************************/ - -static int WakeDir(Dir *dirp, long offset) -{ - if (!dirp->dir) { - dirp->dir = SMB_VFS_OPENDIR(dirp->conn, dirp->dir_path); - if (!dirp->dir) { - DEBUG(0,("WakeDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); - dirp->finished = True; - return -1; - } - } - if (offset != dirp->offset) { - SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); - dirp->offset = SMB_VFS_TELLDIR(dirp->conn, dirp->dir); - if (dirp->offset != offset) { - DEBUG(0,("WakeDir: in path %s. offset changed %ld -> %ld\n", - dirp->dir_path, offset, dirp->offset )); - return -1; - } - } - return 0; -} - /******************************************************************* Read from a directory. Also return current offset. ********************************************************************/ -const char *ReadDirName(void *p, long *poffset) +const char *ReadDirName(struct smb_Dir *dirp, long *poffset) { const char *n; - Dir *dirp = (Dir *)p; connection_struct *conn = dirp->conn; - if (WakeDir(dirp, *poffset) == -1) { - return NULL; - } - + SeekDir(dirp, *poffset); while ((n = vfs_readdirname(conn, dirp->dir))) { struct name_cache_entry *e; @@ -994,9 +946,6 @@ const char *ReadDirName(void *p, long *poffset) *poffset = e->offset= dirp->offset; return e->name; } - - dirp->finished = True; - SleepDir(dirp); return NULL; } @@ -1004,19 +953,20 @@ const char *ReadDirName(void *p, long *poffset) Seek a dir. ********************************************************************/ -BOOL SeekDir(void *p,long offset) +void SeekDir(struct smb_Dir *dirp, long offset) { - Dir *dirp = (Dir *)p; - return (WakeDir(dirp, offset) != -1); + if (offset != dirp->offset) { + SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); + dirp->offset = offset; + } } /******************************************************************* Tell a dir position. ********************************************************************/ -long TellDir(void *p) +long TellDir(struct smb_Dir *dirp) { - Dir *dirp = (Dir *)p; return(dirp->offset); } @@ -1024,24 +974,18 @@ long TellDir(void *p) Find an entry by name. Leave us at the offset after it. ********************************************************************/ -BOOL SearchDir(void *p, const char *name, long *poffset, BOOL case_sensitive) +BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset, BOOL case_sensitive) { int i; - Dir *dirp = (Dir *)p; const char *entry; connection_struct *conn = dirp->conn; - /* Re-create dir but don't seek. */ - if (WakeDir(dirp, dirp->offset) == -1) { - return False; - } - /* Search back in the name cache. */ for (i = dirp->name_cache_index; i >= 0; i--) { struct name_cache_entry *e = &dirp->name_cache[i]; if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { *poffset = e->offset; - WakeDir(dirp, e->offset); + SeekDir(dirp, e->offset); return True; } } @@ -1049,7 +993,7 @@ BOOL SearchDir(void *p, const char *name, long *poffset, BOOL case_sensitive) struct name_cache_entry *e = &dirp->name_cache[i]; if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { *poffset = e->offset; - WakeDir(dirp, e->offset); + SeekDir(dirp, e->offset); return True; } } @@ -1062,7 +1006,5 @@ BOOL SearchDir(void *p, const char *name, long *poffset, BOOL case_sensitive) return True; } } - - SleepDir(dirp); return False; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index fa8ddfd6ca..9af73776eb 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -432,7 +432,7 @@ BOOL check_name(pstring name,connection_struct *conn) static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength) { - void *cur_dir; + struct smb_Dir *cur_dir; const char *dname; BOOL mangled; long curpos; diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 80e8fee54a..d7cb1139dc 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -44,7 +44,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, const char *fname; size_t remaining_len; size_t fullname_len; - void *dp; + struct smb_Dir *dp; long offset; ZERO_STRUCTP(data); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 56d4271213..c9e35e6a6a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -899,8 +899,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); } - dptr_set_wcard(dptr_num, SMB_STRDUP(mask)); - dptr_set_attr(dptr_num, dirtype); + dptr_set_wcard_and_attributes(dptr_num, SMB_STRDUP(mask), dirtype); } else { dirtype = dptr_attr(dptr_num); } @@ -1604,25 +1603,25 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) count++; } } else { - void *dirptr = NULL; + struct smb_Dir *dir_hnd = NULL; const char *dname; if (check_name(directory,conn)) - dirptr = OpenDir(conn, directory, True); + dir_hnd = OpenDir(conn, directory, True); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name We don't implement this yet XXXX */ - if (dirptr) { + if (dir_hnd) { long offset = 0; error = NT_STATUS_NO_SUCH_FILE; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr, &offset))) { + while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; BOOL sys_direntry = False; pstrcpy(fname,dname); @@ -1657,7 +1656,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } - CloseDir(dirptr); + CloseDir(dir_hnd); } } @@ -3366,12 +3365,12 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) const char *dname = NULL; BOOL ret = False; long offset = 0; - void *dirptr = OpenDir(conn, directory, False); + struct smb_Dir *dir_hnd = OpenDir(conn, directory, False); - if(dirptr == NULL) + if(dir_hnd == NULL) return True; - while((dname = ReadDirName(dirptr, &offset))) { + while((dname = ReadDirName(dir_hnd, &offset))) { pstring fullname; SMB_STRUCT_STAT st; @@ -3408,7 +3407,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) break; } } - CloseDir(dirptr); + CloseDir(dir_hnd); return ret; } @@ -3430,11 +3429,11 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) */ BOOL all_veto_files = True; const char *dname; - void *dirptr = OpenDir(conn, directory, False); + struct smb_Dir *dir_hnd = OpenDir(conn, directory, False); - if(dirptr != NULL) { - long dirpos = TellDir(dirptr); - while ((dname = ReadDirName(dirptr,&dirpos))) { + if(dir_hnd != NULL) { + long dirpos = TellDir(dir_hnd); + while ((dname = ReadDirName(dir_hnd,&dirpos))) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; if(!IS_VETO_PATH(conn, dname)) { @@ -3444,8 +3443,8 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) } if(all_veto_files) { - SeekDir(dirptr,dirpos); - while ((dname = ReadDirName(dirptr,&dirpos))) { + SeekDir(dir_hnd,dirpos); + while ((dname = ReadDirName(dir_hnd,&dirpos))) { pstring fullname; SMB_STRUCT_STAT st; @@ -3474,11 +3473,11 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) } else if(SMB_VFS_UNLINK(conn,fullname) != 0) break; } - CloseDir(dirptr); + CloseDir(dir_hnd); /* Retry the rmdir */ ok = (SMB_VFS_RMDIR(conn,directory) == 0); } else { - CloseDir(dirptr); + CloseDir(dir_hnd); } } else { errno = ENOTEMPTY; @@ -3981,14 +3980,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", /* * Wildcards - process each file that matches. */ - void *dirptr = NULL; + struct smb_Dir *dir_hnd = NULL; const char *dname; pstring destname; if (check_name(directory,conn)) - dirptr = OpenDir(conn, directory, True); + dir_hnd = OpenDir(conn, directory, True); - if (dirptr) { + if (dir_hnd) { long offset = 0; error = NT_STATUS_NO_SUCH_FILE; /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ @@ -3996,7 +3995,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr, &offset))) { + while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; BOOL sysdir_entry = False; @@ -4063,7 +4062,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } - CloseDir(dirptr); + CloseDir(dir_hnd); } if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) { @@ -4335,21 +4334,21 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, exists = vfs_file_exist(conn,directory,NULL); } } else { - void *dirptr = NULL; + struct smb_Dir *dir_hnd = NULL; const char *dname; pstring destname; if (check_name(directory,conn)) - dirptr = OpenDir(conn, directory, True); + dir_hnd = OpenDir(conn, directory, True); - if (dirptr) { + if (dir_hnd) { long offset = 0; error = ERRbadfile; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - while ((dname = ReadDirName(dirptr, &offset))) { + while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; pstrcpy(fname,dname); @@ -4365,7 +4364,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, count++; DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); } - CloseDir(dirptr); + CloseDir(dir_hnd); } } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8d3055f6cf..11c21650d4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -867,8 +867,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, while (!found) { BOOL got_match; /* Needed if we run out of space */ - long curr_dirpos = prev_dirpos = TellDir(conn->dirptr); - dname = ReadDirName(conn->dirptr,&curr_dirpos); + long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr); + dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos); /* * Due to bugs in NT client redirectors we are not using @@ -1303,7 +1303,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (PTR_DIFF(p,pdata) > space_remaining) { /* Move the dirptr back to prev_dirpos */ - SeekDir(conn->dirptr, prev_dirpos); + dptr_SeekDir(conn->dirptr, prev_dirpos); *out_of_space = True; DEBUG(9,("get_lanman2_dir_entry: out of space\n")); return False; /* Not finished - just out of space */ @@ -1442,8 +1442,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_DOS(ERRDOS,ERRnomem); } - dptr_set_wcard(dptr_num, wcard); - dptr_set_attr(dptr_num, dirtype); + dptr_set_wcard_and_attributes(dptr_num, wcard, dirtype); DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype)); @@ -1651,7 +1650,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n", dptr_num, mask, dirtype, (long)conn->dirptr, - TellDir(conn->dirptr))); + dptr_TellDir(conn->dirptr))); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ @@ -1690,7 +1689,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * should already be at the correct place. */ - finished = !SearchDir(conn->dirptr, resume_name, ¤t_pos, True); + finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, True); } /* end if resume_name && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { -- cgit From c1d7588c74ecfb8cf613256629e272b81f154aa6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Feb 2005 02:06:00 +0000 Subject: r5154: Tidy up interface a little. Jeremy. (This used to be commit a38eeb765f4c744ca7bf0aca86bb448240ad295d) --- source3/smbd/dir.c | 6 ++++-- source3/smbd/reply.c | 5 ++++- source3/smbd/trans2.c | 4 +--- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7f1237cb29..29ef4cbe61 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -196,13 +196,15 @@ uint16 dptr_attr(int key) Returns 0 on ok, 1 on fail. ****************************************************************************/ -BOOL dptr_set_wcard_and_attributes(int key, char *wcard, uint16 attr) +BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr) { struct dptr_struct *dptr = dptr_get(key, False); if (dptr) { dptr->attr = attr; - dptr->wcard = wcard; + dptr->wcard = SMB_STRDUP(wcard); + if (!dptr->wcard) + return False; dptr->has_wild = ms_has_wild(wcard); return True; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c9e35e6a6a..899dba56d8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -899,7 +899,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); } - dptr_set_wcard_and_attributes(dptr_num, SMB_STRDUP(mask), dirtype); + if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { + END_PROFILE(SMBsearch); + return ERROR_DOS(ERRDOS,ERRnomem); + } } else { dirtype = dptr_attr(dptr_num); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 11c21650d4..d2cef6049d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1437,13 +1437,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ - if(!(wcard = SMB_STRDUP(mask))) { + if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { dptr_close(&dptr_num); return ERROR_DOS(ERRDOS,ERRnomem); } - dptr_set_wcard_and_attributes(dptr_num, wcard, dirtype); - DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype)); /* We don't need to check for VOL here as this is returned by -- cgit From 6c6e231f15c100f1f3449f2656257e120b1071af Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 1 Feb 2005 18:14:15 +0000 Subject: r5157: BUG 2266: conditionally include rpc/nettype.h to work around missing header onf FreeBSD4 (This used to be commit 314da604735696da4cf350f35d84592356e31861) --- source3/smbd/quotas.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index a96f50ad02..1117461bc2 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -938,7 +938,9 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #include #include #include +#ifdef HAVE_RPC_NETTYPE_H #include +#endif #include static int quotastat; -- cgit From 021011f90030f6f4c39c9ef27db17eec5d4536ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Feb 2005 18:33:50 +0000 Subject: r5160: First cut at refactoring of directory code to handle non-wildcard directory match more efficiently. Passes RAW-SEARCH under valgrind but needs more testing (which I'll do later today :-). Jeremy. (This used to be commit 0b04dd9d0c6d1fe02d1b5e43f203577bf5466f33) --- source3/smbd/dir.c | 212 +++++++++++++++++++++++++++++++-------------- source3/smbd/filename.c | 2 +- source3/smbd/notify_hash.c | 12 ++- source3/smbd/reply.c | 30 +++++-- source3/smbd/trans2.c | 15 ++-- 5 files changed, 191 insertions(+), 80 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 29ef4cbe61..e9934ff49c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -40,10 +40,6 @@ struct smb_Dir { char *dir_path; struct name_cache_entry *name_cache; unsigned int name_cache_index; - BOOL hide_unreadable; - BOOL hide_unwriteable; - BOOL hide_special; - BOOL use_veto; }; struct dptr_struct { @@ -142,7 +138,7 @@ static struct dptr_struct *dptr_get(int key, BOOL forclose) if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); - if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, True))) { + if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) { DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, strerror(errno))); return False; @@ -205,7 +201,11 @@ BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr) dptr->wcard = SMB_STRDUP(wcard); if (!dptr->wcard) return False; - dptr->has_wild = ms_has_wild(wcard); + if (wcard[0] == '.' && wcard[1] == 0) { + dptr->has_wild = True; + } else { + dptr->has_wild = ms_has_wild(wcard); + } return True; } return False; @@ -378,7 +378,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp if (!*dir2) dir2 = "."; - dir_hnd = OpenDir(conn, dir2, True); + dir_hnd = OpenDir(conn, dir2); if (!dir_hnd) { return (-2); } @@ -490,11 +490,6 @@ int dptr_CloseDir(struct dptr_struct *dptr) return CloseDir(dptr->dir_hnd); } -const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset) -{ - return ReadDirName(dptr->dir_hnd, poffset); -} - void dptr_SeekDir(struct dptr_struct *dptr, long offset) { SeekDir(dptr->dir_hnd, offset); @@ -505,9 +500,90 @@ long dptr_TellDir(struct dptr_struct *dptr) return TellDir(dptr->dir_hnd); } -BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, BOOL case_sensitive) +/**************************************************************************** + Return the next visible file name, skipping veto'd and invisible files. +****************************************************************************/ + +static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) { - return SearchDir(dptr->dir_hnd, name, poffset, case_sensitive); + /* Normal search for the next file. */ + const char *name; + while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) { + if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { + return name; + } + } + return NULL; +} + +/**************************************************************************** + Return the next visible file name, skipping veto'd and invisible files. +****************************************************************************/ + +const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) +{ + pstring pathreal; + + ZERO_STRUCTP(pst); + if (dptr->has_wild) { + return dptr_normal_ReadDirName(dptr, poffset, pst); + } + + /* We know the stored wcard contains no wildcard characters. See if we can match + with a stat call. If we can't, then set has_wild to true to + prevent us from doing this on every call. */ + + /* First check if it should be visible. */ + if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) { + dptr->has_wild = True; + return dptr_normal_ReadDirName(dptr, poffset, pst); + } + + if (VALID_STAT(*pst)) { + return dptr->wcard; + } + + pstrcpy(pathreal,dptr->path); + pstrcat(pathreal,"/"); + pstrcat(pathreal,dptr->wcard); + + if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { + return dptr->wcard; + } else { + /* If we get any other error than ENOENT or ENOTDIR + then the file exists we just can't stat it. */ + if (errno != ENOENT && errno != ENOTDIR) { + return dptr->wcard; + } + } + + dptr->has_wild = True; + + /* In case sensitive mode we don't search - we know if it doesn't exist + with a stat we will fail. */ + + if (dptr->conn->case_sensitive) { + return NULL; + } else { + return dptr_normal_ReadDirName(dptr, poffset, pst); + } +} + +/**************************************************************************** + Search for a file by name, skipping veto'ed and not visible files. +****************************************************************************/ + +BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) +{ + BOOL ret; + + ZERO_STRUCTP(pst); + while ((ret = SearchDir(dptr->dir_hnd, name, poffset)) == True) { + if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { + return True; + } + } + return False; } /**************************************************************************** @@ -573,7 +649,7 @@ struct dptr_struct *dptr_fetch_lanman2(int dptr_num) Check a filetype for being valid. ****************************************************************************/ -BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype) +BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype) { int mask; @@ -629,8 +705,8 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname return(False); while (!found) { - long curoff = TellDir(conn->dirptr->dir_hnd); - dname = ReadDirName(conn->dirptr->dir_hnd, &curoff); + long curoff = dptr_TellDir(conn->dirptr); + dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf); DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd))); @@ -661,14 +737,14 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (SMB_VFS_STAT(conn, pathreal, &sbuf) != 0) { + if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; } *mode = dos_mode(conn,pathreal,&sbuf); - if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) { + if (!dir_check_ftype(conn,*mode,dirtype)) { DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); continue; } @@ -816,11 +892,58 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT return True; } +/******************************************************************* + Should the file be seen by the client ? +********************************************************************/ + +BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto) +{ + BOOL hide_unreadable = lp_hideunreadable(SNUM(conn)); + BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); + BOOL hide_special = lp_hide_special_files(SNUM(conn)); + + ZERO_STRUCT(pst); + + if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) { + return True; /* . and .. are always visible. */ + } + + /* If it's a vetoed file, pretend it doesn't even exist */ + if (use_veto && IS_VETO_PATH(conn, name)) { + return False; + } + + if (hide_unreadable || hide_unwriteable || hide_special) { + char *entry = NULL; + + if (asprintf(&entry, "%s/%s", dir_path, name) == -1) { + return False; + } + /* Honour _hide unreadable_ option */ + if (hide_unreadable && !user_can_read_file(conn, entry, pst)) { + SAFE_FREE(entry); + return False; + } + /* Honour _hide unwriteable_ option */ + if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) { + SAFE_FREE(entry); + return False; + } + /* Honour _hide_special_ option */ + if (hide_special && !file_is_special(conn, entry, pst)) { + SAFE_FREE(entry); + return False; + } + SAFE_FREE(entry); + } + return True; +} + /******************************************************************* Open a directory. ********************************************************************/ -struct smb_Dir *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) +struct smb_Dir *OpenDir(connection_struct *conn, const char *name) { struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir); if (!dirp) { @@ -829,7 +952,6 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name, BOOL use_veto ZERO_STRUCTP(dirp); dirp->conn = conn; - dirp->use_veto = use_veto; dirp->dir_path = SMB_STRDUP(name); if (!dirp->dir_path) { @@ -846,10 +968,6 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name, BOOL use_veto goto fail; } - dirp->hide_unreadable = lp_hideunreadable(SNUM(conn)); - dirp->hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); - dirp->hide_special = lp_hide_special_files(SNUM(conn)); - dptrs_open++; return dirp; @@ -892,6 +1010,7 @@ int CloseDir(struct smb_Dir *dirp) /******************************************************************* Read from a directory. Also return current offset. + Don't check for veto or invisible files. ********************************************************************/ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) @@ -902,40 +1021,6 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) SeekDir(dirp, *poffset); while ((n = vfs_readdirname(conn, dirp->dir))) { struct name_cache_entry *e; - - if (!((strcmp(".",n) == 0) || (strcmp("..",n) == 0))) { - /* If it's a vetoed file, pretend it doesn't even exist */ - if (dirp->use_veto && IS_VETO_PATH(conn, n)) { - continue; - } - - if (dirp->hide_unreadable || dirp->hide_unwriteable || dirp->hide_special) { - SMB_STRUCT_STAT st; - char *entry = NULL; - ZERO_STRUCT(st); - - if (asprintf(&entry, "%s/%s/%s", conn->origpath, dirp->dir_path, n) == -1) { - return NULL; - } - /* Honour _hide unreadable_ option */ - if (dirp->hide_unreadable && !user_can_read_file(conn, entry, &st)) { - SAFE_FREE(entry); - continue; - } - /* Honour _hide unwriteable_ option */ - if (dirp->hide_unwriteable && !user_can_write_file(conn, entry, &st)) { - SAFE_FREE(entry); - continue; - } - /* Honour _hide_special_ option */ - if (dirp->hide_special && !file_is_special(conn, entry, &st)) { - SAFE_FREE(entry); - continue; - } - SAFE_FREE(entry); - } - } - dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); if (dirp->offset == -1) { return NULL; @@ -974,9 +1059,10 @@ long TellDir(struct smb_Dir *dirp) /******************************************************************* Find an entry by name. Leave us at the offset after it. + Don't check for veto or invisible files. ********************************************************************/ -BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset, BOOL case_sensitive) +BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) { int i; const char *entry; @@ -985,7 +1071,7 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset, BOOL case_ /* Search back in the name cache. */ for (i = dirp->name_cache_index; i >= 0; i--) { struct name_cache_entry *e = &dirp->name_cache[i]; - if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { + if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { *poffset = e->offset; SeekDir(dirp, e->offset); return True; @@ -993,7 +1079,7 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset, BOOL case_ } for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) { struct name_cache_entry *e = &dirp->name_cache[i]; - if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { + if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { *poffset = e->offset; SeekDir(dirp, e->offset); return True; @@ -1004,7 +1090,7 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset, BOOL case_ SMB_VFS_REWINDDIR(conn, dirp->dir); *poffset = 0; while ((entry = ReadDirName(dirp, poffset))) { - if (case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { + if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { return True; } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9af73776eb..c04b43b873 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -454,7 +454,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name mangled = !mangle_check_cache( name, maxlength ); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) { + if (!(cur_dir = OpenDir(conn, path))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); } diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index d7cb1139dc..b16b767783 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -76,7 +76,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * larger than the max time_t value). */ - dp = OpenDir(conn, path, True); + dp = OpenDir(conn, path); if (dp == NULL) return False; @@ -91,18 +91,22 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, offset = 0; while ((fname = ReadDirName(dp, &offset))) { + ZERO_STRUCT(st); if(strequal(fname, ".") || strequal(fname, "..")) continue; + if (!is_visible_file(conn, path, fname, &st, True)) + continue; + data->num_entries++; safe_strcpy(p, fname, remaining_len); - ZERO_STRUCT(st); - /* * Do the stat - but ignore errors. */ - SMB_VFS_STAT(conn,full_name, &st); + if (!VALID_STAT(st)) { + SMB_VFS_STAT(conn,full_name, &st); + } /* * Always sum the times. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 899dba56d8..748d9958bc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1610,7 +1610,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) const char *dname; if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory, True); + dir_hnd = OpenDir(conn, directory); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -1625,10 +1625,15 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) pstrcpy(mask,"*"); while ((dname = ReadDirName(dir_hnd, &offset))) { + SMB_STRUCT_STAT st; pstring fname; BOOL sys_direntry = False; pstrcpy(fname,dname); + if (!is_visible_file(conn, directory, dname, &st, True)) { + continue; + } + /* Quick check for "." and ".." */ if (fname[0] == '.') { if (!fname[1] || (fname[1] == '.' && !fname[2])) { @@ -3368,7 +3373,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) const char *dname = NULL; BOOL ret = False; long offset = 0; - struct smb_Dir *dir_hnd = OpenDir(conn, directory, False); + struct smb_Dir *dir_hnd = OpenDir(conn, directory); if(dir_hnd == NULL) return True; @@ -3380,6 +3385,9 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; + if (!is_visible_file(conn, directory, dname, &st, False)) + continue; + /* Construct the full name. */ if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { errno = ENOMEM; @@ -3421,6 +3429,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) BOOL rmdir_internals(connection_struct *conn, char *directory) { BOOL ok; + SMB_STRUCT_STAT st; ok = (SMB_VFS_RMDIR(conn,directory) == 0); if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { @@ -3432,13 +3441,15 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) */ BOOL all_veto_files = True; const char *dname; - struct smb_Dir *dir_hnd = OpenDir(conn, directory, False); + struct smb_Dir *dir_hnd = OpenDir(conn, directory); if(dir_hnd != NULL) { long dirpos = TellDir(dir_hnd); while ((dname = ReadDirName(dir_hnd,&dirpos))) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; + if (!is_visible_file(conn, directory, dname, &st, False)) + continue; if(!IS_VETO_PATH(conn, dname)) { all_veto_files = False; break; @@ -3449,10 +3460,11 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) SeekDir(dir_hnd,dirpos); while ((dname = ReadDirName(dir_hnd,&dirpos))) { pstring fullname; - SMB_STRUCT_STAT st; if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; + if (!is_visible_file(conn, directory, dname, &st, False)) + continue; /* Construct the full name. */ if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { @@ -3988,7 +4000,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", pstring destname; if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory, True); + dir_hnd = OpenDir(conn, directory); if (dir_hnd) { long offset = 0; @@ -4015,6 +4027,9 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } } + if (!is_visible_file(conn, directory, dname, &sbuf1, False)) + continue; + if(!mask_match(fname, mask, conn->case_sensitive)) continue; @@ -4342,7 +4357,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring destname; if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory, True); + dir_hnd = OpenDir(conn, directory); if (dir_hnd) { long offset = 0; @@ -4355,6 +4370,9 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring fname; pstrcpy(fname,dname); + if (!is_visible_file(conn, directory, dname, &sbuf1, False)) + continue; + if(!mask_match(fname, mask, conn->case_sensitive)) continue; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d2cef6049d..b5029ccd77 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -864,11 +864,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } else pstrcpy(mask, path_mask); + while (!found) { BOOL got_match; /* Needed if we run out of space */ long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr); - dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos); + dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf); /* * Due to bugs in NT client redirectors we are not using @@ -922,7 +923,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pathreal,strerror(errno))); continue; } - } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { /* Needed to show the msdfs symlinks as * directories */ @@ -945,7 +946,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mode = dos_mode(conn,pathreal,&sbuf); - if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) { + if (!dir_check_ftype(conn,mode,dirtype)) { DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); continue; } @@ -1341,7 +1342,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb int info_level = SVAL(params,6); pstring directory; pstring mask; - char *p, *wcard; + char *p; int last_name_off=0; int dptr_num = -1; int numentries = 0; @@ -1442,7 +1443,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_DOS(ERRDOS,ERRnomem); } - DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype)); + DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ @@ -1667,6 +1668,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", */ if(*resume_name && !continue_bit) { + SMB_STRUCT_STAT st; + long current_pos = 0; /* * Remember, mangle_map is called by @@ -1687,7 +1690,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", * should already be at the correct place. */ - finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, True); + finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st); } /* end if resume_name && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { -- cgit From c1b9243c2892220b906df86d7b021d1bf18571b6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 1 Feb 2005 20:43:14 +0000 Subject: r5165: BUG 2295: always use get_local_machine_name() rather than digging in the gloval variable 'local_machine' (This used to be commit 6a6e4af46a5c0a693a3dd9d558a4d1c1e5d72d95) --- source3/smbd/ipc.c | 11 ++++++----- source3/smbd/lanman.c | 10 ++++------ source3/smbd/msdfs.c | 7 +++---- source3/smbd/trans2.c | 5 ++--- 4 files changed, 15 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3f21a2ac6a..e3f6521fba 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -29,8 +29,6 @@ extern int max_send; -extern fstring local_machine; - #define NERR_notsupported 50 extern int smb_read_error; @@ -382,6 +380,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int unsigned int dscnt = SVAL(inbuf,smb_vwv11); unsigned int dsoff = SVAL(inbuf,smb_vwv12); unsigned int suwcnt = CVAL(inbuf,smb_vwv13); + fstring local_machine_name; START_PROFILE(SMBtrans); memset(name, '\0',sizeof(name)); @@ -543,9 +542,11 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int * WinCE wierdness.... */ - if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) && - (name[strlen(local_machine)+1] == '\\')) - name_offset = strlen(local_machine)+1; + fstrcpy( local_machine_name, get_local_machine_name() ); + + if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine_name, strlen(local_machine_name)) == 0) && + (name[strlen(local_machine_name)+1] == '\\')) + name_offset = strlen(local_machine_name)+1; if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) { name_offset += strlen("\\PIPE"); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 9f2cd21425..d8c5201ce6 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -32,8 +32,6 @@ #endif #define CHECK_TYPES 0 -extern fstring local_machine; - #define NERR_Success 0 #define NERR_badpass 86 #define NERR_notsupported 50 @@ -2372,7 +2370,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par p = *rdata; p2 = p + struct_len; if (uLevel != 20) { - srvstr_push(NULL, p,local_machine,16, + srvstr_push(NULL, p,get_local_machine_name(),16, STR_ASCII|STR_UPPER|STR_TERMINATE); } p += 16; @@ -2387,7 +2385,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;ialternate_path, sizeof(pstring)-1, - "\\\\%s\\%s", local_machine, service_name); + "\\\\%s\\%s", get_local_machine_name(), service_name); cnt++; /* Now enumerate all dfs links */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b5029ccd77..18fd5c946f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -25,7 +25,6 @@ extern enum protocol_types Protocol; extern int smb_read_error; -extern fstring local_machine; extern int global_oplock_break; extern uint32 global_client_caps; extern struct current_user current_user; @@ -1825,7 +1824,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi * Add volume serial number - hash of a combination of * the called hostname and the service name. */ - SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); + SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) ); len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; @@ -1868,7 +1867,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi * the called hostname and the service name. */ SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ - (str_checksum(local_machine)<<16)); + (str_checksum(get_local_machine_name())<<16)); len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE); SIVAL(pdata,12,len); -- cgit From 91ef89daa03551fa17ff78adb9f36420057948da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Feb 2005 02:02:54 +0000 Subject: r5183: Ensure we correctly set the per-connection "case_sensitive" setting. Rename dptrs_open to the more correct dirhandles_open. Remove old #if 1. Jeremy. (This used to be commit c43bae306a18f5716acbe8571f4f414873400cb1) --- source3/smbd/dir.c | 10 +++++----- source3/smbd/filename.c | 4 ---- source3/smbd/service.c | 27 ++++++++++++++++++--------- 3 files changed, 23 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index e9934ff49c..fb1a700074 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -57,7 +57,7 @@ struct dptr_struct { static struct bitmap *dptr_bmap; static struct dptr_struct *dirptrs; -static int dptrs_open = 0; +static int dirhandles_open = 0; #define INVALID_DPTR_KEY (-3) @@ -135,7 +135,7 @@ static struct dptr_struct *dptr_get(int key, BOOL forclose) for(dptr = dirptrs; dptr; dptr = dptr->next) { if(dptr->dnum == key) { if (!forclose && !dptr->dir_hnd) { - if (dptrs_open >= MAX_OPEN_DIRECTORIES) + if (dirhandles_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) { @@ -385,7 +385,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp string_set(&conn->dirpath,dir2); - if (dptrs_open >= MAX_OPEN_DIRECTORIES) + if (dirhandles_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); dptr = SMB_MALLOC_P(struct dptr_struct); @@ -968,7 +968,7 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name) goto fail; } - dptrs_open++; + dirhandles_open++; return dirp; fail: @@ -1004,7 +1004,7 @@ int CloseDir(struct smb_Dir *dirp) } SAFE_FREE(dirp->name_cache); SAFE_FREE(dirp); - dptrs_open--; + dirhandles_open--; return ret; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index c04b43b873..8c484dd232 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,11 +150,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } -#if 1 if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)) -#else - if (!conn->case_sensitive && (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve))) -#endif strnorm(name, lp_defaultcase(SNUM(conn))); start = name; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2e60adc636..f199fe3ade 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -60,17 +60,26 @@ BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir) last_flags = flags; /* Obey the client case sensitivity requests - only for clients that support it. */ - if (lp_casesensitive(snum) == Auto) { - /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */ - enum remote_arch_types ra_type = get_remote_arch(); - if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { - /* Client can't support per-packet case sensitive pathnames. */ + switch (lp_casesensitive(snum)) { + case Auto: + { + /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */ + enum remote_arch_types ra_type = get_remote_arch(); + if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { + /* Client can't support per-packet case sensitive pathnames. */ + conn->case_sensitive = False; + } else { + conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES); + } + } + break; + case True: + conn->case_sensitive = True; + break; + default: conn->case_sensitive = False; - } else { - conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES); - } + break; } - magic_char = lp_magicchar(snum); return(True); } -- cgit From 8a2b44e56fd9ca32fa7de8cd3d0286ef7067cbf2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 4 Feb 2005 07:01:33 +0000 Subject: r5225: fix mem leak and debug message metze (This used to be commit c0ee5922cdd4e57007e3a8f16cae71550fb38f2e) --- source3/smbd/nttrans.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2395d0d8db..5758b9d716 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2143,6 +2143,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA); if (shadow_data == NULL) { DEBUG(0,("talloc_zero() failed!\n")); + talloc_destroy(shadow_mem_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -2310,7 +2311,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, /* access check */ if (current_user.uid != 0) { - DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", + DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRDOS,ERRnoaccess); } -- cgit From d09914d218c53b92ffcd4a276c3ce3f33ef5389f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Feb 2005 22:06:49 +0000 Subject: r5268: Fix bug #2310, only do 16-bit normalization on small dfree request. Jeremy. (This used to be commit 96dfec739a7ab6ac082d530ca2b771f9d6acabc6) --- source3/smbd/dfree.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index f93cdf3791..c556c8c8ab 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -36,11 +36,11 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree, errors */ } - while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) { - *dfree /= 2; - *dsize /= 2; - *bsize *= 2; - if(small_query) { + if(small_query) { + while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) { + *dfree /= 2; + *dsize /= 2; + *bsize *= 2; /* * Force max to fit in 16 bit fields. */ -- cgit From a572700531aeca75c62d1a189efd4606dfa8b354 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 9 Feb 2005 21:23:33 +0000 Subject: r5287: fix build problem when HAVE_POSIX_ACL not defined (This used to be commit 2bd0253c11977122b195dc2f685d5367869973fd) --- source3/smbd/trans2.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 18fd5c946f..1d925e81de 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2191,6 +2191,7 @@ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint return UNIXERROR(def_class,def_code); } +#if defined(HAVE_POSIX_ACLS) /**************************************************************************** Utility function to count the number of entries in a POSIX acl. ****************************************************************************/ @@ -2305,6 +2306,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ return True; } +#endif /**************************************************************************** Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by @@ -2870,6 +2872,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * break; } +#if defined(HAVE_POSIX_ACLS) case SMB_QUERY_POSIX_ACL: { SMB_ACL_T file_acl = NULL; @@ -2946,6 +2949,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE; break; } +#endif default: return ERROR_DOS(ERRDOS,ERRunknownlevel); @@ -3755,6 +3759,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return(-1); } +#if defined(HAVE_POSIX_ACLS) case SMB_SET_POSIX_ACL: { uint16 posix_acl_version; @@ -3804,6 +3809,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); } +#endif default: return ERROR_DOS(ERRDOS,ERRunknownlevel); -- cgit From 2257618d7f282ebc7b99279728b4f05c6593c02b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Feb 2005 23:46:14 +0000 Subject: r5290: Fix for bug #2323 - plaintext problem with WinXP. Jeremy. (This used to be commit 3e10c36cb50462d1f220029e8fa64c3b6e554e6c) --- source3/smbd/sesssetup.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index cff7d7371c..40ea28a86d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -755,10 +755,18 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, pstring pass; BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS; +#if 0 + /* This was the previous fix. Not sure if it's still valid. JRA. */ if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) { /* NT4.0 stuffs up plaintext unicode password lengths... */ srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1, sizeof(pass), passlen1, STR_TERMINATE); +#endif + + if (unic && (passlen2 == 0) && passlen1) { + /* Only a ascii plaintext password was sent. */ + srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), + passlen1, STR_TERMINATE|STR_ASCII); } else { srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), unic ? passlen2 : passlen1, -- cgit From fbd9e4098333e7d121207ae6991e525768d411e0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Feb 2005 02:14:49 +0000 Subject: r5324: In order to process DELETE_ACCESS correctly and return access denied to a WXPSP2 client we must do permission checking in userspace first (this is a race condition but what can you do...). Needed for bugid #2227. Jeremy. (This used to be commit da23577f162b6bdca7d631fca256a9b3b04043e4) --- source3/smbd/nttrans.c | 18 ++++++++++++++++++ source3/smbd/posix_acls.c | 11 +++++++++++ source3/smbd/reply.c | 18 +++++++++++------- 3 files changed, 40 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5758b9d716..ea155a8edb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -780,6 +780,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib } } + if (desired_access & DELETE_ACCESS) { + status = can_delete(conn, fname, file_attributes, bad_path, True); + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_IS_A_DIRECTORY)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(status); + } + } + /* * If it's a request for a directory open, deal with it separately. */ @@ -1319,6 +1328,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } + if (desired_access & DELETE_ACCESS) { + status = can_delete(conn, fname, file_attributes, bad_path, True); + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_IS_A_DIRECTORY)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(status); + } + } + /* * If it's a request for a directory open, deal with it separately. */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 903b943522..b3976fdecb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3753,3 +3753,14 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); return True; } + +/**************************************************************************** + Actually emulate the in-kernel access checking for write access. We need + this to successfully return ACCESS_DENIED on a file open for delete access. +****************************************************************************/ + +BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) +{ + /* Add acl check here... JRA */ + return True; +} diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 748d9958bc..68705a8aea 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1438,7 +1438,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Check if a user is allowed to rename a file. ********************************************************************/ -static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst) +static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst) { int smb_action; int access_mode; @@ -1479,7 +1479,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, Check if a user is allowed to delete a file. ********************************************************************/ -static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path) +NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open) { SMB_STRUCT_STAT sbuf; int fmode; @@ -1520,6 +1520,10 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOO if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return NT_STATUS_NO_SUCH_FILE; + if (check_is_at_open && !can_delete_file_in_directory(conn, fname)) { + return NT_STATUS_ACCESS_DENIED; + } + /* We need a better way to return NT status codes from open... */ unix_ERR_class = 0; unix_ERR_code = 0; @@ -1598,7 +1602,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - error = can_delete(directory,conn,dirtype,bad_path); + error = can_delete(conn,directory,dirtype,bad_path,False); if (!NT_STATUS_IS_OK(error)) return error; @@ -1656,7 +1660,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) } slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - error = can_delete(fname,conn,dirtype,bad_path); + error = can_delete(conn,fname,dirtype,bad_path,False); if (!NT_STATUS_IS_OK(error)) { continue; } @@ -3744,7 +3748,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * return NT_STATUS_OBJECT_NAME_COLLISION; } - error = can_rename(newname,conn,attrs,&sbuf); + error = can_rename(conn,newname,attrs,&sbuf); if (dest_exists && !NT_STATUS_IS_OK(error)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", @@ -3950,7 +3954,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - error = can_rename(directory,conn,attrs,&sbuf1); + error = can_rename(conn,directory,attrs,&sbuf1); if (!NT_STATUS_IS_OK(error)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", @@ -4045,7 +4049,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error))); continue; } - error = can_rename(fname,conn,attrs,&sbuf1); + error = can_rename(conn,fname,attrs,&sbuf1); if (!NT_STATUS_IS_OK(error)) { DEBUG(6,("rename %s refused\n", fname)); continue; -- cgit From 0f87a9ada358020874206cf65db5c62a0a83ddbb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Feb 2005 20:00:30 +0000 Subject: r5343: Fix for bug#1525. Timestamps interpreted incorrectly on 64-bit time_t values. Jeremy. (This used to be commit 00f8ac509aaf2f40a067f5fe5c7699ae6f26571e) --- source3/smbd/trans2.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1d925e81de..e8090792b0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -800,21 +800,6 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps return ret; } -/**************************************************************************** - Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date. -****************************************************************************/ - -time_t interpret_long_unix_date(char *p) -{ - DEBUG(10,("interpret_long_unix_date\n")); - if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO && - IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) { - return -1; - } else { - return interpret_long_date(p); - } -} - /**************************************************************************** Get a level dependent lanman2 dir entry. ****************************************************************************/ @@ -3331,7 +3316,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char tvs.modtime = MIN(write_time, changed_time); - if (write_time > tvs.modtime && write_time != 0xffffffff) { + if (write_time > tvs.modtime && write_time != (time_t)-1) { tvs.modtime = write_time; } /* Prefer a defined time to an undefined one. */ @@ -3510,8 +3495,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #endif /* LARGE_SMB_OFF_T */ } pdata+=24; /* ctime & st_blocks are not changed */ - tvs.actime = interpret_long_unix_date(pdata); /* access_time */ - tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */ + tvs.actime = interpret_long_date(pdata); /* access_time */ + tvs.modtime = interpret_long_date(pdata+8); /* modification_time */ pdata+=16; set_owner = (uid_t)IVAL(pdata,0); pdata += 8; -- cgit From 6c84ecb55657ae28eb739a72164f6d7251dc627f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 12 Feb 2005 00:51:31 +0000 Subject: r5349: After talking with Jerry, reverted the addition of account policies to passdb in 3_0 (they are still in trunk). Guenther (This used to be commit fdf9bdbbac1d8d4f3b3e1fc7e49c1e659b9301b1) --- source3/smbd/chgpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 3765b7d38f..540acfc225 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -945,7 +945,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) BOOL found = False; int i, pwHisLen, curr_pwHisLen; - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen); + account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); if (pwHisLen == 0) { return False; } @@ -1017,7 +1017,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw } /* FIXME: AP_MIN_PASSWORD_LEN and lp_min_passwd_length() need to be merged - gd */ - if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { + if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { DEBUG(1, ("user %s cannot change password - password too short\n", username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); -- cgit From 70be7d71924d8ae23837c7555d65f12a0dfaa284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 12 Feb 2005 01:05:49 +0000 Subject: r5355: Fill in the access check code for POSIX ACLs to *really* fix bug #2227. Jeremy. (This used to be commit ecc134a2e3546ed77ab6f1dafc0249c78897e1f3) --- source3/smbd/posix_acls.c | 150 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b3976fdecb..d02edc5ea0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3754,6 +3754,128 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * return True; } +/**************************************************************************** + Check for POSIX group ACLs. If none use stat entry. +****************************************************************************/ + +static int check_posix_acl_group_write(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *psbuf) +{ + extern struct current_user current_user; + SMB_ACL_T posix_acl = NULL; + int entry_id = SMB_ACL_FIRST_ENTRY; + SMB_ACL_ENTRY_T entry; + int i; + int ret = -1; + + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, dname, SMB_ACL_TYPE_ACCESS)) == NULL) { + goto check_stat; + } + + /* First ensure the group mask allows group read. */ + while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; + + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) + entry_id = SMB_ACL_NEXT_ENTRY; + + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) { + goto check_stat; + } + + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { + goto check_stat; + } + + switch(tagtype) { + case SMB_ACL_MASK: + if (!SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE)) { + /* We don't have group write permission. */ + ret = -1; /* Allow caller to check "other" permissions. */ + goto done; + } + break; + default: + continue; + } + } + + /* Now check all group entries. */ + entry_id = SMB_ACL_FIRST_ENTRY; + while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { + SMB_ACL_TAG_T tagtype; + SMB_ACL_PERMSET_T permset; + int have_write = -1; + + /* get_next... */ + if (entry_id == SMB_ACL_FIRST_ENTRY) + entry_id = SMB_ACL_NEXT_ENTRY; + + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) { + goto check_stat; + } + + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { + goto check_stat; + } + + have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE); + if (have_write == -1) { + goto check_stat; + } + + switch(tagtype) { + case SMB_ACL_USER: + { + /* Check against current_user.uid. */ + uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + if (puid == NULL) { + goto check_stat; + } + if (current_user.uid == *puid) { + /* We're done now we have a uid match. */ + ret = have_write; + goto done; + } + } + break; + case SMB_ACL_MASK: + { + gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + if (pgid == NULL) { + goto check_stat; + } + for (i = 0; i < current_user.ngroups; i++) { + if (current_user.groups[i] == *pgid) { + /* We're done now we have a gid match. */ + ret = have_write; + goto done; + } + } + } + break; + default: + continue; + } + } + + + check_stat: + + for (i = 0; i < current_user.ngroups; i++) { + if (current_user.groups[i] == psbuf->st_gid) { + ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; + break; + } + } + + done: + + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + return ret; +} + /**************************************************************************** Actually emulate the in-kernel access checking for write access. We need this to successfully return ACCESS_DENIED on a file open for delete access. @@ -3761,6 +3883,30 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) { - /* Add acl check here... JRA */ - return True; + extern struct current_user current_user; + SMB_STRUCT_STAT sbuf; + pstring dname; + int ret; + + pstrcpy(dname, parent_dirname(fname)); + if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) { + return False; + } + if (!S_ISDIR(sbuf.st_mode)) { + return False; + } + if (current_user.uid == 0) { + /* I'm sorry sir, I didn't know you were root... */ + return True; + } + + if (current_user.uid == sbuf.st_uid) { + return (sbuf.st_mode & S_IWUSR) ? True : False; + } + /* Check group ownership. */ + ret = check_posix_acl_group_write(conn, dname, &sbuf); + if (ret == 0 || ret == 1) { + return ret ? True : False; + } + return (sbuf.st_mode & S_IWOTH) ? True : False; } -- cgit From 6baedb3d3f1f4cafb82c4a8d619cb972d5a42382 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Feb 2005 05:11:37 +0000 Subject: r5497: Fix for DIR1 failures in build farm. It struck me that we only care about failing with ACCESS_DENIED if we can't delete with DELETE access requested. All other errors will be processed as normal. Jeremy. (This used to be commit 360800592c55c9dd8fd787944b3d482f2b9eb951) --- source3/smbd/nttrans.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ea155a8edb..53fee175af 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -782,7 +782,9 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if (desired_access & DELETE_ACCESS) { status = can_delete(conn, fname, file_attributes, bad_path, True); - if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_IS_A_DIRECTORY)) { + /* We're only going to fail here if it's access denied, as that's the + only error we care about for "can we delete this ?" questions. */ + if (!NT_STATUS_IS_OK(status) && NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -1330,7 +1332,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (desired_access & DELETE_ACCESS) { status = can_delete(conn, fname, file_attributes, bad_path, True); - if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_IS_A_DIRECTORY)) { + /* We're only going to fail here if it's access denied, as that's the + only error we care about for "can we delete this ?" questions. */ + if (!NT_STATUS_IS_OK(status) && NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(status); -- cgit From fcbb7b0e25ae22bd8fb04918cf1c5af44a06ca19 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Feb 2005 20:54:06 +0000 Subject: r5508: Typo - ZERO_STRUCT -> ZERO_STRUCTP. Jeremy. (This used to be commit 76e1d90aef45ccc089492d962e0f284e2e4d8e7a) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index fb1a700074..7dde18f430 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -902,7 +902,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); BOOL hide_special = lp_hide_special_files(SNUM(conn)); - ZERO_STRUCT(pst); + ZERO_STRUCTP(pst); if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) { return True; /* . and .. are always visible. */ -- cgit From 14fc089bf52233278afc3ab886b07389960610d9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Feb 2005 20:55:48 +0000 Subject: r5510: Optimisation to only do can_delete check if client asks for FILE_SHARE_DELETE. Not completely correct but will catch the XP SP2 problem. Jeremy. (This used to be commit 1e2d0fcdbb72735f8b53d9faaec07d711ae236d0) --- source3/smbd/nttrans.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 53fee175af..f07fd8c25b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -780,7 +780,16 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib } } +#if 0 + /* This is the correct thing to do (check every time) but can_delete is + expensive (it may have to read the parent directory permissions). So + for now we're not doing it unless we have a strong hint the client + is really going to delete this file. */ if (desired_access & DELETE_ACCESS) { +#else + /* Setting FILE_SHARE_DELETE is the hint. */ + if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { +#endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the only error we care about for "can we delete this ?" questions. */ -- cgit From 34a5c5a580102afe1503da911d6e3b61191bb325 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Feb 2005 02:20:54 +0000 Subject: r5513: Fix for bug #2201 - use same logic with "delete readonly" when setting the delete on close flag as we do in SMBunlink calls. Jeremy. (This used to be commit 7a94eaf1811c79ae52ee78b1cd9cfc691e1d65a0) --- source3/smbd/trans2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e8090792b0..b241aa38f4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2958,10 +2958,12 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, u * Only allow delete on close for writable files. */ - if (dosmode & aRONLY) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n", - fsp->fsp_name )); - return NT_STATUS_CANNOT_DELETE; + if (!lp_delete_readonly(SNUM(fsp->conn))) { + if (dosmode & aRONLY) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n", + fsp->fsp_name )); + return NT_STATUS_CANNOT_DELETE; + } } /* -- cgit From e2cc3f48162d7dec35fb3f256c031979cfa531f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Feb 2005 23:39:51 +0000 Subject: r5524: Don't do share mode checks on can_delete if open, the rest of the open code will do this correctly. More for bug #2201. Jeremy. (This used to be commit faecf639efdecf949e91184d041489aa54e8664f) --- source3/smbd/nttrans.c | 3 ++- source3/smbd/reply.c | 43 ++++++++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f07fd8c25b..2bb2198574 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -793,7 +793,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the only error we care about for "can we delete this ?" questions. */ - if (!NT_STATUS_IS_OK(status) && NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED)) { + if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || + NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(status); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 68705a8aea..89183aed34 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1520,29 +1520,34 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_ if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return NT_STATUS_NO_SUCH_FILE; - if (check_is_at_open && !can_delete_file_in_directory(conn, fname)) { - return NT_STATUS_ACCESS_DENIED; - } - - /* We need a better way to return NT status codes from open... */ - unix_ERR_class = 0; - unix_ERR_code = 0; - - fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); + if (check_is_at_open) { + if (!can_delete_file_in_directory(conn, fname)) { + return NT_STATUS_ACCESS_DENIED; + } + } else { + /* On open checks the open itself will check the share mode, so + don't do it here as we'll get it wrong. */ - if (!fsp) { - NTSTATUS ret = NT_STATUS_ACCESS_DENIED; - if (!NT_STATUS_IS_OK(unix_ERR_ntstatus)) - ret = unix_ERR_ntstatus; - else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - ret = NT_STATUS_SHARING_VIOLATION; + /* We need a better way to return NT status codes from open... */ unix_ERR_class = 0; unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; - return ret; + + fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); + + if (!fsp) { + NTSTATUS ret = NT_STATUS_ACCESS_DENIED; + if (!NT_STATUS_IS_OK(unix_ERR_ntstatus)) + ret = unix_ERR_ntstatus; + else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) + ret = NT_STATUS_SHARING_VIOLATION; + unix_ERR_class = 0; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; + return ret; + } + close_file(fsp,False); } - close_file(fsp,False); return NT_STATUS_OK; } -- cgit From cb203b2d1ec1eec67c3b9347c59230504c68d0b7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Feb 2005 01:03:35 +0000 Subject: r5530: Keep the TRANS call up to date with the NTCreateX call. Jeremy. (This used to be commit 98a07e1520d6fb1f6f5320bc70ac33d4c5052ea6) --- source3/smbd/nttrans.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2bb2198574..d0d5ddf871 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1340,11 +1340,21 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } +#if 0 + /* This is the correct thing to do (check every time) but can_delete is + expensive (it may have to read the parent directory permissions). So + for now we're not doing it unless we have a strong hint the client + is really going to delete this file. */ if (desired_access & DELETE_ACCESS) { +#else + /* Setting FILE_SHARE_DELETE is the hint. */ + if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { +#endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the only error we care about for "can we delete this ?" questions. */ - if (!NT_STATUS_IS_OK(status) && NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED)) { + if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || + NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(status); -- cgit From f95e9fc45b1d34c55b04318b79928adabd8f09e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Feb 2005 02:22:44 +0000 Subject: r5548: Stop lying about allocation sizes to Windows clients. It was a nice idea, and aparently improved performance in some circumstances, but it breaks the VC++ compiler :-(. Not cool. Fix bug #2146. Jeremy. (This used to be commit b9f147634df0126320ffe3b9a23068e76f6c1681) --- source3/smbd/nttrans.c | 8 ++++---- source3/smbd/trans2.c | 20 -------------------- 2 files changed, 4 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d0d5ddf871..675da4c747 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -929,7 +929,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = smb_roundup(allocation_size); + fsp->initial_allocation_size = allocation_size; if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -942,7 +942,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = smb_roundup((SMB_BIG_UINT)file_len); + fsp->initial_allocation_size = (SMB_BIG_UINT)file_len; } /* @@ -1472,7 +1472,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif if (allocation_size && (allocation_size > file_len)) { - fsp->initial_allocation_size = smb_roundup(allocation_size); + fsp->initial_allocation_size = allocation_size; if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -1484,7 +1484,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = smb_roundup((SMB_BIG_UINT)file_len); + fsp->initial_allocation_size = (SMB_BIG_UINT)file_len; } /* Realloc the size of parameters and data we will return */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b241aa38f4..d22705214e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -32,21 +32,6 @@ extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) #define DIR_ENTRY_SAFETY_MARGIN 4096 -/******************************************************************** - Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary. - Only do this for Windows clients. -********************************************************************/ - -SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val) -{ - /* Only roundup for Windows clients. */ - enum remote_arch_types ra_type = get_remote_arch(); - if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { - val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE); - } - return val; -} - /******************************************************************** Given a stat buffer return the allocated size on disk, taking into account sparse files. @@ -65,8 +50,6 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) if (!ret && fsp && fsp->initial_allocation_size) ret = fsp->initial_allocation_size; - ret = smb_roundup(ret); - return ret; } @@ -3350,9 +3333,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)allocation_size )); - if (allocation_size) - allocation_size = smb_roundup(allocation_size); - if(allocation_size != get_file_size(sbuf)) { SMB_STRUCT_STAT new_sbuf; -- cgit From 09f5aa4269a6133e822ce4bbbde426ce5b37cd34 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Mar 2005 21:26:01 +0000 Subject: r5607: Fix for bug #2399 - ensure we use SMB_VFS_STAT instead of stat when checking for existance of a pathname. Jeremy. (This used to be commit 08aac40e3ac0911673ea7e6ef35ba7fe9822d2fd) --- source3/smbd/service.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f199fe3ade..bc74a28faf 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -278,6 +278,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *user = 0; fstrcpy(dev, pdev); + ZERO_STRUCT(st); if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { return NULL; @@ -622,7 +623,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #else /* the alternative is just to check the directory exists */ - if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { + if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); -- cgit From a5e671e867bcf6bd61d68bcf8a1732cf02647843 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 1 Mar 2005 21:48:34 +0000 Subject: r5608: BUG 2399 - removing dead code (not finished with bug yet). (This used to be commit 48353c199cfbfd56760b34ccf99b089bb627e2ed) --- source3/smbd/service.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index bc74a28faf..684d49c56a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -606,22 +606,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #endif -#if CHECK_PATH_ON_TCONX /* win2000 does not check the permissions on the directory during the tree connect, instead relying on permission check during individual operations. To match this behaviour I have disabled this chdir check (tridge) */ - if (vfs_ChDir(conn,conn->connectpath) != 0) { - DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", - get_remote_machine_name(), conn->client_address, - conn->connectpath,strerror(errno))); - change_to_root_user(); - yield_connection(conn, lp_servicename(SNUM(conn))); - conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; - return NULL; - } -#else /* the alternative is just to check the directory exists */ if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); @@ -631,7 +619,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } -#endif string_set(&conn->origpath,conn->connectpath); -- cgit From e9d360aae9ed73da0382204e47a3545cf0d8572c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Mar 2005 03:41:44 +0000 Subject: r5616: Forgot about the sticky bit on directories (commonly set on /tmp). If this is set then only the owner or root can delete a file. We now use the same algorithm to check file delete. Jeremy. (This used to be commit eb18104d10428a5daef2316088edc3dbaff58708) --- source3/smbd/posix_acls.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d02edc5ea0..c5f96db85c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3903,10 +3903,26 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) if (current_user.uid == sbuf.st_uid) { return (sbuf.st_mode & S_IWUSR) ? True : False; } + +#ifdef S_ISVTX + /* sticky bit means delete only by owner or root. */ + if (sbuf.st_mode & S_ISVTX) { + SMB_STRUCT_STAT sbuf_file; + if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { + return False; + } + if (current_user.uid == sbuf_file.st_uid) { + return True; + } + return False; + } +#endif + /* Check group ownership. */ ret = check_posix_acl_group_write(conn, dname, &sbuf); if (ret == 0 || ret == 1) { return ret ? True : False; } + return (sbuf.st_mode & S_IWOTH) ? True : False; } -- cgit From 02bce09010f66422affc478a1d2fd7bc3d1d4b4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Mar 2005 18:19:32 +0000 Subject: r5623: Horrible band-aid patch to fix Blue-Arc torture tester. I know this isn't right but will work until I can refactor the deny mode code with the Samba4 algorithm. Jeremy. (This used to be commit f38f464c722a441402e2d6e2622bcce9227c33b5) --- source3/smbd/open.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 70632a20eb..fc4f97ad16 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -491,7 +491,13 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + return False; + } + if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -502,7 +508,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { - DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with\ + DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with \ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); return True; } -- cgit From a4deaac09f93530e8b8e6b7310c9d8c68eff259c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Mar 2005 21:43:54 +0000 Subject: r5630: This may be a mistake ... needs more cthon investigation. Jeremy. (This used to be commit 0322c5884666bf62a37de069a1cd0ae888ac4285) --- source3/smbd/open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fc4f97ad16..a552dc5b61 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -494,12 +494,15 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign return False; } +#if 0 + /* Bluarc test may need this ... needs further investigation. */ if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } +#endif /* * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE -- cgit From 5713c65a82564b5fdb9ecbbd650ade7f302492c2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Mar 2005 02:04:36 +0000 Subject: r5632: Fix infinite looping bug found by nasty BlueArc test :-). When finding a singleton directory remember that we're at the end and don't continuously return the same name. Jeremy. (This used to be commit 3da50060279609f534aeffe6338b0a2b07d0e8f1) --- source3/smbd/dir.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7dde18f430..d9fd382d52 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -525,10 +525,17 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT pstring pathreal; ZERO_STRUCTP(pst); + if (dptr->has_wild) { return dptr_normal_ReadDirName(dptr, poffset, pst); } + /* If poffset is -1 then we know we returned this name before and we have + no wildcards. We're at the end of the directory. */ + if (*poffset == -1) { + return NULL; + } + /* We know the stored wcard contains no wildcard characters. See if we can match with a stat call. If we can't, then set has_wild to true to prevent us from doing this on every call. */ @@ -540,6 +547,9 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT } if (VALID_STAT(*pst)) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return dptr->wcard; } @@ -548,11 +558,17 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT pstrcat(pathreal,dptr->wcard); if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return dptr->wcard; } else { /* If we get any other error than ENOENT or ENOTDIR then the file exists we just can't stat it. */ if (errno != ENOENT && errno != ENOTDIR) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return dptr->wcard; } } @@ -563,6 +579,9 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT with a stat we will fail. */ if (dptr->conn->case_sensitive) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return NULL; } else { return dptr_normal_ReadDirName(dptr, poffset, pst); @@ -1033,6 +1052,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) *poffset = e->offset= dirp->offset; return e->name; } + dirp->offset = -1; return NULL; } -- cgit From 02fdabc2a7f0199bc5f42afb2c744f3c740122e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Mar 2005 03:43:57 +0000 Subject: r5636: Re-add the allocation size - parameterized by share as "allocation roundup size", by default set as 1Mb. From advice by BlueArc about Windows client behaviour. VC++ people can set this to zero to turn it off. Jeremy. (This used to be commit 833ca101772bfab65dbd79eb64f63464177f144e) --- source3/smbd/nttrans.c | 8 ++++---- source3/smbd/trans2.c | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 675da4c747..aaf1d1679b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -929,7 +929,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = allocation_size; + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -942,7 +942,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = (SMB_BIG_UINT)file_len; + fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); } /* @@ -1472,7 +1472,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif if (allocation_size && (allocation_size > file_len)) { - fsp->initial_allocation_size = allocation_size; + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -1484,7 +1484,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = (SMB_BIG_UINT)file_len; + fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); } /* Realloc the size of parameters and data we will return */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d22705214e..16cea326f9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -32,6 +32,23 @@ extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) #define DIR_ENTRY_SAFETY_MARGIN 4096 +/******************************************************************** + Roundup a value to the nearest allocation roundup size boundary. + Only do this for Windows clients. +********************************************************************/ + +SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val) +{ + SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn)); + + /* Only roundup for Windows clients. */ + enum remote_arch_types ra_type = get_remote_arch(); + if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { + val = SMB_ROUNDUP(val,rval); + } + return val; +} + /******************************************************************** Given a stat buffer return the allocated size on disk, taking into account sparse files. @@ -50,7 +67,7 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) if (!ret && fsp && fsp->initial_allocation_size) ret = fsp->initial_allocation_size; - return ret; + return smb_roundup(fsp->conn, ret); } /**************************************************************************** @@ -3333,6 +3350,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)allocation_size )); + if (allocation_size) { + allocation_size = smb_roundup(conn, allocation_size); + } + if(allocation_size != get_file_size(sbuf)) { SMB_STRUCT_STAT new_sbuf; -- cgit From c56d5cd4c4c0ddc2b9cb018b1cb1fceb1f2fc030 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Mar 2005 04:03:36 +0000 Subject: r5637: Actually test and fix the crash bugs (sorry:-). Jeremy. (This used to be commit 4348ca48549ded8c056877befa216f0e768cb2c1) --- source3/smbd/nttrans.c | 4 ++-- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index aaf1d1679b..eb2232942b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1012,7 +1012,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); + SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; @@ -1529,7 +1529,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); + SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 89183aed34..2dfeebbb9f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5176,7 +5176,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, SIVAL(outbuf,smb_vwv6,0); SIVAL(outbuf,smb_vwv8,0); } else { - uint32 allocation_size = get_allocation_size(fsp, &sbuf); + uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf); SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); SIVAL(outbuf,smb_vwv8,allocation_size); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 16cea326f9..93e497134a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -54,7 +54,7 @@ SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val) account sparse files. ********************************************************************/ -SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) +SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { SMB_BIG_UINT ret; @@ -67,7 +67,7 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) if (!ret && fsp && fsp->initial_allocation_size) ret = fsp->initial_allocation_size; - return smb_roundup(fsp->conn, ret); + return smb_roundup(conn, ret); } /**************************************************************************** @@ -936,7 +936,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(NULL,&sbuf); + allocation_size = get_allocation_size(conn,NULL,&sbuf); mdate = sbuf.st_mtime; adate = sbuf.st_atime; cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); @@ -1232,7 +1232,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */ p+= 8; - SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ p+= 8; put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */ @@ -2439,7 +2439,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * fullpathname = fname; file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(fsp,&sbuf); + allocation_size = get_allocation_size(conn,fsp,&sbuf); if (mode & aDIR) { /* This is necessary, as otherwise the desktop.ini file in * this folder is ignored */ @@ -2785,7 +2785,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */ pdata += 8; - SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */ -- cgit From 6410e6519860641360ea6f75880d62a09a39c7c8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Mar 2005 23:03:38 +0000 Subject: r5700: Fix problems where we're not pointing to the start of entry for a couple of info levels - W2K3 always points to the start, not the name. Jeremy. (This used to be commit 76fb181031e6e3df5b653496692737fd947b7818) --- source3/smbd/trans2.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 93e497134a..d493d37b73 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -811,7 +811,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, BOOL *out_of_space, BOOL *got_exact_match, - int *last_name_off) + int *last_entry_off) { const char *dname; BOOL found = False; @@ -828,6 +828,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint32 len; time_t mdate=0, adate=0, cdate=0; char *nameptr; + char *last_entry_ptr; BOOL was_8_3; int nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); @@ -964,7 +965,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(fname,False,True,SNUM(conn)); p = pdata; - nameptr = p; + last_entry_ptr = p; nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; @@ -1294,8 +1295,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, return False; /* Not finished - just out of space */ } - /* Setup the last_filename pointer, as an offset from base_data */ - *last_name_off = PTR_DIFF(nameptr,base_data); + /* Setup the last entry pointer, as an offset from base_data */ + *last_entry_off = PTR_DIFF(last_entry_ptr,base_data); /* Advance the data pointer to the next slot */ *ppdata = p; @@ -1327,7 +1328,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb pstring directory; pstring mask; char *p; - int last_name_off=0; + int last_entry_off=0; int dptr_num = -1; int numentries = 0; int i; @@ -1454,7 +1455,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_name_off); + &last_entry_off); } if (finished && out_of_space) @@ -1499,7 +1500,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", SSVAL(params,2,numentries); SSVAL(params,4,finished); SSVAL(params,6,0); /* Never an EA error */ - SSVAL(params,8,last_name_off); + SSVAL(params,8,last_entry_off); send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); @@ -1554,7 +1555,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu char *p; uint16 dirtype; int numentries = 0; - int i, last_name_off=0; + int i, last_entry_off=0; BOOL finished = False; BOOL dont_descend = False; BOOL out_of_space = False; @@ -1691,7 +1692,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_name_off); + &last_entry_off); } if (finished && out_of_space) @@ -1723,7 +1724,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", SSVAL(params,0,numentries); SSVAL(params,2,finished); SSVAL(params,4,0); /* Never an EA error */ - SSVAL(params,6,last_name_off); + SSVAL(params,6,last_entry_off); send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); -- cgit From 212de366c9e2f4e73650eb53729290dc4c6fe229 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 9 Mar 2005 15:13:23 +0000 Subject: r5707: BUG 2425: remove ubran legend wrt to win98 and the DFS_PATHNAMES capability bit (This used to be commit 6511bfe84a4036e0d203858aa2f604e346c9412b) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d493d37b73..cb9b7db472 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1378,7 +1378,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); + RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); if (bad_path) { -- cgit From eb546db88d9d4ad8da3709b2edc4d455a88e6119 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Mar 2005 01:30:14 +0000 Subject: r5720: Attempt to fix bug #2382 (Excel shared workbook stops working). Also incorporates part of the fix created by ke_miyata@itg.hitachi.co.jp for bug #2045 (MS-Office behavior of timestamp). Jeremy. (This used to be commit 4f3b12ac73487f4ccb37c17506af1abf5acc80cd) --- source3/smbd/files.c | 59 +++++++++++++++++++++++++++++++++++-- source3/smbd/nttrans.c | 2 +- source3/smbd/reply.c | 27 ++++++++--------- source3/smbd/trans2.c | 80 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 119 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index ecf39c2b54..547206815e 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -37,6 +37,13 @@ static files_struct *oplock_save_chain_fsp = NULL; static int files_used; +/* A singleton cache to speed up searching by dev/inode. */ +static struct fsp_singleton_cache { + files_struct *fsp; + SMB_DEV_T dev; + SMB_INO_T inode; +} fsp_fi_cache; + /**************************************************************************** Return a unique number identifying this fsp over the life of this pid. ****************************************************************************/ @@ -122,6 +129,11 @@ files_struct *file_new(connection_struct *conn) i, fsp->fnum, files_used)); chain_fsp = fsp; + + /* A new fsp invalidates a negative fsp_fi_cache. */ + if (fsp_fi_cache.fsp == NULL) { + ZERO_STRUCT(fsp_fi_cache); + } return fsp; } @@ -299,19 +311,34 @@ files_struct *file_find_fsp(files_struct *orig_fsp) /**************************************************************************** Find the first fsp given a device and inode. + We use a singleton cache here to speed up searching from getfilepathinfo + calls. ****************************************************************************/ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) { files_struct *fsp; + if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { + /* Positive or negative cache hit. */ + return fsp_fi_cache.fsp; + } + + fsp_fi_cache.dev = dev; + fsp_fi_cache.inode = inode; + for (fsp=Files;fsp;fsp=fsp->next) { if ( fsp->fd != -1 && fsp->dev == dev && - fsp->inode == inode ) + fsp->inode == inode ) { + /* Setup positive cache. */ + fsp_fi_cache.fsp = fsp; return fsp; + } } + /* Setup negative cache. */ + fsp_fi_cache.fsp = NULL; return NULL; } @@ -342,12 +369,35 @@ files_struct *file_find_print(void) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next) { - if (fsp->print_file) return fsp; + if (fsp->print_file) { + return fsp; + } } return NULL; } +/**************************************************************************** + Set a pending modtime across all files with a given dev/ino pair. +****************************************************************************/ + +void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) +{ + files_struct *fsp; + + if (null_mtime(pmod)) { + return; + } + + for (fsp = Files;fsp;fsp=fsp->next) { + if ( fsp->fd != -1 && + fsp->dev == tfsp->dev && + fsp->inode == tfsp->inode ) { + fsp->pending_modtime = pmod; + } + } +} + /**************************************************************************** Sync open files on a connection. ****************************************************************************/ @@ -392,6 +442,11 @@ void file_free(files_struct *fsp) chain_fsp = NULL; } + /* Closing a file can invalidate the positive cache. */ + if (fsp == fsp_fi_cache.fsp) { + ZERO_STRUCT(fsp_fi_cache); + } + SAFE_FREE(fsp); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index eb2232942b..fbb7364090 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1698,7 +1698,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new close_file(fsp1,False); /* Ensure the modtime is set correctly on the destination file. */ - fsp2->pending_modtime = sbuf1.st_mtime; + fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); close_ret = close_file(fsp2,False); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2dfeebbb9f..f149b79f79 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2875,6 +2875,13 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, fsp->fd, fsp->fnum, conn->num_files_open)); + /* + * Take care of any time sent in the close. + */ + + mtime = make_unix_date3(inbuf+smb_vwv1); + fsp_set_pending_modtime(fsp, mtime); + /* * close_file() returns the unix errno if an error * was detected on close - normally this is due to @@ -2886,16 +2893,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, END_PROFILE(SMBclose); return (UNIXERROR(ERRHRD,ERRgeneral)); } - - /* - * Now take care of any time sent in the close. - */ - - mtime = make_unix_date3(inbuf+smb_vwv1); - - /* try and set the date */ - set_filetime(conn, file_name, mtime); - } /* We have a cached error */ @@ -4233,7 +4230,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, close_file(fsp1,False); /* Ensure the modtime is set correctly on the destination file. */ - fsp2->pending_modtime = src_sbuf.st_mtime; + fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime); /* * As we are opening fsp1 read-only we only expect @@ -4917,7 +4914,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, * Sometimes times are sent as zero - ignore them. */ - if ((unix_times.actime == 0) && (unix_times.modtime == 0)) { + if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { /* Ignore request */ if( DEBUGLVL( 3 ) ) { dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); @@ -4925,12 +4922,13 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, } END_PROFILE(SMBsetattrE); return(outsize); - } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) { - /* set modify time = to access time if modify time was 0 */ + } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { + /* set modify time = to access time if modify time was unset */ unix_times.modtime = unix_times.actime; } /* Set the date on this file */ + /* Should we set pending modtime here ? JRA */ if(file_utime(conn, fsp->fsp_name, &unix_times)) { END_PROFILE(SMBsetattrE); return ERROR_DOS(ERRDOS,ERRnoaccess); @@ -5170,6 +5168,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); + /* Should we check pending modtime here ? JRA */ put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cb9b7db472..3f3d9c2f46 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2469,9 +2469,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - if (fsp && fsp->pending_modtime) { - /* the pending modtime overrides the current modtime */ - sbuf.st_mtime = fsp->pending_modtime; + if (fsp) { + if (fsp->pending_modtime) { + /* the pending modtime overrides the current modtime */ + sbuf.st_mtime = fsp->pending_modtime; + } + } else { + /* Do we have this path open ? */ + files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); + if (fsp1 && fsp1->pending_modtime) { + /* the pending modtime overrides the current modtime */ + sbuf.st_mtime = fsp1->pending_modtime; + } } if (lp_dos_filetime_resolution(SNUM(conn))) { @@ -3323,9 +3332,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char tvs.modtime = write_time; } /* Prefer a defined time to an undefined one. */ - if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) - tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1 - ? changed_time : write_time); + if (null_mtime(tvs.modtime)) { + tvs.modtime = null_mtime(write_time) ? changed_time : write_time; + } /* attributes */ dosmode = IVAL(pdata,32); @@ -3805,11 +3814,13 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } /* get some defaults (no modifications) if any info is zero or -1. */ - if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1) + if (null_mtime(tvs.actime)) { tvs.actime = sbuf.st_atime; + } - if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) + if (null_mtime(tvs.modtime)) { tvs.modtime = sbuf.st_mtime; + } DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); @@ -3841,30 +3852,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * Try and set the times, size and mode of this file - * if they are different from the current values */ - if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { - if(fsp != NULL) { - /* - * This was a setfileinfo on an open file. - * NT does this a lot. We also need to - * set the time here, as it can be read by - * FindFirst/FindNext and with the patch for bug #2045 - * in smbd/fileio.c it ensures that this timestamp is - * kept sticky even after a write. We save the request - * away and will set it on file close and after a write. JRA. - */ - - if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { - DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) )); - fsp->pending_modtime = tvs.modtime; - } - - DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); - - if(file_utime(conn, fname, &tvs)!=0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } - } /* check the mode isn't different, before changing it */ if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) { @@ -3877,6 +3864,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } } + /* Now the size. */ if (size != get_file_size(sbuf)) { int ret; @@ -3917,6 +3905,34 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return (UNIXERROR(ERRHRD,ERRdiskfull)); } + /* + * Finally the times. + */ + if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { + if(fsp != NULL) { + /* + * This was a setfileinfo on an open file. + * NT does this a lot. We also need to + * set the time here, as it can be read by + * FindFirst/FindNext and with the patch for bug #2045 + * in smbd/fileio.c it ensures that this timestamp is + * kept sticky even after a write. We save the request + * away and will set it on file close and after a write. JRA. + */ + + if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { + DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) )); + fsp_set_pending_modtime(fsp, tvs.modtime); + } + + } + DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); + + if(file_utime(conn, fname, &tvs)!=0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } + SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); -- cgit From 95e68fa7f8c109204b3ddaeb530e192c71b40e58 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Mar 2005 21:43:58 +0000 Subject: r5731: Get delayed write semantics closer to W2K3. We need to store 2 times. This may fix bug #2382. Jeremy. (This used to be commit a27c351e6beafc6609790a9bb9a3d0a1331e8f35) --- source3/smbd/close.c | 4 +++- source3/smbd/fileio.c | 6 ++++++ source3/smbd/files.c | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4445f2516b..b3244432ff 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -260,8 +260,10 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); * Ensure pending modtime is set after close. */ - if(fsp->pending_modtime) { + if(fsp->pending_modtime && fsp->pending_modtime_owner) { set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); + } else if (fsp->last_write_time) { + set_filetime(conn, fsp->fsp_name, fsp->last_write_time); } DEBUG(2,("%s closed file %s (numopen=%d) %s\n", diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index a21bd69a36..3048c27fa2 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -142,6 +142,12 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ if (fsp->pending_modtime) { set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime); + + /* If we didn't get the "set modtime" call ourselves, we must + store the last write time to restore on close. JRA. */ + if (!fsp->pending_modtime_owner) { + fsp->last_write_time = time(NULL); + } } /* Yes - this is correct - writes don't update this. JRA. */ diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 547206815e..143c119693 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -379,6 +379,7 @@ files_struct *file_find_print(void) /**************************************************************************** Set a pending modtime across all files with a given dev/ino pair. + Record the owner of that modtime. ****************************************************************************/ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) @@ -394,8 +395,11 @@ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) fsp->dev == tfsp->dev && fsp->inode == tfsp->inode ) { fsp->pending_modtime = pmod; + fsp->pending_modtime_owner = False; } } + + tfsp->pending_modtime_owner = True; } /**************************************************************************** -- cgit From f7831445162ebce0ac506515055570822bf74b9f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Mar 2005 18:50:09 +0000 Subject: r5757: Fix erroneous debug message - noticed by William Jojo . Jeremy. (This used to be commit fd1999f1d73b871501ff859422c3989b496231a8) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 0102739fe3..e170a71520 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -940,7 +940,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) } #endif - DEBUG(3,("reduce_name: %s reduced to %s\n", fname, p)); + DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name)); if (free_resolved_name) SAFE_FREE(resolved_name); errno = saved_errno; -- cgit From cc5ba986bf4c7b704ae5c3787f2f3881145e719c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Mar 2005 01:19:58 +0000 Subject: r5792: Added new parameter "inherit owner". If set on a share, the created file/directory will be owned by the same uid as the containing directory. Doing this for directories in a race-free mannor has only been tested on Linux (it depends on being able to open a directory and then do a fchown on that file descriptor). If this functionality is not available then the code silently downgrades to not changing the ownership of a new directory. This new parameter (docs to follow) finally makes it possible to create "drop boxes" on Samba, which requires all files within a directory to be commonly owned. A HOWTO on how to use this will follow. Jeremy. (This used to be commit 2e1f727184b9d025d2e3413bdd3d01d5ca803a41) --- source3/smbd/filename.c | 2 +- source3/smbd/open.c | 152 +++++++++++++++++++++++++++++++++++++++--------- source3/smbd/reply.c | 63 ++++++++++++++++---- 3 files changed, 178 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8c484dd232..9ca2c0efae 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -397,7 +397,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen a valid one for the user to access. ****************************************************************************/ -BOOL check_name(pstring name,connection_struct *conn) +BOOL check_name(const pstring name,connection_struct *conn) { BOOL ret = True; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a552dc5b61..3124526c7e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -82,6 +82,103 @@ static void check_for_pipe(const char *fname) } } +/**************************************************************************** + Change the ownership of a file to that of the parent directory. + Do this by fd if possible. +****************************************************************************/ + +void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf) +{ + const char *parent_path = parent_dirname(fname); + SMB_STRUCT_STAT parent_st; + int ret; + + ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + if (ret == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat parent directory %s. Error was %s\n", + parent_path, strerror(errno) )); + return; + } + + if (fsp && fsp->fd != -1) { + become_root(); + ret = SMB_VFS_FCHOWN(fsp, fsp->fd, parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(0,("change_owner_to_parent: failed to fchown file %s to parent directory uid %u. \ +Error was %s\n", + fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + } + + DEBUG(10,("change_owner_to_parent: changed new file %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); + + } else { + /* We've already done an lstat into psbuf, and we know it's a directory. If + we can do an open/fstat and the dev/ino are the same then we can safely + fchown without races. This works under Linux - but should just fail gracefully + if any step on the way fails. JRA */ + + BOOL need_close_fsp = False; + SMB_STRUCT_STAT sbuf; + int fd = -1; + + if (!fsp) { + int action; + fsp = open_directory(conn, fname, psbuf, FILE_GENERIC_READ, + SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + FILE_EXISTS_OPEN, &action); + if (!fsp) { + DEBUG(10,("change_owner_to_parent: open_directory on %s failed. Error was %s\n", + fname, strerror(errno) )); + return; + } + need_close_fsp = True; + } + fd = SMB_VFS_OPEN(conn,fname,O_RDONLY,0); + if (fd == -1) { + DEBUG(10,("change_owner_to_parent: failed to VFS_OPEN directory %s. Error was %s\n", + fname, strerror(errno) )); + goto out; + } + ret = SMB_VFS_FSTAT(fsp,fd,&sbuf); + if (ret == -1) { + DEBUG(10,("change_owner_to_parent: failed to VFS_STAT directory %s. Error was %s\n", + fname, strerror(errno) )); + goto out; + } + + /* Ensure we're pointing at the same place. */ + if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || !S_ISDIR(sbuf.st_mode)) { + DEBUG(0,("change_owner_to_parent: device/inode/mode on director %s changed. Refusing to fchown !\n", + fname )); + goto out; + } + + become_root(); + ret = SMB_VFS_FCHOWN(fsp, fd, parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(10,("change_owner_to_parent: failed to fchown directory %s to parent directory uid %u. \ +Error was %s\n", + fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + goto out; + } + + DEBUG(10,("change_owner_to_parent: changed new directory %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); + + out: + + if (fd != -1) { + SMB_VFS_CLOSE(fsp,fd); + } + if (need_close_fsp) { + close_file(fsp, False); + } + } +} + /**************************************************************************** Open a file. ****************************************************************************/ @@ -1391,8 +1488,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", action = FILE_WAS_OPENED; if (file_existed && (flags2 & O_TRUNC)) action = FILE_WAS_OVERWRITTEN; - if (!file_existed) + if (!file_existed) { action = FILE_WAS_CREATED; + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + } + } if (paction) { *paction = action; @@ -1547,7 +1649,7 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, +files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, int share_mode, int smb_ofun, int *action) { extern struct current_user current_user; @@ -1585,39 +1687,29 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST * Try and create the directory. */ - if(!CAN_WRITE(conn)) { - DEBUG(2,("open_directory: failing create on read-only share\n")); - file_free(fsp); - errno = EACCES; - return NULL; - } + /* We know bad_path is false as it's caught earlier. */ - if (ms_has_wild(fname)) { - file_free(fsp); - DEBUG(5,("open_directory: failing create on filename %s with wildcards\n", fname)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; - return NULL; - } + NTSTATUS status = mkdir_internal(conn, fname, False); - if( strchr_m(fname, ':')) { + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); file_free(fsp); - DEBUG(5,("open_directory: failing create on filename %s with colon in name\n", fname)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_NOT_A_DIRECTORY; + /* Ensure we return the correct NT status to the client. */ + unix_ERR_ntstatus = status; return NULL; } - if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname, True)) < 0) { - DEBUG(2,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + + if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } - if(SMB_VFS_STAT(conn,fname, psbuf) != 0) { + if(!S_ISDIR(psbuf->st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); file_free(fsp); return NULL; } @@ -1674,13 +1766,19 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST string_set(&fsp->fsp_name,fname); if (delete_on_close) { - NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close, 0); + NTSTATUS status = set_delete_on_close_internal(fsp, delete_on_close, 0); - if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + if (!NT_STATUS_IS_OK(status)) { file_free(fsp); return NULL; } } + + /* Change the owner if required. */ + if ((*action == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + } + conn->num_files_open++; return fsp; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f149b79f79..376b42e5fd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3303,29 +3303,47 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ code. ****************************************************************************/ -NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) +NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path) { - BOOL bad_path = False; - SMB_STRUCT_STAT sbuf; int ret= -1; - unix_convert(directory,conn,0,&bad_path,&sbuf); - - if( strchr_m(directory, ':')) { - return NT_STATUS_NOT_A_DIRECTORY; + if(!CAN_WRITE(conn)) { + DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn)))); + errno = EACCES; + return map_nt_error_from_unix(errno); } + /* The following 2 clauses set explicit DOS error codes. JRA. */ if (ms_has_wild(directory)) { + DEBUG(5,("mkdir_internal: failing create on filename %s with wildcards\n", directory)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; return NT_STATUS_OBJECT_NAME_INVALID; } + if( strchr_m(directory, ':')) { + DEBUG(5,("mkdir_internal: failing create on filename %s with colon in name\n", directory)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + return NT_STATUS_NOT_A_DIRECTORY; + } + if (bad_path) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - if (check_name(directory, conn)) - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); - + if (!check_name(directory, conn)) { + if(errno == ENOENT) { + if (bad_path) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + } + return map_nt_error_from_unix(errno); + } + + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); if (ret == -1) { if(errno == ENOENT) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -3345,6 +3363,9 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring directory; int outsize; NTSTATUS status; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + START_PROFILE(SMBmkdir); srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); @@ -3355,12 +3376,32 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); - status = mkdir_internal(conn, directory); + unix_convert(directory,conn,0,&bad_path,&sbuf); + + status = mkdir_internal(conn, directory,bad_path); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); return ERROR_NT(status); } + if (lp_inherit_owner(SNUM(conn))) { + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + + if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) { + END_PROFILE(SMBmkdir); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if(!S_ISDIR(sbuf.st_mode)) { + DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory )); + END_PROFILE(SMBmkdir); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + change_owner_to_parent(conn, NULL, directory, &sbuf); + } + outsize = set_message(outbuf,0,0,True); DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); -- cgit From cc944794c19b672fba1c77d43f198654c009dd55 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Mar 2005 23:17:03 +0000 Subject: r5812: We missed some RESOLVE_DFSPATH calls on pathnames for older calls. Jeremy. (This used to be commit 0b0b8686f3c4261e9b1070f4b2968e6f4ed4bbd7) --- source3/smbd/reply.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 376b42e5fd..326dafd678 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -701,6 +701,8 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + unix_convert(fname,conn,0,&bad_path,&sbuf); if (bad_path) { END_PROFILE(SMBsetatr); @@ -833,6 +835,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBsearch); return ERROR_NT(nt_status); } + + RESOLVE_DFSPATH(path, conn, inbuf, outbuf); + p++; status_len = SVAL(p, 0); p += 2; @@ -4490,6 +4495,8 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } + RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf); + if (strlen(newdir) == 0) { ok = True; } else { -- cgit From 4f92cefcad567c2098e02d902783ac9e722fd02e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Mar 2005 23:40:47 +0000 Subject: r5813: Fix bug found by Jim McDonough Win9x can send a resume name of "..". This will cause the parser to complain (it thinks we're asking for the directory above the shared path). Catch this as the resume name is only compared, never used in a file access and replace it with "..". Jeremy. (This used to be commit c03524363f86ab88f1408f2fba2a1d76ce830301) --- source3/smbd/trans2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3f3d9c2f46..c21fe1113e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1569,7 +1569,15 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True); if (!NT_STATUS_IS_OK(ntstatus)) { - return ERROR_NT(ntstatus); + /* Win9x can send a resume name of "..". This will cause the parser to + complain (it thinks we're asking for the directory above the shared + path). Catch this as the resume name is only compared, never used in + a file access. JRA. */ + if (NT_STATUS_V(ntstatus) == NT_STATUS_V(NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) { + pstrcpy(resume_name, ".."); + } else { + return ERROR_NT(ntstatus); + } } DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \ -- cgit From 55f480b009a577d47dd7ea430607a91db858485f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Mar 2005 23:46:22 +0000 Subject: r5816: Catch the "." resume name case also. Jeremy. (This used to be commit 479bb6ea95e45d6f9d8b5dbddd500451e39202a7) --- source3/smbd/trans2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c21fe1113e..54234deb35 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1569,12 +1569,14 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True); if (!NT_STATUS_IS_OK(ntstatus)) { - /* Win9x can send a resume name of "..". This will cause the parser to + /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to complain (it thinks we're asking for the directory above the shared - path). Catch this as the resume name is only compared, never used in + path or an invalid name). Catch this as the resume name is only compared, never used in a file access. JRA. */ - if (NT_STATUS_V(ntstatus) == NT_STATUS_V(NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) { + if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) { pstrcpy(resume_name, ".."); + } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) { + pstrcpy(resume_name, "."); } else { return ERROR_NT(ntstatus); } -- cgit From 7dcbde86ae22379b67d0a571c93aa34b2a1311aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Mar 2005 01:41:21 +0000 Subject: r5822: Actually return an error message if disk_free fails ! Pointed out by Ying Li . Jeremy. (This used to be commit b5d31b2caf5c4739607bf57cb7e4e0569b57012b) --- source3/smbd/dfree.c | 15 ++++++++++++--- source3/smbd/reply.c | 5 ++++- source3/smbd/trans2.c | 13 ++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index c556c8c8ab..81a48b94fc 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -115,10 +115,19 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, } else { DEBUG (0, ("disk_free: sys_popen() failed for command %s. Error was : %s\n", syscmd, strerror(errno) )); - sys_fsusage(path, dfree, dsize); + if (sys_fsusage(path, dfree, dsize) != 0) { + DEBUG (0, ("disk_free: sys_fsusage() failed. Error was : %s\n", + strerror(errno) )); + return (SMB_BIG_UINT)-1; + } + } + } else { + if (sys_fsusage(path, dfree, dsize) != 0) { + DEBUG (0, ("disk_free: sys_fsusage() failed. Error was : %s\n", + strerror(errno) )); + return (SMB_BIG_UINT)-1; } - } else - sys_fsusage(path, dfree, dsize); + } if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) { (*bsize) = bsize_q; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 326dafd678..e8ee9ffe92 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -751,7 +751,10 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz SMB_BIG_UINT dfree,dsize,bsize; START_PROFILE(SMBdskattr); - SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize); + if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + END_PROFILE(SMBdskattr); + return(UNIXERROR(ERRHRD,ERRgeneral)); + } outsize = set_message(outbuf,5,0,True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 54234deb35..e4e1243d68 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1785,7 +1785,10 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 18; - SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); + if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + return(UNIXERROR(ERRHRD,ERRgeneral)); + } + block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1877,7 +1880,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; - SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); + if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + return(UNIXERROR(ERRHRD,ERRgeneral)); + } block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1907,7 +1912,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; - SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); + if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + return(UNIXERROR(ERRHRD,ERRgeneral)); + } block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; -- cgit From 4ba71014d66f488aa58c216651b207a83b7a7d8e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Mar 2005 02:11:44 +0000 Subject: r5825: Fix one more DISK_FREE call - spotted by Ying Li . Jeremy. (This used to be commit 19e017a78a90aca5f2d39a3c28472b9a595acbf3) --- source3/smbd/vfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index e170a71520..34671b8efc 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -552,6 +552,9 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ space_avail = SMB_VFS_DISK_FREE(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); + if (space_avail == (SMB_BIG_UINT)-1) { + return -1; + } DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail )); -- cgit From e2673ae1c5f942a2197ec5eb68712c382370f6b3 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Wed, 16 Mar 2005 16:14:04 +0000 Subject: r5831: Along with jra's recent checkins, fix dir/xcopy of empty dirs on OS/2. Bugs 2335, 2337. (This used to be commit 2312ac9d42adcea8576c3923cd5bc8c1851d5375) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e4e1243d68..ac2a29bd60 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1484,13 +1484,13 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", } /* - * If there are no matching entries we must return ERRDOS/ERRbadfile - + * If there are no matching entries we must return ERRDOS/ERRnofiles - * from observation of NT. */ if(numentries == 0) { dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRbadfile); + return ERROR_DOS(ERRDOS,ERRnofiles); } /* At this point pdata points to numentries directory entries. */ -- cgit From b05ce8f0470695cbba2da6caad09d604fac5da39 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Mar 2005 19:31:15 +0000 Subject: r5833: Revert change for bug #2335. Tested with a Win9x client and the original error code is correct. I have some theories as to why this is different, I'll add some code to the torture tester to confirm. Jeremy. (This used to be commit a7a7af6815e1123f27070a2fe0a92de5b4372913) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ac2a29bd60..e4e1243d68 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1484,13 +1484,13 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", } /* - * If there are no matching entries we must return ERRDOS/ERRnofiles - + * If there are no matching entries we must return ERRDOS/ERRbadfile - * from observation of NT. */ if(numentries == 0) { dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRnofiles); + return ERROR_DOS(ERRDOS,ERRbadfile); } /* At this point pdata points to numentries directory entries. */ -- cgit From c6e94efcec91d6d64b451fa3da8aeab58dc295b8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Mar 2005 23:32:42 +0000 Subject: r5836: Correct fix for OS/2 bug #2335. The error return code in this case is protocol level dependent. Jeremy. (This used to be commit 712ef86ac008524866615e670db7659ea674fefb) --- source3/smbd/trans2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e4e1243d68..7137c4b5f5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1485,12 +1485,18 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", /* * If there are no matching entries we must return ERRDOS/ERRbadfile - - * from observation of NT. + * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if + * the protocol level is less than NT1. Tested with smbclient. JRA. + * This should fix the OS/2 client bug #2335. */ if(numentries == 0) { dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRbadfile); + if (protocol < PROTOCOL_NT1) { + return ERROR_DOS(ERRDOS,ERRnofiles); + } else { + return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile); + } } /* At this point pdata points to numentries directory entries. */ -- cgit From ee804161aae672a1e46d46bcbbc49fd453616bb7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Mar 2005 01:02:30 +0000 Subject: r5843: Removed unused variable - pointed out by jason@ncac.gwu.edu in bugid #2460. Jeremy. (This used to be commit 1f988333ecaedfb21a8deee6eebb9bd4de91bfd6) --- source3/smbd/dir.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index d9fd382d52..db16b8a6e0 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -594,10 +594,8 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) { - BOOL ret; - ZERO_STRUCTP(pst); - while ((ret = SearchDir(dptr->dir_hnd, name, poffset)) == True) { + while (SearchDir(dptr->dir_hnd, name, poffset) == True) { if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { return True; } -- cgit From 2aaf23ed64f93056655e78f1601254058ee7a6e0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Mar 2005 01:19:49 +0000 Subject: r5844: Fix typo. Add cast for bug #2464 reported by jason@ncac.gwu.edu. Jeremy. (This used to be commit a4b4766e4294c3a0172beeae7a7698160f4a2632) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7137c4b5f5..05ff7d6785 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -143,7 +143,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str } else { pea->name = ea_name; } - pea->value.data = val; + pea->value.data = (unsigned char *)val; pea->value.length = (size_t)sizeret; return True; } @@ -1492,7 +1492,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", if(numentries == 0) { dptr_close(&dptr_num); - if (protocol < PROTOCOL_NT1) { + if (Protocol < PROTOCOL_NT1) { return ERROR_DOS(ERRDOS,ERRnofiles); } else { return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile); -- cgit From 56b22250f478ca2cce43a274589e42a28ea88002 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Mar 2005 01:50:09 +0000 Subject: r5848: Fix inherit owner to chown directories in a porable and secure way (from just secure on Linux). Idea from tridge. Jeremy. (This used to be commit c0924a497b51c126a1db55f48cbf461855dd6c6a) --- source3/smbd/open.c | 62 +++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3124526c7e..79c27388dc 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -115,67 +115,55 @@ Error was %s\n", } else { /* We've already done an lstat into psbuf, and we know it's a directory. If - we can do an open/fstat and the dev/ino are the same then we can safely - fchown without races. This works under Linux - but should just fail gracefully - if any step on the way fails. JRA */ + we can cd into the directory and the dev/ino are the same then we can safely + chown without races as we're locking the directory in place by being in it. + This should work on any UNIX (thanks tridge :-). JRA. + */ - BOOL need_close_fsp = False; + pstring saved_dir; SMB_STRUCT_STAT sbuf; - int fd = -1; - - if (!fsp) { - int action; - fsp = open_directory(conn, fname, psbuf, FILE_GENERIC_READ, - SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - FILE_EXISTS_OPEN, &action); - if (!fsp) { - DEBUG(10,("change_owner_to_parent: open_directory on %s failed. Error was %s\n", - fname, strerror(errno) )); - return; - } - need_close_fsp = True; - } - fd = SMB_VFS_OPEN(conn,fname,O_RDONLY,0); - if (fd == -1) { - DEBUG(10,("change_owner_to_parent: failed to VFS_OPEN directory %s. Error was %s\n", - fname, strerror(errno) )); + + if (!vfs_GetWd(conn,saved_dir)) { + DEBUG(0,("change_owner_to_parent: failed to get current working directory\n")); + return; + } + + /* Chdir into the new path. */ + if (vfs_ChDir(conn, fname) == -1) { + DEBUG(0,("change_owner_to_parent: failed to change current working directory to %s. \ +Error was %s\n", fname, strerror(errno) )); goto out; } - ret = SMB_VFS_FSTAT(fsp,fd,&sbuf); - if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to VFS_STAT directory %s. Error was %s\n", - fname, strerror(errno) )); + + if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat directory '.' (%s) \ +Error was %s\n", fname, strerror(errno))); goto out; } /* Ensure we're pointing at the same place. */ - if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || !S_ISDIR(sbuf.st_mode)) { - DEBUG(0,("change_owner_to_parent: device/inode/mode on director %s changed. Refusing to fchown !\n", + if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { + DEBUG(0,("change_owner_to_parent: device/inode/mode on directory %s changed. Refusing to chown !\n", fname )); goto out; } become_root(); - ret = SMB_VFS_FCHOWN(fsp, fd, parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to fchown directory %s to parent directory uid %u. \ + DEBUG(10,("change_owner_to_parent: failed to chown directory %s to parent directory uid %u. \ Error was %s\n", fname, (unsigned int)parent_st.st_uid, strerror(errno) )); goto out; } - DEBUG(10,("change_owner_to_parent: changed new directory %s to parent directory uid %u.\n", + DEBUG(10,("change_owner_to_parent: changed ownership of new directory %s to parent directory uid %u.\n", fname, (unsigned int)parent_st.st_uid )); out: - if (fd != -1) { - SMB_VFS_CLOSE(fsp,fd); - } - if (need_close_fsp) { - close_file(fsp, False); - } + vfs_ChDir(conn,saved_dir); } } -- cgit From 99509cb0b502c34815dfe9ad33c0ba9c4c524713 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 17 Mar 2005 14:32:52 +0000 Subject: r5854: Fix coredump when OS/2 checks for long file name support (with .+,;=[].). Bugzilla 2338. Thanks to Guenter Kukkukk (This used to be commit c13736287104d96fcc87ada0784eb43c6e373171) --- source3/smbd/open.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 79c27388dc..9d9d9d9208 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1146,17 +1146,15 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ oplock_request = 0; } - /* this is for OS/2 EAs - try and say we don't support them */ + /* this is for OS/2 long file names - say we don't support them */ if (strstr(fname,".+,;=[].")) { unix_ERR_class = ERRDOS; /* OS/2 Workplace shell fix may be main code stream in a later release. */ -#if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ unix_ERR_code = ERRcannotopen; -#else /* OS2_WPS_FIX */ - unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; -#endif /* OS2_WPS_FIX */ - - DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n")); + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); + /* need to reset errno or DEVELOPER will cause us to coredump */ + errno = 0; file_free(fsp); return NULL; } -- cgit From 983a1f69aebaa63dac55a58061386c4bc86b919f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Mar 2005 19:26:23 +0000 Subject: r5864: Stop using 'INFO' names on find calls. Getting ready to fixup OS/2 EA support. Jeremy. (This used to be commit a417feaa4108b443850ef6e8f0da32b79d79db59) --- source3/smbd/trans2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 05ff7d6785..fb44e98fce 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -970,8 +970,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) { - case SMB_INFO_STANDARD: - DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n")); + case SMB_FIND_INFO_STANDARD: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -1002,8 +1002,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += len; break; - case SMB_INFO_QUERY_EA_SIZE: - DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n")); + case SMB_FIND_EA_SIZE: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -1356,8 +1356,8 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", } switch (info_level) { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: + case SMB_FIND_INFO_STANDARD: + case SMB_FIND_EA_SIZE: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: @@ -1600,8 +1600,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", } switch (info_level) { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: + case SMB_FIND_INFO_STANDARD: + case SMB_FIND_EA_SIZE: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: -- cgit From d2467955bf2fdbc9a0e4b3d73124ee49aba0877f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Mar 2005 01:55:30 +0000 Subject: r5872: Restructure ea list code to start to fix the EA_LIST calls. This does not work yet but it's a work in progress. Jeremy. (This used to be commit 0e399422f70ef8b3797277f6f61105fa7fe0d83a) --- source3/smbd/trans2.c | 140 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 104 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fb44e98fce..9991ff477e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -228,14 +228,11 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, that was filled. ****************************************************************************/ -static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, - connection_struct *conn, files_struct *fsp, const char *fname) +static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size, + connection_struct *conn, struct ea_list *ea_list) { unsigned int ret_data_size = 4; char *p = pdata; - size_t total_ea_len; - TALLOC_CTX *mem_ctx; - struct ea_list *ea_list; SMB_ASSERT(total_data_size >= 4); @@ -243,21 +240,6 @@ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, if (!lp_ea_support(SNUM(conn))) { return 4; } - mem_ctx = talloc_init("fill_ea_buffer"); - if (!mem_ctx) { - return 4; - } - - ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); - if (!ea_list) { - talloc_destroy(mem_ctx); - return 4; - } - - if (total_ea_len > total_data_size) { - talloc_destroy(mem_ctx); - return 4; - } for (p = pdata + 4; ea_list; ea_list = ea_list->next) { size_t dos_namelen; @@ -286,9 +268,7 @@ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, } ret_data_size = PTR_DIFF(p, pdata); - DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n", - ret_data_size, total_ea_len )); - talloc_destroy(mem_ctx); + DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size )); SIVAL(pdata,0,ret_data_size); return ret_data_size; } @@ -427,6 +407,38 @@ static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *f return NT_STATUS_OK; } +/**************************************************************************** + Read a list of EA's from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 4; + + while (offset + 2 < data_size) { + struct ea_list *tmp; + struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + unsigned int namelen = CVAL(pdata,offset); + + offset++; /* Go past the namelen byte. */ + if (offset + namelen >= data_size) { + break; + } + eal->ea.name = TALLOC_ARRAY(ctx, char, namelen + 1); + if (!eal->ea.name) { + break; + } + memcpy(eal->ea.name, pdata + offset, namelen); + eal->ea.name[namelen] = '\0'; + + offset += (namelen + 1); /* Go past the name + terminating zero. */ + DLIST_ADD_END(ea_list_head, eal, tmp); + } + + return ea_list_head; +} + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -1039,6 +1051,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ break; +#if 0 + case SMB_FIND_EA_LIST: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } +#endif + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); was_8_3 = mangle_is_8_3(fname, True); @@ -2333,7 +2354,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * int mode=0; SMB_OFF_T file_size=0; SMB_BIG_UINT allocation_size=0; - unsigned int data_size; + unsigned int data_size = 0; unsigned int param_size = 2; SMB_STRUCT_STAT sbuf; pstring fname, dos_fname; @@ -2346,6 +2367,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * int len; time_t c_time; files_struct *fsp = NULL; + TALLOC_CTX *ea_ctx = NULL; + struct ea_list *ea_list = NULL; uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ if (!params) @@ -2471,22 +2494,46 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * file_size = 0; } + /* Pull any EA list from the data portion. */ + if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) { + uint32 ea_size = IVAL(pdata,0); + + if (total_data > 0 && ea_size != total_data) { + DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_list(ea_ctx, pdata, ea_size); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + params = SMB_REALLOC(*pparams,2); - if (params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if (params == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; memset((char *)params,'\0',2); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; pdata = SMB_REALLOC(*ppdata, data_size); - if ( pdata == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); - *ppdata = pdata; - - if (total_data > 0 && IVAL(pdata,0) == total_data) { - /* uggh, EAs for OS2 */ - DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return ERROR_DOS(ERRDOS,ERReasnotsupported); + if ( pdata == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); } + *ppdata = pdata; memset((char *)pdata,'\0',data_size); @@ -2560,6 +2607,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * break; case SMB_INFO_QUERY_EAS_FROM_LIST: + { DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); data_size = 24; put_dos_date2(pdata,0,c_time); @@ -2568,13 +2616,33 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * SIVAL(pdata,12,(uint32)file_size); SIVAL(pdata,16,(uint32)allocation_size); SIVAL(pdata,20,mode); + talloc_destroy(ea_ctx); break; + } case SMB_INFO_QUERY_ALL_EAS: - DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); + { /* We have data_size bytes to put EA's into. */ - data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname); + size_t total_ea_len = 0; + + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); + + ea_ctx = talloc_init("ea_ctx"); + if (!ea_ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + ea_list = get_ea_list(ea_ctx, conn, fsp, fname, &total_ea_len); + if (!ea_list || (total_ea_len > data_size)) { + talloc_destroy(ea_ctx); + data_size = 4; + break; + } + + data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list); + talloc_destroy(ea_ctx); break; + } case SMB_FILE_BASIC_INFORMATION: case SMB_QUERY_FILE_BASIC_INFO: -- cgit From 4faa02fb3016572bc8a6496c35554e4e2075486f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Mar 2005 02:32:35 +0000 Subject: r5874: Work in progress. EA list infolevel. Jeremy (This used to be commit b033a302b59e1e72f4a72fce54abaae5c1c29f18) --- source3/smbd/trans2.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9991ff477e..0aece62018 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -152,7 +152,8 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str Return a linked list of the total EA's. Plus the total size ****************************************************************************/ -static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len) +static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, + const char *fname, size_t *pea_total_len) { /* Get a list of all xattrs. Max namesize is 64k. */ size_t ea_namelist_size = 1024; @@ -186,7 +187,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, if (sizeret == -1) return NULL; - DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret )); + DEBUG(10,("get_ea_list_from_file: ea_namelist size = %d\n", sizeret )); if (sizeret) { for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { @@ -207,7 +208,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, fstring dos_ea_name; push_ascii_fstring(dos_ea_name, listp->ea.name); *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; - DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n", + DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n", *pea_total_len, dos_ea_name, (unsigned int)listp->ea.value.length )); } @@ -219,7 +220,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, } } - DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len)); + DEBUG(10,("get_ea_list_from_file: total_len = %u\n", *pea_total_len)); return ea_list_head; } @@ -282,7 +283,7 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, return 0; } mem_ctx = talloc_init("estimate_ea_size"); - (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); talloc_destroy(mem_ctx); return total_ea_len; } @@ -295,7 +296,7 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con { size_t total_ea_len; TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name"); - struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); for (; ea_list; ea_list = ea_list->next) { if (strequal(&unix_ea_name[5], ea_list->ea.name)) { @@ -439,6 +440,57 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d return ea_list_head; } +/**************************************************************************** + Count the total EA size needed. +****************************************************************************/ + +static size_t ea_list_size(struct ea_list *ealist) +{ + fstring dos_ea_name; + struct ea_list *listp; + size_t ret = 0; + + for (listp = ealist; listp; listp = listp->next) { + push_ascii_fstring(dos_ea_name, listp->ea.name); + ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; + } + /* Add on 4 for total length. */ + if (ret) { + ret += 4; + } + + return ret; +} + +/**************************************************************************** + Return a union of EA's from a file list and a list of names. +****************************************************************************/ + +static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len) +{ + struct ea_list *nlistp, *flistp; + + for (flistp = file_list; flistp;) { + struct ea_list *rem_entry = flistp; + + for (nlistp = name_list; nlistp; nlistp = nlistp->next) { + if (strequal(nlistp->ea.name, flistp->ea.name)) { + break; + } + } + + flistp = flistp->next; + + if (nlistp == NULL) { + /* Remove this entry from file ea list. */ + DLIST_REMOVE(file_list, rem_entry); + } + } + + *total_ea_len = ea_list_size(file_list); + return file_list; +} + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -2608,14 +2660,29 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_INFO_QUERY_EAS_FROM_LIST: { + size_t total_ea_len = 0; + struct ea_list *ea_file_list = NULL; + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); - data_size = 24; put_dos_date2(pdata,0,c_time); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); SIVAL(pdata,12,(uint32)file_size); SIVAL(pdata,16,(uint32)allocation_size); SIVAL(pdata,20,mode); + + ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len); + + ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len); + + if (!ea_list || (total_ea_len > data_size - 24)) { + talloc_destroy(ea_ctx); + data_size = 4; + break; + } + + data_size = fill_ea_buffer(ea_ctx, pdata + 24, data_size - 24, conn, ea_list); + data_size += 24; talloc_destroy(ea_ctx); break; } @@ -2632,7 +2699,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_NO_MEMORY); } - ea_list = get_ea_list(ea_ctx, conn, fsp, fname, &total_ea_len); + ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len); if (!ea_list || (total_ea_len > data_size)) { talloc_destroy(ea_ctx); data_size = 4; -- cgit From deb021217248484ffb532661c82da541107f9bc9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Mar 2005 00:31:45 +0000 Subject: r5893: Get us to pass some of the Samba4 EA tests. EA_LIST seems to be working - need to valgrind it to be sure. Jeremy. (This used to be commit 8b2b652c0a47298cd188c67d256dfdffe01a951d) --- source3/smbd/nttrans.c | 5 ++ source3/smbd/trans2.c | 132 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 92 insertions(+), 45 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fbb7364090..26e5195d77 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -353,6 +353,11 @@ static int map_share_mode( char *fname, uint32 create_options, int smb_open_mode = -1; uint32 original_desired_access = *desired_access; + /* This is a nasty hack - must fix... JRA. */ + if (*desired_access == MAXIMUM_ALLOWED_ACCESS) { + *desired_access = FILE_GENERIC_ALL; + } + /* * Convert GENERIC bits to specific bits. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0aece62018..9455f138cc 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -676,8 +676,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i * Ensure we have enough parameters to perform the operation. */ - if (total_params < 29) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 29) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } open_mode = SVAL(params, 2); open_attr = SVAL(params,6); @@ -1413,8 +1414,9 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb SMB_STRUCT_STAT sbuf; NTSTATUS ntstatus = NT_STATUS_OK; - if (total_params < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } *directory = *mask = 0; @@ -1641,8 +1643,9 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu int space_remaining; NTSTATUS ntstatus = NT_STATUS_OK; - if (total_params < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } *mask = *directory = *resume_name = 0; @@ -2171,7 +2174,7 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb if (total_params < 4) { DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n", total_params)); - return ERROR_DOS(ERRDOS,ERRinvalidparam); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } fsp = file_fsp(params,0); @@ -2429,8 +2432,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * ZERO_STRUCT(sbuf); if (tran_call == TRANSACT2_QFILEINFO) { - if (total_params < 4) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -2485,8 +2489,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * NTSTATUS status = NT_STATUS_OK; /* qpathinfo */ - if (total_params < 6) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } info_level = SVAL(params,0); @@ -3314,8 +3319,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char ZERO_STRUCT(sbuf); if (tran_call == TRANSACT2_SETFILEINFO) { - if (total_params < 4) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -3361,8 +3367,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } } else { /* set path info */ - if (total_params < 6) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } info_level = SVAL(params,0); srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False); @@ -3426,8 +3433,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char switch (info_level) { case SMB_INFO_STANDARD: { - if (total_data < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } /* access time */ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); @@ -3442,12 +3450,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(status); break; +#if 0 + /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */ /* XXXX um, i don't think this is right. it's also not in the cifs6.txt spec. */ case SMB_INFO_QUERY_EAS_FROM_LIST: if (total_data < 28) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); @@ -3458,13 +3468,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char /* XXXX nor this. not in cifs6.txt, either. */ case SMB_INFO_QUERY_ALL_EAS: if (total_data < 28) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); size = IVAL(pdata,16); dosmode = IVAL(pdata,24); break; +#endif case SMB_SET_FILE_BASIC_INFO: case SMB_FILE_BASIC_INFORMATION: @@ -3473,8 +3484,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char time_t write_time; time_t changed_time; - if (total_data < 36) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 36) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } /* Ignore create time at offset pdata. */ @@ -3505,8 +3517,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char int ret = -1; SMB_BIG_UINT allocation_size; - if (total_data < 8) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } allocation_size = (SMB_BIG_UINT)IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T @@ -3579,8 +3592,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_SET_FILE_END_OF_FILE_INFO: { - if (total_data < 8) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T @@ -3598,8 +3612,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char { BOOL delete_on_close; - if (total_data < 1) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 1) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } delete_on_close = (CVAL(pdata,0) ? True : False); @@ -3627,8 +3642,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char { SMB_BIG_UINT position_information; - if (total_data < 8) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } position_information = (SMB_BIG_UINT)IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T @@ -3644,6 +3660,26 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char break; } + /* From tridge Samba4 : + * MODE_INFORMATION in setfileinfo (I have no + * idea what "mode information" on a file is - it takes a value of 0, + * 2, 4 or 6. What could it be?). + */ + + case SMB_FILE_MODE_INFORMATION: + { + uint32 mode; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + mode = IVAL(pdata,0); + if (mode != 0 && mode != 2 && mode != 4 && mode != 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + break; + } + /* * CIFS UNIX extensions. */ @@ -3652,8 +3688,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char { uint32 raw_unixmode; - if (total_data < 100) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 100) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { @@ -3702,8 +3739,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (tran_call == TRANSACT2_SETFILEINFO) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - if (raw_unixmode == SMB_MODE_NO_CHANGE) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (raw_unixmode == SMB_MODE_NO_CHANGE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #if defined(HAVE_MAKEDEV) dev = makedev(dev_major, dev_minor); @@ -3871,8 +3909,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstring base_name; char *p; - if (total_data < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } overwrite = (CVAL(pdata,0) ? True : False); root_fid = IVAL(pdata,4); @@ -3925,7 +3964,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", BOOL valid_def_acls = True; if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } posix_acl_version = SVAL(pdata,0); num_file_acls = SVAL(pdata,2); @@ -3942,12 +3981,12 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } if (posix_acl_version != SMB_POSIX_ACL_VERSION) { - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (total_data < SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, @@ -4115,8 +4154,9 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); - if (total_params < 4) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { @@ -4163,8 +4203,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char char *params = *pparams; uint16 info_level; - if (total_params < 6) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } info_level = SVAL(params,4); DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level)); @@ -4239,8 +4280,9 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* DEBUG(10,("call_trans2getdfsreferral\n")); - if (total_params < 2) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 2) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } max_referral_level = SVAL(params,0); @@ -4423,7 +4465,7 @@ int reply_trans2(connection_struct *conn, DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt)); DEBUG(2,("Transaction is %d\n",tran_call)); END_PROFILE(SMBtrans2); - ERROR_DOS(ERRDOS,ERRinvalidparam); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } -- cgit From 4b122ce2da493e3abd1ca54dd2ce8b9752e70ec8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Mar 2005 18:21:39 +0000 Subject: r5905: Fix two warnings found by AIX. They might actually be bugs on 64-bit platforms. Volker (This used to be commit f7218d1c66ae91fa79f5a40e0ba618beba038bbc) --- source3/smbd/chgpasswd.c | 3 ++- source3/smbd/service.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 540acfc225..989fc4d68c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -943,7 +943,8 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) const uint8 *nt_pw; const uint8 *pwhistory; BOOL found = False; - int i, pwHisLen, curr_pwHisLen; + int i; + uint32 pwHisLen, curr_pwHisLen; account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); if (pwHisLen == 0) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 684d49c56a..7bbf8d7f2a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -272,7 +272,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, struct passwd *pass = NULL; BOOL guest = False; connection_struct *conn; - struct stat st; + SMB_STRUCT_STAT st; fstring user; fstring dev; -- cgit From ff107a93cdf4ab75be44097897ecc42ea46580e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 21 Mar 2005 18:10:21 +0000 Subject: r5922: Fix for NASTY NASTY bug #2501. All my fault :-(. Brown paper bag time. Stops Win98 from looping doing findnext on a singleton directory. More testing very welcome. Jeremy. (This used to be commit e32a58742e618a49934e19b72cd5222c9666cf95) --- source3/smbd/dir.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index db16b8a6e0..1ec35d839c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -595,6 +595,13 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) { ZERO_STRUCTP(pst); + + if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) { + /* This is a singleton directory and we're already at the end. */ + *poffset = -1; + return False; + } + while (SearchDir(dptr->dir_hnd, name, poffset) == True) { if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { return True; -- cgit From 442b9f3e87ee7f9fe8c100cd37c9591733e290e6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Mar 2005 02:14:38 +0000 Subject: r5933: We were handling setting of EA's incorrectly - we should be able to set a list. Also not converting names from DOS CP to UNIX CP correctly. This code doesn't quite work yet but it's a work in progress to be fixed tomorrow (don't want to lose it). Jeremy. (This used to be commit 22fca746576810c5408540031a9603625a66cd75) --- source3/smbd/trans2.c | 453 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 325 insertions(+), 128 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9455f138cc..d09231dd83 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -313,106 +313,78 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con Set or delete an extended attribute. ****************************************************************************/ -static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, - char *pdata, int total_data) +static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list) { - unsigned int namelen; - unsigned int ealen; - int ret; - fstring unix_ea_name; - if (!lp_ea_support(SNUM(conn))) { return NT_STATUS_EAS_NOT_SUPPORTED; } - if (total_data < 8) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (IVAL(pdata,0) > total_data) { - DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); - return NT_STATUS_INVALID_PARAMETER; - } - - pdata += 4; - namelen = CVAL(pdata,1); - ealen = SVAL(pdata,2); - pdata += 4; - if (total_data < 8 + namelen + 1 + ealen) { - DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n", - (unsigned int)total_data, namelen, ealen)); - return NT_STATUS_INVALID_PARAMETER; - } - - if (pdata[namelen] != '\0') { - DEBUG(10,("set_ea: ea name not null terminated\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ - pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE); - pdata += (namelen + 1); + while (ea_list) { + int ret; + fstring unix_ea_name; - canonicalize_ea_name(conn, fsp, fname, unix_ea_name); + fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ + fstrcat(unix_ea_name, ea_list->ea.name); - DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen)); - if (ealen) { - DEBUG(10,("set_ea: data :\n")); - dump_data(10, pdata, ealen); - } + canonicalize_ea_name(conn, fsp, fname, unix_ea_name); - if (samba_private_attr_name(unix_ea_name)) { - DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); - return NT_STATUS_ACCESS_DENIED; - } + DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length)); - if (ealen == 0) { - /* Remove the attribute. */ - if (fsp && (fsp->fd != -1)) { - DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); - } else { - DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", - unix_ea_name, fname)); - ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); + if (samba_private_attr_name(unix_ea_name)) { + DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); + return NT_STATUS_ACCESS_DENIED; } + + if (ea_list->ea.value.length == 0) { + /* Remove the attribute. */ + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); + } else { + DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); + } #ifdef ENOATTR - /* Removing a non existent attribute always succeeds. */ - if (ret == -1 && errno == ENOATTR) { - DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name)); - ret = 0; - } + /* Removing a non existent attribute always succeeds. */ + if (ret == -1 && errno == ENOATTR) { + DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", + unix_ea_name)); + ret = 0; + } #endif - } else { - if (fsp && (fsp->fd != -1)) { - DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0); } else { - DEBUG(10,("set_ea: setting ea name %s on file %s.\n", - unix_ea_name, fname)); - ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0); + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, + ea_list->ea.value.data, ea_list->ea.value.length, 0); + } else { + DEBUG(10,("set_ea: setting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, + ea_list->ea.value.data, ea_list->ea.value.length, 0); + } } - } - if (ret == -1) { + if (ret == -1) { #ifdef ENOTSUP - if (errno == ENOTSUP) { - return NT_STATUS_EAS_NOT_SUPPORTED; - } + if (errno == ENOTSUP) { + return NT_STATUS_EAS_NOT_SUPPORTED; + } #endif - return map_nt_error_from_unix(errno); - } + return map_nt_error_from_unix(errno); + } + } return NT_STATUS_OK; } - /**************************************************************************** - Read a list of EA's from an incoming data buffer. Create an ea_list with them. + Read a list of EA names from an incoming data buffer. Create an ea_list with them. ****************************************************************************/ -static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) { struct ea_list *ea_list_head = NULL; size_t offset = 4; @@ -426,15 +398,83 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d if (offset + namelen >= data_size) { break; } - eal->ea.name = TALLOC_ARRAY(ctx, char, namelen + 1); + /* Ensure the name is null terminated. */ + if (pdata[offset + namelen] != '\0') { + return NULL; + } + pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]); if (!eal->ea.name) { - break; + return NULL; } - memcpy(eal->ea.name, pdata + offset, namelen); - eal->ea.name[namelen] = '\0'; offset += (namelen + 1); /* Go past the name + terminating zero. */ DLIST_ADD_END(ea_list_head, eal, tmp); + DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); + } + + return ea_list_head; +} + +/**************************************************************************** + Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 4; + + if (data_size < 10) { + return NULL; + } + + if (IVAL(pdata,0) > data_size) { + DEBUG(10,("read_ea_list: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)data_size)); + return NULL; + } + + /* Each entry must be at least 6 bytes in length. */ + while (offset + 6 <= data_size) { + struct ea_list *tmp; + struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + uint16 val_len; + unsigned int namelen; + + eal->ea.flags = CVAL(pdata,offset); + namelen = CVAL(pdata,offset + 1); + val_len = SVAL(pdata,offset + 2); + + if (offset + 4 + namelen + 1 + val_len > data_size) { + return NULL; + } + + /* Ensure the name is null terminated. */ + if (pdata[offset + 4 + namelen] != '\0') { + return NULL; + } + pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset); + if (!eal->ea.name) { + return NULL; + } + + eal->ea.value = data_blob(NULL, (size_t)val_len + 1); + if (!eal->ea.value.data) { + break; + } + + memcpy(eal->ea.value.data, pdata + offset + 4 + namelen + 1, val_len); + + /* Ensure we're null terminated just in case we print the value. */ + eal->ea.value.data[val_len] = '\0'; + /* But don't count the null. */ + eal->ea.value.length--; + + offset += 4 + namelen + 1 + val_len; + + DLIST_ADD_END(ea_list_head, eal, tmp); + + DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); + dump_data(10, eal->ea.value.data, eal->ea.value.length); } return ea_list_head; @@ -464,31 +504,34 @@ static size_t ea_list_size(struct ea_list *ealist) /**************************************************************************** Return a union of EA's from a file list and a list of names. + The TALLOC context for the two lists *MUST* be identical as we steal + memory from one list to another. JRA. ****************************************************************************/ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len) { struct ea_list *nlistp, *flistp; - for (flistp = file_list; flistp;) { - struct ea_list *rem_entry = flistp; - - for (nlistp = name_list; nlistp; nlistp = nlistp->next) { + for (nlistp = name_list; nlistp; nlistp = nlistp->next) { + for (flistp = file_list; flistp; flistp = flistp->next) { if (strequal(nlistp->ea.name, flistp->ea.name)) { break; } } - flistp = flistp->next; - - if (nlistp == NULL) { - /* Remove this entry from file ea list. */ - DLIST_REMOVE(file_list, rem_entry); + if (flistp) { + /* Copy the data from this entry. */ + nlistp->ea.flags = flistp->ea.flags; + nlistp->ea.value = flistp->ea.value; + } else { + /* Null entry. */ + nlistp->ea.flags = 0; + ZERO_STRUCT(nlistp->ea.value); } } - *total_ea_len = ea_list_size(file_list); - return file_list; + *total_ea_len = ea_list_size(name_list); + return name_list; } /**************************************************************************** @@ -737,8 +780,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i /* Realloc the size of parameters and data we will return */ params = SMB_REALLOC(*pparams, 28); - if( params == NULL ) - return(ERROR_DOS(ERRDOS,ERRnomem)); + if( params == NULL ) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; memset((char *)params,'\0',28); @@ -876,7 +920,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, BOOL *out_of_space, BOOL *got_exact_match, - int *last_entry_off) + int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx) { const char *dname; BOOL found = False; @@ -1104,14 +1148,62 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ break; -#if 0 case SMB_FIND_EA_LIST: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); + { + struct ea_list *file_list = NULL; + size_t ea_len = 0; + + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); + if (!name_list) { + return False; + } if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; } -#endif + put_dos_date2(p,l2_fdateCreation,cdate); + put_dos_date2(p,l2_fdateLastAccess,adate); + put_dos_date2(p,l2_fdateLastWrite,mdate); + SIVAL(p,l2_cbFile,(uint32)file_size); + SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); + SSVAL(p,l2_attrFile,mode); + p += l2_cbList; /* p now points to the EA area. */ + + file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len); + name_list = ea_list_union(name_list, file_list, &ea_len); + + /* We need to determine if this entry will fit in the space available. */ + /* Max string size is 255 bytes. */ + if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { + /* Move the dirptr back to prev_dirpos */ + dptr_SeekDir(conn->dirptr, prev_dirpos); + *out_of_space = True; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } + + /* Push the ea_data followed by the name. */ + p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list); + nameptr = p; + len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN); + if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; + } + } else { + if (len > 1) { + len -= 1; + } else { + len = 0; + } + } + SCVAL(nameptr,0,len); + p += len + 1; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; + } case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); @@ -1412,6 +1504,8 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb int space_remaining; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + TALLOC_CTX *ea_ctx = NULL; + struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; if (total_params < 12) { @@ -1433,6 +1527,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", switch (info_level) { case SMB_FIND_INFO_STANDARD: case SMB_FIND_EA_SIZE: + case SMB_FIND_EA_LIST: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: @@ -1478,29 +1573,66 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); + if (info_level == SMB_FIND_EA_LIST) { + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ea_size = IVAL(pdata,0); + if (ea_size != total_data) { + DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if( pdata == NULL ) - return(ERROR_DOS(ERRDOS,ERRnomem)); + if( pdata == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 10); - if (params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if (params == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) + if (dptr_num < 0) { + talloc_destroy(ea_ctx); return(UNIXERROR(ERRDOS,ERRbadfile)); + } /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRnomem); + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); } DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); @@ -1530,7 +1662,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_entry_off); + &last_entry_off, ea_list, ea_ctx); } if (finished && out_of_space) @@ -1552,6 +1684,8 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", space_remaining = max_data_bytes - PTR_DIFF(p,pdata); } + talloc_destroy(ea_ctx); + /* Check if we can close the dirptr */ if(close_after_first || (finished && close_if_end)) { DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); @@ -1641,6 +1775,8 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu BOOL dont_descend = False; BOOL out_of_space = False; int space_remaining; + TALLOC_CTX *ea_ctx = NULL; + struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; if (total_params < 12) { @@ -1678,6 +1814,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", switch (info_level) { case SMB_FIND_INFO_STANDARD: case SMB_FIND_EA_SIZE: + case SMB_FIND_EA_LIST: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: @@ -1691,29 +1828,66 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return ERROR_DOS(ERRDOS,ERRunknownlevel); } + if (info_level == SMB_FIND_EA_LIST) { + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ea_size = IVAL(pdata,0); + if (ea_size != total_data) { + DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if(pdata == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(pdata == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 6*SIZEOFWORD); - if( params == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); + if( params == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; /* Check that the dptr is valid */ - if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) + if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { + talloc_destroy(ea_ctx); return ERROR_DOS(ERRDOS,ERRnofiles); + } string_set(&conn->dirpath,dptr_path(dptr_num)); /* Get the wildcard mask from the dptr */ if((p = dptr_wcard(dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); + talloc_destroy(ea_ctx); return ERROR_DOS(ERRDOS,ERRnofiles); } @@ -1784,7 +1958,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_entry_off); + &last_entry_off, ea_list, ea_ctx); } if (finished && out_of_space) @@ -1806,6 +1980,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", space_remaining = max_data_bytes - PTR_DIFF(p,pdata); } + talloc_destroy(ea_ctx); + /* Check if we can close the dirptr */ if(close_after_request || (finished && close_if_end)) { DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); @@ -1856,8 +2032,9 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf } pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if ( pdata == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); + if ( pdata == NULL ) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); @@ -2570,7 +2747,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Pull out the list of names. */ - ea_list = read_ea_list(ea_ctx, pdata, ea_size); + ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); if (!ea_list) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -3408,10 +3585,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); - /* Realloc the parameter and data sizes */ + /* Realloc the parameter size */ params = SMB_REALLOC(*pparams,2); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); @@ -3445,10 +3623,25 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } case SMB_INFO_SET_EA: - status = set_ea(conn, fsp, fname, pdata, total_data); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + { + struct ea_list *ea_list = NULL; + TALLOC_CTX *ctx = talloc_init("SMB_INFO_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata, total_data); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + + if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) { return ERROR_NT(status); + } break; + } #if 0 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */ @@ -4179,8 +4372,9 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,2); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); @@ -4220,8 +4414,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,6); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,fnf_handle); @@ -4253,8 +4448,9 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,4); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); /* No changes */ @@ -4321,8 +4517,9 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { pdata = SMB_REALLOC(*ppdata, 32); - if(pdata == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(pdata == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 @@ -4480,7 +4677,7 @@ int reply_trans2(connection_struct *conn, SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRDOS,ERRnomem); + return ERROR_NT(NT_STATUS_NO_MEMORY); } /* Copy the param and data bytes sent with this request into -- cgit From ebb9ba6ddc88d53656eddf0149abc99299bb6a3e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Mar 2005 02:23:52 +0000 Subject: r5936: Fix bugs in earlier work in progress commit. Closer to properly supporting EA's now. Jeremy. (This used to be commit 8aa2b2617baefef004a864c4210b20a66ef89fd4) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d09231dd83..ce04da2751 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -319,7 +319,7 @@ static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *f return NT_STATUS_EAS_NOT_SUPPORTED; } - while (ea_list) { + for (;ea_list; ea_list = ea_list->next) { int ret; fstring unix_ea_name; @@ -452,7 +452,7 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d if (pdata[offset + 4 + namelen] != '\0') { return NULL; } - pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset); + pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset + 4); if (!eal->ea.name) { return NULL; } -- cgit From 4b831f8e16d305666b0f2b018c35f5427efc21cc Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 22 Mar 2005 15:12:50 +0000 Subject: r5952: BUG 2469: patch from Jason Mader to cleanup compiler warning when not using krb5 (This used to be commit 19a639ac468237b22f16d917c0150fbf10c9623e) --- source3/smbd/sesssetup.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 40ea28a86d..e1fb71d575 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -417,7 +417,9 @@ static int reply_spnego_negotiate(connection_struct *conn, DATA_BLOB secblob; int i; DATA_BLOB chal; - BOOL got_kerberos = False; +#ifdef HAVE_KRB5 + BOOL got_kerberos_mechanism = False; +#endif NTSTATUS nt_status; /* parse out the OIDs and the first sec blob */ @@ -434,11 +436,13 @@ static int reply_spnego_negotiate(connection_struct *conn, server sent back krb5/mskrb5/ntlmssp as mechtypes, but the client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an NTLMSSP mechtoken. --jerry */ - + +#ifdef HAVE_KRB5 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { - got_kerberos = True; + got_kerberos_mechanism = True; } +#endif for (i=0;OIDs[i];i++) { DEBUG(3,("Got OID %s\n", OIDs[i])); @@ -447,7 +451,7 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if (got_kerberos && (SEC_ADS == lp_security())) { + if (got_kerberos_mechanism && (SEC_ADS == lp_security())) { int ret = reply_spnego_kerberos(conn, inbuf, outbuf, length, bufsize, &secblob); data_blob_free(&secblob); -- cgit From cf99ec82969f6d3c553472028bd9aa2112ef35d4 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 22 Mar 2005 17:31:23 +0000 Subject: r5958: BUG 1843: patch from james peach to fix quotas (with no soft limits) on IRIX (This used to be commit aeb3cea54ea2e050aef38e38fd8519510a14a184) --- source3/smbd/quotas.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 1117461bc2..1a73fdf222 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -882,8 +882,17 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB restore_re_uid(); if (r==-1) + { + DEBUG(5, ("quotactl for uid=%u: %s", euser_id, strerror(errno))); return(False); + } + /* No quota for this user. */ + if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) + { + return(False); + } + /* Use softlimit to determine disk space, except when it has been exceeded */ if ( (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) || @@ -895,14 +904,10 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB *dfree = 0; *dsize = F.d_bcount; } - else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) - { - return(False); - } else { *dfree = (F.d_blk_softlimit - F.d_bcount); - *dsize = F.d_blk_softlimit; + *dsize = F.d_blk_softlimit ? F.d_blk_softlimit : F.d_blk_hardlimit; } } -- cgit From 09bb17511b3c5b32ab93ef37dbb451674bcc5a0b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Mar 2005 17:48:41 +0000 Subject: r5960: Integer wrap paranoia when reading EA buffers. Jeremy. (This used to be commit e61f7a6b72fe6186a5a56f23f9133c5b1a49bb89) --- source3/smbd/trans2.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ce04da2751..81c102a4ee 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -395,7 +395,11 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz unsigned int namelen = CVAL(pdata,offset); offset++; /* Go past the namelen byte. */ - if (offset + namelen >= data_size) { + + /* integer wrap paranioa. */ + if ((offset + namelen < offset) || (offset + namelen < namelen) || + (offset > data_size) || (namelen > data_size) || + (offset + namelen >= data_size)) { break; } /* Ensure the name is null terminated. */ @@ -444,6 +448,16 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d namelen = CVAL(pdata,offset + 1); val_len = SVAL(pdata,offset + 2); + /* integer wrap paranioa. */ + if ((offset + namelen + 5 + val_len < offset) || + (offset + namelen + 5 + val_len < namelen) || + (offset + namelen + 5 + val_len < val_len) || + (offset > data_size) || + (namelen > data_size) || + (offset + namelen >= data_size)) { + return NULL; + } + if (offset + 4 + namelen + 1 + val_len > data_size) { return NULL; } @@ -473,7 +487,7 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d DLIST_ADD_END(ea_list_head, eal, tmp); - DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); + DEBUG(10,("read_ea_list: read ea name %s\n", eal->ea.name)); dump_data(10, eal->ea.value.data, eal->ea.value.length); } @@ -505,7 +519,7 @@ static size_t ea_list_size(struct ea_list *ealist) /**************************************************************************** Return a union of EA's from a file list and a list of names. The TALLOC context for the two lists *MUST* be identical as we steal - memory from one list to another. JRA. + memory from one list to add to another. JRA. ****************************************************************************/ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len) @@ -2730,7 +2744,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * /* Pull any EA list from the data portion. */ if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) { - uint32 ea_size = IVAL(pdata,0); + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + ea_size = IVAL(pdata,0); if (total_data > 0 && ea_size != total_data) { DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ -- cgit From 93e04e941e15034c8e7aa1faedc74ce536049153 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 22 Mar 2005 18:07:58 +0000 Subject: r5961: final round of compiler warning fixes based on feedback from Jason Mader (This used to be commit 9e77da9320c900b3e437d534e31fa5ff81e9acfd) --- source3/smbd/chgpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 989fc4d68c..d0e0f6e143 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -747,8 +747,8 @@ static NTSTATUS check_oem_password(const char *user, static uchar null_pw[16]; static uchar null_ntpw[16]; SAM_ACCOUNT *sampass = NULL; - char *password_encrypted; - const char *encryption_key; + uint8 *password_encrypted; + const uint8 *encryption_key; const uint8 *lanman_pw, *nt_pw; uint16 acct_ctrl; uint32 new_pw_len; -- cgit From 8b6a50cf3ecad43fbb70b778983231d7ec5adbbc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Mar 2005 19:35:56 +0000 Subject: r6001: Oops. Checing the wrong tagtype - should have been SMB_ACL_GROUP, not SMB_ACL_MASK. Fix bug #2521. Jeremy. (This used to be commit 21e3cf2f8f6129324ebb799f959f8d2afe0285d2) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c5f96db85c..c5fa035c69 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3840,7 +3840,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *dnam } } break; - case SMB_ACL_MASK: + case SMB_ACL_GROUP: { gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (pgid == NULL) { -- cgit From 5d1cb8e79edea9e8581d3c2c9dd297310cd9a98c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 23 Mar 2005 23:26:33 +0000 Subject: r6014: rather large change set.... pulling back all recent rpc changes from trunk into 3.0. I've tested a compile and so don't think I've missed any files. But if so, just mail me and I'll clean backup in a couple of hours. Changes include \winreg, \eventlog, \svcctl, and general parse_misc.c updates. I am planning on bracketing the event code with an #ifdef ENABLE_EVENTLOG until I finish merging Marcin's changes (very soon). (This used to be commit 4e0ac63c36527cd8c52ef720cae17e84f67e7221) --- source3/smbd/nttrans.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 26e5195d77..49a6d48ce1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -40,6 +40,8 @@ static const char *known_nt_pipes[] = { "\\spoolss", "\\netdfs", "\\rpcecho", + "\\svcctl", + "\\eventlog", NULL }; -- cgit From 5415480d7eea3ddd319625087e6ed902cd6e04c6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Mar 2005 01:02:52 +0000 Subject: r6020: Never do NT status codes with protocols before NT1 as we don't get client caps. Jeremy. (This used to be commit 4868e4202775c1c0a60828e0c6f6fa23cf8346e1) --- source3/smbd/sesssetup.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e1fb71d575..48524b472d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -677,6 +677,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (Protocol < PROTOCOL_NT1) { uint16 passlen1 = SVAL(inbuf,smb_vwv7); + + /* Never do NT status codes with protocols before NT1 as we don't get client caps. */ + remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); + if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } -- cgit From 143bf1202c924f53db811d1d076580eea4acdb7e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Mar 2005 02:23:32 +0000 Subject: r6022: Fix for bug #2533. Incorrect dir listings from OS/2 clients. Jeremy. (This used to be commit cf8949f684ee9adcd35d56d923b2f5733efc05ac) --- source3/smbd/dir.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 1ec35d839c..6ecdcec461 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -713,16 +713,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname SMB_STRUCT_STAT sbuf; pstring path; pstring pathreal; - BOOL isrootdir; pstring filename; BOOL needslash; *path = *pathreal = *filename = 0; - isrootdir = (strequal(conn->dirpath,"./") || - strequal(conn->dirpath,".") || - strequal(conn->dirpath,"/")); - needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); if (!conn->dirptr) @@ -747,8 +742,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname if ((strcmp(mask,"*.*") == 0) || mask_match(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { - if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) - continue; if (!mangle_is_8_3(filename, False)) mangle_map(filename,True,False,SNUM(conn)); -- cgit From 445a9729f03117afdaa141a6d074d8af064b4399 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Mar 2005 19:33:02 +0000 Subject: r6044: Ensure the old search calls always ask mask_match to translate patterns like ????????.??? - even if using an NT1 protocol. Matches W2K3 behavior. Jeremy. (This used to be commit 67f6473f50f3284b9ccbe6f983f23cd42b3b7c9f) --- source3/smbd/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 6ecdcec461..55f1523865 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -698,7 +698,7 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype) static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask) { mangle_map(filename,True,False,SNUM(conn)); - return mask_match(filename,mask,False); + return mask_match_search(filename,mask,False); } /**************************************************************************** @@ -740,7 +740,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname see masktest for a demo */ if ((strcmp(mask,"*.*") == 0) || - mask_match(filename,mask,False) || + mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { if (!mangle_is_8_3(filename, False)) -- cgit From 27b84e5e5573cf922b77bdf935a715af2c4ce1c2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Mar 2005 22:32:52 +0000 Subject: r6048: Split out the check_path_syntax into a findfirst/next/wildcard version. The semantics are different with wildcards. Jeremy. (This used to be commit f8b67159fc1c8224a7caf41409b2654846f34a2d) --- source3/smbd/msdfs.c | 4 +- source3/smbd/reply.c | 158 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 136 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 184dde1635..36baff8022 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -64,7 +64,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1,True); + check_path_syntax(pdp->reqpath, p+1); DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -110,7 +110,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1,True); + check_path_syntax(pdp->reqpath, p+1); DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e8ee9ffe92..059af83001 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -38,13 +38,13 @@ extern uint32 global_client_caps; extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** - Ensure we check the path in *exactly* the same way as W2K. + Ensure we check the path in *exactly* the same way as W2K for regular pathnames. We're assuming here that '/' is not the second byte in any multibyte char set (a safe assumption). '\\' *may* be the second byte in a multibyte char set. ****************************************************************************/ -NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names) +NTSTATUS check_path_syntax(pstring destname, const pstring srcname) { char *d = destname; const char *s = srcname; @@ -118,20 +118,16 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w } if (!(*s & 0x80)) { - if (allow_wcard_names) { - *d++ = *s++; - } else { - switch (*s) { - case '*': - case '?': - case '<': - case '>': - case '"': - return NT_STATUS_OBJECT_NAME_INVALID; - default: - *d++ = *s++; - break; - } + switch (*s) { + case '*': + case '?': + case '<': + case '>': + case '"': + return NT_STATUS_OBJECT_NAME_INVALID; + default: + *d++ = *s++; + break; } } else { switch(next_mb_char_size(s)) { @@ -157,17 +153,127 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w } if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { - /* For some strange reason being called from findfirst changes - the num_components number to cause the error return to change. JRA. */ - if (allow_wcard_names) { - if (num_bad_components > 2) { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + if (num_bad_components > 1) { + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } + + *d = '\0'; + return ret; +} + +/**************************************************************************** + Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext + path or anything including wildcards. + We're assuming here that '/' is not the second byte in any multibyte char + set (a safe assumption). '\\' *may* be the second byte in a multibyte char + set. +****************************************************************************/ + +NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname) +{ + char *d = destname; + const char *s = srcname; + NTSTATUS ret = NT_STATUS_OK; + BOOL start_of_name_component = True; + unsigned int num_bad_components = 0; + + while (*s) { + if (IS_DIRECTORY_SEP(*s)) { + /* + * Safe to assume is not the second part of a mb char as this is handled below. + */ + /* Eat multiple '/' or '\\' */ + while (IS_DIRECTORY_SEP(*s)) { + s++; + } + if ((d != destname) && (*s != '\0')) { + /* We only care about non-leading or trailing '/' or '\\' */ + *d++ = '/'; + } + + start_of_name_component = True; + continue; + } + + if (start_of_name_component) { + if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { + /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */ + + /* + * No mb char starts with '.' so we're safe checking the directory separator here. + */ + + /* If we just added a '/' - delete it */ + if ((d > destname) && (*(d-1) == '/')) { + *(d-1) = '\0'; + d--; + } + + /* Are we at the start ? Can't go back further if so. */ + if (d <= destname) { + ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + break; + } + /* Go back one level... */ + /* We know this is safe as '/' cannot be part of a mb sequence. */ + /* NOTE - if this assumption is invalid we are not in good shape... */ + /* Decrement d first as d points to the *next* char to write into. */ + for (d--; d > destname; d--) { + if (*d == '/') + break; + } + s += 2; /* Else go past the .. */ + /* We're still at the start of a name component, just the previous one. */ + + if (num_bad_components) { + /* Hmmm. Should we only decrement the bad_components if + we're removing a bad component ? Need to check this. JRA. */ + num_bad_components--; + } + + continue; + + } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) { + /* Component of pathname can't be "." only. */ + ret = NT_STATUS_OBJECT_NAME_INVALID; + num_bad_components++; + *d++ = *s++; + continue; } + } + + if (!(*s & 0x80)) { + *d++ = *s++; } else { - if (num_bad_components > 1) { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + switch(next_mb_char_size(s)) { + case 4: + *d++ = *s++; + case 3: + *d++ = *s++; + case 2: + *d++ = *s++; + case 1: + *d++ = *s++; + break; + default: + DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n")); + *d = '\0'; + return NT_STATUS_INVALID_PARAMETER; } } + if (start_of_name_component && num_bad_components) { + num_bad_components++; + } + start_of_name_component = False; + } + + if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { + /* For some strange reason being called from findfirst changes + the num_components number to cause the error return to change. JRA. */ + if (num_bad_components > 2) { + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } } *d = '\0'; @@ -192,7 +298,11 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } else { ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); } - *err = check_path_syntax(dest, tmppath, allow_wcard_names); + if (allow_wcard_names) { + *err = check_path_syntax_wcard(dest, tmppath); + } else { + *err = check_path_syntax(dest, tmppath); + } return ret; } -- cgit From fcfa75b2fc19be9abe9580efa314d4c981f80098 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Mar 2005 22:34:28 +0000 Subject: r6049: Ensure "dos filetime" checks file ACLs correctly. May fix Excel "read-only" issue. Jeremy. (This used to be commit 80e788143a6c3d973d3b8e57d91ca5c4a83605b2) --- source3/smbd/dosmode.c | 25 +++------ source3/smbd/posix_acls.c | 134 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 109 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index fefcaca09d..3a0e81e5fe 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -431,10 +431,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, than POSIX. *******************************************************************/ -int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) +int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times) { - extern struct current_user current_user; - SMB_STRUCT_STAT sb; int ret = -1; errno = 0; @@ -454,21 +452,12 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(SMB_VFS_STAT(conn,fname,&sb) != 0) - return -1; - /* Check if we have write access. */ - if (CAN_WRITE(conn)) { - if (((sb.st_mode & S_IWOTH) || conn->admin_user || - ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || - ((sb.st_mode & S_IWGRP) && - in_group(sb.st_gid,current_user.gid, - current_user.ngroups,current_user.groups)))) { - /* We are allowed to become root and change the filetime. */ - become_root(); - ret = SMB_VFS_UTIME(conn,fname, times); - unbecome_root(); - } + if (can_write_to_file(conn, fname)) { + /* We are allowed to become root and change the filetime. */ + become_root(); + ret = SMB_VFS_UTIME(conn,fname, times); + unbecome_root(); } return ret; @@ -478,7 +467,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) +BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) { struct utimbuf times; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c5fa035c69..c0ccdcb6d6 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3758,23 +3758,27 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * Check for POSIX group ACLs. If none use stat entry. ****************************************************************************/ -static int check_posix_acl_group_write(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *psbuf) +static int check_posix_acl_group_write(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { extern struct current_user current_user; SMB_ACL_T posix_acl = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; int i; + BOOL seen_mask = False; int ret = -1; - if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, dname, SMB_ACL_TYPE_ACCESS)) == NULL) { + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS)) == NULL) { goto check_stat; } /* First ensure the group mask allows group read. */ + /* Also check any user entries (these take preference over group). */ + while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; + int have_write = -1; /* get_next... */ if (entry_id == SMB_ACL_FIRST_ENTRY) @@ -3788,20 +3792,51 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *dnam goto check_stat; } + have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE); + if (have_write == -1) { + goto check_stat; + } + switch(tagtype) { case SMB_ACL_MASK: - if (!SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE)) { - /* We don't have group write permission. */ + if (!have_write) { + /* We don't have any group or explicit user write permission. */ ret = -1; /* Allow caller to check "other" permissions. */ + DEBUG(10,("check_posix_acl_group_write: file %s \ +refusing write due to mask.\n", fname)); goto done; } + seen_mask = True; + break; + case SMB_ACL_USER: + { + /* Check against current_user.uid. */ + uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + if (puid == NULL) { + goto check_stat; + } + if (current_user.uid == *puid) { + /* We have a uid match but we must ensure we have seen the acl mask. */ + ret = have_write; + DEBUG(10,("check_posix_acl_group_write: file %s \ +match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "cannot write")); + if (seen_mask) { + goto done; + } + } break; + } default: continue; } } - /* Now check all group entries. */ + /* If ret is anything other than -1 we matched on a user entry. */ + if (ret != -1) { + goto done; + } + + /* Next check all group entries. */ entry_id = SMB_ACL_FIRST_ENTRY; while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; @@ -3826,35 +3861,23 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *dnam } switch(tagtype) { - case SMB_ACL_USER: - { - /* Check against current_user.uid. */ - uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); - if (puid == NULL) { - goto check_stat; - } - if (current_user.uid == *puid) { - /* We're done now we have a uid match. */ + case SMB_ACL_GROUP: + { + gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + if (pgid == NULL) { + goto check_stat; + } + for (i = 0; i < current_user.ngroups; i++) { + if (current_user.groups[i] == *pgid) { + /* We're done now we have a gid match. */ ret = have_write; + DEBUG(10,("check_posix_acl_group_write: file %s \ +match on group %u -> %s.\n", fname, (unsigned int)*pgid, ret ? "can write" : "cannot write")); goto done; } } break; - case SMB_ACL_GROUP: - { - gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); - if (pgid == NULL) { - goto check_stat; - } - for (i = 0; i < current_user.ngroups; i++) { - if (current_user.groups[i] == *pgid) { - /* We're done now we have a gid match. */ - ret = have_write; - goto done; - } - } - } - break; + } default: continue; } @@ -3877,7 +3900,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *dnam } /**************************************************************************** - Actually emulate the in-kernel access checking for write access. We need + Actually emulate the in-kernel access checking for delete access. We need this to successfully return ACCESS_DENIED on a file open for delete access. ****************************************************************************/ @@ -3888,6 +3911,11 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) pstring dname; int ret; + if (!CAN_WRITE(conn)) { + return False; + } + + /* Get the parent directory permission mask and owners. */ pstrcpy(dname, parent_dirname(fname)); if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) { return False; @@ -3895,11 +3923,12 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) if (!S_ISDIR(sbuf.st_mode)) { return False; } - if (current_user.uid == 0) { + if (current_user.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; } + /* Check primary owner write access. */ if (current_user.uid == sbuf.st_uid) { return (sbuf.st_mode & S_IWUSR) ? True : False; } @@ -3918,11 +3947,52 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) } #endif - /* Check group ownership. */ + /* Check group or explicit user acl entry write access. */ ret = check_posix_acl_group_write(conn, dname, &sbuf); if (ret == 0 || ret == 1) { return ret ? True : False; } + /* Finally check other write access. */ + return (sbuf.st_mode & S_IWOTH) ? True : False; +} + +/**************************************************************************** + Actually emulate the in-kernel access checking for write access. We need + this to successfully check for ability to write for dos filetimes. +****************************************************************************/ + +BOOL can_write_to_file(connection_struct *conn, const char *fname) +{ + extern struct current_user current_user; + SMB_STRUCT_STAT sbuf; + int ret; + + if (!CAN_WRITE(conn)) { + return False; + } + + if (current_user.uid == 0 || conn->admin_user) { + /* I'm sorry sir, I didn't know you were root... */ + return True; + } + + /* Get the file permission mask and owners. */ + if(SMB_VFS_STAT(conn, fname, &sbuf) != 0) { + return False; + } + + /* Check primary owner write access. */ + if (current_user.uid == sbuf.st_uid) { + return (sbuf.st_mode & S_IWUSR) ? True : False; + } + + /* Check group or explicit user acl entry write access. */ + ret = check_posix_acl_group_write(conn, fname, &sbuf); + if (ret == 0 || ret == 1) { + return ret ? True : False; + } + + /* Finally check other write access. */ return (sbuf.st_mode & S_IWOTH) ? True : False; } -- cgit From a5433c4bf7a256880725173b96af5405c3c2eb9c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Mar 2005 00:58:15 +0000 Subject: r6053: Fixup dfs path with the new wildcard parser code split out. Jeremy. (This used to be commit e831cef618d55c362e8d3a8a4c2b9f2ed7d4d7bd) --- source3/smbd/msdfs.c | 39 +++++++++++++++++---------------------- source3/smbd/posix_acls.c | 2 +- source3/smbd/reply.c | 12 ++++++------ source3/smbd/trans2.c | 2 +- 4 files changed, 25 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 36baff8022..2e4649efed 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -75,7 +75,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) into the dfs_path structure **********************************************************************/ -static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) +static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL allow_wcards) { pstring pathname_local; char* p,*temp; @@ -110,7 +110,11 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + if (allow_wcards) { + check_path_syntax_wcard(pdp->reqpath, p+1); + } else { + check_path_syntax(pdp->reqpath, p+1); + } DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -265,9 +269,7 @@ BOOL is_msdfs_link(connection_struct* conn, char * path, Used by other functions to decide if a dfs path is remote, and to get the list of referred locations for that remote path. -findfirst_flag: For findfirsts, dfs links themselves are not -redirected, but paths beyond the links are. For normal smb calls, -even dfs links need to be redirected. +allow_wcards: Should we allow wildcards when parsing paths. self_referralp: clients expect a dfs referral for the same share when they request referrals for dfs roots on a server. @@ -279,7 +281,7 @@ should try the remaining path on the redirected server. static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, connection_struct* conn, - BOOL findfirst_flag, + BOOL allow_wcards, struct referral** reflistpp, int* refcntp, BOOL* self_referralp, int* consumedcntp) { @@ -311,18 +313,11 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /* check if need to redirect */ if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { - if (findfirst_flag) { - DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " - "for dfs link %s.\n", dfspath)); - return False; - } else { - DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", - dfspath)); - if (consumedcntp) - *consumedcntp = strlen(dfspath); - return True; - } - } + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); + if (consumedcntp) + *consumedcntp = strlen(dfspath); + return True; + } /* redirect if any component in the path is a link */ pstrcpy(reqpath, dp->reqpath); @@ -366,15 +361,14 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, If not, the pathname is converted to a tcon-relative local unix path *****************************************************************/ -BOOL dfs_redirect(pstring pathname, connection_struct* conn, - BOOL findfirst_flag) +BOOL dfs_redirect(pstring pathname, connection_struct* conn, BOOL allow_wcards) { struct dfs_path dp; if (!conn || !pathname) return False; - parse_processed_dfs_path(pathname, &dp); + parse_processed_dfs_path(pathname, &dp, allow_wcards); /* if dfs pathname for a non-dfs share, convert to tcon-relative path and return false */ @@ -386,7 +380,7 @@ BOOL dfs_redirect(pstring pathname, connection_struct* conn, if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; - if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, + if (resolve_dfs_path(pathname, &dp, conn, allow_wcards, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -802,6 +796,7 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref /********************************************************************** Creates a junction structure from a Dfs pathname **********************************************************************/ + BOOL create_junction(char* pathname, struct junction_map* jucn) { struct dfs_path dp; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c0ccdcb6d6..76b67169f2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3067,7 +3067,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, - &file_ace_list, &dir_ace_list, security_info_sent, psd); + &file_ace_list, &dir_ace_list, security_info_sent, psd); /* Ignore W2K traverse DACL set. */ if (file_ace_list || dir_ace_list) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 059af83001..17423c531d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -949,7 +949,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(nt_status); } - RESOLVE_DFSPATH(path, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf); p++; status_len = SVAL(p, 0); @@ -1823,7 +1823,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); DEBUG(3,("reply_unlink : %s\n",name)); @@ -4293,8 +4293,8 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); @@ -4453,8 +4453,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRSRV,ERRinvdevice); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); unix_convert(newname,conn,0,&bad_path2,&sbuf2); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 81c102a4ee..8208bf54bb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1562,7 +1562,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); if (bad_path) { -- cgit From 1ca7ec3472e9cb77888f2850930f087b5e5bf761 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Mar 2005 01:30:21 +0000 Subject: r6055: Fix algorithm. If any of the primary or supplementary group ids match a "allow" entry of GROUP or GROUP_OBJ, then access is allowed. It doesn't terminate on the first match. Added debug to show where the match occured (or didn't). Jeremy. (This used to be commit 81fb3372867fa66a092841222e02bd1c104b2d19) --- source3/smbd/posix_acls.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 76b67169f2..33db14aec3 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3860,6 +3860,11 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can goto check_stat; } + /* If we don't have write permission this entry never matches. */ + if (have_write == 0) { + continue; + } + switch(tagtype) { case SMB_ACL_GROUP: { @@ -3870,9 +3875,9 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == *pgid) { /* We're done now we have a gid match. */ - ret = have_write; + ret = 1; DEBUG(10,("check_posix_acl_group_write: file %s \ -match on group %u -> %s.\n", fname, (unsigned int)*pgid, ret ? "can write" : "cannot write")); +match on group %u -> can write.\n", fname, (unsigned int)*pgid )); goto done; } } @@ -3886,13 +3891,24 @@ match on group %u -> %s.\n", fname, (unsigned int)*pgid, ret ? "can write" : "ca check_stat: + /* If we get here we know ret == 0. */ + SMB_ASSERT(ret == 0); + for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == psbuf->st_gid) { ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; + DEBUG(10,("check_posix_acl_group_write: file %s \ +match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write")); break; } } + if (i == current_user.ngroups) { + SMB_ASSERT(ret == 0); + DEBUG(10,("check_posix_acl_group_write: file %s \ +failed to match on user or group in token.\n", fname )); + } + done: SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); -- cgit From 83c61f2ace4e07ed83bb4cd32b604e3819a363a8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Mar 2005 01:36:39 +0000 Subject: r6057: Don't put the assert in the wrong place :-). Jeremy. (This used to be commit 6609b209f513f0859040686a88ee6c7106c06008) --- source3/smbd/posix_acls.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 33db14aec3..0b95a03dcb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3888,12 +3888,11 @@ match on group %u -> can write.\n", fname, (unsigned int)*pgid )); } } - - check_stat: - /* If we get here we know ret == 0. */ SMB_ASSERT(ret == 0); + check_stat: + for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == psbuf->st_gid) { ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; @@ -3904,7 +3903,7 @@ match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "c } if (i == current_user.ngroups) { - SMB_ASSERT(ret == 0); + SMB_ASSERT(ret != 1); DEBUG(10,("check_posix_acl_group_write: file %s \ failed to match on user or group in token.\n", fname )); } -- cgit From 9dba95788071d22f90d222f5a2440d0442d55385 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Mar 2005 03:41:02 +0000 Subject: r6060: It's not quite accurate to say not having write access causes a group entry never to match - it matches but if doesn't grant access is recorded so the "other" entry isn't subsequently checked. Fix the algorithm. Jeremy. (This used to be commit e3c7d08bb68f51bc05768467feb0af896a059e91) --- source3/smbd/posix_acls.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0b95a03dcb..87173fca3b 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3860,11 +3860,6 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can goto check_stat; } - /* If we don't have write permission this entry never matches. */ - if (have_write == 0) { - continue; - } - switch(tagtype) { case SMB_ACL_GROUP: { @@ -3874,11 +3869,17 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can } for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == *pgid) { - /* We're done now we have a gid match. */ - ret = 1; + ret = have_write; DEBUG(10,("check_posix_acl_group_write: file %s \ match on group %u -> can write.\n", fname, (unsigned int)*pgid )); - goto done; + + /* If we don't have write permission this entry doesn't + terminate the enumeration of the entries. */ + if (have_write) { + goto done; + } + /* But does terminate the group iteration. */ + break; } } break; -- cgit From 10fe0ae721194157d87f306feab30b5f3f42c9b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Mar 2005 19:52:01 +0000 Subject: r6063: Fix for bug #2533 - ensure SMBsearch unsets UNICODE flags2 bit as this SMB is DOS codepage only. Jeremy. (This used to be commit 56cc756b9d14db23b2640c347f729fa90dad9b6a) --- source3/smbd/reply.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 17423c531d..6cc6a97afc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1090,7 +1090,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (Protocol >= PROTOCOL_NT1) SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); - + + /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */ + SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); + outsize += DIR_STRUCT_SIZE*numentries; smb_setlen(outbuf,outsize - 4); -- cgit From e2204e24ba39f90fdea6a4de458f81373368eb42 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Mar 2005 23:45:11 +0000 Subject: r6067: Patch from Marcel Müller - fix OS/2 EA_FROM_LIST info level. Jeremy. (This used to be commit e15c36e9497b5e92c0f743a522cd0adb96d22295) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/trans2.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8208bf54bb..b1beed82ac 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2865,25 +2865,17 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd struct ea_list *ea_file_list = NULL; DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); - put_dos_date2(pdata,0,c_time); - put_dos_date2(pdata,4,sbuf.st_atime); - put_dos_date2(pdata,8,sbuf.st_mtime); - SIVAL(pdata,12,(uint32)file_size); - SIVAL(pdata,16,(uint32)allocation_size); - SIVAL(pdata,20,mode); ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len); - ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len); - if (!ea_list || (total_ea_len > data_size - 24)) { + if (!ea_list || (total_ea_len > data_size)) { talloc_destroy(ea_ctx); data_size = 4; break; } - data_size = fill_ea_buffer(ea_ctx, pdata + 24, data_size - 24, conn, ea_list); - data_size += 24; + data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list); talloc_destroy(ea_ctx); break; } -- cgit From 404fa5636ddae8caa0a46bb68b796d23ec3f5a0e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 Mar 2005 00:44:46 +0000 Subject: r6069: Fix for bug #2541. Ensure we recognise LANMAN2.1 as OS/2 and select LANMAN2 protocol, ensure the EA size is always correctly set on a query for a file with no EA's. Jeremy. (This used to be commit d6ad1f8df05e16152d9c95df56e612fde288d3b4) --- source3/smbd/negprot.c | 1 + source3/smbd/trans2.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 9aaa818c62..bdb15cb3f7 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -419,6 +419,7 @@ static const struct { {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1}, + {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b1beed82ac..77f879b53d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -237,8 +237,8 @@ static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned in SMB_ASSERT(total_data_size >= 4); - SIVAL(pdata,0,0); if (!lp_ea_support(SNUM(conn))) { + SIVAL(pdata,4,0); return 4; } -- cgit From 780b1eedab36369ef835e45b966f73ede4c7fd12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 27 Mar 2005 20:44:06 +0000 Subject: r6082: Fix for bugid #2541. Fixes from Guenter Kukkukk Jeremy. (This used to be commit 057e4bf641674473f1ac1e0fbe936b4f2506e013) --- source3/smbd/trans2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 77f879b53d..ad125788a1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2872,6 +2872,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (!ea_list || (total_ea_len > data_size)) { talloc_destroy(ea_ctx); data_size = 4; + SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ break; } @@ -2896,6 +2897,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (!ea_list || (total_ea_len > data_size)) { talloc_destroy(ea_ctx); data_size = 4; + SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ break; } -- cgit From fa787af52093e14de4a472d2ccb50b9ec66b10d1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Mar 2005 00:36:30 +0000 Subject: r6106: Fix bug #2551. It turns out that the incoming flags2 flag FLAGS2_LONG_PATH_COMPONENTS determines if a reply is uppercased on a SMBsearch request, not the protocol level. This could clear up quite a few hacks going forward I think. Jeremy. (This used to be commit 8c64cd368fdd2c5a4b361904855c135ade3f449e) --- source3/smbd/reply.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6cc6a97afc..9a811c14a3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -931,6 +931,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL can_open = True; BOOL bad_path = False; NTSTATUS nt_status; + BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; + START_PROFILE(SMBsearch); *mask = *directory = *fname = 0; @@ -1030,7 +1032,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (ok) { if ((dirtype&0x1F) == aVOLID) { memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); + make_dir_struct(p,"???????????",volume_label(SNUM(conn)), + 0,aVOLID,0,!allow_long_path_components); dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; @@ -1050,7 +1053,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend); if (!finished) { memcpy(p,status,21); - make_dir_struct(p,mask,fname,size,mode,date); + make_dir_struct(p,mask,fname,size, mode,date, + !allow_long_path_components); dptr_fill(p+12,dptr_num); numentries++; p += DIR_STRUCT_SIZE; @@ -1088,8 +1092,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SCVAL(smb_buf(outbuf),0,5); SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); - if (Protocol >= PROTOCOL_NT1) - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); + /* The replies here are never long name. */ + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME)); + if (!allow_long_path_components) { + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS)); + } /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */ SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); -- cgit From 5a69d0a82a71f0a4009e0c4e2a8c053e4d39c903 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Mar 2005 02:05:22 +0000 Subject: r6122: Added "hack" fix for broken SMB_INFO_VOLUME level - used by OS/2 I believe. Reported as fixed by Marcel Müller . Jeremy. (This used to be commit 14eab937a54dd9f02f289d7e2f47c78c834714a3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/trans2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ad125788a1..163cfbd5e3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2097,7 +2097,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi * the called hostname and the service name. */ SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) ); - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN); + /* + * Win2k3 and previous mess this up by sending a name length + * one byte short. I believe only older clients (OS/2 Win9x) use + * this call so try fixing this by adding a terminating null to + * the pushed string. The change here was adding the STR_TERMINATE. JRA. + */ + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", -- cgit From 7dcc247164f53e6a8b36c4024a88fb3759c06b4d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Mar 2005 02:24:47 +0000 Subject: r6124: Fix for bug #2242 from Tom Lackemann - don't set SD on an NTtransact create unless we created the file. Jeremy. (This used to be commit b42eaf424e34544fae3f0fc473694e61dda2a11c) --- source3/smbd/nttrans.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 49a6d48ce1..9dcbea5c25 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1461,15 +1461,28 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } /* - * Now try and apply the desired SD. + * According to the MS documentation, the only time the security + * descriptor is applied to the opened file is iff we *created* the + * file; an existing file stays the same. + * + * Also, it seems (from observation) that you can open the file with + * any access mask but you can still write the sd. We need to override + * the granted access before we call set_sd + * Patch for bug #2242 from Tom Lackemann . */ - if (lp_nt_acl_support(SNUM(conn)) && sd_len && - !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { - close_file(fsp,False); - restore_case_semantics(conn, file_attributes); - return ERROR_NT(status); - } + if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) { + uint32 saved_access = fsp->desired_access; + + fsp->desired_access = FILE_GENERIC_ALL; + + if (!NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { + close_file(fsp,False); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(status); + } + fsp->desired_access = saved_access; + } restore_case_semantics(conn, file_attributes); -- cgit From f1977014f4f239e174b97cba7d4810c01a4581d1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Mar 2005 20:53:02 +0000 Subject: r6138: Refactor length reading out of EA code so we can read length external to buffer. Needed to add EA code to create calls. Jeremy. (This used to be commit 7c4262d6ba48695c2622ea2eba8da6ac889ce543) --- source3/smbd/trans2.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 163cfbd5e3..7071676212 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -387,7 +387,7 @@ static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *f static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) { struct ea_list *ea_list_head = NULL; - size_t offset = 4; + size_t offset = 0; while (offset + 2 < data_size) { struct ea_list *tmp; @@ -426,17 +426,12 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) { struct ea_list *ea_list_head = NULL; - size_t offset = 4; + size_t offset = 0; if (data_size < 10) { return NULL; } - if (IVAL(pdata,0) > data_size) { - DEBUG(10,("read_ea_list: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)data_size)); - return NULL; - } - /* Each entry must be at least 6 bytes in length. */ while (offset + 6 <= data_size) { struct ea_list *tmp; @@ -1589,11 +1584,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", if (info_level == SMB_FIND_EA_LIST) { uint32 ea_size; - + if (total_data < 4) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - + ea_size = IVAL(pdata,0); if (ea_size != total_data) { DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \ @@ -1610,7 +1605,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Pull out the list of names. */ - ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); + ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); if (!ea_list) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -1863,9 +1858,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - + /* Pull out the list of names. */ - ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); + ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); if (!ea_list) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -2772,7 +2767,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Pull out the list of names. */ - ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); + ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); if (!ea_list) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -3644,11 +3639,23 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_INFO_SET_EA: { struct ea_list *ea_list = NULL; - TALLOC_CTX *ctx = talloc_init("SMB_INFO_SET_EA"); + TALLOC_CTX *ctx = NULL; + + if (total_data < 10) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n", + IVAL(pdata,0), (unsigned int)total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ctx = talloc_init("SMB_INFO_SET_EA"); if (!ctx) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - ea_list = read_ea_list(ctx, pdata, total_data); + ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); if (!ea_list) { talloc_destroy(ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); -- cgit From b7c6e71b26b913fda0a4ba4a99eb7ea35657a104 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Mar 2005 00:36:22 +0000 Subject: r6141: Fix OS/2 EA's for NTcreate. OpenX and mkdir to follow. Jeremy. (This used to be commit 106f91ff65acd23a7dda4d0ec89ae41ecb28153e) --- source3/smbd/nttrans.c | 94 ++++++++++++++++++++++++++++++++++++++-- source3/smbd/trans2.c | 113 ++++++++++++++++++++++++++----------------------- 2 files changed, 150 insertions(+), 57 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9dcbea5c25..1d4acf2844 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1165,6 +1165,34 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu return NT_STATUS_OK; } +/**************************************************************************** + Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 0; + + if (data_size < 4) { + return NULL; + } + + while (offset + 4 <= data_size) { + size_t next_offset = IVAL(pdata,offset); + struct ea_list *tmp; + struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); + + DLIST_ADD_END(ea_list_head, eal, tmp); + if (next_offset == 0) { + break; + } + offset += next_offset; + } + + return ea_list_head; +} + /**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ @@ -1194,11 +1222,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o uint32 create_disposition; uint32 create_options; uint32 sd_len; + uint32 ea_len; uint16 root_dir_fid; SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; time_t c_time; + struct ea_list *ea_list = NULL; + TALLOC_CTX *ctx = NULL; + char *pdata = NULL; NTSTATUS status; DEBUG(5,("call_nt_transact_create\n")); @@ -1224,7 +1256,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(parameter_count < 54) { DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count)); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } flags = IVAL(params,0); @@ -1234,8 +1266,24 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o create_disposition = IVAL(params,28); create_options = IVAL(params,32); sd_len = IVAL(params,36); + ea_len = IVAL(params,40); root_dir_fid = (uint16)IVAL(params,4); + /* Ensure the data_len is correct for the sd and ea values given. */ + if ((ea_len + sd_len > data_count) || + (ea_len > data_count) || (sd_len > data_count) || + (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (ea_len && !lp_ea_support(SNUM(conn))) { + return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + } + + if (ea_len < 10) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + if (create_options & FILE_OPEN_BY_FILE_ID) { return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } @@ -1368,6 +1416,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } + ctx = talloc_init("NTTRANS_CREATE_EA"); + if (!ctx) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + pdata = data + sd_len; + + /* We have already checked that ea_len <= data_count here. */ + ea_list = read_nttrans_ea_list(ctx, pdata, ea_len); + if (!ea_list ) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + /* * If it's a request for a directory open, deal with it separately. */ @@ -1376,6 +1441,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1390,6 +1457,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { + talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } @@ -1422,10 +1490,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { + talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { + talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ @@ -1442,9 +1512,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fmode = FILE_ATTRIBUTE_NORMAL; if (fmode & aDIR) { + talloc_destroy(ctx); close_file(fsp,False); restore_case_semantics(conn, file_attributes); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); } /* @@ -1453,11 +1524,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * correct bit for extended oplock reply. */ - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { extended_oplock_granted = True; + } - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { extended_oplock_granted = True; + } } /* @@ -1474,9 +1547,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) { uint32 saved_access = fsp->desired_access; + /* We have already checked that sd_len <= data_count here. */ + fsp->desired_access = FILE_GENERIC_ALL; if (!NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { + talloc_destroy(ctx); close_file(fsp,False); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); @@ -1484,6 +1560,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp->desired_access = saved_access; } + if (ea_len && smb_action == FILE_WAS_CREATED) { + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) { + close_file(fsp,False); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(status); + } + } + restore_case_semantics(conn, file_attributes); /* Save the requested allocation size. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7071676212..1ae013d23a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -95,11 +95,6 @@ static BOOL samba_private_attr_name(const char *unix_ea_name) return False; } -struct ea_list { - struct ea_list *next, *prev; - struct ea_struct ea; -}; - /**************************************************************************** Get one EA value. Fill in a struct ea_struct. ****************************************************************************/ @@ -313,7 +308,7 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con Set or delete an extended attribute. ****************************************************************************/ -static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list) +NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list) { if (!lp_ea_support(SNUM(conn))) { return NT_STATUS_EAS_NOT_SUPPORTED; @@ -420,70 +415,82 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz } /**************************************************************************** - Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. + Read one EA list entry from the buffer. ****************************************************************************/ -static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used) { - struct ea_list *ea_list_head = NULL; - size_t offset = 0; + struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + uint16 val_len; + unsigned int namelen; - if (data_size < 10) { + if (!eal) { return NULL; } - /* Each entry must be at least 6 bytes in length. */ - while (offset + 6 <= data_size) { - struct ea_list *tmp; - struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); - uint16 val_len; - unsigned int namelen; + if (data_size < 6) { + return NULL; + } - eal->ea.flags = CVAL(pdata,offset); - namelen = CVAL(pdata,offset + 1); - val_len = SVAL(pdata,offset + 2); + eal->ea.flags = CVAL(pdata,0); + namelen = CVAL(pdata,1); + val_len = SVAL(pdata,2); - /* integer wrap paranioa. */ - if ((offset + namelen + 5 + val_len < offset) || - (offset + namelen + 5 + val_len < namelen) || - (offset + namelen + 5 + val_len < val_len) || - (offset > data_size) || - (namelen > data_size) || - (offset + namelen >= data_size)) { - return NULL; - } + if (4 + namelen + 1 + val_len > data_size) { + return NULL; + } - if (offset + 4 + namelen + 1 + val_len > data_size) { - return NULL; - } + /* Ensure the name is null terminated. */ + if (pdata[namelen + 4] != '\0') { + return NULL; + } + pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4); + if (!eal->ea.name) { + return NULL; + } - /* Ensure the name is null terminated. */ - if (pdata[offset + 4 + namelen] != '\0') { - return NULL; - } - pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset + 4); - if (!eal->ea.name) { - return NULL; - } + eal->ea.value = data_blob(NULL, (size_t)val_len + 1); + if (!eal->ea.value.data) { + return NULL; + } - eal->ea.value = data_blob(NULL, (size_t)val_len + 1); - if (!eal->ea.value.data) { - break; - } + memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len); - memcpy(eal->ea.value.data, pdata + offset + 4 + namelen + 1, val_len); + /* Ensure we're null terminated just in case we print the value. */ + eal->ea.value.data[val_len] = '\0'; + /* But don't count the null. */ + eal->ea.value.length--; - /* Ensure we're null terminated just in case we print the value. */ - eal->ea.value.data[val_len] = '\0'; - /* But don't count the null. */ - eal->ea.value.length--; + if (pbytes_used) { + *pbytes_used = 4 + namelen + 1 + val_len; + } - offset += 4 + namelen + 1 + val_len; + DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name)); + dump_data(10, eal->ea.value.data, eal->ea.value.length); - DLIST_ADD_END(ea_list_head, eal, tmp); + return eal; +} - DEBUG(10,("read_ea_list: read ea name %s\n", eal->ea.name)); - dump_data(10, eal->ea.value.data, eal->ea.value.length); +/**************************************************************************** + Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 0; + size_t bytes_used = 0; + + while (offset < data_size) { + struct ea_list *tmp; + struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used); + + if (!eal) { + return NULL; + } + + DLIST_ADD_END(ea_list_head, eal, tmp); + offset += bytes_used; } return ea_list_head; -- cgit From b76112f2116c3c08c7656387a4a49ea64915f470 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Mar 2005 02:12:09 +0000 Subject: r6146: Added OS/2 EA support in trans2_open and trans2_mkdir. Fixed in nttrans_create. Jeremy. (This used to be commit 989fcb4c084c63f1e3b114af68ef5bc0a2fbc09e) --- source3/smbd/nttrans.c | 60 ++++++++++++++++++------------- source3/smbd/trans2.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1d4acf2844..70b3f0d0e0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -637,7 +637,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if((smb_ofun = map_create_disposition( create_disposition )) == -1) { END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRnoaccess)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } /* @@ -1273,15 +1273,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if ((ea_len + sd_len > data_count) || (ea_len > data_count) || (sd_len > data_count) || (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) { + DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n", + (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count )); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - if (ea_len && !lp_ea_support(SNUM(conn))) { - return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); - } + if (ea_len) { + if (!lp_ea_support(SNUM(conn))) { + DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n", + (unsigned int)ea_len )); + return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + } - if (ea_len < 10) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if (ea_len < 10) { + DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n", + (unsigned int)ea_len )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } } if (create_options & FILE_OPEN_BY_FILE_ID) { @@ -1293,8 +1301,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * NT values, as that's what our code is structured to accept. */ - if((smb_ofun = map_create_disposition( create_disposition )) == -1) - return ERROR_DOS(ERRDOS,ERRbadmem); + if((smb_ofun = map_create_disposition( create_disposition )) == -1) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } /* * Get the file name. @@ -1416,21 +1425,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } - ctx = talloc_init("NTTRANS_CREATE_EA"); - if (!ctx) { - talloc_destroy(ctx); - restore_case_semantics(conn, file_attributes); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } + if (ea_len) { + ctx = talloc_init("NTTRANS_CREATE_EA"); + if (!ctx) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } - pdata = data + sd_len; + pdata = data + sd_len; - /* We have already checked that ea_len <= data_count here. */ - ea_list = read_nttrans_ea_list(ctx, pdata, ea_len); - if (!ea_list ) { - talloc_destroy(ctx); - restore_case_semantics(conn, file_attributes); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + /* We have already checked that ea_len <= data_count here. */ + ea_list = read_nttrans_ea_list(ctx, pdata, ea_len); + if (!ea_list ) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } } /* @@ -1551,7 +1562,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp->desired_access = FILE_GENERIC_ALL; - if (!NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { + status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION); + if (!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); close_file(fsp,False); restore_case_semantics(conn, file_attributes); @@ -1560,10 +1572,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp->desired_access = saved_access; } - if (ea_len && smb_action == FILE_WAS_CREATED) { + if (ea_len && (smb_action == FILE_WAS_CREATED)) { status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) { + if (!NT_STATUS_IS_OK(status)) { close_file(fsp,False); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1ae013d23a..a68b165cb0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -710,6 +710,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i unsigned int max_data_bytes) { char *params = *pparams; + char *pdata = *ppdata; int16 open_mode; int16 open_attr; BOOL oplock_request; @@ -729,6 +730,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i int smb_action = 0; BOOL bad_path = False; files_struct *fsp; + TALLOC_CTX *ctx = NULL; + struct ea_list *ea_list = NULL; NTSTATUS status; /* @@ -759,7 +762,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(status); } - DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", + DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n", fname,open_mode, open_attr, open_ofun, open_size)); /* XXXX we need to handle passed times, sattr and flags */ @@ -773,10 +776,38 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } + /* Any data in this call is an EA list. */ + if (total_data && !lp_ea_support(SNUM(conn))) { + return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + } + + if (total_data) { + if (total_data < 10) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n", + IVAL(pdata,0), (unsigned int)total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ctx = talloc_init("TRANS2_OPEN_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr, oplock_request, &rmode,&smb_action); if (!fsp) { + talloc_destroy(ctx); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ clear_cached_errors(); @@ -790,10 +821,20 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { + talloc_destroy(ctx); close_file(fsp,False); return(ERROR_DOS(ERRDOS,ERRnoaccess)); } + if (total_data && smb_action == FILE_WAS_CREATED) { + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + if (!NT_STATUS_IS_OK(status)) { + close_file(fsp,False); + return ERROR_NT(status); + } + } + /* Realloc the size of parameters and data we will return */ params = SMB_REALLOC(*pparams, 28); if( params == NULL ) { @@ -3670,7 +3711,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) { + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } break; @@ -3853,13 +3894,15 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char status = set_delete_on_close_internal(fsp, delete_on_close, dosmode); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); + } /* The set is across all open files on this dev/inode pair. */ status =set_delete_on_close_over_all(fsp, delete_on_close); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); + } break; } @@ -4371,11 +4414,14 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, unsigned int max_data_bytes) { char *params = *pparams; + char *pdata = *ppdata; pstring directory; int ret = -1; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; NTSTATUS status = NT_STATUS_OK; + TALLOC_CTX *ctx = NULL; + struct ea_list *ea_list = NULL; if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); @@ -4395,14 +4441,53 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, if (bad_path) { return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - if (check_name(directory,conn)) + + /* Any data in this call is an EA list. */ + if (total_data && !lp_ea_support(SNUM(conn))) { + return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + } + + if (total_data) { + if (total_data < 10) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n", + IVAL(pdata,0), (unsigned int)total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ctx = talloc_init("TRANS2_MKDIR_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + + if (check_name(directory,conn)) { ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); + } if(ret < 0) { + talloc_destroy(ctx); DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } + /* Try and set any given EA. */ + if (total_data) { + status = set_ea(conn, NULL, directory, ea_list); + talloc_destroy(ctx); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + } + /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,2); if(params == NULL) { -- cgit From 9840db418bad5a39edc4a32a1786f5e2d2c9dff8 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 31 Mar 2005 05:06:04 +0000 Subject: r6149: Fixes bugs #2498 and 2484. 1. using smbc_getxattr() et al, one may now request all access control entities in the ACL without getting all other NT attributes. 2. added the ability to exclude specified attributes from the result set provided by smbc_getxattr() et al, when requesting all attributes, all NT attributes, or all DOS attributes. 3. eliminated all compiler warnings, including when --enable-developer compiler flags are in use. removed -Wcast-qual flag from list, as that is specifically to force warnings in the case of casting away qualifiers. Note: In the process of eliminating compiler warnings, a few nasties were discovered. In the file libads/sasl.c, PRIVATE kerberos interfaces are being used; and in libsmb/clikrb5.c, both PRIAVE and DEPRECATED kerberos interfaces are being used. Someone who knows kerberos should look at these and determine if there is an alternate method of accomplishing the task. (This used to be commit 994694f7f26da5099f071e1381271a70407f33bb) --- source3/smbd/notify_kernel.c | 10 ++++++---- source3/smbd/oplock_linux.c | 12 +++++++++--- source3/smbd/sesssetup.c | 4 +++- 3 files changed, 18 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 8fcc18a09f..c368fd79a1 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -101,8 +101,9 @@ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path close((int)fd_pending_array[i]); fd_pending_array[i] = (SIG_ATOMIC_T)-1; if (signals_received - i - 1) { - memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + memmove(CONST_DISCARD(void *, &fd_pending_array[i]), + CONST_DISCARD(void *, &fd_pending_array[i+1]), + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); } data->directory_handle = -1; signals_received--; @@ -129,8 +130,9 @@ static void kernel_remove_notify(void *datap) if (fd == (int)fd_pending_array[i]) { fd_pending_array[i] = (SIG_ATOMIC_T)-1; if (signals_received - i - 1) { - memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + memmove(CONST_DISCARD(void *, &fd_pending_array[i]), + CONST_DISCARD(void *, &fd_pending_array[i+1]), + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); } data->directory_handle = -1; signals_received--; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 5de9dd56e6..fe324577e1 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -69,16 +69,21 @@ static void set_capability(unsigned capability) #define _LINUX_CAPABILITY_VERSION 0x19980330 #endif /* these can be removed when they are in glibc headers */ - struct { + struct cap_user_header { uint32 version; int pid; } header; - struct { + struct cap_user_data { uint32 effective; uint32 permitted; uint32 inheritable; } data; + extern int capget(struct cap_user_header * hdrp, + struct cap_user_data * datap); + extern int capset(struct cap_user_header * hdrp, + const struct cap_user_data * datap); + header.version = _LINUX_CAPABILITY_VERSION; header.pid = 0; @@ -133,7 +138,8 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l fsp = file_find_fd(fd); fd_pending_array[0] = (SIG_ATOMIC_T)-1; if (signals_received > 1) - memmove((void *)&fd_pending_array[0], (void *)&fd_pending_array[1], + memmove(CONST_DISCARD(void *, &fd_pending_array[0]), + CONST_DISCARD(void *, &fd_pending_array[1]), sizeof(SIG_ATOMIC_T)*(signals_received-1)); signals_received--; /* now we can receive more signals */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 48524b472d..60867df653 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -313,7 +313,9 @@ static int reply_spnego_kerberos(connection_struct *conn, /* wrap that up in a nice GSS-API wrapping */ if (NT_STATUS_IS_OK(ret)) { - ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); + ap_rep_wrapped = spnego_gen_krb5_wrap( + ap_rep, + CONST_ADD(const uint8 *, TOK_ID_KRB_AP_REP)); } else { ap_rep_wrapped = data_blob(NULL, 0); } -- cgit From 67425afa3ebc9a105b9b11aebe036c0ca0c5d6e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Mar 2005 19:10:59 +0000 Subject: r6152: Correctly check OpenX open modes. Jeremy. (This used to be commit 326124a7b366feaca6162f7defae89618b005adc) --- source3/smbd/open.c | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9d9d9d9208..baea165d2a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1124,15 +1124,30 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } - fsp = file_new(conn); - if(!fsp) - return NULL; + switch(ofun) { + case FILE_EXISTS_OPEN: + case FILE_EXISTS_TRUNCATE: + case FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST: + case FILE_EXISTS_OPEN | FILE_CREATE_IF_NOT_EXIST: + case FILE_EXISTS_TRUNCATE | FILE_CREATE_IF_NOT_EXIST: + break; /* These are ok. */ + default: + if (GET_OPEN_MODE(share_mode) == DOS_OPEN_EXEC) { + ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; + break; + } + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidparam; + unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; + /* need to reset errno or DEVELOPER will cause us to coredump */ + errno = 0; + return NULL; + } DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); if (!check_name(fname,conn)) { - file_free(fsp); return NULL; } @@ -1155,14 +1170,12 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); /* need to reset errno or DEVELOPER will cause us to coredump */ errno = 0; - file_free(fsp); return NULL; } if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed) { DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", fname )); - file_free(fsp); if (S_ISDIR(psbuf->st_mode)) { errno = EISDIR; } else { @@ -1184,7 +1197,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n", fname, existing_dos_mode, new_dos_mode, (int)psbuf->st_mode, (int)mode )); - file_free(fsp); errno = EACCES; return NULL; } @@ -1197,6 +1209,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ append does not mean the same thing under dos and unix */ switch (GET_OPEN_MODE(share_mode)) { + case DOS_OPEN_RDONLY: + flags = O_RDONLY; + if (desired_access == 0) + desired_access = FILE_READ_DATA; + break; case DOS_OPEN_WRONLY: flags = O_WRONLY; if (desired_access == 0) @@ -1209,15 +1226,18 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; case DOS_OPEN_RDWR: + case DOS_OPEN_EXEC: flags = O_RDWR; if (desired_access == 0) desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; default: - flags = O_RDONLY; - if (desired_access == 0) - desired_access = FILE_READ_DATA; - break; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidparam; + unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; + /* need to reset errno or DEVELOPER will cause us to coredump */ + errno = 0; + return NULL; } #if defined(O_SYNC) @@ -1231,7 +1251,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (!fcbopen) { DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - file_free(fsp); errno = EACCES; return NULL; } @@ -1240,7 +1259,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - file_free(fsp); errno = EINVAL; return NULL; } @@ -1256,6 +1274,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ } } + fsp = file_new(conn); + if(!fsp) + return NULL; + if (file_existed) { dev = psbuf->st_dev; -- cgit From 89fffb349f19708ab23d5fd11fb004ee2ba1fe29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Apr 2005 00:21:55 +0000 Subject: r6160: Ensure allocation size is correctly returned for OpenX. Only set allocation on create/truncate for nttrans. Jeremy. (This used to be commit fb05ac4c03eec21f3f18668610022ebfa6d6bf4a) --- source3/smbd/nttrans.c | 68 ++++++++++++++++++++++++++------------------------ source3/smbd/reply.c | 17 ++++++++++++- 2 files changed, 51 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 70b3f0d0e0..5f5854cda3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -588,7 +588,6 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); - SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; /* Breakout the oplock request bits so we can set the @@ -931,25 +930,27 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib } /* Save the requested allocation size. */ - allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); + if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif - if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); - if (fsp->is_directory) { - close_file(fsp,False); - END_PROFILE(SMBntcreateX); - /* Can't set allocation size on a directory. */ - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_DISK_FULL); + if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (fsp->is_directory) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + /* Can't set allocation size on a directory. */ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else { + fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); } - } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); } /* @@ -1224,7 +1225,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o uint32 sd_len; uint32 ea_len; uint16 root_dir_fid; - SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; time_t c_time; @@ -1585,24 +1585,26 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o restore_case_semantics(conn, file_attributes); /* Save the requested allocation size. */ - allocation_size = (SMB_BIG_UINT)IVAL(params,12); + if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif - if (allocation_size && (allocation_size > file_len)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); - if (fsp->is_directory) { - close_file(fsp,False); - END_PROFILE(SMBntcreateX); - /* Can't set allocation size on a directory. */ - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); - return ERROR_NT(NT_STATUS_DISK_FULL); + if (allocation_size && (allocation_size > file_len)) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (fsp->is_directory) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + /* Can't set allocation size on a directory. */ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else { + fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); } - } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); } /* Realloc the size of parameters and data we will return */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9a811c14a3..e2de97c478 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1311,6 +1311,21 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } size = sbuf.st_size; + + if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9); + if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else { + fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size); + } + } + fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { @@ -1348,7 +1363,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt put_dos_date3(outbuf,smb_vwv4,mtime & ~1); else put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,(uint32)size); + SIVAL(outbuf,smb_vwv6,(uint32)get_allocation_size(conn,fsp,&sbuf)); SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,smb_action); -- cgit From 1da65dc29eefab5a011458d125a9d0597df29848 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Apr 2005 00:54:55 +0000 Subject: r6163: Well I never, all this time the t2open code was incorrectly decting oplock requests and no one noticed. Hmmm. Don't think this is a commonly used codepath :-). Jeremy. (This used to be commit 75a0c11de4b7baf693e5c62e690e4bb26554f8e2) --- source3/smbd/trans2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a68b165cb0..e53b47c1f4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -744,7 +744,11 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i open_mode = SVAL(params, 2); open_attr = SVAL(params,6); - oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1)); + oplock_request = (SVAL(params,0) & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (SVAL(params,0) & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + } + #if 0 return_additional_info = BITSETW(params,0); open_sattr = SVAL(params, 4); -- cgit From 8d2e18ac539455055b23bcbd72434e76ec46a1ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Apr 2005 19:57:22 +0000 Subject: r6169: Fix bug #2563. Infinite loop on non-existant file with findnext. Jeremy (This used to be commit 065ab9182dc39557b8c26d3d110abe9963ad9568) --- source3/smbd/dir.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 55f1523865..27ec003fb8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -573,8 +573,6 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT } } - dptr->has_wild = True; - /* In case sensitive mode we don't search - we know if it doesn't exist with a stat we will fail. */ @@ -584,6 +582,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT dptr->dir_hnd->offset = *poffset = -1; return NULL; } else { + dptr->has_wild = True; return dptr_normal_ReadDirName(dptr, poffset, pst); } } @@ -602,7 +601,7 @@ BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S return False; } - while (SearchDir(dptr->dir_hnd, name, poffset) == True) { + if (SearchDir(dptr->dir_hnd, name, poffset)) { if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { return True; } -- cgit From 0557c6cba2a21c9df547fbc8ff4db2899bc1c171 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Apr 2005 23:11:28 +0000 Subject: r6172: Tidy up error processing significantly. Remove unix_ERR_XXX global nastyness. Jeremy. (This used to be commit d3379fe61bb934082b51a37adac232a96bafcf46) --- source3/smbd/error.c | 143 ++++++++++++++++++++++++++++--------------------- source3/smbd/files.c | 6 +-- source3/smbd/nttrans.c | 32 +++++------ source3/smbd/open.c | 101 +++++++++++----------------------- source3/smbd/oplock.c | 3 ++ source3/smbd/process.c | 3 ++ source3/smbd/reply.c | 78 +++++++++++---------------- source3/smbd/trans2.c | 1 - 8 files changed, 165 insertions(+), 202 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index d611e0ef87..6988d74f91 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -20,23 +20,43 @@ #include "includes.h" -/* these can be set by some functions to override the error codes */ -int unix_ERR_class=SMB_SUCCESS; -int unix_ERR_code=0; -NTSTATUS unix_ERR_ntstatus = NT_STATUS_OK; - /* From lib/error.c */ extern struct unix_error_map unix_dos_nt_errmap[]; +/* these can be set by some functions to override the error codes */ +static int override_ERR_class; +static int override_ERR_code; +static NTSTATUS override_ERR_ntstatus; + /**************************************************************************** - Ensure we don't have any errors cached. + Setting eclass and ecode only and status to NT_STATUS_INVALID forces DOS errors. + Setting status only and eclass and ecode to -1 forces NT errors. ****************************************************************************/ -void clear_cached_errors(void) +void set_saved_error_triple(int eclass, int ecode, NTSTATUS status) +{ + override_ERR_class = eclass; + override_ERR_code = ecode; + override_ERR_ntstatus = status; +} + +/**************************************************************************** + Return the current settings of the error triple. Return True if any are set. +****************************************************************************/ + +BOOL get_saved_error_triple(int *peclass, int *pecode, NTSTATUS *pstatus) { - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + if (peclass) { + *peclass = override_ERR_class; + } + if (pecode) { + *pecode = override_ERR_code; + } + if (pstatus) { + *pstatus = override_ERR_ntstatus; + } + + return (override_ERR_class || !NT_STATUS_IS_OK(override_ERR_ntstatus)); } /**************************************************************************** @@ -46,36 +66,29 @@ void clear_cached_errors(void) int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file) { write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; - int32 eclass = wbmpx->wr_errclass; int32 err = wbmpx->wr_error; + NTSTATUS ntstatus = wbmpx->wr_status; /* We can now delete the auxiliary struct */ - free((char *)wbmpx); - fsp->wbmpx_ptr = NULL; - return error_packet(outbuf,NT_STATUS_OK,eclass,err,False,line,file); + SAFE_FREE(fsp->wbmpx_ptr); + return error_packet(outbuf,eclass,err,ntstatus,line,file); } /**************************************************************************** Create an error packet from errno. ****************************************************************************/ -int unix_error_packet(char *outbuf,int def_class,uint32 def_code, - int line, const char *file) +int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) { int eclass=def_class; int ecode=def_code; - NTSTATUS ntstatus = NT_STATUS_OK; + NTSTATUS ntstatus = def_status; int i=0; - if (unix_ERR_class != SMB_SUCCESS) { - eclass = unix_ERR_class; - ecode = unix_ERR_code; - ntstatus = unix_ERR_ntstatus; - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; - } else { + if (errno != 0) { + DEBUG(3,("unix_error_packet: error string = %s\n",strerror(errno))); + while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { eclass = unix_dos_nt_errmap[i].dos_class; @@ -87,39 +100,44 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, } } - return error_packet(outbuf,ntstatus,eclass,ecode,False,line,file); + return error_packet(outbuf,eclass,ecode,ntstatus,line,file); } /**************************************************************************** Create an error packet. Normally called using the ERROR() macro. + Setting eclass and ecode only and status to NT_STATUS_OK forces DOS errors. + Setting status only and eclass and ecode to zero forces NT errors. + If the override errors are set they take precedence over any passed in values. ****************************************************************************/ -int error_packet(char *outbuf,NTSTATUS ntstatus, - uint8 eclass,uint32 ecode,BOOL force_dos, int line, const char *file) +int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { int outsize = set_message(outbuf,0,0,True); extern uint32 global_client_caps; + BOOL force_nt_status = False; + BOOL force_dos_status = False; + + if (override_ERR_class != SMB_SUCCESS || !NT_STATUS_IS_OK(override_ERR_ntstatus)) { + eclass = override_ERR_class; + ecode = override_ERR_code; + ntstatus = override_ERR_ntstatus; + override_ERR_class = SMB_SUCCESS; + override_ERR_code = 0; + override_ERR_ntstatus = NT_STATUS_OK; + } - if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); - -#if defined(DEVELOPER) - if (unix_ERR_class != SMB_SUCCESS || unix_ERR_code != 0 || !NT_STATUS_IS_OK(unix_ERR_ntstatus)) - smb_panic("logic error in error processing"); -#endif - - /* - * We can explicitly force 32 bit error codes even when the - * parameter "nt status" is set to no by pre-setting the - * FLAGS2_32_BIT_ERROR_CODES bit in the smb_flg2 outbuf. - * This is to allow work arounds for client bugs that are needed - * when talking with clients that normally expect nt status codes. JRA. - */ - - if ((lp_nt_status_support() || (SVAL(outbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) && (global_client_caps & CAP_STATUS32) && (!force_dos)) { - if (NT_STATUS_V(ntstatus) == 0 && eclass) + if (eclass == (uint8)-1) { + force_nt_status = True; + } else if (NT_STATUS_IS_INVALID(ntstatus)) { + force_dos_status = True; + } + + if (force_nt_status || (!force_dos_status && lp_nt_status_support() && (global_client_caps & CAP_STATUS32))) { + /* We're returning an NT error. */ + if (NT_STATUS_V(ntstatus) == 0 && eclass) { ntstatus = dos_to_ntstatus(eclass, ecode); + } SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus)); SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); DEBUG(3,("error packet at %s(%d) cmd=%d (%s) %s\n", @@ -127,22 +145,23 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), nt_errstr(ntstatus))); - return outsize; - } - - if (eclass == 0 && NT_STATUS_V(ntstatus)) - ntstatus_to_dos(ntstatus, &eclass, &ecode); - - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); - SSVAL(outbuf,smb_rcls,eclass); - SSVAL(outbuf,smb_err,ecode); - - DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n", - file, line, - (int)CVAL(outbuf,smb_com), - smb_fn_name(CVAL(outbuf,smb_com)), - eclass, - ecode)); + } else { + /* We're returning a DOS error only. */ + if (eclass == 0 && NT_STATUS_V(ntstatus)) { + ntstatus_to_dos(ntstatus, &eclass, &ecode); + } + + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf,smb_rcls,eclass); + SSVAL(outbuf,smb_err,ecode); + + DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n", + file, line, + (int)CVAL(outbuf,smb_com), + smb_fn_name(CVAL(outbuf,smb_com)), + eclass, + ecode)); + } return outsize; } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 143c119693..e893e9fefc 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -95,15 +95,13 @@ files_struct *file_new(connection_struct *conn) } DEBUG(0,("ERROR! Out of file structures\n")); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRnofids; + set_saved_error_triple(ERRSRV, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES); return NULL; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRnofids; + set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY); return NULL; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5f5854cda3..6abea78239 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -889,10 +889,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(conn, file_attributes); - SSVAL(outbuf, smb_flg2, - SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); + return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } oplock_request = 0; @@ -909,7 +907,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib END_PROFILE(SMBntcreateX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); @@ -1493,8 +1490,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(conn, file_attributes); - SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); + return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } oplock_request = 0; @@ -1510,7 +1506,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o restore_case_semantics(conn, file_attributes); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); @@ -1782,12 +1777,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &access_mode,&smb_action); if (!fsp1) { - status = NT_STATUS_ACCESS_DENIED; - if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - status = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_IS_OK(status)) { + status = NT_STATUS_ACCESS_DENIED; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); return status; } @@ -1796,12 +1790,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &access_mode,&smb_action); if (!fsp2) { - status = NT_STATUS_ACCESS_DENIED; - if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - status = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_IS_OK(status)) { + status = NT_STATUS_ACCESS_DENIED; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); close_file(fsp1,False); return status; } @@ -1907,7 +1900,6 @@ int reply_ntrename(connection_struct *conn, END_PROFILE(SMBntrename); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return ERROR_NT(status); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index baea165d2a..41ced42034 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -76,9 +76,7 @@ static void check_for_pipe(const char *fname) strlower_m(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRaccess; - unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + set_saved_error_triple(ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED); } } @@ -250,9 +248,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + set_saved_error_triple(ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID); return False; } @@ -487,9 +483,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", fname )); /* Use errno to map to correct error. */ - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); return False; } @@ -529,10 +523,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -557,10 +548,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -573,18 +561,14 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } #if 0 /* Bluarc test may need this ... needs further investigation. */ if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } #endif @@ -614,10 +598,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign deny_mode,old_deny_mode,old_open_mode, (int)share->pid,fname, fcbopen, *flags, access_allowed)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -768,10 +749,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); SAFE_FREE(old_shares); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return -1; } @@ -835,9 +813,7 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) { free_broken_entry_list(broken_entry_list); errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return -1; } @@ -1104,9 +1080,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ delete_defered_open_entry_record(conn, dib.dev, dib.inode); unlock_share_entry(conn, dib.dev, dib.inode); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return NULL; } /* Ensure we don't reprocess this message. */ @@ -1136,11 +1110,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; break; } - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidparam; - unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; - /* need to reset errno or DEVELOPER will cause us to coredump */ - errno = 0; + /* Cause caller to force dos errors. */ + set_saved_error_triple(ERRDOS, ERRbadaccess, NT_STATUS_INVALID); return NULL; } @@ -1163,13 +1134,9 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* this is for OS/2 long file names - say we don't support them */ if (strstr(fname,".+,;=[].")) { - unix_ERR_class = ERRDOS; /* OS/2 Workplace shell fix may be main code stream in a later release. */ - unix_ERR_code = ERRcannotopen; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_NOT_FOUND; + set_saved_error_triple(ERRDOS, ERRcannotopen, NT_STATUS_OBJECT_NAME_NOT_FOUND); DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); - /* need to reset errno or DEVELOPER will cause us to coredump */ - errno = 0; return NULL; } @@ -1232,11 +1199,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; default: - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidparam; - unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; - /* need to reset errno or DEVELOPER will cause us to coredump */ - errno = 0; + /* Force DOS error. */ + set_saved_error_triple(ERRDOS, ERRinvalidparam, NT_STATUS_INVALID); return NULL; } @@ -1311,9 +1275,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); if (!fsp_open && errno) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRnoaccess; - unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + /* Default error. */ + set_saved_error_triple(ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED); } /* @@ -1321,9 +1284,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * the braindead 1 second delay. */ - if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents the current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + if (!internal_only_open) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { + /* The fsp->open_time here represents the current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + } } unlock_share_entry(conn, dev, inode); @@ -1333,9 +1300,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here * so return the correct error code */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1407,7 +1372,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * the braindead 1 second delay. */ - if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { /* The fsp->open_time here represents the current time of day. */ defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); } @@ -1419,9 +1386,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here, so * return the correct code. */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return NULL; } @@ -1549,9 +1514,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", fd_close(conn,fsp); file_free(fsp); ntstatus_to_dos(result, &u_e_c, &u_e_code); - unix_ERR_ntstatus = result; - unix_ERR_class = u_e_c; - unix_ERR_code = u_e_code; + set_saved_error_triple(u_e_c, u_e_code, result); return NULL; } } @@ -1704,7 +1667,7 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR fname, strerror(errno) )); file_free(fsp); /* Ensure we return the correct NT status to the client. */ - unix_ERR_ntstatus = status; + set_saved_error_triple(0, 0, status); return NULL; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index a55d5443d5..ea3ac43744 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -934,6 +934,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, abort(); } + /* We know we have no saved errors here. */ + set_saved_error_triple(0, 0, NT_STATUS_OK); + if( DEBUGLVL( 3 ) ) { dbgtext( "oplock_break: returning success for " ); dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 54837c3b9a..3043cadfd8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -211,6 +211,7 @@ BOOL open_was_deferred(uint16 mid) for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { + set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); return True; } } @@ -859,6 +860,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize pid = sys_getpid(); errno = 0; + set_saved_error_triple(0, 0, NT_STATUS_OK); + last_message = type; /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e2de97c478..aef9755122 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1206,7 +1206,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBopen); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1304,7 +1303,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt END_PROFILE(SMBopenX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1453,7 +1451,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBcreate); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1537,7 +1534,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBctemp); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1599,20 +1595,19 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, return NT_STATUS_OK; /* We need a better way to return NT status codes from open... */ - unix_ERR_class = 0; - unix_ERR_code = 0; + set_saved_error_triple(0, 0, NT_STATUS_OK); fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); if (!fsp) { - NTSTATUS ret = NT_STATUS_ACCESS_DENIED; - if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - ret = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; - return ret; + NTSTATUS ret; + if (get_saved_error_triple(NULL, NULL, &ret)) { + set_saved_error_triple(0, 0, NT_STATUS_OK); + return ret; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); + return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); return NT_STATUS_OK; @@ -1672,22 +1667,19 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_ don't do it here as we'll get it wrong. */ /* We need a better way to return NT status codes from open... */ - unix_ERR_class = 0; - unix_ERR_code = 0; + set_saved_error_triple(0, 0, NT_STATUS_OK); fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); if (!fsp) { - NTSTATUS ret = NT_STATUS_ACCESS_DENIED; - if (!NT_STATUS_IS_OK(unix_ERR_ntstatus)) - ret = unix_ERR_ntstatus; - else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - ret = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; - return ret; + NTSTATUS ret; + if (get_saved_error_triple(NULL, NULL, &ret)) { + set_saved_error_triple(0, 0, NT_STATUS_OK); + return ret; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); + return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); } @@ -1856,7 +1848,6 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return ERROR_NT(status); @@ -3456,21 +3447,6 @@ NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL b return map_nt_error_from_unix(errno); } - /* The following 2 clauses set explicit DOS error codes. JRA. */ - if (ms_has_wild(directory)) { - DEBUG(5,("mkdir_internal: failing create on filename %s with wildcards\n", directory)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - return NT_STATUS_OBJECT_NAME_INVALID; - } - - if( strchr_m(directory, ':')) { - DEBUG(5,("mkdir_internal: failing create on filename %s with colon in name\n", directory)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - return NT_STATUS_NOT_A_DIRECTORY; - } - if (bad_path) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } @@ -3521,6 +3497,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,&sbuf); + if( strchr_m(directory, ':')) { + DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory)); + END_PROFILE(SMBmkdir); + return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname); + } + status = mkdir_internal(conn, directory,bad_path); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); @@ -3530,7 +3512,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (lp_inherit_owner(SNUM(conn))) { /* Ensure we're checking for a symlink here.... */ /* We don't want to get caught by a symlink racer. */ - + if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) { END_PROFILE(SMBmkdir); return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -4328,7 +4310,6 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBmv); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return ERROR_NT(status); @@ -4592,8 +4573,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRDOS,error); } else { if((errno == ENOENT) && (bad_path1 || bad_path2)) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; + set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK); } END_PROFILE(SMBcopy); return(UNIXERROR(ERRDOS,error)); @@ -5149,7 +5129,9 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); - CHECK_ERROR(fsp); + if (HAS_CACHED_ERROR(fsp)) { + return(CACHED_ERROR(fsp)); + } tcount = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); @@ -5292,8 +5274,12 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz END_PROFILE(SMBwriteBs); return(ERROR_DOS(ERRHRD,ERRdiskfull)); } + wbms->wr_errclass = ERRHRD; + wbms->wr_error = ERRdiskfull; + wbms->wr_status = NT_STATUS_DISK_FULL; + wbms->wr_discard = True; END_PROFILE(SMBwriteBs); - return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); + return -1; } /* Increment the total written, if this matches tcount diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e53b47c1f4..a497e8d81c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -814,7 +814,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i talloc_destroy(ctx); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); -- cgit From 1045c786246658f5d8e289d46cb4bdfc87655c71 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 2 Apr 2005 00:13:27 +0000 Subject: r6174: Fixup T2 open call - we were returning 2 bytes short. Jeremy. (This used to be commit 0c7de7615bf0edbb36a3afee445db13a71e26d2e) --- source3/smbd/open.c | 17 ----------------- source3/smbd/reply.c | 12 +++++++++++- source3/smbd/trans2.c | 31 ++++++++++++++++++++++++------- 3 files changed, 35 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 41ced42034..fbe763ab0a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1098,23 +1098,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } - switch(ofun) { - case FILE_EXISTS_OPEN: - case FILE_EXISTS_TRUNCATE: - case FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST: - case FILE_EXISTS_OPEN | FILE_CREATE_IF_NOT_EXIST: - case FILE_EXISTS_TRUNCATE | FILE_CREATE_IF_NOT_EXIST: - break; /* These are ok. */ - default: - if (GET_OPEN_MODE(share_mode) == DOS_OPEN_EXEC) { - ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; - break; - } - /* Cause caller to force dos errors. */ - set_saved_error_triple(ERRDOS, ERRbadaccess, NT_STATUS_INVALID); - return NULL; - } - DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index aef9755122..22cb599195 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1295,7 +1295,17 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt END_PROFILE(SMBopenX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - + + /* Strange open mode mapping. */ + if (smb_ofun == 0) { + if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) { + smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; + } else { + END_PROFILE(SMBopenX); + return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); + } + } + fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr, oplock_request, &rmode,&smb_action); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a497e8d81c..cbb350ebb7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -732,6 +732,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i files_struct *fsp; TALLOC_CTX *ctx = NULL; struct ea_list *ea_list = NULL; + uint16 flags = 0; NTSTATUS status; /* @@ -742,11 +743,12 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + flags = SVAL(params, 0); open_mode = SVAL(params, 2); open_attr = SVAL(params,6); - oplock_request = (SVAL(params,0) & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; if (oplock_request) { - oplock_request |= (SVAL(params,0) & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; } #if 0 @@ -780,6 +782,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } + /* Strange open mode mapping. */ + if (open_ofun == 0) { + if (GET_OPEN_MODE(open_mode) == DOS_OPEN_EXEC) { + open_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; + } else { + END_PROFILE(SMBopenX); + return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); + } + } + /* Any data in this call is an EA list. */ if (total_data && !lp_ea_support(SNUM(conn))) { return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); @@ -839,21 +851,22 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } /* Realloc the size of parameters and data we will return */ - params = SMB_REALLOC(*pparams, 28); + params = SMB_REALLOC(*pparams, 30); if( params == NULL ) { return ERROR_NT(NT_STATUS_NO_MEMORY); } *pparams = params; - memset((char *)params,'\0',28); + memset((char *)params,'\0',30); SSVAL(params,0,fsp->fnum); SSVAL(params,2,fmode); put_dos_date2(params,4, mtime); SIVAL(params,8, (uint32)size); SSVAL(params,12,rmode); - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { smb_action |= EXTENDED_OPLOCK_GRANTED; + } SSVAL(params,18,smb_action); @@ -861,9 +874,13 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes. */ SIVAL(params,20,inode); - + if (flags & 8) { + uint32 ea_size = estimate_ea_size(conn, fsp, fname); + SIVAL(params, 26, ea_size); + } + /* Send the required number of replies */ - send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0); return -1; } -- cgit From db69f6fae9f726ac6598a600b4e6e5e1a8ba96e9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 4 Apr 2005 20:40:39 +0000 Subject: r6199: Only do the strange DOS error for openX, not trans2open. Jeremy. (This used to be commit 65970dfc5b8f174fe29201789d6ddcf8802ad48c) --- source3/smbd/trans2.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cbb350ebb7..e7f44a6592 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -786,9 +786,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i if (open_ofun == 0) { if (GET_OPEN_MODE(open_mode) == DOS_OPEN_EXEC) { open_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; - } else { - END_PROFILE(SMBopenX); - return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); } } -- cgit From d318fe4025755b68f88fd9f0605732ee8b94c57f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 4 Apr 2005 20:46:16 +0000 Subject: r6200: Returned access should contain share mode as well as open mode. Jeremy. (This used to be commit 3aa784c07723430b429adc9abab9cc7c1325cb35) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fbe763ab0a..5b349e2e44 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1435,7 +1435,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); if (Access) { - (*Access) = open_mode; + (*Access) = (SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode)); } action = 0; -- cgit From 77fa234ffc71a62990d37e3d32c9d6733d60c17f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Apr 2005 01:20:32 +0000 Subject: r6203: Fix attribute return on creating a directory with nttrans_create. Fix strange allocation semantics of openX. Jeremy. (This used to be commit da5a8b539d39d2765de22c3e55e9f284992ff966) --- source3/smbd/nttrans.c | 62 +++++++++++++++++++++++++------------------------- source3/smbd/reply.c | 31 +++++++++++++++---------- source3/smbd/trans2.c | 14 +++++++++--- 3 files changed, 61 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6abea78239..6421a14b28 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -918,8 +918,9 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib file_len = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) + if(fmode == 0) { fmode = FILE_ATTRIBUTE_NORMAL; + } if (!fsp->is_directory && (fmode & aDIR)) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -956,11 +957,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * correct bit for extended oplock reply. */ - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { extended_oplock_granted = True; + } - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { extended_oplock_granted = True; + } #if 0 /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */ @@ -1481,7 +1484,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o oplock_request,&rmode,&smb_action); if (!fsp) { - if(errno == EISDIR) { /* @@ -1511,32 +1513,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } - - file_len = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) - fmode = FILE_ATTRIBUTE_NORMAL; - - if (fmode & aDIR) { - talloc_destroy(ctx); - close_file(fsp,False); - restore_case_semantics(conn, file_attributes); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } - - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ - - if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - extended_oplock_granted = True; - } - - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - extended_oplock_granted = True; - } } /* @@ -1578,7 +1554,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } restore_case_semantics(conn, file_attributes); + talloc_destroy(ctx); + file_len = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + if(fmode == 0) { + fmode = FILE_ATTRIBUTE_NORMAL; + } + if (!fsp->is_directory && (fmode & aDIR)) { + close_file(fsp,False); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + /* Save the requested allocation size. */ if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12); @@ -1589,7 +1576,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,False); - END_PROFILE(SMBntcreateX); /* Can't set allocation size on a directory. */ return ERROR_NT(NT_STATUS_ACCESS_DENIED); } @@ -1602,6 +1588,20 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { + extended_oplock_granted = True; + } + + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + extended_oplock_granted = True; + } + /* Realloc the size of parameters and data we will return */ params = nttrans_realloc(ppparams, 69); if(params == NULL) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 22cb599195..0d1523ae3b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1268,6 +1268,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt BOOL bad_path = False; files_struct *fsp; NTSTATUS status; + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9); + ssize_t retval = -1; + START_PROFILE(SMBopenX); /* If it's an IPC, pass off the pipe handler. */ @@ -1320,18 +1323,22 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt size = sbuf.st_size; - if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { - SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9); - if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_DISK_FULL); - } - } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size); + /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size, + if the file is truncated or created. */ + if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size); + if (retval < 0) { + close_file(fsp,False); + END_PROFILE(SMBwrite); + return ERROR_NT(NT_STATUS_DISK_FULL); } + size = get_allocation_size(conn,fsp,&sbuf); } fmode = dos_mode(conn,fname,&sbuf); @@ -1371,7 +1378,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt put_dos_date3(outbuf,smb_vwv4,mtime & ~1); else put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,(uint32)get_allocation_size(conn,fsp,&sbuf)); + SIVAL(outbuf,smb_vwv6,(uint32)size); SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,smb_action); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e7f44a6592..f8123bc11a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -58,14 +58,18 @@ SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB { SMB_BIG_UINT ret; + if(S_ISDIR(sbuf->st_mode)) { + return 0; + } + #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks; #else ret = (SMB_BIG_UINT)get_file_size(*sbuf); #endif - if (!ret && fsp && fsp->initial_allocation_size) - ret = fsp->initial_allocation_size; + if (fsp && fsp->initial_allocation_size) + ret = MAX(ret,fsp->initial_allocation_size); return smb_roundup(conn, ret); } @@ -2800,7 +2804,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * fullpathname = fname; file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(conn,fsp,&sbuf); if (mode & aDIR) { /* This is necessary, as otherwise the desktop.ini file in * this folder is ignored */ @@ -2858,6 +2861,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + allocation_size = get_allocation_size(conn,fsp,&sbuf); + if (fsp) { if (fsp->pending_modtime) { /* the pending modtime overrides the current modtime */ @@ -2870,6 +2875,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* the pending modtime overrides the current modtime */ sbuf.st_mtime = fsp1->pending_modtime; } + if (fsp1 && fsp1->initial_allocation_size) { + allocation_size = get_allocation_size(conn, fsp1, &sbuf); + } } if (lp_dos_filetime_resolution(SNUM(conn))) { -- cgit From 6ef9d08090f11fd5638ca6fa9c8a06341a91ab9f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Apr 2005 01:24:04 +0000 Subject: r6204: Fix double-free of talloc context. Jeremy. (This used to be commit d5c56d25741e148ccae7c91f9b0157498d7ff148) --- source3/smbd/nttrans.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6421a14b28..d878df6636 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1554,7 +1554,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } restore_case_semantics(conn, file_attributes); - talloc_destroy(ctx); file_len = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); -- cgit From 978ca8486031e43754a3c23757f361bf3a85f335 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 6 Apr 2005 16:28:04 +0000 Subject: r6225: get rid of warnings from my compiler about nested externs (This used to be commit efea76ac71412f8622cd233912309e91b9ea52da) --- source3/smbd/dir.c | 4 ++-- source3/smbd/error.c | 2 +- source3/smbd/fake_file.c | 3 ++- source3/smbd/lanman.c | 6 +++--- source3/smbd/negprot.c | 2 +- source3/smbd/nttrans.c | 4 ++-- source3/smbd/open.c | 4 +--- source3/smbd/oplock.c | 8 +++----- source3/smbd/oplock_linux.c | 32 ++++++++++++++++---------------- source3/smbd/posix_acls.c | 28 ++++++++-------------------- source3/smbd/process.c | 9 +++++---- source3/smbd/reply.c | 4 +--- source3/smbd/server.c | 4 ++-- source3/smbd/service.c | 2 +- source3/smbd/sesssetup.c | 11 ++++++----- source3/smbd/trans2.c | 2 +- 16 files changed, 55 insertions(+), 70 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 27ec003fb8..0f32dddd2d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -24,6 +24,8 @@ This module implements directory related functions for Samba. */ +extern struct current_user current_user; + /* Make directory handle internals available. */ #define NAME_CACHE_SIZE 100 @@ -785,7 +787,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { - extern struct current_user current_user; SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; @@ -838,7 +839,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { - extern struct current_user current_user; SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 6988d74f91..090a2f6d81 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -23,6 +23,7 @@ /* From lib/error.c */ extern struct unix_error_map unix_dos_nt_errmap[]; +extern uint32 global_client_caps; /* these can be set by some functions to override the error codes */ static int override_ERR_class; static int override_ERR_code; @@ -114,7 +115,6 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { int outsize = set_message(outbuf,0,0,True); - extern uint32 global_client_caps; BOOL force_nt_status = False; BOOL force_dos_status = False; diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 53aac1e036..ee510eb003 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -20,6 +20,8 @@ #include "includes.h" +extern struct current_user current_user; + /**************************************************************************** Open a file with a share mode. ****************************************************************************/ @@ -29,7 +31,6 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect int share_mode,int ofun, uint32 new_dos_attr, int oplock_request, int *Access,int *action) { - extern struct current_user current_user; int flags=0; files_struct *fsp = NULL; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d8c5201ce6..f2794d2901 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -27,6 +27,9 @@ #include "includes.h" +extern struct current_user current_user; +extern userdom_struct current_user_info; + #ifdef CHECK_TYPES #undef CHECK_TYPES #endif @@ -2116,7 +2119,6 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param int snum; fstring sharename; int errcode; - extern struct current_user current_user; WERROR werr = WERR_OK; if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) @@ -2183,7 +2185,6 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param int errcode = NERR_notsupported; int snum; WERROR werr = WERR_OK; - extern struct current_user current_user; /* check it's a supported varient */ if (!(strcsequal(str1,"z") && strcsequal(str2,""))) @@ -2435,7 +2436,6 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); char *p2; - extern userdom_struct current_user_info; int level = SVAL(p,0); DEBUG(4,("NetWkstaGetInfo level %d\n",level)); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index bdb15cb3f7..054afac683 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -20,6 +20,7 @@ #include "includes.h" +extern fstring remote_proto; extern enum protocol_types Protocol; extern int max_recv; BOOL global_encrypted_passwords_negotiated = False; @@ -549,7 +550,6 @@ int reply_negprot(connection_struct *conn, SSVAL(outbuf,smb_vwv0,choice); if(choice != -1) { - extern fstring remote_proto; fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(True); outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d878df6636..69b83fe3da 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -21,6 +21,8 @@ #include "includes.h" +extern DOM_SID global_sid_World; +extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; extern int global_oplock_break; @@ -83,7 +85,6 @@ static char *nttrans_realloc(char **ptr, size_t size) static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params, int paramsize, char *pdata, int datasize) { - extern int max_send; int data_to_send = datasize; int params_to_send = paramsize; int useable_space; @@ -2020,7 +2021,6 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) { - extern DOM_SID global_sid_World; size_t sd_size; *ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5b349e2e44..559994ca46 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -21,6 +21,7 @@ #include "includes.h" +extern struct current_user current_user; extern userdom_struct current_user_info; extern uint16 global_oplock_port; extern uint16 global_smbpid; @@ -172,7 +173,6 @@ Error was %s\n", static BOOL open_file(files_struct *fsp,connection_struct *conn, const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { - extern struct current_user current_user; int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -1606,7 +1606,6 @@ int close_file_fchmod(files_struct *fsp) files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, int share_mode, int smb_ofun, int *action) { - extern struct current_user current_user; BOOL got_stat = False; files_struct *fsp = file_new(conn); BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); @@ -1744,7 +1743,6 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) { - extern struct current_user current_user; files_struct *fsp = NULL; if (!VALID_STAT(*psbuf)) diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ea3ac43744..858092407f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -31,6 +31,9 @@ static int32 level_II_oplocks_open = 0; BOOL global_client_failed_oplock_break = False; BOOL global_oplock_break = False; +extern struct timeval smb_last_time; +extern uint32 global_client_caps; +extern struct current_user current_user; extern int smb_read_error; static struct kernel_oplocks *koplocks; @@ -518,8 +521,6 @@ static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) static void wait_before_sending_break(BOOL local_request) { - extern struct timeval smb_last_time; - if(local_request) { struct timeval cur_tv; long wait_left = (long)lp_oplock_break_wait_time(); @@ -603,7 +604,6 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) { - extern uint32 global_client_caps; char outbuf[128]; SMB_DEV_T dev = fsp->dev; SMB_INO_T inode = fsp->inode; @@ -676,8 +676,6 @@ static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) { - extern uint32 global_client_caps; - extern struct current_user current_user; char *inbuf = NULL; char *outbuf = NULL; files_struct *fsp = NULL; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index fe324577e1..5d6bdb9883 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -22,6 +22,22 @@ #if HAVE_KERNEL_OPLOCKS_LINUX +/* these can be removed when they are in glibc headers */ +struct cap_user_header { + uint32 version; + int pid; +} header; +struct cap_user_data { + uint32 effective; + uint32 permitted; + uint32 inheritable; +} data; + +extern int capget(struct cap_user_header * hdrp, + struct cap_user_data * datap); +extern int capset(struct cap_user_header * hdrp, + const struct cap_user_data * datap); + static SIG_ATOMIC_T signals_received; #define FD_PENDING_SIZE 100 static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; @@ -68,22 +84,6 @@ static void set_capability(unsigned capability) #ifndef _LINUX_CAPABILITY_VERSION #define _LINUX_CAPABILITY_VERSION 0x19980330 #endif - /* these can be removed when they are in glibc headers */ - struct cap_user_header { - uint32 version; - int pid; - } header; - struct cap_user_data { - uint32 effective; - uint32 permitted; - uint32 inheritable; - } data; - - extern int capget(struct cap_user_header * hdrp, - struct cap_user_data * datap); - extern int capset(struct cap_user_header * hdrp, - const struct cap_user_data * datap); - header.version = _LINUX_CAPABILITY_VERSION; header.pid = 0; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 87173fca3b..31135f0907 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -21,6 +21,14 @@ #include "includes.h" +extern struct current_user current_user; +extern DOM_SID global_sid_Creator_Owner; +extern DOM_SID global_sid_Creator_Group; +extern DOM_SID global_sid_World; +extern DOM_SID global_sid_Builtin_Administrators; +extern DOM_SID global_sid_Builtin_Users; +extern struct generic_mapping file_generic_mapping; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_ACLS @@ -916,7 +924,6 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (lp_force_unknown_acl_user(snum)) { /* this allows take ownership to work * reasonably */ - extern struct current_user current_user; *puser = current_user.uid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" @@ -938,7 +945,6 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (lp_force_unknown_acl_user(snum)) { /* this allows take group ownership to work * reasonably */ - extern struct current_user current_user; *pgrp = current_user.gid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" @@ -1003,10 +1009,8 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type) static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) { - extern DOM_SID global_sid_World; fstring u_name; fstring g_name; - extern struct current_user current_user; /* "Everyone" always matches every uid. */ @@ -1046,7 +1050,6 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, SMB_STRUCT_STAT *pst, BOOL setting_acl) { - extern DOM_SID global_sid_World; canon_ace *pace; BOOL got_user = False; BOOL got_grp = False; @@ -1220,10 +1223,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, canon_ace **ppfile_ace, canon_ace **ppdir_ace, SEC_ACL *dacl) { - extern DOM_SID global_sid_Creator_Owner; - extern DOM_SID global_sid_Creator_Group; - extern DOM_SID global_sid_World; - extern struct generic_mapping file_generic_mapping; BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; @@ -1647,7 +1646,6 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); static void process_deny_list( canon_ace **pp_ace_list ) { - extern DOM_SID global_sid_World; canon_ace *ace_list = *pp_ace_list; canon_ace *curr_ace = NULL; canon_ace *curr_ace_next = NULL; @@ -2067,7 +2065,6 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, DOM_SID *powner, DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { - extern DOM_SID global_sid_World; connection_struct *conn = fsp->conn; mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); canon_ace *list_head = NULL; @@ -2629,10 +2626,6 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) { - extern DOM_SID global_sid_Builtin_Administrators; - extern DOM_SID global_sid_Builtin_Users; - extern DOM_SID global_sid_Creator_Owner; - extern DOM_SID global_sid_Creator_Group; connection_struct *conn = fsp->conn; SMB_STRUCT_STAT sbuf; SEC_ACE *nt_ace_list = NULL; @@ -2920,7 +2913,6 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; - extern struct current_user current_user; files_struct *fsp; SMB_STRUCT_STAT st; @@ -2976,7 +2968,6 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) uid_t orig_uid; gid_t orig_gid; BOOL need_chown = False; - extern struct current_user current_user; DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -3760,7 +3751,6 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * static int check_posix_acl_group_write(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - extern struct current_user current_user; SMB_ACL_T posix_acl = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; @@ -3922,7 +3912,6 @@ failed to match on user or group in token.\n", fname )); BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) { - extern struct current_user current_user; SMB_STRUCT_STAT sbuf; pstring dname; int ret; @@ -3980,7 +3969,6 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) BOOL can_write_to_file(connection_struct *conn, const char *fname) { - extern struct current_user current_user; SMB_STRUCT_STAT sbuf; int ret; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3043cadfd8..1bf6f4f9d1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -20,6 +20,11 @@ #include "includes.h" +extern uint16 global_smbpid; +extern int keepalive; +extern struct auth_context *negprot_global_auth_context; +extern int smb_echo_count; + struct timeval smb_last_time; static char *InBuffer = NULL; @@ -852,7 +857,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { static pid_t pid= (pid_t)-1; int outsize = 0; - extern uint16 global_smbpid; type &= 0xff; @@ -1331,7 +1335,6 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t static time_t last_idle_closed_check = 0; time_t t; BOOL allidle = True; - extern int keepalive; if (smb_read_error == READ_EOF) { DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); @@ -1375,7 +1378,6 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t } if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - extern struct auth_context *negprot_global_auth_context; if (!send_keepalive(smbd_server_fd())) { DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); return False; @@ -1493,7 +1495,6 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); void smbd_process(void) { - extern int smb_echo_count; time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0d1523ae3b..c3cb81ddfc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -35,6 +35,7 @@ extern int global_oplock_break; unsigned int smb_echo_count = 0; extern uint32 global_client_caps; +extern struct current_user current_user; extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** @@ -471,7 +472,6 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int passlen = SVAL(inbuf,smb_vwv3); pstring path; char *p, *q; - extern BOOL global_encrypted_passwords_negotiated; START_PROFILE(SMBtconX); @@ -2010,7 +2010,6 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize) { - extern struct current_user current_user; ssize_t maxcount,mincount; size_t nread = 0; SMB_OFF_T startpos; @@ -2980,7 +2979,6 @@ int reply_exit(connection_struct *conn, int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - extern struct current_user current_user; int outsize = 0; time_t mtime; int32 eclass = 0, err = 0; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7f7d55c7e3..9d910cd14a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -30,6 +30,8 @@ int last_message = -1; /* a useful macro to debug the last message processed */ #define LAST_MESSAGE() smb_fn_name(last_message) +extern char *last_inbuf; +extern struct auth_context *negprot_global_auth_context; extern pstring user_socket_options; extern SIG_ATOMIC_T got_sig_term; extern SIG_ATOMIC_T reload_after_sighup; @@ -598,8 +600,6 @@ static BOOL dump_core(void) void exit_server(const char *reason) { static int firsttime=1; - extern char *last_inbuf; - extern struct auth_context *negprot_global_auth_context; if (!firsttime) exit(0); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 7bbf8d7f2a..d39d3d3836 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -20,6 +20,7 @@ #include "includes.h" +extern char magic_char; extern struct timeval smb_last_time; extern userdom_struct current_user_info; @@ -30,7 +31,6 @@ extern userdom_struct current_user_info; BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir) { - extern char magic_char; static connection_struct *last_conn; static uint16 last_flags; int snum; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 60867df653..9fbf0b1d51 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -25,6 +25,12 @@ uint32 global_client_caps = 0; +extern BOOL global_encrypted_passwords_negotiated; +extern BOOL global_spnego_negotiated; +extern enum protocol_types Protocol; +extern int max_send; +extern struct auth_context *negprot_global_auth_context; + static struct auth_ntlmssp_state *global_ntlmssp_state; /* @@ -637,13 +643,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, fstring native_lanman; fstring primary_domain; static BOOL done_sesssetup = False; - extern BOOL global_encrypted_passwords_negotiated; - extern BOOL global_spnego_negotiated; - extern enum protocol_types Protocol; - extern int max_send; auth_usersupplied_info *user_info = NULL; - extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f8123bc11a..8d673c25bd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -23,6 +23,7 @@ #include "includes.h" +extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; extern int global_oplock_break; @@ -574,7 +575,6 @@ static int send_trans2_replies(char *outbuf, global struct. These different max_xmit variables should be merged as this is now too confusing */ - extern int max_send; int data_to_send = datasize; int params_to_send = paramsize; int useable_space; -- cgit From d761233aba3e8ed9abb0b7da81de86b3bf15667f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Apr 2005 18:27:28 +0000 Subject: r6234: Fix for possible root squash nfs bugs from psz@maths.usyd.edu.au Jeremy. (This used to be commit dbf021a2e04e74dd7f072c927a34043fd8c3ae30) --- source3/smbd/oplock.c | 6 ++++++ source3/smbd/vfs.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 858092407f..e6af12cd81 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -806,6 +806,12 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, saved_vuid = current_user.vuid; saved_fsp_conn = fsp->conn; change_to_root_user(); + /* + * Initialize saved_dir to something sensible: vfs_GetWd may not work well + * for root: the directory may be NFS-mounted and exported with root_squash + * (so has no root access). + */ + pstrcpy(saved_dir,saved_fsp_conn->connectpath); vfs_GetWd(saved_fsp_conn,saved_dir); /* Save the chain fnum. */ file_chain_save(); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 34671b8efc..28441c91ab 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -731,7 +731,9 @@ char *vfs_GetWd(connection_struct *conn, char *path) in trouble :-) */ if (SMB_VFS_STAT(conn, ".",&st) == -1) { - DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path)); + /* Known to fail for root: the directory may be + * NFS-mounted and exported with root_squash (so has no root access). */ + DEBUG(1,("vfs_GetWd: couldn't stat \".\" path=%s error %s (NFS problem ?)\n", path, strerror(errno) )); return(SMB_VFS_GETWD(conn,path)); } -- cgit From b751f95a256e0309f878ef93e6da9003fbde92d2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 7 Apr 2005 19:43:19 +0000 Subject: r6237: fix my breakage of WinXP sp2 msdfs support. We did need the special case for RESOLVE_DFSPATH in the findfirst() code. Jeremy, please verify I haven't broken the allow_wcard code you added to resolve_dfs_path() (This used to be commit 29983398e2f7f1dc609d4d981e20f594918243bb) --- source3/smbd/msdfs.c | 21 ++++++++++++++++----- source3/smbd/trans2.c | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 2e4649efed..c5e9d8d21c 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -269,7 +269,9 @@ BOOL is_msdfs_link(connection_struct* conn, char * path, Used by other functions to decide if a dfs path is remote, and to get the list of referred locations for that remote path. -allow_wcards: Should we allow wildcards when parsing paths. +findfirst_flag: For findfirsts, dfs links themselves are not +redirected, but paths beyond the links are. For normal smb calls, +even dfs links need to be redirected. self_referralp: clients expect a dfs referral for the same share when they request referrals for dfs roots on a server. @@ -281,7 +283,7 @@ should try the remaining path on the redirected server. static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, connection_struct* conn, - BOOL allow_wcards, + BOOL findfirst_flag, BOOL allow_wcards, struct referral** reflistpp, int* refcntp, BOOL* self_referralp, int* consumedcntp) { @@ -313,6 +315,12 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /* check if need to redirect */ if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + if (findfirst_flag) { + DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " + "for dfs link %s.\n", dfspath)); + return False; + } + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); if (consumedcntp) *consumedcntp = strlen(dfspath); @@ -326,6 +334,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, *p = '\0'; pstrcpy(localpath, reqpath); if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); /* To find the path consumed, we truncate the original @@ -333,6 +342,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, component. The length of the resulting string is the path consumed */ + if (consumedcntp) { char *q; pstring buf; @@ -361,7 +371,8 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, If not, the pathname is converted to a tcon-relative local unix path *****************************************************************/ -BOOL dfs_redirect(pstring pathname, connection_struct* conn, BOOL allow_wcards) +BOOL dfs_redirect( pstring pathname, connection_struct* conn, + BOOL findfirst_flag, BOOL allow_wcards ) { struct dfs_path dp; @@ -380,7 +391,7 @@ BOOL dfs_redirect(pstring pathname, connection_struct* conn, BOOL allow_wcards) if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; - if (resolve_dfs_path(pathname, &dp, conn, allow_wcards, + if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, allow_wcards, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -518,7 +529,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, return False; /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(pathname, &dp, conn, False, + if (!resolve_dfs_path(pathname, &dp, conn, False, False, &jucn->referral_list, &jucn->referral_count, self_referralp, consumedcntp)) { if (!*self_referralp) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8d673c25bd..9bc509ad54 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1626,7 +1626,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf); + RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); if (bad_path) { -- cgit From ecc6933a86dfc61b49ce907cf444cc45d2e3f8d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Apr 2005 20:59:37 +0000 Subject: r6240: Fix for bug #2581. Add size limit (in kb) to stat cache. Jeremy. (This used to be commit 836b73d0018c3137b7a924b6345e69ae5d23431d) --- source3/smbd/statcache.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index cfc5286327..99f209006b 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -47,10 +47,15 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat TDB_DATA data_val; char *original_path; size_t original_path_length; + size_t sc_size = lp_max_stat_cache_size(); if (!lp_stat_cache()) return; + if (sc_size && (sc_size*1024 > tdb_stat_cache->map_size)) { + reset_stat_cache(); + } + ZERO_STRUCT(data_val); /* -- cgit From 1253a174f376f575819d0c84e8ee10ac43d18725 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 7 Apr 2005 22:37:03 +0000 Subject: r6242: after talking to jeremy, we can actually consolidate the 2 BOOL flags in dfs_redirect() down to one since they both are used in essentially the same context (from what we can tell). Tested Win98SE, WinXP sp 1 & 2, Win2k3 sp1, and WIn2k Sp4. All dfs operations still seem to work. (This used to be commit 59ffacf59c98f2f8277d76ec22712e438fd40618) --- source3/smbd/msdfs.c | 18 ++++++++++-------- source3/smbd/trans2.c | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c5e9d8d21c..b61a328080 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -282,8 +282,7 @@ should try the remaining path on the redirected server. *****************************************************************/ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, - connection_struct* conn, - BOOL findfirst_flag, BOOL allow_wcards, + connection_struct* conn, BOOL search_flag, struct referral** reflistpp, int* refcntp, BOOL* self_referralp, int* consumedcntp) { @@ -315,7 +314,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /* check if need to redirect */ if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { - if (findfirst_flag) { + if ( search_flag ) { DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); return False; @@ -369,17 +368,20 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /***************************************************************** Decides if a dfs pathname should be redirected or not. If not, the pathname is converted to a tcon-relative local unix path + + search_wcard_flag: this flag performs 2 functions bother related + to searches. See resolve_dfs_path() and parse_processed_dfs_path() + for details. *****************************************************************/ -BOOL dfs_redirect( pstring pathname, connection_struct* conn, - BOOL findfirst_flag, BOOL allow_wcards ) +BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_flag ) { struct dfs_path dp; if (!conn || !pathname) return False; - parse_processed_dfs_path(pathname, &dp, allow_wcards); + parse_processed_dfs_path(pathname, &dp, search_wcard_flag); /* if dfs pathname for a non-dfs share, convert to tcon-relative path and return false */ @@ -391,7 +393,7 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; - if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, allow_wcards, + if (resolve_dfs_path(pathname, &dp, conn, search_wcard_flag, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -529,7 +531,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, return False; /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(pathname, &dp, conn, False, False, + if (!resolve_dfs_path(pathname, &dp, conn, False, &jucn->referral_list, &jucn->referral_count, self_referralp, consumedcntp)) { if (!*self_referralp) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9bc509ad54..8d673c25bd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1626,7 +1626,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); if (bad_path) { -- cgit From 43710a45e8308afac43d8ad1bf6f1aab05a77bb9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Apr 2005 17:04:59 +0000 Subject: r6249: Get the comparison the right way around... Jeremy. (This used to be commit 1d542eee571b80259568d49bd5dc2eb14fd80d01) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 99f209006b..8e22d9687b 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -52,7 +52,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (!lp_stat_cache()) return; - if (sc_size && (sc_size*1024 > tdb_stat_cache->map_size)) { + if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) { reset_stat_cache(); } -- cgit From f0fea42a755eb9f30a2a0ac6cd68c523f7cb469f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Apr 2005 19:21:41 +0000 Subject: r6252: Re-order position of become_root() to allow directory to be read first. Jeremy. (This used to be commit 9fa32282ebe78c3ecd433e8ece600881774560b7) --- source3/smbd/oplock.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e6af12cd81..9b8df98fd5 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -805,7 +805,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, saved_user_conn = current_user.conn; saved_vuid = current_user.vuid; saved_fsp_conn = fsp->conn; - change_to_root_user(); /* * Initialize saved_dir to something sensible: vfs_GetWd may not work well * for root: the directory may be NFS-mounted and exported with root_squash @@ -816,6 +815,10 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Save the chain fnum. */ file_chain_save(); + pstrcpy(file_name, fsp->fsp_name); + + change_to_root_user(); + /* * From Charles Hoch . If the break processing * code closes the file (as it often does), then the fsp pointer here @@ -823,8 +826,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * around the loop. */ - pstrcpy(file_name, fsp->fsp_name); - while((fsp = initial_break_processing(dev, inode, file_id)) && OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) { -- cgit From def41233b4ee342313cdcc9417dc5c04d053a18b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 9 Apr 2005 00:41:38 +0000 Subject: r6258: Fix found by OS/2 set_ea call. When setting specific info remember to terminate once we've done that and not "break" into the generic file metadata set code. Jeremy. (This used to be commit f1e12be9ed0ca0077bac8e5f32051758e1d84ad7) --- source3/smbd/trans2.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8d673c25bd..1095e4ce75 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3739,7 +3739,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - break; + + /* We're done. We only get EA info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); } #if 0 @@ -3929,7 +3933,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(status); } - break; + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); } case SMB_FILE_POSITION_INFORMATION: @@ -3949,9 +3955,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", fname, (double)position_information )); - if (fsp) + if (fsp) { fsp->position_information = position_information; - break; + } + + /* We're done. We only get position info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); } /* From tridge Samba4 : @@ -3971,7 +3982,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (mode != 0 && mode != 2 && mode != 4 && mode != 6) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - break; + + /* We're done. We only get mode info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); } /* -- cgit From 9fda3ecda4b88fa5fbe9ba23a1acc149b9a9a73f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 9 Apr 2005 00:50:12 +0000 Subject: r6261: Tidyup message str printf. Ensure tvs struct is zeroed. Jeremy. (This used to be commit 6c9f227ef400f32def85268f411691b569d29889) --- source3/smbd/trans2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1095e4ce75..1868ce8fe4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3581,6 +3581,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(NT_STATUS_INVALID_PARAMETER); ZERO_STRUCT(sbuf); + ZERO_STRUCT(tvs); if (tran_call == TRANSACT2_SETFILEINFO) { if (total_params < 4) { -- cgit From 83e11ba86c2401ece3c845fd10c22b84e6be7811 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 9 Apr 2005 11:46:40 +0000 Subject: r6263: Get rid of generate_wellknown_sids, they are const static and initializable statically. Volker (This used to be commit 3493d9f383567d286e69c0e60c0708ed400a04d9) --- source3/smbd/nttrans.c | 1 - source3/smbd/posix_acls.c | 11 +++-------- 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 69b83fe3da..4dffe870c5 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -21,7 +21,6 @@ #include "includes.h" -extern DOM_SID global_sid_World; extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 31135f0907..e0d98f4b89 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -22,11 +22,6 @@ #include "includes.h" extern struct current_user current_user; -extern DOM_SID global_sid_Creator_Owner; -extern DOM_SID global_sid_Creator_Group; -extern DOM_SID global_sid_World; -extern DOM_SID global_sid_Builtin_Administrators; -extern DOM_SID global_sid_Builtin_Users; extern struct generic_mapping file_generic_mapping; #undef DBGC_CLASS @@ -1045,8 +1040,8 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, files_struct *fsp, - DOM_SID *pfile_owner_sid, - DOM_SID *pfile_grp_sid, + const DOM_SID *pfile_owner_sid, + const DOM_SID *pfile_grp_sid, SMB_STRUCT_STAT *pst, BOOL setting_acl) { @@ -2063,7 +2058,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) ****************************************************************************/ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) + const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { connection_struct *conn = fsp->conn; mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); -- cgit From 000323887350793440c360eba2be7729a7b5c4b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 10 Apr 2005 06:57:55 +0000 Subject: r6269: With help from Marcel Müller in tracking down the bug, fix trans2 and nttrans secondary packet processing. We were being too strict checking the incoming packet (by 1 byte). Jeremy. (This used to be commit 3eea1ff4b7428325c7f304bcac61d6297209a4b8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/nttrans.c | 7 +++++-- source3/smbd/trans2.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4dffe870c5..a3ffaad24a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2946,6 +2946,9 @@ due to being in oplock break state.\n", (unsigned int)function_code )); ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + /* We need to re-calcuate the new length after we've read the secondary packet. */ + length = smb_len(inbuf) + 4; + /* * The sequence number for the trans reply is always * based on the last secondary received. @@ -2993,7 +2996,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); goto bad_param; if (parameter_displacement > total_parameter_count) goto bad_param; - if ((smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) || + if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) || (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) goto bad_param; if (parameter_displacement + params < params) @@ -3010,7 +3013,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); goto bad_param; if (data_displacement > total_data_count) goto bad_param; - if ((smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) || + if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) goto bad_param; if (data_displacement + data < data) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1868ce8fe4..adc6322ac3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4885,6 +4885,9 @@ int reply_trans2(connection_struct *conn, unsigned int data_off; ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + + /* We need to re-calcuate the new length after we've read the secondary packet. */ + length = smb_len(inbuf) + 4; /* * The sequence number for the trans reply is always @@ -4932,7 +4935,7 @@ int reply_trans2(connection_struct *conn, goto bad_param; if (param_disp > total_params) goto bad_param; - if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) || + if ((smb_base(inbuf) + param_off + num_params > inbuf + length) || (smb_base(inbuf) + param_off + num_params < smb_base(inbuf))) goto bad_param; if (params + param_disp < params) @@ -4948,7 +4951,7 @@ int reply_trans2(connection_struct *conn, goto bad_param; if (data_disp > total_data) goto bad_param; - if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) || + if ((smb_base(inbuf) + data_off + num_data > inbuf + length) || (smb_base(inbuf) + data_off + num_data < smb_base(inbuf))) goto bad_param; if (data + data_disp < data) -- cgit From 0f7e9f6c56506cb390491dc7db9153aa41565981 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 10 Apr 2005 15:45:46 +0000 Subject: r6279: Convert the RAP enum functions to the pdb_search API. Who is using this nowadays? This looks rather broken, but survives basic tests with 'net'. Volker (This used to be commit 7ae1b94e3eda574729272238cd08e83a33278a7e) --- source3/smbd/lanman.c | 101 ++++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 45 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f2794d2901..127480f0b3 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1655,9 +1655,10 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - BOOL ret; - GROUP_MAP *group_list; + struct pdb_search *search; + struct samr_displayentry *entries; + int num_entries; if (strcmp(str1,"WrLeh") != 0) @@ -1675,30 +1676,39 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c /* get list of domain groups SID_DOMAIN_GRP=2 */ become_root(); - ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False); + search = pdb_search_groups(); unbecome_root(); - - if( !ret ) { - DEBUG(3,("api_RNetGroupEnum:failed to get group list")); + + if (search == NULL) { + DEBUG(3,("api_RNetGroupEnum:failed to get group list")); return False; } resume_context = SVAL(p,0); cli_buf_size=SVAL(p+2,0); - DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); + DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: " + "%d\n", resume_context, cli_buf_size)); + + become_root(); + num_entries = pdb_search_entries(search, resume_context, 0xffffffff, + &entries); + unbecome_root(); *rdata_len = cli_buf_size; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); p = *rdata; - for(i=resume_context; i=resume_context) { - if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) { - pstrcpy(p,name); - DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p)); - p += 21; - count_sent++; - } else { - /* set overflow error */ - DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name)); - errflags=234; - break; - } - } - } - } ; - pdb_endsampwent(); + become_root(); + num_users = pdb_search_entries(search, resume_context, 0xffffffff, + &users); unbecome_root(); - pdb_free_sam(&pwd); + errflags=NERR_Success; + + for (i=0; i Date: Mon, 11 Apr 2005 20:52:02 +0000 Subject: r6297: Fix bug in our trans2 secondary processing. We need to pass in the trans2 call info from the primary trans2 packet as it isn't present in secondary transs packets. We only need to do this for functions that satisfy more than one case in the switch statement. Found by Marcel Müller . Jeremy. (This used to be commit 62edc3d5dc68fbfe6cd77c588791453e29274dd9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/trans2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index adc6322ac3..4fda95d6c0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2660,12 +2660,12 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ ****************************************************************************/ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + unsigned int tran_call, char **pparams, int total_params, char **ppdata, int total_data, unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; - uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; int mode=0; SMB_OFF_T file_size=0; @@ -3557,12 +3557,12 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam ****************************************************************************/ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + unsigned int tran_call, char **pparams, int total_params, char **ppdata, int total_data, unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; - uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; int dosmode=0; SMB_OFF_T size=0; @@ -5007,14 +5007,14 @@ int reply_trans2(connection_struct *conn, case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: START_PROFILE_NESTED(Trans2_qpathinfo); - outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, + outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call, ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_qpathinfo); break; case TRANSACT2_SETPATHINFO: case TRANSACT2_SETFILEINFO: START_PROFILE_NESTED(Trans2_setpathinfo); - outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, + outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call, ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_setpathinfo); break; -- cgit From c044df57dd78c4c17995913739fb8db6b42928a6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Apr 2005 00:00:19 +0000 Subject: r6302: OS/2 fix from Marcel Müller . Don't check for mangled names if mangled names is off. Jeremy. (This used to be commit b2330c38881baceaafe1ef6b7ce00d1b5cd8d5c7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/trans2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4fda95d6c0..dd72db2fae 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1019,6 +1019,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL was_8_3; int nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); + BOOL check_mangled_names = lp_manglednames(SNUM(conn)); *fname = 0; *out_of_space = False; @@ -1063,7 +1064,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive))) got_match = mask_match(fname, mask, conn->case_sensitive); - if(!got_match && !mangle_is_8_3(fname, False)) { + if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False)) { /* * It turns out that NT matches wildcards against -- cgit From 05cc4785a442967b8b4b576b4a684083d6b236c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Apr 2005 01:20:23 +0000 Subject: r6307: Ensure info requested bitmask is printed in log when querying security descriptors. Jeremy. (This used to be commit 4db288e3143c1ce691ae586a7353da00fec85879) --- source3/smbd/nttrans.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a3ffaad24a..d747e84a3a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2058,7 +2058,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i security_info_wanted = IVAL(params,4); - DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); + DEBUG(3,("call_nt_transact_query_security_desc: file = %s, info_wanted = 0x%x\n", fsp->fsp_name, + (unsigned int)security_info_wanted )); params = nttrans_realloc(ppparams, 4); if(params == NULL) -- cgit From 1a2c1f7d1edcf3b0b31d8e056f3b59cd006d3c11 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Apr 2005 17:30:14 +0000 Subject: r6316: Remove over-cautious asserts. Damn wish I'd made the release with this.... Jeremy. (This used to be commit 11c464268df2a0a5155e93d4a7d053d2920fcff0) --- source3/smbd/posix_acls.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index e0d98f4b89..738f9d76f3 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3874,11 +3874,15 @@ match on group %u -> can write.\n", fname, (unsigned int)*pgid )); } } - /* If we get here we know ret == 0. */ - SMB_ASSERT(ret == 0); + /* If ret is -1 here we didn't match on the user entry or + supplemental group entries. */ + + DEBUG(10,("check_posix_acl_group_write: ret = %d before check_stat:\n", ret)); check_stat: + /* Do we match on the owning group entry ? */ + for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == psbuf->st_gid) { ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; @@ -3889,14 +3893,15 @@ match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "c } if (i == current_user.ngroups) { - SMB_ASSERT(ret != 1); DEBUG(10,("check_posix_acl_group_write: file %s \ -failed to match on user or group in token.\n", fname )); +failed to match on user or group in token (ret = %d).\n", fname, ret )); } done: SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + + DEBUG(10,("check_posix_acl_group_write: file %s returning (ret = %d).\n", fname, ret )); return ret; } -- cgit From da70ef7c06ef55b9049697f13fdaecf8a2f31e35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Apr 2005 21:01:01 +0000 Subject: r6344: Fix bug #2601 - it seems that DOS_OPEN_EXEC does mean readonly. Needed for Win9x and OS/2 clients. More Samba4 tests against W2k3 will be needed to confirm this but in the meantime get it up and running. Jeremy. (This used to be commit 77c0ade9fa1e6a31739823be0faa50799bac2775) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 559994ca46..a3bc4a922d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1159,6 +1159,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ append does not mean the same thing under dos and unix */ switch (GET_OPEN_MODE(share_mode)) { + case DOS_OPEN_EXEC: case DOS_OPEN_RDONLY: flags = O_RDONLY; if (desired_access == 0) @@ -1176,7 +1177,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; case DOS_OPEN_RDWR: - case DOS_OPEN_EXEC: flags = O_RDWR; if (desired_access == 0) desired_access = FILE_READ_DATA|FILE_WRITE_DATA; -- cgit From f60ad8ded6e614f3c0abb2679d3a75096fc595d3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Apr 2005 23:32:56 +0000 Subject: r6346: Add a counter for the number of SMB operations per connection/file. You will need to do a make clean after SVN updating this. Next will come a smbcontrol message to dump this info. This should be interesting to profile client activity. Jeremy. (This used to be commit 743174da86ac724fc9ee3d4b7bd9a2a97a234bd8) --- source3/smbd/process.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1bf6f4f9d1..e79686b43e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -962,8 +962,12 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(ERROR_DOS(ERRSRV,ERRaccess)); /* load service specific parameters */ - if (conn && !set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) - return(ERROR_DOS(ERRSRV,ERRaccess)); + if (conn) { + if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) { + return(ERROR_DOS(ERRSRV,ERRaccess)); + } + conn->num_smb_operations++; + } /* does this protocol need to be run as guest? */ if ((flags & AS_GUEST) && (!change_to_guest() || -- cgit From b39c949ae05ee990bd8daa588e92c768185761b5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 17 Apr 2005 07:57:45 +0000 Subject: r6365: Wow, how much worse does this get. From info provided by Eric Stewart I realised we weren't checking against the current effective groupid (set by force group) as well as the group list. Fix this. Jeremy. (This used to be commit 0c4058c0732b1faa87ca64b8f95ad2fe3106a69f) --- source3/smbd/posix_acls.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 738f9d76f3..353f9a3b03 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3852,6 +3852,23 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can if (pgid == NULL) { goto check_stat; } + + /* Does it match the current effective group ? */ + if (current_user.gid == *pgid) { + ret = have_write; + DEBUG(10,("check_posix_acl_group_write: file %s \ +match on group %u -> can write.\n", fname, (unsigned int)*pgid )); + + /* If we don't have write permission this entry doesn't + * prevent the subsequent enumeration of the supplementary + * groups. + */ + if (have_write) { + goto done; + } + } + + /* Continue with the supplementary groups. */ for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == *pgid) { ret = have_write; @@ -3883,6 +3900,15 @@ match on group %u -> can write.\n", fname, (unsigned int)*pgid )); /* Do we match on the owning group entry ? */ + /* First, does it match the current effective group ? */ + if (current_user.gid == psbuf->st_gid) { + ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; + DEBUG(10,("check_posix_acl_group_write: file %s \ +match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write")); + goto done; + } + + /* If not look at the supplementary groups. */ for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == psbuf->st_gid) { ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; -- cgit From 7f247f7b4de67b3e0a857b146a186e5eabc79235 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Apr 2005 22:53:51 +0000 Subject: r6378: Other systems may not return 1 for checking WRITE permission. Canaonicalise any +ve return to 1. Jeremy. (This used to be commit e594222d0ba7713088420f6c6603a74c1d5def8e) --- source3/smbd/posix_acls.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 353f9a3b03..04429d0456 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3742,6 +3742,7 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * /**************************************************************************** Check for POSIX group ACLs. If none use stat entry. + Return -1 if no match, 0 if match and denied, 1 if match and allowed. ****************************************************************************/ static int check_posix_acl_group_write(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) @@ -3782,6 +3783,12 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam goto check_stat; } + /* + * Solaris returns 2 for this if write is available. + * canonicalize to 0 or 1. + */ + have_write = (have_write ? 1 : 0); + switch(tagtype) { case SMB_ACL_MASK: if (!have_write) { @@ -3845,6 +3852,12 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can goto check_stat; } + /* + * Solaris returns 2 for this if write is available. + * canonicalize to 0 or 1. + */ + have_write = (have_write ? 1 : 0); + switch(tagtype) { case SMB_ACL_GROUP: { -- cgit From fecdaec41c70916dc8e591c6e98e830c0f5cb0b1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Apr 2005 07:12:44 +0000 Subject: r6385: Convert checking of egid and secondary egid list into iterator functions so it can be used easily in a for loop. Drops duplicated code from posix_acls.c Jeremy. (This used to be commit 81f30bf5985f5c6dc8399c4695dfa6f14140fde1) --- source3/smbd/posix_acls.c | 49 ++++++++++++++++------------------------------- source3/smbd/uid.c | 23 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 04429d0456..0abdfdccd9 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3753,6 +3753,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam int i; BOOL seen_mask = False; int ret = -1; + gid_t cu_gid; if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS)) == NULL) { goto check_stat; @@ -3866,27 +3867,16 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can goto check_stat; } - /* Does it match the current effective group ? */ - if (current_user.gid == *pgid) { - ret = have_write; - DEBUG(10,("check_posix_acl_group_write: file %s \ -match on group %u -> can write.\n", fname, (unsigned int)*pgid )); - - /* If we don't have write permission this entry doesn't - * prevent the subsequent enumeration of the supplementary - * groups. - */ - if (have_write) { - goto done; - } - } - - /* Continue with the supplementary groups. */ - for (i = 0; i < current_user.ngroups; i++) { - if (current_user.groups[i] == *pgid) { + /* + * Does it match the current effective group + * or supplementary groups ? + */ + for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; + cu_gid = get_current_user_gid_next(&i)) { + if (cu_gid == *pgid) { ret = have_write; DEBUG(10,("check_posix_acl_group_write: file %s \ -match on group %u -> can write.\n", fname, (unsigned int)*pgid )); +match on group %u -> can write.\n", fname, (unsigned int)cu_gid )); /* If we don't have write permission this entry doesn't terminate the enumeration of the entries. */ @@ -3912,18 +3902,13 @@ match on group %u -> can write.\n", fname, (unsigned int)*pgid )); check_stat: /* Do we match on the owning group entry ? */ - - /* First, does it match the current effective group ? */ - if (current_user.gid == psbuf->st_gid) { - ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; - DEBUG(10,("check_posix_acl_group_write: file %s \ -match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write")); - goto done; - } - - /* If not look at the supplementary groups. */ - for (i = 0; i < current_user.ngroups; i++) { - if (current_user.groups[i] == psbuf->st_gid) { + /* + * Does it match the current effective group + * or supplementary groups ? + */ + for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; + cu_gid = get_current_user_gid_next(&i)) { + if (cu_gid == psbuf->st_gid) { ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; DEBUG(10,("check_posix_acl_group_write: file %s \ match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write")); @@ -3931,7 +3916,7 @@ match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "c } } - if (i == current_user.ngroups) { + if (cu_gid == (gid_t)-1) { DEBUG(10,("check_posix_acl_group_write: file %s \ failed to match on user or group in token (ret = %d).\n", fname, ret )); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 77dc19b87b..d1ecaf6625 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -23,6 +23,29 @@ /* what user is current? */ extern struct current_user current_user; +/**************************************************************************** + Iterator functions for getting all gid's from current_user. +****************************************************************************/ + +gid_t get_current_user_gid_first(int *piterator) +{ + *piterator = 0; + return current_user.gid; +} + +gid_t get_current_user_gid_next(int *piterator) +{ + gid_t ret; + + if (!current_user.groups || *piterator >= current_user.ngroups) { + return (gid_t)-1; + } + + ret = current_user.groups[*piterator]; + (*piterator) += 1; + return ret; +} + /**************************************************************************** Become the guest user without changing the security context stack. ****************************************************************************/ -- cgit From e09150948bf4406b5af13241b267a9d3a6fd1d0c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 21 Apr 2005 01:46:18 +0000 Subject: r6408: Fix compile error lurking where PATH_MAX is not defined. Bugzilla #2560. (This used to be commit 5921fcadd5bdf8e600132db6d5cc6393f3d26f58) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 28441c91ab..dee29f4796 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -894,7 +894,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) #ifdef PATH_MAX safe_strcpy(resolved_name_buf, tmp_fname, PATH_MAX); #else - pstrcpy(pstring resolved_name_buf, tmp_fname); + pstrcpy(resolved_name_buf, tmp_fname); #endif resolved_name = resolved_name_buf; #endif -- cgit From d0a0930485508da9d3bd2ee2e37c3cc15896940e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Apr 2005 07:57:52 +0000 Subject: r6417: Strange old IRIX systems return -1 for telldir() when end of directory reached. Don't check for that and bail when reading directory entries as it's a valid value. Excellent work from Cale Fairchild tracked this down. Jeremy. (This used to be commit a60fe9aba16eac4f195a2359d8b7672d8c8aa240) --- source3/smbd/dir.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 0f32dddd2d..054588b25e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1038,11 +1038,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) while ((n = vfs_readdirname(conn, dirp->dir))) { struct name_cache_entry *e; dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); - if (dirp->offset == -1) { - return NULL; - } dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; - e = &dirp->name_cache[dirp->name_cache_index]; SAFE_FREE(e->name); e->name = SMB_STRDUP(n); -- cgit From e0c105ece672502aae19f0e17fde3021207dd47a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Apr 2005 23:15:48 +0000 Subject: r6473: Fix for bug #2644 - test for special files to be ignored was reversed. Jeremy. (This used to be commit 7c173dec2efcbe3fe42ffb9a2e85f3fbc8710ec4) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 054588b25e..5ebbfe478f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -946,7 +946,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * return False; } /* Honour _hide_special_ option */ - if (hide_special && !file_is_special(conn, entry, pst)) { + if (hide_special && file_is_special(conn, entry, pst)) { SAFE_FREE(entry); return False; } -- cgit From 595183b9163ab7075e04ef210ca9c75aae041841 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Apr 2005 23:52:21 +0000 Subject: r6497: Ensure yield_connection() is called on all appropriate error conditions. Jeremy. (This used to be commit f895f087adbc367a984bfa073f31f890db25a286) --- source3/smbd/service.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d39d3d3836..d4d6274dff 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -521,7 +521,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Initialise VFS function pointers */ if (!smbd_vfs_init(conn)) { - DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); + DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; @@ -544,8 +544,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* ROOT Activities: */ /* check number of connections */ if (!claim_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn)), + lp_servicename(snum), + lp_max_connections(snum), False,0)) { DEBUG(1,("too many connections - rejected\n")); conn_free(conn); @@ -555,16 +555,16 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "root preexec = " line */ - if (*lp_rootpreexec(SNUM(conn))) { + if (*lp_rootpreexec(snum)) { int ret; pstring cmd; - pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); + pstrcpy(cmd,lp_rootpreexec(snum)); standard_sub_conn(conn,cmd,sizeof(cmd)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); - if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { + if (ret != 0 && lp_rootpreexec_close(snum)) { DEBUG(1,("root preexec gave %d - failing connection\n", ret)); - yield_connection(conn, lp_servicename(SNUM(conn))); + yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; @@ -575,6 +575,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (!change_to_user(conn, conn->vuid)) { /* No point continuing if they fail the basic checks */ DEBUG(0,("Can't become connected user!\n")); + yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_LOGON_FAILURE; return NULL; @@ -584,16 +585,16 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "preexec = " line */ - if (*lp_preexec(SNUM(conn))) { + if (*lp_preexec(snum)) { int ret; pstring cmd; - pstrcpy(cmd,lp_preexec(SNUM(conn))); + pstrcpy(cmd,lp_preexec(snum)); standard_sub_conn(conn,cmd,sizeof(cmd)); ret = smbrun(cmd,NULL); - if (ret != 0 && lp_preexec_close(SNUM(conn))) { + if (ret != 0 && lp_preexec_close(snum)) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); change_to_root_user(); - yield_connection(conn, lp_servicename(SNUM(conn))); + yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; @@ -601,7 +602,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #ifdef WITH_FAKE_KASERVER - if (lp_afs_share(SNUM(conn))) { + if (lp_afs_share(snum)) { afs_login(conn); } #endif @@ -612,9 +613,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, I have disabled this chdir check (tridge) */ /* the alternative is just to check the directory exists */ if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); + DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum))); change_to_root_user(); - yield_connection(conn, lp_servicename(SNUM(conn))); + yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; @@ -642,7 +643,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); - dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); + dbgtext( "connect to service %s ", lp_servicename(snum) ); dbgtext( "initially as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)sys_getpid() ); @@ -650,9 +651,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Add veto/hide lists */ if (!IS_IPC(conn) && !IS_PRINT(conn)) { - set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn))); - set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn))); - set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn))); + set_namearray( &conn->veto_list, lp_veto_files(snum)); + set_namearray( &conn->hide_list, lp_hide_files(snum)); + set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); } /* Invoke VFS make connection hook */ @@ -660,6 +661,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); change_to_root_user(); + yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_UNSUCCESSFUL; return NULL; @@ -812,8 +814,9 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } /**************************************************************************** -close a cnum + Close a cnum. ****************************************************************************/ + void close_cnum(connection_struct *conn, uint16 vuid) { if (IS_IPC(conn)) { -- cgit From ed1f7121a39d863066ef47e985b77fe3dbedbc9b Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 27 Apr 2005 18:32:37 +0000 Subject: r6502: add LOCKING debug class - pull PRINTINGDB class definition from trunk so our numbers don't get out of sync (This used to be commit 58e307664e02ebf0415f19ed625d2f166d9cb1cc) --- source3/smbd/reply.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c3cb81ddfc..aa33e59b7e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2129,6 +2129,9 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s return -1; } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING + /**************************************************************************** Reply to a lockread (core+ protocol). ****************************************************************************/ @@ -2222,6 +2225,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return(outsize); } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ALL + /**************************************************************************** Reply to a read. ****************************************************************************/ @@ -2610,6 +2616,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, return(outsize); } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING + /**************************************************************************** Reply to a writeunlock (core+). ****************************************************************************/ @@ -2674,6 +2683,9 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, return outsize; } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ALL + /**************************************************************************** Reply to a write. ****************************************************************************/ @@ -3121,6 +3133,9 @@ int reply_writeclose(connection_struct *conn, return(outsize); } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING + /**************************************************************************** Reply to a lock. ****************************************************************************/ @@ -3201,6 +3216,9 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, return(outsize); } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ALL + /**************************************************************************** Reply to a tdis. ****************************************************************************/ @@ -4652,6 +4670,9 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(outsize); } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING + /**************************************************************************** Get a lock pid, dealing with large count requests. ****************************************************************************/ @@ -4989,6 +5010,9 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return chain_reply(inbuf,outbuf,length,bufsize); } +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ALL + /**************************************************************************** Reply to a SMBreadbmpx (read block multiplex) request. ****************************************************************************/ -- cgit From c6a35c356dc41334bb412934a1b15d37ce3bba4c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 30 Apr 2005 12:28:25 +0000 Subject: r6533: Fix for bad comment from Andreas Gruenbacher . Jeremy. (This used to be commit 60325ab1281ebbe70665b5f763065ca60ee9f682) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0abdfdccd9..1e68900bd3 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2005,8 +2005,8 @@ static BOOL unpack_canon_ace(files_struct *fsp, then a simple POSIX permission of rw-r--r-- should really map to 5 entries, Entry 0: owner : deny all except read and write. - Entry 1: group : deny all except read. - Entry 2: owner : allow read and write. + Entry 1: owner : allow read and write. + Entry 2: group : deny all except read. Entry 3: group : allow read. Entry 4: Everyone : allow read. -- cgit From 431a28a3151f6cb8f9e1de769da11a22c379d9d8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 1 May 2005 09:30:18 +0000 Subject: r6548: Fix bug #2622 - remove DPTR_MASK as it makes no sense. Jeremy. (This used to be commit 927681c8c4458c77de2622557f1465fd5ca1c28b) --- source3/smbd/dir.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5ebbfe478f..3c93c188ff 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -624,11 +624,11 @@ BOOL dptr_fill(char *buf1,unsigned int key) DEBUG(1,("filling null dirptr %d\n",key)); return(False); } - offset = TellDir(dptr->dir_hnd); + offset = (uint32)TellDir(dptr->dir_hnd); DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, (long)dptr->dir_hnd,(int)offset)); buf[0] = key; - SIVAL(buf,1,offset | DPTR_MASK); + SIVAL(buf,1,offset); return(True); } @@ -641,16 +641,22 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) unsigned int key = *(unsigned char *)buf; struct dptr_struct *dptr = dptr_get(key, False); uint32 offset; + long seekoff; if (!dptr) { DEBUG(3,("fetched null dirptr %d\n",key)); return(NULL); } *num = key; - offset = IVAL(buf,1)&~DPTR_MASK; - SeekDir(dptr->dir_hnd,(long)offset); + offset = IVAL(buf,1); + if (offset == (uint32)-1) { + seekoff = -1; + } else { + seekoff = (long)offset; + } + SeekDir(dptr->dir_hnd,seekoff); DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", - key,dptr_path(key),offset)); + key,dptr_path(key),(int)seekoff)); return(dptr); } -- cgit From 0483dd60ded1239d8a3ab46598e164416f7668b8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 1 May 2005 10:00:14 +0000 Subject: r6550: Move function make_dir_struct from util to dir.c Jeremy. (This used to be commit 5b86e3dcdf31dec61449d2faede61d24c3a8d79f) --- source3/smbd/dir.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 3c93c188ff..95a5903c14 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -63,6 +63,40 @@ static int dirhandles_open = 0; #define INVALID_DPTR_KEY (-3) +/**************************************************************************** + Make a dir struct. +****************************************************************************/ + +void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,int mode,time_t date, BOOL uc) +{ + char *p; + pstring mask2; + + pstrcpy(mask2,mask); + + if ((mode & aDIR) != 0) + size = 0; + + memset(buf+1,' ',11); + if ((p = strchr_m(mask2,'.')) != NULL) { + *p = 0; + push_ascii(buf+1,mask2,8, 0); + push_ascii(buf+9,p+1,3, 0); + *p = '.'; + } else + push_ascii(buf+1,mask2,11, 0); + + memset(buf+21,'\0',DIR_STRUCT_SIZE-21); + SCVAL(buf,21,mode); + put_dos_date(buf,22,date); + SSVAL(buf,26,size & 0xFFFF); + SSVAL(buf,28,(size >> 16)&0xFFFF); + /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf. + Strange, but verified on W2K3. Needed for OS/2. JRA. */ + push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0); + DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname)); +} + /**************************************************************************** Initialise the dir bitmap. ****************************************************************************/ -- cgit From 1c4bbe06549d86614318718a45b9bc48e3bfc81f Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Mon, 2 May 2005 17:49:43 +0000 Subject: r6586: get rid of a few more compiler warnings (This used to be commit 173375f8d88bf8e8db8d60e5d5f0e5dcc28767d9) --- source3/smbd/notify_kernel.c | 2 ++ source3/smbd/oplock_linux.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index c368fd79a1..5c9d885eed 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -243,5 +243,7 @@ struct cnotify_fns *kernel_notify_init(void) } #else + void notify_kernel_dummy(void); + void notify_kernel_dummy(void) {} #endif /* HAVE_KERNEL_CHANGE_NOTIFY */ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 5d6bdb9883..6d1bc64ce1 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -311,5 +311,7 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) return &koplocks; } #else + void oplock_linux_dummy(void); + void oplock_linux_dummy(void) {} #endif /* HAVE_KERNEL_OPLOCKS_LINUX */ -- cgit From 7b9d6ac23e1a7d8136fffd2e3977b09a815da65a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 May 2005 07:33:49 +0000 Subject: r6595: This is Volkers new-talloc patch. Just got the go-ahead from Volker to commit. Woo Hoo ! Jeremy. (This used to be commit 316df944a456f150944761dab34add5e8c4ab699) --- source3/smbd/server.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9d910cd14a..301534d750 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -747,6 +747,10 @@ void build_options(BOOL screen); log_stdout = True; } + if (interactive && (DEBUGLEVEL >= 9)) { + talloc_enable_leak_report(); + } + if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); @@ -952,14 +956,6 @@ void build_options(BOOL screen); namecache_shutdown(); - if (interactive) { - TALLOC_CTX *mem_ctx = talloc_init("end_description"); - char *description = talloc_describe_all(mem_ctx); - - DEBUG(3, ("tallocs left:\n%s\n", description)); - talloc_destroy(mem_ctx); - } - exit_server("normal exit"); return(0); } -- cgit From 02e3717ee9e045d197d845489e84ac40083ca868 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 May 2005 08:07:39 +0000 Subject: r6625: Remove another global variable left over from a long time ago (magic char). Jeremy. (This used to be commit b1bfa9cb37deb22d1d08bc60ba44d61334f6446e) --- source3/smbd/dir.c | 2 +- source3/smbd/filename.c | 10 +++++----- source3/smbd/mangle.c | 19 +++++++++---------- source3/smbd/mangle_hash.c | 18 +++++++++++++----- source3/smbd/mangle_hash2.c | 15 +++++++-------- source3/smbd/reply.c | 9 ++++----- source3/smbd/service.c | 3 --- source3/smbd/trans2.c | 12 ++++++------ 8 files changed, 45 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 95a5903c14..d66d1601fb 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -784,7 +784,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { - if (!mangle_is_8_3(filename, False)) + if (!mangle_is_8_3(filename, False, SNUM(conn))) mangle_map(filename,True,False,SNUM(conn)); pstrcpy(fname,filename); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9ca2c0efae..5f3cdfb77e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,7 +150,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } - if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)) + if (!conn->case_preserve || (mangle_is_8_3(name, False, SNUM(conn)) && !conn->short_case_preserve)) strnorm(name, lp_defaultcase(SNUM(conn))); start = name; @@ -179,7 +179,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (conn->case_sensitive && !mangle_is_mangled(name) && !*lp_mangled_map(SNUM(conn))) + if (conn->case_sensitive && !mangle_is_mangled(name, SNUM(conn)) && !*lp_mangled_map(SNUM(conn))) return(False); name_has_wildcard = ms_has_wild(start); @@ -189,7 +189,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * just a component. JRA. */ - if (mangle_is_mangled(start)) + if (mangle_is_mangled(start, SNUM(conn))) component_was_mangled = True; /* @@ -317,7 +317,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * base of the filename. */ - if (mangle_is_mangled(start)) { + if (mangle_is_mangled(start, SNUM(conn))) { mangle_check_cache( start, sizeof(pstring) - 1 - (start - name) ); } @@ -433,7 +433,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name BOOL mangled; long curpos; - mangled = mangle_is_mangled(name); + mangled = mangle_is_mangled(name, SNUM(conn)); /* handle null paths */ if (*path == 0) diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 43becff69d..afc1ca12f0 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -67,29 +67,28 @@ static void mangle_init(void) void mangle_reset_cache(void) { mangle_init(); - mangle_fns->reset(); } /* see if a filename has come out of our mangling code */ -BOOL mangle_is_mangled(const char *s) +BOOL mangle_is_mangled(const char *s, int snum) { - return mangle_fns->is_mangled(s); + return mangle_fns->is_mangled(s, snum); } /* see if a filename matches the rules of a 8.3 filename */ -BOOL mangle_is_8_3(const char *fname, BOOL check_case) +BOOL mangle_is_8_3(const char *fname, BOOL check_case, int snum) { - return mangle_fns->is_8_3(fname, check_case, False); + return mangle_fns->is_8_3(fname, check_case, False, snum); } -BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case) +BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum) { - return mangle_fns->is_8_3(fname, check_case, True); + return mangle_fns->is_8_3(fname, check_case, True, snum); } /* @@ -98,9 +97,9 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case) looking for a matching name if it doesn't. It should succeed most of the time or there will be a huge performance penalty */ -BOOL mangle_check_cache(char *s, size_t maxlen) +BOOL mangle_check_cache(char *s, size_t maxlen, int snum) { - return mangle_fns->check_cache(s, maxlen); + return mangle_fns->check_cache(s, maxlen, snum); } /* @@ -120,5 +119,5 @@ void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) /* invoke the inane "mangled map" code */ mangle_map_filename(OutName, snum); - mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum)); + mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum), snum); } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 0067023e61..98ba775daf 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -276,13 +276,15 @@ done: return ret; } -static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) +static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum) { const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; size_t size; + magic_char = lp_magicchar(snum); + if (!fname || !*fname) return False; if ((f = strrchr(fname, '/')) == NULL) @@ -362,10 +364,12 @@ static void init_chartest( void ) * * ************************************************************************** ** */ -static BOOL is_mangled(const char *s) +static BOOL is_mangled(const char *s, int snum) { char *magic; + magic_char = lp_magicchar(snum); + if( !ct_initialized ) init_chartest(); @@ -460,12 +464,14 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) * ************************************************************************** ** */ -static BOOL check_cache( char *s, size_t maxlen ) +static BOOL check_cache( char *s, size_t maxlen, int snum ) { TDB_DATA data_val; char *ext_start = NULL; char *saved_ext = NULL; + magic_char = lp_magicchar(snum); + /* If the cache isn't initialized, give up. */ if( !tdb_mangled_cache ) return( False ); @@ -604,9 +610,11 @@ static void to_8_3(char *s, int default_case) * **************************************************************************** */ -static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case) +static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum) { smb_ucs2_t *OutName_ucs2; + magic_char = lp_magicchar(snum); + DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, need83 ? "True" : "False", cache83 ? "True" : "False")); @@ -643,9 +651,9 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case) to drop in an alternative mangling implementation */ static struct mangle_fns mangle_fns = { + mangle_reset, is_mangled, is_8_3, - mangle_reset, check_cache, name_map }; diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 4896cfb17b..6a8462ee3d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len) directory separators. It should return true if any component is mangled */ -static BOOL is_mangled(const char *name) +static BOOL is_mangled(const char *name, int snum) { const char *p; const char *s; @@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) +static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum) { int len, i; char *dot_p; @@ -370,7 +370,7 @@ static void mangle_reset(void) try to find a 8.3 name in the cache, and if found then replace the string with the original long name. */ -static BOOL check_cache(char *name, size_t maxlen) +static BOOL check_cache(char *name, size_t maxlen, int snum) { u32 hash, multiplier; unsigned int i; @@ -378,7 +378,7 @@ static BOOL check_cache(char *name, size_t maxlen) char extension[4]; /* make sure that this is a mangled name from this cache */ - if (!is_mangled(name)) { + if (!is_mangled(name, snum)) { M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } @@ -506,7 +506,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case) +static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, int snum) { char *dot_p; char lead_chars[7]; @@ -520,7 +520,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case) if (!is_reserved_name(name)) { /* if the name is already a valid 8.3 name then we don't need to do anything */ - if (is_8_3(name, False, False)) { + if (is_8_3(name, False, False, snum)) { return; } @@ -679,14 +679,13 @@ static void init_tables(void) } } - /* the following provides the abstraction layer to make it easier to drop in an alternative mangling implementation */ static struct mangle_fns mangle_fns = { + mangle_reset, is_mangled, is_8_3, - mangle_reset, check_cache, name_map }; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index aa33e59b7e..d39b9a20d3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -30,7 +30,6 @@ extern enum protocol_types Protocol; extern int max_send; extern int max_recv; -extern char magic_char; extern int global_oplock_break; unsigned int smb_echo_count = 0; extern uint32 global_client_caps; @@ -1753,7 +1752,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask)) + if (!rc && mangle_is_mangled(mask,SNUM(conn))) mangle_check_cache( mask, sizeof(pstring)-1 ); if (!has_wild) { @@ -4055,7 +4054,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask)) + if (!rc && mangle_is_mangled(mask,SNUM(conn))) mangle_check_cache( mask, sizeof(pstring)-1 ); has_wild = ms_has_wild(mask); @@ -4064,7 +4063,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui /* * No wildcards - just process the one file. */ - BOOL is_short_name = mangle_is_8_3(name, True); + BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn)); /* Add a terminating '/' to the directory name. */ pstrcat(directory,"/"); @@ -4536,7 +4535,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask)) + if (!rc && mangle_is_mangled(mask, SNUM(conn))) mangle_check_cache( mask, sizeof(pstring)-1 ); has_wild = ms_has_wild(mask); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d4d6274dff..1708c51ff9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -20,11 +20,9 @@ #include "includes.h" -extern char magic_char; extern struct timeval smb_last_time; extern userdom_struct current_user_info; - /**************************************************************************** Load parameters specific to a connection/service. ****************************************************************************/ @@ -80,7 +78,6 @@ BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir) conn->case_sensitive = False; break; } - magic_char = lp_magicchar(snum); return(True); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dd72db2fae..9f29a89f01 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1064,7 +1064,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive))) got_match = mask_match(fname, mask, conn->case_sensitive); - if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False)) { + if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) { /* * It turns out that NT matches wildcards against @@ -1286,7 +1286,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True); + was_8_3 = mangle_is_8_3(fname, True, SNUM(conn)); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; @@ -1422,7 +1422,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, case SMB_FIND_ID_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True); + was_8_3 = mangle_is_8_3(fname, True, SNUM(conn)); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; @@ -1813,7 +1813,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * (see PR#13758). JRA. */ - if(!mangle_is_8_3_wildcards( mask, False)) + if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn))) mangle_map(mask, True, True, SNUM(conn)); return(-1); @@ -2007,7 +2007,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * could be mangled. Ensure we check the unmangled name. */ - if (mangle_is_mangled(resume_name)) { + if (mangle_is_mangled(resume_name, SNUM(conn))) { mangle_check_cache(resume_name, sizeof(resume_name)-1); } @@ -3044,7 +3044,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n")); pstrcpy(short_name,base_name); /* Mangle if not already 8.3 */ - if(!mangle_is_8_3(short_name, True)) { + if(!mangle_is_8_3(short_name, True, SNUM(conn))) { mangle_map(short_name,True,True,SNUM(conn)); } len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE); -- cgit From af2437b269a175672dd093527e20cc7f719b1e16 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 May 2005 10:47:52 +0000 Subject: r6629: Fix stupid typo. Thanks Gunther. Jeremy. (This used to be commit 8693df2551fce145f7c919dee67a26d8fb8dfd1d) --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d39b9a20d3..8cccd9b568 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1753,7 +1753,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) */ if (!rc && mangle_is_mangled(mask,SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1 ); + mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); if (!has_wild) { pstrcat(directory,"/"); @@ -4055,7 +4055,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui */ if (!rc && mangle_is_mangled(mask,SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1 ); + mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); has_wild = ms_has_wild(mask); @@ -4536,7 +4536,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, */ if (!rc && mangle_is_mangled(mask, SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1 ); + mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); has_wild = ms_has_wild(mask); -- cgit From 5622d96cd674bd63ec86db971531f2088e32842f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 May 2005 10:55:56 +0000 Subject: r6631: More typo's. Sorry. Jeremy. (This used to be commit 2673ccd19f194d1f7756a154afe4200e386ca1b3) --- source3/smbd/filename.c | 4 ++-- source3/smbd/trans2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5f3cdfb77e..7191e75715 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -318,7 +318,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (mangle_is_mangled(start, SNUM(conn))) { - mangle_check_cache( start, sizeof(pstring) - 1 - (start - name) ); + mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), SNUM(conn)); } DEBUG(5,("New file %s\n",start)); @@ -447,7 +447,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name * (JRA). */ if (mangled) - mangled = !mangle_check_cache( name, maxlength ); + mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); /* open the directory */ if (!(cur_dir = OpenDir(conn, path))) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9f29a89f01..d9f3c9e81d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2008,7 +2008,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd */ if (mangle_is_mangled(resume_name, SNUM(conn))) { - mangle_check_cache(resume_name, sizeof(resume_name)-1); + mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn)); } /* -- cgit From bd688a9138a9ee8593a2eada158c2bcde2b59f4e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 May 2005 13:26:54 +0000 Subject: r6633: Added "check_path_syntax_posix()" in preparation for handling POSIX pathnames. Not yet used. Jeremy. (This used to be commit 381da9b55d6a3fda2ba4a3f12bee50853b7fd3b3) --- source3/smbd/nttrans.c | 22 ++++++++---- source3/smbd/reply.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/vfs.c | 6 ++-- 3 files changed, 115 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d747e84a3a..a37ae5548f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -73,7 +73,6 @@ static char *nttrans_realloc(char **ptr, size_t size) return tptr; } - /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -262,6 +261,15 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e return 0; } +/**************************************************************************** + Is it an NTFS stream name ? +****************************************************************************/ + +BOOL is_ntfs_stream_name(const char *fname) +{ + return (strchr_m(fname, ':') != NULL) ? True : False; +} + /**************************************************************************** Save case statics. ****************************************************************************/ @@ -668,7 +676,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * Check to see if this is a mac fork of some kind. */ - if( strchr_m(fname, ':')) { + if( is_ntfs_stream_name(fname)) { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } @@ -717,7 +725,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * Check to see if this is a mac fork of some kind. */ - if( strchr_m(fname, ':')) { + if( is_ntfs_stream_name(fname)) { #ifdef HAVE_SYS_QUOTAS if ((fake_file_type=is_fake_file(fname))!=FAKE_FILE_TYPE_NONE) { @@ -1329,8 +1337,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Check to see if this is a mac fork of some kind. */ - if( strchr_m(fname, ':')) + if( is_ntfs_stream_name(fname)) { return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } return ERROR_DOS(ERRDOS,ERRbadfid); } @@ -1369,8 +1378,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Check to see if this is a mac fork of some kind. */ - if( strchr_m(fname, ':')) + if( is_ntfs_stream_name(fname)) { return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } } /* @@ -1854,7 +1864,7 @@ int reply_ntrename(connection_struct *conn, return ERROR_NT(status); } - if( strchr_m(oldname, ':')) { + if( is_ntfs_stream_name(oldname)) { /* Can't rename a stream. */ END_PROFILE(SMBntrename); return ERROR_NT(NT_STATUS_ACCESS_DENIED); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8cccd9b568..e1131c56ed 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -280,6 +280,100 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname) return ret; } +/**************************************************************************** + Check the path for a POSIX client. + We're assuming here that '/' is not the second byte in any multibyte char + set (a safe assumption). +****************************************************************************/ + +NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) +{ + char *d = destname; + const char *s = srcname; + NTSTATUS ret = NT_STATUS_OK; + BOOL start_of_name_component = True; + + while (*s) { + if (*s == '/') { + /* + * Safe to assume is not the second part of a mb char as this is handled below. + */ + /* Eat multiple '/' or '\\' */ + while (*s == '/') { + s++; + } + if ((d != destname) && (*s != '\0')) { + /* We only care about non-leading or trailing '/' */ + *d++ = '/'; + } + + start_of_name_component = True; + continue; + } + + if (start_of_name_component) { + if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) { + /* Uh oh - "/../" or "/..\0" ! */ + + /* + * No mb char starts with '.' so we're safe checking the directory separator here. + */ + + /* If we just added a '/' - delete it */ + if ((d > destname) && (*(d-1) == '/')) { + *(d-1) = '\0'; + d--; + } + + /* Are we at the start ? Can't go back further if so. */ + if (d <= destname) { + ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + break; + } + /* Go back one level... */ + /* We know this is safe as '/' cannot be part of a mb sequence. */ + /* NOTE - if this assumption is invalid we are not in good shape... */ + /* Decrement d first as d points to the *next* char to write into. */ + for (d--; d > destname; d--) { + if (*d == '/') + break; + } + s += 2; /* Else go past the .. */ + continue; + + } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) { + /* Eat the '.' */ + s++; + continue; + } + } + + if (!(*s & 0x80)) { + *d++ = *s++; + } else { + switch(next_mb_char_size(s)) { + case 4: + *d++ = *s++; + case 3: + *d++ = *s++; + case 2: + *d++ = *s++; + case 1: + *d++ = *s++; + break; + default: + DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n")); + *d = '\0'; + return NT_STATUS_INVALID_PARAMETER; + } + } + start_of_name_component = False; + } + + *d = '\0'; + return ret; +} + /**************************************************************************** Pull a string and check the path - provide for error return. ****************************************************************************/ @@ -3529,7 +3623,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,&sbuf); - if( strchr_m(directory, ':')) { + if( is_ntfs_stream_name(directory)) { DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory)); END_PROFILE(SMBmkdir); return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index dee29f4796..ade28f9bee 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -227,13 +227,15 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) return False; } - if(!backends) static_init_vfs; + if(!backends) { + static_init_vfs; + } DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object)); module_name = smb_xstrdup(vfs_object); - p = strchr(module_name, ':'); + p = strchr_m(module_name, ':'); if (p) { *p = 0; -- cgit From 08355754151b2d02b2102bc76e94b63ffffdf408 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 8 May 2005 23:16:28 +0000 Subject: r6673: Fix the write cache based on some VERY good detective work from Ingo Kilian . You must do a make clean after updating this. Jeremy. (This used to be commit 3b2cd19fcb8ce38578b122fd6ae722b73081dcda) --- source3/smbd/fake_file.c | 1 - source3/smbd/fileio.c | 139 +++++++++++++++++++++++++++-------------------- source3/smbd/open.c | 3 - source3/smbd/reply.c | 17 +++--- 4 files changed, 87 insertions(+), 73 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index ee510eb003..59ddb60db5 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -65,7 +65,6 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; - fsp->size = psbuf->st_size; fsp->pos = -1; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 3048c27fa2..dbf1e5a789 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -28,16 +28,17 @@ static BOOL setup_write_cache(files_struct *, SMB_OFF_T); Read from write cache if we can. ****************************************************************************/ - static BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { write_cache *wcp = fsp->wcp; - if(!wcp) + if(!wcp) { return False; + } - if(n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size) + if( n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size) { return False; + } memcpy(data, wcp->data + (pos - wcp->offset), n); @@ -55,8 +56,9 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) ssize_t ret=0,readret; /* you can't read from print files */ - if (fsp->print_file) + if (fsp->print_file) { return -1; + } /* * Serve from write cache if we can. @@ -90,11 +92,13 @@ tryagain: #else /* NO DMF fix. */ readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos); - if (readret == -1) + if (readret == -1) { return -1; + } #endif - if (readret > 0) + if (readret > 0) { ret += readret; + } } DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", @@ -117,9 +121,9 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ { ssize_t ret; - if (pos == -1) + if (pos == -1) { ret = vfs_write_data(fsp, data, n); - else { + } else { fsp->pos = pos; ret = vfs_pwrite_data(fsp, data, n, pos); } @@ -161,7 +165,26 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ } /**************************************************************************** -write to a file + File size cache change. + Updates size on disk but doesn't flush the cache. +****************************************************************************/ + +static int wcp_file_size_change(files_struct *fsp) +{ + int ret; + write_cache *wcp = fsp->wcp; + + wcp->file_size = wcp->offset + wcp->data_size; + ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, wcp->file_size); + if (ret == -1) { + DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f error %s\n", + fsp->fsp_name, (double)wcp->file_size, strerror(errno) )); + } + return ret; +} + +/**************************************************************************** + Write to a file. ****************************************************************************/ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) @@ -195,7 +218,6 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); - fsp->size = (SMB_BIG_UINT)st.st_size; if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st, False); } @@ -257,8 +279,6 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if(!wcp) { DO_PROFILE_INC(writecache_direct_writes); total_written = real_write_file(fsp, data, pos, n); - if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size)) - fsp->size = (SMB_BIG_UINT)(pos + total_written); return total_written; } @@ -273,7 +293,6 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", */ if (wcp->data_size) { - BOOL cache_flush_needed = False; if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) { @@ -302,16 +321,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * Update the current buffer size with the new data. */ - if(pos + data_used > wcp->offset + wcp->data_size) + if(pos + data_used > wcp->offset + wcp->data_size) { wcp->data_size = pos + data_used - wcp->offset; + } /* * Update the file size if changed. */ if (wcp->offset + wcp->data_size > wcp->file_size) { - wcp->file_size = wcp->offset + wcp->data_size; - fsp->size = (SMB_BIG_UINT)wcp->file_size; + if (wcp_file_size_change(fsp) == -1) { + return -1; + } } /* @@ -319,11 +340,11 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * return here. */ - if(n == data_used) + if(n == data_used) { return n; - else + } else { cache_flush_needed = True; - + } /* * Move the start of data forward by the amount used, * cut down the amount left by the same amount. @@ -365,16 +386,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * Update the current buffer size with the new data. */ - if(pos + n > wcp->offset + wcp->data_size) + if(pos + n > wcp->offset + wcp->data_size) { wcp->data_size = pos + n - wcp->offset; + } /* * Update the file size if changed. */ if (wcp->offset + wcp->data_size > wcp->file_size) { - wcp->file_size = wcp->offset + wcp->data_size; - fsp->size = (SMB_BIG_UINT)wcp->file_size; + if (wcp_file_size_change(fsp) == -1) { + return -1; + } } /* @@ -423,10 +446,11 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", size_t data_used; - if(pos + n <= wcp->offset + wcp->alloc_size) + if(pos + n <= wcp->offset + wcp->alloc_size) { data_used = n; - else + } else { data_used = wcp->offset + wcp->alloc_size - pos; + } /* * Fill in the non-continuous area with zeros. @@ -441,16 +465,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * Update the current buffer size with the new data. */ - if(pos + data_used > wcp->offset + wcp->data_size) + if(pos + data_used > wcp->offset + wcp->data_size) { wcp->data_size = pos + data_used - wcp->offset; + } /* * Update the file size if changed. */ if (wcp->offset + wcp->data_size > wcp->file_size) { - wcp->file_size = wcp->offset + wcp->data_size; - fsp->size = (SMB_BIG_UINT)wcp->file_size; + if (wcp_file_size_change(fsp) == -1) { + return -1; + } } /* @@ -458,10 +484,11 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", * return here. */ - if(n == data_used) + if(n == data_used) { return n; - else + } else { cache_flush_needed = True; + } /* * Move the start of data forward by the amount used, @@ -521,15 +548,6 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); - /* - * Update the file size if needed. - */ - - if(pos + n > wcp->file_size) { - wcp->file_size = pos + n; - fsp->size = (SMB_BIG_UINT)wcp->file_size; - } - /* * If write would fit in the cache, and is larger than * the data already in the cache, flush the cache and @@ -556,12 +574,12 @@ cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned in } DO_PROFILE_INC(writecache_direct_writes); - if (ret == -1) + if (ret == -1) { return ret; + } if (pos + ret > wcp->file_size) { wcp->file_size = pos + ret; - fsp->size = (SMB_BIG_UINT)wcp->file_size; } return ret; @@ -571,11 +589,6 @@ cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned in } - if(wcp->data_size > wcp->file_size) { - wcp->file_size = wcp->data_size; - fsp->size = (SMB_BIG_UINT)wcp->file_size; - } - if (cache_flush_needed) { DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", @@ -593,12 +606,12 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", if (n > wcp->alloc_size ) { ssize_t ret = real_write_file(fsp, data, pos, n); - if (ret == -1) + if (ret == -1) { return -1; + } if (pos + ret > wcp->file_size) { wcp->file_size = pos + n; - fsp->size = (SMB_BIG_UINT)wcp->file_size; } DO_PROFILE_INC(writecache_direct_writes); @@ -629,8 +642,9 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", */ if (wcp->offset + wcp->data_size > wcp->file_size) { - wcp->file_size = wcp->offset + wcp->data_size; - fsp->size = (SMB_BIG_UINT)wcp->file_size; + if (wcp_file_size_change(fsp) == -1) { + return -1; + } } DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n", (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n)); @@ -650,11 +664,13 @@ void delete_write_cache(files_struct *fsp) { write_cache *wcp; - if(!fsp) + if(!fsp) { return; + } - if(!(wcp = fsp->wcp)) + if(!(wcp = fsp->wcp)) { return; + } DO_PROFILE_DEC(writecache_allocated_write_caches); allocated_write_caches--; @@ -676,11 +692,13 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); write_cache *wcp; - if (allocated_write_caches >= MAX_WRITE_CACHES) + if (allocated_write_caches >= MAX_WRITE_CACHES) { return False; + } - if(alloc_size == 0 || fsp->wcp) + if(alloc_size == 0 || fsp->wcp) { return False; + } if((wcp = SMB_MALLOC_P(write_cache)) == NULL) { DEBUG(0,("setup_write_cache: malloc fail.\n")); @@ -716,7 +734,6 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) { - fsp->size = (SMB_BIG_UINT)file_size; if(fsp->wcp) { /* The cache *must* have been flushed before we do this. */ if (fsp->wcp->data_size != 0) { @@ -739,8 +756,9 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) size_t data_size; ssize_t ret; - if(!wcp || !wcp->data_size) + if(!wcp || !wcp->data_size) { return 0; + } data_size = wcp->data_size; wcp->data_size = 0; @@ -751,8 +769,9 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) fsp->fd, (double)wcp->offset, (unsigned int)data_size)); #ifdef WITH_PROFILE - if(data_size == wcp->alloc_size) + if(data_size == wcp->alloc_size) { DO_PROFILE_INC(writecache_num_perfect_writes); + } #endif ret = real_write_file(fsp, wcp->data, wcp->offset, data_size); @@ -761,8 +780,9 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) * Ensure file size if kept up to date if write extends file. */ - if ((ret != -1) && (wcp->offset + ret > wcp->file_size)) + if ((ret != -1) && (wcp->offset + ret > wcp->file_size)) { wcp->file_size = wcp->offset + ret; + } return ret; } @@ -786,8 +806,9 @@ void sync_file(connection_struct *conn, files_struct *fsp) int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) { - if (fsp->fd == -1) + if (fsp->fd == -1) { return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst); - else + } else { return SMB_VFS_FSTAT(fsp,fsp->fd, pst); + } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a3bc4a922d..8b30776fdd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -304,7 +304,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; - fsp->size = psbuf->st_size; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); @@ -1701,7 +1700,6 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; - fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = True; @@ -1765,7 +1763,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; - fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e1131c56ed..686f54c5e7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2190,21 +2190,18 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s maxcount = MIN(65535,maxcount); if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { - SMB_OFF_T size = fsp->size; - SMB_OFF_T sizeneeded = startpos + maxcount; + SMB_STRUCT_STAT st; + SMB_OFF_T size = 0; - if (size < sizeneeded) { - SMB_STRUCT_STAT st; - if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) - size = st.st_size; - if (!fsp->can_write) - fsp->size = size; + if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) { + size = st.st_size; } - if (startpos >= size) + if (startpos >= size) { nread = 0; - else + } else { nread = MIN(maxcount,(size - startpos)); + } } #if 0 /* mincount appears to be ignored in a W2K server. JRA. */ -- cgit From 34ea46ef8c4d94f59c11a7b1edc79db382970e0c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 10 May 2005 04:25:11 +0000 Subject: r6696: Another attempt to fix the (unreproducible for me) bug #2346 (read-only excel files). Ensures that any missing user ACL entry will be generated from a union of all group permissions that contain the user. Awaiting feedback from the reporters. Jeremy. (This used to be commit 874353e617b314429359e8e9516898f670bbf539) --- source3/smbd/posix_acls.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 1e68900bd3..b31e97c76f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1097,13 +1097,28 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, pace->attr = ALLOW_ACE; if (setting_acl) { + /* See if the owning user is in any of the other groups in + the ACE. If so, OR in the permissions from that group. */ + + BOOL group_matched = False; + canon_ace *pace_iter; + + for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) { + if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) { + if (uid_entry_in_group(pace, pace_iter)) { + pace->perms |= pace_iter->perms; + group_matched = True; + } + } + } + /* If we only got an "everyone" perm, just use that. */ - if (!got_grp && got_other) - pace->perms = pace_other->perms; - else if (got_grp && uid_entry_in_group(pace, pace_group)) - pace->perms = pace_group->perms; - else - pace->perms = 0; + if (!group_matched) { + if (got_other) + pace->perms = pace_other->perms; + else + pace->perms = 0; + } apply_default_perms(fsp, pace, S_IRUSR); } else { -- cgit From dba540214ad42ed2fb520d6b831aaa36fcc0c848 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 10 May 2005 15:42:32 +0000 Subject: r6712: BUG 2362: fix quota support on DragonFly (Joerg Sonnenberger ) (This used to be commit 0644a2abf646be35b345665558ca173004beedde) --- source3/smbd/quotas.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 1a73fdf222..008f212c2c 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -923,7 +923,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #else -#if defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #include #include #elif AIX @@ -933,12 +933,12 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #define dqb_curfiles dqb_curinodes #define dqb_fhardlimit dqb_ihardlimit #define dqb_fsoftlimit dqb_isoftlimit -#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ +#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ #include #include #endif -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__DragonFly__) #include #include @@ -1119,7 +1119,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB int r; struct dqblk D; uid_t euser_id; -#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) +#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) char dev_disk[256]; SMB_STRUCT_STAT S; @@ -1136,7 +1136,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB return (False); #endif /* ifdef HPUX */ -#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */ +#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */ euser_id = geteuid(); @@ -1149,11 +1149,11 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB restore_re_uid(); #else -#if defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) { /* FreeBSD patches from Marty Moll */ gid_t egrp_id; -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__DragonFly__) SMB_DEV_T devno; struct statfs *mnts; SMB_STRUCT_STAT st; @@ -1180,7 +1180,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB save_re_uid(); set_effective_uid(0); -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__DragonFly__) if (strcmp(mnts[i].f_fstypename,"nfs") == 0) { BOOL retval; retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize); @@ -1208,17 +1208,17 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB return False; r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); restore_re_uid(); -#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ +#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); -#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */ +#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ #endif /* HPUX */ /* Use softlimit to determine disk space, except when it has been exceeded */ -#if defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) *bsize = DEV_BSIZE; -#else /* !__FreeBSD__ && !__OpenBSD__ */ +#else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */ *bsize = 1024; -#endif /*!__FreeBSD__ && !__OpenBSD__ */ +#endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */ if (r) { @@ -1241,7 +1241,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB return(False); /* Use softlimit to determine disk space, except when it has been exceeded */ if ((D.dqb_curblocks>D.dqb_bsoftlimit) -#if !defined(__FreeBSD__) && !defined(__OpenBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0)) #endif ) { -- cgit From 1d37a6267ed07ce1d181d76a5e4ca06bc41c3c88 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 10 May 2005 17:58:51 +0000 Subject: r6715: We don't need to wrap the setfsinfo call in HAVE_QUOTA as they'll just return ENOSYS if we don't. Add new CAP for POSIX pathnames, prepare to allow FSINFO set for client POSIX caps. Jeremy. (This used to be commit 4d99b57aedba8431ef5827d1e75413a10b35e1ce) --- source3/smbd/trans2.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d9f3c9e81d..8dedf30472 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2405,7 +2405,6 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return -1; } -#ifdef HAVE_SYS_QUOTAS /**************************************************************************** Reply to a TRANS2_SETFSINFO (set filesystem info). ****************************************************************************/ @@ -2517,7 +2516,6 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb return outsize; } -#endif /* HAVE_SYS_QUOTAS */ /**************************************************************************** Utility function to set bad path error. @@ -4997,14 +4995,13 @@ int reply_trans2(connection_struct *conn, END_PROFILE_NESTED(Trans2_qfsinfo); break; -#ifdef HAVE_SYS_QUOTAS case TRANSACT2_SETFSINFO: START_PROFILE_NESTED(Trans2_setfsinfo); outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, ¶ms, total_params, &data, total_data, max_data_bytes); END_PROFILE_NESTED(Trans2_setfsinfo); break; -#endif + case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: START_PROFILE_NESTED(Trans2_qpathinfo); -- cgit From 8a1756006a1abf8ceb22fff889c94b3d28d19c20 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 May 2005 01:04:51 +0000 Subject: r6841: Attempt to fix buf #2681. With "strict allocate = yes" we now zero fill when a file is extended. Should catch disk full errors on write from MS-Office. Jeremy. (This used to be commit 858824f37be443320487a8e28ec8fa172cdf5a18) --- source3/smbd/fileio.c | 5 ++++ source3/smbd/vfs.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index dbf1e5a789..977988fde4 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -125,6 +125,11 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ ret = vfs_write_data(fsp, data, n); } else { fsp->pos = pos; + if (pos && lp_strict_allocate(SNUM(fsp->conn))) { + if (vfs_fill_sparse(fsp, pos) == -1) { + return -1; + } + } ret = vfs_pwrite_data(fsp, data, n, pos); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index ade28f9bee..b09935eaa9 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -588,6 +588,72 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) return ret; } +/**************************************************************************** + A vfs fill sparse call. + Writes zeros from the end of file to len, if len is greater than EOF. + Used only by strict_sync. + Returns 0 on success, -1 on failure. +****************************************************************************/ + +static char *sparse_buf; +#define SPARSE_BUF_WRITE_SIZE (32*1024) + +int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) +{ + int ret; + SMB_STRUCT_STAT st; + SMB_OFF_T offset; + size_t total; + size_t num_to_write; + ssize_t pwrite_ret; + + release_level_2_oplocks_on_change(fsp); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,&st); + if (ret == -1) { + return ret; + } + + if (len <= st.st_size) { + return 0; + } + + DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n", + fsp->fsp_name, (double)st.st_size, (double)len, (double)(len - st.st_size))); + + flush_write_cache(fsp, SIZECHANGE_FLUSH); + + if (!sparse_buf) { + sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE); + if (!sparse_buf) { + errno = ENOMEM; + return -1; + } + } + + offset = st.st_size; + num_to_write = len - st.st_size; + total = 0; + + while (total < num_to_write) { + size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total)); + + pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fd, sparse_buf, curr_write_size, offset + total); + if (pwrite_ret == -1) { + DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n", + fsp->fsp_name, strerror(errno) )); + return -1; + } + if (pwrite_ret == 0) { + return 0; + } + + total += pwrite_ret; + } + + set_filelen_write_cache(fsp, len); + return 0; +} + /**************************************************************************** Transfer some data (n bytes) between two file_struct's. ****************************************************************************/ -- cgit From fe0ce8dd8e18de6110404661f26db7a66ebac5ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 May 2005 18:02:15 +0000 Subject: r6890: Refactor printing interface to take offset into job. Fixes bug where large print jobs can have out-of-order offsets. Bug found by Arcady Chernyak Jeremy. (This used to be commit 482f7e0e3706098b71aa0b31a134994acb1e9fcf) --- source3/smbd/fileio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 977988fde4..9b39bf8fe1 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -117,7 +117,7 @@ static unsigned int allocated_write_caches; *Really* write to a file. ****************************************************************************/ -static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_t n) +static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos, size_t n) { ssize_t ret; @@ -192,7 +192,7 @@ static int wcp_file_size_change(files_struct *fsp) Write to a file. ****************************************************************************/ -ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) +ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) { write_cache *wcp = fsp->wcp; ssize_t total_written = 0; @@ -209,7 +209,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) return -1; } - return print_job_write(SNUM(fsp->conn), jobid, data, n); + return print_job_write(SNUM(fsp->conn), jobid, data, pos, n); } if (!fsp->can_write) { -- cgit From bd16770954424d86298a57d6c59aa69d5b42ce07 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 May 2005 23:37:35 +0000 Subject: r6895: Add "acl check permissions" to turn on/off the new behaviour of checking for write access in a directory before delete. Also controls checking for write access before labeling a file read-only if DOS attributes are not being stored in EA's. Docuementation to follow. Jeremy. (This used to be commit dd1a5e6e499dd721c5bb8d56a61810a7454a3449) --- source3/smbd/dosmode.c | 17 ++++++++++++----- source3/smbd/nttrans.c | 4 ++-- source3/smbd/posix_acls.c | 19 ++++++++++--------- 3 files changed, 24 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 3a0e81e5fe..65ea2807e7 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -116,13 +116,18 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL c Change a unix mode to a dos mode. ****************************************************************************/ -uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf) +uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { int result = 0; - if ((sbuf->st_mode & S_IWUSR) == 0) + if (lp_acl_check_permissions(SNUM(conn))) { + if (!can_write_to_file(conn, path, sbuf)) { + result |= aRONLY; + } + } else if ((sbuf->st_mode & S_IWUSR) == 0) { result |= aRONLY; - + } + if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) result |= aARCH; @@ -291,7 +296,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) return result; } - result = dos_mode_from_sbuf(conn, sbuf); + result = dos_mode_from_sbuf(conn, path, sbuf); /* Now do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ @@ -433,9 +438,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times) { + SMB_STRUCT_STAT sbuf; int ret = -1; errno = 0; + ZERO_STRUCT(sbuf); if(SMB_VFS_UTIME(conn,fname, times) == 0) return 0; @@ -453,7 +460,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times */ /* Check if we have write access. */ - if (can_write_to_file(conn, fname)) { + if (can_write_to_file(conn, fname, &sbuf)) { /* We are allowed to become root and change the filetime. */ become_root(); ret = SMB_VFS_UTIME(conn,fname, times); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a37ae5548f..a0f94d616d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -802,7 +802,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if (desired_access & DELETE_ACCESS) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { #endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the @@ -1422,7 +1422,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (desired_access & DELETE_ACCESS) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { #endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b31e97c76f..b5052eec25 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4006,9 +4006,8 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) this to successfully check for ability to write for dos filetimes. ****************************************************************************/ -BOOL can_write_to_file(connection_struct *conn, const char *fname) +BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - SMB_STRUCT_STAT sbuf; int ret; if (!CAN_WRITE(conn)) { @@ -4020,22 +4019,24 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname) return True; } - /* Get the file permission mask and owners. */ - if(SMB_VFS_STAT(conn, fname, &sbuf) != 0) { - return False; + if (!VALID_STAT(*psbuf)) { + /* Get the file permission mask and owners. */ + if(SMB_VFS_STAT(conn, fname, psbuf) != 0) { + return False; + } } /* Check primary owner write access. */ - if (current_user.uid == sbuf.st_uid) { - return (sbuf.st_mode & S_IWUSR) ? True : False; + if (current_user.uid == psbuf->st_uid) { + return (psbuf->st_mode & S_IWUSR) ? True : False; } /* Check group or explicit user acl entry write access. */ - ret = check_posix_acl_group_write(conn, fname, &sbuf); + ret = check_posix_acl_group_write(conn, fname, psbuf); if (ret == 0 || ret == 1) { return ret ? True : False; } /* Finally check other write access. */ - return (sbuf.st_mode & S_IWOTH) ? True : False; + return (psbuf->st_mode & S_IWOTH) ? True : False; } -- cgit From 4a494ccf768ea242013a42b8dac61655ca863df4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 May 2005 20:47:43 +0000 Subject: r6946: Allow mapping of POSIX ACLs to NT perms to differentiate between directories and files. Needed for Volker's coming changes. Jeremy. (This used to be commit b257744fdfd0a8d940ae834b3c21f0f298c7d1f9) --- source3/smbd/posix_acls.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b5052eec25..b5ac2e8241 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -801,7 +801,7 @@ static BOOL nt4_compatible_acls(void) not get. Deny entries are implicit on get with ace->perms = 0. ****************************************************************************/ -static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon_ace *ace) +static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon_ace *ace, BOOL directory_ace) { SEC_ACCESS sa; uint32 nt_mask = 0; @@ -809,7 +809,11 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; if ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS) { + if (directory_ace) { + nt_mask = UNIX_DIRECTORY_ACCESS_RWX; + } else { nt_mask = UNIX_ACCESS_RWX; + } } else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) { /* * Windows NT refuses to display ACEs with no permissions in them (but @@ -825,9 +829,15 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon else nt_mask = 0; } else { - nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); - nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); - nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 ); + if (directory_ace) { + nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 ); + nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 ); + nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 ); + } else { + nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); + nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); + nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 ); + } } DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n", @@ -2815,7 +2825,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) for (i = 0; i < num_acls; i++, ace = ace->next) { SEC_ACCESS acc; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace, fsp->is_directory); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0); } @@ -2833,7 +2843,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) for (i = 0; i < num_def_acls; i++, ace = ace->next) { SEC_ACCESS acc; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace, fsp->is_directory); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY| -- cgit From 0ef417d9583154a261ae8c4b01f23c29a9110ca1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 May 2005 04:55:18 +0000 Subject: r6949: Back-port Volker's cache fix, plus my change. Jeremy. (This used to be commit 27d43f6d36b3f6abc368ec6a00ef9803cb27c324) --- source3/smbd/fileio.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 9b39bf8fe1..69b8b57642 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -509,6 +509,44 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", write_path = 3; + } else if ( (pos >= wcp->file_size) && + (n == 1) && + (pos < wcp->offset + 2*wcp->alloc_size) && + (wcp->file_size == wcp->offset + wcp->data_size)) { + + /* + +---------------+ + | Cached data | + +---------------+ + + +--------+ + | 1 Byte | + +--------+ + + MS-Office seems to do this a lot to determine if there's enough + space on the filesystem to write a new file. + */ + + SMB_BIG_UINT new_start = wcp->offset + wcp->data_size; + + flush_write_cache(fsp, WRITE_FLUSH); + wcp->offset = new_start; + wcp->data_size = pos - new_start + 1; + memset(wcp->data, '\0', wcp->data_size); + memcpy(wcp->data + wcp->data_size-1, data, 1); + + /* + * Update the file size if changed. + */ + + if (wcp->offset + wcp->data_size > wcp->file_size) { + if (wcp_file_size_change(fsp) == -1) { + return -1; + } + } + + return n; + } else { /* ASCII art..... JRA. -- cgit From 0419e24287d09a71735d94ea019a7f17842201d3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 May 2005 00:51:39 +0000 Subject: r6965: Remove some dead code from util_unistr.c. Start of fix for #2735 - we are not mangling some names we should. More fixes to follow. Jeremy. (This used to be commit ac0fa973774c36b72863aea369e9d243cf7420fa) --- source3/smbd/mangle_hash.c | 86 +++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 98ba775daf..fee386d6db 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -20,36 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* -------------------------------------------------------------------------- ** - * Notable problems... - * - * March/April 1998 CRH - * - Many of the functions in this module overwrite string buffers passed to - * them. This causes a variety of problems and is, generally speaking, - * dangerous and scarry. See the kludge notes in name_map() - * below. - * - It seems that something is calling name_map() twice. The - * first call is probably some sort of test. Names which contain - * illegal characters are being doubly mangled. I'm not sure, but - * I'm guessing the problem is in server.c. - * - * -------------------------------------------------------------------------- ** - */ - -/* -------------------------------------------------------------------------- ** - * History... - * - * March/April 1998 CRH - * Updated a bit. Rewrote is_mangled() to be a bit more selective. - * Rewrote the mangled name cache. Added comments here and there. - * &c. - * -------------------------------------------------------------------------- ** - */ - #include "includes.h" - /* -------------------------------------------------------------------------- ** * Other stuff... * @@ -67,24 +39,17 @@ * * chartest - array 0..255. The index range is the set of all possible * values of a byte. For each byte value, the content is a - * two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK, - * below. + * two nibble pair. See BASECHAR_MASK below. * * ct_initialized - False until the chartest array has been initialized via * a call to init_chartest(). * * BASECHAR_MASK - Masks the upper nibble of a one-byte value. * - * ILLEGAL_MASK - Masks the lower nibble of a one-byte value. - * * isbasecahr() - Given a character, check the chartest array to see * if that character is in the basechars set. This is * faster than using strchr_m(). * - * isillegal() - Given a character, check the chartest array to see - * if that character is in the illegal characters set. - * This is faster than using strchr_m(). - * */ char magic_char = '~'; @@ -97,9 +62,7 @@ static BOOL ct_initialized = False; #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) #define BASECHAR_MASK 0xf0 -#define ILLEGAL_MASK 0x0f #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK ) -#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK ) static TDB_CONTEXT *tdb_mangled_cache; @@ -107,17 +70,38 @@ static TDB_CONTEXT *tdb_mangled_cache; static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, BOOL allow_wildcards) { - if (!s || !*s) + if (!*s) { return NT_STATUS_INVALID_PARAMETER; + } - /* CHECK: this should not be necessary if the ms wild chars - are not valid in valid.dat --- simo */ - if (!allow_wildcards && ms_has_wild_w(s)) + if (!allow_wildcards && ms_has_wild_w(s)) { return NT_STATUS_UNSUCCESSFUL; + } while (*s) { - if(!isvalid83_w(*s)) + if(!isvalid83_w(*s)) { return NT_STATUS_UNSUCCESSFUL; + } + s++; + } + + return NT_STATUS_OK; +} + +static NTSTATUS has_illegal_chars(const smb_ucs2_t *s, BOOL allow_wildcards) +{ + if (!allow_wildcards && ms_has_wild_w(s)) { + return NT_STATUS_UNSUCCESSFUL; + } + + while (*s) { + switch(*s) { + case UCS2_CHAR('\\'): + case UCS2_CHAR('/'): + case UCS2_CHAR('|'): + case UCS2_CHAR(':'): + return NT_STATUS_UNSUCCESSFUL; + } s++; } @@ -156,10 +140,11 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr /* ************************************************************************** ** * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name. + * or contains illegal characters. * * Input: fname - String containing the name to be tested. * - * Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names. + * Output: NT_STATUS_UNSUCCESSFUL, if the condition above is true. * * Notes: This is a static function called by is_8_3(), below. * @@ -188,6 +173,10 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOO return ret; } + ret = has_illegal_chars(fname, allow_wildcards); + if (!NT_STATUS_IS_OK(ret)) + return ret; + str = strdup_w(fname); p = strchr_w(str, UCS2_CHAR('.')); if (p && p[1] == UCS2_CHAR(0)) { @@ -333,16 +322,13 @@ done: */ static void init_chartest( void ) { - const char *illegalchars = "*\\/?<>|\":"; const unsigned char *s; memset( (char *)chartest, '\0', 256 ); - for( s = (const unsigned char *)illegalchars; *s; s++ ) - chartest[*s] = ILLEGAL_MASK; - - for( s = (const unsigned char *)basechars; *s; s++ ) + for( s = (const unsigned char *)basechars; *s; s++ ) { chartest[*s] |= BASECHAR_MASK; + } ct_initialized = True; } @@ -566,7 +552,7 @@ static void to_8_3(char *s, int default_case) p = s; while( *p && baselen < 5 ) { - if (*p != '.') { + if (isbasechar(*p)) { base[baselen++] = p[0]; } p++; -- cgit From 75f109bc81c0ff0d714070b3f324bce62c2f3984 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 May 2005 19:25:35 +0000 Subject: r6977: Fix bug #2735 (not mangling control characters) plus ensure we don't create files with control characters either. Jeremy. (This used to be commit 0ca2423c706423a07721e375345b6d45a45cbcf4) --- source3/smbd/mangle_hash.c | 4 ++++ source3/smbd/mangle_hash2.c | 5 +++++ source3/smbd/reply.c | 6 ++++++ 3 files changed, 15 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index fee386d6db..871702623a 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -95,6 +95,10 @@ static NTSTATUS has_illegal_chars(const smb_ucs2_t *s, BOOL allow_wildcards) } while (*s) { + if (*s <= 0x1f) { + /* Control characters. */ + return NT_STATUS_UNSUCCESSFUL; + } switch(*s) { case UCS2_CHAR('\\'): case UCS2_CHAR('/'): diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 6a8462ee3d..4325c07f58 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -633,6 +633,11 @@ static void init_tables(void) memset(char_flags, 0, sizeof(char_flags)); for (i=1;i<128;i++) { + if (i <= 0x1f) { + /* Control characters. */ + char_flags[i] |= FLAG_ILLEGAL; + } + if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 686f54c5e7..1c2e950836 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -118,6 +118,9 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) } if (!(*s & 0x80)) { + if (*s <= 0x1f) { + return NT_STATUS_OBJECT_NAME_INVALID; + } switch (*s) { case '*': case '?': @@ -244,6 +247,9 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname) } if (!(*s & 0x80)) { + if (*s <= 0x1f) { + return NT_STATUS_OBJECT_NAME_INVALID; + } *d++ = *s++; } else { switch(next_mb_char_size(s)) { -- cgit From 8f8ff6870ca7ac08fce778509e85b742c9438011 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 May 2005 20:31:46 +0000 Subject: r6979: Tidyups. Jeremy. (This used to be commit 619d0aeebba66624ea0f5c7cff1c637738275b84) --- source3/smbd/trans2.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8dedf30472..a0544c31b7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1307,16 +1307,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, * a Win2k client bug. JRA. */ memset(p,'\0',26); - if (!was_8_3 && lp_manglednames(SNUM(conn))) { + if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); - } else { - SSVAL(p,0,0); - *(p+2) = 0; } p += 2 + 24; len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); @@ -1443,16 +1440,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, * a Win2k client bug. JRA. */ memset(p,'\0',26); - if (!was_8_3 && lp_manglednames(SNUM(conn))) { + if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); - } else { - SSVAL(p,0,0); - *(p+2) = 0; } p += 26; SSVAL(p,0,0); p += 2; /* Reserved ? */ -- cgit From af52df2f1fde76b518bf946e396bc29869aa6964 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 27 May 2005 13:58:04 +0000 Subject: r7020: fixing printer ace values and getting rid of false compiler warning about unitialized variable (This used to be commit 3a91b20e4bcc78c91932e6c4394b3f6f153b2ff5) --- source3/smbd/sesssetup.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9fbf0b1d51..0209dc2597 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -125,6 +125,7 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) return nt_status; } + if (!make_user_info_guest(&user_info)) { (auth_context->free)(&auth_context); return NT_STATUS_NO_MEMORY; @@ -146,6 +147,7 @@ static int reply_spnego_kerberos(connection_struct *conn, int length, int bufsize, DATA_BLOB *secblob) { + int map_domainuser_to_guest = 0; DATA_BLOB ticket; char *client, *p, *domain; fstring netbios_domain_name; @@ -245,14 +247,19 @@ static int reply_spnego_kerberos(connection_struct *conn, } asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client); - /* lookup the passwd struct, create a new user if necessary */ + if (lp_map_to_guest() == MAP_TO_GUEST_ON_VALID_DOMAIN_USER ){ + map_domainuser_to_guest == 1; + fstrcpy(user,lp_guestaccount()); + pw = smb_getpwnam( user, real_username, True ); + } else { map_username( user ); pw = smb_getpwnam( user, real_username, True ); if (!pw) { + } DEBUG(1,("Username %s is invalid on this system\n",user)); SAFE_FREE(user); SAFE_FREE(client); @@ -265,16 +272,20 @@ static int reply_spnego_kerberos(connection_struct *conn, sub_set_smb_name( real_username ); reload_services(True); - - if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) + if (map_domainuser_to_guest == 1) { + make_server_info_guest(&server_info); + }else{ + if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); SAFE_FREE(user); SAFE_FREE(client); data_blob_free(&ap_rep); + data_blob_free(&session_key); return ERROR_NT(ret); } + } /* make_server_info_pw does not set the domain. Without this we end up * with the local netbios name in substitutions for %D. */ -- cgit From cc6df2e9cf5b31f83cf88d21457b32712d90f04b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 27 May 2005 14:19:57 +0000 Subject: r7024: reverting mistaken commit (This used to be commit c70c5c4ee9b14fbdb174f542607aceebe0e88470) --- source3/smbd/sesssetup.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0209dc2597..9fbf0b1d51 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -125,7 +125,6 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) return nt_status; } - if (!make_user_info_guest(&user_info)) { (auth_context->free)(&auth_context); return NT_STATUS_NO_MEMORY; @@ -147,7 +146,6 @@ static int reply_spnego_kerberos(connection_struct *conn, int length, int bufsize, DATA_BLOB *secblob) { - int map_domainuser_to_guest = 0; DATA_BLOB ticket; char *client, *p, *domain; fstring netbios_domain_name; @@ -247,19 +245,14 @@ static int reply_spnego_kerberos(connection_struct *conn, } asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client); + /* lookup the passwd struct, create a new user if necessary */ - if (lp_map_to_guest() == MAP_TO_GUEST_ON_VALID_DOMAIN_USER ){ - map_domainuser_to_guest == 1; - fstrcpy(user,lp_guestaccount()); - pw = smb_getpwnam( user, real_username, True ); - } else { map_username( user ); pw = smb_getpwnam( user, real_username, True ); if (!pw) { - } DEBUG(1,("Username %s is invalid on this system\n",user)); SAFE_FREE(user); SAFE_FREE(client); @@ -272,20 +265,16 @@ static int reply_spnego_kerberos(connection_struct *conn, sub_set_smb_name( real_username ); reload_services(True); - if (map_domainuser_to_guest == 1) { - make_server_info_guest(&server_info); - }else{ - if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) + + if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); SAFE_FREE(user); SAFE_FREE(client); data_blob_free(&ap_rep); - data_blob_free(&session_key); return ERROR_NT(ret); } - } /* make_server_info_pw does not set the domain. Without this we end up * with the local netbios name in substitutions for %D. */ -- cgit From f24d88cf9da46680d52b42b92bd484e7b09ce99b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 31 May 2005 13:46:45 +0000 Subject: r7139: trying to reduce the number of diffs between trunk and 3.0; changing version to 3.0.20pre1 (This used to be commit 9727d05241574042dd3aa8844ae5c701d22e2da1) --- source3/smbd/notify_kernel.c | 10 ++++------ source3/smbd/service.c | 6 ++++-- source3/smbd/sesssetup.c | 15 ++++++--------- 3 files changed, 14 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 5c9d885eed..b2ccfc2796 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -101,9 +101,8 @@ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path close((int)fd_pending_array[i]); fd_pending_array[i] = (SIG_ATOMIC_T)-1; if (signals_received - i - 1) { - memmove(CONST_DISCARD(void *, &fd_pending_array[i]), - CONST_DISCARD(void *, &fd_pending_array[i+1]), - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); } data->directory_handle = -1; signals_received--; @@ -130,9 +129,8 @@ static void kernel_remove_notify(void *datap) if (fd == (int)fd_pending_array[i]) { fd_pending_array[i] = (SIG_ATOMIC_T)-1; if (signals_received - i - 1) { - memmove(CONST_DISCARD(void *, &fd_pending_array[i]), - CONST_DISCARD(void *, &fd_pending_array[i+1]), - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); } data->directory_handle = -1; signals_received--; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1708c51ff9..c63a43bac0 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -362,7 +362,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); - conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$")); + conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); conn->dirptr = NULL; /* Case options for the share. */ @@ -783,7 +783,9 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, snum = find_service(service); if (snum < 0) { - if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { + if (strequal(service,"IPC$") + || (lp_enable_asu_support() && strequal(service,"ADMIN$"))) + { DEBUG(3,("refusing IPC connection to %s\n", service)); *status = NT_STATUS_ACCESS_DENIED; return NULL; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9fbf0b1d51..48524b472d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -25,12 +25,6 @@ uint32 global_client_caps = 0; -extern BOOL global_encrypted_passwords_negotiated; -extern BOOL global_spnego_negotiated; -extern enum protocol_types Protocol; -extern int max_send; -extern struct auth_context *negprot_global_auth_context; - static struct auth_ntlmssp_state *global_ntlmssp_state; /* @@ -319,9 +313,7 @@ static int reply_spnego_kerberos(connection_struct *conn, /* wrap that up in a nice GSS-API wrapping */ if (NT_STATUS_IS_OK(ret)) { - ap_rep_wrapped = spnego_gen_krb5_wrap( - ap_rep, - CONST_ADD(const uint8 *, TOK_ID_KRB_AP_REP)); + ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); } else { ap_rep_wrapped = data_blob(NULL, 0); } @@ -643,8 +635,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, fstring native_lanman; fstring primary_domain; static BOOL done_sesssetup = False; + extern BOOL global_encrypted_passwords_negotiated; + extern BOOL global_spnego_negotiated; + extern enum protocol_types Protocol; + extern int max_send; auth_usersupplied_info *user_info = NULL; + extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; -- cgit From 6b036a8ad72d11a9087ab3a63b0cf4960cdfeff1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jun 2005 05:27:37 +0000 Subject: r7190: I *love* valgrind/cachegrind..... By removing unneeded memsets in qfilepathinfo I just improved our netbench performance by *********15%**********. Check it out :-). Jeremy. (This used to be commit c20a7b10b6a82db6df349fa5e6f2fcf3eeefec58) --- source3/smbd/trans2.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a0544c31b7..8c53f0c3ea 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2850,8 +2850,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } *ppdata = pdata; - memset((char *)pdata,'\0',data_size); - c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); allocation_size = get_allocation_size(conn,fsp,&sbuf); @@ -2906,13 +2904,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd unsigned int ea_size = estimate_ea_size(conn, fsp, fname); DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n")); data_size = 26; - put_dos_date2(pdata,l1_fdateCreation,c_time); - put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - SIVAL(pdata,l1_cbFile,(uint32)file_size); - SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); - SSVAL(pdata,l1_attrFile,mode); - SIVAL(pdata,l1_attrFile+2,ea_size); + put_dos_date2(pdata,0,c_time); + put_dos_date2(pdata,4,sbuf.st_atime); + put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */ + SIVAL(pdata,12,(uint32)file_size); + SIVAL(pdata,16,(uint32)allocation_size); + SSVAL(pdata,20,mode); + SIVAL(pdata,22,ea_size); break; } @@ -2999,7 +2997,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); DEBUG(5,("mode: %x\n", mode)); - break; case SMB_FILE_STANDARD_INFORMATION: @@ -3015,6 +3012,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,0); SCVAL(pdata,21,(mode&aDIR)?1:0); + SSVAL(pdata,22,0); /* Padding. */ break; case SMB_FILE_EA_INFORMATION: @@ -3088,6 +3086,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); + SSVAL(pdata,22,0); pdata += 24; SIVAL(pdata,0,ea_size); pdata += 4; /* EA info */ -- cgit From c7bc8c52ca7ea4e826dd4bb91a2053e68d6c93df Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jun 2005 06:19:02 +0000 Subject: r7191: Squeezing out more unnecessary memset's gets us up 20% over older code :-). Getting medieval on our ass about memset.... Jeremy. (This used to be commit d0c804bc353afa1712de3885071712af1daffb11) --- source3/smbd/trans2.c | 73 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8c53f0c3ea..77c20310ac 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -858,12 +858,12 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } *pparams = params; - memset((char *)params,'\0',30); SSVAL(params,0,fsp->fnum); SSVAL(params,2,fmode); put_dos_date2(params,4, mtime); SIVAL(params,8, (uint32)size); SSVAL(params,12,rmode); + SSVAL(params,16,0); /* Padding. */ if (oplock_request && lp_fake_oplocks(SNUM(conn))) { smb_action |= EXTENDED_OPLOCK_GRANTED; @@ -875,9 +875,12 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes. */ SIVAL(params,20,inode); + SSVAL(params,24,0); /* Padding. */ if (flags & 8) { uint32 ea_size = estimate_ea_size(conn, fsp, fname); SIVAL(params, 26, ea_size); + } else { + SIVAL(params, 26, 0); } /* Send the required number of replies */ @@ -1164,13 +1167,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - put_dos_date2(p,l1_fdateCreation,cdate); - put_dos_date2(p,l1_fdateLastAccess,adate); - put_dos_date2(p,l1_fdateLastWrite,mdate); - SIVAL(p,l1_cbFile,(uint32)file_size); - SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size); - SSVAL(p,l1_attrFile,mode); - p += l1_achName; + put_dos_date2(p,0,cdate); + put_dos_date2(p,4,adate); + put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 23; nameptr = p; p += align_string(outbuf, p, 0); len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); @@ -1196,17 +1199,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - put_dos_date2(p,l2_fdateCreation,cdate); - put_dos_date2(p,l2_fdateLastAccess,adate); - put_dos_date2(p,l2_fdateLastWrite,mdate); - SIVAL(p,l2_cbFile,(uint32)file_size); - SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); - SSVAL(p,l2_attrFile,mode); + put_dos_date2(p,0,cdate); + put_dos_date2(p,4,adate); + put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); { unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); - SIVAL(p,l2_cbList,ea_size); /* Extended attributes */ + SIVAL(p,22,ea_size); /* Extended attributes */ } - p += l2_achName; + p += 27; nameptr = p - 1; len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN); if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { @@ -1240,13 +1243,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - put_dos_date2(p,l2_fdateCreation,cdate); - put_dos_date2(p,l2_fdateLastAccess,adate); - put_dos_date2(p,l2_fdateLastWrite,mdate); - SIVAL(p,l2_cbFile,(uint32)file_size); - SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); - SSVAL(p,l2_attrFile,mode); - p += l2_cbList; /* p now points to the EA area. */ + put_dos_date2(p,0,cdate); + put_dos_date2(p,4,adate); + put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 22; /* p now points to the EA area. */ file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len); name_list = ea_list_union(name_list, file_list, &ea_len); @@ -1306,19 +1309,24 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, * IMPORTANT as not doing so will trigger * a Win2k client bug. JRA. */ - memset(p,'\0',26); if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); + } SSVAL(p, 0, len); + } else { + memset(p,'\0',26); } p += 2 + 24; len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); @@ -1339,6 +1347,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII); SIVAL(p,0,len); p += 4 + len; + SIVAL(p,0,0); /* Ensure any padding is null. */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); @@ -1366,6 +1375,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(q, 0, len); p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); @@ -1382,6 +1392,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, -4, len); p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); @@ -1411,6 +1422,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q, 0, len); p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); @@ -1439,7 +1451,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, * IMPORTANT as not doing so will trigger * a Win2k client bug. JRA. */ - memset(p,'\0',26); if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); @@ -1447,6 +1458,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); + } + SSVAL(p, 0, len); + } else { + memset(p,'\0',26); } p += 26; SSVAL(p,0,0); p += 2; /* Reserved ? */ @@ -1455,6 +1472,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; SIVAL(pdata,0,len); @@ -1512,6 +1530,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; @@ -1683,7 +1702,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 10); @@ -1938,7 +1956,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 6*SIZEOFWORD); @@ -2841,7 +2858,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_NO_MEMORY); } *pparams = params; - memset((char *)params,'\0',2); + SSVAL(params,0,0); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; pdata = SMB_REALLOC(*ppdata, data_size); if ( pdata == NULL ) { -- cgit From ed5e7ff9f184fd36b4344c958f145cc4a4987c71 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Jun 2005 23:18:52 +0000 Subject: r7200: Don't use memset, use SET_STAT_INVALID (has the same effect). Jeremy. (This used to be commit 0b6f87d5e14da461bd2b1c3a4e6f47a69d2cd1c4) --- source3/smbd/dir.c | 6 +++--- source3/smbd/filename.c | 6 +++--- source3/smbd/notify_hash.c | 2 +- source3/smbd/service.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index d66d1601fb..935ca20195 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -560,7 +560,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT { pstring pathreal; - ZERO_STRUCTP(pst); + SET_STAT_INVALID(pst); if (dptr->has_wild) { return dptr_normal_ReadDirName(dptr, poffset, pst); @@ -629,7 +629,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) { - ZERO_STRUCTP(pst); + SET_STAT_INVALID(pst); if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) { /* This is a singleton directory and we're already at the end. */ @@ -958,7 +958,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); BOOL hide_special = lp_hide_special_files(SNUM(conn)); - ZERO_STRUCTP(pst); + SET_STAT_INVALID(pst); if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) { return True; /* . and .. are always visible. */ diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7191e75715..733001bc91 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -92,7 +92,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen BOOL component_was_mangled = False; BOOL name_has_wildcard = False; - ZERO_STRUCTP(pst); + SET_STAT_INVALID(pst); *dirpath = 0; *bad_path = False; @@ -258,7 +258,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstring rest; /* Stat failed - ensure we don't use it. */ - ZERO_STRUCT(st); + SET_STAT_INVALID(st); *rest = 0; /* @@ -346,7 +346,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if (SMB_VFS_STAT(conn,name, &st) == 0) { *pst = st; } else { - ZERO_STRUCT(st); + SET_STAT_INVALID(st); } } } /* end else */ diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index b16b767783..0464eaa2eb 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -91,7 +91,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, offset = 0; while ((fname = ReadDirName(dp, &offset))) { - ZERO_STRUCT(st); + SET_STAT_INVALID(st); if(strequal(fname, ".") || strequal(fname, "..")) continue; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c63a43bac0..0566dd8102 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -275,7 +275,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *user = 0; fstrcpy(dev, pdev); - ZERO_STRUCT(st); + SET_STAT_INVALD(st); if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { return NULL; -- cgit From 0deab47cc6f17e597430130df66f7acf8842ff30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Jun 2005 05:35:04 +0000 Subject: r7210: Fix my own mistakes up, sorry. Jeremy. (This used to be commit 53c3a954ee0e1c9dc61950f1a9d0a654de9382c6) --- source3/smbd/dir.c | 6 +++--- source3/smbd/filename.c | 2 +- source3/smbd/service.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 935ca20195..f335c60897 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -560,7 +560,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT { pstring pathreal; - SET_STAT_INVALID(pst); + SET_STAT_INVALID(*pst); if (dptr->has_wild) { return dptr_normal_ReadDirName(dptr, poffset, pst); @@ -629,7 +629,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) { - SET_STAT_INVALID(pst); + SET_STAT_INVALID(*pst); if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) { /* This is a singleton directory and we're already at the end. */ @@ -958,7 +958,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); BOOL hide_special = lp_hide_special_files(SNUM(conn)); - SET_STAT_INVALID(pst); + SET_STAT_INVALID(*pst); if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) { return True; /* . and .. are always visible. */ diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 733001bc91..3fb88974fe 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -92,7 +92,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen BOOL component_was_mangled = False; BOOL name_has_wildcard = False; - SET_STAT_INVALID(pst); + SET_STAT_INVALID(*pst); *dirpath = 0; *bad_path = False; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0566dd8102..24f4df7694 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -275,7 +275,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *user = 0; fstrcpy(dev, pdev); - SET_STAT_INVALD(st); + SET_STAT_INVALID(st); if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { return NULL; -- cgit From b6fb04624910964111a1ad90dbe1ebae7981ba6f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Jun 2005 15:21:09 +0000 Subject: r7344: Correctly return if malloc fails. Jeremy, you might want to check this. Thanks, Volker (This used to be commit 560f9d37353f6b886996144215f99e06f2513007) --- source3/smbd/process.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e79686b43e..afde2e94a9 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -116,6 +116,7 @@ static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct t DEBUG(0,("push_message: malloc fail (3)\n")); data_blob_free(&msg->buf); SAFE_FREE(msg); + return False; } } -- cgit From b279ee16e982d419c2205a7f790bd9cb8035d6e5 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 7 Jun 2005 17:52:19 +0000 Subject: r7372: abartet's patch for BUG 2391 (segv caused by free a static pointer) (This used to be commit 4cda2bd035276bd090bf0fbd4e3b2eff657a80cb) --- source3/smbd/sesssetup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 48524b472d..6f963fc603 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -267,8 +267,10 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); + passwd_free(&pw); return ERROR_NT(ret); } + passwd_free(&pw); /* make_server_info_pw does not set the domain. Without this we end up * with the local netbios name in substitutions for %D. */ -- cgit From 04e07e8cc9d6615381e0501cd36cf7d78aeed189 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jun 2005 03:48:40 +0000 Subject: r7385: Rewrite the RPC bind parsing functions to follow the spec. I haven't yet tested this so I may have screwed this up - however it now follows the DCE spec. valgrinded tests to follow.... Jeremy. (This used to be commit 877e0a61f5821c89149b1403d08675dd7db8039e) --- source3/smbd/notify_kernel.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index b2ccfc2796..6d1f550241 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -217,7 +217,6 @@ struct cnotify_fns *kernel_notify_init(void) ZERO_STRUCT(act); - act.sa_handler = NULL; act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; sigemptyset( &act.sa_mask ); -- cgit From 377f947930f3a3fe69c21d5b9386642cbf8b3df7 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 8 Jun 2005 14:23:49 +0000 Subject: r7395: * new feature 'map to guest = bad uid' (based on patch from aruna.prabakar@hp.com). This re-enables the Samba 2.2 behavior where a user that was successfully authenticated by a remote DC would be mapped to the guest account if there was not existing UNIX account for that user and we could not create one. (This used to be commit b7455fbf81f4e47c087c861f70d492a328730a9b) --- source3/smbd/sesssetup.c | 55 ++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 6f963fc603..5808de9788 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -144,7 +144,7 @@ static int reply_spnego_kerberos(connection_struct *conn, char *client, *p, *domain; fstring netbios_domain_name; struct passwd *pw; - char *user; + fstring user; int sess_vuid; NTSTATUS ret; DATA_BLOB auth_data; @@ -154,6 +154,7 @@ static int reply_spnego_kerberos(connection_struct *conn, uint8 tok_id[2]; DATA_BLOB nullblob = data_blob(NULL, 0); fstring real_username; + BOOL map_domainuser_to_guest = False; ZERO_STRUCT(ticket); ZERO_STRUCT(auth_data); @@ -238,37 +239,52 @@ static int reply_spnego_kerberos(connection_struct *conn, } } - asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client); + fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client); /* lookup the passwd struct, create a new user if necessary */ map_username( user ); pw = smb_getpwnam( user, real_username, True ); - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n",user)); - SAFE_FREE(user); - SAFE_FREE(client); - data_blob_free(&ap_rep); - data_blob_free(&session_key); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + + /* this was originally the behavior of Samba 2.2, if a user + did not have a local uid but has been authenticated, then + map them to a guest account */ + + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ + map_domainuser_to_guest = True; + fstrcpy(user,lp_guestaccount()); + pw = smb_getpwnam( user, real_username, True ); + } + + /* extra sanity check that the guest account is valid */ + + if ( !pw ) { + DEBUG(1,("Username %s is invalid on this system\n", user)); + SAFE_FREE(client); + data_blob_free(&ap_rep); + data_blob_free(&session_key); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } } /* setup the string used by %U */ sub_set_smb_name( real_username ); reload_services(True); - - if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) - { - DEBUG(1,("make_server_info_from_pw failed!\n")); - SAFE_FREE(user); - SAFE_FREE(client); - data_blob_free(&ap_rep); - data_blob_free(&session_key); - passwd_free(&pw); - return ERROR_NT(ret); + if ( map_domainuser_to_guest ) { + make_server_info_guest(&server_info); + } else { + ret = make_server_info_pw(&server_info, real_username, pw); + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(1,("make_server_info_from_pw failed!\n")); + SAFE_FREE(client); + data_blob_free(&ap_rep); + data_blob_free(&session_key); + passwd_free(&pw); + return ERROR_NT(ret); + } } passwd_free(&pw); @@ -284,7 +300,6 @@ static int reply_spnego_kerberos(connection_struct *conn, A better interface would copy it.... */ sess_vuid = register_vuid(server_info, session_key, nullblob, client); - SAFE_FREE(user); SAFE_FREE(client); if (sess_vuid == -1) { -- cgit From dacdfbc98ccb533626058745f4aacef0b0b36286 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 8 Jun 2005 14:57:37 +0000 Subject: r7398: commiting abartlet's patch for kerberos authentication when using a keytab and security != ads (This used to be commit 3faaa5c3eb3b2057984586e069a47cb210c99140) --- source3/smbd/negprot.c | 13 ++++++++----- source3/smbd/sesssetup.c | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 054afac683..d4f0167a5f 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -178,7 +178,6 @@ static int negprot_spnego(char *p) OID_NTLMSSP, NULL}; const char *OIDs_plain[] = {OID_NTLMSSP, NULL}; - char *principal; int len; global_spnego_negotiated = True; @@ -211,12 +210,16 @@ static int negprot_spnego(char *p) return 16; } #endif - if (lp_security() != SEC_ADS) { + if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); } else { - asprintf(&principal, "%s$@%s", guid, lp_realm()); - blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal); - free(principal); + fstring myname; + char *host_princ_s = NULL; + name_to_fqdn(myname, global_myname()); + strlower_m(myname); + asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm()); + blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s); + SAFE_FREE(host_princ_s); } memcpy(p, blob.data, blob.length); len = blob.length; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 5808de9788..3b33db24e8 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -468,7 +468,7 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if (got_kerberos_mechanism && (SEC_ADS == lp_security())) { + if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { int ret = reply_spnego_kerberos(conn, inbuf, outbuf, length, bufsize, &secblob); data_blob_free(&secblob); -- cgit From 66bb4f03c3466205488f72e4878e8801c5bbb295 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jun 2005 20:52:42 +0000 Subject: r7412: Now we're not memset'ing ensure we're valgrind clean. Jeremy. (This used to be commit 0d303ab2f30f6047fc3f2f6fc4916e93704959d2) --- source3/smbd/trans2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 77c20310ac..ebb46a23b2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3094,6 +3094,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,mode); + SIVAL(pdata,36,0); /* padding. */ pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); -- cgit From 129b461673ecd0ad4d16c0c99585dd5c067172df Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 9 Jun 2005 15:20:11 +0000 Subject: r7440: * merge registry server changes from trunk (so far) for more printmig.exe work * merge the sys_select_signal(char c) change from trunk in order to keeo the winbind code in sync (This used to be commit a112c5570a7f8ddddde1af0fa665f40a6067e8cf) --- source3/smbd/notify_kernel.c | 2 +- source3/smbd/oplock_linux.c | 2 +- source3/smbd/server.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 6d1f550241..02abe0b4b6 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -74,7 +74,7 @@ static void signal_handler(int sig, siginfo_t *info, void *unused) fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd; signals_received++; } /* Else signal is lost. */ - sys_select_signal(); + sys_select_signal(RT_SIGNAL_NOTIFY); } /**************************************************************************** diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 6d1bc64ce1..78dc260939 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -72,7 +72,7 @@ static void signal_handler(int sig, siginfo_t *info, void *unused) fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd; signals_received++; } /* Else signal is lost. */ - sys_select_signal(); + sys_select_signal(RT_SIGNAL_LEASE); } /**************************************************************************** diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 301534d750..01515a5726 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -66,7 +66,7 @@ static void smbd_set_server_fd(int fd) static void sig_term(void) { got_sig_term = 1; - sys_select_signal(); + sys_select_signal(SIGTERM); } /**************************************************************************** @@ -76,7 +76,7 @@ static void sig_term(void) static void sig_hup(int sig) { reload_after_sighup = 1; - sys_select_signal(); + sys_select_signal(SIGHUP); } /**************************************************************************** -- cgit From db0b2f9ebe947a244ee4ec493e489d928ed5cb63 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Jun 2005 18:15:23 +0000 Subject: r7447: Sync up a little between HEAD and 3.0 in preparation for moving the AIO code across. Jeremy. (This used to be commit e9604e65f4337a4163398f1f2c71e13da7993ed4) --- source3/smbd/reply.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1c2e950836..f97bedef9b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2569,6 +2569,14 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_DOS(ERRDOS,ERRlock); } +#if 0 + /* Enable when the AIO code is moved over. JRA. */ + if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) { + END_PROFILE(SMBreadX); + return -1; + } +#endif + nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); if (nread != -1) nread = chain_reply(inbuf,outbuf,length,bufsize); @@ -2642,6 +2650,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SCVAL(outbuf,smb_com,SMBwritebraw); SSVALS(outbuf,smb_vwv0,-1); outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_writebraw: send_smb failed."); @@ -2886,9 +2895,12 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); + set_message(outbuf,6,0,True); + /* Deal with possible LARGE_WRITEX */ - if (large_writeX) + if (large_writeX) { numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); + } if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { END_PROFILE(SMBwriteX); @@ -2930,18 +2942,28 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng done, just a write of zero. To truncate a file, use SMBwrite. */ - if(numtowrite == 0) + if(numtowrite == 0) { nwritten = 0; - else + } else { + +#if 0 + /* Enable when AIO code is moved over. JRA. */ + + if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize, + fsp,data,startpos,numtowrite)) { + END_PROFILE(SMBwriteX); + return -1; + } +#endif + nwritten = write_file(fsp,data,startpos,numtowrite); + } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwriteX); return(UNIXERROR(ERRHRD,ERRdiskfull)); } - set_message(outbuf,6,0,True); - SSVAL(outbuf,smb_vwv2,nwritten); if (large_writeX) SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); @@ -3375,6 +3397,7 @@ int reply_echo(connection_struct *conn, smb_setlen(outbuf,outsize - 4); + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_echo: send_smb failed."); } @@ -5173,6 +5196,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, SSVAL(outbuf,smb_vwv6,nread); SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_readbmpx: send_smb failed."); @@ -5333,6 +5357,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, if (write_through && tcount==nwritten) { /* We need to send both a primary and a secondary response */ smb_setlen(outbuf,outsize - 4); + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_writebmpx: send_smb failed."); -- cgit From 6d39f3bdce5ba8ed7d88a430a2de9f96d4b2c513 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Jun 2005 00:31:59 +0000 Subject: r7452: Set sparse flag if needed. Based on code from jpeach@sgi.com. Fixes bug #2774. Jeremy. (This used to be commit 5d366047debed68f36d44d34233ba4670e412d1e) --- source3/smbd/dosmode.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 65ea2807e7..3602e3f908 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -20,6 +20,16 @@ #include "includes.h" +static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf) +{ +#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) + if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) { + return FILE_ATTRIBUTE_SPARSE; + } +#endif + return 0; +} + /**************************************************************************** Change a dos mode to a unix mode. Base permission for files: @@ -140,11 +150,7 @@ uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_ if (S_ISDIR(sbuf->st_mode)) result = aDIR | (result & aRONLY); -#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) { - result |= FILE_ATTRIBUTE_SPARSE; - } -#endif + result |= set_sparse_flag(sbuf); #ifdef S_ISLNK #if LINKS_READ_ONLY @@ -293,6 +299,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) /* Get the DOS attributes from an EA by preference. */ if (get_ea_dos_attribute(conn, path, sbuf, &result)) { + result |= set_sparse_flag(sbuf); return result; } -- cgit From c3fedee2a67966e4640b26dd084e75125e58f55c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Jun 2005 23:13:25 +0000 Subject: r7474: A *foul* and *disgusting* hack to ensure that, at the very lowest level, . and .. are the first two entries returned when reading a directory. This also means we can't seek to these offsets, but we will never be doing that anyway (as far as I can think). The reason we have to do this is that the NT4 explorer will happily display a folder marked ".." as a clickable folder (and probably would display "." as a clickable folder too) if these are not in positions zero and one of the returned file list. W2K seems to have fixed this but there are too many older systems out there... Never mind, more for the "Undocumented CIFS talk", coming to a CIFS2005 conference near you soon.... :-). Jeremy. (This used to be commit 7b6e907922b7d98abe4430ea73712a9c6419ea08) --- source3/smbd/dir.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f335c60897..b9c6cf8797 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -42,6 +42,7 @@ struct smb_Dir { char *dir_path; struct name_cache_entry *name_cache; unsigned int name_cache_index; + unsigned int file_number; }; struct dptr_struct { @@ -1074,15 +1075,35 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) const char *n; connection_struct *conn = dirp->conn; - SeekDir(dirp, *poffset); + /* Cheat to allow . and .. to be the first entries returned. */ + if ((*poffset == 0) && (dirp->file_number < 2)) { + if (dirp->file_number == 0) { + n = "."; + } else { + n = ".."; + } + dirp->file_number++; + return n; + } else { + /* A real offset, seek to it. */ + SeekDir(dirp, *poffset); + } + while ((n = vfs_readdirname(conn, dirp->dir))) { struct name_cache_entry *e; + /* Ignore . and .. - we've already returned them. */ + if (*n == '.') { + if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) { + continue; + } + } dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; e = &dirp->name_cache[dirp->name_cache_index]; SAFE_FREE(e->name); e->name = SMB_STRDUP(n); *poffset = e->offset= dirp->offset; + dirp->file_number++; return e->name; } dirp->offset = -1; @@ -1141,6 +1162,7 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) /* Not found in the name cache. Rewind directory and start from scratch. */ SMB_VFS_REWINDDIR(conn, dirp->dir); + dirp->file_number = 0; *poffset = 0; while ((entry = ReadDirName(dirp, poffset))) { if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { -- cgit From a59149b86a36cd8b51ad5ae11b4d2b0714bb5e9c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Jun 2005 20:42:21 +0000 Subject: r7550: Steal the correct error return for invalid TID on NTcreateX from Samba4 (thanks tridge !). Jeremy. (This used to be commit 0288823aacdbec6ba99e944c9f06f051e55c64b8) --- source3/smbd/process.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index afde2e94a9..0373cd471c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -936,8 +936,14 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize change_to_root_user(); /* does this protocol need a valid tree connection? */ - if ((flags & AS_USER) && !conn) - return ERROR_DOS(ERRSRV, ERRinvnid); + if ((flags & AS_USER) && !conn) { + /* Amazingly, the error code depends on the command (from Samba4). */ + if (type == SMBntcreateX) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } else { + return ERROR_DOS(ERRSRV, ERRinvnid); + } + } /* does this protocol need to be run as the connected user? */ -- cgit From d559edcce23ada96c4a788c3dbeb66c2890db054 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 14 Jun 2005 03:17:31 +0000 Subject: r7563: svcctl patches from Marcin; have cleaned up formating and am checking the code in to snapshot it before I start changing more things (This used to be commit 560ce111ce8de37d02bce64d2ca60a5f471d5477) --- source3/smbd/server.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 01515a5726..e3d6448240 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -887,6 +887,9 @@ void build_options(BOOL screen); if (!init_registry()) exit(1); + if (!init_svcctl_db()) + exit(1); + if (!print_backend_init()) exit(1); -- cgit From 741b0a97bbf3e2f7ed3292b9508b39edb00d97c1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Jun 2005 18:37:34 +0000 Subject: r7617: Fix for bug #2801 - delete veto files was broken with the new large directory code. Jeremy. (This used to be commit f397cc08b5628913af4d7f9c2c6d20c778e5d8ca) --- source3/smbd/dir.c | 18 +++++++++++++++++- source3/smbd/reply.c | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index b9c6cf8797..072f396b8c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1110,6 +1110,18 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) return NULL; } +/******************************************************************* + Rewind to the start. +********************************************************************/ + +void RewindDir(struct smb_Dir *dirp, long *poffset) +{ + SMB_VFS_REWINDDIR(dirp->conn, dirp->dir); + dirp->file_number = 0; + dirp->offset = 0; + *poffset = 0; +} + /******************************************************************* Seek a dir. ********************************************************************/ @@ -1117,7 +1129,11 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) void SeekDir(struct smb_Dir *dirp, long offset) { if (offset != dirp->offset) { - SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); + if (offset == 0) { + RewindDir(dirp, &offset); + } else { + SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); + } dirp->offset = offset; } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f97bedef9b..c9adbf8fcf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3768,7 +3768,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) struct smb_Dir *dir_hnd = OpenDir(conn, directory); if(dir_hnd != NULL) { - long dirpos = TellDir(dir_hnd); + long dirpos = 0; while ((dname = ReadDirName(dir_hnd,&dirpos))) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; @@ -3781,7 +3781,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) } if(all_veto_files) { - SeekDir(dir_hnd,dirpos); + RewindDir(dir_hnd); while ((dname = ReadDirName(dir_hnd,&dirpos))) { pstring fullname; -- cgit From df4f8fc1c67e9d967f712ecd18d08035469a7a49 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Jun 2005 18:49:43 +0000 Subject: r7618: Typo... Jeremy. (This used to be commit 65d1365700588949fc5576c7dd525fc530a15ff4) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c9adbf8fcf..95de3a3469 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3781,7 +3781,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) } if(all_veto_files) { - RewindDir(dir_hnd); + RewindDir(dir_hnd,&dirpos); while ((dname = ReadDirName(dir_hnd,&dirpos))) { pstring fullname; -- cgit From e9e00ee9c2e6dad86d57a858e71caf2066070c8f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 15 Jun 2005 19:28:14 +0000 Subject: r7620: when adding a new printer driver, we should copy the files (not move) to the W32X86/{2,3}/ directory. Printmig.exe copies the driver files for all drivers to print$/W32X86 and the calls AddPrinterDriver() for each driver. If we move the file, then adding a driver which shares a file with a previous driver will fail. I can now restore drivers in bulk to a Samba 3 server. (This used to be commit 46cd95c9b48a00a51139d3654352d4399b774a9b) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 95de3a3469..d49823bea5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4482,7 +4482,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Copy a file as part of a reply_copy. ******************************************************************/ -static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, +BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory, int *err_ret) { int Access,action; -- cgit From b162a396fecb08cc02addf17aed30fbc5e813f5b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 16 Jun 2005 00:46:43 +0000 Subject: r7624: * removed unmatched tdb_lock_by_string() call (should fix build farm issues) * comment out services.tdb code until I finish rewriting it (This used to be commit 707b7822286a6c7e9d1e4ca3d15b99c976f6e704) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e3d6448240..b40a8267cc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -887,8 +887,10 @@ void build_options(BOOL screen); if (!init_registry()) exit(1); +#if 0 if (!init_svcctl_db()) exit(1); +#endif if (!print_backend_init()) exit(1); -- cgit From d9e12b4df7fb8081190910ae25e98d379acda13d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Jun 2005 01:02:11 +0000 Subject: r7662: Allow someone with SeTakeOwnershipPrivilege to chown the user of a file to themself. Jeremy. (This used to be commit f3319e224db8f79baa10413e0e2a96d2bc871f38) --- source3/smbd/posix_acls.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b5ac2e8241..796587c94c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2926,7 +2926,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) Try to chown a file. We will be able to chown it under the following conditions. 1) If we have root privileges, then it will just work. - 2) If we have write permission to the file and dos_filemodes is set + 2) If we have SeTakeOwnershipPrivilege we can change the user to the current user. + 3) If we have write permission to the file and dos_filemodes is set then allow chown to the currently authenticated user. ****************************************************************************/ @@ -2935,21 +2936,40 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ int ret; files_struct *fsp; SMB_STRUCT_STAT st; + SE_PRIV se_take_ownership = SE_TAKE_OWNERSHIP; + if(!CAN_WRITE(conn)) { + return -1; + } + + /* Case (1). */ /* try the direct way first */ ret = SMB_VFS_CHOWN(conn, fname, uid, gid); if (ret == 0) return 0; - if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) + /* Case (2). */ + if ((uid == current_user.uid) && (user_has_privileges(current_user.nt_user_token,&se_take_ownership))) { + become_root(); + /* Keep the current file gid the same - take ownership doesn't imply group change. */ + ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1); + unbecome_root(); + return ret; + } + + /* Case (3). */ + if (!lp_dos_filemode(SNUM(conn))) { return -1; + } - if (SMB_VFS_STAT(conn,fname,&st)) + if (SMB_VFS_STAT(conn,fname,&st)) { return -1; + } fsp = open_file_fchmod(conn,fname,&st); - if (!fsp) + if (!fsp) { return -1; + } /* only allow chown to the current user. This is more secure, and also copes with the case where the SID in a take ownership ACL is @@ -3017,15 +3037,17 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) + if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) { return False; + } /* * Do we need to chown ? */ - if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) + if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) { need_chown = True; + } /* * Chown before setting ACL only if we don't change the user, or -- cgit From a5808e7ddbe3d333057c44db5e76bf8ef032489a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Jun 2005 15:54:10 +0000 Subject: r7693: Fix from James Peach @ SGI for null pointer ACL free. Jeremy. (This used to be commit 000477943c3dd41fd44f2aef3755aa603ba5d595) --- source3/smbd/posix_acls.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 796587c94c..a3174440ef 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2949,7 +2949,9 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ return 0; /* Case (2). */ - if ((uid == current_user.uid) && (user_has_privileges(current_user.nt_user_token,&se_take_ownership))) { + if (lp_enable_privileges() && + (uid == current_user.uid) && + (user_has_privileges(current_user.nt_user_token,&se_take_ownership))) { become_root(); /* Keep the current file gid the same - take ownership doesn't imply group change. */ ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1); @@ -3970,7 +3972,9 @@ failed to match on user or group in token (ret = %d).\n", fname, ret )); done: - SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + if (posix_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + } DEBUG(10,("check_posix_acl_group_write: file %s returning (ret = %d).\n", fname, ret )); return ret; -- cgit From ea41eedc20a9fbd19e69f0de6e9b1bd32b0e7a57 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Jun 2005 05:18:09 +0000 Subject: r7796: Prepare for client setting capabilities to select posix pathnames on the wire. Jerry do not merge this please. New SMB_SET_FS_INFO - level 0x200 as was discussed on the mailing list. Jeremy. (This used to be commit 55029b1a0c9ae5b941eecd699dd905ea3d42b99c) --- source3/smbd/trans2.c | 67 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ebb46a23b2..a504ce9010 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2433,7 +2433,7 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb ZERO_STRUCT(quotas); - DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn)))); + DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn)))); /* access check */ if ((current_user.uid != 0)||!CAN_WRITE(conn)) { @@ -2449,25 +2449,54 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = file_fsp(params,0); - - if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { - DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); - return ERROR_NT(NT_STATUS_INVALID_HANDLE); - } - info_level = SVAL(params,2); switch(info_level) { + case SMB_SET_CIFS_UNIX_INFO: + { + uint16 client_unix_major; + uint16 client_unix_minor; + uint32 client_unix_cap_low; + uint32 client_unix_cap_high; + + if (!lp_unix_extensions()) { + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* There should be 12 bytes of capabilities set. */ + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + client_unix_major = SVAL(pdata,0); + client_unix_minor = SVAL(pdata,2); + client_unix_cap_low = IVAL(pdata,4); + client_unix_cap_high = IVAL(pdata,8); + /* Just print these values for now. */ + DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u\ +cap_low = 0x%x, cap_high = 0x%x\n", + (unsigned int)client_unix_major, + (unsigned int)client_unix_minor, + (unsigned int)client_unix_cap_low, + (unsigned int)client_unix_cap_high )); + + outsize = set_message(outbuf,0,0,True); + break; + } case SMB_FS_QUOTA_INFORMATION: /* note: normaly there're 48 bytes, * but we didn't use the last 6 bytes for now * --metze */ + fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + if (total_data < 42) { DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n", total_data)); - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } /* unknown_1 24 NULL bytes in pdata*/ @@ -2481,7 +2510,7 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb ((quotas.softlim != 0xFFFFFFFF)|| (IVAL(pdata,28)!=0xFFFFFFFF))) { /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } #endif /* LARGE_SMB_OFF_T */ @@ -2494,7 +2523,7 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb ((quotas.hardlim != 0xFFFFFFFF)|| (IVAL(pdata,36)!=0xFFFFFFFF))) { /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } #endif /* LARGE_SMB_OFF_T */ @@ -2509,6 +2538,14 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb return ERROR_DOS(ERRSRV,ERRerror); } + /* + * sending this reply works fine, + * but I'm not sure it's the same + * like windows do... + * --metze + */ + outsize = set_message(outbuf,10,0,True); + break; default: DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n", @@ -2517,14 +2554,6 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb break; } - /* - * sending this reply works fine, - * but I'm not sure it's the same - * like windows do... - * --metze - */ - outsize = set_message(outbuf,10,0,True); - return outsize; } -- cgit From bf28978a70b9abbfb09b44325c712d110b590a33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Jun 2005 05:27:02 +0000 Subject: r7798: CIFSFS client assumes wcnt == 10 for successful trans2 reply. Jeremy. (This used to be commit aea58e6bb60565430aec69598c47b2a8f4667e89) --- source3/smbd/trans2.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a504ce9010..cfe9a2fbdd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2479,7 +2479,6 @@ cap_low = 0x%x, cap_high = 0x%x\n", (unsigned int)client_unix_cap_low, (unsigned int)client_unix_cap_high )); - outsize = set_message(outbuf,0,0,True); break; } case SMB_FS_QUOTA_INFORMATION: @@ -2538,14 +2537,6 @@ cap_low = 0x%x, cap_high = 0x%x\n", return ERROR_DOS(ERRSRV,ERRerror); } - /* - * sending this reply works fine, - * but I'm not sure it's the same - * like windows do... - * --metze - */ - outsize = set_message(outbuf,10,0,True); - break; default: DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n", @@ -2554,6 +2545,14 @@ cap_low = 0x%x, cap_high = 0x%x\n", break; } + /* + * sending this reply works fine, + * but I'm not sure it's the same + * like windows do... + * --metze + */ + outsize = set_message(outbuf,10,0,True); + return outsize; } -- cgit From e9d3cc656f6f5240d8bda460f776f8c872b91424 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Jun 2005 21:26:29 +0000 Subject: r7821: Don't check permissions for setting POSIX pathname request. Jeremy. (This used to be commit 06b40024f3784778a81ae7c69881a516d183a1c3) --- source3/smbd/trans2.c | 109 ++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cfe9a2fbdd..98f4de2bf9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2426,22 +2426,11 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb { char *pdata = *ppdata; char *params = *pparams; - files_struct *fsp = NULL; uint16 info_level; int outsize; - SMB_NTQUOTA_STRUCT quotas; - - ZERO_STRUCT(quotas); DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn)))); - /* access check */ - if ((current_user.uid != 0)||!CAN_WRITE(conn)) { - DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", - lp_servicename(SNUM(conn)),conn->user)); - return ERROR_DOS(ERRSRV,ERRaccess); - } - /* */ if (total_params < 4) { DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n", @@ -2482,62 +2471,76 @@ cap_low = 0x%x, cap_high = 0x%x\n", break; } case SMB_FS_QUOTA_INFORMATION: - /* note: normaly there're 48 bytes, - * but we didn't use the last 6 bytes for now - * --metze - */ - fsp = file_fsp(params,0); - if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { - DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); - return ERROR_NT(NT_STATUS_INVALID_HANDLE); - } + { + files_struct *fsp = NULL; + SMB_NTQUOTA_STRUCT quotas; + + ZERO_STRUCT(quotas); - if (total_data < 42) { - DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n", - total_data)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } + /* access check */ + if ((current_user.uid != 0)||!CAN_WRITE(conn)) { + DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); + return ERROR_DOS(ERRSRV,ERRaccess); + } + + /* note: normaly there're 48 bytes, + * but we didn't use the last 6 bytes for now + * --metze + */ + fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + if (total_data < 42) { + DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n", + total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } - /* unknown_1 24 NULL bytes in pdata*/ + /* unknown_1 24 NULL bytes in pdata*/ - /* the soft quotas 8 bytes (SMB_BIG_UINT)*/ - quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24); + /* the soft quotas 8 bytes (SMB_BIG_UINT)*/ + quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24); #ifdef LARGE_SMB_OFF_T - quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32); + quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32); #else /* LARGE_SMB_OFF_T */ - if ((IVAL(pdata,28) != 0)&& - ((quotas.softlim != 0xFFFFFFFF)|| - (IVAL(pdata,28)!=0xFFFFFFFF))) { - /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } + if ((IVAL(pdata,28) != 0)&& + ((quotas.softlim != 0xFFFFFFFF)|| + (IVAL(pdata,28)!=0xFFFFFFFF))) { + /* more than 32 bits? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #endif /* LARGE_SMB_OFF_T */ - /* the hard quotas 8 bytes (SMB_BIG_UINT)*/ - quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32); + /* the hard quotas 8 bytes (SMB_BIG_UINT)*/ + quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32); #ifdef LARGE_SMB_OFF_T - quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32); + quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32); #else /* LARGE_SMB_OFF_T */ - if ((IVAL(pdata,36) != 0)&& - ((quotas.hardlim != 0xFFFFFFFF)|| - (IVAL(pdata,36)!=0xFFFFFFFF))) { - /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } + if ((IVAL(pdata,36) != 0)&& + ((quotas.hardlim != 0xFFFFFFFF)|| + (IVAL(pdata,36)!=0xFFFFFFFF))) { + /* more than 32 bits? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #endif /* LARGE_SMB_OFF_T */ - /* quota_flags 2 bytes **/ - quotas.qflags = SVAL(pdata,40); + /* quota_flags 2 bytes **/ + quotas.qflags = SVAL(pdata,40); - /* unknown_2 6 NULL bytes follow*/ + /* unknown_2 6 NULL bytes follow*/ - /* now set the quotas */ - if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { - DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); - return ERROR_DOS(ERRSRV,ERRerror); - } + /* now set the quotas */ + if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { + DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); + return ERROR_DOS(ERRSRV,ERRerror); + } - break; + break; + } default: DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n", info_level)); -- cgit From 7e509e9b99a18495bde01a990e37de70bae35aac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Jun 2005 21:20:41 +0000 Subject: r7842: With the patch I sent Steve yesterday this gives us complete POSIX pathnames. ie. files containing : and \ can be accessed from Linux. Jeremy. (This used to be commit e9b8d23d6138d909a65ea70b2e801881e8333b38) --- source3/smbd/dir.c | 2 +- source3/smbd/mangle.c | 10 +++++++++- source3/smbd/mangle_hash2.c | 39 +++++++++++++++++++++++++++++++++++++++ source3/smbd/nttrans.c | 3 +++ source3/smbd/reply.c | 12 +++++++++++- source3/smbd/trans2.c | 8 ++++++-- 6 files changed, 69 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 072f396b8c..ae21e16e31 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -238,7 +238,7 @@ BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr) dptr->wcard = SMB_STRDUP(wcard); if (!dptr->wcard) return False; - if (wcard[0] == '.' && wcard[1] == 0) { + if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { dptr->has_wild = True; } else { dptr->has_wild = ms_has_wild(wcard); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index afc1ca12f0..ed69a6210e 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -29,6 +29,7 @@ static const struct { } mangle_backends[] = { { "hash", mangle_hash_init }, { "hash2", mangle_hash2_init }, + { "posix", posix_mangle_init }, /*{ "tdb", mangle_tdb_init }, */ { NULL, NULL } }; @@ -39,7 +40,7 @@ static const struct { static void mangle_init(void) { int i; - char *method; + const char *method; if (mangle_fns) return; @@ -70,6 +71,13 @@ void mangle_reset_cache(void) mangle_fns->reset(); } +void mangle_change_to_posix(void) +{ + mangle_fns = NULL; + lp_set_mangling_method("posix"); + mangle_reset_cache(); +} + /* see if a filename has come out of our mangling code */ diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 4325c07f58..e44aaf17e7 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -716,3 +716,42 @@ struct mangle_fns *mangle_hash2_init(void) return &mangle_fns; } + +static void posix_mangle_reset(void) +{;} + +static BOOL posix_is_mangled(const char *s, int snum) +{ + return False; +} + +static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum) +{ + return False; +} + +static BOOL posix_check_cache( char *s, size_t maxlen, int snum ) +{ + return False; +} + +static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum) +{ + if (need83) { + memset(OutName, '\0', 13); + } +} + +/* POSIX paths backend - no mangle. */ +static struct mangle_fns posix_mangle_fns = { + posix_mangle_reset, + posix_is_mangled, + posix_is_8_3, + posix_check_cache, + posix_name_map +}; + +struct mangle_fns *posix_mangle_init(void) +{ + return &posix_mangle_fns; +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a0f94d616d..cc37d531f2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -267,6 +267,9 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e BOOL is_ntfs_stream_name(const char *fname) { + if (lp_posix_pathnames()) { + return False; + } return (strchr_m(fname, ':') != NULL) ? True : False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d49823bea5..99e0d5d9a1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -398,7 +398,9 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } else { ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); } - if (allow_wcard_names) { + if (lp_posix_pathnames()) { + *err = check_path_syntax_posix(dest, tmppath); + } else if (allow_wcard_names) { *err = check_path_syntax_wcard(dest, tmppath); } else { *err = check_path_syntax(dest, tmppath); @@ -1032,6 +1034,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size NTSTATUS nt_status; BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; + if (lp_posix_pathnames()) { + return reply_unknown(inbuf, outbuf); + } + START_PROFILE(SMBsearch); *mask = *directory = *fname = 0; @@ -1228,6 +1234,10 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size char *p; NTSTATUS err; + if (lp_posix_pathnames()) { + return reply_unknown(inbuf, outbuf); + } + START_PROFILE(SMBfclose); outsize = set_message(outbuf,1,0,True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 98f4de2bf9..978afa6d74 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2390,7 +2390,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned data_len = 12; SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); - SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */ + SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP| + CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */ break; case SMB_MAC_QUERY_FS_INFO: @@ -2461,13 +2462,16 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb client_unix_cap_low = IVAL(pdata,4); client_unix_cap_high = IVAL(pdata,8); /* Just print these values for now. */ - DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u\ + DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \ cap_low = 0x%x, cap_high = 0x%x\n", (unsigned int)client_unix_major, (unsigned int)client_unix_minor, (unsigned int)client_unix_cap_low, (unsigned int)client_unix_cap_high )); + /* Here is where we must switch to posix pathname processing... */ + lp_set_posix_pathnames(); + mangle_change_to_posix(); break; } case SMB_FS_QUOTA_INFORMATION: -- cgit From 81ee9412854fe57124144a1337f2e6680d1afd80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Jun 2005 17:00:11 +0000 Subject: r7846: Fix from bugzilla@kevinjamieson.com Kevin Jamieson - typo in checking for .. in statcache. Bugid #2819. Jeremy. (This used to be commit a5619d717954ad2a3ffaa549b11bfa738720e325) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8e22d9687b..97ecd4152c 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -64,7 +64,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && ((full_orig_name[1] == '\0') || - (full_orig_name[1] == '.' && full_orig_name[1] == '\0')))) + (full_orig_name[1] == '.' && full_orig_name[2] == '\0')))) return; /* -- cgit From 19ca97a70f6b7b41d251eaa76e4d3c980c6eedff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 24 Jun 2005 20:25:18 +0000 Subject: r7882: Looks like a large patch - but what it actually does is make Samba safe for using our headers and linking with C++ modules. Stops us from using C++ reserved keywords in our code. Jeremy (This used to be commit 9506b8e145982b1160a2f0aee5c9b7a54980940a) --- source3/smbd/chgpasswd.c | 4 ++-- source3/smbd/conn.c | 2 +- source3/smbd/fileio.c | 2 +- source3/smbd/ipc.c | 2 +- source3/smbd/password.c | 4 ++-- source3/smbd/process.c | 10 +++++----- source3/smbd/sesssetup.c | 2 +- source3/smbd/vfs-wrap.c | 6 +++--- 8 files changed, 16 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d0e0f6e143..56e5727b7d 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -970,8 +970,8 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) return True; } - dump_data(100, new_nt_p16, NT_HASH_LEN); - dump_data(100, pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen); + dump_data(100, (const char *)new_nt_p16, NT_HASH_LEN); + dump_data(100, (const char *)pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen); memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN); for (i=0; ioffset = 0; wcp->alloc_size = alloc_size; wcp->data_size = 0; - if((wcp->data = SMB_MALLOC(wcp->alloc_size)) == NULL) { + if((wcp->data = (char *)SMB_MALLOC(wcp->alloc_size)) == NULL) { DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", (unsigned int)wcp->alloc_size )); SAFE_FREE(wcp); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e3f6521fba..86c6d056a0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -163,7 +163,7 @@ void send_trans_reply(char *outbuf, static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p) { BOOL is_data_outstanding; - char *rdata = SMB_MALLOC(p->max_trans_reply); + char *rdata = (char *)SMB_MALLOC(p->max_trans_reply); int data_len; if(rdata == NULL) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 213ef98ea3..2ee8c1232e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -168,7 +168,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, vuser->n_groups = server_info->n_groups; if (vuser->n_groups) { - if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { + if (!(vuser->groups = (gid_t *)memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { DEBUG(0,("register_vuid: failed to memdup vuser->groups\n")); data_blob_free(&session_key); free(vuser); @@ -316,7 +316,7 @@ void add_session_user(const char *user) DEBUG(3,("add_session_user: session userlist already too large.\n")); return; } - newlist = SMB_REALLOC( session_userlist, len_session_userlist + PSTRING_LEN ); + newlist = (char *)SMB_REALLOC( session_userlist, len_session_userlist + PSTRING_LEN ); if( newlist == NULL ) { DEBUG(1,("Unable to resize session_userlist\n")); return; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0373cd471c..1ec176bd08 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -87,7 +87,7 @@ static void free_queued_message(struct pending_message_list *msg) for processing. ****************************************************************************/ -static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private, size_t private_len) +static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private_data, size_t private_len) { struct pending_message_list *tmp_msg; struct pending_message_list *msg = SMB_MALLOC_P(struct pending_message_list); @@ -110,8 +110,8 @@ static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct t msg->msg_time = *ptv; } - if (private) { - msg->private_data = data_blob(private, private_len); + if (private_data) { + msg->private_data = data_blob(private_data, private_len); if (msg->private_data.data == NULL) { DEBUG(0,("push_message: malloc fail (3)\n")); data_blob_free(&msg->buf); @@ -249,7 +249,7 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) for processing. ****************************************************************************/ -BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, size_t priv_len) +BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private_data, size_t priv_len) { uint16 mid = SVAL(InBuffer,smb_mid); struct timeval tv; @@ -275,7 +275,7 @@ BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec)); return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer, - smb_len(InBuffer)+4, &tv, private, priv_len); + smb_len(InBuffer)+4, &tv, private_data, priv_len); } /**************************************************************************** diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3b33db24e8..95fe571cff 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -223,7 +223,7 @@ static int reply_spnego_kerberos(connection_struct *conn, fstrcpy(wb_request.domain_name, domain); - wb_result = winbindd_request(WINBINDD_DOMAIN_INFO, + wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO, &wb_request, &wb_response); if (wb_result == NSS_STATUS_SUCCESS) { diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index abc17a37a2..57442edee6 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -432,15 +432,15 @@ static int copy_reg(const char *source, const char *dest) return -1; } -int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new) +int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname) { int result; START_PROFILE(syscall_rename); - result = rename(old, new); + result = rename(oldname, newname); if (errno == EXDEV) { /* Rename across filesystems needed. */ - result = copy_reg(old, new); + result = copy_reg(oldname, newname); } END_PROFILE(syscall_rename); -- cgit From 292d11bee56c5493f0c1a9e9e2078bd582704874 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 24 Jun 2005 21:43:36 +0000 Subject: r7888: Fix use of "protected". Jeremy. (This used to be commit af5fd615b37f555e5f2c7b9fef24299e99952a41) --- source3/smbd/posix_acls.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a3174440ef..a77fd1b429 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -84,7 +84,7 @@ struct pai_entry { }; struct pai_val { - BOOL protected; + BOOL pai_protected; unsigned int num_entries; struct pai_entry *entry_list; unsigned int num_def_entries; @@ -149,7 +149,7 @@ static unsigned int num_inherited_entries(canon_ace *ace_list) Create the on-disk format. Caller must free. ************************************************************************/ -static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL protected, size_t *store_size) +static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL pai_protected, size_t *store_size) { char *pai_buf = NULL; canon_ace *ace_list = NULL; @@ -177,7 +177,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B /* Set up the header. */ memset(pai_buf, '\0', PAI_ENTRIES_BASE); SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_VERSION); - SCVAL(pai_buf,PAI_FLAG_OFFSET,(protected ? PAI_ACL_FLAG_PROTECTED : 0)); + SCVAL(pai_buf,PAI_FLAG_OFFSET,(pai_protected ? PAI_ACL_FLAG_PROTECTED : 0)); SSVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET,num_entries); SSVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries); @@ -213,7 +213,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B ************************************************************************/ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list, - canon_ace *dir_ace_list, BOOL protected) + canon_ace *dir_ace_list, BOOL pai_protected) { int ret; size_t store_size; @@ -227,7 +227,7 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ * none of the entries in it are marked as inherited. */ - if (!protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) { + if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) { /* Instead just remove the attribute if it exists. */ if (fsp->fd != -1) SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME); @@ -236,7 +236,7 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ return; } - pai_buf = create_pai_buf(file_ace_list, dir_ace_list, protected, &store_size); + pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size); if (fsp->fd != -1) ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, @@ -247,7 +247,7 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ SAFE_FREE(pai_buf); - DEBUG(10,("store_inheritance_attribute:%s for file %s\n", protected ? " (protected)" : "", fsp->fsp_name)); + DEBUG(10,("store_inheritance_attribute:%s for file %s\n", pai_protected ? " (protected)" : "", fsp->fsp_name)); if (ret == -1 && !no_acl_syscall_error(errno)) DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) )); } @@ -280,7 +280,7 @@ static BOOL get_protected_flag(struct pai_val *pal) { if (!pal) return False; - return pal->protected; + return pal->pai_protected; } /************************************************************************ @@ -352,7 +352,7 @@ static struct pai_val *create_pai_val(char *buf, size_t size) memset(paiv, '\0', sizeof(struct pai_val)); - paiv->protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED); + paiv->pai_protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED); paiv->num_entries = SVAL(buf,PAI_NUM_ENTRIES_OFFSET); paiv->num_def_entries = SVAL(buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET); @@ -360,7 +360,7 @@ static struct pai_val *create_pai_val(char *buf, size_t size) entry_offset = buf + PAI_ENTRIES_BASE; DEBUG(10,("create_pai_val:%s num_entries = %u, num_def_entries = %u\n", - paiv->protected ? " (protected)" : "", paiv->num_entries, paiv->num_def_entries )); + paiv->pai_protected ? " (pai_protected)" : "", paiv->num_entries, paiv->num_def_entries )); for (i = 0; i < paiv->num_entries; i++) { struct pai_entry *paie; @@ -484,7 +484,7 @@ static struct pai_val *load_inherited_info(files_struct *fsp) paiv = create_pai_val(pai_buf, ret); - if (paiv && paiv->protected) + if (paiv && paiv->pai_protected) DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fsp->fsp_name)); SAFE_FREE(pai_buf); -- cgit From ff7e5c26733c933d0ed71616c39e2d931ad1e597 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Jun 2005 03:03:44 +0000 Subject: r7893: Add in the extra parameters to opendir() to fix the large directory/insane app problem. Rev vfs version. Doesn't change the normal codepath. Jeremy. (This used to be commit 0f03a6bdcdbdf60da81e0aeffa84ac6e48fc6a04) --- source3/smbd/dir.c | 69 ++++++++++++++++++++-------------------------- source3/smbd/filename.c | 2 +- source3/smbd/msdfs.c | 2 +- source3/smbd/notify_hash.c | 2 +- source3/smbd/reply.c | 52 ++++++++++++++++------------------ source3/smbd/trans2.c | 24 ++++++---------- source3/smbd/vfs-wrap.c | 2 +- 7 files changed, 67 insertions(+), 86 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ae21e16e31..fd0a303504 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -53,7 +53,7 @@ struct dptr_struct { struct smb_Dir *dir_hnd; BOOL expect_close; char *wcard; - uint16 attr; + uint32 attr; char *path; BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ }; @@ -68,7 +68,7 @@ static int dirhandles_open = 0; Make a dir struct. ****************************************************************************/ -void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,int mode,time_t date, BOOL uc) +void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc) { char *p; pstring mask2; @@ -175,7 +175,7 @@ static struct dptr_struct *dptr_get(int key, BOOL forclose) if (dirhandles_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); - if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) { + if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, dptr->wcard, dptr->attr))) { DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, strerror(errno))); return False; @@ -224,30 +224,6 @@ uint16 dptr_attr(int key) return(0); } -/**************************************************************************** - Set the dir wcard for a dir index. - Returns 0 on ok, 1 on fail. -****************************************************************************/ - -BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr) -{ - struct dptr_struct *dptr = dptr_get(key, False); - - if (dptr) { - dptr->attr = attr; - dptr->wcard = SMB_STRDUP(wcard); - if (!dptr->wcard) - return False; - if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { - dptr->has_wild = True; - } else { - dptr->has_wild = ms_has_wild(wcard); - } - return True; - } - return False; -} - /**************************************************************************** Close a dptr (internal func). ****************************************************************************/ @@ -399,7 +375,8 @@ static void dptr_close_oldest(BOOL old) a directory handle is never zero. ****************************************************************************/ -int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid) +int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, + const char *wcard, uint32 attr) { struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; @@ -415,7 +392,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp if (!*dir2) dir2 = "."; - dir_hnd = OpenDir(conn, dir2); + dir_hnd = OpenDir(conn, dir2, wcard, attr); if (!dir_hnd) { return (-2); } @@ -503,9 +480,23 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp dptr->dir_hnd = dir_hnd; dptr->spid = spid; dptr->expect_close = expect_close; - dptr->wcard = NULL; /* Only used in lanman2 searches */ - dptr->attr = 0; /* Only used in lanman2 searches */ - dptr->has_wild = True; /* Only used in lanman2 searches */ + if (wcard) { + dptr->wcard = SMB_STRDUP(wcard); + if (!dptr->wcard) { + bitmap_clear(dptr_bmap, dptr->dnum - 1); + SAFE_FREE(dptr); + CloseDir(dir_hnd); + return -1; + } + } else { + dptr->wcard = NULL; + } + dptr->attr = attr; + if (lp_posix_pathnames() || (wcard && (wcard[0] == '.' && wcard[1] == 0))) { + dptr->has_wild = True; + } else { + dptr->has_wild = ms_has_wild(wcard); + } DLIST_ADD(dirptrs, dptr); @@ -715,9 +706,9 @@ struct dptr_struct *dptr_fetch_lanman2(int dptr_num) Check a filetype for being valid. ****************************************************************************/ -BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype) +BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) { - int mask; + uint32 mask; /* Check the "may have" search bits. */ if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) @@ -747,8 +738,8 @@ static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *m Get an 8.3 directory entry. ****************************************************************************/ -BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname, - SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) +BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname, + SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend) { const char *dname; BOOL found = False; @@ -804,7 +795,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname *mode = dos_mode(conn,pathreal,&sbuf); if (!dir_check_ftype(conn,*mode,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); + DEBUG(5,("[%s] attribs didn't match %x\n",filename,(unsigned int)dirtype)); continue; } @@ -1000,7 +991,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * Open a directory. ********************************************************************/ -struct smb_Dir *OpenDir(connection_struct *conn, const char *name) +struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr) { struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir); if (!dirp) { @@ -1014,7 +1005,7 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name) if (!dirp->dir_path) { goto fail; } - dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path); + dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); if (!dirp->dir) { DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); goto fail; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3fb88974fe..f0a33e568e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -450,7 +450,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path))) { + if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b61a328080..be88a92414 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -989,7 +989,7 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) cnt++; /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(conn, "."); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) goto out; diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 0464eaa2eb..08eefab652 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -76,7 +76,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * larger than the max time_t value). */ - dp = OpenDir(conn, path); + dp = OpenDir(conn, path, NULL, 0); if (dp == NULL) return False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 99e0d5d9a1..9a7c22320c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1014,9 +1014,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring directory; pstring fname; SMB_OFF_T size; - int mode; + uint32 mode; time_t date; - int dirtype; + uint32 dirtype; int outsize = 0; unsigned int numentries = 0; unsigned int maxentries = 0; @@ -1115,7 +1115,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ok = True; if (status_len == 0) { - dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid)); + dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, dirtype); if (dptr_num < 0) { if(dptr_num == -2) { END_PROFILE(SMBsearch); @@ -1124,10 +1124,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); } - if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { - END_PROFILE(SMBsearch); - return ERROR_DOS(ERRDOS,ERRnomem); - } } else { dirtype = dptr_attr(dptr_num); } @@ -1743,10 +1739,10 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, Check if a user is allowed to delete a file. ********************************************************************/ -NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open) +NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open) { SMB_STRUCT_STAT sbuf; - int fmode; + uint32 fmode; int smb_action; int access_mode; files_struct *fsp; @@ -1817,7 +1813,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_ code. ****************************************************************************/ -NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) +NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name) { pstring directory; pstring mask; @@ -1879,8 +1875,11 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) struct smb_Dir *dir_hnd = NULL; const char *dname; + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory); + dir_hnd = OpenDir(conn, directory, mask, dirtype); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -1891,9 +1890,6 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) long offset = 0; error = NT_STATUS_NO_SUCH_FILE; - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - while ((dname = ReadDirName(dir_hnd, &offset))) { SMB_STRUCT_STAT st; pstring fname; @@ -1954,7 +1950,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size { int outsize = 0; pstring name; - int dirtype; + uint32 dirtype; NTSTATUS status; START_PROFILE(SMBunlink); @@ -3707,7 +3703,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) const char *dname = NULL; BOOL ret = False; long offset = 0; - struct smb_Dir *dir_hnd = OpenDir(conn, directory); + struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); if(dir_hnd == NULL) return True; @@ -3775,7 +3771,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) */ BOOL all_veto_files = True; const char *dname; - struct smb_Dir *dir_hnd = OpenDir(conn, directory); + struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); if(dir_hnd != NULL) { long dirpos = 0; @@ -3997,7 +3993,7 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T Rename an open file - given an fsp. ****************************************************************************/ -NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists) { SMB_STRUCT_STAT sbuf; BOOL bad_path = False; @@ -4111,7 +4107,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists) { pstring directory; pstring mask; @@ -4333,17 +4329,17 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", const char *dname; pstring destname; + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory); + dir_hnd = OpenDir(conn, directory, mask, attrs); if (dir_hnd) { long offset = 0; error = NT_STATUS_NO_SUCH_FILE; /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; BOOL sysdir_entry = False; @@ -4444,7 +4440,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring name; pstring newname; char *p; - uint16 attrs = SVAL(inbuf,smb_vwv0); + uint32 attrs = SVAL(inbuf,smb_vwv0); NTSTATUS status; START_PROFILE(SMBmv); @@ -4689,16 +4685,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, const char *dname; pstring destname; + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory); + dir_hnd = OpenDir(conn, directory, mask, 0); if (dir_hnd) { long offset = 0; error = ERRbadfile; - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; pstrcpy(fname,dname); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 978afa6d74..5bf53fca8a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -996,7 +996,7 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps static BOOL get_lanman2_dir_entry(connection_struct *conn, void *inbuf, void *outbuf, - char *path_mask,int dirtype,int info_level, + char *path_mask,uint32 dirtype,int info_level, int requires_resume_key, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, @@ -1012,7 +1012,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, char *p, *q, *pdata = *ppdata; uint32 reskey=0; long prev_dirpos=0; - int mode=0; + uint32 mode=0; SMB_OFF_T file_size = 0; SMB_BIG_UINT allocation_size = 0; uint32 len; @@ -1020,7 +1020,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, char *nameptr; char *last_entry_ptr; BOOL was_8_3; - int nt_extmode; /* Used for NT connections instead of mode */ + uint32 nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); BOOL check_mangled_names = lp_manglednames(SNUM(conn)); @@ -1576,7 +1576,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb requested. */ char *params = *pparams; char *pdata = *ppdata; - int dirtype = SVAL(params,0); + uint32 dirtype = SVAL(params,0); int maxentries = SVAL(params,2); uint16 findfirst_flags = SVAL(params,4); BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE); @@ -1606,9 +1606,9 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb *directory = *mask = 0; - DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \ + DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", - dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, + (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, info_level, max_data_bytes)); if (!maxentries) { @@ -1711,19 +1711,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } *pparams = params; - dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) { - talloc_destroy(ea_ctx); - return(UNIXERROR(ERRDOS,ERRbadfile)); - } - /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ - if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { - dptr_close(&dptr_num); + dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, dirtype); + if (dptr_num < 0) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return(UNIXERROR(ERRDOS,ERRbadfile)); } DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 57442edee6..3260cce9aa 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -88,7 +88,7 @@ int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_ /* Directory operations */ -DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) +DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) { DIR *result; -- cgit From afc7af3fdf3ec8214dff8924734008eb41c81979 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Jun 2005 17:14:15 +0000 Subject: r7948: Ensure we call the vfs connection hook before doing a vfs stat. Allows database vfs backends to initialise with a working connection. Bugid #2827 Jeremy. (This used to be commit 7ef6850056f7fbb380038f5ec5bcb29d27fbf254) --- source3/smbd/service.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 24f4df7694..b53d6e3ad9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -604,6 +604,25 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #endif + /* Add veto/hide lists */ + if (!IS_IPC(conn) && !IS_PRINT(conn)) { + set_namearray( &conn->veto_list, lp_veto_files(snum)); + set_namearray( &conn->hide_list, lp_hide_files(snum)); + set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); + } + + /* Invoke VFS make connection hook - do this before the VFS_STAT call to allow + any filesystems needing user credentials to initialize themselves. */ + + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { + DEBUG(0,("make_connection: VFS make connection failed!\n")); + change_to_root_user(); + yield_connection(conn, lp_servicename(snum)); + conn_free(conn); + *status = NT_STATUS_UNSUCCESSFUL; + return NULL; + } + /* win2000 does not check the permissions on the directory during the tree connect, instead relying on permission check during individual operations. To match this behaviour @@ -612,6 +631,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum))); change_to_root_user(); + /* Call VFS disconnect hook */ + SMB_VFS_DISCONNECT(conn); yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; @@ -646,27 +667,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, dbgtext( "(pid %d)\n", (int)sys_getpid() ); } - /* Add veto/hide lists */ - if (!IS_IPC(conn) && !IS_PRINT(conn)) { - set_namearray( &conn->veto_list, lp_veto_files(snum)); - set_namearray( &conn->hide_list, lp_hide_files(snum)); - set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); - } - - /* Invoke VFS make connection hook */ - - if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { - DEBUG(0,("make_connection: VFS make connection failed!\n")); - change_to_root_user(); - yield_connection(conn, lp_servicename(snum)); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; - return NULL; - } - /* we've finished with the user stuff - go back to root */ change_to_root_user(); - return(conn); } -- cgit From 7ebd74e6c502483b7f7c73943b698d6433c8c0b2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 27 Jun 2005 22:44:57 +0000 Subject: r7961: randomize reloading so that smbds do not pverload cupsd by reloading printers all at the same time. sss (This used to be commit da227d5f4311c84a12a4e2a9fd510328268af4b3) --- source3/smbd/process.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1ec176bd08..c4c1debbf3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1299,6 +1299,7 @@ static int setup_select_timeout(void) void check_reload(int t) { + static pid_t mypid = 0; static time_t last_smb_conf_reload_time = 0; static time_t last_printer_reload_time = 0; time_t printcap_cache_time = (time_t)lp_printcap_cache_time(); @@ -1314,6 +1315,15 @@ void check_reload(int t) last_printer_reload_time = t; } + if (mypid != getpid()) { /* First time or fork happened meanwhile */ + /* randomize over 60 second the printcap reload to avoid all + * process hitting cupsd at the same time */ + int time_range = 60; + + last_printer_reload_time += random() % time_range; + mypid = getpid(); + } + if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { reload_services(True); reload_after_sighup = False; -- cgit From f2f55d703d0dd549a83809d3e5cc5151569b48d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Jun 2005 22:53:56 +0000 Subject: r7963: Add aio support to 3.0. Jeremy. (This used to be commit 1de27da47051af08790317f5b48b02719d6b9934) --- source3/smbd/aio.c | 748 +++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/blocking.c | 10 +- source3/smbd/close.c | 14 + source3/smbd/conn.c | 1 + source3/smbd/notify.c | 1 + source3/smbd/open.c | 4 + source3/smbd/oplock.c | 26 +- source3/smbd/process.c | 111 ++++++- source3/smbd/reply.c | 7 - source3/smbd/server.c | 5 +- source3/smbd/service.c | 1 + source3/smbd/sesssetup.c | 1 + source3/smbd/trans2.c | 3 + source3/smbd/vfs-wrap.c | 35 +++ source3/smbd/vfs.c | 39 ++- 15 files changed, 958 insertions(+), 48 deletions(-) create mode 100644 source3/smbd/aio.c (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c new file mode 100644 index 0000000000..7910ee5a7a --- /dev/null +++ b/source3/smbd/aio.c @@ -0,0 +1,748 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + async_io read handling using POSIX async io. + Copyright (C) Jeremy Allison 2005. + + 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" + +#if defined(WITH_AIO) + +/* The signal we'll use to signify aio done. */ +#ifndef RT_SIGNAL_AIO +#define RT_SIGNAL_AIO (SIGRTMIN+3) +#endif + +/**************************************************************************** + The buffer we keep around whilst an aio request is in process. +*****************************************************************************/ + +struct aio_extra { + struct aio_extra *next, *prev; + SMB_STRUCT_AIOCB acb; + files_struct *fsp; + BOOL read_req; + uint16 mid; + char *inbuf; + char *outbuf; +}; + +static struct aio_extra *aio_list_head; + +/**************************************************************************** + Create the extended aio struct we must keep around for the lifetime + of the aio_read call. +*****************************************************************************/ + +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, uint16 mid) +{ + struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); + + if (!aio_ex) { + return NULL; + } + ZERO_STRUCTP(aio_ex); + /* The output buffer stored in the aio_ex is the start of + the smb return buffer. The buffer used in the acb + is the start of the reply data portion of that buffer. */ + aio_ex->outbuf = SMB_MALLOC_ARRAY(char, buflen); + if (!aio_ex->outbuf) { + SAFE_FREE(aio_ex); + return NULL; + } + DLIST_ADD(aio_list_head, aio_ex); + aio_ex->fsp = fsp; + aio_ex->read_req = True; + aio_ex->mid = mid; + return aio_ex; +} + +/**************************************************************************** + Create the extended aio struct we must keep around for the lifetime + of the aio_write call. +*****************************************************************************/ + +static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen, uint16 mid) +{ + struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); + + if (!aio_ex) { + return NULL; + } + ZERO_STRUCTP(aio_ex); + + /* We need space for an output reply of outbuflen bytes. */ + aio_ex->outbuf = SMB_MALLOC_ARRAY(char, outbuflen); + if (!aio_ex->outbuf) { + SAFE_FREE(aio_ex); + return NULL; + } + /* Steal the input buffer containing the write data from the main SMB call. */ + /* We must re-allocate a new one here. */ + if (NewInBuffer(&aio_ex->inbuf) == NULL) { + SAFE_FREE(aio_ex->outbuf); + SAFE_FREE(aio_ex); + return NULL; + } + + /* aio_ex->inbuf now contains the stolen old InBuf containing the data to write. */ + + DLIST_ADD(aio_list_head, aio_ex); + aio_ex->fsp = fsp; + aio_ex->read_req = False; + aio_ex->mid = mid; + return aio_ex; +} + +/**************************************************************************** + Delete the extended aio struct. +*****************************************************************************/ + +static void delete_aio_ex(struct aio_extra *aio_ex) +{ + DLIST_REMOVE(aio_list_head, aio_ex); + /* Safe to do as we've removed ourselves from the in use list first. */ + free_InBuffer(aio_ex->inbuf); + + SAFE_FREE(aio_ex->outbuf); + SAFE_FREE(aio_ex); +} + +/**************************************************************************** + Given the aiocb struct find the extended aio struct containing it. +*****************************************************************************/ + +static struct aio_extra *find_aio_ex(uint16 mid) +{ + struct aio_extra *p; + + for( p = aio_list_head; p; p = p->next) { + if (mid == p->mid) { + return p; + } + } + return NULL; +} + +/**************************************************************************** + We can have these many aio buffers in flight. +*****************************************************************************/ + +#define AIO_PENDING_SIZE 10 +static sig_atomic_t signals_received; +static int outstanding_aio_calls; +static uint16 aio_pending_array[AIO_PENDING_SIZE]; + +/**************************************************************************** + Signal handler when an aio request completes. +*****************************************************************************/ + +static void signal_handler(int sig, siginfo_t *info, void *unused) +{ + if (signals_received < AIO_PENDING_SIZE - 1) { + aio_pending_array[signals_received] = *(uint16 *)(info->si_value.sival_ptr); + signals_received++; + } /* Else signal is lost. */ + sys_select_signal(RT_SIGNAL_AIO); +} + +/**************************************************************************** + Is there a signal waiting ? +*****************************************************************************/ + +BOOL aio_finished(void) +{ + return (signals_received != 0); +} + +/**************************************************************************** + Initialize the signal handler for aio read/write. +*****************************************************************************/ + +void initialize_async_io_handler(void) +{ + struct sigaction act; + + ZERO_STRUCT(act); + act.sa_sigaction = signal_handler; + act.sa_flags = SA_SIGINFO; + sigemptyset( &act.sa_mask ); + if (sigaction(RT_SIGNAL_AIO, &act, NULL) != 0) { + DEBUG(0,("Failed to setup RT_SIGNAL_AIO handler\n")); + } + + /* the signal can start off blocked due to a bug in bash */ + BlockSignals(False, RT_SIGNAL_AIO); +} + +/**************************************************************************** + Set up an aio request from a SMBreadX call. +*****************************************************************************/ + +BOOL schedule_aio_read_and_X(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int len_outbuf, + files_struct *fsp, SMB_OFF_T startpos, + size_t smb_maxcnt) +{ + struct aio_extra *aio_ex; + SMB_STRUCT_AIOCB *a; + size_t bufsize; + size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); + + if (!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) { + /* Too small a read for aio request. */ + DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small " + "for minimum aio_read of %u\n", + (unsigned int)smb_maxcnt, + (unsigned int)min_aio_read_size )); + return False; + } + + /* Only do this on non-chained and non-chaining reads not using the write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + return False; + } + + if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + DEBUG(10,("schedule_aio_read_and_X: Already have %d aio activities outstanding.\n", + outstanding_aio_calls )); + return False; + } + + /* The following is safe from integer wrap as we've already + checked smb_maxcnt is 128k or less. */ + bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt; + + if ((aio_ex = create_aio_ex_read(fsp, bufsize, SVAL(inbuf,smb_mid))) == NULL) { + DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); + return False; + } + + /* Copy the SMB header already setup in outbuf. */ + memcpy(aio_ex->outbuf, outbuf, smb_buf(outbuf) - outbuf); + SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ + + a = &aio_ex->acb; + + /* Now set up the aio record for the read call. */ + + a->aio_fildes = fsp->fd; + a->aio_buf = smb_buf(aio_ex->outbuf); + a->aio_nbytes = smb_maxcnt; + a->aio_offset = startpos; + a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; + a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; + a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + + if (SMB_VFS_AIO_READ(fsp,a) == -1) { + DEBUG(0,("schedule_aio_read_and_X: aio_read failed. Error %s\n", + strerror(errno) )); + delete_aio_ex(aio_ex); + return False; + } + + DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, offset %.0f, len = %u (mid = %u)\n", + fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->mid )); + + srv_defer_sign_response(aio_ex->mid); + outstanding_aio_calls++; + return True; +} + +/**************************************************************************** + Set up an aio request from a SMBwriteX call. +*****************************************************************************/ + +BOOL schedule_aio_write_and_X(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int len_outbuf, + files_struct *fsp, char *data, + SMB_OFF_T startpos, + size_t numtowrite) +{ + struct aio_extra *aio_ex; + SMB_STRUCT_AIOCB *a; + size_t outbufsize; + BOOL write_through = BITSETW(inbuf+smb_vwv7,0); + size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); + + if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { + /* Too small a write for aio request. */ + DEBUG(10,("schedule_aio_write_and_X: write size (%u) too small " + "for minimum aio_write of %u\n", + (unsigned int)numtowrite, + (unsigned int)min_aio_write_size )); + return False; + } + + /* Only do this on non-chained and non-chaining reads not using the write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + return False; + } + + if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + DEBUG(3,("schedule_aio_write_and_X: Already have %d aio activities outstanding.\n", + outstanding_aio_calls )); + DEBUG(10,("schedule_aio_write_and_X: failed to schedule aio_write for file %s, offset %.0f, len = %u (mid = %u)\n", + fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)SVAL(inbuf,smb_mid) )); + return False; + } + + outbufsize = smb_len(outbuf) + 4; + if ((aio_ex = create_aio_ex_write(fsp, outbufsize, SVAL(inbuf,smb_mid))) == NULL) { + DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n")); + return False; + } + + /* Paranioa.... */ + SMB_ASSERT(aio_ex->inbuf == inbuf); + + /* Copy the SMB header already setup in outbuf. */ + memcpy(aio_ex->outbuf, outbuf, outbufsize); + SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ + + a = &aio_ex->acb; + + /* Now set up the aio record for the write call. */ + + a->aio_fildes = fsp->fd; + a->aio_buf = data; /* As we've stolen inbuf this points within inbuf. */ + a->aio_nbytes = numtowrite; + a->aio_offset = startpos; + a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; + a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; + a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + + if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { + DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. Error %s\n", + strerror(errno) )); + /* Replace global InBuf as we're going to do a normal write. */ + set_InBuffer(aio_ex->inbuf); + aio_ex->inbuf = NULL; + delete_aio_ex(aio_ex); + return False; + } + + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the write. */ + SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); + SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); + show_msg(aio_ex->outbuf); + if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { + exit_server("handle_aio_write: send_smb failed."); + } + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write behind for file %s\n", + fsp->fsp_name )); + } else { + srv_defer_sign_response(aio_ex->mid); + } + outstanding_aio_calls++; + + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file %s, \ +offset %.0f, len = %u (mid = %u) outstanding_aio_calls = %d\n", + fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)aio_ex->mid, outstanding_aio_calls )); + + return True; +} + + +/**************************************************************************** + Complete the read and return the data or error back to the client. + Returns errno or zero if all ok. +*****************************************************************************/ + +static int handle_aio_read_complete(struct aio_extra *aio_ex) +{ + int ret = 0; + int outsize; + char *outbuf = aio_ex->outbuf; + char *data = smb_buf(outbuf); + ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); + + if (nread < 0) { + /* We're relying here on the fact that if the fd is + closed then the aio will complete and aio_return + will return an error. Hopefully this is + true.... JRA. */ + + /* If errno is ECANCELED then don't return anything to the client. */ + if (errno == ECANCELED) { + srv_cancel_sign_response(aio_ex->mid); + return 0; + } + + DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. Error = %s\n", + aio_ex->fsp->fsp_name, strerror(errno) )); + + outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); + ret = errno; + } else { + outsize = set_message(outbuf,12,nread,False); + SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); + SSVAL(smb_buf(outbuf),-2,nread); + + DEBUG( 3, ( "handle_aio_read_complete file %s max=%d nread=%d\n", + aio_ex->fsp->fsp_name, + aio_ex->acb.aio_nbytes, (int)nread ) ); + + } + smb_setlen(outbuf,outsize - 4); + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("handle_aio_read_complete: send_smb failed."); + } + + DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed for file %s, offset %.0f, len = %u\n", + aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)nread )); + + return ret; +} + +/**************************************************************************** + Complete the write and return the data or error back to the client. + Returns errno or zero if all ok. +*****************************************************************************/ + +static int handle_aio_write_complete(struct aio_extra *aio_ex) +{ + int ret = 0; + files_struct *fsp = aio_ex->fsp; + char *outbuf = aio_ex->outbuf; + ssize_t numtowrite = aio_ex->acb.aio_nbytes; + ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); + + if (fsp->aio_write_behind) { + if (nwritten != numtowrite) { + if (nwritten == -1) { + DEBUG(5,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); + ret = errno; + } else { + DEBUG(0,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! \ +Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, (int)nwritten )); + ret = EIO; + } + } else { + DEBUG(10,("handle_aio_write_complete: aio_write_behind completed for file %s\n", + fsp->fsp_name )); + } + return 0; + } + + /* We don't need outsize or set_message here as we've already set the + fixed size length when we set up the aio call. */ + + if(nwritten == -1) { + DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. nwritten == %d. Error = %s\n", + fsp->fsp_name, (unsigned int)numtowrite, + (int)nwritten, strerror(errno) )); + + /* If errno is ECANCELED then don't return anything to the client. */ + if (errno == ECANCELED) { + srv_cancel_sign_response(aio_ex->mid); + return 0; + } + + UNIXERROR(ERRHRD,ERRdiskfull); + ret = errno; + } else { + BOOL write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); + + SSVAL(outbuf,smb_vwv2,nwritten); + SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); + if (nwritten < (ssize_t)numtowrite) { + SCVAL(outbuf,smb_rcls,ERRHRD); + SSVAL(outbuf,smb_err,ERRdiskfull); + } + + DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); + if (lp_syncalways(SNUM(fsp->conn)) || write_through) { + sync_file(fsp->conn,fsp); + } + } + + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("handle_aio_write: send_smb failed."); + } + + DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed for file %s, offset %.0f, requested %u, written = %u\n", + fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)numtowrite, (unsigned int)nwritten )); + + return ret; +} + +/**************************************************************************** + Handle any aio completion. Returns True if finished (and sets *perr if err was non-zero), + False if not. +*****************************************************************************/ + +static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) +{ + int err; + + /* Ensure the operation has really completed. */ + if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) { + DEBUG(10,( "handle_aio_completed: operation mid %u still in process for file %s\n", + aio_ex->mid, aio_ex->fsp->fsp_name )); + return False; + } + + if (aio_ex->read_req) { + err = handle_aio_read_complete(aio_ex); + } else { + err = handle_aio_write_complete(aio_ex); + } + + if (err) { + *perr = err; /* Only save non-zero errors. */ + } + + return True; +} + +/**************************************************************************** + Handle any aio completion inline. + Returns non-zero errno if fail or zero if all ok. +*****************************************************************************/ + +int process_aio_queue(void) +{ + int i; + int ret = 0; + + BlockSignals(True, RT_SIGNAL_AIO); + + DEBUG(10,("process_aio_queue: signals_received = %d\n", (int)signals_received)); + DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", outstanding_aio_calls)); + + if (!signals_received) { + BlockSignals(False, RT_SIGNAL_AIO); + return 0; + } + + /* Drain all the complete aio_reads. */ + for (i = 0; i < signals_received; i++) { + uint16 mid = aio_pending_array[i]; + files_struct *fsp = NULL; + struct aio_extra *aio_ex = find_aio_ex(mid); + + if (!aio_ex) { + DEBUG(3,("process_aio_queue: Can't find record to match mid %u.\n", + (unsigned int)mid)); + srv_cancel_sign_response(mid); + continue; + } + + fsp = aio_ex->fsp; + if (fsp == NULL) { + /* file was closed whilst I/O was outstanding. Just ignore. */ + DEBUG( 3,( "process_aio_queue: file closed whilst aio outstanding.\n")); + srv_cancel_sign_response(mid); + continue; + } + + if (!handle_aio_completed(aio_ex, &ret)) { + continue; + } + + delete_aio_ex(aio_ex); + } + + outstanding_aio_calls -= signals_received; + signals_received = 0; + BlockSignals(False, RT_SIGNAL_AIO); + return ret; +} + +/**************************************************************************** + We're doing write behind and the client closed the file. Wait up to 30 seconds + (my arbitrary choice) for the aio to complete. Return 0 if all writes completed, + errno to return if not. +*****************************************************************************/ + +#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 + +BOOL wait_for_aio_completion(files_struct *fsp) +{ + struct aio_extra *aio_ex; + const SMB_STRUCT_AIOCB **aiocb_list; + int aio_completion_count = 0; + time_t start_time = time(NULL); + int seconds_left; + int ret = 0; + + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; seconds_left >= 0;) { + int err = 0; + int i; + struct timespec ts; + + aio_completion_count = 0; + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aio_completion_count++; + } + } + + if (!aio_completion_count) { + return ret; + } + + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events to complete.\n", + aio_completion_count )); + + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, aio_completion_count); + if (!aiocb_list) { + return False; + } + + for( i = 0, aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aiocb_list[i++] = &aio_ex->acb; + } + } + + /* Now wait up to seconds_left for completion. */ + ts.tv_sec = seconds_left; + ts.tv_nsec = 0; + + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait of %d seconds.\n", + aio_completion_count, seconds_left )); + + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, aio_completion_count, &ts); + + DEBUG(10,("wait_for_aio_completion: returned err = %d, errno = %s\n", + err, strerror(errno) )); + + if (err == -1 && errno == EAGAIN) { + DEBUG(0,("wait_for_aio_completion: aio_suspend timed out waiting for %d events after a wait of %d seconds\n", + aio_completion_count, seconds_left)); + /* Timeout. */ + cancel_aio_by_fsp(fsp); + SAFE_FREE(aiocb_list); + return ret ? ret : EIO; + } + + /* One or more events might have completed - process them if so. */ + for( i = 0; i < aio_completion_count; i++) { + uint16 mid = *(uint16 *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr; + + aio_ex = find_aio_ex(mid); + + if (!handle_aio_completed(aio_ex, &err)) { + continue; + } + delete_aio_ex(aio_ex); + } + + SAFE_FREE(aiocb_list); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT - (time(NULL) - start_time); + } + + /* We timed out - we don't know why. Return ret if already an error, else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting for %d events\n", + aio_completion_count)); + + return ret ? ret : EIO; +} + +/**************************************************************************** + Cancel any outstanding aio requests. The client doesn't care about the reply. +*****************************************************************************/ + +void cancel_aio_by_fsp(files_struct *fsp) +{ + struct aio_extra *aio_ex; + + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + /* Don't delete the aio_extra record as we may have completed + and don't yet know it. Just do the aio_cancel call and return. */ + SMB_VFS_AIO_CANCEL(fsp,fsp->fd, &aio_ex->acb); + aio_ex->fsp = NULL; /* fsp will be closed when we return. */ + } + } +} + +/**************************************************************************** + Check if a buffer was stolen for aio use. +*****************************************************************************/ + +BOOL aio_inbuffer_in_use(char *inbuf) +{ + struct aio_extra *aio_ex; + + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->inbuf == inbuf) { + return True; + } + } + return False; +} +#else +BOOL aio_finished(void) +{ + return False; +} + +void initialize_async_io_handler(void) +{ +} + +int process_aio_queue(void) +{ + return False; +} + +BOOL schedule_aio_read_and_X(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int len_outbuf, + files_struct *fsp, SMB_OFF_T startpos, + size_t smb_maxcnt) +{ + return False; +} + +BOOL schedule_aio_write_and_X(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int len_outbuf, + files_struct *fsp, char *data, + SMB_OFF_T startpos, + size_t numtowrite) +{ + return False; +} + +void cancel_aio_by_fsp(files_struct *fsp) +{ +} + +BOOL wait_for_aio_completion(files_struct *fsp) +{ + return True; +} + +BOOL aio_inbuffer_in_use(char *ptr) +{ + return False; +} +#endif diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 0e71174a2e..72d021d4e6 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -20,8 +20,6 @@ #include "includes.h" -extern char *OutBuffer; - /**************************************************************************** This is the structure to queue to implement blocking locks. notify. It consists of the requesting SMB and the expiry time. @@ -175,7 +173,7 @@ static void send_blocking_reply(char *outbuf, int outsize) static void reply_lockingX_success(blocking_lock_record *blr) { - char *outbuf = OutBuffer; + char *outbuf = get_OutBuffer(); int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; int outsize = 0; @@ -204,7 +202,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status) { - char *outbuf = OutBuffer; + char *outbuf = get_OutBuffer(); char *inbuf = blr->inbuf; construct_reply_common(inbuf, outbuf); @@ -295,7 +293,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status static BOOL process_lockread(blocking_lock_record *blr) { - char *outbuf = OutBuffer; + char *outbuf = get_OutBuffer(); char *inbuf = blr->inbuf; ssize_t nread = -1; char *data, *p; @@ -367,7 +365,7 @@ static BOOL process_lockread(blocking_lock_record *blr) static BOOL process_lock(blocking_lock_record *blr) { - char *outbuf = OutBuffer; + char *outbuf = get_OutBuffer(); char *inbuf = blr->inbuf; int outsize; SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index b3244432ff..b7649bcce4 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -156,6 +156,20 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) remove_pending_lock_requests_by_fid(fsp); + if (fsp->aio_write_behind) { + /* + * If we're finishing write behind on a close we can get a write + * error here, we must remember this. + */ + int ret = wait_for_aio_completion(fsp); + if (ret) { + saved_errno = ret; + err1 = -1; + } + } else { + cancel_aio_by_fsp(fsp); + } + /* * If we're flushing on a close we can get a write * error here, we must remember this. diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index dc7dec4e97..534a3367d4 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -257,6 +257,7 @@ void conn_free(connection_struct *conn) free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); + free_namearray(conn->aio_write_behind_list); string_free(&conn->user); string_free(&conn->dirpath); diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 92b86f350c..ad49dc0a21 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -60,6 +60,7 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) */ set_message(outbuf,18,0,False); + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("change_notify_reply_packet: send_smb failed."); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8b30776fdd..9da53a5057 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -316,6 +316,10 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->is_directory = False; fsp->is_stat = False; fsp->directory_delete_on_close = False; + if (conn->aio_write_behind_list && is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { + fsp->aio_write_behind = True; + } + string_set(&fsp->fsp_name,fname); fsp->wcp = NULL; /* Write cache pointer. */ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 9b8df98fd5..8208fbebe3 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -634,6 +634,7 @@ static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) /* Save the server smb signing state. */ sign_state = srv_oplock_set_signing(False); + show_msg(outbuf); if (!send_smb(smbd_server_fd(), outbuf)) exit_server("oplock_break_level2: send_smb failed."); @@ -677,7 +678,9 @@ static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) { char *inbuf = NULL; + char *saved_inbuf = NULL; char *outbuf = NULL; + char *saved_outbuf = NULL; files_struct *fsp = NULL; time_t start_time; BOOL shutdown_server = False; @@ -740,14 +743,15 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * messages crossing on the wire. */ - if((inbuf = (char *)SMB_MALLOC(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { + if((inbuf = NewInBuffer(&saved_inbuf))==NULL) { DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); return False; } - if((outbuf = (char *)SMB_MALLOC(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { + if((outbuf = NewOutBuffer(&saved_outbuf))==NULL) { DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - SAFE_FREE(inbuf); + set_InBuffer(saved_inbuf); + free_InBuffer(inbuf); return False; } @@ -778,6 +782,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Save the server smb signing state. */ sign_state = srv_oplock_set_signing(False); + show_msg(outbuf); if (!send_smb(smbd_server_fd(), outbuf)) { srv_oplock_set_signing(sign_state); exit_server("oplock_break: send_smb failed."); @@ -823,11 +828,16 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * From Charles Hoch . If the break processing * code closes the file (as it often does), then the fsp pointer here * points to free()'d memory. We *must* revalidate fsp each time - * around the loop. + * around the loop. With async I/O, write calls may steal the global InBuffer, + * so ensure we're using the correct one each time around the loop. */ while((fsp = initial_break_processing(dev, inode, file_id)) && OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + + inbuf = get_InBuffer(); + outbuf = get_OutBuffer(); + if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) { /* * Die if we got an error. @@ -899,9 +909,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Restore the chain fnum. */ file_chain_restore(); + /* Restore the global In/Out buffers. */ + set_InBuffer(saved_inbuf); + set_OutBuffer(saved_outbuf); + /* Free the buffers we've been using to recurse. */ - SAFE_FREE(inbuf); - SAFE_FREE(outbuf); + free_InBuffer(inbuf); + free_OutBuffer(outbuf); /* We need this in case a readraw crossed on the wire. */ if(global_oplock_break) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c4c1debbf3..94d4b8d903 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -28,8 +28,7 @@ extern int smb_echo_count; struct timeval smb_last_time; static char *InBuffer = NULL; -char *OutBuffer = NULL; -char *last_inbuf = NULL; +static char *OutBuffer = NULL; /* * Size of data we can send to client. Set @@ -287,11 +286,17 @@ static void async_processing(char *buffer, int buffer_len) { DEBUG(10,("async_processing: Doing async processing.\n")); + process_aio_queue(); + /* check for oplock messages (both UDP and kernel) */ if (receive_local_message(buffer, buffer_len, 1)) { process_local_message(buffer, buffer_len); } + /* Do the aio check again after receive_local_message as it does a select + and may have eaten our signal. */ + process_aio_queue(); + if (got_sig_term) { exit_server("Caught TERM signal"); } @@ -981,8 +986,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) return(ERROR_DOS(ERRSRV,ERRaccess)); - last_inbuf = inbuf; - outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); } @@ -1511,24 +1514,106 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); } /**************************************************************************** - process commands from the client + Accessor functions for InBuffer, OutBuffer. ****************************************************************************/ -void smbd_process(void) +char *get_InBuffer(void) { - time_t last_timeout_processing_time = time(NULL); - unsigned int num_smbs = 0; - const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN; + return InBuffer; +} - InBuffer = (char *)SMB_MALLOC(total_buffer_size); - OutBuffer = (char *)SMB_MALLOC(total_buffer_size); - if ((InBuffer == NULL) || (OutBuffer == NULL)) - return; +void set_InBuffer(char *new_inbuf) +{ + InBuffer = new_inbuf; +} + +char *get_OutBuffer(void) +{ + return OutBuffer; +} + +void set_OutBuffer(char *new_outbuf) +{ + OutBuffer = new_outbuf; +} + +/**************************************************************************** + Free an InBuffer. Checks if not in use by aio system. + Must have been allocated by NewInBuffer. +****************************************************************************/ + +void free_InBuffer(char *inbuf) +{ + if (!aio_inbuffer_in_use(inbuf)) { + SAFE_FREE(inbuf); + } +} + +/**************************************************************************** + Free an OutBuffer. No outbuffers currently stolen by aio system. + Must have been allocated by NewInBuffer. +****************************************************************************/ + +void free_OutBuffer(char *outbuf) +{ + SAFE_FREE(outbuf); +} + +const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); +/**************************************************************************** + Allocate a new InBuffer. Returns the new and old ones. +****************************************************************************/ + +char *NewInBuffer(char **old_inbuf) +{ + char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size); + if (!new_inbuf) { + return NULL; + } + if (old_inbuf) { + *old_inbuf = InBuffer; + } + InBuffer = new_inbuf; #if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); +#endif + return InBuffer; +} + +/**************************************************************************** + Allocate a new OutBuffer. Returns the new and old ones. +****************************************************************************/ + +char *NewOutBuffer(char **old_outbuf) +{ + char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size); + if (!new_outbuf) { + return NULL; + } + if (old_outbuf) { + *old_outbuf = OutBuffer; + } + OutBuffer = new_outbuf; +#if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); #endif + return OutBuffer; +} + +/**************************************************************************** + Process commands from the client +****************************************************************************/ + +void smbd_process(void) +{ + time_t last_timeout_processing_time = time(NULL); + unsigned int num_smbs = 0; + + /* Allocate the primary Inbut/Output buffers. */ + + if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) + return; max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9a7c22320c..312a3ace23 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2575,13 +2575,10 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_DOS(ERRDOS,ERRlock); } -#if 0 - /* Enable when the AIO code is moved over. JRA. */ if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) { END_PROFILE(SMBreadX); return -1; } -#endif nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); if (nread != -1) @@ -2952,15 +2949,11 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng nwritten = 0; } else { -#if 0 - /* Enable when AIO code is moved over. JRA. */ - if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize, fsp,data,startpos,numtowrite)) { END_PROFILE(SMBwriteX); return -1; } -#endif nwritten = write_file(fsp,data,startpos,numtowrite); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b40a8267cc..4217d821f4 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -30,7 +30,6 @@ int last_message = -1; /* a useful macro to debug the last message processed */ #define LAST_MESSAGE() smb_fn_name(last_message) -extern char *last_inbuf; extern struct auth_context *negprot_global_auth_context; extern pstring user_socket_options; extern SIG_ATOMIC_T got_sig_term; @@ -635,6 +634,7 @@ void exit_server(const char *reason) if (!reason) { int oldlevel = DEBUGLEVEL; + char *last_inbuf = get_InBuffer(); DEBUGLEVEL = 10; DEBUG(0,("Last message was %s\n",smb_fn_name(last_message))); if (last_inbuf) @@ -951,6 +951,9 @@ void build_options(BOOL screen); if (!init_change_notify()) exit(1); + /* Setup aio signal handler. */ + initialize_async_io_handler(); + /* re-initialise the timezone */ TimeInit(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b53d6e3ad9..d330e847e2 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -379,6 +379,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->veto_list = NULL; conn->hide_list = NULL; conn->veto_oplock_list = NULL; + conn->aio_write_behind_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); conn->nt_user_token = NULL; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 95fe571cff..1ddd6256b3 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -96,6 +96,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, set_message_end(outbuf,p); + show_msg(outbuf); return send_smb(smbd_server_fd(),outbuf); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5bf53fca8a..d4daf1fd69 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -591,6 +591,7 @@ static int send_trans2_replies(char *outbuf, /* If there genuinely are no parameters or data to send just send the empty packet */ if(params_to_send == 0 && data_to_send == 0) { + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("send_trans2_replies: send_smb failed."); return 0; @@ -685,6 +686,7 @@ static int send_trans2_replies(char *outbuf, params_to_send, data_to_send, paramsize, datasize)); /* Send the packet */ + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("send_trans2_replies: send_smb failed."); @@ -4912,6 +4914,7 @@ int reply_trans2(connection_struct *conn, of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); srv_signing_trans_stop(); + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("reply_trans2: send_smb failed."); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 3260cce9aa..1d205e5977 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -1052,3 +1052,38 @@ int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp { return sys_fsetxattr(fd, name, value, size, flags); } + +int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_read(aiocb); +} + +int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_write(aiocb); +} + +int vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_return(aiocb); +} + +int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_cancel(fd, aiocb); +} + +int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_error(aiocb); +} + +int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_fsync(op, aiocb); +} + +int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout) +{ + return sys_aio_suspend(aiocb, n, timeout); +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b09935eaa9..11adfed694 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -145,7 +145,16 @@ static struct vfs_ops default_vfs = { vfswrap_fremovexattr, vfswrap_setxattr, vfswrap_lsetxattr, - vfswrap_fsetxattr + vfswrap_fsetxattr, + + /* AIO operations. */ + vfswrap_aio_read, + vfswrap_aio_write, + vfswrap_aio_return, + vfswrap_aio_cancel, + vfswrap_aio_error, + vfswrap_aio_fsync, + vfswrap_aio_suspend } }; @@ -277,20 +286,20 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) DLIST_ADD(conn->vfs_handles, handle); for(i=0; ops[i].op != NULL; i++) { - DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); - if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { - /* Check whether this operation was already made opaque by different module */ - if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { - /* No, it isn't overloaded yet. Overload. */ - DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; - } - } - /* Change current VFS disposition*/ - DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; + DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); + if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { + /* Check whether this operation was already made opaque by different module */ + if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { + /* No, it isn't overloaded yet. Overload. */ + DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); + ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; + ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; + } + } + /* Change current VFS disposition*/ + DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); + ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; + ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; } SAFE_FREE(module_name); -- cgit From bf547ff1ad4120f898e89fd75ec94f577a0fc84d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jun 2005 19:25:48 +0000 Subject: r7981: MS-DFS tidyup patches from James Peach . Looking forward to the day he can commit these himself :-). Jeremy. (This used to be commit 12ff2978295a84fe6177af129c495a0021befacc) --- source3/smbd/msdfs.c | 61 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index be88a92414..fffe44ab60 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -20,6 +20,7 @@ */ +#define DBGC_CLASS DBGC_MSDFS #include "includes.h" extern uint32 global_client_caps; @@ -576,7 +577,9 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, requestedpathlen = rpcstr_push(uni_requestedpath, pathname, -1, STR_TERMINATE); - dump_data(10, (const char *) uni_requestedpath,requestedpathlen); + if (DEBUGLVL(10)) { + dump_data(0, (const char *) uni_requestedpath,requestedpathlen); + } DEBUG(10,("ref count = %u\n",junction->referral_count)); @@ -671,7 +674,9 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, reqpathlen = rpcstr_push(uni_reqpath, pathname, -1, STR_TERMINATE); - dump_data(10, (char *) uni_reqpath,reqpathlen); + if (DEBUGLVL(10)) { + dump_data(0, (char *) uni_reqpath,reqpathlen); + } uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count; uni_reqpathoffset2 = uni_reqpathoffset1 + reqpathlen; @@ -797,8 +802,11 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref return -1; } - DEBUG(10,("DFS Referral pdata:\n")); - dump_data(10,*ppdata,reply_size); + if (DEBUGLVL(10)) { + DEBUGADD(0,("DFS Referral pdata:\n")); + dump_data(0,*ppdata,reply_size); + } + return reply_size; } @@ -937,29 +945,30 @@ BOOL remove_msdfs_link(struct junction_map* jucn) return ret; } -static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) +static int form_junctions(int snum, struct junction_map* jucn, int jn_remain) { - int cnt = *jn_count; + int cnt = 0; DIR *dirp; char* dname; pstring connect_path; char* service_name = lp_servicename(snum); - connection_struct conns; - connection_struct *conn = &conns; + connection_struct conn; struct referral *ref = NULL; - BOOL ret = False; + if (jn_remain <= 0) + return(0); + pstrcpy(connect_path,lp_pathname(snum)); if(*connect_path == '\0') - return False; + return 0; /* * Fake up a connection struct for the VFS layer. */ - if (!create_conn_struct(conn, snum, connect_path)) - return False; + if (!create_conn_struct(&conn, snum, connect_path)) + return 0; /* form a junction for the msdfs root - convention DO NOT REMOVE THIS: NT clients will not work with us @@ -979,22 +988,25 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) ref->ttl = REFERRAL_TTL; if (*lp_msdfs_proxy(snum) != '\0') { pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); - *jn_count = ++cnt; - ret = True; goto out; } slprintf(ref->alternate_path, sizeof(pstring)-1, "\\\\%s\\%s", get_local_machine_name(), service_name); cnt++; - + /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); if(!dirp) goto out; - while((dname = vfs_readdirname(conn, dirp)) != NULL) { - if (is_msdfs_link(conn, dname, &(jucn[cnt].referral_list), + while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + if (cnt >= jn_remain) { + SMB_VFS_CLOSEDIR(&conn,dirp); + DEBUG(2, ("ran out of MSDFS junction slots")); + goto out; + } + if (is_msdfs_link(&conn, dname, &(jucn[cnt].referral_list), &(jucn[cnt].referral_count), NULL)) { pstrcpy(jucn[cnt].service_name, service_name); pstrcpy(jucn[cnt].volume_name, dname); @@ -1002,14 +1014,13 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) } } - SMB_VFS_CLOSEDIR(conn,dirp); - *jn_count = cnt; + SMB_VFS_CLOSEDIR(&conn,dirp); out: - talloc_destroy(conn->mem_ctx); - return ret; + conn_free(&conn); + return cnt; } -int enum_msdfs_links(struct junction_map* jucn) +int enum_msdfs_links(struct junction_map* jucn, int jn_max) { int i=0; int jn_count = 0; @@ -1017,9 +1028,9 @@ int enum_msdfs_links(struct junction_map* jucn) if(!lp_host_msdfs()) return 0; - for(i=0;i < lp_numservices();i++) { + for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) { if(lp_msdfs_root(i)) - form_junctions(i,jucn,&jn_count); + jn_count += form_junctions(i,jucn,jn_max - jn_count); } return jn_count; } -- cgit From 9b782f49350bd7682ad3270bf585b9af15669245 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jun 2005 21:48:09 +0000 Subject: r7985: Add "acl map full control", true by default, to allow people to change mapping of rwx to full control or not. Requested feature at SambaXP. Jeremy. (This used to be commit c870579f4cd91dc9e030134dd367109aed3e3469) --- source3/smbd/posix_acls.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a77fd1b429..ffcfbc4fb1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -801,14 +801,14 @@ static BOOL nt4_compatible_acls(void) not get. Deny entries are implicit on get with ace->perms = 0. ****************************************************************************/ -static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon_ace *ace, BOOL directory_ace) +static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_sid, canon_ace *ace, BOOL directory_ace) { SEC_ACCESS sa; uint32 nt_mask = 0; *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - if ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS) { + if (lp_acl_map_full_control(snum) && ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) { if (directory_ace) { nt_mask = UNIX_DIRECTORY_ACCESS_RWX; } else { @@ -2711,7 +2711,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) * Get the owner, group and world SIDs. */ - if (lp_profile_acls(SNUM(fsp->conn))) { + if (lp_profile_acls(SNUM(conn))) { /* For WXP SP1 the owner must be administrators. */ sid_copy(&owner_sid, &global_sid_Builtin_Administrators); sid_copy(&group_sid, &global_sid_Builtin_Users); @@ -2825,12 +2825,12 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) for (i = 0; i < num_acls; i++, ace = ace->next) { SEC_ACCESS acc; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace, fsp->is_directory); + acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0); } /* The User must have access to a profile share - even if we can't map the SID. */ - if (lp_profile_acls(SNUM(fsp->conn))) { + if (lp_profile_acls(SNUM(conn))) { SEC_ACCESS acc; init_sec_access(&acc,FILE_GENERIC_ALL); @@ -2843,7 +2843,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) for (i = 0; i < num_def_acls; i++, ace = ace->next) { SEC_ACCESS acc; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace, fsp->is_directory); + acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY| @@ -2851,7 +2851,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } /* The User must have access to a profile share - even if we can't map the SID. */ - if (lp_profile_acls(SNUM(fsp->conn))) { + if (lp_profile_acls(SNUM(conn))) { SEC_ACCESS acc; init_sec_access(&acc,FILE_GENERIC_ALL); -- cgit From af8a691db11a5072865f8b03fd1cbd3aab5cb6d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jul 2005 04:51:27 +0000 Subject: r8219: Merge the new open code from HEAD to 3.0. Haven't yet run the torture tests on this as it's very late NY time (just wanted to get this work into the tree). I'll test this over the weekend.... Jerry - in looking at the difference between the two trees there seem to be some printing/ntprinting.c and registry changes we might want to examine to try keep in sync. Jeremy. (This used to be commit c7fe18761e2c753afbffd3a78abff46472a9b8eb) --- source3/smbd/close.c | 46 +- source3/smbd/dir.c | 60 +- source3/smbd/dosmode.c | 2 +- source3/smbd/fake_file.c | 174 ++-- source3/smbd/fileio.c | 42 +- source3/smbd/files.c | 82 +- source3/smbd/ntquotas.c | 1 - source3/smbd/nttrans.c | 754 ++++++++--------- source3/smbd/open.c | 1906 +++++++++++++++++++++++++------------------ source3/smbd/oplock.c | 67 +- source3/smbd/oplock_linux.c | 8 +- source3/smbd/pipes.c | 89 +- source3/smbd/posix_acls.c | 40 +- source3/smbd/reply.c | 398 +++++---- source3/smbd/trans2.c | 257 +++--- source3/smbd/vfs-wrap.c | 6 +- source3/smbd/vfs.c | 20 +- 17 files changed, 2230 insertions(+), 1722 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index b7649bcce4..3fc7fdb059 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -3,6 +3,7 @@ file closing Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1992-2004. + Copyright (C) Volker Lendecke 2005 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 @@ -92,7 +93,7 @@ static int close_filestruct(files_struct *fsp) connection_struct *conn = fsp->conn; int ret = 0; - if (fsp->fd != -1) { + if (fsp->fh->fd != -1) { if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) ret = -1; @@ -148,7 +149,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) { share_mode_entry *share_entry = NULL; size_t share_entry_count = 0; - BOOL delete_on_close = False; + BOOL delete_file = False; connection_struct *conn = fsp->conn; int saved_errno = 0; int err = 0; @@ -194,34 +195,16 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) lock_share_entry_fsp(fsp); - if (fsp->delete_on_close) { - - /* - * Modify the share mode entry for all files open - * on this device and inode to tell other smbds we have - * changed the delete on close flag. The last closer will delete the file - * if flag is set. - */ - - NTSTATUS status =set_delete_on_close_over_all(fsp, fsp->delete_on_close); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) - DEBUG(0,("close_normal_file: failed to change delete on close flag for file %s\n", - fsp->fsp_name )); - } - - share_entry_count = del_share_mode(fsp, &share_entry); + share_entry_count = del_share_mode(fsp, &share_entry, + &delete_file); DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n", (unsigned long)share_entry_count, fsp->fsp_name )); - /* - * We delete on close if it's the last open, and the - * delete on close flag was set in the entry we just deleted. - */ - - if ((share_entry_count == 0) && share_entry && - GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) ) - delete_on_close = True; + if (share_entry_count != 0) { + /* We're not the last ones -- don't delete */ + delete_file = False; + } SAFE_FREE(share_entry); @@ -233,7 +216,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * reference to a file. */ - if (normal_close && delete_on_close) { + if (normal_close && delete_file) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { @@ -311,7 +294,8 @@ static int close_directory(files_struct *fsp, BOOL normal_close) * reference to a directory also. */ - if (normal_close && fsp->directory_delete_on_close) { + if (normal_close && + get_delete_on_close_flag(fsp->dev, fsp->inode)) { BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", fsp->fsp_name, ok ? "succeeded" : "failed" )); @@ -321,8 +305,9 @@ static int close_directory(files_struct *fsp, BOOL normal_close) * now fail as the directory has been deleted. */ - if(ok) + if(ok) { remove_pending_change_notify_requests_by_filename(fsp); + } process_pending_change_notify_queue((time_t)0); } @@ -331,8 +316,9 @@ static int close_directory(files_struct *fsp, BOOL normal_close) */ close_filestruct(fsp); - if (fsp->fsp_name) + if (fsp->fsp_name) { string_free(&fsp->fsp_name); + } file_free(fsp); return 0; diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index fd0a303504..949e31210f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -822,7 +822,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; - int smb_action; NTSTATUS status; uint32 access_granted; @@ -831,32 +830,41 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S * we never hide files from them. */ - if (conn->admin_user) + if (conn->admin_user) { return True; + } /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) { return False; + } /* Pseudo-open the file (note - no fd's created). */ - if(S_ISDIR(pst->st_mode)) - fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - &smb_action); - else + if(S_ISDIR(pst->st_mode)) { + fsp = open_directory(conn, name, pst, + READ_CONTROL_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, /* no create options. */ + NULL); + } else { fsp = open_file_stat(conn, name, pst); + } - if (!fsp) + if (!fsp) { return False; + } /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, True); /* No access if SD get failed. */ - if (!sd_size) + if (!sd_size) { return False; + } return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, &access_granted, &status); @@ -874,8 +882,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; - int smb_action; - int access_mode; + int info; NTSTATUS status; uint32 access_granted; @@ -884,27 +891,36 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ * we never hide files from them. */ - if (conn->admin_user) + if (conn->admin_user) { return True; + } /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) { return False; + } - /* Pseudo-open the file (note - no fd's created). */ + /* Pseudo-open the file */ - if(S_ISDIR(pst->st_mode)) + if(S_ISDIR(pst->st_mode)) { return True; - else - fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - &access_mode, &smb_action); + } else { + fsp = open_file_ntcreate(conn, name, pst, + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + INTERNAL_OPEN_ONLY, + &info); + } - if (!fsp) + if (!fsp) { return False; + } /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, False); diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 3602e3f908..a2bc424b8e 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -430,7 +430,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, if (!fsp) return -1; become_root(); - ret = SMB_VFS_FCHMOD(fsp, fsp->fd, unixmode); + ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); } diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 59ddb60db5..799725a782 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -22,77 +22,6 @@ extern struct current_user current_user; -/**************************************************************************** - Open a file with a share mode. -****************************************************************************/ -files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname, - SMB_STRUCT_STAT *psbuf, - uint32 desired_access, - int share_mode,int ofun, uint32 new_dos_attr, int oplock_request, - int *Access,int *action) -{ - int flags=0; - files_struct *fsp = NULL; - - if (fake_file_type == 0) { - return open_file_shared1(conn,fname,psbuf,desired_access, - share_mode,ofun,new_dos_attr, - oplock_request,Access,action); - } - - /* access check */ - if (current_user.uid != 0) { - DEBUG(1,("access_denied to service[%s] file[%s] user[%s]\n", - lp_servicename(SNUM(conn)),fname,conn->user)); - errno = EACCES; - return NULL; - } - - fsp = file_new(conn); - if(!fsp) - return NULL; - - DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, oplock request = %d\n", - fname, fsp->fnum, share_mode, ofun, oplock_request )); - - if (!check_name(fname,conn)) { - file_free(fsp); - return NULL; - } - - fsp->fd = -1; - fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; - fsp->vuid = current_user.vuid; - fsp->pos = -1; - fsp->can_lock = True; - fsp->can_read = ((flags & O_WRONLY)==0); - fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - fsp->share_mode = 0; - fsp->desired_access = desired_access; - fsp->print_file = False; - fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->is_directory = False; - fsp->is_stat = False; - fsp->directory_delete_on_close = False; - fsp->conn = conn; - string_set(&fsp->fsp_name,fname); - fsp->wcp = NULL; /* Write cache pointer. */ - - fsp->fake_file_handle = init_fake_file_handle(fake_file_type); - - if (fsp->fake_file_handle==NULL) { - file_free(fsp); - return NULL; - } - - conn->num_files_open++; - return fsp; -} - static FAKE_FILE fake_files[] = { #ifdef WITH_QUOTAS {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle}, @@ -100,24 +29,11 @@ static FAKE_FILE fake_files[] = { {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL } }; -int is_fake_file(char *fname) -{ - int i; - - if (!fname) - return 0; - - for (i=0;fake_files[i].name!=NULL;i++) { - if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) { - DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname)); - return fake_files[i].type; - } - } - - return FAKE_FILE_TYPE_NONE; -} +/**************************************************************************** + Create a fake file handle +****************************************************************************/ -struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) +static struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) { TALLOC_CTX *mem_ctx = NULL; FAKE_FILE_HANDLE *fh = NULL; @@ -141,8 +57,9 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) fh->type = type; fh->mem_ctx = mem_ctx; - if (fake_files[i].init_pd) + if (fake_files[i].init_pd) { fh->pd = fake_files[i].init_pd(fh->mem_ctx); + } fh->free_pd = fake_files[i].free_pd; @@ -153,13 +70,88 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) return NULL; } +/**************************************************************************** + Does this name match a fake filename ? +****************************************************************************/ + +enum FAKE_FILE_TYPE is_fake_file(const char *fname) +{ +#ifdef HAVE_SYS_QUOTAS + int i; +#endif + + if (!fname) { + return FAKE_FILE_TYPE_NONE; + } + +#ifdef HAVE_SYS_QUOTAS + for (i=0;fake_files[i].name!=NULL;i++) { + if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) { + DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname)); + return fake_files[i].type; + } + } +#endif + + return FAKE_FILE_TYPE_NONE; +} + + +/**************************************************************************** + Open a fake quota file with a share mode. +****************************************************************************/ + +files_struct *open_fake_file(connection_struct *conn, + enum FAKE_FILE_TYPE fake_file_type, + const char *fname, + uint32 access_mask) +{ + files_struct *fsp = NULL; + + /* access check */ + if (current_user.uid != 0) { + DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n", + lp_servicename(SNUM(conn)),fname,conn->user)); + errno = EACCES; + return NULL; + } + + fsp = file_new(conn); + if(!fsp) { + return NULL; + } + + DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n", + fname, fsp->fnum, (unsigned int)access_mask)); + + fsp->conn = conn; + fsp->fh->fd = -1; + fsp->vuid = current_user.vuid; + fsp->fh->pos = -1; + fsp->can_lock = True; /* Should this be true ? */ + fsp->access_mask = access_mask; + string_set(&fsp->fsp_name,fname); + + fsp->fake_file_handle = init_fake_file_handle(fake_file_type); + + if (fsp->fake_file_handle==NULL) { + file_free(fsp); + return NULL; + } + + conn->num_files_open++; + return fsp; +} + void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) { - if (!fh||!(*fh)) + if (!fh||!(*fh)) { return; + } - if ((*fh)->free_pd) + if ((*fh)->free_pd) { (*fh)->free_pd(&(*fh)->pd); + } talloc_destroy((*fh)->mem_ctx); (*fh) = NULL; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index ba0766c298..76189d114b 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -65,20 +65,20 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) */ if(read_from_write_cache(fsp, data, pos, n)) { - fsp->pos = pos + n; - fsp->position_information = fsp->pos; + fsp->fh->pos = pos + n; + fsp->fh->position_information = fsp->fh->pos; return n; } flush_write_cache(fsp, READ_FLUSH); - fsp->pos = pos; + fsp->fh->pos = pos; if (n > 0) { #ifdef DMF_FIX int numretries = 3; tryagain: - readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos); + readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos); if (readret == -1) { if ((errno == EAGAIN) && numretries) { @@ -90,7 +90,7 @@ tryagain: return -1; } #else /* NO DMF fix. */ - readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos); + readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos); if (readret == -1) { return -1; @@ -104,8 +104,8 @@ tryagain: DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); - fsp->pos += ret; - fsp->position_information = fsp->pos; + fsp->fh->pos += ret; + fsp->fh->position_information = fsp->fh->pos; return(ret); } @@ -124,7 +124,7 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos if (pos == -1) { ret = vfs_write_data(fsp, data, n); } else { - fsp->pos = pos; + fsp->fh->pos = pos; if (pos && lp_strict_allocate(SNUM(fsp->conn))) { if (vfs_fill_sparse(fsp, pos) == -1) { return -1; @@ -137,7 +137,7 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); if (ret != -1) { - fsp->pos += ret; + fsp->fh->pos += ret; /* * It turns out that setting the last write time from a Windows @@ -180,7 +180,7 @@ static int wcp_file_size_change(files_struct *fsp) write_cache *wcp = fsp->wcp; wcp->file_size = wcp->offset + wcp->data_size; - ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, wcp->file_size); + ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, wcp->file_size); if (ret == -1) { DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f error %s\n", fsp->fsp_name, (double)wcp->file_size, strerror(errno) )); @@ -221,7 +221,7 @@ ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) SMB_STRUCT_STAT st; fsp->modified = True; - if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) { + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st, False); @@ -288,9 +288,9 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", } DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", - fsp->fsp_name, fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); + fsp->fsp_name, fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); - fsp->pos = pos + n; + fsp->fh->pos = pos + n; /* * If we have active cache and it isn't contiguous then we flush. @@ -589,7 +589,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", */ DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \ -len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); +len = %u\n",fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); /* * If write would fit in the cache, and is larger than @@ -612,7 +612,7 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne if ((pos <= wcp->offset) && (pos + n >= wcp->offset + wcp->data_size) ) { DEBUG(9,("write_file: discarding overwritten write \ -cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned int)wcp->data_size )); +cache: fd = %d, off=%.0f, size=%u\n", fsp->fh->fd, (double)wcp->offset, (unsigned int)wcp->data_size )); wcp->data_size = 0; } @@ -635,7 +635,7 @@ cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned in if (cache_flush_needed) { DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", - write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, + write_path, fsp->fh->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); flush_write_cache(fsp, WRITE_FLUSH); @@ -809,7 +809,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]); DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", - fsp->fd, (double)wcp->offset, (unsigned int)data_size)); + fsp->fh->fd, (double)wcp->offset, (unsigned int)data_size)); #ifdef WITH_PROFILE if(data_size == wcp->alloc_size) { @@ -836,9 +836,9 @@ sync a file void sync_file(connection_struct *conn, files_struct *fsp) { - if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { + if(lp_strict_sync(SNUM(conn)) && fsp->fh->fd != -1) { flush_write_cache(fsp, SYNC_FLUSH); - SMB_VFS_FSYNC(fsp,fsp->fd); + SMB_VFS_FSYNC(fsp,fsp->fh->fd); } } @@ -849,9 +849,9 @@ void sync_file(connection_struct *conn, files_struct *fsp) int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) { - if (fsp->fd == -1) { + if (fsp->fh->fd == -1) { return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst); } else { - return SMB_VFS_FSTAT(fsp,fsp->fd, pst); + return SMB_VFS_FSTAT(fsp,fsp->fh->fd, pst); } } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e893e9fefc..80e5b0f710 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -106,7 +106,19 @@ files_struct *file_new(connection_struct *conn) } ZERO_STRUCTP(fsp); - fsp->fd = -1; + + fsp->fh = SMB_MALLOC_P(struct fd_handle); + if (!fsp->fh) { + SAFE_FREE(fsp); + set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY); + return NULL; + } + + ZERO_STRUCTP(fsp->fh); + + fsp->fh->ref_count = 1; + fsp->fh->fd = -1; + fsp->conn = conn; fsp->file_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); @@ -233,7 +245,7 @@ void file_dump_open_table(void) for (fsp=Files;fsp;fsp=fsp->next,count++) { DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n", - count, fsp->fnum, fsp->fsp_name, fsp->fd, (unsigned long)fsp->file_id, + count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->file_id, (unsigned int)fsp->dev, (double)fsp->inode )); } } @@ -248,7 +260,7 @@ files_struct *file_find_fd(int fd) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { - if (fsp->fd == fd) { + if (fsp->fh->fd == fd) { if (count > 10) { DLIST_PROMOTE(Files, fsp); } @@ -269,7 +281,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { - /* We can have a fsp->fd == -1 here as it could be a stat open. */ + /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */ if (fsp->dev == dev && fsp->inode == inode && fsp->file_id == file_id ) { @@ -277,7 +289,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i DLIST_PROMOTE(Files, fsp); } /* Paranoia check. */ - if (fsp->fd == -1 && fsp->oplock_type != NO_OPLOCK) { + if (fsp->fh->fd == -1 && fsp->oplock_type != NO_OPLOCK) { DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \ oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, (unsigned int)fsp->file_id, @@ -326,7 +338,7 @@ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) fsp_fi_cache.inode = inode; for (fsp=Files;fsp;fsp=fsp->next) { - if ( fsp->fd != -1 && + if ( fsp->fh->fd != -1 && fsp->dev == dev && fsp->inode == inode ) { /* Setup positive cache. */ @@ -349,7 +361,7 @@ files_struct *file_find_di_next(files_struct *start_fsp) files_struct *fsp; for (fsp = start_fsp->next;fsp;fsp=fsp->next) { - if ( fsp->fd != -1 && + if ( fsp->fh->fd != -1 && fsp->dev == start_fsp->dev && fsp->inode == start_fsp->inode ) return fsp; @@ -389,7 +401,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) } for (fsp = Files;fsp;fsp=fsp->next) { - if ( fsp->fd != -1 && + if ( fsp->fh->fd != -1 && fsp->dev == tfsp->dev && fsp->inode == tfsp->inode ) { fsp->pending_modtime = pmod; @@ -410,7 +422,7 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; - if ((conn == fsp->conn) && (fsp->fd != -1)) { + if ((conn == fsp->conn) && (fsp->fh->fd != -1)) { sync_file(conn,fsp); } } @@ -430,6 +442,12 @@ void file_free(files_struct *fsp) destroy_fake_file_handle(&fsp->fake_file_handle); } + if (fsp->fh->ref_count == 1) { + SAFE_FREE(fsp->fh); + } else { + fsp->fh->ref_count--; + } + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; @@ -506,3 +524,49 @@ void file_chain_restore(void) { chain_fsp = oplock_save_chain_fsp; } + +files_struct *dup_file_fsp(files_struct *fsp, + uint32 access_mask, + uint32 share_access, + uint32 create_options) +{ + files_struct *dup_fsp = file_new(fsp->conn); + + if (!dup_fsp) { + return NULL; + } + + SAFE_FREE(dup_fsp->fh); + + dup_fsp->fh = fsp->fh; + dup_fsp->fh->ref_count++; + + dup_fsp->dev = fsp->dev; + dup_fsp->inode = fsp->inode; + dup_fsp->initial_allocation_size = fsp->initial_allocation_size; + dup_fsp->mode = fsp->mode; + dup_fsp->file_pid = fsp->file_pid; + dup_fsp->vuid = fsp->vuid; + dup_fsp->open_time = fsp->open_time; + dup_fsp->access_mask = access_mask; + dup_fsp->share_access = share_access; + dup_fsp->pending_modtime_owner = fsp->pending_modtime_owner; + dup_fsp->pending_modtime = fsp->pending_modtime; + dup_fsp->last_write_time = fsp->last_write_time; + dup_fsp->oplock_type = fsp->oplock_type; + dup_fsp->can_lock = fsp->can_lock; + dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; + if (!CAN_WRITE(fsp->conn)) { + dup_fsp->can_write = False; + } else { + dup_fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; + } + dup_fsp->print_file = fsp->print_file; + dup_fsp->modified = fsp->modified; + dup_fsp->is_directory = fsp->is_directory; + dup_fsp->is_stat = fsp->is_stat; + dup_fsp->aio_write_behind = fsp->aio_write_behind; + string_set(&dup_fsp->fsp_name,fsp->fsp_name); + + return dup_fsp; +} diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 8fbf858008..9bc444d253 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -259,4 +259,3 @@ void destroy_quota_handle(void **pqt_handle) return; } - diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index cc37d531f2..f9b70de0ac 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -46,20 +46,12 @@ static const char *known_nt_pipes[] = { NULL }; -/* Map generic permissions to file object specific permissions */ - -struct generic_mapping file_generic_mapping = { - FILE_GENERIC_READ, - FILE_GENERIC_WRITE, - FILE_GENERIC_EXECUTE, - FILE_GENERIC_ALL -}; - static char *nttrans_realloc(char **ptr, size_t size) { char *tptr = NULL; - if (ptr==NULL) + if (ptr==NULL) { smb_panic("nttrans_realloc() called with NULL ptr\n"); + } tptr = SMB_REALLOC(*ptr, size); if(tptr == NULL) { @@ -99,8 +91,9 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e set_message(outbuf,18,0,True); - if (NT_STATUS_V(nt_error)) + if (NT_STATUS_V(nt_error)) { ERROR_NT(nt_error); + } /* * If there genuinely are no parameters or data to send just send @@ -108,8 +101,10 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e */ if(params_to_send == 0 && data_to_send == 0) { - if (!send_smb(smbd_server_fd(),outbuf)) + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) { exit_server("send_nt_replies: send_smb failed."); + } return 0; } @@ -119,8 +114,9 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e * can cause NT redirector problems. */ - if (((params_to_send % 4) != 0) && (data_to_send != 0)) + if (((params_to_send % 4) != 0) && (data_to_send != 0)) { data_alignment_offset = 4 - (params_to_send % 4); + } /* * Space is bufsize minus Netbios over TCP header minus SMB header. @@ -221,16 +217,18 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e * Copy the param bytes into the packet. */ - if(params_sent_thistime) + if(params_sent_thistime) { memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + } /* * Copy in the data bytes */ - if(data_sent_thistime) + if(data_sent_thistime) { memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ data_alignment_offset,pd,data_sent_thistime); + } DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", params_sent_thistime, data_sent_thistime, useable_space)); @@ -238,8 +236,10 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e params_to_send, data_to_send, paramsize, datasize)); /* Send the packet */ - if (!send_smb(smbd_server_fd(),outbuf)) + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) { exit_server("send_nt_replies: send_smb failed."); + } pp += params_sent_thistime; pd += data_sent_thistime; @@ -287,8 +287,9 @@ static BOOL saved_short_case_preserve; static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes) { - if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) + if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { return; + } saved_case_sensitive = conn->case_sensitive; saved_case_preserve = conn->case_preserve; @@ -306,200 +307,15 @@ static void set_posix_case_semantics(connection_struct *conn, uint32 file_attrib static void restore_case_semantics(connection_struct *conn, uint32 file_attributes) { - if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) + if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { return; + } conn->case_sensitive = saved_case_sensitive; conn->case_preserve = saved_case_preserve; conn->short_case_preserve = saved_short_case_preserve; } -/**************************************************************************** - Utility function to map create disposition. -****************************************************************************/ - -static int map_create_disposition( uint32 create_disposition) -{ - int ret; - - switch( create_disposition ) { - case FILE_CREATE: - /* create if not exist, fail if exist */ - ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL); - break; - case FILE_SUPERSEDE: - case FILE_OVERWRITE_IF: - /* create if not exist, trunc if exist */ - ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); - break; - case FILE_OPEN: - /* fail if not exist, open if exists */ - ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN); - break; - case FILE_OPEN_IF: - /* create if not exist, open if exists */ - ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_OPEN); - break; - case FILE_OVERWRITE: - /* fail if not exist, truncate if exists */ - ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE); - break; - default: - DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n", - create_disposition )); - return -1; - } - - DEBUG(10,("map_create_disposition: Mapped create_disposition 0x%lx to 0x%x\n", - (unsigned long)create_disposition, ret )); - - return ret; -} - -/**************************************************************************** - Utility function to map share modes. -****************************************************************************/ - -static int map_share_mode( char *fname, uint32 create_options, - uint32 *desired_access, uint32 share_access, uint32 file_attributes) -{ - int smb_open_mode = -1; - uint32 original_desired_access = *desired_access; - - /* This is a nasty hack - must fix... JRA. */ - if (*desired_access == MAXIMUM_ALLOWED_ACCESS) { - *desired_access = FILE_GENERIC_ALL; - } - - /* - * Convert GENERIC bits to specific bits. - */ - - se_map_generic(desired_access, &file_generic_mapping); - - switch( *desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) { - case FILE_READ_DATA: - smb_open_mode = DOS_OPEN_RDONLY; - break; - case FILE_WRITE_DATA: - case FILE_APPEND_DATA: - case FILE_WRITE_DATA|FILE_APPEND_DATA: - smb_open_mode = DOS_OPEN_WRONLY; - break; - case FILE_READ_DATA|FILE_WRITE_DATA: - case FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA: - case FILE_READ_DATA|FILE_APPEND_DATA: - smb_open_mode = DOS_OPEN_RDWR; - break; - } - - /* - * NB. For DELETE_ACCESS we should really check the - * directory permissions, as that is what controls - * delete, and for WRITE_DAC_ACCESS we should really - * check the ownership, as that is what controls the - * chmod. Note that this is *NOT* a security hole (this - * note is for you, Andrew) as we are not *allowing* - * the access at this point, the actual unlink or - * chown or chmod call would do this. We are just helping - * clients out by telling them if they have a hope - * of any of this succeeding. POSIX acls may still - * deny the real call. JRA. - */ - - if (smb_open_mode == -1) { - - if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS| - FILE_EXECUTE|FILE_READ_ATTRIBUTES| - FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS| - FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) { - smb_open_mode = DOS_OPEN_RDONLY; - } else if(*desired_access == 0) { - - /* - * JRA - NT seems to sometimes send desired_access as zero. play it safe - * and map to a stat open. - */ - - smb_open_mode = DOS_OPEN_RDONLY; - - } else { - DEBUG(0,("map_share_mode: Incorrect value 0x%lx for desired_access to file %s\n", - (unsigned long)*desired_access, fname)); - return -1; - } - } - - /* - * Set the special bit that means allow share delete. - * This is held outside the normal share mode bits at 1<<15. - * JRA. - */ - - if(share_access & FILE_SHARE_DELETE) { - smb_open_mode |= ALLOW_SHARE_DELETE; - DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode)); - } - - if(*desired_access & DELETE_ACCESS) { - DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); - } - - /* - * We need to store the intent to open for Delete. This - * is what determines if a delete on close flag can be set. - * This is the wrong way (and place) to store this, but for 2.2 this - * is the only practical way. JRA. - */ - - if (create_options & FILE_DELETE_ON_CLOSE) { - /* - * W2K3 bug compatibility mode... To set delete on close - * the redirector must have *specifically* set DELETE_ACCESS - * in the desired_access field. Just asking for GENERIC_ALL won't do. JRA. - */ - - if (!(original_desired_access & DELETE_ACCESS)) { - DEBUG(5,("map_share_mode: FILE_DELETE_ON_CLOSE requested without \ -DELETE_ACCESS for file %s. (desired_access = 0x%lx)\n", - fname, (unsigned long)*desired_access)); - return -1; - } - /* Implicit delete access is *NOT* requested... */ - smb_open_mode |= DELETE_ON_CLOSE_FLAG; - DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode)); - } - - /* Add in the requested share mode. */ - switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) { - case FILE_SHARE_READ: - smb_open_mode |= SET_DENY_MODE(DENY_WRITE); - break; - case FILE_SHARE_WRITE: - smb_open_mode |= SET_DENY_MODE(DENY_READ); - break; - case (FILE_SHARE_READ|FILE_SHARE_WRITE): - smb_open_mode |= SET_DENY_MODE(DENY_NONE); - break; - case FILE_SHARE_NONE: - smb_open_mode |= SET_DENY_MODE(DENY_ALL); - break; - } - - /* - * Handle an O_SYNC request. - */ - - if(file_attributes & FILE_FLAG_WRITE_THROUGH) - smb_open_mode |= FILE_SYNC_OPENMODE; - - DEBUG(10,("map_share_mode: Mapped desired access 0x%lx, share access 0x%lx, file attributes 0x%lx \ -to open_mode 0x%x\n", (unsigned long)*desired_access, (unsigned long)share_access, - (unsigned long)file_attributes, smb_open_mode )); - - return smb_open_mode; -} - /**************************************************************************** Reply to an NT create and X call on a pipe. ****************************************************************************/ @@ -508,7 +324,6 @@ static int nt_open_pipe(char *fname, connection_struct *conn, char *inbuf, char *outbuf, int *ppnum) { smb_np_struct *p = NULL; - uint16 vuid = SVAL(inbuf, smb_uid); int i; @@ -516,15 +331,19 @@ static int nt_open_pipe(char *fname, connection_struct *conn, /* See if it is one we want to handle. */ - if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) + if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) { return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); + } - for( i = 0; known_nt_pipes[i]; i++ ) - if( strequal(fname,known_nt_pipes[i])) + for( i = 0; known_nt_pipes[i]; i++ ) { + if( strequal(fname,known_nt_pipes[i])) { break; + } + } - if ( known_nt_pipes[i] == NULL ) + if ( known_nt_pipes[i] == NULL ) { return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); + } /* Strip \\ off the name. */ fname++; @@ -532,11 +351,11 @@ static int nt_open_pipe(char *fname, connection_struct *conn, DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); p = open_rpc_pipe_p(fname, conn, vuid); - if (!p) + if (!p) { return(ERROR_DOS(ERRSRV,ERRnofids)); + } *ppnum = p->pnum; - return 0; } @@ -554,8 +373,9 @@ static int do_ntcreate_pipe_open(connection_struct *conn, srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); - if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) + if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { return ret; + } /* * Deal with pipe return. @@ -582,6 +402,66 @@ static int do_ntcreate_pipe_open(connection_struct *conn, return chain_reply(inbuf,outbuf,length,bufsize); } +/**************************************************************************** + Reply to an NT create and X call for a quota file. +****************************************************************************/ + +int reply_ntcreate_and_X_quota(connection_struct *conn, + char *inbuf, + char *outbuf, + int length, + int bufsize, + enum FAKE_FILE_TYPE fake_file_type, + const char *fname) +{ + int result; + char *p; + uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); + files_struct *fsp = open_fake_file(conn, fake_file_type, fname, desired_access); + + if (!fsp) { + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + + set_message(outbuf,34,0,True); + + p = outbuf + smb_vwv2; + + /* SCVAL(p,0,NO_OPLOCK_RETURN); */ + p++; + SSVAL(p,0,fsp->fnum); +#if 0 + p += 2; + SIVAL(p,0,smb_action); + p += 4; + + /* Create time. */ + put_long_date(p,c_time); + p += 8; + put_long_date(p,sbuf.st_atime); /* access time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* write time */ + p += 8; + put_long_date(p,sbuf.st_mtime); /* change time */ + p += 8; + SIVAL(p,0,fattr); /* File Attributes. */ + p += 4; + SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); + p += 8; + SOFF_T(p,0,file_len); + p += 8; + if (flags & EXTENDED_RESPONSE_REQUIRED) + SSVAL(p,2,0x7); + p += 4; + SCVAL(p,0,fsp->is_directory ? 1 : 0); +#endif + + DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); + + result = chain_reply(inbuf,outbuf,length,bufsize); + return result; +} + /**************************************************************************** Reply to an NT create and X call. ****************************************************************************/ @@ -591,23 +471,20 @@ int reply_ntcreate_and_X(connection_struct *conn, { int result; pstring fname; - enum FAKE_FILE_TYPE fake_file_type = FAKE_FILE_TYPE_NONE; uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); - uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); + uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); - int smb_ofun; - int smb_open_mode; /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - int fmode=0,rmode=0; + uint32 fattr=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; - int smb_action = 0; + int info = 0; BOOL bad_path = False; files_struct *fsp=NULL; char *p = NULL; @@ -617,11 +494,16 @@ int reply_ntcreate_and_X(connection_struct *conn, START_PROFILE(SMBntcreateX); - DEBUG(10,("reply_ntcreateX: flags = 0x%x, desired_access = 0x%x \ + DEBUG(10,("reply_ntcreateX: flags = 0x%x, access_mask = 0x%x \ file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \ -create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attributes, - share_access, create_disposition, - create_options, root_dir_fid )); +create_options = 0x%x root_dir_fid = 0x%x\n", + (unsigned int)flags, + (unsigned int)access_mask, + (unsigned int)file_attributes, + (unsigned int)share_access, + (unsigned int)create_disposition, + (unsigned int)create_options, + (unsigned int)root_dir_fid )); /* If it's an IPC, use the pipe handler. */ @@ -640,16 +522,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - /* - * We need to construct the open_and_X ofun value from the - * NT values, as that's what our code is structured to accept. - */ - - if((smb_ofun = map_create_disposition( create_disposition )) == -1) { - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - /* * Get the file name. */ @@ -729,25 +601,25 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib */ if( is_ntfs_stream_name(fname)) { - -#ifdef HAVE_SYS_QUOTAS - if ((fake_file_type=is_fake_file(fname))!=FAKE_FILE_TYPE_NONE) { + enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname); + if (fake_file_type!=FAKE_FILE_TYPE_NONE) { /* - * here we go! support for changing the disk quotas --metze + * Here we go! support for changing the disk quotas --metze * - * we need to fake up to open this MAGIC QUOTA file - * and return a valid FID + * We need to fake up to open this MAGIC QUOTA file + * and return a valid FID. * * w2k close this file directly after openening * xp also tries a QUERY_FILE_INFO on the file and then close it */ + result = reply_ntcreate_and_X_quota(conn, inbuf, outbuf, length, bufsize, + fake_file_type, fname); + END_PROFILE(SMBntcreateX); + return result; } else { -#endif END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); -#ifdef HAVE_SYS_QUOTAS } -#endif } } @@ -757,13 +629,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib */ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - if((smb_open_mode = map_share_mode(fname, create_options, &desired_access, - share_access, - file_attributes)) == -1) { - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; if (oplock_request) { oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; @@ -781,20 +646,16 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib unix_convert(fname,conn,0,&bad_path,&sbuf); - /* FAKE_FILE is a special case */ - if (fake_file_type == FAKE_FILE_TYPE_NONE) { - /* Normal file. */ - if (bad_path) { - restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } - /* All file access must go through check_name() */ - if (!check_name(fname,conn)) { - restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); - } + if (bad_path) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } + /* All file access must go through check_name() */ + if (!check_name(fname,conn)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } #if 0 @@ -805,7 +666,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if (desired_access & DELETE_ACCESS) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) + && (access_mask & DELETE_ACCESS)) { #endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the @@ -814,7 +676,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); } } @@ -831,8 +693,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); - + fsp = open_directory(conn, fname, &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + &info); + restore_case_semantics(conn, file_attributes); if(!fsp) { @@ -857,21 +724,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * before issuing an oplock break request to * our client. JRA. */ - if (fake_file_type==FAKE_FILE_TYPE_NONE) { - fsp = open_file_shared1(conn,fname,&sbuf, - desired_access, - smb_open_mode, - smb_ofun,file_attributes,oplock_request, - &rmode,&smb_action); - } else { - /* to open a fake_file --metze */ - fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf, - desired_access, - smb_open_mode, - smb_ofun,file_attributes, oplock_request, - &rmode,&smb_action); - } - + fsp = open_file_ntcreate(conn,fname,&sbuf, + access_mask, + share_access, + create_disposition, + create_options, + file_attributes, + oplock_request, + &info); if (!fsp) { /* We cheat here. There are two cases we * care about. One is a directory rename, @@ -905,8 +765,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); - + fsp = open_directory(conn, fname, &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + &info); + if(!fsp) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); @@ -928,18 +793,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib restore_case_semantics(conn, file_attributes); file_len = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) { - fmode = FILE_ATTRIBUTE_NORMAL; + fattr = dos_mode(conn,fname,&sbuf); + if(fattr == 0) { + fattr = FILE_ATTRIBUTE_NORMAL; } - if (!fsp->is_directory && (fmode & aDIR)) { + if (!fsp->is_directory && (fattr & aDIR)) { close_file(fsp,False); END_PROFILE(SMBntcreateX); return ERROR_DOS(ERRDOS,ERRnoaccess); } /* Save the requested allocation size. */ - if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); #ifdef LARGE_SMB_OFF_T allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); @@ -1005,10 +870,11 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib p++; SSVAL(p,0,fsp->fnum); p += 2; - if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN)) + if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) { SIVAL(p,0,FILE_WAS_SUPERSEDED); - else - SIVAL(p,0,smb_action); + } else { + SIVAL(p,0,info); + } p += 4; /* Create time. */ @@ -1029,14 +895,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib p += 8; put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ + SIVAL(p,0,fattr); /* File Attributes. */ p += 4; SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; - if (flags & EXTENDED_RESPONSE_REQUIRED) + if (flags & EXTENDED_RESPONSE_REQUIRED) { SSVAL(p,2,0x7); + } p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); @@ -1077,13 +944,15 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha return ERROR_NT(status); } - if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) + if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { return ret; + } /* Realloc the size of parameters and data we will return */ params = nttrans_realloc(ppparams, 69); - if(params == NULL) + if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } p = params; SCVAL(p,0,NO_OPLOCK_RETURN); @@ -1156,16 +1025,20 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu return NT_STATUS_NO_MEMORY; } - if (psd->off_owner_sid==0) + if (psd->off_owner_sid==0) { security_info_sent &= ~OWNER_SECURITY_INFORMATION; - if (psd->off_grp_sid==0) + } + if (psd->off_grp_sid==0) { security_info_sent &= ~GROUP_SECURITY_INFORMATION; - if (psd->off_sacl==0) + } + if (psd->off_sacl==0) { security_info_sent &= ~SACL_SECURITY_INFORMATION; - if (psd->off_dacl==0) + } + if (psd->off_dacl==0) { security_info_sent &= ~DACL_SECURITY_INFORMATION; + } - ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fd, security_info_sent, psd); + ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd); if (!ret) { talloc_destroy(mem_ctx); @@ -1219,16 +1092,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o char *data = *ppdata; /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; - int fmode=0,rmode=0; + uint32 fattr=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; - int smb_action = 0; + int info = 0; BOOL bad_path = False; files_struct *fsp = NULL; char *p = NULL; BOOL extended_oplock_granted = False; uint32 flags; - uint32 desired_access; + uint32 access_mask; uint32 file_attributes; uint32 share_access; uint32 create_disposition; @@ -1236,8 +1109,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o uint32 sd_len; uint32 ea_len; uint16 root_dir_fid; - int smb_ofun; - int smb_open_mode; time_t c_time; struct ea_list *ea_list = NULL; TALLOC_CTX *ctx = NULL; @@ -1251,14 +1122,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ if (IS_IPC(conn)) { - if (lp_nt_pipe_support()) + if (lp_nt_pipe_support()) { return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, bufsize, ppsetup, setup_count, ppparams, parameter_count, ppdata, data_count); - else + } else { return ERROR_DOS(ERRDOS,ERRnoaccess); + } } /* @@ -1271,7 +1143,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } flags = IVAL(params,0); - desired_access = IVAL(params,8); + access_mask = IVAL(params,8); file_attributes = IVAL(params,20); share_access = IVAL(params,24); create_disposition = IVAL(params,28); @@ -1307,15 +1179,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - /* - * We need to construct the open_and_X ofun value from the - * NT values, as that's what our code is structured to accept. - */ - - if((smb_ofun = map_create_disposition( create_disposition )) == -1) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - /* * Get the file name. */ @@ -1327,8 +1190,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o files_struct *dir_fsp = file_fsp(params,4); size_t dir_name_len; - if(!dir_fsp) + if(!dir_fsp) { return ERROR_DOS(ERRDOS,ERRbadfid); + } if(!dir_fsp->is_directory) { srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False); @@ -1386,15 +1250,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } - /* - * Now contruct the smb_open_mode value from the desired access - * and the share access. - */ - - if((smb_open_mode = map_share_mode( fname, create_options, &desired_access, - share_access, file_attributes)) == -1) - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; @@ -1425,7 +1280,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (desired_access & DELETE_ACCESS) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS)) { #endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the @@ -1478,8 +1333,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * CreateDirectory() call. */ - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); - + fsp = open_directory(conn, fname, &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + &info); if(!fsp) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); @@ -1492,9 +1351,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Ordinary file case. */ - fsp = open_file_shared1(conn,fname,&sbuf,desired_access, - smb_open_mode,smb_ofun,file_attributes, - oplock_request,&rmode,&smb_action); + fsp = open_file_ntcreate(conn,fname,&sbuf, + access_mask, + share_access, + create_disposition, + create_options, + file_attributes, + oplock_request, + &info); if (!fsp) { if(errno == EISDIR) { @@ -1509,8 +1373,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); - + fsp = open_directory(conn, fname, &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + &info); if(!fsp) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); @@ -1539,12 +1407,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Patch for bug #2242 from Tom Lackemann . */ - if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) { - uint32 saved_access = fsp->desired_access; + if (lp_nt_acl_support(SNUM(conn)) && sd_len && info == FILE_WAS_CREATED) { + uint32 saved_access_mask = fsp->access_mask; /* We have already checked that sd_len <= data_count here. */ - fsp->desired_access = FILE_GENERIC_ALL; + fsp->access_mask = FILE_GENERIC_ALL; status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION); if (!NT_STATUS_IS_OK(status)) { @@ -1553,10 +1421,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } - fsp->desired_access = saved_access; + fsp->access_mask = saved_access_mask; } - if (ea_len && (smb_action == FILE_WAS_CREATED)) { + if (ea_len && (info == FILE_WAS_CREATED)) { status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); if (!NT_STATUS_IS_OK(status)) { @@ -1569,17 +1437,17 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o restore_case_semantics(conn, file_attributes); file_len = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) { - fmode = FILE_ATTRIBUTE_NORMAL; + fattr = dos_mode(conn,fname,&sbuf); + if(fattr == 0) { + fattr = FILE_ATTRIBUTE_NORMAL; } - if (!fsp->is_directory && (fmode & aDIR)) { + if (!fsp->is_directory && (fattr & aDIR)) { close_file(fsp,False); return ERROR_DOS(ERRDOS,ERRnoaccess); } /* Save the requested allocation size. */ - if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12); #ifdef LARGE_SMB_OFF_T allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); @@ -1616,24 +1484,27 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* Realloc the size of parameters and data we will return */ params = nttrans_realloc(ppparams, 69); - if(params == NULL) + if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } p = params; - if (extended_oplock_granted) + if (extended_oplock_granted) { SCVAL(p,0, BATCH_OPLOCK_RETURN); - else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) + } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); - else + } else { SCVAL(p,0,NO_OPLOCK_RETURN); + } p += 2; SSVAL(p,0,fsp->fnum); p += 2; - if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN)) + if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) { SIVAL(p,0,FILE_WAS_SUPERSEDED); - else - SIVAL(p,0,smb_action); + } else { + SIVAL(p,0,info); + } p += 8; /* Create time. */ @@ -1654,14 +1525,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o p += 8; put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; - SIVAL(p,0,fmode); /* File Attributes. */ + SIVAL(p,0,fattr); /* File Attributes. */ p += 4; SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; - if (flags & EXTENDED_RESPONSE_REQUIRED) + if (flags & EXTENDED_RESPONSE_REQUIRED) { SSVAL(p,2,0x7); + } p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); @@ -1700,7 +1572,7 @@ int reply_ntcancel(connection_struct *conn, Copy a file. ****************************************************************************/ -static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint16 attrs) +static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs) { BOOL bad_path_oldname = False; BOOL bad_path_newname = False; @@ -1708,9 +1580,8 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new pstring last_component_oldname; pstring last_component_newname; files_struct *fsp1,*fsp2; - uint16 fmode; - int access_mode; - int smb_action; + uint32 fattr; + int info; SMB_OFF_T ret=-1; int close_ret; NTSTATUS status = NT_STATUS_OK; @@ -1747,9 +1618,10 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new } /* Ensure attributes match. */ - fmode = dos_mode(conn,oldname,&sbuf1); - if ((fmode & ~attrs) & (aHIDDEN | aSYSTEM)) + fattr = dos_mode(conn,oldname,&sbuf1); + if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) { return NT_STATUS_NO_SUCH_FILE; + } unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); if (bad_path_newname) { @@ -1784,9 +1656,14 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); - fsp1 = open_file_shared1(conn,oldname,&sbuf1,FILE_READ_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0, - &access_mode,&smb_action); + fsp1 = open_file_ntcreate(conn,oldname,&sbuf1, + FILE_READ_DATA, /* Read-only. */ + 0, /* No sharing. */ + FILE_OPEN, + 0, /* No create options. */ + FILE_ATTRIBUTE_NORMAL, + INTERNAL_OPEN_ONLY, + &info); if (!fsp1) { get_saved_error_triple(NULL, NULL, &status); @@ -1797,9 +1674,14 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return status; } - fsp2 = open_file_shared1(conn,newname,&sbuf2,FILE_WRITE_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL),fmode,INTERNAL_OPEN_ONLY, - &access_mode,&smb_action); + fsp2 = open_file_ntcreate(conn,newname,&sbuf2, + FILE_WRITE_DATA, /* Read-only. */ + 0, /* No sharing. */ + FILE_CREATE, + 0, /* No create options. */ + fattr, + INTERNAL_OPEN_ONLY, + &info); if (!fsp2) { get_saved_error_triple(NULL, NULL, &status); @@ -1811,8 +1693,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return status; } - if (sbuf1.st_size) + if (sbuf1.st_size) { ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size); + } /* * As we are opening fsp1 read-only we only expect @@ -1829,7 +1712,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new /* Grrr. We have to do this as open_file_shared1 adds aARCH when it creates the file. This isn't the correct thing to do in the copy case. JRA */ - file_set_dosmode(conn, newname, fmode, &sbuf2, True); + file_set_dosmode(conn, newname, fattr, &sbuf2, True); if (ret < (SMB_OFF_T)sbuf1.st_size) { return NT_STATUS_DISK_FULL; @@ -1855,7 +1738,7 @@ int reply_ntrename(connection_struct *conn, pstring newname; char *p; NTSTATUS status; - uint16 attrs = SVAL(inbuf,smb_vwv0); + uint32 attrs = SVAL(inbuf,smb_vwv0); uint16 rename_type = SVAL(inbuf,smb_vwv1); START_PROFILE(SMBntrename); @@ -1955,22 +1838,26 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, files_struct *fsp; uint32 flags; - if(setup_count < 6) + if(setup_count < 6) { return ERROR_DOS(ERRDOS,ERRbadfunc); + } fsp = file_fsp(setup,4); flags = IVAL(setup, 0); DEBUG(3,("call_nt_transact_notify_change\n")); - if(!fsp) + if(!fsp) { return ERROR_DOS(ERRDOS,ERRbadfid); + } - if((!fsp->is_directory) || (conn != fsp->conn)) + if((!fsp->is_directory) || (conn != fsp->conn)) { return ERROR_DOS(ERRDOS,ERRbadfid); + } - if (!change_notify_set(inbuf, fsp, conn, flags)) + if (!change_notify_set(inbuf, fsp, conn, flags)) { return(UNIXERROR(ERRDOS,ERRbadfid)); + } DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ name = %s\n", fsp->fsp_name )); @@ -1993,8 +1880,9 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o BOOL replace_if_exists = False; NTSTATUS status; - if(parameter_count < 4) + if(parameter_count < 4) { return ERROR_DOS(ERRDOS,ERRbadfunc); + } fsp = file_fsp(params, 0); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; @@ -2062,12 +1950,14 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i TALLOC_CTX *mem_ctx; files_struct *fsp = NULL; - if(parameter_count < 8) + if(parameter_count < 8) { return ERROR_DOS(ERRDOS,ERRbadfunc); + } fsp = file_fsp(params,0); - if(!fsp) + if(!fsp) { return ERROR_DOS(ERRDOS,ERRbadfid); + } security_info_wanted = IVAL(params,4); @@ -2075,8 +1965,9 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i (unsigned int)security_info_wanted )); params = nttrans_realloc(ppparams, 4); - if(params == NULL) + if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) { DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); @@ -2087,10 +1978,11 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i * Get the permissions to return. */ - if (!lp_nt_acl_support(SNUM(conn))) + if (!lp_nt_acl_support(SNUM(conn))) { sd_size = get_null_nt_acl(mem_ctx, &psd); - else - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, security_info_wanted, &psd); + } else { + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, security_info_wanted, &psd); + } if (sd_size == 0) { talloc_destroy(mem_ctx); @@ -2171,25 +2063,30 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb uint32 security_info_sent = 0; NTSTATUS nt_status; - if(parameter_count < 8) + if(parameter_count < 8) { return ERROR_DOS(ERRDOS,ERRbadfunc); + } - if((fsp = file_fsp(params,0)) == NULL) + if((fsp = file_fsp(params,0)) == NULL) { return ERROR_DOS(ERRDOS,ERRbadfid); + } - if(!lp_nt_acl_support(SNUM(conn))) + if(!lp_nt_acl_support(SNUM(conn))) { goto done; + } security_info_sent = IVAL(params,4); DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, (unsigned int)security_info_sent )); - if (data_count == 0) + if (data_count == 0) { return ERROR_DOS(ERRDOS, ERRnoaccess); + } - if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) + if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) { return ERROR_NT(nt_status); + } done: @@ -2520,8 +2417,9 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, /* Realloc the size of parameters and data we will return */ param_len = 4; params = nttrans_realloc(ppparams, param_len); - if(params == NULL) + if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } data_len = 0; SIVAL(params,0,data_len); @@ -2544,19 +2442,20 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, /* Realloc the size of parameters and data we will return */ param_len = 4; params = nttrans_realloc(ppparams, param_len); - if(params == NULL) + if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } /* we should not trust the value in max_data_count*/ max_data_count = MIN(max_data_count,2048); pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/ - if(pdata == NULL) + if(pdata == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } entry = pdata; - /* set params Size of returned Quota Data 4 bytes*/ /* but set it later when we know it */ @@ -2641,7 +2540,6 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, sid_parse(pdata+8,sid_len,&sid); - if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) { ZERO_STRUCT(qt); /* @@ -2654,12 +2552,14 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, /* Realloc the size of parameters and data we will return */ param_len = 4; params = nttrans_realloc(ppparams, param_len); - if(params == NULL) + if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } pdata = nttrans_realloc(ppdata, data_len); - if(pdata == NULL) + if(pdata == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); + } entry = pdata; @@ -2884,12 +2784,15 @@ due to being in oplock break state.\n", (unsigned int)function_code )); /* Allocate the space for the setup, the maximum needed parameters and data */ - if(setup_count > 0) + if(setup_count > 0) { setup = (char *)SMB_MALLOC(setup_count); - if (total_parameter_count > 0) + } + if (total_parameter_count > 0) { params = (char *)SMB_MALLOC(total_parameter_count); - if (total_data_count > 0) + } + if (total_data_count > 0) { data = (char *)SMB_MALLOC(total_data_count); + } if ((total_parameter_count && !params) || (total_data_count && !data) || (setup_count && !setup)) { @@ -2911,10 +2814,12 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if(setup) { DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count)); if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) || - (smb_nt_SetupStart + setup_count < setup_count)) + (smb_nt_SetupStart + setup_count < setup_count)) { goto bad_param; - if (smb_nt_SetupStart + setup_count > length) + } + if (smb_nt_SetupStart + setup_count > length) { goto bad_param; + } memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); dump_data(10, setup, setup_count); @@ -2922,22 +2827,26 @@ due to being in oplock break state.\n", (unsigned int)function_code )); if(params) { DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count)); if ((parameter_offset + parameter_count < parameter_offset) || - (parameter_offset + parameter_count < parameter_count)) + (parameter_offset + parameter_count < parameter_count)) { goto bad_param; + } if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)|| - (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) + (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) { goto bad_param; + } memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); dump_data(10, params, parameter_count); } if(data) { DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); - if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) + if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) { goto bad_param; + } if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || - (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) + (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) { goto bad_param; + } memcpy( data, smb_base(inbuf) + data_offset, data_count); dump_data(10, data, data_count); @@ -2950,8 +2859,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); of the parameter/data bytes */ outsize = set_message(outbuf,0,0,True); srv_signing_trans_stop(); - if (!send_smb(smbd_server_fd(),outbuf)) + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) { exit_server("reply_nttrans: send_smb failed."); + } while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { BOOL ret; @@ -2982,10 +2893,12 @@ due to being in oplock break state.\n", (unsigned int)function_code )); } /* Revise total_params and total_data in case they have changed downwards */ - if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) + if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) { total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); - if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) + } + if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) { total_data_count = IVAL(inbuf, smb_nts_TotalDataCount); + } parameter_count = IVAL(inbuf,smb_nts_ParameterCount); parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset); @@ -3003,43 +2916,54 @@ due to being in oplock break state.\n", (unsigned int)function_code )); } if (parameter_count) { - if (parameter_displacement + parameter_count > total_parameter_count) + if (parameter_displacement + parameter_count > total_parameter_count) { goto bad_param; + } if ((parameter_displacement + parameter_count < parameter_displacement) || - (parameter_displacement + parameter_count < parameter_count)) + (parameter_displacement + parameter_count < parameter_count)) { goto bad_param; - if (parameter_displacement > total_parameter_count) + } + if (parameter_displacement > total_parameter_count) { goto bad_param; + } if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) || - (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) + (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) { goto bad_param; - if (parameter_displacement + params < params) + } + if (parameter_displacement + params < params) { goto bad_param; + } memcpy( ¶ms[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count); } if (data_count) { - if (data_displacement + data_count > total_data_count) + if (data_displacement + data_count > total_data_count) { goto bad_param; + } if ((data_displacement + data_count < data_displacement) || - (data_displacement + data_count < data_count)) + (data_displacement + data_count < data_count)) { goto bad_param; - if (data_displacement > total_data_count) + } + if (data_displacement > total_data_count) { goto bad_param; + } if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || - (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) + (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) { goto bad_param; - if (data_displacement + data < data) + } + if (data_displacement + data < data) { goto bad_param; + } memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count); } } } - if (Protocol >= PROTOCOL_NT1) + if (Protocol >= PROTOCOL_NT1) { SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME); + } /* Now we must call the relevant NT_TRANS function */ switch(function_code) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9da53a5057..810913c025 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3,6 +3,7 @@ file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 2001-2004 + Copyright (C) Volker Lendecke 2005 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 @@ -36,13 +37,16 @@ struct dev_inode_bundle { fd support routines - attempt to do a dos_open. ****************************************************************************/ -static int fd_open(struct connection_struct *conn, const char *fname, - int flags, mode_t mode) +static int fd_open(struct connection_struct *conn, + const char *fname, + int flags, + mode_t mode) { int fd; #ifdef O_NOFOLLOW - if (!lp_symlinks(SNUM(conn))) + if (!lp_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; + } #endif fd = SMB_VFS_OPEN(conn,fname,flags,mode); @@ -57,10 +61,15 @@ static int fd_open(struct connection_struct *conn, const char *fname, Close the file associated with a fsp. ****************************************************************************/ -int fd_close(struct connection_struct *conn, files_struct *fsp) +int fd_close(struct connection_struct *conn, + files_struct *fsp) { - if (fsp->fd == -1) - return 0; /* what we used to call a stat open. */ + if (fsp->fh->fd == -1) { + return 0; /* What we used to call a stat open. */ + } + if (fsp->fh->ref_count > 1) { + return 0; /* Shared handle. Only close last reference. */ + } return fd_close_posix(conn, fsp); } @@ -86,7 +95,10 @@ static void check_for_pipe(const char *fname) Do this by fd if possible. ****************************************************************************/ -void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf) +void change_owner_to_parent(connection_struct *conn, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) { const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; @@ -94,56 +106,67 @@ void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const ch ret = SMB_VFS_STAT(conn, parent_path, &parent_st); if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat parent directory %s. Error was %s\n", - parent_path, strerror(errno) )); + DEBUG(0,("change_owner_to_parent: failed to stat parent " + "directory %s. Error was %s\n", + parent_path, strerror(errno) )); return; } - if (fsp && fsp->fd != -1) { + if (fsp && fsp->fh->fd != -1) { become_root(); - ret = SMB_VFS_FCHOWN(fsp, fsp->fd, parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to fchown file %s to parent directory uid %u. \ -Error was %s\n", - fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + DEBUG(0,("change_owner_to_parent: failed to fchown " + "file %s to parent directory uid %u. Error " + "was %s\n", fname, + (unsigned int)parent_st.st_uid, + strerror(errno) )); } - DEBUG(10,("change_owner_to_parent: changed new file %s to parent directory uid %u.\n", - fname, (unsigned int)parent_st.st_uid )); + DEBUG(10,("change_owner_to_parent: changed new file %s to " + "parent directory uid %u.\n", fname, + (unsigned int)parent_st.st_uid )); } else { - /* We've already done an lstat into psbuf, and we know it's a directory. If - we can cd into the directory and the dev/ino are the same then we can safely - chown without races as we're locking the directory in place by being in it. - This should work on any UNIX (thanks tridge :-). JRA. + /* We've already done an lstat into psbuf, and we know it's a + directory. If we can cd into the directory and the dev/ino + are the same then we can safely chown without races as + we're locking the directory in place by being in it. This + should work on any UNIX (thanks tridge :-). JRA. */ pstring saved_dir; SMB_STRUCT_STAT sbuf; if (!vfs_GetWd(conn,saved_dir)) { - DEBUG(0,("change_owner_to_parent: failed to get current working directory\n")); + DEBUG(0,("change_owner_to_parent: failed to get " + "current working directory\n")); return; } /* Chdir into the new path. */ if (vfs_ChDir(conn, fname) == -1) { - DEBUG(0,("change_owner_to_parent: failed to change current working directory to %s. \ -Error was %s\n", fname, strerror(errno) )); + DEBUG(0,("change_owner_to_parent: failed to change " + "current working directory to %s. Error " + "was %s\n", fname, strerror(errno) )); goto out; } if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat directory '.' (%s) \ -Error was %s\n", fname, strerror(errno))); + DEBUG(0,("change_owner_to_parent: failed to stat " + "directory '.' (%s) Error was %s\n", + fname, strerror(errno))); goto out; } /* Ensure we're pointing at the same place. */ - if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { - DEBUG(0,("change_owner_to_parent: device/inode/mode on directory %s changed. Refusing to chown !\n", - fname )); + if (sbuf.st_dev != psbuf->st_dev || + sbuf.st_ino != psbuf->st_ino || + sbuf.st_mode != psbuf->st_mode ) { + DEBUG(0,("change_owner_to_parent: " + "device/inode/mode on directory %s changed. " + "Refusing to chown !\n", fname )); goto out; } @@ -151,14 +174,16 @@ Error was %s\n", fname, strerror(errno))); ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to chown directory %s to parent directory uid %u. \ -Error was %s\n", - fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + DEBUG(10,("change_owner_to_parent: failed to chown " + "directory %s to parent directory uid %u. " + "Error was %s\n", fname, + (unsigned int)parent_st.st_uid, strerror(errno) )); goto out; } - DEBUG(10,("change_owner_to_parent: changed ownership of new directory %s to parent directory uid %u.\n", - fname, (unsigned int)parent_st.st_uid )); + DEBUG(10,("change_owner_to_parent: changed ownership of new " + "directory %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); out: @@ -170,13 +195,19 @@ Error was %s\n", Open a file. ****************************************************************************/ -static BOOL open_file(files_struct *fsp,connection_struct *conn, - const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) +static BOOL open_file(files_struct *fsp, + connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + int flags, + mode_t unx_mode, + uint32 access_mask) { int accmode = (flags & O_ACCMODE); int local_flags = flags; + BOOL file_existed = VALID_STAT(*psbuf); - fsp->fd = -1; + fsp->fh->fd = -1; fsp->oplock_type = NO_OPLOCK; errno = EPERM; @@ -199,9 +230,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, check_for_pipe(fname); return False; } else if(flags & O_CREAT) { - /* We don't want to write - but we must make sure that O_CREAT - doesn't create the file if we have write access into the - directory. + /* We don't want to write - but we must make sure that + O_CREAT doesn't create the file if we have write + access into the directory. */ flags &= ~O_CREAT; local_flags &= ~O_CREAT; @@ -221,12 +252,14 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, */ if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { - DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname )); + DEBUG(10,("open_file: truncate requested on read-only open " + "for file %s\n",fname )); local_flags = (flags & ~O_ACCMODE)|O_RDWR; } - if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || - (local_flags & O_CREAT) || ((local_flags & O_TRUNC) == O_TRUNC) ) { + if ((access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + (local_flags & O_CREAT) || + ((local_flags & O_TRUNC) == O_TRUNC) ) { /* * We can't actually truncate here as the file may be locked. @@ -242,42 +275,50 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * open flags. JRA. */ - if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode)) + if (file_existed && S_ISFIFO(psbuf->st_mode)) { local_flags |= O_NONBLOCK; + } #endif /* Don't create files with Microsoft wildcard characters. */ - if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { - set_saved_error_triple(ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID); + if ((local_flags & O_CREAT) && !file_existed && + ms_has_wild(fname)) { + set_saved_error_triple(ERRDOS, ERRinvalidname, + NT_STATUS_OBJECT_NAME_INVALID); return False; } /* Actually do the open */ - fsp->fd = fd_open(conn, fname, local_flags, mode); - if (fsp->fd == -1) { - DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", + fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode); + if (fsp->fh->fd == -1) { + DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " + "(flags=%d)\n", fname,strerror(errno),local_flags,flags)); check_for_pipe(fname); return False; } /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) - inherit_access_acl(conn, fname, mode); + if ((local_flags & O_CREAT) && !file_existed) { + inherit_access_acl(conn, fname, unx_mode); + } - } else - fsp->fd = -1; /* What we used to call a stat open. */ + } else { + fsp->fh->fd = -1; /* What we used to call a stat open. */ + } - if (!VALID_STAT(*psbuf)) { + if (!file_existed) { int ret; - if (fsp->fd == -1) + if (fsp->fh->fd == -1) { ret = SMB_VFS_STAT(conn, fname, psbuf); - else { - ret = SMB_VFS_FSTAT(fsp,fsp->fd,psbuf); + } else { + ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf); /* If we have an fd, this stat should succeed. */ - if (ret == -1) - DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); + if (ret == -1) { + DEBUG(0,("Error doing fstat on open file %s " + "(%s)\n", fname,strerror(errno) )); + } } /* For a non-io open, this stat failing means file not found. JRA */ @@ -305,18 +346,20 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = True; - fsp->can_read = ((flags & O_WRONLY)==0); - fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - fsp->share_mode = 0; - fsp->desired_access = desired_access; + fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; + if (!CAN_WRITE(conn)) { + fsp->can_write = False; + } else { + fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; + } fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; - fsp->directory_delete_on_close = False; - if (conn->aio_write_behind_list && is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { + if (conn->aio_write_behind_list && + is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { fsp->aio_write_behind = True; } @@ -349,293 +392,119 @@ static BOOL is_executable(const char *fname) return False; } -enum {AFAIL,AREAD,AWRITE,AALL}; - -/******************************************************************* - Reproduce the share mode access table. - This is horrendoously complex, and really can't be justified on any - rational grounds except that this is _exactly_ what NT does. See - the DENY1 and DENY2 tests in smbtorture for a comprehensive set of - test routines. -********************************************************************/ - -static int access_table(int new_deny,int old_deny,int old_mode, - BOOL same_pid, BOOL isexe) -{ - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (same_pid) { - if (isexe && old_mode == DOS_OPEN_RDONLY && - old_deny == DENY_DOS && new_deny == DENY_READ) { - return AFAIL; - } - if (!isexe && old_mode == DOS_OPEN_RDONLY && - old_deny == DENY_DOS && new_deny == DENY_DOS) { - return AREAD; - } - if (new_deny == DENY_FCB && old_deny == DENY_DOS) { - if (isexe) return AFAIL; - if (old_mode == DOS_OPEN_RDONLY) return AFAIL; - return AALL; - } - if (old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS) { - if (new_deny == DENY_FCB || new_deny == DENY_READ) { - if (isexe) return AREAD; - return AFAIL; - } - } - if (old_deny == DENY_FCB) { - if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL; - return AFAIL; - } - } - - if (old_deny == DENY_DOS || new_deny == DENY_DOS || - old_deny == DENY_FCB || new_deny == DENY_FCB) { - if (isexe) { - if (old_deny == DENY_FCB || new_deny == DENY_FCB) { - return AFAIL; - } - if (old_deny == DENY_DOS) { - if (new_deny == DENY_READ && - (old_mode == DOS_OPEN_RDONLY || - old_mode == DOS_OPEN_RDWR)) { - return AFAIL; - } - if (new_deny == DENY_WRITE && - (old_mode == DOS_OPEN_WRONLY || - old_mode == DOS_OPEN_RDWR)) { - return AFAIL; - } - return AALL; - } - if (old_deny == DENY_NONE) return AALL; - if (old_deny == DENY_READ) return AWRITE; - if (old_deny == DENY_WRITE) return AREAD; - } - /* it isn't a exe, dll, sym or com file */ - if (old_deny == new_deny && same_pid) - return(AALL); - - if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; - if (old_mode == DOS_OPEN_RDONLY) return(AREAD); - - return(AFAIL); - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL); - return(AFAIL); - case DENY_NONE: - if (old_deny==DENY_WRITE) return(AREAD); - if (old_deny==DENY_READ) return(AWRITE); - if (old_deny==DENY_NONE) return(AALL); - return(AFAIL); - } - return(AFAIL); -} - /**************************************************************************** Check if we can open a file with a share mode. + Returns True if conflict, False if not. ****************************************************************************/ -static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access, - const char *fname, BOOL fcbopen, int *flags) +static BOOL share_conflict(share_mode_entry *entry, + uint32 access_mask, + uint32 share_access) { - int deny_mode = GET_DENY_MODE(share_mode); - int old_open_mode = GET_OPEN_MODE(share->share_mode); - int old_deny_mode = GET_DENY_MODE(share->share_mode); - BOOL non_io_open_request; - BOOL non_io_open_existing; - - /* - * share modes = false means don't bother to check for - * DENY mode conflict. This is a *really* bad idea :-). JRA. - */ - - if(!lp_share_modes(SNUM(conn))) - return True; - - if (desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { - non_io_open_request = False; - } else { - non_io_open_request = True; - } - - if (share->desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { - non_io_open_existing = False; - } else { - non_io_open_existing = True; - } - - /* - * Don't allow any opens once the delete on close flag has been - * set. - */ - - if (GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) { - DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", - fname )); - /* Use errno to map to correct error. */ - set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); + DEBUG(10,("share_conflict: entry->access_mask = 0x%x, " + "entry->share_access = 0x%x, " + "entry->private_options = 0x%x\n", + (unsigned int)entry->access_mask, + (unsigned int)entry->share_access, + (unsigned int)entry->private_options)); + + DEBUG(10,("share_conflict: access_mask = 0x%x, share_access = 0x%x\n", + (unsigned int)access_mask, (unsigned int)share_access)); + + if ((entry->access_mask & (FILE_WRITE_DATA| + FILE_APPEND_DATA| + FILE_READ_DATA| + FILE_EXECUTE| + DELETE_ACCESS)) == 0) { + DEBUG(10,("share_conflict: No conflict due to " + "entry->access_mask = 0x%x\n", + (unsigned int)entry->access_mask )); return False; } - /* this is a nasty hack, but necessary until we rewrite our open - handling to use a NTCreateX call as the basic call. - NT may open a file with neither read nor write access, and in - this case it expects the open not to conflict with any - existing deny modes. This happens (for example) during a - "xcopy /o" where the second file descriptor is used for - ACL sets - (tridge) - */ - - /* - * This is a bit wierd - the test for desired access not having the - * critical bits seems seems odd. Firstly, if both opens have no - * critical bits then always ignore. Then check the "allow delete" - * then check for either. This probably isn't quite right yet but - * gets us much closer. JRA. - */ - - /* - * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE - * and the existing desired_acces then share modes don't conflict. - */ - - if (non_io_open_request && non_io_open_existing) { - - /* - * Wrinkle discovered by smbtorture.... - * If both are non-io open and requester is asking for delete and current open has delete access - * but neither open has allowed file share delete then deny.... this is very strange and - * seems to be the only case in which non-io opens conflict. JRA. - */ - - if ((desired_access & DELETE_ACCESS) && (share->desired_access & DELETE_ACCESS) && - (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) { - DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n", - fname )); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; - } - - DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \ -and existing desired access (0x%x) are non-data opens\n", - fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); - return True; - } else if (non_io_open_request || non_io_open_existing) { - /* - * If either are non-io opens then share modes don't conflict. - */ - DEBUG(5,("check_share_mode: One non-io open. Allowing open on file %s as desired access (0x%x) doesn't conflict with\ -existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); - return True; - } - - /* - * If delete access was requested and the existing share mode doesn't have - * ALLOW_SHARE_DELETE then deny. - */ - - if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { - DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", - fname )); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + if ((access_mask & (FILE_WRITE_DATA| + FILE_APPEND_DATA| + FILE_READ_DATA| + FILE_EXECUTE| + DELETE_ACCESS)) == 0) { + DEBUG(10,("share_conflict: No conflict due to " + "access_mask = 0x%x\n", + (unsigned int)access_mask )); return False; } - /* - * The inverse of the above. - * If delete access was granted and the new share mode doesn't have - * ALLOW_SHARE_DELETE then deny. - */ - - if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) { - DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", - fname )); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; - } - -#if 0 - /* Bluarc test may need this ... needs further investigation. */ - if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; +#if 1 /* JRA TEST - Superdebug. */ +#define CHECK_MASK(num, am, right, sa, share) \ + DEBUG(10,("share_conflict: [%d] am (0x%x) & right (0x%x) = 0x%x\n", \ + (unsigned int)(num), (unsigned int)(am), \ + (unsigned int)(right), (unsigned int)(am)&(right) )); \ + DEBUG(10,("share_conflict: [%d] sa (0x%x) & share (0x%x) = 0x%x\n", \ + (unsigned int)(num), (unsigned int)(sa), \ + (unsigned int)(share), (unsigned int)(sa)&(share) )); \ + if (((am) & (right)) && !((sa) & (share))) { \ + DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ +sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ + (unsigned int)(share) )); \ + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ + return True; \ + } +#else +#define CHECK_MASK(num, am, right, sa, share) \ + if (((am) & (right)) && !((sa) & (share))) { \ + DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ +sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ + (unsigned int)(share) )); \ + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ + return True; \ } #endif - /* - * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE - * then share modes don't conflict. Likewise with existing desired access. - */ - - if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || - !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { - DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with \ -existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); - return True; - } - - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == sys_getpid()),is_executable(fname)); - - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags != O_RDONLY) || - (access_allowed == AWRITE && *flags != O_WRONLY)) { - - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n", - deny_mode,old_deny_mode,old_open_mode, - (int)share->pid,fname, fcbopen, *flags, access_allowed)); - - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; - } - - if (access_allowed == AREAD) - *flags = O_RDONLY; - - if (access_allowed == AWRITE) - *flags = O_WRONLY; + CHECK_MASK(1, entry->access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA, + share_access, FILE_SHARE_WRITE); + CHECK_MASK(2, access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA, + entry->share_access, FILE_SHARE_WRITE); + + CHECK_MASK(3, entry->access_mask, FILE_READ_DATA | FILE_EXECUTE, + share_access, FILE_SHARE_READ); + CHECK_MASK(4, access_mask, FILE_READ_DATA | FILE_EXECUTE, + entry->share_access, FILE_SHARE_READ); - } + CHECK_MASK(5, entry->access_mask, DELETE_ACCESS, + share_access, FILE_SHARE_DELETE); + CHECK_MASK(6, access_mask, DELETE_ACCESS, + entry->share_access, FILE_SHARE_DELETE); - return True; + DEBUG(10,("share_conflict: No conflict.\n")); + return False; } - #if defined(DEVELOPER) -static void validate_my_share_entries(int num, share_mode_entry *share_entry) +static void validate_my_share_entries(int num, + share_mode_entry *share_entry) { files_struct *fsp; - if (share_entry->pid != sys_getpid()) + if (share_entry->pid != sys_getpid()) { return; + } - fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); + fsp = file_find_dif(share_entry->dev, share_entry->inode, + share_entry->share_file_id); if (!fsp) { - DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); - smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", + share_mode_str(num, share_entry) )); + smb_panic("validate_my_share_entries: Cannot match a " + "share entry with an open file\n"); } if (((uint16)fsp->oplock_type) != share_entry->op_type) { pstring str; - DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); - slprintf(str, sizeof(str)-1, "validate_my_share_entries: file %s, oplock_type = 0x%x, op_type = 0x%x\n", - fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", + share_mode_str(num, share_entry) )); + slprintf(str, sizeof(str)-1, "validate_my_share_entries: " + "file %s, oplock_type = 0x%x, op_type = 0x%x\n", + fsp->fsp_name, (unsigned int)fsp->oplock_type, + (unsigned int)share_entry->op_type ); smb_panic(str); } } @@ -655,42 +524,75 @@ static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_li } } +static BOOL cause_oplock_break(int request, int existing, uint32 access_mask) +{ + if ((access_mask == DELETE_ACCESS) && + (request == NO_OPLOCK)) { + /* This is a delete request */ + return (BATCH_OPLOCK_TYPE(existing) != 0); + } + + if (EXCLUSIVE_OPLOCK_TYPE(existing) && (request != NO_OPLOCK)) { + return True; + } + + if ((existing != NO_OPLOCK) && (request == NO_OPLOCK)) { + return True; + } + + return False; +} + /**************************************************************************** Deal with open deny mode and oplock break processing. Invarient: Share mode must be locked on entry and exit. Returns -1 on error, or number of share modes on success (may be zero). ****************************************************************************/ -static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev, +static int open_mode_check(connection_struct *conn, + const char *fname, + SMB_DEV_T dev, SMB_INO_T inode, - uint32 desired_access, - int share_mode, int *p_flags, int *p_oplock_request, + uint32 access_mask, + uint32 share_access, + uint32 create_options, + int *p_flags, + int *p_oplock_request, BOOL *p_all_current_opens_are_level_II) { int i; int num_share_modes; int oplock_contention_count = 0; share_mode_entry *old_shares = NULL; - BOOL fcbopen = False; BOOL broke_oplock; + BOOL delete_on_close; - if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) - fcbopen = True; - - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + num_share_modes = get_share_modes(dev, inode, &old_shares, &delete_on_close); if(num_share_modes == 0) { SAFE_FREE(old_shares); return 0; } - if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && - ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { - /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + if (access_mask && + ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES))==0) && + ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode + * checks... ! JRA. */ SAFE_FREE(old_shares); return num_share_modes; } + /* A delete on close prohibits everything */ + + if (delete_on_close) { + SAFE_FREE(old_shares); + errno = EACCES; + return -1; + } + /* * Check if the share modes will give us access. */ @@ -703,132 +605,152 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T *p_all_current_opens_are_level_II = True; for(i = 0; i < num_share_modes; i++) { - BOOL cause_oplock_break = False; share_mode_entry *share_entry = &old_shares[i]; + BOOL opb_ret; #if defined(DEVELOPER) validate_my_share_entries(i, share_entry); #endif /* - * By observation of NetBench, oplocks are broken *before* share - * modes are checked. This allows a file to be closed by the client - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. + * By observation of NetBench, oplocks are broken + * *before* share modes are checked. This allows a + * file to be closed by the client if the share mode + * would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so + * we must break it before continuing. */ - - /* Was this a delete this file request ? */ - if (!*p_oplock_request && desired_access == DELETE_ACCESS && - !BATCH_OPLOCK_TYPE(share_entry->op_type)) { - /* Don't break the oplock in this case. */ - cause_oplock_break = False; - } else if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || - (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { - cause_oplock_break = True; + + if (!cause_oplock_break(*p_oplock_request, + share_entry->op_type, + access_mask)) { + if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + *p_all_current_opens_are_level_II = False; + } + continue; } - if(cause_oplock_break) { - BOOL opb_ret; + /* This is an oplock break */ - DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + DEBUG(5,("open_mode_check: oplock_request = %d, " + "breaking oplock (%x) on file %s, " + "dev = %x, inode = %.0f\n", + *p_oplock_request, share_entry->op_type, + fname, (unsigned int)dev, (double)inode)); - /* Ensure the reply for the open uses the correct sequence number. */ - /* This isn't a real deferred packet as it's response will also increment - * the sequence. - */ - srv_defer_sign_response(get_current_mid()); + /* Ensure the reply for the open uses the correct + * sequence number. */ + /* This isn't a real deferred packet as it's response + * will also increment the sequence. + */ + srv_defer_sign_response(get_current_mid()); - /* Oplock break - unlock to request it. */ - unlock_share_entry(conn, dev, inode); - - opb_ret = request_oplock_break(share_entry); + /* Oplock break - unlock to request it. */ + unlock_share_entry(conn, dev, inode); - /* Now relock. */ - lock_share_entry(conn, dev, inode); + opb_ret = request_oplock_break(share_entry); - if(opb_ret == False) { - DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); - SAFE_FREE(old_shares); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return -1; - } + /* Now relock. */ + lock_share_entry(conn, dev, inode); - broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); - if (!broken_entry) { - smb_panic("open_mode_check: malloc fail.\n"); - } - broken_entry->entry = *share_entry; - DLIST_ADD(broken_entry_list, broken_entry); - broke_oplock = True; + if (!opb_ret) { + DEBUG(0,("open_mode_check: FAILED when breaking " + "oplock (%x) on file %s, dev = %x, " + "inode = %.0f\n", + old_shares[i].op_type, fname, + (unsigned int)dev, (double)inode)); + SAFE_FREE(old_shares); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); + return -1; + } - } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - *p_all_current_opens_are_level_II = False; + broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); + if (!broken_entry) { + smb_panic("open_mode_check: malloc fail.\n"); } + broken_entry->entry = *share_entry; + DLIST_ADD(broken_entry_list, broken_entry); + broke_oplock = True; + } /* end for */ if (broke_oplock) { /* Update the current open table. */ SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + num_share_modes = get_share_modes(dev, inode, + &old_shares, + &delete_on_close); } - /* Now we check the share modes, after any oplock breaks. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; + if (lp_share_modes(SNUM(conn))) { + /* Now we check the share modes, after any oplock breaks. */ + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; - /* someone else has a share lock on it, check to see if we can too */ - if (!check_share_mode(conn, share_entry, share_mode, desired_access, - fname, fcbopen, p_flags)) { - SAFE_FREE(old_shares); - free_broken_entry_list(broken_entry_list); - errno = EACCES; - return -1; - } + /* someone else has a share lock on it, check to see + * if we can too */ + if (share_conflict(share_entry, access_mask, + share_access)) { + SAFE_FREE(old_shares); + free_broken_entry_list(broken_entry_list); + errno = EACCES; + return -1; + } + } } - for(broken_entry = broken_entry_list; broken_entry; broken_entry = broken_entry->next) { + for(broken_entry = broken_entry_list; broken_entry; + broken_entry = broken_entry->next) { oplock_contention_count++; /* Paranoia check that this is no longer an exlusive entry. */ for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &old_shares[i]; - if (share_modes_identical(&broken_entry->entry, share_entry) && - EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) { + if (!(share_modes_identical(&broken_entry->entry, + share_entry) && + EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type))) { + continue; + } - /* - * This should not happen. The target left this oplock - * as exlusive.... The process *must* be dead.... - */ + /* + * This should not happen. The target left this oplock + * as exlusive.... The process *must* be dead.... + */ - DEBUG(0,("open_mode_check: exlusive oplock left by process %d \ -after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n", - (int)broken_entry->entry.pid, fname, (unsigned int)dev, (double)inode)); + DEBUG(0,("open_mode_check: exlusive oplock left by " + "process %d after break ! For file %s, " + "dev = %x, inode = %.0f. Deleting it to " + "continue...\n", + (int)broken_entry->entry.pid, fname, + (unsigned int)dev, (double)inode)); - if (process_exists(broken_entry->entry.pid)) { - DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n", - (unsigned long)broken_entry->entry.pid )); - } + if (process_exists(broken_entry->entry.pid)) { + DEBUG(0,("open_mode_check: Existent process " + "%lu left active oplock.\n", + (unsigned long)broken_entry->entry.pid )); + } - if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) { - free_broken_entry_list(broken_entry_list); - errno = EACCES; - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return -1; - } + if (del_share_entry(dev, inode, &broken_entry->entry, + NULL, &delete_on_close) == -1) { + free_broken_entry_list(broken_entry_list); + errno = EACCES; + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); + return -1; + } - /* - * We must reload the share modes after deleting the - * other process's entry. - */ + /* + * We must reload the share modes after deleting the + * other process's entry. + */ - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - break; - } + SAFE_FREE(old_shares); + num_share_modes = get_share_modes(dev, inode, + &old_shares, + &delete_on_close); + break; } /* end for paranoia... */ } /* end for broken_entry */ free_broken_entry_list(broken_entry_list); @@ -853,7 +775,9 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" Delete the record for a handled deferred open entry. ****************************************************************************/ -static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) +static void delete_defered_open_entry_record(connection_struct *conn, + SMB_DEV_T dev, + SMB_INO_T inode) { uint16 mid = get_current_mid(); pid_t mypid = sys_getpid(); @@ -868,7 +792,7 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T for (i = 0; i < num_de_entries; i++) { deferred_open_entry *entry = &de_array[i]; if (entry->pid == mypid && entry->mid == mid && entry->dev == dev && - entry->inode == inode) { + entry->inode == inode) { /* Remove the deferred open entry from the array. */ delete_deferred_open_entry(entry); @@ -883,8 +807,11 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T Handle the 1 second delay in returning a SHARING_VIOLATION error. ****************************************************************************/ -void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, - char *fname, SMB_DEV_T dev, SMB_INO_T inode) +static void defer_open_sharing_error(connection_struct *conn, + struct timeval *ptv, + const char *fname, + SMB_DEV_T dev, + SMB_INO_T inode) { uint16 mid = get_current_mid(); pid_t mypid = sys_getpid(); @@ -906,10 +833,12 @@ void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, /* * Check if a 1 second timeout has expired. */ - if (usec_time_diff(ptv, &entry->time) > SHARING_VIOLATION_USEC_WAIT) { - DEBUG(10,("defer_open_sharing_error: Deleting deferred open entry for mid %u, \ -file %s\n", - (unsigned int)mid, fname )); + if (usec_time_diff(ptv, &entry->time) > + SHARING_VIOLATION_USEC_WAIT) { + DEBUG(10,("defer_open_sharing_error: Deleting " + "deferred open entry for mid %u, " + "file %s\n", + (unsigned int)mid, fname )); /* Expired, return a real error. */ /* Remove the deferred open entry from the array. */ @@ -919,24 +848,30 @@ file %s\n", return; } /* - * If the timeout hasn't expired yet and we still have a sharing violation, - * just leave the entry in the deferred open array alone. We do need to - * reschedule this open call though (with the original created time). + * If the timeout hasn't expired yet and we still have + * a sharing violation, just leave the entry in the + * deferred open array alone. We do need to reschedule + * this open call though (with the original created + * time). */ - DEBUG(10,("defer_open_sharing_error: time [%u.%06u] updating \ -deferred open entry for mid %u, file %s\n", - (unsigned int)entry->time.tv_sec, - (unsigned int)entry->time.tv_usec, - (unsigned int)mid, fname )); - - push_sharing_violation_open_smb_message(&entry->time, (char *)&dib, sizeof(dib)); + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] " + "updating deferred open entry for mid %u, file %s\n", + (unsigned int)entry->time.tv_sec, + (unsigned int)entry->time.tv_usec, + (unsigned int)mid, fname )); + + push_sharing_violation_open_smb_message(&entry->time, + (char *)&dib, + sizeof(dib)); SAFE_FREE(de_array); return; } } - DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred open entry for mid %u, file %s\n", - (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, (unsigned int)mid, fname )); + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " + "open entry for mid %u, file %s\n", + (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, + (unsigned int)mid, fname )); if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) { SAFE_FREE(de_array); @@ -963,80 +898,302 @@ deferred open entry for mid %u, file %s\n", This requires a patch to Linux. ****************************************************************************/ -static void kernel_flock(files_struct *fsp, int deny_mode) +static void kernel_flock(files_struct *fsp, uint32 share_mode) { #if HAVE_KERNEL_SHARE_MODES int kernel_mode = 0; - if (deny_mode == DENY_READ) kernel_mode = LOCK_MAND|LOCK_WRITE; - else if (deny_mode == DENY_WRITE) kernel_mode = LOCK_MAND|LOCK_READ; - else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND; - if (kernel_mode) flock(fsp->fd, kernel_mode); + if (share_mode == FILE_SHARE_WRITE) { + kernel_mode = LOCK_MAND|LOCK_WRITE; + } else if (share_mode == FILE_SHARE_READ) { + kernel_mode = LOCK_MAND|LOCK_READ; + } else if (share_mode == FILE_SHARE_NONE) { + kernel_mode = LOCK_MAND; + } + if (kernel_mode) { + flock(fsp->fh->fd, kernel_mode); + } #endif - ;; + ; } +/**************************************************************************** + On overwrite open ensure that the attributes match. +****************************************************************************/ -static BOOL open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_mode, uint32 new_dos_mode, - mode_t existing_mode, mode_t new_mode, mode_t *returned_mode) +static BOOL open_match_attributes(connection_struct *conn, + const char *path, + uint32 old_dos_attr, + uint32 new_dos_attr, + mode_t existing_unx_mode, + mode_t new_unx_mode, + mode_t *returned_unx_mode) { - uint32 noarch_old_dos_mode, noarch_new_dos_mode; + uint32 noarch_old_dos_attr, noarch_new_dos_attr; - noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); - noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); + noarch_old_dos_attr = (old_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); + noarch_new_dos_attr = (new_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); - if((noarch_old_dos_mode == 0 && noarch_new_dos_mode != 0) || - (noarch_old_dos_mode != 0 && ((noarch_old_dos_mode & noarch_new_dos_mode) == noarch_old_dos_mode))) - *returned_mode = new_mode; - else - *returned_mode = (mode_t)0; + if((noarch_old_dos_attr == 0 && noarch_new_dos_attr != 0) || + (noarch_old_dos_attr != 0 && ((noarch_old_dos_attr & noarch_new_dos_attr) == noarch_old_dos_attr))) { + *returned_unx_mode = new_unx_mode; + } else { + *returned_unx_mode = (mode_t)0; + } - DEBUG(10,("open_match_attributes: file %s old_dos_mode = 0x%x, existing_mode = 0%o, new_dos_mode = 0x%x returned_mode = 0%o\n", - path, - old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode )); + DEBUG(10,("open_match_attributes: file %s old_dos_attr = 0x%x, " + "existing_unx_mode = 0%o, new_dos_attr = 0x%x " + "returned_unx_mode = 0%o\n", + path, + (unsigned int)old_dos_attr, + (unsigned int)existing_unx_mode, + (unsigned int)new_dos_attr, + (unsigned int)*returned_unx_mode )); /* If we're mapping SYSTEM and HIDDEN ensure they match. */ if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) + if ((old_dos_attr & FILE_ATTRIBUTE_SYSTEM) && + !(new_dos_attr & FILE_ATTRIBUTE_SYSTEM)) { return False; + } } if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) + if ((old_dos_attr & FILE_ATTRIBUTE_HIDDEN) && + !(new_dos_attr & FILE_ATTRIBUTE_HIDDEN)) { return False; + } } return True; } /**************************************************************************** - Open a file with a share mode. + Special FCB or DOS processing in the case of a sharing violation. + Try and find a duplicated file handle. ****************************************************************************/ -files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, - int share_mode,int ofun, uint32 new_dos_mode, int oplock_request, - int *Access,int *action) +static files_struct *fcb_or_dos_open(connection_struct *conn, + const char *fname, SMB_DEV_T dev, + SMB_INO_T inode, + uint32 access_mask, + uint32 share_access, + uint32 create_options) { - return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, new_dos_mode, - oplock_request, Access, action); + files_struct *fsp; + files_struct *dup_fsp; + + DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " + "file %s.\n", fname )); + + for(fsp = file_find_di_first(dev, inode); fsp; + fsp = file_find_di_next(fsp)) { + + DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " + "vuid = %u, file_pid = %u, private_options = 0x%x " + "access_mask = 0x%x\n", fsp->fsp_name, + fsp->fh->fd, (unsigned int)fsp->vuid, + (unsigned int)fsp->file_pid, + (unsigned int)fsp->fh->private_options, + (unsigned int)fsp->access_mask )); + + if (fsp->fh->fd != -1 && + fsp->vuid == current_user.vuid && + fsp->file_pid == global_smbpid && + (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && + (fsp->access_mask & FILE_WRITE_DATA) && + strequal(fsp->fsp_name, fname)) { + DEBUG(10,("fcb_or_dos_open: file match\n")); + break; + } + } + + if (!fsp) { + return NULL; + } + + /* quite an insane set of semantics ... */ + if (is_executable(fname) && + (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) { + DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n")); + return NULL; + } + + /* We need to duplicate this fsp. */ + dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options); + if (!dup_fsp) { + return NULL; + } + + return dup_fsp; +} + +/**************************************************************************** + Open a file with a share mode - old openX method - map into NTCreate. +****************************************************************************/ + +BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, + uint32 *paccess_mask, + uint32 *pshare_mode, + uint32 *pcreate_disposition, + uint32 *pcreate_options) +{ + uint32 access_mask; + uint32 share_mode; + uint32 create_disposition; + uint32 create_options = 0; + + DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, " + "open_func = 0x%x\n", + fname, (unsigned int)deny_mode, (unsigned int)open_func )); + + /* Create the NT compatible access_mask. */ + switch (GET_OPENX_MODE(deny_mode)) { + case DOS_OPEN_RDONLY: + access_mask = FILE_GENERIC_READ; + break; + case DOS_OPEN_WRONLY: + access_mask = FILE_GENERIC_WRITE; + break; + case DOS_OPEN_EXEC: /* This used to be FILE_READ_DATA... */ + case DOS_OPEN_RDWR: + case DOS_OPEN_FCB: + access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE; + break; + default: + DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n", + (unsigned int)GET_OPENX_MODE(deny_mode))); + return False; + } + + /* Create the NT compatible create_disposition. */ + switch (open_func) { + case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST: + create_disposition = FILE_CREATE; + break; + + case OPENX_FILE_EXISTS_OPEN: + create_disposition = FILE_OPEN; + break; + + case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST: + create_disposition = FILE_OPEN_IF; + break; + + case OPENX_FILE_EXISTS_TRUNCATE: + create_disposition = FILE_OVERWRITE; + break; + + case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST: + create_disposition = FILE_OVERWRITE_IF; + break; + + default: + /* From samba4 - to be confirmed. */ + if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) { + create_disposition = FILE_CREATE; + break; + } + DEBUG(10,("map_open_params_to_ntcreate: bad " + "open_func 0x%x\n", (unsigned int)open_func)); + return False; + } + + /* Create the NT compatible share modes. */ + switch (GET_DENY_MODE(deny_mode)) { + case DENY_ALL: + share_mode = FILE_SHARE_NONE; + break; + + case DENY_WRITE: + share_mode = FILE_SHARE_READ; + break; + + case DENY_READ: + share_mode = FILE_SHARE_WRITE; + break; + + case DENY_NONE: + share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + break; + + case DENY_DOS: + create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS; + if (is_executable(fname)) { + share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + } else { + if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) { + share_mode = FILE_SHARE_READ; + } else { + share_mode = FILE_SHARE_NONE; + } + } + break; + + case DENY_FCB: + create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB; + share_mode = FILE_SHARE_NONE; + break; + + default: + DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n", + (unsigned int)GET_DENY_MODE(deny_mode) )); + return False; + } + + DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, " + "share_mode = 0x%x, create_disposition = 0x%x, " + "create_options = 0x%x\n", + fname, + (unsigned int)access_mask, + (unsigned int)share_mode, + (unsigned int)create_disposition, + (unsigned int)create_options )); + + if (paccess_mask) { + *paccess_mask = access_mask; + } + if (pshare_mode) { + *pshare_mode = share_mode; + } + if (pcreate_disposition) { + *pcreate_disposition = create_disposition; + } + if (pcreate_options) { + *pcreate_options = create_options; + } + + return True; + } +/* Map generic permissions to file object specific permissions */ + +struct generic_mapping file_generic_mapping = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_GENERIC_ALL +}; + /**************************************************************************** Open a file with a share mode. ****************************************************************************/ -files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, - uint32 desired_access, - int share_mode,int ofun, uint32 new_dos_mode, - int oplock_request, - int *Access,int *paction) +files_struct *open_file_ntcreate(connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ + uint32 share_access, /* share constants (FILE_SHARE_READ etc). */ + uint32 create_disposition, /* FILE_OPEN_IF etc. */ + uint32 create_options, /* options such as delete on close. */ + uint32 new_dos_attributes, /* attributes used for new file. */ + int oplock_request, /* internal Samba oplock codes. */ + /* Information (FILE_EXISTS etc.) */ + int *pinfo) { int flags=0; int flags2=0; - int deny_mode = GET_DENY_MODE(share_mode); - BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); - BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); - BOOL fcbopen = False; BOOL def_acl = False; - BOOL add_share_mode = True; BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; @@ -1044,15 +1201,40 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL all_current_opens_are_level_II = False; BOOL fsp_open = False; files_struct *fsp = NULL; - int open_mode=0; - uint16 port = 0; - mode_t new_mode = (mode_t)0; - int action; - uint32 existing_dos_mode = 0; + mode_t new_unx_mode = (mode_t)0; + mode_t unx_mode = (mode_t)0; + int info; + uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; + uint16 port = 0; uint16 mid = get_current_mid(); - /* We add aARCH to this as this mode is only used if the file is created new. */ - mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname, True); + + if (conn->printer) { + /* + * Printers are handled completely differently. + * Most of the passed parameters are ignored. + */ + + if (pinfo) { + *pinfo = FILE_WAS_CREATED; + } + + DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); + + return print_fsp_open(conn, fname); + } + + /* We add aARCH to this as this mode is only used if the file is + * created new. */ + unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True); + + DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " + "access_mask=0x%x share_access=0x%x " + "create_disposition = 0x%x create_options=0x%x " + "unix mode=0%o oplock_request=%d\n", + fname, new_dos_attributes, access_mask, share_access, + create_disposition, create_options, unx_mode, + oplock_request)); if (oplock_request == INTERNAL_OPEN_ONLY) { internal_only_open = True; @@ -1065,52 +1247,42 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ memcpy(&dib, pml->private_data.data, sizeof(dib)); /* There could be a race condition where the dev/inode pair - has changed since we deferred the message. If so, just - remove the deferred open entry and return sharing violation. */ - - /* If the timeout value is non-zero, we need to just - return sharing violation. Don't retry the open - as we were not notified of a close and we don't want to - trigger another spurious oplock break. */ - - if (!file_existed || dib.dev != psbuf->st_dev || dib.inode != psbuf->st_ino || - pml->msg_time.tv_sec || pml->msg_time.tv_usec) { + has changed since we deferred the message. If so, just + remove the deferred open entry and return sharing + violation. */ + + /* If the timeout value is non-zero, we need to just return + sharing violation. Don't retry the open as we were not + notified of a close and we don't want to trigger another + spurious oplock break. */ + + if (!file_existed || dib.dev != psbuf->st_dev || + dib.inode != psbuf->st_ino || pml->msg_time.tv_sec || + pml->msg_time.tv_usec) { /* Ensure we don't reprocess this message. */ remove_sharing_violation_open_smb_message(mid); /* Now remove the deferred open entry under lock. */ lock_share_entry(conn, dib.dev, dib.inode); - delete_defered_open_entry_record(conn, dib.dev, dib.inode); + delete_defered_open_entry_record(conn, dib.dev, + dib.inode); unlock_share_entry(conn, dib.dev, dib.inode); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); return NULL; } /* Ensure we don't reprocess this message. */ remove_sharing_violation_open_smb_message(mid); - - } - - if (conn->printer) { - /* printers are handled completely differently. Most of the passed parameters are - ignored */ - if (Access) - *Access = DOS_OPEN_WRONLY; - if (paction) - *paction = FILE_WAS_CREATED; - return print_fsp_open(conn, fname); } - DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", - fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); - if (!check_name(fname,conn)) { return NULL; } - new_dos_mode &= SAMBA_ATTRIBUTES_MASK; + new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; if (file_existed) { - existing_dos_mode = dos_mode(conn, fname, psbuf); + existing_dos_attributes = dos_mode(conn, fname, psbuf); } /* ignore any oplock requests if oplocks are disabled */ @@ -1119,114 +1291,173 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ } /* this is for OS/2 long file names - say we don't support them */ - if (strstr(fname,".+,;=[].")) { - /* OS/2 Workplace shell fix may be main code stream in a later release. */ - set_saved_error_triple(ERRDOS, ERRcannotopen, NT_STATUS_OBJECT_NAME_NOT_FOUND); - DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); + if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { + /* OS/2 Workplace shell fix may be main code stream in a later + * release. */ + set_saved_error_triple(ERRDOS, ERRcannotopen, + NT_STATUS_OBJECT_NAME_NOT_FOUND); + DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " + "supported.\n")); return NULL; } - if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed) { - DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", - fname )); - if (S_ISDIR(psbuf->st_mode)) { - errno = EISDIR; - } else { - errno = EEXIST; - } - return NULL; - } - - if (CAN_WRITE(conn) && (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST)) - flags2 |= O_CREAT; + switch( create_disposition ) { + /* + * Currently we're using FILE_SUPERSEDE as the same as + * FILE_OVERWRITE_IF but they really are + * different. FILE_SUPERSEDE deletes an existing file + * (requiring delete access) then recreates it. + */ + case FILE_SUPERSEDE: + /* If file exists replace/overwrite. If file doesn't + * exist create. */ + flags2 |= (O_CREAT | O_TRUNC); + break; - if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) - flags2 |= O_TRUNC; + case FILE_OVERWRITE_IF: + /* If file exists replace/overwrite. If file doesn't + * exist create. */ + flags2 |= (O_CREAT | O_TRUNC); + break; - /* We only care about matching attributes on file exists and truncate. */ - if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { - if (!open_match_attributes(conn, fname, existing_dos_mode, new_dos_mode, - psbuf->st_mode, mode, &new_mode)) { - DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n", - fname, existing_dos_mode, new_dos_mode, - (int)psbuf->st_mode, (int)mode )); + case FILE_OPEN: + /* If file exists open. If file doesn't exist error. */ + if (!file_existed) { + DEBUG(5,("open_file_ntcreate: FILE_OPEN " + "requested for file %s and file " + "doesn't exist.\n", fname )); + set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + errno = ENOENT; + return NULL; + } + break; + + case FILE_OVERWRITE: + /* If file exists overwrite. If file doesn't exist + * error. */ + if (!file_existed) { + DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " + "requested for file %s and file " + "doesn't exist.\n", fname )); + set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + errno = ENOENT; + return NULL; + } + flags2 |= O_TRUNC; + break; + + case FILE_CREATE: + /* If file exists error. If file doesn't exist + * create. */ + if (file_existed) { + DEBUG(5,("open_file_ntcreate: FILE_CREATE " + "requested for file %s and file " + "already exists.\n", fname )); + if (S_ISDIR(psbuf->st_mode)) { + errno = EISDIR; + } else { + errno = EEXIST; + } + return NULL; + } + flags2 |= (O_CREAT|O_EXCL); + break; + + case FILE_OPEN_IF: + /* If file exists open. If file doesn't exist + * create. */ + flags2 |= O_CREAT; + break; + + default: + set_saved_error_triple(ERRDOS, ERRinvalidparam, + NT_STATUS_INVALID_PARAMETER); + return NULL; + } + + /* We only care about matching attributes on file exists and + * overwrite. */ + + if (file_existed && ((create_disposition == FILE_OVERWRITE) || + (create_disposition == FILE_OVERWRITE_IF))) { + if (!open_match_attributes(conn, fname, + existing_dos_attributes, + new_dos_attributes, psbuf->st_mode, + unx_mode, &new_unx_mode)) { + DEBUG(5,("open_file_ntcreate: attributes missmatch " + "for file %s (%x %x) (0%o, 0%o)\n", + fname, existing_dos_attributes, + new_dos_attributes, + (unsigned int)psbuf->st_mode, + (unsigned int)unx_mode )); errno = EACCES; return NULL; } } - if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) - flags2 |= O_EXCL; + /* This is a nasty hack - must fix... JRA. */ + if (access_mask == MAXIMUM_ALLOWED_ACCESS) { + access_mask = FILE_GENERIC_ALL; + } - /* note that we ignore the append flag as - append does not mean the same thing under dos and unix */ + /* + * Convert GENERIC bits to specific bits. + */ - switch (GET_OPEN_MODE(share_mode)) { - case DOS_OPEN_EXEC: - case DOS_OPEN_RDONLY: - flags = O_RDONLY; - if (desired_access == 0) - desired_access = FILE_READ_DATA; - break; - case DOS_OPEN_WRONLY: - flags = O_WRONLY; - if (desired_access == 0) - desired_access = FILE_WRITE_DATA; - break; - case DOS_OPEN_FCB: - fcbopen = True; - flags = O_RDWR; - if (desired_access == 0) - desired_access = FILE_READ_DATA|FILE_WRITE_DATA; - break; - case DOS_OPEN_RDWR: - flags = O_RDWR; - if (desired_access == 0) - desired_access = FILE_READ_DATA|FILE_WRITE_DATA; - break; - default: - /* Force DOS error. */ - set_saved_error_triple(ERRDOS, ERRinvalidparam, NT_STATUS_INVALID); - return NULL; + se_map_generic(&access_mask, &file_generic_mapping); + + DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping " + "access_mask=0x%x\n", fname, access_mask )); + + /* + * Note that we ignore the append flag as append does not + * mean the same thing under DOS and Unix. + */ + + if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { + flags = O_RDWR; + } else { + flags = O_RDONLY; } + /* + * Currently we only look at FILE_WRITE_THROUGH for create options. + */ + #if defined(O_SYNC) - if (GET_FILE_SYNC_OPENMODE(share_mode)) { + if (create_options & FILE_WRITE_THROUGH) { flags2 |= O_SYNC; } #endif /* O_SYNC */ - if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_mode))) { - if (!fcbopen) { - DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", - fname, !CAN_WRITE(conn) ? "share" : "file" )); - errno = EACCES; - return NULL; - } - flags = O_RDONLY; + if (!CAN_WRITE(conn)) { + /* + * We should really return a permission denied error if either + * O_CREAT or O_TRUNC are set, but for compatibility with + * older versions of Samba we just AND them out. + */ + flags2 &= ~(O_CREAT|O_TRUNC); } - if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { - DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - errno = EINVAL; - return NULL; - } + /* + * Ensure we can't write on a read-only share or file. + */ - if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && - ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { - /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - deny_mode = DENY_NONE; - if (file_existed) { - oplock_request = 0; - add_share_mode = False; - flags2 &= ~O_CREAT; - } + if (flags != O_RDONLY && file_existed && + (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) { + DEBUG(5,("open_file_ntcreate: write access requested for " + "file %s on read only %s\n", + fname, !CAN_WRITE(conn) ? "share" : "file" )); + set_saved_error_triple(ERRDOS, ERRnoaccess, + NT_STATUS_ACCESS_DENIED); + errno = EACCES; + return NULL; } fsp = file_new(conn); - if(!fsp) + if(!fsp) { return NULL; + } if (file_existed) { @@ -1235,47 +1466,86 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ lock_share_entry(conn, dev, inode); - num_share_modes = open_mode_check(conn, fname, dev, inode, - desired_access, - share_mode, - &flags, &oplock_request, &all_current_opens_are_level_II); + num_share_modes = open_mode_check(conn, fname, dev, inode, + access_mask, share_access, + create_options, + &flags, &oplock_request, + &all_current_opens_are_level_II); if(num_share_modes == -1) { + if (!internal_only_open) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { + /* Check if this can be done with the + * deny_dos and fcb calls. */ + if (create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + files_struct *fsp_dup; + fsp_dup = fcb_or_dos_open(conn, fname, dev, + inode, access_mask, + share_access, + create_options); + + if (fsp_dup) { + unlock_share_entry(conn, dev, inode); + file_free(fsp); + if (pinfo) { + *pinfo = FILE_WAS_OPENED; + } + conn->num_files_open++; + return fsp_dup; + } + } + } + } + /* - * This next line is a subtlety we need for MS-Access. If a file open will - * fail due to share permissions and also for security (access) - * reasons, we need to return the access failed error, not the - * share error. This means we must attempt to open the file anyway - * in order to get the UNIX access error - even if we're going to - * fail the open for share reasons. This is bad, as we're burning - * another fd if there are existing locks but there's nothing else - * we can do. We also ensure we're not going to create or tuncate - * the file as we only want an access decision at this stage. JRA. + * This next line is a subtlety we need for + * MS-Access. If a file open will fail due to share + * permissions and also for security (access) reasons, + * we need to return the access failed error, not the + * share error. This means we must attempt to open the + * file anyway in order to get the UNIX access error - + * even if we're going to fail the open for share + * reasons. This is bad, as we're burning another fd + * if there are existing locks but there's nothing + * else we can do. We also ensure we're not going to + * create or tuncate the file as we only want an + * access decision at this stage. JRA. */ errno = 0; fsp_open = open_file(fsp,conn,fname,psbuf, - flags|(flags2&~(O_TRUNC|O_CREAT)),mode,desired_access); + flags|(flags2&~(O_TRUNC|O_CREAT)), + unx_mode,access_mask); - DEBUG(4,("open_file_shared : share_mode deny - calling open_file with \ -flags=0x%X flags2=0x%X mode=0%o returned %d\n", - flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); + DEBUG(4,("open_file_ntcreate : share_mode deny - " + "calling open_file with flags=0x%X " + "flags2=0x%X mode=0%o returned %d\n", + flags, (flags2&~(O_TRUNC|O_CREAT)), + (unsigned int)unx_mode, (int)fsp_open )); if (!fsp_open && errno) { /* Default error. */ - set_saved_error_triple(ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED); + set_saved_error_triple(ERRDOS, ERRnoaccess, + NT_STATUS_ACCESS_DENIED); } /* - * If we're returning a share violation, ensure we cope with - * the braindead 1 second delay. + * If we're returning a share violation, ensure we + * cope with the braindead 1 second delay. */ if (!internal_only_open) { NTSTATUS status; get_saved_error_triple(NULL, NULL, &status); if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents the current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + /* The fsp->open_time here represents + * the current time of day. */ + defer_open_sharing_error(conn, + &fsp->open_time, + fname, dev, inode); } } @@ -1286,7 +1556,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here * so return the correct error code */ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1302,35 +1573,39 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && - (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) - mode = 0777; + (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) { + unx_mode = 0777; + } DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - flags,flags2,(int)mode)); + (unsigned int)flags,(unsigned int)flags2,(unsigned int)unx_mode)); /* * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode,desired_access); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask); - if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { - if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode,desired_access)) == True) + if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT)) { + if((fsp_open = open_file(fsp,conn,fname,psbuf, + O_RDONLY,unx_mode,access_mask)) == True) { flags = O_RDONLY; + } } if (!fsp_open) { - if(file_existed) + if(file_existed) { unlock_share_entry(conn, dev, inode); + } file_free(fsp); return NULL; } /* - * Deal with the race condition where two smbd's detect the file doesn't - * exist and do the create at the same time. One of them will win and - * set a share mode, the other (ie. this one) should check if the - * requested share mode for this create is allowed. + * Deal with the race condition where two smbd's detect the file + * doesn't exist and do the create at the same time. One of them will + * win and set a share mode, the other (ie. this one) should check if + * the requested share mode for this create is allowed. */ if (!file_existed) { @@ -1347,22 +1622,47 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", lock_share_entry_fsp(fsp); - num_share_modes = open_mode_check(conn, fname, dev, inode, - desired_access, - share_mode, - &flags, &oplock_request, &all_current_opens_are_level_II); + num_share_modes = open_mode_check(conn, fname, dev, inode, + access_mask, share_access, + create_options, + &flags, &oplock_request, + &all_current_opens_are_level_II); if(num_share_modes == -1) { - /* - * If we're returning a share violation, ensure we cope with - * the braindead 1 second delay. - */ - NTSTATUS status; get_saved_error_triple(NULL, NULL, &status); if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents the current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + /* Check if this can be done with the deny_dos + * and fcb calls. */ + if (create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + files_struct *fsp_dup; + fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, + access_mask, share_access, + create_options); + if (fsp_dup) { + unlock_share_entry(conn, dev, inode); + fd_close(conn, fsp); + file_free(fsp); + if (pinfo) { + *pinfo = FILE_WAS_OPENED; + } + conn->num_files_open++; + return fsp_dup; + } + } + + /* + * If we're returning a share violation, + * ensure we cope with the braindead 1 second + * delay. + */ + + /* The fsp->open_time here represents the + * current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, + fname, dev, inode); } unlock_share_entry_fsp(fsp); @@ -1372,7 +1672,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here, so * return the correct code. */ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); return NULL; } @@ -1381,8 +1682,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * exist. Ensure we return the correct value for action. */ - if (num_share_modes > 0) + if (num_share_modes > 0) { file_existed = True; + } /* * We exit this block with the share entry *locked*..... @@ -1395,7 +1697,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", mode and we have already checked our more authoritative locking database for permission to set this deny mode. If the kernel refuses the operations then the kernel is wrong */ - kernel_flock(fsp, deny_mode); + + kernel_flock(fsp, share_access); /* * At this point onwards, we can guarentee that the share entry @@ -1409,9 +1712,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (flags2&O_TRUNC) { /* - * We are modifing the file after open - update the stat struct.. + * We are modifing the file after open - update the stat + * struct.. */ - if ((SMB_VFS_FTRUNCATE(fsp,fsp->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { + if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || + (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1419,44 +1724,28 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } - switch (flags) { - case O_RDONLY: - open_mode = DOS_OPEN_RDONLY; - break; - case O_RDWR: - open_mode = DOS_OPEN_RDWR; - break; - case O_WRONLY: - open_mode = DOS_OPEN_WRONLY; - break; - } + /* Record the options we were opened with. */ + fsp->share_access = share_access; + fsp->fh->private_options = create_options; + fsp->access_mask = access_mask; - fsp->share_mode = SET_DENY_MODE(deny_mode) | - SET_OPEN_MODE(open_mode) | - SET_ALLOW_SHARE_DELETE(allow_share_delete); - - DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); - - if (Access) { - (*Access) = (SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode)); - } - - action = 0; - - if (file_existed && !(flags2 & O_TRUNC)) - action = FILE_WAS_OPENED; - if (file_existed && (flags2 & O_TRUNC)) - action = FILE_WAS_OVERWRITTEN; - if (!file_existed) { - action = FILE_WAS_CREATED; + if (file_existed) { + if (!(flags2 & O_TRUNC)) { + info = FILE_WAS_OPENED; + } else { + info = FILE_WAS_OVERWRITTEN; + } + } else { + info = FILE_WAS_CREATED; /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + change_owner_to_parent(conn, fsp, fsp->fsp_name, + psbuf); } } - if (paction) { - *paction = action; + if (pinfo) { + *pinfo = info; } /* @@ -1465,7 +1754,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ if(oplock_request && (num_share_modes == 0) && - !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { + !IS_VETO_OPLOCK_PATH(conn,fname) && + set_file_oplock(fsp, oplock_request) ) { port = global_oplock_port; } else if (oplock_request && all_current_opens_are_level_II) { port = global_oplock_port; @@ -1476,26 +1766,25 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", oplock_request = 0; } - if (add_share_mode) { - set_share_mode(fsp, port, oplock_request); - } + set_share_mode(fsp, port, oplock_request); - if (delete_on_close) { - uint32 dosmode = existing_dos_mode; + if (create_options & FILE_DELETE_ON_CLOSE) { + uint32 dosattr= existing_dos_attributes; NTSTATUS result; - if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { - dosmode = new_dos_mode; + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + info == FILE_WAS_SUPERSEDED) { + dosattr = new_dos_attributes; } - result = set_delete_on_close_internal(fsp, delete_on_close, dosmode); - if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + result = can_set_delete_on_close(fsp, True, dosattr); + + if (!NT_STATUS_IS_OK(result)) { uint8 u_e_c; uint32 u_e_code; + BOOL dummy_del_on_close; /* Remember to delete the mode we just added. */ - if (add_share_mode) { - del_share_mode(fsp, NULL); - } + del_share_mode(fsp, NULL, &dummy_del_on_close); unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1503,12 +1792,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", set_saved_error_triple(u_e_c, u_e_code, result); return NULL; } + set_delete_on_close(fsp, True); } - if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + info == FILE_WAS_SUPERSEDED) { /* Files should be initially set as archive */ - if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL, True); + if (lp_map_archive(SNUM(conn)) || + lp_store_dos_attributes(SNUM(conn))) { + file_set_dosmode(conn, fname, + new_dos_attributes | aARCH, NULL, + True); } } @@ -1519,36 +1813,45 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (!file_existed && !def_acl) { - int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + int saved_errno = errno; /* We might get ENOSYS in the next + * call.. */ - if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 + && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ + } - } else if (new_mode) { + } else if (new_unx_mode) { int ret = -1; /* Attributes need changing. File already existed. */ { - int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); + int saved_errno = errno; /* We might get ENOSYS in the + * next call.. */ + ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, + new_unx_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } else { - DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", - fname, (int)new_mode)); + DEBUG(5, ("open_file_shared: failed to reset " + "attributes of file %s to 0%o\n", + fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ } } - if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) - DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", - fname, (int)new_mode)); + if ((ret == -1) && + (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) + DEBUG(5, ("open_file_shared: failed to reset " + "attributes of file %s to 0%o\n", + fname, (unsigned int)new_unx_mode)); } - /* If this is a successful open, we must remove any deferred open records. */ + /* If this is a successful open, we must remove any deferred open + * records. */ delete_defered_open_entry_record(conn, fsp->dev, fsp->inode); unlock_share_entry_fsp(fsp); @@ -1561,17 +1864,20 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ -files_struct *open_file_fchmod(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +files_struct *open_file_fchmod(connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf) { files_struct *fsp = NULL; BOOL fsp_open; - if (!VALID_STAT(*psbuf)) + if (!VALID_STAT(*psbuf)) { return NULL; + } fsp = file_new(conn); - if(!fsp) + if(!fsp) { return NULL; + } /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ @@ -1606,96 +1912,135 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, - uint32 desired_access, int share_mode, int smb_ofun, int *action) +files_struct *open_directory(connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, + uint32 share_access, + uint32 create_disposition, + uint32 create_options, + int *pinfo) { - BOOL got_stat = False; - files_struct *fsp = file_new(conn); - BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); - - if(!fsp) + files_struct *fsp = NULL; + BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; + BOOL create_dir = False; + int info = 0; + + DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " + "share_access = 0x%x create_options = 0x%x, " + "create_disposition = 0x%x\n", + fname, + (unsigned int)access_mask, + (unsigned int)share_access, + (unsigned int)create_options, + (unsigned int)create_disposition)); + + if (is_ntfs_stream_name(fname)) { + DEBUG(0,("open_directory: %s is a stream name!\n", fname )); + /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ + set_saved_error_triple(ERRDOS, ERRbadpath, + NT_STATUS_NOT_A_DIRECTORY); return NULL; + } - if (VALID_STAT(*psbuf)) - got_stat = True; - - if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { - file_free(fsp); - errno = EEXIST; /* Setup so correct error is returned to client. */ + if (dir_existed && !S_ISDIR(psbuf->st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ + set_saved_error_triple(ERRDOS, ERRbadpath, + NT_STATUS_NOT_A_DIRECTORY); return NULL; } - if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) { - - if (got_stat) { - - if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - file_free(fsp); - errno = EACCES; + switch( create_disposition ) { + case FILE_OPEN: + /* If directory exists open. If directory doesn't + * exist error. */ + if (!dir_existed) { + DEBUG(5,("open_directory: FILE_OPEN requested " + "for directory %s and it doesn't " + "exist.\n", fname )); + set_saved_error_triple(ERRDOS, ERRbadfile, + NT_STATUS_OBJECT_NAME_NOT_FOUND); return NULL; } - *action = FILE_WAS_OPENED; - - } else { - - /* - * Try and create the directory. - */ - - /* We know bad_path is false as it's caught earlier. */ - - NTSTATUS status = mkdir_internal(conn, fname, False); + info = FILE_WAS_OPENED; + break; - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); - file_free(fsp); - /* Ensure we return the correct NT status to the client. */ - set_saved_error_triple(0, 0, status); + case FILE_CREATE: + /* If directory exists error. If directory doesn't + * exist create. */ + if (dir_existed) { + DEBUG(5,("open_directory: FILE_CREATE " + "requested for directory %s and it " + "already exists.\n", fname )); + set_saved_error_triple(ERRDOS, ERRfilexists, + NT_STATUS_OBJECT_NAME_COLLISION); return NULL; } + create_dir = True; + info = FILE_WAS_CREATED; + break; - /* Ensure we're checking for a symlink here.... */ - /* We don't want to get caught by a symlink racer. */ - - if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - file_free(fsp); - return NULL; + case FILE_OPEN_IF: + /* If directory exists open. If directory doesn't + * exist create. */ + if (!dir_existed) { + create_dir = True; + info = FILE_WAS_CREATED; + } else { + info = FILE_WAS_OPENED; } + break; - if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - file_free(fsp); - return NULL; - } + case FILE_SUPERSEDE: + case FILE_OVERWRITE: + case FILE_OVERWRITE_IF: + default: + DEBUG(5,("open_directory: invalid create_disposition " + "0x%x for directory %s\n", + (unsigned int)create_disposition, fname)); + file_free(fsp); + set_saved_error_triple(ERRDOS, ERRinvalidparam, + NT_STATUS_INVALID_PARAMETER); + return NULL; + } + + if (create_dir) { + /* + * Try and create the directory. + */ - *action = FILE_WAS_CREATED; + /* We know bad_path is false as it's caught earlier. */ + NTSTATUS status = mkdir_internal(conn, fname, False); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("open_directory: unable to create %s. " + "Error was %s\n", fname, strerror(errno) )); + /* Ensure we return the correct NT status to the + * client. */ + set_saved_error_triple(0, 0, status); + return NULL; } - } else { - /* - * Don't create - just check that it *was* a directory. - */ + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ - if(!got_stat) { - DEBUG(3,("open_directory: unable to stat name = %s. Error was %s\n", - fname, strerror(errno) )); - file_free(fsp); + if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { return NULL; } if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - file_free(fsp); + DEBUG(0,("open_directory: %s is not a directory !\n", + fname )); return NULL; } + } - *action = FILE_WAS_OPENED; + fsp = file_new(conn); + if(!fsp) { + return NULL; } - - DEBUG(5,("open_directory: opening directory %s\n", fname)); /* * Setup the files_struct for it. @@ -1709,20 +2054,21 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; - fsp->share_mode = share_mode; - fsp->desired_access = desired_access; + + fsp->share_access = share_access; + fsp->fh->private_options = create_options; + fsp->access_mask = access_mask; + fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; fsp->is_stat = False; - fsp->directory_delete_on_close = False; string_set(&fsp->fsp_name,fname); - if (delete_on_close) { - NTSTATUS status = set_delete_on_close_internal(fsp, delete_on_close, 0); - + if (create_options & FILE_DELETE_ON_CLOSE) { + NTSTATUS status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { file_free(fsp); return NULL; @@ -1730,10 +2076,14 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR } /* Change the owner if required. */ - if ((*action == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { + if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); } + if (pinfo) { + *pinfo = info; + } + conn->num_files_open++; return fsp; @@ -1743,7 +2093,8 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) +files_struct *open_file_stat(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf) { files_struct *fsp = NULL; @@ -1772,15 +2123,12 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; - fsp->share_mode = 0; - fsp->desired_access = 0; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = True; - fsp->directory_delete_on_close = False; string_set(&fsp->fsp_name,fname); conn->num_files_open++; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8208fbebe3..3cfce5c7a1 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -343,6 +343,7 @@ BOOL process_local_message(char *buffer, int buf_size) SMB_INO_T inode; unsigned long file_id; uint16 break_cmd_type; + struct sockaddr_in toaddr; msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET); from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET); @@ -366,6 +367,7 @@ BOOL process_local_message(char *buffer, int buf_size) } if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev, &file_id)) { DEBUG(0,("kernel oplock break parse failure!\n")); + return False; } break; @@ -449,49 +451,54 @@ pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", * Now actually process the break request. */ - if((exclusive_oplocks_open + level_II_oplocks_open) != 0) { - if (oplock_break(dev, inode, file_id, False) == False) { - DEBUG(0,("process_local_message: oplock break failed.\n")); - return False; - } - } else { + if ((exclusive_oplocks_open == 0) && + (level_II_oplocks_open == 0)) { /* * If we have no record of any currently open oplocks, * it's not an error, as a close command may have * just been issued on the file that was oplocked. * Just log a message and return success in this case. */ - DEBUG(3,("process_local_message: oplock break requested with no outstanding \ -oplocks. Returning success.\n")); + DEBUG(3,("process_local_message: oplock break requested with " + "no outstanding oplocks. Returning success.\n")); + return True; + } + + if (!oplock_break(dev, inode, file_id, False)) { + DEBUG(0,("process_local_message: oplock break failed.\n")); + return False; } /* - * Do the appropriate reply - none in the kernel or async level II case. + * Do the appropriate reply - none in the kernel or async level II + * case. */ - if(break_cmd_type == OPLOCK_BREAK_CMD || break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD) { - struct sockaddr_in toaddr; + if (!((break_cmd_type == OPLOCK_BREAK_CMD) || + (break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD))) { + return True; + } - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY); + /* Send the message back after OR'ing in the 'REPLY' bit. */ + SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY); - memset((char *)&toaddr,'\0',sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; + memset((char *)&toaddr,'\0',sizeof(toaddr)); + toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + toaddr.sin_port = htons(from_port); + toaddr.sin_family = AF_INET; - if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { - DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", - (int)remotepid, strerror(errno))); - return False; - } - - DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %.0f, file_id = %lu\n", - (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); + if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { + DEBUG(0,("process_local_message: sendto process %d failed. " + "Errno was %s\n", (int)remotepid, strerror(errno))); + return False; } + DEBUG(5,("process_local_message: oplock break reply sent to pid %d, " + "port %d, for file dev = %x, inode = %.0f, file_id = %lu\n", + (int)remotepid, from_port, (unsigned int)dev, + (double)inode, file_id)); + return True; } @@ -1150,7 +1157,7 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) { DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd != -1)) { + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fh->fd != -1)) { /* Try and break the oplock. */ if (oplock_break(fsp->dev, fsp->inode, fsp->file_id, True)) { if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */ @@ -1223,6 +1230,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) pid_t pid = sys_getpid(); int num_share_modes = 0; int i; + BOOL dummy; /* * If this file is level II oplocked then we need @@ -1239,7 +1247,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp) DEBUG(0,("release_level_2_oplocks_on_change: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); } - num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list); + num_share_modes = get_share_modes(fsp->dev, fsp->inode, &share_list, + &dummy); DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", num_share_modes )); diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 78dc260939..477832c6e8 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -179,10 +179,10 @@ dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (doubl static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (linux_setlease(fsp->fd, F_WRLCK) == -1) { + if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. (%s)\n", - fsp->fsp_name, fsp->fd, + fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno))); return False; } @@ -204,7 +204,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) * Check and print out the current kernel * oplock state of this file. */ - int state = fcntl(fsp->fd, F_GETLEASE, 0); + int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, state ); @@ -213,7 +213,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /* * Remove the kernel oplock on this file. */ - if (linux_setlease(fsp->fd, F_UNLCK) == -1) { + if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 6c7faa4c05..951c192e39 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Luke Kenneth Casson Leighton 1996-1998 Copyright (C) Paul Ashton 1997-1998. + Copyright (C) Jeremy Allison 2005. 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 @@ -33,11 +34,11 @@ extern struct pipe_id_info pipe_names[]; /**************************************************************************** - reply to an open and X on a named pipe - - This code is basically stolen from reply_open_and_X with some - wrinkles to handle pipes. + Reply to an open and X on a named pipe. + This code is basically stolen from reply_open_and_X with some + wrinkles to handle pipes. ****************************************************************************/ + int reply_open_pipe_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { @@ -45,7 +46,6 @@ int reply_open_pipe_and_X(connection_struct *conn, pstring pipe_name; uint16 vuid = SVAL(inbuf, smb_uid); smb_np_struct *p; - int smb_ofun = SVAL(inbuf,smb_vwv8); int size=0,fmode=0,mtime=0,rmode=0; int i; @@ -55,23 +55,26 @@ int reply_open_pipe_and_X(connection_struct *conn, /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ - if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) + if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) { return(ERROR_DOS(ERRSRV,ERRaccess)); + } DEBUG(4,("Opening pipe %s.\n", pipe_name)); /* See if it is one we want to handle. */ - for( i = 0; pipe_names[i].client_pipe ; i++ ) - if( strequal(pipe_name,pipe_names[i].client_pipe) ) + for( i = 0; pipe_names[i].client_pipe ; i++ ) { + if( strequal(pipe_name,pipe_names[i].client_pipe)) { break; + } + } - if (pipe_names[i].client_pipe == NULL) + if (pipe_names[i].client_pipe == NULL) { return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); + } /* Strip \PIPE\ off the name. */ pstrcpy(fname, pipe_name + PIPELEN); - #if 0 /* * Hack for NT printers... JRA. @@ -83,10 +86,11 @@ int reply_open_pipe_and_X(connection_struct *conn, /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); - smb_ofun |= FILE_CREATE_IF_NOT_EXIST; p = open_rpc_pipe_p(fname, conn, vuid); - if (!p) return(ERROR_DOS(ERRSRV,ERRnofids)); + if (!p) { + return(ERROR_DOS(ERRSRV,ERRnofids)); + } /* Prepare the reply */ set_message(outbuf,15,0,True); @@ -111,8 +115,9 @@ int reply_open_pipe_and_X(connection_struct *conn, } /**************************************************************************** - reply to a write on a pipe + Reply to a write on a pipe. ****************************************************************************/ + int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) { smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); @@ -121,25 +126,27 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) int outsize; char *data; - if (!p) + if (!p) { return(ERROR_DOS(ERRDOS,ERRbadfid)); + } data = smb_buf(inbuf) + 3; - if (numtowrite == 0) + if (numtowrite == 0) { nwritten = 0; - else + } else { nwritten = write_to_pipe(p, data, numtowrite); + } - if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) + if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { return (UNIXERROR(ERRDOS,ERRnoaccess)); + } outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); - DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", - p->pnum, nwritten)); + DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); return(outsize); } @@ -158,24 +165,25 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == - (PIPE_START_MESSAGE|PIPE_RAW_MODE)); + (PIPE_START_MESSAGE|PIPE_RAW_MODE)); char *data; - if (!p) + if (!p) { return(ERROR_DOS(ERRDOS,ERRbadfid)); + } data = smb_base(inbuf) + smb_doff; - if (numtowrite == 0) + if (numtowrite == 0) { nwritten = 0; - else { + } else { if(pipe_start_message_raw) { /* * For the start of a message in named pipe byte mode, * the first two bytes are a length-of-pdu field. Ignore - * them (we don't trust the client. JRA. + * them (we don't trust the client). JRA. */ - if(numtowrite < 2) { + if(numtowrite < 2) { DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n", (unsigned int)numtowrite )); return (UNIXERROR(ERRDOS,ERRnoaccess)); @@ -183,30 +191,30 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) data += 2; numtowrite -= 2; - } + } nwritten = write_to_pipe(p, data, numtowrite); } - if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) + if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { return (UNIXERROR(ERRDOS,ERRnoaccess)); + } set_message(outbuf,6,0,True); nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); SSVAL(outbuf,smb_vwv2,nwritten); - DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", - p->pnum, nwritten)); + DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); return chain_reply(inbuf,outbuf,length,bufsize); } /**************************************************************************** - reply to a read and X - - This code is basically stolen from reply_read_and_X with some - wrinkles to handle pipes. + Reply to a read and X. + This code is basically stolen from reply_read_and_X with some + wrinkles to handle pipes. ****************************************************************************/ + int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); @@ -223,16 +231,18 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) uint32 smb_offs = IVAL(inbuf,smb_vwv3); #endif - if (!p) + if (!p) { return(ERROR_DOS(ERRDOS,ERRbadfid)); + } set_message(outbuf,12,0,True); data = smb_buf(outbuf); nread = read_from_pipe(p, data, smb_maxcnt, &unused); - if (nread < 0) + if (nread < 0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); + } SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -247,20 +257,23 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) } /**************************************************************************** - reply to a close + Reply to a close. ****************************************************************************/ + int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) { smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); int outsize = set_message(outbuf,0,0,True); - if (!p) + if (!p) { return(ERROR_DOS(ERRDOS,ERRbadfid)); + } DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum)); - if (!close_rpc_pipe_hnd(p)) + if (!close_rpc_pipe_hnd(p)) { return ERROR_DOS(ERRDOS,ERRbadfid); + } return(outsize); } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ffcfbc4fb1..ab14638a24 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -229,8 +229,8 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) { /* Instead just remove the attribute if it exists. */ - if (fsp->fd != -1) - SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME); + if (fsp->fh->fd != -1) + SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME); else SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME); return; @@ -238,8 +238,8 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size); - if (fsp->fd != -1) - ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + if (fsp->fh->fd != -1) + ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, store_size, 0); else ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME, @@ -445,8 +445,8 @@ static struct pai_val *load_inherited_info(files_struct *fsp) return NULL; do { - if (fsp->fd != -1) - ret = SMB_VFS_FGETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + if (fsp->fh->fd != -1) + ret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, pai_buf_size); else ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME, @@ -2422,7 +2422,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Finally apply it to the file or directory. */ - if(default_ace || fsp->is_directory || fsp->fd == -1) { + if(default_ace || fsp->is_directory || fsp->fh->fd == -1) { if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support @@ -2438,7 +2438,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } } else { - if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fd, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2668,7 +2668,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name )); - if(fsp->is_directory || fsp->fd == -1) { + if(fsp->is_directory || fsp->fh->fd == -1) { /* Get the stat struct for the owner info. */ if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { @@ -2692,13 +2692,13 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } else { /* Get the stat struct for the owner info. */ - if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { + if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { return 0; } /* * Get the ACL from the fd. */ - posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); + posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); } DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", @@ -2981,7 +2981,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ become_root(); /* Keep the current file gid the same. */ - ret = SMB_VFS_FCHOWN(fsp, fsp->fd, uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, uid, (gid_t)-1); unbecome_root(); close_file_fchmod(fsp); @@ -3022,11 +3022,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Get the current state of the file. */ - if(fsp->is_directory || fsp->fd == -1) { + if(fsp->is_directory || fsp->fh->fd == -1) { if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) + if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) return False; } @@ -3081,10 +3081,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) int ret; - if(fsp->fd == -1) + if(fsp->fh->fd == -1) ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf); else - ret = SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf); + ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf); if(ret != 0) return False; @@ -3683,8 +3683,8 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c } /* Get the current file ACL. */ - if (fsp && fsp->fd != -1) { - file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); + if (fsp && fsp->fh->fd != -1) { + file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); } else { file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS); } @@ -3767,9 +3767,9 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * return False; } - if (fsp && fsp->fd != -1) { + if (fsp && fsp->fh->fd != -1) { /* The preferred way - use an open fd. */ - if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fd, file_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, file_acl) == -1) { DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n", fname, strerror(errno) )); SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 312a3ace23..bb583fb94b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1275,20 +1275,24 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring fname; int outsize = 0; - int fmode=0; - int share_mode; + uint32 fattr=0; SMB_OFF_T size = 0; time_t mtime=0; - int rmode=0; + int info; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - uint16 dos_attr = SVAL(inbuf,smb_vwv1); + int deny_mode; + uint32 dos_attr = SVAL(inbuf,smb_vwv1); + uint32 access_mask; + uint32 share_mode; + uint32 create_disposition; + uint32 create_options = 0; NTSTATUS status; START_PROFILE(SMBopen); - share_mode = SVAL(inbuf,smb_vwv0); + deny_mode = SVAL(inbuf,smb_vwv0); srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { @@ -1304,8 +1308,20 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - (uint32)dos_attr, oplock_request,&rmode,NULL); + if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, + &access_mask, &share_mode, &create_disposition, &create_options)) { + END_PROFILE(SMBopen); + return ERROR_DOS(ERRDOS, ERRbadaccess); + } + + fsp = open_file_ntcreate(conn,fname,&sbuf, + access_mask, + share_mode, + create_disposition, + create_options, + dos_attr, + oplock_request, + &info); if (!fsp) { END_PROFILE(SMBopen); @@ -1317,10 +1333,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } size = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; - if (fmode & aDIR) { + if (fattr & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); close_file(fsp,False); END_PROFILE(SMBopen); @@ -1329,19 +1345,22 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, outsize = set_message(outbuf,7,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); - SSVAL(outbuf,smb_vwv1,fmode); - if(lp_dos_filetime_resolution(SNUM(conn)) ) + SSVAL(outbuf,smb_vwv1,fattr); + if(lp_dos_filetime_resolution(SNUM(conn)) ) { put_dos_date3(outbuf,smb_vwv2,mtime & ~1); - else + } else { put_dos_date3(outbuf,smb_vwv2,mtime); + } SIVAL(outbuf,smb_vwv4,(uint32)size); - SSVAL(outbuf,smb_vwv6,rmode); + SSVAL(outbuf,smb_vwv6,FILE_WAS_OPENED); - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } END_PROFILE(SMBopen); return(outsize); } @@ -1353,21 +1372,22 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; - int smb_mode = SVAL(inbuf,smb_vwv3); - int smb_attr = SVAL(inbuf,smb_vwv5); + uint16 open_flags = SVAL(inbuf,smb_vwv2); + int deny_mode = SVAL(inbuf,smb_vwv3); + uint32 smb_attr = SVAL(inbuf,smb_vwv5); /* Breakout the oplock request bits so we can set the reply bits separately. */ BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); BOOL oplock_request = ex_oplock_request | core_oplock_request; #if 0 - int open_flags = SVAL(inbuf,smb_vwv2); int smb_sattr = SVAL(inbuf,smb_vwv4); uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); #endif int smb_ofun = SVAL(inbuf,smb_vwv8); SMB_OFF_T size=0; - int fmode=0,mtime=0,rmode=0; + uint32 fattr=0; + int mtime=0; SMB_STRUCT_STAT sbuf; int smb_action = 0; BOOL bad_path = False; @@ -1375,6 +1395,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt NTSTATUS status; SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9); ssize_t retval = -1; + uint32 access_mask; + uint32 share_mode; + uint32 create_disposition; + uint32 create_options = 0; START_PROFILE(SMBopenX); @@ -1404,18 +1428,23 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - /* Strange open mode mapping. */ - if (smb_ofun == 0) { - if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) { - smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; - } else { - END_PROFILE(SMBopenX); - return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); - } + if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun, + &access_mask, + &share_mode, + &create_disposition, + &create_options)) { + END_PROFILE(SMBopenX); + return ERROR_DOS(ERRDOS, ERRbadaccess); } - fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr, - oplock_request, &rmode,&smb_action); + fsp = open_file_ntcreate(conn,fname,&sbuf, + access_mask, + share_mode, + create_disposition, + create_options, + smb_attr, + oplock_request, + &smb_action); if (!fsp) { END_PROFILE(SMBopenX); @@ -1446,9 +1475,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt size = get_allocation_size(conn,fsp,&sbuf); } - fmode = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; - if (fmode & aDIR) { + if (fattr & aDIR) { close_file(fsp,False); END_PROFILE(SMBopenX); return ERROR_DOS(ERRDOS,ERRnoaccess); @@ -1459,34 +1488,47 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt correct bit for extended oplock reply. */ - if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) + if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) { smb_action |= EXTENDED_OPLOCK_GRANTED; + } - if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { smb_action |= EXTENDED_OPLOCK_GRANTED; + } /* If the caller set the core oplock request bit and we granted one (by whatever means) - set the correct bit for core oplock reply. */ - if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) + if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } - if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } - set_message(outbuf,15,0,True); + if (open_flags & EXTENDED_RESPONSE_REQUIRED) { + set_message(outbuf,19,0,True); + } else { + set_message(outbuf,15,0,True); + } SSVAL(outbuf,smb_vwv2,fsp->fnum); - SSVAL(outbuf,smb_vwv3,fmode); - if(lp_dos_filetime_resolution(SNUM(conn)) ) + SSVAL(outbuf,smb_vwv3,fattr); + if(lp_dos_filetime_resolution(SNUM(conn)) ) { put_dos_date3(outbuf,smb_vwv4,mtime & ~1); - else + } else { put_dos_date3(outbuf,smb_vwv4,mtime); + } SIVAL(outbuf,smb_vwv6,(uint32)size); - SSVAL(outbuf,smb_vwv8,rmode); + SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode)); SSVAL(outbuf,smb_vwv11,smb_action); + if (open_flags & EXTENDED_RESPONSE_REQUIRED) { + SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS); + } + END_PROFILE(SMBopenX); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -1528,18 +1570,21 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring fname; int com; int outsize = 0; - int createmode; - int ofun = 0; + uint32 fattr = SVAL(inbuf,smb_vwv0); BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); SMB_STRUCT_STAT sbuf; NTSTATUS status; + uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE; + uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + uint32 create_disposition; + uint32 create_options = 0; + START_PROFILE(SMBcreate); com = SVAL(inbuf,smb_com); - createmode = SVAL(inbuf,smb_vwv0); srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); @@ -1554,20 +1599,27 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - if (createmode & aVOLID) + if (fattr & aVOLID) { DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); - + } + if(com == SMBmknew) { /* We should fail if file exists. */ - ofun = FILE_CREATE_IF_NOT_EXIST; + create_disposition = FILE_CREATE; } else { - /* SMBcreate - Create if file doesn't exist, truncate if it does. */ - ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE; - } - - /* Open file in dos compatibility share mode. */ - fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - ofun, (uint32)createmode, oplock_request, NULL, NULL); + /* Create if file doesn't exist, truncate if it does. */ + create_disposition = FILE_OPEN_IF; + } + + /* Open file using ntcreate. */ + fsp = open_file_ntcreate(conn,fname,&sbuf, + access_mask, + share_mode, + create_disposition, + create_options, + fattr, + oplock_request, + NULL); if (!fsp) { END_PROFILE(SMBcreate); @@ -1581,14 +1633,16 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } - DEBUG( 2, ( "new file %s\n", fname ) ); - DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) ); + DEBUG( 2, ( "reply_mknew: file %s\n", fname ) ); + DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) ); END_PROFILE(SMBcreate); return(outsize); @@ -1602,7 +1656,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring fname; int outsize = 0; - int createattr; + uint32 fattr = SVAL(inbuf,smb_vwv0); BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); @@ -1614,7 +1668,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBctemp); - createattr = SVAL(inbuf,smb_vwv0); srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); @@ -1642,12 +1695,15 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SMB_VFS_STAT(conn,fname,&sbuf); - /* Open file in dos compatibility share mode. */ /* We should fail if file does not exist. */ - fsp = open_file_shared(conn,fname,&sbuf, - SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), - FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST, - (uint32)createattr, oplock_request, NULL, NULL); + fsp = open_file_ntcreate(conn,fname,&sbuf, + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + fattr, + oplock_request, + NULL); /* close fd from smb_mkstemp() */ close(tmpfd); @@ -1666,10 +1722,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /* the returned filename is relative to the directory */ s = strrchr_m(fname, '/'); - if (!s) + if (!s) { s = fname; - else + } else { s++; + } p = smb_buf(outbuf); #if 0 @@ -1681,15 +1738,17 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, p += namelen; outsize = set_message_end(outbuf, p); - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + } - DEBUG( 2, ( "created temp file %s\n", fname ) ); - DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n", - fname, fsp->fd, sbuf.st_mode ) ); + DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) ); + DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd, + (unsigned int)sbuf.st_mode ) ); END_PROFILE(SMBctemp); return(outsize); @@ -1701,26 +1760,33 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst) { - int smb_action; - int access_mode; files_struct *fsp; - uint16 fmode; + uint32 fmode; - if (!CAN_WRITE(conn)) + if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; + } fmode = dos_mode(conn,fname,pst); - if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) + if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) { return NT_STATUS_NO_SUCH_FILE; + } - if (S_ISDIR(pst->st_mode)) + if (S_ISDIR(pst->st_mode)) { return NT_STATUS_OK; + } /* We need a better way to return NT status codes from open... */ set_saved_error_triple(0, 0, NT_STATUS_OK); - fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); + fsp = open_file_ntcreate(conn, fname, pst, + DELETE_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + 0, + NULL); if (!fsp) { NTSTATUS ret; @@ -1742,43 +1808,46 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open) { SMB_STRUCT_STAT sbuf; - uint32 fmode; - int smb_action; - int access_mode; + uint32 fattr; files_struct *fsp; - DEBUG(10,("can_delete: %s, dirtype = %d\n", - fname, dirtype )); + DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype )); - if (!CAN_WRITE(conn)) + if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; + } if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) { if(errno == ENOENT) { - if (bad_path) + if (bad_path) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; - else + } else { return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } } return map_nt_error_from_unix(errno); } - fmode = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fname,&sbuf); /* Can't delete a directory. */ - if (fmode & aDIR) + if (fattr & aDIR) { return NT_STATUS_FILE_IS_A_DIRECTORY; + } + #if 0 /* JRATEST */ else if (dirtype & aDIR) /* Asked for a directory and it isn't. */ return NT_STATUS_OBJECT_NAME_INVALID; #endif /* JRATEST */ if (!lp_delete_readonly(SNUM(conn))) { - if (fmode & aRONLY) + if (fattr & aRONLY) { return NT_STATUS_CANNOT_DELETE; + } } - if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) + if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) { return NT_STATUS_NO_SUCH_FILE; + } if (check_is_at_open) { if (!can_delete_file_in_directory(conn, fname)) { @@ -1791,8 +1860,14 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b /* We need a better way to return NT status codes from open... */ set_saved_error_triple(0, 0, NT_STATUS_OK); - fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); + fsp = open_file_ntcreate(conn, fname, &sbuf, + DELETE_ACCESS, + FILE_SHARE_NONE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + 0, + NULL); if (!fsp) { NTSTATUS ret; @@ -2058,7 +2133,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st header.length = 4; header.free = NULL; - if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { + if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ if (errno == ENOSYS) { goto normal_readbraw; @@ -2205,7 +2280,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s SMB_STRUCT_STAT st; SMB_OFF_T size = 0; - if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) { + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { size = st.st_size; } @@ -2251,7 +2326,9 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length START_PROFILE(SMBlockread); CHECK_FSP(fsp,conn); - CHECK_READ(fsp); + if (!CHECK_READ(fsp,inbuf)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } release_level_2_oplocks_on_change(fsp); @@ -2345,7 +2422,9 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int START_PROFILE(SMBread); CHECK_FSP(fsp,conn); - CHECK_READ(fsp); + if (!CHECK_READ(fsp,inbuf)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); @@ -2413,7 +2492,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length SMB_STRUCT_STAT sbuf; DATA_BLOB header; - if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) + if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); if (startpos > sbuf.st_size) @@ -2442,7 +2521,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length header.length = data - outbuf; header.free = NULL; - if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) { + if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ if (errno == ENOSYS) { goto normal_read; @@ -2530,7 +2609,9 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } CHECK_FSP(fsp,conn); - CHECK_READ(fsp); + if (!CHECK_READ(fsp,inbuf)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } set_message(outbuf,12,0,True); @@ -2610,7 +2691,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, } CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } tcount = IVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); @@ -2744,7 +2827,9 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, START_PROFILE(SMBwriteunlock); CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); @@ -2758,10 +2843,11 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, /* The special X/Open SMB protocol handling of zero length writes is *NOT* done for this call */ - if(numtowrite == 0) + if(numtowrite == 0) { nwritten = 0; - else + } else { nwritten = write_file(fsp,data,startpos,numtowrite); + } if (lp_syncalways(SNUM(conn))) sync_file(conn,fsp); @@ -2815,7 +2901,9 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d } CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); @@ -2896,7 +2984,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng } CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } set_message(outbuf,6,0,True); @@ -3010,7 +3100,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int break; case 1: umode = SEEK_CUR; - res = fsp->pos + startpos; + res = fsp->fh->pos + startpos; break; case 2: umode = SEEK_END; @@ -3022,19 +3112,19 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if (umode == SEEK_END) { - if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { + if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) { if(errno == EINVAL) { SMB_OFF_T current_pos = startpos; SMB_STRUCT_STAT sbuf; - if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { + if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); } current_pos += sbuf.st_size; if(current_pos < 0) - res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); + res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET); } } @@ -3044,7 +3134,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } } - fsp->pos = res; + fsp->fh->pos = res; outsize = set_message(outbuf,2,0,True); SIVAL(outbuf,smb_vwv0,res); @@ -3150,7 +3240,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, pstrcpy( file_name, fsp->fsp_name); DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", - fsp->fd, fsp->fnum, + fsp->fh->fd, fsp->fnum, conn->num_files_open)); /* @@ -3201,7 +3291,9 @@ int reply_writeclose(connection_struct *conn, START_PROFILE(SMBwriteclose); CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); @@ -3276,7 +3368,7 @@ int reply_lock(connection_struct *conn, offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", - fsp->fd, fsp->fnum, (double)offset, (double)count)); + fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); if (NT_STATUS_V(status)) { @@ -3327,7 +3419,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, } DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", - fsp->fd, fsp->fnum, (double)offset, (double)count ) ); + fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) ); END_PROFILE(SMBunlock); return(outsize); @@ -3437,7 +3529,7 @@ int reply_printopen(connection_struct *conn, SSVAL(outbuf,smb_vwv0,fsp->fnum); DEBUG(3,("openprint fd=%d fnum=%d\n", - fsp->fd, fsp->fnum)); + fsp->fh->fd, fsp->fnum)); END_PROFILE(SMBsplopen); return(outsize); @@ -3463,7 +3555,7 @@ int reply_printclose(connection_struct *conn, } DEBUG(3,("printclose fd=%d fnum=%d\n", - fsp->fd,fsp->fnum)); + fsp->fh->fd,fsp->fnum)); close_err = close_file(fsp,True); @@ -3567,7 +3659,9 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ } CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } numtowrite = SVAL(smb_buf(inbuf),1); data = smb_buf(inbuf) + 3; @@ -4484,45 +4578,66 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory, int *err_ret) { - int Access,action; SMB_STRUCT_STAT src_sbuf, sbuf2; SMB_OFF_T ret=-1; files_struct *fsp1,*fsp2; pstring dest; uint32 dosattrs; + uint32 new_create_disposition; *err_ret = 0; pstrcpy(dest,dest1); if (target_is_directory) { char *p = strrchr_m(src,'/'); - if (p) + if (p) { p++; - else + } else { p = src; + } pstrcat(dest,"/"); pstrcat(dest,p); } - if (!vfs_file_exist(conn,src,&src_sbuf)) + if (!vfs_file_exist(conn,src,&src_sbuf)) { return(False); + } + + if (!target_is_directory && count) { + new_create_disposition = FILE_OPEN; + } else { + if (!map_open_params_to_ntcreate(dest1,0,ofun, + NULL, NULL, &new_create_disposition, NULL)) { + return(False); + } + } - fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY, - &Access,&action); + fsp1 = open_file_ntcreate(conn,src,&src_sbuf, + FILE_GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + INTERNAL_OPEN_ONLY, + NULL); - if (!fsp1) + if (!fsp1) { return(False); - - if (!target_is_directory && count) - ofun = FILE_EXISTS_OPEN; + } dosattrs = dos_mode(conn, src, &src_sbuf); - if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) + if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) { ZERO_STRUCTP(&sbuf2); + } - fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action); + fsp2 = open_file_ntcreate(conn,dest,&sbuf2, + FILE_GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + new_create_disposition, + 0, + dosattrs, + INTERNAL_OPEN_ONLY, + NULL); if (!fsp2) { close_file(fsp1,False); @@ -4530,7 +4645,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) { + if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); /* * Stop the copy from occurring. @@ -4540,8 +4655,9 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } } - if (src_sbuf.st_size) + if (src_sbuf.st_size) { ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); + } close_file(fsp1,False); @@ -4955,7 +5071,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, /* we don't support these - and CANCEL_LOCK makes w2k and XP reboot so I don't really want to be compatible! (tridge) */ - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + return ERROR_DOS(ERRDOS, ERRnoatomiclocks); } if (locktype & LOCKING_ANDX_CANCEL_LOCK) { @@ -5158,7 +5274,9 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, outsize = set_message(outbuf,8,0,True); CHECK_FSP(fsp,conn); - CHECK_READ(fsp); + if (!CHECK_READ(fsp,inbuf)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); @@ -5286,7 +5404,9 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, START_PROFILE(SMBwriteBmpx); CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } if (HAS_CACHED_ERROR(fsp)) { return(CACHED_ERROR(fsp)); } @@ -5390,7 +5510,9 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz START_PROFILE(SMBwriteBs); CHECK_FSP(fsp,conn); - CHECK_WRITE(fsp); + if (!CHECK_WRITE(fsp)) { + return(ERROR_DOS(ERRDOS,ERRbadaccess)); + } tcount = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d4daf1fd69..602656080e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3,6 +3,7 @@ SMB transaction2 handling Copyright (C) Jeremy Allison 1994-2003 Copyright (C) Stefan (metze) Metzmacher 2003 + Copyright (C) Volker Lendecke 2005 Extensively modified by Andrew Tridgell, 1995 @@ -119,8 +120,8 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str return False; } - if (fsp && fsp->fd != -1) { - sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size); + if (fsp && fsp->fh->fd != -1) { + sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size); } else { sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size); } @@ -171,8 +172,8 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6; ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { - if (fsp && fsp->fd != -1) { - sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size); + if (fsp && fsp->fh->fd != -1) { + sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size); } else { sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size); } @@ -337,10 +338,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s if (ea_list->ea.value.length == 0) { /* Remove the attribute. */ - if (fsp && (fsp->fd != -1)) { + if (fsp && (fsp->fh->fd != -1)) { DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); + ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name); } else { DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", unix_ea_name, fname)); @@ -355,10 +356,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s } #endif } else { - if (fsp && (fsp->fd != -1)) { + if (fsp && (fsp->fh->fd != -1)) { DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, + ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name, ea_list->ea.value.data, ea_list->ea.value.length, 0); } else { DEBUG(10,("set_ea: setting ea name %s on file %s.\n", @@ -717,20 +718,20 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i { char *params = *pparams; char *pdata = *ppdata; - int16 open_mode; - int16 open_attr; + int deny_mode; + int32 open_attr; BOOL oplock_request; #if 0 BOOL return_additional_info; int16 open_sattr; time_t open_time; #endif - int16 open_ofun; + int open_ofun; int32 open_size; char *pname; pstring fname; SMB_OFF_T size=0; - int fmode=0,mtime=0,rmode; + int fattr=0,mtime=0; SMB_INO_T inode = 0; SMB_STRUCT_STAT sbuf; int smb_action = 0; @@ -740,6 +741,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i struct ea_list *ea_list = NULL; uint16 flags = 0; NTSTATUS status; + uint32 access_mask; + uint32 share_mode; + uint32 create_disposition; + uint32 create_options = 0; /* * Ensure we have enough parameters to perform the operation. @@ -750,7 +755,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } flags = SVAL(params, 0); - open_mode = SVAL(params, 2); + deny_mode = SVAL(params, 2); open_attr = SVAL(params,6); oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; if (oplock_request) { @@ -766,16 +771,18 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i open_size = IVAL(params,14); pname = ¶ms[28]; - if (IS_IPC(conn)) + if (IS_IPC(conn)) { return(ERROR_DOS(ERRSRV,ERRaccess)); + } srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n", - fname,open_mode, open_attr, open_ofun, open_size)); + DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n", + fname, (unsigned int)deny_mode, (unsigned int)open_attr, + (unsigned int)open_ofun, open_size)); /* XXXX we need to handle passed times, sattr and flags */ @@ -788,11 +795,12 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } - /* Strange open mode mapping. */ - if (open_ofun == 0) { - if (GET_OPEN_MODE(open_mode) == DOS_OPEN_EXEC) { - open_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; - } + if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun, + &access_mask, + &share_mode, + &create_disposition, + &create_options)) { + return ERROR_DOS(ERRDOS, ERRbadaccess); } /* Any data in this call is an EA list. */ @@ -822,8 +830,14 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } } - fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr, - oplock_request, &rmode,&smb_action); + fsp = open_file_ntcreate(conn,fname,&sbuf, + access_mask, + share_mode, + create_disposition, + create_options, + open_attr, + oplock_request, + &smb_action); if (!fsp) { talloc_destroy(ctx); @@ -835,10 +849,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } size = get_file_size(sbuf); - fmode = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; inode = sbuf.st_ino; - if (fmode & aDIR) { + if (fattr & aDIR) { talloc_destroy(ctx); close_file(fsp,False); return(ERROR_DOS(ERRDOS,ERRnoaccess)); @@ -861,10 +875,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i *pparams = params; SSVAL(params,0,fsp->fnum); - SSVAL(params,2,fmode); + SSVAL(params,2,open_attr); put_dos_date2(params,4, mtime); SIVAL(params,8, (uint32)size); - SSVAL(params,12,rmode); + SSVAL(params,12,open_ofun); SSVAL(params,16,0); /* Padding. */ if (oplock_request && lp_fake_oplocks(SNUM(conn))) { @@ -2332,7 +2346,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned fsp.conn = conn; fsp.fnum = -1; - fsp.fd = -1; + fsp.fh->fd = -1; /* access check */ if (current_user.uid != 0) { @@ -2709,6 +2723,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * char *pdata = *ppdata; uint16 info_level; int mode=0; + int nlink; SMB_OFF_T file_size=0; SMB_BIG_UINT allocation_size=0; unsigned int data_size = 0; @@ -2726,7 +2741,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * files_struct *fsp = NULL; TALLOC_CTX *ea_ctx = NULL; struct ea_list *ea_list = NULL; - uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ + uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -2751,7 +2766,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * pstrcpy(fname, fsp->fsp_name); /* We know this name is ok, it's already passed the checks. */ - } else if(fsp && (fsp->is_directory || fsp->fd == -1)) { + } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems @@ -2771,7 +2786,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0; + delete_pending = + get_delete_on_close_flag(sbuf.st_dev, + sbuf.st_ino); } else { /* * Original code - this is an open file. @@ -2779,13 +2796,15 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * CHECK_FSP(fsp,conn); pstrcpy(fname, fsp->fsp_name); - if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = fsp->position_information; - delete_pending = fsp->delete_on_close; - desired_access = fsp->desired_access; + pos = fsp->fh->position_information; + delete_pending = + get_delete_on_close_flag(sbuf.st_dev, + sbuf.st_ino); + access_mask = fsp->access_mask; } } else { NTSTATUS status = NT_STATUS_OK; @@ -2825,6 +2844,23 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } + + delete_pending = get_delete_on_close_flag(sbuf.st_dev, + sbuf.st_ino); + if (delete_pending) { + return ERROR_NT(NT_STATUS_DELETE_PENDING); + } + } + + nlink = sbuf.st_nlink; + + if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) { + /* NTFS does not seem to count ".." */ + nlink -= 1; + } + + if ((nlink > 0) && delete_pending) { + nlink -= 1; } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) @@ -3054,11 +3090,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - if (delete_pending & sbuf.st_nlink) - SIVAL(pdata,16,sbuf.st_nlink - 1); - else - SIVAL(pdata,16,sbuf.st_nlink); - SCVAL(pdata,20,0); + SIVAL(pdata,16,nlink); + SCVAL(pdata,20,delete_pending?1:0); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); /* Padding. */ break; @@ -3129,10 +3162,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - if (delete_pending && sbuf.st_nlink) - SIVAL(pdata,16,sbuf.st_nlink - 1); - else - SIVAL(pdata,16,sbuf.st_nlink); + SIVAL(pdata,16,nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); @@ -3160,7 +3190,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_FILE_ACCESS_INFORMATION: DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n")); - SIVAL(pdata,0,desired_access); + SIVAL(pdata,0,access_mask); data_size = 4; break; @@ -3343,8 +3373,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd uint16 num_file_acls = 0; uint16 num_def_acls = 0; - if (fsp && !fsp->is_directory && (fsp->fd != -1)) { - file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); + if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) { + file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); } else { file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS); } @@ -3429,50 +3459,46 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd open_file_shared. JRA. ****************************************************************************/ -NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode) +NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, + uint32 dosmode) { - if (delete_on_close) { - /* - * Only allow delete on close for writable files. - */ - - if (!lp_delete_readonly(SNUM(fsp->conn))) { - if (dosmode & aRONLY) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n", - fsp->fsp_name )); - return NT_STATUS_CANNOT_DELETE; - } - } + if (!delete_on_close) { + return NT_STATUS_OK; + } - /* - * Only allow delete on close for writable shares. - */ + /* + * Only allow delete on close for writable files. + */ - if (!CAN_WRITE(fsp->conn)) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n", - fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } + if ((dosmode & aRONLY) && + !lp_delete_readonly(SNUM(fsp->conn))) { + DEBUG(10,("can_set_delete_on_close: file %s delete on close " + "flag set but file attribute is readonly.\n", + fsp->fsp_name )); + return NT_STATUS_CANNOT_DELETE; + } - /* - * Only allow delete on close for files/directories opened with delete intent. - */ + /* + * Only allow delete on close for writable shares. + */ - if (!(fsp->desired_access & DELETE_ACCESS)) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n", - fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } + if (!CAN_WRITE(fsp->conn)) { + DEBUG(10,("can_set_delete_on_close: file %s delete on " + "close flag set but write access denied on share.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; } - if(fsp->is_directory) { - fsp->directory_delete_on_close = delete_on_close; - DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); - } else { - fsp->delete_on_close = delete_on_close; - DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); + /* + * Only allow delete on close for files/directories opened with delete + * intent. + */ + + if (!(fsp->access_mask & DELETE_ACCESS)) { + DEBUG(10,("can_set_delete_on_close: file %s delete on " + "close flag set but delete access denied.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK; @@ -3487,10 +3513,12 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, u if flag is set. ****************************************************************************/ -NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) +NTSTATUS set_delete_on_close(files_struct *fsp, BOOL delete_on_close) { - DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + DEBUG(10,("set_delete_on_close: %s delete on close flag for " + "fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, + fsp->fsp_name )); if (fsp->is_directory || fsp->is_stat) return NT_STATUS_OK; @@ -3499,8 +3527,9 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) return NT_STATUS_ACCESS_DENIED; if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n", - fsp->fsp_name )); + DEBUG(0,("set_delete_on_close: failed to change delete " + "on close flag for file %s\n", + fsp->fsp_name )); unlock_share_entry_fsp(fsp); return NT_STATUS_ACCESS_DENIED; } @@ -3632,7 +3661,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char fsp = file_fsp(params,0); info_level = SVAL(params,2); - if(fsp && (fsp->is_directory || fsp->fd == -1)) { + if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) { /* * This is actually a SETFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems @@ -3648,7 +3677,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char * Doing a DELETE_ON_CLOSE should cancel a print job. */ if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) { - fsp->share_mode = FILE_DELETE_ON_CLOSE; + fsp->fh->private_options |= FILE_DELETE_ON_CLOSE; DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); @@ -3664,7 +3693,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char CHECK_FSP(fsp,conn); pstrcpy(fname, fsp->fsp_name); - fd = fsp->fd; + fd = fsp->fh->fd; if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); @@ -3881,8 +3910,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (fd == -1) { files_struct *new_fsp = NULL; - int access_mode = 0; - int action = 0; if(global_oplock_break) { /* Queue this file modify as we are the process of an oplock break. */ @@ -3894,16 +3921,20 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return -1; } - new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA, - SET_OPEN_MODE(DOS_OPEN_RDWR), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + new_fsp = open_file_ntcreate(conn, fname, &sbuf, + FILE_WRITE_DATA, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, FILE_ATTRIBUTE_NORMAL, - INTERNAL_OPEN_ONLY, &access_mode, &action); + INTERNAL_OPEN_ONLY, + NULL); - if (new_fsp == NULL) + if (new_fsp == NULL) { return(UNIXERROR(ERRDOS,ERRbadpath)); + } ret = vfs_allocate_file_space(new_fsp, allocation_size); - if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) { + if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", new_fsp->fnum, strerror(errno))); ret = -1; @@ -3963,14 +3994,15 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadfid)); - status = set_delete_on_close_internal(fsp, delete_on_close, dosmode); + status = can_set_delete_on_close(fsp, delete_on_close, + dosmode); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } /* The set is across all open files on this dev/inode pair. */ - status =set_delete_on_close_over_all(fsp, delete_on_close); + status =set_delete_on_close(fsp, delete_on_close); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -3998,7 +4030,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", fname, (double)position_information )); if (fsp) { - fsp->position_information = position_information; + fsp->fh->position_information = position_information; } /* We're done. We only get position info in this call. */ @@ -4422,8 +4454,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (fd == -1) { files_struct *new_fsp = NULL; - int access_mode = 0; - int action = 0; if(global_oplock_break) { /* Queue this file modify as we are the process of an oplock break. */ @@ -4435,22 +4465,27 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return -1; } - new_fsp = open_file_shared(conn, fname, &sbuf, - SET_OPEN_MODE(DOS_OPEN_RDWR), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + new_fsp = open_file_ntcreate(conn, fname, &sbuf, + FILE_WRITE_DATA, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, FILE_ATTRIBUTE_NORMAL, - INTERNAL_OPEN_ONLY, &access_mode, &action); + INTERNAL_OPEN_ONLY, + NULL); - if (new_fsp == NULL) + if (new_fsp == NULL) { return(UNIXERROR(ERRDOS,ERRbadpath)); + } ret = vfs_set_filelen(new_fsp, size); close_file(new_fsp,True); } else { ret = vfs_set_filelen(fsp, size); } - if (ret == -1) + if (ret == -1) { return (UNIXERROR(ERRHRD,ERRdiskfull)); + } } /* diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 1d205e5977..39ac402f34 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -226,7 +226,7 @@ ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void if (result == -1 && errno == ESPIPE) { /* Maintain the fiction that pipes can be seeked (sought?) on. */ result = SMB_VFS_READ(fsp, fd, data, n); - fsp->pos = 0; + fsp->fh->pos = 0; } #else /* HAVE_PREAD */ @@ -237,7 +237,7 @@ ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void if (curr == -1 && errno == ESPIPE) { /* Maintain the fiction that pipes can be seeked (sought?) on. */ result = SMB_VFS_READ(fsp, fd, data, n); - fsp->pos = 0; + fsp->fh->pos = 0; return result; } @@ -660,7 +660,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs SMB_OFF_T retlen; SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); - retlen = SMB_VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write); + retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write); if (retlen <= 0) return -1; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 11adfed694..67970f203a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -430,7 +430,7 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) while (total < byte_count) { - ssize_t ret = SMB_VFS_READ(fsp, fsp->fd, buf + total, + ssize_t ret = SMB_VFS_READ(fsp, fsp->fh->fd, buf + total, byte_count - total); if (ret == 0) return total; @@ -452,7 +452,7 @@ ssize_t vfs_pread_data(files_struct *fsp, char *buf, while (total < byte_count) { - ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fd, buf + total, + ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fh->fd, buf + total, byte_count - total, offset + total); if (ret == 0) return total; @@ -477,7 +477,7 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) ssize_t ret; while (total < N) { - ret = SMB_VFS_WRITE(fsp,fsp->fd,buffer + total,N - total); + ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total); if (ret == -1) return -1; @@ -496,7 +496,7 @@ ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer, ssize_t ret; while (total < N) { - ret = SMB_VFS_PWRITE(fsp, fsp->fd, buffer + total, + ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total, N - total, offset + total); if (ret == -1) @@ -535,7 +535,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) return -1; } - ret = SMB_VFS_FSTAT(fsp,fsp->fd,&st); + ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st); if (ret == -1) return ret; @@ -549,7 +549,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) fsp->fsp_name, (double)st.st_size )); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { + if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, (SMB_OFF_T)len)) != -1) { set_filelen_write_cache(fsp, len); } return ret; @@ -591,7 +591,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, len)) != -1) + if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1) set_filelen_write_cache(fsp, len); return ret; @@ -617,7 +617,7 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) ssize_t pwrite_ret; release_level_2_oplocks_on_change(fsp); - ret = SMB_VFS_FSTAT(fsp,fsp->fd,&st); + ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st); if (ret == -1) { return ret; } @@ -646,7 +646,7 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) while (total < num_to_write) { size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total)); - pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fd, sparse_buf, curr_write_size, offset + total); + pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, sparse_buf, curr_write_size, offset + total); if (pwrite_ret == -1) { DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n", fsp->fsp_name, strerror(errno) )); @@ -685,7 +685,7 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) in_fsp = in; out_fsp = out; - return transfer_file_internal(in_fsp->fd, out_fsp->fd, n, read_fn, write_fn); + return transfer_file_internal(in_fsp->fh->fd, out_fsp->fh->fd, n, read_fn, write_fn); } /******************************************************************* -- cgit From a32a7969c598b32c58fad4a7d1cb88cafb4a9e26 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 8 Jul 2005 07:54:28 +0000 Subject: r8231: Patch from James Peach to fix the IRIX build. Thanks, Volker (This used to be commit 1ebb3aa0d5007c470862e3adca92d2941ffa294c) --- source3/smbd/oplock_irix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index ffcf3d0af4..f4405a021e 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -164,7 +164,7 @@ dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->i static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (sys_fcntl_long(fsp->fd, F_OPLKREG, oplock_pipe_write) == -1) { + if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) { if(errno != EAGAIN) { DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f, file_id = %ul. Error was %s\n", @@ -173,7 +173,7 @@ inode = %.0f, file_id = %ul. Error was %s\n", } else { DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f, file_id = %ul. Another process had the file open.\n", - fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); + fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); } return False; } @@ -195,7 +195,7 @@ static void irix_release_kernel_oplock(files_struct *fsp) * Check and print out the current kernel * oplock state of this file. */ - int state = sys_fcntl_long(fsp->fd, F_OPLKACK, -1); + int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, state ); @@ -204,7 +204,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /* * Remove the kernel oplock on this file. */ - if(sys_fcntl_long(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) { + if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) { if( DEBUGLVL( 0 )) { dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n", -- cgit From a5b39d1f74cd1b9271fed6017cb0708320339a14 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 10 Jul 2005 16:37:32 +0000 Subject: r8290: Fix for bug in SMBwriteBraw where we incorrectly returned the number of bytes written. Patch from Marcel Müller . Jeremy. (This used to be commit 81e7a4a2cfd2d4764d757702f17635e5007e59de) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bb583fb94b..5e8c0ef296 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2751,7 +2751,6 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, /* Set up outbuf to return the correct return */ outsize = set_message(outbuf,1,0,True); SCVAL(outbuf,smb_com,SMBwritec); - SSVAL(outbuf,smb_vwv0,total_written); if (numtowrite != 0) { @@ -2783,6 +2782,8 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, total_written += nwritten; } + SSVAL(outbuf,smb_vwv0,total_written); + if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn))) sync_file(conn,fsp); -- cgit From e24397f084282de2b88dc83995740037e8c4cf32 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 10 Jul 2005 16:40:06 +0000 Subject: r8292: Tidy up function comments. Jeremy. (This used to be commit 8de6b1592ad205f59c44ed30102a56594f65e555) --- source3/smbd/files.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 80e5b0f710..c90c2b627c 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -238,6 +238,10 @@ void file_close_user(int vuid) } } +/**************************************************************************** + Debug to enumerate all open files in the smbd. +****************************************************************************/ + void file_dump_open_table(void) { int count=0; @@ -508,7 +512,7 @@ void file_chain_reset(void) } /**************************************************************************** -Save the chained fsp - done when about to do an oplock break. + Save the chained fsp - done when about to do an oplock break. ****************************************************************************/ void file_chain_save(void) @@ -517,7 +521,7 @@ void file_chain_save(void) } /**************************************************************************** -Restore the chained fsp - done after an oplock break. + Restore the chained fsp - done after an oplock break. ****************************************************************************/ void file_chain_restore(void) @@ -525,6 +529,10 @@ void file_chain_restore(void) chain_fsp = oplock_save_chain_fsp; } +/**************************************************************************** + Duplicate the file handle part for a DOS or FCB open. +****************************************************************************/ + files_struct *dup_file_fsp(files_struct *fsp, uint32 access_mask, uint32 share_access, -- cgit From 60e18904e676c1360950cc8342778f5dee4cd8e2 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Jul 2005 00:26:52 +0000 Subject: r8402: allow to build with --enable-aio-support. Guenther (This used to be commit 49351d91c59b2e96ebddb2d721e660dcd90ec815) --- source3/smbd/aio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 7910ee5a7a..d19706ff61 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -242,7 +242,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, /* Now set up the aio record for the read call. */ - a->aio_fildes = fsp->fd; + a->aio_fildes = fsp->fh->fd; a->aio_buf = smb_buf(aio_ex->outbuf); a->aio_nbytes = smb_maxcnt; a->aio_offset = startpos; @@ -321,7 +321,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, /* Now set up the aio record for the write call. */ - a->aio_fildes = fsp->fd; + a->aio_fildes = fsp->fh->fd; a->aio_buf = data; /* As we've stolen inbuf this points within inbuf. */ a->aio_nbytes = numtowrite; a->aio_offset = startpos; @@ -677,7 +677,7 @@ void cancel_aio_by_fsp(files_struct *fsp) if (aio_ex->fsp == fsp) { /* Don't delete the aio_extra record as we may have completed and don't yet know it. Just do the aio_cancel call and return. */ - SMB_VFS_AIO_CANCEL(fsp,fsp->fd, &aio_ex->acb); + SMB_VFS_AIO_CANCEL(fsp,fsp->fh->fd, &aio_ex->acb); aio_ex->fsp = NULL; /* fsp will be closed when we return. */ } } -- cgit From 200ff9c1e930249a0ab1dea4a8b1b92ef614aa6e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 14 Jul 2005 08:02:10 +0000 Subject: r8454: Fix Bug #2502 Removing deprecated lp_min_password_length (the same functionality is provided by the account policy). Note that we now allow to set passwords less then 5 chars (if the admins decides to do so by setting the account policy). Thanks to Daniel Beschorner Guenther (This used to be commit fd91378925f7e3541df4f31bd461dabc1da523a9) --- source3/smbd/chgpasswd.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 56e5727b7d..f445ca3365 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1017,7 +1017,6 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw return NT_STATUS_ACCOUNT_RESTRICTION; } - /* FIXME: AP_MIN_PASSWORD_LEN and lp_min_passwd_length() need to be merged - gd */ if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { DEBUG(1, ("user %s cannot change password - password too short\n", username)); @@ -1026,16 +1025,6 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw /* return NT_STATUS_PWD_TOO_SHORT; */ } - /* Take the passed information and test it for minimum criteria */ - /* Minimum password length */ - if (str_charnum(new_passwd) < lp_min_passwd_length()) { - /* too short, must be at least MINPASSWDLENGTH */ - DEBUG(1, ("Password Change: user %s, New password is shorter than minimum password length = %d\n", - username, lp_min_passwd_length())); - return NT_STATUS_PASSWORD_RESTRICTION; -/* return NT_STATUS_PWD_TOO_SHORT; */ - } - if (check_passwd_history(hnd,new_passwd)) { return NT_STATUS_PASSWORD_RESTRICTION; } -- cgit From 0d8ef1cec4134521dc507bd27f256ed93084818c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Jul 2005 08:51:48 +0000 Subject: r8457: Fix from Marcel Müller to ensure we correctly set the return packet size to include the pad bytes in reply_readbmpx(). Jeremy. (This used to be commit 3070ec288c64880485ed159d512e91346f5d1b4e) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5e8c0ef296..4ce93222f7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5308,7 +5308,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, if (nread < (ssize_t)N) tcount = total_read + nread; - set_message(outbuf,8,nread,False); + set_message(outbuf,8,nread+pad,False); SIVAL(outbuf,smb_vwv0,startpos); SSVAL(outbuf,smb_vwv2,tcount); SSVAL(outbuf,smb_vwv6,nread); -- cgit From dae78e57e2341e519a2bb609d827968ac93a2499 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 14 Jul 2005 14:39:27 +0000 Subject: r8472: abartlet's patch for parallel ntlmssp supporttrunk/source/smbd/sesssetup.c (This used to be commit aab17a7095a18b243a271f8f3f824facd6932f23) --- source3/smbd/password.c | 37 +++++++++++++++++++++++- source3/smbd/sesssetup.c | 75 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 94 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2ee8c1232e..9ee721089c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -47,7 +47,31 @@ user_struct *get_valid_user_struct(uint16 vuid) return NULL; for (usp=validated_users;usp;usp=usp->next,count++) { - if (vuid == usp->vuid) { + if (vuid == usp->vuid && usp->server_info) { + if (count > 10) { + DLIST_PROMOTE(validated_users, usp); + } + return usp; + } + } + + return NULL; +} + +/**************************************************************************** + Get the user struct of a partial NTLMSSP login +****************************************************************************/ + +user_struct *get_partial_auth_user_struct(uint16 vuid) +{ + user_struct *usp; + int count=0; + + if (vuid == UID_FIELD_INVALID) + return NULL; + + for (usp=validated_users;usp;usp=usp->next,count++) { + if (vuid == usp->vuid && !usp->server_info) { if (count > 10) { DLIST_PROMOTE(validated_users, usp); } @@ -159,6 +183,17 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, vuser->vuid = next_vuid; + if (!server_info) { + next_vuid++; + num_validated_vuids++; + + vuser->server_info = NULL; + + DLIST_ADD(validated_users, vuser); + + return vuser->vuid; + } + /* the next functions should be done by a SID mapping system (SMS) as * the new real sam db won't have reference to unix uids or gids */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1ddd6256b3..8586ac1324 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -25,8 +25,6 @@ uint32 global_client_caps = 0; -static struct auth_ntlmssp_state *global_ntlmssp_state; - /* on a logon error possibly map the error to success if "map to guest" is set approriately @@ -353,6 +351,7 @@ static int reply_spnego_kerberos(connection_struct *conn, ***************************************************************************/ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, + uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) { @@ -416,6 +415,8 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { auth_ntlmssp_end(auth_ntlmssp_state); + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); } return ret; @@ -428,8 +429,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out static int reply_spnego_negotiate(connection_struct *conn, char *inbuf, char *outbuf, + uint16 vuid, int length, int bufsize, - DATA_BLOB blob1) + DATA_BLOB blob1, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { char *OIDs[ASN1_MAX_OIDS]; DATA_BLOB secblob; @@ -442,6 +445,9 @@ static int reply_spnego_negotiate(connection_struct *conn, /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -473,25 +479,31 @@ static int reply_spnego_negotiate(connection_struct *conn, int ret = reply_spnego_kerberos(conn, inbuf, outbuf, length, bufsize, &secblob); data_blob_free(&secblob); + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ret; } #endif - if (global_ntlmssp_state) { - auth_ntlmssp_end(&global_ntlmssp_state); + if (*auth_ntlmssp_state) { + auth_ntlmssp_end(auth_ntlmssp_state); } - nt_status = auth_ntlmssp_start(&global_ntlmssp_state); + nt_status = auth_ntlmssp_start(auth_ntlmssp_state); if (!NT_STATUS_IS_OK(nt_status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ERROR_NT(nt_status); } - nt_status = auth_ntlmssp_update(global_ntlmssp_state, + nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, secblob, &chal); data_blob_free(&secblob); - reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, &chal, nt_status); data_blob_free(&chal); @@ -505,8 +517,10 @@ static int reply_spnego_negotiate(connection_struct *conn, ****************************************************************************/ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, + uint16 vuid, int length, int bufsize, - DATA_BLOB blob1) + DATA_BLOB blob1, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { DATA_BLOB auth, auth_reply; NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; @@ -515,20 +529,27 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, #if 0 file_save("auth.dat", blob1.data, blob1.length); #endif + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - if (!global_ntlmssp_state) { + if (!*auth_ntlmssp_state) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + /* auth before negotiatiate? */ return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - nt_status = auth_ntlmssp_update(global_ntlmssp_state, - auth, &auth_reply); + nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, + auth, &auth_reply); data_blob_free(&auth); - reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, + auth_ntlmssp_state, &auth_reply, nt_status); data_blob_free(&auth_reply); @@ -553,6 +574,8 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, char *p2; uint16 data_blob_len = SVAL(inbuf, smb_vwv7); enum remote_arch_types ra_type = get_remote_arch(); + int vuid = SVAL(inbuf,smb_uid); + user_struct *vuser = NULL; DEBUG(3,("Doing spnego session setup\n")); @@ -597,16 +620,34 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, ra_lanman_string( native_lanman ); } + vuser = get_partial_auth_user_struct(vuid); + if (!vuser) { + vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL); + if (vuid == -1) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + vuser = get_partial_auth_user_struct(vuid); + } + + if (!vuser) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + SSVAL(outbuf,smb_uid,vuid); + if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ - ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1); + ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1, + &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return ret; } if (blob1.data[0] == ASN1_CONTEXT(1)) { /* its a auth packet */ - ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1); + ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1, + &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return ret; } @@ -682,7 +723,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { if (!global_spnego_negotiated) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } if (SVAL(inbuf,smb_vwv4) == 0) { @@ -843,7 +884,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } fstrcpy(sub_user, user); -- cgit From 4fffd271d04fca6e305fda1aba99d88a60fc5271 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 15 Jul 2005 11:52:07 +0000 Subject: r8492: open_mode_check does not use the parameter p_flags, so remove it. Volker (This used to be commit ed9cb0061dbbc7677d5968581fde46c89febb6c0) --- source3/smbd/open.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 810913c025..3cd553f55b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -556,7 +556,6 @@ static int open_mode_check(connection_struct *conn, uint32 access_mask, uint32 share_access, uint32 create_options, - int *p_flags, int *p_oplock_request, BOOL *p_all_current_opens_are_level_II) { @@ -1469,7 +1468,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, num_share_modes = open_mode_check(conn, fname, dev, inode, access_mask, share_access, create_options, - &flags, &oplock_request, + &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { @@ -1625,7 +1624,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, num_share_modes = open_mode_check(conn, fname, dev, inode, access_mask, share_access, create_options, - &flags, &oplock_request, + &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { -- cgit From 787e526652b2f754ca9441a6fdf8e0745ac4d54a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 15 Jul 2005 19:32:56 +0000 Subject: r8508: Rename EXCLUSIVE_BREAK_SENT to BREAK_TO_NONE_SENT. Volker (This used to be commit 1993e409a53908d299f0b2b0e8e5546236fd580b) --- source3/smbd/oplock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 3cfce5c7a1..2e6789267b 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -276,7 +276,7 @@ BOOL remove_oplock(files_struct *fsp, BOOL break_to_none) return False; } - if (fsp->sent_oplock_break == EXCLUSIVE_BREAK_SENT || break_to_none) { + if (fsp->sent_oplock_break == BREAK_TO_NONE_SENT || break_to_none) { /* * Deal with a reply when a break-to-none was sent. */ @@ -784,7 +784,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, prepare_break_message( outbuf, fsp, using_levelII); /* Remember if we just sent a break to level II on this file. */ - fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; + fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; /* Save the server smb signing state. */ sign_state = srv_oplock_set_signing(False); -- cgit From 3c6e5f6d47dd8c86b9b5d1aaca9d9042c500f511 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 17 Jul 2005 09:56:25 +0000 Subject: r8521: Another micro-step: Don't pass down a flag where not necessary. Volker (This used to be commit 5f51b72ec7abea3588f76d22a8daa434cdf90eb0) --- source3/smbd/oplock.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 2e6789267b..6ee2454fab 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -526,24 +526,22 @@ static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) Function to do the waiting before sending a local break. ****************************************************************************/ -static void wait_before_sending_break(BOOL local_request) +static void wait_before_sending_break(void) { - if(local_request) { - struct timeval cur_tv; - long wait_left = (long)lp_oplock_break_wait_time(); + struct timeval cur_tv; + long wait_left = (long)lp_oplock_break_wait_time(); - if (wait_left == 0) - return; + if (wait_left == 0) + return; - GetTimeOfDay(&cur_tv); + GetTimeOfDay(&cur_tv); - wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) + + wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) + ((cur_tv.tv_usec - smb_last_time.tv_usec)/1000); - if(wait_left > 0) { - wait_left = MIN(wait_left, 1000); - sys_usleep(wait_left * 1000); - } + if(wait_left > 0) { + wait_left = MIN(wait_left, 1000); + sys_usleep(wait_left * 1000); } } @@ -633,7 +631,9 @@ static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) * and has reported to cause problems on NT. JRA. */ - wait_before_sending_break(local_request); + if (local_request) { + wait_before_sending_break(); + } /* Prepare the SMBlockingX message. */ prepare_break_message( outbuf, fsp, False); @@ -770,7 +770,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * and has reported to cause problems on NT. JRA. */ - wait_before_sending_break(local_request); + if (local_request) { + wait_before_sending_break(); + } /* Prepare the SMBlockingX message. */ -- cgit From 411be313dd4bac842c4eeb537a6afa69aaf183d3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 17 Jul 2005 21:01:17 +0000 Subject: r8531: Fix a memleak (This used to be commit ebf0cda797da2c63aa0033f034573f6d5485b57a) --- source3/smbd/close.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 3fc7fdb059..afc645ca06 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -134,6 +134,7 @@ static void notify_deferred_opens(files_struct *fsp) send_deferred_open_retry_message(entry); } } + SAFE_FREE(de_array); } /**************************************************************************** -- cgit From 8ebef3f4c80cbf05dbadf71204c781c28e369ec9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Jul 2005 18:50:13 +0000 Subject: r8545: Fix oplock bug introduced by oplock code "simplification" :-). We *always* reply to an exclusive oplock break message even if we have no record of the oplock (and we always did before 3.0.20pre2). Jeremy. (This used to be commit b1a94aadf25e94dcc168ea3a5ae008f4e84ff296) --- source3/smbd/oplock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 6ee2454fab..de12003986 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -461,12 +461,12 @@ pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", */ DEBUG(3,("process_local_message: oplock break requested with " "no outstanding oplocks. Returning success.\n")); - return True; - } - if (!oplock_break(dev, inode, file_id, False)) { - DEBUG(0,("process_local_message: oplock break failed.\n")); - return False; + } else { + if (!oplock_break(dev, inode, file_id, False)) { + DEBUG(0,("process_local_message: oplock break failed.\n")); + return False; + } } /* -- cgit From 023d2162d90ff62d5a8b1d732c7fd69dac7ebe35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Jul 2005 19:55:55 +0000 Subject: r8547: Code tidyup from Jason Mader . Bugid #2885. Jeremy. (This used to be commit 4d69a682b3ab4f660455e6ea5a2970481a6ccffc) --- source3/smbd/posix_acls.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ab14638a24..2052a98c02 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1060,7 +1060,6 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, BOOL got_grp = False; BOOL got_other = False; canon_ace *pace_other = NULL; - canon_ace *pace_group = NULL; for (pace = *pp_ace; pace; pace = pace->next) { if (pace->type == SMB_ACL_USER_OBJ) { @@ -1078,7 +1077,6 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, if (setting_acl) apply_default_perms(fsp, pace, S_IRGRP); got_grp = True; - pace_group = pace; } else if (pace->type == SMB_ACL_OTHER) { -- cgit From a747f1b87a9e901b5fdf3a46ae50a181280c3c15 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Jul 2005 20:47:38 +0000 Subject: r8552: Warning fix from jason@ncac.gwu.edu. Jeremy. (This used to be commit 8558001b38786b7ff16d90d80d183b0277d74e16) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 602656080e..522d3c0f54 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -472,7 +472,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da } DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name)); - dump_data(10, eal->ea.value.data, eal->ea.value.length); + dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length); return eal; } -- cgit From 01822a7e054ed83fa4961498f530ede615ac7c24 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Jul 2005 22:32:35 +0000 Subject: r8556: Fix bug #2878 - Norton commander not running on OS/2 client - we were not correctly returning the requested open mode. Thanks to alex@infobit.ru for reporting this. Jeremy. (This used to be commit 7ff7211b808e708c00a3b0f57be8d1af3c632bd7) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4ce93222f7..770e15f276 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1352,7 +1352,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, put_dos_date3(outbuf,smb_vwv2,mtime); } SIVAL(outbuf,smb_vwv4,(uint32)size); - SSVAL(outbuf,smb_vwv6,FILE_WAS_OPENED); + SSVAL(outbuf,smb_vwv6,GET_OPENX_MODE(deny_mode)); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); -- cgit From 87801bc387e60d8cac74a6fb59af30bfdcc7850d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Jul 2005 17:38:38 +0000 Subject: r8609: Fix for bugid #2889. I think the problem is that the top 16 bits of the "server state" field must be non-zero. As we're using the 32 bit field as an offset then normally this field will be zero. W2K3 fills this field with a counter enumerating the number of SMBsearch calls on this directory - starting at 1. Add back the 1<<31 bit flag DPTR_MASK to ensure this is non-zero - with better checks on use. Jeremy. (This used to be commit 6415657942c49ea51d4e4f4ee2189c7d70b9c5fa) --- source3/smbd/dir.c | 10 ++++++++-- source3/smbd/reply.c | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 949e31210f..aeada5968f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -641,6 +641,8 @@ BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S Fill the 5 byte server reserved dptr field. ****************************************************************************/ +#define DPTR_MASK ((uint32)(((uint32)1)<<31)) + BOOL dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; @@ -653,8 +655,12 @@ BOOL dptr_fill(char *buf1,unsigned int key) offset = (uint32)TellDir(dptr->dir_hnd); DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, (long)dptr->dir_hnd,(int)offset)); + if (offset != (uint32)-1 && (offset & DPTR_MASK)) { + DEBUG(0,("dptr_fill: Error - offset has bit 32 set. Can't use in server state.\n")); + return False; + } buf[0] = key; - SIVAL(buf,1,offset); + SIVAL(buf,1,offset | DPTR_MASK); return(True); } @@ -678,7 +684,7 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) if (offset == (uint32)-1) { seekoff = -1; } else { - seekoff = (long)offset; + seekoff = (long)(offset & ~DPTR_MASK); } SeekDir(dptr->dir_hnd,seekoff); DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 770e15f276..e96c3dc01f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1156,7 +1156,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size memcpy(p,status,21); make_dir_struct(p,mask,fname,size, mode,date, !allow_long_path_components); - dptr_fill(p+12,dptr_num); + if (!dptr_fill(p+12,dptr_num)) { + break; + } numentries++; p += DIR_STRUCT_SIZE; } -- cgit From 78e3b4f04b424fce1e2a908dac214d00bec493cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Jul 2005 17:44:44 +0000 Subject: r8610: If I'm going to do a debug level zero, at least make it useful. Jeremy. (This used to be commit 99dae22dcf4050b5aacbb2cd4d2a08a183611402) --- source3/smbd/dir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index aeada5968f..4f59205feb 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -656,7 +656,8 @@ BOOL dptr_fill(char *buf1,unsigned int key) DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, (long)dptr->dir_hnd,(int)offset)); if (offset != (uint32)-1 && (offset & DPTR_MASK)) { - DEBUG(0,("dptr_fill: Error - offset has bit 32 set. Can't use in server state.\n")); + DEBUG(0,("dptr_fill: Error - offset 0x%x has bit 32 set. Can't use in server state.\n", + (unsigned int)offset )); return False; } buf[0] = key; -- cgit From 21cd4ee355157737c4dfcf6cc901ed1410baceab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Jul 2005 20:59:52 +0000 Subject: r8615: Added "acl group control". Defaults to off. Docs to follow. Jeremy. (This used to be commit f7b169ed57de81229c3b9089a05f4e73ea39010c) --- source3/smbd/posix_acls.c | 161 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 127 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2052a98c02..a1855b0fa9 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2236,11 +2236,43 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ return NULL; } +/**************************************************************************** + Check if the current user group list contains a given group. +****************************************************************************/ + +static BOOL current_user_in_group(gid_t gid) +{ + int i; + + for (i = 0; i < current_user.ngroups; i++) { + if (current_user.groups[i] == gid) { + return True; + } + } + + return False; +} + +/**************************************************************************** + Should we override a deny ? +****************************************************************************/ + +static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid) +{ + if ((errno == EACCES || errno == EPERM) && + lp_acl_group_control(SNUM(conn)) && + current_user_in_group(prim_gid)) { + return True; + } else { + return False; + } +} + /**************************************************************************** Attempt to apply an ACL to a file or directory. ****************************************************************************/ -static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, BOOL *pacl_set_support) +static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, gid_t prim_gid, BOOL *pacl_set_support) { connection_struct *conn = fsp->conn; BOOL ret = False; @@ -2305,7 +2337,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n", i, strerror(errno) )); - goto done; + goto fail; } if (p_ace->type == SMB_ACL_MASK) { @@ -2331,7 +2363,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n", i, strerror(errno) )); - goto done; + goto fail; } /* @@ -2343,7 +2375,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n", i, strerror(errno) )); - goto done; + goto fail; } } @@ -2354,13 +2386,13 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n", i, strerror(errno) )); - goto done; + goto fail; } if (map_acl_perms_to_permset(conn, p_ace->perms, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n", (unsigned int)p_ace->perms, i, strerror(errno) )); - goto done; + goto fail; } /* @@ -2370,7 +2402,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n", i, strerror(errno) )); - goto done; + goto fail; } if( DEBUGLVL( 10 )) @@ -2381,27 +2413,27 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if (needs_mask && !got_mask_entry) { if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); - goto done; + goto fail; } if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); - goto done; + goto fail; } if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); - goto done; + goto fail; } if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) )); - goto done; + goto fail; } if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); - goto done; + goto fail; } } @@ -2413,7 +2445,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", strerror(errno) )); - goto done; + goto fail; } /* @@ -2430,10 +2462,26 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau *pacl_set_support = False; } - DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", - the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", - fsp->fsp_name, strerror(errno) )); - goto done; + if (acl_group_override(conn, prim_gid)) { + int sret; + + DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", + fsp->fsp_name )); + + become_root(); + sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl); + unbecome_root(); + if (sret == 0) { + ret = True; + } + } + + if (ret == False) { + DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", + the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", + fsp->fsp_name, strerror(errno) )); + goto fail; + } } } else { if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl) == -1) { @@ -2445,18 +2493,35 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau *pacl_set_support = False; } - DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", - fsp->fsp_name, strerror(errno) )); - goto done; + if (acl_group_override(conn, prim_gid)) { + int sret; + + DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", + fsp->fsp_name )); + + become_root(); + sret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl); + unbecome_root(); + if (sret == 0) { + ret = True; + } + } + + if (ret == False) { + DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", + fsp->fsp_name, strerror(errno) )); + goto fail; + } } } ret = True; - done: + fail: - if (the_acl != NULL) - SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); + if (the_acl != NULL) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); + } return ret; } @@ -3127,7 +3192,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if (acl_perms && file_ace_list) { - ret = set_canon_ace_list(fsp, file_ace_list, False, &acl_set_support); + ret = set_canon_ace_list(fsp, file_ace_list, False, sbuf.st_gid, &acl_set_support); if (acl_set_support && ret == False) { DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) )); free_canon_ace_list(file_ace_list); @@ -3138,7 +3203,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if (acl_perms && acl_set_support && fsp->is_directory) { if (dir_ace_list) { - if (!set_canon_ace_list(fsp, dir_ace_list, True, &acl_set_support)) { + if (!set_canon_ace_list(fsp, dir_ace_list, True, sbuf.st_gid, &acl_set_support)) { DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); @@ -3151,17 +3216,32 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) { - DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - return False; + int sret = -1; + + if (acl_group_override(conn, sbuf.st_gid)) { + DEBUG(5,("set_nt_acl: acl group control on and " + "current user in file %s primary group. Override delete_def_acl\n", + fsp->fsp_name )); + + become_root(); + sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name); + unbecome_root(); + } + + if (sret == -1) { + DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } } } } - if (acl_set_support) + if (acl_set_support) { store_inheritance_attributes(fsp, file_ace_list, dir_ace_list, (psd->type & SE_DESC_DACL_PROTECTED) ? True : False); + } /* * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. @@ -3184,11 +3264,24 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) fsp->fsp_name, (unsigned int)posix_perms )); if(SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) { - DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", + int sret = -1; + if (acl_group_override(conn, sbuf.st_gid)) { + DEBUG(5,("set_nt_acl: acl group control on and " + "current user in file %s primary group. Override chmod\n", + fsp->fsp_name )); + + become_root(); + sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms); + unbecome_root(); + } + + if (sret == -1) { + DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); - free_canon_ace_list(file_ace_list); - free_canon_ace_list(dir_ace_list); - return False; + free_canon_ace_list(file_ace_list); + free_canon_ace_list(dir_ace_list); + return False; + } } } } -- cgit From aa63997c2341e565c8a81716ed44bca3d6c27798 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Jul 2005 18:21:38 +0000 Subject: r8655: Still trying to fix #2889. We don't need the DPTR_MASK after all, now thinking it might be to do with flags2... Jeremy. (This used to be commit a3ceabf7c678b5e7f77cc073cf535498ffc67eb6) --- source3/smbd/dir.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 4f59205feb..949e31210f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -641,8 +641,6 @@ BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S Fill the 5 byte server reserved dptr field. ****************************************************************************/ -#define DPTR_MASK ((uint32)(((uint32)1)<<31)) - BOOL dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; @@ -655,13 +653,8 @@ BOOL dptr_fill(char *buf1,unsigned int key) offset = (uint32)TellDir(dptr->dir_hnd); DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, (long)dptr->dir_hnd,(int)offset)); - if (offset != (uint32)-1 && (offset & DPTR_MASK)) { - DEBUG(0,("dptr_fill: Error - offset 0x%x has bit 32 set. Can't use in server state.\n", - (unsigned int)offset )); - return False; - } buf[0] = key; - SIVAL(buf,1,offset | DPTR_MASK); + SIVAL(buf,1,offset); return(True); } @@ -685,7 +678,7 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) if (offset == (uint32)-1) { seekoff = -1; } else { - seekoff = (long)(offset & ~DPTR_MASK); + seekoff = (long)offset; } SeekDir(dptr->dir_hnd,seekoff); DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", -- cgit From 58a3749e9c4393330c1c795b689ffb98c0aae381 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Jul 2005 20:24:21 +0000 Subject: r8689: Fixes bugid #2889 for sure. Turns out the OS/2 dos box doesn't like two offsets to be identical. Make offsets for . and .. different (and explicit). Jeremy. (This used to be commit 217cc66e46b3df35a66fed4055bd5032aab4d73f) --- source3/smbd/dir.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 949e31210f..a0df924dc7 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -26,6 +26,11 @@ extern struct current_user current_user; +/* "Special" directory offsets. */ +#define END_OF_DIRECTORY_OFFSET ((long)-1) +#define START_OF_DIRECTORY_OFFSET ((long)0) +#define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000) + /* Make directory handle internals available. */ #define NAME_CACHE_SIZE 100 @@ -560,7 +565,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT /* If poffset is -1 then we know we returned this name before and we have no wildcards. We're at the end of the directory. */ - if (*poffset == -1) { + if (*poffset == END_OF_DIRECTORY_OFFSET) { return NULL; } @@ -577,7 +582,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT if (VALID_STAT(*pst)) { /* We need to set the underlying dir_hdn offset to -1 also as this function is usually called with the output from TellDir. */ - dptr->dir_hnd->offset = *poffset = -1; + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; return dptr->wcard; } @@ -588,7 +593,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { /* We need to set the underlying dir_hdn offset to -1 also as this function is usually called with the output from TellDir. */ - dptr->dir_hnd->offset = *poffset = -1; + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; return dptr->wcard; } else { /* If we get any other error than ENOENT or ENOTDIR @@ -596,7 +601,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT if (errno != ENOENT && errno != ENOTDIR) { /* We need to set the underlying dir_hdn offset to -1 also as this function is usually called with the output from TellDir. */ - dptr->dir_hnd->offset = *poffset = -1; + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; return dptr->wcard; } } @@ -607,7 +612,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT if (dptr->conn->case_sensitive) { /* We need to set the underlying dir_hdn offset to -1 also as this function is usually called with the output from TellDir. */ - dptr->dir_hnd->offset = *poffset = -1; + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; return NULL; } else { dptr->has_wild = True; @@ -623,9 +628,9 @@ BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S { SET_STAT_INVALID(*pst); - if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) { + if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) { /* This is a singleton directory and we're already at the end. */ - *poffset = -1; + *poffset = END_OF_DIRECTORY_OFFSET; return False; } @@ -676,7 +681,7 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) *num = key; offset = IVAL(buf,1); if (offset == (uint32)-1) { - seekoff = -1; + seekoff = END_OF_DIRECTORY_OFFSET; } else { seekoff = (long)offset; } @@ -1083,10 +1088,12 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) connection_struct *conn = dirp->conn; /* Cheat to allow . and .. to be the first entries returned. */ - if ((*poffset == 0) && (dirp->file_number < 2)) { + if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) { if (dirp->file_number == 0) { n = "."; + *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET; } else { + *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET; n = ".."; } dirp->file_number++; @@ -1113,7 +1120,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) dirp->file_number++; return e->name; } - dirp->offset = -1; + dirp->offset = END_OF_DIRECTORY_OFFSET; return NULL; } @@ -1125,8 +1132,8 @@ void RewindDir(struct smb_Dir *dirp, long *poffset) { SMB_VFS_REWINDDIR(dirp->conn, dirp->dir); dirp->file_number = 0; - dirp->offset = 0; - *poffset = 0; + dirp->offset = START_OF_DIRECTORY_OFFSET; + *poffset = START_OF_DIRECTORY_OFFSET; } /******************************************************************* @@ -1136,7 +1143,7 @@ void RewindDir(struct smb_Dir *dirp, long *poffset) void SeekDir(struct smb_Dir *dirp, long offset) { if (offset != dirp->offset) { - if (offset == 0) { + if (offset == START_OF_DIRECTORY_OFFSET || offset == DOT_DOT_DIRECTORY_OFFSET) { RewindDir(dirp, &offset); } else { SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); @@ -1186,7 +1193,7 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) /* Not found in the name cache. Rewind directory and start from scratch. */ SMB_VFS_REWINDDIR(conn, dirp->dir); dirp->file_number = 0; - *poffset = 0; + *poffset = START_OF_DIRECTORY_OFFSET; while ((entry = ReadDirName(dirp, poffset))) { if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { return True; -- cgit From d6973499de8d70662178e9b558a3f5d2c70f203d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Jul 2005 01:14:09 +0000 Subject: r8695: Patch from James Peach for hires timestamps and efficient notify code. Bugid #2285. The last commit by me on behalf of James as he will be able to do his own now :-). Jeremy. (This used to be commit 524298b3f32f478e3750d805c5dc3b8fbe40d8d2) --- source3/smbd/notify_hash.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 08eefab652..ee7d4314ee 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -23,14 +23,28 @@ struct change_data { time_t last_check_time; /* time we last checked this entry */ +#ifdef HAVE_STAT_HIRES_TIMESTAMPS + struct timespec modify_time; + struct timespec status_time; +#else time_t modify_time; /* Info from the directory we're monitoring. */ time_t status_time; /* Info from the directory we're monitoring. */ +#endif time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ unsigned int num_entries; /* Zero or the number of files in the directory. */ unsigned int mode_sum; unsigned char name_hash[16]; }; + +#ifdef HAVE_STAT_HIRES_TIMESTAMPS +/* Compare struct timespec. */ +#define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec)) +#else +/* Compare time_t . */ +#define TIMESTAMP_NEQ(x, y) ((x) != (y)) +#endif + /**************************************************************************** Create the hash we will use to determine if the contents changed. *****************************************************************************/ @@ -52,20 +66,36 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, if(SMB_VFS_STAT(conn,path, &st) == -1) return False; +#ifdef HAVE_STAT_HIRES_TIMESTAMPS + data->modify_time = st.st_mtim; + data->status_time = st.st_ctim; +#else data->modify_time = st.st_mtime; data->status_time = st.st_ctime; +#endif if (old_data) { /* * Shortcut to avoid directory scan if the time * has changed - we always must return true then. */ - if (old_data->modify_time != data->modify_time || - old_data->status_time != data->status_time ) { + if (TIMESTAMP_NEQ(old_data->modify_time, data->modify_time) || + TIMESTAMP_NEQ(old_data->status_time, data->status_time) ) { return True; } } + if (S_ISDIR(st.st_mode) && + (flags & ~(FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME)) == 0) + { + /* This is the case of a client wanting to know only when + * the contents of a directory changes. Since any file + * creation, rename or deletion will update the directory + * timestamps, we don't need to create a hash. + */ + return True; + } + /* * If we are to watch for changes that are only stored * in inodes of files, not in the directory inode, we must @@ -176,8 +206,8 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, } if (!notify_hash(conn, path, flags, &data2, data) || - data2.modify_time != data->modify_time || - data2.status_time != data->status_time || + TIMESTAMP_NEQ(data2.modify_time, data->modify_time) || + TIMESTAMP_NEQ(data2.status_time, data->status_time) || data2.total_time != data->total_time || data2.num_entries != data->num_entries || data2.mode_sum != data->mode_sum || -- cgit From 9365669a5988ea67764e051d626f664daf6596eb Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 22 Jul 2005 03:35:28 +0000 Subject: r8697: BUG 2908: make sure to allow for the trailing NULL (This used to be commit 3b505a824365222352be6a5ad2fb26586415a7a3) --- source3/smbd/msdfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index fffe44ab60..d0438b01af 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -251,8 +251,7 @@ BOOL is_msdfs_link(connection_struct* conn, char * path, if (S_ISLNK(sbufp->st_mode)) { /* open the link and read it */ - referral_len = SMB_VFS_READLINK(conn, path, referral, - sizeof(pstring)); + referral_len = SMB_VFS_READLINK(conn, path, referral, sizeof(pstring)-1); if (referral_len == -1) { DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno))); return False; -- cgit From a344155b8d89869fa82594868b9a6952f53d9631 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Jul 2005 17:58:53 +0000 Subject: r8782: Fix bug #2918. The problem was using Inbuffer to push a deferred open message onto the queue when we're in a chained message set - we're actually processing a different buffer then. Added current_inbuf as a static inside smbd/process.c to ensure the correct message gets pushed and processed. Jeremy. (This used to be commit ccef7581717bff6145ffc386d5be24d6f42634cb) --- source3/smbd/process.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 94d4b8d903..897bd56ba7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -29,6 +29,7 @@ struct timeval smb_last_time; static char *InBuffer = NULL; static char *OutBuffer = NULL; +static char *current_inbuf = NULL; /* * Size of data we can send to client. Set @@ -245,12 +246,12 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) /**************************************************************************** Function to push a sharing violation open smb message onto a linked list of local smb messages ready - for processing. + for processing. We must use current_inbuf here not Inbuf in case we're in a chained message set. ****************************************************************************/ BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private_data, size_t priv_len) { - uint16 mid = SVAL(InBuffer,smb_mid); + uint16 mid = SVAL(current_inbuf,smb_mid); struct timeval tv; SMB_BIG_INT tdif; @@ -270,11 +271,11 @@ BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private_ tv.tv_usec = tdif % 1000000; DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\ - timeout time [%u.%06u]\n", (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid, + timeout time [%u.%06u]\n", (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec)); - return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer, - smb_len(InBuffer)+4, &tv, private_data, priv_len); + return push_queued_message(SHARE_VIOLATION_QUEUE, current_inbuf, + smb_len(current_inbuf)+4, &tv, private_data, priv_len); } /**************************************************************************** @@ -986,6 +987,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) return(ERROR_DOS(ERRSRV,ERRaccess)); + current_inbuf = inbuf; /* In case we need to defer this message in open... */ outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); } -- cgit From 880d62843afd52c2e4bdf66e9e8218823445e109 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 27 Jul 2005 16:10:50 +0000 Subject: r8798: Save one system call per SMB. smb_run_idle_events right now is only used to close idle pdb_ldap connections, and from my point of view this can wait until normal timeout handling, this does not need to be done per client request. Volker (This used to be commit 404b817d7294fbea64f0fca019406c5c7458e386) --- source3/smbd/process.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 897bd56ba7..19add7e095 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1633,10 +1633,6 @@ void smbd_process(void) lp_talloc_free(); main_loop_talloc_free(); - /* run all registered idle events */ - smb_run_idle_events(time(NULL)); - - /* Did someone ask for immediate checks on things like blocking locks ? */ if (select_timeout == 0) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) -- cgit From a3947eaa4eb32c40e983993d17178bb9d9b5f151 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 2 Aug 2005 06:36:42 +0000 Subject: r8912: Samba 3.0 was failing from a Vista client, because it was using 'raw' NTLMSSP (not wrapped in SPNEGO). We really should have supported this anyway, but we got away with it for a while... Andrew Bartlett (This used to be commit 78f0640a4b4af8b40c0af251fd06edd97feaf1be) --- source3/smbd/sesssetup.c | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8586ac1324..6a414acc4c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -353,7 +353,8 @@ static int reply_spnego_kerberos(connection_struct *conn, static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, - DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) + DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, + BOOL wrap) { BOOL ret; DATA_BLOB response; @@ -406,9 +407,16 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out } } - response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP); + if (wrap) { + response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP); + } else { + response = *ntlmssp_blob; + } + ret = reply_sesssetup_blob(conn, outbuf, response, nt_status); - data_blob_free(&response); + if (wrap) { + data_blob_free(&response); + } /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us, and the other end, that we are not finished yet. */ @@ -504,8 +512,8 @@ static int reply_spnego_negotiate(connection_struct *conn, data_blob_free(&secblob); reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, - &chal, nt_status); - + &chal, nt_status, True); + data_blob_free(&chal); /* already replied */ @@ -550,7 +558,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, - &auth_reply, nt_status); + &auth_reply, nt_status, True); data_blob_free(&auth_reply); @@ -652,6 +660,31 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, return ret; } + if (strncmp(blob1.data, "NTLMSSP", 7) == 0) { + DATA_BLOB chal; + NTSTATUS nt_status; + if (!vuser->auth_ntlmssp_state) { + nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(nt_status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + + return ERROR_NT(nt_status); + } + } + + nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state, + blob1, &chal); + + data_blob_free(&blob1); + + reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, + &vuser->auth_ntlmssp_state, + &chal, nt_status, False); + data_blob_free(&blob1); + return -1; + } + /* what sort of packet is this? */ DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n")); -- cgit From f31965b549d5def6d0b25ece6b1ff721fc66bcab Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 2 Aug 2005 07:07:43 +0000 Subject: r8913: Fix memory leak in -r 8912: Free the right thing, rather than blob1 'twice'. Andrew Bartlett (This used to be commit 7adeba4036d9d83a10d8944c81ea3fab0267db21) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 6a414acc4c..bf7287aab9 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -681,7 +681,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, &vuser->auth_ntlmssp_state, &chal, nt_status, False); - data_blob_free(&blob1); + data_blob_free(&chal); return -1; } -- cgit From dada62cf82f82c8a7eec053e2b0d29ec32293160 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 20:50:16 +0000 Subject: r8948: Fix valgrind bad free bug found by Gunther. Jeremy. (This used to be commit ff291f4c97b76fb3e9b71a07752ca68c23011273) --- source3/smbd/msdfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index d0438b01af..e66c13ab93 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -128,10 +128,14 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) { + pstring connpath; + ZERO_STRUCTP(conn); conn->service = snum; - conn->connectpath = path; - pstring_sub(conn->connectpath , "%S", lp_servicename(snum)); + pstrcpy(connpath, path); + pstring_sub(connpath , "%S", lp_servicename(snum)); + + string_set(&conn->connectpath, connpath); /* needed for smbd_vfs_init() */ -- cgit From a4cdedcc085e0b9a94e6757a9b427af503ad6593 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 20:59:20 +0000 Subject: r8950: Fix one more mem leak found by Gunther. Jeremy. (This used to be commit 547c6ee0a965b425719cdb834dd5d68a3a3e7117) --- source3/smbd/msdfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e66c13ab93..0f63966a7d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -948,7 +948,7 @@ BOOL remove_msdfs_link(struct junction_map* jucn) return ret; } -static int form_junctions(int snum, struct junction_map* jucn, int jn_remain) +static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, int jn_remain) { int cnt = 0; DIR *dirp; @@ -981,7 +981,7 @@ static int form_junctions(int snum, struct junction_map* jucn, int jn_remain) jucn[cnt].volume_name[0] = '\0'; jucn[cnt].referral_count = 1; - ref = jucn[cnt].referral_list = SMB_MALLOC_P(struct referral); + ref = jucn[cnt].referral_list = TALLOC_P(ctx, struct referral); if (jucn[cnt].referral_list == NULL) { DEBUG(0, ("Malloc failed!\n")); goto out; @@ -1023,7 +1023,7 @@ out: return cnt; } -int enum_msdfs_links(struct junction_map* jucn, int jn_max) +int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map* jucn, int jn_max) { int i=0; int jn_count = 0; @@ -1033,7 +1033,7 @@ int enum_msdfs_links(struct junction_map* jucn, int jn_max) for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) { if(lp_msdfs_root(i)) - jn_count += form_junctions(i,jucn,jn_max - jn_count); + jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); } return jn_count; } -- cgit From abb81cfe2688dec69fe154d3abff8eff388c779c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 23:24:32 +0000 Subject: r8959: Make msdfs code talloc based. Fix leaks. Jeremy. (This used to be commit 076023df8ea7c0f03baf8102e55d347e05542c7b) --- source3/smbd/msdfs.c | 329 ++++++++++++++++++++++++++++++-------------------- source3/smbd/trans2.c | 2 +- 2 files changed, 196 insertions(+), 135 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 0f63966a7d..ade167f3c5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -30,10 +30,10 @@ extern uint32 global_client_caps; into the dfs_path structure **********************************************************************/ -static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) +static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp) { pstring pathname_local; - char* p,*temp; + char *p, *temp; pstrcpy(pathname_local,pathname); p = temp = pathname_local; @@ -46,8 +46,9 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) /* now tokenize */ /* parse out hostname */ p = strchr_m(temp,'\\'); - if(p == NULL) + if(p == NULL) { return False; + } *p = '\0'; pstrcpy(pdp->hostname,temp); DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); @@ -76,10 +77,10 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) into the dfs_path structure **********************************************************************/ -static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL allow_wcards) +static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) { pstring pathname_local; - char* p,*temp; + char *p,*temp; pstrcpy(pathname_local,pathname); p = temp = pathname_local; @@ -92,8 +93,9 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL /* now tokenize */ /* parse out hostname */ p = strchr_m(temp,'/'); - if(p == NULL) + if(p == NULL) { return False; + } *p = '\0'; pstrcpy(pdp->hostname,temp); DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname)); @@ -126,7 +128,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL Note this CHANGES CWD !!!! JRA. *********************************************************/ -static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) +static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) { pstring connpath; @@ -165,41 +167,48 @@ static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) return True; } - /********************************************************************** Parse the contents of a symlink to verify if it is an msdfs referral A valid referral is of the form: msdfs:server1\share1,server2\share2 + talloc CTX can be NULL here if preflist and refcount pointers are null. **********************************************************************/ -static BOOL parse_symlink(char* buf,struct referral** preflist, - int* refcount) +static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist, int *refcount) { pstring temp; - char* prot; - char* alt_path[MAX_REFERRAL_COUNT]; - int count=0, i; - struct referral* reflist; + char *prot; + char *alt_path[MAX_REFERRAL_COUNT]; + int count = 0, i; + struct referral *reflist; pstrcpy(temp,buf); prot = strtok(temp,":"); - if (!strequal(prot, "msdfs")) + if (!strequal(prot, "msdfs")) { return False; + } /* No referral list requested. Just yes/no. */ - if (!preflist) + if (!preflist) { return True; + } + + if (!ctx) { + DEBUG(0,("parse_symlink: logic error. TALLOC_CTX should not be null.\n")); + return True; + } /* parse out the alternate paths */ - while(((alt_path[count] = strtok(NULL,",")) != NULL) && count %s\n",path,referral)); - if (parse_symlink(referral, reflistp, refcnt)) + if (parse_symlink(ctx, referral, reflistp, refcnt)) { return True; + } } return False; } @@ -282,13 +296,15 @@ they request referrals for dfs roots on a server. consumedcntp: how much of the dfs path is being redirected. the client should try the remaining path on the redirected server. - + +TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp +are also NULL. *****************************************************************/ -static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, - connection_struct* conn, BOOL search_flag, - struct referral** reflistpp, int* refcntp, - BOOL* self_referralp, int* consumedcntp) +static BOOL resolve_dfs_path(TALLOC_CTX *ctx, pstring dfspath, struct dfs_path *dp, + connection_struct *conn, BOOL search_flag, + struct referral **reflistpp, int *refcntp, + BOOL *self_referralp, int *consumedcntp) { pstring localpath; int consumed_level = 1; @@ -302,6 +318,10 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, return False; } + if (!ctx && (reflistpp || refcntp)) { + DEBUG(0,("resolve_dfs_path: logic error. TALLOC_CTX must not be NULL.\n")); + } + if (dp->reqpath[0] == '\0') { if (self_referralp) { DEBUG(6,("resolve_dfs_path: self-referral. returning False\n")); @@ -317,16 +337,17 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, pstrcpy(localpath, dp->reqpath); /* check if need to redirect */ - if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { if ( search_flag ) { DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); return False; } - + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); - if (consumedcntp) + if (consumedcntp) { *consumedcntp = strlen(dfspath); + } return True; } @@ -336,8 +357,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, while (p) { *p = '\0'; pstrcpy(localpath, reqpath); - if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { - + if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); /* To find the path consumed, we truncate the original @@ -353,8 +373,9 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, trim_char(buf, '\0', '\\'); for (; consumed_level; consumed_level--) { q = strrchr_m(buf, '\\'); - if (q) + if (q) { *q = 0; + } } *consumedcntp = strlen(buf); DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp)); @@ -365,7 +386,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, p = strrchr_m(reqpath, '/'); consumed_level++; } - + return False; } @@ -378,12 +399,13 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, for details. *****************************************************************/ -BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_flag ) +BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_flag ) { struct dfs_path dp; - if (!conn || !pathname) + if (!conn || !pathname) { return False; + } parse_processed_dfs_path(pathname, &dp, search_wcard_flag); @@ -394,10 +416,11 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_ return False; } - if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) + if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) { return False; + } - if (resolve_dfs_path(pathname, &dp, conn, search_wcard_flag, + if (resolve_dfs_path(NULL, pathname, &dp, conn, search_wcard_flag, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -406,8 +429,7 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_ /* Form non-dfs tcon-relative path */ pstrcpy(pathname, dp.reqpath); - DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", - pathname)); + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname)); return False; } @@ -418,16 +440,17 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_ Return a self referral. **********************************************************************/ -static BOOL self_ref(char *pathname, struct junction_map *jucn, +static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct referral *ref; - if (self_referralp != NULL) + if (self_referralp != NULL) { *self_referralp = True; + } jucn->referral_count = 1; - if((ref = SMB_MALLOC_P(struct referral)) == NULL) { + if((ref = TALLOC_P(ctx, struct referral)) == NULL) { DEBUG(0,("self_ref: malloc failed for referral\n")); return False; } @@ -436,18 +459,19 @@ static BOOL self_ref(char *pathname, struct junction_map *jucn, ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) + if (consumedcntp) { *consumedcntp = strlen(pathname); + } return True; } /********************************************************************** Gets valid referrals for a dfs path and fills up the - junction_map structure + junction_map structure. **********************************************************************/ -BOOL get_referred_path(char *pathname, struct junction_map *jucn, +BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct dfs_path dp; @@ -459,15 +483,17 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, BOOL ret = False; BOOL self_referral = False; - if (!pathname || !jucn) + if (!pathname || !jucn) { return False; + } ZERO_STRUCT(conns); - if (self_referralp) + if (self_referralp) { *self_referralp = False; - else + } else { self_referralp = &self_referral; + } parse_dfs_path(pathname, &dp); @@ -487,8 +513,9 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, /* Verify the share is a dfs root */ snum = lp_servicenumber(jucn->service_name); if(snum < 0) { - if ((snum = find_service(jucn->service_name)) < 0) + if ((snum = find_service(jucn->service_name)) < 0) { return False; + } } if (!lp_msdfs_root(snum)) { @@ -508,34 +535,37 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, struct referral* ref; - if (*lp_msdfs_proxy(snum) == '\0') - return self_ref(pathname, jucn, consumedcntp, - self_referralp); + if (*lp_msdfs_proxy(snum) == '\0') { + return self_ref(ctx, pathname, jucn, consumedcntp, self_referralp); + } jucn->referral_count = 1; - if ((ref = SMB_MALLOC_P(struct referral)) == NULL) { + if ((ref = TALLOC_P(ctx, struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); goto out; } pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); - if (dp.reqpath[0] != '\0') + if (dp.reqpath[0] != '\0') { pstrcat(ref->alternate_path, dp.reqpath); + } ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) + if (consumedcntp) { *consumedcntp = strlen(pathname); + } ret = True; goto out; } pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) + if (!create_conn_struct(conn, snum, conn_path)) { return False; + } /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(pathname, &dp, conn, False, + if (!resolve_dfs_path(ctx, pathname, &dp, conn, False, &jucn->referral_list, &jucn->referral_count, self_referralp, consumedcntp)) { if (!*self_referralp) { @@ -546,7 +576,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, /* if self_referral, fill up the junction map */ if (*self_referralp) { - if (self_ref(pathname, jucn, consumedcntp, self_referralp) == False) { + if (self_ref(ctx, pathname, jucn, consumedcntp, self_referralp) == False) { goto out; } } @@ -554,14 +584,16 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, ret = True; out: - if (conn->mem_ctx) + + if (conn->mem_ctx) { talloc_destroy( conn->mem_ctx ); + } return ret; } -static int setup_ver2_dfs_referral(char* pathname, char** ppdata, - struct junction_map* junction, +static int setup_ver2_dfs_referral(char *pathname, char **ppdata, + struct junction_map *junction, int consumedcnt, BOOL self_referral) { @@ -611,8 +643,9 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; - } else + } else { *ppdata = pdata; + } /* copy in the dfs requested paths.. required for offset calculations */ memcpy(pdata+uni_reqpathoffset1,uni_requestedpath,requestedpathlen); @@ -621,10 +654,11 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, /* create the header */ SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ SSVAL(pdata,2,junction->referral_count); /* number of referral in this pkt */ - if(self_referral) + if(self_referral) { SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); - else + } else { SIVAL(pdata,4,DFSREF_STORAGE_SERVER); + } offset = 8; /* add the referral elements */ @@ -634,10 +668,11 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, SSVAL(pdata,offset,2); /* version 2 */ SSVAL(pdata,offset+2,VERSION2_REFERRAL_SIZE); - if(self_referral) + if(self_referral) { SSVAL(pdata,offset+4,1); - else + } else { SSVAL(pdata,offset+4,0); + } SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ SIVAL(pdata,offset+8,ref->proximity); SIVAL(pdata,offset+12,ref->ttl); @@ -658,8 +693,8 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, return reply_size; } -static int setup_ver3_dfs_referral(char* pathname, char** ppdata, - struct junction_map* junction, +static int setup_ver3_dfs_referral(char *pathname, char **ppdata, + struct junction_map *junction, int consumedcnt, BOOL self_referral) { @@ -694,16 +729,18 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; - } else + } else { *ppdata = pdata; + } /* create the header */ SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ SSVAL(pdata,2,junction->referral_count); /* number of referral */ - if(self_referral) + if(self_referral) { SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); - else + } else { SIVAL(pdata,4,DFSREF_STORAGE_SERVER); + } /* copy in the reqpaths */ memcpy(pdata+uni_reqpathoffset1,uni_reqpath,reqpathlen); @@ -716,10 +753,11 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, SSVAL(pdata,offset,3); /* version 3 */ SSVAL(pdata,offset+2,VERSION3_REFERRAL_SIZE); - if(self_referral) + if(self_referral) { SSVAL(pdata,offset+4,1); - else + } else { SSVAL(pdata,offset+4,0); + } SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ SIVAL(pdata,offset+8,ref->ttl); @@ -740,10 +778,10 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, } /****************************************************************** - * Set up the Dfs referral for the dfs pathname - ******************************************************************/ + Set up the Dfs referral for the dfs pathname +******************************************************************/ -int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char** ppdata) +int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char **ppdata) { struct junction_map junction; int consumedcnt; @@ -751,23 +789,32 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref pstring buf; int reply_size = 0; char *pathnamep = pathname; + TALLOC_CTX *ctx; + + if (!(ctx=talloc_init("setup_dfs_referral"))) { + return -1; + } ZERO_STRUCT(junction); /* get the junction entry */ - if (!pathnamep) + if (!pathnamep) { + talloc_destroy(ctx); return -1; + } /* Trim pathname sent by client so it begins with only one backslash. Two backslashes confuse some dfs clients */ - while (pathnamep[0] == '\\' && pathnamep[1] == '\\') + while (pathnamep[0] == '\\' && pathnamep[1] == '\\') { pathnamep++; + } pstrcpy(buf, pathnamep); /* The following call can change cwd. */ - if (!get_referred_path(buf, &junction, &consumedcnt, &self_referral)) { + if (!get_referred_path(ctx, buf, &junction, &consumedcnt, &self_referral)) { vfs_ChDir(orig_conn,orig_conn->connectpath); + talloc_destroy(ctx); return -1; } vfs_ChDir(orig_conn,orig_conn->connectpath); @@ -786,30 +833,31 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref /* create the referral depeding on version */ DEBUG(10,("max_referral_level :%d\n",max_referral_level)); - if(max_referral_level<2 || max_referral_level>3) + if(max_referral_level<2 || max_referral_level>3) { max_referral_level = 2; + } switch(max_referral_level) { case 2: reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, &junction, consumedcnt, self_referral); - SAFE_FREE(junction.referral_list); break; case 3: reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, &junction, consumedcnt, self_referral); - SAFE_FREE(junction.referral_list); break; default: DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); + talloc_destroy(ctx); return -1; } if (DEBUGLVL(10)) { - DEBUGADD(0,("DFS Referral pdata:\n")); - dump_data(0,*ppdata,reply_size); + DEBUGADD(0,("DFS Referral pdata:\n")); + dump_data(0,*ppdata,reply_size); } + talloc_destroy(ctx); return reply_size; } @@ -817,11 +865,11 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref The following functions are called by the NETDFS RPC pipe functions **********************************************************************/ -/********************************************************************** +/********************************************************************* Creates a junction structure from a Dfs pathname - **********************************************************************/ +**********************************************************************/ -BOOL create_junction(char* pathname, struct junction_map* jucn) +BOOL create_junction(char *pathname, struct junction_map *jucn) { struct dfs_path dp; @@ -829,51 +877,52 @@ BOOL create_junction(char* pathname, struct junction_map* jucn) /* check if path is dfs : validate first token */ if ( !strequal(get_local_machine_name(),dp.hostname) ) { - - /* Hostname mismatch, check if one of our IP addresses */ - if (!ismyip(*interpret_addr2(dp.hostname))) { - DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", - dp.hostname, pathname)); - return False; - } - } + /* Hostname mismatch, check if one of our IP addresses */ + if (!ismyip(*interpret_addr2(dp.hostname))) { + DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", + dp.hostname, pathname)); + return False; + } + } - /* Check for a non-DFS share */ - if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { - DEBUG(4,("create_junction: %s is not an msdfs root.\n", - dp.servicename)); - return False; - } + /* Check for a non-DFS share */ + if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { + DEBUG(4,("create_junction: %s is not an msdfs root.\n", dp.servicename)); + return False; + } - pstrcpy(jucn->service_name,dp.servicename); - pstrcpy(jucn->volume_name,dp.reqpath); - return True; + pstrcpy(jucn->service_name,dp.servicename); + pstrcpy(jucn->volume_name,dp.reqpath); + return True; } /********************************************************************** Forms a valid Unix pathname from the junction **********************************************************************/ -static BOOL junction_to_local_path(struct junction_map* jucn, char* path, +static BOOL junction_to_local_path(struct junction_map *jucn, char *path, int max_pathlen, connection_struct *conn) { int snum; pstring conn_path; - if(!path || !jucn) + if(!path || !jucn) { return False; + } snum = lp_servicenumber(jucn->service_name); - if(snum < 0) + if(snum < 0) { return False; + } safe_strcpy(path, lp_pathname(snum), max_pathlen-1); safe_strcat(path, "/", max_pathlen-1); safe_strcat(path, jucn->volume_name, max_pathlen-1); pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) + if (!create_conn_struct(conn, snum, conn_path)) { return False; + } return True; } @@ -888,8 +937,9 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) BOOL insert_comma = False; BOOL ret = False; - if(!junction_to_local_path(jucn, path, sizeof(path), conn)) + if(!junction_to_local_path(jucn, path, sizeof(path), conn)) { return False; + } /* form the msdfs_link contents */ pstrcpy(msdfs_link, "msdfs:"); @@ -898,24 +948,28 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) trim_char(refpath, '\\', '\\'); if(*refpath == '\0') { - if (i == 0) + if (i == 0) { insert_comma = False; + } continue; } - if (i > 0 && insert_comma) + if (i > 0 && insert_comma) { pstrcat(msdfs_link, ","); + } pstrcat(msdfs_link, refpath); - if (!insert_comma) + if (!insert_comma) { insert_comma = True; - + } } DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); - if(exists) - if(SMB_VFS_UNLINK(conn,path)!=0) + if(exists) { + if(SMB_VFS_UNLINK(conn,path)!=0) { goto out; + } + } if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n", @@ -931,7 +985,7 @@ out: return ret; } -BOOL remove_msdfs_link(struct junction_map* jucn) +BOOL remove_msdfs_link(struct junction_map *jucn) { pstring path; connection_struct conns; @@ -939,16 +993,16 @@ BOOL remove_msdfs_link(struct junction_map* jucn) BOOL ret = False; if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { - if( SMB_VFS_UNLINK(conn, path) == 0 ) + if( SMB_VFS_UNLINK(conn, path) == 0 ) { ret = True; - + } talloc_destroy( conn->mem_ctx ); } - + return ret; } -static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, int jn_remain) +static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain) { int cnt = 0; DIR *dirp; @@ -958,20 +1012,23 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, connection_struct conn; struct referral *ref = NULL; - if (jn_remain <= 0) - return(0); + if (jn_remain <= 0) { + return 0; + } pstrcpy(connect_path,lp_pathname(snum)); - if(*connect_path == '\0') + if(*connect_path == '\0') { return 0; + } /* * Fake up a connection struct for the VFS layer. */ - if (!create_conn_struct(&conn, snum, connect_path)) + if (!create_conn_struct(&conn, snum, connect_path)) { return 0; + } /* form a junction for the msdfs root - convention DO NOT REMOVE THIS: NT clients will not work with us @@ -1000,8 +1057,9 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, /* Now enumerate all dfs links */ dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); - if(!dirp) + if(!dirp) { goto out; + } while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { if (cnt >= jn_remain) { @@ -1009,8 +1067,8 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, DEBUG(2, ("ran out of MSDFS junction slots")); goto out; } - if (is_msdfs_link(&conn, dname, &(jucn[cnt].referral_list), - &(jucn[cnt].referral_count), NULL)) { + if (is_msdfs_link(ctx, &conn, dname, &jucn[cnt].referral_list, + &jucn[cnt].referral_count, NULL)) { pstrcpy(jucn[cnt].service_name, service_name); pstrcpy(jucn[cnt].volume_name, dname); cnt++; @@ -1018,22 +1076,25 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, } SMB_VFS_CLOSEDIR(&conn,dirp); + out: conn_free(&conn); return cnt; } -int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map* jucn, int jn_max) +int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) { int i=0; int jn_count = 0; - if(!lp_host_msdfs()) + if(!lp_host_msdfs()) { return 0; + } for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) { - if(lp_msdfs_root(i)) + if(lp_msdfs_root(i)) { jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); + } } return jn_count; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 522d3c0f54..e1462c0103 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1122,7 +1122,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - is_msdfs_link(conn, pathreal, NULL, NULL, + is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) { DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal)); -- cgit From 78d6fa7277fadc77d80c400d3a38114a9e296d12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 23:55:38 +0000 Subject: r8963: Clean up the horrid "fake conn struct" part of MSDFS. Jeremy. (This used to be commit 14dd5ab632ff9abb9582e6484187c6ee1573cdd6) --- source3/smbd/conn.c | 22 +++++++++++++++------- source3/smbd/msdfs.c | 30 +++++++++++++++++++----------- 2 files changed, 34 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 534a3367d4..b69868ecec 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -225,10 +225,10 @@ void conn_clear_vuid_cache(uint16 vuid) } /**************************************************************************** - Free a conn structure. + Free a conn structure - internal part. ****************************************************************************/ -void conn_free(connection_struct *conn) +void conn_free_internal(connection_struct *conn) { vfs_handle_struct *handle = NULL, *thandle = NULL; TALLOC_CTX *mem_ctx = NULL; @@ -243,8 +243,6 @@ void conn_free(connection_struct *conn) handle = thandle; } - DLIST_REMOVE(Connections, conn); - if (conn->ngroups && conn->groups) { SAFE_FREE(conn->groups); conn->ngroups = 0; @@ -264,15 +262,25 @@ void conn_free(connection_struct *conn) string_free(&conn->connectpath); string_free(&conn->origpath); - bitmap_clear(bmap, conn->cnum); - num_open--; - mem_ctx = conn->mem_ctx; ZERO_STRUCTP(conn); talloc_destroy(mem_ctx); } +/**************************************************************************** + Free a conn structure. +****************************************************************************/ + +void conn_free(connection_struct *conn) +{ + DLIST_REMOVE(Connections, conn); + bitmap_clear(bmap, conn->cnum); + num_open--; + + conn_free_internal(conn); +} + /**************************************************************************** receive a smbcontrol message to forcibly unmount a share the message contains just a share name and all instances of that diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index ade167f3c5..2b13e2a4b5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -133,12 +133,11 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) pstring connpath; ZERO_STRUCTP(conn); + conn->service = snum; pstrcpy(connpath, path); pstring_sub(connpath , "%S", lp_servicename(snum)); - string_set(&conn->connectpath, connpath); - /* needed for smbd_vfs_init() */ if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) { @@ -146,9 +145,11 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) return False; } + string_set(&conn->connectpath, connpath); + if (!smbd_vfs_init(conn)) { DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); - talloc_destroy( conn->mem_ctx ); + conn_free_internal(conn); return False; } @@ -161,9 +162,10 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", conn->connectpath, strerror(errno) )); - talloc_destroy( conn->mem_ctx ); + conn_free_internal(conn); return False; } + return True; } @@ -477,7 +479,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *juc struct dfs_path dp; struct connection_struct conns; - struct connection_struct* conn = &conns; + struct connection_struct *conn = &conns; pstring conn_path; int snum; BOOL ret = False; @@ -585,10 +587,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *juc out: - if (conn->mem_ctx) { - talloc_destroy( conn->mem_ctx ); - } - + conn_free_internal(conn); return ret; } @@ -937,6 +936,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) BOOL insert_comma = False; BOOL ret = False; + ZERO_STRUCT(conns); + if(!junction_to_local_path(jucn, path, sizeof(path), conn)) { return False; } @@ -981,7 +982,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) ret = True; out: - talloc_destroy( conn->mem_ctx ); + + conn_free_internal(conn); return ret; } @@ -992,6 +994,8 @@ BOOL remove_msdfs_link(struct junction_map *jucn) connection_struct *conn = &conns; BOOL ret = False; + ZERO_STRUCT(conns); + if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { if( SMB_VFS_UNLINK(conn, path) == 0 ) { ret = True; @@ -999,6 +1003,7 @@ BOOL remove_msdfs_link(struct junction_map *jucn) talloc_destroy( conn->mem_ctx ); } + conn_free_internal(conn); return ret; } @@ -1012,6 +1017,8 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, connection_struct conn; struct referral *ref = NULL; + ZERO_STRUCT(conn); + if (jn_remain <= 0) { return 0; } @@ -1078,7 +1085,8 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, SMB_VFS_CLOSEDIR(&conn,dirp); out: - conn_free(&conn); + + conn_free_internal(&conn); return cnt; } -- cgit From 3dae794632f48ae163d1195fef19c14e67f341cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Aug 2005 17:10:10 +0000 Subject: r9126: Fix valgrind bug Volker found in interaction with new aio buffer flipping and oplocks. Jeremy. (This used to be commit a18c5ff3eada93e46da3f7cbd326b8dceb72e147) --- source3/smbd/oplock.c | 12 +++++++----- source3/smbd/process.c | 4 ++++ 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index de12003986..c0c9e989a9 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -757,8 +757,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, if((outbuf = NewOutBuffer(&saved_outbuf))==NULL) { DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - set_InBuffer(saved_inbuf); + /* Free must be done before set.. */ free_InBuffer(inbuf); + set_InBuffer(saved_inbuf); return False; } @@ -918,14 +919,15 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Restore the chain fnum. */ file_chain_restore(); - /* Restore the global In/Out buffers. */ - set_InBuffer(saved_inbuf); - set_OutBuffer(saved_outbuf); - /* Free the buffers we've been using to recurse. */ + /* Free must be done before set.. */ free_InBuffer(inbuf); free_OutBuffer(outbuf); + /* Restore the global In/Out buffers. */ + set_InBuffer(saved_inbuf); + set_OutBuffer(saved_outbuf); + /* We need this in case a readraw crossed on the wire. */ if(global_oplock_break) global_oplock_break = False; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 19add7e095..1deb4da269 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1527,6 +1527,7 @@ char *get_InBuffer(void) void set_InBuffer(char *new_inbuf) { InBuffer = new_inbuf; + current_inbuf = InBuffer; } char *get_OutBuffer(void) @@ -1547,6 +1548,9 @@ void set_OutBuffer(char *new_outbuf) void free_InBuffer(char *inbuf) { if (!aio_inbuffer_in_use(inbuf)) { + if (current_inbuf == inbuf) { + current_inbuf = NULL; + } SAFE_FREE(inbuf); } } -- cgit From e14c6d62d8093a1b44f37f75881033616ab92c55 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Aug 2005 22:45:57 +0000 Subject: r9246: Patch from Marcel samba.10.maazl@spamgourmet.com for OS/2 trans2 open reply bugs. Jeremy. (This used to be commit 3ec6fc8d1e34c344f59b8c1a22f3bab556e7fa07) --- source3/smbd/trans2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e1462c0103..6cebff61ed 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -878,8 +878,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i SSVAL(params,2,open_attr); put_dos_date2(params,4, mtime); SIVAL(params,8, (uint32)size); - SSVAL(params,12,open_ofun); - SSVAL(params,16,0); /* Padding. */ + SSVAL(params,12,deny_mode); + SSVAL(params,14,0); /* open_type - file or directory. */ + SSVAL(params,16,0); /* open_state - only valid for IPC device. */ if (oplock_request && lp_fake_oplocks(SNUM(conn))) { smb_action |= EXTENDED_OPLOCK_GRANTED; -- cgit From 15b842d401beebc304c98e855c33421782c51a85 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Aug 2005 23:45:16 +0000 Subject: r9286: Fix false positive found by Coverity - wcard must not be null. Jeremy. (This used to be commit 31104e5bcfffdd48071b2062809313679f29961f) --- source3/smbd/dir.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index a0df924dc7..159ce37236 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -378,6 +378,7 @@ static void dptr_close_oldest(BOOL old) one byte long. If old_handle is false we allocate from the range 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure a directory handle is never zero. + wcard must not be zero. ****************************************************************************/ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, @@ -389,6 +390,10 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp DEBUG(5,("dptr_create dir=%s\n", path)); + if (!wcard) { + return -1; + } + if (!check_name(path,conn)) return(-2); /* Code to say use a unix error return code. */ @@ -485,24 +490,21 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp dptr->dir_hnd = dir_hnd; dptr->spid = spid; dptr->expect_close = expect_close; - if (wcard) { - dptr->wcard = SMB_STRDUP(wcard); - if (!dptr->wcard) { - bitmap_clear(dptr_bmap, dptr->dnum - 1); - SAFE_FREE(dptr); - CloseDir(dir_hnd); - return -1; - } - } else { - dptr->wcard = NULL; + dptr->wcard = SMB_STRDUP(wcard); + if (!dptr->wcard) { + bitmap_clear(dptr_bmap, dptr->dnum - 1); + SAFE_FREE(dptr); + CloseDir(dir_hnd); + return -1; } - dptr->attr = attr; - if (lp_posix_pathnames() || (wcard && (wcard[0] == '.' && wcard[1] == 0))) { + if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { dptr->has_wild = True; } else { dptr->has_wild = ms_has_wild(wcard); } + dptr->attr = attr; + DLIST_ADD(dirptrs, dptr); DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", -- cgit From cd8a0fbd9ed9e92cdb22fcacf38f9edd24b87aa0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Aug 2005 23:49:57 +0000 Subject: r9288: Whitespace cleanup and memory leak on error path fix found by Coverity. Jeremy. (This used to be commit 0b85900fc8d79c71af986bb8b6346bba7840a704) --- source3/smbd/lanman.c | 115 ++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 127480f0b3..018b7f12ea 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3558,75 +3558,80 @@ static const struct int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { - int api_command; - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; - BOOL reply=False; - int i; + int api_command; + char *rdata = NULL; + char *rparam = NULL; + int rdata_len = 0; + int rparam_len = 0; + BOOL reply=False; + int i; - if (!params) { - DEBUG(0,("ERROR: NULL params in api_reply()\n")); - return 0; - } + if (!params) { + DEBUG(0,("ERROR: NULL params in api_reply()\n")); + return 0; + } - api_command = SVAL(params,0); + api_command = SVAL(params,0); - DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - api_command, - params+2, - skip_string(params+2,1), - tdscnt,tpscnt,mdrcnt,mprcnt)); + DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", + api_command, + params+2, + skip_string(params+2,1), + tdscnt,tpscnt,mdrcnt,mprcnt)); - for (i=0;api_commands[i].name;i++) { - if (api_commands[i].id == api_command && api_commands[i].fn) { - DEBUG(3,("Doing %s\n",api_commands[i].name)); - break; - } - } + for (i=0;api_commands[i].name;i++) { + if (api_commands[i].id == api_command && api_commands[i].fn) { + DEBUG(3,("Doing %s\n",api_commands[i].name)); + break; + } + } - /* Check whether this api call can be done anonymously */ + /* Check whether this api call can be done anonymously */ - if (api_commands[i].auth_user && lp_restrict_anonymous()) { - user_struct *user = get_valid_user_struct(vuid); + if (api_commands[i].auth_user && lp_restrict_anonymous()) { + user_struct *user = get_valid_user_struct(vuid); - if (!user || user->guest) - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } + if (!user || user->guest) { + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + } - rdata = (char *)SMB_MALLOC(1024); - if (rdata) - memset(rdata,'\0',1024); + rdata = (char *)SMB_MALLOC(1024); + if (rdata) { + memset(rdata,'\0',1024); + } - rparam = (char *)SMB_MALLOC(1024); - if (rparam) - memset(rparam,'\0',1024); + rparam = (char *)SMB_MALLOC(1024); + if (rparam) { + memset(rparam,'\0',1024); + } - if(!rdata || !rparam) { - DEBUG(0,("api_reply: malloc fail !\n")); - return -1; - } + if(!rdata || !rparam) { + DEBUG(0,("api_reply: malloc fail !\n")); + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return -1; + } - reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); + reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); - if (rdata_len > mdrcnt || - rparam_len > mprcnt) { - reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } + if (rdata_len > mdrcnt || + rparam_len > mprcnt) { + reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } - /* if we get False back then it's actually unsupported */ - if (!reply) - api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); + /* if we get False back then it's actually unsupported */ + if (!reply) { + api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } - send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); + send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); - SAFE_FREE(rdata); - SAFE_FREE(rparam); - - return -1; + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return -1; } -- cgit From 2d4ded54b68ef7bd4871c780807ac09facc05f2b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Aug 2005 00:13:21 +0000 Subject: r9290: Some error path cleanups found by Coverity. Whitespace reformatting. This file need a lot of error path cleanup. Jeremy. (This used to be commit ce93e469d80bb26cda390626ba8cc55ff9c822b6) --- source3/smbd/lanman.c | 509 +++++++++++++++++++++++++++----------------------- 1 file changed, 277 insertions(+), 232 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 018b7f12ea..0666fe8913 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -332,12 +332,12 @@ static int package(struct pack_desc* p, ...) static void PACKI(struct pack_desc* desc, const char *t,int v) { - PACK(desc,t,v); + PACK(desc,t,v); } static void PACKS(struct pack_desc* desc,const char *t,const char *v) { - PACK(desc,t,v); + PACK(desc,t,v); } @@ -346,51 +346,56 @@ static void PACKS(struct pack_desc* desc,const char *t,const char *v) ****************************************************************************/ static void PackDriverData(struct pack_desc* desc) { - char drivdata[4+4+32]; - SIVAL(drivdata,0,sizeof drivdata); /* cb */ - SIVAL(drivdata,4,1000); /* lVersion */ - memset(drivdata+8,0,32); /* szDeviceName */ - push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE); - PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ + char drivdata[4+4+32]; + SIVAL(drivdata,0,sizeof drivdata); /* cb */ + SIVAL(drivdata,4,1000); /* lVersion */ + memset(drivdata+8,0,32); /* szDeviceName */ + push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE); + PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ } static int check_printq_info(struct pack_desc* desc, - int uLevel, char *id1, char *id2) + unsigned int uLevel, char *id1, char *id2) { - desc->subformat = NULL; - switch( uLevel ) { - case 0: - desc->format = "B13"; - break; - case 1: - desc->format = "B13BWWWzzzzzWW"; - break; - case 2: - desc->format = "B13BWWWzzzzzWN"; - desc->subformat = "WB21BB16B10zWWzDDz"; - break; - case 3: - desc->format = "zWWWWzzzzWWzzl"; - break; - case 4: - desc->format = "zWWWWzzzzWNzzl"; - desc->subformat = "WWzWWDDzz"; - break; - case 5: - desc->format = "z"; - break; - case 51: - desc->format = "K"; - break; - case 52: - desc->format = "WzzzzzzzzN"; - desc->subformat = "z"; - break; - default: return False; - } - if (strcmp(desc->format,id1) != 0) return False; - if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False; - return True; + desc->subformat = NULL; + switch( uLevel ) { + case 0: + desc->format = "B13"; + break; + case 1: + desc->format = "B13BWWWzzzzzWW"; + break; + case 2: + desc->format = "B13BWWWzzzzzWN"; + desc->subformat = "WB21BB16B10zWWzDDz"; + break; + case 3: + desc->format = "zWWWWzzzzWWzzl"; + break; + case 4: + desc->format = "zWWWWzzzzWNzzl"; + desc->subformat = "WWzWWDDzz"; + break; + case 5: + desc->format = "z"; + break; + case 51: + desc->format = "K"; + break; + case 52: + desc->format = "WzzzzzzzzN"; + desc->subformat = "z"; + break; + default: + return False; + } + if (strcmp(desc->format,id1) != 0) { + return False; + } + if (desc->subformat && strcmp(desc->subformat,id2) != 0) { + return False; + } + return True; } @@ -721,7 +726,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); char *QueueName = p; - int uLevel; + unsigned int uLevel; int count=0; int snum; char* str3; @@ -824,134 +829,169 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char **rdata, char** rparam, int *rdata_len, int *rparam_len) { - char *param_format = param+2; - char *output_format1 = skip_string(param_format,1); - char *p = skip_string(output_format1,1); - int uLevel = SVAL(p,0); - char *output_format2 = p + 4; - int services = lp_numservices(); - int i, n; - struct pack_desc desc; - print_queue_struct **queue = NULL; - print_status_struct *status = NULL; - int* subcntarr = NULL; - int queuecnt, subcnt=0, succnt=0; + char *param_format = param+2; + char *output_format1 = skip_string(param_format,1); + char *p = skip_string(output_format1,1); + unsigned int uLevel = SVAL(p,0); + char *output_format2 = p + 4; + int services = lp_numservices(); + int i, n; + struct pack_desc desc; + print_queue_struct **queue = NULL; + print_status_struct *status = NULL; + int *subcntarr = NULL; + int queuecnt = 0, subcnt = 0, succnt = 0; - memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); - DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); + DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); - if (!prefix_ok(param_format,"WrLeh")) return False; - if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) { - /* - * Patch from Scott Moomaw - * to return the 'invalid info level' error if an - * unknown level was requested. - */ - *rdata_len = 0; - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,ERRunknownlevel); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,0); - return(True); - } + if (!prefix_ok(param_format,"WrLeh")) { + return False; + } + if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) { + /* + * Patch from Scott Moomaw + * to return the 'invalid info level' error if an + * unknown level was requested. + */ + *rdata_len = 0; + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,ERRunknownlevel); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,0); + return(True); + } - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - if (uLevel > 0) { - if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - memset(queue,0,queuecnt*sizeof(print_queue_struct*)); - if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - memset(status,0,queuecnt*sizeof(print_status_struct)); - if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - subcnt = 0; - n = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = print_queue_status(i, &queue[n],&status[n]); - subcnt += subcntarr[n]; - n++; - } - } - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + queuecnt++; + } + } - if (init_package(&desc,queuecnt,subcnt)) { - n = 0; - succnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } + if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + goto err; + } + memset(queue,0,queuecnt*sizeof(print_queue_struct*)); + if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + goto err; + } + memset(status,0,queuecnt*sizeof(print_status_struct)); + if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + goto err; + } + + subcnt = 0; + n = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + subcntarr[n] = print_queue_status(i, &queue[n],&status[n]); + subcnt += subcntarr[n]; + n++; + } + } + + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + goto err; + } + } + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,queuecnt,subcnt)) { + n = 0; + succnt = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); + n++; + if (desc.errcode == NERR_Success) { + succnt = n; + } + } + } + } - SAFE_FREE(subcntarr); + SAFE_FREE(subcntarr); - *rdata_len = desc.usedlen; - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); + *rdata_len = desc.usedlen; + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + goto err; + } + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,queuecnt); - for (i = 0; i < queuecnt; i++) { - if (queue) SAFE_FREE(queue[i]); - } + for (i = 0; i < queuecnt; i++) { + if (queue) { + SAFE_FREE(queue[i]); + } + } - SAFE_FREE(queue); - SAFE_FREE(status); + SAFE_FREE(queue); + SAFE_FREE(status); - return True; + return True; + + err: + + SAFE_FREE(subcntarr); + for (i = 0; i < queuecnt; i++) { + if (queue) { + SAFE_FREE(queue[i]); + } + } + SAFE_FREE(queue); + SAFE_FREE(status); + + return False; } /**************************************************************************** - get info level for a server list query - ****************************************************************************/ + Get info level for a server list query. +****************************************************************************/ + static BOOL check_server_info(int uLevel, char* id) { - switch( uLevel ) { - case 0: - if (strcmp(id,"B16") != 0) return False; - break; - case 1: - if (strcmp(id,"B16BBDz") != 0) return False; - break; - default: - return False; - } - return True; + switch( uLevel ) { + case 0: + if (strcmp(id,"B16") != 0) { + return False; + } + break; + case 1: + if (strcmp(id,"B16BBDz") != 0) { + return False; + } + break; + default: + return False; + } + return True; } -struct srv_info_struct -{ - fstring name; - uint32 type; - fstring comment; - fstring domain; - BOOL server_added; +struct srv_info_struct { + fstring name; + uint32 type; + fstring comment; + fstring domain; + BOOL server_added; }; - /******************************************************************* - get server info lists from the files saved by nmbd. Return the - number of entries - ******************************************************************/ + 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, const char *domain) @@ -1059,10 +1099,10 @@ static int get_server_info(uint32 servertype, return(count); } - /******************************************************************* - fill in a server info structure - ******************************************************************/ + Fill in a server info structure. +******************************************************************/ + static int fill_srv_info(struct srv_info_struct *service, int uLevel, char **buf, int *buflen, char **stringbuf, int *stringspace, char *baseaddr) @@ -1141,13 +1181,14 @@ static int fill_srv_info(struct srv_info_struct *service, static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) { - return(strcmp(s1->name,s2->name)); + return(strcmp(s1->name,s2->name)); } /**************************************************************************** - view list of servers available (or possibly domains). The info is - extracted from lists saved by nmbd on the local host - ****************************************************************************/ + View list of servers available (or possibly domains). The info is + extracted from lists saved by nmbd on the local host. +****************************************************************************/ + static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) @@ -1275,6 +1316,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param /**************************************************************************** command 0x34 - suspected of being a "Lookup Names" stub api ****************************************************************************/ + static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) @@ -1308,6 +1350,7 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa /**************************************************************************** get info about a share ****************************************************************************/ + static BOOL check_share_info(int uLevel, char* id) { switch( uLevel ) { @@ -1464,6 +1507,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para twelve byte strings for share names (plus one for a nul terminator). Share names longer than 12 bytes must be skipped. ****************************************************************************/ + static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, char *param, @@ -1547,11 +1591,12 @@ static BOOL api_RNetShareEnum( connection_struct *conn, counted,total,uLevel, buf_len,*rdata_len,mdrcnt)); return(True); -} /* api_RNetShareEnum */ +} /**************************************************************************** Add a share ****************************************************************************/ + static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1638,12 +1683,12 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch SSVAL(*rparam,0,res); SSVAL(*rparam,2,0); return True; - } /**************************************************************************** view list of groups available ****************************************************************************/ + static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1733,8 +1778,9 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c } /******************************************************************* - get groups that a user is a member of - ******************************************************************/ + Get groups that a user is a member of. +******************************************************************/ + static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1839,8 +1885,9 @@ out: } /******************************************************************* - get all users - ******************************************************************/ + Get all users. +******************************************************************/ + static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1869,7 +1916,8 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch resume_context = SVAL(p,0); cli_buf_size=SVAL(p+2,0); - DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); + DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", + resume_context, cli_buf_size)); *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); @@ -1928,11 +1976,10 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch return True; } - - /**************************************************************************** - get the time of day info - ****************************************************************************/ + Get the time of day info. +****************************************************************************/ + static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1974,8 +2021,6 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch SSVAL(p,18,1900+t->tm_year); SCVAL(p,20,t->tm_wday); } - - return(True); } @@ -2117,6 +2162,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * delete a print job Form: <> ****************************************************************************/ + static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2184,6 +2230,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param /**************************************************************************** Purge a print queue - or pause or resume it. ****************************************************************************/ + static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2233,7 +2280,6 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param return(True); } - /**************************************************************************** set the property of a print job (undocumented?) ? function = 0xb -> set name of print job @@ -2241,6 +2287,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param Form: or ****************************************************************************/ + static int check_printjob_info(struct pack_desc* desc, int uLevel, char* id) { @@ -2328,8 +2375,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha /**************************************************************************** - get info about the server - ****************************************************************************/ + Get info about the server. +****************************************************************************/ + static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2434,10 +2482,10 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par return(True); } - /**************************************************************************** - get info about the server - ****************************************************************************/ + Get info about the server. +****************************************************************************/ + static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2912,10 +2960,10 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param return(True); } - /**************************************************************************** - api_WAccessGetUserPerms - ****************************************************************************/ + api_WAccessGetUserPerms +****************************************************************************/ + static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2944,6 +2992,7 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p /**************************************************************************** api_WPrintJobEnumerate ****************************************************************************/ + static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -3500,56 +3549,53 @@ static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,cha return(True); } - - - -static const struct -{ - const char *name; - int id; - BOOL (*fn)(connection_struct *,uint16,char *,char *, - int,int,char **,char **,int *,int *); - BOOL auth_user; /* Deny anonymous access? */ +static const struct { + const char *name; + int id; + BOOL (*fn)(connection_struct *,uint16,char *,char *, + int,int,char **,char **,int *,int *); + BOOL auth_user; /* Deny anonymous access? */ } api_commands[] = { - {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True}, - {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo}, - {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd}, - {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True}, - {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo}, - {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True}, - {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True}, - {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True}, - {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo}, - {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups}, - {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo}, - {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True}, - {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo}, - {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl}, - {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl}, - {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate}, - {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo}, - {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel}, - {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel}, - {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel}, - {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum}, - {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo}, - {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD}, - {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl}, - {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */ - {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms}, - {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword}, - {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon}, - {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo}, - {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum}, - {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum}, - {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum}, - {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */ - {NULL, -1, api_Unsupported}}; - -/* The following RAP calls are not implemented by Samba: - - RAP_WFileEnum2 - anon not OK -*/ + {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True}, + {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo}, + {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd}, + {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True}, + {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo}, + {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True}, + {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True}, + {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True}, + {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo}, + {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups}, + {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo}, + {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True}, + {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo}, + {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl}, + {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl}, + {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate}, + {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo}, + {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel}, + {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel}, + {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel}, + {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum}, + {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo}, + {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD}, + {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl}, + {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */ + {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms}, + {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword}, + {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon}, + {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo}, + {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum}, + {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum}, + {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum}, + {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */ + {NULL, -1, api_Unsupported} + /* The following RAP calls are not implemented by Samba: + + RAP_WFileEnum2 - anon not OK + */ +}; + /**************************************************************************** Handle remote api calls @@ -3617,8 +3663,7 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * &rdata,&rparam,&rdata_len,&rparam_len); - if (rdata_len > mdrcnt || - rparam_len > mprcnt) { + if (rdata_len > mdrcnt || rparam_len > mprcnt) { reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); } -- cgit From baf5fd8336e6bceb05704bc76ecc511cc05be91b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Aug 2005 01:48:29 +0000 Subject: r9293: Fix error path memory leak bug found by Coverity - also potential NULL deref bug (in unlikely error path) found by Coverity. Jeremy. (This used to be commit 9b5cc58f3abdb1945bfad340968ccabdfd040029) --- source3/smbd/posix_acls.c | 48 +++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a1855b0fa9..2f5bcb57fa 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1548,8 +1548,12 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); * entries can be converted to *_OBJ. Usually we will already have these * entries in the Default ACL, and the Access ACL will not have them. */ - check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid); - check_owning_objs(dir_ace, pfile_owner_sid, pfile_grp_sid); + if (file_ace) { + check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid); + } + if (dir_ace) { + check_owning_objs(dir_ace, pfile_owner_sid, pfile_grp_sid); + } } *ppfile_ace = file_ace; @@ -2801,7 +2805,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) if (count_canon_ace_list(file_ace) == 0) { DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); - return 0; + goto done; } if (fsp->is_directory && def_acl) { @@ -2950,33 +2954,37 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) if(!psd) { DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); sd_size = 0; - } else { - /* - * Windows 2000: The DACL_PROTECTED flag in the security - * descriptor marks the ACL as non-inheriting, i.e., no - * ACEs from higher level directories propagate to this - * ACL. In the POSIX ACL model permissions are only - * inherited at file create time, so ACLs never contain - * any ACEs that are inherited dynamically. The DACL_PROTECTED - * flag doesn't seem to bother Windows NT. - * Always set this if map acl inherit is turned off. - */ - if (get_protected_flag(pal) || !lp_map_acl_inherit(SNUM(conn))) { - psd->type |= SE_DESC_DACL_PROTECTED; - } + goto done; } - if (psd->dacl) + /* + * Windows 2000: The DACL_PROTECTED flag in the security + * descriptor marks the ACL as non-inheriting, i.e., no + * ACEs from higher level directories propagate to this + * ACL. In the POSIX ACL model permissions are only + * inherited at file create time, so ACLs never contain + * any ACEs that are inherited dynamically. The DACL_PROTECTED + * flag doesn't seem to bother Windows NT. + * Always set this if map acl inherit is turned off. + */ + if (get_protected_flag(pal) || !lp_map_acl_inherit(SNUM(conn))) { + psd->type |= SE_DESC_DACL_PROTECTED; + } + + if (psd->dacl) { dacl_sort_into_canonical_order(psd->dacl->ace, (unsigned int)psd->dacl->num_aces); + } *ppdesc = psd; done: - if (posix_acl) + if (posix_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); - if (def_acl) + } + if (def_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); + } free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); free_inherited_info(pal); -- cgit From f069f96a1fd96f760597bdfd04968bd6ab2ff5b6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 21 Aug 2005 21:12:27 +0000 Subject: r9457: Attempt to fix bug #3010 by handling END_OF_DIRECTORY_OFFSET consistently. Jeremy. (This used to be commit ac8f22a328d878f064277638d63446bf68b68dfd) --- source3/smbd/dir.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 159ce37236..f722bedecb 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1100,6 +1100,9 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) } dirp->file_number++; return n; + } else if (*poffset == END_OF_DIRECTORY_OFFSET) { + *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET; + return NULL; } else { /* A real offset, seek to it. */ SeekDir(dirp, *poffset); @@ -1122,7 +1125,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) dirp->file_number++; return e->name; } - dirp->offset = END_OF_DIRECTORY_OFFSET; + *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET; return NULL; } @@ -1147,6 +1150,8 @@ void SeekDir(struct smb_Dir *dirp, long offset) if (offset != dirp->offset) { if (offset == START_OF_DIRECTORY_OFFSET || offset == DOT_DOT_DIRECTORY_OFFSET) { RewindDir(dirp, &offset); + } else if (offset == END_OF_DIRECTORY_OFFSET) { + ; /* Don't seek in this case. */ } else { SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); } -- cgit From f98f86394a654722fa13ef1dc3c4dea82d452442 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 22 Aug 2005 18:03:08 +0000 Subject: r9483: Changed DIR to SMB_STRUCT_DIR because of the amazing stupidity of a UNIX vendor not understanding abstract data types :-(. Jeremy. (This used to be commit be5b4e2fa3ed30b0ff01b47d2354e5f782a12e25) --- source3/smbd/dir.c | 2 +- source3/smbd/vfs-wrap.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f722bedecb..02e15d222a 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -42,7 +42,7 @@ struct name_cache_entry { struct smb_Dir { connection_struct *conn; - DIR *dir; + SMB_STRUCT_DIR *dir; long offset; char *dir_path; struct name_cache_entry *name_cache; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 39ac402f34..2129cf8541 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -88,9 +88,9 @@ int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_ /* Directory operations */ -DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) +SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) { - DIR *result; + SMB_STRUCT_DIR *result; START_PROFILE(syscall_opendir); result = sys_opendir(fname); @@ -98,7 +98,7 @@ DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const c return result; } -SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) { SMB_STRUCT_DIRENT *result; @@ -108,14 +108,14 @@ SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct return result; } -void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp, long offset) +void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset) { START_PROFILE(syscall_seekdir); sys_seekdir(dirp, offset); END_PROFILE(syscall_seekdir); } -long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) { long result; START_PROFILE(syscall_telldir); @@ -124,7 +124,7 @@ long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, DIR *di return result; } -void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) { START_PROFILE(syscall_rewinddir); sys_rewinddir(dirp); @@ -170,7 +170,7 @@ int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char return result; } -int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) { int result; -- cgit From 78257e343305b426c5853c4dcbfa3d63dd5f720d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Aug 2005 17:53:11 +0000 Subject: r9532: Fix for bug #2152, championed by Neil Hoggarth . Jeremy. (This used to be commit d29a45565d955e655b9b5a06039be39efc9e021b) --- source3/smbd/mangle_hash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 871702623a..093b60b042 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -167,10 +167,6 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOO if (strcmp_wa(fname, ".")==0 || strcmp_wa(fname, "..")==0) return NT_STATUS_OK; - /* Name cannot start with '.' */ - if (*fname == UCS2_CHAR('.')) - return NT_STATUS_UNSUCCESSFUL; - if (only_8_3) { ret = has_valid_83_chars(fname, allow_wildcards); if (!NT_STATUS_IS_OK(ret)) @@ -247,6 +243,10 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards) if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) return NT_STATUS_OK; + /* Name cannot start with '.' */ + if (*fname == UCS2_CHAR('.')) + return NT_STATUS_UNSUCCESSFUL; + if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards, True))) goto done; -- cgit From b67ba1e36b11aa140822f92b148438a1387d4d9d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Aug 2005 21:29:37 +0000 Subject: r9545: (Hopefully the last) fixes for DIR -> SMB_STRUCT_DIR. Jeremy. (This used to be commit b242f278601e1a23c9116009482e802326d418f7) --- source3/smbd/chgpasswd.c | 8 ++++---- source3/smbd/msdfs.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index f445ca3365..374c57a083 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -64,7 +64,7 @@ static int findpty(char **slave) { int master; static fstring line; - DIR *dirp; + SMB_STRUCT_DIR *dirp; const char *dpname; #if defined(HAVE_GRANTPT) @@ -93,7 +93,7 @@ static int findpty(char **slave) fstrcpy(line, "/dev/ptyXX"); - dirp = opendir("/dev"); + dirp = sys_opendir("/dev"); if (!dirp) return (-1); while ((dpname = readdirname(dirp)) != NULL) @@ -110,12 +110,12 @@ static int findpty(char **slave) DEBUG(3, ("pty: opened %s\n", line)); line[5] = 't'; *slave = line; - closedir(dirp); + sys_closedir(dirp); return (master); } } } - closedir(dirp); + sys_closedir(dirp); return (-1); } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 2b13e2a4b5..1e6306382a 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1010,7 +1010,7 @@ BOOL remove_msdfs_link(struct junction_map *jucn) static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain) { int cnt = 0; - DIR *dirp; + SMB_STRUCT_DIR *dirp; char* dname; pstring connect_path; char* service_name = lp_servicename(snum); -- cgit From fa2ec3651ec88777930e478c888096907006fd8b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 24 Aug 2005 13:15:01 +0000 Subject: r9584: Fix a race condition in Samba 3. If two files are opened simultaneously with NTCREATEX_DISP_CREATE (create if not exists, else fail) they might end up with two or more times NT_STATUS_OK as EEXIST is not correctly handled. Jeremy, please look closely at this. You can easily verify this by adding a smb_msleep(100) to the top of open_file_ntcreate and run the new samba4 torture test. It does also happen without the msleep, but not as reliably. Thanks, Volker (This used to be commit 58b9e48df03098160f39607d869a3c8e10860ba4) --- source3/smbd/open.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3cd553f55b..98c2997a97 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1585,6 +1585,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask); + if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) { + /* + * Two smbd's tried to open exclusively, but only one of them + * succeeded. + */ + file_free(fsp); + return NULL; + } + if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT)) { if((fsp_open = open_file(fsp,conn,fname,psbuf, O_RDONLY,unx_mode,access_mask)) == True) { -- cgit From 470a12d25e8d6bea7a032243c85729ed50411e42 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 2 Sep 2005 09:16:08 +0000 Subject: r9946: allow the priv-based chown (se_take_ownership) to chown to other users (not only to the current_user.uid). Jeremy, please have a look. Guenther (This used to be commit 8e48e8936ed59ed8d50b6eaa9954749168de3138) --- source3/smbd/posix_acls.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2f5bcb57fa..00ec3e0095 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3021,7 +3021,6 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ /* Case (2). */ if (lp_enable_privileges() && - (uid == current_user.uid) && (user_has_privileges(current_user.nt_user_token,&se_take_ownership))) { become_root(); /* Keep the current file gid the same - take ownership doesn't imply group change. */ -- cgit From e722cb25d8b2584a21dc6b4ecbca3b04c4dcb2c1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 2 Sep 2005 12:53:46 +0000 Subject: r9952: Adapt better to the Windows way of taking and assigning ownership: * Users with SeRestorePrivilege may chown files to anyone (be it as a backup software or directly using the ownership-tab in the security acl editor on xp), while * Users with SeTakeOwnershipPrivilege only can chown to themselves. Simo, Jeremy. I think this is correct now. Guenther (This used to be commit 1ef7a192eed457d302a08c692bb54a73a1af4afd) --- source3/smbd/posix_acls.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 00ec3e0095..f1c9426676 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2998,7 +2998,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) 1) If we have root privileges, then it will just work. 2) If we have SeTakeOwnershipPrivilege we can change the user to the current user. - 3) If we have write permission to the file and dos_filemodes is set + 3) If we have SeRestorePrivilege we can change the user to any other user. + 4) If we have write permission to the file and dos_filemodes is set then allow chown to the currently authenticated user. ****************************************************************************/ @@ -3007,7 +3008,6 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ int ret; files_struct *fsp; SMB_STRUCT_STAT st; - SE_PRIV se_take_ownership = SE_TAKE_OWNERSHIP; if(!CAN_WRITE(conn)) { return -1; @@ -3019,17 +3019,28 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ if (ret == 0) return 0; - /* Case (2). */ - if (lp_enable_privileges() && - (user_has_privileges(current_user.nt_user_token,&se_take_ownership))) { - become_root(); - /* Keep the current file gid the same - take ownership doesn't imply group change. */ - ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1); - unbecome_root(); - return ret; + /* Case (2) / (3) */ + if (lp_enable_privileges()) { + + BOOL has_take_ownership_priv = user_has_privileges(current_user.nt_user_token, + &se_take_ownership); + BOOL has_restore_priv = user_has_privileges(current_user.nt_user_token, + &se_restore); + + /* Case (2) */ + if ( ( has_take_ownership_priv && ( uid == current_user.uid ) ) || + /* Case (3) */ + ( has_restore_priv ) ) { + + become_root(); + /* Keep the current file gid the same - take ownership doesn't imply group change. */ + ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1); + unbecome_root(); + return ret; + } } - /* Case (3). */ + /* Case (4). */ if (!lp_dos_filemode(SNUM(conn))) { return -1; } -- cgit From 93954d6390370331731bda5fcf251dc0a796c744 Mon Sep 17 00:00:00 2001 From: James Peach Date: Sat, 3 Sep 2005 07:19:28 +0000 Subject: r9985: Move the all the strict sync logic into file_sync(). (This used to be commit cc680bbe22b8bfc5a1900f11c2cbaeca3a9f9922) --- source3/smbd/aio.c | 4 +--- source3/smbd/fileio.c | 9 ++++++--- source3/smbd/files.c | 2 +- source3/smbd/reply.c | 20 +++++++------------- 4 files changed, 15 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index d19706ff61..af1f172b92 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -475,9 +475,7 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( } DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); - if (lp_syncalways(SNUM(fsp->conn)) || write_through) { - sync_file(fsp->conn,fsp); - } + sync_file(fsp->conn,fsp, write_through); } show_msg(outbuf); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 76189d114b..375bfbe7cf 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -834,15 +834,18 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) sync a file ********************************************************************/ -void sync_file(connection_struct *conn, files_struct *fsp) +void sync_file(connection_struct *conn, files_struct *fsp, BOOL write_through) { - if(lp_strict_sync(SNUM(conn)) && fsp->fh->fd != -1) { + if (fsp->fh->fd == -1) + return; + + if (lp_strict_sync(SNUM(conn)) && + (lp_syncalways(SNUM(conn)) || write_through)) { flush_write_cache(fsp, SYNC_FLUSH); SMB_VFS_FSYNC(fsp,fsp->fh->fd); } } - /************************************************************ Perform a stat whether a valid fd or not. ************************************************************/ diff --git a/source3/smbd/files.c b/source3/smbd/files.c index c90c2b627c..65986e9612 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -427,7 +427,7 @@ void file_sync_all(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next=fsp->next; if ((conn == fsp->conn) && (fsp->fh->fd != -1)) { - sync_file(conn,fsp); + sync_file(conn, fsp, True /* write through */); } } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e96c3dc01f..9050006653 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2786,8 +2786,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SSVAL(outbuf,smb_vwv0,total_written); - if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn))) - sync_file(conn,fsp); + sync_file(conn, fsp, write_through); DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); @@ -2852,8 +2851,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, nwritten = write_file(fsp,data,startpos,numtowrite); } - if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); + sync_file(conn, fsp, False /* write through */); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwriteunlock); @@ -2940,8 +2938,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d } else nwritten = write_file(fsp,data,startpos,numtowrite); - if (lp_syncalways(SNUM(conn))) - sync_file(conn,fsp); + sync_file(conn, fsp, False); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwrite); @@ -3068,8 +3065,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); - if (lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + sync_file(conn, fsp, write_through); END_PROFILE(SMBwriteX); return chain_reply(inbuf,outbuf,length,bufsize); @@ -3166,7 +3162,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (!fsp) { file_sync_all(conn); } else { - sync_file(conn,fsp); + sync_file(conn,fsp, True); } DEBUG(3,("flush\n")); @@ -5433,8 +5429,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, nwritten = write_file(fsp,data,startpos,numtowrite); - if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + sync_file(conn, fsp, write_through); if(nwritten < (ssize_t)numtowrite) { END_PROFILE(SMBwriteBmpx); @@ -5546,8 +5541,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz nwritten = write_file(fsp,data,startpos,numtowrite); - if(lp_syncalways(SNUM(conn)) || write_through) - sync_file(conn,fsp); + sync_file(conn, fsp, write_through); if (nwritten < (ssize_t)numtowrite) { if(write_through) { -- cgit From ac01fda2b97b416467866ea9303a22de778f02e6 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 8 Sep 2005 01:05:16 +0000 Subject: r10068: Use prctl(PR_SET_DUMPABLE) to make sure we can always leave a good looking corpse on Linux. (This used to be commit 7c97a1bcc34892d7bf697b9421ba8caf4061d9b5) --- source3/smbd/server.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4217d821f4..a10968749d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,6 +22,10 @@ #include "includes.h" +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + static int am_parent = 1; /* the last message the was processed */ @@ -915,6 +919,14 @@ void build_options(BOOL screen); * everything after this point is run after the fork() */ +#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) + /* On Linux we lose the ability to dump core when we change our user + * ID. We know how to dump core safely, so let's make sure we have our + * dumpable flag set. + */ + prctl(PR_SET_DUMPABLE, 1); +#endif + /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ -- cgit From 11c79fa98fd41be7d770d7e1da8053dd4f3082a8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Sep 2005 21:49:16 +0000 Subject: r10133: Fix bug #3044. open-exec is read-only. Jeremy. (This used to be commit ed644d4014c3dc6c0508e94470c277599b1db933) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 98c2997a97..ed847826d5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1046,13 +1046,13 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func /* Create the NT compatible access_mask. */ switch (GET_OPENX_MODE(deny_mode)) { + case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */ case DOS_OPEN_RDONLY: access_mask = FILE_GENERIC_READ; break; case DOS_OPEN_WRONLY: access_mask = FILE_GENERIC_WRITE; break; - case DOS_OPEN_EXEC: /* This used to be FILE_READ_DATA... */ case DOS_OPEN_RDWR: case DOS_OPEN_FCB: access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE; -- cgit From d99d15446acfc926a2375af6d681420781feffcb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Sep 2005 00:47:31 +0000 Subject: r10136: Fix for bug #3060 from Leo Weppelman . Ensure SMBcreate truncates the file if it exists. Jeremy. (This used to be commit 9014b0ddcbd87c98613f06033718e4091e3be21c) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9050006653..2d9a31032b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1610,7 +1610,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, create_disposition = FILE_CREATE; } else { /* Create if file doesn't exist, truncate if it does. */ - create_disposition = FILE_OPEN_IF; + create_disposition = FILE_OVERWRITE_IF; } /* Open file using ntcreate. */ -- cgit From f1b1adc13612cbfeeb3286f7e3992911abed5dd2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Sep 2005 21:27:48 +0000 Subject: r10182: Starting to stamp out warnings on a 64-bit box. More to follow. Jeremy. (This used to be commit aa882646854325aa201b66d0ba27026946ce8dcb) --- source3/smbd/trans2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6cebff61ed..38363bf66a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -135,7 +135,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str return False; } - DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret)); + DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret)); dump_data(10, val, sizeret); pea->flags = 0; @@ -188,7 +188,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str if (sizeret == -1) return NULL; - DEBUG(10,("get_ea_list_from_file: ea_namelist size = %d\n", sizeret )); + DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret )); if (sizeret) { for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { @@ -210,7 +210,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str push_ascii_fstring(dos_ea_name, listp->ea.name); *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n", - *pea_total_len, dos_ea_name, + (unsigned int)*pea_total_len, dos_ea_name, (unsigned int)listp->ea.value.length )); } DLIST_ADD_END(ea_list_head, listp, tmp); @@ -221,7 +221,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str } } - DEBUG(10,("get_ea_list_from_file: total_len = %u\n", *pea_total_len)); + DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len)); return ea_list_head; } @@ -329,7 +329,7 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s canonicalize_ea_name(conn, fsp, fname, unix_ea_name); - DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length)); + DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length)); if (samba_private_attr_name(unix_ea_name)) { DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); -- cgit From ab59cdc5803371faa7fd2d983f3dc796afceb007 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Sep 2005 21:47:42 +0000 Subject: r10186: More 64-bit warning fixes. Jeremy. (This used to be commit 88034b9c2845a38833f300b812202c2a4ca3d2fd) --- source3/smbd/statcache.c | 4 ++-- source3/smbd/vfs-wrap.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 97ecd4152c..548d7c4a48 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -136,8 +136,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); } else { - DEBUG(5,("stat_cache_add: Added entry (%x:size%x) %s -> %s\n", - (unsigned int)data_val.dptr, data_val.dsize, original_path, translated_path)); + DEBUG(5,("stat_cache_add: Added entry (%lx:size%x) %s -> %s\n", + (unsigned long)data_val.dptr, (unsigned int)data_val.dsize, original_path, translated_path)); } SAFE_FREE(original_path); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 2129cf8541..9ae1592a8e 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -1063,7 +1063,7 @@ int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp return sys_aio_write(aiocb); } -int vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) { return sys_aio_return(aiocb); } -- cgit From c46b4cabf4ee02fc90b3b42c800926f55c7099be Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Sep 2005 21:50:32 +0000 Subject: r10188: 64-bit warning fix. Jeremy. (This used to be commit 3b8a8e2947e4d956766e97bea8fa9c25210d1c19) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1deb4da269..8f9cc52882 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -897,7 +897,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - DEBUG(3,("switch message %s (pid %d) conn 0x%x\n",smb_fn_name(type),(int)pid,(unsigned int)conn)); + DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn)); smb_dump(smb_fn_name(type), 1, inbuf, size); if(global_oplock_break) { -- cgit From 20f2305c50dc7eedd3b211a13937b2ed85235971 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Sep 2005 20:06:10 +0000 Subject: r10276: Fix for bug #3104 from Leo Weppelman . Don't update the time on read-only shares. We need this as set_filetime (which can be called on close and other paths) can end up calling this function without the NEED_WRITE protection. Jeremy. (This used to be commit 54eab3828aa0405288b68f6954abba201564c9e7) --- source3/smbd/dosmode.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index a2bc424b8e..ee2f1095fa 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -451,6 +451,17 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times errno = 0; ZERO_STRUCT(sbuf); + /* Don't update the time on read-only shares */ + /* We need this as set_filetime (which can be called on + close and other paths) can end up calling this function + without the NEED_WRITE protection. Found by : + Leo Weppelman + */ + + if (!CAN_WRITE(conn)) { + return 0; + } + if(SMB_VFS_UTIME(conn,fname, times) == 0) return 0; -- cgit From 1970294ab3df66d36b713dc8811527ddc8e99bd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Sep 2005 20:20:51 +0000 Subject: r10359: Ensure that smb.conf requests for hidden files are honored, even when DOS attributes are stored in EA's. Jeremy. (This used to be commit 758b30710e9f84f19b79c39afddc742aef495ebd) --- source3/smbd/dosmode.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ee2f1095fa..efbd5f04cb 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -297,27 +297,28 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) return 0; } - /* Get the DOS attributes from an EA by preference. */ - if (get_ea_dos_attribute(conn, path, sbuf, &result)) { - result |= set_sparse_flag(sbuf); - return result; - } - - result = dos_mode_from_sbuf(conn, path, sbuf); - - /* Now do any modifications that depend on the path name. */ + /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { const char *p = strrchr_m(path,'/'); - if (p) + if (p) { p++; - else + } else { p = path; + } - if (p[0] == '.' && p[1] != '.' && p[1] != 0) + if (p[0] == '.' && p[1] != '.' && p[1] != 0) { result |= aHIDDEN; + } } + /* Get the DOS attributes from an EA by preference. */ + if (get_ea_dos_attribute(conn, path, sbuf, &result)) { + result |= set_sparse_flag(sbuf); + } else { + result |= dos_mode_from_sbuf(conn, path, sbuf); + } + /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { -- cgit From a757c6d57fc5f24951ee00070f9b9471244cef05 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Sep 2005 17:42:11 +0000 Subject: r10551: We need to check if the source path is a parent directory of the destination (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must refuse the rename with a sharing violation. Under UNIX the above call can *succeed* if /foo/bar/baz is a symlink to another area in the share. We probably need to check that the client is a Windows one before disallowing this as a UNIX client (one with UNIX extensions) can know the source is a symlink and make this decision intelligently. Found by an excellent bug report from . Jeremy. (This used to be commit fc311adc7964feef5bac85096727f54922d1186c) --- source3/smbd/reply.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2d9a31032b..5572f47e42 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4075,6 +4075,35 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T (unsigned int)dev, (double)inode, newname )); } +/**************************************************************************** + We need to check if the source path is a parent directory of the destination + (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must + refuse the rename with a sharing violation. Under UNIX the above call can + *succeed* if /foo/bar/baz is a symlink to another area in the share. We + probably need to check that the client is a Windows one before disallowing + this as a UNIX client (one with UNIX extensions) can know the source is a + symlink and make this decision intelligently. Found by an excellent bug + report from . +****************************************************************************/ + +static BOOL rename_path_prefix_equal(const char *src, const char *dest) +{ + const char *psrc = src; + const char *pdst = dest; + size_t slen; + + if (psrc[0] == '.' && psrc[1] == '/') { + psrc += 2; + } + if (pdst[0] == '.' && pdst[1] == '/') { + pdst += 2; + } + if ((slen = strlen(psrc)) > strlen(pdst)) { + return False; + } + return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/'); +} + /**************************************************************************** Rename an open file - given an fsp. ****************************************************************************/ @@ -4170,6 +4199,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * return error; } + if (rename_path_prefix_equal(fsp->fsp_name, newname)) { + return NT_STATUS_ACCESS_DENIED; + } + if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); @@ -4391,6 +4424,10 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_NAME_COLLISION; } + if (rename_path_prefix_equal(directory, newname)) { + return NT_STATUS_SHARING_VIOLATION; + } + if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); @@ -4489,6 +4526,10 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", continue; } + if (rename_path_prefix_equal(fname, destname)) { + return NT_STATUS_SHARING_VIOLATION; + } + if (!SMB_VFS_RENAME(conn,fname,destname)) { rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); count++; -- cgit From 22f603ac567f369b544267c5e891d282dd3e2dfa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Sep 2005 20:41:22 +0000 Subject: r10558: Fix bug #3010 yet again. Die monster, die ! Jeremy. (This used to be commit dba56e8d23dc10a31f0f700b02c8776bdc8f57c1) --- source3/smbd/dir.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 02e15d222a..70a3b81ad6 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1148,8 +1148,23 @@ void RewindDir(struct smb_Dir *dirp, long *poffset) void SeekDir(struct smb_Dir *dirp, long offset) { if (offset != dirp->offset) { - if (offset == START_OF_DIRECTORY_OFFSET || offset == DOT_DOT_DIRECTORY_OFFSET) { + if (offset == START_OF_DIRECTORY_OFFSET) { RewindDir(dirp, &offset); + /* + * Ok we should really set the file number here + * to 1 to enable ".." to be returned next. Trouble + * is I'm worried about callers using SeekDir(dirp,0) + * as equivalent to RewindDir(). So leave this alone + * for now. + */ + } else if (offset == DOT_DOT_DIRECTORY_OFFSET) { + RewindDir(dirp, &offset); + /* + * Set the file number to 2 - we want to get the first + * real file entry (the one we return after "..") + * on the next ReadDir. + */ + dirp->file_number = 2; } else if (offset == END_OF_DIRECTORY_OFFSET) { ; /* Don't seek in this case. */ } else { -- cgit From 4850bc63104f5f2945d9e91cfbd99773a5bc570f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Sep 2005 01:27:19 +0000 Subject: r10600: Fix bug #2769 (mangle filenames ending in a space) and an old bug where mangle mathod hash wasn't mangling file names with more than one dot which also end in a dot. Jeremy. (This used to be commit 105e38847dc0078951abcda16808590ccc363b00) --- source3/smbd/mangle_hash.c | 20 +++++++++++++------- source3/smbd/mangle_hash2.c | 6 +++++- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 093b60b042..30befd2c84 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -158,6 +158,7 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOOL only_8_3) { smb_ucs2_t *str, *p; + size_t num_ucs2_chars; NTSTATUS ret = NT_STATUS_OK; if (!fname || !*fname) @@ -177,17 +178,22 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOO if (!NT_STATUS_IS_OK(ret)) return ret; - str = strdup_w(fname); - p = strchr_w(str, UCS2_CHAR('.')); - if (p && p[1] == UCS2_CHAR(0)) { - /* Name cannot end in '.' */ - SAFE_FREE(str); + /* Name can't end in '.' or ' ' */ + num_ucs2_chars = strlen_w(fname); + if (fname[num_ucs2_chars-1] == UCS2_CHAR('.') || fname[num_ucs2_chars-1] == UCS2_CHAR(' ')) { return NT_STATUS_UNSUCCESSFUL; } - if (p) + + str = strdup_w(fname); + + /* Truncate copy after the first dot. */ + p = strchr_w(str, UCS2_CHAR('.')); + if (p) { *p = 0; + } + strupper_w(str); - p = &(str[1]); + p = &str[1]; switch(str[0]) { diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index e44aaf17e7..613dda9a16 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -445,6 +445,7 @@ static BOOL is_reserved_name(const char *name) /* See if a filename is a legal long filename. A filename ending in a '.' is not legal unless it's "." or "..". JRA. + A filename ending in ' ' is not legal either. See bug id #2769. */ static BOOL is_legal_name(const char *name) @@ -480,6 +481,10 @@ static BOOL is_legal_name(const char *name) } else { alldots = False; } + if ((name[0] == ' ') && (name[1] == '\0')) { + /* Can't end in ' ' */ + return False; + } name++; } @@ -491,7 +496,6 @@ static BOOL is_legal_name(const char *name) if (dot_pos[1] == '\0') return False; } - return True; } -- cgit From 4a2cc231d22a82ed21771a72508f15d21ed63227 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 30 Sep 2005 06:37:51 +0000 Subject: r10644: Let the ports parameter be a comma-separated list, as documented in smbd(8). (This used to be commit f049fd463b087ccf4873b03675cca5eb8576af2e) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a10968749d..1ff03174fe 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -245,7 +245,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ continue; } - for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) { + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0) { continue; @@ -285,7 +285,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ num_interfaces = 1; - for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) { + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0) continue; /* open an incoming socket */ -- cgit From 54abd2aa66069e6baf7769c496f46d9dba18db39 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 30 Sep 2005 17:13:37 +0000 Subject: r10656: BIG merge from trunk. Features not copied over * \PIPE\unixinfo * winbindd's {group,alias}membership new functions * winbindd's lookupsids() functionality * swat (trunk changes to be reverted as per discussion with Deryck) (This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3) --- source3/smbd/blocking.c | 24 +- source3/smbd/change_trust_pw.c | 17 +- source3/smbd/chgpasswd.c | 4 +- source3/smbd/close.c | 87 +-- source3/smbd/conn.c | 2 +- source3/smbd/connection.c | 8 +- source3/smbd/error.c | 23 +- source3/smbd/files.c | 33 +- source3/smbd/mangle_hash2.c | 4 +- source3/smbd/message.c | 11 +- source3/smbd/nttrans.c | 29 +- source3/smbd/open.c | 879 ++++++++++++-------------- source3/smbd/oplock.c | 1331 ++++++++++------------------------------ source3/smbd/oplock_irix.c | 51 +- source3/smbd/oplock_linux.c | 56 +- source3/smbd/process.c | 457 ++++++++------ source3/smbd/reply.c | 133 ++-- source3/smbd/server.c | 11 +- source3/smbd/sesssetup.c | 70 ++- source3/smbd/trans2.c | 132 +--- 20 files changed, 1243 insertions(+), 2119 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 72d021d4e6..805e45f6ea 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -80,7 +80,8 @@ static BOOL in_chained_smb(void) return (chain_size != 0); } -static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); +static void received_unlock_msg(int msg_type, struct process_id src, + void *buf, size_t len); /**************************************************************************** Function to push a blocking lock request onto the lock queue. @@ -127,7 +128,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, /* Add a pending lock record for this. */ status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - lock_pid, sys_getpid(), blr->fsp->conn->cnum, + lock_pid, procid_self(), blr->fsp->conn->cnum, offset, count, PENDING_LOCK, &my_lock_ctx); if (!NT_STATUS_IS_OK(status)) { @@ -351,8 +352,8 @@ static BOOL process_lockread(blocking_lock_record *blr) SSVAL(p,0,nread); p += 2; set_message_end(outbuf, p+nread); - DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", - fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) ); + DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%lu nread=%ld\n", + fsp->fsp_name, fsp->fnum, (unsigned long)numtoread, (long)nread ) ); send_blocking_reply(outbuf,outsize); return True; @@ -526,7 +527,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->lock_pid, procid_self(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); @@ -552,7 +553,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->lock_pid, procid_self(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); } @@ -563,7 +564,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); Set a flag as an unlock request affects one of our pending locks. *****************************************************************************/ -static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len) +static void received_unlock_msg(int msg_type, struct process_id src, + void *buf, size_t len) { DEBUG(10,("received_unlock_msg\n")); process_blocking_lock_queue(time(NULL)); @@ -641,7 +643,7 @@ void process_blocking_lock_queue(time_t t) fsp->fnum, fsp->fsp_name )); brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -658,7 +660,7 @@ void process_blocking_lock_queue(time_t t) blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); @@ -673,7 +675,7 @@ void process_blocking_lock_queue(time_t t) blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); @@ -690,7 +692,7 @@ void process_blocking_lock_queue(time_t t) if(blocking_lock_record_process(blr)) { brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 1178400e4d..738d12151d 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -33,7 +33,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct in_addr pdc_ip; fstring dc_name; - struct cli_state *cli; + struct cli_state *cli = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n", domain)); @@ -71,20 +72,18 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(cli, PI_NETLOGON) == False) { + /* Shouldn't we open this with schannel ? JRA. */ + + netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &nt_status); + if (!netlogon_pipe) { DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", - dc_name, cli_errstr(cli))); - cli_nt_session_close(cli); - cli_ulogoff(cli); + dc_name, nt_errstr(nt_status))); cli_shutdown(cli); - nt_status = NT_STATUS_UNSUCCESSFUL; goto failed; } - nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, domain); + nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain); - cli_nt_session_close(cli); - cli_ulogoff(cli); cli_shutdown(cli); failed: diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 374c57a083..c1168583ae 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -946,7 +946,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) int i; uint32 pwHisLen, curr_pwHisLen; - account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen); if (pwHisLen == 0) { return False; } @@ -1017,7 +1017,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw return NT_STATUS_ACCOUNT_RESTRICTION; } - if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { + if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { DEBUG(1, ("user %s cannot change password - password too short\n", username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); diff --git a/source3/smbd/close.c b/source3/smbd/close.c index afc645ca06..becca003b6 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -110,31 +110,30 @@ static int close_filestruct(files_struct *fsp) If any deferred opens are waiting on this close, notify them. ****************************************************************************/ -static void notify_deferred_opens(files_struct *fsp) +static void notify_deferred_opens(struct share_mode_lock *lck) { - deferred_open_entry *de_array = NULL; - int num_de_entries, i; - pid_t mypid = sys_getpid(); - - if (!lp_defer_sharing_violations()) { - return; - } - - num_de_entries = get_deferred_opens(fsp->conn, fsp->dev, fsp->inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid) { - /* - * We need to notify ourself to retry the open. - * Do this by finding the queued SMB record, moving it - * to the head of the queue and changing the wait time to zero. - */ - schedule_sharing_violation_open_smb_message(entry->mid); - } else { - send_deferred_open_retry_message(entry); - } - } - SAFE_FREE(de_array); + int i; + + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + + if (!is_deferred_open_entry(e)) { + continue; + } + + if (procid_is_me(&e->pid)) { + /* + * We need to notify ourself to retry the open. Do + * this by finding the queued SMB record, moving it to + * the head of the queue and changing the wait time to + * zero. + */ + schedule_deferred_open_smb_message(e->op_mid); + } else { + message_send_pid(e->pid, MSG_SMB_OPEN_RETRY, + e, sizeof(*e), True); + } + } } /**************************************************************************** @@ -148,13 +147,12 @@ static void notify_deferred_opens(files_struct *fsp) static int close_normal_file(files_struct *fsp, BOOL normal_close) { - share_mode_entry *share_entry = NULL; - size_t share_entry_count = 0; BOOL delete_file = False; connection_struct *conn = fsp->conn; int saved_errno = 0; int err = 0; int err1 = 0; + struct share_mode_lock *lck; remove_pending_lock_requests_by_fid(fsp); @@ -194,23 +192,34 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * This prevents race conditions with the file being created. JRA. */ - lock_share_entry_fsp(fsp); - - share_entry_count = del_share_mode(fsp, &share_entry, - &delete_file); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); - DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n", - (unsigned long)share_entry_count, fsp->fsp_name )); + if (lck == NULL) { + DEBUG(0, ("Could not get share mode lock\n")); + return EINVAL; + } - if (share_entry_count != 0) { - /* We're not the last ones -- don't delete */ - delete_file = False; + if (!del_share_mode(lck, fsp)) { + DEBUG(0, ("Could not delete share entry\n")); } - SAFE_FREE(share_entry); + delete_file = lck->delete_on_close; + + if (delete_file) { + int i; + /* See if others still have the file open. If this is the + * case, then don't delete */ + for (i=0; inum_share_modes; i++) { + if (is_valid_share_mode_entry(&lck->share_modes[i])) { + delete_file = False; + break; + } + } + } /* Notify any deferred opens waiting on this close. */ - notify_deferred_opens(fsp); + notify_deferred_opens(lck); + reply_to_oplock_break_requests(fsp); /* * NT can set delete_on_close of the last open @@ -234,7 +243,7 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); process_pending_change_notify_queue((time_t)0); } - unlock_share_entry_fsp(fsp); + talloc_free(lck); if(fsp->oplock_type) release_file_oplock(fsp); @@ -296,7 +305,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) */ if (normal_close && - get_delete_on_close_flag(fsp->dev, fsp->inode)) { + get_delete_on_close_flag(fsp->dev, fsp->inode, fsp->fsp_name)) { BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", fsp->fsp_name, ok ? "succeeded" : "failed" )); diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index b69868ecec..bb000bac30 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -287,7 +287,7 @@ the message contains just a share name and all instances of that share are unmounted the special sharename '*' forces unmount of all shares ****************************************************************************/ -void msg_force_tdis(int msg_type, pid_t pid, void *buf, size_t len) +void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len) { connection_struct *conn, *next; fstring sharename; diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 32e2f058fc..07d3181144 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -38,7 +38,7 @@ TDB_CONTEXT *conn_tdb_ctx(void) static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey) { ZERO_STRUCTP(pkey); - pkey->pid = sys_getpid(); + pkey->pid = procid_self(); pkey->cnum = conn?conn->cnum:-1; fstrcpy(pkey->name, name); #ifdef DEVELOPER @@ -107,8 +107,8 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u /* If the pid was not found delete the entry from connections.tdb */ if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) { - DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", - (unsigned int)crec.pid, crec.cnum, crec.name)); + DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", + procid_str_static(&crec.pid), crec.cnum, crec.name)); if (tdb_delete(the_tdb, kbuf) != 0) DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) )); return 0; @@ -174,7 +174,7 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti /* fill in the crec */ ZERO_STRUCT(crec); crec.magic = 0x280267; - crec.pid = sys_getpid(); + crec.pid = procid_self(); crec.cnum = conn?conn->cnum:-1; if (conn) { crec.uid = conn->uid; diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 090a2f6d81..3cdcae5c7f 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -41,23 +41,22 @@ void set_saved_error_triple(int eclass, int ecode, NTSTATUS status) override_ERR_ntstatus = status; } +void set_saved_ntstatus(NTSTATUS status) +{ + uint8 tmp_eclass; /* Hmmm. override_ERR_class is not uint8... */ + override_ERR_ntstatus = status; + ntstatus_to_dos(status, &tmp_eclass, &override_ERR_code); + override_ERR_class = tmp_eclass; + +} + /**************************************************************************** Return the current settings of the error triple. Return True if any are set. ****************************************************************************/ -BOOL get_saved_error_triple(int *peclass, int *pecode, NTSTATUS *pstatus) +NTSTATUS get_saved_ntstatus(void) { - if (peclass) { - *peclass = override_ERR_class; - } - if (pecode) { - *pecode = override_ERR_code; - } - if (pstatus) { - *pstatus = override_ERR_ntstatus; - } - - return (override_ERR_class || !NT_STATUS_IS_OK(override_ERR_ntstatus)); + return override_ERR_ntstatus; } /**************************************************************************** diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 65986e9612..181e17b11f 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -65,7 +65,7 @@ files_struct *file_new(connection_struct *conn) { int i; static int first_file; - files_struct *fsp, *next; + files_struct *fsp; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to @@ -76,32 +76,21 @@ files_struct *file_new(connection_struct *conn) first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; } + /* TODO: Port the id-tree implementation from Samba4 */ + i = bitmap_find(file_bmap, first_file); if (i == -1) { - /* - * Before we give up, go through the open files - * and see if there are any files opened with a - * batch oplock. If so break the oplock and then - * re-use that entry (if it becomes closed). - * This may help as NT/95 clients tend to keep - * files batch oplocked for quite a long time - * after they have finished with them. - */ - for (fsp=Files;fsp;fsp=next) { - next=fsp->next; - if (attempt_close_oplocked_file(fsp)) { - return file_new(conn); - } - } - DEBUG(0,("ERROR! Out of file structures\n")); - set_saved_error_triple(ERRSRV, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES); + /* TODO: We have to unconditionally return a DOS error here, + * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with + * NTSTATUS negotiated */ + set_saved_ntstatus(NT_STATUS_TOO_MANY_OPENED_FILES); return NULL; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { - set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY); + set_saved_ntstatus(NT_STATUS_NO_MEMORY); return NULL; } @@ -110,7 +99,7 @@ files_struct *file_new(connection_struct *conn) fsp->fh = SMB_MALLOC_P(struct fd_handle); if (!fsp->fh) { SAFE_FREE(fsp); - set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY); + set_saved_ntstatus(NT_STATUS_NO_MEMORY); return NULL; } @@ -293,7 +282,9 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i DLIST_PROMOTE(Files, fsp); } /* Paranoia check. */ - if (fsp->fh->fd == -1 && fsp->oplock_type != NO_OPLOCK) { + if ((fsp->fh->fd == -1) && + (fsp->oplock_type != NO_OPLOCK) && + (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \ oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, (unsigned int)fsp->file_id, diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 613dda9a16..335ba8e2ef 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -212,7 +212,7 @@ static BOOL is_mangled_component(const char *name, size_t len) { unsigned int i; - M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len)); + M_DEBUG(10,("is_mangled_component %s (len %lu) ?\n", name, (unsigned long)len)); /* check the length */ if (len > 12 || len < 8) @@ -250,7 +250,7 @@ static BOOL is_mangled_component(const char *name, size_t len) } } - M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len)); + M_DEBUG(10,("is_mangled_component %s (len %lu) -> yes\n", name, (unsigned long)len)); return True; } diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 5af7d3e451..e975da3e15 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -43,6 +43,7 @@ static void msg_deliver(void) int fd; char *msg; int len; + ssize_t sz; if (! (*lp_msg_command())) { @@ -70,14 +71,20 @@ static void msg_deliver(void) if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { i++; continue; } - write(fd, &msgbuf[i++], 1); + sz = write(fd, &msgbuf[i++], 1); + if ( sz != 1 ) { + DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); + } } } else { for (i = 0; i < len;) { if (msg[i] == '\r' && i < (len-1) && msg[i+1] == '\n') { i++; continue; } - write(fd, &msg[i++],1); + sz = write(fd, &msg[i++],1); + if ( sz != 1 ) { + DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); + } } SAFE_FREE(msg); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f9b70de0ac..3db55bad14 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -24,7 +24,6 @@ extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; -extern int global_oplock_break; extern struct current_user current_user; static const char *known_nt_pipes[] = { @@ -43,6 +42,7 @@ static const char *known_nt_pipes[] = { "\\rpcecho", "\\svcctl", "\\eventlog", + "\\unixinfo", NULL }; @@ -861,7 +861,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", } else { SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN); } - } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); } else { SCVAL(p,0,NO_OPLOCK_RETURN); @@ -1666,11 +1666,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &info); if (!fsp1) { - get_saved_error_triple(NULL, NULL, &status); + status = get_saved_ntstatus(); if (NT_STATUS_IS_OK(status)) { status = NT_STATUS_ACCESS_DENIED; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return status; } @@ -1684,11 +1684,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &info); if (!fsp2) { - get_saved_error_triple(NULL, NULL, &status); + status = get_saved_ntstatus(); if (NT_STATUS_IS_OK(status)) { status = NT_STATUS_ACCESS_DENIED; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); close_file(fsp1,False); return status; } @@ -1989,7 +1989,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i return(UNIXERROR(ERRDOS,ERRnoaccess)); } - DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size)); + DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); SIVAL(params,0,(uint32)sd_size); @@ -2743,21 +2743,6 @@ int reply_nttrans(connection_struct *conn, uint32 num_params_sofar, num_data_sofar; START_PROFILE(SMBnttrans); - if(global_oplock_break && - ((function_code == NT_TRANSACT_CREATE) || - (function_code == NT_TRANSACT_RENAME))) { - /* - * Queue this open message as we are the process of an oplock break. - */ - - DEBUG(2,("reply_nttrans: queueing message code 0x%x \ -due to being in oplock break state.\n", (unsigned int)function_code )); - - push_oplock_pending_smb_message( inbuf, length); - END_PROFILE(SMBnttrans); - return -1; - } - if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { END_PROFILE(SMBnttrans); return ERROR_DOS(ERRSRV,ERRaccess); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ed847826d5..56d31c6940 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -24,11 +24,11 @@ extern struct current_user current_user; extern userdom_struct current_user_info; -extern uint16 global_oplock_port; extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; -struct dev_inode_bundle { +struct deferred_open_record { + BOOL delayed_for_oplocks; SMB_DEV_T dev; SMB_INO_T inode; }; @@ -208,7 +208,6 @@ static BOOL open_file(files_struct *fsp, BOOL file_existed = VALID_STAT(*psbuf); fsp->fh->fd = -1; - fsp->oplock_type = NO_OPLOCK; errno = EPERM; /* Check permissions */ @@ -283,8 +282,7 @@ static BOOL open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && ms_has_wild(fname)) { - set_saved_error_triple(ERRDOS, ERRinvalidname, - NT_STATUS_OBJECT_NAME_INVALID); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID); return False; } @@ -354,7 +352,6 @@ static BOOL open_file(files_struct *fsp, } fsp->print_file = False; fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; @@ -397,7 +394,7 @@ static BOOL is_executable(const char *fname) Returns True if conflict, False if not. ****************************************************************************/ -static BOOL share_conflict(share_mode_entry *entry, +static BOOL share_conflict(struct share_mode_entry *entry, uint32 access_mask, uint32 share_access) { @@ -445,7 +442,6 @@ static BOOL share_conflict(share_mode_entry *entry, DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ (unsigned int)(share) )); \ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ return True; \ } #else @@ -454,7 +450,6 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ (unsigned int)(share) )); \ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ return True; \ } #endif @@ -480,11 +475,23 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u #if defined(DEVELOPER) static void validate_my_share_entries(int num, - share_mode_entry *share_entry) + struct share_mode_entry *share_entry) { files_struct *fsp; - if (share_entry->pid != sys_getpid()) { + if (!procid_is_me(&share_entry->pid)) { + return; + } + + if (is_deferred_open_entry(share_entry) && + !open_was_deferred(share_entry->op_mid)) { + pstring str; + DEBUG(0, ("Got a deferred entry without a request: " + "PANIC: %s\n", share_mode_str(num, share_entry))); + smb_panic(str); + } + + if (!is_valid_share_mode_entry(share_entry)) { return; } @@ -497,7 +504,26 @@ static void validate_my_share_entries(int num, "share entry with an open file\n"); } + if (is_deferred_open_entry(share_entry) || + is_unused_share_mode_entry(share_entry)) { + goto panic; + } + + if ((share_entry->op_type == NO_OPLOCK) && + (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK)) { + /* Someone has already written to it, but I haven't yet + * noticed */ + return; + } + if (((uint16)fsp->oplock_type) != share_entry->op_type) { + goto panic; + } + + return; + + panic: + { pstring str; DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); @@ -510,375 +536,217 @@ static void validate_my_share_entries(int num, } #endif -struct share_mode_entry_list { - struct share_mode_entry_list *next, *prev; - share_mode_entry entry; -}; - -static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_list) +static BOOL is_stat_open(uint32 access_mask) { - while (broken_entry_list) { - struct share_mode_entry_list *broken_entry = broken_entry_list; - DLIST_REMOVE(broken_entry_list, broken_entry); - SAFE_FREE(broken_entry); - } -} - -static BOOL cause_oplock_break(int request, int existing, uint32 access_mask) -{ - if ((access_mask == DELETE_ACCESS) && - (request == NO_OPLOCK)) { - /* This is a delete request */ - return (BATCH_OPLOCK_TYPE(existing) != 0); - } - - if (EXCLUSIVE_OPLOCK_TYPE(existing) && (request != NO_OPLOCK)) { - return True; - } - - if ((existing != NO_OPLOCK) && (request == NO_OPLOCK)) { - return True; - } - - return False; + return (access_mask && + ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES))==0) && + ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES)) != 0)); } /**************************************************************************** - Deal with open deny mode and oplock break processing. + Deal with share modes Invarient: Share mode must be locked on entry and exit. Returns -1 on error, or number of share modes on success (may be zero). ****************************************************************************/ -static int open_mode_check(connection_struct *conn, - const char *fname, - SMB_DEV_T dev, - SMB_INO_T inode, - uint32 access_mask, - uint32 share_access, - uint32 create_options, - int *p_oplock_request, - BOOL *p_all_current_opens_are_level_II) +static NTSTATUS open_mode_check(connection_struct *conn, + const char *fname, + struct share_mode_lock *lck, + uint32 access_mask, + uint32 share_access, + uint32 create_options, + BOOL *file_existed) { int i; - int num_share_modes; - int oplock_contention_count = 0; - share_mode_entry *old_shares = NULL; - BOOL broke_oplock; - BOOL delete_on_close; - num_share_modes = get_share_modes(dev, inode, &old_shares, &delete_on_close); - - if(num_share_modes == 0) { - SAFE_FREE(old_shares); - return 0; + if(lck->num_share_modes == 0) { + return NT_STATUS_OK; } + + *file_existed = True; - if (access_mask && - ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| - FILE_WRITE_ATTRIBUTES))==0) && - ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| - FILE_WRITE_ATTRIBUTES)) != 0)) { + if (is_stat_open(access_mask)) { /* Stat open that doesn't trigger oplock breaks or share mode * checks... ! JRA. */ - SAFE_FREE(old_shares); - return num_share_modes; + return NT_STATUS_OK; } /* A delete on close prohibits everything */ - if (delete_on_close) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; + if (lck->delete_on_close) { + return NT_STATUS_DELETE_PENDING; } /* * Check if the share modes will give us access. */ - do { - struct share_mode_entry_list *broken_entry_list = NULL; - struct share_mode_entry_list *broken_entry = NULL; - - broke_oplock = False; - *p_all_current_opens_are_level_II = True; - - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - BOOL opb_ret; - #if defined(DEVELOPER) - validate_my_share_entries(i, share_entry); + for(i = 0; i < lck->num_share_modes; i++) { + validate_my_share_entries(i, &lck->share_modes[i]); + } #endif - /* - * By observation of NetBench, oplocks are broken - * *before* share modes are checked. This allows a - * file to be closed by the client if the share mode - * would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so - * we must break it before continuing. - */ + if (!lp_share_modes(SNUM(conn))) { + return NT_STATUS_OK; + } - if (!cause_oplock_break(*p_oplock_request, - share_entry->op_type, - access_mask)) { - if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - *p_all_current_opens_are_level_II = False; - } - continue; - } + /* Now we check the share modes, after any oplock breaks. */ + for(i = 0; i < lck->num_share_modes; i++) { - /* This is an oplock break */ - - DEBUG(5,("open_mode_check: oplock_request = %d, " - "breaking oplock (%x) on file %s, " - "dev = %x, inode = %.0f\n", - *p_oplock_request, share_entry->op_type, - fname, (unsigned int)dev, (double)inode)); - - /* Ensure the reply for the open uses the correct - * sequence number. */ - /* This isn't a real deferred packet as it's response - * will also increment the sequence. - */ - srv_defer_sign_response(get_current_mid()); - - /* Oplock break - unlock to request it. */ - unlock_share_entry(conn, dev, inode); - - opb_ret = request_oplock_break(share_entry); - - /* Now relock. */ - lock_share_entry(conn, dev, inode); - - if (!opb_ret) { - DEBUG(0,("open_mode_check: FAILED when breaking " - "oplock (%x) on file %s, dev = %x, " - "inode = %.0f\n", - old_shares[i].op_type, fname, - (unsigned int)dev, (double)inode)); - SAFE_FREE(old_shares); - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return -1; - } - - broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); - if (!broken_entry) { - smb_panic("open_mode_check: malloc fail.\n"); - } - broken_entry->entry = *share_entry; - DLIST_ADD(broken_entry_list, broken_entry); - broke_oplock = True; - - } /* end for */ - - if (broke_oplock) { - /* Update the current open table. */ - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(dev, inode, - &old_shares, - &delete_on_close); + if (!is_valid_share_mode_entry(&lck->share_modes[i])) { + continue; } - if (lp_share_modes(SNUM(conn))) { - /* Now we check the share modes, after any oplock breaks. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - /* someone else has a share lock on it, check to see - * if we can too */ - if (share_conflict(share_entry, access_mask, - share_access)) { - SAFE_FREE(old_shares); - free_broken_entry_list(broken_entry_list); - errno = EACCES; - return -1; - } - } + /* someone else has a share lock on it, check to see if we can + * too */ + if (share_conflict(&lck->share_modes[i], + access_mask, share_access)) { + return NT_STATUS_SHARING_VIOLATION; } - - for(broken_entry = broken_entry_list; broken_entry; - broken_entry = broken_entry->next) { - oplock_contention_count++; - - /* Paranoia check that this is no longer an exlusive entry. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - if (!(share_modes_identical(&broken_entry->entry, - share_entry) && - EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type))) { - continue; - } - - /* - * This should not happen. The target left this oplock - * as exlusive.... The process *must* be dead.... - */ - - DEBUG(0,("open_mode_check: exlusive oplock left by " - "process %d after break ! For file %s, " - "dev = %x, inode = %.0f. Deleting it to " - "continue...\n", - (int)broken_entry->entry.pid, fname, - (unsigned int)dev, (double)inode)); - - if (process_exists(broken_entry->entry.pid)) { - DEBUG(0,("open_mode_check: Existent process " - "%lu left active oplock.\n", - (unsigned long)broken_entry->entry.pid )); - } - - if (del_share_entry(dev, inode, &broken_entry->entry, - NULL, &delete_on_close) == -1) { - free_broken_entry_list(broken_entry_list); - errno = EACCES; - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return -1; - } - - /* - * We must reload the share modes after deleting the - * other process's entry. - */ - - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(dev, inode, - &old_shares, - &delete_on_close); - break; - } /* end for paranoia... */ - } /* end for broken_entry */ - free_broken_entry_list(broken_entry_list); - } while(broke_oplock); - - /* - * Refuse to grant an oplock in case the contention limit is - * reached when going through the lock list multiple times. - */ - - if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) { - *p_oplock_request = 0; - DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n", - oplock_contention_count )); } - SAFE_FREE(old_shares); - return num_share_modes; + return NT_STATUS_OK; } -/**************************************************************************** - Delete the record for a handled deferred open entry. -****************************************************************************/ +static BOOL is_delete_request(files_struct *fsp) { + return ((fsp->access_mask == DELETE_ACCESS) && + (fsp->oplock_type == NO_OPLOCK)); +} -static void delete_defered_open_entry_record(connection_struct *conn, - SMB_DEV_T dev, - SMB_INO_T inode) +/* + * 1) No files open at all: Grant whatever the client wants. + * + * 2) Exclusive (or batch) oplock around: If the requested access is a delete + * request, break if the oplock around is a batch oplock. If it's another + * requested access type, break. + * + * 3) Only level2 around: Grant level2 and do nothing else. + */ + +static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) { - uint16 mid = get_current_mid(); - pid_t mypid = sys_getpid(); - deferred_open_entry *de_array = NULL; - int num_de_entries, i; + int i, num_level2; + struct share_mode_entry *exclusive = NULL; + BOOL delay_it = False; + BOOL have_level2 = False; - if (!lp_defer_sharing_violations()) { - return; + if (is_stat_open(fsp->access_mask)) { + fsp->oplock_type = NO_OPLOCK; + return False; } - num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid && entry->mid == mid && entry->dev == dev && - entry->inode == inode) { + num_level2 = 0; - /* Remove the deferred open entry from the array. */ - delete_deferred_open_entry(entry); - SAFE_FREE(de_array); - return; + if (lck->num_share_modes == 0) { + /* No files open at all: Directly grant whatever the client + * wants. */ + + if (fsp->oplock_type == NO_OPLOCK) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + return False; + } + + for (i=0; inum_share_modes; i++) { + + if (!is_valid_share_mode_entry(&lck->share_modes[i])) { + continue; + } + + if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { + SMB_ASSERT(exclusive == NULL); + exclusive = &lck->share_modes[i]; + } + + if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { + have_level2 = True; } } - SAFE_FREE(de_array); + + if (exclusive != NULL) { /* Found an exclusive oplock */ + SMB_ASSERT(!have_level2); + delay_it = is_delete_request(fsp) ? + BATCH_OPLOCK_TYPE(exclusive->op_type) : True; + } + + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + /* We can at most grant level2 */ + fsp->oplock_type = LEVEL_II_OPLOCK; + } + + if ((fsp->oplock_type == NO_OPLOCK) && have_level2) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + + if (delay_it) { + DEBUG(10, ("Sending break request to PID %s\n", + procid_str_static(&exclusive->pid))); + exclusive->op_mid = get_current_mid(); + if (!message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + exclusive, sizeof(*exclusive), True)) { + DEBUG(3, ("Could not send oplock break message\n")); + } + file_free(fsp); + } + + return delay_it; +} + +static BOOL request_timed_out(struct timeval request_time, + struct timeval timeout) +{ + struct timeval now, end_time; + GetTimeOfDay(&now); + end_time = timeval_sum(&request_time, &timeout); + return (timeval_compare(&end_time, &now) < 0); } /**************************************************************************** Handle the 1 second delay in returning a SHARING_VIOLATION error. ****************************************************************************/ -static void defer_open_sharing_error(connection_struct *conn, - struct timeval *ptv, - const char *fname, - SMB_DEV_T dev, - SMB_INO_T inode) +static void defer_open(struct share_mode_lock *lck, + struct timeval request_time, + struct timeval timeout, + struct deferred_open_record *state) { uint16 mid = get_current_mid(); - pid_t mypid = sys_getpid(); - deferred_open_entry *de_array = NULL; - int num_de_entries, i; - struct dev_inode_bundle dib; + int i; - if (!lp_defer_sharing_violations()) { - return; - } + /* Paranoia check */ - dib.dev = dev; - dib.inode = inode; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; - num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid && entry->mid == mid) { - /* - * Check if a 1 second timeout has expired. - */ - if (usec_time_diff(ptv, &entry->time) > - SHARING_VIOLATION_USEC_WAIT) { - DEBUG(10,("defer_open_sharing_error: Deleting " - "deferred open entry for mid %u, " - "file %s\n", - (unsigned int)mid, fname )); - - /* Expired, return a real error. */ - /* Remove the deferred open entry from the array. */ - - delete_deferred_open_entry(entry); - SAFE_FREE(de_array); - return; - } - /* - * If the timeout hasn't expired yet and we still have - * a sharing violation, just leave the entry in the - * deferred open array alone. We do need to reschedule - * this open call though (with the original created - * time). - */ - DEBUG(10,("defer_open_sharing_error: time [%u.%06u] " - "updating deferred open entry for mid %u, file %s\n", - (unsigned int)entry->time.tv_sec, - (unsigned int)entry->time.tv_usec, - (unsigned int)mid, fname )); - - push_sharing_violation_open_smb_message(&entry->time, - (char *)&dib, - sizeof(dib)); - SAFE_FREE(de_array); - return; + if (!is_deferred_open_entry(e)) { + continue; + } + + if (procid_is_me(&e->pid) && (e->op_mid == mid)) { + DEBUG(0, ("Trying to defer an already deferred " + "request: mid=%d, exiting\n", mid)); + exit_server("exiting"); } } + /* End paranoia check */ + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " - "open entry for mid %u, file %s\n", - (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, - (unsigned int)mid, fname )); + "open entry for mid %u\n", + (unsigned int)request_time.tv_sec, + (unsigned int)request_time.tv_usec, + (unsigned int)mid)); - if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) { - SAFE_FREE(de_array); - return; - } - if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) { - remove_sharing_violation_open_smb_message(mid); + if (!push_deferred_smb_message(mid, request_time, timeout, + (char *)state, sizeof(*state))) { + exit_server("push_deferred_smb_message failed\n"); } + add_deferred_open(lck, mid, request_time, state->dev, state->inode); /* * Push the MID of this packet on the signing queue. @@ -888,8 +756,6 @@ static void defer_open_sharing_error(connection_struct *conn, */ srv_defer_sign_response(mid); - - SAFE_FREE(de_array); } /**************************************************************************** @@ -1196,8 +1062,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; - int num_share_modes = 0; - BOOL all_current_opens_are_level_II = False; BOOL fsp_open = False; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; @@ -1205,8 +1069,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, int info; uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; - uint16 port = 0; uint16 mid = get_current_mid(); + BOOL delayed_for_oplocks = False; + struct timeval request_time = timeval_zero(); + struct share_mode_lock *lck = NULL; + NTSTATUS status; if (conn->printer) { /* @@ -1241,9 +1108,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if ((pml = get_open_deferred_message(mid)) != NULL) { - struct dev_inode_bundle dib; + struct deferred_open_record *state = + (struct deferred_open_record *)pml->private_data.data; - memcpy(&dib, pml->private_data.data, sizeof(dib)); + request_time = pml->request_time; + delayed_for_oplocks = state->delayed_for_oplocks; /* There could be a race condition where the dev/inode pair has changed since we deferred the message. If so, just @@ -1255,24 +1124,18 @@ files_struct *open_file_ntcreate(connection_struct *conn, notified of a close and we don't want to trigger another spurious oplock break. */ - if (!file_existed || dib.dev != psbuf->st_dev || - dib.inode != psbuf->st_ino || pml->msg_time.tv_sec || - pml->msg_time.tv_usec) { - /* Ensure we don't reprocess this message. */ - remove_sharing_violation_open_smb_message(mid); - - /* Now remove the deferred open entry under lock. */ - lock_share_entry(conn, dib.dev, dib.inode); - delete_defered_open_entry_record(conn, dib.dev, - dib.inode); - unlock_share_entry(conn, dib.dev, dib.inode); - - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return NULL; + /* Now remove the deferred open entry under lock. */ + lck = get_share_mode_lock(NULL, state->dev, state->inode, + fname); + if (lck == NULL) { + DEBUG(0, ("could not get share mode lock\n")); + } else { + del_deferred_open_entry(lck, mid); + talloc_destroy(lck); } + /* Ensure we don't reprocess this message. */ - remove_sharing_violation_open_smb_message(mid); + remove_deferred_open_smb_message(mid); } if (!check_name(fname,conn)) { @@ -1285,7 +1148,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, } /* ignore any oplock requests if oplocks are disabled */ - if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { + if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || + IS_VETO_OPLOCK_PATH(conn, fname)) { oplock_request = 0; } @@ -1325,7 +1189,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OPEN " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; return NULL; } @@ -1338,7 +1202,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; return NULL; } @@ -1369,8 +1233,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, break; default: - set_saved_error_triple(ERRDOS, ERRinvalidparam, - NT_STATUS_INVALID_PARAMETER); + set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } @@ -1447,8 +1310,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: write access requested for " "file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - set_saved_error_triple(ERRDOS, ERRnoaccess, - NT_STATUS_ACCESS_DENIED); + set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); errno = EACCES; return NULL; } @@ -1458,45 +1320,96 @@ files_struct *open_file_ntcreate(connection_struct *conn, return NULL; } + fsp->dev = psbuf->st_dev; + fsp->inode = psbuf->st_ino; + fsp->share_access = share_access; + fsp->fh->private_options = create_options; + fsp->access_mask = access_mask; + fsp->oplock_type = oplock_request; + + if (timeval_is_zero(&request_time)) { + request_time = fsp->open_time; + } + if (file_existed) { dev = psbuf->st_dev; inode = psbuf->st_ino; - lock_share_entry(conn, dev, inode); - - num_share_modes = open_mode_check(conn, fname, dev, inode, - access_mask, share_access, - create_options, - &oplock_request, - &all_current_opens_are_level_II); - if(num_share_modes == -1) { - - if (!internal_only_open) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* Check if this can be done with the - * deny_dos and fcb calls. */ - if (create_options & - (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| - NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { - files_struct *fsp_dup; - fsp_dup = fcb_or_dos_open(conn, fname, dev, - inode, access_mask, - share_access, - create_options); - - if (fsp_dup) { - unlock_share_entry(conn, dev, inode); - file_free(fsp); - if (pinfo) { - *pinfo = FILE_WAS_OPENED; - } - conn->num_files_open++; - return fsp_dup; - } + lck = get_share_mode_lock(NULL, dev, inode, fname); + + if (lck == NULL) { + DEBUG(0, ("Could not get share mode lock\n")); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + return NULL; + } + + if (delay_for_oplocks(lck, fsp)) { + struct deferred_open_record state; + struct timeval timeout; + + if (delayed_for_oplocks) { + DEBUG(0, ("Trying to delay for oplocks " + "twice\n")); + exit_server("exiting"); + } + + timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + + /* Normally the smbd we asked should respond within + * OPLOCK_BREAK_TIMEOUT seconds regardless of whether + * the client did, give twice the timeout as a safety + * measure here in case the other smbd is stuck + * somewhere else. */ + + state.delayed_for_oplocks = True; + state.dev = dev; + state.inode = inode; + + if (!request_timed_out(request_time, timeout)) { + defer_open(lck, request_time, timeout, + &state); + } + + talloc_free(lck); + return NULL; + } + + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); + + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + /* DELETE_PENDING is not deferred for a second */ + set_saved_ntstatus(status); + talloc_free(lck); + file_free(fsp); + return NULL; + } + + if (!NT_STATUS_IS_OK(status)) { + + SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); + + /* Check if this can be done with the deny_dos and fcb + * calls. */ + if (create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + files_struct *fsp_dup; + fsp_dup = fcb_or_dos_open(conn, fname, dev, + inode, access_mask, + share_access, + create_options); + + if (fsp_dup) { + talloc_free(lck); + file_free(fsp); + if (pinfo) { + *pinfo = FILE_WAS_OPENED; } + conn->num_files_open++; + return fsp_dup; } } @@ -1527,8 +1440,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!fsp_open && errno) { /* Default error. */ - set_saved_error_triple(ERRDOS, ERRnoaccess, - NT_STATUS_ACCESS_DENIED); + set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); } /* @@ -1536,27 +1448,32 @@ files_struct *open_file_ntcreate(connection_struct *conn, * cope with the braindead 1 second delay. */ - if (!internal_only_open) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents - * the current time of day. */ - defer_open_sharing_error(conn, - &fsp->open_time, - fname, dev, inode); + if (!internal_only_open && + lp_defer_sharing_violations()) { + struct timeval timeout; + struct deferred_open_record state; + + timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT); + + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + if (!request_timed_out(request_time, + timeout)) { + defer_open(lck, request_time, timeout, + &state); } } - unlock_share_entry(conn, dev, inode); + talloc_free(lck); if (fsp_open) { fd_close(conn, fsp); /* * We have detected a sharing violation here * so return the correct error code */ - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1567,23 +1484,28 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ } + SMB_ASSERT(!file_existed || (lck != NULL)); + /* * Ensure we pay attention to default ACLs on directories if required. */ if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && - (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) { + (def_acl = directory_has_default_acl(conn, + parent_dirname(fname)))) { unx_mode = 0777; } DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - (unsigned int)flags,(unsigned int)flags2,(unsigned int)unx_mode)); + (unsigned int)flags, (unsigned int)flags2, + (unsigned int)unx_mode)); /* * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, + access_mask); if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) { /* @@ -1602,22 +1524,23 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (!fsp_open) { - if(file_existed) { - unlock_share_entry(conn, dev, inode); + if (lck != NULL) { + talloc_free(lck); } file_free(fsp); return NULL; } - /* - * Deal with the race condition where two smbd's detect the file - * doesn't exist and do the create at the same time. One of them will - * win and set a share mode, the other (ie. this one) should check if - * the requested share mode for this create is allowed. - */ - if (!file_existed) { + /* + * Deal with the race condition where two smbd's detect the + * file doesn't exist and do the create at the same time. One + * of them will win and set a share mode, the other (ie. this + * one) should check if the requested share mode for this + * create is allowed. + */ + /* * Now the file exists and fsp is successfully opened, * fsp->dev and fsp->inode are valid and should replace the @@ -1628,70 +1551,41 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = fsp->dev; inode = fsp->inode; - lock_share_entry_fsp(fsp); - - num_share_modes = open_mode_check(conn, fname, dev, inode, - access_mask, share_access, - create_options, - &oplock_request, - &all_current_opens_are_level_II); - - if(num_share_modes == -1) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* Check if this can be done with the deny_dos - * and fcb calls. */ - if (create_options & - (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| - NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { - files_struct *fsp_dup; - fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, - access_mask, share_access, - create_options); - if (fsp_dup) { - unlock_share_entry(conn, dev, inode); - fd_close(conn, fsp); - file_free(fsp); - if (pinfo) { - *pinfo = FILE_WAS_OPENED; - } - conn->num_files_open++; - return fsp_dup; - } - } - - /* - * If we're returning a share violation, - * ensure we cope with the braindead 1 second - * delay. - */ - - /* The fsp->open_time here represents the - * current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, - fname, dev, inode); - } + lck = get_share_mode_lock(NULL, dev, inode, fname); - unlock_share_entry_fsp(fsp); - fd_close(conn,fsp); + if (lck == NULL) { + DEBUG(0, ("Coult not get share mode lock\n")); + fd_close(conn, fsp); file_free(fsp); - /* - * We have detected a sharing violation here, so - * return the correct code. - */ - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } - /* - * If there are any share modes set then the file *did* - * exist. Ensure we return the correct value for action. - */ + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); + + if (!NT_STATUS_IS_OK(status)) { + struct deferred_open_record state; - if (num_share_modes > 0) { - file_existed = True; + fd_close(conn, fsp); + file_free(fsp); + + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + /* Do it all over again immediately. In the second + * round we will find that the file existed and handle + * the DELETE_PENDING and FCB cases correctly. No need + * to duplicate the code here. Essentially this is a + * "goto top of this function", but don't tell + * anybody... */ + + defer_open(lck, request_time, timeval_zero(), + &state); + talloc_free(lck); + return NULL; } /* @@ -1699,6 +1593,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ } + SMB_ASSERT(lck != NULL); + /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of these only read them. Nobody but Samba can ever set a deny @@ -1725,7 +1621,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { - unlock_share_entry_fsp(fsp); + talloc_free(lck); fd_close(conn,fsp); file_free(fsp); return NULL; @@ -1761,20 +1657,14 @@ files_struct *open_file_ntcreate(connection_struct *conn, * file structs. */ - if(oplock_request && (num_share_modes == 0) && - !IS_VETO_OPLOCK_PATH(conn,fname) && - set_file_oplock(fsp, oplock_request) ) { - port = global_oplock_port; - } else if (oplock_request && all_current_opens_are_level_II) { - port = global_oplock_port; - oplock_request = LEVEL_II_OPLOCK; - set_file_oplock(fsp, oplock_request); - } else { - port = 0; - oplock_request = 0; + if ((fsp->oplock_type != NO_OPLOCK) && + (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { + if (!set_file_oplock(fsp, fsp->oplock_type)) { + /* Could not get the kernel oplock */ + fsp->oplock_type = NO_OPLOCK; + } } - - set_share_mode(fsp, port, oplock_request); + set_share_mode(lck, fsp, 0, fsp->oplock_type); if (create_options & FILE_DELETE_ON_CLOSE) { uint32 dosattr= existing_dos_attributes; @@ -1788,19 +1678,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, result = can_set_delete_on_close(fsp, True, dosattr); if (!NT_STATUS_IS_OK(result)) { - uint8 u_e_c; - uint32 u_e_code; - BOOL dummy_del_on_close; /* Remember to delete the mode we just added. */ - del_share_mode(fsp, NULL, &dummy_del_on_close); - unlock_share_entry_fsp(fsp); + del_share_mode(lck, fsp); + talloc_free(lck); fd_close(conn,fsp); file_free(fsp); - ntstatus_to_dos(result, &u_e_c, &u_e_code); - set_saved_error_triple(u_e_c, u_e_code, result); + set_saved_ntstatus(result); return NULL; } - set_delete_on_close(fsp, True); + lck->delete_on_close = True; + lck->modified = True; } if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || @@ -1860,8 +1747,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* If this is a successful open, we must remove any deferred open * records. */ - delete_defered_open_entry_record(conn, fsp->dev, fsp->inode); - unlock_share_entry_fsp(fsp); + del_deferred_open_entry(lck, mid); + talloc_free(lck); conn->num_files_open++; @@ -1945,17 +1832,13 @@ files_struct *open_directory(connection_struct *conn, if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); - /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ - set_saved_error_triple(ERRDOS, ERRbadpath, - NT_STATUS_NOT_A_DIRECTORY); + set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); return NULL; } if (dir_existed && !S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ - set_saved_error_triple(ERRDOS, ERRbadpath, - NT_STATUS_NOT_A_DIRECTORY); + set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); return NULL; } @@ -1967,8 +1850,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_OPEN requested " "for directory %s and it doesn't " "exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, - NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); return NULL; } info = FILE_WAS_OPENED; @@ -2008,8 +1890,7 @@ files_struct *open_directory(connection_struct *conn, "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); file_free(fsp); - set_saved_error_triple(ERRDOS, ERRinvalidparam, - NT_STATUS_INVALID_PARAMETER); + set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c0c9e989a9..385f998b1c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -3,6 +3,7 @@ oplock processing Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1998 - 2001 + Copyright (C) Volker Lendecke 2005 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 @@ -21,25 +22,17 @@ #include "includes.h" -/* Oplock ipc UDP socket. */ -static int oplock_sock = -1; -uint16 global_oplock_port = 0; - /* Current number of oplocks we have outstanding. */ static int32 exclusive_oplocks_open = 0; static int32 level_II_oplocks_open = 0; BOOL global_client_failed_oplock_break = False; -BOOL global_oplock_break = False; extern struct timeval smb_last_time; extern uint32 global_client_caps; -extern struct current_user current_user; extern int smb_read_error; static struct kernel_oplocks *koplocks; -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local); - /**************************************************************************** Get the number of current exclusive oplocks. ****************************************************************************/ @@ -58,9 +51,6 @@ BOOL oplock_message_waiting(fd_set *fds) if (koplocks && koplocks->msg_waiting(fds)) return True; - if (FD_ISSET(oplock_sock, fds)) - return True; - return False; } @@ -75,13 +65,9 @@ BOOL oplock_message_waiting(fd_set *fds) ****************************************************************************/ -BOOL receive_local_message( char *buffer, int buffer_len, int timeout) +void process_kernel_oplocks(void) { - struct sockaddr_in from; - socklen_t fromlen = sizeof(from); - int32 msg_len = 0; fd_set fds; - int selrtn = -1; FD_ZERO(&fds); smb_read_error = 0; @@ -92,110 +78,29 @@ BOOL receive_local_message( char *buffer, int buffer_len, int timeout) * already been eaten. JRA. */ - if (koplocks && koplocks->msg_waiting(&fds)) { - return koplocks->receive_message(&fds, buffer, buffer_len); + if (!koplocks) { + return; } - while (timeout > 0 && selrtn == -1) { - struct timeval to; - int maxfd = oplock_sock; - time_t starttime = time(NULL); - - FD_ZERO(&fds); - maxfd = setup_oplock_select_set(&fds); + while (koplocks->msg_waiting(&fds)) { + files_struct *fsp; + struct kernel_oplock_message msg; - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - - DEBUG(5,("receive_local_message: doing select with timeout of %d ms\n", timeout)); - - selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); - - if (selrtn == -1 && errno == EINTR) { - - /* could be a kernel oplock interrupt */ - if (koplocks && koplocks->msg_waiting(&fds)) { - return koplocks->receive_message(&fds, buffer, buffer_len); - } + fsp = koplocks->receive_message(&fds); - /* - * Linux 2.0.x seems to have a bug in that - * it can return -1, EINTR with a timeout of zero. - * Make sure we bail out here with a read timeout - * if we got EINTR on a timeout of 1 or less. - */ - - if (timeout <= 1) { - smb_read_error = READ_TIMEOUT; - return False; - } - - /* Not a kernel interrupt - could be a SIGUSR1 message. We must restart. */ - /* We need to decrement the timeout here. */ - timeout -= ((time(NULL) - starttime)*1000); - if (timeout < 0) - timeout = 1; - - DEBUG(5,("receive_local_message: EINTR : new timeout %d ms\n", timeout)); - continue; + if (fsp == NULL) { + DEBUG(3, ("Kernel oplock message announced, but none " + "received\n")); + return; } - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } - - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return False; - } - } - - if (koplocks && koplocks->msg_waiting(&fds)) { - return koplocks->receive_message(&fds, buffer, buffer_len); + msg.dev = fsp->dev; + msg.inode = fsp->inode; + msg.file_id = fsp->file_id; + message_send_pid(pid_to_procid(sys_getpid()), + MSG_SMB_KERNEL_BREAK, + &msg, sizeof(msg), True); } - - if (!FD_ISSET(oplock_sock, &fds)) - return False; - - /* - * From here down we deal with the smbd <--> smbd - * oplock break protocol only. - */ - - /* - * Read a loopback udp message. - */ - msg_len = sys_recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], - buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen); - - if(msg_len < 0) { - DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); - return False; - } - - /* Validate message length. */ - if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { - DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", msg_len, - buffer_len - OPBRK_CMD_HEADER_LEN)); - return False; - } - - /* Validate message from address (must be localhost). */ - if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { - DEBUG(0,("receive_local_message: invalid 'from' address \ -(was %lx should be 127.0.0.1)\n", (long)from.sin_addr.s_addr)); - return False; - } - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,msg_len); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,ntohs(from.sin_port)); - - return True; } /**************************************************************************** @@ -229,13 +134,19 @@ tv_sec = %x, tv_usec = %x\n", void release_file_oplock(files_struct *fsp) { - if ((fsp->oplock_type != NO_OPLOCK) && koplocks) + if ((fsp->oplock_type != NO_OPLOCK) && + (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) && + koplocks) { koplocks->release_oplock(fsp); + } if (fsp->oplock_type == LEVEL_II_OPLOCK) level_II_oplocks_open--; - else if (fsp->oplock_type) + else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) exclusive_oplocks_open--; + + SMB_ASSERT(exclusive_oplocks_open>=0); + SMB_ASSERT(level_II_oplocks_open>=0); fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; @@ -263,45 +174,58 @@ static void downgrade_file_oplock(files_struct *fsp) to none even if a "break-to-level II" was sent. ****************************************************************************/ -BOOL remove_oplock(files_struct *fsp, BOOL break_to_none) +BOOL remove_oplock(files_struct *fsp) { SMB_DEV_T dev = fsp->dev; SMB_INO_T inode = fsp->inode; - BOOL ret = True; + BOOL ret; + struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", - fsp->fsp_name )); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { + DEBUG(0,("remove_oplock: failed to lock share entry for " + "file %s\n", fsp->fsp_name )); return False; } + ret = remove_share_oplock(lck, fsp); + if (!ret) { + DEBUG(0,("remove_oplock: failed to remove share oplock for " + "file %s fnum %d, dev = %x, inode = %.0f\n", + fsp->fsp_name, fsp->fnum, (unsigned int)dev, + (double)inode)); + } + release_file_oplock(fsp); + talloc_free(lck); + return ret; +} - if (fsp->sent_oplock_break == BREAK_TO_NONE_SENT || break_to_none) { - /* - * Deal with a reply when a break-to-none was sent. - */ - - if(remove_share_oplock(fsp)==False) { - DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \ -dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); - ret = False; - } +/* + * Deal with a reply when a break-to-level II was sent. + */ +BOOL downgrade_oplock(files_struct *fsp) +{ + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; + BOOL ret; + struct share_mode_lock *lck; - release_file_oplock(fsp); - } else { - /* - * Deal with a reply when a break-to-level II was sent. - */ - if(downgrade_share_oplock(fsp)==False) { - DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \ -dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); - ret = False; - } - - downgrade_file_oplock(fsp); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { + DEBUG(0,("downgrade_oplock: failed to lock share entry for " + "file %s\n", fsp->fsp_name )); + return False; } - - unlock_share_entry_fsp(fsp); + ret = downgrade_share_oplock(lck, fsp); + if (!ret) { + DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " + "for file %s fnum %d, dev = %x, inode = %.0f\n", + fsp->fsp_name, fsp->fnum, (unsigned int)dev, + (double)inode)); + } + + downgrade_file_oplock(fsp); + talloc_free(lck); return ret; } @@ -313,12 +237,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double) int setup_oplock_select_set( fd_set *fds) { - int maxfd = oplock_sock; - - if(oplock_sock == -1) - return 0; - - FD_SET(oplock_sock,fds); + int maxfd = 0; if (koplocks && koplocks->notification_fd != -1) { FD_SET(koplocks->notification_fd, fds); @@ -329,197 +248,31 @@ int setup_oplock_select_set( fd_set *fds) } /**************************************************************************** - Process an oplock break message - whether it came from the UDP socket - or from the kernel. + Set up an oplock break message. ****************************************************************************/ -BOOL process_local_message(char *buffer, int buf_size) +static char *new_break_smb_message(TALLOC_CTX *mem_ctx, + files_struct *fsp, uint8_t cmd) { - int32 msg_len; - uint16 from_port; - char *msg_start; - pid_t remotepid; - SMB_DEV_T dev; - SMB_INO_T inode; - unsigned long file_id; - uint16 break_cmd_type; - struct sockaddr_in toaddr; - - msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET); - from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET); - - msg_start = &buffer[OPBRK_CMD_HEADER_LEN]; - - DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", - msg_len, from_port)); - - /* - * Pull the info out of the requesting packet. - */ - - break_cmd_type = SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET); - - switch(break_cmd_type) { - case KERNEL_OPLOCK_BREAK_CMD: - if (!koplocks) { - DEBUG(0,("unexpected kernel oplock break!\n")); - break; - } - if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev, &file_id)) { - DEBUG(0,("kernel oplock break parse failure!\n")); - return False; - } - break; - - case OPLOCK_BREAK_CMD: - case LEVEL_II_OPLOCK_BREAK_CMD: - case ASYNC_LEVEL_II_OPLOCK_BREAK_CMD: - - /* Ensure that the msg length is correct. */ - if(msg_len != OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, should be %d).\n", - (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); - memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); - memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id)); - - DEBUG(5,("process_local_message: (%s) oplock break request from \ -pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", - (break_cmd_type == OPLOCK_BREAK_CMD) ? "exclusive" : "level II", - (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); - break; - - case RETRY_DEFERRED_OPEN_CMD: - - /* Request to retry and open that would return SHARING_VIOLATION. */ - if (msg_len != DEFERRED_OPEN_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for RETRY_DEFERRED_OPEN_CMD (was %d, should be %d).\n", - (int)msg_len, (int)DEFERRED_OPEN_MSG_LEN)); - return False; - } - { - uint16 mid; - - memcpy((char *)&remotepid, msg_start+DEFERRED_OPEN_PID_OFFSET,sizeof(remotepid)); - memcpy((char *)&inode, msg_start+DEFERRED_OPEN_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&dev, msg_start+DEFERRED_OPEN_DEV_OFFSET,sizeof(dev)); - memcpy((char *)&mid, msg_start+DEFERRED_OPEN_MID_OFFSET,sizeof(mid)); - - DEBUG(5,("process_local_message: RETRY_DEFERRED_OPEN from \ -pid %d, port %d, dev = %x, inode = %.0f, mid = %u\n", - (int)remotepid, from_port, (unsigned int)dev, (double)inode, (unsigned int)mid)); - - schedule_sharing_violation_open_smb_message(mid); - } - return True; - - /* - * Keep this as a debug case - eventually we can remove it. - */ - case 0x8001: - DEBUG(0,("process_local_message: Received unsolicited break \ -reply - dumping info.\n")); - - if(msg_len != OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: ubr: incorrect length for reply \ -(was %d, should be %d).\n", (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); - memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); - memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id)); + char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0); - DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", - (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); - - return False; - - default: - DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", - (unsigned int)SVAL(msg_start,0))); - return False; - } - - /* - * Now actually process the break request. - */ - - if ((exclusive_oplocks_open == 0) && - (level_II_oplocks_open == 0)) { - /* - * If we have no record of any currently open oplocks, - * it's not an error, as a close command may have - * just been issued on the file that was oplocked. - * Just log a message and return success in this case. - */ - DEBUG(3,("process_local_message: oplock break requested with " - "no outstanding oplocks. Returning success.\n")); - - } else { - if (!oplock_break(dev, inode, file_id, False)) { - DEBUG(0,("process_local_message: oplock break failed.\n")); - return False; - } - } - - /* - * Do the appropriate reply - none in the kernel or async level II - * case. - */ - - if (!((break_cmd_type == OPLOCK_BREAK_CMD) || - (break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD))) { - return True; - } - - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY); - - memset((char *)&toaddr,'\0',sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; - - if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { - DEBUG(0,("process_local_message: sendto process %d failed. " - "Errno was %s\n", (int)remotepid, strerror(errno))); - return False; + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - DEBUG(5,("process_local_message: oplock break reply sent to pid %d, " - "port %d, for file dev = %x, inode = %.0f, file_id = %lu\n", - (int)remotepid, from_port, (unsigned int)dev, - (double)inode, file_id)); - - return True; -} - -/**************************************************************************** - Set up an oplock break message. -****************************************************************************/ - -static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) -{ - memset(outbuf,'\0',smb_size); - set_message(outbuf,8,0,True); - - SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->conn->cnum); - SSVAL(outbuf,smb_pid,0xFFFF); - SSVAL(outbuf,smb_uid,0); - SSVAL(outbuf,smb_mid,0xFFFF); - SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fsp->fnum); - SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); - SCVAL(outbuf,smb_vwv3+1,level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); + memset(result,'\0',smb_size); + set_message(result,8,0,True); + SCVAL(result,smb_com,SMBlockingX); + SSVAL(result,smb_tid,fsp->conn->cnum); + SSVAL(result,smb_pid,0xFFFF); + SSVAL(result,smb_uid,0); + SSVAL(result,smb_mid,0xFFFF); + SCVAL(result,smb_vwv0,0xFF); + SSVAL(result,smb_vwv2,fsp->fnum); + SCVAL(result,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); + SCVAL(result,smb_vwv3+1,cmd); + return result; } /**************************************************************************** @@ -602,639 +355,266 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un return fsp; } -/**************************************************************************** - Process a level II oplock break directly. - We must call this function with the share mode entry locked. -****************************************************************************/ - -static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) +static void oplock_timeout_handler(struct timed_event *te, + const struct timeval *now, + void *private_data) { - char outbuf[128]; - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; - - /* - * We can have a level II oplock even if the client is not - * level II oplock aware. In this case just remove the - * flags and don't send the break-to-none message to - * the client. - */ - - if (global_client_caps & CAP_LEVEL_II_OPLOCKS) { - BOOL sign_state; - - /* - * If we are sending an oplock break due to an SMB sent - * by our own client we ensure that we wait at leat - * lp_oplock_break_wait_time() milliseconds before sending - * the packet. Sending the packet sooner can break Win9x - * and has reported to cause problems on NT. JRA. - */ - - if (local_request) { - wait_before_sending_break(); - } - - /* Prepare the SMBlockingX message. */ - prepare_break_message( outbuf, fsp, False); - - /* Save the server smb signing state. */ - sign_state = srv_oplock_set_signing(False); - - show_msg(outbuf); - if (!send_smb(smbd_server_fd(), outbuf)) - exit_server("oplock_break_level2: send_smb failed."); + files_struct *fsp = private_data; - /* Restore the sign state to what it was. */ - srv_oplock_set_signing(sign_state); - } - - /* - * Now we must update the shared memory structure to tell - * everyone else we no longer have a level II oplock on - * this open file. We must call this function with the share mode - * entry locked so we can change the entry directly. - */ - - if(remove_share_oplock(fsp)==False) { - DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); - } - - release_file_oplock(fsp); - - if(level_II_oplocks_open < 0) { - DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", - level_II_oplocks_open)); - abort(); - } - - if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break_level2: returning success for " ); - dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, fsp->file_id ); - dbgtext( "Current level II oplocks_open = %d\n", level_II_oplocks_open ); - } - - return True; + DEBUG(0, ("Oplock break failed -- replying anyway\n")); + global_client_failed_oplock_break = True; + remove_oplock(fsp); + reply_to_oplock_break_requests(fsp); } -/**************************************************************************** - Process an oplock break directly. - This is always called with the share mode lock *NOT* held. -****************************************************************************/ - -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) +static void process_oplock_break_message(int msg_type, struct process_id src, + void *buf, size_t len) { - char *inbuf = NULL; - char *saved_inbuf = NULL; - char *outbuf = NULL; - char *saved_outbuf = NULL; - files_struct *fsp = NULL; - time_t start_time; - BOOL shutdown_server = False; - BOOL oplock_timeout = False; + struct share_mode_entry *msg = buf; + files_struct *fsp; + char *break_msg; + BOOL break_to_level2 = False; BOOL sign_state; - connection_struct *saved_user_conn; - connection_struct *saved_fsp_conn; - int saved_vuid; - pstring saved_dir; - int timeout = (OPLOCK_BREAK_TIMEOUT * 1000); - pstring file_name; - BOOL using_levelII; - - if((fsp = initial_break_processing(dev, inode, file_id)) == NULL) - return True; - /* - * Deal with a level II oplock going break to none separately. - */ - - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { - BOOL ret; - /* We must always call oplock_break_level2() with - the share mode entry locked. */ - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("oplock_break: unable to lock share entry for file %s\n", fsp->fsp_name )); - return False; - } - ret = oplock_break_level2(fsp, local_request); - unlock_share_entry_fsp(fsp); - return ret; + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - /* Mark the oplock break as sent - we don't want to send twice! */ - if (fsp->sent_oplock_break) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); - dbgtext( "file %s ", fsp->fsp_name); - dbgtext( "(dev = %x, inode = %.0f, file_id = %lu)\n", (unsigned int)dev, (double)inode, fsp->file_id ); - } - - /* - * We have to fail the open here as we cannot send another oplock break on - * this file whilst we are awaiting a response from the client - neither - * can we allow another open to succeed while we are waiting for the client. - */ - return False; + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - if(global_oplock_break) { - DEBUG(0,("ABORT : ABORT : recursion in oplock_break !!!!!\n")); - abort(); - } + DEBUG(10, ("Got oplock break message from pid %d: %d/%d/%d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->share_file_id)); - /* - * Now comes the horrid part. We must send an oplock break to the client, - * and then process incoming messages until we get a close or oplock release. - * At this point we know we need a new inbuf/outbuf buffer pair. - * We cannot use these staticaly as we may recurse into here due to - * messages crossing on the wire. - */ + fsp = initial_break_processing(msg->dev, msg->inode, + msg->share_file_id); - if((inbuf = NewInBuffer(&saved_inbuf))==NULL) { - DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); - return False; + if (fsp == NULL) { + /* We hit race here. Break messages are sent, and before we + * get to process this message, we have closed the file. Reply + * with 'ok, oplock broken' */ + DEBUG(3, ("Did not find fsp\n")); + message_send_pid(src, MSG_SMB_BREAK_RESPONSE, + msg, sizeof(*msg), True); + return; } - if((outbuf = NewOutBuffer(&saved_outbuf))==NULL) { - DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - /* Free must be done before set.. */ - free_InBuffer(inbuf); - set_InBuffer(saved_inbuf); - return False; + if (fsp->sent_oplock_break != NO_BREAK_SENT) { + /* Remember we have to inform the requesting PID when the + * client replies */ + msg->pid = src; + ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg, + &fsp->pending_break_messages, + &fsp->num_pending_break_messages); + return; } - /* - * If we are sending an oplock break due to an SMB sent - * by our own client we ensure that we wait at leat - * lp_oplock_break_wait_time() milliseconds before sending - * the packet. Sending the packet sooner can break Win9x - * and has reported to cause problems on NT. JRA. - */ - - if (local_request) { - wait_before_sending_break(); + if (EXCLUSIVE_OPLOCK_TYPE(msg->op_type) && + !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + DEBUG(3, ("Already downgraded oplock on %.0f/%.0f: %s\n", + (double)fsp->dev, (double)fsp->inode, + fsp->fsp_name)); + message_send_pid(src, MSG_SMB_BREAK_RESPONSE, + msg, sizeof(*msg), True); + return; } - /* Prepare the SMBlockingX message. */ + if ((msg_type == MSG_SMB_BREAK_REQUEST) && + (global_client_caps & CAP_LEVEL_II_OPLOCKS) && + !koplocks && /* NOTE: we force levelII off for kernel oplocks - + * this will change when it is supported */ + lp_level2_oplocks(SNUM(fsp->conn))) { + break_to_level2 = True; + } - if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && - !koplocks && /* NOTE: we force levelII off for kernel oplocks - this will change when it is supported */ - lp_level2_oplocks(SNUM(fsp->conn))) { - using_levelII = True; - } else { - using_levelII = False; + break_msg = new_break_smb_message(NULL, fsp, break_to_level2 ? + OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); + if (break_msg == NULL) { + exit_server("Could not talloc break_msg\n"); } - prepare_break_message( outbuf, fsp, using_levelII); - /* Remember if we just sent a break to level II on this file. */ - fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; + /* Need to wait before sending a break message to a file of our own */ + if (procid_to_pid(&src) == sys_getpid()) { + wait_before_sending_break(); + } /* Save the server smb signing state. */ sign_state = srv_oplock_set_signing(False); - show_msg(outbuf); - if (!send_smb(smbd_server_fd(), outbuf)) { - srv_oplock_set_signing(sign_state); + show_msg(break_msg); + if (!send_smb(smbd_server_fd(), break_msg)) { exit_server("oplock_break: send_smb failed."); } /* Restore the sign state to what it was. */ srv_oplock_set_signing(sign_state); - /* We need this in case a readraw crosses on the wire. */ - global_oplock_break = True; - - /* Process incoming messages. */ - - /* - * JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT - * seconds we should just die.... - */ - - start_time = time(NULL); + talloc_free(break_msg); - /* - * Save the information we need to re-become the - * user, then unbecome the user whilst we're doing this. - */ - saved_user_conn = current_user.conn; - saved_vuid = current_user.vuid; - saved_fsp_conn = fsp->conn; - /* - * Initialize saved_dir to something sensible: vfs_GetWd may not work well - * for root: the directory may be NFS-mounted and exported with root_squash - * (so has no root access). - */ - pstrcpy(saved_dir,saved_fsp_conn->connectpath); - vfs_GetWd(saved_fsp_conn,saved_dir); - /* Save the chain fnum. */ - file_chain_save(); - - pstrcpy(file_name, fsp->fsp_name); - - change_to_root_user(); - - /* - * From Charles Hoch . If the break processing - * code closes the file (as it often does), then the fsp pointer here - * points to free()'d memory. We *must* revalidate fsp each time - * around the loop. With async I/O, write calls may steal the global InBuffer, - * so ensure we're using the correct one each time around the loop. - */ - - while((fsp = initial_break_processing(dev, inode, file_id)) && - OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - - inbuf = get_InBuffer(); - outbuf = get_OutBuffer(); - - if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) { - /* - * Die if we got an error. - */ - - if (smb_read_error == READ_EOF) { - DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); - shutdown_server = True; - } else if (smb_read_error == READ_ERROR) { - DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); - shutdown_server = True; - } else if (smb_read_error == READ_BAD_SIG) { - DEBUG( 0, ("oplock_break: bad signature from client\n" )); - shutdown_server = True; - } else if (smb_read_error == READ_TIMEOUT) { - DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); - oplock_timeout = True; - } - - DEBUGADD( 0, ( "oplock_break failed for file %s ", file_name ) ); - DEBUGADD( 0, ( "(dev = %x, inode = %.0f, file_id = %lu).\n", - (unsigned int)dev, (double)inode, file_id)); + if (msg_type == MSG_SMB_BREAK_REQUEST) { + fsp->sent_oplock_break = break_to_level2 ? + LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; + } else { + /* Async level2 request, don't send a reply */ + fsp->sent_oplock_break = ASYNC_LEVEL_II_BREAK_SENT; + } + msg->pid = src; + ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg, + &fsp->pending_break_messages, + &fsp->num_pending_break_messages); - break; - } + if (fsp->oplock_timeout != NULL) { + DEBUG(0, ("Logic problem -- have an oplock event hanging " + "around\n")); + } - /* - * There are certain SMB requests that we shouldn't allow - * to recurse. opens, renames and deletes are the obvious - * ones. This is handled in the switch_message() function. - * If global_oplock_break is set they will push the packet onto - * the pending smb queue and return -1 (no reply). - * JRA. - */ + fsp->oplock_timeout = + add_timed_event(NULL, + timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), + "oplock_timeout_handler", + oplock_timeout_handler, fsp); - process_smb(inbuf, outbuf); + if (fsp->oplock_timeout == NULL) { + DEBUG(0, ("Could not add oplock timeout handler\n")); + } +} - /* - * Die if we go over the time limit. - */ +static void process_kernel_oplock_break(int msg_type, struct process_id src, + void *buf, size_t len) +{ + struct kernel_oplock_message *msg = buf; + files_struct *fsp; + char *break_msg; + BOOL sign_state; - if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "oplock_break: no break received from client " ); - dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); - dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %.0f, file_id = %lu).\n", - (unsigned int)dev, (double)inode, file_id ); - } - oplock_timeout = True; - break; - } + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - /* - * Go back to being the user who requested the oplock - * break. - */ - if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !change_to_user(saved_user_conn, saved_vuid)) { - DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); - DEBUGADD( 0, ( "Shutting down server\n" ) ); - close(oplock_sock); - exit_server("unable to re-become user"); + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - /* Including the directory. */ - vfs_ChDir(saved_fsp_conn,saved_dir); - - /* Restore the chain fnum. */ - file_chain_restore(); + DEBUG(10, ("Got kernel oplock break message from pid %d: %d/%d/%d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->file_id)); - /* Free the buffers we've been using to recurse. */ - /* Free must be done before set.. */ - free_InBuffer(inbuf); - free_OutBuffer(outbuf); + fsp = initial_break_processing(msg->dev, msg->inode, msg->file_id); - /* Restore the global In/Out buffers. */ - set_InBuffer(saved_inbuf); - set_OutBuffer(saved_outbuf); - - /* We need this in case a readraw crossed on the wire. */ - if(global_oplock_break) - global_oplock_break = False; - - /* - * If the client timed out then clear the oplock (or go to level II) - * and continue. This seems to be what NT does and is better than dropping - * the connection. - */ - - if(oplock_timeout && (fsp = initial_break_processing(dev, inode, file_id)) && - OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name)); - remove_oplock(fsp,True); -#if FASCIST_OPLOCK_BACKOFF - global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */ -#endif + if (fsp == NULL) { + DEBUG(3, ("Got a kernel oplock break message for a file " + "I don't know about\n")); + return; } - /* - * If the client had an error we must die. - */ - - if(shutdown_server) { - DEBUG( 0, ( "oplock_break: client failure in break - " ) ); - DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); - close(oplock_sock); - exit_server("oplock break failure"); + if (fsp->sent_oplock_break != NO_BREAK_SENT) { + /* This is ok, kernel oplocks come in completely async */ + DEBUG(3, ("Got a kernel oplock request while waiting for a " + "break reply\n")); + return; } - /* Santity check - remove this later. JRA */ - if(exclusive_oplocks_open < 0) { - DEBUG(0,("oplock_break: exclusive_oplocks_open < 0 (%d). PANIC ERROR\n", exclusive_oplocks_open)); - abort(); + break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); + if (break_msg == NULL) { + exit_server("Could not talloc break_msg\n"); } - /* We know we have no saved errors here. */ - set_saved_error_triple(0, 0, NT_STATUS_OK); + /* Save the server smb signing state. */ + sign_state = srv_oplock_set_signing(False); - if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break: returning success for " ); - dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Current exclusive_oplocks_open = %d\n", exclusive_oplocks_open ); + show_msg(break_msg); + if (!send_smb(smbd_server_fd(), break_msg)) { + exit_server("oplock_break: send_smb failed."); } - return True; -} - -/**************************************************************************** - Send an oplock break message to another smbd process. If the oplock is held - by the local smbd then call the oplock break function directly. - This function is called with no share locks held. -****************************************************************************/ + /* Restore the sign state to what it was. */ + srv_oplock_set_signing(sign_state); -BOOL request_oplock_break(share_mode_entry *share_entry) -{ - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - pid_t pid = sys_getpid(); - time_t start_time; - int time_left; - SMB_DEV_T dev = share_entry->dev; - SMB_INO_T inode = share_entry->inode; - unsigned long file_id = share_entry->share_file_id; - uint16 break_cmd_type; - - if(pid == share_entry->pid) { - /* We are breaking our own oplock, make sure it's us. */ - if(share_entry->op_port != global_oplock_port) { - DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ -should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); - return False; - } + talloc_free(break_msg); - DEBUG(5,("request_oplock_break: breaking our own oplock\n")); + fsp->sent_oplock_break = BREAK_TO_NONE_SENT; +} -#if 1 /* JRA PARANOIA TEST.... */ - { - files_struct *fsp = file_find_dif(dev, inode, file_id); - if (!fsp) { - DEBUG(0,("request_oplock_break: PANIC : breaking our own oplock requested for \ -dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", - (unsigned int)dev, (double)inode, file_id )); - smb_panic("request_oplock_break: no fsp found for our own oplock\n"); - } - } -#endif /* END JRA PARANOIA TEST... */ +void reply_to_oplock_break_requests(files_struct *fsp) +{ + int i; - /* Call oplock break direct. */ - return oplock_break(dev, inode, file_id, True); + for (i=0; inum_pending_break_messages; i++) { + struct share_mode_entry *msg = &fsp->pending_break_messages[i]; + message_send_pid(msg->pid, MSG_SMB_BREAK_RESPONSE, + msg, sizeof(*msg), True); } - /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ - - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - break_cmd_type = LEVEL_II_OPLOCK_BREAK_CMD; - } else { - break_cmd_type = OPLOCK_BREAK_CMD; + SAFE_FREE(fsp->pending_break_messages); + fsp->num_pending_break_messages = 0; + if (fsp->oplock_timeout != NULL) { + talloc_free(fsp->oplock_timeout); + fsp->oplock_timeout = NULL; } + return; +} - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type); - memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); - memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); - memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); - memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); - - /* Set the address and port. */ - memset((char *)&addr_out,'\0',sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; - - if( DEBUGLVL( 3 ) ) { - dbgtext( "request_oplock_break: sending a synchronous oplock break message to " ); - dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - } +static void process_oplock_break_response(int msg_type, struct process_id src, + void *buf, size_t len) +{ + struct share_mode_entry *msg = buf; - if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_oplock_break: failed when sending a oplock " ); - dbgtext( "break message to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Error was %s\n", strerror(errno) ); - } - return False; + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - /* - * Now we must await the oplock broken message coming back - * from the target smbd process. Timeout if it fails to - * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. - * While we get messages that aren't ours, loop. - */ - - start_time = time(NULL); - time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR; - - while(time_left >= 0) { - char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; - uint16 reply_from_port; - char *reply_msg_start; - - if(receive_local_message(op_break_reply, sizeof(op_break_reply), - time_left ? time_left * 1000 : 1) == False) { - if(smb_read_error == READ_TIMEOUT) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_oplock_break: no response received to oplock " ); - dbgtext( "break request to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - } - - /* - * This is a hack to make handling of failing clients more robust. - * If a oplock break response message is not received in the timeout - * period we may assume that the smbd servicing that client holding - * the oplock has died and the client changes were lost anyway, so - * we should continue to try and open the file. - */ - break; - } else { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_oplock_break: error in response received " ); - dbgtext( "to oplock break request to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Error was (%s).\n", strerror(errno) ); - } - } - return False; - } - - reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET); - reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; - - /* - * Test to see if this is the reply we are awaiting (ie. the one we sent with the CMD_REPLY flag OR'ed in). - */ - if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) && - ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == break_cmd_type) && - (reply_from_port == share_entry->op_port) && - (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], &op_break_msg[OPLOCK_BREAK_PID_OFFSET], - OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) { - - /* - * This is the reply we've been waiting for. - */ - break; - } else { - /* - * This is another message - a break request. - * Note that both kernel oplock break requests - * and UDP inter-smbd oplock break requests will - * be processed here. - * - * Process it to prevent potential deadlock. - * Note that the code in switch_message() prevents - * us from recursing into here as any SMB requests - * we might process that would cause another oplock - * break request to be made will be queued. - * JRA. - */ - - process_local_message(op_break_reply, sizeof(op_break_reply)); - } - - time_left -= (time(NULL) - start_time); + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - DEBUG(3,("request_oplock_break: broke oplock.\n")); + DEBUG(10, ("Got oplock break response from pid %d: %d/%d/%d mid %d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->share_file_id, (int)msg->op_mid)); - return True; + /* Here's the hack from open.c, store the mid in the 'port' field */ + schedule_deferred_open_smb_message(msg->op_mid); } -/**************************************************************************** - Attempt to break an oplock on a file (if oplocked). - Returns True if the file was closed as a result of - the oplock break, False otherwise. - Used as a last ditch attempt to free a space in the - file table when we have run out. -****************************************************************************/ - -BOOL attempt_close_oplocked_file(files_struct *fsp) +static void process_open_retry_message(int msg_type, struct process_id src, + void *buf, size_t len) { - DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fh->fd != -1)) { - /* Try and break the oplock. */ - if (oplock_break(fsp->dev, fsp->inode, fsp->file_id, True)) { - if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */ - return True; - } + struct share_mode_entry *msg = buf; + + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - return False; -} - -/**************************************************************************** - Send an asynchronous oplock break message to another smbd process. -****************************************************************************/ - -static BOOL request_remote_level2_async_oplock_break(share_mode_entry *share_entry) -{ - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - pid_t pid = sys_getpid(); - SMB_DEV_T dev = share_entry->dev; - SMB_INO_T inode = share_entry->inode; - unsigned long file_id = share_entry->share_file_id; - - /* We need to send a ASYNC_LEVEL_II_OPLOCK_BREAK_CMD message to the port in the share mode entry. */ - - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,ASYNC_LEVEL_II_OPLOCK_BREAK_CMD); - memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); - memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); - memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); - memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); - - /* Set the address and port. */ - memset((char *)&addr_out,'\0',sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; - - if( DEBUGLVL( 3 ) ) { - dbgtext( "request_remote_level2_async_oplock_break: sending an asynchronous oplock break message to "); - dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_remote_level2_async_oplock_break: failed when sending a oplock " ); - dbgtext( "break message to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Error was %s\n", strerror(errno) ); - } - return False; - } + DEBUG(10, ("Got open retry msg from pid %d: %d/%d mid %d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->op_mid)); - DEBUG(3,("request_remote_level2_async_oplock_break: sent async break message to level II entry.\n")); - return True; + schedule_deferred_open_smb_message(msg->op_mid); } /**************************************************************************** This function is called on any file modification or lock request. If a file - is level 2 oplocked then it must tell all other level 2 holders to break to none. + is level 2 oplocked then it must tell all other level 2 holders to break to + none. ****************************************************************************/ void release_level_2_oplocks_on_change(files_struct *fsp) { - share_mode_entry *share_list = NULL; - pid_t pid = sys_getpid(); - int num_share_modes = 0; int i; - BOOL dummy; + struct share_mode_lock *lck; /* * If this file is level II oplocked then we need @@ -1247,125 +627,71 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("release_level_2_oplocks_on_change: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { + DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " + "share mode entry for file %s.\n", fsp->fsp_name )); } - num_share_modes = get_share_modes(fsp->dev, fsp->inode, &share_list, - &dummy); - DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", - num_share_modes )); + lck->num_share_modes )); + + if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) { + /* See if someone else has already downgraded us, then we + don't have to do anything */ + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if ((e->op_type == NO_OPLOCK) && + (e->share_file_id == fsp->file_id) && + (e->dev == fsp->dev) && + (e->inode == fsp->inode) && + (procid_is_me(&e->pid))) { + /* We're done */ + fsp->oplock_type = NO_OPLOCK; + talloc_free(lck); + return; + } + } + } - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &share_list[i]; + for(i = 0; i < lck->num_share_modes; i++) { + struct share_mode_entry *share_entry = &lck->share_modes[i]; /* - * As there could have been multiple writes waiting at the lock_share_entry - * gate we may not be the first to enter. Hence the state of the op_types - * in the share mode entries may be partly NO_OPLOCK and partly LEVEL_II - * oplock. It will do no harm to re-send break messages to those smbd's - * that are still waiting their turn to remove their LEVEL_II state, and - * also no harm to ignore existing NO_OPLOCK states. JRA. + * As there could have been multiple writes waiting at the + * lock_share_entry gate we may not be the first to + * enter. Hence the state of the op_types in the share mode + * entries may be partly NO_OPLOCK and partly LEVEL_II + * oplock. It will do no harm to re-send break messages to + * those smbd's that are still waiting their turn to remove + * their LEVEL_II state, and also no harm to ignore existing + * NO_OPLOCK states. JRA. */ - DEBUG(10,("release_level_2_oplocks_on_change: share_entry[%i]->op_type == %d\n", - i, share_entry->op_type )); + DEBUG(10,("release_level_2_oplocks_on_change: " + "share_entry[%i]->op_type == %d\n", + i, share_entry->op_type )); - if (share_entry->op_type == NO_OPLOCK) + if ((share_entry->op_type == NO_OPLOCK) || + (share_entry->op_type == FAKE_LEVEL_II_OPLOCK)) { continue; + } /* Paranoia .... */ if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { - DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is an exlusive oplock !\n", i )); - unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); + DEBUG(0,("release_level_2_oplocks_on_change: PANIC. " + "share mode entry %d is an exlusive " + "oplock !\n", i )); + talloc_free(lck); abort(); } - /* - * Check if this is a file we have open (including the - * file we've been called to do write_file on. If so - * then break it directly without releasing the lock. - */ - - if (pid == share_entry->pid) { - files_struct *new_fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); - - /* Paranoia check... */ - if(new_fsp == NULL) { - DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is not a local file !\n", i )); - unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); - abort(); - } - - DEBUG(10,("release_level_2_oplocks_on_change: breaking our own oplock.\n")); - - oplock_break_level2(new_fsp, True); - - } else { - - /* - * This is a remote file and so we send an asynchronous - * message. - */ - - DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock (async).\n")); - request_remote_level2_async_oplock_break(share_entry); - } - } - - SAFE_FREE(share_list); - unlock_share_entry_fsp(fsp); - - /* Paranoia check... */ - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(0,("release_level_2_oplocks_on_change: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name)); - smb_panic("release_level_2_oplocks_on_change"); - } -} - -/**************************************************************************** - Send a 'retry your open' message to a process with a deferred open entry. -****************************************************************************/ - -BOOL send_deferred_open_retry_message(deferred_open_entry *entry) -{ - char de_msg[DEFERRED_OPEN_MSG_LEN]; - struct sockaddr_in addr_out; - pid_t pid = sys_getpid(); - - memset(de_msg, '\0', DEFERRED_OPEN_MSG_LEN); - SSVAL(de_msg,DEFERRED_OPEN_CMD_OFFSET,RETRY_DEFERRED_OPEN_CMD); - memcpy(de_msg+DEFERRED_OPEN_PID_OFFSET,(char *)&pid,sizeof(pid)); - memcpy(de_msg+DEFERRED_OPEN_DEV_OFFSET,(char *)&entry->dev,sizeof(entry->dev)); - memcpy(de_msg+DEFERRED_OPEN_INODE_OFFSET,(char *)&entry->inode,sizeof(entry->inode)); - memcpy(de_msg+DEFERRED_OPEN_MID_OFFSET,(char *)&entry->mid,sizeof(entry->mid)); - - /* Set the address and port. */ - memset((char *)&addr_out,'\0',sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( entry->port ); - addr_out.sin_family = AF_INET; - - if( DEBUGLVL( 3 ) ) { - dbgtext( "send_deferred_open_retry_message: sending a message to "); - dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port ); - dbgtext( "for dev = %x, inode = %.0f, mid = %u\n", - (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid ); + message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK, + share_entry, sizeof(*share_entry), True); } - if(sys_sendto(oplock_sock,de_msg,DEFERRED_OPEN_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "send_deferred_open_retry_message: failed sending a message to "); - dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port ); - dbgtext( "for dev = %x, inode = %.0f, mid = %u\n", - (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid ); - dbgtext( "Error was %s\n", strerror(errno) ); - } - return False; - } - return True; + remove_all_share_oplocks(lck, fsp); + talloc_free(lck); } /**************************************************************************** @@ -1374,30 +700,18 @@ BOOL send_deferred_open_retry_message(deferred_open_entry *entry) BOOL init_oplocks(void) { - struct sockaddr_in sock_name; - socklen_t len = sizeof(sock_name); - DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); - /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK),False); - if (oplock_sock == -1) { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); - global_oplock_port = 0; - return(False); - } - - /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", - strerror(errno))); - close(oplock_sock); - oplock_sock = -1; - global_oplock_port = 0; - return False; - } - global_oplock_port = ntohs(sock_name.sin_port); + message_register(MSG_SMB_BREAK_REQUEST, + process_oplock_break_message); + message_register(MSG_SMB_ASYNC_LEVEL2_BREAK, + process_oplock_break_message); + message_register(MSG_SMB_BREAK_RESPONSE, + process_oplock_break_response); + message_register(MSG_SMB_KERNEL_BREAK, + process_kernel_oplock_break); + message_register(MSG_SMB_OPEN_RETRY, + process_open_retry_message); if (lp_kernel_oplocks()) { #if HAVE_KERNEL_OPLOCKS_IRIX @@ -1407,8 +721,5 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); #endif } - DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", - (int)sys_getpid(), global_oplock_port)); - return True; } diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index f4405a021e..f49aa297e4 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -86,7 +86,7 @@ Disabling kernel oplock support.\n", strerror(errno) )); * oplock break protocol. ****************************************************************************/ -static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) +static files_struct *irix_oplock_receive_message(fd_set *fds) { extern int smb_read_error; oplock_stat_t os; @@ -102,7 +102,7 @@ static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_le DEBUG(0,("irix_oplock_receive_message: read of kernel notification failed. \ Error was %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; - return False; + return NULL; } /* @@ -122,7 +122,7 @@ Error was %s.\n", strerror(errno) )); return True; } smb_read_error = READ_ERROR; - return False; + return NULL; } /* @@ -138,24 +138,8 @@ Error was %s.\n", strerror(errno) )); DEBUG(5,("irix_oplock_receive_message: kernel oplock break request received for \ dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); - - /* - * Create a kernel oplock break message. - */ - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); - - buffer += OPBRK_CMD_HEADER_LEN; - - SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); - - return True; + + return fsp; } /**************************************************************************** @@ -214,30 +198,6 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, } } -/**************************************************************************** - Parse a kernel oplock message. -****************************************************************************/ - -static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len, - SMB_INO_T *inode, SMB_DEV_T *dev, unsigned long *file_id) -{ - /* Ensure that the msg length is correct. */ - if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %d).\n", - msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); - memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id)); - - DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %ul\n", - (unsigned int)*dev, (double)*inode, *file_id)); - - return True; -} - /**************************************************************************** Set *maxfd to include oplock read pipe. ****************************************************************************/ @@ -274,7 +234,6 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void) koplocks.receive_message = irix_oplock_receive_message; koplocks.set_oplock = irix_set_kernel_oplock; koplocks.release_oplock = irix_release_kernel_oplock; - koplocks.parse_message = irix_kernel_oplock_parse; koplocks.msg_waiting = irix_oplock_msg_waiting; koplocks.notification_fd = oplock_pipe_read; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 477832c6e8..ab0c08f7fc 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -128,10 +128,10 @@ static int linux_setlease(int fd, int leasetype) * oplock break protocol. ****************************************************************************/ -static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) +static files_struct *linux_oplock_receive_message(fd_set *fds) { int fd; - struct files_struct *fsp; + files_struct *fsp; BlockSignals(True, RT_SIGNAL_LEASE); fd = fd_pending_array[0]; @@ -145,32 +145,7 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l /* now we can receive more signals */ BlockSignals(False, RT_SIGNAL_LEASE); - if (fsp == NULL) { - DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd)); - return False; - } - - DEBUG(3,("linux_oplock_receive_message: kernel oplock break request received for \ -dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (double)fsp->inode, - fd, fsp->file_id)); - - /* - * Create a kernel oplock break message. - */ - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); - - buffer += OPBRK_CMD_HEADER_LEN; - - SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); - - return True; + return fsp; } /**************************************************************************** @@ -223,30 +198,6 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, } } -/**************************************************************************** - Parse a kernel oplock message. -****************************************************************************/ - -static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode, - SMB_DEV_T *dev, unsigned long *file_id) -{ - /* Ensure that the msg length is correct. */ - if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %lu).\n", - msg_len, (unsigned long)KERNEL_OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); - memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id)); - - DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)*dev, (double)*inode, *file_id)); - - return True; -} - /**************************************************************************** See if a oplock message is waiting. ****************************************************************************/ @@ -299,7 +250,6 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) koplocks.receive_message = linux_oplock_receive_message; koplocks.set_oplock = linux_set_kernel_oplock; koplocks.release_oplock = linux_release_kernel_oplock; - koplocks.parse_message = linux_kernel_oplock_parse; koplocks.msg_waiting = linux_oplock_msg_waiting; koplocks.notification_fd = -1; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8f9cc52882..0b7b94cce2 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. process incoming packets - main loop Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Volker Lendecke 2005 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 @@ -44,12 +45,11 @@ int max_send = BUFFER_SIZE; int max_recv = BUFFER_SIZE; extern int last_message; -extern int global_oplock_break; extern userdom_struct current_user_info; extern int smb_read_error; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; -BOOL global_machine_password_needs_changing = False; +extern BOOL global_machine_password_needs_changing; extern int max_send; /**************************************************************************** @@ -66,106 +66,72 @@ uint16 get_current_mid(void) for processing. ****************************************************************************/ -static struct pending_message_list *smb_oplock_queue; -static struct pending_message_list *smb_sharing_violation_queue; - -enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE }; - -/**************************************************************************** - Free up a message. -****************************************************************************/ - -static void free_queued_message(struct pending_message_list *msg) -{ - data_blob_free(&msg->buf); - data_blob_free(&msg->private_data); - SAFE_FREE(msg); -} +static struct pending_message_list *deferred_open_queue; /**************************************************************************** Function to push a message onto the tail of a linked list of smb messages ready for processing. ****************************************************************************/ -static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private_data, size_t private_len) +static BOOL push_queued_message(char *buf, int msg_len, + struct timeval request_time, + struct timeval end_time, + char *private_data, size_t private_len) { struct pending_message_list *tmp_msg; - struct pending_message_list *msg = SMB_MALLOC_P(struct pending_message_list); + struct pending_message_list *msg; + + msg = TALLOC_ZERO_P(NULL, struct pending_message_list); if(msg == NULL) { DEBUG(0,("push_message: malloc fail (1)\n")); return False; } - memset(msg,'\0',sizeof(*msg)); - - msg->buf = data_blob(buf, msg_len); + msg->buf = data_blob_talloc(msg, buf, msg_len); if(msg->buf.data == NULL) { DEBUG(0,("push_message: malloc fail (2)\n")); - SAFE_FREE(msg); + talloc_free(msg); return False; } - if (ptv) { - msg->msg_time = *ptv; - } + msg->request_time = request_time; + msg->end_time = end_time; if (private_data) { - msg->private_data = data_blob(private_data, private_len); + msg->private_data = data_blob_talloc(msg, private_data, + private_len); if (msg->private_data.data == NULL) { DEBUG(0,("push_message: malloc fail (3)\n")); - data_blob_free(&msg->buf); - SAFE_FREE(msg); + talloc_free(msg); return False; } } - if (qt == OPLOCK_QUEUE) { - DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg); - } else { - DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg); - } + DLIST_ADD_END(deferred_open_queue, msg, tmp_msg); - DEBUG(10,("push_message: pushed message length %u on queue %s\n", - (unsigned int)msg_len, - qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" )); + DEBUG(10,("push_message: pushed message length %u on " + "deferred_open_queue\n", (unsigned int)msg_len)); return True; } -/**************************************************************************** - Function to push an oplock smb message onto a linked list of local smb messages ready - for processing. -****************************************************************************/ - -BOOL push_oplock_pending_smb_message(char *buf, int msg_len) -{ - BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0); - if (ret) { - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(buf,smb_mid)); - } - return ret; -} - /**************************************************************************** Function to delete a sharing violation open message by mid. ****************************************************************************/ -void remove_sharing_violation_open_smb_message(uint16 mid) +void remove_deferred_open_smb_message(uint16 mid) { struct pending_message_list *pml; - if (!lp_defer_sharing_violations()) { - return; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { - DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n", - (unsigned int)mid, (unsigned int)pml->buf.length )); - DLIST_REMOVE(smb_sharing_violation_queue, pml); - free_queued_message(pml); + DEBUG(10,("remove_sharing_violation_open_smb_message: " + "deleting mid %u len %u\n", + (unsigned int)mid, + (unsigned int)pml->buf.length )); + DLIST_REMOVE(deferred_open_queue, pml); + talloc_free(pml); return; } } @@ -176,30 +142,26 @@ void remove_sharing_violation_open_smb_message(uint16 mid) schedule it for immediate processing. ****************************************************************************/ -void schedule_sharing_violation_open_smb_message(uint16 mid) +void schedule_deferred_open_smb_message(uint16 mid) { struct pending_message_list *pml; int i = 0; - if (!lp_defer_sharing_violations()) { - return; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { uint16 msg_mid = SVAL(pml->buf.data,smb_mid); - DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++, + DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++, (unsigned int)msg_mid )); if (mid == msg_mid) { - DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n", + DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n", mid )); - pml->msg_time.tv_sec = 0; - pml->msg_time.tv_usec = 0; - DLIST_PROMOTE(smb_sharing_violation_queue, pml); + pml->end_time.tv_sec = 0; + pml->end_time.tv_usec = 0; + DLIST_PROMOTE(deferred_open_queue, pml); return; } } - DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n", + DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n", mid )); } @@ -211,13 +173,9 @@ BOOL open_was_deferred(uint16 mid) { struct pending_message_list *pml; - if (!lp_defer_sharing_violations()) { - return False; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { - set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return True; } } @@ -232,11 +190,7 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) { struct pending_message_list *pml; - if (!lp_defer_sharing_violations()) { - return NULL; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { return pml; } @@ -245,57 +199,216 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) } /**************************************************************************** - Function to push a sharing violation open smb message onto a linked list of local smb messages ready - for processing. We must use current_inbuf here not Inbuf in case we're in a chained message set. + Function to push a deferred open smb message onto a linked list of local smb + messages ready for processing. +****************************************************************************/ + +BOOL push_deferred_smb_message(uint16 mid, + struct timeval request_time, + struct timeval timeout, + char *private_data, size_t priv_len) +{ + struct timeval end_time; + + end_time = timeval_sum(&request_time, &timeout); + + DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u " + "timeout time [%u.%06u]\n", + (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, + (unsigned int)end_time.tv_sec, + (unsigned int)end_time.tv_usec)); + + return push_queued_message(current_inbuf, smb_len(current_inbuf)+4, + request_time, end_time, + private_data, priv_len); +} + +static struct timed_event *timed_events; + +struct timed_event { + struct timed_event *next, *prev; + struct timeval when; + const char *event_name; + void (*handler)(struct timed_event *te, + const struct timeval *now, + void *private_data); + void *private_data; +}; + +static int timed_event_destructor(void *p) +{ + struct timed_event *te = talloc_get_type_abort(p, struct timed_event); + DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te, + te->event_name)); + DLIST_REMOVE(timed_events, te); + return 0; +} + +/**************************************************************************** + Schedule a function for future calling, cancel with talloc_free(). + It's the responsibility of the handler to call talloc_free() on the event + handed to it. ****************************************************************************/ -BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private_data, size_t priv_len) +struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx, + struct timeval when, + const char *event_name, + void (*handler)(struct timed_event *te, + const struct timeval *now, + void *private_data), + void *private_data) { - uint16 mid = SVAL(current_inbuf,smb_mid); - struct timeval tv; - SMB_BIG_INT tdif; + struct timed_event *te, *last_te, *cur_te; - if (!lp_defer_sharing_violations()) { - return True; + te = TALLOC_P(mem_ctx, struct timed_event); + if (te == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - tv = *ptv; - tdif = tv.tv_sec; - tdif *= 1000000; - tdif += tv.tv_usec; + te->when = when; + te->event_name = event_name; + te->handler = handler; + te->private_data = private_data; + + /* keep the list ordered */ + last_te = NULL; + for (cur_te = timed_events; cur_te; cur_te = cur_te->next) { + /* if the new event comes before the current one break */ + if (!timeval_is_zero(&cur_te->when) && + timeval_compare(&te->when, &cur_te->when) < 0) { + break; + } + last_te = cur_te; + } - /* Add on the timeout. */ - tdif += SHARING_VIOLATION_USEC_WAIT; - - tv.tv_sec = tdif / 1000000; - tv.tv_usec = tdif % 1000000; - - DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\ - timeout time [%u.%06u]\n", (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, - (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec)); + DLIST_ADD_AFTER(timed_events, te, last_te); + talloc_set_destructor(te, timed_event_destructor); - return push_queued_message(SHARE_VIOLATION_QUEUE, current_inbuf, - smb_len(current_inbuf)+4, &tv, private_data, priv_len); + DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name, + (unsigned long)te)); + return te; } +static void run_events(void) +{ + struct timeval now; + + if (timed_events == NULL) { + /* No syscall if there are no events */ + DEBUG(10, ("run_events: No events\n")); + return; + } + + GetTimeOfDay(&now); + + if (timeval_compare(&now, &timed_events->when) < 0) { + /* Nothing to do yet */ + DEBUG(10, ("run_events: Nothing to do\n")); + return; + } + + DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name, + (unsigned long)timed_events)); + + timed_events->handler(timed_events, &now, timed_events->private_data); + return; +} + +struct timeval timed_events_timeout(void) +{ + struct timeval now, timeout; + + if (timed_events == NULL) { + return timeval_set(SMBD_SELECT_TIMEOUT, 0); + } + + now = timeval_current(); + timeout = timeval_until(&now, &timed_events->when); + + DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec, + (int)timeout.tv_usec)); + + return timeout; +} + +struct idle_event { + struct timed_event *te; + struct timeval interval; + BOOL (*handler)(const struct timeval *now, void *private_data); + void *private_data; +}; + +static void idle_event_handler(struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct idle_event *event = + talloc_get_type_abort(private_data, struct idle_event); + + talloc_free(event->te); + + if (!event->handler(now, event->private_data)) { + /* Don't repeat, delete ourselves */ + talloc_free(event); + return; + } + + event->te = add_timed_event(event, timeval_sum(now, &event->interval), + "idle_event_handler", + idle_event_handler, event); + + /* We can't do much but fail here. */ + SMB_ASSERT(event->te != NULL); +} + +struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, + struct timeval interval, + BOOL (*handler)(const struct timeval *now, + void *private_data), + void *private_data) +{ + struct idle_event *result; + struct timeval now = timeval_current(); + + result = TALLOC_P(mem_ctx, struct idle_event); + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + result->interval = interval; + result->handler = handler; + result->private_data = private_data; + + result->te = add_timed_event(result, timeval_sum(&now, &interval), + "idle_event_handler", + idle_event_handler, result); + if (result->te == NULL) { + DEBUG(0, ("add_timed_event failed\n")); + talloc_free(result); + return NULL; + } + + return result; +} + /**************************************************************************** - Do all async processing in here. This includes UDB oplock messages, kernel - oplock messages, change notify events etc. + Do all async processing in here. This includes kernel oplock messages, change + notify events etc. ****************************************************************************/ -static void async_processing(char *buffer, int buffer_len) +static void async_processing(void) { DEBUG(10,("async_processing: Doing async processing.\n")); process_aio_queue(); - /* check for oplock messages (both UDP and kernel) */ - if (receive_local_message(buffer, buffer_len, 1)) { - process_local_message(buffer, buffer_len); - } + process_kernel_oplocks(); - /* Do the aio check again after receive_local_message as it does a select - and may have eaten our signal. */ + /* Do the aio check again after receive_local_message as it does a + select and may have eaten our signal. */ + /* Is this till true? -- vl */ process_aio_queue(); if (got_sig_term) { @@ -339,17 +452,17 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) { fd_set fds; int selrtn; - struct timeval to; - struct timeval *pto; + struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0); int maxfd; smb_read_error = 0; again: - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - pto = timeout > 0 ? &to : NULL; + if (timeout >= 0) { + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; + } /* * Note that this call must be before processing any SMB @@ -358,38 +471,22 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ message_dispatch(); - /* - * Check to see if we already have a message on the smb queue. - * If so - copy and return it. - */ - if(smb_oplock_queue != NULL) { - struct pending_message_list *msg = smb_oplock_queue; - memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length)); - - /* Free the message we just copied. */ - DLIST_REMOVE(smb_oplock_queue, msg); - free_queued_message(msg); - - DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); - return True; - } - /* * Check to see if we already have a message on the deferred open queue * and it's time to schedule. */ - if(smb_sharing_violation_queue != NULL) { + if(deferred_open_queue != NULL) { BOOL pop_message = False; - struct pending_message_list *msg = smb_sharing_violation_queue; + struct pending_message_list *msg = deferred_open_queue; - if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) { + if (timeval_is_zero(&msg->end_time)) { pop_message = True; } else { struct timeval tv; SMB_BIG_INT tdif; GetTimeOfDay(&tv); - tdif = usec_time_diff(&msg->msg_time, &tv); + tdif = usec_time_diff(&msg->end_time, &tv); if (tdif <= 0) { /* Timed out. Schedule...*/ pop_message = True; @@ -398,9 +495,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) /* Make a more accurate select timeout. */ to.tv_sec = tdif / 1000000; to.tv_usec = tdif % 1000000; - pto = &to; DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n", - (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec )); + (unsigned int)to.tv_sec, (unsigned int)to.tv_usec )); } } @@ -431,7 +527,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) if (oplock_message_waiting(&fds)) { DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n")); - async_processing(buffer, buffer_len); + async_processing(); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -439,18 +535,26 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ goto again; } + + { + struct timeval tmp = timed_events_timeout(); + to = timeval_min(&to, &tmp); + if (timeval_is_zero(&to)) { + return True; + } + } FD_SET(smbd_server_fd(),&fds); maxfd = setup_oplock_select_set(&fds); - selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto); + selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to); /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but is the best we can do until the oplock code knows more about signals */ if (selrtn == -1 && errno == EINTR) { - async_processing(buffer, buffer_len); + async_processing(); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -479,7 +583,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ if (oplock_message_waiting(&fds)) { - async_processing(buffer, buffer_len); + async_processing(); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -518,8 +622,6 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) void respond_to_all_remaining_local_messages(void) { - char buffer[1024]; - /* * Assert we have no exclusive open oplocks. */ @@ -530,15 +632,7 @@ void respond_to_all_remaining_local_messages(void) return; } - /* - * Keep doing receive_local_message with a 1 ms timeout until - * we have no more messages. - */ - - while(receive_local_message(buffer, sizeof(buffer), 1)) { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(buffer, sizeof(buffer)); - } + process_kernel_oplocks(); return; } @@ -556,8 +650,7 @@ force write permissions on print services. #define TIME_INIT (1<<2) #define CAN_IPC (1<<3) #define AS_GUEST (1<<5) -#define QUEUE_IN_OPLOCK (1<<6) -#define DO_CHDIR (1<<7) +#define DO_CHDIR (1<<6) /* define a list of possible SMB messages and their corresponding @@ -572,19 +665,19 @@ static const struct smb_message_struct { /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, -/* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK }, +/* 0x02 */ { "SMBopen",reply_open,AS_USER }, /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER}, /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC }, /* 0x05 */ { "SMBflush",reply_flush,AS_USER}, -/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, -/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, +/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, +/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE }, /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER}, /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, /* 0x0a */ { "SMBread",reply_read,AS_USER}, /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC }, /* 0x0c */ { "SMBlock",reply_lock,AS_USER}, /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER}, -/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, +/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER }, /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER}, /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR}, @@ -611,11 +704,11 @@ static const struct smb_message_struct { /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",reply_ioctl,0}, /* 0x28 */ { "SMBioctls",NULL,AS_USER}, -/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, -/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, +/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE }, +/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE }, /* 0x2b */ { "SMBecho",reply_echo,0}, /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER}, -/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, +/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC }, /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, /* 0x30 */ { NULL, NULL, 0 }, @@ -730,12 +823,12 @@ static const struct smb_message_struct { /* 0x9d */ { NULL, NULL, 0 }, /* 0x9e */ { NULL, NULL, 0 }, /* 0x9f */ { NULL, NULL, 0 }, -/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, +/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, -/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, +/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC }, /* 0xa3 */ { NULL, NULL, 0 }, /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 }, -/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, +/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE }, /* 0xa6 */ { NULL, NULL, 0 }, /* 0xa7 */ { NULL, NULL, 0 }, /* 0xa8 */ { NULL, NULL, 0 }, @@ -762,7 +855,7 @@ static const struct smb_message_struct { /* 0xbd */ { NULL, NULL, 0 }, /* 0xbe */ { NULL, NULL, 0 }, /* 0xbf */ { NULL, NULL, 0 }, -/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK }, +/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER}, /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER}, /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER}, /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER}, @@ -871,7 +964,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize pid = sys_getpid(); errno = 0; - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); last_message = type; @@ -900,19 +993,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn)); smb_dump(smb_fn_name(type), 1, inbuf, size); - if(global_oplock_break) { - if(flags & QUEUE_IN_OPLOCK) { - /* - * Queue this message as we are the process of an oplock break. - */ - - DEBUG( 2, ( "switch_message: queueing message due to being in " ) ); - DEBUGADD( 2, ( "oplock break state.\n" ) ); - - push_oplock_pending_smb_message( inbuf, size ); - return -1; - } - } /* Ensure this value is replaced in the incoming packet. */ SSVAL(inbuf,smb_uid,session_tag); @@ -1289,6 +1369,7 @@ static int setup_select_timeout(void) select_timeout *= 1000; t = change_notify_timeout(); + DEBUG(10, ("change_notify_timeout: %d\n", t)); if (t != -1) select_timeout = MIN(select_timeout, t*1000); @@ -1302,7 +1383,7 @@ static int setup_select_timeout(void) Check if services need reloading. ****************************************************************************/ -void check_reload(int t) +void check_reload(time_t t) { static pid_t mypid = 0; static time_t last_smb_conf_reload_time = 0; @@ -1644,6 +1725,8 @@ void smbd_process(void) num_smbs = 0; /* Reset smb counter. */ } + run_events(); + #if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); #endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5572f47e42..ba22a56cfb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -30,7 +30,6 @@ extern enum protocol_types Protocol; extern int max_send; extern int max_recv; -extern int global_oplock_break; unsigned int smb_echo_count = 0; extern uint32 global_client_caps; @@ -1779,7 +1778,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, } /* We need a better way to return NT status codes from open... */ - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); fsp = open_file_ntcreate(conn, fname, pst, DELETE_ACCESS, @@ -1791,12 +1790,12 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, NULL); if (!fsp) { - NTSTATUS ret; - if (get_saved_error_triple(NULL, NULL, &ret)) { - set_saved_error_triple(0, 0, NT_STATUS_OK); + NTSTATUS ret = get_saved_ntstatus(); + if (!NT_STATUS_IS_OK(ret)) { + set_saved_ntstatus(NT_STATUS_OK); return ret; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); @@ -1860,7 +1859,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b don't do it here as we'll get it wrong. */ /* We need a better way to return NT status codes from open... */ - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); fsp = open_file_ntcreate(conn, fname, &sbuf, DELETE_ACCESS, @@ -1872,12 +1871,12 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b NULL); if (!fsp) { - NTSTATUS ret; - if (get_saved_error_triple(NULL, NULL, &ret)) { - set_saved_error_triple(0, 0, NT_STATUS_OK); + NTSTATUS ret = get_saved_ntstatus(); + if (!NT_STATUS_IS_OK(ret)) { + set_saved_ntstatus(NT_STATUS_OK); return ret; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); @@ -2209,15 +2208,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s * return a zero length response here. */ - if(global_oplock_break) { - _smb_setlen(header,0); - if (write_data(smbd_server_fd(),header,4) != 4) - fail_readraw(); - DEBUG(5,("readbraw - oplock break finished\n")); - END_PROFILE(SMBreadbraw); - return -1; - } - fsp = file_fsp(inbuf,smb_vwv0); if (!FNUM_OK(fsp,conn) || !fsp->can_read) { @@ -2298,8 +2288,8 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s nread = 0; #endif - DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, - (int)maxcount, (int)mincount, (int)nread ) ); + DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos, + (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) ); send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize); @@ -3744,7 +3734,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if( is_ntfs_stream_name(directory)) { DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory)); END_PROFILE(SMBmkdir); - return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname); + return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY); } status = mkdir_internal(conn, directory,bad_path); @@ -5084,7 +5074,8 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma Reply to a lockingX request. ****************************************************************************/ -int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, + int length, int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); unsigned char locktype = CVAL(inbuf,smb_vwv3); @@ -5096,7 +5087,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; + BOOL large_file_format = + (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; BOOL err; BOOL my_lock_ctx = False; NTSTATUS status; @@ -5125,19 +5117,25 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { /* Client can insist on breaking to none. */ BOOL break_to_none = (oplocklevel == 0); - - DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n", - (unsigned int)oplocklevel, fsp->fnum )); + BOOL result; + + DEBUG(5,("reply_lockingX: oplock break reply (%u) from client " + "for fnum = %d\n", (unsigned int)oplocklevel, + fsp->fnum )); /* - * Make sure we have granted an exclusive or batch oplock on this file. + * Make sure we have granted an exclusive or batch oplock on + * this file. */ - if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ -no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); - - /* if this is a pure oplock break request then don't send a reply */ + if (fsp->oplock_type == 0) { + DEBUG(0,("reply_lockingX: Error : oplock break from " + "client for fnum = %d (oplock=%d) and no " + "oplock granted on this file (%s).\n", + fsp->fnum, fsp->oplock_type, fsp->fsp_name)); + + /* if this is a pure oplock break request then don't + * send a reply */ if (num_locks == 0 && num_ulocks == 0) { END_PROFILE(SMBlockingX); return -1; @@ -5147,17 +5145,30 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); } } - if (remove_oplock(fsp, break_to_none) == False) { - DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n", - fsp->fsp_name )); + if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) || + (break_to_none)) { + result = remove_oplock(fsp); + } else { + result = downgrade_oplock(fsp); } - /* if this is a pure oplock break request then don't send a reply */ + if (!result) { + DEBUG(0, ("reply_lockingX: error in removing " + "oplock on file %s\n", fsp->fsp_name)); + /* Hmmm. Is this panic justified? */ + smb_panic("internal tdb error"); + } + + reply_to_oplock_break_requests(fsp); + + /* if this is a pure oplock break request then don't send a + * reply */ if (num_locks == 0 && num_ulocks == 0) { /* Sanity check - ensure a pure oplock break is not a chained request. */ if(CVAL(inbuf,smb_vwv0) != 0xff) - DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", + DEBUG(0,("reply_lockingX: Error : pure oplock " + "break is a chained %d request !\n", (unsigned int)CVAL(inbuf,smb_vwv0) )); END_PROFILE(SMBlockingX); return -1; @@ -5186,8 +5197,9 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR_DOS(ERRDOS,ERRnoaccess); } - DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n", - (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); + DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for " + "pid %u, file %s\n", (double)offset, (double)count, + (unsigned int)lock_pid, fsp->fsp_name )); status = do_unlock(fsp,conn,lock_pid,count,offset); if (NT_STATUS_V(status)) { @@ -5219,27 +5231,34 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR_DOS(ERRDOS,ERRnoaccess); } - DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n", - (double)offset, (double)count, (unsigned int)lock_pid, - fsp->fsp_name, (int)lock_timeout )); + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid " + "%u, file %s timeout = %d\n", (double)offset, + (double)count, (unsigned int)lock_pid, + fsp->fsp_name, (int)lock_timeout )); status = do_lock_spin(fsp,conn,lock_pid, count,offset, - ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx); + ((locktype & 1) ? READ_LOCK:WRITE_LOCK), + &my_lock_ctx); if (NT_STATUS_V(status)) { /* - * Interesting fact found by IFSTEST /t LockOverlappedTest... - * Even if it's our own lock context, we need to wait here as - * there may be an unlock on the way. - * So I removed a "&& !my_lock_ctx" from the following - * if statement. JRA. + * Interesting fact found by IFSTEST /t + * LockOverlappedTest... Even if it's our own lock + * context, we need to wait here as there may be an + * unlock on the way. So I removed a "&& + * !my_lock_ctx" from the following if statement. JRA. */ - if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { + if ((lock_timeout != 0) && + lp_blocking_locks(SNUM(conn)) && + ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) { + if(push_blocking_lock_request(inbuf, length, + lock_timeout, i, + lock_pid, offset, + count)) { END_PROFILE(SMBlockingX); return -1; } @@ -5259,10 +5278,12 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); for(i--; i >= 0; i--) { lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); + offset = get_lock_offset( data, i, large_file_format, + &err); /* - * There is no error code marked "stupid client bug".... :-). + * There is no error code marked "stupid client + * bug".... :-). */ if(err) { END_PROFILE(SMBlockingX); @@ -5277,8 +5298,8 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); set_message(outbuf,2,0,True); - DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", - fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); + DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", + fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); END_PROFILE(SMBlockingX); return chain_reply(inbuf,outbuf,length,bufsize); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1ff03174fe..8310b408d0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -96,7 +96,7 @@ static void killkids(void) somewhere else. ****************************************************************************/ -static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), +static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid), void *UNUSED(buf), size_t UNUSED(len)) { DEBUG(10, ("** sam sync message received, ignoring\n")); @@ -107,7 +107,8 @@ static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), somewhere else. ****************************************************************************/ -static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len) +static void msg_sam_repl(int msg_type, struct process_id pid, + void *buf, size_t len) { uint32 low_serial; @@ -140,7 +141,8 @@ static BOOL open_sockets_inetd(void) return True; } -static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) +static void msg_exit_server(int msg_type, struct process_id src, + void *buf, size_t len) { exit_server("Got a SHUTDOWN message"); } @@ -621,9 +623,6 @@ void exit_server(const char *reason) print_notify_send_messages(3); /* 3 second timeout. */ - /* run all registered exit events */ - smb_run_exit_events(); - /* delete our entry in the connections database. */ yield_connection(NULL,""); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index bf7287aab9..fc2d8b4abb 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -139,6 +139,7 @@ static int reply_spnego_kerberos(connection_struct *conn, int length, int bufsize, DATA_BLOB *secblob) { + TALLOC_CTX *mem_ctx; DATA_BLOB ticket; char *client, *p, *domain; fstring netbios_domain_name; @@ -146,7 +147,7 @@ static int reply_spnego_kerberos(connection_struct *conn, fstring user; int sess_vuid; NTSTATUS ret; - DATA_BLOB auth_data; + PAC_DATA *pac_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob(NULL, 0); @@ -154,18 +155,24 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB nullblob = data_blob(NULL, 0); fstring real_username; BOOL map_domainuser_to_guest = False; + PAC_LOGON_INFO *logon_info = NULL; + int i; ZERO_STRUCT(ticket); - ZERO_STRUCT(auth_data); + ZERO_STRUCT(pac_data); ZERO_STRUCT(ap_rep); ZERO_STRUCT(ap_rep_wrapped); ZERO_STRUCT(response); + mem_ctx = talloc_init("reply_spnego_kerberos"); + if (mem_ctx == NULL) + return ERROR_NT(NT_STATUS_NO_MEMORY); + if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key); + ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key); data_blob_free(&ticket); @@ -174,7 +181,18 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - data_blob_free(&auth_data); + if (pac_data) { + + /* get the logon_info */ + for (i=0; i < pac_data->num_buffers; i++) { + + if (pac_data->pac_buffer[i].type != PAC_TYPE_LOGON_INFO) + continue; + + logon_info = pac_data->pac_buffer[i].ctr->pac.logon_info; + break; + } + } DEBUG(3,("Ticket name is [%s]\n", client)); @@ -203,7 +221,14 @@ static int reply_spnego_kerberos(connection_struct *conn, domain = p+1; - { + if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { + + unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1); + domain = netbios_domain_name; + DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); + + } else { + /* If we have winbind running, we can (and must) shorten the username by using the short netbios name. Otherwise we will have inconsistent user names. With Kerberos, we get the @@ -231,7 +256,7 @@ static int reply_spnego_kerberos(connection_struct *conn, wb_response.data.domain_info.name); domain = netbios_domain_name; - DEBUG(10, ("Mapped to [%s]\n", domain)); + DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain)); } else { DEBUG(3, ("Could not find short name -- winbind " "not running?\n")); @@ -274,8 +299,21 @@ static int reply_spnego_kerberos(connection_struct *conn, reload_services(True); if ( map_domainuser_to_guest ) { make_server_info_guest(&server_info); + } else if (logon_info) { + ret = make_server_info_pac(&server_info, real_username, pw, logon_info); + + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(1,("make_server_info_pac failed!\n")); + SAFE_FREE(client); + data_blob_free(&ap_rep); + data_blob_free(&session_key); + passwd_free(&pw); + return ERROR_NT(ret); + } + } else { ret = make_server_info_pw(&server_info, real_username, pw); + if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_from_pw failed!\n")); SAFE_FREE(client); @@ -284,15 +322,17 @@ static int reply_spnego_kerberos(connection_struct *conn, passwd_free(&pw); return ERROR_NT(ret); } + + /* make_server_info_pw does not set the domain. Without this we end up + * with the local netbios name in substitutions for %D. */ + + if (server_info->sam_account != NULL) { + pdb_set_domain(server_info->sam_account, domain, PDB_SET); + } } - passwd_free(&pw); - /* make_server_info_pw does not set the domain. Without this we end up - * with the local netbios name in substitutions for %D. */ - if (server_info->sam_account != NULL) { - pdb_set_domain(server_info->sam_account, domain, PDB_SET); - } + passwd_free(&pw); /* register_vuid keeps the server info */ /* register_vuid takes ownership of session_key, no need to free after this. @@ -339,6 +379,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&response); + talloc_destroy(mem_ctx); return -1; /* already replied */ } @@ -348,6 +389,8 @@ static int reply_spnego_kerberos(connection_struct *conn, Send a session setup reply, wrapped in SPNEGO. Get vuid and check first. End the NTLMSSP exchange context if we are OK/complete fail + This should be split into two functions, one to handle each + leg of the NTLM auth steps. ***************************************************************************/ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, @@ -422,6 +465,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out and the other end, that we are not finished yet. */ if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + /* NB. This is *NOT* an error case. JRA */ auth_ntlmssp_end(auth_ntlmssp_state); /* Kill the intermediate vuid */ invalidate_vuid(vuid); @@ -660,7 +704,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, return ret; } - if (strncmp(blob1.data, "NTLMSSP", 7) == 0) { + if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) { DATA_BLOB chal; NTSTATUS nt_status; if (!vuser->auth_ntlmssp_state) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 38363bf66a..f0b7812a1e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -27,7 +27,6 @@ extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; -extern int global_oplock_break; extern uint32 global_client_caps; extern struct current_user current_user; @@ -2789,7 +2788,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * delete_pending = get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino); + sbuf.st_ino, + fname); } else { /* * Original code - this is an open file. @@ -2804,7 +2804,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * pos = fsp->fh->position_information; delete_pending = get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino); + sbuf.st_ino, + fname); access_mask = fsp->access_mask; } } else { @@ -2847,7 +2848,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * } delete_pending = get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino); + sbuf.st_ino, + fname); if (delete_pending) { return ERROR_NT(NT_STATUS_DELETE_PENDING); } @@ -3454,91 +3456,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return(-1); } -/**************************************************************************** - Deal with the internal needs of setting the delete on close flag. Note that - as the tdb locking is recursive, it is safe to call this from within - open_file_shared. JRA. -****************************************************************************/ - -NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, - uint32 dosmode) -{ - if (!delete_on_close) { - return NT_STATUS_OK; - } - - /* - * Only allow delete on close for writable files. - */ - - if ((dosmode & aRONLY) && - !lp_delete_readonly(SNUM(fsp->conn))) { - DEBUG(10,("can_set_delete_on_close: file %s delete on close " - "flag set but file attribute is readonly.\n", - fsp->fsp_name )); - return NT_STATUS_CANNOT_DELETE; - } - - /* - * Only allow delete on close for writable shares. - */ - - if (!CAN_WRITE(fsp->conn)) { - DEBUG(10,("can_set_delete_on_close: file %s delete on " - "close flag set but write access denied on share.\n", - fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } - - /* - * Only allow delete on close for files/directories opened with delete - * intent. - */ - - if (!(fsp->access_mask & DELETE_ACCESS)) { - DEBUG(10,("can_set_delete_on_close: file %s delete on " - "close flag set but delete access denied.\n", - fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } - - return NT_STATUS_OK; -} - -/**************************************************************************** - Sets the delete on close flag over all share modes on this file. - Modify the share mode entry for all files open - on this device and inode to tell other smbds we have - changed the delete on close flag. This will be noticed - in the close code, the last closer will delete the file - if flag is set. -****************************************************************************/ - -NTSTATUS set_delete_on_close(files_struct *fsp, BOOL delete_on_close) -{ - DEBUG(10,("set_delete_on_close: %s delete on close flag for " - "fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, - fsp->fsp_name )); - - if (fsp->is_directory || fsp->is_stat) - return NT_STATUS_OK; - - if (lock_share_entry_fsp(fsp) == False) - return NT_STATUS_ACCESS_DENIED; - - if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("set_delete_on_close: failed to change delete " - "on close flag for file %s\n", - fsp->fsp_name )); - unlock_share_entry_fsp(fsp); - return NT_STATUS_ACCESS_DENIED; - } - - unlock_share_entry_fsp(fsp); - return NT_STATUS_OK; -} - /**************************************************************************** Set a hard link (called by UNIX extensions and by NT rename with HARD link code. @@ -3912,16 +3829,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (fd == -1) { files_struct *new_fsp = NULL; - if(global_oplock_break) { - /* Queue this file modify as we are the process of an oplock break. */ - - DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); - - push_oplock_pending_smb_message(inbuf, length); - return -1; - } - new_fsp = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE, @@ -4003,9 +3910,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } /* The set is across all open files on this dev/inode pair. */ - status =set_delete_on_close(fsp, delete_on_close); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + if (!set_delete_on_close(fsp, delete_on_close)) { + return ERROR_NT(NT_STATUS_ACCESS_DENIED); } SSVAL(params,0,0); @@ -4456,16 +4362,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (fd == -1) { files_struct *new_fsp = NULL; - if(global_oplock_break) { - /* Queue this file modify as we are the process of an oplock break. */ - - DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); - - push_oplock_pending_smb_message(inbuf, length); - return -1; - } - new_fsp = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE, @@ -4859,18 +4755,6 @@ int reply_trans2(connection_struct *conn, unsigned int num_params, num_params_sofar, num_data, num_data_sofar; START_PROFILE(SMBtrans2); - if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) { - /* Queue this open message as we are the process of an - * oplock break. */ - - DEBUG(2,("reply_trans2: queueing message trans2open due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); - - push_oplock_pending_smb_message(inbuf, length); - END_PROFILE(SMBtrans2); - return -1; - } - if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) { END_PROFILE(SMBtrans2); -- cgit From f3d7084bad17fe1d4745493cbf99faaaf5532ab4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Oct 2005 10:00:07 +0000 Subject: r10672: Attempt to fix the IRIX build. James, could you test the Oplock code on a box? Thanks, Volker (This used to be commit 9fcf83dcd828515a6f6ac535cd47398b7e04e748) --- source3/smbd/oplock_irix.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index f49aa297e4..2224f9a668 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -99,8 +99,9 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) */ if(read(oplock_pipe_read, &dummy, 1) != 1) { - DEBUG(0,("irix_oplock_receive_message: read of kernel notification failed. \ -Error was %s.\n", strerror(errno) )); + DEBUG(0,("irix_oplock_receive_message: read of kernel " + "notification failed. Error was %s.\n", + strerror(errno) )); smb_read_error = READ_ERROR; return NULL; } @@ -112,14 +113,14 @@ Error was %s.\n", strerror(errno) )); */ if(sys_fcntl_ptr(oplock_pipe_read, F_OPLKSTAT, &os) < 0) { - DEBUG(0,("irix_oplock_receive_message: fcntl of kernel notification failed. \ -Error was %s.\n", strerror(errno) )); + DEBUG(0,("irix_oplock_receive_message: fcntl of kernel " + "notification failed. Error was %s.\n", + strerror(errno) )); if(errno == EAGAIN) { /* * Duplicate kernel break message - ignore. */ - memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN); - return True; + return NULL; } smb_read_error = READ_ERROR; return NULL; @@ -130,14 +131,17 @@ Error was %s.\n", strerror(errno) )); * is the first fsp open with this dev,ino pair. */ - if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev, (SMB_INO_T)os.os_ino)) == NULL) { - DEBUG(0,("irix_oplock_receive_message: unable to find open file with dev = %x, inode = %.0f\n", - (unsigned int)os.os_dev, (double)os.os_ino )); - return False; + if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev, + (SMB_INO_T)os.os_ino)) == NULL) { + DEBUG(0,("irix_oplock_receive_message: unable to find open " + "file with dev = %x, inode = %.0f\n", + (unsigned int)os.os_dev, (double)os.os_ino )); + return NULL; } - DEBUG(5,("irix_oplock_receive_message: kernel oplock break request received for \ -dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); + DEBUG(5,("irix_oplock_receive_message: kernel oplock break request " + "received for dev = %x, inode = %.0f\n, file_id = %ul", + (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); return fsp; } -- cgit From 775056f8e494b716276c9f6b1c6130587a8df9ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Oct 2005 18:14:09 +0000 Subject: r10693: Fix bug #3129, reported by Adam Porter . Rotten error message caused hours of wasted time. Jeremy. (This used to be commit f391f065b240d5731d178f9d4a46ffc3315117bc) --- source3/smbd/service.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d330e847e2..52f9229ee1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -272,6 +272,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, SMB_STRUCT_STAT st; fstring user; fstring dev; + int ret; *user = 0; fstrcpy(dev, pdev); @@ -554,7 +555,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(snum)) { - int ret; pstring cmd; pstrcpy(cmd,lp_rootpreexec(snum)); standard_sub_conn(conn,cmd,sizeof(cmd)); @@ -584,7 +584,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "preexec = " line */ if (*lp_preexec(snum)) { - int ret; pstring cmd; pstrcpy(cmd,lp_preexec(snum)); standard_sub_conn(conn,cmd,sizeof(cmd)); @@ -629,8 +628,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, check during individual operations. To match this behaviour I have disabled this chdir check (tridge) */ /* the alternative is just to check the directory exists */ - if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum))); + if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || !S_ISDIR(st.st_mode)) { + if (ret == 0 && !S_ISDIR(st.st_mode)) { + DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum))); + } else { + DEBUG(0,("'%s' does not exist or permission denied when connecting to [%s] " + "Error was %s\n", conn->connectpath, lp_servicename(snum), strerror(errno) )); + } change_to_root_user(); /* Call VFS disconnect hook */ SMB_VFS_DISCONNECT(conn); -- cgit From 94fe079be747ea5899f483dd8d00fdd247de4e33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Oct 2005 22:41:16 +0000 Subject: r10744: Fix for the second incarnation of bug #3088, pushed by Alex Masterov . A fcbopen specific part of the code was erroneously being called as part of the mainline open. Note, that this patch superceeds and replaces the fix that Volker added for this bug (which he added a Samba4 torture test for ) : "Fix a race condition in Samba 3. If two files are opened simultaneously with NTCREATEX_DISP_CREATE (create if not exists, else fail) they might end up with two or more times NT_STATUS_OK as EEXIST is not correctly handled." Jeremy. (This used to be commit 5d7ab9a17e793c05409a16675ac2aa2861c4f89e) --- source3/smbd/open.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 56d31c6940..a8fb8ed38f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1507,22 +1507,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, access_mask); - if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) { - /* - * Two smbd's tried to open exclusively, but only one of them - * succeeded. - */ - file_free(fsp); - return NULL; - } - - if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT)) { - if((fsp_open = open_file(fsp,conn,fname,psbuf, - O_RDONLY,unx_mode,access_mask)) == True) { - flags = O_RDONLY; - } - } - if (!fsp_open) { if (lck != NULL) { talloc_free(lck); -- cgit From 5b455c1755e0b23b96413bee7886c837b476620a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Oct 2005 00:21:02 +0000 Subject: r10749: Remove one more Samba4 smbtorture RAW-OPEN difference from W2K3. Jeremy. (This used to be commit 0e8cf8eef59e38ba9a79f6c688abe9f1ac3bf64d) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ba22a56cfb..4d876d4289 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1353,7 +1353,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, put_dos_date3(outbuf,smb_vwv2,mtime); } SIVAL(outbuf,smb_vwv4,(uint32)size); - SSVAL(outbuf,smb_vwv6,GET_OPENX_MODE(deny_mode)); + SSVAL(outbuf,smb_vwv6,deny_mode); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); -- cgit From 8a1aa2c0034aa69d9a52f4adbb85485d3a0fa9cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Oct 2005 03:41:01 +0000 Subject: r10750: Ensure we match W2K3 in forcing DOS errors in a couple of cases. Jeremy. (This used to be commit 62ba3454251daf59071a6b2663035b04c5438647) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4d876d4289..47da903256 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1312,7 +1312,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask, &share_mode, &create_disposition, &create_options)) { END_PROFILE(SMBopen); - return ERROR_DOS(ERRDOS, ERRbadaccess); + return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); } fsp = open_file_ntcreate(conn,fname,&sbuf, @@ -1435,7 +1435,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt &create_disposition, &create_options)) { END_PROFILE(SMBopenX); - return ERROR_DOS(ERRDOS, ERRbadaccess); + return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); } fsp = open_file_ntcreate(conn,fname,&sbuf, -- cgit From 8ec32e008a2309e04d954bd7c6740740735628db Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 7 Oct 2005 15:43:32 +0000 Subject: r10822: updating copyright info (This used to be commit ef3845366bc883e735b2008243b7c05a403f42ca) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8310b408d0..1bf9dbc374 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -803,7 +803,7 @@ void build_options(BOOL screen); reopen_logs(); DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING)); - DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2004\n")); + DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) ); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); -- cgit From 3ecf9119d5055b0706c485eeba8df1bd898de4ee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Oct 2005 04:25:47 +0000 Subject: r10885: Fix bug where read-only share files are always seen as read-only. Noticed by Andrew Bartlett. Jeremy (This used to be commit a33f4f0d2afe28ca0e3ab6c9ecfcdbaa267a7fbe) --- source3/smbd/dosmode.c | 2 +- source3/smbd/posix_acls.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index efbd5f04cb..6aee6ba426 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -479,7 +479,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times */ /* Check if we have write access. */ - if (can_write_to_file(conn, fname, &sbuf)) { + if (CAN_WRITE(conn) && can_write_to_file(conn, fname, &sbuf)) { /* We are allowed to become root and change the filetime. */ become_root(); ret = SMB_VFS_UTIME(conn,fname, times); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f1c9426676..818bf95b3f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4149,16 +4149,13 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) /**************************************************************************** Actually emulate the in-kernel access checking for write access. We need this to successfully check for ability to write for dos filetimes. + Note this doesn't take into account share write permissions. ****************************************************************************/ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { int ret; - if (!CAN_WRITE(conn)) { - return False; - } - if (current_user.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; -- cgit From e950ef44c48b7a12247e0000f292ec50e466dfd3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Oct 2005 04:28:46 +0000 Subject: r10888: We've already checked 'CAN_WRITE' so we don't need to do it again. Jeremy. (This used to be commit 1c52bf875cfdacb058aa6f54ab27b9f7e2d178dc) --- source3/smbd/dosmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 6aee6ba426..efbd5f04cb 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -479,7 +479,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times */ /* Check if we have write access. */ - if (CAN_WRITE(conn) && can_write_to_file(conn, fname, &sbuf)) { + if (can_write_to_file(conn, fname, &sbuf)) { /* We are allowed to become root and change the filetime. */ become_root(); ret = SMB_VFS_UTIME(conn,fname, times); -- cgit From 9e1cf0d51cd7487fff809dc3756fdac0c1efd9b3 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 11 Oct 2005 14:46:40 +0000 Subject: r10901: BUG 3145: Fix build issue regarding quota support on Solaris (This used to be commit b7de9a6c6963e7d3bb1a05ed15600dd50a8f4a08) --- source3/smbd/quotas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 008f212c2c..8cb94bca3d 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -414,7 +414,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB static int quotastat; -static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) +static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) { if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN )) return(0); @@ -423,7 +423,7 @@ static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) return (1); } -static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) +static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) { if (!xdr_int(xdrsp, "astat)) { DEBUG(6,("nfs_quotas: Status bad or zero\n")); @@ -493,7 +493,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B clnt->cl_auth = authunix_create_default(); DEBUG(9,("nfs_quotas: auth_success\n")); - clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout); + clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, my_xdr_getquota_args, (caddr_t)&args, my_xdr_getquota_rslt, (caddr_t)&gqr, timeout); if (clnt_stat != RPC_SUCCESS) { DEBUG(9,("nfs_quotas: clnt_call fail\n")); -- cgit From 111f8e59955775620789a75c513d994f53ece3fe Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 12 Oct 2005 13:07:37 +0000 Subject: r10921: BUG 3070: fix crash bug in qfsinfo when retrieving quota info (This used to be commit 1599fc38ab2f2beb5d1a240941b879603ce27ae6) --- source3/smbd/trans2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f0b7812a1e..cfb630a572 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2346,7 +2346,6 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned fsp.conn = conn; fsp.fnum = -1; - fsp.fh->fd = -1; /* access check */ if (current_user.uid != 0) { -- cgit From bd87876a8bbefaed700884653ffcc5e1567cac96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Oct 2005 18:20:34 +0000 Subject: r10930: Fix erroneous debug spotted by Herb. Jeremy. (This used to be commit b2e22e7d128dc22d62f56fda294dc7abc076dc64) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a8fb8ed38f..fac3925b10 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1715,7 +1715,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } else { - DEBUG(5, ("open_file_shared: failed to reset " + DEBUG(5, ("open_file_shared: reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ -- cgit From c5260e733c417642a30a59ebe46ed60b8ef18f6c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Oct 2005 21:42:03 +0000 Subject: r10943: Unused variable. Bug #3160 from jason@ncac.gwu.edu Jeremy. (This used to be commit 5647a5d4b0b7e9083963bfe899e9e0f348ec8bf2) --- source3/smbd/open.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fac3925b10..70687ff580 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -628,7 +628,7 @@ static BOOL is_delete_request(files_struct *fsp) { static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) { - int i, num_level2; + int i; struct share_mode_entry *exclusive = NULL; BOOL delay_it = False; BOOL have_level2 = False; @@ -638,8 +638,6 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) return False; } - num_level2 = 0; - if (lck->num_share_modes == 0) { /* No files open at all: Directly grant whatever the client * wants. */ -- cgit From 4a190ec27bf69f849f22daf3060841f9a1c92b4f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Oct 2005 23:08:49 +0000 Subject: r10947: Fix bugs #3133 and #1828 - SPNEGO not working with PocketPC 2003. Our sessionsetup code now handles raw NTLMSSP connects, so we can go back to doing what W2K3 does here which is to send no OID's in the negprot reply when not in a security=ads mode. Jeremy. (This used to be commit 38a70185b7ca20677026103d40f61608e7ad0c90) --- source3/smbd/negprot.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index d4f0167a5f..1f4cb30003 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -177,7 +177,6 @@ static int negprot_spnego(char *p) OID_KERBEROS5_OLD, OID_NTLMSSP, NULL}; - const char *OIDs_plain[] = {OID_NTLMSSP, NULL}; int len; global_spnego_negotiated = True; @@ -198,20 +197,22 @@ static int negprot_spnego(char *p) } #endif -#if 0 /* strangely enough, NT does not sent the single OID NTLMSSP when not a ADS member, it sends no OIDs at all - we can't do this until we teach our sesssion setup parser to know - about raw NTLMSSP (clients send no ASN.1 wrapping if we do this) + OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know + about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)" + + Our sessionsetup code now handles raw NTLMSSP connects, so we can go + back to doing what W2K3 does here. This is needed to make PocketPC 2003 + CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133 + for details. JRA. + */ - if (lp_security() != SEC_ADS) { + + if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { memcpy(p, guid, 16); return 16; - } -#endif - if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { - blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); } else { fstring myname; char *host_princ_s = NULL; -- cgit From 97a321e557e494e98fa745ec530202120a69403e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Oct 2005 19:45:24 +0000 Subject: r10974: Get closer to trying to fix #1825 (PcoketPC spnego bug). Ensure we set keylen to zero if no spnego. Jeremy. (This used to be commit 57ed94e6e4a095422496d92a0095dc48cfecdd68) --- source3/smbd/negprot.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 1f4cb30003..91942bf028 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -167,7 +167,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) Generate the spnego negprot reply blob. Return the number of bytes used. ****************************************************************************/ -static int negprot_spnego(char *p) +static int negprot_spnego(char *p, uint8 *pkeylen) { DATA_BLOB blob; nstring dos_name; @@ -212,6 +212,7 @@ static int negprot_spnego(char *p) if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { memcpy(p, guid, 16); + *pkeylen = 0; return 16; } else { fstring myname; @@ -224,6 +225,11 @@ static int negprot_spnego(char *p) } memcpy(p, blob.data, blob.length); len = blob.length; + if (len > 256) { + DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len)); + len = 255; + } + *pkeylen = len; data_blob_free(&blob); return len; } @@ -324,16 +330,17 @@ static int reply_nt1(char *inbuf, char *outbuf) /* note that we do not send a challenge at all if we are using plaintext */ get_challenge(p); - SSVALS(outbuf,smb_vwv16+1,8); + SCVAL(outbuf,smb_vwv16+1,8); p += 8; } p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); } else { - int len = negprot_spnego(p); + uint8 keylen; + int len = negprot_spnego(p, &keylen); - SSVALS(outbuf,smb_vwv16+1,len); + SCVAL(outbuf,smb_vwv16+1,keylen); p += len; DEBUG(3,("using SPNEGO\n")); } -- cgit From a1eb5255042c3ff246e27a3cd3cdfd869c5542d3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Oct 2005 01:09:37 +0000 Subject: r10979: After discussions on IRC about profile shares, added new parameter : map readonly = [yes|no|permissions] If yes: map inverse of user "w" bit to mean readonly. If no: never set DOS readonly bit. If permissions: check file permissions for user and set readonly bit if the current user cannot write. If store dos attributes is set to yes then this parameter is ignored. Jeremy. (This used to be commit da4238d18c7a57d1264db8517fb027a10a11baed) --- source3/smbd/dosmode.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index efbd5f04cb..fec148b8e6 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -129,14 +129,19 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL c uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { int result = 0; + enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn)); - if (lp_acl_check_permissions(SNUM(conn))) { + if (ro_opts == MAP_READONLY_YES) { + /* Original Samba method - map inverse of user "w" bit. */ + if ((sbuf->st_mode & S_IWUSR) == 0) { + result |= aRONLY; + } + } else if (ro_opts == MAP_READONLY_PERMISSIONS) { + /* Check actual permissions for read-only. */ if (!can_write_to_file(conn, path, sbuf)) { result |= aRONLY; } - } else if ((sbuf->st_mode & S_IWUSR) == 0) { - result |= aRONLY; - } + } /* Else never set the readonly bit. */ if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) result |= aARCH; -- cgit From bb68761a500fc5d426c75e53700fa793e016135f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 14 Oct 2005 16:07:00 +0000 Subject: r11060: merging new eventlog code from trunk (This used to be commit 1bcf7e82ede63a851a244162a3b939373787b693) --- source3/smbd/posix_acls.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 818bf95b3f..ffb1698394 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4182,3 +4182,58 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST /* Finally check other write access. */ return (psbuf->st_mode & S_IWOTH) ? True : False; } + +/******************************************************************** + Pull the NT ACL from a file on disk or the OpenEventlog() access + check. Caller is responsible for freeing the returned security + descriptor via TALLOC_FREE(). This is designed for dealing with + user space access checks in smbd outside of the VFS. For example, + checking access rights in OpenEventlog(). + + Assume we are dealing with files (for now) +********************************************************************/ + +SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) +{ + SEC_DESC *psd, *ret_sd; + size_t sd_size; + connection_struct conn; + files_struct finfo; + struct fd_handle fh; + fstring path; + pstring filename; + + ZERO_STRUCT( conn ); + conn.service = -1; + + if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) { + DEBUG(0,("novfs_get_nt_acl: talloc() failed!\n")); + return NULL; + } + + fstrcpy( path, "/" ); + string_set(&conn.connectpath, path); + + if (!smbd_vfs_init(&conn)) { + DEBUG(0,("novfs_get_nt_acl: Unable to create a fake connection struct!\n")); + return NULL; + } + + ZERO_STRUCT( finfo ); + ZERO_STRUCT( fh ); + + finfo.fnum = -1; + finfo.conn = &conn; + finfo.fh = &fh; + finfo.fh->fd = -1; + pstrcpy( filename, fname ); + finfo.fsp_name = filename; + + sd_size = get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ); + + ret_sd = dup_sec_desc( ctx, psd ); + + conn_free_internal( &conn ); + + return ret_sd; +} -- cgit From 8d7c88667190fe286971ac4fffb64ee5bd9eeeb0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Oct 2005 03:24:00 +0000 Subject: r11137: Compile with only 2 warnings (I'm still working on that code) on a gcc4 x86_64 box. Jeremy. (This used to be commit d720867a788c735e56d53d63265255830ec21208) --- source3/smbd/error.c | 2 +- source3/smbd/lanman.c | 4 ++-- source3/smbd/negprot.c | 4 ++-- source3/smbd/reply.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 3cdcae5c7f..fa236f0de0 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -26,7 +26,7 @@ extern struct unix_error_map unix_dos_nt_errmap[]; extern uint32 global_client_caps; /* these can be set by some functions to override the error codes */ static int override_ERR_class; -static int override_ERR_code; +static uint32 override_ERR_code; static NTSTATUS override_ERR_ntstatus; /**************************************************************************** diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0666fe8913..3e1174b22f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1797,8 +1797,8 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para BOOL ret = False; DOM_SID *sids; gid_t *gids; - int num_groups; - int i; + size_t num_groups; + size_t i; fstring grp_domain; fstring grp_name; enum SID_NAME_USE grp_type; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 91942bf028..65c31449bb 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -172,7 +172,7 @@ static int negprot_spnego(char *p, uint8 *pkeylen) DATA_BLOB blob; nstring dos_name; fstring unix_name; - uint8 guid[17]; + char guid[17]; const char *OIDs_krb5[] = {OID_KERBEROS5, OID_KERBEROS5_OLD, OID_NTLMSSP, @@ -186,7 +186,7 @@ static int negprot_spnego(char *p, uint8 *pkeylen) safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1); strlower_m(unix_name); push_ascii_nstring(dos_name, unix_name); - safe_strcpy((char *)guid, dos_name, sizeof(guid)-1); + safe_strcpy(guid, dos_name, sizeof(guid)-1); #ifdef DEVELOPER /* valgrind fixer... */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 47da903256..beed90f9aa 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2130,7 +2130,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st DATA_BLOB header; _smb_setlen(outbuf,nread); - header.data = outbuf; + header.data = (uint8 *)outbuf; header.length = 4; header.free = NULL; @@ -2509,7 +2509,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length SSVAL(smb_buf(outbuf),-2,smb_maxcnt); SCVAL(outbuf,smb_vwv0,0xFF); set_message(outbuf,12,smb_maxcnt,False); - header.data = outbuf; + header.data = (uint8 *)outbuf; header.length = data - outbuf; header.free = NULL; -- cgit From ad93243f2399c2f349434dbbb33ed3766a817a8d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 19 Oct 2005 14:34:17 +0000 Subject: r11183: add small helper function to return a PAC_LOGON_INFO. Guenther (This used to be commit a8d5d6b845efb62e73e281549528376f3ee74211) --- source3/smbd/sesssetup.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index fc2d8b4abb..c875e08b24 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -182,16 +182,7 @@ static int reply_spnego_kerberos(connection_struct *conn, } if (pac_data) { - - /* get the logon_info */ - for (i=0; i < pac_data->num_buffers; i++) { - - if (pac_data->pac_buffer[i].type != PAC_TYPE_LOGON_INFO) - continue; - - logon_info = pac_data->pac_buffer[i].ctr->pac.logon_info; - break; - } + logon_info = get_logon_info_from_pac(pac_data); } DEBUG(3,("Ticket name is [%s]\n", client)); -- cgit From c6aea6ef2d97982263b1652b7c186df269bf0de6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Oct 2005 20:02:12 +0000 Subject: r11190: Fix enhancement request #3192. This does 2 things. 1). Makes dfree command a per-share parameter (it should be anyway IMHO). 2). Adds a "dfree cache time" parameter in seconds that specifies how long a dfree command output should be cached for. Default is zero (no caching). Jeremy. (This used to be commit 49ef8b88a3e12883148eb28d8e86fb07dbc3d12d) --- source3/smbd/dfree.c | 63 +++++++++++++++++++++++++++++++++++++++++-------- source3/smbd/vfs-wrap.c | 2 +- 2 files changed, 54 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 81a48b94fc..dad7d917e8 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -21,8 +21,9 @@ #include "includes.h" /**************************************************************************** -normalise for DOS usage + Normalise for DOS usage. ****************************************************************************/ + static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { /* check if the disk is beyond the max disk size */ @@ -59,17 +60,17 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree, /**************************************************************************** - return number of 1K blocks available on a path and total number + Return number of 1K blocks available on a path and total number. ****************************************************************************/ -static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, +SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { int dfree_retval; SMB_BIG_UINT dfree_q = 0; SMB_BIG_UINT bsize_q = 0; SMB_BIG_UINT dsize_q = 0; - char *dfree_command; + const char *dfree_command; (*dfree) = (*dsize) = 0; (*bsize) = 512; @@ -78,7 +79,7 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, * If external disk calculation specified, use it. */ - dfree_command = lp_dfree_command(); + dfree_command = lp_dfree_command(SNUM(conn)); if (dfree_command && *dfree_command) { const char *p; char **lines; @@ -162,12 +163,54 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, return(dfree_retval); } - /**************************************************************************** -wrap it to get filenames right + Potentially returned cached dfree info. ****************************************************************************/ -SMB_BIG_UINT sys_disk_free(const char *path, BOOL small_query, - SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) + +SMB_BIG_UINT get_dfree_info(connection_struct *conn, + const char *path, + BOOL small_query, + SMB_BIG_UINT *bsize, + SMB_BIG_UINT *dfree, + SMB_BIG_UINT *dsize) { - return disk_free(path,small_query, bsize,dfree,dsize); + int dfree_cache_time = lp_dfree_cache_time(SNUM(conn)); + struct dfree_cached_info *dfc = conn->dfree_info; + SMB_BIG_UINT dfree_ret; + + if (!dfree_cache_time) { + return SMB_VFS_DISK_FREE(conn,path,small_query,bsize,dfree,dsize); + } + + if (dfc && (conn->lastused - dfc->last_dfree_time < dfree_cache_time)) { + /* Return cached info. */ + *bsize = dfc->bsize; + *dfree = dfc->dfree; + *dsize = dfc->dsize; + return dfc->dfree_ret; + } + + dfree_ret = SMB_VFS_DISK_FREE(conn,path,small_query,bsize,dfree,dsize); + + if (dfree_ret == (SMB_BIG_UINT)-1) { + /* Don't cache bad data. */ + return dfree_ret; + } + + /* No cached info or time to refresh. */ + if (!dfc) { + dfc = TALLOC_P(conn->mem_ctx, struct dfree_cached_info); + if (!dfc) { + return dfree_ret; + } + conn->dfree_info = dfc; + } + + dfc->bsize = *bsize; + dfc->dfree = *dfree; + dfc->dsize = *dsize; + dfc->dfree_ret = dfree_ret; + dfc->last_dfree_time = conn->lastused; + + return dfree_ret; } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 9ae1592a8e..c203af0c55 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -46,7 +46,7 @@ SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *con { SMB_BIG_UINT result; - result = sys_disk_free(path, small_query, bsize, dfree, dsize); + result = sys_disk_free(conn, path, small_query, bsize, dfree, dsize); return result; } -- cgit From ad7cd4096f73382f3723fb3f4581c6cea4186702 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 20 Oct 2005 08:13:00 +0000 Subject: r11213: Fix the build Guenther (This used to be commit 908ac0c9eccd1ba368a6305fee9673770fc74a53) --- source3/smbd/sesssetup.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c875e08b24..34b161c92f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -156,7 +156,6 @@ static int reply_spnego_kerberos(connection_struct *conn, fstring real_username; BOOL map_domainuser_to_guest = False; PAC_LOGON_INFO *logon_info = NULL; - int i; ZERO_STRUCT(ticket); ZERO_STRUCT(pac_data); -- cgit From a5b339c799b39d5147c6d31f94cc0b2ea9c865db Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 20 Oct 2005 17:33:17 +0000 Subject: r11232: Added ab's POSIX statvfs vfs call. Sorry for the delay ab. Jeremy. (This used to be commit af8545806770a7530eecc184bdd230ca14999884) --- source3/smbd/trans2.c | 33 +++++++++++++++++++++++++++++++++ source3/smbd/vfs-wrap.c | 5 +++++ source3/smbd/vfs.c | 1 + 3 files changed, 39 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cfb630a572..155f8b384c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4,6 +4,7 @@ Copyright (C) Jeremy Allison 1994-2003 Copyright (C) Stefan (metze) Metzmacher 2003 Copyright (C) Volker Lendecke 2005 + Copyright (C) Steve French 2005 Extensively modified by Andrew Tridgell, 1995 @@ -2403,6 +2404,38 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */ break; + case SMB_QUERY_POSIX_FS_INFO: + { + int rc; + vfs_statvfs_struct svfs; + + if (!lp_unix_extensions()) + return ERROR_DOS(ERRDOS,ERRunknownlevel); + + rc = SMB_VFS_STATVFS(conn, ".", &svfs); + + if (!rc) { + data_len = 56; + SIVAL(pdata,0,svfs.OptimalTransferSize); + SIVAL(pdata,4,svfs.BlockSize); + SBIG_UINT(pdata,8,svfs.TotalBlocks); + SBIG_UINT(pdata,16,svfs.BlocksAvail); + SBIG_UINT(pdata,24,svfs.UserBlocksAvail); + SBIG_UINT(pdata,32,svfs.TotalFileNodes); + SBIG_UINT(pdata,40,svfs.FreeFileNodes); + SBIG_UINT(pdata,48,svfs.FsIdentifier); + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n")); +#ifdef EOPNOTSUPP + } else if (rc == EOPNOTSUPP) { + return ERROR_DOS(ERRDOS, ERRunknownlevel); +#endif /* EOPNOTSUPP */ + } else { + DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn)))); + return ERROR_DOS(ERRSRV,ERRerror); + } + break; + } + case SMB_MAC_QUERY_FS_INFO: /* * Thursby MAC extension... ONLY on NTFS filesystems diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index c203af0c55..bbb7b5bb30 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -86,6 +86,11 @@ int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_ return -1; /* Not implemented. */ } +int vfswrap_statvfs(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, vfs_statvfs_struct *statbuf) +{ + return sys_statvfs(path, statbuf); +} + /* Directory operations */ SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 67970f203a..52966d59ae 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -57,6 +57,7 @@ static struct vfs_ops default_vfs = { vfswrap_get_quota, vfswrap_set_quota, vfswrap_get_shadow_copy_data, + vfswrap_statvfs, /* Directory operations */ -- cgit From eb7a808f9811f08880319ccb3e22b4388a9f4434 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 20 Oct 2005 18:15:44 +0000 Subject: r11233: Forgot to add the statvfs file. Oops. Jeremy. (This used to be commit 797b9f47e98bed500dc3dd6ec8de51a0ec3e2bd7) --- source3/smbd/statvfs.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 source3/smbd/statvfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/statvfs.c b/source3/smbd/statvfs.c new file mode 100644 index 0000000000..8f981a6328 --- /dev/null +++ b/source3/smbd/statvfs.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + VFS API's statvfs abstraction + Copyright (C) Alexander Bokovoy 2005 + Copyright (C) Steve French 2005 + + 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" + +#if defined(LINUX) +static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) +{ + struct statvfs statvfs_buf; + int result; + + result = statvfs(path, &statvfs_buf); + + if (!result) { + statbuf->OptimalTransferSize = statvfs_buf.f_frsize; + statbuf->BlockSize = statvfs_buf.f_bsize; + statbuf->TotalBlocks = statvfs_buf.f_blocks; + statbuf->BlocksAvail = statvfs_buf.f_bfree; + statbuf->UserBlocksAvail = statvfs_buf.f_bavail; + statbuf->TotalFileNodes = statvfs_buf.f_files; + statbuf->FreeFileNodes = statvfs_buf.f_ffree; + statbuf->FsIdentifier = statvfs_buf.f_fsid; + } + return result; +} +#endif + +/* + sys_statvfs() is an abstraction layer over system-dependent statvfs()/statfs() + for particular POSIX systems. Due to controversy of what is considered more important + between LSB and FreeBSD/POSIX.1 (IEEE Std 1003.1-2001) we need to abstract the interface + so that particular OS would use its preffered interface. +*/ +int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf) +{ +#if defined(LINUX) + return linux_statvfs(path, statbuf); +#else + /* BB change this to return invalid level */ +#ifdef EOPNOTSUPP + return EOPNOTSUPP; +#else + return -1; +#endif /* EOPNOTSUPP */ +#endif /* LINUX */ + +} -- cgit From 0feff5b60454d7b8c935f61ccbd6c43605901013 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 20 Oct 2005 21:10:05 +0000 Subject: r11237: Fix acl evaluation bug found by Marc Cousin We should only check the S_IWGRP permissions if we haven't already seen an owning group SMB_ACL_GROUP_OBJ ace entry. If there is an SMB_ACL_GROUP_OBJ ace entry then the group bits in st_gid are the same as the SMB_ACL_MASK bits, not the SMB_ACL_GROUP_OBJ bits. Thanks to Marc Cousin for pointing this out. Jeremy. (This used to be commit 7e1318e09bd4b155707020142b08776a546a646e) --- source3/smbd/posix_acls.c | 48 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ffb1698394..91a3f5ed48 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3910,6 +3910,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam SMB_ACL_ENTRY_T entry; int i; BOOL seen_mask = False; + BOOL seen_owning_group = False; int ret = -1; gid_t cu_gid; @@ -3950,6 +3951,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam switch(tagtype) { case SMB_ACL_MASK: + seen_mask = True; if (!have_write) { /* We don't have any group or explicit user write permission. */ ret = -1; /* Allow caller to check "other" permissions. */ @@ -3957,7 +3959,6 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam refusing write due to mask.\n", fname)); goto done; } - seen_mask = True; break; case SMB_ACL_USER: { @@ -4019,8 +4020,16 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can switch(tagtype) { case SMB_ACL_GROUP: + case SMB_ACL_GROUP_OBJ: { - gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + gid_t *pgid = NULL; + + if (tagtype == SMB_ACL_GROUP) { + pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + } else { + seen_owning_group = True; + pgid = &psbuf->st_gid; + } if (pgid == NULL) { goto check_stat; } @@ -4059,24 +4068,35 @@ match on group %u -> can write.\n", fname, (unsigned int)cu_gid )); check_stat: - /* Do we match on the owning group entry ? */ /* - * Does it match the current effective group - * or supplementary groups ? + * We only check the S_IWGRP permissions if we haven't already + * seen an owning group SMB_ACL_GROUP_OBJ ace entry. If there is an + * SMB_ACL_GROUP_OBJ ace entry then the group bits in st_gid are + * the same as the SMB_ACL_MASK bits, not the SMB_ACL_GROUP_OBJ + * bits. Thanks to Marc Cousin for pointing + * this out. JRA. */ - for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; - cu_gid = get_current_user_gid_next(&i)) { - if (cu_gid == psbuf->st_gid) { - ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; - DEBUG(10,("check_posix_acl_group_write: file %s \ + + if (!seen_owning_group) { + /* Do we match on the owning group entry ? */ + /* + * Does it match the current effective group + * or supplementary groups ? + */ + for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; + cu_gid = get_current_user_gid_next(&i)) { + if (cu_gid == psbuf->st_gid) { + ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; + DEBUG(10,("check_posix_acl_group_write: file %s \ match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write")); - break; + break; + } } - } - if (cu_gid == (gid_t)-1) { - DEBUG(10,("check_posix_acl_group_write: file %s \ + if (cu_gid == (gid_t)-1) { + DEBUG(10,("check_posix_acl_group_write: file %s \ failed to match on user or group in token (ret = %d).\n", fname, ret )); + } } done: -- cgit From bd9b6a249a6d58f37d2536de998c5b5719c3a85f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Oct 2005 05:26:53 +0000 Subject: r11283: Move to using sival_int from sival_ptr. Part of bug #2922. Jeremy. (This used to be commit f68ff32630ee3b06b69bac59674ecc1496880a47) --- source3/smbd/aio.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index af1f172b92..c71c374043 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -155,7 +155,7 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE]; static void signal_handler(int sig, siginfo_t *info, void *unused) { if (signals_received < AIO_PENDING_SIZE - 1) { - aio_pending_array[signals_received] = *(uint16 *)(info->si_value.sival_ptr); + aio_pending_array[signals_received] = info->si_value.sival_int; signals_received++; } /* Else signal is lost. */ sys_select_signal(RT_SIGNAL_AIO); @@ -248,7 +248,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; - a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_READ(fsp,a) == -1) { DEBUG(0,("schedule_aio_read_and_X: aio_read failed. Error %s\n", @@ -327,7 +327,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; - a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. Error %s\n", @@ -642,10 +642,16 @@ BOOL wait_for_aio_completion(files_struct *fsp) /* One or more events might have completed - process them if so. */ for( i = 0; i < aio_completion_count; i++) { - uint16 mid = *(uint16 *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr; + uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; aio_ex = find_aio_ex(mid); + if (!aio_ex) { + DEBUG(0, ("wait_for_aio_completion: mid %u doesn't match an aio record\n", + (unsigned int)mid )); + continue; + } + if (!handle_aio_completed(aio_ex, &err)) { continue; } -- cgit From 533da83852b13c2e008938a026f99937ef320f3c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Oct 2005 22:35:08 +0000 Subject: r11341: Put directory opens into the share mode db so we can treat them similarly to file opens (delete on close, share mode violations etc.). This fixes bug #3216 I will up the default hash size on the locking db in a later commit as this means more entries. Jeremy. (This used to be commit 1134abbbb3fd8e8b88e1a5817aae106476a4c126) --- source3/smbd/close.c | 38 ++++++++++++++++++++++++++++++++++---- source3/smbd/open.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index becca003b6..44ab168a3a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -195,12 +195,12 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); if (lck == NULL) { - DEBUG(0, ("Could not get share mode lock\n")); + DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name)); return EINVAL; } if (!del_share_mode(lck, fsp)) { - DEBUG(0, ("Could not delete share entry\n")); + DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name)); } delete_file = lck->delete_on_close; @@ -297,6 +297,9 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); static int close_directory(files_struct *fsp, BOOL normal_close) { + struct share_mode_lock *lck = 0; + BOOL delete_dir = False; + remove_pending_change_notify_requests_by_fid(fsp); /* @@ -304,8 +307,33 @@ static int close_directory(files_struct *fsp, BOOL normal_close) * reference to a directory also. */ - if (normal_close && - get_delete_on_close_flag(fsp->dev, fsp->inode, fsp->fsp_name)) { + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); + + if (lck == NULL) { + DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); + return EINVAL; + } + + if (!del_share_mode(lck, fsp)) { + DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name)); + } + + delete_dir = lck->delete_on_close; + + if (delete_dir) { + int i; + /* See if others still have the file open. If this is the + * case, then don't delete */ + for (i=0; inum_share_modes; i++) { + if (is_valid_share_mode_entry(&lck->share_modes[i])) { + delete_dir = False; + break; + } + } + } + + + if (normal_close && delete_dir) { BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", fsp->fsp_name, ok ? "succeeded" : "failed" )); @@ -321,6 +349,8 @@ static int close_directory(files_struct *fsp, BOOL normal_close) process_pending_change_notify_queue((time_t)0); } + talloc_free(lck); + /* * Do the code common to files and directories. */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 70687ff580..42e1da839f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1536,7 +1536,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(NULL, dev, inode, fname); if (lck == NULL) { - DEBUG(0, ("Coult not get share mode lock\n")); + DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); @@ -1801,6 +1801,8 @@ files_struct *open_directory(connection_struct *conn, files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; BOOL create_dir = False; + struct share_mode_lock *lck = NULL; + NTSTATUS status; int info = 0; DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " @@ -1883,7 +1885,7 @@ files_struct *open_directory(connection_struct *conn, /* We know bad_path is false as it's caught earlier. */ - NTSTATUS status = mkdir_internal(conn, fname, False); + status = mkdir_internal(conn, fname, False); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("open_directory: unable to create %s. " @@ -1938,14 +1940,43 @@ files_struct *open_directory(connection_struct *conn, fsp->is_stat = False; string_set(&fsp->fsp_name,fname); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fname); + + if (lck == NULL) { + DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); + file_free(fsp); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + return NULL; + } + + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &dir_existed); + + if (!NT_STATUS_IS_OK(status)) { + set_saved_ntstatus(status); + talloc_free(lck); + file_free(fsp); + return NULL; + } + + set_share_mode(lck, fsp, 0, NO_OPLOCK); + if (create_options & FILE_DELETE_ON_CLOSE) { - NTSTATUS status = can_set_delete_on_close(fsp, True, 0); + status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { + set_saved_ntstatus(status); + talloc_free(lck); file_free(fsp); return NULL; } + + lck->delete_on_close = True; + lck->modified = True; } + talloc_free(lck); + /* Change the owner if required. */ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); -- cgit From c0dad16e0ff95a800dfbe11ca3c6303d882687a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Oct 2005 23:30:25 +0000 Subject: r11344: I don't think share mode conflicts occur on deleting a directory when you've got permissions. Need to write a smbtorture test for this. Jeremy. (This used to be commit e959a5be393eb59b8987eb6967a2ee5d11978f41) --- source3/smbd/close.c | 23 ++++++----------------- source3/smbd/notify.c | 7 ++++--- 2 files changed, 10 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 44ab168a3a..fcea62e1aa 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -300,8 +300,6 @@ static int close_directory(files_struct *fsp, BOOL normal_close) struct share_mode_lock *lck = 0; BOOL delete_dir = False; - remove_pending_change_notify_requests_by_fid(fsp); - /* * NT can set delete_on_close of the last open * reference to a directory also. @@ -320,18 +318,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) delete_dir = lck->delete_on_close; - if (delete_dir) { - int i; - /* See if others still have the file open. If this is the - * case, then don't delete */ - for (i=0; inum_share_modes; i++) { - if (is_valid_share_mode_entry(&lck->share_modes[i])) { - delete_dir = False; - break; - } - } - } - + talloc_free(lck); if (normal_close && delete_dir) { BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name); @@ -344,13 +331,15 @@ static int close_directory(files_struct *fsp, BOOL normal_close) */ if(ok) { - remove_pending_change_notify_requests_by_filename(fsp); + remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING); + remove_pending_change_notify_requests_by_filename(fsp, NT_STATUS_DELETE_PENDING); + } process_pending_change_notify_queue((time_t)0); + } else { + remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_CANCELLED); } - talloc_free(lck); - /* * Do the code common to files and directories. */ diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ad49dc0a21..bc76cfb322 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -82,13 +82,14 @@ static void change_notify_remove(struct change_notify *cnbp) Delete entries by fnum from the change notify pending queue. *****************************************************************************/ -void remove_pending_change_notify_requests_by_fid(files_struct *fsp) +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) { struct change_notify *cnbp, *next; for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if (cnbp->fsp->fnum == fsp->fnum) { + change_notify_reply_packet(cnbp->request_buf,status); change_notify_remove(cnbp); } } @@ -116,7 +117,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_filename(files_struct *fsp) +void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTATUS status) { struct change_notify *cnbp, *next; @@ -127,7 +128,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_reply_packet(cnbp->request_buf,status); change_notify_remove(cnbp); } } -- cgit From f9b750542933cb60eca7da335193c36361496622 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Oct 2005 01:42:03 +0000 Subject: r11346: Fix for bug found by Dina Fine. If in case sensitive mode then the mangle cache is no good (3 letter extension could be wrong case - so don't demangle in this case - leave as mangled and allow the mangling of the directory entry read (which is done case insensitively) to match instead. This will lead to more false positive matches but we fail completely without it. Jeremy. (This used to be commit 238b35d2e6e21d0e07d500d446f08ec128ea7720) --- source3/smbd/filename.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f0a33e568e..b389b9c1ae 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -445,9 +445,18 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name * read from the directory and then mangled by the mangle_map() * call. We need to mangle both names or neither. * (JRA). + * + * Fix for bug found by Dina Fine. If in case sensitive mode then + * the mangle cache is no good (3 letter extension could be wrong + * case - so don't demangle in this case - leave as mangled and + * allow the mangling of the directory entry read (which is done + * case insensitively) to match instead. This will lead to more + * false positive matches but we fail completely without it. JRA. */ - if (mangled) + + if (mangled && !conn->case_sensitive) { mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); + } /* open the directory */ if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { -- cgit From 3a5c37bfd12781077fe8e7c6ebb23c2cfdb77fd1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 29 Oct 2005 00:27:16 +0000 Subject: r11389: Attempt to fix bug #3212 - ignore bogus OS/2 EA set values on trans2_mkdir/trans2_open/trans2_setfilepathingo. Jeremy. (This used to be commit 71c037dfbb0b51e750f2e14533b03d9932778cb0) --- source3/smbd/trans2.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 155f8b384c..f04e6c78f0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -804,11 +804,11 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } /* Any data in this call is an EA list. */ - if (total_data && !lp_ea_support(SNUM(conn))) { + if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) { return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); } - if (total_data) { + if (total_data != 4) { if (total_data < 10) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -828,6 +828,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i talloc_destroy(ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + } else if (IVAL(pdata,0) != 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } fsp = open_file_ntcreate(conn,fname,&sbuf, @@ -3736,6 +3738,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char TALLOC_CTX *ctx = NULL; if (total_data < 10) { + + /* OS/2 workplace shell seems to send SET_EA requests of "null" + length. They seem to have no effect. Bug #3212. JRA */ + + if ((total_data == 4) && (IVAL(pdata,0) == 4)) { + /* We're done. We only get EA info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -4489,11 +4502,17 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, } /* Any data in this call is an EA list. */ - if (total_data && !lp_ea_support(SNUM(conn))) { + if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) { return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); } - if (total_data) { + /* + * OS/2 workplace shell seems to send SET_EA requests of "null" + * length (4 bytes containing IVAL 4). + * They seem to have no effect. Bug #3212. JRA. + */ + + if (total_data != 4) { if (total_data < 10) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -4513,6 +4532,8 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, talloc_destroy(ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + } else if (IVAL(pdata,0) != 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (check_name(directory,conn)) { -- cgit From 6baec64a7370ff1871f0b806a623b1fc1a898acb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Oct 2005 20:11:58 +0000 Subject: r11420: Fix issue pointed out by Dina Fine . We can only tell at parse time from the wire if an incoming name has wildcards or not. If it's a mangled name and we demangle the demangled name may contain wildcard characters. Ensure these are ignored. Jeremy. (This used to be commit 4cd8e2a96b98ff711905e8c6f416b22440c16062) --- source3/smbd/dir.c | 4 +- source3/smbd/msdfs.c | 3 +- source3/smbd/nttrans.c | 33 +++++++------ source3/smbd/reply.c | 122 +++++++++++++++++++++++++++++++------------------ source3/smbd/trans2.c | 28 +++++++----- 5 files changed, 118 insertions(+), 72 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 70a3b81ad6..7ea97e69b0 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -382,7 +382,7 @@ static void dptr_close_oldest(BOOL old) ****************************************************************************/ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, - const char *wcard, uint32 attr) + const char *wcard, BOOL wcard_has_wild, uint32 attr) { struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; @@ -500,7 +500,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { dptr->has_wild = True; } else { - dptr->has_wild = ms_has_wild(wcard); + dptr->has_wild = wcard_has_wild; } dptr->attr = attr; diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1e6306382a..a4f371b18f 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -114,7 +114,8 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL /* rest is reqpath */ if (allow_wcards) { - check_path_syntax_wcard(pdp->reqpath, p+1); + BOOL path_contains_wcard; + check_path_syntax_wcard(pdp->reqpath, p+1, &path_contains_wcard); } else { check_path_syntax(pdp->reqpath, p+1); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3db55bad14..91dcc93322 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -541,7 +541,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -583,14 +583,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", dir_name_len++; } - srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status,False); + srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } pstrcat(fname, rel_fname); } else { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -939,7 +939,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1195,7 +1195,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1229,14 +1229,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o { pstring tmpname; - srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } pstrcat(fname, tmpname); } } else { - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1738,13 +1738,14 @@ int reply_ntrename(connection_struct *conn, pstring newname; char *p; NTSTATUS status; + BOOL path_contains_wcard = False; uint32 attrs = SVAL(inbuf,smb_vwv0); uint16 rename_type = SVAL(inbuf,smb_vwv1); START_PROFILE(SMBntrename); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, True); + p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1762,7 +1763,7 @@ int reply_ntrename(connection_struct *conn, } p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, False); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1775,13 +1776,18 @@ int reply_ntrename(connection_struct *conn, switch(rename_type) { case RENAME_FLAG_RENAME: - status = rename_internals(conn, oldname, newname, attrs, False); + status = rename_internals(conn, oldname, newname, attrs, False, path_contains_wcard); break; case RENAME_FLAG_HARD_LINK: status = hardlink_internals(conn, oldname, newname); break; case RENAME_FLAG_COPY: - status = copy_internals(conn, oldname, newname, attrs); + if (path_contains_wcard) { + /* No wildcards. */ + status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + } else { + status = copy_internals(conn, oldname, newname, attrs); + } break; case RENAME_FLAG_MOVE_CLUSTER_INFORMATION: status = NT_STATUS_INVALID_PARAMETER; @@ -1878,6 +1884,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o pstring new_name; files_struct *fsp = NULL; BOOL replace_if_exists = False; + BOOL path_contains_wcard = False; NTSTATUS status; if(parameter_count < 4) { @@ -1887,13 +1894,13 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o fsp = file_fsp(params, 0); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); - srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, True); + srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } status = rename_internals(conn, fsp->fsp_name, - new_name, 0, replace_if_exists); + new_name, 0, replace_if_exists, path_contains_wcard); if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index beed90f9aa..f73eea3fa6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -172,7 +172,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) set. ****************************************************************************/ -NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname) +NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard) { char *d = destname; const char *s = srcname; @@ -180,6 +180,8 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname) BOOL start_of_name_component = True; unsigned int num_bad_components = 0; + *p_contains_wcard = False; + while (*s) { if (IS_DIRECTORY_SEP(*s)) { /* @@ -249,6 +251,19 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname) if (*s <= 0x1f) { return NT_STATUS_OBJECT_NAME_INVALID; } + if (!*p_contains_wcard) { + switch (*s) { + case '*': + case '?': + case '<': + case '>': + case '"': + *p_contains_wcard = True; + break; + default: + break; + } + } *d++ = *s++; } else { switch(next_mb_char_size(s)) { @@ -379,11 +394,41 @@ NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) return ret; } +/**************************************************************************** + Pull a string and check the path allowing a wilcard - provide for error return. +****************************************************************************/ + +size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, + NTSTATUS *err, BOOL *contains_wcard) +{ + pstring tmppath; + char *tmppath_ptr = tmppath; + size_t ret; +#ifdef DEVELOPER + SMB_ASSERT(dest_len == sizeof(pstring)); +#endif + + if (src_len == 0) { + ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags); + } else { + ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); + } + + *contains_wcard = False; + + if (lp_posix_pathnames()) { + *err = check_path_syntax_posix(dest, tmppath); + } else { + *err = check_path_syntax_wcard(dest, tmppath, contains_wcard); + } + return ret; +} + /**************************************************************************** Pull a string and check the path - provide for error return. ****************************************************************************/ -size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names) +size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err) { pstring tmppath; char *tmppath_ptr = tmppath; @@ -399,8 +444,6 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } if (lp_posix_pathnames()) { *err = check_path_syntax_posix(dest, tmppath); - } else if (allow_wcard_names) { - *err = check_path_syntax_wcard(dest, tmppath); } else { *err = check_path_syntax(dest, tmppath); } @@ -754,7 +797,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBchkpth); - srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBchkpth); return ERROR_NT(status); @@ -826,7 +869,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBgetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBgetatr); return ERROR_NT(status); @@ -905,7 +948,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBsetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False); + p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsetatr); return ERROR_NT(status); @@ -1031,6 +1074,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL can_open = True; BOOL bad_path = False; NTSTATUS nt_status; + BOOL mask_contains_wcard = False; BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; if (lp_posix_pathnames()) { @@ -1049,7 +1093,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True); + p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); return ERROR_NT(nt_status); @@ -1114,7 +1158,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ok = True; if (status_len == 0) { - dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, dirtype); + dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype); if (dptr_num < 0) { if(dptr_num == -2) { END_PROFILE(SMBsearch); @@ -1185,7 +1229,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dptr_close(&dptr_num); } - if ((numentries == 0) && !ms_has_wild(mask)) { + if ((numentries == 0) && !mask_contains_wcard) { return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); } @@ -1230,6 +1274,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int dptr_num= -2; char *p; NTSTATUS err; + BOOL path_contains_wcard = False; if (lp_posix_pathnames()) { return reply_unknown(inbuf, outbuf); @@ -1239,7 +1284,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(outbuf,1,0,True); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True); + p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard); if (!NT_STATUS_IS_OK(err)) { END_PROFILE(SMBfclose); return ERROR_NT(err); @@ -1295,7 +1340,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, deny_mode = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); return ERROR_NT(status); @@ -1415,7 +1460,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); return ERROR_NT(status); @@ -1586,7 +1631,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); - srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); return ERROR_NT(status); @@ -1669,7 +1714,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBctemp); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); return ERROR_NT(status); @@ -1889,30 +1934,19 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b code. ****************************************************************************/ -NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name) +NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild) { pstring directory; pstring mask; char *p; int count=0; NTSTATUS error = NT_STATUS_OK; - BOOL has_wild; BOOL bad_path = False; BOOL rc = True; SMB_STRUCT_STAT sbuf; *directory = *mask = 0; - /* We must check for wildcards in the name given - * directly by the client - before any unmangling. - * This prevents an unmangling of a UNIX name containing - * a DOS wildcard like '*' or '?' from unmangling into - * a wildcard delete which was not intended. - * FIX for #226. JRA. - */ - - has_wild = ms_has_wild(name); - rc = unix_convert(name,conn,0,&bad_path,&sbuf); p = strrchr_m(name,'/'); @@ -2029,10 +2063,11 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size uint32 dirtype; NTSTATUS status; START_PROFILE(SMBunlink); - + BOOL path_contains_wcard = False; + dirtype = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True); + srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBunlink); return ERROR_NT(status); @@ -2042,7 +2077,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - status = unlink_internals(conn, dirtype, name); + status = unlink_internals(conn, dirtype, name, path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ @@ -3721,7 +3756,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBmkdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); return ERROR_NT(status); @@ -3925,7 +3960,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBrmdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); return ERROR_NT(status); @@ -4216,14 +4251,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild) { pstring directory; pstring mask; pstring last_component_src; pstring last_component_dest; char *p; - BOOL has_wild; BOOL bad_path_src = False; BOOL bad_path_dest = False; int count=0; @@ -4292,8 +4326,6 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui if (!rc && mangle_is_mangled(mask,SNUM(conn))) mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); - has_wild = ms_has_wild(mask); - if (!has_wild) { /* * No wildcards - just process the one file. @@ -4559,17 +4591,18 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, char *p; uint32 attrs = SVAL(inbuf,smb_vwv0); NTSTATUS status; + BOOL path_contains_wcard = False; START_PROFILE(SMBmv); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True); + p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); } p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); + p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); @@ -4580,7 +4613,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - status = rename_internals(conn, name, newname, attrs, False); + status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); if (open_was_deferred(SVAL(inbuf,smb_mid))) { @@ -4727,21 +4760,22 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL target_is_directory=False; BOOL bad_path1 = False; BOOL bad_path2 = False; + BOOL path_contains_wcard1 = False; + BOOL path_contains_wcard2 = False; BOOL rc = True; SMB_STRUCT_STAT sbuf1, sbuf2; NTSTATUS status; - START_PROFILE(SMBcopy); *directory = *mask = 0; p = smb_buf(inbuf); - p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True); + p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); } - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); + p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); @@ -4803,7 +4837,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!rc && mangle_is_mangled(mask, SNUM(conn))) mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); - has_wild = ms_has_wild(mask); + has_wild = path_contains_wcard1; if (!has_wild) { pstrcat(directory,"/"); @@ -4904,7 +4938,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(pathworks_setdir); return ERROR_NT(status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f04e6c78f0..a9b67cc484 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -775,7 +775,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return(ERROR_DOS(ERRSRV,ERRaccess)); } - srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1614,6 +1614,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb BOOL out_of_space = False; int space_remaining; BOOL bad_path = False; + BOOL mask_contains_wcard = False; SMB_STRUCT_STAT sbuf; TALLOC_CTX *ea_ctx = NULL; struct ea_list *ea_list = NULL; @@ -1654,7 +1655,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return(ERROR_DOS(ERRDOS,ERRunknownlevel)); } - srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True); + srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { return ERROR_NT(ntstatus); } @@ -1672,10 +1673,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", p = strrchr_m(directory,'/'); if(p == NULL) { /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */ - if((directory[0] == '.') && (directory[1] == '\0')) + if((directory[0] == '.') && (directory[1] == '\0')) { pstrcpy(mask,"*"); - else + mask_contains_wcard = True; + } else { pstrcpy(mask,directory); + } pstrcpy(directory,"./"); } else { pstrcpy(mask,p+1); @@ -1733,7 +1736,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ - dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, dirtype); + dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype); if (dptr_num < 0) { talloc_destroy(ea_ctx); return(UNIXERROR(ERRDOS,ERRbadfile)); @@ -1868,6 +1871,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); + BOOL mask_contains_wcard = False; pstring resume_name; pstring mask; pstring directory; @@ -1889,7 +1893,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu *mask = *directory = *resume_name = 0; - srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True); + srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to complain (it thinks we're asking for the directory above the shared @@ -2854,7 +2858,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -3659,7 +3663,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } info_level = SVAL(params,0); - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4217,7 +4221,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", char *newname = fname; /* Set a hard link. */ - srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4251,7 +4255,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", overwrite = (CVAL(pdata,0) ? True : False); root_fid = IVAL(pdata,4); len = IVAL(pdata,8); - srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False); + srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4278,7 +4282,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } else { DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, newname )); - status = rename_internals(conn, fname, base_name, 0, overwrite); + status = rename_internals(conn, fname, base_name, 0, overwrite, False); } if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); @@ -4489,7 +4493,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False); + srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } -- cgit From 86909281c8e128c5aef08f51615b868e1c179964 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Oct 2005 22:30:05 +0000 Subject: r11428: Fix bug #3192 by actually hooking up the dfree caching function. Oops. Jeremy. (This used to be commit 7edb26e7657fc01710abe563b941779749409ef2) --- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 6 +++--- source3/smbd/vfs.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f73eea3fa6..8ca7c2a103 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1004,7 +1004,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz SMB_BIG_UINT dfree,dsize,bsize; START_PROFILE(SMBdskattr); - if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { END_PROFILE(SMBdskattr); return(UNIXERROR(ERRHRD,ERRgeneral)); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a9b67cc484..beaf35caa2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2151,7 +2151,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 18; - if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { return(UNIXERROR(ERRHRD,ERRgeneral)); } @@ -2252,7 +2252,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; - if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { return(UNIXERROR(ERRHRD,ERRgeneral)); } block_size = lp_block_size(snum); @@ -2284,7 +2284,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; - if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { return(UNIXERROR(ERRHRD,ERRgeneral)); } block_size = lp_block_size(snum); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 52966d59ae..001d42d172 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -563,7 +563,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ - space_avail = SMB_VFS_DISK_FREE(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); + space_avail = get_dfree_info(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); if (space_avail == (SMB_BIG_UINT)-1) { return -1; } -- cgit From a3d66dfef7025a9712f62cf3dda8ef910f848cf4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Nov 2005 23:49:40 +0000 Subject: r11448: Move decl before code. Jeremy. (This used to be commit f22822790cdbbe7d5a237421c1eda73a504e488d) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8ca7c2a103..ae7710b48f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2062,9 +2062,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring name; uint32 dirtype; NTSTATUS status; - START_PROFILE(SMBunlink); BOOL path_contains_wcard = False; + START_PROFILE(SMBunlink); + dirtype = SVAL(inbuf,smb_vwv0); srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard); -- cgit From c9effb004cb4bb9baa87fb429f22c834226708bb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Nov 2005 00:19:26 +0000 Subject: r11451: Fix -O1 "might be using uninitialized" errors. Jeremy. (This used to be commit cab76c3c33883aad444eefb6562ab1b27d9ca88a) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ae7710b48f..f83b0ff746 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5126,7 +5126,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; BOOL err; BOOL my_lock_ctx = False; - NTSTATUS status; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; START_PROFILE(SMBlockingX); -- cgit From 6d5757395a0e54245543794d0d6d6d6a32cd857a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 5 Nov 2005 04:21:55 +0000 Subject: r11511: A classic "friday night check-in" :-). This moves much of the Samba4 timezone handling code back into Samba3. Gets rid of "kludge-gmt" and removes the effectiveness of the parameter "time offset" (I can add this back in very easily if needed) - it's no longer being looked at. I'm hoping this will fix the problems people have been having with DST transitions. I'll start comprehensive testing tomorrow, but for now all modifications are done. Splits time get/set functions into srv_XXX and cli_XXX as they need to look at different timezone offsets. Get rid of much of the "efficiency" cruft that was added to Samba back in the day when the C library timezone handling functions were slow. Jeremy. (This used to be commit 414303bc0272f207046b471a0364fa296b67c1f8) --- source3/smbd/dir.c | 2 +- source3/smbd/lanman.c | 667 ++++++++++++++++++++++++++----------------------- source3/smbd/negprot.c | 13 +- source3/smbd/pipes.c | 2 +- source3/smbd/reply.c | 38 +-- source3/smbd/trans2.c | 36 +-- 6 files changed, 400 insertions(+), 358 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7ea97e69b0..c993012a25 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -94,7 +94,7 @@ void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T si memset(buf+21,'\0',DIR_STRUCT_SIZE-21); SCVAL(buf,21,mode); - put_dos_date(buf,22,date); + srv_put_dos_date(buf,22,date); SSVAL(buf,26,size & 0xFFFF); SSVAL(buf,28,(size >> 16)&0xFFFF); /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf. diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3e1174b22f..1e2a248851 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -50,23 +50,25 @@ extern userdom_struct current_user_info; #define SHPWLEN 8 /* share password length */ -static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); -static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); +static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len); +static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len); static int CopyExpanded(connection_struct *conn, - int snum, char** dst, char* src, int* n) + int snum, char **dst, char *src, int *n) { pstring buf; int l; - if (!src || !dst || !n || !(*dst)) return(0); + if (!src || !dst || !n || !(*dst)) { + return 0; + } StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); @@ -77,30 +79,36 @@ static int CopyExpanded(connection_struct *conn, return l; } -static int CopyAndAdvance(char** dst, char* src, int* n) +static int CopyAndAdvance(char **dst, char *src, int *n) { - int l; - if (!src || !dst || !n || !(*dst)) return(0); - l = push_ascii(*dst,src,*n, STR_TERMINATE); - (*dst) += l; - (*n) -= l; - return l; + int l; + if (!src || !dst || !n || !(*dst)) { + return 0; + } + l = push_ascii(*dst,src,*n, STR_TERMINATE); + (*dst) += l; + (*n) -= l; + return l; } -static int StrlenExpanded(connection_struct *conn, int snum, char* s) +static int StrlenExpanded(connection_struct *conn, int snum, char *s) { pstring buf; - if (!s) return(0); + if (!s) { + return 0; + } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub_conn(conn,buf,sizeof(buf)); return strlen(buf) + 1; } -static char* Expand(connection_struct *conn, int snum, char* s) +static char *Expand(connection_struct *conn, int snum, char *s) { static pstring buf; - if (!s) return(NULL); + if (!s) { + return NULL; + } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); standard_sub_conn(conn,buf,sizeof(buf)); @@ -108,218 +116,248 @@ static char* Expand(connection_struct *conn, int snum, char* s) } /******************************************************************* - check a API string for validity when we only need to check the prefix - ******************************************************************/ + Check a API string for validity when we only need to check the prefix. +******************************************************************/ + static BOOL prefix_ok(const char *str, const char *prefix) { - return(strncmp(str,prefix,strlen(prefix)) == 0); + return(strncmp(str,prefix,strlen(prefix)) == 0); } struct pack_desc { - const char* format; /* formatstring for structure */ - const char* subformat; /* subformat for structure */ - char* base; /* baseaddress of buffer */ - int buflen; /* remaining size for fixed part; on init: length of base */ - int subcount; /* count of substructures */ - char* structbuf; /* pointer into buffer for remaining fixed part */ - int stringlen; /* remaining size for variable part */ - char* stringbuf; /* pointer into buffer for remaining variable part */ - int neededlen; /* total needed size */ - int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ - const char* curpos; /* current position; pointer into format or subformat */ - int errcode; + const char *format; /* formatstring for structure */ + const char *subformat; /* subformat for structure */ + char *base; /* baseaddress of buffer */ + int buflen; /* remaining size for fixed part; on init: length of base */ + int subcount; /* count of substructures */ + char *structbuf; /* pointer into buffer for remaining fixed part */ + int stringlen; /* remaining size for variable part */ + char *stringbuf; /* pointer into buffer for remaining variable part */ + int neededlen; /* total needed size */ + int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ + const char *curpos; /* current position; pointer into format or subformat */ + int errcode; }; -static int get_counter(const char** p) +static int get_counter(const char **p) { - int i, n; - if (!p || !(*p)) return(1); - if (!isdigit((int)**p)) return 1; - for (n = 0;;) { - i = **p; - if (isdigit(i)) - n = 10 * n + (i - '0'); - else - return n; - (*p)++; - } + int i, n; + if (!p || !(*p)) { + return 1; + } + if (!isdigit((int)**p)) { + return 1; + } + for (n = 0;;) { + i = **p; + if (isdigit(i)) { + n = 10 * n + (i - '0'); + } else { + return n; + } + (*p)++; + } } -static int getlen(const char* p) +static int getlen(const char *p) { - int n = 0; - if (!p) return(0); - while (*p) { - switch( *p++ ) { - case 'W': /* word (2 byte) */ - n += 2; - break; - case 'K': /* status word? (2 byte) */ - n += 2; - break; - case 'N': /* count of substructures (word) at end */ - n += 2; - break; - case 'D': /* double word (4 byte) */ - case 'z': /* offset to zero terminated string (4 byte) */ - case 'l': /* offset to user data (4 byte) */ - n += 4; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - n += 4; - get_counter(&p); - break; - case 'B': /* byte (with optional counter) */ - n += get_counter(&p); - break; - } - } - return n; + int n = 0; + if (!p) { + return 0; + } + + while (*p) { + switch( *p++ ) { + case 'W': /* word (2 byte) */ + n += 2; + break; + case 'K': /* status word? (2 byte) */ + n += 2; + break; + case 'N': /* count of substructures (word) at end */ + n += 2; + break; + case 'D': /* double word (4 byte) */ + case 'z': /* offset to zero terminated string (4 byte) */ + case 'l': /* offset to user data (4 byte) */ + n += 4; + break; + case 'b': /* offset to data (with counter) (4 byte) */ + n += 4; + get_counter(&p); + break; + case 'B': /* byte (with optional counter) */ + n += get_counter(&p); + break; + } + } + return n; } -static BOOL init_package(struct pack_desc* p, int count, int subcount) +static BOOL init_package(struct pack_desc *p, int count, int subcount) { - int n = p->buflen; - int i; + int n = p->buflen; + int i; + + if (!p->format || !p->base) { + return False; + } - if (!p->format || !p->base) return(False); - - i = count * getlen(p->format); - if (p->subformat) i += subcount * getlen(p->subformat); - p->structbuf = p->base; - p->neededlen = 0; - p->usedlen = 0; - p->subcount = 0; - p->curpos = p->format; - if (i > n) { - p->neededlen = i; - i = n = 0; + i = count * getlen(p->format); + if (p->subformat) { + i += subcount * getlen(p->subformat); + } + p->structbuf = p->base; + p->neededlen = 0; + p->usedlen = 0; + p->subcount = 0; + p->curpos = p->format; + if (i > n) { + p->neededlen = i; + i = n = 0; #if 0 - /* - * This is the old error code we used. Aparently - * WinNT/2k systems return ERRbuftoosmall (2123) and - * OS/2 needs this. I'm leaving this here so we can revert - * if needed. JRA. - */ - p->errcode = ERRmoredata; + /* + * This is the old error code we used. Aparently + * WinNT/2k systems return ERRbuftoosmall (2123) and + * OS/2 needs this. I'm leaving this here so we can revert + * if needed. JRA. + */ + p->errcode = ERRmoredata; #else - p->errcode = ERRbuftoosmall; + p->errcode = ERRbuftoosmall; #endif - } - else - p->errcode = NERR_Success; - p->buflen = i; - n -= i; - p->stringbuf = p->base + i; - p->stringlen = n; - return(p->errcode == NERR_Success); + } else { + p->errcode = NERR_Success; + } + p->buflen = i; + n -= i; + p->stringbuf = p->base + i; + p->stringlen = n; + return (p->errcode == NERR_Success); } -static int package(struct pack_desc* p, ...) +static int package(struct pack_desc *p, ...) { - va_list args; - int needed=0, stringneeded; - const char* str=NULL; - int is_string=0, stringused; - int32 temp; + va_list args; + int needed=0, stringneeded; + const char *str=NULL; + int is_string=0, stringused; + int32 temp; - va_start(args,p); + va_start(args,p); - if (!*p->curpos) { - if (!p->subcount) - p->curpos = p->format; - else { - p->curpos = p->subformat; - p->subcount--; - } - } + if (!*p->curpos) { + if (!p->subcount) { + p->curpos = p->format; + } else { + p->curpos = p->subformat; + p->subcount--; + } + } #if CHECK_TYPES - str = va_arg(args,char*); - SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); + str = va_arg(args,char*); + SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); #endif - stringneeded = -1; + stringneeded = -1; - if (!p->curpos) { - va_end(args); - return(0); - } + if (!p->curpos) { + va_end(args); + return 0; + } - switch( *p->curpos++ ) { - case 'W': /* word (2 byte) */ - needed = 2; - temp = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); - break; - case 'K': /* status word? (2 byte) */ - needed = 2; - temp = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); - break; - case 'N': /* count of substructures (word) at end */ - needed = 2; - p->subcount = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount); - break; - case 'D': /* double word (4 byte) */ - needed = 4; - temp = va_arg(args,int); - if (p->buflen >= needed) SIVAL(p->structbuf,0,temp); - break; - case 'B': /* byte (with optional counter) */ - needed = get_counter(&p->curpos); - { - char *s = va_arg(args,char*); - if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1); - } - break; - case 'z': /* offset to zero terminated string (4 byte) */ - str = va_arg(args,char*); - stringneeded = (str ? strlen(str)+1 : 0); - is_string = 1; - break; - case 'l': /* offset to user data (4 byte) */ - str = va_arg(args,char*); - stringneeded = va_arg(args,int); - is_string = 0; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - str = va_arg(args,char*); - stringneeded = get_counter(&p->curpos); - is_string = 0; - break; - } - va_end(args); - if (stringneeded >= 0) { - needed = 4; - if (p->buflen >= needed) { - stringused = stringneeded; - if (stringused > p->stringlen) { - stringused = (is_string ? p->stringlen : 0); - if (p->errcode == NERR_Success) p->errcode = ERRmoredata; - } - if (!stringused) - SIVAL(p->structbuf,0,0); - else { - SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); - memcpy(p->stringbuf,str?str:"",stringused); - if (is_string) p->stringbuf[stringused-1] = '\0'; - p->stringbuf += stringused; - p->stringlen -= stringused; - p->usedlen += stringused; - } - } - p->neededlen += stringneeded; - } - p->neededlen += needed; - if (p->buflen >= needed) { - p->structbuf += needed; - p->buflen -= needed; - p->usedlen += needed; - } - else { - if (p->errcode == NERR_Success) p->errcode = ERRmoredata; - } - return 1; + switch( *p->curpos++ ) { + case 'W': /* word (2 byte) */ + needed = 2; + temp = va_arg(args,int); + if (p->buflen >= needed) { + SSVAL(p->structbuf,0,temp); + } + break; + case 'K': /* status word? (2 byte) */ + needed = 2; + temp = va_arg(args,int); + if (p->buflen >= needed) { + SSVAL(p->structbuf,0,temp); + } + break; + case 'N': /* count of substructures (word) at end */ + needed = 2; + p->subcount = va_arg(args,int); + if (p->buflen >= needed) { + SSVAL(p->structbuf,0,p->subcount); + } + break; + case 'D': /* double word (4 byte) */ + needed = 4; + temp = va_arg(args,int); + if (p->buflen >= needed) { + SIVAL(p->structbuf,0,temp); + } + break; + case 'B': /* byte (with optional counter) */ + needed = get_counter(&p->curpos); + { + char *s = va_arg(args,char*); + if (p->buflen >= needed) { + StrnCpy(p->structbuf,s?s:"",needed-1); + } + } + break; + case 'z': /* offset to zero terminated string (4 byte) */ + str = va_arg(args,char*); + stringneeded = (str ? strlen(str)+1 : 0); + is_string = 1; + break; + case 'l': /* offset to user data (4 byte) */ + str = va_arg(args,char*); + stringneeded = va_arg(args,int); + is_string = 0; + break; + case 'b': /* offset to data (with counter) (4 byte) */ + str = va_arg(args,char*); + stringneeded = get_counter(&p->curpos); + is_string = 0; + break; + } + + va_end(args); + if (stringneeded >= 0) { + needed = 4; + if (p->buflen >= needed) { + stringused = stringneeded; + if (stringused > p->stringlen) { + stringused = (is_string ? p->stringlen : 0); + if (p->errcode == NERR_Success) { + p->errcode = ERRmoredata; + } + } + if (!stringused) { + SIVAL(p->structbuf,0,0); + } else { + SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); + memcpy(p->stringbuf,str?str:"",stringused); + if (is_string) { + p->stringbuf[stringused-1] = '\0'; + } + p->stringbuf += stringused; + p->stringlen -= stringused; + p->usedlen += stringused; + } + } + p->neededlen += stringneeded; + } + + p->neededlen += needed; + if (p->buflen >= needed) { + p->structbuf += needed; + p->buflen -= needed; + p->usedlen += needed; + } else { + if (p->errcode == NERR_Success) { + p->errcode = ERRmoredata; + } + } + return 1; } #if CHECK_TYPES @@ -340,10 +378,10 @@ static void PACKS(struct pack_desc* desc,const char *t,const char *v) PACK(desc,t,v); } - /**************************************************************************** - get a print queue - ****************************************************************************/ + Get a print queue. +****************************************************************************/ + static void PackDriverData(struct pack_desc* desc) { char drivdata[4+4+32]; @@ -439,61 +477,61 @@ static int printq_status(int v) } static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc, - print_queue_struct* queue, int n) + struct pack_desc *desc, + print_queue_struct *queue, int n) { - time_t t = queue->time; - - /* the client expects localtime */ - t -= TimeDiff(t); - - PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */ - if (uLevel == 1) { - PACKS(desc,"B21",queue->fs_user); /* szUserName */ - PACKS(desc,"B",""); /* pad */ - PACKS(desc,"B16",""); /* szNotifyName */ - PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",t); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z",queue->fs_file); /* pszComment */ - } - if (uLevel == 2 || uLevel == 3 || uLevel == 4) { - PACKI(desc,"W",queue->priority); /* uPriority */ - PACKS(desc,"z",queue->fs_user); /* pszUserName */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ - PACKI(desc,"D",t); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z","Samba"); /* pszComment */ - PACKS(desc,"z",queue->fs_file); /* pszDocument */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszNotifyName */ - PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ - PACKS(desc,"z","lpd"); /* pszQProcName */ - PACKS(desc,"z",""); /* pszQProcParms */ - PACKS(desc,"z","NULL"); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - PACKS(desc,"z",""); /* pszPrinterName */ - } else if (uLevel == 4) { /* OS2 */ - PACKS(desc,"z",""); /* pszSpoolFileName */ - PACKS(desc,"z",""); /* pszPortName */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",0); /* ulPagesSpooled */ - PACKI(desc,"D",0); /* ulPagesSent */ - PACKI(desc,"D",0); /* ulPagesPrinted */ - PACKI(desc,"D",0); /* ulTimePrinted */ - PACKI(desc,"D",0); /* ulExtendJobStatus */ - PACKI(desc,"D",0); /* ulStartPage */ - PACKI(desc,"D",0); /* ulEndPage */ - } - } + time_t t = queue->time; + + /* the client expects localtime */ + t -= get_time_zone(t); + + PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */ + if (uLevel == 1) { + PACKS(desc,"B21",queue->fs_user); /* szUserName */ + PACKS(desc,"B",""); /* pad */ + PACKS(desc,"B16",""); /* szNotifyName */ + PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ + PACKS(desc,"z",""); /* pszParms */ + PACKI(desc,"W",n+1); /* uPosition */ + PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",t); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z",queue->fs_file); /* pszComment */ + } + if (uLevel == 2 || uLevel == 3 || uLevel == 4) { + PACKI(desc,"W",queue->priority); /* uPriority */ + PACKS(desc,"z",queue->fs_user); /* pszUserName */ + PACKI(desc,"W",n+1); /* uPosition */ + PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ + PACKI(desc,"D",t); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z","Samba"); /* pszComment */ + PACKS(desc,"z",queue->fs_file); /* pszDocument */ + if (uLevel == 3) { + PACKS(desc,"z",""); /* pszNotifyName */ + PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ + PACKS(desc,"z",""); /* pszParms */ + PACKS(desc,"z",""); /* pszStatus */ + PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ + PACKS(desc,"z","lpd"); /* pszQProcName */ + PACKS(desc,"z",""); /* pszQProcParms */ + PACKS(desc,"z","NULL"); /* pszDriverName */ + PackDriverData(desc); /* pDriverData */ + PACKS(desc,"z",""); /* pszPrinterName */ + } else if (uLevel == 4) { /* OS2 */ + PACKS(desc,"z",""); /* pszSpoolFileName */ + PACKS(desc,"z",""); /* pszPortName */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",0); /* ulPagesSpooled */ + PACKI(desc,"D",0); /* ulPagesSent */ + PACKI(desc,"D",0); /* ulPagesPrinted */ + PACKI(desc,"D",0); /* ulTimePrinted */ + PACKI(desc,"D",0); /* ulExtendJobStatus */ + PACKI(desc,"D",0); /* ulStartPage */ + PACKI(desc,"D",0); /* ulEndPage */ + } + } } /******************************************************************** @@ -2001,20 +2039,20 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch struct tm *t; time_t unixdate = time(NULL); - put_dos_date3(p,0,unixdate); /* this is the time that is looked at + srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at by NT in a "net time" operation, it seems to ignore the one below */ /* the client expects to get localtime, not GMT, in this bit (I think, this needs testing) */ - t = LocalTime(&unixdate); + t = localtime(&unixdate); SIVAL(p,4,0); /* msecs ? */ SCVAL(p,8,t->tm_hour); SCVAL(p,9,t->tm_min); SCVAL(p,10,t->tm_sec); SCVAL(p,11,0); /* hundredths of seconds */ - SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */ + SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */ SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ SCVAL(p,16,t->tm_mday); SCVAL(p,17,t->tm_mon + 1); @@ -2737,23 +2775,25 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param char *p2; const char *level_string; - /* get NIS home of a previously validated user - simeon */ - /* With share level security vuid will always be zero. - Don't depend on vuser being non-null !!. JRA */ - user_struct *vuser = get_valid_user_struct(vuid); - if(vuser != NULL) - DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, - vuser->user.unix_name)); + /* get NIS home of a previously validated user - simeon */ + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ + user_struct *vuser = get_valid_user_struct(vuid); + if(vuser != NULL) { + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, + vuser->user.unix_name)); + } - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); + DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); /* check it's a supported variant */ - if (strcmp(str1,"zWrLh") != 0) return False; - switch( uLevel ) - { + if (strcmp(str1,"zWrLh") != 0) { + return False; + } + switch( uLevel ) { case 0: level_string = "B21"; break; case 1: level_string = "B21BB16DWzzWz"; break; case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; @@ -2762,7 +2802,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param default: return False; } - if (strcmp(level_string,str2) != 0) return False; + if (strcmp(level_string,str2) != 0) { + return False; + } *rdata_len = mdrcnt + 1024; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); @@ -2776,13 +2818,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param memset(p,0,21); fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ - if (uLevel > 0) - { + if (uLevel > 0) { SCVAL(p,usri11_pad,0); /* padding - 1 byte */ *p2 = 0; } - if (uLevel >= 10) - { + + if (uLevel >= 10) { SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ pstrcpy(p2,"Comment"); p2 = skip_string(p2,1); @@ -2797,8 +2838,8 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param p2 = skip_string(p2,1); } - if (uLevel == 11) /* modelled after NTAS 3.51 reply */ - { + if (uLevel == 11) { + /* modelled after NTAS 3.51 reply */ SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ @@ -2832,8 +2873,8 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(p,usri11_code_page,0); /* code page */ } - if (uLevel == 1 || uLevel == 2) - { + + if (uLevel == 1 || uLevel == 2) { memset(p+22,' ',16); /* password */ SIVALS(p,38,-1); /* password age */ SSVAL(p,42, @@ -2847,8 +2888,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); p2 = skip_string(p2,1); - if (uLevel == 2) - { + if (uLevel == 2) { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); @@ -3506,47 +3546,46 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param /**************************************************************************** - The buffer was too small + The buffer was too small. ****************************************************************************/ -static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len) { - *rparam_len = MIN(*rparam_len,mprcnt); - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam_len = MIN(*rparam_len,mprcnt); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_BufTooSmall); + SSVAL(*rparam,0,NERR_BufTooSmall); - DEBUG(3,("Supplied buffer too small in API command\n")); + DEBUG(3,("Supplied buffer too small in API command\n")); - return(True); + return True; } - /**************************************************************************** - The request is not supported + The request is not supported. ****************************************************************************/ -static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len) { - *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam_len = 4; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_notsupported); - SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,0,NERR_notsupported); + SSVAL(*rparam,2,0); /* converter word */ - DEBUG(3,("Unsupported API command\n")); + DEBUG(3,("Unsupported API command\n")); - return(True); + return True; } static const struct { diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 65c31449bb..db061cb1b8 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -23,6 +23,7 @@ extern fstring remote_proto; extern enum protocol_types Protocol; extern int max_recv; + BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; struct auth_context *negprot_global_auth_context = NULL; @@ -115,9 +116,9 @@ static int reply_lanman1(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support readbraw writebraw (possibly) */ SIVAL(outbuf,smb_vwv6,sys_getpid()); - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); + SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60); - put_dos_date(outbuf,smb_vwv8,t); + srv_put_dos_date(outbuf,smb_vwv8,t); return (smb_len(outbuf)+4); } @@ -157,8 +158,8 @@ static int reply_lanman2(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv3,lp_maxmux()); SSVAL(outbuf,smb_vwv4,1); SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); - put_dos_date(outbuf,smb_vwv8,t); + SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60); + srv_put_dos_date(outbuf,smb_vwv8,t); return (smb_len(outbuf)+4); } @@ -245,9 +246,9 @@ static int reply_nt1(char *inbuf, char *outbuf) CAP_LEVEL_II_OPLOCKS; int secword=0; - time_t t = time(NULL); char *p, *q; BOOL negotiate_spnego = False; + time_t t = time(NULL); global_encrypted_passwords_negotiated = lp_encrypted_passwords(); @@ -321,7 +322,7 @@ static int reply_nt1(char *inbuf, char *outbuf) SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */ SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ put_long_date(outbuf+smb_vwv11+1,t); - SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); + SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60); p = q = smb_buf(outbuf); if (!negotiate_spnego) { diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 951c192e39..12f3d180b1 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -106,7 +106,7 @@ int reply_open_pipe_and_X(connection_struct *conn, SSVAL(outbuf,smb_vwv2, p->pnum); SSVAL(outbuf,smb_vwv3,fmode); - put_dos_date3(outbuf,smb_vwv4,mtime); + srv_put_dos_date3(outbuf,smb_vwv4,mtime); SIVAL(outbuf,smb_vwv6,size); SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,0x0001); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f83b0ff746..81240fcb92 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -914,14 +914,16 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(outbuf,10,0,True); SSVAL(outbuf,smb_vwv0,mode); - if(lp_dos_filetime_resolution(SNUM(conn)) ) - put_dos_date3(outbuf,smb_vwv1,mtime & ~1); - else - put_dos_date3(outbuf,smb_vwv1,mtime); + if(lp_dos_filetime_resolution(SNUM(conn)) ) { + srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1); + } else { + srv_put_dos_date3(outbuf,smb_vwv1,mtime); + } SIVAL(outbuf,smb_vwv3,(uint32)size); - if (Protocol >= PROTOCOL_NT1) + if (Protocol >= PROTOCOL_NT1) { SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); + } DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); @@ -963,7 +965,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } mode = SVAL(inbuf,smb_vwv0); - mtime = make_unix_date3(inbuf+smb_vwv1); + mtime = srv_make_unix_date3(inbuf+smb_vwv1); if (mode != FILE_ATTRIBUTE_NORMAL) { if (VALID_STAT_OF_DIR(sbuf)) @@ -1393,9 +1395,9 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SSVAL(outbuf,smb_vwv0,fsp->fnum); SSVAL(outbuf,smb_vwv1,fattr); if(lp_dos_filetime_resolution(SNUM(conn)) ) { - put_dos_date3(outbuf,smb_vwv2,mtime & ~1); + srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1); } else { - put_dos_date3(outbuf,smb_vwv2,mtime); + srv_put_dos_date3(outbuf,smb_vwv2,mtime); } SIVAL(outbuf,smb_vwv4,(uint32)size); SSVAL(outbuf,smb_vwv6,deny_mode); @@ -1563,9 +1565,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SSVAL(outbuf,smb_vwv2,fsp->fnum); SSVAL(outbuf,smb_vwv3,fattr); if(lp_dos_filetime_resolution(SNUM(conn)) ) { - put_dos_date3(outbuf,smb_vwv4,mtime & ~1); + srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1); } else { - put_dos_date3(outbuf,smb_vwv4,mtime); + srv_put_dos_date3(outbuf,smb_vwv4,mtime); } SIVAL(outbuf,smb_vwv6,(uint32)size); SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode)); @@ -3272,7 +3274,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Take care of any time sent in the close. */ - mtime = make_unix_date3(inbuf+smb_vwv1); + mtime = srv_make_unix_date3(inbuf+smb_vwv1); fsp_set_pending_modtime(fsp, mtime); /* @@ -3322,7 +3324,7 @@ int reply_writeclose(connection_struct *conn, numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - mtime = make_unix_date3(inbuf+smb_vwv4); + mtime = srv_make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { @@ -3639,7 +3641,7 @@ int reply_printqueue(connection_struct *conn, for (i=first;i @@ -5713,10 +5715,10 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, * this. */ - put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); - put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); + srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); + srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); /* Should we check pending modtime here ? JRA */ - put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); + srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) { SIVAL(outbuf,smb_vwv6,0); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index beaf35caa2..ee6bed9afd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -878,7 +878,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i SSVAL(params,0,fsp->fnum); SSVAL(params,2,open_attr); - put_dos_date2(params,4, mtime); + srv_put_dos_date2(params,4, mtime); SIVAL(params,8, (uint32)size); SSVAL(params,12,deny_mode); SSVAL(params,14,0); /* open_type - file or directory. */ @@ -1186,9 +1186,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - put_dos_date2(p,0,cdate); - put_dos_date2(p,4,adate); - put_dos_date2(p,8,mdate); + srv_put_dos_date2(p,0,cdate); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); SIVAL(p,12,(uint32)file_size); SIVAL(p,16,(uint32)allocation_size); SSVAL(p,20,mode); @@ -1218,9 +1218,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - put_dos_date2(p,0,cdate); - put_dos_date2(p,4,adate); - put_dos_date2(p,8,mdate); + srv_put_dos_date2(p,0,cdate); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); SIVAL(p,12,(uint32)file_size); SIVAL(p,16,(uint32)allocation_size); SSVAL(p,20,mode); @@ -1262,9 +1262,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - put_dos_date2(p,0,cdate); - put_dos_date2(p,4,adate); - put_dos_date2(p,8,mdate); + srv_put_dos_date2(p,0,cdate); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); SIVAL(p,12,(uint32)file_size); SIVAL(p,16,(uint32)allocation_size); SSVAL(p,20,mode); @@ -3016,9 +3016,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_INFO_STANDARD: DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n")); data_size = 22; - put_dos_date2(pdata,l1_fdateCreation,c_time); - put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ + srv_put_dos_date2(pdata,l1_fdateCreation,c_time); + srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); + srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ SIVAL(pdata,l1_cbFile,(uint32)file_size); SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(pdata,l1_attrFile,mode); @@ -3029,9 +3029,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd unsigned int ea_size = estimate_ea_size(conn, fsp, fname); DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n")); data_size = 26; - put_dos_date2(pdata,0,c_time); - put_dos_date2(pdata,4,sbuf.st_atime); - put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */ + srv_put_dos_date2(pdata,0,c_time); + srv_put_dos_date2(pdata,4,sbuf.st_atime); + srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */ SIVAL(pdata,12,(uint32)file_size); SIVAL(pdata,16,(uint32)allocation_size); SSVAL(pdata,20,mode); @@ -3730,9 +3730,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } /* access time */ - tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); + tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess); /* write time */ - tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); + tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); break; } -- cgit From 9d9fe2d58de24ff7fd7f95bae878d299a1c6d33c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 10 Nov 2005 21:10:24 +0000 Subject: r11655: Two small fixes * remove redundant call to sub_set_smb_name() in session setup code. * Fix lockup when running 'wbinfo -t' on a Samba PDC. Cause was new authenticated session setup from winbindd which resulted in a mangled username (machine_) that was not found in the local files and so was queiued up to nss_winbindd. Deadlock.... So now make sure to keep the trailing '$' for machine account names when calling sub_set_smb_name(). (This used to be commit b0a2d43b603c2e230da6ada73587696605102e8f) --- source3/smbd/sesssetup.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 34b161c92f..9ac258cb5e 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -954,9 +954,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } fstrcpy(sub_user, user); - - /* setup the string used by %U */ - sub_set_smb_name(user); } else { fstrcpy(sub_user, lp_guestaccount()); } -- cgit From 5a06869da700261b97c62b20802f17cf5277cba8 Mon Sep 17 00:00:00 2001 From: Paul Green Date: Thu, 10 Nov 2005 21:34:25 +0000 Subject: r11657: Tiny improvement to debug error message in dir_check_ftype. (This used to be commit 46674ca21d9c257bc48af97e313b49118c7b478d) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index c993012a25..0635db22db 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -802,7 +802,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn *mode = dos_mode(conn,pathreal,&sbuf); if (!dir_check_ftype(conn,*mode,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,(unsigned int)dirtype)); + DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype)); continue; } -- cgit From a4d729bdfadfc39fece612fcdd68955c3e3845bb Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 11 Nov 2005 03:03:41 +0000 Subject: r11661: Store the INFO3 in the PAC data into the netsamlogon_cache. Also remove the mem_ctx from the netsamlogon_cache_store() API. Guenther, what should we be doing with the other fields in the PAC_LOGON_INFO? (This used to be commit 8bead2d2825015fe41ba7d7401a12c06c29ea7f7) --- source3/smbd/sesssetup.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9ac258cb5e..2c96760167 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -180,10 +180,6 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - if (pac_data) { - logon_info = get_logon_info_from_pac(pac_data); - } - DEBUG(3,("Ticket name is [%s]\n", client)); p = strchr_m(client, '@'); @@ -196,6 +192,14 @@ static int reply_spnego_kerberos(connection_struct *conn, } *p = 0; + + /* save the PAC data if we have it */ + + if (pac_data) { + logon_info = get_logon_info_from_pac(pac_data); + netsamlogon_cache_store( client, &logon_info->info3 ); + } + if (!strequal(p+1, lp_realm())) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { -- cgit From 4c8fc93905e89e2c3efa1002ad8fbc2a78fe51e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 Nov 2005 06:29:48 +0000 Subject: r11718: Filter stored DOS attributes by SAMBA_ATTRIBUTES_MASK (0x7f). Jeremy. (This used to be commit 61444049e1543b364eea2ee79743287c75d37db5) --- source3/smbd/dosmode.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index fec148b8e6..814d008cbb 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -337,6 +337,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) if (result & aSYSTEM) DEBUG(8, ("s")); if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); + if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); @@ -355,6 +356,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, mode_t unixmode; int ret = -1; + /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */ + dosmode &= SAMBA_ATTRIBUTES_MASK; + DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname)); if (!st || (st && !VALID_STAT(*st))) { st = &st1; -- cgit From 394f87b9146fab2ebf6a635c8bd4d17e4959fc36 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Nov 2005 22:39:00 +0000 Subject: r11767: Doesn't need to be exported. Jeremy. (This used to be commit 52b6f0db2e4a209641187255bd8815c8d03a5315) --- source3/smbd/dosmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 814d008cbb..5dfeddb80a 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -126,7 +126,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL c Change a unix mode to a dos mode. ****************************************************************************/ -uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) +static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { int result = 0; enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn)); -- cgit From 90603cb3cddcab3c7577cdad81e4a134c39de4ce Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 22 Nov 2005 10:22:59 +0000 Subject: r11846: Destroy the TALLOC_CTX on error in the Kerberos session setup and give a more precise inline comment why PAC verification may fail. Guenther (This used to be commit 43b57715e9b44a0a0c7cc7fe3674a5fd4369e78b) --- source3/smbd/sesssetup.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 2c96760167..8aa046b85a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -168,6 +168,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_NO_MEMORY); if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { + talloc_destroy(mem_ctx); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -177,6 +178,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); + talloc_destroy(mem_ctx); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -188,6 +190,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); SAFE_FREE(client); + talloc_destroy(mem_ctx); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -206,6 +209,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); SAFE_FREE(client); + talloc_destroy(mem_ctx); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } } @@ -283,6 +287,7 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); + talloc_destroy(mem_ctx); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } } @@ -302,6 +307,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); passwd_free(&pw); + talloc_destroy(mem_ctx); return ERROR_NT(ret); } @@ -314,6 +320,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); passwd_free(&pw); + talloc_destroy(mem_ctx); return ERROR_NT(ret); } -- cgit From 056f06915e9c667393046a674581754d8a581d29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Nov 2005 16:21:52 +0000 Subject: r11861: Fix inspired by Thomas Neumann to ensure that default case applies only to new files and correctly examines 8.3 and long names. Jeremy. (This used to be commit ba931a015132f7e8fffa52c617cd8345a1da35d2) --- source3/smbd/filename.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b389b9c1ae..2ee8ba1e4f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,9 +150,6 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } - if (!conn->case_preserve || (mangle_is_8_3(name, False, SNUM(conn)) && !conn->short_case_preserve)) - strnorm(name, lp_defaultcase(SNUM(conn))); - start = name; pstrcpy(orig_path, name); @@ -301,16 +298,17 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(False); } - /* + /* * Just the last part of the name doesn't exist. - * We may need to strupper() or strlower() it in case - * this conversion is being used for file creation - * purposes. If the filename is of mixed case then - * don't normalise it. + * We need to strupper() or strlower() it as + * this conversion may be used for file creation + * purposes. Fix inspired by Thomas Neumann . */ - - if (!conn->case_preserve && (!strhasupper(start) || !strhaslower(start))) + if (!conn->case_preserve || + (mangle_is_8_3(start, False, SNUM(conn)) && + !conn->short_case_preserve)) { strnorm(start, lp_defaultcase(SNUM(conn))); + } /* * check on the mangled stack to see if we can recover the -- cgit From 1bfb5b734b0d5e1bc093bb43513729ed458fe372 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Nov 2005 12:31:40 +0000 Subject: r11909: Implement 'reset on zero vc'. This kills other connections when a session setup comes in with the vc (virtual connection) field set to zero. This is done by Windows, probably you can tweak that by some registry key. This boolean option controls whether an incoming session setup should kill other connections coming from the same IP. This matches the default Windows 2003 behaviour. Setting this parameter to yes becomes necessary when you have a flaky network and windows decides to reconnect while the old connection still has files with share modes open. These files become inaccessible over the new connection. The client sends a zero VC on the new connection, and Windows 2003 kills all other connections coming from the same IP. This way the locked files are accessible again. Please be aware that enabling this option will kill connections behind a masquerading router. Volker (This used to be commit 5629ca16235f0aa21fea3afd9e414309e4e1374e) --- source3/smbd/session.c | 3 ++- source3/smbd/sesssetup.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 9a9a0d90b2..27f760a088 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -198,7 +198,8 @@ void session_yield(user_struct *vuser) tdb_delete(tdb, key); } -static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state) +BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), + void *state) { if (!session_init()) { DEBUG(3, ("No tdb opened\n")); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8aa046b85a..a22a575c76 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -744,6 +744,29 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, a new session setup with VC==0 is ignored. ****************************************************************************/ +static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *p) +{ + struct sessionid *sessionid = (struct sessionid *)dbuf.dptr; + const char *ip = (const char *)p; + + if (!process_exists(pid_to_procid(sessionid->pid))) { + return 0; + } + + if (sessionid->pid == sys_getpid()) { + return 0; + } + + if (strcmp(ip, sessionid->ip_addr) != 0) { + return 0; + } + + message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN, + NULL, 0, True); + return 0; +} + static void setup_new_vc_session(void) { DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n")); @@ -751,6 +774,9 @@ static void setup_new_vc_session(void) conn_close_all(); invalidate_all_vuids(); #endif + if (lp_reset_on_zero_vc()) { + session_traverse(shutdown_other_smbds, client_addr()); + } } /**************************************************************************** -- cgit From e5b9a027ff860fd5f34cf91acd14a43f3d6dfbce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Nov 2005 17:03:50 +0000 Subject: r11943: Don't reset attrs to zero in EA get - we are adding to the attr list not resetting it. Jeremy. (This used to be commit 8ee569626be7ebf3b6ebf71e1becdd091b9e893a) --- source3/smbd/dosmode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 5dfeddb80a..7f3bda582d 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -190,7 +190,8 @@ static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S return False; } - *pattr = 0; + /* Don't reset pattr to zero as we may already have filename-based attributes we + need to preserve. */ sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); if (sizeret == -1) { -- cgit From defe1f3aa8ada898b158836993d8dc98c7cc3b76 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Nov 2005 20:14:07 +0000 Subject: r11945: Make us follow the newly documented pathname processing rules: "As a special case for directories with large numbers of files, if the case options are set as follows, "case sensitive = yes", "case preserve = no", "short preserve case = no" then the "default case" option will be applied and will modify all filenames sent from the client when accessing this share." This is needed as fixing the case preserve rules to only apply to new filenames broke the large directory fix. Glad we caught this before release. Thanks to jht for this one. Jeremy. (This used to be commit abc21cc7322d695cf77b6fb18f4ecdb16288c19b) --- source3/smbd/filename.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 2ee8ba1e4f..6c0f8b7758 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -150,6 +150,19 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } + /* + * Large directory fix normalization. If we're case sensitive, and + * the case preserving parameters are set to "no", normalize the case of + * the incoming filename from the client WHETHER IT EXISTS OR NOT ! + * This is in conflict with the current (3.0.20) man page, but is + * what people expect from the "large directory howto". I'll update + * the man page. Thanks to jht@samba.org for finding this. JRA. + */ + + if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { + strnorm(name, lp_defaultcase(SNUM(conn))); + } + start = name; pstrcpy(orig_path, name); -- cgit From d1f91f7c723733113b4e9792042101c80dfc064c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Dec 2005 06:46:46 +0000 Subject: r12043: It's amazing the warnings you find when compiling on a 64-bit box with gcc4 and -O6... Fix a bunch of C99 dereferencing type-punned pointer will break strict-aliasing rules errors. Also added prs_int32 (not uint32...) as it's needed in one place. Find places where prs_uint32 was being used to marshall/unmarshall a time_t (a big no no on 64-bits). More warning fixes to come. Thanks to Volker for nudging me to compile like this. Jeremy. (This used to be commit c65b752604f8f58abc4e7ae8514dc2c7f086271c) --- source3/smbd/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index e975da3e15..fd28df0d80 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -65,7 +65,7 @@ static void msg_deliver(void) * Incoming message is in DOS codepage format. Convert to UNIX. */ - if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg, True)) < 0 || !msg) { + if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **)(void *)&msg, True)) < 0 || !msg) { DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); for (i = 0; i < msgpos;) { if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { -- cgit From 05ac2de0df78d22ad5afb42ea5c72ba17bef8395 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Dec 2005 18:34:13 +0000 Subject: r12051: Merge across the lookup_name and lookup_sid work. Lets see how the build farm reacts :-) Volker (This used to be commit 9f99d04a54588cd9d1a1ab163ebb304437f932f7) --- source3/smbd/lanman.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 1e2a248851..90e36e2a83 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1837,9 +1837,6 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para gid_t *gids; size_t num_groups; size_t i; - fstring grp_domain; - fstring grp_name; - enum SID_NAME_USE grp_type; struct passwd *passwd; NTSTATUS result; @@ -1896,9 +1893,12 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para goto out; for (i=0; imem_ctx, &sids[i], NULL, &grp_name, + NULL) ) { + pstrcpy(p, grp_name); p += 21; count++; } -- cgit From f6a46f3329683217ec5c71b8a5bf9b8322df023f Mon Sep 17 00:00:00 2001 From: Lars Müller Date: Mon, 5 Dec 2005 16:51:19 +0000 Subject: r12076: Ensure setmntent() returns with != NULL in the disk_quotas() Linux version. The IRIX 6.2 version is still without this check as I'm not sure if setmntent() is implemented in the same way. (This used to be commit 519ed7ca0ecffbc341c7516758a678af59f98586) --- source3/smbd/quotas.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 8cb94bca3d..de31376d6c 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -216,7 +216,9 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB devno = S.st_dev ; - fp = setmntent(MOUNTED,"r"); + if ((fp = setmntent(MOUNTED,"r")) == NULL) + return(False) ; + found = False ; while ((mnt = getmntent(fp))) { -- cgit From 78fa625d2532da8e17ac599455f41db373f9c1ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Dec 2005 01:33:58 +0000 Subject: r12160: The filename parameter to get_share_mode_lock is going to become very important as we fix #3303, so make sure we don't accidently set it here. Jeremy. (This used to be commit d1a9d0587cd9a391f0193ca76cb319803c6e019f) --- source3/smbd/close.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index fcea62e1aa..43049a46a4 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -192,7 +192,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * This prevents race conditions with the file being created. JRA. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); if (lck == NULL) { DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name)); @@ -305,7 +305,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) * reference to a directory also. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); -- cgit From 661c5c741a5285a5ddf8c1fc74ba50335f1c1931 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 10 Dec 2005 11:22:01 +0000 Subject: r12163: Change lookup_sid and lookup_name to return const char * instead of char *, use a temporary talloc_ctx for clarity. Volker (This used to be commit b15815c804bf3e558ed6357b5e9a6e3e0fac777f) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 90e36e2a83..4778702e7a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1894,7 +1894,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para for (i=0; imem_ctx, &sids[i], NULL, &grp_name, NULL) ) { -- cgit From fa4df827d0b7e6e280a1736fb45772ed27131e64 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Dec 2005 18:21:59 +0000 Subject: r12194: Ensure that when we set a connection path we've canonicalized the name (must be abolute - start with /, must not end in /, must have ./ and ../ removed). Of course for realpath resolved paths this won't be the case but for others we need this name to be canonicalized. This name is going into the sharemode db for #3303 so needs to be in a normalized format. Jeremy. (This used to be commit 22e3300911809692b595f49e87d91e3111923e6a) --- source3/smbd/msdfs.c | 2 +- source3/smbd/posix_acls.c | 6 +-- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 105 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 107 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a4f371b18f..1279fe185d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -146,7 +146,7 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) return False; } - string_set(&conn->connectpath, connpath); + set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 91a3f5ed48..1b8e1d6214 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4220,7 +4220,7 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) connection_struct conn; files_struct finfo; struct fd_handle fh; - fstring path; + pstring path; pstring filename; ZERO_STRUCT( conn ); @@ -4231,8 +4231,8 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) return NULL; } - fstrcpy( path, "/" ); - string_set(&conn.connectpath, path); + pstrcpy( path, "/" ); + set_conn_connectpath(&conn, path); if (!smbd_vfs_init(&conn)) { DEBUG(0,("novfs_get_nt_acl: Unable to create a fake connection struct!\n")); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 81240fcb92..d3739c8847 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4954,7 +4954,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { ok = vfs_directory_exist(conn,newdir,NULL); if (ok) - string_set(&conn->connectpath,newdir); + set_conn_connectpath(conn,newdir); } if (!ok) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 52f9229ee1..210edde5d8 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -23,6 +23,105 @@ extern struct timeval smb_last_time; extern userdom_struct current_user_info; +/**************************************************************************** + Ensure when setting connectpath it is a canonicalized (no ./ // or ../) + absolute path stating in / and not ending in /. + Observent people will notice a similarity between this and check_path_syntax :-). +****************************************************************************/ + +void set_conn_connectpath(connection_struct *conn, const pstring connectpath) +{ + pstring destname; + char *d = destname; + const char *s = connectpath; + BOOL start_of_name_component = True; + + *d++ = '/'; /* Always start with root. */ + + while (*s) { + if (*s == '/') { + /* Eat multiple '/' */ + while (*s == '/') { + s++; + } + if ((d != destname) && (*s != '\0')) { + *d++ = '/'; + } + start_of_name_component = True; + continue; + } + + if (start_of_name_component) { + if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) { + /* Uh oh - "/../" or "/..\0" ! */ + + /* Go past the ../ or .. */ + if (s[2] == '/') { + s += 3; + } else { + s += 2; /* Go past the .. */ + } + + /* If we just added a '/' - delete it */ + if ((d > destname) && (*(d-1) == '/')) { + *(d-1) = '\0'; + d--; + } + + /* Are we at the start ? Can't go back further if so. */ + if (d <= destname) { + *d++ = '/'; /* Can't delete root */ + continue; + } + /* Go back one level... */ + /* Decrement d first as d points to the *next* char to write into. */ + for (d--; d > destname; d--) { + if (*d == '/') { + break; + } + } + /* We're still at the start of a name component, just the previous one. */ + continue; + } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) { + /* Component of pathname can't be "." only - skip the '.' . */ + if (s[1] == '/') { + s += 2; + } else { + s++; + } + continue; + } + } + + if (!(*s & 0x80)) { + *d++ = *s++; + } else { + switch(next_mb_char_size(s)) { + case 4: + *d++ = *s++; + case 3: + *d++ = *s++; + case 2: + *d++ = *s++; + case 1: + *d++ = *s++; + break; + default: + break; + } + } + start_of_name_component = False; + } + *d = '\0'; + + /* And must not end in '/' */ + if (d > destname + 1 && (*(d-1) == '/')) { + *(d-1) = '\0'; + } + + string_set(&conn->connectpath, destname); +} + /**************************************************************************** Load parameters specific to a connection/service. ****************************************************************************/ @@ -474,7 +573,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring s; pstrcpy(s,lp_pathname(snum)); standard_sub_conn(conn,s,sizeof(s)); - string_set(&conn->connectpath,s); + set_conn_connectpath(conn,s); DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); } @@ -537,7 +636,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring s; pstrcpy(s,conn->connectpath); canonicalize_path(conn, s); - string_set(&conn->connectpath,s); + set_conn_connectpath(conn,s); } /* ROOT Activities: */ @@ -652,7 +751,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring s; pstrcpy(s,conn->connectpath); vfs_GetWd(conn,s); - string_set(&conn->connectpath,s); + set_conn_connectpath(conn,s); vfs_ChDir(conn,conn->connectpath); } #endif -- cgit From 7d2771e758d4e8ef0adb45e55775b524de4dba9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Dec 2005 22:07:36 +0000 Subject: r12203: Add the share path into the sharemode db. This involves revving the minor version number for libsmbsharemodes (we now have a new _ex interface that takes the share path as well as the filename). Needed for #3303. Some code written by SATOH Fumiyasu included in the changes to locking/locking.c. The smbstatus output is a bit of a mess and needs overhauling... Jeremy. (This used to be commit 9d93af713f8520ca506730dd32aa2b994937eaba) --- source3/smbd/close.c | 4 ++-- source3/smbd/open.c | 15 ++++++++++----- source3/smbd/oplock.c | 6 +++--- source3/smbd/trans2.c | 14 +++----------- 4 files changed, 18 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 43049a46a4..d84b9f925b 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -192,7 +192,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * This prevents race conditions with the file being created. JRA. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name)); @@ -305,7 +305,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) * reference to a directory also. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 42e1da839f..b3f0589dc7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1123,8 +1123,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, spurious oplock break. */ /* Now remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->dev, state->inode, - fname); + lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1334,7 +1333,9 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = psbuf->st_dev; inode = psbuf->st_ino; - lck = get_share_mode_lock(NULL, dev, inode, fname); + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("Could not get share mode lock\n")); @@ -1533,7 +1534,9 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = fsp->dev; inode = fsp->inode; - lck = get_share_mode_lock(NULL, dev, inode, fname); + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); @@ -1940,7 +1943,9 @@ files_struct *open_directory(connection_struct *conn, fsp->is_stat = False; string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fname); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 385f998b1c..f6c97c3df4 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -182,7 +182,7 @@ BOOL remove_oplock(files_struct *fsp) struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -210,7 +210,7 @@ BOOL downgrade_oplock(files_struct *fsp) BOOL ret; struct share_mode_lock *lck; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -627,7 +627,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " "share mode entry for file %s.\n", fsp->fsp_name )); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ee6bed9afd..c165ea1862 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2824,10 +2824,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - delete_pending = - get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino, - fname); + delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); } else { /* * Original code - this is an open file. @@ -2840,10 +2837,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return(UNIXERROR(ERRDOS,ERRbadfid)); } pos = fsp->fh->position_information; - delete_pending = - get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino, - fname); + delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); access_mask = fsp->access_mask; } } else { @@ -2885,9 +2879,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino, - fname); + delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); if (delete_pending) { return ERROR_NT(NT_STATUS_DELETE_PENDING); } -- cgit From ab7a4f7e8e4b946a8acd0a205c16dbf6a3afecad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Dec 2005 18:11:50 +0000 Subject: r12213: Final fix for #3303 - send rename messages to smbd's that have open file handles to allow them to correctly implement delete on close. There is a further correctness fix I'm intending to add to this to cope with different share paths, but not right now... Jeremy. (This used to be commit 932e337db8788e75344e1c7cf1ef009d090cb039) --- source3/smbd/close.c | 45 ++++++++++++++++++++++++++++++++++----------- source3/smbd/open.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/reply.c | 28 +++++++++++++++++++++++----- source3/smbd/server.c | 1 + source3/smbd/service.c | 5 ++++- 5 files changed, 109 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d84b9f925b..407c607838 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -227,20 +227,43 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) */ if (normal_close && delete_file) { + SMB_STRUCT_STAT sbuf; + DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { - /* - * This call can potentially fail as another smbd may have - * had the file open with delete on close set and deleted - * it when its last reference to this file went away. Hence - * we log this but not at debug level zero. - */ - - DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \ -with error %s\n", fsp->fsp_name, strerror(errno) )); + + /* We can only delete the file if the name we have + is still valid and hasn't been renamed. */ + + if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { + DEBUG(5,("close_file: file %s. Delete on close was set " + "and stat failed with error %s\n", + fsp->fsp_name, strerror(errno) )); + } else { + if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { + DEBUG(5,("close_file: file %s. Delete on close was set and " + "dev and/or inode does not match\n", + fsp->fsp_name )); + DEBUG(5,("close_file: file %s. stored dev = %x, inode = %.0f " + "stat dev = %x, inode = %.0f\n", + fsp->fsp_name, + (unsigned int)fsp->dev, (double)fsp->inode, + (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); + + } else if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { + /* + * This call can potentially fail as another smbd may have + * had the file open with delete on close set and deleted + * it when its last reference to this file went away. Hence + * we log this but not at debug level zero. + */ + + DEBUG(5,("close_file: file %s. Delete on close was set " + "and unlink failed with error %s\n", + fsp->fsp_name, strerror(errno) )); + } + process_pending_change_notify_queue((time_t)0); } - process_pending_change_notify_queue((time_t)0); } talloc_free(lck); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b3f0589dc7..7621ee001d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2042,3 +2042,50 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return fsp; } + +/**************************************************************************** + Receive notification that one of our open files has been renamed by another + smbd process. +****************************************************************************/ + +void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len) +{ + files_struct *fsp; + struct file_renamed_message *frm = (struct file_renamed_message *)buf; + const char *sharepath; + const char *newname; + size_t sp_len; + + if (buf == NULL || len < sizeof(*frm)) { + DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); + return; + } + + sharepath = &frm->names[0]; + newname = sharepath + strlen(sharepath) + 1; + sp_len = strlen(sharepath); + + DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " + "dev %x, inode %.0f\n", + sharepath, newname, (unsigned int)frm->dev, (double)frm->inode )); + + for(fsp = file_find_di_first(frm->dev, frm->inode); fsp; fsp = file_find_di_next(fsp)) { + if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { + DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", + fsp->fnum, fsp->fsp_name, newname )); + string_set(&fsp->fsp_name, newname); + } else { + /* TODO. JRA. */ + /* Now we have the complete path we can work out if this is + actually within this share and adjust newname accordingly. */ + DEBUG(10,("msg_file_was_renamed: share mismatch (sharepath %s " + "not sharepath %s) " + "fnum %d from %s -> %s\n", + fsp->conn->connectpath, + sharepath, + fsp->fnum, + fsp->fsp_name, + newname )); + } + } +} diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d3739c8847..5ddba4c2bf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4082,13 +4082,15 @@ static BOOL resolve_wildcards(const char *name1, char *name2) } /**************************************************************************** - Ensure open files have their names updates. + Ensure open files have their names updated. Updated to notify other smbd's + asynchronously. ****************************************************************************/ -static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname) +static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, const char *newname) { files_struct *fsp; BOOL did_rename = False; + struct share_mode_lock *lck = NULL; for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", @@ -4098,9 +4100,24 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T did_rename = True; } - if (!did_rename) + if (!did_rename) { DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n", (unsigned int)dev, (double)inode, newname )); + } + + /* Notify all remote smbd's. */ + lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL); + if (lck == NULL) { + DEBUG(5,("rename_open_files: Could not get share mode lock for file %s\n", + fsp->fsp_name)); + return; + } + + /* Change the stored filename. */ + rename_share_filename(lck, conn->connectpath, newname); + + /* Send messages to all smbd's (not ourself) that the name has changed. */ + talloc_free(lck); } /**************************************************************************** @@ -4238,10 +4255,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * return NT_STATUS_OK; } - if (errno == ENOTDIR || errno == EISDIR) + if (errno == ENOTDIR || errno == EISDIR) { error = NT_STATUS_OBJECT_NAME_COLLISION; - else + } else { error = map_nt_error_from_unix(errno); + } DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", nt_errstr(error), fsp->fsp_name,newname)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1bf9dbc374..304f1b588e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -330,6 +330,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); message_register(MSG_SMB_SAM_REPL, msg_sam_repl); message_register(MSG_SHUTDOWN, msg_exit_server); + message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); /* now accept incoming connections - forking a new process for each incoming connection */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 210edde5d8..c9e2cdcf50 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -44,7 +44,7 @@ void set_conn_connectpath(connection_struct *conn, const pstring connectpath) while (*s == '/') { s++; } - if ((d != destname) && (*s != '\0')) { + if ((d > destname + 1) && (*s != '\0')) { *d++ = '/'; } start_of_name_component = True; @@ -119,6 +119,9 @@ void set_conn_connectpath(connection_struct *conn, const pstring connectpath) *(d-1) = '\0'; } + DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n", + lp_servicename(SNUM(conn)), destname )); + string_set(&conn->connectpath, destname); } -- cgit From e7d2e311a293709c74a97d0e30665dadae510712 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Dec 2005 17:46:29 +0000 Subject: r12234: Reduce the race condition for renames by holding the lock longer. Instigated by complaints on the fix for #3303 from SATOH Fumiyasu . Jeremy. (This used to be commit 855f5f8c32aa530dbad244805a40200824724618) --- source3/smbd/reply.c | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5ddba4c2bf..063cdf2974 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4086,13 +4086,20 @@ static BOOL resolve_wildcards(const char *name1, char *name2) asynchronously. ****************************************************************************/ -static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, const char *newname) +static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, + SMB_DEV_T dev, SMB_INO_T inode, const char *newname) { files_struct *fsp; BOOL did_rename = False; - struct share_mode_lock *lck = NULL; for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + /* fsp_name is a relative path under the fsp. To change this for other + sharepaths we need to manipulate relative paths. */ + /* TODO - create the absolute path and manipulate the newname + relative to the sharepath. */ + if (fsp->conn != conn) { + continue; + } DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fsp_name, newname )); @@ -4105,19 +4112,8 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T (unsigned int)dev, (double)inode, newname )); } - /* Notify all remote smbd's. */ - lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL); - if (lck == NULL) { - DEBUG(5,("rename_open_files: Could not get share mode lock for file %s\n", - fsp->fsp_name)); - return; - } - - /* Change the stored filename. */ - rename_share_filename(lck, conn->connectpath, newname); - /* Send messages to all smbd's (not ourself) that the name has changed. */ - talloc_free(lck); + rename_share_filename(lck, conn->connectpath, newname); } /**************************************************************************** @@ -4161,6 +4157,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * NTSTATUS error = NT_STATUS_OK; BOOL dest_exists; BOOL rcdest = True; + struct share_mode_lock *lck = NULL; ZERO_STRUCT(sbuf); rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); @@ -4248,13 +4245,18 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * return NT_STATUS_ACCESS_DENIED; } + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); - rename_open_files(conn, fsp->dev, fsp->inode, newname); + rename_open_files(conn, lck, fsp->dev, fsp->inode, newname); + talloc_free(lck); return NT_STATUS_OK; } + talloc_free(lck); + if (errno == ENOTDIR || errno == EISDIR) { error = NT_STATUS_OBJECT_NAME_COLLISION; } else { @@ -4286,6 +4288,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui BOOL rc = True; BOOL rcdest = True; SMB_STRUCT_STAT sbuf1, sbuf2; + struct share_mode_lock *lck = NULL; *directory = *mask = 0; @@ -4456,7 +4459,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", */ if (strcsequal(directory, newname)) { - rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory)); return NT_STATUS_OK; } @@ -4471,13 +4474,17 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_SHARING_VIOLATION; } + lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); + if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); - rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); + talloc_free(lck); return NT_STATUS_OK; } + talloc_free(lck); if (errno == ENOTDIR || errno == EISDIR) error = NT_STATUS_OBJECT_NAME_COLLISION; else @@ -4555,7 +4562,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } if (strcsequal(fname,destname)) { - rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); count++; error = NT_STATUS_OK; @@ -4573,11 +4580,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_SHARING_VIOLATION; } + lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); + if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); count++; error = NT_STATUS_OK; } + talloc_free(lck); DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } CloseDir(dir_hnd); -- cgit From 91efc453ab420d51998e159d14264cc24be71558 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Dec 2005 23:52:58 +0000 Subject: r12250: Patch from Martin Koeppe for #3287 to make the dev/inode numbers match what SFU expects. If we're using 8 byte inodes we'll lose the top 4 bytes and replace them with a dev_t instead, but this seem reasonable to ensure uniqueness. Jeremy. (This used to be commit e53574d0b43e5525029c89e56331701399013d91) --- source3/smbd/trans2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c165ea1862..6a4b7111cd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1436,8 +1436,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p +=4; } SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ - SIVAL(p,0,sbuf.st_dev); p += 4; - SIVAL(p,0,sbuf.st_ino); p += 4; + SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q, 0, len); p += len; @@ -1486,8 +1486,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } p += 26; SSVAL(p,0,0); p += 2; /* Reserved ? */ - SIVAL(p,0,sbuf.st_dev); p += 4; - SIVAL(p,0,sbuf.st_ino); p += 4; + SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; @@ -3216,8 +3216,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd BasicFileInformationTest. -tpot */ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); - SIVAL(pdata,0,sbuf.st_dev); - SIVAL(pdata,4,sbuf.st_ino); + SIVAL(pdata,4,sbuf.st_ino); /* FileIndexLow */ + SIVAL(pdata,0,sbuf.st_dev); /* FileIndexHigh */ data_size = 8; break; -- cgit From 10b5609a1458d156938302a5a26c11913c340476 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Dec 2005 01:41:12 +0000 Subject: r12279: unix_mask_match has been broken for *ever*... (How). Ensure it returns a BOOL. Jerry (and anyone else) please check this, I think all uses are now correct but could do with another set of eyes. Essential for 3.0.21 release. Jeremy. (This used to be commit 0c7b8a7637e760fcb6629092f36b610b8c71f5c9) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index c1168583ae..fed73db043 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -263,7 +263,7 @@ static int expect(int master, char *issue, char *expected) pstrcpy( str, buffer); trim_char( str, ' ', ' '); - if ((match = (unix_wild_match(expected, str) == 0))) { + if ((match = unix_wild_match(expected, str)) == True) { /* Now data has started to return, lower timeout. */ timeout = lp_passwd_chat_timeout() * 100; } -- cgit From b15c32800dd509bf63d7eab52b620e2ac289e95a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 17 Dec 2005 16:31:04 +0000 Subject: r12305: Reformatting (This used to be commit f574e980aac5bae5e1e3cc23ec648b69a87eb04a) --- source3/smbd/password.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9ee721089c..e4516be32b 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -381,9 +381,14 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (lp_invalid_users(snum)) { str_list_copy(&invalid, lp_invalid_users(snum)); - if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { - if ( invalid && str_list_sub_basic(invalid, current_user_info.smb_name) ) { - ret = !user_in_list(user, (const char **)invalid, groups, n_groups); + if (invalid && + str_list_substitute(invalid, "%S", lp_servicename(snum))) { + if ( invalid && + str_list_sub_basic(invalid, + current_user_info.smb_name) ) { + ret = !user_in_list(user, + (const char **)invalid, + groups, n_groups); } } } @@ -392,9 +397,13 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (ret && lp_valid_users(snum)) { str_list_copy(&valid, lp_valid_users(snum)); - if ( valid && str_list_substitute(valid, "%S", lp_servicename(snum)) ) { - if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { - ret = user_in_list(user, (const char **)valid, groups, n_groups); + if ( valid && + str_list_substitute(valid, "%S", lp_servicename(snum)) ) { + if ( valid && + str_list_sub_basic(valid, + current_user_info.smb_name) ) { + ret = user_in_list(user, (const char **)valid, + groups, n_groups); } } } @@ -403,8 +412,11 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (ret && lp_onlyuser(snum)) { char **user_list = str_list_make (lp_username(snum), NULL); - if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) { - ret = user_in_list(user, (const char **)user_list, groups, n_groups); + if (user_list && + str_list_substitute(user_list, "%S", + lp_servicename(snum))) { + ret = user_in_list(user, (const char **)user_list, + groups, n_groups); } if (user_list) str_list_free (&user_list); } -- cgit From 862e4a11c15b9971762e5ee97186fbccdd2fcfdf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 17 Dec 2005 17:13:45 +0000 Subject: r12307: Reformatting plus a trivial if/else simplification. There's no point in doing an else branch that only returns NULL. Volker (This used to be commit ef4d9d96de3f1a242d26ae2f8033103bbdb7a2dc) --- source3/smbd/service.c | 194 +++++++++++++++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 72 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c9e2cdcf50..c5fba5b50e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -366,7 +366,8 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) static connection_struct *make_connection_snum(int snum, user_struct *vuser, DATA_BLOB password, - const char *pdev, NTSTATUS *status) + const char *pdev, + NTSTATUS *status) { struct passwd *pass = NULL; BOOL guest = False; @@ -396,7 +397,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, guest = True; pass = getpwnam_alloc(guestname); if (!pass) { - DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname)); + DEBUG(0,("make_connection_snum: Invalid guest " + "account %s??\n",guestname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_USER; return NULL; @@ -411,14 +413,20 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } else if (vuser) { if (vuser->guest) { if (!lp_guest_ok(snum)) { - DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum))); + DEBUG(2, ("guest user (from session setup) " + "not permitted to access this share " + "(%s)\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; } } else { - if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) { - DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum))); + if (!user_ok(vuser->user.unix_name, snum, + vuser->groups, vuser->n_groups)) { + DEBUG(2, ("user '%s' (from session setup) not " + "permitted to access this share " + "(%s)\n", vuser->user.unix_name, + lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; @@ -465,12 +473,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); - conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); + conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || + ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); conn->dirptr = NULL; /* Case options for the share. */ if (lp_casesensitive(snum) == Auto) { - /* We will be setting this per packet. Set to be case insensitive for now. */ + /* We will be setting this per packet. Set to be case + * insensitive for now. */ conn->case_sensitive = False; } else { conn->case_sensitive = (BOOL)lp_casesensitive(snum); @@ -545,30 +555,30 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring_sub(gname,"%S",lp_servicename(snum)); gid = nametogid(gname); - if (gid != (gid_t)-1) { - - /* - * If the user has been forced and the forced group starts - * with a '+', then we only set the group to be the forced - * group if the forced user is a member of that group. - * Otherwise, the meaning of the '+' would be ignored. - */ - if (conn->force_user && user_must_be_member) { - if (user_in_group_list( user, gname, NULL, 0)) { - conn->gid = gid; - DEBUG(3,("Forced group %s for member %s\n",gname,user)); - } - } else { - conn->gid = gid; - DEBUG(3,("Forced group %s\n",gname)); - } - conn->force_group = True; - } else { + if (gid == (gid_t)-1) { DEBUG(1,("Couldn't find group %s\n",gname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_GROUP; return NULL; } + + /* + * If the user has been forced and the forced group starts + * with a '+', then we only set the group to be the forced + * group if the forced user is a member of that group. + * Otherwise, the meaning of the '+' would be ignored. + */ + if (conn->force_user && user_must_be_member) { + if (user_in_group_list( user, gname, NULL, 0)) { + conn->gid = gid; + DEBUG(3,("Forced group %s for member %s\n", + gname,user)); + } + } else { + conn->gid = gid; + DEBUG(3,("Forced group %s\n",gname)); + } + conn->force_group = True; } #endif /* HAVE_GETGRNAM */ @@ -577,7 +587,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstrcpy(s,lp_pathname(snum)); standard_sub_conn(conn,s,sizeof(s)); set_conn_connectpath(conn,s); - DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); + DEBUG(3,("Connect path is '%s' for service [%s]\n",s, + lp_servicename(snum))); } if (conn->force_user || conn->force_group) { @@ -591,9 +602,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, initialise_groups(conn->user, conn->uid, conn->gid); get_current_groups(conn->gid, &conn->ngroups,&conn->groups); - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, - conn->ngroups, conn->groups, - guest); + conn->nt_user_token = + create_nt_token(conn->uid, conn->gid, + conn->ngroups, conn->groups, + guest); } /* @@ -604,12 +616,16 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ { - BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA); + BOOL can_write = share_access_check(conn, snum, vuser, + FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) { + if (!share_access_check(conn, snum, vuser, + FILE_READ_DATA)) { /* No access, read or write. */ - DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", + DEBUG(0,("make_connection: connection to %s " + "denied due to security " + "descriptor.\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -622,18 +638,19 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Initialise VFS function pointers */ if (!smbd_vfs_init(conn)) { - DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); + DEBUG(0, ("vfs_init failed for service %s\n", + lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } /* - * If widelinks are disallowed we need to canonicalise the - * connect path here to ensure we don't have any symlinks in - * the connectpath. We will be checking all paths on this - * connection are below this directory. We must do this after - * the VFS init as we depend on the realpath() pointer in the vfs table. JRA. + * If widelinks are disallowed we need to canonicalise the connect + * path here to ensure we don't have any symlinks in the + * connectpath. We will be checking all paths on this connection are + * below this directory. We must do this after the VFS init as we + * depend on the realpath() pointer in the vfs table. JRA. */ if (!lp_widelinks(snum)) { pstring s; @@ -654,7 +671,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - /* Preexecs are done here as they might make the dir we are to ChDir to below */ + /* Preexecs are done here as they might make the dir we are to ChDir + * to below */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(snum)) { pstring cmd; @@ -663,7 +681,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(snum)) { - DEBUG(1,("root preexec gave %d - failing connection\n", ret)); + DEBUG(1,("root preexec gave %d - failing " + "connection\n", ret)); yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -681,9 +700,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - /* Remember that a different vuid can connect later without these checks... */ + /* Remember that a different vuid can connect later without these + * checks... */ - /* Preexecs are done here as they might make the dir we are to ChDir to below */ + /* Preexecs are done here as they might make the dir we are to ChDir + * to below */ + /* execute any "preexec = " line */ if (*lp_preexec(snum)) { pstring cmd; @@ -691,7 +713,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, standard_sub_conn(conn,cmd,sizeof(cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(snum)) { - DEBUG(1,("preexec gave %d - failing connection\n", ret)); + DEBUG(1,("preexec gave %d - failing connection\n", + ret)); change_to_root_user(); yield_connection(conn, lp_servicename(snum)); conn_free(conn); @@ -713,8 +736,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); } - /* Invoke VFS make connection hook - do this before the VFS_STAT call to allow - any filesystems needing user credentials to initialize themselves. */ + /* Invoke VFS make connection hook - do this before the VFS_STAT call + to allow any filesystems needing user credentials to initialize + themselves. */ if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); @@ -730,12 +754,17 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, check during individual operations. To match this behaviour I have disabled this chdir check (tridge) */ /* the alternative is just to check the directory exists */ - if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || !S_ISDIR(st.st_mode)) { + if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || + !S_ISDIR(st.st_mode)) { if (ret == 0 && !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum))); + DEBUG(0,("'%s' is not a directory, when connecting to " + "[%s]\n", conn->connectpath, + lp_servicename(snum))); } else { - DEBUG(0,("'%s' does not exist or permission denied when connecting to [%s] " - "Error was %s\n", conn->connectpath, lp_servicename(snum), strerror(errno) )); + DEBUG(0,("'%s' does not exist or permission denied " + "when connecting to [%s] Error was %s\n", + conn->connectpath, lp_servicename(snum), + strerror(errno) )); } change_to_root_user(); /* Call VFS disconnect hook */ @@ -766,7 +795,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { - dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); + dbgtext( "%s (%s) ", get_remote_machine_name(), + conn->client_address ); dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(snum) ); dbgtext( "initially as user %s ", user ); @@ -784,8 +814,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, vfs_chdir() **************************************************************************************/ -connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password, - const char *dev, uint16 vuid, NTSTATUS *status) +connection_struct *make_connection_with_chdir(const char *service_in, + DATA_BLOB password, + const char *dev, uint16 vuid, + NTSTATUS *status) { connection_struct *conn = NULL; @@ -797,7 +829,8 @@ connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB */ if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { - DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n", + DEBUG(0,("move_driver_to_download_area: Can't change " + "directory to %s for [print$] (%s)\n", conn->connectpath,strerror(errno))); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); @@ -815,7 +848,8 @@ connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB ****************************************************************************/ connection_struct *make_connection(const char *service_in, DATA_BLOB password, - const char *pdev, uint16 vuid, NTSTATUS *status) + const char *pdev, uint16 vuid, + NTSTATUS *status) { uid_t euid; user_struct *vuser = NULL; @@ -825,43 +859,52 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstrcpy(dev, pdev); - /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ + /* This must ONLY BE CALLED AS ROOT. As it exits this function as + * root. */ if (!non_root_mode() && (euid = geteuid()) != 0) { - DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); + DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot " + "(%u)\n", (unsigned int)euid )); smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); } if(lp_security() != SEC_SHARE) { vuser = get_valid_user_struct(vuid); if (!vuser) { - DEBUG(1,("make_connection: refusing to connect with no session setup\n")); + DEBUG(1,("make_connection: refusing to connect with " + "no session setup\n")); *status = NT_STATUS_ACCESS_DENIED; return NULL; } } - /* Logic to try and connect to the correct [homes] share, preferably without too many - getpwnam() lookups. This is particulary nasty for winbind usernames, where the - share name isn't the same as unix username. + /* Logic to try and connect to the correct [homes] share, preferably + without too many getpwnam() lookups. This is particulary nasty for + winbind usernames, where the share name isn't the same as unix + username. - The snum of the homes share is stored on the vuser at session setup time. + The snum of the homes share is stored on the vuser at session setup + time. */ if (strequal(service_in,HOMES_NAME)) { if(lp_security() != SEC_SHARE) { DATA_BLOB no_pw = data_blob(NULL, 0); if (vuser->homes_snum == -1) { - DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n")); + DEBUG(2, ("[homes] share not available for " + "this user because it was not found " + "or created at session setup " + "time\n")); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } - DEBUG(5, ("making a connection to [homes] service created at session setup time\n")); + DEBUG(5, ("making a connection to [homes] service " + "created at session setup time\n")); return make_connection_snum(vuser->homes_snum, vuser, no_pw, dev, status); } else { - /* Security = share. Try with current_user_info.smb_name - * as the username. */ + /* Security = share. Try with + * current_user_info.smb_name as the username. */ if (*current_user_info.smb_name) { fstring unix_username; fstrcpy(unix_username, @@ -870,16 +913,20 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, snum = find_service(unix_username); } if (snum != -1) { - DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in)); + DEBUG(5, ("making a connection to 'homes' " + "service %s based on " + "security=share\n", service_in)); return make_connection_snum(snum, NULL, password, dev, status); } } } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) - && strequal(service_in, lp_servicename(vuser->homes_snum))) { + && strequal(service_in, + lp_servicename(vuser->homes_snum))) { DATA_BLOB no_pw = data_blob(NULL, 0); - DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in)); + DEBUG(5, ("making a connection to 'homes' service [%s] " + "created at session setup time\n", service_in)); return make_connection_snum(vuser->homes_snum, vuser, no_pw, dev, status); @@ -893,7 +940,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, if (snum < 0) { if (strequal(service,"IPC$") - || (lp_enable_asu_support() && strequal(service,"ADMIN$"))) + || (lp_enable_asu_support() && + strequal(service,"ADMIN$"))) { DEBUG(3,("refusing IPC connection to %s\n", service)); *status = NT_STATUS_ACCESS_DENIED; @@ -908,7 +956,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, /* Handle non-Dfs clients attempting connections to msdfs proxy */ if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) { - DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n", + DEBUG(3, ("refusing connection to dfs proxy share '%s' " + "(pointing to %s)\n", service, lp_msdfs_proxy(snum))); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; @@ -937,7 +986,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_root_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", - get_remote_machine_name(),conn->client_address, + get_remote_machine_name(), + conn->client_address, lp_servicename(SNUM(conn)))); /* Call VFS disconnect hook */ -- cgit From f2c8291791a557889fcdaa4dbcf7d2312e835033 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 17 Dec 2005 17:19:21 +0000 Subject: r12308: Reformatting (This used to be commit 97acfa12e52e889c97d0f7ce72c1a7f863cb0665) --- source3/smbd/service.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c5fba5b50e..fb9dbf0489 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -939,10 +939,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, snum = find_service(service); if (snum < 0) { - if (strequal(service,"IPC$") - || (lp_enable_asu_support() && - strequal(service,"ADMIN$"))) - { + if (strequal(service,"IPC$") || + (lp_enable_asu_support() && strequal(service,"ADMIN$"))) { DEBUG(3,("refusing IPC connection to %s\n", service)); *status = NT_STATUS_ACCESS_DENIED; return NULL; -- cgit From 46dee7219da466e292c865fa7e24bc8634197875 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Dec 2005 13:54:53 +0000 Subject: r12311: Reformatting (This used to be commit 23f5be1dcbb9e5a1e7f24813c67009056b07d59c) --- source3/smbd/password.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e4516be32b..764fbe8a2e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -521,19 +521,21 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, BOOL ok = False; #ifdef DEBUG_PASSWORD - DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n", - user,password.data)); + DEBUG(100,("authorise_login: checking authorisation on " + "user=%s pass=%s\n", user,password.data)); #endif *guest = False; /* there are several possibilities: 1) login as the given user with given password - 2) login as a previously registered username with the given password + 2) login as a previously registered username with the given + password 3) login as a session list username with the given password 4) login as a previously validated user/password pair 5) login as the "user =" user with given password - 6) login as the "user =" user with no password (guest connection) + 6) login as the "user =" user with no password + (guest connection) 7) login as guest user with no password if the service is guest_only then steps 1 to 5 are skipped @@ -562,11 +564,12 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, if (password_ok(user2,password)) { ok = True; fstrcpy(user,user2); - DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \ -and given password ok\n", user)); + DEBUG(3,("authorise_login: ACCEPTED: session " + "list username (%s) and given " + "password ok\n", user)); } } - + SAFE_FREE(user_list); } @@ -585,17 +588,21 @@ and given password ok\n", user)); if (auser) { ok = True; fstrcpy(user,auser); - DEBUG(3,("authorise_login: ACCEPTED: group username \ -and given password ok (%s)\n", user)); + DEBUG(3,("authorise_login: ACCEPTED: " + "group username and given " + "password ok (%s)\n", user)); } } else { fstring user2; fstrcpy(user2,auser); - if (user_ok(user2,snum, NULL, 0) && password_ok(user2,password)) { + if (user_ok(user2,snum, NULL, 0) && + password_ok(user2,password)) { ok = True; fstrcpy(user,user2); - DEBUG(3,("authorise_login: ACCEPTED: user list username \ -and given password ok (%s)\n", user)); + DEBUG(3,("authorise_login: ACCEPTED: " + "user list username and " + "given password ok (%s)\n", + user)); } } } @@ -608,10 +615,11 @@ and given password ok (%s)\n", user)); if (Get_Pwnam(guestname)) { fstrcpy(user,guestname); ok = True; - DEBUG(3,("authorise_login: ACCEPTED: guest account and guest ok (%s)\n", - user)); + DEBUG(3,("authorise_login: ACCEPTED: guest account " + "and guest ok (%s)\n", user)); } else { - DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname)); + DEBUG(0,("authorise_login: Invalid guest account " + "%s??\n",guestname)); } *guest = True; } -- cgit From 0a585102d656b267af723a5bdd258e83f532c3a6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Dec 2005 14:23:23 +0000 Subject: r12312: Reformatting and a trivial change: is_share_read_only_for_user only uses conn->service, so there's no point in passing down the whole conn struct. Volker (This used to be commit 39041297c771795efaa4292bc6e8020c1a047f32) --- source3/smbd/uid.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index d1ecaf6625..458eb3a2c8 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -81,45 +81,53 @@ BOOL change_to_guest(void) Readonly share for this user ? ****************************************************************************/ -static BOOL is_share_read_only_for_user(connection_struct *conn, user_struct *vuser) +static BOOL is_share_read_only_for_user(int snum, user_struct *vuser) { char **list; - const char *service = lp_servicename(conn->service); - BOOL read_only_ret = lp_readonly(conn->service); + const char *service = lp_servicename(snum); + BOOL read_only_ret = lp_readonly(snum); if (!service) return read_only_ret; - str_list_copy(&list, lp_readlist(conn->service)); + str_list_copy(&list, lp_readlist(snum)); if (list) { if (!str_list_sub_basic(list, vuser->user.smb_name) ) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: read list substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: read " + "list substitution failed\n")); } if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: read list service substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: read " + "list service substitution failed\n")); } - if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) { + if (user_in_list(vuser->user.unix_name, (const char **)list, + vuser->groups, vuser->n_groups)) { read_only_ret = True; } str_list_free(&list); } - str_list_copy(&list, lp_writelist(conn->service)); + str_list_copy(&list, lp_writelist(snum)); if (list) { if (!str_list_sub_basic(list, vuser->user.smb_name) ) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: write list substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: write " + "list substitution failed\n")); } if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: write list service substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: write " + "list service substitution failed\n")); } - if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) { + if (user_in_list(vuser->user.unix_name, (const char **)list, + vuser->groups, vuser->n_groups)) { read_only_ret = False; } str_list_free(&list); } - DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user %s\n", - service, read_only_ret ? "read-only" : "read-write", vuser->user.unix_name )); + DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user " + "%s\n", service, + read_only_ret ? "read-only" : "read-write", + vuser->user.unix_name )); return read_only_ret; } @@ -146,7 +154,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups)) return(False); - readonly_share = is_share_read_only_for_user(conn, vuser); + readonly_share = is_share_read_only_for_user(conn->service, vuser); if (!readonly_share && !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) { -- cgit From e53642a131d48bd8c092b7ea537744e59556be88 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 Dec 2005 23:07:25 +0000 Subject: r12376: Second patch from Martin Koeppe for #3287. Jeremy. (This used to be commit 8680eebbba220eea257c9ea093d5a463afe7bd94) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6a4b7111cd..191ccdcf8b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3216,8 +3216,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd BasicFileInformationTest. -tpot */ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); - SIVAL(pdata,4,sbuf.st_ino); /* FileIndexLow */ - SIVAL(pdata,0,sbuf.st_dev); /* FileIndexHigh */ + SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */ + SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */ data_size = 8; break; -- cgit From 67706697c5d8302e0d05d179de90c219531db8c7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Dec 2005 21:06:41 +0000 Subject: r12460: Fixes for bug 3349 (This used to be commit 040eda6bf0517204d5650702eea7e1d1c5eeb3d5) --- source3/smbd/close.c | 2 ++ source3/smbd/open.c | 8 ++++++-- source3/smbd/oplock.c | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 407c607838..f834869935 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -130,8 +130,10 @@ static void notify_deferred_opens(struct share_mode_lock *lck) */ schedule_deferred_open_smb_message(e->op_mid); } else { + become_root(); message_send_pid(e->pid, MSG_SMB_OPEN_RETRY, e, sizeof(*e), True); + unbecome_root(); } } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7621ee001d..e6c749fab9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -682,11 +682,15 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) } if (delay_it) { + BOOL ret; DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); - if (!message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - exclusive, sizeof(*exclusive), True)) { + become_root(); + ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + exclusive, sizeof(*exclusive), True); + unbecome_root(); + if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); } file_free(fsp); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index f6c97c3df4..54e7da11af 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -398,8 +398,10 @@ static void process_oplock_break_message(int msg_type, struct process_id src, * get to process this message, we have closed the file. Reply * with 'ok, oplock broken' */ DEBUG(3, ("Did not find fsp\n")); + become_root(); message_send_pid(src, MSG_SMB_BREAK_RESPONSE, msg, sizeof(*msg), True); + unbecome_root(); return; } @@ -418,8 +420,10 @@ static void process_oplock_break_message(int msg_type, struct process_id src, DEBUG(3, ("Already downgraded oplock on %.0f/%.0f: %s\n", (double)fsp->dev, (double)fsp->inode, fsp->fsp_name)); + become_root(); message_send_pid(src, MSG_SMB_BREAK_RESPONSE, msg, sizeof(*msg), True); + unbecome_root(); return; } @@ -545,11 +549,13 @@ void reply_to_oplock_break_requests(files_struct *fsp) { int i; + become_root(); for (i=0; inum_pending_break_messages; i++) { struct share_mode_entry *msg = &fsp->pending_break_messages[i]; message_send_pid(msg->pid, MSG_SMB_BREAK_RESPONSE, msg, sizeof(*msg), True); } + unbecome_root(); SAFE_FREE(fsp->pending_break_messages); fsp->num_pending_break_messages = 0; @@ -686,8 +692,10 @@ void release_level_2_oplocks_on_change(files_struct *fsp) abort(); } + become_root(); message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK, share_entry, sizeof(*share_entry), True); + unbecome_root(); } remove_all_share_oplocks(lck, fsp); -- cgit From bd08ae25dccff147547cda7575e2171abeb2195f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 25 Dec 2005 10:41:34 +0000 Subject: r12477: Remove a gcc -O6 warning (This used to be commit dd39a37f8e6ab7dad46b180959636f5e402c136d) --- source3/smbd/quotas.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index de31376d6c..d6ba7bc2d5 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -206,6 +206,8 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB uid_t euser_id; gid_t egrp_id; + ZERO_STRUCT(D); + euser_id = geteuid(); egrp_id = getegid(); -- cgit From c4ccc8f37ec4247a3a27277df14311389040fc25 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Dec 2005 11:44:15 +0000 Subject: r12491: End profile fixes from SATOH Fumiyasu . Jeremy. (This used to be commit 2187502732e41690bf266f229312bb9c7177cf22) --- source3/smbd/nttrans.c | 1 - source3/smbd/reply.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 91dcc93322..72288e2c24 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1288,7 +1288,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) { restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); return ERROR_NT(status); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 063cdf2974..d56e3c1f1c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5465,7 +5465,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, outsize = set_message(outbuf,0,0,True); if(!fsp || (fsp->conn != conn)) { - END_PROFILE(SMBgetattrE); + END_PROFILE(SMBsetattrE); return ERROR_DOS(ERRDOS,ERRbadfid); } -- cgit From 5a4881bf396e691524329bcd6aa1ae4a7f4084ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Dec 2005 20:52:36 +0000 Subject: r12522: Try and fix bug #2926 by removing setlocale(LC_ALL, "C") and replace calls to isupper/islower/toupper/tolower with ASCII equivalents (mapping into _w variants). Jeremy. (This used to be commit c2752347eb2deeb2798c580ec7fc751a847717e9) --- source3/smbd/mangle_hash.c | 6 +++--- source3/smbd/mangle_hash2.c | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 30befd2c84..2092f430c0 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -372,8 +372,8 @@ static BOOL is_mangled(const char *s, int snum) magic = strchr_m( s, magic_char ); while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */ if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ - && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ - && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ + && isbasechar( toupper_ascii(magic[1]) ) /* is 2nd char basechar? */ + && isbasechar( toupper_ascii(magic[2]) ) ) /* is 3rd char basechar? */ return( True ); /* If all above, then true, */ magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ } @@ -426,7 +426,7 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) s1 = strrchr( mangled_name_key, '.' ); if( s1 && (s2 = strrchr( raw_name, '.' )) ) { size_t i = 1; - while( s1[i] && (tolower( s1[i] ) == s2[i]) ) + while( s1[i] && (tolower_ascii( s1[i] ) == s2[i]) ) i++; if( !s1[i] && !s2[i] ) { /* Truncate at the '.' */ diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 335ba8e2ef..0a161c9e76 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -560,7 +560,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } - lead_chars[i] = toupper(lead_chars[i]); + lead_chars[i] = toupper_ascii(lead_chars[i]); } for (;i Date: Thu, 29 Dec 2005 13:10:33 +0000 Subject: r12564: Ensure load_case_tables is always done first. Jeremy. (This used to be commit addb5095292d6b201cc85f6acab5ec8e6f8f4404) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 304f1b588e..ff894e2460 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -718,6 +718,8 @@ void build_options(BOOL screen); { NULL } }; + load_case_tables(); + #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif @@ -742,8 +744,6 @@ void build_options(BOOL screen); sec_init(); - load_case_tables(); - set_remote_machine_name("smbd", False); if (interactive) { -- cgit From 7a1cf83dec95ac139c5dd50f3ae6b365e39bfd48 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 1 Jan 2006 15:59:22 +0000 Subject: r12653: Patch from SATOH Fumiyasu for bug #3348. Don't assume owning sticky bit directory means write access allowed. Jeremy. (This used to be commit 1032aa890f53097f87fa97689cb21d908b32093c) --- source3/smbd/posix_acls.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 1b8e1d6214..f49f80f006 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4149,8 +4149,13 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { return False; } - if (current_user.uid == sbuf_file.st_uid) { - return True; + /* + * Patch from SATOH Fumiyasu + * for bug #3348. Don't assume owning sticky bit + * directory means write access allowed. + */ + if (current_user.uid != sbuf_file.st_uid) { + return False; } return False; } -- cgit From 2b509f470d616c8df69e72ec04e25114d22af50f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Jan 2006 12:48:54 +0000 Subject: r12713: Remove use of uint8_t -> uint8. Jeremy. (This used to be commit 4473ac4ef9c86574fc49b1e67089b59b14b6d10d) --- source3/smbd/oplock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 54e7da11af..f788fc9e2e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -252,7 +252,7 @@ int setup_oplock_select_set( fd_set *fds) ****************************************************************************/ static char *new_break_smb_message(TALLOC_CTX *mem_ctx, - files_struct *fsp, uint8_t cmd) + files_struct *fsp, uint8 cmd) { char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0); -- cgit From a189257c15725e36e68970ed723f3365d4496792 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jan 2006 11:35:29 +0000 Subject: r12721: GPFS 2.4 on Linux will contain some windows semantics, ie share modes and oplocks across the cluster. Adapt Samba to it. The gpfs API is called via libgpfs.so. This code is written with dlopen(), so that you can compile on a system with gpfs installed and later on run on systems without gpfs available. So to actually make Samba call gpfs share mode calls you need to compile with gpfs.h and libgpfs.so around and set 'gpfs share = yes' on the shares you export from GPFS. Volker (This used to be commit 2253b17a1a88555291b59d52c826c81c2b8f7e7f) --- source3/smbd/gpfs.c | 159 ++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/open.c | 14 ++++ source3/smbd/oplock_linux.c | 22 ++++-- source3/smbd/server.c | 2 + 4 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 source3/smbd/gpfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/gpfs.c b/source3/smbd/gpfs.c new file mode 100644 index 0000000000..4a8b9eea6c --- /dev/null +++ b/source3/smbd/gpfs.c @@ -0,0 +1,159 @@ +/* + * Unix SMB/CIFS implementation. + * Provide a connection to GPFS specific features + * Copyright (C) Volker Lendecke 2005 + * + * 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" + +#ifdef HAVE_GPFS_SET_SHARE + +#include "gpfs.h" + +static void *libgpfs_handle = NULL; + +static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny); +static int (*gpfs_set_lease_fn)(int fd, unsigned int leaseType); + +BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask, + uint32 share_access) +{ + unsigned int allow = GPFS_SHARE_NONE; + unsigned int deny = GPFS_DENY_NONE; + int result; + + if (gpfs_set_share_fn == NULL) { + return False; + } + + if ((fsp == NULL) || (fsp->fh == NULL) || (fsp->fh->fd < 0)) { + /* No real file, don't disturb */ + return True; + } + + allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA| + DELETE_ACCESS)) ? GPFS_SHARE_WRITE : 0; + allow |= (access_mask & (FILE_READ_DATA|FILE_EXECUTE)) ? + GPFS_SHARE_READ : 0; + deny |= (share_access & (FILE_SHARE_WRITE|FILE_SHARE_DELETE)) ? + 0 : GPFS_DENY_WRITE; + deny |= (share_access & (FILE_SHARE_READ)) ? + 0 : GPFS_DENY_READ; + + DEBUG(10, ("am=%x, allow=%d, sa=%x, deny=%d\n", + access_mask, allow, share_access, deny)); + + result = gpfs_set_share_fn(fsp->fh->fd, allow, deny); + if (result != 0) { + if (errno == ENOSYS) { + DEBUG(5, ("'gpfs share = yes' set, but no gpfs " + "available. Allowing access\n")); + return True; + } else { + DEBUG(10, ("gpfs_set_share failed: %s\n", + strerror(errno))); + } + } + + return (result == 0); +} + +int set_gpfs_lease(int fd, int leasetype) +{ + int gpfs_type = GPFS_LEASE_NONE; + + if (gpfs_set_lease_fn == NULL) { + errno = EINVAL; + return -1; + } + + if (leasetype == F_RDLCK) { + gpfs_type = GPFS_LEASE_READ; + } + if (leasetype == F_WRLCK) { + gpfs_type = GPFS_LEASE_WRITE; + } + return gpfs_set_lease_fn(fd, gpfs_type); +} + +void init_gpfs(void) +{ + if (libgpfs_handle != NULL) { + return; + } + + libgpfs_handle = sys_dlopen("libgpfs.so", RTLD_LAZY); + + if (libgpfs_handle == NULL) { + DEBUG(10, ("sys_dlopen for libgpfs.so failed: %s\n", + strerror(errno))); + return; + } + + DEBUG(10, ("libgpfs.so loaded\n")); + + gpfs_set_share_fn = sys_dlsym(libgpfs_handle, "gpfs_set_share"); + if (gpfs_set_share_fn == NULL) { + DEBUG(3, ("libgpfs.so does not contain the symbol " + "'gpfs_set_share'\n")); + sys_dlclose(libgpfs_handle); + + /* leave libgpfs_handle != NULL around, no point + in trying twice */ + gpfs_set_lease_fn = NULL; + return; + } + + gpfs_set_lease_fn = sys_dlsym(libgpfs_handle, "gpfs_set_lease"); + if (gpfs_set_lease_fn == NULL) { + DEBUG(3, ("libgpfs.so does not contain the symbol " + "'gpfs_set_lease'\n")); + sys_dlclose(libgpfs_handle); + + /* leave libgpfs_handle != NULL around, no point + in trying twice */ + gpfs_set_share_fn = NULL; + return; + } +} + +#else + +int set_gpfs_lease(int snum, int leasetype) +{ + DEBUG(0, ("'gpfs share = yes' set without gpfs support compiled\n")); + + /* We need to indicate that no GPFS is around by returning ENOSYS, so + * that the normal linux kernel oplock code is called. */ + errno = ENOSYS; + return -1; +} + +BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask, + uint32 share_access) +{ + DEBUG(0, ("'gpfs share = yes' set without gpfs support compiled\n")); + /* Don't disturb but complain */ + return True; +} + +void init_gpfs(void) +{ + return; +} + +#endif diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6c749fab9..2f82f04b63 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1599,6 +1599,20 @@ files_struct *open_file_ntcreate(connection_struct *conn, * deny mode is compatible with all current opens. */ + if (lp_gpfs_share(SNUM(fsp->conn)) && + !set_gpfs_sharemode(fsp, access_mask, share_access)) { + + /* GPFS does have share mode support, so the comment above wrt + * NFS being wrong is not correct here. */ + + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); + talloc_free(lck); + fd_close(conn, fsp); + file_free(fsp); + return NULL; + } + /* * If requested, truncate the file. */ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index ab0c08f7fc..0285bfce97 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -101,11 +101,11 @@ static void set_capability(unsigned capability) } /**************************************************************************** - Call SETLEASE. If we get EACCES then we try setting up the right capability and - try again + Call SETLEASE. If we get EACCES then we try setting up the right capability + and try again ****************************************************************************/ -static int linux_setlease(int fd, int leasetype) +static int linux_setlease(int snum, int fd, int leasetype) { int ret; @@ -114,7 +114,17 @@ static int linux_setlease(int fd, int leasetype) return -1; } - ret = fcntl(fd, F_SETLEASE, leasetype); + if (lp_gpfs_share(snum)) { + ret = set_gpfs_lease(fd, leasetype); + } else { + ret = fcntl(fd, F_SETLEASE, leasetype); + } + + if ((ret < 0) && (errno == ENOSYS)) { + /* This must have come from GPFS not being available */ + ret = fcntl(fd, F_SETLEASE, leasetype); + } + if (ret == -1 && errno == EACCES) { set_capability(CAP_LEASE); ret = fcntl(fd, F_SETLEASE, leasetype); @@ -154,7 +164,7 @@ static files_struct *linux_oplock_receive_message(fd_set *fds) static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) { + if (linux_setlease(SNUM(fsp->conn), fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fh->fd, @@ -188,7 +198,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /* * Remove the kernel oplock on this file. */ - if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) { + if (linux_setlease(SNUM(fsp->conn), fsp->fh->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ff894e2460..56c9c72127 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -899,6 +899,8 @@ void build_options(BOOL screen); if (!print_backend_init()) exit(1); + init_gpfs(); + /* Setup the main smbd so that we can get messages. */ /* don't worry about general printing messages here */ -- cgit From 4d1d826be44ec82e3778e89cbd2873e0aacfc134 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 6 Jan 2006 10:27:12 +0000 Subject: r12735: After talking to Tridge and Jeremy... This needs to be made more generic before it goes in. Volker (This used to be commit 2c3d5c029a31111e1fe84ddc13c1bfc183d8bfde) --- source3/smbd/gpfs.c | 159 -------------------------------------------- source3/smbd/open.c | 14 ---- source3/smbd/oplock_linux.c | 22 ++---- source3/smbd/server.c | 2 - 4 files changed, 6 insertions(+), 191 deletions(-) delete mode 100644 source3/smbd/gpfs.c (limited to 'source3/smbd') diff --git a/source3/smbd/gpfs.c b/source3/smbd/gpfs.c deleted file mode 100644 index 4a8b9eea6c..0000000000 --- a/source3/smbd/gpfs.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * Provide a connection to GPFS specific features - * Copyright (C) Volker Lendecke 2005 - * - * 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" - -#ifdef HAVE_GPFS_SET_SHARE - -#include "gpfs.h" - -static void *libgpfs_handle = NULL; - -static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny); -static int (*gpfs_set_lease_fn)(int fd, unsigned int leaseType); - -BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask, - uint32 share_access) -{ - unsigned int allow = GPFS_SHARE_NONE; - unsigned int deny = GPFS_DENY_NONE; - int result; - - if (gpfs_set_share_fn == NULL) { - return False; - } - - if ((fsp == NULL) || (fsp->fh == NULL) || (fsp->fh->fd < 0)) { - /* No real file, don't disturb */ - return True; - } - - allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA| - DELETE_ACCESS)) ? GPFS_SHARE_WRITE : 0; - allow |= (access_mask & (FILE_READ_DATA|FILE_EXECUTE)) ? - GPFS_SHARE_READ : 0; - deny |= (share_access & (FILE_SHARE_WRITE|FILE_SHARE_DELETE)) ? - 0 : GPFS_DENY_WRITE; - deny |= (share_access & (FILE_SHARE_READ)) ? - 0 : GPFS_DENY_READ; - - DEBUG(10, ("am=%x, allow=%d, sa=%x, deny=%d\n", - access_mask, allow, share_access, deny)); - - result = gpfs_set_share_fn(fsp->fh->fd, allow, deny); - if (result != 0) { - if (errno == ENOSYS) { - DEBUG(5, ("'gpfs share = yes' set, but no gpfs " - "available. Allowing access\n")); - return True; - } else { - DEBUG(10, ("gpfs_set_share failed: %s\n", - strerror(errno))); - } - } - - return (result == 0); -} - -int set_gpfs_lease(int fd, int leasetype) -{ - int gpfs_type = GPFS_LEASE_NONE; - - if (gpfs_set_lease_fn == NULL) { - errno = EINVAL; - return -1; - } - - if (leasetype == F_RDLCK) { - gpfs_type = GPFS_LEASE_READ; - } - if (leasetype == F_WRLCK) { - gpfs_type = GPFS_LEASE_WRITE; - } - return gpfs_set_lease_fn(fd, gpfs_type); -} - -void init_gpfs(void) -{ - if (libgpfs_handle != NULL) { - return; - } - - libgpfs_handle = sys_dlopen("libgpfs.so", RTLD_LAZY); - - if (libgpfs_handle == NULL) { - DEBUG(10, ("sys_dlopen for libgpfs.so failed: %s\n", - strerror(errno))); - return; - } - - DEBUG(10, ("libgpfs.so loaded\n")); - - gpfs_set_share_fn = sys_dlsym(libgpfs_handle, "gpfs_set_share"); - if (gpfs_set_share_fn == NULL) { - DEBUG(3, ("libgpfs.so does not contain the symbol " - "'gpfs_set_share'\n")); - sys_dlclose(libgpfs_handle); - - /* leave libgpfs_handle != NULL around, no point - in trying twice */ - gpfs_set_lease_fn = NULL; - return; - } - - gpfs_set_lease_fn = sys_dlsym(libgpfs_handle, "gpfs_set_lease"); - if (gpfs_set_lease_fn == NULL) { - DEBUG(3, ("libgpfs.so does not contain the symbol " - "'gpfs_set_lease'\n")); - sys_dlclose(libgpfs_handle); - - /* leave libgpfs_handle != NULL around, no point - in trying twice */ - gpfs_set_share_fn = NULL; - return; - } -} - -#else - -int set_gpfs_lease(int snum, int leasetype) -{ - DEBUG(0, ("'gpfs share = yes' set without gpfs support compiled\n")); - - /* We need to indicate that no GPFS is around by returning ENOSYS, so - * that the normal linux kernel oplock code is called. */ - errno = ENOSYS; - return -1; -} - -BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask, - uint32 share_access) -{ - DEBUG(0, ("'gpfs share = yes' set without gpfs support compiled\n")); - /* Don't disturb but complain */ - return True; -} - -void init_gpfs(void) -{ - return; -} - -#endif diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2f82f04b63..e6c749fab9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1599,20 +1599,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, * deny mode is compatible with all current opens. */ - if (lp_gpfs_share(SNUM(fsp->conn)) && - !set_gpfs_sharemode(fsp, access_mask, share_access)) { - - /* GPFS does have share mode support, so the comment above wrt - * NFS being wrong is not correct here. */ - - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - talloc_free(lck); - fd_close(conn, fsp); - file_free(fsp); - return NULL; - } - /* * If requested, truncate the file. */ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 0285bfce97..ab0c08f7fc 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -101,11 +101,11 @@ static void set_capability(unsigned capability) } /**************************************************************************** - Call SETLEASE. If we get EACCES then we try setting up the right capability - and try again + Call SETLEASE. If we get EACCES then we try setting up the right capability and + try again ****************************************************************************/ -static int linux_setlease(int snum, int fd, int leasetype) +static int linux_setlease(int fd, int leasetype) { int ret; @@ -114,17 +114,7 @@ static int linux_setlease(int snum, int fd, int leasetype) return -1; } - if (lp_gpfs_share(snum)) { - ret = set_gpfs_lease(fd, leasetype); - } else { - ret = fcntl(fd, F_SETLEASE, leasetype); - } - - if ((ret < 0) && (errno == ENOSYS)) { - /* This must have come from GPFS not being available */ - ret = fcntl(fd, F_SETLEASE, leasetype); - } - + ret = fcntl(fd, F_SETLEASE, leasetype); if (ret == -1 && errno == EACCES) { set_capability(CAP_LEASE); ret = fcntl(fd, F_SETLEASE, leasetype); @@ -164,7 +154,7 @@ static files_struct *linux_oplock_receive_message(fd_set *fds) static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (linux_setlease(SNUM(fsp->conn), fsp->fh->fd, F_WRLCK) == -1) { + if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fh->fd, @@ -198,7 +188,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /* * Remove the kernel oplock on this file. */ - if (linux_setlease(SNUM(fsp->conn), fsp->fh->fd, F_UNLCK) == -1) { + if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 56c9c72127..ff894e2460 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -899,8 +899,6 @@ void build_options(BOOL screen); if (!print_backend_init()) exit(1); - init_gpfs(); - /* Setup the main smbd so that we can get messages. */ /* don't worry about general printing messages here */ -- cgit From 33174847994128387a36a8103f147fe5a96c15fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Jan 2006 22:17:54 +0000 Subject: r12877: Stop passing structs around in smb messages, instead always linearize into little-endian. Should fix all Solaris issues with this, plus provide a cleaner base moving forward for cluster-aware Samba where smbd's can communicate across different compilers/architectures (eventually these message will have to go cross-machine). Jeremy. (This used to be commit d01824b78576a034428e1cef73868d1169057991) --- source3/smbd/close.c | 6 +- source3/smbd/open.c | 22 ++++-- source3/smbd/oplock.c | 188 +++++++++++++++++++++++++++++++++++--------------- source3/smbd/trans2.c | 4 +- 4 files changed, 156 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index f834869935..c0d87b1b21 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -130,9 +130,13 @@ static void notify_deferred_opens(struct share_mode_lock *lck) */ schedule_deferred_open_smb_message(e->op_mid); } else { + char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; + + share_mode_entry_to_message(msg, e); + become_root(); message_send_pid(e->pid, MSG_SMB_OPEN_RETRY, - e, sizeof(*e), True); + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); unbecome_root(); } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6c749fab9..0ccac592d6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -683,12 +683,17 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) if (delay_it) { BOOL ret; + char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; + DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); + + share_mode_entry_to_message(msg, exclusive); + become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - exclusive, sizeof(*exclusive), True); + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); unbecome_root(); if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); @@ -2055,25 +2060,30 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len) { files_struct *fsp; - struct file_renamed_message *frm = (struct file_renamed_message *)buf; + char *frm = (char *)buf; + SMB_DEV_T dev; + SMB_INO_T inode; const char *sharepath; const char *newname; size_t sp_len; - if (buf == NULL || len < sizeof(*frm)) { + if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) { DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); return; } - sharepath = &frm->names[0]; + /* Unpack the message. */ + dev = DEV_T_VAL(frm,0); + inode = INO_T_VAL(frm,8); + sharepath = &frm[16]; newname = sharepath + strlen(sharepath) + 1; sp_len = strlen(sharepath); DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " "dev %x, inode %.0f\n", - sharepath, newname, (unsigned int)frm->dev, (double)frm->inode )); + sharepath, newname, (unsigned int)dev, (double)inode )); - for(fsp = file_find_di_first(frm->dev, frm->inode); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", fsp->fnum, fsp->fsp_name, newname )); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index f788fc9e2e..6739d29470 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -48,8 +48,9 @@ int32 get_number_of_exclusive_open_oplocks(void) BOOL oplock_message_waiting(fd_set *fds) { - if (koplocks && koplocks->msg_waiting(fds)) + if (koplocks && koplocks->msg_waiting(fds)) { return True; + } return False; } @@ -84,7 +85,7 @@ void process_kernel_oplocks(void) while (koplocks->msg_waiting(&fds)) { files_struct *fsp; - struct kernel_oplock_message msg; + char msg[MSG_SMB_KERNEL_BREAK_SIZE]; fsp = koplocks->receive_message(&fds); @@ -94,12 +95,17 @@ void process_kernel_oplocks(void) return; } - msg.dev = fsp->dev; - msg.inode = fsp->inode; - msg.file_id = fsp->file_id; + /* Put the kernel break info into the message. */ + SDEV_T_VAL(msg,0,fsp->dev); + SINO_T_VAL(msg,8,fsp->inode); + SIVAL(msg,16,fsp->file_id); + + /* Don't need to be root here as we're only ever + sending to ourselves. */ + message_send_pid(pid_to_procid(sys_getpid()), MSG_SMB_KERNEL_BREAK, - &msg, sizeof(msg), True); + &msg, MSG_SMB_KERNEL_BREAK_SIZE, True); } } @@ -110,15 +116,17 @@ void process_kernel_oplocks(void) BOOL set_file_oplock(files_struct *fsp, int oplock_type) { - if (koplocks && !koplocks->set_oplock(fsp, oplock_type)) + if (koplocks && !koplocks->set_oplock(fsp, oplock_type)) { return False; + } fsp->oplock_type = oplock_type; fsp->sent_oplock_break = NO_BREAK_SENT; - if (oplock_type == LEVEL_II_OPLOCK) + if (oplock_type == LEVEL_II_OPLOCK) { level_II_oplocks_open++; - else + } else { exclusive_oplocks_open++; + } DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, file_id = %lu, \ tv_sec = %x, tv_usec = %x\n", @@ -140,10 +148,11 @@ void release_file_oplock(files_struct *fsp) koplocks->release_oplock(fsp); } - if (fsp->oplock_type == LEVEL_II_OPLOCK) + if (fsp->oplock_type == LEVEL_II_OPLOCK) { level_II_oplocks_open--; - else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { exclusive_oplocks_open--; + } SMB_ASSERT(exclusive_oplocks_open>=0); SMB_ASSERT(level_II_oplocks_open>=0); @@ -160,8 +169,9 @@ void release_file_oplock(files_struct *fsp) static void downgrade_file_oplock(files_struct *fsp) { - if (koplocks) + if (koplocks) { koplocks->release_oplock(fsp); + } fsp->oplock_type = LEVEL_II_OPLOCK; exclusive_oplocks_open--; level_II_oplocks_open++; @@ -223,7 +233,7 @@ BOOL downgrade_oplock(files_struct *fsp) fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); } - + downgrade_file_oplock(fsp); talloc_free(lck); return ret; @@ -284,8 +294,9 @@ static void wait_before_sending_break(void) struct timeval cur_tv; long wait_left = (long)lp_oplock_break_wait_time(); - if (wait_left == 0) + if (wait_left == 0) { return; + } GetTimeOfDay(&cur_tv); @@ -307,7 +318,7 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un files_struct *fsp = NULL; if( DEBUGLVL( 3 ) ) { - dbgtext( "initial_break_processing: called for dev = %x, inode = %.0f file_id = %lu\n", + dbgtext( "initial_break_processing: called for dev = 0x%x, inode = %.0f file_id = %lu\n", (unsigned int)dev, (double)inode, file_id); dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", exclusive_oplocks_open, level_II_oplocks_open ); @@ -325,7 +336,7 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un /* The file could have been closed in the meantime - return success. */ if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: cannot find open file with " ); - dbgtext( "dev = %x, inode = %.0f file_id = %lu", (unsigned int)dev, + dbgtext( "dev = 0x%x, inode = %.0f file_id = %lu", (unsigned int)dev, (double)inode, file_id); dbgtext( "allowing break to succeed.\n" ); } @@ -370,7 +381,7 @@ static void oplock_timeout_handler(struct timed_event *te, static void process_oplock_break_message(int msg_type, struct process_id src, void *buf, size_t len) { - struct share_mode_entry *msg = buf; + struct share_mode_entry msg; files_struct *fsp; char *break_msg; BOOL break_to_level2 = False; @@ -381,17 +392,20 @@ static void process_oplock_break_message(int msg_type, struct process_id src, return; } - if (len != sizeof(*msg)) { + if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { DEBUG(0, ("Got invalid msg len %d\n", (int)len)); return; } - DEBUG(10, ("Got oplock break message from pid %d: %d/%d/%d\n", - (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, - (int)msg->share_file_id)); + /* De-linearize incoming message. */ + message_to_share_mode_entry(&msg, buf); + + DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%d\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, + (int)msg.share_file_id)); - fsp = initial_break_processing(msg->dev, msg->inode, - msg->share_file_id); + fsp = initial_break_processing(msg.dev, msg.inode, + msg.share_file_id); if (fsp == NULL) { /* We hit race here. Break messages are sent, and before we @@ -399,8 +413,11 @@ static void process_oplock_break_message(int msg_type, struct process_id src, * with 'ok, oplock broken' */ DEBUG(3, ("Did not find fsp\n")); become_root(); + + /* We just send the same message back. */ message_send_pid(src, MSG_SMB_BREAK_RESPONSE, - msg, sizeof(*msg), True); + buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + unbecome_root(); return; } @@ -408,21 +425,24 @@ static void process_oplock_break_message(int msg_type, struct process_id src, if (fsp->sent_oplock_break != NO_BREAK_SENT) { /* Remember we have to inform the requesting PID when the * client replies */ - msg->pid = src; - ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg, + msg.pid = src; + ADD_TO_ARRAY(NULL, struct share_mode_entry, msg, &fsp->pending_break_messages, &fsp->num_pending_break_messages); return; } - if (EXCLUSIVE_OPLOCK_TYPE(msg->op_type) && + if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) && !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(3, ("Already downgraded oplock on %.0f/%.0f: %s\n", - (double)fsp->dev, (double)fsp->inode, + DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n", + (unsigned int)fsp->dev, (double)fsp->inode, fsp->fsp_name)); become_root(); + + /* We just send the same message back. */ message_send_pid(src, MSG_SMB_BREAK_RESPONSE, - msg, sizeof(*msg), True); + buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + unbecome_root(); return; } @@ -466,8 +486,8 @@ static void process_oplock_break_message(int msg_type, struct process_id src, /* Async level2 request, don't send a reply */ fsp->sent_oplock_break = ASYNC_LEVEL_II_BREAK_SENT; } - msg->pid = src; - ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg, + msg.pid = src; + ADD_TO_ARRAY(NULL, struct share_mode_entry, msg, &fsp->pending_break_messages, &fsp->num_pending_break_messages); @@ -490,7 +510,9 @@ static void process_oplock_break_message(int msg_type, struct process_id src, static void process_kernel_oplock_break(int msg_type, struct process_id src, void *buf, size_t len) { - struct kernel_oplock_message *msg = buf; + SMB_DEV_T dev; + SMB_INO_T inode; + unsigned long file_id; files_struct *fsp; char *break_msg; BOOL sign_state; @@ -500,16 +522,21 @@ static void process_kernel_oplock_break(int msg_type, struct process_id src, return; } - if (len != sizeof(*msg)) { + if (len != MSG_SMB_KERNEL_BREAK_SIZE) { DEBUG(0, ("Got invalid msg len %d\n", (int)len)); return; } - DEBUG(10, ("Got kernel oplock break message from pid %d: %d/%d/%d\n", - (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, - (int)msg->file_id)); + /* Pull the data from the message. */ + dev = DEV_T_VAL(buf, 0); + inode = INO_T_VAL(buf, 8); + file_id = (unsigned long)IVAL(buf, 16); - fsp = initial_break_processing(msg->dev, msg->inode, msg->file_id); + DEBUG(10, ("Got kernel oplock break message from pid %d: 0x%x/%.0f/%u\n", + (int)procid_to_pid(&src), (unsigned int)dev, (double)inode, + (unsigned int)file_id)); + + fsp = initial_break_processing(dev, inode, file_id); if (fsp == NULL) { DEBUG(3, ("Got a kernel oplock break message for a file " @@ -551,9 +578,13 @@ void reply_to_oplock_break_requests(files_struct *fsp) become_root(); for (i=0; inum_pending_break_messages; i++) { - struct share_mode_entry *msg = &fsp->pending_break_messages[i]; - message_send_pid(msg->pid, MSG_SMB_BREAK_RESPONSE, - msg, sizeof(*msg), True); + struct share_mode_entry *e = &fsp->pending_break_messages[i]; + char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; + + share_mode_entry_to_message(msg, e); + + message_send_pid(e->pid, MSG_SMB_BREAK_RESPONSE, + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); } unbecome_root(); @@ -569,46 +600,52 @@ void reply_to_oplock_break_requests(files_struct *fsp) static void process_oplock_break_response(int msg_type, struct process_id src, void *buf, size_t len) { - struct share_mode_entry *msg = buf; + struct share_mode_entry msg; if (buf == NULL) { DEBUG(0, ("Got NULL buffer\n")); return; } - if (len != sizeof(*msg)) { - DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { + DEBUG(0, ("Got invalid msg len %u\n", (unsigned int)len)); return; } - DEBUG(10, ("Got oplock break response from pid %d: %d/%d/%d mid %d\n", - (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, - (int)msg->share_file_id, (int)msg->op_mid)); + /* De-linearize incoming message. */ + message_to_share_mode_entry(&msg, buf); + + DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%u mid %u\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, + (unsigned int)msg.share_file_id, (unsigned int)msg.op_mid)); /* Here's the hack from open.c, store the mid in the 'port' field */ - schedule_deferred_open_smb_message(msg->op_mid); + schedule_deferred_open_smb_message(msg.op_mid); } static void process_open_retry_message(int msg_type, struct process_id src, void *buf, size_t len) { - struct share_mode_entry *msg = buf; + struct share_mode_entry msg; if (buf == NULL) { DEBUG(0, ("Got NULL buffer\n")); return; } - if (len != sizeof(*msg)) { + if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { DEBUG(0, ("Got invalid msg len %d\n", (int)len)); return; } - DEBUG(10, ("Got open retry msg from pid %d: %d/%d mid %d\n", - (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, - (int)msg->op_mid)); + /* De-linearize incoming message. */ + message_to_share_mode_entry(&msg, buf); - schedule_deferred_open_smb_message(msg->op_mid); + DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f mid %u\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, + (unsigned int)msg.op_mid)); + + schedule_deferred_open_smb_message(msg.op_mid); } /**************************************************************************** @@ -662,6 +699,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) for(i = 0; i < lck->num_share_modes; i++) { struct share_mode_entry *share_entry = &lck->share_modes[i]; + char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; /* * As there could have been multiple writes waiting at the @@ -692,9 +730,11 @@ void release_level_2_oplocks_on_change(files_struct *fsp) abort(); } + share_mode_entry_to_message(msg, share_entry); + become_root(); message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK, - share_entry, sizeof(*share_entry), True); + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); unbecome_root(); } @@ -702,6 +742,44 @@ void release_level_2_oplocks_on_change(files_struct *fsp) talloc_free(lck); } +/**************************************************************************** + Linearize a share mode entry struct to an internal oplock break message. +****************************************************************************/ + +void share_mode_entry_to_message(char *msg, struct share_mode_entry *e) +{ + SIVAL(msg,0,(uint32)e->pid.pid); + SSVAL(msg,4,e->op_mid); + SSVAL(msg,6,e->op_type); + SIVAL(msg,8,e->access_mask); + SIVAL(msg,12,e->share_access); + SIVAL(msg,16,e->private_options); + SIVAL(msg,20,(uint32)e->time.tv_sec); + SIVAL(msg,24,(uint32)e->time.tv_usec); + SDEV_T_VAL(msg,28,e->dev); + SINO_T_VAL(msg,36,e->inode); + SIVAL(msg,44,e->share_file_id); +} + +/**************************************************************************** + De-linearize an internal oplock break message to a share mode entry struct. +****************************************************************************/ + +void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) +{ + e->pid.pid = (pid_t)IVAL(msg,0); + e->op_mid = SVAL(msg,4); + e->op_type = SVAL(msg,6); + e->access_mask = IVAL(msg,8); + e->share_access = IVAL(msg,12); + e->private_options = IVAL(msg,16); + e->time.tv_sec = (time_t)IVAL(msg,20); + e->time.tv_usec = (int)IVAL(msg,24); + e->dev = DEV_T_VAL(msg,28); + e->inode = INO_T_VAL(msg,36); + e->share_file_id = (unsigned long)IVAL(msg,44); +} + /**************************************************************************** Setup oplocks for this process. ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 191ccdcf8b..8ff219b468 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1536,7 +1536,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,4,0); p+= 8; - SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ + SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ p+= 8; SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */ @@ -3353,7 +3353,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SIVAL(pdata,4,0); pdata += 8; - SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ + SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ pdata += 8; SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */ -- cgit From d86ebaf198f54b0dc18ea607d0ee9803fcbc4f0f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Jan 2006 02:54:46 +0000 Subject: r12885: Oops. Missed last part of correct patch for #3348. Caught by Samba4 oplock torture tester. Jeremy. (This used to be commit c2476b2f75f6521700107a46028f54110083aa52) --- source3/smbd/posix_acls.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f49f80f006..e485dc1eb1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4157,7 +4157,6 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) if (current_user.uid != sbuf_file.st_uid) { return False; } - return False; } #endif -- cgit From 005c88054f526d9a14d748b665cd6b4853e60a35 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 13 Jan 2006 21:22:25 +0000 Subject: r12916: use rpcstr_pull() instead of unistr_to_ascii() when validating share names (This used to be commit c08bc30698eac2f3f5dd8257b4fd7c3e23e6de39) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 458eb3a2c8..9db3d97ab2 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -190,7 +190,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) /**************************************************************************** Become the user of a connection number without changing the security context - stack, but modify the currnet_user entries. + stack, but modify the current_user entries. ****************************************************************************/ BOOL change_to_user(connection_struct *conn, uint16 vuid) -- cgit From bfc2bf8178097425cba2cdf2afe2c7a835c46057 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 14 Jan 2006 20:25:51 +0000 Subject: r12938: Fix for #3408 (change password fails) from William Jojo . Jeremy. (This used to be commit 5fc0ef80876a666c285585f8b55e1909e8f2e0bf) --- source3/smbd/chgpasswd.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fed73db043..5a179dbf47 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -153,9 +153,13 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, DEBUG(3, ("More weirdness, could not open %s\n", slavedev)); return (False); } -#ifdef I_PUSH - ioctl(slave, I_PUSH, "ptem"); - ioctl(slave, I_PUSH, "ldterm"); +#if defined(I_PUSH) && defined(I_FIND) + if (ioctl(slave, I_FIND, "ptem") == 0) { + ioctl(slave, I_PUSH, "ptem"); + } + if (ioctl(slave, I_FIND, "ldterm") == 0) { + ioctl(slave, I_PUSH, "ldterm"); + } #elif defined(TIOCSCTTY) if (ioctl(slave, TIOCSCTTY, 0) < 0) { -- cgit From 2dd7fd8f69ea06ad234c3354493052ef5a147c03 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Jan 2006 05:47:39 +0000 Subject: r12956: Fix for bug #3035 from SATOH Fumiyasu On a Windows share, a file with read-only dosmode can be opened with DELETE_ACCESS. But on a Samba share (delete readonly = no), it fails with NT_STATUS_CANNOT_DELETE error. This semantic causes a problem that a user can not rename a file with read-only dosmode on a Samba share from a Windows command prompt (i.e. cmd.exe, but can rename from Windows Explorer). Jeremy. (This used to be commit dd185c7aa8de156dab58b065bf73905b2a29f40d) --- source3/smbd/reply.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d56e3c1f1c..69c71c74b5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1888,7 +1888,19 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b return NT_STATUS_OBJECT_NAME_INVALID; #endif /* JRATEST */ - if (!lp_delete_readonly(SNUM(conn))) { + /* Fix for bug #3035 from SATOH Fumiyasu + + On a Windows share, a file with read-only dosmode can be opened with + DELETE_ACCESS. But on a Samba share (delete readonly = no), it + fails with NT_STATUS_CANNOT_DELETE error. + + This semantic causes a problem that a user can not + rename a file with read-only dosmode on a Samba share + from a Windows command prompt (i.e. cmd.exe, but can rename + from Windows Explorer). + */ + + if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) { if (fattr & aRONLY) { return NT_STATUS_CANNOT_DELETE; } -- cgit From 9ed512777647b1706d961e4e141e8794bad4d284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Jan 2006 23:42:29 +0000 Subject: r13023: Ensure we notice if we exit due to guest user setup fail. Jeremy. (This used to be commit f8d09d111ccd8c2805245662e01cd99dba1d9292) --- source3/smbd/server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ff894e2460..620bf3ebbd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -826,8 +826,10 @@ void build_options(BOOL screen); init_structs(); - if (!init_guest_info()) + if (!init_guest_info()) { + DEBUG(0,("ERROR: failed to setup guest info.\n")); return -1; + } #ifdef WITH_PROFILE if (!profile_setup(False)) { -- cgit From 543ff192b37feff91fd77c336177cb628bd1e08a Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 19 Jan 2006 00:30:16 +0000 Subject: r13027: Support file change notifications from FAM. (This used to be commit 652b511ff24ce41c7745a0e00363e619e5027828) --- source3/smbd/notify.c | 8 +- source3/smbd/notify_fam.c | 446 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 453 insertions(+), 1 deletion(-) create mode 100644 source3/smbd/notify_fam.c (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index bc76cfb322..df3d45d20b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -212,9 +212,15 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, BOOL init_change_notify(void) { + cnotify = NULL; + #if HAVE_KERNEL_CHANGE_NOTIFY - if (lp_kernel_change_notify()) + if (cnotify == NULL && lp_kernel_change_notify()) cnotify = kernel_notify_init(); +#endif +#if HAVE_FAM_CHANGE_NOTIFY + if (cnotify == NULL && lp_fam_change_notify()) + cnotify = fam_notify_init(); #endif if (!cnotify) cnotify = hash_notify_init(); diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c new file mode 100644 index 0000000000..413340266e --- /dev/null +++ b/source3/smbd/notify_fam.c @@ -0,0 +1,446 @@ +/* + * FAM file notification support. + * + * Copyright (c) James Peach 2005 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "includes.h" + +#ifdef HAVE_FAM_CHANGE_NOTIFY + +#include + +/* NOTE: There are multiple versions of FAM floating around the net, each with + * slight differences from the original SGI FAM implementation. In this file, + * we rely only on the SGI features and do not assume any extensions. For + * example, we do not look at FAMErrno, because it is not set by the original + * implementation. + * + * Random FAM links: + * http://oss.sgi.com/projects/fam/ + * http://savannah.nongnu.org/projects/fam/ + * http://sourceforge.net/projects/bsdfam/ + */ + +struct fam_req_info +{ + FAMRequest req; + int generation; + enum FAMCodes code; + enum + { + /* We are waiting for an event. */ + FAM_REQ_MONITORING, + /* An event has been receive, but we haven't been able to send it back + * to the client yet. It is stashed in the code member. + */ + FAM_REQ_FIRED + } state; +}; + +/* Don't initialise this until the first register request. We want a single + * FAM connection for each worker smbd. If we allow the master (parent) smbd to + * open a FAM connection, multiple processes talking on the same socket will + * undoubtedly create havoc. + */ +static FAMConnection global_fc; +static int global_fc_generation; + +#define FAM_TRACE 8 +#define FAM_TRACE_LOW 10 + +#define FAM_NOTIFY_CHECK_TIMEOUT 1 /* secs */ +#define FAM_EVENT_DRAIN ((uint32_t)(-1)) + +/* Turn a FAM event code into a string. Don't rely on specific code values, + * because that might not work across all flavours of FAM. + */ +static const char * +fam_event_str(enum FAMCodes code) +{ + static struct { enum FAMCodes code; const char * name; } evstr[] = + { + { FAMChanged, "FAMChanged"}, + { FAMDeleted, "FAMDeleted"}, + { FAMStartExecuting, "FAMStartExecuting"}, + { FAMStopExecuting, "FAMStopExecuting"}, + { FAMCreated, "FAMCreated"}, + { FAMMoved, "FAMMoved"}, + { FAMAcknowledge, "FAMAcknowledge"}, + { FAMExists, "FAMExists"}, + { FAMEndExist, "FAMEndExist"} + }; + + int i; + + for (i = 0; i < ARRAY_SIZE(evstr); ++i) { + if (code == evstr[i].code) + return(evstr[i].name); + } + + return(""); +} + +static BOOL +fam_check_reconnect(void) +{ + if (FAMCONNECTION_GETFD(&global_fc) < 0) { + fstring name; + + global_fc_generation++; + snprintf(name, sizeof(name), "smbd (%lu)", (unsigned long)sys_getpid()); + + if (FAMOpen2(&global_fc, name) < 0) { + DEBUG(0, ("failed to connect to FAM service\n")); + return(False); + } + } + + return(True); +} + +static BOOL +fam_monitor_path(connection_struct * conn, + struct fam_req_info * info, + const char * path, + uint32 flags) +{ + SMB_STRUCT_STAT st; + pstring fullpath; + + DEBUG(FAM_TRACE, ("requesting FAM notifications for '%s'\n", path)); + + /* FAM needs an absolute pathname. */ + + /* It would be better to use reduce_name() here, but reduce_name does not + * actually return the reduced result. How utterly un-useful. + */ + pstrcpy(fullpath, path); + if (!canonicalize_path(conn, fullpath)) { + DEBUG(0, ("failed to canonicalize path '%s'\n", path)); + return(False); + } + + if (*fullpath != '/') { + DEBUG(0, ("canonicalized path '%s' into `%s`\n", path, fullpath)); + DEBUGADD(0, ("but expected an absolute path\n")); + return(False); + } + + if (SMB_VFS_STAT(conn, path, &st) < 0) { + DEBUG(0, ("stat of '%s' failed: %s\n", path, strerror(errno))); + return(False); + } + /* Start monitoring this file or directory. We hand the state structure to + * both the caller and the FAM library so we can match up the caller's + * status requests with FAM notifications. + */ + if (S_ISDIR(st.st_mode)) { + FAMMonitorDirectory(&global_fc, fullpath, &(info->req), info); + } else { + FAMMonitorFile(&global_fc, fullpath, &(info->req), info); + } + + /* Grr. On IRIX, neither of the monitor functions return a status. */ + + /* We will stay in initialising state until we see the FAMendExist message + * for this file. + */ + info->state = FAM_REQ_MONITORING; + info->generation = global_fc_generation; + return(True); +} + +static BOOL +fam_handle_event(enum FAMCodes code, uint32 flags) +{ +#define F_CHANGE_MASK (FILE_NOTIFY_CHANGE_FILE | \ + FILE_NOTIFY_CHANGE_ATTRIBUTES | \ + FILE_NOTIFY_CHANGE_SIZE | \ + FILE_NOTIFY_CHANGE_LAST_WRITE | \ + FILE_NOTIFY_CHANGE_LAST_ACCESS | \ + FILE_NOTIFY_CHANGE_CREATION | \ + FILE_NOTIFY_CHANGE_EA | \ + FILE_NOTIFY_CHANGE_SECURITY) + +#define F_DELETE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \ + FILE_NOTIFY_CHANGE_DIR_NAME) + +#define F_CREATE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \ + FILE_NOTIFY_CHANGE_DIR_NAME) + + switch (code) { + case FAMChanged: + if (flags & F_CHANGE_MASK) + return(True); + break; + case FAMDeleted: + if (flags & F_DELETE_MASK) + return(True); + break; + case FAMCreated: + if (flags & F_CREATE_MASK) + return(True); + break; + default: + /* Ignore anything else. */ + break; + } + + return(False); + +#undef F_CHANGE_MASK +#undef F_DELETE_MASK +#undef F_CREATE_MASK +} + +static BOOL +fam_pump_events(struct fam_req_info * info, uint32_t flags) +{ + FAMEvent ev; + + for (;;) { + + /* If we are draining the event queue we must keep going until we find + * the correct FAMAcknowledge event or the connection drops. Otherwise + * we should stop when there are no more events pending. + */ + if (flags != FAM_EVENT_DRAIN && !FAMPending(&global_fc)) { + break; + } + + if (FAMNextEvent(&global_fc, &ev) < 0) { + DEBUG(0, ("failed to fetch pending FAM event\n")); + DEBUGADD(0, ("resetting FAM connection\n")); + FAMClose(&global_fc); + FAMCONNECTION_GETFD(&global_fc) = -1; + return(False); + } + + DEBUG(FAM_TRACE_LOW, ("FAM event %s on '%s' for request %d\n", + fam_event_str(ev.code), ev.filename, ev.fr.reqnum)); + + switch (ev.code) { + case FAMAcknowledge: + /* FAM generates an ACK event when we cancel a monitor. We need + * this to know when it is safe to free out request state + * structure. + */ + if (info->generation == global_fc_generation && + info->req.reqnum == ev.fr.reqnum && + flags == FAM_EVENT_DRAIN) { + return(True); + } + + case FAMEndExist: + case FAMExists: + /* Ignore these. FAM sends these enumeration events when we + * start monitoring. If we are monitoring a directory, we will + * get a FAMExists event for each directory entry. + */ + + /* TODO: we might be able to use these to implement recursive + * monitoring of entire subtrees. + */ + case FAMMoved: + /* These events never happen. A move or rename shows up as a + * create/delete pair. + */ + case FAMStartExecuting: + case FAMStopExecuting: + /* We might get these, but we just don't care. */ + break; + + case FAMChanged: + case FAMDeleted: + case FAMCreated: + if (info->generation != global_fc_generation) { + /* Ignore this; the req number can't be matched. */ + break; + } + + if (info->req.reqnum == ev.fr.reqnum) { + /* This is the event the caller was interested in. */ + DEBUG(FAM_TRACE, ("handling FAM %s event on '%s'\n", + fam_event_str(ev.code), ev.filename)); + /* Ignore events if we are draining this request. */ + if (flags != FAM_EVENT_DRAIN) { + return(fam_handle_event(ev.code, flags)); + } + break; + } else { + /* Caller doesn't want this event. Stash the result so we + * can come back to it. Unfortunately, FAM doesn't + * guarantee to give us back evinfo. + */ + struct fam_req_info * evinfo = + (struct fam_req_info *)ev.userdata; + + if (evinfo) { + DEBUG(FAM_TRACE, ("storing FAM %s event for winter\n", + fam_event_str(ev.code))); + evinfo->state = FAM_REQ_FIRED; + evinfo->code = ev.code; + } else { + DEBUG(2, ("received FAM %s notification for %s, " + "but userdata was unexpectedly NULL\n", + fam_event_str(ev.code), ev.filename)); + } + break; + } + + default: + DEBUG(0, ("ignoring unknown FAM event code %d for `%s`\n", + ev.code, ev.filename)); + } + } + + /* No more notifications pending. */ + return(False); +} + +static BOOL +fam_test_connection(void) +{ + FAMConnection fc; + + /* On IRIX FAMOpen2 leaks 960 bytes in 48 blocks. It's a deliberate leak + * in the library and there's nothing we can do about it here. + */ + if (FAMOpen2(&fc, "smbd probe") < 0) + return(False); + + FAMClose(&fc); + return(True); +} + +/* ------------------------------------------------------------------------- */ + +static void * +fam_register_notify(connection_struct * conn, + char * path, + uint32 flags) +{ + struct fam_req_info * info; + + if (!fam_check_reconnect()) { + return(False); + } + + if ((info = SMB_MALLOC_P(struct fam_req_info)) == NULL) { + DEBUG(0, ("malloc of %d bytes failed\n", sizeof(struct fam_req_info))); + return(NULL); + } + + if (fam_monitor_path(conn, info, path, flags)) { + return(info); + } else { + SAFE_FREE(info); + return(NULL); + } +} + +static BOOL +fam_check_notify(connection_struct * conn, + uint16_t vuid, + char * path, + uint32_t flags, + void * data, + time_t when) +{ + struct fam_req_info * info; + + info = (struct fam_req_info *)data; + SMB_ASSERT(info != NULL); + + DEBUG(10, ("checking FAM events for `%s`\n", path)); + + if (info->state == FAM_REQ_FIRED) { + DEBUG(FAM_TRACE, ("handling previously fired FAM %s event\n", + fam_event_str(info->code))); + info->state = FAM_REQ_MONITORING; + return(fam_handle_event(info->code, flags)); + } + + if (!fam_check_reconnect()) { + return(False); + } + + if (info->generation != global_fc_generation) { + DEBUG(FAM_TRACE, ("reapplying stale FAM monitor to %s\n", path)); + fam_monitor_path(conn, info, path, flags); + return(False); + } + + return(fam_pump_events(info, flags)); +} + +static void +fam_remove_notify(void * data) +{ + struct fam_req_info * info; + + if ((info = (struct fam_req_info *)data) == NULL) + return; + + /* No need to reconnect. If the FAM connection is gone, there's no need to + * cancel and we can safely let FAMCancelMonitor fail. If it we + * reconnected, then the generation check will stop us cancelling the wrong + * request. + */ + + if (info->generation == global_fc_generation) { + DEBUG(FAM_TRACE, ("removing FAM notification for request %d\n", + info->req.reqnum)); + FAMCancelMonitor(&global_fc, &(info->req)); + + /* Soak up all events until the FAMAcknowledge. We can't free + * our request state until we are sure there are no more events in + * flight. + */ + fam_pump_events(info, FAM_EVENT_DRAIN); + } + + SAFE_FREE(info); +} + +struct cnotify_fns * fam_notify_init(void) +{ + static struct cnotify_fns global_fam_notify = + { + fam_register_notify, + fam_check_notify, + fam_remove_notify, + FAM_NOTIFY_CHECK_TIMEOUT + }; + + /* TODO: rather than relying on FAM_NOTIFY_CHECK_TIMEOUT, we should have an + * API to push the FAM fd into the global server fd set. + */ + + FAMCONNECTION_GETFD(&global_fc) = -1; + + if (!fam_test_connection()) { + DEBUG(0, ("FAM file change notifications not available\n")); + return(NULL); + } + + DEBUG(FAM_TRACE, ("enabling FAM change notifications\n")); + return &global_fam_notify; +} + +#endif /* HAVE_FAM_CHANGE_NOTIFY */ -- cgit From b3109006c5b273e5960d71b25787f23bf62ec17f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Jan 2006 23:19:31 +0000 Subject: r13095: Fix warnings assigning int to a size_t. Jeremy. (This used to be commit 1ca4abffd04bcc46b61acdc12444f3e2aad0afed) --- source3/smbd/service.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index fb9dbf0489..7640559d53 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -592,6 +592,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } if (conn->force_user || conn->force_group) { + int ngroups = 0; /* groups stuff added by ih */ conn->ngroups = 0; @@ -600,7 +601,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Find all the groups this uid is in and store them. Used by change_to_user() */ initialise_groups(conn->user, conn->uid, conn->gid); - get_current_groups(conn->gid, &conn->ngroups,&conn->groups); + get_current_groups(conn->gid, &ngroups, &conn->groups); + conn->ngroups = ngroups; conn->nt_user_token = create_nt_token(conn->uid, conn->gid, -- cgit From c4307da13b98190b4185f7894d27686eca800af8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Jan 2006 05:04:08 +0000 Subject: r13125: Very well spotted crash bug fix for #3343 from SATOH Fumiyasu Jerry please pick this up for 3.0.21b. Jeremy. (This used to be commit 3f5860b8fb37e854ccf5d9a80848ef759154f88c) --- source3/smbd/posix_acls.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index e485dc1eb1..34497f0280 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1447,7 +1447,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - SAFE_FREE(current_ace); return False; } @@ -1506,7 +1505,6 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - SAFE_FREE(current_ace); return False; } -- cgit From 6a097ab20ea54a7b090ad6e62c1538d5e5997f31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Jan 2006 19:54:39 +0000 Subject: r13192: Fix up alignment issues when printing share mode entries. Add paranioa to debug so we know when an entry is unused. Jeremy. (This used to be commit fa5fab313e3728ff49c00ca1097242039506f83e) --- source3/smbd/oplock.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 6739d29470..234b62e8ae 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -684,6 +684,11 @@ void release_level_2_oplocks_on_change(files_struct *fsp) don't have to do anything */ for (i=0; inum_share_modes; i++) { struct share_mode_entry *e = &lck->share_modes[i]; + + if (!is_valid_share_mode_entry(e)) { + continue; + } + if ((e->op_type == NO_OPLOCK) && (e->share_file_id == fsp->file_id) && (e->dev == fsp->dev) && @@ -701,6 +706,10 @@ void release_level_2_oplocks_on_change(files_struct *fsp) struct share_mode_entry *share_entry = &lck->share_modes[i]; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; + if (!is_valid_share_mode_entry(share_entry)) { + continue; + } + /* * As there could have been multiple writes waiting at the * lock_share_entry gate we may not be the first to -- cgit From bd34c2ac25af690a00cbbded5b57a834a4e35875 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Jan 2006 23:30:30 +0000 Subject: r13198: Fix issues exposed by Jerry's testing on 64-bit Solaris (I hope). Separate 3.0.21b patch sent to Jerry. Jeremy. (This used to be commit 837e7ea7e40cedc6b01e023445feb4a90c4bf8b9) --- source3/smbd/oplock.c | 193 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 138 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 234b62e8ae..86f5e1a47c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -372,12 +372,129 @@ static void oplock_timeout_handler(struct timed_event *te, { files_struct *fsp = private_data; - DEBUG(0, ("Oplock break failed -- replying anyway\n")); + DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name)); global_client_failed_oplock_break = True; remove_oplock(fsp); reply_to_oplock_break_requests(fsp); } +/******************************************************************* + Add a timeout handler waiting for the client reply. +*******************************************************************/ + +static void add_oplock_timeout_handler(files_struct *fsp) +{ + if (fsp->oplock_timeout != NULL) { + DEBUG(0, ("Logic problem -- have an oplock event hanging " + "around\n")); + } + + fsp->oplock_timeout = + add_timed_event(NULL, + timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), + "oplock_timeout_handler", + oplock_timeout_handler, fsp); + + if (fsp->oplock_timeout == NULL) { + DEBUG(0, ("Could not add oplock timeout handler\n")); + } +} + +/******************************************************************* + This handles the case of a write triggering a break to none + message on a level2 oplock. + When we get this message we may be in any of three states : + NO_OPLOCK, LEVEL_II, FAKE_LEVEL2. We only send a message to + the client for LEVEL2. +*******************************************************************/ + +static void process_oplock_async_level2_break_message(int msg_type, struct process_id src, + void *buf, size_t len) +{ + struct share_mode_entry msg; + files_struct *fsp; + char *break_msg; + BOOL break_to_level2 = False; + BOOL sign_state; + + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; + } + + if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; + } + + /* De-linearize incoming message. */ + message_to_share_mode_entry(&msg, buf); + + DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%d\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, + (int)msg.share_file_id)); + + fsp = initial_break_processing(msg.dev, msg.inode, + msg.share_file_id); + + if (fsp == NULL) { + /* We hit a race here. Break messages are sent, and before we + * get to process this message, we have closed the file. + * No need to reply as this is an async message. */ + DEBUG(3, ("process_oplock_async_level2_break_message: Did not find fsp, ignoring\n")); + return; + } + + if (fsp->oplock_type == NO_OPLOCK) { + /* We already got a "break to none" message and we've handled it. + * just ignore. */ + DEBUG(3, ("process_oplock_async_level2_break_message: already broken to none, ignoring.\n")); + return; + } + + if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) { + /* Don't tell the client, just downgrade. */ + DEBUG(3, ("process_oplock_async_level2_break_message: downgrading fake level 2 oplock.\n")); + remove_oplock(fsp); + return; + } + + /* Ensure we're really at level2 state. */ + SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK); + + /* Now send a break to none message to our client. */ + + break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); + if (break_msg == NULL) { + exit_server("Could not talloc break_msg\n"); + } + + /* Need to wait before sending a break message if we sent ourselves this message. */ + if (procid_to_pid(&src) == sys_getpid()) { + wait_before_sending_break(); + } + + /* Save the server smb signing state. */ + sign_state = srv_oplock_set_signing(False); + + show_msg(break_msg); + if (!send_smb(smbd_server_fd(), break_msg)) { + exit_server("oplock_break: send_smb failed."); + } + + /* Restore the sign state to what it was. */ + srv_oplock_set_signing(sign_state); + + talloc_free(break_msg); + + /* Async level2 request, don't send a reply, just remove the oplock. */ + remove_oplock(fsp); +} + +/******************************************************************* + This handles the generic oplock break message from another smbd. +*******************************************************************/ + static void process_oplock_break_message(int msg_type, struct process_id src, void *buf, size_t len) { @@ -408,7 +525,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, msg.share_file_id); if (fsp == NULL) { - /* We hit race here. Break messages are sent, and before we + /* a We hit race here. Break messages are sent, and before we * get to process this message, we have closed the file. Reply * with 'ok, oplock broken' */ DEBUG(3, ("Did not find fsp\n")); @@ -447,8 +564,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, return; } - if ((msg_type == MSG_SMB_BREAK_REQUEST) && - (global_client_caps & CAP_LEVEL_II_OPLOCKS) && + if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && !koplocks && /* NOTE: we force levelII off for kernel oplocks - * this will change when it is supported */ lp_level2_oplocks(SNUM(fsp->conn))) { @@ -461,7 +577,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, exit_server("Could not talloc break_msg\n"); } - /* Need to wait before sending a break message to a file of our own */ + /* Need to wait before sending a break message if we sent ourselves this message. */ if (procid_to_pid(&src) == sys_getpid()) { wait_before_sending_break(); } @@ -479,34 +595,20 @@ static void process_oplock_break_message(int msg_type, struct process_id src, talloc_free(break_msg); - if (msg_type == MSG_SMB_BREAK_REQUEST) { - fsp->sent_oplock_break = break_to_level2 ? - LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; - } else { - /* Async level2 request, don't send a reply */ - fsp->sent_oplock_break = ASYNC_LEVEL_II_BREAK_SENT; - } + fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; + msg.pid = src; ADD_TO_ARRAY(NULL, struct share_mode_entry, msg, &fsp->pending_break_messages, &fsp->num_pending_break_messages); - if (fsp->oplock_timeout != NULL) { - DEBUG(0, ("Logic problem -- have an oplock event hanging " - "around\n")); - } - - fsp->oplock_timeout = - add_timed_event(NULL, - timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), - "oplock_timeout_handler", - oplock_timeout_handler, fsp); - - if (fsp->oplock_timeout == NULL) { - DEBUG(0, ("Could not add oplock timeout handler\n")); - } + add_oplock_timeout_handler(fsp); } +/******************************************************************* + This handles the kernel oplock break message. +*******************************************************************/ + static void process_kernel_oplock_break(int msg_type, struct process_id src, void *buf, size_t len) { @@ -570,6 +672,8 @@ static void process_kernel_oplock_break(int msg_type, struct process_id src, talloc_free(break_msg); fsp->sent_oplock_break = BREAK_TO_NONE_SENT; + + add_oplock_timeout_handler(fsp); } void reply_to_oplock_break_requests(files_struct *fsp) @@ -591,6 +695,7 @@ void reply_to_oplock_break_requests(files_struct *fsp) SAFE_FREE(fsp->pending_break_messages); fsp->num_pending_break_messages = 0; if (fsp->oplock_timeout != NULL) { + /* Remove the timed event handler. */ talloc_free(fsp->oplock_timeout); fsp->oplock_timeout = NULL; } @@ -679,29 +784,6 @@ void release_level_2_oplocks_on_change(files_struct *fsp) DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", lck->num_share_modes )); - if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) { - /* See if someone else has already downgraded us, then we - don't have to do anything */ - for (i=0; inum_share_modes; i++) { - struct share_mode_entry *e = &lck->share_modes[i]; - - if (!is_valid_share_mode_entry(e)) { - continue; - } - - if ((e->op_type == NO_OPLOCK) && - (e->share_file_id == fsp->file_id) && - (e->dev == fsp->dev) && - (e->inode == fsp->inode) && - (procid_is_me(&e->pid))) { - /* We're done */ - fsp->oplock_type = NO_OPLOCK; - talloc_free(lck); - return; - } - } - } - for(i = 0; i < lck->num_share_modes; i++) { struct share_mode_entry *share_entry = &lck->share_modes[i]; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; @@ -714,7 +796,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) * As there could have been multiple writes waiting at the * lock_share_entry gate we may not be the first to * enter. Hence the state of the op_types in the share mode - * entries may be partly NO_OPLOCK and partly LEVEL_II + * entries may be partly NO_OPLOCK and partly LEVEL_II or FAKE_LEVEL_II * oplock. It will do no harm to re-send break messages to * those smbd's that are still waiting their turn to remove * their LEVEL_II state, and also no harm to ignore existing @@ -725,8 +807,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) "share_entry[%i]->op_type == %d\n", i, share_entry->op_type )); - if ((share_entry->op_type == NO_OPLOCK) || - (share_entry->op_type == FAKE_LEVEL_II_OPLOCK)) { + if (share_entry->op_type == NO_OPLOCK) { continue; } @@ -747,7 +828,9 @@ void release_level_2_oplocks_on_change(files_struct *fsp) unbecome_root(); } - remove_all_share_oplocks(lck, fsp); + /* We let the message receivers handle removing the oplock state + in the share mode lock db. */ + talloc_free(lck); } @@ -795,12 +878,12 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) BOOL init_oplocks(void) { - DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); + DEBUG(3,("open_oplock_ipc: initializing messages.\n")); message_register(MSG_SMB_BREAK_REQUEST, process_oplock_break_message); message_register(MSG_SMB_ASYNC_LEVEL2_BREAK, - process_oplock_break_message); + process_oplock_async_level2_break_message); message_register(MSG_SMB_BREAK_RESPONSE, process_oplock_break_response); message_register(MSG_SMB_KERNEL_BREAK, -- cgit From 9c15bd311db76885b27f30ba92d885833f668550 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 28 Jan 2006 22:53:04 +0000 Subject: r13212: r12414@cabra: derrell | 2006-01-28 17:52:17 -0500 lp_load() could not be called multiple times to modify parameter settings based on reading from multiple configuration settings. Each time, it initialized all of the settings back to their defaults before reading the specified configuration file. This patch adds a parameter to lp_load() specifying whether the settings should be initialized. It does, however, still force the settings to be initialized the first time, even if the request was to not initialize them. (Not doing so could wreak havoc due to uninitialized values.) (This used to be commit f2a24de769d1b2266e576597c57a8e3b1e2a2b51) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 620bf3ebbd..3e970ec16c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -529,7 +529,7 @@ BOOL reload_services(BOOL test) lp_killunused(conn_snum_used); - ret = lp_load(dyn_CONFIGFILE, False, False, True); + ret = lp_load(dyn_CONFIGFILE, False, False, True, True); reload_printers(); -- cgit From d75dc6fa200c59372a0a63c7d1589a5b083548cd Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 30 Jan 2006 18:38:18 +0000 Subject: r13233: build fixes for smbmnt; remove unused variable; ready to ship 3.0.21b now (This used to be commit 51fe6bd845f33139654f641947cffeaaf8e88124) --- source3/smbd/oplock.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 86f5e1a47c..755bcffc7f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -414,7 +414,6 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce struct share_mode_entry msg; files_struct *fsp; char *break_msg; - BOOL break_to_level2 = False; BOOL sign_state; if (buf == NULL) { -- cgit From 86c9bac4c31df1606e3758ec42672506dde26cc6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Feb 2006 04:14:07 +0000 Subject: r13274: Fix for bug #3467. Not a show stopper. jason qian was a *fantastic* help in tracking this down. Jeremy. (This used to be commit 9f4a9c70fa232047868e5d8a3f132a2dd6bfee82) --- source3/smbd/close.c | 4 ++-- source3/smbd/open.c | 46 ++++++++++++++++++++++------------------------ 2 files changed, 24 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c0d87b1b21..d284c82f44 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -209,7 +209,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name)); } - delete_file = lck->delete_on_close; + delete_file = (lck->delete_on_close | lck->initial_delete_on_close); if (delete_file) { int i; @@ -345,7 +345,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name)); } - delete_dir = lck->delete_on_close; + delete_dir = (lck->delete_on_close | lck->initial_delete_on_close); talloc_free(lck); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0ccac592d6..dd2731c897 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1660,32 +1660,28 @@ files_struct *open_file_ntcreate(connection_struct *conn, } set_share_mode(lck, fsp, 0, fsp->oplock_type); - if (create_options & FILE_DELETE_ON_CLOSE) { - uint32 dosattr= existing_dos_attributes; - NTSTATUS result; - - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { - dosattr = new_dos_attributes; - } - - result = can_set_delete_on_close(fsp, True, dosattr); - if (!NT_STATUS_IS_OK(result)) { - /* Remember to delete the mode we just added. */ - del_share_mode(lck, fsp); - talloc_free(lck); - fd_close(conn,fsp); - file_free(fsp); - set_saved_ntstatus(result); - return NULL; + /* Handle strange delete on close create semantics. */ + if (create_options & FILE_DELETE_ON_CLOSE) { + NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes); + + if (!NT_STATUS_IS_OK(result)) { + /* Remember to delete the mode we just added. */ + del_share_mode(lck, fsp); + talloc_free(lck); + fd_close(conn,fsp); + file_free(fsp); + set_saved_ntstatus(result); + return NULL; + } + /* Note that here we set the *inital* delete on close flag, + not the regular one. */ + lck->initial_delete_on_close = True; + lck->modified = True; } - lck->delete_on_close = True; - lck->modified = True; - } - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { @@ -1976,7 +1972,9 @@ files_struct *open_directory(connection_struct *conn, set_share_mode(lck, fsp, 0, NO_OPLOCK); - if (create_options & FILE_DELETE_ON_CLOSE) { + if ((create_options & FILE_DELETE_ON_CLOSE) && + (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + info == FILE_WAS_SUPERSEDED)) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); @@ -1985,7 +1983,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - lck->delete_on_close = True; + lck->initial_delete_on_close = True; lck->modified = True; } -- cgit From 206cbff8b72a2ccc41e52b45097976f4511bfdec Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Feb 2006 16:38:37 +0000 Subject: r13291: NT checks the minimum password age dynamically. That means we have to ignore the sambapwdmustchange field if we can access the corresponding account policy and calculate it dynamically based on the pwdlastset field. Volker (This used to be commit b02b1d3ef3bceec1957d025c642e306a65310d22) --- source3/smbd/chgpasswd.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5a179dbf47..bb30519319 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1010,15 +1010,31 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { BOOL ret; - uint32 min_len; + uint32 min_len, min_age; struct passwd *pass = NULL; const char *username = pdb_get_username(hnd); + time_t last_change_time = pdb_get_pass_last_set_time(hnd); time_t can_change_time = pdb_get_pass_can_change_time(hnd); - if ((can_change_time != 0) && (time(NULL) < can_change_time)) { - DEBUG(1, ("user %s cannot change password now, must wait until %s\n", - username, http_timestring(can_change_time))); - return NT_STATUS_ACCOUNT_RESTRICTION; + if (pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age)) { + /* + * Windows calculates the minimum password age check + * dynamically, it basically ignores the pwdcanchange + * timestamp. Do likewise. + */ + if (last_change_time + min_age > time(NULL)) { + DEBUG(1, ("user %s cannot change password now, must " + "wait until %s\n", username, + http_timestring(last_change_time+min_age))); + return NT_STATUS_ACCOUNT_RESTRICTION; + } + } else { + if ((can_change_time != 0) && (time(NULL) < can_change_time)) { + DEBUG(1, ("user %s cannot change password now, must " + "wait until %s\n", username, + http_timestring(can_change_time))); + return NT_STATUS_ACCOUNT_RESTRICTION; + } } if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { -- cgit From d14af63e6ab600eb3ac705f2f425c860e927553a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Feb 2006 20:44:50 +0000 Subject: r13293: Rather a big patch I'm afraid, but this should fix bug #3347 by saving the UNIX token used to set a delete on close flag, and using it when doing the delete. libsmbsharemodes.so still needs updating to cope with this change. Samba4 torture tests to follow. Jeremy. (This used to be commit 23f16cbc2e8cde97c486831e26bcafd4ab4a9654) --- source3/smbd/close.c | 66 ++++++++++++++++++++++++++++--------- source3/smbd/dir.c | 4 +-- source3/smbd/fake_file.c | 2 +- source3/smbd/files.c | 6 ++-- source3/smbd/nttrans.c | 26 +++++++-------- source3/smbd/open.c | 2 ++ source3/smbd/posix_acls.c | 30 ++++++++--------- source3/smbd/reply.c | 26 +++++++-------- source3/smbd/sec_ctx.c | 83 +++++++++++++++++++++++------------------------ source3/smbd/trans2.c | 14 ++++---- source3/smbd/uid.c | 30 ++++++++--------- 11 files changed, 162 insertions(+), 127 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d284c82f44..059b88ecc8 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -145,13 +145,12 @@ static void notify_deferred_opens(struct share_mode_lock *lck) /**************************************************************************** Close a file. - If normal_close is 1 then this came from a normal SMBclose (or equivalent) - operation otherwise it came as the result of some other operation such as - the closing of the connection. In the latter case printing and - magic scripts are not run. + close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE. + printing and magic scripts are only run on normal close. + delete on close is done on normal and shutdown close. ****************************************************************************/ -static int close_normal_file(files_struct *fsp, BOOL normal_close) +static int close_normal_file(files_struct *fsp, enum file_close_type close_type) { BOOL delete_file = False; connection_struct *conn = fsp->conn; @@ -187,7 +186,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) } if (fsp->print_file) { - print_fsp_end(fsp, normal_close); + print_fsp_end(fsp, close_type); file_free(fsp); return 0; } @@ -232,12 +231,26 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * reference to a file. */ - if (normal_close && delete_file) { + if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && + delete_file && + lck->delete_token) { SMB_STRUCT_STAT sbuf; DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); + /* Become the user who requested the delete. */ + + if (!push_sec_ctx()) { + smb_panic("close_file: file %s. failed to push sec_ctx.\n"); + } + + set_sec_ctx(lck->delete_token->uid, + lck->delete_token->gid, + lck->delete_token->ngroups, + lck->delete_token->groups, + NULL); + /* We can only delete the file if the name we have is still valid and hasn't been renamed. */ @@ -268,8 +281,11 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) "and unlink failed with error %s\n", fsp->fsp_name, strerror(errno) )); } - process_pending_change_notify_queue((time_t)0); } + /* unbecome user. */ + pop_sec_ctx(); + + process_pending_change_notify_queue((time_t)0); } talloc_free(lck); @@ -288,7 +304,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) } /* check for magic scripts */ - if (normal_close) { + if (close_type == NORMAL_CLOSE) { check_magic(fsp,conn); } @@ -324,7 +340,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) Close a directory opened by an NT SMB call. ****************************************************************************/ -static int close_directory(files_struct *fsp, BOOL normal_close) +static int close_directory(files_struct *fsp, enum file_close_type close_type) { struct share_mode_lock *lck = 0; BOOL delete_dir = False; @@ -349,11 +365,31 @@ static int close_directory(files_struct *fsp, BOOL normal_close) talloc_free(lck); - if (normal_close && delete_dir) { - BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name); + if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && + delete_dir && + lck->delete_token) { + BOOL ok; + + /* Become the user who requested the delete. */ + + if (!push_sec_ctx()) { + smb_panic("close_directory: failed to push sec_ctx.\n"); + } + + set_sec_ctx(lck->delete_token->uid, + lck->delete_token->gid, + lck->delete_token->ngroups, + lck->delete_token->groups, + NULL); + + ok = rmdir_internals(fsp->conn, fsp->fsp_name); + DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", fsp->fsp_name, ok ? "succeeded" : "failed" )); + /* unbecome user. */ + pop_sec_ctx(); + /* * Ensure we remove any change notify requests that would * now fail as the directory has been deleted. @@ -404,12 +440,12 @@ static int close_stat(files_struct *fsp) Close a files_struct. ****************************************************************************/ -int close_file(files_struct *fsp, BOOL normal_close) +int close_file(files_struct *fsp, enum file_close_type close_type) { if(fsp->is_directory) - return close_directory(fsp, normal_close); + return close_directory(fsp, close_type); else if (fsp->is_stat) return close_stat(fsp); else - return close_normal_file(fsp, normal_close); + return close_normal_file(fsp, close_type); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 0635db22db..81fe7c4021 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -866,7 +866,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); - close_file(fsp, True); + close_file(fsp, NORMAL_CLOSE); /* No access if SD get failed. */ if (!sd_size) { @@ -929,7 +929,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); - close_file(fsp, False); + close_file(fsp, NORMAL_CLOSE); /* No access if SD get failed. */ if (!sd_size) diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 799725a782..1356baf1a8 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -109,7 +109,7 @@ files_struct *open_fake_file(connection_struct *conn, files_struct *fsp = NULL; /* access check */ - if (current_user.uid != 0) { + if (current_user.ut.uid != 0) { DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n", lp_servicename(SNUM(conn)),fname,conn->user)); errno = EACCES; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 181e17b11f..5a545c236e 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -148,7 +148,7 @@ void file_close_conn(connection_struct *conn) for (fsp=Files;fsp;fsp=next) { next = fsp->next; if (fsp->conn == conn) { - close_file(fsp,False); + close_file(fsp,SHUTDOWN_CLOSE); } } } @@ -164,7 +164,7 @@ void file_close_pid(uint16 smbpid) for (fsp=Files;fsp;fsp=next) { next = fsp->next; if (fsp->file_pid == smbpid) { - close_file(fsp,False); + close_file(fsp,SHUTDOWN_CLOSE); } } } @@ -222,7 +222,7 @@ void file_close_user(int vuid) for (fsp=Files;fsp;fsp=next) { next=fsp->next; if (fsp->vuid == vuid) { - close_file(fsp,False); + close_file(fsp,SHUTDOWN_CLOSE); } } } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 72288e2c24..e12a24968b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -798,7 +798,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", fattr = FILE_ATTRIBUTE_NORMAL; } if (!fsp->is_directory && (fattr & aDIR)) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); END_PROFILE(SMBntcreateX); return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -812,13 +812,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); END_PROFILE(SMBntcreateX); /* Can't set allocation size on a directory. */ return ERROR_NT(NT_STATUS_ACCESS_DENIED); } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_DISK_FULL); } @@ -1416,7 +1416,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION); if (!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } @@ -1427,7 +1427,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); if (!NT_STATUS_IS_OK(status)) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } @@ -1441,7 +1441,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fattr = FILE_ATTRIBUTE_NORMAL; } if (!fsp->is_directory && (fattr & aDIR)) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1454,12 +1454,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (allocation_size && (allocation_size > file_len)) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); /* Can't set allocation size on a directory. */ return ERROR_NT(NT_STATUS_ACCESS_DENIED); } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); return ERROR_NT(NT_STATUS_DISK_FULL); } } else { @@ -1688,7 +1688,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new status = NT_STATUS_ACCESS_DENIED; } set_saved_ntstatus(NT_STATUS_OK); - close_file(fsp1,False); + close_file(fsp1,ERROR_CLOSE); return status; } @@ -1702,12 +1702,12 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new * Thus we don't look at the error return from the * close of fsp1. */ - close_file(fsp1,False); + close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); - close_ret = close_file(fsp2,False); + close_ret = close_file(fsp2,NORMAL_CLOSE); /* Grrr. We have to do this as open_file_shared1 adds aARCH when it creates the file. This isn't the correct thing to do in the copy case. JRA */ @@ -2379,7 +2379,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, ZERO_STRUCT(qt); /* access check */ - if (current_user.uid != 0) { + if (current_user.ut.uid != 0) { DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRDOS,ERRnoaccess); @@ -2626,7 +2626,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, ZERO_STRUCT(qt); /* access check */ - if (current_user.uid != 0) { + if (current_user.ut.uid != 0) { DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRDOS,ERRnoaccess); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd2731c897..15e814aae3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1678,6 +1678,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } /* Note that here we set the *inital* delete on close flag, not the regular one. */ + set_delete_on_close_token(lck, ¤t_user.ut); lck->initial_delete_on_close = True; lck->modified = True; } @@ -1983,6 +1984,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } + set_delete_on_close_token(lck, ¤t_user.ut); lck->initial_delete_on_close = True; lck->modified = True; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 34497f0280..5db245ac0c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -929,7 +929,7 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (lp_force_unknown_acl_user(snum)) { /* this allows take ownership to work * reasonably */ - *puser = current_user.uid; + *puser = current_user.ut.uid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" " owner sid for %s\n", @@ -950,7 +950,7 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (lp_force_unknown_acl_user(snum)) { /* this allows take group ownership to work * reasonably */ - *pgrp = current_user.gid; + *pgrp = current_user.ut.gid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" " group sid.\n")); @@ -1024,7 +1024,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) /* Assume that the current user is in the current group (force group) */ - if (uid_ace->unix_ug.uid == current_user.uid && group_ace->unix_ug.gid == current_user.gid) + if (uid_ace->unix_ug.uid == current_user.ut.uid && group_ace->unix_ug.gid == current_user.ut.gid) return True; fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); @@ -2246,8 +2246,8 @@ static BOOL current_user_in_group(gid_t gid) { int i; - for (i = 0; i < current_user.ngroups; i++) { - if (current_user.groups[i] == gid) { + for (i = 0; i < current_user.ut.ngroups; i++) { + if (current_user.ut.groups[i] == gid) { return True; } } @@ -3026,7 +3026,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ &se_restore); /* Case (2) */ - if ( ( has_take_ownership_priv && ( uid == current_user.uid ) ) || + if ( ( has_take_ownership_priv && ( uid == current_user.ut.uid ) ) || /* Case (3) */ ( has_restore_priv ) ) { @@ -3056,7 +3056,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ and also copes with the case where the SID in a take ownership ACL is a local SID on the users workstation */ - uid = current_user.uid; + uid = current_user.ut.uid; become_root(); /* Keep the current file gid the same. */ @@ -3136,7 +3136,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * the file. */ - if (need_chown && (user == (uid_t)-1 || user == current_user.uid)) { + if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); @@ -3960,12 +3960,12 @@ refusing write due to mask.\n", fname)); break; case SMB_ACL_USER: { - /* Check against current_user.uid. */ + /* Check against current_user.ut.uid. */ uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (puid == NULL) { goto check_stat; } - if (current_user.uid == *puid) { + if (current_user.ut.uid == *puid) { /* We have a uid match but we must ensure we have seen the acl mask. */ ret = have_write; DEBUG(10,("check_posix_acl_group_write: file %s \ @@ -4130,13 +4130,13 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) if (!S_ISDIR(sbuf.st_mode)) { return False; } - if (current_user.uid == 0 || conn->admin_user) { + if (current_user.ut.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; } /* Check primary owner write access. */ - if (current_user.uid == sbuf.st_uid) { + if (current_user.ut.uid == sbuf.st_uid) { return (sbuf.st_mode & S_IWUSR) ? True : False; } @@ -4152,7 +4152,7 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) * for bug #3348. Don't assume owning sticky bit * directory means write access allowed. */ - if (current_user.uid != sbuf_file.st_uid) { + if (current_user.ut.uid != sbuf_file.st_uid) { return False; } } @@ -4178,7 +4178,7 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST { int ret; - if (current_user.uid == 0 || conn->admin_user) { + if (current_user.ut.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; } @@ -4191,7 +4191,7 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST } /* Check primary owner write access. */ - if (current_user.uid == psbuf->st_uid) { + if (current_user.ut.uid == psbuf->st_uid) { return (psbuf->st_mode & S_IWUSR) ? True : False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 69c71c74b5..89b98be1e7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1386,7 +1386,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (fattr & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); END_PROFILE(SMBopen); return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1510,13 +1510,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_DISK_FULL); } retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size); if (retval < 0) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); END_PROFILE(SMBwrite); return ERROR_NT(NT_STATUS_DISK_FULL); } @@ -1526,7 +1526,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt fattr = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; if (fattr & aDIR) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); END_PROFILE(SMBopenX); return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1845,7 +1845,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, set_saved_ntstatus(NT_STATUS_OK); return NT_STATUS_ACCESS_DENIED; } - close_file(fsp,False); + close_file(fsp,NORMAL_CLOSE); return NT_STATUS_OK; } @@ -1938,7 +1938,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b set_saved_ntstatus(NT_STATUS_OK); return NT_STATUS_ACCESS_DENIED; } - close_file(fsp,False); + close_file(fsp,NORMAL_CLOSE); } return NT_STATUS_OK; } @@ -3267,7 +3267,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Special case - close NT SMB directory handle. */ DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum)); - close_file(fsp,True); + close_file(fsp,NORMAL_CLOSE); } else { /* * Close ordinary file. @@ -3295,7 +3295,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * a disk full error. If not then it was probably an I/O error. */ - if((close_err = close_file(fsp,True)) != 0) { + if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) { errno = close_err; END_PROFILE(SMBclose); return (UNIXERROR(ERRHRD,ERRgeneral)); @@ -3356,7 +3356,7 @@ int reply_writeclose(connection_struct *conn, if (numtowrite) { DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n", fsp->fsp_name )); - close_err = close_file(fsp,True); + close_err = close_file(fsp,NORMAL_CLOSE); } DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n", @@ -3596,7 +3596,7 @@ int reply_printclose(connection_struct *conn, DEBUG(3,("printclose fd=%d fnum=%d\n", fsp->fh->fd,fsp->fnum)); - close_err = close_file(fsp,True); + close_err = close_file(fsp,NORMAL_CLOSE); if(close_err != 0) { errno = close_err; @@ -4746,7 +4746,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, NULL); if (!fsp2) { - close_file(fsp1,False); + close_file(fsp1,ERROR_CLOSE); return(False); } @@ -4765,7 +4765,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); } - close_file(fsp1,False); + close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime); @@ -4776,7 +4776,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, * Thus we don't look at the error return from the * close of fsp1. */ - *err_ret = close_file(fsp2,False); + *err_ret = close_file(fsp2,NORMAL_CLOSE); return(ret == (SMB_OFF_T)src_sbuf.st_size); } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index a5411b94a1..fc6a858974 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -23,10 +23,7 @@ extern struct current_user current_user; struct sec_ctx { - uid_t uid; - uid_t gid; - int ngroups; - gid_t *groups; + UNIX_USER_TOKEN ut; NT_USER_TOKEN *token; }; @@ -216,10 +213,10 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx - 1]; - SAFE_FREE(prev_ctx_p->groups); - prev_ctx_p->ngroups = 0; + SAFE_FREE(prev_ctx_p->ut.groups); + prev_ctx_p->ut.ngroups = 0; - get_current_groups(gid, &prev_ctx_p->ngroups, &prev_ctx_p->groups); + get_current_groups(gid, &prev_ctx_p->ut.ngroups, &prev_ctx_p->ut.groups); done: unbecome_root(); @@ -249,26 +246,26 @@ BOOL push_sec_ctx(void) ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; - ctx_p->uid = geteuid(); - ctx_p->gid = getegid(); + ctx_p->ut.uid = geteuid(); + ctx_p->ut.gid = getegid(); DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n", - (unsigned int)ctx_p->uid, (unsigned int)ctx_p->gid, sec_ctx_stack_ndx )); + (unsigned int)ctx_p->ut.uid, (unsigned int)ctx_p->ut.gid, sec_ctx_stack_ndx )); ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); - ctx_p->ngroups = sys_getgroups(0, NULL); + ctx_p->ut.ngroups = sys_getgroups(0, NULL); - if (ctx_p->ngroups != 0) { - if (!(ctx_p->groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ngroups))) { + if (ctx_p->ut.ngroups != 0) { + if (!(ctx_p->ut.groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ut.ngroups))) { DEBUG(0, ("Out of memory in push_sec_ctx()\n")); delete_nt_token(&ctx_p->token); return False; } - sys_getgroups(ctx_p->ngroups, ctx_p->groups); + sys_getgroups(ctx_p->ut.ngroups, ctx_p->ut.groups); } else { - ctx_p->groups = NULL; + ctx_p->ut.groups = NULL; } return True; @@ -296,28 +293,28 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN sys_setgroups(ngroups, groups); #endif - ctx_p->ngroups = ngroups; + ctx_p->ut.ngroups = ngroups; - SAFE_FREE(ctx_p->groups); + SAFE_FREE(ctx_p->ut.groups); if (token && (token == ctx_p->token)) smb_panic("DUPLICATE_TOKEN"); delete_nt_token(&ctx_p->token); - ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups); + ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups); ctx_p->token = dup_nt_token(token); become_id(uid, gid); - ctx_p->uid = uid; - ctx_p->gid = gid; + ctx_p->ut.uid = uid; + ctx_p->ut.gid = gid; /* Update current_user stuff */ - current_user.uid = uid; - current_user.gid = gid; - current_user.ngroups = ngroups; - current_user.groups = groups; + current_user.ut.uid = uid; + current_user.ut.gid = gid; + current_user.ut.ngroups = ngroups; + current_user.ut.groups = groups; current_user.nt_user_token = ctx_p->token; } @@ -352,11 +349,11 @@ BOOL pop_sec_ctx(void) /* Clear previous user info */ - ctx_p->uid = (uid_t)-1; - ctx_p->gid = (gid_t)-1; + ctx_p->ut.uid = (uid_t)-1; + ctx_p->ut.gid = (gid_t)-1; - SAFE_FREE(ctx_p->groups); - ctx_p->ngroups = 0; + SAFE_FREE(ctx_p->ut.groups); + ctx_p->ut.ngroups = 0; delete_nt_token(&ctx_p->token); @@ -369,17 +366,17 @@ BOOL pop_sec_ctx(void) prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; #ifdef HAVE_SETGROUPS - sys_setgroups(prev_ctx_p->ngroups, prev_ctx_p->groups); + sys_setgroups(prev_ctx_p->ut.ngroups, prev_ctx_p->ut.groups); #endif - become_id(prev_ctx_p->uid, prev_ctx_p->gid); + become_id(prev_ctx_p->ut.uid, prev_ctx_p->ut.gid); /* Update current_user stuff */ - current_user.uid = prev_ctx_p->uid; - current_user.gid = prev_ctx_p->gid; - current_user.ngroups = prev_ctx_p->ngroups; - current_user.groups = prev_ctx_p->groups; + current_user.ut.uid = prev_ctx_p->ut.uid; + current_user.ut.gid = prev_ctx_p->ut.gid; + current_user.ut.ngroups = prev_ctx_p->ut.ngroups; + current_user.ut.groups = prev_ctx_p->ut.groups; current_user.nt_user_token = prev_ctx_p->token; DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", @@ -400,26 +397,26 @@ void init_sec_ctx(void) memset(sec_ctx_stack, 0, sizeof(struct sec_ctx) * MAX_SEC_CTX_DEPTH); for (i = 0; i < MAX_SEC_CTX_DEPTH; i++) { - sec_ctx_stack[i].uid = (uid_t)-1; - sec_ctx_stack[i].gid = (gid_t)-1; + sec_ctx_stack[i].ut.uid = (uid_t)-1; + sec_ctx_stack[i].ut.gid = (gid_t)-1; } /* Initialise first level of stack. It is the current context */ ctx_p = &sec_ctx_stack[0]; - ctx_p->uid = geteuid(); - ctx_p->gid = getegid(); + ctx_p->ut.uid = geteuid(); + ctx_p->ut.gid = getegid(); - get_current_groups(ctx_p->gid, &ctx_p->ngroups, &ctx_p->groups); + get_current_groups(ctx_p->ut.gid, &ctx_p->ut.ngroups, &ctx_p->ut.groups); ctx_p->token = NULL; /* Maps to guest user. */ /* Initialise current_user global */ - current_user.uid = ctx_p->uid; - current_user.gid = ctx_p->gid; - current_user.ngroups = ctx_p->ngroups; - current_user.groups = ctx_p->groups; + current_user.ut.uid = ctx_p->ut.uid; + current_user.ut.gid = ctx_p->ut.gid; + current_user.ut.ngroups = ctx_p->ut.ngroups; + current_user.ut.groups = ctx_p->ut.groups; /* The conn and vuid are usually taken care of by other modules. We initialise them here. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8ff219b468..b8fc2b5b8f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -856,7 +856,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i inode = sbuf.st_ino; if (fattr & aDIR) { talloc_destroy(ctx); - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); return(ERROR_DOS(ERRDOS,ERRnoaccess)); } @@ -864,7 +864,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); if (!NT_STATUS_IS_OK(status)) { - close_file(fsp,False); + close_file(fsp,ERROR_CLOSE); return ERROR_NT(status); } } @@ -2355,7 +2355,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned fsp.fnum = -1; /* access check */ - if (current_user.uid != 0) { + if (current_user.ut.uid != 0) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRDOS,ERRnoaccess); @@ -2530,7 +2530,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", ZERO_STRUCT(quotas); /* access check */ - if ((current_user.uid != 0)||!CAN_WRITE(conn)) { + if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRSRV,ERRaccess); @@ -3888,7 +3888,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char new_fsp->fnum, strerror(errno))); ret = -1; } - close_file(new_fsp,True); + close_file(new_fsp,NORMAL_CLOSE); } else { ret = vfs_allocate_file_space(fsp, allocation_size); if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) { @@ -3951,7 +3951,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } /* The set is across all open files on this dev/inode pair. */ - if (!set_delete_on_close(fsp, delete_on_close)) { + if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) { return ERROR_NT(NT_STATUS_ACCESS_DENIED); } @@ -4416,7 +4416,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return(UNIXERROR(ERRDOS,ERRbadpath)); } ret = vfs_set_filelen(new_fsp, size); - close_file(new_fsp,True); + close_file(new_fsp,NORMAL_CLOSE); } else { ret = vfs_set_filelen(fsp, size); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 9db3d97ab2..d419720c33 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -30,18 +30,18 @@ extern struct current_user current_user; gid_t get_current_user_gid_first(int *piterator) { *piterator = 0; - return current_user.gid; + return current_user.ut.gid; } gid_t get_current_user_gid_next(int *piterator) { gid_t ret; - if (!current_user.groups || *piterator >= current_user.ngroups) { + if (!current_user.ut.groups || *piterator >= current_user.ut.ngroups) { return (gid_t)-1; } - ret = current_user.groups[*piterator]; + ret = current_user.ut.groups[*piterator]; (*piterator) += 1; return ret; } @@ -216,12 +216,12 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) */ if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && - (current_user.uid == conn->uid)) { + (current_user.ut.uid == conn->uid)) { DEBUG(4,("change_to_user: Skipping user change - already user\n")); return(True); } else if ((current_user.conn == conn) && (vuser != 0) && (current_user.vuid == vuid) && - (current_user.uid == vuser->uid)) { + (current_user.ut.uid == vuser->uid)) { DEBUG(4,("change_to_user: Skipping user change - already user\n")); return(True); } @@ -237,14 +237,14 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) if (conn->force_user) /* security = share sets this too */ { uid = conn->uid; gid = conn->gid; - current_user.groups = conn->groups; - current_user.ngroups = conn->ngroups; + current_user.ut.groups = conn->groups; + current_user.ut.ngroups = conn->ngroups; token = conn->nt_user_token; } else if (vuser) { uid = conn->admin_user ? 0 : vuser->uid; gid = vuser->gid; - current_user.ngroups = vuser->n_groups; - current_user.groups = vuser->groups; + current_user.ut.ngroups = vuser->n_groups; + current_user.ut.groups = vuser->groups; token = vuser->nt_user_token; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing share %s.\n",vuid, lp_servicename(snum) )); @@ -270,8 +270,8 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) */ int i; - for (i = 0; i < current_user.ngroups; i++) { - if (current_user.groups[i] == conn->gid) { + for (i = 0; i < current_user.ut.ngroups; i++) { + if (current_user.ut.groups[i] == conn->gid) { gid = conn->gid; break; } @@ -288,7 +288,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) if (vuser && vuser->guest) is_guest = True; - token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest); + token = create_nt_token(uid, gid, current_user.ut.ngroups, current_user.ut.groups, is_guest); if (!token) { DEBUG(1, ("change_to_user: create_nt_token failed!\n")); return False; @@ -296,7 +296,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) must_free_token = True; } - set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token); + set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, token); /* * Free the new token (as set_sec_ctx copies it). @@ -343,8 +343,8 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) if (!push_sec_ctx()) return False; - set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, - p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token); + set_sec_ctx(p->pipe_user.ut.uid, p->pipe_user.ut.gid, + p->pipe_user.ut.ngroups, p->pipe_user.ut.groups, p->pipe_user.nt_user_token); return True; } -- cgit From 66d5a32d9cae13ddceb9b4710722d86cdc343043 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Feb 2006 02:16:35 +0000 Subject: r13299: From testing W2K3 and W2K the delete on close bit seems to be always honored (ie. the file gets deleted) for derectories when set at open time - even though it doesn't show in the qfileinfo call. This is not true of files.... (if anyone from the EU is listening, it's stuff like this that makes CIFS non-documentable :-). Jeremy. (This used to be commit e2fc8a196a06f76aa47fabc30872c701a2f7ccec) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 15e814aae3..f75bc55b46 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1973,9 +1973,9 @@ files_struct *open_directory(connection_struct *conn, set_share_mode(lck, fsp, 0, NO_OPLOCK); - if ((create_options & FILE_DELETE_ON_CLOSE) && - (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED)) { + /* For directories the delete on close bit at open time seems + always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ + if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); -- cgit From 21a30a1346c9f9a25659a0cea0d276d8c2e6ddca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Feb 2006 22:10:37 +0000 Subject: r13314: This code has been causing problems since 1.9.x I think. Remove check_for_pipe() - Volker was completely correct. If it gets re-added it will be in a old open call path, not in the generic code path. Jeremy. (This used to be commit 50c894a6e949d4d3579926650674f381a821a671) --- source3/smbd/open.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f75bc55b46..4b13e28f8e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -73,23 +73,6 @@ int fd_close(struct connection_struct *conn, return fd_close_posix(conn, fsp); } - -/**************************************************************************** - Check a filename for the pipe string. -****************************************************************************/ - -static void check_for_pipe(const char *fname) -{ - /* special case of pipe opens */ - char s[10]; - StrnCpy(s,fname,sizeof(s)-1); - strlower_m(s); - if (strstr(s,"pipe/")) { - DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - set_saved_error_triple(ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED); - } -} - /**************************************************************************** Change the ownership of a file to that of the parent directory. Do this by fd if possible. @@ -226,7 +209,6 @@ static BOOL open_file(files_struct *fsp, /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); - check_for_pipe(fname); return False; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that @@ -292,7 +274,6 @@ static BOOL open_file(files_struct *fsp, DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", fname,strerror(errno),local_flags,flags)); - check_for_pipe(fname); return False; } -- cgit From 0af1500fc0bafe61019f1b2ab1d9e1d369221240 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Feb 2006 22:19:41 +0000 Subject: r13316: Let the carnage begin.... Sync with trunk as off r13315 (This used to be commit 17e63ac4ed8325c0d44fe62b2442449f3298559f) --- source3/smbd/chgpasswd.c | 13 +- source3/smbd/conn.c | 2 +- source3/smbd/lanman.c | 2750 +++++++++++++++++++++++-------------------- source3/smbd/msdfs.c | 8 +- source3/smbd/ntquotas.c | 9 +- source3/smbd/nttrans.c | 2 +- source3/smbd/open.c | 10 +- source3/smbd/password.c | 143 ++- source3/smbd/posix_acls.c | 10 +- source3/smbd/process.c | 115 +- source3/smbd/sec_ctx.c | 58 +- source3/smbd/server.c | 29 +- source3/smbd/service.c | 287 +++-- source3/smbd/sesssetup.c | 30 +- source3/smbd/share_access.c | 264 +++++ source3/smbd/uid.c | 131 +-- 16 files changed, 2151 insertions(+), 1710 deletions(-) create mode 100644 source3/smbd/share_access.c (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index bb30519319..0798541cb5 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -690,7 +690,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) } /* Now flush the sam_passwd struct to persistent storage */ - ret = pdb_update_sam_account (sampass); + ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass)); return ret; } @@ -828,7 +828,7 @@ static NTSTATUS check_oem_password(const char *user, DEBUG(1, ("LM password change supplied for user %s, but we have disabled LanMan authentication\n", user)); } - pdb_free_sam(&sampass); + pdb_free_sam(&sampass); return NT_STATUS_WRONG_PASSWORD; } else { DEBUG(1, ("password change requested for user %s, but no password supplied!\n", @@ -1009,7 +1009,6 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { - BOOL ret; uint32 min_len, min_age; struct passwd *pass = NULL; const char *username = pdb_get_username(hnd); @@ -1090,11 +1089,5 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw } /* Now write it into the file. */ - ret = pdb_update_sam_account (hnd); - - if (!ret) { - return NT_STATUS_ACCESS_DENIED; - } - - return NT_STATUS_OK; + return pdb_update_sam_account (hnd); } diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index bb000bac30..bf4db99ea6 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -249,7 +249,7 @@ void conn_free_internal(connection_struct *conn) } if (conn->nt_user_token) { - delete_nt_token(&(conn->nt_user_token)); + talloc_free(conn->nt_user_token); } free_namearray(conn->veto_list); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4778702e7a..83dfdf0d8b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1034,107 +1034,111 @@ static int get_server_info(uint32 servertype, struct srv_info_struct **servers, const char *domain) { - int count=0; - int alloced=0; - char **lines; - BOOL local_list_only; - int i; + int count=0; + int alloced=0; + char **lines; + BOOL local_list_only; + int i; - lines = file_lines_load(lock_path(SERVER_LIST), NULL); - if (!lines) { - DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); - return(0); - } + lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0); + if (!lines) { + DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); + return 0; + } - /* request for everything is code for request all servers */ - if (servertype == SV_TYPE_ALL) - servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + /* request for everything is code for request all servers */ + if (servertype == SV_TYPE_ALL) { + servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + } - local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); + local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); - DEBUG(4,("Servertype search: %8x\n",servertype)); + DEBUG(4,("Servertype search: %8x\n",servertype)); - for (i=0;lines[i];i++) { - fstring stype; - struct srv_info_struct *s; - const char *ptr = lines[i]; - BOOL ok = True; + for (i=0;lines[i];i++) { + fstring stype; + struct srv_info_struct *s; + const char *ptr = lines[i]; + BOOL ok = True; - if (!*ptr) continue; + if (!*ptr) { + continue; + } - if (count == alloced) { - struct srv_info_struct *ts; + if (count == alloced) { + struct srv_info_struct *ts; - alloced += 10; - ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); - if (!ts) { - DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); - return(0); - } - else *servers = ts; - memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); - } - s = &(*servers)[count]; + alloced += 10; + ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); + if (!ts) { + DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); + return 0; + } else { + *servers = ts; + } + memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); + } + s = &(*servers)[count]; - if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue; - if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue; - if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue; - if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) { - /* this allows us to cope with an old nmbd */ - fstrcpy(s->domain,lp_workgroup()); - } + if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) { + continue; + } + if (!next_token(&ptr,stype, NULL, sizeof(stype))) { + continue; + } + if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) { + continue; + } + if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) { + /* this allows us to cope with an old nmbd */ + fstrcpy(s->domain,lp_workgroup()); + } - if (sscanf(stype,"%X",&s->type) != 1) { - DEBUG(4,("r:host file ")); - ok = False; - } + if (sscanf(stype,"%X",&s->type) != 1) { + DEBUG(4,("r:host file ")); + ok = False; + } - /* Filter the servers/domains we return based on what was asked for. */ + /* Filter the servers/domains we return based on what was asked for. */ - /* Check to see if we are being asked for a local list only. */ - if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) { - DEBUG(4,("r: local list only")); - ok = False; - } + /* Check to see if we are being asked for a local list only. */ + if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) { + DEBUG(4,("r: local list only")); + ok = False; + } - /* doesn't match up: don't want it */ - if (!(servertype & s->type)) { - DEBUG(4,("r:serv type ")); - ok = False; - } + /* doesn't match up: don't want it */ + 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: dom mismatch ")); - ok = False; - } + if ((servertype & SV_TYPE_DOMAIN_ENUM) != + (s->type & SV_TYPE_DOMAIN_ENUM)) { + DEBUG(4,("s: dom mismatch ")); + ok = False; + } - if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) - { - ok = False; - } + if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) { + ok = False; + } - /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ - s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; + /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ + s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; - if (ok) - { - DEBUG(4,("**SV** %20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - - s->server_added = True; - count++; - } - else - { - DEBUG(4,("%20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - } - } + if (ok) { + DEBUG(4,("**SV** %20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + s->server_added = True; + count++; + } else { + DEBUG(4,("%20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + } + } - file_lines_free(lines); - return(count); + file_lines_free(lines); + return count; } /******************************************************************* @@ -1145,75 +1149,79 @@ static int fill_srv_info(struct srv_info_struct *service, int uLevel, char **buf, int *buflen, char **stringbuf, int *stringspace, char *baseaddr) { - int struct_len; - char* p; - char* p2; - int l2; - int len; + int struct_len; + char* p; + char* p2; + int l2; + int len; - switch (uLevel) { - case 0: struct_len = 16; break; - case 1: struct_len = 26; break; - default: return -1; - } - - if (!buf) - { - len = 0; - switch (uLevel) - { - case 1: - len = strlen(service->comment)+1; - break; + switch (uLevel) { + case 0: + struct_len = 16; + break; + case 1: + struct_len = 26; + break; + default: + return -1; } + + if (!buf) { + len = 0; + switch (uLevel) { + case 1: + len = strlen(service->comment)+1; + break; + } - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } + if (buflen) { + *buflen = struct_len; + } + if (stringspace) { + *stringspace = len; + } + return struct_len + len; + } - len = struct_len; - p = *buf; - if (*buflen < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = *buflen - struct_len; - } - if (!baseaddr) baseaddr = p; + len = struct_len; + p = *buf; + if (*buflen < struct_len) { + return -1; + } + if (stringbuf) { + p2 = *stringbuf; + l2 = *stringspace; + } else { + p2 = p + struct_len; + l2 = *buflen - struct_len; + } + if (!baseaddr) { + baseaddr = p; + } - switch (uLevel) - { - case 0: - push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE); - break; - - case 1: - push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE); - SIVAL(p,18,service->type); - SIVAL(p,22,PTR_DIFF(p2,baseaddr)); - len += CopyAndAdvance(&p2,service->comment,&l2); - break; - } - - if (stringbuf) - { - *buf = p + struct_len; - *buflen -= struct_len; - *stringbuf = p2; - *stringspace = l2; - } - else - { - *buf = p2; - *buflen -= len; - } - return len; + switch (uLevel) { + case 0: + push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE); + break; + + case 1: + push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE); + SIVAL(p,18,service->type); + SIVAL(p,22,PTR_DIFF(p2,baseaddr)); + len += CopyAndAdvance(&p2,service->comment,&l2); + break; + } + + if (stringbuf) { + *buf = p + struct_len; + *buflen -= struct_len; + *stringbuf = p2; + *stringspace = l2; + } else { + *buf = p2; + *buflen -= len; + } + return len; } @@ -1231,124 +1239,137 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - uint32 servertype = IVAL(p,4); - char *p2; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; - struct srv_info_struct *servers=NULL; - int counted=0,total=0; - int i,missed; - fstring domain; - BOOL domain_request; - BOOL local_request; - - /* If someone sets all the bits they don't really mean to set - DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the - known servers. */ - - if (servertype == SV_TYPE_ALL) - servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); - - /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set - any other bit (they may just set this bit on it's own) they - want all the locally seen servers. However this bit can be - set on its own so set the requested servers to be - ALL - DOMAIN_ENUM. */ - - if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) - servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); - - domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); - local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0); - - p += 8; - - if (!prefix_ok(str1,"WrLehD")) return False; - if (!check_server_info(uLevel,str2)) return False; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + uint32 servertype = IVAL(p,4); + char *p2; + int data_len, fixed_len, string_len; + int f_len = 0, s_len = 0; + struct srv_info_struct *servers=NULL; + int counted=0,total=0; + int i,missed; + fstring domain; + BOOL domain_request; + BOOL local_request; + + /* If someone sets all the bits they don't really mean to set + DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the + known servers. */ + + if (servertype == SV_TYPE_ALL) { + servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + } + + /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set + any other bit (they may just set this bit on it's own) they + want all the locally seen servers. However this bit can be + set on its own so set the requested servers to be + ALL - DOMAIN_ENUM. */ + + if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) { + servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); + } + + domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); + local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0); + + p += 8; + + if (!prefix_ok(str1,"WrLehD")) { + return False; + } + if (!check_server_info(uLevel,str2)) { + return False; + } - 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, "WrLehDz") == 0) { - pull_ascii_fstring(domain, p); - } else { - fstrcpy(domain, lp_workgroup()); - } - - if (lp_browse_list()) - total = get_server_info(servertype,&servers,domain); - - data_len = fixed_len = string_len = 0; - missed = 0; - - if (total > 0) - qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); - - { - char *lastname=NULL; - - for (i=0;iname)) continue; - lastname = s->name; - 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)); + 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, "WrLehDz") == 0) { + pull_ascii_fstring(domain, p); + } else { + fstrcpy(domain, lp_workgroup()); + } + + if (lp_browse_list()) { + total = get_server_info(servertype,&servers,domain); + } + + data_len = fixed_len = string_len = 0; + missed = 0; + + if (total > 0) { + qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); + } + + { + char *lastname=NULL; + + for (i=0;iname)) { + continue; + } + lastname = s->name; + 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; - } else { - missed++; - } - } - } - - *rdata_len = fixed_len + string_len; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); - memset(*rdata,'\0',*rdata_len); + if (data_len <= buf_len) { + counted++; + fixed_len += f_len; + string_len += s_len; + } else { + missed++; + } + } + } + + *rdata_len = fixed_len + string_len; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + memset(*rdata,'\0',*rdata_len); - p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ - p = *rdata; - f_len = fixed_len; - s_len = string_len; - - { - char *lastname=NULL; - int count2 = counted; - for (i = 0; i < total && count2;i++) - { - struct srv_info_struct *s = &servers[i]; - if (lastname && strequal(lastname,s->name)) continue; - lastname = s->name; - 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--; - } - } + p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ + p = *rdata; + f_len = fixed_len; + s_len = string_len; + + { + char *lastname=NULL; + int count2 = counted; + + for (i = 0; i < total && count2;i++) { + struct srv_info_struct *s = &servers[i]; + + if (lastname && strequal(lastname,s->name)) { + continue; + } + lastname = s->name; + 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--; + } + } - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,counted+missed); + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); - SAFE_FREE(servers); + SAFE_FREE(servers); - DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", - domain,uLevel,counted,counted+missed)); + DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", + domain,uLevel,counted,counted+missed)); - return(True); + return True; } /**************************************************************************** @@ -1359,30 +1380,32 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - int counted=0; - int missed=0; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + int counted=0; + int missed=0; DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", str1, str2, p, uLevel, buf_len)); - if (!prefix_ok(str1,"zWrLeh")) return False; + if (!prefix_ok(str1,"zWrLeh")) { + return False; + } - *rdata_len = 0; + *rdata_len = 0; - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVAL(*rparam,0,0x08AC); /* informational warning message */ - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,counted+missed); + SSVAL(*rparam,0,0x08AC); /* informational warning message */ + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); - return(True); + return True; } /**************************************************************************** @@ -1391,117 +1414,146 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa static BOOL check_share_info(int uLevel, char* id) { - switch( uLevel ) { - case 0: - if (strcmp(id,"B13") != 0) return False; - break; - case 1: - if (strcmp(id,"B13BWz") != 0) return False; - break; - case 2: - if (strcmp(id,"B13BWzWWWzB9B") != 0) return False; - break; - case 91: - if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False; - break; - default: return False; - } - return True; + switch( uLevel ) { + case 0: + if (strcmp(id,"B13") != 0) { + return False; + } + break; + case 1: + if (strcmp(id,"B13BWz") != 0) { + return False; + } + break; + case 2: + if (strcmp(id,"B13BWzWWWzB9B") != 0) { + return False; + } + break; + case 91: + if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) { + return False; + } + break; + default: + return False; + } + return True; } static int fill_share_info(connection_struct *conn, int snum, int uLevel, char** buf, int* buflen, char** stringbuf, int* stringspace, char* baseaddr) { - int struct_len; - char* p; - char* p2; - int l2; - int len; + int struct_len; + char* p; + char* p2; + int l2; + int len; - switch( uLevel ) { - case 0: struct_len = 13; break; - case 1: struct_len = 20; break; - case 2: struct_len = 40; break; - case 91: struct_len = 68; break; - default: return -1; - } + switch( uLevel ) { + case 0: + struct_len = 13; + break; + case 1: + struct_len = 20; + break; + case 2: + struct_len = 40; + break; + case 91: + struct_len = 68; + break; + default: + return -1; + } - if (!buf) - { - len = 0; - if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum)); - if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } + if (!buf) { + len = 0; + + if (uLevel > 0) { + len += StrlenExpanded(conn,snum,lp_comment(snum)); + } + if (uLevel > 1) { + len += strlen(lp_pathname(snum)) + 1; + } + if (buflen) { + *buflen = struct_len; + } + if (stringspace) { + *stringspace = len; + } + return struct_len + len; + } - len = struct_len; - p = *buf; - if ((*buflen) < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = (*buflen) - struct_len; - } - if (!baseaddr) baseaddr = p; + len = struct_len; + p = *buf; + if ((*buflen) < struct_len) { + return -1; + } + + if (stringbuf) { + p2 = *stringbuf; + l2 = *stringspace; + } else { + p2 = p + struct_len; + l2 = (*buflen) - struct_len; + } + + if (!baseaddr) { + baseaddr = p; + } - push_ascii(p,lp_servicename(snum),13, STR_TERMINATE); + push_ascii(p,lp_servicename(snum),13, STR_TERMINATE); - if (uLevel > 0) - { - int type; - SCVAL(p,13,0); - type = STYPE_DISKTREE; - if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC; - SSVAL(p,14,type); /* device type */ - SIVAL(p,16,PTR_DIFF(p2,baseaddr)); - len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); - } + if (uLevel > 0) { + int type; + + SCVAL(p,13,0); + type = STYPE_DISKTREE; + if (lp_print_ok(snum)) { + type = STYPE_PRINTQ; + } + if (strequal("IPC",lp_fstype(snum))) { + type = STYPE_IPC; + } + SSVAL(p,14,type); /* device type */ + SIVAL(p,16,PTR_DIFF(p2,baseaddr)); + len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); + } - if (uLevel > 1) - { - SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ - SSVALS(p,22,-1); /* max uses */ - SSVAL(p,24,1); /* current uses */ - SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ - len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); - memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ - } + if (uLevel > 1) { + SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ + SSVALS(p,22,-1); /* max uses */ + SSVAL(p,24,1); /* current uses */ + SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ + len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); + memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ + } - if (uLevel > 2) - { - memset(p+40,0,SHPWLEN+2); - SSVAL(p,50,0); - SIVAL(p,52,0); - SSVAL(p,56,0); - SSVAL(p,58,0); - SIVAL(p,60,0); - SSVAL(p,64,0); - SSVAL(p,66,0); - } + if (uLevel > 2) { + memset(p+40,0,SHPWLEN+2); + SSVAL(p,50,0); + SIVAL(p,52,0); + SSVAL(p,56,0); + SSVAL(p,58,0); + SIVAL(p,60,0); + SSVAL(p,64,0); + SSVAL(p,66,0); + } - if (stringbuf) - { - (*buf) = p + struct_len; - (*buflen) -= struct_len; - (*stringbuf) = p2; - (*stringspace) = l2; - } - else - { - (*buf) = p2; - (*buflen) -= len; - } - return len; + if (stringbuf) { + (*buf) = p + struct_len; + (*buflen) -= struct_len; + (*stringbuf) = p2; + (*stringspace) = l2; + } else { + (*buf) = p2; + (*buflen) -= len; + } + + return len; } static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -1509,31 +1561,39 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *netname = skip_string(str2,1); - char *p = skip_string(netname,1); - int uLevel = SVAL(p,0); - int snum = find_service(netname); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *netname = skip_string(str2,1); + char *p = skip_string(netname,1); + int uLevel = SVAL(p,0); + int snum = find_service(netname); - if (snum < 0) return False; + if (snum < 0) { + return False; + } - /* check it's a supported varient */ - if (!prefix_ok(str1,"zWrLh")) return False; - if (!check_share_info(uLevel,str2)) return False; + /* check it's a supported varient */ + if (!prefix_ok(str1,"zWrLh")) { + return False; + } + if (!check_share_info(uLevel,str2)) { + return False; + } - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - p = *rdata; - *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); - if (*rdata_len < 0) return False; + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + p = *rdata; + *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); + if (*rdata_len < 0) { + return False; + } - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); - return(True); + return True; } /**************************************************************************** @@ -1557,78 +1617,87 @@ static BOOL api_RNetShareEnum( connection_struct *conn, int *rdata_len, int *rparam_len ) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - char *p2; - int count=lp_numservices(); - int total=0,counted=0; - BOOL missed = False; - int i; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + char *p2; + int count = 0; + int total=0,counted=0; + BOOL missed = False; + int i; + int data_len, fixed_len, string_len; + int f_len = 0, s_len = 0; - if (!prefix_ok(str1,"WrLeh")) return False; - if (!check_share_info(uLevel,str2)) return False; + if (!prefix_ok(str1,"WrLeh")) { + return False; + } + if (!check_share_info(uLevel,str2)) { + return False; + } - data_len = fixed_len = string_len = 0; - for (i=0;i= 0) { /* already exists */ - res = ERRfilexists; - goto error_exit; - } - - /* only support disk share adds */ - if (SVAL(data,14)!=STYPE_DISKTREE) return False; - - offset = IVAL(data, 16); - if (offset >= mdrcnt) { - res = ERRinvalidparam; - goto error_exit; - } - pull_ascii_fstring(comment, offset? (data+offset) : ""); - - offset = IVAL(data, 26); - if (offset >= mdrcnt) { - res = ERRinvalidparam; - goto error_exit; - } - pull_ascii_pstring(pathname, offset? (data+offset) : ""); - - string_replace(sharename, '"', ' '); - string_replace(pathname, '"', ' '); - string_replace(comment, '"', ' '); - - cmdname = lp_add_share_cmd(); - - if (!cmdname || *cmdname == '\0') return False; - - asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", - lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment); - - if (command) { - DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); - if ((res = smbrun(command, NULL)) != 0) { - DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); - SAFE_FREE(command); - res = ERRnoaccess; - goto error_exit; - } else { - SAFE_FREE(command); - message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); - } - } else return False; - - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - *rdata_len = 0; - - return True; - - error_exit: - *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - *rdata_len = 0; - SSVAL(*rparam,0,res); - SSVAL(*rparam,2,0); - return True; -} - -/**************************************************************************** - view list of groups available - ****************************************************************************/ - -static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - int i; - int errflags=0; - int resume_context, cli_buf_size; char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + fstring sharename; + fstring comment; + pstring pathname; + char *command, *cmdname; + unsigned int offset; + int snum; + int res = ERRunsup; + + /* check it's a supported varient */ + if (!prefix_ok(str1,RAP_WShareAdd_REQ)) { + return False; + } + if (!check_share_info(uLevel,str2)) { + return False; + } + if (uLevel != 2) { + return False; + } - struct pdb_search *search; - struct samr_displayentry *entries; + pull_ascii_fstring(sharename,data); + snum = find_service(sharename); + if (snum >= 0) { /* already exists */ + res = ERRfilexists; + goto error_exit; + } - int num_entries; - - if (strcmp(str1,"WrLeh") != 0) + /* only support disk share adds */ + if (SVAL(data,14)!=STYPE_DISKTREE) { return False; + } - /* parameters - * W-> resume context (number of users to skip) - * r -> return parameter pointer to receive buffer - * L -> length of receive buffer - * e -> return parameter number of entries - * h -> return parameter total number of users - */ - if (strcmp("B21",str2) != 0) - return False; + offset = IVAL(data, 16); + if (offset >= mdrcnt) { + res = ERRinvalidparam; + goto error_exit; + } + + pull_ascii_fstring(comment, offset? (data+offset) : ""); + + offset = IVAL(data, 26); + + if (offset >= mdrcnt) { + res = ERRinvalidparam; + goto error_exit; + } + + pull_ascii_pstring(pathname, offset? (data+offset) : ""); + + string_replace(sharename, '"', ' '); + string_replace(pathname, '"', ' '); + string_replace(comment, '"', ' '); + + cmdname = lp_add_share_cmd(); + + if (!cmdname || *cmdname == '\0') { + return False; + } + + asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", + lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment); + + if (command) { + DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); + + if ((res = smbrun(command, NULL)) != 0) { + DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); + SAFE_FREE(command); + res = ERRnoaccess; + goto error_exit; + } else { + SAFE_FREE(command); + message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); + } + } else { + return False; + } + + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + *rdata_len = 0; + + return True; + + error_exit: + + *rparam_len = 4; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rdata_len = 0; + SSVAL(*rparam,0,res); + SSVAL(*rparam,2,0); + return True; +} + +/**************************************************************************** + view list of groups available + ****************************************************************************/ + +static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + int i; + int errflags=0; + int resume_context, cli_buf_size; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + + struct pdb_search *search; + struct samr_displayentry *entries; + + int num_entries; + + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + + /* parameters + * W-> resume context (number of users to skip) + * r -> return parameter pointer to receive buffer + * L -> length of receive buffer + * e -> return parameter number of entries + * h -> return parameter total number of users + */ + + if (strcmp("B21",str2) != 0) { + return False; + } /* get list of domain groups SID_DOMAIN_GRP=2 */ become_root(); @@ -1837,8 +1926,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para gid_t *gids; size_t num_groups; size_t i; - struct passwd *passwd; NTSTATUS result; + DOM_SID user_sid; + enum SID_NAME_USE type; + TALLOC_CTX *mem_ctx; *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); @@ -1867,45 +1958,64 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para p = *rdata; + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_new failed\n")); + return False; + } + /* Lookup the user information; This should only be one of our accounts (not remote domains) */ - passwd = getpwnam_alloc(UserName); - - if (passwd == NULL) - return False; - - pdb_init_sam( &sampw ); - become_root(); /* ROOT BLOCK */ - if ( !pdb_getsampwnam(sampw, UserName) ) - goto out; + if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL, + NULL, NULL, &user_sid, &type)) { + DEBUG(10, ("lookup_name(%s) failed\n", UserName)); + goto done; + } + + if (type != SID_NAME_USER) { + DEBUG(10, ("%s is a %s, not a user\n", UserName, + sid_type_lookup(type))); + goto done; + } + + if (!NT_STATUS_IS_OK(pdb_init_sam_talloc(mem_ctx, &sampw))) { + DEBUG(10, ("pdb_init_sam_talloc failed\n")); + goto done; + } + + if ( !pdb_getsampwsid(sampw, &user_sid) ) { + DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n", + sid_string_static(&user_sid), UserName)); + goto done; + } + gids = NULL; sids = NULL; num_groups = 0; - result = pdb_enum_group_memberships(pdb_get_username(sampw), - passwd->pw_gid, + result = pdb_enum_group_memberships(mem_ctx, sampw, &sids, &gids, &num_groups); - if (!NT_STATUS_IS_OK(result)) - goto out; + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10, ("pdb_enum_group_memberships failed for %s\n", + UserName)); + goto done; + } for (i=0; imem_ctx, &sids[i], NULL, &grp_name, - NULL) ) { + if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) { pstrcpy(p, grp_name); p += 21; count++; } } - SAFE_FREE(sids); - *rdata_len = PTR_DIFF(p,*rdata); SSVAL(*rparam,4,count); /* is this right?? */ @@ -1913,11 +2023,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para ret = True; -out: +done: unbecome_root(); /* END ROOT BLOCK */ - pdb_free_sam( &sampw ); - passwd_free(&passwd); + talloc_free(mem_ctx); return ret; } @@ -2023,43 +2132,42 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *p; - *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - - *rdata_len = 21; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - - { - struct tm *t; - time_t unixdate = time(NULL); - - srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at - by NT in a "net time" operation, - it seems to ignore the one below */ - - /* the client expects to get localtime, not GMT, in this bit - (I think, this needs testing) */ - t = localtime(&unixdate); - - SIVAL(p,4,0); /* msecs ? */ - SCVAL(p,8,t->tm_hour); - SCVAL(p,9,t->tm_min); - SCVAL(p,10,t->tm_sec); - SCVAL(p,11,0); /* hundredths of seconds */ - SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */ - SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ - SCVAL(p,16,t->tm_mday); - SCVAL(p,17,t->tm_mon + 1); - SSVAL(p,18,1900+t->tm_year); - SCVAL(p,20,t->tm_wday); - } - return(True); + struct tm *t; + time_t unixdate = time(NULL); + char *p; + + *rparam_len = 4; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + + *rdata_len = 21; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + + p = *rdata; + + srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at + by NT in a "net time" operation, + it seems to ignore the one below */ + + /* the client expects to get localtime, not GMT, in this bit + (I think, this needs testing) */ + t = localtime(&unixdate); + + SIVAL(p,4,0); /* msecs ? */ + SCVAL(p,8,t->tm_hour); + SCVAL(p,9,t->tm_min); + SCVAL(p,10,t->tm_sec); + SCVAL(p,11,0); /* hundredths of seconds */ + SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */ + SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ + SCVAL(p,16,t->tm_mday); + SCVAL(p,17,t->tm_mon + 1); + SSVAL(p,18,1900+t->tm_year); + SCVAL(p,20,t->tm_wday); + + return True; } /**************************************************************************** @@ -2111,7 +2219,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param } unbecome_root(); - free_server_info(&server_info); + talloc_free(server_info); } data_blob_clear_free(&password); } @@ -2421,103 +2529,117 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - char *p2; - int struct_len; - - DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); - - /* check it's a supported varient */ - if (!prefix_ok(str1,"WrLh")) return False; - switch( uLevel ) { - case 0: - if (strcmp(str2,"B16") != 0) return False; - struct_len = 16; - break; - case 1: - if (strcmp(str2,"B16BBDz") != 0) return False; - struct_len = 26; - break; - case 2: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz") - != 0) return False; - struct_len = 134; - break; - case 3: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") - != 0) return False; - struct_len = 144; - break; - case 20: - if (strcmp(str2,"DN") != 0) return False; - struct_len = 6; - break; - case 50: - if (strcmp(str2,"B16BBDzWWzzz") != 0) return False; - struct_len = 42; - break; - default: return False; - } - - *rdata_len = mdrcnt; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); - - p = *rdata; - p2 = p + struct_len; - if (uLevel != 20) { - srvstr_push(NULL, p,get_local_machine_name(),16, - STR_ASCII|STR_UPPER|STR_TERMINATE); - } - p += 16; - if (uLevel > 0) - { - struct srv_info_struct *servers=NULL; - int i,count; - pstring comment; - uint32 servertype= lp_default_server_announce(); - - push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE); - - if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { - for (i=0;i 1) - { - return False; /* not yet implemented */ - } - - *rdata_len = PTR_DIFF(p2,*rdata); - - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - - return(True); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + char *p2; + int struct_len; + + DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); + + /* check it's a supported varient */ + if (!prefix_ok(str1,"WrLh")) { + return False; + } + + switch( uLevel ) { + case 0: + if (strcmp(str2,"B16") != 0) { + return False; + } + struct_len = 16; + break; + case 1: + if (strcmp(str2,"B16BBDz") != 0) { + return False; + } + struct_len = 26; + break; + case 2: + if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) { + return False; + } + struct_len = 134; + break; + case 3: + if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) { + return False; + } + struct_len = 144; + break; + case 20: + if (strcmp(str2,"DN") != 0) { + return False; + } + struct_len = 6; + break; + case 50: + if (strcmp(str2,"B16BBDzWWzzz") != 0) { + return False; + } + struct_len = 42; + break; + default: + return False; + } + + *rdata_len = mdrcnt; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + + p = *rdata; + p2 = p + struct_len; + if (uLevel != 20) { + srvstr_push(NULL, p,get_local_machine_name(),16, + STR_ASCII|STR_UPPER|STR_TERMINATE); + } + p += 16; + if (uLevel > 0) { + struct srv_info_struct *servers=NULL; + int i,count; + pstring comment; + uint32 servertype= lp_default_server_announce(); + + push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE); + + if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { + for (i=0;i 1) { + return False; /* not yet implemented */ + } + + *rdata_len = PTR_DIFF(p2,*rdata); + + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + + return True; } /**************************************************************************** @@ -2529,67 +2651,67 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char *p2; - int level = SVAL(p,0); - - DEBUG(4,("NetWkstaGetInfo level %d\n",level)); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char *p2; + int level = SVAL(p,0); - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + DEBUG(4,("NetWkstaGetInfo level %d\n",level)); - /* check it's a supported varient */ - if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) - return(False); + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - *rdata_len = mdrcnt + 1024; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + /* check it's a supported varient */ + if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) { + return False; + } - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ + *rdata_len = mdrcnt + 1024; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); - p = *rdata; - p2 = p + 22; + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + p = *rdata; + p2 = p + 22; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ - pstrcpy(p2,get_local_machine_name()); - strupper_m(p2); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ + pstrcpy(p2,get_local_machine_name()); + strupper_m(p2); + p2 = skip_string(p2,1); + p += 4; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - pstrcpy(p2,current_user_info.smb_name); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + pstrcpy(p2,current_user_info.smb_name); + p2 = skip_string(p2,1); + p += 4; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ - pstrcpy(p2,lp_workgroup()); - strupper_m(p2); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ + pstrcpy(p2,lp_workgroup()); + strupper_m(p2); + p2 = skip_string(p2,1); + p += 4; - SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ - SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */ - p += 2; + SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ + SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */ + p += 2; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */ - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */ + p2 = skip_string(p2,1); + p += 4; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ - pstrcpy(p2,""); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ + pstrcpy(p2,""); + p2 = skip_string(p2,1); + p += 4; - *rdata_len = PTR_DIFF(p2,*rdata); + *rdata_len = PTR_DIFF(p2,*rdata); - SSVAL(*rparam,4,*rdata_len); + SSVAL(*rparam,4,*rdata_len); - return(True); + return True; } /**************************************************************************** @@ -2929,75 +3051,83 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - struct pack_desc desc; - char* name; - /* With share level security vuid will always be zero. - Don't depend on vuser being non-null !!. JRA */ - user_struct *vuser = get_valid_user_struct(vuid); - if(vuser != NULL) - DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, - vuser->user.unix_name)); - - uLevel = SVAL(p,0); - name = p + 2; - - memset((char *)&desc,'\0',sizeof(desc)); - - DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported varient */ - if (strcmp(str1,"OOWb54WrLh") != 0) return False; - if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False; - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.subformat = NULL; - desc.format = str2; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + struct pack_desc desc; + char* name; + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ + user_struct *vuser = get_valid_user_struct(vuid); + + if(vuser != NULL) { + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, + vuser->user.unix_name)); + } + + uLevel = SVAL(p,0); + name = p + 2; + + memset((char *)&desc,'\0',sizeof(desc)); + + DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); + + /* check it's a supported varient */ + if (strcmp(str1,"OOWb54WrLh") != 0) { + return False; + } + if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) { + return False; + } + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + } + + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.subformat = NULL; + desc.format = str2; - if (init_package(&desc,1,0)) - { - PACKI(&desc,"W",0); /* code */ - PACKS(&desc,"B21",name); /* eff. name */ - PACKS(&desc,"B",""); /* pad */ - PACKI(&desc,"W", - conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - PACKI(&desc,"D",0); /* auth flags XXX */ - PACKI(&desc,"W",0); /* num logons */ - PACKI(&desc,"W",0); /* bad pw count */ - PACKI(&desc,"D",0); /* last logon */ - PACKI(&desc,"D",-1); /* last logoff */ - PACKI(&desc,"D",-1); /* logoff time */ - PACKI(&desc,"D",-1); /* kickoff time */ - PACKI(&desc,"D",0); /* password age */ - PACKI(&desc,"D",0); /* password can change */ - PACKI(&desc,"D",-1); /* password must change */ - { - fstring mypath; - fstrcpy(mypath,"\\\\"); - fstrcat(mypath,get_local_machine_name()); - strupper_m(mypath); - PACKS(&desc,"z",mypath); /* computer */ - } - PACKS(&desc,"z",lp_workgroup());/* domain */ - - PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */ - - PACKI(&desc,"D",0x00000000); /* reserved */ - } - - *rdata_len = desc.usedlen; - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); - return(True); + if (init_package(&desc,1,0)) { + PACKI(&desc,"W",0); /* code */ + PACKS(&desc,"B21",name); /* eff. name */ + PACKS(&desc,"B",""); /* pad */ + PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); + PACKI(&desc,"D",0); /* auth flags XXX */ + PACKI(&desc,"W",0); /* num logons */ + PACKI(&desc,"W",0); /* bad pw count */ + PACKI(&desc,"D",0); /* last logon */ + PACKI(&desc,"D",-1); /* last logoff */ + PACKI(&desc,"D",-1); /* logoff time */ + PACKI(&desc,"D",-1); /* kickoff time */ + PACKI(&desc,"D",0); /* password age */ + PACKI(&desc,"D",0); /* password can change */ + PACKI(&desc,"D",-1); /* password must change */ + + { + fstring mypath; + fstrcpy(mypath,"\\\\"); + fstrcat(mypath,get_local_machine_name()); + strupper_m(mypath); + PACKS(&desc,"z",mypath); /* computer */ + } + + PACKS(&desc,"z",lp_workgroup());/* domain */ + PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */ + PACKI(&desc,"D",0x00000000); /* reserved */ + } + + *rdata_len = desc.usedlen; + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); + + return True; } /**************************************************************************** @@ -3009,24 +3139,28 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *user = skip_string(str2,1); - char *resource = skip_string(user,1); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *user = skip_string(str2,1); + char *resource = skip_string(user,1); - DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); + DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); - /* check it's a supported varient */ - if (strcmp(str1,"zzh") != 0) return False; - if (strcmp(str2,"") != 0) return False; + /* check it's a supported varient */ + if (strcmp(str1,"zzh") != 0) { + return False; + } + if (strcmp(str2,"") != 0) { + return False; + } - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,0); /* errorcode */ - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,0x7f); /* permission flags */ + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,0); /* errorcode */ + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,0x7f); /* permission flags */ - return(True); + return True; } /**************************************************************************** @@ -3038,192 +3172,224 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int count; - int i; - int snum; - fstring sharename; - uint32 jobid; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - char *tmpdata=NULL; - - uLevel = SVAL(p,2); - - memset((char *)&desc,'\0',sizeof(desc)); - memset((char *)&status,'\0',sizeof(status)); - - DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0))); - - /* check it's a supported varient */ - if (strcmp(str1,"WWrLh") != 0) return False; - if (!check_printjob_info(&desc,uLevel,str2)) return False; - - if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) - return False; - - snum = lp_servicenumber( sharename); - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = print_queue_status(snum,&queue,&status); - for (i = 0; i < count; i++) { - if (queue[i].job == jobid) break; - } - - if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - } else { - /* - * Don't return data but need to get correct length - * init_package will return wrong size if buflen=0 - */ - desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); - } - - if (init_package(&desc,1,0)) { - if (i < count) { - fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); - *rdata_len = desc.usedlen; - } - else { - desc.errcode = NERR_JobNotFound; - *rdata_len = 0; - } - } - - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - SAFE_FREE(queue); - SAFE_FREE(tmpdata); - - DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int count; + int i; + int snum; + fstring sharename; + uint32 jobid; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + char *tmpdata=NULL; -static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* name = p; - int uLevel; - int count; - int i, succnt=0; - int snum; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - memset((char *)&desc,'\0',sizeof(desc)); - memset((char *)&status,'\0',sizeof(status)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - - DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported variant */ - if (strcmp(str1,"zWrLeh") != 0) - return False; - - if (uLevel > 2) - return False; /* defined only for uLevel 0,1,2 */ - - if (!check_printjob_info(&desc,uLevel,str2)) - return False; - - snum = find_service(name); - if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) - return False; - - count = print_queue_status(snum,&queue,&status); - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,count,0)) { - succnt = 0; - for (i = 0; i < count; i++) { - fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); - if (desc.errcode == NERR_Success) succnt = i+1; - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,count); - - SAFE_FREE(queue); - - DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); - return(True); -} + uLevel = SVAL(p,2); + + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); + + DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0))); + + /* check it's a supported varient */ + if (strcmp(str1,"WWrLh") != 0) { + return False; + } + if (!check_printjob_info(&desc,uLevel,str2)) { + return False; + } + + if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) { + return False; + } + + snum = lp_servicenumber( sharename); + if (snum < 0 || !VALID_SNUM(snum)) { + return(False); + } + + count = print_queue_status(snum,&queue,&status); + for (i = 0; i < count; i++) { + if (queue[i].job == jobid) { + break; + } + } + + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); + } + + if (init_package(&desc,1,0)) { + if (i < count) { + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); + *rdata_len = desc.usedlen; + } else { + desc.errcode = NERR_JobNotFound; + *rdata_len = 0; + } + } + + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + SAFE_FREE(queue); + SAFE_FREE(tmpdata); + + DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); + + return True; +} + +static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char* name = p; + int uLevel; + int count; + int i, succnt=0; + int snum; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); + + /* check it's a supported variant */ + if (strcmp(str1,"zWrLeh") != 0) { + return False; + } + + if (uLevel > 2) { + return False; /* defined only for uLevel 0,1,2 */ + } + + if (!check_printjob_info(&desc,uLevel,str2)) { + return False; + } + + snum = find_service(name); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { + return False; + } + + count = print_queue_status(snum,&queue,&status); + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + } + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,count,0)) { + succnt = 0; + for (i = 0; i < count; i++) { + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); + if (desc.errcode == NERR_Success) { + succnt = i+1; + } + } + } + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,count); + + SAFE_FREE(queue); + + DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); + + return True; +} static int check_printdest_info(struct pack_desc* desc, int uLevel, char* id) { - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "B9"; break; - case 1: desc->format = "B9B21WWzW"; break; - case 2: desc->format = "z"; break; - case 3: desc->format = "zzzWWzzzWW"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; + desc->subformat = NULL; + switch( uLevel ) { + case 0: + desc->format = "B9"; + break; + case 1: + desc->format = "B9B21WWzW"; + break; + case 2: + desc->format = "z"; + break; + case 3: + desc->format = "zzzWWzzzWW"; + break; + default: + return False; + } + if (strcmp(desc->format,id) != 0) { + return False; + } + return True; } static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, struct pack_desc* desc) { - char buf[100]; - strncpy(buf,SERVICE(snum),sizeof(buf)-1); - buf[sizeof(buf)-1] = 0; - strupper_m(buf); - if (uLevel <= 1) { - PACKS(desc,"B9",buf); /* szName */ - if (uLevel == 1) { - PACKS(desc,"B21",""); /* szUserName */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"W",0); /* time */ - } - } - if (uLevel == 2 || uLevel == 3) { - PACKS(desc,"z",buf); /* pszPrinterName */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszUserName */ - PACKS(desc,"z",""); /* pszLogAddr */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",""); /* pszComment */ - PACKS(desc,"z","NULL"); /* pszDrivers */ - PACKI(desc,"W",0); /* time */ - PACKI(desc,"W",0); /* pad1 */ - } - } + char buf[100]; + + strncpy(buf,SERVICE(snum),sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; + strupper_m(buf); + + if (uLevel <= 1) { + PACKS(desc,"B9",buf); /* szName */ + if (uLevel == 1) { + PACKS(desc,"B21",""); /* szUserName */ + PACKI(desc,"W",0); /* uJobId */ + PACKI(desc,"W",0); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"W",0); /* time */ + } + } + + if (uLevel == 2 || uLevel == 3) { + PACKS(desc,"z",buf); /* pszPrinterName */ + if (uLevel == 3) { + PACKS(desc,"z",""); /* pszUserName */ + PACKS(desc,"z",""); /* pszLogAddr */ + PACKI(desc,"W",0); /* uJobId */ + PACKI(desc,"W",0); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKS(desc,"z",""); /* pszComment */ + PACKS(desc,"z","NULL"); /* pszDrivers */ + PACKI(desc,"W",0); /* time */ + PACKI(desc,"W",0); /* pad1 */ + } + } } static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -3231,60 +3397,64 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* PrinterName = p; - int uLevel; - struct pack_desc desc; - int snum; - char *tmpdata=NULL; - - memset((char *)&desc,'\0',sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - - DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - snum = find_service(PrinterName); - if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { - *rdata_len = 0; - desc.errcode = NERR_DestNotFound; - desc.neededlen = 0; - } - else { - if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - } else { - /* - * Don't return data but need to get correct length - * init_package will return wrong size if buflen=0 - */ - desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); - } - if (init_package(&desc,1,0)) { - fill_printdest_info(conn,snum,uLevel,&desc); - } - *rdata_len = desc.usedlen; - } - - *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); - SAFE_FREE(tmpdata); - return(True); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char* PrinterName = p; + int uLevel; + struct pack_desc desc; + int snum; + char *tmpdata=NULL; + + memset((char *)&desc,'\0',sizeof(desc)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); + + /* check it's a supported varient */ + if (strcmp(str1,"zWrLh") != 0) { + return False; + } + if (!check_printdest_info(&desc,uLevel,str2)) { + return False; + } + + snum = find_service(PrinterName); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { + *rdata_len = 0; + desc.errcode = NERR_DestNotFound; + desc.neededlen = 0; + } else { + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); + } + if (init_package(&desc,1,0)) { + fill_printdest_info(conn,snum,uLevel,&desc); + } + *rdata_len = desc.usedlen; + } + + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); + SAFE_FREE(tmpdata); + + return True; } static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -3292,56 +3462,68 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int queuecnt; - int i, n, succnt=0; - struct pack_desc desc; - int services = lp_numservices(); - - memset((char *)&desc,'\0',sizeof(desc)); - - uLevel = SVAL(p,0); - - DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,queuecnt,0)) { - succnt = 0; - n = 0; - for (i = 0; i < services; i++) { - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printdest_info(conn,i,uLevel,&desc); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); - - DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); - return(True); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int queuecnt; + int i, n, succnt=0; + struct pack_desc desc; + int services = lp_numservices(); + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + if (!check_printdest_info(&desc,uLevel,str2)) { + return False; + } + + queuecnt = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + queuecnt++; + } + } + + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + } + + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,queuecnt,0)) { + succnt = 0; + n = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + fill_printdest_info(conn,i,uLevel,&desc); + n++; + if (desc.errcode == NERR_Success) { + succnt = n; + } + } + } + } + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,queuecnt); + + DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); + + return True; } static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -3349,43 +3531,50 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int succnt; - struct pack_desc desc; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int succnt; + struct pack_desc desc; - memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = SVAL(p,0); - DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); + DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B41") != 0) return False; + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + if (uLevel != 0 || strcmp(str2,"B41") != 0) { + return False; + } + + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + } + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B41","NULL"); + } - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B41","NULL"); - } + succnt = (desc.errcode == NERR_Success ? 1 : 0); - succnt = (desc.errcode == NERR_Success ? 1 : 0); + *rdata_len = desc.usedlen; - *rdata_len = desc.usedlen; + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); + DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); - DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); - return(True); + return True; } static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -3393,44 +3582,51 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int succnt; - struct pack_desc desc; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int succnt; + struct pack_desc desc; - memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = SVAL(p,0); - DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); + DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + if (uLevel != 0 || strcmp(str2,"B13") != 0) { + return False; + } - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lpd"); - } + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + } + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B13","lpd"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); - succnt = (desc.errcode == NERR_Success ? 1 : 0); + *rdata_len = desc.usedlen; - *rdata_len = desc.usedlen; + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); + DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); - DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); - return(True); + return True; } static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -3438,45 +3634,52 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - int succnt; - struct pack_desc desc; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int succnt; + struct pack_desc desc; + + memset((char *)&desc,'\0',sizeof(desc)); - memset((char *)&desc,'\0',sizeof(desc)); + uLevel = SVAL(p,0); - uLevel = SVAL(p,0); + DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); - DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + if (uLevel != 0 || strcmp(str2,"B9") != 0) { + return False; + } - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + } + memset((char *)&desc,'\0',sizeof(desc)); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B13","lp0"); + } - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - memset((char *)&desc,'\0',sizeof(desc)); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lp0"); - } + succnt = (desc.errcode == NERR_Success ? 1 : 0); - succnt = (desc.errcode == NERR_Success ? 1 : 0); + *rdata_len = desc.usedlen; - *rdata_len = desc.usedlen; + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); - *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); + DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); - DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); - return(True); + return True; } @@ -3489,59 +3692,66 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - struct pack_desc desc; - struct sessionid *session_list; - int i, num_sessions; - - memset((char *)&desc,'\0',sizeof(desc)); - - uLevel = SVAL(p,0); - - DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel)); - DEBUG(7,("RNetSessionEnum req string=%s\n",str1)); - DEBUG(7,("RNetSessionEnum ret string=%s\n",str2)); - - /* check it's a supported varient */ - if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False; - if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False; - - num_sessions = list_sessions(&session_list); - - if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); - memset((char *)&desc,'\0',sizeof(desc)); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (!init_package(&desc,num_sessions,0)) { - return False; - } - - for(i=0; i 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + } + memset((char *)&desc,'\0',sizeof(desc)); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (!init_package(&desc,num_sessions,0)) { + return False; + } + + for(i=0; i 0;i++) { + /* Ensure all the usershares are loaded. */ + become_root(); + sharecount = load_usershare_shares(); + unbecome_root(); + + for(i=0;i < sharecount && (jn_max - jn_count) > 0;i++) { if(lp_msdfs_root(i)) { jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); } diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 9bc444d253..a824978ece 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -87,7 +87,7 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, id.uid = -1; - if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) { + if (psid && !sid_to_uid(psid, &id.uid)) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", sid_string_static(psid))); } @@ -131,7 +131,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, D.isoftlimit = limit_blk2inodes(D.softlimit); D.ihardlimit = limit_blk2inodes(D.hardlimit); - if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) { + if (psid && !sid_to_uid(psid, &id.uid)) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", sid_string_static(psid))); } @@ -185,10 +185,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) continue; } - if (!NT_STATUS_IS_OK(uid_to_sid(&sid, usr->pw_uid))) { - DEBUG(0,("uid_to_sid failed for %ld\n",(long)usr->pw_uid)); - continue; - } + uid_to_sid(&sid, usr->pw_uid); if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) { DEBUG(5,("no quota entry for sid[%s] path[%s]\n", diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e12a24968b..417e3421cb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2309,7 +2309,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou sid_parse(pdata+4,sid_len,&sid); DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid))); - if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) { + if (!sid_to_uid(&sid, &uid)) { DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n", sid_string_static(&sid),(unsigned long)sid_len)); uid = (-1); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4b13e28f8e..4f28e291cd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -22,6 +22,7 @@ #include "includes.h" +extern struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; extern uint16 global_smbpid; @@ -1018,15 +1019,6 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func } -/* Map generic permissions to file object specific permissions */ - -struct generic_mapping file_generic_mapping = { - FILE_GENERIC_READ, - FILE_GENERIC_WRITE, - FILE_GENERIC_EXECUTE, - FILE_GENERIC_ALL -}; - /**************************************************************************** Open a file with a share mode. ****************************************************************************/ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 764fbe8a2e..e644550400 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -100,7 +100,7 @@ void invalidate_vuid(uint16 vuid) session_yield(vuser); SAFE_FREE(vuser->session_keystr); - free_server_info(&vuser->server_info); + talloc_free(vuser->server_info); data_blob_free(&vuser->session_key); @@ -111,7 +111,7 @@ void invalidate_vuid(uint16 vuid) conn_clear_vuid_cache(vuid); SAFE_FREE(vuser->groups); - delete_nt_token(&vuser->nt_user_token); + talloc_free(vuser->nt_user_token); SAFE_FREE(vuser); num_validated_vuids--; } @@ -136,9 +136,11 @@ void invalidate_all_vuids(void) * @param server_info The token returned from the authentication process. * (now 'owned' by register_vuid) * - * @param session_key The User session key for the login session (now also 'owned' by register_vuid) + * @param session_key The User session key for the login session (now also + * 'owned' by register_vuid) * - * @param respose_blob The NT challenge-response, if available. (May be freed after this call) + * @param respose_blob The NT challenge-response, if available. (May be + * freed after this call) * * @param smb_name The untranslated name of the user * @@ -147,7 +149,9 @@ void invalidate_all_vuids(void) * */ -int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name) +int register_vuid(auth_serversupplied_info *server_info, + DATA_BLOB session_key, DATA_BLOB response_blob, + const char *smb_name) { user_struct *vuser = NULL; @@ -179,7 +183,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, next_vuid = VUID_OFFSET; } - DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid )); + DEBUG(10,("register_vuid: allocated vuid = %u\n", + (unsigned int)next_vuid )); vuser->vuid = next_vuid; @@ -203,11 +208,14 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, vuser->n_groups = server_info->n_groups; if (vuser->n_groups) { - if (!(vuser->groups = (gid_t *)memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { - DEBUG(0,("register_vuid: failed to memdup vuser->groups\n")); + if (!(vuser->groups = (gid_t *)memdup(server_info->groups, + sizeof(gid_t) * + vuser->n_groups))) { + DEBUG(0,("register_vuid: failed to memdup " + "vuser->groups\n")); data_blob_free(&session_key); free(vuser); - free_server_info(&server_info); + talloc_free(server_info); return UID_FIELD_INVALID; } } @@ -216,26 +224,35 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, fstrcpy(vuser->user.unix_name, server_info->unix_name); /* This is a potentially untrusted username */ - alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name)); + alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", + sizeof(vuser->user.smb_name)); fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); - fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); + fstrcpy(vuser->user.full_name, + pdb_get_fullname(server_info->sam_account)); { /* Keep the homedir handy */ - const char *homedir = pdb_get_homedir(server_info->sam_account); - const char *logon_script = pdb_get_logon_script(server_info->sam_account); - - if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) { - const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); + const char *homedir = + pdb_get_homedir(server_info->sam_account); + const char *logon_script = + pdb_get_logon_script(server_info->sam_account); + + if (!IS_SAM_DEFAULT(server_info->sam_account, + PDB_UNIXHOMEDIR)) { + const char *unix_homedir = + pdb_get_unix_homedir(server_info->sam_account); if (unix_homedir) { - vuser->unix_homedir = smb_xstrdup(unix_homedir); + vuser->unix_homedir = + smb_xstrdup(unix_homedir); } } else { - struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name); + struct passwd *passwd = + getpwnam_alloc(NULL, vuser->user.unix_name); if (passwd) { - vuser->unix_homedir = smb_xstrdup(passwd->pw_dir); - passwd_free(&passwd); + vuser->unix_homedir = + smb_xstrdup(passwd->pw_dir); + talloc_free(passwd); } } @@ -252,15 +269,18 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->uid, (unsigned int)vuser->gid, - vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest )); + vuser->user.unix_name, vuser->user.smb_name, + vuser->user.domain, vuser->guest )); - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name)); + DEBUG(3, ("User name: %s\tReal name: %s\n", vuser->user.unix_name, + vuser->user.full_name)); if (server_info->ptok) { - vuser->nt_user_token = dup_nt_token(server_info->ptok); + vuser->nt_user_token = dup_nt_token(NULL, server_info->ptok); } else { - DEBUG(1, ("server_info does not contain a user_token - cannot continue\n")); - free_server_info(&server_info); + DEBUG(1, ("server_info does not contain a user_token - " + "cannot continue\n")); + talloc_free(server_info); data_blob_free(&session_key); SAFE_FREE(vuser->homedir); SAFE_FREE(vuser->unix_homedir); @@ -273,7 +293,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, /* use this to keep tabs on all our info from the authentication */ vuser->server_info = server_info; - DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid)); + DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n", + (int)vuser->uid,vuser->user.unix_name, vuser->vuid)); next_vuid++; num_validated_vuids++; @@ -281,7 +302,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DLIST_ADD(validated_users, vuser); if (!session_claim(vuser)) { - DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid)); + DEBUG(1, ("Failed to claim session for vuid=%d\n", + vuser->vuid)); invalidate_vuid(vuser->vuid); return -1; } @@ -301,19 +323,26 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, int servicenumber = lp_servicenumber(vuser->user.unix_name); if ( servicenumber == -1 ) { - DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", + DEBUG(3, ("Adding homes service for user '%s' using " + "home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); - vuser->homes_snum = add_home_service(vuser->user.unix_name, - vuser->user.unix_name, vuser->unix_homedir); + vuser->homes_snum = + add_home_service(vuser->user.unix_name, + vuser->user.unix_name, + vuser->unix_homedir); } else { - DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n", - vuser->user.unix_name, lp_pathname(servicenumber) )); + DEBUG(3, ("Using static (or previously created) " + "service for user '%s'; path = '%s'\n", + vuser->user.unix_name, + lp_pathname(servicenumber) )); vuser->homes_snum = servicenumber; } } - if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) { - /* Try and turn on server signing on the first non-guest sessionsetup. */ + if (srv_is_signing_negotiated() && !vuser->guest && + !srv_signing_started()) { + /* Try and turn on server signing on the first non-guest + * sessionsetup. */ srv_set_signing(vuser->session_key, response_blob); } @@ -344,14 +373,19 @@ void add_session_user(const char *user) if( session_userlist && in_list(suser,session_userlist,False) ) return; - if( !session_userlist || (strlen(suser) + strlen(session_userlist) + 2 >= len_session_userlist) ) { + if( !session_userlist || + (strlen(suser) + strlen(session_userlist) + 2 >= + len_session_userlist) ) { char *newlist; if (len_session_userlist > 128 * PSTRING_LEN) { - DEBUG(3,("add_session_user: session userlist already too large.\n")); + DEBUG(3,("add_session_user: session userlist already " + "too large.\n")); return; } - newlist = (char *)SMB_REALLOC( session_userlist, len_session_userlist + PSTRING_LEN ); + newlist = (char *)SMB_REALLOC( + session_userlist, + len_session_userlist + PSTRING_LEN ); if( newlist == NULL ) { DEBUG(1,("Unable to resize session_userlist\n")); return; @@ -371,7 +405,7 @@ void add_session_user(const char *user) Check if a username is valid. ****************************************************************************/ -BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) +static BOOL user_ok(const char *user, int snum) { char **valid, **invalid; BOOL ret; @@ -387,8 +421,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) str_list_sub_basic(invalid, current_user_info.smb_name) ) { ret = !user_in_list(user, - (const char **)invalid, - groups, n_groups); + (const char **)invalid); } } } @@ -402,8 +435,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { - ret = user_in_list(user, (const char **)valid, - groups, n_groups); + ret = user_in_list(user, (const char **)valid); } } } @@ -415,8 +447,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) { - ret = user_in_list(user, (const char **)user_list, - groups, n_groups); + ret = user_in_list(user, (const char **)user_list); } if (user_list) str_list_free (&user_list); } @@ -436,7 +467,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) setnetgrent(group); while (getnetgrent(&host, &user, &domain)) { if (user) { - if (user_ok(user, snum, NULL, 0) && + if (user_ok(user, snum) && password_ok(user,password)) { endnetgrent(); return(user); @@ -472,12 +503,15 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) member = member_list; for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) { - size_t member_len = strlen(gptr->gr_mem[i]) + 1; - if( copied_len + member_len < sizeof(pstring)) { + size_t member_len = strlen(gptr->gr_mem[i])+1; + if(copied_len+member_len < sizeof(pstring)) { - DEBUG(10,("validate_group: = gr_mem = %s\n", gptr->gr_mem[i])); + DEBUG(10,("validate_group: = gr_mem = " + "%s\n", gptr->gr_mem[i])); - safe_strcpy(member, gptr->gr_mem[i], sizeof(pstring) - copied_len - 1); + safe_strcpy(member, gptr->gr_mem[i], + sizeof(pstring) - + copied_len - 1); copied_len += member_len; member += copied_len; } else { @@ -491,13 +525,14 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) while (*member) { static fstring name; fstrcpy(name,member); - if (user_ok(name,snum, NULL, 0) && + if (user_ok(name,snum) && password_ok(name,password)) { endgrent(); return(&name[0]); } - DEBUG(10,("validate_group = member = %s\n", member)); + DEBUG(10,("validate_group = member = %s\n", + member)); member += strlen(member) + 1; } @@ -558,7 +593,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, auser = strtok(NULL,LIST_SEP)) { fstring user2; fstrcpy(user2,auser); - if (!user_ok(user2,snum, NULL, 0)) + if (!user_ok(user2,snum)) continue; if (password_ok(user2,password)) { @@ -595,7 +630,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, } else { fstring user2; fstrcpy(user2,auser); - if (user_ok(user2,snum, NULL, 0) && + if (user_ok(user2,snum) && password_ok(user2,password)) { ok = True; fstrcpy(user,user2); @@ -624,7 +659,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, *guest = True; } - if (ok && !user_ok(user, snum, NULL, 0)) { + if (ok && !user_ok(user, snum)) { DEBUG(0,("authorise_login: rejected invalid user %s\n",user)); ok = False; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 5db245ac0c..d4dd926089 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -925,7 +925,7 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); - if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) { + if (!sid_to_uid(&owner_sid, puser)) { if (lp_force_unknown_acl_user(snum)) { /* this allows take ownership to work * reasonably */ @@ -946,7 +946,7 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); - if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) { + if (!sid_to_gid( &grp_sid, pgrp)) { if (lp_force_unknown_acl_user(snum)) { /* this allows take group ownership to work * reasonably */ @@ -1035,7 +1035,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) * not uids/gids. */ - return user_in_group_list(u_name, g_name, NULL, 0); + return user_in_group(u_name, g_name); } /**************************************************************************** @@ -1390,10 +1390,10 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, if (nt4_compatible_acls()) psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } else if (NT_STATUS_IS_OK(sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid))) { + } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid)) { current_ace->owner_type = UID_ACE; current_ace->type = SMB_ACL_USER; - } else if (NT_STATUS_IS_OK(sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid))) { + } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid)) { current_ace->owner_type = GID_ACE; current_ace->type = SMB_ACL_GROUP; } else { diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0b7b94cce2..d646ebe02d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -223,115 +223,6 @@ BOOL push_deferred_smb_message(uint16 mid, private_data, priv_len); } -static struct timed_event *timed_events; - -struct timed_event { - struct timed_event *next, *prev; - struct timeval when; - const char *event_name; - void (*handler)(struct timed_event *te, - const struct timeval *now, - void *private_data); - void *private_data; -}; - -static int timed_event_destructor(void *p) -{ - struct timed_event *te = talloc_get_type_abort(p, struct timed_event); - DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te, - te->event_name)); - DLIST_REMOVE(timed_events, te); - return 0; -} - -/**************************************************************************** - Schedule a function for future calling, cancel with talloc_free(). - It's the responsibility of the handler to call talloc_free() on the event - handed to it. -****************************************************************************/ - -struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx, - struct timeval when, - const char *event_name, - void (*handler)(struct timed_event *te, - const struct timeval *now, - void *private_data), - void *private_data) -{ - struct timed_event *te, *last_te, *cur_te; - - te = TALLOC_P(mem_ctx, struct timed_event); - if (te == NULL) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } - - te->when = when; - te->event_name = event_name; - te->handler = handler; - te->private_data = private_data; - - /* keep the list ordered */ - last_te = NULL; - for (cur_te = timed_events; cur_te; cur_te = cur_te->next) { - /* if the new event comes before the current one break */ - if (!timeval_is_zero(&cur_te->when) && - timeval_compare(&te->when, &cur_te->when) < 0) { - break; - } - last_te = cur_te; - } - - DLIST_ADD_AFTER(timed_events, te, last_te); - talloc_set_destructor(te, timed_event_destructor); - - DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name, - (unsigned long)te)); - return te; -} - -static void run_events(void) -{ - struct timeval now; - - if (timed_events == NULL) { - /* No syscall if there are no events */ - DEBUG(10, ("run_events: No events\n")); - return; - } - - GetTimeOfDay(&now); - - if (timeval_compare(&now, &timed_events->when) < 0) { - /* Nothing to do yet */ - DEBUG(10, ("run_events: Nothing to do\n")); - return; - } - - DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name, - (unsigned long)timed_events)); - - timed_events->handler(timed_events, &now, timed_events->private_data); - return; -} - -struct timeval timed_events_timeout(void) -{ - struct timeval now, timeout; - - if (timed_events == NULL) { - return timeval_set(SMBD_SELECT_TIMEOUT, 0); - } - - now = timeval_current(); - timeout = timeval_until(&now, &timed_events->when); - - DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec, - (int)timeout.tv_usec)); - - return timeout; -} - struct idle_event { struct timed_event *te; struct timeval interval; @@ -537,8 +428,10 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) } { - struct timeval tmp = timed_events_timeout(); - to = timeval_min(&to, &tmp); + struct timeval tmp; + struct timeval *tp = get_timed_events_timeout(&tmp,SMBD_SELECT_TIMEOUT); + + to = timeval_min(&to, tp); if (timeval_is_zero(&to)) { return True; } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index fc6a858974..ebc47c51d9 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -129,7 +129,7 @@ static void gain_root(void) Get the list of current groups. ****************************************************************************/ -int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups) +static int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups) { int i; gid_t grp; @@ -179,51 +179,6 @@ fail: return -1; } -/**************************************************************************** - Initialize the groups a user belongs to. -****************************************************************************/ - -BOOL initialise_groups(char *user, uid_t uid, gid_t gid) -{ - struct sec_ctx *prev_ctx_p; - BOOL result = True; - - if (non_root_mode()) { - return True; - } - - become_root(); - - /* Call initgroups() to get user groups */ - - if (winbind_initgroups(user,gid) == -1) { - DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); - if (getuid() == 0) { - if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { - DEBUG(0,("This is probably a problem with the account %s\n", user)); - } - } - result = False; - goto done; - } - - /* Store groups in previous user's security context. This will - always work as the become_root() call increments the stack - pointer. */ - - prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx - 1]; - - SAFE_FREE(prev_ctx_p->ut.groups); - prev_ctx_p->ut.ngroups = 0; - - get_current_groups(gid, &prev_ctx_p->ut.ngroups, &prev_ctx_p->ut.groups); - - done: - unbecome_root(); - - return result; -} - /**************************************************************************** Create a new security context on the stack. It is the same as the old one. User changes are done using the set_sec_ctx() function. @@ -252,14 +207,15 @@ BOOL push_sec_ctx(void) DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n", (unsigned int)ctx_p->ut.uid, (unsigned int)ctx_p->ut.gid, sec_ctx_stack_ndx )); - ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); + ctx_p->token = dup_nt_token(NULL, + sec_ctx_stack[sec_ctx_stack_ndx-1].token); ctx_p->ut.ngroups = sys_getgroups(0, NULL); if (ctx_p->ut.ngroups != 0) { if (!(ctx_p->ut.groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ut.ngroups))) { DEBUG(0, ("Out of memory in push_sec_ctx()\n")); - delete_nt_token(&ctx_p->token); + talloc_free(ctx_p->token); return False; } @@ -299,10 +255,10 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN if (token && (token == ctx_p->token)) smb_panic("DUPLICATE_TOKEN"); - delete_nt_token(&ctx_p->token); + talloc_free(ctx_p->token); ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups); - ctx_p->token = dup_nt_token(token); + ctx_p->token = dup_nt_token(NULL, token); become_id(uid, gid); @@ -355,7 +311,7 @@ BOOL pop_sec_ctx(void) SAFE_FREE(ctx_p->ut.groups); ctx_p->ut.ngroups = 0; - delete_nt_token(&ctx_p->token); + talloc_free(ctx_p->token); /* Pop back previous user */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3e970ec16c..6c2034988a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -62,6 +62,18 @@ static void smbd_set_server_fd(int fd) client_setfd(fd); } +/******************************************************************* + What to do when smb.conf is updated. + ********************************************************************/ + +static void smb_conf_updated(int msg_type, struct process_id src, + void *buf, size_t len) +{ + DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n")); + reload_services(False); +} + + /**************************************************************************** Terminate signal. ****************************************************************************/ @@ -331,6 +343,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ message_register(MSG_SMB_SAM_REPL, msg_sam_repl); message_register(MSG_SHUTDOWN, msg_exit_server); message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); + message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated); /* now accept incoming connections - forking a new process for each incoming connection */ @@ -697,6 +710,7 @@ void build_options(BOOL screen); int main(int argc,const char *argv[]) { + extern BOOL in_server; /* shall I run as a daemon */ static BOOL is_daemon = False; static BOOL interactive = False; @@ -718,6 +732,8 @@ void build_options(BOOL screen); { NULL } }; + in_server = True; + load_case_tables(); #ifdef HAVE_SET_AUTH_PARAMETERS @@ -826,11 +842,6 @@ void build_options(BOOL screen); init_structs(); - if (!init_guest_info()) { - DEBUG(0,("ERROR: failed to setup guest info.\n")); - return -1; - } - #ifdef WITH_PROFILE if (!profile_setup(False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); @@ -885,9 +896,6 @@ void build_options(BOOL screen); if (!locking_init(0)) exit(1); - if (!share_info_db_init()) - exit(1); - namecache_enable(); if (!init_registry()) @@ -901,6 +909,11 @@ void build_options(BOOL screen); if (!print_backend_init()) exit(1); + if (!init_guest_info()) { + DEBUG(0,("ERROR: failed to setup guest info.\n")); + return -1; + } + /* Setup the main smbd so that we can get messages. */ /* don't worry about general printing messages here */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 7640559d53..cf0116cc09 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -299,6 +299,13 @@ int find_service(fstring service) } } + /* Is it a usershare service ? */ + if (iService < 0 && *lp_usershare_path()) { + /* Ensure the name is canonicalized. */ + strlower_m(service); + iService = load_usershare_service(service); + } + if (iService >= 0) { if (!VALID_SNUM(iService)) { DEBUG(0,("Invalid snum %d for %s\n",iService, service)); @@ -359,6 +366,131 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } +static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest, + uid_t *uid, gid_t *gid, fstring username, + struct nt_user_token **token) +{ + TALLOC_CTX *mem_ctx; + char *fuser, *found_username; + NTSTATUS result; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_new failed\n")); + return NT_STATUS_NO_MEMORY; + } + + fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S", + lp_servicename(snum)); + if (fuser == NULL) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + result = create_token_from_username(mem_ctx, fuser, vuser_is_guest, + uid, gid, &found_username, + token); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + talloc_steal(NULL, *token); + fstrcpy(username, found_username); + + result = NT_STATUS_OK; + done: + talloc_free(mem_ctx); + return result; +} + +/* + * Go through lookup_name etc to find the force'd group. + * + * Create a new token from src_token, replacing the primary group sid with the + * one found. + */ + +static NTSTATUS find_forced_group(BOOL force_user, + int snum, const char *username, + DOM_SID *pgroup_sid, + gid_t *pgid) +{ + NTSTATUS result = NT_STATUS_NO_SUCH_GROUP; + TALLOC_CTX *mem_ctx; + DOM_SID group_sid; + enum SID_NAME_USE type; + char *groupname; + BOOL user_must_be_member = False; + gid_t gid; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_new failed\n")); + return NT_STATUS_NO_MEMORY; + } + + groupname = talloc_strdup(mem_ctx, lp_force_group(snum)); + if (groupname == NULL) { + DEBUG(1, ("talloc_strdup failed\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + + if (groupname[0] == '+') { + user_must_be_member = True; + groupname += 1; + } + + groupname = talloc_string_sub(mem_ctx, groupname, + "%S", lp_servicename(snum)); + + if (!lookup_name(mem_ctx, groupname, + LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, + NULL, NULL, &group_sid, &type)) { + DEBUG(10, ("lookup_name(%s) failed\n", + groupname)); + goto done; + } + + if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) && + (type != SID_NAME_WKN_GRP)) { + DEBUG(10, ("%s is a %s, not a group\n", groupname, + sid_type_lookup(type))); + goto done; + } + + if (!sid_to_gid(&group_sid, &gid)) { + DEBUG(10, ("sid_to_gid(%s) for %s failed\n", + sid_string_static(&group_sid), groupname)); + goto done; + } + + /* + * If the user has been forced and the forced group starts with a '+', + * then we only set the group to be the forced group if the forced + * user is a member of that group. Otherwise, the meaning of the '+' + * would be ignored. + */ + + if (force_user && user_must_be_member) { + if (user_in_group(username, groupname)) { + sid_copy(pgroup_sid, &group_sid); + *pgid = gid; + DEBUG(3,("Forced group %s for member %s\n", + groupname, username)); + } + } else { + sid_copy(pgroup_sid, &group_sid); + *pgid = gid; + DEBUG(3,("Forced group %s\n", groupname)); + } + + result = NT_STATUS_OK; + done: + talloc_free(mem_ctx); + return result; +} + /**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the connecting user if appropriate. @@ -395,7 +527,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (lp_guest_only(snum)) { const char *guestname = lp_guestaccount(); guest = True; - pass = getpwnam_alloc(guestname); + pass = getpwnam_alloc(NULL, guestname); if (!pass) { DEBUG(0,("make_connection_snum: Invalid guest " "account %s??\n",guestname)); @@ -408,7 +540,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->uid = pass->pw_uid; conn->gid = pass->pw_gid; string_set(&conn->user,pass->pw_name); - passwd_free(&pass); + talloc_free(pass); DEBUG(3,("Guest only user %s\n",user)); } else if (vuser) { if (vuser->guest) { @@ -421,8 +553,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } } else { - if (!user_ok(vuser->user.unix_name, snum, - vuser->groups, vuser->n_groups)) { + if (!user_ok_token(vuser->user.unix_name, + vuser->nt_user_token, snum)) { DEBUG(2, ("user '%s' (from session setup) not " "permitted to access this share " "(%s)\n", vuser->user.unix_name, @@ -501,86 +633,98 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->admin_user = False; /* - * If force user is true, then store the - * given userid and also the groups - * of the user we're forcing. + * If force user is true, then store the given userid and the gid of + * the user we're forcing. + * For auxiliary groups see below. */ if (*lp_force_user(snum)) { - struct passwd *pass2; - pstring fuser; - pstrcpy(fuser,lp_force_user(snum)); - - /* Allow %S to be used by force user. */ - pstring_sub(fuser,"%S",lp_servicename(snum)); - - pass2 = (struct passwd *)Get_Pwnam(fuser); - if (pass2) { - conn->uid = pass2->pw_uid; - conn->gid = pass2->pw_gid; - string_set(&conn->user,pass2->pw_name); - fstrcpy(user,pass2->pw_name); - conn->force_user = True; - DEBUG(3,("Forced user %s\n",user)); - } else { - DEBUG(1,("Couldn't find user %s\n",fuser)); + NTSTATUS status2; + + status2 = find_forced_user(snum, + (vuser != NULL) && vuser->guest, + &conn->uid, &conn->gid, user, + &conn->nt_user_token); + if (!NT_STATUS_IS_OK(status2)) { conn_free(conn); - *status = NT_STATUS_NO_SUCH_USER; + *status = status2; return NULL; } + string_set(&conn->user,user); + conn->force_user = True; + DEBUG(3,("Forced user %s\n",user)); } -#ifdef HAVE_GETGRNAM /* * If force group is true, then override * any groupid stored for the connecting user. */ if (*lp_force_group(snum)) { - gid_t gid; - pstring gname; - pstring tmp_gname; - BOOL user_must_be_member = False; - - pstrcpy(tmp_gname,lp_force_group(snum)); - - if (tmp_gname[0] == '+') { - user_must_be_member = True; - /* even now, tmp_gname is null terminated */ - pstrcpy(gname,&tmp_gname[1]); - } else { - pstrcpy(gname,tmp_gname); - } - /* default service may be a group name */ - pstring_sub(gname,"%S",lp_servicename(snum)); - gid = nametogid(gname); - - if (gid == (gid_t)-1) { - DEBUG(1,("Couldn't find group %s\n",gname)); + NTSTATUS status2; + DOM_SID group_sid; + + status2 = find_forced_group(conn->force_user, + snum, user, + &group_sid, &conn->gid); + if (!NT_STATUS_IS_OK(status2)) { conn_free(conn); - *status = NT_STATUS_NO_SUCH_GROUP; + *status = status2; return NULL; } - /* - * If the user has been forced and the forced group starts - * with a '+', then we only set the group to be the forced - * group if the forced user is a member of that group. - * Otherwise, the meaning of the '+' would be ignored. - */ - if (conn->force_user && user_must_be_member) { - if (user_in_group_list( user, gname, NULL, 0)) { - conn->gid = gid; - DEBUG(3,("Forced group %s for member %s\n", - gname,user)); + if ((conn->nt_user_token == NULL) && (vuser != NULL)) { + + /* Not force user and not security=share, but force + * group. vuser has a token to copy */ + + conn->nt_user_token = dup_nt_token( + NULL, vuser->nt_user_token); + if (conn->nt_user_token == NULL) { + DEBUG(0, ("dup_nt_token failed\n")); + conn_free(conn); + *status = NT_STATUS_NO_MEMORY; + return NULL; } - } else { - conn->gid = gid; - DEBUG(3,("Forced group %s\n",gname)); + } + + /* If conn->nt_user_token is still NULL, we have + * security=share. This means ignore the SID, as we had no + * vuser to copy from */ + + if (conn->nt_user_token != NULL) { + /* Overwrite the primary group sid */ + sid_copy(&conn->nt_user_token->user_sids[1], + &group_sid); + } conn->force_group = True; } -#endif /* HAVE_GETGRNAM */ + + if (conn->nt_user_token != NULL) { + size_t i; + + /* We have a share-specific token from force [user|group]. + * This means we have to create the list of unix groups from + * the list of sids. */ + + conn->ngroups = 0; + conn->groups = NULL; + + for (i=0; int_user_token->num_sids; i++) { + gid_t gid; + DOM_SID *sid = &conn->nt_user_token->user_sids[i]; + + if (!sid_to_gid(sid, &gid)) { + DEBUG(10, ("Could not convert SID %s to gid, " + "ignoring it\n", + sid_string_static(sid))); + continue; + } + add_gid_to_array_unique(NULL, gid, &conn->groups, + &conn->ngroups); + } + } { pstring s; @@ -591,25 +735,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, lp_servicename(snum))); } - if (conn->force_user || conn->force_group) { - int ngroups = 0; - - /* groups stuff added by ih */ - conn->ngroups = 0; - conn->groups = NULL; - - /* Find all the groups this uid is in and - store them. Used by change_to_user() */ - initialise_groups(conn->user, conn->uid, conn->gid); - get_current_groups(conn->gid, &ngroups, &conn->groups); - conn->ngroups = ngroups; - - conn->nt_user_token = - create_nt_token(conn->uid, conn->gid, - conn->ngroups, conn->groups, - guest); - } - /* * New code to check if there's a share security descripter * added from NT server manager. This is done after the diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a22a575c76..38e16126e2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -267,7 +267,7 @@ static int reply_spnego_kerberos(connection_struct *conn, map_username( user ); - pw = smb_getpwnam( user, real_username, True ); + pw = smb_getpwnam( mem_ctx, user, real_username, True ); if (!pw) { /* this was originally the behavior of Samba 2.2, if a user @@ -277,7 +277,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ map_domainuser_to_guest = True; fstrcpy(user,lp_guestaccount()); - pw = smb_getpwnam( user, real_username, True ); + pw = smb_getpwnam( mem_ctx, user, real_username, True ); } /* extra sanity check that the guest account is valid */ @@ -302,11 +302,11 @@ static int reply_spnego_kerberos(connection_struct *conn, ret = make_server_info_pac(&server_info, real_username, pw, logon_info); if ( !NT_STATUS_IS_OK(ret) ) { - DEBUG(1,("make_server_info_pac failed!\n")); + DEBUG(1,("make_server_info_pac failed: %s!\n", + nt_errstr(ret))); SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); - passwd_free(&pw); talloc_destroy(mem_ctx); return ERROR_NT(ret); } @@ -315,26 +315,24 @@ static int reply_spnego_kerberos(connection_struct *conn, ret = make_server_info_pw(&server_info, real_username, pw); if ( !NT_STATUS_IS_OK(ret) ) { - DEBUG(1,("make_server_info_from_pw failed!\n")); + DEBUG(1,("make_server_info_pw failed: %s!\n", + nt_errstr(ret))); SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); - passwd_free(&pw); talloc_destroy(mem_ctx); return ERROR_NT(ret); } - /* make_server_info_pw does not set the domain. Without this we end up - * with the local netbios name in substitutions for %D. */ + /* make_server_info_pw does not set the domain. Without this + * we end up with the local netbios name in substitutions for + * %D. */ if (server_info->sam_account != NULL) { pdb_set_domain(server_info->sam_account, domain, PDB_SET); } } - - passwd_free(&pw); - /* register_vuid keeps the server info */ /* register_vuid takes ownership of session_key, no need to free after this. A better interface would copy it.... */ @@ -1063,6 +1061,16 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(nt_status_squash(nt_status)); } + nt_status = create_local_token(server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(10, ("create_local_token failed: %s\n", + nt_errstr(nt_status))); + data_blob_free(&nt_resp); + data_blob_free(&lm_resp); + data_blob_clear_free(&plaintext_password); + return ERROR_NT(nt_status_squash(nt_status)); + } + if (server_info->user_session_key.data) { session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); } else { diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c new file mode 100644 index 0000000000..11e52b03ab --- /dev/null +++ b/source3/smbd/share_access.c @@ -0,0 +1,264 @@ +/* + Unix SMB/CIFS implementation. + Check access based on valid users, read list and friends + Copyright (C) Volker Lendecke 2005 + + 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" + +/* + * No prefix means direct username + * @name means netgroup first, then unix group + * &name means netgroup + * +name means unix group + * + and & may be combined + */ + +static BOOL do_group_checks(const char **name, const char **pattern) +{ + if ((*name)[0] == '@') { + *pattern = "&+"; + *name += 1; + return True; + } + + if (((*name)[0] == '+') && ((*name)[1] == '&')) { + *pattern = "+&"; + *name += 2; + return True; + } + + if ((*name)[0] == '+') { + *pattern = "+"; + *name += 1; + return True; + } + + if (((*name)[0] == '&') && ((*name)[1] == '+')) { + *pattern = "&+"; + *name += 2; + return True; + } + + if ((*name)[0] == '&') { + *pattern = "&"; + *name += 1; + return True; + } + + return False; +} + +static BOOL token_contains_name(TALLOC_CTX *mem_ctx, + const char *username, + const char *sharename, + const struct nt_user_token *token, + const char *name) +{ + const char *prefix; + DOM_SID sid; + enum SID_NAME_USE type; + + if (username != NULL) { + name = talloc_sub_basic(mem_ctx, username, name); + } + if (sharename != NULL) { + name = talloc_string_sub(mem_ctx, name, "%S", sharename); + } + + if (name == NULL) { + /* This is too security sensitive, better panic than return a + * result that might be interpreted in a wrong way. */ + smb_panic("substitutions failed\n"); + } + + if (!do_group_checks(&name, &prefix)) { + if (!lookup_name(mem_ctx, name, LOOKUP_NAME_ALL, + NULL, NULL, &sid, &type)) { + DEBUG(5, ("lookup_name %s failed\n", name)); + return False; + } + if (type != SID_NAME_USER) { + DEBUG(5, ("%s is a %s, expected a user\n", + name, sid_type_lookup(type))); + return False; + } + return nt_token_check_sid(&sid, token); + } + + for (/* initialized above */ ; *prefix != '\0'; prefix++) { + if (*prefix == '+') { + if (!lookup_name(mem_ctx, name, + LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, + NULL, NULL, &sid, &type)) { + DEBUG(5, ("lookup_name %s failed\n", name)); + return False; + } + if ((type != SID_NAME_DOM_GRP) && + (type != SID_NAME_ALIAS) && + (type != SID_NAME_WKN_GRP)) { + DEBUG(5, ("%s is a %s, expected a group\n", + name, sid_type_lookup(type))); + return False; + } + if (nt_token_check_sid(&sid, token)) { + return True; + } + continue; + } + if (*prefix == '&') { + if (user_in_netgroup(username, name)) { + return True; + } + continue; + } + smb_panic("got invalid prefix from do_groups_check\n"); + } + return False; +} + +/* + * Check whether a user is contained in the list provided. + * + * Please note that the user name and share names passed in here mainly for + * the substitution routines that expand the parameter values, the decision + * whether a user is in the list is done after a lookup_name on the expanded + * parameter value, solely based on comparing the SIDs in token. + * + * The other use is the netgroup check when using @group or &group. + */ + +BOOL token_contains_name_in_list(const char *username, + const char *sharename, + const struct nt_user_token *token, + const char **list) +{ + TALLOC_CTX *mem_ctx; + + if (list == NULL) { + return False; + } + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + smb_panic("talloc_new failed\n"); + } + + while (*list != NULL) { + if (token_contains_name(mem_ctx, username, sharename, + token, *list)) { + talloc_free(mem_ctx); + return True; + } + list += 1; + } + + talloc_free(mem_ctx); + return False; +} + +/* + * Check whether the user described by "token" has access to share snum. + * + * This looks at "invalid users", "valid users" and "only user/username" + * + * Please note that the user name and share names passed in here mainly for + * the substitution routines that expand the parameter values, the decision + * whether a user is in the list is done after a lookup_name on the expanded + * parameter value, solely based on comparing the SIDs in token. + * + * The other use is the netgroup check when using @group or &group. + */ + +BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum) +{ + if (lp_invalid_users(snum) != NULL) { + if (token_contains_name_in_list(username, lp_servicename(snum), + token, + lp_invalid_users(snum))) { + DEBUG(10, ("User %s in 'invalid users'\n", username)); + return False; + } + } + + if (lp_valid_users(snum) != NULL) { + if (!token_contains_name_in_list(username, + lp_servicename(snum), token, + lp_valid_users(snum))) { + DEBUG(10, ("User %s no in 'valid users'\n", username)); + return False; + } + } + + if (lp_onlyuser(snum)) { + const char *list[2]; + list[0] = lp_username(snum); + list[1] = NULL; + if (!token_contains_name_in_list(NULL, lp_servicename(snum), + token, list)) { + DEBUG(10, ("%s != 'username'\n", username)); + return False; + } + } + + DEBUG(10, ("user_ok_token: share %s is ok for unix user %s\n", + lp_servicename(snum), username)); + + return True; +} + +/* + * Check whether the user described by "token" is restricted to read-only + * access on share snum. + * + * This looks at "invalid users", "valid users" and "only user/username" + * + * Please note that the user name and share names passed in here mainly for + * the substitution routines that expand the parameter values, the decision + * whether a user is in the list is done after a lookup_name on the expanded + * parameter value, solely based on comparing the SIDs in token. + * + * The other use is the netgroup check when using @group or &group. + */ + +BOOL is_share_read_only_for_token(const char *username, + struct nt_user_token *token, int snum) +{ + BOOL result = lp_readonly(snum); + + if (lp_readlist(snum) != NULL) { + if (token_contains_name_in_list(username, + lp_servicename(snum), token, + lp_readlist(snum))) { + result = True; + } + } + + if (lp_writelist(snum) != NULL) { + if (token_contains_name_in_list(username, + lp_servicename(snum), token, + lp_writelist(snum))) { + result = False; + } + } + + DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user " + "%s\n", lp_servicename(snum), + result ? "read-only" : "read-write", username)); + + return result; +} diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index d419720c33..6e516d3562 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -56,7 +56,7 @@ BOOL change_to_guest(void) if (!pass) { /* Don't need to free() this as its stored in a static */ - pass = getpwnam_alloc(lp_guestaccount()); + pass = getpwnam_alloc(NULL, lp_guestaccount()); if (!pass) return(False); } @@ -71,67 +71,13 @@ BOOL change_to_guest(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; - - passwd_free(&pass); + talloc_free(pass); + pass = NULL; + return True; } -/**************************************************************************** - Readonly share for this user ? -****************************************************************************/ - -static BOOL is_share_read_only_for_user(int snum, user_struct *vuser) -{ - char **list; - const char *service = lp_servicename(snum); - BOOL read_only_ret = lp_readonly(snum); - - if (!service) - return read_only_ret; - - str_list_copy(&list, lp_readlist(snum)); - if (list) { - if (!str_list_sub_basic(list, vuser->user.smb_name) ) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: read " - "list substitution failed\n")); - } - if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: read " - "list service substitution failed\n")); - } - if (user_in_list(vuser->user.unix_name, (const char **)list, - vuser->groups, vuser->n_groups)) { - read_only_ret = True; - } - str_list_free(&list); - } - - str_list_copy(&list, lp_writelist(snum)); - if (list) { - if (!str_list_sub_basic(list, vuser->user.smb_name) ) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: write " - "list substitution failed\n")); - } - if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: write " - "list service substitution failed\n")); - } - if (user_in_list(vuser->user.unix_name, (const char **)list, - vuser->groups, vuser->n_groups)) { - read_only_ret = False; - } - str_list_free(&list); - } - - DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user " - "%s\n", service, - read_only_ret ? "read-only" : "read-write", - vuser->user.unix_name )); - - return read_only_ret; -} - /******************************************************************* Check if a username is OK. ********************************************************************/ @@ -151,20 +97,25 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) } } - if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups)) + if (!user_ok_token(vuser->user.unix_name, vuser->nt_user_token, snum)) return(False); - readonly_share = is_share_read_only_for_user(conn->service, vuser); + readonly_share = is_share_read_only_for_token(vuser->user.unix_name, + vuser->nt_user_token, + conn->service); if (!readonly_share && !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) { /* smb.conf allows r/w, but the security descriptor denies * write. Fall back to looking at readonly. */ readonly_share = True; - DEBUG(5,("falling back to read-only access-evaluation due to security descriptor\n")); + DEBUG(5,("falling back to read-only access-evaluation due to " + "security descriptor\n")); } - if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { + if (!share_access_check(conn, snum, vuser, + readonly_share ? + FILE_READ_DATA : FILE_WRITE_DATA)) { return False; } @@ -176,11 +127,9 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->vuid = vuser->vuid; ent->read_only = readonly_share; - if (user_in_list(vuser->user.unix_name ,lp_admin_users(conn->service), vuser->groups, vuser->n_groups)) { - ent->admin_user = True; - } else { - ent->admin_user = False; - } + ent->admin_user = token_contains_name_in_list( + vuser->user.unix_name, NULL, vuser->nt_user_token, + lp_admin_users(conn->service)); conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; @@ -217,20 +166,24 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && (current_user.ut.uid == conn->uid)) { - DEBUG(4,("change_to_user: Skipping user change - already user\n")); + DEBUG(4,("change_to_user: Skipping user change - already " + "user\n")); return(True); } else if ((current_user.conn == conn) && (vuser != 0) && (current_user.vuid == vuid) && (current_user.ut.uid == vuser->uid)) { - DEBUG(4,("change_to_user: Skipping user change - already user\n")); + DEBUG(4,("change_to_user: Skipping user change - already " + "user\n")); return(True); } snum = SNUM(conn); if ((vuser) && !check_user_ok(conn, vuser, snum)) { - DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) not permitted access to share %s.\n", - vuser->user.smb_name, vuser->user.unix_name, vuid, lp_servicename(snum))); + DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) " + "not permitted access to share %s.\n", + vuser->user.smb_name, vuser->user.unix_name, vuid, + lp_servicename(snum))); return False; } @@ -247,7 +200,8 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) current_user.ut.groups = vuser->groups; token = vuser->nt_user_token; } else { - DEBUG(2,("change_to_user: Invalid vuid used %d in accessing share %s.\n",vuid, lp_servicename(snum) )); + DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " + "share %s.\n",vuid, lp_servicename(snum) )); return False; } @@ -258,7 +212,13 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) */ if((group_c = *lp_force_group(snum))) { - BOOL is_guest = False; + + token = dup_nt_token(NULL, token); + if (token == NULL) { + DEBUG(0, ("dup_nt_token failed\n")); + return False; + } + must_free_token = True; if(group_c == '+') { @@ -273,37 +233,25 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) for (i = 0; i < current_user.ut.ngroups; i++) { if (current_user.ut.groups[i] == conn->gid) { gid = conn->gid; + gid_to_sid(&token->user_sids[1], gid); break; } } } else { gid = conn->gid; + gid_to_sid(&token->user_sids[1], gid); } - - /* - * We've changed the group list in the token - we must - * re-create it. - */ - - if (vuser && vuser->guest) - is_guest = True; - - token = create_nt_token(uid, gid, current_user.ut.ngroups, current_user.ut.groups, is_guest); - if (!token) { - DEBUG(1, ("change_to_user: create_nt_token failed!\n")); - return False; - } - must_free_token = True; } - set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, token); + set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, + token); /* * Free the new token (as set_sec_ctx copies it). */ if (must_free_token) - delete_nt_token(&token); + talloc_free(token); current_user.conn = conn; current_user.vuid = vuid; @@ -344,7 +292,8 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) return False; set_sec_ctx(p->pipe_user.ut.uid, p->pipe_user.ut.gid, - p->pipe_user.ut.ngroups, p->pipe_user.ut.groups, p->pipe_user.nt_user_token); + p->pipe_user.ut.ngroups, p->pipe_user.ut.groups, + p->pipe_user.nt_user_token); return True; } -- cgit From 43526112a309a0d353be43c0379acb9d5b4c495c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Feb 2006 22:42:49 +0000 Subject: r13318: remove an unused file (This used to be commit 5d373133cbed8fa40e3a9dcd08d27c35ddff96af) --- source3/smbd/tdbutil.c | 85 -------------------------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 source3/smbd/tdbutil.c (limited to 'source3/smbd') diff --git a/source3/smbd/tdbutil.c b/source3/smbd/tdbutil.c deleted file mode 100644 index cafcde2037..0000000000 --- a/source3/smbd/tdbutil.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Main SMB server routines - Copyright (C) Jeremy Allison 2003 - Copyright (C) Gerald (Jerry) Carter 2004 - - 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" - - -/********************************************************************** - logging function used by smbd to detect and remove corrupted tdb's -**********************************************************************/ - -void smbd_tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) -{ - va_list ap; - char *ptr = NULL; - BOOL decrement_smbd_count; - - va_start(ap, format); - vasprintf(&ptr, format, ap); - va_end(ap); - - if (!ptr || !*ptr) - return; - - DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); - - if (tdb->ecode == TDB_ERR_CORRUPT) { - int ret; - - DEBUG(0,("tdb_log: TDB %s is corrupt. Removing file and stopping this process.\n", - tdb->name )); - - become_root(); - ret = unlink(tdb->name); - if ( ret ) { - DEBUG(0,("ERROR: %s\n", strerror(errno))); - } - unbecome_root(); - - - /* if its not connections.tdb, then make sure we decrement the - smbd count. If connections.tdb is bad, there's nothing we - can do and everything will eventually shut down or clean - up anyways */ - - if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) - decrement_smbd_count = False; - else - decrement_smbd_count = True; - - /* now die */ - - smb_panic2("corrupt tdb\n", decrement_smbd_count ); - } - - if (tdb->ecode == TDB_ERR_IO) - { - if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 ) - decrement_smbd_count = False; - else - decrement_smbd_count = True; - - smb_panic2( "i/o error on tdb.\n", decrement_smbd_count ); - } - - SAFE_FREE(ptr); -} - -- cgit From 687e5be25e6090cf73867c3e08dab6a381c0adbc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Feb 2006 01:43:33 +0000 Subject: r13423: Write wrapper functions (and configure tests) so we can always assume we can get a struct timespec out of a stat struct. This will allow us to portably move to nsec timestamps on files and directories in the file server code in future. Jeremy. (This used to be commit 07132d8796a08aa71d6719cb07b5b2c999930632) --- source3/smbd/notify_hash.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index ee7d4314ee..859a92a61e 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -23,13 +23,8 @@ struct change_data { time_t last_check_time; /* time we last checked this entry */ -#ifdef HAVE_STAT_HIRES_TIMESTAMPS - struct timespec modify_time; - struct timespec status_time; -#else - time_t modify_time; /* Info from the directory we're monitoring. */ - time_t status_time; /* Info from the directory we're monitoring. */ -#endif + struct timespec modify_time; /* Info from the directory we're monitoring. */ + struct timespec status_time; /* Info from the directory we're monitoring. */ time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ unsigned int num_entries; /* Zero or the number of files in the directory. */ unsigned int mode_sum; @@ -37,13 +32,8 @@ struct change_data { }; -#ifdef HAVE_STAT_HIRES_TIMESTAMPS /* Compare struct timespec. */ #define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec)) -#else -/* Compare time_t . */ -#define TIMESTAMP_NEQ(x, y) ((x) != (y)) -#endif /**************************************************************************** Create the hash we will use to determine if the contents changed. @@ -66,13 +56,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, if(SMB_VFS_STAT(conn,path, &st) == -1) return False; -#ifdef HAVE_STAT_HIRES_TIMESTAMPS - data->modify_time = st.st_mtim; - data->status_time = st.st_ctim; -#else - data->modify_time = st.st_mtime; - data->status_time = st.st_ctime; -#endif + data->modify_time = get_mtimespec(&st); + data->status_time = get_ctimespec(&st); if (old_data) { /* -- cgit From e83c7d0141c0726a74c7be48914e94bac7167ab1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 10 Feb 2006 23:09:00 +0000 Subject: r13442: Implement samr_chgpasswd_user3 server-side. Guenther (This used to be commit f60eddc0a4dfe623e5f115533a62c03810fd5f38) --- source3/smbd/chgpasswd.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 0798541cb5..501aba3336 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -703,7 +703,8 @@ NTSTATUS pass_oem_change(char *user, uchar password_encrypted_with_lm_hash[516], const uchar old_lm_hash_encrypted[16], uchar password_encrypted_with_nt_hash[516], - const uchar old_nt_hash_encrypted[16]) + const uchar old_nt_hash_encrypted[16], + uint32 *reject_reason) { pstring new_passwd; SAM_ACCOUNT *sampass = NULL; @@ -718,7 +719,7 @@ NTSTATUS pass_oem_change(char *user, /* We've already checked the old password here.... */ become_root(); - nt_status = change_oem_password(sampass, NULL, new_passwd, True); + nt_status = change_oem_password(sampass, NULL, new_passwd, True, reject_reason); unbecome_root(); memset(new_passwd, 0, sizeof(new_passwd)); @@ -1007,7 +1008,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) is correct before calling. JRA. ************************************************************/ -NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) +NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason) { uint32 min_len, min_age; struct passwd *pass = NULL; @@ -1040,11 +1041,17 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw DEBUG(1, ("user %s cannot change password - password too short\n", username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_TOO_SHORT; + } return NT_STATUS_PASSWORD_RESTRICTION; /* return NT_STATUS_PWD_TOO_SHORT; */ } if (check_passwd_history(hnd,new_passwd)) { + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_IN_HISTORY; + } return NT_STATUS_PASSWORD_RESTRICTION; } @@ -1063,6 +1070,9 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw if (check_ret != 0) { DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n")); + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_NOT_COMPLEX; + } return NT_STATUS_PASSWORD_RESTRICTION; } } -- cgit From fbf45d8ce90e88233ce386c1275d38fed3974433 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 10 Feb 2006 23:23:10 +0000 Subject: r13443: Fix the build. Guenther (This used to be commit 40a21776a7a16f3200e87c6564d9b6e8c481dd1e) --- source3/smbd/lanman.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 83dfdf0d8b..a2ec6f34b8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2214,7 +2214,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { become_root(); - if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) { + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) { SSVAL(*rparam,0,NERR_Success); } unbecome_root(); @@ -2297,7 +2297,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * (void)map_username(user); - if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) { + if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) { SSVAL(*rparam,0,NERR_Success); } -- cgit From 72b30eba6463cd4479b4f2c5076209bf77e4fc57 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 10 Feb 2006 23:41:41 +0000 Subject: r13444: Add REJECT_REASON_OTHER for samr_chgpasswd_user3 Guenther (This used to be commit 58baf718be90d750f51cf51a25714fcdcd5679b7) --- source3/smbd/chgpasswd.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 501aba3336..e04e902b3a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1016,6 +1016,10 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw time_t last_change_time = pdb_get_pass_last_set_time(hnd); time_t can_change_time = pdb_get_pass_can_change_time(hnd); + if (samr_reject_reason) { + *samr_reject_reason = Undefined; + } + if (pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age)) { /* * Windows calculates the minimum password age check @@ -1026,6 +1030,9 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw DEBUG(1, ("user %s cannot change password now, must " "wait until %s\n", username, http_timestring(last_change_time+min_age))); + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_OTHER; + } return NT_STATUS_ACCOUNT_RESTRICTION; } } else { @@ -1033,6 +1040,9 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw DEBUG(1, ("user %s cannot change password now, must " "wait until %s\n", username, http_timestring(can_change_time))); + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_OTHER; + } return NT_STATUS_ACCOUNT_RESTRICTION; } } -- cgit From 8fbdd112b2c69a54d05807163bfc52b34f4d0424 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 13 Feb 2006 04:07:15 +0000 Subject: r13482: Push the FAM notification file descriptor into the select set to avoid unnecessary polling. (This used to be commit 1dce945ccbba25092cf54890301c8f78f8aede33) --- source3/smbd/notify.c | 9 +++++++++ source3/smbd/notify_fam.c | 36 +++++++++++++++++++++++------------- source3/smbd/notify_hash.c | 1 + source3/smbd/notify_kernel.c | 1 + source3/smbd/oplock.c | 15 +++++---------- source3/smbd/process.c | 25 ++++++++++++++++++++----- 6 files changed, 59 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index df3d45d20b..b2d0fc3326 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -206,6 +206,15 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, return True; } +int change_notify_fd(void) +{ + if (cnotify) { + return cnotify->notification_fd; + } + + return -1; +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index 413340266e..9f02bfdee9 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -63,9 +63,30 @@ static int global_fc_generation; #define FAM_TRACE 8 #define FAM_TRACE_LOW 10 -#define FAM_NOTIFY_CHECK_TIMEOUT 1 /* secs */ #define FAM_EVENT_DRAIN ((uint32_t)(-1)) +static void * fam_register_notify(connection_struct * conn, + char * path, + uint32 flags); + +static BOOL fam_check_notify(connection_struct * conn, + uint16_t vuid, + char * path, + uint32_t flags, + void * data, + time_t when); + +static void fam_remove_notify(void * data) + +static struct cnotify_fns global_fam_notify = +{ + fam_register_notify, + fam_check_notify, + fam_remove_notify, + -1, + -1 +}; + /* Turn a FAM event code into a string. Don't rely on specific code values, * because that might not work across all flavours of FAM. */ @@ -110,6 +131,7 @@ fam_check_reconnect(void) } } + global_fam_notify.notification_fd = FAMCONNECTION_GETFD(&global_fc); return(True); } @@ -420,18 +442,6 @@ fam_remove_notify(void * data) struct cnotify_fns * fam_notify_init(void) { - static struct cnotify_fns global_fam_notify = - { - fam_register_notify, - fam_check_notify, - fam_remove_notify, - FAM_NOTIFY_CHECK_TIMEOUT - }; - - /* TODO: rather than relying on FAM_NOTIFY_CHECK_TIMEOUT, we should have an - * API to push the FAM fd into the global server fd set. - */ - FAMCONNECTION_GETFD(&global_fc) = -1; if (!fam_test_connection()) { diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 859a92a61e..a98a028fae 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -230,6 +230,7 @@ struct cnotify_fns *hash_notify_init(void) cnotify.check_notify = hash_check_notify; cnotify.remove_notify = hash_remove_notify; cnotify.select_time = lp_change_notify_timeout(); + cnotify.notification_fd = -1; return &cnotify; } diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 02abe0b4b6..0c20effc3d 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -232,6 +232,7 @@ struct cnotify_fns *kernel_notify_init(void) cnotify.check_notify = kernel_check_notify; cnotify.remove_notify = kernel_remove_notify; cnotify.select_time = -1; + cnotify.notification_fd = -1; /* the signal can start off blocked due to a bug in bash */ BlockSignals(False, RT_SIGNAL_NOTIFY); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 755bcffc7f..41eb809909 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -240,21 +240,16 @@ BOOL downgrade_oplock(files_struct *fsp) } /**************************************************************************** - Setup the listening set of file descriptors for an oplock break - message either from the UDP socket or from the kernel. Returns the maximum - fd used. + Return the fd (if any) used for receiving oplock notifications. ****************************************************************************/ -int setup_oplock_select_set( fd_set *fds) +int oplock_notify_fd(void) { - int maxfd = 0; - - if (koplocks && koplocks->notification_fd != -1) { - FD_SET(koplocks->notification_fd, fds); - maxfd = MAX(maxfd, koplocks->notification_fd); + if (koplocks) { + return koplocks->notification_fd; } - return maxfd; + return -1; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d646ebe02d..2f19f909f2 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -283,7 +283,7 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, return result; } - + /**************************************************************************** Do all async processing in here. This includes kernel oplock messages, change notify events etc. @@ -318,6 +318,20 @@ static void async_processing(void) } } +/**************************************************************************** + Add a fd to the set we will be select(2)ing on. +****************************************************************************/ + +static int select_on_fd(int fd, int maxfd, fd_set *fds) +{ + if (fd != -1) { + FD_SET(fd, fds); + maxfd = MAX(maxfd, fd); + } + + return maxfd; +} + /**************************************************************************** Do a select on an two fd's - with timeout. @@ -344,7 +358,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) fd_set fds; int selrtn; struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0); - int maxfd; + int maxfd = 0; smb_read_error = 0; @@ -437,10 +451,11 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) } } - FD_SET(smbd_server_fd(),&fds); - maxfd = setup_oplock_select_set(&fds); + maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds); + maxfd = select_on_fd(change_notify_fd(), maxfd, &fds); + maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds); - selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to); + selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but -- cgit From 8d1b17f50e27aa124bcf6a23886e0781e4b2b6bb Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 13 Feb 2006 04:29:42 +0000 Subject: r13484: Add missing semi-colon. (This used to be commit a78d94f539e41ac384e09cd6e44cb611dd8e1570) --- source3/smbd/notify_fam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index 9f02bfdee9..dd1e5b709e 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -76,7 +76,7 @@ static BOOL fam_check_notify(connection_struct * conn, void * data, time_t when); -static void fam_remove_notify(void * data) +static void fam_remove_notify(void * data); static struct cnotify_fns global_fam_notify = { -- cgit From 301d51e13a1aa4e633e2da161b0dd260a8a499cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Feb 2006 17:08:25 +0000 Subject: r13494: Merge the stuff I've done in head the last days. Volker (This used to be commit bb40e544de68f01a6e774753f508e69373b39899) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/map_username.c | 178 ++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/password.c | 129 ++++++++++++++++++++++++++++++++ source3/smbd/posix_acls.c | 10 +-- source3/smbd/service.c | 2 +- 5 files changed, 310 insertions(+), 11 deletions(-) create mode 100644 source3/smbd/map_username.c (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e04e902b3a..8f3e7236c4 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1067,7 +1067,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw pass = Get_Pwnam(username); if (!pass) { - DEBUG(1, ("check_oem_password: Username %s does not exist in system !?!\n", username)); + DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username)); return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c new file mode 100644 index 0000000000..a6025fcf47 --- /dev/null +++ b/source3/smbd/map_username.c @@ -0,0 +1,178 @@ +/* + Unix SMB/CIFS implementation. + Username handling + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1997-2001. + Copyright (C) Volker Lendecke 2006 + + 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" + +/******************************************************************* + Map a username from a dos name to a unix name by looking in the username + map. Note that this modifies the name in place. + This is the main function that should be called *once* on + any incoming or new username - in order to canonicalize the name. + This is being done to de-couple the case conversions from the user mapping + function. Previously, the map_username was being called + every time Get_Pwnam was called. + Returns True if username was changed, false otherwise. +********************************************************************/ + +BOOL map_username(fstring user) +{ + static BOOL initialised=False; + static fstring last_from,last_to; + XFILE *f; + char *mapfile = lp_username_map(); + char *s; + pstring buf; + BOOL mapped_user = False; + char *cmd = lp_username_map_script(); + + if (!*user) + return False; + + if (strequal(user,last_to)) + return False; + + if (strequal(user,last_from)) { + DEBUG(3,("Mapped user %s to %s\n",user,last_to)); + fstrcpy(user,last_to); + return True; + } + + /* first try the username map script */ + + if ( *cmd ) { + char **qlines; + pstring command; + int numlines, ret, fd; + + pstr_sprintf( command, "%s \"%s\"", cmd, user ); + + DEBUG(10,("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10,("returned [%d]\n", ret)); + + if ( ret != 0 ) { + if (fd != -1) + close(fd); + return False; + } + + numlines = 0; + qlines = fd_lines_load(fd, &numlines,0); + DEBUGADD(10,("Lines returned = [%d]\n", numlines)); + close(fd); + + /* should be either no lines or a single line with the mapped username */ + + if (numlines) { + DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] )); + fstrcpy( user, qlines[0] ); + } + + file_lines_free(qlines); + + return numlines != 0; + } + + /* ok. let's try the mapfile */ + + if (!*mapfile) + return False; + + if (!initialised) { + *last_from = *last_to = 0; + initialised = True; + } + + f = x_fopen(mapfile,O_RDONLY, 0); + if (!f) { + DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) )); + return False; + } + + DEBUG(4,("Scanning username map %s\n",mapfile)); + + while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) { + char *unixname = s; + char *dosname = strchr_m(unixname,'='); + char **dosuserlist; + BOOL return_if_mapped = False; + + if (!dosname) + continue; + + *dosname++ = 0; + + while (isspace((int)*unixname)) + unixname++; + + if ('!' == *unixname) { + return_if_mapped = True; + unixname++; + while (*unixname && isspace((int)*unixname)) + unixname++; + } + + if (!*unixname || strchr_m("#;",*unixname)) + continue; + + { + int l = strlen(unixname); + while (l && isspace((int)unixname[l-1])) { + unixname[l-1] = 0; + l--; + } + } + + dosuserlist = str_list_make(dosname, NULL); + if (!dosuserlist) { + DEBUG(0,("Unable to build user list\n")); + return False; + } + + if (strchr_m(dosname,'*') || + user_in_list(user, (const char **)dosuserlist)) { + DEBUG(3,("Mapped user %s to %s\n",user,unixname)); + mapped_user = True; + fstrcpy( last_from,user ); + fstrcpy( user, unixname ); + fstrcpy( last_to,user ); + if ( return_if_mapped ) { + str_list_free (&dosuserlist); + x_fclose(f); + return True; + } + } + + str_list_free (&dosuserlist); + } + + x_fclose(f); + + /* + * Setup the last_from and last_to as an optimization so + * that we don't scan the file again for the same user. + */ + fstrcpy(last_from,user); + fstrcpy(last_to,user); + + return mapped_user; +} diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e644550400..0eeb537ded 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -401,6 +401,135 @@ void add_session_user(const char *user) safe_strcat(session_userlist,suser,len_session_userlist-1); } +/**************************************************************************** + Check if a user is in a netgroup user list. If at first we don't succeed, + try lower case. +****************************************************************************/ + +BOOL user_in_netgroup(const char *user, const char *ngname) +{ +#ifdef HAVE_NETGROUP + static char *mydomain = NULL; + fstring lowercase_user; + + if (mydomain == NULL) + yp_get_default_domain(&mydomain); + + if(mydomain == NULL) { + DEBUG(5,("Unable to get default yp domain\n")); + return False; + } + + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + user, mydomain, ngname)); + + if (innetgr(ngname, NULL, user, mydomain)) { + DEBUG(5,("user_in_netgroup: Found\n")); + return (True); + } else { + + /* + * Ok, innetgr is case sensitive. Try once more with lowercase + * just in case. Attempt to fix #703. JRA. + */ + + fstrcpy(lowercase_user, user); + strlower_m(lowercase_user); + + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + lowercase_user, mydomain, ngname)); + + if (innetgr(ngname, NULL, lowercase_user, mydomain)) { + DEBUG(5,("user_in_netgroup: Found\n")); + return (True); + } + } +#endif /* HAVE_NETGROUP */ + return False; +} + +/**************************************************************************** + Check if a user is in a user list - can check combinations of UNIX + and netgroup lists. +****************************************************************************/ + +BOOL user_in_list(const char *user,const char **list) +{ + if (!list || !*list) + return False; + + DEBUG(10,("user_in_list: checking user %s in list\n", user)); + + while (*list) { + + DEBUG(10,("user_in_list: checking user |%s| against |%s|\n", + user, *list)); + + /* + * Check raw username. + */ + if (strequal(user, *list)) + return(True); + + /* + * Now check to see if any combination + * of UNIX and netgroups has been specified. + */ + + if(**list == '@') { + /* + * Old behaviour. Check netgroup list + * followed by UNIX list. + */ + if(user_in_netgroup(user, *list +1)) + return True; + if(user_in_group(user, *list +1)) + return True; + } else if (**list == '+') { + + if((*(*list +1)) == '&') { + /* + * Search UNIX list followed by netgroup. + */ + if(user_in_group(user, *list +2)) + return True; + if(user_in_netgroup(user, *list +2)) + return True; + + } else { + + /* + * Just search UNIX list. + */ + + if(user_in_group(user, *list +1)) + return True; + } + + } else if (**list == '&') { + + if(*(*list +1) == '+') { + /* + * Search netgroup list followed by UNIX list. + */ + if(user_in_netgroup(user, *list +2)) + return True; + if(user_in_group(user, *list +2)) + return True; + } else { + /* + * Just search netgroup list. + */ + if(user_in_netgroup(user, *list +1)) + return True; + } + } + + list++; + } + return(False); +} + /**************************************************************************** Check if a username is valid. ****************************************************************************/ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d4dd926089..2befca40c2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1015,7 +1015,6 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type) static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) { fstring u_name; - fstring g_name; /* "Everyone" always matches every uid. */ @@ -1028,14 +1027,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) return True; fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); - fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid)); - - /* - * Due to the winbind interfaces we need to do this via names, - * not uids/gids. - */ - - return user_in_group(u_name, g_name); + return user_in_group_sid(u_name, &group_ace->trustee); } /**************************************************************************** diff --git a/source3/smbd/service.c b/source3/smbd/service.c index cf0116cc09..0fce677ea9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -473,7 +473,7 @@ static NTSTATUS find_forced_group(BOOL force_user, */ if (force_user && user_must_be_member) { - if (user_in_group(username, groupname)) { + if (user_in_group_sid(username, &group_sid)) { sid_copy(pgroup_sid, &group_sid); *pgid = gid; DEBUG(3,("Forced group %s for member %s\n", -- cgit From 7f7c9849e4aed9ff7b51989a81f6039c5b59f2dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Feb 2006 20:26:38 +0000 Subject: r13497: Fix #3508 from jason@ncac.gwu.edu Jeremy. (This used to be commit a28bc614a0eb8409a98b254b32ad17c50c2eec0e) --- source3/smbd/posix_acls.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2befca40c2..d4801d1743 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4210,7 +4210,6 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) { SEC_DESC *psd, *ret_sd; - size_t sd_size; connection_struct conn; files_struct finfo; struct fd_handle fh; @@ -4221,7 +4220,7 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) conn.service = -1; if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) { - DEBUG(0,("novfs_get_nt_acl: talloc() failed!\n")); + DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); return NULL; } @@ -4229,7 +4228,8 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) set_conn_connectpath(&conn, path); if (!smbd_vfs_init(&conn)) { - DEBUG(0,("novfs_get_nt_acl: Unable to create a fake connection struct!\n")); + DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n")); + conn_free_internal( &conn ); return NULL; } @@ -4243,7 +4243,11 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) pstrcpy( filename, fname ); finfo.fsp_name = filename; - sd_size = get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ); + if (get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ) == 0) { + DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); + conn_free_internal( &conn ); + return NULL; + } ret_sd = dup_sec_desc( ctx, psd ); -- cgit From 5c149702b0885db8d63f189f4bba0e17fdaad7a4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Feb 2006 23:00:39 +0000 Subject: r13498: Fix the kernel oplocks code for IRIX. Should fix #3515. Jeremy. (This used to be commit 006cf9c3654e7f18e01b75a5fe87798df862d26a) --- source3/smbd/oplock.c | 23 +++++++---------------- source3/smbd/oplock_irix.c | 27 ++++++++++++++++++++++++++- source3/smbd/process.c | 12 ++++++------ 3 files changed, 39 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 41eb809909..3efd630649 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -56,23 +56,14 @@ BOOL oplock_message_waiting(fd_set *fds) } /**************************************************************************** - Read an oplock break message from either the oplock UDP fd or the - kernel (if kernel oplocks are supported). - - If timeout is zero then *fds contains the file descriptors that - are ready to be read and acted upon. If timeout is non-zero then - *fds contains the file descriptors to be selected on for read. - The timeout is in milliseconds - + Find out if there are any kernel oplock messages waiting and process them + if so. pfds is the fd_set from the main select loop (which contains any + kernel oplock fd if that's what the system uses (IRIX). If may be NULL if + we're calling this in a shutting down state. ****************************************************************************/ -void process_kernel_oplocks(void) +void process_kernel_oplocks(fd_set *pfds) { - fd_set fds; - - FD_ZERO(&fds); - smb_read_error = 0; - /* * We need to check for kernel oplocks before going into the select * here, as the EINTR generated by the linux kernel oplock may have @@ -83,11 +74,11 @@ void process_kernel_oplocks(void) return; } - while (koplocks->msg_waiting(&fds)) { + while (koplocks->msg_waiting(pfds)) { files_struct *fsp; char msg[MSG_SMB_KERNEL_BREAK_SIZE]; - fsp = koplocks->receive_message(&fds); + fsp = koplocks->receive_message(pfds); if (fsp == NULL) { DEBUG(3, ("Kernel oplock message announced, but none " diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 2224f9a668..29bbb0f2ca 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -93,6 +93,9 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) char dummy; files_struct *fsp; + /* Ensure we only get one call per select fd set. */ + FD_CLR(fds, oplock_pipe_read); + /* * Read one byte of zero to clear the * kernel break notify message. @@ -204,14 +207,36 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, /**************************************************************************** Set *maxfd to include oplock read pipe. + Note that fds MAY BE NULL ! If so we must do our own select. ****************************************************************************/ static BOOL irix_oplock_msg_waiting(fd_set *fds) { + int maxfd, selrtn; + fd_set myfds; + struct timeval to; + if (oplock_pipe_read == -1) return False; - return FD_ISSET(oplock_pipe_read,fds); + if (fds) { + return FD_ISSET(oplock_pipe_read,fds); + } + + FD_ZERO(&myfds); + maxfd = setup_oplock_select_set(&myfds); + /* Only do the select if we have something to select *on*. */ + if (maxfd == 0) { + return False; + } + + /* Do a zero-time select. We just need to find out if there + * are any outstanding messages. We use sys_select_intr as + * we need to ignore any signals. */ + + to = timeval_set(0, 0); + selrtn = sys_select_intr(maxfd+1,&myfds,NULL,NULL,&to); + return (selrtn == 1) ? True : False; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2f19f909f2..9d35252e28 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -289,13 +289,13 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, notify events etc. ****************************************************************************/ -static void async_processing(void) +static void async_processing(fd_set *pfds) { DEBUG(10,("async_processing: Doing async processing.\n")); process_aio_queue(); - process_kernel_oplocks(); + process_kernel_oplocks(pfds); /* Do the aio check again after receive_local_message as it does a select and may have eaten our signal. */ @@ -432,7 +432,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) if (oplock_message_waiting(&fds)) { DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n")); - async_processing(); + async_processing(&fds); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -462,7 +462,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) is the best we can do until the oplock code knows more about signals */ if (selrtn == -1 && errno == EINTR) { - async_processing(); + async_processing(&fds); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -491,7 +491,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ if (oplock_message_waiting(&fds)) { - async_processing(); + async_processing(&fds); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -540,7 +540,7 @@ void respond_to_all_remaining_local_messages(void) return; } - process_kernel_oplocks(); + process_kernel_oplocks(NULL); return; } -- cgit From 0c0ce531a87f7e5f5a1a2980335322615a98c037 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 15 Feb 2006 01:05:06 +0000 Subject: r13500: Fix ordering of FD_* arguments. (This used to be commit ed619421de024c44f5f05b3c03bb5311ce73830f) --- source3/smbd/oplock_irix.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 29bbb0f2ca..fa86211c7f 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -94,7 +94,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) files_struct *fsp; /* Ensure we only get one call per select fd set. */ - FD_CLR(fds, oplock_pipe_read); + FD_CLR(oplock_pipe_read, fds); /* * Read one byte of zero to clear the @@ -220,22 +220,18 @@ static BOOL irix_oplock_msg_waiting(fd_set *fds) return False; if (fds) { - return FD_ISSET(oplock_pipe_read,fds); - } - - FD_ZERO(&myfds); - maxfd = setup_oplock_select_set(&myfds); - /* Only do the select if we have something to select *on*. */ - if (maxfd == 0) { - return False; + return FD_ISSET(oplock_pipe_read, fds); } /* Do a zero-time select. We just need to find out if there * are any outstanding messages. We use sys_select_intr as * we need to ignore any signals. */ + FD_ZERO(&myfds); + FD_SET(oplock_pipe_read, &myfds); + to = timeval_set(0, 0); - selrtn = sys_select_intr(maxfd+1,&myfds,NULL,NULL,&to); + selrtn = sys_select_intr(oplock_pipe_read+1,&myfds,NULL,NULL,&to); return (selrtn == 1) ? True : False; } -- cgit From 51e8dc417bdfe009d0fd2dc3eb77cb1346016318 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 18 Feb 2006 02:02:11 +0000 Subject: r13559: Fix bug #3522 reported by Sandeep Tamhankar . mkdir foo returns the wrong error message when file foo exists. Jeremy. (This used to be commit c8185e7f94cbcf2125bf0e84db02fb8d19111f60) --- source3/smbd/open.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4f28e291cd..3e555a8f31 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1802,12 +1802,6 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - if (dir_existed && !S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); - return NULL; - } - switch( create_disposition ) { case FILE_OPEN: /* If directory exists open. If directory doesn't -- cgit From a4d755dacc8e72b6a5f7743f03760fba5810d743 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 19 Feb 2006 21:01:21 +0000 Subject: r13563: Fix bug #3526 found and diagnosed by corinna@vinschen.de. trans2findfirst recognises two info levels *not* recognised by trans2findnext. Add them. Needed for 3.0.21c. Jeremy. (This used to be commit bcb87271d60acd4efe666dd061ea2c09b72fd497) --- source3/smbd/trans2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b8fc2b5b8f..9c46fec790 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1927,6 +1927,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + case SMB_FIND_ID_FULL_DIRECTORY_INFO: + case SMB_FIND_ID_BOTH_DIRECTORY_INFO: break; case SMB_FIND_FILE_UNIX: if (!lp_unix_extensions()) -- cgit From fb5362c069b5b6548478b2217a0519c56d856705 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 20 Feb 2006 17:59:58 +0000 Subject: r13571: Replace all calls to talloc_free() with thye TALLOC_FREE() macro which sets the freed pointer to NULL. (This used to be commit b65be8874a2efe5a4b167448960a4fcf6bd995e2) --- source3/smbd/close.c | 4 ++-- source3/smbd/conn.c | 2 +- source3/smbd/lanman.c | 4 ++-- source3/smbd/open.c | 24 ++++++++++++------------ source3/smbd/oplock.c | 16 ++++++++-------- source3/smbd/password.c | 10 +++++----- source3/smbd/process.c | 16 ++++++++-------- source3/smbd/reply.c | 10 +++++----- source3/smbd/sec_ctx.c | 6 +++--- source3/smbd/server.c | 2 +- source3/smbd/service.c | 6 +++--- source3/smbd/share_access.c | 4 ++-- source3/smbd/uid.c | 4 ++-- 13 files changed, 54 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 059b88ecc8..09276cd200 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -288,7 +288,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) process_pending_change_notify_queue((time_t)0); } - talloc_free(lck); + TALLOC_FREE(lck); if(fsp->oplock_type) release_file_oplock(fsp); @@ -363,7 +363,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) delete_dir = (lck->delete_on_close | lck->initial_delete_on_close); - talloc_free(lck); + TALLOC_FREE(lck); if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && delete_dir && diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index bf4db99ea6..b41467f02c 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -249,7 +249,7 @@ void conn_free_internal(connection_struct *conn) } if (conn->nt_user_token) { - talloc_free(conn->nt_user_token); + TALLOC_FREE(conn->nt_user_token); } free_namearray(conn->veto_list); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a2ec6f34b8..3f10ba41b2 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2026,7 +2026,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para done: unbecome_root(); /* END ROOT BLOCK */ - talloc_free(mem_ctx); + TALLOC_FREE(mem_ctx); return ret; } @@ -2219,7 +2219,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param } unbecome_root(); - talloc_free(server_info); + TALLOC_FREE(server_info); } data_blob_clear_free(&password); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3e555a8f31..258e0e6021 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1352,7 +1352,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, &state); } - talloc_free(lck); + TALLOC_FREE(lck); return NULL; } @@ -1363,7 +1363,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ set_saved_ntstatus(status); - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); return NULL; } @@ -1384,7 +1384,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, create_options); if (fsp_dup) { - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); if (pinfo) { *pinfo = FILE_WAS_OPENED; @@ -1447,7 +1447,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } } - talloc_free(lck); + TALLOC_FREE(lck); if (fsp_open) { fd_close(conn, fsp); /* @@ -1490,7 +1490,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!fsp_open) { if (lck != NULL) { - talloc_free(lck); + TALLOC_FREE(lck); } file_free(fsp); return NULL; @@ -1551,7 +1551,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, defer_open(lck, request_time, timeval_zero(), &state); - talloc_free(lck); + TALLOC_FREE(lck); return NULL; } @@ -1588,7 +1588,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { - talloc_free(lck); + TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); return NULL; @@ -1643,7 +1643,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!NT_STATUS_IS_OK(result)) { /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); - talloc_free(lck); + TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); set_saved_ntstatus(result); @@ -1712,7 +1712,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* If this is a successful open, we must remove any deferred open * records. */ del_deferred_open_entry(lck, mid); - talloc_free(lck); + TALLOC_FREE(lck); conn->num_files_open++; @@ -1933,7 +1933,7 @@ files_struct *open_directory(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); return NULL; } @@ -1946,7 +1946,7 @@ files_struct *open_directory(connection_struct *conn, status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); return NULL; } @@ -1956,7 +1956,7 @@ files_struct *open_directory(connection_struct *conn, lck->modified = True; } - talloc_free(lck); + TALLOC_FREE(lck); /* Change the owner if required. */ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 3efd630649..7d0a94efda 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -197,7 +197,7 @@ BOOL remove_oplock(files_struct *fsp) (double)inode)); } release_file_oplock(fsp); - talloc_free(lck); + TALLOC_FREE(lck); return ret; } @@ -226,7 +226,7 @@ BOOL downgrade_oplock(files_struct *fsp) } downgrade_file_oplock(fsp); - talloc_free(lck); + TALLOC_FREE(lck); return ret; } @@ -470,7 +470,7 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce /* Restore the sign state to what it was. */ srv_oplock_set_signing(sign_state); - talloc_free(break_msg); + TALLOC_FREE(break_msg); /* Async level2 request, don't send a reply, just remove the oplock. */ remove_oplock(fsp); @@ -578,7 +578,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, /* Restore the sign state to what it was. */ srv_oplock_set_signing(sign_state); - talloc_free(break_msg); + TALLOC_FREE(break_msg); fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; @@ -654,7 +654,7 @@ static void process_kernel_oplock_break(int msg_type, struct process_id src, /* Restore the sign state to what it was. */ srv_oplock_set_signing(sign_state); - talloc_free(break_msg); + TALLOC_FREE(break_msg); fsp->sent_oplock_break = BREAK_TO_NONE_SENT; @@ -681,7 +681,7 @@ void reply_to_oplock_break_requests(files_struct *fsp) fsp->num_pending_break_messages = 0; if (fsp->oplock_timeout != NULL) { /* Remove the timed event handler. */ - talloc_free(fsp->oplock_timeout); + TALLOC_FREE(fsp->oplock_timeout); fsp->oplock_timeout = NULL; } return; @@ -801,7 +801,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) DEBUG(0,("release_level_2_oplocks_on_change: PANIC. " "share mode entry %d is an exlusive " "oplock !\n", i )); - talloc_free(lck); + TALLOC_FREE(lck); abort(); } @@ -816,7 +816,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) /* We let the message receivers handle removing the oplock state in the share mode lock db. */ - talloc_free(lck); + TALLOC_FREE(lck); } /**************************************************************************** diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0eeb537ded..782a8c2b89 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -100,7 +100,7 @@ void invalidate_vuid(uint16 vuid) session_yield(vuser); SAFE_FREE(vuser->session_keystr); - talloc_free(vuser->server_info); + TALLOC_FREE(vuser->server_info); data_blob_free(&vuser->session_key); @@ -111,7 +111,7 @@ void invalidate_vuid(uint16 vuid) conn_clear_vuid_cache(vuid); SAFE_FREE(vuser->groups); - talloc_free(vuser->nt_user_token); + TALLOC_FREE(vuser->nt_user_token); SAFE_FREE(vuser); num_validated_vuids--; } @@ -215,7 +215,7 @@ int register_vuid(auth_serversupplied_info *server_info, "vuser->groups\n")); data_blob_free(&session_key); free(vuser); - talloc_free(server_info); + TALLOC_FREE(server_info); return UID_FIELD_INVALID; } } @@ -252,7 +252,7 @@ int register_vuid(auth_serversupplied_info *server_info, if (passwd) { vuser->unix_homedir = smb_xstrdup(passwd->pw_dir); - talloc_free(passwd); + TALLOC_FREE(passwd); } } @@ -280,7 +280,7 @@ int register_vuid(auth_serversupplied_info *server_info, } else { DEBUG(1, ("server_info does not contain a user_token - " "cannot continue\n")); - talloc_free(server_info); + TALLOC_FREE(server_info); data_blob_free(&session_key); SAFE_FREE(vuser->homedir); SAFE_FREE(vuser->unix_homedir); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9d35252e28..a50323887a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -91,7 +91,7 @@ static BOOL push_queued_message(char *buf, int msg_len, msg->buf = data_blob_talloc(msg, buf, msg_len); if(msg->buf.data == NULL) { DEBUG(0,("push_message: malloc fail (2)\n")); - talloc_free(msg); + TALLOC_FREE(msg); return False; } @@ -103,7 +103,7 @@ static BOOL push_queued_message(char *buf, int msg_len, private_len); if (msg->private_data.data == NULL) { DEBUG(0,("push_message: malloc fail (3)\n")); - talloc_free(msg); + TALLOC_FREE(msg); return False; } } @@ -131,7 +131,7 @@ void remove_deferred_open_smb_message(uint16 mid) (unsigned int)mid, (unsigned int)pml->buf.length )); DLIST_REMOVE(deferred_open_queue, pml); - talloc_free(pml); + TALLOC_FREE(pml); return; } } @@ -237,11 +237,11 @@ static void idle_event_handler(struct timed_event *te, struct idle_event *event = talloc_get_type_abort(private_data, struct idle_event); - talloc_free(event->te); + TALLOC_FREE(event->te); if (!event->handler(now, event->private_data)) { /* Don't repeat, delete ourselves */ - talloc_free(event); + TALLOC_FREE(event); return; } @@ -277,7 +277,7 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, idle_event_handler, result); if (result->te == NULL) { DEBUG(0, ("add_timed_event failed\n")); - talloc_free(result); + TALLOC_FREE(result); return NULL; } @@ -1623,8 +1623,8 @@ void smbd_process(void) errno = 0; /* free up temporary memory */ - lp_talloc_free(); - main_loop_talloc_free(); + lp_TALLOC_FREE(); + main_loop_TALLOC_FREE(); /* Did someone ask for immediate checks on things like blocking locks ? */ if (select_timeout == 0) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 89b98be1e7..1ca9d39a4c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4263,11 +4263,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); rename_open_files(conn, lck, fsp->dev, fsp->inode, newname); - talloc_free(lck); + TALLOC_FREE(lck); return NT_STATUS_OK; } - talloc_free(lck); + TALLOC_FREE(lck); if (errno == ENOTDIR || errno == EISDIR) { error = NT_STATUS_OBJECT_NAME_COLLISION; @@ -4492,11 +4492,11 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); - talloc_free(lck); + TALLOC_FREE(lck); return NT_STATUS_OK; } - talloc_free(lck); + TALLOC_FREE(lck); if (errno == ENOTDIR || errno == EISDIR) error = NT_STATUS_OBJECT_NAME_COLLISION; else @@ -4599,7 +4599,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", count++; error = NT_STATUS_OK; } - talloc_free(lck); + TALLOC_FREE(lck); DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } CloseDir(dir_hnd); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index ebc47c51d9..a30123bfa7 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -215,7 +215,7 @@ BOOL push_sec_ctx(void) if (ctx_p->ut.ngroups != 0) { if (!(ctx_p->ut.groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ut.ngroups))) { DEBUG(0, ("Out of memory in push_sec_ctx()\n")); - talloc_free(ctx_p->token); + TALLOC_FREE(ctx_p->token); return False; } @@ -255,7 +255,7 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN if (token && (token == ctx_p->token)) smb_panic("DUPLICATE_TOKEN"); - talloc_free(ctx_p->token); + TALLOC_FREE(ctx_p->token); ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups); ctx_p->token = dup_nt_token(NULL, token); @@ -311,7 +311,7 @@ BOOL pop_sec_ctx(void) SAFE_FREE(ctx_p->ut.groups); ctx_p->ut.ngroups = 0; - talloc_free(ctx_p->token); + TALLOC_FREE(ctx_p->token); /* Pop back previous user */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6c2034988a..2e96b4ceb9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -353,7 +353,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ int num; /* Free up temporary memory from the main smbd. */ - lp_talloc_free(); + lp_TALLOC_FREE(); /* Ensure we respond to PING and DEBUG messages from the main smbd. */ message_dispatch(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0fce677ea9..5c4974329c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -399,7 +399,7 @@ static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest, result = NT_STATUS_OK; done: - talloc_free(mem_ctx); + TALLOC_FREE(mem_ctx); return result; } @@ -487,7 +487,7 @@ static NTSTATUS find_forced_group(BOOL force_user, result = NT_STATUS_OK; done: - talloc_free(mem_ctx); + TALLOC_FREE(mem_ctx); return result; } @@ -540,7 +540,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->uid = pass->pw_uid; conn->gid = pass->pw_gid; string_set(&conn->user,pass->pw_name); - talloc_free(pass); + TALLOC_FREE(pass); DEBUG(3,("Guest only user %s\n",user)); } else if (vuser) { if (vuser->guest) { diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index 11e52b03ab..a429937f8d 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -161,13 +161,13 @@ BOOL token_contains_name_in_list(const char *username, while (*list != NULL) { if (token_contains_name(mem_ctx, username, sharename, token, *list)) { - talloc_free(mem_ctx); + TALLOC_FREE(mem_ctx); return True; } list += 1; } - talloc_free(mem_ctx); + TALLOC_FREE(mem_ctx); return False; } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 6e516d3562..c62c9d928a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -72,7 +72,7 @@ BOOL change_to_guest(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; - talloc_free(pass); + TALLOC_FREE(pass); pass = NULL; return True; @@ -251,7 +251,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) */ if (must_free_token) - talloc_free(token); + TALLOC_FREE(token); current_user.conn = conn; current_user.vuid = vuid; -- cgit From 2203bed32c84c63737f402accf73452efb76b483 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 20 Feb 2006 20:09:36 +0000 Subject: r13576: This is the beginnings of moving the SAM_ACCOUNT data structure to make full use of the new talloc() interface. Discussed with Volker and Jeremy. * remove the internal mem_ctx and simply use the talloc() structure as the context. * replace the internal free_fn() with a talloc_destructor() function * remove the unnecessary private nested structure * rename SAM_ACCOUNT to 'struct samu' to indicate the current an upcoming changes. Groups will most likely be replaced with a 'struct samg' in the future. Note that there are now passbd API changes. And for the most part, the wrapper functions remain the same. While this code has been tested on tdb and ldap based Samba PDC's as well as Samba member servers, there are probably still some bugs. The code also needs more testing under valgrind to ensure it's not leaking memory. But it's a start...... (This used to be commit 19b7593972480540283c5bf02c02e5ecd8d2c3f0) --- source3/smbd/chgpasswd.c | 50 ++++++++++++++++++++++++------------------------ source3/smbd/lanman.c | 6 +++--- 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 8f3e7236c4..f8ae7233c6 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -55,7 +55,7 @@ static NTSTATUS check_oem_password(const char *user, const uchar old_lm_hash_encrypted[16], uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], - SAM_ACCOUNT **hnd, char *new_passwd, + struct samu **hnd, char *new_passwd, int new_passwd_size); #if ALLOW_CHANGE_PASSWORD @@ -570,11 +570,11 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, ************************************************************/ BOOL check_lanman_password(char *user, uchar * pass1, - uchar * pass2, SAM_ACCOUNT **hnd) + uchar * pass2, struct samu **hnd) { uchar unenc_new_pw[16]; uchar unenc_old_pw[16]; - SAM_ACCOUNT *sampass = NULL; + struct samu *sampass = NULL; uint16 acct_ctrl; const uint8 *lanman_pw; BOOL ret; @@ -585,7 +585,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (ret == False) { DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n")); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return False; } @@ -594,7 +594,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, if (acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return False; } @@ -605,7 +605,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, return True; } else { DEBUG(0, ("check_lanman_password: no lanman password !\n")); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return False; } } @@ -619,7 +619,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, /* Check that the two old passwords match. */ if (memcmp(lanman_pw, unenc_old_pw, 16)) { DEBUG(0,("check_lanman_password: old password doesn't match.\n")); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return False; } @@ -636,7 +636,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, is correct before calling. JRA. ************************************************************/ -BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) +BOOL change_lanman_password(struct samu *sampass, uchar *pass2) { static uchar null_pw[16]; uchar unenc_new_pw[16]; @@ -684,7 +684,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) } if (!pdb_set_pass_changed_now (sampass)) { - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); /* Not quite sure what this one qualifies as, but this will do */ return False; } @@ -707,7 +707,7 @@ NTSTATUS pass_oem_change(char *user, uint32 *reject_reason) { pstring new_passwd; - SAM_ACCOUNT *sampass = NULL; + struct samu *sampass = NULL; NTSTATUS nt_status = check_oem_password(user, password_encrypted_with_lm_hash, old_lm_hash_encrypted, password_encrypted_with_nt_hash, @@ -724,7 +724,7 @@ NTSTATUS pass_oem_change(char *user, memset(new_passwd, 0, sizeof(new_passwd)); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return nt_status; } @@ -746,12 +746,12 @@ static NTSTATUS check_oem_password(const char *user, const uchar old_lm_hash_encrypted[16], uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], - SAM_ACCOUNT **hnd, char *new_passwd, + struct samu **hnd, char *new_passwd, int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; - SAM_ACCOUNT *sampass = NULL; + struct samu *sampass = NULL; uint8 *password_encrypted; const uint8 *encryption_key; const uint8 *lanman_pw, *nt_pw; @@ -776,7 +776,7 @@ static NTSTATUS check_oem_password(const char *user, if (ret == False) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_NO_SUCH_USER; } @@ -784,7 +784,7 @@ static NTSTATUS check_oem_password(const char *user, if (acct_ctrl & ACB_DISABLED) { DEBUG(2,("check_lanman_password: account %s disabled.\n", user)); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_ACCOUNT_DISABLED; } @@ -819,7 +819,7 @@ static NTSTATUS check_oem_password(const char *user, } else if (nt_pass_set) { DEBUG(1, ("NT password change supplied for user %s, but we have no NT password to check it with\n", user)); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } else if (lm_pass_set) { if (lp_lanman_auth()) { @@ -829,12 +829,12 @@ static NTSTATUS check_oem_password(const char *user, DEBUG(1, ("LM password change supplied for user %s, but we have disabled LanMan authentication\n", user)); } - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } else { DEBUG(1, ("password change requested for user %s, but no password supplied!\n", user)); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -845,7 +845,7 @@ static NTSTATUS check_oem_password(const char *user, if ( !decode_pw_buffer(password_encrypted, new_passwd, new_passwd_size, &new_pw_len, nt_pass_set ? STR_UNICODE : STR_ASCII)) { - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -868,7 +868,7 @@ static NTSTATUS check_oem_password(const char *user, E_old_pw_hash(new_nt_hash, nt_pw, verifier); if (memcmp(verifier, old_nt_hash_encrypted, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -896,7 +896,7 @@ static NTSTATUS check_oem_password(const char *user, E_old_pw_hash(new_nt_hash, lanman_pw, verifier); if (memcmp(verifier, old_lm_hash_encrypted, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } #ifdef DEBUG_PASSWORD @@ -918,7 +918,7 @@ static NTSTATUS check_oem_password(const char *user, E_old_pw_hash(new_lm_hash, lanman_pw, verifier); if (memcmp(verifier, old_lm_hash_encrypted, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -931,7 +931,7 @@ static NTSTATUS check_oem_password(const char *user, } /* should not be reached */ - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -941,7 +941,7 @@ static NTSTATUS check_oem_password(const char *user, found in the history list. ************************************************************/ -static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) +static BOOL check_passwd_history(struct samu *sampass, const char *plaintext) { uchar new_nt_p16[NT_HASH_LEN]; uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN]; @@ -1008,7 +1008,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) is correct before calling. JRA. ************************************************************/ -NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason) +NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason) { uint32 min_len, min_age; struct passwd *pass = NULL; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3f10ba41b2..03f7f8e5c8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1920,7 +1920,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para int uLevel = SVAL(p,0); const char *level_string; int count=0; - SAM_ACCOUNT *sampw = NULL; + struct samu *sampw = NULL; BOOL ret = False; DOM_SID *sids; gid_t *gids; @@ -2235,7 +2235,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param */ if(SVAL(*rparam,0) != NERR_Success) { - SAM_ACCOUNT *hnd = NULL; + struct samu *hnd = NULL; if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { become_root(); @@ -2243,7 +2243,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param SSVAL(*rparam,0,NERR_Success); } unbecome_root(); - pdb_free_sam(&hnd); + TALLOC_FREE(hnd); } } -- cgit From cd559192633d78a9f06e239c6a448955f6ea0842 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 21 Feb 2006 14:34:11 +0000 Subject: r13590: * replace all pdb_init_sam[_talloc]() calls with samu_new() * replace all pdb_{init,fill}_sam_pw() calls with samu_set_unix() (This used to be commit 6f1afa4acc93a07d0ee9940822d7715acaae634f) --- source3/smbd/chgpasswd.c | 4 +++- source3/smbd/lanman.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index f8ae7233c6..8df824a323 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -768,7 +768,9 @@ static NTSTATUS check_oem_password(const char *user, *hnd = NULL; - pdb_init_sam(&sampass); + if ( !(sampass = samu_new( NULL )) ) { + return NT_STATUS_NO_MEMORY; + } become_root(); ret = pdb_getsampwnam(sampass, user); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 03f7f8e5c8..ca6cc57cc3 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1981,8 +1981,8 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para goto done; } - if (!NT_STATUS_IS_OK(pdb_init_sam_talloc(mem_ctx, &sampw))) { - DEBUG(10, ("pdb_init_sam_talloc failed\n")); + if ( !(sampw = samu_new(mem_ctx)) ) { + DEBUG(0, ("samu_new() failed!\n")); goto done; } -- cgit From 7104002cf87fb2636b0819f386da79a037cc0a4e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Feb 2006 23:21:28 +0000 Subject: r13604: Fix for bug #3512 "use spnego=no" and "server signing=auto" cause client to disconnect after negprot" We missed one case of ignoring "BSRSPYL ". Merge for 3.0.21c. Jeremy. (This used to be commit 7d21cf420fdecaee43408ad5cc192cc0715d95a2) --- source3/smbd/sesssetup.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 38e16126e2..1be117a7d4 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -69,6 +69,23 @@ static int add_signature(char *outbuf, char *p) return PTR_DIFF(p, start); } +/**************************************************************************** + Start the signing engine if needed. Don't fail signing here. +****************************************************************************/ + +static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf) +{ + if (!server_info->guest && !srv_signing_started()) { + /* We need to start the signing engine + * here but a W2K client sends the old + * "BSRSPYL " signature instead of the + * correct one. Subsequent packets will + * be correct. + */ + srv_check_sign_mac(inbuf, False); + } +} + /**************************************************************************** Send a security blob via a session setup reply. ****************************************************************************/ @@ -355,15 +372,7 @@ static int reply_spnego_kerberos(connection_struct *conn, SSVAL(outbuf, smb_uid, sess_vuid); - if (!server_info->guest && !srv_signing_started()) { - /* We need to start the signing engine - * here but a W2K client sends the old - * "BSRSPYL " signature instead of the - * correct one. Subsequent packets will - * be correct. - */ - srv_check_sign_mac(inbuf, False); - } + sessionsetup_start_signing_engine(server_info, inbuf); } /* wrap that up in a nice GSS-API wrapping */ @@ -436,16 +445,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out SSVAL(outbuf,smb_uid,sess_vuid); - if (!server_info->guest && !srv_signing_started()) { - /* We need to start the signing engine - * here but a W2K client sends the old - * "BSRSPYL " signature instead of the - * correct one. Subsequent packets will - * be correct. - */ - - srv_check_sign_mac(inbuf, False); - } + sessionsetup_start_signing_engine(server_info, inbuf); } } @@ -1107,9 +1107,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* current_user_info is changed on new vuid */ reload_services( True ); - if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) { - exit_server("reply_sesssetup_and_X: bad smb signature"); - } + sessionsetup_start_signing_engine(server_info, inbuf); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From 0229b657552dad428343b9e06ead6c66dbc347c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Feb 2006 01:53:26 +0000 Subject: r13647: Fix for standalone Samba servers and XP clients. Reverts part of the PocketPC bugfix. I'm trying to get someone who has a pocketpc to test this. Jeremy. (This used to be commit ce25e6b002f39ba084c3430ca832ad4990cf1994) --- source3/smbd/negprot.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index db061cb1b8..5d2ed6a10d 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -178,6 +178,7 @@ static int negprot_spnego(char *p, uint8 *pkeylen) OID_KERBEROS5_OLD, OID_NTLMSSP, NULL}; + const char *OIDs_plain[] = {OID_NTLMSSP, NULL}; int len; global_spnego_negotiated = True; @@ -212,9 +213,13 @@ static int negprot_spnego(char *p, uint8 *pkeylen) */ if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { - memcpy(p, guid, 16); - *pkeylen = 0; - return 16; +#if 0 + /* Code for PocketPC client */ + blob = data_blob(guid, 16); +#else + /* Code for standalone WXP client */ + blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE"); +#endif } else { fstring myname; char *host_princ_s = NULL; @@ -224,14 +229,20 @@ static int negprot_spnego(char *p, uint8 *pkeylen) blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s); SAFE_FREE(host_princ_s); } + memcpy(p, blob.data, blob.length); len = blob.length; if (len > 256) { DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len)); len = 255; } - *pkeylen = len; data_blob_free(&blob); + + if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { + *pkeylen = 0; + } else { + *pkeylen = len; + } return len; } -- cgit From 04f635f8fc186865b2e099b61c0df27e7f48b37d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 24 Feb 2006 16:00:53 +0000 Subject: r13675: * patch from Bjoern JACKE to remove the artificial RO bit on directories in user profiles when profile acls = yes. (This used to be commit b698e83a82f96db4a4a6ffa4b61af50c943deff0) --- source3/smbd/trans2.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9c46fec790..6da71039f0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1146,7 +1146,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, continue; } - file_size = get_file_size(sbuf); + if (!(mode & aDIR)) + file_size = get_file_size(sbuf); allocation_size = get_allocation_size(conn,NULL,&sbuf); mdate = sbuf.st_mtime; adate = sbuf.st_atime; @@ -1158,13 +1159,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, adate &= ~1; } - if(mode & aDIR) { - /* This is necessary, as otherwise the - * desktop.ini file in this folder is - * ignored */ - mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0); - file_size = 0; - } DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); @@ -2915,13 +2909,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * mode = FILE_ATTRIBUTE_NORMAL; fullpathname = fname; - file_size = get_file_size(sbuf); - if (mode & aDIR) { - /* This is necessary, as otherwise the desktop.ini file in - * this folder is ignored */ - mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0); - file_size = 0; - } + if (!(mode & aDIR)) + file_size = get_file_size(sbuf); /* Pull any EA list from the data portion. */ if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) { -- cgit From f8fccdfd370d6a0291bd38c2cd081a605f0bceac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 26 Feb 2006 14:20:29 +0000 Subject: r13694: Committing patch from Aleksey Fedoseev to NULL out a pointer after talloc_destroy(). Volker (This used to be commit 788e52eb5d17a8f5b41b6ad5244ccf448fc81a36) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 258e0e6021..8913db8380 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1110,7 +1110,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(0, ("could not get share mode lock\n")); } else { del_deferred_open_entry(lck, mid); - talloc_destroy(lck); + TALLOC_FREE(lck); } /* Ensure we don't reprocess this message. */ -- cgit From e54786b53543b4667288c64abb55478fddd95061 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 27 Feb 2006 10:32:45 +0000 Subject: r13711: * Correctly handle acb_info/acct_flags as uint32 not as uint16. * Fix a couple of related parsing issues. * in the info3 reply in a samlogon, return the ACB-flags (instead of returning zero) Guenther (This used to be commit 5b89e8bc24f0fdc8b52d5c9e849aba723df34ea7) --- source3/smbd/chgpasswd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 8df824a323..224ae3d763 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -575,7 +575,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, uchar unenc_new_pw[16]; uchar unenc_old_pw[16]; struct samu *sampass = NULL; - uint16 acct_ctrl; + uint32 acct_ctrl; const uint8 *lanman_pw; BOOL ret; @@ -641,7 +641,7 @@ BOOL change_lanman_password(struct samu *sampass, uchar *pass2) static uchar null_pw[16]; uchar unenc_new_pw[16]; BOOL ret; - uint16 acct_ctrl; + uint32 acct_ctrl; const uint8 *pwd; if (sampass == NULL) { @@ -755,7 +755,7 @@ static NTSTATUS check_oem_password(const char *user, uint8 *password_encrypted; const uint8 *encryption_key; const uint8 *lanman_pw, *nt_pw; - uint16 acct_ctrl; + uint32 acct_ctrl; uint32 new_pw_len; uchar new_nt_hash[16]; uchar new_lm_hash[16]; -- cgit From 447d49be9e42f05211cb77ddc5a8189329791ecf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Feb 2006 18:48:33 +0000 Subject: r13724: Remove unused variable. Bug #3559 from jason@ncac.gwu.edu. Jeremy. (This used to be commit 0295ed3d5c3bb34ef29d01100a6156a754377930) --- source3/smbd/oplock_irix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index fa86211c7f..8f01438745 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -206,13 +206,13 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, } /**************************************************************************** - Set *maxfd to include oplock read pipe. + See if there is a message waiting in this fd set. Note that fds MAY BE NULL ! If so we must do our own select. ****************************************************************************/ static BOOL irix_oplock_msg_waiting(fd_set *fds) { - int maxfd, selrtn; + int selrtn; fd_set myfds; struct timeval to; -- cgit From 99b74908cd064d7e1a3864db9c6b7dba018577c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Feb 2006 06:41:07 +0000 Subject: r13748: Don't reference memory after we just freed it (Doh!). Thanks to tridge's changes to the directory delete on close tests for catching this. Jeremy. (This used to be commit 01ef957d4846191071f95393e6e76e48d4c6aa24) --- source3/smbd/close.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 09276cd200..bc1182032d 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -363,8 +363,6 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) delete_dir = (lck->delete_on_close | lck->initial_delete_on_close); - TALLOC_FREE(lck); - if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && delete_dir && lck->delete_token) { @@ -382,6 +380,8 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) lck->delete_token->groups, NULL); + TALLOC_FREE(lck); + ok = rmdir_internals(fsp->conn, fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", @@ -402,6 +402,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) } process_pending_change_notify_queue((time_t)0); } else { + TALLOC_FREE(lck); remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_CANCELLED); } -- cgit From b532e866446803aaafa0f68340d0a868870d9dfc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Feb 2006 15:58:09 +0000 Subject: r13759: As pointed out by Volker, it isn't much good creating a new empty acl in remove_posix_acl if you don't bother to set it on the file in question :-). Jeremy. (This used to be commit 12eccc8fe4ed043698970de42921757eb0448c84) --- source3/smbd/posix_acls.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d4801d1743..9e513580c3 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3834,6 +3834,21 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c } } + /* Set the new empty file ACL. */ + if (fsp && fsp->fh->fd != -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, new_file_acl) == -1) { + DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n", + fname, strerror(errno) )); + goto done; + } + } else { + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, new_file_acl) == -1) { + DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n", + fname, strerror(errno) )); + goto done; + } + } + ret = True; done: -- cgit From 4f636b57c1330677db3ff17fd91b880cec38eb2c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 1 Mar 2006 15:11:56 +0000 Subject: r13771: BUG 3534: ignore lines in the username map file with no right hand list rather than bailing out (This used to be commit acff5163ca7be59e01438f7cf63faef9ed54b820) --- source3/smbd/map_username.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index a6025fcf47..1f523cc89f 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -142,10 +142,12 @@ BOOL map_username(fstring user) } } + /* skip lines like 'user = ' */ + dosuserlist = str_list_make(dosname, NULL); if (!dosuserlist) { - DEBUG(0,("Unable to build user list\n")); - return False; + DEBUG(0,("Bad username map entry. Unable to build user list. Ignoring.\n")); + continue; } if (strchr_m(dosname,'*') || -- cgit From 894358a8f3e338b339b6c37233edef794b312087 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Mar 2006 06:31:04 +0000 Subject: r13915: Fixed a very interesting class of realloc() bugs found by Coverity. realloc can return NULL in one of two cases - (1) the realloc failed, (2) realloc succeeded but the new size requested was zero, in which case this is identical to a free() call. The error paths dealing with these two cases should be different, but mostly weren't. Secondly the standard idiom for dealing with realloc when you know the new size is non-zero is the following : tmp = realloc(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } However, there were *many* *many* places in Samba where we were using the old (broken) idiom of : p = realloc(p, size) if (!p) { return error; } which will leak the memory pointed to by p on realloc fail. This commit (hopefully) fixes all these cases by moving to a standard idiom of : p = SMB_REALLOC(p, size) if (!p) { return error; } Where if the realloc returns null due to the realloc failing or size == 0 we *guarentee* that the storage pointed to by p has been freed. This allows me to remove a lot of code that was dealing with the standard (more verbose) method that required a tmp pointer. This is almost always what you want. When a realloc fails you never usually want the old memory, you want to free it and get into your error processing asap. For the 11 remaining cases where we really do need to keep the old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR, which can be used as follows : tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the pointer p, even on size == 0 or realloc fail. All this is done by a hidden extra argument to Realloc(), BOOL free_old_on_error which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR macros (and their array counterparts). It remains to be seen what this will do to our Coverity bug count :-). Jeremy. (This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0) --- source3/smbd/lanman.c | 176 +++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/msdfs.c | 6 +- source3/smbd/nttrans.c | 13 ++-- source3/smbd/password.c | 2 +- source3/smbd/session.c | 4 ++ source3/smbd/trans2.c | 79 +++++++++++----------- 6 files changed, 216 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index ca6cc57cc3..a78681bad8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -798,6 +798,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, *rdata_len = 0; *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,ERRunknownlevel); SSVAL(*rparam,2,0); SSVAL(*rparam,4,0); @@ -817,6 +820,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } desc.base = *rdata; desc.buflen = mdrcnt; } else { @@ -846,6 +852,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, *rdata_len = desc.usedlen; *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -896,6 +905,9 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, *rdata_len = 0; *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,ERRunknownlevel); SSVAL(*rparam,2,0); SSVAL(*rparam,4,0); @@ -1066,15 +1078,11 @@ static int get_server_info(uint32 servertype, } if (count == alloced) { - struct srv_info_struct *ts; - alloced += 10; - ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); - if (!ts) { + *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); + if (!*servers) { DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); return 0; - } else { - *servers = ts; } memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); } @@ -1332,6 +1340,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param *rdata_len = fixed_len + string_len; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } memset(*rdata,'\0',*rdata_len); p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ @@ -1359,6 +1370,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); @@ -1399,6 +1413,9 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVAL(*rparam,0,0x08AC); /* informational warning message */ SSVAL(*rparam,2,0); @@ -1581,6 +1598,9 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para } *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } p = *rdata; *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); if (*rdata_len < 0) { @@ -1589,6 +1609,9 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); @@ -1665,6 +1688,9 @@ static BOOL api_RNetShareEnum( connection_struct *conn, *rdata_len = fixed_len + string_len; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } memset(*rdata,0,*rdata_len); p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */ @@ -1688,6 +1714,9 @@ static BOOL api_RNetShareEnum( connection_struct *conn, *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); @@ -1792,6 +1821,9 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); @@ -1803,6 +1835,9 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; SSVAL(*rparam,0,res); SSVAL(*rparam,2,0); @@ -1868,6 +1903,9 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c *rdata_len = cli_buf_size; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } p = *rdata; @@ -1895,7 +1933,9 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); - + if (!*rparam) { + return False; + } SSVAL(*rparam, 0, errflags); SSVAL(*rparam, 2, 0); /* converter word */ SSVAL(*rparam, 4, i); /* is this right?? */ @@ -1933,6 +1973,9 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } /* check it's a supported varient */ @@ -1952,7 +1995,9 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para *rdata_len = mdrcnt + 1024; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); - + if (!*rdata) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -2068,6 +2113,9 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } /* check it's a supported varient */ if (strcmp("B21",str2) != 0) @@ -2075,6 +2123,9 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch *rdata_len = cli_buf_size; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } p = *rdata; @@ -2138,9 +2189,15 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 21; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -2194,6 +2251,9 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; @@ -2266,6 +2326,9 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * char *p = param + 2; *rparam_len = 2; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; @@ -2333,6 +2396,9 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; if (!print_job_exists(sharename, jobid)) { @@ -2396,6 +2462,9 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; snum = print_queue_snum(QueueName); @@ -2470,6 +2539,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha return False; *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } if ( (snum = lp_servicenumber(sharename)) == -1 ) { DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n", @@ -2586,6 +2658,9 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par *rdata_len = mdrcnt; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } p = *rdata; p2 = p + struct_len; @@ -2635,6 +2710,9 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); @@ -2661,6 +2739,9 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } /* check it's a supported varient */ if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) { @@ -2669,6 +2750,9 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param *rdata_len = mdrcnt + 1024; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -2908,6 +2992,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); @@ -2930,6 +3017,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param *rdata_len = mdrcnt + 1024; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -3082,6 +3172,9 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param } if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } } desc.base = *rdata; @@ -3121,6 +3214,9 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param *rdata_len = desc.usedlen; *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -3156,6 +3252,9 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,0); /* errorcode */ SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,0x7f); /* permission flags */ @@ -3219,6 +3318,9 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } desc.base = *rdata; desc.buflen = mdrcnt; } else { @@ -3242,6 +3344,9 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -3300,6 +3405,9 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa count = print_queue_status(snum,&queue,&status); if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } } desc.base = *rdata; desc.buflen = mdrcnt; @@ -3318,6 +3426,9 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3429,6 +3540,9 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par } else { if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } desc.base = *rdata; desc.buflen = mdrcnt; } else { @@ -3447,6 +3561,9 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -3494,6 +3611,9 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } } desc.base = *rdata; @@ -3516,6 +3636,9 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3554,6 +3677,9 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } } desc.base = *rdata; desc.buflen = mdrcnt; @@ -3567,6 +3693,9 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3605,6 +3734,9 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } } desc.base = *rdata; desc.buflen = mdrcnt; @@ -3619,6 +3751,9 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3657,6 +3792,9 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } } memset((char *)&desc,'\0',sizeof(desc)); desc.base = *rdata; @@ -3672,6 +3810,9 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,succnt); @@ -3720,6 +3861,9 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } } memset((char *)&desc,'\0',sizeof(desc)); desc.base = *rdata; @@ -3745,6 +3889,9 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); /* converter */ SSVAL(*rparam,4,num_sessions); /* count */ @@ -3766,6 +3913,9 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char { *rparam_len = MIN(*rparam_len,mprcnt); *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; @@ -3787,6 +3937,9 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, c { *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; @@ -3919,11 +4072,14 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * /* if we get False back then it's actually unsupported */ if (!reply) { - api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, + reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); } - send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); + /* If api_Unsupported returns false we can't return anything. */ + if (reply) { + send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); + } SAFE_FREE(rdata); SAFE_FREE(rparam); diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4f7858d985..955197a425 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -643,9 +643,8 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; - } else { - *ppdata = pdata; } + *ppdata = pdata; /* copy in the dfs requested paths.. required for offset calculations */ memcpy(pdata+uni_reqpathoffset1,uni_requestedpath,requestedpathlen); @@ -729,9 +728,8 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; - } else { - *ppdata = pdata; } + *ppdata = pdata; /* create the header */ SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 417e3421cb..796eb44332 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -48,21 +48,16 @@ static const char *known_nt_pipes[] = { static char *nttrans_realloc(char **ptr, size_t size) { - char *tptr = NULL; if (ptr==NULL) { smb_panic("nttrans_realloc() called with NULL ptr\n"); } - tptr = SMB_REALLOC(*ptr, size); - if(tptr == NULL) { - *ptr = NULL; + *ptr = SMB_REALLOC(*ptr, size); + if(*ptr == NULL) { return NULL; } - memset(tptr,'\0',size); - - *ptr = tptr; - - return tptr; + memset(*ptr,'\0',size); + return *ptr; } /**************************************************************************** diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 782a8c2b89..8b88990e2f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -383,7 +383,7 @@ void add_session_user(const char *user) "too large.\n")); return; } - newlist = (char *)SMB_REALLOC( + newlist = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR( session_userlist, len_session_userlist + PSTRING_LEN ); if( newlist == NULL ) { diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 27f760a088..41f8fd0ed4 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -224,6 +224,10 @@ static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, sesslist->count += 1; sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, sesslist->count); + if (!sesslist->sessions) { + sesslist->count = 0; + return -1; + } memcpy(&sesslist->sessions[sesslist->count - 1], current, sizeof(struct sessionid)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6da71039f0..9cd2d44de5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -870,11 +870,11 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } /* Realloc the size of parameters and data we will return */ - params = SMB_REALLOC(*pparams, 30); - if( params == NULL ) { + *pparams = SMB_REALLOC(*pparams, 30); + if(*pparams == NULL ) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; SSVAL(params,0,fsp->fnum); SSVAL(params,2,open_attr); @@ -1711,21 +1711,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } - pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if( pdata == NULL ) { + *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + if(*ppdata == NULL ) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } - - *ppdata = pdata; + pdata = *ppdata; /* Realloc the params space */ - params = SMB_REALLOC(*pparams, 10); - if (params == NULL) { + *pparams = SMB_REALLOC(*pparams, 10); + if (*pparams == NULL) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ @@ -1962,22 +1961,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } - pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if(pdata == NULL) { + *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + if(*ppdata == NULL) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } - *ppdata = pdata; + pdata = *ppdata; /* Realloc the params space */ - params = SMB_REALLOC(*pparams, 6*SIZEOFWORD); - if( params == NULL ) { + *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD); + if(*pparams == NULL ) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; /* Check that the dptr is valid */ if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { @@ -2134,12 +2133,12 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf return ERROR_DOS(ERRSRV,ERRinvdevice); } - pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if ( pdata == NULL ) { + *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + if (*ppdata == NULL ) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - *ppdata = pdata; + pdata = *ppdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); switch (info_level) { @@ -2943,20 +2942,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } - params = SMB_REALLOC(*pparams,2); - if (params == NULL) { + *pparams = SMB_REALLOC(*pparams,2); + if (*pparams == NULL) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; SSVAL(params,0,0); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; - pdata = SMB_REALLOC(*ppdata, data_size); - if ( pdata == NULL ) { + *ppdata = SMB_REALLOC(*ppdata, data_size); + if (*ppdata == NULL ) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } - *ppdata = pdata; + pdata = *ppdata; c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); @@ -3683,11 +3682,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); /* Realloc the parameter size */ - params = SMB_REALLOC(*pparams,2); - if(params == NULL) { + *pparams = SMB_REALLOC(*pparams,2); + if (*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; SSVAL(params,0,0); @@ -4543,11 +4542,11 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, } /* Realloc the parameter and data sizes */ - params = SMB_REALLOC(*pparams,2); - if(params == NULL) { + *pparams = SMB_REALLOC(*pparams,2); + if(*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; SSVAL(params,0,0); @@ -4585,11 +4584,11 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char } /* Realloc the parameter and data sizes */ - params = SMB_REALLOC(*pparams,6); - if(params == NULL) { + *pparams = SMB_REALLOC(*pparams,6); + if (*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; SSVAL(params,0,fnf_handle); SSVAL(params,2,0); /* No changes */ @@ -4619,11 +4618,11 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2findnotifynext\n")); /* Realloc the parameter and data sizes */ - params = SMB_REALLOC(*pparams,4); - if(params == NULL) { + *pparams = SMB_REALLOC(*pparams,4); + if (*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - *pparams = params; + params = *pparams; SSVAL(params,0,0); /* No changes */ SSVAL(params,2,0); /* No EA errors */ @@ -4688,11 +4687,11 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { - pdata = SMB_REALLOC(*ppdata, 32); - if(pdata == NULL) { + *ppdata = SMB_REALLOC(*ppdata, 32); + if (*ppdata == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - *ppdata = pdata; + pdata = *ppdata; /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 CAN ACCEPT THIS IN UNICODE. JRA. */ -- cgit From 92fa7eadc85472867a5e55c43480ccfb6e3e876f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Mar 2006 09:09:13 +0000 Subject: r13916: Fix Coverity bug #29. Looks like my code. I wonder how much there is still lurking... Volker (This used to be commit 1345a52794f4f55173ed677af3d0714e88bf17c6) --- source3/smbd/oplock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 7d0a94efda..61e812d43a 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -764,6 +764,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " "share mode entry for file %s.\n", fsp->fsp_name )); + return; } DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", -- cgit From 33c9fbab1278302dde1b0daf7ce6ac3462dc930c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Mar 2006 19:52:26 +0000 Subject: r13980: Fix Coverity bug # 63. Jeremy, could you take a look at this? Thanks, Volker (This used to be commit 49043a756dfa6a973d5605f42068df351a4a9ab5) --- source3/smbd/ipc.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 86c6d056a0..77746cb12f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -380,7 +380,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int unsigned int dscnt = SVAL(inbuf,smb_vwv11); unsigned int dsoff = SVAL(inbuf,smb_vwv12); unsigned int suwcnt = CVAL(inbuf,smb_vwv13); - fstring local_machine_name; + char *local_machine_name; START_PROFILE(SMBtrans); memset(name, '\0',sizeof(name)); @@ -542,11 +542,22 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int * WinCE wierdness.... */ - fstrcpy( local_machine_name, get_local_machine_name() ); + asprintf(&local_machine_name, "\\%s\\", get_local_machine_name()); - if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine_name, strlen(local_machine_name)) == 0) && - (name[strlen(local_machine_name)+1] == '\\')) - name_offset = strlen(local_machine_name)+1; + if (local_machine_name == NULL) { + srv_signing_trans_stop(); + SAFE_FREE(data); + SAFE_FREE(params); + SAFE_FREE(setup); + END_PROFILE(SMBtrans); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + if (strnequal(name, local_machine_name, strlen(local_machine_name))) { + name_offset = strlen(local_machine_name)-1; + } + + SAFE_FREE(local_machine_name); if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) { name_offset += strlen("\\PIPE"); -- cgit From dece1a2db267eb7adf1560bc040763be919db592 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Mar 2006 20:24:28 +0000 Subject: r13983: Fix Coverity bug # 111 (This used to be commit 08d7fd31ab250bc6ba3922b36aa7b0cfef1e5bf1) --- source3/smbd/lanman.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a78681bad8..4d4d9d2259 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1082,6 +1082,7 @@ static int get_server_info(uint32 servertype, *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); if (!*servers) { DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); + file_lines_free(lines); return 0; } memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); -- cgit From 9f18298beee5c6abf2cffc9e1d36da2795f4e9d6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 9 Mar 2006 15:51:55 +0000 Subject: r14075: * add support for long variable names in smb.conf in the form of %(....) * add support for %(DomainSID) * replace standard_sub_XXX() functions with wrappers around their alloc_sub_XXX() counterparts * add support for using SIDs in read list, et. al. (anything that is checked by nt_token_contains_name_in_list()) (This used to be commit 71d960250d2c6d01096a03e98884d3f9c395baa0) --- source3/smbd/share_access.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index a429937f8d..df5f445587 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -85,6 +85,13 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, * result that might be interpreted in a wrong way. */ smb_panic("substitutions failed\n"); } + + /* check to see is we already have a SID */ + + if ( string_to_sid( &sid, name ) ) { + DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name)); + return nt_token_check_sid( &sid, token ); + } if (!do_group_checks(&name, &prefix)) { if (!lookup_name(mem_ctx, name, LOOKUP_NAME_ALL, @@ -153,14 +160,12 @@ BOOL token_contains_name_in_list(const char *username, return False; } - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { + if ( (mem_ctx = talloc_new(NULL)) == NULL ) { smb_panic("talloc_new failed\n"); } while (*list != NULL) { - if (token_contains_name(mem_ctx, username, sharename, - token, *list)) { + if (token_contains_name(mem_ctx, username, sharename,token, *list)) { TALLOC_FREE(mem_ctx); return True; } -- cgit From f0210601d19016d0c932ad1623e77a70c9aee023 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 9 Mar 2006 22:31:05 +0000 Subject: r14111: Work around additional typedefs in the gamin implementation of the FAM API. (This used to be commit dc96ce90e50da9a82f941b0b534c0681c8477f5e) --- source3/smbd/notify_fam.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index dd1e5b709e..3b6be77aca 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -24,6 +24,13 @@ #include +#if !defined(HAVE_FAM_H_FAMCODES_TYPEDEF) +/* Gamin provides this typedef which means we can't use 'enum FAMCodes' as per + * every other FAM implementation. Phooey. + */ +typedef enum FAMCodes FAMCodes; +#endif + /* NOTE: There are multiple versions of FAM floating around the net, each with * slight differences from the original SGI FAM implementation. In this file, * we rely only on the SGI features and do not assume any extensions. For @@ -40,7 +47,7 @@ struct fam_req_info { FAMRequest req; int generation; - enum FAMCodes code; + FAMCodes code; enum { /* We are waiting for an event. */ @@ -91,9 +98,9 @@ static struct cnotify_fns global_fam_notify = * because that might not work across all flavours of FAM. */ static const char * -fam_event_str(enum FAMCodes code) +fam_event_str(FAMCodes code) { - static struct { enum FAMCodes code; const char * name; } evstr[] = + static const struct { FAMCodes code; const char * name; } evstr[] = { { FAMChanged, "FAMChanged"}, { FAMDeleted, "FAMDeleted"}, @@ -188,7 +195,7 @@ fam_monitor_path(connection_struct * conn, } static BOOL -fam_handle_event(enum FAMCodes code, uint32 flags) +fam_handle_event(const FAMCodes code, uint32 flags) { #define F_CHANGE_MASK (FILE_NOTIFY_CHANGE_FILE | \ FILE_NOTIFY_CHANGE_ATTRIBUTES | \ -- cgit From 1de2983de4ea1a482c294a9ecce8437cc35ff7ee Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 9 Mar 2006 22:31:37 +0000 Subject: r14112: * fix checks on return code from register_vuid() which could actually fail and we would still return success in the SMBsesssetup reply :-( * Make sure to create the local token for the server_fino struct in reply_spnego_kerberos() so that register_vuid() does not fail. (how did this ever work?) (This used to be commit 8dafa45b97020d1aceb027a85e18401c965bf402) --- source3/smbd/password.c | 2 +- source3/smbd/sesssetup.c | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8b88990e2f..8d33c1deed 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -305,7 +305,7 @@ int register_vuid(auth_serversupplied_info *server_info, DEBUG(1, ("Failed to claim session for vuid=%d\n", vuser->vuid)); invalidate_vuid(vuser->vuid); - return -1; + return UID_FIELD_INVALID; } /* Register a home dir service for this user iff diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1be117a7d4..1abb800627 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -349,6 +349,21 @@ static int reply_spnego_kerberos(connection_struct *conn, pdb_set_domain(server_info->sam_account, domain, PDB_SET); } } + + /* we need to build the token for the user. make_server_info_guest() + already does this */ + + if ( !server_info->ptok ) { + ret = create_local_token( server_info ); + if ( !NT_STATUS_IS_OK(ret) ) { + SAFE_FREE(client); + data_blob_free(&ap_rep); + data_blob_free(&session_key); + TALLOC_FREE( mem_ctx ); + TALLOC_FREE( server_info ); + return ERROR_NT(ret); + } + } /* register_vuid keeps the server info */ /* register_vuid takes ownership of session_key, no need to free after this. @@ -357,7 +372,7 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); - if (sess_vuid == -1) { + if (sess_vuid == UID_FIELD_INVALID ) { ret = NT_STATUS_LOGON_FAILURE; } else { /* current_user_info is changed on new vuid */ @@ -429,7 +444,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); (*auth_ntlmssp_state)->server_info = NULL; - if (sess_vuid == -1) { + if (sess_vuid == UID_FIELD_INVALID ) { nt_status = NT_STATUS_LOGON_FAILURE; } else { @@ -674,7 +689,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, vuser = get_partial_auth_user_struct(vuid); if (!vuser) { vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL); - if (vuid == -1) { + if (vuid == UID_FIELD_INVALID ) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1100,7 +1115,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&nt_resp); data_blob_free(&lm_resp); - if (sess_vuid == -1) { + if (sess_vuid == UID_FIELD_INVALID) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } -- cgit From c077d363a4f14afd2c83d57dcd52e6a2c1a2d42b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 10 Mar 2006 08:43:32 +0000 Subject: r14130: Remove make_server_info_pac alltogether, make_server_info_info3 does already do what we need. Guenther (This used to be commit 773e33c9717ae04f48983ddc49f7619a97523603) --- source3/smbd/sesssetup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1abb800627..98146561b2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -316,10 +316,10 @@ static int reply_spnego_kerberos(connection_struct *conn, if ( map_domainuser_to_guest ) { make_server_info_guest(&server_info); } else if (logon_info) { - ret = make_server_info_pac(&server_info, real_username, pw, logon_info); - + ret = make_server_info_info3(mem_ctx, real_username, real_username, domain, + &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { - DEBUG(1,("make_server_info_pac failed: %s!\n", + DEBUG(1,("make_server_info_info3 failed: %s!\n", nt_errstr(ret))); SAFE_FREE(client); data_blob_free(&ap_rep); -- cgit From 47a11f8a4c6156965163fd89bef668cd6612b70c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Mar 2006 17:52:41 +0000 Subject: r14168: Fix Coverity #219. I think this is a false coverity warning as it seems to get confused with assignment and comparison. Clarify the code anyway. Jeremy. (This used to be commit 754818f8cc0849bddf84b7a534cd65e8dcd932ac) --- source3/smbd/sesssetup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 98146561b2..d32ff9fa14 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1044,7 +1044,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } else { struct auth_context *plaintext_auth_context = NULL; const uint8 *chal; - if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) { + + nt_status = make_auth_context_subsystem(&plaintext_auth_context); + + if (NT_STATUS_IS_OK(nt_status)) { chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); if (!make_user_info_for_reply(&user_info, -- cgit From 5f224c2c265faa50e5495cc738f1a62c6aa70d56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Mar 2006 18:32:18 +0000 Subject: r14170: Paranioa fix for sesssetup. Fix Coverity bug #26. Guard against NULL ref. Jeremy. (This used to be commit c0f906ac8de850f4566b6b3be4e3c7d245e6e252) --- source3/smbd/sesssetup.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index d32ff9fa14..fcb778d1fe 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1079,6 +1079,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(nt_status_squash(nt_status)); } + /* Ensure we can't possible take a code path leading to a null defref. */ + if (!server_info) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + nt_status = create_local_token(server_info); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("create_local_token failed: %s\n", -- cgit From a62c0925e8b38e491fef7967fdca076895152d7e Mon Sep 17 00:00:00 2001 From: James Peach Date: Sat, 11 Mar 2006 10:59:03 +0000 Subject: r14207: Convert the lp_acl_compatibility() param into an enum. (This used to be commit 5429c495c538e416010cf44e1d6fb771770a72ae) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9e513580c3..5356d962a2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -783,15 +783,15 @@ static void merge_aces( canon_ace **pp_list_head ) static BOOL nt4_compatible_acls(void) { - const char *compat = lp_acl_compatibility(); + int compat = lp_acl_compatibility(); - if (*compat == '\0') { + if (compat == ACL_COMPAT_AUTO) { enum remote_arch_types ra_type = get_remote_arch(); /* Automatically adapt to client */ return (ra_type <= RA_WINNT); } else - return (strequal(compat, "winnt")); + return (compat == ACL_COMPAT_WINNT); } -- cgit From ff122b308bf4ad9115ebfe1d292051c3c5ecbb78 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 12 Mar 2006 04:18:43 +0000 Subject: r14229: Something Coverity hasn't caught (yet) but I've gotten sensitive to null derefs. get_timed_events_timeout() can potentially return NULL. Cope with this. Jeremy. (This used to be commit 04838078723613628b298b7a87622df30432cf64) --- source3/smbd/process.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a50323887a..40d6818f3f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -445,9 +445,11 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) struct timeval tmp; struct timeval *tp = get_timed_events_timeout(&tmp,SMBD_SELECT_TIMEOUT); - to = timeval_min(&to, tp); - if (timeval_is_zero(&to)) { - return True; + if (tp) { + to = timeval_min(&to, tp); + if (timeval_is_zero(&to)) { + return True; + } } } -- cgit From ed5095a4903abf41673b8d6c9fbd9a02b994a310 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Mar 2006 18:56:26 +0000 Subject: r14336: Try and quieten coverity #53 and #54. Make it obvious we're using -1 as a special size_t case by casting. Jeremy. (This used to be commit 415530bd082bf351f5e4c1fd32408f123ed77f85) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 955197a425..257a6105c5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -680,7 +680,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, - -1, STR_UNICODE); + (size_t)-1, STR_UNICODE); SSVAL(pdata,offset+20,uni_curroffset-offset); @@ -709,7 +709,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, DEBUG(10,("setting up version3 referral\n")); - reqpathlen = rpcstr_push(uni_reqpath, pathname, -1, STR_TERMINATE); + reqpathlen = rpcstr_push(uni_reqpath, pathname, (size_t)-1, STR_TERMINATE); if (DEBUGLVL(10)) { dump_data(0, (char *) uni_reqpath,reqpathlen); -- cgit From b5c2c5cd2579560eb8d608b3f63b628735ccf3ca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Mar 2006 23:56:02 +0000 Subject: r14357: Try and fix Coverity #169 by making the pointer aliasing clearer. This isn't a bug but a code clarification. Jeremy. line, and those below, will be ignored-- M source/smbd/posix_acls.c (This used to be commit b8397c9f33424e0d1ed3ff849e1c99812f978000) --- source3/smbd/posix_acls.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 5356d962a2..ca0c51b1ea 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -516,10 +516,12 @@ static size_t count_canon_ace_list( canon_ace *list_head ) static void free_canon_ace_list( canon_ace *list_head ) { - while (list_head) { - canon_ace *old_head = list_head; - DLIST_REMOVE(list_head, list_head); - SAFE_FREE(old_head); + canon_ace *list, *next; + + for (list = list_head; list; list = next) { + next = list->next; + DLIST_REMOVE(list_head, list); + SAFE_FREE(list); } } -- cgit From e6676a9a6928deb03c2a43a66c1245dd05d03e71 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Mar 2006 17:21:30 +0000 Subject: r14387: Try and fix the coverity issues (#53, #54) with negative sink by ensuring all uses of rpcstr_push are consistent with a size_t dest size arg. Jeremy. (This used to be commit f65d7afe1977d9d85046732842f9643716c15088) --- source3/smbd/msdfs.c | 8 ++++---- source3/smbd/trans2.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 257a6105c5..4606441c3a 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -609,7 +609,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, DEBUG(10,("setting up version2 referral\nRequested path:\n")); - requestedpathlen = rpcstr_push(uni_requestedpath, pathname, -1, + requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring), STR_TERMINATE); if (DEBUGLVL(10)) { @@ -680,7 +680,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, - (size_t)-1, STR_UNICODE); + sizeof(pstring), STR_UNICODE); SSVAL(pdata,offset+20,uni_curroffset-offset); @@ -709,7 +709,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, DEBUG(10,("setting up version3 referral\n")); - reqpathlen = rpcstr_push(uni_reqpath, pathname, (size_t)-1, STR_TERMINATE); + reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE); if (DEBUGLVL(10)) { dump_data(0, (char *) uni_reqpath,reqpathlen); @@ -764,7 +764,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, SSVAL(pdata,offset+14,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset,ref->alternate_path, - -1, STR_UNICODE | STR_TERMINATE); + sizeof(pstring), STR_UNICODE | STR_TERMINATE); SSVAL(pdata,offset+16,uni_curroffset-offset); /* copy 0x10 bytes of 00's in the ServiceSite GUID */ memset(pdata+offset+18,'\0',16); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9cd2d44de5..8429cd7149 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3221,7 +3221,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Pathname with leading '\'. */ { size_t byte_len; - byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False); + byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False); DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n")); SIVAL(pdata,0,byte_len); data_size = 4 + byte_len; @@ -3265,7 +3265,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (mode & aDIR) { data_size = 0; } else { - size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False); + size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False); SIVAL(pdata,0,0); /* ??? */ SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ SOFF_T(pdata,8,file_size); -- cgit From f04d5530cc9ec849edc39c86dbe3946f054d8178 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Mar 2006 22:52:59 +0000 Subject: r14460: SMBexit closes by pid and vuid. Tested with smbtorture. Jeremy. (This used to be commit 71e81580421225d5b35a25d46a7b6064a826685c) --- source3/smbd/files.c | 6 +++--- source3/smbd/reply.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 5a545c236e..ba4baa93b1 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -154,16 +154,16 @@ void file_close_conn(connection_struct *conn) } /**************************************************************************** - Close all open files for a pid. + Close all open files for a pid and a vuid. ****************************************************************************/ -void file_close_pid(uint16 smbpid) +void file_close_pid(uint16 smbpid, int vuid) { files_struct *fsp, *next; for (fsp=Files;fsp;fsp=next) { next = fsp->next; - if (fsp->file_pid == smbpid) { + if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) { close_file(fsp,SHUTDOWN_CLOSE); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1ca9d39a4c..83f527d326 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3220,7 +3220,7 @@ int reply_exit(connection_struct *conn, int outsize; START_PROFILE(SMBexit); - file_close_pid(SVAL(inbuf,smb_pid)); + file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid)); outsize = set_message(outbuf,0,0,True); -- cgit From 49ecd176ee4bb2c4acffa0db548c33d6c90dcad7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 19 Mar 2006 11:11:37 +0000 Subject: r14559: Oplocks have changed, process_smb can be static again (This used to be commit 19e9bc03f81d8d000b683cf5c5f478ba25ddeb0d) --- source3/smbd/process.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 40d6818f3f..7ec08cb4a7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1072,11 +1072,10 @@ set. Ignoring max smbd restriction.\n")); } /**************************************************************************** - Process an smb from the client - split out from the smbd_process() code so - it can be used by the oplock break code. + Process an smb from the client ****************************************************************************/ -void process_smb(char *inbuf, char *outbuf) +static void process_smb(char *inbuf, char *outbuf) { static int trans_num; int msg_type = CVAL(inbuf,0); -- cgit From 1af229a8f822e3595e3282fc3187c2e7d705aac0 Mon Sep 17 00:00:00 2001 From: James Peach Date: Sun, 19 Mar 2006 23:32:50 +0000 Subject: r14574: Allow use of sendfile as long as the write cache has not been enabled on the particular file we are performing I/O on, irrespective of whether the write cache is globally enabled (This used to be commit 0809e2cb1dfff1cd0e8631b23b415cb2d8a67312) --- source3/smbd/reply.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 83f527d326..ce41266a1c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2176,7 +2176,8 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st * reply_readbraw has already checked the length. */ - if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) { + if ( (chain_size == 0) && (nread > 0) && + (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) { DATA_BLOB header; _smb_setlen(outbuf,nread); @@ -2529,8 +2530,8 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length * on a train in Germany :-). JRA. */ - if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && - (lp_write_cache_size(SNUM(conn)) == 0) ) { + if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) && + lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { SMB_STRUCT_STAT sbuf; DATA_BLOB header; -- cgit From 292afdba59de411f9d6d4ff69d11b1da068df5da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Mar 2006 23:40:43 +0000 Subject: r14596: Fix a logic bug with multiple oplock contention. The sad thing is the core of this bug fix is just removing a paranoia "exit_server" call, as the rest of the logic was already correct :-). Lots of comments to explain the logic added. I will look at adding tests to exercise this, might be possible. Jeremy. (This used to be commit c2488db727e1a00f112be7b169de9e6208e311f3) --- source3/smbd/open.c | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8913db8380..0cf8b68c28 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1091,20 +1091,14 @@ files_struct *open_file_ntcreate(connection_struct *conn, struct deferred_open_record *state = (struct deferred_open_record *)pml->private_data.data; + /* Remember the absolute time of the original + request with this mid. We'll use it later to + see if this has timed out. */ + request_time = pml->request_time; delayed_for_oplocks = state->delayed_for_oplocks; - /* There could be a race condition where the dev/inode pair - has changed since we deferred the message. If so, just - remove the deferred open entry and return sharing - violation. */ - - /* If the timeout value is non-zero, we need to just return - sharing violation. Don't retry the open as we were not - notified of a close and we don't want to trigger another - spurious oplock break. */ - - /* Now remove the deferred open entry under lock. */ + /* Remove the deferred open entry under lock. */ lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); @@ -1327,15 +1321,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (delay_for_oplocks(lck, fsp)) { struct deferred_open_record state; - struct timeval timeout; - if (delayed_for_oplocks) { - DEBUG(0, ("Trying to delay for oplocks " - "twice\n")); - exit_server("exiting"); - } + /* This is a relative time, added to the absolute + request_time value to get the absolute timeout time. + Note that if this is the second or greater time we enter + this codepath for this particular request mid then + request_time is left as the absolute time of the *first* + time this request mid was processed. This is what allows + the request to eventually time out. */ - timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + struct timeval timeout; /* Normally the smbd we asked should respond within * OPLOCK_BREAK_TIMEOUT seconds regardless of whether @@ -1343,6 +1338,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, * measure here in case the other smbd is stuck * somewhere else. */ + timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + + /* Nothing actually uses state.delayed_for_oplocks + but it's handy to differentiate in debug messages + between a 30 second delay due to oplock break, and + a 1 second delay for share mode conflicts. */ + state.delayed_for_oplocks = True; state.dev = dev; state.inode = inode; @@ -1434,8 +1436,21 @@ files_struct *open_file_ntcreate(connection_struct *conn, struct timeval timeout; struct deferred_open_record state; + /* This is a relative time, added to the absolute + request_time value to get the absolute timeout time. + Note that if this is the second or greater time we enter + this codepath for this particular request mid then + request_time is left as the absolute time of the *first* + time this request mid was processed. This is what allows + the request to eventually time out. */ + timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT); + /* Nothing actually uses state.delayed_for_oplocks + but it's handy to differentiate in debug messages + between a 30 second delay due to oplock break, and + a 1 second delay for share mode conflicts. */ + state.delayed_for_oplocks = False; state.dev = dev; state.inode = inode; -- cgit From 97ee5b1afa342eea40f973f5370c9f620c63bd01 Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 21 Mar 2006 02:56:49 +0000 Subject: r14600: Refactor capability interface from being IRIX-specific to using only the POSIX interface. Note that this removes support for inherited capabilities. This wasn't used, and probably should not be. (This used to be commit 763f4c01488a96aec000c18bca313da37ed1df1b) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/oplock_irix.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 224ae3d763..aef487f4a7 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -417,7 +417,7 @@ while we were waiting\n", WTERMSIG(wstat))); /* * Lose any oplock capabilities. */ - oplock_set_capability(False, False); + drop_effective_capability(KERNEL_OPLOCK_CAPABILITY); /* make sure it doesn't freeze */ alarm(20); diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 8f01438745..83883444a7 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -35,7 +35,7 @@ static BOOL irix_oplocks_available(void) int pfd[2]; pstring tmpname; - oplock_set_capability(True, False); + set_effective_capability(KERNEL_OPLOCK_CAPABILITY); slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid()); -- cgit From 5067cca077ab8dde110f79ea9e60611dc25ddf64 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Mar 2006 06:53:49 +0000 Subject: r14602: Fix another logic bug in new oplock handling. Just because lck->num_share_modes != 0 doesn't mean that there *are* other valid share modes. They may be all marked "UNUSED" or be deferred open entries. In that case don't downgrade the granted oplock to level2 needlessly - a client can have an exclusive oplock in this case. The original code handled this correctly in the lck->num_share_modes == 0 case but not in the case where there were no valid share modes but lck->num_share_modes != 0. I'll clean up my Samba4 torture tester for this and commit it tomorrow. Jeremy. (This used to be commit 306061c93d9181262298516fefd83444f5a65ce5) --- source3/smbd/open.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0cf8b68c28..5de03b8dd7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -612,6 +612,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) { int i; struct share_mode_entry *exclusive = NULL; + BOOL valid_entry = False; BOOL delay_it = False; BOOL have_level2 = False; @@ -620,33 +621,36 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) return False; } - if (lck->num_share_modes == 0) { - /* No files open at all: Directly grant whatever the client - * wants. */ - - if (fsp->oplock_type == NO_OPLOCK) { - /* Store a level2 oplock, but don't tell the client */ - fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; - } - return False; - } - for (i=0; inum_share_modes; i++) { if (!is_valid_share_mode_entry(&lck->share_modes[i])) { continue; } + /* At least one entry is not an invalid or deferred entry. */ + valid_entry = True; + if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { SMB_ASSERT(exclusive == NULL); exclusive = &lck->share_modes[i]; } if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { + SMB_ASSERT(exclusive == NULL); have_level2 = True; } } + if (!valid_entry) { + /* All entries are placeholders or deferred. + * Directly grant whatever the client wants. */ + if (fsp->oplock_type == NO_OPLOCK) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + return False; + } + if (exclusive != NULL) { /* Found an exclusive oplock */ SMB_ASSERT(!have_level2); delay_it = is_delete_request(fsp) ? @@ -654,7 +658,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) } if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - /* We can at most grant level2 */ + /* We can at most grant level2 as there are other + * level2 or NO_OPLOCK entries. */ fsp->oplock_type = LEVEL_II_OPLOCK; } -- cgit From 250c02554ec3dd52f33e33406fdd605f5d932d5f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Mar 2006 13:16:50 +0000 Subject: r14618: add --no-process-group to all server programms to make the following possible: timelimit 20000 bin/nmbd -F -S --no-process-group timelimit 20000 bin/smbd -F -S --no-process-group this is needed to 'make test' working without losing child processes metze (This used to be commit c3a9f30e2a12cc852c9fa3a7d161f5c6ee0694ce) --- source3/smbd/server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2e96b4ceb9..46ab191530 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -715,6 +715,7 @@ void build_options(BOOL screen); static BOOL is_daemon = False; static BOOL interactive = False; static BOOL Fork = True; + static BOOL no_process_group = False; static BOOL log_stdout = False; static char *ports = NULL; int opt; @@ -725,6 +726,7 @@ void build_options(BOOL screen); {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" }, + {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, @@ -865,7 +867,7 @@ void build_options(BOOL screen); if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork); + become_daemon(Fork, no_process_group); } #if HAVE_SETPGID @@ -873,8 +875,9 @@ void build_options(BOOL screen); * If we're interactive we want to set our own process group for * signal management. */ - if (interactive) + if (interactive && !no_process_group) { setpgid( (pid_t)0, (pid_t)0); + } #endif if (!directory_exist(lp_lockdir(), NULL)) -- cgit From 40d0707827ee154bcb03013abe6f72f1026a70c9 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 22 Mar 2006 23:49:09 +0000 Subject: r14668: Set the FILE_STATUS_OFFLINE bit by observing the events a DMAPI-based HSM is interested in. Tested on both IRIX and SLES9. (This used to be commit 514a767c57f8194547e5b708ad2573ab9a0719c6) --- source3/smbd/chgpasswd.c | 3 +- source3/smbd/dmapi.c | 576 +++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/dosmode.c | 30 +++ source3/smbd/server.c | 6 + 4 files changed, 614 insertions(+), 1 deletion(-) create mode 100644 source3/smbd/dmapi.c (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index aef487f4a7..16b44a54bf 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -415,9 +415,10 @@ while we were waiting\n", WTERMSIG(wstat))); /* CHILD */ /* - * Lose any oplock capabilities. + * Lose any elevated privileges. */ drop_effective_capability(KERNEL_OPLOCK_CAPABILITY); + drop_effective_capability(DMAPI_ACCESS_CAPABILITY); /* make sure it doesn't freeze */ alarm(20); diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c new file mode 100644 index 0000000000..0fa3a16760 --- /dev/null +++ b/source3/smbd/dmapi.c @@ -0,0 +1,576 @@ +/* + Unix SMB/CIFS implementation. + DMAPI Support routines + + Copyright (C) James Peach 2006 + + 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_DMAPI + +#if defined(HAVE_LIBDM) +#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) +#define USE_DMAPI 1 +#endif +#endif + +#ifndef USE_DMAPI + +int dmapi_init_session(void) { return -1; } +uint32 dmapi_file_flags(const char * const path) { return 0; } +BOOL dmapi_have_session(void) { return False; } + +#else /* USE_DMAPI */ + +#ifdef HAVE_XFS_DMAPI_H +#include +#endif + +#ifdef HAVE_SYS_DMI_H +#include +#endif + +#define DMAPI_SESSION_NAME "samba" +#define DMAPI_TRACE 10 + +static dm_sessid_t dmapi_session = DM_NO_SESSION; + +/* Initialise the DMAPI interface. Make sure that we only end up initialising + * once per process to avoid resource leaks across different DMAPI + * implementations. + */ +static int init_dmapi_service(void) +{ + static pid_t lastpid; + + pid_t mypid; + + mypid = sys_getpid(); + if (mypid != lastpid) { + char *version; + + lastpid = mypid; + if (dm_init_service(&version) < 0) { + return -1; + } + + DEBUG(0, ("Initializing DMAPI: %s\n", version)); + } + + return 0; +} + +BOOL dmapi_have_session(void) +{ + return dmapi_session != DM_NO_SESSION; +} + +static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) +{ + dm_sessid_t *nsessions; + + nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); + if (nsessions == NULL) { + TALLOC_FREE(sessions); + return NULL; + } + + return nsessions; +} + +/* Initialise DMAPI session. The session is persistant kernel state, so it + * might already exist, in which case we merely want to reconnect to it. This + * function should be called as root. + */ +int dmapi_init_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + uint nsessions = 10; + dm_sessid_t *sessions = NULL; + + int i, err; + + /* If we aren't root, something in the following will fail due to lack + * of privileges. Aborting seems a little extreme. + */ + SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); + + dmapi_session = DM_NO_SESSION; + if (init_dmapi_service() < 0) { + return -1; + } + +retry: + + if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { + return -1; + } + + err = dm_getall_sessions(nsessions, sessions, &nsessions); + if (err < 0) { + if (errno == E2BIG) { + nsessions *= 2; + goto retry; + } + + DEBUGADD(DMAPI_TRACE, + ("failed to retrieve DMAPI sessions: %s\n", + strerror(errno))); + TALLOC_FREE(sessions); + return -1; + } + + for (i = 0; i < nsessions; ++i) { + err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); + buf[sizeof(buf) - 1] = '\0'; + if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { + dmapi_session = sessions[i]; + DEBUGADD(DMAPI_TRACE, + ("attached to existing DMAPI session " + "named '%s'\n", buf)); + break; + } + } + + TALLOC_FREE(sessions); + + /* No session already defined. */ + if (dmapi_session == DM_NO_SESSION) { + err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, + &dmapi_session); + if (err < 0) { + DEBUGADD(DMAPI_TRACE, + ("failed to create new DMAPI session: %s\n", + strerror(errno))); + dmapi_session = DM_NO_SESSION; + return -1; + } + + DEBUGADD(DMAPI_TRACE, + ("created new DMAPI session named '%s'\n", + DMAPI_SESSION_NAME)); + } + + /* Note that we never end the DMAPI session. This enables child + * processes to continue to use the session after we exit. It also lets + * you run a second Samba server on different ports without any + * conflict. + */ + + return 0; +} + +/* Reattach to an existing dmapi session. Called from service processes that + * might not be running as root. + */ +static int reattach_dmapi_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + if (dmapi_session != DM_NO_SESSION ) { + become_root(); + + /* NOTE: On Linux, this call opens /dev/dmapi, costing us a + * file descriptor. Ideally, we would close this when we fork. + */ + if (init_dmapi_service() < 0) { + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + if (dm_query_session(dmapi_session, sizeof(buf), + buf, &buflen) < 0) { + /* Session is stale. Disable DMAPI. */ + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + set_effective_capability(DMAPI_ACCESS_CAPABILITY); + + DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); + unbecome_root(); + } + + return 0; +} + +uint32 dmapi_file_flags(const char * const path) +{ + static int attached = 0; + + int err; + dm_eventset_t events = {0}; + uint nevents; + + void *dm_handle; + size_t dm_handle_len; + + uint32 flags = 0; + + /* If a DMAPI session has been initialised, then we need to make sure + * we are attached to it and have the correct privileges. This is + * necessary to be able to do DMAPI operations across a fork(2). If + * it fails, there is no liklihood of that failure being transient. + * + * Note that this use of the static attached flag relies on the fact + * that dmapi_file_flags() is never called prior to forking the + * per-client server process. + */ + if (dmapi_have_session() && !attached) { + attached++; + if (reattach_dmapi_session() < 0) { + return 0; + } + } + + err = dm_path_to_handle(CONST_DISCARD(char *, path), + &dm_handle, &dm_handle_len); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n", + path, strerror(errno))); + + if (errno != EPERM) { + return 0; + } + + /* Linux capabilities are broken in that changing our + * user ID will clobber out effective capabilities irrespective + * of whether we have set PR_SET_KEEPCAPS. Fortunately, the + * capabilities are not removed from our permitted set, so we + * can re-acquire them if necessary. + */ + + set_effective_capability(DMAPI_ACCESS_CAPABILITY); + + err = dm_path_to_handle(CONST_DISCARD(char *, path), + &dm_handle, &dm_handle_len); + if (err < 0) { + DEBUG(DMAPI_TRACE, + ("retrying dm_path_to_handle(%s): %s\n", + path, strerror(errno))); + return 0; + } + } + + err = dm_get_eventlist(dmapi_session, dm_handle, dm_handle_len, + DM_NO_TOKEN, DM_EVENT_MAX, &events, &nevents); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_get_eventlist(%s): %s\n", + path, strerror(errno))); + dm_handle_free(dm_handle, dm_handle_len); + return 0; + } + + /* We figure that the only reason a DMAPI application would be + * interested in trapping read events is that part of the file is + * offline. + */ + DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", + path, events)); + if (DMEV_ISSET(DM_EVENT_READ, events)) { + flags = FILE_ATTRIBUTE_OFFLINE; + } + + dm_handle_free(dm_handle, dm_handle_len); + + if (flags & FILE_ATTRIBUTE_OFFLINE) { + DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); + } + + return flags; +} + +#endif /* USE_DMAPI */ +/* + Unix SMB/CIFS implementation. + DMAPI Support routines + + Copyright (C) Silicon Graphics, Inc. 2006. All rights reserved. + James Peach + + 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_DMAPI + +#if defined(HAVE_LIBDM) +#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) +#define USE_DMAPI 1 +#endif +#endif + +#ifndef USE_DMAPI + +int dmapi_init_session(void) { return -1; } +uint32 dmapi_file_flags(const char * const path) { return 0; } +BOOL dmapi_have_session(void) { return False; } + +#else /* USE_DMAPI */ + +#ifdef HAVE_XFS_DMAPI_H +#include +#endif + +#ifdef HAVE_SYS_DMI_H +#include +#endif + +#define DMAPI_SESSION_NAME "samba" +#define DMAPI_TRACE 10 + +static dm_sessid_t dmapi_session = DM_NO_SESSION; + +/* Initialise the DMAPI interface. Make sure that we only end up initialising + * once per process to avoid resource leaks across different DMAPI + * implementations. + */ +static int init_dmapi_service(void) +{ + static pid_t lastpid; + + pid_t mypid; + + mypid = sys_getpid(); + if (mypid != lastpid) { + char *version; + + lastpid = mypid; + if (dm_init_service(&version) < 0) { + return -1; + } + + DEBUG(0, ("Initializing DMAPI: %s\n", version)); + } + + return 0; +} + +BOOL dmapi_have_session(void) +{ + return dmapi_session != DM_NO_SESSION; +} + +static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) +{ + dm_sessid_t *nsessions; + + nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); + if (nsessions == NULL) { + TALLOC_FREE(sessions); + return NULL; + } + + return nsessions; +} + +/* Initialise DMAPI session. The session is persistant kernel state, so it + * might already exist, in which case we merely want to reconnect to it. This + * function should be called as root. + */ +int dmapi_init_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + uint nsessions = 10; + dm_sessid_t *sessions = NULL; + + int i, err; + + /* If we aren't root, something in the following will fail due to lack + * of privileges. Aborting seems a little extreme. + */ + SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); + + dmapi_session = DM_NO_SESSION; + if (init_dmapi_service() < 0) { + return -1; + } + +retry: + + if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { + return -1; + } + + err = dm_getall_sessions(nsessions, sessions, &nsessions); + if (err < 0) { + if (errno == E2BIG) { + nsessions *= 2; + goto retry; + } + + DEBUGADD(DMAPI_TRACE, + ("failed to retrieve DMAPI sessions: %s\n", + strerror(errno))); + TALLOC_FREE(sessions); + return -1; + } + + for (i = 0; i < nsessions; ++i) { + err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); + buf[sizeof(buf) - 1] = '\0'; + if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { + dmapi_session = sessions[i]; + DEBUGADD(DMAPI_TRACE, + ("attached to existing DMAPI session " + "named '%s'\n", buf)); + break; + } + } + + TALLOC_FREE(sessions); + + /* No session already defined. */ + if (dmapi_session == DM_NO_SESSION) { + err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, + &dmapi_session); + if (err < 0) { + DEBUGADD(DMAPI_TRACE, + ("failed to create new DMAPI session: %s\n", + strerror(errno))); + return -1; + } + + DEBUGADD(DMAPI_TRACE, + ("created new DMAPI session named '%s'\n", + DMAPI_SESSION_NAME)); + } + + /* Note that we never end the DMAPI session. This enables child + * processes to continue to use the session after we exit. It also lets + * you run a second Samba server on different ports without any + * conflict. + */ + + return 0; +} + +/* Reattach to an existing dmapi session. Called from service processes that + * might not be running as root. + */ +static int reattach_dmapi_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + if (dmapi_session != DM_NO_SESSION ) { + become_root(); + + /* NOTE: On Linux, this call opens /dev/dmapi, costing us a + * file descriptor. Ideally, we would close this when we fork. + */ + if (init_dmapi_service() < 0) { + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + if (dm_query_session(dmapi_session, sizeof(buf), + buf, &buflen) < 0) { + /* Session is stale. Disable DMAPI. */ + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + set_effective_capability(DMAPI_ACCESS_CAPABILITY); + + DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); + unbecome_root(); + return 0; + } + + return 0; +} + +uint32 dmapi_file_flags(const char * const path) +{ + int err; + dm_eventset_t events = {0}; + uint nevents; + + void *dm_handle; + size_t dm_handle_len; + + uint32 flags = 0; + + if (dmapi_have_session()) { + if (reattach_dmapi_session() < 0) { + return 0; + } + } + + err = dm_path_to_handle(CONST_DISCARD(char *, path), + &dm_handle, &dm_handle_len); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n", + path, strerror(errno))); + return 0; + } + + err = dm_get_eventlist(dmapi_session, dm_handle, dm_handle_len, + DM_NO_TOKEN, DM_EVENT_MAX, &events, &nevents); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_get_eventlist: %s\n", + strerror(errno))); + dm_handle_free(dm_handle, dm_handle_len); + return 0; + } + + /* We figure that the only reason a DMAPI application would be + * interested in trapping read events is that part of the file is + * offline. + */ + DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", + path, events)); + if (DMEV_ISSET(DM_EVENT_READ, events)) { + flags = FILE_ATTRIBUTE_OFFLINE; + } + + dm_handle_free(dm_handle, dm_handle_len); + + if (flags & FILE_ATTRIBUTE_OFFLINE) { + DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); + } + + return flags; +} + +#endif /* USE_DMAPI */ diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 7f3bda582d..f376de1343 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. dos mode handling functions Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) James Peach 2006 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 @@ -30,6 +31,31 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf) return 0; } +/**************************************************************************** + Work out whether this file is offline +****************************************************************************/ + +#ifndef ISDOT +#define ISDOT(p) (*(p) == '.' && *((p) + 1) == '\0') +#endif /* ISDOT */ + +#ifndef ISDOTDOT +#define ISDOTDOT(p) (*(p) == '.' && *((p) + 1) == '.' && *((p) + 2) == '\0') +#endif /* ISDOTDOT */ + +static uint32 set_offline_flag(connection_struct *conn, const char *const path) +{ + if (ISDOT(path) || ISDOTDOT(path)) { + return 0; + } + + if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) { + return 0; + } + + return dmapi_file_flags(path); +} + /**************************************************************************** Change a dos mode to a unix mode. Base permission for files: @@ -325,6 +351,10 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) result |= dos_mode_from_sbuf(conn, path, sbuf); } + if (S_ISREG(sbuf->st_mode)) { + result |= set_offline_flag(conn, path); + } + /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 46ab191530..5da73046a1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -930,6 +930,12 @@ void build_options(BOOL screen); if ( is_daemon && !interactive ) start_background_queue(); + /* Always attempt to initialize DMAPI. We will only use it later if + * lp_dmapi_support is set on the share, but we need a single global + * session to work with. + */ + dmapi_init_session(); + if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); -- cgit From a7d1a32b1470c5903ae720cfbc0f05ed2348c931 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 23 Mar 2006 00:12:37 +0000 Subject: r14669: Remove duplicate source caused by running patch(1) once too often. (This used to be commit 0ebbfc867c71002eaf921f4f4d8aa7d7b78973a7) --- source3/smbd/dmapi.c | 272 --------------------------------------------------- 1 file changed, 272 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 0fa3a16760..2188924d4b 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -302,275 +302,3 @@ uint32 dmapi_file_flags(const char * const path) } #endif /* USE_DMAPI */ -/* - Unix SMB/CIFS implementation. - DMAPI Support routines - - Copyright (C) Silicon Graphics, Inc. 2006. All rights reserved. - James Peach - - 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" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_DMAPI - -#if defined(HAVE_LIBDM) -#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) -#define USE_DMAPI 1 -#endif -#endif - -#ifndef USE_DMAPI - -int dmapi_init_session(void) { return -1; } -uint32 dmapi_file_flags(const char * const path) { return 0; } -BOOL dmapi_have_session(void) { return False; } - -#else /* USE_DMAPI */ - -#ifdef HAVE_XFS_DMAPI_H -#include -#endif - -#ifdef HAVE_SYS_DMI_H -#include -#endif - -#define DMAPI_SESSION_NAME "samba" -#define DMAPI_TRACE 10 - -static dm_sessid_t dmapi_session = DM_NO_SESSION; - -/* Initialise the DMAPI interface. Make sure that we only end up initialising - * once per process to avoid resource leaks across different DMAPI - * implementations. - */ -static int init_dmapi_service(void) -{ - static pid_t lastpid; - - pid_t mypid; - - mypid = sys_getpid(); - if (mypid != lastpid) { - char *version; - - lastpid = mypid; - if (dm_init_service(&version) < 0) { - return -1; - } - - DEBUG(0, ("Initializing DMAPI: %s\n", version)); - } - - return 0; -} - -BOOL dmapi_have_session(void) -{ - return dmapi_session != DM_NO_SESSION; -} - -static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) -{ - dm_sessid_t *nsessions; - - nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); - if (nsessions == NULL) { - TALLOC_FREE(sessions); - return NULL; - } - - return nsessions; -} - -/* Initialise DMAPI session. The session is persistant kernel state, so it - * might already exist, in which case we merely want to reconnect to it. This - * function should be called as root. - */ -int dmapi_init_session(void) -{ - char buf[DM_SESSION_INFO_LEN]; - size_t buflen; - - uint nsessions = 10; - dm_sessid_t *sessions = NULL; - - int i, err; - - /* If we aren't root, something in the following will fail due to lack - * of privileges. Aborting seems a little extreme. - */ - SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); - - dmapi_session = DM_NO_SESSION; - if (init_dmapi_service() < 0) { - return -1; - } - -retry: - - if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { - return -1; - } - - err = dm_getall_sessions(nsessions, sessions, &nsessions); - if (err < 0) { - if (errno == E2BIG) { - nsessions *= 2; - goto retry; - } - - DEBUGADD(DMAPI_TRACE, - ("failed to retrieve DMAPI sessions: %s\n", - strerror(errno))); - TALLOC_FREE(sessions); - return -1; - } - - for (i = 0; i < nsessions; ++i) { - err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); - buf[sizeof(buf) - 1] = '\0'; - if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { - dmapi_session = sessions[i]; - DEBUGADD(DMAPI_TRACE, - ("attached to existing DMAPI session " - "named '%s'\n", buf)); - break; - } - } - - TALLOC_FREE(sessions); - - /* No session already defined. */ - if (dmapi_session == DM_NO_SESSION) { - err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, - &dmapi_session); - if (err < 0) { - DEBUGADD(DMAPI_TRACE, - ("failed to create new DMAPI session: %s\n", - strerror(errno))); - return -1; - } - - DEBUGADD(DMAPI_TRACE, - ("created new DMAPI session named '%s'\n", - DMAPI_SESSION_NAME)); - } - - /* Note that we never end the DMAPI session. This enables child - * processes to continue to use the session after we exit. It also lets - * you run a second Samba server on different ports without any - * conflict. - */ - - return 0; -} - -/* Reattach to an existing dmapi session. Called from service processes that - * might not be running as root. - */ -static int reattach_dmapi_session(void) -{ - char buf[DM_SESSION_INFO_LEN]; - size_t buflen; - - if (dmapi_session != DM_NO_SESSION ) { - become_root(); - - /* NOTE: On Linux, this call opens /dev/dmapi, costing us a - * file descriptor. Ideally, we would close this when we fork. - */ - if (init_dmapi_service() < 0) { - dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - if (dm_query_session(dmapi_session, sizeof(buf), - buf, &buflen) < 0) { - /* Session is stale. Disable DMAPI. */ - dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - set_effective_capability(DMAPI_ACCESS_CAPABILITY); - - DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); - unbecome_root(); - return 0; - } - - return 0; -} - -uint32 dmapi_file_flags(const char * const path) -{ - int err; - dm_eventset_t events = {0}; - uint nevents; - - void *dm_handle; - size_t dm_handle_len; - - uint32 flags = 0; - - if (dmapi_have_session()) { - if (reattach_dmapi_session() < 0) { - return 0; - } - } - - err = dm_path_to_handle(CONST_DISCARD(char *, path), - &dm_handle, &dm_handle_len); - if (err < 0) { - DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n", - path, strerror(errno))); - return 0; - } - - err = dm_get_eventlist(dmapi_session, dm_handle, dm_handle_len, - DM_NO_TOKEN, DM_EVENT_MAX, &events, &nevents); - if (err < 0) { - DEBUG(DMAPI_TRACE, ("dm_get_eventlist: %s\n", - strerror(errno))); - dm_handle_free(dm_handle, dm_handle_len); - return 0; - } - - /* We figure that the only reason a DMAPI application would be - * interested in trapping read events is that part of the file is - * offline. - */ - DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", - path, events)); - if (DMEV_ISSET(DM_EVENT_READ, events)) { - flags = FILE_ATTRIBUTE_OFFLINE; - } - - dm_handle_free(dm_handle, dm_handle_len); - - if (flags & FILE_ATTRIBUTE_OFFLINE) { - DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); - } - - return flags; -} - -#endif /* USE_DMAPI */ -- cgit From e4878351816d7196efab22b68672430fb61e7b47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 24 Mar 2006 18:40:28 +0000 Subject: r14695: Patch from Björn Jacke: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add DMAPI/XDSM support for AIX - find JFS DMAPI libs on Linux when only they are available Volker (This used to be commit b6b72f8c6a03001ae75457c9e7a78e189bea5a3f) --- source3/smbd/dmapi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 2188924d4b..4a6cba293b 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -24,8 +24,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_DMAPI -#if defined(HAVE_LIBDM) -#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) +#if defined(HAVE_LIBDM) || defined(HAVE_LIBJFSDM) || defined(HAVE_LIBXDSM) +#if defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H) || defined(HAVE_SYS_JFSDMAPI_H) || defined(HAVE_SYS_DMAPI_H) #define USE_DMAPI 1 #endif #endif @@ -40,10 +40,12 @@ BOOL dmapi_have_session(void) { return False; } #ifdef HAVE_XFS_DMAPI_H #include -#endif - -#ifdef HAVE_SYS_DMI_H +#elif defined(HAVE_SYS_DMI_H) #include +#elif defined(HAVE_SYS_JFSDMAPI_H) +#include +#elif defined(HAVE_SYS_DMAPI_H) +#include #endif #define DMAPI_SESSION_NAME "samba" -- cgit From 1d3fd5201c98417ba40bb367d92c3a924f947799 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Mar 2006 19:50:45 +0000 Subject: r14746: Add the Samba4 replacements for opendir/readdir etc. to Samba3 - with some 64-bit macro madness. Attempt to fix the broken directory handling in the *BSD-of-the-month club. Jeremy. (This used to be commit fd98427f64f4206c01f16f82fadf24f5863878db) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 001d42d172..07e18caa5c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -712,7 +712,7 @@ char *vfs_readdirname(connection_struct *conn, void *p) return(NULL); #endif -#ifdef HAVE_BROKEN_READDIR +#ifdef HAVE_BROKEN_READDIR_NAME /* using /usr/ucb/cc is BAD */ dname = dname - 2; #endif -- cgit From 75c965d3a45b6f72b2d2eeb5937ce19dc33af419 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Mar 2006 23:45:08 +0000 Subject: r14790: Fix possible null deref. Coverity #277. Jeremy. (This used to be commit 2454af392a71989ecddb2dbb17a9217658102523) --- source3/smbd/sesssetup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index fcb778d1fe..3280e2d5fc 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -217,7 +217,9 @@ static int reply_spnego_kerberos(connection_struct *conn, if (pac_data) { logon_info = get_logon_info_from_pac(pac_data); - netsamlogon_cache_store( client, &logon_info->info3 ); + if (logon_info) { + netsamlogon_cache_store( client, &logon_info->info3 ); + } } if (!strequal(p+1, lp_realm())) { -- cgit From ecc0c18889cb3d844310fb91130680df22663a31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 1 Apr 2006 05:41:34 +0000 Subject: r14847: Tell static checkers that exit_server() doesn't return. Jeremy. (This used to be commit 9c5e26a56aaaf1143b43e61d208ddaeb96f2ffcb) --- source3/smbd/server.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5da73046a1..4d737d2849 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -570,10 +570,14 @@ BOOL reload_services(BOOL test) #if DUMP_CORE + +static void dump_core(void) NORETURN_ATTRIBUTE ; + /******************************************************************* prepare to dump a core file - carefully! ********************************************************************/ -static BOOL dump_core(void) + +static void dump_core(void) { char *p; pstring dname; @@ -584,7 +588,9 @@ static BOOL dump_core(void) mkdir(dname,0700); sys_chown(dname,getuid(),getgid()); chmod(dname,0700); - if (chdir(dname)) return(False); + if (chdir(dname)) { + abort(); + } umask(~(0700)); #ifdef HAVE_GETRLIMIT @@ -608,7 +614,6 @@ static BOOL dump_core(void) CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); #endif abort(); - return(True); } #endif @@ -616,7 +621,7 @@ static BOOL dump_core(void) Exit the server. ****************************************************************************/ -void exit_server(const char *reason) + void exit_server(const char *reason) { static int firsttime=1; @@ -659,7 +664,7 @@ void exit_server(const char *reason) DEBUGLEVEL = oldlevel; DEBUG(0,("===============================================================\n")); #if DUMP_CORE - if (dump_core()) return; + dump_core(); #endif } -- cgit From 872d3cea871264eed0159f49fba8621dd357ef1d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 1 Apr 2006 18:22:31 +0000 Subject: r14849: Fix >= that should be >. Too strict condition checked by Volker. Jeremy. (This used to be commit 9a763da07385bf9af437cab8dd680f2e13fca3c3) --- source3/smbd/ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 77746cb12f..427b6ae214 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -509,7 +509,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int goto bad_param; if (pdisp > tpscnt) goto bad_param; - if ((smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) || + if ((smb_base(inbuf) + poff + pcnt > inbuf + bufsize) || (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) goto bad_param; if (params + pdisp < params) @@ -525,7 +525,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int goto bad_param; if (ddisp > tdscnt) goto bad_param; - if ((smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) || + if ((smb_base(inbuf) + doff + dcnt > inbuf + bufsize) || (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) goto bad_param; if (data + ddisp < data) -- cgit From 6c9eaa6880897aabbc56ad3d7bd73dfc69f926f9 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sun, 2 Apr 2006 06:25:11 +0000 Subject: r14855: Various fixes: * depreacte 'acl group control' after discussion with Jeremy and implement functionality as part of 'dos filemode' * fix winbindd on a non-member server to expand local groups * prevent code previously only used by smbd from blindly turning _NO_WINBINDD back on (This used to be commit 4ab372f4cab22225716b5c9a9a08f0c1dbc9928d) --- source3/smbd/posix_acls.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ca0c51b1ea..40cb6698a0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2250,18 +2250,20 @@ static BOOL current_user_in_group(gid_t gid) } /**************************************************************************** - Should we override a deny ? + Should we override a deny ? Check deprecated 'acl group control' + and 'dos filemode' ****************************************************************************/ static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid) { - if ((errno == EACCES || errno == EPERM) && - lp_acl_group_control(SNUM(conn)) && - current_user_in_group(prim_gid)) { + if ( (errno == EACCES || errno == EPERM) + && (lp_acl_group_control(SNUM(conn) || lp_dos_filemode(SNUM(conn)))) + && current_user_in_group(prim_gid) ) + { return True; - } else { - return False; - } + } + + return False; } /**************************************************************************** -- cgit From 18e93247aa417eaf7c8fbf649ce45726ccba7433 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 3 Apr 2006 10:43:34 +0000 Subject: r14883: add 'smbd:sharedelay' option, so that we can speed up BASE-DENY2 in make test as done in samba4 metze (This used to be commit b98dd258a74a1e1b4e967e6176a5a92986d03123) --- source3/smbd/open.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5de03b8dd7..ba0a16035a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1440,6 +1440,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, lp_defer_sharing_violations()) { struct timeval timeout; struct deferred_open_record state; + int timeout_usecs; + + /* this is a hack to speed up torture tests + in 'make test' */ + timeout_usecs = lp_parm_int(conn->service, + "smbd","sharedelay", + SHARING_VIOLATION_USEC_WAIT); /* This is a relative time, added to the absolute request_time value to get the absolute timeout time. @@ -1449,7 +1456,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, time this request mid was processed. This is what allows the request to eventually time out. */ - timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT); + timeout = timeval_set(0, timeout_usecs); /* Nothing actually uses state.delayed_for_oplocks but it's handy to differentiate in debug messages -- cgit From 4fa555980070d78b39711ef21d77628d26055bc2 Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 4 Apr 2006 00:27:50 +0000 Subject: r14898: This change is an attempt to improve the quality of the information that is produced when a process exits abnormally. First, we coalesce the core dumping code so that we greatly improve our odds of being able to produce a core file, even in the case of a memory fault. I've removed duplicates of dump_core() and split it in two to reduce the amount of work needed to actually do the dump. Second, we refactor the exit_server code path to always log an explanation and a stack trace. My goal is to always produce enough log information for us to be able to explain any server exit, though there is a risk that this could produce too much log information on a flaky network. Finally, smbcontrol has gained a smbd fault injection operation to test the changes above. This is only enabled for developer builds. (This used to be commit 56bc02d64498eb3faf89f0c5452b9299daea8e95) --- source3/smbd/open.c | 4 +- source3/smbd/process.c | 2 +- source3/smbd/server.c | 162 ++++++++++++++++++++++++++----------------------- 3 files changed, 89 insertions(+), 79 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ba0a16035a..99a7894762 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -724,7 +724,7 @@ static void defer_open(struct share_mode_lock *lck, if (procid_is_me(&e->pid) && (e->op_mid == mid)) { DEBUG(0, ("Trying to defer an already deferred " "request: mid=%d, exiting\n", mid)); - exit_server("exiting"); + exit_server("attempt to defer a deferred request"); } } @@ -738,7 +738,7 @@ static void defer_open(struct share_mode_lock *lck, if (!push_deferred_smb_message(mid, request_time, timeout, (char *)state, sizeof(*state))) { - exit_server("push_deferred_smb_message failed\n"); + exit_server("push_deferred_smb_message failed"); } add_deferred_open(lck, mid, request_time, state->dev, state->inode); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7ec08cb4a7..40d26f7672 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -303,7 +303,7 @@ static void async_processing(fd_set *pfds) process_aio_queue(); if (got_sig_term) { - exit_server("Caught TERM signal"); + exit_server_cleanly(); } /* check for async change notify events */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4d737d2849..dfead851e8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,10 +22,6 @@ #include "includes.h" -#ifdef HAVE_SYS_PRCTL_H -#include -#endif - static int am_parent = 1; /* the last message the was processed */ @@ -156,8 +152,40 @@ static BOOL open_sockets_inetd(void) static void msg_exit_server(int msg_type, struct process_id src, void *buf, size_t len) { - exit_server("Got a SHUTDOWN message"); + DEBUG(3, ("got a SHUTDOWN message\n")); + exit_server_cleanly(); +} + +#ifdef DEVELOPER +static void msg_inject_fault(int msg_type, struct process_id src, + void *buf, size_t len) +{ + int sig; + + if (len != sizeof(int)) { + + DEBUG(0, ("Process %llu sent bogus signal injection request\n", + (unsigned long long)src.pid)); + return; + } + + sig = *(int *)buf; + if (sig == -1) { + exit_server("internal error injected"); + return; + } + +#if HAVE_STRSIGNAL + DEBUG(0, ("Process %llu requested injection of signal %d (%s)\n", + (unsigned long long)src.pid, sig, strsignal(sig))); +#else + DEBUG(0, ("Process %llu requested injection of signal %d\n", + (unsigned long long)src.pid, sig)); +#endif + + kill(sys_getpid(), sig); } +#endif /* DEVELOPER */ /**************************************************************************** @@ -345,6 +373,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated); +#ifdef DEVELOPER + message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault); +#endif + /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); @@ -365,7 +397,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ if (num == -1 && errno == EINTR) { if (got_sig_term) { - exit_server("Caught TERM signal"); + exit_server_cleanly(); } /* check for sighup processing */ @@ -568,60 +600,18 @@ BOOL reload_services(BOOL test) return(ret); } - -#if DUMP_CORE - -static void dump_core(void) NORETURN_ATTRIBUTE ; - -/******************************************************************* -prepare to dump a core file - carefully! -********************************************************************/ - -static void dump_core(void) -{ - char *p; - pstring dname; - - pstrcpy(dname,lp_logfile()); - if ((p=strrchr_m(dname,'/'))) *p=0; - pstrcat(dname,"/corefiles"); - mkdir(dname,0700); - sys_chown(dname,getuid(),getgid()); - chmod(dname,0700); - if (chdir(dname)) { - abort(); - } - umask(~(0700)); - -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_CORE - { - struct rlimit rlp; - getrlimit(RLIMIT_CORE, &rlp); - rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur); - setrlimit(RLIMIT_CORE, &rlp); - getrlimit(RLIMIT_CORE, &rlp); - DEBUG(3,("Core limits now %d %d\n", - (int)rlp.rlim_cur,(int)rlp.rlim_max)); - } -#endif -#endif - - - DEBUG(0,("Dumping core in %s\n", dname)); - /* Ensure we don't have a signal handler for abort. */ -#ifdef SIGABRT - CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); -#endif - abort(); -} -#endif - /**************************************************************************** Exit the server. ****************************************************************************/ - void exit_server(const char *reason) +/* Reasons for shutting down a server process. */ +enum server_exit_reason { SERVER_EXIT_NORMAL, SERVER_EXIT_ABNORMAL }; + +static void exit_server_common(enum server_exit_reason how, + const char *const reason) NORETURN_ATTRIBUTE; + +static void exit_server_common(enum server_exit_reason how, + const char *const reason) { static int firsttime=1; @@ -630,7 +620,6 @@ static void dump_core(void) firsttime = 0; change_to_root_user(); - DEBUG(2,("Closing connections\n")); if (negprot_global_auth_context) { (negprot_global_auth_context->free)(&negprot_global_auth_context); @@ -654,27 +643,54 @@ static void dump_core(void) } #endif - if (!reason) { + locking_end(); + printing_end(); + + if (how != SERVER_EXIT_NORMAL) { int oldlevel = DEBUGLEVEL; char *last_inbuf = get_InBuffer(); + DEBUGLEVEL = 10; - DEBUG(0,("Last message was %s\n",smb_fn_name(last_message))); - if (last_inbuf) + + DEBUGSEP(0); + DEBUG(0,("Abnormal server exit: %s\n", + reason ? reason : "no explanation provided")); + DEBUGSEP(0); + + log_stack_trace(); + if (last_inbuf) { + DEBUG(0,("Last message was %s\n", LAST_MESSAGE())); show_msg(last_inbuf); + } + DEBUGLEVEL = oldlevel; - DEBUG(0,("===============================================================\n")); #if DUMP_CORE dump_core(); #endif - } - locking_end(); - printing_end(); + } else { + DEBUG(3,("Server exit (%s)\n", + (reason ? reason : "normal exit"))); + } - DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); exit(0); } +void exit_server(const char *const explanation) +{ + exit_server_common(SERVER_EXIT_ABNORMAL, explanation); +} + +void exit_server_cleanly(void) +{ + exit_server_common(SERVER_EXIT_NORMAL, NULL); +} + +void exit_server_fault(void) +{ + exit_server("critical server fault"); +} + /**************************************************************************** Initialise connect, service and file structs. ****************************************************************************/ @@ -795,7 +811,9 @@ void build_options(BOOL screen); gain_root_privilege(); gain_root_group_privilege(); - fault_setup((void (*)(void *))exit_server); + fault_setup((void (*)(void *))exit_server_fault); + dump_core_setup("smbd"); + CatchSignal(SIGTERM , SIGNAL_CAST sig_term); CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); @@ -948,14 +966,6 @@ void build_options(BOOL screen); * everything after this point is run after the fork() */ -#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) - /* On Linux we lose the ability to dump core when we change our user - * ID. We know how to dump core safely, so let's make sure we have our - * dumpable flag set. - */ - prctl(PR_SET_DUMPABLE, 1); -#endif - /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ @@ -1002,9 +1012,9 @@ void build_options(BOOL screen); message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); smbd_process(); - + namecache_shutdown(); - exit_server("normal exit"); + exit_server_cleanly(); return(0); } -- cgit From 4ee43dbd477140bd4bf6c42d156dc0a736994da2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 6 Apr 2006 22:31:45 +0000 Subject: r14954: Fix #3569 based on William Jojo's work. AIX also has the linear posix locking issue which causes CLEAR_IF_FIRST to cause performance problems. As we know we're in a daemon architecture with long-lived parent we can avoid this in the Samba case. Add a comment explaining this. Jeremy. (This used to be commit 3cd5c3df0d1b98dfa90663973ab13b5d3dbf737e) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index dfead851e8..ba31827eb3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -474,7 +474,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ set_need_random_reseed(); /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */ - if (tdb_reopen_all() == -1) { + if (tdb_reopen_all(1) == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); smb_panic("tdb_reopen_all failed."); } -- cgit From 876f2deb3a6029b4e02ec25bc3099bfa07840a14 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 8 Apr 2006 05:00:04 +0000 Subject: r14986: Fix OS/2 directory delete bug found by kukks. (Thanks a lot for all your hard work on this). We were caching the results of *all* directory scans, not just the results that match the client wildcard. This actually made no sense, as only matches on the client wildcard can be returned to the client and so might need to be searched for in the cache. This fixes the directory cache to only cache entries that we return to the client. Jeremy. (This used to be commit c88af597d042390ff11b26fe802b0b10d0faa6ce) --- source3/smbd/dir.c | 36 ++++++++++++++++++++++++++++-------- source3/smbd/trans2.c | 2 ++ 2 files changed, 30 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 81fe7c4021..cd6c1b0bda 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -644,6 +644,15 @@ BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S return False; } +/**************************************************************************** + Add the name we're returning into the underlying cache. +****************************************************************************/ + +void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset) +{ + DirCacheAdd(dptr->dir_hnd, name, offset); +} + /**************************************************************************** Fill the 5 byte server reserved dptr field. ****************************************************************************/ @@ -812,6 +821,8 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); found = True; + + DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff); } } @@ -1109,21 +1120,15 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) } while ((n = vfs_readdirname(conn, dirp->dir))) { - struct name_cache_entry *e; /* Ignore . and .. - we've already returned them. */ if (*n == '.') { if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) { continue; } } - dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); - dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; - e = &dirp->name_cache[dirp->name_cache_index]; - SAFE_FREE(e->name); - e->name = SMB_STRDUP(n); - *poffset = e->offset= dirp->offset; + *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); dirp->file_number++; - return e->name; + return n; } *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET; return NULL; @@ -1183,6 +1188,21 @@ long TellDir(struct smb_Dir *dirp) return(dirp->offset); } +/******************************************************************* + Add an entry into the dcache. +********************************************************************/ + +void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) +{ + struct name_cache_entry *e; + + dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; + e = &dirp->name_cache[dirp->name_cache_index]; + SAFE_FREE(e->name); + e->name = SMB_STRDUP(name); + e->offset = offset; +} + /******************************************************************* Find an entry by name. Leave us at the offset after it. Don't check for veto or invisible files. diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8429cd7149..4f5039e86c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1163,6 +1163,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); found = True; + + dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos); } } -- cgit From c9c502442b40aba97de17456ba948effcdfa3d05 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 8 Apr 2006 05:09:12 +0000 Subject: r14989: Fix from Mathias Dietz . EPERM can be a valid return from getting an xattr. Don't disable if we get it. Jeremy. (This used to be commit 7769b678f22d8ab4aa8aef55966813355bf2ce6d) --- source3/smbd/dosmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index f376de1343..583b3f19e7 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -222,7 +222,7 @@ static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); if (sizeret == -1) { #if defined(ENOTSUP) && defined(ENOATTR) - if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES)) { + if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES) && (errno != EPERM)) { DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n", path, strerror(errno) )); set_store_dos_attributes(SNUM(conn), False); -- cgit From 22dbd67708f1651a2341d70ce576fac360affccf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Apr 2006 15:33:04 +0000 Subject: r15018: Merge Volker's ipc/trans2/nttrans changes over into 3.0. Also merge the new POSIX lock code - this is not enabled unless -DDEVELOPER is defined. This doesn't yet map onto underlying system POSIX locks. Updates vfs to allow lock queries. Jeremy. (This used to be commit 08e52ead03304ff04229e1bfe544ff40e2564fc7) --- source3/smbd/blocking.c | 277 ++++++++++---- source3/smbd/ipc.c | 452 ++++++++++++++--------- source3/smbd/nttrans.c | 604 +++++++++++++++--------------- source3/smbd/process.c | 31 +- source3/smbd/reply.c | 112 ++++-- source3/smbd/server.c | 3 +- source3/smbd/trans2.c | 963 ++++++++++++++++++++++++++++++++---------------- source3/smbd/vfs-wrap.c | 12 +- source3/smbd/vfs.c | 1 + 9 files changed, 1561 insertions(+), 894 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 805e45f6ea..6b47d0466b 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -35,6 +35,8 @@ typedef struct _blocking_lock_record { SMB_BIG_UINT offset; SMB_BIG_UINT count; uint16 lock_pid; + enum brl_flavour lock_flav; + enum brl_type lock_type; char *inbuf; int length; } blocking_lock_record; @@ -52,25 +54,6 @@ static void free_blocking_lock_record(blocking_lock_record *blr) SAFE_FREE(blr); } -/**************************************************************************** - Get the files_struct given a particular queued SMB. -*****************************************************************************/ - -static files_struct *get_fsp_from_pkt(char *inbuf) -{ - switch(CVAL(inbuf,smb_com)) { - case SMBlock: - case SMBlockread: - return file_fsp(inbuf,smb_vwv0); - case SMBlockingX: - return file_fsp(inbuf,smb_vwv2); - default: - DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return NULL; /* Keep compiler happy. */ -} - /**************************************************************************** Determine if this is a secondary element of a chained SMB. **************************************************************************/ @@ -87,12 +70,19 @@ static void received_unlock_msg(int msg_type, struct process_id src, Function to push a blocking lock request onto the lock queue. ****************************************************************************/ -BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, - int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) +BOOL push_blocking_lock_request( char *inbuf, int length, + files_struct *fsp, + int lock_timeout, + int lock_num, + uint16 lock_pid, + enum brl_type lock_type, + enum brl_flavour lock_flav, + SMB_BIG_UINT offset, SMB_BIG_UINT count) { static BOOL set_lock_msg; blocking_lock_record *blr, *tmp; BOOL my_lock_ctx = False; + struct byte_range_lock *br_lck = NULL; NTSTATUS status; if(in_chained_smb() ) { @@ -110,6 +100,9 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, return False; } + blr->next = NULL; + blr->prev = NULL; + if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); SAFE_FREE(blr); @@ -117,19 +110,33 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, } blr->com_type = CVAL(inbuf,smb_com); - blr->fsp = get_fsp_from_pkt(inbuf); + blr->fsp = fsp; blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; blr->lock_num = lock_num; blr->lock_pid = lock_pid; + blr->lock_flav = lock_flav; + blr->lock_type = lock_type; blr->offset = offset; blr->count = count; memcpy(blr->inbuf, inbuf, length); blr->length = length; + br_lck = brl_get_locks(NULL, blr->fsp); + if (!br_lck) { + free_blocking_lock_record(blr); + return False; + } + /* Add a pending lock record for this. */ - status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - lock_pid, procid_self(), blr->fsp->conn->cnum, - offset, count, PENDING_LOCK, &my_lock_ctx); + status = brl_lock(br_lck, + lock_pid, + procid_self(), + offset, + count, + PENDING_LOCK, + blr->lock_flav, + &my_lock_ctx); + TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -227,7 +234,6 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) { char *inbuf = blr->inbuf; files_struct *fsp = blr->fsp; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; uint16 lock_pid; @@ -261,7 +267,11 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) * request would never have been queued. JRA. */ - do_unlock(fsp,conn,lock_pid,count,offset); + do_unlock(fsp, + lock_pid, + count, + offset, + WINDOWS_LOCK); } generic_blocking_lock_error(blr, status); @@ -274,19 +284,41 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status) { switch(blr->com_type) { +#if 0 + /* We no longer push blocking lock requests for anything but lockingX and trans2. */ case SMBlock: case SMBlockread: generic_blocking_lock_error(blr, status); break; +#endif case SMBlockingX: reply_lockingX_error(blr, status); break; + case SMBtrans2: + case SMBtranss2: + { + char *outbuf = get_OutBuffer(); + char *inbuf = blr->inbuf; + construct_reply_common(inbuf, outbuf); + /* construct_reply_common has done us the favor to pre-fill the + * command field with SMBtranss2 which is wrong :-) + */ + SCVAL(outbuf,smb_com,SMBtrans2); + ERROR_NT(status); + if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("blocking_lock_reply_error: send_smb failed."); + } + break; + } default: DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); exit_server("PANIC - unknown type on blocking lock queue"); } } +#if 0 +/* We no longer push blocking lock requests for anything but lockingX and trans2. */ + /**************************************************************************** Attempt to finish off getting all pending blocking locks for a lockread call. Returns True if we want to be removed from the list. @@ -302,7 +334,6 @@ static BOOL process_lockread(blocking_lock_record *blr) SMB_BIG_UINT startpos; size_t numtoread; NTSTATUS status; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; BOOL my_lock_ctx = False; @@ -312,7 +343,14 @@ static BOOL process_lockread(blocking_lock_record *blr) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx); + status = do_lock_spin(fsp, + SVAL(inbuf,smb_pid), + (SMB_BIG_UINT)numtoread, + startpos, + READ_LOCK, + WINDOWS_LOCK, + &my_lock_ctx); + if (NT_STATUS_V(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { @@ -371,7 +409,6 @@ static BOOL process_lock(blocking_lock_record *blr) int outsize; SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; NTSTATUS status; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; BOOL my_lock_ctx = False; @@ -379,7 +416,14 @@ static BOOL process_lock(blocking_lock_record *blr) offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); errno = 0; - status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); + status = do_lock_spin(fsp, + SVAL(inbuf,smb_pid), + count, + offset, + WRITE_LOCK, + WINDOWS_LOCK, + &my_lock_ctx); + if (NT_STATUS_IS_ERR(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { @@ -412,6 +456,7 @@ static BOOL process_lock(blocking_lock_record *blr) send_blocking_reply(outbuf,outsize); return True; } +#endif /**************************************************************************** Attempt to finish off getting all pending blocking locks for a lockingX call. @@ -423,7 +468,6 @@ static BOOL process_lockingX(blocking_lock_record *blr) char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); files_struct *fsp = blr->fsp; - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; @@ -452,9 +496,17 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - status = do_lock_spin(fsp,conn,lock_pid,count,offset, - ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx); - if (NT_STATUS_IS_ERR(status)) break; + status = do_lock_spin(fsp, + lock_pid, + count, + offset, + ((locktype & 1) ? READ_LOCK : WRITE_LOCK), + WINDOWS_LOCK, + &my_lock_ctx); + + if (NT_STATUS_IS_ERR(status)) { + break; + } } if(blr->lock_num == num_locks) { @@ -490,6 +542,51 @@ Waiting....\n", return False; } +/**************************************************************************** + Attempt to get the posix lock request from a SMBtrans2 call. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL process_trans2(blocking_lock_record *blr) +{ + extern int max_send; + char *inbuf = blr->inbuf; + char *outbuf; + BOOL my_lock_ctx = False; + char params[2]; + NTSTATUS status; + + status = do_lock(blr->fsp, + blr->lock_pid, + blr->count, + blr->offset, + blr->lock_type, + blr->lock_flav, + &my_lock_ctx); + + if (!NT_STATUS_IS_OK(status)) { + if (ERROR_WAS_LOCK_DENIED(status)) { + /* Still can't get the lock, just keep waiting. */ + return False; + } + /* + * We have other than a "can't get lock" + * error. Send an error and return True so we get dequeued. + */ + blocking_lock_reply_error(blr, status); + return True; + } + + /* We finally got the lock, return success. */ + outbuf = get_OutBuffer(); + construct_reply_common(inbuf, outbuf); + SCVAL(outbuf,smb_com,SMBtrans2); + SSVAL(params,0,0); + send_trans2_replies(outbuf, max_send, params, 2, NULL, 0); + return True; +} + + /**************************************************************************** Process a blocking lock SMB. Returns True if we want to be removed from the list. @@ -498,12 +595,18 @@ Waiting....\n", static BOOL blocking_lock_record_process(blocking_lock_record *blr) { switch(blr->com_type) { +#if 0 + /* We no longer push blocking lock requests for anything but lockingX and trans2. */ case SMBlock: return process_lock(blr); case SMBlockread: return process_lockread(blr); +#endif case SMBlockingX: return process_lockingX(blr); + case SMBtrans2: + case SMBtranss2: + return process_trans2(blr); default: DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); exit_server("PANIC - unknown type on blocking lock queue"); @@ -522,13 +625,21 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) for(blr = blocking_lock_queue; blr; blr = next) { next = blr->next; if(blr->fsp->fnum == fsp->fnum) { + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); - DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ + if (br_lck) { + DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, procid_self(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + brl_remove_pending_lock(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav); + TALLOC_FREE(br_lck); + + } free_blocking_lock_record(blr); } @@ -547,14 +658,22 @@ void remove_pending_lock_requests_by_mid(int mid) next = blr->next; if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); - DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ + if (br_lck) { + DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); + brl_remove_pending_lock(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav); + TALLOC_FREE(br_lck); + } + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, procid_self(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); } } @@ -635,16 +754,25 @@ void process_blocking_lock_queue(time_t t) fsp->fnum, fsp->fsp_name )); if((blr->expire_time != -1) && (blr->expire_time <= t)) { + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + /* * Lock expired - throw away all previously * obtained locks and return lock error. */ - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, procid_self(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + if (br_lck) { + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fsp->fnum, fsp->fsp_name )); + + brl_remove_pending_lock(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav); + TALLOC_FREE(br_lck); + } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); free_blocking_lock_record(blr); @@ -652,32 +780,48 @@ void process_blocking_lock_queue(time_t t) } if(!change_to_user(conn,vuid)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + /* * Remove the entry and return an error to the client. */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, procid_self(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + if (br_lck) { + brl_remove_pending_lock(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav); + TALLOC_FREE(br_lck); + } + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); free_blocking_lock_record(blr); continue; } if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + /* * Remove the entry and return an error to the client. */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, procid_self(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + if (br_lck) { + brl_remove_pending_lock(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav); + TALLOC_FREE(br_lck); + } + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); free_blocking_lock_record(blr); change_to_root_user(); continue; @@ -690,10 +834,17 @@ void process_blocking_lock_queue(time_t t) */ if(blocking_lock_record_process(blr)) { - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, procid_self(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + + if (br_lck) { + brl_remove_pending_lock(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav); + TALLOC_FREE(br_lck); + } free_blocking_lock_record(blr); } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 427b6ae214..1b5a5f39c7 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -355,259 +355,349 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na return 0; } +static NTSTATUS handle_trans(connection_struct *conn, + struct trans_state *state, + char *outbuf, int *outsize) +{ + char *local_machine_name; + int name_offset = 0; + + DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", + state->name,state->total_data,state->total_param, + state->setup_count)); + + /* + * WinCE wierdness.... + */ + + local_machine_name = talloc_asprintf(state, "\\%s\\", + get_local_machine_name()); + + if (local_machine_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (strnequal(state->name, local_machine_name, + strlen(local_machine_name))) { + name_offset = strlen(local_machine_name)-1; + } + + if (!strnequal(&state->name[name_offset], "\\PIPE", + strlen("\\PIPE"))) { + return NT_STATUS_NOT_SUPPORTED; + } + + name_offset += strlen("\\PIPE"); + + /* Win9x weirdness. When talking to a unicode server Win9x + only sends \PIPE instead of \PIPE\ */ + + if (state->name[name_offset] == '\\') + name_offset++; + + DEBUG(5,("calling named_pipe\n")); + *outsize = named_pipe(conn, state->vuid, outbuf, + state->name+name_offset, + state->setup,state->data, + state->param, + state->setup_count,state->total_data, + state->total_param, + state->max_setup_return, + state->max_data_return, + state->max_param_return); + + if (*outsize == 0) { + return NT_STATUS_NOT_SUPPORTED; + } + + if (state->close_on_completion) + close_cnum(conn,state->vuid); + + return NT_STATUS_OK; +} /**************************************************************************** Reply to a SMBtrans. ****************************************************************************/ -int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize) +int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, + int size, int bufsize) { - fstring name; - int name_offset = 0; - char *data=NULL,*params=NULL; - uint16 *setup=NULL; int outsize = 0; - uint16 vuid = SVAL(inbuf,smb_uid); - unsigned int tpscnt = SVAL(inbuf,smb_vwv0); - unsigned int tdscnt = SVAL(inbuf,smb_vwv1); - unsigned int mprcnt = SVAL(inbuf,smb_vwv2); - unsigned int mdrcnt = SVAL(inbuf,smb_vwv3); - unsigned int msrcnt = CVAL(inbuf,smb_vwv4); - BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); - BOOL one_way = BITSETW(inbuf+smb_vwv5,1); - unsigned int pscnt = SVAL(inbuf,smb_vwv9); - unsigned int psoff = SVAL(inbuf,smb_vwv10); - unsigned int dscnt = SVAL(inbuf,smb_vwv11); - unsigned int dsoff = SVAL(inbuf,smb_vwv12); - unsigned int suwcnt = CVAL(inbuf,smb_vwv13); - char *local_machine_name; + unsigned int dsoff = SVAL(inbuf, smb_dsoff); + unsigned int dscnt = SVAL(inbuf, smb_dscnt); + unsigned int psoff = SVAL(inbuf, smb_psoff); + unsigned int pscnt = SVAL(inbuf, smb_pscnt); + struct trans_state *state; + NTSTATUS result; + START_PROFILE(SMBtrans); - memset(name, '\0',sizeof(name)); - srvstr_pull_buf(inbuf, name, smb_buf(inbuf), sizeof(name), STR_TERMINATE); + if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans, + SVAL(inbuf, smb_mid)))) { + DEBUG(2, ("Got invalid trans request: %s\n", + nt_errstr(result))); + END_PROFILE(SMBtrans); + return ERROR_NT(result); + } - if (dscnt > tdscnt || pscnt > tpscnt) + if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) { + DEBUG(0, ("talloc failed\n")); + END_PROFILE(SMBtrans); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + state->cmd = SMBtrans; + + state->mid = SVAL(inbuf, smb_mid); + state->vuid = SVAL(inbuf, smb_uid); + state->setup_count = CVAL(inbuf, smb_suwcnt); + state->total_param = SVAL(inbuf, smb_tpscnt); + state->param = NULL; + state->total_data = SVAL(inbuf, smb_tdscnt); + state->data = NULL; + state->max_param_return = SVAL(inbuf, smb_mprcnt); + state->max_data_return = SVAL(inbuf, smb_mdrcnt); + state->max_setup_return = CVAL(inbuf, smb_msrcnt); + state->close_on_completion = BITSETW(inbuf+smb_vwv5,0); + state->one_way = BITSETW(inbuf+smb_vwv5,1); + + memset(state->name, '\0',sizeof(state->name)); + srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf), + sizeof(state->name), STR_TERMINATE); + + if ((dscnt > state->total_data) || (pscnt > state->total_param)) goto bad_param; - - if (tdscnt) { - if((data = (char *)SMB_MALLOC(tdscnt)) == NULL) { - DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt)); + + if (state->total_data) { + /* Can't use talloc here, the core routines do realloc on the + * params and data. */ + state->data = SMB_MALLOC(state->total_data); + if (state->data == NULL) { + DEBUG(0,("reply_trans: data malloc fail for %u " + "bytes !\n", state->total_data)); + TALLOC_FREE(state); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || - (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) + (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) goto bad_param; - memcpy(data,smb_base(inbuf)+dsoff,dscnt); + memcpy(state->data,smb_base(inbuf)+dsoff,dscnt); } - if (tpscnt) { - if((params = (char *)SMB_MALLOC(tpscnt)) == NULL) { - DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt)); - SAFE_FREE(data); + if (state->total_param) { + /* Can't use talloc here, the core routines do realloc on the + * params and data. */ + state->param = SMB_MALLOC(state->total_param); + if (state->param == NULL) { + DEBUG(0,("reply_trans: param malloc fail for %u " + "bytes !\n", state->total_param)); + SAFE_FREE(state->data); + TALLOC_FREE(state); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || - (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) + (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) goto bad_param; - memcpy(params,smb_base(inbuf)+psoff,pscnt); + memcpy(state->param,smb_base(inbuf)+psoff,pscnt); } - if (suwcnt) { + state->received_data = dscnt; + state->received_param = pscnt; + + if (state->setup_count) { unsigned int i; - if((setup = SMB_MALLOC_ARRAY(uint16,suwcnt)) == NULL) { - DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16)))); - SAFE_FREE(data); - SAFE_FREE(params); + if((state->setup = TALLOC_ARRAY( + state, uint16, state->setup_count)) == NULL) { + DEBUG(0,("reply_trans: setup malloc fail for %u " + "bytes !\n", (unsigned int) + (state->setup_count * sizeof(uint16)))); + TALLOC_FREE(state); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } - if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size) + if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) > + inbuf + size) goto bad_param; - if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD))) + if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) || + (smb_vwv14+(state->setup_count*SIZEOFWORD) < + (state->setup_count*SIZEOFWORD))) goto bad_param; - for (i=0;isetup_count;i++) + state->setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD); } + state->received_param = pscnt; - srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if ((state->received_param == state->total_param) && + (state->received_data == state->total_data)) { - if (pscnt < tpscnt || dscnt < tdscnt) { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - show_msg(outbuf); - srv_signing_trans_stop(); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_trans: send_smb failed."); - } + result = handle_trans(conn, state, outbuf, &outsize); + + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); - /* receive the rest of the trans packet */ - while (pscnt < tpscnt || dscnt < tdscnt) { - BOOL ret; - unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; - - ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); - - /* - * The sequence number for the trans reply is always - * based on the last secondary received. - */ - - srv_signing_trans_start(SVAL(inbuf,smb_mid)); - - if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) { - if(ret) { - DEBUG(0,("reply_trans: Invalid secondary trans packet\n")); - } else { - DEBUG(0,("reply_trans: %s in getting secondary trans response.\n", - (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - } - SAFE_FREE(params); - SAFE_FREE(data); - SAFE_FREE(setup); + if (!NT_STATUS_IS_OK(result)) { END_PROFILE(SMBtrans); - srv_signing_trans_stop(); - return(ERROR_DOS(ERRSRV,ERRerror)); + return ERROR_NT(result); } - show_msg(inbuf); - - /* Revise total_params and total_data in case they have changed downwards */ - if (SVAL(inbuf,smb_vwv0) < tpscnt) - tpscnt = SVAL(inbuf,smb_vwv0); - if (SVAL(inbuf,smb_vwv1) < tdscnt) - tdscnt = SVAL(inbuf,smb_vwv1); - - pcnt = SVAL(inbuf,smb_vwv2); - poff = SVAL(inbuf,smb_vwv3); - pdisp = SVAL(inbuf,smb_vwv4); - - dcnt = SVAL(inbuf,smb_vwv5); - doff = SVAL(inbuf,smb_vwv6); - ddisp = SVAL(inbuf,smb_vwv7); - - pscnt += pcnt; - dscnt += dcnt; - - if (dscnt > tdscnt || pscnt > tpscnt) - goto bad_param; - - if (pcnt) { - if (pdisp+pcnt > tpscnt) - goto bad_param; - if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) - goto bad_param; - if (pdisp > tpscnt) - goto bad_param; - if ((smb_base(inbuf) + poff + pcnt > inbuf + bufsize) || - (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) - goto bad_param; - if (params + pdisp < params) - goto bad_param; - - memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); + if (outsize == 0) { + END_PROFILE(SMBtrans); + return ERROR_NT(NT_STATUS_INTERNAL_ERROR); } - if (dcnt) { - if (ddisp+dcnt > tdscnt) - goto bad_param; - if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) - goto bad_param; - if (ddisp > tdscnt) - goto bad_param; - if ((smb_base(inbuf) + doff + dcnt > inbuf + bufsize) || - (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) - goto bad_param; - if (data + ddisp < data) - goto bad_param; - - memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); - } + END_PROFILE(SMBtrans); + return outsize; } - DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", - name,tdscnt,tpscnt,suwcnt)); + DLIST_ADD(conn->pending_trans, state); - /* - * WinCE wierdness.... - */ + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + show_msg(outbuf); + END_PROFILE(SMBtrans); + return outsize; - asprintf(&local_machine_name, "\\%s\\", get_local_machine_name()); + bad_param: - if (local_machine_name == NULL) { - srv_signing_trans_stop(); - SAFE_FREE(data); - SAFE_FREE(params); - SAFE_FREE(setup); - END_PROFILE(SMBtrans); - return ERROR_NT(NT_STATUS_NO_MEMORY); + DEBUG(0,("reply_trans: invalid trans parameters\n")); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + END_PROFILE(SMBtrans); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); +} + +/**************************************************************************** + Reply to a secondary SMBtrans. + ****************************************************************************/ + +int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, + int size, int bufsize) +{ + int outsize = 0; + unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; + struct trans_state *state; + NTSTATUS result; + + START_PROFILE(SMBtranss); + + show_msg(inbuf); + + for (state = conn->pending_trans; state != NULL; + state = state->next) { + if (state->mid == SVAL(inbuf,smb_mid)) { + break; + } } - if (strnequal(name, local_machine_name, strlen(local_machine_name))) { - name_offset = strlen(local_machine_name)-1; + if ((state == NULL) || (state->cmd != SMBtrans)) { + END_PROFILE(SMBtranss); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - SAFE_FREE(local_machine_name); + /* Revise total_params and total_data in case they have changed + * downwards */ - if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) { - name_offset += strlen("\\PIPE"); + if (SVAL(inbuf, smb_vwv0) < state->total_param) + state->total_param = SVAL(inbuf,smb_vwv0); + if (SVAL(inbuf, smb_vwv1) < state->total_data) + state->total_data = SVAL(inbuf,smb_vwv1); - /* Win9x weirdness. When talking to a unicode server Win9x - only sends \PIPE instead of \PIPE\ */ + pcnt = SVAL(inbuf, smb_spscnt); + poff = SVAL(inbuf, smb_spsoff); + pdisp = SVAL(inbuf, smb_spsdisp); - if (name[name_offset] == '\\') - name_offset++; + dcnt = SVAL(inbuf, smb_sdscnt); + doff = SVAL(inbuf, smb_sdsoff); + ddisp = SVAL(inbuf, smb_sdsdisp); - DEBUG(5,("calling named_pipe\n")); - outsize = named_pipe(conn,vuid,outbuf, - name+name_offset,setup,data,params, - suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); - } else { - DEBUG(3,("invalid pipe name\n")); - outsize = 0; + state->received_param += pcnt; + state->received_data += dcnt; + + if ((state->received_data > state->total_data) || + (state->received_param > state->total_param)) + goto bad_param; + + if (pcnt) { + if (pdisp+pcnt > state->total_param) + goto bad_param; + if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) + goto bad_param; + if (pdisp > state->total_param) + goto bad_param; + if ((smb_base(inbuf) + poff + pcnt > inbuf + size) || + (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) + goto bad_param; + if (state->param + pdisp < state->param) + goto bad_param; + + memcpy(state->param+pdisp,smb_base(inbuf)+poff, + pcnt); } - - SAFE_FREE(data); - SAFE_FREE(params); - SAFE_FREE(setup); - - srv_signing_trans_stop(); + if (dcnt) { + if (ddisp+dcnt > state->total_data) + goto bad_param; + if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) + goto bad_param; + if (ddisp > state->total_data) + goto bad_param; + if ((smb_base(inbuf) + doff + dcnt > inbuf + size) || + (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) + goto bad_param; + if (state->data + ddisp < state->data) + goto bad_param; - if (close_on_completion) - close_cnum(conn,vuid); + memcpy(state->data+ddisp, smb_base(inbuf)+doff, + dcnt); + } - if (one_way) { - END_PROFILE(SMBtrans); - return(-1); + if ((state->received_param < state->total_param) || + (state->received_data < state->total_data)) { + END_PROFILE(SMBtranss); + return -1; } - - if (outsize == 0) { - END_PROFILE(SMBtrans); + + /* construct_reply_common has done us the favor to pre-fill the + * command field with SMBtranss which is wrong :-) + */ + SCVAL(outbuf,smb_com,SMBtrans); + + result = handle_trans(conn, state, outbuf, &outsize); + + DLIST_REMOVE(conn->pending_trans, state); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + + if ((outsize == 0) || !NT_STATUS_IS_OK(result)) { + END_PROFILE(SMBtranss); return(ERROR_DOS(ERRSRV,ERRnosupport)); } - END_PROFILE(SMBtrans); + END_PROFILE(SMBtranss); return(outsize); - bad_param: - srv_signing_trans_stop(); - DEBUG(0,("reply_trans: invalid trans parameters\n")); - SAFE_FREE(data); - SAFE_FREE(params); - SAFE_FREE(setup); - END_PROFILE(SMBtrans); + DEBUG(0,("reply_transs: invalid trans parameters\n")); + DLIST_REMOVE(conn->pending_trans, state); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + END_PROFILE(SMBtranss); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 796eb44332..24d64ecfc7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1811,19 +1811,6 @@ int reply_ntrename(connection_struct *conn, return(outsize); } -/**************************************************************************** - Reply to an unsolicited SMBNTtranss - just ignore it! -****************************************************************************/ - -int reply_nttranss(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) -{ - START_PROFILE(SMBnttranss); - DEBUG(4,("Ignoring nttranss of length %d\n",length)); - END_PROFILE(SMBnttranss); - return(-1); -} - /**************************************************************************** Reply to a notify change - queue the request and don't allow a directory to be opened. @@ -2719,29 +2706,120 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, } #endif /* HAVE_SYS_QUOTAS */ +static int handle_nttrans(connection_struct *conn, + struct trans_state *state, + char *inbuf, char *outbuf, int size, int bufsize) +{ + int outsize; + + if (Protocol >= PROTOCOL_NT1) { + SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ + } + + /* Now we must call the relevant NT_TRANS function */ + switch(state->call) { + case NT_TRANSACT_CREATE: + START_PROFILE_NESTED(NT_transact_create); + outsize = call_nt_transact_create(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); + END_PROFILE_NESTED(NT_transact_create); + break; + case NT_TRANSACT_IOCTL: + START_PROFILE_NESTED(NT_transact_ioctl); + outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, state->max_data_return); + END_PROFILE_NESTED(NT_transact_ioctl); + break; + case NT_TRANSACT_SET_SECURITY_DESC: + START_PROFILE_NESTED(NT_transact_set_security_desc); + outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, state->max_data_return); + END_PROFILE_NESTED(NT_transact_set_security_desc); + break; + case NT_TRANSACT_NOTIFY_CHANGE: + START_PROFILE_NESTED(NT_transact_notify_change); + outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, state->max_data_return); + END_PROFILE_NESTED(NT_transact_notify_change); + break; + case NT_TRANSACT_RENAME: + START_PROFILE_NESTED(NT_transact_rename); + outsize = call_nt_transact_rename(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, state->max_data_return); + END_PROFILE_NESTED(NT_transact_rename); + break; + + case NT_TRANSACT_QUERY_SECURITY_DESC: + START_PROFILE_NESTED(NT_transact_query_security_desc); + outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, state->max_data_return); + END_PROFILE_NESTED(NT_transact_query_security_desc); + break; +#ifdef HAVE_SYS_QUOTAS + case NT_TRANSACT_GET_USER_QUOTA: + START_PROFILE_NESTED(NT_transact_get_user_quota); + outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, state->max_data_return); + END_PROFILE_NESTED(NT_transact_get_user_quota); + break; + case NT_TRANSACT_SET_USER_QUOTA: + START_PROFILE_NESTED(NT_transact_set_user_quota); + outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, + size, bufsize, + (char **)&state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, state->max_data_return); + END_PROFILE_NESTED(NT_transact_set_user_quota); + break; +#endif /* HAVE_SYS_QUOTAS */ + default: + /* Error in request */ + DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", + state->call)); + return ERROR_DOS(ERRSRV,ERRerror); + } + return outsize; +} + /**************************************************************************** Reply to a SMBNTtrans. ****************************************************************************/ int reply_nttrans(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) + char *inbuf,char *outbuf,int size,int bufsize) { int outsize = 0; - uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); -#if 0 /* Not used. */ - uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount); - uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount); -#endif /* Not used. */ - uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount); - uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount); - uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount); - uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset); - uint32 data_count = IVAL(inbuf,smb_nt_DataCount); - uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset); - uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */ + uint32 pscnt = IVAL(inbuf,smb_nt_ParameterCount); + uint32 psoff = IVAL(inbuf,smb_nt_ParameterOffset); + uint32 dscnt = IVAL(inbuf,smb_nt_DataCount); + uint32 dsoff = IVAL(inbuf,smb_nt_DataOffset); + uint16 function_code = SVAL( inbuf, smb_nt_Function); - char *params = NULL, *data = NULL, *setup = NULL; - uint32 num_params_sofar, num_data_sofar; + NTSTATUS result; + struct trans_state *state; + START_PROFILE(SMBnttrans); if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { @@ -2749,319 +2827,269 @@ int reply_nttrans(connection_struct *conn, return ERROR_DOS(ERRSRV,ERRaccess); } - outsize = set_message(outbuf,0,0,True); + if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans, + SVAL(inbuf, smb_mid)))) { + DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result))); + END_PROFILE(SMBnttrans); + return ERROR_NT(result); + } + + if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) { + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRSRV,ERRaccess); + } + + state->cmd = SMBnttrans; + + state->mid = SVAL(inbuf,smb_mid); + state->vuid = SVAL(inbuf,smb_uid); + state->total_data = IVAL(inbuf, smb_nt_TotalDataCount); + state->data = NULL; + state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount); + state->param = NULL; + state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount); + + /* setup count is in *words* */ + state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); + state->call = function_code; /* - * All nttrans messages we handle have smb_wct == 19 + setup_count. - * Ensure this is so as a sanity check. + * All nttrans messages we handle have smb_wct == 19 + + * state->setup_count. Ensure this is so as a sanity check. */ - if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) { + if(CVAL(inbuf, smb_wct) != 19 + (state->setup_count/2)) { DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", - CVAL(inbuf, smb_wct), 19 + (setup_count/2))); + CVAL(inbuf, smb_wct), 19 + (state->setup_count/2))); goto bad_param; } /* Don't allow more than 128mb for each value. */ - if ((total_parameter_count > (1024*1024*128)) || (total_data_count > (1024*1024*128))) { + if ((state->total_data > (1024*1024*128)) || + (state->total_param > (1024*1024*128))) { END_PROFILE(SMBnttrans); return ERROR_DOS(ERRDOS,ERRnomem); } - /* Allocate the space for the setup, the maximum needed parameters and data */ - - if(setup_count > 0) { - setup = (char *)SMB_MALLOC(setup_count); - } - if (total_parameter_count > 0) { - params = (char *)SMB_MALLOC(total_parameter_count); - } - if (total_data_count > 0) { - data = (char *)SMB_MALLOC(total_data_count); - } - - if ((total_parameter_count && !params) || (total_data_count && !data) || - (setup_count && !setup)) { - SAFE_FREE(setup); - SAFE_FREE(params); - SAFE_FREE(data); - DEBUG(0,("reply_nttrans : Out of memory\n")); - END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRDOS,ERRnomem); - } - - /* Copy the param and data bytes sent with this request into the params buffer */ - num_params_sofar = parameter_count; - num_data_sofar = data_count; - - if (parameter_count > total_parameter_count || data_count > total_data_count) + if ((dscnt > state->total_data) || (pscnt > state->total_param)) goto bad_param; - if(setup) { - DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count)); - if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) || - (smb_nt_SetupStart + setup_count < setup_count)) { + if (state->total_data) { + /* Can't use talloc here, the core routines do realloc on the + * params and data. */ + if ((state->data = SMB_MALLOC(state->total_data)) == NULL) { + DEBUG(0,("reply_nttrans: data malloc fail for %u " + "bytes !\n", state->total_data)); + TALLOC_FREE(state); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; - } - if (smb_nt_SetupStart + setup_count > length) { + if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || + (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) goto bad_param; - } - memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count); - dump_data(10, setup, setup_count); + memcpy(state->data,smb_base(inbuf)+dsoff,dscnt); } - if(params) { - DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count)); - if ((parameter_offset + parameter_count < parameter_offset) || - (parameter_offset + parameter_count < parameter_count)) { + + if (state->total_param) { + /* Can't use talloc here, the core routines do realloc on the + * params and data. */ + if ((state->param = SMB_MALLOC(state->total_param)) == NULL) { + DEBUG(0,("reply_nttrans: param malloc fail for %u " + "bytes !\n", state->total_param)); + SAFE_FREE(state->data); + TALLOC_FREE(state); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; - } - if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)|| - (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) { + if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || + (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) goto bad_param; - } - memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count); - dump_data(10, params, parameter_count); + memcpy(state->param,smb_base(inbuf)+psoff,pscnt); } - if(data) { - DEBUG(10,("reply_nttrans: data_count = %d\n",data_count)); - if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) { + + state->received_data = dscnt; + state->received_param = pscnt; + + if(state->setup_count > 0) { + DEBUG(10,("reply_nttrans: state->setup_count = %d\n", + state->setup_count)); + state->setup = TALLOC(state, state->setup_count); + if (state->setup == NULL) { + DEBUG(0,("reply_nttrans : Out of memory\n")); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + END_PROFILE(SMBnttrans); + return ERROR_DOS(ERRDOS,ERRnomem); + } + + if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) || + (smb_nt_SetupStart + state->setup_count < state->setup_count)) { goto bad_param; } - if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || - (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) { + if (smb_nt_SetupStart + state->setup_count > size) { goto bad_param; } - memcpy( data, smb_base(inbuf) + data_offset, data_count); - dump_data(10, data, data_count); + memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count); + dump_data(10, (char *)state->setup, state->setup_count); } - srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if ((state->received_data == state->total_data) && + (state->received_param == state->total_param)) { + outsize = handle_nttrans(conn, state, inbuf, outbuf, + size, bufsize); + SAFE_FREE(state->param); + SAFE_FREE(state->data); + TALLOC_FREE(state); + END_PROFILE(SMBnttrans); + return outsize; + } - if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - srv_signing_trans_stop(); - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("reply_nttrans: send_smb failed."); - } + DLIST_ADD(conn->pending_trans, state); - while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { - BOOL ret; - uint32 parameter_displacement; - uint32 data_displacement; + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + show_msg(outbuf); + END_PROFILE(SMBnttrans); + return outsize; - ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + bad_param: - /* We need to re-calcuate the new length after we've read the secondary packet. */ - length = smb_len(inbuf) + 4; + DEBUG(0,("reply_nttrans: invalid trans parameters\n")); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + END_PROFILE(SMBnttrans); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); +} + +/**************************************************************************** + Reply to a SMBnttranss + ****************************************************************************/ - /* - * The sequence number for the trans reply is always - * based on the last secondary received. - */ +int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf, + int size,int bufsize) +{ + int outsize = 0; + unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; + struct trans_state *state; - srv_signing_trans_start(SVAL(inbuf,smb_mid)); + START_PROFILE(SMBnttranss); - if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) { - outsize = set_message(outbuf,0,0,True); - if(ret) { - DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n")); - } else { - DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n", - (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - } - goto bad_param; - } - - /* Revise total_params and total_data in case they have changed downwards */ - if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) { - total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); - } - if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) { - total_data_count = IVAL(inbuf, smb_nts_TotalDataCount); - } + show_msg(inbuf); - parameter_count = IVAL(inbuf,smb_nts_ParameterCount); - parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset); - parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement); - num_params_sofar += parameter_count; + for (state = conn->pending_trans; state != NULL; + state = state->next) { + if (state->mid == SVAL(inbuf,smb_mid)) { + break; + } + } - data_count = IVAL(inbuf, smb_nts_DataCount); - data_displacement = IVAL(inbuf, smb_nts_DataDisplacement); - data_offset = IVAL(inbuf, smb_nts_DataOffset); - num_data_sofar += data_count; + if ((state == NULL) || (state->cmd != SMBnttrans)) { + END_PROFILE(SMBnttranss); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } - if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) { - DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet")); - goto bad_param; - } + /* Revise state->total_param and state->total_data in case they have + changed downwards */ + if (IVAL(inbuf, smb_nts_TotalParameterCount) < state->total_param) { + state->total_param = IVAL(inbuf, smb_nts_TotalParameterCount); + } + if (IVAL(inbuf, smb_nts_TotalDataCount) < state->total_data) { + state->total_data = IVAL(inbuf, smb_nts_TotalDataCount); + } - if (parameter_count) { - if (parameter_displacement + parameter_count > total_parameter_count) { - goto bad_param; - } - if ((parameter_displacement + parameter_count < parameter_displacement) || - (parameter_displacement + parameter_count < parameter_count)) { - goto bad_param; - } - if (parameter_displacement > total_parameter_count) { - goto bad_param; - } - if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) || - (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) { - goto bad_param; - } - if (parameter_displacement + params < params) { - goto bad_param; - } + pcnt = IVAL(inbuf,smb_nts_ParameterCount); + poff = IVAL(inbuf, smb_nts_ParameterOffset); + pdisp = IVAL(inbuf, smb_nts_ParameterDisplacement); - memcpy( ¶ms[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count); - } + dcnt = IVAL(inbuf, smb_nts_DataCount); + ddisp = IVAL(inbuf, smb_nts_DataDisplacement); + doff = IVAL(inbuf, smb_nts_DataOffset); - if (data_count) { - if (data_displacement + data_count > total_data_count) { - goto bad_param; - } - if ((data_displacement + data_count < data_displacement) || - (data_displacement + data_count < data_count)) { - goto bad_param; - } - if (data_displacement > total_data_count) { - goto bad_param; - } - if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || - (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) { - goto bad_param; - } - if (data_displacement + data < data) { - goto bad_param; - } + state->received_param += pcnt; + state->received_data += dcnt; + + if ((state->received_data > state->total_data) || + (state->received_param > state->total_param)) + goto bad_param; - memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count); - } - } - } + if (pcnt) { + if (pdisp+pcnt > state->total_param) + goto bad_param; + if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) + goto bad_param; + if (pdisp > state->total_param) + goto bad_param; + if ((smb_base(inbuf) + poff + pcnt > inbuf + size) || + (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) + goto bad_param; + if (state->param + pdisp < state->param) + goto bad_param; - if (Protocol >= PROTOCOL_NT1) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME); + memcpy(state->param+pdisp,smb_base(inbuf)+poff, + pcnt); } - /* Now we must call the relevant NT_TRANS function */ - switch(function_code) { - case NT_TRANSACT_CREATE: - START_PROFILE_NESTED(NT_transact_create); - outsize = call_nt_transact_create(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_create); - break; - case NT_TRANSACT_IOCTL: - START_PROFILE_NESTED(NT_transact_ioctl); - outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_ioctl); - break; - case NT_TRANSACT_SET_SECURITY_DESC: - START_PROFILE_NESTED(NT_transact_set_security_desc); - outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_set_security_desc); - break; - case NT_TRANSACT_NOTIFY_CHANGE: - START_PROFILE_NESTED(NT_transact_notify_change); - outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_notify_change); - break; - case NT_TRANSACT_RENAME: - START_PROFILE_NESTED(NT_transact_rename); - outsize = call_nt_transact_rename(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_rename); - break; + if (dcnt) { + if (ddisp+dcnt > state->total_data) + goto bad_param; + if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) + goto bad_param; + if (ddisp > state->total_data) + goto bad_param; + if ((smb_base(inbuf) + doff + dcnt > inbuf + size) || + (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) + goto bad_param; + if (state->data + ddisp < state->data) + goto bad_param; - case NT_TRANSACT_QUERY_SECURITY_DESC: - START_PROFILE_NESTED(NT_transact_query_security_desc); - outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_query_security_desc); - break; -#ifdef HAVE_SYS_QUOTAS - case NT_TRANSACT_GET_USER_QUOTA: - START_PROFILE_NESTED(NT_transact_get_user_quota); - outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_get_user_quota); - break; - case NT_TRANSACT_SET_USER_QUOTA: - START_PROFILE_NESTED(NT_transact_set_user_quota); - outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, - length, bufsize, - &setup, setup_count, - ¶ms, total_parameter_count, - &data, total_data_count, max_data_count); - END_PROFILE_NESTED(NT_transact_set_user_quota); - break; -#endif /* HAVE_SYS_QUOTAS */ - default: - /* Error in request */ - DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); - SAFE_FREE(setup); - SAFE_FREE(params); - SAFE_FREE(data); - END_PROFILE(SMBnttrans); - srv_signing_trans_stop(); - return ERROR_DOS(ERRSRV,ERRerror); + memcpy(state->data+ddisp, smb_base(inbuf)+doff, + dcnt); } - /* As we do not know how many data packets will need to be - returned here the various call_nt_transact_xxxx calls - must send their own. Thus a call_nt_transact_xxxx routine only - returns a value other than -1 when it wants to send - an error packet. - */ + if ((state->received_param < state->total_param) || + (state->received_data < state->total_data)) { + END_PROFILE(SMBnttranss); + return -1; + } - srv_signing_trans_stop(); + /* construct_reply_common has done us the favor to pre-fill the + * command field with SMBnttranss which is wrong :-) + */ + SCVAL(outbuf,smb_com,SMBnttrans); - SAFE_FREE(setup); - SAFE_FREE(params); - SAFE_FREE(data); - END_PROFILE(SMBnttrans); - return outsize; /* If a correct response was needed the call_nt_transact_xxxx - calls have already sent it. If outsize != -1 then it is - returning an error packet. */ + outsize = handle_nttrans(conn, state, inbuf, outbuf, + size, bufsize); - bad_param: + DLIST_REMOVE(conn->pending_trans, state); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); - srv_signing_trans_stop(); - SAFE_FREE(params); - SAFE_FREE(data); - SAFE_FREE(setup); - END_PROFILE(SMBnttrans); + if (outsize == 0) { + END_PROFILE(SMBnttranss); + return(ERROR_DOS(ERRSRV,ERRnosupport)); + } + + END_PROFILE(SMBnttranss); + return(outsize); + + bad_param: + + DEBUG(0,("reply_nttranss: invalid trans parameters\n")); + DLIST_REMOVE(conn->pending_trans, state); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + END_PROFILE(SMBnttranss); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 40d26f7672..cdeccab5e8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -505,22 +505,27 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) return receive_smb(smbd_server_fd(), buffer, 0); } -/**************************************************************************** -Get the next SMB packet, doing the local message processing automatically. -****************************************************************************/ +/* + * Only allow 5 outstanding trans requests. We're allocating memory, so + * prevent a DoS. + */ -BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) +NTSTATUS allow_new_trans(struct trans_state *list, int mid) { - BOOL got_keepalive; - BOOL ret; + int count = 0; + for (; list != NULL; list = list->next) { - do { - ret = receive_message_or_smb(inbuf,bufsize,timeout); - - got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive)); - } while (ret && got_keepalive); + if (list->mid == mid) { + return NT_STATUS_INVALID_PARAMETER; + } + + count += 1; + } + if (count > 5) { + return NT_STATUS_INSUFFICIENT_RESOURCES; + } - return ret; + return NT_STATUS_OK; } /**************************************************************************** @@ -611,7 +616,7 @@ static const struct smb_message_struct { /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER }, /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC }, -/* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC}, +/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",reply_ioctl,0}, /* 0x28 */ { "SMBioctls",NULL,AS_USER}, /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ce41266a1c..040f7710fd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -269,10 +269,13 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * switch(next_mb_char_size(s)) { case 4: *d++ = *s++; + /*fall through*/ case 3: *d++ = *s++; + /*fall through*/ case 2: *d++ = *s++; + /*fall through*/ case 1: *d++ = *s++; break; @@ -374,10 +377,13 @@ NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) switch(next_mb_char_size(s)) { case 4: *d++ = *s++; + /*fall through*/ case 3: *d++ = *s++; + /*fall through*/ case 2: *d++ = *s++; + /*fall through*/ case 1: *d++ = *s++; break; @@ -2319,7 +2325,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); - if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { SMB_STRUCT_STAT st; SMB_OFF_T size = 0; @@ -2390,8 +2396,13 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * Note that the requested lock size is unaffected by max_recv. */ - status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), - (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx); + status = do_lock_spin(fsp, + SVAL(inbuf,smb_pid), + (SMB_BIG_UINT)numtoread, + (SMB_BIG_UINT)startpos, + WRITE_LOCK, + WINDOWS_LOCK, + &my_lock_ctx); if (NT_STATUS_V(status)) { #if 0 @@ -2407,8 +2418,15 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos, - (SMB_BIG_UINT)numtoread)) { + if(push_blocking_lock_request(inbuf, length, + fsp, + -1, + 0, + SVAL(inbuf,smb_pid), + WRITE_LOCK, + WINDOWS_LOCK, + (SMB_BIG_UINT)startpos, + (SMB_BIG_UINT)numtoread)) { END_PROFILE(SMBlockread); return -1; } @@ -2486,7 +2504,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", data = smb_buf(outbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBread); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2694,7 +2712,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2757,7 +2775,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SCVAL(inbuf,smb_com,SMBwritec); SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwritebraw); return(ERROR_DOS(ERRDOS,ERRlock)); } @@ -2878,7 +2896,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteunlock); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2900,8 +2918,12 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, } if (numtowrite) { - status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, - (SMB_BIG_UINT)startpos); + status = do_unlock(fsp, + SVAL(inbuf,smb_pid), + (SMB_BIG_UINT)numtowrite, + (SMB_BIG_UINT)startpos, + WINDOWS_LOCK); + if (NT_STATUS_V(status)) { END_PROFILE(SMBwriteunlock); return ERROR_NT(status); @@ -2951,7 +2973,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwrite); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3066,7 +3088,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3340,7 +3362,7 @@ int reply_writeclose(connection_struct *conn, mtime = srv_make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteclose); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3410,7 +3432,13 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); - status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); + status = do_lock_spin(fsp, + SVAL(inbuf,smb_pid), + count, + offset, + WRITE_LOCK, + WINDOWS_LOCK, + &my_lock_ctx); if (NT_STATUS_V(status)) { #if 0 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */ @@ -3420,7 +3448,14 @@ int reply_lock(connection_struct *conn, * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) { + if(push_blocking_lock_request(inbuf, length, + fsp, + -1, + 0, + SVAL(inbuf,smb_pid), + WRITE_LOCK, + WINDOWS_LOCK, + offset, count)) { END_PROFILE(SMBlock); return -1; } @@ -3452,7 +3487,12 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); - status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset); + status = do_unlock(fsp, + SVAL(inbuf,smb_pid), + count, + offset, + WINDOWS_LOCK); + if (NT_STATUS_V(status)) { END_PROFILE(SMBunlock); return ERROR_NT(status); @@ -5279,7 +5319,12 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, "pid %u, file %s\n", (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); - status = do_unlock(fsp,conn,lock_pid,count,offset); + status = do_unlock(fsp, + lock_pid, + count, + offset, + WINDOWS_LOCK); + if (NT_STATUS_V(status)) { END_PROFILE(SMBlockingX); return ERROR_NT(status); @@ -5297,6 +5342,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, of smb_lkrng structs */ for(i = 0; i < (int)num_locks; i++) { + enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK); lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); @@ -5314,9 +5360,14 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, (double)count, (unsigned int)lock_pid, fsp->fsp_name, (int)lock_timeout )); - status = do_lock_spin(fsp,conn,lock_pid, count,offset, - ((locktype & 1) ? READ_LOCK:WRITE_LOCK), - &my_lock_ctx); + status = do_lock_spin(fsp, + lock_pid, + count, + offset, + lock_type, + WINDOWS_LOCK, + &my_lock_ctx); + if (NT_STATUS_V(status)) { /* * Interesting fact found by IFSTEST /t @@ -5334,8 +5385,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, * onto the blocking lock queue. */ if(push_blocking_lock_request(inbuf, length, - lock_timeout, i, - lock_pid, offset, + fsp, + lock_timeout, + i, + lock_pid, + lock_type, + WINDOWS_LOCK, + offset, count)) { END_PROFILE(SMBlockingX); return -1; @@ -5368,7 +5424,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_DOS(ERRDOS,ERRnoaccess); } - do_unlock(fsp,conn,lock_pid,count,offset); + do_unlock(fsp, + lock_pid, + count, + offset, + WINDOWS_LOCK); } END_PROFILE(SMBlockingX); return ERROR_NT(status); @@ -5430,7 +5490,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadBmpx); return ERROR_DOS(ERRDOS,ERRlock); } @@ -5562,7 +5622,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { + if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { END_PROFILE(SMBwriteBmpx); return(ERROR_DOS(ERRDOS,ERRlock)); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ba31827eb3..0880778f55 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -898,9 +898,8 @@ void build_options(BOOL screen); * If we're interactive we want to set our own process group for * signal management. */ - if (interactive && !no_process_group) { + if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); - } #endif if (!directory_exist(lp_lockdir(), NULL)) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4f5039e86c..19463403ac 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -563,7 +563,7 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list * HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_trans2_replies(char *outbuf, +int send_trans2_replies(char *outbuf, int bufsize, char *params, int paramsize, @@ -1644,11 +1644,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", case SMB_FIND_ID_BOTH_DIRECTORY_INFO: break; case SMB_FIND_FILE_UNIX: - if (!lp_unix_extensions()) - return(ERROR_DOS(ERRDOS,ERRunknownlevel)); + if (!lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } break; default: - return(ERROR_DOS(ERRDOS,ERRunknownlevel)); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard); @@ -1926,11 +1927,12 @@ resume_key = %d resume name = %s continue=%d level = %d\n", case SMB_FIND_ID_BOTH_DIRECTORY_INFO: break; case SMB_FIND_FILE_UNIX: - if (!lp_unix_extensions()) - return(ERROR_DOS(ERRDOS,ERRunknownlevel)); + if (!lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } break; default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } if (info_level == SMB_FIND_EA_LIST) { @@ -2398,13 +2400,21 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned */ case SMB_QUERY_CIFS_UNIX_INFO: - if (!lp_unix_extensions()) - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (!lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } data_len = 12; SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); - SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP| - CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */ + /* We have POSIX ACLs, pathname and locking capability. */ + SBIG_UINT(pdata,4,((SMB_BIG_UINT)( + CIFS_UNIX_POSIX_ACLS_CAP| + CIFS_UNIX_POSIX_PATHNAMES_CAP| +#if defined(DEVELOPER) /* Not quite finished yet... */ + CIFS_UNIX_FCNTL_LOCKS_CAP))); +#else + 0))); +#endif break; case SMB_QUERY_POSIX_FS_INFO: @@ -2412,9 +2422,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int rc; vfs_statvfs_struct svfs; - if (!lp_unix_extensions()) - return ERROR_DOS(ERRDOS,ERRunknownlevel); - + if (!lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + rc = SMB_VFS_STATVFS(conn, ".", &svfs); if (!rc) { @@ -2430,7 +2441,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n")); #ifdef EOPNOTSUPP } else if (rc == EOPNOTSUPP) { - return ERROR_DOS(ERRDOS, ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); #endif /* EOPNOTSUPP */ } else { DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn)))); @@ -2451,7 +2462,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } /* drop through */ default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } @@ -2495,7 +2506,7 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb uint32 client_unix_cap_high; if (!lp_unix_extensions()) { - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } /* There should be 12 bytes of capabilities set. */ @@ -2515,8 +2526,15 @@ cap_low = 0x%x, cap_high = 0x%x\n", (unsigned int)client_unix_cap_high )); /* Here is where we must switch to posix pathname processing... */ - lp_set_posix_pathnames(); - mangle_change_to_posix(); + if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) { + lp_set_posix_pathnames(); + mangle_change_to_posix(); + } +#if defined(DEVELOPER) + if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) { + lp_set_posix_cifsx_locktype(POSIX_LOCK); + } +#endif break; } case SMB_FS_QUOTA_INFORMATION: @@ -2593,7 +2611,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", default: DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n", info_level)); - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); break; } @@ -2768,13 +2786,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * char *fullpathname; char *base_name; char *p; + char *lock_data = NULL; SMB_OFF_T pos = 0; BOOL bad_path = False; BOOL delete_pending = False; int len; time_t c_time; files_struct *fsp = NULL; - TALLOC_CTX *ea_ctx = NULL; + TALLOC_CTX *data_ctx = NULL; struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ @@ -2893,8 +2912,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * nlink -= 1; } - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n", fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data)); @@ -2913,40 +2933,70 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (!(mode & aDIR)) file_size = get_file_size(sbuf); - /* Pull any EA list from the data portion. */ - if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) { - uint32 ea_size; + /* Pull out any data sent here before we realloc. */ + switch (info_level) { + case SMB_INFO_QUERY_EAS_FROM_LIST: + { + /* Pull any EA list from the data portion. */ + uint32 ea_size; - if (total_data < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - ea_size = IVAL(pdata,0); + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + ea_size = IVAL(pdata,0); - if (total_data > 0 && ea_size != total_data) { - DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ + if (total_data > 0 && ea_size != total_data) { + DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } - if (!lp_ea_support(SNUM(conn))) { - return ERROR_DOS(ERRDOS,ERReasnotsupported); - } + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } - if ((ea_ctx = talloc_init("ea_list")) == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + if ((data_ctx = talloc_init("ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4); + if (!ea_list) { + talloc_destroy(data_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + break; } +#if defined(DEVELOPER) + case SMB_QUERY_POSIX_LOCK: + { + if (fsp == NULL || fsp->fh->fd == -1) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } - /* Pull out the list of names. */ - ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); - if (!ea_list) { - talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if (total_data != POSIX_LOCK_DATA_SIZE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if ((data_ctx = talloc_init("lock_request")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Copy the lock range data. */ + lock_data = talloc_memdup(data_ctx, pdata, total_data); + if (!lock_data) { + talloc_destroy(data_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } } +#endif + default: + break; } *pparams = SMB_REALLOC(*pparams,2); if (*pparams == NULL) { - talloc_destroy(ea_ctx); + talloc_destroy(data_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } params = *pparams; @@ -2954,7 +3004,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; *ppdata = SMB_REALLOC(*ppdata, data_size); if (*ppdata == NULL ) { - talloc_destroy(ea_ctx); + talloc_destroy(data_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } pdata = *ppdata; @@ -3040,18 +3090,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); - ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len); + ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len); ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len); if (!ea_list || (total_ea_len > data_size)) { - talloc_destroy(ea_ctx); + talloc_destroy(data_ctx); data_size = 4; SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ break; } - data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list); - talloc_destroy(ea_ctx); + data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list); + talloc_destroy(data_ctx); break; } @@ -3062,21 +3112,21 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); - ea_ctx = talloc_init("ea_ctx"); - if (!ea_ctx) { + data_ctx = talloc_init("ea_ctx"); + if (!data_ctx) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len); + ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len); if (!ea_list || (total_ea_len > data_size)) { - talloc_destroy(ea_ctx); + talloc_destroy(data_ctx); data_size = 4; SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ break; } - data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list); - talloc_destroy(ea_ctx); + data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list); + talloc_destroy(data_ctx); break; } @@ -3469,8 +3519,84 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } #endif + +#if defined(DEVELOPER) + case SMB_QUERY_POSIX_LOCK: + { + NTSTATUS status = NT_STATUS_INVALID_LEVEL; + SMB_BIG_UINT count; + SMB_BIG_UINT offset; + uint16 lock_pid; + enum brl_type lock_type; + + if (total_data != POSIX_LOCK_DATA_SIZE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { + case POSIX_LOCK_TYPE_READ: + lock_type = READ_LOCK; + break; + case POSIX_LOCK_TYPE_WRITE: + lock_type = WRITE_LOCK; + break; + case POSIX_LOCK_TYPE_UNLOCK: + default: + /* There's no point in asking for an unlock... */ + talloc_destroy(data_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET); +#if defined(HAVE_LONGLONG) + offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | + ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); + count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) | + ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET)); +#else /* HAVE_LONGLONG */ + offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET); + count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET); +#endif /* HAVE_LONGLONG */ + + status = query_lock(fsp, + &lock_pid, + &count, + &offset, + &lock_type, + POSIX_LOCK); + + if (ERROR_WAS_LOCK_DENIED(status)) { + /* Here we need to report who has it locked... */ + data_size = POSIX_LOCK_DATA_SIZE; + + SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type); + SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0); + SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid); +#if defined(HAVE_LONGLONG) + SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF)); + SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF)); + SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF)); + SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF)); +#else /* HAVE_LONGLONG */ + SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset); + SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count); +#endif /* HAVE_LONGLONG */ + + } else if (NT_STATUS_IS_OK(status)) { + /* For success we just return a copy of what we sent + with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */ + data_size = POSIX_LOCK_DATA_SIZE; + memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE); + SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK); + } else { + return ERROR_NT(status); + } + break; + } +#endif + default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size); @@ -3674,8 +3800,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } if (VALID_STAT(sbuf)) unixmode = sbuf.st_mode; @@ -3843,8 +3970,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #ifdef LARGE_SMB_OFF_T allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)allocation_size )); @@ -3910,8 +4039,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #ifdef LARGE_SMB_OFF_T size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size )); break; @@ -3964,8 +4095,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #ifdef LARGE_SMB_OFF_T position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", fname, (double)position_information )); @@ -4021,8 +4154,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #ifdef LARGE_SMB_OFF_T size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #endif /* LARGE_SMB_OFF_T */ } pdata+=24; /* ctime & st_blocks are not changed */ @@ -4329,8 +4464,109 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } #endif +#if defined(DEVELOPER) + case SMB_SET_POSIX_LOCK: + { + SMB_BIG_UINT count; + SMB_BIG_UINT offset; + uint16 lock_pid; + BOOL lock_blocking; + enum brl_type lock_type; + BOOL my_lock_ctx; + + if (fsp == NULL || fsp->fh->fd == -1) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + if (total_data != POSIX_LOCK_DATA_SIZE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { + case POSIX_LOCK_TYPE_READ: + lock_type = READ_LOCK; + break; + case POSIX_LOCK_TYPE_WRITE: + /* Return the right POSIX-mappable error code for files opened read-only. */ + if (!fsp->can_write) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + lock_type = WRITE_LOCK; + break; + case POSIX_LOCK_TYPE_UNLOCK: + lock_type = UNLOCK_LOCK; + break; + default: + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) { + lock_blocking = False; + } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) { + lock_blocking = True; + } else { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET); +#if defined(HAVE_LONGLONG) + offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | + ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); + count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) | + ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET)); +#else /* HAVE_LONGLONG */ + offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET); + count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET); +#endif /* HAVE_LONGLONG */ + + if (lock_type == UNLOCK_LOCK) { + status = do_unlock(fsp, + lock_pid, + count, + offset, + POSIX_LOCK); + } else { + status = do_lock(fsp, + lock_pid, + count, + offset, + lock_type, + POSIX_LOCK, + &my_lock_ctx); + + /* TODO: Deal with rescheduling blocking lock fail here... */ + if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, + fsp, + -1, /* infinite timeout. */ + 0, + lock_pid, + lock_type, + POSIX_LOCK, + offset, + count)) { + return -1; + } + } + } + + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } +#endif + default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } /* get some defaults (no modifications) if any info is zero or -1. */ @@ -4582,7 +4818,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char case 2: break; default: - return ERROR_DOS(ERRDOS,ERRunknownlevel); + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } /* Realloc the parameter and data sizes */ @@ -4759,331 +4995,418 @@ int reply_findnclose(connection_struct *conn, return(outsize); } -/**************************************************************************** - Reply to a SMBtranss2 - just ignore it! -****************************************************************************/ - -int reply_transs2(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) -{ - START_PROFILE(SMBtranss2); - DEBUG(4,("Ignoring transs2 of length %d\n",length)); - END_PROFILE(SMBtranss2); - return(-1); -} - -/**************************************************************************** - Reply to a SMBtrans2. -****************************************************************************/ - -int reply_trans2(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +int handle_trans2(connection_struct *conn, + struct trans_state *state, + char *inbuf, char *outbuf, int size, int bufsize) { - int outsize = 0; - unsigned int total_params = SVAL(inbuf, smb_tpscnt); - unsigned int total_data =SVAL(inbuf, smb_tdscnt); - unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt); -#if 0 - unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt); - unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt); - BOOL close_tid = BITSETW(inbuf+smb_flags,0); - BOOL no_final_response = BITSETW(inbuf+smb_flags,1); - int32 timeout = IVALS(inbuf,smb_timeout); -#endif - unsigned int suwcnt = SVAL(inbuf, smb_suwcnt); - unsigned int tran_call = SVAL(inbuf, smb_setup0); - char *params = NULL, *data = NULL; - unsigned int num_params, num_params_sofar, num_data, num_data_sofar; - START_PROFILE(SMBtrans2); - - if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) - && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) { - END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRSRV,ERRaccess); - } - - outsize = set_message(outbuf,0,0,True); - - /* All trans2 messages we handle have smb_sucnt == 1 - ensure this - is so as a sanity check */ - if (suwcnt != 1) { - /* - * Need to have rc=0 for ioctl to get job id for OS/2. - * Network printing will fail if function is not successful. - * Similar function in reply.c will be used if protocol - * is LANMAN1.0 instead of LM1.2X002. - * Until DosPrintSetJobInfo with PRJINFO3 is supported, - * outbuf doesn't have to be set(only job id is used). - */ - if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) && - (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && - (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { - DEBUG(2,("Got Trans2 DevIOctl jobid\n")); - } else { - DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt)); - DEBUG(2,("Transaction is %d\n",tran_call)); - END_PROFILE(SMBtrans2); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - } - - /* Allocate the space for the maximum needed parameters and data */ - if (total_params > 0) - params = (char *)SMB_MALLOC(total_params); - if (total_data > 0) - data = (char *)SMB_MALLOC(total_data); - - if ((total_params && !params) || (total_data && !data)) { - DEBUG(2,("Out of memory in reply_trans2\n")); - SAFE_FREE(params); - SAFE_FREE(data); - END_PROFILE(SMBtrans2); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - /* Copy the param and data bytes sent with this request into - the params buffer */ - num_params = num_params_sofar = SVAL(inbuf,smb_pscnt); - num_data = num_data_sofar = SVAL(inbuf, smb_dscnt); - - if (num_params > total_params || num_data > total_data) - exit_server("invalid params in reply_trans2"); - - if(params) { - unsigned int psoff = SVAL(inbuf, smb_psoff); - if ((psoff + num_params < psoff) || (psoff + num_params < num_params)) - goto bad_param; - if ((smb_base(inbuf) + psoff + num_params > inbuf + length) || - (smb_base(inbuf) + psoff + num_params < smb_base(inbuf))) - goto bad_param; - memcpy( params, smb_base(inbuf) + psoff, num_params); - } - if(data) { - unsigned int dsoff = SVAL(inbuf, smb_dsoff); - if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data)) - goto bad_param; - if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) || - (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf))) - goto bad_param; - memcpy( data, smb_base(inbuf) + dsoff, num_data); - } - - srv_signing_trans_start(SVAL(inbuf,smb_mid)); - - if(num_data_sofar < total_data || num_params_sofar < total_params) { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - srv_signing_trans_stop(); - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_trans2: send_smb failed."); - - while (num_data_sofar < total_data || - num_params_sofar < total_params) { - BOOL ret; - unsigned int param_disp; - unsigned int param_off; - unsigned int data_disp; - unsigned int data_off; - - ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); - - /* We need to re-calcuate the new length after we've read the secondary packet. */ - length = smb_len(inbuf) + 4; - - /* - * The sequence number for the trans reply is always - * based on the last secondary received. - */ + int outsize; - srv_signing_trans_start(SVAL(inbuf,smb_mid)); - - if ((ret && - (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) { - outsize = set_message(outbuf,0,0,True); - if(ret) - DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n")); - else - DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", - (smb_read_error == READ_ERROR) ? "error" : "timeout" )); - goto bad_param; - } - - /* Revise total_params and total_data in case - they have changed downwards */ - if (SVAL(inbuf, smb_tpscnt) < total_params) - total_params = SVAL(inbuf, smb_tpscnt); - if (SVAL(inbuf, smb_tdscnt) < total_data) - total_data = SVAL(inbuf, smb_tdscnt); - - num_params = SVAL(inbuf,smb_spscnt); - param_off = SVAL(inbuf, smb_spsoff); - param_disp = SVAL(inbuf, smb_spsdisp); - num_params_sofar += num_params; - - num_data = SVAL(inbuf, smb_sdscnt); - data_off = SVAL(inbuf, smb_sdsoff); - data_disp = SVAL(inbuf, smb_sdsdisp); - num_data_sofar += num_data; - - if (num_params_sofar > total_params || num_data_sofar > total_data) - goto bad_param; - - if (num_params) { - if (param_disp + num_params > total_params) - goto bad_param; - if ((param_disp + num_params < param_disp) || - (param_disp + num_params < num_params)) - goto bad_param; - if (param_disp > total_params) - goto bad_param; - if ((smb_base(inbuf) + param_off + num_params > inbuf + length) || - (smb_base(inbuf) + param_off + num_params < smb_base(inbuf))) - goto bad_param; - if (params + param_disp < params) - goto bad_param; - - memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params); - } - if (num_data) { - if (data_disp + num_data > total_data) - goto bad_param; - if ((data_disp + num_data < data_disp) || - (data_disp + num_data < num_data)) - goto bad_param; - if (data_disp > total_data) - goto bad_param; - if ((smb_base(inbuf) + data_off + num_data > inbuf + length) || - (smb_base(inbuf) + data_off + num_data < smb_base(inbuf))) - goto bad_param; - if (data + data_disp < data) - goto bad_param; - - memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data); - } - } - } - if (Protocol >= PROTOCOL_NT1) { SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ } /* Now we must call the relevant TRANS2 function */ - switch(tran_call) { + switch(state->call) { case TRANSACT2_OPEN: START_PROFILE_NESTED(Trans2_open); - outsize = call_trans2open(conn, inbuf, outbuf, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2open( + conn, inbuf, outbuf, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_open); break; case TRANSACT2_FINDFIRST: START_PROFILE_NESTED(Trans2_findfirst); - outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2findfirst( + conn, inbuf, outbuf, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_findfirst); break; case TRANSACT2_FINDNEXT: START_PROFILE_NESTED(Trans2_findnext); - outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2findnext( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_findnext); break; case TRANSACT2_QFSINFO: START_PROFILE_NESTED(Trans2_qfsinfo); - outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2qfsinfo( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_qfsinfo); break; case TRANSACT2_SETFSINFO: START_PROFILE_NESTED(Trans2_setfsinfo); - outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2setfsinfo( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_setfsinfo); break; case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: START_PROFILE_NESTED(Trans2_qpathinfo); - outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2qfilepathinfo( + conn, inbuf, outbuf, size, bufsize, state->call, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_qpathinfo); break; case TRANSACT2_SETPATHINFO: case TRANSACT2_SETFILEINFO: START_PROFILE_NESTED(Trans2_setpathinfo); - outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2setfilepathinfo( + conn, inbuf, outbuf, size, bufsize, state->call, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_setpathinfo); break; case TRANSACT2_FINDNOTIFYFIRST: START_PROFILE_NESTED(Trans2_findnotifyfirst); - outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2findnotifyfirst( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_findnotifyfirst); break; case TRANSACT2_FINDNOTIFYNEXT: START_PROFILE_NESTED(Trans2_findnotifynext); - outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2findnotifynext( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_findnotifynext); break; case TRANSACT2_MKDIR: START_PROFILE_NESTED(Trans2_mkdir); - outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2mkdir( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_mkdir); break; case TRANSACT2_GET_DFS_REFERRAL: START_PROFILE_NESTED(Trans2_get_dfs_referral); - outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2getdfsreferral( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_get_dfs_referral); break; case TRANSACT2_IOCTL: START_PROFILE_NESTED(Trans2_ioctl); - outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize, - ¶ms, total_params, &data, total_data, max_data_bytes); + outsize = call_trans2ioctl( + conn, inbuf, outbuf, size, bufsize, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE_NESTED(Trans2_ioctl); break; default: /* Error in request */ - DEBUG(2,("Unknown request %d in trans2 call\n", tran_call)); - SAFE_FREE(params); - SAFE_FREE(data); + DEBUG(2,("Unknown request %d in trans2 call\n", state->call)); + outsize = ERROR_DOS(ERRSRV,ERRerror); + } + return outsize; +} + +/**************************************************************************** + Reply to a SMBtrans2. + ****************************************************************************/ + +int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, + int size, int bufsize) +{ + int outsize = 0; + unsigned int dsoff = SVAL(inbuf, smb_dsoff); + unsigned int dscnt = SVAL(inbuf, smb_dscnt); + unsigned int psoff = SVAL(inbuf, smb_psoff); + unsigned int pscnt = SVAL(inbuf, smb_pscnt); + unsigned int tran_call = SVAL(inbuf, smb_setup0); + struct trans_state *state; + NTSTATUS result; + + START_PROFILE(SMBtrans2); + + if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans, + SVAL(inbuf, smb_mid)))) { + DEBUG(2, ("Got invalid trans2 request: %s\n", + nt_errstr(result))); END_PROFILE(SMBtrans2); - srv_signing_trans_stop(); - return ERROR_DOS(ERRSRV,ERRerror); + return ERROR_NT(result); } - - /* As we do not know how many data packets will need to be - returned here the various call_trans2xxxx calls - must send their own. Thus a call_trans2xxx routine only - returns a value other than -1 when it wants to send - an error packet. - */ - - srv_signing_trans_stop(); - SAFE_FREE(params); - SAFE_FREE(data); + if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) + && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) { + END_PROFILE(SMBtrans2); + return ERROR_DOS(ERRSRV,ERRaccess); + } + + if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) { + DEBUG(0, ("talloc failed\n")); + END_PROFILE(SMBtrans2); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + state->cmd = SMBtrans2; + + state->mid = SVAL(inbuf, smb_mid); + state->vuid = SVAL(inbuf, smb_uid); + state->setup_count = SVAL(inbuf, smb_suwcnt); + state->total_param = SVAL(inbuf, smb_tpscnt); + state->param = NULL; + state->total_data = SVAL(inbuf, smb_tdscnt); + state->data = NULL; + state->max_param_return = SVAL(inbuf, smb_mprcnt); + state->max_data_return = SVAL(inbuf, smb_mdrcnt); + state->max_setup_return = SVAL(inbuf, smb_msrcnt); + state->close_on_completion = BITSETW(inbuf+smb_vwv5,0); + state->one_way = BITSETW(inbuf+smb_vwv5,1); + + state->call = tran_call; + + /* All trans2 messages we handle have smb_sucnt == 1 - ensure this + is so as a sanity check */ + if (state->setup_count != 1) { + /* + * Need to have rc=0 for ioctl to get job id for OS/2. + * Network printing will fail if function is not successful. + * Similar function in reply.c will be used if protocol + * is LANMAN1.0 instead of LM1.2X002. + * Until DosPrintSetJobInfo with PRJINFO3 is supported, + * outbuf doesn't have to be set(only job id is used). + */ + if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) && + (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && + (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + DEBUG(2,("Got Trans2 DevIOctl jobid\n")); + } else { + DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count)); + DEBUG(2,("Transaction is %d\n",tran_call)); + END_PROFILE(SMBtrans2); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + + if ((dscnt > state->total_data) || (pscnt > state->total_param)) + goto bad_param; + + if (state->total_data) { + /* Can't use talloc here, the core routines do realloc on the + * params and data. */ + state->data = SMB_MALLOC(state->total_data); + if (state->data == NULL) { + DEBUG(0,("reply_trans2: data malloc fail for %u " + "bytes !\n", state->total_data)); + TALLOC_FREE(state); + END_PROFILE(SMBtrans2); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) + goto bad_param; + if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || + (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) + goto bad_param; + + memcpy(state->data,smb_base(inbuf)+dsoff,dscnt); + } + + if (state->total_param) { + /* Can't use talloc here, the core routines do realloc on the + * params and data. */ + state->param = SMB_MALLOC(state->total_param); + if (state->param == NULL) { + DEBUG(0,("reply_trans: param malloc fail for %u " + "bytes !\n", state->total_param)); + SAFE_FREE(state->data); + TALLOC_FREE(state); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) + goto bad_param; + if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || + (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) + goto bad_param; + + memcpy(state->param,smb_base(inbuf)+psoff,pscnt); + } + + state->received_data = dscnt; + state->received_param = pscnt; + + if ((state->received_param == state->total_param) && + (state->received_data == state->total_data)) { + + outsize = handle_trans2(conn, state, inbuf, outbuf, + size, bufsize); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + END_PROFILE(SMBtrans); + return outsize; + } + + DLIST_ADD(conn->pending_trans, state); + + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + show_msg(outbuf); END_PROFILE(SMBtrans2); - return outsize; /* If a correct response was needed the - call_trans2xxx calls have already sent - it. If outsize != -1 then it is returning */ + return outsize; bad_param: - srv_signing_trans_stop(); - SAFE_FREE(params); - SAFE_FREE(data); + DEBUG(0,("reply_trans2: invalid trans parameters\n")); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); END_PROFILE(SMBtrans2); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + + +/**************************************************************************** + Reply to a SMBtranss2 + ****************************************************************************/ + +int reply_transs2(connection_struct *conn, + char *inbuf,char *outbuf,int size,int bufsize) +{ + int outsize = 0; + unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; + struct trans_state *state; + + START_PROFILE(SMBtranss2); + + show_msg(inbuf); + + for (state = conn->pending_trans; state != NULL; + state = state->next) { + if (state->mid == SVAL(inbuf,smb_mid)) { + break; + } + } + + if ((state == NULL) || (state->cmd != SMBtrans2)) { + END_PROFILE(SMBtranss2); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + /* Revise state->total_param and state->total_data in case they have + changed downwards */ + + if (SVAL(inbuf, smb_tpscnt) < state->total_param) + state->total_param = SVAL(inbuf, smb_tpscnt); + if (SVAL(inbuf, smb_tdscnt) < state->total_data) + state->total_data = SVAL(inbuf, smb_tdscnt); + + pcnt = SVAL(inbuf, smb_spscnt); + poff = SVAL(inbuf, smb_spsoff); + pdisp = SVAL(inbuf, smb_spsdisp); + + dcnt = SVAL(inbuf, smb_sdscnt); + doff = SVAL(inbuf, smb_sdsoff); + ddisp = SVAL(inbuf, smb_sdsdisp); + + state->received_param += pcnt; + state->received_data += dcnt; + + if ((state->received_data > state->total_data) || + (state->received_param > state->total_param)) + goto bad_param; + + if (pcnt) { + if (pdisp+pcnt > state->total_param) + goto bad_param; + if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) + goto bad_param; + if (pdisp > state->total_param) + goto bad_param; + if ((smb_base(inbuf) + poff + pcnt > inbuf + size) || + (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) + goto bad_param; + if (state->param + pdisp < state->param) + goto bad_param; + + memcpy(state->param+pdisp,smb_base(inbuf)+poff, + pcnt); + } + + if (dcnt) { + if (ddisp+dcnt > state->total_data) + goto bad_param; + if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) + goto bad_param; + if (ddisp > state->total_data) + goto bad_param; + if ((smb_base(inbuf) + doff + dcnt > inbuf + size) || + (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) + goto bad_param; + if (state->data + ddisp < state->data) + goto bad_param; + + memcpy(state->data+ddisp, smb_base(inbuf)+doff, + dcnt); + } + + if ((state->received_param < state->total_param) || + (state->received_data < state->total_data)) { + END_PROFILE(SMBtranss); + return -1; + } + + /* construct_reply_common has done us the favor to pre-fill the + * command field with SMBtranss2 which is wrong :-) + */ + SCVAL(outbuf,smb_com,SMBtrans2); + + outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize); + + DLIST_REMOVE(conn->pending_trans, state); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + + if (outsize == 0) { + END_PROFILE(SMBtranss); + return(ERROR_DOS(ERRSRV,ERRnosupport)); + } + + END_PROFILE(SMBtranss2); + return(outsize); + + bad_param: + + DEBUG(0,("reply_transs2: invalid trans parameters\n")); + DLIST_REMOVE(conn->pending_trans, state); + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + END_PROFILE(SMBtranss2); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); +} diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index bbb7b5bb30..55bf146c20 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -759,11 +759,21 @@ BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, BOOL result; START_PROFILE(syscall_fcntl_lock); - result = fcntl_lock(fd, op, offset, count,type); + result = fcntl_lock(fd, op, offset, count, type); END_PROFILE(syscall_fcntl_lock); return result; } +BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid) +{ + BOOL result; + + START_PROFILE(syscall_fcntl_getlock); + result = fcntl_getlock(fd, poffset, pcount, ptype, ppid); + END_PROFILE(syscall_fcntl_getlock); + return result; +} + int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) { int result; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 07e18caa5c..9a6327b33b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -95,6 +95,7 @@ static struct vfs_ops default_vfs = { vfswrap_utime, vfswrap_ftruncate, vfswrap_lock, + vfswrap_getlock, vfswrap_symlink, vfswrap_readlink, vfswrap_link, -- cgit From 6c237e04b2b6be22465563cb77fd6de35f52fcc4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Apr 2006 18:44:27 +0000 Subject: r15020: Fix issue with samba4 netbench torture tester, it sends break replies to "break to none from level2" requests and it shouldn't. Just don't log a debug level zero message. Jeremy. (This used to be commit dc6a13da33a031d0c2374b692737dbe9215f0f74) --- source3/smbd/reply.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 040f7710fd..3bad4829b9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5247,7 +5247,14 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, */ if (fsp->oplock_type == 0) { - DEBUG(0,("reply_lockingX: Error : oplock break from " + + /* The Samba4 nbench simulator doesn't understand + the difference between break to level2 and break + to none from level2 - it sends oplock break + replies in both cases. Don't keep logging an error + message here - just ignore it. JRA. */ + + DEBUG(5,("reply_lockingX: Error : oplock break from " "client for fnum = %d (oplock=%d) and no " "oplock granted on this file (%s).\n", fsp->fnum, fsp->oplock_type, fsp->fsp_name)); -- cgit From eecdc6c956d983be2c139843e2730136d3273fe9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Apr 2006 22:47:09 +0000 Subject: r15022: Fix core dumps on normal server exit. Jeremy. (This used to be commit 13c3abf03187f84874b5754b54de5d3fe2dea188) --- source3/smbd/process.c | 8 ++++---- source3/smbd/server.c | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cdeccab5e8..b2634e2653 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -303,7 +303,7 @@ static void async_processing(fd_set *pfds) process_aio_queue(); if (got_sig_term) { - exit_server_cleanly(); + exit_server_cleanly("termination signal"); } /* check for async change notify events */ @@ -886,7 +886,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */ if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) { DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf))); - exit_server("Non-SMB packet"); + exit_server_cleanly("Non-SMB packet"); return(-1); } @@ -1100,7 +1100,7 @@ static void process_smb(char *inbuf, char *outbuf) static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) ); (void)send_smb(smbd_server_fd(),(char *)buf); - exit_server("connection denied"); + exit_server_cleanly("connection denied"); } } @@ -1122,7 +1122,7 @@ static void process_smb(char *inbuf, char *outbuf) DEBUG(0,("ERROR: Invalid message response size! %d %d\n", nread, smb_len(outbuf))); } else if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("process_smb: send_smb failed."); + exit_server_cleanly("process_smb: send_smb failed."); } } trans_num++; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0880778f55..d5a678b850 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -153,7 +153,7 @@ static void msg_exit_server(int msg_type, struct process_id src, void *buf, size_t len) { DEBUG(3, ("got a SHUTDOWN message\n")); - exit_server_cleanly(); + exit_server_cleanly(NULL); } #ifdef DEVELOPER @@ -397,7 +397,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ if (num == -1 && errno == EINTR) { if (got_sig_term) { - exit_server_cleanly(); + exit_server_cleanly(NULL); } /* check for sighup processing */ @@ -681,9 +681,9 @@ void exit_server(const char *const explanation) exit_server_common(SERVER_EXIT_ABNORMAL, explanation); } -void exit_server_cleanly(void) +void exit_server_cleanly(const char *const explanation) { - exit_server_common(SERVER_EXIT_NORMAL, NULL); + exit_server_common(SERVER_EXIT_NORMAL, explanation); } void exit_server_fault(void) @@ -1014,6 +1014,6 @@ void build_options(BOOL screen); namecache_shutdown(); - exit_server_cleanly(); + exit_server_cleanly(NULL); return(0); } -- cgit From fc13f284179df5f3f3a1d475bf84da21dc89c970 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Apr 2006 01:43:13 +0000 Subject: r15030: On a performace hunt... Remove as many extraneous memset's as possible. Jeremy. (This used to be commit 1217ed392b75aa8bfefa9c3f1ec5fa3bba841ee0) --- source3/smbd/nttrans.c | 4 ++-- source3/smbd/process.c | 12 ++++-------- source3/smbd/reply.c | 32 ++++++++++++++++---------------- source3/smbd/trans2.c | 6 +++--- 4 files changed, 25 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 24d64ecfc7..839eb7bb27 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1805,7 +1805,7 @@ int reply_ntrename(connection_struct *conn, * update after a rename.. */ process_pending_change_notify_queue((time_t)0); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); END_PROFILE(SMBntrename); return(outsize); @@ -2956,7 +2956,7 @@ int reply_nttrans(connection_struct *conn, /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); show_msg(outbuf); END_PROFILE(SMBnttrans); return outsize; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b2634e2653..c0a43e99dd 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1160,20 +1160,16 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(char *inbuf,char *outbuf) { - memset(outbuf,'\0',smb_size); - - set_message(outbuf,0,0,True); - SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); + set_message(outbuf,0,0,False); - memcpy(outbuf+4,inbuf+4,4); - SCVAL(outbuf,smb_rcls,SMB_SUCCESS); - SCVAL(outbuf,smb_reh,0); + SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); + SIVAL(outbuf,smb_rcls,0); SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); SSVAL(outbuf,smb_flg2, (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) | common_flags2); + memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh)); - SSVAL(outbuf,smb_err,SMB_SUCCESS); SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3bad4829b9..0a3fc27be6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -848,7 +848,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return(UNIXERROR(ERRDOS,ERRbadpath)); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); END_PROFILE(SMBchkpth); @@ -994,7 +994,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); @@ -2113,7 +2113,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size */ process_pending_change_notify_queue((time_t)0); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); END_PROFILE(SMBunlink); return outsize; @@ -3214,7 +3214,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,False); uint16 fnum = SVAL(inbuf,smb_vwv0); files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBflush); @@ -3245,7 +3245,7 @@ int reply_exit(connection_struct *conn, file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid)); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); DEBUG(3,("exit\n")); @@ -3266,7 +3266,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, files_struct *fsp = NULL; START_PROFILE(SMBclose); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); /* If it's an IPC, pass off to the pipe handler. */ if (IS_IPC(conn)) { @@ -3414,7 +3414,7 @@ int reply_writeclose(connection_struct *conn, int reply_lock(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3476,7 +3476,7 @@ int reply_lock(connection_struct *conn, int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3515,7 +3515,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int reply_tdis(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,False); uint16 vuid; START_PROFILE(SMBtdis); @@ -3622,7 +3622,7 @@ int reply_printopen(connection_struct *conn, int reply_printclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,False); files_struct *fsp = file_fsp(inbuf,smb_vwv0); int close_err = 0; START_PROFILE(SMBsplclose); @@ -3727,7 +3727,7 @@ int reply_printqueue(connection_struct *conn, int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int numtowrite; - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,False); char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3852,7 +3852,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, change_owner_to_parent(conn, NULL, directory, &sbuf); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); @@ -4040,7 +4040,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); DEBUG( 3, ( "rmdir %s\n", directory ) ); @@ -4712,7 +4712,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * update after a rename.. */ process_pending_change_notify_queue((time_t)0); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); END_PROFILE(SMBmv); return(outsize); @@ -5043,7 +5043,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRbadpath); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh)); DEBUG(3,("setdir %s\n", newdir)); @@ -5542,7 +5542,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBsetattrE); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); if(!fsp || (fsp->conn != conn)) { END_PROFILE(SMBsetattrE); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 19463403ac..31e3d9e329 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4960,7 +4960,7 @@ int reply_findclose(connection_struct *conn, dptr_close(&dptr_num); - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num)); @@ -4987,7 +4987,7 @@ int reply_findnclose(connection_struct *conn, findnotifyfirst - so any dptr_num is ok here. Just ignore it. */ - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num)); @@ -5274,7 +5274,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,False); show_msg(outbuf); END_PROFILE(SMBtrans2); return outsize; -- cgit From 262ffd9750f58f2c5f2268932b45c4d7b05a5fca Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Apr 2006 06:39:51 +0000 Subject: r15035: It seems that many preprocessors do not like comments in macro args.. (This used to be commit efc833dcba052e52c46eeba71a1ebe248be9cb05) --- source3/smbd/trans2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 31e3d9e329..b229807bfd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2407,12 +2407,15 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); /* We have POSIX ACLs, pathname and locking capability. */ +#if defined(DEVELOPER) /* Not quite finished yet... */ SBIG_UINT(pdata,4,((SMB_BIG_UINT)( CIFS_UNIX_POSIX_ACLS_CAP| CIFS_UNIX_POSIX_PATHNAMES_CAP| -#if defined(DEVELOPER) /* Not quite finished yet... */ CIFS_UNIX_FCNTL_LOCKS_CAP))); #else + SBIG_UINT(pdata,4,((SMB_BIG_UINT)( + CIFS_UNIX_POSIX_ACLS_CAP| + CIFS_UNIX_POSIX_PATHNAMES_CAP| 0))); #endif break; -- cgit From 713eaf1d67d9ef967fb4526113e2a3ba3dd5e229 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Apr 2006 22:22:54 +0000 Subject: r15083: Using talloc with destructors is nice and all, but in this case it's in a performace critical path and it *hurts* us. Go back to plain malloc/free with an explicit destructor call. Jeremy. (This used to be commit 1c99aed563c29e1b3d70939878af747a0660bfec) --- source3/smbd/blocking.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 6b47d0466b..a8db498ef5 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -121,7 +121,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, memcpy(blr->inbuf, inbuf, length); blr->length = length; - br_lck = brl_get_locks(NULL, blr->fsp); + br_lck = brl_get_locks(blr->fsp); if (!br_lck) { free_blocking_lock_record(blr); return False; @@ -136,7 +136,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, PENDING_LOCK, blr->lock_flav, &my_lock_ctx); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -625,7 +625,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) for(blr = blocking_lock_queue; blr; blr = next) { next = blr->next; if(blr->fsp->fnum == fsp->fnum) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ @@ -637,7 +637,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->offset, blr->count, blr->lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } @@ -658,7 +658,7 @@ void remove_pending_lock_requests_by_mid(int mid) next = blr->next; if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ @@ -670,7 +670,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->offset, blr->count, blr->lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -754,7 +754,7 @@ void process_blocking_lock_queue(time_t t) fsp->fnum, fsp->fsp_name )); if((blr->expire_time != -1) && (blr->expire_time <= t)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); /* * Lock expired - throw away all previously @@ -771,7 +771,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -780,7 +780,7 @@ void process_blocking_lock_queue(time_t t) } if(!change_to_user(conn,vuid)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); /* * Remove the entry and return an error to the client. @@ -793,7 +793,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", @@ -804,7 +804,7 @@ void process_blocking_lock_queue(time_t t) } if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); /* * Remove the entry and return an error to the client. @@ -817,7 +817,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); @@ -834,7 +834,7 @@ void process_blocking_lock_queue(time_t t) */ if(blocking_lock_record_process(blr)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(fsp); if (br_lck) { brl_remove_pending_lock(br_lck, @@ -843,7 +843,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - TALLOC_FREE(br_lck); + byte_range_lock_destructor(br_lck); } free_blocking_lock_record(blr); -- cgit From cc203f3e59840b75fbb42a53d36b717a57268c2f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Apr 2006 03:55:42 +0000 Subject: r15084: Try and squeeze more out of the non-read/write code path. Jeremy. (This used to be commit 23dcff4d50d1d35b7ddee0d0cb79c16a312f179c) --- source3/smbd/process.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c0a43e99dd..ba14e57c54 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -357,7 +357,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) { fd_set fds; int selrtn; - struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0); + struct timeval to; int maxfd = 0; smb_read_error = 0; @@ -367,6 +367,9 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) if (timeout >= 0) { to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; + } else { + to.tv_sec = SMBD_SELECT_TIMEOUT; + to.tv_usec = 0; } /* @@ -441,14 +444,20 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) goto again; } + /* + * Are there any timed events waiting ? If so, ensure we don't + * select for longer than it would take to wait for them. + */ + { struct timeval tmp; - struct timeval *tp = get_timed_events_timeout(&tmp,SMBD_SELECT_TIMEOUT); + struct timeval *tp = get_timed_events_timeout(&tmp); if (tp) { to = timeval_min(&to, tp); if (timeval_is_zero(&to)) { - return True; + /* Process a timed event now... */ + run_events(); } } } -- cgit From 010c725b36feb1a234dce9f40b95ae5869058698 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Apr 2006 04:07:10 +0000 Subject: r15088: Remove all time() and gettimeofday() calls out of the mainline packet processing code. Only do these when needed (ie. in the idle timeout code). We drop an unneccessary global here too. Jeremy. (This used to be commit 8272a5ab0605fcf95527143c4f909aa1008e5b94) --- source3/smbd/conn.c | 16 ++++++++++++---- source3/smbd/oplock.c | 18 +++--------------- source3/smbd/process.c | 4 ---- source3/smbd/service.c | 5 ++--- 4 files changed, 17 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index b41467f02c..5aa8901d59 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -154,8 +154,9 @@ find_again: } /**************************************************************************** -close all conn structures + Close all conn structures. ****************************************************************************/ + void conn_close_all(void) { connection_struct *conn, *next; @@ -178,13 +179,20 @@ BOOL conn_idle_all(time_t t, int deadtime) for (conn=Connections;conn;conn=next) { next=conn->next; + + /* Update if connection wasn't idle. */ + if (conn->lastused != conn->lastused_count) { + conn->lastused = t; + } + /* close dirptrs on connections that are idle */ - if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) + if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) { dptr_idlecnum(conn); + } - if (conn->num_files_open > 0 || - (t-conn->lastused)num_files_open > 0 || (t-conn->lastused) 0) { - wait_left = MIN(wait_left, 1000); - sys_usleep(wait_left * 1000); + if (wait_time) { + smb_msleep(wait_time); } } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ba14e57c54..aaf98203a2 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -26,8 +26,6 @@ extern int keepalive; extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; -struct timeval smb_last_time; - static char *InBuffer = NULL; static char *OutBuffer = NULL; static char *current_inbuf = NULL; @@ -1011,8 +1009,6 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) int outsize = 0; int msg_type = CVAL(inbuf,0); - GetTimeOfDay(&smb_last_time); - chain_size = 0; file_chain_reset(); reset_chain_p(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 5c4974329c..ba87d0743d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -20,7 +20,6 @@ #include "includes.h" -extern struct timeval smb_last_time; extern userdom_struct current_user_info; /**************************************************************************** @@ -140,7 +139,7 @@ BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir) return(False); } - conn->lastused = smb_last_time.tv_sec; + conn->lastused_count++; snum = SNUM(conn); @@ -601,7 +600,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, safe_strcpy(conn->client_address, client_addr(), sizeof(conn->client_address)-1); conn->num_files_open = 0; - conn->lastused = time(NULL); + conn->lastused = conn->lastused_count = time(NULL); conn->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); -- cgit From 4f240462949ca7487b111adf7aef249f4c6f6e8d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Apr 2006 12:23:38 +0000 Subject: r15102: u32 is a tdb-only thing that's not exported by samba4 tdb. Replace by uint32. Volker (This used to be commit 0a1665a1b78d063840e42e85229ace5a751e3985) --- source3/smbd/mangle_hash2.c | 24 ++++++++++++------------ source3/smbd/statcache.c | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0a161c9e76..ec17109422 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -101,7 +101,7 @@ static unsigned mangle_prefix; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; -static u32 *prefix_cache_hashes; +static uint32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -119,10 +119,10 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static u32 mangle_hash(const char *key, unsigned int length) +static uint32 mangle_hash(const char *key, unsigned int length) { - u32 value; - u32 i; + uint32 value; + uint32 i; fstring str; /* we have to uppercase here to ensure that the mangled name @@ -139,8 +139,8 @@ static u32 mangle_hash(const char *key, unsigned int length) /* Set the initial value from the key size. */ for (value = FNV1_INIT, i=0; i < length; i++) { - value *= (u32)FNV1_PRIME; - value ^= (u32)(str[i]); + value *= (uint32)FNV1_PRIME; + value ^= (uint32)(str[i]); } /* note that we force it to a 31 bit hash, to keep within the limits @@ -162,7 +162,7 @@ static BOOL cache_init(void) return False; } - prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); + prefix_cache_hashes = SMB_CALLOC_ARRAY(uint32, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { return False; } @@ -173,7 +173,7 @@ static BOOL cache_init(void) /* insert an entry into the prefix cache. The string might not be null terminated */ -static void cache_insert(const char *prefix, int length, u32 hash) +static void cache_insert(const char *prefix, int length, uint32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, u32 hash) /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(u32 hash) +static const char *cache_lookup(uint32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -372,7 +372,7 @@ static void mangle_reset(void) */ static BOOL check_cache(char *name, size_t maxlen, int snum) { - u32 hash, multiplier; + uint32 hash, multiplier; unsigned int i; const char *prefix; char extension[4]; @@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum) /* we need to extract the hash from the 8.3 name */ hash = base_reverse[(unsigned char)name[7]]; for (multiplier=36, i=5;i>=mangle_prefix;i--) { - u32 v = base_reverse[(unsigned char)name[i]]; + uint32 v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } @@ -517,7 +517,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; - u32 hash, v; + uint32 hash, v; char new_name[13]; /* reserved names are handled specially */ diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 548d7c4a48..fe022017b5 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -u32 fast_string_hash(TDB_DATA *key) +uint32 fast_string_hash(TDB_DATA *key) { - u32 n = 0; + uint32 n = 0; const char *p; for (p = key->dptr; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (u32)(*p); + n = ((n << 5) + n) ^ (uint32)(*p); } return n; } -- cgit From 76e581b983989377d3ac3ae89b2b7d925aadc3f5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Apr 2006 12:27:35 +0000 Subject: r15103: Okay, looking closer: Samba4 tdb not exporting u32 is a bug in samba4's tdb. tdb_open_ex needs it. Can someone from samba4 tell me how this should be handled? Thanks, Volker (This used to be commit 0a2f1ed5e9012e07ef158666b68994d0961768b6) --- source3/smbd/mangle_hash2.c | 24 ++++++++++++------------ source3/smbd/statcache.c | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index ec17109422..0a161c9e76 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -101,7 +101,7 @@ static unsigned mangle_prefix; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; -static uint32 *prefix_cache_hashes; +static u32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -119,10 +119,10 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static uint32 mangle_hash(const char *key, unsigned int length) +static u32 mangle_hash(const char *key, unsigned int length) { - uint32 value; - uint32 i; + u32 value; + u32 i; fstring str; /* we have to uppercase here to ensure that the mangled name @@ -139,8 +139,8 @@ static uint32 mangle_hash(const char *key, unsigned int length) /* Set the initial value from the key size. */ for (value = FNV1_INIT, i=0; i < length; i++) { - value *= (uint32)FNV1_PRIME; - value ^= (uint32)(str[i]); + value *= (u32)FNV1_PRIME; + value ^= (u32)(str[i]); } /* note that we force it to a 31 bit hash, to keep within the limits @@ -162,7 +162,7 @@ static BOOL cache_init(void) return False; } - prefix_cache_hashes = SMB_CALLOC_ARRAY(uint32, MANGLE_CACHE_SIZE); + prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { return False; } @@ -173,7 +173,7 @@ static BOOL cache_init(void) /* insert an entry into the prefix cache. The string might not be null terminated */ -static void cache_insert(const char *prefix, int length, uint32 hash) +static void cache_insert(const char *prefix, int length, u32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, uint32 hash) /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(uint32 hash) +static const char *cache_lookup(u32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -372,7 +372,7 @@ static void mangle_reset(void) */ static BOOL check_cache(char *name, size_t maxlen, int snum) { - uint32 hash, multiplier; + u32 hash, multiplier; unsigned int i; const char *prefix; char extension[4]; @@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum) /* we need to extract the hash from the 8.3 name */ hash = base_reverse[(unsigned char)name[7]]; for (multiplier=36, i=5;i>=mangle_prefix;i--) { - uint32 v = base_reverse[(unsigned char)name[i]]; + u32 v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } @@ -517,7 +517,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; - uint32 hash, v; + u32 hash, v; char new_name[13]; /* reserved names are handled specially */ diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index fe022017b5..548d7c4a48 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -uint32 fast_string_hash(TDB_DATA *key) +u32 fast_string_hash(TDB_DATA *key) { - uint32 n = 0; + u32 n = 0; const char *p; for (p = key->dptr; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (uint32)(*p); + n = ((n << 5) + n) ^ (u32)(*p); } return n; } -- cgit From 5445694eb9c7a5e64e7e58feb78c87bc627402b5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Apr 2006 22:32:38 +0000 Subject: r15112: Move strict locking default to auto. Fix up the error return for one of the Samba4 torture tests. Jeremy. (This used to be commit 9db6617756ff155eb7549c3c622a9920189e577d) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0a3fc27be6..0524078310 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5221,7 +5221,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, /* we don't support these - and CANCEL_LOCK makes w2k and XP reboot so I don't really want to be compatible! (tridge) */ - return ERROR_DOS(ERRDOS, ERRnoatomiclocks); + return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks); } if (locktype & LOCKING_ANDX_CANCEL_LOCK) { -- cgit From 6ca1ba38147403bc5a8a3f1ec560c0671b1f9463 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Apr 2006 03:45:09 +0000 Subject: r15115: Fix error return on sessionsetup. Ensure no data blob is added if the logon call failed. Jeremy. (This used to be commit 71d0191c313e2106ae2bdef3119b3ff6e591ee1b) --- source3/smbd/sesssetup.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3280e2d5fc..7c90263a5b 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -95,21 +95,25 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, { char *p; - set_message(outbuf,4,0,True); + if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + ERROR_NT(nt_status); + } else { + set_message(outbuf,4,0,True); - nt_status = nt_status_squash(nt_status); - SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status)); - SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ - SSVAL(outbuf, smb_vwv3, blob.length); - p = smb_buf(outbuf); + nt_status = nt_status_squash(nt_status); + SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status)); + SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ + SSVAL(outbuf, smb_vwv3, blob.length); + p = smb_buf(outbuf); - /* should we cap this? */ - memcpy(p, blob.data, blob.length); - p += blob.length; + /* should we cap this? */ + memcpy(p, blob.data, blob.length); + p += blob.length; - p += add_signature( outbuf, p ); + p += add_signature( outbuf, p ); - set_message_end(outbuf,p); + set_message_end(outbuf,p); + } show_msg(outbuf); return send_smb(smbd_server_fd(),outbuf); -- cgit From bdbd173e8cbce94fbed217932e2c959d1ef4472d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 18 Apr 2006 09:02:58 +0000 Subject: r15119: Initialize our global sam sid first, quite a lot of the other initialization routines further down depend on it. Fix bug 3696. Volker (This used to be commit 6c65cccc83aa7b726e23684f979f1488bed3f751) --- source3/smbd/server.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d5a678b850..a1466c408d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -912,6 +912,28 @@ void build_options(BOOL screen); if (!message_init()) exit(1); + /* Initialize our global sam sid first -- quite a lot of the other + * initialization routines further down depend on it. + */ + + /* Initialise the password backed before the global_sam_sid + to ensure that we fetch from ldap before we make a domain sid up */ + + if(!initialize_password_db(False)) + exit(1); + + /* Fail gracefully if we can't open secrets.tdb */ + + if (!secrets_init()) { + DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n")); + exit(1); + } + + if(!get_global_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); + exit(1); + } + if (!session_init()) exit(1); @@ -965,17 +987,6 @@ void build_options(BOOL screen); * everything after this point is run after the fork() */ - /* Initialise the password backed before the global_sam_sid - to ensure that we fetch from ldap before we make a domain sid up */ - - if(!initialize_password_db(False)) - exit(1); - - if(!get_global_sam_sid()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); - exit(1); - } - static_init_rpc; init_modules(); -- cgit From 335637b2ebeefffb7668639662c03da2f75976ed Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Apr 2006 14:11:51 +0000 Subject: r15133: in_server is not used anywhere (This used to be commit c981bc7f31483e7821b9654eb30d665283aa07d5) --- source3/smbd/server.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a1466c408d..b76ade957c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -731,7 +731,6 @@ void build_options(BOOL screen); int main(int argc,const char *argv[]) { - extern BOOL in_server; /* shall I run as a daemon */ static BOOL is_daemon = False; static BOOL interactive = False; @@ -755,8 +754,6 @@ void build_options(BOOL screen); { NULL } }; - in_server = True; - load_case_tables(); #ifdef HAVE_SET_AUTH_PARAMETERS -- cgit From f60111e074eba237ef2ad416bfd3847ce314e773 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Apr 2006 18:48:14 +0000 Subject: r15138: Teach Samba the difference between exclusive and batch oplocks. Pass Samba4 oplock test (with kernel oplocks off). Jeremy. (This used to be commit 3c260bcce2de76d724279e07dca61eadddfb8782) --- source3/smbd/open.c | 100 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 99a7894762..edc5bc98b6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -608,7 +608,7 @@ static BOOL is_delete_request(files_struct *fsp) { * 3) Only level2 around: Grant level2 and do nothing else. */ -static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) +static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number) { int i; struct share_mode_entry *exclusive = NULL; @@ -630,9 +630,16 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) /* At least one entry is not an invalid or deferred entry. */ valid_entry = True; - if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { - SMB_ASSERT(exclusive == NULL); - exclusive = &lck->share_modes[i]; + if (pass_number == 1) { + if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) { + SMB_ASSERT(exclusive == NULL); + exclusive = &lck->share_modes[i]; + } + } else { + if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { + SMB_ASSERT(exclusive == NULL); + exclusive = &lck->share_modes[i]; + } } if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { @@ -1024,6 +1031,42 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func } +static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time) +{ + struct deferred_open_record state; + + /* This is a relative time, added to the absolute + request_time value to get the absolute timeout time. + Note that if this is the second or greater time we enter + this codepath for this particular request mid then + request_time is left as the absolute time of the *first* + time this request mid was processed. This is what allows + the request to eventually time out. */ + + struct timeval timeout; + + /* Normally the smbd we asked should respond within + * OPLOCK_BREAK_TIMEOUT seconds regardless of whether + * the client did, give twice the timeout as a safety + * measure here in case the other smbd is stuck + * somewhere else. */ + + timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + + /* Nothing actually uses state.delayed_for_oplocks + but it's handy to differentiate in debug messages + between a 30 second delay due to oplock break, and + a 1 second delay for share mode conflicts. */ + + state.delayed_for_oplocks = True; + state.dev = lck->dev; + state.inode = lck->ino; + + if (!request_timed_out(request_time, timeout)) { + defer_open(lck, request_time, timeout, &state); + } +} + /**************************************************************************** Open a file with a share mode. ****************************************************************************/ @@ -1310,7 +1353,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (file_existed) { - dev = psbuf->st_dev; inode = psbuf->st_ino; @@ -1324,41 +1366,9 @@ files_struct *open_file_ntcreate(connection_struct *conn, return NULL; } - if (delay_for_oplocks(lck, fsp)) { - struct deferred_open_record state; - - /* This is a relative time, added to the absolute - request_time value to get the absolute timeout time. - Note that if this is the second or greater time we enter - this codepath for this particular request mid then - request_time is left as the absolute time of the *first* - time this request mid was processed. This is what allows - the request to eventually time out. */ - - struct timeval timeout; - - /* Normally the smbd we asked should respond within - * OPLOCK_BREAK_TIMEOUT seconds regardless of whether - * the client did, give twice the timeout as a safety - * measure here in case the other smbd is stuck - * somewhere else. */ - - timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); - - /* Nothing actually uses state.delayed_for_oplocks - but it's handy to differentiate in debug messages - between a 30 second delay due to oplock break, and - a 1 second delay for share mode conflicts. */ - - state.delayed_for_oplocks = True; - state.dev = dev; - state.inode = inode; - - if (!request_timed_out(request_time, timeout)) { - defer_open(lck, request_time, timeout, - &state); - } - + /* First pass - send break only on batch oplocks. */ + if (delay_for_oplocks(lck, fsp, 1)) { + schedule_defer_open(lck, request_time); TALLOC_FREE(lck); return NULL; } @@ -1367,6 +1377,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, access_mask, share_access, create_options, &file_existed); + if (NT_STATUS_IS_OK(status)) { + /* We might be going to allow this open. Check oplock status again. */ + /* Second pass - send break for both batch or exclusive oplocks. */ + if (delay_for_oplocks(lck, fsp, 2)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + return NULL; + } + } + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ set_saved_ntstatus(status); -- cgit From e18c9a926f43853594a00db89167f698466b10ee Mon Sep 17 00:00:00 2001 From: Paul Green Date: Mon, 24 Apr 2006 10:45:06 +0000 Subject: r15196: Update a comment that I found confusing (I confuse easily). (This used to be commit eb53f01863f8f9d2980d9c2c8d27899dd39e5fa2) --- source3/smbd/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index cd6c1b0bda..27a4182c22 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -719,7 +719,7 @@ struct dptr_struct *dptr_fetch_lanman2(int dptr_num) } /**************************************************************************** - Check a filetype for being valid. + Check that a file matches a particular file type. ****************************************************************************/ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) -- cgit From 1ca61f4748283bdc9d30ddec3ec812fb830b6ac4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 26 Apr 2006 09:43:39 +0000 Subject: r15266: Fix bug 3720. I wonder why -O1 compiles did not catch this... Thanks to Jason Mader for reporting this. Volker (This used to be commit 3e616c3272ba76a2d135f7c51ceb44461ad165ad) --- source3/smbd/ipc.c | 4 ++-- source3/smbd/nttrans.c | 4 ++-- source3/smbd/trans2.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1b5a5f39c7..7f9505606c 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -433,8 +433,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, START_PROFILE(SMBtrans); - if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans, - SVAL(inbuf, smb_mid)))) { + result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); + if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid trans request: %s\n", nt_errstr(result))); END_PROFILE(SMBtrans); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 839eb7bb27..96e2c18bc0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2827,8 +2827,8 @@ int reply_nttrans(connection_struct *conn, return ERROR_DOS(ERRSRV,ERRaccess); } - if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans, - SVAL(inbuf, smb_mid)))) { + result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); + if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result))); END_PROFILE(SMBnttrans); return ERROR_NT(result); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b229807bfd..5d6de951ef 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5154,8 +5154,8 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, START_PROFILE(SMBtrans2); - if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans, - SVAL(inbuf, smb_mid)))) { + result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); + if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid trans2 request: %s\n", nt_errstr(result))); END_PROFILE(SMBtrans2); -- cgit From 31693197bee0d71e83418c0fb72685fd848e358f Mon Sep 17 00:00:00 2001 From: Paul Green Date: Wed, 26 Apr 2006 15:41:25 +0000 Subject: r15283: Oh yeah. The build farm doesn't do much with head. OK, here is the patch to SAMBA_3_0 to declare prototypes for the initialization functions. These are the same changes I just made to head. --paulg (This used to be commit 17774387ad879b6a72dd1cf406326318add31b04) --- source3/smbd/server.c | 2 ++ source3/smbd/vfs.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b76ade957c..d16579f24a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,6 +22,8 @@ #include "includes.h" +static_decl_rpc; + static int am_parent = 1; /* the last message the was processed */ diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9a6327b33b..2c9403a079 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -27,6 +27,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS +static_decl_vfs; + struct vfs_init_function_entry { char *name; vfs_op_tuple *vfs_op_tuples; -- cgit From ec8b810a16e1f08ceb64486be7447e6cf703261d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2006 13:42:18 +0000 Subject: r15293: Don't ever set O_SYNC on open unless "strict sync = yes". This could be the cause of the perf. problem reported between 3.0.14a and 3.0.2x. Lufthansa has *wireless* on their flights to the USA now... (I'm in heaven ! :-). Jeremy. (This used to be commit dbc03125f2643f8ecff8e901cb23fa6408cce011) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index edc5bc98b6..1c8716abda 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1308,7 +1308,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ #if defined(O_SYNC) - if (create_options & FILE_WRITE_THROUGH) { + if (lp_strict_sync(SNUM(conn)) && (create_options & FILE_WRITE_THROUGH)) { flags2 |= O_SYNC; } #endif /* O_SYNC */ -- cgit From 23b2f27a5448d74e456b9bb53f4d487f35d0d210 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 30 Apr 2006 14:14:46 +0000 Subject: r15359: Fix typo (This used to be commit 46d3c7668bdbaaab1b8854617aa7c235f51a74e0) --- source3/smbd/share_access.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index df5f445587..468f61560b 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -204,7 +204,8 @@ BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum) if (!token_contains_name_in_list(username, lp_servicename(snum), token, lp_valid_users(snum))) { - DEBUG(10, ("User %s no in 'valid users'\n", username)); + DEBUG(10, ("User %s not in 'valid users'\n", + username)); return False; } } -- cgit From aca0a3ad3a9646e821f2d4c3d30f3a14592df4ae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2006 03:42:56 +0000 Subject: r15404: Check for WRITE_THOUGH before calling lp_ fn. I hate extra fn calls. Jeremy. (This used to be commit e468e1e5c2dbee29066f0efe4141d8705def5d6f) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1c8716abda..3d537b2f39 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1308,7 +1308,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ #if defined(O_SYNC) - if (lp_strict_sync(SNUM(conn)) && (create_options & FILE_WRITE_THROUGH)) { + if ((create_options & FILE_WRITE_THROUGH) && lp_strict_sync(SNUM(conn))) { flags2 |= O_SYNC; } #endif /* O_SYNC */ -- cgit From 5910e397d3f2d49c3ec13e064f402137205031a8 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 5 May 2006 02:06:37 +0000 Subject: r15446: Tidy up the formatting of locking debug messages and make it more consistent. Bring oplocks withing the purview of the locking debug channel. (This used to be commit e817cfd7d3a42d141198122eada58b5a7ba90e9c) --- source3/smbd/oplock.c | 40 ++++++++++++++++++++++------------------ source3/smbd/oplock_irix.c | 1 + source3/smbd/oplock_linux.c | 1 + 3 files changed, 24 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 70e5bf4d72..8254e77e1b 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define DBGC_CLASS DBGC_LOCKING #include "includes.h" /* Current number of oplocks we have outstanding. */ @@ -118,10 +119,11 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) exclusive_oplocks_open++; } - DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, file_id = %lu, \ -tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, - (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); + DEBUG(5,("set_file_oplock: granted oplock on file %s, 0x%x/%.0f/%lu, " + "tv_sec = %x, tv_usec = %x\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, + fsp->file_id, (int)fsp->open_time.tv_sec, + (int)fsp->open_time.tv_usec )); return True; } @@ -191,7 +193,7 @@ BOOL remove_oplock(files_struct *fsp) ret = remove_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("remove_oplock: failed to remove share oplock for " - "file %s fnum %d, dev = %x, inode = %.0f\n", + "file %s fnum %d, 0x%x/%.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); } @@ -292,8 +294,8 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un files_struct *fsp = NULL; if( DEBUGLVL( 3 ) ) { - dbgtext( "initial_break_processing: called for dev = 0x%x, inode = %.0f file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id); + dbgtext( "initial_break_processing: called for 0x%x/%.0f/%u\n", + (unsigned int)dev, (double)inode, (int)file_id); dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", exclusive_oplocks_open, level_II_oplocks_open ); } @@ -403,9 +405,9 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, buf); - DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%d\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, - (int)msg.share_file_id)); + DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, + (double)msg.inode, msg.share_file_id)); fsp = initial_break_processing(msg.dev, msg.inode, msg.share_file_id); @@ -490,9 +492,9 @@ static void process_oplock_break_message(int msg_type, struct process_id src, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, buf); - DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%d\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, - (int)msg.share_file_id)); + DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, + (double)msg.inode, msg.share_file_id)); fsp = initial_break_processing(msg.dev, msg.inode, msg.share_file_id); @@ -693,9 +695,10 @@ static void process_oplock_break_response(int msg_type, struct process_id src, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, buf); - DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%u mid %u\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, - (unsigned int)msg.share_file_id, (unsigned int)msg.op_mid)); + DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, + (double)msg.inode, msg.share_file_id, + (unsigned int)msg.op_mid)); /* Here's the hack from open.c, store the mid in the 'port' field */ schedule_deferred_open_smb_message(msg.op_mid); @@ -719,8 +722,9 @@ static void process_open_retry_message(int msg_type, struct process_id src, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, buf); - DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f mid %u\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode, + DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n", + (int)procid_to_pid(&src), (unsigned int)msg.dev, + (double)msg.inode, msg.share_file_id, (unsigned int)msg.op_mid)); schedule_deferred_open_smb_message(msg.op_mid); diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 83883444a7..73d582157d 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define DBGC_CLASS DBGC_LOCKING #include "includes.h" #if HAVE_KERNEL_OPLOCKS_IRIX diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index ab0c08f7fc..9a5eb52e61 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define DBGC_CLASS DBGC_LOCKING #include "includes.h" #if HAVE_KERNEL_OPLOCKS_LINUX -- cgit From 4d55a81958a67d5da3227d7af79a5c630f678424 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 5 May 2006 07:15:45 +0000 Subject: r15450: Change profiling data macros to use stack variables rather than globals. This catches mismatched start/end calls and removes the need for special nested profiling calls. (This used to be commit ee750498812190edd3ec52ca3c750258f3b8a97a) --- source3/smbd/nttrans.c | 27 +++++++++++++++++++++++++-- source3/smbd/reply.c | 15 ++++++++------- source3/smbd/trans2.c | 37 +++++++++++++++++++++++++++++++++---- source3/smbd/vfs-wrap.c | 2 +- 4 files changed, 67 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 96e2c18bc0..3cdc4997b2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2719,6 +2719,7 @@ static int handle_nttrans(connection_struct *conn, /* Now we must call the relevant NT_TRANS function */ switch(state->call) { case NT_TRANSACT_CREATE: + { START_PROFILE_NESTED(NT_transact_create); outsize = call_nt_transact_create(conn, inbuf, outbuf, size, bufsize, @@ -2728,7 +2729,10 @@ static int handle_nttrans(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(NT_transact_create); break; + } + case NT_TRANSACT_IOCTL: + { START_PROFILE_NESTED(NT_transact_ioctl); outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, size, bufsize, @@ -2737,7 +2741,10 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_ioctl); break; + } + case NT_TRANSACT_SET_SECURITY_DESC: + { START_PROFILE_NESTED(NT_transact_set_security_desc); outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, size, bufsize, @@ -2746,7 +2753,10 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_set_security_desc); break; + } + case NT_TRANSACT_NOTIFY_CHANGE: + { START_PROFILE_NESTED(NT_transact_notify_change); outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, size, bufsize, @@ -2755,7 +2765,10 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_notify_change); break; + } + case NT_TRANSACT_RENAME: + { START_PROFILE_NESTED(NT_transact_rename); outsize = call_nt_transact_rename(conn, inbuf, outbuf, size, bufsize, @@ -2764,8 +2777,10 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_rename); break; + } case NT_TRANSACT_QUERY_SECURITY_DESC: + { START_PROFILE_NESTED(NT_transact_query_security_desc); outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, size, bufsize, @@ -2774,8 +2789,11 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_query_security_desc); break; + } + #ifdef HAVE_SYS_QUOTAS case NT_TRANSACT_GET_USER_QUOTA: + { START_PROFILE_NESTED(NT_transact_get_user_quota); outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, size, bufsize, @@ -2784,7 +2802,10 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_get_user_quota); break; + } + case NT_TRANSACT_SET_USER_QUOTA: + { START_PROFILE_NESTED(NT_transact_set_user_quota); outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, size, bufsize, @@ -2793,7 +2814,9 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_set_user_quota); break; + } #endif /* HAVE_SYS_QUOTAS */ + default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", @@ -2881,7 +2904,7 @@ int reply_nttrans(connection_struct *conn, DEBUG(0,("reply_nttrans: data malloc fail for %u " "bytes !\n", state->total_data)); TALLOC_FREE(state); - END_PROFILE(SMBtrans); + END_PROFILE(SMBnttrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) @@ -2901,7 +2924,7 @@ int reply_nttrans(connection_struct *conn, "bytes !\n", state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); - END_PROFILE(SMBtrans); + END_PROFILE(SMBnttrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0524078310..387ed4a47f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1085,12 +1085,13 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL mask_contains_wcard = False; BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; + START_PROFILE(SMBsearch); + if (lp_posix_pathnames()) { + END_PROFILE(SMBsearch); return reply_unknown(inbuf, outbuf); } - START_PROFILE(SMBsearch); - *mask = *directory = *fname = 0; /* If we were called as SMBffirst then we must expect close. */ @@ -1284,12 +1285,13 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size NTSTATUS err; BOOL path_contains_wcard = False; + START_PROFILE(SMBfclose); + if (lp_posix_pathnames()) { + END_PROFILE(SMBfclose); return reply_unknown(inbuf, outbuf); } - START_PROFILE(SMBfclose); - outsize = set_message(outbuf,1,0,True); p = smb_buf(inbuf) + 1; p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard); @@ -1517,13 +1519,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,ERROR_CLOSE); - END_PROFILE(SMBntcreateX); + END_PROFILE(SMBopenX); return ERROR_NT(NT_STATUS_DISK_FULL); } retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size); if (retval < 0) { close_file(fsp,ERROR_CLOSE); - END_PROFILE(SMBwrite); + END_PROFILE(SMBopenX); return ERROR_NT(NT_STATUS_DISK_FULL); } size = get_allocation_size(conn,fsp,&sbuf); @@ -2629,7 +2631,6 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length nread = read_file(fsp,data,startpos,smb_maxcnt); if (nread < 0) { - END_PROFILE(SMBreadX); return(UNIXERROR(ERRDOS,ERRnoaccess)); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5d6de951ef..fc14772c57 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5011,6 +5011,7 @@ int handle_trans2(connection_struct *conn, /* Now we must call the relevant TRANS2 function */ switch(state->call) { case TRANSACT2_OPEN: + { START_PROFILE_NESTED(Trans2_open); outsize = call_trans2open( conn, inbuf, outbuf, bufsize, @@ -5019,8 +5020,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_open); break; + } case TRANSACT2_FINDFIRST: + { START_PROFILE_NESTED(Trans2_findfirst); outsize = call_trans2findfirst( conn, inbuf, outbuf, bufsize, @@ -5029,8 +5032,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_findfirst); break; + } case TRANSACT2_FINDNEXT: + { START_PROFILE_NESTED(Trans2_findnext); outsize = call_trans2findnext( conn, inbuf, outbuf, size, bufsize, @@ -5039,8 +5044,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_findnext); break; + } case TRANSACT2_QFSINFO: + { START_PROFILE_NESTED(Trans2_qfsinfo); outsize = call_trans2qfsinfo( conn, inbuf, outbuf, size, bufsize, @@ -5049,8 +5056,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_qfsinfo); break; + } case TRANSACT2_SETFSINFO: + { START_PROFILE_NESTED(Trans2_setfsinfo); outsize = call_trans2setfsinfo( conn, inbuf, outbuf, size, bufsize, @@ -5059,9 +5068,11 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_setfsinfo); break; + } case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: + { START_PROFILE_NESTED(Trans2_qpathinfo); outsize = call_trans2qfilepathinfo( conn, inbuf, outbuf, size, bufsize, state->call, @@ -5070,8 +5081,11 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_qpathinfo); break; + } + case TRANSACT2_SETPATHINFO: case TRANSACT2_SETFILEINFO: + { START_PROFILE_NESTED(Trans2_setpathinfo); outsize = call_trans2setfilepathinfo( conn, inbuf, outbuf, size, bufsize, state->call, @@ -5080,8 +5094,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_setpathinfo); break; + } case TRANSACT2_FINDNOTIFYFIRST: + { START_PROFILE_NESTED(Trans2_findnotifyfirst); outsize = call_trans2findnotifyfirst( conn, inbuf, outbuf, size, bufsize, @@ -5090,8 +5106,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_findnotifyfirst); break; + } case TRANSACT2_FINDNOTIFYNEXT: + { START_PROFILE_NESTED(Trans2_findnotifynext); outsize = call_trans2findnotifynext( conn, inbuf, outbuf, size, bufsize, @@ -5100,7 +5118,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_findnotifynext); break; + } + case TRANSACT2_MKDIR: + { START_PROFILE_NESTED(Trans2_mkdir); outsize = call_trans2mkdir( conn, inbuf, outbuf, size, bufsize, @@ -5109,8 +5130,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_mkdir); break; + } case TRANSACT2_GET_DFS_REFERRAL: + { START_PROFILE_NESTED(Trans2_get_dfs_referral); outsize = call_trans2getdfsreferral( conn, inbuf, outbuf, size, bufsize, @@ -5119,7 +5142,10 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_get_dfs_referral); break; + } + case TRANSACT2_IOCTL: + { START_PROFILE_NESTED(Trans2_ioctl); outsize = call_trans2ioctl( conn, inbuf, outbuf, size, bufsize, @@ -5128,11 +5154,14 @@ int handle_trans2(connection_struct *conn, state->max_data_return); END_PROFILE_NESTED(Trans2_ioctl); break; + } + default: /* Error in request */ DEBUG(2,("Unknown request %d in trans2 call\n", state->call)); outsize = ERROR_DOS(ERRSRV,ERRerror); } + return outsize; } @@ -5246,7 +5275,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, "bytes !\n", state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); - END_PROFILE(SMBtrans); + END_PROFILE(SMBtrans2); return(ERROR_DOS(ERRDOS,ERRnomem)); } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) @@ -5269,7 +5298,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); - END_PROFILE(SMBtrans); + END_PROFILE(SMBtrans2); return outsize; } @@ -5379,7 +5408,7 @@ int reply_transs2(connection_struct *conn, if ((state->received_param < state->total_param) || (state->received_data < state->total_data)) { - END_PROFILE(SMBtranss); + END_PROFILE(SMBtranss2); return -1; } @@ -5396,7 +5425,7 @@ int reply_transs2(connection_struct *conn, TALLOC_FREE(state); if (outsize == 0) { - END_PROFILE(SMBtranss); + END_PROFILE(SMBtranss2); return(ERROR_DOS(ERRSRV,ERRnosupport)); } diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 55bf146c20..ee251c17d8 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -549,7 +549,7 @@ int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t { int saved_errno = errno; /* We might get ENOSYS */ if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { - END_PROFILE(syscall_chmod); + END_PROFILE(syscall_fchmod); return result; } /* Error - return the old errno. */ -- cgit From f2e788ca37b8c812ecaa2e6ccd380ebf68597bf0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 May 2006 23:36:36 +0000 Subject: r15467: Ensure every exit error path calls nt_status_squash. Jeremy. (This used to be commit e9b016ced636dfdfcb1c4d7d4313f89ddb5e7cbc) --- source3/smbd/sesssetup.c | 54 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7c90263a5b..295d3875e4 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -96,7 +96,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, char *p; if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - ERROR_NT(nt_status); + ERROR_NT(nt_status_squash(nt_status)); } else { set_message(outbuf,4,0,True); @@ -186,11 +186,11 @@ static int reply_spnego_kerberos(connection_struct *conn, mem_ctx = talloc_init("reply_spnego_kerberos"); if (mem_ctx == NULL) - return ERROR_NT(NT_STATUS_NO_MEMORY); + return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY)); if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { talloc_destroy(mem_ctx); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key); @@ -200,7 +200,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); talloc_destroy(mem_ctx); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } DEBUG(3,("Ticket name is [%s]\n", client)); @@ -212,7 +212,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&session_key); SAFE_FREE(client); talloc_destroy(mem_ctx); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } *p = 0; @@ -233,7 +233,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&session_key); SAFE_FREE(client); talloc_destroy(mem_ctx); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } } @@ -311,7 +311,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); talloc_destroy(mem_ctx); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } } @@ -331,7 +331,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); talloc_destroy(mem_ctx); - return ERROR_NT(ret); + return ERROR_NT(nt_status_squash(ret)); } } else { @@ -344,7 +344,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); talloc_destroy(mem_ctx); - return ERROR_NT(ret); + return ERROR_NT(nt_status_squash(ret)); } /* make_server_info_pw does not set the domain. Without this @@ -367,7 +367,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&session_key); TALLOC_FREE( mem_ctx ); TALLOC_FREE( server_info ); - return ERROR_NT(ret); + return ERROR_NT(nt_status_squash(ret)); } } @@ -520,7 +520,7 @@ static int reply_spnego_negotiate(connection_struct *conn, /* Kill the intermediate vuid */ invalidate_vuid(vuid); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } /* only look at the first OID for determining the mechToken -- @@ -567,7 +567,7 @@ static int reply_spnego_negotiate(connection_struct *conn, /* Kill the intermediate vuid */ invalidate_vuid(vuid); - return ERROR_NT(nt_status); + return ERROR_NT(nt_status_squash(nt_status)); } nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, @@ -604,7 +604,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, /* Kill the intermediate vuid */ invalidate_vuid(vuid); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } if (!*auth_ntlmssp_state) { @@ -612,7 +612,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, invalidate_vuid(vuid); /* auth before negotiatiate? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, @@ -664,7 +664,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, if (data_blob_len == 0) { /* an invalid request */ - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } bufrem = smb_bufrem(inbuf, p); @@ -696,14 +696,14 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, if (!vuser) { vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL); if (vuid == UID_FIELD_INVALID ) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } vuser = get_partial_auth_user_struct(vuid); } if (!vuser) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } SSVAL(outbuf,smb_uid,vuid); @@ -733,7 +733,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, /* Kill the intermediate vuid */ invalidate_vuid(vuid); - return ERROR_NT(nt_status); + return ERROR_NT(nt_status_squash(nt_status)); } } @@ -754,7 +754,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, data_blob_free(&blob1); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } /**************************************************************************** @@ -846,7 +846,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { if (!global_spnego_negotiated) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } if (SVAL(inbuf,smb_vwv4) == 0) { @@ -864,7 +864,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } if (doencrypt) { @@ -925,11 +925,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* check for nasty tricks */ if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } /* Save the lanman2 password and the NT md4 password. */ @@ -1007,7 +1007,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } fstrcpy(sub_user, user); } else { @@ -1038,7 +1038,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } else if (doencrypt) { if (!negprot_global_auth_context) { DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } nt_status = make_user_info_for_reply_enc(&user_info, user, domain, lm_resp, nt_resp); @@ -1087,7 +1087,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* Ensure we can't possible take a code path leading to a null defref. */ if (!server_info) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } nt_status = create_local_token(server_info); @@ -1130,7 +1130,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&lm_resp); if (sess_vuid == UID_FIELD_INVALID) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } /* current_user_info is changed on new vuid */ -- cgit From 83e4ea7e852e4ae9a4ba6fd187787c76f2d54ef6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 6 May 2006 15:46:53 +0000 Subject: r15472: Remove an unused function parameter (This used to be commit d2f39ae7fe79fd31846c555849655023a2d1cbc7) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 295d3875e4..b13042074a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -322,7 +322,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if ( map_domainuser_to_guest ) { make_server_info_guest(&server_info); } else if (logon_info) { - ret = make_server_info_info3(mem_ctx, real_username, real_username, domain, + ret = make_server_info_info3(mem_ctx, real_username, domain, &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", -- cgit From dc9f30b8b0ace8d6e2c8c0cbed537fde68d1556a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 6 May 2006 19:24:35 +0000 Subject: r15475: Ugly and disgusting patch to fix the username map problem I created by changing the token generation. I *hate* this code! Jerry, you have been looking at this as well, can you double-check that I did not screw it up? Thanks, Volker (This used to be commit 2765c4ff8d44c970db3e075b0a2412662f1936c6) --- source3/smbd/sesssetup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b13042074a..b086090bd9 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -176,6 +176,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB nullblob = data_blob(NULL, 0); fstring real_username; BOOL map_domainuser_to_guest = False; + BOOL username_was_mapped; PAC_LOGON_INFO *logon_info = NULL; ZERO_STRUCT(ticket); @@ -288,7 +289,7 @@ static int reply_spnego_kerberos(connection_struct *conn, /* lookup the passwd struct, create a new user if necessary */ - map_username( user ); + username_was_mapped = map_username( user ); pw = smb_getpwnam( mem_ctx, user, real_username, True ); if (!pw) { @@ -355,6 +356,8 @@ static int reply_spnego_kerberos(connection_struct *conn, pdb_set_domain(server_info->sam_account, domain, PDB_SET); } } + + server_info->was_mapped |= username_was_mapped; /* we need to build the token for the user. make_server_info_guest() already does this */ -- cgit From b3a5633de0dafacd3532fa132814739b0d6c84d4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 7 May 2006 17:33:10 +0000 Subject: r15495: current_user_info is not referenced in process.c (This used to be commit 8cedbbfbcf137b6a0c0323572982e9cb25648b0b) --- source3/smbd/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index aaf98203a2..440d0ac0a5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -43,7 +43,6 @@ int max_send = BUFFER_SIZE; int max_recv = BUFFER_SIZE; extern int last_message; -extern userdom_struct current_user_info; extern int smb_read_error; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; -- cgit From f7776975080c88bec9013ccac8185c582e818e54 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 9 May 2006 19:02:26 +0000 Subject: r15523: Honour the time_offset also when verifying kerberos tickets. This prevents a nasty failure condition in winbindd's pam_auth where a tgt and a service ticket could have been succefully retrieved, but just not validated. Guenther (This used to be commit a75dd80c6210d01aff104a86b0a9d39d65f2c348) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b086090bd9..8fe01a19b3 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -194,7 +194,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } - ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key); + ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key); data_blob_free(&ticket); -- cgit From 2602e5fab165d426e3a87e0cdcf8f7c67596e501 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 May 2006 23:10:01 +0000 Subject: r15555: Make "change notify timeout" a per-share parameter - used when there's no kernel or FAM change notify. If set to zero this will turn off change notify for the share except when we ourselves change something (renames / deletes etc. ). Designed to help on large directory shares where a new changenotify is issued between each delete. This will be fixed correctly when we move to internal change notify (eg. back-port Samba4 changenotify). Jeremy. (This used to be commit 5a17bffbcd5082fde79c241468a0ff2b5903d540) --- source3/smbd/notify.c | 14 +++++++++++++- source3/smbd/notify_hash.c | 20 +++++++++++++++++--- source3/smbd/service.c | 3 +++ 3 files changed, 33 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b2d0fc3326..829ca3a736 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -135,7 +135,19 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT } /**************************************************************************** - Return true if there are pending change notifies. + Set the current change notify timeout to the lowest value across all service + values. +****************************************************************************/ + +void set_change_notify_timeout(int val) +{ + if (val > 0) { + cnotify->select_time = MIN(cnotify->select_time, val); + } +} + +/**************************************************************************** + Longest time to sleep for before doing a change notify scan. ****************************************************************************/ int change_notify_timeout(void) diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index a98a028fae..0787a3eec5 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -81,6 +81,11 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, return True; } + if (lp_change_notify_timeout(SNUM(conn)) <= 0) { + /* It change notify timeout has been disabled, never scan the directory. */ + return True; + } + /* * If we are to watch for changes that are only stored * in inodes of files, not in the directory inode, we must @@ -179,9 +184,17 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, { struct change_data *data = (struct change_data *)datap; struct change_data data2; + int cnto = lp_change_notify_timeout(SNUM(conn)); + + if (t && cnto <= 0) { + /* Change notify turned off on this share. + * Only scan when (t==0) - we think something changed. */ + return False; + } - if (t && t < data->last_check_time + lp_change_notify_timeout()) + if (t && t < data->last_check_time + cnto) { return False; + } if (!change_to_user(conn,vuid)) return True; @@ -201,8 +214,9 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, return True; } - if (t) + if (t) { data->last_check_time = t; + } change_to_root_user(); @@ -229,7 +243,7 @@ struct cnotify_fns *hash_notify_init(void) cnotify.register_notify = hash_register_notify; cnotify.check_notify = hash_check_notify; cnotify.remove_notify = hash_remove_notify; - cnotify.select_time = lp_change_notify_timeout(); + cnotify.select_time = 60; /* Start with 1 minute default. */ cnotify.notification_fd = -1; return &cnotify; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ba87d0743d..7ca2380e0d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -930,6 +930,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, dbgtext( "(pid %d)\n", (int)sys_getpid() ); } + /* Setup the minimum value for a change notify wait time (seconds). */ + set_change_notify_timeout(lp_change_notify_timeout(snum)); + /* we've finished with the user stuff - go back to root */ change_to_root_user(); return(conn); -- cgit From 3895a5a1fcb2c949647fd310b21476aa1db377f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 13 May 2006 21:10:00 +0000 Subject: r15583: Add a comment while trying to understand this code (This used to be commit 7945c935bf197afb61286ddeb0e579078362a1fc) --- source3/smbd/password.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 8d33c1deed..230d7f297f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -189,6 +189,11 @@ int register_vuid(auth_serversupplied_info *server_info, vuser->vuid = next_vuid; if (!server_info) { + /* + * This happens in an unfinished NTLMSSP session setup. We + * need to allocate a vuid between the first and second calls + * to NTLMSSP. + */ next_vuid++; num_validated_vuids++; -- cgit From ee7b4b47cb590dc16ebdf3a40b360b0f0600aa84 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 13 May 2006 23:05:53 +0000 Subject: r15589: While trying to understand the vuid code I found that security=share is broken right now. r14112 broke it, in 3.0.22 register_vuid for security=share returns UID_FIELD_INVALID which in current 3_0 is turned into an error condition. This makes sure that we only call register_vuid if sec!=share and meanwhile also fixes a little memleak. Then I also found a crash in smbclient with sec=share and hostmsdfs=yes. There's another crash with sec=share when coming from w2k3, but I need sleep now. Someone (jerry,jra?) please review the sesssetup.c change. Thanks, Volker (This used to be commit 8059d0ae395604503cad3d9f197928305923e3f5) --- source3/smbd/password.c | 5 ++--- source3/smbd/sesssetup.c | 32 +++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 230d7f297f..73b0ebb4b3 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -155,10 +155,9 @@ int register_vuid(auth_serversupplied_info *server_info, { user_struct *vuser = NULL; - /* Ensure no vuid gets registered in share level security. */ + /* Paranoia check. */ if(lp_security() == SEC_SHARE) { - data_blob_free(&session_key); - return UID_FIELD_INVALID; + smb_panic("Tried to register uid in security=share\n"); } /* Limit allowed vuids to 16bits - VUID_OFFSET. */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8fe01a19b3..46acb20bda 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1127,20 +1127,30 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user); - data_blob_free(&nt_resp); - data_blob_free(&lm_resp); - - if (sess_vuid == UID_FIELD_INVALID) { - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); - } + if (lp_security() == SEC_SHARE) { + sess_vuid = UID_FIELD_INVALID; + data_blob_free(&session_key); + TALLOC_FREE(server_info); + } else { + /* register_vuid keeps the server info */ + sess_vuid = register_vuid(server_info, session_key, + nt_resp.data ? nt_resp : lm_resp, + sub_user); + if (sess_vuid == UID_FIELD_INVALID) { + data_blob_free(&nt_resp); + data_blob_free(&lm_resp); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + } - /* current_user_info is changed on new vuid */ - reload_services( True ); + /* current_user_info is changed on new vuid */ + reload_services( True ); - sessionsetup_start_signing_engine(server_info, inbuf); + sessionsetup_start_signing_engine(server_info, inbuf); + } + data_blob_free(&nt_resp); + data_blob_free(&lm_resp); + SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); -- cgit From 75d2304643c6935c0705b1a8ae2ea73a527f2f97 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 14 May 2006 15:24:14 +0000 Subject: r15601: Fix segfaults with 'security=share' and 'guest only = yes' Volker (This used to be commit ea7cced6bcb3cb7d817e4cb072774692e4afedb0) --- source3/smbd/service.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 7ca2380e0d..cb9bfcc27a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -523,8 +523,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } + conn->nt_user_token = NULL; + if (lp_guest_only(snum)) { const char *guestname = lp_guestaccount(); + NTSTATUS status2; + char *found_username; guest = True; pass = getpwnam_alloc(NULL, guestname); if (!pass) { @@ -534,11 +538,18 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *status = NT_STATUS_NO_SUCH_USER; return NULL; } - fstrcpy(user,pass->pw_name); + status2 = create_token_from_username(NULL, pass->pw_name, True, + &conn->uid, &conn->gid, + &found_username, + &conn->nt_user_token); + if (!NT_STATUS_IS_OK(status2)) { + conn_free(conn); + *status = status2; + return NULL; + } + fstrcpy(user, found_username); + string_set(&conn->user,user); conn->force_user = True; - conn->uid = pass->pw_uid; - conn->gid = pass->pw_gid; - string_set(&conn->user,pass->pw_name); TALLOC_FREE(pass); DEBUG(3,("Guest only user %s\n",user)); } else if (vuser) { @@ -570,6 +581,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, fstrcpy(user,vuser->user.unix_name); guest = vuser->guest; } else if (lp_security() == SEC_SHARE) { + NTSTATUS status2; + char *found_username; /* add it as a possible user name if we are in share mode security */ add_session_user(lp_servicename(snum)); @@ -582,12 +595,18 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } pass = Get_Pwnam(user); + status2 = create_token_from_username(NULL, pass->pw_name, True, + &conn->uid, &conn->gid, + &found_username, + &conn->nt_user_token); + if (!NT_STATUS_IS_OK(status2)) { + conn_free(conn); + *status = status2; + return NULL; + } + fstrcpy(user, found_username); + string_set(&conn->user,user); conn->force_user = True; - conn->uid = pass->pw_uid; - conn->gid = pass->pw_gid; - string_set(&conn->user, pass->pw_name); - fstrcpy(user, pass->pw_name); - } else { DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); conn_free(conn); @@ -626,7 +645,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->aio_write_behind_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); - conn->nt_user_token = NULL; conn->read_only = lp_readonly(conn->service); conn->admin_user = False; -- cgit From c91a675ac108f48046ce72287c6d70a1a54ef65f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 May 2006 15:01:57 +0000 Subject: r15660: Without this when using smbcquotas I get MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close fd=-1 fnum=4321 (numopen=1) close_file: Could not get share mode lock for file $Extend/$Quota:$Q:$INDEX_ALLOCATION unix_error_packet: error string = Das Argument ist ungültig error packet at smbd/reply.c(3325) cmd=4 (SMBclose) NT_STATUS_INVALID_HANDLE so a fake file needs special close handling I think. Jeremy, can you check this? Thanks, Volker (This used to be commit f66b9701b5c6bb6302fa11889adab6902cbaf2e3) --- source3/smbd/close.c | 2 ++ source3/smbd/fake_file.c | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index bc1182032d..f2d54445b9 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -447,6 +447,8 @@ int close_file(files_struct *fsp, enum file_close_type close_type) return close_directory(fsp, close_type); else if (fsp->is_stat) return close_stat(fsp); + else if (fsp->fake_file_handle != NULL) + return close_fake_file(fsp); else return close_normal_file(fsp, close_type); } diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 1356baf1a8..b4f1f02b72 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -156,3 +156,9 @@ void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) talloc_destroy((*fh)->mem_ctx); (*fh) = NULL; } + +int close_fake_file(files_struct *fsp) +{ + file_free(fsp); + return 0; +} -- cgit From cc9ea93456e594432e203e6d2d2f4dbcaac9a3dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 May 2006 23:15:53 +0000 Subject: r15668: DOS or FCB opens share one share mode entry from different fsp pointers. Ensure we cope with this to pass Samba4 DENY tests (we used to pass these, there must have been a regression with newer code). We now pass them. Jeremy (This used to be commit fd6fa1d4eaf61783df74ee2da50d331477f06998) --- source3/smbd/close.c | 138 +++++++++++++++++++++++--------------------- source3/smbd/files.c | 8 +-- source3/smbd/oplock.c | 6 +- source3/smbd/oplock_irix.c | 12 ++-- source3/smbd/oplock_linux.c | 6 +- 5 files changed, 89 insertions(+), 81 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index f2d54445b9..8a63d3b227 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -143,54 +143,15 @@ static void notify_deferred_opens(struct share_mode_lock *lck) } /**************************************************************************** - Close a file. - - close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE. - printing and magic scripts are only run on normal close. - delete on close is done on normal and shutdown close. + Deal with removing a share mode on last close. ****************************************************************************/ -static int close_normal_file(files_struct *fsp, enum file_close_type close_type) +static int close_remove_share_mode(files_struct *fsp, enum file_close_type close_type) { - BOOL delete_file = False; connection_struct *conn = fsp->conn; - int saved_errno = 0; - int err = 0; - int err1 = 0; + BOOL delete_file = False; struct share_mode_lock *lck; - remove_pending_lock_requests_by_fid(fsp); - - if (fsp->aio_write_behind) { - /* - * If we're finishing write behind on a close we can get a write - * error here, we must remember this. - */ - int ret = wait_for_aio_completion(fsp); - if (ret) { - saved_errno = ret; - err1 = -1; - } - } else { - cancel_aio_by_fsp(fsp); - } - - /* - * If we're flushing on a close we can get a write - * error here, we must remember this. - */ - - if (close_filestruct(fsp) == -1) { - saved_errno = errno; - err1 = -1; - } - - if (fsp->print_file) { - print_fsp_end(fsp, close_type); - file_free(fsp); - return 0; - } - /* * Lock the share entries, and determine if we should delete * on close. If so delete whilst the lock is still in effect. @@ -200,12 +161,12 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { - DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name)); + DEBUG(0, ("close_remove_share_mode: Could not get share mode lock for file %s\n", fsp->fsp_name)); return EINVAL; } if (!del_share_mode(lck, fsp)) { - DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name)); + DEBUG(0, ("close_remove_share_mode: Could not delete share entry for file %s\n", fsp->fsp_name)); } delete_file = (lck->delete_on_close | lck->initial_delete_on_close); @@ -236,13 +197,13 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) lck->delete_token) { SMB_STRUCT_STAT sbuf; - DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", + DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); /* Become the user who requested the delete. */ if (!push_sec_ctx()) { - smb_panic("close_file: file %s. failed to push sec_ctx.\n"); + smb_panic("close_remove_share_mode: file %s. failed to push sec_ctx.\n"); } set_sec_ctx(lck->delete_token->uid, @@ -253,17 +214,17 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) /* We can only delete the file if the name we have is still valid and hasn't been renamed. */ - + if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { - DEBUG(5,("close_file: file %s. Delete on close was set " + DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " "and stat failed with error %s\n", fsp->fsp_name, strerror(errno) )); } else { if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { - DEBUG(5,("close_file: file %s. Delete on close was set and " + DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set and " "dev and/or inode does not match\n", fsp->fsp_name )); - DEBUG(5,("close_file: file %s. stored dev = %x, inode = %.0f " + DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, inode = %.0f " "stat dev = %x, inode = %.0f\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, @@ -277,21 +238,80 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) * we log this but not at debug level zero. */ - DEBUG(5,("close_file: file %s. Delete on close was set " + DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " "and unlink failed with error %s\n", fsp->fsp_name, strerror(errno) )); } } /* unbecome user. */ pop_sec_ctx(); - + process_pending_change_notify_queue((time_t)0); } TALLOC_FREE(lck); + return 0; +} + +/**************************************************************************** + Close a file. + + close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE. + printing and magic scripts are only run on normal close. + delete on close is done on normal and shutdown close. +****************************************************************************/ + +static int close_normal_file(files_struct *fsp, enum file_close_type close_type) +{ + connection_struct *conn = fsp->conn; + int saved_errno = 0; + int err = 0; + int err1 = 0; - if(fsp->oplock_type) + remove_pending_lock_requests_by_fid(fsp); + + if (fsp->aio_write_behind) { + /* + * If we're finishing write behind on a close we can get a write + * error here, we must remember this. + */ + int ret = wait_for_aio_completion(fsp); + if (ret) { + saved_errno = ret; + err1 = -1; + } + } else { + cancel_aio_by_fsp(fsp); + } + + /* + * If we're flushing on a close we can get a write + * error here, we must remember this. + */ + + if (close_filestruct(fsp) == -1) { + saved_errno = errno; + err1 = -1; + } + + if (fsp->print_file) { + print_fsp_end(fsp, close_type); + file_free(fsp); + return 0; + } + + /* If this is an old DOS or FCB open and we have multiple opens on + the same handle we only have one share mode. Ensure we only remove + the share mode on the last close. */ + + if (fsp->fh->ref_count == 1) { + /* Should we return on error here... ? */ + close_remove_share_mode(fsp, close_type); + } + + if(fsp->oplock_type) { release_file_oplock(fsp); + } locking_close_file(fsp); @@ -323,9 +343,6 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) conn->num_files_open, (err == -1 || err1 == -1) ? strerror(saved_errno) : "")); - if (fsp->fsp_name) - string_free(&fsp->fsp_name); - file_free(fsp); if (err == -1 || err1 == -1) { @@ -410,11 +427,6 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) * Do the code common to files and directories. */ close_filestruct(fsp); - - if (fsp->fsp_name) { - string_free(&fsp->fsp_name); - } - file_free(fsp); return 0; } @@ -429,10 +441,6 @@ static int close_stat(files_struct *fsp) * Do the code common to files and directories. */ close_filestruct(fsp); - - if (fsp->fsp_name) - string_free(&fsp->fsp_name); - file_free(fsp); return 0; } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index ba4baa93b1..53207e876e 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -109,7 +109,7 @@ files_struct *file_new(connection_struct *conn) fsp->fh->fd = -1; fsp->conn = conn; - fsp->file_id = get_gen_count(); + fsp->fh->file_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; @@ -238,7 +238,7 @@ void file_dump_open_table(void) for (fsp=Files;fsp;fsp=fsp->next,count++) { DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n", - count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->file_id, + count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->file_id, (unsigned int)fsp->dev, (double)fsp->inode )); } } @@ -277,7 +277,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */ if (fsp->dev == dev && fsp->inode == inode && - fsp->file_id == file_id ) { + fsp->fh->file_id == file_id ) { if (count > 10) { DLIST_PROMOTE(Files, fsp); } @@ -287,7 +287,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \ oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, (unsigned int)fsp->file_id, + (double)fsp->inode, (unsigned int)fsp->fh->file_id, (unsigned int)fsp->oplock_type )); smb_panic("file_find_dif\n"); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8254e77e1b..42c64a2843 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -89,7 +89,7 @@ void process_kernel_oplocks(fd_set *pfds) /* Put the kernel break info into the message. */ SDEV_T_VAL(msg,0,fsp->dev); SINO_T_VAL(msg,8,fsp->inode); - SIVAL(msg,16,fsp->file_id); + SIVAL(msg,16,fsp->fh->file_id); /* Don't need to be root here as we're only ever sending to ourselves. */ @@ -122,7 +122,7 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) DEBUG(5,("set_file_oplock: granted oplock on file %s, 0x%x/%.0f/%lu, " "tv_sec = %x, tv_usec = %x\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - fsp->file_id, (int)fsp->open_time.tv_sec, + fsp->fh->file_id, (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); return True; @@ -333,7 +333,7 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n", - (unsigned int)dev, (double)inode, fsp->file_id ); + (unsigned int)dev, (double)inode, fsp->fh->file_id ); dbgtext( "Allowing break to succeed regardless.\n" ); } return NULL; diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 73d582157d..248d902028 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -145,7 +145,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) DEBUG(5,("irix_oplock_receive_message: kernel oplock break request " "received for dev = %x, inode = %.0f\n, file_id = %ul", - (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); + (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id )); return fsp; } @@ -160,18 +160,18 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) if(errno != EAGAIN) { DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f, file_id = %ul. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id, strerror(errno) )); } else { DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f, file_id = %ul. Another process had the file open.\n", - fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); + fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id )); } return False; } DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id)); return True; } @@ -190,7 +190,7 @@ static void irix_release_kernel_oplock(files_struct *fsp) int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->file_id, state ); + (double)fsp->inode, fsp->fh->file_id, state ); } /* @@ -201,7 +201,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->file_id, strerror(errno) ); + (double)fsp->inode, fsp->fh->file_id, strerror(errno) ); } } } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 9a5eb52e61..f186c13ebd 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -164,7 +164,7 @@ inode = %.0f. (%s)\n", } DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id)); return True; } @@ -183,7 +183,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->file_id, state ); + (double)fsp->inode, fsp->fh->file_id, state ); } /* @@ -194,7 +194,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->file_id, strerror(errno) ); + (double)fsp->inode, fsp->fh->file_id, strerror(errno) ); } } } -- cgit From 679e539655dcf37a719816f9c4e4cddfdf73379d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 19 May 2006 14:00:12 +0000 Subject: r15712: BUG 3435: patch from volker to fix 'msdfs root = yes' in [homes] (This used to be commit 466478f07e6233b89f442660ad42ef7ee870ad48) --- source3/smbd/msdfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4606441c3a..700aa2ae81 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -419,7 +419,10 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_ return False; } - if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) { + if ( !( strequal(dp.servicename, lp_servicename(SNUM(conn))) + || ( strequal(dp.servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) + { return False; } -- cgit From e2a90398eca525351022b47eb1e4b864ee9e63ea Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 22 May 2006 18:52:54 +0000 Subject: r15817: Remove some unused code (This used to be commit 72f103708d17aa86e09fa7a02699f969f7ee9190) --- source3/smbd/files.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 53207e876e..e020d8e13a 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -32,8 +32,6 @@ static files_struct *Files; /* a fsp to use when chaining */ static files_struct *chain_fsp = NULL; -/* a fsp to use to save when breaking an oplock. */ -static files_struct *oplock_save_chain_fsp = NULL; static int files_used; @@ -502,24 +500,6 @@ void file_chain_reset(void) chain_fsp = NULL; } -/**************************************************************************** - Save the chained fsp - done when about to do an oplock break. -****************************************************************************/ - -void file_chain_save(void) -{ - oplock_save_chain_fsp = chain_fsp; -} - -/**************************************************************************** - Restore the chained fsp - done after an oplock break. -****************************************************************************/ - -void file_chain_restore(void) -{ - chain_fsp = oplock_save_chain_fsp; -} - /**************************************************************************** Duplicate the file handle part for a DOS or FCB open. ****************************************************************************/ -- cgit From 90a6873b0570f2691ba8d8fd11154c856bdd4415 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 24 May 2006 04:02:14 +0000 Subject: r15848: Introduce commandline options to set the remainder of the parameters in dynconfig.c. This is mainly useful for test harness scripts, hence the lack of short options. (This used to be commit bf3b71c84595608d71e0f15a6158adacb295518e) --- source3/smbd/server.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d16579f24a..2bfeae9f54 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -744,16 +744,17 @@ void build_options(BOOL screen); poptContext pc; struct poptOption long_options[] = { - POPT_AUTOHELP + POPT_AUTOHELP {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, - {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" }, - {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, + {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" }, + {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, POPT_COMMON_SAMBA - { NULL } + POPT_COMMON_DYNCONFIG + POPT_TABLEEND }; load_case_tables(); -- cgit From 9f6631b469366e3617437a12cf40b1a8c7479ad4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 May 2006 15:43:12 +0000 Subject: r15887: Ensure we use sys_write so we're not interrupted. Jeremy. (This used to be commit c66620770d2154543a6ec99d369771b339df5463) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 16b44a54bf..011122ee57 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -241,7 +241,7 @@ static int expect(int master, char *issue, char *expected) if (lp_passwd_chat_debug()) DEBUG(100, ("expect: sending [%s]\n", issue)); - if ((len = write(master, issue, strlen(issue))) != strlen(issue)) { + if ((len = sys_write(master, issue, strlen(issue))) != strlen(issue)) { DEBUG(2,("expect: (short) write returned %d\n", len )); return False; } -- cgit From 263b01ecb9a09c80c3b519c5ec4e52437ace9da0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 May 2006 21:38:54 +0000 Subject: r15911: Make us survive rpc-authcontext committed next (This used to be commit c24bfdce625782637b5f4d11a5117ef795ddfc2f) --- source3/smbd/ipc.c | 6 ++++++ source3/smbd/pipes.c | 10 ++++++++++ 2 files changed, 16 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7f9505606c..3250387909 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -291,6 +291,12 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, return ERROR_NT(NT_STATUS_INVALID_HANDLE); } + if (vuid != p->vuid) { + DEBUG(1, ("Got pipe request (pnum %x) using invalid VUID %d, " + "expected %d\n", pnum, vuid, p->vuid)); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum)); /* record maximum data length that can be transmitted in an SMBtrans */ diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 12f3d180b1..2d90383706 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -121,6 +121,7 @@ int reply_open_pipe_and_X(connection_struct *conn, int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) { smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); + uint16 vuid = SVAL(inbuf,smb_uid); size_t numtowrite = SVAL(inbuf,smb_vwv1); int nwritten; int outsize; @@ -130,6 +131,10 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) return(ERROR_DOS(ERRDOS,ERRbadfid)); } + if (p->vuid != vuid) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + data = smb_buf(inbuf) + 3; if (numtowrite == 0) { @@ -161,6 +166,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) { smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); + uint16 vuid = SVAL(inbuf,smb_uid); size_t numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); @@ -172,6 +178,10 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR_DOS(ERRDOS,ERRbadfid)); } + if (p->vuid != vuid) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + data = smb_base(inbuf) + smb_doff; if (numtowrite == 0) { -- cgit From 803eed10629364445524163d47786431fd91b1f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 29 May 2006 21:44:19 +0000 Subject: r15936: Fix memory leak on error exit path. Trying to track down #3308. Jeremy. (This used to be commit e39c11c91153c1ed547bc635d02769a1cdf3ecc0) --- source3/smbd/trans2.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fc14772c57..ad78c51fdf 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -727,7 +727,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i time_t open_time; #endif int open_ofun; - int32 open_size; + uint32 open_size; char *pname; pstring fname; SMB_OFF_T size=0; @@ -860,6 +860,30 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return(ERROR_DOS(ERRDOS,ERRnoaccess)); } + /* Save the requested allocation size. */ + /* Allocate space for the file if a size hint is supplied */ + if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size; + if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (fsp->is_directory) { + close_file(fsp,ERROR_CLOSE); + /* Can't set allocation size on a directory. */ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,ERROR_CLOSE); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + + /* Adjust size here to return the right size in the reply. + Windows does it this way. */ + size = fsp->initial_allocation_size; + } else { + fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size); + } + } + if (total_data && smb_action == FILE_WAS_CREATED) { status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); @@ -5238,6 +5262,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, } else { DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count)); DEBUG(2,("Transaction is %d\n",tran_call)); + TALLOC_FREE(state); END_PROFILE(SMBtrans2); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } -- cgit From 0a1ca7fa3d19f46c4bcb0c80c78a619c90fe5f2a Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 29 May 2006 23:54:53 +0000 Subject: r15943: Update misleading DEBUG statements and comments that refer to open_file_shared. (This used to be commit 784126edff942d1c2f79f7c9feb59980426f331e) --- source3/smbd/nttrans.c | 5 +++-- source3/smbd/open.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3cdc4997b2..e2a2543e30 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1704,8 +1704,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new close_ret = close_file(fsp2,NORMAL_CLOSE); - /* Grrr. We have to do this as open_file_shared1 adds aARCH when it - creates the file. This isn't the correct thing to do in the copy case. JRA */ + /* Grrr. We have to do this as open_file_ntcreate adds aARCH when it + creates the file. This isn't the correct thing to do in the copy + case. JRA */ file_set_dosmode(conn, newname, fattr, &sbuf2, True); if (ret < (SMB_OFF_T)sbuf1.st_size) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3d537b2f39..f1d1b776dd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -245,7 +245,7 @@ static BOOL open_file(files_struct *fsp, /* * We can't actually truncate here as the file may be locked. - * open_file_shared will take care of the truncate later. JRA. + * open_file_ntcreate will take care of the truncate later. JRA. */ local_flags &= ~O_TRUNC; @@ -1742,7 +1742,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } else { - DEBUG(5, ("open_file_shared: reset " + DEBUG(5, ("open_file_ntcreate: reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ @@ -1751,7 +1751,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) - DEBUG(5, ("open_file_shared: failed to reset " + DEBUG(5, ("open_file_ntcreate: failed to reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); } -- cgit From 41f139c0bbe02ac4abe15d1e540fe9bff8cff5a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 05:08:15 +0000 Subject: r15949: Patch for bug #3308 to stop us returning duplicate mid replies on path based set-eof trans2 calls. Needs modification for HEAD (as in head open_file_ntcreateX properly returns NTSTATUS - I'll fix this tomorrow my time). Secondly it still fails the Samba4 RAW-OPLOCK smbtorture because of an interesting case. Our oplock code always returns "break to level 2" if it can. In this case (path-based set-eof or set-allocation size on an exclusive oplocked file) W2K3 always sends a break-to-none. We send the break to none (from level2) after we've done the write for eof or allocation size. I need to work out some way of telling our break code to always break to none (might need to extend the message field). Jeremy. (This used to be commit ad9895c654f400e242adcd4099f7cd004521ee92) --- source3/smbd/nttrans.c | 10 +++++----- source3/smbd/open.c | 13 ++++++++----- source3/smbd/trans2.c | 21 ++++++++++++++------- 3 files changed, 27 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e2a2543e30..5d19d496fd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1652,11 +1652,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new fsp1 = open_file_ntcreate(conn,oldname,&sbuf1, FILE_READ_DATA, /* Read-only. */ - 0, /* No sharing. */ + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, /* No create options. */ FILE_ATTRIBUTE_NORMAL, - INTERNAL_OPEN_ONLY, + NO_OPLOCK, &info); if (!fsp1) { @@ -1669,12 +1669,12 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new } fsp2 = open_file_ntcreate(conn,newname,&sbuf2, - FILE_WRITE_DATA, /* Read-only. */ - 0, /* No sharing. */ + FILE_WRITE_DATA, /* Write-only. */ + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_CREATE, 0, /* No create options. */ fattr, - INTERNAL_OPEN_ONLY, + NO_OPLOCK, &info); if (!fsp2) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f1d1b776dd..5b615f01e2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -599,7 +599,7 @@ static BOOL is_delete_request(files_struct *fsp) { } /* - * 1) No files open at all: Grant whatever the client wants. + * 1) No files open at all or internal open: Grant whatever the client wants. * * 2) Exclusive (or batch) oplock around: If the requested access is a delete * request, break if the oplock around is a batch oplock. If it's another @@ -608,7 +608,10 @@ static BOOL is_delete_request(files_struct *fsp) { * 3) Only level2 around: Grant level2 and do nothing else. */ -static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number) +static BOOL delay_for_oplocks(struct share_mode_lock *lck, + files_struct *fsp, + int pass_number, + BOOL internal_only_open) { int i; struct share_mode_entry *exclusive = NULL; @@ -616,7 +619,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, in BOOL delay_it = False; BOOL have_level2 = False; - if (is_stat_open(fsp->access_mask)) { + if (internal_only_open || is_stat_open(fsp->access_mask)) { fsp->oplock_type = NO_OPLOCK; return False; } @@ -1367,7 +1370,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1)) { + if (delay_for_oplocks(lck, fsp, 1, internal_only_open)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); return NULL; @@ -1380,7 +1383,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* We might be going to allow this open. Check oplock status again. */ /* Second pass - send break for both batch or exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2)) { + if (delay_for_oplocks(lck, fsp, 2, internal_only_open)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); return NULL; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ad78c51fdf..a033833d00 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4020,15 +4020,19 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char new_fsp = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, - FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - INTERNAL_OPEN_ONLY, + NO_OPLOCK, NULL); if (new_fsp == NULL) { - return(UNIXERROR(ERRDOS,ERRbadpath)); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } + return(UNIXERROR(ERRDOS,ERRnoaccess)); } ret = vfs_allocate_file_space(new_fsp, allocation_size); if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) { @@ -4561,7 +4565,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", POSIX_LOCK, &my_lock_ctx); - /* TODO: Deal with rescheduling blocking lock fail here... */ if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up @@ -4660,15 +4663,19 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", new_fsp = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, - FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - INTERNAL_OPEN_ONLY, + NO_OPLOCK, NULL); if (new_fsp == NULL) { - return(UNIXERROR(ERRDOS,ERRbadpath)); + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } + return(UNIXERROR(ERRDOS,ERRnoaccess)); } ret = vfs_set_filelen(new_fsp, size); close_file(new_fsp,NORMAL_CLOSE); -- cgit From bef4969247da237e7b50fd2abd207de92e9bc980 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 05:24:21 +0000 Subject: r15951: oplock_request must be an int, not a BOOL. We were getting away with mixing types. Not cool. Jeremy. (This used to be commit ad3bc112a21afd3a04449ec3f604e017d753c224) --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 387ed4a47f..d333ebf32e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1433,9 +1433,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt uint32 smb_attr = SVAL(inbuf,smb_vwv5); /* Breakout the oplock request bits so we can set the reply bits separately. */ - BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); - BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); - BOOL oplock_request = ex_oplock_request | core_oplock_request; + int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); + int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); + int oplock_request = ex_oplock_request | core_oplock_request; #if 0 int smb_sattr = SVAL(inbuf,smb_vwv4); uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); -- cgit From 7361c7a883646dd065eabf81e0b1dc60cc9d1f39 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 18:17:37 +0000 Subject: r15958: Make us pass RAW-OPLOCK with kernel oplocks off. This allows a requestor to set FORCE_OPLOCK_BREAK_TO_NONE to ensure we don't break to level 2. Fixed a couple of resource leaks in error paths in open_file_ntcreatex. Jeremy. (This used to be commit c7c9adcce7f13d01445f31b07fb28a76f0a1d6df) --- source3/smbd/open.c | 33 ++++++++++++++++++++------------- source3/smbd/oplock.c | 1 + source3/smbd/trans2.c | 4 ++-- 3 files changed, 23 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5b615f01e2..042d41453e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -611,7 +611,7 @@ static BOOL is_delete_request(files_struct *fsp) { static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number, - BOOL internal_only_open) + int oplock_request) { int i; struct share_mode_entry *exclusive = NULL; @@ -619,7 +619,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL delay_it = False; BOOL have_level2 = False; - if (internal_only_open || is_stat_open(fsp->access_mask)) { + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { fsp->oplock_type = NO_OPLOCK; return False; } @@ -686,8 +686,16 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); + /* Create the message. */ share_mode_entry_to_message(msg, exclusive); + /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We don't + want this set in the share mode struct pointed to by lck. */ + + if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { + SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); + } + become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); @@ -1090,7 +1098,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, int flags2=0; BOOL file_existed = VALID_STAT(*psbuf); BOOL def_acl = False; - BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; BOOL fsp_open = False; @@ -1133,11 +1140,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, create_disposition, create_options, unx_mode, oplock_request)); - if (oplock_request == INTERNAL_OPEN_ONLY) { - internal_only_open = True; - oplock_request = 0; - } - if ((pml = get_open_deferred_message(mid)) != NULL) { struct deferred_open_record *state = (struct deferred_open_record *)pml->private_data.data; @@ -1174,7 +1176,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* ignore any oplock requests if oplocks are disabled */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || IS_VETO_OPLOCK_PATH(conn, fname)) { - oplock_request = 0; + /* Mask off everything except the private Samba bits. */ + oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; } /* this is for OS/2 long file names - say we don't support them */ @@ -1349,7 +1352,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = access_mask; - fsp->oplock_type = oplock_request; + /* Ensure no SAMBA_PRIVATE bits can be set. */ + fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); if (timeval_is_zero(&request_time)) { request_time = fsp->open_time; @@ -1364,15 +1368,17 @@ files_struct *open_file_ntcreate(connection_struct *conn, fname); if (lck == NULL) { + file_free_fsp(fsp); DEBUG(0, ("Could not get share mode lock\n")); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, internal_only_open)) { + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); + file_free_fsp(fsp); return NULL; } @@ -1383,9 +1389,10 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* We might be going to allow this open. Check oplock status again. */ /* Second pass - send break for both batch or exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, internal_only_open)) { + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); + file_free_fsp(fsp); return NULL; } } @@ -1459,7 +1466,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, * cope with the braindead 1 second delay. */ - if (!internal_only_open && + if (!(oplock_request & INTERNAL_OPEN_ONLY) && lp_defer_sharing_violations()) { struct timeval timeout; struct deferred_open_record state; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 42c64a2843..1f731e1729 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -540,6 +540,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, } if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && + !(msg.op_type & FORCE_OPLOCK_BREAK_TO_NONE) && !koplocks && /* NOTE: we force levelII off for kernel oplocks - * this will change when it is supported */ lp_level2_oplocks(SNUM(fsp->conn))) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a033833d00..eda4837ba4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4024,7 +4024,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - NO_OPLOCK, + FORCE_OPLOCK_BREAK_TO_NONE, NULL); if (new_fsp == NULL) { @@ -4667,7 +4667,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - NO_OPLOCK, + FORCE_OPLOCK_BREAK_TO_NONE, NULL); if (new_fsp == NULL) { -- cgit From b990e788665ec2491056f3df66156aa7c51bdb1d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 18:26:49 +0000 Subject: r15959: Ooops. Use the right file_free call... Jeremy. (This used to be commit 1117a327bd4fb425d25ea63df782095701fb83bb) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 042d41453e..1331863bdf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1368,7 +1368,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, fname); if (lck == NULL) { - file_free_fsp(fsp); + file_free(fsp); DEBUG(0, ("Could not get share mode lock\n")); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; @@ -1378,7 +1378,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); - file_free_fsp(fsp); + file_free(fsp); return NULL; } @@ -1392,7 +1392,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); - file_free_fsp(fsp); + file_free(fsp); return NULL; } } -- cgit From 73cc5f1e259fac9656df6a030a91b5005cba1da4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 18:38:10 +0000 Subject: r15960: Don't double-free (ensure we always free file_fsp in the same place on error - I missed the extra free in delay_for_oplocks). Jeremy. (This used to be commit 146a2648156563b41642d42c46aff401e435a42b) --- source3/smbd/open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1331863bdf..633e70ac31 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -703,7 +703,6 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); } - file_free(fsp); } return delay_it; -- cgit From 777c22b300c573e94d4dc99452575b7af7676774 Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 6 Jun 2006 07:43:17 +0000 Subject: r16057: Coalesce the DMAPI configure tests into a single macro. Add a more specific probe to try and eliminate old, incompatible DMAPI implementations provided by IRIX 6.4 and AIX 4.3. (This used to be commit aafd4db457ce8a60c628d54a3ace3b97c8885dca) --- source3/smbd/dmapi.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 4a6cba293b..a9d83c782b 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -24,12 +24,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_DMAPI -#if defined(HAVE_LIBDM) || defined(HAVE_LIBJFSDM) || defined(HAVE_LIBXDSM) -#if defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H) || defined(HAVE_SYS_JFSDMAPI_H) || defined(HAVE_SYS_DMAPI_H) -#define USE_DMAPI 1 -#endif -#endif - #ifndef USE_DMAPI int dmapi_init_session(void) { return -1; } -- cgit From 088c571df8ae984e761a5975ddbf66a652ad0264 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Jun 2006 01:36:58 +0000 Subject: r16112: Added Volker's fix for extra odd byte at the end of UNIX_BASIC infolevel. Checked client implementations (cifsfs and libsmb) and they ignore it. Thanks Volker. Jeremy. (This used to be commit 6cd1cb5c9deba2aa0d7a3251c8142834cbaba6d1) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index eda4837ba4..71ff79081d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3431,7 +3431,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */ SIVAL(pdata,4,0); - pdata += 8+1; + pdata += 8; data_size = PTR_DIFF(pdata,(*ppdata)); { -- cgit From 4d1688bf6bac74df93eb4c3e8f540f541a25390d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 13 Jun 2006 18:06:12 +0000 Subject: r16198: Fix Klocwork 1023 (This used to be commit 3a7d01afbebe5c4c36935b6128998e1327c8f856) --- source3/smbd/open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 633e70ac31..821feffd65 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1905,7 +1905,6 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: invalid create_disposition " "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); - file_free(fsp); set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } -- cgit From a47ffac30d3363a93182584859ab273cfc3de2d3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 13 Jun 2006 19:40:28 +0000 Subject: r16203: Fix potentially writing one result of strtok beyond the end of alt_path. Found by Klocwork, ID 653. Volker (This used to be commit 4cb8cf221f986b15de3ac608b173310c14248533) --- source3/smbd/msdfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 700aa2ae81..55a6850478 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -203,7 +203,8 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist } /* parse out the alternate paths */ - while(((alt_path[count] = strtok(NULL,",")) != NULL) && count Date: Wed, 14 Jun 2006 12:00:53 +0000 Subject: r16219: BUG 3836, 3837, 3004: compile warning fixes from Jason Mader. (This used to be commit 6c1f1c091f5e87bf9464fe8ad7eb2cb683819a62) --- source3/smbd/open.c | 2 -- source3/smbd/trans2.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 821feffd65..2e4091d937 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1107,7 +1107,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; uint16 mid = get_current_mid(); - BOOL delayed_for_oplocks = False; struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; NTSTATUS status; @@ -1148,7 +1147,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, see if this has timed out. */ request_time = pml->request_time; - delayed_for_oplocks = state->delayed_for_oplocks; /* Remove the deferred open entry under lock. */ lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 71ff79081d..86743f626e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2813,7 +2813,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * char *fullpathname; char *base_name; char *p; - char *lock_data = NULL; SMB_OFF_T pos = 0; BOOL bad_path = False; BOOL delete_pending = False; @@ -2823,6 +2822,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * TALLOC_CTX *data_ctx = NULL; struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ +#if defined(DEVELOPER) + char *lock_data = NULL; +#endif if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); -- cgit From a1e0a0e9286fbe90ca04cda9df38e72d8d18b0c1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Jun 2006 21:36:49 +0000 Subject: r16230: Fix Klocwork #861 and others. localtime and asctime can return NULL. Ensure we check all returns correctly. Jeremy. (This used to be commit 6c61dc8ed6d84f310ef391fb7700e93ef42c4afc) --- source3/smbd/lanman.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4d4d9d2259..7d1a2ade54 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2212,6 +2212,9 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch /* the client expects to get localtime, not GMT, in this bit (I think, this needs testing) */ t = localtime(&unixdate); + if (!t) { + return False; + } SIVAL(p,4,0); /* msecs ? */ SCVAL(p,8,t->tm_hour); -- cgit From f9147c4e408d316d194c4e367dfccbf433cb8ec9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Jun 2006 01:54:09 +0000 Subject: r16241: Fix Klocwork #106 and others like it. Make 2 important changes. pdb_get_methods() returning NULL is a *fatal* error. Don't try and cope with it just call smb_panic. This removes a *lot* of pointless "if (!pdb)" handling code. Secondly, ensure that if samu_init() fails we *always* back out of a function. That way we are never in a situation where the pdb_XXX() functions need to start with a "if (sampass)" test - this was just bad design, not defensive programming. Jeremy. (This used to be commit a0d368197d6ae6777b7c2c3c6e970ab8ae7ca2ae) --- source3/smbd/lanman.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7d1a2ade54..e4531d8ae9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2010,6 +2010,12 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para return False; } + if ( !(sampw = samu_new(mem_ctx)) ) { + DEBUG(0, ("samu_new() failed!\n")); + TALLOC_FREE(mem_ctx); + return False; + } + /* Lookup the user information; This should only be one of our accounts (not remote domains) */ @@ -2027,11 +2033,6 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para goto done; } - if ( !(sampw = samu_new(mem_ctx)) ) { - DEBUG(0, ("samu_new() failed!\n")); - goto done; - } - if ( !pdb_getsampwsid(sampw, &user_sid) ) { DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n", sid_string_static(&user_sid), UserName)); -- cgit From 580e9817a2f1201a383b1a0763074e169ef564cc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 15 Jun 2006 10:12:29 +0000 Subject: r16248: Fix Coverity ID 297 (This used to be commit e56e3c19e1244e2b7409d57a030ca8b7ec446932) --- source3/smbd/chgpasswd.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 011122ee57..cd847240dd 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -579,6 +579,11 @@ BOOL check_lanman_password(char *user, uchar * pass1, uint32 acct_ctrl; const uint8 *lanman_pw; BOOL ret; + + if ( !(sampass = samu_new(NULL)) ) { + DEBUG(0, ("samu_new() failed!\n")); + return False; + } become_root(); ret = pdb_getsampwnam(sampass, user); -- cgit From 9bcaf47c635ab92d7c171278180f33f6c72c6b57 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 01:30:42 +0000 Subject: r16275: Start fixing up gcc4 -O6 warnings on an x86_64 box. size_t != unsigned int in a format string. Jeremy. (This used to be commit 952547471f03bd2da1eda0247471b17aa1ff15de) --- source3/smbd/ipc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3250387909..e6dfc6506a 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -369,8 +369,8 @@ static NTSTATUS handle_trans(connection_struct *conn, int name_offset = 0; DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", - state->name,state->total_data,state->total_param, - state->setup_count)); + state->name,(unsigned int)state->total_data,(unsigned int)state->total_param, + (unsigned int)state->setup_count)); /* * WinCE wierdness.... @@ -481,7 +481,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, state->data = SMB_MALLOC(state->total_data); if (state->data == NULL) { DEBUG(0,("reply_trans: data malloc fail for %u " - "bytes !\n", state->total_data)); + "bytes !\n", (unsigned int)state->total_data)); TALLOC_FREE(state); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); @@ -501,7 +501,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, state->param = SMB_MALLOC(state->total_param); if (state->param == NULL) { DEBUG(0,("reply_trans: param malloc fail for %u " - "bytes !\n", state->total_param)); + "bytes !\n", (unsigned int)state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); END_PROFILE(SMBtrans); -- cgit From 17e1b8399631c61ffea8ed87996b49b06ed3903d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 01:32:19 +0000 Subject: r16277: Start fixing up gcc4 -O6 warnings on an x86_64 box. size_t != unsigned int in a format string. Jeremy. (This used to be commit 3a15fff21988b426a514ad28060eaf0ddc17ef6b) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5d19d496fd..17a4a30941 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2903,7 +2903,7 @@ int reply_nttrans(connection_struct *conn, * params and data. */ if ((state->data = SMB_MALLOC(state->total_data)) == NULL) { DEBUG(0,("reply_nttrans: data malloc fail for %u " - "bytes !\n", state->total_data)); + "bytes !\n", (unsigned int)state->total_data)); TALLOC_FREE(state); END_PROFILE(SMBnttrans); return(ERROR_DOS(ERRDOS,ERRnomem)); @@ -2922,7 +2922,7 @@ int reply_nttrans(connection_struct *conn, * params and data. */ if ((state->param = SMB_MALLOC(state->total_param)) == NULL) { DEBUG(0,("reply_nttrans: param malloc fail for %u " - "bytes !\n", state->total_param)); + "bytes !\n", (unsigned int)state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); END_PROFILE(SMBnttrans); -- cgit From 87967b90c44915a64cff6ea961f613ea6676c798 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 01:33:13 +0000 Subject: r16280: Start fixing up gcc4 -O6 warnings on an x86_64 box. size_t != unsigned int in a format string. Jeremy. (This used to be commit 45d5cad8c2438c032d9f11c62a50a04d0637bf6c) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 86743f626e..ef6cae14ba 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5286,7 +5286,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, state->data = SMB_MALLOC(state->total_data); if (state->data == NULL) { DEBUG(0,("reply_trans2: data malloc fail for %u " - "bytes !\n", state->total_data)); + "bytes !\n", (unsigned int)state->total_data)); TALLOC_FREE(state); END_PROFILE(SMBtrans2); return(ERROR_DOS(ERRDOS,ERRnomem)); @@ -5306,7 +5306,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, state->param = SMB_MALLOC(state->total_param); if (state->param == NULL) { DEBUG(0,("reply_trans: param malloc fail for %u " - "bytes !\n", state->total_param)); + "bytes !\n", (unsigned int)state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); END_PROFILE(SMBtrans2); -- cgit From 300acb99ad9fcd4a36998d4ee4d8349478deca59 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 01:47:02 +0000 Subject: r16284: Start fixing up gcc4 -O6 warnings on an x86_64 box. size_t != unsigned int in a format string. Jeremy. (This used to be commit face01ef01e1a3c96eae17c56cadf01020d4cb46) --- source3/smbd/notify_fam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index 3b6be77aca..b7f9a36332 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -371,7 +371,7 @@ fam_register_notify(connection_struct * conn, } if ((info = SMB_MALLOC_P(struct fam_req_info)) == NULL) { - DEBUG(0, ("malloc of %d bytes failed\n", sizeof(struct fam_req_info))); + DEBUG(0, ("malloc of %u bytes failed\n", (unsigned int)sizeof(struct fam_req_info))); return(NULL); } -- cgit From 4b6fef6b6a016aa35637f9f7ebfb6e60f0f24643 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 18:42:39 +0000 Subject: r16295: Fix gcc4 "warning: dereferencing type-punned pointer will break strict-aliasing rules" warning. Jeremy. (This used to be commit 7ac5aee88cae3400fb6400b3628544da2e474560) --- source3/smbd/nttrans.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 17a4a30941..142ff39245 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -914,7 +914,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", ****************************************************************************/ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count) { @@ -1078,7 +1078,7 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, ****************************************************************************/ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { @@ -1818,11 +1818,11 @@ int reply_ntrename(connection_struct *conn, ****************************************************************************/ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { - char *setup = *ppsetup; + uint16 *setup = *ppsetup; files_struct *fsp; uint32 flags; @@ -1830,7 +1830,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfunc); } - fsp = file_fsp(setup,4); + fsp = file_fsp((char *)setup,4); flags = IVAL(setup, 0); DEBUG(3,("call_nt_transact_notify_change\n")); @@ -1858,7 +1858,7 @@ name = %s\n", fsp->fsp_name )); ****************************************************************************/ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { @@ -1926,7 +1926,7 @@ static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) ****************************************************************************/ static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { @@ -2042,7 +2042,7 @@ security descriptor.\n")); ****************************************************************************/ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { @@ -2088,7 +2088,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb ****************************************************************************/ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { @@ -2113,7 +2113,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", function, fidnum, isFSctl, compfilter)); - fsp=file_fsp(*ppsetup, 4); + fsp=file_fsp((char *)*ppsetup, 4); /* this check is done in each implemented function case for now because I don't want to break anything... --metze FSP_BELONGS_CONN(fsp,conn);*/ @@ -2338,7 +2338,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou ****************************************************************************/ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { @@ -2594,7 +2594,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, ****************************************************************************/ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, uint32 setup_count, + uint16 **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count) { @@ -2724,7 +2724,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_create); outsize = call_nt_transact_create(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); @@ -2737,7 +2737,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_ioctl); outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_ioctl); @@ -2749,7 +2749,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_set_security_desc); outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_set_security_desc); @@ -2761,7 +2761,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_notify_change); outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_notify_change); @@ -2773,7 +2773,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_rename); outsize = call_nt_transact_rename(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_rename); @@ -2785,7 +2785,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_query_security_desc); outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_query_security_desc); @@ -2798,7 +2798,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_get_user_quota); outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_get_user_quota); @@ -2810,7 +2810,7 @@ static int handle_nttrans(connection_struct *conn, START_PROFILE_NESTED(NT_transact_set_user_quota); outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, size, bufsize, - (char **)&state->setup, state->setup_count, + &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); END_PROFILE_NESTED(NT_transact_set_user_quota); -- cgit From 17621ea080b7a3da71fcaa0782f8716e944dbc70 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 22:36:12 +0000 Subject: r16309: Fix Klocwork #1596. Check for NULL on talloc. Jeremy. (This used to be commit 34b6b6723b1c87e19b0a51ef785a614d86bd5cef) --- source3/smbd/trans2.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ef6cae14ba..27fd62be7f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -172,6 +172,11 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6; ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { + + if (!ea_namelist) { + return NULL; + } + if (fsp && fsp->fh->fd != -1) { sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size); } else { -- cgit From b85b18d7947fc2125a29b8be9878d66dfd1c79e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 22:40:07 +0000 Subject: r16311: Check for NULL return. Klocwork #998. Jeremy. (This used to be commit c430730f5a0dc00626b9b924e88adfb84cd48869) --- source3/smbd/nttrans.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 142ff39245..e397139d2e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1063,6 +1063,10 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, struct ea_list *tmp; struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); + if (!eal) { + return NULL; + } + DLIST_ADD_END(ea_list_head, eal, tmp); if (next_offset == 0) { break; -- cgit From 52d6b8339a76c78176aaadf8dc7ba12a8bfd9c38 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Jun 2006 23:04:13 +0000 Subject: r16317: Klocwork #300. Check for error return on malloc. Jeremy. (This used to be commit aa0d739834a286aeee88f76048dc347dd2852d09) --- source3/smbd/conn.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 5aa8901d59..d857611c35 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -117,6 +117,10 @@ find_again: oldsz, newsz)); nbmap = bitmap_allocate(newsz); + if (!nbmap) { + DEBUG(0,("ERROR! malloc fail.\n")); + return NULL; + } bitmap_copy(nbmap, bmap); bitmap_free(bmap); -- cgit From ce61fb21d948bd8e3c7733d542f8ecae1390cbfc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Jun 2006 02:38:28 +0000 Subject: r16397: Fix Klocwork #11767 and drasticly simplify the logic in smbd/process.c. All interested (Volker, Jerry, James etc). PLEASE REVIEW THIS CHANGE. The logic should be identical but *much* easier to follow and change (and shouldn't confuse Klockwork :-). Jeremy. (This used to be commit d357f8b33594472ffa78d0a112accccc2a8b1fe7) --- source3/smbd/message.c | 305 +++++++++++++++++++++++------------------------ source3/smbd/negprot.c | 1 + source3/smbd/nttrans.c | 1 + source3/smbd/process.c | 74 ++++++------ source3/smbd/reply.c | 7 ++ source3/smbd/sesssetup.c | 1 + 6 files changed, 198 insertions(+), 191 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index fd28df0d80..31dab45844 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -34,211 +34,210 @@ static fstring msgfrom; static fstring msgto; /**************************************************************************** -deliver the message + Deliver the message. ****************************************************************************/ + static void msg_deliver(void) { - pstring name; - int i; - int fd; - char *msg; - int len; - ssize_t sz; - - if (! (*lp_msg_command())) - { - DEBUG(1,("no messaging command specified\n")); - msgpos = 0; - return; - } - - /* put it in a temporary file */ - slprintf(name,sizeof(name)-1, "%s/msg.XXXXXX",tmpdir()); - fd = smb_mkstemp(name); - - if (fd == -1) { - DEBUG(1,("can't open message file %s\n",name)); - return; - } - - /* - * Incoming message is in DOS codepage format. Convert to UNIX. - */ + pstring name; + int i; + int fd; + char *msg; + int len; + ssize_t sz; + + if (! (*lp_msg_command())) { + DEBUG(1,("no messaging command specified\n")); + msgpos = 0; + return; + } + + /* put it in a temporary file */ + slprintf(name,sizeof(name)-1, "%s/msg.XXXXXX",tmpdir()); + fd = smb_mkstemp(name); + + if (fd == -1) { + DEBUG(1,("can't open message file %s\n",name)); + return; + } + + /* + * Incoming message is in DOS codepage format. Convert to UNIX. + */ - if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **)(void *)&msg, True)) < 0 || !msg) { - DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); - for (i = 0; i < msgpos;) { - if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { - i++; continue; - } - sz = write(fd, &msgbuf[i++], 1); - if ( sz != 1 ) { - DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); - } - } - } else { - for (i = 0; i < len;) { - if (msg[i] == '\r' && i < (len-1) && msg[i+1] == '\n') { - i++; continue; - } - sz = write(fd, &msg[i++],1); - if ( sz != 1 ) { - DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); - } - } - SAFE_FREE(msg); - } - close(fd); - - - /* run the command */ - if (*lp_msg_command()) - { - fstring alpha_msgfrom; - fstring alpha_msgto; - pstring s; - - pstrcpy(s,lp_msg_command()); - pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); - pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); - standard_sub_basic(current_user_info.smb_name, s, sizeof(s)); - pstring_sub(s,"%s",name); - smbrun(s,NULL); - } - - msgpos = 0; + if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **)(void *)&msg, True)) < 0 || !msg) { + DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); + for (i = 0; i < msgpos;) { + if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { + i++; + continue; + } + sz = write(fd, &msgbuf[i++], 1); + if ( sz != 1 ) { + DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); + } + } + } else { + for (i = 0; i < len;) { + if (msg[i] == '\r' && i < (len-1) && msg[i+1] == '\n') { + i++; + continue; + } + sz = write(fd, &msg[i++],1); + if ( sz != 1 ) { + DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); + } + } + SAFE_FREE(msg); + } + close(fd); + + /* run the command */ + if (*lp_msg_command()) { + fstring alpha_msgfrom; + fstring alpha_msgto; + pstring s; + + pstrcpy(s,lp_msg_command()); + pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); + pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); + standard_sub_basic(current_user_info.smb_name, s, sizeof(s)); + pstring_sub(s,"%s",name); + smbrun(s,NULL); + } + + msgpos = 0; } - - /**************************************************************************** - reply to a sends + Reply to a sends. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sends(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int len; - char *msg; - int outsize = 0; - char *p; + int len; + char *msg; + int outsize = 0; + char *p; - START_PROFILE(SMBsends); + START_PROFILE(SMBsends); - msgpos = 0; + msgpos = 0; - if (! (*lp_msg_command())) { - END_PROFILE(SMBsends); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); - } + if (! (*lp_msg_command())) { + END_PROFILE(SMBsends); + return(ERROR_DOS(ERRSRV,ERRmsgoff)); + } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p = smb_buf(inbuf)+1; + p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; - msg = p; + msg = p; - len = SVAL(msg,0); - len = MIN(len,sizeof(msgbuf)-msgpos); + len = SVAL(msg,0); + len = MIN(len,sizeof(msgbuf)-msgpos); - memset(msgbuf,'\0',sizeof(msgbuf)); + memset(msgbuf,'\0',sizeof(msgbuf)); - memcpy(&msgbuf[msgpos],msg+2,len); - msgpos += len; + memcpy(&msgbuf[msgpos],msg+2,len); + msgpos += len; - msg_deliver(); + msg_deliver(); - END_PROFILE(SMBsends); - return(outsize); + END_PROFILE(SMBsends); + return(outsize); } - /**************************************************************************** - reply to a sendstrt + Reply to a sendstrt. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sendstrt(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = 0; - char *p; + int outsize = 0; + char *p; - START_PROFILE(SMBsendstrt); + START_PROFILE(SMBsendstrt); - if (! (*lp_msg_command())) { - END_PROFILE(SMBsendstrt); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); - } + if (! (*lp_msg_command())) { + END_PROFILE(SMBsendstrt); + return(ERROR_DOS(ERRSRV,ERRmsgoff)); + } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(outbuf,1,0,True); - memset(msgbuf,'\0',sizeof(msgbuf)); - msgpos = 0; + memset(msgbuf,'\0',sizeof(msgbuf)); + msgpos = 0; - p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p = smb_buf(inbuf)+1; + p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; - DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); + DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); - END_PROFILE(SMBsendstrt); - return(outsize); + END_PROFILE(SMBsendstrt); + return(outsize); } - /**************************************************************************** - reply to a sendtxt + Reply to a sendtxt. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sendtxt(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_sendtxt(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int len; - int outsize = 0; - char *msg; - START_PROFILE(SMBsendtxt); + int len; + int outsize = 0; + char *msg; + START_PROFILE(SMBsendtxt); - if (! (*lp_msg_command())) { - END_PROFILE(SMBsendtxt); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); - } + if (! (*lp_msg_command())) { + END_PROFILE(SMBsendtxt); + return(ERROR_DOS(ERRSRV,ERRmsgoff)); + } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - msg = smb_buf(inbuf) + 1; + msg = smb_buf(inbuf) + 1; - len = SVAL(msg,0); - len = MIN(len,sizeof(msgbuf)-msgpos); + len = SVAL(msg,0); + len = MIN(len,sizeof(msgbuf)-msgpos); - memcpy(&msgbuf[msgpos],msg+2,len); - msgpos += len; + memcpy(&msgbuf[msgpos],msg+2,len); + msgpos += len; - DEBUG( 3, ( "SMBsendtxt\n" ) ); + DEBUG( 3, ( "SMBsendtxt\n" ) ); - END_PROFILE(SMBsendtxt); - return(outsize); + END_PROFILE(SMBsendtxt); + return(outsize); } - /**************************************************************************** - reply to a sendend + Reply to a sendend. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sendend(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + +int reply_sendend(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = 0; - START_PROFILE(SMBsendend); + int outsize = 0; + START_PROFILE(SMBsendend); - if (! (*lp_msg_command())) { - END_PROFILE(SMBsendend); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); - } + if (! (*lp_msg_command())) { + END_PROFILE(SMBsendend); + return(ERROR_DOS(ERRSRV,ERRmsgoff)); + } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(outbuf,0,0,True); - DEBUG(3,("SMBsendend\n")); + DEBUG(3,("SMBsendend\n")); - msg_deliver(); + msg_deliver(); - END_PROFILE(SMBsendend); - return(outsize); + END_PROFILE(SMBsendend); + return(outsize); } diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 5d2ed6a10d..3347008cdf 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -456,6 +456,7 @@ static const struct { /**************************************************************************** Reply to a negprot. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_negprot(connection_struct *conn, diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e397139d2e..aa6f79e165 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1545,6 +1545,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /**************************************************************************** Reply to a NT CANCEL request. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_ntcancel(connection_struct *conn, diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 440d0ac0a5..b3ce49360d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -567,10 +567,10 @@ are used by some brain-dead clients when printing, and I don't want to force write permissions on print services. */ #define AS_USER (1<<0) -#define NEED_WRITE (1<<1) +#define NEED_WRITE (1<<1) /* Must be paired with AS_USER */ #define TIME_INIT (1<<2) -#define CAN_IPC (1<<3) -#define AS_GUEST (1<<5) +#define CAN_IPC (1<<3) /* Must be paired with AS_USER */ +#define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */ #define DO_CHDIR (1<<6) /* @@ -932,48 +932,46 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize user_struct *vuser = NULL; last_session_tag = session_tag; - if(session_tag != UID_FIELD_INVALID) + if(session_tag != UID_FIELD_INVALID) { vuser = get_valid_user_struct(session_tag); - if(vuser != NULL) - set_current_user_info(&vuser->user); - } - - /* does this protocol need to be run as root? */ - if (!(flags & AS_USER)) - change_to_root_user(); - - /* does this protocol need a valid tree connection? */ - if ((flags & AS_USER) && !conn) { - /* Amazingly, the error code depends on the command (from Samba4). */ - if (type == SMBntcreateX) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); - } else { - return ERROR_DOS(ERRSRV, ERRinvnid); + if (vuser) { + set_current_user_info(&vuser->user); + } } } + /* Does this call need to be run as the connected user? */ + if (flags & AS_USER) { + + /* Does this call need a valid tree connection? */ + if (!conn) { + /* Amazingly, the error code depends on the command (from Samba4). */ + if (type == SMBntcreateX) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } else { + return ERROR_DOS(ERRSRV, ERRinvnid); + } + } - /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !change_to_user(conn,session_tag)) { - if (flags & AS_GUEST) - flags &= ~AS_USER; - else + if (!change_to_user(conn,session_tag)) { return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid)); - } + } - /* this code is to work around a bug is MS client 3 without - introducing a security hole - it needs to be able to do - print queue checks as guest if it isn't logged in properly */ - if (flags & AS_USER) - flags &= ~AS_GUEST; + /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ - /* does it need write permission? */ - if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) - return(ERROR_DOS(ERRSRV,ERRaccess)); + /* Does it need write permission? */ + if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { + return(ERROR_DOS(ERRSRV,ERRaccess)); + } - /* ipc services are limited */ - if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) - return(ERROR_DOS(ERRSRV,ERRaccess)); + /* IPC services are limited */ + if (IS_IPC(conn) && !(flags & CAN_IPC)) { + return(ERROR_DOS(ERRSRV,ERRaccess)); + } + } else { + /* This call needs to be run as root */ + change_to_root_user(); + } /* load service specific parameters */ if (conn) { @@ -985,8 +983,9 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* does this protocol need to be run as guest? */ if ((flags & AS_GUEST) && (!change_to_guest() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { return(ERROR_DOS(ERRSRV,ERRaccess)); + } current_inbuf = inbuf; /* In case we need to defer this message in open... */ outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); @@ -997,7 +996,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(outsize); } - /**************************************************************************** Construct a reply to the incoming packet. ****************************************************************************/ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d333ebf32e..e68e8662d7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -547,6 +547,7 @@ int reply_special(char *inbuf,char *outbuf) /**************************************************************************** Reply to a tcon. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_tcon(connection_struct *conn, @@ -605,6 +606,7 @@ int reply_tcon(connection_struct *conn, /**************************************************************************** Reply to a tcon and X. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) @@ -738,6 +740,7 @@ int reply_unknown(char *inbuf,char *outbuf) /**************************************************************************** Reply to an ioctl. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_ioctl(connection_struct *conn, @@ -1591,6 +1594,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /**************************************************************************** Reply to a SMBulogoffX. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) @@ -3236,6 +3240,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int /**************************************************************************** Reply to a exit. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_exit(connection_struct *conn, @@ -3511,6 +3516,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, /**************************************************************************** Reply to a tdis. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_tdis(connection_struct *conn, @@ -3538,6 +3544,7 @@ int reply_tdis(connection_struct *conn, /**************************************************************************** Reply to a echo. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ int reply_echo(connection_struct *conn, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 46acb20bda..fb579707ca 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -635,6 +635,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, /**************************************************************************** Reply to a session setup command. + conn POINTER CAN BE NULL HERE ! ****************************************************************************/ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, -- cgit From 54ea3c23e3bfd25008198e85fdcc1f48b0325eab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Jun 2006 02:31:12 +0000 Subject: r16435: Add in the uid info that Jerry needs into the share_mode struct. Allows us to know the unix uid of the opener of the file/directory. Needed for info level queries on open files. Jeremy. (This used to be commit d929323d6f513902381369d77bcd7b714346d713) --- source3/smbd/open.c | 4 ++-- source3/smbd/oplock.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2e4091d937..832a8df755 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1685,7 +1685,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; } } - set_share_mode(lck, fsp, 0, fsp->oplock_type); + set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type); if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { @@ -1991,7 +1991,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - set_share_mode(lck, fsp, 0, NO_OPLOCK); + set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1f731e1729..e4f5c434b0 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -830,6 +830,7 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e) SDEV_T_VAL(msg,28,e->dev); SINO_T_VAL(msg,36,e->inode); SIVAL(msg,44,e->share_file_id); + SIVAL(msg,48,e->uid); } /**************************************************************************** @@ -849,6 +850,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) e->dev = DEV_T_VAL(msg,28); e->inode = INO_T_VAL(msg,36); e->share_file_id = (unsigned long)IVAL(msg,44); + e->uid = (uint32)IVAL(msg,48); } /**************************************************************************** -- cgit From a24c4049670e6837705ac7013c7d2da596a95f6a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Jun 2006 23:36:03 +0000 Subject: r16537: Fix for bug #3858, all files in a directory not being deleted when hide unreadable set to true. Here's the scoop. This one is really interesting. The pattern of deleting a directory is to do a findfirst to get the first part of the list, then for each name returned it does a open/set delete on close/close -> thus deleting the file. Then it does a findnext with the last file name THAT IT JUST DELETED ! Now we can handle this in the findnext in the case where hide unreadable is set to false as we look back in our cache of names and just seek to the right point. The bug is actually fixed in the first hunk of this patch - the one that removes the is_visible_file() check after SearchDir returns false. We don't actually need it and in this case it's causing the delete to be aborted because it can't find the name (doh ! it was just deleted). We don't need it as SearchDir is only ever called from findnext, and findnext should only ever be returning names we gave it. The rest of the patch are the debugs I used to find the problem but they're generically useful. Phew - that one took a while to track down..... Jerry, please merge for 3.0.23 final. Jeremy. (This used to be commit cd048cb775f0a8525fc19aa463db07c477521f5b) --- source3/smbd/dir.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 27a4182c22..5ba9e1ed57 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -636,12 +636,7 @@ BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S return False; } - if (SearchDir(dptr->dir_hnd, name, poffset)) { - if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { - return True; - } - } - return False; + return SearchDir(dptr->dir_hnd, name, poffset); } /**************************************************************************** @@ -854,6 +849,8 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S /* If we can't stat it does not show it */ if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) { + DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n", + name, strerror(errno) )); return False; } @@ -992,6 +989,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * /* If it's a vetoed file, pretend it doesn't even exist */ if (use_veto && IS_VETO_PATH(conn, name)) { + DEBUG(10,("is_visible_file: file %s is vetoed.\n", name )); return False; } @@ -1003,16 +1001,19 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * } /* Honour _hide unreadable_ option */ if (hide_unreadable && !user_can_read_file(conn, entry, pst)) { + DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry )); SAFE_FREE(entry); return False; } /* Honour _hide unwriteable_ option */ if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) { + DEBUG(10,("is_visible_file: file %s is unwritable.\n", entry )); SAFE_FREE(entry); return False; } /* Honour _hide_special_ option */ if (hide_special && file_is_special(conn, entry, pst)) { + DEBUG(10,("is_visible_file: file %s is special.\n", entry )); SAFE_FREE(entry); return False; } -- cgit From d1014c1cdfce116741ddd6eccd65b69530ce0b84 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Jun 2006 00:50:14 +0000 Subject: r16582: Fix Klocwork #1997 and all generic class of problems where we don't correctly check the return from memdup. Jeremy. (This used to be commit ce14daf51c7ee2f9c68c77f7f4674e6f0e35c9ca) --- source3/smbd/sec_ctx.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index a30123bfa7..51d1d6cc0a 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -252,13 +252,29 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN ctx_p->ut.ngroups = ngroups; SAFE_FREE(ctx_p->ut.groups); - if (token && (token == ctx_p->token)) + if (token && (token == ctx_p->token)) { smb_panic("DUPLICATE_TOKEN"); + } TALLOC_FREE(ctx_p->token); - ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups); - ctx_p->token = dup_nt_token(NULL, token); + if (ngroups) { + ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups); + if (!ctx_p->ut.groups) { + smb_panic("memdup failed"); + } + } else { + ctx_p->ut.groups = NULL; + } + + if (token) { + ctx_p->token = dup_nt_token(NULL, token); + if (!ctx_p->token) { + smb_panic("dup_nt_token failed"); + } + } else { + ctx_p->token = NULL; + } become_id(uid, gid); -- cgit From 8beeeffd6ec2a31ab6e28ae38c92c92d5be3a8c1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Jun 2006 01:25:29 +0000 Subject: r16591: Belt and braces approach to shut Klocwork up - bug #2001. Jeremy. (This used to be commit d5c1028498de0346b7a35cc132b8081e04e639cc) --- source3/smbd/map_username.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index 1f523cc89f..7cbde3c59e 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -82,7 +82,7 @@ BOOL map_username(fstring user) /* should be either no lines or a single line with the mapped username */ - if (numlines) { + if (numlines && qlines) { DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] )); fstrcpy( user, qlines[0] ); } -- cgit From 3e626e61078500738009a99c0dea8a46551bd315 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Jun 2006 05:00:09 +0000 Subject: r16616: Klocwork #2025. Stop null deref. I actually don't think this can happen in real life but the code is too complicated to be sure.... Jerry please merge this for 3.0.23. Jeremy. (This used to be commit 1e5042d4c0d1a0d0a5cfbcb0d47815e1510ee52a) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 40cb6698a0..6e403dba92 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1483,7 +1483,7 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); * Only add to the file ACL if not inherit only. */ - if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { + if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { DLIST_ADD_END(file_ace, current_ace, tmp_ace); /* -- cgit From 192062c4a60d107cd762183b937249bffd9edde7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Jul 2006 21:07:46 +0000 Subject: r16789: Fix bug #3909, when using ea's getting a directory tries to read ea's from an msdfs link. Stop it from doing that. Jerry please merge to 3.0.23. Jeremy. (This used to be commit 95e5ace6b4f348a3244b6a3ea0fd8badf55271f5) --- source3/smbd/dosmode.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/trans2.c | 11 ++++++++--- 2 files changed, 59 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 583b3f19e7..61145fde2f 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -315,6 +315,57 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ return True; } +/**************************************************************************** + Change a unix mode to a dos mode for an ms dfs link. +****************************************************************************/ + +uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) +{ + uint32 result = 0; + + DEBUG(8,("dos_mode_msdfs: %s\n", path)); + + if (!VALID_STAT(*sbuf)) { + return 0; + } + + /* First do any modifications that depend on the path name. */ + /* hide files with a name starting with a . */ + if (lp_hide_dot_files(SNUM(conn))) { + const char *p = strrchr_m(path,'/'); + if (p) { + p++; + } else { + p = path; + } + + if (p[0] == '.' && p[1] != '.' && p[1] != 0) { + result |= aHIDDEN; + } + } + + result |= dos_mode_from_sbuf(conn, path, sbuf); + + /* Optimization : Only call is_hidden_path if it's not already + hidden. */ + if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { + result |= aHIDDEN; + } + + DEBUG(8,("dos_mode_msdfs returning ")); + + if (result & aHIDDEN) DEBUG(8, ("h")); + if (result & aRONLY ) DEBUG(8, ("r")); + if (result & aSYSTEM) DEBUG(8, ("s")); + if (result & aDIR ) DEBUG(8, ("d")); + if (result & aARCH ) DEBUG(8, ("a")); + if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); + + DEBUG(8,("\n")); + + return(result); +} + /**************************************************************************** Change a unix mode to a dos mode. ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 27fd62be7f..9030737b1b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1091,6 +1091,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, while (!found) { BOOL got_match; + BOOL ms_dfs_link = False; + /* Needed if we run out of space */ long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr); dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf); @@ -1154,8 +1156,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - is_msdfs_link(NULL,conn, pathreal, NULL, NULL, - &sbuf)) { + ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) { DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal)); sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; @@ -1168,7 +1169,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } } - mode = dos_mode(conn,pathreal,&sbuf); + if (ms_dfs_link) { + mode = dos_mode_msdfs(conn,pathreal,&sbuf); + } else { + mode = dos_mode(conn,pathreal,&sbuf); + } if (!dir_check_ftype(conn,mode,dirtype)) { DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); -- cgit From 3dc4d79a446b9a38bea8faed95fbb26b054c3a10 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Jul 2006 13:49:17 +0000 Subject: r16797: Add msdfs proxy junctions in the netdfs rpc enumeration. Guenther (This used to be commit 6bf350895a648ef9b824c94b894e8d7a8989eb97) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 55a6850478..b22b5674d6 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1058,6 +1058,7 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, ref->ttl = REFERRAL_TTL; if (*lp_msdfs_proxy(snum) != '\0') { pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); + cnt++; goto out; } -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/smbd/blocking.c | 40 +- source3/smbd/change_trust_pw.c | 4 +- source3/smbd/conn.c | 8 +- source3/smbd/connection.c | 169 +++++- source3/smbd/dir.c | 21 +- source3/smbd/dosmode.c | 7 +- source3/smbd/error.c | 54 +- source3/smbd/fake_file.c | 23 +- source3/smbd/filename.c | 22 +- source3/smbd/files.c | 70 ++- source3/smbd/lanman.c | 45 +- source3/smbd/mangle.c | 28 +- source3/smbd/mangle_hash.c | 18 +- source3/smbd/mangle_hash2.c | 44 +- source3/smbd/mangle_map.c | 4 +- source3/smbd/message.c | 3 +- source3/smbd/msdfs.c | 8 +- source3/smbd/nttrans.c | 98 ++-- source3/smbd/open.c | 229 +++++---- source3/smbd/password.c | 19 +- source3/smbd/pipes.c | 17 + source3/smbd/posix_acls.c | 12 +- source3/smbd/process.c | 23 +- source3/smbd/reply.c | 172 ++++--- source3/smbd/server.c | 6 - source3/smbd/service.c | 63 ++- source3/smbd/session.c | 45 +- source3/smbd/share_access.c | 5 +- source3/smbd/statcache.c | 8 +- source3/smbd/statvfs.c | 4 +- source3/smbd/trans2.c | 83 ++- source3/smbd/uid.c | 4 +- source3/smbd/vfs-wrap.c | 1104 ---------------------------------------- source3/smbd/vfs.c | 217 +++----- 34 files changed, 869 insertions(+), 1808 deletions(-) delete mode 100644 source3/smbd/vfs-wrap.c (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index a8db498ef5..04ab01eb66 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -34,7 +34,7 @@ typedef struct _blocking_lock_record { int lock_num; SMB_BIG_UINT offset; SMB_BIG_UINT count; - uint16 lock_pid; + uint32 lock_pid; enum brl_flavour lock_flav; enum brl_type lock_type; char *inbuf; @@ -74,7 +74,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, files_struct *fsp, int lock_timeout, int lock_num, - uint16 lock_pid, + uint32 lock_pid, enum brl_type lock_type, enum brl_flavour lock_flav, SMB_BIG_UINT offset, SMB_BIG_UINT count) @@ -121,7 +121,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, memcpy(blr->inbuf, inbuf, length); blr->length = length; - br_lck = brl_get_locks(blr->fsp); + br_lck = brl_get_locks(NULL, blr->fsp); if (!br_lck) { free_blocking_lock_record(blr); return False; @@ -136,7 +136,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, PENDING_LOCK, blr->lock_flav, &my_lock_ctx); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -236,7 +236,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) files_struct *fsp = blr->fsp; uint16 num_ulocks = SVAL(inbuf,smb_vwv6); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; - uint16 lock_pid; + uint32 lock_pid; unsigned char locktype = CVAL(inbuf,smb_vwv3); BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; @@ -344,7 +344,7 @@ static BOOL process_lockread(blocking_lock_record *blr) data = smb_buf(outbuf) + 3; status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, @@ -417,7 +417,7 @@ static BOOL process_lock(blocking_lock_record *blr) errno = 0; status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, @@ -471,7 +471,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; - uint16 lock_pid; + uint32 lock_pid; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; BOOL my_lock_ctx = False; @@ -625,7 +625,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) for(blr = blocking_lock_queue; blr; blr = next) { next = blr->next; if(blr->fsp->fnum == fsp->fnum) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ @@ -637,7 +637,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } @@ -658,7 +658,7 @@ void remove_pending_lock_requests_by_mid(int mid) next = blr->next; if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ @@ -670,7 +670,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -754,7 +754,7 @@ void process_blocking_lock_queue(time_t t) fsp->fnum, fsp->fsp_name )); if((blr->expire_time != -1) && (blr->expire_time <= t)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* * Lock expired - throw away all previously @@ -771,7 +771,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -780,7 +780,7 @@ void process_blocking_lock_queue(time_t t) } if(!change_to_user(conn,vuid)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* * Remove the entry and return an error to the client. @@ -793,7 +793,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", @@ -804,7 +804,7 @@ void process_blocking_lock_queue(time_t t) } if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* * Remove the entry and return an error to the client. @@ -817,7 +817,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); @@ -834,7 +834,7 @@ void process_blocking_lock_queue(time_t t) */ if(blocking_lock_record_process(blr)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { brl_remove_pending_lock(br_lck, @@ -843,7 +843,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } free_blocking_lock_record(blr); diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 738d12151d..31f03cc7fa 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -79,17 +79,19 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", dc_name, nt_errstr(nt_status))); cli_shutdown(cli); + cli = NULL; goto failed; } nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain); cli_shutdown(cli); + cli = NULL; failed: if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", - timestring(False), domain)); + current_timestring(False), domain)); } else DEBUG(5,("change_trust_account_password: sucess!\n")); diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index d857611c35..52182f3129 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -57,7 +57,7 @@ BOOL conn_snum_used(int snum) { connection_struct *conn; for (conn=Connections;conn;conn=conn->next) { - if (conn->service == snum) { + if (conn->params->service == snum) { return(True); } } @@ -136,8 +136,10 @@ find_again: return NULL; } - if ((conn=TALLOC_ZERO_P(mem_ctx, connection_struct))==NULL) { + if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) || + !(conn->params = TALLOC_P(mem_ctx, struct share_params))) { DEBUG(0,("talloc_zero() failed!\n")); + TALLOC_FREE(mem_ctx); return NULL; } conn->mem_ctx = mem_ctx; @@ -314,7 +316,7 @@ void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len) for (conn=Connections;conn;conn=next) { next=conn->next; - if (strequal(lp_servicename(conn->service), sharename)) { + if (strequal(lp_servicename(SNUM(conn)), sharename)) { DEBUG(1,("Forcing close of share %s cnum=%d\n", sharename, conn->cnum)); close_cnum(conn, (uint16)-1); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 07d3181144..0442a9441a 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -83,7 +83,7 @@ BOOL yield_connection(connection_struct *conn, const char *name) struct count_stat { pid_t mypid; int curr_connections; - char *name; + const char *name; BOOL Clear; }; @@ -124,43 +124,55 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u Claim an entry in the connections database. ****************************************************************************/ -BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags) +int count_current_connections( const char *sharename, BOOL clear ) { - struct connections_key key; - struct connections_data crec; - TDB_DATA kbuf, dbuf; - - if (!tdb) - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644); + struct count_stat cs; - if (!tdb) - return False; + cs.mypid = sys_getpid(); + cs.curr_connections = 0; + cs.name = sharename; + cs.Clear = clear; /* - * Enforce the max connections parameter. + * This has a race condition, but locking the chain before hand is worse + * as it leads to deadlock. */ - if (max_connections > 0) { - struct count_stat cs; + if (tdb_traverse(tdb, count_fn, &cs) == -1) { + DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", + tdb_errorstr(tdb) )); + return False; + } + + return cs.curr_connections; +} - cs.mypid = sys_getpid(); - cs.curr_connections = 0; - cs.name = lp_servicename(SNUM(conn)); - cs.Clear = Clear; +/**************************************************************************** + Claim an entry in the connections database. +****************************************************************************/ - /* - * This has a race condition, but locking the chain before hand is worse - * as it leads to deadlock. - */ +BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags) +{ + struct connections_key key; + struct connections_data crec; + TDB_DATA kbuf, dbuf; - if (tdb_traverse(tdb, count_fn, &cs) == -1) { - DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", - tdb_errorstr(tdb) )); + if (!tdb) { + if ( (tdb =conn_tdb_ctx()) == NULL ) { return False; } + } + + /* + * Enforce the max connections parameter. + */ - if (cs.curr_connections >= max_connections) { + if (max_connections > 0) { + int curr_connections; + + curr_connections = count_current_connections( lp_servicename(SNUM(conn)), True ); + + if (curr_connections >= max_connections) { DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n", max_connections, name )); return False; @@ -241,3 +253,108 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) SAFE_FREE(dbuf.dptr); return True; } + +/********************************************************************* +*********************************************************************/ + +static TDB_DATA* make_pipe_rec_key( struct pipe_open_rec *prec ) +{ + TDB_DATA *kbuf = NULL; + fstring key_string; + + if ( !prec ) + return NULL; + + if ( (kbuf = TALLOC_P(prec, TDB_DATA)) == NULL ) { + return NULL; + } + + snprintf( key_string, sizeof(key_string), "%s/%d/%d", + prec->name, procid_to_pid(&prec->pid), prec->pnum ); + + if ( (kbuf->dptr = talloc_strdup(prec, key_string)) == NULL ) + return NULL; + + kbuf->dsize = strlen(key_string)+1; + + return kbuf; +} + +/********************************************************************* +*********************************************************************/ + +static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p ) +{ + prec->pid = pid_to_procid(sys_getpid()); + prec->pnum = p->pnum; + prec->uid = geteuid(); + fstrcpy( prec->name, p->name ); + + return; +} + +/********************************************************************* +*********************************************************************/ + +BOOL store_pipe_opendb( smb_np_struct *p ) +{ + struct pipe_open_rec *prec; + TDB_DATA *key; + TDB_DATA data; + TDB_CONTEXT *pipe_tdb; + BOOL ret = False; + + if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { + DEBUG(0,("store_pipe_opendb: talloc failed!\n")); + return False; + } + + fill_pipe_open_rec( prec, p ); + if ( (key = make_pipe_rec_key( prec )) == NULL ) { + goto done; + } + + data.dptr = (char*)prec; + data.dsize = sizeof(struct pipe_open_rec); + + if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) { + goto done; + } + + ret = (tdb_store( pipe_tdb, *key, data, TDB_REPLACE ) != -1); + +done: + TALLOC_FREE( prec ); + return ret; +} + +/********************************************************************* +*********************************************************************/ + +BOOL delete_pipe_opendb( smb_np_struct *p ) +{ + struct pipe_open_rec *prec; + TDB_DATA *key; + TDB_CONTEXT *pipe_tdb; + BOOL ret = False; + + if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { + DEBUG(0,("store_pipe_opendb: talloc failed!\n")); + return False; + } + + fill_pipe_open_rec( prec, p ); + if ( (key = make_pipe_rec_key( prec )) == NULL ) { + goto done; + } + + if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) { + goto done; + } + + ret = (tdb_delete( pipe_tdb, *key ) != -1 ); + +done: + TALLOC_FREE( prec ); + return ret; +} diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5ba9e1ed57..96e0923dbd 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -741,7 +741,7 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask) { - mangle_map(filename,True,False,SNUM(conn)); + mangle_map(filename,True,False,conn->params); return mask_match_search(filename,mask,False); } @@ -787,8 +787,9 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { - if (!mangle_is_8_3(filename, False, SNUM(conn))) - mangle_map(filename,True,False,SNUM(conn)); + if (!mangle_is_8_3(filename, False, conn->params)) + mangle_map(filename,True,False, + conn->params); pstrcpy(fname,filename); *path = 0; @@ -857,17 +858,17 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S /* Pseudo-open the file (note - no fd's created). */ if(S_ISDIR(pst->st_mode)) { - fsp = open_directory(conn, name, pst, + status = open_directory(conn, name, pst, READ_CONTROL_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, /* no create options. */ - NULL); + NULL, &fsp); } else { - fsp = open_file_stat(conn, name, pst); + status = open_file_stat(conn, name, pst, &fsp); } - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { return False; } @@ -920,17 +921,17 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ if(S_ISDIR(pst->st_mode)) { return True; } else { - fsp = open_file_ntcreate(conn, name, pst, + status = open_file_ntcreate(conn, name, pst, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - &info); + &info, &fsp); } - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { return False; } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 61145fde2f..260a8dadbd 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -300,8 +300,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ * are not violating security in doing the setxattr. */ - fsp = open_file_fchmod(conn,path,sbuf); - if (!fsp) + if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp))) return ret; become_root(); if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) { @@ -518,8 +517,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, * holding. We need to review this.... may need to * break batch oplocks open by others. JRA. */ - files_struct *fsp = open_file_fchmod(conn,fname,st); - if (!fsp) + files_struct *fsp; + if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp))) return -1; become_root(); ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); diff --git a/source3/smbd/error.c b/source3/smbd/error.c index fa236f0de0..409781eaa9 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -24,40 +24,6 @@ extern struct unix_error_map unix_dos_nt_errmap[]; extern uint32 global_client_caps; -/* these can be set by some functions to override the error codes */ -static int override_ERR_class; -static uint32 override_ERR_code; -static NTSTATUS override_ERR_ntstatus; - -/**************************************************************************** - Setting eclass and ecode only and status to NT_STATUS_INVALID forces DOS errors. - Setting status only and eclass and ecode to -1 forces NT errors. -****************************************************************************/ - -void set_saved_error_triple(int eclass, int ecode, NTSTATUS status) -{ - override_ERR_class = eclass; - override_ERR_code = ecode; - override_ERR_ntstatus = status; -} - -void set_saved_ntstatus(NTSTATUS status) -{ - uint8 tmp_eclass; /* Hmmm. override_ERR_class is not uint8... */ - override_ERR_ntstatus = status; - ntstatus_to_dos(status, &tmp_eclass, &override_ERR_code); - override_ERR_class = tmp_eclass; - -} - -/**************************************************************************** - Return the current settings of the error triple. Return True if any are set. -****************************************************************************/ - -NTSTATUS get_saved_ntstatus(void) -{ - return override_ERR_ntstatus; -} /**************************************************************************** Create an error packet from a cached error. @@ -103,6 +69,10 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s return error_packet(outbuf,eclass,ecode,ntstatus,line,file); } +BOOL use_nt_status(void) +{ + return lp_nt_status_support() && (global_client_caps & CAP_STATUS32); +} /**************************************************************************** Create an error packet. Normally called using the ERROR() macro. @@ -117,18 +87,9 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in BOOL force_nt_status = False; BOOL force_dos_status = False; - if (override_ERR_class != SMB_SUCCESS || !NT_STATUS_IS_OK(override_ERR_ntstatus)) { - eclass = override_ERR_class; - ecode = override_ERR_code; - ntstatus = override_ERR_ntstatus; - override_ERR_class = SMB_SUCCESS; - override_ERR_code = 0; - override_ERR_ntstatus = NT_STATUS_OK; - } - if (eclass == (uint8)-1) { force_nt_status = True; - } else if (NT_STATUS_IS_INVALID(ntstatus)) { + } else if (NT_STATUS_IS_DOS(ntstatus)) { force_dos_status = True; } @@ -146,7 +107,10 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in nt_errstr(ntstatus))); } else { /* We're returning a DOS error only. */ - if (eclass == 0 && NT_STATUS_V(ntstatus)) { + if (NT_STATUS_IS_DOS(ntstatus)) { + eclass = NT_STATUS_DOS_CLASS(ntstatus); + ecode = NT_STATUS_DOS_CODE(ntstatus); + } else if (eclass == 0 && NT_STATUS_V(ntstatus)) { ntstatus_to_dos(ntstatus, &eclass, &ecode); } diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index b4f1f02b72..7c5eeae5c7 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -101,24 +101,26 @@ enum FAKE_FILE_TYPE is_fake_file(const char *fname) Open a fake quota file with a share mode. ****************************************************************************/ -files_struct *open_fake_file(connection_struct *conn, +NTSTATUS open_fake_file(connection_struct *conn, enum FAKE_FILE_TYPE fake_file_type, const char *fname, - uint32 access_mask) + uint32 access_mask, + files_struct **result) { files_struct *fsp = NULL; + NTSTATUS status; /* access check */ if (current_user.ut.uid != 0) { DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n", lp_servicename(SNUM(conn)),fname,conn->user)); - errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; + } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n", @@ -128,7 +130,7 @@ files_struct *open_fake_file(connection_struct *conn, fsp->fh->fd = -1; fsp->vuid = current_user.vuid; fsp->fh->pos = -1; - fsp->can_lock = True; /* Should this be true ? */ + fsp->can_lock = False; /* Should this be true ? - No, JRA */ fsp->access_mask = access_mask; string_set(&fsp->fsp_name,fname); @@ -136,11 +138,12 @@ files_struct *open_fake_file(connection_struct *conn, if (fsp->fake_file_handle==NULL) { file_free(fsp); - return NULL; + return NT_STATUS_NO_MEMORY; } conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 6c0f8b7758..1ea5228e91 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -46,12 +46,13 @@ static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitiv Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(const char *name1, const char *name2, int snum) +static BOOL mangled_equal(const char *name1, const char *name2, + const struct share_params *p) { pstring tmpname; pstrcpy(tmpname, name2); - mangle_map(tmpname, True, False, snum); + mangle_map(tmpname, True, False, p); return strequal(name1, tmpname); } @@ -189,7 +190,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (conn->case_sensitive && !mangle_is_mangled(name, SNUM(conn)) && !*lp_mangled_map(SNUM(conn))) + if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) && + !*lp_mangled_map(conn->params)) return(False); name_has_wildcard = ms_has_wild(start); @@ -199,7 +201,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * just a component. JRA. */ - if (mangle_is_mangled(start, SNUM(conn))) + if (mangle_is_mangled(start, conn->params)) component_was_mangled = True; /* @@ -318,7 +320,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * purposes. Fix inspired by Thomas Neumann . */ if (!conn->case_preserve || - (mangle_is_8_3(start, False, SNUM(conn)) && + (mangle_is_8_3(start, False, conn->params) && !conn->short_case_preserve)) { strnorm(start, lp_defaultcase(SNUM(conn))); } @@ -328,8 +330,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * base of the filename. */ - if (mangle_is_mangled(start, SNUM(conn))) { - mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), SNUM(conn)); + if (mangle_is_mangled(start, conn->params)) { + mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params); } DEBUG(5,("New file %s\n",start)); @@ -444,7 +446,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name BOOL mangled; long curpos; - mangled = mangle_is_mangled(name, SNUM(conn)); + mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ if (*path == 0) @@ -466,7 +468,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name */ if (mangled && !conn->case_sensitive) { - mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); + mangled = !mangle_check_cache( name, maxlength, conn->params); } /* open the directory */ @@ -495,7 +497,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name * against unmangled name. */ - if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) { + if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e020d8e13a..7069818dee 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -59,7 +59,7 @@ static unsigned long get_gen_count(void) Find first available file slot. ****************************************************************************/ -files_struct *file_new(connection_struct *conn) +NTSTATUS file_new(connection_struct *conn, files_struct **result) { int i; static int first_file; @@ -82,14 +82,12 @@ files_struct *file_new(connection_struct *conn) /* TODO: We have to unconditionally return a DOS error here, * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with * NTSTATUS negotiated */ - set_saved_ntstatus(NT_STATUS_TOO_MANY_OPENED_FILES); - return NULL; + return NT_STATUS_TOO_MANY_OPENED_FILES; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { - set_saved_ntstatus(NT_STATUS_NO_MEMORY); - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp); @@ -97,8 +95,7 @@ files_struct *file_new(connection_struct *conn) fsp->fh = SMB_MALLOC_P(struct fd_handle); if (!fsp->fh) { SAFE_FREE(fsp); - set_saved_ntstatus(NT_STATUS_NO_MEMORY); - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp->fh); @@ -131,8 +128,9 @@ files_struct *file_new(connection_struct *conn) if (fsp_fi_cache.fsp == NULL) { ZERO_STRUCT(fsp_fi_cache); } - - return fsp; + + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** @@ -464,24 +462,16 @@ void file_free(files_struct *fsp) } /**************************************************************************** - Get a fsp from a packet given the offset of a 16 bit fnum. + Get an fsp from a 16 bit fnum. ****************************************************************************/ -files_struct *file_fsp(char *buf, int where) +files_struct *file_fnum(uint16 fnum) { - int fnum, count=0; files_struct *fsp; - - if (chain_fsp) - return chain_fsp; - - if (!buf) - return NULL; - fnum = SVAL(buf, where); + int count=0; for (fsp=Files;fsp;fsp=fsp->next, count++) { if (fsp->fnum == fnum) { - chain_fsp = fsp; if (count > 10) { DLIST_PROMOTE(Files, fsp); } @@ -491,6 +481,29 @@ files_struct *file_fsp(char *buf, int where) return NULL; } +/**************************************************************************** + Get an fsp from a packet given the offset of a 16 bit fnum. +****************************************************************************/ + +files_struct *file_fsp(char *buf, int where) +{ + files_struct *fsp; + + if (chain_fsp) { + return chain_fsp; + } + + if (!buf) { + return NULL; + } + + fsp = file_fnum(SVAL(buf, where)); + if (fsp) { + chain_fsp = fsp; + } + return fsp; +} + /**************************************************************************** Reset the chained fsp - done at the start of a packet reply. ****************************************************************************/ @@ -504,15 +517,19 @@ void file_chain_reset(void) Duplicate the file handle part for a DOS or FCB open. ****************************************************************************/ -files_struct *dup_file_fsp(files_struct *fsp, +NTSTATUS dup_file_fsp(files_struct *fsp, uint32 access_mask, uint32 share_access, - uint32 create_options) + uint32 create_options, + files_struct **result) { - files_struct *dup_fsp = file_new(fsp->conn); + NTSTATUS status; + files_struct *dup_fsp; - if (!dup_fsp) { - return NULL; + status = file_new(fsp->conn, &dup_fsp); + + if (!NT_STATUS_IS_OK(status)) { + return status; } SAFE_FREE(dup_fsp->fh); @@ -547,5 +564,6 @@ files_struct *dup_file_fsp(files_struct *fsp, dup_fsp->aio_write_behind = fsp->aio_write_behind; string_set(&dup_fsp->fsp_name,fsp->fsp_name); - return dup_fsp; + *result = dup_fsp; + return NT_STATUS_OK; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e4531d8ae9..2d6db8f2a3 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -72,7 +72,11 @@ static int CopyExpanded(connection_struct *conn, StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf,sizeof(buf)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); l = push_ascii(*dst,buf,*n, STR_TERMINATE); (*dst) += l; (*n) -= l; @@ -99,7 +103,11 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf,sizeof(buf)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); return strlen(buf) + 1; } @@ -111,7 +119,11 @@ static char *Expand(connection_struct *conn, int snum, char *s) } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf,sizeof(buf)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); return &buf[0]; } @@ -593,7 +605,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); - standard_sub_basic( "", location, sizeof(location)-1 ); + standard_sub_basic( "", "", location, sizeof(location)-1 ); PACKS(desc,"z", location); /* share to retrieve files */ PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ @@ -2534,7 +2546,6 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); uint32 jobid; - int snum; fstring sharename; int uLevel = SVAL(p,2); int function = SVAL(p,4); @@ -2548,9 +2559,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha return False; } - if ( (snum = lp_servicenumber(sharename)) == -1 ) { - DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n", - sharename)); + if (!share_defined(sharename)) { + DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n", + sharename)); return False; } @@ -2573,14 +2584,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha /* change job place in the queue, data gives the new place */ place = SVAL(data,0); - if (print_job_set_place(snum, jobid, place)) { + if (print_job_set_place(sharename, jobid, place)) { errcode=NERR_Success; } break; case 0xb: /* change print job name, data gives the name */ - if (print_job_set_name(snum, jobid, data)) { + if (print_job_set_name(sharename, jobid, data)) { errcode=NERR_Success; } break; @@ -2701,7 +2712,11 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par SIVAL(p,6,0); } else { SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub_conn(conn,comment,sizeof(comment)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + comment, sizeof(comment)); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); p2 = skip_string(p2,1); } @@ -3126,8 +3141,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVALS(p,102,-1); /* bad_pw_count */ SSVALS(p,104,-1); /* num_logons */ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ - pstrcpy(p2,"\\\\%L"); - standard_sub_conn(conn, p2,0); + { + pstring tmp; + pstrcpy(tmp, "\\\\%L"); + standard_sub_basic("", "", tmp, sizeof(tmp)); + pstrcpy(p2, tmp); + } p2 = skip_string(p2,1); SSVAL(p,110,49); /* country_code */ SSVAL(p,112,860); /* code page */ diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index ed69a6210e..16f99636eb 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -81,22 +81,24 @@ void mangle_change_to_posix(void) /* see if a filename has come out of our mangling code */ -BOOL mangle_is_mangled(const char *s, int snum) +BOOL mangle_is_mangled(const char *s, const struct share_params *p) { - return mangle_fns->is_mangled(s, snum); + return mangle_fns->is_mangled(s, p); } /* see if a filename matches the rules of a 8.3 filename */ -BOOL mangle_is_8_3(const char *fname, BOOL check_case, int snum) +BOOL mangle_is_8_3(const char *fname, BOOL check_case, + const struct share_params *p) { - return mangle_fns->is_8_3(fname, check_case, False, snum); + return mangle_fns->is_8_3(fname, check_case, False, p); } -BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum) +BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, + const struct share_params *p) { - return mangle_fns->is_8_3(fname, check_case, True, snum); + return mangle_fns->is_8_3(fname, check_case, True, p); } /* @@ -105,20 +107,22 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum) looking for a matching name if it doesn't. It should succeed most of the time or there will be a huge performance penalty */ -BOOL mangle_check_cache(char *s, size_t maxlen, int snum) +BOOL mangle_check_cache(char *s, size_t maxlen, + const struct share_params *p) { - return mangle_fns->check_cache(s, maxlen, snum); + return mangle_fns->check_cache(s, maxlen, p); } /* map a long filename to a 8.3 name. */ -void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) +void mangle_map(pstring OutName, BOOL need83, BOOL cache83, + const struct share_params *p) { /* name mangling can be disabled for speed, in which case we just truncate the string */ - if (!lp_manglednames(snum)) { + if (!lp_manglednames(p)) { if (need83) { string_truncate(OutName, 12); } @@ -126,6 +130,6 @@ void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) } /* invoke the inane "mangled map" code */ - mangle_map_filename(OutName, snum); - mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum), snum); + mangle_map_filename(OutName, p); + mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p); } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 2092f430c0..320e31ab67 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -275,14 +275,15 @@ done: return ret; } -static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, + const struct share_params *p) { const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; size_t size; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); if (!fname || !*fname) return False; @@ -360,11 +361,11 @@ static void init_chartest( void ) * * ************************************************************************** ** */ -static BOOL is_mangled(const char *s, int snum) +static BOOL is_mangled(const char *s, const struct share_params *p) { char *magic; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); if( !ct_initialized ) init_chartest(); @@ -460,13 +461,13 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) * ************************************************************************** ** */ -static BOOL check_cache( char *s, size_t maxlen, int snum ) +static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p ) { TDB_DATA data_val; char *ext_start = NULL; char *saved_ext = NULL; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); /* If the cache isn't initialized, give up. */ if( !tdb_mangled_cache ) @@ -606,10 +607,11 @@ static void to_8_3(char *s, int default_case) * **************************************************************************** */ -static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum) +static void name_map(char *OutName, BOOL need83, BOOL cache83, + int default_case, const struct share_params *p) { smb_ucs2_t *OutName_ucs2; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, need83 ? "True" : "False", cache83 ? "True" : "False")); diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0a161c9e76..d1ce1af9ea 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -101,7 +101,7 @@ static unsigned mangle_prefix; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; -static u32 *prefix_cache_hashes; +static unsigned int *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -119,10 +119,10 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static u32 mangle_hash(const char *key, unsigned int length) +static unsigned int mangle_hash(const char *key, unsigned int length) { - u32 value; - u32 i; + unsigned int value; + unsigned int i; fstring str; /* we have to uppercase here to ensure that the mangled name @@ -139,8 +139,8 @@ static u32 mangle_hash(const char *key, unsigned int length) /* Set the initial value from the key size. */ for (value = FNV1_INIT, i=0; i < length; i++) { - value *= (u32)FNV1_PRIME; - value ^= (u32)(str[i]); + value *= (unsigned int)FNV1_PRIME; + value ^= (unsigned int)(str[i]); } /* note that we force it to a 31 bit hash, to keep within the limits @@ -162,7 +162,7 @@ static BOOL cache_init(void) return False; } - prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); + prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { return False; } @@ -173,7 +173,7 @@ static BOOL cache_init(void) /* insert an entry into the prefix cache. The string might not be null terminated */ -static void cache_insert(const char *prefix, int length, u32 hash) +static void cache_insert(const char *prefix, int length, unsigned int hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, u32 hash) /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(u32 hash) +static const char *cache_lookup(unsigned int hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len) directory separators. It should return true if any component is mangled */ -static BOOL is_mangled(const char *name, int snum) +static BOOL is_mangled(const char *name, const struct share_params *parm) { const char *p; const char *s; @@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name, int snum) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) { int len, i; char *dot_p; @@ -370,15 +370,15 @@ static void mangle_reset(void) try to find a 8.3 name in the cache, and if found then replace the string with the original long name. */ -static BOOL check_cache(char *name, size_t maxlen, int snum) +static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) { - u32 hash, multiplier; + unsigned int hash, multiplier; unsigned int i; const char *prefix; char extension[4]; /* make sure that this is a mangled name from this cache */ - if (!is_mangled(name, snum)) { + if (!is_mangled(name, p)) { M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } @@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum) /* we need to extract the hash from the 8.3 name */ hash = base_reverse[(unsigned char)name[7]]; for (multiplier=36, i=5;i>=mangle_prefix;i--) { - u32 v = base_reverse[(unsigned char)name[i]]; + unsigned int v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } @@ -510,21 +510,21 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, int snum) +static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) { char *dot_p; char lead_chars[7]; char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; - u32 hash, v; + unsigned int hash, v; char new_name[13]; /* reserved names are handled specially */ if (!is_reserved_name(name)) { /* if the name is already a valid 8.3 name then we don't need to do anything */ - if (is_8_3(name, False, False, snum)) { + if (is_8_3(name, False, False, p)) { return; } @@ -724,22 +724,22 @@ struct mangle_fns *mangle_hash2_init(void) static void posix_mangle_reset(void) {;} -static BOOL posix_is_mangled(const char *s, int snum) +static BOOL posix_is_mangled(const char *s, const struct share_params *p) { return False; } -static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) { return False; } -static BOOL posix_check_cache( char *s, size_t maxlen, int snum ) +static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p ) { return False; } -static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum) +static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) { if (need83) { memset(OutName, '\0', 13); diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c index 9e798fd41b..c5803786ec 100644 --- a/source3/smbd/mangle_map.c +++ b/source3/smbd/mangle_map.c @@ -201,11 +201,11 @@ static void mangled_map(char *s, const char *MangledMap) front end routine to the mangled map code personally I think that the whole idea of "mangled map" is completely bogus */ -void mangle_map_filename(fstring fname, int snum) +void mangle_map_filename(fstring fname, const struct share_params *p) { char *map; - map = lp_mangled_map(snum); + map = lp_mangled_map(p); if (!map || !*map) return; mangled_map(fname, map); diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 31dab45844..fd53e60c14 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -101,7 +101,8 @@ static void msg_deliver(void) pstrcpy(s,lp_msg_command()); pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); - standard_sub_basic(current_user_info.smb_name, s, sizeof(s)); + standard_sub_basic(current_user_info.smb_name, + current_user_info.domain, s, sizeof(s)); pstring_sub(s,"%s",name); smbrun(s,NULL); } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b22b5674d6..69da4194fd 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -135,7 +135,6 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) ZERO_STRUCTP(conn); - conn->service = snum; pstrcpy(connpath, path); pstring_sub(connpath , "%S", lp_servicename(snum)); @@ -145,6 +144,13 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) DEBUG(0,("talloc_init(connection_struct) failed!\n")); return False; } + + if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) { + DEBUG(0, ("TALLOC failed\n")); + return False; + } + + conn->params->service = snum; set_conn_connectpath(conn, connpath); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index aa6f79e165..0b1bdcadbb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -321,7 +321,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn, smb_np_struct *p = NULL; uint16 vuid = SVAL(inbuf, smb_uid); int i; - + DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); /* See if it is one we want to handle. */ @@ -350,6 +350,12 @@ static int nt_open_pipe(char *fname, connection_struct *conn, return(ERROR_DOS(ERRSRV,ERRnofids)); } + /* TODO: Add pipe to db */ + + if ( !store_pipe_opendb( p ) ) { + DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname)); + } + *ppnum = p->pnum; return 0; } @@ -412,10 +418,14 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, int result; char *p; uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); - files_struct *fsp = open_fake_file(conn, fake_file_type, fname, desired_access); + files_struct *fsp; + NTSTATUS status; - if (!fsp) { - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + status = open_fake_file(conn, fake_file_type, fname, desired_access, + &fsp); + + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } set_message(outbuf,34,0,True); @@ -688,18 +698,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n", return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); + &info, &fsp); restore_case_semantics(conn, file_attributes); - if(!fsp) { + if(!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { /* @@ -719,15 +729,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n", * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_access, create_disposition, create_options, file_attributes, oplock_request, - &info); - if (!fsp) { + &info, &fsp); + if (!NT_STATUS_IS_OK(status)) { /* We cheat here. There are two cases we * care about. One is a directory rename, * where the NT client will attempt to @@ -747,7 +757,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", * we handle in the open_file_stat case. JRA. */ - if(errno == EISDIR) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_FILE_IS_A_DIRECTORY)) { /* * Fail the open if it was explicitly a non-directory file. @@ -760,17 +771,17 @@ create_options = 0x%x root_dir_fid = 0x%x\n", } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); + &info, &fsp); - if(!fsp) { + if(!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { @@ -780,7 +791,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } } @@ -1331,16 +1342,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * CreateDirectory() call. */ - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); - if(!fsp) { + &info, &fsp); + if(!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { @@ -1349,17 +1360,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Ordinary file case. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_access, create_disposition, create_options, file_attributes, oplock_request, - &info); + &info, &fsp); - if (!fsp) { - if(errno == EISDIR) { + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_FILE_IS_A_DIRECTORY)) { /* * Fail the open if it was explicitly a non-directory file. @@ -1371,16 +1383,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); - if(!fsp) { + &info, &fsp); + if(!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { talloc_destroy(ctx); @@ -1389,7 +1401,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } } @@ -1655,39 +1667,29 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); - fsp1 = open_file_ntcreate(conn,oldname,&sbuf1, + status = open_file_ntcreate(conn,oldname,&sbuf1, FILE_READ_DATA, /* Read-only. */ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, /* No create options. */ FILE_ATTRIBUTE_NORMAL, NO_OPLOCK, - &info); + &info, &fsp1); - if (!fsp1) { - status = get_saved_ntstatus(); - if (NT_STATUS_IS_OK(status)) { - status = NT_STATUS_ACCESS_DENIED; - } - set_saved_ntstatus(NT_STATUS_OK); + if (!NT_STATUS_IS_OK(status)) { return status; } - fsp2 = open_file_ntcreate(conn,newname,&sbuf2, - FILE_WRITE_DATA, /* Write-only. */ + status = open_file_ntcreate(conn,newname,&sbuf2, + FILE_WRITE_DATA, /* Read-only. */ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_CREATE, 0, /* No create options. */ fattr, NO_OPLOCK, - &info); + &info, &fsp2); - if (!fsp2) { - status = get_saved_ntstatus(); - if (NT_STATUS_IS_OK(status)) { - status = NT_STATUS_ACCESS_DENIED; - } - set_saved_ntstatus(NT_STATUS_OK); + if (!NT_STATUS_IS_OK(status)) { close_file(fsp1,ERROR_CLOSE); return status; } @@ -2389,7 +2391,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, return ERROR_NT(NT_STATUS_INVALID_HANDLE); } - /* the NULL pointer cheking for fsp->fake_file_handle->pd + /* the NULL pointer checking for fsp->fake_file_handle->pd * is done by CHECK_NTQUOTA_HANDLE_OK() */ qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 832a8df755..7c04cdbe7c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,24 +38,29 @@ struct deferred_open_record { fd support routines - attempt to do a dos_open. ****************************************************************************/ -static int fd_open(struct connection_struct *conn, +static BOOL fd_open(struct connection_struct *conn, const char *fname, + files_struct *fsp, int flags, mode_t mode) { - int fd; + int sav; + #ifdef O_NOFOLLOW if (!lp_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; } #endif - fd = SMB_VFS_OPEN(conn,fname,flags,mode); + fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); + sav = errno; - DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, - flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" )); + DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", + fname, flags, (int)mode, fsp->fh->fd, + (fsp->fh->fd == -1) ? strerror(errno) : "" )); - return fd; + errno = sav; + return fsp->fh->fd != -1; } /**************************************************************************** @@ -179,7 +184,7 @@ void change_owner_to_parent(connection_struct *conn, Open a file. ****************************************************************************/ -static BOOL open_file(files_struct *fsp, +static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, @@ -210,7 +215,7 @@ static BOOL open_file(files_struct *fsp, /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); - return False; + return NT_STATUS_ACCESS_DENIED; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that O_CREAT doesn't create the file if we have write @@ -265,17 +270,15 @@ static BOOL open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && ms_has_wild(fname)) { - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID); - return False; + return NT_STATUS_OBJECT_NAME_INVALID; } /* Actually do the open */ - fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode); - if (fsp->fh->fd == -1) { + if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", fname,strerror(errno),local_flags,flags)); - return False; + return map_nt_error_from_unix(errno); } /* Inherit the ACL if the file was created. */ @@ -303,8 +306,9 @@ static BOOL open_file(files_struct *fsp, /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { + NTSTATUS status = map_nt_error_from_unix(errno); fd_close(conn, fsp); - return False; + return status; } } @@ -317,7 +321,7 @@ static BOOL open_file(files_struct *fsp, if(S_ISDIR(psbuf->st_mode)) { fd_close(conn, fsp); errno = EISDIR; - return False; + return NT_STATUS_FILE_IS_A_DIRECTORY; } fsp->mode = psbuf->st_mode; @@ -351,7 +355,7 @@ static BOOL open_file(files_struct *fsp, conn->num_files_open + 1)); errno = 0; - return True; + return NT_STATUS_OK; } /******************************************************************* @@ -894,8 +898,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, } /* We need to duplicate this fsp. */ - dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options); - if (!dup_fsp) { + if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access, + create_options, &dup_fsp))) { return NULL; } @@ -1081,7 +1085,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ Open a file with a share mode. ****************************************************************************/ -files_struct *open_file_ntcreate(connection_struct *conn, +NTSTATUS open_file_ntcreate(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ @@ -1091,7 +1095,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, uint32 new_dos_attributes, /* attributes used for new file. */ int oplock_request, /* internal Samba oplock codes. */ /* Information (FILE_EXISTS etc.) */ - int *pinfo) + int *pinfo, + files_struct **result) { int flags=0; int flags2=0; @@ -1099,7 +1104,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, BOOL def_acl = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; - BOOL fsp_open = False; + NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; mode_t unx_mode = (mode_t)0; @@ -1123,7 +1128,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(conn, fname); + return print_fsp_open(conn, fname, &fsp); } /* We add aARCH to this as this mode is only used if the file is @@ -1162,7 +1167,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (!check_name(fname,conn)) { - return NULL; + return map_nt_error_from_unix(errno); } new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; @@ -1181,11 +1186,12 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { /* OS/2 Workplace shell fix may be main code stream in a later * release. */ - set_saved_error_triple(ERRDOS, ERRcannotopen, - NT_STATUS_OBJECT_NAME_NOT_FOUND); DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " "supported.\n")); - return NULL; + if (use_nt_status()) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + return NT_STATUS_DOS(ERRDOS, ERRcannotopen); } switch( create_disposition ) { @@ -1213,9 +1219,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OPEN " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } break; @@ -1226,9 +1231,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags2 |= O_TRUNC; break; @@ -1245,7 +1249,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } else { errno = EEXIST; } - return NULL; + return map_nt_error_from_unix(errno); } flags2 |= (O_CREAT|O_EXCL); break; @@ -1257,8 +1261,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, break; default: - set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } /* We only care about matching attributes on file exists and @@ -1277,7 +1280,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, (unsigned int)psbuf->st_mode, (unsigned int)unx_mode )); errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; } } @@ -1334,14 +1337,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: write access requested for " "file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } fsp->dev = psbuf->st_dev; @@ -1367,8 +1369,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (lck == NULL) { file_free(fsp); DEBUG(0, ("Could not get share mode lock\n")); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } /* First pass - send break only on batch oplocks. */ @@ -1376,7 +1377,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1390,16 +1391,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } } if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } if (!NT_STATUS_IS_OK(status)) { @@ -1424,7 +1424,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, *pinfo = FILE_WAS_OPENED; } conn->num_files_open++; - return fsp_dup; + *result = fsp_dup; + return NT_STATUS_OK; } } @@ -1449,13 +1450,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(4,("open_file_ntcreate : share_mode deny - " "calling open_file with flags=0x%X " - "flags2=0x%X mode=0%o returned %d\n", + "flags2=0x%X mode=0%o returned %s\n", flags, (flags2&~(O_TRUNC|O_CREAT)), - (unsigned int)unx_mode, (int)fsp_open )); + (unsigned int)unx_mode, nt_errstr(fsp_open))); - if (!fsp_open && errno) { + if (!NT_STATUS_IS_OK(fsp_open) && errno) { /* Default error. */ - set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); + status = NT_STATUS_ACCESS_DENIED; } /* @@ -1471,7 +1472,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* this is a hack to speed up torture tests in 'make test' */ - timeout_usecs = lp_parm_int(conn->service, + timeout_usecs = lp_parm_int(SNUM(conn), "smbd","sharedelay", SHARING_VIOLATION_USEC_WAIT); @@ -1502,16 +1503,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, } TALLOC_FREE(lck); - if (fsp_open) { + if (NT_STATUS_IS_OK(fsp_open)) { fd_close(conn, fsp); /* * We have detected a sharing violation here * so return the correct error code */ - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + status = NT_STATUS_SHARING_VIOLATION; } file_free(fsp); - return NULL; + return status; } /* @@ -1542,12 +1543,12 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, access_mask); - if (!fsp_open) { + if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { TALLOC_FREE(lck); } file_free(fsp); - return NULL; + return fsp_open; } if (!file_existed) { @@ -1578,8 +1579,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1606,7 +1606,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, defer_open(lck, request_time, timeval_zero(), &state); TALLOC_FREE(lck); - return NULL; + return status; } /* @@ -1642,10 +1642,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { + status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); - return NULL; + return status; } } @@ -1692,16 +1693,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* Handle strange delete on close create semantics. */ if (create_options & FILE_DELETE_ON_CLOSE) { - NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes); + status = can_set_delete_on_close(fsp, True, new_dos_attributes); - if (!NT_STATUS_IS_OK(result)) { + if (!NT_STATUS_IS_OK(status)) { /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); - set_saved_ntstatus(result); - return NULL; + return status; } /* Note that here we set the *inital* delete on close flag, not the regular one. */ @@ -1770,31 +1770,32 @@ files_struct *open_file_ntcreate(connection_struct *conn, conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ -files_struct *open_file_fchmod(connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf) +NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf, files_struct **result) { files_struct *fsp = NULL; - BOOL fsp_open; + NTSTATUS status; if (!VALID_STAT(*psbuf)) { - return NULL; + return NT_STATUS_INVALID_PARAMETER; } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); + status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1802,12 +1803,13 @@ files_struct *open_file_fchmod(connection_struct *conn, const char *fname, * the conn->num_files_open. */ - if (!fsp_open) { + if (!NT_STATUS_IS_OK(status)) { file_free(fsp); - return NULL; + return status; } - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** @@ -1825,14 +1827,15 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, +NTSTATUS open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, uint32 share_access, uint32 create_disposition, uint32 create_options, - int *pinfo) + int *pinfo, + files_struct **result) { files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; @@ -1852,8 +1855,7 @@ files_struct *open_directory(connection_struct *conn, if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); - set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); - return NULL; + return NT_STATUS_NOT_A_DIRECTORY; } switch( create_disposition ) { @@ -1864,8 +1866,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_OPEN requested " "for directory %s and it doesn't " "exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } info = FILE_WAS_OPENED; break; @@ -1877,9 +1878,12 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_CREATE " "requested for directory %s and it " "already exists.\n", fname )); - set_saved_error_triple(ERRDOS, ERRfilexists, - NT_STATUS_OBJECT_NAME_COLLISION); - return NULL; + if (use_nt_status()) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } else { + return NT_STATUS_DOS(ERRDOS, + ERRfilexists); + } } create_dir = True; info = FILE_WAS_CREATED; @@ -1903,8 +1907,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: invalid create_disposition " "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); - set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } if (create_dir) { @@ -1921,27 +1924,26 @@ files_struct *open_directory(connection_struct *conn, "Error was %s\n", fname, strerror(errno) )); /* Ensure we return the correct NT status to the * client. */ - set_saved_error_triple(0, 0, status); - return NULL; + return status; } /* Ensure we're checking for a symlink here.... */ /* We don't want to get caught by a symlink racer. */ if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - return NULL; + return map_nt_error_from_unix(errno); } if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - return NULL; + return NT_STATUS_NOT_A_DIRECTORY; } } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } /* @@ -1953,7 +1955,7 @@ files_struct *open_directory(connection_struct *conn, fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; - fsp->can_lock = True; + fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; @@ -1976,8 +1978,7 @@ files_struct *open_directory(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); file_free(fsp); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1985,10 +1986,9 @@ files_struct *open_directory(connection_struct *conn, create_options, &dir_existed); if (!NT_STATUS_IS_OK(status)) { - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK); @@ -1998,10 +1998,9 @@ files_struct *open_directory(connection_struct *conn, if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } set_delete_on_close_token(lck, ¤t_user.ut); @@ -2022,28 +2021,33 @@ files_struct *open_directory(connection_struct *conn, conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -files_struct *open_file_stat(connection_struct *conn, char *fname, - SMB_STRUCT_STAT *psbuf) +NTSTATUS open_file_stat(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf, files_struct **result) { files_struct *fsp = NULL; + NTSTATUS status; - if (!VALID_STAT(*psbuf)) - return NULL; + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_INVALID_PARAMETER; + } /* Can't 'stat' open directories. */ - if(S_ISDIR(psbuf->st_mode)) - return NULL; + if(S_ISDIR(psbuf->st_mode)) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } - fsp = file_new(conn); - if(!fsp) - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; + } DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); @@ -2069,7 +2073,8 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 73b0ebb4b3..389086e9bf 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -29,9 +29,6 @@ static user_struct *validated_users; static int next_vuid = VUID_OFFSET; static int num_validated_vuids; -extern userdom_struct current_user_info; - - /**************************************************************************** Check if a uid has been validated, and return an pointer to the user_struct if it has. NULL if not. vuid is biased by an offset. This allows us to @@ -550,9 +547,11 @@ static BOOL user_ok(const char *user, int snum) str_list_copy(&invalid, lp_invalid_users(snum)); if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { - if ( invalid && - str_list_sub_basic(invalid, - current_user_info.smb_name) ) { + + /* This is used in sec=share only, so no current user + * around to pass to str_list_sub_basic() */ + + if ( invalid && str_list_sub_basic(invalid, "", "") ) { ret = !user_in_list(user, (const char **)invalid); } @@ -565,9 +564,11 @@ static BOOL user_ok(const char *user, int snum) str_list_copy(&valid, lp_valid_users(snum)); if ( valid && str_list_substitute(valid, "%S", lp_servicename(snum)) ) { - if ( valid && - str_list_sub_basic(valid, - current_user_info.smb_name) ) { + + /* This is used in sec=share only, so no current user + * around to pass to str_list_sub_basic() */ + + if ( valid && str_list_sub_basic(valid, "", "") ) { ret = user_in_list(user, (const char **)valid); } } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 2d90383706..52660da2ff 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -31,6 +31,21 @@ #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) +#define MAX_PIPE_NAME_LEN 24 + +/* PIPE/// */ +#define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d" + +struct pipe_dbrec { + struct process_id pid; + int pnum; + uid_t uid; + + char name[MAX_PIPE_NAME_LEN]; + fstring user; +}; + + extern struct pipe_id_info pipe_names[]; /**************************************************************************** @@ -284,6 +299,8 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) if (!close_rpc_pipe_hnd(p)) { return ERROR_DOS(ERRDOS,ERRbadfid); } + + /* TODO: REMOVE PIPE FROM DB */ return(outsize); } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6e403dba92..73744cf26e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3043,8 +3043,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ return -1; } - fsp = open_file_fchmod(conn,fname,&st); - if (!fsp) { + if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,&st,&fsp))) { return -1; } @@ -4236,12 +4235,19 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) pstring filename; ZERO_STRUCT( conn ); - conn.service = -1; if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) { DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); return NULL; } + + if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) { + DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); + TALLOC_FREE(conn.mem_ctx); + return NULL; + } + + conn.params->service = -1; pstrcpy( path, "/" ); set_conn_connectpath(&conn, path); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b3ce49360d..ce352adfd7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -21,7 +21,7 @@ #include "includes.h" -extern uint16 global_smbpid; +uint16 global_smbpid; extern int keepalive; extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; @@ -172,7 +172,6 @@ BOOL open_was_deferred(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { - set_saved_ntstatus(NT_STATUS_OK); return True; } } @@ -459,11 +458,20 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) } } - maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds); - maxfd = select_on_fd(change_notify_fd(), maxfd, &fds); - maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds); + { + int sav; + START_PROFILE(smbd_idle); + + maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds); + maxfd = select_on_fd(change_notify_fd(), maxfd, &fds); + maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds); - selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); + selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); + sav = errno; + + END_PROFILE(smbd_idle); + errno = sav; + } /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but @@ -885,7 +893,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize pid = sys_getpid(); errno = 0; - set_saved_ntstatus(NT_STATUS_OK); last_message = type; @@ -954,7 +961,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize } if (!change_to_user(conn,session_tag)) { - return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid)); + return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid))); } /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e68e8662d7..ff3c6832e4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -427,6 +427,7 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de } else { *err = check_path_syntax_wcard(dest, tmppath, contains_wcard); } + return ret; } @@ -453,6 +454,7 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } else { *err = check_path_syntax(dest, tmppath); } + return ret; } @@ -809,6 +811,14 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBchkpth); + + /* Strange DOS error code semantics only for chkpth... */ + if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) { + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) { + /* We need to map to ERRbadpath */ + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } return ERROR_NT(status); } @@ -1370,25 +1380,25 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask, &share_mode, &create_disposition, &create_options)) { END_PROFILE(SMBopen); - return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); + return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); } - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, dos_attr, oplock_request, - &info); + &info, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } size = sbuf.st_size; @@ -1493,25 +1503,25 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt &create_disposition, &create_options)) { END_PROFILE(SMBopenX); - return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); + return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); } - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, smb_attr, oplock_request, - &smb_action); + &smb_action, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } size = sbuf.st_size; @@ -1672,22 +1682,22 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file using ntcreate. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, fattr, oplock_request, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } outsize = set_message(outbuf,1,0,True); @@ -1756,25 +1766,25 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SMB_VFS_STAT(conn,fname,&sbuf); /* We should fail if file does not exist. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, fattr, oplock_request, - NULL); + NULL, &fsp); /* close fd from smb_mkstemp() */ close(tmpfd); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } outsize = set_message(outbuf,1,0,True); @@ -1822,6 +1832,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, { files_struct *fsp; uint32 fmode; + NTSTATUS status; if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; @@ -1836,25 +1847,16 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, return NT_STATUS_OK; } - /* We need a better way to return NT status codes from open... */ - set_saved_ntstatus(NT_STATUS_OK); - - fsp = open_file_ntcreate(conn, fname, pst, + status = open_file_ntcreate(conn, fname, pst, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, 0, - NULL); + NULL, &fsp); - if (!fsp) { - NTSTATUS ret = get_saved_ntstatus(); - if (!NT_STATUS_IS_OK(ret)) { - set_saved_ntstatus(NT_STATUS_OK); - return ret; - } - set_saved_ntstatus(NT_STATUS_OK); + if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_ACCESS_DENIED; } close_file(fsp,NORMAL_CLOSE); @@ -1870,6 +1872,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b SMB_STRUCT_STAT sbuf; uint32 fattr; files_struct *fsp; + NTSTATUS status; DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype )); @@ -1929,26 +1932,17 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b /* On open checks the open itself will check the share mode, so don't do it here as we'll get it wrong. */ - /* We need a better way to return NT status codes from open... */ - set_saved_ntstatus(NT_STATUS_OK); - - fsp = open_file_ntcreate(conn, fname, &sbuf, + status = open_file_ntcreate(conn, fname, &sbuf, DELETE_ACCESS, FILE_SHARE_NONE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, 0, - NULL); + NULL, &fsp); - if (!fsp) { - NTSTATUS ret = get_saved_ntstatus(); - if (!NT_STATUS_IS_OK(ret)) { - set_saved_ntstatus(NT_STATUS_OK); - return ret; - } - set_saved_ntstatus(NT_STATUS_OK); - return NT_STATUS_ACCESS_DENIED; + if (!NT_STATUS_IS_OK(status)) { + return status; } close_file(fsp,NORMAL_CLOSE); } @@ -1994,8 +1988,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask,SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); + if (!rc && mangle_is_mangled(mask,conn->params)) + mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { pstrcat(directory,"/"); @@ -2331,7 +2325,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); - if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { SMB_STRUCT_STAT st; SMB_OFF_T size = 0; @@ -2403,7 +2397,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length */ status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, @@ -2510,7 +2504,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", data = smb_buf(outbuf) + 3; - if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBread); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2717,7 +2711,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2780,7 +2774,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SCVAL(inbuf,smb_com,SMBwritec); SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwritebraw); return(ERROR_DOS(ERRDOS,ERRlock)); } @@ -2901,7 +2895,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteunlock); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2924,7 +2918,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, if (numtowrite) { status = do_unlock(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, WINDOWS_LOCK); @@ -2978,7 +2972,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwrite); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3093,7 +3087,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3368,7 +3362,7 @@ int reply_writeclose(connection_struct *conn, mtime = srv_make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteclose); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3439,7 +3433,7 @@ int reply_lock(connection_struct *conn, fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, @@ -3494,7 +3488,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); status = do_unlock(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), count, offset, WINDOWS_LOCK); @@ -3598,6 +3592,8 @@ int reply_printopen(connection_struct *conn, { int outsize = 0; files_struct *fsp; + NTSTATUS status; + START_PROFILE(SMBsplopen); if (!CAN_PRINT(conn)) { @@ -3606,11 +3602,11 @@ int reply_printopen(connection_struct *conn, } /* Open for exclusive use, write only. */ - fsp = print_fsp_open(conn, NULL); + status = print_fsp_open(conn, NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsplopen); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(ERROR_NT(status)); } outsize = set_message(outbuf,1,0,True); @@ -3838,6 +3834,17 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = mkdir_internal(conn, directory,bad_path); if (!NT_STATUS_IS_OK(status)) { + + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION) && + !use_nt_status()) { + /* + * Yes, in the DOS error code case we get a + * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR + * samba4 torture test. + */ + status = NT_STATUS_DOS(ERRDOS, ERRnoaccess); + } + END_PROFILE(SMBmkdir); return ERROR_NT(status); } @@ -4408,14 +4415,14 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask,SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); + if (!rc && mangle_is_mangled(mask, conn->params)) + mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { /* * No wildcards - just process the one file. */ - BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn)); + BOOL is_short_name = mangle_is_8_3(name, True, conn->params); /* Add a terminating '/' to the directory name. */ pstrcat(directory,"/"); @@ -4739,6 +4746,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstring dest; uint32 dosattrs; uint32 new_create_disposition; + NTSTATUS status; *err_ret = 0; @@ -4767,16 +4775,16 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } } - fsp1 = open_file_ntcreate(conn,src,&src_sbuf, + status = open_file_ntcreate(conn,src,&src_sbuf, FILE_GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - NULL); + NULL, &fsp1); - if (!fsp1) { + if (!NT_STATUS_IS_OK(status)) { return(False); } @@ -4785,16 +4793,16 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, ZERO_STRUCTP(&sbuf2); } - fsp2 = open_file_ntcreate(conn,dest,&sbuf2, + status = open_file_ntcreate(conn,dest,&sbuf2, FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, new_create_disposition, 0, dosattrs, INTERNAL_OPEN_ONLY, - NULL); + NULL, &fsp2); - if (!fsp2) { + if (!NT_STATUS_IS_OK(status)) { close_file(fsp1,ERROR_CLOSE); return(False); } @@ -4926,8 +4934,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask, SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); + if (!rc && mangle_is_mangled(mask, conn->params)) + mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); has_wild = path_contains_wcard1; @@ -4995,8 +5003,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBcopy); return ERROR_DOS(ERRDOS,error); } else { - if((errno == ENOENT) && (bad_path1 || bad_path2)) { - set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK); + if((errno == ENOENT) && (bad_path1 || bad_path2) && + !use_nt_status()) { + /* Samba 3.0.22 has ERRDOS/ERRbadpath in the + * DOS error code case + */ + return ERROR_DOS(ERRDOS, ERRbadpath); } END_PROFILE(SMBcopy); return(UNIXERROR(ERRDOS,error)); @@ -5067,12 +5079,12 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size Get a lock pid, dealing with large count requests. ****************************************************************************/ -uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format) +uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format) { if(!large_file_format) - return SVAL(data,SMB_LPID_OFFSET(data_offset)); + return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset)); else - return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset)); + return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset)); } /**************************************************************************** @@ -5209,7 +5221,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = 0, offset = 0; - uint16 lock_pid; + uint32 lock_pid; int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; @@ -5229,7 +5241,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, /* we don't support these - and CANCEL_LOCK makes w2k and XP reboot so I don't really want to be compatible! (tridge) */ - return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks); + return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks)); } if (locktype & LOCKING_ANDX_CANCEL_LOCK) { @@ -5505,7 +5517,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadBmpx); return ERROR_DOS(ERRDOS,ERRlock); } @@ -5637,7 +5649,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { END_PROFILE(SMBwriteBmpx); return(ERROR_DOS(ERRDOS,ERRlock)); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2bfeae9f54..0fba6af697 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -912,18 +912,12 @@ void build_options(BOOL screen); if (!message_init()) exit(1); - /* Initialize our global sam sid first -- quite a lot of the other - * initialization routines further down depend on it. - */ - /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ if(!initialize_password_db(False)) exit(1); - /* Fail gracefully if we can't open secrets.tdb */ - if (!secrets_init()) { DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n")); exit(1); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index cb9bfcc27a..9dcb8a354f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -371,35 +371,38 @@ static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest, { TALLOC_CTX *mem_ctx; char *fuser, *found_username; + struct nt_user_token *tmp_token; NTSTATUS result; - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { + if (!(mem_ctx = talloc_new(NULL))) { DEBUG(0, ("talloc_new failed\n")); return NT_STATUS_NO_MEMORY; } - fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S", - lp_servicename(snum)); - if (fuser == NULL) { - result = NT_STATUS_NO_MEMORY; - goto done; + if (!(fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S", + lp_servicename(snum)))) { + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; + } result = create_token_from_username(mem_ctx, fuser, vuser_is_guest, uid, gid, &found_username, - token); + &tmp_token); if (!NT_STATUS_IS_OK(result)) { - goto done; + TALLOC_FREE(mem_ctx); + return result; + } + + if (!(*token = dup_nt_token(NULL, tmp_token))) { + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; } - talloc_steal(NULL, *token); fstrcpy(username, found_username); - result = NT_STATUS_OK; - done: TALLOC_FREE(mem_ctx); - return result; + return NT_STATUS_OK; } /* @@ -620,7 +623,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = conn->lastused_count = time(NULL); - conn->service = snum; + conn->params->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || @@ -646,7 +649,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, string_set(&conn->dirpath,""); string_set(&conn->user,user); - conn->read_only = lp_readonly(conn->service); + conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; /* @@ -746,7 +749,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, { pstring s; pstrcpy(s,lp_pathname(snum)); - standard_sub_conn(conn,s,sizeof(s)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + s, sizeof(s)); set_conn_connectpath(conn,s); DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); @@ -821,7 +828,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_rootpreexec(snum)) { pstring cmd; pstrcpy(cmd,lp_rootpreexec(snum)); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(snum)) { @@ -854,7 +865,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_preexec(snum)) { pstring cmd; pstrcpy(cmd,lp_preexec(snum)); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(snum)) { DEBUG(1,("preexec gave %d - failing connection\n", @@ -1148,7 +1163,11 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_user(conn, vuid)) { pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); smbrun(cmd,NULL); change_to_root_user(); } @@ -1158,7 +1177,11 @@ void close_cnum(connection_struct *conn, uint16 vuid) if (*lp_rootpostexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); smbrun(cmd,NULL); } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 41f8fd0ed4..bcb840a3fe 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. session handling for utmp and PAM - Copyright (C) tridge@samba.org 2001 - Copyright (C) abartlet@pcug.org.au 2001 + + Copyright (C) tridge@samba.org 2001 + Copyright (C) abartlet@samba.org 2001 + Copyright (C) Gerald (Jerry) Carter 2006 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 @@ -29,6 +31,9 @@ static TDB_CONTEXT *tdb; +/******************************************************************** +********************************************************************/ + BOOL session_init(void) { if (tdb) @@ -44,7 +49,10 @@ BOOL session_init(void) return True; } -/* called when a session is created */ +/******************************************************************** + called when a session is created +********************************************************************/ + BOOL session_claim(user_struct *vuser) { int i = 0; @@ -126,6 +134,7 @@ BOOL session_claim(user_struct *vuser) sessionid.gid = vuser->gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); fstrcpy(sessionid.ip_addr, client_addr()); + sessionid.connect_start = time(NULL); client_ip = client_inaddr(&sa); @@ -159,7 +168,10 @@ BOOL session_claim(user_struct *vuser) return True; } -/* called when a session is destroyed */ +/******************************************************************** + called when a session is destroyed +********************************************************************/ + void session_yield(user_struct *vuser) { TDB_DATA dbuf; @@ -198,6 +210,9 @@ void session_yield(user_struct *vuser) tdb_delete(tdb, key); } +/******************************************************************** +********************************************************************/ + BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state) { @@ -210,32 +225,40 @@ BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), return True; } +/******************************************************************** +********************************************************************/ + struct session_list { int count; struct sessionid *sessions; }; -static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, - void *state) +static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { + uint32 i; struct session_list *sesslist = (struct session_list *) state; const struct sessionid *current = (const struct sessionid *) dbuf.dptr; - sesslist->count += 1; - sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, - sesslist->count); + i = sesslist->count; + + sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, i+1); if (!sesslist->sessions) { sesslist->count = 0; return -1; } - memcpy(&sesslist->sessions[sesslist->count - 1], current, - sizeof(struct sessionid)); + memcpy(&sesslist->sessions[i], current, sizeof(struct sessionid)); + sesslist->count++; + DEBUG(7,("gather_sessioninfo session from %s@%s\n", current->username, current->remote_machine)); + return 0; } +/******************************************************************** +********************************************************************/ + int list_sessions(struct sessionid **session_list) { struct session_list sesslist; diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index 468f61560b..5334976d8d 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -28,6 +28,8 @@ * + and & may be combined */ +extern userdom_struct current_user_info; + static BOOL do_group_checks(const char **name, const char **pattern) { if ((*name)[0] == '@') { @@ -74,7 +76,8 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, enum SID_NAME_USE type; if (username != NULL) { - name = talloc_sub_basic(mem_ctx, username, name); + name = talloc_sub_basic(mem_ctx, username, + current_user_info.domain, name); } if (sharename != NULL) { name = talloc_string_sub(mem_ctx, name, "%S", sharename); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 548d7c4a48..b453fdd544 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -52,7 +52,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (!lp_stat_cache()) return; - if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) { + if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { reset_stat_cache(); } @@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -u32 fast_string_hash(TDB_DATA *key) +unsigned int fast_string_hash(TDB_DATA *key) { - u32 n = 0; + unsigned int n = 0; const char *p; for (p = key->dptr; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (u32)(*p); + n = ((n << 5) + n) ^ (unsigned int)(*p); } return n; } diff --git a/source3/smbd/statvfs.c b/source3/smbd/statvfs.c index 8f981a6328..300b14a7c0 100644 --- a/source3/smbd/statvfs.c +++ b/source3/smbd/statvfs.c @@ -21,7 +21,7 @@ #include "includes.h" -#if defined(LINUX) +#if defined(LINUX) && defined(HAVE_FSID_INT) static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) { struct statvfs statvfs_buf; @@ -51,7 +51,7 @@ static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) */ int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf) { -#if defined(LINUX) +#if defined(LINUX) && defined(HAVE_FSID_INT) return linux_statvfs(path, statbuf); #else /* BB change this to return invalid level */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9030737b1b..aca1fcd70e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -837,16 +837,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, open_attr, oplock_request, - &smb_action); + &smb_action, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ @@ -1070,7 +1070,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL was_8_3; uint32 nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - BOOL check_mangled_names = lp_manglednames(SNUM(conn)); + BOOL check_mangled_names = lp_manglednames(conn->params); *fname = 0; *out_of_space = False; @@ -1117,7 +1117,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive))) got_match = mask_match(fname, mask, conn->case_sensitive); - if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) { + if(!got_match && check_mangled_names && + !mangle_is_8_3(fname, False, conn->params)) { /* * It turns out that NT matches wildcards against @@ -1128,7 +1129,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstring newname; pstrcpy( newname, fname); - mangle_map( newname, True, False, SNUM(conn)); + mangle_map( newname, True, False, conn->params); if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive))) got_match = mask_match(newname, mask, conn->case_sensitive); } @@ -1202,7 +1203,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } } - mangle_map(fname,False,True,SNUM(conn)); + mangle_map(fname,False,True,conn->params); p = pdata; last_entry_ptr = p; @@ -1338,7 +1339,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, SNUM(conn)); + was_8_3 = mangle_is_8_3(fname, True, conn->params); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; @@ -1361,7 +1362,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); - mangle_map(mangled_name,True,True,SNUM(conn)); + mangle_map(mangled_name,True,True, + conn->params); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); if (len < 24) { @@ -1480,7 +1482,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, case SMB_FIND_ID_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, SNUM(conn)); + was_8_3 = mangle_is_8_3(fname, True, conn->params); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; @@ -1503,7 +1505,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); - mangle_map(mangled_name,True,True,SNUM(conn)); + mangle_map(mangled_name,True,True, + conn->params); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); @@ -1871,8 +1874,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * (see PR#13758). JRA. */ - if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn))) - mangle_map(mask, True, True, SNUM(conn)); + if(!mangle_is_8_3_wildcards( mask, False, conn->params)) + mangle_map(mask, True, True, conn->params); return(-1); } @@ -2068,8 +2071,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * could be mangled. Ensure we check the unmangled name. */ - if (mangle_is_mangled(resume_name, SNUM(conn))) { - mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn)); + if (mangle_is_mangled(resume_name, conn->params)) { + mangle_check_cache(resume_name, sizeof(resume_name)-1, + conn->params); } /* @@ -2441,17 +2445,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); /* We have POSIX ACLs, pathname and locking capability. */ -#if defined(DEVELOPER) /* Not quite finished yet... */ SBIG_UINT(pdata,4,((SMB_BIG_UINT)( CIFS_UNIX_POSIX_ACLS_CAP| CIFS_UNIX_POSIX_PATHNAMES_CAP| CIFS_UNIX_FCNTL_LOCKS_CAP))); -#else - SBIG_UINT(pdata,4,((SMB_BIG_UINT)( - CIFS_UNIX_POSIX_ACLS_CAP| - CIFS_UNIX_POSIX_PATHNAMES_CAP| - 0))); -#endif break; case SMB_QUERY_POSIX_FS_INFO: @@ -2567,11 +2564,10 @@ cap_low = 0x%x, cap_high = 0x%x\n", lp_set_posix_pathnames(); mangle_change_to_posix(); } -#if defined(DEVELOPER) + if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) { lp_set_posix_cifsx_locktype(POSIX_LOCK); } -#endif break; } case SMB_FS_QUOTA_INFORMATION: @@ -2832,9 +2828,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * TALLOC_CTX *data_ctx = NULL; struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ -#if defined(DEVELOPER) char *lock_data = NULL; -#endif if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -3006,7 +3000,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } break; } -#if defined(DEVELOPER) + case SMB_QUERY_POSIX_LOCK: { if (fsp == NULL || fsp->fh->fd == -1) { @@ -3028,7 +3022,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_NO_MEMORY); } } -#endif default: break; } @@ -3229,8 +3222,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n")); pstrcpy(short_name,base_name); /* Mangle if not already 8.3 */ - if(!mangle_is_8_3(short_name, True, SNUM(conn))) { - mangle_map(short_name,True,True,SNUM(conn)); + if(!mangle_is_8_3(short_name, True, conn->params)) { + mangle_map(short_name,True,True,conn->params); } len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE); data_size = 4 + len; @@ -3448,7 +3441,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd { int i; - DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC")); + DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC ")); for (i=0; i<100; i++) DEBUG(4,("%d=%x, ",i, (*ppdata)[i])); @@ -3559,13 +3552,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd #endif -#if defined(DEVELOPER) case SMB_QUERY_POSIX_LOCK: { NTSTATUS status = NT_STATUS_INVALID_LEVEL; SMB_BIG_UINT count; SMB_BIG_UINT offset; - uint16 lock_pid; + uint32 lock_pid; enum brl_type lock_type; if (total_data != POSIX_LOCK_DATA_SIZE) { @@ -3586,7 +3578,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET); + lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); #if defined(HAVE_LONGLONG) offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); @@ -3632,7 +3624,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } break; } -#endif default: return ERROR_NT(NT_STATUS_INVALID_LEVEL); @@ -4030,16 +4021,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (fd == -1) { files_struct *new_fsp = NULL; - new_fsp = open_file_ntcreate(conn, fname, &sbuf, + status = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, FORCE_OPLOCK_BREAK_TO_NONE, - NULL); + NULL, &new_fsp); - if (new_fsp == NULL) { + if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; @@ -4404,7 +4395,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_FILE_RENAME_INFORMATION: { BOOL overwrite; - uint32 root_fid; + /* uint32 root_fid; */ /* Not used */ uint32 len; pstring newname; pstring base_name; @@ -4415,7 +4406,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } overwrite = (CVAL(pdata,0) ? True : False); - root_fid = IVAL(pdata,4); + /* root_fid = IVAL(pdata,4); */ len = IVAL(pdata,8); srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); if (!NT_STATUS_IS_OK(status)) { @@ -4507,12 +4498,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } #endif -#if defined(DEVELOPER) case SMB_SET_POSIX_LOCK: { SMB_BIG_UINT count; SMB_BIG_UINT offset; - uint16 lock_pid; + uint32 lock_pid; BOOL lock_blocking; enum brl_type lock_type; BOOL my_lock_ctx; @@ -4551,7 +4541,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET); + lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); #if defined(HAVE_LONGLONG) offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); @@ -4605,7 +4595,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); } -#endif default: return ERROR_NT(NT_STATUS_INVALID_LEVEL); @@ -4673,16 +4662,16 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (fd == -1) { files_struct *new_fsp = NULL; - new_fsp = open_file_ntcreate(conn, fname, &sbuf, + status = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, FORCE_OPLOCK_BREAK_TO_NONE, - NULL); + NULL, &new_fsp); - if (new_fsp == NULL) { + if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c62c9d928a..48d7f590c3 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -102,7 +102,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) readonly_share = is_share_read_only_for_token(vuser->user.unix_name, vuser->nt_user_token, - conn->service); + SNUM(conn)); if (!readonly_share && !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) { @@ -129,7 +129,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->admin_user = token_contains_name_in_list( vuser->user.unix_name, NULL, vuser->nt_user_token, - lp_admin_users(conn->service)); + lp_admin_users(SNUM(conn))); conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c deleted file mode 100644 index ee251c17d8..0000000000 --- a/source3/smbd/vfs-wrap.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Wrap disk only vfs functions to sidestep dodgy compilers. - Copyright (C) Tim Potter 1998 - - 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" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_VFS - - -/* Check for NULL pointer parameters in vfswrap_* functions */ - -/* We don't want to have NULL function pointers lying around. Someone - is sure to try and execute them. These stubs are used to prevent - this possibility. */ - -int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user) -{ - return 0; /* Return >= 0 for success */ -} - -void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn) -{ -} - -/* Disk operations */ - -SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, - SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -{ - SMB_BIG_UINT result; - - result = sys_disk_free(conn, path, small_query, bsize, dfree, dsize); - return result; -} - -int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_get_quota); - result = sys_get_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_get_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_set_quota); - result = sys_set_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_set_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels) -{ - errno = ENOSYS; - return -1; /* Not implemented. */ -} - -int vfswrap_statvfs(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, vfs_statvfs_struct *statbuf) -{ - return sys_statvfs(path, statbuf); -} - -/* Directory operations */ - -SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) -{ - SMB_STRUCT_DIR *result; - - START_PROFILE(syscall_opendir); - result = sys_opendir(fname); - END_PROFILE(syscall_opendir); - return result; -} - -SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - SMB_STRUCT_DIRENT *result; - - START_PROFILE(syscall_readdir); - result = sys_readdir(dirp); - END_PROFILE(syscall_readdir); - return result; -} - -void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset) -{ - START_PROFILE(syscall_seekdir); - sys_seekdir(dirp, offset); - END_PROFILE(syscall_seekdir); -} - -long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - long result; - START_PROFILE(syscall_telldir); - result = sys_telldir(dirp); - END_PROFILE(syscall_telldir); - return result; -} - -void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - START_PROFILE(syscall_rewinddir); - sys_rewinddir(dirp); - END_PROFILE(syscall_rewinddir); -} - -int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) -{ - int result; - BOOL has_dacl = False; - - START_PROFILE(syscall_mkdir); - - if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path)))) - mode = 0777; - - result = mkdir(path, mode); - - if (result == 0 && !has_dacl) { - /* - * We need to do this as the default behavior of POSIX ACLs - * is to set the mask to be the requested group permission - * bits, not the group permission bits to be the requested - * group permission bits. This is not what we want, as it will - * mess up any inherited ACL bits that were set. JRA. - */ - int saved_errno = errno; /* We may get ENOSYS */ - if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) - errno = saved_errno; - } - - END_PROFILE(syscall_mkdir); - return result; -} - -int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - int result; - - START_PROFILE(syscall_rmdir); - result = rmdir(path); - END_PROFILE(syscall_rmdir); - return result; -} - -int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - int result; - - START_PROFILE(syscall_closedir); - result = sys_closedir(dirp); - END_PROFILE(syscall_closedir); - return result; -} - -/* File operations */ - -int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) -{ - int result; - - START_PROFILE(syscall_open); - result = sys_open(fname, flags, mode); - END_PROFILE(syscall_open); - return result; -} - -int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd) -{ - int result; - - START_PROFILE(syscall_close); - - result = close(fd); - END_PROFILE(syscall_close); - return result; -} - -ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n) -{ - ssize_t result; - - START_PROFILE_BYTES(syscall_read, n); - result = sys_read(fd, data, n); - END_PROFILE(syscall_read); - return result; -} - -ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, - size_t n, SMB_OFF_T offset) -{ - ssize_t result; - -#if defined(HAVE_PREAD) || defined(HAVE_PREAD64) - START_PROFILE_BYTES(syscall_pread, n); - result = sys_pread(fd, data, n, offset); - END_PROFILE(syscall_pread); - - if (result == -1 && errno == ESPIPE) { - /* Maintain the fiction that pipes can be seeked (sought?) on. */ - result = SMB_VFS_READ(fsp, fd, data, n); - fsp->fh->pos = 0; - } - -#else /* HAVE_PREAD */ - SMB_OFF_T curr; - int lerrno; - - curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - if (curr == -1 && errno == ESPIPE) { - /* Maintain the fiction that pipes can be seeked (sought?) on. */ - result = SMB_VFS_READ(fsp, fd, data, n); - fsp->fh->pos = 0; - return result; - } - - if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { - return -1; - } - - errno = 0; - result = SMB_VFS_READ(fsp, fd, data, n); - lerrno = errno; - - SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); - errno = lerrno; - -#endif /* HAVE_PREAD */ - - return result; -} - -ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) -{ - ssize_t result; - - START_PROFILE_BYTES(syscall_write, n); - result = sys_write(fd, data, n); - END_PROFILE(syscall_write); - return result; -} - -ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, - size_t n, SMB_OFF_T offset) -{ - ssize_t result; - -#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64) - START_PROFILE_BYTES(syscall_pwrite, n); - result = sys_pwrite(fd, data, n, offset); - END_PROFILE(syscall_pwrite); - - if (result == -1 && errno == ESPIPE) { - /* Maintain the fiction that pipes can be sought on. */ - result = SMB_VFS_WRITE(fsp, fd, data, n); - } - -#else /* HAVE_PWRITE */ - SMB_OFF_T curr; - int lerrno; - - curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - if (curr == -1) { - return -1; - } - - if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { - return -1; - } - - result = SMB_VFS_WRITE(fsp, fd, data, n); - lerrno = errno; - - SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); - errno = lerrno; - -#endif /* HAVE_PWRITE */ - - return result; -} - -SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) -{ - SMB_OFF_T result = 0; - - START_PROFILE(syscall_lseek); - - /* Cope with 'stat' file opens. */ - if (filedes != -1) - result = sys_lseek(filedes, offset, whence); - - /* - * We want to maintain the fiction that we can seek - * on a fifo for file system purposes. This allows - * people to set up UNIX fifo's that feed data to Windows - * applications. JRA. - */ - - if((result == -1) && (errno == ESPIPE)) { - result = 0; - errno = 0; - } - - END_PROFILE(syscall_lseek); - return result; -} - -ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr, - SMB_OFF_T offset, size_t n) -{ - ssize_t result; - - START_PROFILE_BYTES(syscall_sendfile, n); - result = sys_sendfile(tofd, fromfd, hdr, offset, n); - END_PROFILE(syscall_sendfile); - return result; -} - -/********************************************************* - For rename across filesystems Patch from Warren Birnbaum - -**********************************************************/ - -static int copy_reg(const char *source, const char *dest) -{ - SMB_STRUCT_STAT source_stats; - int saved_errno; - int ifd = -1; - int ofd = -1; - - if (sys_lstat (source, &source_stats) == -1) - return -1; - - if (!S_ISREG (source_stats.st_mode)) - return -1; - - if((ifd = sys_open (source, O_RDONLY, 0)) < 0) - return -1; - - if (unlink (dest) && errno != ENOENT) - return -1; - -#ifdef O_NOFOLLOW - if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 ) -#else - if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 ) -#endif - goto err; - - if (transfer_file(ifd, ofd, (size_t)-1) == -1) - goto err; - - /* - * Try to preserve ownership. For non-root it might fail, but that's ok. - * But root probably wants to know, e.g. if NFS disallows it. - */ - -#ifdef HAVE_FCHOWN - if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) -#else - if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) -#endif - goto err; - - /* - * fchown turns off set[ug]id bits for non-root, - * so do the chmod last. - */ - -#if defined(HAVE_FCHMOD) - if (fchmod (ofd, source_stats.st_mode & 07777)) -#else - if (chmod (dest, source_stats.st_mode & 07777)) -#endif - goto err; - - if (close (ifd) == -1) - goto err; - - if (close (ofd) == -1) - return -1; - - /* Try to copy the old file's modtime and access time. */ - { - struct utimbuf tv; - - tv.actime = source_stats.st_atime; - tv.modtime = source_stats.st_mtime; - utime(dest, &tv); - } - - if (unlink (source) == -1) - return -1; - - return 0; - - err: - - saved_errno = errno; - if (ifd != -1) - close(ifd); - if (ofd != -1) - close(ofd); - errno = saved_errno; - return -1; -} - -int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname) -{ - int result; - - START_PROFILE(syscall_rename); - result = rename(oldname, newname); - if (errno == EXDEV) { - /* Rename across filesystems needed. */ - result = copy_reg(oldname, newname); - } - - END_PROFILE(syscall_rename); - return result; -} - -int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) -{ -#ifdef HAVE_FSYNC - int result; - - START_PROFILE(syscall_fsync); - result = fsync(fd); - END_PROFILE(syscall_fsync); - return result; -#else - return 0; -#endif -} - -int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) -{ - int result; - - START_PROFILE(syscall_stat); - result = sys_stat(fname, sbuf); - END_PROFILE(syscall_stat); - return result; -} - -int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) -{ - int result; - - START_PROFILE(syscall_fstat); - result = sys_fstat(fd, sbuf); - END_PROFILE(syscall_fstat); - return result; -} - -int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) -{ - int result; - - START_PROFILE(syscall_lstat); - result = sys_lstat(path, sbuf); - END_PROFILE(syscall_lstat); - return result; -} - -int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - int result; - - START_PROFILE(syscall_unlink); - result = unlink(path); - END_PROFILE(syscall_unlink); - return result; -} - -int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) -{ - int result; - - START_PROFILE(syscall_chmod); - - /* - * We need to do this due to the fact that the default POSIX ACL - * chmod modifies the ACL *mask* for the group owner, not the - * group owner bits directly. JRA. - */ - - - { - int saved_errno = errno; /* We might get ENOSYS */ - if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) { - END_PROFILE(syscall_chmod); - return result; - } - /* Error - return the old errno. */ - errno = saved_errno; - } - - result = chmod(path, mode); - END_PROFILE(syscall_chmod); - return result; -} - -int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) -{ - int result; - - START_PROFILE(syscall_fchmod); - - /* - * We need to do this due to the fact that the default POSIX ACL - * chmod modifies the ACL *mask* for the group owner, not the - * group owner bits directly. JRA. - */ - - { - int saved_errno = errno; /* We might get ENOSYS */ - if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { - END_PROFILE(syscall_fchmod); - return result; - } - /* Error - return the old errno. */ - errno = saved_errno; - } - -#if defined(HAVE_FCHMOD) - result = fchmod(fd, mode); -#else - result = -1; - errno = ENOSYS; -#endif - - END_PROFILE(syscall_fchmod); - return result; -} - -int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) -{ - int result; - - START_PROFILE(syscall_chown); - result = sys_chown(path, uid, gid); - END_PROFILE(syscall_chown); - return result; -} - -int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid) -{ -#ifdef HAVE_FCHOWN - int result; - - START_PROFILE(syscall_fchown); - result = fchown(fd, uid, gid); - END_PROFILE(syscall_fchown); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - int result; - - START_PROFILE(syscall_chdir); - result = chdir(path); - END_PROFILE(syscall_chdir); - return result; -} - -char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path) -{ - char *result; - - START_PROFILE(syscall_getwd); - result = sys_getwd(path); - END_PROFILE(syscall_getwd); - return result; -} - -int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) -{ - int result; - - START_PROFILE(syscall_utime); - result = utime(path, times); - END_PROFILE(syscall_utime); - return result; -} - -/********************************************************************* - A version of ftruncate that will write the space on disk if strict - allocate is set. -**********************************************************************/ - -static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) -{ - SMB_STRUCT_STAT st; - SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - unsigned char zero_space[4096]; - SMB_OFF_T space_to_write; - - if (currpos == -1) - return -1; - - if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) - return -1; - - space_to_write = len - st.st_size; - -#ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) - return 0; -#endif - - if (st.st_size == len) - return 0; - - /* Shrink - just ftruncate. */ - if (st.st_size > len) - return sys_ftruncate(fd, len); - - /* Write out the real space on disk. */ - if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) - return -1; - - space_to_write = len - st.st_size; - - memset(zero_space, '\0', sizeof(zero_space)); - while ( space_to_write > 0) { - SMB_OFF_T retlen; - SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); - - retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write); - if (retlen <= 0) - return -1; - - space_to_write -= retlen; - } - - /* Seek to where we were */ - if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) - return -1; - - return 0; -} - -int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) -{ - int result = -1; - SMB_STRUCT_STAT st; - char c = 0; - SMB_OFF_T currpos; - - START_PROFILE(syscall_ftruncate); - - if (lp_strict_allocate(SNUM(fsp->conn))) { - result = strict_allocate_ftruncate(handle, fsp, fd, len); - END_PROFILE(syscall_ftruncate); - return result; - } - - /* we used to just check HAVE_FTRUNCATE_EXTEND and only use - sys_ftruncate if the system supports it. Then I discovered that - you can have some filesystems that support ftruncate - expansion and some that don't! On Linux fat can't do - ftruncate extend but ext2 can. */ - - result = sys_ftruncate(fd, len); - if (result == 0) - goto done; - - /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot - extend a file with ftruncate. Provide alternate implementation - for this */ - currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - if (currpos == -1) { - goto done; - } - - /* Do an fstat to see if the file is longer than the requested - size in which case the ftruncate above should have - succeeded or shorter, in which case seek to len - 1 and - write 1 byte of zero */ - if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) { - goto done; - } - -#ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) { - result = 0; - goto done; - } -#endif - - if (st.st_size == len) { - result = 0; - goto done; - } - - if (st.st_size > len) { - /* the sys_ftruncate should have worked */ - goto done; - } - - if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) - goto done; - - if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1) - goto done; - - /* Seek to where we were */ - if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) - goto done; - result = 0; - - done: - - END_PROFILE(syscall_ftruncate); - return result; -} - -BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) -{ - BOOL result; - - START_PROFILE(syscall_fcntl_lock); - result = fcntl_lock(fd, op, offset, count, type); - END_PROFILE(syscall_fcntl_lock); - return result; -} - -BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid) -{ - BOOL result; - - START_PROFILE(syscall_fcntl_getlock); - result = fcntl_getlock(fd, poffset, pcount, ptype, ppid); - END_PROFILE(syscall_fcntl_getlock); - return result; -} - -int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) -{ - int result; - - START_PROFILE(syscall_symlink); - result = sys_symlink(oldpath, newpath); - END_PROFILE(syscall_symlink); - return result; -} - -int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) -{ - int result; - - START_PROFILE(syscall_readlink); - result = sys_readlink(path, buf, bufsiz); - END_PROFILE(syscall_readlink); - return result; -} - -int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) -{ - int result; - - START_PROFILE(syscall_link); - result = sys_link(oldpath, newpath); - END_PROFILE(syscall_link); - return result; -} - -int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev) -{ - int result; - - START_PROFILE(syscall_mknod); - result = sys_mknod(pathname, mode, dev); - END_PROFILE(syscall_mknod); - return result; -} - -char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path) -{ - char *result; - - START_PROFILE(syscall_realpath); - result = sys_realpath(path, resolved_path); - END_PROFILE(syscall_realpath); - return result; -} - -size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc) -{ - size_t result; - - START_PROFILE(fget_nt_acl); - result = get_nt_acl(fsp, security_info, ppdesc); - END_PROFILE(fget_nt_acl); - return result; -} - -size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc) -{ - size_t result; - - START_PROFILE(get_nt_acl); - result = get_nt_acl(fsp, security_info, ppdesc); - END_PROFILE(get_nt_acl); - return result; -} - -BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) -{ - BOOL result; - - START_PROFILE(fset_nt_acl); - result = set_nt_acl(fsp, security_info_sent, psd); - END_PROFILE(fset_nt_acl); - return result; -} - -BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) -{ - BOOL result; - - START_PROFILE(set_nt_acl); - result = set_nt_acl(fsp, security_info_sent, psd); - END_PROFILE(set_nt_acl); - return result; -} - -int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode) -{ -#ifdef HAVE_NO_ACL - errno = ENOSYS; - return -1; -#else - int result; - - START_PROFILE(chmod_acl); - result = chmod_acl(conn, name, mode); - END_PROFILE(chmod_acl); - return result; -#endif -} - -int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) -{ -#ifdef HAVE_NO_ACL - errno = ENOSYS; - return -1; -#else - int result; - - START_PROFILE(fchmod_acl); - result = fchmod_acl(fsp, fd, mode); - END_PROFILE(fchmod_acl); - return result; -#endif -} - -int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - return sys_acl_get_entry(theacl, entry_id, entry_p); -} - -int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return sys_acl_get_tag_type(entry_d, tag_type_p); -} - -int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return sys_acl_get_permset(entry_d, permset_p); -} - -void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d) -{ - return sys_acl_get_qualifier(entry_d); -} - -SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) -{ - return sys_acl_get_file(path_p, type); -} - -SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) -{ - return sys_acl_get_fd(fd); -} - -int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset) -{ - return sys_acl_clear_perms(permset); -} - -int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return sys_acl_add_perm(permset, perm); -} - -char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) -{ - return sys_acl_to_text(theacl, plen); -} - -SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count) -{ - return sys_acl_init(count); -} - -int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - return sys_acl_create_entry(pacl, pentry); -} - -int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return sys_acl_set_tag_type(entry, tagtype); -} - -int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) -{ - return sys_acl_set_qualifier(entry, qual); -} - -int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return sys_acl_set_permset(entry, permset); -} - -int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl ) -{ - return sys_acl_valid(theacl ); -} - -int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return sys_acl_set_file(name, acltype, theacl); -} - -int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl) -{ - return sys_acl_set_fd(fd, theacl); -} - -int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - return sys_acl_delete_def_file(path); -} - -int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return sys_acl_get_perm(permset, perm); -} - -int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text) -{ - return sys_acl_free_text(text); -} - -int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl) -{ - return sys_acl_free_acl(posix_acl); -} - -int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) -{ - return sys_acl_free_qualifier(qualifier, tagtype); -} - -/**************************************************************** - Extended attribute operations. -*****************************************************************/ - -ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) -{ - return sys_getxattr(path, name, value, size); -} - -ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) -{ - return sys_lgetxattr(path, name, value, size); -} - -ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) -{ - return sys_fgetxattr(fd, name, value, size); -} - -ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) -{ - return sys_listxattr(path, list, size); -} - -ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) -{ - return sys_llistxattr(path, list, size); -} - -ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size) -{ - return sys_flistxattr(fd, list, size); -} - -int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) -{ - return sys_removexattr(path, name); -} - -int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) -{ - return sys_lremovexattr(path, name); -} - -int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name) -{ - return sys_fremovexattr(fd, name); -} - -int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) -{ - return sys_setxattr(path, name, value, size, flags); -} - -int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) -{ - return sys_lsetxattr(path, name, value, size, flags); -} - -int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags) -{ - return sys_fsetxattr(fd, name, value, size, flags); -} - -int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_read(aiocb); -} - -int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_write(aiocb); -} - -ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_return(aiocb); -} - -int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_cancel(fd, aiocb); -} - -int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_error(aiocb); -} - -int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_fsync(op, aiocb); -} - -int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout) -{ - return sys_aio_suspend(aiocb, n, timeout); -} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2c9403a079..7bb5f798f9 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -4,6 +4,7 @@ VFS initialisation and support functions Copyright (C) Tim Potter 1999 Copyright (C) Alexander Bokovoy 2002 + Copyright (C) James Peach 2006 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 @@ -37,131 +38,6 @@ struct vfs_init_function_entry { static struct vfs_init_function_entry *backends = NULL; -/* Some structures to help us initialise the vfs operations table */ - -struct vfs_syminfo { - char *name; - void *fptr; -}; - -/* Default vfs hooks. WARNING: The order of these initialisers is - very important. They must be in the same order as defined in - vfs.h. Change at your own peril. */ - -static struct vfs_ops default_vfs = { - - { - /* Disk operations */ - - vfswrap_dummy_connect, - vfswrap_dummy_disconnect, - vfswrap_disk_free, - vfswrap_get_quota, - vfswrap_set_quota, - vfswrap_get_shadow_copy_data, - vfswrap_statvfs, - - /* Directory operations */ - - vfswrap_opendir, - vfswrap_readdir, - vfswrap_seekdir, - vfswrap_telldir, - vfswrap_rewinddir, - vfswrap_mkdir, - vfswrap_rmdir, - vfswrap_closedir, - - /* File operations */ - - vfswrap_open, - vfswrap_close, - vfswrap_read, - vfswrap_pread, - vfswrap_write, - vfswrap_pwrite, - vfswrap_lseek, - vfswrap_sendfile, - vfswrap_rename, - vfswrap_fsync, - vfswrap_stat, - vfswrap_fstat, - vfswrap_lstat, - vfswrap_unlink, - vfswrap_chmod, - vfswrap_fchmod, - vfswrap_chown, - vfswrap_fchown, - vfswrap_chdir, - vfswrap_getwd, - vfswrap_utime, - vfswrap_ftruncate, - vfswrap_lock, - vfswrap_getlock, - vfswrap_symlink, - vfswrap_readlink, - vfswrap_link, - vfswrap_mknod, - vfswrap_realpath, - - /* Windows ACL operations. */ - vfswrap_fget_nt_acl, - vfswrap_get_nt_acl, - vfswrap_fset_nt_acl, - vfswrap_set_nt_acl, - - /* POSIX ACL operations. */ - vfswrap_chmod_acl, - vfswrap_fchmod_acl, - - vfswrap_sys_acl_get_entry, - vfswrap_sys_acl_get_tag_type, - vfswrap_sys_acl_get_permset, - vfswrap_sys_acl_get_qualifier, - vfswrap_sys_acl_get_file, - vfswrap_sys_acl_get_fd, - vfswrap_sys_acl_clear_perms, - vfswrap_sys_acl_add_perm, - vfswrap_sys_acl_to_text, - vfswrap_sys_acl_init, - vfswrap_sys_acl_create_entry, - vfswrap_sys_acl_set_tag_type, - vfswrap_sys_acl_set_qualifier, - vfswrap_sys_acl_set_permset, - vfswrap_sys_acl_valid, - vfswrap_sys_acl_set_file, - vfswrap_sys_acl_set_fd, - vfswrap_sys_acl_delete_def_file, - vfswrap_sys_acl_get_perm, - vfswrap_sys_acl_free_text, - vfswrap_sys_acl_free_acl, - vfswrap_sys_acl_free_qualifier, - - /* EA operations. */ - vfswrap_getxattr, - vfswrap_lgetxattr, - vfswrap_fgetxattr, - vfswrap_listxattr, - vfswrap_llistxattr, - vfswrap_flistxattr, - vfswrap_removexattr, - vfswrap_lremovexattr, - vfswrap_fremovexattr, - vfswrap_setxattr, - vfswrap_lsetxattr, - vfswrap_fsetxattr, - - /* AIO operations. */ - vfswrap_aio_read, - vfswrap_aio_write, - vfswrap_aio_return, - vfswrap_aio_cancel, - vfswrap_aio_error, - vfswrap_aio_fsync, - vfswrap_aio_suspend - } -}; - /**************************************************************************** maintain the list of available backends ****************************************************************************/ @@ -217,15 +93,20 @@ NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tu static void vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); - - memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops)); - memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops)); + vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME); } /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ +static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which, + struct vfs_handle_struct * handle, void * op) +{ + ((struct vfs_handle_struct **)&vfs->handles)[which] = handle; + ((void**)&vfs->ops)[which] = op; +} + BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) { vfs_op_tuple *ops; @@ -292,24 +173,86 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) for(i=0; ops[i].op != NULL; i++) { DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { - /* Check whether this operation was already made opaque by different module */ - if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { - /* No, it isn't overloaded yet. Overload. */ - DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; - } + /* If this operation was already made opaque by different module, it + * will be overridded here. + */ + DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); + vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op); } /* Change current VFS disposition*/ DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; + vfs_set_operation(&conn->vfs, ops[i].type, handle, ops[i].op); } SAFE_FREE(module_name); return True; } +/***************************************************************** + Allow VFS modules to extend files_struct with VFS-specific state. + This will be ok for small numbers of extensions, but might need to + be refactored if it becomes more widely used. +******************************************************************/ + +#define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data)) + +void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, size_t ext_size) +{ + struct vfs_fsp_data *ext; + void * ext_data; + + /* Prevent VFS modules adding multiple extensions. */ + if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) { + return ext_data; + } + + ext = TALLOC_ZERO(handle->conn->mem_ctx, + sizeof(struct vfs_fsp_data) + ext_size); + if (ext == NULL) { + return NULL; + } + + ext->owner = handle; + ext->next = fsp->vfs_extension; + fsp->vfs_extension = ext; + return EXT_DATA_AREA(ext); +} + +void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +{ + struct vfs_fsp_data *curr; + struct vfs_fsp_data *prev; + + for (curr = fsp->vfs_extension, prev = NULL; + curr; + prev = curr, curr = curr->next) { + if (curr->owner == handle) { + if (prev) { + prev->next = curr->next; + } else { + fsp->vfs_extension = curr->next; + } + TALLOC_FREE(curr); + return; + } + } +} + +void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +{ + struct vfs_fsp_data *head; + + for (head = fsp->vfs_extension; head; head = head->next) { + if (head->owner == handle) { + return EXT_DATA_AREA(head); + } + } + + return NULL; +} + +#undef EXT_DATA_AREA + /***************************************************************** Generic VFS init. ******************************************************************/ -- cgit From 725d88b6d460f6495ee3117a8124d30115cf37fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jul 2006 03:02:33 +0000 Subject: r16968: The function parse_processed_dfs_path() is dependent on the fact that check_path_syntax() will convert '\\' characters to '/'. When POSIX pathnames have been selected this doesn't happen, so we must look for the unaltered separator of '\\' instead of the modified '/'. Stevef please check this with the CIFSFS MS-DFS code ! Jeremy (This used to be commit 883bb398e58f54ee79160487b49b79a4774ef939) --- source3/smbd/msdfs.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 69da4194fd..b698bc781d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -73,26 +73,32 @@ static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp) } /********************************************************************** - Parse the pathname of the form /hostname/service/reqpath - into the dfs_path structure + Parse the pathname of the form /hostname/service/reqpath + into the dfs_path structure + This code is dependent on the fact that check_path_syntax() will + convert '\\' characters to '/'. + When POSIX pathnames have been selected this doesn't happen, so we + must look for the unaltered separator of '\\' instead of the modified '/'. + JRA. **********************************************************************/ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) { pstring pathname_local; char *p,*temp; + const char sepchar = lp_posix_pathnames() ? '\\' : '/'; pstrcpy(pathname_local,pathname); p = temp = pathname_local; ZERO_STRUCTP(pdp); - trim_char(temp,'/','/'); + trim_char(temp,sepchar,sepchar); DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp)); /* now tokenize */ /* parse out hostname */ - p = strchr_m(temp,'/'); + p = strchr_m(temp,sepchar); if(p == NULL) { return False; } @@ -102,7 +108,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL /* parse out servicename */ temp = p+1; - p = strchr_m(temp,'/'); + p = strchr_m(temp,sepchar); if(p == NULL) { pstrcpy(pdp->servicename,temp); pdp->reqpath[0] = '\0'; -- cgit From 67854e8439d58af7f647dd97d9d4f2912a30265b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jul 2006 19:13:00 +0000 Subject: r16990: Fix bug #3921 spotted by jason@ncac.gwu.edu. Correctly obey blocking/non-blocking request for POSIX locks. Jeremy. (This used to be commit f62c01316ef3ce0351f8b34229307a75d8f9f156) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index aca1fcd70e..43437469d7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4567,7 +4567,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", POSIX_LOCK, &my_lock_ctx); - if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { + if (lock_blocking && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it -- cgit From 283b74fce595642fb2e2a2fad87c2de9c3bc5403 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Jul 2006 19:50:59 +0000 Subject: r17096: Simplify share_access_check a bit: It takes the sharename instead of the snum, and the decision which token to use (conn or vuser) does not really belong here, it is better done in the two places where this is called. Volker (This used to be commit 0a138888adf7a0f04a38cd911e797e1a379e908b) --- source3/smbd/service.c | 9 +++++++-- source3/smbd/uid.c | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9dcb8a354f..395114592a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -767,11 +767,16 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ { - BOOL can_write = share_access_check(conn, snum, vuser, + NT_USER_TOKEN *token = conn->nt_user_token ? + conn->nt_user_token : vuser->nt_user_token; + + BOOL can_write = share_access_check(token, + lp_servicename(snum), FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(conn, snum, vuser, + if (!share_access_check(token, + lp_servicename(snum), FILE_READ_DATA)) { /* No access, read or write. */ DEBUG(0,("make_connection: connection to %s " diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 48d7f590c3..89d082e1ac 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -87,6 +87,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) unsigned int i; struct vuid_cache_entry *ent = NULL; BOOL readonly_share; + NT_USER_TOKEN *token; for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { if (conn->vuid_cache.array[i].vuid == vuser->vuid) { @@ -104,8 +105,12 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) vuser->nt_user_token, SNUM(conn)); + token = conn->nt_user_token ? + conn->nt_user_token : vuser->nt_user_token; + if (!readonly_share && - !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) { + !share_access_check(token, lp_servicename(snum), + FILE_WRITE_DATA)) { /* smb.conf allows r/w, but the security descriptor denies * write. Fall back to looking at readonly. */ readonly_share = True; @@ -113,7 +118,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) "security descriptor\n")); } - if (!share_access_check(conn, snum, vuser, + if (!share_access_check(token, lp_servicename(snum), readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { return False; -- cgit From e1da1fcf12164f50f3462c90f0bb785d18c59b0b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Jul 2006 21:09:02 +0000 Subject: r17098: Samba3 now cleanly passes Samba4 RAW-LOCK torture test. Phew - that was painful :-). But what it means is that we now implement lock cancels and I can add lock cancels into POSIX lock handling which will fix the fast/slow system call issue with cifsfs ! Jeremy. (This used to be commit f1a9cf075b87c76c032d19da0168424c90f6cb3c) --- source3/smbd/blocking.c | 204 +++++++++++++++++++++++++++++++++++++++--------- source3/smbd/close.c | 2 - source3/smbd/reply.c | 123 ++++++++++++++++++----------- source3/smbd/trans2.c | 4 +- 4 files changed, 243 insertions(+), 90 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 04ab01eb66..941e87d3ad 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -19,6 +19,8 @@ */ #include "includes.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_LOCKING /**************************************************************************** This is the structure to queue to implement blocking locks. @@ -41,15 +43,18 @@ typedef struct _blocking_lock_record { int length; } blocking_lock_record; +/* dlink list we store pending lock records on. */ static blocking_lock_record *blocking_lock_queue; +/* dlink list we move cancelled lock records onto. */ +static blocking_lock_record *blocking_lock_cancelled_queue; + /**************************************************************************** Destructor for the above structure. ****************************************************************************/ static void free_blocking_lock_record(blocking_lock_record *blr) { - DLIST_REMOVE(blocking_lock_queue, blr); SAFE_FREE(blr->inbuf); SAFE_FREE(blr); } @@ -81,7 +86,6 @@ BOOL push_blocking_lock_request( char *inbuf, int length, { static BOOL set_lock_msg; blocking_lock_record *blr, *tmp; - BOOL my_lock_ctx = False; struct byte_range_lock *br_lck = NULL; NTSTATUS status; @@ -123,6 +127,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, br_lck = brl_get_locks(NULL, blr->fsp); if (!br_lck) { + DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); return False; } @@ -135,11 +140,12 @@ BOOL push_blocking_lock_request( char *inbuf, int length, count, PENDING_LOCK, blr->lock_flav, - &my_lock_ctx); + lock_timeout); TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); + DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); return False; } @@ -220,9 +226,24 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat status = NT_STATUS_FILE_LOCK_CONFLICT; } + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { + /* Store the last lock error. */ + files_struct *fsp = blr->fsp; + + fsp->last_lock_failure.context.smbpid = blr->lock_pid; + fsp->last_lock_failure.context.tid = fsp->conn->cnum; + fsp->last_lock_failure.context.pid = procid_self(); + fsp->last_lock_failure.start = blr->offset; + fsp->last_lock_failure.size = blr->count; + fsp->last_lock_failure.fnum = fsp->fnum; + fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */ + fsp->last_lock_failure.lock_flav = blr->lock_flav; + } + ERROR_NT(status); - if (!send_smb(smbd_server_fd(),outbuf)) + if (!send_smb(smbd_server_fd(),outbuf)) { exit_server("generic_blocking_lock_error: send_smb failed."); + } } /**************************************************************************** @@ -335,7 +356,6 @@ static BOOL process_lockread(blocking_lock_record *blr) size_t numtoread; NTSTATUS status; files_struct *fsp = blr->fsp; - BOOL my_lock_ctx = False; numtoread = SVAL(inbuf,smb_vwv1); startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2); @@ -343,13 +363,13 @@ static BOOL process_lockread(blocking_lock_record *blr) numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - status = do_lock_spin(fsp, - (uint32)SVAL(inbuf,smb_pid), - (SMB_BIG_UINT)numtoread, - startpos, - READ_LOCK, - WINDOWS_LOCK, - &my_lock_ctx); + status = do_lock(fsp, + (uint32)SVAL(inbuf,smb_pid), + (SMB_BIG_UINT)numtoread, + startpos, + READ_LOCK, + WINDOWS_LOCK, + (int32)-1); if (NT_STATUS_V(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && @@ -410,19 +430,18 @@ static BOOL process_lock(blocking_lock_record *blr) SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; NTSTATUS status; files_struct *fsp = blr->fsp; - BOOL my_lock_ctx = False; count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); errno = 0; - status = do_lock_spin(fsp, - (uint32)SVAL(inbuf,smb_pid), - count, - offset, - WRITE_LOCK, - WINDOWS_LOCK, - &my_lock_ctx); + status = do_lock(fsp, + (uint32)SVAL(inbuf,smb_pid), + count, + offset, + WRITE_LOCK, + WINDOWS_LOCK, + (int32)-1); if (NT_STATUS_IS_ERR(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && @@ -474,7 +493,6 @@ static BOOL process_lockingX(blocking_lock_record *blr) uint32 lock_pid; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; - BOOL my_lock_ctx = False; NTSTATUS status = NT_STATUS_OK; data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); @@ -496,13 +514,14 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - status = do_lock_spin(fsp, + status = do_lock(fsp, lock_pid, count, offset, - ((locktype & 1) ? READ_LOCK : WRITE_LOCK), + ((locktype & LOCKING_ANDX_SHARED_LOCK) ? + READ_LOCK : WRITE_LOCK), WINDOWS_LOCK, - &my_lock_ctx); + (int32)-1); if (NT_STATUS_IS_ERR(status)) { break; @@ -552,7 +571,6 @@ static BOOL process_trans2(blocking_lock_record *blr) extern int max_send; char *inbuf = blr->inbuf; char *outbuf; - BOOL my_lock_ctx = False; char params[2]; NTSTATUS status; @@ -562,7 +580,7 @@ static BOOL process_trans2(blocking_lock_record *blr) blr->offset, blr->lock_type, blr->lock_flav, - &my_lock_ctx); + (int32)-1); if (!NT_STATUS_IS_OK(status)) { if (ERROR_WAS_LOCK_DENIED(status)) { @@ -615,33 +633,41 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) } /**************************************************************************** - Delete entries by fnum from the blocking lock pending queue. + Cancel entries by fnum from the blocking lock pending queue. *****************************************************************************/ -void remove_pending_lock_requests_by_fid(files_struct *fsp) +void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck) { blocking_lock_record *blr, *next = NULL; for(blr = blocking_lock_queue; blr; blr = next) { next = blr->next; if(blr->fsp->fnum == fsp->fnum) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + unsigned char locktype = 0; + + if (blr->com_type == SMBlockingX) { + locktype = CVAL(blr->inbuf,smb_vwv3); + } if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - brl_remove_pending_lock(br_lck, + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, blr->count, blr->lock_flav); - TALLOC_FREE(br_lck); + blocking_lock_cancel(fsp, + blr->lock_pid, + blr->offset, + blr->count, + blr->lock_flav, + locktype, + NT_STATUS_RANGE_NOT_LOCKED); } - - free_blocking_lock_record(blr); } } } @@ -664,7 +690,7 @@ void remove_pending_lock_requests_by_mid(int mid) DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - brl_remove_pending_lock(br_lck, + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, @@ -674,6 +700,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); } } @@ -765,7 +792,7 @@ void process_blocking_lock_queue(time_t t) DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", fsp->fnum, fsp->fsp_name )); - brl_remove_pending_lock(br_lck, + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, @@ -775,6 +802,7 @@ void process_blocking_lock_queue(time_t t) } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); continue; } @@ -787,7 +815,7 @@ void process_blocking_lock_queue(time_t t) */ if (br_lck) { - brl_remove_pending_lock(br_lck, + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, @@ -799,6 +827,7 @@ void process_blocking_lock_queue(time_t t) DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", vuid )); blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); continue; } @@ -811,7 +840,7 @@ void process_blocking_lock_queue(time_t t) */ if (br_lck) { - brl_remove_pending_lock(br_lck, + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, @@ -822,6 +851,7 @@ void process_blocking_lock_queue(time_t t) DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); change_to_root_user(); continue; @@ -837,7 +867,7 @@ void process_blocking_lock_queue(time_t t) struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { - brl_remove_pending_lock(br_lck, + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, @@ -846,8 +876,106 @@ void process_blocking_lock_queue(time_t t) TALLOC_FREE(br_lck); } + DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); } change_to_root_user(); } } + +/**************************************************************************** + Handle a cancel message. Lock already moved onto the cancel queue. +*****************************************************************************/ + +#define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS)) + +static void process_blocking_lock_cancel_message(int msg_type, struct process_id src, + void *buf, size_t len) +{ + NTSTATUS err; + const char *msg = (const char *)buf; + blocking_lock_record *blr; + + if (buf == NULL) { + smb_panic("process_blocking_lock_cancel_message: null msg\n"); + } + + if (len != MSG_BLOCKING_LOCK_CANCEL_SIZE) { + DEBUG(0, ("process_blocking_lock_cancel_message: " + "Got invalid msg len %d\n", (int)len)); + smb_panic("process_blocking_lock_cancel_message: bad msg\n"); + } + + memcpy(&blr, msg, sizeof(blr)); + memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS)); + + DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n", + nt_errstr(err) )); + + blocking_lock_reply_error(blr, err); + DLIST_REMOVE(blocking_lock_cancelled_queue, blr); + free_blocking_lock_record(blr); +} + +/**************************************************************************** + Send ourselves a blocking lock cancelled message. Handled asynchronously above. +*****************************************************************************/ + +BOOL blocking_lock_cancel(files_struct *fsp, + uint32 lock_pid, + SMB_BIG_UINT offset, + SMB_BIG_UINT count, + enum brl_flavour lock_flav, + unsigned char locktype, + NTSTATUS err) +{ + static BOOL initialized; + char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE]; + blocking_lock_record *blr; + + if (!initialized) { + /* Register our message. */ + message_register(MSG_SMB_BLOCKING_LOCK_CANCEL, + process_blocking_lock_cancel_message); + + initialized = True; + } + + for (blr = blocking_lock_queue; blr; blr = blr->next) { + if (fsp == blr->fsp && + lock_pid == blr->lock_pid && + offset == blr->offset && + count == blr->count && + lock_flav == blr->lock_flav) { + break; + } + } + + if (!blr) { + return False; + } + + /* Check the flags are right. */ + if (blr->com_type == SMBlockingX && + (locktype & LOCKING_ANDX_LARGE_FILES) != + (CVAL(blr->inbuf,smb_vwv3) & LOCKING_ANDX_LARGE_FILES)) { + return False; + } + + /* Move to cancelled queue. */ + DLIST_REMOVE(blocking_lock_queue, blr); + DLIST_ADD(blocking_lock_cancelled_queue, blr); + + /* Create the message. */ + memcpy(msg, &blr, sizeof(blr)); + memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS)); + + /* Don't need to be root here as we're only ever + sending to ourselves. */ + + message_send_pid(pid_to_procid(sys_getpid()), + MSG_SMB_BLOCKING_LOCK_CANCEL, + &msg, sizeof(msg), True); + + return True; +} diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 8a63d3b227..08e4a24a56 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -268,8 +268,6 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) int err = 0; int err1 = 0; - remove_pending_lock_requests_by_fid(fsp); - if (fsp->aio_write_behind) { /* * If we're finishing write behind on a close we can get a write diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ff3c6832e4..ec618db3f8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2371,7 +2371,6 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length size_t numtoread; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); - BOOL my_lock_ctx = False; START_PROFILE(SMBlockread); CHECK_FSP(fsp,conn); @@ -2396,13 +2395,13 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * Note that the requested lock size is unaffected by max_recv. */ - status = do_lock_spin(fsp, - (uint32)SVAL(inbuf,smb_pid), - (SMB_BIG_UINT)numtoread, - (SMB_BIG_UINT)startpos, - WRITE_LOCK, - WINDOWS_LOCK, - &my_lock_ctx); + status = do_lock(fsp, + (uint32)SVAL(inbuf,smb_pid), + (SMB_BIG_UINT)numtoread, + (SMB_BIG_UINT)startpos, + WRITE_LOCK, + WINDOWS_LOCK, + 0 /* zero timeout. */); if (NT_STATUS_V(status)) { #if 0 @@ -2412,7 +2411,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * tester. JRA. */ - if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { + if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -3418,7 +3417,6 @@ int reply_lock(connection_struct *conn, SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); - BOOL my_lock_ctx = False; START_PROFILE(SMBlock); @@ -3432,17 +3430,18 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); - status = do_lock_spin(fsp, - (uint32)SVAL(inbuf,smb_pid), - count, - offset, - WRITE_LOCK, - WINDOWS_LOCK, - &my_lock_ctx); + status = do_lock(fsp, + (uint32)SVAL(inbuf,smb_pid), + count, + offset, + WRITE_LOCK, + WINDOWS_LOCK, + 0 /* zero timeout. */); + if (NT_STATUS_V(status)) { #if 0 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */ - if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { + if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it @@ -5228,7 +5227,6 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; BOOL err; - BOOL my_lock_ctx = False; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; START_PROFILE(SMBlockingX); @@ -5244,11 +5242,6 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks)); } - if (locktype & LOCKING_ANDX_CANCEL_LOCK) { - /* Need to make this like a cancel.... JRA. */ - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); - } - /* Check if this is an oplock break on a file we have granted an oplock on. */ @@ -5360,7 +5353,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, /* Setup the timeout in seconds. */ - lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000); + if (lp_blocking_locks(SNUM(conn))) { + lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000); + } else { + lock_timeout = 0; + } /* Now do any requested locks */ data += ((large_file_format ? 20 : 10)*num_ulocks); @@ -5369,7 +5366,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, of smb_lkrng structs */ for(i = 0; i < (int)num_locks; i++) { - enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK); + enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ? + READ_LOCK:WRITE_LOCK); lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); @@ -5387,31 +5385,54 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, (double)count, (unsigned int)lock_pid, fsp->fsp_name, (int)lock_timeout )); - status = do_lock_spin(fsp, + if (locktype & LOCKING_ANDX_CANCEL_LOCK) { + if (lp_blocking_locks(SNUM(conn))) { + + /* Schedule a message to ourselves to + remove the blocking lock record and + return the right error. */ + + if (!blocking_lock_cancel(fsp, + lock_pid, + offset, + count, + WINDOWS_LOCK, + locktype, + NT_STATUS_FILE_LOCK_CONFLICT)) { + END_PROFILE(SMBlockingX); + return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation)); + } + } + /* Remove a matching pending lock. */ + status = do_lock_cancel(fsp, + lock_pid, + count, + offset, + WINDOWS_LOCK); + } else { + status = do_lock(fsp, lock_pid, count, offset, lock_type, WINDOWS_LOCK, - &my_lock_ctx); + lock_timeout); - if (NT_STATUS_V(status)) { - /* - * Interesting fact found by IFSTEST /t - * LockOverlappedTest... Even if it's our own lock - * context, we need to wait here as there may be an - * unlock on the way. So I removed a "&& - * !my_lock_ctx" from the following if statement. JRA. - */ - if ((lock_timeout != 0) && - lp_blocking_locks(SNUM(conn)) && - ERROR_WAS_LOCK_DENIED(status)) { + if (NT_STATUS_V(status)) { /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. + * Interesting fact found by IFSTEST /t + * LockOverlappedTest... Even if it's our own lock + * context, we need to wait here as there may be an + * unlock on the way. JRA. */ - if(push_blocking_lock_request(inbuf, length, + if ((lock_timeout != 0) && + ERROR_WAS_LOCK_DENIED(status)) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, fsp, lock_timeout, i, @@ -5420,17 +5441,25 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, WINDOWS_LOCK, offset, count)) { - END_PROFILE(SMBlockingX); - return -1; + END_PROFILE(SMBlockingX); + return -1; + } } } - break; + } + + if (NT_STATUS_V(status)) { + END_PROFILE(SMBlockingX); + return ERROR_NT(status); } } /* If any of the above locks failed, then we must unlock all of the previous locks (X/Open spec). */ - if (i != num_locks && num_locks != 0) { + + if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) && + (i != num_locks) && + (num_locks != 0)) { /* * Ensure we don't do a remove on the lock that just failed, * as under POSIX rules, if we have a lock already there, we diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 43437469d7..329d5bb0a5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4505,7 +4505,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", uint32 lock_pid; BOOL lock_blocking; enum brl_type lock_type; - BOOL my_lock_ctx; if (fsp == NULL || fsp->fh->fd == -1) { return ERROR_NT(NT_STATUS_INVALID_HANDLE); @@ -4564,8 +4563,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", count, offset, lock_type, - POSIX_LOCK, - &my_lock_ctx); + POSIX_LOCK); if (lock_blocking && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { /* -- cgit From 8d6c41a75a762a370835c9cc06500f0f3c1d15e3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Jul 2006 21:24:56 +0000 Subject: r17100: Ooops. Fix the build... Jeremy. (This used to be commit b21ca265a25b3d1e4f154ce0ee4b8757b41cf910) --- source3/smbd/trans2.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 329d5bb0a5..199204684f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4503,7 +4503,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", SMB_BIG_UINT count; SMB_BIG_UINT offset; uint32 lock_pid; - BOOL lock_blocking; + BOOL lock_blocking = False; enum brl_type lock_type; if (fsp == NULL || fsp->fh->fd == -1) { @@ -4540,6 +4540,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + if (!lp_blocking_locks(SNUM(conn))) { + lock_blocking = False; + } + lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); #if defined(HAVE_LONGLONG) offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | @@ -4563,9 +4567,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", count, offset, lock_type, + lock_blocking ? -1 : 0, POSIX_LOCK); - if (lock_blocking && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { + if (lock_blocking && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it -- cgit From b737f26764cce935d9482335ece11c71a96720f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Jul 2006 01:05:51 +0000 Subject: r17105: Fix the race Volker found - we had a non-locked region between detecting a pending lock was needed and when we added the blocking lock record. Make sure that we hold the lock over all this period. Removed the old code for doing blocking locks on SMB requests that never block (the old SMBlock and friends). Discovered something interesting about the strange NT_STATUS_FILE_LOCK_CONFLICT return. If we asked for a lock with zero timeout, and we got an error of NT_STATUS_FILE_LOCK_CONFLICT, treat it as though it was a blocking lock with a timeout of 150 - 300ms. This only happens when timeout is sent as zero and can be seen quite clearly in ethereal. This is the real replacement for old do_lock_spin() code. Re-worked the blocking lock select timeout to correctly use milliseconds instead of the old second level resolution (far too coarse for this work). Jeremy. (This used to be commit b81d6d1ae95a3d3e449dde629884b565eac289d9) --- source3/smbd/blocking.c | 261 ++++++++++++------------------------------------ source3/smbd/process.c | 13 +-- source3/smbd/reply.c | 134 ++++++++++--------------- source3/smbd/trans2.c | 32 +++--- 4 files changed, 142 insertions(+), 298 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 941e87d3ad..a0b93f5032 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -32,7 +32,7 @@ typedef struct _blocking_lock_record { struct _blocking_lock_record *prev; int com_type; files_struct *fsp; - time_t expire_time; + struct timeval expire_time; int lock_num; SMB_BIG_UINT offset; SMB_BIG_UINT count; @@ -75,7 +75,8 @@ static void received_unlock_msg(int msg_type, struct process_id src, Function to push a blocking lock request onto the lock queue. ****************************************************************************/ -BOOL push_blocking_lock_request( char *inbuf, int length, +BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, + char *inbuf, int length, files_struct *fsp, int lock_timeout, int lock_num, @@ -86,7 +87,6 @@ BOOL push_blocking_lock_request( char *inbuf, int length, { static BOOL set_lock_msg; blocking_lock_record *blr, *tmp; - struct byte_range_lock *br_lck = NULL; NTSTATUS status; if(in_chained_smb() ) { @@ -115,7 +115,13 @@ BOOL push_blocking_lock_request( char *inbuf, int length, blr->com_type = CVAL(inbuf,smb_com); blr->fsp = fsp; - blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + if (lock_timeout == -1) { + blr->expire_time.tv_sec = 0; + blr->expire_time.tv_usec = 0; /* Never expire. */ + } else { + blr->expire_time = timeval_current_ofs(lock_timeout/1000, + (lock_timeout % 1000) * 1000); + } blr->lock_num = lock_num; blr->lock_pid = lock_pid; blr->lock_flav = lock_flav; @@ -125,13 +131,6 @@ BOOL push_blocking_lock_request( char *inbuf, int length, memcpy(blr->inbuf, inbuf, length); blr->length = length; - br_lck = brl_get_locks(NULL, blr->fsp); - if (!br_lck) { - DLIST_REMOVE(blocking_lock_queue, blr); - free_blocking_lock_record(blr); - return False; - } - /* Add a pending lock record for this. */ status = brl_lock(br_lck, lock_pid, @@ -140,8 +139,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, count, PENDING_LOCK, blr->lock_flav, - lock_timeout); - TALLOC_FREE(br_lck); + lock_timeout ? True : False); /* blocking_lock. */ if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -158,8 +156,10 @@ BOOL push_blocking_lock_request( char *inbuf, int length, set_lock_msg = True; } - DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ -for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with " + "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n", + length, (unsigned int)blr->expire_time.tv_sec, + (unsigned int)blr->expire_time.tv_usec, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ @@ -305,13 +305,6 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status) { switch(blr->com_type) { -#if 0 - /* We no longer push blocking lock requests for anything but lockingX and trans2. */ - case SMBlock: - case SMBlockread: - generic_blocking_lock_error(blr, status); - break; -#endif case SMBlockingX: reply_lockingX_error(blr, status); break; @@ -337,146 +330,6 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status } } -#if 0 -/* We no longer push blocking lock requests for anything but lockingX and trans2. */ - -/**************************************************************************** - Attempt to finish off getting all pending blocking locks for a lockread call. - Returns True if we want to be removed from the list. -*****************************************************************************/ - -static BOOL process_lockread(blocking_lock_record *blr) -{ - char *outbuf = get_OutBuffer(); - char *inbuf = blr->inbuf; - ssize_t nread = -1; - char *data, *p; - int outsize = 0; - SMB_BIG_UINT startpos; - size_t numtoread; - NTSTATUS status; - files_struct *fsp = blr->fsp; - - numtoread = SVAL(inbuf,smb_vwv1); - startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2); - - numtoread = MIN(BUFFER_SIZE-outsize,numtoread); - data = smb_buf(outbuf) + 3; - - status = do_lock(fsp, - (uint32)SVAL(inbuf,smb_pid), - (SMB_BIG_UINT)numtoread, - startpos, - READ_LOCK, - WINDOWS_LOCK, - (int32)-1); - - if (NT_STATUS_V(status)) { - if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && - !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { - /* - * We have other than a "can't get lock" - * error. Send an error. - * Return True so we get dequeued. - */ - generic_blocking_lock_error(blr, status); - return True; - } - - /* - * Still waiting for lock.... - */ - - DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n", - fsp->fsp_name)); - return False; - } - - nread = read_file(fsp,data,startpos,numtoread); - - if (nread < 0) { - generic_blocking_lock_error(blr,NT_STATUS_ACCESS_DENIED); - return True; - } - - construct_reply_common(inbuf, outbuf); - outsize = set_message(outbuf,5,0,True); - - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - p = smb_buf(outbuf); - *p++ = 1; - SSVAL(p,0,nread); p += 2; - set_message_end(outbuf, p+nread); - - DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%lu nread=%ld\n", - fsp->fsp_name, fsp->fnum, (unsigned long)numtoread, (long)nread ) ); - - send_blocking_reply(outbuf,outsize); - return True; -} - -/**************************************************************************** - Attempt to finish off getting all pending blocking locks for a lock call. - Returns True if we want to be removed from the list. -*****************************************************************************/ - -static BOOL process_lock(blocking_lock_record *blr) -{ - char *outbuf = get_OutBuffer(); - char *inbuf = blr->inbuf; - int outsize; - SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; - NTSTATUS status; - files_struct *fsp = blr->fsp; - - count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); - offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); - - errno = 0; - status = do_lock(fsp, - (uint32)SVAL(inbuf,smb_pid), - count, - offset, - WRITE_LOCK, - WINDOWS_LOCK, - (int32)-1); - - if (NT_STATUS_IS_ERR(status)) { - if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && - !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { - /* - * We have other than a "can't get lock" - * error. Send an error. - * Return True so we get dequeued. - */ - - blocking_lock_reply_error(blr, status); - return True; - } - /* - * Still can't get the lock - keep waiting. - */ - DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n", - fsp->fsp_name)); - return False; - } - - /* - * Success - we got the lock. - */ - - DEBUG(3,("process_lock : file=%s fnum=%d offset=%.0f count=%.0f\n", - fsp->fsp_name, fsp->fnum, (double)offset, (double)count)); - - construct_reply_common(inbuf, outbuf); - outsize = set_message(outbuf,0,0,True); - send_blocking_reply(outbuf,outsize); - return True; -} -#endif - /**************************************************************************** Attempt to finish off getting all pending blocking locks for a lockingX call. Returns True if we want to be removed from the list. @@ -501,8 +354,9 @@ static BOOL process_lockingX(blocking_lock_record *blr) * Data now points at the beginning of the list * of smb_lkrng structs. */ - + for(; blr->lock_num < num_locks; blr->lock_num++) { + struct byte_range_lock *br_lck = NULL; BOOL err; lock_pid = get_lock_pid( data, blr->lock_num, large_file_format); @@ -514,14 +368,17 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - status = do_lock(fsp, + br_lck = do_lock(fsp, lock_pid, count, offset, ((locktype & LOCKING_ANDX_SHARED_LOCK) ? READ_LOCK : WRITE_LOCK), WINDOWS_LOCK, - (int32)-1); + True, + &status); + + TALLOC_FREE(br_lck); if (NT_STATUS_IS_ERR(status)) { break; @@ -573,14 +430,15 @@ static BOOL process_trans2(blocking_lock_record *blr) char *outbuf; char params[2]; NTSTATUS status; - - status = do_lock(blr->fsp, - blr->lock_pid, - blr->count, - blr->offset, - blr->lock_type, - blr->lock_flav, - (int32)-1); + struct byte_range_lock *br_lck = do_lock(blr->fsp, + blr->lock_pid, + blr->count, + blr->offset, + blr->lock_type, + blr->lock_flav, + True, + &status); + TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { if (ERROR_WAS_LOCK_DENIED(status)) { @@ -613,13 +471,6 @@ static BOOL process_trans2(blocking_lock_record *blr) static BOOL blocking_lock_record_process(blocking_lock_record *blr) { switch(blr->com_type) { -#if 0 - /* We no longer push blocking lock requests for anything but lockingX and trans2. */ - case SMBlock: - return process_lock(blr); - case SMBlockread: - return process_lockread(blr); -#endif case SMBlockingX: return process_lockingX(blr); case SMBtrans2: @@ -714,44 +565,60 @@ static void received_unlock_msg(int msg_type, struct process_id src, void *buf, size_t len) { DEBUG(10,("received_unlock_msg\n")); - process_blocking_lock_queue(time(NULL)); + process_blocking_lock_queue(); } /**************************************************************************** - Return the number of seconds to the next blocking locks timeout, or default_timeout + Return the number of milliseconds to the next blocking locks timeout, or default_timeout *****************************************************************************/ -unsigned blocking_locks_timeout(unsigned default_timeout) +unsigned int blocking_locks_timeout_ms(unsigned int default_timeout_ms) { - unsigned timeout = default_timeout; - time_t t; + unsigned int timeout_ms = default_timeout_ms; + struct timeval tv_curr; + SMB_BIG_INT min_tv_dif_us = 0x7FFFFFFF; /* A large +ve number. */ blocking_lock_record *blr = blocking_lock_queue; - /* note that we avoid the time() syscall if there are no blocking locks */ - if (!blr) - return timeout; + /* note that we avoid the GetTimeOfDay() syscall if there are no blocking locks */ + if (!blr) { + return timeout_ms; + } - t = time(NULL); + tv_curr = timeval_current(); for (; blr; blr = blr->next) { - if ((blr->expire_time != (time_t)-1) && - (timeout > (blr->expire_time - t))) { - timeout = blr->expire_time - t; + SMB_BIG_INT tv_dif_us; + + if (timeval_is_zero(&blr->expire_time)) { + continue; /* Never timeout. */ } + + tv_dif_us = usec_time_diff(&blr->expire_time, &tv_curr); + min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us); + } + + if (min_tv_dif_us < 0) { + min_tv_dif_us = 0; + } + + timeout_ms = (unsigned int)(min_tv_dif_us / (SMB_BIG_INT)1000); + + if (timeout_ms < 1) { + timeout_ms = 1; } - if (timeout < 1) - timeout = 1; + DEBUG(10,("blocking_locks_timeout_ms: returning %u\n", timeout_ms)); - return timeout; + return timeout_ms; } /**************************************************************************** Process the blocking lock queue. Note that this is only called as root. *****************************************************************************/ -void process_blocking_lock_queue(time_t t) +void process_blocking_lock_queue(void) { + struct timeval tv_curr = timeval_current(); blocking_lock_record *blr, *next = NULL; /* @@ -780,7 +647,7 @@ void process_blocking_lock_queue(time_t t) DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", fsp->fnum, fsp->fsp_name )); - if((blr->expire_time != -1) && (blr->expire_time <= t)) { + if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ce352adfd7..f8c66d93ea 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1276,7 +1276,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) } /**************************************************************************** - Setup the needed select timeout. + Setup the needed select timeout in milliseconds. ****************************************************************************/ static int setup_select_timeout(void) @@ -1284,16 +1284,17 @@ static int setup_select_timeout(void) int select_timeout; int t; - select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT); - select_timeout *= 1000; + select_timeout = blocking_locks_timeout_ms(SMBD_SELECT_TIMEOUT*1000); t = change_notify_timeout(); DEBUG(10, ("change_notify_timeout: %d\n", t)); - if (t != -1) + if (t != -1) { select_timeout = MIN(select_timeout, t*1000); + } - if (print_notify_messages_pending()) + if (print_notify_messages_pending()) { select_timeout = MIN(select_timeout, 1000); + } return select_timeout; } @@ -1482,7 +1483,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); * Check to see if we have any blocking locks * outstanding on the queue. */ - process_blocking_lock_queue(t); + process_blocking_lock_queue(); /* update printer queue caches if necessary */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec618db3f8..6176edb52d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2371,6 +2371,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length size_t numtoread; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + struct byte_range_lock *br_lck = NULL; START_PROFILE(SMBlockread); CHECK_FSP(fsp,conn); @@ -2395,42 +2396,17 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * Note that the requested lock size is unaffected by max_recv. */ - status = do_lock(fsp, + br_lck = do_lock(fsp, (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, WINDOWS_LOCK, - 0 /* zero timeout. */); + False, /* Non-blocking lock. */ + &status); + TALLOC_FREE(br_lck); if (NT_STATUS_V(status)) { -#if 0 - /* - * We used to make lockread a blocking lock. It turns out - * that this isn't on W2k. Found by the Samba 4 RAW-READ torture - * tester. JRA. - */ - - if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(inbuf, length, - fsp, - -1, - 0, - SVAL(inbuf,smb_pid), - WRITE_LOCK, - WINDOWS_LOCK, - (SMB_BIG_UINT)startpos, - (SMB_BIG_UINT)numtoread)) { - END_PROFILE(SMBlockread); - return -1; - } - } -#endif END_PROFILE(SMBlockread); return ERROR_NT(status); } @@ -3417,6 +3393,7 @@ int reply_lock(connection_struct *conn, SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + struct byte_range_lock *br_lck = NULL; START_PROFILE(SMBlock); @@ -3430,36 +3407,18 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); - status = do_lock(fsp, + br_lck = do_lock(fsp, (uint32)SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, WINDOWS_LOCK, - 0 /* zero timeout. */); + False, /* Non-blocking lock. */ + &status); + + TALLOC_FREE(br_lck); if (NT_STATUS_V(status)) { -#if 0 - /* Tests using Samba4 against W2K show this call never creates a blocking lock. */ - if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(inbuf, length, - fsp, - -1, - 0, - SVAL(inbuf,smb_pid), - WRITE_LOCK, - WINDOWS_LOCK, - offset, count)) { - END_PROFILE(SMBlock); - return -1; - } - } -#endif END_PROFILE(SMBlock); return ERROR_NT(status); } @@ -5353,9 +5312,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, /* Setup the timeout in seconds. */ - if (lp_blocking_locks(SNUM(conn))) { - lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000); - } else { + if (!lp_blocking_locks(SNUM(conn))) { lock_timeout = 0; } @@ -5410,42 +5367,57 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, offset, WINDOWS_LOCK); } else { - status = do_lock(fsp, + BOOL blocking_lock = lock_timeout ? True : False; + BOOL defer_lock = False; + struct byte_range_lock *br_lck; + + br_lck = do_lock(fsp, lock_pid, count, offset, lock_type, WINDOWS_LOCK, - lock_timeout); + blocking_lock, + &status); - if (NT_STATUS_V(status)) { + if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { + defer_lock = True; + } + + /* This heuristic seems to match W2K3 very well. If a + lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT + it pretends we asked for a timeout of between 150 - 300 milliseconds as + far as I can tell. Replacement for do_lock_spin(). JRA. */ + + if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock && + NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) { + defer_lock = True; + lock_timeout = 200; + } + + if (br_lck && defer_lock) { /* - * Interesting fact found by IFSTEST /t - * LockOverlappedTest... Even if it's our own lock - * context, we need to wait here as there may be an - * unlock on the way. JRA. + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. */ - if ((lock_timeout != 0) && - ERROR_WAS_LOCK_DENIED(status)) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(inbuf, length, - fsp, - lock_timeout, - i, - lock_pid, - lock_type, - WINDOWS_LOCK, - offset, - count)) { - END_PROFILE(SMBlockingX); - return -1; - } + if(push_blocking_lock_request(br_lck, + inbuf, length, + fsp, + lock_timeout, + i, + lock_pid, + lock_type, + WINDOWS_LOCK, + offset, + count)) { + TALLOC_FREE(br_lck); + END_PROFILE(SMBlockingX); + return -1; } } + + TALLOC_FREE(br_lck); } if (NT_STATUS_V(status)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 199204684f..5acce13e52 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4503,7 +4503,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", SMB_BIG_UINT count; SMB_BIG_UINT offset; uint32 lock_pid; - BOOL lock_blocking = False; + BOOL blocking_lock = False; enum brl_type lock_type; if (fsp == NULL || fsp->fh->fd == -1) { @@ -4533,15 +4533,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) { - lock_blocking = False; + blocking_lock = False; } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) { - lock_blocking = True; + blocking_lock = True; } else { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (!lp_blocking_locks(SNUM(conn))) { - lock_blocking = False; + blocking_lock = False; } lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); @@ -4562,21 +4562,23 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", offset, POSIX_LOCK); } else { - status = do_lock(fsp, - lock_pid, - count, - offset, - lock_type, - lock_blocking ? -1 : 0, - POSIX_LOCK); - - if (lock_blocking && ERROR_WAS_LOCK_DENIED(status)) { + struct byte_range_lock *br_lck = do_lock(fsp, + lock_pid, + count, + offset, + lock_type, + blocking_lock, + POSIX_LOCK, + &status); + + if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, + if(push_blocking_lock_request(br_lck, + inbuf, length, fsp, -1, /* infinite timeout. */ 0, @@ -4585,9 +4587,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", POSIX_LOCK, offset, count)) { + TALLOC_FREE(br_lck); return -1; } } + TALLOC_FREE(br_lck); } if (!NT_STATUS_IS_OK(status)) { -- cgit From a456a3130925e946975620131f75b7c82e8a096b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Jul 2006 01:17:54 +0000 Subject: r17106: Match Windows timing values on locks. Jeremy. (This used to be commit b5aaff665937313370e0e87225e146f9af7b7e67) --- source3/smbd/reply.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6176edb52d..bb79918675 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5381,6 +5381,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, &status); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { + /* Windows internal resolution for blocking locks seems + to be about 200ms... Don't wait for less than that. JRA. */ + if (lock_timeout != -1 && lock_timeout < 200) { + lock_timeout = 200; + } defer_lock = True; } -- cgit From 38af904c314396091de1062ec19591326abddec6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Jul 2006 01:20:26 +0000 Subject: r17107: Make the 200 ms timeout value tunable in local.h... Might need to be a parameter ? Jeremy. (This used to be commit 98d8d9399bb287319578daaf2a2fb42f3c48f858) --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bb79918675..f1ac098e7d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5383,8 +5383,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* Windows internal resolution for blocking locks seems to be about 200ms... Don't wait for less than that. JRA. */ - if (lock_timeout != -1 && lock_timeout < 200) { - lock_timeout = 200; + if (lock_timeout != -1 && lock_timeout < WINDOWS_MINIMUM_LOCK_TIMEOUT_MS) { + lock_timeout = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; } defer_lock = True; } @@ -5397,7 +5397,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock && NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) { defer_lock = True; - lock_timeout = 200; + lock_timeout = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; } if (br_lck && defer_lock) { -- cgit From 1cd8d56fdab18a0bcedffba6476f8208d2185040 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Jul 2006 01:29:43 +0000 Subject: r17108: Make the default timeout parameter for lock waiting be lp_lock_spin(). lock spin count is no longer used. I'll update the man pages. Jeremy. (This used to be commit 0451a170c9be88399202abd225af35ddc45023f0) --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f1ac098e7d..edaf5d8062 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5383,8 +5383,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* Windows internal resolution for blocking locks seems to be about 200ms... Don't wait for less than that. JRA. */ - if (lock_timeout != -1 && lock_timeout < WINDOWS_MINIMUM_LOCK_TIMEOUT_MS) { - lock_timeout = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; + if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) { + lock_timeout = lp_lock_spin_time(); } defer_lock = True; } @@ -5397,7 +5397,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock && NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) { defer_lock = True; - lock_timeout = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; + lock_timeout = lp_lock_spin_time(); } if (br_lck && defer_lock) { -- cgit From 0e292222c30c269c17e68acf1bbef787c1e946ed Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 00:13:28 +0000 Subject: r17125: Drastic problems require drastic solutions. There's no way to get all the cases where kernel oplocks are on and we can't open the file and get the correct semantics (think about the open with truncate with an attribute only open - we'd need a vfs change to add the truncate(fname, len) call). So always drop the share mode lock before doing any real fd opens and then re-acquire it afterwards. We're already dealing with the race in the create case, and we deal with any other races in the same way. Volker, please examine *carefully* :-). This should fix the problems people reported with kernel oplocks being on. Jeremy. (This used to be commit 8171c4c404e9f382880c65daa0232f89e560f399) --- source3/smbd/open.c | 149 ++++++++++++++++++------------------ source3/smbd/posix_acls.c | 188 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 228 insertions(+), 109 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c04cdbe7c..b13b4f2a6c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1403,6 +1403,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (!NT_STATUS_IS_OK(status)) { + uint32 can_access_mask; + BOOL can_access = True; SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); @@ -1434,29 +1436,20 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * MS-Access. If a file open will fail due to share * permissions and also for security (access) reasons, * we need to return the access failed error, not the - * share error. This means we must attempt to open the - * file anyway in order to get the UNIX access error - - * even if we're going to fail the open for share - * reasons. This is bad, as we're burning another fd - * if there are existing locks but there's nothing - * else we can do. We also ensure we're not going to - * create or tuncate the file as we only want an - * access decision at this stage. JRA. + * share error. We can't open the file due to kernel + * oplock deadlock (it's possible we failed above on + * the open_mode_check()) so use a userspace check. */ - errno = 0; - fsp_open = open_file(fsp,conn,fname,psbuf, - flags|(flags2&~(O_TRUNC|O_CREAT)), - unx_mode,access_mask); - - DEBUG(4,("open_file_ntcreate : share_mode deny - " - "calling open_file with flags=0x%X " - "flags2=0x%X mode=0%o returned %s\n", - flags, (flags2&~(O_TRUNC|O_CREAT)), - (unsigned int)unx_mode, nt_errstr(fsp_open))); - - if (!NT_STATUS_IS_OK(fsp_open) && errno) { - /* Default error. */ - status = NT_STATUS_ACCESS_DENIED; + + if (flags & O_RDWR) { + can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA; + } else { + can_access_mask = FILE_READ_DATA; + } + + if (((flags & O_RDWR) && !CAN_WRITE(conn)) || + !can_access_file(conn,fname,psbuf,can_access_mask)) { + can_access = False; } /* @@ -1503,13 +1496,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } TALLOC_FREE(lck); - if (NT_STATUS_IS_OK(fsp_open)) { - fd_close(conn, fsp); + if (can_access) { /* * We have detected a sharing violation here * so return the correct error code */ status = NT_STATUS_SHARING_VIOLATION; + } else { + status = NT_STATUS_ACCESS_DENIED; } file_free(fsp); return status; @@ -1536,6 +1530,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (unsigned int)flags, (unsigned int)flags2, (unsigned int)unx_mode)); + /* Drop the lock before doing any real file access. Allows kernel + oplock breaks to be processed. Handle any races after the open + call when we re-acquire the lock. */ + + if (lck) { + TALLOC_FREE(lck); + } + /* * open_file strips any O_TRUNC flags itself. */ @@ -1551,70 +1553,65 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return fsp_open; } - if (!file_existed) { - - /* - * Deal with the race condition where two smbd's detect the - * file doesn't exist and do the create at the same time. One - * of them will win and set a share mode, the other (ie. this - * one) should check if the requested share mode for this - * create is allowed. - */ - - /* - * Now the file exists and fsp is successfully opened, - * fsp->dev and fsp->inode are valid and should replace the - * dev=0,inode=0 from a non existent file. Spotted by - * Nadav Danieli . JRA. - */ + /* + * Deal with the race condition where two smbd's detect the + * file doesn't exist and do the create at the same time. One + * of them will win and set a share mode, the other (ie. this + * one) should check if the requested share mode for this + * create is allowed. + */ - dev = fsp->dev; - inode = fsp->inode; + /* + * Now the file exists and fsp is successfully opened, + * fsp->dev and fsp->inode are valid and should replace the + * dev=0,inode=0 from a non existent file. Spotted by + * Nadav Danieli . JRA. + */ - lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + dev = fsp->dev; + inode = fsp->inode; - if (lck == NULL) { - DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); - fd_close(conn, fsp); - file_free(fsp); - return NT_STATUS_SHARING_VIOLATION; - } + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); - status = open_mode_check(conn, fname, lck, - access_mask, share_access, - create_options, &file_existed); + if (lck == NULL) { + DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } - if (!NT_STATUS_IS_OK(status)) { - struct deferred_open_record state; + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); - fd_close(conn, fsp); - file_free(fsp); + if (!NT_STATUS_IS_OK(status)) { + struct deferred_open_record state; - state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + fd_close(conn, fsp); + file_free(fsp); - /* Do it all over again immediately. In the second - * round we will find that the file existed and handle - * the DELETE_PENDING and FCB cases correctly. No need - * to duplicate the code here. Essentially this is a - * "goto top of this function", but don't tell - * anybody... */ + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; - defer_open(lck, request_time, timeval_zero(), - &state); - TALLOC_FREE(lck); - return status; - } + /* Do it all over again immediately. In the second + * round we will find that the file existed and handle + * the DELETE_PENDING and FCB cases correctly. No need + * to duplicate the code here. Essentially this is a + * "goto top of this function", but don't tell + * anybody... */ - /* - * We exit this block with the share entry *locked*..... - */ + defer_open(lck, request_time, timeval_zero(), + &state); + TALLOC_FREE(lck); + return status; } - SMB_ASSERT(lck != NULL); + /* + * The share entry is again *locked*..... + */ /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 73744cf26e..d265057ac0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3911,7 +3911,7 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * Return -1 if no match, 0 if match and denied, 1 if match and allowed. ****************************************************************************/ -static int check_posix_acl_group_write(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +static int check_posix_acl_group_access(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) { SMB_ACL_T posix_acl = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; @@ -3922,17 +3922,21 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam int ret = -1; gid_t cu_gid; + DEBUG(10,("check_posix_acl_group_access: requesting 0x%x on file %s\n", + (unsigned int)access_mask, fname )); + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS)) == NULL) { goto check_stat; } - /* First ensure the group mask allows group read. */ + /* First ensure the group mask allows group access. */ /* Also check any user entries (these take preference over group). */ while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; int have_write = -1; + int have_read = -1; /* get_next... */ if (entry_id == SMB_ACL_FIRST_ENTRY) @@ -3946,6 +3950,11 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam goto check_stat; } + have_read = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ); + if (have_read == -1) { + goto check_stat; + } + have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE); if (have_write == -1) { goto check_stat; @@ -3956,16 +3965,36 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam * canonicalize to 0 or 1. */ have_write = (have_write ? 1 : 0); + have_read = (have_read ? 1 : 0); switch(tagtype) { case SMB_ACL_MASK: seen_mask = True; - if (!have_write) { - /* We don't have any group or explicit user write permission. */ - ret = -1; /* Allow caller to check "other" permissions. */ - DEBUG(10,("check_posix_acl_group_write: file %s \ -refusing write due to mask.\n", fname)); - goto done; + switch (access_mask) { + case FILE_READ_DATA: + if (!have_read) { + ret = -1; + DEBUG(10,("check_posix_acl_group_access: file %s " + "refusing read due to mask.\n", fname)); + goto done; + } + break; + case FILE_WRITE_DATA: + if (!have_write) { + ret = -1; + DEBUG(10,("check_posix_acl_group_access: file %s " + "refusing write due to mask.\n", fname)); + goto done; + } + break; + default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + if (!have_write || !have_read) { + ret = -1; + DEBUG(10,("check_posix_acl_group_access: file %s " + "refusing read/write due to mask.\n", fname)); + goto done; + } + break; } break; case SMB_ACL_USER: @@ -3977,9 +4006,21 @@ refusing write due to mask.\n", fname)); } if (current_user.ut.uid == *puid) { /* We have a uid match but we must ensure we have seen the acl mask. */ - ret = have_write; - DEBUG(10,("check_posix_acl_group_write: file %s \ -match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "cannot write")); + switch (access_mask) { + case FILE_READ_DATA: + ret = have_read; + break; + case FILE_WRITE_DATA: + ret = have_write; + break; + default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + ret = (have_write & have_read); + break; + } + DEBUG(10,("check_posix_acl_group_access: file %s " + "match on user %u -> %s.\n", + fname, (unsigned int)*puid, + ret ? "can access" : "cannot access")); if (seen_mask) { goto done; } @@ -4002,6 +4043,7 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; int have_write = -1; + int have_read = -1; /* get_next... */ if (entry_id == SMB_ACL_FIRST_ENTRY) @@ -4015,6 +4057,11 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can goto check_stat; } + have_read = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ); + if (have_read == -1) { + goto check_stat; + } + have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE); if (have_write == -1) { goto check_stat; @@ -4025,6 +4072,7 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can * canonicalize to 0 or 1. */ have_write = (have_write ? 1 : 0); + have_read = (have_read ? 1 : 0); switch(tagtype) { case SMB_ACL_GROUP: @@ -4049,13 +4097,25 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; cu_gid = get_current_user_gid_next(&i)) { if (cu_gid == *pgid) { - ret = have_write; - DEBUG(10,("check_posix_acl_group_write: file %s \ -match on group %u -> can write.\n", fname, (unsigned int)cu_gid )); + switch (access_mask) { + case FILE_READ_DATA: + ret = have_read; + break; + case FILE_WRITE_DATA: + ret = have_write; + break; + default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + ret = (have_write & have_read); + break; + } - /* If we don't have write permission this entry doesn't + DEBUG(10,("check_posix_acl_group_access: file %s " + "match on group %u -> can access.\n", + fname, (unsigned int)cu_gid )); + + /* If we don't have access permission this entry doesn't terminate the enumeration of the entries. */ - if (have_write) { + if (ret) { goto done; } /* But does terminate the group iteration. */ @@ -4072,12 +4132,12 @@ match on group %u -> can write.\n", fname, (unsigned int)cu_gid )); /* If ret is -1 here we didn't match on the user entry or supplemental group entries. */ - DEBUG(10,("check_posix_acl_group_write: ret = %d before check_stat:\n", ret)); + DEBUG(10,("check_posix_acl_group_access: ret = %d before check_stat:\n", ret)); check_stat: /* - * We only check the S_IWGRP permissions if we haven't already + * We only check the S_I[RW]GRP permissions if we haven't already * seen an owning group SMB_ACL_GROUP_OBJ ace entry. If there is an * SMB_ACL_GROUP_OBJ ace entry then the group bits in st_gid are * the same as the SMB_ACL_MASK bits, not the SMB_ACL_GROUP_OBJ @@ -4094,16 +4154,33 @@ match on group %u -> can write.\n", fname, (unsigned int)cu_gid )); for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; cu_gid = get_current_user_gid_next(&i)) { if (cu_gid == psbuf->st_gid) { - ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; - DEBUG(10,("check_posix_acl_group_write: file %s \ -match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write")); + switch (access_mask) { + case FILE_READ_DATA: + ret = (psbuf->st_mode & S_IRGRP) ? 1 : 0; + break; + case FILE_WRITE_DATA: + ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; + break; + default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + if ((psbuf->st_mode & (S_IWGRP|S_IRGRP)) == (S_IWGRP|S_IRGRP)) { + ret = 1; + } else { + ret = 0; + } + break; + } + DEBUG(10,("check_posix_acl_group_access: file %s " + "match on owning group %u -> %s.\n", + fname, (unsigned int)psbuf->st_gid, + ret ? "can access" : "cannot access")); break; } } if (cu_gid == (gid_t)-1) { - DEBUG(10,("check_posix_acl_group_write: file %s \ -failed to match on user or group in token (ret = %d).\n", fname, ret )); + DEBUG(10,("check_posix_acl_group_access: file %s " + "failed to match on user or group in token (ret = %d).\n", + fname, ret )); } } @@ -4113,7 +4190,7 @@ failed to match on user or group in token (ret = %d).\n", fname, ret )); SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); } - DEBUG(10,("check_posix_acl_group_write: file %s returning (ret = %d).\n", fname, ret )); + DEBUG(10,("check_posix_acl_group_access: file %s returning (ret = %d).\n", fname, ret )); return ret; } @@ -4169,7 +4246,7 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) #endif /* Check group or explicit user acl entry write access. */ - ret = check_posix_acl_group_write(conn, dname, &sbuf); + ret = check_posix_acl_group_access(conn, dname, &sbuf, FILE_WRITE_DATA); if (ret == 0 || ret == 1) { return ret ? True : False; } @@ -4179,15 +4256,23 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) } /**************************************************************************** - Actually emulate the in-kernel access checking for write access. We need + Actually emulate the in-kernel access checking for read/write access. We need this to successfully check for ability to write for dos filetimes. Note this doesn't take into account share write permissions. ****************************************************************************/ -BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +BOOL can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) { int ret; + if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) { + return False; + } + access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA); + + DEBUG(10,("can_access_file: requesting 0x%x on file %s\n", + (unsigned int)access_mask, fname )); + if (current_user.ut.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; @@ -4200,19 +4285,56 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST } } - /* Check primary owner write access. */ + /* Check primary owner access. */ if (current_user.ut.uid == psbuf->st_uid) { - return (psbuf->st_mode & S_IWUSR) ? True : False; + switch (access_mask) { + case FILE_READ_DATA: + return (psbuf->st_mode & S_IRUSR) ? True : False; + + case FILE_WRITE_DATA: + return (psbuf->st_mode & S_IWUSR) ? True : False; + + default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + + if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) { + return True; + } else { + return False; + } + } } - /* Check group or explicit user acl entry write access. */ - ret = check_posix_acl_group_write(conn, fname, psbuf); + /* Check group or explicit user acl entry access. */ + ret = check_posix_acl_group_access(conn, fname, psbuf, access_mask); if (ret == 0 || ret == 1) { return ret ? True : False; } - /* Finally check other write access. */ - return (psbuf->st_mode & S_IWOTH) ? True : False; + /* Finally check other access. */ + switch (access_mask) { + case FILE_READ_DATA: + return (psbuf->st_mode & S_IROTH) ? True : False; + + case FILE_WRITE_DATA: + return (psbuf->st_mode & S_IWOTH) ? True : False; + + default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + + if ((psbuf->st_mode & (S_IWOTH|S_IROTH)) == (S_IWOTH|S_IROTH)) { + return True; + } + } + return False; +} + +/**************************************************************************** + Userspace check for write access. + Note this doesn't take into account share write permissions. +****************************************************************************/ + +BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +{ + return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA); } /******************************************************************** -- cgit From 4815e2c3441ce2cb18aa7fcb9ae1fe97bbcabd80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 01:30:30 +0000 Subject: r17128: Missed a logic error in my last patch. Ensure we deal with any oplocks that were granted when we had released the lock. Fix strange case where stat open grants a batch oplock on file create, but grants no oplock on file open. Jeremy. (This used to be commit b7374835e6ec0c98fc4020623f0a37c0c173b8aa) --- source3/smbd/open.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b13b4f2a6c..2c259e7822 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -623,8 +623,11 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL delay_it = False; BOOL have_level2 = False; - if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { + if (oplock_request & INTERNAL_OPEN_ONLY) { fsp->oplock_type = NO_OPLOCK; + } + + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { return False; } @@ -1582,10 +1585,43 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } + /* + * The share entry is again *locked*..... + */ + + /* First pass - send break only on batch oplocks. */ + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { + schedule_defer_open(lck, request_time); + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return NT_STATUS_SHARING_VIOLATION; + } + status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); + if (NT_STATUS_IS_OK(status)) { + /* We might be going to allow this open. Check oplock status again. */ + /* Second pass - send break for both batch or exclusive oplocks. */ + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { + schedule_defer_open(lck, request_time); + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return NT_STATUS_SHARING_VIOLATION; + } + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + /* DELETE_PENDING is not deferred for a second */ + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return status; + } + if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; @@ -1609,10 +1645,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - /* - * The share entry is again *locked*..... - */ - /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of these only read them. Nobody but Samba can ever set a deny @@ -1653,6 +1685,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->access_mask = access_mask; if (file_existed) { + /* stat opens on existing files don't get oplocks. */ + if (is_stat_open(fsp->access_mask)) { + fsp->oplock_type = NO_OPLOCK; + } + if (!(flags2 & O_TRUNC)) { info = FILE_WAS_OPENED; } else { -- cgit From addc07be7ddc0b82dd2aa7dbb07dd6277d3e4dc9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 05:26:51 +0000 Subject: r17130: Remove unneeded unlock call. Jeremy. (This used to be commit b3b5aec0eef3bdcae75ce79ffd3ecf21fb1279e7) --- source3/smbd/open.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2c259e7822..53178956cd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1549,9 +1549,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { - if (lck != NULL) { - TALLOC_FREE(lck); - } file_free(fsp); return fsp_open; } -- cgit From 48e1e45183270e2d56248c69e471bbcef816de08 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 05:32:12 +0000 Subject: r17131: Optimisation - when doing a stat open don't open the file unless we really have to (ie. O_CREAT and file doesn't exist). Jeremy. (This used to be commit 788aa15ea24e6dfb61820465b5b881829a64297a) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 53178956cd..4033243888 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -245,7 +245,7 @@ static NTSTATUS open_file(files_struct *fsp, } if ((access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || - (local_flags & O_CREAT) || + (!file_existed && (local_flags & O_CREAT)) || ((local_flags & O_TRUNC) == O_TRUNC) ) { /* -- cgit From 5faee071cb698e64d46b4f72b817c4449b8751da Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Jul 2006 10:42:50 +0000 Subject: r17134: Fix a debug message (This used to be commit 40e267981174840f4f36d1863985ee010ef5074a) --- source3/smbd/oplock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e4f5c434b0..99ce79296f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -859,7 +859,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) BOOL init_oplocks(void) { - DEBUG(3,("open_oplock_ipc: initializing messages.\n")); + DEBUG(3,("init_oplocks: initializing messages.\n")); message_register(MSG_SMB_BREAK_REQUEST, process_oplock_break_message); -- cgit From dada5b4853ec7d7346e075ae0718eea9e64cb7b6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 18:34:19 +0000 Subject: r17140: Get rid of the lock release/reacquire code ! Turns out that create dispositions that cause O_TRUNC break oplocks. This simplifies the code - although we have to keep separate the client requested access mask and the access mask we actually use to open the file. Jeremy. (This used to be commit 3bcd52a4752ec6c2a8f678afa3b7b3646103ad60) --- source3/smbd/open.c | 158 ++++++++++++++++++++++++---------------------------- 1 file changed, 73 insertions(+), 85 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4033243888..2abd367597 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1117,6 +1117,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint16 mid = get_current_mid(); struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; + uint32 open_access_mask = access_mask; NTSTATUS status; if (conn->printer) { @@ -1208,12 +1209,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OVERWRITE_IF: /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OPEN: @@ -1238,6 +1241,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags2 |= O_TRUNC; + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_CREATE: @@ -1289,7 +1293,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* This is a nasty hack - must fix... JRA. */ if (access_mask == MAXIMUM_ALLOWED_ACCESS) { - access_mask = FILE_GENERIC_ALL; + open_access_mask = access_mask = FILE_GENERIC_ALL; + if (flags2 & O_TRUNC) { + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ + } } /* @@ -1353,7 +1360,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->inode = psbuf->st_ino; fsp->share_access = share_access; fsp->fh->private_options = create_options; - fsp->access_mask = access_mask; + fsp->access_mask = open_access_mask; /* We change this to the requested access_mask after the open is done. */ /* Ensure no SAMBA_PRIVATE bits can be set. */ fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); @@ -1383,6 +1390,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } + /* Use the client requested access mask here, not the one we open with. */ status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); @@ -1417,6 +1425,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { files_struct *fsp_dup; + + /* Use the client requested access mask here, not the one we open with. */ fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, access_mask, share_access, @@ -1533,115 +1543,93 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (unsigned int)flags, (unsigned int)flags2, (unsigned int)unx_mode)); - /* Drop the lock before doing any real file access. Allows kernel - oplock breaks to be processed. Handle any races after the open - call when we re-acquire the lock. */ - - if (lck) { - TALLOC_FREE(lck); - } - /* * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, - access_mask); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { + if (lck != NULL) { + TALLOC_FREE(lck); + } file_free(fsp); return fsp_open; } - /* - * Deal with the race condition where two smbd's detect the - * file doesn't exist and do the create at the same time. One - * of them will win and set a share mode, the other (ie. this - * one) should check if the requested share mode for this - * create is allowed. - */ - - /* - * Now the file exists and fsp is successfully opened, - * fsp->dev and fsp->inode are valid and should replace the - * dev=0,inode=0 from a non existent file. Spotted by - * Nadav Danieli . JRA. - */ - - dev = fsp->dev; - inode = fsp->inode; - - lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + if (!file_existed) { - if (lck == NULL) { - DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); - fd_close(conn, fsp); - file_free(fsp); - return NT_STATUS_SHARING_VIOLATION; - } + /* + * Deal with the race condition where two smbd's detect the + * file doesn't exist and do the create at the same time. One + * of them will win and set a share mode, the other (ie. this + * one) should check if the requested share mode for this + * create is allowed. + */ - /* - * The share entry is again *locked*..... - */ + /* + * Now the file exists and fsp is successfully opened, + * fsp->dev and fsp->inode are valid and should replace the + * dev=0,inode=0 from a non existent file. Spotted by + * Nadav Danieli . JRA. + */ - /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { - schedule_defer_open(lck, request_time); - fd_close(conn, fsp); - file_free(fsp); - TALLOC_FREE(lck); - return NT_STATUS_SHARING_VIOLATION; - } + dev = fsp->dev; + inode = fsp->inode; - status = open_mode_check(conn, fname, lck, - access_mask, share_access, - create_options, &file_existed); + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); - if (NT_STATUS_IS_OK(status)) { - /* We might be going to allow this open. Check oplock status again. */ - /* Second pass - send break for both batch or exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); + if (lck == NULL) { + DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); - TALLOC_FREE(lck); return NT_STATUS_SHARING_VIOLATION; } - } - if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { - /* DELETE_PENDING is not deferred for a second */ - fd_close(conn, fsp); - file_free(fsp); - TALLOC_FREE(lck); - return status; - } + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); - if (!NT_STATUS_IS_OK(status)) { - struct deferred_open_record state; + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + /* DELETE_PENDING is not deferred for a second */ + TALLOC_FREE(lck); + file_free(fsp); + return status; + } - fd_close(conn, fsp); - file_free(fsp); + if (!NT_STATUS_IS_OK(status)) { + struct deferred_open_record state; - state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + fd_close(conn, fsp); + file_free(fsp); - /* Do it all over again immediately. In the second - * round we will find that the file existed and handle - * the DELETE_PENDING and FCB cases correctly. No need - * to duplicate the code here. Essentially this is a - * "goto top of this function", but don't tell - * anybody... */ + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + /* Do it all over again immediately. In the second + * round we will find that the file existed and handle + * the DELETE_PENDING and FCB cases correctly. No need + * to duplicate the code here. Essentially this is a + * "goto top of this function", but don't tell + * anybody... */ + + defer_open(lck, request_time, timeval_zero(), + &state); + TALLOC_FREE(lck); + return status; + } + + /* + * We exit this block with the share entry *locked*..... + */ - defer_open(lck, request_time, timeval_zero(), - &state); - TALLOC_FREE(lck); - return status; } + SMB_ASSERT(lck != NULL); + /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of these only read them. Nobody but Samba can ever set a deny @@ -1683,7 +1671,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (file_existed) { /* stat opens on existing files don't get oplocks. */ - if (is_stat_open(fsp->access_mask)) { + if (is_stat_open(open_access_mask)) { fsp->oplock_type = NO_OPLOCK; } -- cgit From 201bd24ac39552fb22772a8eed69ccdba0b2c9e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 18:45:25 +0000 Subject: r17142: Ensure we record the correct can_read/can_write from the client requested access mask. Jeremy. (This used to be commit 12490fafc7f98952bf709c4c504f8f2b5646f197) --- source3/smbd/open.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2abd367597..890f1ef45a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -190,7 +190,8 @@ static NTSTATUS open_file(files_struct *fsp, SMB_STRUCT_STAT *psbuf, int flags, mode_t unx_mode, - uint32 access_mask) + uint32 access_mask, /* client requested access mask. */ + uint32 open_access_mask) /* what we're actually using in the open. */ { int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -244,7 +245,7 @@ static NTSTATUS open_file(files_struct *fsp, local_flags = (flags & ~O_ACCMODE)|O_RDWR; } - if ((access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || (!file_existed && (local_flags & O_CREAT)) || ((local_flags & O_TRUNC) == O_TRUNC) ) { @@ -1547,7 +1548,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, open_access_mask); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, + access_mask, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1814,7 +1816,7 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); + status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA); /* * This is not a user visible file open. -- cgit From dc5f6687e4a4cf22103364eb4f364984700e0e22 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 21:03:03 +0000 Subject: r17152: Don't handle the delete pending here, await reschedule. Jeremy. (This used to be commit 11bab9d57958659c71f053fe8dc0f9156c9f3c1f) --- source3/smbd/open.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 890f1ef45a..21c4bd628a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1594,13 +1594,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, access_mask, share_access, create_options, &file_existed); - if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { - /* DELETE_PENDING is not deferred for a second */ - TALLOC_FREE(lck); - file_free(fsp); - return status; - } - if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; -- cgit From ba72b0242e29e7cc97f02af27290806a07305350 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Fri, 21 Jul 2006 15:51:34 +0000 Subject: r17179: Merge the vl-posixacls tmp branch into mainline. It modularizes our interface into the special posix API used on the system. Without this patch the specific API flavor is determined at compile time, something which severely limits usability on systems with more than one file system. Our first targets are AIX with its JFS and JFS2 APIs, at a later stage also GPFS. But it's certainly not limited to IBM stuff, this abstraction is also necessary for anything that copes with NFSv4 ACLs. For this we will check in handling very soon. Major contributions can be found in the copyright notices as well as the checkin log of the vl-posixacls branch. The final merge to 3_0 post-3.0.23 was done by Peter Somogyi (This used to be commit ca0c73f281a2a65a988094a46bb3e46a94011a53) --- source3/smbd/posix_acls.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d265057ac0..3ea442f818 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -575,6 +575,9 @@ static void print_canon_ace(canon_ace *pace, int num) case SMB_ACL_OTHER: dbgtext( "SMB_ACL_OTHER "); break; + default: + dbgtext( "MASK " ); + break; } if (pace->inherited) dbgtext( "(inherited) "); @@ -2435,17 +2438,6 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau } } - /* - * Check if the ACL is valid. - */ - - if (SMB_VFS_SYS_ACL_VALID(conn, the_acl) == -1) { - DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", - the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", - strerror(errno) )); - goto fail; - } - /* * Finally apply it to the file or directory. */ -- cgit From 120422f7233446e8ca366ee7c4593cdbead79508 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Jul 2006 00:16:45 +0000 Subject: r17220: If we're going to fail a write with an errno, make sure we return -1. Jeremy. (This used to be commit 89b83237b03066785ca4bf3b9d120519bddeffad) --- source3/smbd/fileio.c | 2 +- source3/smbd/reply.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 375bfbe7cf..e0945be889 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -214,7 +214,7 @@ ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) if (!fsp->can_write) { errno = EPERM; - return(0); + return -1; } if (!fsp->modified) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index edaf5d8062..e38edadee4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2807,6 +2807,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, } nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite); + if (nwritten == -1) { + END_PROFILE(SMBwritebraw); + return(UNIXERROR(ERRHRD,ERRdiskfull)); + } if (nwritten < (ssize_t)numtowrite) { SCVAL(outbuf,smb_rcls,ERRHRD); -- cgit From 0e6e3c90c933db15e3a11a5672f252a963541bbc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Jul 2006 08:40:04 +0000 Subject: r17228: Modest reformatting (This used to be commit 640b4297a400fe23418e9c1c01d4c14ce3bde5b4) --- source3/smbd/open.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 21c4bd628a..1b67d74403 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1361,7 +1361,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->inode = psbuf->st_ino; fsp->share_access = share_access; fsp->fh->private_options = create_options; - fsp->access_mask = open_access_mask; /* We change this to the requested access_mask after the open is done. */ + fsp->access_mask = open_access_mask; /* We change this to the + * requested access_mask after + * the open is done. */ /* Ensure no SAMBA_PRIVATE bits can be set. */ fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); @@ -1374,8 +1376,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, inode = psbuf->st_ino; lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + conn->connectpath, + fname); if (lck == NULL) { file_free(fsp); @@ -1391,14 +1393,17 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - /* Use the client requested access mask here, not the one we open with. */ + /* Use the client requested access mask here, not the one we + * open with. */ status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); if (NT_STATUS_IS_OK(status)) { - /* We might be going to allow this open. Check oplock status again. */ - /* Second pass - send break for both batch or exclusive oplocks. */ + /* We might be going to allow this open. Check oplock + * status again. */ + /* Second pass - send break for both batch or + * exclusive oplocks. */ if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); @@ -1427,7 +1432,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { files_struct *fsp_dup; - /* Use the client requested access mask here, not the one we open with. */ + /* Use the client requested access mask here, + * not the one we open with. */ fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, access_mask, share_access, @@ -1462,7 +1468,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (((flags & O_RDWR) && !CAN_WRITE(conn)) || - !can_access_file(conn,fname,psbuf,can_access_mask)) { + !can_access_file(conn,fname,psbuf,can_access_mask)) { can_access = False; } @@ -1549,7 +1555,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, - access_mask, open_access_mask); + access_mask, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1580,11 +1586,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, inode = fsp->inode; lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + conn->connectpath, + fname); if (lck == NULL) { - DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); + DEBUG(0, ("open_file_ntcreate: Could not get share " + "mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1703,7 +1710,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type); if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED) { + info == FILE_WAS_SUPERSEDED) { /* Handle strange delete on close create semantics. */ if (create_options & FILE_DELETE_ON_CLOSE) { @@ -1743,8 +1750,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ - if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 - && errno == ENOSYS) { + if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 && + errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } @@ -1765,7 +1772,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } else { DEBUG(5, ("open_file_ntcreate: reset " "attributes of file %s to 0%o\n", - fname, (unsigned int)new_unx_mode)); + fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ } } @@ -1774,7 +1781,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) DEBUG(5, ("open_file_ntcreate: failed to reset " "attributes of file %s to 0%o\n", - fname, (unsigned int)new_unx_mode)); + fname, (unsigned int)new_unx_mode)); } /* If this is a successful open, we must remove any deferred open -- cgit From 9bbe29ad13c604a79312da45ac238547dbb97c7b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Jul 2006 08:51:54 +0000 Subject: r17229: Indent-style reformatting -- getting used to the code again :-) (This used to be commit 2e400fb0077ccef38fff28ef037f982624b7815b) --- source3/smbd/open.c | 104 ++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1b67d74403..74dd038381 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -39,10 +39,10 @@ struct deferred_open_record { ****************************************************************************/ static BOOL fd_open(struct connection_struct *conn, - const char *fname, - files_struct *fsp, - int flags, - mode_t mode) + const char *fname, + files_struct *fsp, + int flags, + mode_t mode) { int sav; @@ -68,7 +68,7 @@ static BOOL fd_open(struct connection_struct *conn, ****************************************************************************/ int fd_close(struct connection_struct *conn, - files_struct *fsp) + files_struct *fsp) { if (fsp->fh->fd == -1) { return 0; /* What we used to call a stat open. */ @@ -85,9 +85,9 @@ int fd_close(struct connection_struct *conn, ****************************************************************************/ void change_owner_to_parent(connection_struct *conn, - files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) { const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; @@ -185,13 +185,13 @@ void change_owner_to_parent(connection_struct *conn, ****************************************************************************/ static NTSTATUS open_file(files_struct *fsp, - connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - int flags, - mode_t unx_mode, - uint32 access_mask, /* client requested access mask. */ - uint32 open_access_mask) /* what we're actually using in the open. */ + connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + int flags, + mode_t unx_mode, + uint32 access_mask, /* client requested access mask. */ + uint32 open_access_mask) /* what we're actually using in the open. */ { int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -335,7 +335,8 @@ static NTSTATUS open_file(files_struct *fsp, if (!CAN_WRITE(conn)) { fsp->can_write = False; } else { - fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; + fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? + True : False; } fsp->print_file = False; fsp->modified = False; @@ -351,7 +352,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *current_user_info.smb_name ? current_user_info.smb_name : conn->user,fsp->fsp_name, + *current_user_info.smb_name ? + current_user_info.smb_name : conn->user,fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); @@ -614,9 +616,9 @@ static BOOL is_delete_request(files_struct *fsp) { */ static BOOL delay_for_oplocks(struct share_mode_lock *lck, - files_struct *fsp, - int pass_number, - int oplock_request) + files_struct *fsp, + int pass_number, + int oplock_request) { int i; struct share_mode_entry *exclusive = NULL; @@ -805,12 +807,12 @@ static void kernel_flock(files_struct *fsp, uint32 share_mode) ****************************************************************************/ static BOOL open_match_attributes(connection_struct *conn, - const char *path, - uint32 old_dos_attr, - uint32 new_dos_attr, - mode_t existing_unx_mode, - mode_t new_unx_mode, - mode_t *returned_unx_mode) + const char *path, + uint32 old_dos_attr, + uint32 new_dos_attr, + mode_t existing_unx_mode, + mode_t new_unx_mode, + mode_t *returned_unx_mode) { uint32 noarch_old_dos_attr, noarch_new_dos_attr; @@ -915,10 +917,10 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, ****************************************************************************/ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, - uint32 *paccess_mask, - uint32 *pshare_mode, - uint32 *pcreate_disposition, - uint32 *pcreate_options) + uint32 *paccess_mask, + uint32 *pshare_mode, + uint32 *pcreate_disposition, + uint32 *pcreate_options) { uint32 access_mask; uint32 share_mode; @@ -1090,17 +1092,17 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ ****************************************************************************/ NTSTATUS open_file_ntcreate(connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ - uint32 share_access, /* share constants (FILE_SHARE_READ etc). */ - uint32 create_disposition, /* FILE_OPEN_IF etc. */ - uint32 create_options, /* options such as delete on close. */ - uint32 new_dos_attributes, /* attributes used for new file. */ - int oplock_request, /* internal Samba oplock codes. */ - /* Information (FILE_EXISTS etc.) */ - int *pinfo, - files_struct **result) + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ + uint32 share_access, /* share constants (FILE_SHARE_READ etc) */ + uint32 create_disposition, /* FILE_OPEN_IF etc. */ + uint32 create_options, /* options such as delete on close. */ + uint32 new_dos_attributes, /* attributes used for new file. */ + int oplock_request, /* internal Samba oplock codes. */ + /* Information (FILE_EXISTS etc.) */ + int *pinfo, + files_struct **result) { int flags=0; int flags2=0; @@ -1849,14 +1851,14 @@ int close_file_fchmod(files_struct *fsp) ****************************************************************************/ NTSTATUS open_directory(connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - uint32 access_mask, - uint32 share_access, - uint32 create_disposition, - uint32 create_options, - int *pinfo, - files_struct **result) + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, + uint32 share_access, + uint32 create_disposition, + uint32 create_options, + int *pinfo, + files_struct **result) { files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; @@ -1993,8 +1995,8 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, - conn->connectpath, - fname); + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); -- cgit From f43522856bb4a6824447524c612a98fec1f991ef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jul 2006 01:53:23 +0000 Subject: r17247: When we map generic to specific we need to remember to copy over the copy of the access_mask, open_access_mask. Jerry - this is a definate fix for a 3.0.23b and should also be on the patches page. CIFSFS breaks without this. Jeremy. (This used to be commit d11e71ebcccf6907f2404a04aa6bf61b12ab2709) --- source3/smbd/open.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 74dd038381..95c70dff54 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1307,6 +1307,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ se_map_generic(&access_mask, &file_generic_mapping); + open_access_mask = access_mask; DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping " "access_mask=0x%x\n", fname, access_mask )); @@ -1548,9 +1549,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, unx_mode = 0777; } - DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o, " + "access_mask = 0x%x, open_access_mask = 0x%x\n", (unsigned int)flags, (unsigned int)flags2, - (unsigned int)unx_mode)); + (unsigned int)unx_mode, (unsigned int)access_mask, + (unsigned int)open_access_mask)); /* * open_file strips any O_TRUNC flags itself. -- cgit From f6aeba37ff3fbfb3b7d3ff5a3878348e0b3acc39 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jul 2006 02:15:01 +0000 Subject: r17248: Ensure we definately add the WRITE_DATA on O_TRUNC. Jeremy. (This used to be commit 8eed82d5d5ba34cc0a6b99b9d0df45eec5f788fa) --- source3/smbd/open.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 95c70dff54..fd2f1ae54f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1297,9 +1297,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* This is a nasty hack - must fix... JRA. */ if (access_mask == MAXIMUM_ALLOWED_ACCESS) { open_access_mask = access_mask = FILE_GENERIC_ALL; - if (flags2 & O_TRUNC) { - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ - } } /* @@ -1309,6 +1306,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, se_map_generic(&access_mask, &file_generic_mapping); open_access_mask = access_mask; + if (flags2 & O_TRUNC) { + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ + } + DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping " "access_mask=0x%x\n", fname, access_mask )); -- cgit From 999b1e01e1ee55338ff96ddf80c3852038216108 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jul 2006 04:42:18 +0000 Subject: r17249: Ensure we only set the FILE_WRITE_DATA on O_TRUNC in one place. Jeremy. (This used to be commit f326bae3e269046b6f087626240cddbb5dafb0e4) --- source3/smbd/open.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fd2f1ae54f..9bd4e36d5a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1212,14 +1212,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OVERWRITE_IF: /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OPEN: @@ -1244,7 +1242,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags2 |= O_TRUNC; - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_CREATE: -- cgit From 31802698db7e2b48f01bbb0ce540e38653cd8517 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 26 Jul 2006 08:08:48 +0000 Subject: r17254: Simple flattening of an if-statement, no logic change. Jeremy, I'm sure you will look at this nevertheless :-) Volker (This used to be commit 3ef34468b55771b6f6b54454fa6c9decc183c565) --- source3/smbd/open.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9bd4e36d5a..ef59da6447 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -625,6 +625,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL valid_entry = False; BOOL delay_it = False; BOOL have_level2 = False; + BOOL ret; + char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; if (oplock_request & INTERNAL_OPEN_ONLY) { fsp->oplock_type = NO_OPLOCK; @@ -688,34 +690,38 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; } - if (delay_it) { - BOOL ret; - char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; + if (!delay_it) { + return False; + } - DEBUG(10, ("Sending break request to PID %s\n", - procid_str_static(&exclusive->pid))); - exclusive->op_mid = get_current_mid(); + /* + * Send a break message to the oplock holder and delay the open for + * our client. + */ - /* Create the message. */ - share_mode_entry_to_message(msg, exclusive); + DEBUG(10, ("Sending break request to PID %s\n", + procid_str_static(&exclusive->pid))); + exclusive->op_mid = get_current_mid(); - /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We don't - want this set in the share mode struct pointed to by lck. */ + /* Create the message. */ + share_mode_entry_to_message(msg, exclusive); - if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { - SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); - } + /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We + don't want this set in the share mode struct pointed to by lck. */ - become_root(); - ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - unbecome_root(); - if (!ret) { - DEBUG(3, ("Could not send oplock break message\n")); - } + if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { + SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - return delay_it; + become_root(); + ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + unbecome_root(); + if (!ret) { + DEBUG(3, ("Could not send oplock break message\n")); + } + + return True; } static BOOL request_timed_out(struct timeval request_time, -- cgit From a093a76dc14303fd1c42fb2c0b87faf3748815e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jul 2006 22:42:39 +0000 Subject: r17293: After the results from the cluster tests in Germany, fix the messaging code to call the efficient calls : save_re_uid() set_effective_uid(0); messaging_op restore_re_uid(); instead of using heavyweight become_root()/unbecome_root() pairs around all messaging code. Fixup the messaging code to ensure sec_init() is called (only once) so that non-root processes still work when sending messages. This is a lighter weight solution to become_root()/unbecome_root() (which swaps all the supplemental groups) and should be more efficient. I will migrate all server code over to using this (a similar technique should be used in the passdb backend where needed). Jeremy. (This used to be commit 4ace291278d9a44f5c577bdd3b282c1231e543df) --- source3/smbd/blocking.c | 3 --- source3/smbd/close.c | 2 -- source3/smbd/open.c | 2 -- source3/smbd/oplock.c | 11 ----------- 4 files changed, 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index a0b93f5032..ed57c9f621 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -837,9 +837,6 @@ BOOL blocking_lock_cancel(files_struct *fsp, memcpy(msg, &blr, sizeof(blr)); memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS)); - /* Don't need to be root here as we're only ever - sending to ourselves. */ - message_send_pid(pid_to_procid(sys_getpid()), MSG_SMB_BLOCKING_LOCK_CANCEL, &msg, sizeof(msg), True); diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 08e4a24a56..a3ddcae11d 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -134,10 +134,8 @@ static void notify_deferred_opens(struct share_mode_lock *lck) share_mode_entry_to_message(msg, e); - become_root(); message_send_pid(e->pid, MSG_SMB_OPEN_RETRY, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - unbecome_root(); } } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ef59da6447..5c10c59054 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -713,10 +713,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - unbecome_root(); if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 99ce79296f..d9850ee051 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -504,13 +504,10 @@ static void process_oplock_break_message(int msg_type, struct process_id src, * get to process this message, we have closed the file. Reply * with 'ok, oplock broken' */ DEBUG(3, ("Did not find fsp\n")); - become_root(); /* We just send the same message back. */ message_send_pid(src, MSG_SMB_BREAK_RESPONSE, buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - - unbecome_root(); return; } @@ -529,13 +526,9 @@ static void process_oplock_break_message(int msg_type, struct process_id src, DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n", (unsigned int)fsp->dev, (double)fsp->inode, fsp->fsp_name)); - become_root(); - /* We just send the same message back. */ message_send_pid(src, MSG_SMB_BREAK_RESPONSE, buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - - unbecome_root(); return; } @@ -656,7 +649,6 @@ void reply_to_oplock_break_requests(files_struct *fsp) { int i; - become_root(); for (i=0; inum_pending_break_messages; i++) { struct share_mode_entry *e = &fsp->pending_break_messages[i]; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; @@ -666,7 +658,6 @@ void reply_to_oplock_break_requests(files_struct *fsp) message_send_pid(e->pid, MSG_SMB_BREAK_RESPONSE, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); } - unbecome_root(); SAFE_FREE(fsp->pending_break_messages); fsp->num_pending_break_messages = 0; @@ -801,10 +792,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp) share_mode_entry_to_message(msg, share_entry); - become_root(); message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - unbecome_root(); } /* We let the message receivers handle removing the oplock state -- cgit From e4e2be0d8b5778ecc5c521b9e0e0b4c05ac87394 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jul 2006 22:56:41 +0000 Subject: r17294: Make the code a little cleaner. Instead of using the two calls make it : become_root_uid_only() operation unbecome_root_uid_only() saving errno across the second call. Most of our internal change calls can be replaced with these simple calls. Jeremy (This used to be commit 4143aa83c029848d8ec741d9218b3fa6e3fd28dd) --- source3/smbd/posix_acls.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 3ea442f818..f2ed2778f2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2458,9 +2458,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", fsp->fsp_name )); - become_root(); + become_root_uid_only(); sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl); - unbecome_root(); + unbecome_root_uid_only(); if (sret == 0) { ret = True; } @@ -2489,9 +2489,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", fsp->fsp_name )); - become_root(); + become_root_uid_only(); sret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl); - unbecome_root(); + unbecome_root_uid_only(); if (sret == 0) { ret = True; } @@ -3018,10 +3018,10 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ /* Case (3) */ ( has_restore_priv ) ) { - become_root(); + become_root_uid_only(); /* Keep the current file gid the same - take ownership doesn't imply group change. */ ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1); - unbecome_root(); + unbecome_root_uid_only(); return ret; } } @@ -3045,10 +3045,10 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ */ uid = current_user.ut.uid; - become_root(); + become_root_uid_only(); /* Keep the current file gid the same. */ ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, uid, (gid_t)-1); - unbecome_root(); + unbecome_root_uid_only(); close_file_fchmod(fsp); @@ -3226,9 +3226,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) "current user in file %s primary group. Override delete_def_acl\n", fsp->fsp_name )); - become_root(); + become_root_uid_only(); sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name); - unbecome_root(); + unbecome_root_uid_only(); } if (sret == -1) { @@ -3273,9 +3273,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) "current user in file %s primary group. Override chmod\n", fsp->fsp_name )); - become_root(); + become_root_uid_only(); sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms); - unbecome_root(); + unbecome_root_uid_only(); } if (sret == -1) { -- cgit From 5b3d559aa808210b1d6d61bc9bb9088b06e4c9c8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jul 2006 23:09:12 +0000 Subject: r17295: Back out the become_root_uid_only change on the POSIX acls code. I'm pretty sure this was safe, but become_root() does other things to the token stack that become_root_uid_only() does not, and as we're going into a vfs redirectred function I decided it wasn't safe for now. Jeremy. (This used to be commit b3e0f45488595aa96c852dab8e1349631a85dded) --- source3/smbd/posix_acls.c | 24 ++++++++++++------------ source3/smbd/uid.c | 1 - 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f2ed2778f2..3ea442f818 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2458,9 +2458,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", fsp->fsp_name )); - become_root_uid_only(); + become_root(); sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl); - unbecome_root_uid_only(); + unbecome_root(); if (sret == 0) { ret = True; } @@ -2489,9 +2489,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", fsp->fsp_name )); - become_root_uid_only(); + become_root(); sret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl); - unbecome_root_uid_only(); + unbecome_root(); if (sret == 0) { ret = True; } @@ -3018,10 +3018,10 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ /* Case (3) */ ( has_restore_priv ) ) { - become_root_uid_only(); + become_root(); /* Keep the current file gid the same - take ownership doesn't imply group change. */ ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1); - unbecome_root_uid_only(); + unbecome_root(); return ret; } } @@ -3045,10 +3045,10 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ */ uid = current_user.ut.uid; - become_root_uid_only(); + become_root(); /* Keep the current file gid the same. */ ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, uid, (gid_t)-1); - unbecome_root_uid_only(); + unbecome_root(); close_file_fchmod(fsp); @@ -3226,9 +3226,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) "current user in file %s primary group. Override delete_def_acl\n", fsp->fsp_name )); - become_root_uid_only(); + become_root(); sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name); - unbecome_root_uid_only(); + unbecome_root(); } if (sret == -1) { @@ -3273,9 +3273,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) "current user in file %s primary group. Override chmod\n", fsp->fsp_name )); - become_root_uid_only(); + become_root(); sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms); - unbecome_root_uid_only(); + unbecome_root(); } if (sret == -1) { diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 89d082e1ac..8588580322 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -420,4 +420,3 @@ BOOL unbecome_user(void) pop_conn_ctx(); return True; } - -- cgit From 981350a03c14ca526b703925c65d61b70b1f38cb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jul 2006 23:16:52 +0000 Subject: r17296: Replace the understandable parts of the quota code with become_root_uid_only()/unbecome_root_uid_only() pairs. This code needs working on..... Jeremy. (This used to be commit 0661d4e26614180636bc57de0c48adf8b9ce7a21) --- source3/smbd/quotas.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index d6ba7bc2d5..35bb94bcef 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -238,8 +238,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if (!found) return(False); - save_re_uid(); - set_effective_uid(0); + become_root_uid_only(); if (strcmp(mnt->mnt_type, "xfs")==0) { r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); @@ -252,7 +251,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB } } - restore_re_uid(); + unbecome_root_uid_only(); /* Use softlimit to determine disk space, except when it has been exceeded */ *bsize = D.bsize; @@ -654,21 +653,20 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if ( ! found ) return(False) ; - save_re_uid(); - set_effective_uid(0); + become_root_uid_only(); #if defined(SUNOS5) if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) { BOOL retval; DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); - restore_re_uid(); + unbecome_root_uid_only(); return retval; } DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); if((file=sys_open(name, O_RDONLY,0))<0) { - restore_re_uid(); + unbecome_root_uid_only(); return(False); } command.op = Q_GETQUOTA; @@ -681,7 +679,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - restore_re_uid(); + unbecome_root_uid_only(); if (ret < 0) { DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); @@ -841,8 +839,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB } euser_id=geteuid(); - save_re_uid(); - set_effective_uid(0); + become_root_uid_only(); /* Use softlimit to determine disk space, except when it has been exceeded */ @@ -852,7 +849,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB { r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); - restore_re_uid(); + unbecome_root_uid_only(); if (r==-1) return(False); @@ -883,7 +880,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB { r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); - restore_re_uid(); + unbecome_root_uid_only(); if (r==-1) { @@ -917,7 +914,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB } else { - restore_re_uid(); + unbecome_root_uid_only(); return(False); } @@ -1181,14 +1178,13 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB return False; #endif - save_re_uid(); - set_effective_uid(0); + become_root_uid_only(); #if defined(__FreeBSD__) || defined(__DragonFly__) if (strcmp(mnts[i].f_fstypename,"nfs") == 0) { BOOL retval; retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize); - restore_re_uid(); + unbecome_root_uid_only(); return retval; } #endif @@ -1202,7 +1198,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); } - restore_re_uid(); + unbecome_root_uid_only(); } #elif defined(AIX) /* AIX has both USER and GROUP quotas: -- cgit From 2c6030415e0b1f421ea6e85fe6ffe7389ee7a941 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 29 Jul 2006 19:14:24 +0000 Subject: r17314: Optimisation for POSIX locking. If we're downgrading a POSIX lock (applying a read-lock) and we overlap pending read locks then send them an unlock message, we may have allowed them to proceed. Jeremy. (This used to be commit a7a0b6ba50f4cf7c5a0a29809fdff9e1266a29e7) --- source3/smbd/blocking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ed57c9f621..0304a6559f 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -137,7 +137,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, procid_self(), offset, count, - PENDING_LOCK, + lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, blr->lock_flav, lock_timeout ? True : False); /* blocking_lock. */ -- cgit From e23781b3b304d1e69ad80af5ae9c0ed8d02cf996 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 30 Jul 2006 16:36:56 +0000 Subject: r17316: More C++ warnings -- 456 left (This used to be commit 1e4ee728df7eeafc1b4d533240acb032f73b4f5c) --- source3/smbd/ipc.c | 4 ++-- source3/smbd/nttrans.c | 8 ++++---- source3/smbd/trans2.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e6dfc6506a..08381524c0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -478,7 +478,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, if (state->total_data) { /* Can't use talloc here, the core routines do realloc on the * params and data. */ - state->data = SMB_MALLOC(state->total_data); + state->data = (char *)SMB_MALLOC(state->total_data); if (state->data == NULL) { DEBUG(0,("reply_trans: data malloc fail for %u " "bytes !\n", (unsigned int)state->total_data)); @@ -498,7 +498,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, if (state->total_param) { /* Can't use talloc here, the core routines do realloc on the * params and data. */ - state->param = SMB_MALLOC(state->total_param); + state->param = (char *)SMB_MALLOC(state->total_param); if (state->param == NULL) { DEBUG(0,("reply_trans: param malloc fail for %u " "bytes !\n", (unsigned int)state->total_param)); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0b1bdcadbb..d107bf84d3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -52,7 +52,7 @@ static char *nttrans_realloc(char **ptr, size_t size) smb_panic("nttrans_realloc() called with NULL ptr\n"); } - *ptr = SMB_REALLOC(*ptr, size); + *ptr = (char *)SMB_REALLOC(*ptr, size); if(*ptr == NULL) { return NULL; } @@ -2908,7 +2908,7 @@ int reply_nttrans(connection_struct *conn, if (state->total_data) { /* Can't use talloc here, the core routines do realloc on the * params and data. */ - if ((state->data = SMB_MALLOC(state->total_data)) == NULL) { + if ((state->data = (char *)SMB_MALLOC(state->total_data)) == NULL) { DEBUG(0,("reply_nttrans: data malloc fail for %u " "bytes !\n", (unsigned int)state->total_data)); TALLOC_FREE(state); @@ -2927,7 +2927,7 @@ int reply_nttrans(connection_struct *conn, if (state->total_param) { /* Can't use talloc here, the core routines do realloc on the * params and data. */ - if ((state->param = SMB_MALLOC(state->total_param)) == NULL) { + if ((state->param = (char *)SMB_MALLOC(state->total_param)) == NULL) { DEBUG(0,("reply_nttrans: param malloc fail for %u " "bytes !\n", (unsigned int)state->total_param)); SAFE_FREE(state->data); @@ -2950,7 +2950,7 @@ int reply_nttrans(connection_struct *conn, if(state->setup_count > 0) { DEBUG(10,("reply_nttrans: state->setup_count = %d\n", state->setup_count)); - state->setup = TALLOC(state, state->setup_count); + state->setup = (uint16 *)TALLOC(state, state->setup_count); if (state->setup == NULL) { DEBUG(0,("reply_nttrans : Out of memory\n")); SAFE_FREE(state->data); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5acce13e52..8eb8790975 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -170,8 +170,8 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str return NULL; } - for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6; - ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { + for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6; + ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { if (!ea_namelist) { return NULL; @@ -899,7 +899,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } /* Realloc the size of parameters and data we will return */ - *pparams = SMB_REALLOC(*pparams, 30); + *pparams = (char *)SMB_REALLOC(*pparams, 30); if(*pparams == NULL ) { return ERROR_NT(NT_STATUS_NO_MEMORY); } -- cgit From e7952e9c14218d0c8c13973056ab8762876e5a79 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 31 Jul 2006 21:11:03 +0000 Subject: r17347: Some C++ warnings -- 271 left (This used to be commit 641dac4f85c0e00484d90726bea1a4cb58c8235c) --- source3/smbd/trans2.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8eb8790975..82052127c9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1043,7 +1043,7 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps ****************************************************************************/ static BOOL get_lanman2_dir_entry(connection_struct *conn, - void *inbuf, void *outbuf, + void *inbuf, char *outbuf, char *path_mask,uint32 dirtype,int info_level, int requires_resume_key, BOOL dont_descend,char **ppdata, @@ -1751,7 +1751,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } - *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + *ppdata = (char *)SMB_REALLOC( + *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(*ppdata == NULL ) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -1759,7 +1760,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata = *ppdata; /* Realloc the params space */ - *pparams = SMB_REALLOC(*pparams, 10); + *pparams = (char *)SMB_REALLOC(*pparams, 10); if (*pparams == NULL) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -2002,7 +2003,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } - *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + *ppdata = (char *)SMB_REALLOC( + *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(*ppdata == NULL) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -2011,7 +2013,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata = *ppdata; /* Realloc the params space */ - *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD); + *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD); if(*pparams == NULL ) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -2175,7 +2177,8 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf return ERROR_DOS(ERRSRV,ERRinvdevice); } - *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + *ppdata = (char *)SMB_REALLOC( + *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if (*ppdata == NULL ) { return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -3016,7 +3019,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Copy the lock range data. */ - lock_data = talloc_memdup(data_ctx, pdata, total_data); + lock_data = (char *)talloc_memdup( + data_ctx, pdata, total_data); if (!lock_data) { talloc_destroy(data_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -3026,7 +3030,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd break; } - *pparams = SMB_REALLOC(*pparams,2); + *pparams = (char *)SMB_REALLOC(*pparams,2); if (*pparams == NULL) { talloc_destroy(data_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -3034,7 +3038,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd params = *pparams; SSVAL(params,0,0); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; - *ppdata = SMB_REALLOC(*ppdata, data_size); + *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); if (*ppdata == NULL ) { talloc_destroy(data_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -3841,7 +3845,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); /* Realloc the parameter size */ - *pparams = SMB_REALLOC(*pparams,2); + *pparams = (char *)SMB_REALLOC(*pparams,2); if (*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -4822,7 +4826,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, } /* Realloc the parameter and data sizes */ - *pparams = SMB_REALLOC(*pparams,2); + *pparams = (char *)SMB_REALLOC(*pparams,2); if(*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -4864,7 +4868,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char } /* Realloc the parameter and data sizes */ - *pparams = SMB_REALLOC(*pparams,6); + *pparams = (char *)SMB_REALLOC(*pparams,6); if (*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -4898,7 +4902,7 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2findnotifynext\n")); /* Realloc the parameter and data sizes */ - *pparams = SMB_REALLOC(*pparams,4); + *pparams = (char *)SMB_REALLOC(*pparams,4); if (*pparams == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -4967,7 +4971,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { - *ppdata = SMB_REALLOC(*ppdata, 32); + *ppdata = (char *)SMB_REALLOC(*ppdata, 32); if (*ppdata == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -5289,7 +5293,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, if (state->total_data) { /* Can't use talloc here, the core routines do realloc on the * params and data. */ - state->data = SMB_MALLOC(state->total_data); + state->data = (char *)SMB_MALLOC(state->total_data); if (state->data == NULL) { DEBUG(0,("reply_trans2: data malloc fail for %u " "bytes !\n", (unsigned int)state->total_data)); @@ -5309,7 +5313,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, if (state->total_param) { /* Can't use talloc here, the core routines do realloc on the * params and data. */ - state->param = SMB_MALLOC(state->total_param); + state->param = (char *)SMB_MALLOC(state->total_param); if (state->param == NULL) { DEBUG(0,("reply_trans: param malloc fail for %u " "bytes !\n", (unsigned int)state->total_param)); -- cgit From 430fa0eba08cbf180d83740a895a0018af1c7f21 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 31 Jul 2006 21:40:25 +0000 Subject: r17348: Some C++ warnings (This used to be commit ae6b9b34e59167e3958bfdb9997fa25340b9a0a3) --- source3/smbd/msdfs.c | 4 ++-- source3/smbd/ntquotas.c | 2 +- source3/smbd/posix_acls.c | 6 +++--- source3/smbd/sec_ctx.c | 3 ++- source3/smbd/vfs.c | 6 +++--- 5 files changed, 11 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b698bc781d..6891022264 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -655,7 +655,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, /* add the unexplained 0x16 bytes */ reply_size += 0x16; - pdata = SMB_REALLOC(pdata,reply_size); + pdata = (char *)SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; @@ -740,7 +740,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; } - pdata = SMB_REALLOC(pdata,reply_size); + pdata = (char *)SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index a824978ece..e754583312 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -244,7 +244,7 @@ void destroy_quota_handle(void **pqt_handle) if (!pqt_handle||!(*pqt_handle)) return; - qt_handle = (*pqt_handle); + qt_handle = (SMB_NTQUOTA_HANDLE *)(*pqt_handle); if (qt_handle->quota_list) diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 3ea442f818..a431f6e07a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -169,7 +169,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B *store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH); - pai_buf = SMB_MALLOC(*store_size); + pai_buf = (char *)SMB_MALLOC(*store_size); if (!pai_buf) { return NULL; } @@ -441,7 +441,7 @@ static struct pai_val *load_inherited_info(files_struct *fsp) if (!lp_map_acl_inherit(SNUM(fsp->conn))) return NULL; - if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL) + if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) return NULL; do { @@ -462,7 +462,7 @@ static struct pai_val *load_inherited_info(files_struct *fsp) if (pai_buf_size > 1024*1024) { return NULL; /* Limit malloc to 1mb. */ } - if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL) + if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) return NULL; } } while (ret == -1); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 51d1d6cc0a..be00db9adb 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -259,7 +259,8 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN TALLOC_FREE(ctx_p->token); if (ngroups) { - ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups); + ctx_p->ut.groups = (gid_t *)memdup(groups, + sizeof(gid_t) * ngroups); if (!ctx_p->ut.groups) { smb_panic("memdup failed"); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7bb5f798f9..ed6b3dd4c4 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -206,8 +206,8 @@ void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, return ext_data; } - ext = TALLOC_ZERO(handle->conn->mem_ctx, - sizeof(struct vfs_fsp_data) + ext_size); + ext = (struct vfs_fsp_data *)TALLOC_ZERO( + handle->conn->mem_ctx, sizeof(struct vfs_fsp_data) + ext_size); if (ext == NULL) { return NULL; } @@ -647,7 +647,7 @@ char *vfs_readdirname(connection_struct *conn, void *p) if (!p) return(NULL); - ptr = SMB_VFS_READDIR(conn,p); + ptr = SMB_VFS_READDIR(conn, (DIR *)p); if (!ptr) return(NULL); -- cgit From 4cf5769331bb9432fb7455f6eb0384b0282f605f Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 1 Aug 2006 07:38:36 +0000 Subject: r17353: Add support for JFS2 NFS4/AIXC and GPFS acls based on NFSv4 ACLs. (This used to be commit 72312cb2e255301f978455a559461ad83b13b6cb) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a431f6e07a..a1903ef4bb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -901,7 +901,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ -static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) { DOM_SID owner_sid; DOM_SID grp_sid; @@ -2989,7 +2989,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) then allow chown to the currently authenticated user. ****************************************************************************/ -static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) +int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; files_struct *fsp; @@ -3105,7 +3105,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) { + if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) { return False; } -- cgit From 16bf23d973b899f570b6793cf52507086d74d66a Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 1 Aug 2006 08:27:19 +0000 Subject: r17354: Revert -r 17353 per Volker request while gpfs compatibility layer code will be released. (This used to be commit 5b1db0151461af18d994359e86c649922fc6de65) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a1903ef4bb..a431f6e07a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -901,7 +901,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ -BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) { DOM_SID owner_sid; DOM_SID grp_sid; @@ -2989,7 +2989,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) then allow chown to the currently authenticated user. ****************************************************************************/ -int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) +static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; files_struct *fsp; @@ -3105,7 +3105,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) { + if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) { return False; } -- cgit From fbd04d65c56c36bec287f6c4ffe84ea79b048fa7 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 1 Aug 2006 09:25:24 +0000 Subject: r17358: Re-add JFS2 NFS4 ACLs support, move readme for it into AIX-specific examples directory. (This used to be commit c085355c323c65ee782516859eed8a76b53e6035) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a431f6e07a..a1903ef4bb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -901,7 +901,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ -static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) { DOM_SID owner_sid; DOM_SID grp_sid; @@ -2989,7 +2989,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) then allow chown to the currently authenticated user. ****************************************************************************/ -static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) +int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; files_struct *fsp; @@ -3105,7 +3105,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) { + if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) { return False; } -- cgit From d42a96b3ec3dec1e2aa958813ae56326e7b02789 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Aug 2006 18:40:19 +0000 Subject: r17367: Reverting the ab code. Note I'm not saying this code is wrong or bad or anything, just that it needs to be discussed & reviewed on the samba-technical list before we add a platform-specific NFSv4 mapping. That way lies a lot of future pain :-). Jeremy. (This used to be commit 330899ec30ffceb798e3a8362d20e103e20b2897) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a1903ef4bb..a431f6e07a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -901,7 +901,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ -BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) { DOM_SID owner_sid; DOM_SID grp_sid; @@ -2989,7 +2989,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) then allow chown to the currently authenticated user. ****************************************************************************/ -int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) +static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; files_struct *fsp; @@ -3105,7 +3105,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) { + if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) { return False; } -- cgit From f569db1c06848b4205c141938e0d11359855673e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Aug 2006 16:18:45 +0000 Subject: r17376: Fix bug #3985 - ensure in msdfs we check for our netbios aliases. Reported by Björn Jacke . Probably needs to be in 3.0.23b (if Björn approves of the fix). Jeremy. (This used to be commit e9e711fe37d9aec28b329dbfe2ad3ebfc1771825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/msdfs.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6891022264..2edad311ea 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -517,13 +517,10 @@ BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *juc parse_dfs_path(pathname, &dp); /* Verify hostname in path */ - if ( !strequal(get_local_machine_name(), dp.hostname) ) { - /* Hostname mismatch, check if one of our IP addresses */ - if (!ismyip(*interpret_addr2(dp.hostname))) { - DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - dp.hostname, pathname)); - return False; - } + if (!is_myname_or_ipaddr(dp.hostname)) { + DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", + dp.hostname, pathname)); + return False; } pstrcpy(jucn->service_name, dp.servicename); @@ -890,13 +887,10 @@ BOOL create_junction(char *pathname, struct junction_map *jucn) parse_dfs_path(pathname,&dp); /* check if path is dfs : validate first token */ - if ( !strequal(get_local_machine_name(),dp.hostname) ) { - /* Hostname mismatch, check if one of our IP addresses */ - if (!ismyip(*interpret_addr2(dp.hostname))) { - DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", - dp.hostname, pathname)); - return False; - } + if (!is_myname_or_ipaddr(dp.hostname)) { + DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", + dp.hostname, pathname)); + return False; } /* Check for a non-DFS share */ -- cgit From f8aa1c75f4961739863928392c8870c9c9a019d8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Aug 2006 20:35:52 +0000 Subject: r17402: Added lookup_name_smbconf() to be called when looking up names from smb.conf. If the name is unqualified it causes the lookup to be done in WORKGROUP\name, then "Unix [users|groups]"\name rather than searching the domain. Should fix the problems with "force user" selecting a domain user by preference. Jeremy. (This used to be commit 1e1fcb5eb2ac4bd360461b29f85c07dbf460025d) --- source3/smbd/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 395114592a..d0ad6fa7e6 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -446,10 +446,10 @@ static NTSTATUS find_forced_group(BOOL force_user, groupname = talloc_string_sub(mem_ctx, groupname, "%S", lp_servicename(snum)); - if (!lookup_name(mem_ctx, groupname, + if (!lookup_name_smbconf(mem_ctx, groupname, LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, NULL, NULL, &group_sid, &type)) { - DEBUG(10, ("lookup_name(%s) failed\n", + DEBUG(10, ("lookup_name_smbconf(%s) failed\n", groupname)); goto done; } -- cgit From 6361d151a4c2fa96b84347ccd76f0748e8ecb1bf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 4 Aug 2006 21:07:32 +0000 Subject: r17406: We need to do a translation of winbind separator -> '\\' in lookup_name_smbconf, otherwise force user = domain+administrator can not work. Also attempt to fix the 'valid users = domain+group' bug at the same time. Volker (This used to be commit 255475901c13fde29b1b476560d969cc99712767) --- source3/smbd/share_access.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index 5334976d8d..09b56c3522 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -97,7 +97,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, } if (!do_group_checks(&name, &prefix)) { - if (!lookup_name(mem_ctx, name, LOOKUP_NAME_ALL, + if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL, NULL, NULL, &sid, &type)) { DEBUG(5, ("lookup_name %s failed\n", name)); return False; @@ -112,7 +112,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, for (/* initialized above */ ; *prefix != '\0'; prefix++) { if (*prefix == '+') { - if (!lookup_name(mem_ctx, name, + if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, NULL, NULL, &sid, &type)) { DEBUG(5, ("lookup_name %s failed\n", name)); -- cgit From ab75c563704fa86c409072bf1b0938e005aff5ca Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 4 Aug 2006 22:18:02 +0000 Subject: r17408: Let us use netgroups even without a NIS domain but just using files (This used to be commit c065341d3ffc9125514f563c63d416cf7c40375f) --- source3/smbd/password.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 389086e9bf..38000e93f4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -417,12 +417,11 @@ BOOL user_in_netgroup(const char *user, const char *ngname) yp_get_default_domain(&mydomain); if(mydomain == NULL) { - DEBUG(5,("Unable to get default yp domain\n")); - return False; + DEBUG(5,("Unable to get default yp domain, let's try without specifying it\n")); } DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", - user, mydomain, ngname)); + user, mydomain?mydomain:"(ANY)", ngname)); if (innetgr(ngname, NULL, user, mydomain)) { DEBUG(5,("user_in_netgroup: Found\n")); @@ -438,7 +437,7 @@ BOOL user_in_netgroup(const char *user, const char *ngname) strlower_m(lowercase_user); DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", - lowercase_user, mydomain, ngname)); + lowercase_user, mydomain?mydomain:"(ANY)", ngname)); if (innetgr(ngname, NULL, lowercase_user, mydomain)) { DEBUG(5,("user_in_netgroup: Found\n")); -- cgit From 70660495b349cde6245731870d6337eb2800a8ed Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 8 Aug 2006 09:56:38 +0000 Subject: r17452: Some C++ warnings (This used to be commit e4b8c79a9d6f7323953121887af4f482d04a9228) --- source3/smbd/oplock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index d9850ee051..eec19259d0 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -346,7 +346,7 @@ static void oplock_timeout_handler(struct timed_event *te, const struct timeval *now, void *private_data) { - files_struct *fsp = private_data; + files_struct *fsp = (files_struct *)private_data; DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name)); global_client_failed_oplock_break = True; @@ -403,7 +403,7 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, buf); + message_to_share_mode_entry(&msg, (char *)buf); DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, @@ -490,7 +490,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, buf); + message_to_share_mode_entry(&msg, (char *)buf); DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, @@ -685,7 +685,7 @@ static void process_oplock_break_response(int msg_type, struct process_id src, } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, buf); + message_to_share_mode_entry(&msg, (char *)buf); DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, @@ -712,7 +712,7 @@ static void process_open_retry_message(int msg_type, struct process_id src, } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, buf); + message_to_share_mode_entry(&msg, (char *)buf); DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, -- cgit From 11673dc07a137e911de3920f0ee6717b365f2ab4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 8 Aug 2006 11:00:16 +0000 Subject: r17453: Fix msdfs RPC management (this broke with the autogenerated dfs rpcs). * Remove "unknown" from dfs_Enum (samba4 dfs IDL updates to follow). * When encountering an unsupported infolevel the rpc server must reply with a dfs_info_0 structure and WERR_OK (observed from w2k3 when talking to nt4). Guenther (This used to be commit f9bef1f08f7d2a4c95c28329ac73e8646f033998) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 2edad311ea..44415ddd16 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -901,6 +901,7 @@ BOOL create_junction(char *pathname, struct junction_map *jucn) pstrcpy(jucn->service_name,dp.servicename); pstrcpy(jucn->volume_name,dp.reqpath); + pstrcpy(jucn->comment, lp_comment(lp_servicenumber(dp.servicename))); return True; } -- cgit From 6fd4813ece5e03c92334acfa7e168cd7d0248919 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 Aug 2006 16:53:14 +0000 Subject: r17541: When returning a trans2 request, if the "max data bytes returned" is less than the amount we want to send, return what we can and set STATUS_BUFFER_OVERFLOW (doserror ERRDOS,ERRbufferoverflow). Required by OS/2 to handle EA's that are too large. It's hard to test this in Samba4 smbtorture as the max data bytes returned is hard coded at 0xffff (as it is in the Samba3 client libraries also). I used a custom version of Samba4 smbtorture to test this out. Might add a "max data bytes" param to make this testable in the build farm. Confirmed by "Guenter Kukkukk (sambaos2)" and Andreas Taegener that this fixes the issue. Jeremy. (This used to be commit ff2f1202b76991a404dae8df17c36f8135c8dc51) --- source3/smbd/blocking.c | 3 ++- source3/smbd/error.c | 8 +++++-- source3/smbd/trans2.c | 61 ++++++++++++++++++++++++++++++------------------- 3 files changed, 45 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 0304a6559f..2f89759ffd 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -458,7 +458,8 @@ static BOOL process_trans2(blocking_lock_record *blr) construct_reply_common(inbuf, outbuf); SCVAL(outbuf,smb_com,SMBtrans2); SSVAL(params,0,0); - send_trans2_replies(outbuf, max_send, params, 2, NULL, 0); + /* Fake up max_data_bytes here - we know it fits. */ + send_trans2_replies(outbuf, max_send, params, 2, NULL, 0, 0xffff); return True; } diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 409781eaa9..0860b7d1d9 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -81,9 +81,8 @@ BOOL use_nt_status(void) If the override errors are set they take precedence over any passed in values. ****************************************************************************/ -int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { - int outsize = set_message(outbuf,0,0,True); BOOL force_nt_status = False; BOOL force_dos_status = False; @@ -125,6 +124,11 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in eclass, ecode)); } +} +int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +{ + int outsize = set_message(outbuf,0,0,True); + error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 82052127c9..d2806753d3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -573,7 +573,8 @@ int send_trans2_replies(char *outbuf, char *params, int paramsize, char *pdata, - int datasize) + int datasize, + int max_data_bytes) { /* As we are using a protocol > LANMAN1 then the max_send variable must have been set in the sessetupX call. @@ -594,6 +595,18 @@ int send_trans2_replies(char *outbuf, set_message(outbuf,10,0,True); + /* Modify the data_to_send and datasize and set the error if + we're trying to send more than max_data_bytes. We still send + the part of the packet(s) that fit. Strange, but needed + for OS/2. */ + + if (max_data_bytes > 0 && datasize > max_data_bytes) { + DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n", + max_data_bytes, datasize )); + datasize = data_to_send = max_data_bytes; + error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__); + } + /* If there genuinely are no parameters or data to send just send the empty packet */ if(params_to_send == 0 && data_to_send == 0) { @@ -932,7 +945,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } /* Send the required number of replies */ - send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes); return -1; } @@ -1858,7 +1871,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,6,0); /* Never an EA error */ SSVAL(params,8,last_entry_off); - send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); + send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -2140,7 +2153,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,4,0); /* Never an EA error */ SSVAL(params,6,last_entry_off); - send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); + send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -2503,7 +2516,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } - send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len); + send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes); DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) ); @@ -3633,7 +3646,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size); + send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); return(-1); } @@ -3782,7 +3795,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } else return (UNIXERROR(ERRDOS,ERRbadpath)); @@ -3894,7 +3907,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if ((total_data == 4) && (IVAL(pdata,0) == 4)) { /* We're done. We only get EA info in this call. */ SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -3925,7 +3938,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char /* We're done. We only get EA info in this call. */ SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4117,7 +4130,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4146,7 +4159,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char /* We're done. We only get position info in this call. */ SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4170,7 +4183,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char /* We're done. We only get mode info in this call. */ SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4285,7 +4298,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", inherit_access_acl(conn, fname, unixmode); SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4368,7 +4381,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4392,7 +4405,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4446,7 +4459,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } process_pending_change_notify_queue((time_t)0); SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4497,7 +4510,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } #endif @@ -4603,7 +4616,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4729,7 +4742,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4834,7 +4847,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -4883,7 +4896,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char if(fnf_handle == 0) fnf_handle = 257; - send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes); return(-1); } @@ -4911,7 +4924,7 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char SSVAL(params,0,0); /* No changes */ SSVAL(params,2,0); /* No EA errors */ - send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes); return(-1); } @@ -4945,7 +4958,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* return UNIXERROR(ERRDOS,ERRbadfile); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); - send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size); + send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes); return(-1); } @@ -4983,7 +4996,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */ srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ - send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); + send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes); return(-1); } else { DEBUG(2,("Unknown TRANS2_IOCTL\n")); -- cgit From 5615d534595013eb8749037d16efd726e728c330 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 16 Aug 2006 09:10:54 +0000 Subject: r17568: Reformatting -- more than 100 cols is too much :-) (This used to be commit 2a66abca02b5e95b66ab336f0d0e3977676d4540) --- source3/smbd/server.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0fba6af697..edde12465f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -450,7 +450,8 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ if (smbd_server_fd() != -1 && interactive) return True; - if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && sys_fork()==0) { + if (allowable_number_of_smbd_processes() && + smbd_server_fd() != -1 && sys_fork()==0) { /* Child code ... */ /* close the listening socket(s) */ @@ -467,7 +468,8 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* this is needed so that we get decent entries in smbstatus for port 445 connects */ - set_remote_machine_name(get_peer_addr(smbd_server_fd()), False); + set_remote_machine_name(get_peer_addr(smbd_server_fd()), + False); /* Reset the state of the random * number generation system, so @@ -475,7 +477,8 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ * numbers as each other */ set_need_random_reseed(); - /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */ + /* tdb needs special fork handling - remove + * CLEAR_IF_FIRST flags */ if (tdb_reopen_all(1) == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); smb_panic("tdb_reopen_all failed."); -- cgit From 0be131725ff90e48d4f9696b80b35b740575fb2c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 16 Aug 2006 10:36:19 +0000 Subject: r17569: Make 'max smbd processes' more robust. Counting on the child to decrement a tdb entry is not the most reliable way to count children correctly. This increments the number of children after a fork and decrements it upon SIGCLD. I'm keeping a list of children just for consistency checks, so that we at least get a debug level 0 message if something goes wrong. Volker (This used to be commit eb45de167d24d07a218307ec5a48c0029ec097c6) --- source3/smbd/process.c | 58 +--------------------------- source3/smbd/server.c | 100 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 78 insertions(+), 80 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f8c66d93ea..a202c1fa87 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1031,60 +1031,6 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) return(outsize); } -/**************************************************************************** - Keep track of the number of running smbd's. This functionality is used to - 'hard' limit Samba overhead on resource constrained systems. -****************************************************************************/ - -static BOOL process_count_update_successful = False; - -static int32 increment_smbd_process_count(void) -{ - int32 total_smbds; - - if (lp_max_smbd_processes()) { - total_smbds = 0; - if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1) - return 1; - process_count_update_successful = True; - return total_smbds + 1; - } - return 1; -} - -void decrement_smbd_process_count(void) -{ - int32 total_smbds; - - if (lp_max_smbd_processes() && process_count_update_successful) { - total_smbds = 1; - tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1); - } -} - -static BOOL smbd_process_limit(void) -{ - int32 total_smbds; - - if (lp_max_smbd_processes()) { - - /* Always add one to the smbd process count, as exit_server() always - * subtracts one. - */ - - if (!conn_tdb_ctx()) { - DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \ -set. Ignoring max smbd restriction.\n")); - return False; - } - - total_smbds = increment_smbd_process_count(); - return total_smbds > lp_max_smbd_processes(); - } - else - return False; -} - /**************************************************************************** Process an smb from the client ****************************************************************************/ @@ -1103,8 +1049,8 @@ static void process_smb(char *inbuf, char *outbuf) deny parameters before doing any parsing of the packet passed to us by the client. This prevents attacks on our parsing code from hosts not in the hosts allow list */ - if (smbd_process_limit() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { + if (!check_access(smbd_server_fd(), lp_hostsallow(-1), + lp_hostsdeny(-1))) { /* send a negative session response "not listening on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) ); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index edde12465f..460e2cc44b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -36,6 +36,7 @@ extern struct auth_context *negprot_global_auth_context; extern pstring user_socket_options; extern SIG_ATOMIC_T got_sig_term; extern SIG_ATOMIC_T reload_after_sighup; +static SIG_ATOMIC_T got_sig_cld; #ifdef WITH_DFS extern int dcelogin_atmost_once; @@ -92,6 +93,15 @@ static void sig_hup(int sig) sys_select_signal(SIGHUP); } +/**************************************************************************** + Catch a sigcld +****************************************************************************/ +static void sig_cld(int sig) +{ + got_sig_cld = 1; + sys_select_signal(SIGCLD); +} + /**************************************************************************** Send a SIGTERM to our process group. *****************************************************************************/ @@ -189,6 +199,54 @@ static void msg_inject_fault(int msg_type, struct process_id src, } #endif /* DEVELOPER */ +struct child_pid { + struct child_pid *prev, *next; + pid_t pid; +}; + +static struct child_pid *children; +static int num_children; + +static void add_child_pid(pid_t pid) +{ + struct child_pid *child; + + if (lp_max_smbd_processes() == 0) { + /* Don't bother with the child list if we don't care anyway */ + return; + } + + child = SMB_MALLOC_P(struct child_pid); + if (child == NULL) { + DEBUG(0, ("Could not add child struct -- malloc failed\n")); + return; + } + child->pid = pid; + DLIST_ADD(children, child); + num_children += 1; +} + +static void remove_child_pid(pid_t pid) +{ + struct child_pid *child; + + if (lp_max_smbd_processes() == 0) { + /* Don't bother with the child list if we don't care anyway */ + return; + } + + for (child = children; child != NULL; child = child->next) { + if (child->pid == pid) { + struct child_pid *tmp = child; + DLIST_REMOVE(children, child); + SAFE_FREE(tmp); + num_children -= 1; + return; + } + } + + DEBUG(0, ("Could not find child %d -- ignoring\n", (int)pid)); +} /**************************************************************************** Have we reached the process limit ? @@ -201,27 +259,7 @@ static BOOL allowable_number_of_smbd_processes(void) if (!max_processes) return True; - { - TDB_CONTEXT *tdb = conn_tdb_ctx(); - int32 val; - if (!tdb) { - DEBUG(0,("allowable_number_of_smbd_processes: can't open connection tdb.\n" )); - return False; - } - - val = tdb_fetch_int32(tdb, "INFO/total_smbds"); - if (val == -1 && (tdb_error(tdb) != TDB_ERR_NOEXIST)) { - DEBUG(0,("allowable_number_of_smbd_processes: can't fetch INFO/total_smbds. Error %s\n", - tdb_errorstr(tdb) )); - return False; - } - if (val > max_processes) { - DEBUG(0,("allowable_number_of_smbd_processes: number of processes (%d) is over allowed limit (%d)\n", - val, max_processes )); - return False; - } - } - return True; + return num_children < max_processes; } /**************************************************************************** @@ -255,7 +293,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ #endif /* Stop zombies */ - CatchChild(); + CatchSignal(SIGCLD, sig_cld); FD_ZERO(&listen_set); @@ -392,6 +430,15 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* Ensure we respond to PING and DEBUG messages from the main smbd. */ message_dispatch(); + if (got_sig_cld) { + pid_t pid; + got_sig_cld = False; + + while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) { + remove_child_pid(pid); + } + } + memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); @@ -421,6 +468,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ for( ; num > 0; num--) { struct sockaddr addr; socklen_t in_addrlen = sizeof(addr); + pid_t child = 0; s = -1; for(i = 0; i < num_sockets; i++) { @@ -451,7 +499,8 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ return True; if (allowable_number_of_smbd_processes() && - smbd_server_fd() != -1 && sys_fork()==0) { + smbd_server_fd() != -1 && + ((child = sys_fork())==0)) { /* Child code ... */ /* close the listening socket(s) */ @@ -499,6 +548,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ smbd_set_server_fd(-1); + if (child != 0) { + add_child_pid(child); + } + /* Force parent to check log size after * spawning child. Fix from * klausr@ITAP.Physik.Uni-Stuttgart.De. The @@ -640,7 +693,6 @@ static void exit_server_common(enum server_exit_reason how, yield_connection(NULL,""); respond_to_all_remaining_local_messages(); - decrement_smbd_process_count(); #ifdef WITH_DFS if (dcelogin_atmost_once) { -- cgit From f3828606bd7b826dbbb8a56b61750914ea10ecc5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 18 Aug 2006 13:37:36 +0000 Subject: r17604: Fix a bug caught by g++. Jeremy, please check this! Volker (This used to be commit 8117a7b3bf3f273dd018c42864b3136dec47ec79) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d2806753d3..b4799d83cc 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4584,8 +4584,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", count, offset, lock_type, - blocking_lock, POSIX_LOCK, + blocking_lock, &status); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { -- cgit From 23535f7d49d455042f60c1123bade66bbbf592f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 21 Aug 2006 23:30:39 +0000 Subject: r17676: Fix printing bug found by kukks. Don't copy a return value into an auto on the stack that gets removed when we return from the frame :-). Jeremy. (This used to be commit 85bf8a16116e5eb9d4400e809531737d45890abb) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5c10c59054..117d3ac595 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1139,7 +1139,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(conn, fname, &fsp); + return print_fsp_open(conn, fname, result); } /* We add aARCH to this as this mode is only used if the file is -- cgit From a64925ddff467a47f7adfac4b1b977ddc0c7f4ef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Aug 2006 16:44:00 +0000 Subject: r17800: Start using struct timespec internally for file times on the wire. This allows us to go to nsec resolution for systems that support it. It should also now be easy to add a correct "create time" (birth time) for systems that support it (*BSD). I'll be watching the build farm closely after this one for breakage :-). Jeremy. (This used to be commit 425280a1d23f97ef0b0be77462386d619f47b21d) --- source3/smbd/nttrans.c | 71 ++++++++------------- source3/smbd/trans2.c | 164 +++++++++++++++++++++++++++---------------------- 2 files changed, 115 insertions(+), 120 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d107bf84d3..4dcc807c30 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -435,31 +435,6 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, /* SCVAL(p,0,NO_OPLOCK_RETURN); */ p++; SSVAL(p,0,fsp->fnum); -#if 0 - p += 2; - SIVAL(p,0,smb_action); - p += 4; - - /* Create time. */ - put_long_date(p,c_time); - p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ - p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ - p += 8; - SIVAL(p,0,fattr); /* File Attributes. */ - p += 4; - SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); - p += 8; - SOFF_T(p,0,file_len); - p += 8; - if (flags & EXTENDED_RESPONSE_REQUIRED) - SSVAL(p,2,0x7); - p += 4; - SCVAL(p,0,fsp->is_directory ? 1 : 0); -#endif DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); @@ -493,7 +468,9 @@ int reply_ntcreate_and_X(connection_struct *conn, BOOL bad_path = False; files_struct *fsp=NULL; char *p = NULL; - time_t c_time; + struct timespec c_timespec; + struct timespec a_timespec; + struct timespec m_timespec; BOOL extended_oplock_granted = False; NTSTATUS status; @@ -884,22 +861,23 @@ create_options = 0x%x root_dir_fid = 0x%x\n", p += 4; /* Create time. */ - c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + a_timespec = get_atimespec(&sbuf); + m_timespec = get_mtimespec(&sbuf); if (lp_dos_filetime_resolution(SNUM(conn))) { - c_time &= ~1; - sbuf.st_atime &= ~1; - sbuf.st_mtime &= ~1; - sbuf.st_mtime &= ~1; + dos_filetime_timespec(&c_timespec); + dos_filetime_timespec(&a_timespec); + dos_filetime_timespec(&m_timespec); } - put_long_date(p,c_time); + put_long_date_timespec(p, c_timespec); p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ + put_long_date_timespec(p, a_timespec); /* access time */ p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ + put_long_date_timespec(p, m_timespec); /* write time */ p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ + put_long_date_timespec(p, m_timespec); /* change time */ p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; @@ -1119,7 +1097,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o uint32 sd_len; uint32 ea_len; uint16 root_dir_fid; - time_t c_time; + struct timespec c_timespec; + struct timespec a_timespec; + struct timespec m_timespec; struct ea_list *ea_list = NULL; TALLOC_CTX *ctx = NULL; char *pdata = NULL; @@ -1518,22 +1498,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o p += 8; /* Create time. */ - c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + a_timespec = get_atimespec(&sbuf); + m_timespec = get_mtimespec(&sbuf); if (lp_dos_filetime_resolution(SNUM(conn))) { - c_time &= ~1; - sbuf.st_atime &= ~1; - sbuf.st_mtime &= ~1; - sbuf.st_mtime &= ~1; + dos_filetime_timespec(&c_timespec); + dos_filetime_timespec(&a_timespec); + dos_filetime_timespec(&m_timespec); } - put_long_date(p,c_time); + put_long_date_timespec(p, c_timespec); /* create time. */ p += 8; - put_long_date(p,sbuf.st_atime); /* access time */ + put_long_date_timespec(p, a_timespec); /* access time */ p += 8; - put_long_date(p,sbuf.st_mtime); /* write time */ + put_long_date_timespec(p, m_timespec); /* write time */ p += 8; - put_long_date(p,sbuf.st_mtime); /* change time */ + put_long_date_timespec(p, m_timespec); /* change time */ p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b4799d83cc..87bfa18dcf 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1077,7 +1077,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SMB_OFF_T file_size = 0; SMB_BIG_UINT allocation_size = 0; uint32 len; - time_t mdate=0, adate=0, cdate=0; + struct timespec mdate_ts, adate_ts, create_date_ts; + time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0; char *nameptr; char *last_entry_ptr; BOOL was_8_3; @@ -1089,6 +1090,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, *out_of_space = False; *got_exact_match = False; + ZERO_STRUCT(mdate_ts); + ZERO_STRUCT(adate_ts); + ZERO_STRUCT(create_date_ts); + if (!conn->dirptr) return(False); @@ -1197,17 +1202,21 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (!(mode & aDIR)) file_size = get_file_size(sbuf); allocation_size = get_allocation_size(conn,NULL,&sbuf); - mdate = sbuf.st_mtime; - adate = sbuf.st_atime; - cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + + mdate_ts = get_mtimespec(&sbuf); + adate_ts = get_atimespec(&sbuf); + create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); if (lp_dos_filetime_resolution(SNUM(conn))) { - cdate &= ~1; - mdate &= ~1; - adate &= ~1; + dos_filetime_timespec(&create_date_ts); + dos_filetime_timespec(&mdate_ts); + dos_filetime_timespec(&adate_ts); } - + create_date = convert_timespec_to_time_t(create_date_ts); + mdate = convert_timespec_to_time_t(mdate_ts); + adate = convert_timespec_to_time_t(adate_ts); + DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); found = True; @@ -1230,7 +1239,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - srv_put_dos_date2(p,0,cdate); + srv_put_dos_date2(p,0,create_date); srv_put_dos_date2(p,4,adate); srv_put_dos_date2(p,8,mdate); SIVAL(p,12,(uint32)file_size); @@ -1262,7 +1271,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - srv_put_dos_date2(p,0,cdate); + srv_put_dos_date2(p,0,create_date); srv_put_dos_date2(p,4,adate); srv_put_dos_date2(p,8,mdate); SIVAL(p,12,(uint32)file_size); @@ -1306,7 +1315,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,reskey); p += 4; } - srv_put_dos_date2(p,0,cdate); + srv_put_dos_date2(p,0,create_date); srv_put_dos_date2(p,4,adate); srv_put_dos_date2(p,8,mdate); SIVAL(p,12,(uint32)file_size); @@ -1355,10 +1364,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, was_8_3 = mangle_is_8_3(fname, True, conn->params); p += 4; SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; SOFF_T(p,0,file_size); p += 8; SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; @@ -1401,10 +1410,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; SOFF_T(p,0,file_size); p += 8; SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; @@ -1422,10 +1431,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; SOFF_T(p,0,file_size); p += 8; SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; @@ -1467,10 +1476,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; SOFF_T(p,0,file_size); p += 8; SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; @@ -1498,10 +1507,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, was_8_3 = mangle_is_8_3(fname, True, conn->params); p += 4; SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; SOFF_T(p,0,file_size); p += 8; SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; @@ -1558,9 +1567,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ p+= 8; - put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */ - put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */ - put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */ + put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */ + put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */ + put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */ p+= 24; SIVAL(p,0,sbuf.st_uid); /* user id for the owner */ @@ -2839,7 +2848,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * BOOL bad_path = False; BOOL delete_pending = False; int len; - time_t c_time; + time_t create_time, mtime, atime; + struct timespec create_time_ts, mtime_ts, atime_ts; files_struct *fsp = NULL; TALLOC_CTX *data_ctx = NULL; struct ea_list *ea_list = NULL; @@ -3058,21 +3068,25 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } pdata = *ppdata; - c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + mtime_ts = get_mtimespec(&sbuf); + atime_ts = get_atimespec(&sbuf); allocation_size = get_allocation_size(conn,fsp,&sbuf); if (fsp) { if (fsp->pending_modtime) { /* the pending modtime overrides the current modtime */ - sbuf.st_mtime = fsp->pending_modtime; + mtime_ts.tv_sec = fsp->pending_modtime; + mtime_ts.tv_nsec = 0; } } else { /* Do we have this path open ? */ files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); if (fsp1 && fsp1->pending_modtime) { /* the pending modtime overrides the current modtime */ - sbuf.st_mtime = fsp1->pending_modtime; + mtime_ts.tv_sec = fsp->pending_modtime; + mtime_ts.tv_nsec = 0; } if (fsp1 && fsp1->initial_allocation_size) { allocation_size = get_allocation_size(conn, fsp1, &sbuf); @@ -3080,12 +3094,15 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } if (lp_dos_filetime_resolution(SNUM(conn))) { - c_time &= ~1; - sbuf.st_atime &= ~1; - sbuf.st_ctime &= ~1; - sbuf.st_mtime &= ~1; + dos_filetime_timespec(&create_time_ts); + dos_filetime_timespec(&mtime_ts); + dos_filetime_timespec(&atime_ts); } + create_time = convert_timespec_to_time_t(create_time_ts); + mtime = convert_timespec_to_time_t(mtime_ts); + atime = convert_timespec_to_time_t(atime_ts); + /* NT expects the name to be in an exact form of the *full* filename. See the trans2 torture test */ if (strequal(base_name,".")) { @@ -3099,9 +3116,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_INFO_STANDARD: DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n")); data_size = 22; - srv_put_dos_date2(pdata,l1_fdateCreation,c_time); - srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); - srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ + srv_put_dos_date2(pdata,l1_fdateCreation,create_time); + srv_put_dos_date2(pdata,l1_fdateLastAccess,atime); + srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */ SIVAL(pdata,l1_cbFile,(uint32)file_size); SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(pdata,l1_attrFile,mode); @@ -3112,9 +3129,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd unsigned int ea_size = estimate_ea_size(conn, fsp, fname); DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n")); data_size = 26; - srv_put_dos_date2(pdata,0,c_time); - srv_put_dos_date2(pdata,4,sbuf.st_atime); - srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */ + srv_put_dos_date2(pdata,0,create_time); + srv_put_dos_date2(pdata,4,atime); + srv_put_dos_date2(pdata,8,mtime); /* write time */ SIVAL(pdata,12,(uint32)file_size); SIVAL(pdata,16,(uint32)allocation_size); SSVAL(pdata,20,mode); @@ -3190,20 +3207,17 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 40; SIVAL(pdata,36,0); } - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + put_long_date_timespec(pdata,create_time_ts); + put_long_date_timespec(pdata+8,atime_ts); + put_long_date_timespec(pdata+16,mtime_ts); /* write time */ + put_long_date_timespec(pdata+24,mtime_ts); /* change time */ SIVAL(pdata,32,mode); DEBUG(5,("SMB_QFBI - ")); - { - time_t create_time = c_time; - DEBUG(5,("create: %s ", ctime(&create_time))); - } - DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); - DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); - DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); + DEBUG(5,("create: %s ", ctime(&create_time))); + DEBUG(5,("access: %s ", ctime(&atime))); + DEBUG(5,("write: %s ", ctime(&mtime))); + DEBUG(5,("change: %s ", ctime(&mtime))); DEBUG(5,("mode: %x\n", mode)); break; @@ -3277,10 +3291,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd { unsigned int ea_size = estimate_ea_size(conn, fsp, fname); DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n")); - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + put_long_date_timespec(pdata,create_time_ts); + put_long_date_timespec(pdata+8,atime_ts); + put_long_date_timespec(pdata+16,mtime_ts); /* write time */ + put_long_date_timespec(pdata+24,mtime_ts); /* change time */ SIVAL(pdata,32,mode); SIVAL(pdata,36,0); /* padding. */ pdata += 40; @@ -3387,10 +3401,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_FILE_NETWORK_OPEN_INFORMATION: DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n")); - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ + put_long_date_timespec(pdata,create_time_ts); + put_long_date_timespec(pdata+8,atime_ts); + put_long_date_timespec(pdata+16,mtime_ts); /* write time */ + put_long_date_timespec(pdata+24,mtime_ts); /* change time */ SIVAL(pdata,32,allocation_size); SOFF_T(pdata,40,file_size); SIVAL(pdata,48,mode); @@ -3420,9 +3434,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; - put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */ - put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */ - put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */ + put_long_date_timespec(pdata,get_ctimespec(&sbuf)); /* Creation Time 64 Bit */ + put_long_date_timespec(pdata+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */ + put_long_date_timespec(pdata+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */ pdata += 24; SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */ @@ -3983,10 +3997,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char /* Ignore create time at offset pdata. */ /* access time */ - tvs.actime = interpret_long_date(pdata+8); + tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); - write_time = interpret_long_date(pdata+16); - changed_time = interpret_long_date(pdata+24); + write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16)); + changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24)); tvs.modtime = MIN(write_time, changed_time); @@ -4212,8 +4226,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #endif /* LARGE_SMB_OFF_T */ } pdata+=24; /* ctime & st_blocks are not changed */ - tvs.actime = interpret_long_date(pdata); /* access_time */ - tvs.modtime = interpret_long_date(pdata+8); /* modification_time */ + tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */ + tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */ pdata+=16; set_owner = (uid_t)IVAL(pdata,0); pdata += 8; -- cgit From 9230c659f66df3da9fda5e7cae1717f19c9c08c7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Aug 2006 18:24:43 +0000 Subject: r17835: Fix Coverity bugs 306, 309, 310. Jeremy, you might want to look at the trans2 one. Volker (This used to be commit d727fc681c073a1b09accd31a07341b58e10eebb) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 87bfa18dcf..f40dd5154b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3085,7 +3085,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); if (fsp1 && fsp1->pending_modtime) { /* the pending modtime overrides the current modtime */ - mtime_ts.tv_sec = fsp->pending_modtime; + mtime_ts.tv_sec = fsp1->pending_modtime; mtime_ts.tv_nsec = 0; } if (fsp1 && fsp1->initial_allocation_size) { -- cgit From 47e29ebe0975f63f972d137fca30fec843492f78 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Aug 2006 19:13:37 +0000 Subject: r17836: Don't create zombies in the children, thanks to Jeremy! Volker (This used to be commit c0767c08d01a429e1abf7205c14acec5e103ca91) --- source3/smbd/server.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 460e2cc44b..a7a84eced1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -502,6 +502,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ smbd_server_fd() != -1 && ((child = sys_fork())==0)) { /* Child code ... */ + + /* Stop zombies, the parent explicitly handles + * them, counting worker smbds. */ + CatchChild(); /* close the listening socket(s) */ for(i = 0; i < num_sockets; i++) -- cgit From 00ffc8ec93600bd20e380c1242a946749acf0843 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Aug 2006 05:41:32 +0000 Subject: r17879: Make it explicit that we can never pass NULL for buflen or stringlen. Stanford Checker fix. Jeremy. (This used to be commit 2d8bdd2dce633253780a5b0378f229893d049666) --- source3/smbd/lanman.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 2d6db8f2a3..da1def4361 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1195,12 +1195,8 @@ static int fill_srv_info(struct srv_info_struct *service, break; } - if (buflen) { - *buflen = struct_len; - } - if (stringspace) { - *stringspace = len; - } + *buflen = struct_len; + *stringspace = len; return struct_len + len; } -- cgit From 49a08c7c5a099fc9bd45493622c001124f41ce8c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 Aug 2006 18:25:55 +0000 Subject: r17896: Reformatting. I did not want to do it anymore, but these ones looked just silly :-) Volker (This used to be commit 8b6f5937db4b18db711dd0c4f1ae904087249000) --- source3/smbd/oplock_linux.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index f186c13ebd..518283c587 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -89,7 +89,8 @@ static void set_capability(unsigned capability) header.pid = 0; if (capget(&header, &data) == -1) { - DEBUG(3,("Unable to get kernel capabilities (%s)\n", strerror(errno))); + DEBUG(3,("Unable to get kernel capabilities (%s)\n", + strerror(errno))); return; } @@ -156,15 +157,18 @@ static files_struct *linux_oplock_receive_message(fd_set *fds) static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) { - DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ -inode = %.0f. (%s)\n", + DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " + "fd = %d, dev = %x, inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fh->fd, - (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno))); + (unsigned int)fsp->dev, (double)fsp->inode, + strerror(errno))); return False; } - DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id)); + DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, " + "dev = %x, inode = %.0f, file_id = %lu\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, + fsp->fh->file_id)); return True; } @@ -181,8 +185,9 @@ static void linux_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); - dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ -oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, + dbgtext("linux_release_kernel_oplock: file %s, dev = %x, " + "inode = %.0f file_id = %lu has kernel oplock state " + "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id, state ); } @@ -191,10 +196,12 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, */ if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { - dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, strerror(errno) ); + dbgtext("linux_release_kernel_oplock: Error when " + "removing kernel oplock on file " ); + dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. " + "Error was %s\n", fsp->fsp_name, + (unsigned int)fsp->dev, (double)fsp->inode, + fsp->fh->file_id, strerror(errno) ); } } } -- cgit From 545353b062a82920fa8040f248d55c04da33f735 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 29 Aug 2006 15:42:09 +0000 Subject: r17909: ensure we do not call map_username() twice on Krb5 session setups (This used to be commit 779eba0a7cab3156b8580410cfe288609a288548) --- source3/smbd/sesssetup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index fb579707ca..dd8d9fc852 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -320,10 +320,14 @@ static int reply_spnego_kerberos(connection_struct *conn, sub_set_smb_name( real_username ); reload_services(True); + if ( map_domainuser_to_guest ) { make_server_info_guest(&server_info); } else if (logon_info) { - ret = make_server_info_info3(mem_ctx, real_username, domain, + /* pass the unmapped username here since map_username() + will be called again from inside make_server_info_info3() */ + + ret = make_server_info_info3(mem_ctx, user, domain, &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", -- cgit From d07458bd67a29c0a8abfa6e72115732e18f51b2f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Sep 2006 16:51:17 +0000 Subject: r18224: Paranoia - ensure the oplock event handler is removed immediately in the handler. Extra debug info tracking down winbindd DC selection. Jeremy. (This used to be commit 7ba9b6ce588f716589e9f88ed146fad36c4b3758) --- source3/smbd/oplock.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index eec19259d0..aaa236effa 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -348,6 +348,12 @@ static void oplock_timeout_handler(struct timed_event *te, { files_struct *fsp = (files_struct *)private_data; + /* Ensure we always remove this event. */ + if (fsp->oplock_timeout != NULL) { + /* Remove the timed event handler. */ + TALLOC_FREE(fsp->oplock_timeout); + fsp->oplock_timeout = NULL; + } DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name)); global_client_failed_oplock_break = True; remove_oplock(fsp); -- cgit From 2b27c93a9a8471693d7dcb5fdbe8afe65b22ff66 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 8 Sep 2006 14:28:06 +0000 Subject: r18271: Big change: * autogenerate lsa ndr code * rename 'enum SID_NAME_USE' to 'enum lsa_SidType' * merge a log more security descriptor functions from gen_ndr/ndr_security.c in SAMBA_4_0 The most embarassing thing is the "#define strlen_m strlen" We need a real implementation in SAMBA_3_0 which I'll work on after this code is in. (This used to be commit 3da9f80c28b1e75ef6d46d38fbb81ade6b9fa951) --- source3/smbd/lanman.c | 2 +- source3/smbd/service.c | 2 +- source3/smbd/share_access.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index da1def4361..637d5b4120 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1977,7 +1977,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para size_t i; NTSTATUS result; DOM_SID user_sid; - enum SID_NAME_USE type; + enum lsa_SidType type; TALLOC_CTX *mem_ctx; *rparam_len = 8; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d0ad6fa7e6..734feef4f7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -420,7 +420,7 @@ static NTSTATUS find_forced_group(BOOL force_user, NTSTATUS result = NT_STATUS_NO_SUCH_GROUP; TALLOC_CTX *mem_ctx; DOM_SID group_sid; - enum SID_NAME_USE type; + enum lsa_SidType type; char *groupname; BOOL user_must_be_member = False; gid_t gid; diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index 09b56c3522..cee88bcf0b 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -73,7 +73,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, { const char *prefix; DOM_SID sid; - enum SID_NAME_USE type; + enum lsa_SidType type; if (username != NULL) { name = talloc_sub_basic(mem_ctx, username, -- cgit From c432bfc14b18988f1e74a6364340eb1f09084b2e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Sep 2006 21:06:44 +0000 Subject: r18398: Fix bug #4095 - username composed into domain\user twice in spnego path. Jerry please check. Jeremy. (This used to be commit e872bacf2850cfb66be1c57be40484fe8e4c2da5) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index dd8d9fc852..8c8173ef37 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -327,7 +327,7 @@ static int reply_spnego_kerberos(connection_struct *conn, /* pass the unmapped username here since map_username() will be called again from inside make_server_info_info3() */ - ret = make_server_info_info3(mem_ctx, user, domain, + ret = make_server_info_info3(mem_ctx, client, domain, &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", -- cgit From 68a2430c526ae4b94ecec9690a64936299808140 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Sep 2006 21:48:30 +0000 Subject: r18403: Revert until we get this sorted out correctly. Jeremy. (This used to be commit d0fdd5eb1e0c8bf135c267d4ff8183899345beaa) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8c8173ef37..dd8d9fc852 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -327,7 +327,7 @@ static int reply_spnego_kerberos(connection_struct *conn, /* pass the unmapped username here since map_username() will be called again from inside make_server_info_info3() */ - ret = make_server_info_info3(mem_ctx, client, domain, + ret = make_server_info_info3(mem_ctx, user, domain, &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", -- cgit From 48e2a2bfb75cdc914345b498012e82331546f0c0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 13 Sep 2006 16:28:25 +0000 Subject: r18481: Use pidl-generated server side code for dfs. (This used to be commit 3f337c104d42321595161d0283b39357df252a8e) --- source3/smbd/msdfs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 44415ddd16..1f04356b4f 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -30,7 +30,7 @@ extern uint32 global_client_caps; into the dfs_path structure **********************************************************************/ -static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp) +static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp) { pstring pathname_local; char *p, *temp; @@ -317,7 +317,8 @@ TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp are also NULL. *****************************************************************/ -static BOOL resolve_dfs_path(TALLOC_CTX *ctx, pstring dfspath, struct dfs_path *dp, +static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, + struct dfs_path *dp, connection_struct *conn, BOOL search_flag, struct referral **reflistpp, int *refcntp, BOOL *self_referralp, int *consumedcntp) @@ -459,7 +460,7 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_ Return a self referral. **********************************************************************/ -static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, +static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct referral *ref; @@ -490,7 +491,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, junction_map structure. **********************************************************************/ -BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, +BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct dfs_path dp; @@ -880,7 +881,7 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref Creates a junction structure from a Dfs pathname **********************************************************************/ -BOOL create_junction(char *pathname, struct junction_map *jucn) +BOOL create_junction(const char *pathname, struct junction_map *jucn) { struct dfs_path dp; -- cgit From 315ad641c381b0630976eff711f251d1831ffc7c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Sep 2006 09:06:36 +0000 Subject: r18547: Add in fixes to mangling dir code - ensure don't look in the paths for wcard - always read directly from incoming packet. Jeremy. (This used to be commit 3745a1af4ea9262fcda28931539fa6ab4c9060d1) --- source3/smbd/dir.c | 91 +++++++++++++++++++++++++++++---------------------- source3/smbd/trans2.c | 10 +++--- 2 files changed, 56 insertions(+), 45 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 96e0923dbd..1c77630ee7 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -61,6 +61,7 @@ struct dptr_struct { uint32 attr; char *path; BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ + BOOL did_stat; /* Optimisation for non-wcard searches. */ }; static struct bitmap *dptr_bmap; @@ -535,6 +536,11 @@ long dptr_TellDir(struct dptr_struct *dptr) return TellDir(dptr->dir_hnd); } +BOOL dptr_has_wild(struct dptr_struct *dptr) +{ + return dptr->has_wild; +} + /**************************************************************************** Return the next visible file name, skipping veto'd and invisible files. ****************************************************************************/ @@ -557,8 +563,6 @@ static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffs const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) { - pstring pathreal; - SET_STAT_INVALID(*pst); if (dptr->has_wild) { @@ -571,55 +575,62 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT return NULL; } - /* We know the stored wcard contains no wildcard characters. See if we can match - with a stat call. If we can't, then set has_wild to true to - prevent us from doing this on every call. */ + if (!dptr->did_stat) { + pstring pathreal; - /* First check if it should be visible. */ - if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) { - dptr->has_wild = True; - return dptr_normal_ReadDirName(dptr, poffset, pst); - } + /* We know the stored wcard contains no wildcard characters. See if we can match + with a stat call. If we can't, then set did_stat to true to + ensure we only do this once and keep searching. */ - if (VALID_STAT(*pst)) { - /* We need to set the underlying dir_hdn offset to -1 also as - this function is usually called with the output from TellDir. */ - dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; - return dptr->wcard; - } + dptr->did_stat = True; - pstrcpy(pathreal,dptr->path); - pstrcat(pathreal,"/"); - pstrcat(pathreal,dptr->wcard); + /* First check if it should be visible. */ + if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) { + /* This only returns False if the file was found, but + is explicitly not visible. Set us to end of directory, + but return NULL as we know we can't ever find it. */ + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; + return NULL; + } - if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { - /* We need to set the underlying dir_hdn offset to -1 also as - this function is usually called with the output from TellDir. */ - dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; - return dptr->wcard; - } else { - /* If we get any other error than ENOENT or ENOTDIR - then the file exists we just can't stat it. */ - if (errno != ENOENT && errno != ENOTDIR) { - /* We need to set the underlying dir_hdn offset to -1 also as + if (VALID_STAT(*pst)) { + /* We need to set the underlying dir_hnd offset to -1 also as this function is usually called with the output from TellDir. */ dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; return dptr->wcard; } - } - /* In case sensitive mode we don't search - we know if it doesn't exist - with a stat we will fail. */ + pstrcpy(pathreal,dptr->path); + pstrcat(pathreal,"/"); + pstrcat(pathreal,dptr->wcard); - if (dptr->conn->case_sensitive) { - /* We need to set the underlying dir_hdn offset to -1 also as - this function is usually called with the output from TellDir. */ - dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; - return NULL; - } else { - dptr->has_wild = True; - return dptr_normal_ReadDirName(dptr, poffset, pst); + if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { + /* We need to set the underlying dir_hnd offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; + return dptr->wcard; + } else { + /* If we get any other error than ENOENT or ENOTDIR + then the file exists we just can't stat it. */ + if (errno != ENOENT && errno != ENOTDIR) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; + return dptr->wcard; + } + } + + /* In case sensitive mode we don't search - we know if it doesn't exist + with a stat we will fail. */ + + if (dptr->conn->case_sensitive) { + /* We need to set the underlying dir_hnd offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; + return NULL; + } } + return dptr_normal_ReadDirName(dptr, poffset, pst); } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f40dd5154b..adbba92ee7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -957,16 +957,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i Case can be significant or not. **********************************************************/ -static BOOL exact_match(char *str,char *mask, BOOL case_sig) +static BOOL exact_match(connection_struct *conn, char *str, char *mask) { if (mask[0] == '.' && mask[1] == 0) return False; - if (case_sig) + if (conn->case_sensitive) return strcmp(str,mask)==0; if (StrCaseCmp(str,mask) != 0) { return False; } - if (ms_has_wild(str)) { + if (dptr_has_wild(conn->dirptr)) { return False; } return True; @@ -1132,7 +1132,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(fname,dname); - if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive))) + if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) got_match = mask_match(fname, mask, conn->case_sensitive); if(!got_match && check_mangled_names && @@ -1148,7 +1148,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstring newname; pstrcpy( newname, fname); mangle_map( newname, True, False, conn->params); - if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive))) + if(!(got_match = *got_exact_match = exact_match(conn, newname, mask))) got_match = mask_match(newname, mask, conn->case_sensitive); } -- cgit From 8155621d54c7385a60274b30572770bd4f17e504 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Sep 2006 02:27:48 +0000 Subject: r18603: Add in the NFSv4 ACL mapping code from IBM. Sorry for the delay :-). Jeremy. (This used to be commit a52fa218952ffcd784ea31e947aa4d17dfdc8ee0) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a431f6e07a..a1903ef4bb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -901,7 +901,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ -static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) { DOM_SID owner_sid; DOM_SID grp_sid; @@ -2989,7 +2989,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) then allow chown to the currently authenticated user. ****************************************************************************/ -static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) +int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; files_struct *fsp; @@ -3105,7 +3105,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) { + if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) { return False; } -- cgit From 258a465e20e007a30043220367d17ecfc87b4f90 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 18 Sep 2006 07:52:16 +0000 Subject: r18605: sync dlinklist.h with samba4, that means DLIST_ADD_END() and DLIST_DEMOTE() now take the type of the tmp pointer not the tmp pointer itself anymore. metze (This used to be commit 2f58645b7094e81dff3734f11aa183ea2ab53d2d) --- source3/smbd/blocking.c | 4 ++-- source3/smbd/nttrans.c | 3 +-- source3/smbd/posix_acls.c | 16 ++++++---------- source3/smbd/process.c | 3 +-- source3/smbd/trans2.c | 10 ++++------ 5 files changed, 14 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2f89759ffd..f489a8e96b 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -86,7 +86,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, SMB_BIG_UINT offset, SMB_BIG_UINT count) { static BOOL set_lock_msg; - blocking_lock_record *blr, *tmp; + blocking_lock_record *blr; NTSTATUS status; if(in_chained_smb() ) { @@ -148,7 +148,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, return False; } - DLIST_ADD_END(blocking_lock_queue, blr, tmp); + DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *); /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4dcc807c30..c5e48a6324 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1049,14 +1049,13 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, while (offset + 4 <= data_size) { size_t next_offset = IVAL(pdata,offset); - struct ea_list *tmp; struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); if (!eal) { return NULL; } - DLIST_ADD_END(ea_list_head, eal, tmp); + DLIST_ADD_END(ea_list_head, eal, struct ea_list *); if (next_offset == 0) { break; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a1903ef4bb..18ef187f38 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1241,7 +1241,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; - canon_ace *tmp_ace = NULL; canon_ace *current_ace = NULL; BOOL got_dir_allow = False; BOOL got_file_allow = False; @@ -1429,7 +1428,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) == (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) { - DLIST_ADD_END(dir_ace, current_ace, tmp_ace); + DLIST_ADD_END(dir_ace, current_ace, canon_ace *); /* * Note if this was an allow ace. We can't process @@ -1487,7 +1486,7 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); */ if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) { - DLIST_ADD_END(file_ace, current_ace, tmp_ace); + DLIST_ADD_END(file_ace, current_ace, canon_ace *); /* * Note if this was an allow ace. We can't process @@ -1734,7 +1733,6 @@ static void process_deny_list( canon_ace **pp_ace_list ) for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) { mode_t new_perms = (mode_t)0; canon_ace *allow_ace_p; - canon_ace *tmp_ace; curr_ace_next = curr_ace->next; /* So we can't lose the link. */ @@ -1753,7 +1751,7 @@ static void process_deny_list( canon_ace **pp_ace_list ) curr_ace->attr = ALLOW_ACE; curr_ace->perms = (mode_t)0; - DLIST_DEMOTE(ace_list, curr_ace, tmp_ace); + DLIST_DEMOTE(ace_list, curr_ace, canon_ace *); continue; } @@ -1778,13 +1776,12 @@ static void process_deny_list( canon_ace **pp_ace_list ) curr_ace->attr = ALLOW_ACE; curr_ace->perms = (new_perms & ~curr_ace->perms); - DLIST_DEMOTE(ace_list, curr_ace, tmp_ace); + DLIST_DEMOTE(ace_list, curr_ace, canon_ace *); } /* Pass 3 above - deal with deny group entries. */ for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) { - canon_ace *tmp_ace; canon_ace *allow_ace_p; canon_ace *allow_everyone_p = NULL; @@ -1826,8 +1823,7 @@ static void process_deny_list( canon_ace **pp_ace_list ) curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms; else curr_ace->perms = (mode_t)0; - DLIST_DEMOTE(ace_list, curr_ace, tmp_ace); - + DLIST_DEMOTE(ace_list, curr_ace, canon_ace *); } /* Doing this fourth pass allows Windows semantics to be layered @@ -2067,7 +2063,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) } if (other_ace) { - DLIST_DEMOTE(list_head, other_ace, ace); + DLIST_DEMOTE(list_head, other_ace, canon_ace *); } /* We have probably changed the head of the list. */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a202c1fa87..cf61e16a15 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -75,7 +75,6 @@ static BOOL push_queued_message(char *buf, int msg_len, struct timeval end_time, char *private_data, size_t private_len) { - struct pending_message_list *tmp_msg; struct pending_message_list *msg; msg = TALLOC_ZERO_P(NULL, struct pending_message_list); @@ -105,7 +104,7 @@ static BOOL push_queued_message(char *buf, int msg_len, } } - DLIST_ADD_END(deferred_open_queue, msg, tmp_msg); + DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *); DEBUG(10,("push_message: pushed message length %u on " "deferred_open_queue\n", (unsigned int)msg_len)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index adbba92ee7..f2f0150f6f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -197,7 +197,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str if (sizeret) { for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { - struct ea_list *listp, *tmp; + struct ea_list *listp; if (strnequal(p, "system.", 7) || samba_private_attr_name(p)) continue; @@ -218,7 +218,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str (unsigned int)*pea_total_len, dos_ea_name, (unsigned int)listp->ea.value.length )); } - DLIST_ADD_END(ea_list_head, listp, tmp); + DLIST_ADD_END(ea_list_head, listp, struct ea_list *); } /* Add on 4 for total length. */ if (*pea_total_len) { @@ -396,7 +396,6 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz size_t offset = 0; while (offset + 2 < data_size) { - struct ea_list *tmp; struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); unsigned int namelen = CVAL(pdata,offset); @@ -418,7 +417,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz } offset += (namelen + 1); /* Go past the name + terminating zero. */ - DLIST_ADD_END(ea_list_head, eal, tmp); + DLIST_ADD_END(ea_list_head, eal, struct ea_list *); DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); } @@ -493,14 +492,13 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d size_t bytes_used = 0; while (offset < data_size) { - struct ea_list *tmp; struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used); if (!eal) { return NULL; } - DLIST_ADD_END(ea_list_head, eal, tmp); + DLIST_ADD_END(ea_list_head, eal, struct ea_list *); offset += bytes_used; } -- cgit From 4db7642caa99c1b054322a8971c4b673556487ce Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 20 Sep 2006 22:23:12 +0000 Subject: r18745: Use the Samba4 data structures for security descriptors and security descriptor buffers. Make security access masks simply a uint32 rather than a structure with a uint32 in it. (This used to be commit b41c52b9db5fc4a553b20a7a5a051a4afced9366) --- source3/smbd/nttrans.c | 8 +++---- source3/smbd/posix_acls.c | 54 +++++++++++++++++++++++------------------------ 2 files changed, 31 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c5e48a6324..9cebd21d7d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1009,16 +1009,16 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu return NT_STATUS_NO_MEMORY; } - if (psd->off_owner_sid==0) { + if (psd->owner_sid==0) { security_info_sent &= ~OWNER_SECURITY_INFORMATION; } - if (psd->off_grp_sid==0) { + if (psd->group_sid==0) { security_info_sent &= ~GROUP_SECURITY_INFORMATION; } - if (psd->off_sacl==0) { + if (psd->sacl==0) { security_info_sent &= ~SACL_SECURITY_INFORMATION; } - if (psd->off_dacl==0) { + if (psd->dacl==0) { security_info_sent &= ~DACL_SECURITY_INFORMATION; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 18ef187f38..3b38b91547 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -860,36 +860,36 @@ static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_ #define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) #define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) -static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) +static mode_t map_nt_perms( uint32 *mask, int type) { mode_t mode = 0; switch(type) { case S_IRUSR: - if(sec_access.mask & GENERIC_ALL_ACCESS) + if((*mask) & GENERIC_ALL_ACCESS) mode = S_IRUSR|S_IWUSR|S_IXUSR; else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; + mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; + mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; + mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; } break; case S_IRGRP: - if(sec_access.mask & GENERIC_ALL_ACCESS) + if((*mask) & GENERIC_ALL_ACCESS) mode = S_IRGRP|S_IWGRP|S_IXGRP; else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; + mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; + mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; + mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; } break; case S_IROTH: - if(sec_access.mask & GENERIC_ALL_ACCESS) + if((*mask) & GENERIC_ALL_ACCESS) mode = S_IROTH|S_IWOTH|S_IXOTH; else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; + mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; + mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; + mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; } break; } @@ -950,7 +950,7 @@ BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_ */ if (security_info_sent & GROUP_SECURITY_INFORMATION) { - sid_copy(&grp_sid, psd->grp_sid); + sid_copy(&grp_sid, psd->group_sid); if (!sid_to_gid( &grp_sid, pgrp)) { if (lp_force_unknown_acl_user(snum)) { /* this allows take group ownership to work @@ -1254,7 +1254,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, */ for(i = 0; i < dacl->num_aces; i++) { - SEC_ACE *psa = &dacl->ace[i]; + SEC_ACE *psa = &dacl->aces[i]; if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n")); @@ -1273,12 +1273,12 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, * Convert GENERIC bits to specific bits. */ - se_map_generic(&psa->info.mask, &file_generic_mapping); + se_map_generic(&psa->access_mask, &file_generic_mapping); - psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS); + psa->access_mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS); - if(psa->info.mask != UNIX_ACCESS_NONE) - psa->info.mask &= ~UNIX_ACCESS_NONE; + if(psa->access_mask != UNIX_ACCESS_NONE) + psa->access_mask &= ~UNIX_ACCESS_NONE; } } @@ -1291,12 +1291,12 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, */ for(i = 0; i < dacl->num_aces; i++) { - SEC_ACE *psa1 = &dacl->ace[i]; + SEC_ACE *psa1 = &dacl->aces[i]; for (j = i + 1; j < dacl->num_aces; j++) { - SEC_ACE *psa2 = &dacl->ace[j]; + SEC_ACE *psa2 = &dacl->aces[j]; - if (psa1->info.mask != psa2->info.mask) + if (psa1->access_mask != psa2->access_mask) continue; if (!sid_equal(&psa1->trustee, &psa2->trustee)) @@ -1322,7 +1322,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, } for(i = 0; i < dacl->num_aces; i++) { - SEC_ACE *psa = &dacl->ace[i]; + SEC_ACE *psa = &dacl->aces[i]; /* * Ignore non-mappable SIDs (NT Authority, BUILTIN etc). @@ -1408,7 +1408,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, * S_I(R|W|X)USR bits. */ - current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); + current_ace->perms |= map_nt_perms( &psa->access_mask, S_IRUSR); current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE; current_ace->inherited = ((psa->flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False); @@ -2641,7 +2641,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) /* We know the lower number ACE's are file entries. */ if ((nt_ace_list[i].type == nt_ace_list[j].type) && (nt_ace_list[i].size == nt_ace_list[j].size) && - (nt_ace_list[i].info.mask == nt_ace_list[j].info.mask) && + (nt_ace_list[i].access_mask == nt_ace_list[j].access_mask) && sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) && (i_inh == j_inh) && (i_flags_ni == 0) && @@ -2654,7 +2654,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) * the non-inherited ACE onto the inherited ACE. */ - if (nt_ace_list[i].info.mask == 0) { + if (nt_ace_list[i].access_mask == 0) { nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0); if (num_aces - i - 1 > 0) @@ -2954,7 +2954,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } if (psd->dacl) { - dacl_sort_into_canonical_order(psd->dacl->ace, (unsigned int)psd->dacl->num_aces); + dacl_sort_into_canonical_order(psd->dacl->aces, (unsigned int)psd->dacl->num_aces); } *ppdesc = psd; -- cgit From 45ca718d1903cfd400c9e12665c59f3089fe2318 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Sep 2006 00:30:47 +0000 Subject: r18760: Fix typos, remove unneeded code (This used to be commit 56ccfe98b299e1569d59ef447ac486209aa84ca0) --- source3/smbd/negprot.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 3347008cdf..4362bb5467 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -33,7 +33,8 @@ static void get_challenge(char buff[8]) NTSTATUS nt_status; const uint8 *cryptkey; - /* We might be called more than once, muliple negprots are premitted */ + /* We might be called more than once, multiple negprots are + * permitted */ if (negprot_global_auth_context) { DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n")); (negprot_global_auth_context->free)(&negprot_global_auth_context); @@ -190,15 +191,6 @@ static int negprot_spnego(char *p, uint8 *pkeylen) push_ascii_nstring(dos_name, unix_name); safe_strcpy(guid, dos_name, sizeof(guid)-1); -#ifdef DEVELOPER - /* valgrind fixer... */ - { - size_t sl = strlen(guid); - if (sizeof(guid)-sl) - memset(&guid[sl], '\0', sizeof(guid)-sl); - } -#endif - /* strangely enough, NT does not sent the single OID NTLMSSP when not a ADS member, it sends no OIDs at all -- cgit From 8f7643bd8345de0be03b59db2e9490ee5e0ca85f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Sep 2006 01:49:18 +0000 Subject: r18761: Even if only offering NTLMSSP Windows (tested with Vista & XP) sends 0 as the key length in the case of extended security. It does make sense because with SPNEGO our beloved ASN1 structure gives us the length. Next test I did to verify this: I modified the server to put in random garbage, and W2kwks, XP, Vista and W2k3srv still talked to us. Volker (This used to be commit f19bd479cee57f064f63659c533ae108885d54a2) --- source3/smbd/negprot.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 4362bb5467..b984558fb4 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -230,11 +230,8 @@ static int negprot_spnego(char *p, uint8 *pkeylen) } data_blob_free(&blob); - if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) { - *pkeylen = 0; - } else { - *pkeylen = len; - } + *pkeylen = 0; + return len; } -- cgit From a4a2d795b1dc218705cf8bd148a4e59845155f7c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Sep 2006 05:07:47 +0000 Subject: r18771: Sequel to r18761: If we always set the keylen to 0 there's no point in passing a pointer down to negprot_spnego(). Volker (This used to be commit 18f47130b1ccf09873ca684ee0ea986e28f47d78) --- source3/smbd/negprot.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b984558fb4..2df7f45aba 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -169,7 +169,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) Generate the spnego negprot reply blob. Return the number of bytes used. ****************************************************************************/ -static int negprot_spnego(char *p, uint8 *pkeylen) +static int negprot_spnego(char *p) { DATA_BLOB blob; nstring dos_name; @@ -230,8 +230,6 @@ static int negprot_spnego(char *p, uint8 *pkeylen) } data_blob_free(&blob); - *pkeylen = 0; - return len; } @@ -338,10 +336,9 @@ static int reply_nt1(char *inbuf, char *outbuf) STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); } else { - uint8 keylen; - int len = negprot_spnego(p, &keylen); + int len = negprot_spnego(p); - SCVAL(outbuf,smb_vwv16+1,keylen); + SCVAL(outbuf,smb_vwv16+1, 0); p += len; DEBUG(3,("using SPNEGO\n")); } -- cgit From 3bddf16b1f61930f58b49070f1ca8a1c7df50886 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Sep 2006 05:19:22 +0000 Subject: r18772: Now that we don't have a one-byte keylength in the extended security case anymore, we don't have to truncate the length to 255 anymore. The test I did for this: I sent 50 times the NTLMSSP oid. With truncating Vista said Access Denied, without truncating it liked the response. Volker (This used to be commit f1512cb43c69338d4f2cb806486c4f5db51cf695) --- source3/smbd/negprot.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 2df7f45aba..b583623a4b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -224,10 +224,6 @@ static int negprot_spnego(char *p) memcpy(p, blob.data, blob.length); len = blob.length; - if (len > 256) { - DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len)); - len = 255; - } data_blob_free(&blob); return len; -- cgit From c209219d062830aa95e39cd97ac988244f1fc49b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Sep 2006 05:29:07 +0000 Subject: r18773: Change negprot_spnego to return a blob (This used to be commit 28fa772721640a6d3a0f6a30fb56fde18b5f5616) --- source3/smbd/negprot.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b583623a4b..bbd1013050 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -169,7 +169,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) Generate the spnego negprot reply blob. Return the number of bytes used. ****************************************************************************/ -static int negprot_spnego(char *p) +static DATA_BLOB negprot_spnego(void) { DATA_BLOB blob; nstring dos_name; @@ -180,7 +180,6 @@ static int negprot_spnego(char *p) OID_NTLMSSP, NULL}; const char *OIDs_plain[] = {OID_NTLMSSP, NULL}; - int len; global_spnego_negotiated = True; @@ -222,11 +221,7 @@ static int negprot_spnego(char *p) SAFE_FREE(host_princ_s); } - memcpy(p, blob.data, blob.length); - len = blob.length; - data_blob_free(&blob); - - return len; + return blob; } /**************************************************************************** @@ -332,10 +327,17 @@ static int reply_nt1(char *inbuf, char *outbuf) STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); } else { - int len = negprot_spnego(p); - + DATA_BLOB spnego_blob = negprot_spnego(); + + if (spnego_blob.data == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + memcpy(p, spnego_blob.data, spnego_blob.length); + p += spnego_blob.length; + data_blob_free(&spnego_blob); + SCVAL(outbuf,smb_vwv16+1, 0); - p += len; DEBUG(3,("using SPNEGO\n")); } -- cgit From f18c9365caaad75c0f4c9e26b89327a75cfcb3e6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Sep 2006 17:00:07 +0000 Subject: r18787: Fix the strlen_m and strlen_m_term code by merging in (and using elsewhere) next_codepoint from Samba4. Jerry please test. Jeremy. (This used to be commit ece00b70a4621633f1ac9e576c4bbe332031de09) --- source3/smbd/reply.c | 27 ++++++++++++++++++++++++--- source3/smbd/service.c | 11 ++++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e38edadee4..a0596643f8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -132,13 +132,22 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) break; } } else { - switch(next_mb_char_size(s)) { + size_t siz; + /* Get the size of the next MB character. */ + next_codepoint(s,&siz); + switch(siz) { + case 5: + *d++ = *s++; + /*fall through*/ case 4: *d++ = *s++; + /*fall through*/ case 3: *d++ = *s++; + /*fall through*/ case 2: *d++ = *s++; + /*fall through*/ case 1: *d++ = *s++; break; @@ -266,7 +275,13 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * } *d++ = *s++; } else { - switch(next_mb_char_size(s)) { + size_t siz; + /* Get the size of the next MB character. */ + next_codepoint(s,&siz); + switch(siz) { + case 5: + *d++ = *s++; + /*fall through*/ case 4: *d++ = *s++; /*fall through*/ @@ -374,7 +389,13 @@ NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) if (!(*s & 0x80)) { *d++ = *s++; } else { - switch(next_mb_char_size(s)) { + size_t siz; + /* Get the size of the next MB character. */ + next_codepoint(s,&siz); + switch(siz) { + case 5: + *d++ = *s++; + /*fall through*/ case 4: *d++ = *s++; /*fall through*/ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 734feef4f7..9c341f19fd 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -95,13 +95,22 @@ void set_conn_connectpath(connection_struct *conn, const pstring connectpath) if (!(*s & 0x80)) { *d++ = *s++; } else { - switch(next_mb_char_size(s)) { + size_t siz; + /* Get the size of the next MB character. */ + next_codepoint(s,&siz); + switch(siz) { + case 5: + *d++ = *s++; + /*fall through*/ case 4: *d++ = *s++; + /*fall through*/ case 3: *d++ = *s++; + /*fall through*/ case 2: *d++ = *s++; + /*fall through*/ case 1: *d++ = *s++; break; -- cgit From eab57a0a0fe90be464f5061691f57ca1da150885 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 21 Sep 2006 17:51:06 +0000 Subject: r18789: Replace the winreg server code with the libndr parsing code. Many things work (OpenHKLM, etc...) but some still don't. This shouldn't block anyone so I'm checking it in. Will probably move to a bzr tree after this for longer dev cycles between checkins. (This used to be commit cf1404a0d7538288b9370ba80df328f81b713ce0) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9cebd21d7d..636dc750ea 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -37,6 +37,7 @@ static const char *known_nt_pipes[] = { "\\lsass", "\\lsarpc", "\\winreg", + "\\initshutdown", "\\spoolss", "\\netdfs", "\\rpcecho", -- cgit From 3a60a6743262ab2ab221e0fe13ef6b510424ca3f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Sep 2006 18:37:09 +0000 Subject: r18793: Fix BE string handling in the auto-generated code. Should now work again with ASU. Jeremy. (This used to be commit 53e97bf92817b6cfc3f93c999a81ef8ad49a1609) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index d1ce1af9ea..a39f49ec79 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -465,7 +465,7 @@ static BOOL is_legal_name(const char *name) * for mb UNIX asian characters like Japanese (SJIS) here. * JRA. */ - if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) { + if (convert_string(CH_UNIX, CH_UTF16LE, name, 2, mbc, 2, False) == 2) { /* Was a good mb string. */ name += 2; continue; -- cgit From 7ba2554d88a187ca1f4f40014363fdf9de2223a0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 21 Sep 2006 23:57:32 +0000 Subject: r18802: Use the pidl-generated code for the srvsvc interface, both client and server code. This has had some basic testing. I'll do more during the next couple of days and hopefully also make RPC-SRVSVC from Samba4 pass against it. (This used to be commit ef10672399c4b82700dc431b4d93431ffdd42d98) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 117d3ac595..9601329b9e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2057,7 +2057,7 @@ NTSTATUS open_directory(connection_struct *conn, Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -NTSTATUS open_file_stat(connection_struct *conn, char *fname, +NTSTATUS open_file_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, files_struct **result) { files_struct *fsp = NULL; -- cgit From 28800c54dc835d8a3aa97299b1df989ddfd04df2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 25 Sep 2006 20:59:48 +0000 Subject: r18907: W00t. My original fix was correct after all :-). Re-checking it in. Fix bug #4095 - username composed into domain\user twice in spnego path. Jeremy. (This used to be commit 0c770467519e73897462e730c3226e65668d3890) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index dd8d9fc852..8c8173ef37 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -327,7 +327,7 @@ static int reply_spnego_kerberos(connection_struct *conn, /* pass the unmapped username here since map_username() will be called again from inside make_server_info_info3() */ - ret = make_server_info_info3(mem_ctx, user, domain, + ret = make_server_info_info3(mem_ctx, client, domain, &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", -- cgit From 81014d255e488da3807abe75f067042f976fc50d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 29 Sep 2006 12:47:00 +0000 Subject: r19000: Merge the max tcon check from 3_0_23. Thanks to James Peach that this was not done in the 3_0 tree. Volker (This used to be commit b2fbf5ac0ca38577957e8e7ddb176dd3499de213) --- source3/smbd/service.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9c341f19fd..29f26c0302 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1043,6 +1043,11 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); } + if (conn_num_open() > 2047) { + *status = NT_STATUS_INSUFF_SERVER_RESOURCES; + return NULL; + } + if(lp_security() != SEC_SHARE) { vuser = get_valid_user_struct(vuid); if (!vuser) { -- cgit From c9cea2d6247480e0f7c15c50eaa16e41b09b937f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 29 Sep 2006 15:43:27 +0000 Subject: r19001: Fix comment (This used to be commit 048127f9dd6363dfb3c78369fa2227551b741831) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 636dc750ea..d41125564c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -477,7 +477,7 @@ int reply_ntcreate_and_X(connection_struct *conn, START_PROFILE(SMBntcreateX); - DEBUG(10,("reply_ntcreateX: flags = 0x%x, access_mask = 0x%x \ + DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x \ file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \ create_options = 0x%x root_dir_fid = 0x%x\n", (unsigned int)flags, -- cgit From 9430017b304b5d88cb12bcb67b531c66b6a6fdcd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 30 Sep 2006 09:45:53 +0000 Subject: r19010: Fix bug 4137 (This used to be commit 3790d00a78fa4133b9875b9fed36f5752dce8e7f) --- source3/smbd/share_access.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index cee88bcf0b..adb9d16964 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -217,6 +217,10 @@ BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum) const char *list[2]; list[0] = lp_username(snum); list[1] = NULL; + if ((list[0] == NULL) || (*list[0] == '\0')) { + DEBUG(0, ("'only user = yes' and no 'username ='\n")); + return False; + } if (!token_contains_name_in_list(NULL, lp_servicename(snum), token, list)) { DEBUG(10, ("%s != 'username'\n", username)); -- cgit From dc1f0804dd8177d3c3a0b2db993855d5679e9565 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 3 Oct 2006 17:14:18 +0000 Subject: r19058: Implement "user cannot change password", and complete "user must change password at next logon" code. The "password last set time" of zero now means "user must change password", because that's how windows seems to use it. The "can change" and "must change" times are now calculated based on the "last set" time and policies. We use the "can change" field now to indicate that a user cannot change a password by putting MAX_TIME_T in it (so long as "last set" time isn't zero). Based on this, we set the password-can-change bit in the faked secdesc. (This used to be commit 21abbeaee9b7f7cff1d34d048463c30cda44a2e3) --- source3/smbd/chgpasswd.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index cd847240dd..0b8dbfb492 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -689,7 +689,7 @@ BOOL change_lanman_password(struct samu *sampass, uchar *pass2) return False; /* We lose the NT hash. Sorry. */ } - if (!pdb_set_pass_changed_now (sampass)) { + if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) { TALLOC_FREE(sampass); /* Not quite sure what this one qualifies as, but this will do */ return False; @@ -1018,41 +1018,34 @@ static BOOL check_passwd_history(struct samu *sampass, const char *plaintext) NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason) { - uint32 min_len, min_age; + uint32 min_len; struct passwd *pass = NULL; const char *username = pdb_get_username(hnd); - time_t last_change_time = pdb_get_pass_last_set_time(hnd); time_t can_change_time = pdb_get_pass_can_change_time(hnd); if (samr_reject_reason) { *samr_reject_reason = Undefined; } - if (pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age)) { - /* - * Windows calculates the minimum password age check - * dynamically, it basically ignores the pwdcanchange - * timestamp. Do likewise. - */ - if (last_change_time + min_age > time(NULL)) { - DEBUG(1, ("user %s cannot change password now, must " - "wait until %s\n", username, - http_timestring(last_change_time+min_age))); - if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_OTHER; - } - return NT_STATUS_ACCOUNT_RESTRICTION; + /* check to see if the secdesc has previously been set to disallow */ + if (!pdb_get_pass_can_change(hnd)) { + DEBUG(1, ("user %s does not have permissions to change password\n")); + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_OTHER; } - } else { - if ((can_change_time != 0) && (time(NULL) < can_change_time)) { - DEBUG(1, ("user %s cannot change password now, must " - "wait until %s\n", username, - http_timestring(can_change_time))); - if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_OTHER; - } - return NT_STATUS_ACCOUNT_RESTRICTION; + return NT_STATUS_ACCOUNT_RESTRICTION; + } + + /* removed calculation here, becuase passdb now calculates + based on policy. jmcd */ + if ((can_change_time != 0) && (time(NULL) < can_change_time)) { + DEBUG(1, ("user %s cannot change password now, must " + "wait until %s\n", username, + http_timestring(can_change_time))); + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_OTHER; } + return NT_STATUS_ACCOUNT_RESTRICTION; } if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { -- cgit From f27d5c7838eb0183baaedb3deb33cdfe7327c917 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 4 Oct 2006 20:43:56 +0000 Subject: r19077: Fix an uninitialized variable (This used to be commit 6bc2cce645af94274a5959312c52799c221b0899) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9601329b9e..4e91cdfd2a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -475,8 +475,8 @@ static void validate_my_share_entries(int num, if (is_deferred_open_entry(share_entry) && !open_was_deferred(share_entry->op_mid)) { pstring str; - DEBUG(0, ("Got a deferred entry without a request: " - "PANIC: %s\n", share_mode_str(num, share_entry))); + pstr_sprintf(str, "Got a deferred entry without a request: " + "PANIC: %s\n", share_mode_str(num, share_entry)); smb_panic(str); } -- cgit From a8281b19c712a4b87f4c826b52ef4aaf16a6fc11 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 5 Oct 2006 09:38:49 +0000 Subject: r19094: Fix debug statement. Guenther (This used to be commit e99696c97052d4ba962e11fcb7b6ea530350913d) --- source3/smbd/chgpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 0b8dbfb492..7c6886b81c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1029,7 +1029,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw /* check to see if the secdesc has previously been set to disallow */ if (!pdb_get_pass_can_change(hnd)) { - DEBUG(1, ("user %s does not have permissions to change password\n")); + DEBUG(1, ("user %s does not have permissions to change password\n", username)); if (samr_reject_reason) { *samr_reject_reason = REJECT_REASON_OTHER; } -- cgit From 1362fd0b687294ac3e944797a6f87284b545fa22 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 6 Oct 2006 17:28:52 +0000 Subject: r19147: This is WRONG, but the way the VFS works this is the only fix to get rid of this type-punned warning. Volker (This used to be commit d815b1a7e9609a760f93433bf022826f58f256db) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index ed6b3dd4c4..3ed56d3bf6 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -104,7 +104,7 @@ static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which, struct vfs_handle_struct * handle, void * op) { ((struct vfs_handle_struct **)&vfs->handles)[which] = handle; - ((void**)&vfs->ops)[which] = op; + ((void **)(void *)&vfs->ops)[which] = op; } BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) -- cgit From cfed7a5a71aab48b1d5b758df318b991a95592a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Oct 2006 07:17:37 +0000 Subject: r19184: W2k3 returns its name for the GetServerInfo RAP call. Do the same. Implement 'net rap server name'. Volker (This used to be commit 919385ed2a2a07e848bc0baaac9ed3d1964d4386) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 637d5b4120..8a16c2c044 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2677,7 +2677,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par p = *rdata; p2 = p + struct_len; if (uLevel != 20) { - srvstr_push(NULL, p,get_local_machine_name(),16, + srvstr_push(NULL, p,global_myname(),16, STR_ASCII|STR_UPPER|STR_TERMINATE); } p += 16; -- cgit From 9d20474a48931a2574e04ba89db730be9bfb7288 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Oct 2006 13:26:29 +0000 Subject: r19203: Part two of returning our real name. This code is a bit ancient... :-) (This used to be commit 370c24ba2ad3bce29929886f96d626e698da0238) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 8a16c2c044..8ecc965c0d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2691,7 +2691,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;i Date: Fri, 13 Oct 2006 05:22:36 +0000 Subject: r19260: Fix for bug #3524 from tiamat@komi.mts.ru - Solaris quotas. Jeremy. (This used to be commit ac510a90f3adf72b64a8e2a764b0500dcd223b3f) --- source3/smbd/quotas.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 35bb94bcef..bb88957731 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -586,7 +586,6 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB int file; static struct mnttab mnt; static pstring name; - pstring devopt; #else /* SunOS4 */ struct mntent *mnt; static pstring name; @@ -603,7 +602,8 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB return(False) ; devno = sbuf.st_dev ; - DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno)); + DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", + path, (unsigned int)devno)); if ( devno != devno_cached ) { devno_cached = devno ; #if defined(SUNOS5) @@ -611,17 +611,19 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB return(False) ; found = False ; - slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno); + while (getmntent(fd, &mnt) == 0) { - if( !hasmntopt(&mnt, devopt) ) + if (sys_stat(mnt.mnt_mountp, &sbuf) == -1) continue; - DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt)); + DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", + mnt.mnt_mountp, (unsigned int)devno)); /* quotas are only on vxfs, UFS or NFS */ - if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || + if ( (sbuf.st_dev == devno) && ( + strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || strcmp( mnt.mnt_fstype, "nfs" ) == 0 || - strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) { + strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) { found = True ; break; } -- cgit From 09ead9c8fac5e3058e9b6b422171db04dd8dd680 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 18 Oct 2006 03:34:31 +0000 Subject: r19386: Limit the size of the connection bitmap to <64K entries. (This used to be commit 9f0518e0b0d4add7cceac6d4d797edddb0080aaa) --- source3/smbd/conn.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 52182f3129..73d2ed7003 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -107,7 +107,7 @@ find_again: int newsz = bmap->n + BITMAP_BLOCK_SZ; struct bitmap * nbmap; - if (newsz <= 0) { + if (newsz <= oldsz) { /* Integer wrap. */ DEBUG(0,("ERROR! Out of connection structures\n")); return NULL; @@ -131,6 +131,16 @@ find_again: goto find_again; } + /* The bitmap position is used below as the connection number + * conn->cnum). This ends up as the TID field in the SMB header, + * which is limited to 16 bits (we skip 0xffff which is the + * NULL TID). + */ + if (i > 65534) { + DEBUG(0, ("Maximum connection limit reached\n")); + return NULL; + } + if ((mem_ctx=talloc_init("connection_struct"))==NULL) { DEBUG(0,("talloc_init(connection_struct) failed!\n")); return NULL; -- cgit From 9a0273634860386ecdd6b4c606f30f2620ae3dc0 Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 7 Nov 2006 17:18:00 +0000 Subject: r19626: Coalesce usage of DUMP_CORE. Fix formatting on chdir error message in core dump path. (This used to be commit 9a51fba71c5fa7082c331e1a78a98638d9aa06cf) --- source3/smbd/server.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a7a84eced1..593e2bfb12 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -725,9 +725,7 @@ static void exit_server_common(enum server_exit_reason how, } DEBUGLEVEL = oldlevel; -#if DUMP_CORE dump_core(); -#endif } else { DEBUG(3,("Server exit (%s)\n", -- cgit From 892d07b30bc0d3859fce7e8e5baa33a82827cb48 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Nov 2006 18:35:41 +0000 Subject: r19627: Fix for bug #4211 - logic error in acl_group_override() function. Fix from Jim Wang of Wesoft. Jeremy. (This used to be commit eb78ce1f550377bfb1fd43f550641cf8a606e973) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 3b38b91547..f17594c079 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2256,8 +2256,8 @@ static BOOL current_user_in_group(gid_t gid) static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid) { if ( (errno == EACCES || errno == EPERM) - && (lp_acl_group_control(SNUM(conn) || lp_dos_filemode(SNUM(conn)))) - && current_user_in_group(prim_gid) ) + && (lp_acl_group_control(SNUM(conn)) || lp_dos_filemode(SNUM(conn))) + && current_user_in_group(prim_gid)) { return True; } -- cgit From 4fe70bcee2ec8515f123d8c826631b54bbf793e7 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 9 Nov 2006 20:29:31 +0000 Subject: r19647: Add some GPFS support in a vfs mod. Also adds the kernel flock op to the vfs layer, since gpfs supports it. Thanks to Volker, Christian, Mathias, Chetan, and Peter. (This used to be commit 0620658890fa9c68a9848538728023192319c81a) --- source3/smbd/open.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4e91cdfd2a..1899a6fce7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -783,28 +783,6 @@ static void defer_open(struct share_mode_lock *lck, srv_defer_sign_response(mid); } -/**************************************************************************** - Set a kernel flock on a file for NFS interoperability. - This requires a patch to Linux. -****************************************************************************/ - -static void kernel_flock(files_struct *fsp, uint32 share_mode) -{ -#if HAVE_KERNEL_SHARE_MODES - int kernel_mode = 0; - if (share_mode == FILE_SHARE_WRITE) { - kernel_mode = LOCK_MAND|LOCK_WRITE; - } else if (share_mode == FILE_SHARE_READ) { - kernel_mode = LOCK_MAND|LOCK_READ; - } else if (share_mode == FILE_SHARE_NONE) { - kernel_mode = LOCK_MAND; - } - if (kernel_mode) { - flock(fsp->fh->fd, kernel_mode); - } -#endif - ; -} /**************************************************************************** On overwrite open ensure that the attributes match. @@ -1126,6 +1104,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, struct share_mode_lock *lck = NULL; uint32 open_access_mask = access_mask; NTSTATUS status; + int ret_flock; + if (conn->printer) { /* @@ -1644,9 +1624,18 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, these only read them. Nobody but Samba can ever set a deny mode and we have already checked our more authoritative locking database for permission to set this deny mode. If - the kernel refuses the operations then the kernel is wrong */ + the kernel refuses the operations then the kernel is wrong. + note that GPFS supports it as well - jmcd */ + + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); + if(ret_flock == -1 ){ - kernel_flock(fsp, share_access); + talloc_free(lck); + fd_close(conn, fsp); + file_free(fsp); + + return NT_STATUS_SHARING_VIOLATION; + } /* * At this point onwards, we can guarentee that the share entry -- cgit From d988af921de131a05490f1eaa92dd33d36501580 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Nov 2006 20:21:23 +0000 Subject: r19705: Fix blocker bug for 3.0.23d - find_forced_group could return an uninitialized sid. Jeremy. (This used to be commit 57c60103e7dd8f9907bc2954369ea8db8b3b69ff) --- source3/smbd/service.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 29f26c0302..60ba85ab65 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -434,6 +434,9 @@ static NTSTATUS find_forced_group(BOOL force_user, BOOL user_must_be_member = False; gid_t gid; + ZERO_STRUCTP(pgroup_sid); + *pgid = (gid_t)-1; + mem_ctx = talloc_new(NULL); if (mem_ctx == NULL) { DEBUG(0, ("talloc_new failed\n")); @@ -489,6 +492,12 @@ static NTSTATUS find_forced_group(BOOL force_user, *pgid = gid; DEBUG(3,("Forced group %s for member %s\n", groupname, username)); + } else { + DEBUG(0,("find_forced_group: forced user %s is not a member " + "of forced group %s. Disallowing access.\n", + username, groupname )); + result = NT_STATUS_MEMBER_NOT_IN_GROUP; + goto done; } } else { sid_copy(pgroup_sid, &group_sid); -- cgit From 46e59a57eb4d00c4070119dd1584d3158dfb68d1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Nov 2006 01:06:45 +0000 Subject: r19709: Fix bug #4224 - deadtime timeout was broken because of this. Probably a show-stopper for 3.0.23d. Thanks to Alain GORLIER for the fix. Jeremy. (This used to be commit b167785cbd7911940e16fd2a54ec665857feef5e) --- source3/smbd/conn.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 73d2ed7003..0b0da589e4 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -199,6 +199,7 @@ BOOL conn_idle_all(time_t t, int deadtime) /* Update if connection wasn't idle. */ if (conn->lastused != conn->lastused_count) { conn->lastused = t; + conn->lastused_count = t; } /* close dirptrs on connections that are idle */ -- cgit From 60936146d0b74315ff872da047a970fe87d0f1d3 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 24 Nov 2006 05:35:05 +0000 Subject: r19873: Make sure we are privileged when doing DMAPI operations on systems that don't have capability support. Patch by J Raynor . (This used to be commit 53fe047f35534afc4b56fcbaf135a3ca13df65bd) --- source3/smbd/dmapi.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index a9d83c782b..b42b7d51f0 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -240,6 +240,13 @@ uint32 dmapi_file_flags(const char * const path) } } + /* AIX has DMAPI but no POSIX capablities support. In this case, + * we need to be root to do DMAPI manipulations. + */ +#ifndef HAVE_POSIX_CAPABILITIES + become_root(); +#endif + err = dm_path_to_handle(CONST_DISCARD(char *, path), &dm_handle, &dm_handle_len); if (err < 0) { @@ -247,7 +254,7 @@ uint32 dmapi_file_flags(const char * const path) path, strerror(errno))); if (errno != EPERM) { - return 0; + goto done; } /* Linux capabilities are broken in that changing our @@ -265,7 +272,7 @@ uint32 dmapi_file_flags(const char * const path) DEBUG(DMAPI_TRACE, ("retrying dm_path_to_handle(%s): %s\n", path, strerror(errno))); - return 0; + goto done; } } @@ -275,7 +282,7 @@ uint32 dmapi_file_flags(const char * const path) DEBUG(DMAPI_TRACE, ("dm_get_eventlist(%s): %s\n", path, strerror(errno))); dm_handle_free(dm_handle, dm_handle_len); - return 0; + goto done; } /* We figure that the only reason a DMAPI application would be @@ -294,6 +301,12 @@ uint32 dmapi_file_flags(const char * const path) DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); } +done: + +#ifndef HAVE_POSIX_CAPABILITIES + unbecome_root(); +#endif + return flags; } -- cgit From 575845ccbeb2acc5dcb5133b80fd19b1d80169f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 30 Nov 2006 07:38:40 +0000 Subject: r19963: Add 'registry shares = yes' and registry key security descriptors. (This used to be commit 6cab254c49e07b11c170511ec613f0f33914c3e6) --- source3/smbd/lanman.c | 1 + source3/smbd/msdfs.c | 1 + source3/smbd/service.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 8ecc965c0d..e42d96b11e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1671,6 +1671,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, /* Ensure all the usershares are loaded. */ become_root(); + load_registry_shares(); count = load_usershare_shares(); unbecome_root(); diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1f04356b4f..12fd333efe 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1114,6 +1114,7 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) /* Ensure all the usershares are loaded. */ become_root(); + load_registry_shares(); sharecount = load_usershare_shares(); unbecome_root(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 60ba85ab65..e63bc01a7d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -229,6 +229,115 @@ int add_home_service(const char *service, const char *username, const char *home } +static int load_registry_service(const char *servicename) +{ + REGISTRY_KEY *key; + char *path; + WERROR err; + NTSTATUS status; + + uint32 i, num_values; + char **value_names; + struct registry_value **values = NULL; + + int res; + + if (!lp_registry_shares()) { + return -1; + } + + if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) { + return -1; + } + + err = regkey_open_internal(NULL, NULL, &key, path, get_root_nt_token(), + REG_KEY_READ); + SAFE_FREE(path); + + if (!W_ERROR_IS_OK(err)) { + return -1; + } + + status = registry_fetch_values(NULL, key, &num_values, &value_names, + &values); + + TALLOC_FREE(key); + + if (!NT_STATUS_IS_OK(status)) { + goto error; + } + + res = lp_add_service(servicename, -1); + if (res == -1) { + goto error; + } + + for (i=0; itype) { + case REG_DWORD: { + char *val; + if (asprintf(&val, "%d", values[i]->v.dword) == -1) { + continue; + } + lp_do_parameter(res, value_names[i], val); + SAFE_FREE(val); + break; + } + case REG_SZ: { + lp_do_parameter(res, value_names[i], + values[i]->v.sz.str); + break; + } + default: + /* Ignore all the rest */ + break; + } + } + + TALLOC_FREE(value_names); + TALLOC_FREE(values); + return res; + + error: + + TALLOC_FREE(value_names); + TALLOC_FREE(values); + return -1; +} + +void load_registry_shares(void) +{ + REGISTRY_KEY *key; + REGSUBKEY_CTR *keys; + WERROR err; + int i; + + if (!lp_registry_shares()) { + return; + } + + if (!(keys = TALLOC_ZERO_P(NULL, REGSUBKEY_CTR))) { + goto done; + } + + err = regkey_open_internal(keys, NULL, &key, KEY_SMBCONF, + get_root_nt_token(), REG_KEY_READ); + if (!(W_ERROR_IS_OK(err))) { + goto done; + } + + if (fetch_reg_keys(key, keys) == -1) { + goto done; + } + + for (i=0; inum_subkeys; i++) { + load_registry_service(keys->subkeys[i]); + } + + done: + TALLOC_FREE(keys); + return; +} /** * Find a service entry. @@ -307,6 +416,10 @@ int find_service(fstring service) } } + if (iService < 0) { + iService = load_registry_service(service); + } + /* Is it a usershare service ? */ if (iService < 0 && *lp_usershare_path()) { /* Ensure the name is canonicalized. */ -- cgit From ef8d6bf5f700dcfeec7919203da9c357c4f21e3f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 1 Dec 2006 15:04:53 +0000 Subject: r19979: Fix memleak on pw and change talloc_destroy to TALLOC_FREE for mem_ctx (This used to be commit defa0a352b32469984126ec5d47aab9ef8d6b61c) --- source3/smbd/sesssetup.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8c8173ef37..ae6dd49663 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -335,7 +335,8 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); - talloc_destroy(mem_ctx); + TALLOC_FREE(mem_ctx); + TALLOC_FREE(pw); return ERROR_NT(nt_status_squash(ret)); } @@ -348,7 +349,8 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); - talloc_destroy(mem_ctx); + TALLOC_FREE(mem_ctx); + TALLOC_FREE(pw); return ERROR_NT(nt_status_squash(ret)); } @@ -372,6 +374,7 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); + TALLOC_FREE(pw); TALLOC_FREE( mem_ctx ); TALLOC_FREE( server_info ); return ERROR_NT(nt_status_squash(ret)); @@ -415,7 +418,8 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&response); - talloc_destroy(mem_ctx); + TALLOC_FREE(mem_ctx); + TALLOC_FREE(pw); return -1; /* already replied */ } -- cgit From cb0402c2d3941a813e33b2b5e07c54b9ff644ca4 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 1 Dec 2006 15:06:34 +0000 Subject: r19980: Implement pam account stack checks when obey pam restrictions is true. It was missing for security=server/domain/ads Simo. (This used to be commit 550f651499c22c3c11594a0a39061a8a9b438d82) --- source3/smbd/sesssetup.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index ae6dd49663..11c5e9bbf9 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -292,6 +292,22 @@ static int reply_spnego_kerberos(connection_struct *conn, username_was_mapped = map_username( user ); pw = smb_getpwnam( mem_ctx, user, real_username, True ); + + if (pw) { + /* if a real user check pam account restrictions */ + /* only really perfomed if "obey pam restriction" is true */ + /* do this before an eventual mappign to guest occurs */ + ret = smb_pam_accountcheck(pw->pw_name); + if ( !NT_STATUS_IS_OK(ret)) { + DEBUG(1, ("PAM account restriction prevents user login\n")); + data_blob_free(&ap_rep); + data_blob_free(&session_key); + talloc_destroy(mem_ctx); + TALLOC_FREE(pw); + return ERROR_NT(nt_status_squash(ret)); + } + } + if (!pw) { /* this was originally the behavior of Samba 2.2, if a user -- cgit From c81c8cb4a7962f5437690a106bd7793b38175af2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 1 Dec 2006 16:13:06 +0000 Subject: r19984: Must have been drunk yesterday. Freeing memctx is all we need, fix double free stupidity (This used to be commit 2a7454959e93e5bd11161707d0bd16a431b92351) --- source3/smbd/sesssetup.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 11c5e9bbf9..0cf6692e22 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -302,8 +302,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DEBUG(1, ("PAM account restriction prevents user login\n")); data_blob_free(&ap_rep); data_blob_free(&session_key); - talloc_destroy(mem_ctx); - TALLOC_FREE(pw); + TALLOC_FREE(mem_ctx); return ERROR_NT(nt_status_squash(ret)); } } @@ -327,7 +326,7 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); - talloc_destroy(mem_ctx); + TALLOC_FREE(mem_ctx); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } } @@ -335,6 +334,8 @@ static int reply_spnego_kerberos(connection_struct *conn, /* setup the string used by %U */ sub_set_smb_name( real_username ); +C_FR +C_FREE reload_services(True); if ( map_domainuser_to_guest ) { @@ -352,7 +353,6 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); - TALLOC_FREE(pw); return ERROR_NT(nt_status_squash(ret)); } @@ -366,7 +366,6 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); - TALLOC_FREE(pw); return ERROR_NT(nt_status_squash(ret)); } @@ -390,7 +389,6 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); - TALLOC_FREE(pw); TALLOC_FREE( mem_ctx ); TALLOC_FREE( server_info ); return ERROR_NT(nt_status_squash(ret)); @@ -435,7 +433,6 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep_wrapped); data_blob_free(&response); TALLOC_FREE(mem_ctx); - TALLOC_FREE(pw); return -1; /* already replied */ } -- cgit From dc2ed4c830842a21c205fb453d5b15a8e46d1dbc Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 1 Dec 2006 16:37:25 +0000 Subject: r19986: ooops (This used to be commit 97f150fbbbee4837c15de121b418881241f321e2) --- source3/smbd/sesssetup.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0cf6692e22..1603490441 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -334,8 +334,6 @@ static int reply_spnego_kerberos(connection_struct *conn, /* setup the string used by %U */ sub_set_smb_name( real_username ); -C_FR -C_FREE reload_services(True); if ( map_domainuser_to_guest ) { -- cgit From ecf90c495eb850cd6f376fb4e090640b69f0c029 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 1 Dec 2006 20:01:09 +0000 Subject: r19991: Sorry for this 2000-liner... The main thing here is a rewrite of srv_winreg_nt.c. The core functionality has moved to registry/reg_api.c which is then usable by the rest of Samba as well. On that way it fixes creating keys with more than one element in the path. This did not work before. Two things that sneaked in (sorry :-) is the change of some routines from NTSTATUS to WERROR the removed "parent" argument to regkey_open_internal. Volker (This used to be commit fea52801de8c7b85c578d200c599475680c5339f) --- source3/smbd/service.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e63bc01a7d..048c0f00b1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -234,7 +234,6 @@ static int load_registry_service(const char *servicename) REGISTRY_KEY *key; char *path; WERROR err; - NTSTATUS status; uint32 i, num_values; char **value_names; @@ -250,7 +249,7 @@ static int load_registry_service(const char *servicename) return -1; } - err = regkey_open_internal(NULL, NULL, &key, path, get_root_nt_token(), + err = regkey_open_internal(NULL, &key, path, get_root_nt_token(), REG_KEY_READ); SAFE_FREE(path); @@ -258,12 +257,12 @@ static int load_registry_service(const char *servicename) return -1; } - status = registry_fetch_values(NULL, key, &num_values, &value_names, - &values); + err = registry_fetch_values(NULL, key, &num_values, &value_names, + &values); TALLOC_FREE(key); - if (!NT_STATUS_IS_OK(status)) { + if (!W_ERROR_IS_OK(err)) { goto error; } @@ -320,7 +319,7 @@ void load_registry_shares(void) goto done; } - err = regkey_open_internal(keys, NULL, &key, KEY_SMBCONF, + err = regkey_open_internal(keys, &key, KEY_SMBCONF, get_root_nt_token(), REG_KEY_READ); if (!(W_ERROR_IS_OK(err))) { goto done; -- cgit From 61ea96ec79fb9807fb234fe7fc9a59458653c6e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Dec 2006 23:46:07 +0000 Subject: r19993: Fix the problem with Linux clients requesting O_WRONLY on write-only files. Jim please check. Should not affect Windows clients - I ensured all the relevent Samba4 torture tests still pass. Jeremy. (This used to be commit 6df3cac44fb1eafa84f9fc0ce4485242b4cce111) --- source3/smbd/open.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1899a6fce7..3d5dd849b6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1105,7 +1105,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; - if (conn->printer) { /* @@ -1300,7 +1299,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { - flags = O_RDWR; + /* DENY_DOS opens are always underlying read-write on the + file handle, no matter what the requested access mask + says. */ + if ((create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) || + access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|FILE_READ_EA|FILE_EXECUTE)) { + flags = O_RDWR; + } else { + flags = O_WRONLY; + } } else { flags = O_RDONLY; } @@ -1448,11 +1455,13 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (flags & O_RDWR) { can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA; + } else if (flags & O_WRONLY) { + can_access_mask = FILE_WRITE_DATA; } else { can_access_mask = FILE_READ_DATA; } - if (((flags & O_RDWR) && !CAN_WRITE(conn)) || + if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) || !can_access_file(conn,fname,psbuf,can_access_mask)) { can_access = False; } -- cgit From fc030c313f4ec93bceea460787484994b39af2dd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 2 Dec 2006 10:53:00 +0000 Subject: r20006: Convert the registry shares to use the new API (This used to be commit 66e889bbabde6dfd05df46937635a6d3e606cb27) --- source3/smbd/service.c | 79 ++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 048c0f00b1..5779ad1be9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -231,15 +231,15 @@ int add_home_service(const char *service, const char *username, const char *home static int load_registry_service(const char *servicename) { - REGISTRY_KEY *key; + struct registry_key *key; char *path; WERROR err; - uint32 i, num_values; - char **value_names; - struct registry_value **values = NULL; + uint32 i; + char *value_name; + struct registry_value *value; - int res; + int res = -1; if (!lp_registry_shares()) { return -1; @@ -249,65 +249,56 @@ static int load_registry_service(const char *servicename) return -1; } - err = regkey_open_internal(NULL, &key, path, get_root_nt_token(), - REG_KEY_READ); + err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(), + &key); SAFE_FREE(path); if (!W_ERROR_IS_OK(err)) { return -1; } - err = registry_fetch_values(NULL, key, &num_values, &value_names, - &values); - - TALLOC_FREE(key); - - if (!W_ERROR_IS_OK(err)) { - goto error; - } - res = lp_add_service(servicename, -1); if (res == -1) { goto error; } - for (i=0; itype) { + for (i=0; + W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value)); + i++) { + switch (value->type) { case REG_DWORD: { - char *val; - if (asprintf(&val, "%d", values[i]->v.dword) == -1) { + char *tmp; + if (asprintf(&tmp, "%d", value->v.dword) == -1) { continue; } - lp_do_parameter(res, value_names[i], val); - SAFE_FREE(val); + lp_do_parameter(res, value_name, tmp); + SAFE_FREE(tmp); break; } case REG_SZ: { - lp_do_parameter(res, value_names[i], - values[i]->v.sz.str); + lp_do_parameter(res, value_name, value->v.sz.str); break; } default: /* Ignore all the rest */ break; } - } - TALLOC_FREE(value_names); - TALLOC_FREE(values); - return res; + TALLOC_FREE(value_name); + TALLOC_FREE(value); + } + res = 0; error: - TALLOC_FREE(value_names); - TALLOC_FREE(values); - return -1; + TALLOC_FREE(key); + return res; } void load_registry_shares(void) { - REGISTRY_KEY *key; - REGSUBKEY_CTR *keys; + struct registry_key *key; + char *name; WERROR err; int i; @@ -315,26 +306,18 @@ void load_registry_shares(void) return; } - if (!(keys = TALLOC_ZERO_P(NULL, REGSUBKEY_CTR))) { - goto done; - } - - err = regkey_open_internal(keys, &key, KEY_SMBCONF, - get_root_nt_token(), REG_KEY_READ); + err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ, + get_root_nt_token(), &key); if (!(W_ERROR_IS_OK(err))) { - goto done; - } - - if (fetch_reg_keys(key, keys) == -1) { - goto done; + return; } - for (i=0; inum_subkeys; i++) { - load_registry_service(keys->subkeys[i]); + for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) { + load_registry_service(name); + TALLOC_FREE(name); } - done: - TALLOC_FREE(keys); + TALLOC_FREE(key); return; } -- cgit From 7299dc8b54079c42ded160e76e4f18b1eb24450a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 3 Dec 2006 15:34:52 +0000 Subject: r20014: Ouch.... "res" is not a flag here, it is the service number... (This used to be commit a4862f48d085d1f518389f86a410722e91449755) --- source3/smbd/service.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 5779ad1be9..c2dd062777 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -288,7 +288,6 @@ static int load_registry_service(const char *servicename) TALLOC_FREE(value); } - res = 0; error: TALLOC_FREE(key); -- cgit From 63609fbb04d2ce620338b4b79e7c1abf39f08ef8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 9 Dec 2006 02:58:18 +0000 Subject: r20090: Fix a class of bugs found by James Peach. Ensure we never mix malloc and talloc'ed contexts in the add_XX_to_array() and add_XX_to_array_unique() calls. Ensure that these calls always return False on out of memory, True otherwise and always check them. Ensure that the relevent parts of the conn struct and the nt_user_tokens are TALLOC_DESTROYED not SAFE_FREE'd. James - this should fix your crash bug in both branches. Jeremy. (This used to be commit 0ffca7559e07500bd09a64b775e230d448ce5c24) --- source3/smbd/conn.c | 2 +- source3/smbd/service.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 0b0da589e4..f2c04662a1 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -269,7 +269,7 @@ void conn_free_internal(connection_struct *conn) } if (conn->ngroups && conn->groups) { - SAFE_FREE(conn->groups); + TALLOC_FREE(conn->groups); conn->ngroups = 0; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c2dd062777..62d85cfdd9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -853,8 +853,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, sid_string_static(sid))); continue; } - add_gid_to_array_unique(NULL, gid, &conn->groups, - &conn->ngroups); + if (!add_gid_to_array_unique(NULL, gid, &conn->groups, + &conn->ngroups)) { + DEBUG(0, ("add_gid_to_array_unique failed\n")); + conn_free(conn); + *status = NT_STATUS_NO_MEMORY; + return NULL; + } } } -- cgit From af0f14e3a72756dfaff36e0106ae0f7eaac06633 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 9 Dec 2006 23:55:20 +0000 Subject: r20097: Ensure found_username is freed correctly when talloced on the null context. Jeremy. (This used to be commit 2c59c4dddceb9cb12848d7ee48257c5e93ea2667) --- source3/smbd/service.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 62d85cfdd9..08370b1c80 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -643,7 +643,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (lp_guest_only(snum)) { const char *guestname = lp_guestaccount(); NTSTATUS status2; - char *found_username; + char *found_username = NULL; + guest = True; pass = getpwnam_alloc(NULL, guestname); if (!pass) { @@ -658,6 +659,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, &found_username, &conn->nt_user_token); if (!NT_STATUS_IS_OK(status2)) { + TALLOC_FREE(found_username); conn_free(conn); *status = status2; return NULL; @@ -665,6 +667,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, fstrcpy(user, found_username); string_set(&conn->user,user); conn->force_user = True; + TALLOC_FREE(found_username); TALLOC_FREE(pass); DEBUG(3,("Guest only user %s\n",user)); } else if (vuser) { @@ -697,7 +700,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, guest = vuser->guest; } else if (lp_security() == SEC_SHARE) { NTSTATUS status2; - char *found_username; + char *found_username = NULL; /* add it as a possible user name if we are in share mode security */ add_session_user(lp_servicename(snum)); @@ -715,12 +718,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, &found_username, &conn->nt_user_token); if (!NT_STATUS_IS_OK(status2)) { + TALLOC_FREE(found_username); conn_free(conn); *status = status2; return NULL; } fstrcpy(user, found_username); string_set(&conn->user,user); + TALLOC_FREE(found_username); conn->force_user = True; } else { DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); -- cgit From 25d6eaae8d0d885add7e64b96df7a489328c6b0f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 10 Dec 2006 05:23:47 +0000 Subject: r20098: Properly fix issues with create_token_from_username() reported by James. Ensure that this function allocates everything on the temporary context except the return memory. Never call this with a null mem context, and now use conn->mem_ctx instead in smbd/service.c. Remove separate free functions for conn->ngroups and conn->nt_user_token as they are now always talloc'ed off the conn->mem_ctx. Future optimization will be to remove conn->mem_ctx and make all objects pointed to in the conn struct talloc'ed off conn itself. Easy to free then :-). Jeremy. (This used to be commit f83b6de44f1058811ff94ac72a8a71bd8e49e4e8) --- source3/smbd/conn.c | 9 --------- source3/smbd/service.c | 50 +++++++++++++++++--------------------------------- 2 files changed, 17 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index f2c04662a1..19ed49e7bf 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -268,15 +268,6 @@ void conn_free_internal(connection_struct *conn) handle = thandle; } - if (conn->ngroups && conn->groups) { - TALLOC_FREE(conn->groups); - conn->ngroups = 0; - } - - if (conn->nt_user_token) { - TALLOC_FREE(conn->nt_user_token); - } - free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 08370b1c80..9b6743f76b 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -468,43 +468,28 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } -static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest, - uid_t *uid, gid_t *gid, fstring username, - struct nt_user_token **token) +static NTSTATUS find_forced_user(connection_struct *conn, BOOL vuser_is_guest, fstring username) { - TALLOC_CTX *mem_ctx; + int snum = conn->params->service; char *fuser, *found_username; - struct nt_user_token *tmp_token; NTSTATUS result; - if (!(mem_ctx = talloc_new(NULL))) { - DEBUG(0, ("talloc_new failed\n")); - return NT_STATUS_NO_MEMORY; - } - - if (!(fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S", + if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S", lp_servicename(snum)))) { - TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; - } - result = create_token_from_username(mem_ctx, fuser, vuser_is_guest, - uid, gid, &found_username, - &tmp_token); + result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest, + &conn->uid, &conn->gid, &found_username, + &conn->nt_user_token); if (!NT_STATUS_IS_OK(result)) { - TALLOC_FREE(mem_ctx); return result; } - if (!(*token = dup_nt_token(NULL, tmp_token))) { - TALLOC_FREE(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - fstrcpy(username, found_username); - TALLOC_FREE(mem_ctx); + TALLOC_FREE(fuser); + TALLOC_FREE(found_username); return NT_STATUS_OK; } @@ -638,6 +623,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } + conn->params->service = snum; conn->nt_user_token = NULL; if (lp_guest_only(snum)) { @@ -654,12 +640,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *status = NT_STATUS_NO_SUCH_USER; return NULL; } - status2 = create_token_from_username(NULL, pass->pw_name, True, + status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, &conn->uid, &conn->gid, &found_username, &conn->nt_user_token); if (!NT_STATUS_IS_OK(status2)) { - TALLOC_FREE(found_username); + TALLOC_FREE(pass); conn_free(conn); *status = status2; return NULL; @@ -701,6 +687,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } else if (lp_security() == SEC_SHARE) { NTSTATUS status2; char *found_username = NULL; + /* add it as a possible user name if we are in share mode security */ add_session_user(lp_servicename(snum)); @@ -713,12 +700,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } pass = Get_Pwnam(user); - status2 = create_token_from_username(NULL, pass->pw_name, True, + status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, &conn->uid, &conn->gid, &found_username, &conn->nt_user_token); if (!NT_STATUS_IS_OK(status2)) { - TALLOC_FREE(found_username); conn_free(conn); *status = status2; return NULL; @@ -740,7 +726,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = conn->lastused_count = time(NULL); - conn->params->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || @@ -778,10 +763,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_force_user(snum)) { NTSTATUS status2; - status2 = find_forced_user(snum, - (vuser != NULL) && vuser->guest, - &conn->uid, &conn->gid, user, - &conn->nt_user_token); + status2 = find_forced_user(conn, + (vuser != NULL) && vuser->guest, + user); if (!NT_STATUS_IS_OK(status2)) { conn_free(conn); *status = status2; @@ -858,7 +842,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, sid_string_static(sid))); continue; } - if (!add_gid_to_array_unique(NULL, gid, &conn->groups, + if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups, &conn->ngroups)) { DEBUG(0, ("add_gid_to_array_unique failed\n")); conn_free(conn); -- cgit From 791f48f167de339c8ae371e5c80706511fd10018 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 12 Dec 2006 17:38:42 +0000 Subject: r20124: clean up nested extern declaration warnings (This used to be commit ac3eb7813e33b9a2e78c9158433f7ed62c3b62bb) --- source3/smbd/blocking.c | 3 ++- source3/smbd/nttrans.c | 1 - source3/smbd/sesssetup.c | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index f489a8e96b..aeb2bd6b6b 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -22,6 +22,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING +extern int max_send; + /**************************************************************************** This is the structure to queue to implement blocking locks. notify. It consists of the requesting SMB and the expiry time. @@ -425,7 +427,6 @@ Waiting....\n", static BOOL process_trans2(blocking_lock_record *blr) { - extern int max_send; char *inbuf = blr->inbuf; char *outbuf; char params[2]; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d41125564c..3ade5b01c6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2345,7 +2345,6 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, SMB_NTQUOTA_STRUCT qt; SMB_NTQUOTA_LIST *tmp_list; SMB_NTQUOTA_HANDLE *qt_handle = NULL; - extern struct current_user current_user; ZERO_STRUCT(qt); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1603490441..4d731f9c59 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,6 +23,12 @@ #include "includes.h" +extern struct auth_context *negprot_global_auth_context; +extern BOOL global_encrypted_passwords_negotiated; +extern BOOL global_spnego_negotiated; +extern enum protocol_types Protocol; +extern int max_send; + uint32 global_client_caps = 0; /* @@ -840,13 +846,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, fstring native_lanman; fstring primary_domain; static BOOL done_sesssetup = False; - extern BOOL global_encrypted_passwords_negotiated; - extern BOOL global_spnego_negotiated; - extern enum protocol_types Protocol; - extern int max_send; - auth_usersupplied_info *user_info = NULL; - extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; -- cgit From 6914b29daa6700f0d4f1b93866074ce71f63a626 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 12 Dec 2006 20:15:47 +0000 Subject: r20131: get rid of a few no previous prototype warnings (This used to be commit e710a7d39a662a1a339f3f71c4b051fde1bb5a16) --- source3/smbd/oplock_irix.c | 1 + source3/smbd/server.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 248d902028..b62975dd27 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -266,5 +266,6 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void) return &koplocks; } #else + void oplock_irix_dummy(void); void oplock_irix_dummy(void) {} #endif /* HAVE_KERNEL_OPLOCKS_IRIX */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 593e2bfb12..5ee9320fb3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -786,7 +786,7 @@ static BOOL init_structs(void ) mkproto.h. Mixing $(builddir) and $(srcdir) source files in the current prototype generation system is too complicated. */ -void build_options(BOOL screen); +extern void build_options(BOOL screen); int main(int argc,const char *argv[]) { -- cgit From d29722e378011e6085e007e1e6c39a9f002eb2fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Dec 2006 00:49:12 +0000 Subject: r20178: Ensure we allocate the intermediate trans structs off conn->mem_ctx, not the null context so we can safefy free everything on conn close. Should fix possible memleak. Jeremy. (This used to be commit b33bde7b39953e171f05cdb53b6345ee3a9ec6e7) --- source3/smbd/conn.c | 8 ++++++++ source3/smbd/ipc.c | 3 ++- source3/smbd/nttrans.c | 3 ++- source3/smbd/trans2.c | 3 ++- 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 19ed49e7bf..083e8339c8 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -257,6 +257,7 @@ void conn_free_internal(connection_struct *conn) { vfs_handle_struct *handle = NULL, *thandle = NULL; TALLOC_CTX *mem_ctx = NULL; + struct trans_state *state = NULL; /* Free vfs_connection_struct */ handle = conn->vfs_handles; @@ -268,6 +269,13 @@ void conn_free_internal(connection_struct *conn) handle = thandle; } + /* Free any pending transactions stored on this conn. */ + for (state = conn->pending_trans; state; state = state->next) { + /* state->setup is a talloc child of state. */ + SAFE_FREE(state->param); + SAFE_FREE(state->data); + } + free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 08381524c0..9d347a430b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -447,7 +447,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(result); } - if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) { + if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); END_PROFILE(SMBtrans); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -458,6 +458,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, state->mid = SVAL(inbuf, smb_mid); state->vuid = SVAL(inbuf, smb_uid); state->setup_count = CVAL(inbuf, smb_suwcnt); + state->setup = NULL; state->total_param = SVAL(inbuf, smb_tpscnt); state->param = NULL; state->total_data = SVAL(inbuf, smb_tdscnt); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3ade5b01c6..0cee421667 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2845,7 +2845,7 @@ int reply_nttrans(connection_struct *conn, return ERROR_NT(result); } - if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) { + if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { END_PROFILE(SMBnttrans); return ERROR_DOS(ERRSRV,ERRaccess); } @@ -2862,6 +2862,7 @@ int reply_nttrans(connection_struct *conn, /* setup count is in *words* */ state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); + state->setup = NULL; state->call = function_code; /* diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f2f0150f6f..2f4bcb414f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5265,7 +5265,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_DOS(ERRSRV,ERRaccess); } - if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) { + if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); END_PROFILE(SMBtrans2); return ERROR_NT(NT_STATUS_NO_MEMORY); @@ -5276,6 +5276,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, state->mid = SVAL(inbuf, smb_mid); state->vuid = SVAL(inbuf, smb_uid); state->setup_count = SVAL(inbuf, smb_suwcnt); + state->setup = NULL; state->total_param = SVAL(inbuf, smb_tpscnt); state->param = NULL; state->total_data = SVAL(inbuf, smb_tdscnt); -- cgit From e9a2b265e7858cb68953f65a785685a3af70e912 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 16 Dec 2006 10:36:25 +0000 Subject: r20211: send_nt_replies does not need the inbuf arg (This used to be commit ab45c50da36be316773f9332925dee7dc3eec025) --- source3/smbd/nttrans.c | 83 +++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0cee421667..90a2085859 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -68,8 +68,9 @@ static char *nttrans_realloc(char **ptr, size_t size) HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params, - int paramsize, char *pdata, int datasize) +static int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, + char *params, int paramsize, char *pdata, + int datasize) { int data_to_send = datasize; int params_to_send = paramsize; @@ -477,9 +478,10 @@ int reply_ntcreate_and_X(connection_struct *conn, START_PROFILE(SMBntcreateX); - DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x \ -file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \ -create_options = 0x%x root_dir_fid = 0x%x\n", + DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " + "file_attributes = 0x%x, share_access = 0x%x, " + "create_disposition = 0x%x create_options = 0x%x " + "root_dir_fid = 0x%x\n", (unsigned int)flags, (unsigned int)access_mask, (unsigned int)file_attributes, @@ -959,7 +961,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); return -1; } @@ -1531,7 +1533,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); return -1; } @@ -1805,10 +1807,15 @@ int reply_ntrename(connection_struct *conn, don't allow a directory to be opened. ****************************************************************************/ -static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, + char *outbuf, int length, + int bufsize, + uint16 **ppsetup, uint32 setup_count, + char **ppparams, + uint32 parameter_count, + char **ppdata, uint32 data_count, + uint32 max_data_count, + uint32 max_param_count) { uint16 *setup = *ppsetup; files_struct *fsp; @@ -1827,6 +1834,9 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfid); } + DEBUG(3,("call_nt_transact_notify_change: notify change called on " + "directory name = %s\n", fsp->fsp_name )); + if((!fsp->is_directory) || (conn != fsp->conn)) { return ERROR_DOS(ERRDOS,ERRbadfid); } @@ -1835,9 +1845,6 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return(UNIXERROR(ERRDOS,ERRbadfid)); } - DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ -name = %s\n", fsp->fsp_name )); - return -1; } @@ -1877,7 +1884,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o /* * Rename was successful. */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); @@ -1972,8 +1979,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i if(max_data_count < sd_size) { - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, - params, 4, *ppdata, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, + params, 4, *ppdata, 0); talloc_destroy(mem_ctx); return -1; } @@ -2021,7 +2028,8 @@ security descriptor.\n")); talloc_destroy(mem_ctx); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 4, data, + (int)sd_size); return -1; } @@ -2067,7 +2075,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb done: - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; } @@ -2113,7 +2121,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou so we can know if we need to pre-allocate or not */ DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, + 0); return -1; case FSCTL_0x000900C0: @@ -2122,7 +2131,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, + 0); return -1; case FSCTL_GET_REPARSE_POINT: @@ -2131,7 +2141,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, + NULL, 0, NULL, 0); return -1; case FSCTL_SET_REPARSE_POINT: @@ -2140,7 +2151,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, + NULL, 0, NULL, 0); return -1; case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ @@ -2253,7 +2265,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou talloc_destroy(shadow_data->mem_ctx); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, + pdata, data_count); return -1; } @@ -2305,7 +2318,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ /* this works for now... */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, + NULL, 0); return -1; } default: @@ -2571,7 +2585,8 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, break; } - send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len, pdata, data_len); + send_nt_replies(outbuf, bufsize, nt_status, params, param_len, + pdata, data_len); return -1; } @@ -2688,7 +2703,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRSRV,ERRerror); } - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, pdata, data_len); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, + pdata, data_len); return -1; } @@ -2746,11 +2762,13 @@ static int handle_nttrans(connection_struct *conn, case NT_TRANSACT_NOTIFY_CHANGE: { START_PROFILE_NESTED(NT_transact_notify_change); - outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, state->max_data_return); + outsize = call_nt_transact_notify_change( + conn, inbuf, outbuf, size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return, + state->max_param_return); END_PROFILE_NESTED(NT_transact_notify_change); break; } @@ -2859,6 +2877,7 @@ int reply_nttrans(connection_struct *conn, state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount); state->param = NULL; state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount); + state->max_param_return = IVAL(inbuf,smb_nt_MaxParameterCount); /* setup count is in *words* */ state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); -- cgit From 771f5956937a1697b05ea29a00b9fdd36022188f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 17 Dec 2006 18:10:15 +0000 Subject: r20227: Simplify logic in vfs_MkDir() a bit (This used to be commit b24cf79e9ec914ac33f1a20524e5ffa7fe1cba5e) --- source3/smbd/vfs.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 3ed56d3bf6..ab9ddef9ff 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -315,20 +315,24 @@ int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode) int ret; SMB_STRUCT_STAT sbuf; - if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) { + if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { + return ret; + } - inherit_access_acl(conn, name, mode); + inherit_access_acl(conn, name, mode); - /* - * Check if high bits should have been set, - * then (if bits are missing): add them. - * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir. - */ - if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && - !SMB_VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) - SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); + /* + * Check if high bits should have been set, + * then (if bits are missing): add them. + * Consider bits automagically set by UNIX, i.e. SGID bit from parent + * dir. + */ + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) + && (SMB_VFS_STAT(conn,name,&sbuf) == 0) + && (mode & ~sbuf.st_mode)) { + SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); } - return ret; + return 0; } /******************************************************************* -- cgit From 9933b596d1dddca68a7bcc611e1f8cffc7f2a4e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 17 Dec 2006 18:30:44 +0000 Subject: r20228: Bring the calling conventions of inherit_access_acl and change_owner_to_parent a bit closer together: Move the lp_inherit_perms() check into the callers. Volker (This used to be commit 0874093e5fff480d8ec442072318525079add633) --- source3/smbd/open.c | 4 +++- source3/smbd/posix_acls.c | 6 +++--- source3/smbd/trans2.c | 5 ++++- source3/smbd/vfs.c | 4 +++- 4 files changed, 13 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3d5dd849b6..d916609769 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -283,7 +283,9 @@ static NTSTATUS open_file(files_struct *fsp, } /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) && !file_existed) { + if ((local_flags & O_CREAT) + && !file_existed + && lp_inherit_perms(SNUM(conn))) { inherit_access_acl(conn, fname, unx_mode); } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f17594c079..75605ace8a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3457,8 +3457,8 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode) } /**************************************************************************** - If "inherit permissions" is set and the parent directory has no default - ACL but it does have an Access ACL, inherit this Access ACL to file name. + If the parent directory has no default ACL but it does have an Access ACL, + inherit this Access ACL to file name. ****************************************************************************/ int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode) @@ -3466,7 +3466,7 @@ int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode) pstring dirname; pstrcpy(dirname, parent_dirname(name)); - if (!lp_inherit_perms(SNUM(conn)) || directory_has_default_acl(conn, dirname)) + if (directory_has_default_acl(conn, dirname)) return 0; return copy_access_acl(conn, dirname, name, mode); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2f4bcb414f..d15ca6d327 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4307,7 +4307,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); - inherit_access_acl(conn, fname, unixmode); + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl(conn, fname, + unixmode); + } SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index ab9ddef9ff..b6a7d477bd 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -319,7 +319,9 @@ int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode) return ret; } - inherit_access_acl(conn, name, mode); + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl(conn, name, mode); + } /* * Check if high bits should have been set, -- cgit From 0379e088dc8220d7d9f0509a22ac39633f53f899 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 17 Dec 2006 18:41:44 +0000 Subject: r20229: Avoid a silly function call in mkdir_internal. None of the callers look at errno, all go straight to ERROR_NT(status). Volker (This used to be commit 9d8b48c0ef0af5792b879565915832ee141c853c) --- source3/smbd/reply.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a0596643f8..2e71607402 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3755,8 +3755,7 @@ NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL b if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn)))); - errno = EACCES; - return map_nt_error_from_unix(errno); + return NT_STATUS_ACCESS_DENIED; } if (bad_path) { -- cgit From 5bb49b08f3d79ef9ee17dbbd64ce90dc438d96df Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 18 Dec 2006 04:25:21 +0000 Subject: r20237: Replace exit_server with exit_server_cleanly where appropriate. All send_smb failures should be clean exits. All times when we exit as a matter of policy should also be clean exits. (This used to be commit d6382092e72120a3c89ffe81975e8898d454bf06) --- source3/smbd/aio.c | 6 +++--- source3/smbd/blocking.c | 6 +++--- source3/smbd/ipc.c | 4 ++-- source3/smbd/negprot.c | 7 ++++--- source3/smbd/notify.c | 2 +- source3/smbd/nttrans.c | 4 ++-- source3/smbd/oplock.c | 6 +++--- source3/smbd/reply.c | 32 ++++++++++++++++---------------- source3/smbd/trans2.c | 4 ++-- 9 files changed, 36 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index c71c374043..ad25242060 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -345,7 +345,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); show_msg(aio_ex->outbuf); if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server("handle_aio_write: send_smb failed."); + exit_server_cleanly("handle_aio_write: send_smb failed."); } DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write behind for file %s\n", fsp->fsp_name )); @@ -408,7 +408,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("handle_aio_read_complete: send_smb failed."); + exit_server_cleanly("handle_aio_read_complete: send_smb failed."); } DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed for file %s, offset %.0f, len = %u\n", @@ -480,7 +480,7 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("handle_aio_write: send_smb failed."); + exit_server_cleanly("handle_aio_write: send_smb failed."); } DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed for file %s, offset %.0f, requested %u, written = %u\n", diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index aeb2bd6b6b..7a71fc67e5 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -180,7 +180,7 @@ static void send_blocking_reply(char *outbuf, int outsize) smb_setlen(outbuf,outsize - 4); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_blocking_reply: send_smb failed."); + exit_server_cleanly("send_blocking_reply: send_smb failed."); } /**************************************************************************** @@ -244,7 +244,7 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat ERROR_NT(status); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("generic_blocking_lock_error: send_smb failed."); + exit_server_cleanly("generic_blocking_lock_error: send_smb failed."); } } @@ -322,7 +322,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status SCVAL(outbuf,smb_com,SMBtrans2); ERROR_NT(status); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("blocking_lock_reply_error: send_smb failed."); + exit_server_cleanly("blocking_lock_reply_error: send_smb failed."); } break; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9d347a430b..ca128d29d9 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -115,7 +115,7 @@ void send_trans_reply(char *outbuf, show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans_reply: send_smb failed."); + exit_server_cleanly("send_trans_reply: send_smb failed."); tot_data_sent = this_ldata; tot_param_sent = this_lparam; @@ -149,7 +149,7 @@ void send_trans_reply(char *outbuf, show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans_reply: send_smb failed."); + exit_server_cleanly("send_trans_reply: send_smb failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index bbd1013050..8e9dcf22e2 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -293,7 +293,7 @@ static int reply_nt1(char *inbuf, char *outbuf) } else { DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n")); if (lp_server_signing() == Required) { - exit_server("reply_nt1: smb signing required and share level security selected."); + exit_server_cleanly("reply_nt1: smb signing required and share level security selected."); } } } @@ -461,7 +461,7 @@ int reply_negprot(connection_struct *conn, if (done_negprot) { END_PROFILE(SMBnegprot); - exit_server("multiple negprot's are not permitted"); + exit_server_cleanly("multiple negprot's are not permitted"); } done_negprot = True; @@ -570,7 +570,8 @@ int reply_negprot(connection_struct *conn, DEBUG( 5, ( "negprot index=%d\n", choice ) ); if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) { - exit_server("SMB signing is required and client negotiated a downlevel protocol"); + exit_server_cleanly("SMB signing is required and " + "client negotiated a downlevel protocol"); } END_PROFILE(SMBnegprot); diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 829ca3a736..4ec53567dd 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -62,7 +62,7 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("change_notify_reply_packet: send_smb failed."); + exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 90a2085859..d4ca1dab0c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -100,7 +100,7 @@ static int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, if(params_to_send == 0 && data_to_send == 0) { show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("send_nt_replies: send_smb failed."); + exit_server_cleanly("send_nt_replies: send_smb failed."); } return 0; } @@ -235,7 +235,7 @@ static int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, /* Send the packet */ show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("send_nt_replies: send_smb failed."); + exit_server_cleanly("send_nt_replies: send_smb failed."); } pp += params_sent_thistime; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index aaa236effa..427fb7f245 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -460,7 +460,7 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce show_msg(break_msg); if (!send_smb(smbd_server_fd(), break_msg)) { - exit_server("oplock_break: send_smb failed."); + exit_server_cleanly("oplock_break: send_smb failed."); } /* Restore the sign state to what it was. */ @@ -562,7 +562,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, show_msg(break_msg); if (!send_smb(smbd_server_fd(), break_msg)) { - exit_server("oplock_break: send_smb failed."); + exit_server_cleanly("oplock_break: send_smb failed."); } /* Restore the sign state to what it was. */ @@ -638,7 +638,7 @@ static void process_kernel_oplock_break(int msg_type, struct process_id src, show_msg(break_msg); if (!send_smb(smbd_server_fd(), break_msg)) { - exit_server("oplock_break: send_smb failed."); + exit_server_cleanly("oplock_break: send_smb failed."); } /* Restore the sign state to what it was. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2e71607402..c069bd28b9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -503,7 +503,7 @@ int reply_special(char *inbuf,char *outbuf) case 0x81: /* session request */ if (already_got_session) { - exit_server("multiple session request not permitted"); + exit_server_cleanly("multiple session request not permitted"); } SCVAL(outbuf,0,0x82); @@ -2149,7 +2149,7 @@ static void fail_readraw(void) pstring errstr; slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)", strerror(errno) ); - exit_server(errstr); + exit_server_cleanly(errstr); } #if defined(WITH_SENDFILE) @@ -2231,14 +2231,14 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) { DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); - exit_server("send_file_readbraw fake_sendfile failed"); + exit_server_cleanly("send_file_readbraw fake_sendfile failed"); } return; } DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n", fsp->fsp_name, strerror(errno) )); - exit_server("send_file_readbraw sendfile failed"); + exit_server_cleanly("send_file_readbraw sendfile failed"); } } @@ -2277,7 +2277,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s START_PROFILE(SMBreadbraw); if (srv_is_signing_active()) { - exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); } /* @@ -2599,7 +2599,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length len_outbuf - (data-outbuf))) == -1) { DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); - exit_server("send_file_readX: fake_sendfile failed"); + exit_server_cleanly("send_file_readX: fake_sendfile failed"); } DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); @@ -2609,7 +2609,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", fsp->fsp_name, strerror(errno) )); - exit_server("send_file_readX sendfile failed"); + exit_server_cleanly("send_file_readX sendfile failed"); } DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n", @@ -2743,7 +2743,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, START_PROFILE(SMBwritebraw); if (srv_is_signing_active()) { - exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed."); + exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed."); } CHECK_FSP(fsp,conn); @@ -2794,11 +2794,11 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_writebraw: send_smb failed."); + exit_server_cleanly("reply_writebraw: send_smb failed."); /* Now read the raw data into the buffer and write it */ if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { - exit_server("secondary writebraw failed"); + exit_server_cleanly("secondary writebraw failed"); } /* Even though this is not an smb message, smb_len returns the generic length of an smb message */ @@ -2813,7 +2813,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, if (numtowrite > BUFFER_SIZE) { DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n", (unsigned int)numtowrite )); - exit_server("secondary writebraw failed"); + exit_server_cleanly("secondary writebraw failed"); } if (tcount > nwritten+numtowrite) { @@ -2824,7 +2824,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) { DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n", strerror(errno) )); - exit_server("secondary writebraw failed"); + exit_server_cleanly("secondary writebraw failed"); } nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite); @@ -2859,7 +2859,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA. */ if (!send_keepalive(smbd_server_fd())) - exit_server("reply_writebraw: send of keepalive failed"); + exit_server_cleanly("reply_writebraw: send of keepalive failed"); #endif return(-1); } @@ -3555,7 +3555,7 @@ int reply_echo(connection_struct *conn, show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_echo: send_smb failed."); + exit_server_cleanly("reply_echo: send_smb failed."); } DEBUG(3,("echo %d times\n", smb_reverb)); @@ -5571,7 +5571,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_readbmpx: send_smb failed."); + exit_server_cleanly("reply_readbmpx: send_smb failed."); total_read += nread; startpos += nread; @@ -5733,7 +5733,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("reply_writebmpx: send_smb failed."); + exit_server_cleanly("reply_writebmpx: send_smb failed."); /* Now the secondary */ outsize = set_message(outbuf,1,0,True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d15ca6d327..dc85969280 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -610,7 +610,7 @@ int send_trans2_replies(char *outbuf, if(params_to_send == 0 && data_to_send == 0) { show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans2_replies: send_smb failed."); + exit_server_cleanly("send_trans2_replies: send_smb failed."); return 0; } @@ -705,7 +705,7 @@ int send_trans2_replies(char *outbuf, /* Send the packet */ show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("send_trans2_replies: send_smb failed."); + exit_server_cleanly("send_trans2_replies: send_smb failed."); pp += params_sent_thistime; pd += data_sent_thistime; -- cgit From f4f1814f8c7135577c8b774aacb8eed042380788 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Dec 2006 16:36:54 +0000 Subject: r20253: Reduce some code duplication, make reply_mkdir go through the same code paths ncreate does. This is a bit slower (about 10-20%), because it goes touches the share mode db, but I think not having to call change_owner_to_parent and friends in fewer places outweighs this. And, mkdir is not the way current Windows boxes create directories, they do it via the ncreate call. Volker (This used to be commit ddae494fbe36e4a74776f71c212b00cce61fbf81) --- source3/smbd/reply.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c069bd28b9..a7804d3f43 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3795,6 +3795,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + files_struct *fsp; START_PROFILE(SMBmkdir); @@ -3808,17 +3809,17 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,&sbuf); - if( is_ntfs_stream_name(directory)) { - DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory)); - END_PROFILE(SMBmkdir); - return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY); - } + status = open_directory(conn, directory, &sbuf, + FILE_READ_ATTRIBUTES, /* Just a stat open */ + FILE_SHARE_NONE, /* Ignored for stat opens */ + FILE_CREATE, 0, NULL, &fsp); + + DEBUG(1, ("open_directory returned %s\n", nt_errstr(status))); - status = mkdir_internal(conn, directory,bad_path); if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION) && - !use_nt_status()) { + if (NT_STATUS_EQUAL( + status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) { /* * Yes, in the DOS error code case we get a * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR @@ -3831,23 +3832,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (lp_inherit_owner(SNUM(conn))) { - /* Ensure we're checking for a symlink here.... */ - /* We don't want to get caught by a symlink racer. */ - - if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) { - END_PROFILE(SMBmkdir); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if(!S_ISDIR(sbuf.st_mode)) { - DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory )); - END_PROFILE(SMBmkdir); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - change_owner_to_parent(conn, NULL, directory, &sbuf); - } + close_file(fsp, NORMAL_CLOSE); outsize = set_message(outbuf,0,0,False); -- cgit From 920e1a368504228ab3a11aa58cbf12c7c95f4fd0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Dec 2006 18:08:51 +0000 Subject: r20257: Hey, change_owner_to_parent is now static :-) (This used to be commit 4090bc4bca77edafcafa52ecb7dc75ead2779cb5) --- source3/smbd/open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d916609769..3111f68ef5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -84,10 +84,10 @@ int fd_close(struct connection_struct *conn, Do this by fd if possible. ****************************************************************************/ -void change_owner_to_parent(connection_struct *conn, - files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) +static void change_owner_to_parent(connection_struct *conn, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) { const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; -- cgit From 9e41616b0667565e53bdff344165d0df6753b433 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Dec 2006 22:13:10 +0000 Subject: r20264: Two lines above this we just checked if (fsp->is_directory) ... (This used to be commit 88ab54b3b7ec6c0ac1958fca435880e29eeefd69) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a7804d3f43..b8ee13043b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3289,7 +3289,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, /* * Special case - close NT SMB directory handle. */ - DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum)); + DEBUG(3,("close directory fnum=%d\n", fsp->fnum)); close_file(fsp,NORMAL_CLOSE); } else { /* -- cgit From f871861673b09feeeafb3b5b204bddad1cb5cc4a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Dec 2006 21:30:11 +0000 Subject: r20310: We've checked for EA's and support for them further up already. Volker (This used to be commit 9c00ce0bbc809903b5516ef9ea62db13233ea2d4) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dc85969280..cb7e55c83f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4845,7 +4845,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, } /* Try and set any given EA. */ - if (total_data) { + if (ea_list) { status = set_ea(conn, NULL, directory, ea_list); talloc_destroy(ctx); if (!NT_STATUS_IS_OK(status)) { -- cgit From f023f8670969090f55adc96a6009d202ff672590 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Dec 2006 22:30:21 +0000 Subject: r20312: Fix a memleak (This used to be commit 20d3bc3549ef89a6405e186b87b50027d2321ac0) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cb7e55c83f..c1f7f1b5ba 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -459,7 +459,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da return NULL; } - eal->ea.value = data_blob(NULL, (size_t)val_len + 1); + eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1); if (!eal->ea.value.data) { return NULL; } -- cgit From 698877885047db370429ac7311e118512145334b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Dec 2006 22:35:10 +0000 Subject: r20313: Make trans2_mkdir also go through open_directory for all the fancy inherit_acl stuff & friends. Survives raw-mkdir. I'll activate that tomorrow when all build farm machines have picked up the changed samba4 torture test. Volker (This used to be commit 37e7a3f35f48f5689591c75d41d32c43d3b9b853) --- source3/smbd/trans2.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c1f7f1b5ba..2571104fc2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4773,12 +4773,12 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, char *params = *pparams; char *pdata = *ppdata; pstring directory; - int ret = -1; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; NTSTATUS status = NT_STATUS_OK; TALLOC_CTX *ctx = NULL; struct ea_list *ea_list = NULL; + files_struct *fsp; if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); @@ -4827,27 +4827,35 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, } ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); if (!ea_list) { - talloc_destroy(ctx); + TALLOC_FREE(ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } else if (IVAL(pdata,0) != 4) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - if (check_name(directory,conn)) { - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); - } - - if(ret < 0) { - talloc_destroy(ctx); + if (!check_name(directory,conn)) { + TALLOC_FREE(ctx); DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, + ERRnoaccess); } + status = open_directory(conn, directory, &sbuf, + FILE_READ_ATTRIBUTES, /* A stat open */ + FILE_SHARE_NONE, /* Ignored */ + FILE_CREATE, 0, NULL, &fsp); + + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(ctx); + return ERROR_NT(status); + } + close_file(fsp, NORMAL_CLOSE); + /* Try and set any given EA. */ if (ea_list) { status = set_ea(conn, NULL, directory, ea_list); - talloc_destroy(ctx); + TALLOC_FREE(ctx); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } -- cgit From b596d6a11146c8c9d94733fc64de77da8fd0e547 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 23 Dec 2006 18:55:08 +0000 Subject: r20335: Port oplock return logic from ntcreate&x to NT_TRANSACT_CREATE. Fixes parts of raw-open. Volker (This used to be commit e4e766c092e19f78a593c08f22ea1d7521be18e7) --- source3/smbd/nttrans.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d4ca1dab0c..9497c5875c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1482,8 +1482,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o p = params; if (extended_oplock_granted) { - SCVAL(p,0, BATCH_OPLOCK_RETURN); - } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + if (flags & REQUEST_BATCH_OPLOCK) { + SCVAL(p,0, BATCH_OPLOCK_RETURN); + } else { + SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN); + } + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); } else { SCVAL(p,0,NO_OPLOCK_RETURN); -- cgit From 57d11622b55faddd14b3a6e32dca8f56d18280fb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 23 Dec 2006 19:35:36 +0000 Subject: r20336: Fix some memleaks in trans2open and simplify trans2mkdir a bit: We now have tmp_talloc_ctx(). Volker (This used to be commit 165d28f03a82a1a07d0f86c0d5de4a785ea5c7f0) --- source3/smbd/trans2.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2571104fc2..e91cc7be06 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -753,7 +753,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i int smb_action = 0; BOOL bad_path = False; files_struct *fsp; - TALLOC_CTX *ctx = NULL; struct ea_list *ea_list = NULL; uint16 flags = 0; NTSTATUS status; @@ -835,13 +834,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - ctx = talloc_init("TRANS2_OPEN_SET_EA"); - if (!ctx) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4, + total_data - 4); if (!ea_list) { - talloc_destroy(ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } else if (IVAL(pdata,0) != 4) { @@ -858,7 +853,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i &smb_action, &fsp); if (!NT_STATUS_IS_OK(status)) { - talloc_destroy(ctx); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; @@ -871,7 +865,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fattr & aDIR) { - talloc_destroy(ctx); close_file(fsp,ERROR_CLOSE); return(ERROR_DOS(ERRDOS,ERRnoaccess)); } @@ -900,9 +893,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } } - if (total_data && smb_action == FILE_WAS_CREATED) { + if (ea_list && smb_action == FILE_WAS_CREATED) { status = set_ea(conn, fsp, fname, ea_list); - talloc_destroy(ctx); if (!NT_STATUS_IS_OK(status)) { close_file(fsp,ERROR_CLOSE); return ERROR_NT(status); @@ -4776,7 +4768,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, SMB_STRUCT_STAT sbuf; BOOL bad_path = False; NTSTATUS status = NT_STATUS_OK; - TALLOC_CTX *ctx = NULL; struct ea_list *ea_list = NULL; files_struct *fsp; @@ -4821,13 +4812,9 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - ctx = talloc_init("TRANS2_MKDIR_SET_EA"); - if (!ctx) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4, + total_data - 4); if (!ea_list) { - TALLOC_FREE(ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } else if (IVAL(pdata,0) != 4) { @@ -4835,7 +4822,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, } if (!check_name(directory,conn)) { - TALLOC_FREE(ctx); DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -4847,7 +4833,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, FILE_CREATE, 0, NULL, &fsp); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(ctx); return ERROR_NT(status); } close_file(fsp, NORMAL_CLOSE); @@ -4855,7 +4840,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, /* Try and set any given EA. */ if (ea_list) { status = set_ea(conn, NULL, directory, ea_list); - TALLOC_FREE(ctx); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } -- cgit From 469b42c61f73c0bd5166c33a909b3c68c1fb9dde Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 11:13:32 +0000 Subject: r20338: Restructure open_directory a bit. This gets rid of a race condition regarding error messages: We relied upon a stat that a directory did not exist to later on then do the mkdir or not. This does the mkdir directly and copes with a potential error. The second one is more important: It's possible with Samba 3 to do a ntcreate&x with NTCREATEX_OPTIONS_DIRECTORY and we happily do a NT_STATUS_OK. Also move up the use_nt_status() logic a bit. I think this does not belong into the core routines, the smb server as such should take care of it. Jeremy, do you think this should go to 3.0.24? I'll update samba4torture when the build farm has picked up this checkin. Volker (This used to be commit 472fb11f4968d30cedc9851215c63acd3132f3db) --- source3/smbd/nttrans.c | 8 +++++ source3/smbd/open.c | 88 +++++++++++++++++++++----------------------------- source3/smbd/reply.c | 5 +-- 3 files changed, 47 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9497c5875c..49a99a020f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -688,6 +688,10 @@ int reply_ntcreate_and_X(connection_struct *conn, restore_case_semantics(conn, file_attributes); if(!NT_STATUS_IS_OK(status)) { + if (!use_nt_status() && NT_STATUS_EQUAL( + status, NT_STATUS_OBJECT_NAME_COLLISION)) { + status = NT_STATUS_DOS(ERRDOS, ERRfilexists); + } END_PROFILE(SMBntcreateX); return ERROR_NT(status); } @@ -760,6 +764,10 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); + if (!use_nt_status() && NT_STATUS_EQUAL( + status, NT_STATUS_OBJECT_NAME_COLLISION)) { + status = NT_STATUS_DOS(ERRDOS, ERRfilexists); + } END_PROFILE(SMBntcreateX); return ERROR_NT(status); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3111f68ef5..dcd1a7a36f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1867,7 +1867,6 @@ NTSTATUS open_directory(connection_struct *conn, { files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; - BOOL create_dir = False; struct share_mode_lock *lck = NULL; NTSTATUS status; int info = 0; @@ -1888,44 +1887,47 @@ NTSTATUS open_directory(connection_struct *conn, switch( create_disposition ) { case FILE_OPEN: - /* If directory exists open. If directory doesn't - * exist error. */ - if (!dir_existed) { - DEBUG(5,("open_directory: FILE_OPEN requested " - "for directory %s and it doesn't " - "exist.\n", fname )); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + /* + * Don't do anything. The check for existence is done + * futher down. + */ info = FILE_WAS_OPENED; break; case FILE_CREATE: + /* If directory exists error. If directory doesn't * exist create. */ - if (dir_existed) { - DEBUG(5,("open_directory: FILE_CREATE " - "requested for directory %s and it " - "already exists.\n", fname )); - if (use_nt_status()) { - return NT_STATUS_OBJECT_NAME_COLLISION; - } else { - return NT_STATUS_DOS(ERRDOS, - ERRfilexists); - } + + status = mkdir_internal(conn, fname, False); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2, ("open_directory: unable to create " + "%s. Error was %s\n", fname, + nt_errstr(status))); + return status; } - create_dir = True; + info = FILE_WAS_CREATED; break; case FILE_OPEN_IF: - /* If directory exists open. If directory doesn't - * exist create. */ - if (!dir_existed) { - create_dir = True; + /* + * If directory exists open. If directory doesn't + * exist create. + */ + + status = mkdir_internal(conn, fname, False); + + if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; - } else { + } + + if (NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_NAME_COLLISION)) { info = FILE_WAS_OPENED; + status = NT_STATUS_OK; } + break; case FILE_SUPERSEDE: @@ -1938,35 +1940,17 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - if (create_dir) { - /* - * Try and create the directory. - */ - - /* We know bad_path is false as it's caught earlier. */ + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ - status = mkdir_internal(conn, fname, False); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("open_directory: unable to create %s. " - "Error was %s\n", fname, strerror(errno) )); - /* Ensure we return the correct NT status to the - * client. */ - return status; - } - - /* Ensure we're checking for a symlink here.... */ - /* We don't want to get caught by a symlink racer. */ - - if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - return map_nt_error_from_unix(errno); - } + if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { + return map_nt_error_from_unix(errno); + } - if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", - fname )); - return NT_STATUS_NOT_A_DIRECTORY; - } + if(!S_ISDIR(psbuf->st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", + fname )); + return NT_STATUS_NOT_A_DIRECTORY; } status = file_new(conn, &fsp); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b8ee13043b..282779fcd3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3818,8 +3818,9 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL( - status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) { + if (!use_nt_status() + && NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_NAME_COLLISION)) { /* * Yes, in the DOS error code case we get a * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR -- cgit From d0c6f9b728936297efd002008b69a59da6bbfabc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 11:45:55 +0000 Subject: r20339: Make mkdir_internal static to open.c (This used to be commit 6dd0886b49969d0edfe16861f19d35275217b2af) --- source3/smbd/open.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/reply.c | 50 ++------------------------------------------------ 2 files changed, 49 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dcd1a7a36f..e8536e3335 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1851,6 +1851,30 @@ int close_file_fchmod(files_struct *fsp) return ret; } +static NTSTATUS mkdir_internal(connection_struct *conn, + const pstring directory) +{ + int ret= -1; + + if(!CAN_WRITE(conn)) { + DEBUG(5,("mkdir_internal: failing create on read-only share " + "%s\n", lp_servicename(SNUM(conn)))); + return NT_STATUS_ACCESS_DENIED; + } + + if (!check_name(directory, conn)) { + return map_nt_error_from_unix(errno); + } + + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); + + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + + return NT_STATUS_OK; +} + /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -1899,7 +1923,7 @@ NTSTATUS open_directory(connection_struct *conn, /* If directory exists error. If directory doesn't * exist create. */ - status = mkdir_internal(conn, fname, False); + status = mkdir_internal(conn, fname); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("open_directory: unable to create " "%s. Error was %s\n", fname, @@ -1916,7 +1940,7 @@ NTSTATUS open_directory(connection_struct *conn, * exist create. */ - status = mkdir_internal(conn, fname, False); + status = mkdir_internal(conn, fname); if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; @@ -1948,7 +1972,7 @@ NTSTATUS open_directory(connection_struct *conn, } if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", + DEBUG(5,("open_directory: %s is not a directory !\n", fname )); return NT_STATUS_NOT_A_DIRECTORY; } @@ -2037,6 +2061,26 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_OK; } +NTSTATUS create_directory(connection_struct *conn, const char *directory) +{ + NTSTATUS status; + SMB_STRUCT_STAT sbuf; + files_struct *fsp; + + SET_STAT_INVALID(sbuf); + + status = open_directory(conn, directory, &sbuf, + FILE_READ_ATTRIBUTES, /* Just a stat open */ + FILE_SHARE_NONE, /* Ignored for stat opens */ + FILE_CREATE, 0, NULL, &fsp); + + if (NT_STATUS_IS_OK(status)) { + close_file(fsp, NORMAL_CLOSE); + } + + return status; +} + /**************************************************************************** Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 282779fcd3..a156409942 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3744,46 +3744,6 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ return(outsize); } -/**************************************************************************** - The guts of the mkdir command, split out so it may be called by the NT SMB - code. -****************************************************************************/ - -NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path) -{ - int ret= -1; - - if(!CAN_WRITE(conn)) { - DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn)))); - return NT_STATUS_ACCESS_DENIED; - } - - if (bad_path) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - if (!check_name(directory, conn)) { - if(errno == ENOENT) { - if (bad_path) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } else { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - } - return map_nt_error_from_unix(errno); - } - - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); - if (ret == -1) { - if(errno == ENOENT) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - return map_nt_error_from_unix(errno); - } - - return NT_STATUS_OK; -} - /**************************************************************************** Reply to a mkdir. ****************************************************************************/ @@ -3795,7 +3755,6 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; - files_struct *fsp; START_PROFILE(SMBmkdir); @@ -3809,12 +3768,9 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unix_convert(directory,conn,0,&bad_path,&sbuf); - status = open_directory(conn, directory, &sbuf, - FILE_READ_ATTRIBUTES, /* Just a stat open */ - FILE_SHARE_NONE, /* Ignored for stat opens */ - FILE_CREATE, 0, NULL, &fsp); + status = create_directory(conn, directory); - DEBUG(1, ("open_directory returned %s\n", nt_errstr(status))); + DEBUG(1, ("create_directory returned %s\n", nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { @@ -3833,8 +3789,6 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - close_file(fsp, NORMAL_CLOSE); - outsize = set_message(outbuf,0,0,False); DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); -- cgit From af1750934d12c82b87a9d1f1ab96f24474fb9768 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 14:29:19 +0000 Subject: r20340: Join vfs_MkDir to its only caller (This used to be commit cce911780fc52ea56dccde1879b0891cdf9ea320) --- source3/smbd/open.c | 32 +++++++++++++++++++++++++------- source3/smbd/vfs.c | 31 ------------------------------- 2 files changed, 25 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e8536e3335..1ca793fb80 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1851,27 +1851,45 @@ int close_file_fchmod(files_struct *fsp) return ret; } -static NTSTATUS mkdir_internal(connection_struct *conn, - const pstring directory) +static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) { + SMB_STRUCT_STAT sbuf; int ret= -1; - + mode_t mode; + if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " "%s\n", lp_servicename(SNUM(conn)))); return NT_STATUS_ACCESS_DENIED; } - if (!check_name(directory, conn)) { + if (!check_name(name, conn)) { return map_nt_error_from_unix(errno); } - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); + mode = unix_mode(conn, aDIR, name, True); - if (ret == -1) { + if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { return map_nt_error_from_unix(errno); } - + + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl(conn, name, mode); + } + + /* + * Check if high bits should have been set, + * then (if bits are missing): add them. + * Consider bits automagically set by UNIX, i.e. SGID bit from parent + * dir. + */ + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) + && (SMB_VFS_STAT(conn, name, &sbuf) == 0) + && (mode & ~sbuf.st_mode)) { + SMB_VFS_CHMOD(conn, name, + sbuf.st_mode | (mode & ~sbuf.st_mode)); + } + return NT_STATUS_OK; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b6a7d477bd..a4ecff921a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -306,37 +306,6 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ return ret; } -/******************************************************************* - vfs mkdir wrapper -********************************************************************/ - -int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode) -{ - int ret; - SMB_STRUCT_STAT sbuf; - - if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { - return ret; - } - - if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, name, mode); - } - - /* - * Check if high bits should have been set, - * then (if bits are missing): add them. - * Consider bits automagically set by UNIX, i.e. SGID bit from parent - * dir. - */ - if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) - && (SMB_VFS_STAT(conn,name,&sbuf) == 0) - && (mode & ~sbuf.st_mode)) { - SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); - } - return 0; -} - /******************************************************************* Check if an object exists in the vfs. ********************************************************************/ -- cgit From 4e5a335c07c7768cf731ee4bf430ad90acad306d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 15:11:03 +0000 Subject: r20342: Move the lstat into mkdir_internal, for the FILE_OPEN case in open_directory we want to follow symlinks. Volker (This used to be commit c20bdd219d16abcc60d67f4a21b4fcd661473835) --- source3/smbd/open.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1ca793fb80..02decdc06f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1851,9 +1851,9 @@ int close_file_fchmod(files_struct *fsp) return ret; } -static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) +static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, + SMB_STRUCT_STAT *psbuf) { - SMB_STRUCT_STAT sbuf; int ret= -1; mode_t mode; @@ -1873,6 +1873,21 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) return map_nt_error_from_unix(errno); } + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + + if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) { + DEBUG(2, ("Could not stat directory '%s' just created: %s\n", + name, strerror(errno))); + return map_nt_error_from_unix(errno); + } + + if (!S_ISDIR(psbuf->st_mode)) { + DEBUG(0, ("Directory just '%s' created is not a directory\n", + name)); + return NT_STATUS_ACCESS_DENIED; + } + if (lp_inherit_perms(SNUM(conn))) { inherit_access_acl(conn, name, mode); } @@ -1883,11 +1898,9 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) * Consider bits automagically set by UNIX, i.e. SGID bit from parent * dir. */ - if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) - && (SMB_VFS_STAT(conn, name, &sbuf) == 0) - && (mode & ~sbuf.st_mode)) { + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { SMB_VFS_CHMOD(conn, name, - sbuf.st_mode | (mode & ~sbuf.st_mode)); + psbuf->st_mode | (mode & ~psbuf->st_mode)); } return NT_STATUS_OK; @@ -1929,11 +1942,17 @@ NTSTATUS open_directory(connection_struct *conn, switch( create_disposition ) { case FILE_OPEN: + + info = FILE_WAS_OPENED; + /* - * Don't do anything. The check for existence is done - * futher down. + * We want to follow symlinks here. */ - info = FILE_WAS_OPENED; + + if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { + return map_nt_error_from_unix(errno); + } + break; case FILE_CREATE: @@ -1941,7 +1960,7 @@ NTSTATUS open_directory(connection_struct *conn, /* If directory exists error. If directory doesn't * exist create. */ - status = mkdir_internal(conn, fname); + status = mkdir_internal(conn, fname, psbuf); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("open_directory: unable to create " "%s. Error was %s\n", fname, @@ -1958,7 +1977,7 @@ NTSTATUS open_directory(connection_struct *conn, * exist create. */ - status = mkdir_internal(conn, fname); + status = mkdir_internal(conn, fname, psbuf); if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; @@ -1982,13 +2001,6 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - /* Ensure we're checking for a symlink here.... */ - /* We don't want to get caught by a symlink racer. */ - - if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - return map_nt_error_from_unix(errno); - } - if(!S_ISDIR(psbuf->st_mode)) { DEBUG(5,("open_directory: %s is not a directory !\n", fname )); -- cgit From a67757ef9c6ed421341fe948d93aff94991da053 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 15:29:09 +0000 Subject: r20343: Split change_owner_to_parent fd-based (for file opens) and a name-based (for directory opens) routines. Volker (This used to be commit 4ca921d9aa90bc68d21d40ccf4b1ca0b1d2cbcb1) --- source3/smbd/open.c | 156 ++++++++++++++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 73 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 02decdc06f..c3df5acde3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -84,11 +84,43 @@ int fd_close(struct connection_struct *conn, Do this by fd if possible. ****************************************************************************/ +static void change_fd_owner_to_parent(connection_struct *conn, + files_struct *fsp) +{ + const char *parent_path = parent_dirname(fsp->fsp_name); + SMB_STRUCT_STAT parent_st; + int ret; + + ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + if (ret == -1) { + DEBUG(0,("change_fd_owner_to_parent: failed to stat parent " + "directory %s. Error was %s\n", + parent_path, strerror(errno) )); + return; + } + + become_root(); + ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(0,("change_fd_owner_to_parent: failed to fchown " + "file %s to parent directory uid %u. Error " + "was %s\n", fsp->fsp_name, + (unsigned int)parent_st.st_uid, + strerror(errno) )); + } + + DEBUG(10,("change_fd_owner_to_parent: changed new file %s to " + "parent directory uid %u.\n", fsp->fsp_name, + (unsigned int)parent_st.st_uid )); +} + static void change_owner_to_parent(connection_struct *conn, - files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf) { + pstring saved_dir; + SMB_STRUCT_STAT sbuf; const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; int ret; @@ -101,83 +133,62 @@ static void change_owner_to_parent(connection_struct *conn, return; } - if (fsp && fsp->fh->fd != -1) { - become_root(); - ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); - unbecome_root(); - if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to fchown " - "file %s to parent directory uid %u. Error " - "was %s\n", fname, - (unsigned int)parent_st.st_uid, - strerror(errno) )); - } - - DEBUG(10,("change_owner_to_parent: changed new file %s to " - "parent directory uid %u.\n", fname, - (unsigned int)parent_st.st_uid )); + /* We've already done an lstat into psbuf, and we know it's a + directory. If we can cd into the directory and the dev/ino + are the same then we can safely chown without races as + we're locking the directory in place by being in it. This + should work on any UNIX (thanks tridge :-). JRA. + */ - } else { - /* We've already done an lstat into psbuf, and we know it's a - directory. If we can cd into the directory and the dev/ino - are the same then we can safely chown without races as - we're locking the directory in place by being in it. This - should work on any UNIX (thanks tridge :-). JRA. - */ - - pstring saved_dir; - SMB_STRUCT_STAT sbuf; - - if (!vfs_GetWd(conn,saved_dir)) { - DEBUG(0,("change_owner_to_parent: failed to get " - "current working directory\n")); - return; - } + if (!vfs_GetWd(conn,saved_dir)) { + DEBUG(0,("change_owner_to_parent: failed to get " + "current working directory\n")); + return; + } - /* Chdir into the new path. */ - if (vfs_ChDir(conn, fname) == -1) { - DEBUG(0,("change_owner_to_parent: failed to change " - "current working directory to %s. Error " - "was %s\n", fname, strerror(errno) )); - goto out; - } + /* Chdir into the new path. */ + if (vfs_ChDir(conn, fname) == -1) { + DEBUG(0,("change_owner_to_parent: failed to change " + "current working directory to %s. Error " + "was %s\n", fname, strerror(errno) )); + goto out; + } - if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat " - "directory '.' (%s) Error was %s\n", - fname, strerror(errno))); - goto out; - } + if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat " + "directory '.' (%s) Error was %s\n", + fname, strerror(errno))); + goto out; + } - /* Ensure we're pointing at the same place. */ - if (sbuf.st_dev != psbuf->st_dev || - sbuf.st_ino != psbuf->st_ino || - sbuf.st_mode != psbuf->st_mode ) { - DEBUG(0,("change_owner_to_parent: " - "device/inode/mode on directory %s changed. " - "Refusing to chown !\n", fname )); - goto out; - } + /* Ensure we're pointing at the same place. */ + if (sbuf.st_dev != psbuf->st_dev || + sbuf.st_ino != psbuf->st_ino || + sbuf.st_mode != psbuf->st_mode ) { + DEBUG(0,("change_owner_to_parent: " + "device/inode/mode on directory %s changed. " + "Refusing to chown !\n", fname )); + goto out; + } - become_root(); - ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); - unbecome_root(); - if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to chown " - "directory %s to parent directory uid %u. " - "Error was %s\n", fname, - (unsigned int)parent_st.st_uid, strerror(errno) )); - goto out; - } + become_root(); + ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(10,("change_owner_to_parent: failed to chown " + "directory %s to parent directory uid %u. " + "Error was %s\n", fname, + (unsigned int)parent_st.st_uid, strerror(errno) )); + goto out; + } - DEBUG(10,("change_owner_to_parent: changed ownership of new " - "directory %s to parent directory uid %u.\n", - fname, (unsigned int)parent_st.st_uid )); + DEBUG(10,("change_owner_to_parent: changed ownership of new " + "directory %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); - out: + out: - vfs_ChDir(conn,saved_dir); - } + vfs_ChDir(conn,saved_dir); } /**************************************************************************** @@ -1693,8 +1704,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, info = FILE_WAS_CREATED; /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp, fsp->fsp_name, - psbuf); + change_fd_owner_to_parent(conn, fsp); } } @@ -2078,7 +2088,7 @@ NTSTATUS open_directory(connection_struct *conn, /* Change the owner if required. */ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + change_owner_to_parent(conn, fsp->fsp_name, psbuf); } if (pinfo) { -- cgit From e8e5c17f2e5c09dff5b2acaaab9a9659b9242c6f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 16:37:22 +0000 Subject: r20344: Move the calls to inherit_access_acls and change_owner_to_parent together. Jeremy, I'm 100% sure you watch me closely here, I count on you :-) Volker (This used to be commit 02f85265f21607c950639da33bc8fe5d5ffd3cf9) --- source3/smbd/open.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c3df5acde3..59cd8030af 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -293,11 +293,17 @@ static NTSTATUS open_file(files_struct *fsp, return map_nt_error_from_unix(errno); } - /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) - && !file_existed - && lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, fname, unx_mode); + if ((local_flags & O_CREAT) && !file_existed) { + + /* Inherit the ACL if required */ + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl(conn, fname, unx_mode); + } + + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_fd_owner_to_parent(conn, fsp); + } } } else { @@ -1702,10 +1708,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } } else { info = FILE_WAS_CREATED; - /* Change the owner if required. */ - if (lp_inherit_owner(SNUM(conn))) { - change_fd_owner_to_parent(conn, fsp); - } } if (pinfo) { @@ -1913,6 +1915,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, psbuf->st_mode | (mode & ~psbuf->st_mode)); } + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, name, psbuf); + } + return NT_STATUS_OK; } @@ -2086,11 +2093,6 @@ NTSTATUS open_directory(connection_struct *conn, TALLOC_FREE(lck); - /* Change the owner if required. */ - if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp->fsp_name, psbuf); - } - if (pinfo) { *pinfo = info; } -- cgit From 96a2972bd267b4e60242127b43f5466471c3d720 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 17:09:08 +0000 Subject: r20345: Simplify call_nt_transact_create by using tmp_talloc_ctx() (This used to be commit df6362baa0928616c6934950fb9c1264cb27106e) --- source3/smbd/nttrans.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 49a99a020f..260a640dae 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1293,19 +1293,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } if (ea_len) { - ctx = talloc_init("NTTRANS_CREATE_EA"); - if (!ctx) { - talloc_destroy(ctx); - restore_case_semantics(conn, file_attributes); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - pdata = data + sd_len; /* We have already checked that ea_len <= data_count here. */ - ea_list = read_nttrans_ea_list(ctx, pdata, ea_len); + ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata, + ea_len); if (!ea_list ) { - talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1319,7 +1312,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1339,7 +1331,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o create_options, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { - talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } @@ -1380,12 +1371,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o create_options, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { - talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } } else { - talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ @@ -1426,7 +1415,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (ea_len && (info == FILE_WAS_CREATED)) { status = set_ea(conn, fsp, fname, ea_list); - talloc_destroy(ctx); if (!NT_STATUS_IS_OK(status)) { close_file(fsp,ERROR_CLOSE); restore_case_semantics(conn, file_attributes); -- cgit From 8cd9636458e175d2e1b63a5211423cec04a6ce91 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 27 Dec 2006 10:57:59 +0000 Subject: r20356: Consolidate the calls to parent_dirname() per open to one. This involved passing the dirname as argument to a few routines instead of calling parent_dirname() deep down. Volker (This used to be commit 7977fd78652897bb7d4db1c21c5749043428f911) --- source3/smbd/dosmode.c | 27 +++++++++------ source3/smbd/nttrans.c | 3 +- source3/smbd/open.c | 86 ++++++++++++++++++++++++++++------------------- source3/smbd/posix_acls.c | 15 +++++---- source3/smbd/trans2.c | 5 +-- 5 files changed, 80 insertions(+), 56 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 260a8dadbd..1172fe3e6b 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -59,7 +59,7 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path) /**************************************************************************** Change a dos mode to a unix mode. Base permission for files: - if creating file and inheriting + if creating file and inheriting (i.e. parent_dir != NULL) apply read/write bits from parent directory. else everybody gets read bit set @@ -79,23 +79,26 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path) } ****************************************************************************/ -mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL creating_file) +mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, + const char *inherit_from_dir) { mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); - mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ + mode_t dir_mode = 0; /* Mode of the inherit_from directory if + * inheriting. */ if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) { result &= ~(S_IWUSR | S_IWGRP | S_IWOTH); } - if (fname && creating_file && lp_inherit_perms(SNUM(conn))) { - char *dname; + if (fname && (inherit_from_dir != NULL) + && lp_inherit_perms(SNUM(conn))) { SMB_STRUCT_STAT sbuf; - dname = parent_dirname(fname); - DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) { - DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); + DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname, + inherit_from_dir)); + if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) { + DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname, + inherit_from_dir, strerror(errno))); return(0); /* *** shouldn't happen! *** */ } @@ -429,7 +432,9 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) chmod a file - but preserve some bits. ********************************************************************/ -int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, BOOL creating_file) +int file_set_dosmode(connection_struct *conn, const char *fname, + uint32 dosmode, SMB_STRUCT_STAT *st, + const char *parent_dir) { SMB_STRUCT_STAT st1; int mask=0; @@ -462,7 +467,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, return 0; } - unixmode = unix_mode(conn,dosmode,fname, creating_file); + unixmode = unix_mode(conn,dosmode,fname, parent_dir); /* preserve the s bits */ mask |= (S_ISUID | S_ISGID); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 260a640dae..377ddbeec3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1697,7 +1697,8 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new /* Grrr. We have to do this as open_file_ntcreate adds aARCH when it creates the file. This isn't the correct thing to do in the copy case. JRA */ - file_set_dosmode(conn, newname, fattr, &sbuf2, True); + file_set_dosmode(conn, newname, fattr, &sbuf2, + parent_dirname(newname)); if (ret < (SMB_OFF_T)sbuf1.st_size) { return NT_STATUS_DISK_FULL; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 59cd8030af..28170e9cd8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -84,18 +84,18 @@ int fd_close(struct connection_struct *conn, Do this by fd if possible. ****************************************************************************/ -static void change_fd_owner_to_parent(connection_struct *conn, - files_struct *fsp) +static void change_file_owner_to_parent(connection_struct *conn, + const char *inherit_from_dir, + files_struct *fsp) { - const char *parent_path = parent_dirname(fsp->fsp_name); SMB_STRUCT_STAT parent_st; int ret; - ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { - DEBUG(0,("change_fd_owner_to_parent: failed to stat parent " + DEBUG(0,("change_file_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", - parent_path, strerror(errno) )); + inherit_from_dir, strerror(errno) )); return; } @@ -103,33 +103,33 @@ static void change_fd_owner_to_parent(connection_struct *conn, ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(0,("change_fd_owner_to_parent: failed to fchown " + DEBUG(0,("change_file_owner_to_parent: failed to fchown " "file %s to parent directory uid %u. Error " "was %s\n", fsp->fsp_name, (unsigned int)parent_st.st_uid, strerror(errno) )); } - DEBUG(10,("change_fd_owner_to_parent: changed new file %s to " + DEBUG(10,("change_file_owner_to_parent: changed new file %s to " "parent directory uid %u.\n", fsp->fsp_name, (unsigned int)parent_st.st_uid )); } -static void change_owner_to_parent(connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf) +static void change_dir_owner_to_parent(connection_struct *conn, + const char *inherit_from_dir, + const char *fname, + SMB_STRUCT_STAT *psbuf) { pstring saved_dir; SMB_STRUCT_STAT sbuf; - const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; int ret; - ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat parent " + DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", - parent_path, strerror(errno) )); + inherit_from_dir, strerror(errno) )); return; } @@ -141,21 +141,21 @@ static void change_owner_to_parent(connection_struct *conn, */ if (!vfs_GetWd(conn,saved_dir)) { - DEBUG(0,("change_owner_to_parent: failed to get " + DEBUG(0,("change_dir_owner_to_parent: failed to get " "current working directory\n")); return; } /* Chdir into the new path. */ if (vfs_ChDir(conn, fname) == -1) { - DEBUG(0,("change_owner_to_parent: failed to change " + DEBUG(0,("change_dir_owner_to_parent: failed to change " "current working directory to %s. Error " "was %s\n", fname, strerror(errno) )); goto out; } if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat " + DEBUG(0,("change_dir_owner_to_parent: failed to stat " "directory '.' (%s) Error was %s\n", fname, strerror(errno))); goto out; @@ -165,7 +165,7 @@ static void change_owner_to_parent(connection_struct *conn, if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { - DEBUG(0,("change_owner_to_parent: " + DEBUG(0,("change_dir_owner_to_parent: " "device/inode/mode on directory %s changed. " "Refusing to chown !\n", fname )); goto out; @@ -175,14 +175,14 @@ static void change_owner_to_parent(connection_struct *conn, ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to chown " + DEBUG(10,("change_dir_owner_to_parent: failed to chown " "directory %s to parent directory uid %u. " "Error was %s\n", fname, (unsigned int)parent_st.st_uid, strerror(errno) )); goto out; } - DEBUG(10,("change_owner_to_parent: changed ownership of new " + DEBUG(10,("change_dir_owner_to_parent: changed ownership of new " "directory %s to parent directory uid %u.\n", fname, (unsigned int)parent_st.st_uid )); @@ -197,6 +197,7 @@ static void change_owner_to_parent(connection_struct *conn, static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, + const char *parent_dir, const char *fname, SMB_STRUCT_STAT *psbuf, int flags, @@ -297,12 +298,14 @@ static NTSTATUS open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, fname, unx_mode); + inherit_access_acl(conn, parent_dir, fname, + unx_mode); } /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_fd_owner_to_parent(conn, fsp); + change_file_owner_to_parent(conn, parent_dir, + fsp); } } @@ -1124,6 +1127,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; + const char *parent_dir; if (conn->printer) { /* @@ -1140,9 +1144,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return print_fsp_open(conn, fname, result); } + if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), + parent_dirname(fname)))) { + return NT_STATUS_NO_MEMORY; + } + /* We add aARCH to this as this mode is only used if the file is * created new. */ - unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True); + unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, + parent_dir); DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " "access_mask=0x%x share_access=0x%x " @@ -1194,7 +1204,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* this is for OS/2 long file names - say we don't support them */ if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { /* OS/2 Workplace shell fix may be main code stream in a later - * release. */ + * release. */ DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " "supported.\n")); if (use_nt_status()) { @@ -1554,8 +1564,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && - (def_acl = directory_has_default_acl(conn, - parent_dirname(fname)))) { + (def_acl = directory_has_default_acl(conn, parent_dir))) { unx_mode = 0777; } @@ -1569,8 +1578,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, - access_mask, open_access_mask); + fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2, + unx_mode, access_mask, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1658,7 +1667,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); if(ret_flock == -1 ){ - talloc_free(lck); + TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1755,7 +1764,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, lp_store_dos_attributes(SNUM(conn))) { file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, - True); + parent_dir); } } @@ -1835,7 +1844,8 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA); + status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0, + FILE_WRITE_DATA, FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1868,6 +1878,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, { int ret= -1; mode_t mode; + const char *parent_dir; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -1879,7 +1890,12 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return map_nt_error_from_unix(errno); } - mode = unix_mode(conn, aDIR, name, True); + if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), + parent_dirname(name)))) { + return NT_STATUS_NO_MEMORY; + } + + mode = unix_mode(conn, aDIR, name, parent_dir); if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { return map_nt_error_from_unix(errno); @@ -1901,7 +1917,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, } if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, name, mode); + inherit_access_acl(conn, parent_dir, name, mode); } /* @@ -1917,7 +1933,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, name, psbuf); + change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } return NT_STATUS_OK; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 75605ace8a..c5da33c9df 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1878,7 +1878,10 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; mode_t or_bits = (mode_t)0; - mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, False) : S_IRUSR; + mode_t mode = interitable_mode + ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, + NULL ) + : S_IRUSR; if (fsp->is_directory) mode |= (S_IWUSR|S_IXUSR); @@ -3461,15 +3464,13 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode) inherit this Access ACL to file name. ****************************************************************************/ -int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode) +int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir, + const char *name, mode_t mode) { - pstring dirname; - pstrcpy(dirname, parent_dirname(name)); - - if (directory_has_default_acl(conn, dirname)) + if (directory_has_default_acl(conn, inherit_from_dir)) return 0; - return copy_access_acl(conn, dirname, name, mode); + return copy_access_acl(conn, inherit_from_dir, name, mode); } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e91cc7be06..9f22f65e34 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4300,8 +4300,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return(UNIXERROR(ERRDOS,ERRnoaccess)); if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, fname, - unixmode); + inherit_access_acl( + conn, parent_dirname(fname), + fname, unixmode); } SSVAL(params,0,0); -- cgit From ae7526fd55741ecbb0bd90d47a18578f0baafe87 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Dec 2006 18:51:09 +0000 Subject: r20362: Fix valgrind issues where we may read params before checking length. Found by Volker. Jeremy. (This used to be commit 683c5fce6896236a60145f6d3970566503c39163) --- source3/smbd/trans2.c | 58 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9f22f65e34..9b6a175a9a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1640,13 +1640,13 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb requested. */ char *params = *pparams; char *pdata = *ppdata; - uint32 dirtype = SVAL(params,0); - int maxentries = SVAL(params,2); - uint16 findfirst_flags = SVAL(params,4); - BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE); - BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); - BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); - int info_level = SVAL(params,6); + uint32 dirtype; + int maxentries; + uint16 findfirst_flags; + BOOL close_after_first; + BOOL close_if_end; + BOOL requires_resume_key; + int info_level; pstring directory; pstring mask; char *p; @@ -1669,6 +1669,14 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + dirtype = SVAL(params,0); + maxentries = SVAL(params,2); + findfirst_flags = SVAL(params,4); + close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE); + close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); + requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); + info_level = SVAL(params,6); + *directory = *mask = 0; DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \ @@ -1908,15 +1916,15 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu requested. */ char *params = *pparams; char *pdata = *ppdata; - int dptr_num = SVAL(params,0); - int maxentries = SVAL(params,2); - uint16 info_level = SVAL(params,4); - uint32 resume_key = IVAL(params,6); - uint16 findnext_flags = SVAL(params,10); - BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE); - BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); - BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); - BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); + int dptr_num; + int maxentries; + uint16 info_level; + uint32 resume_key; + uint16 findnext_flags; + BOOL close_after_request; + BOOL close_if_end; + BOOL requires_resume_key; + BOOL continue_bit; BOOL mask_contains_wcard = False; pstring resume_name; pstring mask; @@ -1937,6 +1945,16 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + dptr_num = SVAL(params,0); + maxentries = SVAL(params,2); + info_level = SVAL(params,4); + resume_key = IVAL(params,6); + findnext_flags = SVAL(params,10); + close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE); + close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); + requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); + continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); + *mask = *directory = *resume_name = 0; srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard); @@ -2174,7 +2192,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { char *pdata = *ppdata; char *params = *pparams; - uint16 info_level = SVAL(params,0); + uint16 info_level; int data_len, len; SMB_STRUCT_STAT st; char *vname = volume_label(SNUM(conn)); @@ -2182,6 +2200,12 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf char *fstype = lp_fstype(SNUM(conn)); int quota_flag = 0; + if (total_params < 2) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + info_level = SVAL(params,0); + DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); if(SMB_VFS_STAT(conn,".",&st)!=0) { -- cgit From b26a9ad9dfe2976ae1f6c31b270bdcd7818172c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Dec 2006 20:45:12 +0000 Subject: r20363: Fix any possible valgrind errors in srvstr_get_XX or srvstr_pull_XX by ensuring we pass in a valid src_len (or zero when appropriate). Volker is correct in that this is a *horrible* interface and he is now free to generally clean it up everywhere :-). Go for it Volker ! Jeremy. (This used to be commit cd991fb839994dd29dc790b655f5597fa1e12843) --- source3/smbd/nttrans.c | 4 ++-- source3/smbd/trans2.c | 45 +++++++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 377ddbeec3..68c5b46189 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1865,14 +1865,14 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o BOOL path_contains_wcard = False; NTSTATUS status; - if(parameter_count < 4) { + if(parameter_count < 5) { return ERROR_DOS(ERRDOS,ERRbadfunc); } fsp = file_fsp(params, 0); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); - srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, &path_contains_wcard); + srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9b6a175a9a..1ebdf16b8a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -790,7 +790,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return(ERROR_DOS(ERRSRV,ERRaccess)); } - srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1665,7 +1665,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; - if (total_params < 12) { + if (total_params < 13) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1709,7 +1709,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard); + srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { return ERROR_NT(ntstatus); } @@ -1941,7 +1941,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; - if (total_params < 12) { + if (total_params < 13) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1957,7 +1957,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu *mask = *directory = *resume_name = 0; - srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard); + srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to complain (it thinks we're asking for the directory above the shared @@ -2933,7 +2933,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * NTSTATUS status = NT_STATUS_OK; /* qpathinfo */ - if (total_params < 6) { + if (total_params < 7) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -2941,7 +2941,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -3843,12 +3843,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } } else { /* set path info */ - if (total_params < 6) { + if (total_params < 7) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } info_level = SVAL(params,0); - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4377,10 +4377,14 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Set a symbolic link. */ /* Don't allow this if follow links is false. */ + if (total_data == 0) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + if (!lp_symlinks(SNUM(conn))) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE); + srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE); /* !widelinks forces the target path to be within the share. */ /* This means we can interpret the target as a pathname. */ @@ -4423,7 +4427,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", char *newname = fname; /* Set a hard link. */ - srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status); + if (total_data == 0) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4450,13 +4458,18 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstring base_name; char *p; - if (total_data < 12) { + if (total_data < 13) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } overwrite = (CVAL(pdata,0) ? True : False); /* root_fid = IVAL(pdata,4); */ len = IVAL(pdata,8); + + if (len > (total_data - 12) || (len == 0)) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); @@ -4799,11 +4812,11 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); - if (total_params < 4) { + if (total_params < 5) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status); + srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4976,7 +4989,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* DEBUG(10,("call_trans2getdfsreferral\n")); - if (total_params < 2) { + if (total_params < 3) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -4985,7 +4998,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* if(!lp_host_msdfs()) return ERROR_DOS(ERRDOS,ERRbadfunc); - srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE); + srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE); if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0) return UNIXERROR(ERRDOS,ERRbadfile); -- cgit From 2703b3ac480b1c29684b13297f5e78481c889223 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Dec 2006 23:52:47 +0000 Subject: r20368: Fix valgrind report of uninitialized memory being returned (false positive). Up debug level on "open_directory" message. Jeremy. (This used to be commit 71a8b8863f8bdcce082c5971d6489a2da3ff4b2c) --- source3/smbd/negprot.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 8e9dcf22e2..fec5971045 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -174,6 +174,9 @@ static DATA_BLOB negprot_spnego(void) DATA_BLOB blob; nstring dos_name; fstring unix_name; +#ifdef DEVELOPER + size_t slen; +#endif char guid[17]; const char *OIDs_krb5[] = {OID_KERBEROS5, OID_KERBEROS5_OLD, @@ -183,13 +186,21 @@ static DATA_BLOB negprot_spnego(void) global_spnego_negotiated = True; - ZERO_STRUCT(guid); + memset(guid, '\0', sizeof(guid)); safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1); strlower_m(unix_name); push_ascii_nstring(dos_name, unix_name); safe_strcpy(guid, dos_name, sizeof(guid)-1); +#ifdef DEVELOPER + /* Fix valgrind 'uninitialized bytes' issue. */ + slen = strlen(dos_name); + if (slen < sizeof(guid)) { + memset(guid+slen, '\0', sizeof(guid) - slen); + } +#endif + /* strangely enough, NT does not sent the single OID NTLMSSP when not a ADS member, it sends no OIDs at all -- cgit From 654f747e6df985b6b519925662bf1014b98d1670 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Dec 2006 00:01:12 +0000 Subject: r20370: Now we've gone to the trouble of getting an NT status from open_file_ntcreate make sure we return it on rename error. Jeremy. (This used to be commit 633f02fb860223585f388e64c1a2d770db52d4f0) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a156409942..1bd87a5a13 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1878,7 +1878,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, NULL, &fsp); if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_ACCESS_DENIED; + return status; } close_file(fsp,NORMAL_CLOSE); return NT_STATUS_OK; -- cgit From 3430c1ddb825a458f294e48c351be010698bad69 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Dec 2006 00:10:55 +0000 Subject: r20371: In renames (via SMBmv) both src and dest can contain wcards. I had forgotten this and had refused to allow dest to contain wcards. We now pass all the normal Samba4 smbtorture RAW-RENAME tests. Jeremy (This used to be commit 4183c1b49fd5a6107aa87249b7be236af092ed8b) --- source3/smbd/reply.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1bd87a5a13..ec588d4478 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4612,18 +4612,19 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, char *p; uint32 attrs = SVAL(inbuf,smb_vwv0); NTSTATUS status; - BOOL path_contains_wcard = False; + BOOL path1_contains_wcard = False; + BOOL path2_contains_wcard = False; START_PROFILE(SMBmv); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard); + p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); } p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); + p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); @@ -4634,7 +4635,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard); + status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); if (open_was_deferred(SVAL(inbuf,smb_mid))) { -- cgit From 48c3f76b2e6bc197c6977d22480a31e7f4b10b69 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Dec 2006 00:24:34 +0000 Subject: r20372: Make NTrename the same as SMBmv w.r.t. wildcards. Jeremy. (This used to be commit b8d5faac69f3a0c2620a34f9026b4018ebd48bb8) --- source3/smbd/nttrans.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 68c5b46189..6359f931c0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1724,14 +1724,15 @@ int reply_ntrename(connection_struct *conn, pstring newname; char *p; NTSTATUS status; - BOOL path_contains_wcard = False; + BOOL path1_contains_wcard = False; + BOOL path2_contains_wcard = False; uint32 attrs = SVAL(inbuf,smb_vwv0); uint16 rename_type = SVAL(inbuf,smb_vwv1); START_PROFILE(SMBntrename); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path_contains_wcard); + p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path1_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1749,7 +1750,7 @@ int reply_ntrename(connection_struct *conn, } p++; - p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); + p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1762,13 +1763,18 @@ int reply_ntrename(connection_struct *conn, switch(rename_type) { case RENAME_FLAG_RENAME: - status = rename_internals(conn, oldname, newname, attrs, False, path_contains_wcard); + status = rename_internals(conn, oldname, newname, attrs, False, path1_contains_wcard); break; case RENAME_FLAG_HARD_LINK: - status = hardlink_internals(conn, oldname, newname); + if (path1_contains_wcard || path2_contains_wcard) { + /* No wildcards. */ + status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + } else { + status = hardlink_internals(conn, oldname, newname); + } break; case RENAME_FLAG_COPY: - if (path_contains_wcard) { + if (path1_contains_wcard || path2_contains_wcard) { /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { -- cgit From 143a364d6253125c27e229d533940a6822ce7575 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Dec 2006 21:34:31 +0000 Subject: r20393: Debug level 1 is a bit excessive here (This used to be commit 48798b5e57fcb2ee7debfe9d5178adef37907f92) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec588d4478..f6d5211310 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3770,7 +3770,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = create_directory(conn, directory); - DEBUG(1, ("create_directory returned %s\n", nt_errstr(status))); + DEBUG(5, ("create_directory returned %s\n", nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { -- cgit From 98c082489bec0a0ce4db1daf4390e785381f229a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Dec 2006 21:50:31 +0000 Subject: r20394: This is a *VERY* early start of my work on notify. Checking in because Jeremy was bugging me. Potentially this becomes quite intrusive, I'm not sure if I should open a temporary branch for this. Jeremy, Jerry, do you think 3_0 is the right place for this? Volker (This used to be commit bcf5c751cbe203c00814642e26440cf88f300bce) --- source3/smbd/files.c | 37 +++++++ source3/smbd/notify.c | 293 +++++++++++++++++++++++++++++++++++++++++++++++-- source3/smbd/nttrans.c | 7 +- source3/smbd/open.c | 16 ++- source3/smbd/reply.c | 23 +++- 5 files changed, 351 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 7069818dee..8df7a29a65 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -100,6 +100,12 @@ NTSTATUS file_new(connection_struct *conn, files_struct **result) ZERO_STRUCTP(fsp->fh); + if (!(fsp->notify = TALLOC_ZERO_P(NULL, struct notify_changes))) { + SAFE_FREE(fsp->fh); + SAFE_FREE(fsp); + return NT_STATUS_NO_MEMORY; + } + fsp->fh->ref_count = 1; fsp->fh->fd = -1; @@ -361,6 +367,35 @@ files_struct *file_find_di_next(files_struct *start_fsp) return NULL; } +/**************************************************************************** + Find the directory fsp given a device and inode with the lowest + file_id. First use is for notify actions. +****************************************************************************/ + +files_struct *file_find_dir_lowest_id(SMB_DEV_T dev, SMB_INO_T inode) +{ + files_struct *fsp; + files_struct *min_fsp = NULL; + + for (fsp = Files; fsp; fsp = fsp->next) { + if (!fsp->is_directory + || fsp->dev != dev || fsp->inode != inode) { + continue; + } + + if (min_fsp == NULL) { + min_fsp = fsp; + continue; + } + + if (fsp->fh->file_id < min_fsp->fh->file_id) { + min_fsp = fsp; + } + } + + return min_fsp; +} + /**************************************************************************** Find a fsp that is open for printing. ****************************************************************************/ @@ -439,6 +474,8 @@ void file_free(files_struct *fsp) fsp->fh->ref_count--; } + TALLOC_FREE(fsp->notify); + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 4ec53567dd..2a5d7fc552 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -35,22 +35,75 @@ struct change_notify { files_struct *fsp; connection_struct *conn; uint32 flags; + uint32 max_param_count; char request_buf[smb_size]; void *change_data; }; static struct change_notify *change_notify_list; +static BOOL notify_marshall_changes(struct notify_changes *changes, + prs_struct *ps) +{ + int i; + UNISTR uni_name; + + for (i=0; inum_changes; i++) { + struct notify_change *c = &changes->changes[i]; + size_t namelen; + uint32 u32_tmp; /* Temp arg to prs_uint32 to avoid + * signed/unsigned issues */ + + namelen = convert_string_allocate( + NULL, CH_UNIX, CH_UTF16LE, c->name, strlen(c->name)+1, + &uni_name.buffer, True); + if ((namelen == -1) || (uni_name.buffer == NULL)) { + goto fail; + } + + namelen -= 2; /* Dump NULL termination */ + + /* + * Offset to next entry, only if there is one + */ + + u32_tmp = (i == changes->num_changes-1) ? 0 : namelen + 12; + if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = c->action; + if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = namelen; + if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail; + + if (!prs_unistr("name", ps, 1, &uni_name)) goto fail; + + /* + * Not NULL terminated, decrease by the 2 UCS2 \0 chars + */ + prs_set_offset(ps, prs_offset(ps)-2); + + SAFE_FREE(uni_name.buffer); + } + + return True; + + fail: + SAFE_FREE(uni_name.buffer); + return False; +} + /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) +static void change_notify_reply_packet(struct change_notify *notify, + NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common(notify->request_buf, outbuf); ERROR_NT(error_code); @@ -65,6 +118,47 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } +static void change_notify_reply(struct change_notify *notify) +{ + char *outbuf = NULL; + prs_struct ps; + size_t buflen = smb_size+38+notify->max_param_count; + + if (!prs_init(&ps, 0, NULL, False) + || !notify_marshall_changes(notify->fsp->notify, &ps)) { + change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + goto done; + } + + if (prs_offset(&ps) > notify->max_param_count) { + /* + * We exceed what the client is willing to accept. Send + * nothing. + */ + change_notify_reply_packet(notify, NT_STATUS_OK); + goto done; + } + + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { + change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + goto done; + } + + memset(outbuf, '\0', sizeof(outbuf)); + construct_reply_common(notify->request_buf, outbuf); + + if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0) == -1) { + exit_server("change_notify_reply_packet: send_smb failed."); + } + + done: + SAFE_FREE(outbuf); + prs_mem_free(&ps); + notify->fsp->notify->num_changes = 0; + TALLOC_FREE(notify->fsp->notify->changes); +} + /**************************************************************************** Remove an entry from the list and free it, also closing any directory handle if necessary. @@ -89,7 +183,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS st for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp->request_buf,status); + change_notify_reply_packet(cnbp, status); change_notify_remove(cnbp); } } @@ -106,7 +200,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_reply_packet(cnbp, NT_STATUS_CANCELLED); change_notify_remove(cnbp); } } @@ -128,7 +222,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,status); + change_notify_reply_packet(cnbp, status); change_notify_remove(cnbp); } } @@ -171,9 +265,13 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); + if ((cnbp->fsp->notify->num_changes != 0) + || cnotify->check_notify(cnbp->conn, vuid, + cnbp->fsp->fsp_name, cnbp->flags, + cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir " + "%s changed !\n", cnbp->fsp->fsp_name )); + change_notify_reply(cnbp); change_notify_remove(cnbp); } } @@ -188,13 +286,14 @@ BOOL process_pending_change_notify_queue(time_t t) error. ****************************************************************************/ -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, + uint32 flags, uint32 max_param_count) { struct change_notify *cnbp; if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); - return -1; + return False; } ZERO_STRUCTP(cnbp); @@ -203,7 +302,9 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, cnbp->fsp = fsp; cnbp->conn = conn; cnbp->flags = flags; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); + cnbp->max_param_count = max_param_count; + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, + flags); if (!cnbp->change_data) { SAFE_FREE(cnbp); @@ -227,6 +328,174 @@ int change_notify_fd(void) return -1; } +/* notify message definition + +Offset Data length. +0 SMB_DEV_T dev 8 +8 SMB_INO_T inode 8 +16 uint32 action 4 +20.. name +*/ + +#define MSG_NOTIFY_MESSAGE_SIZE 21 /* Includes at least the '\0' terminator */ + +struct notify_message { + SMB_DEV_T dev; + SMB_INO_T inode; + uint32_t action; + char *name; +}; + +static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) +{ + DATA_BLOB result; + size_t len; + + len = strlen(msg->name); + + result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); + if (!result.data) { + return result; + } + + SDEV_T_VAL(result.data, 0, msg->dev); + SINO_T_VAL(result.data, 8, msg->inode); + SIVAL(result.data, 16, msg->action); + memcpy(result.data+20, msg->name, len+1); + + return result; +} + +static BOOL buf_to_notify_message(void *buf, size_t len, + struct notify_message *msg) +{ + if (len < MSG_NOTIFY_MESSAGE_SIZE) { + DEBUG(0, ("Got invalid notify message of len %d\n", len)); + return False; + } + + msg->dev = DEV_T_VAL(buf, 0); + msg->inode = INO_T_VAL(buf, 8); + msg->action = IVAL(buf, 16); + msg->name = ((char *)buf)+20; + return True; +} + +void notify_action(connection_struct *conn, const char *parent, + const char *name, uint32_t action) +{ + struct share_mode_lock *lck; + SMB_STRUCT_STAT sbuf; + int i; + struct notify_message msg; + DATA_BLOB blob; + + struct process_id *pids; + int num_pids; + + if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { + /* + * Not 100% critical, ignore failure + */ + return; + } + + if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, + NULL, NULL))) { + return; + } + + msg.dev = sbuf.st_dev; + msg.inode = sbuf.st_ino; + msg.action = action; + msg.name = CONST_DISCARD(char *, name); + + blob = notify_message_to_buf(&msg); + if (blob.data == NULL) { + DEBUG(0, ("notify_message_to_buf failed\n")); + return; + } + + pids = NULL; + num_pids = 0; + + become_root_uid_only(); + + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + int j; + struct process_id *tmp; + + for (j=0; jpid, &pids[j])) { + break; + } + } + + if (j < num_pids) { + /* + * Already sent to that process, skip it + */ + continue; + } + + message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, + blob.data, blob.length, True); + + if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, + num_pids+1))) { + DEBUG(0, ("realloc failed\n")); + break; + } + pids = tmp; + pids[num_pids] = e->pid; + num_pids += 1; + } + + unbecome_root_uid_only(); + + data_blob_free(&blob); + TALLOC_FREE(lck); +} + +static void notify_message(int msgtype, struct process_id pid, + void *buf, size_t len) +{ + struct notify_message msg; + files_struct *fsp; + struct notify_change *changes, *change; + + if (!buf_to_notify_message(buf, len, &msg)) { + return; + } + + DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", + (unsigned)msg.dev, (double)msg.inode, msg.action)); + + if (!(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { + DEBUG(10, ("notify_message: did not find fsp\n")); + return; + } + + if (!(changes = TALLOC_REALLOC_ARRAY( + fsp->notify, fsp->notify->changes, + struct notify_change, fsp->notify->num_changes+1))) { + DEBUG(0, ("talloc_realloc failed\n")); + return; + } + + fsp->notify->changes = changes; + + change = &(fsp->notify->changes[fsp->notify->num_changes]); + + if (!(change->name = talloc_strdup(changes, msg.name))) { + DEBUG(0, ("talloc_strdup failed\n")); + return; + } + change->action = msg.action; + fsp->notify->num_changes += 1; +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ @@ -250,5 +519,7 @@ BOOL init_change_notify(void) return False; } + message_register(MSG_SMB_NOTIFY, notify_message); + return True; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6359f931c0..976ecf4524 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -68,9 +68,8 @@ static char *nttrans_realloc(char **ptr, size_t size) HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, - char *params, int paramsize, char *pdata, - int datasize) +int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, + char *params, int paramsize, char *pdata, int datasize) { int data_to_send = datasize; int params_to_send = paramsize; @@ -1848,7 +1847,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfid); } - if (!change_notify_set(inbuf, fsp, conn, flags)) { + if (!change_notify_set(inbuf, fsp, conn, flags, max_param_count)) { return(UNIXERROR(ERRDOS,ERRbadfid)); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 28170e9cd8..040b0543aa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1127,7 +1127,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; - const char *parent_dir; + char *parent_dir; + const char *newname; if (conn->printer) { /* @@ -1144,8 +1145,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return print_fsp_open(conn, fname, result); } - if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), - parent_dirname(fname)))) { + if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir, + &newname)) { return NT_STATUS_NO_MEMORY; } @@ -1878,7 +1879,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, { int ret= -1; mode_t mode; - const char *parent_dir; + char *parent_dir; + const char *dirname; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -1890,8 +1892,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return map_nt_error_from_unix(errno); } - if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), - parent_dirname(name)))) { + if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir, + &dirname)) { return NT_STATUS_NO_MEMORY; } @@ -1936,6 +1938,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } + notify_action(conn, parent_dir, dirname, NOTIFY_ACTION_ADDED); + return NT_STATUS_OK; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f6d5211310..f10b649bf1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3860,7 +3860,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) The internals of the rmdir code - called elsewhere. ****************************************************************************/ -BOOL rmdir_internals(connection_struct *conn, char *directory) +BOOL rmdir_internals(connection_struct *conn, const char *directory) { BOOL ok; SMB_STRUCT_STAT st; @@ -3933,10 +3933,25 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) } } - if (!ok) - DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno))); + if (!ok) { + DEBUG(3,("rmdir_internals: couldn't remove directory %s : " + "%s\n", directory,strerror(errno))); + return False; + } + + { + char *parent_dir; + const char *dirname; + + if (parent_dirname_talloc(tmp_talloc_ctx(), directory, + &parent_dir, &dirname)) { + notify_action(conn, parent_dir, dirname, + NOTIFY_ACTION_REMOVED); + TALLOC_FREE(parent_dir); /* Not strictly necessary */ + } + } - return ok; + return True; } /**************************************************************************** -- cgit From 8e6390a1604da9e34f1f6823399687bf38cd7380 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 29 Dec 2006 20:39:53 +0000 Subject: r20411: Fix originally from SATOH Fumiyasu (slightly modified). Ensure "hide unXXX" parameters don't hide MSDFS links. Bug #3319. Jeremy. (This used to be commit e5466fffc286a99fafe0fcfbf70e903e33baa7f9) --- source3/smbd/dir.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 1c77630ee7..5a6b9713e5 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1011,6 +1011,18 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * if (asprintf(&entry, "%s/%s", dir_path, name) == -1) { return False; } + + /* If it's a dfs symlink, ignore _hide xxxx_ options */ + if (lp_host_msdfs() && + lp_msdfs_root(SNUM(conn)) && + /* We get away with NULL talloc ctx here as + we're not interested in the link contents + so we have nothing to free. */ + is_msdfs_link(NULL, conn, entry, NULL, NULL, NULL)) { + SAFE_FREE(entry); + return True; + } + /* Honour _hide unreadable_ option */ if (hide_unreadable && !user_can_read_file(conn, entry, pst)) { DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry )); -- cgit From a77b3f38b9b76b830997bb876d97cec4884f6774 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 30 Dec 2006 03:02:59 +0000 Subject: r20412: Placeholder to remind me to write a torture test for this error code. Jeremy. (This used to be commit 71b868611671a6c9275fce153794a0ccc150551f) --- source3/smbd/trans2.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1ebdf16b8a..14c7eb8fa8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4871,6 +4871,13 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, FILE_CREATE, 0, NULL, &fsp); if (!NT_STATUS_IS_OK(status)) { +#if 0 + /* Do we need to do this here ? Need smbtorture test. JRA. */ + if (!use_nt_status() && NT_STATUS_EQUAL( + status, NT_STATUS_OBJECT_NAME_COLLISION)) { + status = NT_STATUS_DOS(ERRDOS, ERRfilexists); + } +#endif return ERROR_NT(status); } close_file(fsp, NORMAL_CLOSE); -- cgit From 6d1607f4d71906121f3b0495a811ed99a3f8331e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 30 Dec 2006 17:54:22 +0000 Subject: r20424: No, we do not have to do that here :-) (This used to be commit 49a463a97a4f800977ed3a657714e7f3b17bbf21) --- source3/smbd/trans2.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 14c7eb8fa8..78630efd44 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4807,7 +4807,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, BOOL bad_path = False; NTSTATUS status = NT_STATUS_OK; struct ea_list *ea_list = NULL; - files_struct *fsp; if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); @@ -4865,22 +4864,11 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, ERRnoaccess); } - status = open_directory(conn, directory, &sbuf, - FILE_READ_ATTRIBUTES, /* A stat open */ - FILE_SHARE_NONE, /* Ignored */ - FILE_CREATE, 0, NULL, &fsp); + status = create_directory(conn, directory); if (!NT_STATUS_IS_OK(status)) { -#if 0 - /* Do we need to do this here ? Need smbtorture test. JRA. */ - if (!use_nt_status() && NT_STATUS_EQUAL( - status, NT_STATUS_OBJECT_NAME_COLLISION)) { - status = NT_STATUS_DOS(ERRDOS, ERRfilexists); - } -#endif return ERROR_NT(status); } - close_file(fsp, NORMAL_CLOSE); /* Try and set any given EA. */ if (ea_list) { -- cgit From ab7fc62edfb32422bf95dbf358f6ee5d94e27a34 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 10:08:52 +0000 Subject: r20432: Apply some const (This used to be commit 22163fee595251d4ea92279d88a1e8525188c620) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cf61e16a15..28c2cd65dd 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1112,7 +1112,7 @@ void remove_from_common_flags2(uint32 v) common_flags2 &= ~v; } -void construct_reply_common(char *inbuf,char *outbuf) +void construct_reply_common(const char *inbuf, char *outbuf) { set_message(outbuf,0,0,False); -- cgit From 165f5f3f40317c1e75d60a977270f903f7475f69 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 10:16:03 +0000 Subject: r20433: Work in progress: Survive more of RAW-NOTIFY. call_nt_transact_notify_change() is now sync if there are changes around. A notify_message does a direct reply from within the message, so process_pending_change_notify_queue is not needed anymore for samba-generated events. Next step is to restructure the kernel-mechanisms to generate messages. Volker (This used to be commit c813f71d0036ec52c99a97e60fe33ee47d0635fa) --- source3/smbd/notify.c | 98 +++++++++++++++++++++++++++++++++------------- source3/smbd/notify_hash.c | 3 ++ source3/smbd/nttrans.c | 11 ++++++ source3/smbd/open.c | 36 ++++++++++------- source3/smbd/reply.c | 21 +++++++++- 5 files changed, 126 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2a5d7fc552..674505ac5b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -33,7 +33,6 @@ static struct cnotify_fns *cnotify; struct change_notify { struct change_notify *next, *prev; files_struct *fsp; - connection_struct *conn; uint32 flags; uint32 max_param_count; char request_buf[smb_size]; @@ -97,13 +96,13 @@ static BOOL notify_marshall_changes(struct notify_changes *changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(struct change_notify *notify, +static void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(notify->request_buf, outbuf); + construct_reply_common(request_buf, outbuf); ERROR_NT(error_code); @@ -118,34 +117,34 @@ static void change_notify_reply_packet(struct change_notify *notify, exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } -static void change_notify_reply(struct change_notify *notify) +void change_notify_reply(const char *request_buf, uint32 max_param_count, + files_struct *fsp) { char *outbuf = NULL; prs_struct ps; - size_t buflen = smb_size+38+notify->max_param_count; + size_t buflen = smb_size+38+max_param_count; if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(notify->fsp->notify, &ps)) { - change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + || !notify_marshall_changes(fsp->notify, &ps)) { + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } - if (prs_offset(&ps) > notify->max_param_count) { + if (prs_offset(&ps) > max_param_count) { /* * We exceed what the client is willing to accept. Send * nothing. */ - change_notify_reply_packet(notify, NT_STATUS_OK); + change_notify_reply_packet(request_buf, NT_STATUS_OK); goto done; } if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { - change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } - memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(notify->request_buf, outbuf); + construct_reply_common(request_buf, outbuf); if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0) == -1) { @@ -155,8 +154,8 @@ static void change_notify_reply(struct change_notify *notify) done: SAFE_FREE(outbuf); prs_mem_free(&ps); - notify->fsp->notify->num_changes = 0; - TALLOC_FREE(notify->fsp->notify->changes); + fsp->notify->num_changes = 0; + TALLOC_FREE(fsp->notify->changes); } /**************************************************************************** @@ -183,7 +182,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS st for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp, status); + change_notify_reply_packet(cnbp->request_buf, status); change_notify_remove(cnbp); } } @@ -200,7 +199,8 @@ void remove_pending_change_notify_requests_by_mid(int mid) for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp, NT_STATUS_CANCELLED); + change_notify_reply_packet(cnbp->request_buf, + NT_STATUS_CANCELLED); change_notify_remove(cnbp); } } @@ -222,7 +222,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp, status); + change_notify_reply_packet(cnbp->request_buf, status); change_notify_remove(cnbp); } } @@ -265,13 +265,25 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if ((cnbp->fsp->notify->num_changes != 0) - || cnotify->check_notify(cnbp->conn, vuid, - cnbp->fsp->fsp_name, cnbp->flags, - cnbp->change_data, t)) { + if (cnbp->fsp->notify->num_changes != 0) { + DEBUG(10,("process_pending_change_notify_queue: %s " + "has %d changes!\n", cnbp->fsp->fsp_name, + cnbp->fsp->notify->num_changes)); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp); + change_notify_remove(cnbp); + continue; + } + + if (cnotify->check_notify(cnbp->fsp->conn, vuid, + cnbp->fsp->fsp_name, cnbp->flags, + cnbp->change_data, t)) { DEBUG(10,("process_pending_change_notify_queue: dir " "%s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply(cnbp); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp); change_notify_remove(cnbp); } } @@ -300,7 +312,6 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; - cnbp->conn = conn; cnbp->flags = flags; cnbp->max_param_count = max_param_count; cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, @@ -393,6 +404,9 @@ void notify_action(connection_struct *conn, const char *parent, struct process_id *pids; int num_pids; + DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", + parent, name, (unsigned)action)); + if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { /* * Not 100% critical, ignore failure @@ -458,12 +472,13 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } -static void notify_message(int msgtype, struct process_id pid, - void *buf, size_t len) +static void notify_message_callback(int msgtype, struct process_id pid, + void *buf, size_t len) { struct notify_message msg; files_struct *fsp; struct notify_change *changes, *change; + struct change_notify *cnbp; if (!buf_to_notify_message(buf, len, &msg)) { return; @@ -472,7 +487,24 @@ static void notify_message(int msgtype, struct process_id pid, DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", (unsigned)msg.dev, (double)msg.inode, msg.action)); - if (!(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { + fsp = NULL; + + for (cnbp = change_notify_list; cnbp != NULL; cnbp = cnbp->next) { + if ((cnbp->fsp->dev == msg.dev) + && (cnbp->fsp->inode == msg.inode)) { + break; + } + } + + if (cnbp != NULL) { + DEBUG(10, ("Found pending change notify for %s\n", + cnbp->fsp->fsp_name)); + fsp = cnbp->fsp; + SMB_ASSERT(fsp->notify->num_changes == 0); + } + + if ((fsp == NULL) + && !(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { DEBUG(10, ("notify_message: did not find fsp\n")); return; } @@ -494,6 +526,18 @@ static void notify_message(int msgtype, struct process_id pid, } change->action = msg.action; fsp->notify->num_changes += 1; + + if (cnbp != NULL) { + /* + * Respond directly, we have a someone waiting for this change + */ + DEBUG(10, ("Found pending cn for %s, responding directly\n", + cnbp->fsp->fsp_name)); + change_notify_reply(cnbp->request_buf, cnbp->max_param_count, + cnbp->fsp); + change_notify_remove(cnbp); + return; + } } /**************************************************************************** @@ -519,7 +563,7 @@ BOOL init_change_notify(void) return False; } - message_register(MSG_SMB_NOTIFY, notify_message); + message_register(MSG_SMB_NOTIFY, notify_message_callback); return True; } diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 0787a3eec5..5d211ada01 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -186,6 +186,9 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, struct change_data data2; int cnto = lp_change_notify_timeout(SNUM(conn)); + DEBUG(10, ("hash_change_notify called for path %s\n", path)); + return False; + if (t && cnto <= 0) { /* Change notify turned off on this share. * Only scan when (t==0) - we think something changed. */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 976ecf4524..f51d01fb9c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1847,6 +1847,17 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfid); } + if (fsp->notify->num_changes > 0) { + + change_notify_reply(inbuf, max_param_count, fsp); + + /* + * change_notify_reply() above has independently sent its + * results + */ + return -1; + } + if (!change_notify_set(inbuf, fsp, conn, flags, max_param_count)) { return(UNIXERROR(ERRDOS,ERRbadfid)); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 040b0543aa..895dd48221 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -198,7 +198,8 @@ static void change_dir_owner_to_parent(connection_struct *conn, static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, const char *parent_dir, - const char *fname, + const char *name, + const char *path, SMB_STRUCT_STAT *psbuf, int flags, mode_t unx_mode, @@ -227,7 +228,7 @@ static NTSTATUS open_file(files_struct *fsp, if (!CAN_WRITE(conn)) { /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { - DEBUG(3,("Permission denied opening %s\n",fname)); + DEBUG(3,("Permission denied opening %s\n", path)); return NT_STATUS_ACCESS_DENIED; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that @@ -253,7 +254,7 @@ static NTSTATUS open_file(files_struct *fsp, if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { DEBUG(10,("open_file: truncate requested on read-only open " - "for file %s\n",fname )); + "for file %s\n", path)); local_flags = (flags & ~O_ACCMODE)|O_RDWR; } @@ -282,15 +283,15 @@ static NTSTATUS open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && - ms_has_wild(fname)) { + ms_has_wild(path)) { return NT_STATUS_OBJECT_NAME_INVALID; } /* Actually do the open */ - if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) { + if (!fd_open(conn, path, fsp, local_flags, unx_mode)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", - fname,strerror(errno),local_flags,flags)); + path,strerror(errno),local_flags,flags)); return map_nt_error_from_unix(errno); } @@ -298,7 +299,7 @@ static NTSTATUS open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, parent_dir, fname, + inherit_access_acl(conn, parent_dir, path, unx_mode); } @@ -307,6 +308,9 @@ static NTSTATUS open_file(files_struct *fsp, change_file_owner_to_parent(conn, parent_dir, fsp); } + + notify_action(conn, parent_dir, name, + NOTIFY_ACTION_ADDED); } } else { @@ -317,13 +321,13 @@ static NTSTATUS open_file(files_struct *fsp, int ret; if (fsp->fh->fd == -1) { - ret = SMB_VFS_STAT(conn, fname, psbuf); + ret = SMB_VFS_STAT(conn, path, psbuf); } else { ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) { DEBUG(0,("Error doing fstat on open file %s " - "(%s)\n", fname,strerror(errno) )); + "(%s)\n", path,strerror(errno) )); } } @@ -365,12 +369,13 @@ static NTSTATUS open_file(files_struct *fsp, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; - if (conn->aio_write_behind_list && - is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { + if (conn->aio_write_behind_list + && is_in_path(path, conn->aio_write_behind_list, + conn->case_sensitive)) { fsp->aio_write_behind = True; } - string_set(&fsp->fsp_name,fname); + string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -1579,8 +1584,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2, - unx_mode, access_mask, open_access_mask); + fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf, + flags|flags2, unx_mode, access_mask, + open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1845,7 +1851,7 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0, + status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0, FILE_WRITE_DATA, FILE_WRITE_DATA); /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f10b649bf1..935e8033a5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1975,10 +1975,12 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b code. ****************************************************************************/ -NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild) +NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, + char *name, BOOL has_wild) { pstring directory; pstring mask; + pstring orig_name; char *p; int count=0; NTSTATUS error = NT_STATUS_OK; @@ -1989,6 +1991,11 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B *directory = *mask = 0; rc = unix_convert(name,conn,0,&bad_path,&sbuf); + + /* + * Feel my pain, this code needs rewriting *very* badly! -- vl + */ + pstrcpy(orig_name, name); p = strrchr_m(name,'/'); if (!p) { @@ -2089,6 +2096,18 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B error = map_nt_error_from_unix(errno); } + { + char *dir; + const char *fname; + + if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name, + &dir, &fname)) { + notify_action(conn, dir, fname, + NOTIFY_ACTION_REMOVED); + TALLOC_FREE(dir); /* not strictly necessary */ + } + } + return error; } -- cgit From 421ffdbb2439fbf44cb61e0d1549071b85a3507c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 10:17:40 +0000 Subject: r20434: Revert an accidential commit (This used to be commit fe122b07fa1712c15067ed385d4408206e9beef4) --- source3/smbd/notify_hash.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 5d211ada01..0787a3eec5 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -186,9 +186,6 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, struct change_data data2; int cnto = lp_change_notify_timeout(SNUM(conn)); - DEBUG(10, ("hash_change_notify called for path %s\n", path)); - return False; - if (t && cnto <= 0) { /* Change notify turned off on this share. * Only scan when (t==0) - we think something changed. */ -- cgit From 200bd10b32107b4ce8fc72cc2abbf5a247708ba6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 17:52:24 +0000 Subject: r20442: Slight rewrite of the change notify infrastructure. This now survives the first of the raw-notify subtests, the one-level test_notify_dir without any flags around yet. The tricky part was getting the data structures right, I hope the next tests don't let that fall over. fsp->notify is now by default NULL, meaning that nobody has issued a changenotify call. This means nobody is interested in changes for this directory. If that has happened, notify_change_buf collects the changes if no current request is outstanding, and it collects the requests if no change has happened since the last request. Happy New Year, somewhere on this planet it's already 2007 :-) Volker P.S: Jeremy, there's a question for you in smbd/files.c line 367. (This used to be commit ce0ad24988075465addcac0b9afc872e909135af) --- source3/smbd/close.c | 3 +- source3/smbd/files.c | 57 ++++++++------ source3/smbd/notify.c | 202 +++++++++++++++++++++++++++++++++---------------- source3/smbd/nttrans.c | 30 +++++++- source3/smbd/reply.c | 24 +++--- 5 files changed, 210 insertions(+), 106 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index a3ddcae11d..282c4acb24 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -416,7 +416,8 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) process_pending_change_notify_queue((time_t)0); } else { TALLOC_FREE(lck); - remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_CANCELLED); + remove_pending_change_notify_requests_by_fid( + fsp, NT_STATUS_OK); } /* diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 8df7a29a65..982de4c55f 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -100,12 +100,6 @@ NTSTATUS file_new(connection_struct *conn, files_struct **result) ZERO_STRUCTP(fsp->fh); - if (!(fsp->notify = TALLOC_ZERO_P(NULL, struct notify_changes))) { - SAFE_FREE(fsp->fh); - SAFE_FREE(fsp); - return NT_STATUS_NO_MEMORY; - } - fsp->fh->ref_count = 1; fsp->fh->fd = -1; @@ -367,33 +361,48 @@ files_struct *file_find_di_next(files_struct *start_fsp) return NULL; } -/**************************************************************************** - Find the directory fsp given a device and inode with the lowest - file_id. First use is for notify actions. -****************************************************************************/ +/* + * Same as file_find_di_first/next, but also finds non-fd opens. + * + * Jeremy, do we really need the fsp->fh->fd != -1 ?? + */ -files_struct *file_find_dir_lowest_id(SMB_DEV_T dev, SMB_INO_T inode) +struct files_struct *fsp_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) { files_struct *fsp; - files_struct *min_fsp = NULL; - for (fsp = Files; fsp; fsp = fsp->next) { - if (!fsp->is_directory - || fsp->dev != dev || fsp->inode != inode) { - continue; - } + if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { + /* Positive or negative cache hit. */ + return fsp_fi_cache.fsp; + } - if (min_fsp == NULL) { - min_fsp = fsp; - continue; - } + fsp_fi_cache.dev = dev; + fsp_fi_cache.inode = inode; - if (fsp->fh->file_id < min_fsp->fh->file_id) { - min_fsp = fsp; + for (fsp=Files;fsp;fsp=fsp->next) { + if ((fsp->dev == dev) && (fsp->inode == inode)) { + /* Setup positive cache. */ + fsp_fi_cache.fsp = fsp; + return fsp; } } - return min_fsp; + /* Setup negative cache. */ + fsp_fi_cache.fsp = NULL; + return NULL; +} + +struct files_struct *fsp_find_di_next(files_struct *start_fsp) +{ + files_struct *fsp; + + for (fsp = start_fsp->next;fsp;fsp=fsp->next) { + if ( (fsp->dev == start_fsp->dev) + && (fsp->inode == start_fsp->inode) ) + return fsp; + } + + return NULL; } /**************************************************************************** diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 674505ac5b..9957c1fc5d 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,7 @@ #include "includes.h" static struct cnotify_fns *cnotify; +static struct notify_mid_map *notify_changes_by_mid; /**************************************************************************** This is the structure to queue to implement NT change @@ -41,14 +42,15 @@ struct change_notify { static struct change_notify *change_notify_list; -static BOOL notify_marshall_changes(struct notify_changes *changes, +static BOOL notify_marshall_changes(unsigned num_changes, + struct notify_change *changes, prs_struct *ps) { int i; UNISTR uni_name; - for (i=0; inum_changes; i++) { - struct notify_change *c = &changes->changes[i]; + for (i=0; inum_changes-1) ? 0 : namelen + 12; + u32_tmp = (i == num_changes-1) ? 0 : namelen + 12; if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; u32_tmp = c->action; @@ -96,8 +98,7 @@ static BOOL notify_marshall_changes(struct notify_changes *changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(const char *request_buf, - NTSTATUS error_code) +void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { char outbuf[smb_size+38]; @@ -118,14 +119,14 @@ static void change_notify_reply_packet(const char *request_buf, } void change_notify_reply(const char *request_buf, uint32 max_param_count, - files_struct *fsp) + unsigned num_changes, struct notify_change *changes) { char *outbuf = NULL; prs_struct ps; size_t buflen = smb_size+38+max_param_count; if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(fsp->notify, &ps)) { + || !notify_marshall_changes(num_changes, changes, &ps)) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } @@ -154,8 +155,6 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, done: SAFE_FREE(outbuf); prs_mem_free(&ps); - fsp->notify->num_changes = 0; - TALLOC_FREE(fsp->notify->changes); } /**************************************************************************** @@ -171,39 +170,100 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } -/**************************************************************************** - Delete entries by fnum from the change notify pending queue. -*****************************************************************************/ +NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, + struct files_struct *fsp) +{ + struct notify_change_request *request = NULL; + struct notify_mid_map *map = NULL; + + if (!(request = SMB_MALLOC_P(struct notify_change_request)) + || !(map = SMB_MALLOC_P(struct notify_mid_map))) { + SAFE_FREE(request); + return NT_STATUS_NO_MEMORY; + } -void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) + request->mid_map = map; + map->req = request; + + memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); + request->max_param_count = max_param_count; + request->fsp = fsp; + DLIST_ADD_END(fsp->notify->requests, request, + struct notify_change_request *); + + map->mid = SVAL(inbuf, smb_mid); + DLIST_ADD(notify_changes_by_mid, map); + + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + + return NT_STATUS_OK; +} + +static void change_notify_remove_request(struct notify_change_request *remove_req) { - struct change_notify *cnbp, *next; + files_struct *fsp; + struct notify_change_request *req; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp->request_buf, status); - change_notify_remove(cnbp); + /* + * Paranoia checks, the fsp referenced must must have the request in + * its list of pending requests + */ + + fsp = remove_req->fsp; + SMB_ASSERT(fsp->notify != NULL); + + for (req = fsp->notify->requests; req; req = req->next) { + if (req == remove_req) { + break; } } + SMB_ASSERT(req != NULL); + + DLIST_REMOVE(fsp->notify->requests, req); + DLIST_REMOVE(notify_changes_by_mid, req->mid_map); + SAFE_FREE(req->mid_map); + SAFE_FREE(req); } /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_mid(int mid) +void remove_pending_change_notify_requests_by_mid(uint16 mid) { - struct change_notify *cnbp, *next; + struct notify_mid_map *map; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf, - NT_STATUS_CANCELLED); - change_notify_remove(cnbp); + for (map = notify_changes_by_mid; map; map = map->next) { + if (map->mid == mid) { + break; } } + + if (map == NULL) { + return; + } + + change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_remove_request(map->req); +} + +/**************************************************************************** + Delete entries by fnum from the change notify pending queue. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, + NTSTATUS status) +{ + if (fsp->notify == NULL) { + return; + } + + while (fsp->notify->requests != NULL) { + change_notify_reply_packet( + fsp->notify->requests->request_buf, status); + change_notify_remove_request(fsp->notify->requests); + } } /**************************************************************************** @@ -271,7 +331,8 @@ BOOL process_pending_change_notify_queue(time_t t) cnbp->fsp->notify->num_changes)); change_notify_reply(cnbp->request_buf, cnbp->max_param_count, - cnbp->fsp); + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); change_notify_remove(cnbp); continue; } @@ -283,7 +344,8 @@ BOOL process_pending_change_notify_queue(time_t t) "%s changed !\n", cnbp->fsp->fsp_name )); change_notify_reply(cnbp->request_buf, cnbp->max_param_count, - cnbp->fsp); + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); change_notify_remove(cnbp); } } @@ -472,43 +534,42 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } -static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len) +static void notify_fsp(files_struct *fsp, struct notify_message *msg) { - struct notify_message msg; - files_struct *fsp; - struct notify_change *changes, *change; - struct change_notify *cnbp; + struct notify_change *change, *changes; - if (!buf_to_notify_message(buf, len, &msg)) { + if (fsp->notify == NULL) { + /* + * Nobody is waiting, don't queue + */ return; } - DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", - (unsigned)msg.dev, (double)msg.inode, msg.action)); + if (fsp->notify->requests != NULL) { + /* + * Someone is waiting for the change, trigger the reply + * immediately + */ - fsp = NULL; + struct notify_change_request *req = fsp->notify->requests; + struct notify_change onechange; - for (cnbp = change_notify_list; cnbp != NULL; cnbp = cnbp->next) { - if ((cnbp->fsp->dev == msg.dev) - && (cnbp->fsp->inode == msg.inode)) { - break; - } - } + onechange.action = msg->action; + onechange.name = msg->name; - if (cnbp != NULL) { - DEBUG(10, ("Found pending change notify for %s\n", - cnbp->fsp->fsp_name)); - fsp = cnbp->fsp; - SMB_ASSERT(fsp->notify->num_changes == 0); - } + change_notify_reply(req->request_buf, req->max_param_count, + 1, &onechange); - if ((fsp == NULL) - && !(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { - DEBUG(10, ("notify_message: did not find fsp\n")); + DLIST_REMOVE(fsp->notify->requests, req); + SAFE_FREE(req); return; } + /* + * Someone has triggered a notify previously, queue the change for + * later. TODO: Limit the number of changes queued. + */ + if (!(changes = TALLOC_REALLOC_ARRAY( fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { @@ -520,24 +581,33 @@ static void notify_message_callback(int msgtype, struct process_id pid, change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, msg.name))) { + if (!(change->name = talloc_strdup(changes, msg->name))) { DEBUG(0, ("talloc_strdup failed\n")); return; } - change->action = msg.action; + change->action = msg->action; fsp->notify->num_changes += 1; - if (cnbp != NULL) { - /* - * Respond directly, we have a someone waiting for this change - */ - DEBUG(10, ("Found pending cn for %s, responding directly\n", - cnbp->fsp->fsp_name)); - change_notify_reply(cnbp->request_buf, cnbp->max_param_count, - cnbp->fsp); - change_notify_remove(cnbp); + return; +} + +static void notify_message_callback(int msgtype, struct process_id pid, + void *buf, size_t len) +{ + struct notify_message msg; + files_struct *fsp; + + if (!buf_to_notify_message(buf, len, &msg)) { return; } + + DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", + (unsigned)msg.dev, (double)msg.inode, msg.action)); + + for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; + fsp = fsp_find_di_next(fsp)) { + notify_fsp(fsp, &msg); + } } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f51d01fb9c..0ef962ca0f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1826,6 +1826,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, uint16 *setup = *ppsetup; files_struct *fsp; uint32 flags; + NTSTATUS status; if(setup_count < 6) { return ERROR_DOS(ERRDOS,ERRbadfunc); @@ -1847,9 +1848,27 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfid); } + if (fsp->notify == NULL) { + if (!(fsp->notify = TALLOC_ZERO_P( + NULL, struct notify_change_buf))) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + } + if (fsp->notify->num_changes > 0) { - change_notify_reply(inbuf, max_param_count, fsp); + /* + * We've got changes pending, respond immediately + */ + + SMB_ASSERT(fsp->notify->requests == NULL); + + change_notify_reply(inbuf, max_param_count, + fsp->notify->num_changes, + fsp->notify->changes); + + TALLOC_FREE(fsp->notify->changes); + fsp->notify->num_changes = 0; /* * change_notify_reply() above has independently sent its @@ -1858,8 +1877,13 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return -1; } - if (!change_notify_set(inbuf, fsp, conn, flags, max_param_count)) { - return(UNIXERROR(ERRDOS,ERRbadfid)); + /* + * No changes pending, queue the request + */ + + status = change_notify_add_request(inbuf, max_param_count, fsp); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } return -1; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 935e8033a5..c6b3c17c01 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2020,6 +2020,9 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { + char *dir; + const char *fname; + pstrcat(directory,"/"); pstrcat(directory,mask); error = can_delete(conn,directory,dirtype,bad_path,False); @@ -2029,6 +2032,14 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; } + + if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name, + &dir, &fname)) { + notify_action(conn, dir, fname, + NOTIFY_ACTION_REMOVED); + TALLOC_FREE(dir); /* not strictly necessary */ + } + } else { struct smb_Dir *dir_hnd = NULL; const char *dname; @@ -2086,6 +2097,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } if (SMB_VFS_UNLINK(conn,fname) == 0) count++; + notify_action(conn, directory, dname, NOTIFY_ACTION_REMOVED); DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dir_hnd); @@ -2096,18 +2108,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, error = map_nt_error_from_unix(errno); } - { - char *dir; - const char *fname; - - if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name, - &dir, &fname)) { - notify_action(conn, dir, fname, - NOTIFY_ACTION_REMOVED); - TALLOC_FREE(dir); /* not strictly necessary */ - } - } - return error; } -- cgit From dbc231a1c627ac8f83ce36c4139e3ac9b1477cf6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 18:10:47 +0000 Subject: r20443: Fix a compiler warning (This used to be commit 19781d71fc5a8146109395cd53c04cf13cc48652) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9957c1fc5d..49a516b907 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -443,7 +443,8 @@ static BOOL buf_to_notify_message(void *buf, size_t len, struct notify_message *msg) { if (len < MSG_NOTIFY_MESSAGE_SIZE) { - DEBUG(0, ("Got invalid notify message of len %d\n", len)); + DEBUG(0, ("Got invalid notify message of len %d\n", + (int)len)); return False; } -- cgit From 92d02f7afe439a51f5a2eab3e1db8d628c170a6c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Jan 2007 18:11:32 +0000 Subject: r20451: Survive the first of the filter-tests (mkdir). Add lots of TODOs :-) Volker (This used to be commit 0e953884a15873b0962ab1ab064d6b3a436726c0) --- source3/smbd/notify.c | 40 ++++++++++++++++++++++++---------------- source3/smbd/nttrans.c | 12 +++++++++--- source3/smbd/open.c | 5 +++-- source3/smbd/reply.c | 7 ++++--- 4 files changed, 40 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 49a516b907..f94ff76e7b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -171,7 +171,7 @@ static void change_notify_remove(struct change_notify *cnbp) } NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, - struct files_struct *fsp) + uint32 filter, struct files_struct *fsp) { struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; @@ -187,6 +187,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); request->max_param_count = max_param_count; + request->filter = filter; request->fsp = fsp; DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -406,16 +407,18 @@ int change_notify_fd(void) Offset Data length. 0 SMB_DEV_T dev 8 8 SMB_INO_T inode 8 -16 uint32 action 4 -20.. name +16 uint32 filter 4 +20 uint32 action 4 +24.. name */ -#define MSG_NOTIFY_MESSAGE_SIZE 21 /* Includes at least the '\0' terminator */ +#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ struct notify_message { SMB_DEV_T dev; SMB_INO_T inode; - uint32_t action; + uint32 filter; + uint32 action; char *name; }; @@ -433,8 +436,9 @@ static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) SDEV_T_VAL(result.data, 0, msg->dev); SINO_T_VAL(result.data, 8, msg->inode); - SIVAL(result.data, 16, msg->action); - memcpy(result.data+20, msg->name, len+1); + SIVAL(result.data, 16, msg->filter); + SIVAL(result.data, 20, msg->action); + memcpy(result.data+24, msg->name, len+1); return result; } @@ -450,13 +454,14 @@ static BOOL buf_to_notify_message(void *buf, size_t len, msg->dev = DEV_T_VAL(buf, 0); msg->inode = INO_T_VAL(buf, 8); - msg->action = IVAL(buf, 16); - msg->name = ((char *)buf)+20; + msg->filter = IVAL(buf, 16); + msg->action = IVAL(buf, 20); + msg->name = ((char *)buf)+24; return True; } void notify_action(connection_struct *conn, const char *parent, - const char *name, uint32_t action) + const char *name, uint32 filter, uint32_t action) { struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; @@ -484,6 +489,7 @@ void notify_action(connection_struct *conn, const char *parent, msg.dev = sbuf.st_dev; msg.inode = sbuf.st_ino; + msg.filter = filter; msg.action = action; msg.name = CONST_DISCARD(char *, name); @@ -546,10 +552,13 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) return; } - if (fsp->notify->requests != NULL) { + if ((fsp->notify->requests != NULL) + && (fsp->notify->requests->filter & msg->filter)) { /* * Someone is waiting for the change, trigger the reply - * immediately + * immediately. + * + * TODO: do we have to walk the lists of requests pending? */ struct notify_change_request *req = fsp->notify->requests; @@ -560,15 +569,14 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) change_notify_reply(req->request_buf, req->max_param_count, 1, &onechange); - - DLIST_REMOVE(fsp->notify->requests, req); - SAFE_FREE(req); + change_notify_remove_request(req); return; } /* * Someone has triggered a notify previously, queue the change for - * later. TODO: Limit the number of changes queued. + * later. TODO: Limit the number of changes queued, test how filters + * apply here. Do we have to store them? */ if (!(changes = TALLOC_REALLOC_ARRAY( diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0ef962ca0f..9061c75d33 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1825,7 +1825,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, { uint16 *setup = *ppsetup; files_struct *fsp; - uint32 flags; + uint32 filter; NTSTATUS status; if(setup_count < 6) { @@ -1833,7 +1833,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, } fsp = file_fsp((char *)setup,4); - flags = IVAL(setup, 0); + filter = IVAL(setup, 0); DEBUG(3,("call_nt_transact_notify_change\n")); @@ -1861,6 +1861,11 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * We've got changes pending, respond immediately */ + /* + * TODO: write a torture test to check the filtering behaviour + * here. + */ + SMB_ASSERT(fsp->notify->requests == NULL); change_notify_reply(inbuf, max_param_count, @@ -1881,7 +1886,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * No changes pending, queue the request */ - status = change_notify_add_request(inbuf, max_param_count, fsp); + status = change_notify_add_request(inbuf, max_param_count, filter, + fsp); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 895dd48221..81537e0be3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,7 +309,7 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } - notify_action(conn, parent_dir, name, + notify_action(conn, parent_dir, name, -1, NOTIFY_ACTION_ADDED); } @@ -1944,7 +1944,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } - notify_action(conn, parent_dir, dirname, NOTIFY_ACTION_ADDED); + notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, + NOTIFY_ACTION_ADDED); return NT_STATUS_OK; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c6b3c17c01..ee930f20fb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2035,7 +2035,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name, &dir, &fname)) { - notify_action(conn, dir, fname, + notify_action(conn, dir, fname, -1, NOTIFY_ACTION_REMOVED); TALLOC_FREE(dir); /* not strictly necessary */ } @@ -2097,7 +2097,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } if (SMB_VFS_UNLINK(conn,fname) == 0) count++; - notify_action(conn, directory, dname, NOTIFY_ACTION_REMOVED); + notify_action(conn, directory, dname, + -1, NOTIFY_ACTION_REMOVED); DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dir_hnd); @@ -3964,7 +3965,7 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) if (parent_dirname_talloc(tmp_talloc_ctx(), directory, &parent_dir, &dirname)) { - notify_action(conn, parent_dir, dirname, + notify_action(conn, parent_dir, dirname, -1, NOTIFY_ACTION_REMOVED); TALLOC_FREE(parent_dir); /* Not strictly necessary */ } -- cgit From 495c3619071abc618bc1de06e44b2f994c8c4903 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Jan 2007 21:37:02 +0000 Subject: r20454: Get rid of a bogus variable that was only assigned but never read. Jeremy, please check this. Thanks, Volker (This used to be commit 2becbb9e5f7d1b04962178e6f0c97c3ccf2b0f88) --- source3/smbd/reply.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ee930f20fb..e29ecab8ba 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3316,10 +3316,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Close ordinary file. */ int close_err; - pstring file_name; - - /* Save the name for time set in close. */ - pstrcpy( file_name, fsp->fsp_name); DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", fsp->fh->fd, fsp->fnum, -- cgit From 3c4342ddfbe95cfbc64902177d4955882f71a4a0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 2 Jan 2007 11:16:27 +0000 Subject: r20465: Get rid of a redundant !NT_STATUS_IS_OK(status) (This used to be commit ff173995cfeac216ab26faef6553be8f7f439347) --- source3/smbd/nttrans.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9061c75d33..5c96669987 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -656,8 +656,8 @@ int reply_ntcreate_and_X(connection_struct *conn, status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the only error we care about for "can we delete this ?" questions. */ - if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || - NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) { + if (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || + NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_ACCESS_DENIED); @@ -1284,8 +1284,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the only error we care about for "can we delete this ?" questions. */ - if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || - NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) { + if (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || + NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE)) { restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } -- cgit From 2c1b3a072061d40f112c3f1112fd9ae08b6038e4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 2 Jan 2007 12:10:46 +0000 Subject: r20470: Jeremy, another one to check: The only error path of can_delete() that we're interested in ntcreate&x is the one of can_delete_file_in_directory(), so call that directly. The only other one where we might get a NT_STATUS_ACCESS_DENIED is from the lstat in can_delete, but this is covered later in the open_directory and open_file_ntcreate calls. open_directory does a stat() in the open case which also covers the (potential) symlink, and open_file_ntcreate does the open(2) itself, so this should also work. This makes can_delete() static to reply.c. Volker (This used to be commit d289037fdbc8bd3e0723784888946d5b39ffadef) --- source3/smbd/nttrans.c | 39 +++++++++++++++++---------------------- source3/smbd/reply.c | 4 +++- 2 files changed, 20 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5c96669987..faa3e25bae 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -647,21 +647,18 @@ int reply_ntcreate_and_X(connection_struct *conn, expensive (it may have to read the parent directory permissions). So for now we're not doing it unless we have a strong hint the client is really going to delete this file. */ - if (desired_access & DELETE_ACCESS) { + if ((desired_access & DELETE_ACCESS) + && !can_delete_file_in_directory(conn, fname)) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) + && (share_access & FILE_SHARE_DELETE) + && (access_mask & DELETE_ACCESS) + && !can_delete_file_in_directory(conn, fname)) { #endif - status = can_delete(conn, fname, file_attributes, bad_path, True); - /* We're only going to fail here if it's access denied, as that's the - only error we care about for "can we delete this ?" questions. */ - if (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || - NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE)) { - restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); } /* @@ -1276,19 +1273,17 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o expensive (it may have to read the parent directory permissions). So for now we're not doing it unless we have a strong hint the client is really going to delete this file. */ - if (desired_access & DELETE_ACCESS) { + if ((desired_access & DELETE_ACCESS) + && !can_delete_file_in_directory(conn, fname)) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) + && (share_access & FILE_SHARE_DELETE) + && (access_mask & DELETE_ACCESS) + && !can_delete_file_in_directory(conn, fname)) { #endif - status = can_delete(conn, fname, file_attributes, bad_path, True); - /* We're only going to fail here if it's access denied, as that's the - only error we care about for "can we delete this ?" questions. */ - if (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || - NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE)) { - restore_case_semantics(conn, file_attributes); - return ERROR_NT(status); - } + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); } if (ea_len) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e29ecab8ba..607c12f8b1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1888,7 +1888,9 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, Check if a user is allowed to delete a file. ********************************************************************/ -NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open) +static NTSTATUS can_delete(connection_struct *conn, char *fname, + uint32 dirtype, BOOL bad_path, + BOOL check_is_at_open) { SMB_STRUCT_STAT sbuf; uint32 fattr; -- cgit From 58b63b65fcf3dbd14f985f99038733c8a0a2f14f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 2 Jan 2007 15:01:43 +0000 Subject: r20478: Make us survive & activate RAW-UNLINK (This used to be commit 4f0f917b344743e16e8bacf4e72529a2890590fe) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 607c12f8b1..cb25b69a31 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2074,7 +2074,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, /* Quick check for "." and ".." */ if (fname[0] == '.') { if (!fname[1] || (fname[1] == '.' && !fname[2])) { - if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) { + if (dirtype & FILE_ATTRIBUTE_DIRECTORY) { sys_direntry = True; } else { continue; -- cgit From 6edd999dc1fe4894b2fb9f02fb4c215adf3aa795 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 2 Jan 2007 15:07:27 +0000 Subject: r20479: Both remaining calls of can_delete called it with check_is_at_open==False, remove that parameter. Volker (This used to be commit e51b7648703f3a85b840501dd4199600a5a7e44f) --- source3/smbd/reply.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cb25b69a31..a65979e804 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1889,8 +1889,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, ********************************************************************/ static NTSTATUS can_delete(connection_struct *conn, char *fname, - uint32 dirtype, BOOL bad_path, - BOOL check_is_at_open) + uint32 dirtype, BOOL bad_path) { SMB_STRUCT_STAT sbuf; uint32 fattr; @@ -1938,7 +1937,7 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, from Windows Explorer). */ - if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) { + if (!lp_delete_readonly(SNUM(conn))) { if (fattr & aRONLY) { return NT_STATUS_CANNOT_DELETE; } @@ -1947,29 +1946,22 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, return NT_STATUS_NO_SUCH_FILE; } - if (check_is_at_open) { - if (!can_delete_file_in_directory(conn, fname)) { - return NT_STATUS_ACCESS_DENIED; - } - } else { - /* On open checks the open itself will check the share mode, so - don't do it here as we'll get it wrong. */ - - status = open_file_ntcreate(conn, fname, &sbuf, - DELETE_ACCESS, - FILE_SHARE_NONE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - 0, - NULL, &fsp); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } + /* On open checks the open itself will check the share mode, so + don't do it here as we'll get it wrong. */ + + status = open_file_ntcreate(conn, fname, &sbuf, + DELETE_ACCESS, + FILE_SHARE_NONE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + 0, + NULL, &fsp); + + if (NT_STATUS_IS_OK(status)) { close_file(fsp,NORMAL_CLOSE); } - return NT_STATUS_OK; + return status; } /**************************************************************************** @@ -2027,7 +2019,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, pstrcat(directory,"/"); pstrcat(directory,mask); - error = can_delete(conn,directory,dirtype,bad_path,False); + error = can_delete(conn,directory,dirtype,bad_path); if (!NT_STATUS_IS_OK(error)) return error; @@ -2093,7 +2085,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - error = can_delete(conn,fname,dirtype,bad_path,False); + error = can_delete(conn, fname, dirtype, + bad_path); if (!NT_STATUS_IS_OK(error)) { continue; } -- cgit From b3ddd92ba2dfbf732b3e6e22812bca780713ed8f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 2 Jan 2007 16:40:41 +0000 Subject: r20482: Make us survive and activate RAW-CLOSE (This used to be commit 471c6e6a2142afbca36163bcdbb5b6fb4e7ac774) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a65979e804..6bda8fb7ee 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3629,7 +3629,7 @@ int reply_printclose(connection_struct *conn, if (!CAN_PRINT(conn)) { END_PROFILE(SMBsplclose); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror)); } DEBUG(3,("printclose fd=%d fnum=%d\n", -- cgit From 9985f25f0031cb1c91fd99cddf6f80bdf66b4dad Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 3 Jan 2007 06:19:11 +0000 Subject: r20496: Some changes to make Samba3 the RAW-OPEN test. Checking in to both 3_0 and 3_0_24 because I was explicitly asked to, although this needs close review. Jeremy, I'm sure you will check this thoroughly :-) In reply_open_and_X the separate "size" variable kills the calculation of the SPARSE flag returned to the client in the attrib field. In getpathinfo we do it correctly, and RAW-OPEN (correctly) complains about the difference. Add the "set the write time" to mknew and create. For trans2open we were missing the "ofun == 0" -> NT_STATUS_OBJECT_NAME_COLLISION case, and we dropped the status returned in favor of ACCESS_DENIED once too many. Last change is a fix to trans2open: We were returning the attributes given by the client, not the attributes of the new file. Volker (This used to be commit 84e6889632c7f98a7cb37036b0acdf538d50d16c) --- source3/smbd/reply.c | 13 ++++++++----- source3/smbd/trans2.c | 8 ++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6bda8fb7ee..9184a1a696 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1475,7 +1475,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); #endif int smb_ofun = SVAL(inbuf,smb_vwv8); - SMB_OFF_T size=0; uint32 fattr=0; int mtime=0; SMB_STRUCT_STAT sbuf; @@ -1545,8 +1544,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_NT(status); } - size = sbuf.st_size; - /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size, if the file is truncated or created. */ if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) { @@ -1562,7 +1559,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt END_PROFILE(SMBopenX); return ERROR_NT(NT_STATUS_DISK_FULL); } - size = get_allocation_size(conn,fsp,&sbuf); + sbuf.st_size = get_allocation_size(conn,fsp,&sbuf); } fattr = dos_mode(conn,fname,&sbuf); @@ -1611,7 +1608,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } else { srv_put_dos_date3(outbuf,smb_vwv4,mtime); } - SIVAL(outbuf,smb_vwv6,(uint32)size); + SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode)); SSVAL(outbuf,smb_vwv11,smb_action); @@ -1662,6 +1659,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int com; int outsize = 0; uint32 fattr = SVAL(inbuf,smb_vwv0); + struct utimbuf times; BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); @@ -1676,6 +1674,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); + times.modtime = srv_make_unix_date3(inbuf + smb_vwv1); + srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); @@ -1721,6 +1721,9 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } + times.actime = sbuf.st_atime; + file_utime(conn, fname, ×); + outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 78630efd44..33596f19da 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -810,6 +810,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } + if (open_ofun == 0) { + return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION); + } + if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun, &access_mask, &share_mode, @@ -857,7 +861,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } size = get_file_size(sbuf); @@ -909,7 +913,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i params = *pparams; SSVAL(params,0,fsp->fnum); - SSVAL(params,2,open_attr); + SSVAL(params,2,fattr); srv_put_dos_date2(params,4, mtime); SIVAL(params,8, (uint32)size); SSVAL(params,12,deny_mode); -- cgit From bc20aac121edae8812e3c3392d2cd41dfdf258ec Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 3 Jan 2007 12:01:17 +0000 Subject: r20507: smbcli_setattr("") always returns ACCESS_DENIED, test extension to follow. Merge to 3.0.24? Volker (This used to be commit f2563ac98f8ec7af8083d2b62186753acba7a9dd) --- source3/smbd/reply.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9184a1a696..63f8d0bb61 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1004,6 +1004,15 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } + if (strequal(fname, ".")) { + /* + * Not sure here is the right place to catch this + * condition. Might be moved to somewhere else later -- vl + */ + END_PROFILE(SMBsetatr); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + mode = SVAL(inbuf,smb_vwv0); mtime = srv_make_unix_date3(inbuf+smb_vwv1); -- cgit From 3a9133dd0670391f7673c468e845dfae41064312 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 4 Jan 2007 15:12:22 +0000 Subject: r20524: Simplify logic of close_remove_share_mode(). Volker (This used to be commit ade90dbf0c2cbd2cc49a6357f3dd220ea82fd215) --- source3/smbd/close.c | 118 +++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 282c4acb24..bc2d6c3507 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -149,6 +149,7 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close connection_struct *conn = fsp->conn; BOOL delete_file = False; struct share_mode_lock *lck; + SMB_STRUCT_STAT sbuf; /* * Lock the share entries, and determine if we should delete @@ -159,12 +160,14 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { - DEBUG(0, ("close_remove_share_mode: Could not get share mode lock for file %s\n", fsp->fsp_name)); + DEBUG(0, ("close_remove_share_mode: Could not get share mode " + "lock for file %s\n", fsp->fsp_name)); return EINVAL; } if (!del_share_mode(lck, fsp)) { - DEBUG(0, ("close_remove_share_mode: Could not delete share entry for file %s\n", fsp->fsp_name)); + DEBUG(0, ("close_remove_share_mode: Could not delete share " + "entry for file %s\n", fsp->fsp_name)); } delete_file = (lck->delete_on_close | lck->initial_delete_on_close); @@ -190,63 +193,76 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close * reference to a file. */ - if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && - delete_file && - lck->delete_token) { - SMB_STRUCT_STAT sbuf; + if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) + || !delete_file + || (lck->delete_token == NULL)) { + TALLOC_FREE(lck); + return 0; + } - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set - deleting file.\n", - fsp->fsp_name)); + /* + * Ok, we have to delete the file + */ - /* Become the user who requested the delete. */ + DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " + "- deleting file.\n", fsp->fsp_name)); - if (!push_sec_ctx()) { - smb_panic("close_remove_share_mode: file %s. failed to push sec_ctx.\n"); - } + /* Become the user who requested the delete. */ - set_sec_ctx(lck->delete_token->uid, - lck->delete_token->gid, - lck->delete_token->ngroups, - lck->delete_token->groups, - NULL); + if (!push_sec_ctx()) { + smb_panic("close_remove_share_mode: file %s. failed to push " + "sec_ctx.\n"); + } - /* We can only delete the file if the name we have - is still valid and hasn't been renamed. */ - - if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " - "and stat failed with error %s\n", - fsp->fsp_name, strerror(errno) )); - } else { - if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set and " - "dev and/or inode does not match\n", - fsp->fsp_name )); - DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, inode = %.0f " - "stat dev = %x, inode = %.0f\n", - fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); - - } else if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { - /* - * This call can potentially fail as another smbd may have - * had the file open with delete on close set and deleted - * it when its last reference to this file went away. Hence - * we log this but not at debug level zero. - */ - - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " - "and unlink failed with error %s\n", - fsp->fsp_name, strerror(errno) )); - } - } - /* unbecome user. */ - pop_sec_ctx(); + set_sec_ctx(lck->delete_token->uid, + lck->delete_token->gid, + lck->delete_token->ngroups, + lck->delete_token->groups, + NULL); + + /* We can only delete the file if the name we have is still valid and + hasn't been renamed. */ - process_pending_change_notify_queue((time_t)0); + if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { + DEBUG(5,("close_remove_share_mode: file %s. Delete on close " + "was set and stat failed with error %s\n", + fsp->fsp_name, strerror(errno) )); + goto done; + } + + if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { + DEBUG(5,("close_remove_share_mode: file %s. Delete on close " + "was set and dev and/or inode does not match\n", + fsp->fsp_name )); + DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, " + "inode = %.0f stat dev = %x, inode = %.0f\n", + fsp->fsp_name, + (unsigned int)fsp->dev, (double)fsp->inode, + (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); + goto done; + } + + if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { + /* + * This call can potentially fail as another smbd may + * have had the file open with delete on close set and + * deleted it when its last reference to this file + * went away. Hence we log this but not at debug level + * zero. + */ + + DEBUG(5,("close_remove_share_mode: file %s. Delete on close " + "was set and unlink failed with error %s\n", + fsp->fsp_name, strerror(errno) )); + goto done; } + done: + /* unbecome user. */ + pop_sec_ctx(); + + process_pending_change_notify_queue((time_t)0); + TALLOC_FREE(lck); return 0; } -- cgit From 2276cd666ff149f22b56971fb3015b903f5b3165 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 4 Jan 2007 16:26:15 +0000 Subject: r20525: Closing a dir with del-on-close set requires the same as files: Don't actually unlink/rmdir if another process still has it open. Jeremy, this is a potential merger to 3.0.24. Volker (This used to be commit 8e1e896b02da99b5a48883c5f37fe146ad0fb5ce) --- source3/smbd/close.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index bc2d6c3507..7e91208313 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -392,6 +392,18 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) delete_dir = (lck->delete_on_close | lck->initial_delete_on_close); + if (delete_dir) { + int i; + /* See if others still have the dir open. If this is the + * case, then don't delete */ + for (i=0; inum_share_modes; i++) { + if (is_valid_share_mode_entry(&lck->share_modes[i])) { + delete_dir = False; + break; + } + } + } + if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && delete_dir && lck->delete_token) { -- cgit From 2b1760297f3c61aa5f71fc548c51dae8de3cc885 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 4 Jan 2007 22:01:36 +0000 Subject: r20532: From Volker... "smbcli_setattr("") always returns ACCESS_DENIED, test extension to follow. Merge to 3.0.24?" Yep (with slight optimization). Jeremy. (This used to be commit dcc7bca1adbc69f348d46291ec2cbfaf5d8486bc) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 63f8d0bb61..3ebab18434 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1004,7 +1004,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - if (strequal(fname, ".")) { + if (fname[0] == '.' && fname[1] == '\0') { /* * Not sure here is the right place to catch this * condition. Might be moved to somewhere else later -- vl -- cgit From f933a9abc2ea9d2dc417b9ba500bbe730be3c1aa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Jan 2007 11:18:59 +0000 Subject: r20541: Fix some obvious glitches in wait_for_aio_completion. Hmmm. It seems reply_close() at its heart is going to be an async call :-) Volker (This used to be commit 36f60407ae9b430dc5d7f67dd3e7ed8b1dbc93a8) --- source3/smbd/aio.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index ad25242060..0abc20ab7d 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -580,14 +580,13 @@ int process_aio_queue(void) #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 -BOOL wait_for_aio_completion(files_struct *fsp) +int wait_for_aio_completion(files_struct *fsp) { struct aio_extra *aio_ex; const SMB_STRUCT_AIOCB **aiocb_list; int aio_completion_count = 0; time_t start_time = time(NULL); int seconds_left; - int ret = 0; for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; seconds_left >= 0;) { int err = 0; @@ -602,7 +601,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) } if (!aio_completion_count) { - return ret; + return 0; } DEBUG(3,("wait_for_aio_completion: waiting for %d aio events to complete.\n", @@ -610,7 +609,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, aio_completion_count); if (!aiocb_list) { - return False; + return ENOMEM; } for( i = 0, aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { @@ -637,7 +636,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) /* Timeout. */ cancel_aio_by_fsp(fsp); SAFE_FREE(aiocb_list); - return ret ? ret : EIO; + return EIO; } /* One or more events might have completed - process them if so. */ @@ -666,7 +665,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting for %d events\n", aio_completion_count)); - return ret ? ret : EIO; + return EIO; } /**************************************************************************** -- cgit From 84da72860e3912cfd8be45919360c0931b8bbbda Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Jan 2007 11:31:28 +0000 Subject: r20542: Make close_remove_share_mode retun NTSTATUS. Not that anybody cares yet... (This used to be commit c8995771531caa4ec9bcaef2c29b11ee7d8e49e6) --- source3/smbd/close.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 7e91208313..fe5e5eccf2 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -144,12 +144,14 @@ static void notify_deferred_opens(struct share_mode_lock *lck) Deal with removing a share mode on last close. ****************************************************************************/ -static int close_remove_share_mode(files_struct *fsp, enum file_close_type close_type) +static NTSTATUS close_remove_share_mode(files_struct *fsp, + enum file_close_type close_type) { connection_struct *conn = fsp->conn; BOOL delete_file = False; struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; + NTSTATUS status = NT_STATUS_OK; /* * Lock the share entries, and determine if we should delete @@ -162,7 +164,7 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close if (lck == NULL) { DEBUG(0, ("close_remove_share_mode: Could not get share mode " "lock for file %s\n", fsp->fsp_name)); - return EINVAL; + return NT_STATUS_INVALID_PARAMETER; } if (!del_share_mode(lck, fsp)) { @@ -197,7 +199,7 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close || !delete_file || (lck->delete_token == NULL)) { TALLOC_FREE(lck); - return 0; + return NT_STATUS_OK; } /* @@ -227,6 +229,9 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and stat failed with error %s\n", fsp->fsp_name, strerror(errno) )); + /* + * Don't save the errno here, we ignore this error + */ goto done; } @@ -239,6 +244,9 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); + /* + * Don't save the errno here, we ignore this error + */ goto done; } @@ -254,9 +262,13 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and unlink failed with error %s\n", fsp->fsp_name, strerror(errno) )); + + status = map_nt_error_from_unix(errno); goto done; } + status = NT_STATUS_FILE_DELETED; + done: /* unbecome user. */ pop_sec_ctx(); @@ -264,7 +276,7 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close process_pending_change_notify_queue((time_t)0); TALLOC_FREE(lck); - return 0; + return status; } /**************************************************************************** -- cgit From 1307337aaf050fa51758b5b844986eddc06693b7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Jan 2007 13:13:15 +0000 Subject: r20544: Change copy_file() to return NTSTATUS. This is in preparation of turning close_file() to NTSTATUS as well. I'm not sure I got all the error codes right, but as I've never come across a smb_copy() call in all my Samba work, I'm leaving it at that. If I'm absolutely bored, I will write a thorough torture test. As far as I can see, Samba4 even does not have a libcli implementation for it... :-) Volker (This used to be commit 5ebdf02ba166df69e210e6f70c01a44e6205ecc1) --- source3/smbd/reply.c | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3ebab18434..b99cb54840 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4698,8 +4698,12 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Copy a file as part of a reply_copy. ******************************************************************/ -BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, - int count,BOOL target_is_directory, int *err_ret) +/* + * TODO: check error codes on all callers + */ + +NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun, + int count, BOOL target_is_directory) { SMB_STRUCT_STAT src_sbuf, sbuf2; SMB_OFF_T ret=-1; @@ -4708,9 +4712,8 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, uint32 dosattrs; uint32 new_create_disposition; NTSTATUS status; + int close_err; - *err_ret = 0; - pstrcpy(dest,dest1); if (target_is_directory) { char *p = strrchr_m(src,'/'); @@ -4724,7 +4727,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if (!vfs_file_exist(conn,src,&src_sbuf)) { - return(False); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } if (!target_is_directory && count) { @@ -4732,7 +4735,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } else { if (!map_open_params_to_ntcreate(dest1,0,ofun, NULL, NULL, &new_create_disposition, NULL)) { - return(False); + return NT_STATUS_INVALID_PARAMETER; } } @@ -4746,7 +4749,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, NULL, &fsp1); if (!NT_STATUS_IS_OK(status)) { - return(False); + return status; } dosattrs = dos_mode(conn, src, &src_sbuf); @@ -4765,7 +4768,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!NT_STATUS_IS_OK(status)) { close_file(fsp1,ERROR_CLOSE); - return(False); + return status; } if ((ofun&3) == 1) { @@ -4794,9 +4797,17 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, * Thus we don't look at the error return from the * close of fsp1. */ - *err_ret = close_file(fsp2,NORMAL_CLOSE); + close_err = close_file(fsp2,NORMAL_CLOSE); - return(ret == (SMB_OFF_T)src_sbuf.st_size); + if (close_err != 0) { + return map_nt_error_from_unix(close_err); + } + + if (ret != (SMB_OFF_T)src_sbuf.st_size) { + return NT_STATUS_DISK_FULL; + } + + return NT_STATUS_OK; } /**************************************************************************** @@ -4903,13 +4914,14 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (resolve_wildcards(directory,newname) && - copy_file(directory,newname,conn,ofun, count,target_is_directory,&err)) + if (resolve_wildcards(directory,newname) + && NT_STATUS_IS_OK(status = copy_file( + directory,newname,conn,ofun, + count,target_is_directory))) count++; - if(!count && err) { - errno = err; + if(!count && !NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); - return(UNIXERROR(ERRHRD,ERRgeneral)); + return ERROR_NT(status); } if (!count) { exists = vfs_file_exist(conn,directory,NULL); @@ -4942,9 +4954,10 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); pstrcpy(destname,newname); - if (resolve_wildcards(fname,destname) && - copy_file(fname,destname,conn,ofun, - count,target_is_directory,&err)) + if (resolve_wildcards(fname,destname) + && NT_STATUS_IS_OK(status = copy_file( + fname,destname,conn,ofun, + count,target_is_directory))) count++; DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); } -- cgit From 0a8e3fd23632f0c77c4e165cf6070cb1fbcca381 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Jan 2007 17:42:54 +0000 Subject: r20558: Refactor rmdir_internals to use early termination rather than lots of indented code. Change recursive_rmdir() to return the smbd standards of True on success, False on fail (it was doing the reverse, which was very confusing). Jeremy. (This used to be commit 27dc5bebda7ffbdcb2371638f6132063a953fba2) --- source3/smbd/reply.c | 111 ++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b99cb54840..793262f0af 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3822,18 +3822,18 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /**************************************************************************** Static function used by reply_rmdir to delete an entire directory - tree recursively. Return False on ok, True on fail. + tree recursively. Return True on ok, False on fail. ****************************************************************************/ static BOOL recursive_rmdir(connection_struct *conn, char *directory) { const char *dname = NULL; - BOOL ret = False; + BOOL ret = True; long offset = 0; struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); if(dir_hnd == NULL) - return True; + return False; while((dname = ReadDirName(dir_hnd, &offset))) { pstring fullname; @@ -3848,7 +3848,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) /* Construct the full name. */ if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { errno = ENOMEM; - ret = True; + ret = False; break; } @@ -3857,21 +3857,21 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, dname); if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) { - ret = True; + ret = False; break; } if(st.st_mode & S_IFDIR) { - if(recursive_rmdir(conn, fullname)!=0) { - ret = True; + if(!recursive_rmdir(conn, fullname)) { + ret = False; break; } if(SMB_VFS_RMDIR(conn,fullname) != 0) { - ret = True; + ret = False; break; } } else if(SMB_VFS_UNLINK(conn,fullname) != 0) { - ret = True; + ret = False; break; } } @@ -3896,66 +3896,67 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) * retry. If we fail to delete any of them (and we *don't* * do a recursive delete) then fail the rmdir. */ - BOOL all_veto_files = True; const char *dname; + long dirpos = 0; struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); - if(dir_hnd != NULL) { - long dirpos = 0; - while ((dname = ReadDirName(dir_hnd,&dirpos))) { - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - if (!is_visible_file(conn, directory, dname, &st, False)) - continue; - if(!IS_VETO_PATH(conn, dname)) { - all_veto_files = False; - break; - } + if(dir_hnd == NULL) { + errno = ENOTEMPTY; + goto err; + } + + while ((dname = ReadDirName(dir_hnd,&dirpos))) { + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + if (!is_visible_file(conn, directory, dname, &st, False)) + continue; + if(!IS_VETO_PATH(conn, dname)) { + CloseDir(dir_hnd); + errno = ENOTEMPTY; + goto err; } + } - if(all_veto_files) { - RewindDir(dir_hnd,&dirpos); - while ((dname = ReadDirName(dir_hnd,&dirpos))) { - pstring fullname; + /* We only have veto files/directories. Recursive delete. */ - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - if (!is_visible_file(conn, directory, dname, &st, False)) - continue; + RewindDir(dir_hnd,&dirpos); + while ((dname = ReadDirName(dir_hnd,&dirpos))) { + pstring fullname; - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { - errno = ENOMEM; - break; - } + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + continue; + if (!is_visible_file(conn, directory, dname, &st, False)) + continue; - pstrcpy(fullname, directory); - pstrcat(fullname, "/"); - pstrcat(fullname, dname); + /* Construct the full name. */ + if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { + errno = ENOMEM; + break; + } + + pstrcpy(fullname, directory); + pstrcat(fullname, "/"); + pstrcat(fullname, dname); - if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) - break; - if(st.st_mode & S_IFDIR) { - if(lp_recursive_veto_delete(SNUM(conn))) { - if(recursive_rmdir(conn, fullname) != 0) - break; - } - if(SMB_VFS_RMDIR(conn,fullname) != 0) - break; - } else if(SMB_VFS_UNLINK(conn,fullname) != 0) + if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) + break; + if(st.st_mode & S_IFDIR) { + if(lp_recursive_veto_delete(SNUM(conn))) { + if(!recursive_rmdir(conn, fullname)) break; } - CloseDir(dir_hnd); - /* Retry the rmdir */ - ok = (SMB_VFS_RMDIR(conn,directory) == 0); - } else { - CloseDir(dir_hnd); - } - } else { - errno = ENOTEMPTY; + if(SMB_VFS_RMDIR(conn,fullname) != 0) + break; + } else if(SMB_VFS_UNLINK(conn,fullname) != 0) + break; } + CloseDir(dir_hnd); + /* Retry the rmdir */ + ok = (SMB_VFS_RMDIR(conn,directory) == 0); } + err: + if (!ok) { DEBUG(3,("rmdir_internals: couldn't remove directory %s : " "%s\n", directory,strerror(errno))); -- cgit From bb357a1617761177475a422008a14a1ac0435eb1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 6 Jan 2007 18:59:02 +0000 Subject: r20589: Re-add lost bad_path handling, sorry. (This used to be commit 244f96388c843fd629478d0069f68550a2006d06) --- source3/smbd/reply.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 793262f0af..d33940aa64 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3790,6 +3790,10 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); + if (bad_path) { + END_PROFILE(SMBmkdir); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } status = create_directory(conn, directory); -- cgit From b2efff8fe5cdfd031a7b6f814993a9c234a66ee8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 7 Jan 2007 18:08:50 +0000 Subject: r20597: Survive some of the notify mask tests. (This used to be commit e4a2e63272dc5b20413597179d06b0185c4a6817) --- source3/smbd/dosmode.c | 10 +++++++++- source3/smbd/notify.c | 14 ++++++++++++++ source3/smbd/reply.c | 10 +--------- 3 files changed, 24 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 1172fe3e6b..a3c46b3275 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -499,8 +499,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname, unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) + if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) { + notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, + NOTIFY_ACTION_MODIFIED); return 0; + } if((errno != EPERM) && (errno != EACCES)) return -1; @@ -529,6 +532,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); + notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, + NOTIFY_ACTION_MODIFIED); } return( ret ); @@ -601,6 +606,9 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); return False; } + + notify_fname(conn, fname, FILE_NOTIFY_CHANGE_LAST_WRITE, + NOTIFY_ACTION_MODIFIED); return(True); } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index f94ff76e7b..bcd8fcb0ab 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -541,6 +541,20 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } +void notify_fname(connection_struct *conn, const char *path, + uint32 filter, uint32 action) +{ + char *parent; + const char *name; + + if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { + return; + } + + notify_action(conn, parent, name, filter, action); + TALLOC_FREE(parent); +} + static void notify_fsp(files_struct *fsp, struct notify_message *msg) { struct notify_change *change, *changes; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d33940aa64..62fd0ea686 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2026,9 +2026,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { - char *dir; - const char *fname; - pstrcat(directory,"/"); pstrcat(directory,mask); error = can_delete(conn,directory,dirtype,bad_path); @@ -2039,12 +2036,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, count++; } - if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name, - &dir, &fname)) { - notify_action(conn, dir, fname, -1, - NOTIFY_ACTION_REMOVED); - TALLOC_FREE(dir); /* not strictly necessary */ - } + notify_fname(conn, orig_name, -1, NOTIFY_ACTION_REMOVED); } else { struct smb_Dir *dir_hnd = NULL; -- cgit From c79be5713ab5e01e4291b3b66e593c133f8fa9d7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 08:00:53 +0000 Subject: r20602: Fix coverity ID 339. SMB_ASSERT does not panic without -DDEVELOPER. Volker (This used to be commit 33b5950bec407e295b2c6139e21d062e376df330) --- source3/smbd/notify.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index bcd8fcb0ab..6bedb17261 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -219,7 +219,10 @@ static void change_notify_remove_request(struct notify_change_request *remove_re break; } } - SMB_ASSERT(req != NULL); + + if (req == NULL) { + smb_panic("notify_req not found in fsp's requests\n"); + } DLIST_REMOVE(fsp->notify->requests, req); DLIST_REMOVE(notify_changes_by_mid, req->mid_map); -- cgit From ccc54da805983e6ba267a2ec1f50a68e4a9acfec Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 13:05:36 +0000 Subject: r20605: Simplify logic in reply_setatr slightly (This used to be commit f19db8f33ed3749f6b72ae3a4cee83574c606e88) --- source3/smbd/reply.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 62fd0ea686..646cc79522 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -999,7 +999,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { + if (bad_path || !check_name(fname, conn)) { END_PROFILE(SMBsetatr); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } @@ -1022,9 +1022,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size else mode &= ~aDIR; - if (check_name(fname,conn)) { - ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0); - } + ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0); } else { ok = True; } -- cgit From 21cc3895458100158f329786a89bc2a77fe1e8ce Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 13:18:23 +0000 Subject: r20606: bad_path == True has been covered further up in reply_setatr. I'm checking in micro-steps to make them independently checkable. This code just very severely needs cleanup, but I don't want to break anything. So, be patient with me, please :-) Volker (This used to be commit c16775486baa89901f0d5126cb926c9e5a807743) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 646cc79522..66bbce064f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1032,7 +1032,8 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!ok) { END_PROFILE(SMBsetatr); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return set_bad_path_error(errno, False, outbuf, + ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,0,0,False); -- cgit From 72ecfaf32c2f6db114cff37dd1526a85722935fd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 13:21:43 +0000 Subject: r20607: Next micro-step for reply_setatr (This used to be commit cea9a01434490fb8a17c3f12db7a092efda21186) --- source3/smbd/reply.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 66bbce064f..e00d8d99a5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -979,7 +979,6 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size { pstring fname; int outsize = 0; - BOOL ok=False; int mode; time_t mtime; SMB_STRUCT_STAT sbuf; @@ -1022,15 +1021,14 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size else mode &= ~aDIR; - ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0); - } else { - ok = True; + if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) { + END_PROFILE(SMBsetatr); + return set_bad_path_error(errno, False, outbuf, + ERRDOS, ERRnoaccess); + } } - if (ok) - ok = set_filetime(conn,fname,mtime); - - if (!ok) { + if (!set_filetime(conn,fname,mtime)) { END_PROFILE(SMBsetatr); return set_bad_path_error(errno, False, outbuf, ERRDOS, ERRnoaccess); -- cgit From 90149315ea6ad6d165051e51c23f1eb1af8a88e7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 14:08:34 +0000 Subject: r20608: ENOENT->NT_STATUS_OBJECT_NAME_NOT_FOUND is covered in the standard unix error mapping table (This used to be commit 816c19aaeb812a94fd5669174c9beec60ce1a73f) --- source3/smbd/trans2.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 33596f19da..e85d3c0c5b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2711,12 +2711,8 @@ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n", err, (int)bad_path )); - if(err == ENOENT) { - if (bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } else { - return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); - } + if ((err == ENOENT) && bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } return UNIXERROR(def_class,def_code); } -- cgit From 283c690e6efd9b51d63786fac089d7230a3d16ca Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 15:26:17 +0000 Subject: r20611: All but one callers to set_bad_path_error have had the bad_path==True argument being handled further up. Volker (This used to be commit 358673c36697a16aa87f9cebbace34abf16ed28e) --- source3/smbd/nttrans.c | 5 +++-- source3/smbd/reply.c | 6 ++++-- source3/smbd/trans2.c | 33 ++++++++++++++++++++++----------- 3 files changed, 29 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index faa3e25bae..da24e4084d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -639,7 +639,8 @@ int reply_ntcreate_and_X(connection_struct *conn, if (!check_name(fname,conn)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } #if 0 @@ -1265,7 +1266,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* All file access must go through check_name() */ if (!check_name(fname,conn)) { restore_case_semantics(conn, file_attributes); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, ERRDOS,ERRbadpath); } #if 0 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e00d8d99a5..63a1889390 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -948,7 +948,8 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!ok) { END_PROFILE(SMBgetatr); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadfile); } outsize = set_message(outbuf,10,0,True); @@ -4006,7 +4007,8 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!ok) { END_PROFILE(SMBrmdir); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS, ERRbadpath); } outsize = set_message(outbuf,0,0,False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e85d3c0c5b..7d25b09e1f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -807,7 +807,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } if (!check_name(fname,conn)) { - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return set_bad_path_error(errno, False, outbuf, + ERRDOS, ERRnoaccess); } if (open_ofun == 0) { @@ -1725,7 +1726,8 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } if(!check_name(directory,conn)) { - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } p = strrchr_m(directory,'/'); @@ -2906,11 +2908,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error( + errno, False, outbuf, + ERRDOS,ERRbadpath); } } else if (SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); @@ -2954,18 +2959,21 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * } if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); @@ -3811,7 +3819,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pstrcpy(fname, fsp->fsp_name); if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } } else if (fsp && fsp->print_file) { /* @@ -3863,11 +3872,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } if(!check_name(fname, conn)) { - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); + return set_bad_path_error(errno, False, outbuf, + ERRDOS,ERRbadpath); } } @@ -4860,7 +4871,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, if (!check_name(directory,conn)) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, + return set_bad_path_error(errno, False, outbuf, ERRDOS, ERRnoaccess); } -- cgit From d10af0222623c3c76b19fe872adb6de1eeac6e1c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 15:36:33 +0000 Subject: r20612: A checkin I've wanted to do for ages: For bad_path==False set_bad_path_error is equivalent to UNIX_ERROR. Expand the last reference. Lets see if I can kill that as well :-) Volker (This used to be commit 794d5d38f19601bb5b30b965b41b844aacf1caeb) --- source3/smbd/nttrans.c | 5 ++--- source3/smbd/reply.c | 17 ++++++++--------- source3/smbd/trans2.c | 49 +++++++++++-------------------------------------- 3 files changed, 21 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index da24e4084d..f62f5881b3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -639,8 +639,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if (!check_name(fname,conn)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } #if 0 @@ -1266,7 +1265,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* All file access must go through check_name() */ if (!check_name(fname,conn)) { restore_case_semantics(conn, file_attributes); - return set_bad_path_error(errno, False, outbuf, ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } #if 0 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 63a1889390..ac0663d238 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -948,8 +948,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!ok) { END_PROFILE(SMBgetatr); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadfile); + return UNIXERROR(ERRDOS, ERRbadfile); } outsize = set_message(outbuf,10,0,True); @@ -1024,15 +1023,13 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) { END_PROFILE(SMBsetatr); - return set_bad_path_error(errno, False, outbuf, - ERRDOS, ERRnoaccess); + return UNIXERROR(ERRDOS, ERRnoaccess); } } if (!set_filetime(conn,fname,mtime)) { END_PROFILE(SMBsetatr); - return set_bad_path_error(errno, False, outbuf, - ERRDOS, ERRnoaccess); + return UNIXERROR(ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,0,0,False); @@ -1212,7 +1209,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (dptr_num < 0) { if(dptr_num == -2) { END_PROFILE(SMBsearch); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids); + if ((errno == ENOENT) && bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } + return UNIXERROR(ERRDOS, ERRnofids); } END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); @@ -4007,8 +4007,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!ok) { END_PROFILE(SMBrmdir); - return set_bad_path_error(errno, False, outbuf, - ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } outsize = set_message(outbuf,0,0,False); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7d25b09e1f..40394c3d8a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -807,8 +807,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } if (!check_name(fname,conn)) { - return set_bad_path_error(errno, False, outbuf, - ERRDOS, ERRnoaccess); + return UNIXERROR(ERRDOS, ERRnoaccess); } if (open_ofun == 0) { @@ -1726,8 +1725,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } if(!check_name(directory,conn)) { - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } p = strrchr_m(directory,'/'); @@ -2704,21 +2702,6 @@ cap_low = 0x%x, cap_high = 0x%x\n", return outsize; } -/**************************************************************************** - Utility function to set bad path error. -****************************************************************************/ - -int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code) -{ - DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n", - err, (int)bad_path )); - - if ((err == ENOENT) && bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } - return UNIXERROR(def_class,def_code); -} - #if defined(HAVE_POSIX_ACLS) /**************************************************************************** Utility function to count the number of entries in a POSIX acl. @@ -2908,14 +2891,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error( - errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } } else if (SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); @@ -2959,21 +2939,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * } if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); @@ -3819,8 +3796,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pstrcpy(fname, fsp->fsp_name); if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } } else if (fsp && fsp->print_file) { /* @@ -3872,13 +3848,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } if(!check_name(fname, conn)) { - return set_bad_path_error(errno, False, outbuf, - ERRDOS,ERRbadpath); + return UNIXERROR(ERRDOS, ERRbadpath); } } @@ -4871,8 +4845,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, if (!check_name(directory,conn)) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - return set_bad_path_error(errno, False, outbuf, ERRDOS, - ERRnoaccess); + return UNIXERROR(ERRDOS, ERRnoaccess); } status = create_directory(conn, directory); -- cgit From a9e3624bbcb240104af186233ba2de87586d77d3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 20:06:36 +0000 Subject: r20617: Do not notify if the delete failed (This used to be commit c86fbdf8cc8f6f17b23e647bd1f4714c6095b860) --- source3/smbd/reply.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ac0663d238..cc181223f2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2032,10 +2032,10 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; + notify_fname(conn, orig_name, -1, + NOTIFY_ACTION_REMOVED); } - notify_fname(conn, orig_name, -1, NOTIFY_ACTION_REMOVED); - } else { struct smb_Dir *dir_hnd = NULL; const char *dname; @@ -2092,10 +2092,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (!NT_STATUS_IS_OK(error)) { continue; } - if (SMB_VFS_UNLINK(conn,fname) == 0) + if (SMB_VFS_UNLINK(conn,fname) == 0) { count++; - notify_action(conn, directory, dname, - -1, NOTIFY_ACTION_REMOVED); + notify_action( + conn, directory, dname, + -1, NOTIFY_ACTION_REMOVED); + } DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dir_hnd); -- cgit From 1b50bcc9c8af2a7b2a085078e2df62c4ff648d79 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 21:08:31 +0000 Subject: r20618: Fix a bug in bad_path handling that also exists in 3.0.23: For reply_unlink under Linux we returned NT_STATUS_NOT_A_DIRECTORY. This is because in the bad_path==True condition lstat(2) returns ENOTDIR and not ENOENT. Not sure if we want to necessarily replicate the INVALID_PARAMETER here, but this is what W2k3 does. Jeremy, I tried to call you, but you were not around. So I'll leave it up to you to merge this. Volker (This used to be commit b1edc3d053104204b966eed67d070ad5da40f17b) --- source3/smbd/reply.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cc181223f2..b3ee18befe 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1995,6 +1995,11 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, *directory = *mask = 0; rc = unix_convert(name,conn,0,&bad_path,&sbuf); + if (bad_path) { + return has_wild + ? NT_STATUS_INVALID_PARAMETER + : NT_STATUS_OBJECT_PATH_NOT_FOUND; + } /* * Feel my pain, this code needs rewriting *very* badly! -- vl -- cgit From dbac39f74ebd6a906b6c2b83e6f0a406788f5620 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 21:13:27 +0000 Subject: r20619: bad_path is handled somewhere else, so can_delete does not need it anymore (This used to be commit 1798987128be579a1a4574294a7c3094040ebaf2) --- source3/smbd/reply.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b3ee18befe..dfea8bcc0f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1899,7 +1899,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, ********************************************************************/ static NTSTATUS can_delete(connection_struct *conn, char *fname, - uint32 dirtype, BOOL bad_path) + uint32 dirtype) { SMB_STRUCT_STAT sbuf; uint32 fattr; @@ -1913,13 +1913,6 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, } if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) { - if(errno == ENOENT) { - if (bad_path) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } else { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - } return map_nt_error_from_unix(errno); } @@ -2031,7 +2024,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - error = can_delete(conn,directory,dirtype,bad_path); + error = can_delete(conn,directory,dirtype); if (!NT_STATUS_IS_OK(error)) return error; @@ -2092,8 +2085,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - error = can_delete(conn, fname, dirtype, - bad_path); + error = can_delete(conn, fname, dirtype); if (!NT_STATUS_IS_OK(error)) { continue; } -- cgit From b5cad2c2a75ee614ec765d8bfb5b1ad9df984f57 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Jan 2007 08:56:24 +0000 Subject: r20627: orig_name is not needed anymore, and slightly simplify logic by doing early returns. Volker (This used to be commit 614651c6a72742173de5fa8723403880acc37c09) --- source3/smbd/reply.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dfea8bcc0f..d50a6e5224 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1977,7 +1977,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, { pstring directory; pstring mask; - pstring orig_name; char *p; int count=0; NTSTATUS error = NT_STATUS_OK; @@ -1994,11 +1993,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, : NT_STATUS_OBJECT_PATH_NOT_FOUND; } - /* - * Feel my pain, this code needs rewriting *very* badly! -- vl - */ - pstrcpy(orig_name, name); - p = strrchr_m(name,'/'); if (!p) { pstrcpy(directory,"."); @@ -2030,7 +2024,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; - notify_fname(conn, orig_name, -1, + notify_fname(conn, directory, -1, NOTIFY_ACTION_REMOVED); } @@ -2041,8 +2035,13 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory, mask, dirtype); + if (!check_name(directory,conn)) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + if (!(dir_hnd = OpenDir(conn, directory, mask, dirtype))) { + return NT_STATUS_NO_SUCH_FILE; + } /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name -- cgit From 45e7b954cdf7eb2efc970f01fee452e98aed00ee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Jan 2007 09:03:33 +0000 Subject: r20628: Looks bigger than it is. This is just re-indenting the if (dirname) that we've taken care of above. Volker (This used to be commit 5e1da363bb3f2675beb9fd9240301bb432e5239b) --- source3/smbd/reply.c | 78 +++++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d50a6e5224..e0f074a7ca 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2031,6 +2031,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } else { struct smb_Dir *dir_hnd = NULL; const char *dname; + long offset = 0; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); @@ -2048,56 +2049,53 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, We don't implement this yet XXXX */ - if (dir_hnd) { - long offset = 0; - error = NT_STATUS_NO_SUCH_FILE; + error = NT_STATUS_NO_SUCH_FILE; - while ((dname = ReadDirName(dir_hnd, &offset))) { - SMB_STRUCT_STAT st; - pstring fname; - BOOL sys_direntry = False; - pstrcpy(fname,dname); + while ((dname = ReadDirName(dir_hnd, &offset))) { + SMB_STRUCT_STAT st; + pstring fname; + BOOL sys_direntry = False; + pstrcpy(fname,dname); - if (!is_visible_file(conn, directory, dname, &st, True)) { - continue; - } + if (!is_visible_file(conn, directory, dname, &st, True)) { + continue; + } - /* Quick check for "." and ".." */ - if (fname[0] == '.') { - if (!fname[1] || (fname[1] == '.' && !fname[2])) { - if (dirtype & FILE_ATTRIBUTE_DIRECTORY) { - sys_direntry = True; - } else { - continue; - } + /* Quick check for "." and ".." */ + if (fname[0] == '.') { + if (!fname[1] || (fname[1] == '.' && !fname[2])) { + if (dirtype & FILE_ATTRIBUTE_DIRECTORY) { + sys_direntry = True; + } else { + continue; } } + } - if(!mask_match(fname, mask, conn->case_sensitive)) - continue; + if(!mask_match(fname, mask, conn->case_sensitive)) + continue; - if (sys_direntry) { - error = NT_STATUS_OBJECT_NAME_INVALID; - DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n", - fname, mask)); - break; - } + if (sys_direntry) { + error = NT_STATUS_OBJECT_NAME_INVALID; + DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n", + fname, mask)); + break; + } - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - error = can_delete(conn, fname, dirtype); - if (!NT_STATUS_IS_OK(error)) { - continue; - } - if (SMB_VFS_UNLINK(conn,fname) == 0) { - count++; - notify_action( - conn, directory, dname, - -1, NOTIFY_ACTION_REMOVED); - } - DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + error = can_delete(conn, fname, dirtype); + if (!NT_STATUS_IS_OK(error)) { + continue; } - CloseDir(dir_hnd); + if (SMB_VFS_UNLINK(conn,fname) == 0) { + count++; + notify_action( + conn, directory, dname, + -1, NOTIFY_ACTION_REMOVED); + } + DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } + CloseDir(dir_hnd); } if (count == 0 && NT_STATUS_IS_OK(error)) { -- cgit From 87bd4d2723e806ac0bc751ccf36fcdb8ed01c03c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Jan 2007 15:50:40 +0000 Subject: r20632: The extended RAW-SAMBA3BADPATH test led me to some wrong assumptions, in particular the NT_STATUS_INVALID_PARAMETER thing was badly wrong. Remove the changes based on it. Using gentest is much more effective in this respect, but it will take a while to figure out the wildcard error handling of W2k3. Volker (This used to be commit 58b8a242a7f08c1292d24fc73df170dbcd68c10d) --- source3/smbd/reply.c | 112 +++++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e0f074a7ca..cc181223f2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1899,7 +1899,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, ********************************************************************/ static NTSTATUS can_delete(connection_struct *conn, char *fname, - uint32 dirtype) + uint32 dirtype, BOOL bad_path) { SMB_STRUCT_STAT sbuf; uint32 fattr; @@ -1913,6 +1913,13 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, } if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) { + if(errno == ENOENT) { + if (bad_path) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + } return map_nt_error_from_unix(errno); } @@ -1977,6 +1984,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, { pstring directory; pstring mask; + pstring orig_name; char *p; int count=0; NTSTATUS error = NT_STATUS_OK; @@ -1987,12 +1995,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, *directory = *mask = 0; rc = unix_convert(name,conn,0,&bad_path,&sbuf); - if (bad_path) { - return has_wild - ? NT_STATUS_INVALID_PARAMETER - : NT_STATUS_OBJECT_PATH_NOT_FOUND; - } + /* + * Feel my pain, this code needs rewriting *very* badly! -- vl + */ + pstrcpy(orig_name, name); + p = strrchr_m(name,'/'); if (!p) { pstrcpy(directory,"."); @@ -2018,84 +2026,82 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - error = can_delete(conn,directory,dirtype); + error = can_delete(conn,directory,dirtype,bad_path); if (!NT_STATUS_IS_OK(error)) return error; if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; - notify_fname(conn, directory, -1, + notify_fname(conn, orig_name, -1, NOTIFY_ACTION_REMOVED); } } else { struct smb_Dir *dir_hnd = NULL; const char *dname; - long offset = 0; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - if (!check_name(directory,conn)) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - if (!(dir_hnd = OpenDir(conn, directory, mask, dirtype))) { - return NT_STATUS_NO_SUCH_FILE; - } + if (check_name(directory,conn)) + dir_hnd = OpenDir(conn, directory, mask, dirtype); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name We don't implement this yet XXXX */ - error = NT_STATUS_NO_SUCH_FILE; + if (dir_hnd) { + long offset = 0; + error = NT_STATUS_NO_SUCH_FILE; - while ((dname = ReadDirName(dir_hnd, &offset))) { - SMB_STRUCT_STAT st; - pstring fname; - BOOL sys_direntry = False; - pstrcpy(fname,dname); + while ((dname = ReadDirName(dir_hnd, &offset))) { + SMB_STRUCT_STAT st; + pstring fname; + BOOL sys_direntry = False; + pstrcpy(fname,dname); - if (!is_visible_file(conn, directory, dname, &st, True)) { - continue; - } + if (!is_visible_file(conn, directory, dname, &st, True)) { + continue; + } - /* Quick check for "." and ".." */ - if (fname[0] == '.') { - if (!fname[1] || (fname[1] == '.' && !fname[2])) { - if (dirtype & FILE_ATTRIBUTE_DIRECTORY) { - sys_direntry = True; - } else { - continue; + /* Quick check for "." and ".." */ + if (fname[0] == '.') { + if (!fname[1] || (fname[1] == '.' && !fname[2])) { + if (dirtype & FILE_ATTRIBUTE_DIRECTORY) { + sys_direntry = True; + } else { + continue; + } } } - } - if(!mask_match(fname, mask, conn->case_sensitive)) - continue; + if(!mask_match(fname, mask, conn->case_sensitive)) + continue; - if (sys_direntry) { - error = NT_STATUS_OBJECT_NAME_INVALID; - DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n", - fname, mask)); - break; - } + if (sys_direntry) { + error = NT_STATUS_OBJECT_NAME_INVALID; + DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n", + fname, mask)); + break; + } - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - error = can_delete(conn, fname, dirtype); - if (!NT_STATUS_IS_OK(error)) { - continue; - } - if (SMB_VFS_UNLINK(conn,fname) == 0) { - count++; - notify_action( - conn, directory, dname, - -1, NOTIFY_ACTION_REMOVED); + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + error = can_delete(conn, fname, dirtype, + bad_path); + if (!NT_STATUS_IS_OK(error)) { + continue; + } + if (SMB_VFS_UNLINK(conn,fname) == 0) { + count++; + notify_action( + conn, directory, dname, + -1, NOTIFY_ACTION_REMOVED); + } + DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } - DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); + CloseDir(dir_hnd); } - CloseDir(dir_hnd); } if (count == 0 && NT_STATUS_IS_OK(error)) { -- cgit From 46fdae1b6b1b8e3285447193cb10e5a2a444d431 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Jan 2007 16:12:54 +0000 Subject: r20634: A *LOT* more work is necessary before touching notify remotely starts to make sense. Until then, remove it from the tree to keep the diff between 3_0_24 and 3_0 small. Volker (This used to be commit f146a85e74c84e78a11e616a1cbeaeef4693a0e0) --- source3/smbd/dosmode.c | 10 +- source3/smbd/files.c | 46 ----- source3/smbd/notify.c | 467 +++---------------------------------------------- source3/smbd/nttrans.c | 53 +----- source3/smbd/open.c | 5 - source3/smbd/reply.c | 17 -- 6 files changed, 35 insertions(+), 563 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index a3c46b3275..1172fe3e6b 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -499,11 +499,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) { - notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, - NOTIFY_ACTION_MODIFIED); + if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) return 0; - } if((errno != EPERM) && (errno != EACCES)) return -1; @@ -532,8 +529,6 @@ int file_set_dosmode(connection_struct *conn, const char *fname, ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); - notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, - NOTIFY_ACTION_MODIFIED); } return( ret ); @@ -606,9 +601,6 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); return False; } - - notify_fname(conn, fname, FILE_NOTIFY_CHANGE_LAST_WRITE, - NOTIFY_ACTION_MODIFIED); return(True); } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 982de4c55f..7069818dee 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -361,50 +361,6 @@ files_struct *file_find_di_next(files_struct *start_fsp) return NULL; } -/* - * Same as file_find_di_first/next, but also finds non-fd opens. - * - * Jeremy, do we really need the fsp->fh->fd != -1 ?? - */ - -struct files_struct *fsp_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) -{ - files_struct *fsp; - - if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { - /* Positive or negative cache hit. */ - return fsp_fi_cache.fsp; - } - - fsp_fi_cache.dev = dev; - fsp_fi_cache.inode = inode; - - for (fsp=Files;fsp;fsp=fsp->next) { - if ((fsp->dev == dev) && (fsp->inode == inode)) { - /* Setup positive cache. */ - fsp_fi_cache.fsp = fsp; - return fsp; - } - } - - /* Setup negative cache. */ - fsp_fi_cache.fsp = NULL; - return NULL; -} - -struct files_struct *fsp_find_di_next(files_struct *start_fsp) -{ - files_struct *fsp; - - for (fsp = start_fsp->next;fsp;fsp=fsp->next) { - if ( (fsp->dev == start_fsp->dev) - && (fsp->inode == start_fsp->inode) ) - return fsp; - } - - return NULL; -} - /**************************************************************************** Find a fsp that is open for printing. ****************************************************************************/ @@ -483,8 +439,6 @@ void file_free(files_struct *fsp) fsp->fh->ref_count--; } - TALLOC_FREE(fsp->notify); - bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6bedb17261..4ec53567dd 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,7 +22,6 @@ #include "includes.h" static struct cnotify_fns *cnotify; -static struct notify_mid_map *notify_changes_by_mid; /**************************************************************************** This is the structure to queue to implement NT change @@ -34,76 +33,24 @@ static struct notify_mid_map *notify_changes_by_mid; struct change_notify { struct change_notify *next, *prev; files_struct *fsp; + connection_struct *conn; uint32 flags; - uint32 max_param_count; char request_buf[smb_size]; void *change_data; }; static struct change_notify *change_notify_list; -static BOOL notify_marshall_changes(unsigned num_changes, - struct notify_change *changes, - prs_struct *ps) -{ - int i; - UNISTR uni_name; - - for (i=0; iname, strlen(c->name)+1, - &uni_name.buffer, True); - if ((namelen == -1) || (uni_name.buffer == NULL)) { - goto fail; - } - - namelen -= 2; /* Dump NULL termination */ - - /* - * Offset to next entry, only if there is one - */ - - u32_tmp = (i == num_changes-1) ? 0 : namelen + 12; - if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; - - u32_tmp = c->action; - if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail; - - u32_tmp = namelen; - if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail; - - if (!prs_unistr("name", ps, 1, &uni_name)) goto fail; - - /* - * Not NULL terminated, decrease by the 2 UCS2 \0 chars - */ - prs_set_offset(ps, prs_offset(ps)-2); - - SAFE_FREE(uni_name.buffer); - } - - return True; - - fail: - SAFE_FREE(uni_name.buffer); - return False; -} - /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) +static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(request_buf, outbuf); + construct_reply_common(inbuf, outbuf); ERROR_NT(error_code); @@ -118,45 +65,6 @@ void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } -void change_notify_reply(const char *request_buf, uint32 max_param_count, - unsigned num_changes, struct notify_change *changes) -{ - char *outbuf = NULL; - prs_struct ps; - size_t buflen = smb_size+38+max_param_count; - - if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(num_changes, changes, &ps)) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); - goto done; - } - - if (prs_offset(&ps) > max_param_count) { - /* - * We exceed what the client is willing to accept. Send - * nothing. - */ - change_notify_reply_packet(request_buf, NT_STATUS_OK); - goto done; - } - - if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); - goto done; - } - - construct_reply_common(request_buf, outbuf); - - if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), - prs_offset(&ps), NULL, 0) == -1) { - exit_server("change_notify_reply_packet: send_smb failed."); - } - - done: - SAFE_FREE(outbuf); - prs_mem_free(&ps); -} - /**************************************************************************** Remove an entry from the list and free it, also closing any directory handle if necessary. @@ -170,103 +78,37 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } -NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, - uint32 filter, struct files_struct *fsp) -{ - struct notify_change_request *request = NULL; - struct notify_mid_map *map = NULL; - - if (!(request = SMB_MALLOC_P(struct notify_change_request)) - || !(map = SMB_MALLOC_P(struct notify_mid_map))) { - SAFE_FREE(request); - return NT_STATUS_NO_MEMORY; - } - - request->mid_map = map; - map->req = request; - - memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); - request->max_param_count = max_param_count; - request->filter = filter; - request->fsp = fsp; - DLIST_ADD_END(fsp->notify->requests, request, - struct notify_change_request *); - - map->mid = SVAL(inbuf, smb_mid); - DLIST_ADD(notify_changes_by_mid, map); - - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); - - return NT_STATUS_OK; -} - -static void change_notify_remove_request(struct notify_change_request *remove_req) -{ - files_struct *fsp; - struct notify_change_request *req; - - /* - * Paranoia checks, the fsp referenced must must have the request in - * its list of pending requests - */ - - fsp = remove_req->fsp; - SMB_ASSERT(fsp->notify != NULL); - - for (req = fsp->notify->requests; req; req = req->next) { - if (req == remove_req) { - break; - } - } - - if (req == NULL) { - smb_panic("notify_req not found in fsp's requests\n"); - } - - DLIST_REMOVE(fsp->notify->requests, req); - DLIST_REMOVE(notify_changes_by_mid, req->mid_map); - SAFE_FREE(req->mid_map); - SAFE_FREE(req); -} - /**************************************************************************** - Delete entries by mid from the change notify pending queue. Always send reply. + Delete entries by fnum from the change notify pending queue. *****************************************************************************/ -void remove_pending_change_notify_requests_by_mid(uint16 mid) +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) { - struct notify_mid_map *map; + struct change_notify *cnbp, *next; - for (map = notify_changes_by_mid; map; map = map->next) { - if (map->mid == mid) { - break; + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if (cnbp->fsp->fnum == fsp->fnum) { + change_notify_reply_packet(cnbp->request_buf,status); + change_notify_remove(cnbp); } } - - if (map == NULL) { - return; - } - - change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); - change_notify_remove_request(map->req); } /**************************************************************************** - Delete entries by fnum from the change notify pending queue. + Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_fid(files_struct *fsp, - NTSTATUS status) +void remove_pending_change_notify_requests_by_mid(int mid) { - if (fsp->notify == NULL) { - return; - } + struct change_notify *cnbp, *next; - while (fsp->notify->requests != NULL) { - change_notify_reply_packet( - fsp->notify->requests->request_buf, status); - change_notify_remove_request(fsp->notify->requests); + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if(SVAL(cnbp->request_buf,smb_mid) == mid) { + change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_remove(cnbp); + } } } @@ -286,7 +128,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf, status); + change_notify_reply_packet(cnbp->request_buf,status); change_notify_remove(cnbp); } } @@ -329,27 +171,9 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if (cnbp->fsp->notify->num_changes != 0) { - DEBUG(10,("process_pending_change_notify_queue: %s " - "has %d changes!\n", cnbp->fsp->fsp_name, - cnbp->fsp->notify->num_changes)); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); - change_notify_remove(cnbp); - continue; - } - - if (cnotify->check_notify(cnbp->fsp->conn, vuid, - cnbp->fsp->fsp_name, cnbp->flags, - cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir " - "%s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); + if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); + change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); change_notify_remove(cnbp); } } @@ -364,24 +188,22 @@ BOOL process_pending_change_notify_queue(time_t t) error. ****************************************************************************/ -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, - uint32 flags, uint32 max_param_count) +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) { struct change_notify *cnbp; if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); - return False; + return -1; } ZERO_STRUCTP(cnbp); memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; + cnbp->conn = conn; cnbp->flags = flags; - cnbp->max_param_count = max_param_count; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, - flags); + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); if (!cnbp->change_data) { SAFE_FREE(cnbp); @@ -405,237 +227,6 @@ int change_notify_fd(void) return -1; } -/* notify message definition - -Offset Data length. -0 SMB_DEV_T dev 8 -8 SMB_INO_T inode 8 -16 uint32 filter 4 -20 uint32 action 4 -24.. name -*/ - -#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ - -struct notify_message { - SMB_DEV_T dev; - SMB_INO_T inode; - uint32 filter; - uint32 action; - char *name; -}; - -static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) -{ - DATA_BLOB result; - size_t len; - - len = strlen(msg->name); - - result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); - if (!result.data) { - return result; - } - - SDEV_T_VAL(result.data, 0, msg->dev); - SINO_T_VAL(result.data, 8, msg->inode); - SIVAL(result.data, 16, msg->filter); - SIVAL(result.data, 20, msg->action); - memcpy(result.data+24, msg->name, len+1); - - return result; -} - -static BOOL buf_to_notify_message(void *buf, size_t len, - struct notify_message *msg) -{ - if (len < MSG_NOTIFY_MESSAGE_SIZE) { - DEBUG(0, ("Got invalid notify message of len %d\n", - (int)len)); - return False; - } - - msg->dev = DEV_T_VAL(buf, 0); - msg->inode = INO_T_VAL(buf, 8); - msg->filter = IVAL(buf, 16); - msg->action = IVAL(buf, 20); - msg->name = ((char *)buf)+24; - return True; -} - -void notify_action(connection_struct *conn, const char *parent, - const char *name, uint32 filter, uint32_t action) -{ - struct share_mode_lock *lck; - SMB_STRUCT_STAT sbuf; - int i; - struct notify_message msg; - DATA_BLOB blob; - - struct process_id *pids; - int num_pids; - - DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", - parent, name, (unsigned)action)); - - if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { - /* - * Not 100% critical, ignore failure - */ - return; - } - - if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, - NULL, NULL))) { - return; - } - - msg.dev = sbuf.st_dev; - msg.inode = sbuf.st_ino; - msg.filter = filter; - msg.action = action; - msg.name = CONST_DISCARD(char *, name); - - blob = notify_message_to_buf(&msg); - if (blob.data == NULL) { - DEBUG(0, ("notify_message_to_buf failed\n")); - return; - } - - pids = NULL; - num_pids = 0; - - become_root_uid_only(); - - for (i=0; inum_share_modes; i++) { - struct share_mode_entry *e = &lck->share_modes[i]; - int j; - struct process_id *tmp; - - for (j=0; jpid, &pids[j])) { - break; - } - } - - if (j < num_pids) { - /* - * Already sent to that process, skip it - */ - continue; - } - - message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, - blob.data, blob.length, True); - - if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, - num_pids+1))) { - DEBUG(0, ("realloc failed\n")); - break; - } - pids = tmp; - pids[num_pids] = e->pid; - num_pids += 1; - } - - unbecome_root_uid_only(); - - data_blob_free(&blob); - TALLOC_FREE(lck); -} - -void notify_fname(connection_struct *conn, const char *path, - uint32 filter, uint32 action) -{ - char *parent; - const char *name; - - if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { - return; - } - - notify_action(conn, parent, name, filter, action); - TALLOC_FREE(parent); -} - -static void notify_fsp(files_struct *fsp, struct notify_message *msg) -{ - struct notify_change *change, *changes; - - if (fsp->notify == NULL) { - /* - * Nobody is waiting, don't queue - */ - return; - } - - if ((fsp->notify->requests != NULL) - && (fsp->notify->requests->filter & msg->filter)) { - /* - * Someone is waiting for the change, trigger the reply - * immediately. - * - * TODO: do we have to walk the lists of requests pending? - */ - - struct notify_change_request *req = fsp->notify->requests; - struct notify_change onechange; - - onechange.action = msg->action; - onechange.name = msg->name; - - change_notify_reply(req->request_buf, req->max_param_count, - 1, &onechange); - change_notify_remove_request(req); - return; - } - - /* - * Someone has triggered a notify previously, queue the change for - * later. TODO: Limit the number of changes queued, test how filters - * apply here. Do we have to store them? - */ - - if (!(changes = TALLOC_REALLOC_ARRAY( - fsp->notify, fsp->notify->changes, - struct notify_change, fsp->notify->num_changes+1))) { - DEBUG(0, ("talloc_realloc failed\n")); - return; - } - - fsp->notify->changes = changes; - - change = &(fsp->notify->changes[fsp->notify->num_changes]); - - if (!(change->name = talloc_strdup(changes, msg->name))) { - DEBUG(0, ("talloc_strdup failed\n")); - return; - } - change->action = msg->action; - fsp->notify->num_changes += 1; - - return; -} - -static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len) -{ - struct notify_message msg; - files_struct *fsp; - - if (!buf_to_notify_message(buf, len, &msg)) { - return; - } - - DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", - (unsigned)msg.dev, (double)msg.inode, msg.action)); - - for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; - fsp = fsp_find_di_next(fsp)) { - notify_fsp(fsp, &msg); - } -} - /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ @@ -659,7 +250,5 @@ BOOL init_change_notify(void) return False; } - message_register(MSG_SMB_NOTIFY, notify_message_callback); - return True; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f62f5881b3..3e64cdc2d2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1820,15 +1820,14 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, { uint16 *setup = *ppsetup; files_struct *fsp; - uint32 filter; - NTSTATUS status; + uint32 flags; if(setup_count < 6) { return ERROR_DOS(ERRDOS,ERRbadfunc); } fsp = file_fsp((char *)setup,4); - filter = IVAL(setup, 0); + flags = IVAL(setup, 0); DEBUG(3,("call_nt_transact_notify_change\n")); @@ -1836,56 +1835,16 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfid); } - DEBUG(3,("call_nt_transact_notify_change: notify change called on " - "directory name = %s\n", fsp->fsp_name )); - if((!fsp->is_directory) || (conn != fsp->conn)) { return ERROR_DOS(ERRDOS,ERRbadfid); } - if (fsp->notify == NULL) { - if (!(fsp->notify = TALLOC_ZERO_P( - NULL, struct notify_change_buf))) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - } - - if (fsp->notify->num_changes > 0) { - - /* - * We've got changes pending, respond immediately - */ - - /* - * TODO: write a torture test to check the filtering behaviour - * here. - */ - - SMB_ASSERT(fsp->notify->requests == NULL); - - change_notify_reply(inbuf, max_param_count, - fsp->notify->num_changes, - fsp->notify->changes); - - TALLOC_FREE(fsp->notify->changes); - fsp->notify->num_changes = 0; - - /* - * change_notify_reply() above has independently sent its - * results - */ - return -1; + if (!change_notify_set(inbuf, fsp, conn, flags)) { + return(UNIXERROR(ERRDOS,ERRbadfid)); } - /* - * No changes pending, queue the request - */ - - status = change_notify_add_request(inbuf, max_param_count, filter, - fsp); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } + DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ +name = %s\n", fsp->fsp_name )); return -1; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 81537e0be3..bccc91bbd3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,8 +309,6 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } - notify_action(conn, parent_dir, name, -1, - NOTIFY_ACTION_ADDED); } } else { @@ -1944,9 +1942,6 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } - notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, - NOTIFY_ACTION_ADDED); - return NT_STATUS_OK; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cc181223f2..da7fadae3b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2032,8 +2032,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; - notify_fname(conn, orig_name, -1, - NOTIFY_ACTION_REMOVED); } } else { @@ -2094,9 +2092,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } if (SMB_VFS_UNLINK(conn,fname) == 0) { count++; - notify_action( - conn, directory, dname, - -1, NOTIFY_ACTION_REMOVED); } DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } @@ -3959,18 +3954,6 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) return False; } - { - char *parent_dir; - const char *dirname; - - if (parent_dirname_talloc(tmp_talloc_ctx(), directory, - &parent_dir, &dirname)) { - notify_action(conn, parent_dir, dirname, -1, - NOTIFY_ACTION_REMOVED); - TALLOC_FREE(parent_dir); /* Not strictly necessary */ - } - } - return True; } -- cgit From b538c2b86b64220e0c105487a728cc5d0dacd633 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Jan 2007 18:48:38 +0000 Subject: r20635: Add placeholder to ensure we don't go into the wcard unlink if bad_path was set. The error returned here is almost certainly incorrect and will need testing properly with smbtorture, but I don't want to forget about this path (yes Volker I know this is currently incorrect :-). Jeremy. (This used to be commit 06e20c287898d21e437ab117eb5eeeaf2420ba78) --- source3/smbd/reply.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index da7fadae3b..b3df8acf11 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2038,6 +2038,17 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, struct smb_Dir *dir_hnd = NULL; const char *dname; + /* Ensure we check bad_path in the wcard case. + * This may not be correct w.r.t. Windows (needs + * smbtorture test cases which will be forthcoming) + * but prevents us from continuing in the obvious + * bad path case. This is merely a placeholder. JRA. + */ + + if (!rc && bad_path) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); -- cgit From 93433501021bf6df00df3135992ed021385cfce6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 12 Jan 2007 08:49:09 +0000 Subject: r20699: This is an attempt to fix bug 4326. James, can you please confirm this and merge it to 3_0_24? For me it fixes the segfault. Thanks, Volker (This used to be commit a841b7659ba7b76b2da7993e1f4402aa0e11716f) --- source3/smbd/notify_fam.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index b7f9a36332..bfef4ac871 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -432,7 +432,8 @@ fam_remove_notify(void * data) * request. */ - if (info->generation == global_fc_generation) { + if ((FAMCONNECTION_GETFD(&global_fc) != -1) + && (info->generation == global_fc_generation)) { DEBUG(FAM_TRACE, ("removing FAM notification for request %d\n", info->req.reqnum)); FAMCancelMonitor(&global_fc, &(info->req)); -- cgit From 7a915ec3a61b74b07564d93112a3fbc87970c48d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 12 Jan 2007 09:29:44 +0000 Subject: r20700: In the main processing loop we select() on the fam socket. If it fires, it might be possible that we hang in the receive_smb() although that socket is not the reason for the select() to return. This immediately reacts to the fam socket to become readable, and goes into the select loop again. This fixes delays in files showing up in Windows. Jeremy, James please review this and merge to 3_0_24 if appropriate. Thanks, Volker (This used to be commit c846153b2ed2f9aca82491888e391ccbe239e88a) --- source3/smbd/process.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 28c2cd65dd..ecb33453c5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -514,6 +514,19 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ goto again; } + + if ((change_notify_fd() >= 0) && FD_ISSET(change_notify_fd(), &fds)) { + + process_pending_change_notify_queue((time_t)0); + + /* + * Same comment as for oplock processing applies here. We + * might have done I/O on the client socket. + */ + + goto again; + } + return receive_smb(smbd_server_fd(), buffer, 0); } -- cgit From db0ad252a0622dfac17d44ca646168df4c1c22e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Jan 2007 23:47:16 +0000 Subject: r20718: Sync up the filename path parsing changes from SAMBA_3_0_24. The only difference between the two trees now w.r.t file serving are the changes to smbd/open.c in this branch I need to review. Jeremy. (This used to be commit f4474edf6a0c71001dbd01429ef70bafad6abd74) --- source3/smbd/dosmode.c | 8 - source3/smbd/filename.c | 160 ++++++++--- source3/smbd/msdfs.c | 6 +- source3/smbd/nttrans.c | 52 +--- source3/smbd/reply.c | 685 ++++++++++++++++-------------------------------- source3/smbd/trans2.c | 88 +++---- 6 files changed, 387 insertions(+), 612 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 1172fe3e6b..ff4291c08c 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -35,14 +35,6 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf) Work out whether this file is offline ****************************************************************************/ -#ifndef ISDOT -#define ISDOT(p) (*(p) == '.' && *((p) + 1) == '\0') -#endif /* ISDOT */ - -#ifndef ISDOTDOT -#define ISDOTDOT(p) (*(p) == '.' && *((p) + 1) == '.' && *((p) + 2) == '\0') -#endif /* ISDOTDOT */ - static uint32 set_offline_flag(connection_struct *conn, const char *const path) { if (ISDOT(path) || ISDOTDOT(path)) { diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1ea5228e91..3f02f6090f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -64,18 +64,20 @@ changes etc. We assume that we have already done a chdir() to the right "root" directory for this service. -The function will return False if some part of the name except for the last -part cannot be resolved +The function will return an NTSTATUS error if some part of the name except for the last +part cannot be resolved, else NT_STATUS_OK. + +Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't +get any fatal errors that should immediately terminate the calling +SMB processing whilst resolving. If the saved_last_component != 0, then the unmodified last component of the pathname is returned there. This is used in an exceptional case in reply_mv (so far). If saved_last_component == 0 then nothing is returned there. -The bad_path arg is set to True if the filename walk failed. This is -used to pick the correct error code to return between ENOENT and ENOTDIR -as Windows applications depend on ERRbadpath being returned if a component -of a pathname does not exist. +If last_component_wcard is true then a MS wildcard was detected and +should be allowed in the last component of the path only. On exit from unix_convert, if *pst was not null, then the file stat struct will be returned if the file exists and was found, if not this @@ -83,8 +85,11 @@ stat struct will be filled with zeros (and this can be detected by checking for nlinks = 0, which can never be true for any file). ****************************************************************************/ -BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) +NTSTATUS unix_convert(connection_struct *conn, + pstring name, + BOOL allow_wcard_last_component, + char *saved_last_component, + SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; @@ -96,14 +101,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen SET_STAT_INVALID(*pst); *dirpath = 0; - *bad_path = False; - if(saved_last_component) + + if(saved_last_component) { *saved_last_component = 0; + } if (conn->printer) { /* we don't ever use the filenames on a printer share as a filename - so don't convert them */ - return True; + return NT_STATUS_OK; } DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); @@ -136,7 +142,12 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen *pst = st; } DEBUG(5,("conversion finished \"\" -> %s\n",name)); - return(True); + return NT_STATUS_OK; + } + + if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) { + /* Start of pathname can't be "." only. */ + return NT_STATUS_OBJECT_NAME_INVALID; } /* @@ -145,10 +156,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if(saved_last_component) { end = strrchr_m(name, '/'); - if(end) + if (end) { pstrcpy(saved_last_component, end + 1); - else + } else { pstrcpy(saved_last_component, name); + } } /* @@ -169,7 +181,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { *pst = st; - return True; + return NT_STATUS_OK; } /* @@ -177,10 +189,22 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen */ if (SMB_VFS_STAT(conn,name,&st) == 0) { + /* Ensure we catch all names with in "/." + this is disallowed under Windows. */ + const char *p = strstr(name, "/."); /* mb safe. */ + if (p) { + if (p[2] == '/') { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else if (p[2] == '\0') { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } + } stat_cache_add(orig_path, name, conn->case_sensitive); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; - return(True); + return NT_STATUS_OK; } DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); @@ -190,19 +214,20 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) && - !*lp_mangled_map(conn->params)) - return(False); - - name_has_wildcard = ms_has_wild(start); + if (conn->case_sensitive && + !mangle_is_mangled(name, conn->params) && + !*lp_mangled_map(conn->params)) { + return NT_STATUS_OK; + } /* * is_mangled() was changed to look at an entire pathname, not * just a component. JRA. */ - if (mangle_is_mangled(start, conn->params)) + if (mangle_is_mangled(start, conn->params)) { component_was_mangled = True; + } /* * Now we need to recursively match the name against the real @@ -218,16 +243,64 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen /* * Pinpoint the end of this section of the filename. */ - end = strchr_m(start, '/'); + end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */ /* * Chop the name at this point. */ - if (end) + if (end) { *end = 0; + } - if(saved_last_component != 0) + if (saved_last_component != 0) { pstrcpy(saved_last_component, end ? end + 1 : start); + } + + /* The name cannot have a component of "." */ + + if (ISDOT(start)) { + if (end) { + if (allow_wcard_last_component) { + /* We're terminating here so we + * can be a little slower and get + * the error code right. Windows + * treats the last part of the pathname + * separately I think, so if the last + * component is a wildcard then we treat + * this ./ as "end of component" */ + + const char *p = strchr(end+1, '/'); + + if (!p && ms_has_wild(end+1)) { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } else { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } + } + + /* The name cannot have a wildcard if it's not + the last component. */ + + name_has_wildcard = ms_has_wild(start); + + /* Wildcard not valid anywhere. */ + if (name_has_wildcard && !allow_wcard_last_component) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + + /* Wildcards never valid within a pathname. */ + if (name_has_wildcard && end) { + return NT_STATUS_OBJECT_NAME_INVALID; + } /* * Check if the name exists up to this point. @@ -251,9 +324,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Windows applications depend on the difference between * these two errors. */ - errno = ENOTDIR; - *bad_path = True; - return(False); + return NT_STATUS_OBJECT_PATH_NOT_FOUND; } if (!end) { @@ -278,8 +349,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * later. */ - if (end) + if (end) { pstrcpy(rest,end+1); + } /* Reset errno so we can detect directory open errors. */ errno = 0; @@ -288,7 +360,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Try to find this part of the path in the directory. */ - if (ms_has_wild(start) || + if (name_has_wildcard || !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) { if (end) { /* @@ -304,13 +376,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Windows applications depend on the difference between * these two errors. */ - *bad_path = True; - return(False); + if (errno == ENOENT) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + return map_nt_error_from_unix(errno); } if (errno == ENOTDIR) { - *bad_path = True; - return(False); + /* Name exists but is not a directory. */ + return map_nt_error_from_unix(ENOTDIR); } /* @@ -335,7 +409,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen } DEBUG(5,("New file %s\n",start)); - return(True); + return NT_STATUS_OK; } /* @@ -346,7 +420,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen end = start + strlen(start); if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) || !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) { - return False; + return map_nt_error_from_unix(ENAMETOOLONG); } *end = '\0'; } else { @@ -367,8 +441,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen /* * Add to the dirpath that we have resolved so far. */ - if (*dirpath) + if (*dirpath) { pstrcat(dirpath,"/"); + } pstrcat(dirpath,start); @@ -377,14 +452,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * as this can change the size. */ - if(!component_was_mangled && !name_has_wildcard) + if(!component_was_mangled && !name_has_wildcard) { stat_cache_add(orig_path, dirpath, conn->case_sensitive); + } /* * Restore the / that we wiped out earlier. */ - if (end) + if (end) { *end = '/'; + } } /* @@ -392,15 +469,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * as this can change the size. */ - if(!component_was_mangled && !name_has_wildcard) + if(!component_was_mangled && !name_has_wildcard) { stat_cache_add(orig_path, name, conn->case_sensitive); + } /* * The name has been resolved. */ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - return(True); + return NT_STATUS_OK; } /**************************************************************************** diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 12fd333efe..42595c033e 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -326,8 +326,8 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, pstring localpath; int consumed_level = 1; char *p; - BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + NTSTATUS status; pstring reqpath; if (!dp || !conn) { @@ -349,7 +349,9 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); - unix_convert(dp->reqpath,conn,0,&bad_path,&sbuf); + status = unix_convert(conn, dp->reqpath, False, NULL, &sbuf); + /* Should we terminate on status != NT_STATUS_OK ???? */ + /* JRA... should we strlower the last component here.... ? */ pstrcpy(localpath, dp->reqpath); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3e64cdc2d2..94bf363fc7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -466,7 +466,6 @@ int reply_ntcreate_and_X(connection_struct *conn, SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int info = 0; - BOOL bad_path = False; files_struct *fsp=NULL; char *p = NULL; struct timespec c_timespec; @@ -628,18 +627,17 @@ int reply_ntcreate_and_X(connection_struct *conn, set_posix_case_semantics(conn, file_attributes); - unix_convert(fname,conn,0,&bad_path,&sbuf); - - if (bad_path) { + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } /* All file access must go through check_name() */ if (!check_name(fname,conn)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } #if 0 @@ -1090,7 +1088,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int info = 0; - BOOL bad_path = False; files_struct *fsp = NULL; char *p = NULL; BOOL extended_oplock_granted = False; @@ -1257,15 +1254,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } /* All file access must go through check_name() */ if (!check_name(fname,conn)) { restore_case_semantics(conn, file_attributes); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } #if 0 @@ -1562,8 +1559,6 @@ int reply_ntcancel(connection_struct *conn, static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs) { - BOOL bad_path_oldname = False; - BOOL bad_path_newname = False; SMB_STRUCT_STAT sbuf1, sbuf2; pstring last_component_oldname; pstring last_component_newname; @@ -1577,24 +1572,12 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - /* No wildcards. */ - if (ms_has_wild(newname) || ms_has_wild(oldname)) { - return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - } - if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1); - if (bad_path_oldname) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - /* Quick check for "." and ".." */ - if (last_component_oldname[0] == '.') { - if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) { - return NT_STATUS_OBJECT_NAME_INVALID; - } + status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Source must already exist. */ @@ -1611,16 +1594,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return NT_STATUS_NO_SUCH_FILE; } - unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); - if (bad_path_newname) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - /* Quick check for "." and ".." */ - if (last_component_newname[0] == '.') { - if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) { - return NT_STATUS_OBJECT_NAME_INVALID; - } + status = unix_convert(conn, newname, False, last_component_newname, &sbuf2); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Disallow if newname already exists. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b3df8acf11..5914a3b169 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3,7 +3,7 @@ Main SMB reply routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Bartlett 2001 - Copyright (C) Jeremy Allison 1992-2004. + Copyright (C) Jeremy Allison 1992-2007. 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 @@ -36,143 +36,6 @@ extern uint32 global_client_caps; extern struct current_user current_user; extern BOOL global_encrypted_passwords_negotiated; -/**************************************************************************** - Ensure we check the path in *exactly* the same way as W2K for regular pathnames. - We're assuming here that '/' is not the second byte in any multibyte char - set (a safe assumption). '\\' *may* be the second byte in a multibyte char - set. -****************************************************************************/ - -NTSTATUS check_path_syntax(pstring destname, const pstring srcname) -{ - char *d = destname; - const char *s = srcname; - NTSTATUS ret = NT_STATUS_OK; - BOOL start_of_name_component = True; - unsigned int num_bad_components = 0; - - while (*s) { - if (IS_DIRECTORY_SEP(*s)) { - /* - * Safe to assume is not the second part of a mb char as this is handled below. - */ - /* Eat multiple '/' or '\\' */ - while (IS_DIRECTORY_SEP(*s)) { - s++; - } - if ((d != destname) && (*s != '\0')) { - /* We only care about non-leading or trailing '/' or '\\' */ - *d++ = '/'; - } - - start_of_name_component = True; - continue; - } - - if (start_of_name_component) { - if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { - /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */ - - /* - * No mb char starts with '.' so we're safe checking the directory separator here. - */ - - /* If we just added a '/' - delete it */ - if ((d > destname) && (*(d-1) == '/')) { - *(d-1) = '\0'; - d--; - } - - /* Are we at the start ? Can't go back further if so. */ - if (d <= destname) { - ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - break; - } - /* Go back one level... */ - /* We know this is safe as '/' cannot be part of a mb sequence. */ - /* NOTE - if this assumption is invalid we are not in good shape... */ - /* Decrement d first as d points to the *next* char to write into. */ - for (d--; d > destname; d--) { - if (*d == '/') - break; - } - s += 2; /* Else go past the .. */ - /* We're still at the start of a name component, just the previous one. */ - - if (num_bad_components) { - /* Hmmm. Should we only decrement the bad_components if - we're removing a bad component ? Need to check this. JRA. */ - num_bad_components--; - } - - continue; - - } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) { - /* Component of pathname can't be "." only. */ - ret = NT_STATUS_OBJECT_NAME_INVALID; - num_bad_components++; - *d++ = *s++; - continue; - } - } - - if (!(*s & 0x80)) { - if (*s <= 0x1f) { - return NT_STATUS_OBJECT_NAME_INVALID; - } - switch (*s) { - case '*': - case '?': - case '<': - case '>': - case '"': - return NT_STATUS_OBJECT_NAME_INVALID; - default: - *d++ = *s++; - break; - } - } else { - size_t siz; - /* Get the size of the next MB character. */ - next_codepoint(s,&siz); - switch(siz) { - case 5: - *d++ = *s++; - /*fall through*/ - case 4: - *d++ = *s++; - /*fall through*/ - case 3: - *d++ = *s++; - /*fall through*/ - case 2: - *d++ = *s++; - /*fall through*/ - case 1: - *d++ = *s++; - break; - default: - DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); - *d = '\0'; - return NT_STATUS_INVALID_PARAMETER; - } - } - if (start_of_name_component && num_bad_components) { - num_bad_components++; - } - start_of_name_component = False; - } - - if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { - if (num_bad_components > 1) { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - } - - *d = '\0'; - return ret; -} - /**************************************************************************** Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext path or anything including wildcards. @@ -181,15 +44,19 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) set. ****************************************************************************/ -NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard) +NTSTATUS check_path_syntax_internal(pstring destname, + const pstring srcname, + BOOL windows_path, BOOL + *p_last_component_contains_wcard) { char *d = destname; const char *s = srcname; NTSTATUS ret = NT_STATUS_OK; BOOL start_of_name_component = True; - unsigned int num_bad_components = 0; - *p_contains_wcard = False; + if (p_last_component_contains_wcard) { + *p_last_component_contains_wcard = False; + } while (*s) { if (IS_DIRECTORY_SEP(*s)) { @@ -206,6 +73,10 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * } start_of_name_component = True; + /* New component. */ + if (p_last_component_contains_wcard) { + *p_last_component_contains_wcard = False; + } continue; } @@ -238,36 +109,32 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * } s += 2; /* Else go past the .. */ /* We're still at the start of a name component, just the previous one. */ - - if (num_bad_components) { - /* Hmmm. Should we only decrement the bad_components if - we're removing a bad component ? Need to check this. JRA. */ - num_bad_components--; - } - continue; } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) { - /* Component of pathname can't be "." only. */ - ret = NT_STATUS_OBJECT_NAME_INVALID; - num_bad_components++; - *d++ = *s++; - continue; + if (!windows_path) { + /* Eat the '.' */ + s++; + continue; + } } + } if (!(*s & 0x80)) { - if (*s <= 0x1f) { - return NT_STATUS_OBJECT_NAME_INVALID; - } - if (!*p_contains_wcard) { + if (windows_path) { + if (*s <= 0x1f) { + return NT_STATUS_OBJECT_NAME_INVALID; + } switch (*s) { case '*': case '?': case '<': case '>': case '"': - *p_contains_wcard = True; + if (p_last_component_contains_wcard) { + *p_last_component_contains_wcard = True; + } break; default: break; @@ -295,130 +162,48 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * *d++ = *s++; break; default: - DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n")); + DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n")); *d = '\0'; return NT_STATUS_INVALID_PARAMETER; } } - if (start_of_name_component && num_bad_components) { - num_bad_components++; - } start_of_name_component = False; } - if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { - /* For some strange reason being called from findfirst changes - the num_components number to cause the error return to change. JRA. */ - if (num_bad_components > 2) { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - } - *d = '\0'; return ret; } /**************************************************************************** - Check the path for a POSIX client. - We're assuming here that '/' is not the second byte in any multibyte char - set (a safe assumption). + Ensure we check the path in *exactly* the same way as W2K for regular pathnames. + No wildcards allowed. ****************************************************************************/ -NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) +NTSTATUS check_path_syntax(pstring destname, const pstring srcname) { - char *d = destname; - const char *s = srcname; - NTSTATUS ret = NT_STATUS_OK; - BOOL start_of_name_component = True; - - while (*s) { - if (*s == '/') { - /* - * Safe to assume is not the second part of a mb char as this is handled below. - */ - /* Eat multiple '/' or '\\' */ - while (*s == '/') { - s++; - } - if ((d != destname) && (*s != '\0')) { - /* We only care about non-leading or trailing '/' */ - *d++ = '/'; - } - - start_of_name_component = True; - continue; - } - - if (start_of_name_component) { - if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) { - /* Uh oh - "/../" or "/..\0" ! */ - - /* - * No mb char starts with '.' so we're safe checking the directory separator here. - */ - - /* If we just added a '/' - delete it */ - if ((d > destname) && (*(d-1) == '/')) { - *(d-1) = '\0'; - d--; - } + return check_path_syntax_internal(destname, srcname, True, NULL); +} - /* Are we at the start ? Can't go back further if so. */ - if (d <= destname) { - ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - break; - } - /* Go back one level... */ - /* We know this is safe as '/' cannot be part of a mb sequence. */ - /* NOTE - if this assumption is invalid we are not in good shape... */ - /* Decrement d first as d points to the *next* char to write into. */ - for (d--; d > destname; d--) { - if (*d == '/') - break; - } - s += 2; /* Else go past the .. */ - continue; +/**************************************************************************** + Ensure we check the path in *exactly* the same way as W2K for regular pathnames. + Wildcards allowed - p_contains_wcard returns true if the last component contained + a wildcard. +****************************************************************************/ - } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) { - /* Eat the '.' */ - s++; - continue; - } - } +NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard) +{ + return check_path_syntax_internal(destname, srcname, True, p_contains_wcard); +} - if (!(*s & 0x80)) { - *d++ = *s++; - } else { - size_t siz; - /* Get the size of the next MB character. */ - next_codepoint(s,&siz); - switch(siz) { - case 5: - *d++ = *s++; - /*fall through*/ - case 4: - *d++ = *s++; - /*fall through*/ - case 3: - *d++ = *s++; - /*fall through*/ - case 2: - *d++ = *s++; - /*fall through*/ - case 1: - *d++ = *s++; - break; - default: - DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n")); - *d = '\0'; - return NT_STATUS_INVALID_PARAMETER; - } - } - start_of_name_component = False; - } +/**************************************************************************** + Check the path for a POSIX client. + We're assuming here that '/' is not the second byte in any multibyte char + set (a safe assumption). +****************************************************************************/ - *d = '\0'; - return ret; +static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) +{ + return check_path_syntax_internal(destname, srcname, False, NULL); } /**************************************************************************** @@ -823,7 +608,6 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int outsize = 0; pstring name; BOOL ok = False; - BOOL bad_path = False; SMB_STRUCT_STAT sbuf; NTSTATUS status; @@ -845,10 +629,10 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - unix_convert(name,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, name, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBchkpth); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } if (check_name(name,conn)) { @@ -871,8 +655,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size * the parent directory is valid but not the * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND - * if the path is invalid. This is different from set_bad_path_error() - * in the non-NT error case. + * if the path is invalid. */ END_PROFILE(SMBchkpth); return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); @@ -902,7 +685,6 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int mode=0; SMB_OFF_T size=0; time_t mtime=0; - BOOL bad_path = False; char *p; NTSTATUS status; @@ -927,10 +709,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mtime = 0; ok = True; } else { - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, fname, False, NULL,&sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBgetatr); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } if (check_name(fname,conn)) { if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) { @@ -948,7 +730,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!ok) { END_PROFILE(SMBgetatr); - return UNIXERROR(ERRDOS, ERRbadfile); + return UNIXERROR(ERRDOS,ERRbadfile); } outsize = set_message(outbuf,10,0,True); @@ -982,7 +764,6 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size int mode; time_t mtime; SMB_STRUCT_STAT sbuf; - BOOL bad_path = False; char *p; NTSTATUS status; @@ -997,10 +778,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path || !check_name(fname, conn)) { + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsetatr); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } if (fname[0] == '.' && fname[1] == '\0') { @@ -1012,6 +793,11 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(NT_STATUS_ACCESS_DENIED); } + if (!check_name(fname,conn)) { + END_PROFILE(SMBsetatr); + return UNIXERROR(ERRDOS, ERRnoaccess); + } + mode = SVAL(inbuf,smb_vwv0); mtime = srv_make_unix_date3(inbuf+smb_vwv1); @@ -1118,7 +904,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL check_descend = False; BOOL expect_close = False; BOOL can_open = True; - BOOL bad_path = False; NTSTATUS nt_status; BOOL mask_contains_wcard = False; BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; @@ -1160,7 +945,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(directory,path); pstrcpy(dir2,path); - unix_convert(directory,conn,0,&bad_path,&sbuf); + nt_status = unix_convert(conn, directory, mask_contains_wcard, NULL, &sbuf); + if (!NT_STATUS_IS_OK(nt_status)) { + END_PROFILE(SMBsearch); + return ERROR_NT(nt_status); + } unix_format(dir2); if (!check_name(directory,conn)) @@ -1209,9 +998,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (dptr_num < 0) { if(dptr_num == -2) { END_PROFILE(SMBsearch); - if ((errno == ENOENT) && bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); - } return UNIXERROR(ERRDOS, ERRnofids); } END_PROFILE(SMBsearch); @@ -1377,7 +1163,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, time_t mtime=0; int info; SMB_STRUCT_STAT sbuf; - BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); int deny_mode; @@ -1399,10 +1184,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, @@ -1486,7 +1271,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int mtime=0; SMB_STRUCT_STAT sbuf; int smb_action = 0; - BOOL bad_path = False; files_struct *fsp; NTSTATUS status; SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9); @@ -1518,10 +1302,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun, @@ -1667,7 +1451,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int outsize = 0; uint32 fattr = SVAL(inbuf,smb_vwv0); struct utimbuf times; - BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); SMB_STRUCT_STAT sbuf; @@ -1691,10 +1474,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } if (fattr & aVOLID) { @@ -1758,7 +1541,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring fname; int outsize = 0; uint32 fattr = SVAL(inbuf,smb_vwv0); - BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); int tmpfd; @@ -1782,10 +1564,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } tmpfd = smb_mkstemp(fname); @@ -1898,12 +1680,12 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, Check if a user is allowed to delete a file. ********************************************************************/ -static NTSTATUS can_delete(connection_struct *conn, char *fname, - uint32 dirtype, BOOL bad_path) +static NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype) { SMB_STRUCT_STAT sbuf; uint32 fattr; files_struct *fsp; + uint32 dirtype_orig = dirtype; NTSTATUS status; DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype )); @@ -1913,22 +1695,56 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, } if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) { - if(errno == ENOENT) { - if (bad_path) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } else { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - } return map_nt_error_from_unix(errno); } fattr = dos_mode(conn,fname,&sbuf); + if (dirtype & FILE_ATTRIBUTE_NORMAL) { + dirtype = aDIR|aARCH|aRONLY; + } + + dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM); + if (!dirtype) { + return NT_STATUS_NO_SUCH_FILE; + } + + if (!dir_check_ftype(conn, fattr, dirtype)) { + if (fattr & aDIR) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + return NT_STATUS_NO_SUCH_FILE; + } + + if (dirtype_orig & 0x8000) { + /* These will never be set for POSIX. */ + return NT_STATUS_NO_SUCH_FILE; + } + +#if 0 + if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + + if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) { + return NT_STATUS_NO_SUCH_FILE; + } + + if (dirtype & 0xFF00) { + /* These will never be set for POSIX. */ + return NT_STATUS_NO_SUCH_FILE; + } + + dirtype &= 0xFF; + if (!dirtype) { + return NT_STATUS_NO_SUCH_FILE; + } + /* Can't delete a directory. */ if (fattr & aDIR) { return NT_STATUS_FILE_IS_A_DIRECTORY; } +#endif #if 0 /* JRATEST */ else if (dirtype & aDIR) /* Asked for a directory and it isn't. */ @@ -1952,9 +1768,6 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, return NT_STATUS_CANNOT_DELETE; } } - if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) { - return NT_STATUS_NO_SUCH_FILE; - } /* On open checks the open itself will check the share mode, so don't do it here as we'll get it wrong. */ @@ -1979,27 +1792,21 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, code. ****************************************************************************/ -NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, - char *name, BOOL has_wild) +NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild) { pstring directory; pstring mask; - pstring orig_name; char *p; int count=0; - NTSTATUS error = NT_STATUS_OK; - BOOL bad_path = False; - BOOL rc = True; + NTSTATUS status = NT_STATUS_OK; SMB_STRUCT_STAT sbuf; *directory = *mask = 0; - rc = unix_convert(name,conn,0,&bad_path,&sbuf); - - /* - * Feel my pain, this code needs rewriting *very* badly! -- vl - */ - pstrcpy(orig_name, name); + status = unix_convert(conn, name, has_wild, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return status; + } p = strrchr_m(name,'/'); if (!p) { @@ -2020,33 +1827,28 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask,conn->params)) + if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - error = can_delete(conn,directory,dirtype,bad_path); - if (!NT_STATUS_IS_OK(error)) - return error; + if (dirtype == 0) { + dirtype = FILE_ATTRIBUTE_NORMAL; + } + status = can_delete(conn,directory,dirtype); + if (!NT_STATUS_IS_OK(status)) + return status; if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; } - } else { struct smb_Dir *dir_hnd = NULL; const char *dname; - /* Ensure we check bad_path in the wcard case. - * This may not be correct w.r.t. Windows (needs - * smbtorture test cases which will be forthcoming) - * but prevents us from continuing in the obvious - * bad path case. This is merely a placeholder. JRA. - */ - - if (!rc && bad_path) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) { + return NT_STATUS_OBJECT_NAME_INVALID; } if (strequal(mask,"????????.???")) @@ -2062,12 +1864,11 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (dir_hnd) { long offset = 0; - error = NT_STATUS_NO_SUCH_FILE; + status = NT_STATUS_NO_SUCH_FILE; while ((dname = ReadDirName(dir_hnd, &offset))) { SMB_STRUCT_STAT st; pstring fname; - BOOL sys_direntry = False; pstrcpy(fname,dname); if (!is_visible_file(conn, directory, dname, &st, True)) { @@ -2077,44 +1878,31 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, /* Quick check for "." and ".." */ if (fname[0] == '.') { if (!fname[1] || (fname[1] == '.' && !fname[2])) { - if (dirtype & FILE_ATTRIBUTE_DIRECTORY) { - sys_direntry = True; - } else { - continue; - } + continue; } } if(!mask_match(fname, mask, conn->case_sensitive)) continue; - if (sys_direntry) { - error = NT_STATUS_OBJECT_NAME_INVALID; - DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n", - fname, mask)); - break; - } - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - error = can_delete(conn, fname, dirtype, - bad_path); - if (!NT_STATUS_IS_OK(error)) { + status = can_delete(conn, fname, dirtype); + if (!NT_STATUS_IS_OK(status)) { continue; } - if (SMB_VFS_UNLINK(conn,fname) == 0) { + if (SMB_VFS_UNLINK(conn,fname) == 0) count++; - } DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dir_hnd); } } - if (count == 0 && NT_STATUS_IS_OK(error)) { - error = map_nt_error_from_unix(errno); + if (count == 0 && NT_STATUS_IS_OK(status)) { + status = map_nt_error_from_unix(errno); } - return error; + return status; } /**************************************************************************** @@ -3774,7 +3562,6 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring directory; int outsize; NTSTATUS status; - BOOL bad_path = False; SMB_STRUCT_STAT sbuf; START_PROFILE(SMBmkdir); @@ -3787,10 +3574,10 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); - unix_convert(directory,conn,0,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, directory, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } status = create_directory(conn, directory); @@ -3939,7 +3726,7 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) pstrcpy(fullname, directory); pstrcat(fullname, "/"); pstrcat(fullname, dname); - + if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) { @@ -3977,7 +3764,6 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring directory; int outsize = 0; BOOL ok = False; - BOOL bad_path = False; SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBrmdir); @@ -3990,10 +3776,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) - unix_convert(directory,conn, NULL,&bad_path,&sbuf); - if (bad_path) { + status = unix_convert(conn, directory, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return ERROR_NT(status); } if (check_name(directory,conn)) { @@ -4171,24 +3957,16 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest) NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists) { SMB_STRUCT_STAT sbuf; - BOOL bad_path = False; pstring newname_last_component; - NTSTATUS error = NT_STATUS_OK; + NTSTATUS status = NT_STATUS_OK; BOOL dest_exists; - BOOL rcdest = True; struct share_mode_lock *lck = NULL; ZERO_STRUCT(sbuf); - rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); - /* Quick check for "." and ".." */ - if (!bad_path && newname_last_component[0] == '.') { - if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { - return NT_STATUS_ACCESS_DENIED; - } - } - if (!rcdest && bad_path) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + status = unix_convert(conn, newname, False, newname_last_component, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Ensure newname contains a '/' */ @@ -4250,14 +4028,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * return NT_STATUS_OBJECT_NAME_COLLISION; } - error = can_rename(conn,newname,attrs,&sbuf); + status = can_rename(conn,newname,attrs,&sbuf); - if (dest_exists && !NT_STATUS_IS_OK(error)) { + if (dest_exists && !NT_STATUS_IS_OK(status)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(error), fsp->fsp_name,newname)); - if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION)) - error = NT_STATUS_ACCESS_DENIED; - return error; + nt_errstr(status), fsp->fsp_name,newname)); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) + status = NT_STATUS_ACCESS_DENIED; + return status; } if (rename_path_prefix_equal(fsp->fsp_name, newname)) { @@ -4277,15 +4055,15 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * TALLOC_FREE(lck); if (errno == ENOTDIR || errno == EISDIR) { - error = NT_STATUS_OBJECT_NAME_COLLISION; + status = NT_STATUS_OBJECT_NAME_COLLISION; } else { - error = map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); } DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", - nt_errstr(error), fsp->fsp_name,newname)); + nt_errstr(status), fsp->fsp_name,newname)); - return error; + return status; } /**************************************************************************** @@ -4300,12 +4078,8 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui pstring last_component_src; pstring last_component_dest; char *p; - BOOL bad_path_src = False; - BOOL bad_path_dest = False; int count=0; - NTSTATUS error = NT_STATUS_OK; - BOOL rc = True; - BOOL rcdest = True; + NTSTATUS status = NT_STATUS_OK; SMB_STRUCT_STAT sbuf1, sbuf2; struct share_mode_lock *lck = NULL; @@ -4314,27 +4088,14 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1); - if (!rc && bad_path_src) { - if (ms_has_wild(last_component_src)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - /* Quick check for "." and ".." */ - if (last_component_src[0] == '.') { - if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) { - return NT_STATUS_OBJECT_NAME_INVALID; - } + status = unix_convert(conn, name, has_wild, last_component_src, &sbuf1); + if (!NT_STATUS_IS_OK(status)) { + return status; } - rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2); - - /* Quick check for "." and ".." */ - if (last_component_dest[0] == '.') { - if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) { - return NT_STATUS_OBJECT_NAME_INVALID; - } + status = unix_convert(conn, newname, True, last_component_dest, &sbuf2); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* @@ -4366,7 +4127,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask, conn->params)) + if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { @@ -4451,25 +4212,19 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_NAME_NOT_FOUND; return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - error = map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(error), directory,newname)); - - return error; - } + nt_errstr(status), directory,newname)); - if (!rcdest && bad_path_dest) { - if (ms_has_wild(last_component_dest)) - return NT_STATUS_OBJECT_NAME_INVALID; - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + return status; } - error = can_rename(conn,directory,attrs,&sbuf1); + status = can_rename(conn,directory,attrs,&sbuf1); - if (!NT_STATUS_IS_OK(error)) { + if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(error), directory,newname)); - return error; + nt_errstr(status), directory,newname)); + return status; } /* @@ -4505,14 +4260,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", TALLOC_FREE(lck); if (errno == ENOTDIR || errno == EISDIR) - error = NT_STATUS_OBJECT_NAME_COLLISION; + status = NT_STATUS_OBJECT_NAME_COLLISION; else - error = map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(error), directory,newname)); + nt_errstr(status), directory,newname)); - return error; + return status; } else { /* * Wildcards - process each file that matches. @@ -4529,8 +4284,8 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", if (dir_hnd) { long offset = 0; - error = NT_STATUS_NO_SUCH_FILE; -/* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ + status = NT_STATUS_NO_SUCH_FILE; +/* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; @@ -4556,19 +4311,19 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", continue; if (sysdir_entry) { - error = NT_STATUS_OBJECT_NAME_INVALID; + status = NT_STATUS_OBJECT_NAME_INVALID; break; } - error = NT_STATUS_ACCESS_DENIED; + status = NT_STATUS_ACCESS_DENIED; slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); if (!vfs_object_exist(conn, fname, &sbuf1)) { - error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error))); + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status))); continue; } - error = can_rename(conn,fname,attrs,&sbuf1); - if (!NT_STATUS_IS_OK(error)) { + status = can_rename(conn,fname,attrs,&sbuf1); + if (!NT_STATUS_IS_OK(status)) { DEBUG(6,("rename %s refused\n", fname)); continue; } @@ -4584,14 +4339,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); count++; - error = NT_STATUS_OK; + status = NT_STATUS_OK; continue; } if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) { DEBUG(6,("file_exist %s\n", destname)); - error = NT_STATUS_OBJECT_NAME_COLLISION; + status = NT_STATUS_OBJECT_NAME_COLLISION; continue; } @@ -4604,7 +4359,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", if (!SMB_VFS_RENAME(conn,fname,destname)) { rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); count++; - error = NT_STATUS_OK; + status = NT_STATUS_OK; } TALLOC_FREE(lck); DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); @@ -4612,6 +4367,8 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", CloseDir(dir_hnd); } +#if 0 + /* Don't think needed any more - JRA. */ if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) { if (!rcdest && bad_path_dest) { if (ms_has_wild(last_component_dest)) @@ -4619,13 +4376,15 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_PATH_NOT_FOUND; } } +#endif + } - if (count == 0 && NT_STATUS_IS_OK(error)) { - error = map_nt_error_from_unix(errno); + if (count == 0 && NT_STATUS_IS_OK(status)) { + status = map_nt_error_from_unix(errno); } - return error; + return status; } /**************************************************************************** @@ -4821,11 +4580,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int ofun = SVAL(inbuf,smb_vwv1); int flags = SVAL(inbuf,smb_vwv2); BOOL target_is_directory=False; - BOOL bad_path1 = False; - BOOL bad_path2 = False; BOOL path_contains_wcard1 = False; BOOL path_contains_wcard2 = False; - BOOL rc = True; SMB_STRUCT_STAT sbuf1, sbuf2; NTSTATUS status; START_PROFILE(SMBcopy); @@ -4856,8 +4612,17 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); - rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); - unix_convert(newname,conn,0,&bad_path2,&sbuf2); + status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcopy); + return ERROR_NT(status); + } + + status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcopy); + return ERROR_NT(status); + } target_is_directory = VALID_STAT_OF_DIR(sbuf2); @@ -4897,7 +4662,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec . */ - if (!rc && mangle_is_mangled(mask, conn->params)) + if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); has_wild = path_contains_wcard1; @@ -4964,20 +4729,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRHRD,ERRgeneral)); } - if (exists) { - END_PROFILE(SMBcopy); - return ERROR_DOS(ERRDOS,error); - } else { - if((errno == ENOENT) && (bad_path1 || bad_path2) && - !use_nt_status()) { - /* Samba 3.0.22 has ERRDOS/ERRbadpath in the - * DOS error code case - */ - return ERROR_DOS(ERRDOS, ERRbadpath); - } - END_PROFILE(SMBcopy); - return(UNIXERROR(ERRDOS,error)); - } + END_PROFILE(SMBcopy); + return ERROR_DOS(ERRDOS,error); } outsize = set_message(outbuf,1,0,True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 40394c3d8a..2cfb692b02 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -751,7 +751,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i SMB_INO_T inode = 0; SMB_STRUCT_STAT sbuf; int smb_action = 0; - BOOL bad_path = False; files_struct *fsp; struct ea_list *ea_list = NULL; uint16 flags = 0; @@ -801,13 +800,13 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } if (!check_name(fname,conn)) { - return UNIXERROR(ERRDOS, ERRnoaccess); + return UNIXERROR(ERRDOS,ERRnoaccess); } if (open_ofun == 0) { @@ -1662,7 +1661,6 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb BOOL dont_descend = False; BOOL out_of_space = False; int space_remaining; - BOOL bad_path = False; BOOL mask_contains_wcard = False; SMB_STRUCT_STAT sbuf; TALLOC_CTX *ea_ctx = NULL; @@ -1720,12 +1718,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf); - unix_convert(directory,conn,0,&bad_path,&sbuf); - if (bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + ntstatus = unix_convert(conn, directory, mask_contains_wcard, NULL, &sbuf); + if (!NT_STATUS_IS_OK(ntstatus)) { + return ERROR_NT(ntstatus); } if(!check_name(directory,conn)) { - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } p = strrchr_m(directory,'/'); @@ -2844,7 +2842,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * char *base_name; char *p; SMB_OFF_T pos = 0; - BOOL bad_path = False; BOOL delete_pending = False; int len; time_t create_time, mtime, atime; @@ -2891,11 +2888,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } } else if (SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); @@ -2933,24 +2930,24 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); @@ -3671,8 +3668,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname) { - BOOL bad_path_oldname = False; - BOOL bad_path_newname = False; SMB_STRUCT_STAT sbuf1, sbuf2; pstring last_component_oldname; pstring last_component_newname; @@ -3681,21 +3676,9 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - /* No wildcards. */ - if (ms_has_wild(newname) || ms_has_wild(oldname)) { - return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - } - - unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1); - if (bad_path_oldname) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - /* Quick check for "." and ".." */ - if (last_component_oldname[0] == '.') { - if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) { - return NT_STATUS_OBJECT_NAME_INVALID; - } + status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* source must already exist. */ @@ -3707,16 +3690,9 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_ACCESS_DENIED; } - unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); - if (bad_path_newname) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - /* Quick check for "." and ".." */ - if (last_component_newname[0] == '.') { - if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) { - return NT_STATUS_OBJECT_NAME_INVALID; - } + status = unix_convert(conn, newname, False, last_component_newname, &sbuf2); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Disallow if newname already exists. */ @@ -3766,7 +3742,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char SMB_STRUCT_STAT sbuf; pstring fname; int fd = -1; - BOOL bad_path = False; files_struct *fsp = NULL; uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; @@ -3796,7 +3771,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pstrcpy(fname, fsp->fsp_name); if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } } else if (fsp && fsp->print_file) { /* @@ -3837,9 +3812,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - unix_convert(fname,conn,0,&bad_path,&sbuf); - if (bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + status = unix_convert(conn, fname, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } /* @@ -3848,11 +3823,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } if(!check_name(fname, conn)) { - return UNIXERROR(ERRDOS, ERRbadpath); + return UNIXERROR(ERRDOS,ERRbadpath); } } @@ -4789,7 +4764,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, char *pdata = *ppdata; pstring directory; SMB_STRUCT_STAT sbuf; - BOOL bad_path = False; NTSTATUS status = NT_STATUS_OK; struct ea_list *ea_list = NULL; @@ -4807,9 +4781,9 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,conn,0,&bad_path,&sbuf); - if (bad_path) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + status = unix_convert(conn, directory, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } /* Any data in this call is an EA list. */ -- cgit From 1a40a6e08a58d02e912aaa9f81dcff48477f3b81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 01:07:39 +0000 Subject: r20720: Fix the chkpath problem, still looking at findfirst. Jeremy. (This used to be commit c5be0082ef60cd041121a9c36f4af934cd60562d) --- source3/smbd/filename.c | 7 ++++++- source3/smbd/reply.c | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3f02f6090f..44916200da 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -147,7 +147,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) { /* Start of pathname can't be "." only. */ - return NT_STATUS_OBJECT_NAME_INVALID; + if (name[1] == '\0' || name[2] == '\0') { + return NT_STATUS_OBJECT_NAME_INVALID; + } else { + /* Longer pathname starts with ./ */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } } /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5914a3b169..e42c663cec 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -632,6 +632,13 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size status = unix_convert(conn, name, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBchkpth); + /* Strange DOS error code semantics only for chkpth... */ + if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) { + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) { + /* We need to map to ERRbadpath */ + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } return ERROR_NT(status); } -- cgit From dd5e9e2ae7ba3c4f3d4d8e02c7a993dd8e164c5b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 01:29:10 +0000 Subject: r20721: Fix the search unix_convert error returns. Only open to go... Jeremy. (This used to be commit 89f03a8db40365f99c6755ff19a4bfbf8d1bd316) --- source3/smbd/filename.c | 60 ++++++++++++++++++++++++++++--------------------- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 2 +- 3 files changed, 37 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 44916200da..dd1e0de20f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -56,6 +56,38 @@ static BOOL mangled_equal(const char *name1, const char *name2, return strequal(name1, tmpname); } +/**************************************************************************** + Cope with the differing wildcard and non-wildcard error cases. +****************************************************************************/ + +static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_component) +{ + const char *p; + + if (!allow_wcard_last_component) { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* We're terminating here so we + * can be a little slower and get + * the error code right. Windows + * treats the last part of the pathname + * separately I think, so if the last + * component is a wildcard then we treat + * this ./ as "end of component" */ + + p = strchr(name, '/'); + + if (!p && (ms_has_wild(name) || ISDOT(name))) { + /* Error code at the end of a pathname. */ + return NT_STATUS_OBJECT_NAME_INVALID; + } else { + /* Error code within a pathname. */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } +} + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -150,8 +182,7 @@ NTSTATUS unix_convert(connection_struct *conn, if (name[1] == '\0' || name[2] == '\0') { return NT_STATUS_OBJECT_NAME_INVALID; } else { - /* Longer pathname starts with ./ */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + return determine_path_error(&name[2], allow_wcard_last_component); } } @@ -264,32 +295,11 @@ NTSTATUS unix_convert(connection_struct *conn, /* The name cannot have a component of "." */ if (ISDOT(start)) { - if (end) { - if (allow_wcard_last_component) { - /* We're terminating here so we - * can be a little slower and get - * the error code right. Windows - * treats the last part of the pathname - * separately I think, so if the last - * component is a wildcard then we treat - * this ./ as "end of component" */ - - const char *p = strchr(end+1, '/'); - - if (!p && ms_has_wild(end+1)) { - /* Error code at the end of a pathname. */ - return NT_STATUS_OBJECT_NAME_INVALID; - } else { - /* Error code within a pathname. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - } - /* Error code within a pathname. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } else { + if (!end) { /* Error code at the end of a pathname. */ return NT_STATUS_OBJECT_NAME_INVALID; } + return determine_path_error(end+1, allow_wcard_last_component); } /* The name cannot have a wildcard if it's not diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e42c663cec..21c8b13b5c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -952,7 +952,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(directory,path); pstrcpy(dir2,path); - nt_status = unix_convert(conn, directory, mask_contains_wcard, NULL, &sbuf); + nt_status = unix_convert(conn, directory, True, NULL, &sbuf); if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); return ERROR_NT(nt_status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2cfb692b02..7bdecd45ca 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1718,7 +1718,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf); - ntstatus = unix_convert(conn, directory, mask_contains_wcard, NULL, &sbuf); + ntstatus = unix_convert(conn, directory, True, NULL, &sbuf); if (!NT_STATUS_IS_OK(ntstatus)) { return ERROR_NT(ntstatus); } -- cgit From 50b3dacb525d026dd7d280948d8a63075756d029 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 02:13:45 +0000 Subject: r20722: RAW-CHKPATH should now pass, build farm should go back to normal. Sorry about that. Jeremy. (This used to be commit d4127034fb89185fe7464d57c9f56f7914da6141) --- source3/smbd/filename.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index dd1e0de20f..a36b7ff282 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -391,15 +391,24 @@ NTSTATUS unix_convert(connection_struct *conn, * Windows applications depend on the difference between * these two errors. */ - if (errno == ENOENT) { + + /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND + in the filename walk. */ + + if (errno == ENOENT || errno == ENOTDIR) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } return map_nt_error_from_unix(errno); } - if (errno == ENOTDIR) { - /* Name exists but is not a directory. */ - return map_nt_error_from_unix(ENOTDIR); + /* ENOENT is the only valid error here. */ + if (errno != ENOENT) { + /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND + in the filename walk. */ + if (errno == ENOTDIR) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + return map_nt_error_from_unix(errno); } /* -- cgit From 67b0f18f62049013cd220912d66c9029ccbda26b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 02:34:43 +0000 Subject: r20724: Get closer to passing RAW-OPEN. If the client is using create disposition of FILE_CREATE then there's no need to check can_delete_file_in_directory(). Jeremy. (This used to be commit eb32b60efc4c332295ff6fc7e5d575f4b40e8ff6) --- source3/smbd/nttrans.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 94bf363fc7..28d7a169a8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -640,20 +640,19 @@ int reply_ntcreate_and_X(connection_struct *conn, return UNIXERROR(ERRDOS,ERRbadpath); } -#if 0 /* This is the correct thing to do (check every time) but can_delete is expensive (it may have to read the parent directory permissions). So for now we're not doing it unless we have a strong hint the client - is really going to delete this file. */ - if ((desired_access & DELETE_ACCESS) - && !can_delete_file_in_directory(conn, fname)) { -#else + is really going to delete this file. If the client is forcing FILE_CREATE + let the filesystem take care of the permissions. */ + /* Setting FILE_SHARE_DELETE is the hint. */ + if (lp_acl_check_permissions(SNUM(conn)) + && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS) && !can_delete_file_in_directory(conn, fname)) { -#endif restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_ACCESS_DENIED); @@ -1265,20 +1264,19 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return UNIXERROR(ERRDOS,ERRbadpath); } -#if 0 /* This is the correct thing to do (check every time) but can_delete is expensive (it may have to read the parent directory permissions). So for now we're not doing it unless we have a strong hint the client - is really going to delete this file. */ - if ((desired_access & DELETE_ACCESS) - && !can_delete_file_in_directory(conn, fname)) { -#else + is really going to delete this file. If the client is forcing FILE_CREATE + let the filesystem take care of the permissions. */ + /* Setting FILE_SHARE_DELETE is the hint. */ + if (lp_acl_check_permissions(SNUM(conn)) + && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS) && !can_delete_file_in_directory(conn, fname)) { -#endif restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_ACCESS_DENIED); } -- cgit From 165e08e8b1efa55b4548e1853a637e1696e4fd7b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 13 Jan 2007 20:26:53 +0000 Subject: r20740: Get rid of some if-statements (This used to be commit db93c1b98d5445071ad0af229afed1f11ab0a862) --- source3/smbd/reply.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 21c8b13b5c..7d89382a7d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -45,18 +45,16 @@ extern BOOL global_encrypted_passwords_negotiated; ****************************************************************************/ NTSTATUS check_path_syntax_internal(pstring destname, - const pstring srcname, - BOOL windows_path, BOOL - *p_last_component_contains_wcard) + const pstring srcname, + BOOL windows_path, + BOOL *p_last_component_contains_wcard) { char *d = destname; const char *s = srcname; NTSTATUS ret = NT_STATUS_OK; BOOL start_of_name_component = True; - if (p_last_component_contains_wcard) { - *p_last_component_contains_wcard = False; - } + *p_last_component_contains_wcard = False; while (*s) { if (IS_DIRECTORY_SEP(*s)) { @@ -74,9 +72,7 @@ NTSTATUS check_path_syntax_internal(pstring destname, start_of_name_component = True; /* New component. */ - if (p_last_component_contains_wcard) { - *p_last_component_contains_wcard = False; - } + *p_last_component_contains_wcard = False; continue; } @@ -132,9 +128,7 @@ NTSTATUS check_path_syntax_internal(pstring destname, case '<': case '>': case '"': - if (p_last_component_contains_wcard) { - *p_last_component_contains_wcard = True; - } + *p_last_component_contains_wcard = True; break; default: break; @@ -181,7 +175,8 @@ NTSTATUS check_path_syntax_internal(pstring destname, NTSTATUS check_path_syntax(pstring destname, const pstring srcname) { - return check_path_syntax_internal(destname, srcname, True, NULL); + BOOL ignore; + return check_path_syntax_internal(destname, srcname, True, &ignore); } /**************************************************************************** @@ -203,7 +198,8 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) { - return check_path_syntax_internal(destname, srcname, False, NULL); + BOOL ignore; + return check_path_syntax_internal(destname, srcname, False, &ignore); } /**************************************************************************** -- cgit From ab46f9cdd232cc08b4c2f57c3fe7add652f6ce38 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 22:10:18 +0000 Subject: r20742: Rename chkpth -> checkpath for sanity's sake :-). Start removing unneeded "BOOL ok" from this reply.c (this logic is old, old, old..... :-). Jeremy. (This used to be commit 3d52268095c605a80dfcd371769198a332baa0a5) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 70 +++++++++++++++++++++++++------------------------- 2 files changed, 36 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ecb33453c5..929471a48c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -620,7 +620,7 @@ static const struct smb_message_struct { /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER}, /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER }, /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, -/* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER}, +/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER}, /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR}, /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER}, /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7d89382a7d..9fa359de8c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -596,57 +596,58 @@ int reply_ioctl(connection_struct *conn, } /**************************************************************************** - Reply to a chkpth. + Strange checkpath NTSTATUS mapping. ****************************************************************************/ -int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status) +{ + /* Strange DOS error code semantics only for checkpath... */ + if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) { + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) { + /* We need to map to ERRbadpath */ + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } + return status; +} + +/**************************************************************************** + Reply to a checkpath. +****************************************************************************/ + +int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = 0; pstring name; - BOOL ok = False; SMB_STRUCT_STAT sbuf; NTSTATUS status; - START_PROFILE(SMBchkpth); + START_PROFILE(SMBcheckpath); srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBchkpth); - - /* Strange DOS error code semantics only for chkpth... */ - if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) { - if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) { - /* We need to map to ERRbadpath */ - status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - } + END_PROFILE(SMBcheckpath); + status = map_checkpath_error(inbuf, status); return ERROR_NT(status); } RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); + status = unix_convert(conn, name, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBchkpth); - /* Strange DOS error code semantics only for chkpth... */ - if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) { - if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) { - /* We need to map to ERRbadpath */ - status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - } + END_PROFILE(SMBcheckpath); + status = map_checkpath_error(inbuf, status); return ERROR_NT(status); } - if (check_name(name,conn)) { - if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) - if (!(ok = S_ISDIR(sbuf.st_mode))) { - END_PROFILE(SMBchkpth); - return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); - } - } - - if (!ok) { + if (check_name(name,conn) && (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)) { + if (!S_ISDIR(sbuf.st_mode)) { + END_PROFILE(SMBcheckpath); + return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); + } + } else { /* We special case this - as when a Windows machine is parsing a path is steps through the components one at a time - if a component fails it expects @@ -660,19 +661,18 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND * if the path is invalid. */ - END_PROFILE(SMBchkpth); + END_PROFILE(SMBcheckpath); return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); } - END_PROFILE(SMBchkpth); + END_PROFILE(SMBcheckpath); return(UNIXERROR(ERRDOS,ERRbadpath)); } outsize = set_message(outbuf,0,0,False); - DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); - END_PROFILE(SMBchkpth); - return(outsize); + END_PROFILE(SMBcheckpath); + return outsize; } /**************************************************************************** -- cgit From 78fbb597c2101c57c214e6ec0f83285bcf0954eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 13 Jan 2007 22:22:32 +0000 Subject: r20743: Remove another BOOL ok from reply_getatr. Jeremy. (This used to be commit c154f430710a4646fac42774817dfed7b936b087) --- source3/smbd/reply.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9fa359de8c..af183b1fff 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -684,7 +684,6 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring fname; int outsize = 0; SMB_STRUCT_STAT sbuf; - BOOL ok = False; int mode=0; SMB_OFF_T size=0; time_t mtime=0; @@ -704,38 +703,34 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ - if (! (*fname)) { + if (*fname == '\0') { mode = aHIDDEN | aDIR; - if (!CAN_WRITE(conn)) + if (!CAN_WRITE(conn)) { mode |= aRONLY; + } size = 0; mtime = 0; - ok = True; } else { status = unix_convert(conn, fname, False, NULL,&sbuf); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBgetatr); return ERROR_NT(status); } - if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) { - mode = dos_mode(conn,fname,&sbuf); - size = sbuf.st_size; - mtime = sbuf.st_mtime; - if (mode & aDIR) - size = 0; - ok = True; - } else { - DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); + if (check_name(fname,conn) && + (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0)) { + mode = dos_mode(conn,fname,&sbuf); + size = sbuf.st_size; + mtime = sbuf.st_mtime; + if (mode & aDIR) { + size = 0; } + } else { + DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno))); + END_PROFILE(SMBgetatr); + return UNIXERROR(ERRDOS,ERRbadfile); } } - if (!ok) { - END_PROFILE(SMBgetatr); - return UNIXERROR(ERRDOS,ERRbadfile); - } - outsize = set_message(outbuf,10,0,True); SSVAL(outbuf,smb_vwv0,mode); @@ -750,7 +745,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); } - DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); + DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) ); END_PROFILE(SMBgetatr); return(outsize); -- cgit From fb9a229643015fc6fea67bac9317f5d6a6283fc4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 14 Jan 2007 11:25:42 +0000 Subject: r20759: Dummy checkin to let the build farm pick up the new smbtorture4 (This used to be commit 14c88b560e5c8fd59b84333e92337805620ccd7c) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index af183b1fff..02cada71aa 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -59,7 +59,8 @@ NTSTATUS check_path_syntax_internal(pstring destname, while (*s) { if (IS_DIRECTORY_SEP(*s)) { /* - * Safe to assume is not the second part of a mb char as this is handled below. + * Safe to assume is not the second part of a mb char + * as this is handled below. */ /* Eat multiple '/' or '\\' */ while (IS_DIRECTORY_SEP(*s)) { -- cgit From 916342d04bdac47818863d64cf2118fe456210e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 14 Jan 2007 19:43:06 +0000 Subject: r20781: Fix a couple of paths found by Volker where we weren't correctly handling deferred opens. Jeremy. (This used to be commit e47b79d1cef279a1de1128d114d423c1fd2b1e8d) --- source3/smbd/nttrans.c | 8 +++++++- source3/smbd/trans2.c | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 28d7a169a8..df65ad7da6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1853,8 +1853,14 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o status = rename_internals(conn, fsp->fsp_name, new_name, 0, replace_if_exists, path_contains_wcard); - if (!NT_STATUS_IS_OK(status)) + + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return ERROR_NT(status); + } /* * Rename was successful. diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7bdecd45ca..48a5a0c1ac 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4459,9 +4459,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", fname, newname )); status = rename_internals(conn, fname, base_name, 0, overwrite, False); } + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } return ERROR_NT(status); } + process_pending_change_notify_queue((time_t)0); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); -- cgit From 0cfc6a8e11bf1d2dd80861cf5331f4cde78dd674 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 15 Jan 2007 09:17:11 +0000 Subject: r20796: Fix the same problem Jeremy has fixed (improper handling of deferred opens) for delete_driver_files. Proper fix pending... :-) Jeremy, please check. Volker (This used to be commit 21b8f15dd5ad567efeacf5ba22dc4d8c64b09b76) --- source3/smbd/reply.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 02cada71aa..3a1514f1aa 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1679,7 +1679,8 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, Check if a user is allowed to delete a file. ********************************************************************/ -static NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype) +static NTSTATUS can_delete(connection_struct *conn, char *fname, + uint32 dirtype, BOOL can_defer) { SMB_STRUCT_STAT sbuf; uint32 fattr; @@ -1777,7 +1778,7 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype) FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - 0, + can_defer ? 0 : INTERNAL_OPEN_ONLY, NULL, &fsp); if (NT_STATUS_IS_OK(status)) { @@ -1791,7 +1792,8 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype) code. ****************************************************************************/ -NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild) +NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, + char *name, BOOL has_wild, BOOL can_defer) { pstring directory; pstring mask; @@ -1835,7 +1837,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B if (dirtype == 0) { dirtype = FILE_ATTRIBUTE_NORMAL; } - status = can_delete(conn,directory,dirtype); + status = can_delete(conn,directory,dirtype,can_defer); if (!NT_STATUS_IS_OK(status)) return status; @@ -1885,7 +1887,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B continue; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - status = can_delete(conn, fname, dirtype); + status = can_delete(conn, fname, dirtype, + can_defer); if (!NT_STATUS_IS_OK(status)) { continue; } @@ -1931,7 +1934,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - status = unlink_internals(conn, dirtype, name, path_contains_wcard); + status = unlink_internals(conn, dirtype, name, path_contains_wcard, + True); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ -- cgit From def7b0bca194502832192270322c6232622ee48e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 16 Jan 2007 15:50:25 +0000 Subject: r20833: Reformatting (This used to be commit 2c2d5308a23df0b6b078bc647ad550c43b51ee1e) --- source3/smbd/oplock_irix.c | 64 +++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index b62975dd27..c1159cd73b 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -38,16 +38,19 @@ static BOOL irix_oplocks_available(void) set_effective_capability(KERNEL_OPLOCK_CAPABILITY); - slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid()); + slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), + (int)sys_getpid()); if(pipe(pfd) != 0) { - DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n", + DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error " + "was %s\n", strerror(errno) )); return False; } if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) { - DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n", + DEBUG(0,("check_kernel_oplocks: Unable to open temp test file " + "%s. Error was %s\n", tmpname, strerror(errno) )); unlink( tmpname ); close(pfd[0]); @@ -58,8 +61,9 @@ static BOOL irix_oplocks_available(void) unlink(tmpname); if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) { - DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \ -Disabling kernel oplock support.\n" )); + DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not " + "available on this machine. Disabling kernel oplock " + "support.\n" )); close(pfd[0]); close(pfd[1]); close(fd); @@ -67,8 +71,9 @@ Disabling kernel oplock support.\n" )); } if(sys_fcntl_long(fd, F_OPLKACK, OP_REVOKE) < 0 ) { - DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \ -Disabling kernel oplock support.\n", strerror(errno) )); + DEBUG(0,("check_kernel_oplocks: Error when removing kernel " + "oplock. Error was %s. Disabling kernel oplock " + "support.\n", strerror(errno) )); close(pfd[0]); close(pfd[1]); close(fd); @@ -145,7 +150,8 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) DEBUG(5,("irix_oplock_receive_message: kernel oplock break request " "received for dev = %x, inode = %.0f\n, file_id = %ul", - (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id )); + (unsigned int)fsp->dev, (double)fsp->inode, + fsp->fh->file_id )); return fsp; } @@ -158,20 +164,28 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) { if(errno != EAGAIN) { - DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \ -inode = %.0f, file_id = %ul. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id, + DEBUG(0,("irix_set_kernel_oplock: Unable to get " + "kernel oplock on file %s, dev = %x, inode " + "= %.0f, file_id = %ul. Error was %s\n", + fsp->fsp_name, (unsigned int)fsp->dev, + (double)fsp->inode, fsp->fh->file_id, strerror(errno) )); } else { - DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ -inode = %.0f, file_id = %ul. Another process had the file open.\n", - fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id )); + DEBUG(5,("irix_set_kernel_oplock: Refused oplock on " + "file %s, fd = %d, dev = %x, inode = %.0f, " + "file_id = %ul. Another process had the file " + "open.\n", + fsp->fsp_name, fsp->fh->fd, + (unsigned int)fsp->dev, (double)fsp->inode, + fsp->fh->file_id )); } return False; } - DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id)); + DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev " + "= %x, inode = %.0f, file_id = %ul\n", + fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, + fsp->fh->file_id)); return True; } @@ -188,8 +202,9 @@ static void irix_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); - dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \ -oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, + dbgtext("irix_release_kernel_oplock: file %s, dev = %x, " + "inode = %.0f file_id = %ul, has kernel oplock state " + "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id, state ); } @@ -198,10 +213,13 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, */ if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) { if( DEBUGLVL( 0 )) { - dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n", + dbgtext("irix_release_kernel_oplock: Error when " + "removing kernel oplock on file " ); + dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. " + "Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, strerror(errno) ); + (double)fsp->inode, fsp->fh->file_id, + strerror(errno) ); } } } @@ -249,8 +267,8 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void) return NULL; if(pipe(pfd) != 0) { - DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n", - strerror(errno) )); + DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. " + "Error was %s\n", strerror(errno) )); return False; } -- cgit From 6d16226a2d449ab7731bc686a742a2b31ccf41ae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Jan 2007 20:32:39 +0000 Subject: r20840: Keep removing the old BOOL ok logic. Jeremy. (This used to be commit 224ff059915b2c92ec86d2c3c4b10c3bc552ffa2) --- source3/smbd/reply.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3a1514f1aa..d48c081e21 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3677,11 +3677,15 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) BOOL rmdir_internals(connection_struct *conn, const char *directory) { - BOOL ok; + int ret; SMB_STRUCT_STAT st; - ok = (SMB_VFS_RMDIR(conn,directory) == 0); - if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { + ret = SMB_VFS_RMDIR(conn,directory); + if (ret == 0) { + return True; + } + + if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { /* * Check to see if the only thing in this directory are * vetoed files/directories. If so then delete them and @@ -3744,12 +3748,12 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) } CloseDir(dir_hnd); /* Retry the rmdir */ - ok = (SMB_VFS_RMDIR(conn,directory) == 0); + ret = SMB_VFS_RMDIR(conn,directory); } err: - if (!ok) { + if (ret != 0) { DEBUG(3,("rmdir_internals: couldn't remove directory %s : " "%s\n", directory,strerror(errno))); return False; -- cgit From 16f96517f1f51fb9a8fd75e513bb985bf152adae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Jan 2007 20:49:51 +0000 Subject: r20841: Remove more BOOL ok. Jeremy. (This used to be commit c6b651966039b1c21facd4c4789bf873b5b49426) --- source3/smbd/reply.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d48c081e21..f633be3740 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3770,7 +3770,6 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, { pstring directory; int outsize = 0; - BOOL ok = False; SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBrmdir); @@ -3789,12 +3788,13 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (check_name(directory,conn)) { - dptr_closepath(directory,SVAL(inbuf,smb_pid)); - ok = rmdir_internals(conn, directory); + if (!check_name(directory,conn)) { + END_PROFILE(SMBrmdir); + return UNIXERROR(ERRDOS, ERRbadpath); } - - if (!ok) { + + dptr_closepath(directory,SVAL(inbuf,smb_pid)); + if (!rmdir_internals(conn, directory)) { END_PROFILE(SMBrmdir); return UNIXERROR(ERRDOS, ERRbadpath); } -- cgit From f065b42dcceb4eb64b26921aaa88d7a67bac3dc0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Jan 2007 20:53:50 +0000 Subject: r20842: Only one more BOOL ok to go... Jeremy. (This used to be commit de0bf477dab1d57b5f7bc6bf70d8e76f9bfac63f) --- source3/smbd/reply.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f633be3740..c90c59698f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4755,7 +4755,6 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size { int snum; int outsize = 0; - BOOL ok = False; pstring newdir; NTSTATUS status; @@ -4775,17 +4774,12 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf); - if (strlen(newdir) == 0) { - ok = True; - } else { - ok = vfs_directory_exist(conn,newdir,NULL); - if (ok) - set_conn_connectpath(conn,newdir); - } - - if (!ok) { - END_PROFILE(pathworks_setdir); - return ERROR_DOS(ERRDOS,ERRbadpath); + if (strlen(newdir) != 0) { + if (!vfs_directory_exist(conn,newdir,NULL)) { + END_PROFILE(pathworks_setdir); + return ERROR_DOS(ERRDOS,ERRbadpath); + } + set_conn_connectpath(conn,newdir); } outsize = set_message(outbuf,0,0,False); -- cgit From 52a36db39fb96353702616dfac5004239c34cd2c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Jan 2007 21:04:30 +0000 Subject: r20843: Get rid of last BOOL ok. Jeremy. (This used to be commit a36d446fb612f87654c645f6507d413b95efaf21) --- source3/smbd/reply.c | 117 ++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 58 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c90c59698f..9a0e544e38 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -895,14 +895,12 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unsigned int maxentries = 0; BOOL finished = False; char *p; - BOOL ok = False; int status_len; pstring path; char status[21]; int dptr_num= -1; BOOL check_descend = False; BOOL expect_close = False; - BOOL can_open = True; NTSTATUS nt_status; BOOL mask_contains_wcard = False; BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; @@ -917,8 +915,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size *mask = *directory = *fname = 0; /* If we were called as SMBffirst then we must expect close. */ - if(CVAL(inbuf,smb_com) == SMBffirst) + if(CVAL(inbuf,smb_com) == SMBffirst) { expect_close = True; + } outsize = set_message(outbuf,1,3,True); maxentries = SVAL(inbuf,smb_vwv0); @@ -951,8 +950,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } unix_format(dir2); - if (!check_name(directory,conn)) - can_open = False; + if (!check_name(directory,conn)) { + END_PROFILE(SMBsearch); + return UNIXERROR(ERRDOS, ERRnoaccess); + } p = strrchr_m(dir2,'/'); if (p == NULL) { @@ -964,13 +965,15 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } p = strrchr_m(directory,'/'); - if (!p) + if (!p) { *directory = 0; - else + } else { *p = 0; + } - if (strlen(directory) == 0) + if (strlen(directory) == 0) { pstrcpy(directory,"."); + } memset((char *)status,'\0',21); SCVAL(status,0,(dirtype & 0x1F)); } else { @@ -978,83 +981,81 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size memcpy(status,p,21); status_dirtype = CVAL(status,0) & 0x1F; - if (status_dirtype != (dirtype & 0x1F)) + if (status_dirtype != (dirtype & 0x1F)) { dirtype = status_dirtype; + } conn->dirptr = dptr_fetch(status+12,&dptr_num); - if (!conn->dirptr) + if (!conn->dirptr) { goto SearchEmpty; + } string_set(&conn->dirpath,dptr_path(dptr_num)); pstrcpy(mask, dptr_wcard(dptr_num)); } - if (can_open) { - p = smb_buf(outbuf) + 3; - ok = True; + p = smb_buf(outbuf) + 3; - if (status_len == 0) { - dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype); - if (dptr_num < 0) { - if(dptr_num == -2) { - END_PROFILE(SMBsearch); - return UNIXERROR(ERRDOS, ERRnofids); - } + if (status_len == 0) { + dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype); + if (dptr_num < 0) { + if(dptr_num == -2) { END_PROFILE(SMBsearch); - return ERROR_DOS(ERRDOS,ERRnofids); + return UNIXERROR(ERRDOS, ERRnofids); } + END_PROFILE(SMBsearch); + return ERROR_DOS(ERRDOS,ERRnofids); + } + } else { + dirtype = dptr_attr(dptr_num); + } + + DEBUG(4,("dptr_num is %d\n",dptr_num)); + + if ((dirtype&0x1F) == aVOLID) { + memcpy(p,status,21); + make_dir_struct(p,"???????????",volume_label(SNUM(conn)), + 0,aVOLID,0,!allow_long_path_components); + dptr_fill(p+12,dptr_num); + if (dptr_zero(p+12) && (status_len==0)) { + numentries = 1; } else { - dirtype = dptr_attr(dptr_num); + numentries = 0; } + p += DIR_STRUCT_SIZE; + } else { + unsigned int i; + maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE)); - DEBUG(4,("dptr_num is %d\n",dptr_num)); + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", + conn->dirpath,lp_dontdescend(SNUM(conn)))); + if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) { + check_descend = True; + } - if (ok) { - if ((dirtype&0x1F) == aVOLID) { + for (i=numentries;(i dontdescend=<%s>\n", - conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) - check_descend = True; - - for (i=numentries;(i Date: Wed, 17 Jan 2007 02:09:37 +0000 Subject: r20844: Somewhat radical change - this may break the build (I will watch carefully - so I'm doing it in one transaction so I can roll back). Change check_name(), reduce_name() and dptr_create() to return NTSTATUS. This helps a lot in error path processing and especially in reduce_name() allows us to ditch the flaky and error-prone saving of errno and return errors directly. Jeremy. (This used to be commit 6133a694aa429d638320e39ffe1c49d172583ccf) --- source3/smbd/dir.c | 31 ++-- source3/smbd/filename.c | 21 ++- source3/smbd/nttrans.c | 28 ++-- source3/smbd/reply.c | 389 ++++++++++++++++++++++++++---------------------- source3/smbd/trans2.c | 54 ++++--- source3/smbd/vfs.c | 40 +++-- 6 files changed, 306 insertions(+), 257 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5a6b9713e5..7be5c03f1b 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -382,21 +382,26 @@ static void dptr_close_oldest(BOOL old) wcard must not be zero. ****************************************************************************/ -int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, - const char *wcard, BOOL wcard_has_wild, uint32 attr) +NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, + const char *wcard, BOOL wcard_has_wild, uint32 attr, int *dptr_hnd_ret) { struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; const char *dir2; + NTSTATUS status; DEBUG(5,("dptr_create dir=%s\n", path)); + *dptr_hnd_ret = -1; + if (!wcard) { - return -1; + return NT_STATUS_INVALID_PARAMETER; } - if (!check_name(path,conn)) - return(-2); /* Code to say use a unix error return code. */ + status = check_name(conn,path); + if (!NT_STATUS_IS_OK(status)) { + return status; + } /* use a const pointer from here on */ dir2 = path; @@ -405,19 +410,20 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp dir_hnd = OpenDir(conn, dir2, wcard, attr); if (!dir_hnd) { - return (-2); + return map_nt_error_from_unix(errno); } string_set(&conn->dirpath,dir2); - if (dirhandles_open >= MAX_OPEN_DIRECTORIES) + if (dirhandles_open >= MAX_OPEN_DIRECTORIES) { dptr_idleoldest(); + } dptr = SMB_MALLOC_P(struct dptr_struct); if(!dptr) { DEBUG(0,("malloc fail in dptr_create.\n")); CloseDir(dir_hnd); - return -1; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(dptr); @@ -447,7 +453,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); CloseDir(dir_hnd); - return -1; + return NT_STATUS_TOO_MANY_OPENED_FILES; } } } else { @@ -477,7 +483,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); CloseDir(dir_hnd); - return -1; + return NT_STATUS_TOO_MANY_OPENED_FILES; } } } @@ -496,7 +502,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp bitmap_clear(dptr_bmap, dptr->dnum - 1); SAFE_FREE(dptr); CloseDir(dir_hnd); - return -1; + return NT_STATUS_NO_MEMORY; } if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { dptr->has_wild = True; @@ -513,7 +519,8 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp conn->dirptr = dptr; - return(dptr->dnum); + *dptr_hnd_ret = dptr->dnum; + return NT_STATUS_OK; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a36b7ff282..b69d2f3e5e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -512,28 +512,25 @@ NTSTATUS unix_convert(connection_struct *conn, a valid one for the user to access. ****************************************************************************/ -BOOL check_name(const pstring name,connection_struct *conn) +NTSTATUS check_name(connection_struct *conn, const pstring name) { - BOOL ret = True; - if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { - DEBUG(5,("file path name %s vetoed\n",name)); - errno = ENOENT; - return False; + DEBUG(5,("check_name: file path name %s vetoed\n",name)); + return map_nt_error_from_unix(ENOENT); } } if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { - ret = reduce_name(conn,name); - } - - if (!ret) { - DEBUG(5,("check_name on %s failed\n",name)); + NTSTATUS status = reduce_name(conn,name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status))); + return status; + } } - return(ret); + return NT_STATUS_OK; } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index df65ad7da6..f4d6220592 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -634,10 +634,11 @@ int reply_ntcreate_and_X(connection_struct *conn, return ERROR_NT(status); } /* All file access must go through check_name() */ - if (!check_name(fname,conn)) { + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return UNIXERROR(ERRDOS,ERRbadpath); + return ERROR_NT(status); } /* This is the correct thing to do (check every time) but can_delete is @@ -1259,9 +1260,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(status); } /* All file access must go through check_name() */ - if (!check_name(fname,conn)) { + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); - return UNIXERROR(ERRDOS,ERRbadpath); + return ERROR_NT(status); } /* This is the correct thing to do (check every time) but can_delete is @@ -1570,8 +1572,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - if (!CAN_WRITE(conn)) + if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; + } status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1); if (!NT_STATUS_IS_OK(status)) { @@ -1582,8 +1585,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new if (!VALID_STAT(sbuf1)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (!check_name(oldname,conn)) { - return NT_STATUS_ACCESS_DENIED; + status = check_name(conn, oldname); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Ensure attributes match. */ @@ -1602,8 +1606,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return NT_STATUS_OBJECT_NAME_COLLISION; } - if (!check_name(newname,conn)) { - return NT_STATUS_ACCESS_DENIED; + status = check_name(conn, newname); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* No links from a directory. */ @@ -1612,8 +1617,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new } /* Ensure this is within the share. */ - if (!reduce_name(conn, oldname) != 0) { - return NT_STATUS_ACCESS_DENIED; + status = reduce_name(conn, oldname); + if (!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9a0e544e38..2d11b3db98 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -638,42 +638,53 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s status = unix_convert(conn, name, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBcheckpath); - status = map_checkpath_error(inbuf, status); - return ERROR_NT(status); + goto path_err; } - if (check_name(name,conn) && (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)) { - if (!S_ISDIR(sbuf.st_mode)) { - END_PROFILE(SMBcheckpath); - return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); - } - } else { - /* We special case this - as when a Windows machine - is parsing a path is steps through the components - one at a time - if a component fails it expects - ERRbadpath, not ERRbadfile. - */ - if(errno == ENOENT) { - /* - * Windows returns different error codes if - * the parent directory is valid but not the - * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND - * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND - * if the path is invalid. - */ - END_PROFILE(SMBcheckpath); - return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); - } + status = check_name(conn, name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status))); + goto path_err; + } + + if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) { + DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno))); + status = map_nt_error_from_unix(errno); + goto path_err; + } + if (!S_ISDIR(sbuf.st_mode)) { END_PROFILE(SMBcheckpath); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); } outsize = set_message(outbuf,0,0,False); END_PROFILE(SMBcheckpath); return outsize; + + path_err: + + END_PROFILE(SMBcheckpath); + + /* We special case this - as when a Windows machine + is parsing a path is steps through the components + one at a time - if a component fails it expects + ERRbadpath, not ERRbadfile. + */ + status = map_checkpath_error(inbuf, status); + if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + /* + * Windows returns different error codes if + * the parent directory is valid but not the + * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND + * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND + * if the path is invalid. + */ + return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); + } + + return ERROR_NT(status); } /**************************************************************************** @@ -717,19 +728,23 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBgetatr); return ERROR_NT(status); } - if (check_name(fname,conn) && - (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0)) { - mode = dos_mode(conn,fname,&sbuf); - size = sbuf.st_size; - mtime = sbuf.st_mtime; - if (mode & aDIR) { - size = 0; - } - } else { - DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno))); + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status))); END_PROFILE(SMBgetatr); + return ERROR_NT(status); + } + if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) { + DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno))); return UNIXERROR(ERRDOS,ERRbadfile); } + + mode = dos_mode(conn,fname,&sbuf); + size = sbuf.st_size; + mtime = sbuf.st_mtime; + if (mode & aDIR) { + size = 0; + } } outsize = set_message(outbuf,10,0,True); @@ -792,9 +807,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(NT_STATUS_ACCESS_DENIED); } - if (!check_name(fname,conn)) { + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsetatr); - return UNIXERROR(ERRDOS, ERRnoaccess); + return ERROR_NT(status); } mode = SVAL(inbuf,smb_vwv0); @@ -950,9 +966,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } unix_format(dir2); - if (!check_name(directory,conn)) { + nt_status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); - return UNIXERROR(ERRDOS, ERRnoaccess); + return ERROR_NT(nt_status); } p = strrchr_m(dir2,'/'); @@ -996,14 +1013,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size p = smb_buf(outbuf) + 3; if (status_len == 0) { - dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype); - if (dptr_num < 0) { - if(dptr_num == -2) { - END_PROFILE(SMBsearch); - return UNIXERROR(ERRDOS, ERRnofids); - } - END_PROFILE(SMBsearch); - return ERROR_DOS(ERRDOS,ERRnofids); + nt_status = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype,&dptr_num); + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status); } } else { dirtype = dptr_attr(dptr_num); @@ -1839,66 +1851,73 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, dirtype = FILE_ATTRIBUTE_NORMAL; } status = can_delete(conn,directory,dirtype,can_defer); - if (!NT_STATUS_IS_OK(status)) + if (!NT_STATUS_IS_OK(status)) { return status; + } if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; } } else { struct smb_Dir *dir_hnd = NULL; + long offset = 0; const char *dname; if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) { return NT_STATUS_OBJECT_NAME_INVALID; } - if (strequal(mask,"????????.???")) + if (strequal(mask,"????????.???")) { pstrcpy(mask,"*"); + } + + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory, mask, dirtype); + dir_hnd = OpenDir(conn, directory, mask, dirtype); + if (dir_hnd == NULL) { + return map_nt_error_from_unix(errno); + } /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name We don't implement this yet XXXX */ - if (dir_hnd) { - long offset = 0; - status = NT_STATUS_NO_SUCH_FILE; + status = NT_STATUS_NO_SUCH_FILE; - while ((dname = ReadDirName(dir_hnd, &offset))) { - SMB_STRUCT_STAT st; - pstring fname; - pstrcpy(fname,dname); + while ((dname = ReadDirName(dir_hnd, &offset))) { + SMB_STRUCT_STAT st; + pstring fname; + pstrcpy(fname,dname); - if (!is_visible_file(conn, directory, dname, &st, True)) { - continue; - } + if (!is_visible_file(conn, directory, dname, &st, True)) { + continue; + } - /* Quick check for "." and ".." */ - if (fname[0] == '.') { - if (!fname[1] || (fname[1] == '.' && !fname[2])) { - continue; - } + /* Quick check for "." and ".." */ + if (fname[0] == '.') { + if (!fname[1] || (fname[1] == '.' && !fname[2])) { + continue; } + } - if(!mask_match(fname, mask, conn->case_sensitive)) - continue; + if(!mask_match(fname, mask, conn->case_sensitive)) { + continue; + } - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - status = can_delete(conn, fname, dirtype, - can_defer); - if (!NT_STATUS_IS_OK(status)) { - continue; - } - if (SMB_VFS_UNLINK(conn,fname) == 0) - count++; - DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + status = can_delete(conn, fname, dirtype, can_defer); + if (!NT_STATUS_IS_OK(status)) { + continue; } - CloseDir(dir_hnd); + if (SMB_VFS_UNLINK(conn,fname) == 0) + count++; + DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } + CloseDir(dir_hnd); } if (count == 0 && NT_STATUS_IS_OK(status)) { @@ -3789,9 +3808,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (!check_name(directory,conn)) { + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); - return UNIXERROR(ERRDOS, ERRbadpath); + return ERROR_NT(status); } dptr_closepath(directory,SVAL(inbuf,smb_pid)); @@ -4267,10 +4287,11 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } TALLOC_FREE(lck); - if (errno == ENOTDIR || errno == EISDIR) + if (errno == ENOTDIR || errno == EISDIR) { status = NT_STATUS_OBJECT_NAME_COLLISION; - else + } else { status = map_nt_error_from_unix(errno); + } DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", nt_errstr(status), directory,newname)); @@ -4282,98 +4303,105 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", */ struct smb_Dir *dir_hnd = NULL; const char *dname; + long offset = 0; pstring destname; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory, mask, attrs); + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + dir_hnd = OpenDir(conn, directory, mask, attrs); + if (dir_hnd == NULL) { + return map_nt_error_from_unix(errno); + } - if (dir_hnd) { - long offset = 0; - status = NT_STATUS_NO_SUCH_FILE; -/* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ + status = NT_STATUS_NO_SUCH_FILE; +/* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ - while ((dname = ReadDirName(dir_hnd, &offset))) { - pstring fname; - BOOL sysdir_entry = False; + while ((dname = ReadDirName(dir_hnd, &offset))) { + pstring fname; + BOOL sysdir_entry = False; - pstrcpy(fname,dname); + pstrcpy(fname,dname); - /* Quick check for "." and ".." */ - if (fname[0] == '.') { - if (!fname[1] || (fname[1] == '.' && !fname[2])) { - if (attrs & aDIR) { - sysdir_entry = True; - } else { - continue; - } + /* Quick check for "." and ".." */ + if (fname[0] == '.') { + if (!fname[1] || (fname[1] == '.' && !fname[2])) { + if (attrs & aDIR) { + sysdir_entry = True; + } else { + continue; } } + } - if (!is_visible_file(conn, directory, dname, &sbuf1, False)) - continue; + if (!is_visible_file(conn, directory, dname, &sbuf1, False)) { + continue; + } - if(!mask_match(fname, mask, conn->case_sensitive)) - continue; + if(!mask_match(fname, mask, conn->case_sensitive)) { + continue; + } - if (sysdir_entry) { - status = NT_STATUS_OBJECT_NAME_INVALID; - break; - } + if (sysdir_entry) { + status = NT_STATUS_OBJECT_NAME_INVALID; + break; + } - status = NT_STATUS_ACCESS_DENIED; - slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); - if (!vfs_object_exist(conn, fname, &sbuf1)) { - status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status))); - continue; - } - status = can_rename(conn,fname,attrs,&sbuf1); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(6,("rename %s refused\n", fname)); - continue; - } - pstrcpy(destname,newname); - - if (!resolve_wildcards(fname,destname)) { - DEBUG(6,("resolve_wildcards %s %s failed\n", - fname, destname)); - continue; - } + status = NT_STATUS_ACCESS_DENIED; + slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); + if (!vfs_object_exist(conn, fname, &sbuf1)) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status))); + continue; + } + status = can_rename(conn,fname,attrs,&sbuf1); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(6,("rename %s refused\n", fname)); + continue; + } + pstrcpy(destname,newname); + + if (!resolve_wildcards(fname,destname)) { + DEBUG(6,("resolve_wildcards %s %s failed\n", + fname, destname)); + continue; + } - if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); - DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); - count++; - status = NT_STATUS_OK; - continue; - } + if (strcsequal(fname,destname)) { + rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); + DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); + count++; + status = NT_STATUS_OK; + continue; + } - if (!replace_if_exists && - vfs_file_exist(conn,destname, NULL)) { - DEBUG(6,("file_exist %s\n", destname)); - status = NT_STATUS_OBJECT_NAME_COLLISION; - continue; - } + if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) { + DEBUG(6,("file_exist %s\n", destname)); + status = NT_STATUS_OBJECT_NAME_COLLISION; + continue; + } - if (rename_path_prefix_equal(fname, destname)) { - return NT_STATUS_SHARING_VIOLATION; - } + if (rename_path_prefix_equal(fname, destname)) { + return NT_STATUS_SHARING_VIOLATION; + } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); + lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); - if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); - count++; - status = NT_STATUS_OK; - } - TALLOC_FREE(lck); - DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); + if (!SMB_VFS_RENAME(conn,fname,destname)) { + rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); + count++; + status = NT_STATUS_OK; } - CloseDir(dir_hnd); + TALLOC_FREE(lck); + DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } + CloseDir(dir_hnd); + } #if 0 /* Don't think needed any more - JRA. */ @@ -4386,8 +4414,6 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } #endif - } - if (count == 0 && NT_STATUS_IS_OK(status)) { status = map_nt_error_from_unix(errno); } @@ -4693,40 +4719,49 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } else { struct smb_Dir *dir_hnd = NULL; const char *dname; + long offset = 0; pstring destname; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); - if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory, mask, 0); + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + dir_hnd = OpenDir(conn, directory, mask, 0); + if (dir_hnd == NULL) { + status = map_nt_error_from_unix(errno); + return ERROR_NT(status); + } - if (dir_hnd) { - long offset = 0; - error = ERRbadfile; + error = ERRbadfile; - while ((dname = ReadDirName(dir_hnd, &offset))) { - pstring fname; - pstrcpy(fname,dname); + while ((dname = ReadDirName(dir_hnd, &offset))) { + pstring fname; + pstrcpy(fname,dname); - if (!is_visible_file(conn, directory, dname, &sbuf1, False)) - continue; + if (!is_visible_file(conn, directory, dname, &sbuf1, False)) { + continue; + } - if(!mask_match(fname, mask, conn->case_sensitive)) - continue; + if(!mask_match(fname, mask, conn->case_sensitive)) { + continue; + } - error = ERRnoaccess; - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - pstrcpy(destname,newname); - if (resolve_wildcards(fname,destname) - && NT_STATUS_IS_OK(status = copy_file( - fname,destname,conn,ofun, - count,target_is_directory))) - count++; - DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); + error = ERRnoaccess; + slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + pstrcpy(destname,newname); + if (resolve_wildcards(fname,destname) && + NT_STATUS_IS_OK(status = copy_file( + fname,destname,conn,ofun, + count,target_is_directory))) { + count++; } - CloseDir(dir_hnd); + DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); } + CloseDir(dir_hnd); } if (count == 0) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 48a5a0c1ac..e91a2134fd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -805,8 +805,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(status); } - if (!check_name(fname,conn)) { - return UNIXERROR(ERRDOS,ERRnoaccess); + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } if (open_ofun == 0) { @@ -1722,8 +1723,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", if (!NT_STATUS_IS_OK(ntstatus)) { return ERROR_NT(ntstatus); } - if(!check_name(directory,conn)) { - return UNIXERROR(ERRDOS,ERRbadpath); + ntstatus = check_name(conn, directory); + if (!NT_STATUS_IS_OK(ntstatus)) { + return ERROR_NT(ntstatus); } p = strrchr_m(directory,'/'); @@ -1764,7 +1766,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - + /* Pull out the list of names. */ ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); if (!ea_list) { @@ -1792,10 +1794,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ - dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype); - if (dptr_num < 0) { + ntstatus = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype, &dptr_num); + if (!NT_STATUS_IS_OK(ntstatus)) { talloc_destroy(ea_ctx); - return(UNIXERROR(ERRDOS,ERRbadfile)); + return ERROR_NT(ntstatus); } DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); @@ -2934,9 +2936,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - if (!check_name(fname,conn)) { - DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status))); + return ERROR_NT(status); } if (INFO_LEVEL_IS_UNIX(info_level)) { @@ -3686,7 +3689,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (!check_name(oldname,conn)) { + status = check_name(conn, oldname); + if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_ACCESS_DENIED; } @@ -3700,7 +3704,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam return NT_STATUS_OBJECT_NAME_COLLISION; } - if (!check_name(newname,conn)) { + status = check_name(conn, newname); + if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_ACCESS_DENIED; } @@ -3710,8 +3715,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam } /* Ensure this is within the share. */ - if (!reduce_name(conn, oldname) != 0) - return NT_STATUS_ACCESS_DENIED; + status = reduce_name(conn, oldname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname )); @@ -3826,8 +3833,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return UNIXERROR(ERRDOS,ERRbadpath); } - if(!check_name(fname, conn)) { - return UNIXERROR(ERRDOS,ERRbadpath); + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } } @@ -4366,8 +4374,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } pstrcat(rel_name, link_target); - if (!check_name(rel_name, conn)) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + status = check_name(conn, rel_name); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } } @@ -4823,9 +4832,10 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - if (!check_name(directory,conn)) { - DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - return UNIXERROR(ERRDOS, ERRnoaccess); + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status))); + return ERROR_NT(status); } status = create_directory(conn, directory); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a4ecff921a..47ac9ef461 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -821,7 +821,7 @@ BOOL canonicalize_path(connection_struct *conn, pstring path) it is below dir in the heirachy. This uses realpath. ********************************************************************/ -BOOL reduce_name(connection_struct *conn, const pstring fname) +NTSTATUS reduce_name(connection_struct *conn, const pstring fname) { #ifdef REALPATH_TAKES_NULL BOOL free_resolved_name = True; @@ -836,7 +836,6 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) char *resolved_name = NULL; size_t con_path_len = strlen(conn->connectpath); char *p = NULL; - int saved_errno = errno; DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath)); @@ -850,8 +849,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) switch (errno) { case ENOTDIR: DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname)); - errno = saved_errno; - return False; + return map_nt_error_from_unix(errno); case ENOENT: { pstring tmp_fname; @@ -875,8 +873,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) #endif if (!resolved_name) { DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname)); - errno = saved_errno; - return False; + return map_nt_error_from_unix(errno); } pstrcpy(tmp_fname, resolved_name); pstrcat(tmp_fname, "/"); @@ -886,8 +883,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) resolved_name = SMB_STRDUP(tmp_fname); if (!resolved_name) { DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname)); - errno = saved_errno; - return False; + return NT_STATUS_NO_MEMORY; } #else #ifdef PATH_MAX @@ -901,9 +897,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) } default: DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname)); - /* Don't restore the saved errno. We need to return the error that - realpath caused here as it was not one of the cases we handle. JRA. */ - return False; + return map_nt_error_from_unix(errno); } } @@ -911,19 +905,19 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) if (*resolved_name != '/') { DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n")); - if (free_resolved_name) + if (free_resolved_name) { SAFE_FREE(resolved_name); - errno = saved_errno; - return False; + } + return NT_STATUS_OBJECT_NAME_INVALID; } /* Check for widelinks allowed. */ if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) { DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname)); - if (free_resolved_name) + if (free_resolved_name) { SAFE_FREE(resolved_name); - errno = EACCES; - return False; + } + return NT_STATUS_ACCESS_DENIED; } /* Check if we are allowing users to follow symlinks */ @@ -935,18 +929,18 @@ BOOL reduce_name(connection_struct *conn, const pstring fname) SMB_STRUCT_STAT statbuf; if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { - if (free_resolved_name) + if (free_resolved_name) { SAFE_FREE(resolved_name); + } DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name)); - errno = EACCES; - return False; + return NT_STATUS_ACCESS_DENIED; } } #endif DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name)); - if (free_resolved_name) + if (free_resolved_name) { SAFE_FREE(resolved_name); - errno = saved_errno; - return(True); + } + return NT_STATUS_OK; } -- cgit From 60c1a8e5a8f905a5ae703dac05ed2f440875ad5d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Jan 2007 02:44:27 +0000 Subject: r20845: Somehow I missed this one - should have been part of the previous commit :-(. Jeremy. (This used to be commit 8fe3829e8a884ce2ddb91121d46b7a3a385874c1) --- source3/smbd/open.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bccc91bbd3..49dfad3bc0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1189,8 +1189,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, remove_deferred_open_smb_message(mid); } - if (!check_name(fname,conn)) { - return map_nt_error_from_unix(errno); + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return status; } new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; @@ -1885,6 +1886,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, mode_t mode; char *parent_dir; const char *dirname; + NTSTATUS status; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -1892,8 +1894,9 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return NT_STATUS_ACCESS_DENIED; } - if (!check_name(name, conn)) { - return map_nt_error_from_unix(errno); + status = check_name(conn, name); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir, -- cgit From bf219447a35d86913c1a643b66d993986a651360 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 12:59:14 +0000 Subject: r20846: Before this gets out of control... This add a struct event_context and infrastructure for fd events to smbd. This is step zero to import lib/events. Jeremy, I rely on you to watch the change in receive_message_or_smb() closely. For the normal code path this should be the only relevant change. The rest is either not yet used or is cosmetic. Volker (This used to be commit cd07f93a8aecb24c056e33b1ad3447a41959810f) --- source3/smbd/oplock.c | 5 ++-- source3/smbd/process.c | 65 +++++++++++++++++++++++++++++--------------------- source3/smbd/server.c | 10 ++++++++ 3 files changed, 51 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 427fb7f245..1f73ea837d 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -342,7 +342,8 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un return fsp; } -static void oplock_timeout_handler(struct timed_event *te, +static void oplock_timeout_handler(struct event_context *ctx, + struct timed_event *te, const struct timeval *now, void *private_data) { @@ -372,7 +373,7 @@ static void add_oplock_timeout_handler(files_struct *fsp) } fsp->oplock_timeout = - add_timed_event(NULL, + event_add_timed(smbd_event_context(), NULL, timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), "oplock_timeout_handler", oplock_timeout_handler, fsp); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 929471a48c..2a52da12b3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -225,7 +225,8 @@ struct idle_event { void *private_data; }; -static void idle_event_handler(struct timed_event *te, +static void idle_event_handler(struct event_context *ctx, + struct timed_event *te, const struct timeval *now, void *private_data) { @@ -240,7 +241,8 @@ static void idle_event_handler(struct timed_event *te, return; } - event->te = add_timed_event(event, timeval_sum(now, &event->interval), + event->te = event_add_timed(smbd_event_context(), event, + timeval_sum(now, &event->interval), "idle_event_handler", idle_event_handler, event); @@ -267,11 +269,12 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, result->handler = handler; result->private_data = private_data; - result->te = add_timed_event(result, timeval_sum(&now, &interval), + result->te = event_add_timed(smbd_event_context(), result, + timeval_sum(&now, &interval), "idle_event_handler", idle_event_handler, result); if (result->te == NULL) { - DEBUG(0, ("add_timed_event failed\n")); + DEBUG(0, ("event_add_timed failed\n")); TALLOC_FREE(result); return NULL; } @@ -350,7 +353,7 @@ The timeout is in milliseconds static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) { - fd_set fds; + fd_set r_fds, w_fds; int selrtn; struct timeval to; int maxfd = 0; @@ -414,10 +417,11 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) } /* - * Setup the select read fd set. + * Setup the select fd sets. */ - FD_ZERO(&fds); + FD_ZERO(&r_fds); + FD_ZERO(&w_fds); /* * Ensure we process oplock break messages by preference. @@ -428,9 +432,9 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) * This is hideously complex - *MUST* be simplified for 3.0 ! JRA. */ - if (oplock_message_waiting(&fds)) { + if (oplock_message_waiting(&r_fds)) { DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n")); - async_processing(&fds); + async_processing(&r_fds); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -445,15 +449,17 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ { - struct timeval tmp; - struct timeval *tp = get_timed_events_timeout(&tmp); - - if (tp) { - to = timeval_min(&to, tp); - if (timeval_is_zero(&to)) { - /* Process a timed event now... */ - run_events(); - } + struct timeval now; + GetTimeOfDay(&now); + + event_add_to_select_args(smbd_event_context(), &now, + &r_fds, &w_fds, &to, &maxfd); + } + + if (timeval_is_zero(&to)) { + /* Process a timed event now... */ + if (run_events(smbd_event_context(), 0, NULL, NULL)) { + goto again; } } @@ -461,23 +467,27 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) int sav; START_PROFILE(smbd_idle); - maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds); - maxfd = select_on_fd(change_notify_fd(), maxfd, &fds); - maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds); + maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds); + maxfd = select_on_fd(change_notify_fd(), maxfd, &r_fds); + maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds); - selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); + selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to); sav = errno; END_PROFILE(smbd_idle); errno = sav; } + if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) { + goto again; + } + /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but is the best we can do until the oplock code knows more about signals */ if (selrtn == -1 && errno == EINTR) { - async_processing(&fds); + async_processing(&r_fds); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -505,8 +515,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) * sending us an oplock break message. JRA. */ - if (oplock_message_waiting(&fds)) { - async_processing(&fds); + if (oplock_message_waiting(&r_fds)) { + async_processing(&r_fds); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -515,7 +525,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) goto again; } - if ((change_notify_fd() >= 0) && FD_ISSET(change_notify_fd(), &fds)) { + if ((change_notify_fd() >= 0) && FD_ISSET(change_notify_fd(), + &r_fds)) { process_pending_change_notify_queue((time_t)0); @@ -1603,7 +1614,7 @@ void smbd_process(void) num_smbs = 0; /* Reset smb counter. */ } - run_events(); + run_events(smbd_event_context(), 0, NULL, NULL); #if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5ee9320fb3..4a242488da 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -61,6 +61,16 @@ static void smbd_set_server_fd(int fd) client_setfd(fd); } +struct event_context *smbd_event_context(void) +{ + static struct event_context *ctx; + + if (!ctx && !(ctx = event_context_init(NULL))) { + smb_panic("Could not init smbd event context\n"); + } + return ctx; +} + /******************************************************************* What to do when smb.conf is updated. ********************************************************************/ -- cgit From 940192ddcc9d23e3bec806b4419d5845eeac0fd0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 16:23:45 +0000 Subject: r20854: Ok, now I think we're at a point where looking at notify starts to make sense again :-) Volker (This used to be commit 5533cdeec1b0cdee39b1d89e2320587dc9281ee6) --- source3/smbd/dosmode.c | 10 +- source3/smbd/files.c | 46 +++++ source3/smbd/notify.c | 467 ++++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/nttrans.c | 53 +++++- source3/smbd/open.c | 5 + source3/smbd/reply.c | 23 ++- 6 files changed, 567 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ff4291c08c..44e637a0ee 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -491,8 +491,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname, unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) + if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) { + notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, + NOTIFY_ACTION_MODIFIED); return 0; + } if((errno != EPERM) && (errno != EACCES)) return -1; @@ -521,6 +524,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); + notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, + NOTIFY_ACTION_MODIFIED); } return( ret ); @@ -593,6 +598,9 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); return False; } + + notify_fname(conn, fname, FILE_NOTIFY_CHANGE_LAST_WRITE, + NOTIFY_ACTION_MODIFIED); return(True); } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 7069818dee..982de4c55f 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -361,6 +361,50 @@ files_struct *file_find_di_next(files_struct *start_fsp) return NULL; } +/* + * Same as file_find_di_first/next, but also finds non-fd opens. + * + * Jeremy, do we really need the fsp->fh->fd != -1 ?? + */ + +struct files_struct *fsp_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) +{ + files_struct *fsp; + + if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { + /* Positive or negative cache hit. */ + return fsp_fi_cache.fsp; + } + + fsp_fi_cache.dev = dev; + fsp_fi_cache.inode = inode; + + for (fsp=Files;fsp;fsp=fsp->next) { + if ((fsp->dev == dev) && (fsp->inode == inode)) { + /* Setup positive cache. */ + fsp_fi_cache.fsp = fsp; + return fsp; + } + } + + /* Setup negative cache. */ + fsp_fi_cache.fsp = NULL; + return NULL; +} + +struct files_struct *fsp_find_di_next(files_struct *start_fsp) +{ + files_struct *fsp; + + for (fsp = start_fsp->next;fsp;fsp=fsp->next) { + if ( (fsp->dev == start_fsp->dev) + && (fsp->inode == start_fsp->inode) ) + return fsp; + } + + return NULL; +} + /**************************************************************************** Find a fsp that is open for printing. ****************************************************************************/ @@ -439,6 +483,8 @@ void file_free(files_struct *fsp) fsp->fh->ref_count--; } + TALLOC_FREE(fsp->notify); + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 4ec53567dd..6bedb17261 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,7 @@ #include "includes.h" static struct cnotify_fns *cnotify; +static struct notify_mid_map *notify_changes_by_mid; /**************************************************************************** This is the structure to queue to implement NT change @@ -33,24 +34,76 @@ static struct cnotify_fns *cnotify; struct change_notify { struct change_notify *next, *prev; files_struct *fsp; - connection_struct *conn; uint32 flags; + uint32 max_param_count; char request_buf[smb_size]; void *change_data; }; static struct change_notify *change_notify_list; +static BOOL notify_marshall_changes(unsigned num_changes, + struct notify_change *changes, + prs_struct *ps) +{ + int i; + UNISTR uni_name; + + for (i=0; iname, strlen(c->name)+1, + &uni_name.buffer, True); + if ((namelen == -1) || (uni_name.buffer == NULL)) { + goto fail; + } + + namelen -= 2; /* Dump NULL termination */ + + /* + * Offset to next entry, only if there is one + */ + + u32_tmp = (i == num_changes-1) ? 0 : namelen + 12; + if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = c->action; + if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = namelen; + if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail; + + if (!prs_unistr("name", ps, 1, &uni_name)) goto fail; + + /* + * Not NULL terminated, decrease by the 2 UCS2 \0 chars + */ + prs_set_offset(ps, prs_offset(ps)-2); + + SAFE_FREE(uni_name.buffer); + } + + return True; + + fail: + SAFE_FREE(uni_name.buffer); + return False; +} + /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) +void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common(request_buf, outbuf); ERROR_NT(error_code); @@ -65,6 +118,45 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } +void change_notify_reply(const char *request_buf, uint32 max_param_count, + unsigned num_changes, struct notify_change *changes) +{ + char *outbuf = NULL; + prs_struct ps; + size_t buflen = smb_size+38+max_param_count; + + if (!prs_init(&ps, 0, NULL, False) + || !notify_marshall_changes(num_changes, changes, &ps)) { + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); + goto done; + } + + if (prs_offset(&ps) > max_param_count) { + /* + * We exceed what the client is willing to accept. Send + * nothing. + */ + change_notify_reply_packet(request_buf, NT_STATUS_OK); + goto done; + } + + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); + goto done; + } + + construct_reply_common(request_buf, outbuf); + + if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0) == -1) { + exit_server("change_notify_reply_packet: send_smb failed."); + } + + done: + SAFE_FREE(outbuf); + prs_mem_free(&ps); +} + /**************************************************************************** Remove an entry from the list and free it, also closing any directory handle if necessary. @@ -78,38 +170,104 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } -/**************************************************************************** - Delete entries by fnum from the change notify pending queue. -*****************************************************************************/ +NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, + uint32 filter, struct files_struct *fsp) +{ + struct notify_change_request *request = NULL; + struct notify_mid_map *map = NULL; + + if (!(request = SMB_MALLOC_P(struct notify_change_request)) + || !(map = SMB_MALLOC_P(struct notify_mid_map))) { + SAFE_FREE(request); + return NT_STATUS_NO_MEMORY; + } + + request->mid_map = map; + map->req = request; + + memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); + request->max_param_count = max_param_count; + request->filter = filter; + request->fsp = fsp; + DLIST_ADD_END(fsp->notify->requests, request, + struct notify_change_request *); + + map->mid = SVAL(inbuf, smb_mid); + DLIST_ADD(notify_changes_by_mid, map); -void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + + return NT_STATUS_OK; +} + +static void change_notify_remove_request(struct notify_change_request *remove_req) { - struct change_notify *cnbp, *next; + files_struct *fsp; + struct notify_change_request *req; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp->request_buf,status); - change_notify_remove(cnbp); + /* + * Paranoia checks, the fsp referenced must must have the request in + * its list of pending requests + */ + + fsp = remove_req->fsp; + SMB_ASSERT(fsp->notify != NULL); + + for (req = fsp->notify->requests; req; req = req->next) { + if (req == remove_req) { + break; } } + + if (req == NULL) { + smb_panic("notify_req not found in fsp's requests\n"); + } + + DLIST_REMOVE(fsp->notify->requests, req); + DLIST_REMOVE(notify_changes_by_mid, req->mid_map); + SAFE_FREE(req->mid_map); + SAFE_FREE(req); } /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_mid(int mid) +void remove_pending_change_notify_requests_by_mid(uint16 mid) { - struct change_notify *cnbp, *next; + struct notify_mid_map *map; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); - change_notify_remove(cnbp); + for (map = notify_changes_by_mid; map; map = map->next) { + if (map->mid == mid) { + break; } } + + if (map == NULL) { + return; + } + + change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_remove_request(map->req); +} + +/**************************************************************************** + Delete entries by fnum from the change notify pending queue. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, + NTSTATUS status) +{ + if (fsp->notify == NULL) { + return; + } + + while (fsp->notify->requests != NULL) { + change_notify_reply_packet( + fsp->notify->requests->request_buf, status); + change_notify_remove_request(fsp->notify->requests); + } } /**************************************************************************** @@ -128,7 +286,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,status); + change_notify_reply_packet(cnbp->request_buf, status); change_notify_remove(cnbp); } } @@ -171,9 +329,27 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); + if (cnbp->fsp->notify->num_changes != 0) { + DEBUG(10,("process_pending_change_notify_queue: %s " + "has %d changes!\n", cnbp->fsp->fsp_name, + cnbp->fsp->notify->num_changes)); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); + change_notify_remove(cnbp); + continue; + } + + if (cnotify->check_notify(cnbp->fsp->conn, vuid, + cnbp->fsp->fsp_name, cnbp->flags, + cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir " + "%s changed !\n", cnbp->fsp->fsp_name )); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); change_notify_remove(cnbp); } } @@ -188,22 +364,24 @@ BOOL process_pending_change_notify_queue(time_t t) error. ****************************************************************************/ -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, + uint32 flags, uint32 max_param_count) { struct change_notify *cnbp; if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); - return -1; + return False; } ZERO_STRUCTP(cnbp); memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; - cnbp->conn = conn; cnbp->flags = flags; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); + cnbp->max_param_count = max_param_count; + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, + flags); if (!cnbp->change_data) { SAFE_FREE(cnbp); @@ -227,6 +405,237 @@ int change_notify_fd(void) return -1; } +/* notify message definition + +Offset Data length. +0 SMB_DEV_T dev 8 +8 SMB_INO_T inode 8 +16 uint32 filter 4 +20 uint32 action 4 +24.. name +*/ + +#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ + +struct notify_message { + SMB_DEV_T dev; + SMB_INO_T inode; + uint32 filter; + uint32 action; + char *name; +}; + +static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) +{ + DATA_BLOB result; + size_t len; + + len = strlen(msg->name); + + result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); + if (!result.data) { + return result; + } + + SDEV_T_VAL(result.data, 0, msg->dev); + SINO_T_VAL(result.data, 8, msg->inode); + SIVAL(result.data, 16, msg->filter); + SIVAL(result.data, 20, msg->action); + memcpy(result.data+24, msg->name, len+1); + + return result; +} + +static BOOL buf_to_notify_message(void *buf, size_t len, + struct notify_message *msg) +{ + if (len < MSG_NOTIFY_MESSAGE_SIZE) { + DEBUG(0, ("Got invalid notify message of len %d\n", + (int)len)); + return False; + } + + msg->dev = DEV_T_VAL(buf, 0); + msg->inode = INO_T_VAL(buf, 8); + msg->filter = IVAL(buf, 16); + msg->action = IVAL(buf, 20); + msg->name = ((char *)buf)+24; + return True; +} + +void notify_action(connection_struct *conn, const char *parent, + const char *name, uint32 filter, uint32_t action) +{ + struct share_mode_lock *lck; + SMB_STRUCT_STAT sbuf; + int i; + struct notify_message msg; + DATA_BLOB blob; + + struct process_id *pids; + int num_pids; + + DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", + parent, name, (unsigned)action)); + + if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { + /* + * Not 100% critical, ignore failure + */ + return; + } + + if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, + NULL, NULL))) { + return; + } + + msg.dev = sbuf.st_dev; + msg.inode = sbuf.st_ino; + msg.filter = filter; + msg.action = action; + msg.name = CONST_DISCARD(char *, name); + + blob = notify_message_to_buf(&msg); + if (blob.data == NULL) { + DEBUG(0, ("notify_message_to_buf failed\n")); + return; + } + + pids = NULL; + num_pids = 0; + + become_root_uid_only(); + + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + int j; + struct process_id *tmp; + + for (j=0; jpid, &pids[j])) { + break; + } + } + + if (j < num_pids) { + /* + * Already sent to that process, skip it + */ + continue; + } + + message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, + blob.data, blob.length, True); + + if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, + num_pids+1))) { + DEBUG(0, ("realloc failed\n")); + break; + } + pids = tmp; + pids[num_pids] = e->pid; + num_pids += 1; + } + + unbecome_root_uid_only(); + + data_blob_free(&blob); + TALLOC_FREE(lck); +} + +void notify_fname(connection_struct *conn, const char *path, + uint32 filter, uint32 action) +{ + char *parent; + const char *name; + + if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { + return; + } + + notify_action(conn, parent, name, filter, action); + TALLOC_FREE(parent); +} + +static void notify_fsp(files_struct *fsp, struct notify_message *msg) +{ + struct notify_change *change, *changes; + + if (fsp->notify == NULL) { + /* + * Nobody is waiting, don't queue + */ + return; + } + + if ((fsp->notify->requests != NULL) + && (fsp->notify->requests->filter & msg->filter)) { + /* + * Someone is waiting for the change, trigger the reply + * immediately. + * + * TODO: do we have to walk the lists of requests pending? + */ + + struct notify_change_request *req = fsp->notify->requests; + struct notify_change onechange; + + onechange.action = msg->action; + onechange.name = msg->name; + + change_notify_reply(req->request_buf, req->max_param_count, + 1, &onechange); + change_notify_remove_request(req); + return; + } + + /* + * Someone has triggered a notify previously, queue the change for + * later. TODO: Limit the number of changes queued, test how filters + * apply here. Do we have to store them? + */ + + if (!(changes = TALLOC_REALLOC_ARRAY( + fsp->notify, fsp->notify->changes, + struct notify_change, fsp->notify->num_changes+1))) { + DEBUG(0, ("talloc_realloc failed\n")); + return; + } + + fsp->notify->changes = changes; + + change = &(fsp->notify->changes[fsp->notify->num_changes]); + + if (!(change->name = talloc_strdup(changes, msg->name))) { + DEBUG(0, ("talloc_strdup failed\n")); + return; + } + change->action = msg->action; + fsp->notify->num_changes += 1; + + return; +} + +static void notify_message_callback(int msgtype, struct process_id pid, + void *buf, size_t len) +{ + struct notify_message msg; + files_struct *fsp; + + if (!buf_to_notify_message(buf, len, &msg)) { + return; + } + + DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", + (unsigned)msg.dev, (double)msg.inode, msg.action)); + + for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; + fsp = fsp_find_di_next(fsp)) { + notify_fsp(fsp, &msg); + } +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ @@ -250,5 +659,7 @@ BOOL init_change_notify(void) return False; } + message_register(MSG_SMB_NOTIFY, notify_message_callback); + return True; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f4d6220592..ac7beabb53 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1800,14 +1800,15 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, { uint16 *setup = *ppsetup; files_struct *fsp; - uint32 flags; + uint32 filter; + NTSTATUS status; if(setup_count < 6) { return ERROR_DOS(ERRDOS,ERRbadfunc); } fsp = file_fsp((char *)setup,4); - flags = IVAL(setup, 0); + filter = IVAL(setup, 0); DEBUG(3,("call_nt_transact_notify_change\n")); @@ -1815,16 +1816,56 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfid); } + DEBUG(3,("call_nt_transact_notify_change: notify change called on " + "directory name = %s\n", fsp->fsp_name )); + if((!fsp->is_directory) || (conn != fsp->conn)) { return ERROR_DOS(ERRDOS,ERRbadfid); } - if (!change_notify_set(inbuf, fsp, conn, flags)) { - return(UNIXERROR(ERRDOS,ERRbadfid)); + if (fsp->notify == NULL) { + if (!(fsp->notify = TALLOC_ZERO_P( + NULL, struct notify_change_buf))) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + } + + if (fsp->notify->num_changes > 0) { + + /* + * We've got changes pending, respond immediately + */ + + /* + * TODO: write a torture test to check the filtering behaviour + * here. + */ + + SMB_ASSERT(fsp->notify->requests == NULL); + + change_notify_reply(inbuf, max_param_count, + fsp->notify->num_changes, + fsp->notify->changes); + + TALLOC_FREE(fsp->notify->changes); + fsp->notify->num_changes = 0; + + /* + * change_notify_reply() above has independently sent its + * results + */ + return -1; } - DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \ -name = %s\n", fsp->fsp_name )); + /* + * No changes pending, queue the request + */ + + status = change_notify_add_request(inbuf, max_param_count, filter, + fsp); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } return -1; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 49dfad3bc0..4249c6e85b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,6 +309,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } + notify_action(conn, parent_dir, name, -1, + NOTIFY_ACTION_ADDED); } } else { @@ -1945,6 +1947,9 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } + notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, + NOTIFY_ACTION_ADDED); + return NT_STATUS_OK; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2d11b3db98..4d139be98f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1857,6 +1857,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; + notify_fname(conn, directory, -1, + NOTIFY_ACTION_REMOVED); } } else { struct smb_Dir *dir_hnd = NULL; @@ -1913,9 +1915,14 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (!NT_STATUS_IS_OK(status)) { continue; } - if (SMB_VFS_UNLINK(conn,fname) == 0) + if (SMB_VFS_UNLINK(conn,fname) == 0) { count++; - DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); + DEBUG(3,("unlink_internals: succesful unlink " + "[%s]\n",fname)); + notify_action(conn, directory, dname, + -1, NOTIFY_ACTION_REMOVED); + } + } CloseDir(dir_hnd); } @@ -3779,6 +3786,18 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) return False; } + { + char *parent_dir; + const char *dirname; + + if (parent_dirname_talloc(tmp_talloc_ctx(), directory, + &parent_dir, &dirname)) { + notify_action(conn, parent_dir, dirname, -1, + NOTIFY_ACTION_REMOVED); + TALLOC_FREE(parent_dir); /* Not strictly necessary */ + } + } + return True; } -- cgit From 90f59d441223ba9b32b0d788901c9de5cf4b3bc7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 18:23:37 +0000 Subject: r20856: Make "struct notify_mid_map" private to notify.c (This used to be commit beecef0c70521d28dd88552d661281d9c585eb22) --- source3/smbd/notify.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6bedb17261..3b01c2c786 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -40,6 +40,17 @@ struct change_notify { void *change_data; }; +/* + * For NTCancel, we need to find the notify_change_request indexed by + * mid. Separate list here. + */ + +struct notify_mid_map { + struct notify_mid_map *prev, *next; + struct notify_change_request *req; + uint16 mid; +}; + static struct change_notify *change_notify_list; static BOOL notify_marshall_changes(unsigned num_changes, -- cgit From ab41ff67f1308389a130c3a4ff804545d8998dd1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 18:26:37 +0000 Subject: r20858: change_notify_reply_packet is static (This used to be commit a1d0644d156c360d52fb837d3eecddb202135ebe) --- source3/smbd/notify.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 3b01c2c786..2c762bd759 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -109,7 +109,8 @@ static BOOL notify_marshall_changes(unsigned num_changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) +static void change_notify_reply_packet(const char *request_buf, + NTSTATUS error_code) { char outbuf[smb_size+38]; @@ -126,7 +127,8 @@ void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("change_notify_reply_packet: send_smb failed."); + exit_server_cleanly("change_notify_reply_packet: send_smb " + "failed."); } void change_notify_reply(const char *request_buf, uint32 max_param_count, -- cgit From fd37f98158161406229b728a7c767121a30e254f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Jan 2007 06:19:24 +0000 Subject: r20873: Some correctness fixes w.r.t. Samba4 torture BASE-DELETE. Allow us to correctly refuse to set delete on close on a non-empty directory. There are still some delete-on-close wrinkles to be fixed, but I understand how to do that better now. I'll fix this tomorrow. Jeremy. (This used to be commit 029635885825a5562e7974a6f5675cce3bf1b5dc) --- source3/smbd/dir.c | 13 ++++++++----- source3/smbd/nttrans.c | 23 ++++++++++++++--------- source3/smbd/open.c | 10 ++++++---- source3/smbd/posix_acls.c | 5 +++++ source3/smbd/reply.c | 11 ++++++++++- source3/smbd/trans2.c | 14 ++++++++++++-- 6 files changed, 55 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7be5c03f1b..98356882aa 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -383,7 +383,7 @@ static void dptr_close_oldest(BOOL old) ****************************************************************************/ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, - const char *wcard, BOOL wcard_has_wild, uint32 attr, int *dptr_hnd_ret) + const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret) { struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; @@ -392,8 +392,6 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO DEBUG(5,("dptr_create dir=%s\n", path)); - *dptr_hnd_ret = -1; - if (!wcard) { return NT_STATUS_INVALID_PARAMETER; } @@ -517,9 +515,8 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", dptr->dnum,path,expect_close)); - conn->dirptr = dptr; + *dptr_ret = dptr; - *dptr_hnd_ret = dptr->dnum; return NT_STATUS_OK; } @@ -530,6 +527,7 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO int dptr_CloseDir(struct dptr_struct *dptr) { + DLIST_REMOVE(dirptrs, dptr); return CloseDir(dptr->dir_hnd); } @@ -548,6 +546,11 @@ BOOL dptr_has_wild(struct dptr_struct *dptr) return dptr->has_wild; } +int dptr_dnum(struct dptr_struct *dptr) +{ + return dptr->dnum; +} + /**************************************************************************** Return the next visible file name, skipping veto'd and invisible files. ****************************************************************************/ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ac7beabb53..51a4093f29 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -652,11 +652,13 @@ int reply_ntcreate_and_X(connection_struct *conn, if (lp_acl_check_permissions(SNUM(conn)) && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS) - && !can_delete_file_in_directory(conn, fname)) { - restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + && (access_mask & DELETE_ACCESS)) { + if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || + !can_delete_file_in_directory(conn, fname)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } } /* @@ -1277,10 +1279,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (lp_acl_check_permissions(SNUM(conn)) && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS) - && !can_delete_file_in_directory(conn, fname)) { - restore_case_semantics(conn, file_attributes); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + && (access_mask & DELETE_ACCESS)) { + if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || + !can_delete_file_in_directory(conn, fname)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } } if (ea_len) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4249c6e85b..c0638c0039 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2110,15 +2110,17 @@ NTSTATUS open_directory(connection_struct *conn, always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) { TALLOC_FREE(lck); file_free(fsp); return status; } - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + if (NT_STATUS_IS_OK(status)) { + set_delete_on_close_token(lck, ¤t_user.ut); + lck->initial_delete_on_close = True; + lck->modified = True; + } } TALLOC_FREE(lck); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c5da33c9df..630e270de3 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4221,6 +4221,11 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) if (sbuf.st_mode & S_ISVTX) { SMB_STRUCT_STAT sbuf_file; if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { + if (errno == ENOENT) { + /* If the file doesn't already exist then + * yes we'll be able to delete it. */ + return True; + } return False; } /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4d139be98f..2075939f5b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1013,10 +1013,19 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size p = smb_buf(outbuf) + 3; if (status_len == 0) { - nt_status = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype,&dptr_num); + nt_status = dptr_create(conn, + directory, + True, + expect_close, + SVAL(inbuf,smb_pid), + mask, + mask_contains_wcard, + dirtype, + &conn->dirptr); if (!NT_STATUS_IS_OK(nt_status)) { return ERROR_NT(nt_status); } + dptr_num = dptr_dnum(conn->dirptr); } else { dirtype = dptr_attr(dptr_num); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e91a2134fd..c9cb2c5b4f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1794,13 +1794,23 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ - ntstatus = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype, &dptr_num); + ntstatus = dptr_create(conn, + directory, + False, + True, + SVAL(inbuf,smb_pid), + mask, + mask_contains_wcard, + dirtype, + &conn->dirptr); + if (!NT_STATUS_IS_OK(ntstatus)) { talloc_destroy(ea_ctx); return ERROR_NT(ntstatus); } - DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); + dptr_num = dptr_dnum(conn->dirptr); + DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype)); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ -- cgit From 2958f467339913320e8593301127baef8a56beb1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 18 Jan 2007 12:49:59 +0000 Subject: r20877: Random notify fixes (This used to be commit 2f1bfc53733ac3debc6a8b51642ab191869cd792) --- source3/smbd/reply.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2075939f5b..2763924d4f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1866,7 +1866,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; - notify_fname(conn, directory, -1, + notify_fname(conn, directory, + FILE_NOTIFY_CHANGE_FILE, NOTIFY_ACTION_REMOVED); } } else { @@ -1929,7 +1930,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, DEBUG(3,("unlink_internals: succesful unlink " "[%s]\n",fname)); notify_action(conn, directory, dname, - -1, NOTIFY_ACTION_REMOVED); + FILE_NOTIFY_CHANGE_FILE, + NOTIFY_ACTION_REMOVED); } } @@ -3718,6 +3720,8 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) ret = SMB_VFS_RMDIR(conn,directory); if (ret == 0) { + notify_fname(conn, directory, FILE_NOTIFY_CHANGE_DIR_NAME, + NOTIFY_ACTION_REMOVED); return True; } @@ -3795,17 +3799,8 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) return False; } - { - char *parent_dir; - const char *dirname; - - if (parent_dirname_talloc(tmp_talloc_ctx(), directory, - &parent_dir, &dirname)) { - notify_action(conn, parent_dir, dirname, -1, - NOTIFY_ACTION_REMOVED); - TALLOC_FREE(parent_dir); /* Not strictly necessary */ - } - } + notify_fname(conn, directory, FILE_NOTIFY_CHANGE_DIR_NAME, + NOTIFY_ACTION_REMOVED); return True; } -- cgit From 00deaa584c552e1dbf917d240f438977dbbc9b4c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 18 Jan 2007 15:51:51 +0000 Subject: r20878: Fix build with --enable-profiling (This used to be commit eb14d0ea83273c60aee900557aa5dceb77bb8127) --- source3/smbd/nttrans.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 51a4093f29..13e290135a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1283,7 +1283,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || !can_delete_file_in_directory(conn, fname)) { restore_case_semantics(conn, file_attributes); - END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_ACCESS_DENIED); } } -- cgit From c9a14ea19f812d86266bfa9e6ce8b32f7b4ff19f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Jan 2007 21:51:52 +0000 Subject: r20883: W00t! I now understand how "delete on close" really works - even with the strange "initial delete on close" semantics. The "initial delete on close" flag isn't committed to the share mode db until the handle is closed, and is discarded if any real "delete on close" was set. This allows me to remove the "initial_delete_on_close" flag from the share db, and move it into a BOOL in files_struct. Warning ! You must do a make clean after this. Cope with the wrinkle in directory delete on close which is done differently from files. We now pass all Samba4 smbtortute BASE-DELETE tests except for the one checking that files can't be created in a directory which has the delete on close set (possibly expensive to fix). Jeremy. (This used to be commit f2df77a1497958c1ea791f1d2f4446b5fc3389b3) --- source3/smbd/close.c | 39 +++++++++++++++++++++++++++++++++++++-- source3/smbd/open.c | 12 +++++------- 2 files changed, 42 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index fe5e5eccf2..8958878433 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -22,6 +22,8 @@ #include "includes.h" +extern struct current_user current_user; + /**************************************************************************** Run a file if it is a magic script. ****************************************************************************/ @@ -172,7 +174,23 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, "entry for file %s\n", fsp->fsp_name)); } - delete_file = (lck->delete_on_close | lck->initial_delete_on_close); + if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) { + BOOL became_user = False; + + /* Initial delete on close was set and no one else + * wrote a real delete on close. */ + + if (current_user.vuid != fsp->vuid) { + become_user(conn, fsp->vuid); + became_user = True; + } + set_delete_on_close_lck(lck, True, ¤t_user.ut); + if (became_user) { + unbecome_user(); + } + } + + delete_file = lck->delete_on_close; if (delete_file) { int i; @@ -402,7 +420,24 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name)); } - delete_dir = (lck->delete_on_close | lck->initial_delete_on_close); + if (fsp->initial_delete_on_close) { + BOOL became_user = False; + + /* Initial delete on close was set - for + * directories we don't care if anyone else + * wrote a real delete on close. */ + + if (current_user.vuid != fsp->vuid) { + become_user(fsp->conn, fsp->vuid); + became_user = True; + } + set_delete_on_close_lck(lck, True, ¤t_user.ut); + if (became_user) { + unbecome_user(); + } + } + + delete_dir = lck->delete_on_close; if (delete_dir) { int i; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c0638c0039..a5a8eacda0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1761,10 +1761,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } /* Note that here we set the *inital* delete on close flag, - not the regular one. */ - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; } /* Files should be initially set as archive */ @@ -2117,9 +2115,9 @@ NTSTATUS open_directory(connection_struct *conn, } if (NT_STATUS_IS_OK(status)) { - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + /* Note that here we set the *inital* delete on close flag, + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; } } -- cgit From aacd16e7c4bea5018560eea09d55f2a6473be84d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Jan 2007 21:46:12 +0000 Subject: r20916: Add in the delete on close final fix - but only enabled with -DDEVELOPER. Jeremy. (This used to be commit 7f817067a70930ee3502ea3373173e0c23733253) --- source3/smbd/close.c | 1 + source3/smbd/filename.c | 6 ++++++ source3/smbd/server.c | 13 +++++++++++++ source3/smbd/statcache.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 8958878433..07f81f988e 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -431,6 +431,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) become_user(fsp->conn, fsp->vuid); became_user = True; } + send_stat_cache_delete_message(fsp->fsp_name); set_delete_on_close_lck(lck, True, ¤t_user.ut); if (became_user) { unbecome_user(); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b69d2f3e5e..eb86a0efd1 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -462,6 +462,12 @@ NTSTATUS unix_convert(connection_struct *conn, } } /* end else */ +#ifdef DEVELOPER + if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) { + return NT_STATUS_DELETE_PENDING; + } +#endif + /* * Add to the dirpath that we have resolved so far. */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4a242488da..e2f73285b3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -83,6 +83,18 @@ static void smb_conf_updated(int msg_type, struct process_id src, } +/******************************************************************* + Delete a statcache entry. + ********************************************************************/ + +static void smb_stat_cache_delete(int msg_type, struct process_id src, + void *buf, size_t len) +{ + const char *name = (const char *)buf; + DEBUG(10,("smb_stat_cache_delete: delete name %s\n", name)); + stat_cache_delete(name); +} + /**************************************************************************** Terminate signal. ****************************************************************************/ @@ -422,6 +434,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ message_register(MSG_SHUTDOWN, msg_exit_server); message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated); + message_register(MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete); #ifdef DEVELOPER message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index b453fdd544..1a2b7a8237 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -285,6 +285,40 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } +/*************************************************************************** + Tell all smbd's to delete an entry. +**************************************************************************/ + +void send_stat_cache_delete_message(const char *name) +{ +#ifdef DEVELOPER + message_send_all(conn_tdb_ctx(), + MSG_SMB_STAT_CACHE_DELETE, + name, + strlen(name)+1, + True, + NULL); +#endif +} + +/*************************************************************************** + Delete an entry. +**************************************************************************/ + +void stat_cache_delete(const char *name) +{ + char *lname = strdup_upper(name); + + if (!lname) { + return; + } + DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n", + lname, name )); + + tdb_delete_bystring(tdb_stat_cache, lname); + SAFE_FREE(lname); +} + /*************************************************************** Compute a hash value based on a string key value. The function returns the bucket index number for the hashed key. -- cgit From d5206610cd67f88e2cc7d5b2b434e320e81c29d5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 21 Jan 2007 11:49:00 +0000 Subject: r20931: This changes the notify infrastructure from a polling-based to an event-driven based approach. The only remaining hook into the backend is now void *(*notify_add)(TALLOC_CTX *mem_ctx, struct event_context *event_ctx, files_struct *fsp, uint32 *filter); (Should we put this through the VFS, so that others can more easily plug in?) The trick here is that the backend can pick filter bits that the main smbd should not handle anymore. Thanks to tridge for this idea. The backend can notify the main smbd process via void notify_fsp(files_struct *fsp, uint32 action, char *name); The core patch is not big, what makes this more than 1800 lines are the individual backends that are considerably changed but can be reviewed one by one. Based on this I'll continue with inotify now. Volker (This used to be commit 9cd6a8a82792b7b6967141565d043b6337836a5d) --- source3/smbd/close.c | 5 - source3/smbd/notify.c | 226 ++++-------------- source3/smbd/notify_fam.c | 548 +++++++++++++++---------------------------- source3/smbd/notify_hash.c | 191 ++++++++------- source3/smbd/notify_kernel.c | 216 ++++++++++------- source3/smbd/nttrans.c | 14 +- source3/smbd/process.c | 31 --- source3/smbd/reply.c | 11 - source3/smbd/service.c | 3 - source3/smbd/trans2.c | 1 - 10 files changed, 472 insertions(+), 774 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 07f81f988e..714e0615de 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -291,8 +291,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, /* unbecome user. */ pop_sec_ctx(); - process_pending_change_notify_queue((time_t)0); - TALLOC_FREE(lck); return status; } @@ -486,10 +484,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) if(ok) { remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING); - remove_pending_change_notify_requests_by_filename(fsp, NT_STATUS_DELETE_PENDING); - } - process_pending_change_notify_queue((time_t)0); } else { TALLOC_FREE(lck); remove_pending_change_notify_requests_by_fid( diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2c762bd759..ce7680b49a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -3,6 +3,7 @@ change notify handling Copyright (C) Andrew Tridgell 2000 Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Volker Lendecke 2007 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 @@ -24,22 +25,6 @@ static struct cnotify_fns *cnotify; static struct notify_mid_map *notify_changes_by_mid; -/**************************************************************************** - This is the structure to queue to implement NT change - notify. It consists of smb_size bytes stored from the - transact command (to keep the mid, tid etc around). - Plus the fid to examine and notify private data. -*****************************************************************************/ - -struct change_notify { - struct change_notify *next, *prev; - files_struct *fsp; - uint32 flags; - uint32 max_param_count; - char request_buf[smb_size]; - void *change_data; -}; - /* * For NTCancel, we need to find the notify_change_request indexed by * mid. Separate list here. @@ -51,9 +36,7 @@ struct notify_mid_map { uint16 mid; }; -static struct change_notify *change_notify_list; - -static BOOL notify_marshall_changes(unsigned num_changes, +static BOOL notify_marshall_changes(int num_changes, struct notify_change *changes, prs_struct *ps) { @@ -132,12 +115,17 @@ static void change_notify_reply_packet(const char *request_buf, } void change_notify_reply(const char *request_buf, uint32 max_param_count, - unsigned num_changes, struct notify_change *changes) + int num_changes, struct notify_change *changes) { char *outbuf = NULL; prs_struct ps; size_t buflen = smb_size+38+max_param_count; + if (num_changes == -1) { + change_notify_reply_packet(request_buf, NT_STATUS_OK); + return; + } + if (!prs_init(&ps, 0, NULL, False) || !notify_marshall_changes(num_changes, changes, &ps)) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); @@ -170,19 +158,6 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, prs_mem_free(&ps); } -/**************************************************************************** - Remove an entry from the list and free it, also closing any - directory handle if necessary. -*****************************************************************************/ - -static void change_notify_remove(struct change_notify *cnbp) -{ - cnotify->remove_notify(cnbp->change_data); - DLIST_REMOVE(change_notify_list, cnbp); - ZERO_STRUCTP(cnbp); - SAFE_FREE(cnbp); -} - NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, uint32 filter, struct files_struct *fsp) { @@ -202,6 +177,10 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, request->max_param_count = max_param_count; request->filter = filter; request->fsp = fsp; + + request->backend_data = cnotify->notify_add(NULL, smbd_event_context(), + fsp, &request->filter); + DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -240,6 +219,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re DLIST_REMOVE(fsp->notify->requests, req); DLIST_REMOVE(notify_changes_by_mid, req->mid_map); SAFE_FREE(req->mid_map); + TALLOC_FREE(req->backend_data); SAFE_FREE(req); } @@ -283,141 +263,6 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } } -/**************************************************************************** - Delete entries by filename and cnum from the change notify pending queue. - Always send reply. -*****************************************************************************/ - -void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTATUS status) -{ - struct change_notify *cnbp, *next; - - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - /* - * We know it refers to the same directory if the connection number and - * the filename are identical. - */ - if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf, status); - change_notify_remove(cnbp); - } - } -} - -/**************************************************************************** - Set the current change notify timeout to the lowest value across all service - values. -****************************************************************************/ - -void set_change_notify_timeout(int val) -{ - if (val > 0) { - cnotify->select_time = MIN(cnotify->select_time, val); - } -} - -/**************************************************************************** - Longest time to sleep for before doing a change notify scan. -****************************************************************************/ - -int change_notify_timeout(void) -{ - return cnotify->select_time; -} - -/**************************************************************************** - Process the change notify queue. Note that this is only called as root. - Returns True if there are still outstanding change notify requests on the - queue. -*****************************************************************************/ - -BOOL process_pending_change_notify_queue(time_t t) -{ - struct change_notify *cnbp, *next; - uint16 vuid; - - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - - vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - - if (cnbp->fsp->notify->num_changes != 0) { - DEBUG(10,("process_pending_change_notify_queue: %s " - "has %d changes!\n", cnbp->fsp->fsp_name, - cnbp->fsp->notify->num_changes)); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); - change_notify_remove(cnbp); - continue; - } - - if (cnotify->check_notify(cnbp->fsp->conn, vuid, - cnbp->fsp->fsp_name, cnbp->flags, - cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir " - "%s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); - change_notify_remove(cnbp); - } - } - - return (change_notify_list != NULL); -} - -/**************************************************************************** - Now queue an entry on the notify change list. - We only need to save smb_size bytes from this incoming packet - as we will always by returning a 'read the directory yourself' - error. -****************************************************************************/ - -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, - uint32 flags, uint32 max_param_count) -{ - struct change_notify *cnbp; - - if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { - DEBUG(0,("change_notify_set: malloc fail !\n" )); - return False; - } - - ZERO_STRUCTP(cnbp); - - memcpy(cnbp->request_buf, inbuf, smb_size); - cnbp->fsp = fsp; - cnbp->flags = flags; - cnbp->max_param_count = max_param_count; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, - flags); - - if (!cnbp->change_data) { - SAFE_FREE(cnbp); - return False; - } - - DLIST_ADD(change_notify_list, cnbp); - - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); - - return True; -} - -int change_notify_fd(void) -{ - if (cnotify) { - return cnotify->notification_fd; - } - - return -1; -} - /* notify message definition Offset Data length. @@ -571,7 +416,7 @@ void notify_fname(connection_struct *conn, const char *path, TALLOC_FREE(parent); } -static void notify_fsp(files_struct *fsp, struct notify_message *msg) +void notify_fsp(files_struct *fsp, uint32 action, char *name) { struct notify_change *change, *changes; @@ -582,8 +427,7 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) return; } - if ((fsp->notify->requests != NULL) - && (fsp->notify->requests->filter & msg->filter)) { + if (fsp->notify->requests != NULL) { /* * Someone is waiting for the change, trigger the reply * immediately. @@ -594,8 +438,18 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) struct notify_change_request *req = fsp->notify->requests; struct notify_change onechange; - onechange.action = msg->action; - onechange.name = msg->name; + if (name == NULL) { + /* + * Catch-all change, possibly from notify_hash.c + */ + change_notify_reply(req->request_buf, + req->max_param_count, + -1, NULL); + return; + } + + onechange.action = action; + onechange.name = name; change_notify_reply(req->request_buf, req->max_param_count, 1, &onechange); @@ -609,6 +463,19 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) * apply here. Do we have to store them? */ + if ((fsp->notify->num_changes > 30) || (name == NULL)) { + /* + * W2k3 seems to store at most 30 changes. + */ + TALLOC_FREE(fsp->notify->changes); + fsp->notify->num_changes = -1; + return; + } + + if (fsp->notify->num_changes == -1) { + return; + } + if (!(changes = TALLOC_REALLOC_ARRAY( fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { @@ -620,11 +487,11 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, msg->name))) { + if (!(change->name = talloc_strdup(changes, name))) { DEBUG(0, ("talloc_strdup failed\n")); return; } - change->action = msg->action; + change->action = action; fsp->notify->num_changes += 1; return; @@ -645,7 +512,10 @@ static void notify_message_callback(int msgtype, struct process_id pid, for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; fsp = fsp_find_di_next(fsp)) { - notify_fsp(fsp, &msg); + if ((fsp->notify->requests != NULL) + && (fsp->notify->requests->filter & msg.filter)) { + notify_fsp(fsp, msg.action, msg.name); + } } } @@ -659,11 +529,11 @@ BOOL init_change_notify(void) #if HAVE_KERNEL_CHANGE_NOTIFY if (cnotify == NULL && lp_kernel_change_notify()) - cnotify = kernel_notify_init(); + cnotify = kernel_notify_init(smbd_event_context()); #endif #if HAVE_FAM_CHANGE_NOTIFY if (cnotify == NULL && lp_fam_change_notify()) - cnotify = fam_notify_init(); + cnotify = fam_notify_init(smbd_event_context()); #endif if (!cnotify) cnotify = hash_notify_init(); diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index bfef4ac871..306316e49f 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -2,6 +2,7 @@ * FAM file notification support. * * Copyright (c) James Peach 2005 + * Copyright (c) Volker Lendecke 2007 * * 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 @@ -43,422 +44,241 @@ typedef enum FAMCodes FAMCodes; * http://sourceforge.net/projects/bsdfam/ */ -struct fam_req_info -{ - FAMRequest req; - int generation; - FAMCodes code; - enum - { - /* We are waiting for an event. */ - FAM_REQ_MONITORING, - /* An event has been receive, but we haven't been able to send it back - * to the client yet. It is stashed in the code member. - */ - FAM_REQ_FIRED - } state; -}; - -/* Don't initialise this until the first register request. We want a single - * FAM connection for each worker smbd. If we allow the master (parent) smbd to - * open a FAM connection, multiple processes talking on the same socket will - * undoubtedly create havoc. - */ -static FAMConnection global_fc; -static int global_fc_generation; - -#define FAM_TRACE 8 -#define FAM_TRACE_LOW 10 +static void *fam_notify_add(TALLOC_CTX *mem_ctx, + struct event_context *event_ctx, + files_struct *fsp, uint32 *filter); -#define FAM_EVENT_DRAIN ((uint32_t)(-1)) - -static void * fam_register_notify(connection_struct * conn, - char * path, - uint32 flags); +/* ------------------------------------------------------------------------- */ -static BOOL fam_check_notify(connection_struct * conn, - uint16_t vuid, - char * path, - uint32_t flags, - void * data, - time_t when); +struct fam_notify_ctx { + struct fam_notify_ctx *prev, *next; + FAMConnection *fam_connection; + struct FAMRequest fr; + files_struct *fsp; + char *path; + uint32 filter; +}; -static void fam_remove_notify(void * data); +static struct fam_notify_ctx *fam_notify_list; +static FAMConnection fam_connection; +static void fam_handler(struct event_context *event_ctx, + struct fd_event *fd_event, + uint16 flags, + void *private_data); -static struct cnotify_fns global_fam_notify = +static NTSTATUS fam_open_connection(FAMConnection *fam_conn, + struct event_context *event_ctx) { - fam_register_notify, - fam_check_notify, - fam_remove_notify, - -1, - -1 -}; + int res; + char *name; -/* Turn a FAM event code into a string. Don't rely on specific code values, - * because that might not work across all flavours of FAM. - */ -static const char * -fam_event_str(FAMCodes code) -{ - static const struct { FAMCodes code; const char * name; } evstr[] = - { - { FAMChanged, "FAMChanged"}, - { FAMDeleted, "FAMDeleted"}, - { FAMStartExecuting, "FAMStartExecuting"}, - { FAMStopExecuting, "FAMStopExecuting"}, - { FAMCreated, "FAMCreated"}, - { FAMMoved, "FAMMoved"}, - { FAMAcknowledge, "FAMAcknowledge"}, - { FAMExists, "FAMExists"}, - { FAMEndExist, "FAMEndExist"} - }; - - int i; - - for (i = 0; i < ARRAY_SIZE(evstr); ++i) { - if (code == evstr[i].code) - return(evstr[i].name); - } - - return(""); -} + ZERO_STRUCTP(fam_conn); + FAMCONNECTION_GETFD(fam_conn) = -1; -static BOOL -fam_check_reconnect(void) -{ - if (FAMCONNECTION_GETFD(&global_fc) < 0) { - fstring name; + if (asprintf(&name, "smbd (%lu)", (unsigned long)sys_getpid()) == -1) { + DEBUG(0, ("No memory\n")); + return NT_STATUS_NO_MEMORY; + } - global_fc_generation++; - snprintf(name, sizeof(name), "smbd (%lu)", (unsigned long)sys_getpid()); + res = FAMOpen2(fam_conn, name); + SAFE_FREE(name); - if (FAMOpen2(&global_fc, name) < 0) { - DEBUG(0, ("failed to connect to FAM service\n")); - return(False); + if (res < 0) { + DEBUG(5, ("FAM file change notifications not available\n")); + /* + * No idea how to get NT_STATUS from a FAM result + */ + FAMCONNECTION_GETFD(fam_conn) = -1; + return NT_STATUS_UNEXPECTED_IO_ERROR; } - } - global_fam_notify.notification_fd = FAMCONNECTION_GETFD(&global_fc); - return(True); -} + if (event_add_fd(event_ctx, event_ctx, + FAMCONNECTION_GETFD(fam_conn), + EVENT_FD_READ, fam_handler, + (void *)fam_conn) == NULL) { + DEBUG(0, ("event_add_fd failed\n")); + FAMClose(fam_conn); + FAMCONNECTION_GETFD(fam_conn) = -1; + return NT_STATUS_NO_MEMORY; + } -static BOOL -fam_monitor_path(connection_struct * conn, - struct fam_req_info * info, - const char * path, - uint32 flags) -{ - SMB_STRUCT_STAT st; - pstring fullpath; - - DEBUG(FAM_TRACE, ("requesting FAM notifications for '%s'\n", path)); - - /* FAM needs an absolute pathname. */ - - /* It would be better to use reduce_name() here, but reduce_name does not - * actually return the reduced result. How utterly un-useful. - */ - pstrcpy(fullpath, path); - if (!canonicalize_path(conn, fullpath)) { - DEBUG(0, ("failed to canonicalize path '%s'\n", path)); - return(False); - } - - if (*fullpath != '/') { - DEBUG(0, ("canonicalized path '%s' into `%s`\n", path, fullpath)); - DEBUGADD(0, ("but expected an absolute path\n")); - return(False); - } - - if (SMB_VFS_STAT(conn, path, &st) < 0) { - DEBUG(0, ("stat of '%s' failed: %s\n", path, strerror(errno))); - return(False); - } - /* Start monitoring this file or directory. We hand the state structure to - * both the caller and the FAM library so we can match up the caller's - * status requests with FAM notifications. - */ - if (S_ISDIR(st.st_mode)) { - FAMMonitorDirectory(&global_fc, fullpath, &(info->req), info); - } else { - FAMMonitorFile(&global_fc, fullpath, &(info->req), info); - } - - /* Grr. On IRIX, neither of the monitor functions return a status. */ - - /* We will stay in initialising state until we see the FAMendExist message - * for this file. - */ - info->state = FAM_REQ_MONITORING; - info->generation = global_fc_generation; - return(True); + return NT_STATUS_OK; } -static BOOL -fam_handle_event(const FAMCodes code, uint32 flags) +static void fam_reopen(FAMConnection *fam_conn, + struct event_context *event_ctx, + struct fam_notify_ctx *notify_list) { -#define F_CHANGE_MASK (FILE_NOTIFY_CHANGE_FILE | \ - FILE_NOTIFY_CHANGE_ATTRIBUTES | \ - FILE_NOTIFY_CHANGE_SIZE | \ - FILE_NOTIFY_CHANGE_LAST_WRITE | \ - FILE_NOTIFY_CHANGE_LAST_ACCESS | \ - FILE_NOTIFY_CHANGE_CREATION | \ - FILE_NOTIFY_CHANGE_EA | \ - FILE_NOTIFY_CHANGE_SECURITY) - -#define F_DELETE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \ - FILE_NOTIFY_CHANGE_DIR_NAME) - -#define F_CREATE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \ - FILE_NOTIFY_CHANGE_DIR_NAME) - - switch (code) { - case FAMChanged: - if (flags & F_CHANGE_MASK) - return(True); - break; - case FAMDeleted: - if (flags & F_DELETE_MASK) - return(True); - break; - case FAMCreated: - if (flags & F_CREATE_MASK) - return(True); - break; - default: - /* Ignore anything else. */ - break; - } - - return(False); - -#undef F_CHANGE_MASK -#undef F_DELETE_MASK -#undef F_CREATE_MASK -} + struct fam_notify_ctx *ctx; -static BOOL -fam_pump_events(struct fam_req_info * info, uint32_t flags) -{ - FAMEvent ev; + DEBUG(5, ("Re-opening FAM connection\n")); - for (;;) { + FAMClose(fam_conn); - /* If we are draining the event queue we must keep going until we find - * the correct FAMAcknowledge event or the connection drops. Otherwise - * we should stop when there are no more events pending. - */ - if (flags != FAM_EVENT_DRAIN && !FAMPending(&global_fc)) { - break; + if (!NT_STATUS_IS_OK(fam_open_connection(fam_conn, event_ctx))) { + DEBUG(5, ("Re-opening fam connection failed\n")); + return; } - if (FAMNextEvent(&global_fc, &ev) < 0) { - DEBUG(0, ("failed to fetch pending FAM event\n")); - DEBUGADD(0, ("resetting FAM connection\n")); - FAMClose(&global_fc); - FAMCONNECTION_GETFD(&global_fc) = -1; - return(False); + for (ctx = notify_list; ctx; ctx = ctx->next) { + FAMMonitorDirectory(fam_conn, ctx->path, &ctx->fr, NULL); } +} - DEBUG(FAM_TRACE_LOW, ("FAM event %s on '%s' for request %d\n", - fam_event_str(ev.code), ev.filename, ev.fr.reqnum)); +static void fam_handler(struct event_context *event_ctx, + struct fd_event *fd_event, + uint16 flags, + void *private_data) +{ + FAMConnection *fam_conn = (FAMConnection *)private_data; + FAMEvent fam_event; + struct fam_notify_ctx *ctx; + char *name; + + if (FAMPending(fam_conn) == 0) { + DEBUG(10, ("fam_handler called but nothing pending\n")); + return; + } - switch (ev.code) { - case FAMAcknowledge: - /* FAM generates an ACK event when we cancel a monitor. We need - * this to know when it is safe to free out request state - * structure. - */ - if (info->generation == global_fc_generation && - info->req.reqnum == ev.fr.reqnum && - flags == FAM_EVENT_DRAIN) { - return(True); - } + if (FAMNextEvent(fam_conn, &fam_event) != 1) { + DEBUG(10, ("FAMNextEvent returned an error\n")); + TALLOC_FREE(fd_event); + fam_reopen(fam_conn, event_ctx, fam_notify_list); + return; + } - case FAMEndExist: - case FAMExists: - /* Ignore these. FAM sends these enumeration events when we - * start monitoring. If we are monitoring a directory, we will - * get a FAMExists event for each directory entry. - */ + if ((fam_event.code != FAMCreated) && (fam_event.code != FAMDeleted)) { + DEBUG(10, ("Ignoring code FAMCode %d for file %s\n", + (int)fam_event.code, fam_event.filename)); + return; + } - /* TODO: we might be able to use these to implement recursive - * monitoring of entire subtrees. - */ - case FAMMoved: - /* These events never happen. A move or rename shows up as a - * create/delete pair. - */ - case FAMStartExecuting: - case FAMStopExecuting: - /* We might get these, but we just don't care. */ - break; - - case FAMChanged: - case FAMDeleted: - case FAMCreated: - if (info->generation != global_fc_generation) { - /* Ignore this; the req number can't be matched. */ - break; + for (ctx = fam_notify_list; ctx; ctx = ctx->next) { + if (memcmp(&fam_event.fr, &ctx->fr, sizeof(FAMRequest)) == 0) { + break; } + } - if (info->req.reqnum == ev.fr.reqnum) { - /* This is the event the caller was interested in. */ - DEBUG(FAM_TRACE, ("handling FAM %s event on '%s'\n", - fam_event_str(ev.code), ev.filename)); - /* Ignore events if we are draining this request. */ - if (flags != FAM_EVENT_DRAIN) { - return(fam_handle_event(ev.code, flags)); - } - break; - } else { - /* Caller doesn't want this event. Stash the result so we - * can come back to it. Unfortunately, FAM doesn't - * guarantee to give us back evinfo. - */ - struct fam_req_info * evinfo = - (struct fam_req_info *)ev.userdata; - - if (evinfo) { - DEBUG(FAM_TRACE, ("storing FAM %s event for winter\n", - fam_event_str(ev.code))); - evinfo->state = FAM_REQ_FIRED; - evinfo->code = ev.code; - } else { - DEBUG(2, ("received FAM %s notification for %s, " - "but userdata was unexpectedly NULL\n", - fam_event_str(ev.code), ev.filename)); - } - break; - } + if (ctx == NULL) { + DEBUG(5, ("Discarding event for file %s\n", + fam_event.filename)); + return; + } - default: - DEBUG(0, ("ignoring unknown FAM event code %d for `%s`\n", - ev.code, ev.filename)); + if ((name = strrchr_m(fam_event.filename, '\\')) == NULL) { + name = fam_event.filename; } - } - /* No more notifications pending. */ - return(False); + notify_fsp(ctx->fsp, + fam_event.code == FAMCreated + ? NOTIFY_ACTION_ADDED : NOTIFY_ACTION_REMOVED, + name); } -static BOOL -fam_test_connection(void) +static int fam_notify_ctx_destructor(struct fam_notify_ctx *ctx) { - FAMConnection fc; + if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) { + FAMCancelMonitor(&fam_connection, &ctx->fr); + } + DLIST_REMOVE(fam_notify_list, ctx); + return 0; +} - /* On IRIX FAMOpen2 leaks 960 bytes in 48 blocks. It's a deliberate leak - * in the library and there's nothing we can do about it here. - */ - if (FAMOpen2(&fc, "smbd probe") < 0) - return(False); +static void *fam_notify_add(TALLOC_CTX *mem_ctx, + struct event_context *event_ctx, + files_struct *fsp, uint32 *filter) +{ + struct fam_notify_ctx *ctx; + pstring fullpath; - FAMClose(&fc); - return(True); -} + if ((*filter & FILE_NOTIFY_CHANGE_FILE) == 0) { + DEBUG(10, ("filter = %u, no FILE_NOTIFY_CHANGE_FILE\n", + *filter)); + return NULL; + } -/* ------------------------------------------------------------------------- */ + /* FAM needs an absolute pathname. */ -static void * -fam_register_notify(connection_struct * conn, - char * path, - uint32 flags) -{ - struct fam_req_info * info; - - if (!fam_check_reconnect()) { - return(False); - } - - if ((info = SMB_MALLOC_P(struct fam_req_info)) == NULL) { - DEBUG(0, ("malloc of %u bytes failed\n", (unsigned int)sizeof(struct fam_req_info))); - return(NULL); - } - - if (fam_monitor_path(conn, info, path, flags)) { - return(info); - } else { - SAFE_FREE(info); - return(NULL); - } -} + pstrcpy(fullpath, fsp->fsp_name); + if (!canonicalize_path(fsp->conn, fullpath)) { + DEBUG(0, ("failed to canonicalize path '%s'\n", fullpath)); + return NULL; + } -static BOOL -fam_check_notify(connection_struct * conn, - uint16_t vuid, - char * path, - uint32_t flags, - void * data, - time_t when) -{ - struct fam_req_info * info; + if (*fullpath != '/') { + DEBUG(0, ("canonicalized path '%s' into `%s`\n", fsp->fsp_name, + fullpath)); + DEBUGADD(0, ("but expected an absolute path\n")); + return NULL; + } + + if (!(ctx = TALLOC_P(mem_ctx, struct fam_notify_ctx))) { + return NULL; + } - info = (struct fam_req_info *)data; - SMB_ASSERT(info != NULL); + ctx->fsp = fsp; + ctx->fam_connection = &fam_connection; - DEBUG(10, ("checking FAM events for `%s`\n", path)); + /* + * The FAM module in this early state will only take care of + * FAMCreated and FAMDeleted events + */ - if (info->state == FAM_REQ_FIRED) { - DEBUG(FAM_TRACE, ("handling previously fired FAM %s event\n", - fam_event_str(info->code))); - info->state = FAM_REQ_MONITORING; - return(fam_handle_event(info->code, flags)); - } + ctx->filter = FILE_NOTIFY_CHANGE_FILE; - if (!fam_check_reconnect()) { - return(False); - } + if (!(ctx->path = talloc_strdup(ctx, fullpath))) { + DEBUG(0, ("talloc_strdup failed\n")); + TALLOC_FREE(ctx); + return NULL; + } - if (info->generation != global_fc_generation) { - DEBUG(FAM_TRACE, ("reapplying stale FAM monitor to %s\n", path)); - fam_monitor_path(conn, info, path, flags); - return(False); - } + /* + * Leave the rest to smbd itself + */ - return(fam_pump_events(info, flags)); -} + *filter &= ~FILE_NOTIFY_CHANGE_FILE; -static void -fam_remove_notify(void * data) -{ - struct fam_req_info * info; - - if ((info = (struct fam_req_info *)data) == NULL) - return; - - /* No need to reconnect. If the FAM connection is gone, there's no need to - * cancel and we can safely let FAMCancelMonitor fail. If it we - * reconnected, then the generation check will stop us cancelling the wrong - * request. - */ - - if ((FAMCONNECTION_GETFD(&global_fc) != -1) - && (info->generation == global_fc_generation)) { - DEBUG(FAM_TRACE, ("removing FAM notification for request %d\n", - info->req.reqnum)); - FAMCancelMonitor(&global_fc, &(info->req)); - - /* Soak up all events until the FAMAcknowledge. We can't free - * our request state until we are sure there are no more events in - * flight. + DLIST_ADD(fam_notify_list, ctx); + talloc_set_destructor(ctx, fam_notify_ctx_destructor); + + /* + * Only directories monitored so far */ - fam_pump_events(info, FAM_EVENT_DRAIN); - } - SAFE_FREE(info); + if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) { + FAMMonitorDirectory(ctx->fam_connection, ctx->path, &ctx->fr, + NULL); + } + else { + /* + * If the re-open is successful, this will establish the + * FAMMonitor from the list + */ + fam_reopen(ctx->fam_connection, event_ctx, fam_notify_list); + } + + return ctx; } -struct cnotify_fns * fam_notify_init(void) +static struct cnotify_fns global_fam_notify = +{ + fam_notify_add, +}; + +struct cnotify_fns *fam_notify_init(struct event_context *event_ctx) { - FAMCONNECTION_GETFD(&global_fc) = -1; - if (!fam_test_connection()) { - DEBUG(0, ("FAM file change notifications not available\n")); - return(NULL); - } + ZERO_STRUCT(fam_connection); + FAMCONNECTION_GETFD(&fam_connection) = -1; + + if (!NT_STATUS_IS_OK(fam_open_connection(&fam_connection, + event_ctx))) { + DEBUG(0, ("FAM file change notifications not available\n")); + return NULL; + } - DEBUG(FAM_TRACE, ("enabling FAM change notifications\n")); - return &global_fam_notify; + DEBUG(10, ("enabling FAM change notifications\n")); + return &global_fam_notify; } #endif /* HAVE_FAM_CHANGE_NOTIFY */ diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 0787a3eec5..773a7565c5 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -3,6 +3,7 @@ change notify handling - hash based implementation Copyright (C) Jeremy Allison 1994-1998 Copyright (C) Andrew Tridgell 2000 + Copyright (C) Volker Lendecke 2007 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 @@ -21,16 +22,26 @@ #include "includes.h" -struct change_data { +struct hash_change_data { time_t last_check_time; /* time we last checked this entry */ - struct timespec modify_time; /* Info from the directory we're monitoring. */ - struct timespec status_time; /* Info from the directory we're monitoring. */ - time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ - unsigned int num_entries; /* Zero or the number of files in the directory. */ + struct timespec modify_time; /* Info from the directory we're + * monitoring. */ + struct timespec status_time; /* Info from the directory we're + * monitoring. */ + time_t total_time; /* Total time of all directory entries - don't care + * if it wraps. */ + unsigned int num_entries; /* Zero or the number of files in the + * directory. */ unsigned int mode_sum; unsigned char name_hash[16]; }; +struct hash_notify_ctx { + struct hash_change_data *data; + files_struct *fsp; + char *path; + uint32 filter; +}; /* Compare struct timespec. */ #define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec)) @@ -40,7 +51,8 @@ struct change_data { *****************************************************************************/ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, - struct change_data *data, struct change_data *old_data) + struct hash_change_data *data, + struct hash_change_data *old_data) { SMB_STRUCT_STAT st; pstring full_name; @@ -71,7 +83,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, } if (S_ISDIR(st.st_mode) && - (flags & ~(FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME)) == 0) + (flags & ~(FILE_NOTIFY_CHANGE_FILE_NAME + | FILE_NOTIFY_CHANGE_DIR_NAME)) == 0) { /* This is the case of a client wanting to know only when * the contents of a directory changes. Since any file @@ -81,11 +94,6 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, return True; } - if (lp_change_notify_timeout(SNUM(conn)) <= 0) { - /* It change notify timeout has been disabled, never scan the directory. */ - return True; - } - /* * If we are to watch for changes that are only stored * in inodes of files, not in the directory inode, we must @@ -138,10 +146,13 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * If requested hash the names. */ - if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_FILE)) { + if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME + |FILE_NOTIFY_CHANGE_FILE_NAME + |FILE_NOTIFY_CHANGE_FILE)) { int i; unsigned char tmp_hash[16]; - mdfour(tmp_hash, (const unsigned char *)fname, strlen(fname)); + mdfour(tmp_hash, (const unsigned char *)fname, + strlen(fname)); for (i=0;i<16;i++) data->name_hash[i] ^= tmp_hash[i]; } @@ -150,7 +161,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * If requested sum the mode_t's. */ - if (flags & (FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SECURITY)) + if (flags & (FILE_NOTIFY_CHANGE_ATTRIBUTES + |FILE_NOTIFY_CHANGE_SECURITY)) data->mode_sum += st.st_mode; } @@ -159,77 +171,111 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, return True; } -/**************************************************************************** - Register a change notify request. -*****************************************************************************/ - -static void *hash_register_notify(connection_struct *conn, char *path, uint32 flags) +static void hash_change_notify_handler(struct event_context *event_ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) { - struct change_data data; + struct hash_change_data *new_data; + struct hash_notify_ctx *ctx = + talloc_get_type_abort(private_data, + struct hash_notify_ctx); - if (!notify_hash(conn, path, flags, &data, NULL)) - return NULL; + TALLOC_FREE(te); - data.last_check_time = time(NULL); + if (!(new_data = TALLOC_P(ctx, struct hash_change_data))) { + DEBUG(0, ("talloc failed\n")); + /* + * No new timed event; + */ + return; + } - return (void *)memdup(&data, sizeof(data)); + if (!notify_hash(ctx->fsp->conn, ctx->fsp->fsp_name, + ctx->filter, new_data, ctx->data) + || TIMESTAMP_NEQ(new_data->modify_time, ctx->data->modify_time) + || TIMESTAMP_NEQ(new_data->status_time, ctx->data->status_time) + || new_data->total_time != ctx->data->total_time + || new_data->num_entries != ctx->data->num_entries + || new_data->mode_sum != ctx->data->mode_sum + || (memcmp(new_data->name_hash, ctx->data->name_hash, + sizeof(new_data->name_hash)))) { + notify_fsp(ctx->fsp, 0, NULL); + } + + TALLOC_FREE(ctx->data); + ctx->data = new_data; + + event_add_timed( + event_ctx, ctx, + timeval_current_ofs( + lp_change_notify_timeout(SNUM(ctx->fsp->conn)), 0), + "hash_change_notify_handler", + hash_change_notify_handler, ctx); } -/**************************************************************************** - Check if a change notify should be issued. - A time of zero means instantaneous check - don't modify the last check time. -*****************************************************************************/ -static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) + +static void *hash_notify_add(TALLOC_CTX *mem_ctx, + struct event_context *event_ctx, + files_struct *fsp, + uint32 *filter) { - struct change_data *data = (struct change_data *)datap; - struct change_data data2; - int cnto = lp_change_notify_timeout(SNUM(conn)); + struct hash_notify_ctx *ctx; + int timeout = lp_change_notify_timeout(SNUM(fsp->conn)); + pstring fullpath; - if (t && cnto <= 0) { - /* Change notify turned off on this share. - * Only scan when (t==0) - we think something changed. */ - return False; + if (timeout <= 0) { + /* It change notify timeout has been disabled, never scan the + * directory. */ + return NULL; } - if (t && t < data->last_check_time + cnto) { - return False; + pstrcpy(fullpath, fsp->fsp_name); + if (!canonicalize_path(fsp->conn, fullpath)) { + DEBUG(0, ("failed to canonicalize path '%s'\n", fullpath)); + return NULL; } - if (!change_to_user(conn,vuid)) - return True; - if (!set_current_service(conn,FLAG_CASELESS_PATHNAMES,True)) { - change_to_root_user(); - return True; + if (*fullpath != '/') { + DEBUG(0, ("canonicalized path '%s' into `%s`\n", fsp->fsp_name, + fullpath)); + DEBUGADD(0, ("but expected an absolute path\n")); + return NULL; + } + + if (!(ctx = TALLOC_P(mem_ctx, struct hash_notify_ctx))) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - if (!notify_hash(conn, path, flags, &data2, data) || - TIMESTAMP_NEQ(data2.modify_time, data->modify_time) || - TIMESTAMP_NEQ(data2.status_time, data->status_time) || - data2.total_time != data->total_time || - data2.num_entries != data->num_entries || - data2.mode_sum != data->mode_sum || - memcmp(data2.name_hash, data->name_hash, sizeof(data2.name_hash))) { - change_to_root_user(); - return True; + if (!(ctx->path = talloc_strdup(ctx, fullpath))) { + DEBUG(0, ("talloc_strdup failed\n")); + TALLOC_FREE(ctx); + return NULL; } - if (t) { - data->last_check_time = t; + if (!(ctx->data = TALLOC_P(ctx, struct hash_change_data))) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(ctx); + return NULL; } - change_to_root_user(); + ctx->fsp = fsp; - return False; -} + /* + * Don't change the Samba filter, hash can only be a very bad attempt + * anyway. + */ + ctx->filter = *filter; -/**************************************************************************** - Remove a change notify data structure. -*****************************************************************************/ + notify_hash(fsp->conn, ctx->path, ctx->filter, ctx->data, NULL); -static void hash_remove_notify(void *datap) -{ - free(datap); + event_add_timed(event_ctx, ctx, timeval_current_ofs(timeout, 0), + "hash_change_notify_handler", + hash_change_notify_handler, ctx); + + return (void *)ctx; } /**************************************************************************** @@ -240,22 +286,7 @@ struct cnotify_fns *hash_notify_init(void) { static struct cnotify_fns cnotify; - cnotify.register_notify = hash_register_notify; - cnotify.check_notify = hash_check_notify; - cnotify.remove_notify = hash_remove_notify; - cnotify.select_time = 60; /* Start with 1 minute default. */ - cnotify.notification_fd = -1; + cnotify.notify_add = hash_notify_add; return &cnotify; } - -/* - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); - - chain_size = 0; - file_chain_reset(); - - uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(cnbp->request_buf,smb_uid); -*/ diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 0c20effc3d..0b5784f3d0 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -3,6 +3,7 @@ Version 3.0 change notify handling - linux kernel based implementation Copyright (C) Andrew Tridgell 2000 + Copyright (C) Volker Lendecke 2007 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 @@ -23,10 +24,6 @@ #if HAVE_KERNEL_CHANGE_NOTIFY -#define FD_PENDING_SIZE 20 -static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; -static SIG_ATOMIC_T signals_received; - #ifndef DN_ACCESS #define DN_ACCESS 0x00000001 /* File accessed in directory */ #define DN_MODIFY 0x00000002 /* File modified in directory */ @@ -55,10 +52,16 @@ static SIG_ATOMIC_T signals_received; determine if a directory has changed. *****************************************************************************/ -struct change_data { - int directory_handle; +struct dnotify_ctx { + struct dnotify_ctx *prev, *next; + + int fd; + files_struct *fsp; }; +static struct dnotify_ctx *dnotify_list; +static int dnotify_signal_pipe[2]; + /**************************************************************************** The signal handler for change notify. The Linux kernel has a bug in that we should be able to block any @@ -68,107 +71,91 @@ struct change_data { test case for the kernel hackers. JRA. *****************************************************************************/ -static void signal_handler(int sig, siginfo_t *info, void *unused) +static void dnotify_signal_handler(int sig, siginfo_t *info, void *unused) { - if (signals_received < FD_PENDING_SIZE - 1) { - fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd; - signals_received++; - } /* Else signal is lost. */ + int saved_errno; + + /* + * According to http://www.opengroup.org/onlinepubs/009695399/ write + * to a pipe either writes all or nothing, so we can safely write a + * full sizeof(int) and not risk the pipe to become out of sync with + * the receiving end. + * + * We don't care about the result of the write() call. If the pipe is + * full, then this signal is lost, we can't do anything about it. + */ + + saved_errno = errno; + write(dnotify_signal_pipe[1], (const void *)&info->si_fd, sizeof(int)); + errno = saved_errno; + sys_select_signal(RT_SIGNAL_NOTIFY); } /**************************************************************************** - Check if a change notify should be issued. - time non-zero means timeout check (used for hash). Ignore this (async method - where time is zero will be used instead). + The upper level handler informed when the pipe is ready for reading *****************************************************************************/ -static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t) +static void dnotify_pipe_handler(struct event_context *event_ctx, + struct fd_event *event, + uint16 flags, + void *private_data) { - struct change_data *data = (struct change_data *)datap; - int i; - BOOL ret = False; - - if (t) - return False; - - BlockSignals(True, RT_SIGNAL_NOTIFY); - for (i = 0; i < signals_received; i++) { - if (data->directory_handle == (int)fd_pending_array[i]) { - DEBUG(3,("kernel_check_notify: kernel change notify on %s fd[%d]=%d (signals_received=%d)\n", - path, i, (int)fd_pending_array[i], (int)signals_received )); - - close((int)fd_pending_array[i]); - fd_pending_array[i] = (SIG_ATOMIC_T)-1; - if (signals_received - i - 1) { - memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); - } - data->directory_handle = -1; - signals_received--; - ret = True; - break; - } + int res, fd; + struct dnotify_ctx *ctx; + + res = read(dnotify_signal_pipe[0], (void *)&fd, sizeof(int)); + + if (res == -1) { + DEBUG(0, ("Read from the dnotify pipe failed: %s\n", + strerror(errno))); + TALLOC_FREE(event); /* Don't try again */ + return; } - BlockSignals(False, RT_SIGNAL_NOTIFY); - return ret; -} -/**************************************************************************** - Remove a change notify data structure. -*****************************************************************************/ + if (res != sizeof(int)) { + smb_panic("read from dnotify pipe gave wrong number of " + "bytes\n"); + } -static void kernel_remove_notify(void *datap) -{ - struct change_data *data = (struct change_data *)datap; - int fd = data->directory_handle; - if (fd != -1) { - int i; - BlockSignals(True, RT_SIGNAL_NOTIFY); - for (i = 0; i < signals_received; i++) { - if (fd == (int)fd_pending_array[i]) { - fd_pending_array[i] = (SIG_ATOMIC_T)-1; - if (signals_received - i - 1) { - memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); - } - data->directory_handle = -1; - signals_received--; - break; - } + for (ctx = dnotify_list; ctx; ctx = ctx->next) { + if (ctx->fd == fd) { + notify_fsp(ctx->fsp, 0, NULL); } - close(fd); - BlockSignals(False, RT_SIGNAL_NOTIFY); } - SAFE_FREE(data); - DEBUG(3,("kernel_remove_notify: fd=%d\n", fd)); } /**************************************************************************** Register a change notify request. *****************************************************************************/ -static void *kernel_register_notify(connection_struct *conn, char *path, uint32 flags) +static int kernel_register_notify(connection_struct *conn, char *path, + uint32 flags) { - struct change_data data; int fd; unsigned long kernel_flags; fd = sys_open(path,O_RDONLY, 0); if (fd == -1) { - DEBUG(3,("Failed to open directory %s for change notify\n", path)); - return NULL; + DEBUG(3,("Failed to open directory %s for change notify\n", + path)); + return -1; } if (sys_fcntl_long(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) { DEBUG(3,("Failed to set signal handler for change notify\n")); - return NULL; + close(fd); + return -1; } - kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion changes everything! */ + kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion + * changes + * everything! */ if (flags & FILE_NOTIFY_CHANGE_FILE) kernel_flags |= DN_MODIFY; - if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME|DN_DELETE; + if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags + |= DN_RENAME + |DN_DELETE; if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_ATTRIB; if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY; if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY; @@ -176,19 +163,20 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32 if (flags & FILE_NOTIFY_CHANGE_CREATION) kernel_flags |= DN_CREATE; if (flags & FILE_NOTIFY_CHANGE_SECURITY) kernel_flags |= DN_ATTRIB; if (flags & FILE_NOTIFY_CHANGE_EA) kernel_flags |= DN_ATTRIB; - if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE; + if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags + |= DN_RENAME + |DN_DELETE; if (sys_fcntl_long(fd, F_NOTIFY, kernel_flags) == -1) { DEBUG(3,("Failed to set async flag for change notify\n")); - return NULL; + close(fd); + return -1; } - data.directory_handle = fd; - - DEBUG(3,("kernel change notify on %s (ntflags=0x%x flags=0x%x) fd=%d\n", - path, (int)flags, (int)kernel_flags, fd)); + DEBUG(3,("kernel change notify on %s (ntflags=0x%x flags=0x%x) " + "fd=%d\n", path, (int)flags, (int)kernel_flags, fd)); - return (void *)memdup(&data, sizeof(data)); + return fd; } /**************************************************************************** @@ -206,18 +194,74 @@ static BOOL kernel_notify_available(void) return ret == 0; } +static int dnotify_ctx_destructor(struct dnotify_ctx *ctx) +{ + close(ctx->fd); + DLIST_REMOVE(dnotify_list, ctx); + return 0; +} + +static void *kernel_notify_add(TALLOC_CTX *mem_ctx, + struct event_context *event_ctx, + files_struct *fsp, + uint32 *filter) +{ + struct dnotify_ctx *ctx; + + if (!(ctx = TALLOC_P(mem_ctx, struct dnotify_ctx))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + ctx->fsp = fsp; + ctx->fd = kernel_register_notify(fsp->conn, fsp->fsp_name, *filter); + + if (ctx->fd == -1) { + TALLOC_FREE(ctx); + return NULL; + } + + DLIST_ADD(dnotify_list, ctx); + talloc_set_destructor(ctx, dnotify_ctx_destructor); + + return ctx; +} + /**************************************************************************** Setup kernel based change notify. ****************************************************************************/ -struct cnotify_fns *kernel_notify_init(void) +struct cnotify_fns *kernel_notify_init(struct event_context *event_ctx) { static struct cnotify_fns cnotify; struct sigaction act; + if (pipe(dnotify_signal_pipe) == -1) { + DEBUG(0, ("Failed to create signal pipe: %s\n", + strerror(errno))); + return NULL; + } + + if ((set_blocking(dnotify_signal_pipe[0], False) == -1) + || (set_blocking(dnotify_signal_pipe[1], False) == -1)) { + DEBUG(0, ("Failed to set signal pipe to non-blocking: %s\n", + strerror(errno))); + close(dnotify_signal_pipe[0]); + close(dnotify_signal_pipe[1]); + return NULL; + } + + if (event_add_fd(event_ctx, NULL, dnotify_signal_pipe[0], + EVENT_FD_READ, dnotify_pipe_handler, NULL) == NULL) { + DEBUG(0, ("Failed to set signal event handler\n")); + close(dnotify_signal_pipe[0]); + close(dnotify_signal_pipe[1]); + return NULL; + } + ZERO_STRUCT(act); - act.sa_sigaction = signal_handler; + act.sa_sigaction = dnotify_signal_handler; act.sa_flags = SA_SIGINFO; sigemptyset( &act.sa_mask ); if (sigaction(RT_SIGNAL_NOTIFY, &act, NULL) != 0) { @@ -228,11 +272,7 @@ struct cnotify_fns *kernel_notify_init(void) if (!kernel_notify_available()) return NULL; - cnotify.register_notify = kernel_register_notify; - cnotify.check_notify = kernel_check_notify; - cnotify.remove_notify = kernel_remove_notify; - cnotify.select_time = -1; - cnotify.notification_fd = -1; + cnotify.notify_add = kernel_notify_add; /* the signal can start off blocked due to a bug in bash */ BlockSignals(False, RT_SIGNAL_NOTIFY); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 13e290135a..84ea6a150f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1776,11 +1776,6 @@ int reply_ntrename(connection_struct *conn, return ERROR_NT(status); } - /* - * Win2k needs a changenotify request response before it will - * update after a rename.. - */ - process_pending_change_notify_queue((time_t)0); outsize = set_message(outbuf,0,0,False); END_PROFILE(SMBntrename); @@ -1834,7 +1829,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, } } - if (fsp->notify->num_changes > 0) { + if (fsp->notify->num_changes != 0) { /* * We've got changes pending, respond immediately @@ -1921,13 +1916,6 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); - /* - * Win2k needs a changenotify request response before it will - * update after a rename.. - */ - - process_pending_change_notify_queue((time_t)0); - return -1; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2a52da12b3..cfecd7fecb 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -304,9 +304,6 @@ static void async_processing(fd_set *pfds) exit_server_cleanly("termination signal"); } - /* check for async change notify events */ - process_pending_change_notify_queue(0); - /* check for sighup processing */ if (reload_after_sighup) { change_to_root_user(); @@ -468,7 +465,6 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) START_PROFILE(smbd_idle); maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds); - maxfd = select_on_fd(change_notify_fd(), maxfd, &r_fds); maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds); selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to); @@ -525,20 +521,6 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) goto again; } - if ((change_notify_fd() >= 0) && FD_ISSET(change_notify_fd(), - &r_fds)) { - - process_pending_change_notify_queue((time_t)0); - - /* - * Same comment as for oplock processing applies here. We - * might have done I/O on the client socket. - */ - - goto again; - } - - return receive_smb(smbd_server_fd(), buffer, 0); } @@ -1251,16 +1233,9 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) static int setup_select_timeout(void) { int select_timeout; - int t; select_timeout = blocking_locks_timeout_ms(SMBD_SELECT_TIMEOUT*1000); - t = change_notify_timeout(); - DEBUG(10, ("change_notify_timeout: %d\n", t)); - if (t != -1) { - select_timeout = MIN(select_timeout, t*1000); - } - if (print_notify_messages_pending()) { select_timeout = MIN(select_timeout, 1000); } @@ -1458,12 +1433,6 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); update_monitored_printq_cache(); - /* - * Check to see if we have any change notifies - * outstanding on the queue. - */ - process_pending_change_notify_queue(t); - /* * Now we are root, check if the log files need pruning. * Force a log file check. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2763924d4f..7cb086841d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1982,12 +1982,6 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - /* - * Win2k needs a changenotify request response before it will - * update after a rename.. - */ - process_pending_change_notify_queue((time_t)0); - outsize = set_message(outbuf,0,0,False); END_PROFILE(SMBunlink); @@ -4490,11 +4484,6 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - /* - * Win2k needs a changenotify request response before it will - * update after a rename.. - */ - process_pending_change_notify_queue((time_t)0); outsize = set_message(outbuf,0,0,False); END_PROFILE(SMBmv); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9b6743f76b..9efe63a82c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1074,9 +1074,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, dbgtext( "(pid %d)\n", (int)sys_getpid() ); } - /* Setup the minimum value for a change notify wait time (seconds). */ - set_change_notify_timeout(lp_change_notify_timeout(snum)); - /* we've finished with the user stuff - go back to root */ change_to_root_user(); return(conn); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c9cb2c5b4f..b35b27f276 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4487,7 +4487,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return ERROR_NT(status); } - process_pending_change_notify_queue((time_t)0); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); -- cgit From 420e577004cdb9e00d290d3681df3b3196336d81 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 21 Jan 2007 16:05:49 +0000 Subject: r20932: This is the basic infrastructure for inotify support. This is far from being complete, in particular the various mask bits are not correctly supported yet. Checkin in now, I want to see how the build farm likes it. Volker (This used to be commit c9a5d011a91359b242f6c26f46e96ecea6a44a3b) --- source3/smbd/notify.c | 5 + source3/smbd/notify_inotify.c | 263 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 source3/smbd/notify_inotify.c (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ce7680b49a..2493dea9ef 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -527,6 +527,11 @@ BOOL init_change_notify(void) { cnotify = NULL; +#if HAVE_INOTIFY + if ((cnotify == NULL) && lp_kernel_change_notify()) { + cnotify = inotify_notify_init(smbd_event_context()); + } +#endif #if HAVE_KERNEL_CHANGE_NOTIFY if (cnotify == NULL && lp_kernel_change_notify()) cnotify = kernel_notify_init(smbd_event_context()); diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c new file mode 100644 index 0000000000..92af6b473d --- /dev/null +++ b/source3/smbd/notify_inotify.c @@ -0,0 +1,263 @@ +/* + * inotify change notify support + * + * Copyright (c) Andrew Tridgell 2006 + * Copyright (c) Volker Lendecke 2007 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "includes.h" + +#include +#include + +#ifdef HAVE_INOTIFY + +#ifndef HAVE_INOTIFY_INIT +/* + glibc doesn't define these functions yet (as of March 2006) +*/ +static int inotify_init(void) +{ + return syscall(__NR_inotify_init); +} + +static int inotify_add_watch(int fd, const char *path, __u32 mask) +{ + return syscall(__NR_inotify_add_watch, fd, path, mask); +} + +static int inotify_rm_watch(int fd, int wd) +{ + return syscall(__NR_inotify_rm_watch, fd, wd); +} +#endif + +struct inotify_ctx { + struct inotify_ctx *prev, *next; + int wd; + files_struct *fsp; +}; + +static struct inotify_ctx *inotify_list; + +static int inotify_watch_fd; + +/* + map from a change notify mask to a inotify mask. Remove any bits + which we can handle +*/ +static const struct { + uint32_t notify_mask; + uint32_t inotify_mask; +} inotify_mapping[] = { + {FILE_NOTIFY_CHANGE_FILE_NAME, + IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO}, + {FILE_NOTIFY_CHANGE_DIR_NAME, + IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO}, + {FILE_NOTIFY_CHANGE_ATTRIBUTES, + IN_ATTRIB|IN_MOVED_TO|IN_MOVED_FROM|IN_MODIFY}, + {FILE_NOTIFY_CHANGE_LAST_WRITE, IN_ATTRIB}, + {FILE_NOTIFY_CHANGE_LAST_ACCESS, IN_ATTRIB}, + {FILE_NOTIFY_CHANGE_EA, IN_ATTRIB}, + {FILE_NOTIFY_CHANGE_SECURITY, IN_ATTRIB} +}; + +static uint32_t inotify_map(uint32 *filter) +{ + int i; + uint32_t out=0; + for (i=0;iwd) == -1) { + DEBUG(0, ("inotify_rm_watch failed: %s\n", strerror(errno))); + } + DLIST_REMOVE(inotify_list, ctx); + return 0; +} + +static void *inotify_add(TALLOC_CTX *mem_ctx, + struct event_context *event_ctx, + files_struct *fsp, uint32 *pfilter) +{ + struct inotify_ctx *ctx; + uint32_t inotify_mask; + pstring fullpath; + uint32 filter; + + filter = *pfilter; + if ((filter & (FILE_NOTIFY_CHANGE_FILE + |FILE_NOTIFY_CHANGE_DIR_NAME)) == 0) { + /* + * This first implementation only looks at create/delete + */ + return NULL; + } + + inotify_mask = inotify_map(&filter); + + if (inotify_mask == 0) { + DEBUG(10, ("inotify_mask == 0, nothing to do\n")); + return NULL; + } + + pstrcpy(fullpath, fsp->fsp_name); + if (!canonicalize_path(fsp->conn, fullpath)) { + DEBUG(0, ("failed to canonicalize path '%s'\n", fullpath)); + return NULL; + } + + if (*fullpath != '/') { + DEBUG(0, ("canonicalized path '%s' into `%s`\n", fsp->fsp_name, + fullpath)); + DEBUGADD(0, ("but expected an absolute path\n")); + return NULL; + } + + if (!(ctx = TALLOC_P(mem_ctx, struct inotify_ctx))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + ctx->fsp = fsp; + ctx->wd = inotify_add_watch(inotify_watch_fd, fullpath, inotify_mask); + + if (ctx->wd == -1) { + DEBUG(5, ("inotify_add_watch failed: %s\n", strerror(errno))); + TALLOC_FREE(ctx); + return NULL; + } + + DLIST_ADD(inotify_list, ctx); + talloc_set_destructor(ctx, inotify_ctx_destructor); + + *pfilter = filter; + return ctx; +} + +static void inotify_dispatch(struct inotify_event *e) +{ + struct inotify_ctx *ctx; + + for (ctx = inotify_list; ctx; ctx = ctx->next) { + if (ctx->wd == e->wd) { + break; + } + } + + if (ctx == NULL) { + /* not found */ + return; + } + + if (e->mask & IN_CREATE) { + notify_fsp(ctx->fsp, NOTIFY_ACTION_ADDED, e->name); + } + + if (e->mask & IN_DELETE) { + notify_fsp(ctx->fsp, NOTIFY_ACTION_REMOVED, e->name); + } +} + +static void inotify_callback(struct event_context *event_ctx, + struct fd_event *event, + uint16 flags, + void *private_data) +{ + char *buf, *p; + int bufsize; + + /* + we must use FIONREAD as we cannot predict the length of the + filenames, and thus can't know how much to allocate + otherwise + */ + if ((ioctl(inotify_watch_fd, FIONREAD, &bufsize) != 0) + || (bufsize == 0)) { + DEBUG(0,("No data on inotify fd?!\n")); + return; + } + + if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) { + DEBUG(0, ("malloc failed\n")); + return; + } + + if (read(inotify_watch_fd, buf, bufsize) != bufsize) { + DEBUG(0,("Failed to read all inotify data\n")); + SAFE_FREE(buf); + return; + } + + p = buf; + + while (bufsize > sizeof(struct inotify_event)) { + struct inotify_event *iev = (struct inotify_event *)p; + size_t len = sizeof(struct inotify_event) + iev->len; + + if ((len > bufsize) + || ((iev->len != 0) && (iev->name[iev->len-1] != '\0'))) { + smb_panic("invalid inotify reply\n"); + } + + inotify_dispatch(iev); + + p += len; + bufsize -= len; + } + + SAFE_FREE(buf); + return; +} + +static struct cnotify_fns inotify_fns = +{ + inotify_add, +}; + +struct cnotify_fns *inotify_notify_init(struct event_context *event_ctx) +{ + inotify_watch_fd = inotify_init(); + + DEBUG(10, ("inotify_notify_init called\n")); + + if (inotify_watch_fd == -1) { + DEBUG(0, ("inotify_init failed: %s\n", strerror(errno))); + return NULL; + } + + if (event_add_fd(event_ctx, NULL, inotify_watch_fd, + EVENT_FD_READ, inotify_callback, + NULL) == NULL) { + DEBUG(0, ("event_add_fd failed\n")); + close(inotify_watch_fd); + inotify_watch_fd = -1; + return NULL; + } + + return &inotify_fns; +} + +#endif -- cgit From 0de21e951544b5ee85b074427bda30fff3a1c9f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 21 Jan 2007 16:25:25 +0000 Subject: r20933: Fix the build without inotify (This used to be commit 4587d8097255c8b8fb8990bc8a13f8145986d29d) --- source3/smbd/notify_inotify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 92af6b473d..64ea62ff74 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -21,11 +21,11 @@ #include "includes.h" +#ifdef HAVE_INOTIFY + #include #include -#ifdef HAVE_INOTIFY - #ifndef HAVE_INOTIFY_INIT /* glibc doesn't define these functions yet (as of March 2006) -- cgit From 23e227ac391a3f674712bdd09a0581a02cbc8a7e Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 23 Jan 2007 04:12:51 +0000 Subject: r20966: Only attempt to reload the config file atfer the fork point if we are in daemon mode. If we are in inetd mode, there's really no point in rechecking it so soon. (This used to be commit 029d4bb5e3ea02a8a396adc3ca564a714bcdfdb8) --- source3/smbd/server.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e2f73285b3..0bb4ad5b04 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1065,8 +1065,12 @@ extern void build_options(BOOL screen); init_modules(); - /* possibly reload the services file. */ - reload_services(True); + /* Possibly reload the services file. Only worth doing in + * daemon mode. In inetd mode, we know we only just loaded this. + */ + if (is_daemon) { + reload_services(True); + } if (!init_account_policy()) { DEBUG(0,("Could not open account policy tdb.\n")); -- cgit From db8ee51cf26372eee5eed9bf177762fe090f720f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 23 Jan 2007 20:38:14 +0000 Subject: r20982: Fix a segfault -- I wonder why my make test did not show this earlier... (This used to be commit 4984b0627c84cc192868238c0936ca1a38628cd8) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2493dea9ef..c2f4572e7e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -512,7 +512,8 @@ static void notify_message_callback(int msgtype, struct process_id pid, for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; fsp = fsp_find_di_next(fsp)) { - if ((fsp->notify->requests != NULL) + if ((fsp->notify != NULL) + && (fsp->notify->requests != NULL) && (fsp->notify->requests->filter & msg.filter)) { notify_fsp(fsp, msg.action, msg.name); } -- cgit From 109bebe1f877ab2981a5c0d14ad0982a62436520 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 24 Jan 2007 14:53:03 +0000 Subject: r21002: Get rid of unused macros - merge change from 3_0_24 (This used to be commit 9d23cf0cc4a8974bf0cf74b219a1138383083360) --- source3/smbd/nttrans.c | 32 ++++++++++++++++---------------- source3/smbd/trans2.c | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 40 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 84ea6a150f..07d345aacd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2744,44 +2744,44 @@ static int handle_nttrans(connection_struct *conn, switch(state->call) { case NT_TRANSACT_CREATE: { - START_PROFILE_NESTED(NT_transact_create); + START_PROFILE(NT_transact_create); outsize = call_nt_transact_create(conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(NT_transact_create); + END_PROFILE(NT_transact_create); break; } case NT_TRANSACT_IOCTL: { - START_PROFILE_NESTED(NT_transact_ioctl); + START_PROFILE(NT_transact_ioctl); outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(NT_transact_ioctl); + END_PROFILE(NT_transact_ioctl); break; } case NT_TRANSACT_SET_SECURITY_DESC: { - START_PROFILE_NESTED(NT_transact_set_security_desc); + START_PROFILE(NT_transact_set_security_desc); outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(NT_transact_set_security_desc); + END_PROFILE(NT_transact_set_security_desc); break; } case NT_TRANSACT_NOTIFY_CHANGE: { - START_PROFILE_NESTED(NT_transact_notify_change); + START_PROFILE(NT_transact_notify_change); outsize = call_nt_transact_notify_change( conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, @@ -2789,56 +2789,56 @@ static int handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return, state->max_param_return); - END_PROFILE_NESTED(NT_transact_notify_change); + END_PROFILE(NT_transact_notify_change); break; } case NT_TRANSACT_RENAME: { - START_PROFILE_NESTED(NT_transact_rename); + START_PROFILE(NT_transact_rename); outsize = call_nt_transact_rename(conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(NT_transact_rename); + END_PROFILE(NT_transact_rename); break; } case NT_TRANSACT_QUERY_SECURITY_DESC: { - START_PROFILE_NESTED(NT_transact_query_security_desc); + START_PROFILE(NT_transact_query_security_desc); outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(NT_transact_query_security_desc); + END_PROFILE(NT_transact_query_security_desc); break; } #ifdef HAVE_SYS_QUOTAS case NT_TRANSACT_GET_USER_QUOTA: { - START_PROFILE_NESTED(NT_transact_get_user_quota); + START_PROFILE(NT_transact_get_user_quota); outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(NT_transact_get_user_quota); + END_PROFILE(NT_transact_get_user_quota); break; } case NT_TRANSACT_SET_USER_QUOTA: { - START_PROFILE_NESTED(NT_transact_set_user_quota); + START_PROFILE(NT_transact_set_user_quota); outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, size, bufsize, &state->setup, state->setup_count, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(NT_transact_set_user_quota); + END_PROFILE(NT_transact_set_user_quota); break; } #endif /* HAVE_SYS_QUOTAS */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b35b27f276..8afd3de130 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5091,147 +5091,147 @@ int handle_trans2(connection_struct *conn, switch(state->call) { case TRANSACT2_OPEN: { - START_PROFILE_NESTED(Trans2_open); + START_PROFILE(Trans2_open); outsize = call_trans2open( conn, inbuf, outbuf, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_open); + END_PROFILE(Trans2_open); break; } case TRANSACT2_FINDFIRST: { - START_PROFILE_NESTED(Trans2_findfirst); + START_PROFILE(Trans2_findfirst); outsize = call_trans2findfirst( conn, inbuf, outbuf, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_findfirst); + END_PROFILE(Trans2_findfirst); break; } case TRANSACT2_FINDNEXT: { - START_PROFILE_NESTED(Trans2_findnext); + START_PROFILE(Trans2_findnext); outsize = call_trans2findnext( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_findnext); + END_PROFILE(Trans2_findnext); break; } case TRANSACT2_QFSINFO: { - START_PROFILE_NESTED(Trans2_qfsinfo); + START_PROFILE(Trans2_qfsinfo); outsize = call_trans2qfsinfo( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_qfsinfo); + END_PROFILE(Trans2_qfsinfo); break; } case TRANSACT2_SETFSINFO: { - START_PROFILE_NESTED(Trans2_setfsinfo); + START_PROFILE(Trans2_setfsinfo); outsize = call_trans2setfsinfo( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_setfsinfo); + END_PROFILE(Trans2_setfsinfo); break; } case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: { - START_PROFILE_NESTED(Trans2_qpathinfo); + START_PROFILE(Trans2_qpathinfo); outsize = call_trans2qfilepathinfo( conn, inbuf, outbuf, size, bufsize, state->call, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_qpathinfo); + END_PROFILE(Trans2_qpathinfo); break; } case TRANSACT2_SETPATHINFO: case TRANSACT2_SETFILEINFO: { - START_PROFILE_NESTED(Trans2_setpathinfo); + START_PROFILE(Trans2_setpathinfo); outsize = call_trans2setfilepathinfo( conn, inbuf, outbuf, size, bufsize, state->call, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_setpathinfo); + END_PROFILE(Trans2_setpathinfo); break; } case TRANSACT2_FINDNOTIFYFIRST: { - START_PROFILE_NESTED(Trans2_findnotifyfirst); + START_PROFILE(Trans2_findnotifyfirst); outsize = call_trans2findnotifyfirst( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_findnotifyfirst); + END_PROFILE(Trans2_findnotifyfirst); break; } case TRANSACT2_FINDNOTIFYNEXT: { - START_PROFILE_NESTED(Trans2_findnotifynext); + START_PROFILE(Trans2_findnotifynext); outsize = call_trans2findnotifynext( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_findnotifynext); + END_PROFILE(Trans2_findnotifynext); break; } case TRANSACT2_MKDIR: { - START_PROFILE_NESTED(Trans2_mkdir); + START_PROFILE(Trans2_mkdir); outsize = call_trans2mkdir( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_mkdir); + END_PROFILE(Trans2_mkdir); break; } case TRANSACT2_GET_DFS_REFERRAL: { - START_PROFILE_NESTED(Trans2_get_dfs_referral); + START_PROFILE(Trans2_get_dfs_referral); outsize = call_trans2getdfsreferral( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_get_dfs_referral); + END_PROFILE(Trans2_get_dfs_referral); break; } case TRANSACT2_IOCTL: { - START_PROFILE_NESTED(Trans2_ioctl); + START_PROFILE(Trans2_ioctl); outsize = call_trans2ioctl( conn, inbuf, outbuf, size, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); - END_PROFILE_NESTED(Trans2_ioctl); + END_PROFILE(Trans2_ioctl); break; } -- cgit From 3bd12f9658ef5b2058183a561a7e451c40e68099 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 27 Jan 2007 02:33:21 +0000 Subject: r21035: Remove unneeded checks on incoming uid/gid for mknod (fifo) unix extensions code. Problem discovered by Anders Karlsson . Jeremy. (This used to be commit ec6033ad7c8d343969e3dcf59232cb16d075364f) --- source3/smbd/trans2.c | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8afd3de130..c67a52fe8d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4200,6 +4200,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_SET_FILE_UNIX_BASIC: { uint32 raw_unixmode; + BOOL delete_on_fail = False; if (total_data < 100) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -4247,8 +4248,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", uint32 dev_minor = IVAL(pdata,12); #endif - uid_t myuid = geteuid(); - gid_t mygid = getegid(); SMB_DEV_T dev = (SMB_DEV_T)0; if (tran_call == TRANSACT2_SETFILEINFO) @@ -4262,13 +4261,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", dev = makedev(dev_major, dev_minor); #endif - /* We can only create as the owner/group we are. */ - - if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE)) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); - if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE)) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); - switch (file_type) { #if defined(S_IFIFO) case UNIX_TYPE_FIFO: @@ -4298,8 +4290,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", 0%o for file %s\n", (double)dev, unixmode, fname )); /* Ok - do the mknod. */ - if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0) + if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* If any of the other "set" calls fail we + * don't want to end up with a half-constructed mknod. + */ + + delete_on_fail = True; if (lp_inherit_perms(SNUM(conn))) { inherit_access_acl( @@ -4307,9 +4306,18 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", fname, unixmode); } - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + if (SMB_VFS_STAT(conn, fname, &sbuf) != 0) { + int saved_errno = errno; + SMB_VFS_UNLINK(conn,fname); + errno = saved_errno; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + /* Ensure we don't try and change anything else. */ + raw_unixmode = SMB_MODE_NO_CHANGE; + size = get_file_size(sbuf); + tvs.modtime = sbuf.st_mtime; + tvs.actime = sbuf.st_atime; } /* @@ -4330,8 +4338,14 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", (unsigned int)set_owner, fname )); - if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) + if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) { + if (delete_on_fail) { + int saved_errno = errno; + SMB_VFS_UNLINK(conn,fname); + errno = saved_errno; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } /* @@ -4341,8 +4355,14 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", (unsigned int)set_owner, fname )); - if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) + if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) { + if (delete_on_fail) { + int saved_errno = errno; + SMB_VFS_UNLINK(conn,fname); + errno = saved_errno; + } return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } break; } -- cgit From 1e753db3d48038bc2812a5944e00a2f72b200ebf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 01:14:48 +0000 Subject: r21049: Start to refactor some of the setpath set code into separate functions (tridge mailed me a fresh batch) to make it easier to add the POSIX open we'll need soon. Jeremy. (This used to be commit 63bd8759fefe6af80186ab15b470658614690b48) --- source3/smbd/trans2.c | 147 +++++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 74 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c67a52fe8d..886240c72e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3742,7 +3742,69 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam } /**************************************************************************** - Reply to a TRANS2_SETFILEINFO (set file info by fileid). + Deal with SMB_INFO_SET_EA. +****************************************************************************/ + +static int smb_info_set_ea(connection_struct *conn, + char *outbuf, + int bufsize, + char *params, + int total_params, + char *pdata, + int total_data, + unsigned int max_data_bytes, + files_struct *fsp, + const char *fname) +{ + struct ea_list *ea_list = NULL; + TALLOC_CTX *ctx = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (total_data < 10) { + + /* OS/2 workplace shell seems to send SET_EA requests of "null" + length. They seem to have no effect. Bug #3212. JRA */ + + if ((total_data == 4) && (IVAL(pdata,0) == 4)) { + /* We're done. We only get EA info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; + } + + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n", + IVAL(pdata,0), (unsigned int)total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ctx = talloc_init("SMB_INFO_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + /* We're done. We only get EA info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} + +/**************************************************************************** + Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -3901,79 +3963,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } case SMB_INFO_SET_EA: - { - struct ea_list *ea_list = NULL; - TALLOC_CTX *ctx = NULL; - - if (total_data < 10) { - - /* OS/2 workplace shell seems to send SET_EA requests of "null" - length. They seem to have no effect. Bug #3212. JRA */ - - if ((total_data == 4) && (IVAL(pdata,0) == 4)) { - /* We're done. We only get EA info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); - } - - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - if (IVAL(pdata,0) > total_data) { - DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n", - IVAL(pdata,0), (unsigned int)total_data)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - ctx = talloc_init("SMB_INFO_SET_EA"); - if (!ctx) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); - if (!ea_list) { - talloc_destroy(ctx); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - status = set_ea(conn, fsp, fname, ea_list); - talloc_destroy(ctx); - - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - - /* We're done. We only get EA info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); - } - -#if 0 - /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */ - /* XXXX um, i don't think this is right. - it's also not in the cifs6.txt spec. - */ - case SMB_INFO_QUERY_EAS_FROM_LIST: - if (total_data < 28) - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - - tvs.actime = make_unix_date2(pdata+8); - tvs.modtime = make_unix_date2(pdata+12); - size = IVAL(pdata,16); - dosmode = IVAL(pdata,24); - break; - - /* XXXX nor this. not in cifs6.txt, either. */ - case SMB_INFO_QUERY_ALL_EAS: - if (total_data < 28) - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - - tvs.actime = make_unix_date2(pdata+8); - tvs.modtime = make_unix_date2(pdata+12); - size = IVAL(pdata,16); - dosmode = IVAL(pdata,24); - break; -#endif + return smb_info_set_ea(conn, + outbuf, + bufsize, + params, + total_params, + *ppdata, + total_data, + max_data_bytes, + fsp, + fname); case SMB_SET_FILE_BASIC_INFO: case SMB_FILE_BASIC_INFORMATION: -- cgit From 7c5221a777b12a1ab1faed3e050363969f70c880 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 01:36:45 +0000 Subject: r21050: Factor out SMB_SET_FILE_DISPOSITION_INFO. My intent is to factor out all cases where we always return from the case. Jeremy. (This used to be commit 3eca52ba435954f338281f0a9d00b942bab28bab) --- source3/smbd/trans2.c | 80 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 886240c72e..1d577f8183 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3745,7 +3745,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam Deal with SMB_INFO_SET_EA. ****************************************************************************/ -static int smb_info_set_ea(connection_struct *conn, +static int smb_info_set_ea( + connection_struct *conn, char *outbuf, int bufsize, char *params, @@ -3803,6 +3804,50 @@ static int smb_info_set_ea(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_SET_FILE_DISPOSITION_INFO. +****************************************************************************/ + +static int smb_set_file_disposition_info(connection_struct *conn, + char *outbuf, + int bufsize, + char *params, + int total_params, + char *pdata, + int total_data, + unsigned int max_data_bytes, + files_struct *fsp, + int dosmode) +{ + NTSTATUS status = NT_STATUS_OK; + BOOL delete_on_close; + + if (total_data < 1) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + delete_on_close = (CVAL(pdata,0) ? True : False); + + if (fsp == NULL) { + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + + status = can_set_delete_on_close(fsp, delete_on_close, dosmode); + + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + /* The set is across all open files on this dev/inode pair. */ + if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) { + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4107,36 +4152,25 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_DISPOSITION_INFORMATION: case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { - BOOL delete_on_close; - if (total_data < 1) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - delete_on_close = (CVAL(pdata,0) ? True : False); - /* Just ignore this set on a path. */ - if (tran_call != TRANSACT2_SETFILEINFO) + if (tran_call != TRANSACT2_SETFILEINFO) { break; - - if (fsp == NULL) - return(UNIXERROR(ERRDOS,ERRbadfid)); - - status = can_set_delete_on_close(fsp, delete_on_close, - dosmode); - - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); } - /* The set is across all open files on this dev/inode pair. */ - if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) { - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_set_file_disposition_info(conn, + outbuf, + bufsize, + params, + total_params, + *ppdata, + total_data, + max_data_bytes, + fsp, + dosmode); } case SMB_FILE_POSITION_INFORMATION: -- cgit From c219ebd7e811e775bfe9e6ad6403dfce0c1b15cb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 01:46:14 +0000 Subject: r21051: More function refactoring... Added #if 0 for questionable practice (ignoring bad fsp on handle based call). Jeremy. (This used to be commit 5a8c9286c30319f2d2685d4ae29db37679b87e02) --- source3/smbd/trans2.c | 89 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1d577f8183..90365348a0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3745,8 +3745,7 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam Deal with SMB_INFO_SET_EA. ****************************************************************************/ -static int smb_info_set_ea( - connection_struct *conn, +static int smb_info_set_ea(connection_struct *conn, char *outbuf, int bufsize, char *params, @@ -3826,12 +3825,12 @@ static int smb_set_file_disposition_info(connection_struct *conn, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - delete_on_close = (CVAL(pdata,0) ? True : False); - if (fsp == NULL) { return(UNIXERROR(ERRDOS,ERRbadfid)); } + delete_on_close = (CVAL(pdata,0) ? True : False); + status = can_set_delete_on_close(fsp, delete_on_close, dosmode); if (!NT_STATUS_IS_OK(status)) { @@ -3848,6 +3847,47 @@ static int smb_set_file_disposition_info(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_FILE_POSITION_INFORMATION. +****************************************************************************/ + +static int smb_file_position_information(connection_struct *conn, + char *outbuf, + int bufsize, + char *params, + int total_params, + char *pdata, + int total_data, + unsigned int max_data_bytes, + files_struct *fsp) +{ + SMB_BIG_UINT position_information; + + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + position_information = (SMB_BIG_UINT)IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } +#endif /* LARGE_SMB_OFF_T */ + if (fsp) { + DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", + fsp->fsp_name, (double)position_information )); + fsp->fh->position_information = position_information; + } + + /* We're done. We only set position info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4152,15 +4192,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_DISPOSITION_INFORMATION: case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { - if (total_data < 1) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - +#if 0 /* JRA - should we just ignore this on a path ? */ /* Just ignore this set on a path. */ if (tran_call != TRANSACT2_SETFILEINFO) { break; } - +#endif return smb_set_file_disposition_info(conn, outbuf, bufsize, @@ -4175,31 +4212,15 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_POSITION_INFORMATION: { - SMB_BIG_UINT position_information; - - if (total_data < 8) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - position_information = (SMB_BIG_UINT)IVAL(pdata,0); -#ifdef LARGE_SMB_OFF_T - position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); -#else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) { - /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } -#endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", - fname, (double)position_information )); - if (fsp) { - fsp->fh->position_information = position_information; - } - - /* We're done. We only get position info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_file_position_information(conn, + outbuf, + bufsize, + params, + total_params, + *ppdata, + total_data, + max_data_bytes, + fsp); } /* From tridge Samba4 : -- cgit From 1e55fdb7b7b0bd5b75d32dd78b77d41fdf7cf860 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 01:54:07 +0000 Subject: r21052: Refactoring. Jeremy. (This used to be commit 9e31d7dba383c5c14f746537a631a4119dac0cd0) --- source3/smbd/trans2.c | 68 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 90365348a0..8185f423e9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3749,7 +3749,6 @@ static int smb_info_set_ea(connection_struct *conn, char *outbuf, int bufsize, char *params, - int total_params, char *pdata, int total_data, unsigned int max_data_bytes, @@ -3811,7 +3810,6 @@ static int smb_set_file_disposition_info(connection_struct *conn, char *outbuf, int bufsize, char *params, - int total_params, char *pdata, int total_data, unsigned int max_data_bytes, @@ -3855,7 +3853,6 @@ static int smb_file_position_information(connection_struct *conn, char *outbuf, int bufsize, char *params, - int total_params, char *pdata, int total_data, unsigned int max_data_bytes, @@ -3867,6 +3864,10 @@ static int smb_file_position_information(connection_struct *conn, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + if (fsp == NULL) { + return(UNIXERROR(ERRDOS,ERRbadfid)); + } + position_information = (SMB_BIG_UINT)IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); @@ -3876,11 +3877,10 @@ static int smb_file_position_information(connection_struct *conn, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } #endif /* LARGE_SMB_OFF_T */ - if (fsp) { - DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", - fsp->fsp_name, (double)position_information )); - fsp->fh->position_information = position_information; - } + + DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", + fsp->fsp_name, (double)position_information )); + fsp->fh->position_information = position_information; /* We're done. We only set position info in this call. */ SSVAL(params,0,0); @@ -3888,6 +3888,34 @@ static int smb_file_position_information(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_FILE_MODE_INFORMATION. +****************************************************************************/ + +static int smb_file_mode_information(connection_struct *conn, + char *outbuf, + int bufsize, + char *params, + char *pdata, + int total_data, + unsigned int max_data_bytes) +{ + uint32 mode; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + mode = IVAL(pdata,0); + if (mode != 0 && mode != 2 && mode != 4 && mode != 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + /* We're done. We only set (?) mode info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4052,7 +4080,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char outbuf, bufsize, params, - total_params, *ppdata, total_data, max_data_bytes, @@ -4202,7 +4229,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char outbuf, bufsize, params, - total_params, *ppdata, total_data, max_data_bytes, @@ -4216,7 +4242,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char outbuf, bufsize, params, - total_params, *ppdata, total_data, max_data_bytes, @@ -4231,20 +4256,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_MODE_INFORMATION: { - uint32 mode; - - if (total_data < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - mode = IVAL(pdata,0); - if (mode != 0 && mode != 2 && mode != 4 && mode != 6) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - /* We're done. We only get mode info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_file_mode_information(conn, + outbuf, + bufsize, + params, + *ppdata, + total_data, + max_data_bytes); } /* -- cgit From 54aefc22679012af4deecea1160396ef8d3f4b86 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 02:13:58 +0000 Subject: r21053: More refactoring and fix the tests (set position info on a pathname is ignored). Jeremy. (This used to be commit 3c7a876c909d3ba1fdf8f0e38735279a874ab245) --- source3/smbd/trans2.c | 146 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8185f423e9..7450f0581a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3864,8 +3864,11 @@ static int smb_file_position_information(connection_struct *conn, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - if (fsp == NULL) { - return(UNIXERROR(ERRDOS,ERRbadfid)); + if (!fsp) { + /* Ignore on pathname based set. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; } position_information = (SMB_BIG_UINT)IVAL(pdata,0); @@ -3916,6 +3919,76 @@ static int smb_file_mode_information(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink). +****************************************************************************/ + +static int smb_set_file_unix_link(connection_struct *conn, + char *inbuf, + char *outbuf, + int bufsize, + char *params, + char *pdata, + int total_data, + unsigned int max_data_bytes, + const char *fname) +{ + pstring link_target; + const char *newname = fname; + NTSTATUS status = NT_STATUS_OK; + + /* Set a symbolic link. */ + /* Don't allow this if follow links is false. */ + + if (total_data == 0) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_symlinks(SNUM(conn))) { + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + } + + srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE); + + /* !widelinks forces the target path to be within the share. */ + /* This means we can interpret the target as a pathname. */ + if (!lp_widelinks(SNUM(conn))) { + pstring rel_name; + char *last_dirp = NULL; + + unix_format(link_target); + if (*link_target == '/') { + /* No absolute paths allowed. */ + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + pstrcpy(rel_name, newname); + last_dirp = strrchr_m(rel_name, '/'); + if (last_dirp) { + last_dirp[1] = '\0'; + } else { + pstrcpy(rel_name, "./"); + } + pstrcat(rel_name, link_target); + + status = check_name(conn, rel_name); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + } + + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", + newname, link_target )); + + if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} + + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4219,10 +4292,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_DISPOSITION_INFORMATION: case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { -#if 0 /* JRA - should we just ignore this on a path ? */ - /* Just ignore this set on a path. */ +#if 0 + /* JRA - We used to just ignore this on a path ? + * Shouldn't this be invalid level on a pathname + * based call ? + */ if (tran_call != TRANSACT2_SETFILEINFO) { - break; + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } #endif return smb_set_file_disposition_info(conn, @@ -4441,55 +4517,19 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_SET_FILE_UNIX_LINK: { - pstring link_target; - char *newname = fname; - - /* Set a symbolic link. */ - /* Don't allow this if follow links is false. */ - - if (total_data == 0) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - if (!lp_symlinks(SNUM(conn))) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); - - srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE); - - /* !widelinks forces the target path to be within the share. */ - /* This means we can interpret the target as a pathname. */ - if (!lp_widelinks(SNUM(conn))) { - pstring rel_name; - char *last_dirp = NULL; - - unix_format(link_target); - if (*link_target == '/') { - /* No absolute paths allowed. */ - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - pstrcpy(rel_name, newname); - last_dirp = strrchr_m(rel_name, '/'); - if (last_dirp) { - last_dirp[1] = '\0'; - } else { - pstrcpy(rel_name, "./"); - } - pstrcat(rel_name, link_target); - - status = check_name(conn, rel_name); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } + if (tran_call != TRANSACT2_SETPATHINFO) { + /* We must have a pathname for this. */ + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", - fname, link_target )); - - if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_set_file_unix_link(conn, + inbuf, + outbuf, + bufsize, + params, + *ppdata, + total_data, + max_data_bytes, + fname); } case SMB_SET_FILE_UNIX_HLINK: -- cgit From e90b6c743deeb8db2e7c779f5427d8b45ee77aef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 02:27:29 +0000 Subject: r21054: More function refactoring. Jeremy. (This used to be commit b6f43e9509cfedbf77c883cff793c469d6f86370) --- source3/smbd/trans2.c | 76 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7450f0581a..679f589b49 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3679,7 +3679,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd code. ****************************************************************************/ -NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname) +NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname) { SMB_STRUCT_STAT sbuf1, sbuf2; pstring last_component_oldname; @@ -3988,6 +3988,45 @@ static int smb_set_file_unix_link(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link). +****************************************************************************/ + +static int smb_set_file_unix_hlink(connection_struct *conn, + char *inbuf, + char *outbuf, + int bufsize, + char *params, + char *pdata, + int total_data, + unsigned int max_data_bytes, + pstring fname) +{ + pstring oldname; + NTSTATUS status = NT_STATUS_OK; + + /* Set a hard link. */ + if (total_data == 0) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", + fname, oldname)); + + status = hardlink_internals(conn, oldname, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). @@ -4534,30 +4573,19 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_SET_FILE_UNIX_HLINK: { - pstring oldname; - char *newname = fname; - - /* Set a hard link. */ - if (total_data == 0) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", - fname, oldname)); - - status = hardlink_internals(conn, oldname, newname); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + if (tran_call != TRANSACT2_SETPATHINFO) { + /* We must have a pathname for this. */ + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_set_file_unix_hlink(conn, + inbuf, + outbuf, + bufsize, + params, + *ppdata, + total_data, + max_data_bytes, + fname); } case SMB_FILE_RENAME_INFORMATION: -- cgit From 845647f4687431e321ee98a7b48cc324c345cbd4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 18:16:51 +0000 Subject: r21057: More refactoring into functions. Jeremy. (This used to be commit fe2d7cb2dcd7c4d25d71f196aa557ce3e287bb4c) --- source3/smbd/reply.c | 4 +- source3/smbd/trans2.c | 156 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 95 insertions(+), 65 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7cb086841d..a1edce935d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3999,7 +3999,7 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest) Rename an open file - given an fsp. ****************************************************************************/ -NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists) { SMB_STRUCT_STAT sbuf; pstring newname_last_component; @@ -4116,7 +4116,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild) +NTSTATUS rename_internals(connection_struct *conn, pstring name, pstring newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild) { pstring directory; pstring mask; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 679f589b49..6167fa30bd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3881,7 +3881,7 @@ static int smb_file_position_information(connection_struct *conn, } #endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", + DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n", fsp->fsp_name, (double)position_information )); fsp->fh->position_information = position_information; @@ -3976,7 +3976,7 @@ static int smb_set_file_unix_link(connection_struct *conn, } } - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", + DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", newname, link_target )); if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) { @@ -4015,7 +4015,7 @@ static int smb_set_file_unix_hlink(connection_struct *conn, return ERROR_NT(status); } - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", + DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, oldname)); status = hardlink_internals(conn, oldname, fname); @@ -4028,6 +4028,86 @@ static int smb_set_file_unix_hlink(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_FILE_RENAME_INFORMATION. +****************************************************************************/ + +static int smb_file_rename_information(connection_struct *conn, + char *inbuf, + char *outbuf, + int bufsize, + char *params, + char *pdata, + int total_data, + unsigned int max_data_bytes, + files_struct *fsp, + pstring fname) +{ + BOOL overwrite; + /* uint32 root_fid; */ /* Not used */ + uint32 len; + pstring newname; + pstring base_name; + NTSTATUS status = NT_STATUS_OK; + char *p; + + if (total_data < 13) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + overwrite = (CVAL(pdata,0) ? True : False); + /* root_fid = IVAL(pdata,4); */ + len = IVAL(pdata,8); + + if (len > (total_data - 12) || (len == 0)) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + /* Check the new name has no '/' characters. */ + if (strchr_m(newname, '/')) { + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } + + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + + /* Create the base directory. */ + pstrcpy(base_name, fname); + p = strrchr_m(base_name, '/'); + if (p) { + *p = '\0'; + } + /* Append the new name. */ + pstrcat(base_name, "/"); + pstrcat(base_name, newname); + + if (fsp) { + DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", + fsp->fnum, fsp->fsp_name, base_name )); + status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite); + } else { + DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", + fname, newname )); + status = rename_internals(conn, fname, base_name, 0, overwrite, False); + } + + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } + return ERROR_NT(status); + } + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4590,66 +4670,16 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_FILE_RENAME_INFORMATION: { - BOOL overwrite; - /* uint32 root_fid; */ /* Not used */ - uint32 len; - pstring newname; - pstring base_name; - char *p; - - if (total_data < 13) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - overwrite = (CVAL(pdata,0) ? True : False); - /* root_fid = IVAL(pdata,4); */ - len = IVAL(pdata,8); - - if (len > (total_data - 12) || (len == 0)) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - - /* Check the new name has no '/' characters. */ - if (strchr_m(newname, '/')) - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); - - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); - - /* Create the base directory. */ - pstrcpy(base_name, fname); - p = strrchr_m(base_name, '/'); - if (p) - *p = '\0'; - /* Append the new name. */ - pstrcat(base_name, "/"); - pstrcat(base_name, newname); - - if (fsp) { - DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", - fsp->fnum, fsp->fsp_name, base_name )); - status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite); - } else { - DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n", - fname, newname )); - status = rename_internals(conn, fname, base_name, 0, overwrite, False); - } - - if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { - /* We have re-scheduled this call. */ - return -1; - } - return ERROR_NT(status); - } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_file_rename_information(conn, + inbuf, + outbuf, + bufsize, + params, + pdata, + total_data, + max_data_bytes, + fsp, + fname); } #if defined(HAVE_POSIX_ACLS) -- cgit From a4e3c20deb72ef4ddff5e42684462bc3c00176c4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 18:45:19 +0000 Subject: r21058: Finish the easy refactoring - split out all the case statements that do early return. Next will be case statements that need post processing, finally on to qfilepathinfo and do the same. Jeremy. (This used to be commit c961d5ce94a8bf2e2ffba645e522f0e2e372e351) --- source3/smbd/trans2.c | 371 +++++++++++++++++++++++++++++--------------------- 1 file changed, 213 insertions(+), 158 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6167fa30bd..1a48a7b6f2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -568,9 +568,9 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list * int send_trans2_replies(char *outbuf, int bufsize, - char *params, + const char *params, int paramsize, - char *pdata, + const char *pdata, int datasize, int max_data_bytes) { @@ -583,8 +583,8 @@ int send_trans2_replies(char *outbuf, int data_to_send = datasize; int params_to_send = paramsize; int useable_space; - char *pp = params; - char *pd = pdata; + const char *pp = params; + const char *pd = pdata; int params_sent_thistime, data_sent_thistime, total_sent_thistime; int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */ int data_alignment_offset = 0; @@ -3749,7 +3749,7 @@ static int smb_info_set_ea(connection_struct *conn, char *outbuf, int bufsize, char *params, - char *pdata, + const char *pdata, int total_data, unsigned int max_data_bytes, files_struct *fsp, @@ -3810,7 +3810,7 @@ static int smb_set_file_disposition_info(connection_struct *conn, char *outbuf, int bufsize, char *params, - char *pdata, + const char *pdata, int total_data, unsigned int max_data_bytes, files_struct *fsp, @@ -3853,7 +3853,7 @@ static int smb_file_position_information(connection_struct *conn, char *outbuf, int bufsize, char *params, - char *pdata, + const char *pdata, int total_data, unsigned int max_data_bytes, files_struct *fsp) @@ -3899,7 +3899,7 @@ static int smb_file_mode_information(connection_struct *conn, char *outbuf, int bufsize, char *params, - char *pdata, + const char *pdata, int total_data, unsigned int max_data_bytes) { @@ -3928,7 +3928,7 @@ static int smb_set_file_unix_link(connection_struct *conn, char *outbuf, int bufsize, char *params, - char *pdata, + const char *pdata, int total_data, unsigned int max_data_bytes, const char *fname) @@ -3997,7 +3997,7 @@ static int smb_set_file_unix_hlink(connection_struct *conn, char *outbuf, int bufsize, char *params, - char *pdata, + const char *pdata, int total_data, unsigned int max_data_bytes, pstring fname) @@ -4037,7 +4037,7 @@ static int smb_file_rename_information(connection_struct *conn, char *outbuf, int bufsize, char *params, - char *pdata, + const char *pdata, int total_data, unsigned int max_data_bytes, files_struct *fsp, @@ -4108,6 +4108,189 @@ static int smb_file_rename_information(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_SET_POSIX_ACL. +****************************************************************************/ + +#if defined(HAVE_POSIX_ACLS) +static int smb_set_posix_acl(connection_struct *conn, + char *outbuf, + int bufsize, + char *params, + const char *pdata, + int total_data, + unsigned int max_data_bytes, + files_struct *fsp, + const char *fname) +{ + uint16 posix_acl_version; + uint16 num_file_acls; + uint16 num_def_acls; + BOOL valid_file_acls = True; + BOOL valid_def_acls = True; + + if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + posix_acl_version = SVAL(pdata,0); + num_file_acls = SVAL(pdata,2); + num_def_acls = SVAL(pdata,4); + + if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { + valid_file_acls = False; + num_file_acls = 0; + } + + if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { + valid_def_acls = False; + num_def_acls = 0; + } + + if (posix_acl_version != SMB_POSIX_ACL_VERSION) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (total_data < SMB_POSIX_ACL_HEADER_SIZE + + (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE)) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE + + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} +#endif + +/**************************************************************************** + Deal with SMB_SET_POSIX_LOCK. +****************************************************************************/ + +static int smb_set_posix_lock(connection_struct *conn, + char *inbuf, + char *outbuf, + int length, + int bufsize, + char *params, + const char *pdata, + int total_data, + unsigned int max_data_bytes, + files_struct *fsp) +{ + SMB_BIG_UINT count; + SMB_BIG_UINT offset; + uint32 lock_pid; + BOOL blocking_lock = False; + enum brl_type lock_type; + NTSTATUS status = NT_STATUS_OK; + + if (fsp == NULL || fsp->fh->fd == -1) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + if (total_data != POSIX_LOCK_DATA_SIZE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { + case POSIX_LOCK_TYPE_READ: + lock_type = READ_LOCK; + break; + case POSIX_LOCK_TYPE_WRITE: + /* Return the right POSIX-mappable error code for files opened read-only. */ + if (!fsp->can_write) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + lock_type = WRITE_LOCK; + break; + case POSIX_LOCK_TYPE_UNLOCK: + lock_type = UNLOCK_LOCK; + break; + default: + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) { + blocking_lock = False; + } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) { + blocking_lock = True; + } else { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_blocking_locks(SNUM(conn))) { + blocking_lock = False; + } + + lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); +#if defined(HAVE_LONGLONG) + offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | + ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); + count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) | + ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET)); +#else /* HAVE_LONGLONG */ + offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET); + count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET); +#endif /* HAVE_LONGLONG */ + + if (lock_type == UNLOCK_LOCK) { + status = do_unlock(fsp, + lock_pid, + count, + offset, + POSIX_LOCK); + } else { + struct byte_range_lock *br_lck = do_lock(fsp, + lock_pid, + count, + offset, + lock_type, + POSIX_LOCK, + blocking_lock, + &status); + + if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(br_lck, + inbuf, length, + fsp, + -1, /* infinite timeout. */ + 0, + lock_pid, + lock_type, + POSIX_LOCK, + offset, + count)) { + TALLOC_FREE(br_lck); + return -1; + } + } + TALLOC_FREE(br_lck); + } + + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); + return -1; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4685,158 +4868,30 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", #if defined(HAVE_POSIX_ACLS) case SMB_SET_POSIX_ACL: { - uint16 posix_acl_version; - uint16 num_file_acls; - uint16 num_def_acls; - BOOL valid_file_acls = True; - BOOL valid_def_acls = True; - - if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - posix_acl_version = SVAL(pdata,0); - num_file_acls = SVAL(pdata,2); - num_def_acls = SVAL(pdata,4); - - if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { - valid_file_acls = False; - num_file_acls = 0; - } - - if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { - valid_def_acls = False; - num_def_acls = 0; - } - - if (posix_acl_version != SMB_POSIX_ACL_VERSION) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - if (total_data < SMB_POSIX_ACL_HEADER_SIZE + - (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE)) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE + - (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_set_posix_acl(conn, + outbuf, + bufsize, + params, + pdata, + total_data, + max_data_bytes, + fsp, + fname); } #endif case SMB_SET_POSIX_LOCK: { - SMB_BIG_UINT count; - SMB_BIG_UINT offset; - uint32 lock_pid; - BOOL blocking_lock = False; - enum brl_type lock_type; - - if (fsp == NULL || fsp->fh->fd == -1) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); - } - - if (total_data != POSIX_LOCK_DATA_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { - case POSIX_LOCK_TYPE_READ: - lock_type = READ_LOCK; - break; - case POSIX_LOCK_TYPE_WRITE: - /* Return the right POSIX-mappable error code for files opened read-only. */ - if (!fsp->can_write) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); - } - lock_type = WRITE_LOCK; - break; - case POSIX_LOCK_TYPE_UNLOCK: - lock_type = UNLOCK_LOCK; - break; - default: - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) { - blocking_lock = False; - } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) { - blocking_lock = True; - } else { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - if (!lp_blocking_locks(SNUM(conn))) { - blocking_lock = False; - } - - lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); -#if defined(HAVE_LONGLONG) - offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | - ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); - count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) | - ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET)); -#else /* HAVE_LONGLONG */ - offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET); - count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET); -#endif /* HAVE_LONGLONG */ - - if (lock_type == UNLOCK_LOCK) { - status = do_unlock(fsp, - lock_pid, - count, - offset, - POSIX_LOCK); - } else { - struct byte_range_lock *br_lck = do_lock(fsp, - lock_pid, - count, - offset, - lock_type, - POSIX_LOCK, - blocking_lock, - &status); - - if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(br_lck, - inbuf, length, - fsp, - -1, /* infinite timeout. */ - 0, - lock_pid, - lock_type, - POSIX_LOCK, - offset, - count)) { - TALLOC_FREE(br_lck); - return -1; - } - } - TALLOC_FREE(br_lck); - } - - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return smb_set_posix_lock(conn, + inbuf, + outbuf, + length, + bufsize, + params, + pdata, + total_data, + max_data_bytes, + fsp); } default: -- cgit From 5c9344fa4cb0d1796ca7ea819080d344f6238994 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 19:26:01 +0000 Subject: r21060: Start refactoring out the non-return case statements into functions. Jeremy. (This used to be commit 461db3c8ed045cac70eccf3200bf9163dbce5826) --- source3/smbd/trans2.c | 99 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1a48a7b6f2..4bbef4dc45 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4291,6 +4291,60 @@ static int smb_set_posix_lock(connection_struct *conn, return -1; } +/**************************************************************************** + Deal with SMB_INFO_STANDARD. +****************************************************************************/ + +static NTSTATUS smb_set_info_standard(const char *pdata, int total_data, struct utimbuf *p_tvs) +{ + if (total_data < 12) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* access time */ + p_tvs->actime = srv_make_unix_date2(pdata+l1_fdateLastAccess); + /* write time */ + p_tvs->modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); + return NT_STATUS_OK; +} + +/**************************************************************************** + Deal with SMB_SET_FILE_BASIC_INFO. +****************************************************************************/ + +static NTSTATUS smb_set_file_basic_info(const char *pdata, int total_data, struct utimbuf *p_tvs, int *p_dosmode) +{ + /* Patch to do this correctly from Paul Eggert . */ + time_t write_time; + time_t changed_time; + + if (total_data < 36) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* Ignore create time at offset pdata. */ + + /* access time */ + p_tvs->actime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); + + write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16)); + changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24)); + + p_tvs->modtime = MIN(write_time, changed_time); + + if (write_time > p_tvs->modtime && write_time != (time_t)-1) { + p_tvs->modtime = write_time; + } + /* Prefer a defined time to an undefined one. */ + if (null_mtime(p_tvs->modtime)) { + p_tvs->modtime = null_mtime(write_time) ? changed_time : write_time; + } + + /* attributes */ + *p_dosmode = IVAL(pdata,32); + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4437,20 +4491,18 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE; switch (info_level) { + case SMB_INFO_STANDARD: { - if (total_data < 12) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + status = smb_set_info_standard(pdata, total_data, &tvs); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } - - /* access time */ - tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess); - /* write time */ - tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); break; } case SMB_INFO_SET_EA: + { return smb_info_set_ea(conn, outbuf, bufsize, @@ -4460,38 +4512,15 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char max_data_bytes, fsp, fname); + } case SMB_SET_FILE_BASIC_INFO: case SMB_FILE_BASIC_INFORMATION: { - /* Patch to do this correctly from Paul Eggert . */ - time_t write_time; - time_t changed_time; - - if (total_data < 36) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - /* Ignore create time at offset pdata. */ - - /* access time */ - tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); - - write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16)); - changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24)); - - tvs.modtime = MIN(write_time, changed_time); - - if (write_time > tvs.modtime && write_time != (time_t)-1) { - tvs.modtime = write_time; - } - /* Prefer a defined time to an undefined one. */ - if (null_mtime(tvs.modtime)) { - tvs.modtime = null_mtime(write_time) ? changed_time : write_time; + status = smb_set_file_basic_info(pdata, total_data, &tvs, &dosmode); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } - - /* attributes */ - dosmode = IVAL(pdata,32); break; } @@ -5018,7 +5047,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return -1; } /**************************************************************************** -- cgit From e5be27a30851c910dedf42f252bcc20476e6c3f6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 19:54:28 +0000 Subject: r21061: Refactoring all the cases into NTSTATUS returns. Jeremy. (This used to be commit da4ce69d4057c241cf7b4b6b0dd2bf711dd28a43) --- source3/smbd/trans2.c | 168 +++++++++++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 69 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4bbef4dc45..063eca17e0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-2003 + Copyright (C) Jeremy Allison 1994-2007 Copyright (C) Stefan (metze) Metzmacher 2003 Copyright (C) Volker Lendecke 2005 Copyright (C) Steve French 2005 @@ -4345,6 +4345,92 @@ static NTSTATUS smb_set_file_basic_info(const char *pdata, int total_data, struc return NT_STATUS_OK; } +/**************************************************************************** + Deal with SMB_SET_FILE_ALLOCATION_INFO. +****************************************************************************/ + +static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, + const char *pdata, + int total_data, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf, + SMB_OFF_T *p_size) +{ + int ret = -1; + SMB_BIG_UINT allocation_size; + + if (total_data < 8) { + return NT_STATUS_INVALID_PARAMETER; + } + + allocation_size = (SMB_BIG_UINT)IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return NT_STATUS_INVALID_PARAMETER; + } +#endif /* LARGE_SMB_OFF_T */ + + DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n", + fname, (double)allocation_size )); + + if (allocation_size) { + allocation_size = smb_roundup(conn, allocation_size); + } + + if(allocation_size != get_file_size(*psbuf)) { + SMB_STRUCT_STAT new_sbuf; + + DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n", + fname, (double)allocation_size )); + + if (fsp && fsp->fh->fd != -1) { + /* Open file. */ + ret = vfs_allocate_file_space(fsp, allocation_size); + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&new_sbuf) != 0) { + DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n", + fsp->fnum, strerror(errno))); + ret = -1; + } + } else { + /* Pathname or stat or directory file. */ + files_struct *new_fsp = NULL; + NTSTATUS status; + + status = open_file_ntcreate(conn, fname, psbuf, + FILE_WRITE_DATA, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + FORCE_OPLOCK_BREAK_TO_NONE, + NULL, &new_fsp); + + if (!NT_STATUS_IS_OK(status)) { + /* NB. We check for open_was_deferred in the caller. */ + return status; + } + ret = vfs_allocate_file_space(new_fsp, allocation_size); + if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) { + DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n", + new_fsp->fnum, strerror(errno))); + ret = -1; + } + close_file(new_fsp,NORMAL_CLOSE); + } + if (ret == -1) { + return NT_STATUS_DISK_FULL; + } + + /* Allocate can truncate size... */ + *p_size = get_file_size(new_sbuf); + } + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4527,76 +4613,20 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_ALLOCATION_INFORMATION: case SMB_SET_FILE_ALLOCATION_INFO: { - int ret = -1; - SMB_BIG_UINT allocation_size; - - if (total_data < 8) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - allocation_size = (SMB_BIG_UINT)IVAL(pdata,0); -#ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); -#else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) { - /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } -#endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", - fname, (double)allocation_size )); - - if (allocation_size) { - allocation_size = smb_roundup(conn, allocation_size); - } - - if(allocation_size != get_file_size(sbuf)) { - SMB_STRUCT_STAT new_sbuf; - - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n", - fname, (double)allocation_size )); - - if (fd == -1) { - files_struct *new_fsp = NULL; - - status = open_file_ntcreate(conn, fname, &sbuf, - FILE_WRITE_DATA, - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - FORCE_OPLOCK_BREAK_TO_NONE, - NULL, &new_fsp); - - if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { - /* We have re-scheduled this call. */ - return -1; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - ret = vfs_allocate_file_space(new_fsp, allocation_size); - if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) { - DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", - new_fsp->fnum, strerror(errno))); - ret = -1; - } - close_file(new_fsp,NORMAL_CLOSE); - } else { - ret = vfs_allocate_file_space(fsp, allocation_size); - if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) { - DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", - fsp->fnum, strerror(errno))); - ret = -1; - } + status = smb_set_file_allocation_info(conn, + pdata, + total_data, + fsp, + fname, + &sbuf, + &size); + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; } - if (ret == -1) - return ERROR_NT(NT_STATUS_DISK_FULL); - - /* Allocate can truncate size... */ - size = get_file_size(new_sbuf); + return ERROR_NT(status); } - break; } -- cgit From deaf4131b99951cfcc599b96e35af680202ce609 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 20:49:37 +0000 Subject: r21062: Should fix the build plus make all refactored functions return NTSTATUS. Jeremy. (This used to be commit 1f3c2b2abca6f1b3b59b73df038832e14106ff76) --- source3/smbd/blocking.c | 17 +++ source3/smbd/trans2.c | 386 ++++++++++++++++++++++-------------------------- 2 files changed, 191 insertions(+), 212 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 7a71fc67e5..e0478fa762 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -559,6 +559,23 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); } } +/**************************************************************************** + Is this mid a blocking lock request on the queue ? +*****************************************************************************/ + +BOOL blocking_lock_was_deferred(int mid) +{ + blocking_lock_record *blr, *next = NULL; + + for(blr = blocking_lock_queue; blr; blr = next) { + next = blr->next; + if(SVAL(blr->inbuf,smb_mid) == mid) { + return True; + } + } + return False; +} + /**************************************************************************** Set a flag as an unlock request affects one of our pending locks. *****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 063eca17e0..98ea6c111a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3745,13 +3745,9 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne Deal with SMB_INFO_SET_EA. ****************************************************************************/ -static int smb_info_set_ea(connection_struct *conn, - char *outbuf, - int bufsize, - char *params, +static NTSTATUS smb_info_set_ea(connection_struct *conn, const char *pdata, int total_data, - unsigned int max_data_bytes, files_struct *fsp, const char *fname) { @@ -3766,53 +3762,40 @@ static int smb_info_set_ea(connection_struct *conn, if ((total_data == 4) && (IVAL(pdata,0) == 4)) { /* We're done. We only get EA info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return NT_STATUS_OK; } - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } if (IVAL(pdata,0) > total_data) { DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } ctx = talloc_init("SMB_INFO_SET_EA"); if (!ctx) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + return NT_STATUS_NO_MEMORY; } ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); if (!ea_list) { talloc_destroy(ctx); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - - /* We're done. We only get EA info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return status; } /**************************************************************************** Deal with SMB_SET_FILE_DISPOSITION_INFO. ****************************************************************************/ -static int smb_set_file_disposition_info(connection_struct *conn, - char *outbuf, - int bufsize, - char *params, +static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, const char *pdata, int total_data, - unsigned int max_data_bytes, files_struct *fsp, int dosmode) { @@ -3820,11 +3803,11 @@ static int smb_set_file_disposition_info(connection_struct *conn, BOOL delete_on_close; if (total_data < 1) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } if (fsp == NULL) { - return(UNIXERROR(ERRDOS,ERRbadfid)); + return NT_STATUS_INVALID_HANDLE; } delete_on_close = (CVAL(pdata,0) ? True : False); @@ -3832,43 +3815,34 @@ static int smb_set_file_disposition_info(connection_struct *conn, status = can_set_delete_on_close(fsp, delete_on_close, dosmode); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + return status; } /* The set is across all open files on this dev/inode pair. */ if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) { - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + return NT_STATUS_ACCESS_DENIED; } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return NT_STATUS_OK; } /**************************************************************************** Deal with SMB_FILE_POSITION_INFORMATION. ****************************************************************************/ -static int smb_file_position_information(connection_struct *conn, - char *outbuf, - int bufsize, - char *params, +static NTSTATUS smb_file_position_information(connection_struct *conn, const char *pdata, int total_data, - unsigned int max_data_bytes, files_struct *fsp) { SMB_BIG_UINT position_information; if (total_data < 8) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } - if (!fsp) { + if (fsp == NULL) { /* Ignore on pathname based set. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return NT_STATUS_OK; } position_information = (SMB_BIG_UINT)IVAL(pdata,0); @@ -3884,53 +3858,37 @@ static int smb_file_position_information(connection_struct *conn, DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n", fsp->fsp_name, (double)position_information )); fsp->fh->position_information = position_information; - - /* We're done. We only set position info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return NT_STATUS_OK; } /**************************************************************************** Deal with SMB_FILE_MODE_INFORMATION. ****************************************************************************/ -static int smb_file_mode_information(connection_struct *conn, - char *outbuf, - int bufsize, - char *params, +static NTSTATUS smb_file_mode_information(connection_struct *conn, const char *pdata, - int total_data, - unsigned int max_data_bytes) + int total_data) { uint32 mode; if (total_data < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } mode = IVAL(pdata,0); if (mode != 0 && mode != 2 && mode != 4 && mode != 6) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } - - /* We're done. We only set (?) mode info in this call. */ - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return NT_STATUS_OK; } /**************************************************************************** Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink). ****************************************************************************/ -static int smb_set_file_unix_link(connection_struct *conn, +static NTSTATUS smb_set_file_unix_link(connection_struct *conn, char *inbuf, - char *outbuf, - int bufsize, - char *params, const char *pdata, int total_data, - unsigned int max_data_bytes, const char *fname) { pstring link_target; @@ -3941,11 +3899,11 @@ static int smb_set_file_unix_link(connection_struct *conn, /* Don't allow this if follow links is false. */ if (total_data == 0) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } if (!lp_symlinks(SNUM(conn))) { - return(ERROR_DOS(ERRDOS,ERRnoaccess)); + return NT_STATUS_ACCESS_DENIED; } srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE); @@ -3959,7 +3917,7 @@ static int smb_set_file_unix_link(connection_struct *conn, unix_format(link_target); if (*link_target == '/') { /* No absolute paths allowed. */ - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return NT_STATUS_ACCESS_DENIED; } pstrcpy(rel_name, newname); last_dirp = strrchr_m(rel_name, '/'); @@ -3972,7 +3930,7 @@ static int smb_set_file_unix_link(connection_struct *conn, status = check_name(conn, rel_name); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + return status; } } @@ -3980,26 +3938,20 @@ static int smb_set_file_unix_link(connection_struct *conn, newname, link_target )); if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return map_nt_error_from_unix(errno); } - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return NT_STATUS_OK; } /**************************************************************************** Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link). ****************************************************************************/ -static int smb_set_file_unix_hlink(connection_struct *conn, +static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, char *inbuf, - char *outbuf, - int bufsize, - char *params, const char *pdata, int total_data, - unsigned int max_data_bytes, pstring fname) { pstring oldname; @@ -4007,39 +3959,29 @@ static int smb_set_file_unix_hlink(connection_struct *conn, /* Set a hard link. */ if (total_data == 0) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + return status; } DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, oldname)); - status = hardlink_internals(conn, oldname, fname); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return hardlink_internals(conn, oldname, fname); } /**************************************************************************** Deal with SMB_FILE_RENAME_INFORMATION. ****************************************************************************/ -static int smb_file_rename_information(connection_struct *conn, +static NTSTATUS smb_file_rename_information(connection_struct *conn, char *inbuf, char *outbuf, - int bufsize, - char *params, const char *pdata, int total_data, - unsigned int max_data_bytes, files_struct *fsp, pstring fname) { @@ -4052,7 +3994,7 @@ static int smb_file_rename_information(connection_struct *conn, char *p; if (total_data < 13) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } overwrite = (CVAL(pdata,0) ? True : False); @@ -4060,20 +4002,20 @@ static int smb_file_rename_information(connection_struct *conn, len = IVAL(pdata,8); if (len > (total_data - 12) || (len == 0)) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + return status; } /* Check the new name has no '/' characters. */ if (strchr_m(newname, '/')) { - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + return NT_STATUS_NOT_SUPPORTED; } - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf); /* Create the base directory. */ pstrcpy(base_name, fname); @@ -4095,17 +4037,7 @@ static int smb_file_rename_information(connection_struct *conn, status = rename_internals(conn, fname, base_name, 0, overwrite, False); } - if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { - /* We have re-scheduled this call. */ - return -1; - } - return ERROR_NT(status); - } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return status; } /**************************************************************************** @@ -4113,14 +4045,11 @@ static int smb_file_rename_information(connection_struct *conn, ****************************************************************************/ #if defined(HAVE_POSIX_ACLS) -static int smb_set_posix_acl(connection_struct *conn, - char *outbuf, - int bufsize, - char *params, +static NTSTATUS smb_set_posix_acl(connection_struct *conn, const char *pdata, int total_data, - unsigned int max_data_bytes, files_struct *fsp, + SMB_STRUCT_STAT *psbuf, const char *fname) { uint16 posix_acl_version; @@ -4130,7 +4059,7 @@ static int smb_set_posix_acl(connection_struct *conn, BOOL valid_def_acls = True; if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } posix_acl_version = SVAL(pdata,0); num_file_acls = SVAL(pdata,2); @@ -4147,28 +4076,25 @@ static int smb_set_posix_acl(connection_struct *conn, } if (posix_acl_version != SMB_POSIX_ACL_VERSION) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } if (total_data < SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, pdata + SMB_POSIX_ACL_HEADER_SIZE)) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return map_nt_error_from_unix(errno); } - if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls, + if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return map_nt_error_from_unix(errno); } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return NT_STATUS_OK; } #endif @@ -4176,15 +4102,11 @@ static int smb_set_posix_acl(connection_struct *conn, Deal with SMB_SET_POSIX_LOCK. ****************************************************************************/ -static int smb_set_posix_lock(connection_struct *conn, +static NTSTATUS smb_set_posix_lock(connection_struct *conn, char *inbuf, - char *outbuf, int length, - int bufsize, - char *params, const char *pdata, int total_data, - unsigned int max_data_bytes, files_struct *fsp) { SMB_BIG_UINT count; @@ -4195,11 +4117,11 @@ static int smb_set_posix_lock(connection_struct *conn, NTSTATUS status = NT_STATUS_OK; if (fsp == NULL || fsp->fh->fd == -1) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + return NT_STATUS_INVALID_HANDLE; } if (total_data != POSIX_LOCK_DATA_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { @@ -4209,7 +4131,7 @@ static int smb_set_posix_lock(connection_struct *conn, case POSIX_LOCK_TYPE_WRITE: /* Return the right POSIX-mappable error code for files opened read-only. */ if (!fsp->can_write) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + return NT_STATUS_INVALID_HANDLE; } lock_type = WRITE_LOCK; break; @@ -4217,7 +4139,7 @@ static int smb_set_posix_lock(connection_struct *conn, lock_type = UNLOCK_LOCK; break; default: - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) { @@ -4225,7 +4147,7 @@ static int smb_set_posix_lock(connection_struct *conn, } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) { blocking_lock = True; } else { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } if (!lp_blocking_locks(SNUM(conn))) { @@ -4276,19 +4198,13 @@ static int smb_set_posix_lock(connection_struct *conn, offset, count)) { TALLOC_FREE(br_lck); - return -1; + return status; } } TALLOC_FREE(br_lck); } - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - - SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes); - return -1; + return status; } /**************************************************************************** @@ -4431,6 +4347,35 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, return NT_STATUS_OK; } +/**************************************************************************** + Deal with SMB_SET_FILE_END_OF_FILE_INFO. +****************************************************************************/ + +static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, + const char *pdata, + int total_data, + const char *fname, + SMB_OFF_T *p_size) +{ + if (total_data < 8) { + return NT_STATUS_INVALID_PARAMETER; + } + + *p_size = IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + *p_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return NT_STATUS_INVALID_PARAMETER; + } +#endif /* LARGE_SMB_OFF_T */ + DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for " + "file %s to %.0f\n", fname, (double)*p_size )); + return NT_STATUS_OK; +} + + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4455,8 +4400,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char mode_t unixmode = 0; NTSTATUS status = NT_STATUS_OK; - if (!params) + if (!params) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } ZERO_STRUCT(sbuf); ZERO_STRUCT(tvs); @@ -4547,8 +4493,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - if (VALID_STAT(sbuf)) + if (VALID_STAT(sbuf)) { unixmode = sbuf.st_mode; + } DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); @@ -4580,7 +4527,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_INFO_STANDARD: { - status = smb_set_info_standard(pdata, total_data, &tvs); + status = smb_set_info_standard(pdata, + total_data, + &tvs); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4589,21 +4538,24 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_INFO_SET_EA: { - return smb_info_set_ea(conn, - outbuf, - bufsize, - params, - *ppdata, + status = smb_info_set_ea(conn, + pdata, total_data, - max_data_bytes, fsp, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + goto out; } case SMB_SET_FILE_BASIC_INFO: case SMB_FILE_BASIC_INFORMATION: { - status = smb_set_file_basic_info(pdata, total_data, &tvs, &dosmode); + status = smb_set_file_basic_info(pdata, + total_data, + &tvs, + &dosmode); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4633,20 +4585,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_SET_FILE_END_OF_FILE_INFO: { - if (total_data < 8) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - size = IVAL(pdata,0); -#ifdef LARGE_SMB_OFF_T - size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); -#else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) { - /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + status = smb_set_file_end_of_file_info(conn, + pdata, + total_data, + fname, + &size); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } -#endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size )); break; } @@ -4662,27 +4608,27 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(NT_STATUS_INVALID_LEVEL); } #endif - return smb_set_file_disposition_info(conn, - outbuf, - bufsize, - params, - *ppdata, + status = smb_set_file_disposition_info(conn, + pdata, total_data, - max_data_bytes, fsp, dosmode); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + goto out; } case SMB_FILE_POSITION_INFORMATION: { - return smb_file_position_information(conn, - outbuf, - bufsize, - params, - *ppdata, + status = smb_file_position_information(conn, + pdata, total_data, - max_data_bytes, fsp); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + goto out; } /* From tridge Samba4 : @@ -4693,13 +4639,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_MODE_INFORMATION: { - return smb_file_mode_information(conn, - outbuf, - bufsize, - params, - *ppdata, - total_data, - max_data_bytes); + status = smb_file_mode_information(conn, + pdata, + total_data); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + goto out; } /* @@ -4882,15 +4828,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* We must have a pathname for this. */ return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - return smb_set_file_unix_link(conn, + status = smb_set_file_unix_link(conn, inbuf, - outbuf, - bufsize, - params, - *ppdata, + pdata, total_data, - max_data_bytes, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + goto out; } case SMB_SET_FILE_UNIX_HLINK: @@ -4899,58 +4845,71 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* We must have a pathname for this. */ return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - return smb_set_file_unix_hlink(conn, + status = smb_set_file_unix_hlink(conn, inbuf, - outbuf, - bufsize, - params, - *ppdata, + pdata, total_data, - max_data_bytes, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + goto out; } case SMB_FILE_RENAME_INFORMATION: { - return smb_file_rename_information(conn, + status = smb_file_rename_information(conn, inbuf, outbuf, - bufsize, - params, pdata, total_data, - max_data_bytes, fsp, fname); + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); + } + goto out; } #if defined(HAVE_POSIX_ACLS) case SMB_SET_POSIX_ACL: { - return smb_set_posix_acl(conn, - outbuf, - bufsize, - params, + status = smb_set_posix_acl(conn, pdata, total_data, - max_data_bytes, fsp, + &sbuf, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + goto out; } #endif case SMB_SET_POSIX_LOCK: { - return smb_set_posix_lock(conn, + status = smb_set_posix_lock(conn, inbuf, - outbuf, length, - bufsize, - params, pdata, total_data, - max_data_bytes, fsp); + if (!NT_STATUS_IS_OK(status)) { + if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; + } + return ERROR_NT(status); + } + goto out; } default: @@ -4971,10 +4930,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(6,("size: %.0f ", (double)size)); if (dosmode) { - if (S_ISDIR(sbuf.st_mode)) + if (S_ISDIR(sbuf.st_mode)) { dosmode |= aDIR; - else + } else { dosmode &= ~aDIR; + } } DEBUG(6,("dosmode: %x\n" , dosmode)); @@ -5074,6 +5034,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } } + out: + SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); -- cgit From cb916d33f534aef5e3527c41555d32c319345fef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Jan 2007 22:20:55 +0000 Subject: r21063: All case statements are now NTSTATUS returning functions. Now to factor out the post processing and make all cases behave the same (no mixture of "early returns" and "break"s. Jeremy (This used to be commit 7e17e54cb729e34c935927fe69a43690c7f446ae) --- source3/smbd/trans2.c | 393 ++++++++++++++++++++++++++++---------------------- source3/smbd/vfs.c | 1 + 2 files changed, 219 insertions(+), 175 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 98ea6c111a..826ccd3f92 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4211,7 +4211,9 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, Deal with SMB_INFO_STANDARD. ****************************************************************************/ -static NTSTATUS smb_set_info_standard(const char *pdata, int total_data, struct utimbuf *p_tvs) +static NTSTATUS smb_set_info_standard(const char *pdata, + int total_data, + struct utimbuf *p_tvs) { if (total_data < 12) { return NT_STATUS_INVALID_PARAMETER; @@ -4228,7 +4230,10 @@ static NTSTATUS smb_set_info_standard(const char *pdata, int total_data, struct Deal with SMB_SET_FILE_BASIC_INFO. ****************************************************************************/ -static NTSTATUS smb_set_file_basic_info(const char *pdata, int total_data, struct utimbuf *p_tvs, int *p_dosmode) +static NTSTATUS smb_set_file_basic_info(const char *pdata, + int total_data, + struct utimbuf *p_tvs, + int *p_dosmode) { /* Patch to do this correctly from Paul Eggert . */ time_t write_time; @@ -4273,7 +4278,6 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, SMB_STRUCT_STAT *psbuf, SMB_OFF_T *p_size) { - int ret = -1; SMB_BIG_UINT allocation_size; if (total_data < 8) { @@ -4298,6 +4302,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, } if(allocation_size != get_file_size(*psbuf)) { + int ret = -1; SMB_STRUCT_STAT new_sbuf; DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n", @@ -4306,10 +4311,13 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, if (fsp && fsp->fh->fd != -1) { /* Open file. */ ret = vfs_allocate_file_space(fsp, allocation_size); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&new_sbuf) != 0) { DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); - ret = -1; + return map_nt_error_from_unix(errno); } } else { /* Pathname or stat or directory file. */ @@ -4330,16 +4338,20 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, return status; } ret = vfs_allocate_file_space(new_fsp, allocation_size); + if (ret == -1) { + status = map_nt_error_from_unix(errno); + close_file(new_fsp,NORMAL_CLOSE); + return status; + } if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) { DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n", new_fsp->fnum, strerror(errno))); - ret = -1; + status = map_nt_error_from_unix(errno); + close_file(new_fsp,NORMAL_CLOSE); + return status; } close_file(new_fsp,NORMAL_CLOSE); } - if (ret == -1) { - return NT_STATUS_DISK_FULL; - } /* Allocate can truncate size... */ *p_size = get_file_size(new_sbuf); @@ -4375,6 +4387,190 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, return NT_STATUS_OK; } +/**************************************************************************** + Deal with SMB_SET_FILE_UNIX_BASIC. +****************************************************************************/ + +static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, + const char *pdata, + int total_data, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf, + SMB_OFF_T *p_size, + struct utimbuf *p_tvs, + mode_t *p_unixmode, + int *p_dosmode) +{ + uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; + gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; + uint32 raw_unixmode; + BOOL delete_on_fail = False; + NTSTATUS status = NT_STATUS_OK; + + if (total_data < 100) { + return NT_STATUS_INVALID_PARAMETER; + } + + set_owner = VALID_STAT(*psbuf) ? psbuf->st_uid : (uid_t)SMB_UID_NO_CHANGE; + set_grp = VALID_STAT(*psbuf) ? psbuf->st_gid : (gid_t)SMB_GID_NO_CHANGE; + + if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && + IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { + *p_size=IVAL(pdata,0); /* first 8 Bytes are size */ +#ifdef LARGE_SMB_OFF_T + *p_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) { + /* more than 32 bits? */ + return NT_STATUS_INVALID_PARAMETER; + } +#endif /* LARGE_SMB_OFF_T */ + } + + pdata+=24; /* ctime & st_blocks are not changed */ + p_tvs->actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */ + p_tvs->modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */ + pdata+=16; + set_owner = (uid_t)IVAL(pdata,0); + pdata += 8; + set_grp = (gid_t)IVAL(pdata,0); + pdata += 8; + raw_unixmode = IVAL(pdata,28); + *p_unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode); + *p_dosmode = 0; /* Ensure dos mode change doesn't override this. */ + + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \ +size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", + fname, (double)*p_size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode)); + + if (!VALID_STAT(*psbuf)) { + + /* + * The only valid use of this is to create character and block + * devices, and named pipes. This is deprecated (IMHO) and + * a new info level should be used for mknod. JRA. + */ + + uint32 file_type = IVAL(pdata,0); +#if defined(HAVE_MAKEDEV) + uint32 dev_major = IVAL(pdata,4); + uint32 dev_minor = IVAL(pdata,12); +#endif + + SMB_DEV_T dev = (SMB_DEV_T)0; + + if (raw_unixmode == SMB_MODE_NO_CHANGE) { + return NT_STATUS_INVALID_PARAMETER; + } + +#if defined(HAVE_MAKEDEV) + dev = makedev(dev_major, dev_minor); +#endif + + switch (file_type) { +#if defined(S_IFIFO) + case UNIX_TYPE_FIFO: + *p_unixmode |= S_IFIFO; + break; +#endif +#if defined(S_IFSOCK) + case UNIX_TYPE_SOCKET: + *p_unixmode |= S_IFSOCK; + break; +#endif +#if defined(S_IFCHR) + case UNIX_TYPE_CHARDEV: + *p_unixmode |= S_IFCHR; + break; +#endif +#if defined(S_IFBLK) + case UNIX_TYPE_BLKDEV: + *p_unixmode |= S_IFBLK; + break; +#endif + default: + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ +0%o for file %s\n", (double)dev, *p_unixmode, fname )); + + /* Ok - do the mknod. */ + if (SMB_VFS_MKNOD(conn, fname, *p_unixmode, dev) != 0) { + return map_nt_error_from_unix(errno); + } + + /* If any of the other "set" calls fail we + * don't want to end up with a half-constructed mknod. + */ + + delete_on_fail = True; + + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl( + conn, parent_dirname(fname), + fname, *p_unixmode); + } + + if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { + status = map_nt_error_from_unix(errno); + SMB_VFS_UNLINK(conn,fname); + return status; + } + + /* Ensure we don't try and change anything else. */ + raw_unixmode = SMB_MODE_NO_CHANGE; + *p_size = get_file_size(*psbuf); + p_tvs->modtime = psbuf->st_mtime; + p_tvs->actime = psbuf->st_atime; + } + + /* + * Deal with the UNIX specific mode set. + */ + + if (raw_unixmode != SMB_MODE_NO_CHANGE) { + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", + (unsigned int)*p_unixmode, fname )); + if (SMB_VFS_CHMOD(conn,fname,*p_unixmode) != 0) { + return map_nt_error_from_unix(errno); + } + } + + /* + * Deal with the UNIX specific uid set. + */ + + if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) { + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", + (unsigned int)set_owner, fname )); + if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) { + status = map_nt_error_from_unix(errno); + if (delete_on_fail) { + SMB_VFS_UNLINK(conn,fname); + } + return status; + } + } + + /* + * Deal with the UNIX specific gid set. + */ + + if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) { + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", + (unsigned int)set_owner, fname )); + if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) { + status = map_nt_error_from_unix(errno); + if (delete_on_fail) { + SMB_VFS_UNLINK(conn,fname); + } + return status; + } + } + return NT_STATUS_OK; +} /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). @@ -4395,8 +4591,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pstring fname; int fd = -1; files_struct *fsp = NULL; - uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; - gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; mode_t unixmode = 0; NTSTATUS status = NT_STATUS_OK; @@ -4520,9 +4714,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char dosmode = dos_mode(conn,fname,&sbuf); unixmode = sbuf.st_mode; - set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE; - set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE; - switch (info_level) { case SMB_INFO_STANDARD: @@ -4654,170 +4845,22 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_SET_FILE_UNIX_BASIC: { - uint32 raw_unixmode; - BOOL delete_on_fail = False; - - if (total_data < 100) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - - if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && - IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { - size=IVAL(pdata,0); /* first 8 Bytes are size */ -#ifdef LARGE_SMB_OFF_T - size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); -#else /* LARGE_SMB_OFF_T */ - if (IVAL(pdata,4) != 0) { - /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } -#endif /* LARGE_SMB_OFF_T */ - } - pdata+=24; /* ctime & st_blocks are not changed */ - tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */ - tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */ - pdata+=16; - set_owner = (uid_t)IVAL(pdata,0); - pdata += 8; - set_grp = (gid_t)IVAL(pdata,0); - pdata += 8; - raw_unixmode = IVAL(pdata,28); - unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode); - dosmode = 0; /* Ensure dos mode change doesn't override this. */ - - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \ -size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", - fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode)); - - if (!VALID_STAT(sbuf)) { - - /* - * The only valid use of this is to create character and block - * devices, and named pipes. This is deprecated (IMHO) and - * a new info level should be used for mknod. JRA. - */ - - uint32 file_type = IVAL(pdata,0); -#if defined(HAVE_MAKEDEV) - uint32 dev_major = IVAL(pdata,4); - uint32 dev_minor = IVAL(pdata,12); -#endif - - SMB_DEV_T dev = (SMB_DEV_T)0; - - if (tran_call == TRANSACT2_SETFILEINFO) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); - - if (raw_unixmode == SMB_MODE_NO_CHANGE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); - } - -#if defined(HAVE_MAKEDEV) - dev = makedev(dev_major, dev_minor); -#endif - - switch (file_type) { -#if defined(S_IFIFO) - case UNIX_TYPE_FIFO: - unixmode |= S_IFIFO; - break; -#endif -#if defined(S_IFSOCK) - case UNIX_TYPE_SOCKET: - unixmode |= S_IFSOCK; - break; -#endif -#if defined(S_IFCHR) - case UNIX_TYPE_CHARDEV: - unixmode |= S_IFCHR; - break; -#endif -#if defined(S_IFBLK) - case UNIX_TYPE_BLKDEV: - unixmode |= S_IFBLK; - break; -#endif - default: - return(ERROR_DOS(ERRDOS,ERRnoaccess)); - } - - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ -0%o for file %s\n", (double)dev, unixmode, fname )); - - /* Ok - do the mknod. */ - if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - /* If any of the other "set" calls fail we - * don't want to end up with a half-constructed mknod. - */ - - delete_on_fail = True; - - if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl( - conn, parent_dirname(fname), - fname, unixmode); - } - - if (SMB_VFS_STAT(conn, fname, &sbuf) != 0) { - int saved_errno = errno; - SMB_VFS_UNLINK(conn,fname); - errno = saved_errno; - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - /* Ensure we don't try and change anything else. */ - raw_unixmode = SMB_MODE_NO_CHANGE; - size = get_file_size(sbuf); - tvs.modtime = sbuf.st_mtime; - tvs.actime = sbuf.st_atime; - } - - /* - * Deal with the UNIX specific mode set. - */ - - if (raw_unixmode != SMB_MODE_NO_CHANGE) { - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", - (unsigned int)unixmode, fname )); - if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - /* - * Deal with the UNIX specific uid set. - */ - - if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) { - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", - (unsigned int)set_owner, fname )); - if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) { - if (delete_on_fail) { - int saved_errno = errno; - SMB_VFS_UNLINK(conn,fname); - errno = saved_errno; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if (tran_call == TRANSACT2_SETFILEINFO) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - /* - * Deal with the UNIX specific gid set. - */ - - if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) { - DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", - (unsigned int)set_owner, fname )); - if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) { - if (delete_on_fail) { - int saved_errno = errno; - SMB_VFS_UNLINK(conn,fname); - errno = saved_errno; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + status = smb_set_file_unix_basic(conn, + pdata, + total_data, + fsp, + fname, + &sbuf, + &size, + &tvs, + &unixmode, + &dosmode); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } break; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 47ac9ef461..643c48cd27 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -454,6 +454,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) if (((SMB_OFF_T)len) < 0) { DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name )); + errno = EINVAL; return -1; } -- cgit From caf8c6a76be051559ffcfe97084edca43e0a3cee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 30 Jan 2007 22:22:06 +0000 Subject: r21064: The core of this patch is void message_register(int msg_type, void (*fn)(int msg_type, struct process_id pid, - void *buf, size_t len)) + void *buf, size_t len, + void *private_data), + void *private_data) { struct dispatch_fns *dfn; So this adds a (so far unused) private pointer that is passed from message_register to the message handler. A prerequisite to implement a tiny samba4-API compatible wrapper around our messaging system. That itself is necessary for the Samba4 notify system. Yes, I know, I could import the whole Samba4 messaging system, but I want to do it step by step and I think getting notify in is more important in this step. Volker (This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b) --- source3/smbd/blocking.c | 18 ++++++++++++------ source3/smbd/conn.c | 3 ++- source3/smbd/notify.c | 5 +++-- source3/smbd/open.c | 3 ++- source3/smbd/oplock.c | 30 ++++++++++++++++++++---------- source3/smbd/server.c | 30 ++++++++++++++++-------------- 6 files changed, 55 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index e0478fa762..70b2d30aab 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -71,7 +71,8 @@ static BOOL in_chained_smb(void) } static void received_unlock_msg(int msg_type, struct process_id src, - void *buf, size_t len); + void *buf, size_t len, + void *private_data); /**************************************************************************** Function to push a blocking lock request onto the lock queue. @@ -154,7 +155,8 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { - message_register(MSG_SMB_UNLOCK, received_unlock_msg); + message_register(MSG_SMB_UNLOCK, received_unlock_msg, + NULL); set_lock_msg = True; } @@ -581,7 +583,8 @@ BOOL blocking_lock_was_deferred(int mid) *****************************************************************************/ static void received_unlock_msg(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { DEBUG(10,("received_unlock_msg\n")); process_blocking_lock_queue(); @@ -775,8 +778,10 @@ void process_blocking_lock_queue(void) #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS)) -static void process_blocking_lock_cancel_message(int msg_type, struct process_id src, - void *buf, size_t len) +static void process_blocking_lock_cancel_message(int msg_type, + struct process_id src, + void *buf, size_t len, + void *private_data) { NTSTATUS err; const char *msg = (const char *)buf; @@ -822,7 +827,8 @@ BOOL blocking_lock_cancel(files_struct *fsp, if (!initialized) { /* Register our message. */ message_register(MSG_SMB_BLOCKING_LOCK_CANCEL, - process_blocking_lock_cancel_message); + process_blocking_lock_cancel_message, + NULL); initialized = True; } diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 083e8339c8..44888b777f 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -311,7 +311,8 @@ the message contains just a share name and all instances of that share are unmounted the special sharename '*' forces unmount of all shares ****************************************************************************/ -void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len) +void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len, + void *private_data) { connection_struct *conn, *next; fstring sharename; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index c2f4572e7e..d920633b0a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -498,7 +498,8 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) } static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { struct notify_message msg; files_struct *fsp; @@ -548,7 +549,7 @@ BOOL init_change_notify(void) return False; } - message_register(MSG_SMB_NOTIFY, notify_message_callback); + message_register(MSG_SMB_NOTIFY, notify_message_callback, NULL); return True; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a5a8eacda0..529677a5f3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2210,7 +2210,8 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, smbd process. ****************************************************************************/ -void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len) +void msg_file_was_renamed(int msg_type, struct process_id src, + void *buf, size_t len, void *private_data) { files_struct *fsp; char *frm = (char *)buf; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1f73ea837d..7b82a9ad9c 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -392,7 +392,8 @@ static void add_oplock_timeout_handler(files_struct *fsp) *******************************************************************/ static void process_oplock_async_level2_break_message(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { struct share_mode_entry msg; files_struct *fsp; @@ -478,7 +479,8 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce *******************************************************************/ static void process_oplock_break_message(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { struct share_mode_entry msg; files_struct *fsp; @@ -586,7 +588,8 @@ static void process_oplock_break_message(int msg_type, struct process_id src, *******************************************************************/ static void process_kernel_oplock_break(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { SMB_DEV_T dev; SMB_INO_T inode; @@ -677,7 +680,8 @@ void reply_to_oplock_break_requests(files_struct *fsp) } static void process_oplock_break_response(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { struct share_mode_entry msg; @@ -704,7 +708,8 @@ static void process_oplock_break_response(int msg_type, struct process_id src, } static void process_open_retry_message(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { struct share_mode_entry msg; @@ -858,15 +863,20 @@ BOOL init_oplocks(void) DEBUG(3,("init_oplocks: initializing messages.\n")); message_register(MSG_SMB_BREAK_REQUEST, - process_oplock_break_message); + process_oplock_break_message, + NULL); message_register(MSG_SMB_ASYNC_LEVEL2_BREAK, - process_oplock_async_level2_break_message); + process_oplock_async_level2_break_message, + NULL); message_register(MSG_SMB_BREAK_RESPONSE, - process_oplock_break_response); + process_oplock_break_response, + NULL); message_register(MSG_SMB_KERNEL_BREAK, - process_kernel_oplock_break); + process_kernel_oplock_break, + NULL); message_register(MSG_SMB_OPEN_RETRY, - process_open_retry_message); + process_open_retry_message, + NULL); if (lp_kernel_oplocks()) { #if HAVE_KERNEL_OPLOCKS_IRIX diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0bb4ad5b04..dcb685511b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -76,7 +76,7 @@ struct event_context *smbd_event_context(void) ********************************************************************/ static void smb_conf_updated(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n")); reload_services(False); @@ -88,7 +88,7 @@ static void smb_conf_updated(int msg_type, struct process_id src, ********************************************************************/ static void smb_stat_cache_delete(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { const char *name = (const char *)buf; DEBUG(10,("smb_stat_cache_delete: delete name %s\n", name)); @@ -139,7 +139,8 @@ static void killkids(void) ****************************************************************************/ static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid), - void *UNUSED(buf), size_t UNUSED(len)) + void *UNUSED(buf), size_t UNUSED(len), + void *private_data) { DEBUG(10, ("** sam sync message received, ignoring\n")); } @@ -150,7 +151,7 @@ static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid), ****************************************************************************/ static void msg_sam_repl(int msg_type, struct process_id pid, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { uint32 low_serial; @@ -184,7 +185,7 @@ static BOOL open_sockets_inetd(void) } static void msg_exit_server(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { DEBUG(3, ("got a SHUTDOWN message\n")); exit_server_cleanly(NULL); @@ -192,7 +193,7 @@ static void msg_exit_server(int msg_type, struct process_id src, #ifdef DEVELOPER static void msg_inject_fault(int msg_type, struct process_id src, - void *buf, size_t len) + void *buf, size_t len, void *private_data) { int sig; @@ -429,15 +430,16 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* Listen to messages */ - message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); - message_register(MSG_SMB_SAM_REPL, msg_sam_repl); - message_register(MSG_SHUTDOWN, msg_exit_server); - message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); - message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated); - message_register(MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete); + message_register(MSG_SMB_SAM_SYNC, msg_sam_sync, NULL); + message_register(MSG_SMB_SAM_REPL, msg_sam_repl, NULL); + message_register(MSG_SHUTDOWN, msg_exit_server, NULL); + message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed, NULL); + message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated, NULL); + message_register(MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete, + NULL); #ifdef DEVELOPER - message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault); + message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault, NULL); #endif /* now accept incoming connections - forking a new process @@ -1097,7 +1099,7 @@ extern void build_options(BOOL screen); TimeInit(); /* register our message handlers */ - message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); + message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis, NULL); smbd_process(); -- cgit From 44da8a6907882bd90d56daf4b712ebb073869596 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Jan 2007 00:49:49 +0000 Subject: r21067: Finished refactoring setqpathinfo to be readable and modifiable by other people. Now to look over the build farm and fix any breakage. Jeremy. (This used to be commit 997259f2479842ee888621ae2d5446797b3a7cb6) --- source3/smbd/trans2.c | 815 ++++++++++++++++++++++++++------------------------ 1 file changed, 430 insertions(+), 385 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 826ccd3f92..9af25d95d6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3741,6 +3741,162 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne return status; } +/**************************************************************************** + Deal with setting the time from any of the setfilepathinfo functions. +****************************************************************************/ + +static NTSTATUS smb_set_file_time(connection_struct *conn, + files_struct *fsp, + const char *fname, + const SMB_STRUCT_STAT *psbuf, + struct utimbuf tvs) +{ + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* get some defaults (no modifications) if any info is zero or -1. */ + if (null_mtime(tvs.actime)) { + tvs.actime = psbuf->st_atime; + } + + if (null_mtime(tvs.modtime)) { + tvs.modtime = psbuf->st_mtime; + } + + DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime))); + DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime))); + + /* + * Try and set the times of this file if + * they are different from the current values. + */ + + if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) { + return NT_STATUS_OK; + } + + if(fsp != NULL) { + /* + * This was a setfileinfo on an open file. + * NT does this a lot. We also need to + * set the time here, as it can be read by + * FindFirst/FindNext and with the patch for bug #2045 + * in smbd/fileio.c it ensures that this timestamp is + * kept sticky even after a write. We save the request + * away and will set it on file close and after a write. JRA. + */ + + if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { + DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) )); + fsp_set_pending_modtime(fsp, tvs.modtime); + } + + } + DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); + + if(file_utime(conn, fname, &tvs)!=0) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; +} + +/**************************************************************************** + Deal with setting the dosmode from any of the setfilepathinfo functions. +****************************************************************************/ + +static NTSTATUS smb_set_file_dosmode(connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 dosmode) +{ + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (dosmode) { + if (S_ISDIR(psbuf->st_mode)) { + dosmode |= aDIR; + } else { + dosmode &= ~aDIR; + } + } + + DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode)); + + /* check the mode isn't different, before changing it */ + if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) { + + DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n", + fname, (unsigned int)dosmode )); + + if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) { + DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n", + fname, strerror(errno))); + return map_nt_error_from_unix(errno); + } + } + return NT_STATUS_OK; +} + +/**************************************************************************** + Deal with setting the size from any of the setfilepathinfo functions. +****************************************************************************/ + +static NTSTATUS smb_set_file_size(connection_struct *conn, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf, + SMB_OFF_T size) +{ + NTSTATUS status = NT_STATUS_OK; + files_struct *new_fsp = NULL; + + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size)); + + if (size == get_file_size(*psbuf)) { + return NT_STATUS_OK; + } + + DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", + fname, (double)size )); + + if (fsp && fsp->fh->fd != -1) { + /* Handle based call. */ + if (vfs_set_filelen(fsp, size) == -1) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; + } + + status = open_file_ntcreate(conn, fname, psbuf, + FILE_WRITE_DATA, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + FORCE_OPLOCK_BREAK_TO_NONE, + NULL, &new_fsp); + + if (!NT_STATUS_IS_OK(status)) { + /* NB. We check for open_was_deferred in the caller. */ + return status; + } + + if (vfs_set_filelen(new_fsp, size) == -1) { + status = map_nt_error_from_unix(errno); + close_file(new_fsp,NORMAL_CLOSE); + return status; + } + + close_file(new_fsp,NORMAL_CLOSE); + return NT_STATUS_OK; +} + /**************************************************************************** Deal with SMB_INFO_SET_EA. ****************************************************************************/ @@ -3797,10 +3953,12 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - int dosmode) + const char *fname, + SMB_STRUCT_STAT *psbuf) { NTSTATUS status = NT_STATUS_OK; BOOL delete_on_close; + uint32 dosmode = 0; if (total_data < 1) { return NT_STATUS_INVALID_PARAMETER; @@ -3811,6 +3969,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, } delete_on_close = (CVAL(pdata,0) ? True : False); + dosmode = dos_mode(conn, fname, psbuf); status = can_set_delete_on_close(fsp, delete_on_close, dosmode); @@ -4049,8 +4208,8 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - SMB_STRUCT_STAT *psbuf, - const char *fname) + const char *fname, + SMB_STRUCT_STAT *psbuf) { uint16 posix_acl_version; uint16 num_file_acls; @@ -4211,59 +4370,86 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, Deal with SMB_INFO_STANDARD. ****************************************************************************/ -static NTSTATUS smb_set_info_standard(const char *pdata, +static NTSTATUS smb_set_info_standard(connection_struct *conn, + const char *pdata, int total_data, - struct utimbuf *p_tvs) + files_struct *fsp, + const char *fname, + const SMB_STRUCT_STAT *psbuf) { + struct utimbuf tvs; + if (total_data < 12) { return NT_STATUS_INVALID_PARAMETER; } /* access time */ - p_tvs->actime = srv_make_unix_date2(pdata+l1_fdateLastAccess); + tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess); /* write time */ - p_tvs->modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); - return NT_STATUS_OK; + tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); + + return smb_set_file_time(conn, + fsp, + fname, + psbuf, + tvs); } /**************************************************************************** Deal with SMB_SET_FILE_BASIC_INFO. ****************************************************************************/ -static NTSTATUS smb_set_file_basic_info(const char *pdata, +static NTSTATUS smb_set_file_basic_info(connection_struct *conn, + const char *pdata, int total_data, - struct utimbuf *p_tvs, - int *p_dosmode) + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) { /* Patch to do this correctly from Paul Eggert . */ time_t write_time; time_t changed_time; + uint32 dosmode = 0; + struct utimbuf tvs; + NTSTATUS status = NT_STATUS_OK; if (total_data < 36) { return NT_STATUS_INVALID_PARAMETER; } + /* Set the attributes */ + dosmode = IVAL(pdata,32); + status = smb_set_file_dosmode(conn, + fname, + psbuf, + dosmode); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Ignore create time at offset pdata. */ /* access time */ - p_tvs->actime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); + tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16)); changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24)); - p_tvs->modtime = MIN(write_time, changed_time); + tvs.modtime = MIN(write_time, changed_time); - if (write_time > p_tvs->modtime && write_time != (time_t)-1) { - p_tvs->modtime = write_time; + if (write_time > tvs.modtime && write_time != (time_t)-1) { + tvs.modtime = write_time; } /* Prefer a defined time to an undefined one. */ - if (null_mtime(p_tvs->modtime)) { - p_tvs->modtime = null_mtime(write_time) ? changed_time : write_time; + if (null_mtime(tvs.modtime)) { + tvs.modtime = null_mtime(write_time) ? changed_time : write_time; } - /* attributes */ - *p_dosmode = IVAL(pdata,32); - return NT_STATUS_OK; + return smb_set_file_time(conn, + fsp, + fname, + psbuf, + tvs); } /**************************************************************************** @@ -4275,10 +4461,15 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, int total_data, files_struct *fsp, const char *fname, - SMB_STRUCT_STAT *psbuf, - SMB_OFF_T *p_size) + SMB_STRUCT_STAT *psbuf) { - SMB_BIG_UINT allocation_size; + SMB_BIG_UINT allocation_size = 0; + NTSTATUS status = NT_STATUS_OK; + files_struct *new_fsp = NULL; + + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } if (total_data < 8) { return NT_STATUS_INVALID_PARAMETER; @@ -4301,61 +4492,43 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, allocation_size = smb_roundup(conn, allocation_size); } - if(allocation_size != get_file_size(*psbuf)) { - int ret = -1; - SMB_STRUCT_STAT new_sbuf; + if(allocation_size == get_file_size(*psbuf)) { + return NT_STATUS_OK; + } - DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n", + DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n", fname, (double)allocation_size )); - if (fsp && fsp->fh->fd != -1) { - /* Open file. */ - ret = vfs_allocate_file_space(fsp, allocation_size); - if (ret == -1) { - return map_nt_error_from_unix(errno); - } - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&new_sbuf) != 0) { - DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n", - fsp->fnum, strerror(errno))); - return map_nt_error_from_unix(errno); - } - } else { - /* Pathname or stat or directory file. */ - files_struct *new_fsp = NULL; - NTSTATUS status; - - status = open_file_ntcreate(conn, fname, psbuf, - FILE_WRITE_DATA, - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - FORCE_OPLOCK_BREAK_TO_NONE, - NULL, &new_fsp); - - if (!NT_STATUS_IS_OK(status)) { - /* NB. We check for open_was_deferred in the caller. */ - return status; - } - ret = vfs_allocate_file_space(new_fsp, allocation_size); - if (ret == -1) { - status = map_nt_error_from_unix(errno); - close_file(new_fsp,NORMAL_CLOSE); - return status; - } - if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) { - DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n", - new_fsp->fnum, strerror(errno))); - status = map_nt_error_from_unix(errno); - close_file(new_fsp,NORMAL_CLOSE); - return status; - } - close_file(new_fsp,NORMAL_CLOSE); + if (fsp && fsp->fh->fd != -1) { + /* Open file handle. */ + if (vfs_allocate_file_space(fsp, allocation_size) == -1) { + return map_nt_error_from_unix(errno); } + return NT_STATUS_OK; + } + + /* Pathname or stat or directory file. */ - /* Allocate can truncate size... */ - *p_size = get_file_size(new_sbuf); + status = open_file_ntcreate(conn, fname, psbuf, + FILE_WRITE_DATA, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_NORMAL, + FORCE_OPLOCK_BREAK_TO_NONE, + NULL, &new_fsp); + + if (!NT_STATUS_IS_OK(status)) { + /* NB. We check for open_was_deferred in the caller. */ + return status; } + if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) { + status = map_nt_error_from_unix(errno); + close_file(new_fsp,NORMAL_CLOSE); + return status; + } + + close_file(new_fsp,NORMAL_CLOSE); return NT_STATUS_OK; } @@ -4366,16 +4539,19 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, const char *pdata, int total_data, + files_struct *fsp, const char *fname, - SMB_OFF_T *p_size) + SMB_STRUCT_STAT *psbuf) { + SMB_OFF_T size; + if (total_data < 8) { return NT_STATUS_INVALID_PARAMETER; } - *p_size = IVAL(pdata,0); + size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T - *p_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); + size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) { /* more than 32 bits? */ @@ -4383,7 +4559,96 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, } #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for " - "file %s to %.0f\n", fname, (double)*p_size )); + "file %s to %.0f\n", fname, (double)size )); + + return smb_set_file_size(conn, + fsp, + fname, + psbuf, + size); +} + +/**************************************************************************** + Allow a UNIX info mknod. +****************************************************************************/ + +static NTSTATUS smb_unix_mknod(connection_struct *conn, + const char *pdata, + int total_data, + const char *fname, + SMB_STRUCT_STAT *psbuf) +{ + uint32 file_type = IVAL(pdata,56); +#if defined(HAVE_MAKEDEV) + uint32 dev_major = IVAL(pdata,60); + uint32 dev_minor = IVAL(pdata,68); +#endif + SMB_DEV_T dev = (SMB_DEV_T)0; + uint32 raw_unixmode = IVAL(pdata,84); + mode_t unixmode; + + if (total_data < 100) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (raw_unixmode == SMB_MODE_NO_CHANGE) { + return NT_STATUS_INVALID_PARAMETER; + } + + unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode); + +#if defined(HAVE_MAKEDEV) + dev = makedev(dev_major, dev_minor); +#endif + + switch (file_type) { +#if defined(S_IFIFO) + case UNIX_TYPE_FIFO: + unixmode |= S_IFIFO; + break; +#endif +#if defined(S_IFSOCK) + case UNIX_TYPE_SOCKET: + unixmode |= S_IFSOCK; + break; +#endif +#if defined(S_IFCHR) + case UNIX_TYPE_CHARDEV: + unixmode |= S_IFCHR; + break; +#endif +#if defined(S_IFBLK) + case UNIX_TYPE_BLKDEV: + unixmode |= S_IFBLK; + break; +#endif + default: + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ +0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname )); + + /* Ok - do the mknod. */ + if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) { + return map_nt_error_from_unix(errno); + } + + /* If any of the other "set" calls fail we + * don't want to end up with a half-constructed mknod. + */ + + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl( + conn, parent_dirname(fname), + fname, unixmode); + } + + if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { + NTSTATUS status = map_nt_error_from_unix(errno); + SMB_VFS_UNLINK(conn,fname); + return status; + } return NT_STATUS_OK; } @@ -4396,30 +4661,26 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, int total_data, files_struct *fsp, const char *fname, - SMB_STRUCT_STAT *psbuf, - SMB_OFF_T *p_size, - struct utimbuf *p_tvs, - mode_t *p_unixmode, - int *p_dosmode) + SMB_STRUCT_STAT *psbuf) { + struct utimbuf tvs; + uint32 raw_unixmode; + mode_t unixmode; + SMB_OFF_T size = 0; uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; - uint32 raw_unixmode; - BOOL delete_on_fail = False; NTSTATUS status = NT_STATUS_OK; + BOOL delete_on_fail = False; if (total_data < 100) { return NT_STATUS_INVALID_PARAMETER; } - set_owner = VALID_STAT(*psbuf) ? psbuf->st_uid : (uid_t)SMB_UID_NO_CHANGE; - set_grp = VALID_STAT(*psbuf) ? psbuf->st_gid : (gid_t)SMB_GID_NO_CHANGE; - if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { - *p_size=IVAL(pdata,0); /* first 8 Bytes are size */ + size=IVAL(pdata,0); /* first 8 Bytes are size */ #ifdef LARGE_SMB_OFF_T - *p_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); + size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); #else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) { /* more than 32 bits? */ @@ -4428,102 +4689,43 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, #endif /* LARGE_SMB_OFF_T */ } - pdata+=24; /* ctime & st_blocks are not changed */ - p_tvs->actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */ - p_tvs->modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */ - pdata+=16; - set_owner = (uid_t)IVAL(pdata,0); - pdata += 8; - set_grp = (gid_t)IVAL(pdata,0); - pdata += 8; - raw_unixmode = IVAL(pdata,28); - *p_unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode); - *p_dosmode = 0; /* Ensure dos mode change doesn't override this. */ + tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */ + tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */ + set_owner = (uid_t)IVAL(pdata,40); + set_grp = (gid_t)IVAL(pdata,48); + raw_unixmode = IVAL(pdata,84); + unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode); DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", - fname, (double)*p_size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode)); + fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode)); if (!VALID_STAT(*psbuf)) { - /* * The only valid use of this is to create character and block * devices, and named pipes. This is deprecated (IMHO) and * a new info level should be used for mknod. JRA. */ - uint32 file_type = IVAL(pdata,0); -#if defined(HAVE_MAKEDEV) - uint32 dev_major = IVAL(pdata,4); - uint32 dev_minor = IVAL(pdata,12); -#endif - - SMB_DEV_T dev = (SMB_DEV_T)0; - - if (raw_unixmode == SMB_MODE_NO_CHANGE) { - return NT_STATUS_INVALID_PARAMETER; - } - -#if defined(HAVE_MAKEDEV) - dev = makedev(dev_major, dev_minor); -#endif - - switch (file_type) { -#if defined(S_IFIFO) - case UNIX_TYPE_FIFO: - *p_unixmode |= S_IFIFO; - break; -#endif -#if defined(S_IFSOCK) - case UNIX_TYPE_SOCKET: - *p_unixmode |= S_IFSOCK; - break; -#endif -#if defined(S_IFCHR) - case UNIX_TYPE_CHARDEV: - *p_unixmode |= S_IFCHR; - break; -#endif -#if defined(S_IFBLK) - case UNIX_TYPE_BLKDEV: - *p_unixmode |= S_IFBLK; - break; -#endif - default: - return NT_STATUS_INVALID_PARAMETER; - } - - DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ -0%o for file %s\n", (double)dev, *p_unixmode, fname )); - - /* Ok - do the mknod. */ - if (SMB_VFS_MKNOD(conn, fname, *p_unixmode, dev) != 0) { - return map_nt_error_from_unix(errno); - } - - /* If any of the other "set" calls fail we - * don't want to end up with a half-constructed mknod. - */ - - delete_on_fail = True; - - if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl( - conn, parent_dirname(fname), - fname, *p_unixmode); - } - - if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { - status = map_nt_error_from_unix(errno); - SMB_VFS_UNLINK(conn,fname); + status = smb_unix_mknod(conn, + pdata, + total_data, + fname, + psbuf); + if (!NT_STATUS_IS_OK(status)) { return status; } /* Ensure we don't try and change anything else. */ raw_unixmode = SMB_MODE_NO_CHANGE; - *p_size = get_file_size(*psbuf); - p_tvs->modtime = psbuf->st_mtime; - p_tvs->actime = psbuf->st_atime; + size = get_file_size(*psbuf); + tvs.modtime = psbuf->st_mtime; + tvs.actime = psbuf->st_atime; + /* + * We continue here as we might want to change the + * owner uid/gid. + */ + delete_on_fail = True; } /* @@ -4532,8 +4734,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (raw_unixmode != SMB_MODE_NO_CHANGE) { DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", - (unsigned int)*p_unixmode, fname )); - if (SMB_VFS_CHMOD(conn,fname,*p_unixmode) != 0) { + (unsigned int)unixmode, fname )); + if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) { return map_nt_error_from_unix(errno); } } @@ -4569,7 +4771,25 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return status; } } - return NT_STATUS_OK; + + /* Deal with any size changes. */ + + status = smb_set_file_size(conn, + fsp, + fname, + psbuf, + size); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Deal with any time changes. */ + + return smb_set_file_time(conn, + fsp, + fname, + psbuf, + tvs); } /**************************************************************************** @@ -4584,14 +4804,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char char *params = *pparams; char *pdata = *ppdata; uint16 info_level; - int dosmode=0; - SMB_OFF_T size=0; - struct utimbuf tvs; SMB_STRUCT_STAT sbuf; pstring fname; - int fd = -1; files_struct *fsp = NULL; - mode_t unixmode = 0; NTSTATUS status = NT_STATUS_OK; if (!params) { @@ -4599,7 +4814,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } ZERO_STRUCT(sbuf); - ZERO_STRUCT(tvs); if (tran_call == TRANSACT2_SETFILEINFO) { if (total_params < 4) { @@ -4641,9 +4855,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char CHECK_FSP(fsp,conn); pstrcpy(fname, fsp->fsp_name); - fd = fsp->fh->fd; - if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -4680,17 +4893,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } - if (!CAN_WRITE(conn)) + if (!CAN_WRITE(conn)) { return ERROR_DOS(ERRSRV,ERRaccess); + } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - if (VALID_STAT(sbuf)) { - unixmode = sbuf.st_mode; - } - DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); @@ -4708,22 +4918,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char sbuf.st_mtime = fsp->pending_modtime; } - size = get_file_size(sbuf); - tvs.modtime = sbuf.st_mtime; - tvs.actime = sbuf.st_atime; - dosmode = dos_mode(conn,fname,&sbuf); - unixmode = sbuf.st_mode; - switch (info_level) { case SMB_INFO_STANDARD: { - status = smb_set_info_standard(pdata, - total_data, - &tvs); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } + status = smb_set_info_standard(conn, + pdata, + total_data, + fsp, + fname, + &sbuf); break; } @@ -4734,22 +4938,18 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char total_data, fsp, fname); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - goto out; + break; } case SMB_SET_FILE_BASIC_INFO: case SMB_FILE_BASIC_INFORMATION: { - status = smb_set_file_basic_info(pdata, + status = smb_set_file_basic_info(conn, + pdata, total_data, - &tvs, - &dosmode); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } + fsp, + fname, + &sbuf); break; } @@ -4761,15 +4961,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char total_data, fsp, fname, - &sbuf, - &size); - if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { - /* We have re-scheduled this call. */ - return -1; - } - return ERROR_NT(status); - } + &sbuf); break; } @@ -4779,11 +4971,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char status = smb_set_file_end_of_file_info(conn, pdata, total_data, + fsp, fname, - &size); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } + &sbuf); break; } @@ -4803,11 +4993,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pdata, total_data, fsp, - dosmode); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - goto out; + fname, + &sbuf); + break; } case SMB_FILE_POSITION_INFORMATION: @@ -4816,10 +5004,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pdata, total_data, fsp); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - goto out; + break; } /* From tridge Samba4 : @@ -4833,10 +5018,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char status = smb_file_mode_information(conn, pdata, total_data); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - goto out; + break; } /* @@ -4854,14 +5036,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char total_data, fsp, fname, - &sbuf, - &size, - &tvs, - &unixmode, - &dosmode); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } + &sbuf); break; } @@ -4876,10 +5051,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pdata, total_data, fname); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - goto out; + break; } case SMB_SET_FILE_UNIX_HLINK: @@ -4893,10 +5065,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pdata, total_data, fname); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - goto out; + break; } case SMB_FILE_RENAME_INFORMATION: @@ -4908,17 +5077,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char total_data, fsp, fname); - if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { - /* We have re-scheduled this call. */ - return -1; - } - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); - } - return ERROR_NT(status); - } - goto out; + break; } #if defined(HAVE_POSIX_ACLS) @@ -4930,10 +5089,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char fsp, &sbuf, fname); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - goto out; + break; } #endif @@ -4945,140 +5101,29 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pdata, total_data, fsp); - if (!NT_STATUS_IS_OK(status)) { - if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) { - /* We have re-scheduled this call. */ - return -1; - } - return ERROR_NT(status); - } - goto out; + break; } default: return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - /* get some defaults (no modifications) if any info is zero or -1. */ - if (null_mtime(tvs.actime)) { - tvs.actime = sbuf.st_atime; - } - - if (null_mtime(tvs.modtime)) { - tvs.modtime = sbuf.st_mtime; - } - - DEBUG(6,("actime: %s " , ctime(&tvs.actime))); - DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); - DEBUG(6,("size: %.0f ", (double)size)); - - if (dosmode) { - if (S_ISDIR(sbuf.st_mode)) { - dosmode |= aDIR; - } else { - dosmode &= ~aDIR; - } - } - - DEBUG(6,("dosmode: %x\n" , dosmode)); - - if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) || - (info_level == SMB_SET_FILE_ALLOCATION_INFO) || - (info_level == SMB_FILE_ALLOCATION_INFORMATION) || - (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) { - - /* - * Only do this test if we are not explicitly - * changing the size of a file. - */ - if (!size) - size = get_file_size(sbuf); - } - - /* - * Try and set the times, size and mode of this file - - * if they are different from the current values - */ - - /* check the mode isn't different, before changing it */ - if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) { - - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode )); - - if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) { - DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } - - /* Now the size. */ - if (size != get_file_size(sbuf)) { - - int ret; - - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", - fname, (double)size )); - - if (fd == -1) { - files_struct *new_fsp = NULL; - - status = open_file_ntcreate(conn, fname, &sbuf, - FILE_WRITE_DATA, - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - FORCE_OPLOCK_BREAK_TO_NONE, - NULL, &new_fsp); - if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { - /* We have re-scheduled this call. */ - return -1; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - ret = vfs_set_filelen(new_fsp, size); - close_file(new_fsp,NORMAL_CLOSE); - } else { - ret = vfs_set_filelen(fsp, size); - } - - if (ret == -1) { - return (UNIXERROR(ERRHRD,ERRdiskfull)); + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; } - } - - /* - * Finally the times. - */ - if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { - if(fsp != NULL) { - /* - * This was a setfileinfo on an open file. - * NT does this a lot. We also need to - * set the time here, as it can be read by - * FindFirst/FindNext and with the patch for bug #2045 - * in smbd/fileio.c it ensures that this timestamp is - * kept sticky even after a write. We save the request - * away and will set it on file close and after a write. JRA. - */ - - if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { - DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) )); - fsp_set_pending_modtime(fsp, tvs.modtime); - } - + if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) { + /* We have re-scheduled this call. */ + return -1; } - DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); - - if(file_utime(conn, fname, &tvs)!=0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); } + return ERROR_NT(status); } - out: - SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); -- cgit From 05f298b47e4493ccf04b8a1698c0593c8a0deaac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 11:13:40 +0000 Subject: r21073: Fix compiler warning (This used to be commit 3977ee027f500c76bcfd3de34301d3959e9b6d2b) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9af25d95d6..e686acd25d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5087,8 +5087,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pdata, total_data, fsp, - &sbuf, - fname); + fname, + &sbuf); break; } #endif -- cgit From 9ee97d2f7d4e3c7e14d32825c5ee23b136ce4e07 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 12:24:59 +0000 Subject: r21077: A step to minimize the diff later: This pulls in unmodified files from Samba4, not compiled yet. This way the modifications become visible later. ntvfs/common/notify.c -> smbd/notify_internal.c ntvfs/sysdep/inotify.c -> smbd/notify_inotify.c Naturally I had to disable notify again :-) Volker (This used to be commit cdb7d582b7397faa5926bff5783da7fef4209948) --- source3/smbd/notify.c | 5 - source3/smbd/notify_inotify.c | 497 ++++++++++++++++++++----------- source3/smbd/notify_internal.c | 661 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 987 insertions(+), 176 deletions(-) create mode 100644 source3/smbd/notify_internal.c (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d920633b0a..4c82b9fca8 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -529,11 +529,6 @@ BOOL init_change_notify(void) { cnotify = NULL; -#if HAVE_INOTIFY - if ((cnotify == NULL) && lp_kernel_change_notify()) { - cnotify = inotify_notify_init(smbd_event_context()); - } -#endif #if HAVE_KERNEL_CHANGE_NOTIFY if (cnotify == NULL && lp_kernel_change_notify()) cnotify = kernel_notify_init(smbd_event_context()); diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 64ea62ff74..8bb0096dcc 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -1,27 +1,33 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2006 + + 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. +*/ + /* - * inotify change notify support - * - * Copyright (c) Andrew Tridgell 2006 - * Copyright (c) Volker Lendecke 2007 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + notify implementation using inotify +*/ #include "includes.h" - -#ifdef HAVE_INOTIFY +#include "system/filesys.h" +#include "ntvfs/sysdep/sys_notify.h" +#include "lib/events/events.h" +#include "lib/util/dlinklist.h" +#include "libcli/raw/smb.h" #include #include @@ -46,218 +52,367 @@ static int inotify_rm_watch(int fd, int wd) } #endif -struct inotify_ctx { - struct inotify_ctx *prev, *next; - int wd; - files_struct *fsp; -}; -static struct inotify_ctx *inotify_list; +/* older glibc headers don't have these defines either */ +#ifndef IN_ONLYDIR +#define IN_ONLYDIR 0x01000000 +#endif +#ifndef IN_MASK_ADD +#define IN_MASK_ADD 0x20000000 +#endif -static int inotify_watch_fd; +struct inotify_private { + struct sys_notify_context *ctx; + int fd; + struct watch_context *watches; +}; -/* - map from a change notify mask to a inotify mask. Remove any bits - which we can handle -*/ -static const struct { - uint32_t notify_mask; - uint32_t inotify_mask; -} inotify_mapping[] = { - {FILE_NOTIFY_CHANGE_FILE_NAME, - IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO}, - {FILE_NOTIFY_CHANGE_DIR_NAME, - IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO}, - {FILE_NOTIFY_CHANGE_ATTRIBUTES, - IN_ATTRIB|IN_MOVED_TO|IN_MOVED_FROM|IN_MODIFY}, - {FILE_NOTIFY_CHANGE_LAST_WRITE, IN_ATTRIB}, - {FILE_NOTIFY_CHANGE_LAST_ACCESS, IN_ATTRIB}, - {FILE_NOTIFY_CHANGE_EA, IN_ATTRIB}, - {FILE_NOTIFY_CHANGE_SECURITY, IN_ATTRIB} +struct watch_context { + struct watch_context *next, *prev; + struct inotify_private *in; + int wd; + sys_notify_callback_t callback; + void *private_data; + uint32_t mask; /* the inotify mask */ + uint32_t filter; /* the windows completion filter */ + const char *path; }; -static uint32_t inotify_map(uint32 *filter) -{ - int i; - uint32_t out=0; - for (i=0;iwd) == -1) { - DEBUG(0, ("inotify_rm_watch failed: %s\n", strerror(errno))); - } - DLIST_REMOVE(inotify_list, ctx); + close(in->fd); return 0; } -static void *inotify_add(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - files_struct *fsp, uint32 *pfilter) -{ - struct inotify_ctx *ctx; - uint32_t inotify_mask; - pstring fullpath; - uint32 filter; - - filter = *pfilter; - if ((filter & (FILE_NOTIFY_CHANGE_FILE - |FILE_NOTIFY_CHANGE_DIR_NAME)) == 0) { - /* - * This first implementation only looks at create/delete - */ - return NULL; - } - inotify_mask = inotify_map(&filter); - - if (inotify_mask == 0) { - DEBUG(10, ("inotify_mask == 0, nothing to do\n")); - return NULL; +/* + see if a particular event from inotify really does match a requested + notify event in SMB +*/ +static BOOL filter_match(struct watch_context *w, struct inotify_event *e) +{ + if ((e->mask & w->mask) == 0) { + /* this happens because inotify_add_watch() coalesces watches on the same + path, oring their masks together */ + return False; } - pstrcpy(fullpath, fsp->fsp_name); - if (!canonicalize_path(fsp->conn, fullpath)) { - DEBUG(0, ("failed to canonicalize path '%s'\n", fullpath)); - return NULL; + /* SMB separates the filters for files and directories */ + if (e->mask & IN_ISDIR) { + if ((w->filter & FILE_NOTIFY_CHANGE_DIR_NAME) == 0) { + return False; + } + } else { + if ((e->mask & IN_ATTRIB) && + (w->filter & (FILE_NOTIFY_CHANGE_ATTRIBUTES| + FILE_NOTIFY_CHANGE_LAST_WRITE| + FILE_NOTIFY_CHANGE_LAST_ACCESS| + FILE_NOTIFY_CHANGE_EA| + FILE_NOTIFY_CHANGE_SECURITY))) { + return True; + } + if ((e->mask & IN_MODIFY) && + (w->filter & FILE_NOTIFY_CHANGE_ATTRIBUTES)) { + return True; + } + if ((w->filter & FILE_NOTIFY_CHANGE_FILE_NAME) == 0) { + return False; + } } - if (*fullpath != '/') { - DEBUG(0, ("canonicalized path '%s' into `%s`\n", fsp->fsp_name, - fullpath)); - DEBUGADD(0, ("but expected an absolute path\n")); - return NULL; - } + return True; +} - if (!(ctx = TALLOC_P(mem_ctx, struct inotify_ctx))) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } - - ctx->fsp = fsp; - ctx->wd = inotify_add_watch(inotify_watch_fd, fullpath, inotify_mask); - if (ctx->wd == -1) { - DEBUG(5, ("inotify_add_watch failed: %s\n", strerror(errno))); - TALLOC_FREE(ctx); - return NULL; - } - - DLIST_ADD(inotify_list, ctx); - talloc_set_destructor(ctx, inotify_ctx_destructor); - *pfilter = filter; - return ctx; -} - -static void inotify_dispatch(struct inotify_event *e) +/* + dispatch one inotify event + + the cookies are used to correctly handle renames +*/ +static void inotify_dispatch(struct inotify_private *in, + struct inotify_event *e, + uint32_t prev_cookie, + struct inotify_event *e2) { - struct inotify_ctx *ctx; + struct watch_context *w, *next; + struct notify_event ne; + + /* ignore extraneous events, such as unmount and IN_IGNORED events */ + if ((e->mask & (IN_ATTRIB|IN_MODIFY|IN_CREATE|IN_DELETE| + IN_MOVED_FROM|IN_MOVED_TO)) == 0) { + return; + } - for (ctx = inotify_list; ctx; ctx = ctx->next) { - if (ctx->wd == e->wd) { - break; + /* map the inotify mask to a action. This gets complicated for + renames */ + if (e->mask & IN_CREATE) { + ne.action = NOTIFY_ACTION_ADDED; + } else if (e->mask & IN_DELETE) { + ne.action = NOTIFY_ACTION_REMOVED; + } else if (e->mask & IN_MOVED_FROM) { + if (e2 != NULL && e2->cookie == e->cookie) { + ne.action = NOTIFY_ACTION_OLD_NAME; + } else { + ne.action = NOTIFY_ACTION_REMOVED; + } + } else if (e->mask & IN_MOVED_TO) { + if (e->cookie == prev_cookie) { + ne.action = NOTIFY_ACTION_NEW_NAME; + } else { + ne.action = NOTIFY_ACTION_ADDED; } + } else { + ne.action = NOTIFY_ACTION_MODIFIED; } + ne.path = e->name; - if (ctx == NULL) { - /* not found */ - return; + /* find any watches that have this watch descriptor */ + for (w=in->watches;w;w=next) { + next = w->next; + if (w->wd == e->wd && filter_match(w, e)) { + w->callback(in->ctx, w->private_data, &ne); + } } - if (e->mask & IN_CREATE) { - notify_fsp(ctx->fsp, NOTIFY_ACTION_ADDED, e->name); + /* SMB expects a file rename to generate three events, two for + the rename and the other for a modify of the + destination. Strange! */ + if (ne.action != NOTIFY_ACTION_NEW_NAME || + (e->mask & IN_ISDIR) != 0) { + return; } - if (e->mask & IN_DELETE) { - notify_fsp(ctx->fsp, NOTIFY_ACTION_REMOVED, e->name); + ne.action = NOTIFY_ACTION_MODIFIED; + e->mask = IN_ATTRIB; + + for (w=in->watches;w;w=next) { + next = w->next; + if (w->wd == e->wd && filter_match(w, e) && + !(w->filter & FILE_NOTIFY_CHANGE_CREATION)) { + w->callback(in->ctx, w->private_data, &ne); + } } } -static void inotify_callback(struct event_context *event_ctx, - struct fd_event *event, - uint16 flags, - void *private_data) +/* + called when the kernel has some events for us +*/ +static void inotify_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *private_data) { - char *buf, *p; - int bufsize; + struct inotify_private *in = talloc_get_type(private_data, + struct inotify_private); + int bufsize = 0; + struct inotify_event *e0, *e; + uint32_t prev_cookie=0; /* we must use FIONREAD as we cannot predict the length of the filenames, and thus can't know how much to allocate otherwise */ - if ((ioctl(inotify_watch_fd, FIONREAD, &bufsize) != 0) - || (bufsize == 0)) { + if (ioctl(in->fd, FIONREAD, &bufsize) != 0 || + bufsize == 0) { DEBUG(0,("No data on inotify fd?!\n")); return; } - if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) { - DEBUG(0, ("malloc failed\n")); - return; - } + e0 = e = talloc_size(in, bufsize); + if (e == NULL) return; - if (read(inotify_watch_fd, buf, bufsize) != bufsize) { + if (read(in->fd, e0, bufsize) != bufsize) { DEBUG(0,("Failed to read all inotify data\n")); - SAFE_FREE(buf); + talloc_free(e0); return; } - p = buf; + /* we can get more than one event in the buffer */ + while (bufsize >= sizeof(*e)) { + struct inotify_event *e2 = NULL; + bufsize -= e->len + sizeof(*e); + if (bufsize >= sizeof(*e)) { + e2 = (struct inotify_event *)(e->len + sizeof(*e) + (char *)e); + } + inotify_dispatch(in, e, prev_cookie, e2); + prev_cookie = e->cookie; + e = e2; + } - while (bufsize > sizeof(struct inotify_event)) { - struct inotify_event *iev = (struct inotify_event *)p; - size_t len = sizeof(struct inotify_event) + iev->len; + talloc_free(e0); +} - if ((len > bufsize) - || ((iev->len != 0) && (iev->name[iev->len-1] != '\0'))) { - smb_panic("invalid inotify reply\n"); - } +/* + setup the inotify handle - called the first time a watch is added on + this context +*/ +static NTSTATUS inotify_setup(struct sys_notify_context *ctx) +{ + struct inotify_private *in; - inotify_dispatch(iev); + if (!lp_parm_bool(-1, "notify", "inotify", True)) { + return NT_STATUS_INVALID_SYSTEM_SERVICE; + } - p += len; - bufsize -= len; + in = talloc(ctx, struct inotify_private); + NT_STATUS_HAVE_NO_MEMORY(in); + in->fd = inotify_init(); + if (in->fd == -1) { + DEBUG(0,("Failed to init inotify - %s\n", strerror(errno))); + talloc_free(in); + return map_nt_error_from_unix(errno); } + in->ctx = ctx; + in->watches = NULL; + + ctx->private_data = in; + talloc_set_destructor(in, inotify_destructor); - SAFE_FREE(buf); - return; + /* add a event waiting for the inotify fd to be readable */ + event_add_fd(ctx->ev, in, in->fd, EVENT_FD_READ, inotify_handler, in); + + return NT_STATUS_OK; } -static struct cnotify_fns inotify_fns = -{ - inotify_add, + +/* + map from a change notify mask to a inotify mask. Remove any bits + which we can handle +*/ +static const struct { + uint32_t notify_mask; + uint32_t inotify_mask; +} inotify_mapping[] = { + {FILE_NOTIFY_CHANGE_FILE_NAME, IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO}, + {FILE_NOTIFY_CHANGE_DIR_NAME, IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO}, + {FILE_NOTIFY_CHANGE_ATTRIBUTES, IN_ATTRIB|IN_MOVED_TO|IN_MOVED_FROM|IN_MODIFY}, + {FILE_NOTIFY_CHANGE_LAST_WRITE, IN_ATTRIB}, + {FILE_NOTIFY_CHANGE_LAST_ACCESS, IN_ATTRIB}, + {FILE_NOTIFY_CHANGE_EA, IN_ATTRIB}, + {FILE_NOTIFY_CHANGE_SECURITY, IN_ATTRIB} }; -struct cnotify_fns *inotify_notify_init(struct event_context *event_ctx) +static uint32_t inotify_map(struct notify_entry *e) +{ + int i; + uint32_t out=0; + for (i=0;ifilter) { + out |= inotify_mapping[i].inotify_mask; + e->filter &= ~inotify_mapping[i].notify_mask; + } + } + return out; +} + +/* + destroy a watch +*/ +static int watch_destructor(struct watch_context *w) { - inotify_watch_fd = inotify_init(); + struct inotify_private *in = w->in; + int wd = w->wd; + DLIST_REMOVE(w->in->watches, w); + + /* only rm the watch if its the last one with this wd */ + for (w=in->watches;w;w=w->next) { + if (w->wd == wd) break; + } + if (w == NULL) { + inotify_rm_watch(in->fd, wd); + } + return 0; +} + + +/* + add a watch. The watch is removed when the caller calls + talloc_free() on *handle +*/ +static NTSTATUS inotify_watch(struct sys_notify_context *ctx, + struct notify_entry *e, + sys_notify_callback_t callback, + void *private_data, + void *handle_p) +{ + struct inotify_private *in; + int wd; + uint32_t mask; + struct watch_context *w; + uint32_t filter = e->filter; + void **handle = (void **)handle_p; + + /* maybe setup the inotify fd */ + if (ctx->private_data == NULL) { + NTSTATUS status; + status = inotify_setup(ctx); + NT_STATUS_NOT_OK_RETURN(status); + } - DEBUG(10, ("inotify_notify_init called\n")); + in = talloc_get_type(ctx->private_data, struct inotify_private); - if (inotify_watch_fd == -1) { - DEBUG(0, ("inotify_init failed: %s\n", strerror(errno))); - return NULL; + mask = inotify_map(e); + if (mask == 0) { + /* this filter can't be handled by inotify */ + return NT_STATUS_INVALID_PARAMETER; } - if (event_add_fd(event_ctx, NULL, inotify_watch_fd, - EVENT_FD_READ, inotify_callback, - NULL) == NULL) { - DEBUG(0, ("event_add_fd failed\n")); - close(inotify_watch_fd); - inotify_watch_fd = -1; - return NULL; + /* using IN_MASK_ADD allows us to cope with inotify() returning the same + watch descriptor for muliple watches on the same path */ + mask |= (IN_MASK_ADD | IN_ONLYDIR); + + /* get a new watch descriptor for this path */ + wd = inotify_add_watch(in->fd, e->path, mask); + if (wd == -1) { + e->filter = filter; + return map_nt_error_from_unix(errno); } - return &inotify_fns; + w = talloc(in, struct watch_context); + if (w == NULL) { + inotify_rm_watch(in->fd, wd); + e->filter = filter; + return NT_STATUS_NO_MEMORY; + } + + w->in = in; + w->wd = wd; + w->callback = callback; + w->private_data = private_data; + w->mask = mask; + w->filter = filter; + w->path = talloc_strdup(w, e->path); + if (w->path == NULL) { + inotify_rm_watch(in->fd, wd); + e->filter = filter; + return NT_STATUS_NO_MEMORY; + } + + (*handle) = w; + + DLIST_ADD(in->watches, w); + + /* the caller frees the handle to stop watching */ + talloc_set_destructor(w, watch_destructor); + + return NT_STATUS_OK; } -#endif + +static struct sys_notify_backend inotify = { + .name = "inotify", + .notify_watch = inotify_watch +}; + +/* + initialialise the inotify module + */ +NTSTATUS sys_notify_inotify_init(void) +{ + /* register ourselves as a system inotify module */ + return sys_notify_register(&inotify); +} diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c new file mode 100644 index 0000000000..91fa8a1d78 --- /dev/null +++ b/source3/smbd/notify_internal.c @@ -0,0 +1,661 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2006 + + 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. +*/ + +/* + this is the change notify database. It implements mechanisms for + storing current change notify waiters in a tdb, and checking if a + given event matches any of the stored notify waiiters. +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "lib/tdb/include/tdb.h" +#include "lib/util/util_tdb.h" +#include "messaging/messaging.h" +#include "db_wrap.h" +#include "lib/messaging/irpc.h" +#include "librpc/gen_ndr/ndr_notify.h" +#include "lib/util/dlinklist.h" +#include "ntvfs/common/ntvfs_common.h" +#include "ntvfs/sysdep/sys_notify.h" +#include "cluster/cluster.h" + +struct notify_context { + struct tdb_wrap *w; + struct server_id server; + struct messaging_context *messaging_ctx; + struct notify_list *list; + struct notify_array *array; + int seqnum; + struct sys_notify_context *sys_notify_ctx; +}; + + +struct notify_list { + struct notify_list *next, *prev; + void *private_data; + void (*callback)(void *, const struct notify_event *); + void *sys_notify_handle; + int depth; +}; + +#define NOTIFY_KEY "notify array" + +#define NOTIFY_ENABLE "notify:enable" +#define NOTIFY_ENABLE_DEFAULT True + +static NTSTATUS notify_remove_all(struct notify_context *notify); +static void notify_handler(struct messaging_context *msg_ctx, void *private_data, + uint32_t msg_type, struct server_id server_id, DATA_BLOB *data); + +/* + destroy the notify context +*/ +static int notify_destructor(struct notify_context *notify) +{ + messaging_deregister(notify->messaging_ctx, MSG_PVFS_NOTIFY, notify); + notify_remove_all(notify); + return 0; +} + +/* + Open up the notify.tdb database. You should close it down using + talloc_free(). We need the messaging_ctx to allow for notifications + via internal messages +*/ +struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, + struct messaging_context *messaging_ctx, + struct event_context *ev, + struct share_config *scfg) +{ + struct notify_context *notify; + + if (share_bool_option(scfg, NOTIFY_ENABLE, NOTIFY_ENABLE_DEFAULT) != True) { + return NULL; + } + + notify = talloc(mem_ctx, struct notify_context); + if (notify == NULL) { + return NULL; + } + + notify->w = cluster_tdb_tmp_open(notify, "notify.tdb", TDB_SEQNUM); + if (notify->w == NULL) { + talloc_free(notify); + return NULL; + } + + notify->server = server; + notify->messaging_ctx = messaging_ctx; + notify->list = NULL; + notify->array = NULL; + notify->seqnum = tdb_get_seqnum(notify->w->tdb); + + talloc_set_destructor(notify, notify_destructor); + + /* register with the messaging subsystem for the notify + message type */ + messaging_register(notify->messaging_ctx, notify, + MSG_PVFS_NOTIFY, notify_handler); + + notify->sys_notify_ctx = sys_notify_context_create(scfg, notify, ev); + + return notify; +} + + +/* + lock the notify db +*/ +static NTSTATUS notify_lock(struct notify_context *notify) +{ + if (tdb_lock_bystring(notify->w->tdb, NOTIFY_KEY) != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + return NT_STATUS_OK; +} + +/* + unlock the notify db +*/ +static void notify_unlock(struct notify_context *notify) +{ + tdb_unlock_bystring(notify->w->tdb, NOTIFY_KEY); +} + +/* + load the notify array +*/ +static NTSTATUS notify_load(struct notify_context *notify) +{ + TDB_DATA dbuf; + DATA_BLOB blob; + NTSTATUS status; + int seqnum; + + seqnum = tdb_get_seqnum(notify->w->tdb); + + if (seqnum == notify->seqnum && notify->array != NULL) { + return NT_STATUS_OK; + } + + notify->seqnum = seqnum; + + talloc_free(notify->array); + notify->array = talloc_zero(notify, struct notify_array); + NT_STATUS_HAVE_NO_MEMORY(notify->array); + + dbuf = tdb_fetch_bystring(notify->w->tdb, NOTIFY_KEY); + if (dbuf.dptr == NULL) { + return NT_STATUS_OK; + } + + blob.data = dbuf.dptr; + blob.length = dbuf.dsize; + + status = ndr_pull_struct_blob(&blob, notify->array, notify->array, + (ndr_pull_flags_fn_t)ndr_pull_notify_array); + free(dbuf.dptr); + + return status; +} + +/* + compare notify entries for sorting +*/ +static int notify_compare(const void *p1, const void *p2) +{ + const struct notify_entry *e1 = p1, *e2 = p2; + return strcmp(e1->path, e2->path); +} + +/* + save the notify array +*/ +static NTSTATUS notify_save(struct notify_context *notify) +{ + TDB_DATA dbuf; + DATA_BLOB blob; + NTSTATUS status; + int ret; + TALLOC_CTX *tmp_ctx; + + /* if possible, remove some depth arrays */ + while (notify->array->num_depths > 0 && + notify->array->depth[notify->array->num_depths-1].num_entries == 0) { + notify->array->num_depths--; + } + + /* we might just be able to delete the record */ + if (notify->array->num_depths == 0) { + ret = tdb_delete_bystring(notify->w->tdb, NOTIFY_KEY); + if (ret != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + return NT_STATUS_OK; + } + + tmp_ctx = talloc_new(notify); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + status = ndr_push_struct_blob(&blob, tmp_ctx, notify->array, + (ndr_push_flags_fn_t)ndr_push_notify_array); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + + dbuf.dptr = blob.data; + dbuf.dsize = blob.length; + + ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE); + talloc_free(tmp_ctx); + if (ret != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + return NT_STATUS_OK; +} + + +/* + handle incoming notify messages +*/ +static void notify_handler(struct messaging_context *msg_ctx, void *private_data, + uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) +{ + struct notify_context *notify = talloc_get_type(private_data, struct notify_context); + NTSTATUS status; + struct notify_event ev; + TALLOC_CTX *tmp_ctx = talloc_new(notify); + struct notify_list *listel; + + if (tmp_ctx == NULL) { + return; + } + + status = ndr_pull_struct_blob(data, tmp_ctx, &ev, + (ndr_pull_flags_fn_t)ndr_pull_notify_event); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return; + } + + for (listel=notify->list;listel;listel=listel->next) { + if (listel->private_data == ev.private_data) { + listel->callback(listel->private_data, &ev); + break; + } + } + + talloc_free(tmp_ctx); +} + +/* + callback from sys_notify telling us about changes from the OS +*/ +static void sys_notify_callback(struct sys_notify_context *ctx, + void *ptr, struct notify_event *ev) +{ + struct notify_list *listel = talloc_get_type(ptr, struct notify_list); + ev->private_data = listel; + listel->callback(listel->private_data, ev); +} + +/* + add an entry to the notify array +*/ +static NTSTATUS notify_add_array(struct notify_context *notify, struct notify_entry *e, + void *private_data, int depth) +{ + int i; + struct notify_depth *d; + struct notify_entry *ee; + + /* possibly expand the depths array */ + if (depth >= notify->array->num_depths) { + d = talloc_realloc(notify->array, notify->array->depth, + struct notify_depth, depth+1); + NT_STATUS_HAVE_NO_MEMORY(d); + for (i=notify->array->num_depths;i<=depth;i++) { + ZERO_STRUCT(d[i]); + } + notify->array->depth = d; + notify->array->num_depths = depth+1; + } + d = ¬ify->array->depth[depth]; + + /* expand the entries array */ + ee = talloc_realloc(notify->array->depth, d->entries, struct notify_entry, + d->num_entries+1); + NT_STATUS_HAVE_NO_MEMORY(ee); + d->entries = ee; + + d->entries[d->num_entries] = *e; + d->entries[d->num_entries].private_data = private_data; + d->entries[d->num_entries].server = notify->server; + d->entries[d->num_entries].path_len = strlen(e->path); + d->num_entries++; + + d->max_mask |= e->filter; + d->max_mask_subdir |= e->subdir_filter; + + if (d->num_entries > 1) { + qsort(d->entries, d->num_entries, sizeof(d->entries[0]), notify_compare); + } + + /* recalculate the maximum masks */ + d->max_mask = 0; + d->max_mask_subdir = 0; + + for (i=0;inum_entries;i++) { + d->max_mask |= d->entries[i].filter; + d->max_mask_subdir |= d->entries[i].subdir_filter; + } + + return notify_save(notify); +} + +/* + add a notify watch. This is called when a notify is first setup on a open + directory handle. +*/ +NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0, + void (*callback)(void *, const struct notify_event *), + void *private_data) +{ + struct notify_entry e = *e0; + NTSTATUS status; + char *tmp_path = NULL; + struct notify_list *listel; + size_t len; + int depth; + + /* see if change notify is enabled at all */ + if (notify == NULL) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + status = notify_lock(notify); + NT_STATUS_NOT_OK_RETURN(status); + + status = notify_load(notify); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + /* cope with /. on the end of the path */ + len = strlen(e.path); + if (len > 1 && e.path[len-1] == '.' && e.path[len-2] == '/') { + tmp_path = talloc_strndup(notify, e.path, len-2); + if (tmp_path == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + e.path = tmp_path; + } + + depth = count_chars(e.path, '/'); + + listel = talloc_zero(notify, struct notify_list); + if (listel == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + listel->private_data = private_data; + listel->callback = callback; + listel->depth = depth; + DLIST_ADD(notify->list, listel); + + /* ignore failures from sys_notify */ + if (notify->sys_notify_ctx != NULL) { + /* + this call will modify e.filter and e.subdir_filter + to remove bits handled by the backend + */ + status = sys_notify_watch(notify->sys_notify_ctx, &e, + sys_notify_callback, listel, + &listel->sys_notify_handle); + if (NT_STATUS_IS_OK(status)) { + talloc_steal(listel, listel->sys_notify_handle); + } + } + + /* if the system notify handler couldn't handle some of the + filter bits, or couldn't handle a request for recursion + then we need to install it in the array used for the + intra-samba notify handling */ + if (e.filter != 0 || e.subdir_filter != 0) { + status = notify_add_array(notify, &e, private_data, depth); + } + +done: + notify_unlock(notify); + talloc_free(tmp_path); + + return status; +} + +/* + remove a notify watch. Called when the directory handle is closed +*/ +NTSTATUS notify_remove(struct notify_context *notify, void *private_data) +{ + NTSTATUS status; + struct notify_list *listel; + int i, depth; + struct notify_depth *d; + + /* see if change notify is enabled at all */ + if (notify == NULL) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + for (listel=notify->list;listel;listel=listel->next) { + if (listel->private_data == private_data) { + DLIST_REMOVE(notify->list, listel); + break; + } + } + if (listel == NULL) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + depth = listel->depth; + + talloc_free(listel); + + status = notify_lock(notify); + NT_STATUS_NOT_OK_RETURN(status); + + status = notify_load(notify); + if (!NT_STATUS_IS_OK(status)) { + notify_unlock(notify); + return status; + } + + if (depth >= notify->array->num_depths) { + notify_unlock(notify); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* we only have to search at the depth of this element */ + d = ¬ify->array->depth[depth]; + + for (i=0;inum_entries;i++) { + if (private_data == d->entries[i].private_data && + cluster_id_equal(¬ify->server, &d->entries[i].server)) { + break; + } + } + if (i == d->num_entries) { + notify_unlock(notify); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (i < d->num_entries-1) { + memmove(&d->entries[i], &d->entries[i+1], + sizeof(d->entries[i])*(d->num_entries-(i+1))); + } + d->num_entries--; + + status = notify_save(notify); + + notify_unlock(notify); + + return status; +} + +/* + remove all notify watches for this messaging server +*/ +static NTSTATUS notify_remove_all(struct notify_context *notify) +{ + NTSTATUS status; + int i, depth, del_count=0; + + if (notify->list == NULL) { + return NT_STATUS_OK; + } + + status = notify_lock(notify); + NT_STATUS_NOT_OK_RETURN(status); + + status = notify_load(notify); + if (!NT_STATUS_IS_OK(status)) { + notify_unlock(notify); + return status; + } + + /* we have to search for all entries across all depths, looking for matches + for our server id */ + for (depth=0;deptharray->num_depths;depth++) { + struct notify_depth *d = ¬ify->array->depth[depth]; + for (i=0;inum_entries;i++) { + if (cluster_id_equal(¬ify->server, &d->entries[i].server)) { + if (i < d->num_entries-1) { + memmove(&d->entries[i], &d->entries[i+1], + sizeof(d->entries[i])*(d->num_entries-(i+1))); + } + i--; + d->num_entries--; + del_count++; + } + } + } + + if (del_count > 0) { + status = notify_save(notify); + } + + notify_unlock(notify); + + return status; +} + + +/* + send a notify message to another messaging server +*/ +static void notify_send(struct notify_context *notify, struct notify_entry *e, + const char *path, uint32_t action) +{ + struct notify_event ev; + DATA_BLOB data; + NTSTATUS status; + TALLOC_CTX *tmp_ctx; + + ev.action = action; + ev.path = path; + ev.private_data = e->private_data; + + tmp_ctx = talloc_new(notify); + + status = ndr_push_struct_blob(&data, tmp_ctx, &ev, + (ndr_push_flags_fn_t)ndr_push_notify_event); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return; + } + + status = messaging_send(notify->messaging_ctx, e->server, + MSG_PVFS_NOTIFY, &data); + talloc_free(tmp_ctx); +} + + +/* + trigger a notify message for anyone waiting on a matching event + + This function is called a lot, and needs to be very fast. The unusual data structure + and traversal is designed to be fast in the average case, even for large numbers of + notifies +*/ +void notify_trigger(struct notify_context *notify, + uint32_t action, uint32_t filter, const char *path) +{ + NTSTATUS status; + int depth; + const char *p, *next_p; + + /* see if change notify is enabled at all */ + if (notify == NULL) { + return; + } + + status = notify_load(notify); + if (!NT_STATUS_IS_OK(status)) { + return; + } + + /* loop along the given path, working with each directory depth separately */ + for (depth=0,p=path; + p && depth < notify->array->num_depths; + p=next_p,depth++) { + int p_len = p - path; + int min_i, max_i, i; + struct notify_depth *d = ¬ify->array->depth[depth]; + next_p = strchr(p+1, '/'); + + /* see if there are any entries at this depth */ + if (d->num_entries == 0) continue; + + /* try to skip based on the maximum mask. If next_p is + NULL then we know it will be a 'this directory' + match, otherwise it must be a subdir match */ + if (next_p != NULL) { + if (0 == (filter & d->max_mask_subdir)) { + continue; + } + } else { + if (0 == (filter & d->max_mask)) { + continue; + } + } + + /* we know there is an entry here worth looking + for. Use a bisection search to find the first entry + with a matching path */ + min_i = 0; + max_i = d->num_entries-1; + + while (min_i < max_i) { + struct notify_entry *e; + int cmp; + i = (min_i+max_i)/2; + e = &d->entries[i]; + cmp = strncmp(path, e->path, p_len); + if (cmp == 0) { + if (p_len == e->path_len) { + max_i = i; + } else { + max_i = i-1; + } + } else if (cmp < 0) { + max_i = i-1; + } else { + min_i = i+1; + } + } + + if (min_i != max_i) { + /* none match */ + continue; + } + + /* we now know that the entries start at min_i */ + for (i=min_i;inum_entries;i++) { + struct notify_entry *e = &d->entries[i]; + if (p_len != e->path_len || + strncmp(path, e->path, p_len) != 0) break; + if (next_p != NULL) { + if (0 == (filter & e->subdir_filter)) { + continue; + } + } else { + if (0 == (filter & e->filter)) { + continue; + } + } + notify_send(notify, e, path + e->path_len + 1, action); + } + } +} -- cgit From b0bf3ddb386f3c04b44c6e48867c222ae3a15c2e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 12:42:24 +0000 Subject: r21079: Minimizing diff: Adopt the Samba4 style ChangeNotify flags. Volker (This used to be commit a3c1069b0c3da914e2ac7337fd9e924b1c811d39) --- source3/smbd/notify_fam.c | 8 ++++---- source3/smbd/notify_hash.c | 3 +-- source3/smbd/notify_kernel.c | 2 +- source3/smbd/reply.c | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index 306316e49f..aba1f5dcb3 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -191,8 +191,8 @@ static void *fam_notify_add(TALLOC_CTX *mem_ctx, struct fam_notify_ctx *ctx; pstring fullpath; - if ((*filter & FILE_NOTIFY_CHANGE_FILE) == 0) { - DEBUG(10, ("filter = %u, no FILE_NOTIFY_CHANGE_FILE\n", + if ((*filter & FILE_NOTIFY_CHANGE_FILE_NAME) == 0) { + DEBUG(10, ("filter = %u, no FILE_NOTIFY_CHANGE_FILE_NAME\n", *filter)); return NULL; } @@ -224,7 +224,7 @@ static void *fam_notify_add(TALLOC_CTX *mem_ctx, * FAMCreated and FAMDeleted events */ - ctx->filter = FILE_NOTIFY_CHANGE_FILE; + ctx->filter = FILE_NOTIFY_CHANGE_FILE_NAME; if (!(ctx->path = talloc_strdup(ctx, fullpath))) { DEBUG(0, ("talloc_strdup failed\n")); @@ -236,7 +236,7 @@ static void *fam_notify_add(TALLOC_CTX *mem_ctx, * Leave the rest to smbd itself */ - *filter &= ~FILE_NOTIFY_CHANGE_FILE; + *filter &= ~FILE_NOTIFY_CHANGE_FILE_NAME; DLIST_ADD(fam_notify_list, ctx); talloc_set_destructor(ctx, fam_notify_ctx_destructor); diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 773a7565c5..5f563419bd 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -147,8 +147,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, */ if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME - |FILE_NOTIFY_CHANGE_FILE_NAME - |FILE_NOTIFY_CHANGE_FILE)) { + |FILE_NOTIFY_CHANGE_FILE_NAME)) { int i; unsigned char tmp_hash[16]; mdfour(tmp_hash, (const unsigned char *)fname, diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c index 0b5784f3d0..f90414dc79 100644 --- a/source3/smbd/notify_kernel.c +++ b/source3/smbd/notify_kernel.c @@ -152,7 +152,7 @@ static int kernel_register_notify(connection_struct *conn, char *path, kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion * changes * everything! */ - if (flags & FILE_NOTIFY_CHANGE_FILE) kernel_flags |= DN_MODIFY; + if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_MODIFY; if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME |DN_DELETE; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a1edce935d..b0bddc03f6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1867,7 +1867,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; notify_fname(conn, directory, - FILE_NOTIFY_CHANGE_FILE, + FILE_NOTIFY_CHANGE_FILE_NAME, NOTIFY_ACTION_REMOVED); } } else { @@ -1930,7 +1930,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, DEBUG(3,("unlink_internals: succesful unlink " "[%s]\n",fname)); notify_action(conn, directory, dname, - FILE_NOTIFY_CHANGE_FILE, + FILE_NOTIFY_CHANGE_FILE_NAME, NOTIFY_ACTION_REMOVED); } -- cgit From 434bf5fadd1bc7e7c4af0eb402457365860ec760 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 12:55:39 +0000 Subject: r21080: Reformatting (This used to be commit 705f866a78ec3f1169543bf82fb48ea6580160a9) --- source3/smbd/reply.c | 105 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b0bddc03f6..37c8a46ed3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4116,7 +4116,9 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, pstring name, pstring newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild) +NTSTATUS rename_internals(connection_struct *conn, pstring name, + pstring newname, uint32 attrs, + BOOL replace_if_exists, BOOL has_wild) { pstring directory; pstring mask; @@ -4133,12 +4135,14 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, pstring newname ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - status = unix_convert(conn, name, has_wild, last_component_src, &sbuf1); + status = unix_convert(conn, name, has_wild, last_component_src, + &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; } - status = unix_convert(conn, newname, True, last_component_dest, &sbuf2); + status = unix_convert(conn, newname, True, last_component_dest, + &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4194,10 +4198,13 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, pstring newname pstrcpy(newname, tmpstr); } - DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \ -directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", - conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, - newname, last_component_dest, is_short_name)); + DEBUG(3, ("rename_internals: case_sensitive = %d, " + "case_preserve = %d, short case preserve = %d, " + "directory = %s, newname = %s, " + "last_component_dest = %s, is_8_3 = %d\n", + conn->case_sensitive, conn->case_preserve, + conn->short_case_preserve, directory, + newname, last_component_dest, is_short_name)); /* * Check for special case with case preserving and not @@ -4240,13 +4247,16 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", */ if (!vfs_object_exist(conn, directory, &sbuf1)) { - DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n", + DEBUG(3, ("rename_internals: source doesn't exist " + "doing rename %s -> %s\n", directory,newname)); - if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) { + if (errno == ENOTDIR || errno == EISDIR + || errno == ENOENT) { /* - * Must return different errors depending on whether the parent - * directory existed or not. + * Must return different errors depending on + * whether the parent directory existed or + * not. */ p = strrchr_m(directory, '/'); @@ -4258,8 +4268,9 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_PATH_NOT_FOUND; } status = map_nt_error_from_unix(errno); - DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(status), directory,newname)); + DEBUG(3, ("rename_internals: Error %s rename %s -> " + "%s\n", nt_errstr(status), directory, + newname)); return status; } @@ -4267,8 +4278,9 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", status = can_rename(conn,directory,attrs,&sbuf1); if (!NT_STATUS_IS_OK(status)) { - DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(status), directory,newname)); + DEBUG(3,("rename_internals: Error %s rename %s -> " + "%s\n", nt_errstr(status), directory, + newname)); return status; } @@ -4278,14 +4290,17 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", */ if (strcsequal(directory, newname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); - DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory)); + rename_open_files(conn, NULL, sbuf1.st_dev, + sbuf1.st_ino, newname); + DEBUG(3, ("rename_internals: identical names in " + "rename %s - returning success\n", + directory)); return NT_STATUS_OK; } if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) { - DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n", - directory,newname)); + DEBUG(3,("rename_internals: dest exists doing " + "rename %s -> %s\n", directory, newname)); return NT_STATUS_OBJECT_NAME_COLLISION; } @@ -4293,12 +4308,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); + lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, + NULL, NULL); if(SMB_VFS_RENAME(conn,directory, newname) == 0) { - DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", - directory,newname)); - rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); + DEBUG(3,("rename_internals: succeeded doing rename " + "on %s -> %s\n", directory, newname)); + rename_open_files(conn, lck, sbuf1.st_dev, + sbuf1.st_ino, newname); TALLOC_FREE(lck); return NT_STATUS_OK; } @@ -4337,7 +4354,10 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } status = NT_STATUS_NO_SUCH_FILE; -/* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ + /* + * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + * - gentest fix. JRA + */ while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; @@ -4347,7 +4367,8 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", /* Quick check for "." and ".." */ if (fname[0] == '.') { - if (!fname[1] || (fname[1] == '.' && !fname[2])) { + if (!fname[1] + || (fname[1] == '.' && !fname[2])) { if (attrs & aDIR) { sysdir_entry = True; } else { @@ -4356,7 +4377,8 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } } - if (!is_visible_file(conn, directory, dname, &sbuf1, False)) { + if (!is_visible_file(conn, directory, dname, &sbuf1, + False)) { continue; } @@ -4370,34 +4392,40 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } status = NT_STATUS_ACCESS_DENIED; - slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); + slprintf(fname, sizeof(fname)-1, "%s/%s", directory, + dname); if (!vfs_object_exist(conn, fname, &sbuf1)) { status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status))); + DEBUG(6, ("rename %s failed. Error %s\n", + fname, nt_errstr(status))); continue; } status = can_rename(conn,fname,attrs,&sbuf1); if (!NT_STATUS_IS_OK(status)) { - DEBUG(6,("rename %s refused\n", fname)); + DEBUG(6, ("rename %s refused\n", fname)); continue; } pstrcpy(destname,newname); if (!resolve_wildcards(fname,destname)) { - DEBUG(6,("resolve_wildcards %s %s failed\n", - fname, destname)); + DEBUG(6, ("resolve_wildcards %s %s failed\n", + fname, destname)); continue; } if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); - DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); + rename_open_files(conn, NULL, sbuf1.st_dev, + sbuf1.st_ino, newname); + DEBUG(3,("rename_internals: identical names " + "in wildcard rename %s - success\n", + fname)); count++; status = NT_STATUS_OK; continue; } - if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) { + if (!replace_if_exists + && vfs_file_exist(conn,destname, NULL)) { DEBUG(6,("file_exist %s\n", destname)); status = NT_STATUS_OBJECT_NAME_COLLISION; continue; @@ -4407,15 +4435,18 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); + lck = get_share_mode_lock(NULL, sbuf1.st_dev, + sbuf1.st_ino, NULL, NULL); if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, lck, sbuf1.st_dev, + sbuf1.st_ino, newname); count++; status = NT_STATUS_OK; } TALLOC_FREE(lck); - DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); + DEBUG(3,("rename_internals: doing rename on %s -> " + "%s\n",fname,destname)); } CloseDir(dir_hnd); } -- cgit From 37a3339a1891f0189ff62891e6be85ace23efc33 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 13:09:07 +0000 Subject: r21082: Make canonicalize_path static to service.c -- we do have conn->connectpath (This used to be commit 06f58096e3785d0e2e0b9f2053d4975e44568e15) --- source3/smbd/notify_fam.c | 21 +++------------------ source3/smbd/notify_hash.c | 19 +++---------------- source3/smbd/service.c | 25 +++++++++++++++++++++++++ source3/smbd/vfs.c | 25 ------------------------- 4 files changed, 31 insertions(+), 59 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index aba1f5dcb3..08dc4eabb0 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -189,7 +189,6 @@ static void *fam_notify_add(TALLOC_CTX *mem_ctx, files_struct *fsp, uint32 *filter) { struct fam_notify_ctx *ctx; - pstring fullpath; if ((*filter & FILE_NOTIFY_CHANGE_FILE_NAME) == 0) { DEBUG(10, ("filter = %u, no FILE_NOTIFY_CHANGE_FILE_NAME\n", @@ -197,21 +196,6 @@ static void *fam_notify_add(TALLOC_CTX *mem_ctx, return NULL; } - /* FAM needs an absolute pathname. */ - - pstrcpy(fullpath, fsp->fsp_name); - if (!canonicalize_path(fsp->conn, fullpath)) { - DEBUG(0, ("failed to canonicalize path '%s'\n", fullpath)); - return NULL; - } - - if (*fullpath != '/') { - DEBUG(0, ("canonicalized path '%s' into `%s`\n", fsp->fsp_name, - fullpath)); - DEBUGADD(0, ("but expected an absolute path\n")); - return NULL; - } - if (!(ctx = TALLOC_P(mem_ctx, struct fam_notify_ctx))) { return NULL; } @@ -226,8 +210,9 @@ static void *fam_notify_add(TALLOC_CTX *mem_ctx, ctx->filter = FILE_NOTIFY_CHANGE_FILE_NAME; - if (!(ctx->path = talloc_strdup(ctx, fullpath))) { - DEBUG(0, ("talloc_strdup failed\n")); + if (!(ctx->path = talloc_asprintf(ctx, "%s/%s", fsp->conn->connectpath, + fsp->fsp_name))) { + DEBUG(0, ("talloc_asprintf failed\n")); TALLOC_FREE(ctx); return NULL; } diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 5f563419bd..2cd8fbc6bc 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -222,7 +222,6 @@ static void *hash_notify_add(TALLOC_CTX *mem_ctx, { struct hash_notify_ctx *ctx; int timeout = lp_change_notify_timeout(SNUM(fsp->conn)); - pstring fullpath; if (timeout <= 0) { /* It change notify timeout has been disabled, never scan the @@ -230,26 +229,14 @@ static void *hash_notify_add(TALLOC_CTX *mem_ctx, return NULL; } - pstrcpy(fullpath, fsp->fsp_name); - if (!canonicalize_path(fsp->conn, fullpath)) { - DEBUG(0, ("failed to canonicalize path '%s'\n", fullpath)); - return NULL; - } - - if (*fullpath != '/') { - DEBUG(0, ("canonicalized path '%s' into `%s`\n", fsp->fsp_name, - fullpath)); - DEBUGADD(0, ("but expected an absolute path\n")); - return NULL; - } - if (!(ctx = TALLOC_P(mem_ctx, struct hash_notify_ctx))) { DEBUG(0, ("talloc failed\n")); return NULL; } - if (!(ctx->path = talloc_strdup(ctx, fullpath))) { - DEBUG(0, ("talloc_strdup failed\n")); + if (!(ctx->path = talloc_asprintf(ctx, "%s/%s", fsp->conn->connectpath, + fsp->fsp_name))) { + DEBUG(0, ("talloc_asprintf failed\n")); TALLOC_FREE(ctx); return NULL; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 9efe63a82c..ff6f9d1c1a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -22,6 +22,31 @@ extern userdom_struct current_user_info; +BOOL canonicalize_path(connection_struct *conn, pstring path) +{ +#ifdef REALPATH_TAKES_NULL + char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL); + if (!resolved_name) { + return False; + } + pstrcpy(path, resolved_name); + SAFE_FREE(resolved_name); + return True; +#else +#ifdef PATH_MAX + char resolved_name_buf[PATH_MAX+1]; +#else + pstring resolved_name_buf; +#endif + char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf); + if (!resolved_name) { + return False; + } + pstrcpy(path, resolved_name); + return True; +#endif /* REALPATH_TAKES_NULL */ +} + /**************************************************************************** Ensure when setting connectpath it is a canonicalized (no ./ // or ../) absolute path stating in / and not ending in /. diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 643c48cd27..df81b2936d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -792,31 +792,6 @@ char *vfs_GetWd(connection_struct *conn, char *path) return (path); } -BOOL canonicalize_path(connection_struct *conn, pstring path) -{ -#ifdef REALPATH_TAKES_NULL - char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL); - if (!resolved_name) { - return False; - } - pstrcpy(path, resolved_name); - SAFE_FREE(resolved_name); - return True; -#else -#ifdef PATH_MAX - char resolved_name_buf[PATH_MAX+1]; -#else - pstring resolved_name_buf; -#endif - char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf); - if (!resolved_name) { - return False; - } - pstrcpy(path, resolved_name); - return True; -#endif /* REALPATH_TAKES_NULL */ -} - /******************************************************************* Reduce a file name, removing .. elements and checking that it is below dir in the heirachy. This uses realpath. -- cgit From b9af9646807373ba3264a4c44779c0b2eea68723 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 13:12:38 +0000 Subject: r21083: Actually make it static... :-) (This used to be commit 65f473d22bd8f3b04becfc0be369758898fdadb6) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ff6f9d1c1a..b5569c680d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -22,7 +22,7 @@ extern userdom_struct current_user_info; -BOOL canonicalize_path(connection_struct *conn, pstring path) +static BOOL canonicalize_path(connection_struct *conn, pstring path) { #ifdef REALPATH_TAKES_NULL char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL); -- cgit From 113e21f0a57af49d61cfb0dd1afd38b4a8fd5128 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 13:47:37 +0000 Subject: r21084: Make the Samba4 files compile in Samba3, not activated yet. Volker (This used to be commit c24854433a28cc066072a7107e29aa7fe2bec3c8) --- source3/smbd/notify.c | 27 +++++++++++++++++++ source3/smbd/notify_inotify.c | 60 +++++++++++++++++++++++------------------- source3/smbd/notify_internal.c | 30 ++++++++++----------- 3 files changed, 74 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 4c82b9fca8..97192d6e63 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -548,3 +548,30 @@ BOOL init_change_notify(void) return True; } + +struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, + TALLOC_CTX *mem_ctx, + struct event_context *ev) +{ + struct sys_notify_context *ctx; + + if (!(ctx = TALLOC_P(mem_ctx, struct sys_notify_context))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + ctx->ev = ev; + ctx->private_data = NULL; + return ctx; +} + +NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, + struct notify_entry *e, + void (*callback)(struct sys_notify_context *ctx, + void *private_data, + struct notify_event *ev), + void *private_data, void *handle) +{ + return inotify_watch(ctx, e, callback, private_data, handle); +} + diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 8bb0096dcc..39dc7e53e7 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -23,11 +23,8 @@ */ #include "includes.h" -#include "system/filesys.h" -#include "ntvfs/sysdep/sys_notify.h" -#include "lib/events/events.h" -#include "lib/util/dlinklist.h" -#include "libcli/raw/smb.h" + +#ifdef HAVE_INOTIFY #include #include @@ -71,7 +68,9 @@ struct watch_context { struct watch_context *next, *prev; struct inotify_private *in; int wd; - sys_notify_callback_t callback; + void (*callback)(struct sys_notify_context *ctx, + void *private_data, + struct notify_event *ev); void *private_data; uint32_t mask; /* the inotify mask */ uint32_t filter; /* the windows completion filter */ @@ -95,6 +94,9 @@ static int inotify_destructor(struct inotify_private *in) */ static BOOL filter_match(struct watch_context *w, struct inotify_event *e) { + DEBUG(10, ("filter_match: e->mask=%x, w->mask=%x, w->filter=%x\n", + e->mask, w->mask, w->filter)); + if ((e->mask & w->mask) == 0) { /* this happens because inotify_add_watch() coalesces watches on the same path, oring their masks together */ @@ -142,6 +144,9 @@ static void inotify_dispatch(struct inotify_private *in, struct watch_context *w, *next; struct notify_event ne; + DEBUG(10, ("inotify_dispatch called with mask=%x, name=[%s]\n", + e->mask, e->len ? e->name : "")); + /* ignore extraneous events, such as unmount and IN_IGNORED events */ if ((e->mask & (IN_ATTRIB|IN_MODIFY|IN_CREATE|IN_DELETE| IN_MOVED_FROM|IN_MOVED_TO)) == 0) { @@ -171,6 +176,9 @@ static void inotify_dispatch(struct inotify_private *in, } ne.path = e->name; + DEBUG(10, ("inotify_dispatch: ne.action = %d, ne.path = %s\n", + ne.action, ne.path)); + /* find any watches that have this watch descriptor */ for (w=in->watches;w;w=next) { next = w->next; @@ -222,7 +230,7 @@ static void inotify_handler(struct event_context *ev, struct fd_event *fde, return; } - e0 = e = talloc_size(in, bufsize); + e0 = e = (struct inotify_event *)talloc_size(in, bufsize); if (e == NULL) return; if (read(in->fd, e0, bufsize) != bufsize) { @@ -323,7 +331,12 @@ static int watch_destructor(struct watch_context *w) if (w->wd == wd) break; } if (w == NULL) { - inotify_rm_watch(in->fd, wd); + DEBUG(10, ("Deleting inotify watch %d\n", wd)); + if (inotify_rm_watch(in->fd, wd) == -1) { + DEBUG(1, ("inotify_rm_watch returned %s\n", + strerror(errno))); + } + } return 0; } @@ -333,11 +346,13 @@ static int watch_destructor(struct watch_context *w) add a watch. The watch is removed when the caller calls talloc_free() on *handle */ -static NTSTATUS inotify_watch(struct sys_notify_context *ctx, - struct notify_entry *e, - sys_notify_callback_t callback, - void *private_data, - void *handle_p) +NTSTATUS inotify_watch(struct sys_notify_context *ctx, + struct notify_entry *e, + void (*callback)(struct sys_notify_context *ctx, + void *private_data, + struct notify_event *ev), + void *private_data, + void *handle_p) { struct inotify_private *in; int wd; @@ -369,9 +384,13 @@ static NTSTATUS inotify_watch(struct sys_notify_context *ctx, wd = inotify_add_watch(in->fd, e->path, mask); if (wd == -1) { e->filter = filter; + DEBUG(1, ("inotify_add_watch returned %s\n", strerror(errno))); return map_nt_error_from_unix(errno); } + DEBUG(10, ("inotify_add_watch for %s mask %x returned wd %d\n", + e->path, mask, wd)); + w = talloc(in, struct watch_context); if (w == NULL) { inotify_rm_watch(in->fd, wd); @@ -402,17 +421,4 @@ static NTSTATUS inotify_watch(struct sys_notify_context *ctx, return NT_STATUS_OK; } - -static struct sys_notify_backend inotify = { - .name = "inotify", - .notify_watch = inotify_watch -}; - -/* - initialialise the inotify module - */ -NTSTATUS sys_notify_inotify_init(void) -{ - /* register ourselves as a system inotify module */ - return sys_notify_register(&inotify); -} +#endif diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 91fa8a1d78..6d77ba4df6 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -25,17 +25,7 @@ */ #include "includes.h" -#include "system/filesys.h" -#include "lib/tdb/include/tdb.h" -#include "lib/util/util_tdb.h" -#include "messaging/messaging.h" -#include "db_wrap.h" -#include "lib/messaging/irpc.h" #include "librpc/gen_ndr/ndr_notify.h" -#include "lib/util/dlinklist.h" -#include "ntvfs/common/ntvfs_common.h" -#include "ntvfs/sysdep/sys_notify.h" -#include "cluster/cluster.h" struct notify_context { struct tdb_wrap *w; @@ -83,11 +73,11 @@ static int notify_destructor(struct notify_context *notify) struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, struct messaging_context *messaging_ctx, struct event_context *ev, - struct share_config *scfg) + struct share_params *scfg) { struct notify_context *notify; - if (share_bool_option(scfg, NOTIFY_ENABLE, NOTIFY_ENABLE_DEFAULT) != True) { + if (!lp_parm_bool(scfg->service, "notify", "enable", True)) { return NULL; } @@ -96,7 +86,9 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, return NULL; } - notify->w = cluster_tdb_tmp_open(notify, "notify.tdb", TDB_SEQNUM); + notify->w = tdb_wrap_open(notify, lock_path("notify.tdb"), + 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, 0644); if (notify->w == NULL) { talloc_free(notify); return NULL; @@ -167,7 +159,7 @@ static NTSTATUS notify_load(struct notify_context *notify) return NT_STATUS_OK; } - blob.data = dbuf.dptr; + blob.data = (uint8 *)dbuf.dptr; blob.length = dbuf.dsize; status = ndr_pull_struct_blob(&blob, notify->array, notify->array, @@ -182,7 +174,8 @@ static NTSTATUS notify_load(struct notify_context *notify) */ static int notify_compare(const void *p1, const void *p2) { - const struct notify_entry *e1 = p1, *e2 = p2; + const struct notify_entry *e1 = (const struct notify_entry *)p1; + const struct notify_entry *e2 = (const struct notify_entry *)p2; return strcmp(e1->path, e2->path); } @@ -222,7 +215,7 @@ static NTSTATUS notify_save(struct notify_context *notify) return status; } - dbuf.dptr = blob.data; + dbuf.dptr = (char *)blob.data; dbuf.dsize = blob.length; ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE); @@ -276,6 +269,8 @@ static void sys_notify_callback(struct sys_notify_context *ctx, { struct notify_list *listel = talloc_get_type(ptr, struct notify_list); ev->private_data = listel; + DEBUG(10, ("sys_notify_callback called with action=%d, for %s\n", + ev->action, ev->path)); listel->callback(listel->private_data, ev); } @@ -576,6 +571,9 @@ void notify_trigger(struct notify_context *notify, int depth; const char *p, *next_p; + DEBUG(10, ("notify_trigger called action=0x%x, filter=0x%x, " + "path=%s\n", (unsigned)action, (unsigned)filter, path)); + /* see if change notify is enabled at all */ if (notify == NULL) { return; -- cgit From 547f77778abc45bf329dcb53182127d72596c812 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:14:57 +0000 Subject: r21087: Make the param list of notify_fname match notify_trigger (This used to be commit defa28f9c3eda85a072b972fffd2d5de8bcf01f7) --- source3/smbd/dosmode.c | 12 ++++++------ source3/smbd/notify.c | 4 ++-- source3/smbd/open.c | 4 ++-- source3/smbd/reply.c | 14 ++++++++------ 4 files changed, 18 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 44e637a0ee..ad79bbacdd 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -492,8 +492,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, } if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) { - notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, - NOTIFY_ACTION_MODIFIED); + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); return 0; } @@ -524,8 +524,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); - notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, - NOTIFY_ACTION_MODIFIED); + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } return( ret ); @@ -599,8 +599,8 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) return False; } - notify_fname(conn, fname, FILE_NOTIFY_CHANGE_LAST_WRITE, - NOTIFY_ACTION_MODIFIED); + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_LAST_WRITE, fname); return(True); } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 97192d6e63..9cb121a039 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -402,8 +402,8 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } -void notify_fname(connection_struct *conn, const char *path, - uint32 filter, uint32 action) +void notify_fname(connection_struct *conn, uint32 action, uint32 filter, + const char *path) { char *parent; const char *name; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 529677a5f3..8dd4ed1925 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,8 +309,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } - notify_action(conn, parent_dir, name, -1, - NOTIFY_ACTION_ADDED); + notify_fname(conn, NOTIFY_ACTION_ADDED, + FILE_NOTIFY_CHANGE_FILE_NAME, path); } } else { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 37c8a46ed3..7ffebd9118 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1866,9 +1866,9 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; - notify_fname(conn, directory, + notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_FILE_NAME, - NOTIFY_ACTION_REMOVED); + directory); } } else { struct smb_Dir *dir_hnd = NULL; @@ -3714,8 +3714,9 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) ret = SMB_VFS_RMDIR(conn,directory); if (ret == 0) { - notify_fname(conn, directory, FILE_NOTIFY_CHANGE_DIR_NAME, - NOTIFY_ACTION_REMOVED); + notify_fname(conn, NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_DIR_NAME, + directory); return True; } @@ -3793,8 +3794,9 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) return False; } - notify_fname(conn, directory, FILE_NOTIFY_CHANGE_DIR_NAME, - NOTIFY_ACTION_REMOVED); + notify_fname(conn, NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_DIR_NAME, + directory); return True; } -- cgit From 697ccab3f0c8d9cae7ce982009957a79254e4665 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:24:29 +0000 Subject: r21089: Do notifies on rename (This used to be commit 2aadb95a7e58777ee7ff024cc9e14f4334970d50) --- source3/smbd/reply.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7ffebd9118..3c7b3c4e18 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4113,6 +4113,48 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return status; } +/* + * Do the notify calls from a rename + */ + +static void notify_rename(connection_struct *conn, BOOL is_dir, + const char *oldpath, const char *newpath) +{ + char *olddir, *newdir; + const char *oldname, *newname; + uint32 mask; + + mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME + : FILE_NOTIFY_CHANGE_FILE_NAME; + + if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname) + || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) { + TALLOC_FREE(olddir); + return; + } + + if (strcmp(olddir, newdir) == 0) { + notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath); + notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath); + } + else { + notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath); + notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath); + } + TALLOC_FREE(olddir); + TALLOC_FREE(newdir); + + /* this is a strange one. w2k3 gives an additional event for + CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming + files, but not directories */ + if (!is_dir) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES + |FILE_NOTIFY_CHANGE_CREATION, + newpath); + } +} + /**************************************************************************** The guts of the rename command, split out so it may be called by the NT SMB code. @@ -4319,6 +4361,8 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); TALLOC_FREE(lck); + notify_rename(conn, S_ISDIR(sbuf1.st_mode), + directory, newname); return NT_STATUS_OK; } -- cgit From 3af5838096872039ac201385763f1e4c0fafb034 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:28:08 +0000 Subject: r21090: Add some helper routines (This used to be commit 985dde8ed0a7e6da5adf9c55654a4fd362b22acb) --- source3/smbd/notify.c | 38 ++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 11 +++++++++++ 2 files changed, 49 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9cb121a039..2907bd7e0f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -521,6 +521,44 @@ static void notify_message_callback(int msgtype, struct process_id pid, } } +char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) +{ + char *result = NULL; + + result = talloc_strdup(mem_ctx, ""); + + if (filter & FILE_NOTIFY_CHANGE_FILE_NAME) + result = talloc_asprintf_append(result, "FILE_NAME|"); + if (filter & FILE_NOTIFY_CHANGE_DIR_NAME) + result = talloc_asprintf_append(result, "DIR_NAME|"); + if (filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) + result = talloc_asprintf_append(result, "ATTRIBUTES|"); + if (filter & FILE_NOTIFY_CHANGE_SIZE) + result = talloc_asprintf_append(result, "SIZE|"); + if (filter & FILE_NOTIFY_CHANGE_LAST_WRITE) + result = talloc_asprintf_append(result, "LAST_WRITE|"); + if (filter & FILE_NOTIFY_CHANGE_LAST_ACCESS) + result = talloc_asprintf_append(result, "LAST_ACCESS|"); + if (filter & FILE_NOTIFY_CHANGE_CREATION) + result = talloc_asprintf_append(result, "CREATION|"); + if (filter & FILE_NOTIFY_CHANGE_EA) + result = talloc_asprintf_append(result, "EA|"); + if (filter & FILE_NOTIFY_CHANGE_SECURITY) + result = talloc_asprintf_append(result, "SECURITY|"); + if (filter & FILE_NOTIFY_CHANGE_STREAM_NAME) + result = talloc_asprintf_append(result, "STREAM_NAME|"); + if (filter & FILE_NOTIFY_CHANGE_STREAM_SIZE) + result = talloc_asprintf_append(result, "STREAM_SIZE|"); + if (filter & FILE_NOTIFY_CHANGE_STREAM_WRITE) + result = talloc_asprintf_append(result, "STREAM_WRITE|"); + + if (result == NULL) return NULL; + if (*result == '\0') return result; + + result[strlen(result)-1] = '\0'; + return result; +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index dcb685511b..ab43bcb66f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -71,6 +71,17 @@ struct event_context *smbd_event_context(void) return ctx; } +struct messaging_context *smbd_messaging_context(void) +{ + static struct messaging_context *ctx; + + if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), + smbd_event_context()))) { + smb_panic("Could not init smbd messaging context\n"); + } + return ctx; +} + /******************************************************************* What to do when smb.conf is updated. ********************************************************************/ -- cgit From accbfaa4c3ffe669cc29aac8a85c4144ad234e43 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:36:50 +0000 Subject: r21091: Fix the build without inotify (This used to be commit 686345b7ed727db7b1d9bc164208ecfb612837b6) --- source3/smbd/notify.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2907bd7e0f..49219bcca5 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -610,6 +610,10 @@ NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, struct notify_event *ev), void *private_data, void *handle) { +#ifdef HAVE_INOTIFY return inotify_watch(ctx, e, callback, private_data, handle); +#else + return NT_STATUS_OK; +#endif } -- cgit From 2852ecc67ebded7758a07d8fb72eef53bfa1c63a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:42:56 +0000 Subject: r21092: Ok, that's the one that activates the Samba4 notify backend. Now to clean up / fix lots of stuff. Volker (This used to be commit 9e7443fa1417c01be903b15073825dc4def78d99) --- source3/smbd/files.c | 5 ++- source3/smbd/notify.c | 97 +++++++++++++++++++++++++++++--------------------- source3/smbd/nttrans.c | 54 +++++++++++++++++++++++++--- source3/smbd/service.c | 7 ++++ 4 files changed, 117 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 982de4c55f..fc1700de11 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -483,7 +483,10 @@ void file_free(files_struct *fsp) fsp->fh->ref_count--; } - TALLOC_FREE(fsp->notify); + if (fsp->notify) { + notify_remove(fsp->conn->notify_ctx, fsp); + TALLOC_FREE(fsp->notify); + } bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 49219bcca5..93a6357d0c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -159,7 +159,8 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, } NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, - uint32 filter, struct files_struct *fsp) + uint32 filter, BOOL recursive, + struct files_struct *fsp) { struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; @@ -177,9 +178,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, request->max_param_count = max_param_count; request->filter = filter; request->fsp = fsp; - - request->backend_data = cnotify->notify_add(NULL, smbd_event_context(), - fsp, &request->filter); + request->backend_data = NULL; DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -343,6 +342,18 @@ void notify_action(connection_struct *conn, const char *parent, return; } + { + char *fullpath; + + if (asprintf(&fullpath, "%s/%s/%s", conn->connectpath, + parent, name) != -1) { + notify_trigger(conn->notify_ctx, action, filter, + fullpath); + SAFE_FREE(fullpath); + } + return; + } + if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, NULL, NULL))) { return; @@ -405,20 +416,21 @@ void notify_action(connection_struct *conn, const char *parent, void notify_fname(connection_struct *conn, uint32 action, uint32 filter, const char *path) { - char *parent; - const char *name; + char *fullpath; - if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { + if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) { + DEBUG(0, ("asprintf failed\n")); return; } - notify_action(conn, parent, name, filter, action); - TALLOC_FREE(parent); + notify_trigger(conn->notify_ctx, action, filter, fullpath); + SAFE_FREE(fullpath); } -void notify_fsp(files_struct *fsp, uint32 action, char *name) +void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; + char *name2; if (fsp->notify == NULL) { /* @@ -427,35 +439,12 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) return; } - if (fsp->notify->requests != NULL) { - /* - * Someone is waiting for the change, trigger the reply - * immediately. - * - * TODO: do we have to walk the lists of requests pending? - */ - - struct notify_change_request *req = fsp->notify->requests; - struct notify_change onechange; - - if (name == NULL) { - /* - * Catch-all change, possibly from notify_hash.c - */ - change_notify_reply(req->request_buf, - req->max_param_count, - -1, NULL); + if (!(name2 = talloc_strdup(fsp->notify, name))) { + DEBUG(0, ("talloc_strdup failed\n")); return; } - onechange.action = action; - onechange.name = name; - - change_notify_reply(req->request_buf, req->max_param_count, - 1, &onechange); - change_notify_remove_request(req); - return; - } + string_replace(name2, '/', '\\'); /* * Someone has triggered a notify previously, queue the change for @@ -468,6 +457,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) * W2k3 seems to store at most 30 changes. */ TALLOC_FREE(fsp->notify->changes); + TALLOC_FREE(name2); fsp->notify->num_changes = -1; return; } @@ -480,6 +470,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { DEBUG(0, ("talloc_realloc failed\n")); + TALLOC_FREE(name2); return; } @@ -487,14 +478,40 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, name))) { - DEBUG(0, ("talloc_strdup failed\n")); - return; - } + change->name = talloc_move(changes, &name2); change->action = action; fsp->notify->num_changes += 1; + if (fsp->notify->requests == NULL) { + /* + * Nobody is waiting, so don't send anything. The ot + */ + return; + } + + if (action == NOTIFY_ACTION_OLD_NAME) { + /* + * We have to send the two rename events in one reply. So hold + * the first part back. + */ return; + } + + /* + * Someone is waiting for the change, trigger the reply immediately. + * + * TODO: do we have to walk the lists of requests pending? + */ + + change_notify_reply(fsp->notify->requests->request_buf, + fsp->notify->requests->max_param_count, + fsp->notify->num_changes, + fsp->notify->changes); + + change_notify_remove_request(fsp->notify->requests); + + TALLOC_FREE(fsp->notify->changes); + fsp->notify->num_changes = 0; } static void notify_message_callback(int msgtype, struct process_id pid, diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 07d345aacd..6db6311a29 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1787,6 +1787,13 @@ int reply_ntrename(connection_struct *conn, don't allow a directory to be opened. ****************************************************************************/ +static void notify_callback(void *private_data, const struct notify_event *e) +{ + files_struct *fsp = (files_struct *)private_data; + DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name)); + notify_fsp(fsp, e->action, e->path); +} + static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1801,6 +1808,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, files_struct *fsp; uint32 filter; NTSTATUS status; + BOOL recursive; if(setup_count < 6) { return ERROR_DOS(ERRDOS,ERRbadfunc); @@ -1808,6 +1816,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, fsp = file_fsp((char *)setup,4); filter = IVAL(setup, 0); + recursive = (SVAL(setup, 6) != 0) ? True : False; DEBUG(3,("call_nt_transact_notify_change\n")); @@ -1815,18 +1824,55 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfid); } - DEBUG(3,("call_nt_transact_notify_change: notify change called on " - "directory name = %s\n", fsp->fsp_name )); + { + char *filter_string; + + if (!(filter_string = notify_filter_string(NULL, filter))) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + DEBUG(3,("call_nt_transact_notify_change: notify change " + "called on %s, filter = %s, recursive = %d\n", + fsp->fsp_name, filter_string, recursive)); + + TALLOC_FREE(filter_string); + } if((!fsp->is_directory) || (conn != fsp->conn)) { return ERROR_DOS(ERRDOS,ERRbadfid); } if (fsp->notify == NULL) { + char *fullpath; + struct notify_entry e; + if (!(fsp->notify = TALLOC_ZERO_P( NULL, struct notify_change_buf))) { return ERROR_NT(NT_STATUS_NO_MEMORY); } + + if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath, + fsp->fsp_name) == -1) { + DEBUG(0, ("asprintf failed\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + e.path = fullpath; + e.filter = filter; + e.subdir_filter = 0; + if (recursive) { + e.subdir_filter = filter; + } + + status = notify_add(fsp->conn->notify_ctx, &e, notify_callback, + fsp); + SAFE_FREE(fullpath); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("notify_add returned %s\n", + nt_errstr(status))); + return ERROR_NT(status); + } } if (fsp->notify->num_changes != 0) { @@ -1840,8 +1886,6 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * here. */ - SMB_ASSERT(fsp->notify->requests == NULL); - change_notify_reply(inbuf, max_param_count, fsp->notify->num_changes, fsp->notify->changes); @@ -1861,7 +1905,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, */ status = change_notify_add_request(inbuf, max_param_count, filter, - fsp); + recursive, fsp); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index b5569c680d..8dbcc2b5ab 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -946,6 +946,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, set_conn_connectpath(conn,s); } + if ((!conn->printer) && (!conn->ipc)) { + conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(), + smbd_messaging_context(), + smbd_event_context(), + conn->params); + } + /* ROOT Activities: */ /* check number of connections */ if (!claim_connection(conn, -- cgit From 9974656d3be3fb01af59bfefe592475e92bdceb0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 16:56:27 +0000 Subject: r21093: Remove the hash and dnotify backends. Disabling FAM for this checkin, I'm working on that right now. Volker (This used to be commit 01c9fb17281e99300b339d2cfc0acac7ca94843c) --- source3/smbd/notify.c | 204 ------------------------------ source3/smbd/notify_fam.c | 2 +- source3/smbd/notify_hash.c | 278 ----------------------------------------- source3/smbd/notify_kernel.c | 287 ------------------------------------------- source3/smbd/open.c | 4 +- source3/smbd/reply.c | 6 +- source3/smbd/server.c | 4 - 7 files changed, 6 insertions(+), 779 deletions(-) delete mode 100644 source3/smbd/notify_hash.c delete mode 100644 source3/smbd/notify_kernel.c (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 93a6357d0c..5c1143a28e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,7 +22,6 @@ #include "includes.h" -static struct cnotify_fns *cnotify; static struct notify_mid_map *notify_changes_by_mid; /* @@ -262,157 +261,6 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } } -/* notify message definition - -Offset Data length. -0 SMB_DEV_T dev 8 -8 SMB_INO_T inode 8 -16 uint32 filter 4 -20 uint32 action 4 -24.. name -*/ - -#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ - -struct notify_message { - SMB_DEV_T dev; - SMB_INO_T inode; - uint32 filter; - uint32 action; - char *name; -}; - -static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) -{ - DATA_BLOB result; - size_t len; - - len = strlen(msg->name); - - result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); - if (!result.data) { - return result; - } - - SDEV_T_VAL(result.data, 0, msg->dev); - SINO_T_VAL(result.data, 8, msg->inode); - SIVAL(result.data, 16, msg->filter); - SIVAL(result.data, 20, msg->action); - memcpy(result.data+24, msg->name, len+1); - - return result; -} - -static BOOL buf_to_notify_message(void *buf, size_t len, - struct notify_message *msg) -{ - if (len < MSG_NOTIFY_MESSAGE_SIZE) { - DEBUG(0, ("Got invalid notify message of len %d\n", - (int)len)); - return False; - } - - msg->dev = DEV_T_VAL(buf, 0); - msg->inode = INO_T_VAL(buf, 8); - msg->filter = IVAL(buf, 16); - msg->action = IVAL(buf, 20); - msg->name = ((char *)buf)+24; - return True; -} - -void notify_action(connection_struct *conn, const char *parent, - const char *name, uint32 filter, uint32_t action) -{ - struct share_mode_lock *lck; - SMB_STRUCT_STAT sbuf; - int i; - struct notify_message msg; - DATA_BLOB blob; - - struct process_id *pids; - int num_pids; - - DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", - parent, name, (unsigned)action)); - - if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { - /* - * Not 100% critical, ignore failure - */ - return; - } - - { - char *fullpath; - - if (asprintf(&fullpath, "%s/%s/%s", conn->connectpath, - parent, name) != -1) { - notify_trigger(conn->notify_ctx, action, filter, - fullpath); - SAFE_FREE(fullpath); - } - return; - } - - if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, - NULL, NULL))) { - return; - } - - msg.dev = sbuf.st_dev; - msg.inode = sbuf.st_ino; - msg.filter = filter; - msg.action = action; - msg.name = CONST_DISCARD(char *, name); - - blob = notify_message_to_buf(&msg); - if (blob.data == NULL) { - DEBUG(0, ("notify_message_to_buf failed\n")); - return; - } - - pids = NULL; - num_pids = 0; - - become_root_uid_only(); - - for (i=0; inum_share_modes; i++) { - struct share_mode_entry *e = &lck->share_modes[i]; - int j; - struct process_id *tmp; - - for (j=0; jpid, &pids[j])) { - break; - } - } - - if (j < num_pids) { - /* - * Already sent to that process, skip it - */ - continue; - } - - message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, - blob.data, blob.length, True); - - if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, - num_pids+1))) { - DEBUG(0, ("realloc failed\n")); - break; - } - pids = tmp; - pids[num_pids] = e->pid; - num_pids += 1; - } - - unbecome_root_uid_only(); - - data_blob_free(&blob); - TALLOC_FREE(lck); -} - void notify_fname(connection_struct *conn, uint32 action, uint32 filter, const char *path) { @@ -514,30 +362,6 @@ void notify_fsp(files_struct *fsp, uint32 action, const char *name) fsp->notify->num_changes = 0; } -static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len, - void *private_data) -{ - struct notify_message msg; - files_struct *fsp; - - if (!buf_to_notify_message(buf, len, &msg)) { - return; - } - - DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", - (unsigned)msg.dev, (double)msg.inode, msg.action)); - - for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; - fsp = fsp_find_di_next(fsp)) { - if ((fsp->notify != NULL) - && (fsp->notify->requests != NULL) - && (fsp->notify->requests->filter & msg.filter)) { - notify_fsp(fsp, msg.action, msg.name); - } - } -} - char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) { char *result = NULL; @@ -576,34 +400,6 @@ char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) return result; } -/**************************************************************************** - Initialise the change notify subsystem. -****************************************************************************/ - -BOOL init_change_notify(void) -{ - cnotify = NULL; - -#if HAVE_KERNEL_CHANGE_NOTIFY - if (cnotify == NULL && lp_kernel_change_notify()) - cnotify = kernel_notify_init(smbd_event_context()); -#endif -#if HAVE_FAM_CHANGE_NOTIFY - if (cnotify == NULL && lp_fam_change_notify()) - cnotify = fam_notify_init(smbd_event_context()); -#endif - if (!cnotify) cnotify = hash_notify_init(); - - if (!cnotify) { - DEBUG(0,("Failed to init change notify system\n")); - return False; - } - - message_register(MSG_SMB_NOTIFY, notify_message_callback, NULL); - - return True; -} - struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, TALLOC_CTX *mem_ctx, struct event_context *ev) diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index 08dc4eabb0..89bbddae24 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -21,7 +21,7 @@ #include "includes.h" -#ifdef HAVE_FAM_CHANGE_NOTIFY +#if 0 #include diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c deleted file mode 100644 index 2cd8fbc6bc..0000000000 --- a/source3/smbd/notify_hash.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - Unix SMB/CIFS implementation. - change notify handling - hash based implementation - Copyright (C) Jeremy Allison 1994-1998 - Copyright (C) Andrew Tridgell 2000 - Copyright (C) Volker Lendecke 2007 - - 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" - -struct hash_change_data { - time_t last_check_time; /* time we last checked this entry */ - struct timespec modify_time; /* Info from the directory we're - * monitoring. */ - struct timespec status_time; /* Info from the directory we're - * monitoring. */ - time_t total_time; /* Total time of all directory entries - don't care - * if it wraps. */ - unsigned int num_entries; /* Zero or the number of files in the - * directory. */ - unsigned int mode_sum; - unsigned char name_hash[16]; -}; - -struct hash_notify_ctx { - struct hash_change_data *data; - files_struct *fsp; - char *path; - uint32 filter; -}; - -/* Compare struct timespec. */ -#define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec)) - -/**************************************************************************** - Create the hash we will use to determine if the contents changed. -*****************************************************************************/ - -static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, - struct hash_change_data *data, - struct hash_change_data *old_data) -{ - SMB_STRUCT_STAT st; - pstring full_name; - char *p; - const char *fname; - size_t remaining_len; - size_t fullname_len; - struct smb_Dir *dp; - long offset; - - ZERO_STRUCTP(data); - - if(SMB_VFS_STAT(conn,path, &st) == -1) - return False; - - data->modify_time = get_mtimespec(&st); - data->status_time = get_ctimespec(&st); - - if (old_data) { - /* - * Shortcut to avoid directory scan if the time - * has changed - we always must return true then. - */ - if (TIMESTAMP_NEQ(old_data->modify_time, data->modify_time) || - TIMESTAMP_NEQ(old_data->status_time, data->status_time) ) { - return True; - } - } - - if (S_ISDIR(st.st_mode) && - (flags & ~(FILE_NOTIFY_CHANGE_FILE_NAME - | FILE_NOTIFY_CHANGE_DIR_NAME)) == 0) - { - /* This is the case of a client wanting to know only when - * the contents of a directory changes. Since any file - * creation, rename or deletion will update the directory - * timestamps, we don't need to create a hash. - */ - return True; - } - - /* - * If we are to watch for changes that are only stored - * in inodes of files, not in the directory inode, we must - * scan the directory and produce a unique identifier with - * which we can determine if anything changed. We use the - * modify and change times from all the files in the - * directory, added together (ignoring wrapping if it's - * larger than the max time_t value). - */ - - dp = OpenDir(conn, path, NULL, 0); - if (dp == NULL) - return False; - - data->num_entries = 0; - - pstrcpy(full_name, path); - pstrcat(full_name, "/"); - - fullname_len = strlen(full_name); - remaining_len = sizeof(full_name) - fullname_len - 1; - p = &full_name[fullname_len]; - - offset = 0; - while ((fname = ReadDirName(dp, &offset))) { - SET_STAT_INVALID(st); - if(strequal(fname, ".") || strequal(fname, "..")) - continue; - - if (!is_visible_file(conn, path, fname, &st, True)) - continue; - - data->num_entries++; - safe_strcpy(p, fname, remaining_len); - - /* - * Do the stat - but ignore errors. - */ - if (!VALID_STAT(st)) { - SMB_VFS_STAT(conn,full_name, &st); - } - - /* - * Always sum the times. - */ - - data->total_time += (st.st_mtime + st.st_ctime); - - /* - * If requested hash the names. - */ - - if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME - |FILE_NOTIFY_CHANGE_FILE_NAME)) { - int i; - unsigned char tmp_hash[16]; - mdfour(tmp_hash, (const unsigned char *)fname, - strlen(fname)); - for (i=0;i<16;i++) - data->name_hash[i] ^= tmp_hash[i]; - } - - /* - * If requested sum the mode_t's. - */ - - if (flags & (FILE_NOTIFY_CHANGE_ATTRIBUTES - |FILE_NOTIFY_CHANGE_SECURITY)) - data->mode_sum += st.st_mode; - } - - CloseDir(dp); - - return True; -} - -static void hash_change_notify_handler(struct event_context *event_ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data) -{ - struct hash_change_data *new_data; - struct hash_notify_ctx *ctx = - talloc_get_type_abort(private_data, - struct hash_notify_ctx); - - TALLOC_FREE(te); - - if (!(new_data = TALLOC_P(ctx, struct hash_change_data))) { - DEBUG(0, ("talloc failed\n")); - /* - * No new timed event; - */ - return; - } - - if (!notify_hash(ctx->fsp->conn, ctx->fsp->fsp_name, - ctx->filter, new_data, ctx->data) - || TIMESTAMP_NEQ(new_data->modify_time, ctx->data->modify_time) - || TIMESTAMP_NEQ(new_data->status_time, ctx->data->status_time) - || new_data->total_time != ctx->data->total_time - || new_data->num_entries != ctx->data->num_entries - || new_data->mode_sum != ctx->data->mode_sum - || (memcmp(new_data->name_hash, ctx->data->name_hash, - sizeof(new_data->name_hash)))) { - notify_fsp(ctx->fsp, 0, NULL); - } - - TALLOC_FREE(ctx->data); - ctx->data = new_data; - - event_add_timed( - event_ctx, ctx, - timeval_current_ofs( - lp_change_notify_timeout(SNUM(ctx->fsp->conn)), 0), - "hash_change_notify_handler", - hash_change_notify_handler, ctx); -} - - - -static void *hash_notify_add(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - files_struct *fsp, - uint32 *filter) -{ - struct hash_notify_ctx *ctx; - int timeout = lp_change_notify_timeout(SNUM(fsp->conn)); - - if (timeout <= 0) { - /* It change notify timeout has been disabled, never scan the - * directory. */ - return NULL; - } - - if (!(ctx = TALLOC_P(mem_ctx, struct hash_notify_ctx))) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } - - if (!(ctx->path = talloc_asprintf(ctx, "%s/%s", fsp->conn->connectpath, - fsp->fsp_name))) { - DEBUG(0, ("talloc_asprintf failed\n")); - TALLOC_FREE(ctx); - return NULL; - } - - if (!(ctx->data = TALLOC_P(ctx, struct hash_change_data))) { - DEBUG(0, ("talloc failed\n")); - TALLOC_FREE(ctx); - return NULL; - } - - ctx->fsp = fsp; - - /* - * Don't change the Samba filter, hash can only be a very bad attempt - * anyway. - */ - ctx->filter = *filter; - - notify_hash(fsp->conn, ctx->path, ctx->filter, ctx->data, NULL); - - event_add_timed(event_ctx, ctx, timeval_current_ofs(timeout, 0), - "hash_change_notify_handler", - hash_change_notify_handler, ctx); - - return (void *)ctx; -} - -/**************************************************************************** - Setup hash based change notify. -****************************************************************************/ - -struct cnotify_fns *hash_notify_init(void) -{ - static struct cnotify_fns cnotify; - - cnotify.notify_add = hash_notify_add; - - return &cnotify; -} diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c deleted file mode 100644 index f90414dc79..0000000000 --- a/source3/smbd/notify_kernel.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0 - change notify handling - linux kernel based implementation - Copyright (C) Andrew Tridgell 2000 - Copyright (C) Volker Lendecke 2007 - - 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" - -#if HAVE_KERNEL_CHANGE_NOTIFY - -#ifndef DN_ACCESS -#define DN_ACCESS 0x00000001 /* File accessed in directory */ -#define DN_MODIFY 0x00000002 /* File modified in directory */ -#define DN_CREATE 0x00000004 /* File created in directory */ -#define DN_DELETE 0x00000008 /* File removed from directory */ -#define DN_RENAME 0x00000010 /* File renamed in directory */ -#define DN_ATTRIB 0x00000020 /* File changed attribute */ -#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */ -#endif - - -#ifndef RT_SIGNAL_NOTIFY -#define RT_SIGNAL_NOTIFY (SIGRTMIN+2) -#endif - -#ifndef F_SETSIG -#define F_SETSIG 10 -#endif - -#ifndef F_NOTIFY -#define F_NOTIFY 1026 -#endif - -/**************************************************************************** - This is the structure to keep the information needed to - determine if a directory has changed. -*****************************************************************************/ - -struct dnotify_ctx { - struct dnotify_ctx *prev, *next; - - int fd; - files_struct *fsp; -}; - -static struct dnotify_ctx *dnotify_list; -static int dnotify_signal_pipe[2]; - -/**************************************************************************** - The signal handler for change notify. - The Linux kernel has a bug in that we should be able to block any - further delivery of RT signals until the kernel_check_notify() function - unblocks them, but it seems that any signal mask we're setting here is - being overwritten on exit from this handler. I should create a standalone - test case for the kernel hackers. JRA. -*****************************************************************************/ - -static void dnotify_signal_handler(int sig, siginfo_t *info, void *unused) -{ - int saved_errno; - - /* - * According to http://www.opengroup.org/onlinepubs/009695399/ write - * to a pipe either writes all or nothing, so we can safely write a - * full sizeof(int) and not risk the pipe to become out of sync with - * the receiving end. - * - * We don't care about the result of the write() call. If the pipe is - * full, then this signal is lost, we can't do anything about it. - */ - - saved_errno = errno; - write(dnotify_signal_pipe[1], (const void *)&info->si_fd, sizeof(int)); - errno = saved_errno; - - sys_select_signal(RT_SIGNAL_NOTIFY); -} - -/**************************************************************************** - The upper level handler informed when the pipe is ready for reading -*****************************************************************************/ - -static void dnotify_pipe_handler(struct event_context *event_ctx, - struct fd_event *event, - uint16 flags, - void *private_data) -{ - int res, fd; - struct dnotify_ctx *ctx; - - res = read(dnotify_signal_pipe[0], (void *)&fd, sizeof(int)); - - if (res == -1) { - DEBUG(0, ("Read from the dnotify pipe failed: %s\n", - strerror(errno))); - TALLOC_FREE(event); /* Don't try again */ - return; - } - - if (res != sizeof(int)) { - smb_panic("read from dnotify pipe gave wrong number of " - "bytes\n"); - } - - for (ctx = dnotify_list; ctx; ctx = ctx->next) { - if (ctx->fd == fd) { - notify_fsp(ctx->fsp, 0, NULL); - } - } -} - -/**************************************************************************** - Register a change notify request. -*****************************************************************************/ - -static int kernel_register_notify(connection_struct *conn, char *path, - uint32 flags) -{ - int fd; - unsigned long kernel_flags; - - fd = sys_open(path,O_RDONLY, 0); - - if (fd == -1) { - DEBUG(3,("Failed to open directory %s for change notify\n", - path)); - return -1; - } - - if (sys_fcntl_long(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) { - DEBUG(3,("Failed to set signal handler for change notify\n")); - close(fd); - return -1; - } - - kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion - * changes - * everything! */ - if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_MODIFY; - if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags - |= DN_RENAME - |DN_DELETE; - if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_ATTRIB; - if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY; - if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY; - if (flags & FILE_NOTIFY_CHANGE_LAST_ACCESS) kernel_flags |= DN_ACCESS; - if (flags & FILE_NOTIFY_CHANGE_CREATION) kernel_flags |= DN_CREATE; - if (flags & FILE_NOTIFY_CHANGE_SECURITY) kernel_flags |= DN_ATTRIB; - if (flags & FILE_NOTIFY_CHANGE_EA) kernel_flags |= DN_ATTRIB; - if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags - |= DN_RENAME - |DN_DELETE; - - if (sys_fcntl_long(fd, F_NOTIFY, kernel_flags) == -1) { - DEBUG(3,("Failed to set async flag for change notify\n")); - close(fd); - return -1; - } - - DEBUG(3,("kernel change notify on %s (ntflags=0x%x flags=0x%x) " - "fd=%d\n", path, (int)flags, (int)kernel_flags, fd)); - - return fd; -} - -/**************************************************************************** - See if the kernel supports change notify. -****************************************************************************/ - -static BOOL kernel_notify_available(void) -{ - int fd, ret; - fd = open("/tmp", O_RDONLY); - if (fd == -1) - return False; /* uggh! */ - ret = sys_fcntl_long(fd, F_NOTIFY, 0); - close(fd); - return ret == 0; -} - -static int dnotify_ctx_destructor(struct dnotify_ctx *ctx) -{ - close(ctx->fd); - DLIST_REMOVE(dnotify_list, ctx); - return 0; -} - -static void *kernel_notify_add(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - files_struct *fsp, - uint32 *filter) -{ - struct dnotify_ctx *ctx; - - if (!(ctx = TALLOC_P(mem_ctx, struct dnotify_ctx))) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } - - ctx->fsp = fsp; - ctx->fd = kernel_register_notify(fsp->conn, fsp->fsp_name, *filter); - - if (ctx->fd == -1) { - TALLOC_FREE(ctx); - return NULL; - } - - DLIST_ADD(dnotify_list, ctx); - talloc_set_destructor(ctx, dnotify_ctx_destructor); - - return ctx; -} - -/**************************************************************************** - Setup kernel based change notify. -****************************************************************************/ - -struct cnotify_fns *kernel_notify_init(struct event_context *event_ctx) -{ - static struct cnotify_fns cnotify; - struct sigaction act; - - if (pipe(dnotify_signal_pipe) == -1) { - DEBUG(0, ("Failed to create signal pipe: %s\n", - strerror(errno))); - return NULL; - } - - if ((set_blocking(dnotify_signal_pipe[0], False) == -1) - || (set_blocking(dnotify_signal_pipe[1], False) == -1)) { - DEBUG(0, ("Failed to set signal pipe to non-blocking: %s\n", - strerror(errno))); - close(dnotify_signal_pipe[0]); - close(dnotify_signal_pipe[1]); - return NULL; - } - - if (event_add_fd(event_ctx, NULL, dnotify_signal_pipe[0], - EVENT_FD_READ, dnotify_pipe_handler, NULL) == NULL) { - DEBUG(0, ("Failed to set signal event handler\n")); - close(dnotify_signal_pipe[0]); - close(dnotify_signal_pipe[1]); - return NULL; - } - - ZERO_STRUCT(act); - - act.sa_sigaction = dnotify_signal_handler; - act.sa_flags = SA_SIGINFO; - sigemptyset( &act.sa_mask ); - if (sigaction(RT_SIGNAL_NOTIFY, &act, NULL) != 0) { - DEBUG(0,("Failed to setup RT_SIGNAL_NOTIFY handler\n")); - return NULL; - } - - if (!kernel_notify_available()) - return NULL; - - cnotify.notify_add = kernel_notify_add; - - /* the signal can start off blocked due to a bug in bash */ - BlockSignals(False, RT_SIGNAL_NOTIFY); - - return &cnotify; -} - -#else - void notify_kernel_dummy(void); - - void notify_kernel_dummy(void) {} -#endif /* HAVE_KERNEL_CHANGE_NOTIFY */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8dd4ed1925..6de620e488 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1945,8 +1945,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } - notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, - NOTIFY_ACTION_ADDED); + notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME, + name); return NT_STATUS_OK; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3c7b3c4e18..655d78cd24 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1929,9 +1929,9 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, count++; DEBUG(3,("unlink_internals: succesful unlink " "[%s]\n",fname)); - notify_action(conn, directory, dname, - FILE_NOTIFY_CHANGE_FILE_NAME, - NOTIFY_ACTION_REMOVED); + notify_fname(conn, NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME, + fname); } } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ab43bcb66f..5a3ae7f374 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1099,10 +1099,6 @@ extern void build_options(BOOL screen); if (!init_oplocks()) exit(1); - /* Setup change notify */ - if (!init_change_notify()) - exit(1); - /* Setup aio signal handler. */ initialize_async_io_handler(); -- cgit From 4e1a6ca7104cd64d336d3b4d35708b48bdee80ae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Jan 2007 19:26:46 +0000 Subject: r21097: Ensure that when manipulating UNIX permissions via the UNIX extensions we use the correct mask/force mask settings for new and existing files/directories. Bug reported by Juran David . Jeremy. (This used to be commit d84af53666369c314f02faa09b708ec6f971fa28) --- source3/smbd/trans2.c | 71 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e686acd25d..60becc95f6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1005,12 +1005,24 @@ static uint32 unix_filetype(mode_t mode) Map wire perms onto standard UNIX permissions. Obey share restrictions. ****************************************************************************/ -static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms) +enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR}; + +static NTSTATUS unix_perms_from_wire( connection_struct *conn, + SMB_STRUCT_STAT *psbuf, + uint32 perms, + enum perm_type ptype, + mode_t *ret_perms) { mode_t ret = 0; - if (perms == SMB_MODE_NO_CHANGE) - return pst->st_mode; + if (perms == SMB_MODE_NO_CHANGE) { + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_INVALID_PARAMETER; + } else { + *ret_perms = psbuf->st_mode; + return NT_STATUS_OK; + } + } ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0); ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0); @@ -1031,18 +1043,34 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0); #endif - if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) { + switch (ptype) { + case PERM_NEW_FILE: + /* Apply mode mask */ + ret &= lp_create_mask(SNUM(conn)); + /* Add in force bits */ + ret |= lp_force_create_mode(SNUM(conn)); + break; + case PERM_NEW_DIR: ret &= lp_dir_mask(SNUM(conn)); /* Add in force bits */ ret |= lp_force_dir_mode(SNUM(conn)); - } else { + break; + case PERM_EXISTING_FILE: /* Apply mode mask */ - ret &= lp_create_mask(SNUM(conn)); + ret &= lp_security_mask(SNUM(conn)); /* Add in force bits */ - ret |= lp_force_create_mode(SNUM(conn)); + ret |= lp_force_security_mode(SNUM(conn)); + break; + case PERM_EXISTING_DIR: + /* Apply mode mask */ + ret &= lp_dir_security_mask(SNUM(conn)); + /* Add in force bits */ + ret |= lp_force_dir_security_mode(SNUM(conn)); + break; } - return ret; + *ret_perms = ret; + return NT_STATUS_OK; } /**************************************************************************** @@ -4585,18 +4613,18 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn, #endif SMB_DEV_T dev = (SMB_DEV_T)0; uint32 raw_unixmode = IVAL(pdata,84); + NTSTATUS status; mode_t unixmode; if (total_data < 100) { return NT_STATUS_INVALID_PARAMETER; } - if (raw_unixmode == SMB_MODE_NO_CHANGE) { - return NT_STATUS_INVALID_PARAMETER; + status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode); + if (!NT_STATUS_IS_OK(status)) { + return status; } - unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode); - #if defined(HAVE_MAKEDEV) dev = makedev(dev_major, dev_minor); #endif @@ -4645,7 +4673,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn, } if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { - NTSTATUS status = map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); SMB_VFS_UNLINK(conn,fname); return status; } @@ -4671,6 +4699,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; NTSTATUS status = NT_STATUS_OK; BOOL delete_on_fail = False; + enum perm_type ptype; if (total_data < 100) { return NT_STATUS_INVALID_PARAMETER; @@ -4694,7 +4723,21 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, set_owner = (uid_t)IVAL(pdata,40); set_grp = (gid_t)IVAL(pdata,48); raw_unixmode = IVAL(pdata,84); - unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode); + + if (VALID_STAT(*psbuf)) { + if (S_ISDIR(psbuf->st_mode)) { + ptype = PERM_EXISTING_DIR; + } else { + ptype = PERM_EXISTING_FILE; + } + } else { + ptype = PERM_NEW_FILE; + } + + status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode); + if (!NT_STATUS_IS_OK(status)) { + return status; + } DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", -- cgit From 6b5c848e9140b95a8902f96a1d363da9feac9588 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 10:59:35 +0000 Subject: r21104: Rename struct watch_context to struct inotify_watch_context (This used to be commit 7ac79203f247ed4e41d1612ea82211db8c0cd644) --- source3/smbd/notify_inotify.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 39dc7e53e7..5fb414de4c 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -61,11 +61,11 @@ static int inotify_rm_watch(int fd, int wd) struct inotify_private { struct sys_notify_context *ctx; int fd; - struct watch_context *watches; + struct inotify_watch_context *watches; }; -struct watch_context { - struct watch_context *next, *prev; +struct inotify_watch_context { + struct inotify_watch_context *next, *prev; struct inotify_private *in; int wd; void (*callback)(struct sys_notify_context *ctx, @@ -92,7 +92,8 @@ static int inotify_destructor(struct inotify_private *in) see if a particular event from inotify really does match a requested notify event in SMB */ -static BOOL filter_match(struct watch_context *w, struct inotify_event *e) +static BOOL filter_match(struct inotify_watch_context *w, + struct inotify_event *e) { DEBUG(10, ("filter_match: e->mask=%x, w->mask=%x, w->filter=%x\n", e->mask, w->mask, w->filter)); @@ -141,7 +142,7 @@ static void inotify_dispatch(struct inotify_private *in, uint32_t prev_cookie, struct inotify_event *e2) { - struct watch_context *w, *next; + struct inotify_watch_context *w, *next; struct notify_event ne; DEBUG(10, ("inotify_dispatch called with mask=%x, name=[%s]\n", @@ -320,7 +321,7 @@ static uint32_t inotify_map(struct notify_entry *e) /* destroy a watch */ -static int watch_destructor(struct watch_context *w) +static int watch_destructor(struct inotify_watch_context *w) { struct inotify_private *in = w->in; int wd = w->wd; @@ -357,7 +358,7 @@ NTSTATUS inotify_watch(struct sys_notify_context *ctx, struct inotify_private *in; int wd; uint32_t mask; - struct watch_context *w; + struct inotify_watch_context *w; uint32_t filter = e->filter; void **handle = (void **)handle_p; @@ -391,7 +392,7 @@ NTSTATUS inotify_watch(struct sys_notify_context *ctx, DEBUG(10, ("inotify_add_watch for %s mask %x returned wd %d\n", e->path, mask, wd)); - w = talloc(in, struct watch_context); + w = talloc(in, struct inotify_watch_context); if (w == NULL) { inotify_rm_watch(in->fd, wd); e->filter = filter; -- cgit From 8b7233f19b4e294bf4174439b3acc427552dc4ee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 12:36:21 +0000 Subject: r21107: Adapt notify_fam.c to the new infrastructure. This works in my test, but does not survive the raw-notify test just because famd is too slow. Events are coming in too late and are thus unsyncronized. Now to get that through the VFS. Volker (This used to be commit c84bf6c4f92ffe3728acef7de7cefbc08307ea39) --- source3/smbd/notify_fam.c | 166 +++++++++++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 76 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c index 89bbddae24..3fa6dad162 100644 --- a/source3/smbd/notify_fam.c +++ b/source3/smbd/notify_fam.c @@ -21,7 +21,7 @@ #include "includes.h" -#if 0 +#ifdef HAVE_FAM_CHANGE_NOTIFY #include @@ -44,23 +44,30 @@ typedef enum FAMCodes FAMCodes; * http://sourceforge.net/projects/bsdfam/ */ -static void *fam_notify_add(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - files_struct *fsp, uint32 *filter); - /* ------------------------------------------------------------------------- */ -struct fam_notify_ctx { - struct fam_notify_ctx *prev, *next; +struct fam_watch_context { + struct fam_watch_context *prev, *next; FAMConnection *fam_connection; struct FAMRequest fr; - files_struct *fsp; - char *path; - uint32 filter; + struct sys_notify_context *sys_ctx; + void (*callback)(struct sys_notify_context *ctx, + void *private_data, + struct notify_event *ev); + void *private_data; + uint32_t mask; /* the inotify mask */ + uint32_t filter; /* the windows completion filter */ + const char *path; }; -static struct fam_notify_ctx *fam_notify_list; + +/* + * We want one FAM connection per smbd, not one per tcon. + */ static FAMConnection fam_connection; +static BOOL fam_connection_initialized = False; + +static struct fam_watch_context *fam_notify_list; static void fam_handler(struct event_context *event_ctx, struct fd_event *fd_event, uint16 flags, @@ -84,7 +91,7 @@ static NTSTATUS fam_open_connection(FAMConnection *fam_conn, SAFE_FREE(name); if (res < 0) { - DEBUG(5, ("FAM file change notifications not available\n")); + DEBUG(10, ("FAM file change notifications not available\n")); /* * No idea how to get NT_STATUS from a FAM result */ @@ -107,9 +114,9 @@ static NTSTATUS fam_open_connection(FAMConnection *fam_conn, static void fam_reopen(FAMConnection *fam_conn, struct event_context *event_ctx, - struct fam_notify_ctx *notify_list) + struct fam_watch_context *notify_list) { - struct fam_notify_ctx *ctx; + struct fam_watch_context *ctx; DEBUG(5, ("Re-opening FAM connection\n")); @@ -132,8 +139,8 @@ static void fam_handler(struct event_context *event_ctx, { FAMConnection *fam_conn = (FAMConnection *)private_data; FAMEvent fam_event; - struct fam_notify_ctx *ctx; - char *name; + struct fam_watch_context *ctx; + struct notify_event ne; if (FAMPending(fam_conn) == 0) { DEBUG(10, ("fam_handler called but nothing pending\n")); @@ -141,13 +148,23 @@ static void fam_handler(struct event_context *event_ctx, } if (FAMNextEvent(fam_conn, &fam_event) != 1) { - DEBUG(10, ("FAMNextEvent returned an error\n")); + DEBUG(5, ("FAMNextEvent returned an error\n")); TALLOC_FREE(fd_event); fam_reopen(fam_conn, event_ctx, fam_notify_list); return; } - if ((fam_event.code != FAMCreated) && (fam_event.code != FAMDeleted)) { + DEBUG(10, ("Got FAMCode %d for %s\n", fam_event.code, + fam_event.filename)); + + switch (fam_event.code) { + case FAMCreated: + ne.action = NOTIFY_ACTION_ADDED; + break; + case FAMDeleted: + ne.action = NOTIFY_ACTION_REMOVED; + break; + default: DEBUG(10, ("Ignoring code FAMCode %d for file %s\n", (int)fam_event.code, fam_event.filename)); return; @@ -165,17 +182,14 @@ static void fam_handler(struct event_context *event_ctx, return; } - if ((name = strrchr_m(fam_event.filename, '\\')) == NULL) { - name = fam_event.filename; + if ((ne.path = strrchr_m(fam_event.filename, '\\')) == NULL) { + ne.path = fam_event.filename; } - notify_fsp(ctx->fsp, - fam_event.code == FAMCreated - ? NOTIFY_ACTION_ADDED : NOTIFY_ACTION_REMOVED, - name); + ctx->callback(ctx->sys_ctx, ctx->private_data, &ne); } -static int fam_notify_ctx_destructor(struct fam_notify_ctx *ctx) +static int fam_watch_context_destructor(struct fam_watch_context *ctx) { if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) { FAMCancelMonitor(&fam_connection, &ctx->fr); @@ -184,86 +198,86 @@ static int fam_notify_ctx_destructor(struct fam_notify_ctx *ctx) return 0; } -static void *fam_notify_add(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - files_struct *fsp, uint32 *filter) +/* + add a watch. The watch is removed when the caller calls + talloc_free() on *handle +*/ +NTSTATUS fam_watch(struct sys_notify_context *ctx, + struct notify_entry *e, + void (*callback)(struct sys_notify_context *ctx, + void *private_data, + struct notify_event *ev), + void *private_data, + void *handle_p) { - struct fam_notify_ctx *ctx; - - if ((*filter & FILE_NOTIFY_CHANGE_FILE_NAME) == 0) { - DEBUG(10, ("filter = %u, no FILE_NOTIFY_CHANGE_FILE_NAME\n", - *filter)); - return NULL; + const uint32 fam_mask = (FILE_NOTIFY_CHANGE_FILE_NAME| + FILE_NOTIFY_CHANGE_DIR_NAME); + struct fam_watch_context *watch; + void **handle = (void **)handle_p; + + if ((e->filter & fam_mask) == 0) { + DEBUG(10, ("filter = %u, ignoring in FAM\n", e->filter)); + return NT_STATUS_OK; } - if (!(ctx = TALLOC_P(mem_ctx, struct fam_notify_ctx))) { - return NULL; + if (!fam_connection_initialized) { + if (!NT_STATUS_IS_OK(fam_open_connection(&fam_connection, + ctx->ev))) { + /* + * Just let smbd do all the work itself + */ + return NT_STATUS_OK; + } + fam_connection_initialized = True; } - ctx->fsp = fsp; - ctx->fam_connection = &fam_connection; + if (!(watch = TALLOC_P(ctx, struct fam_watch_context))) { + return NT_STATUS_NO_MEMORY; + } - /* - * The FAM module in this early state will only take care of - * FAMCreated and FAMDeleted events - */ + watch->fam_connection = &fam_connection; - ctx->filter = FILE_NOTIFY_CHANGE_FILE_NAME; + watch->callback = callback; + watch->private_data = private_data; + watch->sys_ctx = ctx; - if (!(ctx->path = talloc_asprintf(ctx, "%s/%s", fsp->conn->connectpath, - fsp->fsp_name))) { + if (!(watch->path = talloc_strdup(watch, e->path))) { DEBUG(0, ("talloc_asprintf failed\n")); - TALLOC_FREE(ctx); - return NULL; + TALLOC_FREE(watch); + return NT_STATUS_NO_MEMORY; } /* - * Leave the rest to smbd itself + * The FAM module in this early state will only take care of + * FAMCreated and FAMDeleted events, Leave the rest to + * notify_internal.c */ - *filter &= ~FILE_NOTIFY_CHANGE_FILE_NAME; + watch->filter = fam_mask; + e->filter &= ~fam_mask; - DLIST_ADD(fam_notify_list, ctx); - talloc_set_destructor(ctx, fam_notify_ctx_destructor); + DLIST_ADD(fam_notify_list, watch); + talloc_set_destructor(watch, fam_watch_context_destructor); /* * Only directories monitored so far */ - if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) { - FAMMonitorDirectory(ctx->fam_connection, ctx->path, &ctx->fr, - NULL); + if (FAMCONNECTION_GETFD(watch->fam_connection) != -1) { + FAMMonitorDirectory(watch->fam_connection, watch->path, + &watch->fr, NULL); } else { /* * If the re-open is successful, this will establish the * FAMMonitor from the list */ - fam_reopen(ctx->fam_connection, event_ctx, fam_notify_list); + fam_reopen(watch->fam_connection, ctx->ev, fam_notify_list); } - return ctx; -} - -static struct cnotify_fns global_fam_notify = -{ - fam_notify_add, -}; + *handle = (void *)watch; -struct cnotify_fns *fam_notify_init(struct event_context *event_ctx) -{ - - ZERO_STRUCT(fam_connection); - FAMCONNECTION_GETFD(&fam_connection) = -1; - - if (!NT_STATUS_IS_OK(fam_open_connection(&fam_connection, - event_ctx))) { - DEBUG(0, ("FAM file change notifications not available\n")); - return NULL; - } - - DEBUG(10, ("enabling FAM change notifications\n")); - return &global_fam_notify; + return NT_STATUS_OK; } #endif /* HAVE_FAM_CHANGE_NOTIFY */ -- cgit From 240a3fd644bbc94e5872f699c9b90649b52b98a1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 13:36:02 +0000 Subject: r21108: Send sys_notify_watch through the VFS, FAM is next (This used to be commit 603a96761391f36ae9a1c8777d3333ab5c02eb34) --- source3/smbd/notify.c | 10 ++++------ source3/smbd/notify_internal.c | 7 ++++--- source3/smbd/service.c | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5c1143a28e..8719c83bba 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -400,7 +400,7 @@ char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) return result; } -struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, +struct sys_notify_context *sys_notify_context_create(connection_struct *conn, TALLOC_CTX *mem_ctx, struct event_context *ev) { @@ -412,6 +412,7 @@ struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, } ctx->ev = ev; + ctx->conn = conn; ctx->private_data = NULL; return ctx; } @@ -423,10 +424,7 @@ NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, struct notify_event *ev), void *private_data, void *handle) { -#ifdef HAVE_INOTIFY - return inotify_watch(ctx, e, callback, private_data, handle); -#else - return NT_STATUS_OK; -#endif + return SMB_VFS_NOTIFY_WATCH(ctx->conn, ctx, e, callback, private_data, + handle); } diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 6d77ba4df6..506ad15b71 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -73,11 +73,12 @@ static int notify_destructor(struct notify_context *notify) struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, struct messaging_context *messaging_ctx, struct event_context *ev, - struct share_params *scfg) + connection_struct *conn) { struct notify_context *notify; - if (!lp_parm_bool(scfg->service, "notify", "enable", True)) { + if (!lp_parm_bool(conn->params->service, "notify", "enable", + True)) { return NULL; } @@ -107,7 +108,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, messaging_register(notify->messaging_ctx, notify, MSG_PVFS_NOTIFY, notify_handler); - notify->sys_notify_ctx = sys_notify_context_create(scfg, notify, ev); + notify->sys_notify_ctx = sys_notify_context_create(conn, notify, ev); return notify; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8dbcc2b5ab..c3bc89ec0d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -950,7 +950,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(), smbd_messaging_context(), smbd_event_context(), - conn->params); + conn); } /* ROOT Activities: */ -- cgit From 6b8fc040e56a9b3db6c060b9ab430112561f86bb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 14:31:10 +0000 Subject: r21109: Send notify_fam.c through the VFS. Lets see how the build farm likes this. Volker (This used to be commit e57a6d4d6341a52de55860e7f97031a63810dbfa) --- source3/smbd/notify_fam.c | 283 ---------------------------------------------- 1 file changed, 283 deletions(-) delete mode 100644 source3/smbd/notify_fam.c (limited to 'source3/smbd') diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c deleted file mode 100644 index 3fa6dad162..0000000000 --- a/source3/smbd/notify_fam.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * FAM file notification support. - * - * Copyright (c) James Peach 2005 - * Copyright (c) Volker Lendecke 2007 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "includes.h" - -#ifdef HAVE_FAM_CHANGE_NOTIFY - -#include - -#if !defined(HAVE_FAM_H_FAMCODES_TYPEDEF) -/* Gamin provides this typedef which means we can't use 'enum FAMCodes' as per - * every other FAM implementation. Phooey. - */ -typedef enum FAMCodes FAMCodes; -#endif - -/* NOTE: There are multiple versions of FAM floating around the net, each with - * slight differences from the original SGI FAM implementation. In this file, - * we rely only on the SGI features and do not assume any extensions. For - * example, we do not look at FAMErrno, because it is not set by the original - * implementation. - * - * Random FAM links: - * http://oss.sgi.com/projects/fam/ - * http://savannah.nongnu.org/projects/fam/ - * http://sourceforge.net/projects/bsdfam/ - */ - -/* ------------------------------------------------------------------------- */ - -struct fam_watch_context { - struct fam_watch_context *prev, *next; - FAMConnection *fam_connection; - struct FAMRequest fr; - struct sys_notify_context *sys_ctx; - void (*callback)(struct sys_notify_context *ctx, - void *private_data, - struct notify_event *ev); - void *private_data; - uint32_t mask; /* the inotify mask */ - uint32_t filter; /* the windows completion filter */ - const char *path; -}; - - -/* - * We want one FAM connection per smbd, not one per tcon. - */ -static FAMConnection fam_connection; -static BOOL fam_connection_initialized = False; - -static struct fam_watch_context *fam_notify_list; -static void fam_handler(struct event_context *event_ctx, - struct fd_event *fd_event, - uint16 flags, - void *private_data); - -static NTSTATUS fam_open_connection(FAMConnection *fam_conn, - struct event_context *event_ctx) -{ - int res; - char *name; - - ZERO_STRUCTP(fam_conn); - FAMCONNECTION_GETFD(fam_conn) = -1; - - if (asprintf(&name, "smbd (%lu)", (unsigned long)sys_getpid()) == -1) { - DEBUG(0, ("No memory\n")); - return NT_STATUS_NO_MEMORY; - } - - res = FAMOpen2(fam_conn, name); - SAFE_FREE(name); - - if (res < 0) { - DEBUG(10, ("FAM file change notifications not available\n")); - /* - * No idea how to get NT_STATUS from a FAM result - */ - FAMCONNECTION_GETFD(fam_conn) = -1; - return NT_STATUS_UNEXPECTED_IO_ERROR; - } - - if (event_add_fd(event_ctx, event_ctx, - FAMCONNECTION_GETFD(fam_conn), - EVENT_FD_READ, fam_handler, - (void *)fam_conn) == NULL) { - DEBUG(0, ("event_add_fd failed\n")); - FAMClose(fam_conn); - FAMCONNECTION_GETFD(fam_conn) = -1; - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -static void fam_reopen(FAMConnection *fam_conn, - struct event_context *event_ctx, - struct fam_watch_context *notify_list) -{ - struct fam_watch_context *ctx; - - DEBUG(5, ("Re-opening FAM connection\n")); - - FAMClose(fam_conn); - - if (!NT_STATUS_IS_OK(fam_open_connection(fam_conn, event_ctx))) { - DEBUG(5, ("Re-opening fam connection failed\n")); - return; - } - - for (ctx = notify_list; ctx; ctx = ctx->next) { - FAMMonitorDirectory(fam_conn, ctx->path, &ctx->fr, NULL); - } -} - -static void fam_handler(struct event_context *event_ctx, - struct fd_event *fd_event, - uint16 flags, - void *private_data) -{ - FAMConnection *fam_conn = (FAMConnection *)private_data; - FAMEvent fam_event; - struct fam_watch_context *ctx; - struct notify_event ne; - - if (FAMPending(fam_conn) == 0) { - DEBUG(10, ("fam_handler called but nothing pending\n")); - return; - } - - if (FAMNextEvent(fam_conn, &fam_event) != 1) { - DEBUG(5, ("FAMNextEvent returned an error\n")); - TALLOC_FREE(fd_event); - fam_reopen(fam_conn, event_ctx, fam_notify_list); - return; - } - - DEBUG(10, ("Got FAMCode %d for %s\n", fam_event.code, - fam_event.filename)); - - switch (fam_event.code) { - case FAMCreated: - ne.action = NOTIFY_ACTION_ADDED; - break; - case FAMDeleted: - ne.action = NOTIFY_ACTION_REMOVED; - break; - default: - DEBUG(10, ("Ignoring code FAMCode %d for file %s\n", - (int)fam_event.code, fam_event.filename)); - return; - } - - for (ctx = fam_notify_list; ctx; ctx = ctx->next) { - if (memcmp(&fam_event.fr, &ctx->fr, sizeof(FAMRequest)) == 0) { - break; - } - } - - if (ctx == NULL) { - DEBUG(5, ("Discarding event for file %s\n", - fam_event.filename)); - return; - } - - if ((ne.path = strrchr_m(fam_event.filename, '\\')) == NULL) { - ne.path = fam_event.filename; - } - - ctx->callback(ctx->sys_ctx, ctx->private_data, &ne); -} - -static int fam_watch_context_destructor(struct fam_watch_context *ctx) -{ - if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) { - FAMCancelMonitor(&fam_connection, &ctx->fr); - } - DLIST_REMOVE(fam_notify_list, ctx); - return 0; -} - -/* - add a watch. The watch is removed when the caller calls - talloc_free() on *handle -*/ -NTSTATUS fam_watch(struct sys_notify_context *ctx, - struct notify_entry *e, - void (*callback)(struct sys_notify_context *ctx, - void *private_data, - struct notify_event *ev), - void *private_data, - void *handle_p) -{ - const uint32 fam_mask = (FILE_NOTIFY_CHANGE_FILE_NAME| - FILE_NOTIFY_CHANGE_DIR_NAME); - struct fam_watch_context *watch; - void **handle = (void **)handle_p; - - if ((e->filter & fam_mask) == 0) { - DEBUG(10, ("filter = %u, ignoring in FAM\n", e->filter)); - return NT_STATUS_OK; - } - - if (!fam_connection_initialized) { - if (!NT_STATUS_IS_OK(fam_open_connection(&fam_connection, - ctx->ev))) { - /* - * Just let smbd do all the work itself - */ - return NT_STATUS_OK; - } - fam_connection_initialized = True; - } - - if (!(watch = TALLOC_P(ctx, struct fam_watch_context))) { - return NT_STATUS_NO_MEMORY; - } - - watch->fam_connection = &fam_connection; - - watch->callback = callback; - watch->private_data = private_data; - watch->sys_ctx = ctx; - - if (!(watch->path = talloc_strdup(watch, e->path))) { - DEBUG(0, ("talloc_asprintf failed\n")); - TALLOC_FREE(watch); - return NT_STATUS_NO_MEMORY; - } - - /* - * The FAM module in this early state will only take care of - * FAMCreated and FAMDeleted events, Leave the rest to - * notify_internal.c - */ - - watch->filter = fam_mask; - e->filter &= ~fam_mask; - - DLIST_ADD(fam_notify_list, watch); - talloc_set_destructor(watch, fam_watch_context_destructor); - - /* - * Only directories monitored so far - */ - - if (FAMCONNECTION_GETFD(watch->fam_connection) != -1) { - FAMMonitorDirectory(watch->fam_connection, watch->path, - &watch->fr, NULL); - } - else { - /* - * If the re-open is successful, this will establish the - * FAMMonitor from the list - */ - fam_reopen(watch->fam_connection, ctx->ev, fam_notify_list); - } - - *handle = (void *)watch; - - return NT_STATUS_OK; -} - -#endif /* HAVE_FAM_CHANGE_NOTIFY */ -- cgit From bad8c39f1ce48229c1ca545c03de6b7c26b7ba9f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 15:11:06 +0000 Subject: r21111: Reorganize the change notify params a bit. We now have the per-share parameters change notify = [yes]/no # do we do it at all kernel change notify = [yes]/no # enable/disable inotify Those who want FAM need to say change notify = yes vfs objects = notify_fam Volker (This used to be commit c3a44d8b9606fc516faceb69b8e87bfc8be312f3) --- source3/smbd/notify_internal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 506ad15b71..afa4e0922b 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -77,8 +77,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, { struct notify_context *notify; - if (!lp_parm_bool(conn->params->service, "notify", "enable", - True)) { + if (!lp_change_notify(conn->params)) { return NULL; } -- cgit From 69d8c5ae5f1319e3c9430aa7d6d09ca2a62ba10a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 19:29:07 +0000 Subject: r21115: notify_internal.c needs to remove the table entry if a process has crashed. So it needs the specific error message. Make messages.c return NTSTATUS and specificially NT_STATUS_INVALID_HANDLE if sending to a non-existent process. Volker (This used to be commit 3f620d181da0c356c8ffbdb5b380ccab3645a972) --- source3/smbd/open.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6de620e488..2415433fe9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -652,7 +652,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL valid_entry = False; BOOL delay_it = False; BOOL have_level2 = False; - BOOL ret; + NTSTATUS status; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; if (oplock_request & INTERNAL_OPEN_ONLY) { @@ -740,10 +740,11 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - if (!ret) { - DEBUG(3, ("Could not send oplock break message\n")); + status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not send oplock break message: %s\n", + nt_errstr(status))); } return True; -- cgit From f4c3d1543d94ea0bc6e65c9635ab9250fc9d8921 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Feb 2007 11:34:16 +0000 Subject: r21120: Make notify a bit more robust: Delete the notify records if we figured out that the process holding it is not around anymore. Tridge, please review this and possibly also include it in 4. We can discuss the error message for "unknown target" from messaging_send, INVALID_HANDLE seemed to be most appropriate to me. Volker (This used to be commit 3b3ed7429e54b571375914e473eafc9888b5b204) --- source3/smbd/notify_internal.c | 48 ++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index afa4e0922b..885c85fbc8 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -51,7 +51,8 @@ struct notify_list { #define NOTIFY_ENABLE "notify:enable" #define NOTIFY_ENABLE_DEFAULT True -static NTSTATUS notify_remove_all(struct notify_context *notify); +static NTSTATUS notify_remove_all(struct notify_context *notify, + const struct server_id *server); static void notify_handler(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data); @@ -61,7 +62,11 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data static int notify_destructor(struct notify_context *notify) { messaging_deregister(notify->messaging_ctx, MSG_PVFS_NOTIFY, notify); - notify_remove_all(notify); + + if (notify->list != NULL) { + notify_remove_all(notify, ¬ify->server); + } + return 0; } @@ -164,6 +169,11 @@ static NTSTATUS notify_load(struct notify_context *notify) status = ndr_pull_struct_blob(&blob, notify->array, notify->array, (ndr_pull_flags_fn_t)ndr_pull_notify_array); + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(notify_array, notify->array); + } + free(dbuf.dptr); return status; @@ -480,17 +490,14 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data) } /* - remove all notify watches for this messaging server + remove all notify watches for a messaging server */ -static NTSTATUS notify_remove_all(struct notify_context *notify) +static NTSTATUS notify_remove_all(struct notify_context *notify, + const struct server_id *server) { NTSTATUS status; int i, depth, del_count=0; - if (notify->list == NULL) { - return NT_STATUS_OK; - } - status = notify_lock(notify); NT_STATUS_NOT_OK_RETURN(status); @@ -501,11 +508,11 @@ static NTSTATUS notify_remove_all(struct notify_context *notify) } /* we have to search for all entries across all depths, looking for matches - for our server id */ + for the server id */ for (depth=0;deptharray->num_depths;depth++) { struct notify_depth *d = ¬ify->array->depth[depth]; for (i=0;inum_entries;i++) { - if (cluster_id_equal(¬ify->server, &d->entries[i].server)) { + if (cluster_id_equal(server, &d->entries[i].server)) { if (i < d->num_entries-1) { memmove(&d->entries[i], &d->entries[i+1], sizeof(d->entries[i])*(d->num_entries-(i+1))); @@ -530,8 +537,8 @@ static NTSTATUS notify_remove_all(struct notify_context *notify) /* send a notify message to another messaging server */ -static void notify_send(struct notify_context *notify, struct notify_entry *e, - const char *path, uint32_t action) +static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry *e, + const char *path, uint32_t action) { struct notify_event ev; DATA_BLOB data; @@ -548,12 +555,13 @@ static void notify_send(struct notify_context *notify, struct notify_entry *e, (ndr_push_flags_fn_t)ndr_push_notify_event); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); - return; + return status; } status = messaging_send(notify->messaging_ctx, e->server, MSG_PVFS_NOTIFY, &data); talloc_free(tmp_ctx); + return status; } @@ -579,6 +587,7 @@ void notify_trigger(struct notify_context *notify, return; } + again: status = notify_load(notify); if (!NT_STATUS_IS_OK(status)) { return; @@ -653,7 +662,18 @@ void notify_trigger(struct notify_context *notify, continue; } } - notify_send(notify, e, path + e->path_len + 1, action); + status = notify_send(notify, e, path + e->path_len + 1, + action); + + if (NT_STATUS_EQUAL( + status, NT_STATUS_INVALID_HANDLE)) { + + DEBUG(10, ("Deleting notify entries for " + "process %s because it's gone\n", + procid_str_static(&e->server.id))); + notify_remove_all(notify, &e->server); + goto again; + } } } } -- cgit From fd0f2e20eeb331f977be89056cb9603155b4fecd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Feb 2007 12:38:18 +0000 Subject: r21121: Fix error message, based on RAW-NOTIFY (This used to be commit 2d0a0a0b34fe4b8778d453ccfb5df6bc4534ef62) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6db6311a29..7483073a58 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1839,7 +1839,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, } if((!fsp->is_directory) || (conn != fsp->conn)) { - return ERROR_DOS(ERRDOS,ERRbadfid); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (fsp->notify == NULL) { -- cgit From 0d0e322d4d1fb1a9b1b5fb7825af093b48306826 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Feb 2007 14:55:21 +0000 Subject: r21123: Make notify_fsp() static to notify.c. Volker (This used to be commit d663b729c0b3f4265fa90a5df8534ad52b8f04eb) --- source3/smbd/notify.c | 82 +++++++++++++++++++++++++++++++++++++++++--------- source3/smbd/nttrans.c | 39 ++---------------------- 2 files changed, 71 insertions(+), 50 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 8719c83bba..cf60720bc7 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,19 @@ #include "includes.h" +struct notify_change_request { + struct notify_change_request *prev, *next; + struct files_struct *fsp; /* backpointer for cancel by mid */ + char request_buf[smb_size]; + uint32 filter; + uint32 max_param_count; + uint32 current_bufsize; + struct notify_mid_map *mid_map; + void *backend_data; +}; + +static void notify_fsp(files_struct *fsp, uint32 action, const char *name); + static struct notify_mid_map *notify_changes_by_mid; /* @@ -114,19 +127,20 @@ static void change_notify_reply_packet(const char *request_buf, } void change_notify_reply(const char *request_buf, uint32 max_param_count, - int num_changes, struct notify_change *changes) + struct notify_change_buf *notify_buf) { char *outbuf = NULL; prs_struct ps; size_t buflen = smb_size+38+max_param_count; - if (num_changes == -1) { + if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); return; } if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(num_changes, changes, &ps)) { + || !notify_marshall_changes(notify_buf->num_changes, + notify_buf->changes, &ps)) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } @@ -155,6 +169,49 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, done: SAFE_FREE(outbuf); prs_mem_free(&ps); + + TALLOC_FREE(notify_buf->changes); + notify_buf->num_changes = 0; +} + +static void notify_callback(void *private_data, const struct notify_event *e) +{ + files_struct *fsp = (files_struct *)private_data; + DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name)); + notify_fsp(fsp, e->action, e->path); +} + +NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, + BOOL recursive) +{ + char *fullpath; + struct notify_entry e; + NTSTATUS status; + + SMB_ASSERT(fsp->notify == NULL); + + if (!(fsp->notify = TALLOC_ZERO_P(NULL, struct notify_change_buf))) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath, + fsp->fsp_name) == -1) { + DEBUG(0, ("asprintf failed\n")); + return NT_STATUS_NO_MEMORY; + } + + e.path = fullpath; + e.filter = filter; + e.subdir_filter = 0; + if (recursive) { + e.subdir_filter = filter; + } + + status = notify_add(fsp->conn->notify_ctx, &e, notify_callback, fsp); + SAFE_FREE(fullpath); + + return status; } NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, @@ -175,6 +232,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); request->max_param_count = max_param_count; + request->current_bufsize = 0; request->filter = filter; request->fsp = fsp; request->backend_data = NULL; @@ -275,7 +333,7 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter, SAFE_FREE(fullpath); } -void notify_fsp(files_struct *fsp, uint32 action, const char *name) +static void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; char *name2; @@ -290,19 +348,19 @@ void notify_fsp(files_struct *fsp, uint32 action, const char *name) if (!(name2 = talloc_strdup(fsp->notify, name))) { DEBUG(0, ("talloc_strdup failed\n")); return; - } + } string_replace(name2, '/', '\\'); /* * Someone has triggered a notify previously, queue the change for - * later. TODO: Limit the number of changes queued, test how filters - * apply here. Do we have to store them? + * later. */ - if ((fsp->notify->num_changes > 30) || (name == NULL)) { + if ((fsp->notify->num_changes > 1000) || (name == NULL)) { /* - * W2k3 seems to store at most 30 changes. + * The real number depends on the client buf, just provide a + * guard against a DoS here. */ TALLOC_FREE(fsp->notify->changes); TALLOC_FREE(name2); @@ -353,13 +411,9 @@ void notify_fsp(files_struct *fsp, uint32 action, const char *name) change_notify_reply(fsp->notify->requests->request_buf, fsp->notify->requests->max_param_count, - fsp->notify->num_changes, - fsp->notify->changes); + fsp->notify); change_notify_remove_request(fsp->notify->requests); - - TALLOC_FREE(fsp->notify->changes); - fsp->notify->num_changes = 0; } char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7483073a58..543f393c89 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1787,13 +1787,6 @@ int reply_ntrename(connection_struct *conn, don't allow a directory to be opened. ****************************************************************************/ -static void notify_callback(void *private_data, const struct notify_event *e) -{ - files_struct *fsp = (files_struct *)private_data; - DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name)); - notify_fsp(fsp, e->action, e->path); -} - static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1843,33 +1836,11 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, } if (fsp->notify == NULL) { - char *fullpath; - struct notify_entry e; - - if (!(fsp->notify = TALLOC_ZERO_P( - NULL, struct notify_change_buf))) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath, - fsp->fsp_name) == -1) { - DEBUG(0, ("asprintf failed\n")); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - e.path = fullpath; - e.filter = filter; - e.subdir_filter = 0; - if (recursive) { - e.subdir_filter = filter; - } - - status = notify_add(fsp->conn->notify_ctx, &e, notify_callback, - fsp); - SAFE_FREE(fullpath); + status = change_notify_create(fsp, filter, recursive); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("notify_add returned %s\n", + DEBUG(10, ("change_notify_create returned %s\n", nt_errstr(status))); return ERROR_NT(status); } @@ -1887,11 +1858,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, */ change_notify_reply(inbuf, max_param_count, - fsp->notify->num_changes, - fsp->notify->changes); - - TALLOC_FREE(fsp->notify->changes); - fsp->notify->num_changes = 0; + fsp->notify); /* * change_notify_reply() above has independently sent its -- cgit From 685ca94ac24842fddf22e31edc39de40b0729248 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Feb 2007 22:02:42 +0000 Subject: r21128: Fix Vista connecting to Samba in share level security. Vista sends the NTLMv2 blob by default in the tconX packet. Make sure we save off the workgroup the user was logged into on the client in the sessionsetupX and re-use it for the NTLMv2 calc. Jeremy. (This used to be commit 45dcf62960c2815c4d8e0c5f4a2d0af24df83290) --- source3/smbd/password.c | 25 +++++++++++++++++++++++++ source3/smbd/sesssetup.c | 1 + 2 files changed, 26 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 38000e93f4..10cb920237 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -23,6 +23,8 @@ /* users from session setup */ static char *session_userlist = NULL; static int len_session_userlist = 0; +/* workgroup from session setup. */ +static char *session_workgroup = NULL; /* this holds info on user ids that are already validated for this VC */ static user_struct *validated_users; @@ -402,6 +404,29 @@ void add_session_user(const char *user) safe_strcat(session_userlist,suser,len_session_userlist-1); } +/**************************************************************************** + In security=share mode we need to store the client workgroup, as that's + what Vista uses for the NTLMv2 calculation. +****************************************************************************/ + +void add_session_workgroup(const char *workgroup) +{ + if (session_workgroup) { + SAFE_FREE(session_workgroup); + } + session_workgroup = smb_xstrdup(workgroup); +} + +/**************************************************************************** + In security=share mode we need to return the client workgroup, as that's + what Vista uses for the NTLMv2 calculation. +****************************************************************************/ + +const char *get_session_workgroup(void) +{ + return session_workgroup; +} + /**************************************************************************** Check if a user is in a netgroup user list. If at first we don't succeed, try lower case. diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 4d731f9c59..6c5e8f678f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1050,6 +1050,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, map_username(sub_user); add_session_user(sub_user); + add_session_workgroup(domain); /* Then force it to null for the benfit of the code below */ *user = 0; } -- cgit From 43101d6dd5bf3f4c805e3c23bf5c2a5e3c85d284 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Feb 2007 16:53:52 +0000 Subject: r21131: Some notify fixes (This used to be commit b9300e1d5acba4e2537fcc6631d1ee4d53685f64) --- source3/smbd/trans2.c | 10 ++++++++++ source3/smbd/vfs.c | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 60becc95f6..0394113408 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3779,6 +3779,11 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, const SMB_STRUCT_STAT *psbuf, struct utimbuf tvs) { + uint32 action = + FILE_NOTIFY_CHANGE_LAST_ACCESS + |FILE_NOTIFY_CHANGE_LAST_WRITE; + + if (!VALID_STAT(*psbuf)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -3786,10 +3791,12 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, /* get some defaults (no modifications) if any info is zero or -1. */ if (null_mtime(tvs.actime)) { tvs.actime = psbuf->st_atime; + action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } if (null_mtime(tvs.modtime)) { tvs.modtime = psbuf->st_mtime; + action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime))); @@ -3826,6 +3833,9 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, if(file_utime(conn, fname, &tvs)!=0) { return map_nt_error_from_unix(errno); } + if (action != 0) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname); + } return NT_STATUS_OK; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index df81b2936d..82ea602187 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -514,8 +514,13 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1) + if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1) { set_filelen_write_cache(fsp, len); + notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_SIZE + | FILE_NOTIFY_CHANGE_ATTRIBUTES, + fsp->fsp_name); + } return ret; } -- cgit From 14785319cccde0e36c07927a6a3b23f52cbfb944 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Feb 2007 23:33:53 +0000 Subject: r21166: Ensure we return the correct "EROFS" error on a non-writable filesystem. Jeremy. (This used to be commit 1e25501e8e6c568ab8892e05e0a60197e267d2b5) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cfecd7fecb..5830af8f43 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -973,7 +973,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* Does it need write permission? */ if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED); } /* IPC services are limited */ -- cgit From 6ab97dc69dab505699ef44d43a19fa7835e28751 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 Feb 2007 17:28:03 +0000 Subject: r21181: Add some debug, fix the NT_STATUS_IO_TIMEOUT problems in the RAW-NOTIFY test in the build farm. Volker (This used to be commit 3dd1bf667f42bd03a7b7159b9c2ad9ccbd269130) --- source3/smbd/notify_internal.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 885c85fbc8..72b9604935 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -171,6 +171,7 @@ static NTSTATUS notify_load(struct notify_context *notify) (ndr_pull_flags_fn_t)ndr_pull_notify_array); if (DEBUGLEVEL >= 10) { + DEBUG(10, ("notify_load:\n")); NDR_PRINT_DEBUG(notify_array, notify->array); } @@ -225,6 +226,11 @@ static NTSTATUS notify_save(struct notify_context *notify) return status; } + if (DEBUGLEVEL >= 10) { + DEBUG(10, ("notify_save:\n")); + NDR_PRINT_DEBUG(notify_array, notify->array); + } + dbuf.dptr = (char *)blob.data; dbuf.dsize = blob.length; @@ -667,11 +673,12 @@ void notify_trigger(struct notify_context *notify, if (NT_STATUS_EQUAL( status, NT_STATUS_INVALID_HANDLE)) { + struct server_id server = e->server; DEBUG(10, ("Deleting notify entries for " "process %s because it's gone\n", procid_str_static(&e->server.id))); - notify_remove_all(notify, &e->server); + notify_remove_all(notify, &server); goto again; } } -- cgit From c59a49d83b7e2e46f9d8111f1beb359095cc448e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 Feb 2007 20:07:29 +0000 Subject: r21184: Dummy checkin to let the build farm pick up r21183 of Samba4 (This used to be commit 22c9511314d563e1f4480099d2990cb5fbb8546a) --- source3/smbd/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5830af8f43..6a6da8715f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -66,8 +66,8 @@ uint16 get_current_mid(void) static struct pending_message_list *deferred_open_queue; /**************************************************************************** - Function to push a message onto the tail of a linked list of smb messages ready - for processing. + Function to push a message onto the tail of a linked list of smb messages + ready for processing. ****************************************************************************/ static BOOL push_queued_message(char *buf, int msg_len, -- cgit From 7a5fa7f12ec439ef5a4af29aa86498f799b6b9a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Feb 2007 21:05:34 +0000 Subject: r21191: Add in the POSIX open/mkdir/unlink calls. Move more error code returns to NTSTATUS. Client test code to follow... See if this passes the build-farm before I add it into 3.0.25. Jeremy. (This used to be commit 83dbbdff345fa9e427c9579183f4380004bf3dd7) --- source3/smbd/close.c | 111 +++++++++--------- source3/smbd/dir.c | 1 + source3/smbd/fake_file.c | 4 +- source3/smbd/nttrans.c | 26 +++-- source3/smbd/open.c | 109 ++++++++++++------ source3/smbd/oplock.c | 2 + source3/smbd/reply.c | 54 ++++----- source3/smbd/trans2.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 460 insertions(+), 137 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 714e0615de..05a45cc14f 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. file closing Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1992-2004. + Copyright (C) Jeremy Allison 1992-2007. Copyright (C) Volker Lendecke 2005 This program is free software; you can redistribute it and/or modify @@ -90,22 +90,21 @@ static void check_magic(files_struct *fsp,connection_struct *conn) Common code to close a file or a directory. ****************************************************************************/ -static int close_filestruct(files_struct *fsp) +static NTSTATUS close_filestruct(files_struct *fsp) { + NTSTATUS status = NT_STATUS_OK; connection_struct *conn = fsp->conn; - int ret = 0; if (fsp->fh->fd != -1) { - if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) - ret = -1; - + if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) { + status = map_nt_error_from_unix(errno); + } delete_write_cache(fsp); } conn->num_files_open--; SAFE_FREE(fsp->wbmpx_ptr); - - return ret; + return status; } /**************************************************************************** @@ -195,9 +194,13 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (delete_file) { int i; /* See if others still have the file open. If this is the - * case, then don't delete */ + * case, then don't delete. If all opens are POSIX delete now. */ for (i=0; inum_share_modes; i++) { - if (is_valid_share_mode_entry(&lck->share_modes[i])) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (is_valid_share_mode_entry(e)) { + if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { + continue; + } delete_file = False; break; } @@ -282,12 +285,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, fsp->fsp_name, strerror(errno) )); status = map_nt_error_from_unix(errno); - goto done; } - status = NT_STATUS_FILE_DELETED; - done: + /* unbecome user. */ pop_sec_ctx(); @@ -303,12 +304,13 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, delete on close is done on normal and shutdown close. ****************************************************************************/ -static int close_normal_file(files_struct *fsp, enum file_close_type close_type) +static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type) { + NTSTATUS status = NT_STATUS_OK; + NTSTATUS saved_status1 = NT_STATUS_OK; + NTSTATUS saved_status2 = NT_STATUS_OK; + NTSTATUS saved_status3 = NT_STATUS_OK; connection_struct *conn = fsp->conn; - int saved_errno = 0; - int err = 0; - int err1 = 0; if (fsp->aio_write_behind) { /* @@ -317,8 +319,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) */ int ret = wait_for_aio_completion(fsp); if (ret) { - saved_errno = ret; - err1 = -1; + saved_status1 = map_nt_error_from_unix(ret); } } else { cancel_aio_by_fsp(fsp); @@ -329,15 +330,12 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) * error here, we must remember this. */ - if (close_filestruct(fsp) == -1) { - saved_errno = errno; - err1 = -1; - } + saved_status2 = close_filestruct(fsp); if (fsp->print_file) { print_fsp_end(fsp, close_type); file_free(fsp); - return 0; + return NT_STATUS_OK; } /* If this is an old DOS or FCB open and we have multiple opens on @@ -346,7 +344,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) if (fsp->fh->ref_count == 1) { /* Should we return on error here... ? */ - close_remove_share_mode(fsp, close_type); + saved_status3 = close_remove_share_mode(fsp, close_type); } if(fsp->oplock_type) { @@ -355,13 +353,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) locking_close_file(fsp); - err = fd_close(conn, fsp); - - /* Only save errno if fd_close failed and we don't already - have an errno saved from a flush call. */ - if ((err1 != -1) && (err == -1)) { - saved_errno = errno; - } + status = fd_close(conn, fsp); /* check for magic scripts */ if (close_type == NORMAL_CLOSE) { @@ -378,29 +370,34 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type) set_filetime(conn, fsp->fsp_name, fsp->last_write_time); } + if (NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(saved_status1)) { + status = saved_status1; + } else if (!NT_STATUS_IS_OK(saved_status2)) { + status = saved_status2; + } else if (!NT_STATUS_IS_OK(saved_status3)) { + status = saved_status3; + } + } + DEBUG(2,("%s closed file %s (numopen=%d) %s\n", conn->user,fsp->fsp_name, conn->num_files_open, - (err == -1 || err1 == -1) ? strerror(saved_errno) : "")); + nt_errstr(status) )); file_free(fsp); - - if (err == -1 || err1 == -1) { - errno = saved_errno; - return saved_errno; - } else { - return 0; - } + return status; } /**************************************************************************** Close a directory opened by an NT SMB call. ****************************************************************************/ -static int close_directory(files_struct *fsp, enum file_close_type close_type) +static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type) { struct share_mode_lock *lck = 0; BOOL delete_dir = False; + NTSTATUS status = NT_STATUS_OK; /* * NT can set delete_on_close of the last open @@ -411,7 +408,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); - return EINVAL; + return NT_STATUS_INVALID_PARAMETER; } if (!del_share_mode(lck, fsp)) { @@ -441,9 +438,13 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) if (delete_dir) { int i; /* See if others still have the dir open. If this is the - * case, then don't delete */ + * case, then don't delete. If all opens are POSIX delete now. */ for (i=0; inum_share_modes; i++) { - if (is_valid_share_mode_entry(&lck->share_modes[i])) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (is_valid_share_mode_entry(e)) { + if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { + continue; + } delete_dir = False; break; } @@ -469,7 +470,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) TALLOC_FREE(lck); - ok = rmdir_internals(fsp->conn, fsp->fsp_name); + status = rmdir_internals(fsp->conn, fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", fsp->fsp_name, ok ? "succeeded" : "failed" )); @@ -482,7 +483,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) * now fail as the directory has been deleted. */ - if(ok) { + if(NT_STATUS_IS_OK(status)) { remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING); } } else { @@ -496,35 +497,35 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) */ close_filestruct(fsp); file_free(fsp); - return 0; + return status; } /**************************************************************************** Close a 'stat file' opened internally. ****************************************************************************/ -static int close_stat(files_struct *fsp) +NTSTATUS close_stat(files_struct *fsp) { /* * Do the code common to files and directories. */ close_filestruct(fsp); file_free(fsp); - return 0; + return NT_STATUS_OK; } /**************************************************************************** Close a files_struct. ****************************************************************************/ -int close_file(files_struct *fsp, enum file_close_type close_type) +NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type) { - if(fsp->is_directory) + if(fsp->is_directory) { return close_directory(fsp, close_type); - else if (fsp->is_stat) + } else if (fsp->is_stat) { return close_stat(fsp); - else if (fsp->fake_file_handle != NULL) + } else if (fsp->fake_file_handle != NULL) { return close_fake_file(fsp); - else - return close_normal_file(fsp, close_type); + } + return close_normal_file(fsp, close_type); } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 98356882aa..9f0350fe6d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -884,6 +884,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, /* no create options. */ + FILE_ATTRIBUTE_DIRECTORY, NULL, &fsp); } else { status = open_file_stat(conn, name, pst, &fsp); diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 7c5eeae5c7..208b325667 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -160,8 +160,8 @@ void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) (*fh) = NULL; } -int close_fake_file(files_struct *fsp) +NTSTATUS close_fake_file(files_struct *fsp) { file_free(fsp); - return 0; + return NT_STATUS_OK; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 543f393c89..19710d1dcd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -281,10 +281,10 @@ static BOOL saved_short_case_preserve; Save case semantics. ****************************************************************************/ -static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes) +static uint32 set_posix_case_semantics(connection_struct *conn, uint32 file_attributes) { if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { - return; + return file_attributes; } saved_case_sensitive = conn->case_sensitive; @@ -295,6 +295,8 @@ static void set_posix_case_semantics(connection_struct *conn, uint32 file_attrib conn->case_sensitive = True; conn->case_preserve = True; conn->short_case_preserve = True; + + return (file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); } /**************************************************************************** @@ -455,6 +457,7 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); + uint32 new_file_attributes; uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); @@ -625,7 +628,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * Check if POSIX semantics are wanted. */ - set_posix_case_semantics(conn, file_attributes); + new_file_attributes = set_posix_case_semantics(conn, file_attributes); status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -679,6 +682,7 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, create_disposition, create_options, + new_file_attributes, &info, &fsp); restore_case_semantics(conn, file_attributes); @@ -714,7 +718,7 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, create_disposition, create_options, - file_attributes, + new_file_attributes, oplock_request, &info, &fsp); if (!NT_STATUS_IS_OK(status)) { @@ -756,6 +760,7 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, create_disposition, create_options, + new_file_attributes, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { @@ -1096,6 +1101,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o uint32 flags; uint32 access_mask; uint32 file_attributes; + uint32 new_file_attributes; uint32 share_access; uint32 create_disposition; uint32 create_options; @@ -1252,7 +1258,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Check if POSIX semantics are wanted. */ - set_posix_case_semantics(conn, file_attributes); + new_file_attributes = set_posix_case_semantics(conn, file_attributes); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1324,6 +1330,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o share_access, create_disposition, create_options, + new_file_attributes, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); @@ -1341,7 +1348,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o share_access, create_disposition, create_options, - file_attributes, + new_file_attributes, oplock_request, &info, &fsp); @@ -1364,6 +1371,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o share_access, create_disposition, create_options, + new_file_attributes, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); @@ -1570,7 +1578,6 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new uint32 fattr; int info; SMB_OFF_T ret=-1; - int close_ret; NTSTATUS status = NT_STATUS_OK; ZERO_STRUCT(sbuf1); @@ -1670,7 +1677,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new /* Ensure the modtime is set correctly on the destination file. */ fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); - close_ret = close_file(fsp2,NORMAL_CLOSE); + status = close_file(fsp2,NORMAL_CLOSE); /* Grrr. We have to do this as open_file_ntcreate adds aARCH when it creates the file. This isn't the correct thing to do in the copy @@ -1682,8 +1689,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return NT_STATUS_DISK_FULL; } - if (close_ret != 0) { - status = map_nt_error_from_unix(close_ret); + if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("copy_internals: Error %s copy file %s to %s\n", nt_errstr(status), oldname, newname)); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2415433fe9..c9e29cf0e5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -67,14 +67,13 @@ static BOOL fd_open(struct connection_struct *conn, Close the file associated with a fsp. ****************************************************************************/ -int fd_close(struct connection_struct *conn, - files_struct *fsp) +NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp) { if (fsp->fh->fd == -1) { - return 0; /* What we used to call a stat open. */ + return NT_STATUS_OK; /* What we used to call a stat open. */ } if (fsp->fh->ref_count > 1) { - return 0; /* Shared handle. Only close last reference. */ + return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } return fd_close_posix(conn, fsp); } @@ -1118,6 +1117,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int flags2=0; BOOL file_existed = VALID_STAT(*psbuf); BOOL def_acl = False; + BOOL posix_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; @@ -1156,10 +1156,16 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_NO_MEMORY; } - /* We add aARCH to this as this mode is only used if the file is - * created new. */ - unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, - parent_dir); + if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) { + posix_open = True; + unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS); + new_dos_attributes = 0; + } else { + /* We add aARCH to this as this mode is only used if the file is + * created new. */ + unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, + parent_dir); + } DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " "access_mask=0x%x share_access=0x%x " @@ -1197,9 +1203,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; - if (file_existed) { - existing_dos_attributes = dos_mode(conn, fname, psbuf); + if (!posix_open) { + new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; + if (file_existed) { + existing_dos_attributes = dos_mode(conn, fname, psbuf); + } } /* ignore any oplock requests if oplocks are disabled */ @@ -1294,7 +1302,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* We only care about matching attributes on file exists and * overwrite. */ - if (file_existed && ((create_disposition == FILE_OVERWRITE) || + if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) || (create_disposition == FILE_OVERWRITE_IF))) { if (!open_match_attributes(conn, fname, existing_dos_attributes, @@ -1359,7 +1367,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } #endif /* O_SYNC */ - if (!CAN_WRITE(conn)) { + if (posix_open & (access_mask & FILE_APPEND_DATA)) { + flags2 |= O_APPEND; + } + + if (!posix_open && !CAN_WRITE(conn)) { /* * We should really return a permission denied error if either * O_CREAT or O_TRUNC are set, but for compatibility with @@ -1393,6 +1405,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->access_mask = open_access_mask; /* We change this to the * requested access_mask after * the open is done. */ + fsp->posix_open = posix_open; + /* Ensure no SAMBA_PRIVATE bits can be set. */ fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); @@ -1769,9 +1783,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - file_set_dosmode(conn, fname, + if (!posix_open) { + file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, parent_dir); + } } } @@ -1780,7 +1796,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * selected. */ - if (!file_existed && !def_acl) { + if (!posix_open && !file_existed && !def_acl) { int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ @@ -1873,15 +1889,17 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, Close the fchmod file fd - ensure no locks are lost. ****************************************************************************/ -int close_file_fchmod(files_struct *fsp) +NTSTATUS close_file_fchmod(files_struct *fsp) { - int ret = fd_close(fsp->conn, fsp); + NTSTATUS status = fd_close(fsp->conn, fsp); file_free(fsp); - return ret; + return status; } -static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, - SMB_STRUCT_STAT *psbuf) +static NTSTATUS mkdir_internal(connection_struct *conn, + const char *name, + uint32 file_attributes, + SMB_STRUCT_STAT *psbuf) { int ret= -1; mode_t mode; @@ -1905,7 +1923,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return NT_STATUS_NO_MEMORY; } - mode = unix_mode(conn, aDIR, name, parent_dir); + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); + } else { + mode = unix_mode(conn, aDIR, name, parent_dir); + } if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { return map_nt_error_from_unix(errno); @@ -1930,15 +1952,17 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, inherit_access_acl(conn, parent_dir, name, mode); } - /* - * Check if high bits should have been set, - * then (if bits are missing): add them. - * Consider bits automagically set by UNIX, i.e. SGID bit from parent - * dir. - */ - if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { - SMB_VFS_CHMOD(conn, name, - psbuf->st_mode | (mode & ~psbuf->st_mode)); + if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { + /* + * Check if high bits should have been set, + * then (if bits are missing): add them. + * Consider bits automagically set by UNIX, i.e. SGID bit from parent + * dir. + */ + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { + SMB_VFS_CHMOD(conn, name, + psbuf->st_mode | (mode & ~psbuf->st_mode)); + } } /* Change the owner if required. */ @@ -1963,6 +1987,7 @@ NTSTATUS open_directory(connection_struct *conn, uint32 share_access, uint32 create_disposition, uint32 create_options, + uint32 file_attributes, int *pinfo, files_struct **result) { @@ -1974,12 +1999,13 @@ NTSTATUS open_directory(connection_struct *conn, DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " "share_access = 0x%x create_options = 0x%x, " - "create_disposition = 0x%x\n", + "create_disposition = 0x%x, file_attributes = 0x%x\n", fname, (unsigned int)access_mask, (unsigned int)share_access, (unsigned int)create_options, - (unsigned int)create_disposition)); + (unsigned int)create_disposition, + (unsigned int)file_attributes)); if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); @@ -2006,7 +2032,11 @@ NTSTATUS open_directory(connection_struct *conn, /* If directory exists error. If directory doesn't * exist create. */ - status = mkdir_internal(conn, fname, psbuf); + status = mkdir_internal(conn, + fname, + file_attributes, + psbuf); + if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("open_directory: unable to create " "%s. Error was %s\n", fname, @@ -2023,7 +2053,10 @@ NTSTATUS open_directory(connection_struct *conn, * exist create. */ - status = mkdir_internal(conn, fname, psbuf); + status = mkdir_internal(conn, + fname, + file_attributes, + psbuf); if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; @@ -2081,6 +2114,8 @@ NTSTATUS open_directory(connection_struct *conn, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; fsp->is_stat = False; + fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False; + string_set(&fsp->fsp_name,fname); lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, @@ -2145,7 +2180,11 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) status = open_directory(conn, directory, &sbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ - FILE_CREATE, 0, NULL, &fsp); + FILE_CREATE, + 0, + FILE_ATTRIBUTE_DIRECTORY, + NULL, + &fsp); if (NT_STATUS_IS_OK(status)) { close_file(fsp, NORMAL_CLOSE); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 7b82a9ad9c..423d6b3a99 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -832,6 +832,7 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e) SINO_T_VAL(msg,36,e->inode); SIVAL(msg,44,e->share_file_id); SIVAL(msg,48,e->uid); + SSVAL(msg,52,e->flags); } /**************************************************************************** @@ -852,6 +853,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) e->inode = INO_T_VAL(msg,36); e->share_file_id = (unsigned long)IVAL(msg,44); e->uid = (uint32)IVAL(msg,48); + e->flags = (uint16)SVAL(msg,52); } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 655d78cd24..8bccd45f4b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3108,9 +3108,9 @@ int reply_exit(connection_struct *conn, int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { + NTSTATUS status = NT_STATUS_OK; int outsize = 0; time_t mtime; - int32 eclass = 0, err = 0; files_struct *fsp = NULL; START_PROFILE(SMBclose); @@ -3138,12 +3138,11 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Special case - close NT SMB directory handle. */ DEBUG(3,("close directory fnum=%d\n", fsp->fnum)); - close_file(fsp,NORMAL_CLOSE); + status = close_file(fsp,NORMAL_CLOSE); } else { /* * Close ordinary file. */ - int close_err; DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", fsp->fh->fd, fsp->fnum, @@ -3162,17 +3161,12 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * a disk full error. If not then it was probably an I/O error. */ - if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) { - errno = close_err; - END_PROFILE(SMBclose); - return (UNIXERROR(ERRHRD,ERRgeneral)); - } + status = close_file(fsp,NORMAL_CLOSE); } - /* We have a cached error */ - if(eclass || err) { + if(!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBclose); - return ERROR_DOS(eclass,err); + return ERROR_NT(status); } END_PROFILE(SMBclose); @@ -3189,7 +3183,7 @@ int reply_writeclose(connection_struct *conn, size_t numtowrite; ssize_t nwritten = -1; int outsize = 0; - int close_err = 0; + NTSTATUS close_status = NT_STATUS_OK; SMB_OFF_T startpos; char *data; time_t mtime; @@ -3223,7 +3217,7 @@ int reply_writeclose(connection_struct *conn, if (numtowrite) { DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n", fsp->fsp_name )); - close_err = close_file(fsp,NORMAL_CLOSE); + close_status = close_file(fsp,NORMAL_CLOSE); } DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n", @@ -3235,10 +3229,9 @@ int reply_writeclose(connection_struct *conn, return(UNIXERROR(ERRHRD,ERRdiskfull)); } - if(close_err != 0) { - errno = close_err; + if(!NT_STATUS_IS_OK(close_status)) { END_PROFILE(SMBwriteclose); - return(UNIXERROR(ERRHRD,ERRgeneral)); + return ERROR_NT(close_status); } outsize = set_message(outbuf,1,0,True); @@ -3455,7 +3448,7 @@ int reply_printclose(connection_struct *conn, { int outsize = set_message(outbuf,0,0,False); files_struct *fsp = file_fsp(inbuf,smb_vwv0); - int close_err = 0; + NTSTATUS status; START_PROFILE(SMBsplclose); CHECK_FSP(fsp,conn); @@ -3468,12 +3461,11 @@ int reply_printclose(connection_struct *conn, DEBUG(3,("printclose fd=%d fnum=%d\n", fsp->fh->fd,fsp->fnum)); - close_err = close_file(fsp,NORMAL_CLOSE); + status = close_file(fsp,NORMAL_CLOSE); - if(close_err != 0) { - errno = close_err; + if(!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsplclose); - return(UNIXERROR(ERRHRD,ERRgeneral)); + return ERROR_NT(status); } END_PROFILE(SMBsplclose); @@ -3707,7 +3699,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) The internals of the rmdir code - called elsewhere. ****************************************************************************/ -BOOL rmdir_internals(connection_struct *conn, const char *directory) +NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) { int ret; SMB_STRUCT_STAT st; @@ -3717,7 +3709,7 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_DIR_NAME, directory); - return True; + return NT_STATUS_OK; } if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { @@ -3791,14 +3783,14 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory) if (ret != 0) { DEBUG(3,("rmdir_internals: couldn't remove directory %s : " "%s\n", directory,strerror(errno))); - return False; + return map_nt_error_from_unix(errno); } notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_DIR_NAME, directory); - return True; + return NT_STATUS_OK; } /**************************************************************************** @@ -3834,9 +3826,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } dptr_closepath(directory,SVAL(inbuf,smb_pid)); - if (!rmdir_internals(conn, directory)) { + status = rmdir_internals(conn, directory); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); - return UNIXERROR(ERRDOS, ERRbadpath); + return ERROR_NT(status); } outsize = set_message(outbuf,0,0,False); @@ -4585,7 +4578,6 @@ NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun, uint32 dosattrs; uint32 new_create_disposition; NTSTATUS status; - int close_err; pstrcpy(dest,dest1); if (target_is_directory) { @@ -4670,10 +4662,10 @@ NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun, * Thus we don't look at the error return from the * close of fsp1. */ - close_err = close_file(fsp2,NORMAL_CLOSE); + status = close_file(fsp2,NORMAL_CLOSE); - if (close_err != 0) { - return map_nt_error_from_unix(close_err); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (ret != (SMB_OFF_T)src_sbuf.st_size) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0394113408..d85ed9877d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2529,7 +2529,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SBIG_UINT(pdata,4,((SMB_BIG_UINT)( CIFS_UNIX_POSIX_ACLS_CAP| CIFS_UNIX_POSIX_PATHNAMES_CAP| - CIFS_UNIX_FCNTL_LOCKS_CAP))); + CIFS_UNIX_FCNTL_LOCKS_CAP| + CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))); break; case SMB_QUERY_POSIX_FS_INFO: @@ -2646,8 +2647,14 @@ cap_low = 0x%x, cap_high = 0x%x\n", mangle_change_to_posix(); } - if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) { - lp_set_posix_cifsx_locktype(POSIX_LOCK); + if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) && + !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) { + /* Client that knows how to do posix locks, + * but not posix open/mkdir operations. Set a + * default type for read/write checks. */ + + lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK); + } break; } @@ -4845,6 +4852,246 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", tvs); } +/**************************************************************************** + Create a directory with POSIX semantics. +****************************************************************************/ + +static NTSTATUS smb_posix_mkdir(connection_struct *conn, + const char *pdata, + int total_data, + const char *fname) +{ + NTSTATUS status; + SMB_STRUCT_STAT sbuf; + uint32 raw_unixmode; + uint32 mod_unixmode; + mode_t unixmode; + files_struct *fsp; + + if (total_data < 10) { + return NT_STATUS_INVALID_PARAMETER; + } + + ZERO_STRUCT(sbuf); + + raw_unixmode = IVAL(pdata,8); + status = unix_perms_from_wire(conn, &sbuf, raw_unixmode, PERM_NEW_DIR, &unixmode); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS; + + status = open_directory(conn, + fname, + &sbuf, + FILE_READ_ATTRIBUTES, /* Just a stat open */ + FILE_SHARE_NONE, /* Ignored for stat opens */ + FILE_CREATE, + 0, + mod_unixmode, + NULL, + &fsp); + + if (NT_STATUS_IS_OK(status)) { + close_file(fsp, NORMAL_CLOSE); + } + return status; +} + +/**************************************************************************** + Open/Create a file with POSIX semantics. +****************************************************************************/ + +static NTSTATUS smb_posix_open(connection_struct *conn, + char **ppdata, + int total_data, + const char *fname, + SMB_STRUCT_STAT *psbuf, + int *pdata_return_size) +{ + BOOL extended_oplock_granted = False; + const char *pdata = *ppdata; + uint32 flags = 0; + uint32 wire_open_mode = 0; + uint32 raw_unixmode = 0; + uint32 mod_unixmode = 0; + uint32 create_disp = 0; + uint32 access_mask = 0; + uint32 create_options = 0; + NTSTATUS status = NT_STATUS_OK; + mode_t unixmode = (mode_t)0; + files_struct *fsp = NULL; + int oplock_request = 0; + int info = 0; + + if (total_data < 14) { + return NT_STATUS_INVALID_PARAMETER; + } + + flags = IVAL(pdata,0); + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + } + + wire_open_mode = IVAL(pdata,4); + + if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) { + return smb_posix_mkdir(conn, pdata, total_data, fname); + } + + switch (wire_open_mode & SMB_ACCMODE) { + case SMB_O_RDONLY: + access_mask = FILE_READ_DATA; + break; + case SMB_O_WRONLY: + access_mask = FILE_WRITE_DATA; + break; + case SMB_O_RDWR: + access_mask = FILE_READ_DATA|FILE_WRITE_DATA; + break; + default: + DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n", + (unsigned int)wire_open_mode )); + return NT_STATUS_INVALID_PARAMETER; + } + + wire_open_mode &= ~SMB_ACCMODE; + + if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) { + create_disp = FILE_CREATE; + } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) { + create_disp = FILE_OVERWRITE_IF; + } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) { + create_disp = FILE_OPEN_IF; + } else { + DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n", + (unsigned int)wire_open_mode )); + return NT_STATUS_INVALID_PARAMETER; + } + + raw_unixmode = IVAL(pdata,8); + status = unix_perms_from_wire(conn, + psbuf, + raw_unixmode, + VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE, + &unixmode); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS; + + if (wire_open_mode & SMB_O_SYNC) { + create_options |= FILE_WRITE_THROUGH; + } + if (wire_open_mode & SMB_O_APPEND) { + access_mask |= FILE_APPEND_DATA; + } + if (wire_open_mode & SMB_O_DIRECT) { + mod_unixmode |= FILE_FLAG_NO_BUFFERING; + } + + status = open_file_ntcreate(conn, + fname, + psbuf, + access_mask, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + create_disp, + 0, /* no create options yet. */ + mod_unixmode, + oplock_request, + &info, + &fsp); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { + extended_oplock_granted = True; + } + + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + extended_oplock_granted = True; + } + + *pdata_return_size = 6; + /* Realloc the data size */ + *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size); + if (*ppdata == NULL) { + close_file(fsp,ERROR_CLOSE); + return NT_STATUS_NO_MEMORY; + } + + if (extended_oplock_granted) { + if (flags & REQUEST_BATCH_OPLOCK) { + SSVAL(pdata,0, BATCH_OPLOCK_RETURN); + } else { + SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN); + } + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { + SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN); + } else { + SSVAL(pdata,0,NO_OPLOCK_RETURN); + } + + SSVAL(pdata,2,fsp->fnum); + SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + return NT_STATUS_OK; +} + +/**************************************************************************** + Delete a file with POSIX semantics. +****************************************************************************/ + +static NTSTATUS smb_posix_unlink(connection_struct *conn, + const char *pdata, + int total_data, + const char *fname, + SMB_STRUCT_STAT *psbuf) +{ + NTSTATUS status = NT_STATUS_OK; + files_struct *fsp = NULL; + int info = 0; + + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (VALID_STAT_OF_DIR(*psbuf)) { + status = open_directory(conn, + fname, + psbuf, + DELETE_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + FILE_OPEN, + FILE_DELETE_ON_CLOSE, + FILE_FLAG_POSIX_SEMANTICS|0777, + &info, + &fsp); + } else { + status = open_file_ntcreate(conn, + fname, + psbuf, + DELETE_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + FILE_OPEN, + FILE_DELETE_ON_CLOSE, + FILE_FLAG_POSIX_SEMANTICS|0777, + INTERNAL_OPEN_ONLY, + &info, + &fsp); + } + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return close_file(fsp, NORMAL_CLOSE); +} + /**************************************************************************** Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ @@ -4861,6 +5108,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char pstring fname; files_struct *fsp = NULL; NTSTATUS status = NT_STATUS_OK; + int data_return_size = 0; if (!params) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -5148,6 +5396,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_SET_POSIX_LOCK: { + if (tran_call == TRANSACT2_SETFILEINFO) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } status = smb_set_posix_lock(conn, inbuf, length, @@ -5157,6 +5408,37 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char break; } + case SMB_POSIX_PATH_OPEN: + { + if (tran_call != TRANSACT2_SETPATHINFO) { + /* We must have a pathname for this. */ + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + + status = smb_posix_open(conn, + ppdata, + total_data, + fname, + &sbuf, + &data_return_size); + break; + } + + case SMB_POSIX_PATH_UNLINK: + { + if (tran_call != TRANSACT2_SETPATHINFO) { + /* We must have a pathname for this. */ + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + + status = smb_posix_unlink(conn, + pdata, + total_data, + fname, + &sbuf); + break; + } + default: return ERROR_NT(NT_STATUS_INVALID_LEVEL); } @@ -5178,7 +5460,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes); return -1; } -- cgit From f3f1dd8879af55b675f80c10f5d7f25d65f11385 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Feb 2007 00:49:45 +0000 Subject: r21207: Make the code match the spec :-). Jeremy. (This used to be commit 36afae2d48a3c3e97d1c2c35275f99d51ba2b64a) --- source3/smbd/trans2.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d85ed9877d..e20192c3b5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4857,25 +4857,25 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", ****************************************************************************/ static NTSTATUS smb_posix_mkdir(connection_struct *conn, - const char *pdata, + char **ppdata, int total_data, - const char *fname) + const char *fname, + SMB_STRUCT_STAT *psbuf, + int *pdata_return_size) { NTSTATUS status; - SMB_STRUCT_STAT sbuf; uint32 raw_unixmode; uint32 mod_unixmode; mode_t unixmode; files_struct *fsp; + const char *pdata = *ppdata; if (total_data < 10) { return NT_STATUS_INVALID_PARAMETER; } - ZERO_STRUCT(sbuf); - raw_unixmode = IVAL(pdata,8); - status = unix_perms_from_wire(conn, &sbuf, raw_unixmode, PERM_NEW_DIR, &unixmode); + status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4884,7 +4884,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, status = open_directory(conn, fname, - &sbuf, + psbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ FILE_CREATE, @@ -4896,6 +4896,18 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { close_file(fsp, NORMAL_CLOSE); } + + *pdata_return_size = 6; + /* Realloc the data size */ + *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size); + if (*ppdata == NULL) { + return NT_STATUS_NO_MEMORY; + } + + SSVAL(pdata,0,NO_OPLOCK_RETURN); + SSVAL(pdata,2,0); + SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + return status; } @@ -4938,7 +4950,12 @@ static NTSTATUS smb_posix_open(connection_struct *conn, wire_open_mode = IVAL(pdata,4); if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) { - return smb_posix_mkdir(conn, pdata, total_data, fname); + return smb_posix_mkdir(conn, + ppdata, + total_data, + fname, + psbuf, + pdata_return_size); } switch (wire_open_mode & SMB_ACCMODE) { -- cgit From 995a9164818e67d5b82d5f4e52b347d752660d12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Feb 2007 02:39:43 +0000 Subject: r21210: Fix POSIX open to return an info level. Jeremy. (This used to be commit 5fa720f04f5d3b736145f9323aa8f4e623c14a41) --- source3/smbd/trans2.c | 150 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 96 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e20192c3b5..66f16a52bb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2864,6 +2864,61 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ } #endif +/**************************************************************************** + Store the FILE_UNIX_BASIC info. +****************************************************************************/ + +static char *store_file_unix_basic(char *pdata, + files_struct *fsp, + SMB_STRUCT_STAT *psbuf) +{ + DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n")); + DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode)); + + SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */ + pdata += 8; + + SOFF_T(pdata,0,get_allocation_size(fsp->conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ + pdata += 8; + + put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Creation Time 64 Bit */ + put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */ + put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */ + pdata += 24; + + SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,unix_filetype(psbuf->st_mode)); + pdata += 4; + + SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */ + SIVAL(pdata,4,0); + pdata += 8; + + SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */ + pdata += 8; + + SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */ + SIVAL(pdata,4,0); + pdata += 8; + + return pdata; +} + /**************************************************************************** Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by file name or file id). @@ -3469,49 +3524,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_UNIX_BASIC: - DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n")); - DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode)); - - SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */ - pdata += 8; - - SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */ - pdata += 8; - - put_long_date_timespec(pdata,get_ctimespec(&sbuf)); /* Creation Time 64 Bit */ - put_long_date_timespec(pdata+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */ - put_long_date_timespec(pdata+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */ - pdata += 24; - - SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */ - SIVAL(pdata,4,0); - pdata += 8; - - SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */ - SIVAL(pdata,4,0); - pdata += 8; - - SIVAL(pdata,0,unix_filetype(sbuf.st_mode)); - pdata += 4; - - SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */ - SIVAL(pdata,4,0); - pdata += 8; - - SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */ - SIVAL(pdata,4,0); - pdata += 8; - - SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ - pdata += 8; - - SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */ - SIVAL(pdata,4,0); - pdata += 8; - - SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */ - SIVAL(pdata,4,0); - pdata += 8; + pdata = store_file_unix_basic(pdata, fsp, &sbuf); data_size = PTR_DIFF(pdata,(*ppdata)); { @@ -4863,12 +4876,13 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, SMB_STRUCT_STAT *psbuf, int *pdata_return_size) { - NTSTATUS status; - uint32 raw_unixmode; - uint32 mod_unixmode; - mode_t unixmode; - files_struct *fsp; - const char *pdata = *ppdata; + NTSTATUS status = NT_STATUS_OK; + uint32 raw_unixmode = 0; + uint32 mod_unixmode = 0; + mode_t unixmode = (mode_t)0; + files_struct *fsp = NULL; + uint16 info_level_return = 0; + char *pdata = *ppdata; if (total_data < 10) { return NT_STATUS_INVALID_PARAMETER; @@ -4897,16 +4911,30 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, close_file(fsp, NORMAL_CLOSE); } - *pdata_return_size = 6; + info_level_return = SVAL(pdata,12); + + if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { + *pdata_return_size = 6; + } else { + *pdata_return_size = 6; + } + /* Realloc the data size */ *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size); if (*ppdata == NULL) { + *pdata_return_size = 0; return NT_STATUS_NO_MEMORY; } SSVAL(pdata,0,NO_OPLOCK_RETURN); SSVAL(pdata,2,0); - SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + + if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { + SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); + store_file_unix_basic(pdata + 6, fsp, psbuf); + } else { + SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + } return status; } @@ -4923,7 +4951,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, int *pdata_return_size) { BOOL extended_oplock_granted = False; - const char *pdata = *ppdata; + char *pdata = *ppdata; uint32 flags = 0; uint32 wire_open_mode = 0; uint32 raw_unixmode = 0; @@ -4936,6 +4964,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, files_struct *fsp = NULL; int oplock_request = 0; int info = 0; + uint16 info_level_return = 0; if (total_data < 14) { return NT_STATUS_INVALID_PARAMETER; @@ -5035,11 +5064,19 @@ static NTSTATUS smb_posix_open(connection_struct *conn, extended_oplock_granted = True; } - *pdata_return_size = 6; + info_level_return = SVAL(pdata,12); + + if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { + *pdata_return_size = 6; + } else { + *pdata_return_size = 6; + } + /* Realloc the data size */ *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size); if (*ppdata == NULL) { close_file(fsp,ERROR_CLOSE); + *pdata_return_size = 0; return NT_STATUS_NO_MEMORY; } @@ -5056,7 +5093,12 @@ static NTSTATUS smb_posix_open(connection_struct *conn, } SSVAL(pdata,2,fsp->fnum); - SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { + SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); + store_file_unix_basic(pdata + 6, fsp, psbuf); + } else { + SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + } return NT_STATUS_OK; } -- cgit From 255177d2b9c1ad358728ac15626523b5bb0ac244 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Feb 2007 19:43:44 +0000 Subject: r21223: Try and fix bug #4361 - Vista backup fails. Based on work from Joe Meadows . One for the Vista patchset. Jeremy. (This used to be commit 470a4dc30874b00c599806cb6dbc06fe2775144c) --- source3/smbd/posix_acls.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 630e270de3..50038dd464 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -658,6 +658,7 @@ static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_AC } return 0; } + /**************************************************************************** Function to create owner and group SIDs from a SMB_STRUCT_STAT. ****************************************************************************/ @@ -668,6 +669,27 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI gid_to_sid( pgroup_sid, psbuf->st_gid ); } +/**************************************************************************** + Is the identity in two ACEs equal ? Check both SID and uid/gid. +****************************************************************************/ + +static BOOL identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2) +{ + if (sid_equal(&ace1->trustee, &ace2->trustee)) { + return True; + } + if (ace1->owner_type == ace2->owner_type) { + if (ace1->owner_type == UID_ACE && + ace1->unix_ug.uid == ace2->unix_ug.uid) { + return True; + } else if (ace1->owner_type == GID_ACE && + ace1->unix_ug.gid == ace2->unix_ug.gid) { + return True; + } + } + return False; +} + /**************************************************************************** Merge aces with a common sid - if both are allow or deny, OR the permissions together and delete the second one. If the first is deny, mask the permissions off and delete the allow @@ -695,7 +717,7 @@ static void merge_aces( canon_ace **pp_list_head ) curr_ace_next = curr_ace->next; /* Save the link in case of delete. */ - if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) && + if (identity_in_ace_equal(curr_ace, curr_ace_outer) && (curr_ace->attr == curr_ace_outer->attr)) { if( DEBUGLVL( 10 )) { @@ -735,7 +757,7 @@ static void merge_aces( canon_ace **pp_list_head ) * we've put on the ACL, we know the deny must be the first one. */ - if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) && + if (identity_in_ace_equal(curr_ace, curr_ace_outer) && (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) { if( DEBUGLVL( 10 )) { -- cgit From 4901d7f10bdc34e6378964fc26aaee8289bf59e3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Feb 2007 20:20:56 +0000 Subject: r21225: Couple of fixes from Martin Zielinski mz@seh.de, one typo, one to make sure that time initialization is done before modules that depend on it (printer initialization). Jeremy. (This used to be commit 6df32b4a6a9abd40e963c188b4c8769f15a0ab9b) --- source3/smbd/server.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5a3ae7f374..ab32d656d3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -852,6 +852,8 @@ extern void build_options(BOOL screen); load_case_tables(); + TimeInit(); + #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif @@ -1102,9 +1104,6 @@ extern void build_options(BOOL screen); /* Setup aio signal handler. */ initialize_async_io_handler(); - /* re-initialise the timezone */ - TimeInit(); - /* register our message handlers */ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis, NULL); -- cgit From ffe646b1e67bc532fd954fc84cc85d21d1f4b8f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Feb 2007 22:20:31 +0000 Subject: r21226: Fix bug #4377 (rename of "foo" -> "Foo" fails). This is actually an interesting case as it exposed bad code in our DFS redirect module (that was where the bug was introduced). Caused by our turning on dfsroot be default. Jeremy. (This used to be commit 5fe25588f57ee59d70a66c755dfe70312e7afd08) --- source3/smbd/msdfs.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 42595c033e..a5cdd8130d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -261,7 +261,7 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist talloc CTX can be NULL here if reflistp and refcnt pointers are null. **********************************************************************/ -BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, char *path, +BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, const char *path, struct referral **reflistp, int *refcnt, SMB_STRUCT_STAT *sbufp) { @@ -317,11 +317,15 @@ TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp are also NULL. *****************************************************************/ -static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, - struct dfs_path *dp, - connection_struct *conn, BOOL search_flag, - struct referral **reflistpp, int *refcntp, - BOOL *self_referralp, int *consumedcntp) +static BOOL resolve_dfs_path(TALLOC_CTX *ctx, + const char *dfspath, + struct dfs_path *dp, + connection_struct *conn, + BOOL search_flag, + struct referral **reflistpp, + int *refcntp, + BOOL *self_referralp, + int *consumedcntp) { pstring localpath; int consumed_level = 1; @@ -349,12 +353,25 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); - status = unix_convert(conn, dp->reqpath, False, NULL, &sbuf); - /* Should we terminate on status != NT_STATUS_OK ???? */ + /* + * Note the unix path conversion here we're doing we can + * throw away. We're looking for a symlink for a dfs + * resolution, if we don't find it we'll do another + * unix_convert later in the codepath. + * If we needed to remember what we'd resolved in + * dp->reqpath (as the original code did) we'd + * pstrcpy(localhost, dp->reqpath) on any code + * path below that returns True - but I don't + * think this is needed. JRA. + */ - /* JRA... should we strlower the last component here.... ? */ pstrcpy(localpath, dp->reqpath); + status = unix_convert(conn, localpath, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return False; + } + /* check if need to redirect */ if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { if ( search_flag ) { @@ -371,7 +388,7 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, } /* redirect if any component in the path is a link */ - pstrcpy(reqpath, dp->reqpath); + pstrcpy(reqpath, localpath); p = strrchr_m(reqpath, '/'); while (p) { *p = '\0'; @@ -448,9 +465,10 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_ return True; } else { DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname)); - + /* Form non-dfs tcon-relative path */ pstrcpy(pathname, dp.reqpath); + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname)); return False; } -- cgit From 778f3a00f0fef879c6332abb1c965fe745d138c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Feb 2007 00:14:37 +0000 Subject: r21227: Quick fix for Stevef - ensure the returned data on open is 8 byte aligned. Jeremy. (This used to be commit 7645044fcf77644839bb0d74163d93d03284bd67) --- source3/smbd/trans2.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 66f16a52bb..bab94b1c7d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4914,9 +4914,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, info_level_return = SVAL(pdata,12); if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { - *pdata_return_size = 6; + *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE; } else { - *pdata_return_size = 6; + *pdata_return_size = 8; } /* Realloc the data size */ @@ -4931,9 +4931,11 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); - store_file_unix_basic(pdata + 6, fsp, psbuf); + SSVAL(pdata,6,0); /* Padding. */ + store_file_unix_basic(pdata + 8, fsp, psbuf); } else { SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + SSVAL(pdata,6,0); /* Padding. */ } return status; @@ -5067,9 +5069,9 @@ static NTSTATUS smb_posix_open(connection_struct *conn, info_level_return = SVAL(pdata,12); if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { - *pdata_return_size = 6; + *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE; } else { - *pdata_return_size = 6; + *pdata_return_size = 8; } /* Realloc the data size */ @@ -5095,9 +5097,11 @@ static NTSTATUS smb_posix_open(connection_struct *conn, SSVAL(pdata,2,fsp->fnum); if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); - store_file_unix_basic(pdata + 6, fsp, psbuf); + SSVAL(pdata,6,0); /* padding. */ + store_file_unix_basic(pdata + 8, fsp, psbuf); } else { SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); + SSVAL(pdata,6,0); /* padding. */ } return NT_STATUS_OK; } -- cgit From b32efe921fa9b30ed0cf527cf95ad059285b7b9d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Feb 2007 00:41:57 +0000 Subject: r21229: Don't indirect through a potentially null pointer :-). Jeremy. (This used to be commit 6723f9d85ccb4883f15658aceb021b4c4a752edf) --- source3/smbd/trans2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bab94b1c7d..103be39936 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2868,7 +2868,8 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ Store the FILE_UNIX_BASIC info. ****************************************************************************/ -static char *store_file_unix_basic(char *pdata, +static char *store_file_unix_basic(connection_struct *conn, + char *pdata, files_struct *fsp, SMB_STRUCT_STAT *psbuf) { @@ -2878,7 +2879,7 @@ static char *store_file_unix_basic(char *pdata, SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */ pdata += 8; - SOFF_T(pdata,0,get_allocation_size(fsp->conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Creation Time 64 Bit */ @@ -3524,7 +3525,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_UNIX_BASIC: - pdata = store_file_unix_basic(pdata, fsp, &sbuf); + pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf); data_size = PTR_DIFF(pdata,(*ppdata)); { @@ -4932,7 +4933,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); SSVAL(pdata,6,0); /* Padding. */ - store_file_unix_basic(pdata + 8, fsp, psbuf); + store_file_unix_basic(conn, pdata + 8, fsp, psbuf); } else { SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); SSVAL(pdata,6,0); /* Padding. */ @@ -5098,7 +5099,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); SSVAL(pdata,6,0); /* padding. */ - store_file_unix_basic(pdata + 8, fsp, psbuf); + store_file_unix_basic(conn, pdata + 8, fsp, psbuf); } else { SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); SSVAL(pdata,6,0); /* padding. */ -- cgit From e4bcfcf1c525cce78b7a22731e1a424e8cf02856 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Feb 2007 19:42:27 +0000 Subject: r21246: Remove incorrect control on unix set info. We can take path or handle based calls. Jeremy. (This used to be commit a19fe0f0c4a809d9b086e904586243949f57ec96) --- source3/smbd/trans2.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 103be39936..3bdeec0ead 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3921,7 +3921,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, return NT_STATUS_OK; } - DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", + DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n", fname, (double)size )); if (fsp && fsp->fh->fd != -1) { @@ -5392,10 +5392,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_SET_FILE_UNIX_BASIC: { - if (tran_call == TRANSACT2_SETFILEINFO) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); - } - status = smb_set_file_unix_basic(conn, pdata, total_data, @@ -5460,7 +5456,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_SET_POSIX_LOCK: { - if (tran_call == TRANSACT2_SETFILEINFO) { + if (tran_call != TRANSACT2_SETFILEINFO) { return ERROR_NT(NT_STATUS_INVALID_LEVEL); } status = smb_set_posix_lock(conn, -- cgit From 92715eaf0bf20b25d02e6265be9c960ddc9d6b03 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Feb 2007 20:31:18 +0000 Subject: r21247: In the refactoring I dropped a RESOLVE_DFSPATH call from setpathinfo. Return it and make sure all paths go through a dfs resolve. Jeremy. (This used to be commit 7fd3a146c11b70428ab5fbd7dc0272706abf8280) --- source3/smbd/trans2.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3bdeec0ead..b91cdeef70 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4168,6 +4168,7 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, char *inbuf, + char *outbuf, const char *pdata, int total_data, pstring fname) @@ -4185,6 +4186,8 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, return status; } + RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf); + DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, oldname)); @@ -4228,13 +4231,13 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return status; } + RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf); + /* Check the new name has no '/' characters. */ if (strchr_m(newname, '/')) { return NT_STATUS_NOT_SUPPORTED; } - RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf); - /* Create the base directory. */ pstrcpy(base_name, fname); p = strrchr_m(base_name, '/'); @@ -5237,6 +5240,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } + + RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); @@ -5423,6 +5429,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } status = smb_set_file_unix_hlink(conn, inbuf, + outbuf, pdata, total_data, fname); -- cgit From 7db1c6873c15e7950bf7dcc10ce3cdc7bc10248c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 8 Feb 2007 21:48:09 +0000 Subject: r21250: Partial fix for BUG 4093: Make %a expand to "Vista" based on the flags2 values in the negprot request. This also includes some code for testing the dialect strings for "SMB 2.001" but this is unreliable as Vista only sends that in the 1st negprot and caches the fact that we don't support it. Restartnig the WOrkstation service on the client clears the cache. (This used to be commit d781eeb0e4362b7af1497634d26315498a5257d4) --- source3/smbd/negprot.c | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index fec5971045..fb5610b20b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -252,6 +252,16 @@ static int reply_nt1(char *inbuf, char *outbuf) global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + /* Check the flags field to see if this is Vista. + WinXP sets it and Vista does not. But we have to + distinguish from NT which doesn't set it either. */ + + if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) && + ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) ) + { + set_remote_arch( RA_VISTA ); + } + /* do spnego in user level security if the client supports it and we can do encrypted passwords */ @@ -388,6 +398,15 @@ protocol [LM1.2X002] protocol [LANMAN2.1] protocol [NT LM 0.12] +Vista: +protocol [PC NETWORK PROGRAM 1.0] +protocol [LANMAN1.0] +protocol [Windows for Workgroups 3.1a] +protocol [LM1.2X002] +protocol [LANMAN2.1] +protocol [NT LM 0.12] +protocol [SMB 2.001] + OS/2: protocol [PC NETWORK PROGRAM 1.0] protocol [XENIX CORE] @@ -401,18 +420,19 @@ protocol [LANMAN2.1] * * This appears to be the matrix of which protocol is used by which * MS product. - Protocol WfWg Win95 WinNT Win2K OS/2 - PC NETWORK PROGRAM 1.0 1 1 1 1 1 + Protocol WfWg Win95 WinNT Win2K OS/2 Vista + PC NETWORK PROGRAM 1.0 1 1 1 1 1 1 XENIX CORE 2 2 MICROSOFT NETWORKS 3.0 2 2 DOS LM1.2X002 3 3 MICROSOFT NETWORKS 1.03 3 DOS LANMAN2.1 4 4 - LANMAN1.0 4 2 3 - Windows for Workgroups 3.1a 5 5 5 3 - LM1.2X002 6 4 4 - LANMAN2.1 7 5 5 - NT LM 0.12 6 8 6 + LANMAN1.0 4 2 3 2 + Windows for Workgroups 3.1a 5 5 5 3 3 + LM1.2X002 6 4 4 4 + LANMAN2.1 7 5 5 5 + NT LM 0.12 6 8 6 6 + SMB 2.001 7 * * tim@fsg.com 09/29/95 * Win2K added by matty 17/7/99 @@ -425,6 +445,7 @@ protocol [LANMAN2.1] #define ARCH_OS2 0x14 /* Again OS/2 is like NT */ #define ARCH_SAMBA 0x20 #define ARCH_CIFSFS 0x40 +#define ARCH_VISTA 0x8C /* Vista is like XP/2K */ #define ARCH_ALL 0x7F @@ -488,6 +509,8 @@ int reply_negprot(connection_struct *conn, arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(p,"NT LM 0.12")) arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS); + else if (strcsequal(p,"SMB 2.001")) + arch = ARCH_VISTA; else if (strcsequal(p,"LANMAN2.1")) arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(p,"LM1.2X002")) @@ -532,7 +555,13 @@ int reply_negprot(connection_struct *conn, set_remote_arch(RA_WINNT); break; case ARCH_WIN2K: - set_remote_arch(RA_WIN2K); + /* Vista may have been set in the negprot so don't + override it here */ + if ( get_remote_arch() != RA_VISTA ) + set_remote_arch(RA_WIN2K); + break; + case ARCH_VISTA: + set_remote_arch(RA_VISTA); break; case ARCH_OS2: set_remote_arch(RA_OS2); -- cgit From 5920d870cfc6be3c5bbc65ab63a6e63d1d7286f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 Feb 2007 21:57:41 +0000 Subject: r21251: Okay, after Jeremy has kindly tested this, check it in :-) Attached find a workaround that works for me. This is not the "correct" fix, to me it seems our DFS referral marshalling is broken. Vista requests level 4, we reply with level 2, and Vista seems not to like that. If we reply with level 3 it seems more happy. Needs more work! Volker (This used to be commit 4c3a9135629415086698da28596f68f7a9db9133) --- source3/smbd/msdfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a5cdd8130d..c24cdcc708 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -865,9 +865,13 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref /* create the referral depeding on version */ DEBUG(10,("max_referral_level :%d\n",max_referral_level)); - if(max_referral_level<2 || max_referral_level>3) { + + if (max_referral_level < 2) { max_referral_level = 2; } + if (max_referral_level > 3) { + max_referral_level = 3; + } switch(max_referral_level) { case 2: -- cgit From 86e5659abac9938e7ac0cea989ca33e807b3e181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Feb 2007 02:03:39 +0000 Subject: r21257: Better fix for bug #4188 : Windows Vista RC1 and RC2 can't delete directory on Samba share based on work by Joe Meadows . Jeremy. (This used to be commit 2dab8928769938ab79da7b7ce2d165fc388f9b00) --- source3/smbd/dir.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 9f0350fe6d..2795b2a24b 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1279,3 +1279,42 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) } return False; } + +/***************************************************************** + Is this directory empty ? +*****************************************************************/ + +NTSTATUS can_delete_directory(struct connection_struct *conn, + const char *dirname) +{ + NTSTATUS status = NT_STATUS_OK; + long dirpos = 0; + const char *dname; + struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0); + + if (!dir_hnd) { + return map_nt_error_from_unix(errno); + } + + while ((dname = ReadDirName(dir_hnd,&dirpos))) { + SMB_STRUCT_STAT st; + + /* Quick check for "." and ".." */ + if (dname[0] == '.') { + if (!dname[1] || (dname[1] == '.' && !dname[2])) { + continue; + } + } + + if (!is_visible_file(conn, dirname, dname, &st, True)) { + continue; + } + + DEBUG(10,("can_delete_directory: got name %s - can't delete\n", dname )); + status = NT_STATUS_DIRECTORY_NOT_EMPTY; + break; + } + CloseDir(dir_hnd); + + return status; +} -- cgit From bea1025b1aff1b4531f624524e409e601118aa8e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 10 Feb 2007 13:15:58 +0000 Subject: r21269: Reformatting (This used to be commit b2eaa733c52113f53b6ff8aea9fce20ede1e3b1f) --- source3/smbd/aio.c | 240 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 151 insertions(+), 89 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 0abc20ab7d..fd886178f6 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -49,7 +49,8 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, uint16 mid) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, + uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -77,7 +78,8 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, ui of the aio_write call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen, uint16 mid) +static struct aio_extra *create_aio_ex_write(files_struct *fsp, + size_t outbuflen, uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -92,7 +94,8 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen SAFE_FREE(aio_ex); return NULL; } - /* Steal the input buffer containing the write data from the main SMB call. */ + /* Steal the input buffer containing the write data from the main SMB + * call. */ /* We must re-allocate a new one here. */ if (NewInBuffer(&aio_ex->inbuf) == NULL) { SAFE_FREE(aio_ex->outbuf); @@ -100,7 +103,8 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen return NULL; } - /* aio_ex->inbuf now contains the stolen old InBuf containing the data to write. */ + /* aio_ex->inbuf now contains the stolen old InBuf containing the data + * to write. */ DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; @@ -214,13 +218,16 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, return False; } - /* Only do this on non-chained and non-chaining reads not using the write cache. */ - if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + /* Only do this on non-chained and non-chaining reads not using the + * write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) + || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } if (outstanding_aio_calls >= AIO_PENDING_SIZE) { - DEBUG(10,("schedule_aio_read_and_X: Already have %d aio activities outstanding.\n", + DEBUG(10,("schedule_aio_read_and_X: Already have %d aio " + "activities outstanding.\n", outstanding_aio_calls )); return False; } @@ -229,7 +236,8 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, checked smb_maxcnt is 128k or less. */ bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt; - if ((aio_ex = create_aio_ex_read(fsp, bufsize, SVAL(inbuf,smb_mid))) == NULL) { + if ((aio_ex = create_aio_ex_read(fsp, bufsize, + SVAL(inbuf,smb_mid))) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } @@ -251,14 +259,16 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_READ(fsp,a) == -1) { - DEBUG(0,("schedule_aio_read_and_X: aio_read failed. Error %s\n", - strerror(errno) )); + DEBUG(0,("schedule_aio_read_and_X: aio_read failed. " + "Error %s\n", strerror(errno) )); delete_aio_ex(aio_ex); return False; } - DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, offset %.0f, len = %u (mid = %u)\n", - fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->mid )); + DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, " + "offset %.0f, len = %u (mid = %u)\n", + fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, + (unsigned int)aio_ex->mid )); srv_defer_sign_response(aio_ex->mid); outstanding_aio_calls++; @@ -284,28 +294,36 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { /* Too small a write for aio request. */ - DEBUG(10,("schedule_aio_write_and_X: write size (%u) too small " - "for minimum aio_write of %u\n", + DEBUG(10,("schedule_aio_write_and_X: write size (%u) too " + "small for minimum aio_write of %u\n", (unsigned int)numtowrite, (unsigned int)min_aio_write_size )); return False; } - /* Only do this on non-chained and non-chaining reads not using the write cache. */ - if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + /* Only do this on non-chained and non-chaining reads not using the + * write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) + || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } if (outstanding_aio_calls >= AIO_PENDING_SIZE) { - DEBUG(3,("schedule_aio_write_and_X: Already have %d aio activities outstanding.\n", + DEBUG(3,("schedule_aio_write_and_X: Already have %d aio " + "activities outstanding.\n", outstanding_aio_calls )); - DEBUG(10,("schedule_aio_write_and_X: failed to schedule aio_write for file %s, offset %.0f, len = %u (mid = %u)\n", - fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)SVAL(inbuf,smb_mid) )); + DEBUG(10,("schedule_aio_write_and_X: failed to schedule " + "aio_write for file %s, offset %.0f, len = %u " + "(mid = %u)\n", + fsp->fsp_name, (double)startpos, + (unsigned int)numtowrite, + (unsigned int)SVAL(inbuf,smb_mid) )); return False; } outbufsize = smb_len(outbuf) + 4; - if ((aio_ex = create_aio_ex_write(fsp, outbufsize, SVAL(inbuf,smb_mid))) == NULL) { + if ((aio_ex = create_aio_ex_write(fsp, outbufsize, + SVAL(inbuf,smb_mid))) == NULL) { DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n")); return False; } @@ -322,7 +340,8 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, /* Now set up the aio record for the write call. */ a->aio_fildes = fsp->fh->fd; - a->aio_buf = data; /* As we've stolen inbuf this points within inbuf. */ + a->aio_buf = data; /* As we've stolen inbuf this points within + * inbuf. */ a->aio_nbytes = numtowrite; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; @@ -330,8 +349,8 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { - DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. Error %s\n", - strerror(errno) )); + DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. " + "Error %s\n", strerror(errno) )); /* Replace global InBuf as we're going to do a normal write. */ set_InBuffer(aio_ex->inbuf); aio_ex->inbuf = NULL; @@ -339,24 +358,29 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) { - /* Lie to the client and immediately claim we finished the write. */ + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) + && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the + * write. */ SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); show_msg(aio_ex->outbuf); if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb failed."); + exit_server_cleanly("handle_aio_write: send_smb " + "failed."); } - DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write behind for file %s\n", - fsp->fsp_name )); + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " + "behind for file %s\n", fsp->fsp_name )); } else { srv_defer_sign_response(aio_ex->mid); } outstanding_aio_calls++; - DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file %s, \ -offset %.0f, len = %u (mid = %u) outstanding_aio_calls = %d\n", - fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)aio_ex->mid, outstanding_aio_calls )); + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " + "%s, offset %.0f, len = %u (mid = %u) " + "outstanding_aio_calls = %d\n", + fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, + (unsigned int)aio_ex->mid, outstanding_aio_calls )); return True; } @@ -381,14 +405,16 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) will return an error. Hopefully this is true.... JRA. */ - /* If errno is ECANCELED then don't return anything to the client. */ + /* If errno is ECANCELED then don't return anything to the + * client. */ if (errno == ECANCELED) { srv_cancel_sign_response(aio_ex->mid); return 0; } - DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. Error = %s\n", - aio_ex->fsp->fsp_name, strerror(errno) )); + DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. " + "Error = %s\n", + aio_ex->fsp->fsp_name, strerror(errno) )); outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; @@ -400,19 +426,23 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,nread); - DEBUG( 3, ( "handle_aio_read_complete file %s max=%d nread=%d\n", - aio_ex->fsp->fsp_name, - aio_ex->acb.aio_nbytes, (int)nread ) ); + DEBUG( 3, ( "handle_aio_read_complete file %s max=%d " + "nread=%d\n", + aio_ex->fsp->fsp_name, + aio_ex->acb.aio_nbytes, (int)nread ) ); } smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("handle_aio_read_complete: send_smb failed."); + exit_server_cleanly("handle_aio_read_complete: send_smb " + "failed."); } - DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed for file %s, offset %.0f, len = %u\n", - aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)nread )); + DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed " + "for file %s, offset %.0f, len = %u\n", + aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, + (unsigned int)nread )); return ret; } @@ -433,17 +463,24 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) if (fsp->aio_write_behind) { if (nwritten != numtowrite) { if (nwritten == -1) { - DEBUG(5,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! Error %s\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(5,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); ret = errno; } else { - DEBUG(0,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! \ -Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, (int)nwritten )); + DEBUG(0,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Wanted %u bytes but " + "only wrote %d\n", fsp->fsp_name, + (unsigned int)numtowrite, + (int)nwritten )); ret = EIO; } } else { - DEBUG(10,("handle_aio_write_complete: aio_write_behind completed for file %s\n", - fsp->fsp_name )); + DEBUG(10,("handle_aio_write_complete: " + "aio_write_behind completed for file %s\n", + fsp->fsp_name )); } return 0; } @@ -452,11 +489,13 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( fixed size length when we set up the aio call. */ if(nwritten == -1) { - DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. nwritten == %d. Error = %s\n", - fsp->fsp_name, (unsigned int)numtowrite, - (int)nwritten, strerror(errno) )); + DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. " + "nwritten == %d. Error = %s\n", + fsp->fsp_name, (unsigned int)numtowrite, + (int)nwritten, strerror(errno) )); - /* If errno is ECANCELED then don't return anything to the client. */ + /* If errno is ECANCELED then don't return anything to the + * client. */ if (errno == ECANCELED) { srv_cancel_sign_response(aio_ex->mid); return 0; @@ -473,8 +512,9 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( SCVAL(outbuf,smb_rcls,ERRHRD); SSVAL(outbuf,smb_err,ERRdiskfull); } - - DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); + + DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", + fsp->fnum, (int)numtowrite, (int)nwritten)); sync_file(fsp->conn,fsp, write_through); } @@ -483,15 +523,17 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( exit_server_cleanly("handle_aio_write: send_smb failed."); } - DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed for file %s, offset %.0f, requested %u, written = %u\n", - fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)numtowrite, (unsigned int)nwritten )); + DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed " + "for file %s, offset %.0f, requested %u, written = %u\n", + fsp->fsp_name, (double)aio_ex->acb.aio_offset, + (unsigned int)numtowrite, (unsigned int)nwritten )); return ret; } /**************************************************************************** - Handle any aio completion. Returns True if finished (and sets *perr if err was non-zero), - False if not. + Handle any aio completion. Returns True if finished (and sets *perr if err + was non-zero), False if not. *****************************************************************************/ static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) @@ -500,8 +542,9 @@ static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) /* Ensure the operation has really completed. */ if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) { - DEBUG(10,( "handle_aio_completed: operation mid %u still in process for file %s\n", - aio_ex->mid, aio_ex->fsp->fsp_name )); + DEBUG(10,( "handle_aio_completed: operation mid %u still in " + "process for file %s\n", + aio_ex->mid, aio_ex->fsp->fsp_name )); return False; } @@ -530,8 +573,10 @@ int process_aio_queue(void) BlockSignals(True, RT_SIGNAL_AIO); - DEBUG(10,("process_aio_queue: signals_received = %d\n", (int)signals_received)); - DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", outstanding_aio_calls)); + DEBUG(10,("process_aio_queue: signals_received = %d\n", + (int)signals_received)); + DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", + outstanding_aio_calls)); if (!signals_received) { BlockSignals(False, RT_SIGNAL_AIO); @@ -545,16 +590,18 @@ int process_aio_queue(void) struct aio_extra *aio_ex = find_aio_ex(mid); if (!aio_ex) { - DEBUG(3,("process_aio_queue: Can't find record to match mid %u.\n", - (unsigned int)mid)); + DEBUG(3,("process_aio_queue: Can't find record to " + "match mid %u.\n", (unsigned int)mid)); srv_cancel_sign_response(mid); continue; } fsp = aio_ex->fsp; if (fsp == NULL) { - /* file was closed whilst I/O was outstanding. Just ignore. */ - DEBUG( 3,( "process_aio_queue: file closed whilst aio outstanding.\n")); + /* file was closed whilst I/O was outstanding. Just + * ignore. */ + DEBUG( 3,( "process_aio_queue: file closed whilst " + "aio outstanding.\n")); srv_cancel_sign_response(mid); continue; } @@ -573,9 +620,9 @@ int process_aio_queue(void) } /**************************************************************************** - We're doing write behind and the client closed the file. Wait up to 30 seconds - (my arbitrary choice) for the aio to complete. Return 0 if all writes completed, - errno to return if not. + We're doing write behind and the client closed the file. Wait up to 30 + seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes + completed, errno to return if not. *****************************************************************************/ #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 @@ -588,7 +635,8 @@ int wait_for_aio_completion(files_struct *fsp) time_t start_time = time(NULL); int seconds_left; - for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; seconds_left >= 0;) { + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; + seconds_left >= 0;) { int err = 0; int i; struct timespec ts; @@ -604,15 +652,18 @@ int wait_for_aio_completion(files_struct *fsp) return 0; } - DEBUG(3,("wait_for_aio_completion: waiting for %d aio events to complete.\n", - aio_completion_count )); + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " + "to complete.\n", aio_completion_count )); - aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, aio_completion_count); + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, + aio_completion_count); if (!aiocb_list) { return ENOMEM; } - for( i = 0, aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + for( i = 0, aio_ex = aio_list_head; + aio_ex; + aio_ex = aio_ex->next) { if (aio_ex->fsp == fsp) { aiocb_list[i++] = &aio_ex->acb; } @@ -622,32 +673,38 @@ int wait_for_aio_completion(files_struct *fsp) ts.tv_sec = seconds_left; ts.tv_nsec = 0; - DEBUG(10,("wait_for_aio_completion: %d events, doing a wait of %d seconds.\n", - aio_completion_count, seconds_left )); + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " + "of %d seconds.\n", + aio_completion_count, seconds_left )); - err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, aio_completion_count, &ts); + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, + aio_completion_count, &ts); - DEBUG(10,("wait_for_aio_completion: returned err = %d, errno = %s\n", - err, strerror(errno) )); + DEBUG(10,("wait_for_aio_completion: returned err = %d, " + "errno = %s\n", err, strerror(errno) )); if (err == -1 && errno == EAGAIN) { - DEBUG(0,("wait_for_aio_completion: aio_suspend timed out waiting for %d events after a wait of %d seconds\n", - aio_completion_count, seconds_left)); + DEBUG(0,("wait_for_aio_completion: aio_suspend timed " + "out waiting for %d events after a wait of " + "%d seconds\n", aio_completion_count, + seconds_left)); /* Timeout. */ cancel_aio_by_fsp(fsp); SAFE_FREE(aiocb_list); return EIO; } - /* One or more events might have completed - process them if so. */ + /* One or more events might have completed - process them if + * so. */ for( i = 0; i < aio_completion_count; i++) { uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; aio_ex = find_aio_ex(mid); if (!aio_ex) { - DEBUG(0, ("wait_for_aio_completion: mid %u doesn't match an aio record\n", - (unsigned int)mid )); + DEBUG(0, ("wait_for_aio_completion: mid %u " + "doesn't match an aio record\n", + (unsigned int)mid )); continue; } @@ -658,12 +715,15 @@ int wait_for_aio_completion(files_struct *fsp) } SAFE_FREE(aiocb_list); - seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT - (time(NULL) - start_time); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT + - (time(NULL) - start_time); } - /* We timed out - we don't know why. Return ret if already an error, else EIO. */ - DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting for %d events\n", - aio_completion_count)); + /* We timed out - we don't know why. Return ret if already an error, + * else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " + "for %d events\n", + aio_completion_count)); return EIO; } @@ -678,10 +738,12 @@ void cancel_aio_by_fsp(files_struct *fsp) for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { if (aio_ex->fsp == fsp) { - /* Don't delete the aio_extra record as we may have completed - and don't yet know it. Just do the aio_cancel call and return. */ + /* Don't delete the aio_extra record as we may have + completed and don't yet know it. Just do the + aio_cancel call and return. */ SMB_VFS_AIO_CANCEL(fsp,fsp->fh->fd, &aio_ex->acb); - aio_ex->fsp = NULL; /* fsp will be closed when we return. */ + aio_ex->fsp = NULL; /* fsp will be closed when we + * return. */ } } } -- cgit From 985a26118a3d5411e62c34aa0d62efa68465b352 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Feb 2007 04:37:56 +0000 Subject: r21274: As we now have POSIX opens which can unlink with other open files we may have taken the delete code path with more than one share mode entry - ensure we only delete once by resetting the delete on close flag. Jeremy. (This used to be commit 429dff31663e71556b5193b25d5b8e7e09fa5b9c) --- source3/smbd/close.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 05a45cc14f..eea8fa01d5 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -287,6 +287,15 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, status = map_nt_error_from_unix(errno); } + /* As we now have POSIX opens which can unlink + * with other open files we may have taken + * this code path with more than one share mode + * entry - ensure we only delete once by resetting + * the delete on close flag. JRA. + */ + + set_delete_on_close_lck(lck, False, NULL); + done: /* unbecome user. */ -- cgit From 4f5cfc9899295a5c14f734a6c92b3c902ff738d6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 13:42:48 +0000 Subject: r21277: Fix an off by one error in the signal handler for aio: We can actually receive AIO_PENDING_SIZE signals, not one less. Jeremy I'm not merging this to 3_0_25, I want you to look at it first! Volker (This used to be commit 8fd0ec58360a349826508fc361a943650fdd6694) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index fd886178f6..9425348474 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -158,7 +158,7 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE]; static void signal_handler(int sig, siginfo_t *info, void *unused) { - if (signals_received < AIO_PENDING_SIZE - 1) { + if (signals_received < AIO_PENDING_SIZE) { aio_pending_array[signals_received] = info->si_value.sival_int; signals_received++; } /* Else signal is lost. */ -- cgit From fe881c3e38bb25a6716d94df362a5580afbdfd8b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 14:07:50 +0000 Subject: r21278: The main goal of this was to get rid of the NetInBuffer / set_InBuffer. But it turns out that this patch actually speeds up the async writes considerably. I tested writing 100.000 times 65535 bytes with the allowed 10 ops in parallel. Without this patch it took about 32 seconds on my dual-core 1.6GHz laptop. With this patch it dropped to about 26 seconds. I can only explain it by better cache locality, NewInBuffer allocates more than 128k, so we jump around in memory more. Jeremy, please check! Volker (This used to be commit 452d51bc6fd41771b9c41ba6391664513d7cf2cd) --- source3/smbd/aio.c | 54 ++++++++++++-------------------------------------- source3/smbd/process.c | 40 ++----------------------------------- 2 files changed, 15 insertions(+), 79 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 9425348474..8a9fabf228 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -79,7 +79,9 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, *****************************************************************************/ static struct aio_extra *create_aio_ex_write(files_struct *fsp, - size_t outbuflen, uint16 mid) + size_t inbuflen, + size_t outbuflen, + uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -94,18 +96,13 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, SAFE_FREE(aio_ex); return NULL; } - /* Steal the input buffer containing the write data from the main SMB - * call. */ - /* We must re-allocate a new one here. */ - if (NewInBuffer(&aio_ex->inbuf) == NULL) { + + if (!(aio_ex->inbuf = SMB_MALLOC_ARRAY(char, inbuflen))) { SAFE_FREE(aio_ex->outbuf); SAFE_FREE(aio_ex); return NULL; } - /* aio_ex->inbuf now contains the stolen old InBuf containing the data - * to write. */ - DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; aio_ex->read_req = False; @@ -120,9 +117,7 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, static void delete_aio_ex(struct aio_extra *aio_ex) { DLIST_REMOVE(aio_list_head, aio_ex); - /* Safe to do as we've removed ourselves from the in use list first. */ - free_InBuffer(aio_ex->inbuf); - + SAFE_FREE(aio_ex->inbuf); SAFE_FREE(aio_ex->outbuf); SAFE_FREE(aio_ex); } @@ -288,7 +283,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, { struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; - size_t outbufsize; + size_t inbufsize, outbufsize; BOOL write_through = BITSETW(inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); @@ -321,15 +316,16 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } + inbufsize = smb_len(inbuf) + 4; outbufsize = smb_len(outbuf) + 4; - if ((aio_ex = create_aio_ex_write(fsp, outbufsize, - SVAL(inbuf,smb_mid))) == NULL) { + if (!(aio_ex = create_aio_ex_write(fsp, inbufsize, outbufsize, + SVAL(inbuf,smb_mid)))) { DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n")); return False; } - /* Paranioa.... */ - SMB_ASSERT(aio_ex->inbuf == inbuf); + /* Copy the SMB header already setup in outbuf. */ + memcpy(aio_ex->inbuf, inbuf, inbufsize); /* Copy the SMB header already setup in outbuf. */ memcpy(aio_ex->outbuf, outbuf, outbufsize); @@ -340,8 +336,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, /* Now set up the aio record for the write call. */ a->aio_fildes = fsp->fh->fd; - a->aio_buf = data; /* As we've stolen inbuf this points within - * inbuf. */ + a->aio_buf = aio_ex->inbuf + (PTR_DIFF(data, inbuf)); a->aio_nbytes = numtowrite; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; @@ -351,9 +346,6 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. " "Error %s\n", strerror(errno) )); - /* Replace global InBuf as we're going to do a normal write. */ - set_InBuffer(aio_ex->inbuf); - aio_ex->inbuf = NULL; delete_aio_ex(aio_ex); return False; } @@ -748,21 +740,6 @@ void cancel_aio_by_fsp(files_struct *fsp) } } -/**************************************************************************** - Check if a buffer was stolen for aio use. -*****************************************************************************/ - -BOOL aio_inbuffer_in_use(char *inbuf) -{ - struct aio_extra *aio_ex; - - for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { - if (aio_ex->inbuf == inbuf) { - return True; - } - } - return False; -} #else BOOL aio_finished(void) { @@ -805,9 +782,4 @@ BOOL wait_for_aio_completion(files_struct *fsp) { return True; } - -BOOL aio_inbuffer_in_use(char *ptr) -{ - return False; -} #endif diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6a6da8715f..a0e14d8445 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1463,54 +1463,18 @@ char *get_InBuffer(void) return InBuffer; } -void set_InBuffer(char *new_inbuf) -{ - InBuffer = new_inbuf; - current_inbuf = InBuffer; -} - char *get_OutBuffer(void) { return OutBuffer; } -void set_OutBuffer(char *new_outbuf) -{ - OutBuffer = new_outbuf; -} - -/**************************************************************************** - Free an InBuffer. Checks if not in use by aio system. - Must have been allocated by NewInBuffer. -****************************************************************************/ - -void free_InBuffer(char *inbuf) -{ - if (!aio_inbuffer_in_use(inbuf)) { - if (current_inbuf == inbuf) { - current_inbuf = NULL; - } - SAFE_FREE(inbuf); - } -} - -/**************************************************************************** - Free an OutBuffer. No outbuffers currently stolen by aio system. - Must have been allocated by NewInBuffer. -****************************************************************************/ - -void free_OutBuffer(char *outbuf) -{ - SAFE_FREE(outbuf); -} - const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); /**************************************************************************** Allocate a new InBuffer. Returns the new and old ones. ****************************************************************************/ -char *NewInBuffer(char **old_inbuf) +static char *NewInBuffer(char **old_inbuf) { char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size); if (!new_inbuf) { @@ -1530,7 +1494,7 @@ char *NewInBuffer(char **old_inbuf) Allocate a new OutBuffer. Returns the new and old ones. ****************************************************************************/ -char *NewOutBuffer(char **old_outbuf) +static char *NewOutBuffer(char **old_outbuf) { char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size); if (!new_outbuf) { -- cgit From d9a29aade0f01df1fa00ccdb8691b02b39bc1d14 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 14:39:21 +0000 Subject: r21279: Get rid of 'aio write behind', this is broken. It should probably better be integrated with our write cache. Volker (This used to be commit 58bfd168b046a97a895aaa3384fd7af8d077a1d5) --- source3/smbd/aio.c | 156 +------------------------------------------------ source3/smbd/close.c | 13 +---- source3/smbd/conn.c | 1 - source3/smbd/files.c | 1 - source3/smbd/open.c | 5 -- source3/smbd/service.c | 1 - 6 files changed, 2 insertions(+), 175 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 8a9fabf228..a85cf901ae 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -284,7 +284,6 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; size_t inbufsize, outbufsize; - BOOL write_through = BITSETW(inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { @@ -350,22 +349,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - if (!write_through && !lp_syncalways(SNUM(fsp->conn)) - && fsp->aio_write_behind) { - /* Lie to the client and immediately claim we finished the - * write. */ - SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); - SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); - show_msg(aio_ex->outbuf); - if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb " - "failed."); - } - DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " - "behind for file %s\n", fsp->fsp_name )); - } else { - srv_defer_sign_response(aio_ex->mid); - } + srv_defer_sign_response(aio_ex->mid); outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " @@ -452,31 +436,6 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); - if (fsp->aio_write_behind) { - if (nwritten != numtowrite) { - if (nwritten == -1) { - DEBUG(5,("handle_aio_write_complete: " - "aio_write_behind failed ! File %s " - "is corrupt ! Error %s\n", - fsp->fsp_name, strerror(errno) )); - ret = errno; - } else { - DEBUG(0,("handle_aio_write_complete: " - "aio_write_behind failed ! File %s " - "is corrupt ! Wanted %u bytes but " - "only wrote %d\n", fsp->fsp_name, - (unsigned int)numtowrite, - (int)nwritten )); - ret = EIO; - } - } else { - DEBUG(10,("handle_aio_write_complete: " - "aio_write_behind completed for file %s\n", - fsp->fsp_name )); - } - return 0; - } - /* We don't need outsize or set_message here as we've already set the fixed size length when we set up the aio call. */ @@ -611,115 +570,6 @@ int process_aio_queue(void) return ret; } -/**************************************************************************** - We're doing write behind and the client closed the file. Wait up to 30 - seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes - completed, errno to return if not. -*****************************************************************************/ - -#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 - -int wait_for_aio_completion(files_struct *fsp) -{ - struct aio_extra *aio_ex; - const SMB_STRUCT_AIOCB **aiocb_list; - int aio_completion_count = 0; - time_t start_time = time(NULL); - int seconds_left; - - for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; - seconds_left >= 0;) { - int err = 0; - int i; - struct timespec ts; - - aio_completion_count = 0; - for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { - if (aio_ex->fsp == fsp) { - aio_completion_count++; - } - } - - if (!aio_completion_count) { - return 0; - } - - DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " - "to complete.\n", aio_completion_count )); - - aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, - aio_completion_count); - if (!aiocb_list) { - return ENOMEM; - } - - for( i = 0, aio_ex = aio_list_head; - aio_ex; - aio_ex = aio_ex->next) { - if (aio_ex->fsp == fsp) { - aiocb_list[i++] = &aio_ex->acb; - } - } - - /* Now wait up to seconds_left for completion. */ - ts.tv_sec = seconds_left; - ts.tv_nsec = 0; - - DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " - "of %d seconds.\n", - aio_completion_count, seconds_left )); - - err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, - aio_completion_count, &ts); - - DEBUG(10,("wait_for_aio_completion: returned err = %d, " - "errno = %s\n", err, strerror(errno) )); - - if (err == -1 && errno == EAGAIN) { - DEBUG(0,("wait_for_aio_completion: aio_suspend timed " - "out waiting for %d events after a wait of " - "%d seconds\n", aio_completion_count, - seconds_left)); - /* Timeout. */ - cancel_aio_by_fsp(fsp); - SAFE_FREE(aiocb_list); - return EIO; - } - - /* One or more events might have completed - process them if - * so. */ - for( i = 0; i < aio_completion_count; i++) { - uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; - - aio_ex = find_aio_ex(mid); - - if (!aio_ex) { - DEBUG(0, ("wait_for_aio_completion: mid %u " - "doesn't match an aio record\n", - (unsigned int)mid )); - continue; - } - - if (!handle_aio_completed(aio_ex, &err)) { - continue; - } - delete_aio_ex(aio_ex); - } - - SAFE_FREE(aiocb_list); - seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT - - (time(NULL) - start_time); - } - - /* We timed out - we don't know why. Return ret if already an error, - * else EIO. */ - DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " - "for %d events\n", - aio_completion_count)); - - return EIO; -} - /**************************************************************************** Cancel any outstanding aio requests. The client doesn't care about the reply. *****************************************************************************/ @@ -778,8 +628,4 @@ void cancel_aio_by_fsp(files_struct *fsp) { } -BOOL wait_for_aio_completion(files_struct *fsp) -{ - return True; -} #endif diff --git a/source3/smbd/close.c b/source3/smbd/close.c index eea8fa01d5..52cd90f54a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -321,18 +321,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ NTSTATUS saved_status3 = NT_STATUS_OK; connection_struct *conn = fsp->conn; - if (fsp->aio_write_behind) { - /* - * If we're finishing write behind on a close we can get a write - * error here, we must remember this. - */ - int ret = wait_for_aio_completion(fsp); - if (ret) { - saved_status1 = map_nt_error_from_unix(ret); - } - } else { - cancel_aio_by_fsp(fsp); - } + cancel_aio_by_fsp(fsp); /* * If we're flushing on a close we can get a write diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 44888b777f..6c8267ceed 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -279,7 +279,6 @@ void conn_free_internal(connection_struct *conn) free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); - free_namearray(conn->aio_write_behind_list); string_free(&conn->user); string_free(&conn->dirpath); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index fc1700de11..fa162711ae 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -610,7 +610,6 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->modified = fsp->modified; dup_fsp->is_directory = fsp->is_directory; dup_fsp->is_stat = fsp->is_stat; - dup_fsp->aio_write_behind = fsp->aio_write_behind; string_set(&dup_fsp->fsp_name,fsp->fsp_name); *result = dup_fsp; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c9e29cf0e5..32f70eb0af 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -368,11 +368,6 @@ static NTSTATUS open_file(files_struct *fsp, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; - if (conn->aio_write_behind_list - && is_in_path(path, conn->aio_write_behind_list, - conn->case_sensitive)) { - fsp->aio_write_behind = True; - } string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c3bc89ec0d..eb464c29b2 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -772,7 +772,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->veto_list = NULL; conn->hide_list = NULL; conn->veto_oplock_list = NULL; - conn->aio_write_behind_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); -- cgit From 8a96fe6a59f0d94f55a584b3c0d052130865e533 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 14:55:21 +0000 Subject: r21280: Fix an uninitialized variable warning. Jeremy, please check. Volker (This used to be commit 4faa37a515fb6c6fa0f9364271755f954429beec) --- source3/smbd/close.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 52cd90f54a..a21399ba03 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -452,7 +452,6 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && delete_dir && lck->delete_token) { - BOOL ok; /* Become the user who requested the delete. */ @@ -470,8 +469,9 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty status = rmdir_internals(fsp->conn, fsp->fsp_name); - DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", - fsp->fsp_name, ok ? "succeeded" : "failed" )); + DEBUG(5,("close_directory: %s. Delete on close was set - " + "deleting directory returned %s.\n", + fsp->fsp_name, nt_errstr(status))); /* unbecome user. */ pop_sec_ctx(); -- cgit From a2f2653d9ae4e535384e925112745ed788e2422e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 13 Feb 2007 15:57:54 +0000 Subject: r21319: Remove functions not needed anymore (This used to be commit 0c8a364aec68bc7338d034b6f8223ec4085c9e07) --- source3/smbd/files.c | 44 -------------------------------------------- 1 file changed, 44 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index fa162711ae..0706548334 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -361,50 +361,6 @@ files_struct *file_find_di_next(files_struct *start_fsp) return NULL; } -/* - * Same as file_find_di_first/next, but also finds non-fd opens. - * - * Jeremy, do we really need the fsp->fh->fd != -1 ?? - */ - -struct files_struct *fsp_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) -{ - files_struct *fsp; - - if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { - /* Positive or negative cache hit. */ - return fsp_fi_cache.fsp; - } - - fsp_fi_cache.dev = dev; - fsp_fi_cache.inode = inode; - - for (fsp=Files;fsp;fsp=fsp->next) { - if ((fsp->dev == dev) && (fsp->inode == inode)) { - /* Setup positive cache. */ - fsp_fi_cache.fsp = fsp; - return fsp; - } - } - - /* Setup negative cache. */ - fsp_fi_cache.fsp = NULL; - return NULL; -} - -struct files_struct *fsp_find_di_next(files_struct *start_fsp) -{ - files_struct *fsp; - - for (fsp = start_fsp->next;fsp;fsp=fsp->next) { - if ( (fsp->dev == start_fsp->dev) - && (fsp->inode == start_fsp->inode) ) - return fsp; - } - - return NULL; -} - /**************************************************************************** Find a fsp that is open for printing. ****************************************************************************/ -- cgit From 5a052edf031d2c02b018743f0947a12b4df16c2d Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Wed, 14 Feb 2007 02:37:14 +0000 Subject: r21324: Add linux setlease to the vfs layer. Next round, as Volker points out, it should be abstracted a little higher up so other os'es can have an entry, but it will take a bit more work. Thanks to Chetan Shringarpure and Mathias Dietz. I didn't increment the vfs number again because the kernel change notify stuff hasn't been released yet anyway. (This used to be commit 9463211bf3b46ee408b88dfbf42d498e3839d4cc) --- source3/smbd/oplock_linux.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 518283c587..14db98cde6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -102,20 +102,29 @@ static void set_capability(unsigned capability) } } +/* + Call to set the kernel lease signal handler +*/ +int linux_set_lease_sighandler(int fd) +{ + if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) { + DEBUG(3,("Failed to set signal handler for kernel lease\n")); + return -1; + } + + return 0; +} + /**************************************************************************** Call SETLEASE. If we get EACCES then we try setting up the right capability and - try again + try again. + Use the SMB_VFS_LINUX_SETLEASE instead of this call directly. ****************************************************************************/ -static int linux_setlease(int fd, int leasetype) +int linux_setlease(int fd, int leasetype) { int ret; - if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) { - DEBUG(3,("Failed to set signal handler for kernel lease\n")); - return -1; - } - ret = fcntl(fd, F_SETLEASE, leasetype); if (ret == -1 && errno == EACCES) { set_capability(CAP_LEASE); @@ -156,7 +165,7 @@ static files_struct *linux_oplock_receive_message(fd_set *fds) static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) { + if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " "fd = %d, dev = %x, inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fh->fd, @@ -194,7 +203,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) /* * Remove the kernel oplock on this file. */ - if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) { + if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when " "removing kernel oplock on file " ); -- cgit From 29b6971da7270a119adf7ed3818f540c89814973 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Feb 2007 16:50:14 +0000 Subject: r21369: sys_disk_free return type is SMB_BIG_UINT. Fix dfree_retval to be SMB_BIG_UINT as well, otherwise we may wrap up on > 2T file systems. Simo. (This used to be commit 0bb7f6492ccf4a965d70d43ee1483959c71bcdba) --- source3/smbd/dfree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index dad7d917e8..c488add227 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -66,7 +66,7 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree, SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { - int dfree_retval; + SMB_BIG_UINT dfree_retval; SMB_BIG_UINT dfree_q = 0; SMB_BIG_UINT bsize_q = 0; SMB_BIG_UINT dsize_q = 0; -- cgit From 3057c3975cd8c38fe72a0a425decff11c177c7f9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Feb 2007 12:13:52 +0000 Subject: r21379: Attempt to fix the build on "gwen" (This used to be commit 3d85eb758d2261e0749f6db0ce368a7c0d4df149) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b91cdeef70..584345a906 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4069,7 +4069,7 @@ static NTSTATUS smb_file_position_information(connection_struct *conn, #else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) { /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; } #endif /* LARGE_SMB_OFF_T */ -- cgit From bca83e3b082d0f352d23a33a9774d5b577004bc5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 17 Feb 2007 18:47:40 +0000 Subject: r21409: saved_status1 is not used anymore after aio write behind was removed (This used to be commit 29a1892c131ed41a06d3dcfdb5d21371e60c1ba6) --- source3/smbd/close.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index a21399ba03..50111f62bb 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -318,7 +318,6 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ NTSTATUS status = NT_STATUS_OK; NTSTATUS saved_status1 = NT_STATUS_OK; NTSTATUS saved_status2 = NT_STATUS_OK; - NTSTATUS saved_status3 = NT_STATUS_OK; connection_struct *conn = fsp->conn; cancel_aio_by_fsp(fsp); @@ -328,7 +327,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ * error here, we must remember this. */ - saved_status2 = close_filestruct(fsp); + saved_status1 = close_filestruct(fsp); if (fsp->print_file) { print_fsp_end(fsp, close_type); @@ -342,7 +341,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ if (fsp->fh->ref_count == 1) { /* Should we return on error here... ? */ - saved_status3 = close_remove_share_mode(fsp, close_type); + saved_status2 = close_remove_share_mode(fsp, close_type); } if(fsp->oplock_type) { @@ -373,8 +372,6 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ status = saved_status1; } else if (!NT_STATUS_IS_OK(saved_status2)) { status = saved_status2; - } else if (!NT_STATUS_IS_OK(saved_status3)) { - status = saved_status3; } } -- cgit From f77bdcf6c71a9d0274d96298b136300d5bb05bb1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Feb 2007 06:22:20 +0000 Subject: r21460: Fix for server-side processing of SPNEGO auth fragmented into "max xmit" size security blob chunks. Bug #4400. Needs limits adding, and also a client-side version. Jeremy. (This used to be commit aa69f2481aafee5dccc3783b8a6e23ca4eb0dbfa) --- source3/smbd/password.c | 1 + source3/smbd/sesssetup.c | 226 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 217 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 10cb920237..bf4e9258ff 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -111,6 +111,7 @@ void invalidate_vuid(uint16 vuid) SAFE_FREE(vuser->groups); TALLOC_FREE(vuser->nt_user_token); + SAFE_FREE(vuser); num_validated_vuids--; } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 6c5e8f678f..9b9ae4c353 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -658,6 +658,183 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return -1; } +/**************************************************************************** + List to store partial SPNEGO auth fragments. +****************************************************************************/ + +static struct pending_auth_data *pd_list; + +/**************************************************************************** + Delete an entry on the list. +****************************************************************************/ + +static void delete_partial_auth(struct pending_auth_data *pad) +{ + DLIST_REMOVE(pd_list, pad); + data_blob_free(&pad->partial_data); + SAFE_FREE(pad); +} + +/**************************************************************************** + Search for a partial SPNEGO auth fragment matching an smbpid. +****************************************************************************/ + +static struct pending_auth_data *get_pending_auth_data(uint16 smbpid) +{ + struct pending_auth_data *pad; + + for (pad = pd_list; pad; pad = pad->next) { + if (pad->smbpid == smbpid) { + break; + } + } + return pad; +} + +/**************************************************************************** + Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED, + else return NT_STATUS_OK. +****************************************************************************/ + +static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob) +{ + struct pending_auth_data *pad; + ASN1_DATA data; + size_t needed_len = 0; + + /* Ensure we have some data. */ + if (pblob->length == 0) { + /* Caller can cope. */ + DEBUG(2,("check_spnego_blob_complete: zero blob length !\n")); + delete_partial_auth(pad); + return NT_STATUS_OK; + } + + pad = get_pending_auth_data(smbpid); + + /* Were we waiting for more data ? */ + if (pad) { + DATA_BLOB tmp_blob; + + /* Integer wrap paranoia.... */ + + if (pad->partial_data.length + pblob->length < pad->partial_data.length || + pad->partial_data.length + pblob->length < pblob->length) { + + DEBUG(2,("check_spnego_blob_complete: integer wrap " + "pad->partial_data.length = %u, " + "pblob->length = %u\n", + (unsigned int)pad->partial_data.length, + (unsigned int)pblob->length )); + + delete_partial_auth(pad); + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(10,("check_spnego_blob_complete: " + "pad->partial_data.length = %u, " + "pad->needed_len = %u, " + "pblob->length = %u,\n", + (unsigned int)pad->partial_data.length, + (unsigned int)pad->needed_len, + (unsigned int)pblob->length )); + + tmp_blob = data_blob(NULL, + pad->partial_data.length + pblob->length); + + /* Concatenate the two. */ + memcpy(tmp_blob.data, + pad->partial_data.data, + pad->partial_data.length); + memcpy(tmp_blob.data + pad->partial_data.length, + pblob->data, + pblob->length); + + /* Replace the partial data. */ + data_blob_free(&pad->partial_data); + pad->partial_data = tmp_blob; + ZERO_STRUCT(tmp_blob); + + /* Are we done ? */ + if (pblob->length >= pad->needed_len) { + /* Yes, replace pblob. */ + data_blob_free(pblob); + *pblob = pad->partial_data; + ZERO_STRUCT(pad->partial_data); + delete_partial_auth(pad); + return NT_STATUS_OK; + } + + /* Still need more data. */ + pad->needed_len -= pblob->length; + return NT_STATUS_MORE_PROCESSING_REQUIRED; + } + + if ((pblob->data[0] != ASN1_APPLICATION(0)) && + (pblob->data[0] != ASN1_CONTEXT(1))) { + /* Not something we can determine the + * length of. + */ + return NT_STATUS_OK; + } + + /* This is a new SPNEGO sessionsetup - see if + * the data given in this blob is enough. + */ + + asn1_load(&data, *pblob); + asn1_start_tag(&data, pblob->data[0]); + if (data.has_error || data.nesting == NULL) { + asn1_free(&data); + /* Let caller catch. */ + return NT_STATUS_OK; + } + + /* Integer wrap paranoia.... */ + + if (data.nesting->taglen + data.nesting->start < data.nesting->taglen || + data.nesting->taglen + data.nesting->start < data.nesting->start) { + + DEBUG(2,("check_spnego_blob_complete: integer wrap " + "data.nesting->taglen = %u, " + "data.nesting->start = %u\n", + (unsigned int)data.nesting->taglen, + (unsigned int)data.nesting->start )); + + asn1_free(&data); + return NT_STATUS_INVALID_PARAMETER; + } + + /* Total length of the needed asn1 is the tag length + * plus the current offset. */ + + needed_len = data.nesting->taglen + data.nesting->start; + asn1_free(&data); + + DEBUG(10,("check_spnego_blob_complete: needed_len = %u, " + "pblob->length = %u\n", + (unsigned int)needed_len, + (unsigned int)pblob->length )); + + if (needed_len <= pblob->length) { + /* Nothing to do - blob is complete. */ + return NT_STATUS_OK; + } + + /* We must store this blob until complete. */ + pad = SMB_MALLOC(sizeof(struct pending_auth_data)); + if (!pad) { + return NT_STATUS_NO_MEMORY; + } + pad->needed_len = needed_len - pblob->length; + pad->partial_data = data_blob(pblob->data, pblob->length); + pad->smbpid = smbpid; + pad->vuid = vuid; + DLIST_ADD(pd_list, pad); + + return NT_STATUS_MORE_PROCESSING_REQUIRED; +} + /**************************************************************************** Reply to a session setup command. conn POINTER CAN BE NULL HERE ! @@ -677,6 +854,8 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, enum remote_arch_types ra_type = get_remote_arch(); int vuid = SVAL(inbuf,smb_uid); user_struct *vuser = NULL; + NTSTATUS status = NT_STATUS_OK; + uint16 smbpid = SVAL(inbuf,smb_pid); DEBUG(3,("Doing spnego session setup\n")); @@ -715,16 +894,28 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, /* Windows 2003 doesn't set the native lanman string, but does set primary domain which is a bug I think */ - if ( !strlen(native_lanman) ) + if ( !strlen(native_lanman) ) { ra_lanman_string( primary_domain ); - else + } else { ra_lanman_string( native_lanman ); + } } vuser = get_partial_auth_user_struct(vuid); + if (!vuser) { + struct pending_auth_data *pad = get_pending_auth_data(smbpid); + if (pad) { + DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n", + (unsigned int)pad->vuid )); + vuid = pad->vuid; + vuser = get_partial_auth_user_struct(vuid); + } + } + if (!vuser) { vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL); if (vuid == UID_FIELD_INVALID ) { + data_blob_free(&blob1); return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } @@ -732,11 +923,27 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, } if (!vuser) { + data_blob_free(&blob1); return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } SSVAL(outbuf,smb_uid,vuid); - + + /* Large (greater than 4k) SPNEGO blobs are split into multiple + * sessionsetup requests as the Windows limit on the security blob + * field is 4k. Bug #4400. JRA. + */ + + status = check_spnego_blob_complete(smbpid, vuid, &blob1); + if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + /* Real error - kill the intermediate vuid */ + invalidate_vuid(vuid); + } + data_blob_free(&blob1); + return ERROR_NT(nt_status_squash(status)); + } + if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1, @@ -755,25 +962,24 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) { DATA_BLOB chal; - NTSTATUS nt_status; if (!vuser->auth_ntlmssp_state) { - nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(nt_status)) { + status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); - - return ERROR_NT(nt_status_squash(nt_status)); + data_blob_free(&blob1); + return ERROR_NT(nt_status_squash(status)); } } - nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state, + status = auth_ntlmssp_update(vuser->auth_ntlmssp_state, blob1, &chal); data_blob_free(&blob1); reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, &vuser->auth_ntlmssp_state, - &chal, nt_status, False); + &chal, status, False); data_blob_free(&chal); return -1; } -- cgit From b45442e46d595337c17829aed2d846a8c8963e6e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 20 Feb 2007 12:16:20 +0000 Subject: r21461: Not strictly necessary, as data_blob() panics if it can't allocate. But I'd see this as a design flaw in data_blob() and it made me look in that routine. Jeremy, revert or merge please :-) Volker (This used to be commit e7e6b8b5e0b00cc0746db4e9baa2e860074f903a) --- source3/smbd/sesssetup.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9b9ae4c353..6ca306ac25 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -828,6 +828,10 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB } pad->needed_len = needed_len - pblob->length; pad->partial_data = data_blob(pblob->data, pblob->length); + if (pad->partial_data.data == NULL) { + SAFE_FREE(pad); + return NT_STATUS_NO_MEMORY; + } pad->smbpid = smbpid; pad->vuid = vuid; DLIST_ADD(pd_list, pad); -- cgit From 415612949005edffa3ca05133ea5f1358f578161 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 20 Feb 2007 15:55:12 +0000 Subject: r21467: Add GPFS-provided DMAPI support based on their GPL library (This used to be commit 5876bedda51fce0c932ca0cdab074629b31a9c94) --- source3/smbd/dmapi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index b42b7d51f0..b8c23c2dce 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -40,6 +40,8 @@ BOOL dmapi_have_session(void) { return False; } #include #elif defined(HAVE_SYS_DMAPI_H) #include +#elif defined(HAVE_DMAPI_H) +#include #endif #define DMAPI_SESSION_NAME "samba" -- cgit From cedcf06b22bb30ca52a8bbb21fd331ec20ef9180 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Feb 2007 23:56:46 +0000 Subject: r21478: Add 65k length limit for split SPNEGO blobs. Jeremy (This used to be commit 6be078da267677e3e558033c28099e3932a17712) --- source3/smbd/sesssetup.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 6ca306ac25..4e27914c0d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -693,7 +693,7 @@ static struct pending_auth_data *get_pending_auth_data(uint16 smbpid) /**************************************************************************** Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED, - else return NT_STATUS_OK. + else return NT_STATUS_OK. Don't allow the blob to be more than 64k. ****************************************************************************/ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob) @@ -715,17 +715,18 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB /* Were we waiting for more data ? */ if (pad) { DATA_BLOB tmp_blob; + size_t copy_len = MIN(65536, pblob->length); /* Integer wrap paranoia.... */ - if (pad->partial_data.length + pblob->length < pad->partial_data.length || - pad->partial_data.length + pblob->length < pblob->length) { + if (pad->partial_data.length + copy_len < pad->partial_data.length || + pad->partial_data.length + copy_len < copy_len) { DEBUG(2,("check_spnego_blob_complete: integer wrap " "pad->partial_data.length = %u, " - "pblob->length = %u\n", + "copy_len = %u\n", (unsigned int)pad->partial_data.length, - (unsigned int)pblob->length )); + (unsigned int)copy_len )); delete_partial_auth(pad); return NT_STATUS_INVALID_PARAMETER; @@ -734,21 +735,23 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB DEBUG(10,("check_spnego_blob_complete: " "pad->partial_data.length = %u, " "pad->needed_len = %u, " + "copy_len = %u, " "pblob->length = %u,\n", (unsigned int)pad->partial_data.length, (unsigned int)pad->needed_len, + (unsigned int)copy_len, (unsigned int)pblob->length )); tmp_blob = data_blob(NULL, - pad->partial_data.length + pblob->length); + pad->partial_data.length + copy_len); - /* Concatenate the two. */ + /* Concatenate the two (up to copy_len) bytes. */ memcpy(tmp_blob.data, pad->partial_data.data, pad->partial_data.length); memcpy(tmp_blob.data + pad->partial_data.length, pblob->data, - pblob->length); + copy_len); /* Replace the partial data. */ data_blob_free(&pad->partial_data); @@ -766,7 +769,7 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB } /* Still need more data. */ - pad->needed_len -= pblob->length; + pad->needed_len -= copy_len; return NT_STATUS_MORE_PROCESSING_REQUIRED; } @@ -821,6 +824,13 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB return NT_STATUS_OK; } + /* Refuse the blob if it's bigger than 64k. */ + if (needed_len > 65536) { + DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n", + (unsigned int)needed_len )); + return NT_STATUS_INVALID_PARAMETER; + } + /* We must store this blob until complete. */ pad = SMB_MALLOC(sizeof(struct pending_auth_data)); if (!pad) { -- cgit From a9dbdf937c4901c4e791bff0753bafe709bc0fa5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Feb 2007 01:55:08 +0000 Subject: r21480: Make fd_open match fd_close be translating errno into an NTSTATUS immediately. Jeremy. (This used to be commit 71dd02cc164197152e76d8141f906390c4bd1526) --- source3/smbd/open.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 32f70eb0af..f03c8216d4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,13 +38,13 @@ struct deferred_open_record { fd support routines - attempt to do a dos_open. ****************************************************************************/ -static BOOL fd_open(struct connection_struct *conn, +static NTSTATUS fd_open(struct connection_struct *conn, const char *fname, files_struct *fsp, int flags, mode_t mode) { - int sav; + NTSTATUS status = NT_STATUS_OK; #ifdef O_NOFOLLOW if (!lp_symlinks(SNUM(conn))) { @@ -53,14 +53,15 @@ static BOOL fd_open(struct connection_struct *conn, #endif fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); - sav = errno; + if (fsp->fh->fd == -1) { + status = map_nt_error_from_unix(errno); + } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, flags, (int)mode, fsp->fh->fd, (fsp->fh->fd == -1) ? strerror(errno) : "" )); - errno = sav; - return fsp->fh->fd != -1; + return status; } /**************************************************************************** @@ -205,6 +206,7 @@ static NTSTATUS open_file(files_struct *fsp, uint32 access_mask, /* client requested access mask. */ uint32 open_access_mask) /* what we're actually using in the open. */ { + NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); int local_flags = flags; BOOL file_existed = VALID_STAT(*psbuf); @@ -287,11 +289,12 @@ static NTSTATUS open_file(files_struct *fsp, } /* Actually do the open */ - if (!fd_open(conn, path, fsp, local_flags, unx_mode)) { + status = fd_open(conn, path, fsp, local_flags, unx_mode); + if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", - path,strerror(errno),local_flags,flags)); - return map_nt_error_from_unix(errno); + path,nt_errstr(status),local_flags,flags)); + return status; } if ((local_flags & O_CREAT) && !file_existed) { @@ -332,7 +335,7 @@ static NTSTATUS open_file(files_struct *fsp, /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { - NTSTATUS status = map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); fd_close(conn, fsp); return status; } -- cgit From 01ecda0534a4a7f2a9fe492f1accbcec7552e8d1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Feb 2007 02:04:28 +0000 Subject: r21481: No one said anything, so I'm disallowing anything but explicit shares in "default service" :-). Jeremy. (This used to be commit 90bdcce765998cc0f5768d24926d52b8a4a44f90) --- source3/smbd/service.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index eb464c29b2..1b8e2e1d30 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -402,6 +402,13 @@ int find_service(fstring service) if (iService < 0) { } + /* Is it a usershare service ? */ + if (iService < 0 && *lp_usershare_path()) { + /* Ensure the name is canonicalized. */ + strlower_m(service); + iService = load_usershare_service(service); + } + /* just possibly it's a default service? */ if (iService < 0) { char *pdefservice = lp_defaultservice(); @@ -414,6 +421,14 @@ int find_service(fstring service) */ pstring defservice; pstrcpy(defservice, pdefservice); + + /* Disallow anything except explicit share names. */ + if (strequal(defservice,HOMES_NAME) || + strequal(defservice, PRINTERS_NAME) || + strequal(defservice, "ipc$")) { + goto fail; + } + iService = find_service(defservice); if (iService >= 0) { all_string_sub(service, "_","/",0); @@ -426,13 +441,6 @@ int find_service(fstring service) iService = load_registry_service(service); } - /* Is it a usershare service ? */ - if (iService < 0 && *lp_usershare_path()) { - /* Ensure the name is canonicalized. */ - strlower_m(service); - iService = load_usershare_service(service); - } - if (iService >= 0) { if (!VALID_SNUM(iService)) { DEBUG(0,("Invalid snum %d for %s\n",iService, service)); @@ -440,6 +448,8 @@ int find_service(fstring service) } } + fail: + if (iService < 0) DEBUG(3,("find_service() failed to find service %s\n", service)); -- cgit From 2afcdc8732bbf7364c57a9d10d432684d1f4f037 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Feb 2007 02:11:06 +0000 Subject: r21482: Use IPC$ not ipc$ for consistency. Jeremy. (This used to be commit 42a846b3dfa50eea6592c6bb425f7bdb672c25f9) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1b8e2e1d30..de2bfd9100 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -425,7 +425,7 @@ int find_service(fstring service) /* Disallow anything except explicit share names. */ if (strequal(defservice,HOMES_NAME) || strequal(defservice, PRINTERS_NAME) || - strequal(defservice, "ipc$")) { + strequal(defservice, "IPC$")) { goto fail; } -- cgit From ca229b0980b5c78f140180db764b3229d5ccb078 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Feb 2007 02:15:23 +0000 Subject: r21483: Fix use of uninitialized variable. Jeremy. (This used to be commit 4a74d042c9108ed68cc92f27b390c261c0bc8885) --- source3/smbd/sesssetup.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 4e27914c0d..7a5f8be47f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -670,6 +670,9 @@ static struct pending_auth_data *pd_list; static void delete_partial_auth(struct pending_auth_data *pad) { + if (!pad) { + return; + } DLIST_REMOVE(pd_list, pad); data_blob_free(&pad->partial_data); SAFE_FREE(pad); @@ -698,10 +701,12 @@ static struct pending_auth_data *get_pending_auth_data(uint16 smbpid) static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob) { - struct pending_auth_data *pad; + struct pending_auth_data *pad = NULL; ASN1_DATA data; size_t needed_len = 0; + pad = get_pending_auth_data(smbpid); + /* Ensure we have some data. */ if (pblob->length == 0) { /* Caller can cope. */ @@ -710,8 +715,6 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB return NT_STATUS_OK; } - pad = get_pending_auth_data(smbpid); - /* Were we waiting for more data ? */ if (pad) { DATA_BLOB tmp_blob; -- cgit From 28e2069d1f066f20b376d911d6ed582a76c4a713 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 26 Feb 2007 20:14:35 +0000 Subject: r21547: Fix from Michael Adam : Refuse registry shares without path. Thanks, Volker (This used to be commit e795865d58472498097edc3fb68438ed08c38d8d) --- source3/smbd/service.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index de2bfd9100..c96bcea4e2 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -313,6 +313,14 @@ static int load_registry_service(const char *servicename) TALLOC_FREE(value); } + if (!service_ok(res)) { + /* this is actually never reached, since + * service_ok only returns False if the service + * entry does not have a service name, and we _know_ + * we do have a service name here... */ + res = -1; + } + error: TALLOC_FREE(key); -- cgit From 62a6f8940dce741037c12404e9f14543a0a62ab0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Feb 2007 21:59:39 +0000 Subject: r21603: Horrible backwards compatibility hack as an old server bug allowed a CIFS client bug to remain unnoticed :-(. I suck. Jeremy. (This used to be commit 29761173ee26b4713c9a12166a935c066fc3321b) --- source3/smbd/trans2.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 584345a906..5bbd618231 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2882,7 +2882,7 @@ static char *store_file_unix_basic(connection_struct *conn, SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; - put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Creation Time 64 Bit */ + put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */ put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */ put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */ pdata += 24; @@ -4805,6 +4805,16 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", delete_on_fail = True; } +#if 1 + /* Horrible backwards compatibility hack as an old server bug + * allowed a CIFS client bug to remain unnoticed :-(. JRA. + * */ + + if (!size) { + size = get_file_size(*psbuf); + } +#endif + /* * Deal with the UNIX specific mode set. */ -- cgit From 81cce1332129b97a5538f35c70367858f460935c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Mar 2007 21:01:22 +0000 Subject: r21638: Change POSIX_UNLINK to allow clients to differentiate between unlink/rmdir calls. Jeremy. (This used to be commit f0c8488d382ada32fabe79399f64ba1c6486d009) --- source3/smbd/trans2.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5bbd618231..2952c9b1dc 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5132,12 +5132,24 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, { NTSTATUS status = NT_STATUS_OK; files_struct *fsp = NULL; + uint16 flags = 0; int info = 0; + if (total_data < 2) { + return NT_STATUS_INVALID_PARAMETER; + } + + flags = SVAL(pdata,0); + if (!VALID_STAT(*psbuf)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } + if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) && + !VALID_STAT_OF_DIR(*psbuf)) { + return NT_STATUS_NOT_A_DIRECTORY; + } + if (VALID_STAT_OF_DIR(*psbuf)) { status = open_directory(conn, fname, -- cgit From ea3e890130cbc328ae5c405883c37ae0422e69a2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Mar 2007 22:44:02 +0000 Subject: r21644: Allow mkdir on platforms with no O_DIRECTORY. Add proper debug to all possible setfilepathinfo functions. Jeremy. (This used to be commit 3c47a5ef258d536504759a02f6d84c0ab0af7224) --- source3/smbd/trans2.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2952c9b1dc..96aa185d19 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4305,6 +4305,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } + DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n", + fname ? fname : fsp->fsp_name, + (unsigned int)num_file_acls, + (unsigned int)num_def_acls)); + if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, pdata + SMB_POSIX_ACL_HEADER_SIZE)) { return map_nt_error_from_unix(errno); @@ -4386,6 +4391,14 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET); #endif /* HAVE_LONGLONG */ + DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u," + "lock_pid = %u, count = %.0f, offset = %.0f\n", + fsp->fsp_name, + (unsigned int)lock_type, + (unsigned int)lock_pid, + (double)count, + (double)offset )); + if (lock_type == UNLOCK_LOCK) { status = do_unlock(fsp, lock_pid, @@ -4450,6 +4463,9 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, /* write time */ tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); + DEBUG(10,("smb_set_info_standard: file %s\n", + fname ? fname : fsp->fsp_name )); + return smb_set_file_time(conn, fsp, fname, @@ -4507,6 +4523,9 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, tvs.modtime = null_mtime(write_time) ? changed_time : write_time; } + DEBUG(10,("smb_set_file_basic_info: file %s\n", + fname ? fname : fsp->fsp_name )); + return smb_set_file_time(conn, fsp, fname, @@ -4910,6 +4929,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS; + DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n", + fname, (unsigned int)unixmode )); + status = open_directory(conn, fname, psbuf, @@ -5056,6 +5078,11 @@ static NTSTATUS smb_posix_open(connection_struct *conn, mod_unixmode |= FILE_FLAG_NO_BUFFERING; } + DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n", + fname, + (unsigned int)wire_open_mode, + (unsigned int)unixmode )); + status = open_file_ntcreate(conn, fname, psbuf, @@ -5150,6 +5177,10 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, return NT_STATUS_NOT_A_DIRECTORY; } + DEBUG(10,("smb_posix_unlink: %s %s\n", + (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file", + fname)); + if (VALID_STAT_OF_DIR(*psbuf)) { status = open_directory(conn, fname, -- cgit From 059e4cfa03b9d1bb4aa2fcb95747fc22faea45b1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Mar 2007 23:03:46 +0000 Subject: r21645: Make posix_unlink work - on open files too ! Jeremy. (This used to be commit 98f4b64574ef205ec87401b4bf5eed89f2933fa1) --- source3/smbd/trans2.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 96aa185d19..1908f56793 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4030,6 +4030,12 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, delete_on_close = (CVAL(pdata,0) ? True : False); dosmode = dos_mode(conn, fname, psbuf); + DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, " + "delete_on_close = %u\n", + fsp->fsp_name, + (unsigned int)dosmode, + (unsigned int)delete_on_close )); + status = can_set_delete_on_close(fsp, delete_on_close, dosmode); if (!NT_STATUS_IS_OK(status)) { @@ -5193,17 +5199,34 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, &info, &fsp); } else { + char del = 1; + status = open_file_ntcreate(conn, fname, psbuf, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, - FILE_DELETE_ON_CLOSE, + 0, FILE_FLAG_POSIX_SEMANTICS|0777, INTERNAL_OPEN_ONLY, &info, &fsp); + /* + * For file opens we must set the delete on close + * after the open. + */ + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = smb_set_file_disposition_info(conn, + &del, + 1, + fsp, + fname, + psbuf); } if (!NT_STATUS_IS_OK(status)) { -- cgit From 1f56aabf903c13b170d36e12e50c804f2cbeb79c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Mar 2007 22:19:53 +0000 Subject: r21665: Fix bug #4428 reported by Jason Mader . Jeremy. (This used to be commit fe00771df517071c5e654e0b2b9cfde2d88bd701) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f03c8216d4..f959f00b10 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1899,7 +1899,6 @@ static NTSTATUS mkdir_internal(connection_struct *conn, uint32 file_attributes, SMB_STRUCT_STAT *psbuf) { - int ret= -1; mode_t mode; char *parent_dir; const char *dirname; @@ -1927,7 +1926,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, mode = unix_mode(conn, aDIR, name, parent_dir); } - if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { + if (SMB_VFS_MKDIR(conn, name, mode) != 0) { return map_nt_error_from_unix(errno); } -- cgit From 9b0f22d065b80d8cc0d4d2c9c1f52476ae68df95 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Mar 2007 23:06:53 +0000 Subject: r21667: posix_unlink should break existing oplocks. Jeremy. (This used to be commit 8a90d5dd4f396e5ba207efabc6d852fe4b418310) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1908f56793..86e5f56fe2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5209,7 +5209,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, FILE_OPEN, 0, FILE_FLAG_POSIX_SEMANTICS|0777, - INTERNAL_OPEN_ONLY, + 0, /* No oplock, but break existing ones. */ &info, &fsp); /* -- cgit From 10ab7a3a78b5b4d38f93f13f5b91b5eea5308e86 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Mar 2007 01:35:58 +0000 Subject: r21672: The cannonical file access pattern should look like this : srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } RESOLVE_DFSPATH(name, conn, inbuf, outbuf); status = unix_convert(conn, name, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } status = check_name(conn, name); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } Make sure that every access pattern (including the wildcard generated paths from unlink, rename, and copy) do the same. Tidy things up a bit.... Jeremy. (This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c) --- source3/smbd/nttrans.c | 39 ++--- source3/smbd/reply.c | 417 ++++++++++++++++++++++++++++++------------------- source3/smbd/trans2.c | 44 +++--- 3 files changed, 298 insertions(+), 202 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 19710d1dcd..968c536caf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1592,15 +1592,15 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return status; } - /* Source must already exist. */ - if (!VALID_STAT(sbuf1)) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } status = check_name(conn, oldname); if (!NT_STATUS_IS_OK(status)) { return status; } + /* Source must already exist. */ + if (!VALID_STAT(sbuf1)) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } /* Ensure attributes match. */ fattr = dos_mode(conn,oldname,&sbuf1); if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) { @@ -1612,16 +1612,16 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return status; } - /* Disallow if newname already exists. */ - if (VALID_STAT(sbuf2)) { - return NT_STATUS_OBJECT_NAME_COLLISION; - } - status = check_name(conn, newname); if (!NT_STATUS_IS_OK(status)) { return status; } + /* Disallow if newname already exists. */ + if (VALID_STAT(sbuf2)) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } + /* No links from a directory. */ if (S_ISDIR(sbuf1.st_mode)) { return NT_STATUS_FILE_IS_A_DIRECTORY; @@ -1708,15 +1708,15 @@ int reply_ntrename(connection_struct *conn, pstring newname; char *p; NTSTATUS status; - BOOL path1_contains_wcard = False; - BOOL path2_contains_wcard = False; + BOOL src_has_wcard = False; + BOOL dest_has_wcard = False; uint32 attrs = SVAL(inbuf,smb_vwv0); uint16 rename_type = SVAL(inbuf,smb_vwv1); START_PROFILE(SMBntrename); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path1_contains_wcard); + p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1734,7 +1734,7 @@ int reply_ntrename(connection_struct *conn, } p++; - p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard); + p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1747,10 +1747,10 @@ int reply_ntrename(connection_struct *conn, switch(rename_type) { case RENAME_FLAG_RENAME: - status = rename_internals(conn, oldname, newname, attrs, False, path1_contains_wcard); + status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard); break; case RENAME_FLAG_HARD_LINK: - if (path1_contains_wcard || path2_contains_wcard) { + if (src_has_wcard || dest_has_wcard) { /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { @@ -1758,7 +1758,7 @@ int reply_ntrename(connection_struct *conn, } break; case RENAME_FLAG_COPY: - if (path1_contains_wcard || path2_contains_wcard) { + if (src_has_wcard || dest_has_wcard) { /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { @@ -1899,7 +1899,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o pstring new_name; files_struct *fsp = NULL; BOOL replace_if_exists = False; - BOOL path_contains_wcard = False; + BOOL dest_has_wcard = False; NTSTATUS status; if(parameter_count < 5) { @@ -1909,13 +1909,14 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o fsp = file_fsp(params, 0); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); - srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, STR_TERMINATE, &status, &path_contains_wcard); + srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, + STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } status = rename_internals(conn, fsp->fsp_name, - new_name, 0, replace_if_exists, path_contains_wcard); + new_name, 0, replace_if_exists, False, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8bccd45f4b..25c2aaa4dc 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -798,6 +798,12 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBsetatr); + return ERROR_NT(status); + } + if (fname[0] == '.' && fname[1] == '\0') { /* * Not sure here is the right place to catch this @@ -807,12 +813,6 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(NT_STATUS_ACCESS_DENIED); } - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBsetatr); - return ERROR_NT(status); - } - mode = SVAL(inbuf,smb_vwv0); mtime = srv_make_unix_date3(inbuf+smb_vwv1); @@ -1211,6 +1211,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBopen); + return ERROR_NT(status); + } + if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask, &share_mode, &create_disposition, &create_options)) { END_PROFILE(SMBopen); @@ -1329,6 +1335,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_NT(status); } + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBopenX); + return ERROR_NT(status); + } + if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun, &access_mask, &share_mode, @@ -1501,6 +1513,12 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcreate); + return ERROR_NT(status); + } + if (fattr & aVOLID) { DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); } @@ -1590,6 +1608,12 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBctemp); return ERROR_NT(status); } + + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBctemp); + return ERROR_NT(status); + } tmpfd = smb_mkstemp(fname); if (tmpfd == -1) { @@ -1859,6 +1883,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, if (dirtype == 0) { dirtype = FILE_ATTRIBUTE_NORMAL; } + + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = can_delete(conn,directory,dirtype,can_defer); if (!NT_STATUS_IS_OK(status)) { return status; @@ -1921,6 +1951,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = can_delete(conn, fname, dirtype, can_defer); if (!NT_STATUS_IS_OK(status)) { continue; @@ -3607,6 +3643,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBmkdir); + return ERROR_NT(status); + } + status = create_directory(conn, directory); DEBUG(5, ("create_directory returned %s\n", nt_errstr(status))); @@ -3855,7 +3897,6 @@ static BOOL resolve_wildcards(const char *name1, char *name2) char *p,*p2, *pname1, *pname2; int available_space, actual_space; - pname1 = strrchr_m(name1,'/'); pname2 = strrchr_m(name2,'/'); @@ -4009,6 +4050,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return status; } + status = check_name(conn, newname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Ensure newname contains a '/' */ if(strrchr_m(newname,'/') == 0) { pstring tmpstr; @@ -4153,9 +4199,13 @@ static void notify_rename(connection_struct *conn, BOOL is_dir, code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, pstring name, - pstring newname, uint32 attrs, - BOOL replace_if_exists, BOOL has_wild) +NTSTATUS rename_internals(connection_struct *conn, + pstring name, + pstring newname, + uint32 attrs, + BOOL replace_if_exists, + BOOL src_has_wild, + BOOL dest_has_wild) { pstring directory; pstring mask; @@ -4166,20 +4216,22 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, NTSTATUS status = NT_STATUS_OK; SMB_STRUCT_STAT sbuf1, sbuf2; struct share_mode_lock *lck = NULL; + struct smb_Dir *dir_hnd = NULL; + const char *dname; + long offset = 0; + pstring destname; *directory = *mask = 0; ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - status = unix_convert(conn, name, has_wild, last_component_src, - &sbuf1); + status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; } - status = unix_convert(conn, newname, True, last_component_dest, - &sbuf2); + status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4213,10 +4265,11 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, * Tine Smukavec . */ - if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) + if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) { mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); + } - if (!has_wild) { + if (!src_has_wild) { /* * No wildcards - just process the one file. */ @@ -4243,6 +4296,21 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, conn->short_case_preserve, directory, newname, last_component_dest, is_short_name)); + /* Ensure the source name is valid for us to access. */ + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* The dest name still may have wildcards. */ + if (dest_has_wild) { + if (!resolve_wildcards(directory,newname)) { + DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", + directory,newname)); + return NT_STATUS_NO_MEMORY; + } + } + /* * Check for special case with case preserving and not * case sensitive, if directory and newname are identical, @@ -4277,8 +4345,12 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, } } - resolve_wildcards(directory,newname); - + /* Ensure the dest name is valid for us to access. */ + status = check_name(conn, newname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* * The source object must exist. */ @@ -4370,136 +4442,130 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name, nt_errstr(status), directory,newname)); return status; - } else { - /* - * Wildcards - process each file that matches. - */ - struct smb_Dir *dir_hnd = NULL; - const char *dname; - long offset = 0; - pstring destname; - - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); + } + + /* + * Wildcards - process each file that matches. + */ + if (strequal(mask,"????????.???")) { + pstrcpy(mask,"*"); + } - status = check_name(conn, directory); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - dir_hnd = OpenDir(conn, directory, mask, attrs); - if (dir_hnd == NULL) { - return map_nt_error_from_unix(errno); - } + dir_hnd = OpenDir(conn, directory, mask, attrs); + if (dir_hnd == NULL) { + return map_nt_error_from_unix(errno); + } - status = NT_STATUS_NO_SUCH_FILE; - /* - * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - * - gentest fix. JRA - */ + status = NT_STATUS_NO_SUCH_FILE; + /* + * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + * - gentest fix. JRA + */ - while ((dname = ReadDirName(dir_hnd, &offset))) { - pstring fname; - BOOL sysdir_entry = False; + while ((dname = ReadDirName(dir_hnd, &offset))) { + pstring fname; + BOOL sysdir_entry = False; - pstrcpy(fname,dname); + pstrcpy(fname,dname); - /* Quick check for "." and ".." */ - if (fname[0] == '.') { - if (!fname[1] - || (fname[1] == '.' && !fname[2])) { - if (attrs & aDIR) { - sysdir_entry = True; - } else { - continue; - } + /* Quick check for "." and ".." */ + if (fname[0] == '.') { + if (!fname[1] || (fname[1] == '.' && !fname[2])) { + if (attrs & aDIR) { + sysdir_entry = True; + } else { + continue; } } + } - if (!is_visible_file(conn, directory, dname, &sbuf1, - False)) { - continue; - } + if (!is_visible_file(conn, directory, dname, &sbuf1, False)) { + continue; + } - if(!mask_match(fname, mask, conn->case_sensitive)) { - continue; - } + if(!mask_match(fname, mask, conn->case_sensitive)) { + continue; + } - if (sysdir_entry) { - status = NT_STATUS_OBJECT_NAME_INVALID; - break; - } + if (sysdir_entry) { + status = NT_STATUS_OBJECT_NAME_INVALID; + break; + } - status = NT_STATUS_ACCESS_DENIED; - slprintf(fname, sizeof(fname)-1, "%s/%s", directory, - dname); - if (!vfs_object_exist(conn, fname, &sbuf1)) { - status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(6, ("rename %s failed. Error %s\n", - fname, nt_errstr(status))); - continue; - } - status = can_rename(conn,fname,attrs,&sbuf1); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(6, ("rename %s refused\n", fname)); - continue; - } - pstrcpy(destname,newname); + status = NT_STATUS_ACCESS_DENIED; + slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname); + + /* Ensure the source name is valid for us to access. */ + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (!vfs_object_exist(conn, fname, &sbuf1)) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(6, ("rename %s failed. Error %s\n", + fname, nt_errstr(status))); + continue; + } + status = can_rename(conn,fname,attrs,&sbuf1); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(6, ("rename %s refused\n", fname)); + continue; + } + pstrcpy(destname,newname); - if (!resolve_wildcards(fname,destname)) { - DEBUG(6, ("resolve_wildcards %s %s failed\n", - fname, destname)); - continue; - } + if (!resolve_wildcards(fname,destname)) { + DEBUG(6, ("resolve_wildcards %s %s failed\n", + fname, destname)); + continue; + } - if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, - sbuf1.st_ino, newname); - DEBUG(3,("rename_internals: identical names " - "in wildcard rename %s - success\n", - fname)); - count++; - status = NT_STATUS_OK; - continue; - } + /* Ensure the dest name is valid for us to access. */ + status = check_name(conn, destname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - if (!replace_if_exists - && vfs_file_exist(conn,destname, NULL)) { - DEBUG(6,("file_exist %s\n", destname)); - status = NT_STATUS_OBJECT_NAME_COLLISION; - continue; - } + if (strcsequal(fname,destname)) { + rename_open_files(conn, NULL, sbuf1.st_dev, + sbuf1.st_ino, newname); + DEBUG(3,("rename_internals: identical names " + "in wildcard rename %s - success\n", + fname)); + count++; + status = NT_STATUS_OK; + continue; + } + + if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) { + DEBUG(6,("file_exist %s\n", destname)); + status = NT_STATUS_OBJECT_NAME_COLLISION; + continue; + } - if (rename_path_prefix_equal(fname, destname)) { - return NT_STATUS_SHARING_VIOLATION; - } + if (rename_path_prefix_equal(fname, destname)) { + return NT_STATUS_SHARING_VIOLATION; + } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, - sbuf1.st_ino, NULL, NULL); + lck = get_share_mode_lock(NULL, sbuf1.st_dev, + sbuf1.st_ino, NULL, NULL); - if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, sbuf1.st_dev, - sbuf1.st_ino, newname); - count++; - status = NT_STATUS_OK; - } - TALLOC_FREE(lck); - DEBUG(3,("rename_internals: doing rename on %s -> " - "%s\n",fname,destname)); + if (!SMB_VFS_RENAME(conn,fname,destname)) { + rename_open_files(conn, lck, sbuf1.st_dev, + sbuf1.st_ino, newname); + count++; + status = NT_STATUS_OK; } - CloseDir(dir_hnd); + TALLOC_FREE(lck); + DEBUG(3,("rename_internals: doing rename on %s -> " + "%s\n",fname,destname)); } - -#if 0 - /* Don't think needed any more - JRA. */ - if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) { - if (!rcdest && bad_path_dest) { - if (ms_has_wild(last_component_dest)) - return NT_STATUS_OBJECT_NAME_INVALID; - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - } -#endif + CloseDir(dir_hnd); if (count == 0 && NT_STATUS_IS_OK(status)) { status = map_nt_error_from_unix(errno); @@ -4521,19 +4587,19 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, char *p; uint32 attrs = SVAL(inbuf,smb_vwv0); NTSTATUS status; - BOOL path1_contains_wcard = False; - BOOL path2_contains_wcard = False; + BOOL src_has_wcard = False; + BOOL dest_has_wcard = False; START_PROFILE(SMBmv); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard); + p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); } p++; - p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard); + p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); @@ -4544,7 +4610,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard); + status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); if (open_was_deferred(SVAL(inbuf,smb_mid))) { @@ -4568,8 +4634,12 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * TODO: check error codes on all callers */ -NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun, - int count, BOOL target_is_directory) +NTSTATUS copy_file(connection_struct *conn, + char *src, + char *dest1, + int ofun, + int count, + BOOL target_is_directory) { SMB_STRUCT_STAT src_sbuf, sbuf2; SMB_OFF_T ret=-1; @@ -4689,14 +4759,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int count=0; int error = ERRnoaccess; int err = 0; - BOOL has_wild; - BOOL exists=False; int tid2 = SVAL(inbuf,smb_vwv0); int ofun = SVAL(inbuf,smb_vwv1); int flags = SVAL(inbuf,smb_vwv2); BOOL target_is_directory=False; - BOOL path_contains_wcard1 = False; - BOOL path_contains_wcard2 = False; + BOOL source_has_wild = False; + BOOL dest_has_wild = False; SMB_STRUCT_STAT sbuf1, sbuf2; NTSTATUS status; START_PROFILE(SMBcopy); @@ -4704,12 +4772,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, *directory = *mask = 0; p = smb_buf(inbuf); - p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1); + p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); } - p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2); + p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); @@ -4727,13 +4795,13 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); - status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1); + status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); } - status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2); + status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); @@ -4777,25 +4845,38 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec . */ - if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) + if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) { mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); + } - has_wild = path_contains_wcard1; - - if (!has_wild) { + if (!source_has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); - if (resolve_wildcards(directory,newname) - && NT_STATUS_IS_OK(status = copy_file( - directory,newname,conn,ofun, - count,target_is_directory))) - count++; - if(!count && !NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBcopy); + if (dest_has_wild) { + if (!resolve_wildcards(directory,newname)) { + END_PROFILE(SMBcopy); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + } + + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - if (!count) { - exists = vfs_file_exist(conn,directory,NULL); + + status = check_name(conn, newname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + status = copy_file(conn,directory,newname,ofun, + count,target_is_directory); + + if(!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcopy); + return ERROR_NT(status); + } else { + count++; } } else { struct smb_Dir *dir_hnd = NULL; @@ -4834,13 +4915,27 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); pstrcpy(destname,newname); - if (resolve_wildcards(fname,destname) && - NT_STATUS_IS_OK(status = copy_file( - fname,destname,conn,ofun, - count,target_is_directory))) { + if (!resolve_wildcards(fname,destname)) { + continue; + } + + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + status = check_name(conn, destname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname)); + + status = copy_file(conn,fname,destname,ofun, + count,target_is_directory); + if (NT_STATUS_IS_OK(status)) { count++; } - DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); } CloseDir(dir_hnd); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 86e5f56fe2..33618360f1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3743,17 +3743,22 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne return status; } + status = check_name(conn, oldname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* source must already exist. */ if (!VALID_STAT(sbuf1)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - status = check_name(conn, oldname); + status = unix_convert(conn, newname, False, last_component_newname, &sbuf2); if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_ACCESS_DENIED; + return status; } - status = unix_convert(conn, newname, False, last_component_newname, &sbuf2); + status = check_name(conn, newname); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3763,11 +3768,6 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne return NT_STATUS_OBJECT_NAME_COLLISION; } - status = check_name(conn, newname); - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_ACCESS_DENIED; - } - /* No links from a directory. */ if (S_ISDIR(sbuf1.st_mode)) { return NT_STATUS_FILE_IS_A_DIRECTORY; @@ -4217,6 +4217,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, uint32 len; pstring newname; pstring base_name; + BOOL dest_has_wcard = False; NTSTATUS status = NT_STATUS_OK; char *p; @@ -4232,7 +4233,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); + srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4261,7 +4262,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, } else { DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, newname )); - status = rename_internals(conn, fname, base_name, 0, overwrite, False); + status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard); } return status; @@ -5324,6 +5325,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(status); } + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + /* * For CIFS UNIX extensions the target name may not exist. */ @@ -5332,12 +5338,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); return UNIXERROR(ERRDOS,ERRbadpath); } - - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); - } - } if (!CAN_WRITE(conn)) { @@ -5642,6 +5642,12 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(status); } + status = check_name(conn, directory); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status))); + return ERROR_NT(status); + } + /* Any data in this call is an EA list. */ if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) { return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); @@ -5673,12 +5679,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - status = check_name(conn, directory); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status))); - return ERROR_NT(status); - } - status = create_directory(conn, directory); if (!NT_STATUS_IS_OK(status)) { -- cgit From 4952fe368a40b239140b3035db6075427d237bb9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Mar 2007 23:40:03 +0000 Subject: r21714: Change the VFS interface to use struct timespec for utimes - change the call to ntimes. This preserves nsec timestamps we get from stat (if the system supports it) and only maps back down to usec or sec resolution on time set. Looks bigger than it is as I had to move lots of internal code from using time_t and struct utimebuf to struct timespec. Jeremy. (This used to be commit 8f3d530c5a748ea90f42ed8fbe68ae92178d4875) --- source3/smbd/close.c | 4 +-- source3/smbd/dosmode.c | 36 +++++++++++--------- source3/smbd/fileio.c | 4 +-- source3/smbd/files.c | 6 ++-- source3/smbd/nttrans.c | 2 +- source3/smbd/reply.c | 43 ++++++++++++------------ source3/smbd/trans2.c | 91 ++++++++++++++++++++++++++------------------------ 7 files changed, 99 insertions(+), 87 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 50111f62bb..1c9f6ea8c4 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -361,9 +361,9 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ * Ensure pending modtime is set after close. */ - if(fsp->pending_modtime && fsp->pending_modtime_owner) { + if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) { set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); - } else if (fsp->last_write_time) { + } else if (!null_timespec(fsp->last_write_time)) { set_filetime(conn, fsp->fsp_name, fsp->last_write_time); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ad79bbacdd..71d4fa179d 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -282,7 +282,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ } /* We want DOS semantics, ie allow non owner with write permission to change the - bits on a file. Just like file_utime below. + bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ @@ -504,7 +504,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, return -1; /* We want DOS semantics, ie allow non owner with write permission to change the - bits on a file. Just like file_utime below. + bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ @@ -532,11 +532,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname, } /******************************************************************* - Wrapper around dos_utime that possibly allows DOS semantics rather + Wrapper around the VFS ntimes that possibly allows DOS semantics rather than POSIX. *******************************************************************/ -int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times) +int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2]) { SMB_STRUCT_STAT sbuf; int ret = -1; @@ -555,14 +555,17 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times return 0; } - if(SMB_VFS_UTIME(conn,fname, times) == 0) + if(SMB_VFS_NTIMES(conn, fname, ts) == 0) { return 0; + } - if((errno != EPERM) && (errno != EACCES)) + if((errno != EPERM) && (errno != EACCES)) { return -1; + } - if(!lp_dos_filetimes(SNUM(conn))) + if(!lp_dos_filetimes(SNUM(conn))) { return -1; + } /* We have permission (given by the Samba admin) to break POSIX semantics and allow a user to change @@ -574,7 +577,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times if (can_write_to_file(conn, fname, &sbuf)) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = SMB_VFS_UTIME(conn,fname, times); + ret = SMB_VFS_NTIMES(conn, fname, ts); unbecome_root(); } @@ -585,16 +588,19 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) +BOOL set_filetime(connection_struct *conn, const char *fname, + const struct timespec mtime) { - struct utimbuf times; + struct timespec ts[2]; - if (null_mtime(mtime)) + if (null_timespec(mtime)) { return(True); + } - times.modtime = times.actime = mtime; + ts[1] = mtime; /* mtime. */ + ts[0] = ts[1]; /* atime. */ - if (file_utime(conn, fname, ×)) { + if (file_ntimes(conn, fname, ts)) { DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); return False; } @@ -602,5 +608,5 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE, fname); - return(True); -} + return True; +} diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index e0945be889..65238c0e9e 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -149,13 +149,13 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos * The 99% solution will hopefully be good enough in this case. JRA. */ - if (fsp->pending_modtime) { + if (!null_timespec(fsp->pending_modtime)) { set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime); /* If we didn't get the "set modtime" call ourselves, we must store the last write time to restore on close. JRA. */ if (!fsp->pending_modtime_owner) { - fsp->last_write_time = time(NULL); + fsp->last_write_time = timespec_current(); } } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 0706548334..062bebd58e 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -383,11 +383,11 @@ files_struct *file_find_print(void) Record the owner of that modtime. ****************************************************************************/ -void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) +void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod) { files_struct *fsp; - if (null_mtime(pmod)) { + if (null_timespec(mod)) { return; } @@ -395,7 +395,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) if ( fsp->fh->fd != -1 && fsp->dev == tfsp->dev && fsp->inode == tfsp->inode ) { - fsp->pending_modtime = pmod; + fsp->pending_modtime = mod; fsp->pending_modtime_owner = False; } } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 968c536caf..eedc3cfba4 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1675,7 +1675,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); + fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1)); status = close_file(fsp2,NORMAL_CLOSE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 25c2aaa4dc..df560390c9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -828,7 +828,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } } - if (!set_filetime(conn,fname,mtime)) { + if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) { END_PROFILE(SMBsetatr); return UNIXERROR(ERRDOS, ERRnoaccess); } @@ -1483,7 +1483,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int com; int outsize = 0; uint32 fattr = SVAL(inbuf,smb_vwv0); - struct utimbuf times; + struct timespec ts[2]; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); SMB_STRUCT_STAT sbuf; @@ -1497,7 +1497,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); - times.modtime = srv_make_unix_date3(inbuf + smb_vwv1); + ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */ srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -1550,8 +1550,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - times.actime = sbuf.st_atime; - file_utime(conn, fname, ×); + ts[0] = get_atimespec(&sbuf); /* atime. */ + file_ntimes(conn, fname, ts); outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); @@ -3146,7 +3146,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, { NTSTATUS status = NT_STATUS_OK; int outsize = 0; - time_t mtime; files_struct *fsp = NULL; START_PROFILE(SMBclose); @@ -3188,8 +3187,8 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Take care of any time sent in the close. */ - mtime = srv_make_unix_date3(inbuf+smb_vwv1); - fsp_set_pending_modtime(fsp, mtime); + fsp_set_pending_modtime(fsp, + convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1))); /* * close_file() returns the unix errno if an error @@ -3222,7 +3221,7 @@ int reply_writeclose(connection_struct *conn, NTSTATUS close_status = NT_STATUS_OK; SMB_OFF_T startpos; char *data; - time_t mtime; + struct timespec mtime; files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBwriteclose); @@ -3233,7 +3232,7 @@ int reply_writeclose(connection_struct *conn, numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - mtime = srv_make_unix_date3(inbuf+smb_vwv4); + mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4)); data = smb_buf(inbuf) + 1; if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { @@ -3243,7 +3242,7 @@ int reply_writeclose(connection_struct *conn, nwritten = write_file(fsp,data,startpos,numtowrite); - set_filetime(conn, fsp->fsp_name,mtime); + set_filetime(conn, fsp->fsp_name, mtime); /* * More insanity. W2K only closes the file if writelen > 0. @@ -4724,7 +4723,7 @@ NTSTATUS copy_file(connection_struct *conn, close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime); + fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf)); /* * As we are opening fsp1 read-only we only expect @@ -5536,7 +5535,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - struct utimbuf unix_times; + struct timespec ts[2]; int outsize = 0; files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBsetattrE); @@ -5553,15 +5552,15 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, * time as UNIX can't set this. */ - unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3); - unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5); + ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */ + ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */ /* * Patch from Ray Frush * Sometimes times are sent as zero - ignore them. */ - if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { + if (null_timespec(ts[0]) && null_timespec(ts[1])) { /* Ignore request */ if( DEBUGLVL( 3 ) ) { dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); @@ -5569,20 +5568,22 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, } END_PROFILE(SMBsetattrE); return(outsize); - } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { + } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) { /* set modify time = to access time if modify time was unset */ - unix_times.modtime = unix_times.actime; + ts[1] = ts[0]; } /* Set the date on this file */ /* Should we set pending modtime here ? JRA */ - if(file_utime(conn, fsp->fsp_name, &unix_times)) { + if(file_ntimes(conn, fsp->fsp_name, ts)) { END_PROFILE(SMBsetattrE); return ERROR_DOS(ERRDOS,ERRnoaccess); } - DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", - fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); + DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n", + fsp->fnum, + (unsigned int)ts[0].tv_sec, + (unsigned int)ts[1].tv_sec)); END_PROFILE(SMBsetattrE); return(outsize); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 33618360f1..41fd2c5102 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3175,18 +3175,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd allocation_size = get_allocation_size(conn,fsp,&sbuf); if (fsp) { - if (fsp->pending_modtime) { + if (!null_timespec(fsp->pending_modtime)) { /* the pending modtime overrides the current modtime */ - mtime_ts.tv_sec = fsp->pending_modtime; - mtime_ts.tv_nsec = 0; + mtime_ts = fsp->pending_modtime; } } else { /* Do we have this path open ? */ files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); - if (fsp1 && fsp1->pending_modtime) { + if (fsp1 && !null_timespec(fsp1->pending_modtime)) { /* the pending modtime overrides the current modtime */ - mtime_ts.tv_sec = fsp1->pending_modtime; - mtime_ts.tv_nsec = 0; + mtime_ts = fsp->pending_modtime; } if (fsp1 && fsp1->initial_allocation_size) { allocation_size = get_allocation_size(conn, fsp1, &sbuf); @@ -3798,7 +3796,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, const char *fname, const SMB_STRUCT_STAT *psbuf, - struct utimbuf tvs) + struct timespec ts[2]) { uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS @@ -3810,26 +3808,30 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, } /* get some defaults (no modifications) if any info is zero or -1. */ - if (null_mtime(tvs.actime)) { - tvs.actime = psbuf->st_atime; + if (null_timespec(ts[0])) { + ts[0] = get_atimespec(psbuf); action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } - if (null_mtime(tvs.modtime)) { - tvs.modtime = psbuf->st_mtime; + if (null_timespec(ts[1])) { + ts[1] = get_mtimespec(psbuf); action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } - DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime))); - DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime))); + DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) )); + DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) )); /* * Try and set the times of this file if * they are different from the current values. */ - if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) { - return NT_STATUS_OK; + { + struct timespec mts = get_mtimespec(psbuf); + struct timespec ats = get_atimespec(psbuf); + if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) { + return NT_STATUS_OK; + } } if(fsp != NULL) { @@ -3843,15 +3845,16 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, * away and will set it on file close and after a write. JRA. */ - if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { - DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) )); - fsp_set_pending_modtime(fsp, tvs.modtime); + if (!null_timespec(ts[1])) { + DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", + time_to_asc(convert_timespec_to_time_t(ts[1])) )); + fsp_set_pending_modtime(fsp, ts[1]); } } DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); - if(file_utime(conn, fname, &tvs)!=0) { + if(file_ntimes(conn, fname, ts)!=0) { return map_nt_error_from_unix(errno); } if (action != 0) { @@ -4459,16 +4462,16 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf) { - struct utimbuf tvs; + struct timespec ts[2]; if (total_data < 12) { return NT_STATUS_INVALID_PARAMETER; } /* access time */ - tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess); + ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess)); /* write time */ - tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); + ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite)); DEBUG(10,("smb_set_info_standard: file %s\n", fname ? fname : fsp->fsp_name )); @@ -4477,7 +4480,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, fsp, fname, psbuf, - tvs); + ts); } /**************************************************************************** @@ -4492,10 +4495,10 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, SMB_STRUCT_STAT *psbuf) { /* Patch to do this correctly from Paul Eggert . */ - time_t write_time; - time_t changed_time; + struct timespec write_time; + struct timespec changed_time; uint32 dosmode = 0; - struct utimbuf tvs; + struct timespec ts[2]; NTSTATUS status = NT_STATUS_OK; if (total_data < 36) { @@ -4515,19 +4518,21 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, /* Ignore create time at offset pdata. */ /* access time */ - tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); + ts[0] = interpret_long_date(pdata+8); - write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16)); - changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24)); + write_time = interpret_long_date(pdata+16); + changed_time = interpret_long_date(pdata+24); - tvs.modtime = MIN(write_time, changed_time); + /* mtime */ + ts[1] = timespec_min(&write_time, &changed_time); - if (write_time > tvs.modtime && write_time != (time_t)-1) { - tvs.modtime = write_time; + if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) { + ts[1] = write_time; } + /* Prefer a defined time to an undefined one. */ - if (null_mtime(tvs.modtime)) { - tvs.modtime = null_mtime(write_time) ? changed_time : write_time; + if (null_timespec(ts[1])) { + ts[1] = null_timespec(write_time) ? changed_time : write_time; } DEBUG(10,("smb_set_file_basic_info: file %s\n", @@ -4537,7 +4542,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, fsp, fname, psbuf, - tvs); + ts); } /**************************************************************************** @@ -4751,7 +4756,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - struct utimbuf tvs; + struct timespec ts[2]; uint32 raw_unixmode; mode_t unixmode; SMB_OFF_T size = 0; @@ -4778,8 +4783,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, #endif /* LARGE_SMB_OFF_T */ } - tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */ - tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */ + ts[0] = interpret_long_date(pdata+24); /* access_time */ + ts[1] = interpret_long_date(pdata+32); /* modification_time */ set_owner = (uid_t)IVAL(pdata,40); set_grp = (gid_t)IVAL(pdata,48); raw_unixmode = IVAL(pdata,84); @@ -4822,8 +4827,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Ensure we don't try and change anything else. */ raw_unixmode = SMB_MODE_NO_CHANGE; size = get_file_size(*psbuf); - tvs.modtime = psbuf->st_mtime; - tvs.actime = psbuf->st_atime; + ts[0] = get_atimespec(psbuf); + ts[1] = get_mtimespec(psbuf); /* * We continue here as we might want to change the * owner uid/gid. @@ -4902,7 +4907,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", fsp, fname, psbuf, - tvs); + ts); } /**************************************************************************** @@ -5360,9 +5365,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char SSVAL(params,0,0); - if (fsp && fsp->pending_modtime) { + if (fsp && !null_timespec(fsp->pending_modtime)) { /* the pending modtime overrides the current modtime */ - sbuf.st_mtime = fsp->pending_modtime; + set_mtimespec(&sbuf, fsp->pending_modtime); } switch (info_level) { -- cgit From ba992d5ad7bc2e32b2b458d8d91ca450e97513c3 Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 6 Mar 2007 00:54:05 +0000 Subject: r21717: Support the SMB_QUERY_POSIX_WHOAMI info level on QueryFsInfo. (This used to be commit 32c7281f90b042c9f01962c4661faaf979676711) --- source3/smbd/trans2.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 41fd2c5102..0951160b3c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5,6 +5,7 @@ Copyright (C) Stefan (metze) Metzmacher 2003 Copyright (C) Volker Lendecke 2005 Copyright (C) Steve French 2005 + Copyright (C) James Peach 2007 Extensively modified by Andrew Tridgell, 1995 @@ -2232,7 +2233,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf char **pparams, int total_params, char **ppdata, int total_data, unsigned int max_data_bytes) { - char *pdata = *ppdata; + char *pdata; char *params = *pparams; uint16 info_level; int data_len, len; @@ -2566,6 +2567,114 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned break; } + case SMB_QUERY_POSIX_WHOAMI: + { + uint32_t flags = 0; + uint32_t sid_bytes; + int i; + + if (!lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + + if (max_data_bytes < 40) { + return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); + } + + /* We ARE guest if global_sid_Builtin_Guests is + * in our list of SIDs. + */ + if (nt_token_check_sid(&global_sid_Builtin_Guests, + current_user.nt_user_token)) { + flags |= SMB_WHOAMI_GUEST; + } + + /* We are NOT guest if global_sid_Authenticated_Users + * is in our list of SIDs. + */ + if (nt_token_check_sid(&global_sid_Authenticated_Users, + current_user.nt_user_token)) { + flags &= ~SMB_WHOAMI_GUEST; + } + + /* NOTE: 8 bytes for UID/GID, irrespective of native + * platform size. This matches + * SMB_QUERY_FILE_UNIX_BASIC and friends. + */ + data_len = 4 /* flags */ + + 4 /* flag mask */ + + 8 /* uid */ + + 8 /* gid */ + + 4 /* ngroups */ + + 4 /* num_sids */ + + 4 /* SID bytes */ + + 4 /* pad/reserved */ + + (current_user.ut.ngroups * 8) + /* groups list */ + + (current_user.nt_user_token->num_sids * + SID_MAX_SIZE) + /* SID list */; + + SIVAL(pdata, 0, flags); + SIVAL(pdata, 4, SMB_WHOAMI_MASK); + SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid); + SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid); + + + if (data_len >= max_data_bytes) { + /* Potential overflow, skip the GIDs and SIDs. */ + + SIVAL(pdata, 24, 0); /* num_groups */ + SIVAL(pdata, 28, 0); /* num_sids */ + SIVAL(pdata, 32, 0); /* num_sid_bytes */ + SIVAL(pdata, 36, 0); /* reserved */ + + data_len = 40; + break; + } + + SIVAL(pdata, 24, current_user.ut.ngroups); + SIVAL(pdata, 28, + current_user.nt_user_token->num_sids); + + /* We walk the SID list twice, but this call is fairly + * infrequent, and I don't expect that it's performance + * sensitive -- jpeach + */ + for (i = 0, sid_bytes = 0; + i < current_user.nt_user_token->num_sids; ++i) { + sid_bytes += + sid_size(¤t_user.nt_user_token->user_sids[i]); + } + + /* SID list byte count */ + SIVAL(pdata, 32, sid_bytes); + + /* 4 bytes pad/reserved - must be zero */ + SIVAL(pdata, 36, 0); + data_len = 40; + + /* GID list */ + for (i = 0; i < current_user.ut.ngroups; ++i) { + SBIG_UINT(pdata, data_len, + (SMB_BIG_UINT)current_user.ut.groups[i]); + data_len += 8; + } + + /* SID list */ + for (i = 0; + i < current_user.nt_user_token->num_sids; ++i) { + int sid_len = + sid_size(¤t_user.nt_user_token->user_sids[i]); + + sid_linearize(pdata + data_len, sid_len, + ¤t_user.nt_user_token->user_sids[i]); + data_len += sid_len; + } + + break; + } + case SMB_MAC_QUERY_FS_INFO: /* * Thursby MAC extension... ONLY on NTFS filesystems -- cgit From 235b0f97f280cd0b3d7941969cf154a89fd53775 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Mar 2007 01:28:19 +0000 Subject: r21731: Fix long-standing bug in our chain processing code. Should fix a bug with WinPE. Probably a candidate for the Vista patchset. Jeremy. (This used to be commit ef32de6b59fef3e9f59e6f864ce5eb072390ea48) --- source3/smbd/process.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a0e14d8445..dbac553aea 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1148,6 +1148,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) unsigned smb_off2 = SVAL(inbuf,smb_vwv1); char *inbuf2, *outbuf2; int outsize2; + int new_size; char inbuf_saved[smb_wct]; char outbuf_saved[smb_wct]; int outsize = smb_len(outbuf) + 4; @@ -1198,6 +1199,20 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* create the in buffer */ SCVAL(inbuf2,smb_com,smb_com2); + /* work out the new size for the in buffer. */ + new_size = size - (inbuf2 - inbuf); + if (new_size < 0) { + DEBUG(0,("chain_reply: chain packet size incorrect (orig size = %d, " + "offset = %d)\n", + size, + (inbuf2 - inbuf) )); + exit_server_cleanly("Bad chained packet"); + return(-1); + } + + /* And set it in the header. */ + smb_setlen(inbuf2, new_size); + /* create the out buffer */ construct_reply_common(inbuf2, outbuf2); @@ -1205,7 +1220,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) show_msg(inbuf2); /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, + outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size, bufsize-chain_size); /* copy the new reply and request headers over the old ones, but @@ -1219,8 +1234,10 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) { int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) ofs = 0; - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); + if (ofs < 0) { + ofs = 0; + } + memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); } return outsize2; -- cgit From 5309fd6d13082767c6ac059d911808897f938a0f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 Mar 2007 13:57:32 +0000 Subject: r21747: Cosmetic checkin to bring ntcreate and nttranscreate closer together (This used to be commit ecc781f1a211377e9ebb3e416c86123c00b11ed3) --- source3/smbd/nttrans.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index eedc3cfba4..de3863eabe 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -469,7 +469,7 @@ int reply_ntcreate_and_X(connection_struct *conn, SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int info = 0; - files_struct *fsp=NULL; + files_struct *fsp = NULL; char *p = NULL; struct timespec c_timespec; struct timespec a_timespec; @@ -502,7 +502,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return(ERROR_DOS(ERRDOS,ERRnoaccess)); } } - + if (create_options & FILE_OPEN_BY_FILE_ID) { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_NOT_SUPPORTED); @@ -522,7 +522,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!dir_fsp) { END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRbadfid)); + return ERROR_DOS(ERRDOS,ERRbadfid); } if(!dir_fsp->is_directory) { @@ -533,7 +533,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return ERROR_NT(status); } - /* + /* * Check to see if this is a mac fork of some kind. */ @@ -564,7 +564,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * Ensure it ends in a '\'. */ - if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') { + if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { pstrcat(fname, "/"); dir_name_len++; } @@ -582,7 +582,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return ERROR_NT(status); } - /* + /* * Check to see if this is a mac fork of some kind. */ @@ -664,7 +664,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } } - /* + /* * If it's a request for a directory open, deal with it separately. */ @@ -695,7 +695,9 @@ int reply_ntcreate_and_X(connection_struct *conn, END_PROFILE(SMBntcreateX); return ERROR_NT(status); } + } else { + /* * Ordinary file case. */ @@ -827,11 +829,11 @@ int reply_ntcreate_and_X(connection_struct *conn, * and we granted one (by whatever means) - set the * correct bit for extended oplock reply. */ - + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { extended_oplock_granted = True; } - + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { extended_oplock_granted = True; } @@ -1254,10 +1256,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + /* + * Ordinary file or directory. + */ + /* * Check if POSIX semantics are wanted. */ - + new_file_attributes = set_posix_case_semantics(conn, file_attributes); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); @@ -1273,7 +1279,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } - + /* This is the correct thing to do (check every time) but can_delete is expensive (it may have to read the parent directory permissions). So for now we're not doing it unless we have a strong hint the client @@ -1464,11 +1470,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * and we granted one (by whatever means) - set the * correct bit for extended oplock reply. */ - + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { extended_oplock_granted = True; } - + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { extended_oplock_granted = True; } -- cgit From 062a22be47261d6a447e66f96a4988be1fe2dd20 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 Mar 2007 14:25:07 +0000 Subject: r21748: More cosmetic alignment. One change to call_nt_transact_create(): We were asking open_file_ntcreate for a batch oplock if the client asked us to do so, even if it did not ask for an oplock in the first place. Did not test it, but I think this is bogus anyway. Volker (This used to be commit 0b94af112b9a40171fd9b14ea39981ac65d709f2) --- source3/smbd/nttrans.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index de3863eabe..19989d2178 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -491,7 +491,9 @@ int reply_ntcreate_and_X(connection_struct *conn, (unsigned int)create_options, (unsigned int)root_dir_fid )); - /* If it's an IPC, use the pipe handler. */ + /* + * If it's an IPC, use the pipe handler. + */ if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { @@ -669,14 +671,14 @@ int reply_ntcreate_and_X(connection_struct *conn, */ if(create_options & FILE_DIRECTORY_FILE) { - oplock_request = 0; - + /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + oplock_request = 0; status = open_directory(conn, fname, &sbuf, access_mask, share_access, @@ -723,6 +725,7 @@ int reply_ntcreate_and_X(connection_struct *conn, new_file_attributes, oplock_request, &info, &fsp); + if (!NT_STATUS_IS_OK(status)) { /* We cheat here. There are two cases we * care about. One is a directory rename, @@ -775,7 +778,6 @@ int reply_ntcreate_and_X(connection_struct *conn, return ERROR_NT(status); } } else { - restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { @@ -788,7 +790,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } restore_case_semantics(conn, file_attributes); - + file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); if(fattr == 0) { @@ -873,8 +875,8 @@ int reply_ntcreate_and_X(connection_struct *conn, SIVAL(p,0,info); } p += 4; - - /* Create time. */ + + /* Create time. */ c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); a_timespec = get_atimespec(&sbuf); m_timespec = get_mtimespec(&sbuf); @@ -885,7 +887,7 @@ int reply_ntcreate_and_X(connection_struct *conn, dos_filetime_timespec(&m_timespec); } - put_long_date_timespec(p, c_timespec); + put_long_date_timespec(p, c_timespec); /* create time. */ p += 8; put_long_date_timespec(p, a_timespec); /* access time */ p += 8; @@ -1254,7 +1256,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + } /* * Ordinary file or directory. @@ -1323,14 +1327,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - oplock_request = 0; - /* * We will get a create directory here if the Win32 * app specified a security descriptor in the * CreateDirectory() call. */ + oplock_request = 0; status = open_directory(conn, fname, &sbuf, access_mask, share_access, -- cgit From 7b2c2e415543aaee13193be1bd11706f2528c692 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Mar 2007 22:12:58 +0000 Subject: r21754: Volker is completely correct. There's no need for the RESOLVE_DFSPATH macros and their varients any more. Fix reporting profile bug with all error returns. Jeremy. (This used to be commit cdf0fdb1049fd68b46885cbea887dc0e595fa524) --- source3/smbd/msdfs.c | 32 +++++++++++++++++++- source3/smbd/nttrans.c | 21 +++++++++---- source3/smbd/reply.c | 80 ++++++++++++++++++++++++++++++++++++++++---------- source3/smbd/trans2.c | 20 +++++++++---- 4 files changed, 126 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c24cdcc708..f06bb3b044 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -3,6 +3,7 @@ Version 3.0 MSDfs services for Samba Copyright (C) Shirish Kalele 2000 + Copyright (C) Jeremy Allison 2007 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 @@ -435,7 +436,7 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, for details. *****************************************************************/ -BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_flag ) +static BOOL dfs_redirect( connection_struct *conn, pstring pathname, BOOL search_wcard_flag ) { struct dfs_path dp; @@ -1149,3 +1150,32 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) } return jn_count; } + +/****************************************************************************** + Core function to resolve a dfs pathname. +******************************************************************************/ + +BOOL resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) +{ + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && + dfs_redirect(conn, name, False)) { + return False; /* Pathname didn't resolve. */ + } + return True; +} + +/****************************************************************************** + Core function to resolve a dfs pathname possibly containing a wildcard. + This function is identical to the above except for the BOOL param to + dfs_redirect but I need this to be separate so it's really clear when + we're allowing wildcards and when we're not. JRA. +******************************************************************************/ + +BOOL resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name) +{ + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && + dfs_redirect(conn, name, True)) { + return False; /* Pathname didn't resolve. */ + } + return True; +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 19989d2178..0cc7193170 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -615,7 +615,10 @@ int reply_ntcreate_and_X(connection_struct *conn, * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + END_PROFILE(SMBntcreateX); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; if (oplock_request) { @@ -1270,7 +1273,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o new_file_attributes = set_posix_case_semantics(conn, file_attributes); - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -1749,9 +1754,15 @@ int reply_ntrename(connection_struct *conn, return ERROR_NT(status); } - RESOLVE_DFSPATH(oldname, conn, inbuf, outbuf); - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); - + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname)) { + END_PROFILE(SMBntrename); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { + END_PROFILE(SMBntrename); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); switch(rename_type) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index df560390c9..f85f635d6b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -632,7 +632,10 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s return ERROR_NT(status); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { + END_PROFILE(SMBcheckpath); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); @@ -711,7 +714,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + END_PROFILE(SMBgetatr); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ @@ -790,7 +796,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + END_PROFILE(SMBsetatr); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -945,7 +954,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(nt_status); } - RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf); + if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path)) { + END_PROFILE(SMBsearch); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } p++; status_len = SVAL(p, 0); @@ -1203,7 +1215,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + END_PROFILE(SMBopen); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -1327,7 +1342,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_NT(status); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + END_PROFILE(SMBopenX); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -1505,7 +1523,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + END_PROFILE(SMBcreate); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -1601,7 +1622,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(fname,"TMXXXXXX"); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + END_PROFILE(SMBctemp); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -2004,7 +2028,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); + if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { + END_PROFILE(SMBunlink); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } DEBUG(3,("reply_unlink : %s\n",name)); @@ -3634,7 +3661,10 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) { + END_PROFILE(SMBmkdir); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, directory, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -3852,7 +3882,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) { + END_PROFILE(SMBrmdir); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, directory, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -4604,8 +4637,14 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); + if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { + END_PROFILE(SMBmv); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { + END_PROFILE(SMBmv); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); @@ -4791,8 +4830,14 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRSRV,ERRinvdevice); } - RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); + if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { + END_PROFILE(SMBcopy); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { + END_PROFILE(SMBcopy); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1); if (!NT_STATUS_IS_OK(status)) { @@ -4983,7 +5028,10 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir)) { + END_PROFILE(pathworks_setdir); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } if (strlen(newdir) != 0) { if (!vfs_directory_exist(conn,newdir,NULL)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0951160b3c..00327ddf45 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1746,7 +1746,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf); + if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } ntstatus = unix_convert(conn, directory, True, NULL, &sbuf); if (!NT_STATUS_IS_OK(ntstatus)) { @@ -3140,7 +3142,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return ERROR_NT(status); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -4304,7 +4308,9 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, return status; } - RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname)) { + return NT_STATUS_PATH_NOT_COVERED; + } DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, oldname)); @@ -4350,7 +4356,9 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return status; } - RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { + return NT_STATUS_PATH_NOT_COVERED; + } /* Check the new name has no '/' characters. */ if (strchr_m(newname, '/')) { @@ -5432,7 +5440,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(status); } - RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); + if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { -- cgit From 286d8554aa4547629b7e5d1349be4550885b76a2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Mar 2007 23:58:40 +0000 Subject: r21756: An invarient the dfs code depended on for POSIX paths is no longer true, so fix it. Jeremy. (This used to be commit 698159c0ee8d9adb3b56231c0c8ad2ddebd5be11) --- source3/smbd/msdfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index f06bb3b044..25c9c59497 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -78,16 +78,13 @@ static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp) into the dfs_path structure This code is dependent on the fact that check_path_syntax() will convert '\\' characters to '/'. - When POSIX pathnames have been selected this doesn't happen, so we - must look for the unaltered separator of '\\' instead of the modified '/'. - JRA. **********************************************************************/ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) { pstring pathname_local; char *p,*temp; - const char sepchar = lp_posix_pathnames() ? '\\' : '/'; + const char sepchar = '/'; pstrcpy(pathname_local,pathname); p = temp = pathname_local; -- cgit From c4ea95fd303ae6fd51d125e756c1289f440adbd2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Mar 2007 02:51:41 +0000 Subject: r21758: Fix a very specific dfs bug when passing in POSIX pathnames. When we're working out how much we've consumed we need to backtrack by either a '/' or '\\' component, as both are valid separators. Jeremy. (This used to be commit 1722ea20db2d531f92fb18fa5783f09258727c64) --- source3/smbd/msdfs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 25c9c59497..c34512493f 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -92,7 +92,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL ZERO_STRUCTP(pdp); trim_char(temp,sepchar,sepchar); - DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp)); + DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming /'s\n",temp)); /* now tokenize */ /* parse out hostname */ @@ -401,12 +401,15 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, */ if (consumedcntp) { - char *q; pstring buf; pstrcpy(buf, dfspath); trim_char(buf, '\0', '\\'); for (; consumed_level; consumed_level--) { - q = strrchr_m(buf, '\\'); + char *q, *q1, *q2; + /* Either '\\' or '/' may be a separator. */ + q1 = strrchr_m(buf, '\\'); + q2 = strrchr_m(buf, '/'); + q = MAX(q1,q2); if (q) { *q = 0; } -- cgit From db32963181843c0ae425ee5a3bb517010ab0bf0f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Mar 2007 03:00:42 +0000 Subject: r21759: Fix the same bug in a more elegant way, strrchr_m is an expensive call.... Jeremy. (This used to be commit 321a136dbce1a0532f123ea79ecb91f987b9a286) --- source3/smbd/msdfs.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c34512493f..861588e6b7 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -331,6 +331,7 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, SMB_STRUCT_STAT sbuf; NTSTATUS status; pstring reqpath; + pstring local_dfspath; if (!dp || !conn) { DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n")); @@ -385,6 +386,12 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, return True; } + /* Prepare to test only for '/' components in the given path, + * so replace all '\\' characters with '/'. */ + + pstrcpy(local_dfspath, dfspath); + string_replace(local_dfspath, '\\', '/'); + /* redirect if any component in the path is a link */ pstrcpy(reqpath, localpath); p = strrchr_m(reqpath, '/'); @@ -402,14 +409,12 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, if (consumedcntp) { pstring buf; - pstrcpy(buf, dfspath); - trim_char(buf, '\0', '\\'); + pstrcpy(buf, local_dfspath); + trim_char(buf, '\0', '/'); for (; consumed_level; consumed_level--) { - char *q, *q1, *q2; - /* Either '\\' or '/' may be a separator. */ - q1 = strrchr_m(buf, '\\'); - q2 = strrchr_m(buf, '/'); - q = MAX(q1,q2); + char *q; + /* We made sure only '/' may be a separator above. */ + q = strrchr_m(buf, '/'); if (q) { *q = 0; } -- cgit From 30b9b9acae1a0bcea100e7fd9d2cdf29bf25148f Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 8 Mar 2007 18:05:55 +0000 Subject: r21763: Add support for the UNIX_INFO2 infolevel. (This used to be commit 262e4e1fd8398934780db354fcc5316368032d7b) --- source3/smbd/trans2.c | 291 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 245 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 00327ddf45..441a798f27 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -35,6 +35,16 @@ extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) #define DIR_ENTRY_SAFETY_MARGIN 4096 +static char *store_file_unix_basic(connection_struct *conn, + char *pdata, + files_struct *fsp, + const SMB_STRUCT_STAT *psbuf); + +static char *store_file_unix_basic_info2(connection_struct *conn, + char *pdata, + files_struct *fsp, + const SMB_STRUCT_STAT *psbuf); + /******************************************************************** Roundup a value to the nearest allocation roundup size boundary. Only do this for Windows clients. @@ -57,7 +67,7 @@ SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val) account sparse files. ********************************************************************/ -SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf) +SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf) { SMB_BIG_UINT ret; @@ -1579,51 +1589,21 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, /* CIFS UNIX Extension. */ case SMB_FIND_FILE_UNIX: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); + case SMB_FIND_FILE_UNIX_INFO2: p+= 4; SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ - SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */ - p+= 8; - - SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ - p+= 8; - - put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */ - put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */ - put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */ - p+= 24; - SIVAL(p,0,sbuf.st_uid); /* user id for the owner */ - SIVAL(p,4,0); - p+= 8; - - SIVAL(p,0,sbuf.st_gid); /* group id of owner */ - SIVAL(p,4,0); - p+= 8; - - SIVAL(p,0,unix_filetype(sbuf.st_mode)); - p+= 4; - - SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */ - SIVAL(p,4,0); - p+= 8; - - SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */ - SIVAL(p,4,0); - p+= 8; - - SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */ - p+= 8; - - SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */ - SIVAL(p,4,0); - p+= 8; - - SIVAL(p,0,sbuf.st_nlink); /* number of hard links */ - SIVAL(p,4,0); - p+= 8; + if (info_level == SMB_FIND_FILE_UNIX) { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); + p = store_file_unix_basic(conn, p, + NULL, &sbuf); + } else { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); + p = store_file_unix_basic_info2(conn, p, + NULL, &sbuf); + } len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); p += len; @@ -1733,6 +1713,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", case SMB_FIND_ID_BOTH_DIRECTORY_INFO: break; case SMB_FIND_FILE_UNIX: + case SMB_FIND_FILE_UNIX_INFO2: if (!lp_unix_extensions()) { return ERROR_NT(NT_STATUS_INVALID_LEVEL); } @@ -2040,6 +2021,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", case SMB_FIND_ID_BOTH_DIRECTORY_INFO: break; case SMB_FIND_FILE_UNIX: + case SMB_FIND_FILE_UNIX_INFO2: if (!lp_unix_extensions()) { return ERROR_NT(NT_STATUS_INVALID_LEVEL); } @@ -2533,6 +2515,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_POSIX_ACLS_CAP| CIFS_UNIX_POSIX_PATHNAMES_CAP| CIFS_UNIX_FCNTL_LOCKS_CAP| + CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))); break; @@ -2982,7 +2965,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ static char *store_file_unix_basic(connection_struct *conn, char *pdata, files_struct *fsp, - SMB_STRUCT_STAT *psbuf) + const SMB_STRUCT_STAT *psbuf) { DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n")); DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode)); @@ -3031,6 +3014,116 @@ static char *store_file_unix_basic(connection_struct *conn, return pdata; } +/* Forward and reverse mappings from the UNIX_INFO2 file flags field and + * the chflags(2) (or equivalent) flags. + * + * XXX: this really should be behind the VFS interface. To do this, we would + * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field. + * Each VFS module could then implement it's own mapping as appropriate for the + * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS. + */ +static const struct {unsigned stat_fflag; unsigned smb_fflag;} + info2_flags_map[] = +{ +#ifdef UF_NODUMP + { UF_NODUMP, EXT_DO_NOT_BACKUP }, +#endif + +#ifdef UF_IMMUTABLE + { UF_IMMUTABLE, EXT_IMMUTABLE }, +#endif + +#ifdef UF_APPEND + { UF_APPEND, EXT_OPEN_APPEND_ONLY }, +#endif + +#ifdef UF_HIDDEN + { UF_HIDDEN, EXT_HIDDEN } +#endif + +}; + +static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf, + uint32 *smb_fflags, uint32 *smb_fmask) +{ +#ifdef HAVE_STAT_ST_FLAGS + int i; + + for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) { + *smb_fmask |= info2_flags_map[i].smb_fflag; + if (psbuf->st_flags & info2_flags_map[i].stat_fflag) { + *smb_fflags |= info2_flags_map[i].smb_fflag; + } + } +#endif /* HAVE_STAT_ST_FLAGS */ +} + +static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf, + const uint32 smb_fflags, + const uint32 smb_fmask, + int *stat_fflags) +{ +#ifdef HAVE_STAT_ST_FLAGS + uint32 max_fmask; + int i; + + *stat_fflags = psbuf->st_flags; + + /* For each flags requested in smb_fmask, check the state of the + * corresponding flag in smb_fflags and set or clear the matching + * stat flag. + */ + + for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) { + max_fmask |= info2_flags_map[i].smb_fflag; + if (smb_fmask & info2_flags_map[i].smb_fflag) { + if (smb_fflags & info2_flags_map[i].smb_fflag) { + *stat_fflags |= info2_flags_map[i].stat_fflag; + } else { + *stat_fflags &= ~info2_flags_map[i].stat_fflag; + } + } + } + + /* If smb_fmask is asking to set any bits that are not supported by + * our flag mappings, we should fail. + */ + if ((smb_fmask & max_fmask) != smb_fmask) { + return False; + } + + return True; +#else + return False; +#endif /* HAVE_STAT_ST_FLAGS */ +} + + +/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition + * of file flags and birth (create) time. + */ +static char *store_file_unix_basic_info2(connection_struct *conn, + char *pdata, + files_struct *fsp, + const SMB_STRUCT_STAT *psbuf) +{ + uint32 file_flags = 0; + uint32 flags_mask = 0; + + pdata = store_file_unix_basic(conn, pdata, fsp, psbuf); + + /* Create (birth) time 64 bit */ + put_long_date_timespec(pdata, get_create_timespec(psbuf, False)); + pdata += 8; + + map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask); + SIVAL(pdata, 0, file_flags); /* flags */ + SIVAL(pdata, 4, flags_mask); /* mask */ + pdata += 8; + + return pdata; +} + /**************************************************************************** Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by file name or file id). @@ -3081,6 +3174,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + if(fsp && (fsp->fake_file_handle)) { /* * This is actually for the QUOTA_FAKE_FILE --metze @@ -3137,6 +3234,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); @@ -3650,6 +3751,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd break; + case SMB_QUERY_FILE_UNIX_INFO2: + + pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf); + data_size = PTR_DIFF(pdata,(*ppdata)); + + { + int i; + DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 ")); + + for (i=0; i<100; i++) + DEBUG(4,("%d=%x, ",i, (*ppdata)[i])); + DEBUG(4,("\n")); + } + + break; + case SMB_QUERY_FILE_UNIX_LINK: { pstring buffer; @@ -5027,6 +5144,67 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", ts); } +/**************************************************************************** + Deal with SMB_SET_FILE_UNIX_INFO2. +****************************************************************************/ + +static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, + const char *pdata, + int total_data, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) +{ + NTSTATUS status; + uint32 smb_fflags; + uint32 smb_fmask; + + if (total_data < 116) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* Start by setting all the fields that are common between UNIX_BASIC + * and UNIX_INFO2. + */ + status = smb_set_file_unix_basic(conn, pdata, total_data, + fsp, fname, psbuf); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + smb_fflags = IVAL(pdata, 108); + smb_fmask = IVAL(pdata, 112); + + /* NB: We should only attempt to alter the file flags if the client + * sends a non-zero mask. + */ + if (smb_fmask != 0) { + int stat_fflags = 0; + + if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask, + &stat_fflags)) { + /* Client asked to alter a flag we don't understand. */ + return NT_STATUS_INVALID_PARAMETER; + } + + if (fsp && fsp->fh->fd != -1) { + /* XXX: we should be using SMB_VFS_FCHFLAGS here. */ + return NT_STATUS_NOT_SUPPORTED; + } else { + if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) { + return map_nt_error_from_unix(errno); + } + } + } + + /* XXX: need to add support for changing the create_time here. You + * can do this for paths on Darwin with setattrlist(2). The right way + * to hook this up is probably by extending the VFS utimes interface. + */ + + return NT_STATUS_OK; +} + /**************************************************************************** Create a directory with POSIX semantics. ****************************************************************************/ @@ -5094,11 +5272,16 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, SSVAL(pdata,0,NO_OPLOCK_RETURN); SSVAL(pdata,2,0); - if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { + switch (info_level_return) { + case SMB_QUERY_FILE_UNIX_BASIC: SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); SSVAL(pdata,6,0); /* Padding. */ store_file_unix_basic(conn, pdata + 8, fsp, psbuf); - } else { + case SMB_QUERY_FILE_UNIX_INFO2: + SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_INFO2); + SSVAL(pdata,6,0); /* Padding. */ + store_file_unix_basic_info2(conn, pdata + 8, fsp, psbuf); + default: SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); SSVAL(pdata,6,0); /* Padding. */ } @@ -5265,11 +5448,16 @@ static NTSTATUS smb_posix_open(connection_struct *conn, } SSVAL(pdata,2,fsp->fnum); - if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { + switch (info_level_return) { + case SMB_QUERY_FILE_UNIX_BASIC: SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); SSVAL(pdata,6,0); /* padding. */ store_file_unix_basic(conn, pdata + 8, fsp, psbuf); - } else { + case SMB_QUERY_FILE_UNIX_INFO2: + SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_INFO2); + SSVAL(pdata,6,0); /* padding. */ + store_file_unix_basic_info2(conn, pdata + 8, fsp, psbuf); + default: SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); SSVAL(pdata,6,0); /* padding. */ } @@ -5607,6 +5795,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char break; } + case SMB_SET_FILE_UNIX_INFO2: + { + status = smb_set_file_unix_info2(conn, + pdata, + total_data, + fsp, + fname, + &sbuf); + break; + } + case SMB_SET_FILE_UNIX_LINK: { if (tran_call != TRANSACT2_SETPATHINFO) { -- cgit From 872cd741caec2831578a3b0ef7741c814e05f50c Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 8 Mar 2007 18:45:44 +0000 Subject: r21765: Fix the build for HP-UX. (This used to be commit 04cb34ff9dbdc02f21ed8d938fb754478c2b89c1) --- source3/smbd/trans2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 441a798f27..45eb0067ef 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3038,9 +3038,14 @@ static const struct {unsigned stat_fflag; unsigned smb_fflag;} #endif #ifdef UF_HIDDEN - { UF_HIDDEN, EXT_HIDDEN } + { UF_HIDDEN, EXT_HIDDEN }, #endif + /* Do not remove. We need to guarantee that this array has at least one + * entry to build on HP-UX. + */ + { 0, 0 } + }; static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf, -- cgit From 41c8f3da97a443fc4a9a987a3c2588eb07e324b3 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 8 Mar 2007 20:54:13 +0000 Subject: r21766: Fix compiler warning. (This used to be commit f82ac78b2fa623f5868201bd54ffac9c8f318eef) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 45eb0067ef..a298a258f0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3069,7 +3069,7 @@ static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf, int *stat_fflags) { #ifdef HAVE_STAT_ST_FLAGS - uint32 max_fmask; + uint32 max_fmask = 0; int i; *stat_fflags = psbuf->st_flags; -- cgit From 12c617af08bdded3a3a60196016e9cb207eedccf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Mar 2007 02:16:03 +0000 Subject: r21769: Attempt to fix bug #4384 in old search code. We were accessing a pathname that hadn't gone through unix_convert ! That's a big no-no... Jeremy. (This used to be commit 33a67fd39e1a51944bf0783350aa6ef95dfafb84) --- source3/smbd/reply.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f85f635d6b..a9c94b8163 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -967,16 +967,13 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (status_len == 0) { SMB_STRUCT_STAT sbuf; - pstring dir2; pstrcpy(directory,path); - pstrcpy(dir2,path); nt_status = unix_convert(conn, directory, True, NULL, &sbuf); if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); return ERROR_NT(nt_status); } - unix_format(dir2); nt_status = check_name(conn, directory); if (!NT_STATUS_IS_OK(nt_status)) { @@ -984,23 +981,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(nt_status); } - p = strrchr_m(dir2,'/'); - if (p == NULL) { - pstrcpy(mask,dir2); - *dir2 = 0; - } else { - *p = 0; - pstrcpy(mask,p+1); - } - p = strrchr_m(directory,'/'); if (!p) { - *directory = 0; + pstrcpy(mask,directory); + pstrcpy(directory,"."); } else { *p = 0; + pstrcpy(mask,p+1); } - if (strlen(directory) == 0) { + if (*directory == '\0') { pstrcpy(directory,"."); } memset((char *)status,'\0',21); -- cgit From dd011f453eed247a92973206239129bc21c26534 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Mar 2007 02:40:49 +0000 Subject: r21770: For old DOS style searches we must remember if the initial search had a wildcard in order to correctly return no error on end of search. Found by Samba4 torture tester. Jeremy. (This used to be commit c74bcf7677123f273d44181ca053ba49b8c7ddae) --- source3/smbd/reply.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a9c94b8163..225e0e7407 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1010,6 +1010,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } string_set(&conn->dirpath,dptr_path(dptr_num)); pstrcpy(mask, dptr_wcard(dptr_num)); + /* + * For a 'continue' search we have no string. So + * check from the initial saved string. + */ + mask_contains_wcard = ms_has_wild(mask); } p = smb_buf(outbuf) + 3; -- cgit From f6c9f87e0577633f466154e3dca4c9342c92b115 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 9 Mar 2007 11:34:24 +0000 Subject: r21774: Fix the build with Fedora Core 6. tridge/vl: please check. Guenther (This used to be commit 39d54738db5eed106fca07a417843b1e7e4033ff) --- source3/smbd/notify_inotify.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 5fb414de4c..ff17d455f3 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -26,6 +26,10 @@ #ifdef HAVE_INOTIFY +#ifdef HAVE_ASM_TYPES_H +#include +#endif + #include #include -- cgit From 257d2e0d2a6cd4c2ea62399ec97ada46dd8c395c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Mar 2007 18:33:16 +0000 Subject: r21777: As Stevef requested and the Apple guys agreed, make mode_t in posix_open/posix_mkdir -> 8 bytes to match the SET_UNIX_INFO_BASIC call. Steve is updating the Wikki. Jeremy. (This used to be commit 2f1c95ac7718c1d2a75367ba712edd6b57069432) --- source3/smbd/trans2.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a298a258f0..5401aac15d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5229,11 +5229,13 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, uint16 info_level_return = 0; char *pdata = *ppdata; - if (total_data < 10) { + if (total_data < 18) { return NT_STATUS_INVALID_PARAMETER; } raw_unixmode = IVAL(pdata,8); + /* Next 4 bytes are not yet defined. */ + status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode); if (!NT_STATUS_IS_OK(status)) { return status; @@ -5259,7 +5261,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, close_file(fsp, NORMAL_CLOSE); } - info_level_return = SVAL(pdata,12); + info_level_return = SVAL(pdata,16); if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE; @@ -5321,7 +5323,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, int info = 0; uint16 info_level_return = 0; - if (total_data < 14) { + if (total_data < 18) { return NT_STATUS_INVALID_PARAMETER; } @@ -5373,6 +5375,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn, } raw_unixmode = IVAL(pdata,8); + /* Next 4 bytes are not yet defined. */ + status = unix_perms_from_wire(conn, psbuf, raw_unixmode, @@ -5424,7 +5428,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, extended_oplock_granted = True; } - info_level_return = SVAL(pdata,12); + info_level_return = SVAL(pdata,16); if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE; -- cgit From 5214cb6782b1ac01b4b23d53478fa11ad00915fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2007 02:33:17 +0000 Subject: r21783: Add in the "create info" field to the reply from POSIX_OPEN and POSIX_MKDIR as specified by Stevef in the wikki (extra 4 byte field). Also fix horrible bug in James's code (James you should review this for your Apple patch tree) where he failed to allocate the correct return memory size when returning a INFO2 struct. Added #define for the size of the INFO2 struct and made sure we allocate the correct size for return. Jeremy. (This used to be commit d88bc59cb4d5e8851b0856c67ed878ba8bd84552) --- source3/smbd/trans2.c | 54 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5401aac15d..01956d8119 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5227,6 +5227,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, mode_t unixmode = (mode_t)0; files_struct *fsp = NULL; uint16 info_level_return = 0; + int info; char *pdata = *ppdata; if (total_data < 18) { @@ -5254,7 +5255,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, FILE_CREATE, 0, mod_unixmode, - NULL, + &info, &fsp); if (NT_STATUS_IS_OK(status)) { @@ -5264,9 +5265,11 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, info_level_return = SVAL(pdata,16); if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { - *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE; + *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE; + } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) { + *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE; } else { - *pdata_return_size = 8; + *pdata_return_size = 12; } /* Realloc the data size */ @@ -5277,20 +5280,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, } SSVAL(pdata,0,NO_OPLOCK_RETURN); - SSVAL(pdata,2,0); + SSVAL(pdata,2,0); /* No fnum. */ + SIVAL(pdata,4,info); /* Was directory created. */ switch (info_level_return) { case SMB_QUERY_FILE_UNIX_BASIC: - SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); - SSVAL(pdata,6,0); /* Padding. */ - store_file_unix_basic(conn, pdata + 8, fsp, psbuf); + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); + SSVAL(pdata,10,0); /* Padding. */ + store_file_unix_basic(conn, pdata + 12, fsp, psbuf); case SMB_QUERY_FILE_UNIX_INFO2: - SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_INFO2); - SSVAL(pdata,6,0); /* Padding. */ - store_file_unix_basic_info2(conn, pdata + 8, fsp, psbuf); + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); + SSVAL(pdata,10,0); /* Padding. */ + store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); default: - SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); - SSVAL(pdata,6,0); /* Padding. */ + SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); + SSVAL(pdata,10,0); /* Padding. */ } return status; @@ -5430,10 +5434,14 @@ static NTSTATUS smb_posix_open(connection_struct *conn, info_level_return = SVAL(pdata,16); + /* Allocate the correct return size. */ + if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) { - *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE; + *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE; + } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) { + *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE; } else { - *pdata_return_size = 8; + *pdata_return_size = 12; } /* Realloc the data size */ @@ -5457,18 +5465,20 @@ static NTSTATUS smb_posix_open(connection_struct *conn, } SSVAL(pdata,2,fsp->fnum); + SIVAL(pdata,4,info); /* Was file created etc. */ + switch (info_level_return) { case SMB_QUERY_FILE_UNIX_BASIC: - SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC); - SSVAL(pdata,6,0); /* padding. */ - store_file_unix_basic(conn, pdata + 8, fsp, psbuf); + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); + SSVAL(pdata,10,0); /* padding. */ + store_file_unix_basic(conn, pdata + 12, fsp, psbuf); case SMB_QUERY_FILE_UNIX_INFO2: - SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_INFO2); - SSVAL(pdata,6,0); /* padding. */ - store_file_unix_basic_info2(conn, pdata + 8, fsp, psbuf); + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); + SSVAL(pdata,10,0); /* padding. */ + store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); default: - SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED); - SSVAL(pdata,6,0); /* padding. */ + SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); + SSVAL(pdata,10,0); /* padding. */ } return NT_STATUS_OK; } -- cgit From 0d91334fe799f6b50a8265f9dc097411c3a29e18 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Mar 2007 16:49:16 +0000 Subject: r21784: Replace smb_register_idle_event() with event_add_timed(). This fixes winbind who did not run the idle events to drop ldap connections. Volker (This used to be commit af3308ce5a21220ff4c510de356dbaa6cf9ff997) --- source3/smbd/process.c | 3 --- source3/smbd/server.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dbac553aea..11ef33679f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1351,9 +1351,6 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t /* become root again if waiting */ change_to_root_user(); - /* run all registered idle events */ - smb_run_idle_events(t); - /* check if we need to reload services */ check_reload(t); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ab32d656d3..0ae2f3e836 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1010,7 +1010,7 @@ extern void build_options(BOOL screen); /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ - if(!initialize_password_db(False)) + if(!initialize_password_db(False, smbd_event_context())) exit(1); if (!secrets_init()) { -- cgit From 59c071f707c8bd366b807869e88cbf4714185c29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Mar 2007 05:54:14 +0000 Subject: r21792: Fix crash bug triggered by Excel reported by Jerry. Bad cut-n-paste on rewrite of timestamps. Jeremy. (This used to be commit 1809e0866ae135af1d5ea36a8534e1678ee9b27d) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 01956d8119..58fa4eb31b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3403,7 +3403,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); if (fsp1 && !null_timespec(fsp1->pending_modtime)) { /* the pending modtime overrides the current modtime */ - mtime_ts = fsp->pending_modtime; + mtime_ts = fsp1->pending_modtime; } if (fsp1 && fsp1->initial_allocation_size) { allocation_size = get_allocation_size(conn, fsp1, &sbuf); -- cgit From 24cdd7c73389c9eed981313973df2c3595222781 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Mar 2007 17:55:24 +0000 Subject: r21800: Check-in the DFS rewrite. I am still testing this but it works from smbclient and Windows, and I am promising to support and fix both client and server code moving forward. Still need to test the RPC admin support but I haven't changed that code. Jeremy. (This used to be commit 7a7862c01d07796ef206b255c676ad7dc2cc42fc) --- source3/smbd/dir.c | 6 +- source3/smbd/msdfs.c | 829 +++++++++++++++++++++++++++---------------------- source3/smbd/nttrans.c | 33 +- source3/smbd/reply.c | 180 ++++++++--- source3/smbd/trans2.c | 43 ++- 5 files changed, 650 insertions(+), 441 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 2795b2a24b..db3e155ae4 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1017,6 +1017,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * } if (hide_unreadable || hide_unwriteable || hide_special) { + pstring link_target; char *entry = NULL; if (asprintf(&entry, "%s/%s", dir_path, name) == -1) { @@ -1026,10 +1027,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * /* If it's a dfs symlink, ignore _hide xxxx_ options */ if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - /* We get away with NULL talloc ctx here as - we're not interested in the link contents - so we have nothing to free. */ - is_msdfs_link(NULL, conn, entry, NULL, NULL, NULL)) { + is_msdfs_link(conn, entry, link_target, NULL)) { SAFE_FREE(entry); return True; } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 861588e6b7..ae2009ad38 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1,7 +1,7 @@ /* Unix SMB/Netbios implementation. Version 3.0 - MSDfs services for Samba + MSDFS services for Samba Copyright (C) Shirish Kalele 2000 Copyright (C) Jeremy Allison 2007 @@ -27,105 +27,142 @@ extern uint32 global_client_caps; /********************************************************************** - Parse the pathname of the form \hostname\service\reqpath - into the dfs_path structure - **********************************************************************/ + Parse a DFS pathname of the form \hostname\service\reqpath + into the dfs_path structure. + If POSIX pathnames is true, the pathname may also be of the + form /hostname/service/reqpath. + We cope with either here. + + Unfortunately, due to broken clients who might set the + SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then + send a local path, we have to cope with that too.... + + JRA. +**********************************************************************/ -static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp) +static NTSTATUS parse_dfs_path(const char *pathname, + BOOL allow_wcards, + struct dfs_path *pdp, + BOOL *ppath_contains_wcard) { pstring pathname_local; - char *p, *temp; + char *p,*temp; + NTSTATUS status = NT_STATUS_OK; + char sepchar; + + ZERO_STRUCTP(pdp); pstrcpy(pathname_local,pathname); p = temp = pathname_local; - ZERO_STRUCTP(pdp); + pdp->posix_path = (lp_posix_pathnames() && *pathname == '/'); - trim_char(temp,'\\','\\'); - DEBUG(10,("temp in parse_dfs_path: .%s. after trimming \\'s\n",temp)); + sepchar = pdp->posix_path ? '/' : '\\'; - /* now tokenize */ - /* parse out hostname */ - p = strchr_m(temp,'\\'); - if(p == NULL) { - return False; - } - *p = '\0'; - pstrcpy(pdp->hostname,temp); - DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); + if (*pathname != sepchar) { + DEBUG(10,("parse_dfs_path: path %s doesn't start with %c\n", + pathname, sepchar )); + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ - /* parse out servicename */ - temp = p+1; - p = strchr_m(temp,'\\'); - if(p == NULL) { - pstrcpy(pdp->servicename,temp); - pdp->reqpath[0] = '\0'; - return True; + pdp->hostname[0] = '\0'; + pdp->servicename[0] = '\0'; + + /* We've got no info about separators. */ + pdp->posix_path = lp_posix_pathnames(); + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + temp)); + goto local_path; } - *p = '\0'; - pstrcpy(pdp->servicename,temp); - DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); - /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + trim_char(temp,sepchar,sepchar); - DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); - return True; -} + DEBUG(10,("parse_dfs_path: temp = |%s| after trimming %c's\n", + temp, sepchar)); -/********************************************************************** - Parse the pathname of the form /hostname/service/reqpath - into the dfs_path structure - This code is dependent on the fact that check_path_syntax() will - convert '\\' characters to '/'. - **********************************************************************/ + /* Now tokenize. */ + /* Parse out hostname. */ + p = strchr_m(temp,sepchar); + if(p == NULL) { + DEBUG(10,("parse_dfs_path: can't parse hostname from path %s\n", + temp)); + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ -static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) -{ - pstring pathname_local; - char *p,*temp; - const char sepchar = '/'; + pdp->hostname[0] = '\0'; + pdp->servicename[0] = '\0'; - pstrcpy(pathname_local,pathname); - p = temp = pathname_local; + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + temp)); + goto local_path; + } + *p = '\0'; + fstrcpy(pdp->hostname,temp); + DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); - ZERO_STRUCTP(pdp); + /* If we got a hostname, is it ours (or an IP address) ? */ + if (!is_myname_or_ipaddr(pdp->hostname)) { + /* Repair path. */ + *p = sepchar; + DEBUG(10,("parse_dfs_path: hostname %s isn't ours. Try local path from path %s\n", + pdp->hostname, temp)); + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ - trim_char(temp,sepchar,sepchar); - DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming /'s\n",temp)); + pdp->hostname[0] = '\0'; + pdp->servicename[0] = '\0'; - /* now tokenize */ - /* parse out hostname */ - p = strchr_m(temp,sepchar); - if(p == NULL) { - return False; + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + temp)); + goto local_path; } - *p = '\0'; - pstrcpy(pdp->hostname,temp); - DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname)); - /* parse out servicename */ + /* Parse out servicename. */ temp = p+1; p = strchr_m(temp,sepchar); if(p == NULL) { - pstrcpy(pdp->servicename,temp); + fstrcpy(pdp->servicename,temp); pdp->reqpath[0] = '\0'; - return True; + return NT_STATUS_OK; } *p = '\0'; - pstrcpy(pdp->servicename,temp); - DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); + fstrcpy(pdp->servicename,temp); + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + + p++; + + local_path: - /* rest is reqpath */ - if (allow_wcards) { - BOOL path_contains_wcard; - check_path_syntax_wcard(pdp->reqpath, p+1, &path_contains_wcard); + *ppath_contains_wcard = False; + + /* Rest is reqpath. */ + if (pdp->posix_path) { + status = check_path_syntax_posix(pdp->reqpath, p); } else { - check_path_syntax(pdp->reqpath, p+1); + if (allow_wcards) { + status = check_path_syntax_wcard(pdp->reqpath, p, ppath_contains_wcard); + } else { + status = check_path_syntax(pdp->reqpath, p); + } } - DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); - return True; + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("parse_dfs_path: '%s' failed with %s\n", + p, nt_errstr(status) )); + return status; + } + + DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); + return NT_STATUS_OK; } /******************************************************** @@ -133,7 +170,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL Note this CHANGES CWD !!!! JRA. *********************************************************/ -static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) +static BOOL create_conn_struct(connection_struct *conn, int snum, const char *path) { pstring connpath; @@ -143,19 +180,19 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) pstring_sub(connpath , "%S", lp_servicename(snum)); /* needed for smbd_vfs_init() */ - - if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) { - DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return False; - } - if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) { + if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { + DEBUG(0,("talloc_init(connection_struct) failed!\n")); + return False; + } + + if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); return False; } - + conn->params->service = snum; - + set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { @@ -182,11 +219,27 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) /********************************************************************** Parse the contents of a symlink to verify if it is an msdfs referral - A valid referral is of the form: msdfs:server1\share1,server2\share2 - talloc CTX can be NULL here if preflist and refcount pointers are null. + A valid referral is of the form: + + msdfs:server1\share1,server2\share2 + msdfs:server1\share1\pathname,server2\share2\pathname + msdfs:server1/share1,server2/share2 + msdfs:server1/share1/pathname,server2/share2/pathname. + + Note that the alternate paths returned here must be of the canonicalized + form: + + \server\share or + \server\share\path\to\file, + + even in posix path mode. This is because we have no knowledge if the + server we're referring to understands posix paths. **********************************************************************/ -static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist, int *refcount) +static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, + char *target, + struct referral **preflist, + int *refcount) { pstring temp; char *prot; @@ -194,45 +247,28 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist int count = 0, i; struct referral *reflist; - pstrcpy(temp,buf); - + pstrcpy(temp,target); prot = strtok(temp,":"); - if (!strequal(prot, "msdfs")) { - return False; - } - - /* No referral list requested. Just yes/no. */ - if (!preflist) { - return True; - } - - if (!ctx) { - DEBUG(0,("parse_symlink: logic error. TALLOC_CTX should not be null.\n")); - return True; - } - /* parse out the alternate paths */ while((countst_mode)) { - /* open the link and read it */ - referral_len = SMB_VFS_READLINK(conn, path, referral, sizeof(pstring)-1); - if (referral_len == -1) { - DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno))); - return False; - } + if (!S_ISLNK(sbufp->st_mode)) { + DEBUG(5,("is_msdfs_link: %s is not a link.\n",path)); + return False; + } - referral[referral_len] = '\0'; - DEBUG(5,("is_msdfs_link: %s -> %s\n",path,referral)); - if (parse_symlink(ctx, referral, reflistp, refcnt)) { - return True; - } + /* open the link and read it */ + referral_len = SMB_VFS_READLINK(conn, path, link_target, sizeof(pstring)-1); + if (referral_len == -1) { + DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", + path, strerror(errno))); + return False; } - return False; + link_target[referral_len] = '\0'; + + DEBUG(5,("is_msdfs_link: %s -> %s\n",path, link_target)); + + if (!strnequal(link_target, "msdfs:", 6)) { + return False; + } + return True; } /***************************************************************** Used by other functions to decide if a dfs path is remote, -and to get the list of referred locations for that remote path. + and to get the list of referred locations for that remote path. -findfirst_flag: For findfirsts, dfs links themselves are not -redirected, but paths beyond the links are. For normal smb calls, -even dfs links need to be redirected. - -self_referralp: clients expect a dfs referral for the same share when -they request referrals for dfs roots on a server. + search_flag: For findfirsts, dfs links themselves are not + redirected, but paths beyond the links are. For normal smb calls, + even dfs links need to be redirected. -consumedcntp: how much of the dfs path is being redirected. the client -should try the remaining path on the redirected server. + consumedcntp: how much of the dfs path is being redirected. the client + should try the remaining path on the redirected server. -TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp -are also NULL. + If this returns NT_STATUS_PATH_NOT_COVERED the contents of the msdfs + link redirect are in targetpath. *****************************************************************/ -static BOOL resolve_dfs_path(TALLOC_CTX *ctx, - const char *dfspath, - struct dfs_path *dp, - connection_struct *conn, - BOOL search_flag, - struct referral **reflistpp, - int *refcntp, - BOOL *self_referralp, - int *consumedcntp) +static NTSTATUS dfs_path_lookup(connection_struct *conn, + const char *dfspath, /* Incoming complete dfs path */ + const struct dfs_path *pdp, /* Parsed out server+share+extrapath. */ + BOOL search_flag, /* Called from a findfirst ? */ + int *consumedcntp, + pstring targetpath) { - pstring localpath; - int consumed_level = 1; - char *p; + char *p = NULL; + char *q = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; - pstring reqpath; - pstring local_dfspath; - - if (!dp || !conn) { - DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n")); - return False; - } - - if (!ctx && (reflistpp || refcntp)) { - DEBUG(0,("resolve_dfs_path: logic error. TALLOC_CTX must not be NULL.\n")); - } - - if (dp->reqpath[0] == '\0') { - if (self_referralp) { - DEBUG(6,("resolve_dfs_path: self-referral. returning False\n")); - *self_referralp = True; - } - return False; - } + pstring localpath; + pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */ - DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); + DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n", + conn->connectpath, pdp->reqpath)); /* * Note the unix path conversion here we're doing we can @@ -364,151 +376,188 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, * think this is needed. JRA. */ - pstrcpy(localpath, dp->reqpath); - - status = unix_convert(conn, localpath, False, NULL, &sbuf); + pstrcpy(localpath, pdp->reqpath); + status = unix_convert(conn, localpath, search_flag, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - return False; + return status; } - /* check if need to redirect */ - if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { - if ( search_flag ) { - DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " + /* Optimization - check if we can redirect the whole path. */ + + if (is_msdfs_link(conn, localpath, targetpath, NULL)) { + if (search_flag) { + DEBUG(6,("dfs_path_lookup (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); - return False; + return NT_STATUS_OK; } - DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); + DEBUG(6,("dfs_path_lookup: %s resolves to a " + "valid dfs link %s.\n", dfspath, targetpath)); + if (consumedcntp) { *consumedcntp = strlen(dfspath); } - return True; + return NT_STATUS_PATH_NOT_COVERED; } /* Prepare to test only for '/' components in the given path, - * so replace all '\\' characters with '/'. */ + * so if a Windows path replace all '\\' characters with '/'. + * For a POSIX DFS path we know all separators are already '/'. */ - pstrcpy(local_dfspath, dfspath); - string_replace(local_dfspath, '\\', '/'); + pstrcpy(canon_dfspath, dfspath); + if (!pdp->posix_path) { + string_replace(canon_dfspath, '\\', '/'); + } + + /* + * Redirect if any component in the path is a link. + * We do this by walking backwards through the + * local path, chopping off the last component + * in both the local path and the canonicalized + * DFS path. If we hit a DFS link then we're done. + */ + + p = strrchr_m(localpath, '/'); + if (consumedcntp) { + q = strrchr_m(canon_dfspath, '/'); + } - /* redirect if any component in the path is a link */ - pstrcpy(reqpath, localpath); - p = strrchr_m(reqpath, '/'); while (p) { *p = '\0'; - pstrcpy(localpath, reqpath); - if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { - DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); - - /* To find the path consumed, we truncate the original - DFS pathname passed to use to remove the last - component. The length of the resulting string is - the path consumed - */ - + if (q) { + *q = '\0'; + } + + if (is_msdfs_link(conn, localpath, targetpath, NULL)) { + DEBUG(4, ("dfs_path_lookup: Redirecting %s because " + "parent %s is dfs link\n", dfspath, localpath)); + if (consumedcntp) { - pstring buf; - pstrcpy(buf, local_dfspath); - trim_char(buf, '\0', '/'); - for (; consumed_level; consumed_level--) { - char *q; - /* We made sure only '/' may be a separator above. */ - q = strrchr_m(buf, '/'); - if (q) { - *q = 0; - } - } - *consumedcntp = strlen(buf); - DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp)); + *consumedcntp = strlen(canon_dfspath); + DEBUG(10, ("dfs_path_lookup: Path consumed: %s " + "(%d)\n", canon_dfspath, *consumedcntp)); } - - return True; + + return NT_STATUS_PATH_NOT_COVERED; + } + + /* Step back on the filesystem. */ + p = strrchr_m(localpath, '/'); + + if (consumedcntp) { + /* And in the canonicalized dfs path. */ + q = strrchr_m(canon_dfspath, '/'); } - p = strrchr_m(reqpath, '/'); - consumed_level++; } - return False; + return NT_STATUS_OK; } /***************************************************************** - Decides if a dfs pathname should be redirected or not. - If not, the pathname is converted to a tcon-relative local unix path - - search_wcard_flag: this flag performs 2 functions bother related - to searches. See resolve_dfs_path() and parse_processed_dfs_path() - for details. + Decides if a dfs pathname should be redirected or not. + If not, the pathname is converted to a tcon-relative local unix path + + search_wcard_flag: this flag performs 2 functions bother related + to searches. See resolve_dfs_path() and parse_dfs_path_XX() + for details. + + This function can return NT_STATUS_OK, meaning use the returned path as-is + (mapped into a local path). + or NT_STATUS_NOT_COVERED meaning return a DFS redirect, or + any other NT_STATUS error which is a genuine error to be + returned to the client. *****************************************************************/ -static BOOL dfs_redirect( connection_struct *conn, pstring pathname, BOOL search_wcard_flag ) +static NTSTATUS dfs_redirect( connection_struct *conn, + pstring dfs_path, + BOOL search_wcard_flag, + BOOL *ppath_contains_wcard) { + NTSTATUS status; struct dfs_path dp; + pstring targetpath; - if (!conn || !pathname) { - return False; + status = parse_dfs_path(dfs_path, search_wcard_flag, &dp, ppath_contains_wcard); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (dp.reqpath[0] == '\0') { + DEBUG(5,("dfs_redirect: self-referral.\n")); + return NT_STATUS_OK; } - parse_processed_dfs_path(pathname, &dp, search_wcard_flag); + /* If dfs pathname for a non-dfs share, convert to tcon-relative + path and return OK */ - /* if dfs pathname for a non-dfs share, convert to tcon-relative - path and return false */ if (!lp_msdfs_root(SNUM(conn))) { - pstrcpy(pathname, dp.reqpath); - return False; + pstrcpy(dfs_path, dp.reqpath); + return NT_STATUS_OK; } - - if ( !( strequal(dp.servicename, lp_servicename(SNUM(conn))) - || ( strequal(dp.servicename, HOMES_NAME) - && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) - { - return False; + + /* If it looked like a local path (zero hostname/servicename) + * just treat as a tcon-relative path. */ + + if (dp.hostname[0] == '\0' && dp.servicename[0] == '\0') { + pstrcpy(dfs_path, dp.reqpath); + return NT_STATUS_OK; } - if (resolve_dfs_path(NULL, pathname, &dp, conn, search_wcard_flag, - NULL, NULL, NULL, NULL)) { - DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); - return True; - } else { - DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname)); + if (!( strequal(dp.servicename, lp_servicename(SNUM(conn))) + || (strequal(dp.servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) { - /* Form non-dfs tcon-relative path */ - pstrcpy(pathname, dp.reqpath); + /* The given sharename doesn't match this connection. */ - DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname)); - return False; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + status = dfs_path_lookup(conn, dfs_path, &dp, + search_wcard_flag, NULL, targetpath); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { + DEBUG(3,("dfs_redirect: Redirecting %s\n", dfs_path)); + } else { + DEBUG(10,("dfs_redirect: dfs_path_lookup failed for %s with %s\n", + dfs_path, nt_errstr(status) )); + } + return status; } - /* never reached */ + DEBUG(3,("dfs_redirect: Not redirecting %s.\n", dfs_path)); + + /* Form non-dfs tcon-relative path */ + pstrcpy(dfs_path, dp.reqpath); + + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", dfs_path)); + return NT_STATUS_OK; } /********************************************************************** Return a self referral. **********************************************************************/ -static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, - int *consumedcntp, BOOL *self_referralp) +static BOOL self_ref(TALLOC_CTX *ctx, + const char *dfs_path, + struct junction_map *jucn, + int *consumedcntp, + BOOL *self_referralp) { struct referral *ref; - if (self_referralp != NULL) { - *self_referralp = True; - } + *self_referralp = True; jucn->referral_count = 1; - if((ref = TALLOC_P(ctx, struct referral)) == NULL) { - DEBUG(0,("self_ref: malloc failed for referral\n")); + if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { + DEBUG(0,("self_ref: talloc failed for referral\n")); return False; } - pstrcpy(ref->alternate_path,pathname); + pstrcpy(ref->alternate_path,dfs_path); ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) { - *consumedcntp = strlen(pathname); - } - + *consumedcntp = strlen(dfs_path); return True; } @@ -517,40 +566,39 @@ static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map junction_map structure. **********************************************************************/ -BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, - int *consumedcntp, BOOL *self_referralp) +BOOL get_referred_path(TALLOC_CTX *ctx, + const char *dfs_path, + struct junction_map *jucn, + int *consumedcntp, + BOOL *self_referralp) { - struct dfs_path dp; - struct connection_struct conns; struct connection_struct *conn = &conns; + struct dfs_path dp; pstring conn_path; + pstring targetpath; int snum; + NTSTATUS status; BOOL ret = False; - BOOL self_referral = False; - - if (!pathname || !jucn) { - return False; - } + BOOL dummy; ZERO_STRUCT(conns); - if (self_referralp) { - *self_referralp = False; - } else { - self_referralp = &self_referral; - } + *self_referralp = False; - parse_dfs_path(pathname, &dp); + status = parse_dfs_path(dfs_path, False, &dp, &dummy); + if (!NT_STATUS_IS_OK(status)) { + return False; + } /* Verify hostname in path */ if (!is_myname_or_ipaddr(dp.hostname)) { DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - dp.hostname, pathname)); + dp.hostname, dfs_path)); return False; } - pstrcpy(jucn->service_name, dp.servicename); + fstrcpy(jucn->service_name, dp.servicename); pstrcpy(jucn->volume_name, dp.reqpath); /* Verify the share is a dfs root */ @@ -562,8 +610,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma } if (!lp_msdfs_root(snum)) { - DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n", - dp.servicename, pathname)); + DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n", + dp.servicename, dfs_path)); goto out; } @@ -575,15 +623,23 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma */ if (dp.reqpath[0] == '\0') { - - struct referral* ref; + struct referral *ref; if (*lp_msdfs_proxy(snum) == '\0') { - return self_ref(ctx, pathname, jucn, consumedcntp, self_referralp); + return self_ref(ctx, + dfs_path, + jucn, + consumedcntp, + self_referralp); } + /* + * It's an msdfs proxy share. Redirect to + * the configured target share. + */ + jucn->referral_count = 1; - if ((ref = TALLOC_P(ctx, struct referral)) == NULL) { + if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); goto out; } @@ -595,9 +651,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) { - *consumedcntp = strlen(pathname); - } + *consumedcntp = strlen(dfs_path); ret = True; goto out; } @@ -607,23 +661,27 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma return False; } - /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(ctx, pathname, &dp, conn, False, - &jucn->referral_list, &jucn->referral_count, - self_referralp, consumedcntp)) { - if (!*self_referralp) { - DEBUG(3,("get_referred_path: No valid referrals for path %s\n", pathname)); - goto out; - } + /* If this is a DFS path dfs_lookup should return + * NT_STATUS_PATH_NOT_COVERED. */ + + status = dfs_path_lookup(conn, dfs_path, &dp, + False, consumedcntp, targetpath); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { + DEBUG(3,("get_referred_path: No valid referrals for path %s\n", + dfs_path)); + goto out; } - - /* if self_referral, fill up the junction map */ - if (*self_referralp) { - if (self_ref(ctx, pathname, jucn, consumedcntp, self_referralp) == False) { - goto out; - } + + /* We know this is a valid dfs link. Parse the targetpath. */ + if (!parse_msdfs_symlink(ctx, targetpath, + &jucn->referral_list, + &jucn->referral_count)) { + DEBUG(3,("get_referred_path: failed to parse symlink " + "target %s\n", targetpath )); + goto out; } - + ret = True; out: @@ -632,10 +690,11 @@ out: return ret; } -static int setup_ver2_dfs_referral(char *pathname, char **ppdata, - struct junction_map *junction, - int consumedcnt, - BOOL self_referral) +static int setup_ver2_dfs_referral(const char *pathname, + char **ppdata, + struct junction_map *junction, + int consumedcnt, + BOOL self_referral) { char* pdata = *ppdata; @@ -647,7 +706,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, int reply_size = 0; int i=0; - DEBUG(10,("setting up version2 referral\nRequested path:\n")); + DEBUG(10,("Setting up version2 referral\nRequested path:\n")); requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring), STR_TERMINATE); @@ -681,7 +740,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, pdata = (char *)SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { - DEBUG(0,("malloc failed for Realloc!\n")); + DEBUG(0,("Realloc failed!\n")); return -1; } *ppdata = pdata; @@ -732,10 +791,11 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, return reply_size; } -static int setup_ver3_dfs_referral(char *pathname, char **ppdata, - struct junction_map *junction, - int consumedcnt, - BOOL self_referral) +static int setup_ver3_dfs_referral(const char *pathname, + char **ppdata, + struct junction_map *junction, + int consumedcnt, + BOOL self_referral) { char* pdata = *ppdata; @@ -816,17 +876,23 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, } /****************************************************************** - Set up the Dfs referral for the dfs pathname + Set up the DFS referral for the dfs pathname. This call returns + the amount of the path covered by this server, and where the + client should be redirected to. This is the meat of the + TRANS2_GET_DFS_REFERRAL call. ******************************************************************/ -int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char **ppdata) +int setup_dfs_referral(connection_struct *orig_conn, + const char *dfs_path, + int max_referral_level, + char **ppdata) { struct junction_map junction; - int consumedcnt; + int consumedcnt = 0; BOOL self_referral = False; - pstring buf; int reply_size = 0; - char *pathnamep = pathname; + char *pathnamep = NULL; + pstring local_dfs_path; TALLOC_CTX *ctx; if (!(ctx=talloc_init("setup_dfs_referral"))) { @@ -836,21 +902,24 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref ZERO_STRUCT(junction); /* get the junction entry */ - if (!pathnamep) { + if (!dfs_path) { talloc_destroy(ctx); return -1; } - /* Trim pathname sent by client so it begins with only one backslash. - Two backslashes confuse some dfs clients + /* + * Trim pathname sent by client so it begins with only one backslash. + * Two backslashes confuse some dfs clients */ - while (pathnamep[0] == '\\' && pathnamep[1] == '\\') { + + pstrcpy(local_dfs_path, dfs_path); + pathnamep = local_dfs_path; + while (IS_DIRECTORY_SEP(pathnamep[0]) && IS_DIRECTORY_SEP(pathnamep[1])) { pathnamep++; } - pstrcpy(buf, pathnamep); /* The following call can change cwd. */ - if (!get_referred_path(ctx, buf, &junction, &consumedcnt, &self_referral)) { + if (!get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral)) { vfs_ChDir(orig_conn,orig_conn->connectpath); talloc_destroy(ctx); return -1; @@ -908,31 +977,40 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref **********************************************************************/ /********************************************************************* - Creates a junction structure from a Dfs pathname + Creates a junction structure from a DFS pathname **********************************************************************/ -BOOL create_junction(const char *pathname, struct junction_map *jucn) +BOOL create_junction(const char *dfs_path, struct junction_map *jucn) { - struct dfs_path dp; + int snum; + BOOL dummy; + struct dfs_path dp; - parse_dfs_path(pathname,&dp); + NTSTATUS status = parse_dfs_path(dfs_path, False, &dp, &dummy); + + if (!NT_STATUS_IS_OK(status)) { + return False; + } - /* check if path is dfs : validate first token */ + /* check if path is dfs : validate first token */ if (!is_myname_or_ipaddr(dp.hostname)) { DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", - dp.hostname, pathname)); + dp.hostname, dfs_path)); return False; } /* Check for a non-DFS share */ - if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { - DEBUG(4,("create_junction: %s is not an msdfs root.\n", dp.servicename)); + snum = lp_servicenumber(dp.servicename); + + if(snum < 0 || !lp_msdfs_root(snum)) { + DEBUG(4,("create_junction: %s is not an msdfs root.\n", + dp.servicename)); return False; } - pstrcpy(jucn->service_name,dp.servicename); + fstrcpy(jucn->service_name,dp.servicename); pstrcpy(jucn->volume_name,dp.reqpath); - pstrcpy(jucn->comment, lp_comment(lp_servicenumber(dp.servicename))); + pstrcpy(jucn->comment, lp_comment(snum)); return True; } @@ -940,16 +1018,14 @@ BOOL create_junction(const char *pathname, struct junction_map *jucn) Forms a valid Unix pathname from the junction **********************************************************************/ -static BOOL junction_to_local_path(struct junction_map *jucn, char *path, - int max_pathlen, connection_struct *conn) +static BOOL junction_to_local_path(struct junction_map *jucn, + char *path, + int max_pathlen, + connection_struct *conn_out) { int snum; pstring conn_path; - if(!path || !jucn) { - return False; - } - snum = lp_servicenumber(jucn->service_name); if(snum < 0) { return False; @@ -960,7 +1036,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn, char *path, safe_strcat(path, jucn->volume_name, max_pathlen-1); pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) { + if (!create_conn_struct(conn_out, snum, conn_path)) { return False; } @@ -983,11 +1059,12 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) return False; } - /* form the msdfs_link contents */ + /* Form the msdfs_link contents */ pstrcpy(msdfs_link, "msdfs:"); for(i=0; ireferral_count; i++) { char* refpath = jucn->referral_list[i].alternate_path; + /* Alternate paths always use Windows separators. */ trim_char(refpath, '\\', '\\'); if(*refpath == '\0') { if (i == 0) { @@ -1005,7 +1082,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) } } - DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); + DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", + path, msdfs_link)); if(exists) { if(SMB_VFS_UNLINK(conn,path)!=0) { @@ -1021,7 +1099,7 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) ret = True; - + out: conn_free_internal(conn); @@ -1048,13 +1126,16 @@ BOOL remove_msdfs_link(struct junction_map *jucn) return ret; } -static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain) +static int form_junctions(TALLOC_CTX *ctx, + int snum, + struct junction_map *jucn, + int jn_remain) { int cnt = 0; SMB_STRUCT_DIR *dirp; - char* dname; + char *dname; pstring connect_path; - char* service_name = lp_servicename(snum); + char *service_name = lp_servicename(snum); connection_struct conn; struct referral *ref = NULL; @@ -1082,13 +1163,13 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, DO NOT REMOVE THIS: NT clients will not work with us if this is not present */ - pstrcpy(jucn[cnt].service_name, service_name); + fstrcpy(jucn[cnt].service_name, service_name); jucn[cnt].volume_name[0] = '\0'; jucn[cnt].referral_count = 1; - ref = jucn[cnt].referral_list = TALLOC_P(ctx, struct referral); + ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral); if (jucn[cnt].referral_list == NULL) { - DEBUG(0, ("Malloc failed!\n")); + DEBUG(0, ("talloc failed!\n")); goto out; } @@ -1099,9 +1180,10 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, cnt++; goto out; } - - slprintf(ref->alternate_path, sizeof(pstring)-1, - "\\\\%s\\%s", get_local_machine_name(), service_name); + + pstr_sprintf(ref->alternate_path, "\\\\%s\\%s", + get_local_machine_name(), + service_name); cnt++; /* Now enumerate all dfs links */ @@ -1111,16 +1193,22 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, } while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + pstring link_target; if (cnt >= jn_remain) { SMB_VFS_CLOSEDIR(&conn,dirp); DEBUG(2, ("ran out of MSDFS junction slots")); goto out; } - if (is_msdfs_link(ctx, &conn, dname, &jucn[cnt].referral_list, - &jucn[cnt].referral_count, NULL)) { - pstrcpy(jucn[cnt].service_name, service_name); - pstrcpy(jucn[cnt].volume_name, dname); - cnt++; + if (is_msdfs_link(&conn, dname, link_target, NULL)) { + if (parse_msdfs_symlink(ctx, + link_target, + &jucn[cnt].referral_list, + &jucn[cnt].referral_count)) { + + fstrcpy(jucn[cnt].service_name, service_name); + pstrcpy(jucn[cnt].volume_name, dname); + cnt++; + } } } @@ -1160,13 +1248,14 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) Core function to resolve a dfs pathname. ******************************************************************************/ -BOOL resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) +NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) { - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - dfs_redirect(conn, name, False)) { - return False; /* Pathname didn't resolve. */ + NTSTATUS status = NT_STATUS_OK; + BOOL dummy; + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + status = dfs_redirect(conn, name, False, &dummy); } - return True; + return status; } /****************************************************************************** @@ -1176,11 +1265,11 @@ BOOL resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) we're allowing wildcards and when we're not. JRA. ******************************************************************************/ -BOOL resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name) +NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard) { - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - dfs_redirect(conn, name, True)) { - return False; /* Pathname didn't resolve. */ + NTSTATUS status = NT_STATUS_OK; + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + status = dfs_redirect(conn, name, True, ppath_contains_wcard); } - return True; + return status; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0cc7193170..0ecb14f9c7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -615,9 +615,13 @@ int reply_ntcreate_and_X(connection_struct *conn, * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -1273,8 +1277,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o new_file_attributes = set_posix_case_semantics(conn, file_attributes); - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); @@ -1754,13 +1762,22 @@ int reply_ntrename(connection_struct *conn, return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { + + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 225e0e7407..c0a2e23c3d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -44,9 +44,12 @@ extern BOOL global_encrypted_passwords_negotiated; set. ****************************************************************************/ +/* Custom version for processing POSIX paths. */ +#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\')) + NTSTATUS check_path_syntax_internal(pstring destname, const pstring srcname, - BOOL windows_path, + BOOL posix_path, BOOL *p_last_component_contains_wcard) { char *d = destname; @@ -57,13 +60,13 @@ NTSTATUS check_path_syntax_internal(pstring destname, *p_last_component_contains_wcard = False; while (*s) { - if (IS_DIRECTORY_SEP(*s)) { + if (IS_PATH_SEP(*s,posix_path)) { /* * Safe to assume is not the second part of a mb char * as this is handled below. */ /* Eat multiple '/' or '\\' */ - while (IS_DIRECTORY_SEP(*s)) { + while (IS_PATH_SEP(*s,posix_path)) { s++; } if ((d != destname) && (*s != '\0')) { @@ -78,7 +81,7 @@ NTSTATUS check_path_syntax_internal(pstring destname, } if (start_of_name_component) { - if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { + if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) { /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */ /* @@ -108,8 +111,8 @@ NTSTATUS check_path_syntax_internal(pstring destname, /* We're still at the start of a name component, just the previous one. */ continue; - } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) { - if (!windows_path) { + } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) { + if (posix_path) { /* Eat the '.' */ s++; continue; @@ -119,7 +122,7 @@ NTSTATUS check_path_syntax_internal(pstring destname, } if (!(*s & 0x80)) { - if (windows_path) { + if (!posix_path) { if (*s <= 0x1f) { return NT_STATUS_OBJECT_NAME_INVALID; } @@ -177,7 +180,7 @@ NTSTATUS check_path_syntax_internal(pstring destname, NTSTATUS check_path_syntax(pstring destname, const pstring srcname) { BOOL ignore; - return check_path_syntax_internal(destname, srcname, True, &ignore); + return check_path_syntax_internal(destname, srcname, False, &ignore); } /**************************************************************************** @@ -188,7 +191,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard) { - return check_path_syntax_internal(destname, srcname, True, p_contains_wcard); + return check_path_syntax_internal(destname, srcname, False, p_contains_wcard); } /**************************************************************************** @@ -197,10 +200,10 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * set (a safe assumption). ****************************************************************************/ -static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) +NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) { BOOL ignore; - return check_path_syntax_internal(destname, srcname, False, &ignore); + return check_path_syntax_internal(destname, srcname, True, &ignore); } /**************************************************************************** @@ -225,6 +228,16 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de *contains_wcard = False; + if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) { + /* + * For a DFS path the function parse_dfs_path() + * will do the path processing, just make a copy. + */ + pstrcpy(dest, tmppath); + *err = NT_STATUS_OK; + return ret; + } + if (lp_posix_pathnames()) { *err = check_path_syntax_posix(dest, tmppath); } else { @@ -252,6 +265,17 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } else { ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); } + + if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) { + /* + * For a DFS path the function parse_dfs_path() + * will do the path processing, just make a copy. + */ + pstrcpy(dest, tmppath); + *err = NT_STATUS_OK; + return ret; + } + if (lp_posix_pathnames()) { *err = check_path_syntax_posix(dest, tmppath); } else { @@ -632,9 +656,13 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { - END_PROFILE(SMBcheckpath); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + END_PROFILE(SMBcheckpath); + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + goto path_err; } DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); @@ -714,9 +742,13 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBgetatr); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } /* dos smetimes asks for a stat of "" - it returns a "hidden directory" @@ -796,9 +828,13 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsetatr); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); @@ -954,9 +990,13 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(nt_status); } - if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path)) { + nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard); + if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(nt_status); } p++; @@ -1210,9 +1250,13 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); @@ -1337,9 +1381,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); @@ -1518,9 +1566,13 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); @@ -1617,9 +1669,13 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(fname,"TMXXXXXX"); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); @@ -2022,10 +2078,14 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBunlink); return ERROR_NT(status); } - - if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { + + status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBunlink); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } DEBUG(3,("reply_unlink : %s\n",name)); @@ -3656,9 +3716,13 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, directory, False, NULL, &sbuf); @@ -3877,9 +3941,13 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, directory, False, NULL, &sbuf); @@ -4632,13 +4700,22 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { + status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } - if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { + + status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); @@ -4825,13 +4902,22 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRSRV,ERRinvdevice); } - if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) { + status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } - if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { + + status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1); @@ -5023,9 +5109,13 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir)) { + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(pathworks_setdir); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } if (strlen(newdir) != 0) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 58fa4eb31b..deb5db1baf 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1202,15 +1202,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, continue; } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { + pstring link_target; /* Needed to show the msdfs symlinks as * directories */ if(lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) { - - DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal)); + ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) { + DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s " + "as a directory\n", + pathreal)); sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; } else { @@ -1727,8 +1729,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard); + if (!NT_STATUS_IS_OK(ntstatus)) { + if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(ntstatus); } ntstatus = unix_convert(conn, directory, True, NULL, &sbuf); @@ -3248,8 +3254,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); @@ -4376,7 +4386,6 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, pstring rel_name; char *last_dirp = NULL; - unix_format(link_target); if (*link_target == '/') { /* No absolute paths allowed. */ return NT_STATUS_ACCESS_DENIED; @@ -4430,8 +4439,9 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, return status; } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname)) { - return NT_STATUS_PATH_NOT_COVERED; + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname); + if (!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", @@ -4478,8 +4488,9 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return status; } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) { - return NT_STATUS_PATH_NOT_COVERED; + status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* Check the new name has no '/' characters. */ @@ -5647,8 +5658,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(status); } - if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) { - ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + } + return ERROR_NT(status); } status = unix_convert(conn, fname, False, NULL, &sbuf); -- cgit From 81c820d77dd8e4de90150a230a3c894e58444f8f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 12 Mar 2007 18:19:48 +0000 Subject: r21801: Fix Coverity ID # 342 (This used to be commit 8700cd71bb3af3a55f025b34b61062aa5b66b6bc) --- source3/smbd/reply.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c0a2e23c3d..5be086f749 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2029,6 +2029,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + CloseDir(dir_hnd); return status; } -- cgit From a5dd4355cddbd49de1f2434c1a890799dd1a1dd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Mar 2007 20:10:12 +0000 Subject: r21803: Missed part of patch to make self-referrals work. Jeremy. (This used to be commit b1fa55e513f506bfb58687b692e1507732b00fbc) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index ae2009ad38..1641679a35 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -483,6 +483,7 @@ static NTSTATUS dfs_redirect( connection_struct *conn, } if (dp.reqpath[0] == '\0') { + pstrcpy(dfs_path, dp.reqpath); DEBUG(5,("dfs_redirect: self-referral.\n")); return NT_STATUS_OK; } -- cgit From edccfc91928c323f18febb7b90e41e0ddbfd8c7c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Mar 2007 19:18:18 +0000 Subject: r21845: Refactor the sessionsetupX code a little to allow us to return a NT_STATUS_TIME_DIFFERENCE_AT_DC error to a client when there's clock skew. Will help people debug this. Prepare us for being able to return the correct sessionsetupX "NT_STATUS_MORE_PROCESSING_REQUIRED" error with associated krb5 clock skew error to allow clients to re-sync time with us when we're eventually able to be a KDC. Jeremy. (This used to be commit c426340fc79a6b446033433b8de599130adffe28) --- source3/smbd/sesssetup.c | 235 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 193 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7a5f8be47f..e678d959d8 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -158,13 +158,75 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) #ifdef HAVE_KRB5 + +#if 0 +/* Experiment that failed. See "only happens with a KDC" comment below. */ +/**************************************************************************** + Cerate a clock skew error blob for a Windows client. +****************************************************************************/ + +static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out) +{ + krb5_context context = NULL; + krb5_error_code kerr = 0; + krb5_data reply; + krb5_principal host_princ = NULL; + char *host_princ_s = NULL; + BOOL ret = False; + + *pblob_out = data_blob(NULL,0); + + kerr = krb5_init_context(&context); + if (kerr) { + return False; + } + /* Create server principal. */ + asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm()); + if (!host_princ_s) { + goto out; + } + strlower_m(host_princ_s); + + kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ); + if (kerr) { + DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n", + host_princ_s, error_message(kerr) )); + goto out; + } + + kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply); + if (kerr) { + DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n", + error_message(kerr) )); + goto out; + } + + *pblob_out = data_blob(reply.data, reply.length); + kerberos_free_data_contents(context,&reply); + ret = True; + + out: + + if (host_princ_s) { + SAFE_FREE(host_princ_s); + } + if (host_princ) { + krb5_free_principal(context, host_princ); + } + krb5_free_context(context); + return ret; +} +#endif + /**************************************************************************** -reply to a session setup spnego negotiate packet for kerberos + Reply to a session setup spnego negotiate packet for kerberos. ****************************************************************************/ + static int reply_spnego_kerberos(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - DATA_BLOB *secblob) + DATA_BLOB *secblob, + BOOL *p_invalidate_vuid) { TALLOC_CTX *mem_ctx; DATA_BLOB ticket; @@ -191,9 +253,13 @@ static int reply_spnego_kerberos(connection_struct *conn, ZERO_STRUCT(ap_rep_wrapped); ZERO_STRUCT(response); + /* Normally we will always invalidate the intermediate vuid. */ + *p_invalidate_vuid = True; + mem_ctx = talloc_init("reply_spnego_kerberos"); - if (mem_ctx == NULL) + if (mem_ctx == NULL) { return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY)); + } if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { talloc_destroy(mem_ctx); @@ -205,9 +271,50 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ticket); if (!NT_STATUS_IS_OK(ret)) { - DEBUG(1,("Failed to verify incoming ticket!\n")); +#if 0 + /* Experiment that failed. See "only happens with a KDC" comment below. */ + + if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { + + /* + * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED + * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded + * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its + * clock and continues rather than giving an error. JRA. + * -- Looks like this only happens with a KDC. JRA. + */ + + BOOL ok = make_krb5_skew_error(&ap_rep); + if (!ok) { + talloc_destroy(mem_ctx); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + } + ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR); + response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); + reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED); + + /* + * In this one case we don't invalidate the intermediate vuid. + * as we're expecting the client to re-use it for the next + * sessionsetupX packet. JRA. + */ + + *p_invalidate_vuid = False; + + data_blob_free(&ap_rep); + data_blob_free(&ap_rep_wrapped); + data_blob_free(&response); + talloc_destroy(mem_ctx); + return -1; /* already replied */ + } +#else + if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { + ret = NT_STATUS_LOGON_FAILURE; + } +#endif + DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret))); talloc_destroy(mem_ctx); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + return ERROR_NT(nt_status_squash(ret)); } DEBUG(3,("Ticket name is [%s]\n", client)); @@ -523,32 +630,19 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out } /**************************************************************************** - Reply to a session setup spnego negotiate packet. + Is this a krb5 mechanism ? ****************************************************************************/ -static int reply_spnego_negotiate(connection_struct *conn, - char *inbuf, - char *outbuf, - uint16 vuid, - int length, int bufsize, - DATA_BLOB blob1, - AUTH_NTLMSSP_STATE **auth_ntlmssp_state) +static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5) { char *OIDs[ASN1_MAX_OIDS]; - DATA_BLOB secblob; int i; - DATA_BLOB chal; -#ifdef HAVE_KRB5 - BOOL got_kerberos_mechanism = False; -#endif - NTSTATUS nt_status; - /* parse out the OIDs and the first sec blob */ - if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { - /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + *p_is_krb5 = False; - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + /* parse out the OIDs and the first sec blob */ + if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) { + return NT_STATUS_LOGON_FAILURE; } /* only look at the first OID for determining the mechToken -- @@ -564,24 +658,53 @@ static int reply_spnego_negotiate(connection_struct *conn, #ifdef HAVE_KRB5 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { - got_kerberos_mechanism = True; + *p_is_krb5 = True; } #endif for (i=0;OIDs[i];i++) { - DEBUG(3,("Got OID %s\n", OIDs[i])); + DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i])); free(OIDs[i]); } - DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); + return NT_STATUS_OK; +} + +/**************************************************************************** + Reply to a session setup spnego negotiate packet. +****************************************************************************/ + +static int reply_spnego_negotiate(connection_struct *conn, + char *inbuf, + char *outbuf, + uint16 vuid, + int length, int bufsize, + DATA_BLOB blob1, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state) +{ + DATA_BLOB secblob; + DATA_BLOB chal; + BOOL got_kerberos_mechanism = False; + NTSTATUS status; + + status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism); + if (!NT_STATUS_IS_OK(status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ERROR_NT(nt_status_squash(status)); + } + + DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { + BOOL destroy_vuid = True; int ret = reply_spnego_kerberos(conn, inbuf, outbuf, - length, bufsize, &secblob); + length, bufsize, &secblob, &destroy_vuid); data_blob_free(&secblob); - /* Kill the intermediate vuid */ - invalidate_vuid(vuid); - + if (destroy_vuid) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + } return ret; } #endif @@ -590,28 +713,27 @@ static int reply_spnego_negotiate(connection_struct *conn, auth_ntlmssp_end(auth_ntlmssp_state); } - nt_status = auth_ntlmssp_start(auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(nt_status)) { + status = auth_ntlmssp_start(auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); - - return ERROR_NT(nt_status_squash(nt_status)); + return ERROR_NT(nt_status_squash(status)); } - nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, + status = auth_ntlmssp_update(*auth_ntlmssp_state, secblob, &chal); data_blob_free(&secblob); reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, - &chal, nt_status, True); + &chal, status, True); data_blob_free(&chal); /* already replied */ return -1; } - + /**************************************************************************** Reply to a session setup spnego auth packet. ****************************************************************************/ @@ -622,8 +744,10 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DATA_BLOB blob1, AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { - DATA_BLOB auth, auth_reply; - NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; + DATA_BLOB auth = data_blob(NULL,0); + DATA_BLOB auth_reply = data_blob(NULL,0); + DATA_BLOB secblob = data_blob(NULL,0); + NTSTATUS status = NT_STATUS_INVALID_PARAMETER; if (!spnego_parse_auth(blob1, &auth)) { #if 0 @@ -634,6 +758,33 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } + + if (auth.data[0] == ASN1_APPLICATION(0)) { + /* Might be a second negTokenTarg packet */ + + BOOL got_krb5_mechanism = False; + status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism); + if (NT_STATUS_IS_OK(status)) { + DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length)); +#ifdef HAVE_KRB5 + if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { + BOOL destroy_vuid = True; + int ret = reply_spnego_kerberos(conn, inbuf, outbuf, + length, bufsize, &secblob, &destroy_vuid); + data_blob_free(&secblob); + data_blob_free(&auth); + if (destroy_vuid) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + } + return ret; + } +#endif + } + } + + /* If we get here it wasn't a negTokenTarg auth packet. */ + data_blob_free(&secblob); if (!*auth_ntlmssp_state) { /* Kill the intermediate vuid */ @@ -643,14 +794,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } - nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, + status = auth_ntlmssp_update(*auth_ntlmssp_state, auth, &auth_reply); data_blob_free(&auth); reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, - &auth_reply, nt_status, True); + &auth_reply, status, True); data_blob_free(&auth_reply); -- cgit From 7d77dd9db600a4b2ee11913bf8169224c2d9424a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Mar 2007 21:53:53 +0000 Subject: r21847: Fix memory leaks in error paths (and in main code path in one case...) in sasl bind. Wonder why coverity didn't find these ? Jeremy. (This used to be commit 89bdd30e4b2bb9dbc2ab57c54be8c6d01cae5a26) --- source3/smbd/sesssetup.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e678d959d8..ff1b2821cc 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -176,6 +176,7 @@ static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out) *pblob_out = data_blob(NULL,0); + initialize_krb5_error_table(); kerr = krb5_init_context(&context); if (kerr) { return False; -- cgit From 8d5f85e0046c8fd2c0f8832788719e319751d358 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 16 Mar 2007 16:20:47 +0000 Subject: r21857: Stop pretending to be Vista in the %a macro towards Samba clients. Guenther (This used to be commit f55e1a312e75dc72ea040a35a9c20ccf539c4ae4) --- source3/smbd/negprot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index fb5610b20b..04b06a9bce 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -259,7 +259,9 @@ static int reply_nt1(char *inbuf, char *outbuf) if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) && ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) ) { - set_remote_arch( RA_VISTA ); + if (get_remote_arch() != RA_SAMBA) {; + set_remote_arch( RA_VISTA ); + } } /* do spnego in user level security if the client -- cgit From ab9a46a35c05869f1aa4bb3c57a987def459791e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 16 Mar 2007 16:21:38 +0000 Subject: r21858: Fix typo. Guenther (This used to be commit 663514e511982437c09d45334b8d435448347ed6) --- source3/smbd/negprot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 04b06a9bce..bc7c75aab4 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -259,7 +259,7 @@ static int reply_nt1(char *inbuf, char *outbuf) if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) && ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) ) { - if (get_remote_arch() != RA_SAMBA) {; + if (get_remote_arch() != RA_SAMBA) { set_remote_arch( RA_VISTA ); } } -- cgit From 2864d86b37fe29ba2e985b61e646061feb0b841f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Mar 2007 10:09:16 +0000 Subject: r21867: Simplify calling convention of timeout_processing. lp_deadtime is only referenced in conn_idle_all(). (This used to be commit c0aaee6d36cf1fb873cfb9ab6ee52ff097a202a0) --- source3/smbd/conn.c | 6 +++++- source3/smbd/process.c | 21 +++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 6c8267ceed..2d4020af39 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -187,12 +187,16 @@ void conn_close_all(void) Idle inactive connections. ****************************************************************************/ -BOOL conn_idle_all(time_t t, int deadtime) +BOOL conn_idle_all(time_t t) { + int deadtime = lp_deadtime()*60; pipes_struct *plist = NULL; BOOL allidle = True; connection_struct *conn, *next; + if (deadtime <= 0) + deadtime = DEFAULT_SMBD_TIMEOUT; + for (conn=Connections;conn;conn=next) { next=conn->next; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 11ef33679f..846f338ccf 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1317,7 +1317,8 @@ void check_reload(time_t t) Process any timeout housekeeping. Return False if the caller should exit. ****************************************************************************/ -static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time) +static BOOL timeout_processing(int *select_timeout, + time_t *last_timeout_processing_time) { static time_t last_keepalive_sent_time = 0; static time_t last_idle_closed_check = 0; @@ -1382,7 +1383,7 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t } /* check for connection timeouts */ - allidle = conn_idle_all(t, deadtime); + allidle = conn_idle_all(t); if (allidle && conn_num_open()>0) { DEBUG(2,("Closing idle connection 2.\n")); @@ -1541,13 +1542,9 @@ void smbd_process(void) max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); while (True) { - int deadtime = lp_deadtime()*60; int select_timeout = setup_select_timeout(); int num_echos; - if (deadtime <= 0) - deadtime = DEFAULT_SMBD_TIMEOUT; - errno = 0; /* free up temporary memory */ @@ -1556,7 +1553,8 @@ void smbd_process(void) /* Did someone ask for immediate checks on things like blocking locks ? */ if (select_timeout == 0) { - if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + if(!timeout_processing(&select_timeout, + &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ } @@ -1568,7 +1566,8 @@ void smbd_process(void) #endif while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { - if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + if(!timeout_processing(&select_timeout, + &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ } @@ -1589,7 +1588,7 @@ void smbd_process(void) process_smb(InBuffer, OutBuffer); if (smb_echo_count != num_echos) { - if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + if(!timeout_processing( &select_timeout, &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ } @@ -1606,7 +1605,9 @@ void smbd_process(void) if ((num_smbs % 200) == 0) { time_t new_check_time = time(NULL); if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) { - if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) + if(!timeout_processing( + &select_timeout, + &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ last_timeout_processing_time = new_check_time; /* Reset time. */ -- cgit From 8d0cfddb26a354606844a10254055fb8cd54e792 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Mar 2007 10:13:35 +0000 Subject: r21868: Remove check_log_size from the central smbd processing loop. This can be done with a become_root/unbecome_root in debug.c. (This used to be commit 4632a0caaf251d9cc7b9d84cbd20362d37f0e4e0) --- source3/smbd/process.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 846f338ccf..83072817a3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1448,13 +1448,6 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); update_monitored_printq_cache(); - /* - * Now we are root, check if the log files need pruning. - * Force a log file check. - */ - force_check_log_size(); - check_log_size(); - /* Send any queued printer notify message to interested smbd's. */ print_notify_send_messages(0); -- cgit From 7c2bc9c07083e7035028cf22e97e0c31b3e9d6a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Mar 2007 10:57:46 +0000 Subject: r21869: Move sending keepalives out of the main processing loop into idle event. On the way, make lp_keepalive() a proper parameter. Volker (This used to be commit 9499fd9c803d030ce9827f8379c2e56d91bb786e) --- source3/smbd/process.c | 27 +++++++++++++++------------ source3/smbd/server.c | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 83072817a3..5edb2c1009 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -22,7 +22,6 @@ #include "includes.h" uint16 global_smbpid; -extern int keepalive; extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; @@ -221,6 +220,7 @@ BOOL push_deferred_smb_message(uint16 mid, struct idle_event { struct timed_event *te; struct timeval interval; + char *name; BOOL (*handler)(const struct timeval *now, void *private_data); void *private_data; }; @@ -241,17 +241,19 @@ static void idle_event_handler(struct event_context *ctx, return; } - event->te = event_add_timed(smbd_event_context(), event, + event->te = event_add_timed(ctx, event, timeval_sum(now, &event->interval), - "idle_event_handler", + event->name, idle_event_handler, event); /* We can't do much but fail here. */ SMB_ASSERT(event->te != NULL); } -struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, +struct idle_event *event_add_idle(struct event_context *event_ctx, + TALLOC_CTX *mem_ctx, struct timeval interval, + const char *name, BOOL (*handler)(const struct timeval *now, void *private_data), void *private_data) @@ -269,9 +271,15 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, result->handler = handler; result->private_data = private_data; - result->te = event_add_timed(smbd_event_context(), result, + if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(result); + return NULL; + } + + result->te = event_add_timed(event_ctx, result, timeval_sum(&now, &interval), - "idle_event_handler", + result->name, idle_event_handler, result); if (result->te == NULL) { DEBUG(0, ("event_add_timed failed\n")); @@ -1363,12 +1371,7 @@ static BOOL timeout_processing(int *select_timeout, last_idle_closed_check = t; } - if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - if (!send_keepalive(smbd_server_fd())) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return False; - } - + if (lp_keepalive() && (t - last_keepalive_sent_time)> lp_keepalive()) { /* send a keepalive for a password server or the like. This is attached to the auth_info created in the negprot */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0ae2f3e836..0d4953e5b8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -814,6 +814,18 @@ static BOOL init_structs(void ) return True; } +/* + * Send keepalive packets to our client + */ +static BOOL keepalive_fn(const struct timeval *now, void *private_data) +{ + if (!send_keepalive(smbd_server_fd())) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + return True; +} + /**************************************************************************** main program. ****************************************************************************/ @@ -1107,6 +1119,20 @@ extern void build_options(BOOL screen); /* register our message handlers */ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis, NULL); + if (lp_keepalive() != 0) { + struct timeval interval; + + interval.tv_sec = lp_keepalive(); + interval.tv_usec = 0; + + if (!(event_add_idle(smbd_event_context(), NULL, + interval, "keepalive", keepalive_fn, + NULL))) { + DEBUG(0, ("Could not add keepalive event\n")); + exit(1); + } + } + smbd_process(); namecache_shutdown(); -- cgit From c0e37a74963ae942ed48431bd2ea353ebad256ff Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Mar 2007 11:24:10 +0000 Subject: r21870: Move sending auth_server keepalives out of the main loop into an idle event. Volker (This used to be commit 6226b30f38cd82531422815ba66a687aab50028d) --- source3/smbd/process.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5edb2c1009..76af8f2054 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1328,7 +1328,6 @@ void check_reload(time_t t) static BOOL timeout_processing(int *select_timeout, time_t *last_timeout_processing_time) { - static time_t last_keepalive_sent_time = 0; static time_t last_idle_closed_check = 0; time_t t; BOOL allidle = True; @@ -1351,9 +1350,6 @@ static BOOL timeout_processing(int *select_timeout, *last_timeout_processing_time = t = time(NULL); - if(last_keepalive_sent_time == 0) - last_keepalive_sent_time = t; - if(last_idle_closed_check == 0) last_idle_closed_check = t; @@ -1371,20 +1367,6 @@ static BOOL timeout_processing(int *select_timeout, last_idle_closed_check = t; } - if (lp_keepalive() && (t - last_keepalive_sent_time)> lp_keepalive()) { - /* send a keepalive for a password server or the like. - This is attached to the auth_info created in the - negprot */ - if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method - && negprot_global_auth_context->challenge_set_method->send_keepalive) { - - negprot_global_auth_context->challenge_set_method->send_keepalive - (&negprot_global_auth_context->challenge_set_method->private_data); - } - - last_keepalive_sent_time = t; - } - /* check for connection timeouts */ allidle = conn_idle_all(t); -- cgit From fe0b56ead166377d415b0eaf04ee1af3bdb435de Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Mar 2007 13:19:40 +0000 Subject: r21871: Move deadtime processing into an idle event. While there, simplify conn_idle_all() a bit. Volker (This used to be commit 3fc00977a99932b226bdcbc43bbc0ede1bcec26f) --- source3/smbd/conn.c | 27 ++++++++++++++++----------- source3/smbd/process.c | 21 --------------------- source3/smbd/server.c | 40 +++++++++++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 2d4020af39..388cd004f9 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -191,14 +191,14 @@ BOOL conn_idle_all(time_t t) { int deadtime = lp_deadtime()*60; pipes_struct *plist = NULL; - BOOL allidle = True; - connection_struct *conn, *next; + connection_struct *conn; if (deadtime <= 0) deadtime = DEFAULT_SMBD_TIMEOUT; - for (conn=Connections;conn;conn=next) { - next=conn->next; + for (conn=Connections;conn;conn=conn->next) { + + time_t age = t - conn->lastused; /* Update if connection wasn't idle. */ if (conn->lastused != conn->lastused_count) { @@ -207,12 +207,12 @@ BOOL conn_idle_all(time_t t) } /* close dirptrs on connections that are idle */ - if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) { + if (age > DPTR_IDLE_TIMEOUT) { dptr_idlecnum(conn); } - if (conn->num_files_open > 0 || (t-conn->lastused)num_files_open > 0 || age < deadtime) { + return False; } } @@ -221,11 +221,14 @@ BOOL conn_idle_all(time_t t) * idle with a handle open. */ - for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) - if (plist->pipe_handles && plist->pipe_handles->count) - allidle = False; + for (plist = get_first_internal_pipe(); plist; + plist = get_next_internal_pipe(plist)) { + if (plist->pipe_handles && plist->pipe_handles->count) { + return False; + } + } - return allidle; + return True; } /**************************************************************************** @@ -303,6 +306,8 @@ void conn_free(connection_struct *conn) DLIST_REMOVE(Connections, conn); bitmap_clear(bmap, conn->cnum); + + SMB_ASSERT(num_open > 0); num_open--; conn_free_internal(conn); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 76af8f2054..6497dfa97b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1328,9 +1328,7 @@ void check_reload(time_t t) static BOOL timeout_processing(int *select_timeout, time_t *last_timeout_processing_time) { - static time_t last_idle_closed_check = 0; time_t t; - BOOL allidle = True; if (smb_read_error == READ_EOF) { DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); @@ -1350,31 +1348,12 @@ static BOOL timeout_processing(int *select_timeout, *last_timeout_processing_time = t = time(NULL); - if(last_idle_closed_check == 0) - last_idle_closed_check = t; - /* become root again if waiting */ change_to_root_user(); /* check if we need to reload services */ check_reload(t); - /* automatic timeout if all connections are closed */ - if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) { - DEBUG( 2, ( "Closing idle connection\n" ) ); - return False; - } else { - last_idle_closed_check = t; - } - - /* check for connection timeouts */ - allidle = conn_idle_all(t); - - if (allidle && conn_num_open()>0) { - DEBUG(2,("Closing idle connection 2.\n")); - return False; - } - if(global_machine_password_needs_changing && /* for ADS we need to do a regular ADS password change, not a domain password change */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0d4953e5b8..3f4313ce7f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -826,6 +826,22 @@ static BOOL keepalive_fn(const struct timeval *now, void *private_data) return True; } +/* + * Do the recurring check if we're idle + */ +static BOOL deadtime_fn(const struct timeval *now, void *private_data) +{ + if ((conn_num_open() == 0) + || (conn_idle_all(now->tv_sec))) { + DEBUG( 2, ( "Closing idle connection\n" ) ); + message_send_pid(procid_self(), MSG_SHUTDOWN, NULL, 0, False); + return False; + } + + return True; +} + + /**************************************************************************** main program. ****************************************************************************/ @@ -1119,18 +1135,20 @@ extern void build_options(BOOL screen); /* register our message handlers */ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis, NULL); - if (lp_keepalive() != 0) { - struct timeval interval; - - interval.tv_sec = lp_keepalive(); - interval.tv_usec = 0; + if ((lp_keepalive() != 0) + && !(event_add_idle(smbd_event_context(), NULL, + timeval_set(lp_keepalive(), 0), + "keepalive", keepalive_fn, + NULL))) { + DEBUG(0, ("Could not add keepalive event\n")); + exit(1); + } - if (!(event_add_idle(smbd_event_context(), NULL, - interval, "keepalive", keepalive_fn, - NULL))) { - DEBUG(0, ("Could not add keepalive event\n")); - exit(1); - } + if (!(event_add_idle(smbd_event_context(), NULL, + timeval_set(IDLE_CLOSED_TIMEOUT, 0), + "deadtime", deadtime_fn, NULL))) { + DEBUG(0, ("Could not add deadtime event\n")); + exit(1); } smbd_process(); -- cgit From 496dbdf4350ffc5f53c9f8f734d2c29b312ff11b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 19 Mar 2007 21:52:27 +0000 Subject: r21879: Move process_blocking_lock_queue to a timed event. The idea is that we have blocking.c:brl_timeout as a timed event that is present whenever we do have a blocking lock pending. It fires brl_timeout_fn() which calls process_blocking_lock_queue(). Whenever we make changes to blocking_lock_queue, we trigger a recalc_brl_timeout() which sets a new brl_timout event if necessary. This makes the call to blocking_locks_timeout_ms() in setup_select_timeout() unnecessary, this is implicitly done in event_add_to_select_args() from the timed events. Volker (This used to be commit 7e31b8ce21de803ac1f8967967393341a3f44ac3) --- source3/smbd/blocking.c | 116 +++++++++++++++++++++++++++++------------------- source3/smbd/process.c | 8 +--- 2 files changed, 72 insertions(+), 52 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 70b2d30aab..101f16bb9d 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -51,6 +51,9 @@ static blocking_lock_record *blocking_lock_queue; /* dlink list we move cancelled lock records onto. */ static blocking_lock_record *blocking_lock_cancelled_queue; +/* The event that makes us process our blocking lock queue */ +static struct timed_event *brl_timeout; + /**************************************************************************** Destructor for the above structure. ****************************************************************************/ @@ -73,6 +76,63 @@ static BOOL in_chained_smb(void) static void received_unlock_msg(int msg_type, struct process_id src, void *buf, size_t len, void *private_data); +static void process_blocking_lock_queue(void); + +static void brl_timeout_fn(struct event_context *event_ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + SMB_ASSERT(brl_timeout == te); + TALLOC_FREE(brl_timeout); + + change_to_root_user(); /* TODO: Possibly run all timed events as + * root */ + + process_blocking_lock_queue(); +} + +/**************************************************************************** + After a change to blocking_lock_queue, recalculate the timed_event for the + next processing. +****************************************************************************/ + +static BOOL recalc_brl_timeout(void) +{ + blocking_lock_record *brl; + struct timeval next_timeout; + + TALLOC_FREE(brl_timeout); + + next_timeout = timeval_zero(); + + for (brl = blocking_lock_queue; brl; brl = brl->next) { + if (timeval_is_zero(&brl->expire_time)) { + continue; + } + + if (timeval_is_zero(&next_timeout)) { + next_timeout = brl->expire_time; + } + else { + next_timeout = timeval_min(&next_timeout, + &brl->expire_time); + } + } + + if (timeval_is_zero(&next_timeout)) { + return True; + } + + if (!(brl_timeout = event_add_timed(smbd_event_context(), NULL, + next_timeout, "brl_timeout", + brl_timeout_fn, NULL))) { + return False; + } + + return True; +} + /**************************************************************************** Function to push a blocking lock request onto the lock queue. @@ -152,6 +212,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, } DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *); + recalc_brl_timeout(); /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { @@ -590,58 +651,15 @@ static void received_unlock_msg(int msg_type, struct process_id src, process_blocking_lock_queue(); } -/**************************************************************************** - Return the number of milliseconds to the next blocking locks timeout, or default_timeout -*****************************************************************************/ - -unsigned int blocking_locks_timeout_ms(unsigned int default_timeout_ms) -{ - unsigned int timeout_ms = default_timeout_ms; - struct timeval tv_curr; - SMB_BIG_INT min_tv_dif_us = 0x7FFFFFFF; /* A large +ve number. */ - blocking_lock_record *blr = blocking_lock_queue; - - /* note that we avoid the GetTimeOfDay() syscall if there are no blocking locks */ - if (!blr) { - return timeout_ms; - } - - tv_curr = timeval_current(); - - for (; blr; blr = blr->next) { - SMB_BIG_INT tv_dif_us; - - if (timeval_is_zero(&blr->expire_time)) { - continue; /* Never timeout. */ - } - - tv_dif_us = usec_time_diff(&blr->expire_time, &tv_curr); - min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us); - } - - if (min_tv_dif_us < 0) { - min_tv_dif_us = 0; - } - - timeout_ms = (unsigned int)(min_tv_dif_us / (SMB_BIG_INT)1000); - - if (timeout_ms < 1) { - timeout_ms = 1; - } - - DEBUG(10,("blocking_locks_timeout_ms: returning %u\n", timeout_ms)); - - return timeout_ms; -} - /**************************************************************************** Process the blocking lock queue. Note that this is only called as root. *****************************************************************************/ -void process_blocking_lock_queue(void) +static void process_blocking_lock_queue(void) { struct timeval tv_curr = timeval_current(); blocking_lock_record *blr, *next = NULL; + BOOL recalc_timeout = False; /* * Go through the queue and see if we can get any of the locks. @@ -693,6 +711,7 @@ void process_blocking_lock_queue(void) blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); + recalc_timeout = True; continue; } @@ -718,6 +737,7 @@ void process_blocking_lock_queue(void) blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); + recalc_timeout = True; continue; } @@ -742,6 +762,7 @@ void process_blocking_lock_queue(void) blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); + recalc_timeout = True; change_to_root_user(); continue; } @@ -767,9 +788,14 @@ void process_blocking_lock_queue(void) DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); + recalc_timeout = True; } change_to_root_user(); } + + if (recalc_timeout) { + recalc_brl_timeout(); + } } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6497dfa97b..59ad96d880 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1259,7 +1259,7 @@ static int setup_select_timeout(void) { int select_timeout; - select_timeout = blocking_locks_timeout_ms(SMBD_SELECT_TIMEOUT*1000); + select_timeout = SMBD_SELECT_TIMEOUT*1000; if (print_notify_messages_pending()) { select_timeout = MIN(select_timeout, 1000); @@ -1402,12 +1402,6 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); secrets_lock_trust_account_password(lp_workgroup(), False); } - /* - * Check to see if we have any blocking locks - * outstanding on the queue. - */ - process_blocking_lock_queue(); - /* update printer queue caches if necessary */ update_monitored_printq_cache(); -- cgit From 296dcbac5897ad208c890720d3356a3ddc5f7794 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Mar 2007 01:17:47 +0000 Subject: r21882: The server part of the code has to use an AUTH_NTLMSSP struct, not just an NTLMSSP - grr. This complicates the re-use of common client and server code but I think I've got it right. Not turned on of valgrinded yet, but you can see it start to take shape ! Jeremy. (This used to be commit 60fc9c0aedf42dcd9df2ef9f1df07eaf3bca9bce) --- source3/smbd/seal.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 2 + source3/smbd/sesssetup.c | 2 +- source3/smbd/trans2.c | 27 +++++ 4 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 source3/smbd/seal.c (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c new file mode 100644 index 0000000000..2dd4fc8b62 --- /dev/null +++ b/source3/smbd/seal.c @@ -0,0 +1,257 @@ +/* + Unix SMB/CIFS implementation. + SMB Transport encryption (sealing) code - server code. + Copyright (C) Jeremy Allison 2007. + + 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" + +/****************************************************************************** + Server side encryption. +******************************************************************************/ + +/****************************************************************************** + Global server state. +******************************************************************************/ + +struct smb_srv_trans_enc_ctx { + struct smb_trans_enc_state *es; + AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ +}; + +static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; +static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; + +/****************************************************************************** + Is server encryption on ? +******************************************************************************/ + +BOOL srv_encryption_on(void) +{ + if (srv_trans_enc_ctx) { + return common_encryption_on(srv_trans_enc_ctx->es); + } + return False; +} + +/****************************************************************************** + Shutdown a server encryption state. +******************************************************************************/ + +static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) +{ + struct smb_srv_trans_enc_ctx *ec = *pp_ec; + + if (!ec) { + return; + } + + if (ec->es) { + struct smb_trans_enc_state *es = ec->es; + if (es->smb_enc_type == SMB_TRANS_ENC_NTLM && + ec->auth_ntlmssp_state) { + auth_ntlmssp_end(&ec->auth_ntlmssp_state); + /* The auth_ntlmssp_end killed this already. */ + es->ntlmssp_state = NULL; + } + common_free_encryption_state(&ec->es); + } + + SAFE_FREE(ec); + *pp_ec = NULL; +} + +/****************************************************************************** + Free an encryption-allocated buffer. +******************************************************************************/ + +void srv_free_enc_buffer(char *buf) +{ + if (srv_trans_enc_ctx) { + return common_free_enc_buffer(srv_trans_enc_ctx->es, buf); + } +} + +/****************************************************************************** + Decrypt an incoming buffer. +******************************************************************************/ + +NTSTATUS srv_decrypt_buffer(char *buf) +{ + if (srv_trans_enc_ctx) { + return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); + } + return NT_STATUS_OK; +} + +/****************************************************************************** + Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. +******************************************************************************/ + +NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) +{ + if (srv_trans_enc_ctx) { + return common_encrypt_buffer(srv_trans_enc_ctx->es, buffer, buf_out); + } + /* Not encrypting. */ + *buf_out = buffer; + return NT_STATUS_OK; +} + +/****************************************************************************** + Do the gss encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB *psecblob) +{ + return NT_STATUS_NOT_SUPPORTED; +} +#endif + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. + Covers the NTLM case. Based off code in smbd/sesssionsetup.c + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob(NULL,0); + DATA_BLOB secblob = data_blob(NULL, 0); + DATA_BLOB chal = data_blob(NULL, 0); + DATA_BLOB response = data_blob(NULL, 0); + BOOL got_kerberos_mechanism = False; + struct smb_srv_trans_enc_ctx *ec = NULL; + + blob = data_blob_const(*ppdata, *p_data_size); + + status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* We should have no partial context at this point. */ + + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + + partial_srv_trans_enc_ctx = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); + if (!partial_srv_trans_enc_ctx) { + data_blob_free(&secblob); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(partial_srv_trans_enc_ctx); + +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) + if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { + status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, &secblob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&secblob); + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + } + return status; + } +#endif + + /* Deal with an NTLM enc. setup. */ + ec = partial_srv_trans_enc_ctx; + + status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); + data_blob_free(&secblob); + + /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED + * for success ... */ + + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + + return status; +} + +/****************************************************************************** + Complete a SPNEGO encryption negotiation. Parameters are in/out. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_auth(unsigned char **ppdata, size_t *p_data_size) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. +******************************************************************************/ + +NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_size) +{ + unsigned char *pdata = *ppdata; + + if (*p_data_size < 1) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (pdata[0] == ASN1_APPLICATION(0)) { + /* + * Until success we do everything on the partial + * enc state. + */ + /* its a negTokenTarg packet */ + return srv_enc_spnego_negotiate(ppdata, p_data_size); + } + + if (pdata[0] == ASN1_CONTEXT(1)) { + /* Its a auth packet */ + return srv_enc_spnego_auth(ppdata, p_data_size); + } + + return NT_STATUS_INVALID_PARAMETER; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +void srv_encryption_start(void) +{ + srv_free_encryption_context(&srv_trans_enc_ctx); + /* Steal the partial pointer. Deliberate shallow copy. */ + srv_trans_enc_ctx = partial_srv_trans_enc_ctx; + srv_trans_enc_ctx->es->enc_on = True; + + partial_srv_trans_enc_ctx = NULL; +} + +/****************************************************************************** + Shutdown all server contexts. +******************************************************************************/ + +void server_encryption_shutdown(void) +{ + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + srv_free_encryption_context(&srv_trans_enc_ctx); +} diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3f4313ce7f..348d3354d7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -743,6 +743,8 @@ static void exit_server_common(enum server_exit_reason how, locking_end(); printing_end(); + server_encryption_shutdown(); + if (how != SERVER_EXIT_NORMAL) { int oldlevel = DEBUGLEVEL; char *last_inbuf = get_InBuffer(); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index ff1b2821cc..91f4a9e12f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -634,7 +634,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out Is this a krb5 mechanism ? ****************************************************************************/ -static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5) +NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5) { char *OIDs[ASN1_MAX_OIDS]; int i; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index deb5db1baf..25fd6621e9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2758,6 +2758,33 @@ cap_low = 0x%x, cap_high = 0x%x\n", } break; } + case SMB_REQUEST_TRANSPORT_ENCRYPTION: + { + NTSTATUS status; + size_t data_len = total_data; + + if (!lp_unix_extensions()) { + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + + DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n")); + + status = srv_request_encryption_setup((unsigned char **)&pdata, &data_len); + + if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__); + } else if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + + send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes); + + if (NT_STATUS_IS_OK(status)) { + /* Server-side transport encryption is now *on*. */ + srv_encryption_start(); + } + return -1; + } case SMB_FS_QUOTA_INFORMATION: { files_struct *fsp = NULL; -- cgit From 492ad718552b77d6de7233b126e834cf11f9316c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Mar 2007 18:11:48 +0000 Subject: r21891: Finish server-side NTLM-SPNEGO negotiation support. Now for the client part, and testing. Jeremy. (This used to be commit 487706701f5f4a92c8fd1da1f29fb44491bac064) --- source3/smbd/seal.c | 108 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 2dd4fc8b62..0a530526a2 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -118,15 +118,46 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) ******************************************************************************/ #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB *psecblob) +static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { return NT_STATUS_NOT_SUPPORTED; } #endif +/****************************************************************************** + Do the NTLM SPNEGO encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +{ + NTSTATUS status; + DATA_BLOB chal = data_blob(NULL, 0); + DATA_BLOB response = data_blob(NULL, 0); + struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; + + status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); + + /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED + * for success ... */ + + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + /****************************************************************************** Do the SPNEGO encryption negotiation. Parameters are in/out. - Covers the NTLM case. Based off code in smbd/sesssionsetup.c + Based off code in smbd/sesssionsetup.c Until success we do everything on the partial enc ctx. ******************************************************************************/ @@ -135,10 +166,7 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ NTSTATUS status; DATA_BLOB blob = data_blob(NULL,0); DATA_BLOB secblob = data_blob(NULL, 0); - DATA_BLOB chal = data_blob(NULL, 0); - DATA_BLOB response = data_blob(NULL, 0); BOOL got_kerberos_mechanism = False; - struct smb_srv_trans_enc_ctx *ec = NULL; blob = data_blob_const(*ppdata, *p_data_size); @@ -160,47 +188,59 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { - status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, &secblob); - if (!NT_STATUS_IS_OK(status)) { - data_blob_free(&secblob); - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - } - return status; - } + status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); + } else #endif - - /* Deal with an NTLM enc. setup. */ - ec = partial_srv_trans_enc_ctx; - - status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); + { + status = srv_enc_spnego_ntlm_negotiate(ppdata, p_data_size, secblob); } - status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); data_blob_free(&secblob); - /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED - * for success ... */ - - response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); - data_blob_free(&chal); - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + } return status; } /****************************************************************************** Complete a SPNEGO encryption negotiation. Parameters are in/out. + We only get this for a NTLM auth second stage. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_auth(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) { - return NT_STATUS_NOT_SUPPORTED; + NTSTATUS status; + DATA_BLOB blob = data_blob(NULL,0); + DATA_BLOB auth = data_blob(NULL,0); + DATA_BLOB auth_reply = data_blob(NULL,0); + DATA_BLOB response = data_blob(NULL,0); + struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; + + /* We must have a partial context here. */ + + if (!ec || ec->auth_ntlmssp_state == NULL) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + blob = data_blob_const(*ppdata, *p_data_size); + if (!spnego_parse_auth(blob, &auth)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); + data_blob_free(&auth); + + response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); + data_blob_free(&auth_reply); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; } /****************************************************************************** @@ -226,7 +266,7 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz if (pdata[0] == ASN1_CONTEXT(1)) { /* Its a auth packet */ - return srv_enc_spnego_auth(ppdata, p_data_size); + return srv_enc_spnego_ntlm_auth(ppdata, p_data_size); } return NT_STATUS_INVALID_PARAMETER; @@ -238,7 +278,9 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz void srv_encryption_start(void) { + /* Throw away the context we're using currently (if any). */ srv_free_encryption_context(&srv_trans_enc_ctx); + /* Steal the partial pointer. Deliberate shallow copy. */ srv_trans_enc_ctx = partial_srv_trans_enc_ctx; srv_trans_enc_ctx->es->enc_on = True; -- cgit From 6b0dcfa62d23980351e852eec05123c0a9823f1d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Mar 2007 22:01:02 +0000 Subject: r21894: Some refactoring of server side encryption context. Support "raw" NTLM auth (no spnego). Jeremy. (This used to be commit 6b5ff7bd591b4f65e2eb767928db50ddf445f09a) --- source3/smbd/seal.c | 163 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 0a530526a2..9910a84f4c 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -49,7 +49,44 @@ BOOL srv_encryption_on(void) } /****************************************************************************** - Shutdown a server encryption state. + Create an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + ec->es->ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; + return status; +} + +/****************************************************************************** + Destroy an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + + if (ec->auth_ntlmssp_state) { + auth_ntlmssp_end(&ec->auth_ntlmssp_state); + /* The auth_ntlmssp_end killed this already. */ + ec->es->ntlmssp_state = NULL; + } +} + +/****************************************************************************** + Shutdown a server encryption context. ******************************************************************************/ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) @@ -61,12 +98,8 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) } if (ec->es) { - struct smb_trans_enc_state *es = ec->es; - if (es->smb_enc_type == SMB_TRANS_ENC_NTLM && - ec->auth_ntlmssp_state) { - auth_ntlmssp_end(&ec->auth_ntlmssp_state); - /* The auth_ntlmssp_end killed this already. */ - es->ntlmssp_state = NULL; + if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { + destroy_auth_ntlmssp(ec); } common_free_encryption_state(&ec->es); } @@ -75,6 +108,36 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) *pp_ec = NULL; } +/****************************************************************************** + Create a server encryption context. +******************************************************************************/ + +static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type) +{ + struct smb_srv_trans_enc_ctx *ec; + + ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); + if (!ec) { + return NULL; + } + ZERO_STRUCTP(partial_srv_trans_enc_ctx); + ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); + if (!ec->es) { + SAFE_FREE(ec); + return NULL; + } + ZERO_STRUCTP(ec->es); + ec->es->smb_enc_type = smb_enc_type; + if (smb_enc_type == SMB_TRANS_ENC_NTLM) { + NTSTATUS status = make_auth_ntlmssp(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return NULL; + } + } + return ec; +} + /****************************************************************************** Free an encryption-allocated buffer. ******************************************************************************/ @@ -125,29 +188,33 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, #endif /****************************************************************************** - Do the NTLM SPNEGO encryption negotiation. Parameters are in/out. + Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. Until success we do everything on the partial enc ctx. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap) { NTSTATUS status; DATA_BLOB chal = data_blob(NULL, 0); DATA_BLOB response = data_blob(NULL, 0); - struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; - status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); + partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_NTLM); + if (!partial_srv_trans_enc_ctx) { + return NT_STATUS_NO_MEMORY; } - status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED * for success ... */ - response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); - data_blob_free(&chal); + if (spnego_wrap) { + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + } else { + /* Return the raw blob. */ + response = chal; + } SAFE_FREE(*ppdata); *ppdata = response.data; @@ -179,20 +246,13 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ srv_free_encryption_context(&partial_srv_trans_enc_ctx); - partial_srv_trans_enc_ctx = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); - if (!partial_srv_trans_enc_ctx) { - data_blob_free(&secblob); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(partial_srv_trans_enc_ctx); - #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); } else #endif { - status = srv_enc_spnego_ntlm_negotiate(ppdata, p_data_size, secblob); + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, True); } data_blob_free(&secblob); @@ -220,7 +280,7 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ /* We must have a partial context here. */ - if (!ec || ec->auth_ntlmssp_state == NULL) { + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { srv_free_encryption_context(&partial_srv_trans_enc_ctx); return NT_STATUS_INVALID_PARAMETER; } @@ -243,6 +303,44 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ return status; } +/****************************************************************************** + Raw NTLM encryption negotiation. Parameters are in/out. + This function does both steps. +******************************************************************************/ + +static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); + DATA_BLOB response = data_blob(NULL,0); + struct smb_srv_trans_enc_ctx *ec; + + if (!partial_srv_trans_enc_ctx) { + /* This is the initial step. */ + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + return status; + } + + ec = partial_srv_trans_enc_ctx; + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + /* Second step. */ + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); + + /* Return the raw blob. */ + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + /****************************************************************************** Do the SPNEGO encryption negotiation. Parameters are in/out. ******************************************************************************/ @@ -265,11 +363,22 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz } if (pdata[0] == ASN1_CONTEXT(1)) { - /* Its a auth packet */ + /* It's an auth packet */ return srv_enc_spnego_ntlm_auth(ppdata, p_data_size); } - return NT_STATUS_INVALID_PARAMETER; + /* Maybe it's a raw unwrapped auth ? */ + if (*p_data_size < 7) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { + return srv_enc_raw_ntlm_auth(ppdata, p_data_size); + } + + DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); + + return NT_STATUS_LOGON_FAILURE; } /****************************************************************************** -- cgit From 071db6fdbff694681fa1793ee678a9a0af3e266a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 00:25:08 +0000 Subject: r21897: Add in a basic raw NTLM encrypt request. Now for testing. Jeremy. (This used to be commit 783a7b3085a155d9652cd725bf2960cd272cb554) --- source3/smbd/seal.c | 31 ++++++++++++++++++++++++++++++- source3/smbd/trans2.c | 5 ++++- 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 9910a84f4c..8283346c28 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -385,8 +385,36 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz Negotiation was successful - turn on server-side encryption. ******************************************************************************/ -void srv_encryption_start(void) +static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) { + if (!ec || !ec->es) { + return NT_STATUS_LOGON_FAILURE; + } + + if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { + if ((ec->es->ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != + (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { + return NT_STATUS_INVALID_PARAMETER; + } + } + /* Todo - check gssapi case. */ + + return NT_STATUS_OK; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +NTSTATUS srv_encryption_start(void) +{ + NTSTATUS status; + + /* Check that we are really doing sign+seal. */ + status = check_enc_good(partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } /* Throw away the context we're using currently (if any). */ srv_free_encryption_context(&srv_trans_enc_ctx); @@ -395,6 +423,7 @@ void srv_encryption_start(void) srv_trans_enc_ctx->es->enc_on = True; partial_srv_trans_enc_ctx = NULL; + return NT_STATUS_OK; } /****************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 25fd6621e9..158642a588 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2781,7 +2781,10 @@ cap_low = 0x%x, cap_high = 0x%x\n", if (NT_STATUS_IS_OK(status)) { /* Server-side transport encryption is now *on*. */ - srv_encryption_start(); + status = srv_encryption_start(); + if (!NT_STATUS_IS_OK(status)) { + exit_server_cleanly("Failure in setting up encrypted transport"); + } } return -1; } -- cgit From a828b56884a1385823cdb1d186860a1e1466fca7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 00:44:15 +0000 Subject: r21898: Added test command, fixed first valgrind bugs. Now to investigate why it doesn't work :-). Jeremy. (This used to be commit 73f7c6cef8371ad63eb1dc3e79bfc78503dbd7a4) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 158642a588..1c1606fd67 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2769,7 +2769,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n")); - status = srv_request_encryption_setup((unsigned char **)&pdata, &data_len); + status = srv_request_encryption_setup((unsigned char **)ppdata, &data_len); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__); @@ -2777,7 +2777,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", return ERROR_NT(status); } - send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes); + send_trans2_replies( outbuf, bufsize, params, 0, *ppdata, data_len, max_data_bytes); if (NT_STATUS_IS_OK(status)) { /* Server-side transport encryption is now *on*. */ -- cgit From ea4dada48f404b1ee0caa7b128ddac9c224fc1f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 01:04:56 +0000 Subject: r21900: Token exchange now seems to work, now why does the client encrypt fail ? Jeremy. (This used to be commit 6bd7c05290909ef9f5f377dd141a64ed0d654134) --- source3/smbd/seal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 8283346c28..fa47786d51 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -318,7 +318,7 @@ static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_siz if (!partial_srv_trans_enc_ctx) { /* This is the initial step. */ status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&partial_srv_trans_enc_ctx); return nt_status_squash(status); } -- cgit From 4a965110e5cebcb7395bc71de2ee5d222000c524 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 21 Mar 2007 14:13:42 +0000 Subject: r21904: Fix HP build -- thanks, Don (This used to be commit 57efba97b634728ae75901cb76b904a5d82986a4) --- source3/smbd/seal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index fa47786d51..64965d4272 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -145,7 +145,7 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ void srv_free_enc_buffer(char *buf) { if (srv_trans_enc_ctx) { - return common_free_enc_buffer(srv_trans_enc_ctx->es, buf); + common_free_enc_buffer(srv_trans_enc_ctx->es, buf); } } -- cgit From 42238c78bb8820a21cfb08fc29a5109ee1a62bab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 19:15:14 +0000 Subject: r21917: Start to do the gss versions of sign+seal. Jeremy. (This used to be commit a226645353a40047b72de1b96c3a7676a2bf1034) --- source3/smbd/seal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 64965d4272..9fa35601f8 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -180,8 +180,8 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) Until success we do everything on the partial enc ctx. ******************************************************************************/ -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) +static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { return NT_STATUS_NOT_SUPPORTED; } @@ -246,8 +246,8 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ srv_free_encryption_context(&partial_srv_trans_enc_ctx); -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); } else #endif -- cgit From 23149b3bb8257eeb1aeb15f165099bf3447ee05b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Mar 2007 01:14:55 +0000 Subject: r21925: Start to code up the gss acquire creds calls. Jeremy. (This used to be commit 4a7fbc88520e8f5dfe53a7c5da68040271149da3) --- source3/smbd/seal.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 9fa35601f8..e3c8b4f029 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -98,8 +98,14 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) } if (ec->es) { - if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - destroy_auth_ntlmssp(ec); + switch (ec->es->smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + destroy_auth_ntlmssp(ec); + break; +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + break; +#endif } common_free_encryption_state(&ec->es); } @@ -128,12 +134,25 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ } ZERO_STRUCTP(ec->es); ec->es->smb_enc_type = smb_enc_type; - if (smb_enc_type == SMB_TRANS_ENC_NTLM) { - NTSTATUS status = make_auth_ntlmssp(ec); - if (!NT_STATUS_IS_OK(status)) { + switch (smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + { + NTSTATUS status = make_auth_ntlmssp(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return NULL; + } + } + break; + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + /* Acquire our credentials by calling gss_acquire_cred here. */ + break; +#endif + default: srv_free_encryption_context(&ec); return NULL; - } } return ec; } @@ -183,6 +202,13 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { + if (!partial_srv_trans_enc_ctx) { + partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_GSS); + if (!partial_srv_trans_enc_ctx) { + return NT_STATUS_NO_MEMORY; + } + } + return NT_STATUS_NOT_SUPPORTED; } #endif -- cgit From f93d75c932e7a48da8bcd589d7505bf5445b89df Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Mar 2007 02:24:12 +0000 Subject: r21926: Fix missing enum specifier pointed out by Don McCall @ HP. Thanks Don ! Jeremy. (This used to be commit 662344d1ec3593689de7602afa518ed98e10dc37) --- source3/smbd/seal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index e3c8b4f029..f95a982f60 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -63,7 +63,7 @@ static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) * We must remember to update the pointer copy for the common * functions after any auth_ntlmssp_start/auth_ntlmssp_end. */ - ec->es->ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; + ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; return status; } @@ -81,7 +81,7 @@ static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) if (ec->auth_ntlmssp_state) { auth_ntlmssp_end(&ec->auth_ntlmssp_state); /* The auth_ntlmssp_end killed this already. */ - ec->es->ntlmssp_state = NULL; + ec->es->s.ntlmssp_state = NULL; } } @@ -418,7 +418,7 @@ static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) } if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - if ((ec->es->ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != + if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { return NT_STATUS_INVALID_PARAMETER; } -- cgit From bf26a7632e438199ab10c9557f7d018e19705604 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Mar 2007 22:15:35 +0000 Subject: r21942: Hoist by our own petard :-). Older smbclient binaries were not able to connect to the rewritten dfs code as they set the dfs flag bit but then send local paths. Now that our dfs code is a *lot* more robust in detecting this sort of braindamage we can just call into it directly on getting a DFS flag and let the parser sort it out without having to check it's actually connecting to a dfs enabled share (I'm proud of this code :-). Jeremy. (This used to be commit 8c4d929c76ba56d59f651c57d1feb37d2916a436) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1641679a35..13c44e9420 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1253,7 +1253,7 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na { NTSTATUS status = NT_STATUS_OK; BOOL dummy; - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + if (dfs_pathnames) { status = dfs_redirect(conn, name, False, &dummy); } return status; @@ -1269,7 +1269,7 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard) { NTSTATUS status = NT_STATUS_OK; - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + if (dfs_pathnames) { status = dfs_redirect(conn, name, True, ppath_contains_wcard); } return status; -- cgit From cc87cb7770198aa2aeac8253ff57fef8fe01f27d Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 23 Mar 2007 19:31:11 +0000 Subject: r21950: After discussion with the Apple and Linux client maintainers, changing the FindFirst response for the UNIX_INFO2 level to include a length field before the name. The name is not required to be null terminated. The length field does not count any null. Also add call to chflags(2) in the default VFS module so that this will work be default on BSD-derived platform. Add UNIX-INFO2 test to the build farm to get some non-BSD coverage. Jeremy and Jerry, please review for inclusion in 3.0.25. (This used to be commit e7b21b1ef3f79c0df2bae5f15c345ef74292c404) --- source3/smbd/trans2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1c1606fd67..14dfbe0bbf 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1601,13 +1601,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); p = store_file_unix_basic(conn, p, NULL, &sbuf); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); } else { DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); p = store_file_unix_basic_info2(conn, p, NULL, &sbuf); + nameptr = p; + p += 4; + len = srvstr_push(outbuf, p, fname, -1, 0); + SIVAL(nameptr, 0, len); } - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ -- cgit From eb465894322c78688480827b55e084210a6228a6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2007 21:11:08 +0000 Subject: r21952: Fix critical (!) error found by IBM checker. Missing break statements meant that no info levels would ever be returned correctly from POSIX open/mkdir. Jeremy. (This used to be commit ae5761ccc66b35b66ca4fa90aef02d8be1564737) --- source3/smbd/trans2.c | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 14dfbe0bbf..007ad50b10 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5329,17 +5329,20 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, SIVAL(pdata,4,info); /* Was directory created. */ switch (info_level_return) { - case SMB_QUERY_FILE_UNIX_BASIC: - SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); - SSVAL(pdata,10,0); /* Padding. */ - store_file_unix_basic(conn, pdata + 12, fsp, psbuf); - case SMB_QUERY_FILE_UNIX_INFO2: - SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); - SSVAL(pdata,10,0); /* Padding. */ - store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); - default: - SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); - SSVAL(pdata,10,0); /* Padding. */ + case SMB_QUERY_FILE_UNIX_BASIC: + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); + SSVAL(pdata,10,0); /* Padding. */ + store_file_unix_basic(conn, pdata + 12, fsp, psbuf); + break; + case SMB_QUERY_FILE_UNIX_INFO2: + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); + SSVAL(pdata,10,0); /* Padding. */ + store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); + break; + default: + SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); + SSVAL(pdata,10,0); /* Padding. */ + break; } return status; @@ -5513,17 +5516,20 @@ static NTSTATUS smb_posix_open(connection_struct *conn, SIVAL(pdata,4,info); /* Was file created etc. */ switch (info_level_return) { - case SMB_QUERY_FILE_UNIX_BASIC: - SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); - SSVAL(pdata,10,0); /* padding. */ - store_file_unix_basic(conn, pdata + 12, fsp, psbuf); - case SMB_QUERY_FILE_UNIX_INFO2: - SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); - SSVAL(pdata,10,0); /* padding. */ - store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); - default: - SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); - SSVAL(pdata,10,0); /* padding. */ + case SMB_QUERY_FILE_UNIX_BASIC: + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); + SSVAL(pdata,10,0); /* padding. */ + store_file_unix_basic(conn, pdata + 12, fsp, psbuf); + break; + case SMB_QUERY_FILE_UNIX_INFO2: + SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); + SSVAL(pdata,10,0); /* padding. */ + store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); + break; + default: + SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); + SSVAL(pdata,10,0); /* padding. */ + break; } return NT_STATUS_OK; } -- cgit From b93126ea12f057497fd5d97e79e5ebac1bcfe1ef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2007 21:50:44 +0000 Subject: r21953: One format fix, clarify a condition that the IBM checker was worried about. Jeremy. (This used to be commit 70eec7b8ae6a4992b43df853dffc21dd91498390) --- source3/smbd/service.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c96bcea4e2..79c618e7b3 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -915,10 +915,28 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ { + BOOL can_write = False; NT_USER_TOKEN *token = conn->nt_user_token ? - conn->nt_user_token : vuser->nt_user_token; + conn->nt_user_token : + (vuser ? vuser->nt_user_token : NULL); + + /* + * I don't believe this can happen. But the + * logic above is convoluted enough to confuse + * automated checkers, so be sure. JRA. + */ + + if (token == NULL) { + DEBUG(0,("make_connection: connection to %s " + "denied due to missing " + "NT token.\n", + lp_servicename(snum))); + conn_free(conn); + *status = NT_STATUS_ACCESS_DENIED; + return NULL; + } - BOOL can_write = share_access_check(token, + can_write = share_access_check(token, lp_servicename(snum), FILE_WRITE_DATA); -- cgit From eca13022ef78237f915c8fec1ecbe676b1c86ae3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Mar 2007 18:14:46 +0000 Subject: r21960: Fix bugs 4463,4464,4465,4466. Thanks Jason :-) (This used to be commit a2e27c443101a59ef3429a55e049af3ebd5ec1f2) --- source3/smbd/msdfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 13c44e9420..8f85b90fdc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -242,13 +242,11 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, int *refcount) { pstring temp; - char *prot; char *alt_path[MAX_REFERRAL_COUNT]; int count = 0, i; struct referral *reflist; pstrcpy(temp,target); - prot = strtok(temp,":"); /* parse out the alternate paths */ while((count Date: Sat, 24 Mar 2007 18:22:20 +0000 Subject: r21961: Repair bug introduced by rev. 21960. We need to do the initial strtok to set up the internal state. Jeremy. (This used to be commit 8c7042b4192cb33988c1bbccdd4a80bb99fd0118) --- source3/smbd/msdfs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 8f85b90fdc..916f661eaa 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -242,11 +242,17 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, int *refcount) { pstring temp; + char *prot; char *alt_path[MAX_REFERRAL_COUNT]; int count = 0, i; struct referral *reflist; pstrcpy(temp,target); + prot = strtok(temp,":"); + if (!prot) { + DEBUG(0,("parse_msdfs_symlink: invalid path !\n")); + return False; + } /* parse out the alternate paths */ while((count Date: Tue, 27 Mar 2007 00:50:53 +0000 Subject: r21969: Start working on the gss-side of the server negotiation. Jeremy. (This used to be commit fbc569b530104679e47fe743963eb0c4384de6ae) --- source3/smbd/negprot.c | 4 +++ source3/smbd/seal.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index bc7c75aab4..e1df08579d 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -228,6 +228,10 @@ static DATA_BLOB negprot_spnego(void) name_to_fqdn(myname, global_myname()); strlower_m(myname); asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm()); + if (host_princ_s == NULL) { + blob = data_blob(NULL, 0); + return blob; + } blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s); SAFE_FREE(host_princ_s); } diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index f95a982f60..fbb0eade52 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -85,6 +85,85 @@ static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) } } +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + +/****************************************************************************** + Import a name. +******************************************************************************/ + +static NTSTATUS get_gss_creds(const char *service, + const char *name, + gss_cred_usage_t cred_type, + gss_cred_id_t *p_srv_cred) +{ + OM_uint32 ret; + OM_uint32 min; + gss_name_t srv_name; + gss_buffer_desc input_name; + char *host_princ_s = NULL; + NTSTATUS status = NT_STATUS_OK; + + asprintf(&host_princ_s, "%s@%s", service, name); + if (host_princ_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + input_name.value = host_princ_s; + input_name.length = strlen(host_princ_s) + 1; + + ret = gss_import_name(&min, + &input_name, + GSS_C_NT_HOSTBASED_SERVICE, + &srv_name); + + if (ret != GSS_S_COMPLETE) { + SAFE_FREE(host_princ_s); + return map_nt_error_from_gss(ret, min); + } + + ret = gss_acquire_cred(&min, + &srv_name, + GSS_C_INDEFINITE, + GSS_C_NULL_OID_SET, + cred_type, + p_srv_cred, + NULL, + NULL); + + if (ret != GSS_S_COMPLETE) { + status = map_nt_error_from_gss(ret, min); + } + + SAFE_FREE(host_princ_s); + gss_release_name(&min, &srv_name); + return status; +} + +/****************************************************************************** + Create a gss state. +******************************************************************************/ + +static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status; + gss_cred_id_t srv_cred; + fstring fqdn; + + name_to_fqdn(fqdn, global_myname()); + strlower_m(fqdn); + + status = get_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + status = get_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + } + + return NT_STATUS_OK; +} +#endif + /****************************************************************************** Shutdown a server encryption context. ******************************************************************************/ @@ -148,6 +227,13 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) case SMB_TRANS_ENC_GSS: /* Acquire our credentials by calling gss_acquire_cred here. */ + { + NTSTATUS status = make_auth_gss(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return NULL; + } + } break; #endif default: -- cgit From f61062b31d8d58f7f1ddd0f9f7932ca6f6499aaa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Mar 2007 10:20:50 +0000 Subject: r21980: make use of tdb_*_bystring() and string_term_tdb_data() in smbd/ to avoid creating the TDB_DATA struct from strings "by hand" metze (This used to be commit 09b477ed85e46bc780ce3c1461472883a6b952f9) --- source3/smbd/mangle_hash.c | 3 +-- source3/smbd/session.c | 21 +++++---------------- 2 files changed, 6 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 320e31ab67..f20e473079 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -437,8 +437,7 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) } /* Allocate a new cache entry. If the allocation fails, just return. */ - data_val.dptr = raw_name; - data_val.dsize = strlen(raw_name)+1; + data_val = string_term_tdb_data(raw_name); if (tdb_store_bystring(tdb_mangled_cache, mangled_name_key, data_val, TDB_REPLACE) != 0) { DEBUG(0,("cache_mangled_name: Error storing entry %s -> %s\n", mangled_name_key, raw_name)); } else { diff --git a/source3/smbd/session.c b/source3/smbd/session.c index bcb840a3fe..da2ab40338 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -61,7 +61,6 @@ BOOL session_claim(user_struct *vuser) struct in_addr *client_ip; struct sessionid sessionid; uint32 pid = (uint32)sys_getpid(); - TDB_DATA key; fstring keystr; char * hostname; int tdb_store_flag; /* If using utmp, we do an inital 'lock hold' store, @@ -87,10 +86,8 @@ BOOL session_claim(user_struct *vuser) if (lp_utmp()) { for (i=1;ivuid); - - key.dptr = keystr; - key.dsize = strlen(keystr)+1; - tdb_store_flag = TDB_REPLACE; } @@ -142,14 +135,14 @@ BOOL session_claim(user_struct *vuser) DEBUG(1,("pam_session rejected the session for %s [%s]\n", sessionid.username, sessionid.id_str)); if (tdb_store_flag == TDB_MODIFY) { - tdb_delete(tdb, key); + tdb_delete_bystring(tdb, keystr); } return False; } data.dptr = (char *)&sessionid; data.dsize = sizeof(sessionid); - if (tdb_store(tdb, key, data, tdb_store_flag) != 0) { + if (tdb_store_bystring(tdb, keystr, data, tdb_store_flag) != 0) { DEBUG(1,("session_claim: unable to create session id record\n")); return False; } @@ -177,7 +170,6 @@ void session_yield(user_struct *vuser) TDB_DATA dbuf; struct sessionid sessionid; struct in_addr *client_ip; - TDB_DATA key; if (!tdb) return; @@ -185,10 +177,7 @@ void session_yield(user_struct *vuser) return; } - key.dptr = vuser->session_keystr; - key.dsize = strlen(vuser->session_keystr)+1; - - dbuf = tdb_fetch(tdb, key); + dbuf = tdb_fetch_bystring(tdb, vuser->session_keystr); if (dbuf.dsize != sizeof(sessionid)) return; @@ -207,7 +196,7 @@ void session_yield(user_struct *vuser) smb_pam_close_session(sessionid.username, sessionid.id_str, sessionid.hostname); - tdb_delete(tdb, key); + tdb_delete_bystring(tdb, vuser->session_keystr); } /******************************************************************** -- cgit From 4a66d0e232271968ba96da50274428916a393975 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Mar 2007 21:13:31 +0000 Subject: r21991: I hate Steve French :-). Add support for encryption contexts.... Jeremy. (This used to be commit ae8f3649f773b8a8dcb55921536d038d3475322e) --- source3/smbd/seal.c | 96 +++++++++++++++++++++++++++++++++++++++++++-------- source3/smbd/trans2.c | 12 +++++-- 2 files changed, 90 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index fbb0eade52..d5b956c53d 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -249,6 +249,14 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ void srv_free_enc_buffer(char *buf) { + /* We know this is an smb buffer, and we + * didn't malloc, only copy, for a keepalive, + * so ignore session keepalives. */ + + if(CVAL(buf,0) == SMBkeepalive) { + return; + } + if (srv_trans_enc_ctx) { common_free_enc_buffer(srv_trans_enc_ctx->es, buf); } @@ -260,9 +268,15 @@ void srv_free_enc_buffer(char *buf) NTSTATUS srv_decrypt_buffer(char *buf) { + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + if (srv_trans_enc_ctx) { return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); } + return NT_STATUS_OK; } @@ -270,13 +284,19 @@ NTSTATUS srv_decrypt_buffer(char *buf) Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. ******************************************************************************/ -NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) +NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) { + *buf_out = buf; + + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + if (srv_trans_enc_ctx) { - return common_encrypt_buffer(srv_trans_enc_ctx->es, buffer, buf_out); + return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); } /* Not encrypting. */ - *buf_out = buffer; return NT_STATUS_OK; } @@ -340,7 +360,11 @@ static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_si Until success we do everything on the partial enc ctx. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { NTSTATUS status; DATA_BLOB blob = data_blob(NULL,0); @@ -371,6 +395,17 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + *pparam = SMB_MALLOC(2); + if (!*pparam) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); + *p_param_size = 2; } return status; @@ -381,7 +416,11 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ We only get this for a NTLM auth second stage. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { NTSTATUS status; DATA_BLOB blob = data_blob(NULL,0); @@ -409,6 +448,16 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); data_blob_free(&auth_reply); + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + *pparam = SMB_MALLOC(2); + if (!*pparam) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + SAFE_FREE(*ppdata); *ppdata = response.data; *p_data_size = response.length; @@ -420,7 +469,11 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ This function does both steps. ******************************************************************************/ -static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { NTSTATUS status; DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); @@ -446,6 +499,16 @@ static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_siz /* Second step. */ status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + *pparam = SMB_MALLOC(2); + if (!*pparam) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + /* Return the raw blob. */ SAFE_FREE(*ppdata); *ppdata = response.data; @@ -457,26 +520,29 @@ static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_siz Do the SPNEGO encryption negotiation. Parameters are in/out. ******************************************************************************/ -NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_size) +NTSTATUS srv_request_encryption_setup(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { unsigned char *pdata = *ppdata; + SAFE_FREE(*pparam); + *p_param_size = 0; + if (*p_data_size < 1) { return NT_STATUS_INVALID_PARAMETER; } if (pdata[0] == ASN1_APPLICATION(0)) { - /* - * Until success we do everything on the partial - * enc state. - */ /* its a negTokenTarg packet */ - return srv_enc_spnego_negotiate(ppdata, p_data_size); + return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); } if (pdata[0] == ASN1_CONTEXT(1)) { /* It's an auth packet */ - return srv_enc_spnego_ntlm_auth(ppdata, p_data_size); + return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); } /* Maybe it's a raw unwrapped auth ? */ @@ -485,7 +551,7 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz } if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { - return srv_enc_raw_ntlm_auth(ppdata, p_data_size); + return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); } DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); @@ -518,7 +584,7 @@ static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) Negotiation was successful - turn on server-side encryption. ******************************************************************************/ -NTSTATUS srv_encryption_start(void) +NTSTATUS srv_encryption_start(connection_struct *conn) { NTSTATUS status; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 007ad50b10..df713db564 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2765,6 +2765,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", case SMB_REQUEST_TRANSPORT_ENCRYPTION: { NTSTATUS status; + size_t param_len = 0; size_t data_len = total_data; if (!lp_unix_extensions()) { @@ -2773,7 +2774,12 @@ cap_low = 0x%x, cap_high = 0x%x\n", DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n")); - status = srv_request_encryption_setup((unsigned char **)ppdata, &data_len); + status = srv_request_encryption_setup(conn, + (unsigned char **)ppdata, + &data_len, + (unsigned char **)pparams, + ¶m_len + ); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__); @@ -2781,11 +2787,11 @@ cap_low = 0x%x, cap_high = 0x%x\n", return ERROR_NT(status); } - send_trans2_replies( outbuf, bufsize, params, 0, *ppdata, data_len, max_data_bytes); + send_trans2_replies(outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes); if (NT_STATUS_IS_OK(status)) { /* Server-side transport encryption is now *on*. */ - status = srv_encryption_start(); + status = srv_encryption_start(conn); if (!NT_STATUS_IS_OK(status)) { exit_server_cleanly("Failure in setting up encrypted transport"); } -- cgit From e9157961d6c89318de4c7ff5a700aed640d91d92 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Mar 2007 01:11:27 +0000 Subject: r21997: Implement the server side of gss seal negotiate. Jeremy. (This used to be commit 6b923acfee59e39eea69e9e9a00f1f6118ed4270) --- source3/smbd/seal.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index d5b956c53d..0a093d21ab 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -97,7 +97,7 @@ static NTSTATUS get_gss_creds(const char *service, gss_cred_id_t *p_srv_cred) { OM_uint32 ret; - OM_uint32 min; + OM_uint32 min; gss_name_t srv_name; gss_buffer_desc input_name; char *host_princ_s = NULL; @@ -141,6 +141,8 @@ static NTSTATUS get_gss_creds(const char *service, /****************************************************************************** Create a gss state. + Try and get the cifs/server@realm principal first, then fall back to + host/server@realm. ******************************************************************************/ static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) @@ -160,6 +162,18 @@ static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) } } + ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); + if (!ec->es->s.gss_state) { + OM_uint32 min; + gss_release_cred(&min, &srv_cred); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(ec->es->s.gss_state); + ec->es->s.gss_state->creds = srv_cred; + + /* No context yet. */ + ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; + return NT_STATUS_OK; } #endif @@ -197,19 +211,21 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) Create a server encryption context. ******************************************************************************/ -static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type) +static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) { struct smb_srv_trans_enc_ctx *ec; + *pp_ec = NULL; + ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); if (!ec) { - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(partial_srv_trans_enc_ctx); ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); if (!ec->es) { SAFE_FREE(ec); - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(ec->es); ec->es->smb_enc_type = smb_enc_type; @@ -219,7 +235,7 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ NTSTATUS status = make_auth_ntlmssp(ec); if (!NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&ec); - return NULL; + return status; } } break; @@ -231,16 +247,17 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ NTSTATUS status = make_auth_gss(ec); if (!NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&ec); - return NULL; + return status; } } break; #endif default: srv_free_encryption_context(&ec); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } - return ec; + *pp_ec = ec; + return NT_STATUS_OK; } /****************************************************************************** @@ -308,14 +325,68 @@ NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { + OM_uint32 ret; + OM_uint32 min; + OM_uint32 flags = 0; + gss_buffer_desc in_buf, out_buf; + struct smb_tran_enc_state_gss *gss_state; + if (!partial_srv_trans_enc_ctx) { - partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_GSS); - if (!partial_srv_trans_enc_ctx) { - return NT_STATUS_NO_MEMORY; + NTSTATUS status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; + + in_buf.value = secblob.data; + in_buf.length = secblob.length; + + out_buf.value = NULL; + out_buf.length = 0; + + ret = gss_accept_sec_context(&min, + &gss_state->gss_ctx, + gss_state->creds, + &in_buf, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, /* Ignore oids. */ + &out_buf, /* To return. */ + &flags, + NULL, /* Ingore time. */ + NULL); /* Ignore delegated creds. */ + + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + return gss_err_to_ntstatus(ret, min); + } + + /* Ensure we've got sign+seal available. */ + if (ret == GSS_S_COMPLETE) { + if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != + (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { + DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " + "for SMB sealing.\n")); + gss_release_buffer(&min, &out_buf); + return NT_STATUS_ACCESS_DENIED; } } - return NT_STATUS_NOT_SUPPORTED; + SAFE_FREE(*ppdata); + *ppdata = memdup(out_buf.value, out_buf.length); + if (!*ppdata) { + gss_release_buffer(&min, &out_buf); + return NT_STATUS_NO_MEMORY; + } + *p_data_size = out_buf.length; + gss_release_buffer(&min, &out_buf); + + if (ret != GSS_S_CONTINUE_NEEDED) { + return NT_STATUS_MORE_PROCESSING_REQUIRED; + } else { + return NT_STATUS_OK; + } } #endif @@ -330,9 +401,9 @@ static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_si DATA_BLOB chal = data_blob(NULL, 0); DATA_BLOB response = data_blob(NULL, 0); - partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_NTLM); - if (!partial_srv_trans_enc_ctx) { - return NT_STATUS_NO_MEMORY; + status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; } status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); -- cgit From 56ba44766854ed7cda265bdaf85913f2a1008282 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 28 Mar 2007 13:34:59 +0000 Subject: r22001: change prototype of dump_data(), so that it takes unsigned char * now, which matches what samba4 has. also fix all the callers to prevent compiler warnings metze (This used to be commit fa322f0cc9c26a9537ba3f0a7d4e4a25941317e7) --- source3/smbd/chgpasswd.c | 4 ++-- source3/smbd/msdfs.c | 6 +++--- source3/smbd/nttrans.c | 2 +- source3/smbd/trans2.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 7c6886b81c..8146d6d137 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -983,8 +983,8 @@ static BOOL check_passwd_history(struct samu *sampass, const char *plaintext) return True; } - dump_data(100, (const char *)new_nt_p16, NT_HASH_LEN); - dump_data(100, (const char *)pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen); + dump_data(100, new_nt_p16, NT_HASH_LEN); + dump_data(100, pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen); memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN); for (i=0; ireferral_count)); @@ -817,7 +817,7 @@ static int setup_ver3_dfs_referral(const char *pathname, reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE); if (DEBUGLVL(10)) { - dump_data(0, (char *) uni_reqpath,reqpathlen); + dump_data(0, uni_reqpath,reqpathlen); } uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count; @@ -970,7 +970,7 @@ int setup_dfs_referral(connection_struct *orig_conn, if (DEBUGLVL(10)) { DEBUGADD(0,("DFS Referral pdata:\n")); - dump_data(0,*ppdata,reply_size); + dump_data(0,(uint8 *)*ppdata,reply_size); } talloc_destroy(ctx); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0ecb14f9c7..51ed081edb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3044,7 +3044,7 @@ int reply_nttrans(connection_struct *conn, } memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count); - dump_data(10, (char *)state->setup, state->setup_count); + dump_data(10, (uint8 *)state->setup, state->setup_count); } if ((state->received_data == state->total_data) && diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index df713db564..b06b53b299 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -147,7 +147,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str } DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret)); - dump_data(10, val, sizeret); + dump_data(10, (uint8 *)val, sizeret); pea->flags = 0; if (strnequal(ea_name, "user.", 5)) { @@ -487,7 +487,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da } DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name)); - dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length); + dump_data(10, eal->ea.value.data, eal->ea.value.length); return eal; } -- cgit From b9461058d59f8e4f4b69c31592bd12a179b2d8ac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Mar 2007 08:24:15 +0000 Subject: r22008: use string_term_tdb_data() metze (This used to be commit 1f047d7e31252481c4ed905e0dfdb791c704adca) --- source3/smbd/connection.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 0442a9441a..7838c5c23d 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -272,11 +272,10 @@ static TDB_DATA* make_pipe_rec_key( struct pipe_open_rec *prec ) snprintf( key_string, sizeof(key_string), "%s/%d/%d", prec->name, procid_to_pid(&prec->pid), prec->pnum ); - if ( (kbuf->dptr = talloc_strdup(prec, key_string)) == NULL ) + *kbuf = string_term_tdb_data(talloc_strdup(prec, key_string)); + if (kbuf->dptr == NULL ) return NULL; - - kbuf->dsize = strlen(key_string)+1; - + return kbuf; } -- cgit From bc2b6436d0f5f3e9ffdfaeb7f1b32996a83d5478 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Mar 2007 09:35:51 +0000 Subject: r22009: change TDB_DATA from char * to unsigned char * and fix all compiler warnings in the users metze (This used to be commit 3a28443079c141a6ce8182c65b56ca210e34f37f) --- source3/smbd/connection.c | 6 +++--- source3/smbd/mangle_hash.c | 2 +- source3/smbd/notify_internal.c | 2 +- source3/smbd/session.c | 2 +- source3/smbd/statcache.c | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 7838c5c23d..7e53a29b04 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -50,7 +50,7 @@ static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *p } #endif - pkbuf->dptr = (char *)pkey; + pkbuf->dptr = (uint8 *)pkey; pkbuf->dsize = sizeof(*pkey); } @@ -200,7 +200,7 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti safe_strcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1); safe_strcpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1); - dbuf.dptr = (char *)&crec; + dbuf.dptr = (uint8 *)&crec; dbuf.dsize = sizeof(crec); if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { @@ -313,7 +313,7 @@ BOOL store_pipe_opendb( smb_np_struct *p ) goto done; } - data.dptr = (char*)prec; + data.dptr = (uint8 *)prec; data.dsize = sizeof(struct pipe_open_rec); if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) { diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index f20e473079..3cc7d1e5c2 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -502,7 +502,7 @@ static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p ) } /* If we *did* find it, we need to copy it into the string buffer. */ - (void)safe_strcpy( s, data_val.dptr, maxlen ); + (void)safe_strcpy( s, (const char *)data_val.dptr, maxlen ); if( saved_ext ) { /* Replace the saved_ext as it was truncated. */ (void)safe_strcat( s, saved_ext, maxlen ); diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 72b9604935..e1f47540e5 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -231,7 +231,7 @@ static NTSTATUS notify_save(struct notify_context *notify) NDR_PRINT_DEBUG(notify_array, notify->array); } - dbuf.dptr = (char *)blob.data; + dbuf.dptr = blob.data; dbuf.dsize = blob.length; ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index da2ab40338..a3334a353e 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -140,7 +140,7 @@ BOOL session_claim(user_struct *vuser) return False; } - data.dptr = (char *)&sessionid; + data.dptr = (uint8 *)&sessionid; data.dsize = sizeof(sessionid); if (tdb_store_bystring(tdb, keystr, data, tdb_store_flag) != 0) { DEBUG(1,("session_claim: unable to create session id record\n")); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 1a2b7a8237..e257483f81 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -131,7 +131,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat */ data_val.dsize = translated_path_length + 1; - data_val.dptr = translated_path; + data_val.dptr = (uint8 *)translated_path; if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); @@ -242,7 +242,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } else { BOOL retval; - char *translated_path = data_val.dptr; + char *translated_path = (char *)data_val.dptr; size_t translated_path_length = data_val.dsize - 1; DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path )); @@ -329,7 +329,7 @@ unsigned int fast_string_hash(TDB_DATA *key) { unsigned int n = 0; const char *p; - for (p = key->dptr; *p != '\0'; p++) { + for (p = (const char *)key->dptr; *p != '\0'; p++) { n = ((n << 5) + n) ^ (unsigned int)(*p); } return n; -- cgit From 75b4e240671067e1e94825b9e923eb4a4de0b708 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Mar 2007 19:40:59 +0000 Subject: r22010: Now I'm looking at mangling again, make sure that we mangle any illegal names before doing any wildcard matches. That way lies least suprises. Don't merge this for 3.0.25, too dangerous. Thanks. Jeremy. (This used to be commit 8e15ef476cada7a900ff17c7ba70c729d56718bd) --- source3/smbd/trans2.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b06b53b299..dfba188b74 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1160,16 +1160,28 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n", (long)conn->dirptr,curr_dirpos)); - if (!dname) + if (!dname) { return(False); + } + + /* + * fname may get mangled, dname is never mangled. + * Whenever we're accessing the filesystem we use + * pathreal which is composed from dname. + */ pstrcpy(fname,dname); - if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) + /* This will mangle fname if it's an illegal name. */ + mangle_map(fname,False,True,conn->params); + + if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) { got_match = mask_match(fname, mask, conn->case_sensitive); + } if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, conn->params)) { + pstring mangled_name; /* * It turns out that NT matches wildcards against @@ -1178,21 +1190,25 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, * that some people have been seeing.... JRA. */ - pstring newname; - pstrcpy( newname, fname); - mangle_map( newname, True, False, conn->params); - if(!(got_match = *got_exact_match = exact_match(conn, newname, mask))) - got_match = mask_match(newname, mask, conn->case_sensitive); + pstrcpy(mangled_name, fname); + + /* Force the mangling into 8.3. */ + mangle_map( mangled_name, True, False, conn->params); + if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) { + got_match = mask_match(mangled_name, mask, conn->case_sensitive); + } } - if(got_match) { - BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); - if (dont_descend && !isdots) + if (got_match) { + BOOL isdots = (strequal(dname,"..") || strequal(dname,".")); + if (dont_descend && !isdots) { continue; + } pstrcpy(pathreal,conn->dirpath); - if(needslash) + if(needslash) { pstrcat(pathreal,"/"); + } pstrcat(pathreal,dname); if (INFO_LEVEL_IS_UNIX(info_level)) { @@ -1230,12 +1246,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } if (!dir_check_ftype(conn,mode,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); + DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype)); continue; } - if (!(mode & aDIR)) + if (!(mode & aDIR)) { file_size = get_file_size(sbuf); + } allocation_size = get_allocation_size(conn,NULL,&sbuf); mdate_ts = get_mtimespec(&sbuf); @@ -1252,7 +1269,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mdate = convert_timespec_to_time_t(mdate_ts); adate = convert_timespec_to_time_t(adate_ts); - DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); + DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname)); found = True; @@ -1260,8 +1277,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } } - mangle_map(fname,False,True,conn->params); - p = pdata; last_entry_ptr = p; -- cgit From b0bcb483697249123f92f5ac477c98b579135887 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2007 22:19:51 +0000 Subject: r22013: Move to SSPI framing (sig first in NTLM). Jeremy (This used to be commit 22eaed76f01ea9d0184dcaf57adca23abc6330b9) --- source3/smbd/seal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 0a093d21ab..66ae8419d4 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -91,7 +91,7 @@ static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) Import a name. ******************************************************************************/ -static NTSTATUS get_gss_creds(const char *service, +static NTSTATUS get_srv_gss_creds(const char *service, const char *name, gss_cred_usage_t cred_type, gss_cred_id_t *p_srv_cred) @@ -154,9 +154,9 @@ static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) name_to_fqdn(fqdn, global_myname()); strlower_m(fqdn); - status = get_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); + status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); if (!NT_STATUS_IS_OK(status)) { - status = get_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); + status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); if (!NT_STATUS_IS_OK(status)) { return nt_status_squash(status); } -- cgit From 261c004d7bf85de945a1a3956c1d8f15075bc224 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2007 22:25:08 +0000 Subject: r22014: Make us pass RANDOMIPC test again :-(. This is an ugly check-in, but I've no option. Jeremy. (This used to be commit c3a565081d70b209a4f9e6e8f1859bf7194a5f74) --- source3/smbd/lanman.c | 878 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 601 insertions(+), 277 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e42d96b11e..905b6a023a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -50,10 +50,13 @@ extern userdom_struct current_user_info; #define SHPWLEN 8 /* share password length */ -static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, - char **rdata, char **rparam, - int *rdata_len, int *rparam_len); +static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len); + static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, @@ -585,7 +588,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, lp_servicename(snum))); goto err; } - + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, "Windows 4.0", 0)) ) { @@ -597,17 +600,17 @@ static void fill_printq_info_52(connection_struct *conn, int snum, trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0); trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0); trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0); - + PACKI(desc, "W", 0x0400); /* don't know */ PACKS(desc, "z", driver.info_3->name); /* long printer name */ PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */ PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */ PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ - + fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); standard_sub_basic( "", "", location, sizeof(location)-1 ); PACKS(desc,"z", location); /* share to retrieve files */ - + PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */ PACKS(desc,"z", driver.info_3->driverpath); /* driver name */ @@ -627,12 +630,12 @@ static void fill_printq_info_52(connection_struct *conn, int snum, PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */ DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i])); } - + /* sanity check */ if ( i != count ) DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n", count, i)); - + DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i)); desc->errcode=NERR_Success; @@ -645,7 +648,7 @@ err: done: if ( printer ) free_a_printer( &printer, 2 ); - + if ( driver.info_3 ) free_a_printer_driver( driver, 3 ); } @@ -743,7 +746,7 @@ static int get_printerdrivernumber(int snum) lp_servicename(snum))); goto done; } - + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, "Windows 4.0", 0)) ) { @@ -751,7 +754,7 @@ static int get_printerdrivernumber(int snum) printer->info_2->drivername)); goto done; } - + /* count the number of files */ while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] ) result++; @@ -759,39 +762,50 @@ static int get_printerdrivernumber(int snum) done: if ( printer ) free_a_printer( &printer, 2 ); - + if ( driver.info_3 ) free_a_printer_driver( driver, 3 ); - + return result; } -static BOOL api_DosPrintQGetInfo(connection_struct *conn, - uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); char *QueueName = p; unsigned int uLevel; int count=0; int snum; - char* str3; + char *str3; struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; char* tmpdata=NULL; + if (!str1 || !str2 || !p) { + return False; + } memset((char *)&status,'\0',sizeof(status)); memset((char *)&desc,'\0',sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - str3 = p + 4; - + + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + str3 = get_safe_offset(param,tpscnt,p,4) ? p + 4 : 0; + /* Check if string exists. */ + if (skip_string(param,tpscnt,str3,1) == NULL) { + return False; + } + /* remove any trailing username */ if ((p = strchr_m(QueueName,'%'))) *p = 0; @@ -883,16 +897,18 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, View list of all print jobs on all queues. ****************************************************************************/ -static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data, - int mdrcnt, int mprcnt, - char **rdata, char** rparam, - int *rdata_len, int *rparam_len) +static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, + char **rdata, char** rparam, + int *rdata_len, int *rparam_len) { - char *param_format = param+2; - char *output_format1 = skip_string(param_format,1); - char *p = skip_string(output_format1,1); - unsigned int uLevel = SVAL(p,0); - char *output_format2 = p + 4; + char *param_format = get_safe_offset(param,tpscnt,param,2); + char *output_format1 = skip_string(param,tpscnt,param_format,1); + char *p = skip_string(param,tpscnt,output_format1,1); + unsigned int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + char *output_format2 = get_safe_offset(param,tpscnt,p,4); int services = lp_numservices(); int i, n; struct pack_desc desc; @@ -901,6 +917,13 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, int *subcntarr = NULL; int queuecnt = 0, subcnt = 0, succnt = 0; + if (!param_format || !output_format1 || !p || !output_format2) { + return False; + } + + uLevel = SVAL(p,0); + output_format2 = p + 4; + memset((char *)&desc,'\0',sizeof(desc)); DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); @@ -1252,16 +1275,18 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) extracted from lists saved by nmbd on the local host. ****************************************************************************/ -static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, char **rdata, - char **rparam, int *rdata_len, int *rparam_len) +static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - uint32 servertype = IVAL(p,4); + char *str1 = get_safe_offset(param, tpscnt, param, 2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param, tpscnt, p, 2) ? SVAL(p,0) : -1; + int buf_len = get_safe_offset(param,tpscnt, p, 4) ? SVAL(p,2) : 0; + uint32 servertype = get_safe_offset(param,tpscnt,p,8) ? IVAL(p,4) : 0; char *p2; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; @@ -1272,6 +1297,10 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param BOOL domain_request; BOOL local_request; + if (!str1 || !str2 || !p) { + return False; + } + /* If someone sets all the bits they don't really mean to set DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the known servers. */ @@ -1307,6 +1336,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); if (strcmp(str1, "WrLehDz") == 0) { + if (skip_string(param,tpscnt,p,1) == NULL) { + return False; + } pull_ascii_fstring(domain, p); } else { fstrcpy(domain, lp_workgroup()); @@ -1399,18 +1431,24 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param command 0x34 - suspected of being a "Lookup Names" stub api ****************************************************************************/ -static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, char **rdata, - char **rparam, int *rdata_len, int *rparam_len) +static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int buf_len = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : 0; int counted=0; int missed=0; + if (!str1 || !str2 || !p) { + return False; + } + DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", str1, str2, p, uLevel, buf_len)); @@ -1582,18 +1620,25 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, return len; } -static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *netname = skip_string(str2,1); - char *p = skip_string(netname,1); - int uLevel = SVAL(p,0); - int snum = find_service(netname); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *netname = skip_string(param,tpscnt,str2,1); + char *p = skip_string(param,tpscnt,netname,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int snum; + if (!str1 || !str2 || !netname || !p) { + return False; + } + + snum = find_service(netname); if (snum < 0) { return False; } @@ -1638,22 +1683,21 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para Share names longer than 12 bytes must be skipped. ****************************************************************************/ -static BOOL api_RNetShareEnum( connection_struct *conn, - uint16 vuid, - char *param, - char *data, - int mdrcnt, - int mprcnt, - char **rdata, - char **rparam, - int *rdata_len, - int *rparam_len ) +static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, + int mprcnt, + char **rdata, + char **rparam, + int *rdata_len, + int *rparam_len ) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int buf_len = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : 0; char *p2; int count = 0; int total=0,counted=0; @@ -1662,6 +1706,10 @@ static BOOL api_RNetShareEnum( connection_struct *conn, int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; + if (!str1 || !str2 || !p) { + return False; + } + if (!prefix_ok(str1,"WrLeh")) { return False; } @@ -1743,15 +1791,17 @@ static BOOL api_RNetShareEnum( connection_struct *conn, Add a share ****************************************************************************/ -static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; fstring sharename; fstring comment; pstring pathname; @@ -1760,6 +1810,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch int snum; int res = ERRunsup; + if (!str1 || !str2 || !p) { + return False; + } + /* check it's a supported varient */ if (!prefix_ok(str1,RAP_WShareAdd_REQ)) { return False; @@ -1771,6 +1825,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch return False; } + /* Do we have a string ? */ + if (skip_string(data,mdrcnt,data,1) == NULL) { + return False; + } pull_ascii_fstring(sharename,data); snum = find_service(sharename); if (snum >= 0) { /* already exists */ @@ -1778,6 +1836,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch goto error_exit; } + if (mdrcnt < 28) { + return False; + } + /* only support disk share adds */ if (SVAL(data,14)!=STYPE_DISKTREE) { return False; @@ -1789,6 +1851,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch goto error_exit; } + /* Do we have a string ? */ + if (skip_string(data,mdrcnt,data+offset,1) == NULL) { + return False; + } pull_ascii_fstring(comment, offset? (data+offset) : ""); offset = IVAL(data, 26); @@ -1798,6 +1864,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch goto error_exit; } + /* Do we have a string ? */ + if (skip_string(data,mdrcnt,data+offset,1) == NULL) { + return False; + } pull_ascii_pstring(pathname, offset? (data+offset) : ""); string_replace(sharename, '"', ' '); @@ -1858,23 +1928,29 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch view list of groups available ****************************************************************************/ -static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { int i; int errflags=0; int resume_context, cli_buf_size; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); struct pdb_search *search; struct samr_displayentry *entries; int num_entries; + if (!str1 || !str2 || !p) { + return False; + } + if (strcmp(str1,"WrLeh") != 0) { return False; } @@ -1901,8 +1977,8 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c return False; } - resume_context = SVAL(p,0); - cli_buf_size=SVAL(p+2,0); + resume_context = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + cli_buf_size= get_safe_offset(param,tpscnt,p,4) ? SVAL(p+2,0) : 0; DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: " "%d\n", resume_context, cli_buf_size)); @@ -1958,16 +2034,18 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c Get groups that a user is a member of. ******************************************************************/ -static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *UserName = skip_string(str2,1); - char *p = skip_string(UserName,1); - int uLevel = SVAL(p,0); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *UserName = skip_string(param,tpscnt,str2,1); + char *p = skip_string(param,tpscnt,UserName,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; const char *level_string; int count=0; struct samu *sampw = NULL; @@ -1981,6 +2059,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para enum lsa_SidType type; TALLOC_CTX *mem_ctx; + if (!str1 || !str2 || !UserName || !p) { + return False; + } + *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { @@ -2091,10 +2173,12 @@ done: Get all users. ******************************************************************/ -static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { int count_sent=0; int num_users=0; @@ -2103,9 +2187,13 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch struct pdb_search *search; struct samr_displayentry *users; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + + if (!str1 || !str2 || !p) { + return False; + } if (strcmp(str1,"WrLeh") != 0) return False; @@ -2117,8 +2205,8 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch * h -> return parameter total number of users */ - resume_context = SVAL(p,0); - cli_buf_size=SVAL(p+2,0); + resume_context = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + cli_buf_size= get_safe_offset(param,tpscnt,p,4) ? SVAL(p+2,0) : 0; DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); @@ -2189,10 +2277,12 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch Get the time of day info. ****************************************************************************/ -static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { struct tm *t; time_t unixdate = time(NULL); @@ -2245,21 +2335,38 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch Set the user password. *****************************************************************************/ -static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *p = skip_string(param+2,2); + char *np = get_safe_offset(param,tpscnt,param,2); + char *p = skip_string(param,tpscnt,np,2); fstring user; fstring pass1,pass2; + if (!np || !p) { + return False; + } + + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == NULL) { + return False; + } pull_ascii_fstring(user,p); - p = skip_string(p,1); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } memset(pass1,'\0',sizeof(pass1)); memset(pass2,'\0',sizeof(pass2)); + if (get_safe_offset(param,tpscnt,p,32) == NULL) { + return False; + } memcpy(pass1,p,16); memcpy(pass2,p+16,16); @@ -2331,19 +2438,24 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param Set the user password (SamOEM version - gets plaintext). ****************************************************************************/ -static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { fstring user; - char *p = param + 2; + char *p = get_safe_offset(param,tpscnt,param,2); *rparam_len = 2; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { return False; } + if (!p) { + return False; + } *rdata_len = 0; SSVAL(*rparam,0,NERR_badpass); @@ -2352,17 +2464,35 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * * Check the parameter definition is correct. */ - if(!strequal(param + 2, "zsT")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == 0) { + return False; + } + if(!strequal(p, "zsT")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p)); + return False; + } + p = skip_string(param, tpscnt, p, 1); + if (!p) { return False; } - p = skip_string(p, 1); + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == 0) { + return False; + } if(!strequal(p, "B516B16")) { DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); return False; } - p = skip_string(p,1); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == 0) { + return False; + } p += pull_ascii_fstring(user,p); DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); @@ -2386,21 +2516,29 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * Form: <> ****************************************************************************/ -static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + int function = get_safe_offset(param,tpscnt,param,2) ? SVAL(param,0) : 0; + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); uint32 jobid; int snum; fstring sharename; int errcode; WERROR werr = WERR_OK; + if (!str1 || !str2 || !p) { + return False; + } + if (get_safe_offset(param,tpscnt,p,2) == NULL) { + return False; + } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; @@ -2457,19 +2595,25 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param Purge a print queue - or pause or resume it. ****************************************************************************/ -static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *QueueName = skip_string(str2,1); + int function = get_safe_offset(param,tpscnt,param,2) ? SVAL(param,0) : 0; + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *QueueName = skip_string(param,tpscnt,str2,1); int errcode = NERR_notsupported; int snum; WERROR werr = WERR_OK; + if (!str1 || !str2 || !QueueName) { + return False; + } + /* check it's a supported varient */ if (!(strcsequal(str1,"z") && strcsequal(str2,""))) return(False); @@ -2533,21 +2677,29 @@ static int check_printjob_info(struct pack_desc* desc, return True; } -static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { struct pack_desc desc; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); uint32 jobid; fstring sharename; - int uLevel = SVAL(p,2); - int function = SVAL(p,4); + int uLevel = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : -1; + int function = get_safe_offset(param,tpscnt,p,6) ? SVAL(p,4) : -1; int place, errcode; + if (!str1 || !str2 || !p) { + return False; + } + if (get_safe_offset(param,tpscnt,p,2) == NULL) { + return False; + } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; *rparam_len = 4; @@ -2609,18 +2761,24 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha Get info about the server. ****************************************************************************/ -static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; char *p2; int struct_len; + if (!str1 || !str2 || !p) { + return False; + } + DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); /* check it's a supported varient */ @@ -2715,7 +2873,10 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par current_user_info.domain, comment, sizeof(comment)); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } } } @@ -2741,16 +2902,22 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par Get info about the server. ****************************************************************************/ -static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); char *p2; - int level = SVAL(p,0); + int level = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + + if (!str1 || !str2 || !p) { + return False; + } DEBUG(4,("NetWkstaGetInfo level %d\n",level)); @@ -2775,23 +2942,35 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(*rparam,2,0); /* converter word */ p = *rdata; - p2 = p + 22; + p2 = get_safe_offset(*rdata,*rdata_len,p,22); + if (!p2) { + return False; + } SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ pstrcpy(p2,get_local_machine_name()); strupper_m(p2); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); pstrcpy(p2,current_user_info.smb_name); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ pstrcpy(p2,lp_workgroup()); strupper_m(p2); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ @@ -2800,12 +2979,18 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,0,PTR_DIFF(p2,*rdata)); pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */ - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; *rdata_len = PTR_DIFF(p2,*rdata); @@ -2985,16 +3170,18 @@ There is no auxiliary data in the response. #define AF_OP_ACCOUNTS 3 -static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *UserName = skip_string(str2,1); - char *p = skip_string(UserName,1); - int uLevel = SVAL(p,0); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *UserName = skip_string(param,tpscnt,str2,1); + char *p = skip_string(param,tpscnt,UserName,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; char *p2; const char *level_string; @@ -3007,6 +3194,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param vuser->user.unix_name)); } + if (!str1 || !str2 || !UserName || !p) { + return False; + } + *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { @@ -3042,7 +3233,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(*rparam,2,0); /* converter word */ p = *rdata; - p2 = p + usri11_end; + p2 = get_safe_offset(*rdata,*rdata_len,p,usri11_end); + if (!p2) { + return False; + } memset(p,0,21); fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ @@ -3055,16 +3249,25 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param if (uLevel >= 10) { SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ pstrcpy(p2,"Comment"); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ pstrcpy(p2,"UserComment"); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } } if (uLevel == 11) { @@ -3074,22 +3277,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,usri11_last_logon,0); /* last logon */ SIVAL(p,usri11_last_logoff,0); /* last logoff */ SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ SSVALS(p,usri11_num_logons,-1); /* num logons */ SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ pstrcpy(p2,"\\\\*"); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SSVAL(p,usri11_country_code,0); /* country code */ SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVALS(p,usri11_max_storage,-1); /* max storage */ SSVAL(p,usri11_units_per_week,168); /* units per week */ @@ -3098,7 +3313,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param /* a simple way to get logon hours at all times. */ memset(p2,0xff,21); SCVAL(p2,21,0); /* fix zero termination */ - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SSVAL(p,usri11_code_page,0); /* code page */ } @@ -3110,22 +3328,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } if (uLevel == 2) { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,76,0); /* workstations */ SIVAL(p,80,0); /* last_logon */ SIVAL(p,84,0); /* last_logoff */ @@ -3144,7 +3374,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param standard_sub_basic("", "", tmp, sizeof(tmp)); pstrcpy(p2, tmp); } - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SSVAL(p,110,49); /* country_code */ SSVAL(p,112,860); /* code page */ } @@ -3157,14 +3390,16 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param return(True); } -static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; struct pack_desc desc; char* name; @@ -3172,12 +3407,19 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); + if (!str1 || !str2 || !p) { + return False; + } + if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->user.unix_name)); } - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + if (skip_string(param,tpscnt,p+2,1) == NULL) { + return False; + } name = p + 2; memset((char *)&desc,'\0',sizeof(desc)); @@ -3251,15 +3493,21 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param api_WAccessGetUserPerms ****************************************************************************/ -static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *user = skip_string(str2,1); - char *resource = skip_string(user,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *user = skip_string(param,tpscnt,str2,1); + char *resource = skip_string(param,tpscnt,user,1); + + if (!str1 || !str2 || !user || !resource) { + return False; + } DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); @@ -3287,14 +3535,16 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p api_WPrintJobEnumerate ****************************************************************************/ -static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int count; int i; @@ -3306,7 +3556,11 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para print_status_struct status; char *tmpdata=NULL; - uLevel = SVAL(p,2); + if (!str1 || !str2 || !p) { + return False; + } + + uLevel = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : -1; memset((char *)&desc,'\0',sizeof(desc)); memset((char *)&status,'\0',sizeof(status)); @@ -3380,15 +3634,17 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para return True; } -static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* name = p; + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + char *name = p; int uLevel; int count; int i, succnt=0; @@ -3397,11 +3653,18 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa print_queue_struct *queue=NULL; print_status_struct status; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); memset((char *)&status,'\0',sizeof(status)); - p = skip_string(p,1); - uLevel = SVAL(p,0); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); @@ -3524,24 +3787,33 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, } } -static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); char* PrinterName = p; int uLevel; struct pack_desc desc; int snum; char *tmpdata=NULL; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - p = skip_string(p,1); - uLevel = SVAL(p,0); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); @@ -3595,23 +3867,29 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par return True; } -static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int queuecnt; int i, n, succnt=0; struct pack_desc desc; int services = lp_numservices(); + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); @@ -3670,21 +3948,27 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, return True; } -static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int succnt; struct pack_desc desc; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : 0; DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); @@ -3727,21 +4011,26 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para return True; } -static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int succnt; struct pack_desc desc; + if (!str1 || !str2 || !p) { + return False; + } memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); @@ -3785,21 +4074,27 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param return True; } -static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int succnt; struct pack_desc desc; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); @@ -3844,27 +4139,33 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, return True; } - /**************************************************************************** List open sessions ****************************************************************************/ -static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) + +static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; struct pack_desc desc; struct sessionid *session_list; int i, num_sessions; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel)); DEBUG(7,("RNetSessionEnum req string=%s\n",str1)); @@ -3951,10 +4252,12 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char The request is not supported. ****************************************************************************/ -static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, - char **rdata, char **rparam, - int *rdata_len, int *rparam_len) +static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len) { *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); @@ -3975,7 +4278,9 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, c static const struct { const char *name; int id; - BOOL (*fn)(connection_struct *,uint16,char *,char *, + BOOL (*fn)(connection_struct *, uint16, + char *, int, + char *, int, int,int,char **,char **,int *,int *); BOOL auth_user; /* Deny anonymous access? */ } api_commands[] = { @@ -4030,6 +4335,8 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * int api_command; char *rdata = NULL; char *rparam = NULL; + const char *name1 = NULL; + const char *name2 = NULL; int rdata_len = 0; int rparam_len = 0; BOOL reply=False; @@ -4040,12 +4347,25 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * return 0; } + if (tpscnt < 2) { + return 0; + } api_command = SVAL(params,0); + /* Is there a string at position params+2 ? */ + if (skip_string(params,tpscnt,params+2,1)) { + name1 = params + 2; + } else { + name1 = ""; + } + name2 = skip_string(params,tpscnt,params+2,1); + if (!name2) { + name2 = ""; + } DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", api_command, - params+2, - skip_string(params+2,1), + name1, + name2, tdscnt,tpscnt,mdrcnt,mprcnt)); for (i=0;api_commands[i].name;i++) { @@ -4082,7 +4402,11 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * return -1; } - reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, + reply = api_commands[i].fn(conn, + vuid, + params,tpscnt, /* params + length */ + data,tdscnt, /* data + length */ + mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); @@ -4093,7 +4417,7 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * /* if we get False back then it's actually unsupported */ if (!reply) { - reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, + reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); } -- cgit From 730bfd9ced5dc7bf6948de66834f3e465a8cc724 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 31 Mar 2007 01:14:00 +0000 Subject: r22017: After changing 2000 lines of this I think this is needed :-). Jeremy. (This used to be commit 99092e8841edea468fa1e59a8c725f3467b58966) --- source3/smbd/lanman.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 905b6a023a..f0e553e231 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Inter-process communication and named pipe handling Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2007. SMB Version handling Copyright (C) John H Terpstra 1995-1998 -- cgit From fb3835846ef89a632230ff808259dad1cddc05c0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 Apr 2007 03:46:13 +0000 Subject: r22020: Make it more clear that both the vuser struct and it's contents are talloc_free()'ed at the end of a session. Rework the passwd cache code to use talloc_unlink and talloc_reference, to more carefully manage the cache. Andrew Bartlett (This used to be commit e3e0ec25e67308de314aa61852905ee42aa2c8fe) --- source3/smbd/password.c | 64 +++++++++++++++++++------------------------------ source3/smbd/session.c | 4 ++-- 2 files changed, 27 insertions(+), 41 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index bf4e9258ff..b7945bd7ea 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -92,14 +92,7 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; - SAFE_FREE(vuser->homedir); - SAFE_FREE(vuser->unix_homedir); - SAFE_FREE(vuser->logon_script); - session_yield(vuser); - SAFE_FREE(vuser->session_keystr); - - TALLOC_FREE(vuser->server_info); data_blob_free(&vuser->session_key); @@ -109,10 +102,7 @@ void invalidate_vuid(uint16 vuid) from the vuid 'owner' of connections */ conn_clear_vuid_cache(vuid); - SAFE_FREE(vuser->groups); - TALLOC_FREE(vuser->nt_user_token); - - SAFE_FREE(vuser); + TALLOC_FREE(vuser); num_validated_vuids--; } @@ -153,7 +143,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name) { - user_struct *vuser = NULL; + user_struct *vuser; /* Paranoia check. */ if(lp_security() == SEC_SHARE) { @@ -166,14 +156,12 @@ int register_vuid(auth_serversupplied_info *server_info, return UID_FIELD_INVALID; } - if((vuser = SMB_MALLOC_P(user_struct)) == NULL) { - DEBUG(0,("Failed to malloc users struct!\n")); + if((vuser = talloc_zero(NULL, user_struct)) == NULL) { + DEBUG(0,("Failed to talloc users struct!\n")); data_blob_free(&session_key); return UID_FIELD_INVALID; } - ZERO_STRUCTP(vuser); - /* Allocate a free vuid. Yes this is a linear search... :-) */ while( get_valid_user_struct(next_vuid) != NULL ) { next_vuid++; @@ -203,6 +191,11 @@ int register_vuid(auth_serversupplied_info *server_info, return vuser->vuid; } + /* use this to keep tabs on all our info from the authentication */ + vuser->server_info = server_info; + /* Ensure that the server_info will dissapear with the vuser it is now attached to */ + talloc_steal(vuser, vuser->server_info); + /* the next functions should be done by a SID mapping system (SMS) as * the new real sam db won't have reference to unix uids or gids */ @@ -212,14 +205,13 @@ int register_vuid(auth_serversupplied_info *server_info, vuser->n_groups = server_info->n_groups; if (vuser->n_groups) { - if (!(vuser->groups = (gid_t *)memdup(server_info->groups, - sizeof(gid_t) * - vuser->n_groups))) { - DEBUG(0,("register_vuid: failed to memdup " + if (!(vuser->groups = (gid_t *)talloc_memdup(vuser, server_info->groups, + sizeof(gid_t) * + vuser->n_groups))) { + DEBUG(0,("register_vuid: failed to talloc_memdup " "vuser->groups\n")); data_blob_free(&session_key); - free(vuser); - TALLOC_FREE(server_info); + TALLOC_FREE(vuser); return UID_FIELD_INVALID; } } @@ -247,24 +239,26 @@ int register_vuid(auth_serversupplied_info *server_info, const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); if (unix_homedir) { - vuser->unix_homedir = - smb_xstrdup(unix_homedir); + vuser->unix_homedir = unix_homedir; } } else { struct passwd *passwd = - getpwnam_alloc(NULL, vuser->user.unix_name); + getpwnam_alloc(vuser, vuser->user.unix_name); if (passwd) { - vuser->unix_homedir = - smb_xstrdup(passwd->pw_dir); + vuser->unix_homedir = passwd->pw_dir; + /* Ensure that the unix_homedir now + * belongs to vuser, so it goes away + * with it, not with passwd below: */ + talloc_steal(vuser, vuser->unix_homedir); TALLOC_FREE(passwd); } } if (homedir) { - vuser->homedir = smb_xstrdup(homedir); + vuser->homedir = homedir; } if (logon_script) { - vuser->logon_script = smb_xstrdup(logon_script); + vuser->logon_script = logon_script; } } @@ -280,23 +274,15 @@ int register_vuid(auth_serversupplied_info *server_info, vuser->user.full_name)); if (server_info->ptok) { - vuser->nt_user_token = dup_nt_token(NULL, server_info->ptok); + vuser->nt_user_token = dup_nt_token(vuser, server_info->ptok); } else { DEBUG(1, ("server_info does not contain a user_token - " "cannot continue\n")); - TALLOC_FREE(server_info); + TALLOC_FREE(vuser); data_blob_free(&session_key); - SAFE_FREE(vuser->homedir); - SAFE_FREE(vuser->unix_homedir); - SAFE_FREE(vuser->logon_script); - - SAFE_FREE(vuser); return UID_FIELD_INVALID; } - /* use this to keep tabs on all our info from the authentication */ - vuser->server_info = server_info; - DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n", (int)vuser->uid,vuser->user.unix_name, vuser->vuid)); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index a3334a353e..05b1026f41 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -153,9 +153,9 @@ BOOL session_claim(user_struct *vuser) sessionid.id_str, sessionid.id_num); } - vuser->session_keystr = SMB_STRDUP(keystr); + vuser->session_keystr = talloc_strdup(vuser, keystr); if (!vuser->session_keystr) { - DEBUG(0, ("session_claim: strdup() failed for session_keystr\n")); + DEBUG(0, ("session_claim: talloc_strdup() failed for session_keystr\n")); return False; } return True; -- cgit From e5358d6c55cc0aae64447d32611bea4c249f0788 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Apr 2007 19:04:57 +0000 Subject: r22042: Try and clean up my own mess using the API Volker suggested. I now use : BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off) char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off) char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off) int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval) int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval) Volker, please criticize and comment. Thanks, Jeremy. (This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3) --- source3/smbd/lanman.c | 147 ++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 71 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f0e553e231..03411b8dd9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -777,7 +777,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); char *QueueName = p; @@ -800,10 +800,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, if (!p) { return False; } - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; - str3 = get_safe_offset(param,tpscnt,p,4) ? p + 4 : 0; - /* Check if string exists. */ - if (skip_string(param,tpscnt,str3,1) == NULL) { + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); + str3 = get_safe_str_ptr(param,tpscnt,p,4); + if (!str3) { return False; } @@ -905,11 +904,11 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char **rdata, char** rparam, int *rdata_len, int *rparam_len) { - char *param_format = get_safe_offset(param,tpscnt,param,2); + char *param_format = get_safe_str_ptr(param,tpscnt,param,2); char *output_format1 = skip_string(param,tpscnt,param_format,1); char *p = skip_string(param,tpscnt,output_format1,1); - unsigned int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; - char *output_format2 = get_safe_offset(param,tpscnt,p,4); + unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); + char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4); int services = lp_numservices(); int i, n; struct pack_desc desc; @@ -1282,12 +1281,12 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = get_safe_offset(param, tpscnt, param, 2); + char *str1 = get_safe_str_ptr(param, tpscnt, param, 2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); - int uLevel = get_safe_offset(param, tpscnt, p, 2) ? SVAL(p,0) : -1; - int buf_len = get_safe_offset(param,tpscnt, p, 4) ? SVAL(p,2) : 0; - uint32 servertype = get_safe_offset(param,tpscnt,p,8) ? IVAL(p,4) : 0; + int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1); + int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0); + uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0); char *p2; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; @@ -1438,11 +1437,11 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); - int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; - int buf_len = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : 0; + int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); + int buf_len = get_safe_SVAL(param,tpscnt,p,2,0); int counted=0; int missed=0; @@ -1628,11 +1627,11 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *netname = skip_string(param,tpscnt,str2,1); char *p = skip_string(param,tpscnt,netname,1); - int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); int snum; if (!str1 || !str2 || !netname || !p) { @@ -1694,11 +1693,11 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, int *rdata_len, int *rparam_len ) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); - int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; - int buf_len = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : 0; + int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); + int buf_len = get_safe_SVAL(param,tpscnt,p,2,0); char *p2; int count = 0; int total=0,counted=0; @@ -1799,10 +1798,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); - int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); fstring sharename; fstring comment; pstring pathname; @@ -1939,7 +1938,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, int i; int errflags=0; int resume_context, cli_buf_size; - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); @@ -1978,8 +1977,8 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, return False; } - resume_context = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; - cli_buf_size= get_safe_offset(param,tpscnt,p,4) ? SVAL(p+2,0) : 0; + resume_context = get_safe_SVAL(param,tpscnt,p,0,-1); + cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0); DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: " "%d\n", resume_context, cli_buf_size)); @@ -2042,11 +2041,11 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *UserName = skip_string(param,tpscnt,str2,1); char *p = skip_string(param,tpscnt,UserName,1); - int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); const char *level_string; int count=0; struct samu *sampw = NULL; @@ -2188,7 +2187,7 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, struct pdb_search *search; struct samr_displayentry *users; - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); @@ -2206,8 +2205,8 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, * h -> return parameter total number of users */ - resume_context = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; - cli_buf_size= get_safe_offset(param,tpscnt,p,4) ? SVAL(p+2,0) : 0; + resume_context = get_safe_SVAL(param,tpscnt,p,0,-1); + cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0); DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); @@ -2343,7 +2342,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *np = get_safe_offset(param,tpscnt,param,2); + char *np = get_safe_str_ptr(param,tpscnt,param,2); char *p = skip_string(param,tpscnt,np,2); fstring user; fstring pass1,pass2; @@ -2365,7 +2364,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, memset(pass1,'\0',sizeof(pass1)); memset(pass2,'\0',sizeof(pass2)); - if (get_safe_offset(param,tpscnt,p,32) == NULL) { + if (!is_offset_safe(param,tpscnt,p,32)) { return False; } memcpy(pass1,p,16); @@ -2447,7 +2446,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { fstring user; - char *p = get_safe_offset(param,tpscnt,param,2); + char *p = get_safe_str_ptr(param,tpscnt,param,2); *rparam_len = 2; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { @@ -2524,8 +2523,8 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - int function = get_safe_offset(param,tpscnt,param,2) ? SVAL(param,0) : 0; - char *str1 = get_safe_offset(param,tpscnt,param,2); + int function = get_safe_SVAL(param,tpscnt,param,0,0); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); uint32 jobid; @@ -2537,7 +2536,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, if (!str1 || !str2 || !p) { return False; } - if (get_safe_offset(param,tpscnt,p,2) == NULL) { + if (!is_offset_safe(param,tpscnt,p,2)) { return False; } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) @@ -2603,8 +2602,8 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - int function = get_safe_offset(param,tpscnt,param,2) ? SVAL(param,0) : 0; - char *str1 = get_safe_offset(param,tpscnt,param,2); + int function = get_safe_SVAL(param,tpscnt,param,0,0); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *QueueName = skip_string(param,tpscnt,str2,1); int errcode = NERR_notsupported; @@ -2626,6 +2625,9 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, } *rdata_len = 0; + if (skip_string(param,tpscnt,QueueName,1) == NULL) { + return False; + } snum = print_queue_snum(QueueName); if (snum == -1) { @@ -2686,19 +2688,19 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { struct pack_desc desc; - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); uint32 jobid; fstring sharename; - int uLevel = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : -1; - int function = get_safe_offset(param,tpscnt,p,6) ? SVAL(p,4) : -1; + int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1); + int function = get_safe_SVAL(param,tpscnt,p,4,-1); int place, errcode; if (!str1 || !str2 || !p) { return False; } - if (get_safe_offset(param,tpscnt,p,2) == NULL) { + if (!is_offset_safe(param,tpscnt,p,2)) { return False; } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) @@ -2769,10 +2771,10 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); - int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); char *p2; int struct_len; @@ -2910,11 +2912,11 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); char *p2; - int level = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int level = get_safe_SVAL(param,tpscnt,p,0,-1); if (!str1 || !str2 || !p) { return False; @@ -2943,7 +2945,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, SSVAL(*rparam,2,0); /* converter word */ p = *rdata; - p2 = get_safe_offset(*rdata,*rdata_len,p,22); + p2 = get_safe_ptr(*rdata,*rdata_len,p,22); if (!p2) { return False; } @@ -3178,11 +3180,11 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *UserName = skip_string(param,tpscnt,str2,1); char *p = skip_string(param,tpscnt,UserName,1); - int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); char *p2; const char *level_string; @@ -3234,7 +3236,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SSVAL(*rparam,2,0); /* converter word */ p = *rdata; - p2 = get_safe_offset(*rdata,*rdata_len,p,usri11_end); + p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end); if (!p2) { return False; } @@ -3398,7 +3400,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); int uLevel; @@ -3417,11 +3419,11 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, vuser->user.unix_name)); } - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; - if (skip_string(param,tpscnt,p+2,1) == NULL) { + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); + name = get_safe_str_ptr(param,tpscnt,p,2); + if (!name) { return False; } - name = p + 2; memset((char *)&desc,'\0',sizeof(desc)); @@ -3501,7 +3503,7 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *user = skip_string(param,tpscnt,str2,1); char *resource = skip_string(param,tpscnt,user,1); @@ -3510,6 +3512,9 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, return False; } + if (skip_string(param,tpscnt,resource,1) == NULL) { + return False; + } DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); /* check it's a supported varient */ @@ -3543,7 +3548,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); int uLevel; @@ -3561,7 +3566,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, return False; } - uLevel = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : -1; + uLevel = get_safe_SVAL(param,tpscnt,p,2,-1); memset((char *)&desc,'\0',sizeof(desc)); memset((char *)&status,'\0',sizeof(status)); @@ -3642,7 +3647,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); char *name = p; @@ -3665,7 +3670,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, if (!p) { return False; } - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); @@ -3795,7 +3800,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); char* PrinterName = p; @@ -3814,7 +3819,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, if (!p) { return False; } - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); @@ -3875,7 +3880,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); int uLevel; @@ -3890,7 +3895,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, memset((char *)&desc,'\0',sizeof(desc)); - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); @@ -3956,7 +3961,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); int uLevel; @@ -3969,7 +3974,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, memset((char *)&desc,'\0',sizeof(desc)); - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : 0; + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); @@ -4019,7 +4024,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); int uLevel; @@ -4031,7 +4036,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, } memset((char *)&desc,'\0',sizeof(desc)); - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); @@ -4082,7 +4087,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); int uLevel; @@ -4095,7 +4100,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, memset((char *)&desc,'\0',sizeof(desc)); - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); @@ -4152,7 +4157,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { - char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str1 = get_safe_str_ptr(param,tpscnt,param,2); char *str2 = skip_string(param,tpscnt,str1,1); char *p = skip_string(param,tpscnt,str2,1); int uLevel; @@ -4166,7 +4171,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, memset((char *)&desc,'\0',sizeof(desc)); - uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel)); DEBUG(7,("RNetSessionEnum req string=%s\n",str1)); -- cgit From 7371762dae1127117470c436ad0e3521f4bd4a35 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 2 Apr 2007 19:46:27 +0000 Subject: r22043: Comparing lanman.c with -r22013 is now MUCH easier, thanks! This looks much easier to review! Damn close to what I had in my tree, just the fn names were slightly different. This removes one unnecessary dupe. Next thing is to get rid of the parameter "n" of skip_string, there is only one (!) caller that does not pass in 1.... Volker (This used to be commit 2878c1e93a8d71288fa3144cff57bce66c592e22) --- source3/smbd/lanman.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 03411b8dd9..f7fe965430 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -921,9 +921,6 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, return False; } - uLevel = SVAL(p,0); - output_format2 = p + 4; - memset((char *)&desc,'\0',sizeof(desc)); DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); -- cgit From 8990b13d2f576aac2e32cec91c0a70adf8b58539 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 2 Apr 2007 20:04:05 +0000 Subject: r22044: Remove the only skip_string(...,2) caller (This used to be commit 08ea2b83b26968990fce191cdafe26d3183518a6) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f7fe965430..1f38f65f3e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2340,7 +2340,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *np = get_safe_str_ptr(param,tpscnt,param,2); - char *p = skip_string(param,tpscnt,np,2); + char *p = skip_string(param,tpscnt,skip_string(param,tpscnt,np,1),1); fstring user; fstring pass1,pass2; -- cgit From 0a2cc569a1803f459f7db77d03e6e90ae30aa35d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Apr 2007 20:10:21 +0000 Subject: r22045: As Volker noticed, skip_string's last argument is redundent. Remove it. Jeremy. (This used to be commit 140881cfbb59ce4a699b5900efe02bf315be7bd5) --- source3/smbd/lanman.c | 192 ++++++++++++++++++++++++++------------------------ 1 file changed, 98 insertions(+), 94 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 1f38f65f3e..0ef6fe1c47 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -778,8 +778,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); char *QueueName = p; unsigned int uLevel; int count=0; @@ -796,7 +796,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, memset((char *)&status,'\0',sizeof(status)); memset((char *)&desc,'\0',sizeof(desc)); - p = skip_string(param,tpscnt,p,1); + p = skip_string(param,tpscnt,p); if (!p) { return False; } @@ -905,8 +905,8 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, int *rdata_len, int *rparam_len) { char *param_format = get_safe_str_ptr(param,tpscnt,param,2); - char *output_format1 = skip_string(param,tpscnt,param_format,1); - char *p = skip_string(param,tpscnt,output_format1,1); + char *output_format1 = skip_string(param,tpscnt,param_format); + char *p = skip_string(param,tpscnt,output_format1); unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4); int services = lp_numservices(); @@ -1279,8 +1279,8 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char **rparam, int *rdata_len, int *rparam_len) { char *str1 = get_safe_str_ptr(param, tpscnt, param, 2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1); int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0); uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0); @@ -1333,7 +1333,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); if (strcmp(str1, "WrLehDz") == 0) { - if (skip_string(param,tpscnt,p,1) == NULL) { + if (skip_string(param,tpscnt,p) == NULL) { return False; } pull_ascii_fstring(domain, p); @@ -1435,8 +1435,8 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char **rparam, int *rdata_len, int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); int buf_len = get_safe_SVAL(param,tpscnt,p,2,0); int counted=0; @@ -1625,9 +1625,9 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *netname = skip_string(param,tpscnt,str2,1); - char *p = skip_string(param,tpscnt,netname,1); + char *str2 = skip_string(param,tpscnt,str1); + char *netname = skip_string(param,tpscnt,str2); + char *p = skip_string(param,tpscnt,netname); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); int snum; @@ -1691,8 +1691,8 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, int *rparam_len ) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); int buf_len = get_safe_SVAL(param,tpscnt,p,2,0); char *p2; @@ -1796,8 +1796,8 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); fstring sharename; fstring comment; @@ -1823,7 +1823,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, } /* Do we have a string ? */ - if (skip_string(data,mdrcnt,data,1) == NULL) { + if (skip_string(data,mdrcnt,data) == NULL) { return False; } pull_ascii_fstring(sharename,data); @@ -1849,7 +1849,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, } /* Do we have a string ? */ - if (skip_string(data,mdrcnt,data+offset,1) == NULL) { + if (skip_string(data,mdrcnt,data+offset) == NULL) { return False; } pull_ascii_fstring(comment, offset? (data+offset) : ""); @@ -1862,7 +1862,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, } /* Do we have a string ? */ - if (skip_string(data,mdrcnt,data+offset,1) == NULL) { + if (skip_string(data,mdrcnt,data+offset) == NULL) { return False; } pull_ascii_pstring(pathname, offset? (data+offset) : ""); @@ -1936,8 +1936,8 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, int errflags=0; int resume_context, cli_buf_size; char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); struct pdb_search *search; struct samr_displayentry *entries; @@ -2039,9 +2039,9 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *UserName = skip_string(param,tpscnt,str2,1); - char *p = skip_string(param,tpscnt,UserName,1); + char *str2 = skip_string(param,tpscnt,str1); + char *UserName = skip_string(param,tpscnt,str2); + char *p = skip_string(param,tpscnt,UserName); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); const char *level_string; int count=0; @@ -2185,8 +2185,8 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, struct samr_displayentry *users; char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); if (!str1 || !str2 || !p) { return False; @@ -2340,21 +2340,25 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *np = get_safe_str_ptr(param,tpscnt,param,2); - char *p = skip_string(param,tpscnt,skip_string(param,tpscnt,np,1),1); + char *p = NULL; fstring user; fstring pass1,pass2; + /* Skip 2 strings. */ + p = skip_string(param,tpscnt,np); + p = skip_string(param,tpscnt,p); + if (!np || !p) { return False; } /* Do we have a string ? */ - if (skip_string(param,tpscnt,p,1) == NULL) { + if (skip_string(param,tpscnt,p) == NULL) { return False; } pull_ascii_fstring(user,p); - p = skip_string(param,tpscnt,p,1); + p = skip_string(param,tpscnt,p); if (!p) { return False; } @@ -2462,32 +2466,32 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, */ /* Do we have a string ? */ - if (skip_string(param,tpscnt,p,1) == 0) { + if (skip_string(param,tpscnt,p) == 0) { return False; } if(!strequal(p, "zsT")) { DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p)); return False; } - p = skip_string(param, tpscnt, p, 1); + p = skip_string(param, tpscnt, p); if (!p) { return False; } /* Do we have a string ? */ - if (skip_string(param,tpscnt,p,1) == 0) { + if (skip_string(param,tpscnt,p) == 0) { return False; } if(!strequal(p, "B516B16")) { DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); return False; } - p = skip_string(param,tpscnt,p,1); + p = skip_string(param,tpscnt,p); if (!p) { return False; } /* Do we have a string ? */ - if (skip_string(param,tpscnt,p,1) == 0) { + if (skip_string(param,tpscnt,p) == 0) { return False; } p += pull_ascii_fstring(user,p); @@ -2522,8 +2526,8 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, { int function = get_safe_SVAL(param,tpscnt,param,0,0); char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); uint32 jobid; int snum; fstring sharename; @@ -2601,8 +2605,8 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, { int function = get_safe_SVAL(param,tpscnt,param,0,0); char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *QueueName = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *QueueName = skip_string(param,tpscnt,str2); int errcode = NERR_notsupported; int snum; WERROR werr = WERR_OK; @@ -2622,7 +2626,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, } *rdata_len = 0; - if (skip_string(param,tpscnt,QueueName,1) == NULL) { + if (skip_string(param,tpscnt,QueueName) == NULL) { return False; } snum = print_queue_snum(QueueName); @@ -2686,8 +2690,8 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, { struct pack_desc desc; char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); uint32 jobid; fstring sharename; int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1); @@ -2769,8 +2773,8 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); char *p2; int struct_len; @@ -2873,7 +2877,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, current_user_info.domain, comment, sizeof(comment)); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -2910,8 +2914,8 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); char *p2; int level = get_safe_SVAL(param,tpscnt,p,0,-1); @@ -2950,7 +2954,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ pstrcpy(p2,get_local_machine_name()); strupper_m(p2); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -2958,7 +2962,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, SIVAL(p,0,PTR_DIFF(p2,*rdata)); pstrcpy(p2,current_user_info.smb_name); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -2967,7 +2971,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ pstrcpy(p2,lp_workgroup()); strupper_m(p2); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -2979,7 +2983,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, SIVAL(p,0,PTR_DIFF(p2,*rdata)); pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */ - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -2987,7 +2991,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ pstrcpy(p2,""); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3178,9 +3182,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *UserName = skip_string(param,tpscnt,str2,1); - char *p = skip_string(param,tpscnt,UserName,1); + char *str2 = skip_string(param,tpscnt,str1); + char *UserName = skip_string(param,tpscnt,str2); + char *p = skip_string(param,tpscnt,UserName); int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); char *p2; const char *level_string; @@ -3249,14 +3253,14 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, if (uLevel >= 10) { SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ pstrcpy(p2,"Comment"); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ pstrcpy(p2,"UserComment"); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3264,7 +3268,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3277,13 +3281,13 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3293,7 +3297,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SSVALS(p,usri11_num_logons,-1); /* num logons */ SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ pstrcpy(p2,"\\\\*"); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3301,7 +3305,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ pstrcpy(p2,""); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3313,7 +3317,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, /* a simple way to get logon hours at all times. */ memset(p2,0xff,21); SCVAL(p2,21,0); /* fix zero termination */ - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3328,7 +3332,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3337,7 +3341,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3345,14 +3349,14 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ pstrcpy(p2,""); - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3374,7 +3378,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, standard_sub_basic("", "", tmp, sizeof(tmp)); pstrcpy(p2, tmp); } - p2 = skip_string(*rdata,*rdata_len,p2,1); + p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } @@ -3398,8 +3402,8 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel; struct pack_desc desc; char* name; @@ -3501,15 +3505,15 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *user = skip_string(param,tpscnt,str2,1); - char *resource = skip_string(param,tpscnt,user,1); + char *str2 = skip_string(param,tpscnt,str1); + char *user = skip_string(param,tpscnt,str2); + char *resource = skip_string(param,tpscnt,user); if (!str1 || !str2 || !user || !resource) { return False; } - if (skip_string(param,tpscnt,resource,1) == NULL) { + if (skip_string(param,tpscnt,resource) == NULL) { return False; } DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); @@ -3546,8 +3550,8 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel; int count; int i; @@ -3645,8 +3649,8 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); char *name = p; int uLevel; int count; @@ -3663,7 +3667,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, memset((char *)&desc,'\0',sizeof(desc)); memset((char *)&status,'\0',sizeof(status)); - p = skip_string(param,tpscnt,p,1); + p = skip_string(param,tpscnt,p); if (!p) { return False; } @@ -3798,8 +3802,8 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); char* PrinterName = p; int uLevel; struct pack_desc desc; @@ -3812,7 +3816,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, memset((char *)&desc,'\0',sizeof(desc)); - p = skip_string(param,tpscnt,p,1); + p = skip_string(param,tpscnt,p); if (!p) { return False; } @@ -3878,8 +3882,8 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel; int queuecnt; int i, n, succnt=0; @@ -3959,8 +3963,8 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel; int succnt; struct pack_desc desc; @@ -4022,8 +4026,8 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel; int succnt; struct pack_desc desc; @@ -4085,8 +4089,8 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, int *rdata_len,int *rparam_len) { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel; int succnt; struct pack_desc desc; @@ -4155,8 +4159,8 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, { char *str1 = get_safe_str_ptr(param,tpscnt,param,2); - char *str2 = skip_string(param,tpscnt,str1,1); - char *p = skip_string(param,tpscnt,str2,1); + char *str2 = skip_string(param,tpscnt,str1); + char *p = skip_string(param,tpscnt,str2); int uLevel; struct pack_desc desc; struct sessionid *session_list; @@ -4355,12 +4359,12 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * } api_command = SVAL(params,0); /* Is there a string at position params+2 ? */ - if (skip_string(params,tpscnt,params+2,1)) { + if (skip_string(params,tpscnt,params+2)) { name1 = params + 2; } else { name1 = ""; } - name2 = skip_string(params,tpscnt,params+2,1); + name2 = skip_string(params,tpscnt,params+2); if (!name2) { name2 = ""; } -- cgit From afd637e926c70f9ca88d8e85ea2c684032962bc9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Apr 2007 04:52:09 +0000 Subject: r22050: Fix a couple of off-by-one errors in the rap call patch. Jerry, this works now for displaying shares on Win9x (and hopefully everything else as well :-). Jeremy. (This used to be commit 728a4cc71376f9cfff2578d21a47602f8b7c6531) --- source3/smbd/lanman.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0ef6fe1c47..4ca9a4b051 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2365,7 +2365,11 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, memset(pass1,'\0',sizeof(pass1)); memset(pass2,'\0',sizeof(pass2)); - if (!is_offset_safe(param,tpscnt,p,32)) { + /* + * We use 31 here not 32 as we're checking + * the last byte we want to access is safe. + */ + if (!is_offset_safe(param,tpscnt,p,31)) { return False; } memcpy(pass1,p,16); @@ -2537,7 +2541,11 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, if (!str1 || !str2 || !p) { return False; } - if (!is_offset_safe(param,tpscnt,p,2)) { + /* + * We use 1 here not 2 as we're checking + * the last byte we want to access is safe. + */ + if (!is_offset_safe(param,tpscnt,p,1)) { return False; } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) @@ -2701,7 +2709,11 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, if (!str1 || !str2 || !p) { return False; } - if (!is_offset_safe(param,tpscnt,p,2)) { + /* + * We use 1 here not 2 as we're checking + * the last byte we want to access is safe. + */ + if (!is_offset_safe(param,tpscnt,p,1)) { return False; } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) -- cgit From 2498a973acba0d7500a7cd6501928161bc0ed31b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 3 Apr 2007 14:16:56 +0000 Subject: r22059: Over-allocate and NULL out 100 bytes for lanman.c. Volker (This used to be commit 0eea6b84cec7e2a3fc1f784d5a9b162f71cc8a02) --- source3/smbd/ipc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ca128d29d9..6e5ff9f035 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -478,8 +478,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, if (state->total_data) { /* Can't use talloc here, the core routines do realloc on the - * params and data. */ - state->data = (char *)SMB_MALLOC(state->total_data); + * params and data. Out of paranoia, 100 bytes too many. */ + state->data = (char *)SMB_MALLOC(state->total_data+100); if (state->data == NULL) { DEBUG(0,("reply_trans: data malloc fail for %u " "bytes !\n", (unsigned int)state->total_data)); @@ -487,6 +487,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } + /* null-terminate the slack space */ + memset(&state->data[state->total_data], 0, 100); if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || @@ -498,8 +500,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, if (state->total_param) { /* Can't use talloc here, the core routines do realloc on the - * params and data. */ - state->param = (char *)SMB_MALLOC(state->total_param); + * params and data. Out of paranoia, 100 bytes too many */ + state->param = (char *)SMB_MALLOC(state->total_param+100); if (state->param == NULL) { DEBUG(0,("reply_trans: param malloc fail for %u " "bytes !\n", (unsigned int)state->total_param)); @@ -508,6 +510,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); } + /* null-terminate the slack space */ + memset(&state->param[state->total_param], 0, 100); if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || -- cgit From 9b807d4f87d80e542bf8209d4ea4b6c09a953470 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Apr 2007 17:10:52 +0000 Subject: r22060: Fix for AIX quotas from Heinrich Mislik . Jeremy. (This used to be commit 8d95cdf8c0a46abc6b5cbcec3fd8bf246d49ee4b) --- source3/smbd/quotas.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index bb88957731..0492130950 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -936,6 +936,10 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #define dqb_curfiles dqb_curinodes #define dqb_fhardlimit dqb_ihardlimit #define dqb_fsoftlimit dqb_isoftlimit +#ifdef _AIXVERSION_530 +#include +#include +#endif /* AIX 5.3 */ #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ #include #include @@ -1205,11 +1209,37 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #elif defined(AIX) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ +#ifdef _AIXVERSION_530 + { + struct statfs statbuf; + quota64_t user_quota; + if (statfs(path,&statbuf) != 0) + return False; + if(statbuf.f_vfstype == MNT_J2) + { + /* For some reason we need to be root for jfs2 */ + become_root_uid_only(); + r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota); + unbecome_root_uid_only(); + /* Copy results to old struct to let the following code work as before */ + D.dqb_curblocks = user_quota.bused; + D.dqb_bsoftlimit = user_quota.bsoft; + D.dqb_bhardlimit = user_quota.bhard; + } + else if(statbuf.f_vfstype == MNT_JFS) + { +#endif /* AIX 5.3 */ save_re_uid(); if (set_re_uid() != 0) return False; r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); restore_re_uid(); +#ifdef _AIXVERSION_530 + } + else + r = 1; /* Fail for other FS-types */ + } +#endif /* AIX 5.3 */ #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ -- cgit From cab91684e51356215a4c764e1673e4fd8420b8e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Apr 2007 22:59:55 +0000 Subject: r22064: Fix the DFS code to work better with Vista clients. Allow "host msdfs = true" to be set in the [global] section and allow Vista to see shares with "msdfs root = yes" and "msdfs root = no" off the same server. Down to an error message really :-). Jeremy. (This used to be commit 1a0f69bb21fd03a18514dfc93c84568708144e28) --- source3/smbd/msdfs.c | 68 +++++++++++++++++++++++++++------------------------ source3/smbd/trans2.c | 5 ++-- 2 files changed, 39 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 397d43b8bb..effe868657 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -170,7 +170,7 @@ static NTSTATUS parse_dfs_path(const char *pathname, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static BOOL create_conn_struct(connection_struct *conn, int snum, const char *path) +static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char *path) { pstring connpath; @@ -183,12 +183,12 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return False; + return NT_STATUS_NO_MEMORY; } if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); - return False; + return NT_STATUS_NO_MEMORY; } conn->params->service = snum; @@ -196,9 +196,10 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { + NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); conn_free_internal(conn); - return False; + return status; } /* @@ -208,13 +209,14 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa */ if (vfs_ChDir(conn,conn->connectpath) != 0) { + NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", conn->connectpath, strerror(errno) )); conn_free_internal(conn); - return False; + return status; } - return True; + return NT_STATUS_OK; } /********************************************************************** @@ -542,7 +544,7 @@ static NTSTATUS dfs_redirect( connection_struct *conn, Return a self referral. **********************************************************************/ -static BOOL self_ref(TALLOC_CTX *ctx, +static NTSTATUS self_ref(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, @@ -555,7 +557,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, jucn->referral_count = 1; if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { DEBUG(0,("self_ref: talloc failed for referral\n")); - return False; + return NT_STATUS_NO_MEMORY; } pstrcpy(ref->alternate_path,dfs_path); @@ -563,7 +565,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; *consumedcntp = strlen(dfs_path); - return True; + return NT_STATUS_OK; } /********************************************************************** @@ -571,7 +573,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, junction_map structure. **********************************************************************/ -BOOL get_referred_path(TALLOC_CTX *ctx, +NTSTATUS get_referred_path(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, @@ -583,8 +585,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, pstring conn_path; pstring targetpath; int snum; - NTSTATUS status; - BOOL ret = False; + NTSTATUS status = NT_STATUS_NOT_FOUND; BOOL dummy; ZERO_STRUCT(conns); @@ -593,14 +594,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx, status = parse_dfs_path(dfs_path, False, &dp, &dummy); if (!NT_STATUS_IS_OK(status)) { - return False; + return status; } /* Verify hostname in path */ if (!is_myname_or_ipaddr(dp.hostname)) { DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", dp.hostname, dfs_path)); - return False; + return NT_STATUS_NOT_FOUND; } fstrcpy(jucn->service_name, dp.servicename); @@ -610,14 +611,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx, snum = lp_servicenumber(jucn->service_name); if(snum < 0) { if ((snum = find_service(jucn->service_name)) < 0) { - return False; + return NT_STATUS_NOT_FOUND; } } if (!lp_msdfs_root(snum)) { DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n", dp.servicename, dfs_path)); - goto out; + return NT_STATUS_NOT_FOUND; } /* @@ -646,7 +647,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, jucn->referral_count = 1; if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); - goto out; + return NT_STATUS_NO_MEMORY; } pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); @@ -657,13 +658,13 @@ BOOL get_referred_path(TALLOC_CTX *ctx, ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; *consumedcntp = strlen(dfs_path); - ret = True; - goto out; + return NT_STATUS_OK; } pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) { - return False; + status = create_conn_struct(conn, snum, conn_path); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* If this is a DFS path dfs_lookup should return @@ -675,7 +676,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx, if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); - goto out; + conn_free_internal(conn); + return status; } /* We know this is a valid dfs link. Parse the targetpath. */ @@ -684,15 +686,12 @@ BOOL get_referred_path(TALLOC_CTX *ctx, &jucn->referral_count)) { DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); - goto out; + conn_free_internal(conn); + return NT_STATUS_NOT_FOUND; } - ret = True; - -out: - conn_free_internal(conn); - return ret; + return NT_STATUS_OK; } static int setup_ver2_dfs_referral(const char *pathname, @@ -890,7 +889,7 @@ static int setup_ver3_dfs_referral(const char *pathname, int setup_dfs_referral(connection_struct *orig_conn, const char *dfs_path, int max_referral_level, - char **ppdata) + char **ppdata, NTSTATUS *pstatus) { struct junction_map junction; int consumedcnt = 0; @@ -901,6 +900,7 @@ int setup_dfs_referral(connection_struct *orig_conn, TALLOC_CTX *ctx; if (!(ctx=talloc_init("setup_dfs_referral"))) { + *pstatus = NT_STATUS_NO_MEMORY; return -1; } @@ -909,6 +909,7 @@ int setup_dfs_referral(connection_struct *orig_conn, /* get the junction entry */ if (!dfs_path) { talloc_destroy(ctx); + *pstatus = NT_STATUS_NOT_FOUND; return -1; } @@ -924,7 +925,8 @@ int setup_dfs_referral(connection_struct *orig_conn, } /* The following call can change cwd. */ - if (!get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral)) { + *pstatus = get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral); + if (!NT_STATUS_IS_OK(*pstatus)) { vfs_ChDir(orig_conn,orig_conn->connectpath); talloc_destroy(ctx); return -1; @@ -965,6 +967,7 @@ int setup_dfs_referral(connection_struct *orig_conn, default: DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); talloc_destroy(ctx); + *pstatus = NT_STATUS_INVALID_LEVEL; return -1; } @@ -974,6 +977,7 @@ int setup_dfs_referral(connection_struct *orig_conn, } talloc_destroy(ctx); + *pstatus = NT_STATUS_OK; return reply_size; } @@ -1041,7 +1045,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn, safe_strcat(path, jucn->volume_name, max_pathlen-1); pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn_out, snum, conn_path)) { + if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, conn_path))) { return False; } @@ -1160,7 +1164,7 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!create_conn_struct(&conn, snum, connect_path)) { + if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { return 0; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dfba188b74..04969784c0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6214,6 +6214,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* pstring pathname; int reply_size = 0; int max_referral_level; + NTSTATUS status = NT_STATUS_OK; DEBUG(10,("call_trans2getdfsreferral\n")); @@ -6227,8 +6228,8 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* return ERROR_DOS(ERRDOS,ERRbadfunc); srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE); - if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0) - return UNIXERROR(ERRDOS,ERRbadfile); + if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0) + return ERROR_NT(status); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes); -- cgit From 97e3cb896f284ba5330ad834a821a3a227e9abe4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Apr 2007 00:03:12 +0000 Subject: r22065: First logic change I've found :-(. We were being too restrictive about strings being NULL. If an info level doesn't use a subformat the subformat string may be missing (null). Add debug statements to help track this. Jeremy (This used to be commit 70875f92a22985539dc41e26a084218a45e1a13f) --- source3/smbd/lanman.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4ca9a4b051..15e0284521 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -441,12 +441,18 @@ static int check_printq_info(struct pack_desc* desc, desc->subformat = "z"; break; default: + DEBUG(0,("check_printq_info: invalid level %d\n", + uLevel )); return False; } - if (strcmp(desc->format,id1) != 0) { + if (id1 == NULL || strcmp(desc->format,id1) != 0) { + DEBUG(0,("check_printq_info: invalid format %s\n", + id1 ? id1 : "" )); return False; } - if (desc->subformat && strcmp(desc->subformat,id2) != 0) { + if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) { + DEBUG(0,("check_printq_info: invalid subformat %s\n", + id2 ? id2 : "" )); return False; } return True; @@ -802,9 +808,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, } uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); str3 = get_safe_str_ptr(param,tpscnt,p,4); - if (!str3) { - return False; - } + /* str3 may be null here and is checked in check_printq_info(). */ /* remove any trailing username */ if ((p = strchr_m(QueueName,'%'))) @@ -917,7 +921,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, int *subcntarr = NULL; int queuecnt = 0, subcnt = 0, succnt = 0; - if (!param_format || !output_format1 || !p || !output_format2) { + if (!param_format || !output_format1 || !p) { return False; } @@ -2683,9 +2687,16 @@ static int check_printjob_info(struct pack_desc* desc, case 2: desc->format = "WWzWWDDzz"; break; case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break; - default: return False; + default: + DEBUG(0,("check_printjob_info: invalid level %d\n", + uLevel )); + return False; + } + if (id == NULL || strcmp(desc->format,id) != 0) { + DEBUG(0,("check_printjob_info: invalid format %s\n", + id ? id : "" )); + return False; } - if (strcmp(desc->format,id) != 0) return False; return True; } @@ -3762,9 +3773,13 @@ static int check_printdest_info(struct pack_desc* desc, desc->format = "zzzWWzzzWW"; break; default: + DEBUG(0,("check_printdest_info: invalid level %d\n", + uLevel)); return False; } - if (strcmp(desc->format,id) != 0) { + if (id == NULL || strcmp(desc->format,id) != 0) { + DEBUG(0,("check_printdest_info: invalid string %s\n", + id ? id : "" )); return False; } return True; -- cgit From 90dc2613153bb8c865a1cfda0318ae4db3cf212e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 5 Apr 2007 19:56:08 +0000 Subject: r22095: BUG 4484: Add more checks to set %a for Vista clients (based on absence of native OS and Lanman strings in the session setup request) (This used to be commit e5c9fc937d40046030c0d3bcfced505410a14caf) --- source3/smbd/sesssetup.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 91f4a9e12f..7b5528222e 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1060,6 +1060,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, native_os, native_lanman, primary_domain)); if ( ra_type == RA_WIN2K ) { + /* Vista sets neither the OS or lanman strings */ + + if ( !strlen(native_os) && !strlen(native_lanman) ) + set_remote_arch(RA_VISTA); + /* Windows 2003 doesn't set the native lanman string, but does set primary domain which is a bug I think */ -- cgit From bc45c82904e268327bfbf72cd3f35699ae6e7397 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Apr 2007 23:56:10 +0000 Subject: r22096: become_root_uid_only() is unneeded - it's only used in messages.c. Refactor to use become_root() instead and make it local to messages.c Jeremy. (This used to be commit f3ffb3f98472b69b476b702dfe5c0575b32da018) --- source3/smbd/quotas.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 0492130950..ddfcb8e0f8 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -238,7 +238,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if (!found) return(False); - become_root_uid_only(); + become_root(); if (strcmp(mnt->mnt_type, "xfs")==0) { r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); @@ -251,7 +251,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB } } - unbecome_root_uid_only(); + unbecome_root(); /* Use softlimit to determine disk space, except when it has been exceeded */ *bsize = D.bsize; @@ -655,20 +655,20 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if ( ! found ) return(False) ; - become_root_uid_only(); + become_root(); #if defined(SUNOS5) if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) { BOOL retval; DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); - unbecome_root_uid_only(); + unbecome(); return retval; } DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); if((file=sys_open(name, O_RDONLY,0))<0) { - unbecome_root_uid_only(); + unbecome_root(); return(False); } command.op = Q_GETQUOTA; @@ -681,7 +681,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB ret = quotactl(Q_GETQUOTA, name, euser_id, &D); #endif - unbecome_root_uid_only(); + unbecome_root(); if (ret < 0) { DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); @@ -841,7 +841,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB } euser_id=geteuid(); - become_root_uid_only(); + become_root(); /* Use softlimit to determine disk space, except when it has been exceeded */ @@ -851,7 +851,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB { r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); - unbecome_root_uid_only(); + unbecome_root(); if (r==-1) return(False); @@ -882,7 +882,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB { r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); - unbecome_root_uid_only(); + unbecome_root(); if (r==-1) { @@ -916,7 +916,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB } else { - unbecome_root_uid_only(); + unbecome_root(); return(False); } @@ -1184,13 +1184,13 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB return False; #endif - become_root_uid_only(); + become_root(); #if defined(__FreeBSD__) || defined(__DragonFly__) if (strcmp(mnts[i].f_fstypename,"nfs") == 0) { BOOL retval; retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize); - unbecome_root_uid_only(); + unbecome_root(); return retval; } #endif @@ -1204,7 +1204,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); } - unbecome_root_uid_only(); + unbecome_root(); } #elif defined(AIX) /* AIX has both USER and GROUP quotas: @@ -1218,9 +1218,9 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if(statbuf.f_vfstype == MNT_J2) { /* For some reason we need to be root for jfs2 */ - become_root_uid_only(); + become_root(); r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota); - unbecome_root_uid_only(); + unbecome_root(); /* Copy results to old struct to let the following code work as before */ D.dqb_curblocks = user_quota.bused; D.dqb_bsoftlimit = user_quota.bsoft; -- cgit From bca29ddbba62320204ac9eb098cdaac9a6b03d80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 7 Apr 2007 05:49:24 +0000 Subject: r22122: Start to fix csc issue with Vista. Make smbd support the extended 7 word response for tconX rather than the 3 word one we supported previously. Jeremy. (This used to be commit 137953226a2d691259e7e84d6ae0dc24755e5a3a) --- source3/smbd/reply.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5be086f749..d7b3a0fab1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -452,6 +452,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int passlen = SVAL(inbuf,smb_vwv3); pstring path; char *p, *q; + uint16 tcon_flags = SVAL(inbuf,smb_vwv2); START_PROFILE(SMBtconX); @@ -522,7 +523,27 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* NT sets the fstype of IPC$ to the null string */ const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); - set_message(outbuf,3,0,True); + if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) { + /* Return permissions. */ + uint32 perm1 = 0; + uint32 perm2 = 0; + + set_message(outbuf,7,0,True); + + if (IS_IPC(conn)) { + perm1 = FILE_ALL_ACCESS; + perm2 = FILE_ALL_ACCESS; + } else { + perm1 = CAN_WRITE(conn) ? + SHARE_ALL_ACCESS : + SHARE_READ_ONLY; + } + + SIVAL(outbuf, smb_vwv3, perm1); + SIVAL(outbuf, smb_vwv5, perm2); + } else { + set_message(outbuf,3,0,True); + } p = smb_buf(outbuf); p += srvstr_push(outbuf, p, server_devicetype, -1, -- cgit From bd472a542acab7b16c0dd8e0b017b9dd6fc96ad2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 7 Apr 2007 06:38:45 +0000 Subject: r22123: Try and fix the csc (#4404) bug by supporting the extended response to NTCreateX - need to fix this also for pipe open and NTTransCreate as well so this isn't finished. Jeremy. (This used to be commit be742f248178ae606dfa3a90c6148a18b42128e3) --- source3/smbd/nttrans.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 51ed081edb..9094519b3e 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -847,13 +847,12 @@ int reply_ntcreate_and_X(connection_struct *conn, extended_oplock_granted = True; } -#if 0 - /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */ - set_message(outbuf,42,0,True); -#else - set_message(outbuf,34,0,True); -#endif - + if (flags & EXTENDED_RESPONSE_REQUIRED) { + set_message(outbuf,42,0,True); + } else { + set_message(outbuf,34,0,True); + } + p = outbuf + smb_vwv2; /* @@ -914,6 +913,18 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); + /* Fixme - we must do the same for NTTransCreate and pipe open. */ + if (flags & EXTENDED_RESPONSE_REQUIRED) { + uint32 perms = 0; + p += 26; + if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) { + perms = FILE_GENERIC_ALL; + } else { + perms = FILE_GENERIC_READ|FILE_EXECUTE; + } + SIVAL(p,0,perms); + } + DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); result = chain_reply(inbuf,outbuf,length,bufsize); -- cgit From 8710c0ddd2e689aa2191ad5083858b0fc4324bac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 7 Apr 2007 06:59:32 +0000 Subject: r22124: Wow - NTCreateX sets the word count to 42, but returns 50 on the wire. Strange.... But now we're returning Windows compatible extended info. Next to fix the pipe returns and NTTrans Creates. Jeremy. (This used to be commit 57e46f2f80db153fc7ce0eb09f24afa78aa27349) --- source3/smbd/nttrans.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9094519b3e..0618a938e7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -848,7 +848,13 @@ int reply_ntcreate_and_X(connection_struct *conn, } if (flags & EXTENDED_RESPONSE_REQUIRED) { - set_message(outbuf,42,0,True); + /* This is very strange. We + * return 50 words, but only set + * the wcnt to 42 ? It's definately + * what happens on the wire.... + */ + set_message(outbuf,50,0,True); + SCVAL(outbuf,smb_wct,42); } else { set_message(outbuf,34,0,True); } -- cgit From 2ca369e0a66b30cc0df9740a699b912bb652b930 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 8 Apr 2007 00:47:49 +0000 Subject: r22128: Fix the pipe open response with EXTENDED_RESPONSE_REQUIRED set. Only the NTTrans create left to fix for csc. Jeremy. (This used to be commit 7856db9fce9906c5a7d19fbe69dfcfd4b644c134) --- source3/smbd/nttrans.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0618a938e7..fa9e89d097 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -374,6 +374,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, int ret; int pnum = -1; char *p = NULL; + uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); @@ -385,7 +386,17 @@ static int do_ntcreate_pipe_open(connection_struct *conn, * Deal with pipe return. */ - set_message(outbuf,34,0,True); + if (flags & EXTENDED_RESPONSE_REQUIRED) { + /* This is very strange. We + * return 50 words, but only set + * the wcnt to 42 ? It's definately + * what happens on the wire.... + */ + set_message(outbuf,50,0,True); + SCVAL(outbuf,smb_wct,42); + } else { + set_message(outbuf,34,0,True); + } p = outbuf + smb_vwv2; p++; @@ -400,6 +411,18 @@ static int do_ntcreate_pipe_open(connection_struct *conn, SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); /* Device state. */ SSVAL(p,2, 0x5FF); /* ? */ + p += 4; + + if (flags & EXTENDED_RESPONSE_REQUIRED) { + p += 26; + SIVAL(p,0,FILE_GENERIC_ALL); + /* + * For pipes W2K3 seems to return + * 0x12019B next. + * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA) + */ + SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA); + } DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname)); -- cgit From 6a3e72aa69b9b2e77da86369a25d63773b14669f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 8 Apr 2007 04:54:44 +0000 Subject: r22129: Fix the nttrans create extended response for pipes and files (tested with Win32 code). Bug #4404 should now be dead :-). Jeremy. (This used to be commit 40a86a56662eca2668b8a9515b9f924f54d80cc0) --- source3/smbd/nttrans.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fa9e89d097..94de1c709c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -942,7 +942,6 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); - /* Fixme - we must do the same for NTTransCreate and pipe open. */ if (flags & EXTENDED_RESPONSE_REQUIRED) { uint32 perms = 0; p += 26; @@ -976,6 +975,8 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha int pnum = -1; char *p = NULL; NTSTATUS status; + size_t param_len; + uint32 flags; /* * Ensure minimum number of parameters sent. @@ -986,6 +987,8 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha return ERROR_DOS(ERRDOS,ERRnoaccess); } + flags = IVAL(params,0); + srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); @@ -996,7 +999,13 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha } /* Realloc the size of parameters and data we will return */ - params = nttrans_realloc(ppparams, 69); + if (flags & EXTENDED_RESPONSE_REQUIRED) { + /* Extended response is 32 more byyes. */ + param_len = 101; + } else { + param_len = 69; + } + params = nttrans_realloc(ppparams, param_len); if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); } @@ -1017,11 +1026,23 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); /* Device state. */ SSVAL(p,2, 0x5FF); /* ? */ + p += 4; + if (flags & EXTENDED_RESPONSE_REQUIRED) { + p += 26; + SIVAL(p,0,FILE_GENERIC_ALL); + /* + * For pipes W2K3 seems to return + * 0x12019B next. + * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA) + */ + SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA); + } + DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); return -1; } @@ -1166,6 +1187,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o TALLOC_CTX *ctx = NULL; char *pdata = NULL; NTSTATUS status; + size_t param_len; DEBUG(5,("call_nt_transact_create\n")); @@ -1536,7 +1558,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } /* Realloc the size of parameters and data we will return */ - params = nttrans_realloc(ppparams, 69); + if (flags & EXTENDED_RESPONSE_REQUIRED) { + /* Extended response is 32 more byyes. */ + param_len = 101; + } else { + param_len = 69; + } + params = nttrans_realloc(ppparams, param_len); if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); } @@ -1595,10 +1623,21 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); + if (flags & EXTENDED_RESPONSE_REQUIRED) { + uint32 perms = 0; + p += 26; + if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) { + perms = FILE_GENERIC_ALL; + } else { + perms = FILE_GENERIC_READ|FILE_EXECUTE; + } + SIVAL(p,0,perms); + } + DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); + send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); return -1; } -- cgit From 4838055e5f300ec5c9e09ac5ebb9d661fa9a7cd1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 8 Apr 2007 19:41:47 +0000 Subject: r22132: I hate inefficiency. Don't call conv_str_size() on every pread/sendfile call, initialize these variables in an allocated struct at connection time and just refer to them directly. Jeremy. (This used to be commit 85df3fca681a44c882f596ef042ad9956c3a63c0) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 82ea602187..0803ffb7e7 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -174,7 +174,7 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { /* If this operation was already made opaque by different module, it - * will be overridded here. + * will be overridden here. */ DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op); -- cgit From a0987247347e473e4802f9267773b0bff68f0187 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Apr 2007 21:01:46 +0000 Subject: r22145: Fix bug #4494 - reported by Kevin Jamieson . If returning a mapped UNIX error from sendfile, don't call chain_reply. Jeremy. (This used to be commit 38404c990db1436241c3a774c51196bc058d7576) --- source3/smbd/process.c | 4 ++-- source3/smbd/reply.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 59ad96d880..c5db007525 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1161,8 +1161,8 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) char outbuf_saved[smb_wct]; int outsize = smb_len(outbuf) + 4; - /* maybe its not chained */ - if (smb_com2 == 0xFF) { + /* Maybe its not chained, or it's an error packet. */ + if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) { SCVAL(outbuf,smb_vwv0,0xFF); return outsize; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d7b3a0fab1..eb4106b0c1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2706,8 +2706,10 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); - if (nread != -1) + /* Only call chain_reply if not an error. */ + if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) { nread = chain_reply(inbuf,outbuf,length,bufsize); + } END_PROFILE(SMBreadX); return nread; -- cgit From 1790c67780af0bcc4bc1df3f015fa6fcb7e55f95 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 10 Apr 2007 15:41:23 +0000 Subject: r22149: BUG 4500: patch from Jorge Santos to fix compile bug ni quotas.c (typo calling unbecome_root()). (This used to be commit 22d550d62b5834e2c5155550756d3462a1bd6561) --- source3/smbd/quotas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index ddfcb8e0f8..feb28e2c74 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -662,7 +662,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB BOOL retval; DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); - unbecome(); + unbecome_root(); return retval; } -- cgit From a633b42592080982b38f5e3cde8d32bf2fd80e7e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 14 Apr 2007 06:40:47 +0000 Subject: r22213: We can't use become_root() here, as it does DEBUG() itself. become_root_uid_only did not :-) Revert 21868, we need to find a better way. Volker (This used to be commit 629f966714c7a8d96b06027d514b86cde81b69b9) --- source3/smbd/process.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c5db007525..6f3ad9884c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1406,6 +1406,13 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); update_monitored_printq_cache(); + /* + * Now we are root, check if the log files need pruning. + * Force a log file check. + */ + force_check_log_size(); + check_log_size(); + /* Send any queued printer notify message to interested smbd's. */ print_notify_send_messages(0); -- cgit From 3678d69b82a109218211d6abc89cef9c460d3b45 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Apr 2007 12:00:08 +0000 Subject: r22262: fix the build on systems without GSS_C_NT_HOSTBASED_SERVICE metze (This used to be commit 402704b62972c223f3e70bcd6221dc7c3a64f4b9) --- source3/smbd/seal.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 66ae8419d4..259aff014a 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -103,6 +103,9 @@ static NTSTATUS get_srv_gss_creds(const char *service, char *host_princ_s = NULL; NTSTATUS status = NT_STATUS_OK; + gss_OID_desc nt_hostbased_service = + {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; + asprintf(&host_princ_s, "%s@%s", service, name); if (host_princ_s == NULL) { return NT_STATUS_NO_MEMORY; @@ -113,7 +116,7 @@ static NTSTATUS get_srv_gss_creds(const char *service, ret = gss_import_name(&min, &input_name, - GSS_C_NT_HOSTBASED_SERVICE, + &nt_hostbased_service, &srv_name); if (ret != GSS_S_COMPLETE) { -- cgit From 74a07edb505c9f20a93c00da06cb5c997b6b3c8a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Apr 2007 19:10:16 +0000 Subject: r22266: Fix bug #4512 - we were returning a volume label greater than 32 unicode chars. Windows XP doesn't like that :-). Jeremy (This used to be commit e59b5276b56d6963ddd0598bbd1b15426d2d13e8) --- source3/smbd/connection.c | 8 ++++---- source3/smbd/trans2.c | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 7e53a29b04..5c31a5460b 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -108,13 +108,13 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) { DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", - procid_str_static(&crec.pid), crec.cnum, crec.name)); + procid_str_static(&crec.pid), crec.cnum, crec.servicename)); if (tdb_delete(the_tdb, kbuf) != 0) DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) )); return 0; } - if (strequal(crec.name, cs->name)) + if (strequal(crec.servicename, cs->name)) cs->curr_connections++; return 0; @@ -191,8 +191,8 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti if (conn) { crec.uid = conn->uid; crec.gid = conn->gid; - safe_strcpy(crec.name, - lp_servicename(SNUM(conn)),sizeof(crec.name)-1); + safe_strcpy(crec.servicename, + lp_servicename(SNUM(conn)),sizeof(crec.servicename)-1); } crec.start = time(NULL); crec.bcast_msg_flags = msg_flags; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 04969784c0..8f1226c666 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2247,7 +2247,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf uint16 info_level; int data_len, len; SMB_STRUCT_STAT st; - char *vname = volume_label(SNUM(conn)); + const char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); int quota_flag = 0; @@ -2368,9 +2368,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16)); + /* Max label len is 32 characters. */ len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE); SIVAL(pdata,12,len); data_len = 18+len; + DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", (int)strlen(vname),vname, lp_servicename(snum))); break; -- cgit From 2da54a66b970917ca5290001af0f4ab7adf68460 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Apr 2007 02:14:28 +0000 Subject: r22291: Fix off-by-one in tconX parsing. Jeremy. (This used to be commit bc6ac4feac8c62cda2b6151eb648d3d5979e8a95) --- source3/smbd/reply.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eb4106b0c1..3d0f8a3ca8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -469,13 +469,22 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (global_encrypted_passwords_negotiated) { password = data_blob(smb_buf(inbuf),passlen); + if (lp_security() == SEC_SHARE) { + /* + * Security = share always has a pad byte + * after the password. + */ + p = smb_buf(inbuf) + passlen + 1; + } else { + p = smb_buf(inbuf) + passlen; + } } else { password = data_blob(smb_buf(inbuf),passlen+1); /* Ensure correct termination */ - password.data[passlen]=0; + password.data[passlen]=0; + p = smb_buf(inbuf) + passlen + 1; } - p = smb_buf(inbuf) + passlen; p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); /* -- cgit From 9812a7e32e515315302d3040a4145592640de7f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Apr 2007 00:34:10 +0000 Subject: r22327: Finish the gss-spnego part of the seal code. Now for testing.... Jeremy. (This used to be commit 1c1f5360b67792f14b50835a2c5a4d4ac68aca8f) --- source3/smbd/seal.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 259aff014a..c6fab5f078 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -333,9 +333,12 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d OM_uint32 flags = 0; gss_buffer_desc in_buf, out_buf; struct smb_tran_enc_state_gss *gss_state; + DATA_BLOB auth_reply = data_blob(NULL,0); + DATA_BLOB response = data_blob(NULL,0); + NTSTATUS status; if (!partial_srv_trans_enc_ctx) { - NTSTATUS status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); + status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -361,8 +364,9 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d NULL, /* Ingore time. */ NULL); /* Ignore delegated creds. */ + status = gss_err_to_ntstatus(ret, min); if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - return gss_err_to_ntstatus(ret, min); + return status; } /* Ensure we've got sign+seal available. */ @@ -376,20 +380,18 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d } } - SAFE_FREE(*ppdata); - *ppdata = memdup(out_buf.value, out_buf.length); - if (!*ppdata) { - gss_release_buffer(&min, &out_buf); - return NT_STATUS_NO_MEMORY; - } - *p_data_size = out_buf.length; + auth_reply = data_blob(out_buf.value, out_buf.length); gss_release_buffer(&min, &out_buf); - if (ret != GSS_S_CONTINUE_NEEDED) { - return NT_STATUS_MORE_PROCESSING_REQUIRED; - } else { - return NT_STATUS_OK; - } + /* Wrap in SPNEGO. */ + response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); + data_blob_free(&auth_reply); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + + return status; } #endif -- cgit From 1adbf4af06a71ffea493a3a3750d163f85f62c7f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 00:35:18 +0000 Subject: r22350: Add some helpful debug messages. Jeremy. (This used to be commit bf2e6bd82dc0d35313677c6cb04357da1e74ce4f) --- source3/smbd/seal.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index c6fab5f078..c0682a8201 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -119,13 +119,16 @@ static NTSTATUS get_srv_gss_creds(const char *service, &nt_hostbased_service, &srv_name); + DEBUG(10,("get_srv_gss_creds: imported name %s\n", + host_princ_s )); + if (ret != GSS_S_COMPLETE) { SAFE_FREE(host_princ_s); return map_nt_error_from_gss(ret, min); } ret = gss_acquire_cred(&min, - &srv_name, + srv_name, GSS_C_INDEFINITE, GSS_C_NULL_OID_SET, cred_type, @@ -134,6 +137,9 @@ static NTSTATUS get_srv_gss_creds(const char *service, NULL); if (ret != GSS_S_COMPLETE) { + ADS_STATUS adss = ADS_ERROR_GSS(ret, min); + DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", + ads_errstr(adss))); status = map_nt_error_from_gss(ret, min); } -- cgit From 226d96337fdb53f402569c12c6fd5b6a07123eb4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 00:40:08 +0000 Subject: r22351: Making progress in tests... Jeremy. (This used to be commit f1726e04eb1d63387cf955c907fe077b2201a3ae) --- source3/smbd/seal.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index c0682a8201..7dd6e3d7bb 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -127,6 +127,12 @@ static NTSTATUS get_srv_gss_creds(const char *service, return map_nt_error_from_gss(ret, min); } + /* + * We're accessing the krb5.keytab file here. + * ensure we have permissions to do so. + */ + become_root(); + ret = gss_acquire_cred(&min, srv_name, GSS_C_INDEFINITE, @@ -135,6 +141,7 @@ static NTSTATUS get_srv_gss_creds(const char *service, p_srv_cred, NULL, NULL); + unbecome_root(); if (ret != GSS_S_COMPLETE) { ADS_STATUS adss = ADS_ERROR_GSS(ret, min); -- cgit From d47868cb5e7db5b75848473b90ff2984c3162f8d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 00:44:39 +0000 Subject: r22352: Wow - working gss SMB sealing ! Jeremy. (This used to be commit abcb2a4b0709ef84c50c1d9a85191dc3866cd138) --- source3/smbd/seal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 7dd6e3d7bb..07ef186e2e 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -365,6 +365,8 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d out_buf.value = NULL; out_buf.length = 0; + become_root(); + ret = gss_accept_sec_context(&min, &gss_state->gss_ctx, gss_state->creds, @@ -376,6 +378,7 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d &flags, NULL, /* Ingore time. */ NULL); /* Ignore delegated creds. */ + unbecome_root(); status = gss_err_to_ntstatus(ret, min); if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { -- cgit From dc90cd89a7fef3b0a744ef1873193cf2c9d75cad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 20:50:49 +0000 Subject: r22389: Start preparing for multiple encryption contexts in the server. Allow server to reflect back to calling client the encryption context that was sent. Jeremy. (This used to be commit b49e90335d1e589916b5ab4992e3c4a2d221ca7e) --- source3/smbd/aio.c | 16 +++++++++++++--- source3/smbd/blocking.c | 12 +++++++----- source3/smbd/process.c | 7 ++++--- source3/smbd/reply.c | 8 ++++---- 4 files changed, 28 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index a85cf901ae..6b403e1e36 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -49,8 +49,10 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, - uint16 mid) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, + size_t buflen, + uint16 mid, + const char *inbuf) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -66,6 +68,14 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, SAFE_FREE(aio_ex); return NULL; } + /* Save the first 8 bytes of inbuf for possible enc data. */ + aio_ex->inbuf = SMB_MALLOC_ARRAY(char, 8); + if (!aio_ex->inbuf) { + SAFE_FREE(aio_ex->outbuf); + SAFE_FREE(aio_ex); + return NULL; + } + memcpy(aio_ex->inbuf, inbuf, 8); DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; aio_ex->read_req = True; @@ -408,7 +418,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4,aio_ex->inbuf); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 101f16bb9d..58953bac11 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -237,13 +237,15 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, Return a smd with a given size. *****************************************************************************/ -static void send_blocking_reply(char *outbuf, int outsize) +static void send_blocking_reply(char *outbuf, int outsize, const char *inbuf) { - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); + if(outsize > 4) { + smb_setlen(outbuf,outsize - 4, inbuf); + } - if (!send_smb(smbd_server_fd(),outbuf)) + if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("send_blocking_reply: send_smb failed."); + } } /**************************************************************************** @@ -272,7 +274,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) outsize += chain_size; - send_blocking_reply(outbuf,outsize); + send_blocking_reply(outbuf,outsize,inbuf); } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6f3ad9884c..c6bcfb7394 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1039,8 +1039,9 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) outsize += chain_size; - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); + if(outsize > 4) { + smb_setlen(outbuf,outsize - 4, inbuf); + } return(outsize); } @@ -1219,7 +1220,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) } /* And set it in the header. */ - smb_setlen(inbuf2, new_size); + smb_setlen(inbuf2, new_size, inbuf); /* create the out buffer */ construct_reply_common(inbuf2, outbuf2); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3d0f8a3ca8..1b6f861cb8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -303,7 +303,7 @@ int reply_special(char *inbuf,char *outbuf) memset(outbuf,'\0',smb_size); - smb_setlen(outbuf,0); + smb_setlen(outbuf,0,inbuf); switch (msg_type) { case 0x81: /* session request */ @@ -1182,7 +1182,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); outsize += DIR_STRUCT_SIZE*numentries; - smb_setlen(outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4,inbuf); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -3538,7 +3538,7 @@ int reply_echo(connection_struct *conn, for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) { SSVAL(outbuf,smb_vwv0,seq_num); - smb_setlen(outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4,inbuf); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) @@ -5846,7 +5846,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, if (write_through && tcount==nwritten) { /* We need to send both a primary and a secondary response */ - smb_setlen(outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4,inbuf); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server_cleanly("reply_writebmpx: send_smb failed."); -- cgit From 0829e1ad1c3646efecf50729f493b9ee72ef0517 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 22:40:32 +0000 Subject: r22391: Looks bigger than it is. Make "inbuf" available to all callers of smb_setlen (via set_message() calls). This will allow the server to reflect back the correct encryption context. Jeremy. (This used to be commit 2d80a96120a5fe2fe726f00746d36d85044c4bdb) --- source3/smbd/aio.c | 2 +- source3/smbd/blocking.c | 6 +- source3/smbd/error.c | 12 ++-- source3/smbd/ipc.c | 179 +++++++++++++++++++++++++++++++++-------------- source3/smbd/lanman.c | 24 +++++-- source3/smbd/message.c | 8 +-- source3/smbd/negprot.c | 14 ++-- source3/smbd/notify.c | 5 +- source3/smbd/nttrans.c | 56 ++++++++------- source3/smbd/oplock.c | 2 +- source3/smbd/pipes.c | 12 ++-- source3/smbd/process.c | 6 +- source3/smbd/reply.c | 124 ++++++++++++++++---------------- source3/smbd/sesssetup.c | 25 ++++--- source3/smbd/trans2.c | 41 +++++------ 15 files changed, 307 insertions(+), 209 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 6b403e1e36..0d4760a266 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -418,7 +418,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(outbuf,outsize - 4,aio_ex->inbuf); + smb_setlen(aio_ex->inbuf,outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 58953bac11..d0caa29597 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -240,7 +240,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, static void send_blocking_reply(char *outbuf, int outsize, const char *inbuf) { if(outsize > 4) { - smb_setlen(outbuf,outsize - 4, inbuf); + smb_setlen(inbuf, outbuf,outsize - 4); } if (!send_smb(smbd_server_fd(),outbuf)) { @@ -260,7 +260,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) int outsize = 0; construct_reply_common(inbuf, outbuf); - set_message(outbuf,2,0,True); + set_message(inbuf,outbuf,2,0,True); /* * As this message is a lockingX call we must handle @@ -525,7 +525,7 @@ static BOOL process_trans2(blocking_lock_record *blr) SCVAL(outbuf,smb_com,SMBtrans2); SSVAL(params,0,0); /* Fake up max_data_bytes here - we know it fits. */ - send_trans2_replies(outbuf, max_send, params, 2, NULL, 0, 0xffff); + send_trans2_replies(inbuf, outbuf, max_send, params, 2, NULL, 0, 0xffff); return True; } diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 0860b7d1d9..dc35c0fa64 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -29,7 +29,7 @@ extern uint32 global_client_caps; Create an error packet from a cached error. ****************************************************************************/ -int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file) +int cached_error_packet(const char *inbuf,char *outbuf,files_struct *fsp,int line,const char *file) { write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; int32 eclass = wbmpx->wr_errclass; @@ -38,14 +38,14 @@ int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file /* We can now delete the auxiliary struct */ SAFE_FREE(fsp->wbmpx_ptr); - return error_packet(outbuf,eclass,err,ntstatus,line,file); + return error_packet(inbuf,outbuf,eclass,err,ntstatus,line,file); } /**************************************************************************** Create an error packet from errno. ****************************************************************************/ -int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) +int unix_error_packet(const char *inbuf,char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) { int eclass=def_class; int ecode=def_code; @@ -66,7 +66,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s } } - return error_packet(outbuf,eclass,ecode,ntstatus,line,file); + return error_packet(inbuf,outbuf,eclass,ecode,ntstatus,line,file); } BOOL use_nt_status(void) @@ -126,9 +126,9 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu } } -int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(inbuf,outbuf,0,0,True); error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6e5ff9f035..6b647fc72b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -72,10 +72,13 @@ static void copy_trans_params_and_data(char *outbuf, int align, Send a trans reply. ****************************************************************************/ -void send_trans_reply(char *outbuf, - char *rparam, int rparam_len, - char *rdata, int rdata_len, - BOOL buffer_too_large) +void send_trans_reply(const char *inbuf, + char *outbuf, + char *rparam, + int rparam_len, + char *rdata, + int rdata_len, + BOOL buffer_too_large) { int this_ldata,this_lparam; int tot_data_sent = 0; @@ -97,11 +100,11 @@ void send_trans_reply(char *outbuf, ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata); } - set_message(outbuf,10,1+align+this_ldata+this_lparam,True); + set_message(inbuf,outbuf,10,1+align+this_ldata+this_lparam,True); copy_trans_params_and_data(outbuf, align, - rparam, tot_param_sent, this_lparam, - rdata, tot_data_sent, this_ldata); + rparam, tot_param_sent, this_lparam, + rdata, tot_data_sent, this_ldata); SSVAL(outbuf,smb_vwv0,lparam); SSVAL(outbuf,smb_vwv1,ldata); @@ -133,7 +136,7 @@ void send_trans_reply(char *outbuf, align = (this_lparam%4); - set_message(outbuf,10,1+this_ldata+this_lparam+align,False); + set_message(inbuf,outbuf,10,1+this_ldata+this_lparam+align,False); copy_trans_params_and_data(outbuf, align, rparam, tot_param_sent, this_lparam, @@ -160,7 +163,9 @@ void send_trans_reply(char *outbuf, Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p) +static BOOL api_rpc_trans_reply(const char *inbuf, + char *outbuf, + smb_np_struct *p) { BOOL is_data_outstanding; char *rdata = (char *)SMB_MALLOC(p->max_trans_reply); @@ -177,7 +182,7 @@ static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p) return False; } - send_trans_reply(outbuf, NULL, 0, rdata, data_len, is_data_outstanding); + send_trans_reply(inbuf, outbuf, NULL, 0, rdata, data_len, is_data_outstanding); SAFE_FREE(rdata); return True; @@ -187,7 +192,11 @@ static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p) WaitNamedPipeHandleState ****************************************************************************/ -static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len) +static BOOL api_WNPHS(const char *inbuf, + char *outbuf, + smb_np_struct *p, + char *param, + int param_len) { uint16 priority; @@ -199,7 +208,7 @@ static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len if (wait_rpc_pipe_hnd_state(p, priority)) { /* now send the reply */ - send_trans_reply(outbuf, NULL, 0, NULL, 0, False); + send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False); return True; } return False; @@ -210,7 +219,11 @@ static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len SetNamedPipeHandleState ****************************************************************************/ -static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len) +static BOOL api_SNPHS(const char *inbuf, + char *outbuf, + smb_np_struct *p, + char *param, + int param_len) { uint16 id; @@ -222,7 +235,7 @@ static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply(outbuf, NULL, 0, NULL, 0, False); + send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False); return True; } return False; @@ -233,7 +246,7 @@ static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len When no reply is generated, indicate unsupported. ****************************************************************************/ -static BOOL api_no_reply(char *outbuf, int max_rdata_len) +static BOOL api_no_reply(const char *inbuf, char *outbuf, int max_rdata_len) { char rparam[4]; @@ -244,7 +257,7 @@ static BOOL api_no_reply(char *outbuf, int max_rdata_len) DEBUG(3,("Unsupported API fd command\n")); /* now send the reply */ - send_trans_reply(outbuf, rparam, 4, NULL, 0, False); + send_trans_reply(inbuf, outbuf, rparam, 4, NULL, 0, False); return -1; } @@ -253,9 +266,18 @@ static BOOL api_no_reply(char *outbuf, int max_rdata_len) Handle remote api calls delivered to a named pipe already opened. ****************************************************************************/ -static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +static int api_fd_reply(connection_struct *conn, + uint16 vuid, + const char *inbuf, + char *outbuf, + uint16 *setup, + char *data, + char *params, + int suwcnt, + int tdscnt, + int tpscnt, + int mdrcnt, + int mprcnt) { BOOL reply = False; smb_np_struct *p = NULL; @@ -283,7 +305,7 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, /* Win9x does this call with a unicode pipe name, not a pnum. */ /* Just return success for now... */ DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n")); - send_trans_reply(outbuf, NULL, 0, NULL, 0, False); + send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False); return -1; } @@ -309,51 +331,94 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, /* dce/rpc command */ reply = write_to_pipe(p, data, tdscnt); if (reply) - reply = api_rpc_trans_reply(outbuf, p); + reply = api_rpc_trans_reply(inbuf, outbuf, p); break; case TRANSACT_WAITNAMEDPIPEHANDLESTATE: /* Wait Named Pipe Handle state */ - reply = api_WNPHS(outbuf, p, params, tpscnt); + reply = api_WNPHS(inbuf, outbuf, p, params, tpscnt); break; case TRANSACT_SETNAMEDPIPEHANDLESTATE: /* Set Named Pipe Handle state */ - reply = api_SNPHS(outbuf, p, params, tpscnt); + reply = api_SNPHS(inbuf, outbuf, p, params, tpscnt); break; default: return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (!reply) - return api_no_reply(outbuf, mdrcnt); + return api_no_reply(inbuf, outbuf, mdrcnt); return -1; } /**************************************************************************** - handle named pipe commands - ****************************************************************************/ -static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt, - int msrcnt,int mdrcnt,int mprcnt) + Handle named pipe commands. +****************************************************************************/ + +static int named_pipe(connection_struct *conn, + uint16 vuid, + const char *inbuf, + char *outbuf, + char *name, + uint16 *setup, + char *data, + char *params, + int suwcnt, + int tdscnt, + int tpscnt, + int msrcnt, + int mdrcnt, + int mprcnt) { DEBUG(3,("named pipe command on <%s> name\n", name)); - if (strequal(name,"LANMAN")) - return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt); + if (strequal(name,"LANMAN")) { + return api_reply(conn, + vuid, + inbuf, + outbuf, + data, + params, + tdscnt, + tpscnt, + mdrcnt, + mprcnt); + } if (strequal(name,"WKSSVC") || strequal(name,"SRVSVC") || strequal(name,"WINREG") || strequal(name,"SAMR") || - strequal(name,"LSARPC")) - { + strequal(name,"LSARPC")) { DEBUG(4,("named pipe command from Win95 (wow!)\n")); - return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); + return api_fd_reply(conn, + vuid, + inbuf, + outbuf, + setup, + data, + params, + suwcnt, + tdscnt, + tpscnt, + mdrcnt, + mprcnt); } - if (strlen(name) < 1) - return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); + if (strlen(name) < 1) { + return api_fd_reply(conn, + vuid, + inbuf, + outbuf, + setup, + data, + params, + suwcnt, + tdscnt, + tpscnt, + mdrcnt, + mprcnt); + } if (setup) DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1])); @@ -362,8 +427,10 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na } static NTSTATUS handle_trans(connection_struct *conn, - struct trans_state *state, - char *outbuf, int *outsize) + struct trans_state *state, + const char *inbuf, + char *outbuf, + int *outsize) { char *local_machine_name; int name_offset = 0; @@ -402,15 +469,18 @@ static NTSTATUS handle_trans(connection_struct *conn, name_offset++; DEBUG(5,("calling named_pipe\n")); - *outsize = named_pipe(conn, state->vuid, outbuf, - state->name+name_offset, - state->setup,state->data, - state->param, - state->setup_count,state->total_data, - state->total_param, - state->max_setup_return, - state->max_data_return, - state->max_param_return); + *outsize = named_pipe(conn, + state->vuid, + inbuf, + outbuf, + state->name+name_offset, + state->setup,state->data, + state->param, + state->setup_count,state->total_data, + state->total_param, + state->max_setup_return, + state->max_data_return, + state->max_param_return); if (*outsize == 0) { return NT_STATUS_NOT_SUPPORTED; @@ -426,8 +496,11 @@ static NTSTATUS handle_trans(connection_struct *conn, Reply to a SMBtrans. ****************************************************************************/ -int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, - int size, int bufsize) +int reply_trans(connection_struct *conn, + char *inbuf, + char *outbuf, + int size, + int bufsize) { int outsize = 0; unsigned int dsoff = SVAL(inbuf, smb_dsoff); @@ -552,7 +625,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, if ((state->received_param == state->total_param) && (state->received_data == state->total_data)) { - result = handle_trans(conn, state, outbuf, &outsize); + result = handle_trans(conn, state, inbuf, outbuf, &outsize); SAFE_FREE(state->data); SAFE_FREE(state->param); @@ -576,7 +649,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); + outsize = set_message(inbuf,outbuf,0,0,True); show_msg(outbuf); END_PROFILE(SMBtrans); return outsize; @@ -687,7 +760,7 @@ int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, */ SCVAL(outbuf,smb_com,SMBtrans); - result = handle_trans(conn, state, outbuf, &outsize); + result = handle_trans(conn, state, inbuf, outbuf, &outsize); DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 15e0284521..cd2750d759 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4360,11 +4360,19 @@ static const struct { /**************************************************************************** - Handle remote api calls - ****************************************************************************/ + Handle remote api calls. +****************************************************************************/ -int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, - int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +int api_reply(connection_struct *conn, + uint16 vuid, + const char *inbuf, + char *outbuf, + char *data, + char *params, + int tdscnt, + int tpscnt, + int mdrcnt, + int mprcnt) { int api_command; char *rdata = NULL; @@ -4457,7 +4465,13 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * /* If api_Unsupported returns false we can't return anything. */ if (reply) { - send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); + send_trans_reply(inbuf, + outbuf, + rparam, + rparam_len, + rdata, + rdata_len, + False); } SAFE_FREE(rdata); diff --git a/source3/smbd/message.c b/source3/smbd/message.c index fd53e60c14..e6a5015276 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -131,7 +131,7 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR_DOS(ERRSRV,ERRmsgoff)); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(inbuf,outbuf,0,0,True); p = smb_buf(inbuf)+1; p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; @@ -170,7 +170,7 @@ int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_si return(ERROR_DOS(ERRSRV,ERRmsgoff)); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); memset(msgbuf,'\0',sizeof(msgbuf)); msgpos = 0; @@ -202,7 +202,7 @@ int reply_sendtxt(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz return(ERROR_DOS(ERRSRV,ERRmsgoff)); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(inbuf,outbuf,0,0,True); msg = smb_buf(inbuf) + 1; @@ -233,7 +233,7 @@ int reply_sendend(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz return(ERROR_DOS(ERRSRV,ERRmsgoff)); } - outsize = set_message(outbuf,0,0,True); + outsize = set_message(inbuf,outbuf,0,0,True); DEBUG(3,("SMBsendend\n")); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index e1df08579d..1722c81d2a 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -56,7 +56,7 @@ static void get_challenge(char buff[8]) static int reply_corep(char *inbuf, char *outbuf) { - int outsize = set_message(outbuf,1,0,True); + int outsize = set_message(inbuf,outbuf,1,0,True); Protocol = PROTOCOL_CORE; @@ -70,7 +70,7 @@ static int reply_corep(char *inbuf, char *outbuf) static int reply_coreplus(char *inbuf, char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int outsize = set_message(outbuf,13,0,True); + int outsize = set_message(inbuf,outbuf,13,0,True); SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support readbraw and writebraw (possibly) */ /* Reply, SMBlockread, SMBwritelock supported. */ @@ -99,7 +99,7 @@ static int reply_lanman1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; - set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); + set_message(inbuf,outbuf,13,global_encrypted_passwords_negotiated?8:0,True); SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { @@ -141,7 +141,7 @@ static int reply_lanman2(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; - set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); + set_message(inbuf,outbuf,13,global_encrypted_passwords_negotiated?8:0,True); SSVAL(outbuf,smb_vwv1,secword); SIVAL(outbuf,smb_vwv6,sys_getpid()); @@ -325,7 +325,7 @@ static int reply_nt1(char *inbuf, char *outbuf) } } - set_message(outbuf,17,0,True); + set_message(inbuf,outbuf,17,0,True); SCVAL(outbuf,smb_vwv1,secword); @@ -369,7 +369,7 @@ static int reply_nt1(char *inbuf, char *outbuf) } SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */ - set_message_end(outbuf, p); + set_message_end(inbuf,outbuf, p); return (smb_len(outbuf)+4); } @@ -485,7 +485,7 @@ int reply_negprot(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,1,0,True); + int outsize = set_message(inbuf,outbuf,1,0,True); int Index=0; int choice= -1; int protocol; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index cf60720bc7..d18bbb180f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -107,6 +107,7 @@ static BOOL notify_marshall_changes(int num_changes, static void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { + const char *inbuf = request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); @@ -118,7 +119,7 @@ static void change_notify_reply_packet(const char *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - set_message(outbuf,18,0,False); + set_message(inbuf,outbuf,18,0,False); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) @@ -161,7 +162,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, construct_reply_common(request_buf, outbuf); - if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + if (send_nt_replies(request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0) == -1) { exit_server("change_notify_reply_packet: send_smb failed."); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 94de1c709c..fa9828ae03 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -68,8 +68,14 @@ static char *nttrans_realloc(char **ptr, size_t size) HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, - char *params, int paramsize, char *pdata, int datasize) +int send_nt_replies(const char *inbuf, + char *outbuf, + int bufsize, + NTSTATUS nt_error, + char *params, + int paramsize, + char *pdata, + int datasize) { int data_to_send = datasize; int params_to_send = paramsize; @@ -85,7 +91,7 @@ int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, * transNT replies. */ - set_message(outbuf,18,0,True); + set_message(inbuf,outbuf,18,0,True); if (NT_STATUS_V(nt_error)) { ERROR_NT(nt_error); @@ -149,7 +155,7 @@ int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error, total_sent_thistime = MIN(total_sent_thistime, useable_space); - set_message(outbuf, 18, total_sent_thistime, True); + set_message(inbuf,outbuf, 18, total_sent_thistime, True); /* * Set total params and data to be sent. @@ -392,10 +398,10 @@ static int do_ntcreate_pipe_open(connection_struct *conn, * the wcnt to 42 ? It's definately * what happens on the wire.... */ - set_message(outbuf,50,0,True); + set_message(inbuf,outbuf,50,0,True); SCVAL(outbuf,smb_wct,42); } else { - set_message(outbuf,34,0,True); + set_message(inbuf,outbuf,34,0,True); } p = outbuf + smb_vwv2; @@ -454,7 +460,7 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, return ERROR_NT(status); } - set_message(outbuf,34,0,True); + set_message(inbuf,outbuf,34,0,True); p = outbuf + smb_vwv2; @@ -876,10 +882,10 @@ int reply_ntcreate_and_X(connection_struct *conn, * the wcnt to 42 ? It's definately * what happens on the wire.... */ - set_message(outbuf,50,0,True); + set_message(inbuf,outbuf,50,0,True); SCVAL(outbuf,smb_wct,42); } else { - set_message(outbuf,34,0,True); + set_message(inbuf,outbuf,34,0,True); } p = outbuf + smb_vwv2; @@ -1042,7 +1048,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); return -1; } @@ -1637,7 +1643,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); return -1; } @@ -1898,7 +1904,7 @@ int reply_ntrename(connection_struct *conn, return ERROR_NT(status); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); END_PROFILE(SMBntrename); return(outsize); @@ -2045,7 +2051,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o /* * Rename was successful. */ - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); @@ -2133,7 +2139,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i if(max_data_count < sd_size) { - send_nt_replies(outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); talloc_destroy(mem_ctx); return -1; @@ -2182,7 +2188,7 @@ security descriptor.\n")); talloc_destroy(mem_ctx); - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 4, data, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size); return -1; } @@ -2229,7 +2235,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb done: - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; } @@ -2275,7 +2281,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou so we can know if we need to pre-allocate or not */ DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; @@ -2285,7 +2291,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; @@ -2295,7 +2301,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; @@ -2305,7 +2311,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; @@ -2419,7 +2425,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou talloc_destroy(shadow_data->mem_ctx); - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); return -1; @@ -2472,7 +2478,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ /* this works for now... */ - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; } @@ -2739,7 +2745,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, break; } - send_nt_replies(outbuf, bufsize, nt_status, params, param_len, + send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len, pdata, data_len); return -1; @@ -2857,7 +2863,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRSRV,ERRerror); } - send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, pdata, data_len); return -1; @@ -3141,7 +3147,7 @@ int reply_nttrans(connection_struct *conn, /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); show_msg(outbuf); END_PROFILE(SMBnttrans); return outsize; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 423d6b3a99..26ee52b797 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -259,7 +259,7 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx, } memset(result,'\0',smb_size); - set_message(result,8,0,True); + set_message(NULL,result,8,0,True); SCVAL(result,smb_com,SMBlockingX); SSVAL(result,smb_tid,fsp->conn->cnum); SSVAL(result,smb_pid,0xFFFF); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 52660da2ff..bec2f19f86 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -108,7 +108,7 @@ int reply_open_pipe_and_X(connection_struct *conn, } /* Prepare the reply */ - set_message(outbuf,15,0,True); + set_message(inbuf,outbuf,15,0,True); /* Mark the opened file as an existing named pipe in message mode. */ SSVAL(outbuf,smb_vwv9,2); @@ -162,7 +162,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) return (UNIXERROR(ERRDOS,ERRnoaccess)); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); @@ -224,7 +224,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) return (UNIXERROR(ERRDOS,ERRnoaccess)); } - set_message(outbuf,6,0,True); + set_message(inbuf,outbuf,6,0,True); nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); SSVAL(outbuf,smb_vwv2,nwritten); @@ -260,7 +260,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR_DOS(ERRDOS,ERRbadfid)); } - set_message(outbuf,12,0,True); + set_message(inbuf,outbuf,12,0,True); data = smb_buf(outbuf); nread = read_from_pipe(p, data, smb_maxcnt, &unused); @@ -277,7 +277,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) p->pnum, smb_mincnt, smb_maxcnt, nread)); /* Ensure we set up the message length to include the data length read. */ - set_message_bcc(outbuf,nread); + set_message_bcc(inbuf,outbuf,nread); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -288,7 +288,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) { smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); - int outsize = set_message(outbuf,0,0,True); + int outsize = set_message(inbuf,outbuf,0,0,True); if (!p) { return(ERROR_DOS(ERRDOS,ERRbadfid)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c6bcfb7394..ff1170f552 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1040,7 +1040,7 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) outsize += chain_size; if(outsize > 4) { - smb_setlen(outbuf,outsize - 4, inbuf); + smb_setlen(inbuf,outbuf,outsize - 4); } return(outsize); } @@ -1129,7 +1129,7 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(const char *inbuf, char *outbuf) { - set_message(outbuf,0,0,False); + set_message(inbuf,outbuf,0,0,False); SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); SIVAL(outbuf,smb_rcls,0); @@ -1220,7 +1220,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) } /* And set it in the header. */ - smb_setlen(inbuf2, new_size, inbuf); + smb_setlen(inbuf, inbuf2, new_size); /* create the out buffer */ construct_reply_common(inbuf2, outbuf2); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1b6f861cb8..bf739aa643 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -303,7 +303,7 @@ int reply_special(char *inbuf,char *outbuf) memset(outbuf,'\0',smb_size); - smb_setlen(outbuf,0,inbuf); + smb_setlen(inbuf,outbuf,0); switch (msg_type) { case 0x81: /* session request */ @@ -421,7 +421,7 @@ int reply_tcon(connection_struct *conn, return ERROR_NT(nt_status); } - outsize = set_message(outbuf,2,0,True); + outsize = set_message(inbuf,outbuf,2,0,True); SSVAL(outbuf,smb_vwv0,max_recv); SSVAL(outbuf,smb_vwv1,conn->cnum); SSVAL(outbuf,smb_tid,conn->cnum); @@ -523,11 +523,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt server_devicetype = "A:"; if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,2,0,True); + set_message(inbuf,outbuf,2,0,True); p = smb_buf(outbuf); p += srvstr_push(outbuf, p, server_devicetype, -1, STR_TERMINATE|STR_ASCII); - set_message_end(outbuf,p); + set_message_end(inbuf,outbuf,p); } else { /* NT sets the fstype of IPC$ to the null string */ const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); @@ -537,7 +537,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt uint32 perm1 = 0; uint32 perm2 = 0; - set_message(outbuf,7,0,True); + set_message(inbuf,outbuf,7,0,True); if (IS_IPC(conn)) { perm1 = FILE_ALL_ACCESS; @@ -551,7 +551,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SIVAL(outbuf, smb_vwv3, perm1); SIVAL(outbuf, smb_vwv5, perm2); } else { - set_message(outbuf,3,0,True); + set_message(inbuf,outbuf,3,0,True); } p = smb_buf(outbuf); @@ -560,7 +560,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt p += srvstr_push(outbuf, p, fstype, -1, STR_TERMINATE); - set_message_end(outbuf,p); + set_message_end(inbuf,outbuf,p); /* what does setting this bit do? It is set by NT4 and may affect the ability to autorun mounted cdroms */ @@ -623,7 +623,7 @@ int reply_ioctl(connection_struct *conn, return(ERROR_DOS(ERRSRV,ERRnosupport)); } - outsize = set_message(outbuf,8,replysize+1,True); + outsize = set_message(inbuf,outbuf,8,replysize+1,True); SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */ SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */ SSVAL(outbuf,smb_vwv6,52); /* Offset to data */ @@ -719,7 +719,7 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); END_PROFILE(SMBcheckpath); return outsize; @@ -815,7 +815,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } } - outsize = set_message(outbuf,10,0,True); + outsize = set_message(inbuf,outbuf,10,0,True); SSVAL(outbuf,smb_vwv0,mode); if(lp_dos_filetime_resolution(SNUM(conn)) ) { @@ -908,7 +908,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return UNIXERROR(ERRDOS, ERRnoaccess); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); @@ -931,7 +931,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz return(UNIXERROR(ERRHRD,ERRgeneral)); } - outsize = set_message(outbuf,5,0,True); + outsize = set_message(inbuf,outbuf,5,0,True); if (Protocol <= PROTOCOL_LANMAN2) { double total_space, free_space; @@ -1010,7 +1010,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size expect_close = True; } - outsize = set_message(outbuf,1,3,True); + outsize = set_message(inbuf,outbuf,1,3,True); maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); p = smb_buf(inbuf) + 1; @@ -1182,7 +1182,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); outsize += DIR_STRUCT_SIZE*numentries; - smb_setlen(outbuf,outsize - 4,inbuf); + smb_setlen(inbuf,outbuf,outsize - 4); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -1217,7 +1217,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return reply_unknown(inbuf, outbuf); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); p = smb_buf(inbuf) + 1; p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard); if (!NT_STATUS_IS_OK(err)) { @@ -1336,7 +1336,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRDOS,ERRnoaccess); } - outsize = set_message(outbuf,7,0,True); + outsize = set_message(inbuf,outbuf,7,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); SSVAL(outbuf,smb_vwv1,fattr); if(lp_dos_filetime_resolution(SNUM(conn)) ) { @@ -1512,9 +1512,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } if (open_flags & EXTENDED_RESPONSE_REQUIRED) { - set_message(outbuf,19,0,True); + set_message(inbuf,outbuf,19,0,True); } else { - set_message(outbuf,15,0,True); + set_message(inbuf,outbuf,15,0,True); } SSVAL(outbuf,smb_vwv2,fsp->fnum); SSVAL(outbuf,smb_vwv3,fattr); @@ -1556,7 +1556,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, invalidate_vuid(vuid); - set_message(outbuf,2,0,True); + set_message(inbuf,outbuf,2,0,True); DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); @@ -1651,7 +1651,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, ts[0] = get_atimespec(&sbuf); /* atime. */ file_ntimes(conn, fname, ts); - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { @@ -1750,7 +1750,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); /* the returned filename is relative to the directory */ @@ -1769,7 +1769,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, #endif namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE); p += namelen; - outsize = set_message_end(outbuf, p); + outsize = set_message_end(inbuf,outbuf, p); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); @@ -2131,7 +2131,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); END_PROFILE(SMBunlink); return outsize; @@ -2402,7 +2402,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - outsize = set_message(outbuf,5,3,True); + outsize = set_message(inbuf,outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; @@ -2483,7 +2483,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - outsize = set_message(outbuf,5,3,True); + outsize = set_message(inbuf,outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); /* * The requested read size cannot be greater than max_recv. JRA. @@ -2570,7 +2570,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,smb_maxcnt); SCVAL(outbuf,smb_vwv0,0xFF); - set_message(outbuf,12,smb_maxcnt,False); + set_message(inbuf,outbuf,12,smb_maxcnt,False); header.data = (uint8 *)outbuf; header.length = data - outbuf; header.free = NULL; @@ -2625,7 +2625,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length return(UNIXERROR(ERRDOS,ERRnoaccess)); } - outsize = set_message(outbuf,12,nread,False); + outsize = set_message(inbuf,outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -2666,7 +2666,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(ERROR_DOS(ERRDOS,ERRbadaccess)); } - set_message(outbuf,12,0,True); + set_message(inbuf,outbuf,12,0,True); if (global_client_caps & CAP_LARGE_READX) { if (SVAL(inbuf,smb_vwv7) == 1) { @@ -2790,7 +2790,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, /* Return a message to the redirector to tell it to send more bytes */ SCVAL(outbuf,smb_com,SMBwritebraw); SSVALS(outbuf,smb_vwv0,-1); - outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); + outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server_cleanly("reply_writebraw: send_smb failed."); @@ -2804,7 +2804,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, numtowrite = smb_len(inbuf); /* Set up outbuf to return the correct return */ - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SCVAL(outbuf,smb_com,SMBwritec); if (numtowrite != 0) { @@ -2928,7 +2928,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, } } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); @@ -3006,7 +3006,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d return(UNIXERROR(ERRHRD,ERRdiskfull)); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); @@ -3049,7 +3049,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng return(ERROR_DOS(ERRDOS,ERRbadaccess)); } - set_message(outbuf,6,0,True); + set_message(inbuf,outbuf,6,0,True); /* Deal with possible LARGE_WRITEX */ if (large_writeX) { @@ -3196,7 +3196,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int fsp->fh->pos = res; - outsize = set_message(outbuf,2,0,True); + outsize = set_message(inbuf,outbuf,2,0,True); SIVAL(outbuf,smb_vwv0,res); DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n", @@ -3212,7 +3212,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,False); + int outsize = set_message(inbuf,outbuf,0,0,False); uint16 fnum = SVAL(inbuf,smb_vwv0); files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBflush); @@ -3244,7 +3244,7 @@ int reply_exit(connection_struct *conn, file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid)); - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); DEBUG(3,("exit\n")); @@ -3264,7 +3264,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, files_struct *fsp = NULL; START_PROFILE(SMBclose); - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); /* If it's an IPC, pass off to the pipe handler. */ if (IS_IPC(conn)) { @@ -3384,7 +3384,7 @@ int reply_writeclose(connection_struct *conn, return ERROR_NT(close_status); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,nwritten); END_PROFILE(SMBwriteclose); @@ -3401,7 +3401,7 @@ int reply_writeclose(connection_struct *conn, int reply_lock(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,False); + int outsize = set_message(inbuf,outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3446,7 +3446,7 @@ int reply_lock(connection_struct *conn, int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,False); + int outsize = set_message(inbuf,outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3486,7 +3486,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int reply_tdis(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,False); + int outsize = set_message(inbuf,outbuf,0,0,False); uint16 vuid; START_PROFILE(SMBtdis); @@ -3517,7 +3517,7 @@ int reply_echo(connection_struct *conn, int smb_reverb = SVAL(inbuf,smb_vwv0); int seq_num; unsigned int data_len = smb_buflen(inbuf); - int outsize = set_message(outbuf,1,data_len,True); + int outsize = set_message(inbuf,outbuf,1,data_len,True); START_PROFILE(SMBecho); if (data_len > BUFFER_SIZE) { @@ -3538,7 +3538,7 @@ int reply_echo(connection_struct *conn, for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) { SSVAL(outbuf,smb_vwv0,seq_num); - smb_setlen(outbuf,outsize - 4,inbuf); + smb_setlen(inbuf,outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) @@ -3579,7 +3579,7 @@ int reply_printopen(connection_struct *conn, return(ERROR_NT(status)); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); DEBUG(3,("openprint fd=%d fnum=%d\n", @@ -3596,7 +3596,7 @@ int reply_printopen(connection_struct *conn, int reply_printclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,0,0,False); + int outsize = set_message(inbuf,outbuf,0,0,False); files_struct *fsp = file_fsp(inbuf,smb_vwv0); NTSTATUS status; START_PROFILE(SMBsplclose); @@ -3629,7 +3629,7 @@ int reply_printclose(connection_struct *conn, int reply_printqueue(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { - int outsize = set_message(outbuf,2,3,True); + int outsize = set_message(inbuf,outbuf,2,3,True); int max_count = SVAL(inbuf,smb_vwv0); int start_index = SVAL(inbuf,smb_vwv1); START_PROFILE(SMBsplretq); @@ -3677,7 +3677,7 @@ int reply_printqueue(connection_struct *conn, } if (count > 0) { - outsize = set_message(outbuf,2,28*count+3,False); + outsize = set_message(inbuf,outbuf,2,28*count+3,False); SSVAL(outbuf,smb_vwv0,count); SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); SCVAL(smb_buf(outbuf),0,1); @@ -3700,7 +3700,7 @@ int reply_printqueue(connection_struct *conn, int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int numtowrite; - int outsize = set_message(outbuf,0,0,False); + int outsize = set_message(inbuf,outbuf,0,0,False); char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); @@ -3791,7 +3791,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); @@ -4002,7 +4002,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); DEBUG( 3, ( "rmdir %s\n", directory ) ); @@ -4763,7 +4763,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); END_PROFILE(SMBmv); return(outsize); @@ -5110,7 +5110,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRDOS,error); } - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,count); END_PROFILE(SMBcopy); @@ -5159,7 +5159,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size set_conn_connectpath(conn,newdir); } - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh)); DEBUG(3,("setdir %s\n", newdir)); @@ -5605,7 +5605,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(status); } - set_message(outbuf,2,0,True); + set_message(inbuf,outbuf,2,0,True); DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); @@ -5641,7 +5641,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, return ERROR_DOS(ERRSRV,ERRuseSTD); } - outsize = set_message(outbuf,8,0,True); + outsize = set_message(inbuf,outbuf,8,0,True); CHECK_FSP(fsp,conn); if (!CHECK_READ(fsp,inbuf)) { @@ -5677,7 +5677,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, if (nread < (ssize_t)N) tcount = total_read + nread; - set_message(outbuf,8,nread+pad,False); + set_message(inbuf,outbuf,8,nread+pad,False); SIVAL(outbuf,smb_vwv0,startpos); SSVAL(outbuf,smb_vwv2,tcount); SSVAL(outbuf,smb_vwv6,nread); @@ -5706,7 +5706,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBsetattrE); - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf,outbuf,0,0,False); if(!fsp || (fsp->conn != conn)) { END_PROFILE(SMBsetattrE); @@ -5837,7 +5837,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, SMBwritebmpx */ SCVAL(outbuf,smb_com,SMBwriteBmpx); - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ @@ -5846,13 +5846,13 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, if (write_through && tcount==nwritten) { /* We need to send both a primary and a secondary response */ - smb_setlen(outbuf,outsize - 4,inbuf); + smb_setlen(inbuf,outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server_cleanly("reply_writebmpx: send_smb failed."); /* Now the secondary */ - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SCVAL(outbuf,smb_com,SMBwritec); SSVAL(outbuf,smb_vwv0,nwritten); } @@ -5938,7 +5938,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz wbms->wr_total_written += nwritten; if(wbms->wr_total_written >= tcount) { if (write_through) { - outsize = set_message(outbuf,1,0,True); + outsize = set_message(inbuf,outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); send_response = True; } @@ -5968,7 +5968,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBgetattrE); - outsize = set_message(outbuf,11,0,True); + outsize = set_message(inbuf,outbuf,11,0,True); if(!fsp || (fsp->conn != conn)) { END_PROFILE(SMBgetattrE); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7b5528222e..188b7bfb81 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -96,15 +96,18 @@ static void sessionsetup_start_signing_engine(const auth_serversupplied_info *se Send a security blob via a session setup reply. ****************************************************************************/ -static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, - DATA_BLOB blob, NTSTATUS nt_status) +static BOOL reply_sesssetup_blob(connection_struct *conn, + const char *inbuf, + char *outbuf, + DATA_BLOB blob, + NTSTATUS nt_status) { char *p; if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { ERROR_NT(nt_status_squash(nt_status)); } else { - set_message(outbuf,4,0,True); + set_message(inbuf,outbuf,4,0,True); nt_status = nt_status_squash(nt_status); SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status)); @@ -118,7 +121,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, p += add_signature( outbuf, p ); - set_message_end(outbuf,p); + set_message_end(inbuf,outbuf,p); } show_msg(outbuf); @@ -292,7 +295,7 @@ static int reply_spnego_kerberos(connection_struct *conn, } ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR); response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); - reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED); + reply_sesssetup_blob(conn, inbuf, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED); /* * In this one case we don't invalidate the intermediate vuid. @@ -520,7 +523,7 @@ static int reply_spnego_kerberos(connection_struct *conn, /* current_user_info is changed on new vuid */ reload_services( True ); - set_message(outbuf,4,0,True); + set_message(inbuf,outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); if (server_info->guest) { @@ -539,7 +542,7 @@ static int reply_spnego_kerberos(connection_struct *conn, ap_rep_wrapped = data_blob(NULL, 0); } response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); - reply_sesssetup_blob(conn, outbuf, response, ret); + reply_sesssetup_blob(conn, inbuf, outbuf, response, ret); data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); @@ -593,7 +596,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out /* current_user_info is changed on new vuid */ reload_services( True ); - set_message(outbuf,4,0,True); + set_message(inbuf,outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); if (server_info->guest) { @@ -612,7 +615,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out response = *ntlmssp_blob; } - ret = reply_sesssetup_blob(conn, outbuf, response, nt_status); + ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status); if (wrap) { data_blob_free(&response); } @@ -1513,11 +1516,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_clear_free(&plaintext_password); /* it's ok - setup a reply */ - set_message(outbuf,3,0,True); + set_message(inbuf,outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { char *p = smb_buf( outbuf ); p += add_signature( outbuf, p ); - set_message_end( outbuf, p ); + set_message_end(inbuf, outbuf, p ); /* perhaps grab OS version here?? */ } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8f1226c666..12a9e19301 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -577,7 +577,8 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list * HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -int send_trans2_replies(char *outbuf, +int send_trans2_replies(const char *inbuf, + char *outbuf, int bufsize, const char *params, int paramsize, @@ -602,7 +603,7 @@ int send_trans2_replies(char *outbuf, /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */ - set_message(outbuf,10,0,True); + set_message(inbuf,outbuf,10,0,True); /* Modify the data_to_send and datasize and set the error if we're trying to send more than max_data_bytes. We still send @@ -657,7 +658,7 @@ int send_trans2_replies(char *outbuf, total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset); - set_message(outbuf, 10, total_sent_thistime, True); + set_message(inbuf, outbuf, 10, total_sent_thistime, True); /* Set total params and data to be sent */ SSVAL(outbuf,smb_tprcnt,paramsize); @@ -950,7 +951,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i } /* Send the required number of replies */ - send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes); return -1; } @@ -1929,7 +1930,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,6,0); /* Never an EA error */ SSVAL(params,8,last_entry_off); - send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -2222,7 +2223,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,4,0); /* Never an EA error */ SSVAL(params,6,last_entry_off); - send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -2703,7 +2704,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } - send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes); DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) ); @@ -2804,7 +2805,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", return ERROR_NT(status); } - send_trans2_replies(outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes); if (NT_STATUS_IS_OK(status)) { /* Server-side transport encryption is now *on*. */ @@ -2899,7 +2900,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", * like windows do... * --metze */ - outsize = set_message(outbuf,10,0,True); + outsize = set_message(inbuf, outbuf,10,0,True); return outsize; } @@ -4018,7 +4019,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); return(-1); } @@ -5692,7 +5693,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } else return (UNIXERROR(ERRDOS,ERRbadpath)); @@ -6023,7 +6024,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes); return -1; } @@ -6122,7 +6123,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, SSVAL(params,0,0); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); return(-1); } @@ -6171,7 +6172,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char if(fnf_handle == 0) fnf_handle = 257; - send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes); return(-1); } @@ -6199,7 +6200,7 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char SSVAL(params,0,0); /* No changes */ SSVAL(params,2,0); /* No EA errors */ - send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes); return(-1); } @@ -6234,7 +6235,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* return ERROR_NT(status); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); - send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes); + send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes); return(-1); } @@ -6272,7 +6273,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */ srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ - send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes); + send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes); return(-1); } else { DEBUG(2,("Unknown TRANS2_IOCTL\n")); @@ -6295,7 +6296,7 @@ int reply_findclose(connection_struct *conn, dptr_close(&dptr_num); - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf, outbuf,0,0,False); DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num)); @@ -6322,7 +6323,7 @@ int reply_findnclose(connection_struct *conn, findnotifyfirst - so any dptr_num is ok here. Just ignore it. */ - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf, outbuf,0,0,False); DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num)); @@ -6640,7 +6641,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,False); + outsize = set_message(inbuf, outbuf,0,0,False); show_msg(outbuf); END_PROFILE(SMBtrans2); return outsize; -- cgit From 80576572cc733336d61f33a2d640151393ec977b Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 20 Apr 2007 01:52:44 +0000 Subject: r22395: allow profiling level to be set on startup (This used to be commit f8f51e8648224af6645dbd0c2f2bffc678b83dac) --- source3/smbd/server.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 348d3354d7..f1efcd41e9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -863,6 +863,7 @@ extern void build_options(BOOL screen); static BOOL no_process_group = False; static BOOL log_stdout = False; static char *ports = NULL; + static char *profile_level = NULL; int opt; poptContext pc; @@ -875,6 +876,7 @@ extern void build_options(BOOL screen); {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, + {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"}, POPT_COMMON_SAMBA POPT_COMMON_DYNCONFIG POPT_TABLEEND @@ -997,6 +999,14 @@ extern void build_options(BOOL screen); DEBUG(0,("ERROR: failed to setup profiling\n")); return -1; } + if (profile_level != NULL) { + int pl = atoi(profile_level); + struct process_id src; + + DEBUG(1, ("setting profiling level: %s\n",profile_level)); + src.pid = getpid(); + set_profile_level(pl, src); + } #endif DEBUG(3,( "loaded services\n")); -- cgit From e95c34dc6bbfd16f2f0a0cafa3c89ce0c20b8b06 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 20 Apr 2007 12:06:38 +0000 Subject: r22411: Fix the build: Prototype of create_aio_ex_read, set_message and definition of UNIXERROR have changed in r22389 and r22391? to require an additional "inbuf" argument. Some places in smbd/aio.c had not been adapted. This patch fixes the build. Michael (This used to be commit 9de1af6dc835fa12a75bae00935cd605f61217a3) --- source3/smbd/aio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 0d4760a266..bee6ebc89a 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -242,7 +242,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt; if ((aio_ex = create_aio_ex_read(fsp, bufsize, - SVAL(inbuf,smb_mid))) == NULL) { + SVAL(inbuf,smb_mid), inbuf)) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } @@ -382,6 +382,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; + char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -405,7 +406,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; } else { - outsize = set_message(outbuf,12,nread,False); + outsize = set_message(inbuf,outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -418,7 +419,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(aio_ex->inbuf,outbuf,outsize - 4); + smb_setlen(inbuf,outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -443,6 +444,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; + char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); -- cgit From 8a22b1f0ea81f06616a2dc41a138c5126359f009 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 20 Apr 2007 18:34:33 +0000 Subject: r22417: Refactor the various daemon run-mode options to make the semantics of the various flags explicit. (This used to be commit 19c929c6330a50f278ac322ac5fcb83d03734ea2) --- source3/smbd/server.c | 89 ++++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f1efcd41e9..255f9d0c65 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -300,7 +300,7 @@ static BOOL allowable_number_of_smbd_processes(void) Open the socket communication. ****************************************************************************/ -static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) +static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ports) { int num_interfaces = iface_count(); int num_sockets = 0; @@ -311,11 +311,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ int i; char *ports; - if (!is_daemon) { + if (server_mode == SERVER_MODE_INETD) { return open_sockets_inetd(); } - #ifdef HAVE_ATEXIT { static int atexit_set; @@ -531,8 +530,13 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* Ensure child is set to blocking mode */ set_blocking(smbd_server_fd(),True); - if (smbd_server_fd() != -1 && interactive) + /* In interactive mode, return with a connected socket. + * Foreground and daemon modes should fork worker + * processes. + */ + if (server_mode == SERVER_MODE_INTERACTIVE) { return True; + } if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && @@ -857,22 +861,25 @@ extern void build_options(BOOL screen); int main(int argc,const char *argv[]) { /* shall I run as a daemon */ - static BOOL is_daemon = False; - static BOOL interactive = False; - static BOOL Fork = True; - static BOOL no_process_group = False; - static BOOL log_stdout = False; - static char *ports = NULL; - static char *profile_level = NULL; + BOOL no_process_group = False; + BOOL log_stdout = False; + const char *ports = NULL; + const char *profile_level = NULL; int opt; poptContext pc; + enum smb_server_mode server_mode = SERVER_MODE_DAEMON; + struct poptOption long_options[] = { POPT_AUTOHELP - {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, - {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, - {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" }, - {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, + {"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON, + "Become a daemon (default)" }, + {"interactive", 'i', POPT_ARG_VAL, &server_mode, SERVER_MODE_INTERACTIVE, + "Run interactive (not a daemon)"}, + {"foreground", 'F', POPT_ARG_VAL, &server_mode, SERVER_MODE_FOREGROUND, + "Run daemon in foreground (for daemontools, etc.)" }, + {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, + "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, @@ -912,16 +919,14 @@ extern void build_options(BOOL screen); set_remote_machine_name("smbd", False); - if (interactive) { - Fork = False; + if (server_mode == SERVER_MODE_INTERACTIVE) { log_stdout = True; + if (DEBUGLEVEL >= 9) { + talloc_enable_leak_report(); + } } - if (interactive && (DEBUGLEVEL >= 9)) { - talloc_enable_leak_report(); - } - - if (log_stdout && Fork) { + if (log_stdout && server_mode == SERVER_MODE_DAEMON) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } @@ -1011,21 +1016,19 @@ extern void build_options(BOOL screen); DEBUG(3,( "loaded services\n")); - if (!is_daemon && !is_a_socket(0)) { - if (!interactive) - DEBUG(0,("standard input is not a socket, assuming -D option\n")); - - /* - * Setting is_daemon here prevents us from eventually calling - * the open_sockets_inetd() - */ - - is_daemon = True; + if (is_a_socket(0)) { + if (server_mode == SERVER_MODE_DAEMON) { + DEBUG(0,("standard input is a socket, " + "assuming -F option\n")); + } + server_mode = SERVER_MODE_INETD; } - if (is_daemon && !interactive) { + if (server_mode == SERVER_MODE_DAEMON) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork, no_process_group); + become_daemon(True, no_process_group); + } else if (server_mode == SERVER_MODE_FOREGROUND) { + become_daemon(False, no_process_group); } #if HAVE_SETPGID @@ -1033,15 +1036,18 @@ extern void build_options(BOOL screen); * If we're interactive we want to set our own process group for * signal management. */ - if (interactive && !no_process_group) + if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) { setpgid( (pid_t)0, (pid_t)0); + } #endif if (!directory_exist(lp_lockdir(), NULL)) mkdir(lp_lockdir(), 0755); - if (is_daemon) + if (server_mode != SERVER_MODE_INETD && + server_mode != SERVER_MODE_INTERACTIVE) { pidfile_create("smbd"); + } /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (!message_init()) @@ -1099,9 +1105,10 @@ extern void build_options(BOOL screen); running as a daemon -- bad things will happen if smbd is launched via inetd and we fork a copy of ourselves here */ - - if ( is_daemon && !interactive ) + if (server_mode != SERVER_MODE_INETD && + server_mode != SERVER_MODE_INTERACTIVE) { start_background_queue(); + } /* Always attempt to initialize DMAPI. We will only use it later if * lp_dmapi_support is set on the share, but we need a single global @@ -1109,8 +1116,9 @@ extern void build_options(BOOL screen); */ dmapi_init_session(); - if (!open_sockets_smbd(is_daemon, interactive, ports)) + if (!open_sockets_smbd(server_mode, ports)) { exit(1); + } /* * everything after this point is run after the fork() @@ -1123,7 +1131,8 @@ extern void build_options(BOOL screen); /* Possibly reload the services file. Only worth doing in * daemon mode. In inetd mode, we know we only just loaded this. */ - if (is_daemon) { + if (server_mode != SERVER_MODE_INETD && + server_mode != SERVER_MODE_INTERACTIVE) { reload_services(True); } -- cgit From 44f5211c170c0ddc2be23717f1ad08f5fc0b329a Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 20 Apr 2007 21:09:44 +0000 Subject: r22418: Support running under launchd. We abstract the method of obtaining sockets to listen on a little, because in the launchd case these are provided for us. We also add an idle timeout so that a daemon can exit after a period of inactivity. (This used to be commit fc8589a3371d396197fae508e563f814899c2beb) --- source3/smbd/connection.c | 42 +++++++++-- source3/smbd/server.c | 175 +++++++++++++++++++++++++++++++++------------- 2 files changed, 162 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 5c31a5460b..e609b90a50 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -96,13 +96,15 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u struct connections_data crec; struct count_stat *cs = (struct count_stat *)udp; - if (dbuf.dsize != sizeof(crec)) + if (dbuf.dsize != sizeof(crec)) { return 0; + } memcpy(&crec, dbuf.dptr, sizeof(crec)); - if (crec.cnum == -1) + if (crec.cnum == -1) { return 0; + } /* If the pid was not found delete the entry from connections.tdb */ @@ -113,9 +115,19 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) )); return 0; } - - if (strequal(crec.servicename, cs->name)) + + if (cs->name) { + /* We are counting all the connections to a given share. */ + if (strequal(crec.servicename, cs->name)) { + cs->curr_connections++; + } + } else { + /* We are counting all the connections. Static registrations + * like the lpq backgroud process and the smbd daemon process + * have a cnum of -1, so won't be counted here. + */ cs->curr_connections++; + } return 0; } @@ -139,14 +151,30 @@ int count_current_connections( const char *sharename, BOOL clear ) */ if (tdb_traverse(tdb, count_fn, &cs) == -1) { - DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", + DEBUG(0,("count_current_connections: traverse of connections.tdb failed with error %s\n", tdb_errorstr(tdb) )); - return False; + DEBUGADD(0, ("count_current_connections: connection count of %d might not be accurate", + cs.curr_connections)); } - + + /* If the traverse failed part-way through, we at least return + * as many connections as we had already counted. If it failed + * right at the start, we will return 0, which is about all we + * can do anywway. + */ + return cs.curr_connections; } +/**************************************************************************** + Count the number of connections open across all shares. +****************************************************************************/ + +int count_all_current_connections(void) +{ + return count_current_connections(NULL, True /* clear stale entries */); +} + /**************************************************************************** Claim an entry in the connections database. ****************************************************************************/ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 255f9d0c65..78f9779cfc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 Copyright (C) Jelmer Vernooij 2002-2003 + Copyright (C) James Peach 2007 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 @@ -21,6 +22,7 @@ */ #include "includes.h" +#include "smb_launchd.h" static_decl_rpc; @@ -296,39 +298,13 @@ static BOOL allowable_number_of_smbd_processes(void) return num_children < max_processes; } -/**************************************************************************** - Open the socket communication. -****************************************************************************/ - -static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ports) +static int init_sockets_smbd(const char *smb_ports, + int fd_listenset[FD_SETSIZE]) { int num_interfaces = iface_count(); + char * ports; int num_sockets = 0; - int fd_listenset[FD_SETSIZE]; - fd_set listen_set; - int s; - int maxfd = 0; - int i; - char *ports; - - if (server_mode == SERVER_MODE_INETD) { - return open_sockets_inetd(); - } - -#ifdef HAVE_ATEXIT - { - static int atexit_set; - if(atexit_set == 0) { - atexit_set=1; - atexit(killkids); - } - } -#endif - - /* Stop zombies */ - CatchSignal(SIGCLD, sig_cld); - - FD_ZERO(&listen_set); + int i, s; /* use a reasonable default set of ports - listing on 445 and 139 */ if (!smb_ports) { @@ -356,7 +332,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ const char *ptr; if(ifip == NULL) { - DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); + DEBUG(0,("init_sockets_smbd: interface %d has NULL IP address !\n", i)); continue; } @@ -367,7 +343,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ } s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); if(s == -1) - return False; + return 0; /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); @@ -379,15 +355,13 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("listen: %s\n",strerror(errno))); close(s); - return False; + return 0; } - FD_SET(s,&listen_set); - maxfd = MAX( maxfd, s); num_sockets++; if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); - return False; + DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + return 0; } } } @@ -407,7 +381,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ s = open_socket_in(SOCK_STREAM, port, 0, interpret_addr(lp_socket_address()),True); if (s == -1) - return(False); + return 0; /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); @@ -417,26 +391,122 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ set_blocking(s,False); if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("open_sockets_smbd: listen: %s\n", + DEBUG(0,("init_sockets_smbd: listen: %s\n", strerror(errno))); close(s); - return False; + return 0; } fd_listenset[num_sockets] = s; - FD_SET(s,&listen_set); - maxfd = MAX( maxfd, s); - num_sockets++; if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); - return False; + DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + return 0; } } } SAFE_FREE(ports); + return num_sockets; +} + +static int init_sockets_launchd(const struct smb_launch_info *linfo, + const char * smb_ports, + int fd_listenset[FD_SETSIZE]) +{ + int num_sockets; + int i; + + /* The launchd service configuration does not have to provide sockets, + * even though it's basically useless without it. + */ + if (!linfo->num_sockets) { + return init_sockets_smbd(smb_ports, fd_listenset); + } + + /* Make sure we don't get more sockets than we can handle. */ + num_sockets = MIN(FD_SETSIZE, linfo->num_sockets); + memcpy(fd_listenset, linfo->socket_list, num_sockets * sizeof(int)); + + /* Get the sockets ready. This could be hoisted into + * open_sockets_smbd(), but the order of socket operations might + * matter for some platforms, so this approach seems less risky. + * --jpeach + */ + for (i = 0; i < num_sockets; ++i) { + set_socket_options(fd_listenset[i], "SO_KEEPALIVE"); + set_socket_options(fd_listenset[i], user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(fd_listenset[i], False); + } + + return num_sockets; +} + +/**************************************************************************** + Open the socket communication. +****************************************************************************/ + +static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ports) +{ + int num_sockets = 0; + int fd_listenset[FD_SETSIZE]; + fd_set listen_set; + int s; + int maxfd = 0; + int i; + struct timeval idle_timeout = {0, 0}; + struct smb_launch_info linfo; + + if (server_mode == SERVER_MODE_INETD) { + return open_sockets_inetd(); + } + +#ifdef HAVE_ATEXIT + { + static int atexit_set; + if(atexit_set == 0) { + atexit_set=1; + atexit(killkids); + } + } +#endif + + /* Stop zombies */ + CatchSignal(SIGCLD, sig_cld); + + FD_ZERO(&listen_set); + + /* At this point, it doesn't matter what daemon mode we are in, we + * need some sockets to listen on. If we are in FOREGROUND mode, + * the launchd checkin might succeed. If we are in DAEMON or + * INTERACTIVE modes, it will fail and we will open the sockets + * ourselves. + */ + if (smb_launchd_checkin(&linfo)) { + /* We are running under launchd and launchd has + * opened some sockets for us. + */ + num_sockets = init_sockets_launchd(&linfo, + smb_ports, + fd_listenset); + idle_timeout.tv_sec = linfo.idle_timeout_secs; + smb_launchd_checkout(&linfo); + } else { + num_sockets = init_sockets_smbd(smb_ports, + fd_listenset); + } + + if (num_sockets == 0) { + return False; + } + + for (i = 0; i < num_sockets; ++i) { + FD_SET(fd_listenset[i], &listen_set); + maxfd = MAX(maxfd, fd_listenset[i]); + } /* Listen to messages */ @@ -476,8 +546,9 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); - - num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL); + + num = sys_select(maxfd+1,&lfds,NULL,NULL, + idle_timeout.tv_sec ? &idle_timeout : NULL); if (num == -1 && errno == EINTR) { if (got_sig_term) { @@ -494,7 +565,15 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ continue; } - + + /* If the idle timeout fired and we don't have any connected + * users, exit gracefully. We should be running under a process + * controller that will restart us if necessry. + */ + if (num == 0 && count_all_current_connections() == 0) { + exit_server_cleanly("idle timeout"); + } + /* check if we need to reload services */ check_reload(time(NULL)); -- cgit From 2541e0d59048f9d0f522aaebca4c4c6f5019fec5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Apr 2007 14:51:07 +0000 Subject: r22458: Fix a comment (This used to be commit f5ccec42287cfdf128bbfcf562a47a852bd0e3fe) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ff1170f552..16c1d80c0f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -121,7 +121,7 @@ void remove_deferred_open_smb_message(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { - DEBUG(10,("remove_sharing_violation_open_smb_message: " + DEBUG(10,("remove_deferred_open_smb_message: " "deleting mid %u len %u\n", (unsigned int)mid, (unsigned int)pml->buf.length )); -- cgit From 5e7174a2c831883a23ce17b48e3787855b3bb8ff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Apr 2007 09:19:35 +0000 Subject: r22481: Move check for non-mappable SIDs to after sid_to_uid, sid_to_gid mapping, add LocalSystem to non-mappable list. Jeremy. (This used to be commit 805f01464f3feb30725dbce1f90d4296380dd796) --- source3/smbd/posix_acls.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 50038dd464..cdb60a23e7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1346,17 +1346,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, for(i = 0; i < dacl->num_aces; i++) { SEC_ACE *psa = &dacl->aces[i]; - /* - * Ignore non-mappable SIDs (NT Authority, BUILTIN etc). - */ - - if (non_mappable_sid(&psa->trustee)) { - fstring str; - DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n", - sid_to_string(str, &psa->trustee) )); - continue; - } - /* * Create a cannon_ace entry representing this NT DACL ACE. */ @@ -1417,6 +1406,16 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, } else { fstring str; + /* + * Silently ignore map failures in non-mappable SIDs (NT Authority, BUILTIN etc). + */ + + if (non_mappable_sid(&psa->trustee)) { + DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n", + sid_to_string(str, &psa->trustee) )); + continue; + } + free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n", -- cgit From 1ddcc5c06aa88638ec89bb75cc7e4d3feb74efd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Apr 2007 16:32:24 +0000 Subject: r22490: Fix a couple of bugs found whist investigating CSC Vista issues. Ensure we correctly NULL out allocation size fields. Allow QFILEINFO on pipes (Vista bug ?). Jerry - don't automatically merge for 3.0.25. Jeremy. (This used to be commit a27577815201101de4ca5c8375b7f768b6127fb2) --- source3/smbd/trans2.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 12a9e19301..84bbc3b0dd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2235,6 +2235,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return(-1); } +unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16]) +{ + E_md4hash(lp_servicename(SNUM(conn)),objid); + return objid; +} + /**************************************************************************** Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ @@ -2342,6 +2348,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| + FILE_SUPPORTS_OBJECT_IDS| + FILE_UNICODE_ON_DISK| quota_flag); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ @@ -2523,8 +2531,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } #endif /* HAVE_SYS_QUOTAS */ case SMB_FS_OBJECTID_INFORMATION: + { + unsigned char objid[16]; + memcpy(pdata,create_volume_objectid(conn, objid),16); data_len = 64; break; + } /* * Query the version and capabilities of the CIFS UNIX extensions @@ -3193,6 +3205,68 @@ static char *store_file_unix_basic_info2(connection_struct *conn, return pdata; } +/**************************************************************************** + Reply to a TRANSACT2_QFILEINFO on a PIPE ! +****************************************************************************/ + +static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + unsigned int tran_call, + char **pparams, int total_params, char **ppdata, int total_data, + unsigned int max_data_bytes) +{ + char *params = *pparams; + char *pdata = *ppdata; + unsigned int data_size = 0; + unsigned int param_size = 2; + uint16 info_level; + smb_np_struct *p_pipe = NULL; + + if (!params) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (total_params < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + p_pipe = get_rpc_pipe_p(params,0); + if (p_pipe == NULL) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + info_level = SVAL(params,2); + + *pparams = (char *)SMB_REALLOC(*pparams,2); + if (*pparams == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + params = *pparams; + SSVAL(params,0,0); + data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; + *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); + if (*ppdata == NULL ) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + pdata = *ppdata; + + switch (info_level) { + case SMB_FILE_STANDARD_INFORMATION: + memset(pdata,24,0); + SOFF_T(pdata,0,4096LL); + SIVAL(pdata,16,1); + SIVAL(pdata,20,1); + data_size = 24; + break; + + default: + return ERROR_NT(NT_STATUS_INVALID_LEVEL); + } + + send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); + + return(-1); +} + /**************************************************************************** Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by file name or file id). @@ -3238,6 +3312,20 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + if (IS_IPC(conn)) { + return call_trans2qpipeinfo(conn, + inbuf, + outbuf, + length, + bufsize, + tran_call, + pparams, + total_params, + ppdata, + total_data, + max_data_bytes); + } + fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -3769,8 +3857,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SIVAL(pdata,0,0); /* ??? */ SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,allocation_size); - SIVAL(pdata,20,0); /* ??? */ + SOFF_T(pdata,16,allocation_size); data_size = 24 + byte_len; } break; @@ -3790,7 +3877,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd put_long_date_timespec(pdata+8,atime_ts); put_long_date_timespec(pdata+16,mtime_ts); /* write time */ put_long_date_timespec(pdata+24,mtime_ts); /* change time */ - SIVAL(pdata,32,allocation_size); + SOFF_T(pdata,32,allocation_size); SOFF_T(pdata,40,file_size); SIVAL(pdata,48,mode); SIVAL(pdata,52,0); /* ??? */ @@ -6525,7 +6612,8 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, } if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) - && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) { + && (tran_call != TRANSACT2_GET_DFS_REFERRAL) + && (tran_call != TRANSACT2_QFILEINFO)) { END_PROFILE(SMBtrans2); return ERROR_DOS(ERRSRV,ERRaccess); } -- cgit From 7d859f04f2c9b51c34b5445743f04ae743489ba3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Apr 2007 16:45:56 +0000 Subject: r22491: Fix the build (3.0.25 and 3.0 are different here). Jeremy. (This used to be commit c34c291194f34a4b68c1b149dd513b79295a7f1c) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 84bbc3b0dd..2c6df0a11e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3262,7 +3262,7 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); + send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); return(-1); } -- cgit From 4742fa9366020accb033e622881c8cb29a6e427f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Apr 2007 21:07:05 +0000 Subject: r22492: Add objectid code. Jeremy. (This used to be commit d3df922038032b65f52e1e0ac1f2dd53a6933fb7) --- source3/smbd/nttrans.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fa9828ae03..1a4b43ce51 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2285,15 +2285,30 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou 0); return -1; - case FSCTL_0x000900C0: - /* pretend this succeeded - don't know what this really is - but works ok like this --metze + case FSCTL_CREATE_OR_GET_OBJECT_ID: + { + unsigned char objid[16]; + + /* This should return the object-id on this file. + * I think I'll make this be the inode+dev. JRA. */ - DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, - 0); + DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum)); + + data_count = 64; + pdata = nttrans_realloc(ppdata, data_count); + if (pdata == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + SINO_T_VAL(pdata,0,fsp->inode); + SDEV_T_VAL(pdata,8,fsp->dev); + memcpy(pdata+16,create_volume_objectid(conn,objid),16); + SINO_T_VAL(pdata,32,fsp->inode); + SDEV_T_VAL(pdata,40,fsp->dev); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); return -1; + } + case FSCTL_GET_REPARSE_POINT: /* pretend this fail - my winXP does it like this @@ -2301,8 +2316,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, - NULL, 0, NULL, 0); + return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT); return -1; case FSCTL_SET_REPARSE_POINT: @@ -2311,8 +2325,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, - NULL, 0, NULL, 0); + return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT); return -1; case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ -- cgit From 0845fa40853040c3ddb9d7a56fd756924f3369eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 23 Apr 2007 21:40:54 +0000 Subject: r22493: Fix horrible memory corruption bug with CIFS POSIX open/mkidr. Found by SteveF + valgrind :-). Jerry - essential for rc3. Jeremy. (This used to be commit b01c1c4618fe0ff9fd9bac7ed780a4676ea1ba7a) --- source3/smbd/trans2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2c6df0a11e..512b3162fa 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5434,6 +5434,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, *pdata_return_size = 0; return NT_STATUS_NO_MEMORY; } + pdata = *ppdata; SSVAL(pdata,0,NO_OPLOCK_RETURN); SSVAL(pdata,2,0); /* No fnum. */ @@ -5610,6 +5611,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, *pdata_return_size = 0; return NT_STATUS_NO_MEMORY; } + pdata = *ppdata; if (extended_oplock_granted) { if (flags & REQUEST_BATCH_OPLOCK) { -- cgit From c620832983d99205576b7885568221a1a576febe Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 23 Apr 2007 22:17:06 +0000 Subject: r22495: Create wrapper to hide the details of obtaining a set of sockets to listen on. (This used to be commit 29a16b2acb8da604776d48c6a1e6163c9e868d12) --- source3/smbd/server.c | 169 +--------------------------------------- source3/smbd/sockinit.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+), 167 deletions(-) create mode 100644 source3/smbd/sockinit.c (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 78f9779cfc..ee5d219b97 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -22,7 +22,6 @@ */ #include "includes.h" -#include "smb_launchd.h" static_decl_rpc; @@ -298,153 +297,6 @@ static BOOL allowable_number_of_smbd_processes(void) return num_children < max_processes; } -static int init_sockets_smbd(const char *smb_ports, - int fd_listenset[FD_SETSIZE]) -{ - int num_interfaces = iface_count(); - char * ports; - int num_sockets = 0; - int i, s; - - /* use a reasonable default set of ports - listing on 445 and 139 */ - if (!smb_ports) { - ports = lp_smb_ports(); - if (!ports || !*ports) { - ports = smb_xstrdup(SMB_PORTS); - } else { - ports = smb_xstrdup(ports); - } - } else { - ports = smb_xstrdup(smb_ports); - } - - if (lp_interfaces() && lp_bind_interfaces_only()) { - /* We have been given an interfaces line, and been - told to only bind to those interfaces. Create a - socket per interface and bind to only these. - */ - - /* Now open a listen socket for each of the - interfaces. */ - for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); - fstring tok; - const char *ptr; - - if(ifip == NULL) { - DEBUG(0,("init_sockets_smbd: interface %d has NULL IP address !\n", i)); - continue; - } - - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0) { - continue; - } - s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); - if(s == -1) - return 0; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return 0; - } - - num_sockets++; - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); - return 0; - } - } - } - } else { - /* Just bind to 0.0.0.0 - accept connections - from anywhere. */ - - fstring tok; - const char *ptr; - - num_interfaces = 1; - - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0) continue; - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()),True); - if (s == -1) - return 0; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("init_sockets_smbd: listen: %s\n", - strerror(errno))); - close(s); - return 0; - } - - fd_listenset[num_sockets] = s; - num_sockets++; - - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); - return 0; - } - } - } - - SAFE_FREE(ports); - return num_sockets; -} - -static int init_sockets_launchd(const struct smb_launch_info *linfo, - const char * smb_ports, - int fd_listenset[FD_SETSIZE]) -{ - int num_sockets; - int i; - - /* The launchd service configuration does not have to provide sockets, - * even though it's basically useless without it. - */ - if (!linfo->num_sockets) { - return init_sockets_smbd(smb_ports, fd_listenset); - } - - /* Make sure we don't get more sockets than we can handle. */ - num_sockets = MIN(FD_SETSIZE, linfo->num_sockets); - memcpy(fd_listenset, linfo->socket_list, num_sockets * sizeof(int)); - - /* Get the sockets ready. This could be hoisted into - * open_sockets_smbd(), but the order of socket operations might - * matter for some platforms, so this approach seems less risky. - * --jpeach - */ - for (i = 0; i < num_sockets; ++i) { - set_socket_options(fd_listenset[i], "SO_KEEPALIVE"); - set_socket_options(fd_listenset[i], user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(fd_listenset[i], False); - } - - return num_sockets; -} - /**************************************************************************** Open the socket communication. ****************************************************************************/ @@ -458,7 +310,6 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ int maxfd = 0; int i; struct timeval idle_timeout = {0, 0}; - struct smb_launch_info linfo; if (server_mode == SERVER_MODE_INETD) { return open_sockets_inetd(); @@ -480,25 +331,9 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ FD_ZERO(&listen_set); /* At this point, it doesn't matter what daemon mode we are in, we - * need some sockets to listen on. If we are in FOREGROUND mode, - * the launchd checkin might succeed. If we are in DAEMON or - * INTERACTIVE modes, it will fail and we will open the sockets - * ourselves. + * need some sockets to listen on. */ - if (smb_launchd_checkin(&linfo)) { - /* We are running under launchd and launchd has - * opened some sockets for us. - */ - num_sockets = init_sockets_launchd(&linfo, - smb_ports, - fd_listenset); - idle_timeout.tv_sec = linfo.idle_timeout_secs; - smb_launchd_checkout(&linfo); - } else { - num_sockets = init_sockets_smbd(smb_ports, - fd_listenset); - } - + num_sockets = smbd_sockinit(smb_ports, fd_listenset, &idle_timeout); if (num_sockets == 0) { return False; } diff --git a/source3/smbd/sockinit.c b/source3/smbd/sockinit.c new file mode 100644 index 0000000000..a4b9d63810 --- /dev/null +++ b/source3/smbd/sockinit.c @@ -0,0 +1,201 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) James Peach 2007 + + 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 "smb_launchd.h" + +extern pstring user_socket_options; + +static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) +{ + int num_interfaces = iface_count(); + char * ports; + int num_sockets = 0; + int i, s; + + /* use a reasonable default set of ports - listing on 445 and 139 */ + if (!smb_ports) { + ports = lp_smb_ports(); + if (!ports || !*ports) { + ports = smb_xstrdup(SMB_PORTS); + } else { + ports = smb_xstrdup(ports); + } + } else { + ports = smb_xstrdup(smb_ports); + } + + if (lp_interfaces() && lp_bind_interfaces_only()) { + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + + /* Now open a listen socket for each of the + interfaces. */ + for(i = 0; i < num_interfaces; i++) { + struct in_addr *ifip = iface_n_ip(i); + fstring tok; + const char *ptr; + + if(ifip == NULL) { + DEBUG(0,("init_sockets_smbd: interface %d has NULL IP address !\n", i)); + continue; + } + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0) { + continue; + } + s = listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + if(s == -1) + return 0; + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return 0; + } + + num_sockets++; + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + return 0; + } + } + } + } else { + /* Just bind to 0.0.0.0 - accept connections + from anywhere. */ + + fstring tok; + const char *ptr; + + num_interfaces = 1; + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0) continue; + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address()),True); + if (s == -1) + return 0; + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("init_sockets_smbd: listen: %s\n", + strerror(errno))); + close(s); + return 0; + } + + listenset[num_sockets] = s; + num_sockets++; + + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + return 0; + } + } + } + + SAFE_FREE(ports); + return num_sockets; +} + +static int init_sockets_launchd(const struct smb_launch_info *linfo, + const char * smb_ports, + int listenset[FD_SETSIZE]) +{ + int num_sockets; + int i; + + /* The launchd service configuration does not have to provide sockets, + * even though it's basically useless without it. + */ + if (!linfo->num_sockets) { + return init_sockets_smbd(smb_ports, listenset); + } + + /* Make sure we don't get more sockets than we can handle. */ + num_sockets = MIN(FD_SETSIZE, linfo->num_sockets); + memcpy(listenset, linfo->socket_list, num_sockets * sizeof(int)); + + /* Get the sockets ready. This could be hoisted into + * open_sockets_smbd(), but the order of socket operations might + * matter for some platforms, so this approach seems less risky. + * --jpeach + */ + for (i = 0; i < num_sockets; ++i) { + set_socket_options(listenset[i], "SO_KEEPALIVE"); + set_socket_options(listenset[i], user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(listenset[i], False); + } + + return num_sockets; +} + +/* This function is responsible for opening (or retrieving) all the sockets we + * smbd will be listening on. It should apply all the configured socket options + * and return the number of valid sockets in listenset. + */ +int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE], + struct timeval *idle) +{ + int num_sockets; + struct smb_launch_info linfo; + + ZERO_STRUCTP(idle); + + if (smb_launchd_checkin(&linfo)) { + /* We are running under launchd and launchd has + * opened some sockets for us. + */ + num_sockets = init_sockets_launchd(&linfo, + cmdline_ports, + listenset); + idle->tv_sec = linfo.idle_timeout_secs; + smb_launchd_checkout(&linfo); + } else { + num_sockets = init_sockets_smbd(cmdline_ports, + listenset); + } + + return num_sockets; +} + -- cgit From 2ad66881dfd0fb8a03efc409af7f5bb6d3d204b2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Apr 2007 12:56:23 +0000 Subject: r22502: Fix bug #4536 - delete symlinks to a directory correctly. Jeremy. (This used to be commit dcc6517d9d349c65b045160e8a1358af088ae97a) --- source3/smbd/reply.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bf739aa643..1acd78a106 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3867,7 +3867,23 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) int ret; SMB_STRUCT_STAT st; - ret = SMB_VFS_RMDIR(conn,directory); + /* Might be a symlink. */ + if(SMB_VFS_LSTAT(conn, directory, &st) != 0) { + return map_nt_error_from_unix(errno); + } + + if (S_ISLNK(st.st_mode)) { + /* Is what it points to a directory ? */ + if(SMB_VFS_STAT(conn, directory, &st) != 0) { + return map_nt_error_from_unix(errno); + } + if (!(S_ISDIR(st.st_mode))) { + return NT_STATUS_NOT_A_DIRECTORY; + } + ret = SMB_VFS_UNLINK(conn,directory); + } else { + ret = SMB_VFS_RMDIR(conn,directory); + } if (ret == 0) { notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_DIR_NAME, -- cgit From 322ca3b9336bebdcc4337004a312ced9349269e8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 27 Apr 2007 14:00:27 +0000 Subject: r22533: Use lib functions where we have them (This used to be commit dc18ab2f3407234dc545d5133660f9f04e8e5b55) --- source3/smbd/server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ee5d219b97..3422290a90 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -309,7 +309,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ int s; int maxfd = 0; int i; - struct timeval idle_timeout = {0, 0}; + struct timeval idle_timeout = timeval_zero(); if (server_mode == SERVER_MODE_INETD) { return open_sockets_inetd(); @@ -383,7 +383,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ sizeof(listen_set)); num = sys_select(maxfd+1,&lfds,NULL,NULL, - idle_timeout.tv_sec ? &idle_timeout : NULL); + timeval_is_zero(&idle_timeout) ? + NULL : &idle_timeout); if (num == -1 && errno == EINTR) { if (got_sig_term) { -- cgit From 12ba88574bf91bdcc4447bfc3d429b799064bfd9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Apr 2007 23:18:41 +0000 Subject: r22542: Move over to using the _strict varients of the talloc calls. No functional changes. Looks bigger than it is :-). Jeremy. (This used to be commit f6fa3080fee1b20df9f1968500840a88cf0ee592) --- source3/smbd/conn.c | 2 +- source3/smbd/fake_file.c | 2 +- source3/smbd/notify_inotify.c | 2 +- source3/smbd/notify_internal.c | 4 ++-- source3/smbd/ntquotas.c | 6 +++--- source3/smbd/nttrans.c | 2 +- source3/smbd/password.c | 2 +- source3/smbd/trans2.c | 2 +- source3/smbd/vfs.c | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 388cd004f9..a15684a35b 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -148,7 +148,7 @@ find_again: if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) || !(conn->params = TALLOC_P(mem_ctx, struct share_params))) { - DEBUG(0,("talloc_zero() failed!\n")); + DEBUG(0,("TALLOC_ZERO() failed!\n")); TALLOC_FREE(mem_ctx); return NULL; } diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 208b325667..5333742ba8 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -49,7 +49,7 @@ static struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) } if ((fh =TALLOC_ZERO_P(mem_ctx, FAKE_FILE_HANDLE))==NULL) { - DEBUG(0,("talloc_zero() failed.\n")); + DEBUG(0,("TALLOC_ZERO() failed.\n")); talloc_destroy(mem_ctx); return NULL; } diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index ff17d455f3..1b1bad7e96 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -235,7 +235,7 @@ static void inotify_handler(struct event_context *ev, struct fd_event *fde, return; } - e0 = e = (struct inotify_event *)talloc_size(in, bufsize); + e0 = e = (struct inotify_event *)TALLOC_SIZE(in, bufsize); if (e == NULL) return; if (read(in->fd, e0, bufsize) != bufsize) { diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index e1f47540e5..9f23db6671 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -156,7 +156,7 @@ static NTSTATUS notify_load(struct notify_context *notify) notify->seqnum = seqnum; talloc_free(notify->array); - notify->array = talloc_zero(notify, struct notify_array); + notify->array = TALLOC_ZERO_P(notify, struct notify_array); NT_STATUS_HAVE_NO_MEMORY(notify->array); dbuf = tdb_fetch_bystring(notify->w->tdb, NOTIFY_KEY); @@ -385,7 +385,7 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0, depth = count_chars(e.path, '/'); - listel = talloc_zero(notify, struct notify_list); + listel = TALLOC_ZERO_P(notify, struct notify_list); if (listel == NULL) { status = NT_STATUS_NO_MEMORY; goto done; diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index e754583312..df851a2ca8 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -197,14 +197,14 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) sid_string_static(&sid),fsp->conn->connectpath)); if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) { - DEBUG(0,("talloc_zero() failed\n")); + DEBUG(0,("TALLOC_ZERO() failed\n")); *qt_list = NULL; talloc_destroy(mem_ctx); return (-1); } if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) { - DEBUG(0,("talloc_zero() failed\n")); + DEBUG(0,("TALLOC_ZERO() failed\n")); *qt_list = NULL; talloc_destroy(mem_ctx); return (-1); @@ -231,7 +231,7 @@ void *init_quota_handle(TALLOC_CTX *mem_ctx) qt_handle = TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_HANDLE); if (qt_handle==NULL) { - DEBUG(0,("talloc_zero() failed\n")); + DEBUG(0,("TALLOC_ZERO() failed\n")); return NULL; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1a4b43ce51..eb4a6cd969 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2367,7 +2367,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA); if (shadow_data == NULL) { - DEBUG(0,("talloc_zero() failed!\n")); + DEBUG(0,("TALLOC_ZERO() failed!\n")); talloc_destroy(shadow_mem_ctx); return ERROR_NT(NT_STATUS_NO_MEMORY); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b7945bd7ea..ce03e6d85f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -156,7 +156,7 @@ int register_vuid(auth_serversupplied_info *server_info, return UID_FIELD_INVALID; } - if((vuser = talloc_zero(NULL, user_struct)) == NULL) { + if((vuser = TALLOC_ZERO_P(NULL, user_struct)) == NULL) { DEBUG(0,("Failed to talloc users struct!\n")); data_blob_free(&session_key); return UID_FIELD_INVALID; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 512b3162fa..91218fe9f4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3517,7 +3517,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Copy the lock range data. */ - lock_data = (char *)talloc_memdup( + lock_data = (char *)TALLOC_MEMDUP( data_ctx, pdata, total_data); if (!lock_data) { talloc_destroy(data_ctx); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 0803ffb7e7..2fd448061e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -159,7 +159,7 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct); if (!handle) { - DEBUG(0,("talloc_zero() failed!\n")); + DEBUG(0,("TALLOC_ZERO() failed!\n")); SAFE_FREE(module_name); return False; } -- cgit From e26dee48f079f429690584aa2666f498e08e6810 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 28 Apr 2007 18:16:33 +0000 Subject: r22561: Fix a memleak in lanman.c: Nobody would free the session_list. Volker (This used to be commit 5d428400f77399b7fc30fb2a0fb10f0c74b96458) --- source3/smbd/lanman.c | 2 +- source3/smbd/session.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index cd2750d759..05b1e812b2 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4213,7 +4213,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, return False; } - num_sessions = list_sessions(&session_list); + num_sessions = list_sessions(tmp_talloc_ctx(), &session_list); if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 05b1026f41..30ade8aedf 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -218,6 +218,7 @@ BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), ********************************************************************/ struct session_list { + TALLOC_CTX *mem_ctx; int count; struct sessionid *sessions; }; @@ -230,7 +231,9 @@ static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, v i = sesslist->count; - sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, i+1); + sesslist->sessions = TALLOC_REALLOC_ARRAY( + sesslist->mem_ctx, sesslist->sessions, struct sessionid, i+1); + if (!sesslist->sessions) { sesslist->count = 0; return -1; @@ -248,10 +251,11 @@ static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, v /******************************************************************** ********************************************************************/ -int list_sessions(struct sessionid **session_list) +int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list) { struct session_list sesslist; + sesslist.mem_ctx = mem_ctx; sesslist.count = 0; sesslist.sessions = NULL; -- cgit From 56a5d05b8b285250bdc0e9cc3c8f3c3d8af80382 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Apr 2007 02:51:26 +0000 Subject: r22590: Make TALLOC_ARRAY consistent across all uses. That should be it.... Jeremy. (This used to be commit 603233a98bbf65467c8b4f04719d771c70b3b4c9) --- source3/smbd/msdfs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index effe868657..9f203bfd19 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -264,10 +264,14 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, DEBUG(10,("parse_msdfs_symlink: count=%d\n", count)); - reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, struct referral, count); - if(reflist == NULL) { - DEBUG(0,("parse_msdfs_symlink: talloc failed!\n")); - return False; + if (count) { + reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, struct referral, count); + if(reflist == NULL) { + DEBUG(0,("parse_msdfs_symlink: talloc failed!\n")); + return False; + } + } else { + reflist = *preflist = NULL; } for(i=0;i Date: Mon, 30 Apr 2007 16:32:17 +0000 Subject: r22611: Fix from Jens Nissen . Fix bad memory leak I introduced into acl code, also remove redundent extra check for global_sid_System : global_sid_System == S-1-5-18 which is already included in the check for a domain of global_sid_NT_Authority == S-1-5 Jeremy. (This used to be commit 10649540ac11e679997f414d4a6b12d057bd7913) --- source3/smbd/posix_acls.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index cdb60a23e7..7eda998547 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1413,6 +1413,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, if (non_mappable_sid(&psa->trustee)) { DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n", sid_to_string(str, &psa->trustee) )); + SAFE_FREE(current_ace); continue; } -- cgit From fb5644342760cb54b4285c65ab36d693f558a289 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 5 May 2007 21:13:40 +0000 Subject: r22691: Fix a 64-bit warning and a const const discard warning (This used to be commit 3a2ca1b1b85e268928587287f61d26f992b303a5) --- source3/smbd/dmapi.c | 3 ++- source3/smbd/process.c | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index b8c23c2dce..23b5d5e947 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -152,7 +152,8 @@ retry: /* No session already defined. */ if (dmapi_session == DM_NO_SESSION) { - err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, + err = dm_create_session(DM_NO_SESSION, + CONST_DISCARD(DMAPI_SESSION_NAME), &dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 16c1d80c0f..44baa96059 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1211,10 +1211,9 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* work out the new size for the in buffer. */ new_size = size - (inbuf2 - inbuf); if (new_size < 0) { - DEBUG(0,("chain_reply: chain packet size incorrect (orig size = %d, " - "offset = %d)\n", - size, - (inbuf2 - inbuf) )); + DEBUG(0,("chain_reply: chain packet size incorrect " + "(orig size = %d, offset = %d)\n", + size, (int)(inbuf2 - inbuf) )); exit_server_cleanly("Bad chained packet"); return(-1); } -- cgit From c4d42829a5c0e9d2bf7d706ff627117a2c678526 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 May 2007 08:22:59 +0000 Subject: r22693: Always compile before checkin.... I've now installed dmapi on my laptop :-) (This used to be commit 7460511c4e92f6fdde430d0c56bbb72377e80b4b) --- source3/smbd/dmapi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 23b5d5e947..c433a7329e 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -153,7 +153,8 @@ retry: /* No session already defined. */ if (dmapi_session == DM_NO_SESSION) { err = dm_create_session(DM_NO_SESSION, - CONST_DISCARD(DMAPI_SESSION_NAME), + CONST_DISCARD(char *, + DMAPI_SESSION_NAME), &dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, -- cgit From bf7008abb8c79c0d4c86d60408b03e419a1dc0dc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 May 2007 13:46:30 +0000 Subject: r22695: Dummy checkin (reformatting) to make the AIX hosts retry. (This used to be commit cd55ccef6a1d0c95836feeb5efb5abcaedb35df2) --- source3/smbd/process.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 44baa96059..4ae6dcd5ba 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -144,11 +144,11 @@ void schedule_deferred_open_smb_message(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { uint16 msg_mid = SVAL(pml->buf.data,smb_mid); - DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++, - (unsigned int)msg_mid )); + DEBUG(10, ("schedule_deferred_open_smb_message: [%d] " + "msg_mid = %u\n", i++, (unsigned int)msg_mid )); if (mid == msg_mid) { - DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n", - mid )); + DEBUG(10, ("schedule_deferred_open_smb_message: " + "scheduling mid %u\n", mid)); pml->end_time.tv_sec = 0; pml->end_time.tv_usec = 0; DLIST_PROMOTE(deferred_open_queue, pml); @@ -156,8 +156,8 @@ void schedule_deferred_open_smb_message(uint16 mid) } } - DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n", - mid )); + DEBUG(10, ("schedule_deferred_open_smb_message: failed to find " + "message mid %u\n", mid )); } /**************************************************************************** -- cgit From e6383f47629368d9dd4e803f17566a24e9d7359e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 09:35:35 +0000 Subject: r22736: Start to merge the low-hanging fruit from the now 7000-line cluster patch. This changes "struct process_id" to "struct server_id", keeping both is just too much hassle. No functional change (I hope ;-)) Volker (This used to be commit 0ad4b1226c9d91b72136310d3bbb640d2c5d67b8) --- source3/smbd/blocking.c | 6 +++--- source3/smbd/conn.c | 2 +- source3/smbd/notify_internal.c | 2 +- source3/smbd/open.c | 2 +- source3/smbd/oplock.c | 10 +++++----- source3/smbd/pipes.c | 2 +- source3/smbd/server.c | 14 +++++++------- 7 files changed, 19 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index d0caa29597..7fe9f0c3c7 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -73,7 +73,7 @@ static BOOL in_chained_smb(void) return (chain_size != 0); } -static void received_unlock_msg(int msg_type, struct process_id src, +static void received_unlock_msg(int msg_type, struct server_id src, void *buf, size_t len, void *private_data); static void process_blocking_lock_queue(void); @@ -645,7 +645,7 @@ BOOL blocking_lock_was_deferred(int mid) Set a flag as an unlock request affects one of our pending locks. *****************************************************************************/ -static void received_unlock_msg(int msg_type, struct process_id src, +static void received_unlock_msg(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { @@ -807,7 +807,7 @@ static void process_blocking_lock_queue(void) #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS)) static void process_blocking_lock_cancel_message(int msg_type, - struct process_id src, + struct server_id src, void *buf, size_t len, void *private_data) { diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index a15684a35b..d126bd39e6 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -319,7 +319,7 @@ the message contains just a share name and all instances of that share are unmounted the special sharename '*' forces unmount of all shares ****************************************************************************/ -void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len, +void msg_force_tdis(int msg_type, struct server_id pid, void *buf, size_t len, void *private_data) { connection_struct *conn, *next; diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 9f23db6671..940ff8aae9 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -677,7 +677,7 @@ void notify_trigger(struct notify_context *notify, DEBUG(10, ("Deleting notify entries for " "process %s because it's gone\n", - procid_str_static(&e->server.id))); + procid_str_static(&e->server))); notify_remove_all(notify, &server); goto again; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f959f00b10..e891209d2b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2247,7 +2247,7 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, smbd process. ****************************************************************************/ -void msg_file_was_renamed(int msg_type, struct process_id src, +void msg_file_was_renamed(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { files_struct *fsp; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 26ee52b797..8a84331810 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -391,7 +391,7 @@ static void add_oplock_timeout_handler(files_struct *fsp) the client for LEVEL2. *******************************************************************/ -static void process_oplock_async_level2_break_message(int msg_type, struct process_id src, +static void process_oplock_async_level2_break_message(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { @@ -478,7 +478,7 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce This handles the generic oplock break message from another smbd. *******************************************************************/ -static void process_oplock_break_message(int msg_type, struct process_id src, +static void process_oplock_break_message(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { @@ -587,7 +587,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, This handles the kernel oplock break message. *******************************************************************/ -static void process_kernel_oplock_break(int msg_type, struct process_id src, +static void process_kernel_oplock_break(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { @@ -679,7 +679,7 @@ void reply_to_oplock_break_requests(files_struct *fsp) return; } -static void process_oplock_break_response(int msg_type, struct process_id src, +static void process_oplock_break_response(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { @@ -707,7 +707,7 @@ static void process_oplock_break_response(int msg_type, struct process_id src, schedule_deferred_open_smb_message(msg.op_mid); } -static void process_open_retry_message(int msg_type, struct process_id src, +static void process_open_retry_message(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index bec2f19f86..aba2fe69c5 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -37,7 +37,7 @@ #define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d" struct pipe_dbrec { - struct process_id pid; + struct server_id pid; int pnum; uid_t uid; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3422290a90..1020ad3aca 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -87,7 +87,7 @@ struct messaging_context *smbd_messaging_context(void) What to do when smb.conf is updated. ********************************************************************/ -static void smb_conf_updated(int msg_type, struct process_id src, +static void smb_conf_updated(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n")); @@ -99,7 +99,7 @@ static void smb_conf_updated(int msg_type, struct process_id src, Delete a statcache entry. ********************************************************************/ -static void smb_stat_cache_delete(int msg_type, struct process_id src, +static void smb_stat_cache_delete(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { const char *name = (const char *)buf; @@ -150,7 +150,7 @@ static void killkids(void) somewhere else. ****************************************************************************/ -static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid), +static void msg_sam_sync(int UNUSED(msg_type), struct server_id UNUSED(pid), void *UNUSED(buf), size_t UNUSED(len), void *private_data) { @@ -162,7 +162,7 @@ static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid), somewhere else. ****************************************************************************/ -static void msg_sam_repl(int msg_type, struct process_id pid, +static void msg_sam_repl(int msg_type, struct server_id pid, void *buf, size_t len, void *private_data) { uint32 low_serial; @@ -196,7 +196,7 @@ static BOOL open_sockets_inetd(void) return True; } -static void msg_exit_server(int msg_type, struct process_id src, +static void msg_exit_server(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { DEBUG(3, ("got a SHUTDOWN message\n")); @@ -204,7 +204,7 @@ static void msg_exit_server(int msg_type, struct process_id src, } #ifdef DEVELOPER -static void msg_inject_fault(int msg_type, struct process_id src, +static void msg_inject_fault(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { int sig; @@ -921,7 +921,7 @@ extern void build_options(BOOL screen); } if (profile_level != NULL) { int pl = atoi(profile_level); - struct process_id src; + struct server_id src; DEBUG(1, ("setting profiling level: %s\n",profile_level)); src.pid = getpid(); -- cgit From 71921605995fa95d84301534760a6bc2db3fa74b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 15:07:49 +0000 Subject: r22747: Fix some C++ warnings (This used to be commit a66a04e9f11f6c4462f2b56b447bae4eca7b177c) --- source3/smbd/seal.c | 9 +++------ source3/smbd/sesssetup.c | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 07ef186e2e..c4d60b0a60 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -492,8 +492,7 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* Return the context we're using for this encryption state. */ - *pparam = SMB_MALLOC(2); - if (!*pparam) { + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { return NT_STATUS_NO_MEMORY; } SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); @@ -542,8 +541,7 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* Return the context we're using for this encryption state. */ - *pparam = SMB_MALLOC(2); - if (!*pparam) { + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { return NT_STATUS_NO_MEMORY; } SSVAL(*pparam,0,ec->es->enc_ctx_num); @@ -593,8 +591,7 @@ static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* Return the context we're using for this encryption state. */ - *pparam = SMB_MALLOC(2); - if (!*pparam) { + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { return NT_STATUS_NO_MEMORY; } SSVAL(*pparam,0,ec->es->enc_ctx_num); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 188b7bfb81..7dbf20a189 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -990,8 +990,7 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB } /* We must store this blob until complete. */ - pad = SMB_MALLOC(sizeof(struct pending_auth_data)); - if (!pad) { + if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) { return NT_STATUS_NO_MEMORY; } pad->needed_len = needed_len - pblob->length; -- cgit From 76ce309234adbe0a6a56b849a91714cab148c4a7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 15:31:12 +0000 Subject: r22751: Next step for the cluster merge: sessionid.tdb should contain a 'struct server_id' instead of a 'uint32 pid' (This used to be commit be7bac55c37676a8137c59a22dfb2e4c4821ac21) --- source3/smbd/session.c | 2 +- source3/smbd/sesssetup.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 30ade8aedf..cd7511430e 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -60,7 +60,7 @@ BOOL session_claim(user_struct *vuser) struct sockaddr sa; struct in_addr *client_ip; struct sessionid sessionid; - uint32 pid = (uint32)sys_getpid(); + struct server_id pid = procid_self(); fstring keystr; char * hostname; int tdb_store_flag; /* If using utmp, we do an inital 'lock hold' store, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7dbf20a189..d6cdf777d8 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1180,11 +1180,11 @@ static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, struct sessionid *sessionid = (struct sessionid *)dbuf.dptr; const char *ip = (const char *)p; - if (!process_exists(pid_to_procid(sessionid->pid))) { + if (!process_exists(sessionid->pid)) { return 0; } - if (sessionid->pid == sys_getpid()) { + if (procid_is_me(&sessionid->pid)) { return 0; } @@ -1192,7 +1192,7 @@ static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, return 0; } - message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN, + message_send_pid(sessionid->pid, MSG_SHUTDOWN, NULL, 0, True); return 0; } -- cgit From 87d18ac48853e1d63d127b03ea6dbc7568e334f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 20:53:10 +0000 Subject: r22755: Second half of r22754. As it stands now, string_replace expects a pstring. Give it one, although I hate putting it in :-) Thanks to Tom Bork! :-) (This used to be commit f4ea3fd36543120fa7d712e6e650c704e4e23759) --- source3/smbd/notify.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d18bbb180f..b2ac26764a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -337,7 +337,7 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter, static void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; - char *name2; + pstring name2; if (fsp->notify == NULL) { /* @@ -346,11 +346,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) return; } - if (!(name2 = talloc_strdup(fsp->notify, name))) { - DEBUG(0, ("talloc_strdup failed\n")); - return; - } - + pstrcpy(name2, name); string_replace(name2, '/', '\\'); /* @@ -364,7 +360,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) * guard against a DoS here. */ TALLOC_FREE(fsp->notify->changes); - TALLOC_FREE(name2); fsp->notify->num_changes = -1; return; } @@ -377,7 +372,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { DEBUG(0, ("talloc_realloc failed\n")); - TALLOC_FREE(name2); return; } @@ -385,7 +379,11 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) change = &(fsp->notify->changes[fsp->notify->num_changes]); - change->name = talloc_move(changes, &name2); + if (!(change->name = talloc_strdup(changes, name2))) { + DEBUG(0, ("talloc_strdup failed\n")); + return; + } + change->action = action; fsp->notify->num_changes += 1; @@ -401,7 +399,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) * We have to send the two rename events in one reply. So hold * the first part back. */ - return; + return; } /* -- cgit From 4aa44f7475e03dcc596f6a13fffffda7268074a1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 8 May 2007 13:44:36 +0000 Subject: r22761: This introduces lib/conn_tdb.c with two main functions: connections_traverse and connections_forall. This centralizes all the routines that did individual tdb_open("connections.tdb") and direct tdb_traverse. Volker (This used to be commit e43e94cda1ad8876b3cb5d1129080b57fa6ec214) --- source3/smbd/connection.c | 29 ++++++++--------------------- source3/smbd/lanman.c | 3 ++- source3/smbd/server.c | 2 +- source3/smbd/statcache.c | 3 +-- 4 files changed, 12 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index e609b90a50..b9cdede69e 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -20,21 +20,6 @@ #include "includes.h" -static TDB_CONTEXT *tdb; - -/**************************************************************************** - Return the connection tdb context (used for message send all). -****************************************************************************/ - -TDB_CONTEXT *conn_tdb_ctx(void) -{ - if (!tdb) - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644); - - return tdb; -} - static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey) { ZERO_STRUCTP(pkey); @@ -62,6 +47,7 @@ BOOL yield_connection(connection_struct *conn, const char *name) { struct connections_key key; TDB_DATA kbuf; + TDB_CONTEXT *tdb = conn_tdb_ctx(True); if (!tdb) return False; @@ -112,7 +98,7 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", procid_str_static(&crec.pid), crec.cnum, crec.servicename)); if (tdb_delete(the_tdb, kbuf) != 0) - DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) )); + DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(the_tdb) )); return 0; } @@ -139,6 +125,7 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u int count_current_connections( const char *sharename, BOOL clear ) { struct count_stat cs; + TDB_CONTEXT *tdb = conn_tdb_ctx(True); cs.mypid = sys_getpid(); cs.curr_connections = 0; @@ -184,11 +171,10 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti struct connections_key key; struct connections_data crec; TDB_DATA kbuf, dbuf; + TDB_CONTEXT *tdb = conn_tdb_ctx(True); if (!tdb) { - if ( (tdb =conn_tdb_ctx()) == NULL ) { - return False; - } + return False; } /* @@ -245,6 +231,7 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) struct connections_key key; struct connections_data *pcrec; TDB_DATA kbuf, dbuf; + TDB_CONTEXT *tdb = conn_tdb_ctx(True); if (!tdb) return False; @@ -344,7 +331,7 @@ BOOL store_pipe_opendb( smb_np_struct *p ) data.dptr = (uint8 *)prec; data.dsize = sizeof(struct pipe_open_rec); - if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) { + if ( (pipe_tdb = conn_tdb_ctx(True) ) == NULL ) { goto done; } @@ -375,7 +362,7 @@ BOOL delete_pipe_opendb( smb_np_struct *p ) goto done; } - if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) { + if ( (pipe_tdb = conn_tdb_ctx(True) ) == NULL ) { goto done; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 05b1e812b2..b235fd1698 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1894,7 +1894,8 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, goto error_exit; } else { SAFE_FREE(command); - message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); + message_send_all(MSG_SMB_CONF_UPDATED, NULL, 0, + False, NULL); } } else { return False; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1020ad3aca..b869a1a48e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -987,7 +987,7 @@ extern void build_options(BOOL screen); if (!session_init()) exit(1); - if (conn_tdb_ctx() == NULL) + if (!connections_init(True)) exit(1); if (!locking_init(0)) diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index e257483f81..7c2c968d8d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -292,8 +292,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, void send_stat_cache_delete_message(const char *name) { #ifdef DEVELOPER - message_send_all(conn_tdb_ctx(), - MSG_SMB_STAT_CACHE_DELETE, + message_send_all(MSG_SMB_STAT_CACHE_DELETE, name, strlen(name)+1, True, -- cgit From 1e6e3f82798d31bc7f5d33d84b5413c4d7f91e97 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 May 2007 00:52:46 +0000 Subject: r22765: Fix from Alison Winters for missing return in sendfilereadbraw. Jeremy. (This used to be commit b523e782b0f3a3899e5f448698fbecddd59f4369) --- source3/smbd/reply.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1acd78a106..8748c1cd23 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2238,6 +2238,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st exit_server_cleanly("send_file_readbraw sendfile failed"); } + return; } normal_readbraw: -- cgit From 2383ffce6993a70abffcbabdf2e6ebb0d8ccd756 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 11 May 2007 07:22:10 +0000 Subject: r22784: fixed change notify for delete on close (This used to be commit 6f52435a72427a8264096ac14bad54020c9d852b) --- source3/smbd/close.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 1c9f6ea8c4..2eb3a3e13c 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -287,6 +287,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, status = map_nt_error_from_unix(errno); } + notify_fname(conn, NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME, + fsp->fsp_name); + /* As we now have POSIX opens which can unlink * with other open files we may have taken * this code path with more than one share mode -- cgit From b4a7b7a8889737e2891fc1176feabd4ce47f2737 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 May 2007 12:16:20 +0000 Subject: r22844: Introduce const DATA_BLOB data_blob_null = { NULL, 0, NULL }; and replace all data_blob(NULL, 0) calls. (This used to be commit 3d3d61687ef00181f4f04e001d42181d93ac931e) --- source3/smbd/negprot.c | 2 +- source3/smbd/seal.c | 22 +++++++++++----------- source3/smbd/service.c | 4 ++-- source3/smbd/sesssetup.c | 20 ++++++++++---------- 4 files changed, 24 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 1722c81d2a..12b1e84600 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -229,7 +229,7 @@ static DATA_BLOB negprot_spnego(void) strlower_m(myname); asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm()); if (host_princ_s == NULL) { - blob = data_blob(NULL, 0); + blob = data_blob_null; return blob; } blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s); diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index c4d60b0a60..5d8ef9b63c 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -346,8 +346,8 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d OM_uint32 flags = 0; gss_buffer_desc in_buf, out_buf; struct smb_tran_enc_state_gss *gss_state; - DATA_BLOB auth_reply = data_blob(NULL,0); - DATA_BLOB response = data_blob(NULL,0); + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; NTSTATUS status; if (!partial_srv_trans_enc_ctx) { @@ -419,8 +419,8 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap) { NTSTATUS status; - DATA_BLOB chal = data_blob(NULL, 0); - DATA_BLOB response = data_blob(NULL, 0); + DATA_BLOB chal = data_blob_null; + DATA_BLOB response = data_blob_null; status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); if (!NT_STATUS_IS_OK(status)) { @@ -459,8 +459,8 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, size_t *p_param_size) { NTSTATUS status; - DATA_BLOB blob = data_blob(NULL,0); - DATA_BLOB secblob = data_blob(NULL, 0); + DATA_BLOB blob = data_blob_null; + DATA_BLOB secblob = data_blob_null; BOOL got_kerberos_mechanism = False; blob = data_blob_const(*ppdata, *p_data_size); @@ -514,10 +514,10 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, size_t *p_param_size) { NTSTATUS status; - DATA_BLOB blob = data_blob(NULL,0); - DATA_BLOB auth = data_blob(NULL,0); - DATA_BLOB auth_reply = data_blob(NULL,0); - DATA_BLOB response = data_blob(NULL,0); + DATA_BLOB blob = data_blob_null; + DATA_BLOB auth = data_blob_null; + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; /* We must have a partial context here. */ @@ -567,7 +567,7 @@ static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, { NTSTATUS status; DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); - DATA_BLOB response = data_blob(NULL,0); + DATA_BLOB response = data_blob_null; struct smb_srv_trans_enc_ctx *ec; if (!partial_srv_trans_enc_ctx) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 79c618e7b3..6d2cdff594 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1230,7 +1230,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, if (strequal(service_in,HOMES_NAME)) { if(lp_security() != SEC_SHARE) { - DATA_BLOB no_pw = data_blob(NULL, 0); + DATA_BLOB no_pw = data_blob_null; if (vuser->homes_snum == -1) { DEBUG(2, ("[homes] share not available for " "this user because it was not found " @@ -1266,7 +1266,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) && strequal(service_in, lp_servicename(vuser->homes_snum))) { - DATA_BLOB no_pw = data_blob(NULL, 0); + DATA_BLOB no_pw = data_blob_null; DEBUG(5, ("making a connection to 'homes' service [%s] " "created at session setup time\n", service_in)); return make_connection_snum(vuser->homes_snum, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index d6cdf777d8..dcff27f70c 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -177,7 +177,7 @@ static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out) char *host_princ_s = NULL; BOOL ret = False; - *pblob_out = data_blob(NULL,0); + *pblob_out = data_blob_null; initialize_krb5_error_table(); kerr = krb5_init_context(&context); @@ -243,9 +243,9 @@ static int reply_spnego_kerberos(connection_struct *conn, PAC_DATA *pac_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; - DATA_BLOB session_key = data_blob(NULL, 0); + DATA_BLOB session_key = data_blob_null; uint8 tok_id[2]; - DATA_BLOB nullblob = data_blob(NULL, 0); + DATA_BLOB nullblob = data_blob_null; fstring real_username; BOOL map_domainuser_to_guest = False; BOOL username_was_mapped; @@ -539,7 +539,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (NT_STATUS_IS_OK(ret)) { ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); } else { - ap_rep_wrapped = data_blob(NULL, 0); + ap_rep_wrapped = data_blob_null; } response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); reply_sesssetup_blob(conn, inbuf, outbuf, response, ret); @@ -582,7 +582,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; - DATA_BLOB nullblob = data_blob(NULL, 0); + DATA_BLOB nullblob = data_blob_null; DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); /* register_vuid keeps the server info */ @@ -748,9 +748,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DATA_BLOB blob1, AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { - DATA_BLOB auth = data_blob(NULL,0); - DATA_BLOB auth_reply = data_blob(NULL,0); - DATA_BLOB secblob = data_blob(NULL,0); + DATA_BLOB auth = data_blob_null; + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB secblob = data_blob_null; NTSTATUS status = NT_STATUS_INVALID_PARAMETER; if (!spnego_parse_auth(blob1, &auth)) { @@ -1089,7 +1089,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, } if (!vuser) { - vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL); + vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL); if (vuid == UID_FIELD_INVALID ) { data_blob_free(&blob1); return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); @@ -1509,7 +1509,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (server_info->user_session_key.data) { session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); } else { - session_key = data_blob(NULL, 0); + session_key = data_blob_null; } data_blob_clear_free(&plaintext_password); -- cgit From b92064fcfd804b861e2f5125078812d83b9120a6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 May 2007 13:01:28 +0000 Subject: r22846: Chunk one to replace message_send_pid with messaging_send: Deep inside locking/locking.c we have to send retry messages to timed lock holders. The majority of this patch passes a "struct messaging_context" down there. No functional change, survives make test. (This used to be commit bbb508414683eeddd2ee0d2d36fe620118180bbb) --- source3/smbd/blocking.c | 11 +++++++---- source3/smbd/close.c | 2 +- source3/smbd/reply.c | 24 ++++++++++++++++-------- source3/smbd/trans2.c | 6 ++++-- 4 files changed, 28 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 7fe9f0c3c7..ab2b0949bd 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -195,7 +195,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, blr->length = length; /* Add a pending lock record for this. */ - status = brl_lock(br_lck, + status = brl_lock(smbd_messaging_context(), br_lck, lock_pid, procid_self(), offset, @@ -355,7 +355,8 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) * request would never have been queued. JRA. */ - do_unlock(fsp, + do_unlock(smbd_messaging_context(), + fsp, lock_pid, count, offset, @@ -435,7 +436,8 @@ static BOOL process_lockingX(blocking_lock_record *blr) * request would never have been queued. JRA. */ errno = 0; - br_lck = do_lock(fsp, + br_lck = do_lock(smbd_messaging_context(), + fsp, lock_pid, count, offset, @@ -496,7 +498,8 @@ static BOOL process_trans2(blocking_lock_record *blr) char *outbuf; char params[2]; NTSTATUS status; - struct byte_range_lock *br_lck = do_lock(blr->fsp, + struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(), + blr->fsp, blr->lock_pid, blr->count, blr->offset, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 2eb3a3e13c..ca4e501a14 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -352,7 +352,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ release_file_oplock(fsp); } - locking_close_file(fsp); + locking_close_file(smbd_messaging_context(), fsp); status = fd_close(conn, fsp); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8748c1cd23..5353e392b1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2415,7 +2415,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length * Note that the requested lock size is unaffected by max_recv. */ - br_lck = do_lock(fsp, + br_lck = do_lock(smbd_messaging_context(), + fsp, (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, @@ -2917,7 +2918,8 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, } if (numtowrite) { - status = do_unlock(fsp, + status = do_unlock(smbd_messaging_context(), + fsp, (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, @@ -3420,7 +3422,8 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); - br_lck = do_lock(fsp, + br_lck = do_lock(smbd_messaging_context(), + fsp, (uint32)SVAL(inbuf,smb_pid), count, offset, @@ -3458,7 +3461,8 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); - status = do_unlock(fsp, + status = do_unlock(smbd_messaging_context(), + fsp, (uint32)SVAL(inbuf,smb_pid), count, offset, @@ -4144,7 +4148,8 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l } /* Send messages to all smbd's (not ourself) that the name has changed. */ - rename_share_filename(lck, conn->connectpath, newname); + rename_share_filename(smbd_messaging_context(), lck, conn->connectpath, + newname); } /**************************************************************************** @@ -5453,7 +5458,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, "pid %u, file %s\n", (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); - status = do_unlock(fsp, + status = do_unlock(smbd_messaging_context(), + fsp, lock_pid, count, offset, @@ -5526,7 +5532,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, BOOL defer_lock = False; struct byte_range_lock *br_lck; - br_lck = do_lock(fsp, + br_lck = do_lock(smbd_messaging_context(), + fsp, lock_pid, count, offset, @@ -5612,7 +5619,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_DOS(ERRDOS,ERRnoaccess); } - do_unlock(fsp, + do_unlock(smbd_messaging_context(), + fsp, lock_pid, count, offset, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 91218fe9f4..1c55684330 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4805,13 +4805,15 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, (double)offset )); if (lock_type == UNLOCK_LOCK) { - status = do_unlock(fsp, + status = do_unlock(smbd_messaging_context(), + fsp, lock_pid, count, offset, POSIX_LOCK); } else { - struct byte_range_lock *br_lck = do_lock(fsp, + struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(), + fsp, lock_pid, count, offset, -- cgit From fad7dd8a60e6637598b17fa89ec92d98db51fffe Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 May 2007 20:31:28 +0000 Subject: r22868: Replace some message_send_pid calls with messaging_send_pid calls. More tomorrow. (This used to be commit 74fa57ca5d7fa8eace72bbe948a08a0bca3cc4ca) --- source3/smbd/blocking.c | 6 +- source3/smbd/close.c | 6 +- source3/smbd/open.c | 6 +- source3/smbd/oplock.c | 142 +++++++++++++++++++++++++---------------------- source3/smbd/process.c | 6 +- source3/smbd/server.c | 8 ++- source3/smbd/sesssetup.c | 4 +- 7 files changed, 98 insertions(+), 80 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ab2b0949bd..ae7b861f2b 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -893,9 +893,9 @@ BOOL blocking_lock_cancel(files_struct *fsp, memcpy(msg, &blr, sizeof(blr)); memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS)); - message_send_pid(pid_to_procid(sys_getpid()), - MSG_SMB_BLOCKING_LOCK_CANCEL, - &msg, sizeof(msg), True); + messaging_send_buf(smbd_messaging_context(), procid_self(), + MSG_SMB_BLOCKING_LOCK_CANCEL, + (uint8 *)&msg, sizeof(msg)); return True; } diff --git a/source3/smbd/close.c b/source3/smbd/close.c index ca4e501a14..38b4988415 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -135,8 +135,10 @@ static void notify_deferred_opens(struct share_mode_lock *lck) share_mode_entry_to_message(msg, e); - message_send_pid(e->pid, MSG_SMB_OPEN_RETRY, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + messaging_send_buf(smbd_messaging_context(), + e->pid, MSG_SMB_OPEN_RETRY, + (uint8 *)msg, + MSG_SMB_SHARE_MODE_ENTRY_SIZE); } } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e891209d2b..35dc13d86c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -737,8 +737,10 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + status = messaging_send_buf(smbd_messaging_context(), exclusive->pid, + MSG_SMB_BREAK_REQUEST, + (uint8 *)msg, + MSG_SMB_SHARE_MODE_ENTRY_SIZE); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not send oplock break message: %s\n", nt_errstr(status))); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8a84331810..63f88b7824 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -62,7 +62,7 @@ BOOL oplock_message_waiting(fd_set *fds) we're calling this in a shutting down state. ****************************************************************************/ -void process_kernel_oplocks(fd_set *pfds) +void process_kernel_oplocks(struct messaging_context *msg_ctx, fd_set *pfds) { /* * We need to check for kernel oplocks before going into the select @@ -94,9 +94,9 @@ void process_kernel_oplocks(fd_set *pfds) /* Don't need to be root here as we're only ever sending to ourselves. */ - message_send_pid(pid_to_procid(sys_getpid()), - MSG_SMB_KERNEL_BREAK, - &msg, MSG_SMB_KERNEL_BREAK_SIZE, True); + messaging_send_buf(msg_ctx, procid_self(), + MSG_SMB_KERNEL_BREAK, + (uint8 *)&msg, MSG_SMB_KERNEL_BREAK_SIZE); } } @@ -391,27 +391,29 @@ static void add_oplock_timeout_handler(files_struct *fsp) the client for LEVEL2. *******************************************************************/ -static void process_oplock_async_level2_break_message(int msg_type, struct server_id src, - void *buf, size_t len, - void *private_data) +static void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) { struct share_mode_entry msg; files_struct *fsp; char *break_msg; BOOL sign_state; - if (buf == NULL) { + if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); return; } - if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { - DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { + DEBUG(0, ("Got invalid msg len %d\n", (int)data->length)); return; } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, (char *)buf); + message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, @@ -478,9 +480,11 @@ static void process_oplock_async_level2_break_message(int msg_type, struct serve This handles the generic oplock break message from another smbd. *******************************************************************/ -static void process_oplock_break_message(int msg_type, struct server_id src, - void *buf, size_t len, - void *private_data) +static void process_oplock_break_message(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) { struct share_mode_entry msg; files_struct *fsp; @@ -488,18 +492,18 @@ static void process_oplock_break_message(int msg_type, struct server_id src, BOOL break_to_level2 = False; BOOL sign_state; - if (buf == NULL) { + if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); return; } - if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { - DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { + DEBUG(0, ("Got invalid msg len %d\n", (int)data->length)); return; } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, (char *)buf); + message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, @@ -515,8 +519,9 @@ static void process_oplock_break_message(int msg_type, struct server_id src, DEBUG(3, ("Did not find fsp\n")); /* We just send the same message back. */ - message_send_pid(src, MSG_SMB_BREAK_RESPONSE, - buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE, + (uint8 *)data->data, + MSG_SMB_SHARE_MODE_ENTRY_SIZE); return; } @@ -536,8 +541,9 @@ static void process_oplock_break_message(int msg_type, struct server_id src, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fsp_name)); /* We just send the same message back. */ - message_send_pid(src, MSG_SMB_BREAK_RESPONSE, - buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE, + (uint8 *)data->data, + MSG_SMB_SHARE_MODE_ENTRY_SIZE); return; } @@ -587,9 +593,11 @@ static void process_oplock_break_message(int msg_type, struct server_id src, This handles the kernel oplock break message. *******************************************************************/ -static void process_kernel_oplock_break(int msg_type, struct server_id src, - void *buf, size_t len, - void *private_data) +static void process_kernel_oplock_break(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) { SMB_DEV_T dev; SMB_INO_T inode; @@ -598,20 +606,20 @@ static void process_kernel_oplock_break(int msg_type, struct server_id src, char *break_msg; BOOL sign_state; - if (buf == NULL) { + if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); return; } - if (len != MSG_SMB_KERNEL_BREAK_SIZE) { - DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) { + DEBUG(0, ("Got invalid msg len %d\n", (int)data->length)); return; } /* Pull the data from the message. */ - dev = DEV_T_VAL(buf, 0); - inode = INO_T_VAL(buf, 8); - file_id = (unsigned long)IVAL(buf, 16); + dev = DEV_T_VAL(data->data, 0); + inode = INO_T_VAL(data->data, 8); + file_id = (unsigned long)IVAL(data->data, 16); DEBUG(10, ("Got kernel oplock break message from pid %d: 0x%x/%.0f/%u\n", (int)procid_to_pid(&src), (unsigned int)dev, (double)inode, @@ -665,8 +673,10 @@ void reply_to_oplock_break_requests(files_struct *fsp) share_mode_entry_to_message(msg, e); - message_send_pid(e->pid, MSG_SMB_BREAK_RESPONSE, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + messaging_send_buf(smbd_messaging_context(), e->pid, + MSG_SMB_BREAK_RESPONSE, + (uint8 *)msg, + MSG_SMB_SHARE_MODE_ENTRY_SIZE); } SAFE_FREE(fsp->pending_break_messages); @@ -679,24 +689,27 @@ void reply_to_oplock_break_requests(files_struct *fsp) return; } -static void process_oplock_break_response(int msg_type, struct server_id src, - void *buf, size_t len, - void *private_data) +static void process_oplock_break_response(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) { struct share_mode_entry msg; - if (buf == NULL) { + if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); return; } - if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { - DEBUG(0, ("Got invalid msg len %u\n", (unsigned int)len)); + if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { + DEBUG(0, ("Got invalid msg len %u\n", + (unsigned int)data->length)); return; } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, (char *)buf); + message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, @@ -707,24 +720,26 @@ static void process_oplock_break_response(int msg_type, struct server_id src, schedule_deferred_open_smb_message(msg.op_mid); } -static void process_open_retry_message(int msg_type, struct server_id src, - void *buf, size_t len, - void *private_data) +static void process_open_retry_message(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) { struct share_mode_entry msg; - if (buf == NULL) { + if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); return; } - if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { - DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) { + DEBUG(0, ("Got invalid msg len %d\n", (int)data->length)); return; } /* De-linearize incoming message. */ - message_to_share_mode_entry(&msg, (char *)buf); + message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n", (int)procid_to_pid(&src), (unsigned int)msg.dev, @@ -804,8 +819,10 @@ void release_level_2_oplocks_on_change(files_struct *fsp) share_mode_entry_to_message(msg, share_entry); - message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + messaging_send_buf(smbd_messaging_context(), share_entry->pid, + MSG_SMB_ASYNC_LEVEL2_BREAK, + (uint8 *)msg, + MSG_SMB_SHARE_MODE_ENTRY_SIZE); } /* We let the message receivers handle removing the oplock state @@ -860,25 +877,20 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) Setup oplocks for this process. ****************************************************************************/ -BOOL init_oplocks(void) +BOOL init_oplocks(struct messaging_context *msg_ctx) { DEBUG(3,("init_oplocks: initializing messages.\n")); - message_register(MSG_SMB_BREAK_REQUEST, - process_oplock_break_message, - NULL); - message_register(MSG_SMB_ASYNC_LEVEL2_BREAK, - process_oplock_async_level2_break_message, - NULL); - message_register(MSG_SMB_BREAK_RESPONSE, - process_oplock_break_response, - NULL); - message_register(MSG_SMB_KERNEL_BREAK, - process_kernel_oplock_break, - NULL); - message_register(MSG_SMB_OPEN_RETRY, - process_open_retry_message, - NULL); + messaging_register(msg_ctx, NULL, MSG_SMB_BREAK_REQUEST, + process_oplock_break_message); + messaging_register(msg_ctx, NULL, MSG_SMB_ASYNC_LEVEL2_BREAK, + process_oplock_async_level2_break_message); + messaging_register(msg_ctx, NULL, MSG_SMB_BREAK_RESPONSE, + process_oplock_break_response); + messaging_register(msg_ctx, NULL, MSG_SMB_KERNEL_BREAK, + process_kernel_oplock_break); + messaging_register(msg_ctx, NULL, MSG_SMB_OPEN_RETRY, + process_open_retry_message); if (lp_kernel_oplocks()) { #if HAVE_KERNEL_OPLOCKS_IRIX diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4ae6dcd5ba..02dc507e11 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -301,7 +301,7 @@ static void async_processing(fd_set *pfds) process_aio_queue(); - process_kernel_oplocks(pfds); + process_kernel_oplocks(smbd_messaging_context(), pfds); /* Do the aio check again after receive_local_message as it does a select and may have eaten our signal. */ @@ -574,7 +574,7 @@ void respond_to_all_remaining_local_messages(void) return; } - process_kernel_oplocks(NULL); + process_kernel_oplocks(smbd_messaging_context(), NULL); return; } @@ -1415,7 +1415,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); /* Send any queued printer notify message to interested smbd's. */ - print_notify_send_messages(0); + print_notify_send_messages(smbd_messaging_context(), 0); /* * Modify the select timeout depending upon diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b869a1a48e..9cdc083bf6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -646,7 +646,8 @@ static void exit_server_common(enum server_exit_reason how, invalidate_all_vuids(); - print_notify_send_messages(3); /* 3 second timeout. */ + /* 3 second timeout. */ + print_notify_send_messages(smbd_messaging_context(), 3); /* delete our entry in the connections database. */ yield_connection(NULL,""); @@ -755,7 +756,8 @@ static BOOL deadtime_fn(const struct timeval *now, void *private_data) if ((conn_num_open() == 0) || (conn_idle_all(now->tv_sec))) { DEBUG( 2, ( "Closing idle connection\n" ) ); - message_send_pid(procid_self(), MSG_SHUTDOWN, NULL, 0, False); + messaging_send(smbd_messaging_context(), procid_self(), + MSG_SHUTDOWN, &data_blob_null); return False; } @@ -1062,7 +1064,7 @@ extern void build_options(BOOL screen); } /* Setup oplocks */ - if (!init_oplocks()) + if (!init_oplocks(smbd_messaging_context())) exit(1); /* Setup aio signal handler. */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index dcff27f70c..ccfc22598d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1192,8 +1192,8 @@ static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, return 0; } - message_send_pid(sessionid->pid, MSG_SHUTDOWN, - NULL, 0, True); + messaging_send(smbd_messaging_context(), sessionid->pid, MSG_SHUTDOWN, + &data_blob_null); return 0; } -- cgit From 8f9369f2e627cf2da4f5902be570200a9d2b1a67 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 15 May 2007 12:18:17 +0000 Subject: r22900: Convert profile/ to messaging_send_pid/messaging_register (This used to be commit edbeea520727f51568ccd8ffa802e06bd120794c) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9cdc083bf6..ca54b2471d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -917,7 +917,7 @@ extern void build_options(BOOL screen); init_structs(); #ifdef WITH_PROFILE - if (!profile_setup(False)) { + if (!profile_setup(smbd_messaging_context(), False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); return -1; } -- cgit From 84758bd1f8633d3efe30e293887596db6bfd5e5b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 15 May 2007 15:14:32 +0000 Subject: r22908: All callers of message_init now also call messaging_init. Unify those. (This used to be commit 330946ad2307ca34f0a8d068a0193fcb8a0d6036) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ca54b2471d..f227579c04 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -967,7 +967,7 @@ extern void build_options(BOOL screen); } /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ - if (!message_init()) + if (smbd_messaging_context() == NULL) exit(1); /* Initialise the password backed before the global_sam_sid -- cgit From 8c3f8e5697f29f1a9829298e0561ff7305b62082 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 15 May 2007 15:49:55 +0000 Subject: r22911: Pass a messaging_context to message_send_all (This used to be commit cc92ce665dcfe9054d09429219883b18a4cab090) --- source3/smbd/lanman.c | 3 ++- source3/smbd/statcache.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b235fd1698..fae6312080 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1894,7 +1894,8 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, goto error_exit; } else { SAFE_FREE(command); - message_send_all(MSG_SMB_CONF_UPDATED, NULL, 0, + message_send_all(smbd_messaging_context(), + MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); } } else { diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 7c2c968d8d..1d6646257a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -292,7 +292,8 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, void send_stat_cache_delete_message(const char *name) { #ifdef DEVELOPER - message_send_all(MSG_SMB_STAT_CACHE_DELETE, + message_send_all(smbd_messaging_context(), + MSG_SMB_STAT_CACHE_DELETE, name, strlen(name)+1, True, -- cgit From 32106b23951e01fb17f814584ebbcc8d7288cb75 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 May 2007 00:07:38 +0000 Subject: r22920: Add in the UNIX capability for 24-bit readX, as discussed with the Apple guys and Linux kernel guys. Still looking at how to do writeX as there's no recvfile(). Jeremy. (This used to be commit a53268fb2082de586e2df250d8ddfcff53379102) --- source3/smbd/reply.c | 169 ++++++++++++++++++++++++++++++++------------------ source3/smbd/trans2.c | 5 +- 2 files changed, 111 insertions(+), 63 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5353e392b1..4285e0ea77 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2149,39 +2149,42 @@ static void fail_readraw(void) exit_server_cleanly(errstr); } -#if defined(WITH_SENDFILE) /**************************************************************************** Fake (read/write) sendfile. Returns -1 on read or write fail. ****************************************************************************/ -static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize) +static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize) { - ssize_t ret=0; + size_t tosend = nread; - /* Paranioa check... */ - if (nread > bufsize) { - fail_readraw(); - } + while (tosend > 0) { + ssize_t ret; + size_t cur_read; - if (nread > 0) { - ret = read_file(fsp,buf,startpos,nread); + if (tosend > bufsize) { + cur_read = bufsize; + } else { + cur_read = tosend; + } + ret = read_file(fsp,buf,startpos,cur_read); if (ret == -1) { return -1; } - } - /* If we had a short read, fill with zeros. */ - if (ret < nread) { - memset(buf, '\0', nread - ret); - } + /* If we had a short read, fill with zeros. */ + if (ret < cur_read) { + memset(buf, '\0', cur_read - ret); + } - if (write_data(smbd_server_fd(),buf,nread) != nread) { - return -1; - } + if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) { + return -1; + } + tosend -= cur_read; + startpos += cur_read; + } return (ssize_t)nread; } -#endif /**************************************************************************** Use sendfile in readbraw. @@ -2525,6 +2528,27 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return(outsize); } +/**************************************************************************** + Setup readX header. +****************************************************************************/ + +static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt) +{ + int outsize; + char *data = smb_buf(outbuf); + + SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ + SSVAL(outbuf,smb_vwv5,smb_maxcnt); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16)); + SSVAL(smb_buf(outbuf),-2,smb_maxcnt); + SCVAL(outbuf,smb_vwv0,0xFF); + outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False); + /* Reset the outgoing length, set_message truncates at 0x1FFFF. */ + _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4)); + return outsize; +} + /**************************************************************************** Reply to a read and X - possibly using sendfile. ****************************************************************************/ @@ -2532,10 +2556,27 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) { + SMB_STRUCT_STAT sbuf; int outsize = 0; ssize_t nread = -1; char *data = smb_buf(outbuf); + if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if (startpos > sbuf.st_size) { + smb_maxcnt = 0; + } + + if (smb_maxcnt > (sbuf.st_size - startpos)) { + smb_maxcnt = (sbuf.st_size - startpos); + } + + if (smb_maxcnt == 0) { + goto normal_read; + } + #if defined(WITH_SENDFILE) /* * We can only use sendfile on a non-chained packet @@ -2545,33 +2586,15 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { - SMB_STRUCT_STAT sbuf; DATA_BLOB header; - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - if (startpos > sbuf.st_size) - goto normal_read; - - if (smb_maxcnt > (sbuf.st_size - startpos)) - smb_maxcnt = (sbuf.st_size - startpos); - - if (smb_maxcnt == 0) - goto normal_read; - /* * Set up the packet header before send. We * assume here the sendfile will work (get the * correct amount of data). */ - SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ - SSVAL(outbuf,smb_vwv5,smb_maxcnt); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); - SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1)); - SSVAL(smb_buf(outbuf),-2,smb_maxcnt); - SCVAL(outbuf,smb_vwv0,0xFF); + setup_readX_header(inbuf,outbuf,smb_maxcnt); set_message(inbuf,outbuf,12,smb_maxcnt,False); header.data = (uint8 *)outbuf; header.length = data - outbuf; @@ -2621,24 +2644,41 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length #endif - nread = read_file(fsp,data,startpos,smb_maxcnt); - - if (nread < 0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } + if ((smb_maxcnt && 0xFF0000) > 0x10000) { + int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt; + /* Send out the header. */ + if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) { + DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n", + fsp->fsp_name, strerror(errno) )); + exit_server_cleanly("send_file_readX sendfile failed"); + } + if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data, + len_outbuf - (data-outbuf))) == -1) { + DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", + fsp->fsp_name, strerror(errno) )); + exit_server_cleanly("send_file_readX: fake_sendfile failed"); + } + return -1; + } else { + nread = read_file(fsp,data,startpos,smb_maxcnt); - outsize = set_message(inbuf,outbuf,12,nread,False); - SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ - SSVAL(outbuf,smb_vwv5,nread); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); - SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); - SSVAL(smb_buf(outbuf),-2,nread); - - DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", - fsp->fnum, (int)smb_maxcnt, (int)nread ) ); + if (nread < 0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - /* Returning the number of bytes we want to send back - including header. */ - return outsize; + outsize = set_message(inbuf, outbuf,12,nread,False); + SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); + SSVAL(smb_buf(outbuf),-2,nread); + + DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", + fsp->fnum, (int)smb_maxcnt, (int)nread ) ); + + /* Returning the number of bytes we want to send back - including header. */ + return outsize; + } } /**************************************************************************** @@ -2651,6 +2691,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); ssize_t nread = -1; size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); + BOOL big_readX = False; #if 0 size_t smb_mincnt = SVAL(inbuf,smb_vwv6); #endif @@ -2671,14 +2712,18 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(inbuf,outbuf,12,0,True); if (global_client_caps & CAP_LARGE_READX) { - if (SVAL(inbuf,smb_vwv7) == 1) { - smb_maxcnt |= (1<<16); - } - if (smb_maxcnt > BUFFER_SIZE) { - DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n", - (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE)); - END_PROFILE(SMBreadX); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + size_t upper_size = SVAL(inbuf,smb_vwv7); + smb_maxcnt |= (upper_size<<16); + if (upper_size > 1) { + /* Can't do this on a chained packet. */ + if ((CVAL(inbuf,smb_vwv0) != 0xFF)) { + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } + /* We currently don't do this on signed or sealed data. */ + if (srv_is_signing_active() || srv_encryption_on()) { + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } + big_readX = True; } } @@ -2711,7 +2756,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_DOS(ERRDOS,ERRlock); } - if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) { + if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) { END_PROFILE(SMBreadX); return -1; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1c55684330..0730041899 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2556,7 +2556,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_POSIX_PATHNAMES_CAP| CIFS_UNIX_FCNTL_LOCKS_CAP| CIFS_UNIX_EXTATTR_CAP| - CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))); + CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| + /* Ensure we don't do this on signed or sealed data. */ + (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP) + ))); break; case SMB_QUERY_POSIX_FS_INFO: -- cgit From c3bde5a591b79682cba273e32229f6ffb9bdf531 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 May 2007 00:21:12 +0000 Subject: r22922: Move "normal_read:" label out of ifdef guard. Fix the build. Jeremy. (This used to be commit 3c1ccc68f03b02d2223ec745e241129766e0c15e) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4285e0ea77..51ac95caf9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2640,10 +2640,10 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length return -1; } - normal_read: - #endif + normal_read: + if ((smb_maxcnt && 0xFF0000) > 0x10000) { int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt; /* Send out the header. */ -- cgit From 2b2eec4cfc0684009e135331f9e4e693a5def508 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 May 2007 01:36:23 +0000 Subject: r22925: Sync read_and_X with 3.0.26 code (use setup_readX_header()). Jeremy. (This used to be commit e1052c0e3d50473a9ded6092b6a85d78590a00e7) --- source3/smbd/reply.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 51ac95caf9..24fff5da52 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2666,12 +2666,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length return(UNIXERROR(ERRDOS,ERRnoaccess)); } - outsize = set_message(inbuf, outbuf,12,nread,False); - SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ - SSVAL(outbuf,smb_vwv5,nread); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); - SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); - SSVAL(smb_buf(outbuf),-2,nread); + outsize = setup_readX_header(inbuf, outbuf,nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); -- cgit From 81acb2d8051544f3ca9cfdfb964a7560dfad6105 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 16 May 2007 14:24:06 +0000 Subject: r22942: Some message_register -> messaging_register conversions (This used to be commit 65335a420645202fc79c599a1177838ec19a4075) --- source3/smbd/conn.c | 9 +++-- source3/smbd/open.c | 15 ++++++--- source3/smbd/server.c | 93 ++++++++++++++++++++++++++++++++------------------- 3 files changed, 75 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index d126bd39e6..da55c0a645 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -319,13 +319,16 @@ the message contains just a share name and all instances of that share are unmounted the special sharename '*' forces unmount of all shares ****************************************************************************/ -void msg_force_tdis(int msg_type, struct server_id pid, void *buf, size_t len, - void *private_data) +void msg_force_tdis(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { connection_struct *conn, *next; fstring sharename; - fstrcpy(sharename, (const char *)buf); + fstrcpy(sharename, (const char *)data->data); if (strcmp(sharename, "*") == 0) { DEBUG(1,("Forcing close of all shares\n")); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 35dc13d86c..1a8a087bb7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2249,19 +2249,24 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, smbd process. ****************************************************************************/ -void msg_file_was_renamed(int msg_type, struct server_id src, - void *buf, size_t len, void *private_data) +void msg_file_was_renamed(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { files_struct *fsp; - char *frm = (char *)buf; + char *frm = (char *)data->data; SMB_DEV_T dev; SMB_INO_T inode; const char *sharepath; const char *newname; size_t sp_len; - if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) { - DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); + if (data->data == NULL + || data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) { + DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", + data->length)); return; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f227579c04..a54bed3e1b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -87,10 +87,14 @@ struct messaging_context *smbd_messaging_context(void) What to do when smb.conf is updated. ********************************************************************/ -static void smb_conf_updated(int msg_type, struct server_id src, - void *buf, size_t len, void *private_data) +static void smb_conf_updated(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { - DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n")); + DEBUG(10,("smb_conf_updated: Got message saying smb.conf was " + "updated. Reloading.\n")); reload_services(False); } @@ -99,10 +103,13 @@ static void smb_conf_updated(int msg_type, struct server_id src, Delete a statcache entry. ********************************************************************/ -static void smb_stat_cache_delete(int msg_type, struct server_id src, - void *buf, size_t len, void *private_data) +static void smb_stat_cache_delete(struct messaging_context *msg, + void *private_data, + uint32_t msg_tnype, + struct server_id server_id, + DATA_BLOB *data) { - const char *name = (const char *)buf; + const char *name = (const char *)data->data; DEBUG(10,("smb_stat_cache_delete: delete name %s\n", name)); stat_cache_delete(name); } @@ -150,9 +157,11 @@ static void killkids(void) somewhere else. ****************************************************************************/ -static void msg_sam_sync(int UNUSED(msg_type), struct server_id UNUSED(pid), - void *UNUSED(buf), size_t UNUSED(len), - void *private_data) +static void msg_sam_sync(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { DEBUG(10, ("** sam sync message received, ignoring\n")); } @@ -162,15 +171,18 @@ static void msg_sam_sync(int UNUSED(msg_type), struct server_id UNUSED(pid), somewhere else. ****************************************************************************/ -static void msg_sam_repl(int msg_type, struct server_id pid, - void *buf, size_t len, void *private_data) +static void msg_sam_repl(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { uint32 low_serial; - if (len != sizeof(uint32)) + if (data->length != sizeof(low_serial)) return; - low_serial = *((uint32 *)buf); + low_serial = *((uint32 *)data->data); DEBUG(3, ("received sam replication message, serial = 0x%04x\n", low_serial)); @@ -196,38 +208,44 @@ static BOOL open_sockets_inetd(void) return True; } -static void msg_exit_server(int msg_type, struct server_id src, - void *buf, size_t len, void *private_data) +static void msg_exit_server(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { DEBUG(3, ("got a SHUTDOWN message\n")); exit_server_cleanly(NULL); } #ifdef DEVELOPER -static void msg_inject_fault(int msg_type, struct server_id src, - void *buf, size_t len, void *private_data) +static void msg_inject_fault(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) { int sig; - if (len != sizeof(int)) { + if (data->length != sizeof(sig)) { - DEBUG(0, ("Process %llu sent bogus signal injection request\n", - (unsigned long long)src.pid)); + DEBUG(0, ("Process %s sent bogus signal injection request\n", + procid_str_static(&src))); return; } - sig = *(int *)buf; + sig = *(int *)data->data; if (sig == -1) { exit_server("internal error injected"); return; } #if HAVE_STRSIGNAL - DEBUG(0, ("Process %llu requested injection of signal %d (%s)\n", - (unsigned long long)src.pid, sig, strsignal(sig))); + DEBUG(0, ("Process %s requested injection of signal %d (%s)\n", + procid_str_static(&src), sig, strsignal(sig))); #else - DEBUG(0, ("Process %llu requested injection of signal %d\n", - (unsigned long long)src.pid, sig)); + DEBUG(0, ("Process %s requested injection of signal %d\n", + procid_str_static(&src), sig)); #endif kill(sys_getpid(), sig); @@ -345,16 +363,22 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ /* Listen to messages */ - message_register(MSG_SMB_SAM_SYNC, msg_sam_sync, NULL); - message_register(MSG_SMB_SAM_REPL, msg_sam_repl, NULL); - message_register(MSG_SHUTDOWN, msg_exit_server, NULL); - message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed, NULL); - message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated, NULL); - message_register(MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete, - NULL); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_SAM_SYNC, msg_sam_sync); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_SAM_REPL, msg_sam_repl); + messaging_register(smbd_messaging_context(), NULL, + MSG_SHUTDOWN, msg_exit_server); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_FILE_RENAME, msg_file_was_renamed); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_CONF_UPDATED, smb_conf_updated); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete); #ifdef DEVELOPER - message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault, NULL); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_INJECT_FAULT, msg_inject_fault); #endif /* now accept incoming connections - forking a new process @@ -1071,7 +1095,8 @@ extern void build_options(BOOL screen); initialize_async_io_handler(); /* register our message handlers */ - message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis, NULL); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_FORCE_TDIS, msg_force_tdis); if ((lp_keepalive() != 0) && !(event_add_idle(smbd_event_context(), NULL, -- cgit From e95942ed84fef4dd34c380d59145d3e182b01702 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 16 May 2007 20:56:39 +0000 Subject: r22954: More messaging_register (This used to be commit 9b8df24107ffe3016031e5257c5680689f061886) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a54bed3e1b..7a139afa47 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1029,7 +1029,7 @@ extern void build_options(BOOL screen); exit(1); #endif - if (!print_backend_init()) + if (!print_backend_init(smbd_messaging_context())) exit(1); if (!init_guest_info()) { -- cgit From 0e9210d0eaf0c9de231e48e671cfb0861d62a1da Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 17 May 2007 22:27:42 +0000 Subject: r22978: Don't use current_user to prep the security ctx in change_to_user since any SID/uid/gid translation calls will reset the struct when popping the security ctx. This should fix the standalone server configuration issues reported by David Rankin (thanks for the logs). (This used to be commit 63cb25bad19d9600399a6ee2221497d71e805320) --- source3/smbd/uid.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8588580322..c6d4e3329c 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -156,7 +156,9 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) char group_c; BOOL must_free_token = False; NT_USER_TOKEN *token = NULL; - + int num_groups = 0; + gid_t *group_list = NULL; + if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); return(False); @@ -195,14 +197,14 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) if (conn->force_user) /* security = share sets this too */ { uid = conn->uid; gid = conn->gid; - current_user.ut.groups = conn->groups; - current_user.ut.ngroups = conn->ngroups; + group_list = conn->groups; + num_groups = conn->ngroups; token = conn->nt_user_token; } else if (vuser) { uid = conn->admin_user ? 0 : vuser->uid; gid = vuser->gid; - current_user.ut.ngroups = vuser->n_groups; - current_user.ut.groups = vuser->groups; + num_groups = vuser->n_groups; + group_list = vuser->groups; token = vuser->nt_user_token; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " @@ -235,8 +237,8 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) */ int i; - for (i = 0; i < current_user.ut.ngroups; i++) { - if (current_user.ut.groups[i] == conn->gid) { + for (i = 0; i < num_groups; i++) { + if (group_list[i] == conn->gid) { gid = conn->gid; gid_to_sid(&token->user_sids[1], gid); break; @@ -248,6 +250,12 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) } } + /* Now set current_user since we will immediately also call + set_sec_ctx() */ + + current_user.ut.ngroups = num_groups; + current_user.ut.groups = group_list; + set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, token); -- cgit From 63e74f305920a44606d1b0380c605e00fca14940 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 May 2007 01:27:34 +0000 Subject: r23007: Ensure we don't allow large read over the possible packet size. Jeremy. (This used to be commit 5d465dd2d559df29d18a844137c8e14ffbb1a269) --- source3/smbd/reply.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 24fff5da52..c71c7b8bea 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2718,6 +2718,10 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (srv_is_signing_active() || srv_encryption_on()) { return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } + /* Is there room in the reply for this data ? */ + if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } big_readX = True; } } -- cgit From 01a7017d7b0e0cbc3b0923c43b7fe3f0b01aac0b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 May 2007 20:57:12 +0000 Subject: r23014: For all branches, ensure that if we're blocked on a POSIX lock we know nothing about that we retry the lock every 10 seconds instead of waiting for the standard select timeout. This is how we used to (and are supposed to) work. Jeremy. (This used to be commit fa18fc25a50cf13c687ae88e7e5e2dda1120e017) --- source3/smbd/blocking.c | 25 +++++++++++++++++++++---- source3/smbd/reply.c | 13 +++++++++---- source3/smbd/trans2.c | 8 ++++++-- 3 files changed, 36 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ae7b861f2b..43b2633b9a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -39,6 +39,7 @@ typedef struct _blocking_lock_record { SMB_BIG_UINT offset; SMB_BIG_UINT count; uint32 lock_pid; + uint32 blocking_pid; /* PID that blocks us. */ enum brl_flavour lock_flav; enum brl_type lock_type; char *inbuf; @@ -108,6 +109,16 @@ static BOOL recalc_brl_timeout(void) for (brl = blocking_lock_queue; brl; brl = brl->next) { if (timeval_is_zero(&brl->expire_time)) { + /* + * If we're blocked on pid 0xFFFFFFFF this is + * a POSIX lock, so calculate a timeout of + * 10 seconds into the future. + */ + if (brl->blocking_pid == 0xFFFFFFFF) { + struct timeval psx_to = timeval_current_ofs(10, 0); + next_timeout = timeval_min(&next_timeout, &psx_to); + } + continue; } @@ -146,7 +157,9 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, uint32 lock_pid, enum brl_type lock_type, enum brl_flavour lock_flav, - SMB_BIG_UINT offset, SMB_BIG_UINT count) + SMB_BIG_UINT offset, + SMB_BIG_UINT count, + uint32 blocking_pid) { static BOOL set_lock_msg; blocking_lock_record *blr; @@ -187,6 +200,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, } blr->lock_num = lock_num; blr->lock_pid = lock_pid; + blr->blocking_pid = blocking_pid; blr->lock_flav = lock_flav; blr->lock_type = lock_type; blr->offset = offset; @@ -202,7 +216,8 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, count, lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, blr->lock_flav, - lock_timeout ? True : False); /* blocking_lock. */ + lock_timeout ? True : False, /* blocking_lock. */ + NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -445,7 +460,8 @@ static BOOL process_lockingX(blocking_lock_record *blr) READ_LOCK : WRITE_LOCK), WINDOWS_LOCK, True, - &status); + &status, + &blr->blocking_pid); TALLOC_FREE(br_lck); @@ -506,7 +522,8 @@ static BOOL process_trans2(blocking_lock_record *blr) blr->lock_type, blr->lock_flav, True, - &status); + &status, + &blr->blocking_pid); TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c71c7b8bea..ec110e7b21 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2426,7 +2426,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length WRITE_LOCK, WINDOWS_LOCK, False, /* Non-blocking lock. */ - &status); + &status, + NULL); TALLOC_FREE(br_lck); if (NT_STATUS_V(status)) { @@ -3474,7 +3475,8 @@ int reply_lock(connection_struct *conn, WRITE_LOCK, WINDOWS_LOCK, False, /* Non-blocking lock. */ - &status); + &status, + NULL); TALLOC_FREE(br_lck); @@ -5575,6 +5577,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, BOOL blocking_lock = lock_timeout ? True : False; BOOL defer_lock = False; struct byte_range_lock *br_lck; + uint32 block_smbpid; br_lck = do_lock(smbd_messaging_context(), fsp, @@ -5584,7 +5587,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, lock_type, WINDOWS_LOCK, blocking_lock, - &status); + &status, + &block_smbpid); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* Windows internal resolution for blocking locks seems @@ -5621,7 +5625,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, lock_type, WINDOWS_LOCK, offset, - count)) { + count, + block_smbpid)) { TALLOC_FREE(br_lck); END_PROFILE(SMBlockingX); return -1; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0730041899..63fd414e16 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4815,6 +4815,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, offset, POSIX_LOCK); } else { + uint32 block_smbpid; + struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(), fsp, lock_pid, @@ -4823,7 +4825,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, lock_type, POSIX_LOCK, blocking_lock, - &status); + &status, + &block_smbpid); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* @@ -4840,7 +4843,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, lock_type, POSIX_LOCK, offset, - count)) { + count, + block_smbpid)) { TALLOC_FREE(br_lck); return status; } -- cgit From 4d5f58c2b945e7a2263ba42749f73c7ba72ab3c7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 May 2007 21:53:28 +0000 Subject: r23015: Make message_(de)register static to messages.c (This used to be commit a8082a3c7c3d1e68c27fc3bf42f3d44402cc6f9f) --- source3/smbd/blocking.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 43b2633b9a..6a892b477d 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -74,9 +74,11 @@ static BOOL in_chained_smb(void) return (chain_size != 0); } -static void received_unlock_msg(int msg_type, struct server_id src, - void *buf, size_t len, - void *private_data); +static void received_unlock_msg(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); static void process_blocking_lock_queue(void); static void brl_timeout_fn(struct event_context *event_ctx, @@ -231,8 +233,8 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { - message_register(MSG_SMB_UNLOCK, received_unlock_msg, - NULL); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_UNLOCK, received_unlock_msg); set_lock_msg = True; } @@ -665,9 +667,11 @@ BOOL blocking_lock_was_deferred(int mid) Set a flag as an unlock request affects one of our pending locks. *****************************************************************************/ -static void received_unlock_msg(int msg_type, struct server_id src, - void *buf, size_t len, - void *private_data) +static void received_unlock_msg(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { DEBUG(10,("received_unlock_msg\n")); process_blocking_lock_queue(); @@ -826,22 +830,23 @@ static void process_blocking_lock_queue(void) #define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS)) -static void process_blocking_lock_cancel_message(int msg_type, - struct server_id src, - void *buf, size_t len, - void *private_data) +static void process_blocking_lock_cancel_message(struct messaging_context *ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { NTSTATUS err; - const char *msg = (const char *)buf; + const char *msg = (const char *)data->data; blocking_lock_record *blr; - if (buf == NULL) { + if (data->data == NULL) { smb_panic("process_blocking_lock_cancel_message: null msg\n"); } - if (len != MSG_BLOCKING_LOCK_CANCEL_SIZE) { + if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) { DEBUG(0, ("process_blocking_lock_cancel_message: " - "Got invalid msg len %d\n", (int)len)); + "Got invalid msg len %d\n", (int)data->length)); smb_panic("process_blocking_lock_cancel_message: bad msg\n"); } @@ -874,9 +879,9 @@ BOOL blocking_lock_cancel(files_struct *fsp, if (!initialized) { /* Register our message. */ - message_register(MSG_SMB_BLOCKING_LOCK_CANCEL, - process_blocking_lock_cancel_message, - NULL); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_BLOCKING_LOCK_CANCEL, + process_blocking_lock_cancel_message); initialized = True; } -- cgit From e67c8d09fde8594c411702f6d32bb977d15c7445 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 May 2007 22:29:59 +0000 Subject: r23016: Remove extra & - thanks to Volker for spotting this. Jeremy. (This used to be commit c2c970fd50b293031390358d72aaa7bd94da6e6d) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec110e7b21..364f571f4b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2645,7 +2645,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length normal_read: - if ((smb_maxcnt && 0xFF0000) > 0x10000) { + if ((smb_maxcnt & 0xFF0000) > 0x10000) { int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt; /* Send out the header. */ if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) { -- cgit From ac3f08ddbe0b484375624db0e35999a8584b57f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 21 May 2007 22:17:13 +0000 Subject: r23055: Rewrite messages.c to use auto-generated marshalling in the tdb. I'm doing this because for the clustering the marshalling is needed in more than one place, so I wanted a decent routine to marshall a message_rec struct which was not there before. Tridge, this seems about the same speed as it used to be before, the librpc/ndr overhead in my tests was under the noise. Volker (This used to be commit eaefd00563173dfabb7716c5695ac0a2f7139bb6) --- source3/smbd/lanman.c | 3 +-- source3/smbd/process.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/statcache.c | 1 - 4 files changed, 3 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fae6312080..0a9a529a85 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1895,8 +1895,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, } else { SAFE_FREE(command); message_send_all(smbd_messaging_context(), - MSG_SMB_CONF_UPDATED, NULL, 0, - False, NULL); + MSG_SMB_CONF_UPDATED, NULL, 0, NULL); } } else { return False; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 02dc507e11..3b922af51f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -380,7 +380,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) * messages as we need to synchronously process any messages * we may have sent to ourselves from the previous SMB. */ - message_dispatch(); + message_dispatch(smbd_messaging_context()); /* * Check to see if we already have a message on the deferred open queue diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7a139afa47..6746271c09 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -392,7 +392,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ lp_TALLOC_FREE(); /* Ensure we respond to PING and DEBUG messages from the main smbd. */ - message_dispatch(); + message_dispatch(smbd_messaging_context()); if (got_sig_cld) { pid_t pid; diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 1d6646257a..b63dd165a7 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -296,7 +296,6 @@ void send_stat_cache_delete_message(const char *name) MSG_SMB_STAT_CACHE_DELETE, name, strlen(name)+1, - True, NULL); #endif } -- cgit From 828cb240047506afd292a613742ff88ee994896e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 May 2007 22:35:13 +0000 Subject: r23087: Fix POSIX setfilepathinfo to use lstat, not stat. Still missing lchown (will add this for 3.0.26). Don't merge for 3.0.25a - possibly 3.0.25b (if it exists). Jeremy. (This used to be commit f546750176a22cdd7298a73afc81587923baaff9) --- source3/smbd/open.c | 7 ++++++- source3/smbd/trans2.c | 30 +++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1a8a087bb7..7784740063 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -47,7 +47,12 @@ static NTSTATUS fd_open(struct connection_struct *conn, NTSTATUS status = NT_STATUS_OK; #ifdef O_NOFOLLOW - if (!lp_symlinks(SNUM(conn))) { + /* + * Never follow symlinks on a POSIX client. The + * client should be doing this. + */ + + if (fsp->posix_open || !lp_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; } #endif diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 63fd414e16..a41aa3c7df 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5777,9 +5777,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char * to do this call. JRA. */ pstrcpy(fname, fsp->fsp_name); - if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) { - DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); + return UNIXERROR(ERRDOS,ERRbadpath); + } + } else { + if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) { + DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); + return UNIXERROR(ERRDOS,ERRbadpath); + } } } else if (fsp && fsp->print_file) { /* @@ -5838,14 +5846,18 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(status); } - /* - * For CIFS UNIX extensions the target name may not exist. - */ + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* + * For CIFS UNIX extensions the target name may not exist. + */ + + /* Always do lstat for UNIX calls. */ + SMB_VFS_LSTAT(conn,fname,&sbuf); - if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { - DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); return UNIXERROR(ERRDOS,ERRbadpath); - } + } } if (!CAN_WRITE(conn)) { -- cgit From 918b6ea082562dd269c5f23941adb2f47a61dd59 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 May 2007 23:56:47 +0000 Subject: r23088: Fix rename for cifsfs client. This may be needed for 3.0.25a. Jeremy. (This used to be commit 02e4f6b0f1f1a1cc6bfe5fed7866eb5b18ab87e0) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 364f571f4b..fb042a6b1d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4310,10 +4310,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OBJECT_NAME_COLLISION; } - status = can_rename(conn,newname,attrs,&sbuf); + status = can_rename(conn,fsp->fsp_name,attrs,&sbuf); if (dest_exists && !NT_STATUS_IS_OK(status)) { - DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", + DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", nt_errstr(status), fsp->fsp_name,newname)); if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) status = NT_STATUS_ACCESS_DENIED; -- cgit From dbfd6bf8c8cc9945c4ba7e22ac44b1f33f9c7ce6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 May 2007 21:32:10 +0000 Subject: r23100: Implement the delete on close semantics I've just tested for in Samba4 smbtorture. Fix rename on an open file handle. Needed for 3.0.25a. Jeremy. (This used to be commit a301467d5f645dada27093ddfd74890b88bb4ce8) --- source3/smbd/open.c | 40 +++++++++++++++++++++----------------- source3/smbd/reply.c | 54 ++++++++++++++++++++++++++++++++++++++++++++------- source3/smbd/trans2.c | 5 +++-- 3 files changed, 72 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7784740063..89ff9ae809 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1123,6 +1123,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, BOOL file_existed = VALID_STAT(*psbuf); BOOL def_acl = False; BOOL posix_open = False; + BOOL new_file_created = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; @@ -1763,28 +1764,31 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; } } - set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type); - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED) { + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { + new_file_created = True; + } - /* Handle strange delete on close create semantics. */ - if (create_options & FILE_DELETE_ON_CLOSE) { - status = can_set_delete_on_close(fsp, True, new_dos_attributes); + set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); - if (!NT_STATUS_IS_OK(status)) { - /* Remember to delete the mode we just added. */ - del_share_mode(lck, fsp); - TALLOC_FREE(lck); - fd_close(conn,fsp); - file_free(fsp); - return status; - } - /* Note that here we set the *inital* delete on close flag, - not the regular one. The magic gets handled in close. */ - fsp->initial_delete_on_close = True; + /* Handle strange delete on close create semantics. */ + if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) { + status = can_set_delete_on_close(fsp, True, new_dos_attributes); + + if (!NT_STATUS_IS_OK(status)) { + /* Remember to delete the mode we just added. */ + del_share_mode(lck, fsp); + TALLOC_FREE(lck); + fd_close(conn,fsp); + file_free(fsp); + return status; } + /* Note that here we set the *inital* delete on close flag, + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; + } + if (new_file_created) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { @@ -2142,7 +2146,7 @@ NTSTATUS open_directory(connection_struct *conn, return status; } - set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK); + set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK, True); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fb042a6b1d..98976dd39d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1791,7 +1791,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Check if a user is allowed to rename a file. ********************************************************************/ -static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst) +static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open) { files_struct *fsp; uint32 fmode; @@ -1812,7 +1812,10 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, status = open_file_ntcreate(conn, fname, pst, DELETE_ACCESS, - FILE_SHARE_READ|FILE_SHARE_WRITE, + /* If we're checking our fsp don't deny for delete. */ + self_open ? + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE : + FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, @@ -4242,7 +4245,9 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin ZERO_STRUCT(sbuf); status = unix_convert(conn, newname, False, newname_last_component, &sbuf); - if (!NT_STATUS_IS_OK(status)) { + /* We expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */ + if (!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) { + return NT_STATUS_OBJECT_NAME_COLLISION; return status; } @@ -4310,9 +4315,20 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OBJECT_NAME_COLLISION; } - status = can_rename(conn,fsp->fsp_name,attrs,&sbuf); + /* Ensure we have a valid stat struct for the source. */ + if (fsp->fh->fd != -1) { + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) { + return map_nt_error_from_unix(errno); + } + } else { + if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) { + return map_nt_error_from_unix(errno); + } + } - if (dest_exists && !NT_STATUS_IS_OK(status)) { + status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True); + + if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", nt_errstr(status), fsp->fsp_name,newname)); if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) @@ -4327,9 +4343,33 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { + uint32 create_options = fsp->fh->private_options; + DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); + rename_open_files(conn, lck, fsp->dev, fsp->inode, newname); + + /* + * A rename acts as a new file create w.r.t. allowing an initial delete + * on close, probably because in Windows there is a new handle to the + * new file. If initial delete on close was requested but not + * originally set, we need to set it here. This is probably not 100% correct, + * but will work for the CIFSFS client which in non-posix mode + * depends on these semantics. JRA. + */ + + set_allow_initial_delete_on_close(lck, fsp, True); + + if (create_options & FILE_DELETE_ON_CLOSE) { + status = can_set_delete_on_close(fsp, True, 0); + + if (NT_STATUS_IS_OK(status)) { + /* Note that here we set the *inital* delete on close flag, + * not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; + } + } TALLOC_FREE(lck); return NT_STATUS_OK; } @@ -4580,7 +4620,7 @@ NTSTATUS rename_internals(connection_struct *conn, return status; } - status = can_rename(conn,directory,attrs,&sbuf1); + status = can_rename(conn,directory,attrs,&sbuf1,False); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("rename_internals: Error %s rename %s -> " @@ -4708,7 +4748,7 @@ NTSTATUS rename_internals(connection_struct *conn, fname, nt_errstr(status))); continue; } - status = can_rename(conn,fname,attrs,&sbuf1); + status = can_rename(conn,fname,attrs,&sbuf1,False); if (!NT_STATUS_IS_OK(status)) { DEBUG(6, ("rename %s refused\n", fname)); continue; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a41aa3c7df..bd66980983 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4650,10 +4650,11 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, pstrcpy(base_name, fname); p = strrchr_m(base_name, '/'); if (p) { - *p = '\0'; + p[1] = '\0'; + } else { + pstrcpy(base_name, "./"); } /* Append the new name. */ - pstrcat(base_name, "/"); pstrcat(base_name, newname); if (fsp) { -- cgit From f5038178a9a2ad295365e54ff4e7661daf55f2df Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 May 2007 00:13:24 +0000 Subject: r23106: Use lchown for symlinks. Jeremy. (This used to be commit b98175440b2c235fe223b4375441f15ea027a5b2) --- source3/smbd/trans2.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bd66980983..835fd0cedb 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5268,9 +5268,18 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", */ if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) { - DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", + int ret; + + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n", (unsigned int)set_owner, fname )); - if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) { + + if (S_ISLNK(psbuf->st_mode)) { + ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1); + } else { + ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1); + } + + if (ret != 0) { status = map_nt_error_from_unix(errno); if (delete_on_fail) { SMB_VFS_UNLINK(conn,fname); -- cgit From 4aa857d875663f39740b4667fc7852a530536660 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 May 2007 01:57:02 +0000 Subject: r23107: Fix renames on file descriptors that are supposed to overwrite the target. Needs merging for 3.0.25a (sorry). Jeremy. (This used to be commit a56bce3d44e89b4fd7806cc5b464c7481ec0197f) --- source3/smbd/reply.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 98976dd39d..40311758c9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4245,9 +4245,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin ZERO_STRUCT(sbuf); status = unix_convert(conn, newname, False, newname_last_component, &sbuf); - /* We expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */ - if (!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) { - return NT_STATUS_OBJECT_NAME_COLLISION; + + /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */ + + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) { return status; } -- cgit From 4c795b293d34db5fa334c7627fa86d0ed197adcb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 May 2007 01:19:51 +0000 Subject: r23150: Fix Samba3 in the build farm again. In the case where the file was being created and we go into the race condition check, we were testing for compatible open modes, but were not breaking oplocks in the same way as if the file existed. This meant that we weren't going into the code path that sets fsp->oplock = FAKE_LEVEL_II_OPLOCK if the client didn't ask for an oplock on file create. We need to do this as internally it's what Windows does. Jeremy. (This used to be commit 9b9513856e9e9f84d5acd94e3e3d6e73358ee7dc) --- source3/smbd/open.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 89ff9ae809..ccd12c6946 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1650,6 +1650,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } + /* First pass - send break only on batch oplocks. */ + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } + status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); @@ -1677,6 +1686,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } + /* * We exit this block with the share entry *locked*..... */ -- cgit From f3de07503af29e5593255324fb1f901e878dc776 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 May 2007 01:26:09 +0000 Subject: r23151: Re-arrange the logic so it looks identical to the "file existed" case above. This has no functional change but is easier to see that it's doing the same thing. Jeremy. (This used to be commit 0a7d8362be8379b77e6afb803ab88d726ae7877d) --- source3/smbd/open.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ccd12c6946..987da7a94d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1663,6 +1663,20 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, access_mask, share_access, create_options, &file_existed); + if (NT_STATUS_IS_OK(status)) { + /* We might be going to allow this open. Check oplock + * status again. */ + /* Second pass - send break for both batch or + * exclusive oplocks. */ + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } + } + if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; @@ -1686,14 +1700,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); - TALLOC_FREE(lck); - fd_close(conn, fsp); - file_free(fsp); - return NT_STATUS_SHARING_VIOLATION; - } - /* * We exit this block with the share entry *locked*..... */ -- cgit From f3c477c631e7318ccaa6f277731b721a462112b8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 May 2007 16:22:12 +0000 Subject: r23167: Remove an unused parameter (This used to be commit 3452a870d58cdddf03ddf6ee698bca8416e05cbf) --- source3/smbd/connection.c | 3 ++- source3/smbd/negprot.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/service.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index b9cdede69e..1069f95ed8 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -166,7 +166,8 @@ int count_all_current_connections(void) Claim an entry in the connections database. ****************************************************************************/ -BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags) +BOOL claim_connection(connection_struct *conn, const char *name, + int max_connections, uint32 msg_flags) { struct connections_key key; struct connections_data crec; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 12b1e84600..7aa9725062 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -584,7 +584,7 @@ int reply_negprot(connection_struct *conn, when the client connects to port 445. Of course there is a small window where we are listening to messages -- jerry */ - claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); + claim_connection(NULL,"",0,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); /* Check for protocols, most desirable first */ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6746271c09..3a2895cfcb 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1040,7 +1040,7 @@ extern void build_options(BOOL screen); /* Setup the main smbd so that we can get messages. */ /* don't worry about general printing messages here */ - claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); + claim_connection(NULL,"",0,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); /* only start the background queue daemon if we are running as a daemon -- bad things will happen if diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 6d2cdff594..5b087fd583 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -993,7 +993,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (!claim_connection(conn, lp_servicename(snum), lp_max_connections(snum), - False,0)) { + 0)) { DEBUG(1,("too many connections - rejected\n")); conn_free(conn); *status = NT_STATUS_INSUFFICIENT_RESOURCES; -- cgit From 14e25f10d6a3da34fb8b29c4331571efa11ee3b8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 May 2007 16:34:49 +0000 Subject: r23168: Move the lp_max_connections() into service.c. (This used to be commit 4afe37d431b6eb475769a2057025da9aa8d1bb14) --- source3/smbd/connection.c | 20 ++------------------ source3/smbd/negprot.c | 3 ++- source3/smbd/server.c | 2 +- source3/smbd/service.c | 26 ++++++++++++++++++++------ 4 files changed, 25 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 1069f95ed8..3e4a8a858b 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -167,7 +167,7 @@ int count_all_current_connections(void) ****************************************************************************/ BOOL claim_connection(connection_struct *conn, const char *name, - int max_connections, uint32 msg_flags) + uint32 msg_flags) { struct connections_key key; struct connections_data crec; @@ -178,23 +178,7 @@ BOOL claim_connection(connection_struct *conn, const char *name, return False; } - /* - * Enforce the max connections parameter. - */ - - if (max_connections > 0) { - int curr_connections; - - curr_connections = count_current_connections( lp_servicename(SNUM(conn)), True ); - - if (curr_connections >= max_connections) { - DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n", - max_connections, name )); - return False; - } - } - - DEBUG(5,("claiming %s %d\n",name,max_connections)); + DEBUG(5,("claiming %s\n",name)); make_conn_key(conn, name, &kbuf, &key); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 7aa9725062..92c392b366 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -584,7 +584,8 @@ int reply_negprot(connection_struct *conn, when the client connects to port 445. Of course there is a small window where we are listening to messages -- jerry */ - claim_connection(NULL,"",0,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); + claim_connection( + NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); /* Check for protocols, most desirable first */ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3a2895cfcb..fc1faa9d36 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1040,7 +1040,7 @@ extern void build_options(BOOL screen); /* Setup the main smbd so that we can get messages. */ /* don't worry about general printing messages here */ - claim_connection(NULL,"",0,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); + claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD); /* only start the background queue daemon if we are running as a daemon -- bad things will happen if diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 5b087fd583..2b84223695 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -989,17 +989,31 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } /* ROOT Activities: */ - /* check number of connections */ - if (!claim_connection(conn, - lp_servicename(snum), - lp_max_connections(snum), - 0)) { - DEBUG(1,("too many connections - rejected\n")); + /* + * Enforce the max connections parameter. + */ + + if ((lp_max_connections(snum) > 0) + && (count_current_connections(lp_servicename(SNUM(conn)), True) >= + lp_max_connections(snum))) { + + DEBUG(1, ("Max connections (%d) exceeded for %s\n", + lp_max_connections(snum), lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } + /* + * Get us an entry in the connections db + */ + if (!claim_connection(conn, lp_servicename(snum), 0)) { + DEBUG(1, ("Could not store connections entry\n")); + conn_free(conn); + *status = NT_STATUS_INTERNAL_DB_ERROR; + return NULL; + } + /* Preexecs are done here as they might make the dir we are to ChDir * to below */ /* execute any "root preexec = " line */ -- cgit From 054bf2fc8bd8ac62e16ec04001c0a4a8409d0e1d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 May 2007 11:38:42 +0000 Subject: r23171: Convert connections.tdb to dbwrap (This used to be commit 80a1f43825063bbbda896175d99700ede5a4757a) --- source3/smbd/connection.c | 163 +++++++++++++++++++++------------------------- 1 file changed, 75 insertions(+), 88 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 3e4a8a858b..4c4ddbc0f0 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -20,50 +20,30 @@ #include "includes.h" -static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey) -{ - ZERO_STRUCTP(pkey); - pkey->pid = procid_self(); - pkey->cnum = conn?conn->cnum:-1; - fstrcpy(pkey->name, name); -#ifdef DEVELOPER - /* valgrind fixer... */ - { - size_t sl = strlen(pkey->name); - if (sizeof(fstring)-sl) - memset(&pkey->name[sl], '\0', sizeof(fstring)-sl); - } -#endif - - pkbuf->dptr = (uint8 *)pkey; - pkbuf->dsize = sizeof(*pkey); -} - /**************************************************************************** Delete a connection record. ****************************************************************************/ BOOL yield_connection(connection_struct *conn, const char *name) { - struct connections_key key; - TDB_DATA kbuf; - TDB_CONTEXT *tdb = conn_tdb_ctx(True); - - if (!tdb) - return False; + struct db_record *rec; + NTSTATUS status; DEBUG(3,("Yielding connection to %s\n",name)); - make_conn_key(conn, name, &kbuf, &key); + if (!(rec = connections_fetch_entry(NULL, conn, name))) { + DEBUG(0, ("connections_fetch_entry failed\n")); + return False; + } - if (tdb_delete(tdb, kbuf) != 0) { - int dbg_lvl = (!conn && (tdb_error(tdb) == TDB_ERR_NOEXIST)) ? 3 : 0; - DEBUG(dbg_lvl,("yield_connection: tdb_delete for name %s failed with error %s.\n", - name, tdb_errorstr(tdb) )); - return (False); + status = rec->delete_rec(rec); + if (!NT_STATUS_IS_OK(status)) { + DEBUG( NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) ? 3 : 0, + ("deleting connection record returned %s\n", + nt_errstr(status))); } - return(True); + return NT_STATUS_IS_OK(status); } struct count_stat { @@ -77,34 +57,36 @@ struct count_stat { Count the entries belonging to a service in the connection db. ****************************************************************************/ -static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *udp) +static int count_fn(struct db_record *rec, + const struct connections_key *ckey, + const struct connections_data *crec, + void *udp) { - struct connections_data crec; struct count_stat *cs = (struct count_stat *)udp; - if (dbuf.dsize != sizeof(crec)) { - return 0; - } - - memcpy(&crec, dbuf.dptr, sizeof(crec)); - - if (crec.cnum == -1) { + if (crec->cnum == -1) { return 0; } /* If the pid was not found delete the entry from connections.tdb */ - if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) { + if (cs->Clear && !process_exists(crec->pid) && (errno == ESRCH)) { + NTSTATUS status; DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", - procid_str_static(&crec.pid), crec.cnum, crec.servicename)); - if (tdb_delete(the_tdb, kbuf) != 0) - DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(the_tdb) )); + procid_str_static(&crec->pid), crec->cnum, + crec->servicename)); + + status = rec->delete_rec(rec); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("count_fn: tdb_delete failed with error %s\n", + nt_errstr(status))); + } return 0; } if (cs->name) { /* We are counting all the connections to a given share. */ - if (strequal(crec.servicename, cs->name)) { + if (strequal(crec->servicename, cs->name)) { cs->curr_connections++; } } else { @@ -125,7 +107,6 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u int count_current_connections( const char *sharename, BOOL clear ) { struct count_stat cs; - TDB_CONTEXT *tdb = conn_tdb_ctx(True); cs.mypid = sys_getpid(); cs.curr_connections = 0; @@ -137,9 +118,9 @@ int count_current_connections( const char *sharename, BOOL clear ) * as it leads to deadlock. */ - if (tdb_traverse(tdb, count_fn, &cs) == -1) { - DEBUG(0,("count_current_connections: traverse of connections.tdb failed with error %s\n", - tdb_errorstr(tdb) )); + if (connections_forall(count_fn, &cs) == -1) { + DEBUG(0,("count_current_connections: traverse of " + "connections.tdb failed\n")); DEBUGADD(0, ("count_current_connections: connection count of %d might not be accurate", cs.curr_connections)); } @@ -169,18 +150,17 @@ int count_all_current_connections(void) BOOL claim_connection(connection_struct *conn, const char *name, uint32 msg_flags) { - struct connections_key key; + struct db_record *rec; struct connections_data crec; - TDB_DATA kbuf, dbuf; - TDB_CONTEXT *tdb = conn_tdb_ctx(True); + TDB_DATA dbuf; + NTSTATUS status; - if (!tdb) { + DEBUG(5,("claiming [%s]\n", name)); + + if (!(rec = connections_fetch_entry(NULL, conn, name))) { + DEBUG(0, ("connections_fetch_entry failed\n")); return False; } - - DEBUG(5,("claiming %s\n",name)); - - make_conn_key(conn, name, &kbuf, &key); /* fill in the crec */ ZERO_STRUCT(crec); @@ -190,21 +170,26 @@ BOOL claim_connection(connection_struct *conn, const char *name, if (conn) { crec.uid = conn->uid; crec.gid = conn->gid; - safe_strcpy(crec.servicename, - lp_servicename(SNUM(conn)),sizeof(crec.servicename)-1); + strlcpy(crec.servicename, lp_servicename(SNUM(conn)), + sizeof(crec.servicename)); } crec.start = time(NULL); crec.bcast_msg_flags = msg_flags; - safe_strcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1); - safe_strcpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1); + strlcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)); + strlcpy(crec.addr,conn?conn->client_address:client_addr(), + sizeof(crec.addr)); dbuf.dptr = (uint8 *)&crec; dbuf.dsize = sizeof(crec); - if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { + status = rec->store(rec, dbuf, TDB_REPLACE); + + TALLOC_FREE(rec); + + if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("claim_connection: tdb_store failed with error %s.\n", - tdb_errorstr(tdb) )); + nt_errstr(status))); return False; } @@ -213,44 +198,44 @@ BOOL claim_connection(connection_struct *conn, const char *name, BOOL register_message_flags(BOOL doreg, uint32 msg_flags) { - struct connections_key key; + struct db_record *rec; struct connections_data *pcrec; - TDB_DATA kbuf, dbuf; - TDB_CONTEXT *tdb = conn_tdb_ctx(True); - - if (!tdb) - return False; + NTSTATUS status; DEBUG(10,("register_message_flags: %s flags 0x%x\n", doreg ? "adding" : "removing", (unsigned int)msg_flags )); - make_conn_key(NULL, "", &kbuf, &key); + if (!(rec = connections_fetch_entry(NULL, NULL, NULL))) { + DEBUG(0, ("connections_fetch_entry failed\n")); + return False; + } - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) { - DEBUG(0,("register_message_flags: tdb_fetch failed: %s\n", - tdb_errorstr(tdb))); + if (rec->value.dsize != sizeof(struct connections_data)) { + DEBUG(0,("register_message_flags: Got wrong record size\n")); + TALLOC_FREE(rec); return False; } - pcrec = (struct connections_data *)dbuf.dptr; + pcrec = (struct connections_data *)rec->value.dptr; if (doreg) pcrec->bcast_msg_flags |= msg_flags; else pcrec->bcast_msg_flags &= ~msg_flags; - if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { + status = rec->store(rec, rec->value, TDB_REPLACE); + + TALLOC_FREE(rec); + + if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("register_message_flags: tdb_store failed: %s.\n", - tdb_errorstr(tdb) )); - SAFE_FREE(dbuf.dptr); + nt_errstr(status))); return False; } DEBUG(10,("register_message_flags: new flags 0x%x\n", (unsigned int)pcrec->bcast_msg_flags )); - SAFE_FREE(dbuf.dptr); return True; } @@ -297,10 +282,10 @@ static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p ) BOOL store_pipe_opendb( smb_np_struct *p ) { + struct db_record *dbrec; struct pipe_open_rec *prec; TDB_DATA *key; TDB_DATA data; - TDB_CONTEXT *pipe_tdb; BOOL ret = False; if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { @@ -315,12 +300,13 @@ BOOL store_pipe_opendb( smb_np_struct *p ) data.dptr = (uint8 *)prec; data.dsize = sizeof(struct pipe_open_rec); - - if ( (pipe_tdb = conn_tdb_ctx(True) ) == NULL ) { + + if (!(dbrec = connections_fetch_record(prec, *key))) { + DEBUG(0, ("connections_fetch_record failed\n")); goto done; } - - ret = (tdb_store( pipe_tdb, *key, data, TDB_REPLACE ) != -1); + + ret = NT_STATUS_IS_OK(dbrec->store(dbrec, data, TDB_REPLACE)); done: TALLOC_FREE( prec ); @@ -332,9 +318,9 @@ done: BOOL delete_pipe_opendb( smb_np_struct *p ) { + struct db_record *dbrec; struct pipe_open_rec *prec; TDB_DATA *key; - TDB_CONTEXT *pipe_tdb; BOOL ret = False; if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { @@ -347,11 +333,12 @@ BOOL delete_pipe_opendb( smb_np_struct *p ) goto done; } - if ( (pipe_tdb = conn_tdb_ctx(True) ) == NULL ) { + if (!(dbrec = connections_fetch_record(prec, *key))) { + DEBUG(0, ("connections_fetch_record failed\n")); goto done; } - ret = (tdb_delete( pipe_tdb, *key ) != -1 ); + ret = NT_STATUS_IS_OK(dbrec->delete_rec(dbrec)); done: TALLOC_FREE( prec ); -- cgit From fff51a9af20b7221844ffb11d7491372bbbcda0e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 May 2007 12:39:39 +0000 Subject: r23172: Change shutdown_other_smbds to use connections_traverse instead of session_traverse. (This used to be commit ccb5eb245e962b0264b337c2d0275c22e2a36830) --- source3/smbd/session.c | 5 +++-- source3/smbd/sesssetup.c | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index cd7511430e..f55576a7be 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -202,8 +202,9 @@ void session_yield(user_struct *vuser) /******************************************************************** ********************************************************************/ -BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), - void *state) +static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, + void *), + void *state) { if (!session_init()) { DEBUG(3, ("No tdb opened\n")); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index ccfc22598d..42a71f8ad7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1174,25 +1174,26 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, a new session setup with VC==0 is ignored. ****************************************************************************/ -static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, - void *p) +static int shutdown_other_smbds(struct db_record *rec, + const struct connections_key *key, + const struct connections_data *crec, + void *private_data) { - struct sessionid *sessionid = (struct sessionid *)dbuf.dptr; - const char *ip = (const char *)p; + const char *ip = (const char *)private_data; - if (!process_exists(sessionid->pid)) { + if (!process_exists(crec->pid)) { return 0; } - if (procid_is_me(&sessionid->pid)) { + if (procid_is_me(&crec->pid)) { return 0; } - if (strcmp(ip, sessionid->ip_addr) != 0) { + if (strcmp(ip, crec->addr) != 0) { return 0; } - messaging_send(smbd_messaging_context(), sessionid->pid, MSG_SHUTDOWN, + messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN, &data_blob_null); return 0; } @@ -1205,7 +1206,7 @@ static void setup_new_vc_session(void) invalidate_all_vuids(); #endif if (lp_reset_on_zero_vc()) { - session_traverse(shutdown_other_smbds, client_addr()); + connections_forall(shutdown_other_smbds, client_addr()); } } -- cgit From ba0bce2c6f7298840e0d223a5f170b777b8c9d64 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 May 2007 13:33:54 +0000 Subject: r23173: Convert sessionid.tdb to ctdb. The 3.0.26 patch is a bit larger because it brings across the tdb-based list_sessions (This used to be commit 0153386c1a3625b2f699863991893f399c40af48) --- source3/smbd/session.c | 171 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 118 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index f55576a7be..837c37a49f 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -29,19 +29,25 @@ #include "includes.h" -static TDB_CONTEXT *tdb; - /******************************************************************** ********************************************************************/ -BOOL session_init(void) +static struct db_context *session_db_ctx(void) { - if (tdb) - return True; + static struct db_context *ctx; + + if (ctx) + return ctx; + + ctx = db_open(NULL, lock_path("sessionid.tdb"), 0, + TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR | O_CREAT, 0644); + return ctx; +} - tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644); - if (!tdb) { +BOOL session_init(void) +{ + if (session_db_ctx() == NULL) { DEBUG(1,("session_init: failed to open sessionid tdb\n")); return False; } @@ -55,17 +61,17 @@ BOOL session_init(void) BOOL session_claim(user_struct *vuser) { + TDB_DATA key, data; int i = 0; - TDB_DATA data; struct sockaddr sa; struct in_addr *client_ip; struct sessionid sessionid; struct server_id pid = procid_self(); fstring keystr; char * hostname; - int tdb_store_flag; /* If using utmp, we do an inital 'lock hold' store, - but we don't need this if we are just using the - (unique) pid/vuid combination */ + struct db_context *ctx; + struct db_record *rec; + NTSTATUS status; vuser->session_keystr = NULL; @@ -75,8 +81,9 @@ BOOL session_claim(user_struct *vuser) return True; } - if (!session_init()) + if (!(ctx = session_db_ctx())) { return False; + } ZERO_STRUCT(sessionid); @@ -84,30 +91,70 @@ BOOL session_claim(user_struct *vuser) data.dsize = 0; if (lp_utmp()) { + for (i=1;ifetch_locked(ctx, NULL, key); + + if (rec == NULL) { + DEBUG(1, ("Could not lock \"%s\"\n", keystr)); + return False; + } + + if (rec->value.dsize != sizeof(sessionid)) { + DEBUG(1, ("Re-using invalid record\n")); + break; + } + + sess_pid = ((struct sessionid *)rec->value.dptr)->pid; + + if (!process_exists(sess_pid)) { + DEBUG(5, ("%s has died -- re-using session\n", + procid_str_static(&sess_pid))); + break; + } + + TALLOC_FREE(rec); } if (i == MAX_SESSION_ID) { - DEBUG(1,("session_claim: out of session IDs (max is %d)\n", - MAX_SESSION_ID)); + SMB_ASSERT(rec == NULL); + DEBUG(1,("session_claim: out of session IDs " + "(max is %d)\n", MAX_SESSION_ID)); return False; } - slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_UTMP_TEMPLATE, i); - tdb_store_flag = TDB_MODIFY; + + snprintf(sessionid.id_str, sizeof(sessionid.id_str), + SESSION_UTMP_TEMPLATE, i); } else { - slprintf(keystr, sizeof(keystr)-1, "ID/%lu/%u", - (long unsigned int)sys_getpid(), - vuser->vuid); - slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, + snprintf(keystr, sizeof(keystr), "ID/%s/%u", + procid_str_static(&pid), vuser->vuid); + key = string_term_tdb_data(keystr); + + rec = ctx->fetch_locked(ctx, NULL, key); + + if (rec == NULL) { + DEBUG(1, ("Could not lock \"%s\"\n", keystr)); + return False; + } + + snprintf(sessionid.id_str, sizeof(sessionid.id_str), SESSION_TEMPLATE, (long unsigned int)sys_getpid(), vuser->vuid); - tdb_store_flag = TDB_REPLACE; } + SMB_ASSERT(rec != NULL); + /* If 'hostname lookup' == yes, then do the DNS lookup. This is needed because utmp and PAM both expect DNS names @@ -131,19 +178,24 @@ BOOL session_claim(user_struct *vuser) client_ip = client_inaddr(&sa); - if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) { + if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, + sessionid.hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", sessionid.username, sessionid.id_str)); - if (tdb_store_flag == TDB_MODIFY) { - tdb_delete_bystring(tdb, keystr); - } + + TALLOC_FREE(rec); return False; } data.dptr = (uint8 *)&sessionid; data.dsize = sizeof(sessionid); - if (tdb_store_bystring(tdb, keystr, data, tdb_store_flag) != 0) { - DEBUG(1,("session_claim: unable to create session id record\n")); + + status = rec->store(rec, data, TDB_REPLACE); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("session_claim: unable to create session id " + "record: %s\n", nt_errstr(status))); + TALLOC_FREE(rec); return False; } @@ -153,9 +205,12 @@ BOOL session_claim(user_struct *vuser) sessionid.id_str, sessionid.id_num); } + TALLOC_FREE(rec); + vuser->session_keystr = talloc_strdup(vuser, keystr); if (!vuser->session_keystr) { - DEBUG(0, ("session_claim: talloc_strdup() failed for session_keystr\n")); + DEBUG(0, ("session_claim: talloc_strdup() failed for " + "session_keystr\n")); return False; } return True; @@ -167,26 +222,30 @@ BOOL session_claim(user_struct *vuser) void session_yield(user_struct *vuser) { - TDB_DATA dbuf; + TDB_DATA key; struct sessionid sessionid; struct in_addr *client_ip; + struct db_context *ctx; + struct db_record *rec; - if (!tdb) return; + if (!(ctx = session_db_ctx())) return; if (!vuser->session_keystr) { return; } - dbuf = tdb_fetch_bystring(tdb, vuser->session_keystr); + key = string_term_tdb_data(vuser->session_keystr); - if (dbuf.dsize != sizeof(sessionid)) + if (!(rec = ctx->fetch_locked(ctx, NULL, key))) { return; + } - memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); + if (rec->value.dsize != sizeof(sessionid)) + return; - client_ip = interpret_addr2(sessionid.ip_addr); + memcpy(&sessionid, rec->value.dptr, sizeof(sessionid)); - SAFE_FREE(dbuf.dptr); + client_ip = interpret_addr2(sessionid.ip_addr); if (lp_utmp()) { sys_utmp_yield(sessionid.username, sessionid.hostname, @@ -194,24 +253,29 @@ void session_yield(user_struct *vuser) sessionid.id_str, sessionid.id_num); } - smb_pam_close_session(sessionid.username, sessionid.id_str, sessionid.hostname); + smb_pam_close_session(sessionid.username, sessionid.id_str, + sessionid.hostname); + + rec->delete_rec(rec); - tdb_delete_bystring(tdb, vuser->session_keystr); + TALLOC_FREE(rec); } /******************************************************************** ********************************************************************/ -static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, - void *), - void *state) +static BOOL session_traverse(int (*fn)(struct db_record *db, + void *private_data), + void *private_data) { - if (!session_init()) { + struct db_context *ctx; + + if (!(ctx = session_db_ctx())) { DEBUG(3, ("No tdb opened\n")); return False; } - tdb_traverse(tdb, fn, state); + ctx->traverse(ctx, fn, private_data); return True; } @@ -224,23 +288,24 @@ struct session_list { struct sessionid *sessions; }; -static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +static int gather_sessioninfo(struct db_record *rec, void *state) { - uint32 i; struct session_list *sesslist = (struct session_list *) state; - const struct sessionid *current = (const struct sessionid *) dbuf.dptr; + const struct sessionid *current = + (const struct sessionid *) rec->value.dptr; - i = sesslist->count; - sesslist->sessions = TALLOC_REALLOC_ARRAY( - sesslist->mem_ctx, sesslist->sessions, struct sessionid, i+1); + sesslist->mem_ctx, sesslist->sessions, struct sessionid, + sesslist->count+1); if (!sesslist->sessions) { sesslist->count = 0; return -1; } - memcpy(&sesslist->sessions[i], current, sizeof(struct sessionid)); + memcpy(&sesslist->sessions[sesslist->count], current, + sizeof(struct sessionid)); + sesslist->count++; DEBUG(7,("gather_sessioninfo session from %s@%s\n", -- cgit From e8156439f24137b5418baad20a7f00f6949cfe29 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 09:30:34 +0000 Subject: r23183: Check in a change made by Tridge: This replaces the internal explicit dev/ino file id representation by a "struct file_id". This is necessary as cluster file systems and NFS don't necessarily assign the same device number to the shared file system. With this structure in place we can now easily add different schemes to map a file to a unique 64-bit device node. Jeremy, you might note that I did not change the external interface of smb_share_modes.c. Volker (This used to be commit 9b10dbbd5de8813fc15ebbb6be9b18010ffe8139) --- source3/smbd/close.c | 17 ++++---- source3/smbd/filename.c | 2 +- source3/smbd/files.c | 48 ++++++++++------------- source3/smbd/nttrans.c | 6 +-- source3/smbd/open.c | 69 ++++++++++++++------------------- source3/smbd/oplock.c | 94 ++++++++++++++++++--------------------------- source3/smbd/oplock_irix.c | 44 ++++++++++----------- source3/smbd/oplock_linux.c | 24 ++++++------ source3/smbd/reply.c | 39 +++++++++---------- source3/smbd/trans2.c | 8 ++-- 10 files changed, 158 insertions(+), 193 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 38b4988415..c4aa2e2e28 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -155,6 +155,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; + struct file_id id; /* * Lock the share entries, and determine if we should delete @@ -162,7 +163,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, * This prevents race conditions with the file being created. JRA. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_remove_share_mode: Could not get share mode " @@ -258,15 +259,17 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, goto done; } - if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { + id = file_id_sbuf(&sbuf); + + if (!file_id_equal(&fsp->file_id, &id)) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and dev and/or inode does not match\n", fsp->fsp_name )); - DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, " - "inode = %.0f stat dev = %x, inode = %.0f\n", + DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, " + "stat file_id %s\n", fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); + file_id_static_string(&fsp->file_id), + file_id_static_string2(&id))); /* * Don't save the errno here, we ignore this error */ @@ -405,7 +408,7 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty * reference to a directory also. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index eb86a0efd1..c26eba2ded 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -463,7 +463,7 @@ NTSTATUS unix_convert(connection_struct *conn, } /* end else */ #ifdef DEVELOPER - if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) { + if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) { return NT_STATUS_DELETE_PENDING; } #endif diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 062bebd58e..5ee0696ef9 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -38,8 +38,7 @@ static int files_used; /* A singleton cache to speed up searching by dev/inode. */ static struct fsp_singleton_cache { files_struct *fsp; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; } fsp_fi_cache; /**************************************************************************** @@ -104,7 +103,7 @@ NTSTATUS file_new(connection_struct *conn, files_struct **result) fsp->fh->fd = -1; fsp->conn = conn; - fsp->fh->file_id = get_gen_count(); + fsp->fh->gen_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; @@ -233,9 +232,9 @@ void file_dump_open_table(void) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { - DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n", - count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->file_id, - (unsigned int)fsp->dev, (double)fsp->inode )); + DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n", + count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id, + file_id_static_string(&fsp->file_id))); } } @@ -264,16 +263,15 @@ files_struct *file_find_fd(int fd) Find a fsp given a device, inode and file_id. ****************************************************************************/ -files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id) +files_struct *file_find_dif(struct file_id id, unsigned long gen_id) { int count=0; files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */ - if (fsp->dev == dev && - fsp->inode == inode && - fsp->fh->file_id == file_id ) { + if (file_id_equal(&fsp->file_id, &id) && + fsp->fh->gen_id == gen_id ) { if (count > 10) { DLIST_PROMOTE(Files, fsp); } @@ -281,10 +279,11 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i if ((fsp->fh->fd == -1) && (fsp->oplock_type != NO_OPLOCK) && (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { - DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \ -oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, (unsigned int)fsp->fh->file_id, - (unsigned int)fsp->oplock_type )); + DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \ +oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, + file_id_static_string(&fsp->file_id), + (unsigned int)fsp->fh->gen_id, + (unsigned int)fsp->oplock_type )); smb_panic("file_find_dif\n"); } return fsp; @@ -316,22 +315,20 @@ files_struct *file_find_fsp(files_struct *orig_fsp) calls. ****************************************************************************/ -files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) +files_struct *file_find_di_first(struct file_id id) { files_struct *fsp; - if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { + if (file_id_equal(&fsp_fi_cache.id, &id)) { /* Positive or negative cache hit. */ return fsp_fi_cache.fsp; } - fsp_fi_cache.dev = dev; - fsp_fi_cache.inode = inode; + fsp_fi_cache.id = id; for (fsp=Files;fsp;fsp=fsp->next) { if ( fsp->fh->fd != -1 && - fsp->dev == dev && - fsp->inode == inode ) { + file_id_equal(&fsp->file_id, &id)) { /* Setup positive cache. */ fsp_fi_cache.fsp = fsp; return fsp; @@ -353,9 +350,9 @@ files_struct *file_find_di_next(files_struct *start_fsp) for (fsp = start_fsp->next;fsp;fsp=fsp->next) { if ( fsp->fh->fd != -1 && - fsp->dev == start_fsp->dev && - fsp->inode == start_fsp->inode ) + file_id_equal(&fsp->file_id, &start_fsp->file_id)) { return fsp; + } } return NULL; @@ -392,9 +389,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod) } for (fsp = Files;fsp;fsp=fsp->next) { - if ( fsp->fh->fd != -1 && - fsp->dev == tfsp->dev && - fsp->inode == tfsp->inode ) { + if ( fsp->fh->fd != -1 && file_id_equal(&fsp->file_id, &tfsp->file_id)) { fsp->pending_modtime = mod; fsp->pending_modtime_owner = False; } @@ -542,8 +537,7 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->fh = fsp->fh; dup_fsp->fh->ref_count++; - dup_fsp->dev = fsp->dev; - dup_fsp->inode = fsp->inode; + dup_fsp->file_id = fsp->file_id; dup_fsp->initial_allocation_size = fsp->initial_allocation_size; dup_fsp->mode = fsp->mode; dup_fsp->file_pid = fsp->file_pid; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index eb4a6cd969..e8919f9faf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2300,11 +2300,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou if (pdata == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - SINO_T_VAL(pdata,0,fsp->inode); - SDEV_T_VAL(pdata,8,fsp->dev); + push_file_id_16(pdata, &fsp->file_id); memcpy(pdata+16,create_volume_objectid(conn,objid),16); - SINO_T_VAL(pdata,32,fsp->inode); - SDEV_T_VAL(pdata,40,fsp->dev); + push_file_id_16(pdata+32, &fsp->file_id); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); return -1; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 987da7a94d..30576f1e08 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,8 +30,7 @@ extern BOOL global_client_failed_oplock_break; struct deferred_open_record { BOOL delayed_for_oplocks; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; }; /**************************************************************************** @@ -359,8 +358,7 @@ static NTSTATUS open_file(files_struct *fsp, } fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = True; @@ -513,7 +511,7 @@ static void validate_my_share_entries(int num, return; } - fsp = file_find_dif(share_entry->dev, share_entry->inode, + fsp = file_find_dif(share_entry->id, share_entry->share_file_id); if (!fsp) { DEBUG(0,("validate_my_share_entries: PANIC : %s\n", @@ -803,7 +801,7 @@ static void defer_open(struct share_mode_lock *lck, (char *)state, sizeof(*state))) { exit_server("push_deferred_smb_message failed"); } - add_deferred_open(lck, mid, request_time, state->dev, state->inode); + add_deferred_open(lck, mid, request_time, state->id); /* * Push the MID of this packet on the signing queue. @@ -871,8 +869,8 @@ static BOOL open_match_attributes(connection_struct *conn, ****************************************************************************/ static files_struct *fcb_or_dos_open(connection_struct *conn, - const char *fname, SMB_DEV_T dev, - SMB_INO_T inode, + const char *fname, + struct file_id id, uint32 access_mask, uint32 share_access, uint32 create_options) @@ -883,7 +881,7 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " "file %s.\n", fname )); - for(fsp = file_find_di_first(dev, inode); fsp; + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " @@ -1093,8 +1091,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ a 1 second delay for share mode conflicts. */ state.delayed_for_oplocks = True; - state.dev = lck->dev; - state.inode = lck->ino; + state.id = lck->id; if (!request_timed_out(request_time, timeout)) { defer_open(lck, request_time, timeout, &state); @@ -1124,8 +1121,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, BOOL def_acl = False; BOOL posix_open = False; BOOL new_file_created = False; - SMB_DEV_T dev = 0; - SMB_INO_T inode = 0; + struct file_id id; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; @@ -1142,6 +1138,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, char *parent_dir; const char *newname; + ZERO_STRUCT(id); + if (conn->printer) { /* * Printers are handled completely differently. @@ -1192,7 +1190,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, request_time = pml->request_time; /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, state->id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1404,8 +1402,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - fsp->dev = psbuf->st_dev; - fsp->inode = psbuf->st_ino; + fsp->file_id = file_id_sbuf(psbuf); fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = open_access_mask; /* We change this to the @@ -1421,10 +1418,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { - dev = psbuf->st_dev; - inode = psbuf->st_ino; + id = file_id_sbuf(psbuf); - lck = get_share_mode_lock(NULL, dev, inode, + lck = get_share_mode_lock(NULL, id, conn->connectpath, fname); @@ -1483,8 +1479,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Use the client requested access mask here, * not the one we open with. */ - fsp_dup = fcb_or_dos_open(conn, fname, dev, - inode, access_mask, + fsp_dup = fcb_or_dos_open(conn, fname, id, + access_mask, share_access, create_options); @@ -1556,8 +1552,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, a 1 second delay for share mode conflicts. */ state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + state.id = id; if (!request_timed_out(request_time, timeout)) { @@ -1635,10 +1630,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * Nadav Danieli . JRA. */ - dev = fsp->dev; - inode = fsp->inode; + id = fsp->file_id; - lck = get_share_mode_lock(NULL, dev, inode, + lck = get_share_mode_lock(NULL, id, conn->connectpath, fname); @@ -1684,8 +1678,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, file_free(fsp); state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + state.id = id; /* Do it all over again immediately. In the second * round we will find that the file existed and handle @@ -2127,8 +2120,7 @@ NTSTATUS open_directory(connection_struct *conn, */ fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; @@ -2149,7 +2141,7 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, + lck = get_share_mode_lock(NULL, fsp->file_id, conn->connectpath, fname); @@ -2255,8 +2247,7 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, */ fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; @@ -2289,8 +2280,7 @@ void msg_file_was_renamed(struct messaging_context *msg, { files_struct *fsp; char *frm = (char *)data->data; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; const char *sharepath; const char *newname; size_t sp_len; @@ -2303,17 +2293,16 @@ void msg_file_was_renamed(struct messaging_context *msg, } /* Unpack the message. */ - dev = DEV_T_VAL(frm,0); - inode = INO_T_VAL(frm,8); + pull_file_id_16(frm, &id); sharepath = &frm[16]; newname = sharepath + strlen(sharepath) + 1; sp_len = strlen(sharepath); DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " - "dev %x, inode %.0f\n", - sharepath, newname, (unsigned int)dev, (double)inode )); + "file_id %s\n", + sharepath, newname, file_id_static_string(&id))); - for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", fsp->fnum, fsp->fsp_name, newname )); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 63f88b7824..9f3679390b 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -87,9 +87,8 @@ void process_kernel_oplocks(struct messaging_context *msg_ctx, fd_set *pfds) } /* Put the kernel break info into the message. */ - SDEV_T_VAL(msg,0,fsp->dev); - SINO_T_VAL(msg,8,fsp->inode); - SIVAL(msg,16,fsp->fh->file_id); + push_file_id_16(msg, &fsp->file_id); + SIVAL(msg,16,fsp->fh->gen_id); /* Don't need to be root here as we're only ever sending to ourselves. */ @@ -119,10 +118,10 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) exclusive_oplocks_open++; } - DEBUG(5,("set_file_oplock: granted oplock on file %s, 0x%x/%.0f/%lu, " + DEBUG(5,("set_file_oplock: granted oplock on file %s, %s/%lu, " "tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id, (int)fsp->open_time.tv_sec, + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); return True; @@ -178,13 +177,11 @@ static void downgrade_file_oplock(files_struct *fsp) BOOL remove_oplock(files_struct *fsp) { - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; BOOL ret; struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -193,9 +190,8 @@ BOOL remove_oplock(files_struct *fsp) ret = remove_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("remove_oplock: failed to remove share oplock for " - "file %s fnum %d, 0x%x/%.0f\n", - fsp->fsp_name, fsp->fnum, (unsigned int)dev, - (double)inode)); + "file %s fnum %d, %s\n", + fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id))); } release_file_oplock(fsp); TALLOC_FREE(lck); @@ -207,12 +203,10 @@ BOOL remove_oplock(files_struct *fsp) */ BOOL downgrade_oplock(files_struct *fsp) { - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; BOOL ret; struct share_mode_lock *lck; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -221,9 +215,8 @@ BOOL downgrade_oplock(files_struct *fsp) ret = downgrade_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " - "for file %s fnum %d, dev = %x, inode = %.0f\n", - fsp->fsp_name, fsp->fnum, (unsigned int)dev, - (double)inode)); + "for file %s fnum %d, file_id %s\n", + fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id))); } downgrade_file_oplock(fsp); @@ -289,13 +282,13 @@ static void wait_before_sending_break(void) Ensure that we have a valid oplock. ****************************************************************************/ -static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id) +static files_struct *initial_break_processing(struct file_id id, unsigned long file_id) { files_struct *fsp = NULL; if( DEBUGLVL( 3 ) ) { - dbgtext( "initial_break_processing: called for 0x%x/%.0f/%u\n", - (unsigned int)dev, (double)inode, (int)file_id); + dbgtext( "initial_break_processing: called for %s/%u\n", + file_id_static_string(&id), (int)file_id); dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", exclusive_oplocks_open, level_II_oplocks_open ); } @@ -306,14 +299,13 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un * we have an oplock on it. */ - fsp = file_find_dif(dev, inode, file_id); + fsp = file_find_dif(id, file_id); if(fsp == NULL) { /* The file could have been closed in the meantime - return success. */ if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: cannot find open file with " ); - dbgtext( "dev = 0x%x, inode = %.0f file_id = %lu", (unsigned int)dev, - (double)inode, file_id); + dbgtext( "file_id %s gen_id = %lu", file_id_static_string(&id), file_id); dbgtext( "allowing break to succeed.\n" ); } return NULL; @@ -332,8 +324,8 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un if(fsp->oplock_type == NO_OPLOCK) { if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n", - (unsigned int)dev, (double)inode, fsp->fh->file_id ); + dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n", + file_id_static_string(&id), fsp->fh->gen_id ); dbgtext( "Allowing break to succeed regardless.\n" ); } return NULL; @@ -415,12 +407,10 @@ static void process_oplock_async_level2_break_message(struct messaging_context * /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id)); + DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id)); - fsp = initial_break_processing(msg.dev, msg.inode, - msg.share_file_id); + fsp = initial_break_processing(msg.id, msg.share_file_id); if (fsp == NULL) { /* We hit a race here. Break messages are sent, and before we @@ -505,12 +495,10 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id)); + DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id)); - fsp = initial_break_processing(msg.dev, msg.inode, - msg.share_file_id); + fsp = initial_break_processing(msg.id, msg.share_file_id); if (fsp == NULL) { /* a We hit race here. Break messages are sent, and before we @@ -537,8 +525,8 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) && !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n", - (unsigned int)fsp->dev, (double)fsp->inode, + DEBUG(3, ("Already downgraded oplock on %s: %s\n", + file_id_static_string(&fsp->file_id), fsp->fsp_name)); /* We just send the same message back. */ messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE, @@ -599,8 +587,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, struct server_id src, DATA_BLOB *data) { - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; unsigned long file_id; files_struct *fsp; char *break_msg; @@ -617,15 +604,14 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, } /* Pull the data from the message. */ - dev = DEV_T_VAL(data->data, 0); - inode = INO_T_VAL(data->data, 8); + pull_file_id_16((char *)data->data, &id); file_id = (unsigned long)IVAL(data->data, 16); - DEBUG(10, ("Got kernel oplock break message from pid %d: 0x%x/%.0f/%u\n", - (int)procid_to_pid(&src), (unsigned int)dev, (double)inode, + DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n", + (int)procid_to_pid(&src), file_id_static_string(&id), (unsigned int)file_id)); - fsp = initial_break_processing(dev, inode, file_id); + fsp = initial_break_processing(id, file_id); if (fsp == NULL) { DEBUG(3, ("Got a kernel oplock break message for a file " @@ -711,9 +697,8 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id, + DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id, (unsigned int)msg.op_mid)); /* Here's the hack from open.c, store the mid in the 'port' field */ @@ -741,9 +726,8 @@ static void process_open_retry_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id, + DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), (unsigned int)msg.op_mid)); schedule_deferred_open_smb_message(msg.op_mid); @@ -771,7 +755,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " "share mode entry for file %s.\n", fsp->fsp_name )); @@ -845,8 +829,7 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e) SIVAL(msg,16,e->private_options); SIVAL(msg,20,(uint32)e->time.tv_sec); SIVAL(msg,24,(uint32)e->time.tv_usec); - SDEV_T_VAL(msg,28,e->dev); - SINO_T_VAL(msg,36,e->inode); + push_file_id_16(msg+28, &e->id); SIVAL(msg,44,e->share_file_id); SIVAL(msg,48,e->uid); SSVAL(msg,52,e->flags); @@ -866,8 +849,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) e->private_options = IVAL(msg,16); e->time.tv_sec = (time_t)IVAL(msg,20); e->time.tv_usec = (int)IVAL(msg,24); - e->dev = DEV_T_VAL(msg,28); - e->inode = INO_T_VAL(msg,36); + pull_file_id_16(msg+28, &e->id); e->share_file_id = (unsigned long)IVAL(msg,44); e->uid = (uint32)IVAL(msg,48); e->flags = (uint16)SVAL(msg,52); diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index c1159cd73b..1ac0cb4674 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -149,9 +149,9 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) } DEBUG(5,("irix_oplock_receive_message: kernel oplock break request " - "received for dev = %x, inode = %.0f\n, file_id = %ul", - (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id )); + "received for file_id %s gen_id = %ul", + file_id_static_string(&fsp->file_id), + fsp->fh->gen_id )); return fsp; } @@ -165,27 +165,27 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) { if(errno != EAGAIN) { DEBUG(0,("irix_set_kernel_oplock: Unable to get " - "kernel oplock on file %s, dev = %x, inode " - "= %.0f, file_id = %ul. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, + "kernel oplock on file %s, file_id %s " + "gen_id = %ul. Error was %s\n", + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, strerror(errno) )); } else { DEBUG(5,("irix_set_kernel_oplock: Refused oplock on " - "file %s, fd = %d, dev = %x, inode = %.0f, " - "file_id = %ul. Another process had the file " + "file %s, fd = %d, file_id = 5s, " + "gen_id = %ul. Another process had the file " "open.\n", fsp->fsp_name, fsp->fh->fd, - (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id )); + file_id_static_string(&fsp->file_id), + fsp->fh->gen_id )); } return False; } - DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev " - "= %x, inode = %.0f, file_id = %ul\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id)); + DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s " + "gen_id = %ul\n", + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id)); return True; } @@ -202,10 +202,10 @@ static void irix_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); - dbgtext("irix_release_kernel_oplock: file %s, dev = %x, " - "inode = %.0f file_id = %ul, has kernel oplock state " - "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, state ); + dbgtext("irix_release_kernel_oplock: file %s, file_id = %s" + "gen_id = %ul, has kernel oplock state " + "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, state ); } /* @@ -215,10 +215,10 @@ static void irix_release_kernel_oplock(files_struct *fsp) if( DEBUGLVL( 0 )) { dbgtext("irix_release_kernel_oplock: Error when " "removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. " + dbgtext("%s, file_id = %s gen_id = %ul. " "Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, strerror(errno) ); } } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 14db98cde6..e12a9d66ca 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -167,17 +167,17 @@ static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " - "fd = %d, dev = %x, inode = %.0f. (%s)\n", + "fd = %d, file_id = %s. (%s)\n", fsp->fsp_name, fsp->fh->fd, - (unsigned int)fsp->dev, (double)fsp->inode, + file_id_static_string(&fsp->file_id), strerror(errno))); return False; } DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, " - "dev = %x, inode = %.0f, file_id = %lu\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id)); + "file_id = %s gen_id = %lu\n", + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id)); return True; } @@ -194,10 +194,10 @@ static void linux_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); - dbgtext("linux_release_kernel_oplock: file %s, dev = %x, " - "inode = %.0f file_id = %lu has kernel oplock state " - "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, state ); + dbgtext("linux_release_kernel_oplock: file %s, file_id = %s " + "gen_id = %lu has kernel oplock state " + "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, state ); } /* @@ -207,10 +207,10 @@ static void linux_release_kernel_oplock(files_struct *fsp) if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when " "removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. " + dbgtext("%s, file_id = %s, gen_id = %lu. " "Error was %s\n", fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id, strerror(errno) ); + file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, strerror(errno) ); } } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 40311758c9..6d4c08b663 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4171,12 +4171,12 @@ static BOOL resolve_wildcards(const char *name1, char *name2) ****************************************************************************/ static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, - SMB_DEV_T dev, SMB_INO_T inode, const char *newname) + struct file_id id, const char *newname) { files_struct *fsp; BOOL did_rename = False; - for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { /* fsp_name is a relative path under the fsp. To change this for other sharepaths we need to manipulate relative paths. */ /* TODO - create the absolute path and manipulate the newname @@ -4184,16 +4184,16 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l if (fsp->conn != conn) { continue; } - DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", - fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode, + DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n", + fsp->fnum, file_id_static_string(&fsp->file_id), fsp->fsp_name, newname )); string_set(&fsp->fsp_name, newname); did_rename = True; } if (!did_rename) { - DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n", - (unsigned int)dev, (double)inode, newname )); + DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n", + file_id_static_string(&id), newname )); } /* Send messages to all smbd's (not ourself) that the name has changed. */ @@ -4341,7 +4341,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_ACCESS_DENIED; } - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { uint32 create_options = fsp->fh->private_options; @@ -4349,7 +4349,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); - rename_open_files(conn, lck, fsp->dev, fsp->inode, newname); + rename_open_files(conn, lck, fsp->file_id, newname); /* * A rename acts as a new file create w.r.t. allowing an initial delete @@ -4457,6 +4457,7 @@ NTSTATUS rename_internals(connection_struct *conn, const char *dname; long offset = 0; pstring destname; + struct file_id id; *directory = *mask = 0; @@ -4635,9 +4636,10 @@ NTSTATUS rename_internals(connection_struct *conn, * don't do the rename, just return success. */ + id = file_id_sbuf(&sbuf1); + if (strcsequal(directory, newname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, NULL, id, newname); DEBUG(3, ("rename_internals: identical names in " "rename %s - returning success\n", directory)); @@ -4654,14 +4656,12 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, - NULL, NULL); + lck = get_share_mode_lock(NULL, id, NULL, NULL); if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename " "on %s -> %s\n", directory, newname)); - rename_open_files(conn, lck, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, lck, id, newname); TALLOC_FREE(lck); notify_rename(conn, S_ISDIR(sbuf1.st_mode), directory, newname); @@ -4768,9 +4768,10 @@ NTSTATUS rename_internals(connection_struct *conn, return status; } + id = file_id_sbuf(&sbuf1); + if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, NULL, id, newname); DEBUG(3,("rename_internals: identical names " "in wildcard rename %s - success\n", fname)); @@ -4789,12 +4790,10 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, - sbuf1.st_ino, NULL, NULL); + lck = get_share_mode_lock(NULL, id, NULL, NULL); if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, lck, id, newname); count++; status = NT_STATUS_OK; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 835fd0cedb..429fdc154d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3366,7 +3366,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return UNIXERROR(ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); } else { /* * Original code - this is an open file. @@ -3379,7 +3379,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return(UNIXERROR(ERRDOS,ERRbadfid)); } pos = fsp->fh->position_information; - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); access_mask = fsp->access_mask; } } else { @@ -3432,7 +3432,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return UNIXERROR(ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); if (delete_pending) { return ERROR_NT(NT_STATUS_DELETE_PENDING); } @@ -3559,7 +3559,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } else { /* Do we have this path open ? */ - files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); + files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf)); if (fsp1 && !null_timespec(fsp1->pending_modtime)) { /* the pending modtime overrides the current modtime */ mtime_ts = fsp1->pending_modtime; -- cgit From fb76516ccd06bd5d2e013d07c4477e28df74962a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 10:48:42 +0000 Subject: r23185: Try to fix the IRIX build, also add the forgotten file_id.c in .26 (This used to be commit 5360e6405b170137e558fd0696ebd6030e0f5deb) --- source3/smbd/oplock_irix.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 1ac0cb4674..eb0164ae50 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -140,8 +140,9 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) * is the first fsp open with this dev,ino pair. */ - if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev, - (SMB_INO_T)os.os_ino)) == NULL) { + if ((fsp = file_find_di_first( + file_id_create((SMB_DEV_T)os.os_dev, + (SMB_INO_T)os.os_ino))) == NULL) { DEBUG(0,("irix_oplock_receive_message: unable to find open " "file with dev = %x, inode = %.0f\n", (unsigned int)os.os_dev, (double)os.os_ino )); -- cgit From 9c6f9fa28a849035ee40bb65e8a79c5f555242d6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 10:50:25 +0000 Subject: r23186: Checkin on behalf of Tridge: Change notify.tdb to use dbwrap (This used to be commit 3a089403871df88f4a3bf86c3db0d169cd4fb434) --- source3/smbd/notify_internal.c | 114 ++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 57 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 940ff8aae9..20bfb74a29 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -28,13 +28,14 @@ #include "librpc/gen_ndr/ndr_notify.h" struct notify_context { - struct tdb_wrap *w; + struct db_context *db; struct server_id server; struct messaging_context *messaging_ctx; struct notify_list *list; struct notify_array *array; int seqnum; struct sys_notify_context *sys_notify_ctx; + TDB_DATA key; }; @@ -91,10 +92,10 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, return NULL; } - notify->w = tdb_wrap_open(notify, lock_path("notify.tdb"), + notify->db = db_open(notify, lock_path("notify.tdb"), 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644); - if (notify->w == NULL) { + if (notify->db == NULL) { talloc_free(notify); return NULL; } @@ -103,7 +104,8 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, notify->messaging_ctx = messaging_ctx; notify->list = NULL; notify->array = NULL; - notify->seqnum = tdb_get_seqnum(notify->w->tdb); + notify->seqnum = notify->db->get_seqnum(notify->db); + notify->key = string_term_tdb_data(NOTIFY_KEY); talloc_set_destructor(notify, notify_destructor); @@ -117,37 +119,29 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, return notify; } - /* - lock the notify db + lock and fetch the record */ -static NTSTATUS notify_lock(struct notify_context *notify) +static NTSTATUS notify_fetch_locked(struct notify_context *notify, struct db_record **rec) { - if (tdb_lock_bystring(notify->w->tdb, NOTIFY_KEY) != 0) { + *rec = notify->db->fetch_locked(notify->db, notify, notify->key); + if (*rec == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } return NT_STATUS_OK; } -/* - unlock the notify db -*/ -static void notify_unlock(struct notify_context *notify) -{ - tdb_unlock_bystring(notify->w->tdb, NOTIFY_KEY); -} - /* load the notify array */ -static NTSTATUS notify_load(struct notify_context *notify) +static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec) { TDB_DATA dbuf; DATA_BLOB blob; NTSTATUS status; int seqnum; - seqnum = tdb_get_seqnum(notify->w->tdb); + seqnum = notify->db->get_seqnum(notify->db); if (seqnum == notify->seqnum && notify->array != NULL) { return NT_STATUS_OK; @@ -159,23 +153,32 @@ static NTSTATUS notify_load(struct notify_context *notify) notify->array = TALLOC_ZERO_P(notify, struct notify_array); NT_STATUS_HAVE_NO_MEMORY(notify->array); - dbuf = tdb_fetch_bystring(notify->w->tdb, NOTIFY_KEY); - if (dbuf.dptr == NULL) { - return NT_STATUS_OK; + if (!rec) { + if (notify->db->fetch(notify->db, notify, notify->key, &dbuf) != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + } else { + dbuf = rec->value; } blob.data = (uint8 *)dbuf.dptr; blob.length = dbuf.dsize; - status = ndr_pull_struct_blob(&blob, notify->array, notify->array, - (ndr_pull_flags_fn_t)ndr_pull_notify_array); + if (blob.length == 0) { + status = NT_STATUS_OK; + } else { + status = ndr_pull_struct_blob(&blob, notify->array, notify->array, + (ndr_pull_flags_fn_t)ndr_pull_notify_array); + } if (DEBUGLEVEL >= 10) { DEBUG(10, ("notify_load:\n")); NDR_PRINT_DEBUG(notify_array, notify->array); } - free(dbuf.dptr); + if (!rec) { + talloc_free(dbuf.dptr); + } return status; } @@ -193,12 +196,11 @@ static int notify_compare(const void *p1, const void *p2) /* save the notify array */ -static NTSTATUS notify_save(struct notify_context *notify) +static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec) { TDB_DATA dbuf; DATA_BLOB blob; NTSTATUS status; - int ret; TALLOC_CTX *tmp_ctx; /* if possible, remove some depth arrays */ @@ -209,11 +211,7 @@ static NTSTATUS notify_save(struct notify_context *notify) /* we might just be able to delete the record */ if (notify->array->num_depths == 0) { - ret = tdb_delete_bystring(notify->w->tdb, NOTIFY_KEY); - if (ret != 0) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - return NT_STATUS_OK; + return rec->delete_rec(rec); } tmp_ctx = talloc_new(notify); @@ -233,14 +231,11 @@ static NTSTATUS notify_save(struct notify_context *notify) dbuf.dptr = blob.data; dbuf.dsize = blob.length; - - ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE); + + status = rec->store(rec, dbuf, TDB_REPLACE); talloc_free(tmp_ctx); - if (ret != 0) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - return NT_STATUS_OK; + return status; } @@ -293,7 +288,8 @@ static void sys_notify_callback(struct sys_notify_context *ctx, /* add an entry to the notify array */ -static NTSTATUS notify_add_array(struct notify_context *notify, struct notify_entry *e, +static NTSTATUS notify_add_array(struct notify_context *notify, struct db_record *rec, + struct notify_entry *e, void *private_data, int depth) { int i; @@ -341,7 +337,7 @@ static NTSTATUS notify_add_array(struct notify_context *notify, struct notify_en d->max_mask_subdir |= d->entries[i].subdir_filter; } - return notify_save(notify); + return notify_save(notify, rec); } /* @@ -358,18 +354,20 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0, struct notify_list *listel; size_t len; int depth; + struct db_record *rec; /* see if change notify is enabled at all */ if (notify == NULL) { return NT_STATUS_NOT_IMPLEMENTED; } - status = notify_lock(notify); + status = notify_fetch_locked(notify, &rec); NT_STATUS_NOT_OK_RETURN(status); - status = notify_load(notify); + status = notify_load(notify, rec); if (!NT_STATUS_IS_OK(status)) { - goto done; + talloc_free(rec); + return status; } /* cope with /. on the end of the path */ @@ -415,11 +413,11 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0, then we need to install it in the array used for the intra-samba notify handling */ if (e.filter != 0 || e.subdir_filter != 0) { - status = notify_add_array(notify, &e, private_data, depth); + status = notify_add_array(notify, rec, &e, private_data, depth); } done: - notify_unlock(notify); + talloc_free(rec); talloc_free(tmp_path); return status; @@ -434,6 +432,7 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data) struct notify_list *listel; int i, depth; struct notify_depth *d; + struct db_record *rec; /* see if change notify is enabled at all */ if (notify == NULL) { @@ -454,17 +453,17 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data) talloc_free(listel); - status = notify_lock(notify); + status = notify_fetch_locked(notify, &rec); NT_STATUS_NOT_OK_RETURN(status); - status = notify_load(notify); + status = notify_load(notify, rec); if (!NT_STATUS_IS_OK(status)) { - notify_unlock(notify); + talloc_free(rec); return status; } if (depth >= notify->array->num_depths) { - notify_unlock(notify); + talloc_free(rec); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -478,7 +477,7 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data) } } if (i == d->num_entries) { - notify_unlock(notify); + talloc_free(rec); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -488,9 +487,9 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data) } d->num_entries--; - status = notify_save(notify); + status = notify_save(notify, rec); - notify_unlock(notify); + talloc_free(rec); return status; } @@ -503,13 +502,14 @@ static NTSTATUS notify_remove_all(struct notify_context *notify, { NTSTATUS status; int i, depth, del_count=0; + struct db_record *rec; - status = notify_lock(notify); + status = notify_fetch_locked(notify, &rec); NT_STATUS_NOT_OK_RETURN(status); - status = notify_load(notify); + status = notify_load(notify, rec); if (!NT_STATUS_IS_OK(status)) { - notify_unlock(notify); + talloc_free(rec); return status; } @@ -531,10 +531,10 @@ static NTSTATUS notify_remove_all(struct notify_context *notify, } if (del_count > 0) { - status = notify_save(notify); + status = notify_save(notify, rec); } - notify_unlock(notify); + talloc_free(rec); return status; } @@ -594,7 +594,7 @@ void notify_trigger(struct notify_context *notify, } again: - status = notify_load(notify); + status = notify_load(notify, NULL); if (!NT_STATUS_IS_OK(status)) { return; } -- cgit From 3f5742e20b30010ef88e19b6ee41c6b071258aee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 14:49:19 +0000 Subject: r23204: Add MSG_SMB_BRL_VALIDATE. Tridge, this is a bit different from your bzr branch, please check if it fulfils your needs. Two changes: The validation is not done inside the brlock.c traverse_fn, it's done as a separate routine. Secondly, this patch does not call the checker routines in smbcontrol directly but depends on a running smbd. (This used to be commit 7e39d77c1f90d9025cab08918385d140e20ca25b) --- source3/smbd/server.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index fc1faa9d36..f837d38ac6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -375,6 +375,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ MSG_SMB_CONF_UPDATED, smb_conf_updated); messaging_register(smbd_messaging_context(), NULL, MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete); + brl_register_msgs(smbd_messaging_context()); #ifdef DEVELOPER messaging_register(smbd_messaging_context(), NULL, @@ -991,6 +992,7 @@ extern void build_options(BOOL screen); } /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ + if (smbd_messaging_context() == NULL) exit(1); -- cgit From 403684f7bd199bd569d7fa8c17da79e0e8a1ccc9 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 29 May 2007 14:53:13 +0000 Subject: r23206: remove unreachable code (This used to be commit 6e2bb4836fab5e548429613dea431007af3a7995) --- source3/smbd/nttrans.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e8919f9faf..a1edc99bce 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2307,7 +2307,6 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou return -1; } - case FSCTL_GET_REPARSE_POINT: /* pretend this fail - my winXP does it like this * --metze @@ -2315,7 +2314,6 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT); - return -1; case FSCTL_SET_REPARSE_POINT: /* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case. @@ -2324,7 +2322,6 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT); - return -1; case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ { -- cgit From a9503016859dc4bc3f68eb302c1adf37bf311187 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 18:04:38 +0000 Subject: r23220: Add traverse_read to dbwrap (This used to be commit b38dc5ffdfe9fdc2879c57dc181815f06b4747fe) --- source3/smbd/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 837c37a49f..d5973ef5c3 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -275,7 +275,7 @@ static BOOL session_traverse(int (*fn)(struct db_record *db, return False; } - ctx->traverse(ctx, fn, private_data); + ctx->traverse_read(ctx, fn, private_data); return True; } -- cgit From 3a931bc8fc32c7578095e4ebd80e5cfcf9f978ef Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 18:14:54 +0000 Subject: r23221: Fix a bad merge, avoid a memory leak and tdb lock problem (This used to be commit 2e2415655d352708b9799ae5ff4d9276c49cfb3b) --- source3/smbd/connection.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 4c4ddbc0f0..211f0e6acb 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -43,6 +43,7 @@ BOOL yield_connection(connection_struct *conn, const char *name) nt_errstr(status))); } + TALLOC_FREE(rec); return NT_STATUS_IS_OK(status); } -- cgit From 4b70daaa59cd49afcdaa2934aee4b257f9157682 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 30 May 2007 07:02:40 +0000 Subject: r23236: Another bad merge: Correctly free and unlock the session record in session_claim. Jerry, this fixes the hanging smbstatus. Sorry for that, Volker (This used to be commit 86ff82a5df998045185682cf09b2db3d37f01004) --- source3/smbd/session.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index d5973ef5c3..6b1bb0cbee 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -192,10 +192,11 @@ BOOL session_claim(user_struct *vuser) status = rec->store(rec, data, TDB_REPLACE); + TALLOC_FREE(rec); + if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("session_claim: unable to create session id " "record: %s\n", nt_errstr(status))); - TALLOC_FREE(rec); return False; } -- cgit From 9f3b3b3bd60dcd3f72427de993e72eb6b0ac43e3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 30 May 2007 13:41:38 +0000 Subject: r23241: In preparation for the cluster messaging import the parent smbd needs to respond to events.c style events. (This used to be commit 476080df3ff19c3c4742928ff50293935e171f99) --- source3/smbd/server.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f837d38ac6..8aa4e848a8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -386,7 +386,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ for each incoming connection */ DEBUG(2,("waiting for a connection\n")); while (1) { - fd_set lfds; + struct timeval now; + fd_set r_fds, w_fds; int num; /* Free up temporary memory from the main smbd. */ @@ -404,13 +405,21 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ } } - memcpy((char *)&lfds, (char *)&listen_set, + memcpy((char *)&r_fds, (char *)&listen_set, sizeof(listen_set)); + FD_ZERO(&w_fds); + GetTimeOfDay(&now); - num = sys_select(maxfd+1,&lfds,NULL,NULL, + event_add_to_select_args(smbd_event_context(), &now, + &r_fds, &w_fds, &idle_timeout, + &maxfd); + + num = sys_select(maxfd+1,&r_fds,&w_fds,NULL, timeval_is_zero(&idle_timeout) ? NULL : &idle_timeout); + run_events(smbd_event_context(), num, &r_fds, &w_fds); + if (num == -1 && errno == EINTR) { if (got_sig_term) { exit_server_cleanly(NULL); @@ -427,6 +436,10 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ continue; } +#if 0 + Deactivated for now, this needs to become a timed event + vl + /* If the idle timeout fired and we don't have any connected * users, exit gracefully. We should be running under a process * controller that will restart us if necessry. @@ -434,6 +447,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ if (num == 0 && count_all_current_connections() == 0) { exit_server_cleanly("idle timeout"); } +#endif /* check if we need to reload services */ check_reload(time(NULL)); @@ -447,11 +461,11 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ s = -1; for(i = 0; i < num_sockets; i++) { - if(FD_ISSET(fd_listenset[i],&lfds)) { + if(FD_ISSET(fd_listenset[i],&r_fds)) { s = fd_listenset[i]; /* Clear this so we don't look at it again. */ - FD_CLR(fd_listenset[i],&lfds); + FD_CLR(fd_listenset[i],&r_fds); break; } } -- cgit From 1a13bb5112dc51d6d7da801e9a7dd2655f067a6f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 May 2007 17:26:30 +0000 Subject: r23272: Fix main event loop - reviewed by Volker. Jeremy. (This used to be commit dfb4cb5d2bd6c50ad2ecfa729d76daccfc43925a) --- source3/smbd/server.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8aa4e848a8..e95f3cf4a2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -418,8 +418,6 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ timeval_is_zero(&idle_timeout) ? NULL : &idle_timeout); - run_events(smbd_event_context(), num, &r_fds, &w_fds); - if (num == -1 && errno == EINTR) { if (got_sig_term) { exit_server_cleanly(NULL); @@ -436,6 +434,10 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ continue; } + if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { + continue; + } + #if 0 Deactivated for now, this needs to become a timed event vl -- cgit From 7d48db6a622af587d2f3fa2541b77fa1179ca042 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 1 Jun 2007 19:34:08 +0000 Subject: r23299: Fix the build for !WITH_SENDFILE. (This used to be commit 87b92e7ebda018f1d6a588748e282dc1a2c50613) --- source3/smbd/reply.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6d4c08b663..3a80d9eaa6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2246,11 +2246,10 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st return; } - - normal_readbraw: - #endif +normal_readbraw: + if (nread > 0) { ret = read_file(fsp,outbuf+4,startpos,nread); #if 0 /* mincount appears to be ignored in a W2K server. JRA. */ @@ -2646,7 +2645,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length #endif - normal_read: +normal_read: if ((smb_maxcnt & 0xFF0000) > 0x10000) { int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt; -- cgit From 72e76cb90b26a0ff907bdd16b61de3a95984e9a8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 4 Jun 2007 22:29:23 +0000 Subject: r23346: Fix offline caching with XP/Vista. It was an off-by-one in storing the access mask. I shouldn't have made this mistake. Damn. Fixes bug #4673. Jeremy (This used to be commit 84801d4e83786b9de3d0875a317ca9ed8ff5b3e4) --- source3/smbd/nttrans.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a1edc99bce..71e6dd47b4 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -420,7 +420,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, p += 4; if (flags & EXTENDED_RESPONSE_REQUIRED) { - p += 26; + p += 25; SIVAL(p,0,FILE_GENERIC_ALL); /* * For pipes W2K3 seems to return @@ -950,7 +950,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if (flags & EXTENDED_RESPONSE_REQUIRED) { uint32 perms = 0; - p += 26; + p += 25; if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) { perms = FILE_GENERIC_ALL; } else { @@ -1035,7 +1035,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha p += 4; if (flags & EXTENDED_RESPONSE_REQUIRED) { - p += 26; + p += 25; SIVAL(p,0,FILE_GENERIC_ALL); /* * For pipes W2K3 seems to return @@ -1631,7 +1631,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (flags & EXTENDED_RESPONSE_REQUIRED) { uint32 perms = 0; - p += 26; + p += 25; if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) { perms = FILE_GENERIC_ALL; } else { -- cgit From 075a5dfdc43303734122160e1a82c7685e616002 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 7 Jun 2007 07:49:43 +0000 Subject: r23375: Fix a 64-bit warning (This used to be commit c592b562fa793c9fb3bd0d84074d4ffaa8f63b64) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 30576f1e08..41fbce9889 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2288,7 +2288,7 @@ void msg_file_was_renamed(struct messaging_context *msg, if (data->data == NULL || data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) { DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", - data->length)); + (int)data->length)); return; } -- cgit From 334c961cc55aafb6b5587ba8ab517b94f1cbe278 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jun 2007 19:52:18 +0000 Subject: r23390: First part of the patch to make Apple's life easier. Doing this in two stages to make it very easy to review. Context switching must look like : gain_root(); sys_setgroups(ngroups, groups); become_id(uid, gid); Re-arrange order so these three calls are always seen together. Next will be to turn these into a function. Jeremy. (This used to be commit eb537185ee4a3f460709267c843c9303a9bb61b5) --- source3/smbd/sec_ctx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index be00db9adb..14faba5ee3 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -243,11 +243,13 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN debug_nt_user_token(DBGC_CLASS, 5, token); debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups); + /* Start context switch */ gain_root(); - #ifdef HAVE_SETGROUPS sys_setgroups(ngroups, groups); #endif + become_id(uid, gid); + /* end context switch */ ctx_p->ut.ngroups = ngroups; @@ -277,8 +279,6 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN ctx_p->token = NULL; } - become_id(uid, gid); - ctx_p->ut.uid = uid; ctx_p->ut.gid = gid; @@ -334,15 +334,15 @@ BOOL pop_sec_ctx(void) sec_ctx_stack_ndx--; - gain_root(); - prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; + /* Start context switch */ + gain_root(); #ifdef HAVE_SETGROUPS sys_setgroups(prev_ctx_p->ut.ngroups, prev_ctx_p->ut.groups); #endif - become_id(prev_ctx_p->ut.uid, prev_ctx_p->ut.gid); + /* end context switch */ /* Update current_user stuff */ -- cgit From 0a1f5d71e4ad551f178613fff8bd288ad0cad057 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jun 2007 19:58:32 +0000 Subject: r23391: Second part of the patch for Apple. Change the sequence : gain_root(); sys_setgroups(ngroups, groups); become_id(uid, gid); to a function call : set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) James - should be safe for you to create a Darwin-specific version of this function now. Jeremy. (This used to be commit 8ee982b3678be41ce8b4f4c1df428dcbf897ccbe) --- source3/smbd/sec_ctx.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 14faba5ee3..fd79fbb7fe 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -227,6 +227,21 @@ BOOL push_sec_ctx(void) return True; } +/**************************************************************************** + Change UNIX security context. Calls panic if not successful so no return value. +****************************************************************************/ + +static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) +{ + /* Start context switch */ + gain_root(); +#ifdef HAVE_SETGROUPS + sys_setgroups(ngroups, groups); +#endif + become_id(uid, gid); + /* end context switch */ +} + /**************************************************************************** Set the current security context to a given user. ****************************************************************************/ @@ -243,13 +258,8 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN debug_nt_user_token(DBGC_CLASS, 5, token); debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups); - /* Start context switch */ - gain_root(); -#ifdef HAVE_SETGROUPS - sys_setgroups(ngroups, groups); -#endif - become_id(uid, gid); - /* end context switch */ + /* Change uid, gid and supplementary group list. */ + set_unix_security_ctx(uid, gid, ngroups, groups); ctx_p->ut.ngroups = ngroups; @@ -336,13 +346,11 @@ BOOL pop_sec_ctx(void) prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; - /* Start context switch */ - gain_root(); -#ifdef HAVE_SETGROUPS - sys_setgroups(prev_ctx_p->ut.ngroups, prev_ctx_p->ut.groups); -#endif - become_id(prev_ctx_p->ut.uid, prev_ctx_p->ut.gid); - /* end context switch */ + /* Change uid, gid and supplementary group list. */ + set_unix_security_ctx(prev_ctx_p->ut.uid, + prev_ctx_p->ut.gid, + prev_ctx_p->ut.ngroups, + prev_ctx_p->ut.groups); /* Update current_user stuff */ -- cgit From 74c74f8dccc01c99c8098dcb0dcae5cfaa81566d Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 8 Jun 2007 22:25:55 +0000 Subject: r23393: Support BSD group semantics by making sure that the effective GID is always passed as the first GID when calling setgroups(2). (This used to be commit 6ebaf856c1d27f2fbfa0444a5c6c17c4331d2780) --- source3/smbd/sec_ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index fd79fbb7fe..19dac0d27f 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -236,7 +236,7 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou /* Start context switch */ gain_root(); #ifdef HAVE_SETGROUPS - sys_setgroups(ngroups, groups); + sys_setgroups(gid, ngroups, groups); #endif become_id(uid, gid); /* end context switch */ -- cgit From bde0642ab43b92b780bd60cc889116154110c878 Mon Sep 17 00:00:00 2001 From: James Peach Date: Sat, 9 Jun 2007 00:10:26 +0000 Subject: r23398: Support membership of >16 groups on Darwin by making sure we opt in to the dynamic group resolution mechanism when switching UNIX credentials. (This used to be commit b5cb21e951550fe836b0ef5febc037af9a7f51ec) --- source3/smbd/sec_ctx.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 19dac0d27f..4d4e24407b 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -231,6 +231,10 @@ BOOL push_sec_ctx(void) Change UNIX security context. Calls panic if not successful so no return value. ****************************************************************************/ +#ifndef HAVE_DARWIN_INITGROUPS + +/* Normal credential switch path. */ + static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) { /* Start context switch */ @@ -242,6 +246,51 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou /* end context switch */ } +#else /* HAVE_DARWIN_INITGROUPS */ + +/* The Darwin groups implementation is a little unusual. The list of +* groups in the kernel credential is not exhaustive, but more like +* a cache. The full group list is held in userspace and checked +* dynamically. +* +* This is an optional mechanism, and setgroups(2) opts out +* of it. That is, if you call setgroups, then the list of groups you +* set are the only groups that are ever checked. This is not what we +* want. We want to opt in to the dynamic resolution mechanism, so we +* need to specify the uid of the user whose group list (cache) we are +* setting. +* +* The Darwin rules are: +* 1. Thou shalt setegid, initgroups and seteuid IN THAT ORDER +* 2. Thou shalt not pass more that NGROUPS_MAX to initgroups +* 3. Thou shalt leave the first entry in the groups list well alone +*/ + +#include + +static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) +{ + int max = groups_max(); + + /* Start context switch */ + gain_root(); + + become_gid(gid); + + + if (syscall(SYS_initgroups, (ngroups > max) ? max : ngroups, + groups, uid) == 1) { + DEBUG(0, ("WARNING: failed to set group list " + "(%d groups) for UID %ld: %s\n", + ngroups, uid, strerror(errno))); + } + + become_uid(uid); + /* end context switch */ +} + +#endif /* HAVE_DARWIN_INITGROUPS */ + /**************************************************************************** Set the current security context to a given user. ****************************************************************************/ -- cgit From de565785f5e1f097bd75f57331425c4185185f80 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 10 Jun 2007 17:02:09 +0000 Subject: r23410: Merge the core of the cluster code. I'm 100% certain I've forgotten to merge something, but the main code should be in. It's mainly in dbwrap_ctdb.c, ctdbd_conn.c and messages_ctdbd.c. There should be no changes to the non-cluster case, it does survive make test on my laptop. It survives some very basic tests with ctdbd enables, I did not do the full test suite for clusters yet. Phew... Volker (This used to be commit 15553d6327a3aecdd2b0b94a3656d04bf4106323) --- source3/smbd/oplock.c | 6 ++++++ source3/smbd/server.c | 7 +++++++ 2 files changed, 13 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 9f3679390b..ddb05d8b92 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -833,6 +833,9 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e) SIVAL(msg,44,e->share_file_id); SIVAL(msg,48,e->uid); SSVAL(msg,52,e->flags); +#ifdef CLUSTER_SUPPORT + SIVAL(msg,54,e->pid.vnn); +#endif } /**************************************************************************** @@ -853,6 +856,9 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) e->share_file_id = (unsigned long)IVAL(msg,44); e->uid = (uint32)IVAL(msg,48); e->flags = (uint16)SVAL(msg,52); +#ifdef CLUSTER_SUPPORT + e->pid.vnn = IVAL(msg,54); +#endif } /**************************************************************************** diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e95f3cf4a2..98b9fb8626 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1112,6 +1112,13 @@ extern void build_options(BOOL screen); /* Setup aio signal handler. */ initialize_async_io_handler(); + /* + * For clustering, we need to re-init our ctdbd connection after the + * fork + */ + if (!NT_STATUS_IS_OK(messaging_reinit(smbd_messaging_context()))) + exit(1); + /* register our message handlers */ messaging_register(smbd_messaging_context(), NULL, MSG_SMB_FORCE_TDIS, msg_force_tdis); -- cgit From cacbe41945a8f40193981f4237e28e40b6932f1e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Jun 2007 18:14:16 +0000 Subject: r23445: Fix suggested by Volker. Don't call rename_open_files if the name wasn't changed. Jeremy. (This used to be commit 7a9629365eb4eb2829982fe2b2bfffd840648e6f) --- source3/smbd/reply.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3a80d9eaa6..6490856f04 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4638,7 +4638,6 @@ NTSTATUS rename_internals(connection_struct *conn, id = file_id_sbuf(&sbuf1); if (strcsequal(directory, newname)) { - rename_open_files(conn, NULL, id, newname); DEBUG(3, ("rename_internals: identical names in " "rename %s - returning success\n", directory)); @@ -4770,7 +4769,6 @@ NTSTATUS rename_internals(connection_struct *conn, id = file_id_sbuf(&sbuf1); if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, id, newname); DEBUG(3,("rename_internals: identical names " "in wildcard rename %s - success\n", fname)); -- cgit From 28bc066aa843d97741b6507f4936516ff39b3d48 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Jun 2007 19:59:38 +0000 Subject: r23450: max_params_return is complete fiction when getting a changenotify request. Ignore it. Should fix bug #4689 but more tests and valgrinding will follow. Jeremy. (This used to be commit c23e08cc09b8de860ab9c7ac9d0e7c2502dfccd9) --- source3/smbd/notify.c | 18 ++++-------------- source3/smbd/nttrans.c | 6 ++---- 2 files changed, 6 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b2ac26764a..5491f8eaf8 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -27,7 +27,6 @@ struct notify_change_request { struct files_struct *fsp; /* backpointer for cancel by mid */ char request_buf[smb_size]; uint32 filter; - uint32 max_param_count; uint32 current_bufsize; struct notify_mid_map *mid_map; void *backend_data; @@ -127,12 +126,12 @@ static void change_notify_reply_packet(const char *request_buf, "failed."); } -void change_notify_reply(const char *request_buf, uint32 max_param_count, +void change_notify_reply(const char *request_buf, struct notify_change_buf *notify_buf) { char *outbuf = NULL; prs_struct ps; - size_t buflen = smb_size+38+max_param_count; + size_t buflen; if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); @@ -146,14 +145,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, goto done; } - if (prs_offset(&ps) > max_param_count) { - /* - * We exceed what the client is willing to accept. Send - * nothing. - */ - change_notify_reply_packet(request_buf, NT_STATUS_OK); - goto done; - } + buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); @@ -215,7 +207,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, +NTSTATUS change_notify_add_request(const char *inbuf, uint32 filter, BOOL recursive, struct files_struct *fsp) { @@ -232,7 +224,6 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, map->req = request; memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); - request->max_param_count = max_param_count; request->current_bufsize = 0; request->filter = filter; request->fsp = fsp; @@ -409,7 +400,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) */ change_notify_reply(fsp->notify->requests->request_buf, - fsp->notify->requests->max_param_count, fsp->notify); change_notify_remove_request(fsp->notify->requests); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 71e6dd47b4..e713922ecb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1985,8 +1985,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * here. */ - change_notify_reply(inbuf, max_param_count, - fsp->notify); + change_notify_reply(inbuf, fsp->notify); /* * change_notify_reply() above has independently sent its @@ -1999,8 +1998,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * No changes pending, queue the request */ - status = change_notify_add_request(inbuf, max_param_count, filter, - recursive, fsp); + status = change_notify_add_request(inbuf, filter, recursive, fsp); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } -- cgit From 062a411c12e032e14252cbfb261fd5b069de2bb8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 13 Jun 2007 09:55:13 +0000 Subject: r23457: After Jeremy's ack: The attached patch removes a little race condition for people with real kernel oplock support, and reduces some code paths. It changes reply_unlink to open_file_ntcreate, set_delete_on_close and close_file. The race condition happens if we break the oplock in can_delete via open_file_ntcreate, we close the file, someone else gets a batch oplock and we try to unlink. It reduces code paths by calling SMB_VFS_UNLINK in 2 fewer places. (This used to be commit 0342ce7057045a362134281bcc7030111276dea0) --- source3/smbd/reply.c | 53 ++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6490856f04..be35099470 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1830,11 +1830,11 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, } /******************************************************************* - Check if a user is allowed to delete a file. -********************************************************************/ + * unlink a file with all relevant access checks + *******************************************************************/ -static NTSTATUS can_delete(connection_struct *conn, char *fname, - uint32 dirtype, BOOL can_defer) +static NTSTATUS do_unlink(connection_struct *conn, char *fname, + uint32 dirtype, BOOL can_defer) { SMB_STRUCT_STAT sbuf; uint32 fattr; @@ -1935,10 +1935,19 @@ static NTSTATUS can_delete(connection_struct *conn, char *fname, can_defer ? 0 : INTERNAL_OPEN_ONLY, NULL, &fsp); - if (NT_STATUS_IS_OK(status)) { - close_file(fsp,NORMAL_CLOSE); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file_ntcreate failed: %s\n", + nt_errstr(status))); + return status; } - return status; + + /* The set is across all open files on this dev/inode pair. */ + if (!set_delete_on_close(fsp, True, ¤t_user.ut)) { + close_file(fsp, NORMAL_CLOSE); + return NT_STATUS_ACCESS_DENIED; + } + + return close_file(fsp,NORMAL_CLOSE); } /**************************************************************************** @@ -1997,17 +2006,15 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, return status; } - status = can_delete(conn,directory,dirtype,can_defer); + status = do_unlink(conn,directory,dirtype,can_defer); if (!NT_STATUS_IS_OK(status)) { return status; } - if (SMB_VFS_UNLINK(conn,directory) == 0) { - count++; - notify_fname(conn, NOTIFY_ACTION_REMOVED, - FILE_NOTIFY_CHANGE_FILE_NAME, - directory); - } + count++; + notify_fname(conn, NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME, + directory); } else { struct smb_Dir *dir_hnd = NULL; long offset = 0; @@ -2066,19 +2073,17 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, return status; } - status = can_delete(conn, fname, dirtype, can_defer); + status = do_unlink(conn, fname, dirtype, can_defer); if (!NT_STATUS_IS_OK(status)) { continue; } - if (SMB_VFS_UNLINK(conn,fname) == 0) { - count++; - DEBUG(3,("unlink_internals: succesful unlink " - "[%s]\n",fname)); - notify_fname(conn, NOTIFY_ACTION_REMOVED, - FILE_NOTIFY_CHANGE_FILE_NAME, - fname); - } - + + count++; + DEBUG(3,("unlink_internals: succesful unlink [%s]\n", + fname)); + notify_fname(conn, NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME, + fname); } CloseDir(dir_hnd); } -- cgit From 719df44c03c54429504c9f58922f348a5cb5aafe Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 13 Jun 2007 11:32:46 +0000 Subject: r23466: Fix RAW-NOTIFY: by using delete on close the notify is triggered deep inside close_file() already. (This used to be commit 0b29e3ad0f2b1759eb195fb37f1f8667d87f5670) --- source3/smbd/reply.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index be35099470..f2ff0b85e0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2012,9 +2012,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, } count++; - notify_fname(conn, NOTIFY_ACTION_REMOVED, - FILE_NOTIFY_CHANGE_FILE_NAME, - directory); } else { struct smb_Dir *dir_hnd = NULL; long offset = 0; @@ -2081,9 +2078,6 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n", fname)); - notify_fname(conn, NOTIFY_ACTION_REMOVED, - FILE_NOTIFY_CHANGE_FILE_NAME, - fname); } CloseDir(dir_hnd); } -- cgit From 0e0fed6f25520d31966a5b29429533397ee5e171 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 13 Jun 2007 12:52:36 +0000 Subject: r23467: Next little simplification: In rename_internals it's a bit pointless to first ask for existence of a file when we do the open_file_ntcreate in can_rename later on anyway. That also gets us the right error message in case the file is not there automatically. (This used to be commit f3d582cb908f95c1b557bda5d41b5a8aff75b124) --- source3/smbd/reply.c | 51 +++++++++++++-------------------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f2ff0b85e0..14dbdcafbd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4588,38 +4588,9 @@ NTSTATUS rename_internals(connection_struct *conn, } /* - * The source object must exist. + * The source object must exist, and it may not have a + * conflicting share mode. */ - - if (!vfs_object_exist(conn, directory, &sbuf1)) { - DEBUG(3, ("rename_internals: source doesn't exist " - "doing rename %s -> %s\n", - directory,newname)); - - if (errno == ENOTDIR || errno == EISDIR - || errno == ENOENT) { - /* - * Must return different errors depending on - * whether the parent directory existed or - * not. - */ - - p = strrchr_m(directory, '/'); - if (!p) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - *p = '\0'; - if (vfs_object_exist(conn, directory, NULL)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - status = map_nt_error_from_unix(errno); - DEBUG(3, ("rename_internals: Error %s rename %s -> " - "%s\n", nt_errstr(status), directory, - newname)); - - return status; - } - status = can_rename(conn,directory,attrs,&sbuf1,False); if (!NT_STATUS_IS_OK(status)) { @@ -4740,15 +4711,19 @@ NTSTATUS rename_internals(connection_struct *conn, return status; } - if (!vfs_object_exist(conn, fname, &sbuf1)) { - status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(6, ("rename %s failed. Error %s\n", - fname, nt_errstr(status))); - continue; - } + /* + * can_rename does an open_file_ntcreate which needs a valid + * stat in case the file exists + */ + + ZERO_STRUCT(sbuf1); + SMB_VFS_STAT(conn, fname, &sbuf1); + status = can_rename(conn,fname,attrs,&sbuf1,False); + if (!NT_STATUS_IS_OK(status)) { - DEBUG(6, ("rename %s refused\n", fname)); + DEBUG(6, ("rename %s refused: %s\n", fname, + nt_errstr(status))); continue; } pstrcpy(destname,newname); -- cgit From 8b2637631e79112408cfce628d3b26aa701f78ef Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 13 Jun 2007 19:01:41 +0000 Subject: r23469: Fix a comment (This used to be commit 47cc9359aa1b4d5fcd9469be0b1378030ac388fc) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 14dbdcafbd..272c3966ba 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1842,7 +1842,7 @@ static NTSTATUS do_unlink(connection_struct *conn, char *fname, uint32 dirtype_orig = dirtype; NTSTATUS status; - DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype )); + DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype )); if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; -- cgit From 4caefdf348857577343075ae647e29a0ac904ae0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 13 Jun 2007 20:49:20 +0000 Subject: r23474: Here's a small patch that disables the libkrb5.so replay cache when verifying a ticket from winbindd_pam.c. I've found during multiple, fast, automated SSH logins (such as from a cron script) that the replay cache in MIT's krb5 lib will occasionally fail the krb5_rd_req() as a replay attack. There seems to be a small window during which the MIT krb5 libs could reproduce identical time stamps for ctime and cusec in the authenticator since Unix systems only give back milli-seconds rather than the micro-seconds needed by the authenticator. Checked against MIT 1.5.1. Have not researched how Heimdal does it. My thinking is that if someone can spoof the KDC and TDS services we are pretty hopeless anyways. (This used to be commit cbd33da9f78373e29729325bbab1ae9040712b11) --- source3/smbd/sesssetup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 42a71f8ad7..22c598a654 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -270,7 +270,9 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } - ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key); + ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, + &client, &pac_data, &ap_rep, + &session_key, True); data_blob_free(&ticket); -- cgit From c03c86232c0d32fd997a5cf52e632e7b159ab688 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Jun 2007 09:45:39 +0000 Subject: r23482: Slightly simplify the rename code: Remove two local variables that are not really needed. (This used to be commit e068e38ef3b364f2c6477f9d8d6ef3b81a6207ca) --- source3/smbd/reply.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 272c3966ba..a183bb3952 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4168,13 +4168,15 @@ static BOOL resolve_wildcards(const char *name1, char *name2) asynchronously. ****************************************************************************/ -static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, - struct file_id id, const char *newname) +static void rename_open_files(connection_struct *conn, + struct share_mode_lock *lck, + const char *newname) { files_struct *fsp; BOOL did_rename = False; - for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(lck->id); fsp; + fsp = file_find_di_next(fsp)) { /* fsp_name is a relative path under the fsp. To change this for other sharepaths we need to manipulate relative paths. */ /* TODO - create the absolute path and manipulate the newname @@ -4191,7 +4193,7 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l if (!did_rename) { DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n", - file_id_static_string(&id), newname )); + file_id_static_string(&lck->id), newname )); } /* Send messages to all smbd's (not ourself) that the name has changed. */ @@ -4237,7 +4239,6 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin SMB_STRUCT_STAT sbuf; pstring newname_last_component; NTSTATUS status = NT_STATUS_OK; - BOOL dest_exists; struct share_mode_lock *lck = NULL; ZERO_STRUCT(sbuf); @@ -4306,9 +4307,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OK; } - dest_exists = vfs_object_exist(conn,newname,NULL); - - if(!replace_if_exists && dest_exists) { + if(!replace_if_exists && vfs_object_exist(conn, newname, NULL)) { DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n", fsp->fsp_name,newname)); return NT_STATUS_OBJECT_NAME_COLLISION; @@ -4347,7 +4346,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); - rename_open_files(conn, lck, fsp->file_id, newname); + rename_open_files(conn, lck, newname); /* * A rename acts as a new file create w.r.t. allowing an initial delete @@ -4455,7 +4454,6 @@ NTSTATUS rename_internals(connection_struct *conn, const char *dname; long offset = 0; pstring destname; - struct file_id id; *directory = *mask = 0; @@ -4605,8 +4603,6 @@ NTSTATUS rename_internals(connection_struct *conn, * don't do the rename, just return success. */ - id = file_id_sbuf(&sbuf1); - if (strcsequal(directory, newname)) { DEBUG(3, ("rename_internals: identical names in " "rename %s - returning success\n", @@ -4624,12 +4620,13 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, id, NULL, NULL); + lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), + NULL, NULL); if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename " "on %s -> %s\n", directory, newname)); - rename_open_files(conn, lck, id, newname); + rename_open_files(conn, lck, newname); TALLOC_FREE(lck); notify_rename(conn, S_ISDIR(sbuf1.st_mode), directory, newname); @@ -4740,8 +4737,6 @@ NTSTATUS rename_internals(connection_struct *conn, return status; } - id = file_id_sbuf(&sbuf1); - if (strcsequal(fname,destname)) { DEBUG(3,("rename_internals: identical names " "in wildcard rename %s - success\n", @@ -4761,10 +4756,11 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, id, NULL, NULL); + lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), NULL, + NULL); if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, id, newname); + rename_open_files(conn, lck, newname); count++; status = NT_STATUS_OK; } -- cgit From 4944a5227cedb52db3f08bfaa81cc4489efa6e28 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Jun 2007 09:51:13 +0000 Subject: r23483: Revert 23482, I must have run 'make test' in the wrong subdir. (This used to be commit 1ce0c582bccc90e54a69b1e70973ed7ccb47cbbb) --- source3/smbd/reply.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a183bb3952..272c3966ba 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4168,15 +4168,13 @@ static BOOL resolve_wildcards(const char *name1, char *name2) asynchronously. ****************************************************************************/ -static void rename_open_files(connection_struct *conn, - struct share_mode_lock *lck, - const char *newname) +static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, + struct file_id id, const char *newname) { files_struct *fsp; BOOL did_rename = False; - for(fsp = file_find_di_first(lck->id); fsp; - fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { /* fsp_name is a relative path under the fsp. To change this for other sharepaths we need to manipulate relative paths. */ /* TODO - create the absolute path and manipulate the newname @@ -4193,7 +4191,7 @@ static void rename_open_files(connection_struct *conn, if (!did_rename) { DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n", - file_id_static_string(&lck->id), newname )); + file_id_static_string(&id), newname )); } /* Send messages to all smbd's (not ourself) that the name has changed. */ @@ -4239,6 +4237,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin SMB_STRUCT_STAT sbuf; pstring newname_last_component; NTSTATUS status = NT_STATUS_OK; + BOOL dest_exists; struct share_mode_lock *lck = NULL; ZERO_STRUCT(sbuf); @@ -4307,7 +4306,9 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OK; } - if(!replace_if_exists && vfs_object_exist(conn, newname, NULL)) { + dest_exists = vfs_object_exist(conn,newname,NULL); + + if(!replace_if_exists && dest_exists) { DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n", fsp->fsp_name,newname)); return NT_STATUS_OBJECT_NAME_COLLISION; @@ -4346,7 +4347,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); - rename_open_files(conn, lck, newname); + rename_open_files(conn, lck, fsp->file_id, newname); /* * A rename acts as a new file create w.r.t. allowing an initial delete @@ -4454,6 +4455,7 @@ NTSTATUS rename_internals(connection_struct *conn, const char *dname; long offset = 0; pstring destname; + struct file_id id; *directory = *mask = 0; @@ -4603,6 +4605,8 @@ NTSTATUS rename_internals(connection_struct *conn, * don't do the rename, just return success. */ + id = file_id_sbuf(&sbuf1); + if (strcsequal(directory, newname)) { DEBUG(3, ("rename_internals: identical names in " "rename %s - returning success\n", @@ -4620,13 +4624,12 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), - NULL, NULL); + lck = get_share_mode_lock(NULL, id, NULL, NULL); if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename " "on %s -> %s\n", directory, newname)); - rename_open_files(conn, lck, newname); + rename_open_files(conn, lck, id, newname); TALLOC_FREE(lck); notify_rename(conn, S_ISDIR(sbuf1.st_mode), directory, newname); @@ -4737,6 +4740,8 @@ NTSTATUS rename_internals(connection_struct *conn, return status; } + id = file_id_sbuf(&sbuf1); + if (strcsequal(fname,destname)) { DEBUG(3,("rename_internals: identical names " "in wildcard rename %s - success\n", @@ -4756,11 +4761,10 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), NULL, - NULL); + lck = get_share_mode_lock(NULL, id, NULL, NULL); if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, newname); + rename_open_files(conn, lck, id, newname); count++; status = NT_STATUS_OK; } -- cgit From 184eb775ffdd6f8afa8822a889b754e5e7050e45 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Jun 2007 12:03:46 +0000 Subject: r23486: Ok, this time with a hopefully successful make test in the right place: Remove two local variables (This used to be commit 575e594e936c3cb197945063309f0b424dcdefc8) --- source3/smbd/reply.c | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 272c3966ba..45c4b1d1df 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4168,13 +4168,15 @@ static BOOL resolve_wildcards(const char *name1, char *name2) asynchronously. ****************************************************************************/ -static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, - struct file_id id, const char *newname) +static void rename_open_files(connection_struct *conn, + struct share_mode_lock *lck, + const char *newname) { files_struct *fsp; BOOL did_rename = False; - for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(lck->id); fsp; + fsp = file_find_di_next(fsp)) { /* fsp_name is a relative path under the fsp. To change this for other sharepaths we need to manipulate relative paths. */ /* TODO - create the absolute path and manipulate the newname @@ -4191,7 +4193,7 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l if (!did_rename) { DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n", - file_id_static_string(&id), newname )); + file_id_static_string(&lck->id), newname )); } /* Send messages to all smbd's (not ourself) that the name has changed. */ @@ -4237,7 +4239,6 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin SMB_STRUCT_STAT sbuf; pstring newname_last_component; NTSTATUS status = NT_STATUS_OK; - BOOL dest_exists; struct share_mode_lock *lck = NULL; ZERO_STRUCT(sbuf); @@ -4306,9 +4307,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OK; } - dest_exists = vfs_object_exist(conn,newname,NULL); - - if(!replace_if_exists && dest_exists) { + if(!replace_if_exists && vfs_object_exist(conn, newname, NULL)) { DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n", fsp->fsp_name,newname)); return NT_STATUS_OBJECT_NAME_COLLISION; @@ -4341,13 +4340,20 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + /* + * We have the file open ourselves, so not being able to get the + * corresponding share mode lock is a fatal error. + */ + + SMB_ASSERT(lck != NULL); + if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { uint32 create_options = fsp->fh->private_options; DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); - rename_open_files(conn, lck, fsp->file_id, newname); + rename_open_files(conn, lck, newname); /* * A rename acts as a new file create w.r.t. allowing an initial delete @@ -4455,7 +4461,6 @@ NTSTATUS rename_internals(connection_struct *conn, const char *dname; long offset = 0; pstring destname; - struct file_id id; *directory = *mask = 0; @@ -4605,8 +4610,6 @@ NTSTATUS rename_internals(connection_struct *conn, * don't do the rename, just return success. */ - id = file_id_sbuf(&sbuf1); - if (strcsequal(directory, newname)) { DEBUG(3, ("rename_internals: identical names in " "rename %s - returning success\n", @@ -4624,12 +4627,19 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, id, NULL, NULL); + lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), + NULL, NULL); if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename " "on %s -> %s\n", directory, newname)); - rename_open_files(conn, lck, id, newname); + if (lck != NULL) { + /* + * Only in this case there are open files at + * all. + */ + rename_open_files(conn, lck, newname); + } TALLOC_FREE(lck); notify_rename(conn, S_ISDIR(sbuf1.st_mode), directory, newname); @@ -4740,8 +4750,6 @@ NTSTATUS rename_internals(connection_struct *conn, return status; } - id = file_id_sbuf(&sbuf1); - if (strcsequal(fname,destname)) { DEBUG(3,("rename_internals: identical names " "in wildcard rename %s - success\n", @@ -4761,10 +4769,17 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, id, NULL, NULL); + lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), NULL, + NULL); if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, id, newname); + if (lck != NULL) { + /* + * Only in this case there are open files at + * all. + */ + rename_open_files(conn, lck, newname); + } count++; status = NT_STATUS_OK; } -- cgit From 9c4d185ef0740ea31da8718b9cb16dac7cddcc15 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Jun 2007 14:45:37 +0000 Subject: r23500: Two changes to survive the now activated test for rename_internals_fsp: With the target being open we have to return NT_STATUS_ACCESS_DENIED and root_fid != 0 leads to NT_STATUS_INVALID_PARAMETER (This used to be commit b599e5b1e10bdf825b2ce53de4a6ec35726d00f6) --- source3/smbd/reply.c | 15 +++++++++++++-- source3/smbd/trans2.c | 6 +++--- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 45c4b1d1df..c20daae21b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4236,10 +4236,11 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest) NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists) { - SMB_STRUCT_STAT sbuf; + SMB_STRUCT_STAT sbuf, sbuf1; pstring newname_last_component; NTSTATUS status = NT_STATUS_OK; struct share_mode_lock *lck = NULL; + BOOL dst_exists; ZERO_STRUCT(sbuf); @@ -4307,12 +4308,22 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OK; } - if(!replace_if_exists && vfs_object_exist(conn, newname, NULL)) { + /* + * Have vfs_object_exist also fill sbuf1 + */ + dst_exists = vfs_object_exist(conn, newname, &sbuf1); + + if(!replace_if_exists && dst_exists) { DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n", fsp->fsp_name,newname)); return NT_STATUS_OBJECT_NAME_COLLISION; } + if (file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) { + DEBUG(3, ("rename_internals_fsp: Target file open\n")); + return NT_STATUS_ACCESS_DENIED; + } + /* Ensure we have a valid stat struct for the source. */ if (fsp->fh->fd != -1) { if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 429fdc154d..af6bc413d9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4611,7 +4611,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, pstring fname) { BOOL overwrite; - /* uint32 root_fid; */ /* Not used */ + uint32 root_fid; uint32 len; pstring newname; pstring base_name; @@ -4624,10 +4624,10 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, } overwrite = (CVAL(pdata,0) ? True : False); - /* root_fid = IVAL(pdata,4); */ + root_fid = IVAL(pdata,4); len = IVAL(pdata,8); - if (len > (total_data - 12) || (len == 0)) { + if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) { return NT_STATUS_INVALID_PARAMETER; } -- cgit From 59c872103dc82a1a9dcb743b39e4ca0f0205dad2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 14 Jun 2007 15:50:47 +0000 Subject: r23501: Move notify_rename before rename_internals_fsp and call it from there. (This used to be commit 8d3828871c561cd05e6461e157db4c0ccddd5f22) --- source3/smbd/reply.c | 86 +++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c20daae21b..205374cff7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4230,6 +4230,48 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest) return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/'); } +/* + * Do the notify calls from a rename + */ + +static void notify_rename(connection_struct *conn, BOOL is_dir, + const char *oldpath, const char *newpath) +{ + char *olddir, *newdir; + const char *oldname, *newname; + uint32 mask; + + mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME + : FILE_NOTIFY_CHANGE_FILE_NAME; + + if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname) + || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) { + TALLOC_FREE(olddir); + return; + } + + if (strcmp(olddir, newdir) == 0) { + notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath); + notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath); + } + else { + notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath); + notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath); + } + TALLOC_FREE(olddir); + TALLOC_FREE(newdir); + + /* this is a strange one. w2k3 gives an additional event for + CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming + files, but not directories */ + if (!is_dir) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES + |FILE_NOTIFY_CHANGE_CREATION, + newpath); + } +} + /**************************************************************************** Rename an open file - given an fsp. ****************************************************************************/ @@ -4366,6 +4408,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin rename_open_files(conn, lck, newname); + notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname); + /* * A rename acts as a new file create w.r.t. allowing an initial delete * on close, probably because in Windows there is a new handle to the @@ -4404,48 +4448,6 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return status; } -/* - * Do the notify calls from a rename - */ - -static void notify_rename(connection_struct *conn, BOOL is_dir, - const char *oldpath, const char *newpath) -{ - char *olddir, *newdir; - const char *oldname, *newname; - uint32 mask; - - mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME - : FILE_NOTIFY_CHANGE_FILE_NAME; - - if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname) - || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) { - TALLOC_FREE(olddir); - return; - } - - if (strcmp(olddir, newdir) == 0) { - notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath); - notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath); - } - else { - notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath); - notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath); - } - TALLOC_FREE(olddir); - TALLOC_FREE(newdir); - - /* this is a strange one. w2k3 gives an additional event for - CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming - files, but not directories */ - if (!is_dir) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES - |FILE_NOTIFY_CHANGE_CREATION, - newpath); - } -} - /**************************************************************************** The guts of the rename command, split out so it may be called by the NT SMB code. -- cgit From 4a3e4db1cde61f41e5700ad696645f2910c2cbb9 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 14 Jun 2007 18:48:51 +0000 Subject: r23502: Restore exit-on-idle. Small refactoring for clarity. Exit if we are idle and we timed out waiting for something to do. (This used to be commit b4ab1a0cd992cf9e966b8edb9796d1eae53db744) --- source3/smbd/server.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 98b9fb8626..532de36bf8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -315,6 +315,16 @@ static BOOL allowable_number_of_smbd_processes(void) return num_children < max_processes; } +/**************************************************************************** + Are we idle enough that we could safely exit? +****************************************************************************/ + +static BOOL smbd_is_idle(void) +{ + /* Currently we define "idle" as having no client connections. */ + return count_all_current_connections() == 0; +} + /**************************************************************************** Open the socket communication. ****************************************************************************/ @@ -414,10 +424,22 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ &r_fds, &w_fds, &idle_timeout, &maxfd); - num = sys_select(maxfd+1,&r_fds,&w_fds,NULL, - timeval_is_zero(&idle_timeout) ? - NULL : &idle_timeout); - + if (timeval_is_zero(&idle_timeout)) { + num = sys_select(maxfd + 1, &r_fds, &w_fds, + NULL, NULL); + } else { + num = sys_select(maxfd + 1, &r_fds, &w_fds, + NULL, &idle_timeout); + + /* If the idle timeout fired and we are idle, exit + * gracefully. We expect to be running under a process + * controller that will restart us if necessry. + */ + if (num == 0 && smbd_is_idle()) { + exit_server_cleanly("idle timeout"); + } + } + if (num == -1 && errno == EINTR) { if (got_sig_term) { exit_server_cleanly(NULL); @@ -438,19 +460,6 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ continue; } -#if 0 - Deactivated for now, this needs to become a timed event - vl - - /* If the idle timeout fired and we don't have any connected - * users, exit gracefully. We should be running under a process - * controller that will restart us if necessry. - */ - if (num == 0 && count_all_current_connections() == 0) { - exit_server_cleanly("idle timeout"); - } -#endif - /* check if we need to reload services */ check_reload(time(NULL)); -- cgit From cc35d1300d487c65f1dc8a275140701ba276adaf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Jun 2007 19:24:04 +0000 Subject: r23508: Fix sync_file() to return NTSTATUS and return this on failure in the write path. Jeremy. (This used to be commit cd3f7dbee809fb40194af0e7509142166e02b252) --- source3/smbd/aio.c | 9 +++++++- source3/smbd/fileio.c | 15 +++++++++---- source3/smbd/reply.c | 58 ++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 69 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index bee6ebc89a..f747cf5c06 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -468,6 +468,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ret = errno; } else { BOOL write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); + NTSTATUS status; SSVAL(outbuf,smb_vwv2,nwritten); SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); @@ -478,7 +479,13 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); - sync_file(fsp->conn,fsp, write_through); + status = sync_file(fsp->conn,fsp, write_through); + if (!NT_STATUS_IS_OK(status)) { + UNIXERROR(ERRHRD,ERRdiskfull); + ret = errno; + DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", + fsp->fsp_name, nt_errstr(status) )); + } } show_msg(outbuf); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 65238c0e9e..1227d12b08 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -834,16 +834,23 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) sync a file ********************************************************************/ -void sync_file(connection_struct *conn, files_struct *fsp, BOOL write_through) +NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, BOOL write_through) { if (fsp->fh->fd == -1) - return; + return NT_STATUS_INVALID_HANDLE; if (lp_strict_sync(SNUM(conn)) && (lp_syncalways(SNUM(conn)) || write_through)) { - flush_write_cache(fsp, SYNC_FLUSH); - SMB_VFS_FSYNC(fsp,fsp->fh->fd); + int ret = flush_write_cache(fsp, SYNC_FLUSH); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + ret = SMB_VFS_FSYNC(fsp,fsp->fh->fd); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } } + return NT_STATUS_OK; } /************************************************************ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 205374cff7..33ccb7f386 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2787,6 +2787,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, BOOL write_through; files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; + NTSTATUS status; START_PROFILE(SMBwritebraw); if (srv_is_signing_active()) { @@ -2891,7 +2892,13 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SSVAL(outbuf,smb_vwv0,total_written); - sync_file(conn, fsp, write_through); + status = sync_file(conn, fsp, write_through); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n", + fsp->fsp_name, nt_errstr(status) )); + END_PROFILE(SMBwritebraw); + return ERROR_NT(status); + } DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); @@ -2956,7 +2963,13 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, nwritten = write_file(fsp,data,startpos,numtowrite); } - sync_file(conn, fsp, False /* write through */); + status = sync_file(conn, fsp, False /* write through */); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBwriteunlock); + DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n", + fsp->fsp_name, nt_errstr(status) )); + return ERROR_NT(status); + } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwriteunlock); @@ -3003,6 +3016,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); int outsize = 0; + NTSTATUS status; START_PROFILE(SMBwrite); /* If it's an IPC, pass off the pipe handler. */ @@ -3013,6 +3027,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d CHECK_FSP(fsp,conn); if (!CHECK_WRITE(fsp)) { + END_PROFILE(SMBwrite); return(ERROR_DOS(ERRDOS,ERRbadaccess)); } @@ -3048,7 +3063,13 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d } else nwritten = write_file(fsp,data,startpos,numtowrite); - sync_file(conn, fsp, False); + status = sync_file(conn, fsp, False); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBwrite); + DEBUG(5,("reply_write: sync_file for %s returned %s\n", + fsp->fsp_name, nt_errstr(status) )); + return ERROR_NT(status); + } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { END_PROFILE(SMBwrite); @@ -3085,6 +3106,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng unsigned int smblen = smb_len(inbuf); char *data; BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); + NTSTATUS status; START_PROFILE(SMBwriteX); /* If it's an IPC, pass off the pipe handler. */ @@ -3175,7 +3197,13 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); - sync_file(conn, fsp, write_through); + status = sync_file(conn, fsp, write_through); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBwriteX); + DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n", + fsp->fsp_name, nt_errstr(status) )); + return ERROR_NT(status); + } END_PROFILE(SMBwriteX); return chain_reply(inbuf,outbuf,length,bufsize); @@ -3272,7 +3300,13 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int if (!fsp) { file_sync_all(conn); } else { - sync_file(conn,fsp, True); + NTSTATUS status = sync_file(conn, fsp, True); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBflush); + DEBUG(5,("reply_flush: sync_file for %s returned %s\n", + fsp->fsp_name, nt_errstr(status) )); + return ERROR_NT(status); + } } DEBUG(3,("flush\n")); @@ -5886,6 +5920,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int smb_doff; char *data; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + NTSTATUS status; START_PROFILE(SMBwriteBmpx); CHECK_FSP(fsp,conn); @@ -5915,7 +5950,13 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, nwritten = write_file(fsp,data,startpos,numtowrite); - sync_file(conn, fsp, write_through); + status = sync_file(conn, fsp, write_through); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBwriteBmpx); + DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n", + fsp->fsp_name, nt_errstr(status) )); + return ERROR_NT(status); + } if(nwritten < (ssize_t)numtowrite) { END_PROFILE(SMBwriteBmpx); @@ -5991,6 +6032,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz write_bmpx_struct *wbms; BOOL send_response = False; files_struct *fsp = file_fsp(inbuf,smb_vwv0); + NTSTATUS status; START_PROFILE(SMBwriteBs); CHECK_FSP(fsp,conn); @@ -6027,9 +6069,9 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz nwritten = write_file(fsp,data,startpos,numtowrite); - sync_file(conn, fsp, write_through); + status = sync_file(conn, fsp, write_through); - if (nwritten < (ssize_t)numtowrite) { + if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) { if(write_through) { /* We are returning an error - we can delete the aux struct */ if (wbms) -- cgit From b1ce226af8b61ad7e3c37860a59c6715012e738b Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 15 Jun 2007 21:58:49 +0000 Subject: r23510: Tidy calls to smb_panic by removing trailing newlines. Print the failed expression in SMB_ASSERT. (This used to be commit 171dc060e2a576d724eed1ca65636bdafffd7713) --- source3/smbd/blocking.c | 4 ++-- source3/smbd/files.c | 2 +- source3/smbd/negprot.c | 2 +- source3/smbd/notify.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/password.c | 2 +- source3/smbd/sec_ctx.c | 4 ++-- source3/smbd/server.c | 6 +++--- source3/smbd/share_access.c | 6 +++--- 9 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 6a892b477d..924b99b113 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -841,13 +841,13 @@ static void process_blocking_lock_cancel_message(struct messaging_context *ctx, blocking_lock_record *blr; if (data->data == NULL) { - smb_panic("process_blocking_lock_cancel_message: null msg\n"); + smb_panic("process_blocking_lock_cancel_message: null msg"); } if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) { DEBUG(0, ("process_blocking_lock_cancel_message: " "Got invalid msg len %d\n", (int)data->length)); - smb_panic("process_blocking_lock_cancel_message: bad msg\n"); + smb_panic("process_blocking_lock_cancel_message: bad msg"); } memcpy(&blr, msg, sizeof(blr)); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 5ee0696ef9..590916011b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -284,7 +284,7 @@ oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, file_id_static_string(&fsp->file_id), (unsigned int)fsp->fh->gen_id, (unsigned int)fsp->oplock_type )); - smb_panic("file_find_dif\n"); + smb_panic("file_find_dif"); } return fsp; } diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 92c392b366..3fdae1e06b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -43,7 +43,7 @@ static void get_challenge(char buff[8]) DEBUG(10, ("get challenge: creating negprot_global_auth_context\n")); if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) { DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status))); - smb_panic("cannot make_negprot_global_auth_context!\n"); + smb_panic("cannot make_negprot_global_auth_context!"); } DEBUG(10, ("get challenge: getting challenge\n")); cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context); diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5491f8eaf8..9074990be7 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -261,7 +261,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re } if (req == NULL) { - smb_panic("notify_req not found in fsp's requests\n"); + smb_panic("notify_req not found in fsp's requests"); } DLIST_REMOVE(fsp->notify->requests, req); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e713922ecb..965da90a64 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -50,7 +50,7 @@ static const char *known_nt_pipes[] = { static char *nttrans_realloc(char **ptr, size_t size) { if (ptr==NULL) { - smb_panic("nttrans_realloc() called with NULL ptr\n"); + smb_panic("nttrans_realloc() called with NULL ptr"); } *ptr = (char *)SMB_REALLOC(*ptr, size); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ce03e6d85f..00f687dc27 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -147,7 +147,7 @@ int register_vuid(auth_serversupplied_info *server_info, /* Paranoia check. */ if(lp_security() == SEC_SHARE) { - smb_panic("Tried to register uid in security=share\n"); + smb_panic("Tried to register uid in security=share"); } /* Limit allowed vuids to 16bits - VUID_OFFSET. */ diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 4d4e24407b..97842419d5 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -192,7 +192,7 @@ BOOL push_sec_ctx(void) if (sec_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) { DEBUG(0, ("Security context stack overflow!\n")); - smb_panic("Security context stack overflow!\n"); + smb_panic("Security context stack overflow!"); } /* Store previous user context */ @@ -374,7 +374,7 @@ BOOL pop_sec_ctx(void) if (sec_ctx_stack_ndx == 0) { DEBUG(0, ("Security context stack underflow!\n")); - smb_panic("Security context stack underflow!\n"); + smb_panic("Security context stack underflow!"); } ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 532de36bf8..edbd879847 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -67,7 +67,7 @@ struct event_context *smbd_event_context(void) static struct event_context *ctx; if (!ctx && !(ctx = event_context_init(NULL))) { - smb_panic("Could not init smbd event context\n"); + smb_panic("Could not init smbd event context"); } return ctx; } @@ -78,7 +78,7 @@ struct messaging_context *smbd_messaging_context(void) if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), smbd_event_context()))) { - smb_panic("Could not init smbd messaging context\n"); + smb_panic("Could not init smbd messaging context"); } return ctx; } @@ -539,7 +539,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ * CLEAR_IF_FIRST flags */ if (tdb_reopen_all(1) == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); - smb_panic("tdb_reopen_all failed."); + smb_panic("tdb_reopen_all failed"); } return True; diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index adb9d16964..b12d543f5a 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -86,7 +86,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, if (name == NULL) { /* This is too security sensitive, better panic than return a * result that might be interpreted in a wrong way. */ - smb_panic("substitutions failed\n"); + smb_panic("substitutions failed"); } /* check to see is we already have a SID */ @@ -136,7 +136,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, } continue; } - smb_panic("got invalid prefix from do_groups_check\n"); + smb_panic("got invalid prefix from do_groups_check"); } return False; } @@ -164,7 +164,7 @@ BOOL token_contains_name_in_list(const char *username, } if ( (mem_ctx = talloc_new(NULL)) == NULL ) { - smb_panic("talloc_new failed\n"); + smb_panic("talloc_new failed"); } while (*list != NULL) { -- cgit From 80c085d8ef1619865710b2ceb2c13fc56fd1929c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 16 Jun 2007 10:02:51 +0000 Subject: r23517: After Jeremy has given is ack on irc: Change rename_internals to open the file/directory and then call rename_internals_fsp. Two reasons: Remove code duplication and remove a race condition. The race condition was due to the fact that in can_rename the share mode check closed the file and then after that did the rename. (This used to be commit aa16d8a649d1a38593edd5ca94ed2c7d4291911b) --- source3/smbd/reply.c | 240 +++++++++++++-------------------------------------- 1 file changed, 61 insertions(+), 179 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 33ccb7f386..72a3f5da8e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1791,17 +1791,16 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Check if a user is allowed to rename a file. ********************************************************************/ -static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open) +static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, + uint16 dirtype, SMB_STRUCT_STAT *pst) { - files_struct *fsp; uint32 fmode; - NTSTATUS status; if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; } - fmode = dos_mode(conn,fname,pst); + fmode = dos_mode(conn, fsp->fsp_name, pst); if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) { return NT_STATUS_NO_SUCH_FILE; } @@ -1810,23 +1809,11 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, return NT_STATUS_OK; } - status = open_file_ntcreate(conn, fname, pst, - DELETE_ACCESS, - /* If we're checking our fsp don't deny for delete. */ - self_open ? - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE : - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - 0, - NULL, &fsp); - - if (!NT_STATUS_IS_OK(status)) { - return status; + if (fsp->access_mask & DELETE_ACCESS) { + return NT_STATUS_OK; } - close_file(fsp,NORMAL_CLOSE); - return NT_STATUS_OK; + + return NT_STATUS_ACCESS_DENIED; } /******************************************************************* @@ -4395,7 +4382,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OBJECT_NAME_COLLISION; } - if (file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) { + if (dst_exists && file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) { DEBUG(3, ("rename_internals_fsp: Target file open\n")); return NT_STATUS_ACCESS_DENIED; } @@ -4411,7 +4398,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin } } - status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True); + status = can_rename(conn, fsp, attrs, &sbuf); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", @@ -4503,7 +4490,6 @@ NTSTATUS rename_internals(connection_struct *conn, int count=0; NTSTATUS status = NT_STATUS_OK; SMB_STRUCT_STAT sbuf1, sbuf2; - struct share_mode_lock *lck = NULL; struct smb_Dir *dir_hnd = NULL; const char *dname; long offset = 0; @@ -4558,6 +4544,8 @@ NTSTATUS rename_internals(connection_struct *conn, } if (!src_has_wild) { + files_struct *fsp; + /* * No wildcards - just process the one file. */ @@ -4584,12 +4572,6 @@ NTSTATUS rename_internals(connection_struct *conn, conn->short_case_preserve, directory, newname, last_component_dest, is_short_name)); - /* Ensure the source name is valid for us to access. */ - status = check_name(conn, directory); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* The dest name still may have wildcards. */ if (dest_has_wild) { if (!resolve_wildcards(directory,newname)) { @@ -4599,109 +4581,34 @@ NTSTATUS rename_internals(connection_struct *conn, } } - /* - * Check for special case with case preserving and not - * case sensitive, if directory and newname are identical, - * and the old last component differs from the original - * last component only by case, then we should allow - * the rename (user is trying to change the case of the - * filename). - */ - if((conn->case_sensitive == False) && - (((conn->case_preserve == True) && - (is_short_name == False)) || - ((conn->short_case_preserve == True) && - (is_short_name == True))) && - strcsequal(directory, newname)) { - pstring modified_last_component; - - /* - * Get the last component of the modified name. - * Note that we guarantee that newname contains a '/' - * character above. - */ - p = strrchr_m(newname,'/'); - pstrcpy(modified_last_component,p+1); - - if(strcsequal(modified_last_component, - last_component_dest) == False) { - /* - * Replace the modified last component with - * the original. - */ - pstrcpy(p+1, last_component_dest); - } - } - - /* Ensure the dest name is valid for us to access. */ - status = check_name(conn, newname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* - * The source object must exist, and it may not have a - * conflicting share mode. - */ - status = can_rename(conn,directory,attrs,&sbuf1,False); + ZERO_STRUCT(sbuf1); + SMB_VFS_STAT(conn, directory, &sbuf1); + + status = S_ISDIR(sbuf1.st_mode) ? + open_directory(conn, directory, &sbuf1, + DELETE_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, 0, 0, NULL, + &fsp) + : open_file_ntcreate(conn, directory, &sbuf1, + DELETE_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, 0, 0, 0, NULL, + &fsp); if (!NT_STATUS_IS_OK(status)) { - DEBUG(3,("rename_internals: Error %s rename %s -> " - "%s\n", nt_errstr(status), directory, - newname)); + DEBUG(3, ("Could not open rename source %s: %s\n", + directory, nt_errstr(status))); return status; } - /* - * If the src and dest names are identical - including case, - * don't do the rename, just return success. - */ - - if (strcsequal(directory, newname)) { - DEBUG(3, ("rename_internals: identical names in " - "rename %s - returning success\n", - directory)); - return NT_STATUS_OK; - } - - if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) { - DEBUG(3,("rename_internals: dest exists doing " - "rename %s -> %s\n", directory, newname)); - return NT_STATUS_OBJECT_NAME_COLLISION; - } - - if (rename_path_prefix_equal(directory, newname)) { - return NT_STATUS_SHARING_VIOLATION; - } - - lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), - NULL, NULL); + status = rename_internals_fsp(conn, fsp, newname, attrs, + replace_if_exists); - if(SMB_VFS_RENAME(conn,directory, newname) == 0) { - DEBUG(3,("rename_internals: succeeded doing rename " - "on %s -> %s\n", directory, newname)); - if (lck != NULL) { - /* - * Only in this case there are open files at - * all. - */ - rename_open_files(conn, lck, newname); - } - TALLOC_FREE(lck); - notify_rename(conn, S_ISDIR(sbuf1.st_mode), - directory, newname); - return NT_STATUS_OK; - } + close_file(fsp, NORMAL_CLOSE); - TALLOC_FREE(lck); - if (errno == ENOTDIR || errno == EISDIR) { - status = NT_STATUS_OBJECT_NAME_COLLISION; - } else { - status = map_nt_error_from_unix(errno); - } - - DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(status), directory,newname)); + DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n", + nt_errstr(status), directory,newname)); return status; } @@ -4730,6 +4637,7 @@ NTSTATUS rename_internals(connection_struct *conn, */ while ((dname = ReadDirName(dir_hnd, &offset))) { + files_struct *fsp; pstring fname; BOOL sysdir_entry = False; @@ -4759,30 +4667,8 @@ NTSTATUS rename_internals(connection_struct *conn, break; } - status = NT_STATUS_ACCESS_DENIED; slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname); - /* Ensure the source name is valid for us to access. */ - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* - * can_rename does an open_file_ntcreate which needs a valid - * stat in case the file exists - */ - - ZERO_STRUCT(sbuf1); - SMB_VFS_STAT(conn, fname, &sbuf1); - - status = can_rename(conn,fname,attrs,&sbuf1,False); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(6, ("rename %s refused: %s\n", fname, - nt_errstr(status))); - continue; - } pstrcpy(destname,newname); if (!resolve_wildcards(fname,destname)) { @@ -4791,46 +4677,42 @@ NTSTATUS rename_internals(connection_struct *conn, continue; } - /* Ensure the dest name is valid for us to access. */ - status = check_name(conn, destname); + ZERO_STRUCT(sbuf1); + SMB_VFS_STAT(conn, fname, &sbuf1); + + status = S_ISDIR(sbuf1.st_mode) ? + open_directory(conn, fname, &sbuf1, + DELETE_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, 0, 0, NULL, + &fsp) + : open_file_ntcreate(conn, fname, &sbuf1, + DELETE_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, 0, 0, 0, NULL, + &fsp); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3,("rename_internals: open_file_ntcreate " + "returned %s rename %s -> %s\n", + nt_errstr(status), directory, newname)); return status; } - if (strcsequal(fname,destname)) { - DEBUG(3,("rename_internals: identical names " - "in wildcard rename %s - success\n", - fname)); - count++; - status = NT_STATUS_OK; - continue; - } + status = rename_internals_fsp(conn, fsp, destname, attrs, + replace_if_exists); - if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) { - DEBUG(6,("file_exist %s\n", destname)); - status = NT_STATUS_OBJECT_NAME_COLLISION; - continue; - } - - if (rename_path_prefix_equal(fname, destname)) { - return NT_STATUS_SHARING_VIOLATION; + close_file(fsp, NORMAL_CLOSE); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("rename_internals_fsp returned %s for " + "rename %s -> %s\n", nt_errstr(status), + directory, newname)); + return status; } - lck = get_share_mode_lock(NULL, file_id_sbuf(&sbuf1), NULL, - NULL); + count++; - if (!SMB_VFS_RENAME(conn,fname,destname)) { - if (lck != NULL) { - /* - * Only in this case there are open files at - * all. - */ - rename_open_files(conn, lck, newname); - } - count++; - status = NT_STATUS_OK; - } - TALLOC_FREE(lck); DEBUG(3,("rename_internals: doing rename on %s -> " "%s\n",fname,destname)); } -- cgit From 32ba5145b8c8385f56a1e8f025c7be1bc848077b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 16 Jun 2007 11:48:11 +0000 Subject: r23518: Remove the silly assumption that string_replace requires a pstring. Jeremy, I am always very confused about the different length arguments in convert_string and friends. Can you take a look at the change in string_replace and verify it's ok? Thanks! While at it, remove the pstring limit for strhasupper and strhaslower. (This used to be commit e6e5703658aeaeb0cca5d7281095e17553001d4b) --- source3/smbd/notify.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9074990be7..1b75916942 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -328,7 +328,7 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter, static void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; - pstring name2; + char *tmp; if (fsp->notify == NULL) { /* @@ -337,9 +337,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) return; } - pstrcpy(name2, name); - string_replace(name2, '/', '\\'); - /* * Someone has triggered a notify previously, queue the change for * later. @@ -370,11 +367,14 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, name2))) { + if (!(tmp = talloc_strdup(changes, name))) { DEBUG(0, ("talloc_strdup failed\n")); return; } + string_replace(tmp, '/', '\\'); + change->name = tmp; + change->action = action; fsp->notify->num_changes += 1; -- cgit From 43e51b39892e1742a22c3fb61c4e8afc6a09edc0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 16 Jun 2007 18:07:44 +0000 Subject: r23522: Save us a kilobyte stack space in a hot code path: I can't see a reason why check_path_syntax should not be able to run in-line. The destination pointer either walks side by side with the source pointer or is decremented. So as far as I can see s>=d is true throughout the whole routine. Jeremy, I'm checking this only into 3_0 for now. Please review and ack or directly merge this to 3_0_26. Thanks, Volker (This used to be commit 34a13c82a3b72d6900614b57c58fbaefeeca8fa7) --- source3/smbd/msdfs.c | 8 +++++--- source3/smbd/reply.c | 53 +++++++++++++++++++++++----------------------------- 2 files changed, 28 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 9f203bfd19..a3de199116 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -144,14 +144,16 @@ static NTSTATUS parse_dfs_path(const char *pathname, *ppath_contains_wcard = False; + pstrcpy(pdp->reqpath, p); + /* Rest is reqpath. */ if (pdp->posix_path) { - status = check_path_syntax_posix(pdp->reqpath, p); + status = check_path_syntax_posix(pdp->reqpath); } else { if (allow_wcards) { - status = check_path_syntax_wcard(pdp->reqpath, p, ppath_contains_wcard); + status = check_path_syntax_wcard(pdp->reqpath, ppath_contains_wcard); } else { - status = check_path_syntax(pdp->reqpath, p); + status = check_path_syntax(pdp->reqpath); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 72a3f5da8e..b826cc7bda 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -47,13 +47,12 @@ extern BOOL global_encrypted_passwords_negotiated; /* Custom version for processing POSIX paths. */ #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\')) -NTSTATUS check_path_syntax_internal(pstring destname, - const pstring srcname, - BOOL posix_path, - BOOL *p_last_component_contains_wcard) +static NTSTATUS check_path_syntax_internal(char *path, + BOOL posix_path, + BOOL *p_last_component_contains_wcard) { - char *d = destname; - const char *s = srcname; + char *d = path; + const char *s = path; NTSTATUS ret = NT_STATUS_OK; BOOL start_of_name_component = True; @@ -69,7 +68,7 @@ NTSTATUS check_path_syntax_internal(pstring destname, while (IS_PATH_SEP(*s,posix_path)) { s++; } - if ((d != destname) && (*s != '\0')) { + if ((d != path) && (*s != '\0')) { /* We only care about non-leading or trailing '/' or '\\' */ *d++ = '/'; } @@ -89,13 +88,13 @@ NTSTATUS check_path_syntax_internal(pstring destname, */ /* If we just added a '/' - delete it */ - if ((d > destname) && (*(d-1) == '/')) { + if ((d > path) && (*(d-1) == '/')) { *(d-1) = '\0'; d--; } /* Are we at the start ? Can't go back further if so. */ - if (d <= destname) { + if (d <= path) { ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; break; } @@ -103,7 +102,7 @@ NTSTATUS check_path_syntax_internal(pstring destname, /* We know this is safe as '/' cannot be part of a mb sequence. */ /* NOTE - if this assumption is invalid we are not in good shape... */ /* Decrement d first as d points to the *next* char to write into. */ - for (d--; d > destname; d--) { + for (d--; d > path; d--) { if (*d == '/') break; } @@ -177,10 +176,10 @@ NTSTATUS check_path_syntax_internal(pstring destname, No wildcards allowed. ****************************************************************************/ -NTSTATUS check_path_syntax(pstring destname, const pstring srcname) +NTSTATUS check_path_syntax(char *path) { BOOL ignore; - return check_path_syntax_internal(destname, srcname, False, &ignore); + return check_path_syntax_internal(path, False, &ignore); } /**************************************************************************** @@ -189,9 +188,9 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname) a wildcard. ****************************************************************************/ -NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard) +NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard) { - return check_path_syntax_internal(destname, srcname, False, p_contains_wcard); + return check_path_syntax_internal(path, False, p_contains_wcard); } /**************************************************************************** @@ -200,10 +199,10 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL * set (a safe assumption). ****************************************************************************/ -NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) +NTSTATUS check_path_syntax_posix(char *name) { BOOL ignore; - return check_path_syntax_internal(destname, srcname, True, &ignore); + return check_path_syntax_internal(path, True, &ignore); } /**************************************************************************** @@ -213,17 +212,15 @@ NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname) size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL *contains_wcard) { - pstring tmppath; - char *tmppath_ptr = tmppath; size_t ret; #ifdef DEVELOPER SMB_ASSERT(dest_len == sizeof(pstring)); #endif if (src_len == 0) { - ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags); + ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); } else { - ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); + ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags); } *contains_wcard = False; @@ -233,15 +230,14 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de * For a DFS path the function parse_dfs_path() * will do the path processing, just make a copy. */ - pstrcpy(dest, tmppath); *err = NT_STATUS_OK; return ret; } if (lp_posix_pathnames()) { - *err = check_path_syntax_posix(dest, tmppath); + *err = check_path_syntax_posix(dest); } else { - *err = check_path_syntax_wcard(dest, tmppath, contains_wcard); + *err = check_path_syntax_wcard(dest, contains_wcard); } return ret; @@ -253,17 +249,15 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err) { - pstring tmppath; - char *tmppath_ptr = tmppath; size_t ret; #ifdef DEVELOPER SMB_ASSERT(dest_len == sizeof(pstring)); #endif if (src_len == 0) { - ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags); + ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); } else { - ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); + ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags); } if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) { @@ -271,15 +265,14 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len * For a DFS path the function parse_dfs_path() * will do the path processing, just make a copy. */ - pstrcpy(dest, tmppath); *err = NT_STATUS_OK; return ret; } if (lp_posix_pathnames()) { - *err = check_path_syntax_posix(dest, tmppath); + *err = check_path_syntax_posix(dest); } else { - *err = check_path_syntax(dest, tmppath); + *err = check_path_syntax(dest); } return ret; -- cgit From c1a2e8f6da82b80a9d47bef633c17a8591c0cb3d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 16 Jun 2007 18:19:42 +0000 Subject: r23523: Gaa -- had renamed "name" to "path" and apparently not compiled after that.... Volker (This used to be commit 1a45ea28ced3775acd6127e05e844873ed23d40b) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b826cc7bda..e2b7084f11 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -199,7 +199,7 @@ NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard) set (a safe assumption). ****************************************************************************/ -NTSTATUS check_path_syntax_posix(char *name) +NTSTATUS check_path_syntax_posix(char *path) { BOOL ignore; return check_path_syntax_internal(path, True, &ignore); -- cgit From 5e8a4c12f9617d7e7b2c392eddc1ced613a561fe Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 17 Jun 2007 05:19:30 +0000 Subject: r23528: Two changes to make the valgrind massif (heap profiler) output readable: Remove the allocated inbuf/output. In async I/O we copy the buffers explicitly now, so NewInBuffer is called exactly once. This does not reduce memory footprint, but removes one of the larger chunks that clobber the rest of the massif output In getgroups_unix_user on Linux 2.6 we allocated 64k groups x 4 bytes per group x 2 (once in the routine itself and once in libc) = 512k just to throw it away directly again. This reduces it do a more typical limit of 32 groups per user. We certainly cope with overflow fine if 32 is not enough. Not 100% sure about this one, a DEVELOPER only thing? (This used to be commit 009af0909944e0f303c5d496b56fb65ca40a41d5) --- source3/smbd/process.c | 64 ++++++++------------------------------------------ 1 file changed, 10 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3b922af51f..0e1ad06ed5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -25,9 +25,10 @@ uint16 global_smbpid; extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; -static char *InBuffer = NULL; -static char *OutBuffer = NULL; -static char *current_inbuf = NULL; +#define TOTAL_BUFFER_SIZE (BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN) + +static char InBuffer[TOTAL_BUFFER_SIZE]; +static char OutBuffer[TOTAL_BUFFER_SIZE]; /* * Size of data we can send to client. Set @@ -208,11 +209,11 @@ BOOL push_deferred_smb_message(uint16 mid, DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u " "timeout time [%u.%06u]\n", - (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, + (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid, (unsigned int)end_time.tv_sec, (unsigned int)end_time.tv_usec)); - return push_queued_message(current_inbuf, smb_len(current_inbuf)+4, + return push_queued_message(InBuffer, smb_len(InBuffer)+4, request_time, end_time, private_data, priv_len); } @@ -1007,7 +1008,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(ERROR_DOS(ERRSRV,ERRaccess)); } - current_inbuf = inbuf; /* In case we need to defer this message in open... */ outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); } @@ -1441,47 +1441,6 @@ char *get_OutBuffer(void) return OutBuffer; } -const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); - -/**************************************************************************** - Allocate a new InBuffer. Returns the new and old ones. -****************************************************************************/ - -static char *NewInBuffer(char **old_inbuf) -{ - char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size); - if (!new_inbuf) { - return NULL; - } - if (old_inbuf) { - *old_inbuf = InBuffer; - } - InBuffer = new_inbuf; -#if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); -#endif - return InBuffer; -} - -/**************************************************************************** - Allocate a new OutBuffer. Returns the new and old ones. -****************************************************************************/ - -static char *NewOutBuffer(char **old_outbuf) -{ - char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size); - if (!new_outbuf) { - return NULL; - } - if (old_outbuf) { - *old_outbuf = OutBuffer; - } - OutBuffer = new_outbuf; -#if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); -#endif - return OutBuffer; -} /**************************************************************************** Process commands from the client @@ -1492,11 +1451,6 @@ void smbd_process(void) time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; - /* Allocate the primary Inbut/Output buffers. */ - - if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) - return; - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); while (True) { @@ -1520,7 +1474,8 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); #if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, + InBuffer, TOTAL_BUFFER_SIZE); #endif while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { @@ -1541,7 +1496,8 @@ void smbd_process(void) */ num_echos = smb_echo_count; - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, + OutBuffer, TOTAL_BUFFER_SIZE); process_smb(InBuffer, OutBuffer); -- cgit From 864cad1353867a4092e4ba4b46721f91ada64ca9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 18 Jun 2007 09:25:31 +0000 Subject: r23537: Revert the inbuf/outbuf part of r23528: This caused the Solaris CC make test to break. The Solaris CC put the static char InBuffer[TOTAL_BUFFER_SIZE] on an odd address, the malloc'ed one is always aligned. The problem showed up in pull_ucs2, ucs2_align uses the address of InBuffer as an indication whether to bump up the src of the string by one. Unfortunately in the trans calls the data portion is malloced and thus has different alignment guarantees than a static variable. This one is bigger.... Volker (This used to be commit 6affd7818f6981be2a9f44fcf302e7fddb468347) --- source3/smbd/process.c | 64 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0e1ad06ed5..3b922af51f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -25,10 +25,9 @@ uint16 global_smbpid; extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; -#define TOTAL_BUFFER_SIZE (BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN) - -static char InBuffer[TOTAL_BUFFER_SIZE]; -static char OutBuffer[TOTAL_BUFFER_SIZE]; +static char *InBuffer = NULL; +static char *OutBuffer = NULL; +static char *current_inbuf = NULL; /* * Size of data we can send to client. Set @@ -209,11 +208,11 @@ BOOL push_deferred_smb_message(uint16 mid, DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u " "timeout time [%u.%06u]\n", - (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid, + (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, (unsigned int)end_time.tv_sec, (unsigned int)end_time.tv_usec)); - return push_queued_message(InBuffer, smb_len(InBuffer)+4, + return push_queued_message(current_inbuf, smb_len(current_inbuf)+4, request_time, end_time, private_data, priv_len); } @@ -1008,6 +1007,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(ERROR_DOS(ERRSRV,ERRaccess)); } + current_inbuf = inbuf; /* In case we need to defer this message in open... */ outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); } @@ -1441,6 +1441,47 @@ char *get_OutBuffer(void) return OutBuffer; } +const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); + +/**************************************************************************** + Allocate a new InBuffer. Returns the new and old ones. +****************************************************************************/ + +static char *NewInBuffer(char **old_inbuf) +{ + char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size); + if (!new_inbuf) { + return NULL; + } + if (old_inbuf) { + *old_inbuf = InBuffer; + } + InBuffer = new_inbuf; +#if defined(DEVELOPER) + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); +#endif + return InBuffer; +} + +/**************************************************************************** + Allocate a new OutBuffer. Returns the new and old ones. +****************************************************************************/ + +static char *NewOutBuffer(char **old_outbuf) +{ + char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size); + if (!new_outbuf) { + return NULL; + } + if (old_outbuf) { + *old_outbuf = OutBuffer; + } + OutBuffer = new_outbuf; +#if defined(DEVELOPER) + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); +#endif + return OutBuffer; +} /**************************************************************************** Process commands from the client @@ -1451,6 +1492,11 @@ void smbd_process(void) time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; + /* Allocate the primary Inbut/Output buffers. */ + + if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) + return; + max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); while (True) { @@ -1474,8 +1520,7 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); #if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, - InBuffer, TOTAL_BUFFER_SIZE); + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); #endif while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { @@ -1496,8 +1541,7 @@ void smbd_process(void) */ num_echos = smb_echo_count; - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, - OutBuffer, TOTAL_BUFFER_SIZE); + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); process_smb(InBuffer, OutBuffer); -- cgit From 8908bd64eab93e763d8b943732bc19ed9d276eb2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 18 Jun 2007 12:22:42 +0000 Subject: r23538: Fix for wild-card rename: We can't return directly on error, we need to CloseDir. (This used to be commit 48cdafc10a0eb615d79057ec9e235ffe9a85e016) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e2b7084f11..41665e1676 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4689,7 +4689,7 @@ NTSTATUS rename_internals(connection_struct *conn, DEBUG(3,("rename_internals: open_file_ntcreate " "returned %s rename %s -> %s\n", nt_errstr(status), directory, newname)); - return status; + break; } status = rename_internals_fsp(conn, fsp, destname, attrs, @@ -4701,7 +4701,7 @@ NTSTATUS rename_internals(connection_struct *conn, DEBUG(3, ("rename_internals_fsp returned %s for " "rename %s -> %s\n", nt_errstr(status), directory, newname)); - return status; + break; } count++; -- cgit From 08a9de8927bbca982be4e566e56748045defc1c7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Jun 2007 17:19:08 +0000 Subject: r23589: Ensure we will always release any timeout handler on fsp close or removal of oplock. Mulitple removals are safe. Jeremy. (This used to be commit 6de0970704b3eff2b71e6bf499c6dda45d4d5e2d) --- source3/smbd/files.c | 3 +++ source3/smbd/oplock.c | 10 ++++------ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 590916011b..9994b50d15 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -439,6 +439,9 @@ void file_free(files_struct *fsp) TALLOC_FREE(fsp->notify); } + /* Ensure this event will never fire. */ + TALLOC_FREE(fsp->oplock_timeout); + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index ddb05d8b92..39fc847d6f 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -152,6 +152,8 @@ void release_file_oplock(files_struct *fsp) fsp->sent_oplock_break = NO_BREAK_SENT; flush_write_cache(fsp, OPLOCK_RELEASE_FLUSH); + + TALLOC_FREE(fsp->oplock_timeout); } /**************************************************************************** @@ -341,12 +343,8 @@ static void oplock_timeout_handler(struct event_context *ctx, { files_struct *fsp = (files_struct *)private_data; - /* Ensure we always remove this event. */ - if (fsp->oplock_timeout != NULL) { - /* Remove the timed event handler. */ - TALLOC_FREE(fsp->oplock_timeout); - fsp->oplock_timeout = NULL; - } + /* Remove the timed event handler. */ + TALLOC_FREE(fsp->oplock_timeout); DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name)); global_client_failed_oplock_break = True; remove_oplock(fsp); -- cgit From a0ac7a7f4c0290787cdadb5866272cee2bd61b8a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Jun 2007 22:49:10 +0000 Subject: r23620: Convert set_nt_acl to return NTSTATUS. Also fix the chown return to correctly return NT_STATUS_INVALID_OWNER if it should be disallowed. Matches better what W2K3R3 does. NFSv4 ACL module owners, please examine these changes. Jeremy. (This used to be commit fc6899a5506b272f8cd5f5837ca13300b4e69a5f) --- source3/smbd/nttrans.c | 12 ++----- source3/smbd/posix_acls.c | 89 ++++++++++++++++++----------------------------- 2 files changed, 36 insertions(+), 65 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 965da90a64..c13e35698b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1062,7 +1062,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu prs_struct pd; SEC_DESC *psd = NULL; TALLOC_CTX *mem_ctx; - BOOL ret; + NTSTATUS status; if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) { return NT_STATUS_OK; @@ -1112,16 +1112,10 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu security_info_sent &= ~DACL_SECURITY_INFORMATION; } - ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd); - - if (!ret) { - talloc_destroy(mem_ctx); - return NT_STATUS_ACCESS_DENIED; - } + status = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd); talloc_destroy(mem_ctx); - - return NT_STATUS_OK; + return status; } /**************************************************************************** diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7eda998547..8db48ea664 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -923,7 +923,7 @@ static mode_t map_nt_perms( uint32 *mask, int type) Unpack a SEC_DESC into a UNIX owner and group. ****************************************************************************/ -BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) +NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd) { DOM_SID owner_sid; DOM_SID grp_sid; @@ -933,7 +933,7 @@ BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_ if(security_info_sent == 0) { DEBUG(0,("unpack_nt_owners: no security info sent !\n")); - return True; + return NT_STATUS_OK; } /* @@ -961,9 +961,11 @@ BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_ DEBUG(3,("unpack_nt_owners: unable to validate" " owner sid for %s\n", sid_string_static(&owner_sid))); - return False; + return NT_STATUS_INVALID_OWNER; } } + DEBUG(3,("unpack_nt_owners: owner sid mapped to uid %u\n", + (unsigned int)*puser )); } /* @@ -981,14 +983,16 @@ BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_ } else { DEBUG(3,("unpack_nt_owners: unable to validate" " group sid.\n")); - return False; + return NT_STATUS_INVALID_OWNER; } } - } + DEBUG(3,("unpack_nt_owners: group sid mapped to gid %u\n", + (unsigned int)*pgrp)); + } DEBUG(5,("unpack_nt_owners: owner_sids validated.\n")); - return True; + return NT_STATUS_OK; } /**************************************************************************** @@ -3049,6 +3053,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) /* Case (4). */ if (!lp_dos_filemode(SNUM(conn))) { + errno = EPERM; return -1; } @@ -3082,7 +3087,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) This should be the only external function needed for the UNIX style set ACL. ****************************************************************************/ -BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) +NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) { connection_struct *conn = fsp->conn; uid_t user = (uid_t)-1; @@ -3094,15 +3099,13 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) canon_ace *dir_ace_list = NULL; BOOL acl_perms = False; mode_t orig_mode = (mode_t)0; - uid_t orig_uid; - gid_t orig_gid; - BOOL need_chown = False; + NTSTATUS status; DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); if (!CAN_WRITE(conn)) { DEBUG(10,("set acl rejected on read-only share\n")); - return False; + return NT_STATUS_MEDIA_WRITE_PROTECTED; } /* @@ -3111,40 +3114,29 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(fsp->is_directory || fsp->fh->fd == -1) { if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) - return False; + return map_nt_error_from_unix(errno); } else { if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) - return False; + return map_nt_error_from_unix(errno); } /* Save the original elements we check against. */ orig_mode = sbuf.st_mode; - orig_uid = sbuf.st_uid; - orig_gid = sbuf.st_gid; /* * Unpack the user/group/world id's. */ - if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) { - return False; + status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* * Do we need to chown ? */ - if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) { - need_chown = True; - } - - /* - * Chown before setting ACL only if we don't change the user, or - * if we change to the current user, but not if we want to give away - * the file. - */ - - if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) { + if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); @@ -3152,7 +3144,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); - return False; + if (errno == EPERM) { + return NT_STATUS_INVALID_OWNER; + } + return map_nt_error_from_unix(errno); } /* @@ -3162,7 +3157,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(fsp->is_directory) { if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) { - return False; + return map_nt_error_from_unix(errno); } } else { @@ -3174,16 +3169,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf); if(ret != 0) - return False; + return map_nt_error_from_unix(errno); } /* Save the original elements we check against. */ orig_mode = sbuf.st_mode; - orig_uid = sbuf.st_uid; - orig_gid = sbuf.st_gid; - - /* We did it, don't try again */ - need_chown = False; } create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); @@ -3198,7 +3188,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: cannot set permissions\n")); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return False; + return NT_STATUS_ACCESS_DENIED; } /* @@ -3221,7 +3211,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) )); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return False; + return map_nt_error_from_unix(errno); } } @@ -3231,7 +3221,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return False; + return map_nt_error_from_unix(errno); } } else { @@ -3256,7 +3246,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return False; + return map_nt_error_from_unix(errno); } } } @@ -3279,7 +3269,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) free_canon_ace_list(dir_ace_list); DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n", fsp->fsp_name )); - return False; + return NT_STATUS_ACCESS_DENIED; } if (orig_mode != posix_perms) { @@ -3304,7 +3294,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return False; + return map_nt_error_from_unix(errno); } } } @@ -3315,20 +3305,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) free_canon_ace_list(dir_ace_list); } - /* Any chown pending? */ - if (need_chown) { - - DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - - if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { - DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); - return False; - } - } - - return True; + return NT_STATUS_OK; } /**************************************************************************** -- cgit From a49b2ea9c8b66d7e0fa3b256277a1b317f504a40 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Jun 2007 22:45:08 +0000 Subject: r23640: When we support the SeSecurity privilage, this is where we'll check it. Jeremy. (This used to be commit 1b73bf79f4f8a2bc408d52a1ce9df47f33fb3a87) --- source3/smbd/nttrans.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c13e35698b..2c259713c2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -702,6 +702,17 @@ int reply_ntcreate_and_X(connection_struct *conn, } } +#if 0 + /* We need to support SeSecurityPrivilege for this. */ + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY)) && + !user_has_privileges(current_user.nt_user_token, + &se_security)) { + restore_case_semantics(conn, file_attributes); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); + } +#endif + /* * If it's a request for a directory open, deal with it separately. */ @@ -1378,6 +1389,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } +#if 0 + /* We need to support SeSecurityPrivilege for this. */ + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY)) && + !user_has_privileges(current_user.nt_user_token, + &se_security)) { + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); + } +#endif + if (ea_len) { pdata = data + sd_len; -- cgit From 07d2a3a89322a04fcc164c2c827b7f68f7369c29 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 29 Jun 2007 17:57:05 +0000 Subject: r23663: Fix bug #4308 - Excel save operation corrupts file ACLs. You don't want to know what I discovered about Windows ACLs to make this work :-(. See : http://www.codeproject.com/win32/accessctrl2.asp Search for "Q. How does Inheritance come into this?" for details. Jeremy. (This used to be commit e1d3a80d2bff2e3540637fd741fc149eeca5fb9d) --- source3/smbd/posix_acls.c | 283 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 255 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 8db48ea664..efead2dce1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -47,7 +47,7 @@ typedef struct canon_ace { DOM_SID trustee; enum ace_owner owner_type; enum ace_attribute attr; - posix_id unix_ug; + posix_id unix_ug; BOOL inherited; } canon_ace; @@ -828,20 +828,23 @@ static BOOL nt4_compatible_acls(void) not get. Deny entries are implicit on get with ace->perms = 0. ****************************************************************************/ -static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_sid, canon_ace *ace, BOOL directory_ace) +static SEC_ACCESS map_canon_ace_perms(int snum, + int *pacl_type, + mode_t perms, + BOOL directory_ace) { SEC_ACCESS sa; uint32 nt_mask = 0; *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - if (lp_acl_map_full_control(snum) && ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) { + if (lp_acl_map_full_control(snum) && ((perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) { if (directory_ace) { nt_mask = UNIX_DIRECTORY_ACCESS_RWX; } else { nt_mask = UNIX_ACCESS_RWX; } - } else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) { + } else if ((perms & ALL_ACE_PERMS) == (mode_t)0) { /* * Windows NT refuses to display ACEs with no permissions in them (but * they are perfectly legal with Windows 2000). If the ACE has empty @@ -857,18 +860,18 @@ static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_ nt_mask = 0; } else { if (directory_ace) { - nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 ); - nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 ); - nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 ); + nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 ); + nt_mask |= ((perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 ); + nt_mask |= ((perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 ); } else { - nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); - nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); - nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 ); + nt_mask |= ((perms & S_IRUSR) ? UNIX_ACCESS_R : 0 ); + nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 ); + nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 ); } } DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n", - (unsigned int)ace->perms, (unsigned int)nt_mask )); + (unsigned int)perms, (unsigned int)nt_mask )); init_sec_access(&sa,nt_mask); return sa; @@ -2893,26 +2896,37 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(SEC_ACE) ); - + /* * Create the NT ACE list from the canonical ace lists. */ - + ace = file_ace; for (i = 0; i < num_acls; i++, ace = ace->next) { SEC_ACCESS acc; - acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0); + acc = map_canon_ace_perms(SNUM(conn), + &nt_acl_type, + ace->perms, + fsp->is_directory); + init_sec_ace(&nt_ace_list[num_aces++], + &ace->trustee, + nt_acl_type, + acc, + ace->inherited ? + SEC_ACE_FLAG_INHERITED_ACE : 0); } - /* The User must have access to a profile share - even if we can't map the SID. */ + /* The User must have access to a profile share - even + * if we can't map the SID. */ if (lp_profile_acls(SNUM(conn))) { SEC_ACCESS acc; init_sec_access(&acc,FILE_GENERIC_ALL); - init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, + init_sec_ace(&nt_ace_list[num_aces++], + &global_sid_Builtin_Users, + SEC_ACE_TYPE_ACCESS_ALLOWED, acc, 0); } @@ -2920,18 +2934,27 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) for (i = 0; i < num_def_acls; i++, ace = ace->next) { SEC_ACCESS acc; - - acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, - SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY| - (ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0)); + + acc = map_canon_ace_perms(SNUM(conn), + &nt_acl_type, + ace->perms, + fsp->is_directory); + init_sec_ace(&nt_ace_list[num_aces++], + &ace->trustee, + nt_acl_type, + acc, + SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY| + (ace->inherited ? + SEC_ACE_FLAG_INHERITED_ACE : 0)); } - /* The User must have access to a profile share - even if we can't map the SID. */ + /* The User must have access to a profile share - even + * if we can't map the SID. */ if (lp_profile_acls(SNUM(conn))) { SEC_ACCESS acc; - + init_sec_access(&acc,FILE_GENERIC_ALL); init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| @@ -3081,6 +3104,198 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) return ret; } +static NTSTATUS append_ugw_ace(files_struct *fsp, + SMB_STRUCT_STAT *psbuf, + mode_t unx_mode, + int ugw, + SEC_ACE *se) +{ + mode_t perms; + SEC_ACCESS acc; + int acl_type; + DOM_SID trustee; + + switch (ugw) { + case S_IRUSR: + perms = unix_perms_to_acl_perms(unx_mode, + S_IRUSR, + S_IWUSR, + S_IXUSR); + uid_to_sid(&trustee, psbuf->st_uid ); + break; + case S_IRGRP: + perms = unix_perms_to_acl_perms(unx_mode, + S_IRGRP, + S_IWGRP, + S_IXGRP); + gid_to_sid(&trustee, psbuf->st_gid ); + break; + case S_IROTH: + perms = unix_perms_to_acl_perms(unx_mode, + S_IROTH, + S_IWOTH, + S_IXOTH); + sid_copy(&trustee, &global_sid_World); + break; + default: + return NT_STATUS_INVALID_PARAMETER; + } + acc = map_canon_ace_perms(SNUM(fsp->conn), + &acl_type, + perms, + fsp->is_directory); + + init_sec_ace(se, + &trustee, + acl_type, + acc, + 0); + return NT_STATUS_OK; +} + +/**************************************************************************** + If this is an +****************************************************************************/ + +static NTSTATUS append_parent_acl(files_struct *fsp, + SMB_STRUCT_STAT *psbuf, + SEC_DESC *psd, + SEC_DESC **pp_new_sd) +{ + SEC_DESC *parent_sd = NULL; + files_struct *parent_fsp = NULL; + TALLOC_CTX *mem_ctx = talloc_parent(psd); + char *parent_name = NULL; + SEC_ACE *new_ace = NULL; + unsigned int num_aces = psd->dacl->num_aces; + SMB_STRUCT_STAT sbuf; + NTSTATUS status; + int info; + size_t sd_size; + unsigned int i, j; + mode_t unx_mode; + + ZERO_STRUCT(sbuf); + + if (mem_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (!parent_dirname_talloc(mem_ctx, + fsp->fsp_name, + &parent_name, + NULL)) { + return NT_STATUS_NO_MEMORY; + } + + /* Create a default mode for u/g/w. */ + unx_mode = unix_mode(fsp->conn, + aARCH | (fsp->is_directory ? aDIR : 0), + fsp->fsp_name, + parent_name); + + status = open_directory(fsp->conn, + parent_name, + &sbuf, + FILE_READ_ATTRIBUTES, /* Just a stat open */ + FILE_SHARE_NONE, /* Ignored for stat opens */ + FILE_OPEN, + 0, + 0, + &info, + &parent_fsp); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + sd_size = SMB_VFS_GET_NT_ACL(parent_fsp, parent_fsp->fsp_name, + DACL_SECURITY_INFORMATION, &parent_sd ); + + close_file(parent_fsp, NORMAL_CLOSE); + + if (!sd_size) { + return NT_STATUS_ACCESS_DENIED; + } + + /* + * Make room for potentially all the ACLs from + * the parent, plus the user/group/other triple. + */ + + num_aces += parent_sd->dacl->num_aces + 3; + + if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, SEC_ACE, + num_aces)) == NULL) { + return NT_STATUS_NO_MEMORY; + } + + DEBUG(10,("append_parent_acl: parent ACL has %u entries. New " + "ACL has %u entries\n", + parent_sd->dacl->num_aces, num_aces )); + + /* Start by copying in all the given ACE entries. */ + for (i = 0; i < psd->dacl->num_aces; i++) { + sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]); + } + + /* + * Note that we're ignoring "inherit permissions" here + * as that really only applies to newly created files. JRA. + */ + + /* + * Append u/g/w. + */ + + status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRUSR, &new_ace[i++]); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRGRP, &new_ace[i++]); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = append_ugw_ace(fsp, psbuf, unx_mode, S_IROTH, &new_ace[i++]); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Finally append any inherited ACEs. */ + for (j = 0; j < parent_sd->dacl->num_aces; j++) { + SEC_ACE *se = &parent_sd->dacl->aces[i]; + uint32 i_flags = se->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY); + + if (fsp->is_directory) { + if (i_flags == SEC_ACE_FLAG_OBJECT_INHERIT) { + /* Should only apply to a file - ignore. */ + continue; + } + } else { + if ((i_flags & (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY)) != + SEC_ACE_FLAG_OBJECT_INHERIT) { + /* Should not apply to a file - ignore. */ + continue; + } + } + sec_ace_copy(&new_ace[i], se); + if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { + new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT); + } + new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE; + i++; + } + + parent_sd->dacl->aces = new_ace; + parent_sd->dacl->num_aces = i; + + *pp_new_sd = parent_sd; + return status; +} + /**************************************************************************** Reply to set a security descriptor on an fsp. security_info_sent is the description of the following NT ACL. @@ -3092,7 +3307,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) connection_struct *conn = fsp->conn; uid_t user = (uid_t)-1; gid_t grp = (gid_t)-1; - SMB_STRUCT_STAT sbuf; + SMB_STRUCT_STAT sbuf; DOM_SID file_owner_sid; DOM_SID file_grp_sid; canon_ace *file_ace_list = NULL; @@ -3162,12 +3377,12 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) } else { int ret; - + if(fsp->fh->fd == -1) ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf); else ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf); - + if(ret != 0) return map_nt_error_from_unix(errno); } @@ -3178,6 +3393,18 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); + if ((security_info_sent & DACL_SECURITY_INFORMATION) && + psd->dacl != NULL && + (psd->type & (SE_DESC_DACL_AUTO_INHERITED| + SE_DESC_DACL_AUTO_INHERIT_REQ))== + (SE_DESC_DACL_AUTO_INHERITED| + SE_DESC_DACL_AUTO_INHERIT_REQ) ) { + status = append_parent_acl(fsp, &sbuf, psd, &psd); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); -- cgit From ffe11a657f2cbef87c32774153c51bbf28c49d5d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 30 Jun 2007 00:22:59 +0000 Subject: r23664: Fix incorrect index - should be j not i. How did we ever live without valgrind :-). Jeremy. (This used to be commit 9b231149c78c8bbfb70c5675cffb652705ba2cd2) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index efead2dce1..c4c4b2e393 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3263,7 +3263,7 @@ static NTSTATUS append_parent_acl(files_struct *fsp, /* Finally append any inherited ACEs. */ for (j = 0; j < parent_sd->dacl->num_aces; j++) { - SEC_ACE *se = &parent_sd->dacl->aces[i]; + SEC_ACE *se = &parent_sd->dacl->aces[j]; uint32 i_flags = se->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY); -- cgit From b85bfd50663bbec07313d626ad3845f2a9fcfd3c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 3 Jul 2007 13:07:56 +0000 Subject: r23682: Old patch I forgot in one of my 3.0.25 trees. Make sure we honour the directive not to allow machine password changes. (This used to be commit 436555f05ceae34d8df2356d1066b6b5e0a07c41) --- source3/smbd/chgpasswd.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 8146d6d137..1227163c22 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1019,6 +1019,7 @@ static BOOL check_passwd_history(struct samu *sampass, const char *plaintext) NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason) { uint32 min_len; + uint32 refuse; struct passwd *pass = NULL; const char *username = pdb_get_username(hnd); time_t can_change_time = pdb_get_pass_can_change_time(hnd); @@ -1036,6 +1037,21 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw return NT_STATUS_ACCOUNT_RESTRICTION; } + /* check to see if it is a Machine account and if the policy + * denies machines to change the password. * + * Should we deny also SRVTRUST and/or DOMSTRUST ? .SSS. */ + if (pdb_get_acct_ctrl(hnd) & ACB_WSTRUST) { + if (pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &refuse) && refuse) { + DEBUG(1, ("Machine %s cannot change password now, " + "denied by Refuse Machine Password Change policy\n", + username)); + if (samr_reject_reason) { + *samr_reject_reason = REJECT_REASON_OTHER; + } + return NT_STATUS_ACCOUNT_RESTRICTION; + } + } + /* removed calculation here, becuase passdb now calculates based on policy. jmcd */ if ((can_change_time != 0) && (time(NULL) < can_change_time)) { -- cgit From d37c1991361f23318d549a0af62afa50a2382984 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 3 Jul 2007 13:11:56 +0000 Subject: r23683: Check ports are in the correct range (1-65535) (This used to be commit 84b193a7d95aa8c00da2a3720ee87a7231e0fc6e) --- source3/smbd/sockinit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sockinit.c b/source3/smbd/sockinit.c index a4b9d63810..9d46776f89 100644 --- a/source3/smbd/sockinit.c +++ b/source3/smbd/sockinit.c @@ -63,7 +63,7 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); - if (port == 0) { + if (port == 0 || port > 0xffff) { continue; } s = listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); @@ -101,7 +101,7 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); - if (port == 0) continue; + if (port == 0 || port > 0xffff) continue; /* open an incoming socket */ s = open_socket_in(SOCK_STREAM, port, 0, interpret_addr(lp_socket_address()),True); -- cgit From 0bc56a2e5ffd0e65e4770e10c80d9fec02950b36 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jul 2007 16:26:27 +0000 Subject: r23724: Reduce access to the global inbuf a tiny bit. Add a struct smb_request that contains some of the fields from the SMB header, removing the need to access inbuf directly. This right now is used only in the open file code & friends, and creating that header is only done when needed. This needs more work, but it is a start. Jeremy, I'm only checking this into 3_0, please review before I merge it to _26. Volker (This used to be commit ca988f4e79e977160d82e86486972afd15d4acf5) --- source3/smbd/dir.c | 6 ++-- source3/smbd/nttrans.c | 53 +++++++++++++++++------------- source3/smbd/open.c | 66 +++++++++++++++++++++++++------------ source3/smbd/posix_acls.c | 3 +- source3/smbd/process.c | 12 +++++++ source3/smbd/reply.c | 64 +++++++++++++++++++++++------------- source3/smbd/trans2.c | 83 ++++++++++++++++++++++++++++++----------------- 7 files changed, 189 insertions(+), 98 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index db3e155ae4..e7baf2b759 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -879,7 +879,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S /* Pseudo-open the file (note - no fd's created). */ if(S_ISDIR(pst->st_mode)) { - status = open_directory(conn, name, pst, + status = open_directory(conn, NULL, name, pst, READ_CONTROL_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, @@ -887,7 +887,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S FILE_ATTRIBUTE_DIRECTORY, NULL, &fsp); } else { - status = open_file_stat(conn, name, pst, &fsp); + status = open_file_stat(conn, NULL, name, pst, &fsp); } if (!NT_STATUS_IS_OK(status)) { @@ -943,7 +943,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ if(S_ISDIR(pst->st_mode)) { return True; } else { - status = open_file_ntcreate(conn, name, pst, + status = open_file_ntcreate(conn, NULL, name, pst, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 2c259713c2..7e17e3b938 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -505,6 +505,7 @@ int reply_ntcreate_and_X(connection_struct *conn, struct timespec m_timespec; BOOL extended_oplock_granted = False; NTSTATUS status; + struct smb_request req; START_PROFILE(SMBntcreateX); @@ -520,6 +521,8 @@ int reply_ntcreate_and_X(connection_struct *conn, (unsigned int)create_options, (unsigned int)root_dir_fid )); + init_smb_request(&req, (uint8 *)inbuf); + /* * If it's an IPC, use the pipe handler. */ @@ -726,7 +729,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } oplock_request = 0; - status = open_directory(conn, fname, &sbuf, + status = open_directory(conn, &req, fname, &sbuf, access_mask, share_access, create_disposition, @@ -764,7 +767,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - status = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn, &req, fname, &sbuf, access_mask, share_access, create_disposition, @@ -807,7 +810,8 @@ int reply_ntcreate_and_X(connection_struct *conn, } oplock_request = 0; - status = open_directory(conn, fname, &sbuf, + status = open_directory(conn, &req, fname, + &sbuf, access_mask, share_access, create_disposition, @@ -1199,6 +1203,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o char *pdata = NULL; NTSTATUS status; size_t param_len; + struct smb_request req; DEBUG(5,("call_nt_transact_create\n")); @@ -1227,6 +1232,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + init_smb_request(&req, (uint8 *)inbuf); + flags = IVAL(params,0); access_mask = IVAL(params,8); file_attributes = IVAL(params,20); @@ -1389,16 +1396,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } -#if 0 - /* We need to support SeSecurityPrivilege for this. */ - if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY)) && - !user_has_privileges(current_user.nt_user_token, - &se_security)) { - restore_case_semantics(conn, file_attributes); - return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); - } -#endif - if (ea_len) { pdata = data + sd_len; @@ -1430,7 +1427,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ oplock_request = 0; - status = open_directory(conn, fname, &sbuf, + status = open_directory(conn, &req, fname, &sbuf, access_mask, share_access, create_disposition, @@ -1448,7 +1445,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Ordinary file case. */ - status = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,&req,fname,&sbuf, access_mask, share_access, create_disposition, @@ -1471,7 +1468,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } oplock_request = 0; - status = open_directory(conn, fname, &sbuf, + status = open_directory(conn, &req, fname, + &sbuf, access_mask, share_access, create_disposition, @@ -1691,7 +1689,9 @@ int reply_ntcancel(connection_struct *conn, Copy a file. ****************************************************************************/ -static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs) +static NTSTATUS copy_internals(connection_struct *conn, + struct smb_request *req, + char *oldname, char *newname, uint32 attrs) { SMB_STRUCT_STAT sbuf1, sbuf2; pstring last_component_oldname; @@ -1757,7 +1757,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); - status = open_file_ntcreate(conn,oldname,&sbuf1, + status = open_file_ntcreate(conn, req, oldname, &sbuf1, FILE_READ_DATA, /* Read-only. */ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, @@ -1770,7 +1770,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new return status; } - status = open_file_ntcreate(conn,newname,&sbuf2, + status = open_file_ntcreate(conn, req, newname, &sbuf2, FILE_WRITE_DATA, /* Read-only. */ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_CREATE, @@ -1834,9 +1834,12 @@ int reply_ntrename(connection_struct *conn, BOOL dest_has_wcard = False; uint32 attrs = SVAL(inbuf,smb_vwv0); uint16 rename_type = SVAL(inbuf,smb_vwv1); + struct smb_request req; START_PROFILE(SMBntrename); + init_smb_request(&req, (uint8 *)inbuf); + p = smb_buf(inbuf) + 1; p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -1884,7 +1887,9 @@ int reply_ntrename(connection_struct *conn, switch(rename_type) { case RENAME_FLAG_RENAME: - status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard); + status = rename_internals(conn, &req, oldname, newname, + attrs, False, src_has_wcard, + dest_has_wcard); break; case RENAME_FLAG_HARD_LINK: if (src_has_wcard || dest_has_wcard) { @@ -1899,7 +1904,8 @@ int reply_ntrename(connection_struct *conn, /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { - status = copy_internals(conn, oldname, newname, attrs); + status = copy_internals(conn, &req, oldname, + newname, attrs); } break; case RENAME_FLAG_MOVE_CLUSTER_INFORMATION: @@ -2036,6 +2042,9 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o BOOL replace_if_exists = False; BOOL dest_has_wcard = False; NTSTATUS status; + struct smb_request req; + + init_smb_request(&req, (uint8 *)inbuf); if(parameter_count < 5) { return ERROR_DOS(ERRDOS,ERRbadfunc); @@ -2050,7 +2059,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o return ERROR_NT(status); } - status = rename_internals(conn, fsp->fsp_name, + status = rename_internals(conn, &req, fsp->fsp_name, new_name, 0, replace_if_exists, False, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 41fbce9889..62a4fe0807 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -25,7 +25,6 @@ extern struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; -extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; struct deferred_open_record { @@ -201,6 +200,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, + struct smb_request *req, const char *parent_dir, const char *name, const char *path, @@ -359,8 +359,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp->mode = psbuf->st_mode; fsp->file_id = file_id_sbuf(psbuf); - fsp->vuid = current_user.vuid; - fsp->file_pid = global_smbpid; + fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; + fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = True; fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; if (!CAN_WRITE(conn)) { @@ -871,6 +871,8 @@ static BOOL open_match_attributes(connection_struct *conn, static files_struct *fcb_or_dos_open(connection_struct *conn, const char *fname, struct file_id id, + uint16 file_pid, + uint16 vuid, uint32 access_mask, uint32 share_access, uint32 create_options) @@ -893,8 +895,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, (unsigned int)fsp->access_mask )); if (fsp->fh->fd != -1 && - fsp->vuid == current_user.vuid && - fsp->file_pid == global_smbpid && + fsp->vuid == vuid && + fsp->file_pid == file_pid && (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && (fsp->access_mask & FILE_WRITE_DATA) && @@ -1103,6 +1105,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ ****************************************************************************/ NTSTATUS open_file_ntcreate(connection_struct *conn, + struct smb_request *req, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ @@ -1129,7 +1132,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int info; uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; - uint16 mid = get_current_mid(); struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; uint32 open_access_mask = access_mask; @@ -1179,7 +1181,17 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, create_disposition, create_options, unx_mode, oplock_request)); - if ((pml = get_open_deferred_message(mid)) != NULL) { + if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) { + DEBUG(0, ("No smb request but not an internal only open!\n")); + return NT_STATUS_INTERNAL_ERROR; + } + + /* + * Only non-internal opens can be deferred at all + */ + + if ((req != NULL) + && ((pml = get_open_deferred_message(req->mid)) != NULL)) { struct deferred_open_record *state = (struct deferred_open_record *)pml->private_data.data; @@ -1194,12 +1206,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { - del_deferred_open_entry(lck, mid); + del_deferred_open_entry(lck, req->mid); TALLOC_FREE(lck); } /* Ensure we don't reprocess this message. */ - remove_deferred_open_smb_message(mid); + remove_deferred_open_smb_message(req->mid); } status = check_name(conn, fname); @@ -1477,9 +1489,19 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { files_struct *fsp_dup; + if (req == NULL) { + DEBUG(0, ("DOS open without an SMB " + "request!\n")); + TALLOC_FREE(lck); + file_free(fsp); + return NT_STATUS_INTERNAL_ERROR; + } + /* Use the client requested access mask here, * not the one we open with. */ fsp_dup = fcb_or_dos_open(conn, fname, id, + req->smbpid, + req->vuid, access_mask, share_access, create_options); @@ -1601,7 +1623,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf, + fsp_open = open_file(fsp, conn, req, parent_dir, newname, fname, psbuf, flags|flags2, unx_mode, access_mask, open_access_mask); @@ -1862,7 +1884,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* If this is a successful open, we must remove any deferred open * records. */ - del_deferred_open_entry(lck, mid); + if (req != NULL) { + del_deferred_open_entry(lck, req->mid); + } TALLOC_FREE(lck); conn->num_files_open++; @@ -1892,8 +1916,8 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0, - FILE_WRITE_DATA, FILE_WRITE_DATA); + status = open_file(fsp, conn, NULL, NULL, NULL, fname, psbuf, O_WRONLY, + 0, FILE_WRITE_DATA, FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -2005,6 +2029,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, ****************************************************************************/ NTSTATUS open_directory(connection_struct *conn, + struct smb_request *req, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, @@ -2121,8 +2146,8 @@ NTSTATUS open_directory(connection_struct *conn, fsp->mode = psbuf->st_mode; fsp->file_id = file_id_sbuf(psbuf); - fsp->vuid = current_user.vuid; - fsp->file_pid = global_smbpid; + fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; + fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; @@ -2200,7 +2225,7 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) SET_STAT_INVALID(sbuf); - status = open_directory(conn, directory, &sbuf, + status = open_directory(conn, NULL, directory, &sbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ FILE_CREATE, @@ -2220,8 +2245,9 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -NTSTATUS open_file_stat(connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf, files_struct **result) +NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req, + const char *fname, SMB_STRUCT_STAT *psbuf, + files_struct **result) { files_struct *fsp = NULL; NTSTATUS status; @@ -2248,8 +2274,8 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, fsp->mode = psbuf->st_mode; fsp->file_id = file_id_sbuf(psbuf); - fsp->vuid = current_user.vuid; - fsp->file_pid = global_smbpid; + fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; + fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c4c4b2e393..947c30fb4a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3195,13 +3195,14 @@ static NTSTATUS append_parent_acl(files_struct *fsp, parent_name); status = open_directory(fsp->conn, + NULL, parent_name, &sbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ FILE_OPEN, 0, - 0, + INTERNAL_OPEN_ONLY, &info, &parent_fsp); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3b922af51f..dd623e69a5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -57,6 +57,18 @@ uint16 get_current_mid(void) return SVAL(InBuffer,smb_mid); } +/* + * Initialize a struct smb_request from an inbuf + */ + +void init_smb_request(struct smb_request *req, const uint8 *inbuf) +{ + req->flags2 = SVAL(inbuf, smb_flg2); + req->smbpid = SVAL(inbuf, smb_pid); + req->mid = SVAL(inbuf, smb_mid); + req->vuid = SVAL(inbuf, smb_uid); +} + /**************************************************************************** structure to hold a linked list of queued messages. for processing. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 41665e1676..76265ed464 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1263,7 +1263,11 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, uint32 create_disposition; uint32 create_options = 0; NTSTATUS status; + struct smb_request req; + START_PROFILE(SMBopen); + + init_smb_request(&req, (uint8 *)inbuf); deny_mode = SVAL(inbuf,smb_vwv0); @@ -1300,7 +1304,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); } - status = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn, &req, fname, &sbuf, access_mask, share_mode, create_disposition, @@ -1383,9 +1387,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt uint32 share_mode; uint32 create_disposition; uint32 create_options = 0; + struct smb_request req; START_PROFILE(SMBopenX); + init_smb_request(&req, (uint8 *)inbuf); + /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { @@ -1434,7 +1441,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); } - status = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn, &req, fname, &sbuf, access_mask, share_mode, create_disposition, @@ -1576,8 +1583,11 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; uint32 create_disposition; uint32 create_options = 0; + struct smb_request req; START_PROFILE(SMBcreate); + + init_smb_request(&req, (uint8 *)inbuf); com = SVAL(inbuf,smb_com); @@ -1623,7 +1633,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file using ntcreate. */ - status = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn, &req, fname, &sbuf, access_mask, share_mode, create_disposition, @@ -1678,9 +1688,12 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, char *p, *s; NTSTATUS status; unsigned int namelen; + struct smb_request req; START_PROFILE(SMBctemp); + init_smb_request(&req, (uint8 *)inbuf); + srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); @@ -1722,7 +1735,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SMB_VFS_STAT(conn,fname,&sbuf); /* We should fail if file does not exist. */ - status = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn, &req, fname, &sbuf, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, @@ -1813,8 +1826,8 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, * unlink a file with all relevant access checks *******************************************************************/ -static NTSTATUS do_unlink(connection_struct *conn, char *fname, - uint32 dirtype, BOOL can_defer) +static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req, + char *fname, uint32 dirtype) { SMB_STRUCT_STAT sbuf; uint32 fattr; @@ -1906,13 +1919,13 @@ static NTSTATUS do_unlink(connection_struct *conn, char *fname, /* On open checks the open itself will check the share mode, so don't do it here as we'll get it wrong. */ - status = open_file_ntcreate(conn, fname, &sbuf, + status = open_file_ntcreate(conn, req, fname, &sbuf, DELETE_ACCESS, FILE_SHARE_NONE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - can_defer ? 0 : INTERNAL_OPEN_ONLY, + req != NULL ? 0 : INTERNAL_OPEN_ONLY, NULL, &fsp); if (!NT_STATUS_IS_OK(status)) { @@ -1935,8 +1948,8 @@ static NTSTATUS do_unlink(connection_struct *conn, char *fname, code. ****************************************************************************/ -NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, - char *name, BOOL has_wild, BOOL can_defer) +NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, + uint32 dirtype, char *name, BOOL has_wild) { pstring directory; pstring mask; @@ -1986,7 +1999,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, return status; } - status = do_unlink(conn,directory,dirtype,can_defer); + status = do_unlink(conn, req, directory, dirtype); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2050,7 +2063,7 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, return status; } - status = do_unlink(conn, fname, dirtype, can_defer); + status = do_unlink(conn, req, fname, dirtype); if (!NT_STATUS_IS_OK(status)) { continue; } @@ -2081,9 +2094,12 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size uint32 dirtype; NTSTATUS status; BOOL path_contains_wcard = False; + struct smb_request req; START_PROFILE(SMBunlink); + init_smb_request(&req, (uint8 *)inbuf); + dirtype = SVAL(inbuf,smb_vwv0); srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard); @@ -2103,8 +2119,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - status = unlink_internals(conn, dirtype, name, path_contains_wcard, - True); + status = unlink_internals(conn, &req, dirtype, name, + path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ @@ -4467,7 +4483,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, +NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, pstring name, pstring newname, uint32 attrs, @@ -4578,12 +4594,12 @@ NTSTATUS rename_internals(connection_struct *conn, SMB_VFS_STAT(conn, directory, &sbuf1); status = S_ISDIR(sbuf1.st_mode) ? - open_directory(conn, directory, &sbuf1, + open_directory(conn, req, directory, &sbuf1, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, NULL, &fsp) - : open_file_ntcreate(conn, directory, &sbuf1, + : open_file_ntcreate(conn, req, directory, &sbuf1, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, 0, NULL, @@ -4674,12 +4690,12 @@ NTSTATUS rename_internals(connection_struct *conn, SMB_VFS_STAT(conn, fname, &sbuf1); status = S_ISDIR(sbuf1.st_mode) ? - open_directory(conn, fname, &sbuf1, + open_directory(conn, req, fname, &sbuf1, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, NULL, &fsp) - : open_file_ntcreate(conn, fname, &sbuf1, + : open_file_ntcreate(conn, req, fname, &sbuf1, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, 0, NULL, @@ -4733,9 +4749,12 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; BOOL src_has_wcard = False; BOOL dest_has_wcard = False; + struct smb_request req; START_PROFILE(SMBmv); + init_smb_request(&req, (uint8 *)inbuf); + p = smb_buf(inbuf) + 1; p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -4769,7 +4788,8 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard); + status = rename_internals(conn, &req, name, newname, attrs, False, + src_has_wcard, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); if (open_was_deferred(SVAL(inbuf,smb_mid))) { @@ -4833,7 +4853,7 @@ NTSTATUS copy_file(connection_struct *conn, } } - status = open_file_ntcreate(conn,src,&src_sbuf, + status = open_file_ntcreate(conn, NULL, src, &src_sbuf, FILE_GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, @@ -4851,7 +4871,7 @@ NTSTATUS copy_file(connection_struct *conn, ZERO_STRUCTP(&sbuf2); } - status = open_file_ntcreate(conn,dest,&sbuf2, + status = open_file_ntcreate(conn, NULL, dest, &sbuf2, FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, new_create_disposition, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index af6bc413d9..8d4f505e09 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -740,9 +740,12 @@ int send_trans2_replies(const char *inbuf, Reply to a TRANSACT2_OPEN. ****************************************************************************/ -static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static int call_trans2open(connection_struct *conn, + struct smb_request *req, + char *inbuf, char *outbuf, int bufsize, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; @@ -859,7 +862,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - status = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn, req, fname, &sbuf, access_mask, share_mode, create_disposition, @@ -4299,6 +4302,7 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_size(connection_struct *conn, + struct smb_request *req, files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf, @@ -4328,7 +4332,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, return NT_STATUS_OK; } - status = open_file_ntcreate(conn, fname, psbuf, + status = open_file_ntcreate(conn, req, fname, psbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, @@ -4603,6 +4607,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_file_rename_information(connection_struct *conn, + struct smb_request *req, char *inbuf, char *outbuf, const char *pdata, @@ -4664,7 +4669,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, } else { DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, newname )); - status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard); + status = rename_internals(conn, req, fname, base_name, 0, + overwrite, False, dest_has_wcard); } return status; @@ -4955,6 +4961,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, + struct smb_request *req, const char *pdata, int total_data, files_struct *fsp, @@ -5007,7 +5014,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, /* Pathname or stat or directory file. */ - status = open_file_ntcreate(conn, fname, psbuf, + status = open_file_ntcreate(conn, req, fname, psbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, @@ -5035,6 +5042,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, + struct smb_request *req, const char *pdata, int total_data, files_struct *fsp, @@ -5059,7 +5067,7 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for " "file %s to %.0f\n", fname, (double)size )); - return smb_set_file_size(conn, + return smb_set_file_size(conn, req, fsp, fname, psbuf, @@ -5155,6 +5163,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, + struct smb_request *req, const char *pdata, int total_data, files_struct *fsp, @@ -5306,7 +5315,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Deal with any size changes. */ - status = smb_set_file_size(conn, + status = smb_set_file_size(conn, req, fsp, fname, psbuf, @@ -5329,6 +5338,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", ****************************************************************************/ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, + struct smb_request *req, const char *pdata, int total_data, files_struct *fsp, @@ -5346,7 +5356,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, /* Start by setting all the fields that are common between UNIX_BASIC * and UNIX_INFO2. */ - status = smb_set_file_unix_basic(conn, pdata, total_data, + status = smb_set_file_unix_basic(conn, req, pdata, total_data, fsp, fname, psbuf); if (!NT_STATUS_IS_OK(status)) { return status; @@ -5390,6 +5400,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_posix_mkdir(connection_struct *conn, + struct smb_request *req, char **ppdata, int total_data, const char *fname, @@ -5422,7 +5433,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n", fname, (unsigned int)unixmode )); - status = open_directory(conn, + status = open_directory(conn, req, fname, psbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ @@ -5484,6 +5495,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_posix_open(connection_struct *conn, + struct smb_request *req, char **ppdata, int total_data, const char *fname, @@ -5519,7 +5531,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, wire_open_mode = IVAL(pdata,4); if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) { - return smb_posix_mkdir(conn, + return smb_posix_mkdir(conn, req, ppdata, total_data, fname, @@ -5587,7 +5599,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, (unsigned int)wire_open_mode, (unsigned int)unixmode )); - status = open_file_ntcreate(conn, + status = open_file_ntcreate(conn, req, fname, psbuf, access_mask, @@ -5671,6 +5683,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_posix_unlink(connection_struct *conn, + struct smb_request *req, const char *pdata, int total_data, const char *fname, @@ -5701,7 +5714,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, fname)); if (VALID_STAT_OF_DIR(*psbuf)) { - status = open_directory(conn, + status = open_directory(conn, req, fname, psbuf, DELETE_ACCESS, @@ -5714,7 +5727,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, } else { char del = 1; - status = open_file_ntcreate(conn, + status = open_file_ntcreate(conn, req, fname, psbuf, DELETE_ACCESS, @@ -5752,7 +5765,10 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ -static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, +static int call_trans2setfilepathinfo(connection_struct *conn, + struct smb_request *req, + char *inbuf, char *outbuf, int length, + int bufsize, unsigned int tran_call, char **pparams, int total_params, char **ppdata, int total_data, unsigned int max_data_bytes) @@ -5933,7 +5949,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_ALLOCATION_INFORMATION: case SMB_SET_FILE_ALLOCATION_INFO: { - status = smb_set_file_allocation_info(conn, + status = smb_set_file_allocation_info(conn, req, pdata, total_data, fsp, @@ -5945,7 +5961,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_SET_FILE_END_OF_FILE_INFO: { - status = smb_set_file_end_of_file_info(conn, + status = smb_set_file_end_of_file_info(conn, req, pdata, total_data, fsp, @@ -6004,7 +6020,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_SET_FILE_UNIX_BASIC: { - status = smb_set_file_unix_basic(conn, + status = smb_set_file_unix_basic(conn, req, pdata, total_data, fsp, @@ -6015,7 +6031,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_SET_FILE_UNIX_INFO2: { - status = smb_set_file_unix_info2(conn, + status = smb_set_file_unix_info2(conn, req, pdata, total_data, fsp, @@ -6055,7 +6071,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_RENAME_INFORMATION: { - status = smb_file_rename_information(conn, + status = smb_file_rename_information(conn, req, inbuf, outbuf, pdata, @@ -6099,7 +6115,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - status = smb_posix_open(conn, + status = smb_posix_open(conn, req, ppdata, total_data, fname, @@ -6115,7 +6131,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - status = smb_posix_unlink(conn, + status = smb_posix_unlink(conn, req, pdata, total_data, fname, @@ -6451,9 +6467,9 @@ int reply_findnclose(connection_struct *conn, return(outsize); } -int handle_trans2(connection_struct *conn, - struct trans_state *state, - char *inbuf, char *outbuf, int size, int bufsize) +static int handle_trans2(connection_struct *conn, struct smb_request *req, + struct trans_state *state, + char *inbuf, char *outbuf, int size, int bufsize) { int outsize; @@ -6467,7 +6483,7 @@ int handle_trans2(connection_struct *conn, { START_PROFILE(Trans2_open); outsize = call_trans2open( - conn, inbuf, outbuf, bufsize, + conn, req, inbuf, outbuf, bufsize, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); @@ -6541,7 +6557,7 @@ int handle_trans2(connection_struct *conn, { START_PROFILE(Trans2_setpathinfo); outsize = call_trans2setfilepathinfo( - conn, inbuf, outbuf, size, bufsize, state->call, + conn, req, inbuf, outbuf, size, bufsize, state->call, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); @@ -6749,7 +6765,10 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, if ((state->received_param == state->total_param) && (state->received_data == state->total_data)) { - outsize = handle_trans2(conn, state, inbuf, outbuf, + struct smb_request req; + init_smb_request(&req, (uint8 *)inbuf); + + outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size, bufsize); SAFE_FREE(state->data); SAFE_FREE(state->param); @@ -6788,6 +6807,7 @@ int reply_transs2(connection_struct *conn, int outsize = 0; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; + struct smb_request req; START_PROFILE(SMBtranss2); @@ -6873,7 +6893,10 @@ int reply_transs2(connection_struct *conn, */ SCVAL(outbuf,smb_com,SMBtrans2); - outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize); + init_smb_request(&req, (uint8 *)inbuf); + + outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size, + bufsize); DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); -- cgit From 5391750ce6db47678a03db4d67a016acff4fc8e2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jul 2007 16:27:47 +0000 Subject: r23725: Remove get_current_mid() Jeremy, next one to review :-) (This used to be commit a50555dda7db5e848e337185ed91c41c2557f7be) --- source3/smbd/open.c | 50 +++++++++++++++++++++++++++++++++----------------- source3/smbd/process.c | 9 --------- 2 files changed, 33 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 62a4fe0807..5cb8340e0e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -644,6 +644,7 @@ static BOOL is_delete_request(files_struct *fsp) { static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, + uint16 mid, int pass_number, int oplock_request) { @@ -728,7 +729,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); - exclusive->op_mid = get_current_mid(); + exclusive->op_mid = mid; /* Create the message. */ share_mode_entry_to_message(msg, exclusive); @@ -768,9 +769,9 @@ static BOOL request_timed_out(struct timeval request_time, static void defer_open(struct share_mode_lock *lck, struct timeval request_time, struct timeval timeout, + uint16 mid, struct deferred_open_record *state) { - uint16 mid = get_current_mid(); int i; /* Paranoia check */ @@ -1065,7 +1066,9 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func } -static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time) +static void schedule_defer_open(struct share_mode_lock *lck, + struct timeval request_time, + uint16 mid) { struct deferred_open_record state; @@ -1096,7 +1099,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ state.id = lck->id; if (!request_timed_out(request_time, timeout)) { - defer_open(lck, request_time, timeout, &state); + defer_open(lck, request_time, timeout, mid, &state); } } @@ -1443,8 +1446,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 1, + oplock_request)) { + schedule_defer_open(lck, request_time, req->mid); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1461,8 +1466,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * status again. */ /* Second pass - send break for both batch or * exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 2, + oplock_request)) { + schedule_defer_open(lck, request_time, + req->mid); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1576,10 +1584,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, state.delayed_for_oplocks = False; state.id = id; - if (!request_timed_out(request_time, - timeout)) { + if ((req != NULL) + && !request_timed_out(request_time, + timeout)) { defer_open(lck, request_time, timeout, - &state); + req->mid, &state); } } @@ -1667,8 +1676,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 1, + oplock_request)) { + schedule_defer_open(lck, request_time, req->mid); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1684,8 +1695,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * status again. */ /* Second pass - send break for both batch or * exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 2, + oplock_request)) { + schedule_defer_open(lck, request_time, + req->mid); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1709,8 +1723,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * "goto top of this function", but don't tell * anybody... */ - defer_open(lck, request_time, timeval_zero(), - &state); + if (req != NULL) { + defer_open(lck, request_time, timeval_zero(), + req->mid, &state); + } TALLOC_FREE(lck); return status; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dd623e69a5..1cb2c27fd3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -48,15 +48,6 @@ SIG_ATOMIC_T got_sig_term = 0; extern BOOL global_machine_password_needs_changing; extern int max_send; -/**************************************************************************** - Function to return the current request mid from Inbuffer. -****************************************************************************/ - -uint16 get_current_mid(void) -{ - return SVAL(InBuffer,smb_mid); -} - /* * Initialize a struct smb_request from an inbuf */ -- cgit From fcda5b589633b96415890c569bf23e3e284e0916 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jul 2007 16:33:37 +0000 Subject: r23726: Explicitly pass down the FLAGS2 field to srvstr_pull_buf. The next checkin will pull this up to srvstr_get_path. At that point we can get more independent of the inbuf, the base_ptr in pull_string will only be used to satisfy UCS2 alignment constraints. (This used to be commit 836782b07bf133e9b2598c4a089f1c810e4c7754) --- source3/smbd/ipc.c | 4 ++-- source3/smbd/message.c | 12 ++++++++---- source3/smbd/nttrans.c | 3 ++- source3/smbd/pipes.c | 3 ++- source3/smbd/reply.c | 27 ++++++++++++++++++--------- source3/smbd/sesssetup.c | 43 +++++++++++++++++++++++++++++-------------- source3/smbd/trans2.c | 6 ++++-- 7 files changed, 65 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6b647fc72b..ce26b53e1b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -543,8 +543,8 @@ int reply_trans(connection_struct *conn, state->one_way = BITSETW(inbuf+smb_vwv5,1); memset(state->name, '\0',sizeof(state->name)); - srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf), - sizeof(state->name), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), state->name, + smb_buf(inbuf), sizeof(state->name), STR_TERMINATE); if ((dscnt > state->total_data) || (pscnt > state->total_param)) goto bad_param; diff --git a/source3/smbd/message.c b/source3/smbd/message.c index e6a5015276..f390e539b0 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -134,8 +134,10 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, outsize = set_message(inbuf,outbuf,0,0,True); p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p, + sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p, + sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; msg = p; @@ -176,8 +178,10 @@ int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_si msgpos = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p, + sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p, + sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7e17e3b938..782c90cba1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -382,7 +382,8 @@ static int do_ntcreate_pipe_open(connection_struct *conn, char *p = NULL; uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), fname, smb_buf(inbuf), + sizeof(fname), STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { return ret; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index aba2fe69c5..1da2f0c22f 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -65,7 +65,8 @@ int reply_open_pipe_and_X(connection_struct *conn, int i; /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull_buf(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), pipe_name, + smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 76265ed464..ac06f2fd6d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -218,9 +218,11 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de #endif if (src_len == 0) { - ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); + ret = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, flags); } else { - ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags); + ret = srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, src_len, flags); } *contains_wcard = False; @@ -255,9 +257,11 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len #endif if (src_len == 0) { - ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); + ret = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, flags); } else { - ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags); + ret = srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, src_len, flags); } if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) { @@ -391,10 +395,13 @@ int reply_tcon(connection_struct *conn, *service_buf = *password = *dev = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1; - pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p, + sizeof(service_buf), STR_TERMINATE) + 1; + pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p, + sizeof(password), STR_TERMINATE) + 1; p += pwlen; - p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev), + STR_TERMINATE) + 1; p = strrchr_m(service_buf,'\\'); if (p) { @@ -478,7 +485,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt p = smb_buf(inbuf) + passlen + 1; } - p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p, + sizeof(path), STR_TERMINATE); /* * the service name can be either: \\server\share @@ -495,7 +503,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt else fstrcpy(service,path); - p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII); + p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p, + sizeof(client_devicetype), 6, STR_ASCII); DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service)); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 22c598a654..3ed338bda7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1057,9 +1057,12 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, #endif p2 = inbuf + smb_vwv13 + data_blob_len; - p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE); + p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_os, p2, + sizeof(native_os), STR_TERMINATE); + p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_lanman, p2, + sizeof(native_lanman), STR_TERMINATE); + p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), primary_domain, p2, + sizeof(primary_domain), STR_TERMINATE); DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", native_os, native_lanman, primary_domain)); @@ -1283,7 +1286,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, plaintext_password.data[passlen1] = 0; } - srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), user, + smb_buf(inbuf)+passlen1, sizeof(user), + STR_TERMINATE); *domain = 0; } else { @@ -1363,21 +1368,28 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (unic && (passlen2 == 0) && passlen1) { /* Only a ascii plaintext password was sent. */ - srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), - passlen1, STR_TERMINATE|STR_ASCII); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pass, + smb_buf(inbuf), sizeof(pass), + passlen1, STR_TERMINATE|STR_ASCII); } else { - srvstr_pull(inbuf, pass, smb_buf(inbuf), - sizeof(pass), unic ? passlen2 : passlen1, - STR_TERMINATE); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pass, + smb_buf(inbuf), sizeof(pass), + unic ? passlen2 : passlen1, + STR_TERMINATE); } plaintext_password = data_blob(pass, strlen(pass)+1); } p += passlen1 + passlen2; - p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), user, p, + sizeof(user), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), domain, p, + sizeof(domain), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_os, + p, sizeof(native_os), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), + native_lanman, p, sizeof(native_lanman), + STR_TERMINATE); /* not documented or decoded by Ethereal but there is one more string in the extra bytes which is the same as the PrimaryDomain when using @@ -1387,7 +1399,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, byte_count = SVAL(inbuf, smb_vwv13); if ( PTR_DIFF(p, save_p) < byte_count) - p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), + primary_domain, p, + sizeof(primary_domain), + STR_TERMINATE); else fstrcpy( primary_domain, "null" ); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8d4f505e09..2219ebd1c1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4530,7 +4530,8 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata, + sizeof(link_target), total_data, STR_TERMINATE); /* !widelinks forces the target path to be within the share. */ /* This means we can interpret the target as a pathname. */ @@ -6366,7 +6367,8 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* if(!lp_host_msdfs()) return ERROR_DOS(ERRDOS,ERRbadfunc); - srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2], + sizeof(pathname), total_params - 2, STR_TERMINATE); if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0) return ERROR_NT(status); -- cgit From 8724dfe55155eef0fb612e547ecf0ebaee89adf4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jul 2007 16:36:15 +0000 Subject: r23727: Explicitly pass down FLAGS2 to srvstr_get_path. Next step is to remove the bug that in the trans2 code we use the inbuf as the base pointer to decide whether we need ucs2 alignment where we need to use the beginning of the params buffer Jeremy, last one for today to reviw :-) (This used to be commit 18078b9faa3820fb34604063c9079c1ebe3ad47f) --- source3/smbd/nttrans.c | 43 ++++++++++++++++++++------- source3/smbd/reply.c | 80 ++++++++++++++++++++++++++++++++++---------------- source3/smbd/trans2.c | 32 +++++++++++++++----- 3 files changed, 111 insertions(+), 44 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 782c90cba1..8865afad0d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -562,7 +562,9 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, + smb_buf(inbuf), sizeof(fname), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -604,14 +606,18 @@ int reply_ntcreate_and_X(connection_struct *conn, dir_name_len++; } - srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), rel_fname, + smb_buf(inbuf), sizeof(rel_fname), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } pstrcat(fname, rel_fname); } else { - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, + smb_buf(inbuf), sizeof(fname), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); @@ -1011,7 +1017,9 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha flags = IVAL(params,0); - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53, + sizeof(fname), parameter_count-53, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1288,7 +1296,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, + params+53, sizeof(fname), + parameter_count-53, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1322,14 +1333,19 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o { pstring tmpname; - srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), tmpname, + params+53, sizeof(tmpname), + parameter_count-53, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } pstrcat(fname, tmpname); } } else { - srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53, + sizeof(fname), parameter_count-53, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1842,7 +1858,9 @@ int reply_ntrename(connection_struct *conn, init_smb_request(&req, (uint8 *)inbuf); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), oldname, p, + sizeof(oldname), 0, STR_TERMINATE, &status, + &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -1860,7 +1878,9 @@ int reply_ntrename(connection_struct *conn, } p++; - p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p, + sizeof(newname), 0, STR_TERMINATE, &status, + &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); @@ -2054,8 +2074,9 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o fsp = file_fsp(params, 0); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); - srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, - STR_TERMINATE, &status, &dest_has_wcard); + srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), new_name, params+4, + sizeof(new_name), parameter_count - 4, + STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ac06f2fd6d..e0442c143a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -209,8 +209,9 @@ NTSTATUS check_path_syntax_posix(char *path) Pull a string and check the path allowing a wilcard - provide for error return. ****************************************************************************/ -size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, - NTSTATUS *err, BOOL *contains_wcard) +size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest, + const char *src, size_t dest_len, size_t src_len, + int flags, NTSTATUS *err, BOOL *contains_wcard) { size_t ret; #ifdef DEVELOPER @@ -218,10 +219,10 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de #endif if (src_len == 0) { - ret = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dest, src, + ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src, dest_len, flags); } else { - ret = srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), dest, src, + ret = srvstr_pull(inbuf, smb_flags2, dest, src, dest_len, src_len, flags); } @@ -249,7 +250,9 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de Pull a string and check the path - provide for error return. ****************************************************************************/ -size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err) +size_t srvstr_get_path(char *inbuf, uint16 smb_flags2, char *dest, + const char *src, size_t dest_len, size_t src_len, + int flags, NTSTATUS *err) { size_t ret; #ifdef DEVELOPER @@ -257,14 +260,14 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len #endif if (src_len == 0) { - ret = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dest, src, + ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src, dest_len, flags); } else { - ret = srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), dest, src, + ret = srvstr_pull(inbuf, smb_flags2, dest, src, dest_len, src_len, flags); } - if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) { + if (smb_flags2 & FLAGS2_DFS_PATHNAMES) { /* * For a DFS path the function parse_dfs_path() * will do the path processing, just make a copy. @@ -681,7 +684,8 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s START_PROFILE(SMBcheckpath); - srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), name, smb_buf(inbuf) + 1, + sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcheckpath); status = map_checkpath_error(inbuf, status); @@ -768,7 +772,8 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBgetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p, + sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBgetatr); return ERROR_NT(status); @@ -854,7 +859,8 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBsetatr); p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); + p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p, + sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsetatr); return ERROR_NT(status); @@ -1016,7 +1022,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size maxentries = SVAL(inbuf,smb_vwv0); dirtype = SVAL(inbuf,smb_vwv1); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p, + sizeof(path), 0, STR_TERMINATE, &nt_status, + &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { END_PROFILE(SMBsearch); return ERROR_NT(nt_status); @@ -1221,7 +1229,9 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size outsize = set_message(inbuf,outbuf,1,0,True); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p, + sizeof(path), 0, STR_TERMINATE, &err, + &path_contains_wcard); if (!NT_STATUS_IS_OK(err)) { END_PROFILE(SMBfclose); return ERROR_NT(err); @@ -1280,7 +1290,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, deny_mode = SVAL(inbuf,smb_vwv0); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1, + sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); return ERROR_NT(status); @@ -1414,7 +1425,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf), + sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); return ERROR_NT(status); @@ -1602,7 +1614,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */ - srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1, + sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); return ERROR_NT(status); @@ -1703,7 +1716,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, init_smb_request(&req, (uint8 *)inbuf); - srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1, + sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); return ERROR_NT(status); @@ -2111,7 +2125,9 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dirtype = SVAL(inbuf,smb_vwv0); - srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard); + srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, + smb_buf(inbuf) + 1, sizeof(name), 0, + STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBunlink); return ERROR_NT(status); @@ -3834,7 +3850,9 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBmkdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, + smb_buf(inbuf) + 1, sizeof(directory), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); return ERROR_NT(status); @@ -4075,7 +4093,9 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, NTSTATUS status; START_PROFILE(SMBrmdir); - srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, + smb_buf(inbuf) + 1, sizeof(directory), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBrmdir); return ERROR_NT(status); @@ -4765,13 +4785,17 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, init_smb_request(&req, (uint8 *)inbuf); p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p, + sizeof(name), 0, STR_TERMINATE, &status, + &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); } p++; - p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p, + sizeof(newname), 0, STR_TERMINATE, &status, + &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmv); return ERROR_NT(status); @@ -4960,12 +4984,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, *directory = *mask = 0; p = smb_buf(inbuf); - p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p, + sizeof(name), 0, STR_TERMINATE, &status, + &source_has_wild); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); } - p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild); + p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p, + sizeof(newname), 0, STR_TERMINATE, &status, + &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcopy); return ERROR_NT(status); @@ -5181,7 +5209,9 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir, + smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(pathworks_setdir); return ERROR_NT(status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2219ebd1c1..15394cd863 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -804,7 +804,9 @@ static int call_trans2open(connection_struct *conn, return(ERROR_DOS(ERRSRV,ERRaccess)); } - srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, pname, + sizeof(fname), total_params - 28, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -1747,7 +1749,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); + srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), directory, + params+12, sizeof(directory), total_params - 12, + STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { return ERROR_NT(ntstatus); } @@ -2012,7 +2016,10 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu *mask = *directory = *resume_name = 0; - srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); + srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name, + params+12, sizeof(resume_name), + total_params - 12, STR_TERMINATE, &ntstatus, + &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to complain (it thinks we're asking for the directory above the shared @@ -3401,7 +3408,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6], + sizeof(fname), total_params - 6, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -4587,7 +4596,8 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata, + sizeof(oldname), total_data, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4637,7 +4647,9 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard); + srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12], + sizeof(newname), len, 0, &status, + &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -5850,7 +5862,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } info_level = SVAL(params,0); - srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6], + sizeof(fname), total_params - 6, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } @@ -6188,7 +6202,9 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status); + srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, ¶ms[4], + sizeof(directory), total_params - 4, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } -- cgit From 35d09869edf09b2af394a3eea1ee7b9ef1ba696b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Jul 2007 18:28:18 +0000 Subject: r23728: First part of bugfix for #4763. Limit notify responses to client max buf size. Jeremy. (This used to be commit 6113f56919a3cd7fd753808dbbe473603851bc3c) --- source3/smbd/notify.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 1b75916942..746a8f47e5 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,9 @@ #include "includes.h" +/* Max size we can send to client in a notify response. */ +extern int max_send; + struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ @@ -147,6 +150,15 @@ void change_notify_reply(const char *request_buf, buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; + if (buflen > max_send) { + /* + * We exceed what the client is willing to accept. Send + * nothing. + */ + change_notify_reply_packet(request_buf, NT_STATUS_OK); + goto done; + } + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; -- cgit From 6821e39e4b64301af96f74d7afd9abccca4bc2e2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 6 Jul 2007 16:39:58 +0000 Subject: r23731: Forgot one reference to inbuf (This used to be commit b02115f2ca6aca8655a4ebd1bd0adaa1e50578ce) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e0442c143a..6e41de4ec9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -228,7 +228,7 @@ size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest, *contains_wcard = False; - if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) { + if (smb_flags2 & FLAGS2_DFS_PATHNAMES) { /* * For a DFS path the function parse_dfs_path() * will do the path processing, just make a copy. -- cgit From 10c83ace04f675eb88e9686725795b0e965510e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Jul 2007 21:46:43 +0000 Subject: r23735: Second part of the bugfix for #4763 This should coalesce identical adjacent notify records - making the "too large" bug very rare indeed. Please test. Jeremy. (This used to be commit 1aaa1f5bbe9222acbe3dea1daa1c6c5ce72e1c2c) --- source3/smbd/notify.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 746a8f47e5..cbafeccd94 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -50,6 +50,17 @@ struct notify_mid_map { uint16 mid; }; +static BOOL notify_change_record_identical(struct notify_change *c1, + struct notify_change *c2) +{ + /* Note this is deliberately case sensitive. */ + if (c1->action == c2->action && + strcmp(c1->name, c2->name) == 0) { + return True; + } + return False; +} + static BOOL notify_marshall_changes(int num_changes, struct notify_change *changes, prs_struct *ps) @@ -58,11 +69,20 @@ static BOOL notify_marshall_changes(int num_changes, UNISTR uni_name; for (i=0; iname, strlen(c->name)+1, &uni_name.buffer, True); -- cgit From d3965a2689123cd4618c224a3999fdd7e76f36e0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Jul 2007 23:07:40 +0000 Subject: r23736: Use local variable of smb_flag2 instead of using the macro every time. Jeremy. (This used to be commit 9e1663b1f18d716a7f307bea2b09dadeef392ab8) --- source3/smbd/sesssetup.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3ed338bda7..e938c0bbac 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1029,6 +1029,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, user_struct *vuser = NULL; NTSTATUS status = NT_STATUS_OK; uint16 smbpid = SVAL(inbuf,smb_pid); + uint16 smb_flag2 = SVAL(inbuf, smb_flg2); DEBUG(3,("Doing spnego session setup\n")); @@ -1057,11 +1058,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, #endif p2 = inbuf + smb_vwv13 + data_blob_len; - p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_os, p2, + p2 += srvstr_pull_buf(inbuf, smb_flag2, native_os, p2, sizeof(native_os), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_lanman, p2, + p2 += srvstr_pull_buf(inbuf, smb_flag2, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), primary_domain, p2, + p2 += srvstr_pull_buf(inbuf, smb_flag2, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE); DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", native_os, native_lanman, primary_domain)); @@ -1236,6 +1237,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, static BOOL done_sesssetup = False; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; + uint16 smb_flag2 = SVAL(inbuf, smb_flg2); NTSTATUS nt_status; @@ -1249,12 +1251,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, ZERO_STRUCT(nt_resp); ZERO_STRUCT(plaintext_password); - DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2))); + DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), smb_flag2)); /* a SPNEGO session setup has 12 command words, whereas a normal NT1 session setup has 13. See the cifs spec. */ if (CVAL(inbuf, smb_wct) == 12 && - (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { + (smb_flag2 & FLAGS2_EXTENDED_SECURITY)) { if (!global_spnego_negotiated) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); @@ -1286,7 +1288,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, plaintext_password.data[passlen1] = 0; } - srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), user, + srvstr_pull_buf(inbuf, smb_flag2, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE); *domain = 0; @@ -1356,7 +1358,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, nt_resp = data_blob(p+passlen1, passlen2); } else { pstring pass; - BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS; + BOOL unic= smb_flag2 & FLAGS2_UNICODE_STRINGS; #if 0 /* This was the previous fix. Not sure if it's still valid. JRA. */ @@ -1368,11 +1370,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (unic && (passlen2 == 0) && passlen1) { /* Only a ascii plaintext password was sent. */ - srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pass, + srvstr_pull(inbuf, smb_flag2, pass, smb_buf(inbuf), sizeof(pass), passlen1, STR_TERMINATE|STR_ASCII); } else { - srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pass, + srvstr_pull(inbuf, smb_flag2, pass, smb_buf(inbuf), sizeof(pass), unic ? passlen2 : passlen1, STR_TERMINATE); @@ -1381,13 +1383,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } p += passlen1 + passlen2; - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), user, p, + p += srvstr_pull_buf(inbuf, smb_flag2, user, p, sizeof(user), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), domain, p, + p += srvstr_pull_buf(inbuf, smb_flag2, domain, p, sizeof(domain), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_os, + p += srvstr_pull_buf(inbuf, smb_flag2, native_os, p, sizeof(native_os), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), + p += srvstr_pull_buf(inbuf, smb_flag2, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); @@ -1399,7 +1401,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, byte_count = SVAL(inbuf, smb_vwv13); if ( PTR_DIFF(p, save_p) < byte_count) - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), + p += srvstr_pull_buf(inbuf, smb_flag2, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); -- cgit From 0e43c1e80d463e144fe6f08384b208003cd4f424 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 7 Jul 2007 08:46:26 +0000 Subject: r23738: Re-add commented out code snipped that got lost by accident (This used to be commit c38c31afb770350e47713bf1025c23fd774607ab) --- source3/smbd/nttrans.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8865afad0d..5760cb75a4 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1413,6 +1413,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } +#if 0 + /* We need to support SeSecurityPrivilege for this. */ + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY)) && + !user_has_privileges(current_user.nt_user_token, + &se_security)) { + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); + } +#endif + if (ea_len) { pdata = data + sd_len; -- cgit From c35d814e393e4211e3f6e0dcaff76536c256ff6b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 7 Jul 2007 09:57:27 +0000 Subject: r23743: Simplify stat_cache_lookup() logic. For the history of this, see http://article.gmane.org/gmane.network.samba.internals/32486. (This used to be commit e5e42fe3d5b26c0ec48d98c001b9cb1623c0b5a7) --- source3/smbd/statcache.c | 144 +++++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 68 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index b63dd165a7..92c845ce2e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -165,6 +165,9 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, size_t namelen; BOOL sizechanged = False; unsigned int num_components = 0; + char *translated_path; + size_t translated_path_length; + TDB_DATA data_val; if (!lp_stat_cache()) return False; @@ -207,82 +210,87 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } while (1) { - TDB_DATA data_val; char *sp; data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name); - if(data_val.dptr == NULL || data_val.dsize == 0) { - DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); + + if (data_val.dptr != NULL && data_val.dsize != 0) { + break; + } + + DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); + /* + * Didn't find it - remove last component for next try. + */ + if (!(sp = strrchr_m(chk_name, '/'))) { /* - * Didn't find it - remove last component for next try. + * We reached the end of the name - no match. */ - sp = strrchr_m(chk_name, '/'); - if (sp) { - *sp = '\0'; - /* - * Count the number of times we have done this, - * we'll need it when reconstructing the string. - */ - if (sizechanged) - num_components++; - - } else { - /* - * We reached the end of the name - no match. - */ - DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); - return False; - } - if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) - || (strcmp(chk_name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); - return False; - } - } else { - BOOL retval; - char *translated_path = (char *)data_val.dptr; - size_t translated_path_length = data_val.dsize - 1; - - DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path )); - DO_PROFILE_INC(statcache_hits); - if(SMB_VFS_STAT(conn,translated_path, pst) != 0) { - /* Discard this entry - it doesn't exist in the filesystem. */ - tdb_delete_bystring(tdb_stat_cache, chk_name); - SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); - return False; - } - - if (!sizechanged) { - memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length)); - } else if (num_components == 0) { - pstrcpy(name, translated_path); - } else { - sp = strnrchr_m(name, '/', num_components); - if (sp) { - pstring last_component; - pstrcpy(last_component, sp); - pstrcpy(name, translated_path); - pstrcat(name, last_component); - } else { - pstrcpy(name, translated_path); - } - } - - /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[translated_path_length]; - if(**start == '/') - ++*start; - - pstrcpy(dirpath, translated_path); - retval = (namelen == translated_path_length) ? True : False; + DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); + return False; + } + + *sp = '\0'; + + /* + * Count the number of times we have done this, we'll + * need it when reconstructing the string. + */ + if (sizechanged) + num_components++; + + if ((*chk_name == '\0') + || ISDOT(chk_name) || ISDOTDOT(chk_name)) { + DO_PROFILE_INC(statcache_misses); SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); - return retval; + return False; + } + } + + translated_path = (char *)data_val.dptr; + translated_path_length = data_val.dsize - 1; + + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " + "-> [%s]\n", chk_name, translated_path )); + DO_PROFILE_INC(statcache_hits); + + if (SMB_VFS_STAT(conn, translated_path, pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + tdb_delete_bystring(tdb_stat_cache, chk_name); + SAFE_FREE(chk_name); + SAFE_FREE(data_val.dptr); + return False; + } + + if (!sizechanged) { + memcpy(name, translated_path, + MIN(sizeof(pstring)-1, translated_path_length)); + } else if (num_components == 0) { + pstrcpy(name, translated_path); + } else { + char *sp; + + sp = strnrchr_m(name, '/', num_components); + if (sp) { + pstring last_component; + pstrcpy(last_component, sp); + pstrcpy(name, translated_path); + pstrcat(name, last_component); + } else { + pstrcpy(name, translated_path); } } + + /* set pointer for 'where to start' on fixing the rest of the name */ + *start = &name[translated_path_length]; + if (**start == '/') + ++*start; + + pstrcpy(dirpath, translated_path); + SAFE_FREE(chk_name); + SAFE_FREE(data_val.dptr); + return (namelen == translated_path_length); } /*************************************************************************** -- cgit From 59590a1c4dc9bebc0e3a4ff6b0db9beb6ea81fef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 00:48:07 +0000 Subject: r23752: Fix bug introduced by checkin 22920, allow large readX. Fix from Dmitry Shatrov . "In send_file_readX(), if startpos > sbuf.st_size, then smb_maxcnt is set to an invalid large value due to integer overflow. As for me, this resulted in MS Word hanging while trying to save a 1.5Mb document." This isn't in shipping code. Jeremy. (This used to be commit af715c602a8ef6038e6272c7cc6a08501617ae67) --- source3/smbd/reply.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6e41de4ec9..b17fa1949b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2590,9 +2590,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length if (startpos > sbuf.st_size) { smb_maxcnt = 0; - } - - if (smb_maxcnt > (sbuf.st_size - startpos)) { + } else if (smb_maxcnt > (sbuf.st_size - startpos)) { smb_maxcnt = (sbuf.st_size - startpos); } -- cgit From ead70dc92e16a79cd7767dbc9f727bc530925abd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 09:43:41 +0000 Subject: r23761: Rename reduce_name to check_reduced_name The function name reduce_name is misleading, making the user believe it changes an argument. (This used to be commit 68234f0bc6fb4d6d99ae94ff067db118c60804aa) --- source3/smbd/filename.c | 4 ++-- source3/smbd/nttrans.c | 2 +- source3/smbd/trans2.c | 2 +- source3/smbd/vfs.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index c26eba2ded..de15d923b8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -512,7 +512,7 @@ NTSTATUS unix_convert(connection_struct *conn, } /**************************************************************************** - Check a filename - possibly caling reducename. + Check a filename - possibly calling check_reduced_name. This is called by every routine before it allows an operation on a filename. It does any final confirmation necessary to ensure that the filename is a valid one for the user to access. @@ -529,7 +529,7 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) } if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { - NTSTATUS status = reduce_name(conn,name); + NTSTATUS status = check_reduced_name(conn,name); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status))); return status; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5760cb75a4..f4508d07f1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1777,7 +1777,7 @@ static NTSTATUS copy_internals(connection_struct *conn, } /* Ensure this is within the share. */ - status = reduce_name(conn, oldname); + status = check_reduced_name(conn, oldname); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 15394cd863..005983f133 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4177,7 +4177,7 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne } /* Ensure this is within the share. */ - status = reduce_name(conn, oldname); + status = check_reduced_name(conn, oldname); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2fd448061e..b854c36a7b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -802,7 +802,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) it is below dir in the heirachy. This uses realpath. ********************************************************************/ -NTSTATUS reduce_name(connection_struct *conn, const pstring fname) +NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) { #ifdef REALPATH_TAKES_NULL BOOL free_resolved_name = True; -- cgit From a3f69f3710edfca08fce2f8b03ffcd7147edef85 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 13:04:44 +0000 Subject: r23764: Do restore_case_semantics in an error path. Jeremy, please check! (This used to be commit 3b5422c9a401321788d824c68da31a39d85aece1) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f4508d07f1..17d71117ed 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -731,6 +731,7 @@ int reply_ntcreate_and_X(connection_struct *conn, /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } -- cgit From c13f62a6753e9cb9b19408752566495e11f329f5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 13:24:31 +0000 Subject: r23765: Another error-path restore_case_semantics(). (This used to be commit a3e5fe1693a3e1830561d60254d6a3bfc0c30686) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 17d71117ed..6681ce7de3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1377,6 +1377,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); if (!NT_STATUS_IS_OK(status)) { + restore_case_semantics(conn, file_attributes); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); } -- cgit From 5daa21f558217d727e4f1d42b778e1beea69af4c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 14:43:36 +0000 Subject: r23768: Get rid of the three global variables for the case semantics. I think this is really not worth globals. Jeremy, please check for 3.0.26. (This used to be commit 6e655500c05f2584094329a95ad5791160147fd9) --- source3/smbd/nttrans.c | 134 ++++++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 6681ce7de3..ef5f299c43 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -275,49 +275,49 @@ BOOL is_ntfs_stream_name(const char *fname) return (strchr_m(fname, ':') != NULL) ? True : False; } +struct case_semantics_state { + connection_struct *conn; + BOOL case_sensitive; + BOOL case_preserve; + BOOL short_case_preserve; +}; + /**************************************************************************** - Save case statics. + Restore case semantics. ****************************************************************************/ - -static BOOL saved_case_sensitive; -static BOOL saved_case_preserve; -static BOOL saved_short_case_preserve; +static int restore_case_semantics(struct case_semantics_state *state) +{ + state->conn->case_sensitive = state->case_sensitive; + state->conn->case_preserve = state->case_preserve; + state->conn->short_case_preserve = state->short_case_preserve; + return 0; +} /**************************************************************************** Save case semantics. ****************************************************************************/ - -static uint32 set_posix_case_semantics(connection_struct *conn, uint32 file_attributes) +static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx, + connection_struct *conn) { - if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { - return file_attributes; + struct case_semantics_state *result; + + if (!(result = talloc(mem_ctx, struct case_semantics_state))) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - saved_case_sensitive = conn->case_sensitive; - saved_case_preserve = conn->case_preserve; - saved_short_case_preserve = conn->short_case_preserve; + result->case_sensitive = conn->case_sensitive; + result->case_preserve = conn->case_preserve; + result->short_case_preserve = conn->short_case_preserve; /* Set to POSIX. */ conn->case_sensitive = True; conn->case_preserve = True; conn->short_case_preserve = True; - return (file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); -} + talloc_set_destructor(result, restore_case_semantics); -/**************************************************************************** - Restore case semantics. -****************************************************************************/ - -static void restore_case_semantics(connection_struct *conn, uint32 file_attributes) -{ - if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { - return; - } - - conn->case_sensitive = saved_case_sensitive; - conn->case_preserve = saved_case_preserve; - conn->short_case_preserve = saved_short_case_preserve; + return result; } /**************************************************************************** @@ -487,7 +487,6 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); - uint32 new_file_attributes; uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); @@ -507,6 +506,7 @@ int reply_ntcreate_and_X(connection_struct *conn, BOOL extended_oplock_granted = False; NTSTATUS status; struct smb_request req; + struct case_semantics_state *case_state = NULL; START_PROFILE(SMBntcreateX); @@ -676,18 +676,21 @@ int reply_ntcreate_and_X(connection_struct *conn, * Check if POSIX semantics are wanted. */ - new_file_attributes = set_posix_case_semantics(conn, file_attributes); + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + case_state = set_posix_case_semantics(NULL, conn); + file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; + } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); return ERROR_NT(status); } /* All file access must go through check_name() */ status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); return ERROR_NT(status); } @@ -706,7 +709,7 @@ int reply_ntcreate_and_X(connection_struct *conn, && (access_mask & DELETE_ACCESS)) { if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || !can_delete_file_in_directory(conn, fname)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_ACCESS_DENIED); } @@ -714,10 +717,10 @@ int reply_ntcreate_and_X(connection_struct *conn, #if 0 /* We need to support SeSecurityPrivilege for this. */ - if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY)) && + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && !user_has_privileges(current_user.nt_user_token, &se_security)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); } @@ -731,7 +734,7 @@ int reply_ntcreate_and_X(connection_struct *conn, /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -742,10 +745,10 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, create_disposition, create_options, - new_file_attributes, + file_attributes, &info, &fsp); - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); if(!NT_STATUS_IS_OK(status)) { if (!use_nt_status() && NT_STATUS_EQUAL( @@ -780,7 +783,7 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, create_disposition, create_options, - new_file_attributes, + file_attributes, oplock_request, &info, &fsp); @@ -812,7 +815,7 @@ int reply_ntcreate_and_X(connection_struct *conn, */ if (create_options & FILE_NON_DIRECTORY_FILE) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } @@ -824,11 +827,11 @@ int reply_ntcreate_and_X(connection_struct *conn, share_access, create_disposition, create_options, - new_file_attributes, + file_attributes, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); if (!use_nt_status() && NT_STATUS_EQUAL( status, NT_STATUS_OBJECT_NAME_COLLISION)) { status = NT_STATUS_DOS(ERRDOS, ERRfilexists); @@ -837,7 +840,7 @@ int reply_ntcreate_and_X(connection_struct *conn, return ERROR_NT(status); } } else { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ @@ -848,7 +851,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } } - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); @@ -1198,7 +1201,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o uint32 flags; uint32 access_mask; uint32 file_attributes; - uint32 new_file_attributes; uint32 share_access; uint32 create_disposition; uint32 create_options; @@ -1214,6 +1216,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o NTSTATUS status; size_t param_len; struct smb_request req; + struct case_semantics_state *case_state = NULL; DEBUG(5,("call_nt_transact_create\n")); @@ -1372,12 +1375,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* * Check if POSIX semantics are wanted. */ + + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + case_state = set_posix_case_semantics(NULL, conn); + file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; + } - new_file_attributes = set_posix_case_semantics(conn, file_attributes); - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); if (!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); } @@ -1386,13 +1392,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(status); } /* All file access must go through check_name() */ status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(status); } @@ -1410,17 +1416,17 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o && (access_mask & DELETE_ACCESS)) { if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || !can_delete_file_in_directory(conn, fname)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(NT_STATUS_ACCESS_DENIED); } } #if 0 /* We need to support SeSecurityPrivilege for this. */ - if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY)) && + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && !user_has_privileges(current_user.nt_user_token, &se_security)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); } #endif @@ -1432,7 +1438,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata, ea_len); if (!ea_list ) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } @@ -1445,7 +1451,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1461,10 +1467,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o share_access, create_disposition, create_options, - new_file_attributes, + file_attributes, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(status); } @@ -1479,7 +1485,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o share_access, create_disposition, create_options, - new_file_attributes, + file_attributes, oplock_request, &info, &fsp); @@ -1492,7 +1498,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ if (create_options & FILE_NON_DIRECTORY_FILE) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } @@ -1503,14 +1509,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o share_access, create_disposition, create_options, - new_file_attributes, + file_attributes, &info, &fsp); if(!NT_STATUS_IS_OK(status)) { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(status); } } else { - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; @@ -1542,7 +1548,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); close_file(fsp,ERROR_CLOSE); - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(status); } fsp->access_mask = saved_access_mask; @@ -1552,12 +1558,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o status = set_ea(conn, fsp, fname, ea_list); if (!NT_STATUS_IS_OK(status)) { close_file(fsp,ERROR_CLOSE); - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); return ERROR_NT(status); } } - restore_case_semantics(conn, file_attributes); + TALLOC_FREE(case_state); file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); -- cgit From f850ba5787b893fcf0e25cfa52affb93eb0c5afc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 9 Jul 2007 16:27:13 +0000 Subject: r23773: One pstring a day... (This used to be commit 0c3016d32b5277b901788b13aa7d3f4b647728f2) --- source3/smbd/fileio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 1227d12b08..946d57da7e 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -780,9 +780,11 @@ void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) if(fsp->wcp) { /* The cache *must* have been flushed before we do this. */ if (fsp->wcp->data_size != 0) { - pstring msg; - slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \ -on file %s with write cache size = %lu\n", fsp->fsp_name, (unsigned long)fsp->wcp->data_size ); + char *msg; + asprintf(&msg, "set_filelen_write_cache: size change " + "on file %s with write cache size = %lu\n", + fsp->fsp_name, + (unsigned long)fsp->wcp->data_size); smb_panic(msg); } fsp->wcp->file_size = file_size; -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/aio.c | 2 +- source3/smbd/blocking.c | 2 +- source3/smbd/change_trust_pw.c | 2 +- source3/smbd/chgpasswd.c | 2 +- source3/smbd/close.c | 2 +- source3/smbd/conn.c | 2 +- source3/smbd/connection.c | 2 +- source3/smbd/dfree.c | 2 +- source3/smbd/dir.c | 2 +- source3/smbd/dmapi.c | 2 +- source3/smbd/dosmode.c | 2 +- source3/smbd/error.c | 2 +- source3/smbd/fake_file.c | 2 +- source3/smbd/fileio.c | 2 +- source3/smbd/filename.c | 2 +- source3/smbd/files.c | 2 +- source3/smbd/ipc.c | 2 +- source3/smbd/lanman.c | 2 +- source3/smbd/mangle.c | 2 +- source3/smbd/mangle_hash.c | 2 +- source3/smbd/mangle_hash2.c | 2 +- source3/smbd/mangle_map.c | 2 +- source3/smbd/map_username.c | 2 +- source3/smbd/message.c | 2 +- source3/smbd/msdfs.c | 2 +- source3/smbd/negprot.c | 2 +- source3/smbd/noquotas.c | 2 +- source3/smbd/notify.c | 2 +- source3/smbd/notify_inotify.c | 2 +- source3/smbd/notify_internal.c | 2 +- source3/smbd/ntquotas.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/open.c | 2 +- source3/smbd/oplock.c | 2 +- source3/smbd/oplock_irix.c | 2 +- source3/smbd/oplock_linux.c | 2 +- source3/smbd/password.c | 2 +- source3/smbd/pipes.c | 2 +- source3/smbd/posix_acls.c | 2 +- source3/smbd/process.c | 2 +- source3/smbd/quotas.c | 2 +- source3/smbd/reply.c | 2 +- source3/smbd/seal.c | 2 +- source3/smbd/sec_ctx.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/service.c | 2 +- source3/smbd/session.c | 2 +- source3/smbd/sesssetup.c | 2 +- source3/smbd/share_access.c | 2 +- source3/smbd/sockinit.c | 2 +- source3/smbd/srvstr.c | 2 +- source3/smbd/statcache.c | 2 +- source3/smbd/statvfs.c | 2 +- source3/smbd/trans2.c | 2 +- source3/smbd/uid.c | 2 +- source3/smbd/utmp.c | 2 +- source3/smbd/vfs.c | 2 +- 57 files changed, 57 insertions(+), 57 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index f747cf5c06..7a91306fb2 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 924b99b113..7fafdcf887 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 31f03cc7fa..99dbebf47b 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -9,7 +9,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 1227163c22..bf634b5a67 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c4aa2e2e28..c2267f9b3d 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index da55c0a645..9e322ab1cc 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 211f0e6acb..9223cce3d2 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index c488add227..5eca7a85ab 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index e7baf2b759..074fe6aed6 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index c433a7329e..1ad1bc3d1c 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 71d4fa179d..9efd691682 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/error.c b/source3/smbd/error.c index dc35c0fa64..9c858c40a2 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 5333742ba8..17617ce443 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 946d57da7e..df9f4a8c3b 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index de15d923b8..b7470aa902 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 9994b50d15..4ed3661920 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ce26b53e1b..ed617dc399 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -8,7 +8,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0a9a529a85..5e0cdf09fc 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -9,7 +9,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 16f99636eb..9625136cfe 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 3cc7d1e5c2..3e188bb591 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index a39f49ec79..70b0d86f10 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c index c5803786ec..052311e0c4 100644 --- a/source3/smbd/mangle_map.c +++ b/source3/smbd/mangle_map.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index 7cbde3c59e..78a37ea143 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/message.c b/source3/smbd/message.c index f390e539b0..22fb593b11 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a3de199116..01c29ce6a2 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 3fdae1e06b..7256e2da6d 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/noquotas.c b/source3/smbd/noquotas.c index 85caef57e1..02172a31e0 100644 --- a/source3/smbd/noquotas.c +++ b/source3/smbd/noquotas.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index cbafeccd94..eecf9fa57c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 1b1bad7e96..859f0c2935 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 20bfb74a29..2d2178ba6b 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index df851a2ca8..240dceddde 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ef5f299c43..29a65a2dda 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5cb8340e0e..948f475fda 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 39fc847d6f..0945475623 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index eb0164ae50..9cf387da6e 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index e12a9d66ca..5fe3668aec 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 00f687dc27..f9654ce3a4 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 1da2f0c22f..9392d7b2fc 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -8,7 +8,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 947c30fb4a..49ca5b86b7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1cb2c27fd3..595c524137 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index feb28e2c74..19c103f2ba 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b17fa1949b..73fe08f589 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 5d8ef9b63c..b816af1e00 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 97842419d5..1ba3d3721d 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/server.c b/source3/smbd/server.c index edbd879847..5f19f865be 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -8,7 +8,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2b84223695..007b99d79c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 6b1bb0cbee..62fa10f591 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -8,7 +8,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e938c0bbac..4ec7d5f03a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -8,7 +8,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index b12d543f5a..beca6414ae 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/sockinit.c b/source3/smbd/sockinit.c index 9d46776f89..8fd76f84b7 100644 --- a/source3/smbd/sockinit.c +++ b/source3/smbd/sockinit.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 409fd30a67..21474c5c3c 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 92c845ce2e..17fda8163d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/statvfs.c b/source3/smbd/statvfs.c index 300b14a7c0..d836930daf 100644 --- a/source3/smbd/statvfs.c +++ b/source3/smbd/statvfs.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 005983f133..5fa26ca1f7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -11,7 +11,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c6d4e3329c..bf23680b54 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index b1735dfcc4..cc2db2a4a8 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -6,7 +6,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b854c36a7b..91b6396d92 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -8,7 +8,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From df2465298b2ca9cca92fadf69536dc77ade9fdb3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:47:40 +0000 Subject: r23783: Processing the UAS change message was causing problems on ppc64 Linux systems. Rather than trying to fix this, it's much better just to remove the code, as it serves no purpose at all (the message that is generated is ignored by smbd). This sort of parsing should really be done by PIDL generated code. (This used to be commit 22e8404cef4961f7468a9f24e23024c827233b84) --- source3/smbd/server.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 5f19f865be..61e79b75cc 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -166,27 +166,6 @@ static void msg_sam_sync(struct messaging_context *msg, DEBUG(10, ("** sam sync message received, ignoring\n")); } -/**************************************************************************** - Process a sam sync replicate message - not sure whether to do this here or - somewhere else. -****************************************************************************/ - -static void msg_sam_repl(struct messaging_context *msg, - void *private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB *data) -{ - uint32 low_serial; - - if (data->length != sizeof(low_serial)) - return; - - low_serial = *((uint32 *)data->data); - - DEBUG(3, ("received sam replication message, serial = 0x%04x\n", - low_serial)); -} /**************************************************************************** Open the socket communication - inetd. @@ -375,8 +354,6 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ messaging_register(smbd_messaging_context(), NULL, MSG_SMB_SAM_SYNC, msg_sam_sync); - messaging_register(smbd_messaging_context(), NULL, - MSG_SMB_SAM_REPL, msg_sam_repl); messaging_register(smbd_messaging_context(), NULL, MSG_SHUTDOWN, msg_exit_server); messaging_register(smbd_messaging_context(), NULL, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/aio.c | 3 +-- source3/smbd/blocking.c | 3 +-- source3/smbd/chgpasswd.c | 3 +-- source3/smbd/close.c | 3 +-- source3/smbd/conn.c | 3 +-- source3/smbd/connection.c | 3 +-- source3/smbd/dfree.c | 3 +-- source3/smbd/dir.c | 3 +-- source3/smbd/dmapi.c | 3 +-- source3/smbd/dosmode.c | 3 +-- source3/smbd/error.c | 3 +-- source3/smbd/fake_file.c | 3 +-- source3/smbd/fileio.c | 3 +-- source3/smbd/filename.c | 3 +-- source3/smbd/files.c | 3 +-- source3/smbd/ipc.c | 3 +-- source3/smbd/lanman.c | 3 +-- source3/smbd/mangle.c | 3 +-- source3/smbd/mangle_hash.c | 3 +-- source3/smbd/mangle_hash2.c | 3 +-- source3/smbd/mangle_map.c | 3 +-- source3/smbd/map_username.c | 3 +-- source3/smbd/message.c | 3 +-- source3/smbd/msdfs.c | 3 +-- source3/smbd/negprot.c | 3 +-- source3/smbd/noquotas.c | 3 +-- source3/smbd/notify.c | 3 +-- source3/smbd/notify_inotify.c | 3 +-- source3/smbd/notify_internal.c | 3 +-- source3/smbd/ntquotas.c | 3 +-- source3/smbd/nttrans.c | 3 +-- source3/smbd/open.c | 3 +-- source3/smbd/oplock.c | 3 +-- source3/smbd/oplock_irix.c | 3 +-- source3/smbd/oplock_linux.c | 3 +-- source3/smbd/password.c | 3 +-- source3/smbd/pipes.c | 3 +-- source3/smbd/posix_acls.c | 3 +-- source3/smbd/process.c | 3 +-- source3/smbd/quotas.c | 3 +-- source3/smbd/reply.c | 3 +-- source3/smbd/seal.c | 3 +-- source3/smbd/sec_ctx.c | 3 +-- source3/smbd/server.c | 3 +-- source3/smbd/service.c | 3 +-- source3/smbd/session.c | 3 +-- source3/smbd/sesssetup.c | 3 +-- source3/smbd/share_access.c | 3 +-- source3/smbd/sockinit.c | 3 +-- source3/smbd/srvstr.c | 3 +-- source3/smbd/statcache.c | 3 +-- source3/smbd/statvfs.c | 3 +-- source3/smbd/trans2.c | 3 +-- source3/smbd/uid.c | 3 +-- source3/smbd/utmp.c | 3 +-- source3/smbd/vfs.c | 3 +-- 56 files changed, 56 insertions(+), 112 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 7a91306fb2..afef36f61e 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 7fafdcf887..ed1977e3be 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index bf634b5a67..242f0e0753 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ /* These comments regard the code to change the user's unix password: */ diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c2267f9b3d..dedf935501 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 9e322ab1cc..f9befb84d2 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 9223cce3d2..da8bd89e7a 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 5eca7a85ab..2290558f0a 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 074fe6aed6..30c1d77a84 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 1ad1bc3d1c..127d1627cf 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 9efd691682..b4ab0ca226 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 9c858c40a2..12b57d5ab4 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 17617ce443..e4f71193e1 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index df9f4a8c3b..e797dbda14 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b7470aa902..737ed5a89c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ /* diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4ed3661920..02e4cd9663 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ed617dc399..c2b780ae74 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -17,8 +17,7 @@ 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. + along with this program. If not, see . */ /* This file handles the named pipe and mailslot calls diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 5e0cdf09fc..a7fe07b314 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -18,8 +18,7 @@ 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. + along with this program. If not, see . */ /* This file handles the named pipe and mailslot calls diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 9625136cfe..d7f2eb8db2 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 3e188bb591..4c02d9685f 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 70b0d86f10..299d7c99fa 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ /* diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c index 052311e0c4..81de125248 100644 --- a/source3/smbd/mangle_map.c +++ b/source3/smbd/mangle_map.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index 78a37ea143..38881b3b2d 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 22fb593b11..fa4c9e69ef 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ /* This file handles the messaging system calls for winpopup style diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 01c29ce6a2..d4c08848d7 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 7256e2da6d..4a9492a766 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/noquotas.c b/source3/smbd/noquotas.c index 02172a31e0..0c23bb6f06 100644 --- a/source3/smbd/noquotas.c +++ b/source3/smbd/noquotas.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index eecf9fa57c..6ab4266c19 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 859f0c2935..f332e4b3d2 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ /* diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 2d2178ba6b..48ca572a25 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ /* diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 240dceddde..4fbf0384a4 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 29a65a2dda..56eef9b4e2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 948f475fda..432f6b808a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 0945475623..e552cb545e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #define DBGC_CLASS DBGC_LOCKING diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 9cf387da6e..6f2dceeddc 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #define DBGC_CLASS DBGC_LOCKING diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 5fe3668aec..66ed900015 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #define DBGC_CLASS DBGC_LOCKING diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f9654ce3a4..1a7dc33c61 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 9392d7b2fc..1ea3e052b2 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -17,8 +17,7 @@ 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. + along with this program. If not, see . */ /* This file handles reply_ calls on named pipes that the server diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 49ca5b86b7..87b456a2f7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 595c524137..0e39614f58 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 19c103f2ba..271f3b5d96 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 73fe08f589..9a2dc19fa1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ /* This file handles most of the reply_ calls that the server diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index b816af1e00..0276e34002 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 1ba3d3721d..67b15dc014 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 61e79b75cc..c09a0d7b98 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -17,8 +17,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 007b99d79c..aeb0e0f31d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 62fa10f591..3cc93c1a7f 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -17,8 +17,7 @@ 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. + along with this program. If not, see . */ /* a "session" is claimed when we do a SessionSetupX operation diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 4ec7d5f03a..320d283575 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -17,8 +17,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index beca6414ae..a5e0988b0f 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/sockinit.c b/source3/smbd/sockinit.c index 8fd76f84b7..c526a181d3 100644 --- a/source3/smbd/sockinit.c +++ b/source3/smbd/sockinit.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 21474c5c3c..4462a423c8 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 17fda8163d..51e8c0417a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/statvfs.c b/source3/smbd/statvfs.c index d836930daf..f6663208ea 100644 --- a/source3/smbd/statvfs.c +++ b/source3/smbd/statvfs.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5fa26ca1f7..8711f988a8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -20,8 +20,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index bf23680b54..d1837c41dc 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index cc2db2a4a8..eb2152dac2 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -15,8 +15,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 91b6396d92..f9a5ba5ed6 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -17,8 +17,7 @@ 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. + along with this program. If not, see . This work was sponsored by Optifacio Software Services, Inc. */ -- cgit From ef591178d08089494f45ab49870a7aaa4f12bed1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 01:15:57 +0000 Subject: r23786: Use linux/dqblk_xfs.h rather than a private copy of this header in the Samba3 tree. This is neater, plus it avoids the need to get legal approval from SGI to use their GPLv2-only code under GPLv3. If/when SGI legal sort things out, we could consider adding back this header for very old systems where linux/dqblk_xfs.h is not available. (This used to be commit cb435543f84955be75368a3294bc6b627414d876) --- source3/smbd/quotas.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 271f3b5d96..1f30acef33 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -61,7 +61,6 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B */ #include "samba_linux_quota.h" -#include "samba_xfs_quota.h" typedef struct _LINUX_SMB_DISK_QUOTA { SMB_BIG_UINT bsize; @@ -73,6 +72,10 @@ typedef struct _LINUX_SMB_DISK_QUOTA { SMB_BIG_UINT curinodes; /* Current used inodes. */ } LINUX_SMB_DISK_QUOTA; + +#ifdef HAVE_LINUX_DQBLK_XFS_H +#include + /**************************************************************************** Abstract out the XFS Quota Manager quota get call. ****************************************************************************/ @@ -102,6 +105,15 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LI return ret; } +#else +static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) +{ + DEBUG(0,("XFS quota support not available\n")); + errno = ENOSYS; + return -1; +} +#endif + /**************************************************************************** Abstract out the old and new Linux quota get calls. -- cgit From 153cfb9c83534b09f15cc16205d7adb19b394928 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 05:23:25 +0000 Subject: r23801: The FSF has moved around a lot. This fixes their Mass Ave address. (This used to be commit 87c91e4362c51819032bfbebbb273c52e203b227) --- source3/smbd/change_trust_pw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 99dbebf47b..eb26e56ac5 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -18,8 +18,7 @@ * 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. + * along with this program; if not, see . */ #include "includes.h" -- cgit From fa919f24f082dbcc7e5f88d69273eba4f72e8806 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 10 Jul 2007 12:22:44 +0000 Subject: r23813: Remove unused global variable (This used to be commit 3b811134c02ff9b24d3e36c1ff94b32946c6183c) --- source3/smbd/process.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0e39614f58..e6bafa8dc3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -20,7 +20,6 @@ #include "includes.h" -uint16 global_smbpid; extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; @@ -918,10 +917,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(-1); } - /* yuck! this is an interim measure before we get rid of our - current inbuf/outbuf system */ - global_smbpid = SVAL(inbuf,smb_pid); - if (smb_messages[type].fn == NULL) { DEBUG(0,("Unknown message type %d!\n",type)); smb_dump("Unknown", 1, inbuf, size); -- cgit From 0ff8556f8b9e641c6e9e06857d72f4cd28a186fb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 11 Jul 2007 06:18:32 +0000 Subject: r23823: Memory leak fix from Atsushi Nakabayashi Thanks! Volker (This used to be commit 17b875ae5bab9473f0f896e63fff4a65588c2fb8) --- source3/smbd/ipc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c2b780ae74..769147926f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -603,6 +603,8 @@ int reply_trans(connection_struct *conn, DEBUG(0,("reply_trans: setup malloc fail for %u " "bytes !\n", (unsigned int) (state->setup_count * sizeof(uint16)))); + SAFE_FREE(state->data); + SAFE_FREE(state->param); TALLOC_FREE(state); END_PROFILE(SMBtrans); return(ERROR_DOS(ERRDOS,ERRnomem)); -- cgit From 188b84f9d07ec33f8780ea5494d5892568cdbfe8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2007 21:01:06 +0000 Subject: r23843: Fix bug #4777, reported by Bill Marshall . Doing a DFS traverse through a deep link could fail (not using explorer). Jeremy. (This used to be commit cd93f0cb00207098014e41e0ba16210cb150b895) --- source3/smbd/msdfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index d4c08848d7..a89f4ceffc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -389,7 +389,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, pstrcpy(localpath, pdp->reqpath); status = unix_convert(conn, localpath, search_flag, NULL, &sbuf); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_PATH_NOT_FOUND)) { return status; } -- cgit From f01698027d15ca546d9a92c799d0cad18a625789 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2007 22:39:11 +0000 Subject: r23844: Add patch series from Volker (after review and consultation). 0001-Save-a-strdup-in-stat_cache_add.patch 0002-Use-ISDOT-and-ISDOTDOT.patch 0003-Move-fname_equal-around.patch 0004-unix_convert-pstring-dirpath-char.patch 0005-Ignore-.o-files.patch 0006-Get-rid-of-pstrings-inside-unix_convert.patch 0007-revert-pstring-unix_convert.patch 0008-Make-name-an-allocated-pstring-inside-unix_convert.patch 0009-Pass-explicit-pstring-to-mangle_check_cache.patch 0010-Don-t-overwrite-orig_path-unnecessarily.patch 0011-Defer-allocating-name.patch 0012-Make-sure-dirpath-is-always-correctly-allocated.patch 0013-Remove-one-pstring-dependency-in-unix_convert.patch 0014-Remove-more-name-pstring-dependencies.patch 0015-Hide-the-nasty-API-of-mangle_check_cache-in-mangle_c.patch 0016-name-does-not-need-to-be-pstring-size-anymore.patch 0017-Make-use-of-ISDOT-and-ISDOTDOT.patch 0018-Remove-pstring-from-stat_cache_lookup.patch 0019-Add-my-copyright.patch To remove pstrings from statcache and unix_convert. Jeremy. (This used to be commit ea6ef368891af24164d2e76700c405a82b3dfc19) --- source3/smbd/filename.c | 306 ++++++++++++++++++++++++++++++++--------------- source3/smbd/mangle.c | 15 +++ source3/smbd/statcache.c | 84 ++++++++----- 3 files changed, 273 insertions(+), 132 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 737ed5a89c..fd7727c594 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Ying Chen 2000 + Copyright (C) Volker Lendecke 2007 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 @@ -25,21 +26,8 @@ #include "includes.h" -static BOOL scan_directory(connection_struct *conn, const char *path, char *name,size_t maxlength); - -/**************************************************************************** - Check if two filenames are equal. - This needs to be careful about whether we are case sensitive. -****************************************************************************/ - -static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) -{ - /* Normal filename handling */ - if (case_sensitive) - return(strcmp(name1,name2) == 0); - - return(strequal(name1,name2)); -} +static BOOL scan_directory(connection_struct *conn, const char *path, + char *name, char **found_name); /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. @@ -117,22 +105,21 @@ for nlinks = 0, which can never be true for any file). ****************************************************************************/ NTSTATUS unix_convert(connection_struct *conn, - pstring name, + pstring orig_path, BOOL allow_wcard_last_component, - char *saved_last_component, + char *saved_last_component, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; - pstring dirpath; - pstring orig_path; + char *dirpath = NULL; + char *name = NULL; BOOL component_was_mangled = False; BOOL name_has_wildcard = False; + NTSTATUS result; SET_STAT_INVALID(*pst); - *dirpath = 0; - if(saved_last_component) { *saved_last_component = 0; } @@ -143,19 +130,19 @@ NTSTATUS unix_convert(connection_struct *conn, return NT_STATUS_OK; } - DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); + DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path)); - /* + /* * Conversion to basic unix format is already done in check_path_syntax(). */ - /* + /* * Names must be relative to the root of the service - any leading /. * and trailing /'s should have been trimmed by check_path_syntax(). */ #ifdef DEVELOPER - SMB_ASSERT(*name != '/'); + SMB_ASSERT(*orig_path != '/'); #endif /* @@ -166,23 +153,27 @@ NTSTATUS unix_convert(connection_struct *conn, * As we know this is valid we can return true here. */ - if (!*name) { - name[0] = '.'; - name[1] = '\0'; + if (!*orig_path) { + if (!(name = SMB_STRDUP("."))) { + result = NT_STATUS_NO_MEMORY; + goto fail; + } if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; } DEBUG(5,("conversion finished \"\" -> %s\n",name)); - return NT_STATUS_OK; + goto done; } - if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) { + if (orig_path[0] == '.' && (orig_path[1] == '/' || orig_path[1] == '\0')) { /* Start of pathname can't be "." only. */ - if (name[1] == '\0' || name[2] == '\0') { - return NT_STATUS_OBJECT_NAME_INVALID; + if (orig_path[1] == '\0' || orig_path[2] == '\0') { + result = NT_STATUS_OBJECT_NAME_INVALID; } else { - return determine_path_error(&name[2], allow_wcard_last_component); + result =determine_path_error( + &orig_path[2], allow_wcard_last_component); } + goto fail; } /* @@ -190,14 +181,19 @@ NTSTATUS unix_convert(connection_struct *conn, */ if(saved_last_component) { - end = strrchr_m(name, '/'); + end = strrchr_m(orig_path, '/'); if (end) { pstrcpy(saved_last_component, end + 1); } else { - pstrcpy(saved_last_component, name); + pstrcpy(saved_last_component, orig_path); } } + if (!(name = SMB_STRDUP(orig_path))) { + DEBUG(0, ("strdup failed\n")); + return NT_STATUS_NO_MEMORY; + } + /* * Large directory fix normalization. If we're case sensitive, and * the case preserving parameters are set to "no", normalize the case of @@ -210,16 +206,27 @@ NTSTATUS unix_convert(connection_struct *conn, if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { strnorm(name, lp_defaultcase(SNUM(conn))); } - + start = name; - pstrcpy(orig_path, name); - if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) { + if(!conn->case_sensitive + && stat_cache_lookup(conn, &name, &dirpath, &start, &st)) { *pst = st; - return NT_STATUS_OK; + goto done; + } + + /* + * Make sure "dirpath" is an allocated string, we use this for + * building the directories with asprintf and free it. + */ + + if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) { + DEBUG(0, ("strdup failed\n")); + result = NT_STATUS_NO_MEMORY; + goto fail; } - /* + /* * stat the name - if it exists then we are all done! */ @@ -239,24 +246,24 @@ NTSTATUS unix_convert(connection_struct *conn, stat_cache_add(orig_path, name, conn->case_sensitive); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; - return NT_STATUS_OK; + goto done; } DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); - /* + /* * A special case - if we don't have any mangling chars and are case * sensitive then searching won't help. */ - if (conn->case_sensitive && + if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) && !*lp_mangled_map(conn->params)) { - return NT_STATUS_OK; + goto done; } - /* - * is_mangled() was changed to look at an entire pathname, not + /* + * is_mangled() was changed to look at an entire pathname, not * just a component. JRA. */ @@ -264,23 +271,23 @@ NTSTATUS unix_convert(connection_struct *conn, component_was_mangled = True; } - /* - * Now we need to recursively match the name against the real + /* + * Now we need to recursively match the name against the real * directory structure. */ - /* + /* * Match each part of the path name separately, trying the names * as is first, then trying to scan the directory for matching names. */ for (; start ; start = (end?end+1:(char *)NULL)) { - /* + /* * Pinpoint the end of this section of the filename. */ end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */ - /* + /* * Chop the name at this point. */ if (end) { @@ -296,9 +303,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (ISDOT(start)) { if (!end) { /* Error code at the end of a pathname. */ - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + } else { + result = determine_path_error(end+1, + allow_wcard_last_component); } - return determine_path_error(end+1, allow_wcard_last_component); + goto fail; } /* The name cannot have a wildcard if it's not @@ -308,15 +318,17 @@ NTSTATUS unix_convert(connection_struct *conn, /* Wildcard not valid anywhere. */ if (name_has_wildcard && !allow_wcard_last_component) { - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + goto fail; } /* Wildcards never valid within a pathname. */ if (name_has_wildcard && end) { - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + goto fail; } - /* + /* * Check if the name exists up to this point. */ @@ -331,14 +343,15 @@ NTSTATUS unix_convert(connection_struct *conn, */ DEBUG(5,("Not a dir %s\n",start)); *end = '/'; - /* + /* * We need to return the fact that the intermediate * name resolution failed. This is used to return an * error of ERRbadpath rather than ERRbadfile. Some * Windows applications depend on the difference between * these two errors. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; } if (!end) { @@ -352,20 +365,10 @@ NTSTATUS unix_convert(connection_struct *conn, } } else { - pstring rest; + char *found_name = NULL; /* Stat failed - ensure we don't use it. */ SET_STAT_INVALID(st); - *rest = 0; - - /* - * Remember the rest of the pathname so it can be restored - * later. - */ - - if (end) { - pstrcpy(rest,end+1); - } /* Reset errno so we can detect directory open errors. */ errno = 0; @@ -375,7 +378,9 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (name_has_wildcard || - !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) { + !scan_directory(conn, dirpath, start, &found_name)) { + char *unmangled; + if (end) { /* * An intermediate part of the name can't be found. @@ -383,7 +388,7 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5,("Intermediate not found %s\n",start)); *end = '/'; - /* + /* * We need to return the fact that the intermediate * name resolution failed. This is used to return an * error of ERRbadpath rather than ERRbadfile. Some @@ -395,19 +400,25 @@ NTSTATUS unix_convert(connection_struct *conn, in the filename walk. */ if (errno == ENOENT || errno == ENOTDIR) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + else { + result = map_nt_error_from_unix(errno); } - return map_nt_error_from_unix(errno); + goto fail; } - + /* ENOENT is the only valid error here. */ if (errno != ENOENT) { /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND in the filename walk. */ if (errno == ENOTDIR) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + else { + result = map_nt_error_from_unix(errno); } - return map_nt_error_from_unix(errno); + goto fail; } /* @@ -427,26 +438,79 @@ NTSTATUS unix_convert(connection_struct *conn, * base of the filename. */ - if (mangle_is_mangled(start, conn->params)) { - mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params); + if (mangle_is_mangled(start, conn->params) + && mangle_check_cache_alloc(start, &unmangled, + conn->params)) { + char *tmp; + size_t start_ofs = start - name; + + if (*dirpath != '\0') { + asprintf(&tmp, "%s/%s", dirpath, + unmangled); + SAFE_FREE(unmangled); + } + else { + tmp = unmangled; + } + if (tmp == NULL) { + DEBUG(0, ("malloc failed\n")); + result = NT_STATUS_NO_MEMORY; + } + SAFE_FREE(name); + name = tmp; + start = name + start_ofs; + end = start + strlen(start); } DEBUG(5,("New file %s\n",start)); - return NT_STATUS_OK; + goto done; } - /* + + /* * Restore the rest of the string. If the string was mangled the size * may have changed. */ if (end) { - end = start + strlen(start); - if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) || - !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) { - return map_nt_error_from_unix(ENAMETOOLONG); + char *tmp; + size_t start_ofs = start - name; + + if (*dirpath != '\0') { + asprintf(&tmp, "%s/%s/%s", dirpath, + found_name, end+1); } + else { + asprintf(&tmp, "%s/%s", found_name, + end+1); + } + if (tmp == NULL) { + DEBUG(0, ("asprintf failed\n")); + result = NT_STATUS_NO_MEMORY; + } + SAFE_FREE(name); + name = tmp; + start = name + start_ofs; + end = start + strlen(found_name); *end = '\0'; } else { + char *tmp; + size_t start_ofs = start - name; + + if (*dirpath != '\0') { + asprintf(&tmp, "%s/%s", dirpath, + found_name); + } + else { + tmp = SMB_STRDUP(found_name); + } + if (tmp == NULL) { + DEBUG(0, ("malloc failed\n")); + result = NT_STATUS_NO_MEMORY; + } + SAFE_FREE(name); + name = tmp; + start = name + start_ofs; + /* * We just scanned for, and found the end of the path. * We must return a valid stat struct if it exists. @@ -459,40 +523,56 @@ NTSTATUS unix_convert(connection_struct *conn, SET_STAT_INVALID(st); } } + + SAFE_FREE(found_name); } /* end else */ #ifdef DEVELOPER if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) { - return NT_STATUS_DELETE_PENDING; + result = NT_STATUS_DELETE_PENDING; + goto fail; } #endif /* * Add to the dirpath that we have resolved so far. */ - if (*dirpath) { - pstrcat(dirpath,"/"); - } - pstrcat(dirpath,start); + if (*dirpath != '\0') { + char *tmp; + + if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) { + DEBUG(0, ("asprintf failed\n")); + return NT_STATUS_NO_MEMORY; + } + SAFE_FREE(dirpath); + dirpath = tmp; + } + else { + SAFE_FREE(dirpath); + if (!(dirpath = SMB_STRDUP(start))) { + DEBUG(0, ("strdup failed\n")); + return NT_STATUS_NO_MEMORY; + } + } /* * Don't cache a name with mangled or wildcard components * as this can change the size. */ - + if(!component_was_mangled && !name_has_wildcard) { stat_cache_add(orig_path, dirpath, conn->case_sensitive); } - - /* + + /* * Restore the / that we wiped out earlier. */ if (end) { *end = '/'; } } - + /* * Don't cache a name with mangled or wildcard components * as this can change the size. @@ -502,12 +582,19 @@ NTSTATUS unix_convert(connection_struct *conn, stat_cache_add(orig_path, name, conn->case_sensitive); } - /* + /* * The name has been resolved. */ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - return NT_STATUS_OK; + + done: + result = NT_STATUS_OK; + pstrcpy(orig_path, name); + fail: + SAFE_FREE(name); + SAFE_FREE(dirpath); + return result; } /**************************************************************************** @@ -538,22 +625,38 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) return NT_STATUS_OK; } +/**************************************************************************** + Check if two filenames are equal. + This needs to be careful about whether we are case sensitive. +****************************************************************************/ + +static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) +{ + /* Normal filename handling */ + if (case_sensitive) + return(strcmp(name1,name2) == 0); + + return(strequal(name1,name2)); +} + /**************************************************************************** Scan a directory to find a filename, matching without case sensitivity. If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength) +static BOOL scan_directory(connection_struct *conn, const char *path, + char *name, char **found_name) { struct smb_Dir *cur_dir; const char *dname; BOOL mangled; + char *unmangled_name = NULL; long curpos; mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ - if (*path == 0) + if ((path == NULL) || (*path == 0)) path = "."; /* @@ -572,12 +675,15 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name */ if (mangled && !conn->case_sensitive) { - mangled = !mangle_check_cache( name, maxlength, conn->params); + mangled = !mangle_check_cache_alloc(name, &unmangled_name, + conn->params); + name = unmangled_name; } /* open the directory */ if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); + SAFE_FREE(unmangled_name); return(False); } @@ -603,12 +709,14 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ - safe_strcpy(name, dname, maxlength); + *found_name = SMB_STRDUP(dname); + SAFE_FREE(unmangled_name); CloseDir(cur_dir); return(True); } } + SAFE_FREE(unmangled_name); CloseDir(cur_dir); errno = ENOENT; return(False); diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index d7f2eb8db2..f69c940539 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -112,6 +112,21 @@ BOOL mangle_check_cache(char *s, size_t maxlen, return mangle_fns->check_cache(s, maxlen, p); } +BOOL mangle_check_cache_alloc(const char *name, char **presult, + const struct share_params *p) +{ + pstring tmp; + char *result; + pstrcpy(tmp, name); + + if (!mangle_check_cache(tmp, sizeof(pstring), p) + || !(result = SMB_STRDUP(tmp))) { + return False; + } + *presult = result; + return True; +} + /* map a long filename to a 8.3 name. */ diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 51e8c0417a..24cfe3beb8 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Andrew Bartlett 2003 + Copyright (C) Volker Lendecke 2007 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 @@ -39,9 +40,8 @@ static TDB_CONTEXT *tdb_stat_cache; * */ -void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive) +void stat_cache_add( const char *full_orig_name, const char *translated_path, BOOL case_sensitive) { - char *translated_path; size_t translated_path_length; TDB_DATA data_val; char *original_path; @@ -61,10 +61,10 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * Don't cache trivial valid directory entries such as . and .. */ - if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && - ((full_orig_name[1] == '\0') || - (full_orig_name[1] == '.' && full_orig_name[2] == '\0')))) + if ((*full_orig_name == '\0') + || ISDOT(full_orig_name) || ISDOTDOT(full_orig_name)) { return; + } /* * If we are in case insentive mode, we don't need to @@ -72,7 +72,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * would be a waste. */ - if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) return; /* @@ -80,14 +80,15 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * translated path. */ - translated_path = SMB_STRDUP(orig_translated_path); - if (!translated_path) - return; + /* + * To save a strdup we don't necessarily 0-terminate the translated + * path in the tdb. Instead, we do it directly after the tdb_fetch in + * stat_cache_lookup. + */ translated_path_length = strlen(translated_path); if(translated_path[translated_path_length-1] == '/') { - translated_path[translated_path_length-1] = '\0'; translated_path_length--; } @@ -98,7 +99,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } if (!original_path) { - SAFE_FREE(translated_path); return; } @@ -114,7 +114,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %lu and [%s] %lu)!\n", original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); SAFE_FREE(original_path); - SAFE_FREE(translated_path); return; } @@ -140,7 +139,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } SAFE_FREE(original_path); - SAFE_FREE(translated_path); } /** @@ -148,7 +146,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * * @param conn A connection struct to do the stat() with. * @param name The path we are attempting to cache, modified by this routine - * to be correct as far as the cache can tell us + * to be correct as far as the cache can tell us. We assume that + * it is a malloc'ed string, we free it if necessary. * @param dirpath The path as far as the stat cache told us. * @param start A pointer into name, for where to 'start' in fixing the rest of the name up. * @param psd A stat buffer, NOT from the cache, but just a side-effect. @@ -157,7 +156,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * */ -BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, +BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, char **start, SMB_STRUCT_STAT *pst) { char *chk_name; @@ -167,10 +166,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char *translated_path; size_t translated_path_length; TDB_DATA data_val; + char *name; if (!lp_stat_cache()) return False; + name = *pname; namelen = strlen(name); *start = name; @@ -180,10 +181,9 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, /* * Don't lookup trivial valid directory entries. */ - if((*name == '\0') || (name[0] == '.' && - ((name[1] == '\0') || - (name[1] == '.' && name[1] == '\0')))) + if ((*name == '\0') || ISDOT(name) || ISDOTDOT(name)) { return False; + } if (conn->case_sensitive) { chk_name = SMB_STRDUP(name); @@ -250,6 +250,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, translated_path = (char *)data_val.dptr; translated_path_length = data_val.dsize - 1; + /* + * In stat_cache_add we did not necessarily 0-terminate the translated + * path. Do it here, where we do have a freshly malloc'ed blob. + */ + translated_path[translated_path_length] = '\0'; + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " "-> [%s]\n", chk_name, translated_path )); DO_PROFILE_INC(statcache_hits); @@ -264,31 +270,43 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if (!sizechanged) { memcpy(name, translated_path, - MIN(sizeof(pstring)-1, translated_path_length)); - } else if (num_components == 0) { - pstrcpy(name, translated_path); - } else { - char *sp; - - sp = strnrchr_m(name, '/', num_components); - if (sp) { - pstring last_component; - pstrcpy(last_component, sp); - pstrcpy(name, translated_path); - pstrcat(name, last_component); + MIN(namelen, translated_path_length)); + } + else { + if (num_components == 0) { + name = SMB_STRNDUP(translated_path, + translated_path_length); } else { - pstrcpy(name, translated_path); + char *sp; + + sp = strnrchr_m(name, '/', num_components); + if (sp) { + asprintf(&name, "%.*s%s", + (int)translated_path_length, + translated_path, sp); + } else { + name = SMB_STRNDUP(translated_path, + translated_path_length); + } } + if (name == NULL) { + /* + * TODO: Get us out of here with a real error message + */ + smb_panic("malloc failed"); + } + SAFE_FREE(*pname); + *pname = name; } + /* set pointer for 'where to start' on fixing the rest of the name */ *start = &name[translated_path_length]; if (**start == '/') ++*start; - pstrcpy(dirpath, translated_path); + *dirpath = translated_path; SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); return (namelen == translated_path_length); } -- cgit From b114d3dc70a631f41c9d6e0e05b0ed98baa9d815 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2007 23:54:01 +0000 Subject: r23846: Belt-and-braces on the msdfs bug. Ensure ELOOP maps correctly. Jeremy. (This used to be commit f2cf4b6b9d1ce561fdf9f6815564d5b4f033dd10) --- source3/smbd/filename.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index fd7727c594..cf6613aa71 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -396,10 +396,15 @@ NTSTATUS unix_convert(connection_struct *conn, * these two errors. */ - /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND - in the filename walk. */ + /* + * ENOENT, ENOTDIR and ELOOP all map + * to NT_STATUS_OBJECT_PATH_NOT_FOUND + * in the filename walk. + */ - if (errno == ENOENT || errno == ENOTDIR) { + if (errno == ENOENT || + errno == ENOTDIR || + errno == ELOOP) { result = NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { @@ -410,9 +415,13 @@ NTSTATUS unix_convert(connection_struct *conn, /* ENOENT is the only valid error here. */ if (errno != ENOENT) { - /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND - in the filename walk. */ - if (errno == ENOTDIR) { + /* + * ENOTDIR and ELOOP both map to + * NT_STATUS_OBJECT_PATH_NOT_FOUND + * in the filename walk. + */ + if (errno == ENOTDIR || + errno == ELOOP) { result = NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { -- cgit From 967b22827ff51d2f546931206cdb4a876f345820 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Jul 2007 18:11:41 +0000 Subject: r23855: Setting the allocation size updates the modified time as a write does. Fix bug #4779. Jeremy. (This used to be commit ed0e2174a895b25ce2b4e8ffd912ad57b31dd2e9) --- source3/smbd/trans2.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8711f988a8..1659c8fcbd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5009,17 +5009,24 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, allocation_size = smb_roundup(conn, allocation_size); } - if(allocation_size == get_file_size(*psbuf)) { - return NT_STATUS_OK; - } - DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n", fname, (double)allocation_size )); - + if (fsp && fsp->fh->fd != -1) { /* Open file handle. */ - if (vfs_allocate_file_space(fsp, allocation_size) == -1) { - return map_nt_error_from_unix(errno); + /* Only change if needed. */ + if (allocation_size != get_file_size(*psbuf)) { + if (vfs_allocate_file_space(fsp, allocation_size) == -1) { + return map_nt_error_from_unix(errno); + } + } + /* But always update the time. */ + if (null_timespec(fsp->pending_modtime)) { + /* + * This is equivalent to a write. Ensure it's seen immediately + * if there are no pending writes. + */ + set_filetime(fsp->conn, fsp->fsp_name, timespec_current()); } return NT_STATUS_OK; } @@ -5034,17 +5041,27 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, FILE_ATTRIBUTE_NORMAL, FORCE_OPLOCK_BREAK_TO_NONE, NULL, &new_fsp); - + if (!NT_STATUS_IS_OK(status)) { /* NB. We check for open_was_deferred in the caller. */ return status; } - if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) { - status = map_nt_error_from_unix(errno); - close_file(new_fsp,NORMAL_CLOSE); - return status; + + /* Only change if needed. */ + if (allocation_size != get_file_size(*psbuf)) { + if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) { + status = map_nt_error_from_unix(errno); + close_file(new_fsp,NORMAL_CLOSE); + return status; + } } + /* Changing the allocation size should set the last mod time. */ + /* Don't need to call set_filetime as this will be flushed on + * close. */ + + fsp_set_pending_modtime(new_fsp, timespec_current()); + close_file(new_fsp,NORMAL_CLOSE); return NT_STATUS_OK; } -- cgit From e8dc2ea03d212bc4b4facc2a900f6a443365c390 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Jul 2007 01:22:09 +0000 Subject: r23858: Added srvstr_pull_buf_talloc() and srvstr_pull_talloc() calls and converted reply_tcon and reply_tconX to use them - to show the boilerplate usage (valgrind tested). In conjunction with Volker's srvstr_get_path_talloc() work this should allow us to start eliminating all pstrings/fstrings out of the main path processing code. I'll watch the build farm tonight... Jeremy. (This used to be commit b4eff3f68089f082781afcf90d43faa317949566) --- source3/smbd/reply.c | 115 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9a2dc19fa1..8b6a164a66 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -381,30 +381,40 @@ int reply_special(char *inbuf,char *outbuf) int reply_tcon(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { + TALLOC_CTX *ctx; const char *service; - pstring service_buf; - pstring password; - pstring dev; + char *service_buf = NULL; + char *password = NULL; + char *dev = NULL; int outsize = 0; uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; NTSTATUS nt_status; char *p; DATA_BLOB password_blob; - + START_PROFILE(SMBtcon); - *service_buf = *password = *dev = 0; + ctx = talloc_init("reply_tcon"); + if (!ctx) { + END_PROFILE(SMBtcon); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p, - sizeof(service_buf), STR_TERMINATE) + 1; - pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p, - sizeof(password), STR_TERMINATE) + 1; + p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), + &service_buf, p, STR_TERMINATE) + 1; + pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), + &password, p, STR_TERMINATE) + 1; p += pwlen; - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev), - STR_TERMINATE) + 1; + p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), + &dev, p, STR_TERMINATE) + 1; + if (service_buf == NULL || password == NULL || dev == NULL) { + TALLOC_FREE(ctx); + END_PROFILE(SMBtcon); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } p = strrchr_m(service_buf,'\\'); if (p) { service = p+1; @@ -417,21 +427,23 @@ int reply_tcon(connection_struct *conn, conn = make_connection(service,password_blob,dev,vuid,&nt_status); data_blob_clear_free(&password_blob); - + if (!conn) { + TALLOC_FREE(ctx); END_PROFILE(SMBtcon); return ERROR_NT(nt_status); } - + outsize = set_message(inbuf,outbuf,2,0,True); SSVAL(outbuf,smb_vwv0,max_recv); SSVAL(outbuf,smb_vwv1,conn->cnum); SSVAL(outbuf,smb_tid,conn->cnum); - + DEBUG(3,("tcon service=%s cnum=%d\n", service, conn->cnum)); - + END_PROFILE(SMBtcon); + TALLOC_FREE(ctx); return(outsize); } @@ -442,23 +454,22 @@ int reply_tcon(connection_struct *conn, int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - fstring service; + char *service = NULL; DATA_BLOB password; + TALLOC_CTX *ctx = NULL; /* what the cleint thinks the device is */ - fstring client_devicetype; + char *client_devicetype = NULL; /* what the server tells the client the share represents */ const char *server_devicetype; NTSTATUS nt_status; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); - pstring path; + char *path = NULL; char *p, *q; uint16 tcon_flags = SVAL(inbuf,smb_vwv2); - - START_PROFILE(SMBtconX); - *service = *client_devicetype = 0; + START_PROFILE(SMBtconX); /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { @@ -468,7 +479,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (passlen > MAX_PASS_LEN) { return ERROR_DOS(ERRDOS,ERRbuftoosmall); } - + if (global_encrypted_passwords_negotiated) { password = data_blob(smb_buf(inbuf),passlen); if (lp_security() == SEC_SHARE) { @@ -487,34 +498,53 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt p = smb_buf(inbuf) + passlen + 1; } - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p, - sizeof(path), STR_TERMINATE); + ctx = talloc_init("reply_tcon_and_X"); + if (!ctx) { + END_PROFILE(SMBtconX); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), &path, p, + STR_TERMINATE); + + if (path == NULL) { + TALLOC_FREE(ctx); + END_PROFILE(SMBtconX); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } /* * the service name can be either: \\server\share * or share directly like on the DELL PowerVault 705 */ - if (*path=='\\') { + if (*path=='\\') { q = strchr_m(path+2,'\\'); if (!q) { + TALLOC_FREE(ctx); END_PROFILE(SMBtconX); return(ERROR_DOS(ERRDOS,ERRnosuchshare)); } - fstrcpy(service,q+1); + service = q+1; + } else { + service = path; + } + + p += srvstr_pull_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), &client_devicetype, p, + 6, STR_ASCII); + + if (client_devicetype == NULL) { + TALLOC_FREE(ctx); + END_PROFILE(SMBtconX); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - else - fstrcpy(service,path); - - p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p, - sizeof(client_devicetype), 6, STR_ASCII); DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service)); conn = make_connection(service,password,client_devicetype,vuid,&nt_status); - + data_blob_clear_free(&password); if (!conn) { + TALLOC_FREE(ctx); END_PROFILE(SMBtconX); return ERROR_NT(nt_status); } @@ -523,19 +553,19 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt server_devicetype = "IPC"; else if ( IS_PRINT(conn) ) server_devicetype = "LPT1:"; - else + else server_devicetype = "A:"; if (Protocol < PROTOCOL_NT1) { set_message(inbuf,outbuf,2,0,True); p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, server_devicetype, -1, + p += srvstr_push(outbuf, p, server_devicetype, -1, STR_TERMINATE|STR_ASCII); set_message_end(inbuf,outbuf,p); } else { /* NT sets the fstype of IPC$ to the null string */ const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); - + if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) { /* Return permissions. */ uint32 perm1 = 0; @@ -559,29 +589,30 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, server_devicetype, -1, + p += srvstr_push(outbuf, p, server_devicetype, -1, STR_TERMINATE|STR_ASCII); - p += srvstr_push(outbuf, p, fstype, -1, + p += srvstr_push(outbuf, p, fstype, -1, STR_TERMINATE); - + set_message_end(inbuf,outbuf,p); - + /* what does setting this bit do? It is set by NT4 and may affect the ability to autorun mounted cdroms */ SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS| (lp_csc_policy(SNUM(conn)) << 2)); - + init_dfsroot(conn, inbuf, outbuf); } - + DEBUG(3,("tconX service=%s \n", service)); - + /* set the incoming and outgoing tid to the just created one */ SSVAL(inbuf,smb_tid,conn->cnum); SSVAL(outbuf,smb_tid,conn->cnum); + TALLOC_FREE(ctx); END_PROFILE(SMBtconX); return chain_reply(inbuf,outbuf,length,bufsize); } -- cgit From ac51ffb77b70ef1387f454dc128d1aa1c4d3be89 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 13 Jul 2007 13:29:12 +0000 Subject: r23866: Fix a 1-byte buffer overrun (This used to be commit 2ed83d36fec918e6ad9605f43e1a49fa5b61f17b) --- source3/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index f69c940539..fce86903f2 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -119,7 +119,7 @@ BOOL mangle_check_cache_alloc(const char *name, char **presult, char *result; pstrcpy(tmp, name); - if (!mangle_check_cache(tmp, sizeof(pstring), p) + if (!mangle_check_cache(tmp, sizeof(pstring)-1, p) || !(result = SMB_STRDUP(tmp))) { return False; } -- cgit From 3912eebdc94021d6be9fd9e0115b8b67f241b9bc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jul 2007 09:37:36 +0000 Subject: r23877: Fix two segfaults in (very unlikely) error paths, found by the IBM checker. (This used to be commit 33068885e62f3681644c128e381822d48298ea05) --- source3/smbd/trans2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1659c8fcbd..080eb36b42 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2998,6 +2998,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (!puid) { DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n")); + return False; } own_grp = (unsigned int)*puid; SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); @@ -3017,6 +3018,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (!pgid) { DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n")); + return False; } own_grp = (unsigned int)*pgid; SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype); -- cgit From e84f8662e6af515aba5db7ffd874ad5da97188bf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jul 2007 09:40:00 +0000 Subject: r23878: Fix an error return, found by the IBM checker (This used to be commit a369c67f6678bdcc0689929238bc96f45cdeeb25) --- source3/smbd/filename.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index cf6613aa71..824c32867a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -515,6 +515,7 @@ NTSTATUS unix_convert(connection_struct *conn, if (tmp == NULL) { DEBUG(0, ("malloc failed\n")); result = NT_STATUS_NO_MEMORY; + goto fail; } SAFE_FREE(name); name = tmp; -- cgit From d537225c4c467e8bda6e8f45b69a64c16c5ecb58 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jul 2007 09:42:43 +0000 Subject: r23879: Fix two memleaks, found by the IBM checker (This used to be commit 4d1b33f51308c95293fa2494b47ba1255af8d216) --- source3/smbd/filename.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 824c32867a..a1b56736a0 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -237,10 +237,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (p) { if (p[2] == '/') { /* Error code within a pathname. */ - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; } else if (p[2] == '\0') { /* Error code at the end of a pathname. */ - return NT_STATUS_OBJECT_NAME_INVALID; + result = NT_STATUS_OBJECT_NAME_INVALID; + goto fail; } } stat_cache_add(orig_path, name, conn->case_sensitive); -- cgit From b4366f6c37457d082478e72f05040eb13df94b64 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Jul 2007 18:17:19 +0000 Subject: r23902: Fix uninitialized read in devicetype noticed by Volker. Jeremy (This used to be commit 98c23939731654440d2f008e44e11371eaddf014) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8b6a164a66..2421e2ffd9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -529,7 +529,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } p += srvstr_pull_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), &client_devicetype, p, - 6, STR_ASCII); + MIN(6,smb_bufrem(inbuf, p)), STR_ASCII); if (client_devicetype == NULL) { TALLOC_FREE(ctx); -- cgit From 5e8590753ce0745ee1811bd68bb96aad5fe123a3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 16 Jul 2007 19:36:46 +0000 Subject: r23903: Fix a potential reason for the segfault Steve found (This used to be commit c06bc91085c24bf6cc4491448ba12c5c2f1c7937) --- source3/smbd/nttrans.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 56eef9b4e2..f7df37b433 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -305,6 +305,7 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx return NULL; } + result->conn = conn; result->case_sensitive = conn->case_sensitive; result->case_preserve = conn->case_preserve; result->short_case_preserve = conn->short_case_preserve; -- cgit From f798837c23415653fc83cddeab3285b6f1563526 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 16 Jul 2007 21:17:26 +0000 Subject: r23904: Remove an unused variable reference (This used to be commit 7f4ceb1bf0c7aad50d93bb963c49dbc405e9524a) --- source3/smbd/reply.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2421e2ffd9..d6b0dcab2e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -27,7 +27,6 @@ /* look in server.c for some explanation of these variables */ extern enum protocol_types Protocol; -extern int max_send; extern int max_recv; unsigned int smb_echo_count = 0; extern uint32 global_client_caps; -- cgit From b3d471d36740cc6afdf69cb1da438049fa1529a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 00:09:56 +0000 Subject: r23906: Fix POSIX unlink bug found by Steve. If we used lstat during the open (which we always do for POSIX) then use lstat for the unlink. Jeremy. (This used to be commit 4aad77c27cc277e3d937f674ee620729411e3eaf) --- source3/smbd/close.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index dedf935501..7c3e1eef28 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -154,6 +154,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; + int ret; struct file_id id; /* @@ -247,8 +248,14 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, /* We can only delete the file if the name we have is still valid and hasn't been renamed. */ - - if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { + + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf); + } else { + ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf); + } + + if (ret != 0) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and stat failed with error %s\n", fsp->fsp_name, strerror(errno) )); -- cgit From 5e3e15f754a9bc6412f6172d454f815e5b71307b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 02:06:38 +0000 Subject: r23909: Get closer to passing the cthon tests for delete open file. It matters how the target is open. Jeremy. (This used to be commit 0989877fd191f7c9e195dc6e45dda5fd026f09dd) --- source3/smbd/reply.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d6b0dcab2e..e3ae0ef7f6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4447,9 +4447,12 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_OBJECT_NAME_COLLISION; } - if (dst_exists && file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) { - DEBUG(3, ("rename_internals_fsp: Target file open\n")); - return NT_STATUS_ACCESS_DENIED; + if (dst_exists) { + files_struct *dst_fsp = file_find_di_first(file_id_sbuf(&sbuf1)); + if (dst_fsp && !(dst_fsp->share_access & FILE_SHARE_DELETE)) { + DEBUG(3, ("rename_internals_fsp: Target file open\n")); + return NT_STATUS_ACCESS_DENIED; + } } /* Ensure we have a valid stat struct for the source. */ -- cgit From cfb7c04696f0ac4306a6e1847212fed44f6b2cd5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 02:17:23 +0000 Subject: r23910: We used to deny renames on the source open for non-delete open. Turns out this is not the case. VL please test but this matches Windows behaviour. (I'll add a torture test tomorrow). Jeremy. (This used to be commit 03e3d587468ce66044814a8a58308b2fe9ab5499) --- source3/smbd/reply.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e3ae0ef7f6..2135299df0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1863,6 +1863,12 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, return NT_STATUS_NO_SUCH_FILE; } +#if 0 + /* We used to deny renames on the + * source open for non-delete open. + * Turns out this is not the case. + * VL please test but this matches + * Windows behaviour. JRA. */ if (S_ISDIR(pst->st_mode)) { return NT_STATUS_OK; } @@ -1872,6 +1878,9 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, } return NT_STATUS_ACCESS_DENIED; +#else + return NT_STATUS_OK; +#endif } /******************************************************************* -- cgit From 02730aa86cf187cfcdcb71b07197e0071afd60cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 04:47:36 +0000 Subject: r23911: Revert r23910 to try and fix the build farm. I need to look at this more closely tomorrow. Stevef's cthon tests definately show we're not matching Windows behaviour (as his tests pass against Windows but not SAMBA_3_2) but this isn't the fix. Jeremy. (This used to be commit 90bbc077e15de0493dccda50be9bcdf6e2649137) --- source3/smbd/reply.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2135299df0..e3ae0ef7f6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1863,12 +1863,6 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, return NT_STATUS_NO_SUCH_FILE; } -#if 0 - /* We used to deny renames on the - * source open for non-delete open. - * Turns out this is not the case. - * VL please test but this matches - * Windows behaviour. JRA. */ if (S_ISDIR(pst->st_mode)) { return NT_STATUS_OK; } @@ -1878,9 +1872,6 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, } return NT_STATUS_ACCESS_DENIED; -#else - return NT_STATUS_OK; -#endif } /******************************************************************* -- cgit From 1ffa14ff923ab5790e55bcedee9f10203cf8dfad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 05:55:10 +0000 Subject: r23913: Revert back to Volker's original logic to fix the RAW-SFILEINFO-RENAME until I can figure out what is different from the way CIFSFS drives this in the cthon tests and the way smbtorture drives it. Jeremy. (This used to be commit 99f72dd9af82921de4827b9b9d90d75127332295) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e3ae0ef7f6..0062ca18da 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4449,7 +4449,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin if (dst_exists) { files_struct *dst_fsp = file_find_di_first(file_id_sbuf(&sbuf1)); - if (dst_fsp && !(dst_fsp->share_access & FILE_SHARE_DELETE)) { + if (dst_fsp) { DEBUG(3, ("rename_internals_fsp: Target file open\n")); return NT_STATUS_ACCESS_DENIED; } -- cgit From 63e93ad01274f34617bacd56d0e43cb0b81475c9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Jul 2007 06:03:03 +0000 Subject: r23914: try to fix the build on Tru64 /usr/include/sys/acl.h:#define acl_type acl_common.entry_type was the problem... metze (This used to be commit 8557b8b570ac8f8d3d14aaeb894c8b3532558736) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 87b456a2f7..6286cd0414 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3111,7 +3111,7 @@ static NTSTATUS append_ugw_ace(files_struct *fsp, { mode_t perms; SEC_ACCESS acc; - int acl_type; + int nt_acl_type; DOM_SID trustee; switch (ugw) { @@ -3140,13 +3140,13 @@ static NTSTATUS append_ugw_ace(files_struct *fsp, return NT_STATUS_INVALID_PARAMETER; } acc = map_canon_ace_perms(SNUM(fsp->conn), - &acl_type, + &nt_acl_type, perms, fsp->is_directory); init_sec_ace(se, &trustee, - acl_type, + nt_acl_type, acc, 0); return NT_STATUS_OK; -- cgit From 14826b0a794fb321cee43df0aadf3a34460dbfcc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 18:48:39 +0000 Subject: r23935: We were lying to the client in the case of POSIX_UNLINK if a Windows client had the file open. We were setting delete on close and returning "ok". The POSIX client then believed the file was gone (and it wasn't). Fix this to return SHARING_VIOLATION if there is an existing NTcreateX open on the file and someone calls POSIX_UNLINK. Still one more Cthon test to fix but getting closer now. Should be in 3.0.25c also. Jeremy. (This used to be commit 24e625a615447c025b73fed2d3db03c1f11ae596) --- source3/smbd/trans2.c | 67 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 080eb36b42..2d7d96e8b3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5723,7 +5723,10 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, NTSTATUS status = NT_STATUS_OK; files_struct *fsp = NULL; uint16 flags = 0; + char del = 1; int info = 0; + int i; + struct share_mode_lock *lck = NULL; if (total_data < 2) { return NT_STATUS_INVALID_PARAMETER; @@ -5751,12 +5754,11 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, - FILE_DELETE_ON_CLOSE, + 0, FILE_FLAG_POSIX_SEMANTICS|0777, - &info, + &info, &fsp); } else { - char del = 1; status = open_file_ntcreate(conn, req, fname, @@ -5769,26 +5771,59 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, 0, /* No oplock, but break existing ones. */ &info, &fsp); - /* - * For file opens we must set the delete on close - * after the open. - */ + } - if (!NT_STATUS_IS_OK(status)) { - return status; - } + if (!NT_STATUS_IS_OK(status)) { + return status; + } - status = smb_set_file_disposition_info(conn, - &del, - 1, - fsp, - fname, - psbuf); + /* + * Don't lie to client. If we can't really delete due to + * non-POSIX opens return SHARING_VIOLATION. + */ + + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + if (lck == NULL) { + DEBUG(0, ("smb_posix_unlink: Could not get share mode " + "lock for file %s\n", fsp->fsp_name)); + close_file(fsp, NORMAL_CLOSE); + return NT_STATUS_INVALID_PARAMETER; + } + + /* + * See if others still have the file open. If this is the case, then + * don't delete. If all opens are POSIX delete we can set the delete + * on close disposition. + */ + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (is_valid_share_mode_entry(e)) { + if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) { + continue; + } + /* Fail with sharing violation. */ + close_file(fsp, NORMAL_CLOSE); + TALLOC_FREE(lck); + return NT_STATUS_SHARING_VIOLATION; + } } + /* + * Set the delete on close. + */ + status = smb_set_file_disposition_info(conn, + &del, + 1, + fsp, + fname, + psbuf); + if (!NT_STATUS_IS_OK(status)) { + close_file(fsp, NORMAL_CLOSE); + TALLOC_FREE(lck); return status; } + TALLOC_FREE(lck); return close_file(fsp, NORMAL_CLOSE); } -- cgit From ed9e0d9a3acfa6ab05639da5c29e2edb07a9fb67 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 23:01:02 +0000 Subject: r23939: Fixes for notify returns. Returned param value must fix inside max_param or return NT_STATUS_OK. Jeremy. (This used to be commit ab4af60d1ab4583fd27deb63b3f7baa1ede3473d) --- source3/smbd/notify.c | 36 +++++++++++++++++------------------- source3/smbd/nttrans.c | 5 +++-- 2 files changed, 20 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6ab4266c19..40dcecee26 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -21,15 +21,12 @@ #include "includes.h" -/* Max size we can send to client in a notify response. */ -extern int max_send; - struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ char request_buf[smb_size]; uint32 filter; - uint32 current_bufsize; + uint32 max_param; struct notify_mid_map *mid_map; void *backend_data; }; @@ -61,8 +58,9 @@ static BOOL notify_change_record_identical(struct notify_change *c1, } static BOOL notify_marshall_changes(int num_changes, - struct notify_change *changes, - prs_struct *ps) + uint32 max_offset, + struct notify_change *changes, + prs_struct *ps) { int i; UNISTR uni_name; @@ -112,6 +110,11 @@ static BOOL notify_marshall_changes(int num_changes, prs_set_offset(ps, prs_offset(ps)-2); SAFE_FREE(uni_name.buffer); + + if (prs_offset(ps) > max_offset) { + /* Too much data for client. */ + return False; + } } return True; @@ -148,7 +151,7 @@ static void change_notify_reply_packet(const char *request_buf, "failed."); } -void change_notify_reply(const char *request_buf, +void change_notify_reply(const char *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { char *outbuf = NULL; @@ -160,16 +163,10 @@ void change_notify_reply(const char *request_buf, return; } - if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(notify_buf->num_changes, - notify_buf->changes, &ps)) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); - goto done; - } - - buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; + prs_init(&ps, 0, NULL, False); - if (buflen > max_send) { + if (!notify_marshall_changes(notify_buf->num_changes, max_param, + notify_buf->changes, &ps)) { /* * We exceed what the client is willing to accept. Send * nothing. @@ -238,7 +235,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const char *inbuf, +NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param, uint32 filter, BOOL recursive, struct files_struct *fsp) { @@ -255,11 +252,11 @@ NTSTATUS change_notify_add_request(const char *inbuf, map->req = request; memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); - request->current_bufsize = 0; + request->max_param = max_param; request->filter = filter; request->fsp = fsp; request->backend_data = NULL; - + DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -431,6 +428,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) */ change_notify_reply(fsp->notify->requests->request_buf, + fsp->notify->requests->max_param, fsp->notify); change_notify_remove_request(fsp->notify->requests); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f7df37b433..64b6d33eee 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2045,7 +2045,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * here. */ - change_notify_reply(inbuf, fsp->notify); + change_notify_reply(inbuf, max_param_count, fsp->notify); /* * change_notify_reply() above has independently sent its @@ -2058,7 +2058,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * No changes pending, queue the request */ - status = change_notify_add_request(inbuf, filter, recursive, fsp); + status = change_notify_add_request(inbuf, max_param_count, filter, + recursive, fsp); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } -- cgit From cf0962789447d881cfeb220b4d20bcbcf0197fe8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 23:57:13 +0000 Subject: r23940: Added missing line that was deleted accidently. Should fix the build. Jeremy. (This used to be commit b085366d5b982b635561f1d3211a6f3197258e6f) --- source3/smbd/notify.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 40dcecee26..872ec86644 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -175,6 +175,8 @@ void change_notify_reply(const char *request_buf, uint32 max_param, goto done; } + buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; -- cgit From 921ac7da4f00b86b853dd0874c7ca0d4c8677486 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Jul 2007 00:18:57 +0000 Subject: r23941: Don't use "False" when you mean "MARSHALL". Jeremy. (This used to be commit 57d4d5f2cd1ad7bae28f40478f4c2f9b6a475ce6) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 872ec86644..d003cfa88f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -163,7 +163,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param, return; } - prs_init(&ps, 0, NULL, False); + prs_init(&ps, 0, NULL, MARSHALL); if (!notify_marshall_changes(notify_buf->num_changes, max_param, notify_buf->changes, &ps)) { -- cgit From e6c6c0438d07d4362b2a773199b288ed5335c23d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Jul 2007 01:27:03 +0000 Subject: r23942: Fix issue found by Shlomi Yaakobovich where invalid names sent as a resume name were incorrectly mapped into . and .. Ensure they really *are . and .. Jeremy. (This used to be commit 78d0c5194fe42ad4f096657e2210a15541303a2a) --- source3/smbd/trans2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2d7d96e8b3..18b51ab56c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2024,11 +2024,12 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu complain (it thinks we're asking for the directory above the shared path or an invalid name). Catch this as the resume name is only compared, never used in a file access. JRA. */ - if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) { - pstrcpy(resume_name, ".."); - } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) { - pstrcpy(resume_name, "."); - } else { + srvstr_pull(inbuf, SVAL(inbuf,smb_flg2), + resume_name, params+12, + sizeof(resume_name), total_params - 12, + STR_TERMINATE); + + if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) { return ERROR_NT(ntstatus); } } -- cgit From 16443996b51f56b3c788d4f15e85ec0911a807b7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jul 2007 10:23:36 +0000 Subject: r23967: Memleak fix from Atsushi Nakabayashi Thanks! Volker (This used to be commit 46997a70199296d4ec45780f002898f23029bb26) --- source3/smbd/lanman.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a7fe07b314..3568bb55b9 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -850,6 +850,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); if (!*rdata) { + SAFE_FREE(queue); return False; } desc.base = *rdata; @@ -882,6 +883,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { + SAFE_FREE(queue); + SAFE_FREE(tmpdata); return False; } SSVALS(*rparam,0,desc.errcode); -- cgit From 799c3ec8d466853a87b94df04e0e7b404a311bea Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 21 Jul 2007 22:00:09 +0000 Subject: r23987: Remove static pid in switch_message() There's no point in duplicating functionality that exists in sys_getpid() that also only used in a debug statement (This used to be commit ebf1b1e97c709f5ffe48c85b4227a0af1f88b0ab) --- source3/smbd/process.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e6bafa8dc3..d193cfb95b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -898,14 +898,10 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len) static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize) { - static pid_t pid= (pid_t)-1; int outsize = 0; type &= 0xff; - if (pid == (pid_t)-1) - pid = sys_getpid(); - errno = 0; last_message = type; @@ -928,7 +924,9 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn)); + DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", + smb_fn_name(type), (int)sys_getpid(), + (unsigned long)conn)); smb_dump(smb_fn_name(type), 1, inbuf, size); -- cgit From 941db29ab41a893ca2f4f2fb39f31cfbb6a634c9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 21 Jul 2007 22:29:55 +0000 Subject: r23988: Looks a lot more scary than it is: This just unwraps the else-branch of if (smb_messages[type].fn == NULL) { into the function top-level. Makes this function a bit easier to understand IMO. Volker (This used to be commit ada23b7f06acb00c36763a3e7a6f6e0caac86951) --- source3/smbd/process.c | 141 ++++++++++++++++++++++++++----------------------- 1 file changed, 74 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d193cfb95b..7958fc761d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -899,6 +899,10 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len) static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize) { int outsize = 0; + int flags; + static uint16 last_session_tag = UID_FIELD_INVALID; + uint16 session_tag; + connection_struct *conn; type &= 0xff; @@ -917,97 +921,100 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize DEBUG(0,("Unknown message type %d!\n",type)); smb_dump("Unknown", 1, inbuf, size); outsize = reply_unknown(inbuf,outbuf); - } else { - int flags = smb_messages[type].flags; - static uint16 last_session_tag = UID_FIELD_INVALID; - /* In share mode security we must ignore the vuid. */ - uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); - connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + goto done; + } - DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", - smb_fn_name(type), (int)sys_getpid(), - (unsigned long)conn)); + flags = smb_messages[type].flags; - smb_dump(smb_fn_name(type), 1, inbuf, size); + /* In share mode security we must ignore the vuid. */ + session_tag = (lp_security() == SEC_SHARE) + ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); - /* Ensure this value is replaced in the incoming packet. */ - SSVAL(inbuf,smb_uid,session_tag); + conn = conn_find(SVAL(inbuf,smb_tid)); - /* - * Ensure the correct username is in current_user_info. - * This is a really ugly bugfix for problems with - * multiple session_setup_and_X's being done and - * allowing %U and %G substitutions to work correctly. - * There is a reason this code is done here, don't - * move it unless you know what you're doing... :-). - * JRA. - */ + DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", + smb_fn_name(type), (int)sys_getpid(), + (unsigned long)conn)); + + smb_dump(smb_fn_name(type), 1, inbuf, size); + + /* Ensure this value is replaced in the incoming packet. */ + SSVAL(inbuf,smb_uid,session_tag); - if (session_tag != last_session_tag) { - user_struct *vuser = NULL; + /* + * Ensure the correct username is in current_user_info. This is a + * really ugly bugfix for problems with multiple session_setup_and_X's + * being done and allowing %U and %G substitutions to work correctly. + * There is a reason this code is done here, don't move it unless you + * know what you're doing... :-). JRA. + */ - last_session_tag = session_tag; - if(session_tag != UID_FIELD_INVALID) { - vuser = get_valid_user_struct(session_tag); - if (vuser) { - set_current_user_info(&vuser->user); - } + if (session_tag != last_session_tag) { + user_struct *vuser = NULL; + + last_session_tag = session_tag; + if(session_tag != UID_FIELD_INVALID) { + vuser = get_valid_user_struct(session_tag); + if (vuser) { + set_current_user_info(&vuser->user); } } + } - /* Does this call need to be run as the connected user? */ - if (flags & AS_USER) { - - /* Does this call need a valid tree connection? */ - if (!conn) { - /* Amazingly, the error code depends on the command (from Samba4). */ - if (type == SMBntcreateX) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); - } else { - return ERROR_DOS(ERRSRV, ERRinvnid); - } - } + /* Does this call need to be run as the connected user? */ + if (flags & AS_USER) { - if (!change_to_user(conn,session_tag)) { - return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid))); + /* Does this call need a valid tree connection? */ + if (!conn) { + /* Amazingly, the error code depends on the command (from Samba4). */ + if (type == SMBntcreateX) { + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } else { + return ERROR_DOS(ERRSRV, ERRinvnid); } + } - /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ + if (!change_to_user(conn,session_tag)) { + return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid))); + } - /* Does it need write permission? */ - if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { - return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED); - } + /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ - /* IPC services are limited */ - if (IS_IPC(conn) && !(flags & CAN_IPC)) { - return(ERROR_DOS(ERRSRV,ERRaccess)); - } - } else { - /* This call needs to be run as root */ - change_to_root_user(); + /* Does it need write permission? */ + if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { + return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED); } - /* load service specific parameters */ - if (conn) { - if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) { - return(ERROR_DOS(ERRSRV,ERRaccess)); - } - conn->num_smb_operations++; + /* IPC services are limited */ + if (IS_IPC(conn) && !(flags & CAN_IPC)) { + return(ERROR_DOS(ERRSRV,ERRaccess)); } + } else { + /* This call needs to be run as root */ + change_to_root_user(); + } - /* does this protocol need to be run as guest? */ - if ((flags & AS_GUEST) && (!change_to_guest() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { + /* load service specific parameters */ + if (conn) { + if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) { return(ERROR_DOS(ERRSRV,ERRaccess)); } + conn->num_smb_operations++; + } - current_inbuf = inbuf; /* In case we need to defer this message in open... */ - outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); + /* does this protocol need to be run as guest? */ + if ((flags & AS_GUEST) + && (!change_to_guest() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), + lp_hostsdeny(-1)))) { + return(ERROR_DOS(ERRSRV,ERRaccess)); } - smb_dump(smb_fn_name(type), 0, outbuf, outsize); + current_inbuf = inbuf; /* In case we need to defer this message in open... */ + outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); + done: + smb_dump(smb_fn_name(type), 0, outbuf, outsize); return(outsize); } -- cgit From 8579dd4deddb97d851dc03b6961d1a0c01cc7bfa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jul 2007 11:38:11 +0000 Subject: r23990: Reformatting for 80 cols and trailing whitespace (This used to be commit 0484de27d97306707ae0243443d18e9dec6d80f3) --- source3/smbd/process.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7958fc761d..558d403948 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -900,10 +900,11 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { int outsize = 0; int flags; - static uint16 last_session_tag = UID_FIELD_INVALID; uint16 session_tag; connection_struct *conn; + static uint16 last_session_tag = UID_FIELD_INVALID; + type &= 0xff; errno = 0; @@ -929,12 +930,10 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* In share mode security we must ignore the vuid. */ session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); - conn = conn_find(SVAL(inbuf,smb_tid)); - DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", - smb_fn_name(type), (int)sys_getpid(), - (unsigned long)conn)); + DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type), + (int)sys_getpid(), (unsigned long)conn)); smb_dump(smb_fn_name(type), 1, inbuf, size); @@ -946,7 +945,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize * really ugly bugfix for problems with multiple session_setup_and_X's * being done and allowing %U and %G substitutions to work correctly. * There is a reason this code is done here, don't move it unless you - * know what you're doing... :-). JRA. + * know what you're doing... :-). + * JRA. */ if (session_tag != last_session_tag) { @@ -954,7 +954,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize last_session_tag = session_tag; if(session_tag != UID_FIELD_INVALID) { - vuser = get_valid_user_struct(session_tag); + vuser = get_valid_user_struct(session_tag); if (vuser) { set_current_user_info(&vuser->user); } @@ -966,7 +966,10 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* Does this call need a valid tree connection? */ if (!conn) { - /* Amazingly, the error code depends on the command (from Samba4). */ + /* + * Amazingly, the error code depends on the command + * (from Samba4). + */ if (type == SMBntcreateX) { return ERROR_NT(NT_STATUS_INVALID_HANDLE); } else { @@ -996,7 +999,9 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* load service specific parameters */ if (conn) { - if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) { + if (!set_current_service(conn,SVAL(inbuf,smb_flg), + (flags & (AS_USER|DO_CHDIR) + ?True:False))) { return(ERROR_DOS(ERRSRV,ERRaccess)); } conn->num_smb_operations++; @@ -1004,17 +1009,19 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* does this protocol need to be run as guest? */ if ((flags & AS_GUEST) - && (!change_to_guest() || + && (!change_to_guest() || !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { return(ERROR_DOS(ERRSRV,ERRaccess)); } - current_inbuf = inbuf; /* In case we need to defer this message in open... */ + current_inbuf = inbuf; /* In case we need to defer this message in + * open... */ outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); done: smb_dump(smb_fn_name(type), 0, outbuf, outsize); + return(outsize); } -- cgit From 530f6a927baae8eb5c8b1b03295c8ff5ddbc70be Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jul 2007 17:13:46 +0000 Subject: r23992: Some const (This used to be commit bc106cf50732ed6c169dcf593797501fcb3ae675) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0062ca18da..f8d3bb8c48 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -207,7 +207,7 @@ NTSTATUS check_path_syntax_posix(char *path) Pull a string and check the path allowing a wilcard - provide for error return. ****************************************************************************/ -size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest, +size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL *contains_wcard) { @@ -248,7 +248,7 @@ size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest, Pull a string and check the path - provide for error return. ****************************************************************************/ -size_t srvstr_get_path(char *inbuf, uint16 smb_flags2, char *dest, +size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err) { -- cgit From 041204d1a4ec9b19287ca92fa5b291a8eb5ff10b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 08:20:44 +0000 Subject: r23996: One more const (This used to be commit a54fa551a4b9ffe3f29b339a54e563cdfe924959) --- source3/smbd/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 02e4cd9663..07dec80a47 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -487,7 +487,7 @@ files_struct *file_fnum(uint16 fnum) Get an fsp from a packet given the offset of a 16 bit fnum. ****************************************************************************/ -files_struct *file_fsp(char *buf, int where) +files_struct *file_fsp(const char *buf, int where) { files_struct *fsp; -- cgit From cc6a41017c577742af73b4bc60993d8d415ea580 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 09:36:09 +0000 Subject: r23997: Check in the infrastructure for getting rid of the global InBuffer/OutBuffer The complete history of this patch can be found under http://www.samba.org/~vlendec/inbuf-checkin/. Jeremy, Jerry: If possible I would like to see this in 3.2.0. I'm only checking into 3_2 at the moment, as it currently will slow down operations for all non-converted (i.e. all at this moment) operations, as it will copy the talloc'ed inbuf over the global InBuffer. It will need quite a bit of effort to convert everything necessary for the normal operations an XP box does. I have patches for negprot, session setup, tcon_and_X, open_and_X, close. More to come, but I would appreciate some help here. Volker (This used to be commit 5594af2b208c860d3f4b453af6a649d9e4295d1c) --- source3/smbd/blocking.c | 2 +- source3/smbd/error.c | 26 ++ source3/smbd/nttrans.c | 6 +- source3/smbd/pipes.c | 6 +- source3/smbd/process.c | 968 +++++++++++++++++++++++++++++------------------ source3/smbd/reply.c | 43 ++- source3/smbd/sesssetup.c | 2 +- 7 files changed, 658 insertions(+), 395 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ed1977e3be..09d16337cd 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -286,7 +286,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); + outsize = chain_reply(inbuf,&outbuf,blr->length,bufsize); outsize += chain_size; diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 12b57d5ab4..d00c61487a 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -131,3 +131,29 @@ int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NT error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } + +void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus, + int line, const char *file) +{ + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file); +} + +void reply_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode, + int line, const char *file) +{ + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + error_packet_set((char *)req->outbuf, eclass, ecode, NT_STATUS_OK, line, + file); +} + +void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode, + NTSTATUS status, int line, const char *file) +{ + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + error_packet_set((char *)req->outbuf, eclass, ecode, status, + line, file); +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 64b6d33eee..e435e1b6fb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -433,7 +433,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname)); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -471,7 +471,7 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - result = chain_reply(inbuf,outbuf,length,bufsize); + result = chain_reply(inbuf,&outbuf,length,bufsize); return result; } @@ -987,7 +987,7 @@ int reply_ntcreate_and_X(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - result = chain_reply(inbuf,outbuf,length,bufsize); + result = chain_reply(inbuf,&outbuf,length,bufsize); END_PROFILE(SMBntcreateX); return result; } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 1ea3e052b2..a6cdc3a989 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -126,7 +126,7 @@ int reply_open_pipe_and_X(connection_struct *conn, SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,0x0001); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -231,7 +231,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -278,7 +278,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* Ensure we set up the message length to include the data length read. */ set_message_bcc(inbuf,outbuf,nread); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 558d403948..4a846e9708 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -23,9 +23,14 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; +const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); + static char *InBuffer = NULL; static char *OutBuffer = NULL; -static char *current_inbuf = NULL; +static const char *current_inbuf = NULL; + +static char *NewInBuffer(char **old_inbuf); +static char *NewOutBuffer(char **old_outbuf); /* * Size of data we can send to client. Set @@ -56,6 +61,10 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) req->smbpid = SVAL(inbuf, smb_pid); req->mid = SVAL(inbuf, smb_mid); req->vuid = SVAL(inbuf, smb_uid); + req->tid = SVAL(inbuf, smb_tid); + req->wct = CVAL(inbuf, smb_wct); + req->inbuf = inbuf; + req->outbuf = NULL; } /**************************************************************************** @@ -70,7 +79,7 @@ static struct pending_message_list *deferred_open_queue; ready for processing. ****************************************************************************/ -static BOOL push_queued_message(char *buf, int msg_len, +static BOOL push_queued_message(const char *buf, int msg_len, struct timeval request_time, struct timeval end_time, char *private_data, size_t private_len) @@ -357,12 +366,14 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds) The timeout is in milliseconds ****************************************************************************/ -static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) +static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, + size_t *buffer_len, int timeout) { fd_set r_fds, w_fds; int selrtn; struct timeval to; int maxfd = 0; + ssize_t len; smb_read_error = 0; @@ -413,8 +424,16 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) } if (pop_message) { - memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length)); - + + *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data, + msg->buf.length); + if (*buffer == NULL) { + DEBUG(0, ("talloc failed\n")); + smb_read_error = READ_ERROR; + return False; + } + *buffer_len = msg->buf.length; + /* We leave this message on the queue so the open code can know this is a retry. */ DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n")); @@ -530,7 +549,15 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) goto again; } - return receive_smb(smbd_server_fd(), buffer, 0); + len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0); + + if (len == -1) { + return False; + } + + *buffer_len = (size_t)len; + + return True; } /* @@ -603,273 +630,301 @@ force write permissions on print services. static const struct smb_message_struct { const char *name; int (*fn)(connection_struct *conn, char *, char *, int, int); + void (*fn_new)(connection_struct *conn, struct smb_request *req); int flags; } smb_messages[256] = { -/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, -/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, -/* 0x02 */ { "SMBopen",reply_open,AS_USER }, -/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER}, -/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC }, -/* 0x05 */ { "SMBflush",reply_flush,AS_USER}, -/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, -/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE }, -/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER}, -/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, -/* 0x0a */ { "SMBread",reply_read,AS_USER}, -/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC }, -/* 0x0c */ { "SMBlock",reply_lock,AS_USER}, -/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER}, -/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER }, -/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, -/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER}, -/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR}, -/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER}, -/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER}, -/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER}, -/* 0x15 */ { NULL, NULL, 0 }, -/* 0x16 */ { NULL, NULL, 0 }, -/* 0x17 */ { NULL, NULL, 0 }, -/* 0x18 */ { NULL, NULL, 0 }, -/* 0x19 */ { NULL, NULL, 0 }, -/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER}, -/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER}, -/* 0x1c */ { "SMBreadBs",NULL,0 }, -/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER}, -/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER}, -/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER}, -/* 0x20 */ { "SMBwritec",NULL,0}, -/* 0x21 */ { NULL, NULL, 0 }, -/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, -/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, -/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER }, -/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC }, -/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC}, -/* 0x27 */ { "SMBioctl",reply_ioctl,0}, -/* 0x28 */ { "SMBioctls",NULL,AS_USER}, -/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE }, -/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE }, -/* 0x2b */ { "SMBecho",reply_echo,0}, -/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER}, -/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC }, -/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, -/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, -/* 0x30 */ { NULL, NULL, 0 }, -/* 0x31 */ { NULL, NULL, 0 }, -/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC }, -/* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER}, -/* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER}, -/* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER}, -/* 0x36 */ { NULL, NULL, 0 }, -/* 0x37 */ { NULL, NULL, 0 }, -/* 0x38 */ { NULL, NULL, 0 }, -/* 0x39 */ { NULL, NULL, 0 }, -/* 0x3a */ { NULL, NULL, 0 }, -/* 0x3b */ { NULL, NULL, 0 }, -/* 0x3c */ { NULL, NULL, 0 }, -/* 0x3d */ { NULL, NULL, 0 }, -/* 0x3e */ { NULL, NULL, 0 }, -/* 0x3f */ { NULL, NULL, 0 }, -/* 0x40 */ { NULL, NULL, 0 }, -/* 0x41 */ { NULL, NULL, 0 }, -/* 0x42 */ { NULL, NULL, 0 }, -/* 0x43 */ { NULL, NULL, 0 }, -/* 0x44 */ { NULL, NULL, 0 }, -/* 0x45 */ { NULL, NULL, 0 }, -/* 0x46 */ { NULL, NULL, 0 }, -/* 0x47 */ { NULL, NULL, 0 }, -/* 0x48 */ { NULL, NULL, 0 }, -/* 0x49 */ { NULL, NULL, 0 }, -/* 0x4a */ { NULL, NULL, 0 }, -/* 0x4b */ { NULL, NULL, 0 }, -/* 0x4c */ { NULL, NULL, 0 }, -/* 0x4d */ { NULL, NULL, 0 }, -/* 0x4e */ { NULL, NULL, 0 }, -/* 0x4f */ { NULL, NULL, 0 }, -/* 0x50 */ { NULL, NULL, 0 }, -/* 0x51 */ { NULL, NULL, 0 }, -/* 0x52 */ { NULL, NULL, 0 }, -/* 0x53 */ { NULL, NULL, 0 }, -/* 0x54 */ { NULL, NULL, 0 }, -/* 0x55 */ { NULL, NULL, 0 }, -/* 0x56 */ { NULL, NULL, 0 }, -/* 0x57 */ { NULL, NULL, 0 }, -/* 0x58 */ { NULL, NULL, 0 }, -/* 0x59 */ { NULL, NULL, 0 }, -/* 0x5a */ { NULL, NULL, 0 }, -/* 0x5b */ { NULL, NULL, 0 }, -/* 0x5c */ { NULL, NULL, 0 }, -/* 0x5d */ { NULL, NULL, 0 }, -/* 0x5e */ { NULL, NULL, 0 }, -/* 0x5f */ { NULL, NULL, 0 }, -/* 0x60 */ { NULL, NULL, 0 }, -/* 0x61 */ { NULL, NULL, 0 }, -/* 0x62 */ { NULL, NULL, 0 }, -/* 0x63 */ { NULL, NULL, 0 }, -/* 0x64 */ { NULL, NULL, 0 }, -/* 0x65 */ { NULL, NULL, 0 }, -/* 0x66 */ { NULL, NULL, 0 }, -/* 0x67 */ { NULL, NULL, 0 }, -/* 0x68 */ { NULL, NULL, 0 }, -/* 0x69 */ { NULL, NULL, 0 }, -/* 0x6a */ { NULL, NULL, 0 }, -/* 0x6b */ { NULL, NULL, 0 }, -/* 0x6c */ { NULL, NULL, 0 }, -/* 0x6d */ { NULL, NULL, 0 }, -/* 0x6e */ { NULL, NULL, 0 }, -/* 0x6f */ { NULL, NULL, 0 }, -/* 0x70 */ { "SMBtcon",reply_tcon,0}, -/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR}, -/* 0x72 */ { "SMBnegprot",reply_negprot,0}, -/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0}, -/* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ -/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0}, -/* 0x76 */ { NULL, NULL, 0 }, -/* 0x77 */ { NULL, NULL, 0 }, -/* 0x78 */ { NULL, NULL, 0 }, -/* 0x79 */ { NULL, NULL, 0 }, -/* 0x7a */ { NULL, NULL, 0 }, -/* 0x7b */ { NULL, NULL, 0 }, -/* 0x7c */ { NULL, NULL, 0 }, -/* 0x7d */ { NULL, NULL, 0 }, -/* 0x7e */ { NULL, NULL, 0 }, -/* 0x7f */ { NULL, NULL, 0 }, -/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER}, -/* 0x81 */ { "SMBsearch",reply_search,AS_USER}, -/* 0x82 */ { "SMBffirst",reply_search,AS_USER}, -/* 0x83 */ { "SMBfunique",reply_search,AS_USER}, -/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER}, -/* 0x85 */ { NULL, NULL, 0 }, -/* 0x86 */ { NULL, NULL, 0 }, -/* 0x87 */ { NULL, NULL, 0 }, -/* 0x88 */ { NULL, NULL, 0 }, -/* 0x89 */ { NULL, NULL, 0 }, -/* 0x8a */ { NULL, NULL, 0 }, -/* 0x8b */ { NULL, NULL, 0 }, -/* 0x8c */ { NULL, NULL, 0 }, -/* 0x8d */ { NULL, NULL, 0 }, -/* 0x8e */ { NULL, NULL, 0 }, -/* 0x8f */ { NULL, NULL, 0 }, -/* 0x90 */ { NULL, NULL, 0 }, -/* 0x91 */ { NULL, NULL, 0 }, -/* 0x92 */ { NULL, NULL, 0 }, -/* 0x93 */ { NULL, NULL, 0 }, -/* 0x94 */ { NULL, NULL, 0 }, -/* 0x95 */ { NULL, NULL, 0 }, -/* 0x96 */ { NULL, NULL, 0 }, -/* 0x97 */ { NULL, NULL, 0 }, -/* 0x98 */ { NULL, NULL, 0 }, -/* 0x99 */ { NULL, NULL, 0 }, -/* 0x9a */ { NULL, NULL, 0 }, -/* 0x9b */ { NULL, NULL, 0 }, -/* 0x9c */ { NULL, NULL, 0 }, -/* 0x9d */ { NULL, NULL, 0 }, -/* 0x9e */ { NULL, NULL, 0 }, -/* 0x9f */ { NULL, NULL, 0 }, -/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, -/* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, -/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC }, -/* 0xa3 */ { NULL, NULL, 0 }, -/* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 }, -/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE }, -/* 0xa6 */ { NULL, NULL, 0 }, -/* 0xa7 */ { NULL, NULL, 0 }, -/* 0xa8 */ { NULL, NULL, 0 }, -/* 0xa9 */ { NULL, NULL, 0 }, -/* 0xaa */ { NULL, NULL, 0 }, -/* 0xab */ { NULL, NULL, 0 }, -/* 0xac */ { NULL, NULL, 0 }, -/* 0xad */ { NULL, NULL, 0 }, -/* 0xae */ { NULL, NULL, 0 }, -/* 0xaf */ { NULL, NULL, 0 }, -/* 0xb0 */ { NULL, NULL, 0 }, -/* 0xb1 */ { NULL, NULL, 0 }, -/* 0xb2 */ { NULL, NULL, 0 }, -/* 0xb3 */ { NULL, NULL, 0 }, -/* 0xb4 */ { NULL, NULL, 0 }, -/* 0xb5 */ { NULL, NULL, 0 }, -/* 0xb6 */ { NULL, NULL, 0 }, -/* 0xb7 */ { NULL, NULL, 0 }, -/* 0xb8 */ { NULL, NULL, 0 }, -/* 0xb9 */ { NULL, NULL, 0 }, -/* 0xba */ { NULL, NULL, 0 }, -/* 0xbb */ { NULL, NULL, 0 }, -/* 0xbc */ { NULL, NULL, 0 }, -/* 0xbd */ { NULL, NULL, 0 }, -/* 0xbe */ { NULL, NULL, 0 }, -/* 0xbf */ { NULL, NULL, 0 }, -/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER}, -/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER}, -/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER}, -/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER}, -/* 0xc4 */ { NULL, NULL, 0 }, -/* 0xc5 */ { NULL, NULL, 0 }, -/* 0xc6 */ { NULL, NULL, 0 }, -/* 0xc7 */ { NULL, NULL, 0 }, -/* 0xc8 */ { NULL, NULL, 0 }, -/* 0xc9 */ { NULL, NULL, 0 }, -/* 0xca */ { NULL, NULL, 0 }, -/* 0xcb */ { NULL, NULL, 0 }, -/* 0xcc */ { NULL, NULL, 0 }, -/* 0xcd */ { NULL, NULL, 0 }, -/* 0xce */ { NULL, NULL, 0 }, -/* 0xcf */ { NULL, NULL, 0 }, -/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST}, -/* 0xd1 */ { "SMBsendb",NULL,AS_GUEST}, -/* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST}, -/* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST}, -/* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST}, -/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST}, -/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST}, -/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST}, -/* 0xd8 */ { NULL, NULL, 0 }, -/* 0xd9 */ { NULL, NULL, 0 }, -/* 0xda */ { NULL, NULL, 0 }, -/* 0xdb */ { NULL, NULL, 0 }, -/* 0xdc */ { NULL, NULL, 0 }, -/* 0xdd */ { NULL, NULL, 0 }, -/* 0xde */ { NULL, NULL, 0 }, -/* 0xdf */ { NULL, NULL, 0 }, -/* 0xe0 */ { NULL, NULL, 0 }, -/* 0xe1 */ { NULL, NULL, 0 }, -/* 0xe2 */ { NULL, NULL, 0 }, -/* 0xe3 */ { NULL, NULL, 0 }, -/* 0xe4 */ { NULL, NULL, 0 }, -/* 0xe5 */ { NULL, NULL, 0 }, -/* 0xe6 */ { NULL, NULL, 0 }, -/* 0xe7 */ { NULL, NULL, 0 }, -/* 0xe8 */ { NULL, NULL, 0 }, -/* 0xe9 */ { NULL, NULL, 0 }, -/* 0xea */ { NULL, NULL, 0 }, -/* 0xeb */ { NULL, NULL, 0 }, -/* 0xec */ { NULL, NULL, 0 }, -/* 0xed */ { NULL, NULL, 0 }, -/* 0xee */ { NULL, NULL, 0 }, -/* 0xef */ { NULL, NULL, 0 }, -/* 0xf0 */ { NULL, NULL, 0 }, -/* 0xf1 */ { NULL, NULL, 0 }, -/* 0xf2 */ { NULL, NULL, 0 }, -/* 0xf3 */ { NULL, NULL, 0 }, -/* 0xf4 */ { NULL, NULL, 0 }, -/* 0xf5 */ { NULL, NULL, 0 }, -/* 0xf6 */ { NULL, NULL, 0 }, -/* 0xf7 */ { NULL, NULL, 0 }, -/* 0xf8 */ { NULL, NULL, 0 }, -/* 0xf9 */ { NULL, NULL, 0 }, -/* 0xfa */ { NULL, NULL, 0 }, -/* 0xfb */ { NULL, NULL, 0 }, -/* 0xfc */ { NULL, NULL, 0 }, -/* 0xfd */ { NULL, NULL, 0 }, -/* 0xfe */ { NULL, NULL, 0 }, -/* 0xff */ { NULL, NULL, 0 } +/* 0x00 */ { "SMBmkdir",reply_mkdir,NULL,AS_USER | NEED_WRITE}, +/* 0x01 */ { "SMBrmdir",reply_rmdir,NULL,AS_USER | NEED_WRITE}, +/* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, +/* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, +/* 0x04 */ { "SMBclose",reply_close,NULL,AS_USER | CAN_IPC }, +/* 0x05 */ { "SMBflush",reply_flush,NULL,AS_USER}, +/* 0x06 */ { "SMBunlink",reply_unlink,NULL,AS_USER | NEED_WRITE }, +/* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE }, +/* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER}, +/* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE}, +/* 0x0a */ { "SMBread",reply_read,NULL,AS_USER}, +/* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC }, +/* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, +/* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, +/* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER }, +/* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER}, +/* 0x10 */ { "SMBcheckpath",reply_checkpath,NULL,AS_USER}, +/* 0x11 */ { "SMBexit",reply_exit,NULL,DO_CHDIR}, +/* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER}, +/* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER}, +/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER}, +/* 0x15 */ { NULL, NULL, NULL, 0 }, +/* 0x16 */ { NULL, NULL, NULL, 0 }, +/* 0x17 */ { NULL, NULL, NULL, 0 }, +/* 0x18 */ { NULL, NULL, NULL, 0 }, +/* 0x19 */ { NULL, NULL, NULL, 0 }, +/* 0x1a */ { "SMBreadbraw",reply_readbraw,NULL,AS_USER}, +/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER}, +/* 0x1c */ { "SMBreadBs",NULL, NULL,0 }, +/* 0x1d */ { "SMBwritebraw",reply_writebraw,NULL,AS_USER}, +/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,NULL,AS_USER}, +/* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER}, +/* 0x20 */ { "SMBwritec",NULL, NULL,0}, +/* 0x21 */ { NULL, NULL, NULL, 0 }, +/* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE }, +/* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER }, +/* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER }, +/* 0x25 */ { "SMBtrans",reply_trans,NULL,AS_USER | CAN_IPC }, +/* 0x26 */ { "SMBtranss",reply_transs,NULL,AS_USER | CAN_IPC}, +/* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0}, +/* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, +/* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE }, +/* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, +/* 0x2b */ { "SMBecho",reply_echo,NULL,0}, +/* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER}, +/* 0x2d */ { "SMBopenX",reply_open_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x2f */ { "SMBwriteX",reply_write_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x30 */ { NULL, NULL, NULL, 0 }, +/* 0x31 */ { NULL, NULL, NULL, 0 }, +/* 0x32 */ { "SMBtrans2", reply_trans2,NULL, AS_USER | CAN_IPC }, +/* 0x33 */ { "SMBtranss2", reply_transs2,NULL, AS_USER}, +/* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER}, +/* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER}, +/* 0x36 */ { NULL, NULL, NULL, 0 }, +/* 0x37 */ { NULL, NULL, NULL, 0 }, +/* 0x38 */ { NULL, NULL, NULL, 0 }, +/* 0x39 */ { NULL, NULL, NULL, 0 }, +/* 0x3a */ { NULL, NULL, NULL, 0 }, +/* 0x3b */ { NULL, NULL, NULL, 0 }, +/* 0x3c */ { NULL, NULL, NULL, 0 }, +/* 0x3d */ { NULL, NULL, NULL, 0 }, +/* 0x3e */ { NULL, NULL, NULL, 0 }, +/* 0x3f */ { NULL, NULL, NULL, 0 }, +/* 0x40 */ { NULL, NULL, NULL, 0 }, +/* 0x41 */ { NULL, NULL, NULL, 0 }, +/* 0x42 */ { NULL, NULL, NULL, 0 }, +/* 0x43 */ { NULL, NULL, NULL, 0 }, +/* 0x44 */ { NULL, NULL, NULL, 0 }, +/* 0x45 */ { NULL, NULL, NULL, 0 }, +/* 0x46 */ { NULL, NULL, NULL, 0 }, +/* 0x47 */ { NULL, NULL, NULL, 0 }, +/* 0x48 */ { NULL, NULL, NULL, 0 }, +/* 0x49 */ { NULL, NULL, NULL, 0 }, +/* 0x4a */ { NULL, NULL, NULL, 0 }, +/* 0x4b */ { NULL, NULL, NULL, 0 }, +/* 0x4c */ { NULL, NULL, NULL, 0 }, +/* 0x4d */ { NULL, NULL, NULL, 0 }, +/* 0x4e */ { NULL, NULL, NULL, 0 }, +/* 0x4f */ { NULL, NULL, NULL, 0 }, +/* 0x50 */ { NULL, NULL, NULL, 0 }, +/* 0x51 */ { NULL, NULL, NULL, 0 }, +/* 0x52 */ { NULL, NULL, NULL, 0 }, +/* 0x53 */ { NULL, NULL, NULL, 0 }, +/* 0x54 */ { NULL, NULL, NULL, 0 }, +/* 0x55 */ { NULL, NULL, NULL, 0 }, +/* 0x56 */ { NULL, NULL, NULL, 0 }, +/* 0x57 */ { NULL, NULL, NULL, 0 }, +/* 0x58 */ { NULL, NULL, NULL, 0 }, +/* 0x59 */ { NULL, NULL, NULL, 0 }, +/* 0x5a */ { NULL, NULL, NULL, 0 }, +/* 0x5b */ { NULL, NULL, NULL, 0 }, +/* 0x5c */ { NULL, NULL, NULL, 0 }, +/* 0x5d */ { NULL, NULL, NULL, 0 }, +/* 0x5e */ { NULL, NULL, NULL, 0 }, +/* 0x5f */ { NULL, NULL, NULL, 0 }, +/* 0x60 */ { NULL, NULL, NULL, 0 }, +/* 0x61 */ { NULL, NULL, NULL, 0 }, +/* 0x62 */ { NULL, NULL, NULL, 0 }, +/* 0x63 */ { NULL, NULL, NULL, 0 }, +/* 0x64 */ { NULL, NULL, NULL, 0 }, +/* 0x65 */ { NULL, NULL, NULL, 0 }, +/* 0x66 */ { NULL, NULL, NULL, 0 }, +/* 0x67 */ { NULL, NULL, NULL, 0 }, +/* 0x68 */ { NULL, NULL, NULL, 0 }, +/* 0x69 */ { NULL, NULL, NULL, 0 }, +/* 0x6a */ { NULL, NULL, NULL, 0 }, +/* 0x6b */ { NULL, NULL, NULL, 0 }, +/* 0x6c */ { NULL, NULL, NULL, 0 }, +/* 0x6d */ { NULL, NULL, NULL, 0 }, +/* 0x6e */ { NULL, NULL, NULL, 0 }, +/* 0x6f */ { NULL, NULL, NULL, 0 }, +/* 0x70 */ { "SMBtcon",reply_tcon,NULL,0}, +/* 0x71 */ { "SMBtdis",reply_tdis,NULL,DO_CHDIR}, +/* 0x72 */ { "SMBnegprot",reply_negprot,NULL,0}, +/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,NULL,0}, +/* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */ +/* 0x75 */ { "SMBtconX",reply_tcon_and_X,NULL,0}, +/* 0x76 */ { NULL, NULL, NULL, 0 }, +/* 0x77 */ { NULL, NULL, NULL, 0 }, +/* 0x78 */ { NULL, NULL, NULL, 0 }, +/* 0x79 */ { NULL, NULL, NULL, 0 }, +/* 0x7a */ { NULL, NULL, NULL, 0 }, +/* 0x7b */ { NULL, NULL, NULL, 0 }, +/* 0x7c */ { NULL, NULL, NULL, 0 }, +/* 0x7d */ { NULL, NULL, NULL, 0 }, +/* 0x7e */ { NULL, NULL, NULL, 0 }, +/* 0x7f */ { NULL, NULL, NULL, 0 }, +/* 0x80 */ { "SMBdskattr",reply_dskattr,NULL,AS_USER}, +/* 0x81 */ { "SMBsearch",reply_search,NULL,AS_USER}, +/* 0x82 */ { "SMBffirst",reply_search,NULL,AS_USER}, +/* 0x83 */ { "SMBfunique",reply_search,NULL,AS_USER}, +/* 0x84 */ { "SMBfclose",reply_fclose,NULL,AS_USER}, +/* 0x85 */ { NULL, NULL, NULL, 0 }, +/* 0x86 */ { NULL, NULL, NULL, 0 }, +/* 0x87 */ { NULL, NULL, NULL, 0 }, +/* 0x88 */ { NULL, NULL, NULL, 0 }, +/* 0x89 */ { NULL, NULL, NULL, 0 }, +/* 0x8a */ { NULL, NULL, NULL, 0 }, +/* 0x8b */ { NULL, NULL, NULL, 0 }, +/* 0x8c */ { NULL, NULL, NULL, 0 }, +/* 0x8d */ { NULL, NULL, NULL, 0 }, +/* 0x8e */ { NULL, NULL, NULL, 0 }, +/* 0x8f */ { NULL, NULL, NULL, 0 }, +/* 0x90 */ { NULL, NULL, NULL, 0 }, +/* 0x91 */ { NULL, NULL, NULL, 0 }, +/* 0x92 */ { NULL, NULL, NULL, 0 }, +/* 0x93 */ { NULL, NULL, NULL, 0 }, +/* 0x94 */ { NULL, NULL, NULL, 0 }, +/* 0x95 */ { NULL, NULL, NULL, 0 }, +/* 0x96 */ { NULL, NULL, NULL, 0 }, +/* 0x97 */ { NULL, NULL, NULL, 0 }, +/* 0x98 */ { NULL, NULL, NULL, 0 }, +/* 0x99 */ { NULL, NULL, NULL, 0 }, +/* 0x9a */ { NULL, NULL, NULL, 0 }, +/* 0x9b */ { NULL, NULL, NULL, 0 }, +/* 0x9c */ { NULL, NULL, NULL, 0 }, +/* 0x9d */ { NULL, NULL, NULL, 0 }, +/* 0x9e */ { NULL, NULL, NULL, 0 }, +/* 0x9f */ { NULL, NULL, NULL, 0 }, +/* 0xa0 */ { "SMBnttrans", reply_nttrans,NULL, AS_USER | CAN_IPC }, +/* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC }, +/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X,NULL, AS_USER | CAN_IPC }, +/* 0xa3 */ { NULL, NULL, NULL, 0 }, +/* 0xa4 */ { "SMBntcancel", reply_ntcancel,NULL, 0 }, +/* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE }, +/* 0xa6 */ { NULL, NULL, NULL, 0 }, +/* 0xa7 */ { NULL, NULL, NULL, 0 }, +/* 0xa8 */ { NULL, NULL, NULL, 0 }, +/* 0xa9 */ { NULL, NULL, NULL, 0 }, +/* 0xaa */ { NULL, NULL, NULL, 0 }, +/* 0xab */ { NULL, NULL, NULL, 0 }, +/* 0xac */ { NULL, NULL, NULL, 0 }, +/* 0xad */ { NULL, NULL, NULL, 0 }, +/* 0xae */ { NULL, NULL, NULL, 0 }, +/* 0xaf */ { NULL, NULL, NULL, 0 }, +/* 0xb0 */ { NULL, NULL, NULL, 0 }, +/* 0xb1 */ { NULL, NULL, NULL, 0 }, +/* 0xb2 */ { NULL, NULL, NULL, 0 }, +/* 0xb3 */ { NULL, NULL, NULL, 0 }, +/* 0xb4 */ { NULL, NULL, NULL, 0 }, +/* 0xb5 */ { NULL, NULL, NULL, 0 }, +/* 0xb6 */ { NULL, NULL, NULL, 0 }, +/* 0xb7 */ { NULL, NULL, NULL, 0 }, +/* 0xb8 */ { NULL, NULL, NULL, 0 }, +/* 0xb9 */ { NULL, NULL, NULL, 0 }, +/* 0xba */ { NULL, NULL, NULL, 0 }, +/* 0xbb */ { NULL, NULL, NULL, 0 }, +/* 0xbc */ { NULL, NULL, NULL, 0 }, +/* 0xbd */ { NULL, NULL, NULL, 0 }, +/* 0xbe */ { NULL, NULL, NULL, 0 }, +/* 0xbf */ { NULL, NULL, NULL, 0 }, +/* 0xc0 */ { "SMBsplopen",reply_printopen,NULL,AS_USER}, +/* 0xc1 */ { "SMBsplwr",reply_printwrite,NULL,AS_USER}, +/* 0xc2 */ { "SMBsplclose",reply_printclose,NULL,AS_USER}, +/* 0xc3 */ { "SMBsplretq",reply_printqueue,NULL,AS_USER}, +/* 0xc4 */ { NULL, NULL, NULL, 0 }, +/* 0xc5 */ { NULL, NULL, NULL, 0 }, +/* 0xc6 */ { NULL, NULL, NULL, 0 }, +/* 0xc7 */ { NULL, NULL, NULL, 0 }, +/* 0xc8 */ { NULL, NULL, NULL, 0 }, +/* 0xc9 */ { NULL, NULL, NULL, 0 }, +/* 0xca */ { NULL, NULL, NULL, 0 }, +/* 0xcb */ { NULL, NULL, NULL, 0 }, +/* 0xcc */ { NULL, NULL, NULL, 0 }, +/* 0xcd */ { NULL, NULL, NULL, 0 }, +/* 0xce */ { NULL, NULL, NULL, 0 }, +/* 0xcf */ { NULL, NULL, NULL, 0 }, +/* 0xd0 */ { "SMBsends",reply_sends,NULL,AS_GUEST}, +/* 0xd1 */ { "SMBsendb",NULL, NULL,AS_GUEST}, +/* 0xd2 */ { "SMBfwdname",NULL, NULL,AS_GUEST}, +/* 0xd3 */ { "SMBcancelf",NULL, NULL,AS_GUEST}, +/* 0xd4 */ { "SMBgetmac",NULL, NULL,AS_GUEST}, +/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,NULL,AS_GUEST}, +/* 0xd6 */ { "SMBsendend",reply_sendend,NULL,AS_GUEST}, +/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,NULL,AS_GUEST}, +/* 0xd8 */ { NULL, NULL, NULL, 0 }, +/* 0xd9 */ { NULL, NULL, NULL, 0 }, +/* 0xda */ { NULL, NULL, NULL, 0 }, +/* 0xdb */ { NULL, NULL, NULL, 0 }, +/* 0xdc */ { NULL, NULL, NULL, 0 }, +/* 0xdd */ { NULL, NULL, NULL, 0 }, +/* 0xde */ { NULL, NULL, NULL, 0 }, +/* 0xdf */ { NULL, NULL, NULL, 0 }, +/* 0xe0 */ { NULL, NULL, NULL, 0 }, +/* 0xe1 */ { NULL, NULL, NULL, 0 }, +/* 0xe2 */ { NULL, NULL, NULL, 0 }, +/* 0xe3 */ { NULL, NULL, NULL, 0 }, +/* 0xe4 */ { NULL, NULL, NULL, 0 }, +/* 0xe5 */ { NULL, NULL, NULL, 0 }, +/* 0xe6 */ { NULL, NULL, NULL, 0 }, +/* 0xe7 */ { NULL, NULL, NULL, 0 }, +/* 0xe8 */ { NULL, NULL, NULL, 0 }, +/* 0xe9 */ { NULL, NULL, NULL, 0 }, +/* 0xea */ { NULL, NULL, NULL, 0 }, +/* 0xeb */ { NULL, NULL, NULL, 0 }, +/* 0xec */ { NULL, NULL, NULL, 0 }, +/* 0xed */ { NULL, NULL, NULL, 0 }, +/* 0xee */ { NULL, NULL, NULL, 0 }, +/* 0xef */ { NULL, NULL, NULL, 0 }, +/* 0xf0 */ { NULL, NULL, NULL, 0 }, +/* 0xf1 */ { NULL, NULL, NULL, 0 }, +/* 0xf2 */ { NULL, NULL, NULL, 0 }, +/* 0xf3 */ { NULL, NULL, NULL, 0 }, +/* 0xf4 */ { NULL, NULL, NULL, 0 }, +/* 0xf5 */ { NULL, NULL, NULL, 0 }, +/* 0xf6 */ { NULL, NULL, NULL, 0 }, +/* 0xf7 */ { NULL, NULL, NULL, 0 }, +/* 0xf8 */ { NULL, NULL, NULL, 0 }, +/* 0xf9 */ { NULL, NULL, NULL, 0 }, +/* 0xfa */ { NULL, NULL, NULL, 0 }, +/* 0xfb */ { NULL, NULL, NULL, 0 }, +/* 0xfc */ { NULL, NULL, NULL, 0 }, +/* 0xfd */ { NULL, NULL, NULL, 0 }, +/* 0xfe */ { NULL, NULL, NULL, 0 }, +/* 0xff */ { NULL, NULL, NULL, 0 } }; +/******************************************************************* + allocate and initialize a reply packet +********************************************************************/ + +void reply_outbuf(struct smb_request *req, uint8 num_words, uint16 num_bytes) +{ + if (!(req->outbuf = TALLOC_ARRAY( + req, uint8, + smb_size + num_words*2 + num_bytes))) { + smb_panic("could not allocate output buffer\n"); + } + + construct_reply_common((char *)req->inbuf, (char *)req->outbuf); + set_message((char *)req->inbuf, (char *)req->outbuf, + num_words, num_bytes, False); + /* + * Zero out the word area, the caller has to take care of the bcc area + * himself + */ + if (num_words != 0) { + memset(req->outbuf + smb_vwv0, 0, num_words*2); + } + + return; +} + + /******************************************************************* Dump a packet to a file. ********************************************************************/ -static void smb_dump(const char *name, int type, char *data, ssize_t len) +static void smb_dump(const char *name, int type, const char *data, ssize_t len) { int fd, i; pstring fname; @@ -891,37 +946,47 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len) } } - /**************************************************************************** - Do a switch on the message type, and return the response size + Prepare everything for calling the actual request function, and potentially + call the request function via the "new" interface. + + Return False if the "legacy" function needs to be called, everything is + prepared. + + Return True if we're done. + + I know this API sucks, but it is the one with the least code change I could + find. ****************************************************************************/ -static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize) +static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, + connection_struct **pconn) { - int outsize = 0; int flags; uint16 session_tag; connection_struct *conn; static uint16 last_session_tag = UID_FIELD_INVALID; - type &= 0xff; - errno = 0; last_message = type; - /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */ - if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) { - DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf))); + /* Make sure this is an SMB packet. smb_size contains NetBIOS header + * so subtract 4 from it. */ + if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0) + || (size < (smb_size - 4))) { + DEBUG(2,("Non-SMB packet of length %d. Terminating server\n", + smb_len(req->inbuf))); exit_server_cleanly("Non-SMB packet"); - return(-1); + return True; } - if (smb_messages[type].fn == NULL) { + if ((smb_messages[type].fn == NULL) + && (smb_messages[type].fn_new == NULL)) { DEBUG(0,("Unknown message type %d!\n",type)); - smb_dump("Unknown", 1, inbuf, size); - outsize = reply_unknown(inbuf,outbuf); + smb_dump("Unknown", 1, (char *)req->inbuf, size); + reply_unknown_new(req, type); goto done; } @@ -929,16 +994,16 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* In share mode security we must ignore the vuid. */ session_tag = (lp_security() == SEC_SHARE) - ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); - conn = conn_find(SVAL(inbuf,smb_tid)); + ? UID_FIELD_INVALID : req->vuid; + conn = conn_find(req->tid); DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type), (int)sys_getpid(), (unsigned long)conn)); - smb_dump(smb_fn_name(type), 1, inbuf, size); + smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size); /* Ensure this value is replaced in the incoming packet. */ - SSVAL(inbuf,smb_uid,session_tag); + SSVAL(req->inbuf,smb_uid,session_tag); /* * Ensure the correct username is in current_user_info. This is a @@ -971,26 +1036,30 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize * (from Samba4). */ if (type == SMBntcreateX) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); } else { - return ERROR_DOS(ERRSRV, ERRinvnid); + reply_doserror(req, ERRSRV, ERRinvnid); } + goto done; } if (!change_to_user(conn,session_tag)) { - return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid))); + reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); + goto done; } /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ /* Does it need write permission? */ if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { - return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED); + reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED); + goto done; } /* IPC services are limited */ if (IS_IPC(conn) && !(flags & CAN_IPC)) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV,ERRaccess); + goto done; } } else { /* This call needs to be run as root */ @@ -999,10 +1068,11 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* load service specific parameters */ if (conn) { - if (!set_current_service(conn,SVAL(inbuf,smb_flg), + if (!set_current_service(conn,SVAL(req->inbuf,smb_flg), (flags & (AS_USER|DO_CHDIR) ?True:False))) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV, ERRaccess); + goto done; } conn->num_smb_operations++; } @@ -1012,15 +1082,72 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize && (!change_to_guest() || !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV, ERRaccess); + goto done; } - current_inbuf = inbuf; /* In case we need to defer this message in - * open... */ - outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); + current_inbuf = (char *)req->inbuf; /* In case we need to defer this + * message in open... */ + + if (smb_messages[type].fn_new != NULL) { + smb_messages[type].fn_new(conn, req); + goto done; + } + + /* + * Indicate the upper layer that there's still work. + */ + *pconn = conn; + return False; done: - smb_dump(smb_fn_name(type), 0, outbuf, outsize); + return True; +} + + +/**************************************************************************** + Do a switch on the message type, and return the response size +****************************************************************************/ + +static int switch_message(uint8 type, struct smb_request *req, char **outbuf, + int size, int bufsize) +{ + int outsize = 0; + connection_struct *conn = NULL; + + if (switch_message_new(type, req, size, &conn)) { + if (req->outbuf != NULL) { + *outbuf = (char *)req->outbuf; + return smb_len(req->outbuf)+4; + } + return -1; + } + + if (InBuffer == NULL) { + DEBUG(1, ("have to alloc InBuffer for %s\n", + smb_fn_name(type))); + if (NewInBuffer(NULL) == NULL) { + smb_panic("Could not allocate InBuffer"); + } + } + + if ((OutBuffer == NULL) && (NewOutBuffer(NULL) == NULL)) { + smb_panic("Could not allocate OutBuffer"); + } + + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, + total_buffer_size); + + memcpy(InBuffer, req->inbuf, MIN(size, total_buffer_size)); + + construct_reply_common(InBuffer, OutBuffer); + + outsize = smb_messages[type].fn(conn, InBuffer, OutBuffer, size, + bufsize); + + smb_dump(smb_fn_name(type), 0, OutBuffer, outsize); + + *outbuf = OutBuffer; return(outsize); } @@ -1029,41 +1156,54 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize Construct a reply to the incoming packet. ****************************************************************************/ -static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) +static void construct_reply(char *inbuf, int size) { - int type = CVAL(inbuf,smb_com); + uint8 type = CVAL(inbuf,smb_com); int outsize = 0; - int msg_type = CVAL(inbuf,0); + struct smb_request *req; + char *outbuf; chain_size = 0; file_chain_reset(); reset_chain_p(); - if (msg_type != 0) - return(reply_special(inbuf,outbuf)); + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + smb_panic("could not allocate smb_request"); + } + init_smb_request(req, (uint8 *)inbuf); - construct_reply_common(inbuf, outbuf); + outsize = switch_message(type, req, &outbuf, size, max_send); - outsize = switch_message(type,inbuf,outbuf,size,bufsize); + if (outsize > 4) { + smb_setlen(inbuf,outbuf,outsize - 4); + } - outsize += chain_size; + if (outsize > 0) { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); - if(outsize > 4) { - smb_setlen(inbuf,outbuf,outsize - 4); + if (outsize != smb_len(outbuf) + 4) { + DEBUG(0,("ERROR: Invalid message response size! " + "%d %d\n", outsize, smb_len(outbuf))); + } else if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server_cleanly("construct_reply: send_smb " + "failed."); + } } - return(outsize); + + TALLOC_FREE(req); + + return; } /**************************************************************************** Process an smb from the client ****************************************************************************/ -static void process_smb(char *inbuf, char *outbuf) +static void process_smb(char *inbuf, size_t nread) { static int trans_num; int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; DO_PROFILE_INC(smb_count); @@ -1082,27 +1222,22 @@ static void process_smb(char *inbuf, char *outbuf) } } - DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, + smb_len(inbuf) ) ); DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); - if (msg_type == 0) - show_msg(inbuf); - else if(msg_type == SMBkeepalive) - return; /* Keepalive packet. */ + if (msg_type != 0) { + /* + * NetBIOS session request, keepalive, etc. + */ + reply_special(inbuf); + return; + } - nread = construct_reply(inbuf,outbuf,nread,max_send); + show_msg(inbuf); + + construct_reply(inbuf,nread); - if(nread > 0) { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); - - if (nread != smb_len(outbuf) + 4) { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } else if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("process_smb: send_smb failed."); - } - } trans_num++; } @@ -1158,18 +1293,23 @@ void construct_reply_common(const char *inbuf, char *outbuf) Construct a chained reply and add it to the already made reply ****************************************************************************/ -int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) +int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) { static char *orig_inbuf; - static char *orig_outbuf; int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); unsigned smb_off2 = SVAL(inbuf,smb_vwv1); - char *inbuf2, *outbuf2; + char *inbuf2; int outsize2; int new_size; char inbuf_saved[smb_wct]; - char outbuf_saved[smb_wct]; - int outsize = smb_len(outbuf) + 4; + char *outbuf = *poutbuf; + size_t outsize = smb_len(outbuf) + 4; + size_t outsize_padded; + size_t ofs, to_move; + + struct smb_request *req; + size_t caller_outputlen; + char *caller_output; /* Maybe its not chained, or it's an error packet. */ if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) { @@ -1180,7 +1320,20 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) if (chain_size == 0) { /* this is the first part of the chain */ orig_inbuf = inbuf; - orig_outbuf = outbuf; + } + + /* + * We need to save the output the caller added to the chain so that we + * can splice it into the final output buffer later. + */ + + caller_outputlen = outsize - smb_wct; + + caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen); + + if (caller_output == NULL) { + /* TODO: NT_STATUS_NO_MEMORY */ + smb_panic("could not dup outbuf"); } /* @@ -1189,27 +1342,25 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) * 4 byte aligned. JRA. */ - outsize = (outsize + 3) & ~3; + outsize_padded = (outsize + 3) & ~3; - /* we need to tell the client where the next part of the reply will be */ - SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - SCVAL(outbuf,smb_vwv0,smb_com2); - - /* remember how much the caller added to the chain, only counting stuff - after the parameter words */ - chain_size += outsize - smb_wct; + /* + * remember how much the caller added to the chain, only counting + * stuff after the parameter words + */ + chain_size += outsize_padded - smb_wct; - /* work out pointers into the original packets. The - headers on these need to be filled in */ + /* + * work out pointers into the original packets. The + * headers on these need to be filled in + */ inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; - outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; /* remember the original command type */ smb_com1 = CVAL(orig_inbuf,smb_com); /* save the data which will be overwritten by the new headers */ memcpy(inbuf_saved,inbuf2,smb_wct); - memcpy(outbuf_saved,outbuf2,smb_wct); /* give the new packet the same header as the last part of the SMB */ memmove(inbuf2,inbuf,smb_wct); @@ -1230,34 +1381,112 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* And set it in the header. */ smb_setlen(inbuf, inbuf2, new_size); - /* create the out buffer */ - construct_reply_common(inbuf2, outbuf2); - DEBUG(3,("Chained message\n")); show_msg(inbuf2); + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + smb_panic("could not allocate smb_request"); + } + init_smb_request(req, (uint8 *)inbuf2); + /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size, - bufsize-chain_size); + outsize2 = switch_message(smb_com2, req, &outbuf, new_size, + bufsize-chain_size); - /* copy the new reply and request headers over the old ones, but - preserve the smb_com field */ - memmove(orig_outbuf,outbuf2,smb_wct); - SCVAL(orig_outbuf,smb_com,smb_com1); + /* + * We don't accept deferred operations in chained requests. + */ + SMB_ASSERT(outsize2 >= smb_wct); - /* restore the saved data, being careful not to overwrite any - data from the reply header */ - memcpy(inbuf2,inbuf_saved,smb_wct); + /* + * Move away the new command output so that caller_output fits in, + * copy in the caller_output saved above. + */ - { - int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) { - ofs = 0; + SMB_ASSERT(outsize_padded >= smb_wct); + + /* + * "ofs" is the space we need for caller_output. Equal to + * caller_outputlen plus the padding. + */ + + ofs = outsize_padded - smb_wct; + + /* + * "to_move" is the amount of bytes the secondary routine gave us + */ + + to_move = outsize2 - smb_wct; + + if (to_move + ofs + smb_wct + chain_size > max_send) { + smb_panic("replies too large -- would have to cut"); + } + + /* + * In the "new" API "outbuf" is allocated via reply_outbuf, just for + * the first request in the chain. So we have to re-allocate it. In + * the "old" API the only outbuf ever used is the global OutBuffer + * which is always large enough. + */ + + if (outbuf != OutBuffer) { + outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char, + to_move + ofs + smb_wct); + if (outbuf == NULL) { + smb_panic("could not realloc outbuf"); } - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); } - return outsize2; + *poutbuf = outbuf; + + memmove(outbuf + smb_wct + ofs, outbuf + smb_wct, to_move); + memcpy(outbuf + smb_wct, caller_output, caller_outputlen); + + /* + * The secondary function has overwritten smb_com + */ + + SCVAL(outbuf, smb_com, smb_com1); + + /* + * We've just copied in the whole "wct" area from the secondary + * function. Fix up the chaining: com2 and the offset need to be + * readjusted. + */ + + SCVAL(outbuf, smb_vwv0, smb_com2); + SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4); + + if (outsize_padded > outsize) { + + /* + * Due to padding we have some uninitialized bytes after the + * caller's output + */ + + memset(outbuf + outsize, 0, outsize_padded - outsize); + } + + smb_setlen(NULL, outbuf, outsize2 + chain_size - 4); + + /* + * restore the saved data, being careful not to overwrite any data + * from the reply header + */ + memcpy(inbuf2,inbuf_saved,smb_wct); + + SAFE_FREE(caller_output); + TALLOC_FREE(req); + + return outsize2 + chain_size; +} + +void chain_reply_new(struct smb_request *req) +{ + chain_reply(CONST_DISCARD(char *, req->inbuf), + (char **)(void *)&req->outbuf, + smb_len(req->inbuf)+4, + smb_len(req->outbuf)+4); } /**************************************************************************** @@ -1450,8 +1679,6 @@ char *get_OutBuffer(void) return OutBuffer; } -const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); - /**************************************************************************** Allocate a new InBuffer. Returns the new and old ones. ****************************************************************************/ @@ -1501,16 +1728,13 @@ void smbd_process(void) time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; - /* Allocate the primary Inbut/Output buffers. */ - - if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) - return; - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); while (True) { int select_timeout = setup_select_timeout(); int num_echos; + char *inbuf; + size_t inbuf_len; errno = 0; @@ -1528,17 +1752,15 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); -#if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); -#endif - - while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { + while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len, + select_timeout)) { if(!timeout_processing(&select_timeout, &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ } + /* * Ensure we do timeout processing if the SMB we just got was * only an echo request. This allows us to set the select @@ -1550,9 +1772,9 @@ void smbd_process(void) */ num_echos = smb_echo_count; - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); + process_smb(inbuf, inbuf_len); - process_smb(InBuffer, OutBuffer); + TALLOC_FREE(inbuf); if (smb_echo_count != num_echos) { if(!timeout_processing( &select_timeout, &last_timeout_processing_time)) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f8d3bb8c48..00e2bf5984 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -284,22 +284,28 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, } /**************************************************************************** - Reply to a special message. + Reply to a (netbios-level) special message. ****************************************************************************/ -int reply_special(char *inbuf,char *outbuf) +void reply_special(char *inbuf) { - int outsize = 4; int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); fstring name1,name2; char name_type = 0; + + /* + * We only really use 4 bytes of the outbuf, but for the smb_setlen + * calculation & friends (send_smb uses that) we need the full smb + * header. + */ + char outbuf[smb_size]; static BOOL already_got_session = False; *name1 = *name2 = 0; - memset(outbuf,'\0',smb_size); + memset(outbuf, '\0', sizeof(outbuf)); smb_setlen(inbuf,outbuf,0); @@ -315,7 +321,7 @@ int reply_special(char *inbuf,char *outbuf) if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { DEBUG(0,("Invalid name length in session request\n")); - return(0); + return; } name_extract(inbuf,4,name1); name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2); @@ -363,13 +369,14 @@ int reply_special(char *inbuf,char *outbuf) case SMBkeepalive: /* session keepalive */ default: - return(0); + return; } DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n", msg_type, msg_flags)); - - return(outsize); + + send_smb(smbd_server_fd(), outbuf); + return; } /**************************************************************************** @@ -613,7 +620,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt TALLOC_FREE(ctx); END_PROFILE(SMBtconX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -631,6 +638,14 @@ int reply_unknown(char *inbuf,char *outbuf) return(ERROR_DOS(ERRSRV,ERRunknownsmb)); } +void reply_unknown_new(struct smb_request *req, uint8 type) +{ + DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n", + smb_fn_name(type), type, type)); + reply_doserror(req, ERRSRV, ERRunknownsmb); + return; +} + /**************************************************************************** Reply to an ioctl. conn POINTER CAN BE NULL HERE ! @@ -1582,7 +1597,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } END_PROFILE(SMBopenX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -1611,7 +1626,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); END_PROFILE(SMBulogoffX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -2813,7 +2828,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); /* Only call chain_reply if not an error. */ if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) { - nread = chain_reply(inbuf,outbuf,length,bufsize); + nread = chain_reply(inbuf,&outbuf,length,bufsize); } END_PROFILE(SMBreadX); @@ -3254,7 +3269,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng } END_PROFILE(SMBwriteX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -5722,7 +5737,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); END_PROFILE(SMBlockingX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } #undef DBGC_CLASS diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 320d283575..eb0d7b3e12 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1582,5 +1582,5 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, done_sesssetup = True; END_PROFILE(SMBsesssetupX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } -- cgit From 47cdfc0413886780f51fb98b7fca18d7c83b7c23 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 09:53:06 +0000 Subject: r23998: Convert reply_close to the new API (This used to be commit dbf74cb747d34dac571d85d6bae9398558086456) --- source3/smbd/pipes.c | 14 ++++++++------ source3/smbd/process.c | 2 +- source3/smbd/reply.c | 31 +++++++++++++++++++------------ 3 files changed, 28 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index a6cdc3a989..cb1461478a 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -285,22 +285,24 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) Reply to a close. ****************************************************************************/ -int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) +void reply_pipe_close(connection_struct *conn, struct smb_request *req) { - smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); - int outsize = set_message(inbuf,outbuf,0,0,True); + smb_np_struct *p = get_rpc_pipe_p((char *)req->inbuf,smb_vwv0); if (!p) { - return(ERROR_DOS(ERRDOS,ERRbadfid)); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum)); if (!close_rpc_pipe_hnd(p)) { - return ERROR_DOS(ERRDOS,ERRbadfid); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } /* TODO: REMOVE PIPE FROM DB */ - return(outsize); + reply_outbuf(req, 0, 0); + return; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4a846e9708..f40caa49ad 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -638,7 +638,7 @@ static const struct smb_message_struct { /* 0x01 */ { "SMBrmdir",reply_rmdir,NULL,AS_USER | NEED_WRITE}, /* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, /* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, -/* 0x04 */ { "SMBclose",reply_close,NULL,AS_USER | CAN_IPC }, +/* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, /* 0x05 */ { "SMBflush",reply_flush,NULL,AS_USER}, /* 0x06 */ { "SMBunlink",reply_unlink,NULL,AS_USER | NEED_WRITE }, /* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 00e2bf5984..98a2f6ee5e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3402,31 +3402,35 @@ int reply_exit(connection_struct *conn, Reply to a close - has to deal with closing a directory opened by NT SMB's. ****************************************************************************/ -int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, - int dum_buffsize) +void reply_close(connection_struct *conn, struct smb_request *req) { NTSTATUS status = NT_STATUS_OK; - int outsize = 0; files_struct *fsp = NULL; START_PROFILE(SMBclose); - outsize = set_message(inbuf,outbuf,0,0,False); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBclose); + return; + } /* If it's an IPC, pass off to the pipe handler. */ if (IS_IPC(conn)) { + reply_pipe_close(conn, req); END_PROFILE(SMBclose); - return reply_pipe_close(conn, inbuf,outbuf); + return; } - fsp = file_fsp(inbuf,smb_vwv0); + fsp = file_fsp((char *)req->inbuf,smb_vwv0); /* * We can only use CHECK_FSP if we know it's not a directory. */ if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) { + reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBclose); - return ERROR_DOS(ERRDOS,ERRbadfid); + return; } if(fsp->is_directory) { @@ -3448,8 +3452,9 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Take care of any time sent in the close. */ - fsp_set_pending_modtime(fsp, - convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1))); + fsp_set_pending_modtime(fsp, convert_time_t_to_timespec( + srv_make_unix_date3( + req->inbuf+smb_vwv1))); /* * close_file() returns the unix errno if an error @@ -3460,13 +3465,15 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, status = close_file(fsp,NORMAL_CLOSE); } - if(!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBclose); - return ERROR_NT(status); + return; } + reply_outbuf(req, 0, 0); END_PROFILE(SMBclose); - return(outsize); + return; } /**************************************************************************** -- cgit From 9e40557047b32dae012b0b5a3450c2c23b7895e5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 09:54:36 +0000 Subject: r23999: Convert reply_open_and_X This is an example of chained code that is executed in make test (This used to be commit e3a10e9ffb06f429208f8b8e8482bbfd56dace91) --- source3/smbd/pipes.c | 47 ++++++++++-------- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 127 ++++++++++++++++++++++++++++++------------------- 3 files changed, 105 insertions(+), 71 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index cb1461478a..a4ac807377 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -53,25 +53,24 @@ extern struct pipe_id_info pipe_names[]; wrinkles to handle pipes. ****************************************************************************/ -int reply_open_pipe_and_X(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) { pstring fname; pstring pipe_name; - uint16 vuid = SVAL(inbuf, smb_uid); smb_np_struct *p; int size=0,fmode=0,mtime=0,rmode=0; int i; /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), pipe_name, - smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE); + srvstr_pull_buf(req->inbuf, req->flags2, pipe_name, + smb_buf(req->inbuf), sizeof(pipe_name), STR_TERMINATE); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV, ERRaccess); + return; } DEBUG(4,("Opening pipe %s.\n", pipe_name)); @@ -84,7 +83,9 @@ int reply_open_pipe_and_X(connection_struct *conn, } if (pipe_names[i].client_pipe == NULL) { - return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpipe); + return; } /* Strip \PIPE\ off the name. */ @@ -94,39 +95,43 @@ int reply_open_pipe_and_X(connection_struct *conn, /* * Hack for NT printers... JRA. */ - if(should_fail_next_srvsvc_open(fname)) - return(ERROR(ERRSRV,ERRaccess)); + if(should_fail_next_srvsvc_open(fname)) { + reply_doserror(req, ERRSRV, ERRaccess); + return; + } #endif /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); - p = open_rpc_pipe_p(fname, conn, vuid); + p = open_rpc_pipe_p(fname, conn, req->vuid); if (!p) { - return(ERROR_DOS(ERRSRV,ERRnofids)); + reply_doserror(req, ERRSRV, ERRnofids); + return; } /* Prepare the reply */ - set_message(inbuf,outbuf,15,0,True); + reply_outbuf(req, 15, 0); /* Mark the opened file as an existing named pipe in message mode. */ - SSVAL(outbuf,smb_vwv9,2); - SSVAL(outbuf,smb_vwv10,0xc700); + SSVAL(req->outbuf,smb_vwv9,2); + SSVAL(req->outbuf,smb_vwv10,0xc700); if (rmode == 2) { DEBUG(4,("Resetting open result to open from create.\n")); rmode = 1; } - SSVAL(outbuf,smb_vwv2, p->pnum); - SSVAL(outbuf,smb_vwv3,fmode); - srv_put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,size); - SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,0x0001); + SSVAL(req->outbuf,smb_vwv2, p->pnum); + SSVAL(req->outbuf,smb_vwv3,fmode); + srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime); + SIVAL(req->outbuf,smb_vwv6,size); + SSVAL(req->outbuf,smb_vwv8,rmode); + SSVAL(req->outbuf,smb_vwv11,0x0001); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); + return; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f40caa49ad..ea8f37563b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -679,7 +679,7 @@ static const struct smb_message_struct { /* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, /* 0x2b */ { "SMBecho",reply_echo,NULL,0}, /* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER}, -/* 0x2d */ { "SMBopenX",reply_open_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC }, /* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC }, /* 0x2f */ { "SMBwriteX",reply_write_and_X,NULL,AS_USER | CAN_IPC }, /* 0x30 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 98a2f6ee5e..9eca450dc4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1423,78 +1423,98 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, Reply to an open and X. ****************************************************************************/ -int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +void reply_open_and_X(connection_struct *conn, struct smb_request *req) { pstring fname; - uint16 open_flags = SVAL(inbuf,smb_vwv2); - int deny_mode = SVAL(inbuf,smb_vwv3); - uint32 smb_attr = SVAL(inbuf,smb_vwv5); + uint16 open_flags; + int deny_mode; + uint32 smb_attr; /* Breakout the oplock request bits so we can set the reply bits separately. */ - int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); - int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); - int oplock_request = ex_oplock_request | core_oplock_request; + int ex_oplock_request; + int core_oplock_request; + int oplock_request; #if 0 - int smb_sattr = SVAL(inbuf,smb_vwv4); - uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); + int smb_sattr = SVAL(req->inbuf,smb_vwv4); + uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6); #endif - int smb_ofun = SVAL(inbuf,smb_vwv8); + int smb_ofun; uint32 fattr=0; int mtime=0; SMB_STRUCT_STAT sbuf; int smb_action = 0; files_struct *fsp; NTSTATUS status; - SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9); + SMB_BIG_UINT allocation_size; ssize_t retval = -1; uint32 access_mask; uint32 share_mode; uint32 create_disposition; uint32 create_options = 0; - struct smb_request req; START_PROFILE(SMBopenX); - init_smb_request(&req, (uint8 *)inbuf); + if (req->wct < 15) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBopenX); + return; + } + + open_flags = SVAL(req->inbuf,smb_vwv2); + deny_mode = SVAL(req->inbuf,smb_vwv3); + smb_attr = SVAL(req->inbuf,smb_vwv5); + ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf); + core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); + oplock_request = ex_oplock_request | core_oplock_request; + smb_ofun = SVAL(req->inbuf,smb_vwv8); + allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9); /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { - END_PROFILE(SMBopenX); - return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); + reply_open_pipe_and_X(conn, req); } else { - END_PROFILE(SMBopenX); - return ERROR_DOS(ERRSRV,ERRaccess); + reply_doserror(req, ERRSRV, ERRaccess); } + END_PROFILE(SMBopenX); + return; } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf), - sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path((char *)req->inbuf, req->flags2, fname, + smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBopenX); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBopenX); - return ERROR_NT(status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBopenX); - return ERROR_NT(status); + return; } if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun, @@ -1502,11 +1522,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt &share_mode, &create_disposition, &create_options)) { + reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); END_PROFILE(SMBopenX); - return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); + return; } - status = open_file_ntcreate(conn, &req, fname, &sbuf, + status = open_file_ntcreate(conn, req, fname, &sbuf, access_mask, share_mode, create_disposition, @@ -1517,11 +1538,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size, @@ -1530,14 +1552,16 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,ERROR_CLOSE); + reply_nterror(req, NT_STATUS_DISK_FULL); END_PROFILE(SMBopenX); - return ERROR_NT(NT_STATUS_DISK_FULL); + return; } retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size); if (retval < 0) { close_file(fsp,ERROR_CLOSE); + reply_nterror(req, NT_STATUS_DISK_FULL); END_PROFILE(SMBopenX); - return ERROR_NT(NT_STATUS_DISK_FULL); + return; } sbuf.st_size = get_allocation_size(conn,fsp,&sbuf); } @@ -1546,8 +1570,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt mtime = sbuf.st_mtime; if (fattr & aDIR) { close_file(fsp,ERROR_CLOSE); + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBopenX); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } /* If the caller set the extended oplock request bit @@ -1568,36 +1593,40 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt correct bit for core oplock reply. */ + if (open_flags & EXTENDED_RESPONSE_REQUIRED) { + reply_outbuf(req, 19, 0); + } else { + reply_outbuf(req, 15, 0); + } + if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf, smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf, smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - if (open_flags & EXTENDED_RESPONSE_REQUIRED) { - set_message(inbuf,outbuf,19,0,True); - } else { - set_message(inbuf,outbuf,15,0,True); - } - SSVAL(outbuf,smb_vwv2,fsp->fnum); - SSVAL(outbuf,smb_vwv3,fattr); + SSVAL(req->outbuf,smb_vwv2,fsp->fnum); + SSVAL(req->outbuf,smb_vwv3,fattr); if(lp_dos_filetime_resolution(SNUM(conn)) ) { - srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1); + srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1); } else { - srv_put_dos_date3(outbuf,smb_vwv4,mtime); + srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime); } - SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); - SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode)); - SSVAL(outbuf,smb_vwv11,smb_action); + SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size); + SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode)); + SSVAL(req->outbuf,smb_vwv11,smb_action); if (open_flags & EXTENDED_RESPONSE_REQUIRED) { - SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS); + SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS); } END_PROFILE(SMBopenX); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); + return; } /**************************************************************************** -- cgit From 944fe69d03f1fcd6ab680fcb672d06036f89f251 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 10:52:39 +0000 Subject: r24000: Add message_push_blob() and message_push_string(). The proposed new API convention is to start with a 0 bcc length and then push things step by step. These routines reallocate the outbuf and adjust the length and bcc fields as necessary. (This used to be commit 624f1fe4f6e022d73e78fa8c9646f6f64035f3ee) --- source3/smbd/srvstr.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 4462a423c8..1daa25553f 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -41,3 +41,43 @@ size_t srvstr_push_fn(const char *function, unsigned int line, /* 'normal' push into size-specified buffer */ return push_string_fn(function, line, base_ptr, dest, src, dest_len, flags); } + +/******************************************************************* + Add a string to the end of a smb_buf, adjusting bcc and smb_len. + Return the bytes added +********************************************************************/ + +ssize_t message_push_string(uint8 **outbuf, const char *str, int flags) +{ + size_t buf_size = smb_len(*outbuf) + 4; + size_t grow_size; + size_t result; + uint8 *tmp; + + /* + * We need to over-allocate, now knowing what srvstr_push will + * actually use. This is very generous by incorporating potential + * padding, the terminating 0 and at most 4 chars per UTF-16 code + * point. + */ + grow_size = (strlen(str) + 2) * 4; + + if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, + buf_size + grow_size))) { + DEBUG(0, ("talloc failed\n")); + return -1; + } + + result = srvstr_push((char *)tmp, tmp + buf_size, str, grow_size, + flags); + + if (result == (size_t)-1) { + DEBUG(0, ("srvstr_push failed\n")); + return -1; + } + set_message_bcc(NULL, (char *)tmp, smb_buflen(tmp) + result); + + *outbuf = tmp; + + return result; +} -- cgit From de1c9f1f6d36282fc6d1a7f25a7d79b74a081160 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 11:08:43 +0000 Subject: r24001: Separate out the parsing of the client's requested protocols This way the range checking only needs to be done once (This used to be commit befaa9713adec90088eedcf264f1e396ab150d25) --- source3/smbd/negprot.c | 95 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 4a9492a766..4e3d8f1b3e 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -481,16 +481,17 @@ static const struct { ****************************************************************************/ int reply_negprot(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, + char *inbuf,char *outbuf, int size, int dum_buffsize) { int outsize = set_message(inbuf,outbuf,1,0,True); - int Index=0; int choice= -1; int protocol; char *p; - int bcc = SVAL(smb_buf(inbuf),-2); int arch = ARCH_ALL; + int num_cliprotos; + char **cliprotos; + int i; static BOOL done_negprot = False; @@ -502,41 +503,78 @@ int reply_negprot(connection_struct *conn, } done_negprot = True; + if (inbuf[size-1] != '\0') { + DEBUG(0, ("negprot protocols not 0-terminated\n")); + END_PROFILE(SMBnegprot); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + p = smb_buf(inbuf)+1; - while (p < (smb_buf(inbuf) + bcc)) { - Index++; - DEBUG(3,("Requested protocol [%s]\n",p)); - if (strcsequal(p,"Windows for Workgroups 3.1a")) - arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); - else if (strcsequal(p,"DOS LM1.2X002")) + + num_cliprotos = 0; + cliprotos = NULL; + + while (smb_bufrem(inbuf, p) > 0) { + char **tmp; + + tmp = TALLOC_REALLOC_ARRAY(tmp_talloc_ctx(), cliprotos, char *, + num_cliprotos+1); + if (tmp == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(cliprotos); + END_PROFILE(SMBnegprot); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + cliprotos = tmp; + + if (pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p) + == (size_t)-1) { + DEBUG(0, ("pull_ascii_talloc failed\n")); + TALLOC_FREE(cliprotos); + END_PROFILE(SMBnegprot); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + DEBUG(3, ("Requested protocol [%s]\n", + cliprotos[num_cliprotos])); + + num_cliprotos += 1; + p += strlen(p) + 2; + } + + for (i=0; i= lp_minprotocol())) - while (p < (smb_buf(inbuf) + bcc)) { - if (strequal(p,supported_protocols[protocol].proto_name)) - choice = Index; - Index++; - p += strlen(p) + 2; + while (i < num_cliprotos) { + if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) + choice = i; + i++; } if(choice != -1) break; @@ -620,6 +656,7 @@ int reply_negprot(connection_struct *conn, "client negotiated a downlevel protocol"); } + TALLOC_FREE(cliprotos); END_PROFILE(SMBnegprot); return(outsize); } -- cgit From 3d12c53eb3bf5506b0661fbcaa0d36f90f847c65 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 11:18:20 +0000 Subject: r24002: Convert reply_negprot to the new API (This used to be commit bd981f53282573058bf4c2939e0e836499cf38be) --- source3/smbd/negprot.c | 204 +++++++++++++++++++++++++++---------------------- source3/smbd/process.c | 2 +- 2 files changed, 115 insertions(+), 91 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 4e3d8f1b3e..61be2e8f9a 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -27,7 +27,7 @@ BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; struct auth_context *negprot_global_auth_context = NULL; -static void get_challenge(char buff[8]) +static void get_challenge(uint8 buff[8]) { NTSTATUS nt_status; const uint8 *cryptkey; @@ -53,39 +53,39 @@ static void get_challenge(char buff[8]) Reply for the core protocol. ****************************************************************************/ -static int reply_corep(char *inbuf, char *outbuf) +static void reply_corep(struct smb_request *req, uint16 choice) { - int outsize = set_message(inbuf,outbuf,1,0,True); + reply_outbuf(req, 1, 0); + SSVAL(req->outbuf, smb_vwv0, choice); Protocol = PROTOCOL_CORE; - - return outsize; } /**************************************************************************** Reply for the coreplus protocol. ****************************************************************************/ -static int reply_coreplus(char *inbuf, char *outbuf) +static void reply_coreplus(struct smb_request *req, uint16 choice) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int outsize = set_message(inbuf,outbuf,13,0,True); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support + + reply_outbuf(req, 13, 0); + + SSVAL(req->outbuf,smb_vwv0,choice); + SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support readbraw and writebraw (possibly) */ /* Reply, SMBlockread, SMBwritelock supported. */ - SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */ - + SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); + SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't + * encrypt */ Protocol = PROTOCOL_COREPLUS; - - return outsize; } /**************************************************************************** Reply for the lanman 1.0 protocol. ****************************************************************************/ -static int reply_lanman1(char *inbuf, char *outbuf) +static void reply_lanman1(struct smb_request *req, uint16 choice) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; @@ -98,36 +98,38 @@ static int reply_lanman1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; - set_message(inbuf,outbuf,13,global_encrypted_passwords_negotiated?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); + reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0); + + SSVAL(req->outbuf,smb_vwv0,choice); + SSVAL(req->outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - get_challenge(smb_buf(outbuf)); - SSVAL(outbuf,smb_vwv11, 8); + get_challenge((uint8 *)smb_buf(req->outbuf)); + SSVAL(req->outbuf,smb_vwv11, 8); } Protocol = PROTOCOL_LANMAN1; /* Reply, SMBlockread, SMBwritelock supported. */ - SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support + SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); + SSVAL(req->outbuf,smb_vwv2,max_recv); + SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ + SSVAL(req->outbuf,smb_vwv4,1); + SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support readbraw writebraw (possibly) */ - SIVAL(outbuf,smb_vwv6,sys_getpid()); - SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60); + SIVAL(req->outbuf,smb_vwv6,sys_getpid()); + SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60); - srv_put_dos_date(outbuf,smb_vwv8,t); + srv_put_dos_date((char *)req->outbuf,smb_vwv8,t); - return (smb_len(outbuf)+4); + return; } /**************************************************************************** Reply for the lanman 2.0 protocol. ****************************************************************************/ -static int reply_lanman2(char *inbuf, char *outbuf) +static void reply_lanman2(struct smb_request *req, uint16 choice) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; @@ -140,28 +142,28 @@ static int reply_lanman2(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; - set_message(inbuf,outbuf,13,global_encrypted_passwords_negotiated?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); - SIVAL(outbuf,smb_vwv6,sys_getpid()); + reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0); + + SSVAL(req->outbuf,smb_vwv0,choice); + SSVAL(req->outbuf,smb_vwv1,secword); + SIVAL(req->outbuf,smb_vwv6,sys_getpid()); /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - get_challenge(smb_buf(outbuf)); - SSVAL(outbuf,smb_vwv11, 8); + get_challenge((uint8 *)smb_buf(req->outbuf)); + SSVAL(req->outbuf,smb_vwv11, 8); } Protocol = PROTOCOL_LANMAN2; /* Reply, SMBlockread, SMBwritelock supported. */ - SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ - SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60); - srv_put_dos_date(outbuf,smb_vwv8,t); - - return (smb_len(outbuf)+4); + SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); + SSVAL(req->outbuf,smb_vwv2,max_recv); + SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); + SSVAL(req->outbuf,smb_vwv4,1); + SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ + SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60); + srv_put_dos_date((char *)req->outbuf,smb_vwv8,t); } /**************************************************************************** @@ -242,7 +244,7 @@ static DATA_BLOB negprot_spnego(void) Reply for the nt protocol. ****************************************************************************/ -static int reply_nt1(char *inbuf, char *outbuf) +static void reply_nt1(struct smb_request *req, uint16 choice) { /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| @@ -252,6 +254,7 @@ static int reply_nt1(char *inbuf, char *outbuf) char *p, *q; BOOL negotiate_spnego = False; time_t t = time(NULL); + ssize_t ret; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); @@ -259,27 +262,30 @@ static int reply_nt1(char *inbuf, char *outbuf) WinXP sets it and Vista does not. But we have to distinguish from NT which doesn't set it either. */ - if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) && - ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) ) + if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) && + ((req->flags2 & FLAGS2_UNKNOWN_BIT4) == 0) ) { if (get_remote_arch() != RA_SAMBA) { set_remote_arch( RA_VISTA ); } } + reply_outbuf(req,17,0); + /* do spnego in user level security if the client supports it and we can do encrypted passwords */ if (global_encrypted_passwords_negotiated && (lp_security() != SEC_SHARE) && lp_use_spnego() && - (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { + (req->flags2 & FLAGS2_EXTENDED_SECURITY)) { negotiate_spnego = True; capabilities |= CAP_EXTENDED_SECURITY; add_to_common_flags2(FLAGS2_EXTENDED_SECURITY); - /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already - partially constructed. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY); + /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply + (already partially constructed. */ + SSVAL(req->outbuf, smb_flg2, + req->flags2 | FLAGS2_EXTENDED_SECURITY); } capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE; @@ -324,53 +330,72 @@ static int reply_nt1(char *inbuf, char *outbuf) } } - set_message(inbuf,outbuf,17,0,True); - - SCVAL(outbuf,smb_vwv1,secword); + SSVAL(req->outbuf,smb_vwv0,choice); + SCVAL(req->outbuf,smb_vwv1,secword); Protocol = PROTOCOL_NT1; - SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ - SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ - SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */ - SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ - SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */ - SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ - put_long_date(outbuf+smb_vwv11+1,t); - SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60); + SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ + SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */ + SIVAL(req->outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */ + SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ + SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */ + SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */ + put_long_date((char *)req->outbuf+smb_vwv11+1,t); + SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(t)/60); - p = q = smb_buf(outbuf); + p = q = smb_buf(req->outbuf); if (!negotiate_spnego) { /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { + uint8 chal[8]; /* note that we do not send a challenge at all if we are using plaintext */ - get_challenge(p); - SCVAL(outbuf,smb_vwv16+1,8); - p += 8; + get_challenge(chal); + ret = message_push_blob( + &req->outbuf, data_blob_const(chal, sizeof(chal))); + if (ret == -1) { + DEBUG(0, ("Could not push challenge\n")); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + SCVAL(req->outbuf, smb_vwv16+1, ret); + p += ret; + } + ret = message_push_string(&req->outbuf, lp_workgroup(), + STR_UNICODE|STR_TERMINATE + |STR_NOALIGN); + if (ret == -1) { + DEBUG(0, ("Could not push challenge\n")); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } - p += srvstr_push(outbuf, p, lp_workgroup(), -1, - STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); } else { DATA_BLOB spnego_blob = negprot_spnego(); if (spnego_blob.data == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } - memcpy(p, spnego_blob.data, spnego_blob.length); - p += spnego_blob.length; + ret = message_push_blob(&req->outbuf, spnego_blob); + if (ret == -1) { + DEBUG(0, ("Could not push spnego blob\n")); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + p += ret; data_blob_free(&spnego_blob); - SCVAL(outbuf,smb_vwv16+1, 0); + SCVAL(req->outbuf,smb_vwv16+1, 0); DEBUG(3,("using SPNEGO\n")); } - SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */ - set_message_end(inbuf,outbuf, p); - - return (smb_len(outbuf)+4); + SSVAL(req->outbuf,smb_vwv17, p - q); /* length of challenge+domain + * strings */ + + return; } /* these are the protocol lists used for auto architecture detection: @@ -458,7 +483,7 @@ protocol [LANMAN2.1] static const struct { const char *proto_name; const char *short_name; - int (*proto_reply_fn)(char *, char *); + void (*proto_reply_fn)(struct smb_request *req, uint16 choice); int protocol_level; } supported_protocols[] = { {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, @@ -480,11 +505,9 @@ static const struct { conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_negprot(connection_struct *conn, - char *inbuf,char *outbuf, int size, - int dum_buffsize) +void reply_negprot(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,1,0,True); + size_t size = smb_len(req->inbuf) + 4; int choice= -1; int protocol; char *p; @@ -503,18 +526,19 @@ int reply_negprot(connection_struct *conn, } done_negprot = True; - if (inbuf[size-1] != '\0') { + if (req->inbuf[size-1] != '\0') { DEBUG(0, ("negprot protocols not 0-terminated\n")); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnegprot); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } - p = smb_buf(inbuf)+1; + p = smb_buf(req->inbuf)+1; num_cliprotos = 0; cliprotos = NULL; - while (smb_bufrem(inbuf, p) > 0) { + while (smb_bufrem(req->inbuf, p) > 0) { char **tmp; tmp = TALLOC_REALLOC_ARRAY(tmp_talloc_ctx(), cliprotos, char *, @@ -522,8 +546,9 @@ int reply_negprot(connection_struct *conn, if (tmp == NULL) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(cliprotos); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBnegprot); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return; } cliprotos = tmp; @@ -532,8 +557,9 @@ int reply_negprot(connection_struct *conn, == (size_t)-1) { DEBUG(0, ("pull_ascii_talloc failed\n")); TALLOC_FREE(cliprotos); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBnegprot); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return; } DEBUG(3, ("Requested protocol [%s]\n", @@ -592,7 +618,7 @@ int reply_negprot(connection_struct *conn, set_remote_arch(RA_WIN95); break; case ARCH_WINNT: - if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE) + if(req->flags2 == FLAGS2_WIN2K_SIGNATURE) set_remote_arch(RA_WIN2K); else set_remote_arch(RA_WINNT); @@ -638,16 +664,14 @@ int reply_negprot(connection_struct *conn, break; } - SSVAL(outbuf,smb_vwv0,choice); if(choice != -1) { fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(True); - outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf); + supported_protocols[protocol].proto_reply_fn(req, choice); DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { DEBUG(0,("No protocol supported !\n")); } - SSVAL(outbuf,smb_vwv0,choice); DEBUG( 5, ( "negprot index=%d\n", choice ) ); @@ -658,5 +682,5 @@ int reply_negprot(connection_struct *conn, TALLOC_FREE(cliprotos); END_PROFILE(SMBnegprot); - return(outsize); + return; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ea8f37563b..5d37b43321 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -748,7 +748,7 @@ static const struct smb_message_struct { /* 0x6f */ { NULL, NULL, NULL, 0 }, /* 0x70 */ { "SMBtcon",reply_tcon,NULL,0}, /* 0x71 */ { "SMBtdis",reply_tdis,NULL,DO_CHDIR}, -/* 0x72 */ { "SMBnegprot",reply_negprot,NULL,0}, +/* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0}, /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,NULL,0}, /* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */ /* 0x75 */ { "SMBtconX",reply_tcon_and_X,NULL,0}, -- cgit From db9f25c1c58cbf17b5b94d598126b019d9e7507e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 11:38:29 +0000 Subject: r24003: Convert reply_tcon_and_X to the new API (This used to be commit 9422385d9c018a0b1f2a0b2edd82dc574a9fb403) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 116 ++++++++++++++++++++++++++++++------------------- 2 files changed, 73 insertions(+), 45 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5d37b43321..2cc8b3976b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -751,7 +751,7 @@ static const struct smb_message_struct { /* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0}, /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,NULL,0}, /* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */ -/* 0x75 */ { "SMBtconX",reply_tcon_and_X,NULL,0}, +/* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,0}, /* 0x76 */ { NULL, NULL, NULL, 0 }, /* 0x77 */ { NULL, NULL, NULL, 0 }, /* 0x78 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9eca450dc4..725dd416f2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -458,7 +458,7 @@ int reply_tcon(connection_struct *conn, conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) { char *service = NULL; DATA_BLOB password; @@ -469,53 +469,67 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* what the server tells the client the share represents */ const char *server_devicetype; NTSTATUS nt_status; - uint16 vuid = SVAL(inbuf,smb_uid); - int passlen = SVAL(inbuf,smb_vwv3); + int passlen; char *path = NULL; char *p, *q; - uint16 tcon_flags = SVAL(inbuf,smb_vwv2); + uint16 tcon_flags; START_PROFILE(SMBtconX); + if (req->wct < 4) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBtconX); + return; + } + + passlen = SVAL(req->inbuf,smb_vwv3); + tcon_flags = SVAL(req->inbuf,smb_vwv2); + /* we might have to close an old one */ - if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { - close_cnum(conn,vuid); + if ((tcon_flags & 0x1) && conn) { + close_cnum(conn,req->vuid); } - if (passlen > MAX_PASS_LEN) { - return ERROR_DOS(ERRDOS,ERRbuftoosmall); + if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) { + reply_doserror(req, ERRDOS, ERRbuftoosmall); + END_PROFILE(SMBtconX); + return; } if (global_encrypted_passwords_negotiated) { - password = data_blob(smb_buf(inbuf),passlen); + password = data_blob(smb_buf(req->inbuf),passlen); if (lp_security() == SEC_SHARE) { /* * Security = share always has a pad byte * after the password. */ - p = smb_buf(inbuf) + passlen + 1; + p = smb_buf(req->inbuf) + passlen + 1; } else { - p = smb_buf(inbuf) + passlen; + p = smb_buf(req->inbuf) + passlen; } } else { - password = data_blob(smb_buf(inbuf),passlen+1); + password = data_blob(smb_buf(req->inbuf),passlen+1); /* Ensure correct termination */ password.data[passlen]=0; - p = smb_buf(inbuf) + passlen + 1; + p = smb_buf(req->inbuf) + passlen + 1; } ctx = talloc_init("reply_tcon_and_X"); if (!ctx) { + data_blob_clear_free(&password); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtconX); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return; } - p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), &path, p, + p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p, STR_TERMINATE); if (path == NULL) { + data_blob_clear_free(&password); TALLOC_FREE(ctx); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtconX); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } /* @@ -525,34 +539,41 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt if (*path=='\\') { q = strchr_m(path+2,'\\'); if (!q) { + data_blob_clear_free(&password); TALLOC_FREE(ctx); + reply_doserror(req, ERRDOS, ERRnosuchshare); END_PROFILE(SMBtconX); - return(ERROR_DOS(ERRDOS,ERRnosuchshare)); + return; } service = q+1; } else { service = path; } - p += srvstr_pull_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), &client_devicetype, p, - MIN(6,smb_bufrem(inbuf, p)), STR_ASCII); + p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2, + &client_devicetype, p, + MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII); if (client_devicetype == NULL) { + data_blob_clear_free(&password); TALLOC_FREE(ctx); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtconX); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service)); - conn = make_connection(service,password,client_devicetype,vuid,&nt_status); + conn = make_connection(service, password, client_devicetype, + req->vuid, &nt_status); data_blob_clear_free(&password); if (!conn) { TALLOC_FREE(ctx); + reply_nterror(req, nt_status); END_PROFILE(SMBtconX); - return ERROR_NT(nt_status); + return; } if ( IS_IPC(conn) ) @@ -563,11 +584,14 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt server_devicetype = "A:"; if (Protocol < PROTOCOL_NT1) { - set_message(inbuf,outbuf,2,0,True); - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, server_devicetype, -1, - STR_TERMINATE|STR_ASCII); - set_message_end(inbuf,outbuf,p); + reply_outbuf(req, 2, 0); + if (message_push_string(&req->outbuf, server_devicetype, + STR_TERMINATE|STR_ASCII) == -1) { + TALLOC_FREE(ctx); + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBtconX); + return; + } } else { /* NT sets the fstype of IPC$ to the null string */ const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); @@ -577,7 +601,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt uint32 perm1 = 0; uint32 perm2 = 0; - set_message(inbuf,outbuf,7,0,True); + reply_outbuf(req, 7, 0); if (IS_IPC(conn)) { perm1 = FILE_ALL_ACCESS; @@ -588,26 +612,28 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt SHARE_READ_ONLY; } - SIVAL(outbuf, smb_vwv3, perm1); - SIVAL(outbuf, smb_vwv5, perm2); + SIVAL(req->outbuf, smb_vwv3, perm1); + SIVAL(req->outbuf, smb_vwv5, perm2); } else { - set_message(inbuf,outbuf,3,0,True); + reply_outbuf(req, 3, 0); } - p = smb_buf(outbuf); - p += srvstr_push(outbuf, p, server_devicetype, -1, - STR_TERMINATE|STR_ASCII); - p += srvstr_push(outbuf, p, fstype, -1, - STR_TERMINATE); - - set_message_end(inbuf,outbuf,p); + if ((message_push_string(&req->outbuf, server_devicetype, + STR_TERMINATE|STR_ASCII) == -1) + || (message_push_string(&req->outbuf, fstype, + STR_TERMINATE) == -1)) { + TALLOC_FREE(ctx); + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBtconX); + return; + } /* what does setting this bit do? It is set by NT4 and may affect the ability to autorun mounted cdroms */ - SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS| - (lp_csc_policy(SNUM(conn)) << 2)); + SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS| + (lp_csc_policy(SNUM(conn)) << 2)); - init_dfsroot(conn, inbuf, outbuf); + init_dfsroot(conn, req->inbuf, req->outbuf); } @@ -615,12 +641,14 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt service)); /* set the incoming and outgoing tid to the just created one */ - SSVAL(inbuf,smb_tid,conn->cnum); - SSVAL(outbuf,smb_tid,conn->cnum); + SSVAL(req->inbuf,smb_tid,conn->cnum); + SSVAL(req->outbuf,smb_tid,conn->cnum); TALLOC_FREE(ctx); END_PROFILE(SMBtconX); - return chain_reply(inbuf,&outbuf,length,bufsize); + + chain_reply_new(req); + return; } /**************************************************************************** -- cgit From 01d5091c26b9edd54023b5d3b0ab00ad93608654 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 12:03:58 +0000 Subject: r24004: Convert reply_checkpath to the new API (This used to be commit e5c7c6406af5552b3060f03a09b5e6c9a42e531c) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 39 +++++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2cc8b3976b..41ca060d56 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -650,7 +650,7 @@ static const struct smb_message_struct { /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, /* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER }, /* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER}, -/* 0x10 */ { "SMBcheckpath",reply_checkpath,NULL,AS_USER}, +/* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, /* 0x11 */ { "SMBexit",reply_exit,NULL,DO_CHDIR}, /* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER}, /* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 725dd416f2..fd9fc09e5a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -747,33 +747,36 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status) Reply to a checkpath. ****************************************************************************/ -int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_checkpath(connection_struct *conn, struct smb_request *req) { - int outsize = 0; pstring name; SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBcheckpath); - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), name, smb_buf(inbuf) + 1, - sizeof(name), 0, STR_TERMINATE, &status); + srvstr_get_path((char *)req->inbuf, req->flags2, name, + smb_buf(req->inbuf) + 1, sizeof(name), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + status = map_checkpath_error((char *)req->inbuf, status); + reply_nterror(req, status); END_PROFILE(SMBcheckpath); - status = map_checkpath_error(inbuf, status); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); END_PROFILE(SMBcheckpath); - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + return; } goto path_err; } - DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); + DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0))); status = unix_convert(conn, name, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -793,14 +796,16 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s } if (!S_ISDIR(sbuf.st_mode)) { + reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY, + ERRDOS, ERRbadpath); END_PROFILE(SMBcheckpath); - return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); + return; } - outsize = set_message(inbuf,outbuf,0,0,False); + reply_outbuf(req, 0, 0); END_PROFILE(SMBcheckpath); - return outsize; + return; path_err: @@ -811,8 +816,8 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s one at a time - if a component fails it expects ERRbadpath, not ERRbadfile. */ - status = map_checkpath_error(inbuf, status); - if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + status = map_checkpath_error((char *)req->inbuf, status); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { /* * Windows returns different error codes if * the parent directory is valid but not the @@ -820,10 +825,12 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND * if the path is invalid. */ - return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpath); + return; } - return ERROR_NT(status); + reply_nterror(req, status); } /**************************************************************************** -- cgit From 3a836c3ee44e9abc5b5028bf6286628981bf0f99 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 23 Jul 2007 14:36:54 +0000 Subject: r24006: Some more paranoia in reply_negprot Some hosts see the smb_bufrem(req->inbuf, p) as an unsigned int. And as the p += strlen(p) + 2 went one beyond the buffer, this was a very large positive. Also take the chance to add one more consistency check. (This used to be commit 3673707f9f1a3ba29966ac7cf744e2b6462c8dde) --- source3/smbd/negprot.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 61be2e8f9a..7602490c2d 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -533,7 +533,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) return; } - p = smb_buf(req->inbuf)+1; + p = smb_buf(req->inbuf); num_cliprotos = 0; cliprotos = NULL; @@ -541,6 +541,16 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) while (smb_bufrem(req->inbuf, p) > 0) { char **tmp; + if (p[0] != 0x02) { + DEBUG(3, ("Invalid string specifier %x, expected " + "0x02\n", (int)p[0])); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBnegprot); + return; + } + + p += 1; /* Skip the "0x02" */ + tmp = TALLOC_REALLOC_ARRAY(tmp_talloc_ctx(), cliprotos, char *, num_cliprotos+1); if (tmp == NULL) { @@ -566,7 +576,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) cliprotos[num_cliprotos])); num_cliprotos += 1; - p += strlen(p) + 2; + p += strlen(p) + 1; } for (i=0; i Date: Mon, 23 Jul 2007 19:46:48 +0000 Subject: r24009: Revert to the 3.0.25 logic for parsing the client's protocols. hpisgr8 with gcc still gives timeouts which worry me. Volker (This used to be commit c30835b4f0416b2b2b7d77d31b0fca0606f2387a) --- source3/smbd/negprot.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 7602490c2d..a8578d56b5 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -511,6 +511,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) int choice= -1; int protocol; char *p; + int bcc = SVAL(smb_buf(req->inbuf),-2); int arch = ARCH_ALL; int num_cliprotos; char **cliprotos; @@ -533,23 +534,14 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) return; } - p = smb_buf(req->inbuf); + p = smb_buf(req->inbuf) + 1; num_cliprotos = 0; cliprotos = NULL; - while (smb_bufrem(req->inbuf, p) > 0) { - char **tmp; - - if (p[0] != 0x02) { - DEBUG(3, ("Invalid string specifier %x, expected " - "0x02\n", (int)p[0])); - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBnegprot); - return; - } + while (p < (smb_buf(req->inbuf) + bcc)) { - p += 1; /* Skip the "0x02" */ + char **tmp; tmp = TALLOC_REALLOC_ARRAY(tmp_talloc_ctx(), cliprotos, char *, num_cliprotos+1); @@ -576,7 +568,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) cliprotos[num_cliprotos])); num_cliprotos += 1; - p += strlen(p) + 1; + p += strlen(p) + 2; } for (i=0; i Date: Tue, 24 Jul 2007 10:35:10 +0000 Subject: r24029: merge from http://samba.org/~tridge/samba_3_2_ctdb/: the claim_connection() must come after the sockets are open metze (This used to be commit 306846a14f554c55b57e9ce0ad324d5c81776330) --- source3/smbd/server.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c09a0d7b98..491482eea6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -349,6 +349,14 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ maxfd = MAX(maxfd, fd_listenset[i]); } + + /* Setup the main smbd so that we can get messages. Note that + do this after starting listening. This is needed as when in + clustered mode, ctdb won't allow us to start doing database + operations until it has gone thru a full startup, which + includes checking to see that smbd is listening. */ + claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD); + /* Listen to messages */ messaging_register(smbd_messaging_context(), NULL, @@ -1040,11 +1048,6 @@ extern void build_options(BOOL screen); return -1; } - /* Setup the main smbd so that we can get messages. */ - /* don't worry about general printing messages here */ - - claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD); - /* only start the background queue daemon if we are running as a daemon -- bad things will happen if smbd is launched via inetd and we fork a copy of -- cgit From e5cdc454aadf2d3d93d80524d2c84990f239aaa0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 25 Jul 2007 18:39:10 +0000 Subject: r24046: Fix a 64-bit warning (This used to be commit a2ecc34aa43f810e68815c25016da1d184a21a04) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 41ca060d56..1159589e8d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1224,7 +1224,7 @@ static void process_smb(char *inbuf, size_t nread) DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, smb_len(inbuf) ) ); - DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); + DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, (int)nread ) ); if (msg_type != 0) { /* -- cgit From 115062e7cea8c265b9f910360ae3e8b9af4c95a8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 25 Jul 2007 18:53:16 +0000 Subject: r24049: Some more 64-bit warnings (This used to be commit eabe796e464e5fe10d0f4cca1362985c529f5a5b) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index afef36f61e..f4c4aaec41 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -415,7 +415,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) DEBUG( 3, ( "handle_aio_read_complete file %s max=%d " "nread=%d\n", aio_ex->fsp->fsp_name, - aio_ex->acb.aio_nbytes, (int)nread ) ); + (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } smb_setlen(inbuf,outbuf,outsize - 4); -- cgit From e29325a6ce6aafb64485f1372ebb4148bffae57b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 25 Jul 2007 20:01:03 +0000 Subject: r24050: Fix a typo (This used to be commit 53027d0ee2dbe15beb2fce5d11a26f4ac0b08b9c) --- source3/smbd/sesssetup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index eb0d7b3e12..70819831f6 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1257,7 +1257,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (CVAL(inbuf, smb_wct) == 12 && (smb_flag2 & FLAGS2_EXTENDED_SECURITY)) { if (!global_spnego_negotiated) { - DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); + DEBUG(0, ("reply_sesssetup_and_X: Rejecting attempt " + "at SPNEGO session setup when it was not " + "negotiated.\n")); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } -- cgit From 7d2d4ddfa2fbd859f35f8f4e2b8243f52a4ace0e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 26 Jul 2007 16:01:12 +0000 Subject: r24056: Another big one: This converts reply_sesssetup_and_X to the new API. As usual, its history can be found on http://samba.org/~vlendec/sesssetup/. This very obviously needs close review. Volker (This used to be commit 35675a6a33d584e5c3c97d1cb5ca9b0315a5fa92) --- source3/smbd/process.c | 2 +- source3/smbd/sesssetup.c | 433 +++++++++++++++++++++++++++-------------------- 2 files changed, 249 insertions(+), 186 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1159589e8d..85e061710d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -749,7 +749,7 @@ static const struct smb_message_struct { /* 0x70 */ { "SMBtcon",reply_tcon,NULL,0}, /* 0x71 */ { "SMBtdis",reply_tdis,NULL,DO_CHDIR}, /* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0}, -/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,NULL,0}, +/* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0}, /* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */ /* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,0}, /* 0x76 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 70819831f6..e9808e0040 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -60,25 +60,43 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv Add the standard 'Samba' signature to the end of the session setup. ****************************************************************************/ -static int add_signature(char *outbuf, char *p) +static int push_signature(uint8 **outbuf) { - char *start = p; - fstring lanman; + char *lanman; + int result, tmp; - fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING); + result = 0; - p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); - p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + tmp = message_push_string(outbuf, "Unix", STR_TERMINATE); - return PTR_DIFF(p, start); + if (tmp == -1) return -1; + result += tmp; + + if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) { + tmp = message_push_string(outbuf, lanman, STR_TERMINATE); + SAFE_FREE(lanman); + } + else { + tmp = message_push_string(outbuf, "Samba", STR_TERMINATE); + } + + if (tmp == -1) return -1; + result += tmp; + + tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE); + + if (tmp == -1) return -1; + result += tmp; + + return result; } /**************************************************************************** Start the signing engine if needed. Don't fail signing here. ****************************************************************************/ -static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf) +static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, + const uint8 *inbuf) { if (!server_info->guest && !srv_signing_started()) { /* We need to start the signing engine @@ -87,7 +105,7 @@ static void sessionsetup_start_signing_engine(const auth_serversupplied_info *se * correct one. Subsequent packets will * be correct. */ - srv_check_sign_mac(inbuf, False); + srv_check_sign_mac((char *)inbuf, False); } } @@ -95,36 +113,29 @@ static void sessionsetup_start_signing_engine(const auth_serversupplied_info *se Send a security blob via a session setup reply. ****************************************************************************/ -static BOOL reply_sesssetup_blob(connection_struct *conn, - const char *inbuf, - char *outbuf, - DATA_BLOB blob, - NTSTATUS nt_status) +static void reply_sesssetup_blob(connection_struct *conn, + struct smb_request *req, + DATA_BLOB blob, + NTSTATUS nt_status) { - char *p; - - if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - ERROR_NT(nt_status_squash(nt_status)); + if (!NT_STATUS_IS_OK(nt_status) && + !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + reply_nterror(req, nt_status_squash(nt_status)); } else { - set_message(inbuf,outbuf,4,0,True); - nt_status = nt_status_squash(nt_status); - SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status)); - SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ - SSVAL(outbuf, smb_vwv3, blob.length); - p = smb_buf(outbuf); - - /* should we cap this? */ - memcpy(p, blob.data, blob.length); - p += blob.length; + SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status)); + SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */ + SSVAL(req->outbuf, smb_vwv3, blob.length); - p += add_signature( outbuf, p ); - - set_message_end(inbuf,outbuf,p); + if ((message_push_blob(&req->outbuf, blob) == -1) + || (push_signature(&req->outbuf) == -1)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + } } - show_msg(outbuf); - return send_smb(smbd_server_fd(),outbuf); + show_msg((char *)req->outbuf); + send_smb(smbd_server_fd(),(char *)req->outbuf); + TALLOC_FREE(req->outbuf); } /**************************************************************************** @@ -225,11 +236,11 @@ static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out) Reply to a session setup spnego negotiate packet for kerberos. ****************************************************************************/ -static int reply_spnego_kerberos(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - DATA_BLOB *secblob, - BOOL *p_invalidate_vuid) +static void reply_spnego_kerberos(connection_struct *conn, + struct smb_request *req, + DATA_BLOB *secblob, + uint16 vuid, + BOOL *p_invalidate_vuid) { TALLOC_CTX *mem_ctx; DATA_BLOB ticket; @@ -261,12 +272,14 @@ static int reply_spnego_kerberos(connection_struct *conn, mem_ctx = talloc_init("reply_spnego_kerberos"); if (mem_ctx == NULL) { - return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY)); + reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY)); + return; } if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { talloc_destroy(mem_ctx); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE)); + return; } ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, @@ -319,7 +332,8 @@ static int reply_spnego_kerberos(connection_struct *conn, #endif DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret))); talloc_destroy(mem_ctx); - return ERROR_NT(nt_status_squash(ret)); + reply_nterror(req, nt_status_squash(ret)); + return; } DEBUG(3,("Ticket name is [%s]\n", client)); @@ -331,7 +345,8 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&session_key); SAFE_FREE(client); talloc_destroy(mem_ctx); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE)); + return; } *p = 0; @@ -352,7 +367,9 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&session_key); SAFE_FREE(client); talloc_destroy(mem_ctx); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); + return; } } @@ -421,7 +438,8 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); - return ERROR_NT(nt_status_squash(ret)); + reply_nterror(req, nt_status_squash(ret)); + return; } } @@ -445,7 +463,9 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); + return; } } @@ -469,7 +489,8 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); - return ERROR_NT(nt_status_squash(ret)); + reply_nterror(req, nt_status_squash(ret)); + return; } } else { @@ -482,7 +503,8 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); - return ERROR_NT(nt_status_squash(ret)); + reply_nterror(req, nt_status_squash(ret)); + return; } /* make_server_info_pw does not set the domain. Without this @@ -507,7 +529,8 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&session_key); TALLOC_FREE( mem_ctx ); TALLOC_FREE( server_info ); - return ERROR_NT(nt_status_squash(ret)); + reply_nterror(req, nt_status_squash(ret)); + return; } } @@ -518,22 +541,24 @@ static int reply_spnego_kerberos(connection_struct *conn, SAFE_FREE(client); + reply_outbuf(req, 4, 0); + SSVAL(req->outbuf,smb_uid,vuid); + if (sess_vuid == UID_FIELD_INVALID ) { ret = NT_STATUS_LOGON_FAILURE; } else { /* current_user_info is changed on new vuid */ reload_services( True ); - set_message(inbuf,outbuf,4,0,True); - SSVAL(outbuf, smb_vwv3, 0); + SSVAL(req->outbuf, smb_vwv3, 0); if (server_info->guest) { - SSVAL(outbuf,smb_vwv2,1); + SSVAL(req->outbuf,smb_vwv2,1); } - SSVAL(outbuf, smb_uid, sess_vuid); + SSVAL(req->outbuf, smb_uid, sess_vuid); - sessionsetup_start_signing_engine(server_info, inbuf); + sessionsetup_start_signing_engine(server_info, req->inbuf); } /* wrap that up in a nice GSS-API wrapping */ @@ -543,15 +568,14 @@ static int reply_spnego_kerberos(connection_struct *conn, ap_rep_wrapped = data_blob_null; } response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); - reply_sesssetup_blob(conn, inbuf, outbuf, response, ret); + reply_sesssetup_blob(conn, req, response, ret); data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&response); TALLOC_FREE(mem_ctx); - - return -1; /* already replied */ } + #endif /**************************************************************************** @@ -562,13 +586,13 @@ static int reply_spnego_kerberos(connection_struct *conn, leg of the NTLM auth steps. ***************************************************************************/ -static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, +static void reply_spnego_ntlmssp(connection_struct *conn, + struct smb_request *req, uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, - DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, - BOOL wrap) + DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, + BOOL wrap) { - BOOL ret; DATA_BLOB response; struct auth_serversupplied_info *server_info = NULL; @@ -581,6 +605,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out (*auth_ntlmssp_state)->ntlmssp_state->domain); } + reply_outbuf(req, 4, 0); + + SSVAL(req->outbuf, smb_uid, vuid); + if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; DATA_BLOB nullblob = data_blob_null; @@ -597,16 +625,15 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out /* current_user_info is changed on new vuid */ reload_services( True ); - set_message(inbuf,outbuf,4,0,True); - SSVAL(outbuf, smb_vwv3, 0); + SSVAL(req->outbuf, smb_vwv3, 0); if (server_info->guest) { - SSVAL(outbuf,smb_vwv2,1); + SSVAL(req->outbuf,smb_vwv2,1); } - SSVAL(outbuf,smb_uid,sess_vuid); + SSVAL(req->outbuf,smb_uid,sess_vuid); - sessionsetup_start_signing_engine(server_info, inbuf); + sessionsetup_start_signing_engine(server_info, req->inbuf); } } @@ -616,7 +643,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out response = *ntlmssp_blob; } - ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status); + reply_sesssetup_blob(conn, req, response, nt_status); if (wrap) { data_blob_free(&response); } @@ -624,14 +651,12 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us, and the other end, that we are not finished yet. */ - if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { /* NB. This is *NOT* an error case. JRA */ auth_ntlmssp_end(auth_ntlmssp_state); /* Kill the intermediate vuid */ invalidate_vuid(vuid); } - - return ret; } /**************************************************************************** @@ -678,13 +703,11 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL * Reply to a session setup spnego negotiate packet. ****************************************************************************/ -static int reply_spnego_negotiate(connection_struct *conn, - char *inbuf, - char *outbuf, - uint16 vuid, - int length, int bufsize, - DATA_BLOB blob1, - AUTH_NTLMSSP_STATE **auth_ntlmssp_state) +static void reply_spnego_negotiate(connection_struct *conn, + struct smb_request *req, + uint16 vuid, + DATA_BLOB blob1, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { DATA_BLOB secblob; DATA_BLOB chal; @@ -695,7 +718,8 @@ static int reply_spnego_negotiate(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); - return ERROR_NT(nt_status_squash(status)); + reply_nterror(req, nt_status_squash(status)); + return; } DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); @@ -703,14 +727,14 @@ static int reply_spnego_negotiate(connection_struct *conn, #ifdef HAVE_KRB5 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { BOOL destroy_vuid = True; - int ret = reply_spnego_kerberos(conn, inbuf, outbuf, - length, bufsize, &secblob, &destroy_vuid); + reply_spnego_kerberos(conn, req, &secblob, vuid, + &destroy_vuid); data_blob_free(&secblob); if (destroy_vuid) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); } - return ret; + return; } #endif @@ -722,7 +746,8 @@ static int reply_spnego_negotiate(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); - return ERROR_NT(nt_status_squash(status)); + reply_nterror(req, nt_status_squash(status)); + return; } status = auth_ntlmssp_update(*auth_ntlmssp_state, @@ -730,24 +755,24 @@ static int reply_spnego_negotiate(connection_struct *conn, data_blob_free(&secblob); - reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, + reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state, &chal, status, True); data_blob_free(&chal); /* already replied */ - return -1; + return; } /**************************************************************************** Reply to a session setup spnego auth packet. ****************************************************************************/ -static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, - uint16 vuid, - int length, int bufsize, - DATA_BLOB blob1, - AUTH_NTLMSSP_STATE **auth_ntlmssp_state) +static void reply_spnego_auth(connection_struct *conn, + struct smb_request *req, + uint16 vuid, + DATA_BLOB blob1, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { DATA_BLOB auth = data_blob_null; DATA_BLOB auth_reply = data_blob_null; @@ -761,7 +786,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, /* Kill the intermediate vuid */ invalidate_vuid(vuid); - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + return; } if (auth.data[0] == ASN1_APPLICATION(0)) { @@ -774,15 +801,15 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, #ifdef HAVE_KRB5 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { BOOL destroy_vuid = True; - int ret = reply_spnego_kerberos(conn, inbuf, outbuf, - length, bufsize, &secblob, &destroy_vuid); + reply_spnego_kerberos(conn, req, &secblob, + vuid, &destroy_vuid); data_blob_free(&secblob); data_blob_free(&auth); if (destroy_vuid) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); } - return ret; + return; } #endif } @@ -796,7 +823,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, invalidate_vuid(vuid); /* auth before negotiatiate? */ - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + return; } status = auth_ntlmssp_update(*auth_ntlmssp_state, @@ -804,14 +833,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, data_blob_free(&auth); - reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, + reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state, &auth_reply, status, True); data_blob_free(&auth_reply); /* and tell smbd that we have already replied to this packet */ - return -1; + return; } /**************************************************************************** @@ -1012,28 +1041,26 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, - char *outbuf, - int length,int bufsize) +static void reply_sesssetup_and_X_spnego(connection_struct *conn, + struct smb_request *req) { uint8 *p; DATA_BLOB blob1; - int ret; size_t bufrem; fstring native_os, native_lanman, primary_domain; - char *p2; - uint16 data_blob_len = SVAL(inbuf, smb_vwv7); + const char *p2; + uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7); enum remote_arch_types ra_type = get_remote_arch(); - int vuid = SVAL(inbuf,smb_uid); + int vuid = SVAL(req->inbuf,smb_uid); user_struct *vuser = NULL; NTSTATUS status = NT_STATUS_OK; - uint16 smbpid = SVAL(inbuf,smb_pid); - uint16 smb_flag2 = SVAL(inbuf, smb_flg2); + uint16 smbpid = req->smbpid; + uint16 smb_flag2 = req->flags2; DEBUG(3,("Doing spnego session setup\n")); if (global_client_caps == 0) { - global_client_caps = IVAL(inbuf,smb_vwv10); + global_client_caps = IVAL(req->inbuf,smb_vwv10); if (!(global_client_caps & CAP_STATUS32)) { remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); @@ -1041,14 +1068,15 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, } - p = (uint8 *)smb_buf(inbuf); + p = (uint8 *)smb_buf(req->inbuf); if (data_blob_len == 0) { /* an invalid request */ - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE)); + return; } - bufrem = smb_bufrem(inbuf, p); + bufrem = smb_bufrem(req->inbuf, p); /* pull the spnego blob */ blob1 = data_blob(p, MIN(bufrem, data_blob_len)); @@ -1056,12 +1084,12 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, file_save("negotiate.dat", blob1.data, blob1.length); #endif - p2 = inbuf + smb_vwv13 + data_blob_len; - p2 += srvstr_pull_buf(inbuf, smb_flag2, native_os, p2, + p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len; + p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2, sizeof(native_os), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, smb_flag2, native_lanman, p2, + p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, smb_flag2, primary_domain, p2, + p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE); DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", native_os, native_lanman, primary_domain)); @@ -1097,7 +1125,9 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL); if (vuid == UID_FIELD_INVALID ) { data_blob_free(&blob1); - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + return; } vuser = get_partial_auth_user_struct(vuid); @@ -1105,11 +1135,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, if (!vuser) { data_blob_free(&blob1); - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + return; } - SSVAL(outbuf,smb_uid,vuid); - /* Large (greater than 4k) SPNEGO blobs are split into multiple * sessionsetup requests as the Windows limit on the security blob * field is 4k. Bug #4400. JRA. @@ -1122,34 +1152,41 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, invalidate_vuid(vuid); } data_blob_free(&blob1); - return ERROR_NT(nt_status_squash(status)); + reply_nterror(req, nt_status_squash(status)); + return; } if (blob1.data[0] == ASN1_APPLICATION(0)) { + /* its a negTokenTarg packet */ - ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1, - &vuser->auth_ntlmssp_state); + + reply_spnego_negotiate(conn, req, vuid, blob1, + &vuser->auth_ntlmssp_state); data_blob_free(&blob1); - return ret; + return; } if (blob1.data[0] == ASN1_CONTEXT(1)) { + /* its a auth packet */ - ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1, - &vuser->auth_ntlmssp_state); + + reply_spnego_auth(conn, req, vuid, blob1, + &vuser->auth_ntlmssp_state); data_blob_free(&blob1); - return ret; + return; } if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) { DATA_BLOB chal; + if (!vuser->auth_ntlmssp_state) { status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); data_blob_free(&blob1); - return ERROR_NT(nt_status_squash(status)); + reply_nterror(req, nt_status_squash(status)); + return; } } @@ -1158,11 +1195,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, data_blob_free(&blob1); - reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, - &vuser->auth_ntlmssp_state, - &chal, status, False); + reply_spnego_ntlmssp(conn, req, vuid, + &vuser->auth_ntlmssp_state, + &chal, status, False); data_blob_free(&chal); - return -1; + return; } /* what sort of packet is this? */ @@ -1170,7 +1207,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, data_blob_free(&blob1); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE)); } /**************************************************************************** @@ -1219,8 +1256,7 @@ static void setup_new_vc_session(void) Reply to a session setup command. ****************************************************************************/ -int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, - int length,int bufsize) +void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) { int sess_vuid; int smb_bufsize; @@ -1236,75 +1272,88 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, static BOOL done_sesssetup = False; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; - uint16 smb_flag2 = SVAL(inbuf, smb_flg2); + uint16 smb_flag2 = req->flags2; NTSTATUS nt_status; BOOL doencrypt = global_encrypted_passwords_negotiated; DATA_BLOB session_key; + + START_PROFILE(SMBsesssetupX); ZERO_STRUCT(lm_resp); ZERO_STRUCT(nt_resp); ZERO_STRUCT(plaintext_password); - DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), smb_flag2)); + DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2)); /* a SPNEGO session setup has 12 command words, whereas a normal NT1 session setup has 13. See the cifs spec. */ - if (CVAL(inbuf, smb_wct) == 12 && - (smb_flag2 & FLAGS2_EXTENDED_SECURITY)) { + if (req->wct == 12 && + (req->flags2 & FLAGS2_EXTENDED_SECURITY)) { + if (!global_spnego_negotiated) { - DEBUG(0, ("reply_sesssetup_and_X: Rejecting attempt " - "at SPNEGO session setup when it was not " - "negotiated.\n")); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt " + "at SPNEGO session setup when it was not " + "negotiated.\n")); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); + return; } - if (SVAL(inbuf,smb_vwv4) == 0) { + if (SVAL(req->inbuf,smb_vwv4) == 0) { setup_new_vc_session(); } - return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); + + reply_sesssetup_and_X_spnego(conn, req); + + return; } - smb_bufsize = SVAL(inbuf,smb_vwv2); + smb_bufsize = SVAL(req->inbuf,smb_vwv2); if (Protocol < PROTOCOL_NT1) { - uint16 passlen1 = SVAL(inbuf,smb_vwv7); + uint16 passlen1 = SVAL(req->inbuf,smb_vwv7); /* Never do NT status codes with protocols before NT1 as we don't get client caps. */ remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); - if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) { - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + if ((passlen1 > MAX_PASS_LEN) + || (passlen1 > smb_bufrem(req->inbuf, + smb_buf(req->inbuf)))) { + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + return; } if (doencrypt) { - lm_resp = data_blob(smb_buf(inbuf), passlen1); + lm_resp = data_blob(smb_buf(req->inbuf), passlen1); } else { - plaintext_password = data_blob(smb_buf(inbuf), passlen1+1); + plaintext_password = data_blob(smb_buf(req->inbuf), + passlen1+1); /* Ensure null termination */ plaintext_password.data[passlen1] = 0; } - srvstr_pull_buf(inbuf, smb_flag2, user, - smb_buf(inbuf)+passlen1, sizeof(user), + srvstr_pull_buf(req->inbuf, req->flags2, user, + smb_buf(req->inbuf)+passlen1, sizeof(user), STR_TERMINATE); *domain = 0; } else { - uint16 passlen1 = SVAL(inbuf,smb_vwv7); - uint16 passlen2 = SVAL(inbuf,smb_vwv8); + uint16 passlen1 = SVAL(req->inbuf,smb_vwv7); + uint16 passlen2 = SVAL(req->inbuf,smb_vwv8); enum remote_arch_types ra_type = get_remote_arch(); - char *p = smb_buf(inbuf); - char *save_p = smb_buf(inbuf); + char *p = smb_buf(req->inbuf); + char *save_p = smb_buf(req->inbuf); uint16 byte_count; if(global_client_caps == 0) { - global_client_caps = IVAL(inbuf,smb_vwv11); + global_client_caps = IVAL(req->inbuf,smb_vwv11); if (!(global_client_caps & CAP_STATUS32)) { remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); @@ -1340,12 +1389,18 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } /* check for nasty tricks */ - if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) { - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + if (passlen1 > MAX_PASS_LEN + || passlen1 > smb_bufrem(req->inbuf, p)) { + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + return; } - if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) { - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + if (passlen2 > MAX_PASS_LEN + || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) { + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + return; } /* Save the lanman2 password and the NT md4 password. */ @@ -1371,12 +1426,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (unic && (passlen2 == 0) && passlen1) { /* Only a ascii plaintext password was sent. */ - srvstr_pull(inbuf, smb_flag2, pass, - smb_buf(inbuf), sizeof(pass), + srvstr_pull(req->inbuf, req->flags2, pass, + smb_buf(req->inbuf), sizeof(pass), passlen1, STR_TERMINATE|STR_ASCII); } else { - srvstr_pull(inbuf, smb_flag2, pass, - smb_buf(inbuf), sizeof(pass), + srvstr_pull(req->inbuf, req->flags2, pass, + smb_buf(req->inbuf), sizeof(pass), unic ? passlen2 : passlen1, STR_TERMINATE); } @@ -1384,13 +1439,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } p += passlen1 + passlen2; - p += srvstr_pull_buf(inbuf, smb_flag2, user, p, + p += srvstr_pull_buf(req->inbuf, req->flags2, user, p, sizeof(user), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, smb_flag2, domain, p, + p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p, sizeof(domain), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, smb_flag2, native_os, + p += srvstr_pull_buf(req->inbuf, req->flags2, native_os, p, sizeof(native_os), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, smb_flag2, + p += srvstr_pull_buf(req->inbuf, req->flags2, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); @@ -1400,9 +1455,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, the native lanman string. Windows 9x does not include a string here at all so we have to check if we have any extra bytes left */ - byte_count = SVAL(inbuf, smb_vwv13); + byte_count = SVAL(req->inbuf, smb_vwv13); if ( PTR_DIFF(p, save_p) < byte_count) - p += srvstr_pull_buf(inbuf, smb_flag2, + p += srvstr_pull_buf(req->inbuf, req->flags2, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); @@ -1421,7 +1476,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } - if (SVAL(inbuf,smb_vwv4) == 0) { + if (SVAL(req->inbuf,smb_vwv4) == 0) { setup_new_vc_session(); } @@ -1433,7 +1488,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); + return; } fstrcpy(sub_user, user); } else { @@ -1465,7 +1522,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } else if (doencrypt) { if (!negprot_global_auth_context) { DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n")); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); + return; } nt_status = make_user_info_for_reply_enc(&user_info, user, domain, lm_resp, nt_resp); @@ -1509,12 +1568,14 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); - return ERROR_NT(nt_status_squash(nt_status)); + reply_nterror(req, nt_status_squash(nt_status)); + return; } /* Ensure we can't possible take a code path leading to a null defref. */ if (!server_info) { - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE)); + return; } nt_status = create_local_token(server_info); @@ -1524,7 +1585,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); - return ERROR_NT(nt_status_squash(nt_status)); + reply_nterror(req, nt_status_squash(nt_status)); + return; } if (server_info->user_session_key.data) { @@ -1536,16 +1598,14 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, data_blob_clear_free(&plaintext_password); /* it's ok - setup a reply */ - set_message(inbuf,outbuf,3,0,True); + reply_outbuf(req, 3, 0); if (Protocol >= PROTOCOL_NT1) { - char *p = smb_buf( outbuf ); - p += add_signature( outbuf, p ); - set_message_end(inbuf, outbuf, p ); + push_signature(&req->outbuf); /* perhaps grab OS version here?? */ } if (server_info->guest) { - SSVAL(outbuf,smb_vwv2,1); + SSVAL(req->outbuf,smb_vwv2,1); } /* register the name and uid as being validated, so further connections @@ -1563,20 +1623,22 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (sess_vuid == UID_FIELD_INVALID) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); + return; } /* current_user_info is changed on new vuid */ reload_services( True ); - sessionsetup_start_signing_engine(server_info, inbuf); + sessionsetup_start_signing_engine(server_info, req->inbuf); } data_blob_free(&nt_resp); data_blob_free(&lm_resp); - SSVAL(outbuf,smb_uid,sess_vuid); - SSVAL(inbuf,smb_uid,sess_vuid); + SSVAL(req->outbuf,smb_uid,sess_vuid); + SSVAL(req->inbuf,smb_uid,sess_vuid); if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); @@ -1584,5 +1646,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, done_sesssetup = True; END_PROFILE(SMBsesssetupX); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); + return; } -- cgit From c1ca4c298bfdba42fc7db9d83514edd33893e7e7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Jul 2007 16:40:45 +0000 Subject: r24070: Apply some const (This used to be commit e6d592dcb8ff9f986b531435d0d03df20880880b) --- source3/smbd/blocking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 09d16337cd..c6e174ae22 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -151,7 +151,7 @@ static BOOL recalc_brl_timeout(void) ****************************************************************************/ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, - char *inbuf, int length, + const char *inbuf, int length, files_struct *fsp, int lock_timeout, int lock_num, -- cgit From dd98820185b4cdaef7c4e247039b6c1da6600105 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Jul 2007 07:50:24 +0000 Subject: r24071: Fix a missing END_PROFILE call (This used to be commit c9f12326dd1c090bd0ef9bb97c82926c2efd6ae8) --- source3/smbd/reply.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index fd9fc09e5a..c347182b99 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2255,6 +2255,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size status = unlink_internals(conn, &req, dirtype, name, path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBunlink); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; -- cgit From 09b3d2525249fd832b7d46a19921a87a13b71407 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Jul 2007 10:20:52 +0000 Subject: r24077: Convert reply_tdis to the new API (This used to be commit bd0cb48dde401f48dec98fa7ca794a912e0244f1) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 85e061710d..fdec2d106d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -747,7 +747,7 @@ static const struct smb_message_struct { /* 0x6e */ { NULL, NULL, NULL, 0 }, /* 0x6f */ { NULL, NULL, NULL, 0 }, /* 0x70 */ { "SMBtcon",reply_tcon,NULL,0}, -/* 0x71 */ { "SMBtdis",reply_tdis,NULL,DO_CHDIR}, +/* 0x71 */ { "SMBtdis",NULL,reply_tdis,DO_CHDIR}, /* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0}, /* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0}, /* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c347182b99..7af0807c0a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3704,27 +3704,24 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_tdis(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_tdis(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,0,0,False); - uint16 vuid; START_PROFILE(SMBtdis); - vuid = SVAL(inbuf,smb_uid); - if (!conn) { DEBUG(4,("Invalid connection in tdis\n")); + reply_doserror(req, ERRSRV, ERRinvnid); END_PROFILE(SMBtdis); - return ERROR_DOS(ERRSRV,ERRinvnid); + return; } conn->used = False; - close_cnum(conn,vuid); - + close_cnum(conn,req->vuid); + + reply_outbuf(req, 0, 0); END_PROFILE(SMBtdis); - return outsize; + return; } /**************************************************************************** -- cgit From 4392d47b34720d2dcd8ee47bd14a71bf1eab2c86 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Jul 2007 10:23:26 +0000 Subject: r24078: Add reply_unixerror (This used to be commit 10ac991750e9476299d39ac6f763d1638ff8c619) --- source3/smbd/error.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index d00c61487a..023e1b7dcc 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -157,3 +157,33 @@ void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode, error_packet_set((char *)req->outbuf, eclass, ecode, status, line, file); } + +void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode, + NTSTATUS defstatus, int line, const char *file) +{ + int eclass=defclass; + int ecode=defcode; + NTSTATUS ntstatus = defstatus; + int i=0; + + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + + if (errno != 0) { + DEBUG(3,("unix_error_packet: error string = %s\n", + strerror(errno))); + + while (unix_dos_nt_errmap[i].dos_class != 0) { + if (unix_dos_nt_errmap[i].unix_error == errno) { + eclass = unix_dos_nt_errmap[i].dos_class; + ecode = unix_dos_nt_errmap[i].dos_code; + ntstatus = unix_dos_nt_errmap[i].nt_error; + break; + } + i++; + } + } + + error_packet_set((char *)req->outbuf, eclass, ecode, ntstatus, + line, file); +} -- cgit From ef97e2dece55d84e64bdcbb922939ea28199a2e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Jul 2007 10:30:19 +0000 Subject: r24079: Convert reply_dskattr to the new API (This used to be commit c8e0aa5752fde34f7271a4fad758dfae0991722d) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index fdec2d106d..971a9d299b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -762,7 +762,7 @@ static const struct smb_message_struct { /* 0x7d */ { NULL, NULL, NULL, 0 }, /* 0x7e */ { NULL, NULL, NULL, 0 }, /* 0x7f */ { NULL, NULL, NULL, 0 }, -/* 0x80 */ { "SMBdskattr",reply_dskattr,NULL,AS_USER}, +/* 0x80 */ { "SMBdskattr",NULL,reply_dskattr,AS_USER}, /* 0x81 */ { "SMBsearch",reply_search,NULL,AS_USER}, /* 0x82 */ { "SMBffirst",reply_search,NULL,AS_USER}, /* 0x83 */ { "SMBfunique",reply_search,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7af0807c0a..13f1c1ce58 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1007,18 +1007,18 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size Reply to a dskattr. ****************************************************************************/ -int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_dskattr(connection_struct *conn, struct smb_request *req) { - int outsize = 0; SMB_BIG_UINT dfree,dsize,bsize; START_PROFILE(SMBdskattr); if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { + reply_unixerror(req, ERRHRD, ERRgeneral); END_PROFILE(SMBdskattr); - return(UNIXERROR(ERRHRD,ERRgeneral)); + return; } - - outsize = set_message(inbuf,outbuf,5,0,True); + + reply_outbuf(req, 5, 0); if (Protocol <= PROTOCOL_LANMAN2) { double total_space, free_space; @@ -1037,21 +1037,21 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz if (dsize > 0xFFFF) dsize = 0xFFFF; if (dfree > 0xFFFF) dfree = 0xFFFF; - SSVAL(outbuf,smb_vwv0,dsize); - SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */ - SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */ - SSVAL(outbuf,smb_vwv3,dfree); + SSVAL(req->outbuf,smb_vwv0,dsize); + SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */ + SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */ + SSVAL(req->outbuf,smb_vwv3,dfree); } else { - SSVAL(outbuf,smb_vwv0,dsize); - SSVAL(outbuf,smb_vwv1,bsize/512); - SSVAL(outbuf,smb_vwv2,512); - SSVAL(outbuf,smb_vwv3,dfree); + SSVAL(req->outbuf,smb_vwv0,dsize); + SSVAL(req->outbuf,smb_vwv1,bsize/512); + SSVAL(req->outbuf,smb_vwv2,512); + SSVAL(req->outbuf,smb_vwv3,dfree); } DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree)); END_PROFILE(SMBdskattr); - return(outsize); + return; } /**************************************************************************** -- cgit From 68513d521d930188bb381b1737d3a7130ef2088f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Jul 2007 11:35:39 +0000 Subject: r24084: Convert reply_mkdir to the new API (This used to be commit e93f3996fcdde6f0fbba3fb9e1e97407e9ccdd62) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 39 ++++++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 971a9d299b..4b0f2902ef 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -634,7 +634,7 @@ static const struct smb_message_struct { int flags; } smb_messages[256] = { -/* 0x00 */ { "SMBmkdir",reply_mkdir,NULL,AS_USER | NEED_WRITE}, +/* 0x00 */ { "SMBmkdir",NULL,reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",reply_rmdir,NULL,AS_USER | NEED_WRITE}, /* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, /* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 13f1c1ce58..b1e2f00067 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3952,42 +3952,50 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ Reply to a mkdir. ****************************************************************************/ -int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_mkdir(connection_struct *conn, struct smb_request *req) { pstring directory; - int outsize; NTSTATUS status; SMB_STRUCT_STAT sbuf; START_PROFILE(SMBmkdir); - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, - smb_buf(inbuf) + 1, sizeof(directory), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, directory, + smb_buf(req->inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBmkdir); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory); + status = resolve_dfspath(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + directory); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBmkdir); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBmkdir); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBmkdir); + return; } status = unix_convert(conn, directory, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBmkdir); - return ERROR_NT(status); + return; } status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBmkdir); - return ERROR_NT(status); + return; } status = create_directory(conn, directory); @@ -4007,16 +4015,17 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = NT_STATUS_DOS(ERRDOS, ERRnoaccess); } + reply_nterror(req, status); END_PROFILE(SMBmkdir); - return ERROR_NT(status); + return; } - outsize = set_message(inbuf,outbuf,0,0,False); + reply_outbuf(req, 0, 0); - DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); + DEBUG( 3, ( "mkdir %s\n", directory ) ); END_PROFILE(SMBmkdir); - return(outsize); + return; } /**************************************************************************** -- cgit From 4694e757ba084e68e6f5bc3bf2d3714474c215cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Jul 2007 14:07:29 +0000 Subject: r24085: Convert reply_rmdir to the new API (This used to be commit 7689048d71cc4adbdaee5521cc57890518e7090a) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 39 ++++++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4b0f2902ef..dafea5ed2f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -635,7 +635,7 @@ static const struct smb_message_struct { } smb_messages[256] = { /* 0x00 */ { "SMBmkdir",NULL,reply_mkdir,AS_USER | NEED_WRITE}, -/* 0x01 */ { "SMBrmdir",reply_rmdir,NULL,AS_USER | NEED_WRITE}, +/* 0x01 */ { "SMBrmdir",NULL,reply_rmdir,AS_USER | NEED_WRITE}, /* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, /* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b1e2f00067..64e63abdf1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4205,56 +4205,65 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) Reply to a rmdir. ****************************************************************************/ -int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_rmdir(connection_struct *conn, struct smb_request *req) { pstring directory; - int outsize = 0; SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBrmdir); - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, - smb_buf(inbuf) + 1, sizeof(directory), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, directory, + smb_buf(req->inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBrmdir); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory); + status = resolve_dfspath(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + directory); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBrmdir); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBrmdir); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBrmdir); + return; } status = unix_convert(conn, directory, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBrmdir); - return ERROR_NT(status); + return; } status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBrmdir); - return ERROR_NT(status); + return; } - dptr_closepath(directory,SVAL(inbuf,smb_pid)); + dptr_closepath(directory, req->smbpid); status = rmdir_internals(conn, directory); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBrmdir); - return ERROR_NT(status); + return; } - outsize = set_message(inbuf,outbuf,0,0,False); + reply_outbuf(req, 0, 0); DEBUG( 3, ( "rmdir %s\n", directory ) ); END_PROFILE(SMBrmdir); - return(outsize); + return; } /******************************************************************* -- cgit From 8084a39ce0a2b2535c537115a08dd57dec82a102 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 30 Jul 2007 19:53:57 +0000 Subject: r24086: Convert reply_ulogoffX to the new API (This used to be commit bbc99e1c3b764bc2adf620553b7fa85efdf8ac53) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dafea5ed2f..70276293f8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -750,7 +750,7 @@ static const struct smb_message_struct { /* 0x71 */ { "SMBtdis",NULL,reply_tdis,DO_CHDIR}, /* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0}, /* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0}, -/* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */ +/* 0x74 */ { "SMBulogoffX", NULL,reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ /* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,0}, /* 0x76 */ { NULL, NULL, NULL, 0 }, /* 0x77 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 64e63abdf1..90f713a948 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1669,28 +1669,33 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +void reply_ulogoffX(connection_struct *conn, struct smb_request *req) { - uint16 vuid = SVAL(inbuf,smb_uid); - user_struct *vuser = get_valid_user_struct(vuid); + user_struct *vuser; + START_PROFILE(SMBulogoffX); - if(vuser == 0) - DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); + vuser = get_valid_user_struct(req->vuid); + + if(vuser == NULL) { + DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", + req->vuid)); + } /* in user level security we are supposed to close any files open by this user */ - if ((vuser != 0) && (lp_security() != SEC_SHARE)) - file_close_user(vuid); + if ((vuser != NULL) && (lp_security() != SEC_SHARE)) { + file_close_user(req->vuid); + } - invalidate_vuid(vuid); + invalidate_vuid(req->vuid); - set_message(inbuf,outbuf,2,0,True); + reply_outbuf(req, 2, 0); - DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); + DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) ); END_PROFILE(SMBulogoffX); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); } /**************************************************************************** -- cgit From 4254af71803b122449887258ac0e721f67ed39a3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 07:57:33 +0000 Subject: r24088: Convert reply_unlink to the new API (This used to be commit fb0a1b7bd0a195dbedb3b0c02d8a4ec25c21b9bf) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 52 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 70276293f8..e99d70f236 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -640,7 +640,7 @@ static const struct smb_message_struct { /* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, /* 0x05 */ { "SMBflush",reply_flush,NULL,AS_USER}, -/* 0x06 */ { "SMBunlink",reply_unlink,NULL,AS_USER | NEED_WRITE }, +/* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE }, /* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE }, /* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER}, /* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 90f713a948..c703a4d72b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2222,56 +2222,66 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, Reply to a unlink ****************************************************************************/ -int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, - int dum_buffsize) +void reply_unlink(connection_struct *conn, struct smb_request *req) { - int outsize = 0; pstring name; uint32 dirtype; NTSTATUS status; BOOL path_contains_wcard = False; - struct smb_request req; START_PROFILE(SMBunlink); - init_smb_request(&req, (uint8 *)inbuf); + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBunlink); + return; + } - dirtype = SVAL(inbuf,smb_vwv0); + dirtype = SVAL(req->inbuf,smb_vwv0); - srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, - smb_buf(inbuf) + 1, sizeof(name), 0, + srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, + smb_buf(req->inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBunlink); - return ERROR_NT(status); + return; } - status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard); + status = resolve_dfspath_wcard(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + name, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBunlink); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBunlink); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBunlink); + return; } DEBUG(3,("reply_unlink : %s\n",name)); - status = unlink_internals(conn, &req, dirtype, name, + status = unlink_internals(conn, req, dirtype, name, path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBunlink); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + END_PROFILE(SMBunlink); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBunlink); + return; } - outsize = set_message(inbuf,outbuf,0,0,False); - + reply_outbuf(req, 0, 0); END_PROFILE(SMBunlink); - return outsize; + + return; } /**************************************************************************** -- cgit From 15dc8917dbe5a1fed5ca909bb1bee24cff59db0f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 08:06:56 +0000 Subject: r24089: Add reply_prep/post_legacy Routines to ease the transition to the new API (This used to be commit 1bb2b341e2cb6c0175376dc8bd2d1ce6d9c6c00e) --- source3/smbd/process.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e99d70f236..1fba7e487c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -67,6 +67,60 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) req->outbuf = NULL; } +/* + * From within a converted call you might have to call non-converted + * subroutines that still take the old inbuf/outbuf/lenght/bufsize + * parameters. This takes a struct smb_request and prepares the legacy + * parameters. + */ + +BOOL reply_prep_legacy(struct smb_request *req, + char **pinbuf, char **poutbuf, + int *psize, int *pbufsize) +{ + const int bufsize = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + + SAFETY_MARGIN); + char *inbuf, *outbuf; + + if (!(inbuf = TALLOC_ARRAY(req, char, bufsize))) { + DEBUG(0, ("Could not allocate legacy inbuf\n")); + return False; + } + memcpy(inbuf, req->inbuf, MIN(smb_len(req->inbuf)+4, bufsize)); + req->inbuf = (uint8 *)inbuf; + + if (!(outbuf = TALLOC_ARRAY(req, char, bufsize))) { + DEBUG(0, ("Could not allocate legacy outbuf\n")); + return False; + } + req->outbuf = (uint8 *)outbuf; + + construct_reply_common(inbuf, outbuf); + + *pinbuf = inbuf; + *poutbuf = outbuf; + *psize = smb_len(inbuf)+4; + *pbufsize = bufsize; + + return True; +} + +/* + * Post-process the output of the legacy routine so that the result fits into + * the new reply_xxx API + */ + +void reply_post_legacy(struct smb_request *req, int outsize) +{ + if (outsize > 0) { + smb_setlen((char *)req->inbuf, (char *)req->outbuf, + outsize); + } + else { + TALLOC_FREE(req->outbuf); + } +} + /**************************************************************************** structure to hold a linked list of queued messages. for processing. -- cgit From 5e9d12cd3062be663bdcefd0131a88e966c62c60 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 08:37:54 +0000 Subject: r24090: Separate parsing in reply_ntcreate_and_X In particular, check if we have enough parameters (This used to be commit 7a19b3071e1d5d5002013a67794261bf6be0c81d) --- source3/smbd/nttrans.c | 50 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e435e1b6fb..989e99e6e8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -484,13 +484,14 @@ int reply_ntcreate_and_X(connection_struct *conn, { int result; pstring fname; - uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); - uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); - uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); - uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); - uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); - uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); - uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); + uint32 flags; + uint32 access_mask; + uint32 file_attributes; + uint32 share_access; + uint32 create_disposition; + uint32 create_options; + uint16 root_dir_fid; + SMB_BIG_UINT allocation_size; /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; @@ -510,6 +511,25 @@ int reply_ntcreate_and_X(connection_struct *conn, START_PROFILE(SMBntcreateX); + init_smb_request(&req, (uint8 *)inbuf); + + if (req.wct < 24) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + flags = IVAL(inbuf,smb_ntcreate_Flags); + access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); + file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); + share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); + create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); + create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); + root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); + + allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); +#ifdef LARGE_SMB_OFF_T + allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); +#endif + DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " "file_attributes = 0x%x, share_access = 0x%x, " "create_disposition = 0x%x create_options = 0x%x " @@ -522,8 +542,6 @@ int reply_ntcreate_and_X(connection_struct *conn, (unsigned int)create_options, (unsigned int)root_dir_fid )); - init_smb_request(&req, (uint8 *)inbuf); - /* * If it's an IPC, use the pipe handler. */ @@ -562,7 +580,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, + srvstr_get_path(inbuf, req.flags2, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -606,7 +624,7 @@ int reply_ntcreate_and_X(connection_struct *conn, dir_name_len++; } - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), rel_fname, + srvstr_get_path(inbuf, req.flags2, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -615,7 +633,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } pstrcat(fname, rel_fname); } else { - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, + srvstr_get_path(inbuf, req.flags2, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -654,7 +672,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req.flags2 & FLAGS2_DFS_PATHNAMES, fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -842,7 +860,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } else { TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req.mid)) { /* We have re-scheduled this call. */ return -1; } @@ -866,10 +884,6 @@ int reply_ntcreate_and_X(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); -#ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); -#endif if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { -- cgit From d95725370ffb8613828a440a513201520ffb5de3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 08:56:08 +0000 Subject: r24091: Convert reply_ntcreate_and_X to the new API The routines called will follow (This used to be commit 28025fc17efa033515cef94789e518a6615e141f) --- source3/smbd/nttrans.c | 172 +++++++++++++++++++++++++++++++------------------ source3/smbd/process.c | 2 +- 2 files changed, 110 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 989e99e6e8..e4cc968b17 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -479,10 +479,9 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, Reply to an NT create and X call. ****************************************************************************/ -int reply_ntcreate_and_X(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +void reply_ntcreate_and_X(connection_struct *conn, + struct smb_request *req) { - int result; pstring fname; uint32 flags; uint32 access_mask; @@ -506,28 +505,26 @@ int reply_ntcreate_and_X(connection_struct *conn, struct timespec m_timespec; BOOL extended_oplock_granted = False; NTSTATUS status; - struct smb_request req; struct case_semantics_state *case_state = NULL; START_PROFILE(SMBntcreateX); - init_smb_request(&req, (uint8 *)inbuf); - - if (req.wct < 24) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if (req->wct < 24) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } - flags = IVAL(inbuf,smb_ntcreate_Flags); - access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); - file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); - share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); - create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); - create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); - root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); + flags = IVAL(req->inbuf,smb_ntcreate_Flags); + access_mask = IVAL(req->inbuf,smb_ntcreate_DesiredAccess); + file_attributes = IVAL(req->inbuf,smb_ntcreate_FileAttributes); + share_access = IVAL(req->inbuf,smb_ntcreate_ShareAccess); + create_disposition = IVAL(req->inbuf,smb_ntcreate_CreateDisposition); + create_options = IVAL(req->inbuf,smb_ntcreate_CreateOptions); + root_dir_fid = (uint16)IVAL(req->inbuf,smb_ntcreate_RootDirectoryFid); - allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); + allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_ntcreate_AllocationSize); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(req->inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " @@ -548,17 +545,30 @@ int reply_ntcreate_and_X(connection_struct *conn, if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { + char *inbuf, *outbuf; + int length, bufsize; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, + &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + reply_post_legacy(req, do_ntcreate_pipe_open( + conn, inbuf, outbuf, + length, bufsize)); END_PROFILE(SMBntcreateX); - return do_ntcreate_pipe_open(conn,inbuf,outbuf,length,bufsize); + return; } else { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRnoaccess)); + return; } } if (create_options & FILE_OPEN_BY_FILE_ID) { + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + return; } /* @@ -570,22 +580,25 @@ int reply_ntcreate_and_X(connection_struct *conn, * This filename is relative to a directory fid. */ pstring rel_fname; - files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid); + files_struct *dir_fsp = file_fsp( + (char *)req->inbuf, smb_ntcreate_RootDirectoryFid); size_t dir_name_len; if(!dir_fsp) { + reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBntcreateX); - return ERROR_DOS(ERRDOS,ERRbadfid); + return; } if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, req.flags2, fname, - smb_buf(inbuf), sizeof(fname), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, fname, + smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return; } /* @@ -593,8 +606,10 @@ int reply_ntcreate_and_X(connection_struct *conn, */ if( is_ntfs_stream_name(fname)) { + reply_nterror( + req, NT_STATUS_OBJECT_PATH_NOT_FOUND); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return; } /* @@ -604,8 +619,9 @@ int reply_ntcreate_and_X(connection_struct *conn, (hint from demyn plantenberg) */ + reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRbadfid)); + return; } /* @@ -624,21 +640,23 @@ int reply_ntcreate_and_X(connection_struct *conn, dir_name_len++; } - srvstr_get_path(inbuf, req.flags2, rel_fname, - smb_buf(inbuf), sizeof(rel_fname), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, rel_fname, + smb_buf(req->inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return; } pstrcat(fname, rel_fname); } else { - srvstr_get_path(inbuf, req.flags2, fname, - smb_buf(inbuf), sizeof(fname), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, fname, + smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return; } /* @@ -648,6 +666,10 @@ int reply_ntcreate_and_X(connection_struct *conn, if( is_ntfs_stream_name(fname)) { enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname); if (fake_file_type!=FAKE_FILE_TYPE_NONE) { + + char *inbuf, *outbuf; + int length, bufsize; + /* * Here we go! support for changing the disk quotas --metze * @@ -657,13 +679,21 @@ int reply_ntcreate_and_X(connection_struct *conn, * w2k close this file directly after openening * xp also tries a QUERY_FILE_INFO on the file and then close it */ - result = reply_ntcreate_and_X_quota(conn, inbuf, outbuf, length, bufsize, - fake_file_type, fname); + if (!reply_prep_legacy(req, &inbuf, &outbuf, + &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + reply_post_legacy(req, reply_ntcreate_and_X_quota( + conn, inbuf, outbuf, + length, bufsize, + fake_file_type, fname)); END_PROFILE(SMBntcreateX); - return result; + return; } else { + reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + return; } } } @@ -672,13 +702,18 @@ int reply_ntcreate_and_X(connection_struct *conn, * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ - status = resolve_dfspath(conn, req.flags2 & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); } - return ERROR_NT(status); + else { + reply_nterror(req, status); + } + END_PROFILE(SMBntcreateX); + return; } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -702,15 +737,17 @@ int reply_ntcreate_and_X(connection_struct *conn, status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); + reply_nterror(req, status); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return; } /* All file access must go through check_name() */ status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); + reply_nterror(req, status); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return; } /* This is the correct thing to do (check every time) but can_delete is @@ -728,8 +765,9 @@ int reply_ntcreate_and_X(connection_struct *conn, if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || !can_delete_file_in_directory(conn, fname)) { TALLOC_FREE(case_state); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + return; } } @@ -753,12 +791,13 @@ int reply_ntcreate_and_X(connection_struct *conn, /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { TALLOC_FREE(case_state); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } oplock_request = 0; - status = open_directory(conn, &req, fname, &sbuf, + status = open_directory(conn, req, fname, &sbuf, access_mask, share_access, create_disposition, @@ -773,8 +812,9 @@ int reply_ntcreate_and_X(connection_struct *conn, status, NT_STATUS_OBJECT_NAME_COLLISION)) { status = NT_STATUS_DOS(ERRDOS, ERRfilexists); } + reply_nterror(req, status); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return; } } else { @@ -796,7 +836,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - status = open_file_ntcreate(conn, &req, fname, &sbuf, + status = open_file_ntcreate(conn, req, fname, &sbuf, access_mask, share_access, create_disposition, @@ -834,12 +874,13 @@ int reply_ntcreate_and_X(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { TALLOC_FREE(case_state); + reply_nterror(req, NT_STATUS_FILE_IS_A_DIRECTORY); END_PROFILE(SMBntcreateX); - return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); + return; } oplock_request = 0; - status = open_directory(conn, &req, fname, + status = open_directory(conn, req, fname, &sbuf, access_mask, share_access, @@ -854,17 +895,19 @@ int reply_ntcreate_and_X(connection_struct *conn, status, NT_STATUS_OBJECT_NAME_COLLISION)) { status = NT_STATUS_DOS(ERRDOS, ERRfilexists); } + reply_nterror(req, status); END_PROFILE(SMBntcreateX); - return ERROR_NT(status); + return; } } else { TALLOC_FREE(case_state); END_PROFILE(SMBntcreateX); - if (open_was_deferred(req.mid)) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } } } @@ -878,8 +921,9 @@ int reply_ntcreate_and_X(connection_struct *conn, } if (!fsp->is_directory && (fattr & aDIR)) { close_file(fsp,ERROR_CLOSE); + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBntcreateX); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } /* Save the requested allocation size. */ @@ -888,14 +932,16 @@ int reply_ntcreate_and_X(connection_struct *conn, fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,ERROR_CLOSE); - END_PROFILE(SMBntcreateX); /* Can't set allocation size on a directory. */ - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + END_PROFILE(SMBntcreateX); + return; } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,ERROR_CLOSE); + reply_nterror(req, NT_STATUS_DISK_FULL); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_DISK_FULL); + return; } } else { fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); @@ -922,13 +968,13 @@ int reply_ntcreate_and_X(connection_struct *conn, * the wcnt to 42 ? It's definately * what happens on the wire.... */ - set_message(inbuf,outbuf,50,0,True); - SCVAL(outbuf,smb_wct,42); + reply_outbuf(req, 50, 0); + SCVAL(req->outbuf,smb_wct,42); } else { - set_message(inbuf,outbuf,34,0,True); + reply_outbuf(req, 34, 0); } - p = outbuf + smb_vwv2; + p = (char *)req->outbuf + smb_vwv2; /* * Currently as we don't support level II oplocks we just report @@ -1001,9 +1047,9 @@ int reply_ntcreate_and_X(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - result = chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); END_PROFILE(SMBntcreateX); - return result; + return; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1fba7e487c..2773779898 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -850,7 +850,7 @@ static const struct smb_message_struct { /* 0x9f */ { NULL, NULL, NULL, 0 }, /* 0xa0 */ { "SMBnttrans", reply_nttrans,NULL, AS_USER | CAN_IPC }, /* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC }, -/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X,NULL, AS_USER | CAN_IPC }, +/* 0xa2 */ { "SMBntcreateX", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC }, /* 0xa3 */ { NULL, NULL, NULL, 0 }, /* 0xa4 */ { "SMBntcancel", reply_ntcancel,NULL, 0 }, /* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE }, -- cgit From 04dcbbbd6886b5347d35407348541ff6d415e100 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 09:22:16 +0000 Subject: r24092: Convert do_ntcreate_pipe_open to the new API nt_open_pipe_new() is a copy of nt_open_pipe(). It will stick for a bit until do_nt_transact_create_pipe is converted as well. (This used to be commit 247d6baaed6f017328de6688e6daa15aa6aaa18e) --- source3/smbd/nttrans.c | 92 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e4cc968b17..62c8c62fa0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -321,7 +321,8 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx } /**************************************************************************** - Reply to an NT create and X call on a pipe. + Reply to an NT create and X call on a pipe -- this will die when all + callers are converted to nt_open_pipe_new ****************************************************************************/ static int nt_open_pipe(char *fname, connection_struct *conn, @@ -369,24 +370,75 @@ static int nt_open_pipe(char *fname, connection_struct *conn, return 0; } +static void nt_open_pipe_new(char *fname, connection_struct *conn, + struct smb_request *req, int *ppnum) +{ + smb_np_struct *p = NULL; + int i; + + DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); + + /* See if it is one we want to handle. */ + + if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) { + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpipe); + return; + } + + for( i = 0; known_nt_pipes[i]; i++ ) { + if( strequal(fname,known_nt_pipes[i])) { + break; + } + } + + if ( known_nt_pipes[i] == NULL ) { + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpipe); + return; + } + + /* Strip \\ off the name. */ + fname++; + + DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); + + p = open_rpc_pipe_p(fname, conn, req->vuid); + if (!p) { + reply_doserror(req, ERRSRV, ERRnofids); + return; + } + + /* TODO: Add pipe to db */ + + if ( !store_pipe_opendb( p ) ) { + DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname)); + } + + *ppnum = p->pnum; + return; +} + /**************************************************************************** Reply to an NT create and X call for pipes. ****************************************************************************/ -static int do_ntcreate_pipe_open(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +static void do_ntcreate_pipe_open(connection_struct *conn, + struct smb_request *req) { pstring fname; - int ret; int pnum = -1; char *p = NULL; - uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); + uint32 flags = IVAL(req->inbuf,smb_ntcreate_Flags); - srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), fname, smb_buf(inbuf), - sizeof(fname), STR_TERMINATE); + srvstr_pull_buf((char *)req->inbuf, req->flags2, fname, + smb_buf(req->inbuf), sizeof(fname), STR_TERMINATE); - if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { - return ret; + nt_open_pipe_new(fname, conn, req, &pnum); + + if (req->outbuf) { + /* error reply */ + return; } /* @@ -399,13 +451,13 @@ static int do_ntcreate_pipe_open(connection_struct *conn, * the wcnt to 42 ? It's definately * what happens on the wire.... */ - set_message(inbuf,outbuf,50,0,True); - SCVAL(outbuf,smb_wct,42); + reply_outbuf(req, 50, 0); + SCVAL(req->outbuf,smb_wct,42); } else { - set_message(inbuf,outbuf,34,0,True); + reply_outbuf(req, 34, 0); } - p = outbuf + smb_vwv2; + p = (char *)req->outbuf + smb_vwv2; p++; SSVAL(p,0,pnum); p += 2; @@ -433,7 +485,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname)); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); } /**************************************************************************** @@ -545,17 +597,7 @@ void reply_ntcreate_and_X(connection_struct *conn, if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { - char *inbuf, *outbuf; - int length, bufsize; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, - &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - reply_post_legacy(req, do_ntcreate_pipe_open( - conn, inbuf, outbuf, - length, bufsize)); + do_ntcreate_pipe_open(conn, req); END_PROFILE(SMBntcreateX); return; } else { -- cgit From ae5da66e2321052f23260f3ebbe4854df31a4d66 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 09:41:21 +0000 Subject: r24097: Convert reply_ntcreate_and_X_quota to the new API (This used to be commit 08acadae56e0b603ccac7dc21f89d5071a33b255) --- source3/smbd/nttrans.c | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 62c8c62fa0..9aa824feda 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -492,17 +492,13 @@ static void do_ntcreate_pipe_open(connection_struct *conn, Reply to an NT create and X call for a quota file. ****************************************************************************/ -int reply_ntcreate_and_X_quota(connection_struct *conn, - char *inbuf, - char *outbuf, - int length, - int bufsize, - enum FAKE_FILE_TYPE fake_file_type, - const char *fname) +static void reply_ntcreate_and_X_quota(connection_struct *conn, + struct smb_request *req, + enum FAKE_FILE_TYPE fake_file_type, + const char *fname) { - int result; char *p; - uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); + uint32 desired_access = IVAL(req->inbuf,smb_ntcreate_DesiredAccess); files_struct *fsp; NTSTATUS status; @@ -510,12 +506,13 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, &fsp); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } - set_message(inbuf,outbuf,34,0,True); + reply_outbuf(req, 34, 0); - p = outbuf + smb_vwv2; + p = (char *)req->outbuf + smb_vwv2; /* SCVAL(p,0,NO_OPLOCK_RETURN); */ p++; @@ -523,8 +520,7 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - result = chain_reply(inbuf,&outbuf,length,bufsize); - return result; + chain_reply_new(req); } /**************************************************************************** @@ -708,10 +704,6 @@ void reply_ntcreate_and_X(connection_struct *conn, if( is_ntfs_stream_name(fname)) { enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname); if (fake_file_type!=FAKE_FILE_TYPE_NONE) { - - char *inbuf, *outbuf; - int length, bufsize; - /* * Here we go! support for changing the disk quotas --metze * @@ -721,22 +713,13 @@ void reply_ntcreate_and_X(connection_struct *conn, * w2k close this file directly after openening * xp also tries a QUERY_FILE_INFO on the file and then close it */ - if (!reply_prep_legacy(req, &inbuf, &outbuf, - &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - reply_post_legacy(req, reply_ntcreate_and_X_quota( - conn, inbuf, outbuf, - length, bufsize, - fake_file_type, fname)); - END_PROFILE(SMBntcreateX); - return; + reply_ntcreate_and_X_quota(conn, req, + fake_file_type, fname); } else { reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); - END_PROFILE(SMBntcreateX); - return; } + END_PROFILE(SMBntcreateX); + return; } } -- cgit From 4473a5ec545ad4b087f6ac6738a961c6cddabb82 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 10:04:54 +0000 Subject: r24100: Convert reply_ntcancel to the new API (This used to be commit 6e5f39379f60e30cd0445a049df619ec8f65fc01) --- source3/smbd/nttrans.c | 14 ++++++-------- source3/smbd/process.c | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9aa824feda..8250942274 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1786,23 +1786,21 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_ntcancel(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +void reply_ntcancel(connection_struct *conn, struct smb_request *req) { /* * Go through and cancel any pending change notifies. */ - int mid = SVAL(inbuf,smb_mid); START_PROFILE(SMBntcancel); - remove_pending_change_notify_requests_by_mid(mid); - remove_pending_lock_requests_by_mid(mid); - srv_cancel_sign_response(mid); + remove_pending_change_notify_requests_by_mid(req->mid); + remove_pending_lock_requests_by_mid(req->mid); + srv_cancel_sign_response(req->mid); - DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); + DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", req->mid)); END_PROFILE(SMBntcancel); - return(-1); + return; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2773779898..ab2f205ebe 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -852,7 +852,7 @@ static const struct smb_message_struct { /* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC }, /* 0xa2 */ { "SMBntcreateX", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC }, /* 0xa3 */ { NULL, NULL, NULL, 0 }, -/* 0xa4 */ { "SMBntcancel", reply_ntcancel,NULL, 0 }, +/* 0xa4 */ { "SMBntcancel", NULL,reply_ntcancel, 0 }, /* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE }, /* 0xa6 */ { NULL, NULL, NULL, 0 }, /* 0xa7 */ { NULL, NULL, NULL, 0 }, -- cgit From 3d769de244b9193e309a7e1c8f602985b0c1fa75 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 11:26:24 +0000 Subject: r24101: Move prohibited_ea_names[] into samba_private_attr_name() Minor cleanup (This used to be commit 04879717229d5b74b94b79a962cca5e9624648bc) --- source3/smbd/trans2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 18b51ab56c..b5077ed8ff 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -90,18 +90,18 @@ SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, con Utility functions for dealing with extended attributes. ****************************************************************************/ -static const char *prohibited_ea_names[] = { - SAMBA_POSIX_INHERITANCE_EA_NAME, - SAMBA_XATTR_DOS_ATTRIB, - NULL -}; - /**************************************************************************** Refuse to allow clients to overwrite our private xattrs. ****************************************************************************/ static BOOL samba_private_attr_name(const char *unix_ea_name) { + static const char *prohibited_ea_names[] = { + SAMBA_POSIX_INHERITANCE_EA_NAME, + SAMBA_XATTR_DOS_ATTRIB, + NULL + }; + int i; for (i = 0; prohibited_ea_names[i]; i++) { -- cgit From a2d6aa829faa65df14ee566e455e807693cc2bd9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 12:05:40 +0000 Subject: r24102: Pass the fid instead of inbuf and an offset to file_fsp. This removes the buf==NULL condition in file_fsp(), but wherever it is called we do have a buffer anyway. Volker (This used to be commit d70a1f82fed64fa332f16407bea7c6671f48c59a) --- source3/smbd/files.c | 8 ++------ source3/smbd/nttrans.c | 18 +++++++++--------- source3/smbd/reply.c | 46 +++++++++++++++++++++++----------------------- source3/smbd/trans2.c | 8 ++++---- 4 files changed, 38 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 07dec80a47..9d27c69a6b 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -487,7 +487,7 @@ files_struct *file_fnum(uint16 fnum) Get an fsp from a packet given the offset of a 16 bit fnum. ****************************************************************************/ -files_struct *file_fsp(const char *buf, int where) +files_struct *file_fsp(uint16 fid) { files_struct *fsp; @@ -495,11 +495,7 @@ files_struct *file_fsp(const char *buf, int where) return chain_fsp; } - if (!buf) { - return NULL; - } - - fsp = file_fnum(SVAL(buf, where)); + fsp = file_fnum(fid); if (fsp) { chain_fsp = fsp; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8250942274..3676079ec8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -619,7 +619,7 @@ void reply_ntcreate_and_X(connection_struct *conn, */ pstring rel_fname; files_struct *dir_fsp = file_fsp( - (char *)req->inbuf, smb_ntcreate_RootDirectoryFid); + SVAL(req->inbuf, smb_ntcreate_RootDirectoryFid)); size_t dir_name_len; if(!dir_fsp) { @@ -1377,7 +1377,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* * This filename is relative to a directory fid. */ - files_struct *dir_fsp = file_fsp(params,4); + files_struct *dir_fsp = file_fsp(SVAL(params,4)); size_t dir_name_len; if(!dir_fsp) { @@ -2078,7 +2078,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, return ERROR_DOS(ERRDOS,ERRbadfunc); } - fsp = file_fsp((char *)setup,4); + fsp = file_fsp(SVAL(setup,4)); filter = IVAL(setup, 0); recursive = (SVAL(setup, 6) != 0) ? True : False; @@ -2173,7 +2173,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o return ERROR_DOS(ERRDOS,ERRbadfunc); } - fsp = file_fsp(params, 0); + fsp = file_fsp(SVAL(params, 0)); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), new_name, params+4, @@ -2244,7 +2244,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i return ERROR_DOS(ERRDOS,ERRbadfunc); } - fsp = file_fsp(params,0); + fsp = file_fsp(SVAL(params,0)); if(!fsp) { return ERROR_DOS(ERRDOS,ERRbadfid); } @@ -2358,7 +2358,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb return ERROR_DOS(ERRDOS,ERRbadfunc); } - if((fsp = file_fsp(params,0)) == NULL) { + if((fsp = file_fsp(SVAL(params,0))) == NULL) { return ERROR_DOS(ERRDOS,ERRbadfid); } @@ -2415,7 +2415,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", function, fidnum, isFSctl, compfilter)); - fsp=file_fsp((char *)*ppsetup, 4); + fsp=file_fsp(SVAL(ppsetup, 4)); /* this check is done in each implemented function case for now because I don't want to break anything... --metze FSP_BELONGS_CONN(fsp,conn);*/ @@ -2693,7 +2693,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, } /* maybe we can check the quota_fnum */ - fsp = file_fsp(params,0); + fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); return ERROR_NT(NT_STATUS_INVALID_HANDLE); @@ -2941,7 +2941,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, } /* maybe we can check the quota_fnum */ - fsp = file_fsp(params,0); + fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); return ERROR_NT(NT_STATUS_INVALID_HANDLE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c703a4d72b..385a47bbf3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -709,7 +709,7 @@ int reply_ioctl(connection_struct *conn, switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: { - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); if (!fsp) { END_PROFILE(SMBioctl); return(UNIXERROR(ERRDOS,ERRbadfid)); @@ -2433,7 +2433,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s * return a zero length response here. */ - fsp = file_fsp(inbuf,smb_vwv0); + fsp = file_fsp(SVAL(inbuf,smb_vwv0)); if (!FNUM_OK(fsp,conn) || !fsp->can_read) { /* @@ -2538,7 +2538,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length SMB_OFF_T startpos; size_t numtoread; NTSTATUS status; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); struct byte_range_lock *br_lck = NULL; START_PROFILE(SMBlockread); @@ -2624,7 +2624,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int char *data; SMB_OFF_T startpos; int outsize = 0; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBread); CHECK_FSP(fsp,conn); @@ -2827,7 +2827,7 @@ normal_read: int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = file_fsp(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2)); SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); ssize_t nread = -1; size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); @@ -2928,7 +2928,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SMB_OFF_T startpos; char *data=NULL; BOOL write_through; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); int outsize = 0; NTSTATUS status; START_PROFILE(SMBwritebraw); @@ -3079,7 +3079,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, SMB_OFF_T startpos; char *data; NTSTATUS status = NT_STATUS_OK; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); int outsize = 0; START_PROFILE(SMBwriteunlock); @@ -3157,7 +3157,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d ssize_t nwritten = -1; SMB_OFF_T startpos; char *data; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); int outsize = 0; NTSTATUS status; START_PROFILE(SMBwrite); @@ -3240,7 +3240,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = file_fsp(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2)); SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); size_t numtowrite = SVAL(inbuf,smb_vwv10); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); @@ -3362,7 +3362,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_OFF_T res= -1; int mode,umode; int outsize = 0; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBlseek); CHECK_FSP(fsp,conn); @@ -3434,7 +3434,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int { int outsize = set_message(inbuf,outbuf,0,0,False); uint16 fnum = SVAL(inbuf,smb_vwv0); - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBflush); if (fnum != 0xFFFF) @@ -3501,7 +3501,7 @@ void reply_close(connection_struct *conn, struct smb_request *req) return; } - fsp = file_fsp((char *)req->inbuf,smb_vwv0); + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); /* * We can only use CHECK_FSP if we know it's not a directory. @@ -3570,7 +3570,7 @@ int reply_writeclose(connection_struct *conn, SMB_OFF_T startpos; char *data; struct timespec mtime; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBwriteclose); CHECK_FSP(fsp,conn); @@ -3637,7 +3637,7 @@ int reply_lock(connection_struct *conn, int outsize = set_message(inbuf,outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); struct byte_range_lock *br_lck = NULL; START_PROFILE(SMBlock); @@ -3684,7 +3684,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = set_message(inbuf,outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBunlock); CHECK_FSP(fsp,conn); @@ -3830,7 +3830,7 @@ int reply_printclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(inbuf,outbuf,0,0,False); - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); NTSTATUS status; START_PROFILE(SMBsplclose); @@ -3935,7 +3935,7 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ int numtowrite; int outsize = set_message(inbuf,outbuf,0,0,False); char *data; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBsplwr); @@ -5533,7 +5533,7 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize) { - files_struct *fsp = file_fsp(inbuf,smb_vwv2); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2)); unsigned char locktype = CVAL(inbuf,smb_vwv3); unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); @@ -5860,7 +5860,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, int max_per_packet; size_t tcount; int pad; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBreadBmpx); /* this function doesn't seem to work - disable by default */ @@ -5931,7 +5931,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, { struct timespec ts[2]; int outsize = 0; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBsetattrE); outsize = set_message(inbuf,outbuf,0,0,False); @@ -6000,7 +6000,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, BOOL write_through; int smb_doff; char *data; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); NTSTATUS status; START_PROFILE(SMBwriteBmpx); @@ -6112,7 +6112,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz char *data; write_bmpx_struct *wbms; BOOL send_response = False; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); NTSTATUS status; START_PROFILE(SMBwriteBs); @@ -6201,7 +6201,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, SMB_STRUCT_STAT sbuf; int outsize = 0; int mode; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBgetattrE); outsize = set_message(inbuf,outbuf,11,0,True); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b5077ed8ff..d455a12fa1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2859,7 +2859,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", * but we didn't use the last 6 bytes for now * --metze */ - fsp = file_fsp(params,0); + fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); return ERROR_NT(NT_STATUS_INVALID_HANDLE); @@ -3341,7 +3341,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * max_data_bytes); } - fsp = file_fsp(params,0); + fsp = file_fsp(SVAL(params,0)); info_level = SVAL(params,2); DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); @@ -5860,7 +5860,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = file_fsp(params,0); + fsp = file_fsp(SVAL(params,0)); info_level = SVAL(params,2); if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) { @@ -6460,7 +6460,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, unsigned int max_data_bytes) { char *pdata = *ppdata; - files_struct *fsp = file_fsp(inbuf,smb_vwv15); + files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15)); /* check for an invalid fid before proceeding */ -- cgit From bfbd75653581ab21ce3f26b006c00389b7939bd7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Jul 2007 13:14:07 +0000 Subject: r24106: Pass fnum instead of buf/offset into get_rpc_pipe_p (This used to be commit eb353412c60fc21a31530d9678505470ffbf11ce) --- source3/smbd/pipes.c | 8 ++++---- source3/smbd/trans2.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index a4ac807377..24e0f47001 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -140,7 +140,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) { - smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0); + smb_np_struct *p = get_rpc_pipe_p(SVAL(inbuf,smb_vwv0)); uint16 vuid = SVAL(inbuf,smb_uid); size_t numtowrite = SVAL(inbuf,smb_vwv1); int nwritten; @@ -185,7 +185,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); + smb_np_struct *p = get_rpc_pipe_p(SVAL(inbuf,smb_vwv2)); uint16 vuid = SVAL(inbuf,smb_uid); size_t numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; @@ -247,7 +247,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); + smb_np_struct *p = get_rpc_pipe_p(SVAL(inbuf,smb_vwv2)); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); int nread = -1; @@ -292,7 +292,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) void reply_pipe_close(connection_struct *conn, struct smb_request *req) { - smb_np_struct *p = get_rpc_pipe_p((char *)req->inbuf,smb_vwv0); + smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv0)); if (!p) { reply_doserror(req, ERRDOS, ERRbadfid); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d455a12fa1..77a13ad186 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3244,7 +3244,7 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - p_pipe = get_rpc_pipe_p(params,0); + p_pipe = get_rpc_pipe_p(SVAL(params,0)); if (p_pipe == NULL) { return ERROR_NT(NT_STATUS_INVALID_HANDLE); } -- cgit From a0a9a301d258ffdd6e1f35a9d4d32c555237556c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 05:50:40 +0000 Subject: r24119: Convert reply_exit to the new API (This used to be commit d4d550aa2ba20d704d2ab1265732b03405e8819c) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ab2f205ebe..4acdb177a6 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -705,7 +705,7 @@ static const struct smb_message_struct { /* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER }, /* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER}, /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, -/* 0x11 */ { "SMBexit",reply_exit,NULL,DO_CHDIR}, +/* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR}, /* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER}, /* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER}, /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 385a47bbf3..ec27450593 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3462,20 +3462,18 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_exit(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_exit(connection_struct *conn, struct smb_request *req) { - int outsize; START_PROFILE(SMBexit); - file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid)); + file_close_pid(req->smbpid, req->vuid); - outsize = set_message(inbuf,outbuf,0,0,False); + reply_outbuf(req, 0, 0); DEBUG(3,("exit\n")); END_PROFILE(SMBexit); - return(outsize); + return; } /**************************************************************************** -- cgit From 4b15f31f106f1dd69fdda721b5c3b787f5245a80 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 2 Aug 2007 08:53:24 +0000 Subject: r24120: add a file_id_create() hook into the VFS layer it's needed for some cluster filesystems to overload this function. metze (This used to be commit cdaa24e8047399002e4b287a31a8340a665e580f) --- source3/smbd/close.c | 2 +- source3/smbd/filename.c | 3 ++- source3/smbd/open.c | 10 +++++----- source3/smbd/reply.c | 3 ++- source3/smbd/trans2.c | 14 ++++++++++---- 5 files changed, 20 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 7c3e1eef28..9718fef4ea 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -265,7 +265,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, goto done; } - id = file_id_sbuf(&sbuf); + id = vfs_file_id_from_sbuf(conn, &sbuf); if (!file_id_equal(&fsp->file_id, &id)) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a1b56736a0..d5c22e81c3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -540,7 +540,8 @@ NTSTATUS unix_convert(connection_struct *conn, } /* end else */ #ifdef DEVELOPER - if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) { + if (VALID_STAT(st) && + get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, &st))) { result = NT_STATUS_DELETE_PENDING; goto fail; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 432f6b808a..bff445bf61 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -357,7 +357,7 @@ static NTSTATUS open_file(files_struct *fsp, } fsp->mode = psbuf->st_mode; - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = True; @@ -1416,7 +1416,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = open_access_mask; /* We change this to the @@ -1432,7 +1432,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { - id = file_id_sbuf(psbuf); + id = vfs_file_id_from_sbuf(conn, psbuf); lck = get_share_mode_lock(NULL, id, conn->connectpath, @@ -2160,7 +2160,7 @@ NTSTATUS open_directory(connection_struct *conn, */ fsp->mode = psbuf->st_mode; - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; @@ -2288,7 +2288,7 @@ NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req, */ fsp->mode = psbuf->st_mode; - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ec27450593..cebb905a9e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4563,7 +4563,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin } if (dst_exists) { - files_struct *dst_fsp = file_find_di_first(file_id_sbuf(&sbuf1)); + struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1); + files_struct *dst_fsp = file_find_di_first(fileid); if (dst_fsp) { DEBUG(3, ("rename_internals_fsp: Target file open\n")); return NT_STATUS_ACCESS_DENIED; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 77a13ad186..2b0925d195 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3312,6 +3312,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * time_t create_time, mtime, atime; struct timespec create_time_ts, mtime_ts, atime_ts; files_struct *fsp = NULL; + struct file_id fileid; TALLOC_CTX *data_ctx = NULL; struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ @@ -3378,7 +3379,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return UNIXERROR(ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + delete_pending = get_delete_on_close_flag(fileid); } else { /* * Original code - this is an open file. @@ -3391,7 +3393,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return(UNIXERROR(ERRDOS,ERRbadfid)); } pos = fsp->fh->position_information; - delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + delete_pending = get_delete_on_close_flag(fileid); access_mask = fsp->access_mask; } } else { @@ -3446,7 +3449,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return UNIXERROR(ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + delete_pending = get_delete_on_close_flag(fileid); if (delete_pending) { return ERROR_NT(NT_STATUS_DELETE_PENDING); } @@ -3572,8 +3576,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd mtime_ts = fsp->pending_modtime; } } else { + files_struct *fsp1; /* Do we have this path open ? */ - files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf)); + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + fsp1 = file_find_di_first(fileid); if (fsp1 && !null_timespec(fsp1->pending_modtime)) { /* the pending modtime overrides the current modtime */ mtime_ts = fsp1->pending_modtime; -- cgit From 6c6fed5e656d64df9c9c12d7909f2c2289208bf7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 17:37:38 +0000 Subject: r24130: Explicitly pass flags2 to srvstr_push This is in preparation of the trans2 conversion: srvstr_push should not look at inbuf directly. (This used to be commit 5fd7e6a3821bea26d352e3edc23b7a216b1200e5) --- source3/smbd/lanman.c | 2 +- source3/smbd/nttrans.c | 5 ++- source3/smbd/reply.c | 14 ++++++--- source3/smbd/srvstr.c | 6 ++-- source3/smbd/trans2.c | 85 ++++++++++++++++++++++++++++++++++++-------------- 5 files changed, 80 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3568bb55b9..f7a4f9b0bd 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2866,7 +2866,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, p = *rdata; p2 = p + struct_len; if (uLevel != 20) { - srvstr_push(NULL, p,global_myname(),16, + srvstr_push(NULL, 0, p,global_myname(),16, STR_ASCII|STR_UPPER|STR_TERMINATE); } p += 16; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3676079ec8..c091ed1e71 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2571,7 +2571,10 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou shadow_data->num_volumes,fsp->fsp_name)); if (labels && shadow_data->labels) { for (i=0;inum_volumes;i++) { - srvstr_push(outbuf, cur_pdata, shadow_data->labels[i], 2*sizeof(SHADOW_COPY_LABEL), STR_UNICODE|STR_TERMINATE); + srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + cur_pdata, shadow_data->labels[i], + 2*sizeof(SHADOW_COPY_LABEL), + STR_UNICODE|STR_TERMINATE); cur_pdata+=2*sizeof(SHADOW_COPY_LABEL); DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i])); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cebb905a9e..4fbf179797 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -715,9 +715,13 @@ int reply_ioctl(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadfid)); } SSVAL(p,0,fsp->rap_print_jobid); /* Job number */ - srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII); + srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+2, + global_myname(), 15, + STR_TERMINATE|STR_ASCII); if (conn) { - srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); + srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + p+18, lp_servicename(SNUM(conn)), + 13, STR_TERMINATE|STR_ASCII); } break; } @@ -1909,7 +1913,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, thing in the byte section. JRA */ SSVALS(p, 0, -1); /* what is this? not in spec */ #endif - namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE); + namelen = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, s, -1, + STR_ASCII|STR_TERMINATE); p += namelen; outsize = set_message_end(inbuf,outbuf, p); @@ -3903,7 +3908,8 @@ int reply_printqueue(connection_struct *conn, SSVAL(p,5, queue[i].job); SIVAL(p,7,queue[i].size); SCVAL(p,11,0); - srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII); + srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12, + queue[i].fs_user, 16, STR_ASCII); p += 28; } diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 1daa25553f..df993537ba 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -24,7 +24,7 @@ extern int max_send; /* Make sure we can't write a string past the end of the buffer */ size_t srvstr_push_fn(const char *function, unsigned int line, - const char *base_ptr, void *dest, + const char *base_ptr, uint16 smb_flags2, void *dest, const char *src, int dest_len, int flags) { size_t buf_used = PTR_DIFF(dest, base_ptr); @@ -68,8 +68,8 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags) return -1; } - result = srvstr_push((char *)tmp, tmp + buf_size, str, grow_size, - flags); + result = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2), + tmp + buf_size, str, grow_size, flags); if (result == (size_t)-1) { DEBUG(0, ("srvstr_push failed\n")); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2b0925d195..8b4b36a7fa 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1303,7 +1303,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 23; nameptr = p; p += align_string(outbuf, p, 0); - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, + fname, -1, STR_TERMINATE); if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { if (len > 2) { SCVAL(nameptr, -1, len - 2); @@ -1338,7 +1339,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } p += 27; nameptr = p - 1; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + p, fname, -1, + STR_TERMINATE | STR_NOALIGN); if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { if (len > 2) { len -= 2; @@ -1394,7 +1397,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, /* Push the ea_data followed by the name. */ p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list); nameptr = p; - len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + p + 1, fname, -1, + STR_TERMINATE | STR_NOALIGN); if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { if (len > 2) { len -= 2; @@ -1442,7 +1447,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(mangled_name,True,True, conn->params); mangled_name[12] = 0; - len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); + len = srvstr_push(outbuf, + SVAL(outbuf, smb_flg2), + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); if (len < 24) { memset(p + 2 + len,'\0',24 - len); } @@ -1451,7 +1459,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, memset(p,'\0',26); } p += 2 + 24; - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, + fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1472,7 +1481,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,file_size); p += 8; SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; - len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + p + 4, fname, -1, + STR_TERMINATE_ASCII); SIVAL(p,0,len); p += 4 + len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1499,7 +1510,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,ea_size); /* Extended attributes */ p +=4; } - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, + fname, -1, STR_TERMINATE_ASCII); SIVAL(q, 0, len); p += len; @@ -1517,7 +1529,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; /* this must *not* be null terminated or w2k gets in a loop trying to set an acl on a dir (tridge) */ - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + p, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, -4, len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1547,7 +1560,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, + fname, -1, STR_TERMINATE_ASCII); SIVAL(q, 0, len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1585,7 +1599,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(mangled_name,True,True, conn->params); mangled_name[12] = 0; - len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); + len = srvstr_push(outbuf, + SVAL(outbuf, smb_flg2), + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); if (len < 24) { memset(p + 2 + len,'\0',24 - len); @@ -1598,7 +1615,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,0,0); p += 2; /* Reserved ? */ SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, + fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1621,14 +1639,19 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); p = store_file_unix_basic(conn, p, NULL, &sbuf); - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, + SVAL(outbuf, smb_flg2), + p, fname, -1, + STR_TERMINATE); } else { DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); p = store_file_unix_basic_info2(conn, p, NULL, &sbuf); nameptr = p; p += 4; - len = srvstr_push(outbuf, p, fname, -1, 0); + len = srvstr_push(outbuf, + SVAL(outbuf, smb_flg2), + p, fname, -1, 0); SIVAL(nameptr, 0, len); } @@ -2341,7 +2364,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi * this call so try fixing this by adding a terminating null to * the pushed string. The change here was adding the STR_TERMINATE. JRA. */ - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + pdata+l2_vol_szVolLabel, vname, + -1, STR_NOALIGN|STR_TERMINATE); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", @@ -2365,14 +2390,16 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it and will think we can't do long filenames */ - len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + pdata+12, fstype, -1, STR_UNICODE); SIVAL(pdata,8,len); data_len = 12 + len; break; case SMB_QUERY_FS_LABEL_INFO: case SMB_FS_LABEL_INFORMATION: - len = srvstr_push(outbuf, pdata+4, vname, -1, 0); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + pdata+4, vname, -1, 0); data_len = 4 + len; SIVAL(pdata,0,len); break; @@ -2388,7 +2415,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi (str_checksum(get_local_machine_name())<<16)); /* Max label len is 32 characters. */ - len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + pdata+18, vname, -1, STR_UNICODE); SIVAL(pdata,12,len); data_len = 18+len; @@ -3752,7 +3780,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if(!mangle_is_8_3(short_name, True, conn->params)) { mangle_map(short_name,True,True,conn->params); } - len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + pdata+4, short_name, -1, + STR_UNICODE); data_size = 4 + len; SIVAL(pdata,0,len); break; @@ -3762,7 +3792,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* this must be *exactly* right for ACLs on mapped drives to work */ - len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + pdata+4, dos_fname, -1, STR_UNICODE); DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n")); data_size = 4 + len; SIVAL(pdata,0,len); @@ -3803,7 +3834,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 24; SIVAL(pdata,0,ea_size); pdata += 4; /* EA info */ - len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE); + len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + pdata+4, dos_fname, -1, STR_UNICODE); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -3965,7 +3997,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (len == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); buffer[len] = 0; - len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE); + len = srvstr_push(outbuf, + SVAL(outbuf, smb_flg2), + pdata, buffer, -1, + STR_TERMINATE); pdata += len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -6485,8 +6520,12 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, CAN ACCEPT THIS IN UNICODE. JRA. */ SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */ - srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ - srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ + srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata + 2, + global_myname(), 15, + STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ + srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata+18, + lp_servicename(SNUM(conn)), 13, + STR_ASCII|STR_TERMINATE); /* Service name */ send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes); return(-1); } else { -- cgit From b62bd05b93e2317f78a4aea089295cf1162d23e2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 18:06:45 +0000 Subject: r24133: Explicitly pass flags2 down to push_string_fn This needs a bit closer review, it also touches the client libs (This used to be commit 824eb26738d64af1798d319d339582cf047521f0) --- source3/smbd/srvstr.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index df993537ba..fbcf249ffb 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -33,13 +33,17 @@ size_t srvstr_push_fn(const char *function, unsigned int line, #if 0 DEBUG(0, ("Pushing string of 'unlimited' length into non-SMB buffer!\n")); #endif - return push_string_fn(function, line, base_ptr, dest, src, -1, flags); + return push_string_fn(function, line, base_ptr, + smb_flags2, dest, src, -1, + flags); } - return push_string_fn(function, line, base_ptr, dest, src, max_send - buf_used, flags); + return push_string_fn(function, line, base_ptr, smb_flags2, + dest, src, max_send - buf_used, flags); } /* 'normal' push into size-specified buffer */ - return push_string_fn(function, line, base_ptr, dest, src, dest_len, flags); + return push_string_fn(function, line, base_ptr, smb_flags2, dest, src, + dest_len, flags); } /******************************************************************* -- cgit From d526657d5f8f269782eb92228d5d0390c7d37efa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 18:13:57 +0000 Subject: r24134: talloc smb_request for handle_trans2 When starting to convert the individual trans2 subcalls, I need the new API conventions to be present there. This means that those calls fill in req->outbuf when there's something to ship (This used to be commit d9eef977dc80d6ee71898efc1ff736afb75eba0c) --- source3/smbd/trans2.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8b4b36a7fa..3a1a1ca816 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6882,11 +6882,22 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, if ((state->received_param == state->total_param) && (state->received_data == state->total_data)) { - struct smb_request req; - init_smb_request(&req, (uint8 *)inbuf); + struct smb_request *req; - outsize = handle_trans2(conn, &req, state, inbuf, outbuf, + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + END_PROFILE(SMBtrans2); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + init_smb_request(req, (uint8 *)inbuf); + + outsize = handle_trans2(conn, req, state, inbuf, outbuf, size, bufsize); + if (req->outbuf != NULL) { + outsize = smb_len(req->outbuf) + 4; + memcpy(outbuf, req->outbuf, outsize); + } + TALLOC_FREE(req); SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); @@ -6924,7 +6935,7 @@ int reply_transs2(connection_struct *conn, int outsize = 0; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - struct smb_request req; + struct smb_request *req; START_PROFILE(SMBtranss2); @@ -7010,10 +7021,20 @@ int reply_transs2(connection_struct *conn, */ SCVAL(outbuf,smb_com,SMBtrans2); - init_smb_request(&req, (uint8 *)inbuf); + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + END_PROFILE(SMBtranss2); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } - outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size, + init_smb_request(req, (uint8 *)inbuf); + + outsize = handle_trans2(conn, req, state, inbuf, outbuf, size, bufsize); + if (req->outbuf != NULL) { + outsize = smb_len(req->outbuf) + 4; + memcpy(outbuf, req->outbuf, outsize); + } + TALLOC_FREE(req); DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); -- cgit From b91704d47b7946d561a0021a08c14f8923d59e3a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 18:28:41 +0000 Subject: r24135: Convert call_trans2open to the new API This itself won't help much, because send_trans2_replies_new still allocates the big buffers, but stay tuned :-) Also add/update my copyright on stuff I recently touched. Volker (This used to be commit 248f15ff143474db2493cef89ba446892342a361) --- source3/smbd/negprot.c | 1 + source3/smbd/process.c | 2 +- source3/smbd/reply.c | 1 + source3/smbd/sesssetup.c | 1 + source3/smbd/trans2.c | 110 +++++++++++++++++++++++++++++++---------------- 5 files changed, 77 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index a8578d56b5..06b17a9a24 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. negprot reply code Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Volker Lendecke 2007 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 diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4acdb177a6..54a1ef17b1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. process incoming packets - main loop Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Volker Lendecke 2005 + Copyright (C) Volker Lendecke 2005-2007 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 diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4fbf179797..0bb9d9ca7d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Bartlett 2001 Copyright (C) Jeremy Allison 1992-2007. + Copyright (C) Volker Lendecke 2007 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 diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e9808e0040..22ad43ff75 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Bartlett 2001 Copyright (C) Jim McDonough 2002 Copyright (C) Luke Howard 2003 + Copyright (C) Volker Lendecke 2007 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 diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3a1a1ca816..aca5186a5c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3,7 +3,7 @@ SMB transaction2 handling Copyright (C) Jeremy Allison 1994-2007 Copyright (C) Stefan (metze) Metzmacher 2003 - Copyright (C) Volker Lendecke 2005 + Copyright (C) Volker Lendecke 2005-2007 Copyright (C) Steve French 2005 Copyright (C) James Peach 2007 @@ -735,16 +735,37 @@ int send_trans2_replies(const char *inbuf, return 0; } +static void send_trans2_replies_new(struct smb_request *req, + const char *params, + int paramsize, + const char *pdata, + int datasize, + int max_data_bytes) +{ + char *inbuf, *outbuf; + int length, bufsize; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + reply_post_legacy(req, send_trans2_replies( + inbuf, outbuf, bufsize, + params, paramsize, + pdata, datasize, + max_data_bytes)); +} + /**************************************************************************** Reply to a TRANSACT2_OPEN. ****************************************************************************/ -static int call_trans2open(connection_struct *conn, - struct smb_request *req, - char *inbuf, char *outbuf, int bufsize, - char **pparams, int total_params, - char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2open(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; @@ -779,7 +800,8 @@ static int call_trans2open(connection_struct *conn, */ if (total_params < 29) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } flags = SVAL(params, 0); @@ -800,14 +822,16 @@ static int call_trans2open(connection_struct *conn, pname = ¶ms[28]; if (IS_IPC(conn)) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV, ERRaccess); + return; } - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, pname, + srvstr_get_path(params, req->flags2, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n", @@ -818,16 +842,19 @@ static int call_trans2open(connection_struct *conn, status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } if (open_ofun == 0) { - return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION); + reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION); + return; } if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun, @@ -835,32 +862,38 @@ static int call_trans2open(connection_struct *conn, &share_mode, &create_disposition, &create_options)) { - return ERROR_DOS(ERRDOS, ERRbadaccess); + reply_doserror(req, ERRDOS, ERRbadaccess); + return; } /* Any data in this call is an EA list. */ if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) { - return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); + return; } if (total_data != 4) { if (total_data < 10) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (IVAL(pdata,0) > total_data) { DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4, total_data - 4); if (!ea_list) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } } else if (IVAL(pdata,0) != 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } status = open_file_ntcreate(conn, req, fname, &sbuf, @@ -873,11 +906,12 @@ static int call_trans2open(connection_struct *conn, &smb_action, &fsp); if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } size = get_file_size(sbuf); @@ -886,7 +920,8 @@ static int call_trans2open(connection_struct *conn, inode = sbuf.st_ino; if (fattr & aDIR) { close_file(fsp,ERROR_CLOSE); - return(ERROR_DOS(ERRDOS,ERRnoaccess)); + reply_doserror(req, ERRDOS,ERRnoaccess); + return; } /* Save the requested allocation size. */ @@ -898,11 +933,13 @@ static int call_trans2open(connection_struct *conn, if (fsp->is_directory) { close_file(fsp,ERROR_CLOSE); /* Can't set allocation size on a directory. */ - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,ERROR_CLOSE); - return ERROR_NT(NT_STATUS_DISK_FULL); + reply_nterror(req, NT_STATUS_DISK_FULL); + return; } /* Adjust size here to return the right size in the reply. @@ -917,14 +954,16 @@ static int call_trans2open(connection_struct *conn, status = set_ea(conn, fsp, fname, ea_list); if (!NT_STATUS_IS_OK(status)) { close_file(fsp,ERROR_CLOSE); - return ERROR_NT(status); + reply_nterror(req, status); + return; } } /* Realloc the size of parameters and data we will return */ *pparams = (char *)SMB_REALLOC(*pparams, 30); if(*pparams == NULL ) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; @@ -955,9 +994,7 @@ static int call_trans2open(connection_struct *conn, } /* Send the required number of replies */ - send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes); - - return -1; + send_trans2_replies_new(req, params, 30, *ppdata, 0, max_data_bytes); } /********************************************************* @@ -6588,7 +6625,7 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, struct trans_state *state, char *inbuf, char *outbuf, int size, int bufsize) { - int outsize; + int outsize = -1; if (Protocol >= PROTOCOL_NT1) { SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ @@ -6599,11 +6636,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_OPEN: { START_PROFILE(Trans2_open); - outsize = call_trans2open( - conn, req, inbuf, outbuf, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2open(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_open); break; } -- cgit From 4d34c5eef7db0df5ba1a0f3b167f758bb637148f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 18:50:17 +0000 Subject: r24136: get_lanman2_dir_entry() does not need access to inbuf/outbuf It did not use inbuf anyway. Outbuf was used for alignment and to the flags2. The alignment works ok if we align relative to base_data because this and outbuf are both malloc'ed, and we put send_trans2_replies aligns out_data properly relative to the start of the outbuf. I don't know if the explicit align_string() calls in get_lanman2_dir_entry are really necessary. I think that srvstr_push also does the same. Please also note that this changes dst_len in srvstr_push from -1 to the real length remaining. Volker (This used to be commit 9b1614f8cb415c15032e6a34f2da5df026f92e6e) --- source3/smbd/trans2.c | 88 ++++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index aca5186a5c..edfbe330a1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1130,12 +1130,12 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn, Get a level dependent lanman2 dir entry. ****************************************************************************/ -static BOOL get_lanman2_dir_entry(connection_struct *conn, - void *inbuf, char *outbuf, +static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, char *path_mask,uint32 dirtype,int info_level, int requires_resume_key, BOOL dont_descend,char **ppdata, - char *base_data, int space_remaining, + char *base_data, char *end_data, + int space_remaining, BOOL *out_of_space, BOOL *got_exact_match, int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx) { @@ -1339,10 +1339,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,20,mode); p += 23; nameptr = p; - p += align_string(outbuf, p, 0); - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, - fname, -1, STR_TERMINATE); - if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + p += align_string(pdata, p, 0); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE); + if (flags2 & FLAGS2_UNICODE_STRINGS) { if (len > 2) { SCVAL(nameptr, -1, len - 2); } else { @@ -1376,10 +1377,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } p += 27; nameptr = p - 1; - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - p, fname, -1, + len = srvstr_push(base_data, flags2, + p, fname, PTR_DIFF(end_data, p), STR_TERMINATE | STR_NOALIGN); - if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + if (flags2 & FLAGS2_UNICODE_STRINGS) { if (len > 2) { len -= 2; } else { @@ -1434,10 +1435,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, /* Push the ea_data followed by the name. */ p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list); nameptr = p; - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - p + 1, fname, -1, + len = srvstr_push(base_data, flags2, + p + 1, fname, PTR_DIFF(end_data, p), STR_TERMINATE | STR_NOALIGN); - if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + if (flags2 & FLAGS2_UNICODE_STRINGS) { if (len > 2) { len -= 2; } else { @@ -1484,8 +1485,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(mangled_name,True,True, conn->params); mangled_name[12] = 0; - len = srvstr_push(outbuf, - SVAL(outbuf, smb_flg2), + len = srvstr_push(base_data, flags2, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); if (len < 24) { @@ -1496,8 +1496,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, memset(p,'\0',26); } p += 2 + 24; - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, - fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1518,8 +1519,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,file_size); p += 8; SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - p + 4, fname, -1, + len = srvstr_push(base_data, flags2, + p + 4, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII); SIVAL(p,0,len); p += 4 + len; @@ -1547,8 +1548,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,ea_size); /* Extended attributes */ p +=4; } - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, - fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); SIVAL(q, 0, len); p += len; @@ -1566,8 +1568,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; /* this must *not* be null terminated or w2k gets in a loop trying to set an acl on a dir (tridge) */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - p, fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); SIVAL(p, -4, len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1597,8 +1600,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, - fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); SIVAL(q, 0, len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1636,8 +1640,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(mangled_name,True,True, conn->params); mangled_name[12] = 0; - len = srvstr_push(outbuf, - SVAL(outbuf, smb_flg2), + len = srvstr_push(base_data, flags2, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); @@ -1652,8 +1655,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SSVAL(p,0,0); p += 2; /* Reserved ? */ SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, - fname, -1, STR_TERMINATE_ASCII); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; SIVAL(p,0,0); /* Ensure any padding is null. */ @@ -1676,9 +1680,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); p = store_file_unix_basic(conn, p, NULL, &sbuf); - len = srvstr_push(outbuf, - SVAL(outbuf, smb_flg2), - p, fname, -1, + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), STR_TERMINATE); } else { DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); @@ -1686,9 +1689,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, NULL, &sbuf); nameptr = p; p += 4; - len = srvstr_push(outbuf, - SVAL(outbuf, smb_flg2), - p, fname, -1, 0); + len = srvstr_push(base_data, flags2, p, fname, + PTR_DIFF(end_data, p), 0); SIVAL(nameptr, 0, len); } @@ -1739,6 +1741,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb requested. */ char *params = *pparams; char *pdata = *ppdata; + char *data_end; uint32 dirtype; int maxentries; uint16 findfirst_flags; @@ -1886,6 +1889,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_NO_MEMORY); } pdata = *ppdata; + data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1; /* Realloc the params space */ *pparams = (char *)SMB_REALLOC(*pparams, 10); @@ -1937,10 +1941,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd finished = False; } else { finished = !get_lanman2_dir_entry(conn, - inbuf, outbuf, + SVAL(outbuf, smb_flg2), mask,dirtype,info_level, requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, &got_exact_match, + &p,pdata,data_end, + space_remaining, &out_of_space, + &got_exact_match, &last_entry_off, ea_list, ea_ctx); } @@ -2034,6 +2040,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu requested. */ char *params = *pparams; char *pdata = *ppdata; + char *data_end; int dptr_num; int maxentries; uint16 info_level; @@ -2164,6 +2171,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } pdata = *ppdata; + data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1; /* Realloc the params space */ *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD); @@ -2253,10 +2261,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd finished = False; } else { finished = !get_lanman2_dir_entry(conn, - inbuf, outbuf, + SVAL(outbuf, smb_flg2), mask,dirtype,info_level, requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, &got_exact_match, + &p,pdata,data_end, + space_remaining, &out_of_space, + &got_exact_match, &last_entry_off, ea_list, ea_ctx); } -- cgit From e5ad62702be5a343cfec8465016c1afb5fd80cba Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 19:08:21 +0000 Subject: r24137: Convert call_trans2findfirst to the new API (This used to be commit 238edebab71ed1596af82f4c8611432f9156bd18) --- source3/smbd/trans2.c | 88 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index edfbe330a1..4a7fd51342 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1730,9 +1730,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, Reply to a TRANS2_FINDFIRST. ****************************************************************************/ -static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2findfirst(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { /* We must be careful here that we don't return more than the allowed number of data bytes. If this means returning fewer than @@ -1767,7 +1769,8 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb NTSTATUS ntstatus = NT_STATUS_OK; if (total_params < 13) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } dirtype = SVAL(params,0); @@ -1804,35 +1807,43 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", case SMB_FIND_FILE_UNIX: case SMB_FIND_FILE_UNIX_INFO2: if (!lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } break; default: - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } - srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), directory, + srvstr_get_path_wcard(params, req->flags2, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { - return ERROR_NT(ntstatus); + reply_nterror(req, ntstatus); + return; } - ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard); + ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; } - return ERROR_NT(ntstatus); + reply_nterror(req, ntstatus); + return; } ntstatus = unix_convert(conn, directory, True, NULL, &sbuf); if (!NT_STATUS_IS_OK(ntstatus)) { - return ERROR_NT(ntstatus); + reply_nterror(req, ntstatus); + return; } ntstatus = check_name(conn, directory); if (!NT_STATUS_IS_OK(ntstatus)) { - return ERROR_NT(ntstatus); + reply_nterror(req, ntstatus); + return; } p = strrchr_m(directory,'/'); @@ -1856,29 +1867,34 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", uint32 ea_size; if (total_data < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } ea_size = IVAL(pdata,0); if (ea_size != total_data) { DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (!lp_ea_support(SNUM(conn))) { - return ERROR_DOS(ERRDOS,ERReasnotsupported); + reply_doserror(req, ERRDOS, ERReasnotsupported); + return; } if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } /* Pull out the list of names. */ ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); if (!ea_list) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } } @@ -1886,7 +1902,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(*ppdata == NULL ) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } pdata = *ppdata; data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1; @@ -1895,7 +1912,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *pparams = (char *)SMB_REALLOC(*pparams, 10); if (*pparams == NULL) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; @@ -1906,7 +1924,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd directory, False, True, - SVAL(inbuf,smb_pid), + req->smbpid, mask, mask_contains_wcard, dirtype, @@ -1914,7 +1932,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (!NT_STATUS_IS_OK(ntstatus)) { talloc_destroy(ea_ctx); - return ERROR_NT(ntstatus); + reply_nterror(req, ntstatus); + return; } dptr_num = dptr_dnum(conn->dirptr); @@ -1941,7 +1960,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd finished = False; } else { finished = !get_lanman2_dir_entry(conn, - SVAL(outbuf, smb_flg2), + req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,data_end, @@ -1987,9 +2006,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if(numentries == 0) { dptr_close(&dptr_num); if (Protocol < PROTOCOL_NT1) { - return ERROR_DOS(ERRDOS,ERRnofiles); + reply_doserror(req, ERRDOS, ERRnofiles); + return; } else { - return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile); + reply_botherror(req, NT_STATUS_NO_SUCH_FILE, + ERRDOS, ERRbadfile); + return; } } @@ -2002,13 +2024,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,6,0); /* Never an EA error */ SSVAL(params,8,last_entry_off); - send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); + send_trans2_replies_new(req, params, 10, pdata, PTR_DIFF(p,pdata), + max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", - smb_fn_name(CVAL(inbuf,smb_com)), + smb_fn_name(CVAL(req->inbuf,smb_com)), mask, directory, dirtype, numentries ) ); /* @@ -2022,7 +2045,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if(!mangle_is_8_3_wildcards( mask, False, conn->params)) mangle_map(mask, True, True, conn->params); - return(-1); + return; } /**************************************************************************** @@ -6657,11 +6680,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_FINDFIRST: { START_PROFILE(Trans2_findfirst); - outsize = call_trans2findfirst( - conn, inbuf, outbuf, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2findfirst(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_findfirst); break; } -- cgit From a1d70fcad740b5255234358e389fced75ea59db8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 19:22:14 +0000 Subject: r24138: Convert call_trans2findnext to the new API (This used to be commit af1855e4cebb6df3415ca5389b10aaa5a956adc2) --- source3/smbd/trans2.c | 69 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4a7fd51342..8ce4861102 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2052,9 +2052,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd Reply to a TRANS2_FINDNEXT. ****************************************************************************/ -static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2findnext(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { /* We must be careful here that we don't return more than the allowed number of data bytes. If this means returning fewer than @@ -2090,7 +2092,8 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu NTSTATUS ntstatus = NT_STATUS_OK; if (total_params < 13) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } dptr_num = SVAL(params,0); @@ -2105,7 +2108,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu *mask = *directory = *resume_name = 0; - srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name, + srvstr_get_path_wcard(params, req->flags2, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); @@ -2114,13 +2117,14 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu complain (it thinks we're asking for the directory above the shared path or an invalid name). Catch this as the resume name is only compared, never used in a file access. JRA. */ - srvstr_pull(inbuf, SVAL(inbuf,smb_flg2), + srvstr_pull(params, req->flags2, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE); if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) { - return ERROR_NT(ntstatus); + reply_nterror(req, ntstatus); + return; } } @@ -2149,40 +2153,47 @@ resume_key = %d resume name = %s continue=%d level = %d\n", case SMB_FIND_FILE_UNIX: case SMB_FIND_FILE_UNIX_INFO2: if (!lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } break; default: - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } if (info_level == SMB_FIND_EA_LIST) { uint32 ea_size; if (total_data < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } ea_size = IVAL(pdata,0); if (ea_size != total_data) { DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (!lp_ea_support(SNUM(conn))) { - return ERROR_DOS(ERRDOS,ERReasnotsupported); + reply_doserror(req, ERRDOS, ERReasnotsupported); + return; } if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } /* Pull out the list of names. */ ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); if (!ea_list) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } } @@ -2190,7 +2201,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(*ppdata == NULL) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } pdata = *ppdata; @@ -2200,7 +2212,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD); if(*pparams == NULL ) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; @@ -2208,7 +2221,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Check that the dptr is valid */ if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { talloc_destroy(ea_ctx); - return ERROR_DOS(ERRDOS,ERRnofiles); + reply_doserror(req, ERRDOS, ERRnofiles); + return; } string_set(&conn->dirpath,dptr_path(dptr_num)); @@ -2217,7 +2231,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if((p = dptr_wcard(dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); talloc_destroy(ea_ctx); - return ERROR_DOS(ERRDOS,ERRnofiles); + reply_doserror(req, ERRDOS, ERRnofiles); + return; } pstrcpy(mask, p); @@ -2284,7 +2299,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd finished = False; } else { finished = !get_lanman2_dir_entry(conn, - SVAL(outbuf, smb_flg2), + req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,data_end, @@ -2326,16 +2341,17 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,4,0); /* Never an EA error */ SSVAL(params,6,last_entry_off); - send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes); + send_trans2_replies_new(req, params, 8, pdata, PTR_DIFF(p,pdata), + max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", - smb_fn_name(CVAL(inbuf,smb_com)), + smb_fn_name(CVAL(req->inbuf,smb_com)), mask, directory, dirtype, numentries ) ); - return(-1); + return; } unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16]) @@ -6691,11 +6707,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_FINDNEXT: { START_PROFILE(Trans2_findnext); - outsize = call_trans2findnext( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2findnext(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_findnext); break; } -- cgit From 133a8bbe0757933e91928df9ca4a210e3dce46df Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 19:35:27 +0000 Subject: r24139: Convert call_trans2mkdir to the new API (This used to be commit d0b7f409e1ec88bcd695474aa77e75cb50dce013) --- source3/smbd/trans2.c | 64 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8ce4861102..a3415c40b5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6365,9 +6365,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, Reply to a TRANS2_MKDIR (make directory with extended attributes). ****************************************************************************/ -static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; @@ -6376,36 +6377,43 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, NTSTATUS status = NT_STATUS_OK; struct ea_list *ea_list = NULL; - if (!CAN_WRITE(conn)) - return ERROR_DOS(ERRSRV,ERRaccess); + if (!CAN_WRITE(conn)) { + reply_doserror(req, ERRSRV, ERRaccess); + return; + } if (total_params < 5) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, ¶ms[4], + srvstr_get_path(params, req->flags2, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); status = unix_convert(conn, directory, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status))); - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* Any data in this call is an EA list. */ if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) { - return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); + return; } /* @@ -6416,50 +6424,57 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, if (total_data != 4) { if (total_data < 10) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (IVAL(pdata,0) > total_data) { DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4, total_data - 4); if (!ea_list) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } } else if (IVAL(pdata,0) != 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } status = create_directory(conn, directory); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* Try and set any given EA. */ if (ea_list) { status = set_ea(conn, NULL, directory, ea_list); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } } /* Realloc the parameter and data sizes */ *pparams = (char *)SMB_REALLOC(*pparams,2); if(*pparams == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; SSVAL(params,0,0); - send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); + send_trans2_replies_new(req, params, 2, *ppdata, 0, max_data_bytes); - return(-1); + return; } /**************************************************************************** @@ -6792,11 +6807,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_MKDIR: { START_PROFILE(Trans2_mkdir); - outsize = call_trans2mkdir( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2mkdir(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_mkdir); break; } -- cgit From e3a53acafe4c4fd35970e2512c3a782ed644730f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 19:48:44 +0000 Subject: r24140: Convert call_trans2findnotifyfirst/next to the new API (This used to be commit 46d9c51631d099af0f8696d3942eb51b0cb09865) --- source3/smbd/trans2.c | 54 ++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a3415c40b5..c85585464d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6482,16 +6482,19 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, We don't actually do this - we just send a null response. ****************************************************************************/ -static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2findnotifyfirst(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { static uint16 fnf_handle = 257; char *params = *pparams; uint16 info_level; if (total_params < 6) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } info_level = SVAL(params,4); @@ -6502,13 +6505,15 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char case 2: break; default: - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } /* Realloc the parameter and data sizes */ *pparams = (char *)SMB_REALLOC(*pparams,6); if (*pparams == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; @@ -6521,9 +6526,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char if(fnf_handle == 0) fnf_handle = 257; - send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes); + send_trans2_replies_new(req, params, 6, *ppdata, 0, max_data_bytes); - return(-1); + return; } /**************************************************************************** @@ -6531,9 +6536,11 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char changes). Currently this does nothing. ****************************************************************************/ -static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2findnotifynext(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; @@ -6542,16 +6549,17 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char /* Realloc the parameter and data sizes */ *pparams = (char *)SMB_REALLOC(*pparams,4); if (*pparams == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; SSVAL(params,0,0); /* No changes */ SSVAL(params,2,0); /* No EA errors */ - send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes); + send_trans2_replies_new(req, params, 4, *ppdata, 0, max_data_bytes); - return(-1); + return; } /**************************************************************************** @@ -6783,11 +6791,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_FINDNOTIFYFIRST: { START_PROFILE(Trans2_findnotifyfirst); - outsize = call_trans2findnotifyfirst( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2findnotifyfirst(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_findnotifyfirst); break; } @@ -6795,11 +6802,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_FINDNOTIFYNEXT: { START_PROFILE(Trans2_findnotifynext); - outsize = call_trans2findnotifynext( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2findnotifynext(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_findnotifynext); break; } -- cgit From 2945d4492d10d83acd2d345339da941db5d7fc53 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 19:50:56 +0000 Subject: r24141: Add check_fsp as a replacement for CHECK_FSP (This used to be commit a3d77a576f863c4d9f95a1a898f70ae5b5bbc471) --- source3/smbd/reply.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0bb9d9ca7d..91e4274814 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -284,6 +284,33 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, return ret; } +/**************************************************************************** + Check if we have a correct fsp pointing to a file. Replacement for the + CHECK_FSP macro. +****************************************************************************/ +BOOL check_fsp(connection_struct *conn, struct smb_request *req, + files_struct *fsp, struct current_user *user) +{ + if (!(fsp) || !(conn)) { + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return False; + } + if (((conn) != (fsp)->conn) || current_user.vuid != (fsp)->vuid) { + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return False; + } + if ((fsp)->is_directory) { + reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST); + return False; + } + if ((fsp)->fh->fd == -1) { + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return False; + } + (fsp)->num_smb_operations++; + return True; +} + /**************************************************************************** Reply to a (netbios-level) special message. ****************************************************************************/ -- cgit From fa2b8a447af818e6f2547d3a8b996f2220737beb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 20:06:15 +0000 Subject: r24142: Remove some direct inbuf references from call_trans2qfilepathinfo (This used to be commit c9c0133d5512e68fcaf22b2abd3343ae944ddb9d) --- source3/smbd/trans2.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c85585464d..9bae8a416e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3401,7 +3401,9 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb file name or file id). ****************************************************************************/ -static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, +static int call_trans2qfilepathinfo(connection_struct *conn, + struct smb_request *req, + char *inbuf, char *outbuf, int length, int bufsize, unsigned int tran_call, char **pparams, int total_params, char **ppdata, int total_data, unsigned int max_data_bytes) @@ -3527,14 +3529,16 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6], + srvstr_get_path(params, req->flags2, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); @@ -6767,7 +6771,8 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, { START_PROFILE(Trans2_qpathinfo); outsize = call_trans2qfilepathinfo( - conn, inbuf, outbuf, size, bufsize, state->call, + conn, req, + inbuf, outbuf, size, bufsize, state->call, &state->param, state->total_param, &state->data, state->total_data, state->max_data_return); -- cgit From 44c5ee4ca646f90009c69752d3882f202544095c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 20:19:27 +0000 Subject: r24143: Convert call_trans2qfilepathinfo to the new API (This used to be commit 0b84e29120b87bf6fc86df10102f1c4d4f98cdb6) --- source3/smbd/trans2.c | 246 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 161 insertions(+), 85 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9bae8a416e..b95c017b83 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3338,10 +3338,12 @@ static char *store_file_unix_basic_info2(connection_struct *conn, Reply to a TRANSACT2_QFILEINFO on a PIPE ! ****************************************************************************/ -static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - unsigned int tran_call, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2qpipeinfo(connection_struct *conn, + struct smb_request *req, + unsigned int tran_call, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; @@ -3351,30 +3353,35 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb smb_np_struct *p_pipe = NULL; if (!params) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (total_params < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } p_pipe = get_rpc_pipe_p(SVAL(params,0)); if (p_pipe == NULL) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } info_level = SVAL(params,2); *pparams = (char *)SMB_REALLOC(*pparams,2); if (*pparams == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; SSVAL(params,0,0); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); if (*ppdata == NULL ) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } pdata = *ppdata; @@ -3388,12 +3395,14 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb break; default: - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } - send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); + send_trans2_replies_new(req, params, param_size, *ppdata, data_size, + max_data_bytes); - return(-1); + return; } /**************************************************************************** @@ -3401,15 +3410,16 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb file name or file id). ****************************************************************************/ -static int call_trans2qfilepathinfo(connection_struct *conn, - struct smb_request *req, - char *inbuf, char *outbuf, int length, int bufsize, - unsigned int tran_call, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2qfilepathinfo(connection_struct *conn, + struct smb_request *req, + unsigned int tran_call, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; + char *dstart, *dend; uint16 info_level; int mode=0; int nlink; @@ -3434,22 +3444,21 @@ static int call_trans2qfilepathinfo(connection_struct *conn, uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ char *lock_data = NULL; - if (!params) - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if (!params) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } ZERO_STRUCT(sbuf); if (tran_call == TRANSACT2_QFILEINFO) { if (total_params < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (IS_IPC(conn)) { - return call_trans2qpipeinfo(conn, - inbuf, - outbuf, - length, - bufsize, + return call_trans2qpipeinfo(conn, req, tran_call, pparams, total_params, @@ -3464,7 +3473,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } if(fsp && (fsp->fake_file_handle)) { @@ -3488,11 +3498,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + reply_unixerror(req,ERRDOS,ERRbadpath); + return; } } else if (SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + reply_unixerror(req, ERRDOS, ERRbadpath); + return; } fileid = vfs_file_id_from_sbuf(conn, &sbuf); @@ -3501,12 +3513,15 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* * Original code - this is an open file. */ - CHECK_FSP(fsp,conn); + if (!check_fsp(conn, req, fsp, ¤t_user)) { + return; + } pstrcpy(fname, fsp->fsp_name); if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadfid)); + reply_unixerror(req, ERRDOS, ERRbadfid); + return; } pos = fsp->fh->position_information; fileid = vfs_file_id_from_sbuf(conn, &sbuf); @@ -3518,7 +3533,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, /* qpathinfo */ if (total_params < 7) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } info_level = SVAL(params,0); @@ -3526,14 +3542,16 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } srvstr_get_path(params, req->flags2, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = resolve_dfspath(conn, @@ -3541,36 +3559,44 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); } - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status))); - return ERROR_NT(status); + reply_nterror(req, status); + return; } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + reply_unixerror(req, ERRDOS, ERRbadpath); + return; } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + reply_unixerror(req, ERRDOS, ERRbadpath); + return; } fileid = vfs_file_id_from_sbuf(conn, &sbuf); delete_pending = get_delete_on_close_flag(fileid); if (delete_pending) { - return ERROR_NT(NT_STATUS_DELETE_PENDING); + reply_nterror(req, NT_STATUS_DELETE_PENDING); + return; } } @@ -3586,7 +3612,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n", @@ -3614,29 +3641,38 @@ static int call_trans2qfilepathinfo(connection_struct *conn, uint32 ea_size; if (total_data < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; } ea_size = IVAL(pdata,0); if (total_data > 0 && ea_size != total_data) { DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; } if (!lp_ea_support(SNUM(conn))) { - return ERROR_DOS(ERRDOS,ERReasnotsupported); + reply_doserror(req, ERRDOS, + ERReasnotsupported); + return; } if ((data_ctx = talloc_init("ea_list")) == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } /* Pull out the list of names. */ ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4); if (!ea_list) { talloc_destroy(data_ctx); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; } break; } @@ -3644,15 +3680,19 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_POSIX_LOCK: { if (fsp == NULL || fsp->fh->fd == -1) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } if (total_data != POSIX_LOCK_DATA_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; } if ((data_ctx = talloc_init("lock_request")) == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } /* Copy the lock range data. */ @@ -3660,7 +3700,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_ctx, pdata, total_data); if (!lock_data) { talloc_destroy(data_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } } default: @@ -3670,7 +3711,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *pparams = (char *)SMB_REALLOC(*pparams,2); if (*pparams == NULL) { talloc_destroy(data_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; SSVAL(params,0,0); @@ -3678,9 +3720,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); if (*ppdata == NULL ) { talloc_destroy(data_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } pdata = *ppdata; + dstart = pdata; + dend = dstart + data_size - 1; create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); mtime_ts = get_mtimespec(&sbuf); @@ -3757,7 +3802,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n")); if (tran_call == TRANSACT2_QFILEINFO) { /* os/2 needs this ? really ?*/ - return ERROR_DOS(ERRDOS,ERRbadfunc); + reply_doserror(req, ERRDOS, ERRbadfunc); + return; } data_size = 0; param_size = 0; @@ -3794,7 +3840,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_ctx = talloc_init("ea_ctx"); if (!data_ctx) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len); @@ -3870,8 +3917,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if(!mangle_is_8_3(short_name, True, conn->params)) { mangle_map(short_name,True,True,conn->params); } - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - pdata+4, short_name, -1, + len = srvstr_push(dstart, req->flags2, + pdata+4, short_name, + PTR_DIFF(dend, pdata+4), STR_UNICODE); data_size = 4 + len; SIVAL(pdata,0,len); @@ -3882,8 +3930,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* this must be *exactly* right for ACLs on mapped drives to work */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - pdata+4, dos_fname, -1, STR_UNICODE); + len = srvstr_push(dstart, req->flags2, + pdata+4, dos_fname, + PTR_DIFF(dend, pdata+4), + STR_UNICODE); DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n")); data_size = 4 + len; SIVAL(pdata,0,len); @@ -3924,8 +3974,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 24; SIVAL(pdata,0,ea_size); pdata += 4; /* EA info */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - pdata+4, dos_fname, -1, STR_UNICODE); + len = srvstr_push(dstart, req->flags2, + pdata+4, dos_fname, + PTR_DIFF(dend, pdata+4), + STR_UNICODE); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -4078,18 +4130,25 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK - if(!S_ISLNK(sbuf.st_mode)) - return(UNIXERROR(ERRSRV,ERRbadlink)); + if(!S_ISLNK(sbuf.st_mode)) { + reply_unixerror(req, ERRSRV, + ERRbadlink); + return; + } #else - return(UNIXERROR(ERRDOS,ERRbadlink)); + reply_unixerror(req, ERRDOS, ERRbadlink); + return; #endif len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ - if (len == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if (len == -1) { + reply_unixerror(req, ERRDOS, + ERRnoaccess); + return; + } buffer[len] = 0; - len = srvstr_push(outbuf, - SVAL(outbuf, smb_flg2), - pdata, buffer, -1, + len = srvstr_push(dstart, req->flags2, + pdata, buffer, + PTR_DIFF(dend, pdata), STR_TERMINATE); pdata += len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -4114,7 +4173,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (file_acl == NULL && no_acl_syscall_error(errno)) { DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n", fname )); - return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED); + reply_nterror( + req, + NT_STATUS_NOT_IMPLEMENTED); + return; } if (S_ISDIR(sbuf.st_mode)) { @@ -4140,7 +4202,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (def_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); + reply_nterror( + req, + NT_STATUS_BUFFER_TOO_SMALL); + return; } SSVAL(pdata,0,SMB_POSIX_ACL_VERSION); @@ -4153,7 +4218,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (def_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - return ERROR_NT(NT_STATUS_INTERNAL_ERROR); + reply_nterror( + req, NT_STATUS_INTERNAL_ERROR); + return; } if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) { if (file_acl) { @@ -4162,7 +4229,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (def_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - return ERROR_NT(NT_STATUS_INTERNAL_ERROR); + reply_nterror( + req, + NT_STATUS_INTERNAL_ERROR); + return; } if (file_acl) { @@ -4186,7 +4256,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd enum brl_type lock_type; if (total_data != POSIX_LOCK_DATA_SIZE) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; } switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { @@ -4200,7 +4272,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd default: /* There's no point in asking for an unlock... */ talloc_destroy(data_ctx); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, + NT_STATUS_INVALID_PARAMETER); + return; } lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); @@ -4245,18 +4320,21 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE); SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK); } else { - return ERROR_NT(status); + reply_nterror(req, status); + return; } break; } default: - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } - send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes); + send_trans2_replies_new(req, params, param_size, *ppdata, data_size, + max_data_bytes); - return(-1); + return; } /**************************************************************************** @@ -6770,12 +6848,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_QFILEINFO: { START_PROFILE(Trans2_qpathinfo); - outsize = call_trans2qfilepathinfo( - conn, req, - inbuf, outbuf, size, bufsize, state->call, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2qfilepathinfo(conn, req, state->call, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_qpathinfo); break; } -- cgit From bd627a1597253e03e14c2dc60a99cf7e57bc169c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Aug 2007 20:56:40 +0000 Subject: r24144: Fix the build In a function returning void the "return;" needs to stand alone on some compilers (This used to be commit 28affcca8e22b9a147876a60fec28551256bcaa8) --- source3/smbd/trans2.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b95c017b83..803a2eb306 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3458,13 +3458,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } if (IS_IPC(conn)) { - return call_trans2qpipeinfo(conn, req, - tran_call, - pparams, - total_params, - ppdata, - total_data, - max_data_bytes); + call_trans2qpipeinfo(conn, req, tran_call, + pparams, total_params, + ppdata, total_data, + max_data_bytes); + return; } fsp = file_fsp(SVAL(params,0)); -- cgit From fe92fdc67db225d80aedbff45e3fa64fae961ee3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 07:00:19 +0000 Subject: r24145: Fix a comment (This used to be commit 34a00d8aa9af167c65baf7fc24de3c8e192f5ec0) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c091ed1e71..487d523670 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3142,8 +3142,8 @@ static int handle_nttrans(connection_struct *conn, default: /* Error in request */ - DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", - state->call)); + DEBUG(0,("handle_nttrans: Unknown request %d in " + "nttrans call\n", state->call)); return ERROR_DOS(ERRSRV,ERRerror); } return outsize; -- cgit From f2e2c22b6f6fd1639bf91f027dd8989fc6bf0659 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 09:09:00 +0000 Subject: r24147: Remove some inbuf refs from call_trans2setfilepathinfo (This used to be commit a13c42be7548fc0de3e1f6f1eaacbad3046af0d0) --- source3/smbd/trans2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 803a2eb306..c6a17cc93b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6123,14 +6123,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } info_level = SVAL(params,0); - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6], + srvstr_get_path(params, req->flags2, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); @@ -6421,11 +6423,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ return -1; } - if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) { + if (blocking_lock_was_deferred(req->mid)) { /* We have re-scheduled this call. */ return -1; } -- cgit From 67fde05d680e8b46640c391efde56392c2dff55c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 09:45:42 +0000 Subject: r24148: Remove some inbuf refs from subcommands of call_trans2setfilepathinfo (This used to be commit 09ed6537b39f72e61043a93fadea33562b07c6c6) --- source3/smbd/trans2.c | 61 ++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c6a17cc93b..bbfe5cfb77 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4728,10 +4728,10 @@ static NTSTATUS smb_file_mode_information(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, - char *inbuf, - const char *pdata, - int total_data, - const char *fname) + struct smb_request *req, + const char *pdata, + int total_data, + const char *fname) { pstring link_target; const char *newname = fname; @@ -4748,7 +4748,7 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata, + srvstr_pull(pdata, req->flags2, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE); /* !widelinks forces the target path to be within the share. */ @@ -4791,11 +4791,9 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, - char *inbuf, - char *outbuf, - const char *pdata, - int total_data, - pstring fname) + struct smb_request *req, + const char *pdata, int total_data, + pstring fname) { pstring oldname; NTSTATUS status = NT_STATUS_OK; @@ -4805,13 +4803,14 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata, + srvstr_get_path(pdata, req->flags2, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + oldname); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4828,12 +4827,8 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, static NTSTATUS smb_file_rename_information(connection_struct *conn, struct smb_request *req, - char *inbuf, - char *outbuf, - const char *pdata, - int total_data, - files_struct *fsp, - pstring fname) + const char *pdata, int total_data, + files_struct *fsp, pstring fname) { BOOL overwrite; uint32 root_fid; @@ -4856,14 +4851,16 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12], + srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; } - status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard); + status = resolve_dfspath_wcard(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + newname, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -6324,11 +6321,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, /* We must have a pathname for this. */ return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - status = smb_set_file_unix_link(conn, - inbuf, - pdata, - total_data, - fname); + status = smb_set_file_unix_link(conn, req, pdata, + total_data, fname); break; } @@ -6338,24 +6332,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, /* We must have a pathname for this. */ return ERROR_NT(NT_STATUS_INVALID_LEVEL); } - status = smb_set_file_unix_hlink(conn, - inbuf, - outbuf, - pdata, - total_data, - fname); + status = smb_set_file_unix_hlink(conn, req, + pdata, total_data, + fname); break; } case SMB_FILE_RENAME_INFORMATION: { status = smb_file_rename_information(conn, req, - inbuf, - outbuf, - pdata, - total_data, - fsp, - fname); + pdata, total_data, + fsp, fname); break; } -- cgit From 24e97edc78f8c55397b66669b8beae1f7d3d66d5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 10:07:18 +0000 Subject: r24149: Convert call_trans2setfilepathinfo to the new API (This used to be commit 50aa149cefc1da587f110eb0bf0344c737500f5b) --- source3/smbd/trans2.c | 133 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 52 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bbfe5cfb77..46a103d54e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4963,7 +4963,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_posix_lock(connection_struct *conn, - char *inbuf, + const uint8 *inbuf, int length, const char *pdata, int total_data, @@ -5061,7 +5061,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, * onto the blocking lock queue. */ if(push_blocking_lock_request(br_lck, - inbuf, length, + (char *)inbuf, length, fsp, -1, /* infinite timeout. */ 0, @@ -6036,13 +6036,12 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). ****************************************************************************/ -static int call_trans2setfilepathinfo(connection_struct *conn, - struct smb_request *req, - char *inbuf, char *outbuf, int length, - int bufsize, - unsigned int tran_call, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2setfilepathinfo(connection_struct *conn, + struct smb_request *req, + unsigned int tran_call, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; @@ -6054,14 +6053,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, int data_return_size = 0; if (!params) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } ZERO_STRUCT(sbuf); if (tran_call == TRANSACT2_SETFILEINFO) { if (total_params < 4) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } fsp = file_fsp(SVAL(params,0)); @@ -6078,12 +6079,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + reply_unixerror(req,ERRDOS,ERRbadpath); + return; } } else { if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + reply_unixerror(req,ERRDOS,ERRbadpath); + return; } } } else if (fsp && fsp->print_file) { @@ -6096,27 +6099,36 @@ static int call_trans2setfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); SSVAL(params,0,0); - send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes); - return(-1); - } else - return (UNIXERROR(ERRDOS,ERRbadpath)); + send_trans2_replies_new(req, params, 2, + *ppdata, 0, + max_data_bytes); + return; + } + else { + reply_unixerror(req, ERRDOS, ERRbadpath); + return; + } } else { /* * Original code - this is an open file. */ - CHECK_FSP(fsp,conn); + if (!check_fsp(conn, req, fsp, ¤t_user)) { + return; + } pstrcpy(fname, fsp->fsp_name); if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadfid)); + reply_unixerror(req, ERRDOS, ERRbadfid); + return; } } } else { /* set path info */ if (total_params < 7) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } info_level = SVAL(params,0); @@ -6124,7 +6136,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, sizeof(fname), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = resolve_dfspath(conn, @@ -6132,19 +6145,25 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } if (INFO_LEVEL_IS_UNIX(info_level)) { @@ -6157,16 +6176,19 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadpath); + reply_unixerror(req, ERRDOS, ERRbadpath); + return; } } if (!CAN_WRITE(conn)) { - return ERROR_DOS(ERRSRV,ERRaccess); + reply_doserror(req, ERRSRV, ERRaccess); + return; } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", @@ -6175,7 +6197,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, /* Realloc the parameter size */ *pparams = (char *)SMB_REALLOC(*pparams,2); if (*pparams == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } params = *pparams; @@ -6319,7 +6342,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if (tran_call != TRANSACT2_SETPATHINFO) { /* We must have a pathname for this. */ - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } status = smb_set_file_unix_link(conn, req, pdata, total_data, fname); @@ -6330,7 +6354,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if (tran_call != TRANSACT2_SETPATHINFO) { /* We must have a pathname for this. */ - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } status = smb_set_file_unix_hlink(conn, req, pdata, total_data, @@ -6362,14 +6387,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_POSIX_LOCK: { if (tran_call != TRANSACT2_SETFILEINFO) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } - status = smb_set_posix_lock(conn, - inbuf, - length, - pdata, - total_data, - fsp); + status = smb_set_posix_lock(conn, req->inbuf, + smb_len(req->inbuf) + 4, + pdata, total_data, fsp); break; } @@ -6377,7 +6400,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if (tran_call != TRANSACT2_SETPATHINFO) { /* We must have a pathname for this. */ - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } status = smb_posix_open(conn, req, @@ -6393,7 +6417,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if (tran_call != TRANSACT2_SETPATHINFO) { /* We must have a pathname for this. */ - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } status = smb_posix_unlink(conn, req, @@ -6405,29 +6430,34 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } default: - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + return; } if (blocking_lock_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + return; } if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } SSVAL(params,0,0); - send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes); + send_trans2_replies_new(req, params, 2, *ppdata, data_return_size, + max_data_bytes); - return -1; + return; } /**************************************************************************** @@ -6847,11 +6877,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_SETFILEINFO: { START_PROFILE(Trans2_setpathinfo); - outsize = call_trans2setfilepathinfo( - conn, req, inbuf, outbuf, size, bufsize, state->call, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2setfilepathinfo(conn, req, state->call, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_setpathinfo); break; } -- cgit From ccd0b815e8640e1a76c8686469a10158c8f30b0a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 10:32:41 +0000 Subject: r24150: Convert call_trans2qfsinfo to the new API (This used to be commit cdd86497b9830ba5fbc5b4511ed39ca44167faab) --- source3/smbd/trans2.c | 95 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 46a103d54e..ce52ba9e70 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2364,11 +2364,13 @@ unsigned char *create_volume_objectid(connection_struct *conn, unsigned char obj Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ -static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2qfsinfo(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { - char *pdata; + char *pdata, *end_data; char *params = *pparams; uint16 info_level; int data_len, len; @@ -2379,7 +2381,8 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf int quota_flag = 0; if (total_params < 2) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } info_level = SVAL(params,0); @@ -2388,17 +2391,20 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf if(SMB_VFS_STAT(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); - return ERROR_DOS(ERRSRV,ERRinvdevice); + reply_doserror(req, ERRSRV, ERRinvdevice); + return; } *ppdata = (char *)SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if (*ppdata == NULL ) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } pdata = *ppdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); + end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1; switch (info_level) { case SMB_INFO_ALLOCATION: @@ -2406,7 +2412,8 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 18; if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { - return(UNIXERROR(ERRHRD,ERRgeneral)); + reply_unixerror(req, ERRHRD, ERRgeneral); + return; } block_size = lp_block_size(snum); @@ -2450,9 +2457,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi * this call so try fixing this by adding a terminating null to * the pushed string. The change here was adding the STR_TERMINATE. JRA. */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - pdata+l2_vol_szVolLabel, vname, - -1, STR_NOALIGN|STR_TERMINATE); + len = srvstr_push( + pdata, req->flags2, + pdata+l2_vol_szVolLabel, vname, + PTR_DIFF(end_data, pdata+l2_vol_szVolLabel), + STR_NOALIGN|STR_TERMINATE); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", @@ -2476,16 +2485,17 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it and will think we can't do long filenames */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - pdata+12, fstype, -1, STR_UNICODE); + len = srvstr_push(pdata, req->flags2, pdata+12, fstype, + PTR_DIFF(end_data, pdata+12), + STR_UNICODE); SIVAL(pdata,8,len); data_len = 12 + len; break; case SMB_QUERY_FS_LABEL_INFO: case SMB_FS_LABEL_INFORMATION: - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - pdata+4, vname, -1, 0); + len = srvstr_push(pdata, req->flags2, pdata+4, vname, + PTR_DIFF(end_data, pdata+4), 0); data_len = 4 + len; SIVAL(pdata,0,len); break; @@ -2501,8 +2511,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi (str_checksum(get_local_machine_name())<<16)); /* Max label len is 32 characters. */ - len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), - pdata+18, vname, -1, STR_UNICODE); + len = srvstr_push(pdata, req->flags2, pdata+18, vname, + PTR_DIFF(end_data, pdata+18), + STR_UNICODE); SIVAL(pdata,12,len); data_len = 18+len; @@ -2516,7 +2527,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { - return(UNIXERROR(ERRHRD,ERRgeneral)); + reply_unixerror(req, ERRHRD, ERRgeneral); + return; } block_size = lp_block_size(snum); if (bsize < block_size) { @@ -2548,7 +2560,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { - return(UNIXERROR(ERRHRD,ERRgeneral)); + reply_unixerror(req, ERRHRD, ERRgeneral); + return; } block_size = lp_block_size(snum); if (bsize < block_size) { @@ -2621,12 +2634,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned if (current_user.ut.uid != 0) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); - return ERROR_DOS(ERRSRV,ERRerror); + reply_doserror(req, ERRSRV, ERRerror); + return; } data_len = 48; @@ -2669,7 +2684,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned case SMB_QUERY_CIFS_UNIX_INFO: if (!lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } data_len = 12; SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); @@ -2692,7 +2708,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned vfs_statvfs_struct svfs; if (!lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } rc = SMB_VFS_STATVFS(conn, ".", &svfs); @@ -2710,11 +2727,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n")); #ifdef EOPNOTSUPP } else if (rc == EOPNOTSUPP) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; #endif /* EOPNOTSUPP */ } else { DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn)))); - return ERROR_DOS(ERRSRV,ERRerror); + reply_doserror(req, ERRSRV, ERRerror); + return; } break; } @@ -2726,11 +2745,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int i; if (!lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } if (max_data_bytes < 40) { - return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); + reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); + return; } /* We ARE guest if global_sid_Builtin_Guests is @@ -2839,15 +2860,18 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } /* drop through */ default: - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; } - send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes); + send_trans2_replies_new(req, params, 0, pdata, data_len, + max_data_bytes); - DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) ); + DEBUG( 4, ( "%s info_level = %d\n", + smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) ); - return -1; + return; } /**************************************************************************** @@ -6840,11 +6864,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_QFSINFO: { START_PROFILE(Trans2_qfsinfo); - outsize = call_trans2qfsinfo( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2qfsinfo(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_qfsinfo); break; } -- cgit From 70496e030fe9918e8732794c81543f26466b9e76 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 10:51:59 +0000 Subject: r24151: Convert call_trans2getdfsreferral to the new API (This used to be commit 642c58648b2468544e9488cbffe1a8b236949bcc) --- source3/smbd/trans2.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ce52ba9e70..01b1278c2f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6689,9 +6689,11 @@ static void call_trans2findnotifynext(connection_struct *conn, Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele . ****************************************************************************/ -static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2getdfsreferral(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *params = *pparams; pstring pathname; @@ -6702,23 +6704,30 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* DEBUG(10,("call_trans2getdfsreferral\n")); if (total_params < 3) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } max_referral_level = SVAL(params,0); - if(!lp_host_msdfs()) - return ERROR_DOS(ERRDOS,ERRbadfunc); + if(!lp_host_msdfs()) { + reply_doserror(req, ERRDOS, ERRbadfunc); + return; + } - srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2], + srvstr_pull(params, req->flags2, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE); - if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0) - return ERROR_NT(status); + if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level, + ppdata,&status)) < 0) { + reply_nterror(req, status); + return; + } - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); - send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes); + SSVAL(req->inbuf, smb_flg2, + SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); + send_trans2_replies_new(req,0,0,*ppdata,reply_size, max_data_bytes); - return(-1); + return; } #define LMCAT_SPL 0x53 @@ -6944,11 +6953,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_GET_DFS_REFERRAL: { START_PROFILE(Trans2_get_dfs_referral); - outsize = call_trans2getdfsreferral( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2getdfsreferral(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_get_dfs_referral); break; } -- cgit From 4514ea2034ca8e049c64a4fea1c5771e7ea113de Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 11:57:39 +0000 Subject: r24152: Convert call_trans2ioctl to the new API (This used to be commit db4e6781c4d1a9755a3ec45556be8dd935f15bae) --- source3/smbd/trans2.c | 55 ++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 01b1278c2f..a30407cc5a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6737,23 +6737,28 @@ static void call_trans2getdfsreferral(connection_struct *conn, Reply to a TRANS2_IOCTL - used for OS/2 printing. ****************************************************************************/ -static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2ioctl(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *pdata = *ppdata; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15)); + files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15)); /* check for an invalid fid before proceeding */ - if (!fsp) - return(ERROR_DOS(ERRDOS,ERRbadfid)); + if (!fsp) { + reply_doserror(req, ERRDOS, ERRbadfid); + return; + } - if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && - (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL) + && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { *ppdata = (char *)SMB_REALLOC(*ppdata, 32); if (*ppdata == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } pdata = *ppdata; @@ -6761,18 +6766,19 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, CAN ACCEPT THIS IN UNICODE. JRA. */ SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */ - srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata + 2, - global_myname(), 15, - STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ - srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata+18, - lp_servicename(SNUM(conn)), 13, - STR_ASCII|STR_TERMINATE); /* Service name */ - send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes); - return(-1); - } else { - DEBUG(2,("Unknown TRANS2_IOCTL\n")); - return ERROR_DOS(ERRSRV,ERRerror); + srvstr_push(pdata, req->flags2, pdata + 2, + global_myname(), 15, + STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */ + srvstr_push(pdata, req->flags2, pdata+18, + lp_servicename(SNUM(conn)), 13, + STR_ASCII|STR_TERMINATE); /* Service name */ + send_trans2_replies_new(req, *pparams, 0, *ppdata, 32, + max_data_bytes); + return; } + + DEBUG(2,("Unknown TRANS2_IOCTL\n")); + reply_doserror(req, ERRSRV, ERRerror); } /**************************************************************************** @@ -6964,11 +6970,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_IOCTL: { START_PROFILE(Trans2_ioctl); - outsize = call_trans2ioctl( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2ioctl(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_ioctl); break; } -- cgit From 2516942a4b0fd940ff701fa17bb4e662fe4b7f17 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 12:15:58 +0000 Subject: r24153: Convert call_trans2setfsinfo to the new API. This *might* break the transport encryption stuff. I need to check that. (This used to be commit 82b34d7bdbe5c5038810c11540b6b7bc04290653) --- source3/smbd/trans2.c | 87 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a30407cc5a..cc542ace6c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2878,14 +2878,15 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned Reply to a TRANS2_SETFSINFO (set filesystem info). ****************************************************************************/ -static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **pparams, int total_params, char **ppdata, int total_data, - unsigned int max_data_bytes) +static void call_trans2setfsinfo(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) { char *pdata = *ppdata; char *params = *pparams; uint16 info_level; - int outsize; DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn)))); @@ -2893,7 +2894,8 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb if (total_params < 4) { DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n", total_params)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } info_level = SVAL(params,2); @@ -2907,12 +2909,17 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb uint32 client_unix_cap_high; if (!lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, + NT_STATUS_INVALID_LEVEL); + return; } /* There should be 12 bytes of capabilities set. */ if (total_data < 8) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, + NT_STATUS_INVALID_PARAMETER); + return; } client_unix_major = SVAL(pdata,0); client_unix_minor = SVAL(pdata,2); @@ -2950,7 +2957,9 @@ cap_low = 0x%x, cap_high = 0x%x\n", size_t data_len = total_data; if (!lp_unix_extensions()) { - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror( + req, NT_STATUS_INVALID_LEVEL); + return; } DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n")); @@ -2962,13 +2971,20 @@ cap_low = 0x%x, cap_high = 0x%x\n", ¶m_len ); - if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__); - } else if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + if (!NT_STATUS_IS_OK(status)) { + /* + * TODO: Check + * MORE_PROCESSING_REQUIRED, this used + * to have special handling here. + */ + reply_nterror(req, status); + return; } - send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes); + send_trans2_replies_new(req, + *pparams, param_len, + *ppdata, data_len, + max_data_bytes); if (NT_STATUS_IS_OK(status)) { /* Server-side transport encryption is now *on*. */ @@ -2977,7 +2993,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", exit_server_cleanly("Failure in setting up encrypted transport"); } } - return -1; + return; } case SMB_FS_QUOTA_INFORMATION: { @@ -2990,7 +3006,8 @@ cap_low = 0x%x, cap_high = 0x%x\n", if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); - return ERROR_DOS(ERRSRV,ERRaccess); + reply_doserror(req, ERRSRV, ERRaccess); + return; } /* note: normaly there're 48 bytes, @@ -3000,13 +3017,18 @@ cap_low = 0x%x, cap_high = 0x%x\n", fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror( + req, NT_STATUS_INVALID_HANDLE); + return; } if (total_data < 42) { DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n", total_data)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, + NT_STATUS_INVALID_PARAMETER); + return; } /* unknown_1 24 NULL bytes in pdata*/ @@ -3020,7 +3042,10 @@ cap_low = 0x%x, cap_high = 0x%x\n", ((quotas.softlim != 0xFFFFFFFF)|| (IVAL(pdata,28)!=0xFFFFFFFF))) { /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, + NT_STATUS_INVALID_PARAMETER); + return; } #endif /* LARGE_SMB_OFF_T */ @@ -3033,7 +3058,10 @@ cap_low = 0x%x, cap_high = 0x%x\n", ((quotas.hardlim != 0xFFFFFFFF)|| (IVAL(pdata,36)!=0xFFFFFFFF))) { /* more than 32 bits? */ - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror( + req, + NT_STATUS_INVALID_PARAMETER); + return; } #endif /* LARGE_SMB_OFF_T */ @@ -3045,7 +3073,8 @@ cap_low = 0x%x, cap_high = 0x%x\n", /* now set the quotas */ if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); - return ERROR_DOS(ERRSRV,ERRerror); + reply_doserror(req, ERRSRV, ERRerror); + return; } break; @@ -3053,7 +3082,8 @@ cap_low = 0x%x, cap_high = 0x%x\n", default: DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n", info_level)); - return ERROR_NT(NT_STATUS_INVALID_LEVEL); + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; break; } @@ -3062,10 +3092,8 @@ cap_low = 0x%x, cap_high = 0x%x\n", * but I'm not sure it's the same * like windows do... * --metze - */ - outsize = set_message(inbuf, outbuf,10,0,True); - - return outsize; + */ + reply_outbuf(req, 10, 0); } #if defined(HAVE_POSIX_ACLS) @@ -6890,11 +6918,10 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, case TRANSACT2_SETFSINFO: { START_PROFILE(Trans2_setfsinfo); - outsize = call_trans2setfsinfo( - conn, inbuf, outbuf, size, bufsize, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + call_trans2setfsinfo(conn, req, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(Trans2_setfsinfo); break; } -- cgit From c28bd38aa67b2f73640282685b76104382650b47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 12:44:06 +0000 Subject: r24154: handle_trans2 does not reference inbuf/outbuf anymore (This used to be commit 8eb016a91e3ec8d1d9d5ae1ec6f92e1e0657d593) --- source3/smbd/trans2.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index cc542ace6c..acaabeea54 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6859,14 +6859,12 @@ int reply_findnclose(connection_struct *conn, return(outsize); } -static int handle_trans2(connection_struct *conn, struct smb_request *req, - struct trans_state *state, - char *inbuf, char *outbuf, int size, int bufsize) +static void handle_trans2(connection_struct *conn, struct smb_request *req, + struct trans_state *state) { - int outsize = -1; - if (Protocol >= PROTOCOL_NT1) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ + req->flags2 |= 0x40; /* IS_LONG_NAME */ + SSVAL(req->inbuf,smb_flg2,req->flags2); } /* Now we must call the relevant TRANS2 function */ @@ -7008,10 +7006,8 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req, default: /* Error in request */ DEBUG(2,("Unknown request %d in trans2 call\n", state->call)); - outsize = ERROR_DOS(ERRSRV,ERRerror); + reply_doserror(req, ERRSRV,ERRerror); } - - return outsize; } /**************************************************************************** @@ -7154,8 +7150,8 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, init_smb_request(req, (uint8 *)inbuf); - outsize = handle_trans2(conn, req, state, inbuf, outbuf, - size, bufsize); + outsize = -1; + handle_trans2(conn, req, state); if (req->outbuf != NULL) { outsize = smb_len(req->outbuf) + 4; memcpy(outbuf, req->outbuf, outsize); @@ -7291,8 +7287,8 @@ int reply_transs2(connection_struct *conn, init_smb_request(req, (uint8 *)inbuf); - outsize = handle_trans2(conn, req, state, inbuf, outbuf, size, - bufsize); + outsize = -1; + handle_trans2(conn, req, state); if (req->outbuf != NULL) { outsize = smb_len(req->outbuf) + 4; memcpy(outbuf, req->outbuf, outsize); -- cgit From 675a484670fd778947661c9227b332c035fe1cf8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 13:13:57 +0000 Subject: r24155: Check wct in reply_trans2 (This used to be commit e0a708c79b4db4aab84022d568b5e7bf519e4b5a) --- source3/smbd/trans2.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index acaabeea54..33aa3d0036 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7018,16 +7018,27 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize) { int outsize = 0; - unsigned int dsoff = SVAL(inbuf, smb_dsoff); - unsigned int dscnt = SVAL(inbuf, smb_dscnt); - unsigned int psoff = SVAL(inbuf, smb_psoff); - unsigned int pscnt = SVAL(inbuf, smb_pscnt); - unsigned int tran_call = SVAL(inbuf, smb_setup0); + unsigned int dsoff; + unsigned int dscnt; + unsigned int psoff; + unsigned int pscnt; + unsigned int tran_call; struct trans_state *state; NTSTATUS result; START_PROFILE(SMBtrans2); + if (SVAL(inbuf, smb_wct) < 8) { + END_PROFILE(SMBtrans2); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + dsoff = SVAL(inbuf, smb_dsoff); + dscnt = SVAL(inbuf, smb_dscnt); + psoff = SVAL(inbuf, smb_psoff); + pscnt = SVAL(inbuf, smb_pscnt); + tran_call = SVAL(inbuf, smb_setup0); + result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid trans2 request: %s\n", @@ -7198,6 +7209,11 @@ int reply_transs2(connection_struct *conn, START_PROFILE(SMBtranss2); + if (SVAL(inbuf, smb_wct) < 8) { + END_PROFILE(SMBtranss2); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + show_msg(inbuf); for (state = conn->pending_trans; state != NULL; -- cgit From e2f0b5dd2afa60a9ba2239f9ad7da8a2363baea6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 13:34:02 +0000 Subject: r24156: Convert reply_trans2 to the new API (This used to be commit a9c2d75b42be8b0d89ed1e1a2ce2c6ab4284f5ea) --- source3/smbd/process.c | 2 +- source3/smbd/trans2.c | 108 ++++++++++++++++++++++++------------------------- 2 files changed, 53 insertions(+), 57 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 54a1ef17b1..0076cfcad7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -738,7 +738,7 @@ static const struct smb_message_struct { /* 0x2f */ { "SMBwriteX",reply_write_and_X,NULL,AS_USER | CAN_IPC }, /* 0x30 */ { NULL, NULL, NULL, 0 }, /* 0x31 */ { NULL, NULL, NULL, 0 }, -/* 0x32 */ { "SMBtrans2", reply_trans2,NULL, AS_USER | CAN_IPC }, +/* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC }, /* 0x33 */ { "SMBtranss2", reply_transs2,NULL, AS_USER}, /* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER}, /* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER}, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 33aa3d0036..240d45e94b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7014,67 +7014,71 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req, Reply to a SMBtrans2. ****************************************************************************/ -int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, - int size, int bufsize) +void reply_trans2(connection_struct *conn, struct smb_request *req) { - int outsize = 0; unsigned int dsoff; unsigned int dscnt; unsigned int psoff; unsigned int pscnt; unsigned int tran_call; + int size; struct trans_state *state; NTSTATUS result; START_PROFILE(SMBtrans2); - if (SVAL(inbuf, smb_wct) < 8) { + if (req->wct < 8) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtrans2); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } - dsoff = SVAL(inbuf, smb_dsoff); - dscnt = SVAL(inbuf, smb_dscnt); - psoff = SVAL(inbuf, smb_psoff); - pscnt = SVAL(inbuf, smb_pscnt); - tran_call = SVAL(inbuf, smb_setup0); + dsoff = SVAL(req->inbuf, smb_dsoff); + dscnt = SVAL(req->inbuf, smb_dscnt); + psoff = SVAL(req->inbuf, smb_psoff); + pscnt = SVAL(req->inbuf, smb_pscnt); + tran_call = SVAL(req->inbuf, smb_setup0); + size = smb_len(req->inbuf) + 4; - result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); + result = allow_new_trans(conn->pending_trans, req->mid); if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid trans2 request: %s\n", nt_errstr(result))); + reply_nterror(req, result); END_PROFILE(SMBtrans2); - return ERROR_NT(result); + return; } if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) && (tran_call != TRANSACT2_GET_DFS_REFERRAL) && (tran_call != TRANSACT2_QFILEINFO)) { + reply_doserror(req, ERRSRV, ERRaccess); END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRSRV,ERRaccess); + return; } if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans2); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return; } state->cmd = SMBtrans2; - state->mid = SVAL(inbuf, smb_mid); - state->vuid = SVAL(inbuf, smb_uid); - state->setup_count = SVAL(inbuf, smb_suwcnt); + state->mid = req->mid; + state->vuid = req->vuid; + state->setup_count = SVAL(req->inbuf, smb_suwcnt); state->setup = NULL; - state->total_param = SVAL(inbuf, smb_tpscnt); + state->total_param = SVAL(req->inbuf, smb_tpscnt); state->param = NULL; - state->total_data = SVAL(inbuf, smb_tdscnt); + state->total_data = SVAL(req->inbuf, smb_tdscnt); state->data = NULL; - state->max_param_return = SVAL(inbuf, smb_mprcnt); - state->max_data_return = SVAL(inbuf, smb_mdrcnt); - state->max_setup_return = SVAL(inbuf, smb_msrcnt); - state->close_on_completion = BITSETW(inbuf+smb_vwv5,0); - state->one_way = BITSETW(inbuf+smb_vwv5,1); + state->max_param_return = SVAL(req->inbuf, smb_mprcnt); + state->max_data_return = SVAL(req->inbuf, smb_mdrcnt); + state->max_setup_return = SVAL(req->inbuf, smb_msrcnt); + state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0); + state->one_way = BITSETW(req->inbuf+smb_vwv5,1); state->call = tran_call; @@ -7089,16 +7093,18 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, * Until DosPrintSetJobInfo with PRJINFO3 is supported, * outbuf doesn't have to be set(only job id is used). */ - if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) && - (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && - (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + if ( (state->setup_count == 4) + && (tran_call == TRANSACT2_IOCTL) + && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL) + && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { DEBUG(2,("Got Trans2 DevIOctl jobid\n")); } else { DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count)); DEBUG(2,("Transaction is %d\n",tran_call)); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtrans2); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } } @@ -7113,16 +7119,18 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, DEBUG(0,("reply_trans2: data malloc fail for %u " "bytes !\n", (unsigned int)state->total_data)); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans2); - return(ERROR_DOS(ERRDOS,ERRnomem)); + return; } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; - if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || - (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) + if ((smb_base(req->inbuf)+dsoff+dscnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf))) goto bad_param; - memcpy(state->data,smb_base(inbuf)+dsoff,dscnt); + memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } if (state->total_param) { @@ -7134,16 +7142,18 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, "bytes !\n", (unsigned int)state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans2); - return(ERROR_DOS(ERRDOS,ERRnomem)); + return; } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; - if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || - (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) + if ((smb_base(req->inbuf)+psoff+pscnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf))) goto bad_param; - memcpy(state->param,smb_base(inbuf)+psoff,pscnt); + memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } state->received_data = dscnt; @@ -7152,37 +7162,23 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, if ((state->received_param == state->total_param) && (state->received_data == state->total_data)) { - struct smb_request *req; - - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { - END_PROFILE(SMBtrans2); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - init_smb_request(req, (uint8 *)inbuf); - - outsize = -1; handle_trans2(conn, req, state); - if (req->outbuf != NULL) { - outsize = smb_len(req->outbuf) + 4; - memcpy(outbuf, req->outbuf, outsize); - } - TALLOC_FREE(req); + SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); END_PROFILE(SMBtrans2); - return outsize; + return; } DLIST_ADD(conn->pending_trans, state); /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(inbuf, outbuf,0,0,False); - show_msg(outbuf); + reply_outbuf(req, 0, 0); + show_msg((char *)req->outbuf); END_PROFILE(SMBtrans2); - return outsize; + return; bad_param: @@ -7191,7 +7187,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf, SAFE_FREE(state->param); TALLOC_FREE(state); END_PROFILE(SMBtrans2); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); } -- cgit From 1d8851f4c734b65312baae042d12c014a8fe88c5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 14:02:07 +0000 Subject: r24159: Convert reply_transs2 to the new API (This used to be commit a55a4d71ffe9ff1395e02f8bb3ad88fe5132fe99) --- source3/smbd/process.c | 2 +- source3/smbd/trans2.c | 86 +++++++++++++++++++++++--------------------------- 2 files changed, 41 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0076cfcad7..df86970ca8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -739,7 +739,7 @@ static const struct smb_message_struct { /* 0x30 */ { NULL, NULL, NULL, 0 }, /* 0x31 */ { NULL, NULL, NULL, 0 }, /* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC }, -/* 0x33 */ { "SMBtranss2", reply_transs2,NULL, AS_USER}, +/* 0x33 */ { "SMBtranss2", NULL,reply_transs2, AS_USER}, /* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER}, /* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER}, /* 0x36 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 240d45e94b..577524dedd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7195,50 +7195,52 @@ void reply_trans2(connection_struct *conn, struct smb_request *req) Reply to a SMBtranss2 ****************************************************************************/ -int reply_transs2(connection_struct *conn, - char *inbuf,char *outbuf,int size,int bufsize) +void reply_transs2(connection_struct *conn, struct smb_request *req) { - int outsize = 0; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - struct smb_request *req; + int size; START_PROFILE(SMBtranss2); - if (SVAL(inbuf, smb_wct) < 8) { + show_msg((char *)req->inbuf); + + if (req->wct < 8) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtranss2); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } - show_msg(inbuf); + size = smb_len(req->inbuf)+4; for (state = conn->pending_trans; state != NULL; state = state->next) { - if (state->mid == SVAL(inbuf,smb_mid)) { + if (state->mid == req->mid) { break; } } if ((state == NULL) || (state->cmd != SMBtrans2)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtranss2); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } /* Revise state->total_param and state->total_data in case they have changed downwards */ - if (SVAL(inbuf, smb_tpscnt) < state->total_param) - state->total_param = SVAL(inbuf, smb_tpscnt); - if (SVAL(inbuf, smb_tdscnt) < state->total_data) - state->total_data = SVAL(inbuf, smb_tdscnt); + if (SVAL(req->inbuf, smb_tpscnt) < state->total_param) + state->total_param = SVAL(req->inbuf, smb_tpscnt); + if (SVAL(req->inbuf, smb_tdscnt) < state->total_data) + state->total_data = SVAL(req->inbuf, smb_tdscnt); - pcnt = SVAL(inbuf, smb_spscnt); - poff = SVAL(inbuf, smb_spsoff); - pdisp = SVAL(inbuf, smb_spsdisp); + pcnt = SVAL(req->inbuf, smb_spscnt); + poff = SVAL(req->inbuf, smb_spsoff); + pdisp = SVAL(req->inbuf, smb_spsdisp); - dcnt = SVAL(inbuf, smb_sdscnt); - doff = SVAL(inbuf, smb_sdsoff); - ddisp = SVAL(inbuf, smb_sdsdisp); + dcnt = SVAL(req->inbuf, smb_sdscnt); + doff = SVAL(req->inbuf, smb_sdsoff); + ddisp = SVAL(req->inbuf, smb_sdsdisp); state->received_param += pcnt; state->received_data += dcnt; @@ -7254,13 +7256,14 @@ int reply_transs2(connection_struct *conn, goto bad_param; if (pdisp > state->total_param) goto bad_param; - if ((smb_base(inbuf) + poff + pcnt > inbuf + size) || - (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) + if ((smb_base(req->inbuf) + poff + pcnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf))) goto bad_param; if (state->param + pdisp < state->param) goto bad_param; - memcpy(state->param+pdisp,smb_base(inbuf)+poff, + memcpy(state->param+pdisp,smb_base(req->inbuf)+poff, pcnt); } @@ -7271,54 +7274,44 @@ int reply_transs2(connection_struct *conn, goto bad_param; if (ddisp > state->total_data) goto bad_param; - if ((smb_base(inbuf) + doff + dcnt > inbuf + size) || - (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) + if ((smb_base(req->inbuf) + doff + dcnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf))) goto bad_param; if (state->data + ddisp < state->data) goto bad_param; - memcpy(state->data+ddisp, smb_base(inbuf)+doff, + memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, dcnt); } if ((state->received_param < state->total_param) || (state->received_data < state->total_data)) { END_PROFILE(SMBtranss2); - return -1; + return; } - /* construct_reply_common has done us the favor to pre-fill the - * command field with SMBtranss2 which is wrong :-) + /* + * construct_reply_common will copy smb_com from inbuf to + * outbuf. SMBtranss2 is wrong here. */ - SCVAL(outbuf,smb_com,SMBtrans2); - - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { - END_PROFILE(SMBtranss2); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - init_smb_request(req, (uint8 *)inbuf); + SCVAL(req->inbuf,smb_com,SMBtrans2); - outsize = -1; handle_trans2(conn, req, state); - if (req->outbuf != NULL) { - outsize = smb_len(req->outbuf) + 4; - memcpy(outbuf, req->outbuf, outsize); - } - TALLOC_FREE(req); DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); - if (outsize == 0) { + if (req->outbuf == NULL) { + reply_doserror(req, ERRSRV, ERRnosupport); END_PROFILE(SMBtranss2); - return(ERROR_DOS(ERRSRV,ERRnosupport)); + return; } END_PROFILE(SMBtranss2); - return(outsize); + return; bad_param: @@ -7327,6 +7320,7 @@ int reply_transs2(connection_struct *conn, SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtranss2); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } -- cgit From 9f3062d8a7abd904cf75da58553bdd34bc106e56 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 14:33:38 +0000 Subject: r24160: process_trans2 in smbd/blocking.c used send_trans2_replies. Fake a struct smb_request here. Volker (This used to be commit f712d1c92bee024a165b5facabdac1e2c866d9b1) --- source3/smbd/blocking.c | 17 +++++++++++------ source3/smbd/trans2.c | 12 ++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index c6e174ae22..1a0a988ea7 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -511,8 +511,7 @@ Waiting....\n", static BOOL process_trans2(blocking_lock_record *blr) { - char *inbuf = blr->inbuf; - char *outbuf; + struct smb_request *req; char params[2]; NTSTATUS status; struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(), @@ -541,12 +540,18 @@ static BOOL process_trans2(blocking_lock_record *blr) } /* We finally got the lock, return success. */ - outbuf = get_OutBuffer(); - construct_reply_common(inbuf, outbuf); - SCVAL(outbuf,smb_com,SMBtrans2); + + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + blocking_lock_reply_error(blr, NT_STATUS_NO_MEMORY); + return True; + } + + init_smb_request(req, (uint8 *)blr->inbuf); + + SCVAL(req->inbuf, smb_com, SMBtrans2); SSVAL(params,0,0); /* Fake up max_data_bytes here - we know it fits. */ - send_trans2_replies(inbuf, outbuf, max_send, params, 2, NULL, 0, 0xffff); + send_trans2_replies_new(req, params, 2, NULL, 0, 0xffff); return True; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 577524dedd..be4754ac08 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -735,12 +735,12 @@ int send_trans2_replies(const char *inbuf, return 0; } -static void send_trans2_replies_new(struct smb_request *req, - const char *params, - int paramsize, - const char *pdata, - int datasize, - int max_data_bytes) +void send_trans2_replies_new(struct smb_request *req, + const char *params, + int paramsize, + const char *pdata, + int datasize, + int max_data_bytes) { char *inbuf, *outbuf; int length, bufsize; -- cgit From 72ce8ef16856374a63816293c95d5fca1cda2a7b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 15:27:28 +0000 Subject: r24161: handle_trans2 takes care of errors itself, no need to do it in reply_transs2 (This used to be commit ca26b43e02f25d75e7439c6130f32dc322acd327) --- source3/smbd/trans2.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index be4754ac08..b024ab3f9b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7304,12 +7304,6 @@ void reply_transs2(connection_struct *conn, struct smb_request *req) SAFE_FREE(state->param); TALLOC_FREE(state); - if (req->outbuf == NULL) { - reply_doserror(req, ERRSRV, ERRnosupport); - END_PROFILE(SMBtranss2); - return; - } - END_PROFILE(SMBtranss2); return; -- cgit From c2fb81bbf037a810fd874c13fc1d0807b5e1f3c2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 15:45:41 +0000 Subject: r24162: send_trans2_replies is now static in trans2.c (This used to be commit 47261fb6fecc036cb1605f46bbe24e9b3661ff8c) --- source3/smbd/trans2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b024ab3f9b..12383c8f1f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -576,14 +576,14 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list * HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -int send_trans2_replies(const char *inbuf, - char *outbuf, - int bufsize, - const char *params, - int paramsize, - const char *pdata, - int datasize, - int max_data_bytes) +static int send_trans2_replies(const char *inbuf, + char *outbuf, + int bufsize, + const char *params, + int paramsize, + const char *pdata, + int datasize, + int max_data_bytes) { /* As we are using a protocol > LANMAN1 then the max_send variable must have been set in the sessetupX call. -- cgit From c7a425f30fc0fa5f1e32ae30f631849c81786057 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 3 Aug 2007 16:06:44 +0000 Subject: r24163: Remove the send_trans2_replies_new wrapper This changes send_trans2_replies to not depend on large buffers anymore and finishes the trans2 conversion. (This used to be commit b1d133e4ffa8c9b8219ba6e7b83e23ca4bdd1616) --- source3/smbd/blocking.c | 2 +- source3/smbd/trans2.c | 177 ++++++++++++++++++++++++------------------------ 2 files changed, 90 insertions(+), 89 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 1a0a988ea7..0b24fc8257 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -551,7 +551,7 @@ static BOOL process_trans2(blocking_lock_record *blr) SCVAL(req->inbuf, smb_com, SMBtrans2); SSVAL(params,0,0); /* Fake up max_data_bytes here - we know it fits. */ - send_trans2_replies_new(req, params, 2, NULL, 0, 0xffff); + send_trans2_replies(req, params, 2, NULL, 0, 0xffff); return True; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 12383c8f1f..26769e53d6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -576,14 +576,12 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list * HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_trans2_replies(const char *inbuf, - char *outbuf, - int bufsize, - const char *params, - int paramsize, - const char *pdata, - int datasize, - int max_data_bytes) +void send_trans2_replies(struct smb_request *req, + const char *params, + int paramsize, + const char *pdata, + int datasize, + int max_data_bytes) { /* As we are using a protocol > LANMAN1 then the max_send variable must have been set in the sessetupX call. @@ -599,10 +597,7 @@ static int send_trans2_replies(const char *inbuf, int params_sent_thistime, data_sent_thistime, total_sent_thistime; int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */ int data_alignment_offset = 0; - - /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */ - - set_message(inbuf,outbuf,10,0,True); + BOOL overflow = False; /* Modify the data_to_send and datasize and set the error if we're trying to send more than max_data_bytes. We still send @@ -613,16 +608,15 @@ static int send_trans2_replies(const char *inbuf, DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n", max_data_bytes, datasize )); datasize = data_to_send = max_data_bytes; - error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__); + overflow = True; } /* If there genuinely are no parameters or data to send just send the empty packet */ if(params_to_send == 0 && data_to_send == 0) { - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("send_trans2_replies: send_smb failed."); - return 0; + reply_outbuf(req, 10, 0); + show_msg((char *)req->outbuf); + return; } /* When sending params and data ensure that both are nicely aligned */ @@ -636,7 +630,10 @@ static int send_trans2_replies(const char *inbuf, /* The alignment_offset is to align the param bytes on an even byte boundary. NT 4.0 Beta needs this to work correctly. */ - useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf); + useable_space = max_send - (smb_size + + 2 * 10 /* wct */ + + alignment_offset + + data_alignment_offset); /* useable_space can never be more than max_send minus the alignment offset. */ @@ -657,11 +654,11 @@ static int send_trans2_replies(const char *inbuf, total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset); - set_message(inbuf, outbuf, 10, total_sent_thistime, True); + reply_outbuf(req, 10, total_sent_thistime); /* Set total params and data to be sent */ - SSVAL(outbuf,smb_tprcnt,paramsize); - SSVAL(outbuf,smb_tdrcnt,datasize); + SSVAL(req->outbuf,smb_tprcnt,paramsize); + SSVAL(req->outbuf,smb_tdrcnt,datasize); /* Calculate how many parameters and data we can fit into * this packet. Parameters get precedence @@ -671,53 +668,79 @@ static int send_trans2_replies(const char *inbuf, data_sent_thistime = useable_space - params_sent_thistime; data_sent_thistime = MIN(data_sent_thistime,data_to_send); - SSVAL(outbuf,smb_prcnt, params_sent_thistime); + SSVAL(req->outbuf,smb_prcnt, params_sent_thistime); /* smb_proff is the offset from the start of the SMB header to the parameter bytes, however the first 4 bytes of outbuf are the Netbios over TCP header. Thus use smb_base() to subtract them from the calculation */ - SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + SSVAL(req->outbuf,smb_proff, + ((smb_buf(req->outbuf)+alignment_offset) + - smb_base(req->outbuf))); if(params_sent_thistime == 0) - SSVAL(outbuf,smb_prdisp,0); + SSVAL(req->outbuf,smb_prdisp,0); else /* Absolute displacement of param bytes sent in this packet */ - SSVAL(outbuf,smb_prdisp,pp - params); + SSVAL(req->outbuf,smb_prdisp,pp - params); - SSVAL(outbuf,smb_drcnt, data_sent_thistime); + SSVAL(req->outbuf,smb_drcnt, data_sent_thistime); if(data_sent_thistime == 0) { - SSVAL(outbuf,smb_droff,0); - SSVAL(outbuf,smb_drdisp, 0); + SSVAL(req->outbuf,smb_droff,0); + SSVAL(req->outbuf,smb_drdisp, 0); } else { /* The offset of the data bytes is the offset of the parameter bytes plus the number of parameters being sent this time */ - SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - - smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); - SSVAL(outbuf,smb_drdisp, pd - pdata); + SSVAL(req->outbuf, smb_droff, + ((smb_buf(req->outbuf)+alignment_offset) + - smb_base(req->outbuf)) + + params_sent_thistime + data_alignment_offset); + SSVAL(req->outbuf,smb_drdisp, pd - pdata); } /* Copy the param bytes into the packet */ - if(params_sent_thistime) - memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + if(params_sent_thistime) { + if (alignment_offset != 0) { + memset(smb_buf(req->outbuf), 0, + alignment_offset); + } + memcpy((smb_buf(req->outbuf)+alignment_offset), pp, + params_sent_thistime); + } /* Copy in the data bytes */ - if(data_sent_thistime) - memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ - data_alignment_offset,pd,data_sent_thistime); + if(data_sent_thistime) { + if (data_alignment_offset != 0) { + memset((smb_buf(req->outbuf)+alignment_offset+ + params_sent_thistime), 0, + data_alignment_offset); + } + memcpy(smb_buf(req->outbuf)+alignment_offset + +params_sent_thistime+data_alignment_offset, + pd,data_sent_thistime); + } DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", params_sent_thistime, data_sent_thistime, useable_space)); DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", params_to_send, data_to_send, paramsize, datasize)); + if (overflow) { + error_packet_set((char *)req->outbuf, + ERRDOS,ERRbufferoverflow, + STATUS_BUFFER_OVERFLOW, + __LINE__,__FILE__); + } + /* Send the packet */ - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) + show_msg((char *)req->outbuf); + if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) exit_server_cleanly("send_trans2_replies: send_smb failed."); + TALLOC_FREE(req->outbuf); + pp += params_sent_thistime; pd += data_sent_thistime; @@ -728,33 +751,11 @@ static int send_trans2_replies(const char *inbuf, if(params_to_send < 0 || data_to_send < 0) { DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!", params_to_send, data_to_send)); - return -1; + return; } } - return 0; -} - -void send_trans2_replies_new(struct smb_request *req, - const char *params, - int paramsize, - const char *pdata, - int datasize, - int max_data_bytes) -{ - char *inbuf, *outbuf; - int length, bufsize; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - reply_post_legacy(req, send_trans2_replies( - inbuf, outbuf, bufsize, - params, paramsize, - pdata, datasize, - max_data_bytes)); + return; } /**************************************************************************** @@ -994,7 +995,7 @@ static void call_trans2open(connection_struct *conn, } /* Send the required number of replies */ - send_trans2_replies_new(req, params, 30, *ppdata, 0, max_data_bytes); + send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes); } /********************************************************* @@ -2024,8 +2025,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,6,0); /* Never an EA error */ SSVAL(params,8,last_entry_off); - send_trans2_replies_new(req, params, 10, pdata, PTR_DIFF(p,pdata), - max_data_bytes); + send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata), + max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -2341,8 +2342,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,4,0); /* Never an EA error */ SSVAL(params,6,last_entry_off); - send_trans2_replies_new(req, params, 8, pdata, PTR_DIFF(p,pdata), - max_data_bytes); + send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata), + max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); @@ -2865,8 +2866,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } - send_trans2_replies_new(req, params, 0, pdata, data_len, - max_data_bytes); + send_trans2_replies(req, params, 0, pdata, data_len, + max_data_bytes); DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) ); @@ -2981,10 +2982,10 @@ cap_low = 0x%x, cap_high = 0x%x\n", return; } - send_trans2_replies_new(req, - *pparams, param_len, - *ppdata, data_len, - max_data_bytes); + send_trans2_replies(req, + *pparams, param_len, + *ppdata, data_len, + max_data_bytes); if (NT_STATUS_IS_OK(status)) { /* Server-side transport encryption is now *on*. */ @@ -3451,8 +3452,8 @@ static void call_trans2qpipeinfo(connection_struct *conn, return; } - send_trans2_replies_new(req, params, param_size, *ppdata, data_size, - max_data_bytes); + send_trans2_replies(req, params, param_size, *ppdata, data_size, + max_data_bytes); return; } @@ -4381,8 +4382,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return; } - send_trans2_replies_new(req, params, param_size, *ppdata, data_size, - max_data_bytes); + send_trans2_replies(req, params, param_size, *ppdata, data_size, + max_data_bytes); return; } @@ -6151,9 +6152,9 @@ static void call_trans2setfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); SSVAL(params,0,0); - send_trans2_replies_new(req, params, 2, - *ppdata, 0, - max_data_bytes); + send_trans2_replies(req, params, 2, + *ppdata, 0, + max_data_bytes); return; } else { @@ -6506,8 +6507,8 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } SSVAL(params,0,0); - send_trans2_replies_new(req, params, 2, *ppdata, data_return_size, - max_data_bytes); + send_trans2_replies(req, params, 2, *ppdata, data_return_size, + max_data_bytes); return; } @@ -6623,7 +6624,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, SSVAL(params,0,0); - send_trans2_replies_new(req, params, 2, *ppdata, 0, max_data_bytes); + send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes); return; } @@ -6677,7 +6678,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn, if(fnf_handle == 0) fnf_handle = 257; - send_trans2_replies_new(req, params, 6, *ppdata, 0, max_data_bytes); + send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes); return; } @@ -6708,7 +6709,7 @@ static void call_trans2findnotifynext(connection_struct *conn, SSVAL(params,0,0); /* No changes */ SSVAL(params,2,0); /* No EA errors */ - send_trans2_replies_new(req, params, 4, *ppdata, 0, max_data_bytes); + send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes); return; } @@ -6753,7 +6754,7 @@ static void call_trans2getdfsreferral(connection_struct *conn, SSVAL(req->inbuf, smb_flg2, SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); - send_trans2_replies_new(req,0,0,*ppdata,reply_size, max_data_bytes); + send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes); return; } @@ -6800,8 +6801,8 @@ static void call_trans2ioctl(connection_struct *conn, srvstr_push(pdata, req->flags2, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ - send_trans2_replies_new(req, *pparams, 0, *ppdata, 32, - max_data_bytes); + send_trans2_replies(req, *pparams, 0, *ppdata, 32, + max_data_bytes); return; } -- cgit From 01ee1c7909bc6840ada40421b9ca1c3b4cbf99ae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Aug 2007 16:51:43 +0000 Subject: r24164: Fix for write cache corruption bug reported by Jean-Francois Panisset . Awaiting confirmation from reporter. Jeremy. (This used to be commit 7bd65060bd965bd17a5d79639cf561b8b578cb36) --- source3/smbd/fileio.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index e797dbda14..76b29ec998 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -508,15 +508,20 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", write_path = 3; - } else if ( (pos >= wcp->file_size) && + } else if ( (pos >= wcp->file_size) && (n == 1) && - (pos < wcp->offset + 2*wcp->alloc_size) && - (wcp->file_size == wcp->offset + wcp->data_size)) { + (wcp->file_size == wcp->offset + wcp->data_size) && + (pos < wcp->file_size + wcp->alloc_size)) { /* - +---------------+ - | Cached data | - +---------------+ + + End of file ---->| + + +---------------+---------------+ + | Cached data | Cache buffer | + +---------------+---------------+ + + |<------- allocated size ---------------->| +--------+ | 1 Byte | @@ -524,13 +529,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", MS-Office seems to do this a lot to determine if there's enough space on the filesystem to write a new file. - */ - SMB_BIG_UINT new_start = wcp->offset + wcp->data_size; + Change to : + + End of file ---->| + +-----------------------+--------+ + | Zeroed Cached data | 1 Byte | + +-----------------------+--------+ + */ flush_write_cache(fsp, WRITE_FLUSH); - wcp->offset = new_start; - wcp->data_size = pos - new_start + 1; + wcp->offset = wcp->file_size; + wcp->data_size = pos - wcp->file_size + 1; memset(wcp->data, '\0', wcp->data_size); memcpy(wcp->data + wcp->data_size-1, data, 1); -- cgit From c847b2afe7f4c979499c20869563439e25f0cb7e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 4 Aug 2007 20:08:35 +0000 Subject: r24223: Convert reply_echo to the new API (This used to be commit 4863ff2899419e791ed0e340821072d004fb1d17) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 39 +++++++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index df86970ca8..02ad205bd5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -731,7 +731,7 @@ static const struct smb_message_struct { /* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, /* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE }, /* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, -/* 0x2b */ { "SMBecho",reply_echo,NULL,0}, +/* 0x2b */ { "SMBecho",NULL,reply_echo,0}, /* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER}, /* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC }, /* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 91e4274814..94f18641bf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3775,24 +3775,35 @@ void reply_tdis(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_echo(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_echo(connection_struct *conn, struct smb_request *req) { - int smb_reverb = SVAL(inbuf,smb_vwv0); + int smb_reverb; int seq_num; - unsigned int data_len = smb_buflen(inbuf); - int outsize = set_message(inbuf,outbuf,1,data_len,True); + unsigned int data_len = smb_buflen(req->inbuf); + START_PROFILE(SMBecho); + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBecho); + return; + } + if (data_len > BUFFER_SIZE) { DEBUG(0,("reply_echo: data_len too large.\n")); + reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES); END_PROFILE(SMBecho); - return -1; + return; } + smb_reverb = SVAL(req->inbuf,smb_vwv0); + + reply_outbuf(req, 1, data_len); + /* copy any incoming data back out */ - if (data_len > 0) - memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len); + if (data_len > 0) { + memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len); + } if (smb_reverb > 100) { DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb)); @@ -3800,21 +3811,21 @@ int reply_echo(connection_struct *conn, } for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) { - SSVAL(outbuf,smb_vwv0,seq_num); - - smb_setlen(inbuf,outbuf,outsize - 4); + SSVAL(req->outbuf,smb_vwv0,seq_num); - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) + show_msg((char *)req->outbuf); + if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) exit_server_cleanly("reply_echo: send_smb failed."); } DEBUG(3,("echo %d times\n", smb_reverb)); + TALLOC_FREE(req->outbuf); + smb_echo_count++; END_PROFILE(SMBecho); - return -1; + return; } /**************************************************************************** -- cgit From bf160bb6211fa1ca68c17f54290ce4cbb5dbb263 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 4 Aug 2007 20:28:46 +0000 Subject: r24224: Check wct in reply_trans (This used to be commit fc8759e63ccec7f1cfb9f1d0ecd0f19a496e4153) --- source3/smbd/ipc.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 769147926f..2e6b03fb94 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -502,15 +502,25 @@ int reply_trans(connection_struct *conn, int bufsize) { int outsize = 0; - unsigned int dsoff = SVAL(inbuf, smb_dsoff); - unsigned int dscnt = SVAL(inbuf, smb_dscnt); - unsigned int psoff = SVAL(inbuf, smb_psoff); - unsigned int pscnt = SVAL(inbuf, smb_pscnt); + unsigned int dsoff; + unsigned int dscnt; + unsigned int psoff; + unsigned int pscnt; struct trans_state *state; NTSTATUS result; START_PROFILE(SMBtrans); + if (SVAL(inbuf, smb_wct) < 10) { + END_PROFILE(SMBtrans); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + dsoff = SVAL(inbuf, smb_dsoff); + dscnt = SVAL(inbuf, smb_dscnt); + psoff = SVAL(inbuf, smb_psoff); + pscnt = SVAL(inbuf, smb_pscnt); + result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid trans request: %s\n", @@ -681,6 +691,11 @@ int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, show_msg(inbuf); + if (SVAL(inbuf, smb_wct) < 10) { + END_PROFILE(SMBtranss); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + for (state = conn->pending_trans; state != NULL; state = state->next) { if (state->mid == SVAL(inbuf,smb_mid)) { -- cgit From 5d2031915e9fa56cb1ccdc55a489bd62225ce739 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 4 Aug 2007 20:44:33 +0000 Subject: r24225: Convert reply_flush to the new API (This used to be commit f843c02f0794964eba02ab983f9c0701801f415c) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 30 +++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 02ad205bd5..f455b39a52 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -693,7 +693,7 @@ static const struct smb_message_struct { /* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, /* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, -/* 0x05 */ { "SMBflush",reply_flush,NULL,AS_USER}, +/* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER}, /* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE }, /* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE }, /* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 94f18641bf..2b54c636a5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3463,31 +3463,43 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int Reply to a flush. ****************************************************************************/ -int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_flush(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,0,0,False); - uint16 fnum = SVAL(inbuf,smb_vwv0); - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + uint16 fnum; + files_struct *fsp; + START_PROFILE(SMBflush); - if (fnum != 0xFFFF) - CHECK_FSP(fsp,conn); + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + fnum = SVAL(req->inbuf,smb_vwv0); + fsp = file_fsp(fnum); + + if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, ¤t_user)) { + return; + } if (!fsp) { file_sync_all(conn); } else { NTSTATUS status = sync_file(conn, fsp, True); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBflush); DEBUG(5,("reply_flush: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBflush); + return; } } + reply_outbuf(req, 0, 0); + DEBUG(3,("flush\n")); END_PROFILE(SMBflush); - return(outsize); + return; } /**************************************************************************** -- cgit From 133ef281c08b3c0f35b57d935e343674d69b39b3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 08:04:11 +0000 Subject: r24229: Push allocating InBuffer/OutBuffer into reply_transs (This used to be commit 39a7809aa4c34bb26178589245c419df44796e22) --- source3/smbd/ipc.c | 50 ++++++++++++++++++++++++++++++++------------------ source3/smbd/process.c | 2 +- 2 files changed, 33 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 2e6b03fb94..8ded5754fb 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -495,11 +495,7 @@ static NTSTATUS handle_trans(connection_struct *conn, Reply to a SMBtrans. ****************************************************************************/ -int reply_trans(connection_struct *conn, - char *inbuf, - char *outbuf, - int size, - int bufsize) +void reply_trans(connection_struct *conn, struct smb_request *req) { int outsize = 0; unsigned int dsoff; @@ -508,12 +504,21 @@ int reply_trans(connection_struct *conn, unsigned int pscnt; struct trans_state *state; NTSTATUS result; + char *inbuf, *outbuf; + int size, bufsize; START_PROFILE(SMBtrans); + if (!(reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize))) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBtrans); + return; + } + if (SVAL(inbuf, smb_wct) < 10) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtrans); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } dsoff = SVAL(inbuf, smb_dsoff); @@ -525,14 +530,16 @@ int reply_trans(connection_struct *conn, if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid trans request: %s\n", nt_errstr(result))); + reply_nterror(req, result); END_PROFILE(SMBtrans); - return ERROR_NT(result); + return; } if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return; } state->cmd = SMBtrans; @@ -566,8 +573,9 @@ int reply_trans(connection_struct *conn, DEBUG(0,("reply_trans: data malloc fail for %u " "bytes !\n", (unsigned int)state->total_data)); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans); - return(ERROR_DOS(ERRDOS,ERRnomem)); + return; } /* null-terminate the slack space */ memset(&state->data[state->total_data], 0, 100); @@ -589,8 +597,9 @@ int reply_trans(connection_struct *conn, "bytes !\n", (unsigned int)state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans); - return(ERROR_DOS(ERRDOS,ERRnomem)); + return; } /* null-terminate the slack space */ memset(&state->param[state->total_param], 0, 100); @@ -616,8 +625,9 @@ int reply_trans(connection_struct *conn, SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans); - return(ERROR_DOS(ERRDOS,ERRnomem)); + return; } if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) > inbuf + size) @@ -643,27 +653,30 @@ int reply_trans(connection_struct *conn, TALLOC_FREE(state); if (!NT_STATUS_IS_OK(result)) { + reply_nterror(req, result); END_PROFILE(SMBtrans); - return ERROR_NT(result); + return; } if (outsize == 0) { + reply_nterror(req, NT_STATUS_INTERNAL_ERROR); END_PROFILE(SMBtrans); - return ERROR_NT(NT_STATUS_INTERNAL_ERROR); + return; } END_PROFILE(SMBtrans); - return outsize; + reply_post_legacy(req, outsize); + return; } DLIST_ADD(conn->pending_trans, state); /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(inbuf,outbuf,0,0,True); - show_msg(outbuf); + reply_outbuf(req, 0, 0); + show_msg((char *)req->outbuf); END_PROFILE(SMBtrans); - return outsize; + return; bad_param: @@ -672,7 +685,8 @@ int reply_trans(connection_struct *conn, SAFE_FREE(state->param); TALLOC_FREE(state); END_PROFILE(SMBtrans); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f455b39a52..f593c5e177 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -725,7 +725,7 @@ static const struct smb_message_struct { /* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE }, /* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER }, /* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER }, -/* 0x25 */ { "SMBtrans",reply_trans,NULL,AS_USER | CAN_IPC }, +/* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC }, /* 0x26 */ { "SMBtranss",reply_transs,NULL,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0}, /* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, -- cgit From f1822fe737f700ffcf9b7afc32e96725b5c69e99 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 08:31:41 +0000 Subject: r24230: Push down reply_prep_legacy in reply_trans The last checkin was for reply_trans, not reply_transs (This used to be commit 50a2bfd9e04d51aa5e3ae9d6620a98eeb158b6ea) --- source3/smbd/ipc.c | 114 +++++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 52 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8ded5754fb..8b80d8bcc4 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -509,24 +509,19 @@ void reply_trans(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBtrans); - if (!(reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize))) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBtrans); - return; - } - - if (SVAL(inbuf, smb_wct) < 10) { + if (SVAL(req->inbuf, smb_wct) < 10) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtrans); return; } - dsoff = SVAL(inbuf, smb_dsoff); - dscnt = SVAL(inbuf, smb_dscnt); - psoff = SVAL(inbuf, smb_psoff); - pscnt = SVAL(inbuf, smb_pscnt); + size = smb_len(req->inbuf) + 4; + dsoff = SVAL(req->inbuf, smb_dsoff); + dscnt = SVAL(req->inbuf, smb_dscnt); + psoff = SVAL(req->inbuf, smb_psoff); + pscnt = SVAL(req->inbuf, smb_pscnt); - result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); + result = allow_new_trans(conn->pending_trans, req->mid); if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid trans request: %s\n", nt_errstr(result))); @@ -544,23 +539,24 @@ void reply_trans(connection_struct *conn, struct smb_request *req) state->cmd = SMBtrans; - state->mid = SVAL(inbuf, smb_mid); - state->vuid = SVAL(inbuf, smb_uid); - state->setup_count = CVAL(inbuf, smb_suwcnt); + state->mid = req->mid; + state->vuid = req->vuid; + state->setup_count = CVAL(req->inbuf, smb_suwcnt); state->setup = NULL; - state->total_param = SVAL(inbuf, smb_tpscnt); + state->total_param = SVAL(req->inbuf, smb_tpscnt); state->param = NULL; - state->total_data = SVAL(inbuf, smb_tdscnt); + state->total_data = SVAL(req->inbuf, smb_tdscnt); state->data = NULL; - state->max_param_return = SVAL(inbuf, smb_mprcnt); - state->max_data_return = SVAL(inbuf, smb_mdrcnt); - state->max_setup_return = CVAL(inbuf, smb_msrcnt); - state->close_on_completion = BITSETW(inbuf+smb_vwv5,0); - state->one_way = BITSETW(inbuf+smb_vwv5,1); + state->max_param_return = SVAL(req->inbuf, smb_mprcnt); + state->max_data_return = SVAL(req->inbuf, smb_mdrcnt); + state->max_setup_return = CVAL(req->inbuf, smb_msrcnt); + state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0); + state->one_way = BITSETW(req->inbuf+smb_vwv5,1); memset(state->name, '\0',sizeof(state->name)); - srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), state->name, - smb_buf(inbuf), sizeof(state->name), STR_TERMINATE); + srvstr_pull_buf(req->inbuf, req->flags2, state->name, + smb_buf(req->inbuf), sizeof(state->name), + STR_TERMINATE); if ((dscnt > state->total_data) || (pscnt > state->total_param)) goto bad_param; @@ -581,11 +577,12 @@ void reply_trans(connection_struct *conn, struct smb_request *req) memset(&state->data[state->total_data], 0, 100); if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; - if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || - (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) + if ((smb_base(req->inbuf)+dsoff+dscnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf))) goto bad_param; - memcpy(state->data,smb_base(inbuf)+dsoff,dscnt); + memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } if (state->total_param) { @@ -605,11 +602,12 @@ void reply_trans(connection_struct *conn, struct smb_request *req) memset(&state->param[state->total_param], 0, 100); if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; - if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || - (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) + if ((smb_base(req->inbuf)+psoff+pscnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf))) goto bad_param; - memcpy(state->param,smb_base(inbuf)+psoff,pscnt); + memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } state->received_data = dscnt; @@ -629,8 +627,8 @@ void reply_trans(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBtrans); return; } - if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) > - inbuf + size) + if (req->inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) > + req->inbuf + size) goto bad_param; if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(state->setup_count*SIZEOFWORD) < @@ -638,43 +636,55 @@ void reply_trans(connection_struct *conn, struct smb_request *req) goto bad_param; for (i=0;isetup_count;i++) - state->setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD); + state->setup[i] = SVAL(req->inbuf, + smb_vwv14+i*SIZEOFWORD); } state->received_param = pscnt; - if ((state->received_param == state->total_param) && - (state->received_data == state->total_data)) { + if ((state->received_param != state->total_param) || + (state->received_data != state->total_data)) { + DLIST_ADD(conn->pending_trans, state); - result = handle_trans(conn, state, inbuf, outbuf, &outsize); + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + reply_outbuf(req, 0, 0); + show_msg((char *)req->outbuf); + END_PROFILE(SMBtrans); + return; + } + if (!(reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize))) { SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBtrans); + return; + } - if (!NT_STATUS_IS_OK(result)) { - reply_nterror(req, result); - END_PROFILE(SMBtrans); - return; - } + result = handle_trans(conn, state, inbuf, outbuf, &outsize); - if (outsize == 0) { - reply_nterror(req, NT_STATUS_INTERNAL_ERROR); - END_PROFILE(SMBtrans); - return; - } + if (NT_STATUS_IS_OK(result)) { + reply_post_legacy(req, outsize); + } + SAFE_FREE(state->data); + SAFE_FREE(state->param); + TALLOC_FREE(state); + + if (!NT_STATUS_IS_OK(result)) { + reply_nterror(req, result); END_PROFILE(SMBtrans); - reply_post_legacy(req, outsize); return; } - DLIST_ADD(conn->pending_trans, state); + if (outsize == 0) { + reply_nterror(req, NT_STATUS_INTERNAL_ERROR); + END_PROFILE(SMBtrans); + return; + } - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - reply_outbuf(req, 0, 0); - show_msg((char *)req->outbuf); END_PROFILE(SMBtrans); return; -- cgit From 1d3c1de502bdb925fbe83714e65c37984d63ee52 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 08:47:09 +0000 Subject: r24231: Push allocating InBuffer/OutBuffer into reply_transs (This used to be commit 74ae19cca6dd15b65deffbf464cfd0e485da8611) --- source3/smbd/ipc.c | 29 ++++++++++++++++++++--------- source3/smbd/process.c | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8b80d8bcc4..17c27b9957 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -703,21 +703,29 @@ void reply_trans(connection_struct *conn, struct smb_request *req) Reply to a secondary SMBtrans. ****************************************************************************/ -int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, - int size, int bufsize) +void reply_transs(connection_struct *conn, struct smb_request *req) { int outsize = 0; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; NTSTATUS result; + char *inbuf, *outbuf; + int size, bufsize; START_PROFILE(SMBtranss); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBtranss); + return; + } + show_msg(inbuf); - if (SVAL(inbuf, smb_wct) < 10) { + if (req->wct < 10) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtranss); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } for (state = conn->pending_trans; state != NULL; @@ -728,8 +736,9 @@ int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, } if ((state == NULL) || (state->cmd != SMBtrans)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtranss); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } /* Revise total_params and total_data in case they have changed @@ -792,7 +801,7 @@ int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, if ((state->received_param < state->total_param) || (state->received_data < state->total_data)) { END_PROFILE(SMBtranss); - return -1; + return; } /* construct_reply_common has done us the favor to pre-fill the @@ -808,12 +817,13 @@ int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, TALLOC_FREE(state); if ((outsize == 0) || !NT_STATUS_IS_OK(result)) { + reply_doserror(req, ERRSRV, ERRnosupport); END_PROFILE(SMBtranss); - return(ERROR_DOS(ERRSRV,ERRnosupport)); + return; } END_PROFILE(SMBtranss); - return(outsize); + return; bad_param: @@ -822,6 +832,7 @@ int reply_transs(connection_struct *conn, char *inbuf,char *outbuf, SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtranss); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f593c5e177..d7bde0043a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -726,7 +726,7 @@ static const struct smb_message_struct { /* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER }, /* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER }, /* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC }, -/* 0x26 */ { "SMBtranss",reply_transs,NULL,AS_USER | CAN_IPC}, +/* 0x26 */ { "SMBtranss",NULL,reply_transs,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0}, /* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, /* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE }, -- cgit From 0cfea6de67493ce4496f6fbbb1bc14b486831111 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 09:01:15 +0000 Subject: r24232: Push down reply_prep_legacy inside reply_transs (This used to be commit 511f8bc030a9a16c2e793ce5d06577608e101de4) --- source3/smbd/ipc.c | 60 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 17c27b9957..3df740f9cf 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -714,13 +714,7 @@ void reply_transs(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBtranss); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBtranss); - return; - } - - show_msg(inbuf); + show_msg((char *)req->inbuf); if (req->wct < 10) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -730,7 +724,7 @@ void reply_transs(connection_struct *conn, struct smb_request *req) for (state = conn->pending_trans; state != NULL; state = state->next) { - if (state->mid == SVAL(inbuf,smb_mid)) { + if (state->mid == req->mid) { break; } } @@ -744,18 +738,20 @@ void reply_transs(connection_struct *conn, struct smb_request *req) /* Revise total_params and total_data in case they have changed * downwards */ - if (SVAL(inbuf, smb_vwv0) < state->total_param) - state->total_param = SVAL(inbuf,smb_vwv0); - if (SVAL(inbuf, smb_vwv1) < state->total_data) - state->total_data = SVAL(inbuf,smb_vwv1); + if (SVAL(req->inbuf, smb_vwv0) < state->total_param) + state->total_param = SVAL(req->inbuf,smb_vwv0); + if (SVAL(req->inbuf, smb_vwv1) < state->total_data) + state->total_data = SVAL(req->inbuf,smb_vwv1); + + size = smb_len(req->inbuf) + 4; - pcnt = SVAL(inbuf, smb_spscnt); - poff = SVAL(inbuf, smb_spsoff); - pdisp = SVAL(inbuf, smb_spsdisp); + pcnt = SVAL(req->inbuf, smb_spscnt); + poff = SVAL(req->inbuf, smb_spsoff); + pdisp = SVAL(req->inbuf, smb_spsdisp); - dcnt = SVAL(inbuf, smb_sdscnt); - doff = SVAL(inbuf, smb_sdsoff); - ddisp = SVAL(inbuf, smb_sdsdisp); + dcnt = SVAL(req->inbuf, smb_sdscnt); + doff = SVAL(req->inbuf, smb_sdsoff); + ddisp = SVAL(req->inbuf, smb_sdsdisp); state->received_param += pcnt; state->received_data += dcnt; @@ -771,13 +767,15 @@ void reply_transs(connection_struct *conn, struct smb_request *req) goto bad_param; if (pdisp > state->total_param) goto bad_param; - if ((smb_base(inbuf) + poff + pcnt > inbuf + size) || - (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) + if ((smb_base(req->inbuf) + poff + pcnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf) + poff + pcnt + < smb_base(req->inbuf))) goto bad_param; if (state->param + pdisp < state->param) goto bad_param; - memcpy(state->param+pdisp,smb_base(inbuf)+poff, + memcpy(state->param+pdisp,smb_base(req->inbuf)+poff, pcnt); } @@ -788,13 +786,15 @@ void reply_transs(connection_struct *conn, struct smb_request *req) goto bad_param; if (ddisp > state->total_data) goto bad_param; - if ((smb_base(inbuf) + doff + dcnt > inbuf + size) || - (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) + if ((smb_base(req->inbuf) + doff + dcnt + > (char *)inbuf + size) || + (smb_base(req->inbuf) + doff + dcnt + < smb_base(req->inbuf))) goto bad_param; if (state->data + ddisp < state->data) goto bad_param; - memcpy(state->data+ddisp, smb_base(inbuf)+doff, + memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, dcnt); } @@ -804,13 +804,23 @@ void reply_transs(connection_struct *conn, struct smb_request *req) return; } + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBtranss); + return; + } + /* construct_reply_common has done us the favor to pre-fill the * command field with SMBtranss which is wrong :-) */ - SCVAL(outbuf,smb_com,SMBtrans); + SCVAL(req->outbuf,smb_com,SMBtrans); result = handle_trans(conn, state, inbuf, outbuf, &outsize); + if (NT_STATUS_IS_OK(result)) { + reply_post_legacy(req, outsize); + } + DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); SAFE_FREE(state->param); -- cgit From e41528c3f498640800bb3c773f01e27105963bdf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 09:18:14 +0000 Subject: r24233: Push reply_prep_legacy into handle_trans (This used to be commit dc27c3c668f86d008c27b8a749f5726287ba54a5) --- source3/smbd/ipc.c | 50 ++++++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3df740f9cf..1dab5dbe56 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -426,18 +426,23 @@ static int named_pipe(connection_struct *conn, } static NTSTATUS handle_trans(connection_struct *conn, - struct trans_state *state, - const char *inbuf, - char *outbuf, - int *outsize) + struct smb_request *req, + struct trans_state *state, + int *outsize) { char *local_machine_name; int name_offset = 0; + char *inbuf, *outbuf; + int size, bufsize; DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", state->name,(unsigned int)state->total_data,(unsigned int)state->total_param, (unsigned int)state->setup_count)); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + return NT_STATUS_NO_MEMORY; + } + /* * WinCE wierdness.... */ @@ -488,6 +493,8 @@ static NTSTATUS handle_trans(connection_struct *conn, if (state->close_on_completion) close_cnum(conn,state->vuid); + reply_post_legacy(req, *outsize); + return NT_STATUS_OK; } @@ -504,8 +511,7 @@ void reply_trans(connection_struct *conn, struct smb_request *req) unsigned int pscnt; struct trans_state *state; NTSTATUS result; - char *inbuf, *outbuf; - int size, bufsize; + int size; START_PROFILE(SMBtrans); @@ -654,20 +660,7 @@ void reply_trans(connection_struct *conn, struct smb_request *req) return; } - if (!(reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize))) { - SAFE_FREE(state->data); - SAFE_FREE(state->param); - TALLOC_FREE(state); - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBtrans); - return; - } - - result = handle_trans(conn, state, inbuf, outbuf, &outsize); - - if (NT_STATUS_IS_OK(result)) { - reply_post_legacy(req, outsize); - } + result = handle_trans(conn, req, state, &outsize); SAFE_FREE(state->data); SAFE_FREE(state->param); @@ -709,8 +702,7 @@ void reply_transs(connection_struct *conn, struct smb_request *req) unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; NTSTATUS result; - char *inbuf, *outbuf; - int size, bufsize; + int size; START_PROFILE(SMBtranss); @@ -787,7 +779,7 @@ void reply_transs(connection_struct *conn, struct smb_request *req) if (ddisp > state->total_data) goto bad_param; if ((smb_base(req->inbuf) + doff + dcnt - > (char *)inbuf + size) || + > (char *)req->inbuf + size) || (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf))) goto bad_param; @@ -804,22 +796,12 @@ void reply_transs(connection_struct *conn, struct smb_request *req) return; } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBtranss); - return; - } - /* construct_reply_common has done us the favor to pre-fill the * command field with SMBtranss which is wrong :-) */ SCVAL(req->outbuf,smb_com,SMBtrans); - result = handle_trans(conn, state, inbuf, outbuf, &outsize); - - if (NT_STATUS_IS_OK(result)) { - reply_post_legacy(req, outsize); - } + result = handle_trans(conn, req, state, &outsize); DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); -- cgit From abc519ff43fc71b3353704227d1941285062a256 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 09:19:21 +0000 Subject: r24234: Reformatting -- SCNR (This used to be commit 040d6d5db6d929f1612b1b0dc762b7f55c956740) --- source3/smbd/ipc.c | 69 ++++++++++++++++-------------------------------------- 1 file changed, 20 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1dab5dbe56..c56d167806 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -354,34 +354,20 @@ static int api_fd_reply(connection_struct *conn, Handle named pipe commands. ****************************************************************************/ -static int named_pipe(connection_struct *conn, - uint16 vuid, - const char *inbuf, - char *outbuf, - char *name, - uint16 *setup, - char *data, - char *params, - int suwcnt, - int tdscnt, - int tpscnt, - int msrcnt, - int mdrcnt, - int mprcnt) +static int named_pipe(connection_struct *conn, uint16 vuid, + const char *inbuf, char *outbuf, + char *name, uint16 *setup, + char *data, char *params, + int suwcnt, int tdscnt,int tpscnt, + int msrcnt, int mdrcnt, int mprcnt) { DEBUG(3,("named pipe command on <%s> name\n", name)); if (strequal(name,"LANMAN")) { - return api_reply(conn, - vuid, - inbuf, - outbuf, - data, - params, - tdscnt, - tpscnt, - mdrcnt, - mprcnt); + return api_reply(conn, vuid, inbuf, outbuf, + data, params, + tdscnt, tpscnt, + mdrcnt, mprcnt); } if (strequal(name,"WKSSVC") || @@ -390,37 +376,22 @@ static int named_pipe(connection_struct *conn, strequal(name,"SAMR") || strequal(name,"LSARPC")) { DEBUG(4,("named pipe command from Win95 (wow!)\n")); - return api_fd_reply(conn, - vuid, - inbuf, - outbuf, - setup, - data, - params, - suwcnt, - tdscnt, - tpscnt, - mdrcnt, - mprcnt); + return api_fd_reply(conn, vuid, inbuf, outbuf, + setup, data, params, + suwcnt, tdscnt, tpscnt, + mdrcnt, mprcnt); } if (strlen(name) < 1) { - return api_fd_reply(conn, - vuid, - inbuf, - outbuf, - setup, - data, - params, - suwcnt, - tdscnt, - tpscnt, - mdrcnt, - mprcnt); + return api_fd_reply(conn, vuid, inbuf, outbuf, + setup, data, + params, suwcnt, tdscnt, + tpscnt, mdrcnt, mprcnt); } if (setup) - DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1])); + DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", + (int)setup[0],(int)setup[1])); return 0; } -- cgit From 3bb9f20bc3df85d8c099999dbc2c372eac245c28 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 09:46:17 +0000 Subject: r24235: Make handle_trans reply to errors itself (This used to be commit 06d0c74b74754c55f4c8ef0899bda08476e7dd4b) --- source3/smbd/ipc.c | 76 +++++++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c56d167806..51403cd8b2 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -396,22 +396,22 @@ static int named_pipe(connection_struct *conn, uint16 vuid, return 0; } -static NTSTATUS handle_trans(connection_struct *conn, - struct smb_request *req, - struct trans_state *state, - int *outsize) +static void handle_trans(connection_struct *conn, struct smb_request *req, + struct trans_state *state) { char *local_machine_name; int name_offset = 0; char *inbuf, *outbuf; int size, bufsize; + int outsize; DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", state->name,(unsigned int)state->total_data,(unsigned int)state->total_param, (unsigned int)state->setup_count)); if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - return NT_STATUS_NO_MEMORY; + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } /* @@ -422,7 +422,8 @@ static NTSTATUS handle_trans(connection_struct *conn, get_local_machine_name()); if (local_machine_name == NULL) { - return NT_STATUS_NO_MEMORY; + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } if (strnequal(state->name, local_machine_name, @@ -432,7 +433,8 @@ static NTSTATUS handle_trans(connection_struct *conn, if (!strnequal(&state->name[name_offset], "\\PIPE", strlen("\\PIPE"))) { - return NT_STATUS_NOT_SUPPORTED; + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + return; } name_offset += strlen("\\PIPE"); @@ -444,29 +446,30 @@ static NTSTATUS handle_trans(connection_struct *conn, name_offset++; DEBUG(5,("calling named_pipe\n")); - *outsize = named_pipe(conn, - state->vuid, - inbuf, - outbuf, - state->name+name_offset, - state->setup,state->data, - state->param, - state->setup_count,state->total_data, - state->total_param, - state->max_setup_return, - state->max_data_return, - state->max_param_return); - - if (*outsize == 0) { - return NT_STATUS_NOT_SUPPORTED; + outsize = named_pipe(conn, + state->vuid, + inbuf, + outbuf, + state->name+name_offset, + state->setup,state->data, + state->param, + state->setup_count,state->total_data, + state->total_param, + state->max_setup_return, + state->max_data_return, + state->max_param_return); + + if (outsize == 0) { + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + return; } if (state->close_on_completion) close_cnum(conn,state->vuid); - reply_post_legacy(req, *outsize); + reply_post_legacy(req, outsize); - return NT_STATUS_OK; + return; } /**************************************************************************** @@ -475,7 +478,6 @@ static NTSTATUS handle_trans(connection_struct *conn, void reply_trans(connection_struct *conn, struct smb_request *req) { - int outsize = 0; unsigned int dsoff; unsigned int dscnt; unsigned int psoff; @@ -631,24 +633,12 @@ void reply_trans(connection_struct *conn, struct smb_request *req) return; } - result = handle_trans(conn, req, state, &outsize); + handle_trans(conn, req, state); SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); - if (!NT_STATUS_IS_OK(result)) { - reply_nterror(req, result); - END_PROFILE(SMBtrans); - return; - } - - if (outsize == 0) { - reply_nterror(req, NT_STATUS_INTERNAL_ERROR); - END_PROFILE(SMBtrans); - return; - } - END_PROFILE(SMBtrans); return; @@ -669,10 +659,8 @@ void reply_trans(connection_struct *conn, struct smb_request *req) void reply_transs(connection_struct *conn, struct smb_request *req) { - int outsize = 0; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - NTSTATUS result; int size; START_PROFILE(SMBtranss); @@ -772,19 +760,13 @@ void reply_transs(connection_struct *conn, struct smb_request *req) */ SCVAL(req->outbuf,smb_com,SMBtrans); - result = handle_trans(conn, req, state, &outsize); + handle_trans(conn, req, state); DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); - if ((outsize == 0) || !NT_STATUS_IS_OK(result)) { - reply_doserror(req, ERRSRV, ERRnosupport); - END_PROFILE(SMBtranss); - return; - } - END_PROFILE(SMBtranss); return; -- cgit From 97a817dceb2906e9d4d63979f9f7619fb12a03a1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 10:01:58 +0000 Subject: r24236: Push reply_prep_legacy() into named_pipe() (This used to be commit b38f9347e81364d224e5ca00609099a74410e99c) --- source3/smbd/ipc.c | 92 +++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 51403cd8b2..9140ea66ac 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -354,20 +354,31 @@ static int api_fd_reply(connection_struct *conn, Handle named pipe commands. ****************************************************************************/ -static int named_pipe(connection_struct *conn, uint16 vuid, - const char *inbuf, char *outbuf, - char *name, uint16 *setup, - char *data, char *params, - int suwcnt, int tdscnt,int tpscnt, - int msrcnt, int mdrcnt, int mprcnt) +static void named_pipe(connection_struct *conn, uint16 vuid, + struct smb_request *req, + char *name, uint16 *setup, + char *data, char *params, + int suwcnt, int tdscnt,int tpscnt, + int msrcnt, int mdrcnt, int mprcnt) { + char *inbuf, *outbuf; + int size, bufsize; + DEBUG(3,("named pipe command on <%s> name\n", name)); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + if (strequal(name,"LANMAN")) { - return api_reply(conn, vuid, inbuf, outbuf, - data, params, - tdscnt, tpscnt, - mdrcnt, mprcnt); + reply_post_legacy( + req, + api_reply(conn, vuid, inbuf, outbuf, + data, params, + tdscnt, tpscnt, + mdrcnt, mprcnt)); + return; } if (strequal(name,"WKSSVC") || @@ -376,24 +387,31 @@ static int named_pipe(connection_struct *conn, uint16 vuid, strequal(name,"SAMR") || strequal(name,"LSARPC")) { DEBUG(4,("named pipe command from Win95 (wow!)\n")); - return api_fd_reply(conn, vuid, inbuf, outbuf, - setup, data, params, - suwcnt, tdscnt, tpscnt, - mdrcnt, mprcnt); + reply_post_legacy( + req, + api_fd_reply(conn, vuid, inbuf, outbuf, + setup, data, params, + suwcnt, tdscnt, tpscnt, + mdrcnt, mprcnt)); + return; } if (strlen(name) < 1) { - return api_fd_reply(conn, vuid, inbuf, outbuf, - setup, data, - params, suwcnt, tdscnt, - tpscnt, mdrcnt, mprcnt); + reply_post_legacy( + req, + api_fd_reply(conn, vuid, inbuf, outbuf, + setup, data, + params, suwcnt, tdscnt, + tpscnt, mdrcnt, mprcnt)); + return; } if (setup) DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1])); - return 0; + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + return; } static void handle_trans(connection_struct *conn, struct smb_request *req, @@ -401,19 +419,11 @@ static void handle_trans(connection_struct *conn, struct smb_request *req, { char *local_machine_name; int name_offset = 0; - char *inbuf, *outbuf; - int size, bufsize; - int outsize; DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", state->name,(unsigned int)state->total_data,(unsigned int)state->total_param, (unsigned int)state->setup_count)); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - /* * WinCE wierdness.... */ @@ -446,29 +456,19 @@ static void handle_trans(connection_struct *conn, struct smb_request *req, name_offset++; DEBUG(5,("calling named_pipe\n")); - outsize = named_pipe(conn, - state->vuid, - inbuf, - outbuf, - state->name+name_offset, - state->setup,state->data, - state->param, - state->setup_count,state->total_data, - state->total_param, - state->max_setup_return, - state->max_data_return, - state->max_param_return); - - if (outsize == 0) { - reply_nterror(req, NT_STATUS_NOT_SUPPORTED); - return; - } + named_pipe(conn, state->vuid, req, + state->name+name_offset, + state->setup,state->data, + state->param, + state->setup_count,state->total_data, + state->total_param, + state->max_setup_return, + state->max_data_return, + state->max_param_return); if (state->close_on_completion) close_cnum(conn,state->vuid); - reply_post_legacy(req, outsize); - return; } -- cgit From d57a88a9948017bc9a1b5a12307e8e974425e39b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 10:04:11 +0000 Subject: r24237: Add send_trans_reply_new (This used to be commit f0598b3ca0ee04e31855c3e54f3198e6fd968737) --- source3/smbd/ipc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 9140ea66ac..157aff20c1 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -158,6 +158,24 @@ void send_trans_reply(const char *inbuf, } } +void send_trans_reply_new(struct smb_request *req, + char *rparam, int rparam_len, + char *rdata, int rdata_len, + BOOL buffer_too_large) +{ + char *inbuf, *outbuf; + int size, buflength; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &buflength)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + send_trans_reply(inbuf, outbuf, rparam, rparam_len, + rdata, rdata_len, buffer_too_large); + reply_post_legacy(req, -1); +} + /**************************************************************************** Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -- cgit From bcd0bf8e5e52d8f09e43aa74be55cafcb8e2cb59 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 10:17:58 +0000 Subject: r24238: Push down reply_prep_legacy one level (This used to be commit a6a2d97facf95c7997f3d12457f2811b3b7bde1b) --- source3/smbd/ipc.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 157aff20c1..e238a3cc12 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -379,17 +379,17 @@ static void named_pipe(connection_struct *conn, uint16 vuid, int suwcnt, int tdscnt,int tpscnt, int msrcnt, int mdrcnt, int mprcnt) { - char *inbuf, *outbuf; - int size, bufsize; - DEBUG(3,("named pipe command on <%s> name\n", name)); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - if (strequal(name,"LANMAN")) { + char *inbuf, *outbuf; + int size, bufsize; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + reply_post_legacy( req, api_reply(conn, vuid, inbuf, outbuf, @@ -404,7 +404,16 @@ static void named_pipe(connection_struct *conn, uint16 vuid, strequal(name,"WINREG") || strequal(name,"SAMR") || strequal(name,"LSARPC")) { + char *inbuf, *outbuf; + int size, bufsize; + DEBUG(4,("named pipe command from Win95 (wow!)\n")); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + reply_post_legacy( req, api_fd_reply(conn, vuid, inbuf, outbuf, @@ -415,6 +424,14 @@ static void named_pipe(connection_struct *conn, uint16 vuid, } if (strlen(name) < 1) { + char *inbuf, *outbuf; + int size, bufsize; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + reply_post_legacy( req, api_fd_reply(conn, vuid, inbuf, outbuf, -- cgit From fbe15d8db9fc06c9ad6565f15da58dbb7027ce35 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 10:28:12 +0000 Subject: r24239: Push reply_prep_legacy into api_fd_reply (This used to be commit e2a96497928ab959e36639fef2d493640bb6e951) --- source3/smbd/ipc.c | 89 +++++++++++++++++++++++------------------------------- 1 file changed, 38 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index e238a3cc12..a190a59996 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -263,7 +263,7 @@ static BOOL api_SNPHS(const char *inbuf, When no reply is generated, indicate unsupported. ****************************************************************************/ -static BOOL api_no_reply(const char *inbuf, char *outbuf, int max_rdata_len) +static void api_no_reply(struct smb_request *req) { char rparam[4]; @@ -274,39 +274,35 @@ static BOOL api_no_reply(const char *inbuf, char *outbuf, int max_rdata_len) DEBUG(3,("Unsupported API fd command\n")); /* now send the reply */ - send_trans_reply(inbuf, outbuf, rparam, 4, NULL, 0, False); + send_trans_reply_new(req, rparam, 4, NULL, 0, False); - return -1; + return; } /**************************************************************************** Handle remote api calls delivered to a named pipe already opened. ****************************************************************************/ -static int api_fd_reply(connection_struct *conn, - uint16 vuid, - const char *inbuf, - char *outbuf, - uint16 *setup, - char *data, - char *params, - int suwcnt, - int tdscnt, - int tpscnt, - int mdrcnt, - int mprcnt) +static void api_fd_reply(connection_struct *conn, uint16 vuid, + struct smb_request *req, + uint16 *setup, char *data, char *params, + int suwcnt, int tdscnt, int tpscnt, + int mdrcnt, int mprcnt) { BOOL reply = False; smb_np_struct *p = NULL; int pnum; int subcommand; + char *inbuf, *outbuf; + int size, buflength; DEBUG(5,("api_fd_reply\n")); /* First find out the name of this file. */ if (suwcnt != 2) { DEBUG(0,("Unexpected named pipe transaction.\n")); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } /* Get the file handle and hence the file name. */ @@ -322,18 +318,20 @@ static int api_fd_reply(connection_struct *conn, /* Win9x does this call with a unicode pipe name, not a pnum. */ /* Just return success for now... */ DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n")); - send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False); - return -1; + send_trans_reply_new(req, NULL, 0, NULL, 0, False); + return; } DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } if (vuid != p->vuid) { DEBUG(1, ("Got pipe request (pnum %x) using invalid VUID %d, " "expected %d\n", pnum, vuid, p->vuid)); - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum)); @@ -343,6 +341,11 @@ static int api_fd_reply(connection_struct *conn, DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply)); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &buflength)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + switch (subcommand) { case TRANSACT_DCERPCCMD: /* dce/rpc command */ @@ -359,13 +362,16 @@ static int api_fd_reply(connection_struct *conn, reply = api_SNPHS(inbuf, outbuf, p, params, tpscnt); break; default: - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } - if (!reply) - return api_no_reply(inbuf, outbuf, mdrcnt); + if (!reply) { + api_no_reply(req); + return; + } - return -1; + reply_post_legacy(req, -1); } /**************************************************************************** @@ -404,40 +410,21 @@ static void named_pipe(connection_struct *conn, uint16 vuid, strequal(name,"WINREG") || strequal(name,"SAMR") || strequal(name,"LSARPC")) { - char *inbuf, *outbuf; - int size, bufsize; DEBUG(4,("named pipe command from Win95 (wow!)\n")); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - reply_post_legacy( - req, - api_fd_reply(conn, vuid, inbuf, outbuf, - setup, data, params, - suwcnt, tdscnt, tpscnt, - mdrcnt, mprcnt)); + api_fd_reply(conn, vuid, req, + setup, data, params, + suwcnt, tdscnt, tpscnt, + mdrcnt, mprcnt); return; } if (strlen(name) < 1) { - char *inbuf, *outbuf; - int size, bufsize; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - reply_post_legacy( - req, - api_fd_reply(conn, vuid, inbuf, outbuf, - setup, data, - params, suwcnt, tdscnt, - tpscnt, mdrcnt, mprcnt)); + api_fd_reply(conn, vuid, req, + setup, data, + params, suwcnt, tdscnt, + tpscnt, mdrcnt, mprcnt); return; } -- cgit From b8de67a2f2ef7334a77aa3b71752658c4555191d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 10:37:08 +0000 Subject: r24240: Push down reply_prep_legacy one level inside api_fd_reply (This used to be commit 0bb95639d6b49b18f2a7f1131f54239355097119) --- source3/smbd/ipc.c | 73 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a190a59996..ddc42c408e 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -293,8 +293,6 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, smb_np_struct *p = NULL; int pnum; int subcommand; - char *inbuf, *outbuf; - int size, buflength; DEBUG(5,("api_fd_reply\n")); @@ -341,37 +339,74 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply)); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &buflength)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - switch (subcommand) { - case TRANSACT_DCERPCCMD: + case TRANSACT_DCERPCCMD: { + + char *inbuf, *outbuf; + int size, buflength; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &buflength)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + /* dce/rpc command */ reply = write_to_pipe(p, data, tdscnt); if (reply) reply = api_rpc_trans_reply(inbuf, outbuf, p); + + if (!reply) { + api_no_reply(req); + return; + } + reply_post_legacy(req, -1); break; - case TRANSACT_WAITNAMEDPIPEHANDLESTATE: + } + case TRANSACT_WAITNAMEDPIPEHANDLESTATE: { + + char *inbuf, *outbuf; + int size, buflength; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &buflength)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + /* Wait Named Pipe Handle state */ - reply = api_WNPHS(inbuf, outbuf, p, params, tpscnt); + if (!api_WNPHS(inbuf, outbuf, p, params, tpscnt)) { + api_no_reply(req); + return; + } + + reply_post_legacy(req, -1); break; - case TRANSACT_SETNAMEDPIPEHANDLESTATE: + } + case TRANSACT_SETNAMEDPIPEHANDLESTATE: { + + char *inbuf, *outbuf; + int size, buflength; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &buflength)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + /* Set Named Pipe Handle state */ - reply = api_SNPHS(inbuf, outbuf, p, params, tpscnt); + if (!api_SNPHS(inbuf, outbuf, p, params, tpscnt)) { + api_no_reply(req); + return; + } + + reply_post_legacy(req, -1); break; + } default: reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } - - if (!reply) { - api_no_reply(req); - return; - } - - reply_post_legacy(req, -1); } /**************************************************************************** -- cgit From 40f6afcea2dc2341682ce2dc1bc9082342c46d06 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 10:48:35 +0000 Subject: r24241: Remove reply_prep_legacy from api_WNPHS and api_SNPHS (This used to be commit 8702450e91943b1097ae3c8979d60b6962a69632) --- source3/smbd/ipc.c | 80 ++++++++++++++++-------------------------------------- 1 file changed, 23 insertions(+), 57 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ddc42c408e..bea4f77450 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -30,7 +30,7 @@ extern int max_send; #define NERR_notsupported 50 -extern int smb_read_error; +static void api_no_reply(struct smb_request *req); /******************************************************************* copies parameters and data, as needed, into the smb buffer @@ -209,26 +209,25 @@ static BOOL api_rpc_trans_reply(const char *inbuf, WaitNamedPipeHandleState ****************************************************************************/ -static BOOL api_WNPHS(const char *inbuf, - char *outbuf, - smb_np_struct *p, - char *param, - int param_len) +static void api_WNPHS(struct smb_request *req, smb_np_struct *p, + char *param, int param_len) { uint16 priority; - if (!param || param_len < 2) - return False; + if (!param || param_len < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } priority = SVAL(param,0); DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority)); if (wait_rpc_pipe_hnd_state(p, priority)) { /* now send the reply */ - send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False); - return True; + send_trans_reply_new(req, NULL, 0, NULL, 0, False); + return; } - return False; + api_no_reply(req); } @@ -236,26 +235,25 @@ static BOOL api_WNPHS(const char *inbuf, SetNamedPipeHandleState ****************************************************************************/ -static BOOL api_SNPHS(const char *inbuf, - char *outbuf, - smb_np_struct *p, - char *param, - int param_len) +static void api_SNPHS(struct smb_request *req, smb_np_struct *p, + char *param, int param_len) { uint16 id; - if (!param || param_len < 2) - return False; + if (!param || param_len < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } id = SVAL(param,0); DEBUG(4,("SetNamedPipeHandleState to code %x\n", id)); if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False); - return True; + send_trans_reply_new(req, NULL, 0, NULL, 0, False); + return; } - return False; + api_no_reply(req); } @@ -363,46 +361,14 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, reply_post_legacy(req, -1); break; } - case TRANSACT_WAITNAMEDPIPEHANDLESTATE: { - - char *inbuf, *outbuf; - int size, buflength; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &buflength)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - + case TRANSACT_WAITNAMEDPIPEHANDLESTATE: /* Wait Named Pipe Handle state */ - if (!api_WNPHS(inbuf, outbuf, p, params, tpscnt)) { - api_no_reply(req); - return; - } - - reply_post_legacy(req, -1); + api_WNPHS(req, p, params, tpscnt); break; - } - case TRANSACT_SETNAMEDPIPEHANDLESTATE: { - - char *inbuf, *outbuf; - int size, buflength; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &buflength)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - + case TRANSACT_SETNAMEDPIPEHANDLESTATE: /* Set Named Pipe Handle state */ - if (!api_SNPHS(inbuf, outbuf, p, params, tpscnt)) { - api_no_reply(req); - return; - } - - reply_post_legacy(req, -1); + api_SNPHS(req, p, params, tpscnt); break; - } default: reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; -- cgit From 43a77ab149f154961113f05296815af50c0274da Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 10:57:04 +0000 Subject: r24242: Remove reply_prep_legacy from api_rpc_trans_reply (This used to be commit 160f65946af9b3e1609b0efb211edc81514fb36f) --- source3/smbd/ipc.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index bea4f77450..3b26ded71f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -180,9 +180,7 @@ void send_trans_reply_new(struct smb_request *req, Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -static BOOL api_rpc_trans_reply(const char *inbuf, - char *outbuf, - smb_np_struct *p) +static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p) { BOOL is_data_outstanding; char *rdata = (char *)SMB_MALLOC(p->max_trans_reply); @@ -190,19 +188,21 @@ static BOOL api_rpc_trans_reply(const char *inbuf, if(rdata == NULL) { DEBUG(0,("api_rpc_trans_reply: malloc fail.\n")); - return False; + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } if((data_len = read_from_pipe( p, rdata, p->max_trans_reply, &is_data_outstanding)) < 0) { SAFE_FREE(rdata); - return False; + api_no_reply(req); + return; } - send_trans_reply(inbuf, outbuf, NULL, 0, rdata, data_len, is_data_outstanding); - + send_trans_reply_new(req, NULL, 0, rdata, data_len, + is_data_outstanding); SAFE_FREE(rdata); - return True; + return; } /**************************************************************************** @@ -338,29 +338,15 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply)); switch (subcommand) { - case TRANSACT_DCERPCCMD: { - - char *inbuf, *outbuf; - int size, buflength; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &buflength)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - + case TRANSACT_DCERPCCMD: /* dce/rpc command */ reply = write_to_pipe(p, data, tdscnt); - if (reply) - reply = api_rpc_trans_reply(inbuf, outbuf, p); - if (!reply) { api_no_reply(req); return; } - reply_post_legacy(req, -1); + api_rpc_trans_reply(req, p); break; - } case TRANSACT_WAITNAMEDPIPEHANDLESTATE: /* Wait Named Pipe Handle state */ api_WNPHS(req, p, params, tpscnt); -- cgit From d274724ebbbce15abe2c5cd73fca94453dfc2a84 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 11:19:24 +0000 Subject: r24243: Remove reply_prep_legacy from api_reply (This used to be commit b01664b43b0bd94bb59dec57480d2be954a7298a) --- source3/smbd/ipc.c | 18 ++++-------------- source3/smbd/lanman.c | 38 ++++++++++++++++---------------------- 2 files changed, 20 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 3b26ded71f..f865af2fc7 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -375,20 +375,10 @@ static void named_pipe(connection_struct *conn, uint16 vuid, DEBUG(3,("named pipe command on <%s> name\n", name)); if (strequal(name,"LANMAN")) { - char *inbuf, *outbuf; - int size, bufsize; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - reply_post_legacy( - req, - api_reply(conn, vuid, inbuf, outbuf, - data, params, - tdscnt, tpscnt, - mdrcnt, mprcnt)); + api_reply(conn, vuid, req, + data, params, + tdscnt, tpscnt, + mdrcnt, mprcnt); return; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f7a4f9b0bd..3673998f79 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4366,16 +4366,11 @@ static const struct { Handle remote api calls. ****************************************************************************/ -int api_reply(connection_struct *conn, - uint16 vuid, - const char *inbuf, - char *outbuf, - char *data, - char *params, - int tdscnt, - int tpscnt, - int mdrcnt, - int mprcnt) +void api_reply(connection_struct *conn, uint16 vuid, + struct smb_request *req, + char *data, char *params, + int tdscnt, int tpscnt, + int mdrcnt, int mprcnt) { int api_command; char *rdata = NULL; @@ -4389,11 +4384,13 @@ int api_reply(connection_struct *conn, if (!params) { DEBUG(0,("ERROR: NULL params in api_reply()\n")); - return 0; + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (tpscnt < 2) { - return 0; + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } api_command = SVAL(params,0); /* Is there a string at position params+2 ? */ @@ -4426,7 +4423,8 @@ int api_reply(connection_struct *conn, user_struct *user = get_valid_user_struct(vuid); if (!user || user->guest) { - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; } } @@ -4444,7 +4442,8 @@ int api_reply(connection_struct *conn, DEBUG(0,("api_reply: malloc fail !\n")); SAFE_FREE(rdata); SAFE_FREE(rparam); - return -1; + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } reply = api_commands[i].fn(conn, @@ -4468,16 +4467,11 @@ int api_reply(connection_struct *conn, /* If api_Unsupported returns false we can't return anything. */ if (reply) { - send_trans_reply(inbuf, - outbuf, - rparam, - rparam_len, - rdata, - rdata_len, - False); + send_trans_reply_new(req, rparam, rparam_len, + rdata, rdata_len, False); } SAFE_FREE(rdata); SAFE_FREE(rparam); - return -1; + return; } -- cgit From b0ed26faf088d921e876f3a850c3e146514cc7e8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 5 Aug 2007 11:34:57 +0000 Subject: r24244: Complete the conversion of reply_trans[s] Remove reply_prep/post_legacy from send_trans_replies (This used to be commit c08366f840ead5aba7199cf0b058587055b4d98e) --- source3/smbd/ipc.c | 125 +++++++++++++++++++++++++------------------------- source3/smbd/lanman.c | 4 +- 2 files changed, 65 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f865af2fc7..b13c18a590 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -46,7 +46,7 @@ static void copy_trans_params_and_data(char *outbuf, int align, char *rparam, int param_offset, int param_len, char *rdata, int data_offset, int data_len) { - char *copy_into = smb_buf(outbuf)+1; + char *copy_into = smb_buf(outbuf); if(param_len < 0) param_len = 0; @@ -58,6 +58,10 @@ static void copy_trans_params_and_data(char *outbuf, int align, param_offset, param_offset + param_len, data_offset , data_offset + data_len)); + *copy_into = '\0'; + + copy_into += 1; + if (param_len) memcpy(copy_into, &rparam[param_offset], param_len); @@ -71,13 +75,10 @@ static void copy_trans_params_and_data(char *outbuf, int align, Send a trans reply. ****************************************************************************/ -void send_trans_reply(const char *inbuf, - char *outbuf, - char *rparam, - int rparam_len, - char *rdata, - int rdata_len, - BOOL buffer_too_large) +void send_trans_reply(struct smb_request *req, + char *rparam, int rparam_len, + char *rdata, int rdata_len, + BOOL buffer_too_large) { int this_ldata,this_lparam; int tot_data_sent = 0; @@ -95,30 +96,38 @@ void send_trans_reply(const char *inbuf, align = ((this_lparam)%4); - if (buffer_too_large) { - ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata); - } - - set_message(inbuf,outbuf,10,1+align+this_ldata+this_lparam,True); + reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); - copy_trans_params_and_data(outbuf, align, + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,0); - - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) + SSVAL(req->outbuf,smb_vwv0,lparam); + SSVAL(req->outbuf,smb_vwv1,ldata); + SSVAL(req->outbuf,smb_vwv3,this_lparam); + SSVAL(req->outbuf,smb_vwv4,smb_offset(smb_buf(req->outbuf)+1, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv5,0); + SSVAL(req->outbuf,smb_vwv6,this_ldata); + SSVAL(req->outbuf,smb_vwv7,smb_offset(smb_buf(req->outbuf)+1+ + this_lparam+align, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv8,0); + SSVAL(req->outbuf,smb_vwv9,0); + + if (buffer_too_large) { + error_packet_set((char *)req->outbuf, + ERRDOS, ERRmoredata, + STATUS_BUFFER_OVERFLOW, + __LINE__, __FILE__); + } + + show_msg((char *)req->outbuf); + if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) exit_server_cleanly("send_trans_reply: send_smb failed."); + TALLOC_FREE(req->outbuf); + tot_data_sent = this_ldata; tot_param_sent = this_lparam; @@ -135,47 +144,40 @@ void send_trans_reply(const char *inbuf, align = (this_lparam%4); - set_message(inbuf,outbuf,10,1+this_ldata+this_lparam+align,False); + reply_outbuf(req, 10, 1+this_ldata+this_lparam+align); - copy_trans_params_and_data(outbuf, align, + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,tot_param_sent); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,tot_data_sent); - SSVAL(outbuf,smb_vwv9,0); - - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) + SSVAL(req->outbuf,smb_vwv3,this_lparam); + SSVAL(req->outbuf,smb_vwv4,smb_offset(smb_buf(req->outbuf)+1, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv5,tot_param_sent); + SSVAL(req->outbuf,smb_vwv6,this_ldata); + SSVAL(req->outbuf,smb_vwv7,smb_offset(smb_buf(req->outbuf)+1+ + this_lparam+align, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv8,tot_data_sent); + SSVAL(req->outbuf,smb_vwv9,0); + + if (buffer_too_large) { + error_packet_set((char *)req->outbuf, + ERRDOS, ERRmoredata, + STATUS_BUFFER_OVERFLOW, + __LINE__, __FILE__); + } + + show_msg((char *)req->outbuf); + if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) exit_server_cleanly("send_trans_reply: send_smb failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; + TALLOC_FREE(req->outbuf); } } -void send_trans_reply_new(struct smb_request *req, - char *rparam, int rparam_len, - char *rdata, int rdata_len, - BOOL buffer_too_large) -{ - char *inbuf, *outbuf; - int size, buflength; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &buflength)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - send_trans_reply(inbuf, outbuf, rparam, rparam_len, - rdata, rdata_len, buffer_too_large); - reply_post_legacy(req, -1); -} - /**************************************************************************** Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ @@ -199,8 +201,7 @@ static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p) return; } - send_trans_reply_new(req, NULL, 0, rdata, data_len, - is_data_outstanding); + send_trans_reply(req, NULL, 0, rdata, data_len, is_data_outstanding); SAFE_FREE(rdata); return; } @@ -224,7 +225,7 @@ static void api_WNPHS(struct smb_request *req, smb_np_struct *p, if (wait_rpc_pipe_hnd_state(p, priority)) { /* now send the reply */ - send_trans_reply_new(req, NULL, 0, NULL, 0, False); + send_trans_reply(req, NULL, 0, NULL, 0, False); return; } api_no_reply(req); @@ -250,7 +251,7 @@ static void api_SNPHS(struct smb_request *req, smb_np_struct *p, if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply_new(req, NULL, 0, NULL, 0, False); + send_trans_reply(req, NULL, 0, NULL, 0, False); return; } api_no_reply(req); @@ -272,7 +273,7 @@ static void api_no_reply(struct smb_request *req) DEBUG(3,("Unsupported API fd command\n")); /* now send the reply */ - send_trans_reply_new(req, rparam, 4, NULL, 0, False); + send_trans_reply(req, rparam, 4, NULL, 0, False); return; } @@ -314,7 +315,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, /* Win9x does this call with a unicode pipe name, not a pnum. */ /* Just return success for now... */ DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n")); - send_trans_reply_new(req, NULL, 0, NULL, 0, False); + send_trans_reply(req, NULL, 0, NULL, 0, False); return; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3673998f79..1d6369c18b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4467,8 +4467,8 @@ void api_reply(connection_struct *conn, uint16 vuid, /* If api_Unsupported returns false we can't return anything. */ if (reply) { - send_trans_reply_new(req, rparam, rparam_len, - rdata, rdata_len, False); + send_trans_reply(req, rparam, rparam_len, + rdata, rdata_len, False); } SAFE_FREE(rdata); -- cgit From d75a38ae264ab3bbe73414576b37ccdafbbb9975 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Aug 2007 18:54:26 +0000 Subject: r24253: From Jan Martin . ---------------------------------------------------------- In rare cases, Samba 3.0.25b shows directory contents at the wrong position in the file tree when displaying a subdirectory of a DFS link. The problem occurs whenever Windows XP asks for a DFS referral for a subdirectory of a DFS link with a trailing backslash. Windows does not do this very often, but we saw it several times per day on our central DFS server. smbd/msdfs.c, dfs_path_lookup() does the following with the requested path: - in line 390, the local copy 'localpath' is 'unix_convert'ed; the trailing backslash is removed inside unix_convert - in lines 417-20, 'dfspath' (another copy of the requested path) is mangled another way without removing trailing backslashes That's why the following loop (lines 435-461) that is meant to synchronously cut off the last path component from both strings until it comes to a DFS link, does not handle both strings the same. When the original path ended with a backslash, 'canon_dfspath' has always one component more than 'localpath', so that *consumedcntp gets too big in line 446. This value is reported to the client. ---------------------------------------------------------- Bug #4860. Jeremy. (This used to be commit 42d1c6713a56197ca8dfebf74eb0d483102148f7) --- source3/smbd/msdfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a89f4ceffc..16f3cd4370 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -421,6 +421,14 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, string_replace(canon_dfspath, '\\', '/'); } + /* + * localpath comes out of unix_convert, so it has + * no trailing backslash. Make sure that canon_dfspath hasn't either. + * Fix for bug #4860 from Jan Martin . + */ + + trim_char(canon_dfspath,0,'/'); + /* * Redirect if any component in the path is a link. * We do this by walking backwards through the -- cgit From d18b7b1223a3f9f7584e6d0913fa588a2bc5a1f3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Aug 2007 21:03:03 +0000 Subject: r24254: Fix a segfault in r24102 The really pure bugfix would have replaced pparam by *pparam, but we pulled the fid anyway. Metze, in line 2421 the FSP_BELONGS_CONN is commented out, is that intended? The FSCTL_CREATE_OR_GET_OBJECT_ID ioctl did not have it. Volker (This used to be commit 2c1376225b98a9325dfc2d00bad1722e63cf522b) --- source3/smbd/nttrans.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 487d523670..0008747473 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2415,7 +2415,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", function, fidnum, isFSctl, compfilter)); - fsp=file_fsp(SVAL(ppsetup, 4)); + fsp=file_fsp(fidnum); /* this check is done in each implemented function case for now because I don't want to break anything... --metze FSP_BELONGS_CONN(fsp,conn);*/ @@ -2441,6 +2441,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum)); + FSP_BELONGS_CONN(fsp, conn); + data_count = 64; pdata = nttrans_realloc(ppdata, data_count); if (pdata == NULL) { -- cgit From 456305325ce0d5d7562e0596ead983009de76143 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Aug 2007 13:10:21 +0000 Subject: r24268: Fix two crashes for spoolss strlcpy does not like a NULL source. Fix a use-after-free. (This used to be commit c2a214501788b5f0b6f555bd01ed310d331d07fa) --- source3/smbd/connection.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index da8bd89e7a..4b807f7b90 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -206,7 +206,7 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) doreg ? "adding" : "removing", (unsigned int)msg_flags )); - if (!(rec = connections_fetch_entry(NULL, NULL, NULL))) { + if (!(rec = connections_fetch_entry(NULL, NULL, ""))) { DEBUG(0, ("connections_fetch_entry failed\n")); return False; } @@ -225,17 +225,18 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) status = rec->store(rec, rec->value, TDB_REPLACE); - TALLOC_FREE(rec); - if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("register_message_flags: tdb_store failed: %s.\n", nt_errstr(status))); + TALLOC_FREE(rec); return False; } DEBUG(10,("register_message_flags: new flags 0x%x\n", (unsigned int)pcrec->bcast_msg_flags )); + TALLOC_FREE(rec); + return True; } -- cgit From bb9664302b354c46041f58549d5adf0a241eb6c1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Aug 2007 13:12:46 +0000 Subject: r24269: Check wct in reply_write_and_X (This used to be commit 1297fac11778cb910d1bcd12b6d9d3a6269972db) --- source3/smbd/reply.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2b54c636a5..8007a769ec 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3273,18 +3273,31 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2)); - SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); - size_t numtowrite = SVAL(inbuf,smb_vwv10); - BOOL write_through = BITSETW(inbuf+smb_vwv7,0); - ssize_t nwritten = -1; - unsigned int smb_doff = SVAL(inbuf,smb_vwv11); - unsigned int smblen = smb_len(inbuf); + files_struct *fsp; + SMB_OFF_T startpos; + size_t numtowrite; + BOOL write_through; + ssize_t nwritten; + unsigned int smb_doff; + unsigned int smblen; char *data; - BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); + BOOL large_writeX; NTSTATUS status; + START_PROFILE(SMBwriteX); + if ((CVAL(inbuf, smb_wct) != 12) && (CVAL(inbuf, smb_wct) != 14)) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + fsp = file_fsp(SVAL(inbuf,smb_vwv2)); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); + numtowrite = SVAL(inbuf,smb_vwv10); + write_through = BITSETW(inbuf+smb_vwv7,0); + smb_doff = SVAL(inbuf,smb_vwv11); + smblen = smb_len(inbuf); + large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); + /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { END_PROFILE(SMBwriteX); -- cgit From 1f67efab7c40ad440d6919d71bdee29d7bf7d175 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Aug 2007 13:14:49 +0000 Subject: r24270: Fix some END_PROFILE(SMBwriteX) (This used to be commit 36f2347561ab06b5d8175ad0a9c4da2817e759f9) --- source3/smbd/reply.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8007a769ec..d7b30fd72d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3287,6 +3287,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng START_PROFILE(SMBwriteX); if ((CVAL(inbuf, smb_wct) != 12) && (CVAL(inbuf, smb_wct) != 14)) { + END_PROFILE(SMBwriteX); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -3306,6 +3307,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_FSP(fsp,conn); if (!CHECK_WRITE(fsp)) { + END_PROFILE(SMBwriteX); return(ERROR_DOS(ERRDOS,ERRbadaccess)); } @@ -3388,9 +3390,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng status = sync_file(conn, fsp, write_through); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBwriteX); DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); + END_PROFILE(SMBwriteX); return ERROR_NT(status); } -- cgit From b0dc209c190b90cef64d5fdea0623567e42c5a85 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Aug 2007 13:43:02 +0000 Subject: r24271: Push reply_prep_legacy into reply_write_and_X (This used to be commit 607e7d2447bf19eea872a3a4d1ad499a53f0a935) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 62 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d7bde0043a..1b8e6521f7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -735,7 +735,7 @@ static const struct smb_message_struct { /* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER}, /* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC }, /* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC }, -/* 0x2f */ { "SMBwriteX",reply_write_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x2f */ { "SMBwriteX",NULL,reply_write_and_X,AS_USER | CAN_IPC }, /* 0x30 */ { NULL, NULL, NULL, 0 }, /* 0x31 */ { NULL, NULL, NULL, 0 }, /* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d7b30fd72d..30b90a6459 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3271,7 +3271,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d Reply to a write and X. ****************************************************************************/ -int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +void reply_write_and_X(connection_struct *conn, struct smb_request *req) { files_struct *fsp; SMB_OFF_T startpos; @@ -3284,11 +3284,21 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng BOOL large_writeX; NTSTATUS status; + char *inbuf, *outbuf; + int length, bufsize; + START_PROFILE(SMBwriteX); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBwriteX); + return; + } + if ((CVAL(inbuf, smb_wct) != 12) && (CVAL(inbuf, smb_wct) != 14)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBwriteX); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } fsp = file_fsp(SVAL(inbuf,smb_vwv2)); @@ -3301,17 +3311,25 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { + reply_post_legacy( + req, + reply_pipe_write_and_X(inbuf,outbuf,length,bufsize)); END_PROFILE(SMBwriteX); - return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize); + return; + } + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBwriteX); + return; } - CHECK_FSP(fsp,conn); if (!CHECK_WRITE(fsp)) { + reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBwriteX); - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + return; } - set_message(inbuf,outbuf,6,0,True); + set_message(inbuf, outbuf, 6, 0, True); /* Deal with possible LARGE_WRITEX */ if (large_writeX) { @@ -3319,8 +3337,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng } if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { + reply_doserror(req, ERRDOS, ERRbadmem); END_PROFILE(SMBwriteX); - return ERROR_DOS(ERRDOS,ERRbadmem); + return; } data = smb_base(inbuf) + smb_doff; @@ -3339,18 +3358,23 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng */ if(IVAL(inbuf,smb_vwv12) != 0) { - DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \ -64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) )); + DEBUG(0,("reply_write_and_X - large offset (%x << 32) " + "used and we don't support 64 bit offsets.\n", + (unsigned int)IVAL(inbuf,smb_vwv12) )); + reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBwriteX); - return ERROR_DOS(ERRDOS,ERRbadaccess); + return; } #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid), + (SMB_BIG_UINT)numtowrite, + (SMB_BIG_UINT)startpos, WRITE_LOCK)) { + reply_doserror(req, ERRDOS, ERRlock); END_PROFILE(SMBwriteX); - return ERROR_DOS(ERRDOS,ERRlock); + return; } /* X/Open SMB protocol says that, unlike SMBwrite @@ -3364,16 +3388,18 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize, fsp,data,startpos,numtowrite)) { + reply_post_legacy(req, -1); END_PROFILE(SMBwriteX); - return -1; + return; } nwritten = write_file(fsp,data,startpos,numtowrite); } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBwriteX); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } SSVAL(outbuf,smb_vwv2,nwritten); @@ -3392,12 +3418,16 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); + reply_nterror(req, status); END_PROFILE(SMBwriteX); - return ERROR_NT(status); + return; } + reply_post_legacy(req, smb_len(req->outbuf)); + END_PROFILE(SMBwriteX); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); + return; } /**************************************************************************** -- cgit From 3e8fc031c8c28880657423de632172b2717f07a7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 7 Aug 2007 14:06:27 +0000 Subject: r24272: try to fix the build on irix... metze (This used to be commit dd7e94258b0fc0157d890d71f05c6fe16b6a2ea9) --- source3/smbd/oplock_irix.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 6f2dceeddc..75f807f86b 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -96,6 +96,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) extern int smb_read_error; oplock_stat_t os; char dummy; + struct file_id fileid; files_struct *fsp; /* Ensure we only get one call per select fd set. */ @@ -137,11 +138,14 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) /* * We only have device and inode info here - we have to guess that this * is the first fsp open with this dev,ino pair. + * + * NOTE: this doesn't work if any VFS modules overloads + * the file_id_create() hook! */ - if ((fsp = file_find_di_first( - file_id_create((SMB_DEV_T)os.os_dev, - (SMB_INO_T)os.os_ino))) == NULL) { + fileid = file_id_create_dev((SMB_DEV_T)os.os_dev, + (SMB_INO_T)os.os_ino); + if ((fsp = file_find_di_first(fileid)) == NULL) { DEBUG(0,("irix_oplock_receive_message: unable to find open " "file with dev = %x, inode = %.0f\n", (unsigned int)os.os_dev, (double)os.os_ino )); -- cgit From a6810cb9a303d31dfedfb4bdc52f4d4df7e4eb90 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Aug 2007 18:40:26 +0000 Subject: r24278: Push down reply_prep_legacy in reply_write_and_X Remove the need for reply_prep_legacy for reply_pipe_write_and_X (This used to be commit de143d5fa61aa487613dda729a43dc3d59a72899) --- source3/smbd/pipes.c | 45 ++++++++++++++++++++++++++------------------- source3/smbd/reply.c | 47 +++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 24e0f47001..cf12b4be4d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -183,26 +183,29 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) wrinkles to handle pipes. ****************************************************************************/ -int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) +void reply_pipe_write_and_X(struct smb_request *req) { - smb_np_struct *p = get_rpc_pipe_p(SVAL(inbuf,smb_vwv2)); - uint16 vuid = SVAL(inbuf,smb_uid); - size_t numtowrite = SVAL(inbuf,smb_vwv10); + smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2)); + size_t numtowrite = SVAL(req->inbuf,smb_vwv10); int nwritten = -1; - int smb_doff = SVAL(inbuf, smb_vwv11); - BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == - (PIPE_START_MESSAGE|PIPE_RAW_MODE)); + int smb_doff = SVAL(req->inbuf, smb_vwv11); + BOOL pipe_start_message_raw = + ((SVAL(req->inbuf, smb_vwv7) + & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) + == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); char *data; if (!p) { - return(ERROR_DOS(ERRDOS,ERRbadfid)); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } - if (p->vuid != vuid) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + if (p->vuid != req->vuid) { + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } - data = smb_base(inbuf) + smb_doff; + data = smb_base(req->inbuf) + smb_doff; if (numtowrite == 0) { nwritten = 0; @@ -214,9 +217,12 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) * them (we don't trust the client). JRA. */ if(numtowrite < 2) { - DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n", - (unsigned int)numtowrite )); - return (UNIXERROR(ERRDOS,ERRnoaccess)); + DEBUG(0,("reply_pipe_write_and_X: start of " + "message set and not enough data " + "sent.(%u)\n", + (unsigned int)numtowrite )); + reply_unixerror(req, ERRDOS, ERRnoaccess); + return; } data += 2; @@ -226,17 +232,18 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { - return (UNIXERROR(ERRDOS,ERRnoaccess)); + reply_unixerror(req, ERRDOS,ERRnoaccess); + return; } - - set_message(inbuf,outbuf,6,0,True); + + reply_outbuf(req, 6, 0); nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); - SSVAL(outbuf,smb_vwv2,nwritten); + SSVAL(req->outbuf,smb_vwv2,nwritten); DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 30b90a6459..e4fbc839ff 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3289,35 +3289,39 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBwriteX); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); + if ((req->wct != 12) && (req->wct != 14)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBwriteX); return; } - if ((CVAL(inbuf, smb_wct) != 12) && (CVAL(inbuf, smb_wct) != 14)) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + numtowrite = SVAL(req->inbuf,smb_vwv10); + smb_doff = SVAL(req->inbuf,smb_vwv11); + smblen = smb_len(req->inbuf); + large_writeX = ((req->wct == 14) && (smblen > 0xFFFF)); + + /* Deal with possible LARGE_WRITEX */ + if (large_writeX) { + numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16); + } + + if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { + reply_doserror(req, ERRDOS, ERRbadmem); END_PROFILE(SMBwriteX); return; } - fsp = file_fsp(SVAL(inbuf,smb_vwv2)); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); - numtowrite = SVAL(inbuf,smb_vwv10); - write_through = BITSETW(inbuf+smb_vwv7,0); - smb_doff = SVAL(inbuf,smb_vwv11); - smblen = smb_len(inbuf); - large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); - /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { - reply_post_legacy( - req, - reply_pipe_write_and_X(inbuf,outbuf,length,bufsize)); + reply_pipe_write_and_X(req); END_PROFILE(SMBwriteX); return; } + fsp = file_fsp(SVAL(req->inbuf,smb_vwv2)); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); + write_through = BITSETW(req->inbuf+smb_vwv7,0); + if (!check_fsp(conn, req, fsp, ¤t_user)) { END_PROFILE(SMBwriteX); return; @@ -3329,19 +3333,14 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) return; } - set_message(inbuf, outbuf, 6, 0, True); - - /* Deal with possible LARGE_WRITEX */ - if (large_writeX) { - numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); - } - - if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { - reply_doserror(req, ERRDOS, ERRbadmem); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBwriteX); return; } + set_message(inbuf, outbuf, 6, 0, True); + data = smb_base(inbuf) + smb_doff; if(CVAL(inbuf,smb_wct) == 14) { -- cgit From 12d94f77f919851989da8dbcc12eb632258a2084 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Aug 2007 19:05:30 +0000 Subject: r24279: Remove reply_prep_legacy from reply_write_and_X (This used to be commit f18b7a9a282ebb5c31a89a601798f9a0db51867e) --- source3/smbd/aio.c | 36 ++++++++++++++++++------------------ source3/smbd/reply.c | 37 ++++++++++++------------------------- 2 files changed, 30 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index f4c4aaec41..0ba857e2e5 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -284,11 +284,10 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, *****************************************************************************/ BOOL schedule_aio_write_and_X(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int len_outbuf, - files_struct *fsp, char *data, - SMB_OFF_T startpos, - size_t numtowrite) + struct smb_request *req, + files_struct *fsp, char *data, + SMB_OFF_T startpos, + size_t numtowrite) { struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; @@ -306,7 +305,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, /* Only do this on non-chained and non-chaining reads not using the * write cache. */ - if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) + if (chain_size !=0 || (CVAL(req->inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } @@ -320,23 +319,25 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, "(mid = %u)\n", fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, - (unsigned int)SVAL(inbuf,smb_mid) )); + (unsigned int)req->mid )); return False; } - inbufsize = smb_len(inbuf) + 4; - outbufsize = smb_len(outbuf) + 4; + inbufsize = smb_len(req->inbuf) + 4; + reply_outbuf(req, 6, 0); + outbufsize = smb_len(req->outbuf) + 4; if (!(aio_ex = create_aio_ex_write(fsp, inbufsize, outbufsize, - SVAL(inbuf,smb_mid)))) { + req->mid))) { DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n")); return False; } /* Copy the SMB header already setup in outbuf. */ - memcpy(aio_ex->inbuf, inbuf, inbufsize); + memcpy(aio_ex->inbuf, req->inbuf, inbufsize); /* Copy the SMB header already setup in outbuf. */ - memcpy(aio_ex->outbuf, outbuf, outbufsize); + memcpy(aio_ex->outbuf, req->outbuf, outbufsize); + TALLOC_FREE(req->outbuf); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -344,7 +345,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, /* Now set up the aio record for the write call. */ a->aio_fildes = fsp->fh->fd; - a->aio_buf = aio_ex->inbuf + (PTR_DIFF(data, inbuf)); + a->aio_buf = aio_ex->inbuf + (PTR_DIFF(data, req->inbuf)); a->aio_nbytes = numtowrite; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; @@ -633,11 +634,10 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, } BOOL schedule_aio_write_and_X(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int len_outbuf, - files_struct *fsp, char *data, - SMB_OFF_T startpos, - size_t numtowrite) + struct smb_request *req, + files_struct *fsp, char *data, + SMB_OFF_T startpos, + size_t numtowrite) { return False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e4fbc839ff..17bcab12fd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3284,9 +3284,6 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) BOOL large_writeX; NTSTATUS status; - char *inbuf, *outbuf; - int length, bufsize; - START_PROFILE(SMBwriteX); if ((req->wct != 12) && (req->wct != 14)) { @@ -3333,22 +3330,14 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) return; } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBwriteX); - return; - } - - set_message(inbuf, outbuf, 6, 0, True); + data = smb_base(req->inbuf) + smb_doff; - data = smb_base(inbuf) + smb_doff; - - if(CVAL(inbuf,smb_wct) == 14) { + if(req->wct == 14) { #ifdef LARGE_SMB_OFF_T /* * This is a large offset (64 bit) write. */ - startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); + startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32); #else /* !LARGE_SMB_OFF_T */ @@ -3356,7 +3345,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) * Ensure we haven't been sent a >32 bit offset. */ - if(IVAL(inbuf,smb_vwv12) != 0) { + if(IVAL(req->inbuf,smb_vwv12) != 0) { DEBUG(0,("reply_write_and_X - large offset (%x << 32) " "used and we don't support 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) )); @@ -3368,7 +3357,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid), + if (is_locked(fsp,(uint32)req->smbpid, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, WRITE_LOCK)) { reply_doserror(req, ERRDOS, ERRlock); @@ -3385,14 +3374,14 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) nwritten = 0; } else { - if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize, - fsp,data,startpos,numtowrite)) { - reply_post_legacy(req, -1); + if (schedule_aio_write_and_X(conn, req, fsp, data, startpos, + numtowrite)) { END_PROFILE(SMBwriteX); return; } nwritten = write_file(fsp,data,startpos,numtowrite); + reply_outbuf(req, 6, 0); } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { @@ -3401,13 +3390,13 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) return; } - SSVAL(outbuf,smb_vwv2,nwritten); + SSVAL(req->outbuf,smb_vwv2,nwritten); if (large_writeX) - SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); + SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1); if (nwritten < (ssize_t)numtowrite) { - SCVAL(outbuf,smb_rcls,ERRHRD); - SSVAL(outbuf,smb_err,ERRdiskfull); + SCVAL(req->outbuf,smb_rcls,ERRHRD); + SSVAL(req->outbuf,smb_err,ERRdiskfull); } DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", @@ -3422,8 +3411,6 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) return; } - reply_post_legacy(req, smb_len(req->outbuf)); - END_PROFILE(SMBwriteX); chain_reply_new(req); return; -- cgit From 9239b8e8d3f490ee1452820c61742f455d67e095 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 09:53:42 +0000 Subject: r24306: the check_fsp() function has an explicit user argument so use it... metze (This used to be commit 4154bee0d91dd2ace9a7a627418f652d0d11b959) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 17bcab12fd..c02bbc8719 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -295,7 +295,7 @@ BOOL check_fsp(connection_struct *conn, struct smb_request *req, reply_nterror(req, NT_STATUS_INVALID_HANDLE); return False; } - if (((conn) != (fsp)->conn) || current_user.vuid != (fsp)->vuid) { + if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) { reply_nterror(req, NT_STATUS_INVALID_HANDLE); return False; } -- cgit From f210f7c4320bb253944193f2a96d4f6c0169214f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 09:56:13 +0000 Subject: r24307: fill in choise with value -1 on error as we've done before revision 24002 metze (This used to be commit 2961a35e90aae44c8560b1f4b56bfa6343c837d7) --- source3/smbd/negprot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 06b17a9a24..a28b2f3d4c 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -674,6 +674,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { DEBUG(0,("No protocol supported !\n")); + SSVAL(outbuf,smb_vwv0,choice); } DEBUG( 5, ( "negprot index=%d\n", choice ) ); -- cgit From aece6db7148cad4876c90bb9da8653c780285abb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 09:57:30 +0000 Subject: r24308: this needs a better fix that compiles... metze (This used to be commit 1a177eb08d4022c1ef7b5400ffdf426bcb9b97ff) --- source3/smbd/negprot.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index a28b2f3d4c..06b17a9a24 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -674,7 +674,6 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { DEBUG(0,("No protocol supported !\n")); - SSVAL(outbuf,smb_vwv0,choice); } DEBUG( 5, ( "negprot index=%d\n", choice ) ); -- cgit From 66294f9db508038a333b6c73fa5181fec5773530 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 10:11:40 +0000 Subject: r24309: if no protocol matches, just return choise 0xffff as we've done before revision 24002 metze (This used to be commit 6014ecbbfd50bc8f4f351dec1f9dd35c3fe62456) --- source3/smbd/negprot.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 06b17a9a24..935d25fab3 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -674,6 +674,8 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { DEBUG(0,("No protocol supported !\n")); + reply_outbuf(req, 1, 0); + SSVAL(req->outbuf, smb_vwv0, choice); } DEBUG( 5, ( "negprot index=%d\n", choice ) ); -- cgit From c25f22562e9e7cfdf193a01f10fe571b748a6d46 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 10:15:25 +0000 Subject: r24310: we should not call END_PROFILE(SMBntcreateX); twice... metze (This used to be commit 7a98e09f2e4d5eff074e2d71dd1ff2f019a4547a) --- source3/smbd/nttrans.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 0008747473..61f21406b6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -729,7 +729,6 @@ void reply_ntcreate_and_X(connection_struct *conn, */ status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBntcreateX); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); -- cgit From a5f412f305ea2bdb0ee0efd5a38385525d4671c8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 10:28:09 +0000 Subject: r24311: add a reply_force_nterror() macro metze (This used to be commit b9ae00f4980c305f2f7334b139f9bc72fd9afbd6) --- source3/smbd/error.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 023e1b7dcc..dd9ff85640 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -140,6 +140,14 @@ void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus, error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file); } +void reply_force_nt_error(struct smb_request *req, NTSTATUS ntstatus, + int line, const char *file) +{ + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + error_packet_set((char *)req->outbuf, -1, -1, ntstatus, line, file); +} + void reply_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode, int line, const char *file) { -- cgit From 5cc4dbd44930bdf3f5ec8a177ea94f6b68fdb1c9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 10:31:28 +0000 Subject: r24312: revision 24091 removed the 'FORCE'... metze (This used to be commit 34d821daf0af6ef1e51dfd5cd99741f426d6956e) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 61f21406b6..1d13036920 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -898,7 +898,7 @@ void reply_ntcreate_and_X(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { TALLOC_FREE(case_state); - reply_nterror(req, NT_STATUS_FILE_IS_A_DIRECTORY); + reply_force_nterror(req, NT_STATUS_FILE_IS_A_DIRECTORY); END_PROFILE(SMBntcreateX); return; } -- cgit From 3c5811c272db98d037892d26cf5eb22275c1e6e4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Aug 2007 14:01:14 +0000 Subject: r24314: Attempt to fix bug 4868 (This used to be commit 0ced8fcfe124f99159061143f29775aacd6e1c8f) --- source3/smbd/notify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d003cfa88f..6c77f4c270 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -160,6 +160,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param, if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); + notify_buf->num_changes = 0; return; } -- cgit From c898c519843e9bca4104e1414d9f5e0dbad77950 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Aug 2007 20:53:27 +0000 Subject: r24318: Print a prominent warning when reply_prep_legacy is called This is a temporary function anyway (This used to be commit 9269e3d5882e97d1c884df6511fa6d63a7b1cfcd) --- source3/smbd/process.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1b8e6521f7..d0531bdfd9 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -82,6 +82,8 @@ BOOL reply_prep_legacy(struct smb_request *req, + SAFETY_MARGIN); char *inbuf, *outbuf; + DEBUG(1, ("reply_prep_legacy called\n")); + if (!(inbuf = TALLOC_ARRAY(req, char, bufsize))) { DEBUG(0, ("Could not allocate legacy inbuf\n")); return False; -- cgit From d465b468c1bd1e43fc1bf1622415ed98dafa6627 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Aug 2007 21:33:58 +0000 Subject: r24319: Check wct in reply_read_and_X (This used to be commit 9ddacdfa131c4a4a852b3d30db1ee22d1852d0c2) --- source3/smbd/reply.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c02bbc8719..3e35c0064b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2860,10 +2860,10 @@ normal_read: int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2)); - SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); + files_struct *fsp; + SMB_OFF_T startpos; ssize_t nread = -1; - size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); + size_t smb_maxcnt; BOOL big_readX = False; #if 0 size_t smb_mincnt = SVAL(inbuf,smb_vwv6); @@ -2871,6 +2871,14 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt START_PROFILE(SMBreadX); + if ((CVAL(inbuf, smb_wct) != 10) && (CVAL(inbuf, smb_wct) != 12)) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + fsp = file_fsp(SVAL(inbuf,smb_vwv2)); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); + smb_maxcnt = SVAL(inbuf,smb_vwv5); + /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { END_PROFILE(SMBreadX); -- cgit From 23998e1da83c77c16ff4d33529b8dab38005b001 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Aug 2007 21:34:55 +0000 Subject: r24320: Fix the wct checks in reply_trans2 and the reply_trans calls No idea what I've been smoking here. Thanks to Stefan for closely looking (This used to be commit 708f5af2e8c10d9a0d0027e3c31fa23689e746b8) --- source3/smbd/ipc.c | 4 ++-- source3/smbd/trans2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index b13c18a590..2403706929 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -488,7 +488,7 @@ void reply_trans(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBtrans); - if (SVAL(req->inbuf, smb_wct) < 10) { + if (req->wct < 14) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtrans); return; @@ -667,7 +667,7 @@ void reply_transs(connection_struct *conn, struct smb_request *req) show_msg((char *)req->inbuf); - if (req->wct < 10) { + if (req->wct < 8) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtranss); return; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 26769e53d6..f65d833ab0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7028,7 +7028,7 @@ void reply_trans2(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBtrans2); - if (req->wct < 8) { + if (req->wct < 14) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtrans2); return; -- cgit From 61ee2d37200f8cc00d4b0291683f4b3fb8992457 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 10:26:40 +0000 Subject: r24322: Wrap reply_read_and_X in reply_prep_legacy (This used to be commit 7926b5dfb8d05ad2fe40c3f7658a492f0450e505) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d0531bdfd9..2946eb878f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -736,7 +736,7 @@ static const struct smb_message_struct { /* 0x2b */ { "SMBecho",NULL,reply_echo,0}, /* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER}, /* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC }, -/* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x2e */ { "SMBreadX",NULL,reply_read_and_X,AS_USER | CAN_IPC }, /* 0x2f */ { "SMBwriteX",NULL,reply_write_and_X,AS_USER | CAN_IPC }, /* 0x30 */ { NULL, NULL, NULL, 0 }, /* 0x31 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3e35c0064b..7cfcecbf2f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2858,7 +2858,9 @@ normal_read: Reply to a read and X. ****************************************************************************/ -int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +static int reply_read_and_X_old(connection_struct *conn, + char *inbuf, char *outbuf, + int length,int bufsize) { files_struct *fsp; SMB_OFF_T startpos; @@ -2956,6 +2958,31 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return nread; } +void reply_read_and_X(connection_struct *conn, struct smb_request *req) +{ + char *inbuf, *outbuf; + int length, bufsize; + int outsize; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + outsize = reply_read_and_X_old(conn, inbuf, outbuf, length, bufsize); + + DEBUG(10, ("outsize = %d\n", outsize)); + + /* + * Can't use reply_post_legacy here, setup_readX_header has set up its + * size itself already. + */ + + if (outsize == -1) { + TALLOC_FREE(req->outbuf); + } +} + /**************************************************************************** Reply to a writebraw (core+ or LANMAN1.0 protocol). ****************************************************************************/ -- cgit From 8d6dcd94eba51a39f510fc2351fb9e2b7fcbc3ce Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 10:40:35 +0000 Subject: r24323: Remove the reply_read_and_X wrapper function (This used to be commit 96b218789401bb9e512339e7c6d9e0c9d9724420) --- source3/smbd/reply.c | 112 +++++++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7cfcecbf2f..5d47e532cf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2858,9 +2858,7 @@ normal_read: Reply to a read and X. ****************************************************************************/ -static int reply_read_and_X_old(connection_struct *conn, - char *inbuf, char *outbuf, - int length,int bufsize) +void reply_read_and_X(connection_struct *conn, struct smb_request *req) { files_struct *fsp; SMB_OFF_T startpos; @@ -2868,28 +2866,46 @@ static int reply_read_and_X_old(connection_struct *conn, size_t smb_maxcnt; BOOL big_readX = False; #if 0 - size_t smb_mincnt = SVAL(inbuf,smb_vwv6); + size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6); #endif + char *inbuf, *outbuf; + int length, bufsize; START_PROFILE(SMBreadX); - if ((CVAL(inbuf, smb_wct) != 10) && (CVAL(inbuf, smb_wct) != 12)) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if ((req->wct != 10) && (req->wct != 12)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } - fsp = file_fsp(SVAL(inbuf,smb_vwv2)); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); - smb_maxcnt = SVAL(inbuf,smb_vwv5); + fsp = file_fsp(SVAL(req->inbuf,smb_vwv2)); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); + smb_maxcnt = SVAL(req->inbuf,smb_vwv5); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBreadX); + return; + } /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { + reply_post_legacy( + req, + reply_pipe_read_and_X(inbuf,outbuf,length,bufsize)); END_PROFILE(SMBreadX); - return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); + return; } - CHECK_FSP(fsp,conn); - if (!CHECK_READ(fsp,inbuf)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBreadX); + return; + } + + if (!CHECK_READ(fsp,req->inbuf)) { + reply_doserror(req, ERRDOS,ERRbadaccess); + END_PROFILE(SMBreadX); + return; } set_message(inbuf,outbuf,12,0,True); @@ -2900,15 +2916,22 @@ static int reply_read_and_X_old(connection_struct *conn, if (upper_size > 1) { /* Can't do this on a chained packet. */ if ((CVAL(inbuf,smb_vwv0) != 0xFF)) { - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + END_PROFILE(SMBreadX); + return; } /* We currently don't do this on signed or sealed data. */ if (srv_is_signing_active() || srv_encryption_on()) { - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + END_PROFILE(SMBreadX); + return; } /* Is there room in the reply for this data ? */ if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, + NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBreadX); + return; } big_readX = True; } @@ -2928,59 +2951,50 @@ static int reply_read_and_X_old(connection_struct *conn, */ if(IVAL(inbuf,smb_vwv10) != 0) { - DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \ -64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) )); + DEBUG(0,("reply_read_and_X - large offset (%x << 32) " + "used and we don't support 64 bit offsets.\n", + (unsigned int)IVAL(inbuf,smb_vwv10) )); END_PROFILE(SMBreadX); - return ERROR_DOS(ERRDOS,ERRbadaccess); + reply_doserror(req, ERRDOS, ERRbadaccess); + return; } #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt, + (SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadX); - return ERROR_DOS(ERRDOS,ERRlock); + reply_doserror(req, ERRDOS, ERRlock); + return; } - if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) { + if (!big_readX + && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, + fsp, startpos, smb_maxcnt)) { END_PROFILE(SMBreadX); - return -1; + reply_post_legacy(req, -1); + return; } - nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); + nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, + startpos, smb_maxcnt); /* Only call chain_reply if not an error. */ if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) { nread = chain_reply(inbuf,&outbuf,length,bufsize); } - END_PROFILE(SMBreadX); - return nread; -} - -void reply_read_and_X(connection_struct *conn, struct smb_request *req) -{ - char *inbuf, *outbuf; - int length, bufsize; - int outsize; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - outsize = reply_read_and_X_old(conn, inbuf, outbuf, length, bufsize); - - DEBUG(10, ("outsize = %d\n", outsize)); - - /* - * Can't use reply_post_legacy here, setup_readX_header has set up its - * size itself already. - */ - - if (outsize == -1) { + if (nread == -1) { + /* + * Can't use reply_post_legacy here, setup_readX_header has + * set up its (potentially LARGE) size itself already. + */ TALLOC_FREE(req->outbuf); } + + END_PROFILE(SMBreadX); + return; } /**************************************************************************** -- cgit From 8e146e4b7b284a4e89eea11272407c57090af395 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 10:53:36 +0000 Subject: r24324: No reply_prep_legacy() in reply_pipe_read_and_X (This used to be commit 304843315c5457ff0288d66d31f1ddb1ef2796f4) --- source3/smbd/pipes.c | 33 ++++++++++++++++++--------------- source3/smbd/reply.c | 16 +++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index cf12b4be4d..7a221fa37e 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -252,11 +252,11 @@ void reply_pipe_write_and_X(struct smb_request *req) wrinkles to handle pipes. ****************************************************************************/ -int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) +void reply_pipe_read_and_X(struct smb_request *req) { - smb_np_struct *p = get_rpc_pipe_p(SVAL(inbuf,smb_vwv2)); - int smb_maxcnt = SVAL(inbuf,smb_vwv5); - int smb_mincnt = SVAL(inbuf,smb_vwv6); + smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2)); + int smb_maxcnt = SVAL(req->inbuf,smb_vwv5); + int smb_mincnt = SVAL(req->inbuf,smb_vwv6); int nread = -1; char *data; BOOL unused; @@ -265,32 +265,35 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) is deliberate, instead we always return the next lump of data on the pipe */ #if 0 - uint32 smb_offs = IVAL(inbuf,smb_vwv3); + uint32 smb_offs = IVAL(req->inbuf,smb_vwv3); #endif if (!p) { - return(ERROR_DOS(ERRDOS,ERRbadfid)); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } - set_message(inbuf,outbuf,12,0,True); - data = smb_buf(outbuf); + reply_outbuf(req, 12, smb_maxcnt); + + data = smb_buf(req->outbuf); nread = read_from_pipe(p, data, smb_maxcnt, &unused); if (nread < 0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } + + set_message(NULL, (char *)req->outbuf, 12, nread, False); - SSVAL(outbuf,smb_vwv5,nread); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); - SSVAL(smb_buf(outbuf),-2,nread); + SSVAL(req->outbuf,smb_vwv5,nread); + SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); + SSVAL(smb_buf(req->outbuf),-2,nread); DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); - /* Ensure we set up the message length to include the data length read. */ - set_message_bcc(inbuf,outbuf,nread); - return chain_reply(inbuf,&outbuf,length,bufsize); + return chain_reply_new(req); } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5d47e532cf..cf30c183fa 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2882,17 +2882,9 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); smb_maxcnt = SVAL(req->inbuf,smb_vwv5); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBreadX); - return; - } - /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { - reply_post_legacy( - req, - reply_pipe_read_and_X(inbuf,outbuf,length,bufsize)); + reply_pipe_read_and_X(req); END_PROFILE(SMBreadX); return; } @@ -2908,6 +2900,12 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) return; } + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBreadX); + return; + } + set_message(inbuf,outbuf,12,0,True); if (global_client_caps & CAP_LARGE_READX) { -- cgit From bb373dbd6c1d68d42d664351ee36f5ca4a9272c6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 11:20:21 +0000 Subject: r24325: Push down reply_prep_legacy in reply_read_and_X (This used to be commit 9d2354129dad1d4d015d463f138a196f9f72af2f) --- source3/smbd/reply.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index cf30c183fa..7b981e1c8a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2900,20 +2900,12 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) return; } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBreadX); - return; - } - - set_message(inbuf,outbuf,12,0,True); - if (global_client_caps & CAP_LARGE_READX) { - size_t upper_size = SVAL(inbuf,smb_vwv7); + size_t upper_size = SVAL(req->inbuf,smb_vwv7); smb_maxcnt |= (upper_size<<16); if (upper_size > 1) { /* Can't do this on a chained packet. */ - if ((CVAL(inbuf,smb_vwv0) != 0xFF)) { + if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBreadX); return; @@ -2935,12 +2927,12 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) } } - if(CVAL(inbuf,smb_wct) == 12) { + if (req->wct == 12) { #ifdef LARGE_SMB_OFF_T /* * This is a large offset (64 bit) read. */ - startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); + startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32); #else /* !LARGE_SMB_OFF_T */ @@ -2948,10 +2940,10 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) * Ensure we haven't been sent a >32 bit offset. */ - if(IVAL(inbuf,smb_vwv10) != 0) { + if(IVAL(req->inbuf,smb_vwv10) != 0) { DEBUG(0,("reply_read_and_X - large offset (%x << 32) " "used and we don't support 64 bit offsets.\n", - (unsigned int)IVAL(inbuf,smb_vwv10) )); + (unsigned int)IVAL(req->inbuf,smb_vwv10) )); END_PROFILE(SMBreadX); reply_doserror(req, ERRDOS, ERRbadaccess); return; @@ -2968,6 +2960,14 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) return; } + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBreadX); + return; + } + + set_message(inbuf,outbuf,12,0,True); + if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) { -- cgit From bf47a89c98aaf05d083e67bc02dc8efd3827c9cc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 11:50:53 +0000 Subject: r24326: Fix the build for Solaris CC (This used to be commit 7af4c1f547accc973f8b3ed88958bdeaf941754a) --- source3/smbd/pipes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 7a221fa37e..bf4567ddb9 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -293,7 +293,7 @@ void reply_pipe_read_and_X(struct smb_request *req) DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); - return chain_reply_new(req); + chain_reply_new(req); } /**************************************************************************** -- cgit From 26f6826dfc996fe4d170dc7bc5ef2a728c9ddcaf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 14:37:39 +0000 Subject: r24327: First round of fixes to chain_reply The argument to smb_setlen does not contain the nbt header of 4 bytes The chained function might allocate outbuf itself (as now happens with reply_read_and_X). This would erroneously overwrite the caller's outbuf. Give it an outbuf pointer of it's own (This used to be commit f923bba90866af14b32c0d0ab58acc00a5939fbb) --- source3/smbd/process.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2946eb878f..9624ca0e49 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1355,6 +1355,7 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); unsigned smb_off2 = SVAL(inbuf,smb_vwv1); char *inbuf2; + char *outbuf2 = NULL; int outsize2; int new_size; char inbuf_saved[smb_wct]; @@ -1435,7 +1436,7 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) } /* And set it in the header. */ - smb_setlen(inbuf, inbuf2, new_size); + smb_setlen(inbuf, inbuf2, new_size - 4); DEBUG(3,("Chained message\n")); show_msg(inbuf2); @@ -1446,7 +1447,7 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) init_smb_request(req, (uint8 *)inbuf2); /* process the request */ - outsize2 = switch_message(smb_com2, req, &outbuf, new_size, + outsize2 = switch_message(smb_com2, req, &outbuf2, new_size, bufsize-chain_size); /* @@ -1495,7 +1496,7 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) *poutbuf = outbuf; - memmove(outbuf + smb_wct + ofs, outbuf + smb_wct, to_move); + memmove(outbuf + smb_wct + ofs, outbuf2 + smb_wct, to_move); memcpy(outbuf + smb_wct, caller_output, caller_outputlen); /* -- cgit From d90f6fa1bd9f4aa1e09de1169597e0c703859b75 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 15:02:58 +0000 Subject: r24328: Restore chain_reply error handling Get the whole smb header from the second chained function, in particular the error fields (This used to be commit 0eb831ca0eadb725242cb4ad75eb7008a5c18bf2) --- source3/smbd/process.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9624ca0e49..adc3f638e0 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1500,9 +1500,10 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) memcpy(outbuf + smb_wct, caller_output, caller_outputlen); /* - * The secondary function has overwritten smb_com + * copy the new reply header over the old one but preserve the smb_com + * field */ - + memmove(outbuf,outbuf2,smb_wct); SCVAL(outbuf, smb_com, smb_com1); /* -- cgit From 921fbb25eb4a6097a1e960abadc4dc4b11d32cf6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 16:28:10 +0000 Subject: r24332: schedule_aio_read_and_X does not need InBuf/OutBuf (This used to be commit 9ad91bd20592850d7b6393e1ac7f0e0919d69668) --- source3/smbd/aio.c | 25 ++++++++++++------------- source3/smbd/reply.c | 15 +++++++-------- 2 files changed, 19 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 0ba857e2e5..49855796b7 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -51,7 +51,7 @@ static struct aio_extra *aio_list_head; static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, uint16 mid, - const char *inbuf) + const uint8 *inbuf) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -203,8 +203,7 @@ void initialize_async_io_handler(void) *****************************************************************************/ BOOL schedule_aio_read_and_X(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int len_outbuf, + struct smb_request *req, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) { @@ -224,7 +223,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, /* Only do this on non-chained and non-chaining reads not using the * write cache. */ - if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) + if (chain_size !=0 || (CVAL(req->inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } @@ -236,18 +235,19 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, return False; } - /* The following is safe from integer wrap as we've already - checked smb_maxcnt is 128k or less. */ - bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt; + /* The following is safe from integer wrap as we've already checked + smb_maxcnt is 128k or less. Wct is 12 for read replies */ + + bufsize = smb_size + 12 * 2 + smb_maxcnt; - if ((aio_ex = create_aio_ex_read(fsp, bufsize, - SVAL(inbuf,smb_mid), inbuf)) == NULL) { + if (!(aio_ex = create_aio_ex_read(fsp, bufsize, req->mid, + req->inbuf))) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } - /* Copy the SMB header already setup in outbuf. */ - memcpy(aio_ex->outbuf, outbuf, smb_buf(outbuf) - outbuf); + construct_reply_common((char *)req->inbuf, aio_ex->outbuf); + set_message((char *)req->inbuf, aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -625,8 +625,7 @@ int process_aio_queue(void) } BOOL schedule_aio_read_and_X(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int len_outbuf, + struct smb_request *req, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7b981e1c8a..a62b54550e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2960,22 +2960,21 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) return; } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); + if (!big_readX + && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) { END_PROFILE(SMBreadX); + reply_post_legacy(req, -1); return; } - set_message(inbuf,outbuf,12,0,True); - - if (!big_readX - && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, - fsp, startpos, smb_maxcnt)) { + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBreadX); - reply_post_legacy(req, -1); return; } + set_message(inbuf,outbuf,12,0,True); + nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); /* Only call chain_reply if not an error. */ -- cgit From d198962d14d417bf191ce45ad8e9034bc943a865 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Aug 2007 09:16:54 +0000 Subject: r24346: Push reply_prep_legacy into send_file_readX (This used to be commit cded66a7dc72d41e4d6ea90edd8b03ed080c042f) --- source3/smbd/reply.c | 71 +++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a62b54550e..93e2aaf0be 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2733,16 +2733,28 @@ static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt) Reply to a read and X - possibly using sendfile. ****************************************************************************/ -int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf, - files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) +static void send_file_readX(connection_struct *conn, struct smb_request *req, + files_struct *fsp, SMB_OFF_T startpos, + size_t smb_maxcnt) { SMB_STRUCT_STAT sbuf; - int outsize = 0; ssize_t nread = -1; - char *data = smb_buf(outbuf); + char *data; + char *inbuf, *outbuf; + int length, len_outbuf; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &len_outbuf)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + set_message(inbuf, outbuf, 12, 0, True); + + data = smb_buf(outbuf); if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + reply_unixerror(req, ERRDOS, ERRnoaccess); + return; } if (startpos > sbuf.st_size) { @@ -2803,8 +2815,9 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length } DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); - /* Returning -1 here means successful sendfile. */ - return -1; + /* No outbuf here means successful sendfile. */ + TALLOC_FREE(req->outbuf); + return; } DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", @@ -2814,8 +2827,9 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); - /* Returning -1 here means successful sendfile. */ - return -1; + /* No outbuf here means successful sendfile. */ + TALLOC_FREE(req->outbuf); + return; } #endif @@ -2836,21 +2850,24 @@ normal_read: fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readX: fake_sendfile failed"); } - return -1; + TALLOC_FREE(req->outbuf); + return; } else { nread = read_file(fsp,data,startpos,smb_maxcnt); if (nread < 0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); + reply_unixerror(req, ERRDOS, ERRnoaccess); + return; } - outsize = setup_readX_header(inbuf, outbuf,nread); + setup_readX_header(inbuf, outbuf,nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); - /* Returning the number of bytes we want to send back - including header. */ - return outsize; + chain_reply_new(req); + + return; } } @@ -2862,14 +2879,11 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) { files_struct *fsp; SMB_OFF_T startpos; - ssize_t nread = -1; size_t smb_maxcnt; BOOL big_readX = False; #if 0 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6); #endif - char *inbuf, *outbuf; - int length, bufsize; START_PROFILE(SMBreadX); @@ -2967,28 +2981,7 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) return; } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBreadX); - return; - } - - set_message(inbuf,outbuf,12,0,True); - - nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, - startpos, smb_maxcnt); - /* Only call chain_reply if not an error. */ - if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) { - nread = chain_reply(inbuf,&outbuf,length,bufsize); - } - - if (nread == -1) { - /* - * Can't use reply_post_legacy here, setup_readX_header has - * set up its (potentially LARGE) size itself already. - */ - TALLOC_FREE(req->outbuf); - } + send_file_readX(conn, req, fsp, startpos, smb_maxcnt); END_PROFILE(SMBreadX); return; -- cgit From 6dcf0c64cfcf905e55e46b423d8e153918da862c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Aug 2007 11:22:26 +0000 Subject: r24347: fake_sendfile does not need Inbuf/Outbuf In the future, we might put the new Linux splice(2) syscall here. This should also work for reply_write, but getting that in is a bit trickier. We need to decide very early before fetching the whole buffer that we have a write call. (This used to be commit 32921c878a7f60251a9217173951065784077077) --- source3/smbd/reply.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 93e2aaf0be..9119ec1e0b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2333,9 +2333,22 @@ static void fail_readraw(void) Fake (read/write) sendfile. Returns -1 on read or write fail. ****************************************************************************/ -static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize) +static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, + size_t nread) { + size_t bufsize; size_t tosend = nread; + char *buf; + + if (nread == 0) { + return 0; + } + + bufsize = MIN(nread, 65536); + + if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) { + return -1; + } while (tosend > 0) { ssize_t ret; @@ -2348,6 +2361,7 @@ static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread } ret = read_file(fsp,buf,startpos,cur_read); if (ret == -1) { + SAFE_FREE(buf); return -1; } @@ -2357,12 +2371,14 @@ static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread } if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) { + SAFE_FREE(buf); return -1; } tosend -= cur_read; startpos += cur_read; } + SAFE_FREE(buf); return (ssize_t)nread; } @@ -2408,7 +2424,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st set_use_sendfile(SNUM(conn), False); DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n")); - if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) { + if (fake_sendfile(fsp, startpos, nread) == -1) { DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readbraw fake_sendfile failed"); @@ -2806,9 +2822,9 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, /* Ensure we don't do this again. */ set_use_sendfile(SNUM(conn), False); DEBUG(0,("send_file_readX: sendfile not available. Faking..\n")); - - if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data, - len_outbuf - (data-outbuf))) == -1) { + nread = fake_sendfile(fsp, startpos, + smb_maxcnt); + if (nread == -1) { DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readX: fake_sendfile failed"); @@ -2844,8 +2860,8 @@ normal_read: fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readX sendfile failed"); } - if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data, - len_outbuf - (data-outbuf))) == -1) { + nread = fake_sendfile(fsp, startpos, smb_maxcnt); + if (nread == -1) { DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readX: fake_sendfile failed"); -- cgit From a0ad547ccbf5316862bd8f7b8ae9e76c4386b62c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Aug 2007 11:40:27 +0000 Subject: r24348: Do not use inbuf/outbuf in the sendfile path of read_and_X (This used to be commit 595ea708ee8c9b6f86648dfdb5ff5a3feafe1f07) --- source3/smbd/reply.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9119ec1e0b..1698a0e7b1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2731,7 +2731,10 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt) { int outsize; - char *data = smb_buf(outbuf); + char *data; + + outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False); + data = smb_buf(outbuf); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,smb_maxcnt); @@ -2739,7 +2742,6 @@ static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt) SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16)); SSVAL(smb_buf(outbuf),-2,smb_maxcnt); SCVAL(outbuf,smb_vwv0,0xFF); - outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False); /* Reset the outgoing length, set_message truncates at 0x1FFFF. */ _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4)); return outsize; @@ -2759,15 +2761,6 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, char *inbuf, *outbuf; int length, len_outbuf; - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &len_outbuf)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - set_message(inbuf, outbuf, 12, 0, True); - - data = smb_buf(outbuf); - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); return; @@ -2790,8 +2783,9 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, * on a train in Germany :-). JRA. */ - if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) && + if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { + char headerbuf[smb_size + 12 * 2]; DATA_BLOB header; /* @@ -2800,11 +2794,10 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, * correct amount of data). */ - setup_readX_header(inbuf,outbuf,smb_maxcnt); - set_message(inbuf,outbuf,12,smb_maxcnt,False); - header.data = (uint8 *)outbuf; - header.length = data - outbuf; - header.free = NULL; + header = data_blob_const(headerbuf, sizeof(headerbuf)); + + construct_reply_common((char *)req->inbuf, headerbuf); + setup_readX_header((char *)req->inbuf, headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ @@ -2852,6 +2845,15 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, normal_read: + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &len_outbuf)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + set_message(inbuf, outbuf, 12, 0, True); + + data = smb_buf(outbuf); + if ((smb_maxcnt & 0xFF0000) > 0x10000) { int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt; /* Send out the header. */ -- cgit From 2fb27fcb692dfaccf36c6530012d6e24f944e1a4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Aug 2007 12:15:32 +0000 Subject: r24349: For large read&x we need more than 64k of outbuf. (This used to be commit f7e2eec35f7457ec70d75ef099b34f83c9dfd654) --- source3/smbd/process.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index adc3f638e0..c59ee2c200 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -953,8 +953,19 @@ static const struct smb_message_struct { allocate and initialize a reply packet ********************************************************************/ -void reply_outbuf(struct smb_request *req, uint8 num_words, uint16 num_bytes) +void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) { + /* + * Protect against integer wrap + */ + if ((num_bytes > 0xffffff) + || ((num_bytes + smb_size + num_words*2) > 0xffffff)) { + char *msg; + asprintf(&msg, "num_bytes too large: %u", + (unsigned)num_bytes); + smb_panic(msg); + } + if (!(req->outbuf = TALLOC_ARRAY( req, uint8, smb_size + num_words*2 + num_bytes))) { -- cgit From 5d39acf2f8cdee9e70a470a638909db7ceb219b2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 12 Aug 2007 12:57:56 +0000 Subject: r24351: Remove reply_prep_legacy from reply_read_and_X (This used to be commit 8f3e3a21008a2cb6ed73d8629aaf1fa565f19e79) --- source3/smbd/reply.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1698a0e7b1..bf09180529 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2728,12 +2728,14 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Setup readX header. ****************************************************************************/ -static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt) +static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf, + size_t smb_maxcnt) { int outsize; char *data; - outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False); + outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt, + False); data = smb_buf(outbuf); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ @@ -2757,9 +2759,6 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, { SMB_STRUCT_STAT sbuf; ssize_t nread = -1; - char *data; - char *inbuf, *outbuf; - int length, len_outbuf; if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); @@ -2785,7 +2784,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { - char headerbuf[smb_size + 12 * 2]; + uint8 headerbuf[smb_size + 12 * 2]; DATA_BLOB header; /* @@ -2796,8 +2795,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, header = data_blob_const(headerbuf, sizeof(headerbuf)); - construct_reply_common((char *)req->inbuf, headerbuf); - setup_readX_header((char *)req->inbuf, headerbuf, smb_maxcnt); + construct_reply_common((char *)req->inbuf, (char *)headerbuf); + setup_readX_header(req->inbuf, headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ @@ -2845,19 +2844,15 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, normal_read: - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &len_outbuf)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - set_message(inbuf, outbuf, 12, 0, True); + if ((smb_maxcnt & 0xFF0000) > 0x10000) { + uint8 headerbuf[smb_size + 2*12]; - data = smb_buf(outbuf); + construct_reply_common((char *)req->inbuf, (char *)headerbuf); + setup_readX_header(req->inbuf, headerbuf, smb_maxcnt); - if ((smb_maxcnt & 0xFF0000) > 0x10000) { - int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt; /* Send out the header. */ - if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) { + if (write_data(smbd_server_fd(), (char *)headerbuf, + sizeof(headerbuf)) != sizeof(headerbuf)) { DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n", fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readX sendfile failed"); @@ -2871,14 +2866,16 @@ normal_read: TALLOC_FREE(req->outbuf); return; } else { - nread = read_file(fsp,data,startpos,smb_maxcnt); + reply_outbuf(req, 12, smb_maxcnt); + nread = read_file(fsp, smb_buf(req->outbuf), startpos, + smb_maxcnt); if (nread < 0) { reply_unixerror(req, ERRDOS, ERRnoaccess); return; } - setup_readX_header(inbuf, outbuf,nread); + setup_readX_header(req->inbuf, req->outbuf, nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); -- cgit From 5af3e2d613f55ab7289b85d22a0e9fa115de4549 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Aug 2007 07:20:19 +0000 Subject: r24355: move reply_outbuf() to the place where it's used metze (This used to be commit c7ed550483233851d395edb4b8443b3296b45fb7) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bf09180529..26ddde7a65 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3435,7 +3435,6 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) } nwritten = write_file(fsp,data,startpos,numtowrite); - reply_outbuf(req, 6, 0); } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { @@ -3444,6 +3443,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) return; } + reply_outbuf(req, 6, 0); SSVAL(req->outbuf,smb_vwv2,nwritten); if (large_writeX) SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1); -- cgit From 2d8e4456cd8f0bff60e164c685e69ca9214bacb2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 08:33:01 +0000 Subject: r24356: Add send_nt_replies_new wrapper (This used to be commit 8a910d37ccc767eb8ab25ef2af3a136ad874346f) --- source3/smbd/nttrans.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1d13036920..1500c355d1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -262,6 +262,24 @@ int send_nt_replies(const char *inbuf, return 0; } +void send_nt_replies_new(struct smb_request *req, NTSTATUS nt_error, + char *params, int paramsize, + char *pdata, int datasize) +{ + char *inbuf, *outbuf; + int length, bufsize; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + reply_post_legacy( + req, + send_nt_replies(inbuf, outbuf, bufsize, nt_error, + params, paramsize, pdata, datasize)); +} + /**************************************************************************** Is it an NTFS stream name ? ****************************************************************************/ -- cgit From ecb32af916fbc3fdc5fc48cf0a8c0bbe6ace2ddd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 08:50:09 +0000 Subject: r24357: Check wct in reply_nttrans[s] (This used to be commit 9ab87e644e4dc54ebbcb8ad300fe338f4a809ba9) --- source3/smbd/nttrans.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1500c355d1..566e03008f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3176,17 +3176,27 @@ int reply_nttrans(connection_struct *conn, char *inbuf,char *outbuf,int size,int bufsize) { int outsize = 0; - uint32 pscnt = IVAL(inbuf,smb_nt_ParameterCount); - uint32 psoff = IVAL(inbuf,smb_nt_ParameterOffset); - uint32 dscnt = IVAL(inbuf,smb_nt_DataCount); - uint32 dsoff = IVAL(inbuf,smb_nt_DataOffset); - - uint16 function_code = SVAL( inbuf, smb_nt_Function); + uint32 pscnt; + uint32 psoff; + uint32 dscnt; + uint32 dsoff; + uint16 function_code; NTSTATUS result; struct trans_state *state; START_PROFILE(SMBnttrans); + if (CVAL(inbuf, smb_wct) < 19) { + END_PROFILE(SMBnttrans); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + pscnt = IVAL(inbuf,smb_nt_ParameterCount); + psoff = IVAL(inbuf,smb_nt_ParameterOffset); + dscnt = IVAL(inbuf,smb_nt_DataCount); + dsoff = IVAL(inbuf,smb_nt_DataOffset); + function_code = SVAL( inbuf, smb_nt_Function); + if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { END_PROFILE(SMBnttrans); return ERROR_DOS(ERRSRV,ERRaccess); @@ -3353,6 +3363,11 @@ int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf, show_msg(inbuf); + if (CVAL(inbuf, smb_wct) < 18) { + END_PROFILE(SMBnttranss); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + for (state = conn->pending_trans; state != NULL; state = state->next) { if (state->mid == SVAL(inbuf,smb_mid)) { -- cgit From 6bee410431067dc4525fd5a4ff57b5ae22a8fb0c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 09:12:21 +0000 Subject: r24358: Push reply_prep_legacy into reply_nttrans[s] (This used to be commit 197c2310792965f94d66ad7c8016a1594945bdf8) --- source3/smbd/nttrans.c | 74 ++++++++++++++++++++++++++++++++++++-------------- source3/smbd/process.c | 4 +-- 2 files changed, 55 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 566e03008f..b9b7a3c2eb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3172,8 +3172,7 @@ static int handle_nttrans(connection_struct *conn, Reply to a SMBNTtrans. ****************************************************************************/ -int reply_nttrans(connection_struct *conn, - char *inbuf,char *outbuf,int size,int bufsize) +void reply_nttrans(connection_struct *conn, struct smb_request *req) { int outsize = 0; uint32 pscnt; @@ -3184,11 +3183,21 @@ int reply_nttrans(connection_struct *conn, NTSTATUS result; struct trans_state *state; + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(SMBnttrans); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + if (CVAL(inbuf, smb_wct) < 19) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnttrans); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } pscnt = IVAL(inbuf,smb_nt_ParameterCount); @@ -3198,20 +3207,23 @@ int reply_nttrans(connection_struct *conn, function_code = SVAL( inbuf, smb_nt_Function); if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { + reply_doserror(req, ERRSRV, ERRaccess); END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRaccess); + return; } result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result))); + reply_nterror(req, result); END_PROFILE(SMBnttrans); - return ERROR_NT(result); + return; } if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { + reply_doserror(req, ERRSRV, ERRaccess); END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRSRV,ERRaccess); + return; } state->cmd = SMBnttrans; @@ -3244,8 +3256,9 @@ int reply_nttrans(connection_struct *conn, /* Don't allow more than 128mb for each value. */ if ((state->total_data > (1024*1024*128)) || (state->total_param > (1024*1024*128))) { + reply_doserror(req, ERRDOS, ERRnomem); END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRDOS,ERRnomem); + return; } if ((dscnt > state->total_data) || (pscnt > state->total_param)) @@ -3258,8 +3271,9 @@ int reply_nttrans(connection_struct *conn, DEBUG(0,("reply_nttrans: data malloc fail for %u " "bytes !\n", (unsigned int)state->total_data)); TALLOC_FREE(state); + reply_doserror(req, ERRDOS, ERRnomem); END_PROFILE(SMBnttrans); - return(ERROR_DOS(ERRDOS,ERRnomem)); + return; } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; @@ -3278,8 +3292,9 @@ int reply_nttrans(connection_struct *conn, "bytes !\n", (unsigned int)state->total_param)); SAFE_FREE(state->data); TALLOC_FREE(state); + reply_doserror(req, ERRDOS, ERRnomem); END_PROFILE(SMBnttrans); - return(ERROR_DOS(ERRDOS,ERRnomem)); + return; } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; @@ -3302,8 +3317,9 @@ int reply_nttrans(connection_struct *conn, SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); + reply_doserror(req, ERRDOS, ERRnomem); END_PROFILE(SMBnttrans); - return ERROR_DOS(ERRDOS,ERRnomem); + return; } if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) || @@ -3325,8 +3341,9 @@ int reply_nttrans(connection_struct *conn, SAFE_FREE(state->param); SAFE_FREE(state->data); TALLOC_FREE(state); + reply_post_legacy(req, outsize); END_PROFILE(SMBnttrans); - return outsize; + return; } DLIST_ADD(conn->pending_trans, state); @@ -3336,7 +3353,8 @@ int reply_nttrans(connection_struct *conn, outsize = set_message(inbuf,outbuf,0,0,False); show_msg(outbuf); END_PROFILE(SMBnttrans); - return outsize; + reply_post_legacy(req, outsize); + return; bad_param: @@ -3344,28 +3362,38 @@ int reply_nttrans(connection_struct *conn, SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnttrans); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } /**************************************************************************** Reply to a SMBnttranss ****************************************************************************/ -int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf, - int size,int bufsize) +void reply_nttranss(connection_struct *conn, struct smb_request *req) { int outsize = 0; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(SMBnttranss); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + show_msg(inbuf); if (CVAL(inbuf, smb_wct) < 18) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnttranss); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } for (state = conn->pending_trans; state != NULL; @@ -3376,8 +3404,9 @@ int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf, } if ((state == NULL) || (state->cmd != SMBnttrans)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnttranss); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } /* Revise state->total_param and state->total_data in case they have @@ -3441,7 +3470,7 @@ int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf, if ((state->received_param < state->total_param) || (state->received_data < state->total_data)) { END_PROFILE(SMBnttranss); - return -1; + return; } /* construct_reply_common has done us the favor to pre-fill the @@ -3458,12 +3487,14 @@ int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf, TALLOC_FREE(state); if (outsize == 0) { + reply_doserror(req, ERRSRV, ERRnosupport); END_PROFILE(SMBnttranss); - return(ERROR_DOS(ERRSRV,ERRnosupport)); + return; } + reply_post_legacy(req, outsize); END_PROFILE(SMBnttranss); - return(outsize); + return; bad_param: @@ -3472,6 +3503,7 @@ int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf, SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnttranss); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c59ee2c200..93c6be8c2f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -850,8 +850,8 @@ static const struct smb_message_struct { /* 0x9d */ { NULL, NULL, NULL, 0 }, /* 0x9e */ { NULL, NULL, NULL, 0 }, /* 0x9f */ { NULL, NULL, NULL, 0 }, -/* 0xa0 */ { "SMBnttrans", reply_nttrans,NULL, AS_USER | CAN_IPC }, -/* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC }, +/* 0xa0 */ { "SMBnttrans", NULL,reply_nttrans, AS_USER | CAN_IPC }, +/* 0xa1 */ { "SMBnttranss", NULL,reply_nttranss, AS_USER | CAN_IPC }, /* 0xa2 */ { "SMBntcreateX", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC }, /* 0xa3 */ { NULL, NULL, NULL, 0 }, /* 0xa4 */ { "SMBntcancel", NULL,reply_ntcancel, 0 }, -- cgit From 6216cd58c2cc608d0a90ff9fd52b93b7949baeba Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 09:49:03 +0000 Subject: r24359: Fix the build (This used to be commit b2ac1a3ec59f7c804521e5a478916fba16f4b3d4) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b9b7a3c2eb..39029424d5 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3384,7 +3384,7 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); + END_PROFILE(SMBnttranss); return; } -- cgit From 1d8e64aeceef5a4dd43b18491714fb6d9eb10105 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 14:29:44 +0000 Subject: r24361: Push reply_prep_legacy down in reply_nttrans[s] (This used to be commit d97a2e91d3c44ad39e6a1ee369e1e906d98707f5) --- source3/smbd/nttrans.c | 117 +++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 39029424d5..3b9ebe3b88 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3188,23 +3188,18 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBnttrans); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - if (CVAL(inbuf, smb_wct) < 19) { + if (req->wct < 19) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnttrans); return; } - pscnt = IVAL(inbuf,smb_nt_ParameterCount); - psoff = IVAL(inbuf,smb_nt_ParameterOffset); - dscnt = IVAL(inbuf,smb_nt_DataCount); - dsoff = IVAL(inbuf,smb_nt_DataOffset); - function_code = SVAL( inbuf, smb_nt_Function); + size = smb_len(req->inbuf) + 4; + pscnt = IVAL(req->inbuf,smb_nt_ParameterCount); + psoff = IVAL(req->inbuf,smb_nt_ParameterOffset); + dscnt = IVAL(req->inbuf,smb_nt_DataCount); + dsoff = IVAL(req->inbuf,smb_nt_DataOffset); + function_code = SVAL(req->inbuf, smb_nt_Function); if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { reply_doserror(req, ERRSRV, ERRaccess); @@ -3212,7 +3207,7 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) return; } - result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid)); + result = allow_new_trans(conn->pending_trans, req->mid); if (!NT_STATUS_IS_OK(result)) { DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result))); reply_nterror(req, result); @@ -3228,17 +3223,17 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) state->cmd = SMBnttrans; - state->mid = SVAL(inbuf,smb_mid); - state->vuid = SVAL(inbuf,smb_uid); - state->total_data = IVAL(inbuf, smb_nt_TotalDataCount); + state->mid = req->mid; + state->vuid = req->vuid; + state->total_data = IVAL(req->inbuf, smb_nt_TotalDataCount); state->data = NULL; - state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount); + state->total_param = IVAL(req->inbuf, smb_nt_TotalParameterCount); state->param = NULL; - state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount); - state->max_param_return = IVAL(inbuf,smb_nt_MaxParameterCount); + state->max_data_return = IVAL(req->inbuf,smb_nt_MaxDataCount); + state->max_param_return = IVAL(req->inbuf,smb_nt_MaxParameterCount); /* setup count is in *words* */ - state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); + state->setup_count = 2*CVAL(req->inbuf,smb_nt_SetupCount); state->setup = NULL; state->call = function_code; @@ -3247,9 +3242,9 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) * state->setup_count. Ensure this is so as a sanity check. */ - if(CVAL(inbuf, smb_wct) != 19 + (state->setup_count/2)) { + if(req->wct != 19 + (state->setup_count/2)) { DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n", - CVAL(inbuf, smb_wct), 19 + (state->setup_count/2))); + req->wct, 19 + (state->setup_count/2))); goto bad_param; } @@ -3277,11 +3272,12 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; - if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) || - (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf))) + if ((smb_base(req->inbuf)+dsoff+dscnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf))) goto bad_param; - memcpy(state->data,smb_base(inbuf)+dsoff,dscnt); + memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } if (state->total_param) { @@ -3298,11 +3294,12 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; - if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) || - (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf))) + if ((smb_base(req->inbuf)+psoff+pscnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf))) goto bad_param; - memcpy(state->param,smb_base(inbuf)+psoff,pscnt); + memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } state->received_data = dscnt; @@ -3330,10 +3327,17 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) goto bad_param; } - memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count); + memcpy( state->setup, &req->inbuf[smb_nt_SetupStart], + state->setup_count); dump_data(10, (uint8 *)state->setup, state->setup_count); } + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + if ((state->received_data == state->total_data) && (state->received_param == state->total_param)) { outsize = handle_nttrans(conn, state, inbuf, outbuf, @@ -3382,15 +3386,9 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBnttranss); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttranss); - return; - } - - show_msg(inbuf); + show_msg((char *)req->inbuf); - if (CVAL(inbuf, smb_wct) < 18) { + if (req->wct < 18) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnttranss); return; @@ -3398,7 +3396,7 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) for (state = conn->pending_trans; state != NULL; state = state->next) { - if (state->mid == SVAL(inbuf,smb_mid)) { + if (state->mid == req->mid) { break; } } @@ -3411,20 +3409,24 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) /* Revise state->total_param and state->total_data in case they have changed downwards */ - if (IVAL(inbuf, smb_nts_TotalParameterCount) < state->total_param) { - state->total_param = IVAL(inbuf, smb_nts_TotalParameterCount); + if (IVAL(req->inbuf, smb_nts_TotalParameterCount) + < state->total_param) { + state->total_param = IVAL(req->inbuf, + smb_nts_TotalParameterCount); } - if (IVAL(inbuf, smb_nts_TotalDataCount) < state->total_data) { - state->total_data = IVAL(inbuf, smb_nts_TotalDataCount); + if (IVAL(req->inbuf, smb_nts_TotalDataCount) < state->total_data) { + state->total_data = IVAL(req->inbuf, smb_nts_TotalDataCount); } - pcnt = IVAL(inbuf,smb_nts_ParameterCount); - poff = IVAL(inbuf, smb_nts_ParameterOffset); - pdisp = IVAL(inbuf, smb_nts_ParameterDisplacement); + size = smb_len(req->inbuf) + 4; + + pcnt = IVAL(req->inbuf,smb_nts_ParameterCount); + poff = IVAL(req->inbuf, smb_nts_ParameterOffset); + pdisp = IVAL(req->inbuf, smb_nts_ParameterDisplacement); - dcnt = IVAL(inbuf, smb_nts_DataCount); - ddisp = IVAL(inbuf, smb_nts_DataDisplacement); - doff = IVAL(inbuf, smb_nts_DataOffset); + dcnt = IVAL(req->inbuf, smb_nts_DataCount); + ddisp = IVAL(req->inbuf, smb_nts_DataDisplacement); + doff = IVAL(req->inbuf, smb_nts_DataOffset); state->received_param += pcnt; state->received_data += dcnt; @@ -3440,13 +3442,15 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) goto bad_param; if (pdisp > state->total_param) goto bad_param; - if ((smb_base(inbuf) + poff + pcnt > inbuf + size) || - (smb_base(inbuf) + poff + pcnt < smb_base(inbuf))) + if ((smb_base(req->inbuf) + poff + pcnt + > (char *)req->inbuf + size) || + (smb_base(req->inbuf) + poff + pcnt + < smb_base(req->inbuf))) goto bad_param; if (state->param + pdisp < state->param) goto bad_param; - memcpy(state->param+pdisp,smb_base(inbuf)+poff, + memcpy(state->param+pdisp, smb_base(req->inbuf)+poff, pcnt); } @@ -3457,13 +3461,14 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) goto bad_param; if (ddisp > state->total_data) goto bad_param; - if ((smb_base(inbuf) + doff + dcnt > inbuf + size) || + if ((smb_base(inbuf) + doff + dcnt + > (char *)req->inbuf + size) || (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) goto bad_param; if (state->data + ddisp < state->data) goto bad_param; - memcpy(state->data+ddisp, smb_base(inbuf)+doff, + memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, dcnt); } @@ -3473,6 +3478,12 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) return; } + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + /* construct_reply_common has done us the favor to pre-fill the * command field with SMBnttranss which is wrong :-) */ -- cgit From 2a375f12be2ce2b2b8db58105b1794679bfa3920 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 14:40:56 +0000 Subject: r24362: Initialize padding also when no params are sent back (This used to be commit 03c5e960a21ae78cdd832a5c760015f7fbd83bd9) --- source3/smbd/trans2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f65d833ab0..9c4c8556d2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -699,13 +699,15 @@ void send_trans2_replies(struct smb_request *req, SSVAL(req->outbuf,smb_drdisp, pd - pdata); } + /* Initialize the padding for alignment */ + + if (alignment_offset != 0) { + memset(smb_buf(req->outbuf), 0, alignment_offset); + } + /* Copy the param bytes into the packet */ if(params_sent_thistime) { - if (alignment_offset != 0) { - memset(smb_buf(req->outbuf), 0, - alignment_offset); - } memcpy((smb_buf(req->outbuf)+alignment_offset), pp, params_sent_thistime); } -- cgit From 1b034a8f9e0668f7a2a40109989680c9eb2a5c12 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 15:40:37 +0000 Subject: r24367: Push reply_prep_legacy into handle_nttrans (This used to be commit 8b5e51c2668799890d033a371e5b9a57b8f086c6) --- source3/smbd/nttrans.c | 79 ++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 47 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3b9ebe3b88..99391887d6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3046,14 +3046,24 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, } #endif /* HAVE_SYS_QUOTAS */ -static int handle_nttrans(connection_struct *conn, - struct trans_state *state, - char *inbuf, char *outbuf, int size, int bufsize) +static void handle_nttrans(connection_struct *conn, + struct trans_state *state, + struct smb_request *req) { - int outsize; + int outsize = -1; + + char *inbuf, *outbuf; + int size, bufsize; if (Protocol >= PROTOCOL_NT1) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */ + req->flags2 |= 0x40; /* IS_LONG_NAME */ + SSVAL(req->inbuf,smb_flg2,req->flags2); + } + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; } /* Now we must call the relevant NT_TRANS function */ @@ -3163,9 +3173,11 @@ static int handle_nttrans(connection_struct *conn, /* Error in request */ DEBUG(0,("handle_nttrans: Unknown request %d in " "nttrans call\n", state->call)); - return ERROR_DOS(ERRSRV,ERRerror); + reply_doserror(req, ERRSRV, ERRerror); + return; } - return outsize; + reply_post_legacy(req, outsize); + return; } /**************************************************************************** @@ -3174,7 +3186,6 @@ static int handle_nttrans(connection_struct *conn, void reply_nttrans(connection_struct *conn, struct smb_request *req) { - int outsize = 0; uint32 pscnt; uint32 psoff; uint32 dscnt; @@ -3182,9 +3193,7 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) uint16 function_code; NTSTATUS result; struct trans_state *state; - - char *inbuf, *outbuf; - int size, bufsize; + int size; START_PROFILE(SMBnttrans); @@ -3332,20 +3341,12 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) dump_data(10, (uint8 *)state->setup, state->setup_count); } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - if ((state->received_data == state->total_data) && (state->received_param == state->total_param)) { - outsize = handle_nttrans(conn, state, inbuf, outbuf, - size, bufsize); + handle_nttrans(conn, state, req); SAFE_FREE(state->param); SAFE_FREE(state->data); TALLOC_FREE(state); - reply_post_legacy(req, outsize); END_PROFILE(SMBnttrans); return; } @@ -3354,10 +3355,9 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) /* We need to send an interim response then receive the rest of the parameter/data bytes */ - outsize = set_message(inbuf,outbuf,0,0,False); - show_msg(outbuf); + reply_outbuf(req, 0, 0); + show_msg((char *)req->outbuf); END_PROFILE(SMBnttrans); - reply_post_legacy(req, outsize); return; bad_param: @@ -3377,12 +3377,10 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) void reply_nttranss(connection_struct *conn, struct smb_request *req) { - int outsize = 0; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - char *inbuf, *outbuf; - int size, bufsize; + int size; START_PROFILE(SMBnttranss); @@ -3461,9 +3459,10 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) goto bad_param; if (ddisp > state->total_data) goto bad_param; - if ((smb_base(inbuf) + doff + dcnt + if ((smb_base(req->inbuf) + doff + dcnt > (char *)req->inbuf + size) || - (smb_base(inbuf) + doff + dcnt < smb_base(inbuf))) + (smb_base(req->inbuf) + doff + dcnt + < smb_base(req->inbuf))) goto bad_param; if (state->data + ddisp < state->data) goto bad_param; @@ -3478,32 +3477,18 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) return; } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - /* construct_reply_common has done us the favor to pre-fill the - * command field with SMBnttranss which is wrong :-) + /* + * construct_reply_common will copy smb_com from inbuf to + * outbuf. SMBnttranss is wrong here. */ - SCVAL(outbuf,smb_com,SMBnttrans); + SCVAL(req->inbuf,smb_com,SMBnttrans); - outsize = handle_nttrans(conn, state, inbuf, outbuf, - size, bufsize); + handle_nttrans(conn, state, req); DLIST_REMOVE(conn->pending_trans, state); SAFE_FREE(state->data); SAFE_FREE(state->param); TALLOC_FREE(state); - - if (outsize == 0) { - reply_doserror(req, ERRSRV, ERRnosupport); - END_PROFILE(SMBnttranss); - return; - } - - reply_post_legacy(req, outsize); END_PROFILE(SMBnttranss); return; -- cgit From 20b3daec50f32a790e242337690572dd21ac51ca Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 15:41:29 +0000 Subject: r24368: Push down reply_prep_legacy one level Not pretty, but necessary to convert the calls one by one (This used to be commit 523a463be427da0c3dbe01399e87b82b9f759512) --- source3/smbd/nttrans.c | 222 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 167 insertions(+), 55 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 99391887d6..fd3d8b462b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -3050,95 +3050,176 @@ static void handle_nttrans(connection_struct *conn, struct trans_state *state, struct smb_request *req) { - int outsize = -1; - - char *inbuf, *outbuf; - int size, bufsize; - if (Protocol >= PROTOCOL_NT1) { req->flags2 |= 0x40; /* IS_LONG_NAME */ SSVAL(req->inbuf,smb_flg2,req->flags2); } - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - /* Now we must call the relevant NT_TRANS function */ switch(state->call) { case NT_TRANSACT_CREATE: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_create); - outsize = call_nt_transact_create(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_create( + conn, inbuf, outbuf, + size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return)); + END_PROFILE(NT_transact_create); break; } case NT_TRANSACT_IOCTL: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_ioctl); - outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, state->max_data_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_ioctl( + conn, inbuf, outbuf, + size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return)); + END_PROFILE(NT_transact_ioctl); break; } case NT_TRANSACT_SET_SECURITY_DESC: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_set_security_desc); - outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, state->max_data_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_set_security_desc( + conn, inbuf, outbuf, + size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return)); END_PROFILE(NT_transact_set_security_desc); break; } case NT_TRANSACT_NOTIFY_CHANGE: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_notify_change); - outsize = call_nt_transact_notify_change( - conn, inbuf, outbuf, size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return, - state->max_param_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_notify_change( + conn, inbuf, outbuf, size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return, + state->max_param_return)); + END_PROFILE(NT_transact_notify_change); break; } case NT_TRANSACT_RENAME: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_rename); - outsize = call_nt_transact_rename(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, state->max_data_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_rename( + conn, inbuf, outbuf, + size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return)); + END_PROFILE(NT_transact_rename); break; } case NT_TRANSACT_QUERY_SECURITY_DESC: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_query_security_desc); - outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, state->max_data_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_query_security_desc( + conn, inbuf, outbuf, + size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return)); + END_PROFILE(NT_transact_query_security_desc); break; } @@ -3146,24 +3227,56 @@ static void handle_nttrans(connection_struct *conn, #ifdef HAVE_SYS_QUOTAS case NT_TRANSACT_GET_USER_QUOTA: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_get_user_quota); - outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, state->max_data_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_get_user_quota( + conn, inbuf, outbuf, + size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return)); + END_PROFILE(NT_transact_get_user_quota); break; } case NT_TRANSACT_SET_USER_QUOTA: { + char *inbuf, *outbuf; + int size, bufsize; + START_PROFILE(NT_transact_set_user_quota); - outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, state->max_data_return); + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, + &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBnttrans); + return; + } + + reply_post_legacy( + req, + call_nt_transact_set_user_quota( + conn, inbuf, outbuf, + size, bufsize, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return)); + END_PROFILE(NT_transact_set_user_quota); break; } @@ -3176,7 +3289,6 @@ static void handle_nttrans(connection_struct *conn, reply_doserror(req, ERRSRV, ERRerror); return; } - reply_post_legacy(req, outsize); return; } -- cgit From 8590265e94dbe6a2f970c80d09e4063bed12bb9d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 19:03:52 +0000 Subject: r24381: Push reply_prep_legacy into call_nt_transact_create (This used to be commit ca18ba96be84ed12003af84c53cc5f2e92fcc984) --- source3/smbd/nttrans.c | 166 +++++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 68 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fd3d8b462b..729ff72650 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1283,10 +1283,12 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ -static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static void call_nt_transact_create(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count, + uint32 max_data_count) { pstring fname; char *params = *ppparams; @@ -1317,24 +1319,35 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o char *pdata = NULL; NTSTATUS status; size_t param_len; - struct smb_request req; struct case_semantics_state *case_state = NULL; + char *inbuf, *outbuf; + int length, bufsize; + DEBUG(5,("call_nt_transact_create\n")); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + /* * If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { - return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, - bufsize, + reply_post_legacy( + req, + do_nt_transact_create_pipe( + conn, inbuf, outbuf, length, bufsize, ppsetup, setup_count, ppparams, parameter_count, - ppdata, data_count); + ppdata, data_count)); + return; } else { - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } } @@ -1344,11 +1357,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(parameter_count < 54) { DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } - init_smb_request(&req, (uint8 *)inbuf); - flags = IVAL(params,0); access_mask = IVAL(params,8); file_attributes = IVAL(params,20); @@ -1365,25 +1377,29 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) { DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n", (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count )); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (ea_len) { if (!lp_ea_support(SNUM(conn))) { DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n", (unsigned int)ea_len )); - return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); + return; } if (ea_len < 10) { DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n", (unsigned int)ea_len )); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } } if (create_options & FILE_OPEN_BY_FILE_ID) { - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + return; } /* @@ -1398,7 +1414,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o size_t dir_name_len; if(!dir_fsp) { - return ERROR_DOS(ERRDOS,ERRbadfid); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } if(!dir_fsp->is_directory) { @@ -1407,7 +1424,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* @@ -1415,10 +1433,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ if( is_ntfs_stream_name(fname)) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + reply_nterror(req, + NT_STATUS_OBJECT_PATH_NOT_FOUND); + return; } - return ERROR_DOS(ERRDOS,ERRbadfid); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } /* @@ -1444,7 +1465,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } pstrcat(fname, tmpname); } @@ -1453,7 +1475,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* @@ -1461,7 +1484,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ if( is_ntfs_stream_name(fname)) { - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); + return; } } @@ -1487,21 +1511,26 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* All file access must go through check_name() */ status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* This is the correct thing to do (check every time) but can_delete is @@ -1519,7 +1548,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || !can_delete_file_in_directory(conn, fname)) { TALLOC_FREE(case_state); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; } } @@ -1529,7 +1559,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o !user_has_privileges(current_user.nt_user_token, &se_security)) { TALLOC_FREE(case_state); - return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); + reply_nterror(req, NT_STATUS_PRIVILEGE_NOT_HELD); + return; } #endif @@ -1541,7 +1572,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o ea_len); if (!ea_list ) { TALLOC_FREE(case_state); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } } @@ -1554,7 +1586,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { TALLOC_FREE(case_state); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } /* @@ -1564,7 +1597,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o */ oplock_request = 0; - status = open_directory(conn, &req, fname, &sbuf, + status = open_directory(conn, req, fname, &sbuf, access_mask, share_access, create_disposition, @@ -1573,7 +1606,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o &info, &fsp); if(!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); - return ERROR_NT(status); + reply_nterror(req, status); + return; } } else { @@ -1582,7 +1616,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Ordinary file case. */ - status = open_file_ntcreate(conn,&req,fname,&sbuf, + status = open_file_ntcreate(conn,req,fname,&sbuf, access_mask, share_access, create_disposition, @@ -1601,11 +1635,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (create_options & FILE_NON_DIRECTORY_FILE) { TALLOC_FREE(case_state); - return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); + reply_force_nterror( + req, + NT_STATUS_FILE_IS_A_DIRECTORY); + return; } oplock_request = 0; - status = open_directory(conn, &req, fname, + status = open_directory(conn, req, fname, &sbuf, access_mask, share_access, @@ -1615,15 +1652,17 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o &info, &fsp); if(!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); - return ERROR_NT(status); + reply_nterror(req, status); + return; } } else { TALLOC_FREE(case_state); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - return -1; + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } } } @@ -1651,7 +1690,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o talloc_destroy(ctx); close_file(fsp,ERROR_CLOSE); TALLOC_FREE(case_state); - return ERROR_NT(status); + reply_nterror(req, status); + return; } fsp->access_mask = saved_access_mask; } @@ -1661,7 +1701,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (!NT_STATUS_IS_OK(status)) { close_file(fsp,ERROR_CLOSE); TALLOC_FREE(case_state); - return ERROR_NT(status); + reply_nterror(req, status); + return; } } @@ -1674,7 +1715,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } if (!fsp->is_directory && (fattr & aDIR)) { close_file(fsp,ERROR_CLOSE); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } /* Save the requested allocation size. */ @@ -1688,11 +1730,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (fsp->is_directory) { close_file(fsp,ERROR_CLOSE); /* Can't set allocation size on a directory. */ - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,ERROR_CLOSE); - return ERROR_NT(NT_STATUS_DISK_FULL); + reply_nterror(req, NT_STATUS_DISK_FULL); + return; } } else { fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); @@ -1722,7 +1766,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } params = nttrans_realloc(ppparams, param_len); if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } p = params; @@ -1793,9 +1838,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies_new(req, NT_STATUS_OK, params, param_len, *ppdata, 0); - return -1; + return; } /**************************************************************************** @@ -3059,28 +3104,13 @@ static void handle_nttrans(connection_struct *conn, switch(state->call) { case NT_TRANSACT_CREATE: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_create); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_create( - conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return)); - + call_nt_transact_create( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(NT_transact_create); break; } -- cgit From 89f27bb35b023472d2ab01f47050ad05b91bd35a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 19:22:07 +0000 Subject: r24382: Remove reply_prep_legacy from call_nt_transact_create (This used to be commit 73392485f4c3bf8b4138b500b4882c492bf96358) --- source3/smbd/nttrans.c | 117 ++++++++++++++----------------------------------- 1 file changed, 34 insertions(+), 83 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 729ff72650..c8914132cc 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -339,57 +339,11 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx } /**************************************************************************** - Reply to an NT create and X call on a pipe -- this will die when all - callers are converted to nt_open_pipe_new + Reply to an NT create and X call on a pipe ****************************************************************************/ -static int nt_open_pipe(char *fname, connection_struct *conn, - char *inbuf, char *outbuf, int *ppnum) -{ - smb_np_struct *p = NULL; - uint16 vuid = SVAL(inbuf, smb_uid); - int i; - - DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); - - /* See if it is one we want to handle. */ - - if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) { - return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); - } - - for( i = 0; known_nt_pipes[i]; i++ ) { - if( strequal(fname,known_nt_pipes[i])) { - break; - } - } - - if ( known_nt_pipes[i] == NULL ) { - return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); - } - - /* Strip \\ off the name. */ - fname++; - - DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); - - p = open_rpc_pipe_p(fname, conn, vuid); - if (!p) { - return(ERROR_DOS(ERRSRV,ERRnofids)); - } - - /* TODO: Add pipe to db */ - - if ( !store_pipe_opendb( p ) ) { - DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname)); - } - - *ppnum = p->pnum; - return 0; -} - -static void nt_open_pipe_new(char *fname, connection_struct *conn, - struct smb_request *req, int *ppnum) +static void nt_open_pipe(char *fname, connection_struct *conn, + struct smb_request *req, int *ppnum) { smb_np_struct *p = NULL; int i; @@ -452,7 +406,7 @@ static void do_ntcreate_pipe_open(connection_struct *conn, srvstr_pull_buf((char *)req->inbuf, req->flags2, fname, smb_buf(req->inbuf), sizeof(fname), STR_TERMINATE); - nt_open_pipe_new(fname, conn, req, &pnum); + nt_open_pipe(fname, conn, req, &pnum); if (req->outbuf) { /* error reply */ @@ -1098,14 +1052,14 @@ void reply_ntcreate_and_X(connection_struct *conn, Reply to a NT_TRANSACT_CREATE call to open a pipe. ****************************************************************************/ -static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count) +static void do_nt_transact_create_pipe(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { pstring fname; char *params = *ppparams; - int ret; int pnum = -1; char *p = NULL; NTSTATUS status; @@ -1118,20 +1072,25 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha if(parameter_count < 54) { DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count)); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } flags = IVAL(params,0); - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53, + srvstr_get_path(params, req->flags2, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } - if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { - return ret; + nt_open_pipe(fname, conn, req, &pnum); + + if (req->outbuf) { + /* Error return */ + return; } /* Realloc the size of parameters and data we will return */ @@ -1143,7 +1102,8 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha } params = nttrans_realloc(ppparams, param_len); if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } p = params; @@ -1178,9 +1138,9 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies_new(req, NT_STATUS_OK, params, param_len, *ppdata, 0); - return -1; + return; } /**************************************************************************** @@ -1321,29 +1281,19 @@ static void call_nt_transact_create(connection_struct *conn, size_t param_len; struct case_semantics_state *case_state = NULL; - char *inbuf, *outbuf; - int length, bufsize; - DEBUG(5,("call_nt_transact_create\n")); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - /* * If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { - reply_post_legacy( - req, - do_nt_transact_create_pipe( - conn, inbuf, outbuf, length, bufsize, - ppsetup, setup_count, - ppparams, parameter_count, - ppdata, data_count)); + do_nt_transact_create_pipe( + conn, req, + ppsetup, setup_count, + ppparams, parameter_count, + ppdata, data_count); return; } else { reply_doserror(req, ERRDOS, ERRnoaccess); @@ -1419,7 +1369,7 @@ static void call_nt_transact_create(connection_struct *conn, } if(!dir_fsp->is_directory) { - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, + srvstr_get_path(params, req->flags2, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); @@ -1460,7 +1410,7 @@ static void call_nt_transact_create(connection_struct *conn, { pstring tmpname; - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), tmpname, + srvstr_get_path(params, req->flags2, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status); @@ -1471,7 +1421,7 @@ static void call_nt_transact_create(connection_struct *conn, pstrcat(fname, tmpname); } } else { - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53, + srvstr_get_path(params, req->flags2, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -1507,7 +1457,8 @@ static void call_nt_transact_create(connection_struct *conn, file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1657,7 +1608,7 @@ static void call_nt_transact_create(connection_struct *conn, } } else { TALLOC_FREE(case_state); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ return; } -- cgit From 89dfa3883f0f4766af33f880a331512ec6970a7d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 19:58:28 +0000 Subject: r24383: Convert call_nt_transact_ioctl to the new API (This used to be commit 8e6485e0782e9ab31b07dd9f662bd845f58faf4a) --- source3/smbd/nttrans.c | 107 +++++++++++++++++++++++++------------------------ source3/smbd/reply.c | 16 ++++++++ 2 files changed, 71 insertions(+), 52 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c8914132cc..8e6c76571a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2402,10 +2402,12 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb Reply to NT IOCTL ****************************************************************************/ -static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static void call_nt_transact_ioctl(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count, + uint32 max_data_count) { uint32 function; uint16 fidnum; @@ -2417,7 +2419,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou if (setup_count != 8) { DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count)); - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + return; } function = IVAL(*ppsetup, 0); @@ -2440,9 +2443,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou so we can know if we need to pre-allocate or not */ DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, - 0); - return -1; + send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); + return; case FSCTL_CREATE_OR_GET_OBJECT_ID: { @@ -2454,18 +2456,22 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum)); - FSP_BELONGS_CONN(fsp, conn); + if (!fsp_belongs_conn(conn, req, fsp, ¤t_user)) { + return; + } data_count = 64; pdata = nttrans_realloc(ppdata, data_count); if (pdata == NULL) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } push_file_id_16(pdata, &fsp->file_id); memcpy(pdata+16,create_volume_objectid(conn,objid),16); push_file_id_16(pdata+32, &fsp->file_id); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); - return -1; + send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, + pdata, data_count); + return; } case FSCTL_GET_REPARSE_POINT: @@ -2474,7 +2480,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT); + reply_nterror(req, NT_STATUS_NOT_A_REPARSE_POINT); + return; case FSCTL_SET_REPARSE_POINT: /* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case. @@ -2482,7 +2489,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); - return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT); + reply_nterror(req, NT_STATUS_NOT_A_REPARSE_POINT); + return; case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ { @@ -2503,12 +2511,15 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou uint32 i; char *cur_pdata; - FSP_BELONGS_CONN(fsp,conn); + if (!fsp_belongs_conn(conn, req, fsp, ¤t_user)) { + return; + } if (max_data_count < 16) { DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n", max_data_count)); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (max_data_count > 16) { @@ -2518,14 +2529,16 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou shadow_mem_ctx = talloc_init("SHADOW_COPY_DATA"); if (shadow_mem_ctx == NULL) { DEBUG(0,("talloc_init(SHADOW_COPY_DATA) failed!\n")); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA); if (shadow_data == NULL) { DEBUG(0,("TALLOC_ZERO() failed!\n")); talloc_destroy(shadow_mem_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } shadow_data->mem_ctx = shadow_mem_ctx; @@ -2538,11 +2551,13 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou if (errno == ENOSYS) { DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", conn->connectpath)); - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); + return; } else { DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n", conn->connectpath)); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + reply_nterror(req, NT_STATUS_UNSUCCESSFUL); + return; } } @@ -2558,13 +2573,15 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n", max_data_count,data_count)); talloc_destroy(shadow_data->mem_ctx); - return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); + reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); + return; } pdata = nttrans_realloc(ppdata, data_count); if (pdata == NULL) { talloc_destroy(shadow_data->mem_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } cur_pdata = pdata; @@ -2586,7 +2603,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou shadow_data->num_volumes,fsp->fsp_name)); if (labels && shadow_data->labels) { for (i=0;inum_volumes;i++) { - srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + srvstr_push(pdata, req->flags2, cur_pdata, shadow_data->labels[i], 2*sizeof(SHADOW_COPY_LABEL), STR_UNICODE|STR_TERMINATE); @@ -2597,10 +2614,10 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou talloc_destroy(shadow_data->mem_ctx); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, - pdata, data_count); + send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, + pdata, data_count); - return -1; + return; } case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */ @@ -2617,7 +2634,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum)); - FSP_BELONGS_CONN(fsp,conn); + if (!fsp_belongs_conn(conn, req, fsp, ¤t_user)) { + return; + } /* unknown 4 bytes: this is not the length of the sid :-( */ /*unknown = IVAL(pdata,0);*/ @@ -2650,9 +2669,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou */ /* this works for now... */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, - NULL, 0); - return -1; + send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); + return; } default: if (!logged_message) { @@ -2662,7 +2680,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou } } - return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + reply_nterror(req, NT_STATUS_NOT_SUPPORTED); } @@ -3068,28 +3086,13 @@ static void handle_nttrans(connection_struct *conn, case NT_TRANSACT_IOCTL: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_ioctl); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_ioctl( - conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return)); - + call_nt_transact_ioctl( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(NT_transact_ioctl); break; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 26ddde7a65..ea86cd03d8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -311,6 +311,22 @@ BOOL check_fsp(connection_struct *conn, struct smb_request *req, return True; } +/**************************************************************************** + Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro +****************************************************************************/ + +BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req, + files_struct *fsp, struct current_user *user) +{ + if ((fsp) && (conn) && ((conn)==(fsp)->conn) + && (current_user.vuid==(fsp)->vuid)) { + return True; + } + + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return False; +} + /**************************************************************************** Reply to a (netbios-level) special message. ****************************************************************************/ -- cgit From ff355558e37cbc0863b1955d63463f39b8820335 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 19:59:00 +0000 Subject: r24384: Convert call_nt_transact_set_security_desc to the new API (This used to be commit 925ed1e186da594b5c40d3abbad885060ca87fd0) --- source3/smbd/nttrans.c | 55 +++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8e6c76571a..e474c9a3b6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2356,10 +2356,15 @@ security descriptor.\n")); Reply to set a security descriptor. Map to UNIX perms or POSIX ACLs. ****************************************************************************/ -static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static void call_nt_transact_set_security_desc(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, + uint32 setup_count, + char **ppparams, + uint32 parameter_count, + char **ppdata, + uint32 data_count, + uint32 max_data_count) { char *params= *ppparams; char *data = *ppdata; @@ -2368,11 +2373,13 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb NTSTATUS nt_status; if(parameter_count < 8) { - return ERROR_DOS(ERRDOS,ERRbadfunc); + reply_doserror(req, ERRDOS, ERRbadfunc); + return; } if((fsp = file_fsp(SVAL(params,0))) == NULL) { - return ERROR_DOS(ERRDOS,ERRbadfid); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } if(!lp_nt_acl_support(SNUM(conn))) { @@ -2385,17 +2392,19 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb (unsigned int)security_info_sent )); if (data_count == 0) { - return ERROR_DOS(ERRDOS, ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) { - return ERROR_NT(nt_status); + reply_nterror(req, nt_status); + return; } done: - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); - return -1; + send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); + return; } /**************************************************************************** @@ -3099,27 +3108,13 @@ static void handle_nttrans(connection_struct *conn, case NT_TRANSACT_SET_SECURITY_DESC: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_set_security_desc); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_set_security_desc( - conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return)); + call_nt_transact_set_security_desc( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(NT_transact_set_security_desc); break; } -- cgit From 6624bf7fd28d20fab0becb7140627b88c24456ce Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Aug 2007 20:16:33 +0000 Subject: r24385: Convert call_nt_transact_query_security_desc to the new API (This used to be commit f44e0aac2b47ea377c2ce701426e57ee15c42fe7) --- source3/smbd/nttrans.c | 73 ++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e474c9a3b6..53ba37bafd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2239,10 +2239,15 @@ static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) Reply to query a security descriptor. ****************************************************************************/ -static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static void call_nt_transact_query_security_desc(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, + uint32 setup_count, + char **ppparams, + uint32 parameter_count, + char **ppdata, + uint32 data_count, + uint32 max_data_count) { char *params = *ppparams; char *data = *ppdata; @@ -2254,12 +2259,14 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i files_struct *fsp = NULL; if(parameter_count < 8) { - return ERROR_DOS(ERRDOS,ERRbadfunc); + reply_doserror(req, ERRDOS, ERRbadfunc); + return; } fsp = file_fsp(SVAL(params,0)); if(!fsp) { - return ERROR_DOS(ERRDOS,ERRbadfid); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } security_info_wanted = IVAL(params,4); @@ -2269,12 +2276,14 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i params = nttrans_realloc(ppparams, 4); if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) { DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } /* @@ -2289,7 +2298,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i if (sd_size == 0) { talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + reply_unixerror(req, ERRDOS, ERRnoaccess); + return; } DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); @@ -2298,10 +2308,10 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i if(max_data_count < sd_size) { - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL, - params, 4, *ppdata, 0); + send_nt_replies_new(req, NT_STATUS_BUFFER_TOO_SMALL, + params, 4, *ppdata, 0); talloc_destroy(mem_ctx); - return -1; + return; } /* @@ -2311,7 +2321,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i data = nttrans_realloc(ppdata, sd_size); if(data == NULL) { talloc_destroy(mem_ctx); - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } /* @@ -2338,7 +2349,8 @@ security descriptor.\n")); * Return access denied for want of a better error message.. */ talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + reply_unixerror(req, ERRDOS, ERRnoaccess); + return; } /* @@ -2347,9 +2359,9 @@ security descriptor.\n")); talloc_destroy(mem_ctx); - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, - (int)sd_size); - return -1; + send_nt_replies_new(req, NT_STATUS_OK, params, 4, data, + (int)sd_size); + return; } /**************************************************************************** @@ -3177,28 +3189,13 @@ static void handle_nttrans(connection_struct *conn, case NT_TRANSACT_QUERY_SECURITY_DESC: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_query_security_desc); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_query_security_desc( - conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return)); - + call_nt_transact_query_security_desc( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(NT_transact_query_security_desc); break; } -- cgit From 5cc0a6b43c32f2a118c0b7995a74c99ccca6ca64 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Aug 2007 20:29:24 +0000 Subject: r24386: Piss off Volker (not deliberately) by checking in a reply_mknew -> conversion. Sorry vl, remove one of your 15 patches :-). Jeremy. (This used to be commit a7648ed9d40d6f61362e1488dc30216363870694) --- source3/smbd/process.c | 4 +-- source3/smbd/reply.c | 84 +++++++++++++++++++++++++++++++------------------- 2 files changed, 54 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 93c6be8c2f..96945e0748 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -693,7 +693,7 @@ static const struct smb_message_struct { /* 0x00 */ { "SMBmkdir",NULL,reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",NULL,reply_rmdir,AS_USER | NEED_WRITE}, /* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, -/* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, +/* 0x03 */ { "SMBcreate",NULL,reply_mknew,AS_USER}, /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, /* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER}, /* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE }, @@ -705,7 +705,7 @@ static const struct smb_message_struct { /* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, /* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER }, -/* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER}, +/* 0x0f */ { "SMBmknew",NULL,reply_mknew,AS_USER}, /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, /* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR}, /* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ea86cd03d8..48b100764a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1750,61 +1750,76 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req) Reply to a mknew or a create. ****************************************************************************/ -int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_mknew(connection_struct *conn, struct smb_request *req) { pstring fname; int com; - int outsize = 0; - uint32 fattr = SVAL(inbuf,smb_vwv0); + uint32 fattr = 0; struct timespec ts[2]; files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + int oplock_request = 0; SMB_STRUCT_STAT sbuf; NTSTATUS status; uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE; uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; uint32 create_disposition; uint32 create_options = 0; - struct smb_request req; START_PROFILE(SMBcreate); - init_smb_request(&req, (uint8 *)inbuf); - - com = SVAL(inbuf,smb_com); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBcreate); + return; + } - ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */ + fattr = SVAL(req->inbuf,smb_vwv0); + oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); + com = SVAL(req->inbuf,smb_com); - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1, - sizeof(fname), 0, STR_TERMINATE, &status); + ts[1] =convert_time_t_to_timespec( + srv_make_unix_date3(req->inbuf + smb_vwv1)); + /* mtime. */ + + srvstr_get_path((char *)req->inbuf, req->flags2, fname, + smb_buf(req->inbuf) + 1, sizeof(fname), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcreate); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcreate); - return ERROR_NT(status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcreate); - return ERROR_NT(status); + return; } if (fattr & aVOLID) { - DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); + DEBUG(0,("Attempt to create file (%s) with volid set - " + "please report this\n", fname)); } if(com == SMBmknew) { @@ -1816,7 +1831,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file using ntcreate. */ - status = open_file_ntcreate(conn, &req, fname, &sbuf, + status = open_file_ntcreate(conn, req, fname, &sbuf, access_mask, share_mode, create_disposition, @@ -1824,35 +1839,40 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, fattr, oplock_request, NULL, &fsp); - + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } - + ts[0] = get_atimespec(&sbuf); /* atime. */ file_ntimes(conn, fname, ts); - outsize = set_message(inbuf,outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); + reply_outbuf(req, 1, 0); + + SSVAL(req->outbuf,smb_vwv0,fsp->fnum); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf,smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf,smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - + DEBUG( 2, ( "reply_mknew: file %s\n", fname ) ); - DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) ); + DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", + fname, fsp->fh->fd, (unsigned int)fattr ) ); END_PROFILE(SMBcreate); - return(outsize); + return; } /**************************************************************************** -- cgit From d701a47c736b058af9308cfb031b9862948c86a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Aug 2007 01:45:26 +0000 Subject: r24387: Convert readbraw to the new api. Volker, keep checking in your patches please :-). I'll work on SMBreadBmpx tomorrow. Jeremy. (This used to be commit 27e183afa8d23dca6aada1f3810dc53aa8c55ccd) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 177 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 122 insertions(+), 57 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 96945e0748..7e499b7797 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -716,7 +716,7 @@ static const struct smb_message_struct { /* 0x17 */ { NULL, NULL, NULL, 0 }, /* 0x18 */ { NULL, NULL, NULL, 0 }, /* 0x19 */ { NULL, NULL, NULL, 0 }, -/* 0x1a */ { "SMBreadbraw",reply_readbraw,NULL,AS_USER}, +/* 0x1a */ { "SMBreadbraw",NULL,reply_readbraw,AS_USER}, /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER}, /* 0x1c */ { "SMBreadBs",NULL, NULL,0 }, /* 0x1d */ { "SMBwritebraw",reply_writebraw,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 48b100764a..43e702803f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -288,6 +288,7 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, Check if we have a correct fsp pointing to a file. Replacement for the CHECK_FSP macro. ****************************************************************************/ + BOOL check_fsp(connection_struct *conn, struct smb_request *req, files_struct *fsp, struct current_user *user) { @@ -2418,13 +2419,30 @@ static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, return (ssize_t)nread; } +/**************************************************************************** + Return a readbraw error (4 bytes of zero). +****************************************************************************/ + +static void reply_readbraw_error(void) +{ + char header[4]; + SIVAL(header,0,0); + if (write_data(smbd_server_fd(),header,4) != 4) { + fail_readraw(); + } +} + /**************************************************************************** Use sendfile in readbraw. ****************************************************************************/ -void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread, - ssize_t mincount, char *outbuf, int out_buffsize) +void send_file_readbraw(connection_struct *conn, + files_struct *fsp, + SMB_OFF_T startpos, + size_t nread, + ssize_t mincount) { + char *outbuf = NULL; ssize_t ret=0; #if defined(WITH_SENDFILE) @@ -2437,15 +2455,18 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st if ( (chain_size == 0) && (nread > 0) && (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) { - DATA_BLOB header; - - _smb_setlen(outbuf,nread); - header.data = (uint8 *)outbuf; - header.length = 4; - header.free = NULL; - - if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) { - /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ + char header[4]; + DATA_BLOB header_blob; + + _smb_setlen(header,nread); + header_blob.data = (uint8 *)header; + header_blob.length = 4; + header_blob.free = NULL; + + if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, + &header_blob, startpos, nread) == -1) { + /* Returning ENOSYS means no data at all was sent. + * Do this as a normal read. */ if (errno == ENOSYS) { goto normal_readbraw; } @@ -2479,6 +2500,14 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st normal_readbraw: + outbuf = TALLOC_ARRAY(NULL, char, nread+4); + if (!outbuf) { + DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n", + nread+4)); + reply_readbraw_error(); + return; + } + if (nread > 0) { ret = read_file(fsp,outbuf+4,startpos,nread); #if 0 /* mincount appears to be ignored in a W2K server. JRA. */ @@ -2493,23 +2522,34 @@ normal_readbraw: _smb_setlen(outbuf,ret); if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret) fail_readraw(); + + TALLOC_FREE(outbuf); } /**************************************************************************** Reply to a readbraw (core+ protocol). ****************************************************************************/ -int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize) +void reply_readbraw(connection_struct *conn, struct smb_request *req) { ssize_t maxcount,mincount; size_t nread = 0; SMB_OFF_T startpos; - char *header = outbuf; files_struct *fsp; + SMB_STRUCT_STAT st; + SMB_OFF_T size = 0; + START_PROFILE(SMBreadbraw); if (srv_is_signing_active()) { - exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + exit_server_cleanly("reply_readbraw: SMB signing is active - " + "raw reads/writes are disallowed."); + } + + if (req->wct < 8) { + reply_readbraw_error(); + END_PROFILE(SMBreadbraw); + return; } /* @@ -2518,32 +2558,49 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s * return a zero length response here. */ - fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!FNUM_OK(fsp,conn) || !fsp->can_read) { + /* + * We have to do a check_fsp by hand here, as + * we must always return 4 zero bytes on error, + * not a NTSTATUS. + */ + + if (!fsp || !conn || conn != fsp->conn || + current_user.vuid != fsp->vuid || + fsp->is_directory || fsp->fh->fd == -1) { /* * fsp could be NULL here so use the value from the packet. JRA. */ - DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0))); - _smb_setlen(header,0); - if (write_data(smbd_server_fd(),header,4) != 4) - fail_readraw(); + DEBUG(3,("reply_readbraw: fnum %d not valid " + "- cache prime?\n", + (int)SVAL(req->inbuf,smb_vwv0))); + reply_readbraw_error(); END_PROFILE(SMBreadbraw); - return(-1); + return; } - CHECK_FSP(fsp,conn); + /* Do a "by hand" version of CHECK_READ. */ + if (!(fsp->can_read || + ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) && + (fsp->access_mask & FILE_EXECUTE)))) { + DEBUG(3,("reply_readbraw: fnum %d not readable.\n", + (int)SVAL(req->inbuf,smb_vwv0))); + reply_readbraw_error(); + END_PROFILE(SMBreadbraw); + return; + } flush_write_cache(fsp, READRAW_FLUSH); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); - if(CVAL(inbuf,smb_wct) == 10) { + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1); + if(CVAL(req->inbuf,smb_wct) == 10) { /* * This is a large offset (64 bit) read. */ #ifdef LARGE_SMB_OFF_T - startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32); + startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32); #else /* !LARGE_SMB_OFF_T */ @@ -2551,46 +2608,51 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s * Ensure we haven't been sent a >32 bit offset. */ - if(IVAL(inbuf,smb_vwv8) != 0) { - DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ -64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) )); - _smb_setlen(header,0); - if (write_data(smbd_server_fd(),header,4) != 4) - fail_readraw(); + if(IVAL(req->inbuf,smb_vwv8) != 0) { + DEBUG(0,("reply_readbraw: large offset " + "(%x << 32) used and we don't support " + "64 bit offsets.\n", + (unsigned int)IVAL(req->inbuf,smb_vwv8) )); + reply_readbraw_error(); END_PROFILE(SMBreadbraw); - return(-1); + return; } #endif /* LARGE_SMB_OFF_T */ if(startpos < 0) { - DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos )); - _smb_setlen(header,0); - if (write_data(smbd_server_fd(),header,4) != 4) - fail_readraw(); + DEBUG(0,("reply_readbraw: negative 64 bit " + "readraw offset (%.0f) !\n", + (double)startpos )); + reply_readbraw_error(); END_PROFILE(SMBreadbraw); - return(-1); + return; } } - maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); - mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); + + maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF); + mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF); /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); - if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { - SMB_STRUCT_STAT st; - SMB_OFF_T size = 0; - - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { - size = st.st_size; - } + if (is_locked(fsp,(uint32)req->smbpid, + (SMB_BIG_UINT)maxcount, + (SMB_BIG_UINT)startpos, + READ_LOCK)) { + reply_readbraw_error(); + END_PROFILE(SMBreadbraw); + return; + } - if (startpos >= size) { - nread = 0; - } else { - nread = MIN(maxcount,(size - startpos)); - } + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { + size = st.st_size; + } + + if (startpos >= size) { + nread = 0; + } else { + nread = MIN(maxcount,(size - startpos)); } #if 0 /* mincount appears to be ignored in a W2K server. JRA. */ @@ -2598,14 +2660,17 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s nread = 0; #endif - DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos, - (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) ); + DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu " + "min=%lu nread=%lu\n", + fsp->fnum, (double)startpos, + (unsigned long)maxcount, + (unsigned long)mincount, + (unsigned long)nread ) ); - send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize); + send_file_readbraw(conn, fsp, startpos, nread, mincount); - DEBUG(5,("readbraw finished\n")); + DEBUG(5,("reply_readbraw finished\n")); END_PROFILE(SMBreadbraw); - return -1; } #undef DBGC_CLASS -- cgit From 4b485d807ef9ddd761ff9d9f15fce2882bf5d9f1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 05:58:13 +0000 Subject: r24391: Convert call_nt_transact_get_user_quota to the new API (This used to be commit 0e47a6643e9b3f546e1905e5152d3abe2511bcd9) --- source3/smbd/nttrans.c | 88 ++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 43 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 53ba37bafd..9d06795637 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2710,10 +2710,15 @@ static void call_nt_transact_ioctl(connection_struct *conn, Reply to get user quota ****************************************************************************/ -static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static void call_nt_transact_get_user_quota(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, + uint32 setup_count, + char **ppparams, + uint32 parameter_count, + char **ppdata, + uint32 data_count, + uint32 max_data_count) { NTSTATUS nt_status = NT_STATUS_OK; char *params = *ppparams; @@ -2737,7 +2742,8 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, if (current_user.ut.uid != 0) { DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } /* @@ -2746,14 +2752,16 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, if (parameter_count < 4) { DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",parameter_count)); - return ERROR_DOS(ERRDOS,ERRinvalidparam); + reply_doserror(req, ERRDOS, ERRinvalidparam); + return; } /* maybe we can check the quota_fnum */ fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } /* the NULL pointer checking for fsp->fake_file_handle->pd @@ -2779,7 +2787,8 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, param_len = 4; params = nttrans_realloc(ppparams, param_len); if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } data_len = 0; @@ -2797,14 +2806,17 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, start_enum = True; } - if (start_enum && vfs_get_user_ntquota_list(fsp,&(qt_handle->quota_list))!=0) - return ERROR_DOS(ERRSRV,ERRerror); + if (start_enum && vfs_get_user_ntquota_list(fsp,&(qt_handle->quota_list))!=0) { + reply_doserror(req, ERRSRV, ERRerror); + return; + } /* Realloc the size of parameters and data we will return */ param_len = 4; params = nttrans_realloc(ppparams, param_len); if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } /* we should not trust the value in max_data_count*/ @@ -2812,7 +2824,8 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/ if(pdata == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } entry = pdata; @@ -2873,18 +2886,21 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, if (data_count < 8) { DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8)); - return ERROR_DOS(ERRDOS,ERRunknownlevel); + reply_doserror(req, ERRDOS, ERRunknownlevel); + return; } sid_len = IVAL(pdata,4); /* Ensure this is less than 1mb. */ if (sid_len > (1024*1024)) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } if (data_count < 8+sid_len) { DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len))); - return ERROR_DOS(ERRDOS,ERRunknownlevel); + reply_doserror(req, ERRDOS, ERRunknownlevel); + return; } data_len = 4+40+sid_len; @@ -2914,12 +2930,14 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, param_len = 4; params = nttrans_realloc(ppparams, param_len); if(params == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } pdata = nttrans_realloc(ppdata, data_len); if(pdata == NULL) { - return ERROR_DOS(ERRDOS,ERRnomem); + reply_doserror(req, ERRDOS, ERRnomem); + return; } entry = pdata; @@ -2952,14 +2970,13 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, default: DEBUG(0,("do_nt_transact_get_user_quota: fnum %d unknown level 0x%04hX\n",fsp->fnum,level)); - return ERROR_DOS(ERRSRV,ERRerror); + reply_doserror(req, ERRSRV, ERRerror); + return; break; } - send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len, - pdata, data_len); - - return -1; + send_nt_replies_new(req, nt_status, params, param_len, + pdata, data_len); } /**************************************************************************** @@ -3203,28 +3220,13 @@ static void handle_nttrans(connection_struct *conn, #ifdef HAVE_SYS_QUOTAS case NT_TRANSACT_GET_USER_QUOTA: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_get_user_quota); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_get_user_quota( - conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return)); - + call_nt_transact_get_user_quota( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(NT_transact_get_user_quota); break; } -- cgit From 3038f27a5916b650b024e60bf9ff3decd7378505 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 06:18:55 +0000 Subject: r24392: Minor simplifications (This used to be commit 96a943587418e07019974b45c368e749a5ef82c2) --- source3/smbd/reply.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 43e702803f..826306c883 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2459,9 +2459,7 @@ void send_file_readbraw(connection_struct *conn, DATA_BLOB header_blob; _smb_setlen(header,nread); - header_blob.data = (uint8 *)header; - header_blob.length = 4; - header_blob.free = NULL; + header_blob = data_blob_const(header, 4); if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header_blob, startpos, nread) == -1) { @@ -2594,7 +2592,7 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req) flush_write_cache(fsp, READRAW_FLUSH); startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1); - if(CVAL(req->inbuf,smb_wct) == 10) { + if(req->wct == 10) { /* * This is a large offset (64 bit) read. */ -- cgit From 4f111b6e784c404cb8b11ae975b88caabb441ccc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 06:21:02 +0000 Subject: r24393: Convert call_nt_transact_set_user_quota to the new API (This used to be commit 4cb60abd4c7f32a51f0e9be0d226fe09c794bed8) --- source3/smbd/nttrans.c | 73 ++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9d06795637..1ca8e01802 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2983,10 +2983,15 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, Reply to set user quota ****************************************************************************/ -static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static void call_nt_transact_set_user_quota(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, + uint32 setup_count, + char **ppparams, + uint32 parameter_count, + char **ppdata, + uint32 data_count, + uint32 max_data_count) { char *params = *ppparams; char *pdata = *ppdata; @@ -3002,7 +3007,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, if (current_user.ut.uid != 0) { DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)),conn->user)); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } /* @@ -3011,19 +3017,22 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, if (parameter_count < 2) { DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count)); - return ERROR_DOS(ERRDOS,ERRinvalidparam); + reply_doserror(req, ERRDOS, ERRinvalidparam); + return; } /* maybe we can check the quota_fnum */ fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } if (data_count < 40) { DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40)); - return ERROR_DOS(ERRDOS,ERRunknownlevel); + reply_doserror(req, ERRDOS, ERRunknownlevel); + return; } /* offset to next quota record. @@ -3036,7 +3045,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, if (data_count < 40+sid_len) { DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data\n",data_count,(unsigned long)40+sid_len)); - return ERROR_DOS(ERRDOS,ERRunknownlevel); + reply_doserror(req, ERRDOS, ERRunknownlevel); + return; } /* unknown 8 bytes in pdata @@ -3052,7 +3062,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, ((qt.usedspace != 0xFFFFFFFF)|| (IVAL(pdata,20)!=0xFFFFFFFF))) { /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + reply_doserror(req, ERRDOS, ERRunknownlevel); + return; } #endif /* LARGE_SMB_OFF_T */ @@ -3065,7 +3076,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, ((qt.softlim != 0xFFFFFFFF)|| (IVAL(pdata,28)!=0xFFFFFFFF))) { /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + reply_doserror(req, ERRDOS, ERRunknownlevel); + return; } #endif /* LARGE_SMB_OFF_T */ @@ -3078,7 +3090,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, ((qt.hardlim != 0xFFFFFFFF)|| (IVAL(pdata,36)!=0xFFFFFFFF))) { /* more than 32 bits? */ - return ERROR_DOS(ERRDOS,ERRunknownlevel); + reply_doserror(req, ERRDOS, ERRunknownlevel); + return; } #endif /* LARGE_SMB_OFF_T */ @@ -3088,13 +3101,12 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, /* 44 unknown bytes left... */ if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) { - return ERROR_DOS(ERRSRV,ERRerror); + reply_doserror(req, ERRSRV, ERRerror); + return; } - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, - pdata, data_len); - - return -1; + send_nt_replies_new(req, NT_STATUS_OK, params, param_len, + pdata, data_len); } #endif /* HAVE_SYS_QUOTAS */ @@ -3233,28 +3245,13 @@ static void handle_nttrans(connection_struct *conn, case NT_TRANSACT_SET_USER_QUOTA: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_set_user_quota); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_set_user_quota( - conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return)); - + call_nt_transact_set_user_quota( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(NT_transact_set_user_quota); break; } -- cgit From bba684f2c0c40c58fcc263eb6794c389760d0d44 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 06:52:30 +0000 Subject: r24394: Convert call_nt_transact_rename to the new API (This used to be commit 189876a664efcfb601a8b14c21f272ed7d9f6b41) --- source3/smbd/nttrans.c | 65 +++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1ca8e01802..970703a2d6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2167,10 +2167,12 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, Reply to an NT transact rename command. ****************************************************************************/ -static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, uint32 parameter_count, - char **ppdata, uint32 data_count, uint32 max_data_count) +static void call_nt_transact_rename(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count, + uint32 max_data_count) { char *params = *ppparams; pstring new_name; @@ -2178,44 +2180,46 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o BOOL replace_if_exists = False; BOOL dest_has_wcard = False; NTSTATUS status; - struct smb_request req; - - init_smb_request(&req, (uint8 *)inbuf); if(parameter_count < 5) { - return ERROR_DOS(ERRDOS,ERRbadfunc); + reply_doserror(req, ERRDOS, ERRbadfunc); + return; } fsp = file_fsp(SVAL(params, 0)); replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; - CHECK_FSP(fsp, conn); - srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), new_name, params+4, + if (!check_fsp(conn, req, fsp, ¤t_user)) { + return; + } + srvstr_get_path_wcard(params, req->flags2, new_name, params+4, sizeof(new_name), parameter_count - 4, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + return; } - status = rename_internals(conn, &req, fsp->fsp_name, + status = rename_internals(conn, req, fsp->fsp_name, new_name, 0, replace_if_exists, False, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + return; } - return ERROR_NT(status); + reply_nterror(req, status); + return; } /* * Rename was successful. */ - send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); - return -1; + return; } /****************************************************************************** @@ -3190,28 +3194,13 @@ static void handle_nttrans(connection_struct *conn, case NT_TRANSACT_RENAME: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_rename); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_rename( - conn, inbuf, outbuf, - size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return)); - + call_nt_transact_rename( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return); END_PROFILE(NT_transact_rename); break; } -- cgit From b41b38031f8eeec916e0e5f9fb80cd8ecd5e22cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 07:39:11 +0000 Subject: r24398: Convert call_nt_transact_notify_change to the new API (This used to be commit 607b3ab8bc6052770f0324b57f3db6e1c11a7005) --- source3/smbd/notify.c | 16 +++++------ source3/smbd/nttrans.c | 72 ++++++++++++++++++++++---------------------------- 2 files changed, 39 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6c77f4c270..8474ca6446 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -24,7 +24,7 @@ struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ - char request_buf[smb_size]; + uint8 request_buf[smb_size]; uint32 filter; uint32 max_param; struct notify_mid_map *mid_map; @@ -128,14 +128,14 @@ static BOOL notify_marshall_changes(int num_changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(const char *request_buf, +static void change_notify_reply_packet(const uint8 *request_buf, NTSTATUS error_code) { - const char *inbuf = request_buf; + const char *inbuf = (char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(request_buf, outbuf); + construct_reply_common(inbuf, outbuf); ERROR_NT(error_code); @@ -151,7 +151,7 @@ static void change_notify_reply_packet(const char *request_buf, "failed."); } -void change_notify_reply(const char *request_buf, uint32 max_param, +void change_notify_reply(const uint8 *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { char *outbuf = NULL; @@ -183,9 +183,9 @@ void change_notify_reply(const char *request_buf, uint32 max_param, goto done; } - construct_reply_common(request_buf, outbuf); + construct_reply_common((char *)request_buf, outbuf); - if (send_nt_replies(request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + if (send_nt_replies((char *)request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0) == -1) { exit_server("change_notify_reply_packet: send_smb failed."); } @@ -238,7 +238,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param, +NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, uint32 filter, BOOL recursive, struct files_struct *fsp) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 970703a2d6..401fdca929 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2071,15 +2071,15 @@ int reply_ntrename(connection_struct *conn, don't allow a directory to be opened. ****************************************************************************/ -static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, - char *outbuf, int length, - int bufsize, - uint16 **ppsetup, uint32 setup_count, - char **ppparams, - uint32 parameter_count, - char **ppdata, uint32 data_count, - uint32 max_data_count, - uint32 max_param_count) +static void call_nt_transact_notify_change(connection_struct *conn, + struct smb_request *req, + uint16 **ppsetup, + uint32 setup_count, + char **ppparams, + uint32 parameter_count, + char **ppdata, uint32 data_count, + uint32 max_data_count, + uint32 max_param_count) { uint16 *setup = *ppsetup; files_struct *fsp; @@ -2088,7 +2088,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, BOOL recursive; if(setup_count < 6) { - return ERROR_DOS(ERRDOS,ERRbadfunc); + reply_doserror(req, ERRDOS, ERRbadfunc); + return; } fsp = file_fsp(SVAL(setup,4)); @@ -2098,14 +2099,16 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, DEBUG(3,("call_nt_transact_notify_change\n")); if(!fsp) { - return ERROR_DOS(ERRDOS,ERRbadfid); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } { char *filter_string; if (!(filter_string = notify_filter_string(NULL, filter))) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + reply_nterror(req,NT_STATUS_NO_MEMORY); + return; } DEBUG(3,("call_nt_transact_notify_change: notify change " @@ -2116,7 +2119,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, } if((!fsp->is_directory) || (conn != fsp->conn)) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; } if (fsp->notify == NULL) { @@ -2126,7 +2130,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("change_notify_create returned %s\n", nt_errstr(status))); - return ERROR_NT(status); + reply_nterror(req, status); + return; } } @@ -2141,26 +2146,25 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, * here. */ - change_notify_reply(inbuf, max_param_count, fsp->notify); + change_notify_reply(req->inbuf, max_param_count, fsp->notify); /* * change_notify_reply() above has independently sent its * results */ - return -1; + return; } /* * No changes pending, queue the request */ - status = change_notify_add_request(inbuf, max_param_count, filter, + status = change_notify_add_request(req->inbuf, max_param_count, filter, recursive, fsp); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); } - - return -1; + return; } /**************************************************************************** @@ -3166,28 +3170,14 @@ static void handle_nttrans(connection_struct *conn, case NT_TRANSACT_NOTIFY_CHANGE: { - char *inbuf, *outbuf; - int size, bufsize; - START_PROFILE(NT_transact_notify_change); - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &size, - &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBnttrans); - return; - } - - reply_post_legacy( - req, - call_nt_transact_notify_change( - conn, inbuf, outbuf, size, bufsize, - &state->setup, state->setup_count, - &state->param, state->total_param, - &state->data, state->total_data, - state->max_data_return, - state->max_param_return)); - + call_nt_transact_notify_change( + conn, req, + &state->setup, state->setup_count, + &state->param, state->total_param, + &state->data, state->total_data, + state->max_data_return, + state->max_param_return); END_PROFILE(NT_transact_notify_change); break; } -- cgit From 6a5bdb79e136f8cf123e36070640244ad924b274 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 07:58:56 +0000 Subject: r24399: Change change_notify_reply to use send_nt_replies_new (This used to be commit be67bb50eef88f4d56f48e785c1e5865616f5f33) --- source3/smbd/notify.c | 17 ++++++----------- source3/smbd/nttrans.c | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 8474ca6446..144af093cf 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -154,9 +154,8 @@ static void change_notify_reply_packet(const uint8 *request_buf, void change_notify_reply(const uint8 *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { - char *outbuf = NULL; prs_struct ps; - size_t buflen; + struct smb_request *req = NULL; if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); @@ -176,22 +175,18 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } - buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; - - if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } - construct_reply_common((char *)request_buf, outbuf); + init_smb_request(req, request_buf); - if (send_nt_replies((char *)request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), - prs_offset(&ps), NULL, 0) == -1) { - exit_server("change_notify_reply_packet: send_smb failed."); - } + send_nt_replies_new(req, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0); done: - SAFE_FREE(outbuf); + TALLOC_FREE(req); prs_mem_free(&ps); TALLOC_FREE(notify_buf->changes); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 401fdca929..881378c924 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -67,7 +67,7 @@ static char *nttrans_realloc(char **ptr, size_t size) HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -int send_nt_replies(const char *inbuf, +static int send_nt_replies(const char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, -- cgit From 52a738301aae2b646ffdb621f2c09ad943ad3f63 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 08:23:54 +0000 Subject: r24400: Fix a valgrind bug (This used to be commit 7c65deaed734f5623813922637877b94fc9a6259) --- source3/smbd/notify.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 144af093cf..cf64acae07 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -180,10 +180,12 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } + smb_setlen(NULL, request_buf, smb_size); + init_smb_request(req, request_buf); - send_nt_replies_new(req, NT_STATUS_OK, prs_data_p(&ps), - prs_offset(&ps), NULL, 0); + send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0); done: TALLOC_FREE(req); -- cgit From f7f176dd0d8878b79991455df9d9bf80ac82cd1a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 08:24:02 +0000 Subject: r24401: Push reply_prep_legacy into send_nt_replies (This used to be commit 489436a65632c4e6c1001a23dd33c896e9d7dfde) --- source3/smbd/nttrans.c | 80 ++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 881378c924..f5177c1f39 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -67,14 +67,9 @@ static char *nttrans_realloc(char **ptr, size_t size) HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -static int send_nt_replies(const char *inbuf, - char *outbuf, - int bufsize, - NTSTATUS nt_error, - char *params, - int paramsize, - char *pdata, - int datasize) +void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, + char *params, int paramsize, + char *pdata, int datasize) { int data_to_send = datasize; int params_to_send = paramsize; @@ -90,6 +85,14 @@ static int send_nt_replies(const char *inbuf, * transNT replies. */ + char *inbuf, *outbuf; + int length, bufsize; + + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + set_message(inbuf,outbuf,18,0,True); if (NT_STATUS_V(nt_error)) { @@ -106,7 +109,8 @@ static int send_nt_replies(const char *inbuf, if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("send_nt_replies: send_smb failed."); } - return 0; + TALLOC_FREE(req->outbuf); + return; } /* @@ -255,29 +259,10 @@ static int send_nt_replies(const char *inbuf, if(params_to_send < 0 || data_to_send < 0) { DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!", params_to_send, data_to_send)); - return -1; + TALLOC_FREE(req->outbuf); + return; } } - - return 0; -} - -void send_nt_replies_new(struct smb_request *req, NTSTATUS nt_error, - char *params, int paramsize, - char *pdata, int datasize) -{ - char *inbuf, *outbuf; - int length, bufsize; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - reply_post_legacy( - req, - send_nt_replies(inbuf, outbuf, bufsize, nt_error, - params, paramsize, pdata, datasize)); } /**************************************************************************** @@ -1138,7 +1123,7 @@ static void do_nt_transact_create_pipe(connection_struct *conn, DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies_new(req, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0); return; } @@ -1789,7 +1774,7 @@ static void call_nt_transact_create(connection_struct *conn, DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies_new(req, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0); return; } @@ -2218,7 +2203,7 @@ static void call_nt_transact_rename(connection_struct *conn, /* * Rename was successful. */ - send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); @@ -2316,8 +2301,8 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, if(max_data_count < sd_size) { - send_nt_replies_new(req, NT_STATUS_BUFFER_TOO_SMALL, - params, 4, *ppdata, 0); + send_nt_replies(req, NT_STATUS_BUFFER_TOO_SMALL, + params, 4, *ppdata, 0); talloc_destroy(mem_ctx); return; } @@ -2367,8 +2352,7 @@ security descriptor.\n")); talloc_destroy(mem_ctx); - send_nt_replies_new(req, NT_STATUS_OK, params, 4, data, - (int)sd_size); + send_nt_replies(req, NT_STATUS_OK, params, 4, data, (int)sd_size); return; } @@ -2423,7 +2407,7 @@ static void call_nt_transact_set_security_desc(connection_struct *conn, done: - send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); return; } @@ -2472,7 +2456,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, so we can know if we need to pre-allocate or not */ DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); - send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); return; case FSCTL_CREATE_OR_GET_OBJECT_ID: @@ -2498,8 +2482,8 @@ static void call_nt_transact_ioctl(connection_struct *conn, push_file_id_16(pdata, &fsp->file_id); memcpy(pdata+16,create_volume_objectid(conn,objid),16); push_file_id_16(pdata+32, &fsp->file_id); - send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, - pdata, data_count); + send_nt_replies(req, NT_STATUS_OK, NULL, 0, + pdata, data_count); return; } @@ -2643,8 +2627,8 @@ static void call_nt_transact_ioctl(connection_struct *conn, talloc_destroy(shadow_data->mem_ctx); - send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, - pdata, data_count); + send_nt_replies(req, NT_STATUS_OK, NULL, 0, + pdata, data_count); return; } @@ -2698,7 +2682,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, */ /* this works for now... */ - send_nt_replies_new(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); return; } default: @@ -2983,8 +2967,8 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, break; } - send_nt_replies_new(req, nt_status, params, param_len, - pdata, data_len); + send_nt_replies(req, nt_status, params, param_len, + pdata, data_len); } /**************************************************************************** @@ -3113,8 +3097,8 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, return; } - send_nt_replies_new(req, NT_STATUS_OK, params, param_len, - pdata, data_len); + send_nt_replies(req, NT_STATUS_OK, params, param_len, + pdata, data_len); } #endif /* HAVE_SYS_QUOTAS */ -- cgit From df6edb0d3cc739dedd5edbc5398535923df5df92 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 08:29:36 +0000 Subject: r24402: Fix a 64-bit warning (This used to be commit 73d99d6f9a5554d957ae737ff617b6a2e88b52bc) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 826306c883..d42d6399fb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2501,7 +2501,7 @@ normal_readbraw: outbuf = TALLOC_ARRAY(NULL, char, nread+4); if (!outbuf) { DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n", - nread+4)); + (unsigned)(nread+4))); reply_readbraw_error(); return; } -- cgit From e0880fa7bd79878f53bfa2536e683a38e9c89c6a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 08:44:00 +0000 Subject: r24403: Remove reply_prep_legacy from send_nttrans_replies (This used to be commit a6400ca6e2301d1cfc1d6a513dc7809ed99d7b58) --- source3/smbd/nttrans.c | 98 +++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 48 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f5177c1f39..85103e0e69 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -80,36 +80,14 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, int alignment_offset = 3; int data_alignment_offset = 0; - /* - * Initially set the wcnt area to be 18 - this is true for all - * transNT replies. - */ - - char *inbuf, *outbuf; - int length, bufsize; - - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - set_message(inbuf,outbuf,18,0,True); - - if (NT_STATUS_V(nt_error)) { - ERROR_NT(nt_error); - } - /* * If there genuinely are no parameters or data to send just send * the empty packet. */ if(params_to_send == 0 && data_to_send == 0) { - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("send_nt_replies: send_smb failed."); - } - TALLOC_FREE(req->outbuf); + reply_outbuf(req, 18, 0); + show_msg((char *)req->outbuf); return; } @@ -130,9 +108,10 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, * NT needs this to work correctly. */ - useable_space = bufsize - ((smb_buf(outbuf)+ - alignment_offset+data_alignment_offset) - - outbuf); + useable_space = max_send - (smb_size + + 2 * 18 /* wct */ + + alignment_offset + + data_alignment_offset); /* * useable_space can never be more than max_send minus the @@ -158,14 +137,14 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, total_sent_thistime = MIN(total_sent_thistime, useable_space); - set_message(inbuf,outbuf, 18, total_sent_thistime, True); + reply_outbuf(req, 18, total_sent_thistime); /* * Set total params and data to be sent. */ - SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize); - SIVAL(outbuf,smb_ntr_TotalDataCount,datasize); + SIVAL(req->outbuf,smb_ntr_TotalParameterCount,paramsize); + SIVAL(req->outbuf,smb_ntr_TotalDataCount,datasize); /* * Calculate how many parameters and data we can fit into @@ -176,11 +155,12 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, data_sent_thistime = useable_space - params_sent_thistime; data_sent_thistime = MIN(data_sent_thistime,data_to_send); - SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime); + SIVAL(req->outbuf, smb_ntr_ParameterCount, + params_sent_thistime); if(params_sent_thistime == 0) { - SIVAL(outbuf,smb_ntr_ParameterOffset,0); - SIVAL(outbuf,smb_ntr_ParameterDisplacement,0); + SIVAL(req->outbuf,smb_ntr_ParameterOffset,0); + SIVAL(req->outbuf,smb_ntr_ParameterDisplacement,0); } else { /* * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the @@ -189,33 +169,37 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, * them from the calculation. */ - SIVAL(outbuf,smb_ntr_ParameterOffset, - ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); + SIVAL(req->outbuf,smb_ntr_ParameterOffset, + ((smb_buf(req->outbuf)+alignment_offset) + - smb_base(req->outbuf))); /* * Absolute displacement of param bytes sent in this packet. */ - SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params); + SIVAL(req->outbuf, smb_ntr_ParameterDisplacement, + pp - params); } /* * Deal with the data portion. */ - SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime); + SIVAL(req->outbuf, smb_ntr_DataCount, data_sent_thistime); if(data_sent_thistime == 0) { - SIVAL(outbuf,smb_ntr_DataOffset,0); - SIVAL(outbuf,smb_ntr_DataDisplacement, 0); + SIVAL(req->outbuf,smb_ntr_DataOffset,0); + SIVAL(req->outbuf,smb_ntr_DataDisplacement, 0); } else { /* * The offset of the data bytes is the offset of the * parameter bytes plus the number of parameters being sent this time. */ - SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) - - smb_base(outbuf)) + params_sent_thistime + data_alignment_offset); - SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata); + SIVAL(req->outbuf, smb_ntr_DataOffset, + ((smb_buf(req->outbuf)+alignment_offset) - + smb_base(req->outbuf)) + + params_sent_thistime + data_alignment_offset); + SIVAL(req->outbuf,smb_ntr_DataDisplacement, pd - pdata); } /* @@ -223,7 +207,12 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, */ if(params_sent_thistime) { - memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); + if (alignment_offset != 0) { + memset(smb_buf(req->outbuf), 0, + alignment_offset); + } + memcpy((smb_buf(req->outbuf)+alignment_offset), pp, + params_sent_thistime); } /* @@ -231,20 +220,34 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, */ if(data_sent_thistime) { - memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+ - data_alignment_offset,pd,data_sent_thistime); + if (data_alignment_offset != 0) { + memset((smb_buf(req->outbuf)+alignment_offset+ + params_sent_thistime), 0, + data_alignment_offset); + } + memcpy(smb_buf(req->outbuf)+alignment_offset + +params_sent_thistime+data_alignment_offset, + pd,data_sent_thistime); } DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", params_sent_thistime, data_sent_thistime, useable_space)); DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", params_to_send, data_to_send, paramsize, datasize)); + + if (NT_STATUS_V(nt_error)) { + error_packet_set((char *)req->outbuf, + 0, 0, nt_error, + __LINE__,__FILE__); + } /* Send the packet */ - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) { + show_msg((char *)req->outbuf); + if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) { exit_server_cleanly("send_nt_replies: send_smb failed."); } + + TALLOC_FREE(req->outbuf); pp += params_sent_thistime; pd += data_sent_thistime; @@ -259,7 +262,6 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, if(params_to_send < 0 || data_to_send < 0) { DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!", params_to_send, data_to_send)); - TALLOC_FREE(req->outbuf); return; } } -- cgit From ae89ba48ec548f28d38a0a35bc3884181946f1b8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 10:06:33 +0000 Subject: r24404: Remove get_OutBuffer usage from blocking.c (This used to be commit cb8fab5663db2cb408e1b85a7287d3670b09d503) --- source3/smbd/blocking.c | 41 ++++++++++++++--------------------------- source3/smbd/process.c | 5 ----- 2 files changed, 14 insertions(+), 32 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 0b24fc8257..8bdc992910 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -249,34 +249,20 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, return True; } -/**************************************************************************** - Return a smd with a given size. -*****************************************************************************/ - -static void send_blocking_reply(char *outbuf, int outsize, const char *inbuf) -{ - if(outsize > 4) { - smb_setlen(inbuf, outbuf,outsize - 4); - } - - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("send_blocking_reply: send_smb failed."); - } -} - /**************************************************************************** Return a lockingX success SMB. *****************************************************************************/ static void reply_lockingX_success(blocking_lock_record *blr) { - char *outbuf = get_OutBuffer(); - int bufsize = BUFFER_SIZE; - char *inbuf = blr->inbuf; - int outsize = 0; + struct smb_request *req; - construct_reply_common(inbuf, outbuf); - set_message(inbuf,outbuf,2,0,True); + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + smb_panic("Could not allocate smb_request"); + } + + init_smb_request(req, (uint8 *)blr->inbuf); + reply_outbuf(req, 2, 0); /* * As this message is a lockingX call we must handle @@ -286,11 +272,11 @@ static void reply_lockingX_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - outsize = chain_reply(inbuf,&outbuf,blr->length,bufsize); - - outsize += chain_size; + chain_reply_new(req); - send_blocking_reply(outbuf,outsize,inbuf); + if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) { + exit_server_cleanly("send_blocking_reply: send_smb failed."); + } } /**************************************************************************** @@ -299,8 +285,9 @@ static void reply_lockingX_success(blocking_lock_record *blr) static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status) { - char *outbuf = get_OutBuffer(); + char outbuf[smb_size]; char *inbuf = blr->inbuf; + construct_reply_common(inbuf, outbuf); /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to @@ -395,7 +382,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status case SMBtrans2: case SMBtranss2: { - char *outbuf = get_OutBuffer(); + char outbuf[smb_size]; char *inbuf = blr->inbuf; construct_reply_common(inbuf, outbuf); /* construct_reply_common has done us the favor to pre-fill the diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7e499b7797..ca55c8f63f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1743,11 +1743,6 @@ char *get_InBuffer(void) return InBuffer; } -char *get_OutBuffer(void) -{ - return OutBuffer; -} - /**************************************************************************** Allocate a new InBuffer. Returns the new and old ones. ****************************************************************************/ -- cgit From 439d6020e9b1994ad8e9b4080ba73dde6da93037 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 10:27:27 +0000 Subject: r24405: Check wct in reply_lockingX (This used to be commit c4972632f8b41c87a4c0fdfc6c98515c42eafda5) --- source3/smbd/reply.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d42d6399fb..a9af46bb69 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5773,23 +5773,34 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize) { - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2)); - unsigned char locktype = CVAL(inbuf,smb_vwv3); - unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint16 num_locks = SVAL(inbuf,smb_vwv7); + files_struct *fsp; + unsigned char locktype; + unsigned char oplocklevel; + uint16 num_ulocks; + uint16 num_locks; SMB_BIG_UINT count = 0, offset = 0; uint32 lock_pid; - int32 lock_timeout = IVAL(inbuf,smb_vwv4); + int32 lock_timeout; int i; char *data; - BOOL large_file_format = - (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; + BOOL large_file_format; BOOL err; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; START_PROFILE(SMBlockingX); + + if (CVAL(inbuf, smb_wct) < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + fsp = file_fsp(SVAL(inbuf,smb_vwv2)); + locktype = CVAL(inbuf,smb_vwv3); + oplocklevel = CVAL(inbuf,smb_vwv3+1); + num_ulocks = SVAL(inbuf,smb_vwv6); + num_locks = SVAL(inbuf,smb_vwv7); + lock_timeout = IVAL(inbuf,smb_vwv4); + large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; + CHECK_FSP(fsp,conn); data = smb_buf(inbuf); -- cgit From 29df25351df5ce5987334318e7f3507aa01c7ebe Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 10:47:47 +0000 Subject: r24406: Push reply_prep_legacy into reply_lockingX (This used to be commit bce87ebdc00b9086dcdcc55442b57b92345971ac) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 65 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ca55c8f63f..0f4d53b77a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -726,7 +726,7 @@ static const struct smb_message_struct { /* 0x21 */ { NULL, NULL, NULL, 0 }, /* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE }, /* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER }, -/* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER }, +/* 0x24 */ { "SMBlockingX",NULL,reply_lockingX,AS_USER }, /* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC }, /* 0x26 */ { "SMBtranss",NULL,reply_transs,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a9af46bb69..c5dd5a6dbf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5770,8 +5770,7 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma Reply to a lockingX request. ****************************************************************************/ -int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, - int length, int bufsize) +void reply_lockingX(connection_struct *conn, struct smb_request *req) { files_struct *fsp; unsigned char locktype; @@ -5787,10 +5786,21 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, BOOL err; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + char *inbuf, *outbuf; + int length, bufsize; + START_PROFILE(SMBlockingX); + if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBlockingX); + return; + } + if (CVAL(inbuf, smb_wct) < 8) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBlockingX); + return; } fsp = file_fsp(SVAL(inbuf,smb_vwv2)); @@ -5801,7 +5811,9 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, lock_timeout = IVAL(inbuf,smb_vwv4); large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; - CHECK_FSP(fsp,conn); + if (!check_fsp(conn, req, fsp, ¤t_user)) { + return; + } data = smb_buf(inbuf); @@ -5809,7 +5821,9 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, /* we don't support these - and CANCEL_LOCK makes w2k and XP reboot so I don't really want to be compatible! (tridge) */ - return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks)); + reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks)); + END_PROFILE(SMBlockingX); + return; } /* Check if this is an oplock break on a file @@ -5846,10 +5860,12 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, * send a reply */ if (num_locks == 0 && num_ulocks == 0) { END_PROFILE(SMBlockingX); - return -1; + reply_post_legacy(req, -1); + return; } else { END_PROFILE(SMBlockingX); - return ERROR_DOS(ERRDOS,ERRlock); + reply_doserror(req, ERRDOS, ERRlock); + return; } } @@ -5879,7 +5895,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, "break is a chained %d request !\n", (unsigned int)CVAL(inbuf,smb_vwv0) )); END_PROFILE(SMBlockingX); - return -1; + reply_post_legacy(req, -1); + return; } } @@ -5902,7 +5919,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, */ if(err) { END_PROFILE(SMBlockingX); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for " @@ -5918,7 +5936,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, if (NT_STATUS_V(status)) { END_PROFILE(SMBlockingX); - return ERROR_NT(status); + reply_nterror(req, status); + return; } } @@ -5946,7 +5965,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, */ if(err) { END_PROFILE(SMBlockingX); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid " @@ -5969,7 +5989,12 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, locktype, NT_STATUS_FILE_LOCK_CONFLICT)) { END_PROFILE(SMBlockingX); - return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation)); + reply_nterror( + req, + NT_STATUS_DOS( + ERRDOS, + ERRcancelviolation)); + return; } } /* Remove a matching pending lock. */ @@ -6034,7 +6059,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, block_smbpid)) { TALLOC_FREE(br_lck); END_PROFILE(SMBlockingX); - return -1; + reply_post_legacy(req, -1); + return; } } @@ -6043,7 +6069,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, if (NT_STATUS_V(status)) { END_PROFILE(SMBlockingX); - return ERROR_NT(status); + reply_nterror(req, status); + return; } } @@ -6070,7 +6097,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, */ if(err) { END_PROFILE(SMBlockingX); - return ERROR_DOS(ERRDOS,ERRnoaccess); + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } do_unlock(smbd_messaging_context(), @@ -6081,16 +6109,19 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, WINDOWS_LOCK); } END_PROFILE(SMBlockingX); - return ERROR_NT(status); + reply_nterror(req, status); + return; } set_message(inbuf,outbuf,2,0,True); + + reply_post_legacy(req, smb_len(outbuf)+4); DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); END_PROFILE(SMBlockingX); - return chain_reply(inbuf,&outbuf,length,bufsize); + chain_reply_new(req); } #undef DBGC_CLASS -- cgit From ec5b2a718192f5d5a26c44ff9c6714515d42ea47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 13:38:14 +0000 Subject: r24408: Remove reply_prep_legacy from reply_lockingX (This used to be commit e0db5fd11bd5e0a3aca801a14509fddd6a625a84) --- source3/smbd/reply.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c5dd5a6dbf..4a8ecb86e9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5786,36 +5786,28 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) BOOL err; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - char *inbuf, *outbuf; - int length, bufsize; - START_PROFILE(SMBlockingX); - if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBlockingX); - return; - } - - if (CVAL(inbuf, smb_wct) < 8) { + if (req->wct < 8) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBlockingX); return; } - fsp = file_fsp(SVAL(inbuf,smb_vwv2)); - locktype = CVAL(inbuf,smb_vwv3); - oplocklevel = CVAL(inbuf,smb_vwv3+1); - num_ulocks = SVAL(inbuf,smb_vwv6); - num_locks = SVAL(inbuf,smb_vwv7); - lock_timeout = IVAL(inbuf,smb_vwv4); + fsp = file_fsp(SVAL(req->inbuf,smb_vwv2)); + locktype = CVAL(req->inbuf,smb_vwv3); + oplocklevel = CVAL(req->inbuf,smb_vwv3+1); + num_ulocks = SVAL(req->inbuf,smb_vwv6); + num_locks = SVAL(req->inbuf,smb_vwv7); + lock_timeout = IVAL(req->inbuf,smb_vwv4); large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBlockingX); return; } - data = smb_buf(inbuf); + data = smb_buf(req->inbuf); if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) { /* we don't support these - and CANCEL_LOCK makes w2k @@ -5890,12 +5882,12 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) if (num_locks == 0 && num_ulocks == 0) { /* Sanity check - ensure a pure oplock break is not a chained request. */ - if(CVAL(inbuf,smb_vwv0) != 0xff) + if(CVAL(req->inbuf,smb_vwv0) != 0xff) DEBUG(0,("reply_lockingX: Error : pure oplock " "break is a chained %d request !\n", - (unsigned int)CVAL(inbuf,smb_vwv0) )); + (unsigned int)CVAL(req->inbuf, + smb_vwv0) )); END_PROFILE(SMBlockingX); - reply_post_legacy(req, -1); return; } } @@ -5906,6 +5898,13 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) */ release_level_2_oplocks_on_change(fsp); + + if (smb_buflen(req->inbuf) < + (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBlockingX); + return; + } /* Data now points at the beginning of the list of smb_unlkrng structs */ @@ -6047,7 +6046,8 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) * onto the blocking lock queue. */ if(push_blocking_lock_request(br_lck, - inbuf, length, + (char *)req->inbuf, + smb_len(req->inbuf)+4, fsp, lock_timeout, i, @@ -6113,9 +6113,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) return; } - set_message(inbuf,outbuf,2,0,True); - - reply_post_legacy(req, smb_len(outbuf)+4); + reply_outbuf(req, 2, 0); DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); -- cgit From a12e7ef30a45c155c0f211d02445ef0ad46acde0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 13:57:36 +0000 Subject: r24409: Check wct in reply_open (This used to be commit ee6f212ed0b332e6886056e6d254d0c0da7c5046) --- source3/smbd/reply.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4a8ecb86e9..6acee164c6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1402,9 +1402,9 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int info; SMB_STRUCT_STAT sbuf; files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + int oplock_request; int deny_mode; - uint32 dos_attr = SVAL(inbuf,smb_vwv1); + uint32 dos_attr; uint32 access_mask; uint32 share_mode; uint32 create_disposition; @@ -1415,8 +1415,14 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, START_PROFILE(SMBopen); init_smb_request(&req, (uint8 *)inbuf); + + if (req.wct < 2) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + oplock_request = CORE_OPLOCK_REQUEST(inbuf); deny_mode = SVAL(inbuf,smb_vwv0); + dos_attr = SVAL(inbuf,smb_vwv1); srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status); -- cgit From 2da44a2dee1ad425a25f9a188896ce031356630c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 14:31:55 +0000 Subject: r24412: Convert reply_open to the new API (This used to be commit 394987f5224086cb379ea8d0364924679b8a0214) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 87 +++++++++++++++++++++++++++++--------------------- 2 files changed, 51 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 0f4d53b77a..f0d1c56e90 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -692,7 +692,7 @@ static const struct smb_message_struct { /* 0x00 */ { "SMBmkdir",NULL,reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",NULL,reply_rmdir,AS_USER | NEED_WRITE}, -/* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, +/* 0x02 */ { "SMBopen",NULL,reply_open,AS_USER }, /* 0x03 */ { "SMBcreate",NULL,reply_mknew,AS_USER}, /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, /* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6acee164c6..40b9630ecf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1392,10 +1392,9 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size Reply to an open. ****************************************************************************/ -int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_open(connection_struct *conn, struct smb_request *req) { pstring fname; - int outsize = 0; uint32 fattr=0; SMB_OFF_T size = 0; time_t mtime=0; @@ -1410,55 +1409,64 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, uint32 create_disposition; uint32 create_options = 0; NTSTATUS status; - struct smb_request req; START_PROFILE(SMBopen); - init_smb_request(&req, (uint8 *)inbuf); - - if (req.wct < 2) { - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if (req->wct < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBopen); + return; } - oplock_request = CORE_OPLOCK_REQUEST(inbuf); - deny_mode = SVAL(inbuf,smb_vwv0); - dos_attr = SVAL(inbuf,smb_vwv1); + oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); + deny_mode = SVAL(req->inbuf,smb_vwv0); + dos_attr = SVAL(req->inbuf,smb_vwv1); - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1, - sizeof(fname), 0, STR_TERMINATE, &status); + srvstr_get_path((char *)req->inbuf, req->flags2, fname, + smb_buf(req->inbuf)+1, sizeof(fname), 0, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBopen); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBopen); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBopen); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBopen); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBopen); - return ERROR_NT(status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBopen); - return ERROR_NT(status); + return; } if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask, &share_mode, &create_disposition, &create_options)) { + reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); END_PROFILE(SMBopen); - return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); + return; } - status = open_file_ntcreate(conn, &req, fname, &sbuf, + status = open_file_ntcreate(conn, req, fname, &sbuf, access_mask, share_mode, create_disposition, @@ -1468,12 +1476,14 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, &info, &fsp); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBopen); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + END_PROFILE(SMBopen); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBopen); + return; } size = sbuf.st_size; @@ -1483,30 +1493,33 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (fattr & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); close_file(fsp,ERROR_CLOSE); + reply_doserror(req, ERRDOS,ERRnoaccess); END_PROFILE(SMBopen); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } - - outsize = set_message(inbuf,outbuf,7,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); - SSVAL(outbuf,smb_vwv1,fattr); + + reply_outbuf(req, 7, 0); + SSVAL(req->outbuf,smb_vwv0,fsp->fnum); + SSVAL(req->outbuf,smb_vwv1,fattr); if(lp_dos_filetime_resolution(SNUM(conn)) ) { - srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1); + srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1); } else { - srv_put_dos_date3(outbuf,smb_vwv2,mtime); + srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime); } - SIVAL(outbuf,smb_vwv4,(uint32)size); - SSVAL(outbuf,smb_vwv6,deny_mode); + SIVAL(req->outbuf,smb_vwv4,(uint32)size); + SSVAL(req->outbuf,smb_vwv6,deny_mode); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf,smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf,smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } END_PROFILE(SMBopen); - return(outsize); + return; } /**************************************************************************** -- cgit From 5fe4384cd98237c7e426de8508dfb2b7b29f757f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 14:50:49 +0000 Subject: r24414: Convert reply_mv to the new API (This used to be commit fa341e4840d422cee389c06112e0b2df43a31f45) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 71 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f0d1c56e90..a03529ed0d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -697,7 +697,7 @@ static const struct smb_message_struct { /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, /* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER}, /* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE }, -/* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE }, +/* 0x07 */ { "SMBmv",NULL,reply_mv,AS_USER | NEED_WRITE }, /* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER}, /* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE}, /* 0x0a */ { "SMBread",reply_read,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 40b9630ecf..a6d06cfa7e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5173,75 +5173,94 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, Reply to a mv. ****************************************************************************/ -int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, - int dum_buffsize) +void reply_mv(connection_struct *conn, struct smb_request *req) { - int outsize = 0; pstring name; pstring newname; char *p; - uint32 attrs = SVAL(inbuf,smb_vwv0); + uint32 attrs; NTSTATUS status; BOOL src_has_wcard = False; BOOL dest_has_wcard = False; - struct smb_request req; START_PROFILE(SMBmv); - init_smb_request(&req, (uint8 *)inbuf); + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBmv); + return; + } - p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p, + attrs = SVAL(req->inbuf,smb_vwv0); + + p = smb_buf(req->inbuf) + 1; + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBmv); - return ERROR_NT(status); + return; } p++; - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBmv); - return ERROR_NT(status); + return; } - status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard); + status = resolve_dfspath_wcard(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + name, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBmv); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBmv); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBmv); + return; } - status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard); + status = resolve_dfspath_wcard(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + newname, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBmv); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBmv); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBmv); + return; } DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - status = rename_internals(conn, &req, name, newname, attrs, False, + status = rename_internals(conn, req, name, newname, attrs, False, src_has_wcard, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBmv); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + END_PROFILE(SMBmv); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBmv); + return; } - outsize = set_message(inbuf,outbuf,0,0,False); + reply_outbuf(req, 0, 0); END_PROFILE(SMBmv); - return(outsize); + return; } /******************************************************************* -- cgit From 73b3ae9c55c5c1b3d20c69ce3571d066556881ed Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 15:09:49 +0000 Subject: r24415: Convert reply_getatr to the new API (This used to be commit 1a08b97a933e25362707cb0d8ba09d733af4cbbf) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 50 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a03529ed0d..b49945eafc 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -698,7 +698,7 @@ static const struct smb_message_struct { /* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER}, /* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE }, /* 0x07 */ { "SMBmv",NULL,reply_mv,AS_USER | NEED_WRITE }, -/* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER}, +/* 0x08 */ { "SMBgetatr",NULL,reply_getatr,AS_USER}, /* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE}, /* 0x0a */ { "SMBread",reply_read,NULL,AS_USER}, /* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a6d06cfa7e..94f1843191 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -886,10 +886,9 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) Reply to a getatr. ****************************************************************************/ -int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_getatr(connection_struct *conn, struct smb_request *req) { pstring fname; - int outsize = 0; SMB_STRUCT_STAT sbuf; int mode=0; SMB_OFF_T size=0; @@ -899,21 +898,27 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBgetatr); - p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p, + p = smb_buf(req->inbuf) + 1; + p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBgetatr); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBgetatr); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBgetatr); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBgetatr); + return; } /* dos smetimes asks for a stat of "" - it returns a "hidden directory" @@ -928,18 +933,22 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { status = unix_convert(conn, fname, False, NULL,&sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBgetatr); - return ERROR_NT(status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status))); + reply_nterror(req, status); END_PROFILE(SMBgetatr); - return ERROR_NT(status); + return; } if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) { DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno))); - return UNIXERROR(ERRDOS,ERRbadfile); + reply_unixerror(req, ERRDOS,ERRbadfile); + END_PROFILE(SMBgetatr); + return; } mode = dos_mode(conn,fname,&sbuf); @@ -949,25 +958,26 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size size = 0; } } - - outsize = set_message(inbuf,outbuf,10,0,True); - SSVAL(outbuf,smb_vwv0,mode); + reply_outbuf(req, 10, 0); + + SSVAL(req->outbuf,smb_vwv0,mode); if(lp_dos_filetime_resolution(SNUM(conn)) ) { - srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1); + srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1); } else { - srv_put_dos_date3(outbuf,smb_vwv1,mtime); + srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime); } - SIVAL(outbuf,smb_vwv3,(uint32)size); + SIVAL(req->outbuf,smb_vwv3,(uint32)size); if (Protocol >= PROTOCOL_NT1) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); + SSVAL(req->outbuf, smb_flg2, + SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); } DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) ); END_PROFILE(SMBgetatr); - return(outsize); + return; } /**************************************************************************** -- cgit From 06ed827edf3fa210aebeea2e1e059fde090159fa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 15:26:54 +0000 Subject: r24417: Convert reply_setatr to the new API (This used to be commit 56bab5ea4cbcf8e46101053bd68f66691fd737c5) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 53 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 35 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b49945eafc..883c39c532 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -699,7 +699,7 @@ static const struct smb_message_struct { /* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE }, /* 0x07 */ { "SMBmv",NULL,reply_mv,AS_USER | NEED_WRITE }, /* 0x08 */ { "SMBgetatr",NULL,reply_getatr,AS_USER}, -/* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE}, +/* 0x09 */ { "SMBsetatr",NULL,reply_setatr,AS_USER | NEED_WRITE}, /* 0x0a */ { "SMBread",reply_read,NULL,AS_USER}, /* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC }, /* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 94f1843191..864125fd04 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -984,10 +984,9 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) Reply to a setatr. ****************************************************************************/ -int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_setatr(connection_struct *conn, struct smb_request *req) { pstring fname; - int outsize = 0; int mode; time_t mtime; SMB_STRUCT_STAT sbuf; @@ -996,33 +995,46 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBsetatr); - p = smb_buf(inbuf) + 1; - p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p, + if (req->wct < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + p = smb_buf(req->inbuf) + 1; + p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBsetatr); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBsetatr); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBsetatr); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBsetatr); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBsetatr); - return ERROR_NT(status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBsetatr); - return ERROR_NT(status); + return; } if (fname[0] == '.' && fname[1] == '\0') { @@ -1030,12 +1042,13 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size * Not sure here is the right place to catch this * condition. Might be moved to somewhere else later -- vl */ + reply_nterror(req, NT_STATUS_ACCESS_DENIED); END_PROFILE(SMBsetatr); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + return; } - mode = SVAL(inbuf,smb_vwv0); - mtime = srv_make_unix_date3(inbuf+smb_vwv1); + mode = SVAL(req->inbuf,smb_vwv0); + mtime = srv_make_unix_date3(req->inbuf+smb_vwv1); if (mode != FILE_ATTRIBUTE_NORMAL) { if (VALID_STAT_OF_DIR(sbuf)) @@ -1044,22 +1057,24 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode &= ~aDIR; if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) { + reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetatr); - return UNIXERROR(ERRDOS, ERRnoaccess); + return; } } if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) { + reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetatr); - return UNIXERROR(ERRDOS, ERRnoaccess); + return; } + + reply_outbuf(req, 0, 0); - outsize = set_message(inbuf,outbuf,0,0,False); - DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); END_PROFILE(SMBsetatr); - return(outsize); + return; } /**************************************************************************** -- cgit From dee4ab15338841469729c794275eea158079e076 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 15:42:39 +0000 Subject: r24422: Convert reply_ctemp to the new API (This used to be commit 3cc22fd74f0ffc72f4340a963b4eca7178be2192) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 85 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 53 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 883c39c532..1241741449 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -704,7 +704,7 @@ static const struct smb_message_struct { /* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC }, /* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, -/* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER }, +/* 0x0e */ { "SMBctemp",NULL,reply_ctemp,AS_USER }, /* 0x0f */ { "SMBmknew",NULL,reply_mknew,AS_USER}, /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, /* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 864125fd04..87e3e29a4a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1924,29 +1924,35 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) Reply to a create temporary file. ****************************************************************************/ -int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_ctemp(connection_struct *conn, struct smb_request *req) { pstring fname; - int outsize = 0; - uint32 fattr = SVAL(inbuf,smb_vwv0); + uint32 fattr; files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + int oplock_request; int tmpfd; SMB_STRUCT_STAT sbuf; - char *p, *s; + char *s; NTSTATUS status; - unsigned int namelen; - struct smb_request req; START_PROFILE(SMBctemp); - init_smb_request(&req, (uint8 *)inbuf); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBctemp); + return; + } - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1, - sizeof(fname), 0, STR_TERMINATE, &status); + fattr = SVAL(req->inbuf,smb_vwv0); + oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); + + srvstr_get_path((char *)req->inbuf, req->flags2, fname, + smb_buf(req->inbuf)+1, sizeof(fname), 0, STR_TERMINATE, + &status); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBctemp); - return ERROR_NT(status); + return; } if (*fname) { pstrcat(fname,"/TMXXXXXX"); @@ -1954,37 +1960,45 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(fname,"TMXXXXXX"); } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBctemp); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBctemp); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBctemp); + return; } status = unix_convert(conn, fname, False, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBctemp); - return ERROR_NT(status); + return; } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBctemp); - return ERROR_NT(status); + return; } tmpfd = smb_mkstemp(fname); if (tmpfd == -1) { + reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBctemp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return; } SMB_VFS_STAT(conn,fname,&sbuf); /* We should fail if file does not exist. */ - status = open_file_ntcreate(conn, &req, fname, &sbuf, + status = open_file_ntcreate(conn, req, fname, &sbuf, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, @@ -1997,16 +2011,18 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, close(tmpfd); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBctemp); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + END_PROFILE(SMBctemp); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBctemp); + return; } - outsize = set_message(inbuf,outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); + reply_outbuf(req, 1, 0); + SSVAL(req->outbuf,smb_vwv0,fsp->fnum); /* the returned filename is relative to the directory */ s = strrchr_m(fname, '/'); @@ -2016,23 +2032,26 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, s++; } - p = smb_buf(outbuf); #if 0 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only thing in the byte section. JRA */ SSVALS(p, 0, -1); /* what is this? not in spec */ #endif - namelen = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, s, -1, - STR_ASCII|STR_TERMINATE); - p += namelen; - outsize = set_message_end(inbuf,outbuf, p); + if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE) + == -1) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBctemp); + return; + } if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf, smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); + SCVAL(req->outbuf, smb_flg, + CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) ); @@ -2040,7 +2059,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, (unsigned int)sbuf.st_mode ) ); END_PROFILE(SMBctemp); - return(outsize); + return; } /******************************************************************* -- cgit From fe502551c32263ef6faed26ee691aa1586f75104 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 16:04:31 +0000 Subject: r24423: Convert reply_lseek to the new API (This used to be commit bd228853863ce5b4b9b974347c50c956d7f2e055) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 37 +++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1241741449..fe6da4b265 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -708,7 +708,7 @@ static const struct smb_message_struct { /* 0x0f */ { "SMBmknew",NULL,reply_mknew,AS_USER}, /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, /* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR}, -/* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER}, +/* 0x12 */ { "SMBlseek",NULL,reply_lseek,AS_USER}, /* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER}, /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER}, /* 0x15 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 87e3e29a4a..80a2e9ff14 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3636,22 +3636,32 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) Reply to a lseek. ****************************************************************************/ -int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_lseek(connection_struct *conn, struct smb_request *req) { SMB_OFF_T startpos; SMB_OFF_T res= -1; int mode,umode; - int outsize = 0; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; + START_PROFILE(SMBlseek); - CHECK_FSP(fsp,conn); + if (req->wct < 4) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBlseek); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + return; + } flush_write_cache(fsp, SEEK_FLUSH); - mode = SVAL(inbuf,smb_vwv1) & 3; + mode = SVAL(req->inbuf,smb_vwv1) & 3; /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ - startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2); + startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2); switch (mode) { case 0: @@ -3678,8 +3688,10 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { + reply_unixerror(req, ERRDOS, + ERRnoaccess); END_PROFILE(SMBlseek); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return; } current_pos += sbuf.st_size; @@ -3689,21 +3701,22 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if(res == -1) { + reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBlseek); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return; } } fsp->fh->pos = res; - - outsize = set_message(inbuf,outbuf,2,0,True); - SIVAL(outbuf,smb_vwv0,res); + + reply_outbuf(req, 2, 0); + SIVAL(req->outbuf,smb_vwv0,res); DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n", fsp->fnum, (double)startpos, (double)res, mode)); END_PROFILE(SMBlseek); - return(outsize); + return; } /**************************************************************************** -- cgit From 7c25bf4511161cb7d3da8c27ca74b73c02b8841f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 18:16:04 +0000 Subject: r24425: Convert reply_write to the new API (This used to be commit 244965f7b67becb85774311e6ce84318d554384d) --- source3/smbd/pipes.c | 29 ++++++++++++------------ source3/smbd/process.c | 2 +- source3/smbd/reply.c | 61 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 56 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index bf4567ddb9..e8a496ffa7 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -138,24 +138,24 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) Reply to a write on a pipe. ****************************************************************************/ -int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) +void reply_pipe_write(struct smb_request *req) { - smb_np_struct *p = get_rpc_pipe_p(SVAL(inbuf,smb_vwv0)); - uint16 vuid = SVAL(inbuf,smb_uid); - size_t numtowrite = SVAL(inbuf,smb_vwv1); + smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv0)); + size_t numtowrite = SVAL(req->inbuf,smb_vwv1); int nwritten; - int outsize; char *data; if (!p) { - return(ERROR_DOS(ERRDOS,ERRbadfid)); + reply_doserror(req, ERRDOS, ERRbadfid); + return; } - if (p->vuid != vuid) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + if (p->vuid != req->vuid) { + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; } - data = smb_buf(inbuf) + 3; + data = smb_buf(req->inbuf) + 3; if (numtowrite == 0) { nwritten = 0; @@ -164,16 +164,17 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize) } if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { - return (UNIXERROR(ERRDOS,ERRnoaccess)); + reply_unixerror(req, ERRDOS, ERRnoaccess); + return; } - - outsize = set_message(inbuf,outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,nwritten); + reply_outbuf(req, 1, 0); + + SSVAL(req->outbuf,smb_vwv0,nwritten); DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); - return(outsize); + return; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index fe6da4b265..c84f4b2dee 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -701,7 +701,7 @@ static const struct smb_message_struct { /* 0x08 */ { "SMBgetatr",NULL,reply_getatr,AS_USER}, /* 0x09 */ { "SMBsetatr",NULL,reply_setatr,AS_USER | NEED_WRITE}, /* 0x0a */ { "SMBread",reply_read,NULL,AS_USER}, -/* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC }, +/* 0x0b */ { "SMBwrite",NULL,reply_write,AS_USER | CAN_IPC }, /* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, /* 0x0e */ { "SMBctemp",NULL,reply_ctemp,AS_USER }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 80a2e9ff14..3805994fb5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3400,36 +3400,51 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, Reply to a write. ****************************************************************************/ -int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize) +void reply_write(connection_struct *conn, struct smb_request *req) { size_t numtowrite; ssize_t nwritten = -1; SMB_OFF_T startpos; char *data; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); - int outsize = 0; + files_struct *fsp; NTSTATUS status; + START_PROFILE(SMBwrite); + if (req->wct < 5) { + END_PROFILE(SMBwrite); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { + reply_pipe_write(req); END_PROFILE(SMBwrite); - return reply_pipe_write(inbuf,outbuf,size,dum_buffsize); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + return; } - CHECK_FSP(fsp,conn); if (!CHECK_WRITE(fsp)) { + reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBwrite); - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + return; } - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - data = smb_buf(inbuf) + 3; + numtowrite = SVAL(req->inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); + data = smb_buf(req->inbuf) + 3; - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite, + (SMB_BIG_UINT)startpos, WRITE_LOCK)) { + reply_doserror(req, ERRDOS, ERRlock); END_PROFILE(SMBwrite); - return ERROR_DOS(ERRDOS,ERRlock); + return; } /* @@ -3444,43 +3459,47 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d */ nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos); if (nwritten < 0) { + reply_nterror(req, NT_STATUS_DISK_FULL); END_PROFILE(SMBwrite); - return ERROR_NT(NT_STATUS_DISK_FULL); + return; } nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos); if (nwritten < 0) { + reply_nterror(req, NT_STATUS_DISK_FULL); END_PROFILE(SMBwrite); - return ERROR_NT(NT_STATUS_DISK_FULL); + return; } } else nwritten = write_file(fsp,data,startpos,numtowrite); status = sync_file(conn, fsp, False); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBwrite); DEBUG(5,("reply_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBwrite); + return; } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBwrite); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } - outsize = set_message(inbuf,outbuf,1,0,True); + reply_outbuf(req, 1, 0); - SSVAL(outbuf,smb_vwv0,nwritten); + SSVAL(req->outbuf,smb_vwv0,nwritten); if (nwritten < (ssize_t)numtowrite) { - SCVAL(outbuf,smb_rcls,ERRHRD); - SSVAL(outbuf,smb_err,ERRdiskfull); + SCVAL(req->outbuf,smb_rcls,ERRHRD); + SSVAL(req->outbuf,smb_err,ERRdiskfull); } DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); END_PROFILE(SMBwrite); - return(outsize); + return; } /**************************************************************************** -- cgit From 4c7212b4e4099c03049853cd211085030128ffd9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 18:33:29 +0000 Subject: r24426: Convert reply_read to the new API (This used to be commit 30aada0ef8e16ce94035039b63ab140d158009d9) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 59 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c84f4b2dee..e05a941542 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -700,7 +700,7 @@ static const struct smb_message_struct { /* 0x07 */ { "SMBmv",NULL,reply_mv,AS_USER | NEED_WRITE }, /* 0x08 */ { "SMBgetatr",NULL,reply_getatr,AS_USER}, /* 0x09 */ { "SMBsetatr",NULL,reply_setatr,AS_USER | NEED_WRITE}, -/* 0x0a */ { "SMBread",reply_read,NULL,AS_USER}, +/* 0x0a */ { "SMBread",NULL,reply_read,AS_USER}, /* 0x0b */ { "SMBwrite",NULL,reply_write,AS_USER | CAN_IPC }, /* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3805994fb5..37d13bfa96 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2828,26 +2828,41 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Reply to a read. ****************************************************************************/ -int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_read(connection_struct *conn, struct smb_request *req) { size_t numtoread; ssize_t nread = 0; char *data; SMB_OFF_T startpos; int outsize = 0; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; + START_PROFILE(SMBread); - CHECK_FSP(fsp,conn); - if (!CHECK_READ(fsp,inbuf)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBread); + return; } - numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBread); + return; + } + + if (!CHECK_READ(fsp,req->inbuf)) { + reply_doserror(req, ERRDOS, ERRbadaccess); + END_PROFILE(SMBread); + return; + } + + numtoread = SVAL(req->inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); - outsize = set_message(inbuf,outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + /* * The requested read size cannot be greater than max_recv. JRA. */ @@ -2858,32 +2873,38 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", numtoread = MIN(numtoread,max_recv); } - data = smb_buf(outbuf) + 3; + reply_outbuf(req, 5, numtoread+3); + + data = smb_buf(req->outbuf) + 3; - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread, + (SMB_BIG_UINT)startpos, READ_LOCK)) { + reply_doserror(req, ERRDOS,ERRlock); END_PROFILE(SMBread); - return ERROR_DOS(ERRDOS,ERRlock); + return; } if (numtoread > 0) nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) { + reply_unixerror(req, ERRDOS,ERRnoaccess); END_PROFILE(SMBread); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return; } - - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - SCVAL(smb_buf(outbuf),0,1); - SSVAL(smb_buf(outbuf),1,nread); + + set_message(NULL, (char *)req->outbuf, 5, nread+3, False); + + SSVAL(req->outbuf,smb_vwv0,nread); + SSVAL(req->outbuf,smb_vwv5,nread+3); + SCVAL(smb_buf(req->outbuf),0,1); + SSVAL(smb_buf(req->outbuf),1,nread); DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", fsp->fnum, (int)numtoread, (int)nread ) ); END_PROFILE(SMBread); - return(outsize); + return; } /**************************************************************************** -- cgit From ca70ea9310fdf904011ce55cf1122043e2b42b4a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 18:52:58 +0000 Subject: r24427: Convert reply_lock to the new API (This used to be commit 212f43ddeaa6369e5437ed3915eb066a37bc9014) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 32 ++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e05a941542..e0da594450 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -702,7 +702,7 @@ static const struct smb_message_struct { /* 0x09 */ { "SMBsetatr",NULL,reply_setatr,AS_USER | NEED_WRITE}, /* 0x0a */ { "SMBread",NULL,reply_read,AS_USER}, /* 0x0b */ { "SMBwrite",NULL,reply_write,AS_USER | CAN_IPC }, -/* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, +/* 0x0c */ { "SMBlock",NULL,reply_lock,AS_USER}, /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, /* 0x0e */ { "SMBctemp",NULL,reply_ctemp,AS_USER }, /* 0x0f */ { "SMBmknew",NULL,reply_mknew,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 37d13bfa96..00b3e514c6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3974,30 +3974,39 @@ int reply_writeclose(connection_struct *conn, Reply to a lock. ****************************************************************************/ -int reply_lock(connection_struct *conn, - char *inbuf,char *outbuf, int length, int dum_buffsize) +void reply_lock(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; struct byte_range_lock *br_lck = NULL; START_PROFILE(SMBlock); - CHECK_FSP(fsp,conn); + if (req->wct < 5) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBlock); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBlock); + return; + } release_level_2_oplocks_on_change(fsp); - count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); - offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); + count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1); + offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3); DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); br_lck = do_lock(smbd_messaging_context(), fsp, - (uint32)SVAL(inbuf,smb_pid), + req->smbpid, count, offset, WRITE_LOCK, @@ -4009,12 +4018,15 @@ int reply_lock(connection_struct *conn, TALLOC_FREE(br_lck); if (NT_STATUS_V(status)) { + reply_nterror(req, status); END_PROFILE(SMBlock); - return ERROR_NT(status); + return; } + reply_outbuf(req, 0, 0); + END_PROFILE(SMBlock); - return(outsize); + return; } /**************************************************************************** -- cgit From 0f73d64f7dcabffa7b2e512d4c2b5750f6799090 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 19:09:37 +0000 Subject: r24428: Convert reply_unlock to the new API (This used to be commit 01c7426fc0e2af6a955dcb37111ca439fc913d5f) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 35 ++++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e0da594450..64e41ff155 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -703,7 +703,7 @@ static const struct smb_message_struct { /* 0x0a */ { "SMBread",NULL,reply_read,AS_USER}, /* 0x0b */ { "SMBwrite",NULL,reply_write,AS_USER | CAN_IPC }, /* 0x0c */ { "SMBlock",NULL,reply_lock,AS_USER}, -/* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, +/* 0x0d */ { "SMBunlock",NULL,reply_unlock,AS_USER}, /* 0x0e */ { "SMBctemp",NULL,reply_ctemp,AS_USER }, /* 0x0f */ { "SMBmknew",NULL,reply_mknew,AS_USER}, /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 00b3e514c6..e16d8d4f6b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4033,37 +4033,50 @@ void reply_lock(connection_struct *conn, struct smb_request *req) Reply to a unlock. ****************************************************************************/ -int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, - int dum_buffsize) +void reply_unlock(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,0,0,False); SMB_BIG_UINT count,offset; NTSTATUS status; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; + START_PROFILE(SMBunlock); - CHECK_FSP(fsp,conn); + if (req->wct < 5) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBunlock); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBunlock); + return; + } - count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); - offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); + count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1); + offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3); status = do_unlock(smbd_messaging_context(), fsp, - (uint32)SVAL(inbuf,smb_pid), + req->smbpid, count, offset, WINDOWS_LOCK); if (NT_STATUS_V(status)) { + reply_nterror(req, status); END_PROFILE(SMBunlock); - return ERROR_NT(status); + return; } DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) ); - + + reply_outbuf(req, 0, 0); + END_PROFILE(SMBunlock); - return(outsize); + return; } #undef DBGC_CLASS -- cgit From 3f172071d4eb34a462fd481cee53276a9c2b675b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 19:20:25 +0000 Subject: r24429: reply_setdir is not used... (This used to be commit ca27a718b07949959efaeb49f310123de76af9a0) --- source3/smbd/reply.c | 53 ---------------------------------------------------- 1 file changed, 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e16d8d4f6b..59a5caad1a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5737,59 +5737,6 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(outsize); } -/**************************************************************************** - Reply to a setdir. -****************************************************************************/ - -int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) -{ - int snum; - int outsize = 0; - pstring newdir; - NTSTATUS status; - - START_PROFILE(pathworks_setdir); - - snum = SNUM(conn); - if (!CAN_SETDIR(snum)) { - END_PROFILE(pathworks_setdir); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } - - srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir, - smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(pathworks_setdir); - return ERROR_NT(status); - } - - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir); - if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(pathworks_setdir); - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); - } - return ERROR_NT(status); - } - - if (strlen(newdir) != 0) { - if (!vfs_directory_exist(conn,newdir,NULL)) { - END_PROFILE(pathworks_setdir); - return ERROR_DOS(ERRDOS,ERRbadpath); - } - set_conn_connectpath(conn,newdir); - } - - outsize = set_message(inbuf,outbuf,0,0,False); - SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh)); - - DEBUG(3,("setdir %s\n", newdir)); - - END_PROFILE(pathworks_setdir); - return(outsize); -} - #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING -- cgit From 4a989dac81372a8829d3769633c46fcba6e798f3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 19:29:02 +0000 Subject: r24430: Convert reply_writeclose to the new API (This used to be commit 6def2ee03bb3510f000b1977c4d5293cad4ae364) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 54 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 64e41ff155..6751272567 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -734,7 +734,7 @@ static const struct smb_message_struct { /* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE }, /* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, /* 0x2b */ { "SMBecho",NULL,reply_echo,0}, -/* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER}, +/* 0x2c */ { "SMBwriteclose",NULL,reply_writeclose,AS_USER}, /* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC }, /* 0x2e */ { "SMBreadX",NULL,reply_read_and_X,AS_USER | CAN_IPC }, /* 0x2f */ { "SMBwriteX",NULL,reply_write_and_X,AS_USER | CAN_IPC }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 59a5caad1a..9313f3883c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3903,32 +3903,48 @@ void reply_close(connection_struct *conn, struct smb_request *req) Reply to a writeclose (Core+ protocol). ****************************************************************************/ -int reply_writeclose(connection_struct *conn, - char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_writeclose(connection_struct *conn, struct smb_request *req) { size_t numtowrite; ssize_t nwritten = -1; - int outsize = 0; NTSTATUS close_status = NT_STATUS_OK; SMB_OFF_T startpos; char *data; struct timespec mtime; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; + START_PROFILE(SMBwriteclose); - CHECK_FSP(fsp,conn); + if (req->wct < 6) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBwriteclose); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBwriteclose); + return; + } if (!CHECK_WRITE(fsp)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + reply_doserror(req, ERRDOS,ERRbadaccess); + END_PROFILE(SMBwriteclose); + return; } - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4)); - data = smb_buf(inbuf) + 1; + numtowrite = SVAL(req->inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); + mtime = convert_time_t_to_timespec(srv_make_unix_date3( + req->inbuf+smb_vwv4)); + data = smb_buf(req->inbuf) + 1; - if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite + && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite, + (SMB_BIG_UINT)startpos, WRITE_LOCK)) { + reply_doserror(req, ERRDOS,ERRlock); END_PROFILE(SMBwriteclose); - return ERROR_DOS(ERRDOS,ERRlock); + return; } nwritten = write_file(fsp,data,startpos,numtowrite); @@ -3951,20 +3967,22 @@ int reply_writeclose(connection_struct *conn, conn->num_files_open)); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + reply_doserror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBwriteclose); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } if(!NT_STATUS_IS_OK(close_status)) { + reply_nterror(req, close_status); END_PROFILE(SMBwriteclose); - return ERROR_NT(close_status); + return; } - - outsize = set_message(inbuf,outbuf,1,0,True); + + reply_outbuf(req, 1, 0); - SSVAL(outbuf,smb_vwv0,nwritten); + SSVAL(req->outbuf,smb_vwv0,nwritten); END_PROFILE(SMBwriteclose); - return(outsize); + return; } #undef DBGC_CLASS -- cgit From 591669ba066cde377c0c14e3473f23b35530b4ba Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 19:45:24 +0000 Subject: r24431: Convert the reply_printXX calls to the new API (This used to be commit e528479f56bc936cc60eb95c9738a48de48dbd05) --- source3/smbd/process.c | 8 +-- source3/smbd/reply.c | 154 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 111 insertions(+), 51 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6751272567..be311b4135 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -882,10 +882,10 @@ static const struct smb_message_struct { /* 0xbd */ { NULL, NULL, NULL, 0 }, /* 0xbe */ { NULL, NULL, NULL, 0 }, /* 0xbf */ { NULL, NULL, NULL, 0 }, -/* 0xc0 */ { "SMBsplopen",reply_printopen,NULL,AS_USER}, -/* 0xc1 */ { "SMBsplwr",reply_printwrite,NULL,AS_USER}, -/* 0xc2 */ { "SMBsplclose",reply_printclose,NULL,AS_USER}, -/* 0xc3 */ { "SMBsplretq",reply_printqueue,NULL,AS_USER}, +/* 0xc0 */ { "SMBsplopen",NULL,reply_printopen,AS_USER}, +/* 0xc1 */ { "SMBsplwr",NULL,reply_printwrite,AS_USER}, +/* 0xc2 */ { "SMBsplclose",NULL,reply_printclose,AS_USER}, +/* 0xc3 */ { "SMBsplretq",NULL,reply_printqueue,AS_USER}, /* 0xc4 */ { NULL, NULL, NULL, 0 }, /* 0xc5 */ { NULL, NULL, NULL, 0 }, /* 0xc6 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9313f3883c..1d0791a899 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4187,55 +4187,72 @@ void reply_echo(connection_struct *conn, struct smb_request *req) Reply to a printopen. ****************************************************************************/ -int reply_printopen(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printopen(connection_struct *conn, struct smb_request *req) { - int outsize = 0; files_struct *fsp; NTSTATUS status; START_PROFILE(SMBsplopen); - + + if (req->wct < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplopen); + return; + } + if (!CAN_PRINT(conn)) { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsplopen); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } /* Open for exclusive use, write only. */ status = print_fsp_open(conn, NULL, &fsp); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBsplopen); - return(ERROR_NT(status)); + return; } - outsize = set_message(inbuf,outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); + reply_outbuf(req, 1, 0); + SSVAL(req->outbuf,smb_vwv0,fsp->fnum); DEBUG(3,("openprint fd=%d fnum=%d\n", fsp->fh->fd, fsp->fnum)); END_PROFILE(SMBsplopen); - return(outsize); + return; } /**************************************************************************** Reply to a printclose. ****************************************************************************/ -int reply_printclose(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printclose(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,0,0,False); - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; NTSTATUS status; + START_PROFILE(SMBsplclose); - CHECK_FSP(fsp,conn); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplclose); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBsplclose); + return; + } if (!CAN_PRINT(conn)) { + reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror)); END_PROFILE(SMBsplclose); - return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror)); + return; } DEBUG(3,("printclose fd=%d fnum=%d\n", @@ -4244,39 +4261,50 @@ int reply_printclose(connection_struct *conn, status = close_file(fsp,NORMAL_CLOSE); if(!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBsplclose); - return ERROR_NT(status); + return; } END_PROFILE(SMBsplclose); - return(outsize); + return; } /**************************************************************************** Reply to a printqueue. ****************************************************************************/ -int reply_printqueue(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printqueue(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,2,3,True); - int max_count = SVAL(inbuf,smb_vwv0); - int start_index = SVAL(inbuf,smb_vwv1); + int max_count; + int start_index; + START_PROFILE(SMBsplretq); + if (req->wct < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplretq); + return; + } + + max_count = SVAL(req->inbuf,smb_vwv0); + start_index = SVAL(req->inbuf,smb_vwv1); + /* we used to allow the client to get the cnum wrong, but that is really quite gross and only worked when there was only one printer - I think we should now only accept it if they get it right (tridge) */ if (!CAN_PRINT(conn)) { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsplretq); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } - SSVAL(outbuf,smb_vwv0,0); - SSVAL(outbuf,smb_vwv1,0); - SCVAL(smb_buf(outbuf),0,1); - SSVAL(smb_buf(outbuf),1,0); + reply_outbuf(req, 2, 3); + SSVAL(req->outbuf,smb_vwv0,0); + SSVAL(req->outbuf,smb_vwv1,0); + SCVAL(smb_buf(req->outbuf),0,1); + SSVAL(smb_buf(req->outbuf),1,0); DEBUG(3,("printqueue start_index=%d max_count=%d\n", start_index, max_count)); @@ -4284,7 +4312,6 @@ int reply_printqueue(connection_struct *conn, { print_queue_struct *queue = NULL; print_status_struct status; - char *p = smb_buf(outbuf) + 3; int count = print_queue_status(SNUM(conn), &queue, &status); int num_to_get = ABS(max_count); int first = (max_count>0?start_index:start_index+max_count+1); @@ -4297,22 +4324,33 @@ int reply_printqueue(connection_struct *conn, for (i=first;iflags2, p+12, queue[i].fs_user, 16, STR_ASCII); - p += 28; + + if (message_push_blob( + &req->outbuf, + data_blob_const( + blob, sizeof(blob))) == -1) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsplretq); + return; + } } if (count > 0) { - outsize = set_message(inbuf,outbuf,2,28*count+3,False); - SSVAL(outbuf,smb_vwv0,count); - SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); - SCVAL(smb_buf(outbuf),0,1); - SSVAL(smb_buf(outbuf),1,28*count); + SSVAL(req->outbuf,smb_vwv0,count); + SSVAL(req->outbuf,smb_vwv1, + (max_count>0?first+count:first-1)); + SCVAL(smb_buf(req->outbuf),0,1); + SSVAL(smb_buf(req->outbuf),1,28*count); } SAFE_FREE(queue); @@ -4321,44 +4359,66 @@ int reply_printqueue(connection_struct *conn, } END_PROFILE(SMBsplretq); - return(outsize); + return; } /**************************************************************************** Reply to a printwrite. ****************************************************************************/ -int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printwrite(connection_struct *conn, struct smb_request *req) { int numtowrite; - int outsize = set_message(inbuf,outbuf,0,0,False); char *data; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; START_PROFILE(SMBsplwr); + + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplwr); + return; + } + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBsplwr); + return; + } + if (!CAN_PRINT(conn)) { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsplwr); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } - CHECK_FSP(fsp,conn); if (!CHECK_WRITE(fsp)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + reply_doserror(req, ERRDOS, ERRbadaccess); + END_PROFILE(SMBsplwr); + return; } - numtowrite = SVAL(smb_buf(inbuf),1); - data = smb_buf(inbuf) + 3; - + numtowrite = SVAL(smb_buf(req->inbuf),1); + + if (smb_buflen(req->inbuf) < numtowrite + 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplwr); + return; + } + + data = smb_buf(req->inbuf) + 3; + if (write_file(fsp,data,-1,numtowrite) != numtowrite) { + reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBsplwr); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); END_PROFILE(SMBsplwr); - return(outsize); + return; } /**************************************************************************** -- cgit From 2ea14d4e987e9cad627e4a66eb20ab545305b965 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 20:02:11 +0000 Subject: r24433: Convert reply_ntrename to the new API (This used to be commit 42b07a52b9f4fe147426e9156958cb4d33691678) --- source3/smbd/nttrans.c | 81 +++++++++++++++++++++++++++++++------------------- source3/smbd/process.c | 2 +- 2 files changed, 52 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 85103e0e69..1b6c324e9d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1940,76 +1940,94 @@ static NTSTATUS copy_internals(connection_struct *conn, Reply to a NT rename request. ****************************************************************************/ -int reply_ntrename(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +void reply_ntrename(connection_struct *conn, struct smb_request *req) { - int outsize = 0; pstring oldname; pstring newname; char *p; NTSTATUS status; BOOL src_has_wcard = False; BOOL dest_has_wcard = False; - uint32 attrs = SVAL(inbuf,smb_vwv0); - uint16 rename_type = SVAL(inbuf,smb_vwv1); - struct smb_request req; + uint32 attrs; + uint16 rename_type; START_PROFILE(SMBntrename); - init_smb_request(&req, (uint8 *)inbuf); + if (req->wct < 4) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBntrename); + return; + } + + attrs = SVAL(req->inbuf,smb_vwv0); + rename_type = SVAL(req->inbuf,smb_vwv1); - p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), oldname, p, + p = smb_buf(req->inbuf) + 1; + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBntrename); - return ERROR_NT(status); + return; } if( is_ntfs_stream_name(oldname)) { /* Can't rename a stream. */ + reply_nterror(req, NT_STATUS_ACCESS_DENIED); END_PROFILE(SMBntrename); - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + return; } if (ms_has_wild(oldname)) { + reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); END_PROFILE(SMBntrename); - return ERROR_NT(NT_STATUS_OBJECT_PATH_SYNTAX_BAD); + return; } p++; - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBntrename); - return ERROR_NT(status); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + oldname); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBntrename); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBntrename); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBntrename); + return; } - status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + newname); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBntrename); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBntrename); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBntrename); + return; } DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); switch(rename_type) { case RENAME_FLAG_RENAME: - status = rename_internals(conn, &req, oldname, newname, + status = rename_internals(conn, req, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard); break; @@ -2026,7 +2044,7 @@ int reply_ntrename(connection_struct *conn, /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { - status = copy_internals(conn, &req, oldname, + status = copy_internals(conn, req, oldname, newname, attrs); } break; @@ -2039,18 +2057,21 @@ int reply_ntrename(connection_struct *conn, } if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBntrename); - if (open_was_deferred(SVAL(inbuf,smb_mid))) { + if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return -1; + END_PROFILE(SMBntrename); + return; } - return ERROR_NT(status); + + reply_nterror(req, status); + END_PROFILE(SMBntrename); + return; } - outsize = set_message(inbuf,outbuf,0,0,False); + reply_outbuf(req, 0, 0); END_PROFILE(SMBntrename); - return(outsize); + return; } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index be311b4135..837991f2ee 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -855,7 +855,7 @@ static const struct smb_message_struct { /* 0xa2 */ { "SMBntcreateX", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC }, /* 0xa3 */ { NULL, NULL, NULL, 0 }, /* 0xa4 */ { "SMBntcancel", NULL,reply_ntcancel, 0 }, -/* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE }, +/* 0xa5 */ { "SMBntrename", NULL,reply_ntrename, AS_USER | NEED_WRITE }, /* 0xa6 */ { NULL, NULL, NULL, 0 }, /* 0xa7 */ { NULL, NULL, NULL, 0 }, /* 0xa8 */ { NULL, NULL, NULL, 0 }, -- cgit From 05fafc1df28e7848a1e6869d0103ea96dc21f0e4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 20:20:51 +0000 Subject: r24436: Convert reply_lockread/writeunlock to the new API (This used to be commit 1b6add251ca1db565a03407db30884132dd93e7d) --- source3/smbd/process.c | 4 +- source3/smbd/reply.c | 118 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 837991f2ee..aaaf475d2e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -709,8 +709,8 @@ static const struct smb_message_struct { /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, /* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR}, /* 0x12 */ { "SMBlseek",NULL,reply_lseek,AS_USER}, -/* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER}, -/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER}, +/* 0x13 */ { "SMBlockread",NULL,reply_lockread,AS_USER}, +/* 0x14 */ { "SMBwriteunlock",NULL,reply_writeunlock,AS_USER}, /* 0x15 */ { NULL, NULL, NULL, 0 }, /* 0x16 */ { NULL, NULL, NULL, 0 }, /* 0x17 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1d0791a899..f41387fb68 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2741,31 +2741,47 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req) Reply to a lockread (core+ protocol). ****************************************************************************/ -int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz) +void reply_lockread(connection_struct *conn, struct smb_request *req) { ssize_t nread = -1; char *data; - int outsize = 0; SMB_OFF_T startpos; size_t numtoread; NTSTATUS status; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; struct byte_range_lock *br_lck = NULL; + START_PROFILE(SMBlockread); - CHECK_FSP(fsp,conn); - if (!CHECK_READ(fsp,inbuf)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + if (req->wct < 5) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBlockread); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBlockread); + return; + } + + if (!CHECK_READ(fsp,req->inbuf)) { + reply_doserror(req, ERRDOS, ERRbadaccess); + END_PROFILE(SMBlockread); + return; } release_level_2_oplocks_on_change(fsp); - numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - - outsize = set_message(inbuf,outbuf,5,3,True); - numtoread = MIN(BUFFER_SIZE-outsize,numtoread); - data = smb_buf(outbuf) + 3; + numtoread = SVAL(req->inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); + + numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread); + + reply_outbuf(req, 5, numtoread + 3); + + data = smb_buf(req->outbuf) + 3; /* * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+ @@ -2777,7 +2793,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length br_lck = do_lock(smbd_messaging_context(), fsp, - (uint32)SVAL(inbuf,smb_pid), + req->smbpid, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, @@ -2788,8 +2804,9 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length TALLOC_FREE(br_lck); if (NT_STATUS_V(status)) { + reply_nterror(req, status); END_PROFILE(SMBlockread); - return ERROR_NT(status); + return; } /* @@ -2805,20 +2822,22 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) { + reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBlockread); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return; } - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - SSVAL(smb_buf(outbuf),1,nread); + set_message(NULL, (char *)req->outbuf, 5, nread+3, False); + + SSVAL(req->outbuf,smb_vwv0,nread); + SSVAL(req->outbuf,smb_vwv5,nread+3); + SSVAL(smb_buf(req->outbuf),1,nread); DEBUG(3,("lockread fnum=%d num=%d nread=%d\n", fsp->fnum, (int)numtoread, (int)nread)); END_PROFILE(SMBlockread); - return(outsize); + return; } #undef DBGC_CLASS @@ -3341,30 +3360,46 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, Reply to a writeunlock (core+). ****************************************************************************/ -int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, - int size, int dum_buffsize) +void reply_writeunlock(connection_struct *conn, struct smb_request *req) { ssize_t nwritten = -1; size_t numtowrite; SMB_OFF_T startpos; char *data; NTSTATUS status = NT_STATUS_OK; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); - int outsize = 0; + files_struct *fsp; + START_PROFILE(SMBwriteunlock); + + if (req->wct < 5) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBwriteunlock); + return; + } - CHECK_FSP(fsp,conn); + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBwriteunlock); + return; + } + if (!CHECK_WRITE(fsp)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + reply_doserror(req, ERRDOS,ERRbadaccess); + END_PROFILE(SMBwriteunlock); + return; } - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - data = smb_buf(inbuf) + 3; + numtowrite = SVAL(req->inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); + data = smb_buf(req->inbuf) + 3; - if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite + && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite, + (SMB_BIG_UINT)startpos, WRITE_LOCK)) { + reply_doserror(req, ERRDOS, ERRlock); END_PROFILE(SMBwriteunlock); - return ERROR_DOS(ERRDOS,ERRlock); + return; } /* The special X/Open SMB protocol handling of @@ -3378,40 +3413,43 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, status = sync_file(conn, fsp, False /* write through */); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBwriteunlock); DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBwriteunlock); + return; } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBwriteunlock); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } if (numtowrite) { status = do_unlock(smbd_messaging_context(), fsp, - (uint32)SVAL(inbuf,smb_pid), + req->smbpid, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, WINDOWS_LOCK); if (NT_STATUS_V(status)) { + reply_nterror(req, status); END_PROFILE(SMBwriteunlock); - return ERROR_NT(status); + return; } } + + reply_outbuf(req, 1, 0); - outsize = set_message(inbuf,outbuf,1,0,True); - - SSVAL(outbuf,smb_vwv0,nwritten); + SSVAL(req->outbuf,smb_vwv0,nwritten); DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); END_PROFILE(SMBwriteunlock); - return outsize; + return; } #undef DBGC_CLASS -- cgit From 90741da80bf99fea22d9ee3a03a0f0994d0da6a3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 20:55:24 +0000 Subject: r24439: Convert reply_get/setattrE to the new API (This used to be commit 6b0ad071d85ddd8fbf24386db11688bde49baf81) --- source3/smbd/process.c | 4 +-- source3/smbd/reply.c | 75 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 52 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index aaaf475d2e..c198aa7c0c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -724,8 +724,8 @@ static const struct smb_message_struct { /* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER}, /* 0x20 */ { "SMBwritec",NULL, NULL,0}, /* 0x21 */ { NULL, NULL, NULL, 0 }, -/* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE }, -/* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER }, +/* 0x22 */ { "SMBsetattrE",NULL,reply_setattrE,AS_USER | NEED_WRITE }, +/* 0x23 */ { "SMBgetattrE",NULL,reply_getattrE,AS_USER }, /* 0x24 */ { "SMBlockingX",NULL,reply_lockingX,AS_USER }, /* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC }, /* 0x26 */ { "SMBtranss",NULL,reply_transs,AS_USER | CAN_IPC}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f41387fb68..2b2fc7c895 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -6430,28 +6430,40 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, Reply to a SMBsetattrE. ****************************************************************************/ -int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_setattrE(connection_struct *conn, struct smb_request *req) { struct timespec ts[2]; - int outsize = 0; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; + START_PROFILE(SMBsetattrE); - outsize = set_message(inbuf,outbuf,0,0,False); + if (req->wct < 7) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsetattrE); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); if(!fsp || (fsp->conn != conn)) { + reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBsetattrE); - return ERROR_DOS(ERRDOS,ERRbadfid); + return; } + /* * Convert the DOS times into unix times. Ignore create * time as UNIX can't set this. */ - ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */ - ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */ + ts[0] = convert_time_t_to_timespec( + srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */ + ts[1] = convert_time_t_to_timespec( + srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */ + reply_outbuf(req, 0, 0); + /* * Patch from Ray Frush * Sometimes times are sent as zero - ignore them. @@ -6464,7 +6476,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); } END_PROFILE(SMBsetattrE); - return(outsize); + return; } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) { /* set modify time = to access time if modify time was unset */ ts[1] = ts[0]; @@ -6473,8 +6485,9 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, /* Set the date on this file */ /* Should we set pending modtime here ? JRA */ if(file_ntimes(conn, fsp->fsp_name, ts)) { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetattrE); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n", @@ -6483,7 +6496,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, (unsigned int)ts[1].tv_sec)); END_PROFILE(SMBsetattrE); - return(outsize); + return; } @@ -6699,25 +6712,33 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz Reply to a SMBgetattrE. ****************************************************************************/ -int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_getattrE(connection_struct *conn, struct smb_request *req) { SMB_STRUCT_STAT sbuf; - int outsize = 0; int mode; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; + START_PROFILE(SMBgetattrE); - outsize = set_message(inbuf,outbuf,11,0,True); + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBgetattrE); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); if(!fsp || (fsp->conn != conn)) { + reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBgetattrE); - return ERROR_DOS(ERRDOS,ERRbadfid); + return; } /* Do an fstat on this file */ if(fsp_stat(fsp, &sbuf)) { + reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBgetattrE); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return; } mode = dos_mode(conn,fsp->fsp_name,&sbuf); @@ -6728,23 +6749,27 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, * this. */ - srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); - srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); + reply_outbuf(req, 11, 0); + + srv_put_dos_date2((char *)req->outbuf, smb_vwv0, + get_create_time(&sbuf, + lp_fake_dir_create_times(SNUM(conn)))); + srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime); /* Should we check pending modtime here ? JRA */ - srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); + srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime); if (mode & aDIR) { - SIVAL(outbuf,smb_vwv6,0); - SIVAL(outbuf,smb_vwv8,0); + SIVAL(req->outbuf, smb_vwv6, 0); + SIVAL(req->outbuf, smb_vwv8, 0); } else { uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf); - SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); - SIVAL(outbuf,smb_vwv8,allocation_size); + SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size); + SIVAL(req->outbuf, smb_vwv8, allocation_size); } - SSVAL(outbuf,smb_vwv10, mode); + SSVAL(req->outbuf,smb_vwv10, mode); DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum)); END_PROFILE(SMBgetattrE); - return(outsize); + return; } -- cgit From c5572072e5c50883a643ebd55295c7fb4d10fe3e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 21:07:44 +0000 Subject: r24440: Convert the reply_sendXX functions to the new API (This used to be commit a64bc31098de8694b79eeafd3a226cf519700707) --- source3/smbd/message.c | 62 +++++++++++++++++++++++++------------------------- source3/smbd/process.c | 8 +++---- 2 files changed, 35 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index fa4c9e69ef..b044b6f92d 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -114,11 +114,10 @@ static void msg_deliver(void) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_sends(connection_struct *conn, struct smb_request *req) { int len; char *msg; - int outsize = 0; char *p; START_PROFILE(SMBsends); @@ -126,16 +125,15 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, msgpos = 0; if (! (*lp_msg_command())) { + reply_doserror(req, ERRSRV, ERRmsgoff); END_PROFILE(SMBsends); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); + return; } - outsize = set_message(inbuf,outbuf,0,0,True); - - p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p, + p = smb_buf(req->inbuf)+1; + p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p, + p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; msg = p; @@ -150,8 +148,10 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, msg_deliver(); + reply_outbuf(req, 0, 0); + END_PROFILE(SMBsends); - return(outsize); + return; } /**************************************************************************** @@ -159,33 +159,33 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_sendstrt(connection_struct *conn, struct smb_request *req) { - int outsize = 0; char *p; START_PROFILE(SMBsendstrt); if (! (*lp_msg_command())) { + reply_doserror(req, ERRSRV, ERRmsgoff); END_PROFILE(SMBsendstrt); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); + return; } - outsize = set_message(inbuf,outbuf,1,0,True); - memset(msgbuf,'\0',sizeof(msgbuf)); msgpos = 0; - p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p, + p = smb_buf(req->inbuf)+1; + p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p, + p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); + reply_outbuf(req, 0, 0); + END_PROFILE(SMBsendstrt); - return(outsize); + return; } /**************************************************************************** @@ -193,21 +193,19 @@ int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_si conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sendtxt(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_sendtxt(connection_struct *conn, struct smb_request *req) { int len; - int outsize = 0; char *msg; START_PROFILE(SMBsendtxt); if (! (*lp_msg_command())) { + reply_doserror(req, ERRSRV, ERRmsgoff); END_PROFILE(SMBsendtxt); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); + return; } - outsize = set_message(inbuf,outbuf,0,0,True); - - msg = smb_buf(inbuf) + 1; + msg = smb_buf(req->inbuf) + 1; len = SVAL(msg,0); len = MIN(len,sizeof(msgbuf)-msgpos); @@ -217,8 +215,10 @@ int reply_sendtxt(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz DEBUG( 3, ( "SMBsendtxt\n" ) ); + reply_outbuf(req, 0, 0); + END_PROFILE(SMBsendtxt); - return(outsize); + return; } /**************************************************************************** @@ -226,22 +226,22 @@ int reply_sendtxt(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_sendend(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_sendend(connection_struct *conn, struct smb_request *req) { - int outsize = 0; START_PROFILE(SMBsendend); if (! (*lp_msg_command())) { + reply_doserror(req, ERRSRV, ERRmsgoff); END_PROFILE(SMBsendend); - return(ERROR_DOS(ERRSRV,ERRmsgoff)); + return; } - outsize = set_message(inbuf,outbuf,0,0,True); - DEBUG(3,("SMBsendend\n")); msg_deliver(); + reply_outbuf(req, 0, 0); + END_PROFILE(SMBsendend); - return(outsize); + return; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c198aa7c0c..671b7116fa 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -898,14 +898,14 @@ static const struct smb_message_struct { /* 0xcd */ { NULL, NULL, NULL, 0 }, /* 0xce */ { NULL, NULL, NULL, 0 }, /* 0xcf */ { NULL, NULL, NULL, 0 }, -/* 0xd0 */ { "SMBsends",reply_sends,NULL,AS_GUEST}, +/* 0xd0 */ { "SMBsends",NULL,reply_sends,AS_GUEST}, /* 0xd1 */ { "SMBsendb",NULL, NULL,AS_GUEST}, /* 0xd2 */ { "SMBfwdname",NULL, NULL,AS_GUEST}, /* 0xd3 */ { "SMBcancelf",NULL, NULL,AS_GUEST}, /* 0xd4 */ { "SMBgetmac",NULL, NULL,AS_GUEST}, -/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,NULL,AS_GUEST}, -/* 0xd6 */ { "SMBsendend",reply_sendend,NULL,AS_GUEST}, -/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,NULL,AS_GUEST}, +/* 0xd5 */ { "SMBsendstrt",NULL,reply_sendstrt,AS_GUEST}, +/* 0xd6 */ { "SMBsendend",NULL,reply_sendend,AS_GUEST}, +/* 0xd7 */ { "SMBsendtxt",NULL,reply_sendtxt,AS_GUEST}, /* 0xd8 */ { NULL, NULL, NULL, 0 }, /* 0xd9 */ { NULL, NULL, NULL, 0 }, /* 0xda */ { NULL, NULL, NULL, 0 }, -- cgit From 9c2bfffecec108c5ffaf0308390dfd8093881adb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 21:13:05 +0000 Subject: r24441: Convert reply_ioctl to the new API (This used to be commit a5af7ebb7f1d869659fbab187652e68ec4fafbb8) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 56 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 671b7116fa..9604439230 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -729,7 +729,7 @@ static const struct smb_message_struct { /* 0x24 */ { "SMBlockingX",NULL,reply_lockingX,AS_USER }, /* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC }, /* 0x26 */ { "SMBtranss",NULL,reply_transs,AS_USER | CAN_IPC}, -/* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0}, +/* 0x27 */ { "SMBioctl",NULL,reply_ioctl,0}, /* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, /* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE }, /* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2b2fc7c895..f079ef4b21 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -724,56 +724,72 @@ void reply_unknown_new(struct smb_request *req, uint8 type) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_ioctl(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_ioctl(connection_struct *conn, struct smb_request *req) { - uint16 device = SVAL(inbuf,smb_vwv1); - uint16 function = SVAL(inbuf,smb_vwv2); - uint32 ioctl_code = (device << 16) + function; - int replysize, outsize; + uint16 device; + uint16 function; + uint32 ioctl_code; + int replysize; char *p; + START_PROFILE(SMBioctl); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBioctl); + return; + } + + device = SVAL(req->inbuf,smb_vwv1); + function = SVAL(req->inbuf,smb_vwv2); + ioctl_code = (device << 16) + function; + DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: - replysize = 32; - break; + replysize = 32; + break; default: - END_PROFILE(SMBioctl); - return(ERROR_DOS(ERRSRV,ERRnosupport)); + reply_doserror(req, ERRSRV, ERRnosupport); + END_PROFILE(SMBioctl); + return; } - outsize = set_message(inbuf,outbuf,8,replysize+1,True); - SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */ - SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */ - SSVAL(outbuf,smb_vwv6,52); /* Offset to data */ - p = smb_buf(outbuf) + 1; /* Allow for alignment */ + reply_outbuf(req, 8, replysize+1); + SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */ + SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */ + SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */ + p = smb_buf(req->outbuf) + 1; /* Allow for alignment */ switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: { - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp = file_fsp(SVAL(req->inbuf, + smb_vwv0)); if (!fsp) { + reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBioctl); - return(UNIXERROR(ERRDOS,ERRbadfid)); + return; } SSVAL(p,0,fsp->rap_print_jobid); /* Job number */ - srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+2, + srvstr_push((char *)req->outbuf, req->flags2, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII); if (conn) { - srvstr_push(outbuf, SVAL(outbuf, smb_flg2), + srvstr_push((char *)req->outbuf, req->flags2, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); } + else { + memset(p+18, 0, 13); + } break; } } END_PROFILE(SMBioctl); - return outsize; + return; } /**************************************************************************** -- cgit From f93b093d5f3a2cc7b72e1ddff8d84fe70267c23c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 21:21:52 +0000 Subject: r24442: Convert reply_copy to the new API (This used to be commit 0cb00c54750837ab2d2dc12e4947fedb7d38e878) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 122 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 85 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9604439230..ad6ddba737 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -731,7 +731,7 @@ static const struct smb_message_struct { /* 0x26 */ { "SMBtranss",NULL,reply_transs,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",NULL,reply_ioctl,0}, /* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, -/* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE }, +/* 0x29 */ { "SMBcopy",NULL,reply_copy,AS_USER | NEED_WRITE }, /* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, /* 0x2b */ { "SMBecho",NULL,reply_echo,0}, /* 0x2c */ { "SMBwriteclose",NULL,reply_writeclose,AS_USER}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f079ef4b21..831c376e08 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5640,9 +5640,8 @@ NTSTATUS copy_file(connection_struct *conn, Reply to a file copy. ****************************************************************************/ -int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_copy(connection_struct *conn, struct smb_request *req) { - int outsize = 0; pstring name; pstring directory; pstring mask,newname; @@ -5650,32 +5649,45 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int count=0; int error = ERRnoaccess; int err = 0; - int tid2 = SVAL(inbuf,smb_vwv0); - int ofun = SVAL(inbuf,smb_vwv1); - int flags = SVAL(inbuf,smb_vwv2); + int tid2; + int ofun; + int flags; BOOL target_is_directory=False; BOOL source_has_wild = False; BOOL dest_has_wild = False; SMB_STRUCT_STAT sbuf1, sbuf2; NTSTATUS status; + START_PROFILE(SMBcopy); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBcopy); + return; + } + + tid2 = SVAL(req->inbuf,smb_vwv0); + ofun = SVAL(req->inbuf,smb_vwv1); + flags = SVAL(req->inbuf,smb_vwv2); + *directory = *mask = 0; - p = smb_buf(inbuf); - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p, + p = smb_buf(req->inbuf); + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcopy); - return ERROR_NT(status); + return; } - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcopy); - return ERROR_NT(status); + return; } DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); @@ -5683,57 +5695,75 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (tid2 != conn->cnum) { /* can't currently handle inter share copies XXXX */ DEBUG(3,("Rejecting inter-share copy\n")); + reply_doserror(req, ERRSRV, ERRinvdevice); END_PROFILE(SMBcopy); - return ERROR_DOS(ERRSRV,ERRinvdevice); + return; } - status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild); + status = resolve_dfspath_wcard(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + name, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBcopy); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBcopy); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } - status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild); + status = resolve_dfspath_wcard(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + newname, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBcopy); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBcopy); + return; } - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcopy); - return ERROR_NT(status); + return; } status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcopy); - return ERROR_NT(status); + return; } target_is_directory = VALID_STAT_OF_DIR(sbuf2); if ((flags&1) && target_is_directory) { + reply_doserror(req, ERRDOS, ERRbadfile); END_PROFILE(SMBcopy); - return ERROR_DOS(ERRDOS,ERRbadfile); + return; } if ((flags&2) && !target_is_directory) { + reply_doserror(req, ERRDOS, ERRbadpath); END_PROFILE(SMBcopy); - return ERROR_DOS(ERRDOS,ERRbadpath); + return; } if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); + reply_doserror(req, ERRSRV, ERRerror); END_PROFILE(SMBcopy); - return ERROR_DOS(ERRSRV,ERRerror); + return; } p = strrchr_m(name,'/'); @@ -5764,27 +5794,33 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstrcat(directory,mask); if (dest_has_wild) { if (!resolve_wildcards(directory,newname)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBcopy); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return; } } status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } status = check_name(conn, newname); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } status = copy_file(conn,directory,newname,ofun, count,target_is_directory); if(!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBcopy); - return ERROR_NT(status); + return; } else { count++; } @@ -5799,13 +5835,17 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } dir_hnd = OpenDir(conn, directory, mask, 0); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } error = ERRbadfile; @@ -5831,12 +5871,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } status = check_name(conn, destname); if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + reply_nterror(req, status); + END_PROFILE(SMBcopy); + return; } DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname)); @@ -5854,19 +5898,21 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if(err) { /* Error on close... */ errno = err; + reply_unixerror(req, ERRHRD, ERRgeneral); END_PROFILE(SMBcopy); - return(UNIXERROR(ERRHRD,ERRgeneral)); + return; } + reply_doserror(req, ERRDOS, error); END_PROFILE(SMBcopy); - return ERROR_DOS(ERRDOS,error); + return; } - - outsize = set_message(inbuf,outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,count); + + reply_outbuf(req, 1, 0); + SSVAL(req->outbuf,smb_vwv0,count); END_PROFILE(SMBcopy); - return(outsize); + return; } #undef DBGC_CLASS -- cgit From 5edcc342c6b24e41fed826c13a257929f4071668 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 21:32:52 +0000 Subject: r24443: Convert reply_search/fclose to the new API (This used to be commit a8a33c377e38046b4103cf1d59032b97ab6bac9a) --- source3/smbd/process.c | 8 +-- source3/smbd/reply.c | 152 ++++++++++++++++++++++++++++++------------------- 2 files changed, 99 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ad6ddba737..7f307ade63 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -819,10 +819,10 @@ static const struct smb_message_struct { /* 0x7e */ { NULL, NULL, NULL, 0 }, /* 0x7f */ { NULL, NULL, NULL, 0 }, /* 0x80 */ { "SMBdskattr",NULL,reply_dskattr,AS_USER}, -/* 0x81 */ { "SMBsearch",reply_search,NULL,AS_USER}, -/* 0x82 */ { "SMBffirst",reply_search,NULL,AS_USER}, -/* 0x83 */ { "SMBfunique",reply_search,NULL,AS_USER}, -/* 0x84 */ { "SMBfclose",reply_fclose,NULL,AS_USER}, +/* 0x81 */ { "SMBsearch",NULL,reply_search,AS_USER}, +/* 0x82 */ { "SMBffirst",NULL,reply_search,AS_USER}, +/* 0x83 */ { "SMBfunique",NULL,reply_search,AS_USER}, +/* 0x84 */ { "SMBfclose",NULL,reply_fclose,AS_USER}, /* 0x85 */ { NULL, NULL, NULL, 0 }, /* 0x86 */ { NULL, NULL, NULL, 0 }, /* 0x87 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 831c376e08..7ab503906d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1149,7 +1149,7 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req) Can be called from SMBsearch, SMBffirst or SMBfunique. ****************************************************************************/ -int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_search(connection_struct *conn, struct smb_request *req) { pstring mask; pstring directory; @@ -1158,7 +1158,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size uint32 mode; time_t date; uint32 dirtype; - int outsize = 0; unsigned int numentries = 0; unsigned int maxentries = 0; BOOL finished = False; @@ -1171,41 +1170,55 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL expect_close = False; NTSTATUS nt_status; BOOL mask_contains_wcard = False; - BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; + BOOL allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; START_PROFILE(SMBsearch); + if (req->wct < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsearch); + return; + } + if (lp_posix_pathnames()) { + reply_unknown_new(req, CVAL(req->inbuf, smb_com)); END_PROFILE(SMBsearch); - return reply_unknown(inbuf, outbuf); + return; } *mask = *directory = *fname = 0; /* If we were called as SMBffirst then we must expect close. */ - if(CVAL(inbuf,smb_com) == SMBffirst) { + if(CVAL(req->inbuf,smb_com) == SMBffirst) { expect_close = True; } - - outsize = set_message(inbuf,outbuf,1,3,True); - maxentries = SVAL(inbuf,smb_vwv0); - dirtype = SVAL(inbuf,smb_vwv1); - p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p, + + reply_outbuf(req, 1, 3); + maxentries = SVAL(req->inbuf,smb_vwv0); + dirtype = SVAL(req->inbuf,smb_vwv1); + p = smb_buf(req->inbuf) + 1; + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { + reply_nterror(req, nt_status); END_PROFILE(SMBsearch); - return ERROR_NT(nt_status); + return; } - nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard); + nt_status = resolve_dfspath_wcard(conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + path, &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { - END_PROFILE(SMBsearch); if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) { - return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBsearch); + return; } - return ERROR_NT(nt_status); + reply_nterror(req, nt_status); + END_PROFILE(SMBsearch); + return; } p++; @@ -1220,14 +1233,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(directory,path); nt_status = unix_convert(conn, directory, True, NULL, &sbuf); if (!NT_STATUS_IS_OK(nt_status)) { + reply_nterror(req, nt_status); END_PROFILE(SMBsearch); - return ERROR_NT(nt_status); + return; } nt_status = check_name(conn, directory); if (!NT_STATUS_IS_OK(nt_status)) { + reply_nterror(req, nt_status); END_PROFILE(SMBsearch); - return ERROR_NT(nt_status); + return; } p = strrchr_m(directory,'/'); @@ -1266,20 +1281,20 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mask_contains_wcard = ms_has_wild(mask); } - p = smb_buf(outbuf) + 3; - if (status_len == 0) { nt_status = dptr_create(conn, directory, True, expect_close, - SVAL(inbuf,smb_pid), + req->smbpid, mask, mask_contains_wcard, dirtype, &conn->dirptr); if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); + reply_nterror(req, nt_status); + END_PROFILE(SMBsearch); + return; } dptr_num = dptr_dnum(conn->dirptr); } else { @@ -1288,20 +1303,31 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(4,("dptr_num is %d\n",dptr_num)); - if ((dirtype&0x1F) == aVOLID) { - memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(conn)), + if ((dirtype&0x1F) == aVOLID) { + char buf[DIR_STRUCT_SIZE]; + memcpy(buf,status,21); + make_dir_struct(buf,"???????????",volume_label(SNUM(conn)), 0,aVOLID,0,!allow_long_path_components); - dptr_fill(p+12,dptr_num); - if (dptr_zero(p+12) && (status_len==0)) { + dptr_fill(buf+12,dptr_num); + if (dptr_zero(buf+12) && (status_len==0)) { numentries = 1; } else { numentries = 0; } - p += DIR_STRUCT_SIZE; + if (message_push_blob(&req->outbuf, + data_blob_const(buf, sizeof(buf))) + == -1) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsearch); + return; + } } else { unsigned int i; - maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE)); + maxentries = MIN( + maxentries, + ((BUFFER_SIZE - + ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf)) + /DIR_STRUCT_SIZE)); DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn)))); @@ -1312,14 +1338,21 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size for (i=numentries;(ioutbuf, + data_blob_const(buf, sizeof(buf))) + == -1) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsearch); + return; + } numentries++; - p += DIR_STRUCT_SIZE; } } } @@ -1338,49 +1371,51 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } /* If we were called as SMBfunique, then we can close the dirptr now ! */ - if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) { + if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) { dptr_close(&dptr_num); } if ((numentries == 0) && !mask_contains_wcard) { - return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); + reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles); + END_PROFILE(SMBsearch); + return; } - SSVAL(outbuf,smb_vwv0,numentries); - SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); - SCVAL(smb_buf(outbuf),0,5); - SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); + SSVAL(req->outbuf,smb_vwv0,numentries); + SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); + SCVAL(smb_buf(req->outbuf),0,5); + SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE); /* The replies here are never long name. */ - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME)); + SSVAL(req->outbuf, smb_flg2, + SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME)); if (!allow_long_path_components) { - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS)); + SSVAL(req->outbuf, smb_flg2, + SVAL(req->outbuf, smb_flg2) + & (~FLAGS2_LONG_PATH_COMPONENTS)); } /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */ - SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); + SSVAL(req->outbuf, smb_flg2, + (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); - outsize += DIR_STRUCT_SIZE*numentries; - smb_setlen(inbuf,outbuf,outsize - 4); - if ((! *directory) && dptr_path(dptr_num)) slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n", - smb_fn_name(CVAL(inbuf,smb_com)), + smb_fn_name(CVAL(req->inbuf,smb_com)), mask, directory, dirtype, numentries, maxentries ) ); END_PROFILE(SMBsearch); - return(outsize); + return; } /**************************************************************************** Reply to a fclose (stop directory search). ****************************************************************************/ -int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_fclose(connection_struct *conn, struct smb_request *req) { - int outsize = 0; int status_len; pstring path; char status[21]; @@ -1392,26 +1427,28 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size START_PROFILE(SMBfclose); if (lp_posix_pathnames()) { + reply_unknown_new(req, CVAL(req->inbuf, smb_com)); END_PROFILE(SMBfclose); - return reply_unknown(inbuf, outbuf); + return; } - outsize = set_message(inbuf,outbuf,1,0,True); - p = smb_buf(inbuf) + 1; - p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p, + p = smb_buf(req->inbuf) + 1; + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard); if (!NT_STATUS_IS_OK(err)) { + reply_nterror(req, err); END_PROFILE(SMBfclose); - return ERROR_NT(err); + return; } p++; status_len = SVAL(p,0); p += 2; if (status_len == 0) { + reply_doserror(req, ERRSRV, ERRsrverror); END_PROFILE(SMBfclose); - return ERROR_DOS(ERRSRV,ERRsrverror); + return; } memcpy(status,p,21); @@ -1421,12 +1458,13 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dptr_close(&dptr_num); } - SSVAL(outbuf,smb_vwv0,0); + reply_outbuf(req, 1, 0); + SSVAL(req->outbuf,smb_vwv0,0); DEBUG(3,("search close\n")); END_PROFILE(SMBfclose); - return(outsize); + return; } /**************************************************************************** -- cgit From 527905a09a0b5b39830440189a145182b7d571f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 21:53:48 +0000 Subject: r24444: Convert reply_find[n]close to the new API (This used to be commit 6af85953465789594342f2d199ef5d29462cf34f) --- source3/smbd/process.c | 4 ++-- source3/smbd/trans2.c | 38 +++++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7f307ade63..6405ddf1f5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -742,8 +742,8 @@ static const struct smb_message_struct { /* 0x31 */ { NULL, NULL, NULL, 0 }, /* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC }, /* 0x33 */ { "SMBtranss2", NULL,reply_transs2, AS_USER}, -/* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER}, -/* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER}, +/* 0x34 */ { "SMBfindclose", NULL,reply_findclose,AS_USER}, +/* 0x35 */ { "SMBfindnclose", NULL,reply_findnclose,AS_USER}, /* 0x36 */ { NULL, NULL, NULL, 0 }, /* 0x37 */ { NULL, NULL, NULL, 0 }, /* 0x38 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9c4c8556d2..74c287c757 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6816,37 +6816,49 @@ static void call_trans2ioctl(connection_struct *conn, Reply to a SMBfindclose (stop trans2 directory search). ****************************************************************************/ -int reply_findclose(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +void reply_findclose(connection_struct *conn, struct smb_request *req) { - int outsize = 0; - int dptr_num=SVALS(inbuf,smb_vwv0); + int dptr_num; + START_PROFILE(SMBfindclose); + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBfindclose); + return; + } + + dptr_num = SVALS(req->inbuf,smb_vwv0); + DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num)); dptr_close(&dptr_num); - outsize = set_message(inbuf, outbuf,0,0,False); + reply_outbuf(req, 0, 0); DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num)); END_PROFILE(SMBfindclose); - return(outsize); + return; } /**************************************************************************** Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search). ****************************************************************************/ -int reply_findnclose(connection_struct *conn, - char *inbuf,char *outbuf,int length,int bufsize) +void reply_findnclose(connection_struct *conn, struct smb_request *req) { - int outsize = 0; - int dptr_num= -1; + int dptr_num; + START_PROFILE(SMBfindnclose); + + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBfindnclose); + return; + } - dptr_num = SVAL(inbuf,smb_vwv0); + dptr_num = SVAL(req->inbuf,smb_vwv0); DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num)); @@ -6854,12 +6866,12 @@ int reply_findnclose(connection_struct *conn, findnotifyfirst - so any dptr_num is ok here. Just ignore it. */ - outsize = set_message(inbuf, outbuf,0,0,False); + reply_outbuf(req, 0, 0); DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num)); END_PROFILE(SMBfindnclose); - return(outsize); + return; } static void handle_trans2(connection_struct *conn, struct smb_request *req, -- cgit From 2823bf10b520996a20688190d784f45851e1ba24 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Aug 2007 01:54:37 +0000 Subject: r24445: Convert SMBwritebraw. No test suite unfortunately.... I need to write one for this. Jeremy (This used to be commit edc17dfcbd21cccaffb76f4ae67fe4b06520f1a9) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 211 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 151 insertions(+), 62 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6405ddf1f5..b4de0edc28 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -719,7 +719,7 @@ static const struct smb_message_struct { /* 0x1a */ { "SMBreadbraw",NULL,reply_readbraw,AS_USER}, /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER}, /* 0x1c */ { "SMBreadBs",NULL, NULL,0 }, -/* 0x1d */ { "SMBwritebraw",reply_writebraw,NULL,AS_USER}, +/* 0x1d */ { "SMBwritebraw",NULL,reply_writebraw,AS_USER}, /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,NULL,AS_USER}, /* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER}, /* 0x20 */ { "SMBwritec",NULL, NULL,0}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7ab503906d..1a14d6c594 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3258,12 +3258,28 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) return; } +/**************************************************************************** + Error replies to writebraw must have smb_wct == 1. Fix this up. +****************************************************************************/ + +void error_to_writebrawerr(struct smb_request *req) +{ + uint8 *old_outbuf = req->outbuf; + + reply_outbuf(req, 1, 0); + + memcpy(req->outbuf, old_outbuf, smb_size); + TALLOC_FREE(old_outbuf); +} + /**************************************************************************** Reply to a writebraw (core+ or LANMAN1.0 protocol). ****************************************************************************/ -int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_writebraw(connection_struct *conn, struct smb_request *req) { + int outsize = 0; + char *buf = NULL; ssize_t nwritten=0; ssize_t total_written=0; size_t numtowrite=0; @@ -3271,140 +3287,212 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SMB_OFF_T startpos; char *data=NULL; BOOL write_through; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); - int outsize = 0; + files_struct *fsp; NTSTATUS status; + START_PROFILE(SMBwritebraw); + /* + * If we ever reply with an error, it must have the SMB command + * type of SMBwritec, not SMBwriteBraw, as this tells the client + * we're finished. + */ + SCVAL(req->inbuf,smb_com,SMBwritec); + if (srv_is_signing_active()) { - exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed."); + END_PROFILE(SMBwritebraw); + exit_server_cleanly("reply_writebraw: SMB signing is active - " + "raw reads/writes are disallowed."); + } + + if (req->wct < 12) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + error_to_writebrawerr(req); + END_PROFILE(SMBwritebraw); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + if (!check_fsp(conn, req, fsp, ¤t_user)) { + error_to_writebrawerr(req); + END_PROFILE(SMBwritebraw); + return; } - CHECK_FSP(fsp,conn); if (!CHECK_WRITE(fsp)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + reply_doserror(req, ERRDOS, ERRbadaccess); + error_to_writebrawerr(req); + END_PROFILE(SMBwritebraw); + return; } - - tcount = IVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); - write_through = BITSETW(inbuf+smb_vwv7,0); + + tcount = IVAL(req->inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); + write_through = BITSETW(req->inbuf+smb_vwv7,0); /* We have to deal with slightly different formats depending on whether we are using the core+ or lanman1.0 protocol */ if(Protocol <= PROTOCOL_COREPLUS) { - numtowrite = SVAL(smb_buf(inbuf),-2); - data = smb_buf(inbuf); + numtowrite = SVAL(smb_buf(req->inbuf),-2); + data = smb_buf(req->inbuf); } else { - numtowrite = SVAL(inbuf,smb_vwv10); - data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11); + numtowrite = SVAL(req->inbuf,smb_vwv10); + data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11); } - /* force the error type */ - SCVAL(inbuf,smb_com,SMBwritec); - SCVAL(outbuf,smb_com,SMBwritec); + /* Ensure we don't write bytes past the end of this packet. */ + if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + error_to_writebrawerr(req); + END_PROFILE(SMBwritebraw); + return; + } - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount, + (SMB_BIG_UINT)startpos, WRITE_LOCK)) { + reply_doserror(req, ERRDOS, ERRlock); + error_to_writebrawerr(req); END_PROFILE(SMBwritebraw); - return(ERROR_DOS(ERRDOS,ERRlock)); + return; } - if (numtowrite>0) + if (numtowrite>0) { nwritten = write_file(fsp,data,startpos,numtowrite); - - DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", - fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); + } + + DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d " + "wrote=%d sync=%d\n", + fsp->fnum, (double)startpos, (int)numtowrite, + (int)nwritten, (int)write_through)); if (nwritten < (ssize_t)numtowrite) { + reply_unixerror(req, ERRHRD, ERRdiskfull); + error_to_writebrawerr(req); END_PROFILE(SMBwritebraw); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } total_written = nwritten; - /* Return a message to the redirector to tell it to send more bytes */ - SCVAL(outbuf,smb_com,SMBwritebraw); - SSVALS(outbuf,smb_vwv0,-1); - outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("reply_writebraw: send_smb failed."); - + /* Allocate a buffer of 64k + length. */ + buf = TALLOC_ARRAY(NULL, char, 65540); + if (!buf) { + reply_doserror(req, ERRDOS, ERRnomem); + error_to_writebrawerr(req); + END_PROFILE(SMBwritebraw); + return; + } + + /* Return a SMBwritebraw message to the redirector to tell + * it to send more bytes */ + + memcpy(buf, req->inbuf, smb_size); + outsize = set_message(NULL,buf, + Protocol>PROTOCOL_COREPLUS?1:0,0,True); + SCVAL(buf,smb_com,SMBwritebraw); + SSVALS(buf,smb_vwv0,0xFFFF); + show_msg(buf); + if (!send_smb(smbd_server_fd(),buf)) { + exit_server_cleanly("reply_writebraw: send_smb " + "failed."); + } + /* Now read the raw data into the buffer and write it */ - if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { + if (read_smb_length(smbd_server_fd(),buf,SMB_SECONDARY_WAIT) == -1) { exit_server_cleanly("secondary writebraw failed"); } - - /* Even though this is not an smb message, smb_len returns the generic length of an smb message */ - numtowrite = smb_len(inbuf); - /* Set up outbuf to return the correct return */ - outsize = set_message(inbuf,outbuf,1,0,True); - SCVAL(outbuf,smb_com,SMBwritec); + /* + * Even though this is not an smb message, + * smb_len returns the generic length of a packet. + */ + + numtowrite = smb_len(buf); + + /* Set up outbuf to return the correct size */ + reply_outbuf(req, 1, 0); if (numtowrite != 0) { - if (numtowrite > BUFFER_SIZE) { - DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n", + if (numtowrite > 0xFFFF) { + DEBUG(0,("reply_writebraw: Oversize secondary write " + "raw requested (%u). Terminating\n", (unsigned int)numtowrite )); exit_server_cleanly("secondary writebraw failed"); } if (tcount > nwritten+numtowrite) { - DEBUG(3,("Client overestimated the write %d %d %d\n", + DEBUG(3,("reply_writebraw: Client overestimated the " + "write %d %d %d\n", (int)tcount,(int)nwritten,(int)numtowrite)); } - if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) { - DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n", + if (read_data(smbd_server_fd(), buf+4, numtowrite) + != numtowrite ) { + DEBUG(0,("reply_writebraw: Oversize secondary write " + "raw read failed (%s). Terminating\n", strerror(errno) )); exit_server_cleanly("secondary writebraw failed"); } - nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite); + nwritten = write_file(fsp,buf+4,startpos+nwritten,numtowrite); if (nwritten == -1) { + TALLOC_FREE(buf); + reply_unixerror(req, ERRHRD, ERRdiskfull); + error_to_writebrawerr(req); END_PROFILE(SMBwritebraw); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } if (nwritten < (ssize_t)numtowrite) { - SCVAL(outbuf,smb_rcls,ERRHRD); - SSVAL(outbuf,smb_err,ERRdiskfull); + SCVAL(req->outbuf,smb_rcls,ERRHRD); + SSVAL(req->outbuf,smb_err,ERRdiskfull); } - if (nwritten > 0) + if (nwritten > 0) { total_written += nwritten; + } } - - SSVAL(outbuf,smb_vwv0,total_written); + + TALLOC_FREE(buf); + SSVAL(req->outbuf,smb_vwv0,total_written); status = sync_file(conn, fsp, write_through); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); + reply_nterror(req, status); + error_to_writebrawerr(req); END_PROFILE(SMBwritebraw); - return ERROR_NT(status); + return; } - DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", - fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); + DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d " + "wrote=%d\n", + fsp->fnum, (double)startpos, (int)numtowrite, + (int)total_written)); - /* we won't return a status if write through is not selected - this follows what WfWg does */ + /* We won't return a status if write through is not selected - this + * follows what WfWg does */ END_PROFILE(SMBwritebraw); + if (!write_through && total_written==tcount) { #if RABBIT_PELLET_FIX /* * Fix for "rabbit pellet" mode, trigger an early TCP ack by - * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA. + * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. + * JRA. */ - if (!send_keepalive(smbd_server_fd())) - exit_server_cleanly("reply_writebraw: send of keepalive failed"); + if (!send_keepalive(smbd_server_fd())) { + exit_server_cleanly("reply_writebraw: send of " + "keepalive failed"); + } #endif - return(-1); + TALLOC_FREE(req->outbuf); } - - return(outsize); + return; } #undef DBGC_CLASS @@ -3540,6 +3628,7 @@ void reply_write(connection_struct *conn, struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBwrite); return; } -- cgit From 24f42c5cefff01cc69118cb714a053cddb68e4d9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 15 Aug 2007 09:52:09 +0000 Subject: r24453: Remove the read and write bmpx calls Talked to both Tridge and Jeremy about this, Tridge said that there is a special error message persuading OS/2 to fall back to other methods. The calls now checked in always return the error message we used to return when "read bmpx = False" was set (the default): ERRSRV, ERRuseSTD. If someone has a reproducable test case where this is really needed, we can always dig it up from version control and convert it to the new API. But that time without that silly parameter, and with a torture test case for "make test" please :-) Volker (This used to be commit d941aae2dfd11609e807bf4ce712571a2e354627) --- source3/smbd/process.c | 8 +- source3/smbd/reply.c | 284 +++++-------------------------------------------- 2 files changed, 32 insertions(+), 260 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b4de0edc28..e64a18a196 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -717,11 +717,11 @@ static const struct smb_message_struct { /* 0x18 */ { NULL, NULL, NULL, 0 }, /* 0x19 */ { NULL, NULL, NULL, 0 }, /* 0x1a */ { "SMBreadbraw",NULL,reply_readbraw,AS_USER}, -/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER}, -/* 0x1c */ { "SMBreadBs",NULL, NULL,0 }, +/* 0x1b */ { "SMBreadBmpx",NULL,reply_readbmpx,AS_USER}, +/* 0x1c */ { "SMBreadBs",NULL,reply_readbs,AS_USER }, /* 0x1d */ { "SMBwritebraw",NULL,reply_writebraw,AS_USER}, -/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,NULL,AS_USER}, -/* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER}, +/* 0x1e */ { "SMBwriteBmpx",NULL,reply_writebmpx,AS_USER}, +/* 0x1f */ { "SMBwriteBs",NULL,reply_writebs,AS_USER}, /* 0x20 */ { "SMBwritec",NULL, NULL,0}, /* 0x21 */ { NULL, NULL, NULL, 0 }, /* 0x22 */ { "SMBsetattrE",NULL,reply_setattrE,AS_USER | NEED_WRITE }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1a14d6c594..c7040278a5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -6539,80 +6539,30 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) /**************************************************************************** Reply to a SMBreadbmpx (read block multiplex) request. + Always reply with an error, if someone has a platform really needs this, + please contact vl@samba.org ****************************************************************************/ -int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +void reply_readbmpx(connection_struct *conn, struct smb_request *req) { - ssize_t nread = -1; - ssize_t total_read; - char *data; - SMB_OFF_T startpos; - int outsize; - size_t maxcount; - int max_per_packet; - size_t tcount; - int pad; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); START_PROFILE(SMBreadBmpx); + reply_doserror(req, ERRSRV, ERRuseSTD); + END_PROFILE(SMBreadBmpx); + return; +} - /* this function doesn't seem to work - disable by default */ - if (!lp_readbmpx()) { - END_PROFILE(SMBreadBmpx); - return ERROR_DOS(ERRSRV,ERRuseSTD); - } - - outsize = set_message(inbuf,outbuf,8,0,True); - - CHECK_FSP(fsp,conn); - if (!CHECK_READ(fsp,inbuf)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); - } - - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); - maxcount = SVAL(inbuf,smb_vwv3); - - data = smb_buf(outbuf); - pad = ((long)data)%4; - if (pad) - pad = 4 - pad; - data += pad; - - max_per_packet = bufsize-(outsize+pad); - tcount = maxcount; - total_read = 0; - - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { - END_PROFILE(SMBreadBmpx); - return ERROR_DOS(ERRDOS,ERRlock); - } - - do { - size_t N = MIN(max_per_packet,tcount-total_read); - - nread = read_file(fsp,data,startpos,N); - - if (nread <= 0) - nread = 0; - - if (nread < (ssize_t)N) - tcount = total_read + nread; - - set_message(inbuf,outbuf,8,nread+pad,False); - SIVAL(outbuf,smb_vwv0,startpos); - SSVAL(outbuf,smb_vwv2,tcount); - SSVAL(outbuf,smb_vwv6,nread); - SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); - - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("reply_readbmpx: send_smb failed."); - - total_read += nread; - startpos += nread; - } while (total_read < (ssize_t)tcount); +/**************************************************************************** + Reply to a SMBreadbs (read block multiplex secondary) request. + Always reply with an error, if someone has a platform really needs this, + please contact vl@samba.org +****************************************************************************/ - END_PROFILE(SMBreadBmpx); - return(-1); +void reply_readbs(connection_struct *conn, struct smb_request *req) +{ + START_PROFILE(SMBreadBs); + reply_doserror(req, ERRSRV, ERRuseSTD); + END_PROFILE(SMBreadBs); + return; } /**************************************************************************** @@ -6693,208 +6643,30 @@ void reply_setattrE(connection_struct *conn, struct smb_request *req) /**************************************************************************** Reply to a SMBwritebmpx (write block multiplex primary) request. + Always reply with an error, if someone has a platform really needs this, + please contact vl@samba.org ****************************************************************************/ -int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) +void reply_writebmpx(connection_struct *conn, struct smb_request *req) { - size_t numtowrite; - ssize_t nwritten = -1; - int outsize = 0; - SMB_OFF_T startpos; - size_t tcount; - BOOL write_through; - int smb_doff; - char *data; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); - NTSTATUS status; START_PROFILE(SMBwriteBmpx); - - CHECK_FSP(fsp,conn); - if (!CHECK_WRITE(fsp)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); - } - if (HAS_CACHED_ERROR(fsp)) { - return(CACHED_ERROR(fsp)); - } - - tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); - write_through = BITSETW(inbuf+smb_vwv7,0); - numtowrite = SVAL(inbuf,smb_vwv10); - smb_doff = SVAL(inbuf,smb_vwv11); - - data = smb_base(inbuf) + smb_doff; - - /* If this fails we need to send an SMBwriteC response, - not an SMBwritebmpx - set this up now so we don't forget */ - SCVAL(outbuf,smb_com,SMBwritec); - - if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { - END_PROFILE(SMBwriteBmpx); - return(ERROR_DOS(ERRDOS,ERRlock)); - } - - nwritten = write_file(fsp,data,startpos,numtowrite); - - status = sync_file(conn, fsp, write_through); - if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBwriteBmpx); - DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status) )); - return ERROR_NT(status); - } - - if(nwritten < (ssize_t)numtowrite) { - END_PROFILE(SMBwriteBmpx); - return(UNIXERROR(ERRHRD,ERRdiskfull)); - } - - /* If the maximum to be written to this file - is greater than what we just wrote then set - up a secondary struct to be attached to this - fd, we will use this to cache error messages etc. */ - - if((ssize_t)tcount > nwritten) { - write_bmpx_struct *wbms; - if(fsp->wbmpx_ptr != NULL) - wbms = fsp->wbmpx_ptr; /* Use an existing struct */ - else - wbms = SMB_MALLOC_P(write_bmpx_struct); - if(!wbms) { - DEBUG(0,("Out of memory in reply_readmpx\n")); - END_PROFILE(SMBwriteBmpx); - return(ERROR_DOS(ERRSRV,ERRnoresource)); - } - wbms->wr_mode = write_through; - wbms->wr_discard = False; /* No errors yet */ - wbms->wr_total_written = nwritten; - wbms->wr_errclass = 0; - wbms->wr_error = 0; - fsp->wbmpx_ptr = wbms; - } - - /* We are returning successfully, set the message type back to - SMBwritebmpx */ - SCVAL(outbuf,smb_com,SMBwriteBmpx); - - outsize = set_message(inbuf,outbuf,1,0,True); - - SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ - - DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n", - fsp->fnum, (int)numtowrite, (int)nwritten ) ); - - if (write_through && tcount==nwritten) { - /* We need to send both a primary and a secondary response */ - smb_setlen(inbuf,outbuf,outsize - 4); - show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("reply_writebmpx: send_smb failed."); - - /* Now the secondary */ - outsize = set_message(inbuf,outbuf,1,0,True); - SCVAL(outbuf,smb_com,SMBwritec); - SSVAL(outbuf,smb_vwv0,nwritten); - } - + reply_doserror(req, ERRSRV, ERRuseSTD); END_PROFILE(SMBwriteBmpx); - return(outsize); + return; } /**************************************************************************** Reply to a SMBwritebs (write block multiplex secondary) request. + Always reply with an error, if someone has a platform really needs this, + please contact vl@samba.org ****************************************************************************/ -int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_writebs(connection_struct *conn, struct smb_request *req) { - size_t numtowrite; - ssize_t nwritten = -1; - int outsize = 0; - SMB_OFF_T startpos; - size_t tcount; - BOOL write_through; - int smb_doff; - char *data; - write_bmpx_struct *wbms; - BOOL send_response = False; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); - NTSTATUS status; START_PROFILE(SMBwriteBs); - - CHECK_FSP(fsp,conn); - if (!CHECK_WRITE(fsp)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); - } - - tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - numtowrite = SVAL(inbuf,smb_vwv6); - smb_doff = SVAL(inbuf,smb_vwv7); - - data = smb_base(inbuf) + smb_doff; - - /* We need to send an SMBwriteC response, not an SMBwritebs */ - SCVAL(outbuf,smb_com,SMBwritec); - - /* This fd should have an auxiliary struct attached, - check that it does */ - wbms = fsp->wbmpx_ptr; - if(!wbms) { - END_PROFILE(SMBwriteBs); - return(-1); - } - - /* If write through is set we can return errors, else we must cache them */ - write_through = wbms->wr_mode; - - /* Check for an earlier error */ - if(wbms->wr_discard) { - END_PROFILE(SMBwriteBs); - return -1; /* Just discard the packet */ - } - - nwritten = write_file(fsp,data,startpos,numtowrite); - - status = sync_file(conn, fsp, write_through); - - if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) { - if(write_through) { - /* We are returning an error - we can delete the aux struct */ - if (wbms) - free((char *)wbms); - fsp->wbmpx_ptr = NULL; - END_PROFILE(SMBwriteBs); - return(ERROR_DOS(ERRHRD,ERRdiskfull)); - } - wbms->wr_errclass = ERRHRD; - wbms->wr_error = ERRdiskfull; - wbms->wr_status = NT_STATUS_DISK_FULL; - wbms->wr_discard = True; - END_PROFILE(SMBwriteBs); - return -1; - } - - /* Increment the total written, if this matches tcount - we can discard the auxiliary struct (hurrah !) and return a writeC */ - wbms->wr_total_written += nwritten; - if(wbms->wr_total_written >= tcount) { - if (write_through) { - outsize = set_message(inbuf,outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); - send_response = True; - } - - free((char *)wbms); - fsp->wbmpx_ptr = NULL; - } - - if(send_response) { - END_PROFILE(SMBwriteBs); - return(outsize); - } - + reply_doserror(req, ERRSRV, ERRuseSTD); END_PROFILE(SMBwriteBs); - return(-1); + return; } /**************************************************************************** -- cgit From 716e01d97e91227a0d03cbd5e74e4a36efc223eb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 15 Aug 2007 10:29:47 +0000 Subject: r24457: Convert reply_tcon to the new API Jeremy, I really apologize for doing this, but I just wanted to enjoy converting the last SMB call :-) I've left one little task for you there, I'm not certain that checking the inbuf length is correct here. Volker (This used to be commit 1e08fddafda11961f8855423b29c1f8a9a6b4457) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 54 +++++++++++++++++++++++--------------------------- 2 files changed, 26 insertions(+), 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e64a18a196..bf86603924 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -802,7 +802,7 @@ static const struct smb_message_struct { /* 0x6d */ { NULL, NULL, NULL, 0 }, /* 0x6e */ { NULL, NULL, NULL, 0 }, /* 0x6f */ { NULL, NULL, NULL, 0 }, -/* 0x70 */ { "SMBtcon",reply_tcon,NULL,0}, +/* 0x70 */ { "SMBtcon",NULL,reply_tcon,0}, /* 0x71 */ { "SMBtdis",NULL,reply_tdis,DO_CHDIR}, /* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0}, /* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0}, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c7040278a5..a95f2ec87e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -429,16 +429,12 @@ void reply_special(char *inbuf) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -int reply_tcon(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_tcon(connection_struct *conn, struct smb_request *req) { - TALLOC_CTX *ctx; const char *service; char *service_buf = NULL; char *password = NULL; char *dev = NULL; - int outsize = 0; - uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; NTSTATUS nt_status; char *p; @@ -446,25 +442,26 @@ int reply_tcon(connection_struct *conn, START_PROFILE(SMBtcon); - ctx = talloc_init("reply_tcon"); - if (!ctx) { - END_PROFILE(SMBtcon); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - p = smb_buf(inbuf)+1; - p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), - &service_buf, p, STR_TERMINATE) + 1; - pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), - &password, p, STR_TERMINATE) + 1; + /******************************************************************** + * Warning! I'm not sure that the inbuf length check is actually + * correct here. -- vl + * + * Jeremy, please check and remove this comment :-) + ********************************************************************/ + + p = smb_buf(req->inbuf)+1; + p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, + &service_buf, p, STR_TERMINATE) + 1; + pwlen = srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, + &password, p, STR_TERMINATE) + 1; p += pwlen; - p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), - &dev, p, STR_TERMINATE) + 1; + p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, + &dev, p, STR_TERMINATE) + 1; if (service_buf == NULL || password == NULL || dev == NULL) { - TALLOC_FREE(ctx); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtcon); - return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + return; } p = strrchr_m(service_buf,'\\'); if (p) { @@ -475,27 +472,26 @@ int reply_tcon(connection_struct *conn, password_blob = data_blob(password, pwlen+1); - conn = make_connection(service,password_blob,dev,vuid,&nt_status); + conn = make_connection(service,password_blob,dev,req->vuid,&nt_status); data_blob_clear_free(&password_blob); if (!conn) { - TALLOC_FREE(ctx); + reply_nterror(req, nt_status); END_PROFILE(SMBtcon); - return ERROR_NT(nt_status); + return; } - outsize = set_message(inbuf,outbuf,2,0,True); - SSVAL(outbuf,smb_vwv0,max_recv); - SSVAL(outbuf,smb_vwv1,conn->cnum); - SSVAL(outbuf,smb_tid,conn->cnum); + reply_outbuf(req, 2, 0); + SSVAL(req->outbuf,smb_vwv0,max_recv); + SSVAL(req->outbuf,smb_vwv1,conn->cnum); + SSVAL(req->outbuf,smb_tid,conn->cnum); DEBUG(3,("tcon service=%s cnum=%d\n", service, conn->cnum)); END_PROFILE(SMBtcon); - TALLOC_FREE(ctx); - return(outsize); + return; } /**************************************************************************** -- cgit From 6051d516547813d48b58d0519ee9f52b291c1ed2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 15 Aug 2007 13:44:34 +0000 Subject: r24461: Fix Bug 4852, thank to anto for reporting it. (This used to be commit 0fecd8a0c3aaa64e137d2efd3f9cc7705837ea2a) --- source3/smbd/reply.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a95f2ec87e..786fe9c6a1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1718,9 +1718,23 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBopenX); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ + END_PROFILE(SMBopenX); + return; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); + END_PROFILE(SMBopenX); return; } reply_nterror(req, status); + END_PROFILE(SMBopenX); return; } -- cgit From 3dd3c4cd013dadd1a1f57ac3e0750018dc5a0698 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Aug 2007 16:58:29 +0000 Subject: r24464: Now Volker removed the readbmpx we don't need cached errors any more. Jeremy. (This used to be commit 9256ec0a20f532c7dd7ddc2d3534336a47e6c2d2) --- source3/smbd/close.c | 1 - source3/smbd/error.c | 16 ---------------- 2 files changed, 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 9718fef4ea..30220ce4de 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -102,7 +102,6 @@ static NTSTATUS close_filestruct(files_struct *fsp) } conn->num_files_open--; - SAFE_FREE(fsp->wbmpx_ptr); return status; } diff --git a/source3/smbd/error.c b/source3/smbd/error.c index dd9ff85640..74029a2b05 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -24,22 +24,6 @@ extern struct unix_error_map unix_dos_nt_errmap[]; extern uint32 global_client_caps; -/**************************************************************************** - Create an error packet from a cached error. -****************************************************************************/ - -int cached_error_packet(const char *inbuf,char *outbuf,files_struct *fsp,int line,const char *file) -{ - write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; - int32 eclass = wbmpx->wr_errclass; - int32 err = wbmpx->wr_error; - NTSTATUS ntstatus = wbmpx->wr_status; - - /* We can now delete the auxiliary struct */ - SAFE_FREE(fsp->wbmpx_ptr); - return error_packet(inbuf,outbuf,eclass,err,ntstatus,line,file); -} - /**************************************************************************** Create an error packet from errno. ****************************************************************************/ -- cgit From a1f593cd737ccfaf48a98b954f38a541646cc5c7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Aug 2007 19:25:38 +0000 Subject: r24467: Do range checking on incoming smb request. Jeremy. (This used to be commit dbd58dd647279def1681d88701e41d8a738c680a) --- source3/smbd/process.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index bf86603924..ce04c4331f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -57,12 +57,26 @@ extern int max_send; void init_smb_request(struct smb_request *req, const uint8 *inbuf) { + size_t req_size = smb_len(inbuf); + /* Ensure we have at smb_size request. */ + if (req_size < smb_size) { + DEBUG(0,("init_smb_request: invalid request size %u\n", + (unsigned int)req_size )); + exit_server_cleanly("Invalid SMB request"); + } req->flags2 = SVAL(inbuf, smb_flg2); req->smbpid = SVAL(inbuf, smb_pid); req->mid = SVAL(inbuf, smb_mid); req->vuid = SVAL(inbuf, smb_uid); req->tid = SVAL(inbuf, smb_tid); req->wct = CVAL(inbuf, smb_wct); + /* Ensure we have at least wct words. */ + if (smb_size + req->wct*2 > req_size) { + DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n", + (unsigned int)req->wct, + (unsigned int)req_size)); + exit_server_cleanly("Invalid SMB request"); + } req->inbuf = inbuf; req->outbuf = NULL; } -- cgit From ed70bc0d8eef17af75ffcafd0c4b90ea403002fc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Aug 2007 19:43:26 +0000 Subject: r24468: Don't forget the +4 for length :-). Jeremy. (This used to be commit 4d01e0b7443aa4e4d450d705df5762d801172809) --- source3/smbd/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ce04c4331f..bf3abf9758 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -57,8 +57,8 @@ extern int max_send; void init_smb_request(struct smb_request *req, const uint8 *inbuf) { - size_t req_size = smb_len(inbuf); - /* Ensure we have at smb_size request. */ + size_t req_size = smb_len(inbuf) + 4; + /* Ensure we have at least smb_size bytes. */ if (req_size < smb_size) { DEBUG(0,("init_smb_request: invalid request size %u\n", (unsigned int)req_size )); -- cgit From fd9c413786e54f07a1db992c2a103c6f1be832e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Aug 2007 23:05:49 +0000 Subject: r24470: Start fixing up the mapping of OBJECT_NAME_COLLISION to DOS error ERRDOS, ERRfilexists on open calls. Jeremy. (This used to be commit 4674486450bbe79ec9b22bcbc23c534365d6798a) --- source3/smbd/trans2.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 74c287c757..355c040a1c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -907,12 +907,23 @@ static void call_trans2open(connection_struct *conn, open_attr, oplock_request, &smb_action, &fsp); - + if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ return; } + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); + return; + } reply_nterror(req, status); return; } -- cgit From 606f10945fc159d3e12f181b3e5137b3e035c450 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Aug 2007 23:56:08 +0000 Subject: r24474: Map error value NT_STATUS_OBJECT_NAME_COLLISION to ERRDOS, ERRfilexists for NTCreateX and NTTransCreate. Jeremy. (This used to be commit 5b2316d1734765ef6c31ff09beea974d9629d17f) --- source3/smbd/nttrans.c | 58 +++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1b6c324e9d..23905181cd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -788,18 +788,6 @@ void reply_ntcreate_and_X(connection_struct *conn, file_attributes, &info, &fsp); - TALLOC_FREE(case_state); - - if(!NT_STATUS_IS_OK(status)) { - if (!use_nt_status() && NT_STATUS_EQUAL( - status, NT_STATUS_OBJECT_NAME_COLLISION)) { - status = NT_STATUS_DOS(ERRDOS, ERRfilexists); - } - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; - } - } else { /* @@ -861,7 +849,7 @@ void reply_ntcreate_and_X(connection_struct *conn, END_PROFILE(SMBntcreateX); return; } - + oplock_request = 0; status = open_directory(conn, req, fname, &sbuf, @@ -872,31 +860,33 @@ void reply_ntcreate_and_X(connection_struct *conn, file_attributes, &info, &fsp); - if(!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); - if (!use_nt_status() && NT_STATUS_EQUAL( - status, NT_STATUS_OBJECT_NAME_COLLISION)) { - status = NT_STATUS_DOS(ERRDOS, ERRfilexists); - } - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; - } - } else { - TALLOC_FREE(case_state); - END_PROFILE(SMBntcreateX); - if (open_was_deferred(req->mid)) { - /* We have re-scheduled this call. */ - return; - } - reply_nterror(req, status); - return; } - } + } } - + TALLOC_FREE(case_state); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBntcreateX); + if (open_was_deferred(req->mid)) { + /* We have re-scheduled this call. */ + return; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); + return; + } + reply_nterror(req, status); + return; + } + file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); if(fattr == 0) { -- cgit From 522418ce16f8d0af8dcf4673a795b42e14ea9e9c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Aug 2007 00:22:35 +0000 Subject: r24475: Fix the error mapping for SMB_POSIX_PATH_OPEN. Jeremy. (This used to be commit 6dac315ba1d9b9582c2b573e0785b2f6d627f846) --- source3/smbd/trans2.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 355c040a1c..a01e79b624 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6515,6 +6515,18 @@ static void call_trans2setfilepathinfo(connection_struct *conn, ERRSRV, ERRbadpath); return; } + if (info_level == SMB_POSIX_PATH_OPEN && + NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + return ERROR_BOTH(NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); + } + reply_nterror(req, status); return; } -- cgit From 622abf53f9de8a0230d71fcdb3724e1be31a2cc7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Aug 2007 00:37:07 +0000 Subject: r24476: Fix the mappings in reply_opeXXX calls. Now to test renames. Jeremy. (This used to be commit 74d10b09a68f5c06d6b3ceffe0a40818dc84106e) --- source3/smbd/reply.c | 31 ++++++++++++++++++++++++------- source3/smbd/trans2.c | 4 +++- 2 files changed, 27 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 786fe9c6a1..1b0785285d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1551,13 +1551,23 @@ void reply_open(connection_struct *conn, struct smb_request *req) &info, &fsp); if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBopen); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - END_PROFILE(SMBopen); + return; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); return; } reply_nterror(req, status); - END_PROFILE(SMBopen); return; } @@ -1718,7 +1728,6 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBopenX); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - END_PROFILE(SMBopenX); return; } if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { @@ -1730,11 +1739,9 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) */ reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, ERRfilexists); - END_PROFILE(SMBopenX); return; } reply_nterror(req, status); - END_PROFILE(SMBopenX); return; } @@ -2075,13 +2082,23 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) close(tmpfd); if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBctemp); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - END_PROFILE(SMBctemp); + return; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); return; } reply_nterror(req, status); - END_PROFILE(SMBctemp); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a01e79b624..dbbb2faba9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6523,8 +6523,10 @@ static void call_trans2setfilepathinfo(connection_struct *conn, * ERRDOS/183, we need to return ERRDOS/80, see bug * 4852. */ - return ERROR_BOTH(NT_STATUS_OBJECT_NAME_COLLISION, + reply_botherror(req, + NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, ERRfilexists); + return; } reply_nterror(req, status); -- cgit From 93fc3a024820bd4a01565b301d37b0e4106500ac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 16 Aug 2007 12:15:52 +0000 Subject: r24485: Even in the failure case unix_convert must pass the already converted part of the string to the caller. (This used to be commit 301ae3d68bc64c9526eb7d4458584a5ebb151137) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d5c22e81c3..6ab179a316 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -603,8 +603,8 @@ NTSTATUS unix_convert(connection_struct *conn, done: result = NT_STATUS_OK; - pstrcpy(orig_path, name); fail: + pstrcpy(orig_path, name); SAFE_FREE(name); SAFE_FREE(dirpath); return result; -- cgit From bcc7bdcfe38673ab9a409b94d525ca5c09e0e591 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 16 Aug 2007 15:44:13 +0000 Subject: r24497: Revert r24485 -- this needs more thought (This used to be commit 01f701ba1ea9859b090aaf8f4ae9722c5502316c) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 6ab179a316..d5c22e81c3 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -603,8 +603,8 @@ NTSTATUS unix_convert(connection_struct *conn, done: result = NT_STATUS_OK; - fail: pstrcpy(orig_path, name); + fail: SAFE_FREE(name); SAFE_FREE(dirpath); return result; -- cgit From 077d5d2e369e4fcb3e8c8fec862da9e450398ef3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Aug 2007 17:42:34 +0000 Subject: r24498: More extra code into a function, reply_openerror. Jeremy. (This used to be commit 43ddfb8c918bd27e2efd3b54077db815da80a53a) --- source3/smbd/error.c | 17 ++++++ source3/smbd/nttrans.c | 163 +++++++++++++++++++++---------------------------- source3/smbd/reply.c | 43 ++----------- source3/smbd/trans2.c | 28 ++------- 4 files changed, 96 insertions(+), 155 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 74029a2b05..143417dce3 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -179,3 +179,20 @@ void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode, error_packet_set((char *)req->outbuf, eclass, ecode, ntstatus, line, file); } + +void reply_openerror(struct smb_request *req, NTSTATUS status) +{ + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); + } else { + reply_nterror(req, status); + } +} + diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 23905181cd..907176c161 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -816,51 +816,50 @@ void reply_ntcreate_and_X(connection_struct *conn, oplock_request, &info, &fsp); - if (!NT_STATUS_IS_OK(status)) { - /* We cheat here. There are two cases we - * care about. One is a directory rename, - * where the NT client will attempt to - * open the source directory for - * DELETE access. Note that when the - * NT client does this it does *not* - * set the directory bit in the - * request packet. This is translated - * into a read/write open - * request. POSIX states that any open - * for write request on a directory - * will generate an EISDIR error, so - * we can catch this here and open a - * pseudo handle that is flagged as a - * directory. The second is an open - * for a permissions read only, which - * we handle in the open_file_stat case. JRA. - */ + /* We cheat here. There are two cases we + * care about. One is a directory rename, + * where the NT client will attempt to + * open the source directory for + * DELETE access. Note that when the + * NT client does this it does *not* + * set the directory bit in the + * request packet. This is translated + * into a read/write open + * request. POSIX states that any open + * for write request on a directory + * will generate an EISDIR error, so + * we can catch this here and open a + * pseudo handle that is flagged as a + * directory. The second is an open + * for a permissions read only, which + * we handle in the open_file_stat case. JRA. + */ - if (NT_STATUS_EQUAL(status, - NT_STATUS_FILE_IS_A_DIRECTORY)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - /* - * Fail the open if it was explicitly a non-directory file. - */ + /* + * Fail the open if it was explicitly a non-directory + * file. + */ - if (create_options & FILE_NON_DIRECTORY_FILE) { - TALLOC_FREE(case_state); - reply_force_nterror(req, NT_STATUS_FILE_IS_A_DIRECTORY); - END_PROFILE(SMBntcreateX); - return; - } + if (create_options & FILE_NON_DIRECTORY_FILE) { + TALLOC_FREE(case_state); + reply_force_nterror(req, + NT_STATUS_FILE_IS_A_DIRECTORY); + END_PROFILE(SMBntcreateX); + return; + } - oplock_request = 0; - status = open_directory(conn, req, fname, - &sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - &info, &fsp); + oplock_request = 0; + status = open_directory(conn, req, fname, + &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + file_attributes, + &info, &fsp); - } } } @@ -872,18 +871,7 @@ void reply_ntcreate_and_X(connection_struct *conn, /* We have re-scheduled this call. */ return; } - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - /* - * We hit an existing file, and if we're returning DOS - * error codes OBJECT_NAME_COLLISION would map to - * ERRDOS/183, we need to return ERRDOS/80, see bug - * 4852. - */ - reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, - ERRDOS, ERRfilexists); - return; - } - reply_nterror(req, status); + reply_openerror(req, status); return; } @@ -1532,12 +1520,6 @@ static void call_nt_transact_create(connection_struct *conn, create_options, file_attributes, &info, &fsp); - if(!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); - reply_nterror(req, status); - return; - } - } else { /* @@ -1553,46 +1535,41 @@ static void call_nt_transact_create(connection_struct *conn, oplock_request, &info, &fsp); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, - NT_STATUS_FILE_IS_A_DIRECTORY)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - /* - * Fail the open if it was explicitly a non-directory file. - */ + /* + * Fail the open if it was explicitly a non-directory file. + */ - if (create_options & FILE_NON_DIRECTORY_FILE) { - TALLOC_FREE(case_state); - reply_force_nterror( - req, - NT_STATUS_FILE_IS_A_DIRECTORY); - return; - } - - oplock_request = 0; - status = open_directory(conn, req, fname, - &sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - &info, &fsp); - if(!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); - reply_nterror(req, status); - return; - } - } else { + if (create_options & FILE_NON_DIRECTORY_FILE) { TALLOC_FREE(case_state); - if (open_was_deferred(req->mid)) { - /* We have re-scheduled this call. */ - return; - } - reply_nterror(req, status); + reply_force_nterror( + req, + NT_STATUS_FILE_IS_A_DIRECTORY); return; } - } + + oplock_request = 0; + status = open_directory(conn, req, fname, + &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + file_attributes, + &info, &fsp); + } + } + + TALLOC_FREE(case_state); + + if(!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(req->mid)) { + /* We have re-scheduled this call. */ + return; + } + reply_openerror(req, status); + return; } /* diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1b0785285d..a2ea35b115 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1556,18 +1556,7 @@ void reply_open(connection_struct *conn, struct smb_request *req) /* We have re-scheduled this call. */ return; } - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - /* - * We hit an existing file, and if we're returning DOS - * error codes OBJECT_NAME_COLLISION would map to - * ERRDOS/183, we need to return ERRDOS/80, see bug - * 4852. - */ - reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, - ERRDOS, ERRfilexists); - return; - } - reply_nterror(req, status); + reply_openerror(req, status); return; } @@ -1723,25 +1712,14 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) smb_attr, oplock_request, &smb_action, &fsp); - + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ return; } - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - /* - * We hit an existing file, and if we're returning DOS - * error codes OBJECT_NAME_COLLISION would map to - * ERRDOS/183, we need to return ERRDOS/80, see bug - * 4852. - */ - reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, - ERRDOS, ERRfilexists); - return; - } - reply_nterror(req, status); + reply_openerror(req, status); return; } @@ -2087,18 +2065,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) /* We have re-scheduled this call. */ return; } - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - /* - * We hit an existing file, and if we're returning DOS - * error codes OBJECT_NAME_COLLISION would map to - * ERRDOS/183, we need to return ERRDOS/80, see bug - * 4852. - */ - reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, - ERRDOS, ERRfilexists); - return; - } - reply_nterror(req, status); + reply_openerror(req, status); return; } @@ -4678,7 +4645,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBmkdir); return; } - + status = create_directory(conn, directory); DEBUG(5, ("create_directory returned %s\n", nt_errstr(status))); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dbbb2faba9..36fb2eee76 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -913,18 +913,7 @@ static void call_trans2open(connection_struct *conn, /* We have re-scheduled this call. */ return; } - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - /* - * We hit an existing file, and if we're returning DOS - * error codes OBJECT_NAME_COLLISION would map to - * ERRDOS/183, we need to return ERRDOS/80, see bug - * 4852. - */ - reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, - ERRDOS, ERRfilexists); - return; - } - reply_nterror(req, status); + reply_openerror(req, status); return; } @@ -6515,18 +6504,9 @@ static void call_trans2setfilepathinfo(connection_struct *conn, ERRSRV, ERRbadpath); return; } - if (info_level == SMB_POSIX_PATH_OPEN && - NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - /* - * We hit an existing file, and if we're returning DOS - * error codes OBJECT_NAME_COLLISION would map to - * ERRDOS/183, we need to return ERRDOS/80, see bug - * 4852. - */ - reply_botherror(req, - NT_STATUS_OBJECT_NAME_COLLISION, - ERRDOS, ERRfilexists); - return; + if (info_level == SMB_POSIX_PATH_OPEN) { + reply_openerror(req, status); + return; } reply_nterror(req, status); -- cgit From a662a62e5a718065640e9b9f3c8f166638f4ec9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Aug 2007 23:53:51 +0000 Subject: r24500: Add check that bcc is correct in an incoming packet. Jeremy. (This used to be commit 267a0ac48d358e1bd10d92238352ca3d867a58d4) --- source3/smbd/process.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index bf3abf9758..35f1d6fb3c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -70,13 +70,22 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) req->vuid = SVAL(inbuf, smb_uid); req->tid = SVAL(inbuf, smb_tid); req->wct = CVAL(inbuf, smb_wct); - /* Ensure we have at least wct words. */ + /* Ensure we have at least wct words and 2 bytes of bcc. */ if (smb_size + req->wct*2 > req_size) { DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n", (unsigned int)req->wct, (unsigned int)req_size)); exit_server_cleanly("Invalid SMB request"); } + /* Ensure bcc is correct. */ + if (((uint8 *)smb_buf(inbuf)) + smb_buflen(inbuf) > inbuf + req_size) { + DEBUG(0,("init_smb_request: invalid bcc number %u " + "(wct = %u, size %u)\n", + (unsigned int)smb_buflen(inbuf), + (unsigned int)req->wct, + (unsigned int)req_size)); + exit_server_cleanly("Invalid SMB request"); + } req->inbuf = inbuf; req->outbuf = NULL; } -- cgit From 891fa216ead2c5001bc8c671639ae59be79b968b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Aug 2007 01:55:58 +0000 Subject: r24501: Added bcc test for reply_tcon & removed Vl's comment :-). Jeremy. (This used to be commit 9d9ed41f2139051578c35f80112640cffb5f7608) --- source3/smbd/reply.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a2ea35b115..ce3eebff99 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -442,12 +442,11 @@ void reply_tcon(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBtcon); - /******************************************************************** - * Warning! I'm not sure that the inbuf length check is actually - * correct here. -- vl - * - * Jeremy, please check and remove this comment :-) - ********************************************************************/ + if (smb_buflen(req->inbuf) < 4) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBtcon); + return; + } p = smb_buf(req->inbuf)+1; p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, -- cgit From f65041cbf18d9e3778e549179edb3e134a1608b1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 17 Aug 2007 10:05:14 +0000 Subject: r24512: Fix RAW-NOTIFY With the inbuf consistency checks we have to more correctly fake the inbuf (This used to be commit 2b8ecda30fc57bb4027b7208d22d85d213074158) --- source3/smbd/notify.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index cf64acae07..0bdf466092 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -156,6 +156,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, { prs_struct ps; struct smb_request *req = NULL; + uint8 tmp_request[smb_size]; if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); @@ -180,9 +181,16 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } - smb_setlen(NULL, request_buf, smb_size); + memcpy(tmp_request, request_buf, smb_size); - init_smb_request(req, request_buf); + /* + * We're only interested in the header fields here + */ + + smb_setlen(NULL, (char *)tmp_request, smb_size); + SCVAL(tmp_request, smb_wct, 0); + + init_smb_request(req, tmp_request); send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); -- cgit From 2efabbbf4b97a62247aa080249d3de21f044b1cb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 19 Aug 2007 19:57:55 +0000 Subject: r24548: Fix the case-changing renames This was broken when I changed reply_mv to wrap in a open_file_ntcreate call, unix_convert on the destination was called twice (This used to be commit fddc9db91175bdb0b7ac6a636f8bef918bd7c1b4) --- source3/smbd/reply.c | 23 +++++++++-------------- source3/smbd/trans2.c | 21 ++++++++++++++++++++- 2 files changed, 29 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ce3eebff99..b3c4717b0b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5111,24 +5111,18 @@ static void notify_rename(connection_struct *conn, BOOL is_dir, Rename an open file - given an fsp. ****************************************************************************/ -NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, + pstring newname, + const char *newname_last_component, + uint32 attrs, BOOL replace_if_exists) { SMB_STRUCT_STAT sbuf, sbuf1; - pstring newname_last_component; NTSTATUS status = NT_STATUS_OK; struct share_mode_lock *lck = NULL; BOOL dst_exists; ZERO_STRUCT(sbuf); - status = unix_convert(conn, newname, False, newname_last_component, &sbuf); - - /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */ - - if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) { - return status; - } - status = check_name(conn, newname); if (!NT_STATUS_IS_OK(status)) { return status; @@ -5420,8 +5414,9 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, return status; } - status = rename_internals_fsp(conn, fsp, newname, attrs, - replace_if_exists); + status = rename_internals_fsp(conn, fsp, newname, + last_component_dest, + attrs, replace_if_exists); close_file(fsp, NORMAL_CLOSE); @@ -5517,8 +5512,8 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, break; } - status = rename_internals_fsp(conn, fsp, destname, attrs, - replace_if_exists); + status = rename_internals_fsp(conn, fsp, destname, dname, + attrs, replace_if_exists); close_file(fsp, NORMAL_CLOSE); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 36fb2eee76..53368cd8ef 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4937,9 +4937,28 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, pstrcat(base_name, newname); if (fsp) { + SMB_STRUCT_STAT sbuf; + pstring newname_last_component; + + ZERO_STRUCT(sbuf); + + status = unix_convert(conn, newname, False, + newname_last_component, &sbuf); + + /* If an error we expect this to be + * NT_STATUS_OBJECT_PATH_NOT_FOUND */ + + if (!NT_STATUS_IS_OK(status) + && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, + status)) { + return status; + } + DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", fsp->fnum, fsp->fsp_name, base_name )); - status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite); + status = rename_internals_fsp(conn, fsp, base_name, + newname_last_component, 0, + overwrite); } else { DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, newname )); -- cgit From f5ab9ddd760321ed983f0ef3354410e0a05decfc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 19 Aug 2007 20:00:43 +0000 Subject: r24549: Fix unix_convert to return the already converted part This API will change anyway when moving away from pstrings. It took so long to fix, because that rename bug I just fixed gave make test failures that had nothing to do with this one. I have samba4 tests for both bugs, will check them in when the build farm has caught up (This used to be commit d4f442ed9b145990af4db26859663954ddd70926) --- source3/smbd/filename.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index d5c22e81c3..73e3869f50 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -173,7 +173,7 @@ NTSTATUS unix_convert(connection_struct *conn, result =determine_path_error( &orig_path[2], allow_wcard_last_component); } - goto fail; + return result; } /* @@ -222,8 +222,8 @@ NTSTATUS unix_convert(connection_struct *conn, if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) { DEBUG(0, ("strdup failed\n")); - result = NT_STATUS_NO_MEMORY; - goto fail; + SAFE_FREE(name); + return NT_STATUS_NO_MEMORY; } /* @@ -602,9 +602,15 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); done: - result = NT_STATUS_OK; pstrcpy(orig_path, name); + SAFE_FREE(name); + SAFE_FREE(dirpath); + return NT_STATUS_OK; fail: + DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start)); + pstrcpy(orig_path, dirpath); + pstrcat(orig_path, "/"); + pstrcat(orig_path, start); SAFE_FREE(name); SAFE_FREE(dirpath); return result; -- cgit From 57e2718e097bba57c96632064956f6ce048d8f28 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Aug 2007 01:43:22 +0000 Subject: r24589: Refactor our vuid code so that we keep the same vuid that was allocated whilst the connection is being constructed and after the connection has been set up. This is what Windows does and at least one client (and HP printer) depends on this behaviour. As it depends on the req struct not yet ported to SAMBA_3_2_0 (Volker, hint hint.... :-) I am not yet adding this to that branch, but will investigate that tomorrow. Jeremy. (This used to be commit a54f2805df92c67e74a6764568eedebe394fd500) --- source3/smbd/password.c | 297 ++++++++++++++++++++++++++--------------------- source3/smbd/sesssetup.c | 122 ++++++++++++------- 2 files changed, 244 insertions(+), 175 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 1a7dc33c61..847b8db082 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -30,13 +30,12 @@ static user_struct *validated_users; static int next_vuid = VUID_OFFSET; static int num_validated_vuids; -/**************************************************************************** - Check if a uid has been validated, and return an pointer to the user_struct - if it has. NULL if not. vuid is biased by an offset. This allows us to - tell random client vuid's (normally zero) from valid vuids. -****************************************************************************/ +enum server_allocated_state { SERVER_ALLOCATED_REQUIRED_YES, + SERVER_ALLOCATED_REQUIRED_NO, + SERVER_ALLOCATED_REQUIRED_ANY}; -user_struct *get_valid_user_struct(uint16 vuid) +static user_struct *get_valid_user_struct_internal(uint16 vuid, + enum server_allocated_state server_allocated) { user_struct *usp; int count=0; @@ -45,7 +44,20 @@ user_struct *get_valid_user_struct(uint16 vuid) return NULL; for (usp=validated_users;usp;usp=usp->next,count++) { - if (vuid == usp->vuid && usp->server_info) { + if (vuid == usp->vuid) { + switch (server_allocated) { + case SERVER_ALLOCATED_REQUIRED_YES: + if (usp->server_info == NULL) { + continue; + } + break; + case SERVER_ALLOCATED_REQUIRED_NO: + if (usp->server_info != NULL) { + continue; + } + case SERVER_ALLOCATED_REQUIRED_ANY: + break; + } if (count > 10) { DLIST_PROMOTE(validated_users, usp); } @@ -57,27 +69,33 @@ user_struct *get_valid_user_struct(uint16 vuid) } /**************************************************************************** - Get the user struct of a partial NTLMSSP login + Check if a uid has been validated, and return an pointer to the user_struct + if it has. NULL if not. vuid is biased by an offset. This allows us to + tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -user_struct *get_partial_auth_user_struct(uint16 vuid) +user_struct *get_valid_user_struct(uint16 vuid) { - user_struct *usp; - int count=0; - - if (vuid == UID_FIELD_INVALID) - return NULL; + return get_valid_user_struct_internal(vuid, SERVER_ALLOCATED_REQUIRED_YES); +} - for (usp=validated_users;usp;usp=usp->next,count++) { - if (vuid == usp->vuid && !usp->server_info) { - if (count > 10) { - DLIST_PROMOTE(validated_users, usp); - } - return usp; - } +BOOL is_partial_auth_vuid(uint16 vuid) +{ + if (vuid == UID_FIELD_INVALID) { + return False; } + return get_valid_user_struct_internal(vuid, + SERVER_ALLOCATED_REQUIRED_NO) ? True : False; +} - return NULL; +/**************************************************************************** + Get the user struct of a partial NTLMSSP login +****************************************************************************/ + +user_struct *get_partial_auth_user_struct(uint16 vuid) +{ + return get_valid_user_struct_internal(vuid, + SERVER_ALLOCATED_REQUIRED_NO); } /**************************************************************************** @@ -86,11 +104,18 @@ user_struct *get_partial_auth_user_struct(uint16 vuid) void invalidate_vuid(uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); + user_struct *vuser = NULL; - if (vuser == NULL) + if (vuid == UID_FIELD_INVALID) { return; - + } + + vuser = get_valid_user_struct_internal(vuid, + SERVER_ALLOCATED_REQUIRED_ANY); + if (vuser == NULL) { + return; + } + session_yield(vuser); data_blob_free(&vuser->session_key); @@ -115,116 +140,127 @@ void invalidate_all_vuids(void) for (usp=validated_users;usp;usp=next) { next = usp->next; - invalidate_vuid(usp->vuid); } } -/** - * register that a valid login has been performed, establish 'session'. - * @param server_info The token returned from the authentication process. - * (now 'owned' by register_vuid) - * - * @param session_key The User session key for the login session (now also - * 'owned' by register_vuid) - * - * @param respose_blob The NT challenge-response, if available. (May be - * freed after this call) - * - * @param smb_name The untranslated name of the user - * - * @return Newly allocated vuid, biased by an offset. (This allows us to - * tell random client vuid's (normally zero) from valid vuids.) - * - */ +/**************************************************** + Create a new partial auth user struct. +*****************************************************/ -int register_vuid(auth_serversupplied_info *server_info, - DATA_BLOB session_key, DATA_BLOB response_blob, - const char *smb_name) +int register_initial_vuid(void) { user_struct *vuser; /* Paranoia check. */ if(lp_security() == SEC_SHARE) { - smb_panic("Tried to register uid in security=share"); + smb_panic("register_initial_vuid: " + "Tried to register uid in security=share"); } /* Limit allowed vuids to 16bits - VUID_OFFSET. */ if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) { - data_blob_free(&session_key); return UID_FIELD_INVALID; } - if((vuser = TALLOC_ZERO_P(NULL, user_struct)) == NULL) { - DEBUG(0,("Failed to talloc users struct!\n")); - data_blob_free(&session_key); + if((vuser = talloc_zero(NULL, user_struct)) == NULL) { + DEBUG(0,("register_initial_vuid: " + "Failed to talloc users struct!\n")); return UID_FIELD_INVALID; } - /* Allocate a free vuid. Yes this is a linear search... :-) */ - while( get_valid_user_struct(next_vuid) != NULL ) { + /* Allocate a free vuid. Yes this is a linear search... */ + while( get_valid_user_struct_internal(next_vuid, + SERVER_ALLOCATED_REQUIRED_ANY) != NULL ) { next_vuid++; /* Check for vuid wrap. */ - if (next_vuid == UID_FIELD_INVALID) + if (next_vuid == UID_FIELD_INVALID) { next_vuid = VUID_OFFSET; + } } - DEBUG(10,("register_vuid: allocated vuid = %u\n", - (unsigned int)next_vuid )); + DEBUG(10,("register_initial_vuid: allocated vuid = %u\n", + (unsigned int)next_vuid )); vuser->vuid = next_vuid; - if (!server_info) { - /* - * This happens in an unfinished NTLMSSP session setup. We - * need to allocate a vuid between the first and second calls - * to NTLMSSP. - */ - next_vuid++; - num_validated_vuids++; - - vuser->server_info = NULL; - - DLIST_ADD(validated_users, vuser); - - return vuser->vuid; + /* + * This happens in an unfinished NTLMSSP session setup. We + * need to allocate a vuid between the first and second calls + * to NTLMSSP. + */ + next_vuid++; + num_validated_vuids++; + + DLIST_ADD(validated_users, vuser); + return vuser->vuid; +} + +/** + * register that a valid login has been performed, establish 'session'. + * @param server_info The token returned from the authentication process. + * (now 'owned' by register_existing_vuid) + * + * @param session_key The User session key for the login session (now also + * 'owned' by register_existing_vuid) + * + * @param respose_blob The NT challenge-response, if available. (May be + * freed after this call) + * + * @param smb_name The untranslated name of the user + * + * @return Newly allocated vuid, biased by an offset. (This allows us to + * tell random client vuid's (normally zero) from valid vuids.) + * + */ + +int register_existing_vuid(uint16 vuid, + auth_serversupplied_info *server_info, + DATA_BLOB session_key, + DATA_BLOB response_blob, + const char *smb_name) +{ + user_struct *vuser = get_partial_auth_user_struct(vuid); + if (!vuser) { + goto fail; } - /* use this to keep tabs on all our info from the authentication */ + /* Use this to keep tabs on all our info from the authentication */ vuser->server_info = server_info; - /* Ensure that the server_info will dissapear with the vuser it is now attached to */ + + /* Ensure that the server_info will disappear with + * the vuser it is now attached to */ + talloc_steal(vuser, vuser->server_info); /* the next functions should be done by a SID mapping system (SMS) as * the new real sam db won't have reference to unix uids or gids */ - + vuser->uid = server_info->uid; vuser->gid = server_info->gid; - + vuser->n_groups = server_info->n_groups; if (vuser->n_groups) { - if (!(vuser->groups = (gid_t *)talloc_memdup(vuser, server_info->groups, - sizeof(gid_t) * - vuser->n_groups))) { - DEBUG(0,("register_vuid: failed to talloc_memdup " - "vuser->groups\n")); - data_blob_free(&session_key); - TALLOC_FREE(vuser); - return UID_FIELD_INVALID; + if (!(vuser->groups = (gid_t *)talloc_memdup(vuser, + server_info->groups, + sizeof(gid_t)*vuser->n_groups))) { + DEBUG(0,("register_existing_vuid: " + "failed to talloc_memdup vuser->groups\n")); + goto fail; } } vuser->guest = server_info->guest; - fstrcpy(vuser->user.unix_name, server_info->unix_name); + fstrcpy(vuser->user.unix_name, server_info->unix_name); /* This is a potentially untrusted username */ alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", - sizeof(vuser->user.smb_name)); + sizeof(vuser->user.smb_name)); fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); fstrcpy(vuser->user.full_name, - pdb_get_fullname(server_info->sam_account)); + pdb_get_fullname(server_info->sam_account)); { /* Keep the homedir handy */ @@ -234,7 +270,7 @@ int register_vuid(auth_serversupplied_info *server_info, pdb_get_logon_script(server_info->sam_account); if (!IS_SAM_DEFAULT(server_info->sam_account, - PDB_UNIXHOMEDIR)) { + PDB_UNIXHOMEDIR)) { const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); if (unix_homedir) { @@ -252,7 +288,7 @@ int register_vuid(auth_serversupplied_info *server_info, TALLOC_FREE(passwd); } } - + if (homedir) { vuser->homedir = homedir; } @@ -260,86 +296,83 @@ int register_vuid(auth_serversupplied_info *server_info, vuser->logon_script = logon_script; } } - vuser->session_key = session_key; - DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", - (unsigned int)vuser->uid, - (unsigned int)vuser->gid, - vuser->user.unix_name, vuser->user.smb_name, - vuser->user.domain, vuser->guest )); + DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", + (unsigned int)vuser->uid, + (unsigned int)vuser->gid, + vuser->user.unix_name, vuser->user.smb_name, + vuser->user.domain, vuser->guest )); - DEBUG(3, ("User name: %s\tReal name: %s\n", vuser->user.unix_name, - vuser->user.full_name)); + DEBUG(3, ("register_existing_vuid: User name: %s\t" + "Real name: %s\n", vuser->user.unix_name, + vuser->user.full_name)); - if (server_info->ptok) { + if (server_info->ptok) { vuser->nt_user_token = dup_nt_token(vuser, server_info->ptok); } else { - DEBUG(1, ("server_info does not contain a user_token - " - "cannot continue\n")); - TALLOC_FREE(vuser); - data_blob_free(&session_key); - return UID_FIELD_INVALID; + DEBUG(1, ("register_existing_vuid: server_info does not " + "contain a user_token - cannot continue\n")); + goto fail; } - DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n", - (int)vuser->uid,vuser->user.unix_name, vuser->vuid)); + DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, " + "and will be vuid %u\n", + (int)vuser->uid,vuser->user.unix_name, vuser->vuid)); next_vuid++; num_validated_vuids++; - DLIST_ADD(validated_users, vuser); - if (!session_claim(vuser)) { - DEBUG(1, ("Failed to claim session for vuid=%d\n", - vuser->vuid)); - invalidate_vuid(vuser->vuid); - return UID_FIELD_INVALID; + DEBUG(1, ("register_existing_vuid: Failed to claim session " + "for vuid=%d\n", + vuser->vuid)); + goto fail; } - /* Register a home dir service for this user iff - - (a) This is not a guest connection, - (b) we have a home directory defined - (c) there s not an existing static share by that name - - If a share exists by this name (autoloaded or not) reuse it . */ + /* Register a home dir service for this user if + (a) This is not a guest connection, + (b) we have a home directory defined + (c) there s not an existing static share by that name + If a share exists by this name (autoloaded or not) reuse it . */ vuser->homes_snum = -1; - - if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) - { + if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { int servicenumber = lp_servicenumber(vuser->user.unix_name); - if ( servicenumber == -1 ) { DEBUG(3, ("Adding homes service for user '%s' using " - "home directory: '%s'\n", + "home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); vuser->homes_snum = - add_home_service(vuser->user.unix_name, - vuser->user.unix_name, - vuser->unix_homedir); + add_home_service(vuser->user.unix_name, + vuser->user.unix_name, + vuser->unix_homedir); } else { DEBUG(3, ("Using static (or previously created) " - "service for user '%s'; path = '%s'\n", - vuser->user.unix_name, - lp_pathname(servicenumber) )); + "service for user '%s'; path = '%s'\n", + vuser->user.unix_name, + lp_pathname(servicenumber) )); vuser->homes_snum = servicenumber; } - } - + } + if (srv_is_signing_negotiated() && !vuser->guest && - !srv_signing_started()) { + !srv_signing_started()) { /* Try and turn on server signing on the first non-guest * sessionsetup. */ srv_set_signing(vuser->session_key, response_blob); } - + /* fill in the current_user_info struct */ set_current_user_info( &vuser->user ); + return vuser->vuid; + fail: - return vuser->vuid; + if (vuser) { + invalidate_vuid(vuid); + } + return UID_FIELD_INVALID; } /**************************************************************************** diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 22ad43ff75..e63511c368 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -249,8 +249,8 @@ static void reply_spnego_kerberos(connection_struct *conn, fstring netbios_domain_name; struct passwd *pw; fstring user; - int sess_vuid; - NTSTATUS ret; + int sess_vuid = SVAL(req->inbuf, smb_uid); + NTSTATUS ret = NT_STATUS_OK; PAC_DATA *pac_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; @@ -535,18 +535,28 @@ static void reply_spnego_kerberos(connection_struct *conn, } } - /* register_vuid keeps the server info */ - /* register_vuid takes ownership of session_key, no need to free after this. - A better interface would copy it.... */ - sess_vuid = register_vuid(server_info, session_key, nullblob, client); + /* register_existing_vuid keeps the server info */ + /* register_existing_vuid takes ownership of session_key on success, + * no need to free after this on success. A better interface would copy + * it.... */ + + if (!is_partial_auth_vuid(sess_vuid)) { + sess_vuid = register_initial_vuid(); + } + sess_vuid = register_existing_vuid(sess_vuid, + server_info, + session_key, + nullblob, + client); SAFE_FREE(client); reply_outbuf(req, 4, 0); - SSVAL(req->outbuf,smb_uid,vuid); + SSVAL(req->outbuf,smb_uid,sess_vuid); if (sess_vuid == UID_FIELD_INVALID ) { ret = NT_STATUS_LOGON_FAILURE; + data_blob_free(&session_key); } else { /* current_user_info is changed on new vuid */ reload_services( True ); @@ -560,6 +570,8 @@ static void reply_spnego_kerberos(connection_struct *conn, SSVAL(req->outbuf, smb_uid, sess_vuid); sessionsetup_start_signing_engine(server_info, req->inbuf); + /* Successful logon. Keep this vuid. */ + *p_invalidate_vuid = False; } /* wrap that up in a nice GSS-API wrapping */ @@ -611,33 +623,43 @@ static void reply_spnego_ntlmssp(connection_struct *conn, SSVAL(req->outbuf, smb_uid, vuid); if (NT_STATUS_IS_OK(nt_status)) { - int sess_vuid; DATA_BLOB nullblob = data_blob_null; DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); - /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); + if (!is_partial_auth_vuid(vuid)) { + data_blob_free(&session_key); + nt_status = NT_STATUS_LOGON_FAILURE; + goto out; + } + /* register_existing_vuid keeps the server info */ + if (register_existing_vuid(vuid, + server_info, + session_key, nullblob, + (*auth_ntlmssp_state)->ntlmssp_state->user) != + vuid) { + data_blob_free(&session_key); + nt_status = NT_STATUS_LOGON_FAILURE; + goto out; + } + (*auth_ntlmssp_state)->server_info = NULL; - if (sess_vuid == UID_FIELD_INVALID ) { - nt_status = NT_STATUS_LOGON_FAILURE; - } else { - - /* current_user_info is changed on new vuid */ - reload_services( True ); + /* current_user_info is changed on new vuid */ + reload_services( True ); - SSVAL(req->outbuf, smb_vwv3, 0); - - if (server_info->guest) { - SSVAL(req->outbuf,smb_vwv2,1); - } - - SSVAL(req->outbuf,smb_uid,sess_vuid); + SSVAL(req->outbuf, smb_vwv3, 0); - sessionsetup_start_signing_engine(server_info, req->inbuf); + if (server_info->guest) { + SSVAL(req->outbuf,smb_vwv2,1); } + + SSVAL(req->outbuf,smb_uid,vuid); + + sessionsetup_start_signing_engine(server_info, req->inbuf); } + out: + if (wrap) { response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP); } else { @@ -655,8 +677,10 @@ static void reply_spnego_ntlmssp(connection_struct *conn, if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { /* NB. This is *NOT* an error case. JRA */ auth_ntlmssp_end(auth_ntlmssp_state); - /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + if (!NT_STATUS_IS_OK(nt_status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + } } } @@ -1111,36 +1135,36 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, } } - vuser = get_partial_auth_user_struct(vuid); - if (!vuser) { + /* Did we get a valid vuid ? */ + if (!is_partial_auth_vuid(vuid)) { + /* No, then try and see if this is an intermediate sessionsetup + * for a large SPNEGO packet. */ struct pending_auth_data *pad = get_pending_auth_data(smbpid); if (pad) { DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n", (unsigned int)pad->vuid )); vuid = pad->vuid; - vuser = get_partial_auth_user_struct(vuid); } } - if (!vuser) { - vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL); - if (vuid == UID_FIELD_INVALID ) { + /* Do we have a valid vuid now ? */ + if (!is_partial_auth_vuid(vuid)) { + /* No, start a new authentication setup. */ + vuid = register_initial_vuid(); + if (vuid == UID_FIELD_INVALID) { data_blob_free(&blob1); reply_nterror(req, nt_status_squash( NT_STATUS_INVALID_PARAMETER)); return; } - - vuser = get_partial_auth_user_struct(vuid); } + vuser = get_partial_auth_user_struct(vuid); + /* This MUST be valid. */ if (!vuser) { - data_blob_free(&blob1); - reply_nterror(req, nt_status_squash( - NT_STATUS_INVALID_PARAMETER)); - return; + smb_panic("reply_sesssetup_and_X_spnego: invalid vuid."); } - + /* Large (greater than 4k) SPNEGO blobs are split into multiple * sessionsetup requests as the Windows limit on the security blob * field is 4k. Bug #4400. JRA. @@ -1617,13 +1641,25 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) data_blob_free(&session_key); TALLOC_FREE(server_info); } else { - /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, session_key, - nt_resp.data ? nt_resp : lm_resp, - sub_user); + /* Ignore the initial vuid. */ + sess_vuid = register_initial_vuid(); if (sess_vuid == UID_FIELD_INVALID) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); + data_blob_free(&session_key); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); + } + /* register_existing_vuid keeps the server info */ + sess_vuid = register_existing_vuid(sess_vuid, + server_info, + session_key, + nt_resp.data ? nt_resp : lm_resp, + sub_user); + if (sess_vuid == UID_FIELD_INVALID) { + data_blob_free(&nt_resp); + data_blob_free(&lm_resp); + data_blob_free(&session_key); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); return; -- cgit From 644b43d993db7ec709a2bc4e121426e7a27237e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Aug 2007 02:04:24 +0000 Subject: r24590: Reformatting to coding standards. Added my (C) in places it already should have been :-). Jeremy. (This used to be commit 41611a22ed852bb74e2ef3f45766c0580ffd3a18) --- source3/smbd/password.c | 41 ++--- source3/smbd/sesssetup.c | 421 ++++++++++++++++++++++++++++------------------- 2 files changed, 271 insertions(+), 191 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 847b8db082..a1590f2a58 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1,18 +1,19 @@ -/* +/* Unix SMB/CIFS implementation. Password and authentication handling Copyright (C) Andrew Tridgell 1992-1998 - + Copyright (C) Jeremy Allison 2007. + 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 3 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, see . */ @@ -76,7 +77,8 @@ static user_struct *get_valid_user_struct_internal(uint16 vuid, user_struct *get_valid_user_struct(uint16 vuid) { - return get_valid_user_struct_internal(vuid, SERVER_ALLOCATED_REQUIRED_YES); + return get_valid_user_struct_internal(vuid, + SERVER_ALLOCATED_REQUIRED_YES); } BOOL is_partial_auth_vuid(uint16 vuid) @@ -461,7 +463,8 @@ BOOL user_in_netgroup(const char *user, const char *ngname) yp_get_default_domain(&mydomain); if(mydomain == NULL) { - DEBUG(5,("Unable to get default yp domain, let's try without specifying it\n")); + DEBUG(5,("Unable to get default yp domain, " + "let's try without specifying it\n")); } DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", @@ -479,7 +482,7 @@ BOOL user_in_netgroup(const char *user, const char *ngname) fstrcpy(lowercase_user, user); strlower_m(lowercase_user); - + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", lowercase_user, mydomain?mydomain:"(ANY)", ngname)); @@ -568,7 +571,7 @@ BOOL user_in_list(const char *user,const char **list) return True; } } - + list++; } return(False); @@ -654,7 +657,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) endnetgrent(); } #endif - + #ifdef HAVE_GETGRENT { struct group *gptr; @@ -727,26 +730,26 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) Note this is *NOT* used when logging on using sessionsetup_and_X. ****************************************************************************/ -BOOL authorise_login(int snum, fstring user, DATA_BLOB password, +BOOL authorise_login(int snum, fstring user, DATA_BLOB password, BOOL *guest) { BOOL ok = False; - + #ifdef DEBUG_PASSWORD DEBUG(100,("authorise_login: checking authorisation on " "user=%s pass=%s\n", user,password.data)); #endif *guest = False; - + /* there are several possibilities: 1) login as the given user with given password - 2) login as a previously registered username with the given + 2) login as a previously registered username with the given password 3) login as a session list username with the given password 4) login as a previously validated user/password pair 5) login as the "user =" user with given password - 6) login as the "user =" user with no password + 6) login as the "user =" user with no password (guest connection) 7) login as guest user with no password @@ -765,14 +768,14 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, if (!user_list) return(False); - + for (auser=strtok(user_list,LIST_SEP); !ok && auser; auser = strtok(NULL,LIST_SEP)) { fstring user2; fstrcpy(user2,auser); if (!user_ok(user2,snum)) continue; - + if (password_ok(user2,password)) { ok = True; fstrcpy(user,user2); @@ -784,15 +787,15 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password, SAFE_FREE(user_list); } - + /* check the user= fields and the given password */ if (!ok && lp_username(snum)) { char *auser; pstring user_list; pstrcpy(user_list,lp_username(snum)); - + pstring_sub(user_list,"%S",lp_servicename(snum)); - + for (auser=strtok(user_list,LIST_SEP); auser && !ok; auser = strtok(NULL,LIST_SEP)) { if (*auser == '@') { diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e63511c368..4c45806b02 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -6,17 +6,18 @@ Copyright (C) Jim McDonough 2002 Copyright (C) Luke Howard 2003 Copyright (C) Volker Lendecke 2007 + Copyright (C) Jeremy Allison 2007 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 3 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, see . */ @@ -35,11 +36,12 @@ uint32 global_client_caps = 0; on a logon error possibly map the error to success if "map to guest" is set approriately */ -static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info, +static NTSTATUS do_map_to_guest(NTSTATUS status, + auth_serversupplied_info **server_info, const char *user, const char *domain) { if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { - if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { DEBUG(3,("No such user %s [%s] - using guest account\n", user, domain)); @@ -49,7 +51,8 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) { if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { - DEBUG(3,("Registered username %s for guest access\n",user)); + DEBUG(3,("Registered username %s for guest access\n", + user)); status = make_server_info_guest(server_info); } } @@ -96,8 +99,9 @@ static int push_signature(uint8 **outbuf) Start the signing engine if needed. Don't fail signing here. ****************************************************************************/ -static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, - const uint8 *inbuf) +static void sessionsetup_start_signing_engine( + const auth_serversupplied_info *server_info, + const uint8 *inbuf) { if (!server_info->guest && !srv_signing_started()) { /* We need to start the signing engine @@ -106,7 +110,7 @@ static void sessionsetup_start_signing_engine(const auth_serversupplied_info *se * correct one. Subsequent packets will * be correct. */ - srv_check_sign_mac((char *)inbuf, False); + srv_check_sign_mac((char *)inbuf, False); } } @@ -140,14 +144,14 @@ static void reply_sesssetup_blob(connection_struct *conn, } /**************************************************************************** - Do a 'guest' logon, getting back the + Do a 'guest' logon, getting back the ****************************************************************************/ -static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) +static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) { struct auth_context *auth_context; auth_usersupplied_info *user_info = NULL; - + NTSTATUS nt_status; unsigned char chal[8]; @@ -155,7 +159,8 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) DEBUG(3,("Got anonymous request\n")); - if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) { + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, + chal))) { return nt_status; } @@ -163,8 +168,10 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) (auth_context->free)(&auth_context); return NT_STATUS_NO_MEMORY; } - - nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info); + + nt_status = auth_context->check_ntlm_password(auth_context, + user_info, + server_info); (auth_context->free)(&auth_context); free_user_info(&user_info); return nt_status; @@ -204,14 +211,17 @@ static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out) kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ); if (kerr) { - DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n", + DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed " + "for name %s: Error %s\n", host_princ_s, error_message(kerr) )); goto out; } - - kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply); + + kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, + host_princ, &reply); if (kerr) { - DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n", + DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error " + "failed: Error %s\n", error_message(kerr) )); goto out; } @@ -283,39 +293,46 @@ static void reply_spnego_kerberos(connection_struct *conn, return; } - ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, - &client, &pac_data, &ap_rep, + ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, + &client, &pac_data, &ap_rep, &session_key, True); data_blob_free(&ticket); if (!NT_STATUS_IS_OK(ret)) { #if 0 - /* Experiment that failed. See "only happens with a KDC" comment below. */ + /* Experiment that failed. + * See "only happens with a KDC" comment below. */ if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { /* - * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED - * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded - * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its - * clock and continues rather than giving an error. JRA. + * Windows in this case returns + * NT_STATUS_MORE_PROCESSING_REQUIRED + * with a negTokenTarg blob containing an krb5_error + * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW. + * The client then fixes its clock and continues rather + * than giving an error. JRA. * -- Looks like this only happens with a KDC. JRA. */ BOOL ok = make_krb5_skew_error(&ap_rep); if (!ok) { talloc_destroy(mem_ctx); - return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + return ERROR_NT(nt_status_squash( + NT_STATUS_LOGON_FAILURE)); } - ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR); - response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); - reply_sesssetup_blob(conn, inbuf, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED); + ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, + TOK_ID_KRB_ERROR); + response = spnego_gen_auth_response(&ap_rep_wrapped, + ret, OID_KERBEROS5_OLD); + reply_sesssetup_blob(conn, inbuf, outbuf, response, + NT_STATUS_MORE_PROCESSING_REQUIRED); /* - * In this one case we don't invalidate the intermediate vuid. - * as we're expecting the client to re-use it for the next - * sessionsetupX packet. JRA. + * In this one case we don't invalidate the + * intermediate vuid as we're expecting the client + * to re-use it for the next sessionsetupX packet. JRA. */ *p_invalidate_vuid = False; @@ -331,7 +348,8 @@ static void reply_spnego_kerberos(connection_struct *conn, ret = NT_STATUS_LOGON_FAILURE; } #endif - DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret))); + DEBUG(1,("Failed to verify incoming ticket with error %s!\n", + nt_errstr(ret))); talloc_destroy(mem_ctx); reply_nterror(req, nt_status_squash(ret)); return; @@ -380,8 +398,9 @@ static void reply_spnego_kerberos(connection_struct *conn, domain = p+1; if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { - - unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1); + unistr2_to_ascii(netbios_domain_name, + &logon_info->info3.uni_logon_dom, + -1); domain = netbios_domain_name; DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); @@ -422,7 +441,7 @@ static void reply_spnego_kerberos(connection_struct *conn, } fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client); - + /* lookup the passwd struct, create a new user if necessary */ username_was_mapped = map_username( user ); @@ -435,7 +454,8 @@ static void reply_spnego_kerberos(connection_struct *conn, /* do this before an eventual mappign to guest occurs */ ret = smb_pam_accountcheck(pw->pw_name); if ( !NT_STATUS_IS_OK(ret)) { - DEBUG(1, ("PAM account restriction prevents user login\n")); + DEBUG(1,("PAM account restriction " + "prevents user login\n")); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); @@ -447,19 +467,20 @@ static void reply_spnego_kerberos(connection_struct *conn, if (!pw) { /* this was originally the behavior of Samba 2.2, if a user - did not have a local uid but has been authenticated, then + did not have a local uid but has been authenticated, then map them to a guest account */ - if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ map_domainuser_to_guest = True; fstrcpy(user,lp_guestaccount()); pw = smb_getpwnam( mem_ctx, user, real_username, True ); - } + } /* extra sanity check that the guest account is valid */ if ( !pw ) { - DEBUG(1,("Username %s is invalid on this system\n", user)); + DEBUG(1,("Username %s is invalid on this system\n", + user)); SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); @@ -471,17 +492,17 @@ static void reply_spnego_kerberos(connection_struct *conn, } /* setup the string used by %U */ - + sub_set_smb_name( real_username ); reload_services(True); if ( map_domainuser_to_guest ) { make_server_info_guest(&server_info); } else if (logon_info) { - /* pass the unmapped username here since map_username() + /* pass the unmapped username here since map_username() will be called again from inside make_server_info_info3() */ - - ret = make_server_info_info3(mem_ctx, client, domain, + + ret = make_server_info_info3(mem_ctx, client, domain, &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", @@ -513,15 +534,16 @@ static void reply_spnego_kerberos(connection_struct *conn, * %D. */ if (server_info->sam_account != NULL) { - pdb_set_domain(server_info->sam_account, domain, PDB_SET); + pdb_set_domain(server_info->sam_account, + domain, PDB_SET); } } server_info->was_mapped |= username_was_mapped; - + /* we need to build the token for the user. make_server_info_guest() already does this */ - + if ( !server_info->ptok ) { ret = create_local_token( server_info ); if ( !NT_STATUS_IS_OK(ret) ) { @@ -562,11 +584,11 @@ static void reply_spnego_kerberos(connection_struct *conn, reload_services( True ); SSVAL(req->outbuf, smb_vwv3, 0); - + if (server_info->guest) { SSVAL(req->outbuf,smb_vwv2,1); } - + SSVAL(req->outbuf, smb_uid, sess_vuid); sessionsetup_start_signing_engine(server_info, req->inbuf); @@ -576,11 +598,13 @@ static void reply_spnego_kerberos(connection_struct *conn, /* wrap that up in a nice GSS-API wrapping */ if (NT_STATUS_IS_OK(ret)) { - ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); + ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, + TOK_ID_KRB_AP_REP); } else { ap_rep_wrapped = data_blob_null; } - response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); + response = spnego_gen_auth_response(&ap_rep_wrapped, ret, + OID_KERBEROS5_OLD); reply_sesssetup_blob(conn, req, response, ret); data_blob_free(&ap_rep); @@ -612,10 +636,10 @@ static void reply_spnego_ntlmssp(connection_struct *conn, if (NT_STATUS_IS_OK(nt_status)) { server_info = (*auth_ntlmssp_state)->server_info; } else { - nt_status = do_map_to_guest(nt_status, - &server_info, - (*auth_ntlmssp_state)->ntlmssp_state->user, - (*auth_ntlmssp_state)->ntlmssp_state->domain); + nt_status = do_map_to_guest(nt_status, + &server_info, + (*auth_ntlmssp_state)->ntlmssp_state->user, + (*auth_ntlmssp_state)->ntlmssp_state->domain); } reply_outbuf(req, 4, 0); @@ -624,7 +648,10 @@ static void reply_spnego_ntlmssp(connection_struct *conn, if (NT_STATUS_IS_OK(nt_status)) { DATA_BLOB nullblob = data_blob_null; - DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); + DATA_BLOB session_key = + data_blob( + (*auth_ntlmssp_state)->ntlmssp_state->session_key.data, + (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); if (!is_partial_auth_vuid(vuid)) { data_blob_free(&session_key); @@ -661,7 +688,8 @@ static void reply_spnego_ntlmssp(connection_struct *conn, out: if (wrap) { - response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP); + response = spnego_gen_auth_response(ntlmssp_blob, + nt_status, OID_NTLMSSP); } else { response = *ntlmssp_blob; } @@ -688,7 +716,8 @@ static void reply_spnego_ntlmssp(connection_struct *conn, Is this a krb5 mechanism ? ****************************************************************************/ -NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5) +NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, + BOOL *p_is_krb5) { char *OIDs[ASN1_MAX_OIDS]; int i; @@ -701,22 +730,22 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL * } /* only look at the first OID for determining the mechToken -- - accoirding to RFC2478, we should choose the one we want - and renegotiate, but i smell a client bug here.. - - Problem observed when connecting to a member (samba box) - of an AD domain as a user in a Samba domain. Samba member - server sent back krb5/mskrb5/ntlmssp as mechtypes, but the - client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an + according to RFC2478, we should choose the one we want + and renegotiate, but i smell a client bug here.. + + Problem observed when connecting to a member (samba box) + of an AD domain as a user in a Samba domain. Samba member + server sent back krb5/mskrb5/ntlmssp as mechtypes, but the + client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an NTLMSSP mechtoken. --jerry */ -#ifdef HAVE_KRB5 +#ifdef HAVE_KRB5 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { *p_is_krb5 = True; } #endif - + for (i=0;OIDs[i];i++) { DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i])); free(OIDs[i]); @@ -739,7 +768,8 @@ static void reply_spnego_negotiate(connection_struct *conn, BOOL got_kerberos_mechanism = False; NTSTATUS status; - status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism); + status = parse_spnego_mechanisms(blob1, &secblob, + &got_kerberos_mechanism); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); @@ -747,10 +777,12 @@ static void reply_spnego_negotiate(connection_struct *conn, return; } - DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); + DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", + (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { + if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || + lp_use_kerberos_keytab()) ) { BOOL destroy_vuid = True; reply_spnego_kerberos(conn, req, &secblob, vuid, &destroy_vuid); @@ -775,7 +807,7 @@ static void reply_spnego_negotiate(connection_struct *conn, return; } - status = auth_ntlmssp_update(*auth_ntlmssp_state, + status = auth_ntlmssp_update(*auth_ntlmssp_state, secblob, &chal); data_blob_free(&secblob); @@ -820,11 +852,14 @@ static void reply_spnego_auth(connection_struct *conn, /* Might be a second negTokenTarg packet */ BOOL got_krb5_mechanism = False; - status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism); + status = parse_spnego_mechanisms(auth, &secblob, + &got_krb5_mechanism); if (NT_STATUS_IS_OK(status)) { - DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length)); + DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", + (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { + if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || + lp_use_kerberos_keytab()) ) { BOOL destroy_vuid = True; reply_spnego_kerberos(conn, req, &secblob, vuid, &destroy_vuid); @@ -842,7 +877,7 @@ static void reply_spnego_auth(connection_struct *conn, /* If we get here it wasn't a negTokenTarg auth packet. */ data_blob_free(&secblob); - + if (!*auth_ntlmssp_state) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); @@ -852,8 +887,8 @@ static void reply_spnego_auth(connection_struct *conn, NT_STATUS_INVALID_PARAMETER)); return; } - - status = auth_ntlmssp_update(*auth_ntlmssp_state, + + status = auth_ntlmssp_update(*auth_ntlmssp_state, auth, &auth_reply); data_blob_free(&auth); @@ -861,7 +896,7 @@ static void reply_spnego_auth(connection_struct *conn, reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state, &auth_reply, status, True); - + data_blob_free(&auth_reply); /* and tell smbd that we have already replied to this packet */ @@ -905,11 +940,13 @@ static struct pending_auth_data *get_pending_auth_data(uint16 smbpid) } /**************************************************************************** - Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED, - else return NT_STATUS_OK. Don't allow the blob to be more than 64k. + Check the size of an SPNEGO blob. If we need more return + NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow + the blob to be more than 64k. ****************************************************************************/ -static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob) +static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, + DATA_BLOB *pblob) { struct pending_auth_data *pad = NULL; ASN1_DATA data; @@ -932,7 +969,8 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB /* Integer wrap paranoia.... */ - if (pad->partial_data.length + copy_len < pad->partial_data.length || + if (pad->partial_data.length + copy_len < + pad->partial_data.length || pad->partial_data.length + copy_len < copy_len) { DEBUG(2,("check_spnego_blob_complete: integer wrap " @@ -1039,7 +1077,8 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB /* Refuse the blob if it's bigger than 64k. */ if (needed_len > 65536) { - DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n", + DEBUG(2,("check_spnego_blob_complete: needed_len " + "too large (%u)\n", (unsigned int)needed_len )); return NT_STATUS_INVALID_PARAMETER; } @@ -1092,7 +1131,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, } } - + p = (uint8 *)smb_buf(req->inbuf); if (data_blob_len == 0) { @@ -1116,7 +1155,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, sizeof(native_lanman), STR_TERMINATE); p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE); - DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", + DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", native_os, native_lanman, primary_domain)); if ( ra_type == RA_WIN2K ) { @@ -1124,24 +1163,25 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, if ( !strlen(native_os) && !strlen(native_lanman) ) set_remote_arch(RA_VISTA); - - /* Windows 2003 doesn't set the native lanman string, + + /* Windows 2003 doesn't set the native lanman string, but does set primary domain which is a bug I think */ - + if ( !strlen(native_lanman) ) { ra_lanman_string( primary_domain ); } else { ra_lanman_string( native_lanman ); } } - + /* Did we get a valid vuid ? */ if (!is_partial_auth_vuid(vuid)) { /* No, then try and see if this is an intermediate sessionsetup * for a large SPNEGO packet. */ struct pending_auth_data *pad = get_pending_auth_data(smbpid); if (pad) { - DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n", + DEBUG(10,("reply_sesssetup_and_X_spnego: found " + "pending vuid %u\n", (unsigned int)pad->vuid )); vuid = pad->vuid; } @@ -1172,7 +1212,8 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, status = check_spnego_blob_complete(smbpid, vuid, &blob1); if (!NT_STATUS_IS_OK(status)) { - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + if (!NT_STATUS_EQUAL(status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { /* Real error - kill the intermediate vuid */ invalidate_vuid(vuid); } @@ -1217,9 +1258,9 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, status = auth_ntlmssp_update(vuser->auth_ntlmssp_state, blob1, &chal); - + data_blob_free(&blob1); - + reply_spnego_ntlmssp(conn, req, vuid, &vuser->auth_ntlmssp_state, &chal, status, False); @@ -1267,7 +1308,8 @@ static int shutdown_other_smbds(struct db_record *rec, static void setup_new_vc_session(void) { - DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n")); + DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x " + "compatible we would close all old resources.\n")); #if 0 conn_close_all(); invalidate_all_vuids(); @@ -1284,7 +1326,7 @@ static void setup_new_vc_session(void) void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) { int sess_vuid; - int smb_bufsize; + int smb_bufsize; DATA_BLOB lm_resp; DATA_BLOB nt_resp; DATA_BLOB plaintext_password; @@ -1305,8 +1347,6 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) DATA_BLOB session_key; - - START_PROFILE(SMBsesssetupX); ZERO_STRUCT(lm_resp); @@ -1326,6 +1366,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) "negotiated.\n")); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); + END_PROFILE(SMBsesssetupX); return; } @@ -1334,7 +1375,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) } reply_sesssetup_and_X_spnego(conn, req); - + END_PROFILE(SMBsesssetupX); return; } @@ -1343,7 +1384,8 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) if (Protocol < PROTOCOL_NT1) { uint16 passlen1 = SVAL(req->inbuf,smb_vwv7); - /* Never do NT status codes with protocols before NT1 as we don't get client caps. */ + /* Never do NT status codes with protocols before NT1 as we + * don't get client caps. */ remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); if ((passlen1 > MAX_PASS_LEN) @@ -1351,6 +1393,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) smb_buf(req->inbuf)))) { reply_nterror(req, nt_status_squash( NT_STATUS_INVALID_PARAMETER)); + END_PROFILE(SMBsesssetupX); return; } @@ -1375,49 +1418,55 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) char *p = smb_buf(req->inbuf); char *save_p = smb_buf(req->inbuf); uint16 byte_count; - + if(global_client_caps == 0) { global_client_caps = IVAL(req->inbuf,smb_vwv11); - + if (!(global_client_caps & CAP_STATUS32)) { - remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); + remove_from_common_flags2( + FLAGS2_32_BIT_ERROR_CODES); } - /* client_caps is used as final determination if client is NT or Win95. - This is needed to return the correct error codes in some - circumstances. + /* client_caps is used as final determination if + * client is NT or Win95. This is needed to return + * the correct error codes in some circumstances. */ - - if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) { - if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) { + + if(ra_type == RA_WINNT || ra_type == RA_WIN2K || + ra_type == RA_WIN95) { + if(!(global_client_caps & (CAP_NT_SMBS| + CAP_STATUS32))) { set_remote_arch( RA_WIN95); } } } if (!doencrypt) { - /* both Win95 and WinNT stuff up the password lengths for - non-encrypting systems. Uggh. - - if passlen1==24 its a win95 system, and its setting the - password length incorrectly. Luckily it still works with the - default code because Win95 will null terminate the password - anyway - - if passlen1>0 and passlen2>0 then maybe its a NT box and its - setting passlen2 to some random value which really stuffs - things up. we need to fix that one. */ - - if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1) + /* both Win95 and WinNT stuff up the password + * lengths for non-encrypting systems. Uggh. + + if passlen1==24 its a win95 system, and its setting + the password length incorrectly. Luckily it still + works with the default code because Win95 will null + terminate the password anyway + + if passlen1>0 and passlen2>0 then maybe its a NT box + and its setting passlen2 to some random value which + really stuffs things up. we need to fix that one. */ + + if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && + passlen2 != 1) { passlen2 = 0; + } } - + /* check for nasty tricks */ if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(req->inbuf, p)) { reply_nterror(req, nt_status_squash( NT_STATUS_INVALID_PARAMETER)); + END_PROFILE(SMBsesssetupX); return; } @@ -1425,11 +1474,12 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) { reply_nterror(req, nt_status_squash( NT_STATUS_INVALID_PARAMETER)); + END_PROFILE(SMBsesssetupX); return; } /* Save the lanman2 password and the NT md4 password. */ - + if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) { doencrypt = False; } @@ -1442,9 +1492,12 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) BOOL unic= smb_flag2 & FLAGS2_UNICODE_STRINGS; #if 0 - /* This was the previous fix. Not sure if it's still valid. JRA. */ - if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) { - /* NT4.0 stuffs up plaintext unicode password lengths... */ + /* This was the previous fix. Not sure if it's still + * valid. JRA. */ + if ((ra_type == RA_WINNT) && (passlen2 == 0) + && unic && passlen1) { + /* NT4.0 stuffs up plaintext unicode password + * lengths... */ srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1, sizeof(pass), passlen1, STR_TERMINATE); #endif @@ -1462,7 +1515,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) } plaintext_password = data_blob(pass, strlen(pass)+1); } - + p += passlen1 + passlen2; p += srvstr_pull_buf(req->inbuf, req->flags2, user, p, sizeof(user), STR_TERMINATE); @@ -1474,23 +1527,26 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) native_lanman, p, sizeof(native_lanman), STR_TERMINATE); - /* not documented or decoded by Ethereal but there is one more string - in the extra bytes which is the same as the PrimaryDomain when using - extended security. Windows NT 4 and 2003 use this string to store - the native lanman string. Windows 9x does not include a string here - at all so we have to check if we have any extra bytes left */ - + /* not documented or decoded by Ethereal but there is one more + * string in the extra bytes which is the same as the + * PrimaryDomain when using extended security. Windows NT 4 + * and 2003 use this string to store the native lanman string. + * Windows 9x does not include a string here at all so we have + * to check if we have any extra bytes left */ + byte_count = SVAL(req->inbuf, smb_vwv13); - if ( PTR_DIFF(p, save_p) < byte_count) + if ( PTR_DIFF(p, save_p) < byte_count) { p += srvstr_pull_buf(req->inbuf, req->flags2, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); - else + } else { fstrcpy( primary_domain, "null" ); + } - DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", - domain, native_os, native_lanman, primary_domain)); + DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] " + "PrimaryDomain=[%s]\n", + domain, native_os, native_lanman, primary_domain)); if ( ra_type == RA_WIN2K ) { if ( strlen(native_lanman) == 0 ) @@ -1505,16 +1561,21 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) setup_new_vc_session(); } - DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name())); + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", + domain, user, get_remote_machine_name())); if (*user) { if (global_spnego_negotiated) { - - /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ - - DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); + + /* This has to be here, because this is a perfectly + * valid behaviour for guest logons :-( */ + + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt " + "at 'normal' session setup after " + "negotiating spnego.\n")); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); + END_PROFILE(SMBsesssetupX); return; } fstrcpy(sub_user, user); @@ -1525,7 +1586,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) sub_set_smb_name(sub_user); reload_services(True); - + if (lp_security() == SEC_SHARE) { /* in share level we should ignore any passwords */ @@ -1539,67 +1600,79 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) /* Then force it to null for the benfit of the code below */ *user = 0; } - + if (!*user) { nt_status = check_guest_password(&server_info); } else if (doencrypt) { if (!negprot_global_auth_context) { - DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n")); + DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted " + "session setup without negprot denied!\n")); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); + END_PROFILE(SMBsesssetupX); return; } - nt_status = make_user_info_for_reply_enc(&user_info, user, domain, - lm_resp, nt_resp); + nt_status = make_user_info_for_reply_enc(&user_info, user, + domain, + lm_resp, nt_resp); if (NT_STATUS_IS_OK(nt_status)) { - nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, - user_info, - &server_info); + nt_status = negprot_global_auth_context->check_ntlm_password( + negprot_global_auth_context, + user_info, + &server_info); } } else { struct auth_context *plaintext_auth_context = NULL; const uint8 *chal; - nt_status = make_auth_context_subsystem(&plaintext_auth_context); + nt_status = make_auth_context_subsystem( + &plaintext_auth_context); if (NT_STATUS_IS_OK(nt_status)) { - chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); - - if (!make_user_info_for_reply(&user_info, + chal = plaintext_auth_context->get_ntlm_challenge( + plaintext_auth_context); + + if (!make_user_info_for_reply(&user_info, user, domain, chal, plaintext_password)) { nt_status = NT_STATUS_NO_MEMORY; } - + if (NT_STATUS_IS_OK(nt_status)) { - nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, - user_info, - &server_info); - - (plaintext_auth_context->free)(&plaintext_auth_context); + nt_status = plaintext_auth_context->check_ntlm_password( + plaintext_auth_context, + user_info, + &server_info); + + (plaintext_auth_context->free)( + &plaintext_auth_context); } } } free_user_info(&user_info); - + if (!NT_STATUS_IS_OK(nt_status)) { - nt_status = do_map_to_guest(nt_status, &server_info, user, domain); + nt_status = do_map_to_guest(nt_status, &server_info, + user, domain); } - + if (!NT_STATUS_IS_OK(nt_status)) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); reply_nterror(req, nt_status_squash(nt_status)); + END_PROFILE(SMBsesssetupX); return; } - /* Ensure we can't possible take a code path leading to a null defref. */ + /* Ensure we can't possible take a code path leading to a + * null defref. */ if (!server_info) { reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE)); + END_PROFILE(SMBsesssetupX); return; } @@ -1611,24 +1684,26 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); reply_nterror(req, nt_status_squash(nt_status)); + END_PROFILE(SMBsesssetupX); return; } if (server_info->user_session_key.data) { - session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); + session_key = data_blob(server_info->user_session_key.data, + server_info->user_session_key.length); } else { session_key = data_blob_null; } data_blob_clear_free(&plaintext_password); - + /* it's ok - setup a reply */ reply_outbuf(req, 3, 0); if (Protocol >= PROTOCOL_NT1) { push_signature(&req->outbuf); /* perhaps grab OS version here?? */ } - + if (server_info->guest) { SSVAL(req->outbuf,smb_vwv2,1); } @@ -1647,6 +1722,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_free(&session_key); + END_PROFILE(SMBsesssetupX); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); } @@ -1662,6 +1738,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) data_blob_free(&session_key); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); + END_PROFILE(SMBsesssetupX); return; } @@ -1673,15 +1750,15 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) data_blob_free(&nt_resp); data_blob_free(&lm_resp); - + SSVAL(req->outbuf,smb_uid,sess_vuid); SSVAL(req->inbuf,smb_uid,sess_vuid); - + if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); - + done_sesssetup = True; - + END_PROFILE(SMBsesssetupX); chain_reply_new(req); return; -- cgit From a9184f49d3226358042bd88e65e29adacc2ecf41 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 21 Aug 2007 12:58:10 +0000 Subject: r24595: Fix Coverity ID 393 In this error case we would have used "start" not having it initialized (This used to be commit 751834fff92e85a424152c1642b238daa3060dbd) --- source3/smbd/filename.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 73e3869f50..25ade52947 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -155,8 +155,7 @@ NTSTATUS unix_convert(connection_struct *conn, if (!*orig_path) { if (!(name = SMB_STRDUP("."))) { - result = NT_STATUS_NO_MEMORY; - goto fail; + return NT_STATUS_NO_MEMORY; } if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; -- cgit From 2e498b48bbfb127b33d2e84ba87c7d9456c42558 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Aug 2007 14:22:16 +0000 Subject: r24599: patch from Karolin Seeger : smbd, nmbd and winbindd can be started with invalid options currently. The first patch attached would be a possible solution. It contains an exit if an invalid option has been used. The main problem is, that existing setups with wrong options or missing arguments in start scripts will break (which is the right behaviour from my point of view). metze (This used to be commit 8532e3182ab44d4ac84823e9798293f156192aaf) --- source3/smbd/server.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 491482eea6..3bb60058ac 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -855,7 +855,10 @@ extern void build_options(BOOL screen); case 'b': build_options(True); /* Display output to screen as well as debug */ exit(0); - break; + default: + d_fprintf(stderr, "\nInvalid option %s: %s\n", + poptBadOption(pc, 0), poptStrerror(opt)); + exit(1); } } -- cgit From 281931ea77d6a38606261d5056e7dba21ed6d357 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 21 Aug 2007 18:45:45 +0000 Subject: r24603: In case of error we need to free prefix_cache otherwise on re-init the first statement will return positively but prefix_cache_hashes would be NULL (This used to be commit fdc20894a0deb3c68b834e5d9d466873ca634bed) --- source3/smbd/mangle_hash2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 299d7c99fa..c3db112051 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -163,6 +163,7 @@ static BOOL cache_init(void) prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { + SAFE_FREE(prefix_cache); return False; } -- cgit From 8dd00920ef8f9e6dce9bfb80c45ae46c2a562abd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 22 Aug 2007 12:06:27 +0000 Subject: r24621: - deferr calling build_options();exit(0); - use poptPrintUsage() to give the user more info metze (This used to be commit a95d9d1ef99d6a2f77a289f8d2011cae482821b1) --- source3/smbd/server.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3bb60058ac..8f6d9a38ac 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -818,6 +818,7 @@ extern void build_options(BOOL screen); const char *profile_level = NULL; int opt; poptContext pc; + BOOL print_build_options = False; enum smb_server_mode server_mode = SERVER_MODE_DAEMON; @@ -849,21 +850,25 @@ extern void build_options(BOOL screen); #endif pc = poptGetContext("smbd", argc, argv, long_options, 0); - while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'b': - build_options(True); /* Display output to screen as well as debug */ - exit(0); + print_build_options = True; + break; default: - d_fprintf(stderr, "\nInvalid option %s: %s\n", + d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); exit(1); } } - poptFreeContext(pc); + if (print_build_options) { + build_options(True); /* Display output to screen as well as debug */ + exit(0); + } + #ifdef HAVE_SETLUID /* needed for SecureWare on SCO */ setluid(0); -- cgit From a689f6082b2c8ee82a794e742f904a990702859a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Aug 2007 21:34:08 +0000 Subject: r24638: Remove redundent setting of vuid. Jeremy (This used to be commit fd682c3f397714ebdaf4af3f6d1cbcbab6a2f572) --- source3/smbd/sesssetup.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 4c45806b02..4405b69475 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. handle SMBsessionsetup Copyright (C) Andrew Tridgell 1998-2001 @@ -680,8 +680,6 @@ static void reply_spnego_ntlmssp(connection_struct *conn, SSVAL(req->outbuf,smb_vwv2,1); } - SSVAL(req->outbuf,smb_uid,vuid); - sessionsetup_start_signing_engine(server_info, req->inbuf); } -- cgit From f1041f98ced8ef50373ca37d541d7ca8b1d46638 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Aug 2007 21:53:00 +0000 Subject: r24639: Add parameter "directory name cache size" - parameterize use of directory name cache, 100 by default. Will be needed to turn this off for *BSD systems. Jeremy. (This used to be commit bea8e9840fd65268e649f813eba10502b0c4d721) --- source3/smbd/dir.c | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 30c1d77a84..eec8fa12ef 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -32,8 +32,6 @@ extern struct current_user current_user; /* Make directory handle internals available. */ -#define NAME_CACHE_SIZE 100 - struct name_cache_entry { char *name; long offset; @@ -44,6 +42,7 @@ struct smb_Dir { SMB_STRUCT_DIR *dir; long offset; char *dir_path; + size_t name_cache_size; struct name_cache_entry *name_cache; unsigned int name_cache_index; unsigned int file_number; @@ -1061,12 +1060,14 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr) { struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir); + if (!dirp) { return NULL; } ZERO_STRUCTP(dirp); dirp->conn = conn; + dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); dirp->dir_path = SMB_STRDUP(name); if (!dirp->dir_path) { @@ -1078,9 +1079,14 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *m goto fail; } - dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE); - if (!dirp->name_cache) { - goto fail; + if (dirp->name_cache_size) { + dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, + dirp->name_cache_size); + if (!dirp->name_cache) { + goto fail; + } + } else { + dirp->name_cache = NULL; } dirhandles_open++; @@ -1113,7 +1119,7 @@ int CloseDir(struct smb_Dir *dirp) } SAFE_FREE(dirp->dir_path); if (dirp->name_cache) { - for (i = 0; i < NAME_CACHE_SIZE; i++) { + for (i = 0; i < dirp->name_cache_size; i++) { SAFE_FREE(dirp->name_cache[i].name); } } @@ -1229,7 +1235,12 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) { struct name_cache_entry *e; - dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; + if (!dirp->name_cache_size || !dirp->name_cache) { + return; + } + + dirp->name_cache_index = (dirp->name_cache_index+1) % + dirp->name_cache_size; e = &dirp->name_cache[dirp->name_cache_index]; SAFE_FREE(e->name); e->name = SMB_STRDUP(name); @@ -1248,20 +1259,22 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) connection_struct *conn = dirp->conn; /* Search back in the name cache. */ - for (i = dirp->name_cache_index; i >= 0; i--) { - struct name_cache_entry *e = &dirp->name_cache[i]; - if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { - *poffset = e->offset; - SeekDir(dirp, e->offset); - return True; + if (dirp->name_cache_size && dirp->name_cache) { + for (i = dirp->name_cache_index; i >= 0; i--) { + struct name_cache_entry *e = &dirp->name_cache[i]; + if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { + *poffset = e->offset; + SeekDir(dirp, e->offset); + return True; + } } - } - for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) { - struct name_cache_entry *e = &dirp->name_cache[i]; - if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { - *poffset = e->offset; - SeekDir(dirp, e->offset); - return True; + for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) { + struct name_cache_entry *e = &dirp->name_cache[i]; + if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { + *poffset = e->offset; + SeekDir(dirp, e->offset); + return True; + } } } -- cgit From 5993ddf240a945ae770754454a201c3f7a0ad7d8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 25 Aug 2007 19:47:57 +0000 Subject: r24659: Some formatting changes helping to minimize the 3_2_0 diff (This used to be commit c5caea43af154671448df82881efe09a5c982386) --- source3/smbd/negprot.c | 9 ++++----- source3/smbd/nttrans.c | 6 +++--- source3/smbd/reply.c | 16 ++++++++-------- 3 files changed, 15 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 935d25fab3..4437f0bd3f 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -229,10 +229,9 @@ static DATA_BLOB negprot_spnego(void) char *host_princ_s = NULL; name_to_fqdn(myname, global_myname()); strlower_m(myname); - asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm()); - if (host_princ_s == NULL) { - blob = data_blob_null; - return blob; + if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm()) + == -1) { + return data_blob_null; } blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s); SAFE_FREE(host_princ_s); @@ -540,7 +539,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) num_cliprotos = 0; cliprotos = NULL; - while (p < (smb_buf(req->inbuf) + bcc)) { + while (p < (smb_buf(req->inbuf) + bcc)) { char **tmp; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 907176c161..5e20002339 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -859,19 +859,19 @@ void reply_ntcreate_and_X(connection_struct *conn, create_options, file_attributes, &info, &fsp); - } } TALLOC_FREE(case_state); - if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBntcreateX); + if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ + END_PROFILE(SMBntcreateX); return; } reply_openerror(req, status); + END_PROFILE(SMBntcreateX); return; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b3c4717b0b..c3ae4ef61f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -486,7 +486,7 @@ void reply_tcon(connection_struct *conn, struct smb_request *req) SSVAL(req->outbuf,smb_vwv1,conn->cnum); SSVAL(req->outbuf,smb_tid,conn->cnum); - DEBUG(3,("tcon service=%s cnum=%d\n", + DEBUG(3,("tcon service=%s cnum=%d\n", service, conn->cnum)); END_PROFILE(SMBtcon); @@ -1550,12 +1550,13 @@ void reply_open(connection_struct *conn, struct smb_request *req) &info, &fsp); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBopen); if (open_was_deferred(req->mid)) { + END_PROFILE(SMBopen); /* We have re-scheduled this call. */ return; } reply_openerror(req, status); + END_PROFILE(SMBopen); return; } @@ -1876,7 +1877,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) srvstr_get_path((char *)req->inbuf, req->flags2, fname, smb_buf(req->inbuf) + 1, sizeof(fname), 0, - STR_TERMINATE, &status); + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcreate); @@ -1947,7 +1948,6 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) file_ntimes(conn, fname, ts); reply_outbuf(req, 1, 0); - SSVAL(req->outbuf,smb_vwv0,fsp->fnum); if (oplock_request && lp_fake_oplocks(SNUM(conn))) { @@ -2059,12 +2059,13 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) close(tmpfd); if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBctemp); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ + END_PROFILE(SMBctemp); return; } reply_openerror(req, status); + END_PROFILE(SMBctemp); return; } @@ -2668,7 +2669,7 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - /* + /* * We have to do a check_fsp by hand here, as * we must always return 4 zero bytes on error, * not a NTSTATUS. @@ -2760,7 +2761,7 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req) if (startpos >= size) { nread = 0; } else { - nread = MIN(maxcount,(size - startpos)); + nread = MIN(maxcount,(size - startpos)); } #if 0 /* mincount appears to be ignored in a W2K server. JRA. */ @@ -3088,7 +3089,6 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, TALLOC_FREE(req->outbuf); return; } - #endif normal_read: -- cgit From 7bd8ad3c92839b07fd5f5a3ed0f4eb4c571c24ac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 26 Aug 2007 10:50:39 +0000 Subject: r24661: Fix some obvious diffs between 3_2 and 3_2_0 Jeremy, there are two remaining diffs in sesssetup.c which I don't really know which one is right. Can you take a look? Thanks, Volker (This used to be commit d82f35448763eacd564836f34c9aa450b15ea582) --- source3/smbd/sesssetup.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 4405b69475..0cfe672a82 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -259,7 +259,7 @@ static void reply_spnego_kerberos(connection_struct *conn, fstring netbios_domain_name; struct passwd *pw; fstring user; - int sess_vuid = SVAL(req->inbuf, smb_uid); + int sess_vuid = req->vuid; NTSTATUS ret = NT_STATUS_OK; PAC_DATA *pac_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; @@ -680,7 +680,8 @@ static void reply_spnego_ntlmssp(connection_struct *conn, SSVAL(req->outbuf,smb_vwv2,1); } - sessionsetup_start_signing_engine(server_info, req->inbuf); + sessionsetup_start_signing_engine(server_info, + (uint8 *)req->inbuf); } out: @@ -1720,9 +1721,10 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_free(&session_key); - END_PROFILE(SMBsesssetupX); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); + END_PROFILE(SMBsesssetupX); + return; } /* register_existing_vuid keeps the server info */ sess_vuid = register_existing_vuid(sess_vuid, -- cgit From 3aed02989f0366c48ce2fa41186ad53caadc26d3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 27 Aug 2007 11:01:13 +0000 Subject: r24699: Actually write 24 zeros instead of zero 24's... Jeremy, please check ;-) (This used to be commit 85b64bde7df10ade5ba0abd493d433a7688f0979) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 53368cd8ef..dd3363b20c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3442,7 +3442,7 @@ static void call_trans2qpipeinfo(connection_struct *conn, switch (info_level) { case SMB_FILE_STANDARD_INFORMATION: - memset(pdata,24,0); + memset(pdata,0,24); SOFF_T(pdata,0,4096LL); SIVAL(pdata,16,1); SIVAL(pdata,20,1); -- cgit From b578db69e91a088f158c1cd78a71d00045fc1da6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 27 Aug 2007 12:04:09 +0000 Subject: r24702: Remove the old API pointers (This used to be commit 17df313db42199e26d7d2044f6a1d845aacd1a90) --- source3/smbd/blocking.c | 4 +- source3/smbd/nttrans.c | 6 +- source3/smbd/open.c | 32 +- source3/smbd/pipes.c | 6 +- source3/smbd/process.c | 804 ++++++++++++++++++----------------------------- source3/smbd/reply.c | 15 +- source3/smbd/server.c | 5 - source3/smbd/sesssetup.c | 2 +- 8 files changed, 337 insertions(+), 537 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 8bdc992910..86cf315930 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -21,8 +21,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING -extern int max_send; - /**************************************************************************** This is the structure to queue to implement blocking locks. notify. It consists of the requesting SMB and the expiry time. @@ -272,7 +270,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - chain_reply_new(req); + chain_reply(req); if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) { exit_server_cleanly("send_blocking_reply: send_smb failed."); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5e20002339..f5c5db72a0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -444,7 +444,7 @@ static void do_ntcreate_pipe_open(connection_struct *conn, DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname)); - chain_reply_new(req); + chain_reply(req); } /**************************************************************************** @@ -479,7 +479,7 @@ static void reply_ntcreate_and_X_quota(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - chain_reply_new(req); + chain_reply(req); } /**************************************************************************** @@ -1008,7 +1008,7 @@ void reply_ntcreate_and_X(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - chain_reply_new(req); + chain_reply(req); END_PROFILE(SMBntcreateX); return; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bff445bf61..725d72b284 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -768,7 +768,7 @@ static BOOL request_timed_out(struct timeval request_time, static void defer_open(struct share_mode_lock *lck, struct timeval request_time, struct timeval timeout, - uint16 mid, + struct smb_request *req, struct deferred_open_record *state) { int i; @@ -782,9 +782,9 @@ static void defer_open(struct share_mode_lock *lck, continue; } - if (procid_is_me(&e->pid) && (e->op_mid == mid)) { + if (procid_is_me(&e->pid) && (e->op_mid == req->mid)) { DEBUG(0, ("Trying to defer an already deferred " - "request: mid=%d, exiting\n", mid)); + "request: mid=%d, exiting\n", req->mid)); exit_server("attempt to defer a deferred request"); } } @@ -795,13 +795,13 @@ static void defer_open(struct share_mode_lock *lck, "open entry for mid %u\n", (unsigned int)request_time.tv_sec, (unsigned int)request_time.tv_usec, - (unsigned int)mid)); + (unsigned int)req->mid)); - if (!push_deferred_smb_message(mid, request_time, timeout, + if (!push_deferred_smb_message(req, request_time, timeout, (char *)state, sizeof(*state))) { exit_server("push_deferred_smb_message failed"); } - add_deferred_open(lck, mid, request_time, state->id); + add_deferred_open(lck, req->mid, request_time, state->id); /* * Push the MID of this packet on the signing queue. @@ -810,7 +810,7 @@ static void defer_open(struct share_mode_lock *lck, * of incrementing the response sequence number. */ - srv_defer_sign_response(mid); + srv_defer_sign_response(req->mid); } @@ -1067,7 +1067,7 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time, - uint16 mid) + struct smb_request *req) { struct deferred_open_record state; @@ -1098,7 +1098,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, state.id = lck->id; if (!request_timed_out(request_time, timeout)) { - defer_open(lck, request_time, timeout, mid, &state); + defer_open(lck, request_time, timeout, req, &state); } } @@ -1448,7 +1448,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 1, oplock_request)) { - schedule_defer_open(lck, request_time, req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1468,8 +1468,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 2, oplock_request)) { - schedule_defer_open(lck, request_time, - req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1587,7 +1586,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, && !request_timed_out(request_time, timeout)) { defer_open(lck, request_time, timeout, - req->mid, &state); + req, &state); } } @@ -1678,7 +1677,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 1, oplock_request)) { - schedule_defer_open(lck, request_time, req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1697,8 +1696,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 2, oplock_request)) { - schedule_defer_open(lck, request_time, - req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1724,7 +1722,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (req != NULL) { defer_open(lck, request_time, timeval_zero(), - req->mid, &state); + req, &state); } TALLOC_FREE(lck); return status; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index e8a496ffa7..f43e243453 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -130,7 +130,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) SSVAL(req->outbuf,smb_vwv8,rmode); SSVAL(req->outbuf,smb_vwv11,0x0001); - chain_reply_new(req); + chain_reply(req); return; } @@ -244,7 +244,7 @@ void reply_pipe_write_and_X(struct smb_request *req) DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); - chain_reply_new(req); + chain_reply(req); } /**************************************************************************** @@ -294,7 +294,7 @@ void reply_pipe_read_and_X(struct smb_request *req) DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); - chain_reply_new(req); + chain_reply(req); } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 35f1d6fb3c..99898141db 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -25,13 +25,6 @@ extern int smb_echo_count; const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); -static char *InBuffer = NULL; -static char *OutBuffer = NULL; -static const char *current_inbuf = NULL; - -static char *NewInBuffer(char **old_inbuf); -static char *NewOutBuffer(char **old_outbuf); - /* * Size of data we can send to client. Set * by the client for all protocols above CORE. @@ -90,62 +83,6 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) req->outbuf = NULL; } -/* - * From within a converted call you might have to call non-converted - * subroutines that still take the old inbuf/outbuf/lenght/bufsize - * parameters. This takes a struct smb_request and prepares the legacy - * parameters. - */ - -BOOL reply_prep_legacy(struct smb_request *req, - char **pinbuf, char **poutbuf, - int *psize, int *pbufsize) -{ - const int bufsize = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE - + SAFETY_MARGIN); - char *inbuf, *outbuf; - - DEBUG(1, ("reply_prep_legacy called\n")); - - if (!(inbuf = TALLOC_ARRAY(req, char, bufsize))) { - DEBUG(0, ("Could not allocate legacy inbuf\n")); - return False; - } - memcpy(inbuf, req->inbuf, MIN(smb_len(req->inbuf)+4, bufsize)); - req->inbuf = (uint8 *)inbuf; - - if (!(outbuf = TALLOC_ARRAY(req, char, bufsize))) { - DEBUG(0, ("Could not allocate legacy outbuf\n")); - return False; - } - req->outbuf = (uint8 *)outbuf; - - construct_reply_common(inbuf, outbuf); - - *pinbuf = inbuf; - *poutbuf = outbuf; - *psize = smb_len(inbuf)+4; - *pbufsize = bufsize; - - return True; -} - -/* - * Post-process the output of the legacy routine so that the result fits into - * the new reply_xxx API - */ - -void reply_post_legacy(struct smb_request *req, int outsize) -{ - if (outsize > 0) { - smb_setlen((char *)req->inbuf, (char *)req->outbuf, - outsize); - } - else { - TALLOC_FREE(req->outbuf); - } -} - /**************************************************************************** structure to hold a linked list of queued messages. for processing. @@ -158,11 +95,12 @@ static struct pending_message_list *deferred_open_queue; ready for processing. ****************************************************************************/ -static BOOL push_queued_message(const char *buf, int msg_len, +static BOOL push_queued_message(struct smb_request *req, struct timeval request_time, struct timeval end_time, char *private_data, size_t private_len) { + int msg_len = smb_len(req->inbuf) + 4; struct pending_message_list *msg; msg = TALLOC_ZERO_P(NULL, struct pending_message_list); @@ -172,7 +110,7 @@ static BOOL push_queued_message(const char *buf, int msg_len, return False; } - msg->buf = data_blob_talloc(msg, buf, msg_len); + msg->buf = data_blob_talloc(msg, req->inbuf, msg_len); if(msg->buf.data == NULL) { DEBUG(0,("push_message: malloc fail (2)\n")); TALLOC_FREE(msg); @@ -286,7 +224,7 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) messages ready for processing. ****************************************************************************/ -BOOL push_deferred_smb_message(uint16 mid, +BOOL push_deferred_smb_message(struct smb_request *req, struct timeval request_time, struct timeval timeout, char *private_data, size_t priv_len) @@ -297,12 +235,11 @@ BOOL push_deferred_smb_message(uint16 mid, DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u " "timeout time [%u.%06u]\n", - (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, + (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid, (unsigned int)end_time.tv_sec, (unsigned int)end_time.tv_usec)); - return push_queued_message(current_inbuf, smb_len(current_inbuf)+4, - request_time, end_time, + return push_queued_message(req, request_time, end_time, private_data, priv_len); } @@ -708,267 +645,266 @@ force write permissions on print services. */ static const struct smb_message_struct { const char *name; - int (*fn)(connection_struct *conn, char *, char *, int, int); void (*fn_new)(connection_struct *conn, struct smb_request *req); int flags; } smb_messages[256] = { -/* 0x00 */ { "SMBmkdir",NULL,reply_mkdir,AS_USER | NEED_WRITE}, -/* 0x01 */ { "SMBrmdir",NULL,reply_rmdir,AS_USER | NEED_WRITE}, -/* 0x02 */ { "SMBopen",NULL,reply_open,AS_USER }, -/* 0x03 */ { "SMBcreate",NULL,reply_mknew,AS_USER}, -/* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC }, -/* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER}, -/* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE }, -/* 0x07 */ { "SMBmv",NULL,reply_mv,AS_USER | NEED_WRITE }, -/* 0x08 */ { "SMBgetatr",NULL,reply_getatr,AS_USER}, -/* 0x09 */ { "SMBsetatr",NULL,reply_setatr,AS_USER | NEED_WRITE}, -/* 0x0a */ { "SMBread",NULL,reply_read,AS_USER}, -/* 0x0b */ { "SMBwrite",NULL,reply_write,AS_USER | CAN_IPC }, -/* 0x0c */ { "SMBlock",NULL,reply_lock,AS_USER}, -/* 0x0d */ { "SMBunlock",NULL,reply_unlock,AS_USER}, -/* 0x0e */ { "SMBctemp",NULL,reply_ctemp,AS_USER }, -/* 0x0f */ { "SMBmknew",NULL,reply_mknew,AS_USER}, -/* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER}, -/* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR}, -/* 0x12 */ { "SMBlseek",NULL,reply_lseek,AS_USER}, -/* 0x13 */ { "SMBlockread",NULL,reply_lockread,AS_USER}, -/* 0x14 */ { "SMBwriteunlock",NULL,reply_writeunlock,AS_USER}, -/* 0x15 */ { NULL, NULL, NULL, 0 }, -/* 0x16 */ { NULL, NULL, NULL, 0 }, -/* 0x17 */ { NULL, NULL, NULL, 0 }, -/* 0x18 */ { NULL, NULL, NULL, 0 }, -/* 0x19 */ { NULL, NULL, NULL, 0 }, -/* 0x1a */ { "SMBreadbraw",NULL,reply_readbraw,AS_USER}, -/* 0x1b */ { "SMBreadBmpx",NULL,reply_readbmpx,AS_USER}, -/* 0x1c */ { "SMBreadBs",NULL,reply_readbs,AS_USER }, -/* 0x1d */ { "SMBwritebraw",NULL,reply_writebraw,AS_USER}, -/* 0x1e */ { "SMBwriteBmpx",NULL,reply_writebmpx,AS_USER}, -/* 0x1f */ { "SMBwriteBs",NULL,reply_writebs,AS_USER}, -/* 0x20 */ { "SMBwritec",NULL, NULL,0}, -/* 0x21 */ { NULL, NULL, NULL, 0 }, -/* 0x22 */ { "SMBsetattrE",NULL,reply_setattrE,AS_USER | NEED_WRITE }, -/* 0x23 */ { "SMBgetattrE",NULL,reply_getattrE,AS_USER }, -/* 0x24 */ { "SMBlockingX",NULL,reply_lockingX,AS_USER }, -/* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC }, -/* 0x26 */ { "SMBtranss",NULL,reply_transs,AS_USER | CAN_IPC}, -/* 0x27 */ { "SMBioctl",NULL,reply_ioctl,0}, -/* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, -/* 0x29 */ { "SMBcopy",NULL,reply_copy,AS_USER | NEED_WRITE }, -/* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, -/* 0x2b */ { "SMBecho",NULL,reply_echo,0}, -/* 0x2c */ { "SMBwriteclose",NULL,reply_writeclose,AS_USER}, -/* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC }, -/* 0x2e */ { "SMBreadX",NULL,reply_read_and_X,AS_USER | CAN_IPC }, -/* 0x2f */ { "SMBwriteX",NULL,reply_write_and_X,AS_USER | CAN_IPC }, -/* 0x30 */ { NULL, NULL, NULL, 0 }, -/* 0x31 */ { NULL, NULL, NULL, 0 }, -/* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC }, -/* 0x33 */ { "SMBtranss2", NULL,reply_transs2, AS_USER}, -/* 0x34 */ { "SMBfindclose", NULL,reply_findclose,AS_USER}, -/* 0x35 */ { "SMBfindnclose", NULL,reply_findnclose,AS_USER}, -/* 0x36 */ { NULL, NULL, NULL, 0 }, -/* 0x37 */ { NULL, NULL, NULL, 0 }, -/* 0x38 */ { NULL, NULL, NULL, 0 }, -/* 0x39 */ { NULL, NULL, NULL, 0 }, -/* 0x3a */ { NULL, NULL, NULL, 0 }, -/* 0x3b */ { NULL, NULL, NULL, 0 }, -/* 0x3c */ { NULL, NULL, NULL, 0 }, -/* 0x3d */ { NULL, NULL, NULL, 0 }, -/* 0x3e */ { NULL, NULL, NULL, 0 }, -/* 0x3f */ { NULL, NULL, NULL, 0 }, -/* 0x40 */ { NULL, NULL, NULL, 0 }, -/* 0x41 */ { NULL, NULL, NULL, 0 }, -/* 0x42 */ { NULL, NULL, NULL, 0 }, -/* 0x43 */ { NULL, NULL, NULL, 0 }, -/* 0x44 */ { NULL, NULL, NULL, 0 }, -/* 0x45 */ { NULL, NULL, NULL, 0 }, -/* 0x46 */ { NULL, NULL, NULL, 0 }, -/* 0x47 */ { NULL, NULL, NULL, 0 }, -/* 0x48 */ { NULL, NULL, NULL, 0 }, -/* 0x49 */ { NULL, NULL, NULL, 0 }, -/* 0x4a */ { NULL, NULL, NULL, 0 }, -/* 0x4b */ { NULL, NULL, NULL, 0 }, -/* 0x4c */ { NULL, NULL, NULL, 0 }, -/* 0x4d */ { NULL, NULL, NULL, 0 }, -/* 0x4e */ { NULL, NULL, NULL, 0 }, -/* 0x4f */ { NULL, NULL, NULL, 0 }, -/* 0x50 */ { NULL, NULL, NULL, 0 }, -/* 0x51 */ { NULL, NULL, NULL, 0 }, -/* 0x52 */ { NULL, NULL, NULL, 0 }, -/* 0x53 */ { NULL, NULL, NULL, 0 }, -/* 0x54 */ { NULL, NULL, NULL, 0 }, -/* 0x55 */ { NULL, NULL, NULL, 0 }, -/* 0x56 */ { NULL, NULL, NULL, 0 }, -/* 0x57 */ { NULL, NULL, NULL, 0 }, -/* 0x58 */ { NULL, NULL, NULL, 0 }, -/* 0x59 */ { NULL, NULL, NULL, 0 }, -/* 0x5a */ { NULL, NULL, NULL, 0 }, -/* 0x5b */ { NULL, NULL, NULL, 0 }, -/* 0x5c */ { NULL, NULL, NULL, 0 }, -/* 0x5d */ { NULL, NULL, NULL, 0 }, -/* 0x5e */ { NULL, NULL, NULL, 0 }, -/* 0x5f */ { NULL, NULL, NULL, 0 }, -/* 0x60 */ { NULL, NULL, NULL, 0 }, -/* 0x61 */ { NULL, NULL, NULL, 0 }, -/* 0x62 */ { NULL, NULL, NULL, 0 }, -/* 0x63 */ { NULL, NULL, NULL, 0 }, -/* 0x64 */ { NULL, NULL, NULL, 0 }, -/* 0x65 */ { NULL, NULL, NULL, 0 }, -/* 0x66 */ { NULL, NULL, NULL, 0 }, -/* 0x67 */ { NULL, NULL, NULL, 0 }, -/* 0x68 */ { NULL, NULL, NULL, 0 }, -/* 0x69 */ { NULL, NULL, NULL, 0 }, -/* 0x6a */ { NULL, NULL, NULL, 0 }, -/* 0x6b */ { NULL, NULL, NULL, 0 }, -/* 0x6c */ { NULL, NULL, NULL, 0 }, -/* 0x6d */ { NULL, NULL, NULL, 0 }, -/* 0x6e */ { NULL, NULL, NULL, 0 }, -/* 0x6f */ { NULL, NULL, NULL, 0 }, -/* 0x70 */ { "SMBtcon",NULL,reply_tcon,0}, -/* 0x71 */ { "SMBtdis",NULL,reply_tdis,DO_CHDIR}, -/* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0}, -/* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0}, -/* 0x74 */ { "SMBulogoffX", NULL,reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ -/* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,0}, -/* 0x76 */ { NULL, NULL, NULL, 0 }, -/* 0x77 */ { NULL, NULL, NULL, 0 }, -/* 0x78 */ { NULL, NULL, NULL, 0 }, -/* 0x79 */ { NULL, NULL, NULL, 0 }, -/* 0x7a */ { NULL, NULL, NULL, 0 }, -/* 0x7b */ { NULL, NULL, NULL, 0 }, -/* 0x7c */ { NULL, NULL, NULL, 0 }, -/* 0x7d */ { NULL, NULL, NULL, 0 }, -/* 0x7e */ { NULL, NULL, NULL, 0 }, -/* 0x7f */ { NULL, NULL, NULL, 0 }, -/* 0x80 */ { "SMBdskattr",NULL,reply_dskattr,AS_USER}, -/* 0x81 */ { "SMBsearch",NULL,reply_search,AS_USER}, -/* 0x82 */ { "SMBffirst",NULL,reply_search,AS_USER}, -/* 0x83 */ { "SMBfunique",NULL,reply_search,AS_USER}, -/* 0x84 */ { "SMBfclose",NULL,reply_fclose,AS_USER}, -/* 0x85 */ { NULL, NULL, NULL, 0 }, -/* 0x86 */ { NULL, NULL, NULL, 0 }, -/* 0x87 */ { NULL, NULL, NULL, 0 }, -/* 0x88 */ { NULL, NULL, NULL, 0 }, -/* 0x89 */ { NULL, NULL, NULL, 0 }, -/* 0x8a */ { NULL, NULL, NULL, 0 }, -/* 0x8b */ { NULL, NULL, NULL, 0 }, -/* 0x8c */ { NULL, NULL, NULL, 0 }, -/* 0x8d */ { NULL, NULL, NULL, 0 }, -/* 0x8e */ { NULL, NULL, NULL, 0 }, -/* 0x8f */ { NULL, NULL, NULL, 0 }, -/* 0x90 */ { NULL, NULL, NULL, 0 }, -/* 0x91 */ { NULL, NULL, NULL, 0 }, -/* 0x92 */ { NULL, NULL, NULL, 0 }, -/* 0x93 */ { NULL, NULL, NULL, 0 }, -/* 0x94 */ { NULL, NULL, NULL, 0 }, -/* 0x95 */ { NULL, NULL, NULL, 0 }, -/* 0x96 */ { NULL, NULL, NULL, 0 }, -/* 0x97 */ { NULL, NULL, NULL, 0 }, -/* 0x98 */ { NULL, NULL, NULL, 0 }, -/* 0x99 */ { NULL, NULL, NULL, 0 }, -/* 0x9a */ { NULL, NULL, NULL, 0 }, -/* 0x9b */ { NULL, NULL, NULL, 0 }, -/* 0x9c */ { NULL, NULL, NULL, 0 }, -/* 0x9d */ { NULL, NULL, NULL, 0 }, -/* 0x9e */ { NULL, NULL, NULL, 0 }, -/* 0x9f */ { NULL, NULL, NULL, 0 }, -/* 0xa0 */ { "SMBnttrans", NULL,reply_nttrans, AS_USER | CAN_IPC }, -/* 0xa1 */ { "SMBnttranss", NULL,reply_nttranss, AS_USER | CAN_IPC }, -/* 0xa2 */ { "SMBntcreateX", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC }, -/* 0xa3 */ { NULL, NULL, NULL, 0 }, -/* 0xa4 */ { "SMBntcancel", NULL,reply_ntcancel, 0 }, -/* 0xa5 */ { "SMBntrename", NULL,reply_ntrename, AS_USER | NEED_WRITE }, -/* 0xa6 */ { NULL, NULL, NULL, 0 }, -/* 0xa7 */ { NULL, NULL, NULL, 0 }, -/* 0xa8 */ { NULL, NULL, NULL, 0 }, -/* 0xa9 */ { NULL, NULL, NULL, 0 }, -/* 0xaa */ { NULL, NULL, NULL, 0 }, -/* 0xab */ { NULL, NULL, NULL, 0 }, -/* 0xac */ { NULL, NULL, NULL, 0 }, -/* 0xad */ { NULL, NULL, NULL, 0 }, -/* 0xae */ { NULL, NULL, NULL, 0 }, -/* 0xaf */ { NULL, NULL, NULL, 0 }, -/* 0xb0 */ { NULL, NULL, NULL, 0 }, -/* 0xb1 */ { NULL, NULL, NULL, 0 }, -/* 0xb2 */ { NULL, NULL, NULL, 0 }, -/* 0xb3 */ { NULL, NULL, NULL, 0 }, -/* 0xb4 */ { NULL, NULL, NULL, 0 }, -/* 0xb5 */ { NULL, NULL, NULL, 0 }, -/* 0xb6 */ { NULL, NULL, NULL, 0 }, -/* 0xb7 */ { NULL, NULL, NULL, 0 }, -/* 0xb8 */ { NULL, NULL, NULL, 0 }, -/* 0xb9 */ { NULL, NULL, NULL, 0 }, -/* 0xba */ { NULL, NULL, NULL, 0 }, -/* 0xbb */ { NULL, NULL, NULL, 0 }, -/* 0xbc */ { NULL, NULL, NULL, 0 }, -/* 0xbd */ { NULL, NULL, NULL, 0 }, -/* 0xbe */ { NULL, NULL, NULL, 0 }, -/* 0xbf */ { NULL, NULL, NULL, 0 }, -/* 0xc0 */ { "SMBsplopen",NULL,reply_printopen,AS_USER}, -/* 0xc1 */ { "SMBsplwr",NULL,reply_printwrite,AS_USER}, -/* 0xc2 */ { "SMBsplclose",NULL,reply_printclose,AS_USER}, -/* 0xc3 */ { "SMBsplretq",NULL,reply_printqueue,AS_USER}, -/* 0xc4 */ { NULL, NULL, NULL, 0 }, -/* 0xc5 */ { NULL, NULL, NULL, 0 }, -/* 0xc6 */ { NULL, NULL, NULL, 0 }, -/* 0xc7 */ { NULL, NULL, NULL, 0 }, -/* 0xc8 */ { NULL, NULL, NULL, 0 }, -/* 0xc9 */ { NULL, NULL, NULL, 0 }, -/* 0xca */ { NULL, NULL, NULL, 0 }, -/* 0xcb */ { NULL, NULL, NULL, 0 }, -/* 0xcc */ { NULL, NULL, NULL, 0 }, -/* 0xcd */ { NULL, NULL, NULL, 0 }, -/* 0xce */ { NULL, NULL, NULL, 0 }, -/* 0xcf */ { NULL, NULL, NULL, 0 }, -/* 0xd0 */ { "SMBsends",NULL,reply_sends,AS_GUEST}, -/* 0xd1 */ { "SMBsendb",NULL, NULL,AS_GUEST}, -/* 0xd2 */ { "SMBfwdname",NULL, NULL,AS_GUEST}, -/* 0xd3 */ { "SMBcancelf",NULL, NULL,AS_GUEST}, -/* 0xd4 */ { "SMBgetmac",NULL, NULL,AS_GUEST}, -/* 0xd5 */ { "SMBsendstrt",NULL,reply_sendstrt,AS_GUEST}, -/* 0xd6 */ { "SMBsendend",NULL,reply_sendend,AS_GUEST}, -/* 0xd7 */ { "SMBsendtxt",NULL,reply_sendtxt,AS_GUEST}, -/* 0xd8 */ { NULL, NULL, NULL, 0 }, -/* 0xd9 */ { NULL, NULL, NULL, 0 }, -/* 0xda */ { NULL, NULL, NULL, 0 }, -/* 0xdb */ { NULL, NULL, NULL, 0 }, -/* 0xdc */ { NULL, NULL, NULL, 0 }, -/* 0xdd */ { NULL, NULL, NULL, 0 }, -/* 0xde */ { NULL, NULL, NULL, 0 }, -/* 0xdf */ { NULL, NULL, NULL, 0 }, -/* 0xe0 */ { NULL, NULL, NULL, 0 }, -/* 0xe1 */ { NULL, NULL, NULL, 0 }, -/* 0xe2 */ { NULL, NULL, NULL, 0 }, -/* 0xe3 */ { NULL, NULL, NULL, 0 }, -/* 0xe4 */ { NULL, NULL, NULL, 0 }, -/* 0xe5 */ { NULL, NULL, NULL, 0 }, -/* 0xe6 */ { NULL, NULL, NULL, 0 }, -/* 0xe7 */ { NULL, NULL, NULL, 0 }, -/* 0xe8 */ { NULL, NULL, NULL, 0 }, -/* 0xe9 */ { NULL, NULL, NULL, 0 }, -/* 0xea */ { NULL, NULL, NULL, 0 }, -/* 0xeb */ { NULL, NULL, NULL, 0 }, -/* 0xec */ { NULL, NULL, NULL, 0 }, -/* 0xed */ { NULL, NULL, NULL, 0 }, -/* 0xee */ { NULL, NULL, NULL, 0 }, -/* 0xef */ { NULL, NULL, NULL, 0 }, -/* 0xf0 */ { NULL, NULL, NULL, 0 }, -/* 0xf1 */ { NULL, NULL, NULL, 0 }, -/* 0xf2 */ { NULL, NULL, NULL, 0 }, -/* 0xf3 */ { NULL, NULL, NULL, 0 }, -/* 0xf4 */ { NULL, NULL, NULL, 0 }, -/* 0xf5 */ { NULL, NULL, NULL, 0 }, -/* 0xf6 */ { NULL, NULL, NULL, 0 }, -/* 0xf7 */ { NULL, NULL, NULL, 0 }, -/* 0xf8 */ { NULL, NULL, NULL, 0 }, -/* 0xf9 */ { NULL, NULL, NULL, 0 }, -/* 0xfa */ { NULL, NULL, NULL, 0 }, -/* 0xfb */ { NULL, NULL, NULL, 0 }, -/* 0xfc */ { NULL, NULL, NULL, 0 }, -/* 0xfd */ { NULL, NULL, NULL, 0 }, -/* 0xfe */ { NULL, NULL, NULL, 0 }, -/* 0xff */ { NULL, NULL, NULL, 0 } +/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, +/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, +/* 0x02 */ { "SMBopen",reply_open,AS_USER }, +/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER}, +/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC }, +/* 0x05 */ { "SMBflush",reply_flush,AS_USER}, +/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, +/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE }, +/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER}, +/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, +/* 0x0a */ { "SMBread",reply_read,AS_USER}, +/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC }, +/* 0x0c */ { "SMBlock",reply_lock,AS_USER}, +/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER}, +/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER }, +/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, +/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER}, +/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR}, +/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER}, +/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER}, +/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER}, +/* 0x15 */ { NULL, NULL, 0 }, +/* 0x16 */ { NULL, NULL, 0 }, +/* 0x17 */ { NULL, NULL, 0 }, +/* 0x18 */ { NULL, NULL, 0 }, +/* 0x19 */ { NULL, NULL, 0 }, +/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER}, +/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER}, +/* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER }, +/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER}, +/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER}, +/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER}, +/* 0x20 */ { "SMBwritec", NULL,0}, +/* 0x21 */ { NULL, NULL, 0 }, +/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, +/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, +/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER }, +/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC }, +/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC}, +/* 0x27 */ { "SMBioctl",reply_ioctl,0}, +/* 0x28 */ { "SMBioctls", NULL,AS_USER}, +/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE }, +/* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE }, +/* 0x2b */ { "SMBecho",reply_echo,0}, +/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER}, +/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC }, +/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, +/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, +/* 0x30 */ { NULL, NULL, 0 }, +/* 0x31 */ { NULL, NULL, 0 }, +/* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC }, +/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER}, +/* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER}, +/* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER}, +/* 0x36 */ { NULL, NULL, 0 }, +/* 0x37 */ { NULL, NULL, 0 }, +/* 0x38 */ { NULL, NULL, 0 }, +/* 0x39 */ { NULL, NULL, 0 }, +/* 0x3a */ { NULL, NULL, 0 }, +/* 0x3b */ { NULL, NULL, 0 }, +/* 0x3c */ { NULL, NULL, 0 }, +/* 0x3d */ { NULL, NULL, 0 }, +/* 0x3e */ { NULL, NULL, 0 }, +/* 0x3f */ { NULL, NULL, 0 }, +/* 0x40 */ { NULL, NULL, 0 }, +/* 0x41 */ { NULL, NULL, 0 }, +/* 0x42 */ { NULL, NULL, 0 }, +/* 0x43 */ { NULL, NULL, 0 }, +/* 0x44 */ { NULL, NULL, 0 }, +/* 0x45 */ { NULL, NULL, 0 }, +/* 0x46 */ { NULL, NULL, 0 }, +/* 0x47 */ { NULL, NULL, 0 }, +/* 0x48 */ { NULL, NULL, 0 }, +/* 0x49 */ { NULL, NULL, 0 }, +/* 0x4a */ { NULL, NULL, 0 }, +/* 0x4b */ { NULL, NULL, 0 }, +/* 0x4c */ { NULL, NULL, 0 }, +/* 0x4d */ { NULL, NULL, 0 }, +/* 0x4e */ { NULL, NULL, 0 }, +/* 0x4f */ { NULL, NULL, 0 }, +/* 0x50 */ { NULL, NULL, 0 }, +/* 0x51 */ { NULL, NULL, 0 }, +/* 0x52 */ { NULL, NULL, 0 }, +/* 0x53 */ { NULL, NULL, 0 }, +/* 0x54 */ { NULL, NULL, 0 }, +/* 0x55 */ { NULL, NULL, 0 }, +/* 0x56 */ { NULL, NULL, 0 }, +/* 0x57 */ { NULL, NULL, 0 }, +/* 0x58 */ { NULL, NULL, 0 }, +/* 0x59 */ { NULL, NULL, 0 }, +/* 0x5a */ { NULL, NULL, 0 }, +/* 0x5b */ { NULL, NULL, 0 }, +/* 0x5c */ { NULL, NULL, 0 }, +/* 0x5d */ { NULL, NULL, 0 }, +/* 0x5e */ { NULL, NULL, 0 }, +/* 0x5f */ { NULL, NULL, 0 }, +/* 0x60 */ { NULL, NULL, 0 }, +/* 0x61 */ { NULL, NULL, 0 }, +/* 0x62 */ { NULL, NULL, 0 }, +/* 0x63 */ { NULL, NULL, 0 }, +/* 0x64 */ { NULL, NULL, 0 }, +/* 0x65 */ { NULL, NULL, 0 }, +/* 0x66 */ { NULL, NULL, 0 }, +/* 0x67 */ { NULL, NULL, 0 }, +/* 0x68 */ { NULL, NULL, 0 }, +/* 0x69 */ { NULL, NULL, 0 }, +/* 0x6a */ { NULL, NULL, 0 }, +/* 0x6b */ { NULL, NULL, 0 }, +/* 0x6c */ { NULL, NULL, 0 }, +/* 0x6d */ { NULL, NULL, 0 }, +/* 0x6e */ { NULL, NULL, 0 }, +/* 0x6f */ { NULL, NULL, 0 }, +/* 0x70 */ { "SMBtcon",reply_tcon,0}, +/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR}, +/* 0x72 */ { "SMBnegprot",reply_negprot,0}, +/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0}, +/* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ +/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0}, +/* 0x76 */ { NULL, NULL, 0 }, +/* 0x77 */ { NULL, NULL, 0 }, +/* 0x78 */ { NULL, NULL, 0 }, +/* 0x79 */ { NULL, NULL, 0 }, +/* 0x7a */ { NULL, NULL, 0 }, +/* 0x7b */ { NULL, NULL, 0 }, +/* 0x7c */ { NULL, NULL, 0 }, +/* 0x7d */ { NULL, NULL, 0 }, +/* 0x7e */ { NULL, NULL, 0 }, +/* 0x7f */ { NULL, NULL, 0 }, +/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER}, +/* 0x81 */ { "SMBsearch",reply_search,AS_USER}, +/* 0x82 */ { "SMBffirst",reply_search,AS_USER}, +/* 0x83 */ { "SMBfunique",reply_search,AS_USER}, +/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER}, +/* 0x85 */ { NULL, NULL, 0 }, +/* 0x86 */ { NULL, NULL, 0 }, +/* 0x87 */ { NULL, NULL, 0 }, +/* 0x88 */ { NULL, NULL, 0 }, +/* 0x89 */ { NULL, NULL, 0 }, +/* 0x8a */ { NULL, NULL, 0 }, +/* 0x8b */ { NULL, NULL, 0 }, +/* 0x8c */ { NULL, NULL, 0 }, +/* 0x8d */ { NULL, NULL, 0 }, +/* 0x8e */ { NULL, NULL, 0 }, +/* 0x8f */ { NULL, NULL, 0 }, +/* 0x90 */ { NULL, NULL, 0 }, +/* 0x91 */ { NULL, NULL, 0 }, +/* 0x92 */ { NULL, NULL, 0 }, +/* 0x93 */ { NULL, NULL, 0 }, +/* 0x94 */ { NULL, NULL, 0 }, +/* 0x95 */ { NULL, NULL, 0 }, +/* 0x96 */ { NULL, NULL, 0 }, +/* 0x97 */ { NULL, NULL, 0 }, +/* 0x98 */ { NULL, NULL, 0 }, +/* 0x99 */ { NULL, NULL, 0 }, +/* 0x9a */ { NULL, NULL, 0 }, +/* 0x9b */ { NULL, NULL, 0 }, +/* 0x9c */ { NULL, NULL, 0 }, +/* 0x9d */ { NULL, NULL, 0 }, +/* 0x9e */ { NULL, NULL, 0 }, +/* 0x9f */ { NULL, NULL, 0 }, +/* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC }, +/* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC }, +/* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC }, +/* 0xa3 */ { NULL, NULL, 0 }, +/* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 }, +/* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE }, +/* 0xa6 */ { NULL, NULL, 0 }, +/* 0xa7 */ { NULL, NULL, 0 }, +/* 0xa8 */ { NULL, NULL, 0 }, +/* 0xa9 */ { NULL, NULL, 0 }, +/* 0xaa */ { NULL, NULL, 0 }, +/* 0xab */ { NULL, NULL, 0 }, +/* 0xac */ { NULL, NULL, 0 }, +/* 0xad */ { NULL, NULL, 0 }, +/* 0xae */ { NULL, NULL, 0 }, +/* 0xaf */ { NULL, NULL, 0 }, +/* 0xb0 */ { NULL, NULL, 0 }, +/* 0xb1 */ { NULL, NULL, 0 }, +/* 0xb2 */ { NULL, NULL, 0 }, +/* 0xb3 */ { NULL, NULL, 0 }, +/* 0xb4 */ { NULL, NULL, 0 }, +/* 0xb5 */ { NULL, NULL, 0 }, +/* 0xb6 */ { NULL, NULL, 0 }, +/* 0xb7 */ { NULL, NULL, 0 }, +/* 0xb8 */ { NULL, NULL, 0 }, +/* 0xb9 */ { NULL, NULL, 0 }, +/* 0xba */ { NULL, NULL, 0 }, +/* 0xbb */ { NULL, NULL, 0 }, +/* 0xbc */ { NULL, NULL, 0 }, +/* 0xbd */ { NULL, NULL, 0 }, +/* 0xbe */ { NULL, NULL, 0 }, +/* 0xbf */ { NULL, NULL, 0 }, +/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER}, +/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER}, +/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER}, +/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER}, +/* 0xc4 */ { NULL, NULL, 0 }, +/* 0xc5 */ { NULL, NULL, 0 }, +/* 0xc6 */ { NULL, NULL, 0 }, +/* 0xc7 */ { NULL, NULL, 0 }, +/* 0xc8 */ { NULL, NULL, 0 }, +/* 0xc9 */ { NULL, NULL, 0 }, +/* 0xca */ { NULL, NULL, 0 }, +/* 0xcb */ { NULL, NULL, 0 }, +/* 0xcc */ { NULL, NULL, 0 }, +/* 0xcd */ { NULL, NULL, 0 }, +/* 0xce */ { NULL, NULL, 0 }, +/* 0xcf */ { NULL, NULL, 0 }, +/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST}, +/* 0xd1 */ { "SMBsendb", NULL,AS_GUEST}, +/* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST}, +/* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST}, +/* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST}, +/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST}, +/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST}, +/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST}, +/* 0xd8 */ { NULL, NULL, 0 }, +/* 0xd9 */ { NULL, NULL, 0 }, +/* 0xda */ { NULL, NULL, 0 }, +/* 0xdb */ { NULL, NULL, 0 }, +/* 0xdc */ { NULL, NULL, 0 }, +/* 0xdd */ { NULL, NULL, 0 }, +/* 0xde */ { NULL, NULL, 0 }, +/* 0xdf */ { NULL, NULL, 0 }, +/* 0xe0 */ { NULL, NULL, 0 }, +/* 0xe1 */ { NULL, NULL, 0 }, +/* 0xe2 */ { NULL, NULL, 0 }, +/* 0xe3 */ { NULL, NULL, 0 }, +/* 0xe4 */ { NULL, NULL, 0 }, +/* 0xe5 */ { NULL, NULL, 0 }, +/* 0xe6 */ { NULL, NULL, 0 }, +/* 0xe7 */ { NULL, NULL, 0 }, +/* 0xe8 */ { NULL, NULL, 0 }, +/* 0xe9 */ { NULL, NULL, 0 }, +/* 0xea */ { NULL, NULL, 0 }, +/* 0xeb */ { NULL, NULL, 0 }, +/* 0xec */ { NULL, NULL, 0 }, +/* 0xed */ { NULL, NULL, 0 }, +/* 0xee */ { NULL, NULL, 0 }, +/* 0xef */ { NULL, NULL, 0 }, +/* 0xf0 */ { NULL, NULL, 0 }, +/* 0xf1 */ { NULL, NULL, 0 }, +/* 0xf2 */ { NULL, NULL, 0 }, +/* 0xf3 */ { NULL, NULL, 0 }, +/* 0xf4 */ { NULL, NULL, 0 }, +/* 0xf5 */ { NULL, NULL, 0 }, +/* 0xf6 */ { NULL, NULL, 0 }, +/* 0xf7 */ { NULL, NULL, 0 }, +/* 0xf8 */ { NULL, NULL, 0 }, +/* 0xf9 */ { NULL, NULL, 0 }, +/* 0xfa */ { NULL, NULL, 0 }, +/* 0xfb */ { NULL, NULL, 0 }, +/* 0xfc */ { NULL, NULL, 0 }, +/* 0xfd */ { NULL, NULL, 0 }, +/* 0xfe */ { NULL, NULL, 0 }, +/* 0xff */ { NULL, NULL, 0 } }; @@ -1049,8 +985,7 @@ static void smb_dump(const char *name, int type, const char *data, ssize_t len) find. ****************************************************************************/ -static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, - connection_struct **pconn) +static void switch_message(uint8 type, struct smb_request *req, int size) { int flags; uint16 session_tag; @@ -1069,15 +1004,13 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, DEBUG(2,("Non-SMB packet of length %d. Terminating server\n", smb_len(req->inbuf))); exit_server_cleanly("Non-SMB packet"); - return True; } - if ((smb_messages[type].fn == NULL) - && (smb_messages[type].fn_new == NULL)) { + if (smb_messages[type].fn_new == NULL) { DEBUG(0,("Unknown message type %d!\n",type)); smb_dump("Unknown", 1, (char *)req->inbuf, size); reply_unknown_new(req, type); - goto done; + return; } flags = smb_messages[type].flags; @@ -1130,12 +1063,12 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, } else { reply_doserror(req, ERRSRV, ERRinvnid); } - goto done; + return; } if (!change_to_user(conn,session_tag)) { reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); - goto done; + return; } /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ @@ -1143,13 +1076,13 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, /* Does it need write permission? */ if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED); - goto done; + return; } /* IPC services are limited */ if (IS_IPC(conn) && !(flags & CAN_IPC)) { reply_doserror(req, ERRSRV,ERRaccess); - goto done; + return; } } else { /* This call needs to be run as root */ @@ -1162,7 +1095,7 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, (flags & (AS_USER|DO_CHDIR) ?True:False))) { reply_doserror(req, ERRSRV, ERRaccess); - goto done; + return; } conn->num_smb_operations++; } @@ -1173,73 +1106,10 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { reply_doserror(req, ERRSRV, ERRaccess); - goto done; - } - - current_inbuf = (char *)req->inbuf; /* In case we need to defer this - * message in open... */ - - if (smb_messages[type].fn_new != NULL) { - smb_messages[type].fn_new(conn, req); - goto done; - } - - /* - * Indicate the upper layer that there's still work. - */ - *pconn = conn; - return False; - - done: - return True; -} - - -/**************************************************************************** - Do a switch on the message type, and return the response size -****************************************************************************/ - -static int switch_message(uint8 type, struct smb_request *req, char **outbuf, - int size, int bufsize) -{ - int outsize = 0; - connection_struct *conn = NULL; - - if (switch_message_new(type, req, size, &conn)) { - if (req->outbuf != NULL) { - *outbuf = (char *)req->outbuf; - return smb_len(req->outbuf)+4; - } - return -1; - } - - if (InBuffer == NULL) { - DEBUG(1, ("have to alloc InBuffer for %s\n", - smb_fn_name(type))); - if (NewInBuffer(NULL) == NULL) { - smb_panic("Could not allocate InBuffer"); - } - } - - if ((OutBuffer == NULL) && (NewOutBuffer(NULL) == NULL)) { - smb_panic("Could not allocate OutBuffer"); + return; } - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, - total_buffer_size); - - memcpy(InBuffer, req->inbuf, MIN(size, total_buffer_size)); - - construct_reply_common(InBuffer, OutBuffer); - - outsize = smb_messages[type].fn(conn, InBuffer, OutBuffer, size, - bufsize); - - smb_dump(smb_fn_name(type), 0, OutBuffer, outsize); - - *outbuf = OutBuffer; - - return(outsize); + smb_messages[type].fn_new(conn, req); } /**************************************************************************** @@ -1249,9 +1119,7 @@ static int switch_message(uint8 type, struct smb_request *req, char **outbuf, static void construct_reply(char *inbuf, int size) { uint8 type = CVAL(inbuf,smb_com); - int outsize = 0; struct smb_request *req; - char *outbuf; chain_size = 0; file_chain_reset(); @@ -1262,23 +1130,18 @@ static void construct_reply(char *inbuf, int size) } init_smb_request(req, (uint8 *)inbuf); - outsize = switch_message(type, req, &outbuf, size, max_send); + switch_message(type, req, size); - if (outsize > 4) { - smb_setlen(inbuf,outbuf,outsize - 4); + if (req->outbuf == NULL) { + return; } - if (outsize > 0) { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); + if (CVAL(req->outbuf,0) == 0) { + show_msg((char *)req->outbuf); + } - if (outsize != smb_len(outbuf) + 4) { - DEBUG(0,("ERROR: Invalid message response size! " - "%d %d\n", outsize, smb_len(outbuf))); - } else if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("construct_reply: send_smb " - "failed."); - } + if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) { + exit_server_cleanly("construct_reply: send_smb failed."); } TALLOC_FREE(req); @@ -1383,29 +1246,37 @@ void construct_reply_common(const char *inbuf, char *outbuf) Construct a chained reply and add it to the already made reply ****************************************************************************/ -int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) +void chain_reply(struct smb_request *req) { static char *orig_inbuf; + + /* + * Dirty little const_discard: We mess with req->inbuf, which is + * declared as const. If maybe at some point this routine gets + * rewritten, this const_discard could go away. + */ + char *inbuf = CONST_DISCARD(char *, req->inbuf); + int size = smb_len(req->inbuf)+4; + int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); unsigned smb_off2 = SVAL(inbuf,smb_vwv1); char *inbuf2; - char *outbuf2 = NULL; int outsize2; int new_size; char inbuf_saved[smb_wct]; - char *outbuf = *poutbuf; + char *outbuf = (char *)req->outbuf; size_t outsize = smb_len(outbuf) + 4; size_t outsize_padded; size_t ofs, to_move; - struct smb_request *req; + struct smb_request *req2; size_t caller_outputlen; char *caller_output; /* Maybe its not chained, or it's an error packet. */ if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) { SCVAL(outbuf,smb_vwv0,0xFF); - return outsize; + return; } if (chain_size == 0) { @@ -1466,7 +1337,7 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) "(orig size = %d, offset = %d)\n", size, (int)(inbuf2 - inbuf) )); exit_server_cleanly("Bad chained packet"); - return(-1); + return; } /* And set it in the header. */ @@ -1475,19 +1346,19 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) DEBUG(3,("Chained message\n")); show_msg(inbuf2); - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + if (!(req2 = talloc(tmp_talloc_ctx(), struct smb_request))) { smb_panic("could not allocate smb_request"); } - init_smb_request(req, (uint8 *)inbuf2); + init_smb_request(req2, (uint8 *)inbuf2); /* process the request */ - outsize2 = switch_message(smb_com2, req, &outbuf2, new_size, - bufsize-chain_size); + switch_message(smb_com2, req2, new_size); /* * We don't accept deferred operations in chained requests. */ - SMB_ASSERT(outsize2 >= smb_wct); + SMB_ASSERT(req2->outbuf != NULL); + outsize2 = smb_len(req2->outbuf)+4; /* * Move away the new command output so that caller_output fits in, @@ -1520,24 +1391,22 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) * which is always large enough. */ - if (outbuf != OutBuffer) { - outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char, - to_move + ofs + smb_wct); - if (outbuf == NULL) { - smb_panic("could not realloc outbuf"); - } + outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char, + to_move + ofs + smb_wct); + if (outbuf == NULL) { + smb_panic("could not realloc outbuf"); } - *poutbuf = outbuf; + req->outbuf = (uint8 *)outbuf; - memmove(outbuf + smb_wct + ofs, outbuf2 + smb_wct, to_move); + memmove(outbuf + smb_wct + ofs, req2->outbuf + smb_wct, to_move); memcpy(outbuf + smb_wct, caller_output, caller_outputlen); /* * copy the new reply header over the old one but preserve the smb_com * field */ - memmove(outbuf,outbuf2,smb_wct); + memmove(outbuf, req2->outbuf, smb_wct); SCVAL(outbuf, smb_com, smb_com1); /* @@ -1568,17 +1437,9 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) memcpy(inbuf2,inbuf_saved,smb_wct); SAFE_FREE(caller_output); - TALLOC_FREE(req); - - return outsize2 + chain_size; -} + TALLOC_FREE(req2); -void chain_reply_new(struct smb_request *req) -{ - chain_reply(CONST_DISCARD(char *, req->inbuf), - (char **)(void *)&req->outbuf, - smb_len(req->inbuf)+4, - smb_len(req->outbuf)+4); + return; } /**************************************************************************** @@ -1757,55 +1618,6 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); return True; } -/**************************************************************************** - Accessor functions for InBuffer, OutBuffer. -****************************************************************************/ - -char *get_InBuffer(void) -{ - return InBuffer; -} - -/**************************************************************************** - Allocate a new InBuffer. Returns the new and old ones. -****************************************************************************/ - -static char *NewInBuffer(char **old_inbuf) -{ - char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size); - if (!new_inbuf) { - return NULL; - } - if (old_inbuf) { - *old_inbuf = InBuffer; - } - InBuffer = new_inbuf; -#if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); -#endif - return InBuffer; -} - -/**************************************************************************** - Allocate a new OutBuffer. Returns the new and old ones. -****************************************************************************/ - -static char *NewOutBuffer(char **old_outbuf) -{ - char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size); - if (!new_outbuf) { - return NULL; - } - if (old_outbuf) { - *old_outbuf = OutBuffer; - } - OutBuffer = new_outbuf; -#if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); -#endif - return OutBuffer; -} - /**************************************************************************** Process commands from the client ****************************************************************************/ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c3ae4ef61f..2694176ca7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -687,7 +687,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) TALLOC_FREE(ctx); END_PROFILE(SMBtconX); - chain_reply_new(req); + chain_reply(req); return; } @@ -1802,7 +1802,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) } END_PROFILE(SMBopenX); - chain_reply_new(req); + chain_reply(req); return; } @@ -1837,7 +1837,7 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req) DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) ); END_PROFILE(SMBulogoffX); - chain_reply_new(req); + chain_reply(req); } /**************************************************************************** @@ -3129,7 +3129,7 @@ normal_read: DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); - chain_reply_new(req); + chain_reply(req); return; } @@ -3241,7 +3241,6 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) if (!big_readX && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) { END_PROFILE(SMBreadX); - reply_post_legacy(req, -1); return; } @@ -3842,7 +3841,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) } END_PROFILE(SMBwriteX); - chain_reply_new(req); + chain_reply(req); return; } @@ -6252,7 +6251,6 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) * send a reply */ if (num_locks == 0 && num_ulocks == 0) { END_PROFILE(SMBlockingX); - reply_post_legacy(req, -1); return; } else { END_PROFILE(SMBlockingX); @@ -6459,7 +6457,6 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) block_smbpid)) { TALLOC_FREE(br_lck); END_PROFILE(SMBlockingX); - reply_post_legacy(req, -1); return; } } @@ -6519,7 +6516,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); END_PROFILE(SMBlockingX); - chain_reply_new(req); + chain_reply(req); } #undef DBGC_CLASS diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8f6d9a38ac..7e55d3c086 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -701,7 +701,6 @@ static void exit_server_common(enum server_exit_reason how, if (how != SERVER_EXIT_NORMAL) { int oldlevel = DEBUGLEVEL; - char *last_inbuf = get_InBuffer(); DEBUGLEVEL = 10; @@ -711,10 +710,6 @@ static void exit_server_common(enum server_exit_reason how, DEBUGSEP(0); log_stack_trace(); - if (last_inbuf) { - DEBUG(0,("Last message was %s\n", LAST_MESSAGE())); - show_msg(last_inbuf); - } DEBUGLEVEL = oldlevel; dump_core(); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0cfe672a82..520835bef7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1760,6 +1760,6 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) done_sesssetup = True; END_PROFILE(SMBsesssetupX); - chain_reply_new(req); + chain_reply(req); return; } -- cgit From d76e724b1029f840c947859ba5354fa171a2b383 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 29 Aug 2007 20:49:09 +0000 Subject: r24791: Fix logic error in timeout of blocking lock processing found by Ronnie. If a lock timeout expires, we must check we can get the lock before responding with failure. Volker is writing a torture test. Jeremy. (This used to be commit 45380f356b99d575645873b05af17c504b091dc8) --- source3/smbd/blocking.c | 51 ++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 86cf315930..3bf6e0f99a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -702,18 +702,14 @@ static void process_blocking_lock_queue(void) DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", fsp->fnum, fsp->fsp_name )); - if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { + if(!change_to_user(conn,vuid)) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* - * Lock expired - throw away all previously - * obtained locks and return lock error. + * Remove the entry and return an error to the client. */ if (br_lck) { - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); - brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), @@ -723,14 +719,16 @@ static void process_blocking_lock_queue(void) TALLOC_FREE(br_lck); } - blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); recalc_timeout = True; continue; } - if(!change_to_user(conn,vuid)) { + if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* @@ -747,21 +745,23 @@ static void process_blocking_lock_queue(void) TALLOC_FREE(br_lck); } - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); recalc_timeout = True; + change_to_root_user(); continue; } - if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + /* + * Go through the remaining locks and try and obtain them. + * The call returns True if all locks were obtained successfully + * and False if we still need to wait. + */ - /* - * Remove the entry and return an error to the client. - */ + if(blocking_lock_record_process(blr)) { + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { brl_lock_cancel(br_lck, @@ -773,8 +773,6 @@ static void process_blocking_lock_queue(void) TALLOC_FREE(br_lck); } - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); recalc_timeout = True; @@ -782,16 +780,25 @@ static void process_blocking_lock_queue(void) continue; } + change_to_root_user(); + /* - * Go through the remaining locks and try and obtain them. - * The call returns True if all locks were obtained successfully - * and False if we still need to wait. + * We couldn't get the locks for this record on the list. + * If the time has expired, return a lock error. */ - if(blocking_lock_record_process(blr)) { + if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + /* + * Lock expired - throw away all previously + * obtained locks and return lock error. + */ + if (br_lck) { + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fsp->fnum, fsp->fsp_name )); + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), @@ -801,11 +808,11 @@ static void process_blocking_lock_queue(void) TALLOC_FREE(br_lck); } + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); recalc_timeout = True; } - change_to_root_user(); } if (recalc_timeout) { -- cgit From 929e1d99209e20a9c2c95c8bdfc8eaa37b2c2291 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 30 Aug 2007 19:48:31 +0000 Subject: r24809: Consolidate the use of temporary talloc contexts. This adds the two functions talloc_stackframe() and talloc_tos(). * When a new talloc stackframe is allocated with talloc_stackframe(), then * the TALLOC_CTX returned with talloc_tos() is reset to that new * frame. Whenever that stack frame is TALLOC_FREE()'ed, then the reverse * happens: The previous talloc_tos() is restored. * * This API is designed to be robust in the sense that if someone forgets to * TALLOC_FREE() a stackframe, then the next outer one correctly cleans up and * resets the talloc_tos(). The original motivation for this patch was to get rid of the sid_string_static & friends buffers. Explicitly passing talloc context everywhere clutters code too much for my taste, so an implicit talloc_tos() is introduced here. Many of these static buffers are replaced by a single static pointer. The intended use would thus be that low-level functions can rather freely push stuff to talloc_tos, the upper layers clean up by freeing the stackframe. The more of these stackframes are used and correctly freed the more exact the memory cleanup happens. This patch removes the main_loop_talloc_ctx, tmp_talloc_ctx and lp_talloc_ctx (did I forget any?) So, never do a tmp_ctx = talloc_init("foo"); anymore, instead, use tmp_ctx = talloc_stackframe() :-) Volker (This used to be commit 6585ea2cb7f417e14540495b9c7380fe9c8c717b) --- source3/smbd/blocking.c | 4 ++-- source3/smbd/lanman.c | 2 +- source3/smbd/negprot.c | 2 +- source3/smbd/notify.c | 2 +- source3/smbd/nttrans.c | 2 +- source3/smbd/open.c | 4 ++-- source3/smbd/posix_acls.c | 4 ++-- source3/smbd/process.c | 10 ++++------ source3/smbd/server.c | 3 --- source3/smbd/trans2.c | 4 ++-- 10 files changed, 16 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 3bf6e0f99a..ef70829f74 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -255,7 +255,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) { struct smb_request *req; - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + if (!(req = talloc(talloc_tos(), struct smb_request))) { smb_panic("Could not allocate smb_request"); } @@ -526,7 +526,7 @@ static BOOL process_trans2(blocking_lock_record *blr) /* We finally got the lock, return success. */ - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + if (!(req = talloc(talloc_tos(), struct smb_request))) { blocking_lock_reply_error(blr, NT_STATUS_NO_MEMORY); return True; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 1d6369c18b..581ac90aeb 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4216,7 +4216,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, return False; } - num_sessions = list_sessions(tmp_talloc_ctx(), &session_list); + num_sessions = list_sessions(talloc_tos(), &session_list); if (mdrcnt > 0) { *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 4437f0bd3f..98109a2149 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -543,7 +543,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) char **tmp; - tmp = TALLOC_REALLOC_ARRAY(tmp_talloc_ctx(), cliprotos, char *, + tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), cliprotos, char *, num_cliprotos+1); if (tmp == NULL) { DEBUG(0, ("talloc failed\n")); diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 0bdf466092..da80c25407 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -176,7 +176,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + if (!(req = talloc(talloc_tos(), struct smb_request))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f5c5db72a0..b5af173d45 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1484,7 +1484,7 @@ static void call_nt_transact_create(connection_struct *conn, pdata = data + sd_len; /* We have already checked that ea_len <= data_count here. */ - ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata, + ea_list = read_nttrans_ea_list(talloc_tos(), pdata, ea_len); if (!ea_list ) { TALLOC_FREE(case_state); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 725d72b284..6efef2f912 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1159,7 +1159,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return print_fsp_open(conn, fname, result); } - if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir, + if (!parent_dirname_talloc(talloc_tos(), fname, &parent_dir, &newname)) { return NT_STATUS_NO_MEMORY; } @@ -1979,7 +1979,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, return status; } - if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir, + if (!parent_dirname_talloc(talloc_tos(), name, &parent_dir, &dirname)) { return NT_STATUS_NO_MEMORY; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6286cd0414..64051d23b1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2971,14 +2971,14 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } if (num_aces) { - if((psa = make_sec_acl( main_loop_talloc_get(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) { + if((psa = make_sec_acl( talloc_tos(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); goto done; } } } /* security_info & DACL_SECURITY_INFORMATION */ - psd = make_standard_sec_desc( main_loop_talloc_get(), + psd = make_standard_sec_desc( talloc_tos(), (security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL, (security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL, psa, diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 99898141db..8b3e85f4b4 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1125,7 +1125,7 @@ static void construct_reply(char *inbuf, int size) file_chain_reset(); reset_chain_p(); - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + if (!(req = talloc(talloc_tos(), struct smb_request))) { smb_panic("could not allocate smb_request"); } init_smb_request(req, (uint8 *)inbuf); @@ -1346,7 +1346,7 @@ void chain_reply(struct smb_request *req) DEBUG(3,("Chained message\n")); show_msg(inbuf2); - if (!(req2 = talloc(tmp_talloc_ctx(), struct smb_request))) { + if (!(req2 = talloc(talloc_tos(), struct smb_request))) { smb_panic("could not allocate smb_request"); } init_smb_request(req2, (uint8 *)inbuf2); @@ -1634,13 +1634,10 @@ void smbd_process(void) int num_echos; char *inbuf; size_t inbuf_len; + TALLOC_CTX *frame = talloc_stackframe(); errno = 0; - /* free up temporary memory */ - lp_TALLOC_FREE(); - main_loop_TALLOC_FREE(); - /* Did someone ask for immediate checks on things like blocking locks ? */ if (select_timeout == 0) { if(!timeout_processing(&select_timeout, @@ -1713,5 +1710,6 @@ void smbd_process(void) change_to_root_user(); check_log_size(); } + TALLOC_FREE(frame); } } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7e55d3c086..72eeb7ee6a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -384,9 +384,6 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ fd_set r_fds, w_fds; int num; - /* Free up temporary memory from the main smbd. */ - lp_TALLOC_FREE(); - /* Ensure we respond to PING and DEBUG messages from the main smbd. */ message_dispatch(smbd_messaging_context()); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dd3363b20c..ed4d4554d4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -888,7 +888,7 @@ static void call_trans2open(connection_struct *conn, return; } - ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4, + ea_list = read_ea_list(talloc_tos(), pdata + 4, total_data - 4); if (!ea_list) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -6613,7 +6613,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, return; } - ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4, + ea_list = read_ea_list(talloc_tos(), pdata + 4, total_data - 4); if (!ea_list) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); -- cgit From 3b0422ee01ec69c2cf8a538a3547bf5c3e111992 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Aug 2007 21:46:42 +0000 Subject: r24811: Simple reformatting to fit the 80 columns rule. Jeremy. (This used to be commit 0cdf046dae8ba0741bb7786aa4e85c34fc35dade) --- source3/smbd/filename.c | 159 +++++++++++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 63 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 25ade52947..5f9563b83c 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1,21 +1,21 @@ -/* +/* Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Ying Chen 2000 Copyright (C) Volker Lendecke 2007 - + 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 3 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, see . */ @@ -33,11 +33,12 @@ static BOOL scan_directory(connection_struct *conn, const char *path, Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(const char *name1, const char *name2, - const struct share_params *p) +static BOOL mangled_equal(const char *name1, + const char *name2, + const struct share_params *p) { pstring tmpname; - + pstrcpy(tmpname, name2); mangle_map(tmpname, True, False, p); return strequal(name1, tmpname); @@ -47,7 +48,8 @@ static BOOL mangled_equal(const char *name1, const char *name2, Cope with the differing wildcard and non-wildcard error cases. ****************************************************************************/ -static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_component) +static NTSTATUS determine_path_error(const char *name, + BOOL allow_wcard_last_component) { const char *p; @@ -74,7 +76,7 @@ static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_com return NT_STATUS_OBJECT_PATH_NOT_FOUND; } } - + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -83,8 +85,8 @@ changes etc. We assume that we have already done a chdir() to the right "root" directory for this service. -The function will return an NTSTATUS error if some part of the name except for the last -part cannot be resolved, else NT_STATUS_OK. +The function will return an NTSTATUS error if some part of the name except for +the last part cannot be resolved, else NT_STATUS_OK. Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't get any fatal errors that should immediately terminate the calling @@ -133,7 +135,8 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path)); /* - * Conversion to basic unix format is already done in check_path_syntax(). + * Conversion to basic unix format is already done in + * check_path_syntax(). */ /* @@ -164,7 +167,8 @@ NTSTATUS unix_convert(connection_struct *conn, goto done; } - if (orig_path[0] == '.' && (orig_path[1] == '/' || orig_path[1] == '\0')) { + if (orig_path[0] == '.' && (orig_path[1] == '/' || + orig_path[1] == '\0')) { /* Start of pathname can't be "." only. */ if (orig_path[1] == '\0' || orig_path[2] == '\0') { result = NT_STATUS_OBJECT_NAME_INVALID; @@ -202,7 +206,8 @@ NTSTATUS unix_convert(connection_struct *conn, * the man page. Thanks to jht@samba.org for finding this. JRA. */ - if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { + if (conn->case_sensitive && !conn->case_preserve && + !conn->short_case_preserve) { strnorm(name, lp_defaultcase(SNUM(conn))); } @@ -250,7 +255,8 @@ NTSTATUS unix_convert(connection_struct *conn, goto done; } - DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start)); + DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", + name, dirpath, start)); /* * A special case - if we don't have any mangling chars and are case @@ -286,7 +292,8 @@ NTSTATUS unix_convert(connection_struct *conn, /* * Pinpoint the end of this section of the filename. */ - end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */ + /* mb safe. '/' can't be in any encoded char. */ + end = strchr(start, '/'); /* * Chop the name at this point. @@ -335,20 +342,22 @@ NTSTATUS unix_convert(connection_struct *conn, if (SMB_VFS_STAT(conn,name, &st) == 0) { /* - * It exists. it must either be a directory or this must be - * the last part of the path for it to be OK. + * It exists. it must either be a directory or this must + * be the last part of the path for it to be OK. */ if (end && !(st.st_mode & S_IFDIR)) { /* - * An intermediate part of the name isn't a directory. + * An intermediate part of the name isn't + * a directory. */ DEBUG(5,("Not a dir %s\n",start)); *end = '/'; /* - * We need to return the fact that the intermediate - * name resolution failed. This is used to return an - * error of ERRbadpath rather than ERRbadfile. Some - * Windows applications depend on the difference between + * We need to return the fact that the + * intermediate name resolution failed. This + * is used to return an error of ERRbadpath + * rather than ERRbadfile. Some Windows + * applications depend on the difference between * these two errors. */ result = NT_STATUS_OBJECT_PATH_NOT_FOUND; @@ -357,9 +366,9 @@ NTSTATUS unix_convert(connection_struct *conn, if (!end) { /* - * We just scanned for, and found the end of the path. - * We must return the valid stat struct. - * JRA. + * We just scanned for, and found the end of + * the path. We must return the valid stat + * struct. JRA. */ *pst = st; @@ -371,30 +380,38 @@ NTSTATUS unix_convert(connection_struct *conn, /* Stat failed - ensure we don't use it. */ SET_STAT_INVALID(st); - /* Reset errno so we can detect directory open errors. */ + /* + * Reset errno so we can detect + * directory open errors. + */ errno = 0; /* * Try to find this part of the path in the directory. */ - if (name_has_wildcard || - !scan_directory(conn, dirpath, start, &found_name)) { + if (name_has_wildcard || + !scan_directory(conn, dirpath, + start, &found_name)) { char *unmangled; if (end) { /* - * An intermediate part of the name can't be found. + * An intermediate part of the name + * can't be found. */ - DEBUG(5,("Intermediate not found %s\n",start)); + DEBUG(5,("Intermediate not found %s\n", + start)); *end = '/'; /* - * We need to return the fact that the intermediate - * name resolution failed. This is used to return an - * error of ERRbadpath rather than ERRbadfile. Some - * Windows applications depend on the difference between - * these two errors. + * We need to return the fact that the + * intermediate name resolution failed. + * This is used to return an error of + * ERRbadpath rather than ERRbadfile. + * Some Windows applications depend on + * the difference between these two + * errors. */ /* @@ -406,10 +423,12 @@ NTSTATUS unix_convert(connection_struct *conn, if (errno == ENOENT || errno == ENOTDIR || errno == ELOOP) { - result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = + NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { - result = map_nt_error_from_unix(errno); + result = + map_nt_error_from_unix(errno); } goto fail; } @@ -423,10 +442,12 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (errno == ENOTDIR || errno == ELOOP) { - result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + result = + NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { - result = map_nt_error_from_unix(errno); + result = + map_nt_error_from_unix(errno); } goto fail; } @@ -434,22 +455,26 @@ NTSTATUS unix_convert(connection_struct *conn, /* * Just the last part of the name doesn't exist. * We need to strupper() or strlower() it as - * this conversion may be used for file creation - * purposes. Fix inspired by Thomas Neumann . + * this conversion may be used for file creation + * purposes. Fix inspired by + * Thomas Neumann . */ if (!conn->case_preserve || - (mangle_is_8_3(start, False, conn->params) && + (mangle_is_8_3(start, False, + conn->params) && !conn->short_case_preserve)) { - strnorm(start, lp_defaultcase(SNUM(conn))); + strnorm(start, + lp_defaultcase(SNUM(conn))); } /* - * check on the mangled stack to see if we can recover the - * base of the filename. + * check on the mangled stack to see if we can + * recover the base of the filename. */ if (mangle_is_mangled(start, conn->params) - && mangle_check_cache_alloc(start, &unmangled, + && mangle_check_cache_alloc(start, + &unmangled, conn->params)) { char *tmp; size_t start_ofs = start - name; @@ -478,8 +503,8 @@ NTSTATUS unix_convert(connection_struct *conn, /* - * Restore the rest of the string. If the string was mangled the size - * may have changed. + * Restore the rest of the string. If the string was + * mangled the size may have changed. */ if (end) { char *tmp; @@ -523,9 +548,9 @@ NTSTATUS unix_convert(connection_struct *conn, start = name + start_ofs; /* - * We just scanned for, and found the end of the path. - * We must return a valid stat struct if it exists. - * JRA. + * We just scanned for, and found the end of + * the path. We must return a valid stat struct + * if it exists. JRA. */ if (SMB_VFS_STAT(conn,name, &st) == 0) { @@ -540,13 +565,14 @@ NTSTATUS unix_convert(connection_struct *conn, #ifdef DEVELOPER if (VALID_STAT(st) && - get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, &st))) { + get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, + &st))) { result = NT_STATUS_DELETE_PENDING; goto fail; } #endif - /* + /* * Add to the dirpath that we have resolved so far. */ @@ -574,7 +600,8 @@ NTSTATUS unix_convert(connection_struct *conn, */ if(!component_was_mangled && !name_has_wildcard) { - stat_cache_add(orig_path, dirpath, conn->case_sensitive); + stat_cache_add(orig_path, dirpath, + conn->case_sensitive); } /* @@ -626,8 +653,10 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) { if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ - if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) { - DEBUG(5,("check_name: file path name %s vetoed\n",name)); + if (!((name[0] == '.') && (!name[1] || + (name[1] == '.' && !name[2])))) { + DEBUG(5,("check_name: file path name %s vetoed\n", + name)); return map_nt_error_from_unix(ENOENT); } } @@ -635,7 +664,8 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) { NTSTATUS status = check_reduced_name(conn,name); if (!NT_STATUS_IS_OK(status)) { - DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status))); + DEBUG(5,("check_name: name %s failed with %s\n",name, + nt_errstr(status))); return status; } } @@ -648,7 +678,8 @@ NTSTATUS check_name(connection_struct *conn, const pstring name) This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) +static BOOL fname_equal(const char *name1, const char *name2, + BOOL case_sensitive) { /* Normal filename handling */ if (case_sensitive) @@ -710,14 +741,15 @@ static BOOL scan_directory(connection_struct *conn, const char *path, while ((dname = ReadDirName(cur_dir, &curpos))) { /* Is it dot or dot dot. */ - if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { + if ((dname[0] == '.') && (!dname[1] || + (dname[1] == '.' && !dname[2]))) { continue; } /* * At this point dname is the unmangled name. - * name is either mangled or not, depending on the state of the "mangled" - * variable. JRA. + * name is either mangled or not, depending on the state + * of the "mangled" variable. JRA. */ /* @@ -725,7 +757,8 @@ static BOOL scan_directory(connection_struct *conn, const char *path, * against unmangled name. */ - if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { + if ((mangled && mangled_equal(name,dname,conn->params)) || + fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ *found_name = SMB_STRDUP(dname); SAFE_FREE(unmangled_name); -- cgit From dacdde6e5c047ad9a0e416dcff7afdc5e21fc4ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Aug 2007 23:07:10 +0000 Subject: r24813: Reformat to 80 columns. Jeremy. (This used to be commit c6c8f5a897602d53876fe75e86283d97a394037d) --- source3/smbd/statcache.c | 51 ++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 24cfe3beb8..d2f09930a0 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -1,21 +1,21 @@ -/* +/* Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Andrew Bartlett 2003 Copyright (C) Volker Lendecke 2007 - + 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 3 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, see . */ @@ -33,14 +33,15 @@ static TDB_CONTEXT *tdb_stat_cache; * * @param full_orig_name The original name as specified by the client * @param orig_translated_path The name on our filesystem. - * - * @note Only the first strlen(orig_translated_path) characters are stored + * + * @note Only the first strlen(orig_translated_path) characters are stored * into the cache. This means that full_orig_name will be internally * truncated. * */ -void stat_cache_add( const char *full_orig_name, const char *translated_path, BOOL case_sensitive) +void stat_cache_add( const char *full_orig_name, const char *translated_path, + BOOL case_sensitive) { size_t translated_path_length; TDB_DATA data_val; @@ -111,8 +112,12 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, BO if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %lu and [%s] %lu)!\n", - original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); + DEBUG(0, ("OOPS - tried to store stat cache entry " + "for weird length paths [%s] %lu and [%s] %lu)!\n", + original_path, + (unsigned long)original_path_length, + translated_path, + (unsigned long)translated_path_length)); SAFE_FREE(original_path); return; } @@ -127,15 +132,20 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, BO /* * New entry or replace old entry. */ - + data_val.dsize = translated_path_length + 1; data_val.dptr = (uint8 *)translated_path; - if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { - DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); + if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, + TDB_REPLACE) != 0) { + DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", + original_path, translated_path)); } else { DEBUG(5,("stat_cache_add: Added entry (%lx:size%x) %s -> %s\n", - (unsigned long)data_val.dptr, (unsigned int)data_val.dsize, original_path, translated_path)); + (unsigned long)data_val.dptr, + (unsigned int)data_val.dsize, + original_path, + translated_path)); } SAFE_FREE(original_path); @@ -149,10 +159,12 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, BO * to be correct as far as the cache can tell us. We assume that * it is a malloc'ed string, we free it if necessary. * @param dirpath The path as far as the stat cache told us. - * @param start A pointer into name, for where to 'start' in fixing the rest of the name up. + * @param start A pointer into name, for where to 'start' in fixing the rest + * of the name up. * @param psd A stat buffer, NOT from the cache, but just a side-effect. * - * @return True if we translated (and did a scuccessful stat on) the entire name. + * @return True if we translated (and did a scuccessful stat on) the entire + * name. * */ @@ -170,7 +182,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, if (!lp_stat_cache()) return False; - + name = *pname; namelen = strlen(name); @@ -217,7 +229,8 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, break; } - DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); + DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", + chk_name )); /* * Didn't find it - remove last component for next try. */ @@ -348,7 +361,7 @@ void stat_cache_delete(const char *name) The function returns the bucket index number for the hashed key. JRA. Use a djb-algorithm hash for speed. ***************************************************************/ - + unsigned int fast_string_hash(TDB_DATA *key) { unsigned int n = 0; @@ -374,7 +387,7 @@ BOOL reset_stat_cache( void ) /* Create the in-memory tdb using our custom hash function. */ tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL, - (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); + (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); if (!tdb_stat_cache) return False; -- cgit From ff0947fbed841065fce85c64ff4b2a2e8f24f056 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Sep 2007 10:15:04 +0000 Subject: r24949: Remove some static buffers (This used to be commit df648d47ff3c4e24f439fda839653bda98323100) --- source3/smbd/lanman.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 581ac90aeb..9eb2a283cc 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -116,18 +116,16 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) static char *Expand(connection_struct *conn, int snum, char *s) { - static pstring buf; + pstring buf; if (!s) { return NULL; } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - buf, sizeof(buf)); - return &buf[0]; + return talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)), + conn->user, conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, buf); } /******************************************************************* -- cgit From 132ee3990af5d31573978f5a3abf43db2303880b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2007 20:57:01 +0000 Subject: r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based interface. More development will come on top of this. Remove the "mangled map" parameter. Jeremy. (This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736) --- source3/smbd/dir.c | 36 ++-- source3/smbd/filename.c | 189 ++++++++++------- source3/smbd/mangle.c | 65 +++--- source3/smbd/mangle_hash.c | 201 ++++++++++-------- source3/smbd/mangle_hash2.c | 135 +++++++----- source3/smbd/msdfs.c | 7 +- source3/smbd/nttrans.c | 93 +++++---- source3/smbd/reply.c | 489 ++++++++++++++++++++++++++++---------------- source3/smbd/statcache.c | 128 ++++++------ source3/smbd/trans2.c | 243 +++++++++++++--------- 10 files changed, 947 insertions(+), 639 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index eec8fa12ef..e602008b8f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -380,12 +380,11 @@ static void dptr_close_oldest(BOOL old) wcard must not be zero. ****************************************************************************/ -NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, +NTSTATUS dptr_create(connection_struct *conn, const char *path, BOOL old_handle, BOOL expect_close,uint16 spid, const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret) { struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; - const char *dir2; NTSTATUS status; DEBUG(5,("dptr_create dir=%s\n", path)); @@ -399,17 +398,12 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO return status; } - /* use a const pointer from here on */ - dir2 = path; - if (!*dir2) - dir2 = "."; - - dir_hnd = OpenDir(conn, dir2, wcard, attr); + dir_hnd = OpenDir(conn, path, wcard, attr); if (!dir_hnd) { return map_nt_error_from_unix(errno); } - string_set(&conn->dirpath,dir2); + string_set(&conn->dirpath,path); if (dirhandles_open >= MAX_OPEN_DIRECTORIES) { dptr_idleoldest(); @@ -488,7 +482,7 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ - string_set(&dptr->path,dir2); + string_set(&dptr->path,path); dptr->conn = conn; dptr->dir_hnd = dir_hnd; dptr->spid = spid; @@ -758,10 +752,15 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) return True; } -static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask) +static BOOL mangle_mask_match(connection_struct *conn, const char *filename, + char *mask) { - mangle_map(filename,True,False,conn->params); - return mask_match_search(filename,mask,False); + char mname[13]; + + if (!name_to_8_3(filename,mname,False,conn->params)) { + return False; + } + return mask_match_search(mname,mask,False); } /**************************************************************************** @@ -806,9 +805,14 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { - if (!mangle_is_8_3(filename, False, conn->params)) - mangle_map(filename,True,False, - conn->params); + if (!mangle_is_8_3(filename, False, conn->params)) { + char mname[13]; + if (!name_to_8_3(filename,mname,False, + conn->params)) { + continue; + } + pstrcpy(filename,mname); + } pstrcpy(fname,filename); *path = 0; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5f9563b83c..5871fd143f 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. filename handling routines Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1999-2004 + Copyright (C) Jeremy Allison 1999-2007 Copyright (C) Ying Chen 2000 Copyright (C) Volker Lendecke 2007 @@ -37,11 +37,12 @@ static BOOL mangled_equal(const char *name1, const char *name2, const struct share_params *p) { - pstring tmpname; + char mname[13]; - pstrcpy(tmpname, name2); - mangle_map(tmpname, True, False, p); - return strequal(name1, tmpname); + if (!name_to_8_3(name2, mname, False, p)) { + return False; + } + return strequal(name1, mname); } /**************************************************************************** @@ -107,9 +108,10 @@ for nlinks = 0, which can never be true for any file). ****************************************************************************/ NTSTATUS unix_convert(connection_struct *conn, - pstring orig_path, + const char *orig_path, BOOL allow_wcard_last_component, - char *saved_last_component, + char **pp_conv_path, + char **pp_saved_last_component, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; @@ -119,16 +121,20 @@ NTSTATUS unix_convert(connection_struct *conn, BOOL component_was_mangled = False; BOOL name_has_wildcard = False; NTSTATUS result; + TALLOC_CTX *ctx = talloc_tos(); SET_STAT_INVALID(*pst); - - if(saved_last_component) { - *saved_last_component = 0; + *pp_conv_path = NULL; + if(pp_saved_last_component) { + *pp_saved_last_component = NULL; } if (conn->printer) { /* we don't ever use the filenames on a printer share as a filename - so don't convert them */ + if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) { + return NT_STATUS_NO_MEMORY; + } return NT_STATUS_OK; } @@ -157,11 +163,13 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (!*orig_path) { - if (!(name = SMB_STRDUP("."))) { + if (!(name = talloc_strdup(ctx,"."))) { return NT_STATUS_NO_MEMORY; } if (SMB_VFS_STAT(conn,name,&st) == 0) { *pst = st; + } else { + return map_nt_error_from_unix(errno); } DEBUG(5,("conversion finished \"\" -> %s\n",name)); goto done; @@ -183,17 +191,18 @@ NTSTATUS unix_convert(connection_struct *conn, * Ensure saved_last_component is valid even if file exists. */ - if(saved_last_component) { + if(pp_saved_last_component) { end = strrchr_m(orig_path, '/'); if (end) { - pstrcpy(saved_last_component, end + 1); + *pp_saved_last_component = talloc_strdup(ctx, end + 1); } else { - pstrcpy(saved_last_component, orig_path); + *pp_saved_last_component = talloc_strdup(ctx, + orig_path); } } - if (!(name = SMB_STRDUP(orig_path))) { - DEBUG(0, ("strdup failed\n")); + if (!(name = talloc_strdup(ctx, orig_path))) { + DEBUG(0, ("talloc_strdup failed\n")); return NT_STATUS_NO_MEMORY; } @@ -224,9 +233,9 @@ NTSTATUS unix_convert(connection_struct *conn, * building the directories with asprintf and free it. */ - if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) { - DEBUG(0, ("strdup failed\n")); - SAFE_FREE(name); + if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) { + DEBUG(0, ("talloc_strdup failed\n")); + TALLOC_FREE(name); return NT_STATUS_NO_MEMORY; } @@ -264,8 +273,7 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (conn->case_sensitive && - !mangle_is_mangled(name, conn->params) && - !*lp_mangled_map(conn->params)) { + !mangle_is_mangled(name, conn->params)) { goto done; } @@ -302,8 +310,14 @@ NTSTATUS unix_convert(connection_struct *conn, *end = 0; } - if (saved_last_component != 0) { - pstrcpy(saved_last_component, end ? end + 1 : start); + if (pp_saved_last_component) { + TALLOC_FREE(*pp_saved_last_component); + *pp_saved_last_component = talloc_strdup(ctx, + end ? end + 1 : start); + if (!*pp_saved_last_component) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } } /* The name cannot have a component of "." */ @@ -473,25 +487,27 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (mangle_is_mangled(start, conn->params) - && mangle_check_cache_alloc(start, - &unmangled, - conn->params)) { + && mangle_lookup_name_from_8_3(ctx, + start, + &unmangled, + conn->params)) { char *tmp; size_t start_ofs = start - name; if (*dirpath != '\0') { - asprintf(&tmp, "%s/%s", dirpath, - unmangled); - SAFE_FREE(unmangled); + tmp = talloc_asprintf(ctx, + "%s/%s", dirpath, + unmangled); + TALLOC_FREE(unmangled); } else { tmp = unmangled; } if (tmp == NULL) { - DEBUG(0, ("malloc failed\n")); - result = NT_STATUS_NO_MEMORY; + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; } - SAFE_FREE(name); + TALLOC_FREE(name); name = tmp; start = name + start_ofs; end = start + strlen(start); @@ -511,18 +527,20 @@ NTSTATUS unix_convert(connection_struct *conn, size_t start_ofs = start - name; if (*dirpath != '\0') { - asprintf(&tmp, "%s/%s/%s", dirpath, - found_name, end+1); + tmp = talloc_asprintf(ctx, + "%s/%s/%s", dirpath, + found_name, end+1); } else { - asprintf(&tmp, "%s/%s", found_name, - end+1); + tmp = talloc_asprintf(ctx, + "%s/%s", found_name, + end+1); } if (tmp == NULL) { - DEBUG(0, ("asprintf failed\n")); - result = NT_STATUS_NO_MEMORY; + DEBUG(0, ("talloc_asprintf failed\n")); + return NT_STATUS_NO_MEMORY; } - SAFE_FREE(name); + TALLOC_FREE(name); name = tmp; start = name + start_ofs; end = start + strlen(found_name); @@ -532,18 +550,19 @@ NTSTATUS unix_convert(connection_struct *conn, size_t start_ofs = start - name; if (*dirpath != '\0') { - asprintf(&tmp, "%s/%s", dirpath, - found_name); + tmp = talloc_asprintf(ctx, + "%s/%s", dirpath, + found_name); } else { - tmp = SMB_STRDUP(found_name); + tmp = talloc_strdup(ctx, + found_name); } if (tmp == NULL) { - DEBUG(0, ("malloc failed\n")); - result = NT_STATUS_NO_MEMORY; - goto fail; + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; } - SAFE_FREE(name); + TALLOC_FREE(name); name = tmp; start = name + start_ofs; @@ -560,7 +579,7 @@ NTSTATUS unix_convert(connection_struct *conn, } } - SAFE_FREE(found_name); + TALLOC_FREE(found_name); } /* end else */ #ifdef DEVELOPER @@ -577,19 +596,19 @@ NTSTATUS unix_convert(connection_struct *conn, */ if (*dirpath != '\0') { - char *tmp; - - if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) { - DEBUG(0, ("asprintf failed\n")); + char *tmp = talloc_asprintf(ctx, + "%s/%s", dirpath, start); + if (!tmp) { + DEBUG(0, ("talloc_asprintf failed\n")); return NT_STATUS_NO_MEMORY; } - SAFE_FREE(dirpath); + TALLOC_FREE(dirpath); dirpath = tmp; } else { - SAFE_FREE(dirpath); - if (!(dirpath = SMB_STRDUP(start))) { - DEBUG(0, ("strdup failed\n")); + TALLOC_FREE(dirpath); + if (!(dirpath = talloc_strdup(ctx,start))) { + DEBUG(0, ("talloc_strdup failed\n")); return NT_STATUS_NO_MEMORY; } } @@ -628,17 +647,23 @@ NTSTATUS unix_convert(connection_struct *conn, DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); done: - pstrcpy(orig_path, name); - SAFE_FREE(name); - SAFE_FREE(dirpath); + *pp_conv_path = name; + TALLOC_FREE(dirpath); return NT_STATUS_OK; fail: DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start)); - pstrcpy(orig_path, dirpath); - pstrcat(orig_path, "/"); - pstrcat(orig_path, start); - SAFE_FREE(name); - SAFE_FREE(dirpath); + if (*dirpath != '\0') { + *pp_conv_path = talloc_asprintf(ctx, + "%s/%s", dirpath, start); + } else { + *pp_conv_path = talloc_strdup(ctx, start); + } + if (!*pp_conv_path) { + DEBUG(0, ("talloc_asprintf failed\n")); + return NT_STATUS_NO_MEMORY; + } + TALLOC_FREE(name); + TALLOC_FREE(dirpath); return result; } @@ -649,7 +674,7 @@ NTSTATUS unix_convert(connection_struct *conn, a valid one for the user to access. ****************************************************************************/ -NTSTATUS check_name(connection_struct *conn, const pstring name) +NTSTATUS check_name(connection_struct *conn, const char *name) { if (IS_VETO_PATH(conn, name)) { /* Is it not dot or dot dot. */ @@ -682,8 +707,9 @@ static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive) { /* Normal filename handling */ - if (case_sensitive) + if (case_sensitive) { return(strcmp(name1,name2) == 0); + } return(strequal(name1,name2)); } @@ -701,17 +727,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path, BOOL mangled; char *unmangled_name = NULL; long curpos; + TALLOC_CTX *ctx = talloc_tos(); mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ - if ((path == NULL) || (*path == 0)) + if ((path == NULL) || (*path == 0)) { path = "."; + } /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) - * read from the directory and then mangled by the mangle_map() + * read from the directory and then mangled by the name_to_8_3() * call. We need to mangle both names or neither. * (JRA). * @@ -724,15 +752,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path, */ if (mangled && !conn->case_sensitive) { - mangled = !mangle_check_cache_alloc(name, &unmangled_name, - conn->params); - name = unmangled_name; + mangled = !mangle_lookup_name_from_8_3(ctx, + name, + &unmangled_name, + conn->params); + if (mangled) { + name = unmangled_name; + } } /* open the directory */ if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); - SAFE_FREE(unmangled_name); + TALLOC_FREE(unmangled_name); return(False); } @@ -741,8 +773,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, while ((dname = ReadDirName(cur_dir, &curpos))) { /* Is it dot or dot dot. */ - if ((dname[0] == '.') && (!dname[1] || - (dname[1] == '.' && !dname[2]))) { + if (ISDOT(dname) || ISDOTDOT(dname)) { continue; } @@ -760,15 +791,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path, if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ - *found_name = SMB_STRDUP(dname); - SAFE_FREE(unmangled_name); + *found_name = talloc_strdup(ctx,dname); + TALLOC_FREE(unmangled_name); CloseDir(cur_dir); + if (!*found_name) { + errno = ENOMEM; + return False; + } return(True); } } - SAFE_FREE(unmangled_name); + TALLOC_FREE(unmangled_name); CloseDir(cur_dir); errno = ENOENT; - return(False); + return False; } diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index fce86903f2..61490c444e 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -1,18 +1,18 @@ -/* +/* Unix SMB/CIFS implementation. Name mangling interface Copyright (C) Andrew Tridgell 2002 - + 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 3 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, see . */ @@ -100,50 +100,51 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, return mangle_fns->is_8_3(fname, check_case, True, p); } +BOOL mangle_must_mangle(const char *fname, + const struct share_params *p) +{ + if (!lp_manglednames(p)) { + return False; + } + return mangle_fns->must_mangle(fname, p); +} + /* - try to reverse map a 8.3 name to the original filename. This doesn't have to + try to reverse map a 8.3 name to the original filename. This doesn't have to always succeed, as the directory handling code in smbd will scan the directory looking for a matching name if it doesn't. It should succeed most of the time or there will be a huge performance penalty */ -BOOL mangle_check_cache(char *s, size_t maxlen, +BOOL mangle_lookup_name_from_8_3(TALLOC_CTX *ctx, + const char *in, + char **out, /* talloced on the given context. */ const struct share_params *p) { - return mangle_fns->check_cache(s, maxlen, p); -} - -BOOL mangle_check_cache_alloc(const char *name, char **presult, - const struct share_params *p) -{ - pstring tmp; - char *result; - pstrcpy(tmp, name); - - if (!mangle_check_cache(tmp, sizeof(pstring)-1, p) - || !(result = SMB_STRDUP(tmp))) { - return False; - } - *presult = result; - return True; + return mangle_fns->lookup_name_from_8_3(ctx, in, out, p); } -/* - map a long filename to a 8.3 name. +/* + mangle a long filename to a 8.3 name. + Return True if we did mangle the name (ie. out is filled in). + False on error. + JRA. */ -void mangle_map(pstring OutName, BOOL need83, BOOL cache83, +BOOL name_to_8_3(const char *in, + char out[13], + BOOL cache83, const struct share_params *p) { /* name mangling can be disabled for speed, in which case we just truncate the string */ if (!lp_manglednames(p)) { - if (need83) { - string_truncate(OutName, 12); - } - return; + safe_strcpy(out,in,12); + return True; } - /* invoke the inane "mangled map" code */ - mangle_map_filename(OutName, p); - mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p); + return mangle_fns->name_to_8_3(in, + out, + cache83, + lp_defaultcase(p->service), + p); } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 4c02d9685f..d63a980cfb 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -1,20 +1,21 @@ -/* +/* Unix SMB/CIFS implementation. Name mangling Copyright (C) Andrew Tridgell 1992-2002 Copyright (C) Simo Sorce 2001 Copyright (C) Andrew Bartlett 2002 - + Copyright (C) Jeremy Allison 2007 + 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 3 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, see . */ @@ -244,14 +245,14 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards) if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL; - + if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) return NT_STATUS_OK; /* Name cannot start with '.' */ if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL; - + if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards, True))) goto done; @@ -293,7 +294,7 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, if (strlen(f) > 12) return False; - + size = push_ucs2_allocate(&ucs2name, f); if (size == (size_t)-1) { DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n")); @@ -305,15 +306,13 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, done: SAFE_FREE(ucs2name); - if (!NT_STATUS_IS_OK(ret)) { + if (!NT_STATUS_IS_OK(ret)) { return False; } - + return True; } - - /* -------------------------------------------------------------------------- ** * Functions... */ @@ -330,10 +329,11 @@ done: * * ************************************************************************** ** */ + static void init_chartest( void ) { const unsigned char *s; - + memset( (char *)chartest, '\0', 256 ); for( s = (const unsigned char *)basechars; *s; s++ ) { @@ -360,6 +360,7 @@ static void init_chartest( void ) * * ************************************************************************** ** */ + static BOOL is_mangled(const char *s, const struct share_params *p) { char *magic; @@ -406,7 +407,8 @@ static void mangle_reset( void ) crh 07-Apr-1998 **************************************************************************/ -static void cache_mangled_name( const char mangled_name[13], char *raw_name ) +static void cache_mangled_name( const char mangled_name[13], + const char *raw_name ) { TDB_DATA data_val; char mangled_name_key[13]; @@ -459,30 +461,37 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) * ************************************************************************** ** */ -static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p ) +static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, + const char *in, + char **out, /* talloced on the given context. */ + const struct share_params *p) { TDB_DATA data_val; - char *ext_start = NULL; char *saved_ext = NULL; + char *s = talloc_strdup(ctx, in); magic_char = lp_magicchar(p); /* If the cache isn't initialized, give up. */ - if( !tdb_mangled_cache ) - return( False ); + if(!s || !tdb_mangled_cache ) { + TALLOC_FREE(s); + return False; + } data_val = tdb_fetch_bystring(tdb_mangled_cache, s); /* If we didn't find the name *with* the extension, try without. */ if(data_val.dptr == NULL || data_val.dsize == 0) { - ext_start = strrchr( s, '.' ); + char *ext_start = strrchr( s, '.' ); if( ext_start ) { - if((saved_ext = SMB_STRDUP(ext_start)) == NULL) + if((saved_ext = talloc_strdup(ctx,ext_start)) == NULL) { + TALLOC_FREE(s); return False; + } *ext_start = '\0'; data_val = tdb_fetch_bystring(tdb_mangled_cache, s); - /* + /* * At this point s is the name without the * extension. We re-add the extension if saved_ext * is not null, before freeing saved_ext. @@ -492,31 +501,32 @@ static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p ) /* Okay, if we haven't found it we're done. */ if(data_val.dptr == NULL || data_val.dsize == 0) { - if(saved_ext) { - /* Replace the saved_ext as it was truncated. */ - (void)safe_strcat( s, saved_ext, maxlen ); - SAFE_FREE(saved_ext); - } - return( False ); + TALLOC_FREE(saved_ext); + TALLOC_FREE(s); + return False; } - /* If we *did* find it, we need to copy it into the string buffer. */ - (void)safe_strcpy( s, (const char *)data_val.dptr, maxlen ); - if( saved_ext ) { - /* Replace the saved_ext as it was truncated. */ - (void)safe_strcat( s, saved_ext, maxlen ); - SAFE_FREE(saved_ext); + /* If we *did* find it, we need to talloc it on the given ctx. */ + if (saved_ext) { + *out = talloc_asprintf(ctx, "%s%s", + (char *)data_val.dptr, + saved_ext); + } else { + *out = talloc_strdup(ctx, (char *)data_val.dptr); } + + TALLOC_FREE(s); + TALLOC_FREE(saved_ext); SAFE_FREE(data_val.dptr); - return( True ); + + return *out ? True : False; } /***************************************************************************** - * do the actual mangling to 8.3 format - * the buffer must be able to hold 13 characters (including the null) - ***************************************************************************** - */ -static void to_8_3(char *s, int default_case) + Do the actual mangling to 8.3 format. +*****************************************************************************/ + +static BOOL to_8_3(const char *in, char out[13], int default_case) { int csum; char *p; @@ -524,11 +534,16 @@ static void to_8_3(char *s, int default_case) char base[9]; int baselen = 0; int extlen = 0; + char *s = SMB_STRDUP(in); extension[0] = 0; base[0] = 0; - p = strrchr(s,'.'); + if (!s) { + return False; + } + + p = strrchr(s,'.'); if( p && (strlen(p+1) < (size_t)4) ) { BOOL all_normal = ( strisnormal(p+1, default_case) ); /* XXXXXXXXX */ @@ -557,7 +572,7 @@ static void to_8_3(char *s, int default_case) extension[extlen] = 0; } } - + p = s; while( *p && baselen < 5 ) { @@ -567,79 +582,88 @@ static void to_8_3(char *s, int default_case) p++; } base[baselen] = 0; - + csum = csum % (MANGLE_BASE*MANGLE_BASE); - - (void)slprintf(s, 12, "%s%c%c%c", - base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) ); - + + memcpy(out, base, baselen); + out[baselen] = magic_char; + out[baselen+1] = mangle( csum/MANGLE_BASE ); + out[baselen+2] = mangle( csum ); + if( *extension ) { - (void)pstrcat( s, "." ); - (void)pstrcat( s, extension ); + out[baselen+3] = '.'; + safe_strcpy(&out[baselen+4], extension, 3); + } + + SAFE_FREE(s); + return True; +} + +static BOOL must_mangle(const char *name, + const struct share_params *p) +{ + smb_ucs2_t *name_ucs2 = NULL; + NTSTATUS status; + magic_char = lp_magicchar(p); + + if (push_ucs2_allocate(&name_ucs2, name) == (size_t)-1) { + DEBUG(0, ("push_ucs2_allocate failed!\n")); + return False; } + status = is_valid_name(name_ucs2, False, False); + SAFE_FREE(name_ucs2); + return NT_STATUS_IS_OK(status); } /***************************************************************************** * Convert a filename to DOS format. Return True if successful. + * Input: in Incoming name. * - * Input: OutName - Source *and* destination buffer. + * out 8.3 DOS name. * - * NOTE that OutName must point to a memory space that - * is at least 13 bytes in size! - * - * need83 - If False, name mangling will be skipped unless the - * name contains illegal characters. Mapping will still - * be done, if appropriate. This is probably used to - * signal that a client does not require name mangling, - * thus skipping the name mangling even on shares which - * have name-mangling turned on. * cache83 - If False, the mangled name cache will not be updated. * This is usually used to prevent that we overwrite * a conflicting cache entry prematurely, i.e. before * we know whether the client is really interested in the * current name. (See PR#13758). UKD. * - * Output: Returns False only if the name wanted mangling but the share does - * not have name mangling turned on. - * * **************************************************************************** */ -static void name_map(char *OutName, BOOL need83, BOOL cache83, - int default_case, const struct share_params *p) +static BOOL hash_name_to_8_3(const char *in, + char out[13], + BOOL cache83, + int default_case, + const struct share_params *p) { - smb_ucs2_t *OutName_ucs2; + smb_ucs2_t *in_ucs2 = NULL; magic_char = lp_magicchar(p); - DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, - need83 ? "True" : "False", cache83 ? "True" : "False")); - - if (push_ucs2_allocate(&OutName_ucs2, OutName) == (size_t)-1) { + DEBUG(5,("hash_name_to_8_3( %s, cache83 = %s)\n", in, + cache83 ? "True" : "False")); + + if (push_ucs2_allocate(&in_ucs2, in) == (size_t)-1) { DEBUG(0, ("push_ucs2_allocate failed!\n")); - return; + return False; } - if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False, False))) - need83 = True; - - /* check if it's already in 8.3 format */ - if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2, False))) { - char *tmp = NULL; - - /* mangle it into 8.3 */ - if (cache83) - tmp = SMB_STRDUP(OutName); - - to_8_3(OutName, default_case); + /* If it's already 8.3, just copy. */ + if (NT_STATUS_IS_OK(is_valid_name(in_ucs2, False, False)) && + NT_STATUS_IS_OK(is_8_3_w(in_ucs2, False))) { + SAFE_FREE(in_ucs2); + safe_strcpy(out, in, 12); + return True; + } - if(tmp != NULL) { - cache_mangled_name(OutName, tmp); - SAFE_FREE(tmp); - } + SAFE_FREE(in_ucs2); + if (!to_8_3(in, out, default_case)) { + return False; } - DEBUG(5,("name_map() ==> [%s]\n", OutName)); - SAFE_FREE(OutName_ucs2); + cache_mangled_name(out, in); + + DEBUG(5,("hash_name_to_8_3(%s) ==> [%s]\n", in, out)); + return True; } /* @@ -649,9 +673,10 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83, static struct mangle_fns mangle_fns = { mangle_reset, is_mangled, + must_mangle, is_8_3, - check_cache, - name_map + lookup_name_from_8_3, + hash_name_to_8_3 }; /* return the methods for this mangling implementation */ diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index c3db112051..73f81fe9ae 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -368,18 +368,23 @@ static void mangle_reset(void) /* try to find a 8.3 name in the cache, and if found then - replace the string with the original long name. + replace the string with the original long name. */ -static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) +static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, + const char *name, + char **pp_out, /* talloced on the given context. */ + const struct share_params *p) { unsigned int hash, multiplier; unsigned int i; const char *prefix; char extension[4]; + *pp_out = NULL; + /* make sure that this is a mangled name from this cache */ if (!is_mangled(name, p)) { - M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); + M_DEBUG(10,("lookup_name_from_8_3: %s -> not mangled\n", name)); return False; } @@ -394,7 +399,8 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) /* now look in the prefix cache for that hash */ prefix = cache_lookup(hash); if (!prefix) { - M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash)); + M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n", + name, hash)); return False; } @@ -407,17 +413,22 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) } if (extension[0]) { - M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); - slprintf(name, maxlen, "%s.%s", prefix, extension); + M_DEBUG(10,("lookup_name_from_8_3: %s -> %s.%s\n", + name, prefix, extension)); + *pp_out = talloc_asprintf(ctx, "%s.%s", prefix, extension); } else { - M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); - safe_strcpy(name, prefix, maxlen); + M_DEBUG(10,("lookup_name_from_8_3: %s -> %s\n", name, prefix)); + *pp_out = talloc_strdup(ctx, prefix); + } + + if (!pp_out) { + M_DEBUG(0,("talloc_fail")); + return False; } return True; } - /* look for a DOS reserved name */ @@ -499,18 +510,27 @@ static BOOL is_legal_name(const char *name) return True; } +static BOOL must_mangle(const char *name, + const struct share_params *p) +{ + if (is_reserved_name(name)) { + return True; + } + return !is_legal_name(name); +} + /* the main forward mapping function, which converts a long filename to a 8.3 name - if need83 is not set then we only do the mangling if the name is illegal - as a long name - if cache83 is not set then we don't cache the result - the name parameter must be able to hold 13 bytes */ -static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) +static BOOL hash2_name_to_8_3(const char *name, + char new_name[13], + BOOL cache83, + int default_case, + const struct share_params *p) { char *dot_p; char lead_chars[7]; @@ -518,20 +538,14 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, unsigned int extension_length, i; unsigned int prefix_len; unsigned int hash, v; - char new_name[13]; /* reserved names are handled specially */ if (!is_reserved_name(name)) { - /* if the name is already a valid 8.3 name then we don't need to - do anything */ - if (is_8_3(name, False, False, p)) { - return; - } - - /* if the caller doesn't strictly need 8.3 then just check for illegal - filenames */ - if (!need83 && is_legal_name(name)) { - return; + /* if the name is already a valid 8.3 name then we don't need to + * change anything */ + if (is_legal_name(name) && is_8_3(name, False, False, p)) { + safe_strcpy(new_name, name, 12); + return True; } } @@ -548,7 +562,9 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, break; } } - if (i == 0 || i == 4) dot_p = NULL; + if (i == 0 || i == 4) { + dot_p = NULL; + } } /* the leading characters in the mangled name is taken from @@ -580,11 +596,12 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; if (FLAG_CHECK(c, FLAG_ASCII)) { - extension[extension_length++] = toupper_ascii(c); + extension[extension_length++] = + toupper_ascii(c); } } } - + /* find the hash for this prefix */ v = hash = mangle_hash(name, prefix_len); @@ -593,7 +610,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, new_name[i] = lead_chars[i]; } new_name[7] = base_forward(v % 36); - new_name[6] = '~'; + new_name[6] = '~'; for (i=5; i>=mangle_prefix; i--) { v = v / 36; new_name[i] = base_forward(v % 36); @@ -613,22 +630,18 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, cache_insert(name, prefix_len, hash); } - M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", + M_DEBUG(10,("hash2_name_to_8_3: %s -> %08X -> %s (cache=%d)\n", name, hash, new_name, cache83)); - /* and overwrite the old name */ - fstrcpy(name, new_name); - - /* all done, we've managed to mangle it */ + return True; } - -/* initialise the flags table +/* initialise the flags table we allow only a very restricted set of characters as 'ascii' in this mangling backend. This isn't a significant problem as modern clients use the 'long' filenames anyway, and those don't have these - restrictions. + restrictions. */ static void init_tables(void) { @@ -642,8 +655,8 @@ static void init_tables(void) char_flags[i] |= FLAG_ILLEGAL; } - if ((i >= '0' && i <= '9') || - (i >= 'a' && i <= 'z') || + if ((i >= '0' && i <= '9') || + (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) { char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); } @@ -663,7 +676,7 @@ static void init_tables(void) memset(base_reverse, 0, sizeof(base_reverse)); for (i=0;i<36;i++) { base_reverse[(unsigned char)base_forward(i)] = i; - } + } /* fill in the reserved names flags. These are used as a very fast filter for finding possible DOS reserved filenames */ @@ -694,9 +707,10 @@ static void init_tables(void) static struct mangle_fns mangle_fns = { mangle_reset, is_mangled, + must_mangle, is_8_3, - check_cache, - name_map + lookup_name_from_8_3, + hash2_name_to_8_3 }; /* return the methods for this mangling implementation */ @@ -729,30 +743,45 @@ static BOOL posix_is_mangled(const char *s, const struct share_params *p) return False; } -static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) +static BOOL posix_must_mangle(const char *s, const struct share_params *p) { return False; } -static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p ) +static BOOL posix_is_8_3(const char *fname, + BOOL check_case, + BOOL allow_wildcards, + const struct share_params *p) { return False; } -static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) +static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx, + const char *in, + char **out, /* talloced on the given context. */ + const struct share_params *p) { - if (need83) { - memset(OutName, '\0', 13); - } + return False; +} + +static BOOL posix_name_to_8_3(const char *in, + char out[13], + BOOL cache83, + int default_case, + const struct share_params *p) +{ + memset(out, '\0', 13); + return True; } /* POSIX paths backend - no mangle. */ static struct mangle_fns posix_mangle_fns = { - posix_mangle_reset, - posix_is_mangled, - posix_is_8_3, - posix_check_cache, - posix_name_map + posix_mangle_reset, + posix_is_mangled, + posix_must_mangle, + posix_is_8_3, + posix_lookup_name_from_8_3, + posix_name_to_8_3 }; struct mangle_fns *posix_mangle_init(void) diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 16f3cd4370..10652874c5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -369,7 +369,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, char *q = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; - pstring localpath; + pstring localpath_in; + char *localpath = NULL; pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */ DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n", @@ -387,8 +388,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, * think this is needed. JRA. */ - pstrcpy(localpath, pdp->reqpath); - status = unix_convert(conn, localpath, search_flag, NULL, &sbuf); + pstrcpy(localpath_in, pdp->reqpath); + status = unix_convert(conn, localpath_in, search_flag, &localpath, NULL, &sbuf); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { return status; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b5af173d45..735c147b8d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -489,7 +489,8 @@ static void reply_ntcreate_and_X_quota(connection_struct *conn, void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) { - pstring fname; + pstring fname_in; + char *fname = NULL; uint32 flags; uint32 access_mask; uint32 file_attributes; @@ -589,8 +590,8 @@ void reply_ntcreate_and_X(connection_struct *conn, if(!dir_fsp->is_directory) { - srvstr_get_path((char *)req->inbuf, req->flags2, fname, - smb_buf(req->inbuf), sizeof(fname), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, + smb_buf(req->inbuf), sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -602,7 +603,7 @@ void reply_ntcreate_and_X(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname)) { + if( is_ntfs_stream_name(fname_in)) { reply_nterror( req, NT_STATUS_OBJECT_PATH_NOT_FOUND); END_PROFILE(SMBntcreateX); @@ -625,15 +626,15 @@ void reply_ntcreate_and_X(connection_struct *conn, * Copy in the base directory name. */ - pstrcpy( fname, dir_fsp->fsp_name ); - dir_name_len = strlen(fname); + pstrcpy( fname_in, dir_fsp->fsp_name ); + dir_name_len = strlen(fname_in); /* * Ensure it ends in a '\'. */ - if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { - pstrcat(fname, "/"); + if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) { + pstrcat(fname_in, "/"); dir_name_len++; } @@ -645,10 +646,10 @@ void reply_ntcreate_and_X(connection_struct *conn, END_PROFILE(SMBntcreateX); return; } - pstrcat(fname, rel_fname); + pstrcat(fname_in, rel_fname); } else { - srvstr_get_path((char *)req->inbuf, req->flags2, fname, - smb_buf(req->inbuf), sizeof(fname), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, + smb_buf(req->inbuf), sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -660,8 +661,8 @@ void reply_ntcreate_and_X(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname)) { - enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname); + if( is_ntfs_stream_name(fname_in)) { + enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname_in); if (fake_file_type!=FAKE_FILE_TYPE_NONE) { /* * Here we go! support for changing the disk quotas --metze @@ -673,7 +674,7 @@ void reply_ntcreate_and_X(connection_struct *conn, * xp also tries a QUERY_FILE_INFO on the file and then close it */ reply_ntcreate_and_X_quota(conn, req, - fake_file_type, fname); + fake_file_type, fname_in); } else { reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); } @@ -686,7 +687,7 @@ void reply_ntcreate_and_X(connection_struct *conn, * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -707,17 +708,17 @@ void reply_ntcreate_and_X(connection_struct *conn, /* * Ordinary file or directory. */ - + /* * Check if POSIX semantics are wanted. */ - + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { case_state = set_posix_case_semantics(NULL, conn); file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - - status = unix_convert(conn, fname, False, NULL, &sbuf); + + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); reply_nterror(req, status); @@ -1200,7 +1201,7 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, } offset += next_offset; } - + return ea_list_head; } @@ -1215,7 +1216,8 @@ static void call_nt_transact_create(connection_struct *conn, char **ppdata, uint32 data_count, uint32 max_data_count) { - pstring fname; + pstring fname_in; + char *fname = NULL; char *params = *ppparams; char *data = *ppdata; /* Breakout the oplock request bits so we can set the reply bits separately. */ @@ -1334,8 +1336,8 @@ static void call_nt_transact_create(connection_struct *conn, } if(!dir_fsp->is_directory) { - srvstr_get_path(params, req->flags2, fname, - params+53, sizeof(fname), + srvstr_get_path(params, req->flags2, fname_in, + params+53, sizeof(fname_in), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -1347,7 +1349,7 @@ static void call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname)) { + if( is_ntfs_stream_name(fname_in)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); return; @@ -1361,15 +1363,15 @@ static void call_nt_transact_create(connection_struct *conn, * Copy in the base directory name. */ - pstrcpy( fname, dir_fsp->fsp_name ); - dir_name_len = strlen(fname); + pstrcpy( fname_in, dir_fsp->fsp_name ); + dir_name_len = strlen(fname_in); /* * Ensure it ends in a '\'. */ - if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { - pstrcat(fname, "/"); + if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) { + pstrcat(fname_in, "/"); dir_name_len++; } @@ -1383,11 +1385,11 @@ static void call_nt_transact_create(connection_struct *conn, reply_nterror(req, status); return; } - pstrcat(fname, tmpname); + pstrcat(fname_in, tmpname); } } else { - srvstr_get_path(params, req->flags2, fname, params+53, - sizeof(fname), parameter_count-53, + srvstr_get_path(params, req->flags2, fname_in, params+53, + sizeof(fname_in), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1398,7 +1400,7 @@ static void call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname)) { + if( is_ntfs_stream_name(fname_in)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); return; } @@ -1412,7 +1414,7 @@ static void call_nt_transact_create(connection_struct *conn, /* * Ordinary file or directory. */ - + /* * Check if POSIX semantics are wanted. */ @@ -1421,9 +1423,9 @@ static void call_nt_transact_create(connection_struct *conn, case_state = set_posix_case_semantics(NULL, conn); file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1435,7 +1437,7 @@ static void call_nt_transact_create(connection_struct *conn, return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); reply_nterror(req, status); @@ -1776,11 +1778,15 @@ void reply_ntcancel(connection_struct *conn, struct smb_request *req) static NTSTATUS copy_internals(connection_struct *conn, struct smb_request *req, - char *oldname, char *newname, uint32 attrs) + const char *oldname_in, + const char *newname_in, + uint32 attrs) { SMB_STRUCT_STAT sbuf1, sbuf2; - pstring last_component_oldname; - pstring last_component_newname; + char *oldname = NULL; + char *newname = NULL; + char *last_component_oldname = NULL; + char *last_component_newname = NULL; files_struct *fsp1,*fsp2; uint32 fattr; int info; @@ -1794,7 +1800,8 @@ static NTSTATUS copy_internals(connection_struct *conn, return NT_STATUS_MEDIA_WRITE_PROTECTED; } - status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1); + status = unix_convert(conn, oldname_in, False, &oldname, + &last_component_oldname, &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1814,7 +1821,8 @@ static NTSTATUS copy_internals(connection_struct *conn, return NT_STATUS_NO_SUCH_FILE; } - status = unix_convert(conn, newname, False, last_component_newname, &sbuf2); + status = unix_convert(conn, newname_in, False, &newname, + &last_component_newname, &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1840,7 +1848,8 @@ static NTSTATUS copy_internals(connection_struct *conn, return status; } - DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); + DEBUG(10,("copy_internals: doing file copy %s to %s\n", + oldname, newname)); status = open_file_ntcreate(conn, req, oldname, &sbuf1, FILE_READ_DATA, /* Read-only. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2694176ca7..dec0e26c41 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -285,11 +285,10 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, } /**************************************************************************** - Check if we have a correct fsp pointing to a file. Replacement for the - CHECK_FSP macro. + Check if we have a correct fsp pointing to a file. Basic check for open fsp. ****************************************************************************/ -BOOL check_fsp(connection_struct *conn, struct smb_request *req, +BOOL check_fsp_open(connection_struct *conn, struct smb_request *req, files_struct *fsp, struct current_user *user) { if (!(fsp) || !(conn)) { @@ -300,6 +299,20 @@ BOOL check_fsp(connection_struct *conn, struct smb_request *req, reply_nterror(req, NT_STATUS_INVALID_HANDLE); return False; } + return True; +} + +/**************************************************************************** + Check if we have a correct fsp pointing to a file. Replacement for the + CHECK_FSP macro. +****************************************************************************/ + +BOOL check_fsp(connection_struct *conn, struct smb_request *req, + files_struct *fsp, struct current_user *user) +{ + if (!check_fsp_open(conn, req, fsp, user)) { + return False; + } if ((fsp)->is_directory) { reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST); return False; @@ -755,7 +768,9 @@ void reply_ioctl(connection_struct *conn, struct smb_request *req) SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */ SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */ SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */ - p = smb_buf(req->outbuf) + 1; /* Allow for alignment */ + p = smb_buf(req->outbuf); + memset(p, '\0', replysize+1); /* valgrind-safe. */ + p += 1; /* Allow for alignment */ switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: @@ -775,8 +790,7 @@ void reply_ioctl(connection_struct *conn, struct smb_request *req) srvstr_push((char *)req->outbuf, req->flags2, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); - } - else { + } else { memset(p+18, 0, 13); } break; @@ -809,14 +823,15 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status) void reply_checkpath(connection_struct *conn, struct smb_request *req) { - pstring name; + pstring name_in; + char *name = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBcheckpath); - srvstr_get_path((char *)req->inbuf, req->flags2, name, - smb_buf(req->inbuf) + 1, sizeof(name), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, name_in, + smb_buf(req->inbuf) + 1, sizeof(name_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { status = map_checkpath_error((char *)req->inbuf, status); @@ -825,7 +840,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name); + status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -836,9 +851,9 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) goto path_err; } - DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0))); + DEBUG(3,("reply_checkpath %s mode=%d\n", name_in, (int)SVAL(req->inbuf,smb_vwv0))); - status = unix_convert(conn, name, False, NULL, &sbuf); + status = unix_convert(conn, name_in, False, &name, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { goto path_err; } @@ -899,7 +914,8 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) void reply_getatr(connection_struct *conn, struct smb_request *req) { - pstring fname; + pstring fname_in; + char *fname = NULL; SMB_STRUCT_STAT sbuf; int mode=0; SMB_OFF_T size=0; @@ -910,8 +926,8 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBgetatr); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p, - sizeof(fname), 0, STR_TERMINATE, &status); + p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p, + sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBgetatr); @@ -919,7 +935,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) } status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -934,7 +950,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ - if (*fname == '\0') { + if (*fname_in == '\0') { mode = aHIDDEN | aDIR; if (!CAN_WRITE(conn)) { mode |= aRONLY; @@ -942,7 +958,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) size = 0; mtime = 0; } else { - status = unix_convert(conn, fname, False, NULL,&sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL,&sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBgetatr); @@ -997,7 +1013,8 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) void reply_setatr(connection_struct *conn, struct smb_request *req) { - pstring fname; + pstring fname_in; + char *fname = NULL; int mode; time_t mtime; SMB_STRUCT_STAT sbuf; @@ -1012,8 +1029,8 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) } p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p, - sizeof(fname), 0, STR_TERMINATE, &status); + p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p, + sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBsetatr); @@ -1021,7 +1038,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) } status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1034,7 +1051,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBsetatr); @@ -1147,7 +1164,7 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req) void reply_search(connection_struct *conn, struct smb_request *req) { pstring mask; - pstring directory; + char *directory = NULL; pstring fname; SMB_OFF_T size; uint32 mode; @@ -1181,7 +1198,7 @@ void reply_search(connection_struct *conn, struct smb_request *req) return; } - *mask = *directory = *fname = 0; + *mask = *fname = 0; /* If we were called as SMBffirst then we must expect close. */ if(CVAL(req->inbuf,smb_com) == SMBffirst) { @@ -1225,8 +1242,7 @@ void reply_search(connection_struct *conn, struct smb_request *req) if (status_len == 0) { SMB_STRUCT_STAT sbuf; - pstrcpy(directory,path); - nt_status = unix_convert(conn, directory, True, NULL, &sbuf); + nt_status = unix_convert(conn, path, True, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); END_PROFILE(SMBsearch); @@ -1243,17 +1259,43 @@ void reply_search(connection_struct *conn, struct smb_request *req) p = strrchr_m(directory,'/'); if (!p) { pstrcpy(mask,directory); - pstrcpy(directory,"."); + directory = talloc_strdup(talloc_tos(),"."); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsearch); + return; + } } else { *p = 0; pstrcpy(mask,p+1); } if (*directory == '\0') { - pstrcpy(directory,"."); + directory = talloc_strdup(talloc_tos(),"."); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsearch); + return; + } } memset((char *)status,'\0',21); SCVAL(status,0,(dirtype & 0x1F)); + + nt_status = dptr_create(conn, + directory, + True, + expect_close, + req->smbpid, + mask, + mask_contains_wcard, + dirtype, + &conn->dirptr); + if (!NT_STATUS_IS_OK(nt_status)) { + reply_nterror(req, nt_status); + END_PROFILE(SMBsearch); + return; + } + dptr_num = dptr_dnum(conn->dirptr); } else { int status_dirtype; @@ -1263,7 +1305,7 @@ void reply_search(connection_struct *conn, struct smb_request *req) dirtype = status_dirtype; } - conn->dirptr = dptr_fetch(status+12,&dptr_num); + conn->dirptr = dptr_fetch(status+12,&dptr_num); if (!conn->dirptr) { goto SearchEmpty; } @@ -1274,25 +1316,6 @@ void reply_search(connection_struct *conn, struct smb_request *req) * check from the initial saved string. */ mask_contains_wcard = ms_has_wild(mask); - } - - if (status_len == 0) { - nt_status = dptr_create(conn, - directory, - True, - expect_close, - req->smbpid, - mask, - mask_contains_wcard, - dirtype, - &conn->dirptr); - if (!NT_STATUS_IS_OK(nt_status)) { - reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; - } - dptr_num = dptr_dnum(conn->dirptr); - } else { dirtype = dptr_attr(dptr_num); } @@ -1393,13 +1416,18 @@ void reply_search(connection_struct *conn, struct smb_request *req) /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */ SSVAL(req->outbuf, smb_flg2, (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); - - if ((! *directory) && dptr_path(dptr_num)) - slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n", + if (!directory) { + directory = dptr_path(dptr_num); + } + + DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n", smb_fn_name(CVAL(req->inbuf,smb_com)), - mask, directory, dirtype, numentries, maxentries ) ); + mask, + directory ? directory : "./", + dirtype, + numentries, + maxentries )); END_PROFILE(SMBsearch); return; @@ -1468,7 +1496,8 @@ void reply_fclose(connection_struct *conn, struct smb_request *req) void reply_open(connection_struct *conn, struct smb_request *req) { - pstring fname; + pstring fname_in; + char *fname = NULL; uint32 fattr=0; SMB_OFF_T size = 0; time_t mtime=0; @@ -1496,8 +1525,8 @@ void reply_open(connection_struct *conn, struct smb_request *req) deny_mode = SVAL(req->inbuf,smb_vwv0); dos_attr = SVAL(req->inbuf,smb_vwv1); - srvstr_get_path((char *)req->inbuf, req->flags2, fname, - smb_buf(req->inbuf)+1, sizeof(fname), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, + smb_buf(req->inbuf)+1, sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1506,7 +1535,7 @@ void reply_open(connection_struct *conn, struct smb_request *req) } status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1519,7 +1548,7 @@ void reply_open(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopen); @@ -1602,7 +1631,8 @@ void reply_open(connection_struct *conn, struct smb_request *req) void reply_open_and_X(connection_struct *conn, struct smb_request *req) { - pstring fname; + pstring fname_in; + char *fname = NULL; uint16 open_flags; int deny_mode; uint32 smb_attr; @@ -1658,8 +1688,8 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path((char *)req->inbuf, req->flags2, fname, - smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE, + srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, + smb_buf(req->inbuf), sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1668,7 +1698,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) } status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1680,7 +1710,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopenX); @@ -1846,7 +1876,8 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req) void reply_mknew(connection_struct *conn, struct smb_request *req) { - pstring fname; + pstring fname_in; + char *fname = NULL; int com; uint32 fattr = 0; struct timespec ts[2]; @@ -1875,8 +1906,8 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) srv_make_unix_date3(req->inbuf + smb_vwv1)); /* mtime. */ - srvstr_get_path((char *)req->inbuf, req->flags2, fname, - smb_buf(req->inbuf) + 1, sizeof(fname), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, + smb_buf(req->inbuf) + 1, sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1885,7 +1916,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) } status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1897,7 +1928,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcreate); @@ -1974,7 +2005,8 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) void reply_ctemp(connection_struct *conn, struct smb_request *req) { - pstring fname; + pstring fname_in; + char *fname = NULL; uint32 fattr; files_struct *fsp; int oplock_request; @@ -1994,22 +2026,22 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) fattr = SVAL(req->inbuf,smb_vwv0); oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); - srvstr_get_path((char *)req->inbuf, req->flags2, fname, - smb_buf(req->inbuf)+1, sizeof(fname), 0, STR_TERMINATE, + srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, + smb_buf(req->inbuf)+1, sizeof(fname_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); return; } - if (*fname) { - pstrcat(fname,"/TMXXXXXX"); + if (*fname_in) { + pstrcat(fname_in,"/TMXXXXXX"); } else { - pstrcat(fname,"TMXXXXXX"); + pstrcat(fname_in,"TMXXXXXX"); } status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2022,7 +2054,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); @@ -2266,22 +2298,23 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req, ****************************************************************************/ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, - uint32 dirtype, char *name, BOOL has_wild) + uint32 dirtype, const char *name_in, BOOL has_wild) { pstring directory; pstring mask; + char *name = NULL; char *p; int count=0; NTSTATUS status = NT_STATUS_OK; SMB_STRUCT_STAT sbuf; - + *directory = *mask = 0; - - status = unix_convert(conn, name, has_wild, NULL, &sbuf); + + status = unix_convert(conn, name_in, has_wild, &name, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { return status; } - + p = strrchr_m(name,'/'); if (!p) { pstrcpy(directory,"."); @@ -2291,7 +2324,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, pstrcpy(directory,name); pstrcpy(mask,p+1); } - + /* * We should only check the mangled cache * here if unix_convert failed. This means @@ -2300,10 +2333,18 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, * for a possible mangle. This patch from * Tine Smukavec . */ - - if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) - mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); - + + if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) { + char *new_mask = NULL; + mangle_lookup_name_from_8_3(talloc_tos(), + mask, + &new_mask, + conn->params ); + if (new_mask) { + pstrcpy(mask, new_mask); + } + } + if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); @@ -2326,7 +2367,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, struct smb_Dir *dir_hnd = NULL; long offset = 0; const char *dname; - + if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) { return NT_STATUS_OBJECT_NAME_INVALID; } @@ -2798,6 +2839,7 @@ void reply_lockread(connection_struct *conn, struct smb_request *req) NTSTATUS status; files_struct *fsp; struct byte_range_lock *br_lck = NULL; + char *p = NULL; START_PROFILE(SMBlockread); @@ -2879,7 +2921,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); - SSVAL(smb_buf(req->outbuf),1,nread); + p = smb_buf(req->outbuf); + SCVAL(p,0,0); /* pad byte. */ + SSVAL(p,1,nread); DEBUG(3,("lockread fnum=%d num=%d nread=%d\n", fsp->fnum, (int)numtoread, (int)nread)); @@ -4600,14 +4644,15 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req) void reply_mkdir(connection_struct *conn, struct smb_request *req) { - pstring directory; + pstring directory_in; + char *directory = NULL; NTSTATUS status; SMB_STRUCT_STAT sbuf; START_PROFILE(SMBmkdir); - srvstr_get_path((char *)req->inbuf, req->flags2, directory, - smb_buf(req->inbuf) + 1, sizeof(directory), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, directory_in, + smb_buf(req->inbuf) + 1, sizeof(directory_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -4617,7 +4662,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - directory); + directory_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -4630,7 +4675,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, directory, False, NULL, &sbuf); + status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBmkdir); @@ -4853,13 +4898,14 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) void reply_rmdir(connection_struct *conn, struct smb_request *req) { - pstring directory; + pstring directory_in; + char *directory = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBrmdir); - srvstr_get_path((char *)req->inbuf, req->flags2, directory, - smb_buf(req->inbuf) + 1, sizeof(directory), 0, + srvstr_get_path((char *)req->inbuf, req->flags2, directory_in, + smb_buf(req->inbuf) + 1, sizeof(directory_in), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -4869,7 +4915,7 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - directory); + directory_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -4882,7 +4928,8 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, directory, False, NULL, &sbuf); + status = unix_convert(conn, directory_in, False, &directory, + NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBrmdir); @@ -4914,87 +4961,129 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) /******************************************************************* Resolve wildcards in a filename rename. - Note that name is in UNIX charset and thus potentially can be more - than fstring buffer (255 bytes) especially in default UTF-8 case. - Therefore, we use pstring inside and all calls should ensure that - name2 is at least pstring-long (they do already) ********************************************************************/ -static BOOL resolve_wildcards(const char *name1, char *name2) +static BOOL resolve_wildcards(TALLOC_CTX *ctx, + const char *name1, + const char *name2, + char **pp_newname) { - pstring root1,root2; - pstring ext1,ext2; + char *name2_copy = NULL; + char *root1 = NULL; + char *root2 = NULL; + char *ext1 = NULL; + char *ext2 = NULL; char *p,*p2, *pname1, *pname2; - int available_space, actual_space; + name2_copy = talloc_strdup(ctx, name2); + if (!name2_copy) { + return False; + } + pname1 = strrchr_m(name1,'/'); - pname2 = strrchr_m(name2,'/'); + pname2 = strrchr_m(name2_copy,'/'); - if (!pname1 || !pname2) - return(False); + if (!pname1 || !pname2) { + return False; + } - pstrcpy(root1,pname1); - pstrcpy(root2,pname2); + /* Truncate the copy of name2 at the last '/' */ + *pname2 = '\0'; + + /* Now go past the '/' */ + pname1++; + pname2++; + + root1 = talloc_strdup(ctx, pname1); + root2 = talloc_strdup(ctx, pname2); + + if (!root1 || !root2) { + return False; + } + p = strrchr_m(root1,'.'); if (p) { *p = 0; - pstrcpy(ext1,p+1); + ext1 = talloc_strdup(ctx, p+1); } else { - pstrcpy(ext1,""); + ext1 = talloc_strdup(ctx, ""); } p = strrchr_m(root2,'.'); if (p) { *p = 0; - pstrcpy(ext2,p+1); + ext2 = talloc_strdup(ctx, p+1); } else { - pstrcpy(ext2,""); + ext2 = talloc_strdup(ctx, ""); + } + + if (!ext1 || !ext2) { + return False; } p = root1; p2 = root2; while (*p2) { if (*p2 == '?') { + /* Hmmm. Should this be mb-aware ? */ *p2 = *p; p2++; } else if (*p2 == '*') { - pstrcpy(p2, p); + *p2 = '\0'; + root2 = talloc_asprintf(ctx, "%s%s", + root2, + p); + if (!root2) { + return False; + } break; } else { p2++; } - if (*p) + if (*p) { p++; + } } p = ext1; p2 = ext2; while (*p2) { if (*p2 == '?') { + /* Hmmm. Should this be mb-aware ? */ *p2 = *p; p2++; } else if (*p2 == '*') { - pstrcpy(p2, p); + *p2 = '\0'; + ext2 = talloc_asprintf(ctx, "%s%s", + ext2, + p); + if (!ext2) { + return False; + } break; } else { p2++; } - if (*p) + if (*p) { p++; + } } - available_space = sizeof(pstring) - PTR_DIFF(pname2, name2); - - if (ext2[0]) { - actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); - if (actual_space >= available_space - 1) { - DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n", - actual_space - available_space)); - } + if (*ext2) { + *pp_newname = talloc_asprintf(ctx, "%s/%s.%s", + name2_copy, + root2, + ext2); } else { - pstrcpy_base(pname2, root2, name2); + *pp_newname = talloc_asprintf(ctx, "%s/%s", + name2_copy, + root2); } - return(True); + if (!*pp_newname) { + return False; + } + + return True; } /**************************************************************************** @@ -5110,11 +5199,14 @@ static void notify_rename(connection_struct *conn, BOOL is_dir, Rename an open file - given an fsp. ****************************************************************************/ -NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, - pstring newname, - const char *newname_last_component, - uint32 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals_fsp(connection_struct *conn, + files_struct *fsp, + char *newname, + const char *newname_last_component, + uint32 attrs, + BOOL replace_if_exists) { + TALLOC_CTX *ctx = talloc_tos(); SMB_STRUCT_STAT sbuf, sbuf1; NTSTATUS status = NT_STATUS_OK; struct share_mode_lock *lck = NULL; @@ -5126,14 +5218,15 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, if (!NT_STATUS_IS_OK(status)) { return status; } - + /* Ensure newname contains a '/' */ if(strrchr_m(newname,'/') == 0) { - pstring tmpstr; - - pstrcpy(tmpstr, "./"); - pstrcat(tmpstr, newname); - pstrcpy(newname, tmpstr); + newname = talloc_asprintf(ctx, + "./%s", + newname); + if (!newname) { + return NT_STATUS_NO_MEMORY; + } } /* @@ -5147,7 +5240,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, if((conn->case_sensitive == False) && (conn->case_preserve == True) && strequal(newname, fsp->fsp_name)) { char *p; - pstring newname_modified_last_component; + char *newname_modified_last_component = NULL; /* * Get the last component of the modified name. @@ -5155,15 +5248,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, * character above. */ p = strrchr_m(newname,'/'); - pstrcpy(newname_modified_last_component,p+1); - - if(strcsequal(newname_modified_last_component, + newname_modified_last_component = talloc_strdup(ctx, + p+1); + if (!newname_modified_last_component) { + return NT_STATUS_NO_MEMORY; + } + + if(strcsequal(newname_modified_last_component, newname_last_component) == False) { /* * Replace the modified last component with * the original. */ - pstrcpy(p+1, newname_last_component); + *p = '\0'; /* Truncate at the '/' */ + newname = talloc_asprintf(ctx, + "%s/%s", + newname, + newname_last_component); } } @@ -5263,7 +5364,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, } } TALLOC_FREE(lck); - return NT_STATUS_OK; + return NT_STATUS_OK; } TALLOC_FREE(lck); @@ -5273,7 +5374,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, } else { status = map_nt_error_from_unix(errno); } - + DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", nt_errstr(status), fsp->fsp_name,newname)); @@ -5286,8 +5387,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, ****************************************************************************/ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, - pstring name, - pstring newname, + const char *name_in, + const char *newname_in, uint32 attrs, BOOL replace_if_exists, BOOL src_has_wild, @@ -5295,8 +5396,10 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, { pstring directory; pstring mask; - pstring last_component_src; - pstring last_component_dest; + char *last_component_src = NULL; + char *last_component_dest = NULL; + char *name = NULL; + char *newname = NULL; char *p; int count=0; NTSTATUS status = NT_STATUS_OK; @@ -5311,12 +5414,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1); + status = unix_convert(conn, name_in, src_has_wild, &name, + &last_component_src, &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; } - status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2); + status = unix_convert(conn, newname_in, dest_has_wild, &newname, + &last_component_dest, &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -5351,7 +5456,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, */ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) { - mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); + char *new_mask = NULL; + mangle_lookup_name_from_8_3(talloc_tos(), + mask, + &new_mask, + conn->params ); + if (new_mask) { + pstrcpy(mask, new_mask); + } } if (!src_has_wild) { @@ -5365,16 +5477,17 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, /* Add a terminating '/' to the directory name. */ pstrcat(directory,"/"); pstrcat(directory,mask); - + /* Ensure newname contains a '/' also */ if(strrchr_m(newname,'/') == 0) { - pstring tmpstr; - - pstrcpy(tmpstr, "./"); - pstrcat(tmpstr, newname); - pstrcpy(newname, tmpstr); + newname = talloc_asprintf(talloc_tos(), + "./%s", + newname); + if (!newname) { + return NT_STATUS_NO_MEMORY; + } } - + DEBUG(3, ("rename_internals: case_sensitive = %d, " "case_preserve = %d, short case preserve = %d, " "directory = %s, newname = %s, " @@ -5385,11 +5498,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, /* The dest name still may have wildcards. */ if (dest_has_wild) { - if (!resolve_wildcards(directory,newname)) { + char *mod_newname = NULL; + if (!resolve_wildcards(talloc_tos(), + directory,newname,&mod_newname)) { DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", directory,newname)); return NT_STATUS_NO_MEMORY; } + newname = mod_newname; } ZERO_STRUCT(sbuf1); @@ -5452,6 +5568,7 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, files_struct *fsp; pstring fname; BOOL sysdir_entry = False; + char *mod_destname = NULL; pstrcpy(fname,dname); @@ -5483,11 +5600,13 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, pstrcpy(destname,newname); - if (!resolve_wildcards(fname,destname)) { + if (!resolve_wildcards(talloc_tos(), + fname,destname,&mod_destname)) { DEBUG(6, ("resolve_wildcards %s %s failed\n", fname, destname)); continue; } + pstrcpy(destname,mod_destname); ZERO_STRUCT(sbuf1); SMB_VFS_STAT(conn, fname, &sbuf1); @@ -5756,9 +5875,12 @@ NTSTATUS copy_file(connection_struct *conn, void reply_copy(connection_struct *conn, struct smb_request *req) { - pstring name; + pstring name_in; + char *name = NULL; + pstring newname_in; + char *newname = NULL; pstring directory; - pstring mask,newname; + pstring mask; char *p; int count=0; int error = ERRnoaccess; @@ -5787,16 +5909,16 @@ void reply_copy(connection_struct *conn, struct smb_request *req) *directory = *mask = 0; p = smb_buf(req->inbuf); - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p, - sizeof(name), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, p, + sizeof(name_in), 0, STR_TERMINATE, &status, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); return; } - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p, - sizeof(newname), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p, + sizeof(newname_in), 0, STR_TERMINATE, &status, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -5804,7 +5926,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) return; } - DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); + DEBUG(3,("reply_copy : %s -> %s\n",name_in,newname_in)); if (tid2 != conn->cnum) { /* can't currently handle inter share copies XXXX */ @@ -5816,7 +5938,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) status = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name, &source_has_wild); + name_in, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5831,7 +5953,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) status = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname, &dest_has_wild); + newname_in, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5844,14 +5966,14 @@ void reply_copy(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1); + status = unix_convert(conn, name_in, source_has_wild, &name, NULL, &sbuf1); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); return; } - status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2); + status = unix_convert(conn, newname_in, dest_has_wild, &newname, NULL, &sbuf2); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); @@ -5900,18 +6022,28 @@ void reply_copy(connection_struct *conn, struct smb_request *req) */ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) { - mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); + char *new_mask = NULL; + mangle_lookup_name_from_8_3( talloc_tos(), + mask, + &new_mask, + conn->params ); + if (new_mask) { + pstrcpy(mask, new_mask); + } } if (!source_has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); if (dest_has_wild) { - if (!resolve_wildcards(directory,newname)) { + char *mod_newname = NULL; + if (!resolve_wildcards(talloc_tos(), + directory,newname,&mod_newname)) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBcopy); return; } + newname = mod_newname; } status = check_name(conn, directory); @@ -5965,6 +6097,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) error = ERRbadfile; while ((dname = ReadDirName(dir_hnd, &offset))) { + char *mod_destname = NULL; pstring fname; pstrcpy(fname,dname); @@ -5979,9 +6112,11 @@ void reply_copy(connection_struct *conn, struct smb_request *req) error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); pstrcpy(destname,newname); - if (!resolve_wildcards(fname,destname)) { + if (!resolve_wildcards(talloc_tos(), + fname,destname,&mod_destname)) { continue; } + pstrcpy(destname,mod_destname); status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index d2f09930a0..a066091b52 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 1999-2004 + Copyright (C) Jeremy Allison 1999-2007 Copyright (C) Andrew Bartlett 2003 Copyright (C) Volker Lendecke 2007 @@ -40,7 +40,8 @@ static TDB_CONTEXT *tdb_stat_cache; * */ -void stat_cache_add( const char *full_orig_name, const char *translated_path, +void stat_cache_add( const char *full_orig_name, + char *translated_path, BOOL case_sensitive) { size_t translated_path_length; @@ -48,9 +49,12 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, char *original_path; size_t original_path_length; size_t sc_size = lp_max_stat_cache_size(); + char saved_char; + TALLOC_CTX *ctx = talloc_tos(); - if (!lp_stat_cache()) + if (!lp_stat_cache()) { return; + } if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { reset_stat_cache(); @@ -73,20 +77,15 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, * would be a waste. */ - if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) + if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) { return; + } /* * Remove any trailing '/' characters from the * translated path. */ - /* - * To save a strdup we don't necessarily 0-terminate the translated - * path in the tdb. Instead, we do it directly after the tdb_fetch in - * stat_cache_lookup. - */ - translated_path_length = strlen(translated_path); if(translated_path[translated_path_length-1] == '/') { @@ -94,9 +93,9 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, } if(case_sensitive) { - original_path = SMB_STRDUP(full_orig_name); + original_path = talloc_strdup(ctx,full_orig_name); } else { - original_path = strdup_upper(full_orig_name); + original_path = talloc_strdup_upper(ctx,full_orig_name); } if (!original_path) { @@ -118,7 +117,7 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); - SAFE_FREE(original_path); + TALLOC_FREE(original_path); return; } @@ -129,13 +128,17 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, original_path_length = translated_path_length; } - /* - * New entry or replace old entry. - */ + /* Ensure we're null terminated. */ + saved_char = translated_path[translated_path_length]; + translated_path[translated_path_length] = '\0'; data_val.dsize = translated_path_length + 1; data_val.dptr = (uint8 *)translated_path; + /* + * New entry or replace old entry. + */ + if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", @@ -148,7 +151,8 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, translated_path)); } - SAFE_FREE(original_path); + translated_path[translated_path_length] = saved_char; + TALLOC_FREE(original_path); } /** @@ -157,8 +161,10 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, * @param conn A connection struct to do the stat() with. * @param name The path we are attempting to cache, modified by this routine * to be correct as far as the cache can tell us. We assume that - * it is a malloc'ed string, we free it if necessary. - * @param dirpath The path as far as the stat cache told us. + * it is a talloc'ed string from top of stack, we free it if + * necessary. + * @param dirpath The path as far as the stat cache told us. Also talloced + * from top of stack. * @param start A pointer into name, for where to 'start' in fixing the rest * of the name up. * @param psd A stat buffer, NOT from the cache, but just a side-effect. @@ -168,8 +174,11 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, * */ -BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, - char **start, SMB_STRUCT_STAT *pst) +BOOL stat_cache_lookup(connection_struct *conn, + char **pp_name, + char **pp_dirpath, + char **pp_start, + SMB_STRUCT_STAT *pst) { char *chk_name; size_t namelen; @@ -179,15 +188,18 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, size_t translated_path_length; TDB_DATA data_val; char *name; + TALLOC_CTX *ctx = talloc_tos(); - if (!lp_stat_cache()) + *pp_dirpath = NULL; + *pp_start = *pp_name; + + if (!lp_stat_cache()) { return False; + } - name = *pname; + name = *pp_name; namelen = strlen(name); - *start = name; - DO_PROFILE_INC(statcache_lookups); /* @@ -198,14 +210,14 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, } if (conn->case_sensitive) { - chk_name = SMB_STRDUP(name); + chk_name = talloc_strdup(ctx,name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); return False; } } else { - chk_name = strdup_upper(name); + chk_name = talloc_strdup_upper(ctx,name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n")); return False; @@ -216,8 +228,9 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, * if we uppercase. We need to treat this differently * below. */ - if (strlen(chk_name) != namelen) + if (strlen(chk_name) != namelen) { sizechanged = True; + } } while (1) { @@ -239,7 +252,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, * We reached the end of the name - no match. */ DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); + TALLOC_FREE(chk_name); return False; } @@ -249,25 +262,25 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, * Count the number of times we have done this, we'll * need it when reconstructing the string. */ - if (sizechanged) + + if (sizechanged) { num_components++; + } if ((*chk_name == '\0') || ISDOT(chk_name) || ISDOTDOT(chk_name)) { DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); + TALLOC_FREE(chk_name); return False; } } - translated_path = (char *)data_val.dptr; + translated_path = talloc_strdup(ctx,(char *)data_val.dptr); + if (!translated_path) { + smb_panic("talloc failed"); + } translated_path_length = data_val.dsize - 1; - - /* - * In stat_cache_add we did not necessarily 0-terminate the translated - * path. Do it here, where we do have a freshly malloc'ed blob. - */ - translated_path[translated_path_length] = '\0'; + SAFE_FREE(data_val.dptr); DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " "-> [%s]\n", chk_name, translated_path )); @@ -276,50 +289,51 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, if (SMB_VFS_STAT(conn, translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ tdb_delete_bystring(tdb_stat_cache, chk_name); - SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); + TALLOC_FREE(chk_name); + TALLOC_FREE(translated_path); return False; } if (!sizechanged) { - memcpy(name, translated_path, + memcpy(*pp_name, translated_path, MIN(namelen, translated_path_length)); - } - else { + } else { if (num_components == 0) { - name = SMB_STRNDUP(translated_path, + name = talloc_strndup(ctx, translated_path, translated_path_length); } else { char *sp; sp = strnrchr_m(name, '/', num_components); if (sp) { - asprintf(&name, "%.*s%s", + name = talloc_asprintf(ctx,"%.*s%s", (int)translated_path_length, translated_path, sp); } else { - name = SMB_STRNDUP(translated_path, - translated_path_length); + name = talloc_strndup(ctx, + translated_path, + translated_path_length); } } if (name == NULL) { /* * TODO: Get us out of here with a real error message */ - smb_panic("malloc failed"); + smb_panic("talloc failed"); } - SAFE_FREE(*pname); - *pname = name; + TALLOC_FREE(*pp_name); + *pp_name = name; } /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[translated_path_length]; - if (**start == '/') - ++*start; + *pp_start = &name[translated_path_length]; + if (**pp_start == '/') { + ++*pp_start; + } - *dirpath = translated_path; - SAFE_FREE(chk_name); + *pp_dirpath = translated_path; + TALLOC_FREE(chk_name); return (namelen == translated_path_length); } @@ -344,7 +358,7 @@ void send_stat_cache_delete_message(const char *name) void stat_cache_delete(const char *name) { - char *lname = strdup_upper(name); + char *lname = talloc_strdup_upper(talloc_tos(), name); if (!lname) { return; @@ -353,7 +367,7 @@ void stat_cache_delete(const char *name) lname, name )); tdb_delete_bystring(tdb_stat_cache, lname); - SAFE_FREE(lname); + TALLOC_FREE(lname); } /*************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ed4d4554d4..59f384e8b0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -783,7 +783,8 @@ static void call_trans2open(connection_struct *conn, int open_ofun; uint32 open_size; char *pname; - pstring fname; + pstring fname_in; + char *fname = NULL; SMB_OFF_T size=0; int fattr=0,mtime=0; SMB_INO_T inode = 0; @@ -829,8 +830,8 @@ static void call_trans2open(connection_struct *conn, return; } - srvstr_get_path(params, req->flags2, fname, pname, - sizeof(fname), total_params - 28, STR_TERMINATE, + srvstr_get_path(params, req->flags2, fname_in, pname, + sizeof(fname_in), total_params - 28, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -843,7 +844,7 @@ static void call_trans2open(connection_struct *conn, /* XXXX we need to handle passed times, sattr and flags */ - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -1163,6 +1164,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, uint32 nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); BOOL check_mangled_names = lp_manglednames(conn->params); + char mangled_name[13]; /* mangled 8.3 name. */ *fname = 0; *out_of_space = False; @@ -1215,10 +1217,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, * pathreal which is composed from dname. */ - pstrcpy(fname,dname); + pstrcpy(fname,dname); - /* This will mangle fname if it's an illegal name. */ - mangle_map(fname,False,True,conn->params); + /* Mangle fname if it's an illegal name. */ + if (mangle_must_mangle(fname,conn->params)) { + if (!name_to_8_3(fname,mangled_name,True,conn->params)) { + continue; /* Error - couldn't mangle. */ + } + pstrcpy(fname,mangled_name); + } if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) { got_match = mask_match(fname, mask, conn->case_sensitive); @@ -1226,19 +1233,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, conn->params)) { - pstring mangled_name; - /* * It turns out that NT matches wildcards against * both long *and* short names. This may explain some * of the wildcard wierdness from old DOS clients * that some people have been seeing.... JRA. */ - - pstrcpy(mangled_name, fname); - /* Force the mangling into 8.3. */ - mangle_map( mangled_name, True, False, conn->params); + if (!name_to_8_3( fname, mangled_name, False, conn->params)) { + continue; /* Error - couldn't mangle. */ + } + if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) { got_match = mask_match(mangled_name, mask, conn->case_sensitive); } @@ -1483,10 +1488,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, * a Win2k client bug. JRA. */ if (!was_8_3 && check_mangled_names) { - pstring mangled_name; - pstrcpy(mangled_name, fname); - mangle_map(mangled_name,True,True, - conn->params); + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); + } mangled_name[12] = 0; len = srvstr_push(base_data, flags2, p+2, mangled_name, 24, @@ -1638,10 +1644,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, * a Win2k client bug. JRA. */ if (!was_8_3 && check_mangled_names) { - pstring mangled_name; - pstrcpy(mangled_name, fname); - mangle_map(mangled_name,True,True, - conn->params); + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); + } mangled_name[12] = 0; len = srvstr_push(base_data, flags2, p+2, mangled_name, 24, @@ -1754,7 +1761,8 @@ static void call_trans2findfirst(connection_struct *conn, BOOL close_if_end; BOOL requires_resume_key; int info_level; - pstring directory; + pstring directory_in; + char *directory = NULL; pstring mask; char *p; int last_entry_off=0; @@ -1784,7 +1792,7 @@ static void call_trans2findfirst(connection_struct *conn, requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); info_level = SVAL(params,6); - *directory = *mask = 0; + *directory_in = *mask = 0; DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", @@ -1819,15 +1827,15 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return; } - srvstr_get_path_wcard(params, req->flags2, directory, - params+12, sizeof(directory), total_params - 12, + srvstr_get_path_wcard(params, req->flags2, directory_in, + params+12, sizeof(directory_in), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); return; } - ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard); + ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory_in, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1838,11 +1846,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return; } - ntstatus = unix_convert(conn, directory, True, NULL, &sbuf); + ntstatus = unix_convert(conn, directory_in, True, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); return; } + ntstatus = check_name(conn, directory); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); @@ -1858,7 +1867,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", } else { pstrcpy(mask,directory); } - pstrcpy(directory,"./"); + directory = talloc_strdup(talloc_tos(), "./"); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } } else { pstrcpy(mask,p+1); *p = 0; @@ -2030,14 +2043,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); - if ((! *directory) && dptr_path(dptr_num)) - slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); + if ((! *directory) && dptr_path(dptr_num)) { + directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num)); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + } + } DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", smb_fn_name(CVAL(req->inbuf,smb_com)), mask, directory, dirtype, numentries ) ); - /* + /* * Force a name mangle here to ensure that the * mask as an 8.3 name is top of the mangled cache. * The reasons for this are subtle. Don't remove @@ -2045,8 +2062,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * (see PR#13758). JRA. */ - if(!mangle_is_8_3_wildcards( mask, False, conn->params)) - mangle_map(mask, True, True, conn->params); + if(!mangle_is_8_3_wildcards( mask, False, conn->params)) { + char mangled_name[13]; + name_to_8_3(mask, mangled_name, True, conn->params); + } return; } @@ -2270,14 +2289,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd long current_pos = 0; /* - * Remember, mangle_map is called by + * Remember, name_to_8_3 is called by * get_lanman2_dir_entry(), so the resume name * could be mangled. Ensure we check the unmangled name. */ if (mangle_is_mangled(resume_name, conn->params)) { - mangle_check_cache(resume_name, sizeof(resume_name)-1, - conn->params); + char *new_resume_name = NULL; + mangle_lookup_name_from_8_3(talloc_tos(), + resume_name, + &new_resume_name, + conn->params); + if (new_resume_name) { + pstrcpy(resume_name, new_resume_name); + } } /* @@ -3483,7 +3508,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn, unsigned int data_size = 0; unsigned int param_size = 2; SMB_STRUCT_STAT sbuf; - pstring fname, dos_fname; + pstring dos_fname; + char *fname = NULL; char *fullpathname; char *base_name; char *p; @@ -3530,23 +3556,31 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - if(fsp && (fsp->fake_file_handle)) { + /* Initial check for valid fsp ptr. */ + if (!check_fsp_open(conn, req, fsp, ¤t_user)) { + return; + } + + fname = talloc_strdup(talloc_tos(),fsp->fsp_name); + if (!fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + if(fsp->fake_file_handle) { /* * This is actually for the QUOTA_FAKE_FILE --metze */ - - pstrcpy(fname, fsp->fsp_name); + /* We know this name is ok, it's already passed the checks. */ - + } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems * to do this call. JRA. */ - /* We know this name is ok, it's already passed the checks. */ - pstrcpy(fname, fsp->fsp_name); - + if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { @@ -3570,7 +3604,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - pstrcpy(fname, fsp->fsp_name); if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); reply_unixerror(req, ERRDOS, ERRbadfid); @@ -3581,7 +3614,9 @@ static void call_trans2qfilepathinfo(connection_struct *conn, delete_pending = get_delete_on_close_flag(fileid); access_mask = fsp->access_mask; } + } else { + pstring fname_in; NTSTATUS status = NT_STATUS_OK; /* qpathinfo */ @@ -3599,8 +3634,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - srvstr_get_path(params, req->flags2, fname, ¶ms[6], - sizeof(fname), total_params - 6, + srvstr_get_path(params, req->flags2, fname_in, ¶ms[6], + sizeof(fname_in), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -3609,7 +3644,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -3620,7 +3655,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -3962,16 +3997,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_ALT_NAME_INFO: case SMB_FILE_ALTERNATE_NAME_INFORMATION: { - pstring short_name; - + char mangled_name[13]; DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n")); - pstrcpy(short_name,base_name); - /* Mangle if not already 8.3 */ - if(!mangle_is_8_3(short_name, True, conn->params)) { - mangle_map(short_name,True,True,conn->params); + if (!name_to_8_3(base_name,mangled_name, + True,conn->params)) { + reply_nterror( + req, + NT_STATUS_NO_MEMORY); } len = srvstr_push(dstart, req->flags2, - pdata+4, short_name, + pdata+4, mangled_name, PTR_DIFF(dend, pdata+4), STR_UNICODE); data_size = 4 + len; @@ -4395,17 +4430,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd code. ****************************************************************************/ -NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname) +NTSTATUS hardlink_internals(connection_struct *conn, + char *oldname_in, + char *newname_in) { SMB_STRUCT_STAT sbuf1, sbuf2; - pstring last_component_oldname; - pstring last_component_newname; + char *last_component_oldname = NULL; + char *last_component_newname = NULL; + char *oldname = NULL; + char *newname = NULL; NTSTATUS status = NT_STATUS_OK; ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1); + status = unix_convert(conn, oldname_in, False, &oldname, + &last_component_oldname, &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4420,7 +4460,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - status = unix_convert(conn, newname, False, last_component_newname, &sbuf2); + status = unix_convert(conn, newname_in, False, &newname, + &last_component_newname, &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4882,13 +4923,15 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, static NTSTATUS smb_file_rename_information(connection_struct *conn, struct smb_request *req, - const char *pdata, int total_data, - files_struct *fsp, pstring fname) + const char *pdata, + int total_data, + files_struct *fsp, + const char *fname) { BOOL overwrite; uint32 root_fid; uint32 len; - pstring newname; + pstring newname_in; pstring base_name; BOOL dest_has_wcard = False; NTSTATUS status = NT_STATUS_OK; @@ -4906,8 +4949,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12], - sizeof(newname), len, 0, &status, + srvstr_get_path_wcard(pdata, req->flags2, newname_in, &pdata[12], + sizeof(newname_in), len, 0, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; @@ -4915,13 +4958,13 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, status = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname, &dest_has_wcard); + newname_in, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; } /* Check the new name has no '/' characters. */ - if (strchr_m(newname, '/')) { + if (strchr_m(newname_in, '/')) { return NT_STATUS_NOT_SUPPORTED; } @@ -4934,16 +4977,19 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, pstrcpy(base_name, "./"); } /* Append the new name. */ - pstrcat(base_name, newname); + pstrcat(base_name, newname_in); if (fsp) { SMB_STRUCT_STAT sbuf; - pstring newname_last_component; + char *newname = NULL; + char *newname_last_component = NULL; ZERO_STRUCT(sbuf); - status = unix_convert(conn, newname, False, - newname_last_component, &sbuf); + status = unix_convert(conn, newname_in, False, + &newname, + &newname_last_component, + &sbuf); /* If an error we expect this to be * NT_STATUS_OBJECT_PATH_NOT_FOUND */ @@ -4961,7 +5007,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, overwrite); } else { DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", - fname, newname )); + fname, base_name )); status = rename_internals(conn, req, fname, base_name, 0, overwrite, False, dest_has_wcard); } @@ -6121,7 +6167,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, char *pdata = *ppdata; uint16 info_level; SMB_STRUCT_STAT sbuf; - pstring fname; + char *fname = NULL; files_struct *fsp = NULL; NTSTATUS status = NT_STATUS_OK; int data_return_size = 0; @@ -6140,15 +6186,24 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } fsp = file_fsp(SVAL(params,0)); - info_level = SVAL(params,2); + /* Basic check for non-null fsp. */ + if (!check_fsp_open(conn, req, fsp, ¤t_user)) { + return; + } + info_level = SVAL(params,2); - if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) { + fname = talloc_strdup(talloc_tos(),fsp->fsp_name); + if (!fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + if(fsp->is_directory || fsp->fh->fd == -1) { /* * This is actually a SETFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems * to do this call. JRA. */ - pstrcpy(fname, fsp->fsp_name); if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { @@ -6163,7 +6218,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } } - } else if (fsp && fsp->print_file) { + } else if (fsp->print_file) { /* * Doing a DELETE_ON_CLOSE should cancel a print job. */ @@ -6171,18 +6226,17 @@ static void call_trans2setfilepathinfo(connection_struct *conn, fsp->fh->private_options |= FILE_DELETE_ON_CLOSE; DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); - + SSVAL(params,0,0); send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes); return; - } - else { + } else { reply_unixerror(req, ERRDOS, ERRbadpath); return; } - } else { + } else { /* * Original code - this is an open file. */ @@ -6190,8 +6244,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - pstrcpy(fname, fsp->fsp_name); - if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); reply_unixerror(req, ERRDOS, ERRbadfid); @@ -6199,15 +6251,17 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } } } else { + pstring fname_in; + /* set path info */ if (total_params < 7) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } - info_level = SVAL(params,0); - srvstr_get_path(params, req->flags2, fname, ¶ms[6], - sizeof(fname), total_params - 6, STR_TERMINATE, + info_level = SVAL(params,0); + srvstr_get_path(params, req->flags2, fname_in, ¶ms[6], + sizeof(fname_in), total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -6216,7 +6270,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname); + fname_in); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -6228,7 +6282,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - status = unix_convert(conn, fname, False, NULL, &sbuf); + status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -6550,7 +6604,8 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, { char *params = *pparams; char *pdata = *ppdata; - pstring directory; + pstring directory_in; + char *directory = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; struct ea_list *ea_list = NULL; @@ -6565,17 +6620,17 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, return; } - srvstr_get_path(params, req->flags2, directory, ¶ms[4], - sizeof(directory), total_params - 4, STR_TERMINATE, + srvstr_get_path(params, req->flags2, directory_in, ¶ms[4], + sizeof(directory_in), total_params - 4, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; } - DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); + DEBUG(3,("call_trans2mkdir : name = %s\n", directory_in)); - status = unix_convert(conn, directory, False, NULL, &sbuf); + status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; -- cgit From 62e3caf0feb396b65923ef849dab3143effcf787 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2007 22:54:43 +0000 Subject: r25011: We don't use mangle_map any more. Jeremy. (This used to be commit 2e0999c1df33c192fee5f739070a0e4c3d22dff8) --- source3/smbd/mangle_map.c | 211 ---------------------------------------------- 1 file changed, 211 deletions(-) delete mode 100644 source3/smbd/mangle_map.c (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c deleted file mode 100644 index 81de125248..0000000000 --- a/source3/smbd/mangle_map.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Name mapping code - Copyright (C) Jeremy Allison 1998 - Copyright (C) Andrew Tridgell 2002 - - 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 3 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, see . -*/ - -#include "includes.h" - - -/* ************************************************************************** ** - * Used only in do_fwd_mangled_map(), below. - * ************************************************************************** ** - */ -static char *map_filename( char *s, /* This is null terminated */ - const char *pattern, /* This isn't. */ - int len ) /* This is the length of pattern. */ - { - static pstring matching_bit; /* The bit of the string which matches */ - /* a * in pattern if indeed there is a * */ - char *sp; /* Pointer into s. */ - char *pp; /* Pointer into p. */ - char *match_start; /* Where the matching bit starts. */ - pstring pat; - - StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */ - pstrcpy( matching_bit, "" ); /* Match but no star gets this. */ - pp = pat; /* Initialize the pointers. */ - sp = s; - - if( strequal(s, ".") || strequal(s, "..")) - { - return NULL; /* Do not map '.' and '..' */ - } - - if( (len == 1) && (*pattern == '*') ) - { - return NULL; /* Impossible, too ambiguous for */ - } /* words! */ - - while( (*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp) /* The two match. */ - && (*pp != '*') ) /* No wildcard. */ - { - sp++; /* Keep looking. */ - pp++; - } - - if( !*sp && !*pp ) /* End of pattern. */ - return( matching_bit ); /* Simple match. Return empty string. */ - - if( *pp == '*' ) - { - pp++; /* Always interrested in the chacter */ - /* after the '*' */ - if( !*pp ) /* It is at the end of the pattern. */ - { - StrnCpy( matching_bit, s, sp-s ); - return( matching_bit ); - } - else - { - /* The next character in pattern must match a character further */ - /* along s than sp so look for that character. */ - match_start = sp; - while( (*sp) /* Not the end of s. */ - && (*sp != *pp) ) /* Not the same */ - sp++; /* Keep looking. */ - if( !*sp ) /* Got to the end without a match. */ - { - return( NULL ); - } /* Still hope for a match. */ - else - { - /* Now sp should point to a matching character. */ - StrnCpy(matching_bit, match_start, sp-match_start); - /* Back to needing a stright match again. */ - while( (*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp) ) /* The two match. */ - { - sp++; /* Keep looking. */ - pp++; - } - if( !*sp && !*pp ) /* Both at end so it matched */ - return( matching_bit ); - else - return( NULL ); - } - } - } - return( NULL ); /* No match. */ - } /* map_filename */ - - -/* ************************************************************************** ** - * MangledMap is a series of name pairs in () separated by spaces. - * If s matches the first of the pair then the name given is the - * second of the pair. A * means any number of any character and if - * present in the second of the pair as well as the first the - * matching part of the first string takes the place of the * in the - * second. - * - * I wanted this so that we could have RCS files which can be used - * by UNIX and DOS programs. My mapping string is (RCS rcs) which - * converts the UNIX RCS file subdirectory to lowercase thus - * preventing mangling. - * - * See 'mangled map' in smb.conf(5). - * - * ************************************************************************** ** - */ -static void mangled_map(char *s, const char *MangledMap) -{ - const char *start=MangledMap; /* Use this to search for mappings. */ - const char *end; /* Used to find the end of strings. */ - char *match_string; - pstring new_string; /* Make up the result here. */ - char *np; /* Points into new_string. */ - - DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) ); - while( *start ) { - while( (*start) && (*start != '(') ) - start++; - if( !*start ) - continue; /* Always check for the end. */ - start++; /* Skip the ( */ - end = start; /* Search for the ' ' or a ')' */ - DEBUG( 5, ("Start of first in pair '%s'\n", start) ); - while( (*end) && !((*end == ' ') || (*end == ')')) ) - end++; - if( !*end ) { - start = end; - continue; /* Always check for the end. */ - } - DEBUG( 5, ("End of first in pair '%s'\n", end) ); - if( (match_string = map_filename( s, start, end-start )) ) { - int size_left = sizeof(new_string) - 1; - DEBUG( 5, ("Found a match\n") ); - /* Found a match. */ - start = end + 1; /* Point to start of what it is to become. */ - DEBUG( 5, ("Start of second in pair '%s'\n", start) ); - end = start; - np = new_string; - while( (*end && size_left > 0) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*') ) { /* Not a wildcard. */ - *np++ = *end++; - size_left--; - } - - if( !*end ) { - start = end; - continue; /* Always check for the end. */ - } - if( *end == '*' ) { - if (size_left > 0 ) - safe_strcpy( np, match_string, size_left ); - np += strlen( match_string ); - size_left -= strlen( match_string ); - end++; /* Skip the '*' */ - while ((*end && size_left > 0) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*')) { /* Not a wildcard. */ - *np++ = *end++; - size_left--; - } - } - if (!*end) { - start = end; - continue; /* Always check for the end. */ - } - if (size_left > 0) - *np++ = '\0'; /* NULL terminate it. */ - DEBUG(5,("End of second in pair '%s'\n", end)); - new_string[sizeof(new_string)-1] = '\0'; - pstrcpy( s, new_string ); /* Substitute with the new name. */ - DEBUG( 5, ("s is now '%s'\n", s) ); - } - start = end; /* Skip a bit which cannot be wanted anymore. */ - start++; - } -} - -/* - front end routine to the mangled map code - personally I think that the whole idea of "mangled map" is completely bogus -*/ -void mangle_map_filename(fstring fname, const struct share_params *p) -{ - char *map; - - map = lp_mangled_map(p); - if (!map || !*map) return; - - mangled_map(fname, map); -} -- cgit From 4ee8b2937d48308c6089fb539fdbd8625dfde360 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 10 Sep 2007 10:56:07 +0000 Subject: r25055: Add file_id_string_tos This removes file_id_string_static and file_id_string_static2 (This used to be commit 638c848c9afe374feb30e34c494f89b2a6c64f7b) --- source3/smbd/close.c | 4 ++-- source3/smbd/files.c | 4 ++-- source3/smbd/open.c | 2 +- source3/smbd/oplock.c | 24 ++++++++++++------------ source3/smbd/oplock_irix.c | 12 ++++++------ source3/smbd/oplock_linux.c | 8 ++++---- source3/smbd/reply.c | 4 ++-- 7 files changed, 29 insertions(+), 29 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 30220ce4de..4eb1a30342 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -273,8 +273,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, " "stat file_id %s\n", fsp->fsp_name, - file_id_static_string(&fsp->file_id), - file_id_static_string2(&id))); + file_id_string_tos(&fsp->file_id), + file_id_string_tos(&id))); /* * Don't save the errno here, we ignore this error */ diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 9d27c69a6b..f3740da328 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -233,7 +233,7 @@ void file_dump_open_table(void) for (fsp=Files;fsp;fsp=fsp->next,count++) { DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n", count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id, - file_id_static_string(&fsp->file_id))); + file_id_string_tos(&fsp->file_id))); } } @@ -280,7 +280,7 @@ files_struct *file_find_dif(struct file_id id, unsigned long gen_id) (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \ oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, - file_id_static_string(&fsp->file_id), + file_id_string_tos(&fsp->file_id), (unsigned int)fsp->fh->gen_id, (unsigned int)fsp->oplock_type )); smb_panic("file_find_dif"); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6efef2f912..691599ca97 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2339,7 +2339,7 @@ void msg_file_was_renamed(struct messaging_context *msg, DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " "file_id %s\n", - sharepath, newname, file_id_static_string(&id))); + sharepath, newname, file_id_string_tos(&id))); for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e552cb545e..a5f74b89d0 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -119,7 +119,7 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) DEBUG(5,("set_file_oplock: granted oplock on file %s, %s/%lu, " "tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fsp_name, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); @@ -192,7 +192,7 @@ BOOL remove_oplock(files_struct *fsp) if (!ret) { DEBUG(0,("remove_oplock: failed to remove share oplock for " "file %s fnum %d, %s\n", - fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id))); + fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id))); } release_file_oplock(fsp); TALLOC_FREE(lck); @@ -217,7 +217,7 @@ BOOL downgrade_oplock(files_struct *fsp) if (!ret) { DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " "for file %s fnum %d, file_id %s\n", - fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id))); + fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id))); } downgrade_file_oplock(fsp); @@ -289,7 +289,7 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: called for %s/%u\n", - file_id_static_string(&id), (int)file_id); + file_id_string_tos(&id), (int)file_id); dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", exclusive_oplocks_open, level_II_oplocks_open ); } @@ -306,7 +306,7 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f /* The file could have been closed in the meantime - return success. */ if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: cannot find open file with " ); - dbgtext( "file_id %s gen_id = %lu", file_id_static_string(&id), file_id); + dbgtext( "file_id %s gen_id = %lu", file_id_string_tos(&id), file_id); dbgtext( "allowing break to succeed.\n" ); } return NULL; @@ -326,7 +326,7 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n", - file_id_static_string(&id), fsp->fh->gen_id ); + file_id_string_tos(&id), fsp->fh->gen_id ); dbgtext( "Allowing break to succeed regardless.\n" ); } return NULL; @@ -405,7 +405,7 @@ static void process_oplock_async_level2_break_message(struct messaging_context * message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n", - (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id)); + (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -493,7 +493,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n", - (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id)); + (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id)); fsp = initial_break_processing(msg.id, msg.share_file_id); @@ -523,7 +523,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) && !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { DEBUG(3, ("Already downgraded oplock on %s: %s\n", - file_id_static_string(&fsp->file_id), + file_id_string_tos(&fsp->file_id), fsp->fsp_name)); /* We just send the same message back. */ messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE, @@ -605,7 +605,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, file_id = (unsigned long)IVAL(data->data, 16); DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n", - (int)procid_to_pid(&src), file_id_static_string(&id), + (int)procid_to_pid(&src), file_id_string_tos(&id), (unsigned int)file_id)); fsp = initial_break_processing(id, file_id); @@ -695,7 +695,7 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx, message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n", - (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id, + (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id, (unsigned int)msg.op_mid)); /* Here's the hack from open.c, store the mid in the 'port' field */ @@ -724,7 +724,7 @@ static void process_open_retry_message(struct messaging_context *msg_ctx, message_to_share_mode_entry(&msg, (char *)data->data); DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n", - (int)procid_to_pid(&src), file_id_static_string(&msg.id), + (int)procid_to_pid(&src), file_id_string_tos(&msg.id), (unsigned int)msg.op_mid)); schedule_deferred_open_smb_message(msg.op_mid); diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 75f807f86b..dde32fa288 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -154,7 +154,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) DEBUG(5,("irix_oplock_receive_message: kernel oplock break request " "received for file_id %s gen_id = %ul", - file_id_static_string(&fsp->file_id), + file_id_string_tos(&fsp->file_id), fsp->fh->gen_id )); return fsp; @@ -171,7 +171,7 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) DEBUG(0,("irix_set_kernel_oplock: Unable to get " "kernel oplock on file %s, file_id %s " "gen_id = %ul. Error was %s\n", - fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fsp_name, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) )); } else { @@ -180,7 +180,7 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) "gen_id = %ul. Another process had the file " "open.\n", fsp->fsp_name, fsp->fh->fd, - file_id_static_string(&fsp->file_id), + file_id_string_tos(&fsp->file_id), fsp->fh->gen_id )); } return False; @@ -188,7 +188,7 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s " "gen_id = %ul\n", - fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fsp_name, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id)); return True; @@ -208,7 +208,7 @@ static void irix_release_kernel_oplock(files_struct *fsp) int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); dbgtext("irix_release_kernel_oplock: file %s, file_id = %s" "gen_id = %ul, has kernel oplock state " - "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id), + "of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, state ); } @@ -221,7 +221,7 @@ static void irix_release_kernel_oplock(files_struct *fsp) "removing kernel oplock on file " ); dbgtext("%s, file_id = %s gen_id = %ul. " "Error was %s\n", - fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fsp_name, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) ); } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 66ed900015..b07c2644a9 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -168,14 +168,14 @@ static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " "fd = %d, file_id = %s. (%s)\n", fsp->fsp_name, fsp->fh->fd, - file_id_static_string(&fsp->file_id), + file_id_string_tos(&fsp->file_id), strerror(errno))); return False; } DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, " "file_id = %s gen_id = %lu\n", - fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fsp_name, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id)); return True; @@ -195,7 +195,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); dbgtext("linux_release_kernel_oplock: file %s, file_id = %s " "gen_id = %lu has kernel oplock state " - "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id), + "of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, state ); } @@ -208,7 +208,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) "removing kernel oplock on file " ); dbgtext("%s, file_id = %s, gen_id = %lu. " "Error was %s\n", fsp->fsp_name, - file_id_static_string(&fsp->file_id), + file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) ); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dec0e26c41..e3c3e8dff0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5108,7 +5108,7 @@ static void rename_open_files(connection_struct *conn, continue; } DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n", - fsp->fnum, file_id_static_string(&fsp->file_id), + fsp->fnum, file_id_string_tos(&fsp->file_id), fsp->fsp_name, newname )); string_set(&fsp->fsp_name, newname); did_rename = True; @@ -5116,7 +5116,7 @@ static void rename_open_files(connection_struct *conn, if (!did_rename) { DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n", - file_id_static_string(&lck->id), newname )); + file_id_string_tos(&lck->id), newname )); } /* Send messages to all smbd's (not ourself) that the name has changed. */ -- cgit From 351eb37a2555ce474ee02758f2f2cfee33d4d434 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Sep 2007 18:31:29 +0000 Subject: r25102: Rewrite msdfs code to use talloced filenames. Passes make test and make valgrindtest. Final step will be to change srvstr_get_path() to return talloced memory in the major codepaths. Jeremy. (This used to be commit cf6b6f9c3a38b68d2671c753f412772344506742) --- source3/smbd/dir.c | 3 +- source3/smbd/msdfs.c | 861 ++++++++++++++++++++++++++++++++++--------------- source3/smbd/nttrans.c | 58 ++-- source3/smbd/reply.c | 213 ++++++------ source3/smbd/trans2.c | 71 ++-- 5 files changed, 811 insertions(+), 395 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index e602008b8f..b21e6501d6 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1019,7 +1019,6 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * } if (hide_unreadable || hide_unwriteable || hide_special) { - pstring link_target; char *entry = NULL; if (asprintf(&entry, "%s/%s", dir_path, name) == -1) { @@ -1029,7 +1028,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * /* If it's a dfs symlink, ignore _hide xxxx_ options */ if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - is_msdfs_link(conn, entry, link_target, NULL)) { + is_msdfs_link(conn, entry, NULL)) { SAFE_FREE(entry); return True; } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 10652874c5..d687974ff3 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/Netbios implementation. Version 3.0 MSDFS services for Samba @@ -9,12 +9,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 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, see . @@ -36,22 +36,37 @@ extern uint32 global_client_caps; SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then send a local path, we have to cope with that too.... + This version does everything using pointers within one copy of the + pathname string, talloced on the struct dfs_path pointer (which + must be talloced). This may be too clever to live.... JRA. **********************************************************************/ static NTSTATUS parse_dfs_path(const char *pathname, BOOL allow_wcards, - struct dfs_path *pdp, + struct dfs_path *pdp, /* MUST BE TALLOCED */ BOOL *ppath_contains_wcard) { - pstring pathname_local; + char *pathname_local; char *p,*temp; + char *eos_ptr; NTSTATUS status = NT_STATUS_OK; char sepchar; ZERO_STRUCTP(pdp); - pstrcpy(pathname_local,pathname); + /* + * This is the only talloc we should need to do + * on the struct dfs_path. All the pointers inside + * it should point to offsets within this string. + */ + + pathname_local = talloc_strdup(pdp, pathname); + if (!pathname_local) { + return NT_STATUS_NO_MEMORY; + } + /* Get a pointer to the terminating '\0' */ + eos_ptr = &pathname_local[strlen(pathname_local)]; p = temp = pathname_local; pdp->posix_path = (lp_posix_pathnames() && *pathname == '/'); @@ -66,17 +81,22 @@ static NTSTATUS parse_dfs_path(const char *pathname, * Try and convert to a local path. */ - pdp->hostname[0] = '\0'; - pdp->servicename[0] = '\0'; + pdp->hostname = eos_ptr; /* "" */ + pdp->servicename = eos_ptr; /* "" */ /* We've got no info about separators. */ pdp->posix_path = lp_posix_pathnames(); p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + DEBUG(10,("parse_dfs_path: trying to convert %s to a " + "local path\n", temp)); goto local_path; } + /* + * Safe to use on talloc'ed string as it only shrinks. + * It also doesn't affect the eos_ptr. + */ trim_char(temp,sepchar,sepchar); DEBUG(10,("parse_dfs_path: temp = |%s| after trimming %c's\n", @@ -93,34 +113,38 @@ static NTSTATUS parse_dfs_path(const char *pathname, * Try and convert to a local path. */ - pdp->hostname[0] = '\0'; - pdp->servicename[0] = '\0'; + pdp->hostname = eos_ptr; /* "" */ + pdp->servicename = eos_ptr; /* "" */ p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", temp)); goto local_path; } *p = '\0'; - fstrcpy(pdp->hostname,temp); + pdp->hostname = temp; + DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); /* If we got a hostname, is it ours (or an IP address) ? */ if (!is_myname_or_ipaddr(pdp->hostname)) { /* Repair path. */ *p = sepchar; - DEBUG(10,("parse_dfs_path: hostname %s isn't ours. Try local path from path %s\n", + DEBUG(10,("parse_dfs_path: hostname %s isn't ours. " + "Try local path from path %s\n", pdp->hostname, temp)); /* * Possibly client sent a local path by mistake. * Try and convert to a local path. */ - pdp->hostname[0] = '\0'; - pdp->servicename[0] = '\0'; + pdp->hostname = eos_ptr; /* "" */ + pdp->servicename = eos_ptr; /* "" */ p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", temp)); goto local_path; } @@ -129,12 +153,12 @@ static NTSTATUS parse_dfs_path(const char *pathname, temp = p+1; p = strchr_m(temp,sepchar); if(p == NULL) { - fstrcpy(pdp->servicename,temp); - pdp->reqpath[0] = '\0'; + pdp->servicename = temp; + pdp->reqpath = eos_ptr; /* "" */ return NT_STATUS_OK; } *p = '\0'; - fstrcpy(pdp->servicename,temp); + pdp->servicename = temp; DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); p++; @@ -143,14 +167,15 @@ static NTSTATUS parse_dfs_path(const char *pathname, *ppath_contains_wcard = False; - pstrcpy(pdp->reqpath, p); + pdp->reqpath = p; /* Rest is reqpath. */ if (pdp->posix_path) { status = check_path_syntax_posix(pdp->reqpath); } else { if (allow_wcards) { - status = check_path_syntax_wcard(pdp->reqpath, ppath_contains_wcard); + status = check_path_syntax_wcard(pdp->reqpath, + ppath_contains_wcard); } else { status = check_path_syntax(pdp->reqpath); } @@ -171,7 +196,9 @@ static NTSTATUS parse_dfs_path(const char *pathname, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char *path) +static NTSTATUS create_conn_struct(connection_struct *conn, + int snum, + const char *path) { pstring connpath; @@ -187,7 +214,8 @@ static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char return NT_STATUS_NO_MEMORY; } - if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) { + if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, + struct share_params))) { DEBUG(0, ("TALLOC failed\n")); return NT_STATUS_NO_MEMORY; } @@ -204,15 +232,16 @@ static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char } /* - * Windows seems to insist on doing trans2getdfsreferral() calls on the IPC$ - * share as the anonymous user. If we try to chdir as that user we will - * fail.... WTF ? JRA. + * Windows seems to insist on doing trans2getdfsreferral() calls on + * the IPC$ share as the anonymous user. If we try to chdir as that + * user we will fail.... WTF ? JRA. */ if (vfs_ChDir(conn,conn->connectpath) != 0) { NTSTATUS status = map_nt_error_from_unix(errno); - DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", - conn->connectpath, strerror(errno) )); + DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. " + "Error was %s\n", + conn->connectpath, strerror(errno) )); conn_free_internal(conn); return status; } @@ -240,23 +269,31 @@ static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char **********************************************************************/ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, - char *target, + const char *target, struct referral **preflist, int *refcount) { - pstring temp; + char *temp = NULL; char *prot; - char *alt_path[MAX_REFERRAL_COUNT]; + char **alt_path = NULL; int count = 0, i; struct referral *reflist; - pstrcpy(temp,target); + temp = talloc_strdup(ctx, target); + if (!temp) { + return False; + } prot = strtok(temp,":"); if (!prot) { DEBUG(0,("parse_msdfs_symlink: invalid path !\n")); return False; } + alt_path = TALLOC_ARRAY(ctx, char *, MAX_REFERRAL_COUNT); + if (!alt_path) { + return False; + } + /* parse out the alternate paths */ while((countst_mode)) { - DEBUG(5,("is_msdfs_link: %s is not a link.\n",path)); - return False; + DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n", + path)); + goto err; } - /* open the link and read it */ - referral_len = SMB_VFS_READLINK(conn, path, link_target, sizeof(pstring)-1); + referral_len = SMB_VFS_READLINK(conn, path, link_target, bufsize - 1); if (referral_len == -1) { - DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", + DEBUG(0,("is_msdfs_link_read_target: Error reading " + "msdfs link %s: %s\n", path, strerror(errno))); - return False; + goto err; } link_target[referral_len] = '\0'; - DEBUG(5,("is_msdfs_link: %s -> %s\n",path, link_target)); + DEBUG(5,("is_msdfs_link_internal: %s -> %s\n",path, + link_target)); if (!strnequal(link_target, "msdfs:", 6)) { - return False; + goto err; } return True; + + err: + + if (link_target != link_target_buf) { + TALLOC_FREE(link_target); + } + return False; +} + +/********************************************************************** + Returns true if the unix path is a valid msdfs symlink. +**********************************************************************/ + +BOOL is_msdfs_link(connection_struct *conn, + const char *path, + SMB_STRUCT_STAT *sbufp) +{ + return is_msdfs_link_internal(talloc_tos(), + conn, + path, + NULL, + sbufp); } /***************************************************************** Used by other functions to decide if a dfs path is remote, and to get the list of referred locations for that remote path. - + search_flag: For findfirsts, dfs links themselves are not redirected, but paths beyond the links are. For normal smb calls, even dfs links need to be redirected. @@ -358,25 +444,27 @@ BOOL is_msdfs_link(connection_struct *conn, link redirect are in targetpath. *****************************************************************/ -static NTSTATUS dfs_path_lookup(connection_struct *conn, - const char *dfspath, /* Incoming complete dfs path */ - const struct dfs_path *pdp, /* Parsed out server+share+extrapath. */ - BOOL search_flag, /* Called from a findfirst ? */ - int *consumedcntp, - pstring targetpath) +static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, + connection_struct *conn, + const char *dfspath, /* Incoming complete dfs path */ + const struct dfs_path *pdp, /* Parsed out + server+share+extrapath. */ + BOOL search_flag, /* Called from a findfirst ? */ + int *consumedcntp, + char **pp_targetpath) { char *p = NULL; char *q = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; - pstring localpath_in; char *localpath = NULL; - pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */ + char *canon_dfspath = NULL; /* Canonicalized dfs path. (only '/' + components). */ DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n", conn->connectpath, pdp->reqpath)); - /* + /* * Note the unix path conversion here we're doing we can * throw away. We're looking for a symlink for a dfs * resolution, if we don't find it we'll do another @@ -388,8 +476,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, * think this is needed. JRA. */ - pstrcpy(localpath_in, pdp->reqpath); - status = unix_convert(conn, localpath_in, search_flag, &localpath, NULL, &sbuf); + status = unix_convert(conn, pdp->reqpath, search_flag, &localpath, + NULL, &sbuf); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { return status; @@ -397,7 +485,7 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, /* Optimization - check if we can redirect the whole path. */ - if (is_msdfs_link(conn, localpath, targetpath, NULL)) { + if (is_msdfs_link_internal(ctx, conn, localpath, pp_targetpath, NULL)) { if (search_flag) { DEBUG(6,("dfs_path_lookup (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); @@ -405,7 +493,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, } DEBUG(6,("dfs_path_lookup: %s resolves to a " - "valid dfs link %s.\n", dfspath, targetpath)); + "valid dfs link %s.\n", dfspath, + pp_targetpath ? *pp_targetpath : "")); if (consumedcntp) { *consumedcntp = strlen(dfspath); @@ -417,7 +506,10 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, * so if a Windows path replace all '\\' characters with '/'. * For a POSIX DFS path we know all separators are already '/'. */ - pstrcpy(canon_dfspath, dfspath); + canon_dfspath = talloc_strdup(ctx, dfspath); + if (!canon_dfspath) { + return NT_STATUS_NO_MEMORY; + } if (!pdp->posix_path) { string_replace(canon_dfspath, '\\', '/'); } @@ -432,7 +524,7 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, /* * Redirect if any component in the path is a link. - * We do this by walking backwards through the + * We do this by walking backwards through the * local path, chopping off the last component * in both the local path and the canonicalized * DFS path. If we hit a DFS link then we're done. @@ -449,14 +541,17 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, *q = '\0'; } - if (is_msdfs_link(conn, localpath, targetpath, NULL)) { + if (is_msdfs_link_internal(ctx, conn, + localpath, pp_targetpath, NULL)) { DEBUG(4, ("dfs_path_lookup: Redirecting %s because " "parent %s is dfs link\n", dfspath, localpath)); if (consumedcntp) { *consumedcntp = strlen(canon_dfspath); DEBUG(10, ("dfs_path_lookup: Path consumed: %s " - "(%d)\n", canon_dfspath, *consumedcntp)); + "(%d)\n", + canon_dfspath, + *consumedcntp)); } return NT_STATUS_PATH_NOT_COVERED; @@ -478,7 +573,7 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, Decides if a dfs pathname should be redirected or not. If not, the pathname is converted to a tcon-relative local unix path - search_wcard_flag: this flag performs 2 functions bother related + search_wcard_flag: this flag performs 2 functions both related to searches. See resolve_dfs_path() and parse_dfs_path_XX() for details. @@ -486,25 +581,36 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, (mapped into a local path). or NT_STATUS_NOT_COVERED meaning return a DFS redirect, or any other NT_STATUS error which is a genuine error to be - returned to the client. + returned to the client. *****************************************************************/ -static NTSTATUS dfs_redirect( connection_struct *conn, - pstring dfs_path, +static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, + connection_struct *conn, + const char *path_in, BOOL search_wcard_flag, + char **pp_path_out, BOOL *ppath_contains_wcard) { NTSTATUS status; - struct dfs_path dp; - pstring targetpath; - - status = parse_dfs_path(dfs_path, search_wcard_flag, &dp, ppath_contains_wcard); + struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); + + if (!pdp) { + return NT_STATUS_NO_MEMORY; + } + + status = parse_dfs_path(path_in, search_wcard_flag, pdp, + ppath_contains_wcard); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(pdp); return status; } - if (dp.reqpath[0] == '\0') { - pstrcpy(dfs_path, dp.reqpath); + if (pdp->reqpath[0] == '\0') { + TALLOC_FREE(pdp); + *pp_path_out = talloc_strdup(ctx, ""); + if (!*pp_path_out) { + return NT_STATUS_NO_MEMORY; + } DEBUG(5,("dfs_redirect: self-referral.\n")); return NT_STATUS_OK; } @@ -513,45 +619,63 @@ static NTSTATUS dfs_redirect( connection_struct *conn, path and return OK */ if (!lp_msdfs_root(SNUM(conn))) { - pstrcpy(dfs_path, dp.reqpath); + *pp_path_out = talloc_strdup(ctx, pdp->reqpath); + TALLOC_FREE(pdp); + if (!*pp_path_out) { + return NT_STATUS_NO_MEMORY; + } return NT_STATUS_OK; } /* If it looked like a local path (zero hostname/servicename) - * just treat as a tcon-relative path. */ + * just treat as a tcon-relative path. */ - if (dp.hostname[0] == '\0' && dp.servicename[0] == '\0') { - pstrcpy(dfs_path, dp.reqpath); + if (pdp->hostname[0] == '\0' && pdp->servicename[0] == '\0') { + *pp_path_out = talloc_strdup(ctx, pdp->reqpath); + TALLOC_FREE(pdp); + if (!*pp_path_out) { + return NT_STATUS_NO_MEMORY; + } return NT_STATUS_OK; } - if (!( strequal(dp.servicename, lp_servicename(SNUM(conn))) - || (strequal(dp.servicename, HOMES_NAME) - && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) { + if (!( strequal(pdp->servicename, lp_servicename(SNUM(conn))) + || (strequal(pdp->servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), + get_current_username()) )) ) { /* The given sharename doesn't match this connection. */ + TALLOC_FREE(pdp); return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - status = dfs_path_lookup(conn, dfs_path, &dp, - search_wcard_flag, NULL, targetpath); + status = dfs_path_lookup(ctx, conn, path_in, pdp, + search_wcard_flag, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { - DEBUG(3,("dfs_redirect: Redirecting %s\n", dfs_path)); + DEBUG(3,("dfs_redirect: Redirecting %s\n", path_in)); } else { - DEBUG(10,("dfs_redirect: dfs_path_lookup failed for %s with %s\n", - dfs_path, nt_errstr(status) )); + DEBUG(10,("dfs_redirect: dfs_path_lookup " + "failed for %s with %s\n", + path_in, nt_errstr(status) )); } return status; } - DEBUG(3,("dfs_redirect: Not redirecting %s.\n", dfs_path)); + DEBUG(3,("dfs_redirect: Not redirecting %s.\n", path_in)); /* Form non-dfs tcon-relative path */ - pstrcpy(dfs_path, dp.reqpath); + *pp_path_out = talloc_strdup(ctx, pdp->reqpath); + TALLOC_FREE(pdp); + if (!*pp_path_out) { + return NT_STATUS_NO_MEMORY; + } + + DEBUG(3,("dfs_redirect: Path %s converted to non-dfs path %s\n", + path_in, + *pp_path_out)); - DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", dfs_path)); return NT_STATUS_OK; } @@ -571,11 +695,13 @@ static NTSTATUS self_ref(TALLOC_CTX *ctx, jucn->referral_count = 1; if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { - DEBUG(0,("self_ref: talloc failed for referral\n")); return NT_STATUS_NO_MEMORY; } - pstrcpy(ref->alternate_path,dfs_path); + ref->alternate_path = talloc_strdup(ctx, dfs_path); + if (!ref->alternate_path) { + return NT_STATUS_NO_MEMORY; + } ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; @@ -596,57 +722,76 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, { struct connection_struct conns; struct connection_struct *conn = &conns; - struct dfs_path dp; - pstring conn_path; - pstring targetpath; + char *targetpath = NULL; int snum; NTSTATUS status = NT_STATUS_NOT_FOUND; BOOL dummy; + struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); - ZERO_STRUCT(conns); + if (!pdp) { + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCT(conns); *self_referralp = False; - status = parse_dfs_path(dfs_path, False, &dp, &dummy); + status = parse_dfs_path(dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return status; } /* Verify hostname in path */ - if (!is_myname_or_ipaddr(dp.hostname)) { + if (!is_myname_or_ipaddr(pdp->hostname)) { DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - dp.hostname, dfs_path)); + pdp->hostname, dfs_path)); + TALLOC_FREE(pdp); return NT_STATUS_NOT_FOUND; } - fstrcpy(jucn->service_name, dp.servicename); - pstrcpy(jucn->volume_name, dp.reqpath); + jucn->service_name = talloc_strdup(ctx, pdp->servicename); + jucn->volume_name = talloc_strdup(ctx, pdp->reqpath); + if (!jucn->service_name || !jucn->volume_name) { + TALLOC_FREE(pdp); + return NT_STATUS_NO_MEMORY; + } /* Verify the share is a dfs root */ snum = lp_servicenumber(jucn->service_name); if(snum < 0) { - if ((snum = find_service(jucn->service_name)) < 0) { + fstring service_name; + fstrcpy(service_name, jucn->service_name); + if ((snum = find_service(service_name)) < 0) { return NT_STATUS_NOT_FOUND; } + TALLOC_FREE(jucn->service_name); + jucn->service_name = talloc_strdup(ctx, service_name); + if (!jucn->service_name) { + TALLOC_FREE(pdp); + return NT_STATUS_NO_MEMORY; + } } if (!lp_msdfs_root(snum)) { - DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n", - dp.servicename, dfs_path)); + DEBUG(3,("get_referred_path: |%s| in dfs path %s is not " + "a dfs root.\n", + pdp->servicename, dfs_path)); + TALLOC_FREE(pdp); return NT_STATUS_NOT_FOUND; } /* * Self referrals are tested with a anonymous IPC connection and - * a GET_DFS_REFERRAL call to \\server\share. (which means dp.reqpath[0] points - * to an empty string). create_conn_struct cd's into the directory and will - * fail if it cannot (as the anonymous user). Cope with this. + * a GET_DFS_REFERRAL call to \\server\share. (which means + * dp.reqpath[0] points to an empty string). create_conn_struct cd's + * into the directory and will fail if it cannot (as the anonymous + * user). Cope with this. */ - if (dp.reqpath[0] == '\0') { + if (pdp->reqpath[0] == '\0') { struct referral *ref; if (*lp_msdfs_proxy(snum) == '\0') { + TALLOC_FREE(pdp); return self_ref(ctx, dfs_path, jucn, @@ -654,44 +799,58 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, self_referralp); } - /* + /* * It's an msdfs proxy share. Redirect to * the configured target share. */ jucn->referral_count = 1; if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { - DEBUG(0, ("malloc failed for referral\n")); + TALLOC_FREE(pdp); return NT_STATUS_NO_MEMORY; } - pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); - if (dp.reqpath[0] != '\0') { - pstrcat(ref->alternate_path, dp.reqpath); + ref->alternate_path = talloc_strdup(ctx, lp_msdfs_proxy(snum)); + if (!ref->alternate_path) { + TALLOC_FREE(pdp); + return NT_STATUS_NO_MEMORY; + } + + if (pdp->reqpath[0] != '\0') { + ref->alternate_path = talloc_asprintf(ctx, + "%s%s", + ref->alternate_path, + pdp->reqpath); + if (!ref->alternate_path) { + TALLOC_FREE(pdp); + return NT_STATUS_NO_MEMORY; + } } ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; *consumedcntp = strlen(dfs_path); + TALLOC_FREE(pdp); return NT_STATUS_OK; } - pstrcpy(conn_path, lp_pathname(snum)); - status = create_conn_struct(conn, snum, conn_path); + status = create_conn_struct(conn, snum, lp_pathname(snum)); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(pdp); return status; } /* If this is a DFS path dfs_lookup should return * NT_STATUS_PATH_NOT_COVERED. */ - status = dfs_path_lookup(conn, dfs_path, &dp, - False, consumedcntp, targetpath); + status = dfs_path_lookup(ctx, conn, dfs_path, pdp, + False, consumedcntp, &targetpath); if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); conn_free_internal(conn); + TALLOC_FREE(pdp); return status; } @@ -702,22 +861,24 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); conn_free_internal(conn); + TALLOC_FREE(pdp); return NT_STATUS_NOT_FOUND; } conn_free_internal(conn); + TALLOC_FREE(pdp); return NT_STATUS_OK; } static int setup_ver2_dfs_referral(const char *pathname, - char **ppdata, + char **ppdata, struct junction_map *junction, int consumedcnt, BOOL self_referral) { char* pdata = *ppdata; - unsigned char uni_requestedpath[1024]; + unsigned char uni_requestedpath[sizeof(pstring)]; int uni_reqpathoffset1,uni_reqpathoffset2; int uni_curroffset; int requestedpathlen=0; @@ -727,30 +888,35 @@ static int setup_ver2_dfs_referral(const char *pathname, DEBUG(10,("Setting up version2 referral\nRequested path:\n")); - requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring), - STR_TERMINATE); + requestedpathlen = rpcstr_push(uni_requestedpath, + pathname, sizeof(pstring), + STR_TERMINATE); if (DEBUGLVL(10)) { - dump_data(0, uni_requestedpath,requestedpathlen); + dump_data(0, uni_requestedpath,requestedpathlen); } DEBUG(10,("ref count = %u\n",junction->referral_count)); - uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + + uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION2_REFERRAL_SIZE * junction->referral_count; uni_reqpathoffset2 = uni_reqpathoffset1 + requestedpathlen; uni_curroffset = uni_reqpathoffset2 + requestedpathlen; - reply_size = REFERRAL_HEADER_SIZE + VERSION2_REFERRAL_SIZE*junction->referral_count + - 2 * requestedpathlen; + reply_size = REFERRAL_HEADER_SIZE + + VERSION2_REFERRAL_SIZE*junction->referral_count + + 2 * requestedpathlen; DEBUG(10,("reply_size: %u\n",reply_size)); /* add up the unicode lengths of all the referral paths */ for(i=0;ireferral_count;i++) { - DEBUG(10,("referral %u : %s\n",i,junction->referral_list[i].alternate_path)); - reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; + DEBUG(10,("referral %u : %s\n", + i, + junction->referral_list[i].alternate_path)); + reply_size += + (strlen(junction->referral_list[i].alternate_path)+1)*2; } DEBUG(10,("reply_size = %u\n",reply_size)); @@ -770,9 +936,10 @@ static int setup_ver2_dfs_referral(const char *pathname, /* create the header */ SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ - SSVAL(pdata,2,junction->referral_count); /* number of referral in this pkt */ + /* number of referral in this pkt */ + SSVAL(pdata,2,junction->referral_count); if(self_referral) { - SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); + SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); } else { SIVAL(pdata,4,DFSREF_STORAGE_SERVER); } @@ -790,7 +957,9 @@ static int setup_ver2_dfs_referral(const char *pathname, } else { SSVAL(pdata,offset+4,0); } - SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ + + /* ref_flags :use path_consumed bytes? */ + SSVAL(pdata,offset+6,0); SIVAL(pdata,offset+8,ref->proximity); SIVAL(pdata,offset+12,ref->ttl); @@ -811,41 +980,47 @@ static int setup_ver2_dfs_referral(const char *pathname, } static int setup_ver3_dfs_referral(const char *pathname, - char **ppdata, + char **ppdata, struct junction_map *junction, int consumedcnt, BOOL self_referral) { - char* pdata = *ppdata; + char *pdata = *ppdata; - unsigned char uni_reqpath[1024]; + unsigned char uni_reqpath[sizeof(pstring)]; int uni_reqpathoffset1, uni_reqpathoffset2; int uni_curroffset; int reply_size = 0; int reqpathlen = 0; int offset,i=0; - + DEBUG(10,("setting up version3 referral\n")); - reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE); - + reqpathlen = rpcstr_push(uni_reqpath, pathname, + sizeof(pstring), STR_TERMINATE); + if (DEBUGLVL(10)) { - dump_data(0, uni_reqpath,reqpathlen); + dump_data(0, uni_reqpath,reqpathlen); } - uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count; + uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + + VERSION3_REFERRAL_SIZE * junction->referral_count; uni_reqpathoffset2 = uni_reqpathoffset1 + reqpathlen; reply_size = uni_curroffset = uni_reqpathoffset2 + reqpathlen; for(i=0;ireferral_count;i++) { - DEBUG(10,("referral %u : %s\n",i,junction->referral_list[i].alternate_path)); - reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; + DEBUG(10,("referral %u : %s\n", + i, + junction->referral_list[i].alternate_path)); + reply_size += + (strlen(junction->referral_list[i].alternate_path)+1)*2; } pdata = (char *)SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { - DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); + DEBUG(0,("version3 referral setup:" + "malloc failed for Realloc!\n")); return -1; } *ppdata = pdata; @@ -854,15 +1029,15 @@ static int setup_ver3_dfs_referral(const char *pathname, SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ SSVAL(pdata,2,junction->referral_count); /* number of referral */ if(self_referral) { - SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); + SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); } else { SIVAL(pdata,4,DFSREF_STORAGE_SERVER); } - + /* copy in the reqpaths */ memcpy(pdata+uni_reqpathoffset1,uni_reqpath,reqpathlen); memcpy(pdata+uni_reqpathoffset2,uni_reqpath,reqpathlen); - + offset = 8; for(i=0;ireferral_count;i++) { struct referral* ref = &(junction->referral_list[i]); @@ -876,14 +1051,16 @@ static int setup_ver3_dfs_referral(const char *pathname, SSVAL(pdata,offset+4,0); } - SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ + /* ref_flags :use path_consumed bytes? */ + SSVAL(pdata,offset+6,0); SIVAL(pdata,offset+8,ref->ttl); - + SSVAL(pdata,offset+12,uni_reqpathoffset1-offset); SSVAL(pdata,offset+14,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset,ref->alternate_path, - sizeof(pstring), STR_UNICODE | STR_TERMINATE); + sizeof(pstring), + STR_UNICODE | STR_TERMINATE); SSVAL(pdata,offset+16,uni_curroffset-offset); /* copy 0x10 bytes of 00's in the ServiceSite GUID */ memset(pdata+offset+18,'\0',16); @@ -906,12 +1083,12 @@ int setup_dfs_referral(connection_struct *orig_conn, int max_referral_level, char **ppdata, NTSTATUS *pstatus) { - struct junction_map junction; + struct junction_map *junction = NULL; int consumedcnt = 0; BOOL self_referral = False; int reply_size = 0; char *pathnamep = NULL; - pstring local_dfs_path; + char *local_dfs_path = NULL; TALLOC_CTX *ctx; if (!(ctx=talloc_init("setup_dfs_referral"))) { @@ -919,8 +1096,6 @@ int setup_dfs_referral(connection_struct *orig_conn, return -1; } - ZERO_STRUCT(junction); - /* get the junction entry */ if (!dfs_path) { talloc_destroy(ctx); @@ -928,34 +1103,51 @@ int setup_dfs_referral(connection_struct *orig_conn, return -1; } - /* + /* * Trim pathname sent by client so it begins with only one backslash. * Two backslashes confuse some dfs clients */ - pstrcpy(local_dfs_path, dfs_path); + local_dfs_path = talloc_strdup(ctx,dfs_path); + if (!local_dfs_path) { + *pstatus = NT_STATUS_NO_MEMORY; + talloc_destroy(ctx); + return -1; + } pathnamep = local_dfs_path; - while (IS_DIRECTORY_SEP(pathnamep[0]) && IS_DIRECTORY_SEP(pathnamep[1])) { + while (IS_DIRECTORY_SEP(pathnamep[0]) && + IS_DIRECTORY_SEP(pathnamep[1])) { pathnamep++; } + junction = TALLOC_ZERO_P(ctx, struct junction_map); + if (!junction) { + *pstatus = NT_STATUS_NO_MEMORY; + talloc_destroy(ctx); + return -1; + } + /* The following call can change cwd. */ - *pstatus = get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral); + *pstatus = get_referred_path(ctx, pathnamep, junction, + &consumedcnt, &self_referral); if (!NT_STATUS_IS_OK(*pstatus)) { vfs_ChDir(orig_conn,orig_conn->connectpath); talloc_destroy(ctx); return -1; } vfs_ChDir(orig_conn,orig_conn->connectpath); - + if (!self_referral) { pathnamep[consumedcnt] = '\0'; if( DEBUGLVL( 3 ) ) { int i=0; - dbgtext("setup_dfs_referral: Path %s to alternate path(s):",pathnamep); - for(i=0;ireferral_count;i++) + dbgtext(" %s", + junction->referral_list[i].alternate_path); dbgtext(".\n"); } } @@ -972,20 +1164,23 @@ int setup_dfs_referral(connection_struct *orig_conn, switch(max_referral_level) { case 2: - reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, &junction, - consumedcnt, self_referral); + reply_size = setup_ver2_dfs_referral(pathnamep, + ppdata, junction, + consumedcnt, self_referral); break; case 3: - reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, &junction, - consumedcnt, self_referral); + reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, + junction, consumedcnt, self_referral); break; default: - DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); + DEBUG(0,("setup_dfs_referral: Invalid dfs referral " + "version: %d\n", + max_referral_level)); talloc_destroy(ctx); *pstatus = NT_STATUS_INVALID_LEVEL; return -1; } - + if (DEBUGLVL(10)) { DEBUGADD(0,("DFS Referral pdata:\n")); dump_data(0,(uint8 *)*ppdata,reply_size); @@ -1004,73 +1199,87 @@ int setup_dfs_referral(connection_struct *orig_conn, Creates a junction structure from a DFS pathname **********************************************************************/ -BOOL create_junction(const char *dfs_path, struct junction_map *jucn) +BOOL create_junction(TALLOC_CTX *ctx, + const char *dfs_path, + struct junction_map *jucn) { int snum; BOOL dummy; - struct dfs_path dp; - - NTSTATUS status = parse_dfs_path(dfs_path, False, &dp, &dummy); + struct dfs_path *pdp = TALLOC_P(ctx,struct dfs_path); + NTSTATUS status; + if (!pdp) { + return False; + } + status = parse_dfs_path(dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return False; } /* check if path is dfs : validate first token */ - if (!is_myname_or_ipaddr(dp.hostname)) { - DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", - dp.hostname, dfs_path)); + if (!is_myname_or_ipaddr(pdp->hostname)) { + DEBUG(4,("create_junction: Invalid hostname %s " + "in dfs path %s\n", + pdp->hostname, dfs_path)); + TALLOC_FREE(pdp); return False; } /* Check for a non-DFS share */ - snum = lp_servicenumber(dp.servicename); + snum = lp_servicenumber(pdp->servicename); if(snum < 0 || !lp_msdfs_root(snum)) { DEBUG(4,("create_junction: %s is not an msdfs root.\n", - dp.servicename)); + pdp->servicename)); + TALLOC_FREE(pdp); return False; } - fstrcpy(jucn->service_name,dp.servicename); - pstrcpy(jucn->volume_name,dp.reqpath); - pstrcpy(jucn->comment, lp_comment(snum)); + jucn->service_name = talloc_strdup(ctx, pdp->servicename); + jucn->volume_name = talloc_strdup(ctx, pdp->reqpath); + jucn->comment = talloc_strdup(ctx, lp_comment(snum)); + + TALLOC_FREE(pdp); + if (!jucn->service_name || !jucn->volume_name || ! jucn->comment) { + return False; + } return True; } /********************************************************************** - Forms a valid Unix pathname from the junction + Forms a valid Unix pathname from the junction **********************************************************************/ -static BOOL junction_to_local_path(struct junction_map *jucn, - char *path, - int max_pathlen, +static BOOL junction_to_local_path(const struct junction_map *jucn, + char **pp_path_out, connection_struct *conn_out) { int snum; - pstring conn_path; snum = lp_servicenumber(jucn->service_name); if(snum < 0) { return False; } - - safe_strcpy(path, lp_pathname(snum), max_pathlen-1); - safe_strcat(path, "/", max_pathlen-1); - safe_strcat(path, jucn->volume_name, max_pathlen-1); - - pstrcpy(conn_path, lp_pathname(snum)); - if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, conn_path))) { + if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, + lp_pathname(snum)))) { return False; } + *pp_path_out = talloc_asprintf(conn_out->mem_ctx, + "%s/%s", + lp_pathname(snum), + jucn->volume_name); + if (!*pp_path_out) { + return False; + } return True; } -BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) +BOOL create_msdfs_link(const struct junction_map *jucn, + BOOL exists) { - pstring path; - pstring msdfs_link; + char *path = NULL; + char *msdfs_link = NULL; connection_struct conns; connection_struct *conn = &conns; int i=0; @@ -1079,15 +1288,19 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) ZERO_STRUCT(conns); - if(!junction_to_local_path(jucn, path, sizeof(path), conn)) { + if(!junction_to_local_path(jucn, &path, conn)) { return False; } - + /* Form the msdfs_link contents */ - pstrcpy(msdfs_link, "msdfs:"); + msdfs_link = talloc_strdup(conn->mem_ctx, "msdfs:"); + if (!msdfs_link) { + goto out; + } for(i=0; ireferral_count; i++) { - char* refpath = jucn->referral_list[i].alternate_path; - + char *old_msdfs_link = msdfs_link; + char *refpath = jucn->referral_list[i].alternate_path; + /* Alternate paths always use Windows separators. */ trim_char(refpath, '\\', '\\'); if(*refpath == '\0') { @@ -1097,10 +1310,21 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) continue; } if (i > 0 && insert_comma) { - pstrcat(msdfs_link, ","); + msdfs_link = talloc_asprintf(conn->mem_ctx, + "%s,%s", + old_msdfs_link, + refpath); + } else { + msdfs_link = talloc_asprintf(conn->mem_ctx, + "%s%s", + old_msdfs_link, + refpath); } - pstrcat(msdfs_link, refpath); + if (!msdfs_link) { + goto out; + } + TALLOC_FREE(old_msdfs_link); if (!insert_comma) { insert_comma = True; } @@ -1116,12 +1340,12 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) } if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { - DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n", - path, msdfs_link, strerror(errno))); + DEBUG(1,("create_msdfs_link: symlink failed " + "%s -> %s\nError: %s\n", + path, msdfs_link, strerror(errno))); goto out; } - - + ret = True; out: @@ -1130,47 +1354,105 @@ out: return ret; } -BOOL remove_msdfs_link(struct junction_map *jucn) +BOOL remove_msdfs_link(const struct junction_map *jucn) { - pstring path; + char *path = NULL; connection_struct conns; connection_struct *conn = &conns; BOOL ret = False; ZERO_STRUCT(conns); - if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { + if( junction_to_local_path(jucn, &path, conn) ) { if( SMB_VFS_UNLINK(conn, path) == 0 ) { ret = True; } - talloc_destroy( conn->mem_ctx ); } conn_free_internal(conn); return ret; } +/********************************************************************* + Return the number of DFS links at the root of this share. +*********************************************************************/ + +static int count_dfs_links(TALLOC_CTX *ctx, int snum) +{ + size_t cnt = 0; + SMB_STRUCT_DIR *dirp = NULL; + char *dname = NULL; + const char *connect_path = lp_pathname(snum); + const char *msdfs_proxy = lp_msdfs_proxy(snum); + connection_struct conn; + + ZERO_STRUCT(conn); + + if(*connect_path == '\0') { + return 0; + } + + /* + * Fake up a connection struct for the VFS layer. + */ + + if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { + return 0; + } + + /* Count a link for the msdfs root - convention */ + cnt = 1; + + /* No more links if this is an msdfs proxy. */ + if (*msdfs_proxy != '\0') { + goto out; + } + + /* Now enumerate all dfs links */ + dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); + if(!dirp) { + goto out; + } + + while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + if (is_msdfs_link(&conn, + dname, + NULL)) { + cnt++; + } + } + + SMB_VFS_CLOSEDIR(&conn,dirp); + +out: + + conn_free_internal(&conn); + return cnt; +} + +/********************************************************************* +*********************************************************************/ + static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, - int jn_remain) + size_t jn_remain) { - int cnt = 0; - SMB_STRUCT_DIR *dirp; - char *dname; - pstring connect_path; + size_t cnt = 0; + SMB_STRUCT_DIR *dirp = NULL; + char *dname = NULL; + const char *connect_path = lp_pathname(snum); char *service_name = lp_servicename(snum); + const char *msdfs_proxy = lp_msdfs_proxy(snum); connection_struct conn; struct referral *ref = NULL; - + ZERO_STRUCT(conn); - if (jn_remain <= 0) { + if (jn_remain == 0) { return 0; } - pstrcpy(connect_path,lp_pathname(snum)); - if(*connect_path == '\0') { return 0; } @@ -1183,33 +1465,44 @@ static int form_junctions(TALLOC_CTX *ctx, return 0; } - /* form a junction for the msdfs root - convention + /* form a junction for the msdfs root - convention DO NOT REMOVE THIS: NT clients will not work with us if this is not present - */ - fstrcpy(jucn[cnt].service_name, service_name); - jucn[cnt].volume_name[0] = '\0'; + */ + jucn[cnt].service_name = talloc_strdup(ctx,service_name); + jucn[cnt].volume_name = talloc_strdup(ctx, ""); + if (!jucn[cnt].service_name || jucn[cnt].volume_name) { + goto out; + } jucn[cnt].referral_count = 1; ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral); if (jucn[cnt].referral_list == NULL) { - DEBUG(0, ("talloc failed!\n")); goto out; } ref->proximity = 0; ref->ttl = REFERRAL_TTL; - if (*lp_msdfs_proxy(snum) != '\0') { - pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); - cnt++; - goto out; - } - - pstr_sprintf(ref->alternate_path, "\\\\%s\\%s", + if (*msdfs_proxy != '\0') { + ref->alternate_path = talloc_strdup(ctx, + msdfs_proxy); + } else { + ref->alternate_path = talloc_asprintf(ctx, + "\\\\%s\\%s", get_local_machine_name(), service_name); + } + + if (!ref->alternate_path) { + goto out; + } cnt++; + /* Don't enumerate if we're an msdfs proxy. */ + if (*msdfs_proxy != '\0') { + goto out; + } + /* Now enumerate all dfs links */ dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); if(!dirp) { @@ -1217,41 +1510,55 @@ static int form_junctions(TALLOC_CTX *ctx, } while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { - pstring link_target; + char *link_target = NULL; if (cnt >= jn_remain) { SMB_VFS_CLOSEDIR(&conn,dirp); - DEBUG(2, ("ran out of MSDFS junction slots")); + DEBUG(2, ("form_junctions: ran out of MSDFS " + "junction slots")); goto out; } - if (is_msdfs_link(&conn, dname, link_target, NULL)) { + if (is_msdfs_link_internal(ctx, + &conn, + dname, &link_target, + NULL)) { if (parse_msdfs_symlink(ctx, link_target, &jucn[cnt].referral_list, &jucn[cnt].referral_count)) { - fstrcpy(jucn[cnt].service_name, service_name); - pstrcpy(jucn[cnt].volume_name, dname); + jucn[cnt].service_name = talloc_strdup(ctx, + service_name); + jucn[cnt].volume_name = talloc_strdup(ctx, + dname); + if (!jucn[cnt].service_name || + !jucn[cnt].volume_name) { + goto out; + } cnt++; } } } - - SMB_VFS_CLOSEDIR(&conn,dirp); out: + if (dirp) { + SMB_VFS_CLOSEDIR(&conn,dirp); + } + conn_free_internal(&conn); return cnt; } -int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) +struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) { + struct junction_map *jn = NULL; int i=0; + size_t jn_count; int sharecount = 0; - int jn_count = 0; + *p_num_jn = 0; if(!lp_host_msdfs()) { - return 0; + return NULL; } /* Ensure all the usershares are loaded. */ @@ -1260,24 +1567,57 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) sharecount = load_usershare_shares(); unbecome_root(); - for(i=0;i < sharecount && (jn_max - jn_count) > 0;i++) { + for(i=0;i < sharecount;i++) { if(lp_msdfs_root(i)) { - jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); + jn_count += count_dfs_links(ctx, i); } } - return jn_count; + if (jn_count == 0) { + return NULL; + } + jn = TALLOC_ARRAY(ctx, struct junction_map, jn_count); + if (!jn) { + return NULL; + } + for(i=0; i < sharecount; i++) { + if (*p_num_jn >= jn_count) { + break; + } + if(lp_msdfs_root(i)) { + *p_num_jn += form_junctions(ctx, i, + &jn[*p_num_jn], + jn_count - *p_num_jn); + } + } + return jn; } /****************************************************************************** Core function to resolve a dfs pathname. ******************************************************************************/ -NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) +NTSTATUS resolve_dfspath(TALLOC_CTX *ctx, + connection_struct *conn, + BOOL dfs_pathnames, + const char *name_in, + char **pp_name_out) { NTSTATUS status = NT_STATUS_OK; BOOL dummy; if (dfs_pathnames) { - status = dfs_redirect(conn, name, False, &dummy); + status = dfs_redirect(ctx, + conn, + name_in, + False, + pp_name_out, + &dummy); + } else { + /* + * Cheat and just return a copy of the in ptr. + * Once srvstr_get_path() uses talloc it'll + * be a talloced ptr anyway. + */ + *pp_name_out = CONST_DISCARD(char *,name_in); } return status; } @@ -1289,11 +1629,28 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na we're allowing wildcards and when we're not. JRA. ******************************************************************************/ -NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard) +NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx, + connection_struct *conn, + BOOL dfs_pathnames, + const char *name_in, + char **pp_name_out, + BOOL *ppath_contains_wcard) { NTSTATUS status = NT_STATUS_OK; if (dfs_pathnames) { - status = dfs_redirect(conn, name, True, ppath_contains_wcard); + status = dfs_redirect(ctx, + conn, + name_in, + True, + pp_name_out, + ppath_contains_wcard); + } else { + /* + * Cheat and just return a copy of the in ptr. + * Once srvstr_get_path() uses talloc it'll + * be a talloced ptr anyway. + */ + *pp_name_out = CONST_DISCARD(char *,name_in); } return status; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 735c147b8d..114050ae16 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -514,6 +514,7 @@ void reply_ntcreate_and_X(connection_struct *conn, BOOL extended_oplock_granted = False; NTSTATUS status; struct case_semantics_state *case_state = NULL; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBntcreateX); @@ -682,12 +683,15 @@ void reply_ntcreate_and_X(connection_struct *conn, return; } } - + /* - * Now contruct the smb_open_mode value from the filename, + * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -718,7 +722,7 @@ void reply_ntcreate_and_X(connection_struct *conn, file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); reply_nterror(req, status); @@ -1242,11 +1246,11 @@ static void call_nt_transact_create(connection_struct *conn, struct timespec a_timespec; struct timespec m_timespec; struct ea_list *ea_list = NULL; - TALLOC_CTX *ctx = NULL; char *pdata = NULL; NTSTATUS status; size_t param_len; struct case_semantics_state *case_state = NULL; + TALLOC_CTX *ctx = talloc_tos(); DEBUG(5,("call_nt_transact_create\n")); @@ -1424,8 +1428,10 @@ static void call_nt_transact_create(connection_struct *conn, file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1437,7 +1443,7 @@ static void call_nt_transact_create(connection_struct *conn, return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); reply_nterror(req, status); @@ -1594,7 +1600,6 @@ static void call_nt_transact_create(connection_struct *conn, status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION); if (!NT_STATUS_IS_OK(status)) { - talloc_destroy(ctx); close_file(fsp,ERROR_CLOSE); TALLOC_FREE(case_state); reply_nterror(req, status); @@ -1918,14 +1923,17 @@ static NTSTATUS copy_internals(connection_struct *conn, void reply_ntrename(connection_struct *conn, struct smb_request *req) { - pstring oldname; - pstring newname; + pstring oldname_in; + pstring newname_in; + char *oldname = NULL; + char *newname = NULL; char *p; NTSTATUS status; BOOL src_has_wcard = False; BOOL dest_has_wcard = False; uint32 attrs; uint16 rename_type; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBntrename); @@ -1939,8 +1947,8 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) rename_type = SVAL(req->inbuf,smb_vwv1); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, oldname, p, - sizeof(oldname), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, oldname_in, p, + sizeof(oldname_in), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1948,31 +1956,33 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) return; } - if( is_ntfs_stream_name(oldname)) { + if( is_ntfs_stream_name(oldname_in)) { /* Can't rename a stream. */ reply_nterror(req, NT_STATUS_ACCESS_DENIED); END_PROFILE(SMBntrename); return; } - if (ms_has_wild(oldname)) { + if (ms_has_wild(oldname_in)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); END_PROFILE(SMBntrename); return; } p++; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p, - sizeof(newname), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p, + sizeof(newname_in), 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBntrename); return; } - - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - oldname); + + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + oldname_in, + &oldname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1985,8 +1995,10 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + newname_in, + &newname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2000,7 +2012,7 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) } DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); - + switch(rename_type) { case RENAME_FLAG_RENAME: status = rename_internals(conn, req, oldname, newname, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e3c3e8dff0..672c683309 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -452,6 +452,7 @@ void reply_tcon(connection_struct *conn, struct smb_request *req) NTSTATUS nt_status; char *p; DATA_BLOB password_blob; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBtcon); @@ -462,12 +463,12 @@ void reply_tcon(connection_struct *conn, struct smb_request *req) } p = smb_buf(req->inbuf)+1; - p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, + p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &service_buf, p, STR_TERMINATE) + 1; - pwlen = srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, + pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &password, p, STR_TERMINATE) + 1; p += pwlen; - p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, + p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &dev, p, STR_TERMINATE) + 1; if (service_buf == NULL || password == NULL || dev == NULL) { @@ -515,8 +516,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) { char *service = NULL; DATA_BLOB password; - - TALLOC_CTX *ctx = NULL; + TALLOC_CTX *ctx = talloc_tos(); /* what the cleint thinks the device is */ char *client_devicetype = NULL; /* what the server tells the client the share represents */ @@ -567,19 +567,11 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) p = smb_buf(req->inbuf) + passlen + 1; } - ctx = talloc_init("reply_tcon_and_X"); - if (!ctx) { - data_blob_clear_free(&password); - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBtconX); - return; - } p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p, STR_TERMINATE); if (path == NULL) { data_blob_clear_free(&password); - TALLOC_FREE(ctx); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtconX); return; @@ -593,7 +585,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) q = strchr_m(path+2,'\\'); if (!q) { data_blob_clear_free(&password); - TALLOC_FREE(ctx); reply_doserror(req, ERRDOS, ERRnosuchshare); END_PROFILE(SMBtconX); return; @@ -609,7 +600,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) if (client_devicetype == NULL) { data_blob_clear_free(&password); - TALLOC_FREE(ctx); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtconX); return; @@ -623,7 +613,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) data_blob_clear_free(&password); if (!conn) { - TALLOC_FREE(ctx); reply_nterror(req, nt_status); END_PROFILE(SMBtconX); return; @@ -640,7 +629,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) reply_outbuf(req, 2, 0); if (message_push_string(&req->outbuf, server_devicetype, STR_TERMINATE|STR_ASCII) == -1) { - TALLOC_FREE(ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtconX); return; @@ -675,7 +663,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) STR_TERMINATE|STR_ASCII) == -1) || (message_push_string(&req->outbuf, fstype, STR_TERMINATE) == -1)) { - TALLOC_FREE(ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtconX); return; @@ -697,7 +684,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) SSVAL(req->inbuf,smb_tid,conn->cnum); SSVAL(req->outbuf,smb_tid,conn->cnum); - TALLOC_FREE(ctx); END_PROFILE(SMBtconX); chain_reply(req); @@ -827,6 +813,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) char *name = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBcheckpath); @@ -840,7 +827,10 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + name_in, + &name); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -853,7 +843,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) DEBUG(3,("reply_checkpath %s mode=%d\n", name_in, (int)SVAL(req->inbuf,smb_vwv0))); - status = unix_convert(conn, name_in, False, &name, NULL, &sbuf); + status = unix_convert(conn, name, False, &name, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { goto path_err; } @@ -922,6 +912,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) time_t mtime=0; char *p; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBgetatr); @@ -934,8 +925,10 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -947,10 +940,10 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBgetatr); return; } - + /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ - if (*fname_in == '\0') { + if (*fname == '\0') { mode = aHIDDEN | aDIR; if (!CAN_WRITE(conn)) { mode |= aRONLY; @@ -958,7 +951,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) size = 0; mtime = 0; } else { - status = unix_convert(conn, fname_in, False, &fname, NULL,&sbuf); + status = unix_convert(conn, fname, False, &fname, NULL,&sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBgetatr); @@ -1020,6 +1013,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) SMB_STRUCT_STAT sbuf; char *p; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBsetatr); @@ -1037,8 +1031,10 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1051,7 +1047,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBsetatr); @@ -1175,7 +1171,8 @@ void reply_search(connection_struct *conn, struct smb_request *req) BOOL finished = False; char *p; int status_len; - pstring path; + pstring path_in; + char *path = NULL; char status[21]; int dptr_num= -1; BOOL check_descend = False; @@ -1183,6 +1180,7 @@ void reply_search(connection_struct *conn, struct smb_request *req) NTSTATUS nt_status; BOOL mask_contains_wcard = False; BOOL allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBsearch); @@ -1209,8 +1207,8 @@ void reply_search(connection_struct *conn, struct smb_request *req) maxentries = SVAL(req->inbuf,smb_vwv0); dirtype = SVAL(req->inbuf,smb_vwv1); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p, - sizeof(path), 0, STR_TERMINATE, &nt_status, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path_in, p, + sizeof(path_in), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); @@ -1218,9 +1216,11 @@ void reply_search(connection_struct *conn, struct smb_request *req) return; } - nt_status = resolve_dfspath_wcard(conn, + nt_status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - path, &mask_contains_wcard); + path_in, + &path, + &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1232,11 +1232,11 @@ void reply_search(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBsearch); return; } - + p++; status_len = SVAL(p, 0); p += 2; - + /* dirtype &= ~aDIR; */ if (status_len == 0) { @@ -1512,6 +1512,7 @@ void reply_open(connection_struct *conn, struct smb_request *req) uint32 create_disposition; uint32 create_options = 0; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBopen); @@ -1520,7 +1521,7 @@ void reply_open(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBopen); return; } - + oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); deny_mode = SVAL(req->inbuf,smb_vwv0); dos_attr = SVAL(req->inbuf,smb_vwv1); @@ -1534,8 +1535,10 @@ void reply_open(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1548,7 +1551,7 @@ void reply_open(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopen); @@ -1658,6 +1661,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) uint32 share_mode; uint32 create_disposition; uint32 create_options = 0; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBopenX); @@ -1697,8 +1701,10 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1710,7 +1716,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopenX); @@ -1889,6 +1895,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; uint32 create_disposition; uint32 create_options = 0; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBcreate); @@ -1915,8 +1922,10 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1928,7 +1937,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcreate); @@ -2014,6 +2023,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) SMB_STRUCT_STAT sbuf; char *s; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBctemp); @@ -2040,8 +2050,10 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) pstrcat(fname_in,"TMXXXXXX"); } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2054,20 +2066,20 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); return; } - status = check_name(conn, fname); + status = check_name(conn, CONST_DISCARD(char *,fname)); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); return; } - + tmpfd = smb_mkstemp(fname); if (tmpfd == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); @@ -2446,10 +2458,12 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, void reply_unlink(connection_struct *conn, struct smb_request *req) { - pstring name; + pstring name_in; + char *name = NULL; uint32 dirtype; NTSTATUS status; BOOL path_contains_wcard = False; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBunlink); @@ -2460,9 +2474,9 @@ void reply_unlink(connection_struct *conn, struct smb_request *req) } dirtype = SVAL(req->inbuf,smb_vwv0); - - srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, - smb_buf(req->inbuf) + 1, sizeof(name), 0, + + srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, + smb_buf(req->inbuf) + 1, sizeof(name_in), 0, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -2470,9 +2484,11 @@ void reply_unlink(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath_wcard(conn, + status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name, &path_contains_wcard); + name_in, + &name, + &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2484,9 +2500,9 @@ void reply_unlink(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBunlink); return; } - + DEBUG(3,("reply_unlink : %s\n",name)); - + status = unlink_internals(conn, req, dirtype, name, path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -4633,7 +4649,7 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req) } DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); - + END_PROFILE(SMBsplwr); return; } @@ -4648,9 +4664,10 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) char *directory = NULL; NTSTATUS status; SMB_STRUCT_STAT sbuf; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBmkdir); - + srvstr_get_path((char *)req->inbuf, req->flags2, directory_in, smb_buf(req->inbuf) + 1, sizeof(directory_in), 0, STR_TERMINATE, &status); @@ -4660,9 +4677,10 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, + status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - directory_in); + directory_in, + &directory); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -4675,7 +4693,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf); + status = unix_convert(conn, directory, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBmkdir); @@ -4902,6 +4920,8 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) char *directory = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); + START_PROFILE(SMBrmdir); srvstr_get_path((char *)req->inbuf, req->flags2, directory_in, @@ -4913,9 +4933,10 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(conn, + status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - directory_in); + directory_in, + &directory); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -4928,14 +4949,14 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, directory_in, False, &directory, + status = unix_convert(conn, directory, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBrmdir); return; } - + status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -5662,13 +5683,16 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, void reply_mv(connection_struct *conn, struct smb_request *req) { - pstring name; - pstring newname; + pstring name_in; + pstring newname_in; + char *name = NULL; + char *newname = NULL; char *p; uint32 attrs; NTSTATUS status; BOOL src_has_wcard = False; BOOL dest_has_wcard = False; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBmv); @@ -5681,8 +5705,8 @@ void reply_mv(connection_struct *conn, struct smb_request *req) attrs = SVAL(req->inbuf,smb_vwv0); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p, - sizeof(name), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, p, + sizeof(name_in), 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -5690,18 +5714,20 @@ void reply_mv(connection_struct *conn, struct smb_request *req) return; } p++; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p, - sizeof(newname), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p, + sizeof(newname_in), 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBmv); return; } - - status = resolve_dfspath_wcard(conn, + + status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name, &src_has_wcard); + name_in, + &name, + &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5714,9 +5740,11 @@ void reply_mv(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath_wcard(conn, + status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname, &dest_has_wcard); + newname_in, + &newname, + &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5728,9 +5756,9 @@ void reply_mv(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBmv); return; } - + DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - + status = rename_internals(conn, req, name, newname, attrs, False, src_has_wcard, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -5745,7 +5773,7 @@ void reply_mv(connection_struct *conn, struct smb_request *req) } reply_outbuf(req, 0, 0); - + END_PROFILE(SMBmv); return; } @@ -5893,6 +5921,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) BOOL dest_has_wild = False; SMB_STRUCT_STAT sbuf1, sbuf2; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBcopy); @@ -5925,9 +5954,9 @@ void reply_copy(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBcopy); return; } - + DEBUG(3,("reply_copy : %s -> %s\n",name_in,newname_in)); - + if (tid2 != conn->cnum) { /* can't currently handle inter share copies XXXX */ DEBUG(3,("Rejecting inter-share copy\n")); @@ -5936,9 +5965,11 @@ void reply_copy(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath_wcard(conn, + status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name_in, &source_has_wild); + name_in, + &name, + &source_has_wild); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5951,9 +5982,11 @@ void reply_copy(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath_wcard(conn, + status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname_in, &dest_has_wild); + newname_in, + &newname, + &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5966,14 +5999,14 @@ void reply_copy(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, name_in, source_has_wild, &name, NULL, &sbuf1); + status = unix_convert(conn, name, source_has_wild, &name, NULL, &sbuf1); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); return; } - status = unix_convert(conn, newname_in, dest_has_wild, &newname, NULL, &sbuf2); + status = unix_convert(conn, newname, dest_has_wild, &newname, NULL, &sbuf2); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 59f384e8b0..2ba0781e62 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1268,14 +1268,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, continue; } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { - pstring link_target; - - /* Needed to show the msdfs symlinks as + /* Needed to show the msdfs symlinks as * directories */ - if(lp_host_msdfs() && + if(lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) { + ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) { DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s " "as a directory\n", pathreal)); @@ -1778,6 +1776,7 @@ static void call_trans2findfirst(connection_struct *conn, TALLOC_CTX *ea_ctx = NULL; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; + TALLOC_CTX *ctx = talloc_tos(); if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -1835,7 +1834,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return; } - ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory_in, &mask_contains_wcard); + ntstatus = resolve_dfspath_wcard(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + directory_in, + &directory, + &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1846,7 +1849,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return; } - ntstatus = unix_convert(conn, directory_in, True, &directory, NULL, &sbuf); + ntstatus = unix_convert(conn, directory, True, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); return; @@ -3524,6 +3527,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ char *lock_data = NULL; + TALLOC_CTX *ctx = NULL; if (!params) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -3642,9 +3646,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - status = resolve_dfspath(conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + status = resolve_dfspath(ctx, + conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -3655,7 +3661,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -4431,8 +4437,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd ****************************************************************************/ NTSTATUS hardlink_internals(connection_struct *conn, - char *oldname_in, - char *newname_in) + const char *oldname_in, + const char *newname_in) { SMB_STRUCT_STAT sbuf1, sbuf2; char *last_component_oldname = NULL; @@ -4889,9 +4895,11 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, struct smb_request *req, const char *pdata, int total_data, - pstring fname) + const char *fname) { - pstring oldname; + pstring oldname_in; + char *oldname = NULL; + TALLOC_CTX *ctx = talloc_tos(); NTSTATUS status = NT_STATUS_OK; /* Set a hard link. */ @@ -4899,14 +4907,16 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path(pdata, req->flags2, oldname, pdata, - sizeof(oldname), total_data, STR_TERMINATE, &status); + srvstr_get_path(pdata, req->flags2, oldname_in, pdata, + sizeof(oldname_in), total_data, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return status; } - status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - oldname); + status = resolve_dfspath(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + oldname_in, + &oldname); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4932,10 +4942,12 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, uint32 root_fid; uint32 len; pstring newname_in; + char *newname = NULL; pstring base_name; BOOL dest_has_wcard = False; NTSTATUS status = NT_STATUS_OK; char *p; + TALLOC_CTX *ctx = talloc_tos(); if (total_data < 13) { return NT_STATUS_INVALID_PARAMETER; @@ -4956,15 +4968,17 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return status; } - status = resolve_dfspath_wcard(conn, + status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname_in, &dest_has_wcard); + newname_in, + &newname, + &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; } /* Check the new name has no '/' characters. */ - if (strchr_m(newname_in, '/')) { + if (strchr_m(newname, '/')) { return NT_STATUS_NOT_SUPPORTED; } @@ -4977,16 +4991,15 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, pstrcpy(base_name, "./"); } /* Append the new name. */ - pstrcat(base_name, newname_in); + pstrcat(base_name, newname); if (fsp) { SMB_STRUCT_STAT sbuf; - char *newname = NULL; char *newname_last_component = NULL; ZERO_STRUCT(sbuf); - status = unix_convert(conn, newname_in, False, + status = unix_convert(conn, newname, False, &newname, &newname_last_component, &sbuf); @@ -6171,6 +6184,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, files_struct *fsp = NULL; NTSTATUS status = NT_STATUS_OK; int data_return_size = 0; + TALLOC_CTX *ctx = talloc_tos(); if (!params) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -6268,9 +6282,10 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - status = resolve_dfspath(conn, + status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in); + fname_in, + &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -6282,7 +6297,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; -- cgit From 327ca9167ed28d2207444a93424cadef79d166b5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Sep 2007 19:27:34 +0000 Subject: r25103: Ensure we don't return unwritten memory (valgrind caught). Jeremy. (This used to be commit b3f0d39d11fa18b7bfef6cec88efaf4a2be2d6e0) --- source3/smbd/ipc.c | 12 +++-- source3/smbd/lanman.c | 135 +++++++++++++++++++++++++++----------------------- 2 files changed, 83 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 2403706929..0709acc756 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -54,9 +54,10 @@ static void copy_trans_params_and_data(char *outbuf, int align, if(data_len < 0) data_len = 0; - DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", + DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d] (align %d)\n", param_offset, param_offset + param_len, - data_offset , data_offset + data_len)); + data_offset , data_offset + data_len, + align)); *copy_into = '\0'; @@ -65,7 +66,12 @@ static void copy_trans_params_and_data(char *outbuf, int align, if (param_len) memcpy(copy_into, &rparam[param_offset], param_len); - copy_into += param_len + align; + copy_into += param_len; + if (align) { + memset(copy_into, '\0', align); + } + + copy_into += align; if (data_len ) memcpy(copy_into, &rdata[data_offset], data_len); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 9eb2a283cc..37fcc658db 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -50,6 +50,20 @@ extern userdom_struct current_user_info; #define SHPWLEN 8 /* share password length */ +/* Limit size of ipc replies */ + +static char *smb_realloc_limit(void *ptr, size_t size) +{ + char *val; + + size = MAX((size),4*1024); + val = (char *)SMB_REALLOC(ptr,size); + if (val) { + memset(val,'\0',size); + } + return val; +} + static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, @@ -824,7 +838,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, */ *rdata_len = 0; *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -846,7 +860,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { SAFE_FREE(queue); return False; @@ -879,7 +893,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { SAFE_FREE(queue); SAFE_FREE(tmpdata); @@ -940,7 +954,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, */ *rdata_len = 0; *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -982,7 +996,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { goto err; } @@ -1008,7 +1022,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { goto err; } @@ -1381,11 +1395,10 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, } *rdata_len = fixed_len + string_len; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } - memset(*rdata,'\0',*rdata_len); p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ p = *rdata; @@ -1411,7 +1424,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, } *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -1460,7 +1473,7 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, *rdata_len = 0; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -1652,7 +1665,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, return False; } - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -1663,7 +1676,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, } *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -1746,12 +1759,11 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, } *rdata_len = fixed_len + string_len; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } - memset(*rdata,0,*rdata_len); - + p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */ p = *rdata; f_len = fixed_len; @@ -1772,7 +1784,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, } *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -1902,7 +1914,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, } *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -1916,7 +1928,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, error_exit: *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -1990,7 +2002,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, unbecome_root(); *rdata_len = cli_buf_size; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } @@ -2020,7 +2032,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, *rdata_len = PTR_DIFF(p,*rdata); *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2066,16 +2078,16 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, } *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } - + /* check it's a supported varient */ - + if ( strcmp(str1,"zWrLeh") != 0 ) return False; - + switch( uLevel ) { case 0: level_string = "B21"; @@ -2088,10 +2100,11 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, return False; *rdata_len = mdrcnt + 1024; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } + SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -2213,7 +2226,7 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, resume_context, cli_buf_size)); *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2223,7 +2236,7 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, return False; *rdata_len = cli_buf_size; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } @@ -2291,13 +2304,13 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *p; *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } *rdata_len = 21; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } @@ -2381,7 +2394,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, memcpy(pass2,p+16,16); *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2458,7 +2471,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, fstring user; char *p = get_safe_str_ptr(param,tpscnt,param,2); *rparam_len = 2; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2561,7 +2574,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, return(False); *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2633,7 +2646,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, return(False); *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2731,7 +2744,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2856,7 +2869,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, } *rdata_len = mdrcnt; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } @@ -2915,7 +2928,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, *rdata_len = PTR_DIFF(p2,*rdata); *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2950,7 +2963,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, DEBUG(4,("NetWkstaGetInfo level %d\n",level)); *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -2961,7 +2974,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, } *rdata_len = mdrcnt + 1024; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } @@ -3227,7 +3240,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, } *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -3252,7 +3265,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, } *rdata_len = mdrcnt + 1024; - *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + *rdata = smb_realloc_limit(*rdata,*rdata_len); if (!*rdata) { return False; } @@ -3462,7 +3475,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, return False; } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -3504,7 +3517,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -3551,7 +3564,7 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, } *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -3623,7 +3636,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -3649,7 +3662,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, } *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -3719,7 +3732,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, count = print_queue_status(snum,&queue,&status); if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -3740,7 +3753,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -3867,7 +3880,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, desc.neededlen = 0; } else { if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -3888,7 +3901,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, } *rparam_len = 6; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -3944,7 +3957,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -3969,7 +3982,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -4016,7 +4029,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -4032,7 +4045,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -4078,7 +4091,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -4095,7 +4108,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -4142,7 +4155,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, } if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -4160,7 +4173,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -4217,7 +4230,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, num_sessions = list_sessions(talloc_tos(), &session_list); if (mdrcnt > 0) { - *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; } @@ -4245,7 +4258,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, *rdata_len = desc.usedlen; *rparam_len = 8; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -4269,7 +4282,7 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char int *rdata_len, int *rparam_len) { *rparam_len = MIN(*rparam_len,mprcnt); - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } @@ -4295,7 +4308,7 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, int *rdata_len, int *rparam_len) { *rparam_len = 4; - *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { return False; } -- cgit From 3a9d3821649c9ea88a6cd424f0838a453165a00a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Sep 2007 23:57:59 +0000 Subject: r25111: Move to talloced pathnames on most code paths. There are now ony 17 pstrings left in reply.c, and these will be easy to remove (and I'll be doing that shortly). Had to fix an interesting bug in pull_ucs2_base_talloc() when a source string is not null terminated :-). Jeremy. (This used to be commit 0c9a8c4dff10974dbffd2a302ae982896122fcc0) --- source3/smbd/dir.c | 13 +- source3/smbd/filename.c | 3 +- source3/smbd/msdfs.c | 16 +-- source3/smbd/nttrans.c | 376 ++++++++++++++++++++++++++---------------------- source3/smbd/reply.c | 249 +++++++++++++++++++------------- source3/smbd/trans2.c | 106 +++++++------- 6 files changed, 423 insertions(+), 340 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index b21e6501d6..7a6815b680 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -752,8 +752,9 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) return True; } -static BOOL mangle_mask_match(connection_struct *conn, const char *filename, - char *mask) +static BOOL mangle_mask_match(connection_struct *conn, + const char *filename, + const char *mask) { char mname[13]; @@ -791,11 +792,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd))); - - if (dname == NULL) + + if (dname == NULL) return(False); - - pstrcpy(filename,dname); + + pstrcpy(filename,dname); /* notice the special *.* handling. This appears to be the only difference between the wildcard handling in this routine and in the trans2 routines. diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5871fd143f..27f17f9628 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -553,8 +553,7 @@ NTSTATUS unix_convert(connection_struct *conn, tmp = talloc_asprintf(ctx, "%s/%s", dirpath, found_name); - } - else { + } else { tmp = talloc_strdup(ctx, found_name); } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index d687974ff3..5cbe8c68ac 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -817,9 +817,9 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, } if (pdp->reqpath[0] != '\0') { - ref->alternate_path = talloc_asprintf(ctx, - "%s%s", + ref->alternate_path = talloc_asprintf_append( ref->alternate_path, + "%s", pdp->reqpath); if (!ref->alternate_path) { TALLOC_FREE(pdp); @@ -1298,7 +1298,6 @@ BOOL create_msdfs_link(const struct junction_map *jucn, goto out; } for(i=0; ireferral_count; i++) { - char *old_msdfs_link = msdfs_link; char *refpath = jucn->referral_list[i].alternate_path; /* Alternate paths always use Windows separators. */ @@ -1310,21 +1309,18 @@ BOOL create_msdfs_link(const struct junction_map *jucn, continue; } if (i > 0 && insert_comma) { - msdfs_link = talloc_asprintf(conn->mem_ctx, - "%s,%s", - old_msdfs_link, + msdfs_link = talloc_asprintf_append(msdfs_link, + ",%s", refpath); } else { - msdfs_link = talloc_asprintf(conn->mem_ctx, - "%s%s", - old_msdfs_link, + msdfs_link = talloc_asprintf_append(msdfs_link, + "%s", refpath); } if (!msdfs_link) { goto out; } - TALLOC_FREE(old_msdfs_link); if (!insert_comma) { insert_comma = True; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 114050ae16..7886ee86ce 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. SMB NT transaction handling - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2007 Copyright (C) Stefan (metze) Metzmacher 2003 This program is free software; you can redistribute it and/or modify @@ -51,7 +51,7 @@ static char *nttrans_realloc(char **ptr, size_t size) if (ptr==NULL) { smb_panic("nttrans_realloc() called with NULL ptr"); } - + *ptr = (char *)SMB_REALLOC(*ptr, size); if(*ptr == NULL) { return NULL; @@ -80,7 +80,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, int alignment_offset = 3; int data_alignment_offset = 0; - /* + /* * If there genuinely are no parameters or data to send just send * the empty packet. */ @@ -101,10 +101,10 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, data_alignment_offset = 4 - (params_to_send % 4); } - /* + /* * Space is bufsize minus Netbios over TCP header minus SMB header. * The alignment_offset is to align the param bytes on a four byte - * boundary (2 bytes for data len, one byte pad). + * boundary (2 bytes for data len, one byte pad). * NT needs this to work correctly. */ @@ -131,7 +131,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset; - /* + /* * We can never send more than useable_space. */ @@ -146,7 +146,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, SIVAL(req->outbuf,smb_ntr_TotalParameterCount,paramsize); SIVAL(req->outbuf,smb_ntr_TotalDataCount,datasize); - /* + /* * Calculate how many parameters and data we can fit into * this packet. Parameters get precedence. */ @@ -172,7 +172,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, SIVAL(req->outbuf,smb_ntr_ParameterOffset, ((smb_buf(req->outbuf)+alignment_offset) - smb_base(req->outbuf))); - /* + /* * Absolute displacement of param bytes sent in this packet. */ @@ -202,7 +202,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, SIVAL(req->outbuf,smb_ntr_DataDisplacement, pd - pdata); } - /* + /* * Copy the param bytes into the packet. */ @@ -229,7 +229,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, +params_sent_thistime+data_alignment_offset, pd,data_sent_thistime); } - + DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", params_sent_thistime, data_sent_thistime, useable_space)); DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", @@ -240,7 +240,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, 0, 0, nt_error, __LINE__,__FILE__); } - + /* Send the packet */ show_msg((char *)req->outbuf); if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) { @@ -248,10 +248,10 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, } TALLOC_FREE(req->outbuf); - + pp += params_sent_thistime; pd += data_sent_thistime; - + params_to_send -= params_sent_thistime; data_to_send -= data_sent_thistime; @@ -264,7 +264,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, params_to_send, data_to_send)); return; } - } + } } /**************************************************************************** @@ -385,14 +385,20 @@ static void nt_open_pipe(char *fname, connection_struct *conn, static void do_ntcreate_pipe_open(connection_struct *conn, struct smb_request *req) { - pstring fname; + char *fname = NULL; int pnum = -1; char *p = NULL; uint32 flags = IVAL(req->inbuf,smb_ntcreate_Flags); + TALLOC_CTX *ctx = talloc_tos(); - srvstr_pull_buf((char *)req->inbuf, req->flags2, fname, - smb_buf(req->inbuf), sizeof(fname), STR_TERMINATE); + srvstr_pull_buf_talloc(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf), STR_TERMINATE); + if (!fname) { + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpipe); + return; + } nt_open_pipe(fname, conn, req, &pnum); if (req->outbuf) { @@ -402,7 +408,7 @@ static void do_ntcreate_pipe_open(connection_struct *conn, /* * Deal with pipe return. - */ + */ if (flags & EXTENDED_RESPONSE_REQUIRED) { /* This is very strange. We @@ -434,7 +440,7 @@ static void do_ntcreate_pipe_open(connection_struct *conn, if (flags & EXTENDED_RESPONSE_REQUIRED) { p += 25; SIVAL(p,0,FILE_GENERIC_ALL); - /* + /* * For pipes W2K3 seems to return * 0x12019B next. * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA) @@ -470,9 +476,9 @@ static void reply_ntcreate_and_X_quota(connection_struct *conn, } reply_outbuf(req, 34, 0); - + p = (char *)req->outbuf + smb_vwv2; - + /* SCVAL(p,0,NO_OPLOCK_RETURN); */ p++; SSVAL(p,0,fsp->fnum); @@ -488,8 +494,7 @@ static void reply_ntcreate_and_X_quota(connection_struct *conn, void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) -{ - pstring fname_in; +{ char *fname = NULL; uint32 flags; uint32 access_mask; @@ -578,7 +583,7 @@ void reply_ntcreate_and_X(connection_struct *conn, /* * This filename is relative to a directory fid. */ - pstring rel_fname; + char *rel_fname = NULL; files_struct *dir_fsp = file_fsp( SVAL(req->inbuf, smb_ntcreate_RootDirectoryFid)); size_t dir_name_len; @@ -591,8 +596,9 @@ void reply_ntcreate_and_X(connection_struct *conn, if(!dir_fsp->is_directory) { - srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, - smb_buf(req->inbuf), sizeof(fname_in), 0, + srvstr_get_path(ctx, (char *)req->inbuf, + req->flags2, &fname, + smb_buf(req->inbuf), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -604,7 +610,7 @@ void reply_ntcreate_and_X(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname_in)) { + if( is_ntfs_stream_name(fname)) { reply_nterror( req, NT_STATUS_OBJECT_PATH_NOT_FOUND); END_PROFILE(SMBntcreateX); @@ -627,30 +633,47 @@ void reply_ntcreate_and_X(connection_struct *conn, * Copy in the base directory name. */ - pstrcpy( fname_in, dir_fsp->fsp_name ); - dir_name_len = strlen(fname_in); + dir_name_len = strlen(dir_fsp->fsp_name); + fname = TALLOC_SIZE(ctx, dir_name_len+2); + if (!fname) { + reply_nterror( + req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBntcreateX); + return; + } + memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); /* - * Ensure it ends in a '\'. + * Ensure it ends in a '/'. + * We used TALLOC_SIZE +2 to add space for the '/'. */ - if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) { - pstrcat(fname_in, "/"); + if(dir_name_len && (fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { + fname[dir_name_len] = '/'; + fname[dir_name_len+1] = '\0'; dir_name_len++; } - srvstr_get_path((char *)req->inbuf, req->flags2, rel_fname, - smb_buf(req->inbuf), sizeof(rel_fname), 0, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &rel_fname, + smb_buf(req->inbuf), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBntcreateX); return; } - pstrcat(fname_in, rel_fname); + fname = talloc_asprintf(ctx, "%s%s", + fname, + rel_fname); + if (!fname) { + reply_nterror( + req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBntcreateX); + return; + } } else { - srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, - smb_buf(req->inbuf), sizeof(fname_in), 0, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -662,8 +685,8 @@ void reply_ntcreate_and_X(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname_in)) { - enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname_in); + if( is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname); if (fake_file_type!=FAKE_FILE_TYPE_NONE) { /* * Here we go! support for changing the disk quotas --metze @@ -675,7 +698,7 @@ void reply_ntcreate_and_X(connection_struct *conn, * xp also tries a QUERY_FILE_INFO on the file and then close it */ reply_ntcreate_and_X_quota(conn, req, - fake_file_type, fname_in); + fake_file_type, fname); } else { reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); } @@ -690,7 +713,7 @@ void reply_ntcreate_and_X(connection_struct *conn, */ status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -890,8 +913,8 @@ void reply_ntcreate_and_X(connection_struct *conn, reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBntcreateX); return; - } - + } + /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { @@ -914,7 +937,7 @@ void reply_ntcreate_and_X(connection_struct *conn, } } - /* + /* * If the caller set the extended oplock request bit * and we granted one (by whatever means) - set the * correct bit for extended oplock reply. @@ -941,7 +964,7 @@ void reply_ntcreate_and_X(connection_struct *conn, } p = (char *)req->outbuf + smb_vwv2; - + /* * Currently as we don't support level II oplocks we just report * exclusive & batch here. @@ -958,7 +981,7 @@ void reply_ntcreate_and_X(connection_struct *conn, } else { SCVAL(p,0,NO_OPLOCK_RETURN); } - + p++; SSVAL(p,0,fsp->fnum); p += 2; @@ -1028,13 +1051,14 @@ static void do_nt_transact_create_pipe(connection_struct *conn, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count) { - pstring fname; + char *fname = NULL; char *params = *ppparams; int pnum = -1; char *p = NULL; NTSTATUS status; size_t param_len; uint32 flags; + TALLOC_CTX *ctx = talloc_tos(); /* * Ensure minimum number of parameters sent. @@ -1048,8 +1072,8 @@ static void do_nt_transact_create_pipe(connection_struct *conn, flags = IVAL(params,0); - srvstr_get_path(params, req->flags2, fname, params+53, - sizeof(fname), parameter_count-53, STR_TERMINATE, + srvstr_get_path(ctx, params, req->flags2, &fname, params+53, + parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1062,7 +1086,7 @@ static void do_nt_transact_create_pipe(connection_struct *conn, /* Error return */ return; } - + /* Realloc the size of parameters and data we will return */ if (flags & EXTENDED_RESPONSE_REQUIRED) { /* Extended response is 32 more byyes. */ @@ -1075,16 +1099,16 @@ static void do_nt_transact_create_pipe(connection_struct *conn, reply_doserror(req, ERRDOS, ERRnomem); return; } - + p = params; SCVAL(p,0,NO_OPLOCK_RETURN); - + p += 2; SSVAL(p,0,pnum); p += 2; SIVAL(p,0,FILE_WAS_OPENED); p += 8; - + p += 32; SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ p += 20; @@ -1093,11 +1117,11 @@ static void do_nt_transact_create_pipe(connection_struct *conn, /* Device state. */ SSVAL(p,2, 0x5FF); /* ? */ p += 4; - + if (flags & EXTENDED_RESPONSE_REQUIRED) { p += 25; SIVAL(p,0,FILE_GENERIC_ALL); - /* + /* * For pipes W2K3 seems to return * 0x12019B next. * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA) @@ -1106,10 +1130,10 @@ static void do_nt_transact_create_pipe(connection_struct *conn, } DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); - + /* Send the required number of replies */ send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0); - + return; } @@ -1123,7 +1147,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu SEC_DESC *psd = NULL; TALLOC_CTX *mem_ctx; NTSTATUS status; - + if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) { return NT_STATUS_OK; } @@ -1143,7 +1167,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu * Setup the prs_struct to point at the memory we just * allocated. */ - + prs_give_memory( &pd, data, sd_len, False); /* @@ -1154,11 +1178,11 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n")); /* * Return access denied for want of a better error message.. - */ + */ talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } - + if (psd->owner_sid==0) { security_info_sent &= ~OWNER_SECURITY_INFORMATION; } @@ -1171,9 +1195,9 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu if (psd->dacl==0) { security_info_sent &= ~DACL_SECURITY_INFORMATION; } - + status = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd); - + talloc_destroy(mem_ctx); return status; } @@ -1181,7 +1205,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu /**************************************************************************** Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. ****************************************************************************/ - + static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) { struct ea_list *ea_list_head = NULL; @@ -1220,7 +1244,6 @@ static void call_nt_transact_create(connection_struct *conn, char **ppdata, uint32 data_count, uint32 max_data_count) { - pstring fname_in; char *fname = NULL; char *params = *ppparams; char *data = *ppdata; @@ -1331,6 +1354,7 @@ static void call_nt_transact_create(connection_struct *conn, /* * This filename is relative to a directory fid. */ + char *tmpname = NULL; files_struct *dir_fsp = file_fsp(SVAL(params,4)); size_t dir_name_len; @@ -1340,8 +1364,8 @@ static void call_nt_transact_create(connection_struct *conn, } if(!dir_fsp->is_directory) { - srvstr_get_path(params, req->flags2, fname_in, - params+53, sizeof(fname_in), + srvstr_get_path(ctx, params, req->flags2, &fname, + params+53, parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -1353,7 +1377,7 @@ static void call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname_in)) { + if( is_ntfs_stream_name(fname)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); return; @@ -1367,33 +1391,46 @@ static void call_nt_transact_create(connection_struct *conn, * Copy in the base directory name. */ - pstrcpy( fname_in, dir_fsp->fsp_name ); - dir_name_len = strlen(fname_in); + dir_name_len = strlen(dir_fsp->fsp_name); + fname = TALLOC_SIZE(ctx, dir_name_len+2); + if (!fname) { + reply_nterror( + req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBntcreateX); + return; + } + memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); /* - * Ensure it ends in a '\'. + * Ensure it ends in a '/'. + * We used TALLOC_SIZE +2 to add space for the '/'. */ - if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) { - pstrcat(fname_in, "/"); + if(dir_name_len && (fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { + fname[dir_name_len] = '/'; + fname[dir_name_len+1] = '\0'; dir_name_len++; } - { - pstring tmpname; - srvstr_get_path(params, req->flags2, tmpname, - params+53, sizeof(tmpname), - parameter_count-53, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - pstrcat(fname_in, tmpname); + srvstr_get_path(ctx, params, req->flags2, &tmpname, + params+53, + parameter_count-53, STR_TERMINATE, + &status); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + fname = talloc_asprintf(ctx, "%s%s", + fname, + tmpname); + if (!fname) { + reply_nterror( + req, NT_STATUS_NO_MEMORY); + return; } } else { - srvstr_get_path(params, req->flags2, fname_in, params+53, - sizeof(fname_in), parameter_count-53, + srvstr_get_path(ctx, params, req->flags2, &fname, params+53, + parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1404,7 +1441,7 @@ static void call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname_in)) { + if( is_ntfs_stream_name(fname)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); return; } @@ -1430,7 +1467,7 @@ static void call_nt_transact_create(connection_struct *conn, status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); @@ -1584,7 +1621,7 @@ static void call_nt_transact_create(connection_struct *conn, * According to the MS documentation, the only time the security * descriptor is applied to the opened file is iff we *created* the * file; an existing file stays the same. - * + * * Also, it seems (from observation) that you can open the file with * any access mask but you can still write the sd. We need to override * the granted access before we call set_sd @@ -1607,7 +1644,7 @@ static void call_nt_transact_create(connection_struct *conn, } fsp->access_mask = saved_access_mask; } - + if (ea_len && (info == FILE_WAS_CREATED)) { status = set_ea(conn, fsp, fname, ea_list); if (!NT_STATUS_IS_OK(status)) { @@ -1629,8 +1666,8 @@ static void call_nt_transact_create(connection_struct *conn, close_file(fsp,ERROR_CLOSE); reply_doserror(req, ERRDOS, ERRnoaccess); return; - } - + } + /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12); @@ -1655,7 +1692,7 @@ static void call_nt_transact_create(connection_struct *conn, } } - /* + /* * If the caller set the extended oplock request bit * and we granted one (by whatever means) - set the * correct bit for extended oplock reply. @@ -1694,7 +1731,7 @@ static void call_nt_transact_create(connection_struct *conn, } else { SCVAL(p,0,NO_OPLOCK_RETURN); } - + p += 2; SSVAL(p,0,fsp->fnum); p += 2; @@ -1765,12 +1802,12 @@ void reply_ntcancel(connection_struct *conn, struct smb_request *req) /* * Go through and cancel any pending change notifies. */ - + START_PROFILE(SMBntcancel); remove_pending_change_notify_requests_by_mid(req->mid); remove_pending_lock_requests_by_mid(req->mid); srv_cancel_sign_response(req->mid); - + DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", req->mid)); END_PROFILE(SMBntcancel); @@ -1923,8 +1960,6 @@ static NTSTATUS copy_internals(connection_struct *conn, void reply_ntrename(connection_struct *conn, struct smb_request *req) { - pstring oldname_in; - pstring newname_in; char *oldname = NULL; char *newname = NULL; char *p; @@ -1947,8 +1982,8 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) rename_type = SVAL(req->inbuf,smb_vwv1); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, oldname_in, p, - sizeof(oldname_in), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &oldname, p, + 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1956,22 +1991,22 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) return; } - if( is_ntfs_stream_name(oldname_in)) { + if( is_ntfs_stream_name(oldname)) { /* Can't rename a stream. */ reply_nterror(req, NT_STATUS_ACCESS_DENIED); END_PROFILE(SMBntrename); return; } - if (ms_has_wild(oldname_in)) { + if (ms_has_wild(oldname)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); END_PROFILE(SMBntrename); return; } p++; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p, - sizeof(newname_in), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p, + 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1981,7 +2016,7 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - oldname_in, + oldname, &oldname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1997,7 +2032,7 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname_in, + newname, &newname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -2057,13 +2092,13 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) } reply_outbuf(req, 0, 0); - + END_PROFILE(SMBntrename); return; } /**************************************************************************** - Reply to a notify change - queue the request and + Reply to a notify change - queue the request and don't allow a directory to be opened. ****************************************************************************/ @@ -2175,11 +2210,12 @@ static void call_nt_transact_rename(connection_struct *conn, uint32 max_data_count) { char *params = *ppparams; - pstring new_name; + char *new_name = NULL; files_struct *fsp = NULL; BOOL replace_if_exists = False; BOOL dest_has_wcard = False; NTSTATUS status; + TALLOC_CTX *ctx = talloc_tos(); if(parameter_count < 5) { reply_doserror(req, ERRDOS, ERRbadfunc); @@ -2191,8 +2227,8 @@ static void call_nt_transact_rename(connection_struct *conn, if (!check_fsp(conn, req, fsp, ¤t_user)) { return; } - srvstr_get_path_wcard(params, req->flags2, new_name, params+4, - sizeof(new_name), parameter_count - 4, + srvstr_get_path_wcard(ctx, params, req->flags2, &new_name, params+4, + parameter_count - 4, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -2215,10 +2251,10 @@ static void call_nt_transact_rename(connection_struct *conn, * Rename was successful. */ send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); - + DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); - + return; } @@ -2351,7 +2387,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, security descriptor.\n")); /* * Return access denied for want of a better error message.. - */ + */ talloc_destroy(mem_ctx); reply_unixerror(req, ERRDOS, ERRnoaccess); return; @@ -2421,7 +2457,7 @@ static void call_nt_transact_set_security_desc(connection_struct *conn, send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); return; } - + /**************************************************************************** Reply to NT IOCTL ****************************************************************************/ @@ -2469,7 +2505,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); return; - + case FSCTL_CREATE_OR_GET_OBJECT_ID: { unsigned char objid[16]; @@ -2515,7 +2551,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); reply_nterror(req, NT_STATUS_NOT_A_REPARSE_POINT); return; - + case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ { /* @@ -2564,9 +2600,9 @@ static void call_nt_transact_ioctl(connection_struct *conn, reply_nterror(req, NT_STATUS_NO_MEMORY); return; } - + shadow_data->mem_ctx = shadow_mem_ctx; - + /* * Call the VFS routine to actually do the work. */ @@ -2606,7 +2642,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, talloc_destroy(shadow_data->mem_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; - } + } cur_pdata = pdata; @@ -2643,11 +2679,11 @@ static void call_nt_transact_ioctl(connection_struct *conn, return; } - + case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */ { - /* pretend this succeeded - - * + /* pretend this succeeded - + * * we have to send back a list with all files owned by this SID * * but I have to check that --metze @@ -2655,7 +2691,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, DOM_SID sid; uid_t uid; size_t sid_len = MIN(data_count-4,SID_MAX_SIZE); - + DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum)); if (!fsp_belongs_conn(conn, req, fsp, ¤t_user)) { @@ -2664,7 +2700,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, /* unknown 4 bytes: this is not the length of the sid :-( */ /*unknown = IVAL(pdata,0);*/ - + sid_parse(pdata+4,sid_len,&sid); DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid))); @@ -2673,7 +2709,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, sid_string_static(&sid),(unsigned long)sid_len)); uid = (-1); } - + /* we can take a look at the find source :-) * * find ./ -uid $uid -name '*' is what we need here @@ -2686,16 +2722,16 @@ static void call_nt_transact_ioctl(connection_struct *conn, * (maybe we can hang the result anywhere in the fsp struct) * * we don't send all files at once - * and at the next we should *not* start from the beginning, - * so we have to cache the result + * and at the next we should *not* start from the beginning, + * so we have to cache the result * * --metze */ - + /* this works for now... */ send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); return; - } + } default: if (!logged_message) { logged_message = True; /* Only print this once... */ @@ -2710,7 +2746,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, #ifdef HAVE_SYS_QUOTAS /**************************************************************************** - Reply to get user quota + Reply to get user quota ****************************************************************************/ static void call_nt_transact_get_user_quota(connection_struct *conn, @@ -2758,7 +2794,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, reply_doserror(req, ERRDOS, ERRinvalidparam); return; } - + /* maybe we can check the quota_fnum */ fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { @@ -2773,16 +2809,16 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd; level = SVAL(params,2); - - /* unknown 12 bytes leading in params */ - + + /* unknown 12 bytes leading in params */ + switch (level) { case TRANSACT_GET_USER_QUOTA_LIST_CONTINUE: /* seems that we should continue with the enum here --metze */ - if (qt_handle->quota_list!=NULL && + if (qt_handle->quota_list!=NULL && qt_handle->tmp_list==NULL) { - + /* free the list */ free_ntquota_list(&(qt_handle->quota_list)); @@ -2824,7 +2860,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, /* we should not trust the value in max_data_count*/ max_data_count = MIN(max_data_count,2048); - + pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/ if(pdata == NULL) { reply_doserror(req, ERRDOS, ERRnomem); @@ -2835,7 +2871,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, /* set params Size of returned Quota Data 4 bytes*/ /* but set it later when we know it */ - + /* for each entry push the data */ if (start_enum) { @@ -2852,28 +2888,28 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, /* nextoffset entry 4 bytes */ SIVAL(entry,0,entry_len); - + /* then the len of the SID 4 bytes */ SIVAL(entry,4,sid_len); - + /* unknown data 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-metze*/ - + /* the used disk space 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,16,tmp_list->quotas->usedspace); - + /* the soft quotas 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,24,tmp_list->quotas->softlim); - + /* the hard quotas 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,32,tmp_list->quotas->hardlim); - + /* and now the SID */ sid_linearize(entry+40, sid_len, &tmp_list->quotas->sid); } - + qt_handle->tmp_list = tmp_list; - + /* overwrite the offset of the last entry */ SIVAL(entry-entry_len,0,0); @@ -2884,9 +2920,9 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, break; case TRANSACT_GET_USER_QUOTA_FOR_SID: - - /* unknown 4 bytes IVAL(pdata,0) */ - + + /* unknown 4 bytes IVAL(pdata,0) */ + if (data_count < 8) { DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8)); reply_doserror(req, ERRDOS, ERRunknownlevel); @@ -2919,11 +2955,11 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, } sid_parse(pdata+8,sid_len,&sid); - + if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) { ZERO_STRUCT(qt); - /* - * we have to return zero's in all fields + /* + * we have to return zero's in all fields * instead of returning an error here * --metze */ @@ -2947,25 +2983,25 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, /* set params Size of returned Quota Data 4 bytes*/ SIVAL(params,0,data_len); - + /* nextoffset entry 4 bytes */ SIVAL(entry,0,0); - + /* then the len of the SID 4 bytes */ SIVAL(entry,4,sid_len); - + /* unknown data 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-mezte*/ - + /* the used disk space 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,16,qt.usedspace); - + /* the soft quotas 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,24,qt.softlim); - + /* the hard quotas 8 bytes SMB_BIG_UINT */ SBIG_UINT(entry,32,qt.hardlim); - + /* and now the SID */ sid_linearize(entry+40, sid_len, &sid); @@ -3023,7 +3059,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, reply_doserror(req, ERRDOS, ERRinvalidparam); return; } - + /* maybe we can check the quota_fnum */ fsp = file_fsp(SVAL(params,0)); if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { @@ -3052,7 +3088,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, return; } - /* unknown 8 bytes in pdata + /* unknown 8 bytes in pdata * maybe its the change time in NTTIME */ @@ -3097,7 +3133,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, return; } #endif /* LARGE_SMB_OFF_T */ - + sid_parse(pdata+40,sid_len,&sid); DEBUGADD(8,("SID: %s\n",sid_string_static(&sid))); @@ -3227,7 +3263,7 @@ static void handle_nttrans(connection_struct *conn, &state->data, state->total_data, state->max_data_return); END_PROFILE(NT_transact_set_user_quota); - break; + break; } #endif /* HAVE_SYS_QUOTAS */ @@ -3307,7 +3343,7 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) state->setup = NULL; state->call = function_code; - /* + /* * All nttrans messages we handle have smb_wct == 19 + * state->setup_count. Ensure this is so as a sanity check. */ @@ -3339,7 +3375,7 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) reply_doserror(req, ERRDOS, ERRnomem); END_PROFILE(SMBnttrans); return; - } + } if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) goto bad_param; if ((smb_base(req->inbuf)+dsoff+dscnt @@ -3361,7 +3397,7 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) reply_doserror(req, ERRDOS, ERRnomem); END_PROFILE(SMBnttrans); return; - } + } if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) goto bad_param; if ((smb_base(req->inbuf)+psoff+pscnt @@ -3431,7 +3467,7 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBnttrans); return; } - + /**************************************************************************** Reply to a SMBnttranss ****************************************************************************/ @@ -3489,7 +3525,7 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) state->received_param += pcnt; state->received_data += dcnt; - + if ((state->received_data > state->total_data) || (state->received_param > state->total_param)) goto bad_param; @@ -3529,7 +3565,7 @@ void reply_nttranss(connection_struct *conn, struct smb_request *req) goto bad_param; memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, - dcnt); + dcnt); } if ((state->received_param < state->total_param) || diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 672c683309..7ac6c4699f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. Main SMB reply routines Copyright (C) Andrew Tridgell 1992-1998 @@ -10,12 +10,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 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, see . */ @@ -208,27 +208,46 @@ NTSTATUS check_path_syntax_posix(char *path) Pull a string and check the path allowing a wilcard - provide for error return. ****************************************************************************/ -size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest, - const char *src, size_t dest_len, size_t src_len, - int flags, NTSTATUS *err, BOOL *contains_wcard) +size_t srvstr_get_path_wcard(TALLOC_CTX *ctx, + const char *inbuf, + uint16 smb_flags2, + char **pp_dest, + const char *src, + size_t src_len, + int flags, + NTSTATUS *err, + BOOL *contains_wcard) { size_t ret; -#ifdef DEVELOPER - SMB_ASSERT(dest_len == sizeof(pstring)); -#endif + + *pp_dest = NULL; if (src_len == 0) { - ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src, - dest_len, flags); + ret = srvstr_pull_buf_talloc(ctx, + inbuf, + smb_flags2, + pp_dest, + src, + flags); } else { - ret = srvstr_pull(inbuf, smb_flags2, dest, src, - dest_len, src_len, flags); + ret = srvstr_pull_talloc(ctx, + inbuf, + smb_flags2, + pp_dest, + src, + src_len, + flags); + } + + if (!*pp_dest) { + *err = NT_STATUS_INVALID_PARAMETER; + return ret; } *contains_wcard = False; if (smb_flags2 & FLAGS2_DFS_PATHNAMES) { - /* + /* * For a DFS path the function parse_dfs_path() * will do the path processing, just make a copy. */ @@ -237,9 +256,9 @@ size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest, } if (lp_posix_pathnames()) { - *err = check_path_syntax_posix(dest); + *err = check_path_syntax_posix(*pp_dest); } else { - *err = check_path_syntax_wcard(dest, contains_wcard); + *err = check_path_syntax_wcard(*pp_dest, contains_wcard); } return ret; @@ -249,25 +268,43 @@ size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest, Pull a string and check the path - provide for error return. ****************************************************************************/ -size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, - const char *src, size_t dest_len, size_t src_len, - int flags, NTSTATUS *err) +size_t srvstr_get_path(TALLOC_CTX *ctx, + const char *inbuf, + uint16 smb_flags2, + char **pp_dest, + const char *src, + size_t src_len, + int flags, + NTSTATUS *err) { size_t ret; -#ifdef DEVELOPER - SMB_ASSERT(dest_len == sizeof(pstring)); -#endif + + *pp_dest = NULL; if (src_len == 0) { - ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src, - dest_len, flags); + ret = srvstr_pull_buf_talloc(ctx, + inbuf, + smb_flags2, + pp_dest, + src, + flags); } else { - ret = srvstr_pull(inbuf, smb_flags2, dest, src, - dest_len, src_len, flags); + ret = srvstr_pull_talloc(ctx, + inbuf, + smb_flags2, + pp_dest, + src, + src_len, + flags); + } + + if (!*pp_dest) { + *err = NT_STATUS_INVALID_PARAMETER; + return ret; } if (smb_flags2 & FLAGS2_DFS_PATHNAMES) { - /* + /* * For a DFS path the function parse_dfs_path() * will do the path processing, just make a copy. */ @@ -276,9 +313,9 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, } if (lp_posix_pathnames()) { - *err = check_path_syntax_posix(dest); + *err = check_path_syntax_posix(*pp_dest); } else { - *err = check_path_syntax(dest); + *err = check_path_syntax(*pp_dest); } return ret; @@ -802,14 +839,13 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status) } return status; } - + /**************************************************************************** Reply to a checkpath. ****************************************************************************/ void reply_checkpath(connection_struct *conn, struct smb_request *req) { - pstring name_in; char *name = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; @@ -817,8 +853,8 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBcheckpath); - srvstr_get_path((char *)req->inbuf, req->flags2, name_in, - smb_buf(req->inbuf) + 1, sizeof(name_in), 0, + srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name, + smb_buf(req->inbuf) + 1, 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { status = map_checkpath_error((char *)req->inbuf, status); @@ -829,7 +865,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name_in, + name, &name); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -841,7 +877,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) goto path_err; } - DEBUG(3,("reply_checkpath %s mode=%d\n", name_in, (int)SVAL(req->inbuf,smb_vwv0))); + DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0))); status = unix_convert(conn, name, False, &name, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -904,7 +940,6 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) void reply_getatr(connection_struct *conn, struct smb_request *req) { - pstring fname_in; char *fname = NULL; SMB_STRUCT_STAT sbuf; int mode=0; @@ -917,8 +952,8 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBgetatr); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p, - sizeof(fname_in), 0, STR_TERMINATE, &status); + p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p, + 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBgetatr); @@ -927,7 +962,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -995,7 +1030,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) } DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) ); - + END_PROFILE(SMBgetatr); return; } @@ -1006,7 +1041,6 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) void reply_setatr(connection_struct *conn, struct smb_request *req) { - pstring fname_in; char *fname = NULL; int mode; time_t mtime; @@ -1023,8 +1057,8 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) } p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p, - sizeof(fname_in), 0, STR_TERMINATE, &status); + p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p, + 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBsetatr); @@ -1033,7 +1067,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1046,7 +1080,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBsetatr); return; } - + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1171,7 +1205,6 @@ void reply_search(connection_struct *conn, struct smb_request *req) BOOL finished = False; char *p; int status_len; - pstring path_in; char *path = NULL; char status[21]; int dptr_num= -1; @@ -1207,9 +1240,15 @@ void reply_search(connection_struct *conn, struct smb_request *req) maxentries = SVAL(req->inbuf,smb_vwv0); dirtype = SVAL(req->inbuf,smb_vwv1); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path_in, p, - sizeof(path_in), 0, STR_TERMINATE, &nt_status, - &mask_contains_wcard); + p += srvstr_get_path_wcard(ctx, + (char *)req->inbuf, + req->flags2, + &path, + p, + 0, + STR_TERMINATE, + &nt_status, + &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); END_PROFILE(SMBsearch); @@ -1218,7 +1257,7 @@ void reply_search(connection_struct *conn, struct smb_request *req) nt_status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - path_in, + path, &path, &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { @@ -1440,12 +1479,13 @@ void reply_search(connection_struct *conn, struct smb_request *req) void reply_fclose(connection_struct *conn, struct smb_request *req) { int status_len; - pstring path; char status[21]; int dptr_num= -2; char *p; + char *path = NULL; NTSTATUS err; BOOL path_contains_wcard = False; + TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBfclose); @@ -1456,9 +1496,15 @@ void reply_fclose(connection_struct *conn, struct smb_request *req) } p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p, - sizeof(path), 0, STR_TERMINATE, &err, - &path_contains_wcard); + p += srvstr_get_path_wcard(ctx, + (char *)req->inbuf, + req->flags2, + &path, + p, + 0, + STR_TERMINATE, + &err, + &path_contains_wcard); if (!NT_STATUS_IS_OK(err)) { reply_nterror(req, err); END_PROFILE(SMBfclose); @@ -1496,7 +1542,6 @@ void reply_fclose(connection_struct *conn, struct smb_request *req) void reply_open(connection_struct *conn, struct smb_request *req) { - pstring fname_in; char *fname = NULL; uint32 fattr=0; SMB_OFF_T size = 0; @@ -1526,8 +1571,8 @@ void reply_open(connection_struct *conn, struct smb_request *req) deny_mode = SVAL(req->inbuf,smb_vwv0); dos_attr = SVAL(req->inbuf,smb_vwv1); - srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, - smb_buf(req->inbuf)+1, sizeof(fname_in), 0, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf)+1, 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1537,7 +1582,7 @@ void reply_open(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1634,7 +1679,6 @@ void reply_open(connection_struct *conn, struct smb_request *req) void reply_open_and_X(connection_struct *conn, struct smb_request *req) { - pstring fname_in; char *fname = NULL; uint16 open_flags; int deny_mode; @@ -1692,8 +1736,8 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, - smb_buf(req->inbuf), sizeof(fname_in), 0, STR_TERMINATE, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1703,7 +1747,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); @@ -1882,7 +1926,6 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req) void reply_mknew(connection_struct *conn, struct smb_request *req) { - pstring fname_in; char *fname = NULL; int com; uint32 fattr = 0; @@ -1913,8 +1956,8 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) srv_make_unix_date3(req->inbuf + smb_vwv1)); /* mtime. */ - srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, - smb_buf(req->inbuf) + 1, sizeof(fname_in), 0, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf) + 1, 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1924,7 +1967,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); @@ -2014,7 +2057,6 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) void reply_ctemp(connection_struct *conn, struct smb_request *req) { - pstring fname_in; char *fname = NULL; uint32 fattr; files_struct *fsp; @@ -2036,23 +2078,31 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) fattr = SVAL(req->inbuf,smb_vwv0); oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); - srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, - smb_buf(req->inbuf)+1, sizeof(fname_in), 0, STR_TERMINATE, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf)+1, 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); return; } - if (*fname_in) { - pstrcat(fname_in,"/TMXXXXXX"); + if (*fname) { + fname = talloc_asprintf(ctx, + "%s/TMXXXXXX", + fname); } else { - pstrcat(fname_in,"TMXXXXXX"); + fname = talloc_strdup(ctx, "TMXXXXXX"); + } + + if (!fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBctemp); + return; } status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -2458,7 +2508,6 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, void reply_unlink(connection_struct *conn, struct smb_request *req) { - pstring name_in; char *name = NULL; uint32 dirtype; NTSTATUS status; @@ -2475,8 +2524,8 @@ void reply_unlink(connection_struct *conn, struct smb_request *req) dirtype = SVAL(req->inbuf,smb_vwv0); - srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, - smb_buf(req->inbuf) + 1, sizeof(name_in), 0, + srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, + smb_buf(req->inbuf) + 1, 0, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -2486,7 +2535,7 @@ void reply_unlink(connection_struct *conn, struct smb_request *req) status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name_in, + name, &name, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -4660,7 +4709,6 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req) void reply_mkdir(connection_struct *conn, struct smb_request *req) { - pstring directory_in; char *directory = NULL; NTSTATUS status; SMB_STRUCT_STAT sbuf; @@ -4668,8 +4716,8 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBmkdir); - srvstr_get_path((char *)req->inbuf, req->flags2, directory_in, - smb_buf(req->inbuf) + 1, sizeof(directory_in), 0, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory, + smb_buf(req->inbuf) + 1, 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -4679,7 +4727,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - directory_in, + directory, &directory); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -4916,7 +4964,6 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) void reply_rmdir(connection_struct *conn, struct smb_request *req) { - pstring directory_in; char *directory = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; @@ -4924,8 +4971,8 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBrmdir); - srvstr_get_path((char *)req->inbuf, req->flags2, directory_in, - smb_buf(req->inbuf) + 1, sizeof(directory_in), 0, + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory, + smb_buf(req->inbuf) + 1, 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -4935,7 +4982,7 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - directory_in, + directory, &directory); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -5683,8 +5730,6 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, void reply_mv(connection_struct *conn, struct smb_request *req) { - pstring name_in; - pstring newname_in; char *name = NULL; char *newname = NULL; char *p; @@ -5705,8 +5750,8 @@ void reply_mv(connection_struct *conn, struct smb_request *req) attrs = SVAL(req->inbuf,smb_vwv0); p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, p, - sizeof(name_in), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p, + 0, STR_TERMINATE, &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -5714,8 +5759,8 @@ void reply_mv(connection_struct *conn, struct smb_request *req) return; } p++; - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p, - sizeof(newname_in), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p, + 0, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -5725,7 +5770,7 @@ void reply_mv(connection_struct *conn, struct smb_request *req) status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name_in, + name, &name, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -5742,7 +5787,7 @@ void reply_mv(connection_struct *conn, struct smb_request *req) status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname_in, + newname, &newname, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -5903,9 +5948,7 @@ NTSTATUS copy_file(connection_struct *conn, void reply_copy(connection_struct *conn, struct smb_request *req) { - pstring name_in; char *name = NULL; - pstring newname_in; char *newname = NULL; pstring directory; pstring mask; @@ -5938,16 +5981,16 @@ void reply_copy(connection_struct *conn, struct smb_request *req) *directory = *mask = 0; p = smb_buf(req->inbuf); - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, p, - sizeof(name_in), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p, + 0, STR_TERMINATE, &status, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); return; } - p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p, - sizeof(newname_in), 0, STR_TERMINATE, &status, + p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p, + 0, STR_TERMINATE, &status, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -5955,7 +5998,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) return; } - DEBUG(3,("reply_copy : %s -> %s\n",name_in,newname_in)); + DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); if (tid2 != conn->cnum) { /* can't currently handle inter share copies XXXX */ @@ -5967,7 +6010,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - name_in, + name, &name, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { @@ -5984,7 +6027,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname_in, + newname, &newname, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { @@ -6085,7 +6128,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBcopy); return; } - + status = check_name(conn, newname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2ba0781e62..8e03094aef 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -783,7 +783,6 @@ static void call_trans2open(connection_struct *conn, int open_ofun; uint32 open_size; char *pname; - pstring fname_in; char *fname = NULL; SMB_OFF_T size=0; int fattr=0,mtime=0; @@ -798,6 +797,7 @@ static void call_trans2open(connection_struct *conn, uint32 share_mode; uint32 create_disposition; uint32 create_options = 0; + TALLOC_CTX *ctx = talloc_tos(); /* * Ensure we have enough parameters to perform the operation. @@ -830,8 +830,8 @@ static void call_trans2open(connection_struct *conn, return; } - srvstr_get_path(params, req->flags2, fname_in, pname, - sizeof(fname_in), total_params - 28, STR_TERMINATE, + srvstr_get_path(ctx, params, req->flags2, &fname, pname, + total_params - 28, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -844,12 +844,12 @@ static void call_trans2open(connection_struct *conn, /* XXXX we need to handle passed times, sattr and flags */ - status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); + status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; } - + status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1759,7 +1759,6 @@ static void call_trans2findfirst(connection_struct *conn, BOOL close_if_end; BOOL requires_resume_key; int info_level; - pstring directory_in; char *directory = NULL; pstring mask; char *p; @@ -1791,7 +1790,7 @@ static void call_trans2findfirst(connection_struct *conn, requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); info_level = SVAL(params,6); - *directory_in = *mask = 0; + *mask = 0; DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", @@ -1826,8 +1825,8 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return; } - srvstr_get_path_wcard(params, req->flags2, directory_in, - params+12, sizeof(directory_in), total_params - 12, + srvstr_get_path_wcard(ctx, params, req->flags2, &directory, + params+12, total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); @@ -1836,7 +1835,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", ntstatus = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - directory_in, + directory, &directory, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { @@ -2101,7 +2100,7 @@ static void call_trans2findnext(connection_struct *conn, BOOL requires_resume_key; BOOL continue_bit; BOOL mask_contains_wcard = False; - pstring resume_name; + char *resume_name = NULL; pstring mask; pstring directory; char *p; @@ -2115,6 +2114,7 @@ static void call_trans2findnext(connection_struct *conn, TALLOC_CTX *ea_ctx = NULL; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; + TALLOC_CTX *ctx = talloc_tos(); if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2131,10 +2131,10 @@ static void call_trans2findnext(connection_struct *conn, requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); - *mask = *directory = *resume_name = 0; + *mask = *directory = 0; - srvstr_get_path_wcard(params, req->flags2, resume_name, - params+12, sizeof(resume_name), + srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name, + params+12, total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { @@ -2142,12 +2142,12 @@ static void call_trans2findnext(connection_struct *conn, complain (it thinks we're asking for the directory above the shared path or an invalid name). Catch this as the resume name is only compared, never used in a file access. JRA. */ - srvstr_pull(params, req->flags2, - resume_name, params+12, - sizeof(resume_name), total_params - 12, + srvstr_pull_talloc(ctx, params, req->flags2, + &resume_name, params+12, + total_params - 12, STR_TERMINATE); - if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) { + if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) { reply_nterror(req, ntstatus); return; } @@ -3527,7 +3527,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ char *lock_data = NULL; - TALLOC_CTX *ctx = NULL; + TALLOC_CTX *ctx = talloc_tos(); if (!params) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -3620,7 +3620,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } } else { - pstring fname_in; NTSTATUS status = NT_STATUS_OK; /* qpathinfo */ @@ -3638,8 +3637,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - srvstr_get_path(params, req->flags2, fname_in, ¶ms[6], - sizeof(fname_in), total_params - 6, + srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6], + total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -3649,7 +3648,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -4835,9 +4834,10 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, int total_data, const char *fname) { - pstring link_target; + char *link_target = NULL; const char *newname = fname; NTSTATUS status = NT_STATUS_OK; + TALLOC_CTX *ctx = talloc_tos(); /* Set a symbolic link. */ /* Don't allow this if follow links is false. */ @@ -4850,8 +4850,12 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - srvstr_pull(pdata, req->flags2, link_target, pdata, - sizeof(link_target), total_data, STR_TERMINATE); + srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata, + total_data, STR_TERMINATE); + + if (!link_target) { + return NT_STATUS_INVALID_PARAMETER; + } /* !widelinks forces the target path to be within the share. */ /* This means we can interpret the target as a pathname. */ @@ -4897,7 +4901,6 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, const char *pdata, int total_data, const char *fname) { - pstring oldname_in; char *oldname = NULL; TALLOC_CTX *ctx = talloc_tos(); NTSTATUS status = NT_STATUS_OK; @@ -4907,15 +4910,15 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path(pdata, req->flags2, oldname_in, pdata, - sizeof(oldname_in), total_data, STR_TERMINATE, &status); + srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata, + total_data, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return status; } status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - oldname_in, + oldname, &oldname); if (!NT_STATUS_IS_OK(status)) { return status; @@ -4941,7 +4944,6 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, BOOL overwrite; uint32 root_fid; uint32 len; - pstring newname_in; char *newname = NULL; pstring base_name; BOOL dest_has_wcard = False; @@ -4961,16 +4963,19 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - srvstr_get_path_wcard(pdata, req->flags2, newname_in, &pdata[12], - sizeof(newname_in), len, 0, &status, + srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12], + len, 0, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { return status; } + DEBUG(10,("smb_file_rename_information: got name |%s|\n", + newname)); + status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - newname_in, + newname, &newname, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { @@ -6265,8 +6270,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } } } else { - pstring fname_in; - /* set path info */ if (total_params < 7) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -6274,8 +6277,8 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } info_level = SVAL(params,0); - srvstr_get_path(params, req->flags2, fname_in, ¶ms[6], - sizeof(fname_in), total_params - 6, STR_TERMINATE, + srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6], + total_params - 6, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -6284,7 +6287,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname_in, + fname, &fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -6619,11 +6622,11 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, { char *params = *pparams; char *pdata = *ppdata; - pstring directory_in; char *directory = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; struct ea_list *ea_list = NULL; + TALLOC_CTX *ctx = talloc_tos(); if (!CAN_WRITE(conn)) { reply_doserror(req, ERRSRV, ERRaccess); @@ -6635,17 +6638,17 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, return; } - srvstr_get_path(params, req->flags2, directory_in, ¶ms[4], - sizeof(directory_in), total_params - 4, STR_TERMINATE, + srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4], + total_params - 4, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; } - DEBUG(3,("call_trans2mkdir : name = %s\n", directory_in)); + DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf); + status = unix_convert(conn, directory, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -6821,10 +6824,11 @@ static void call_trans2getdfsreferral(connection_struct *conn, unsigned int max_data_bytes) { char *params = *pparams; - pstring pathname; + char *pathname = NULL; int reply_size = 0; int max_referral_level; NTSTATUS status = NT_STATUS_OK; + TALLOC_CTX *ctx = talloc_tos(); DEBUG(10,("call_trans2getdfsreferral\n")); @@ -6840,14 +6844,18 @@ static void call_trans2getdfsreferral(connection_struct *conn, return; } - srvstr_pull(params, req->flags2, pathname, ¶ms[2], - sizeof(pathname), total_params - 2, STR_TERMINATE); + srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2], + total_params - 2, STR_TERMINATE); + if (!pathname) { + reply_nterror(req, NT_STATUS_NOT_FOUND); + return; + } if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level, ppdata,&status)) < 0) { reply_nterror(req, status); return; } - + SSVAL(req->inbuf, smb_flg2, SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes); @@ -6872,7 +6880,7 @@ static void call_trans2ioctl(connection_struct *conn, files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15)); /* check for an invalid fid before proceeding */ - + if (!fsp) { reply_doserror(req, ERRDOS, ERRbadfid); return; -- cgit From 12f61e09d943ea7fc4149166077507b5b0b3b4e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Sep 2007 21:48:20 +0000 Subject: r25117: The mega-patch Jerry was waiting for. Remove all pstrings from the main server code paths. We should now be able to cope with paths up to PATH_MAX length now. Final job will be to add the TALLOC_CTX * parameter to unix_convert to make it explicit (for Volker). Jeremy. (This used to be commit 7f0db75fb0f24873577dcb758a2ecee74fdc4297) --- source3/smbd/close.c | 3 +- source3/smbd/dir.c | 135 +++++++++---- source3/smbd/mangle.c | 2 + source3/smbd/nttrans.c | 23 ++- source3/smbd/open.c | 40 ++-- source3/smbd/posix_acls.c | 64 ++++--- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 469 ++++++++++++++++++++++++++++------------------ source3/smbd/service.c | 22 ++- source3/smbd/trans2.c | 329 +++++++++++++++++--------------- source3/smbd/vfs.c | 110 ++++++++--- 11 files changed, 731 insertions(+), 468 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4eb1a30342..40db9f9b7f 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -478,7 +478,8 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty TALLOC_FREE(lck); - status = rmdir_internals(fsp->conn, fsp->fsp_name); + status = rmdir_internals(talloc_tos(), + fsp->conn, fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - " "deleting directory returned %s.\n", diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7a6815b680..a7b1b020b8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1,18 +1,19 @@ -/* +/* Unix SMB/CIFS implementation. Directory handling routines Copyright (C) Andrew Tridgell 1992-1998 - + Copyright (C) Jeremy Allison 2007 + 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 3 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, see . */ @@ -72,15 +73,25 @@ static int dirhandles_open = 0; Make a dir struct. ****************************************************************************/ -void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc) -{ +BOOL make_dir_struct(TALLOC_CTX *ctx, + char *buf, + const char *mask, + const char *fname, + SMB_OFF_T size, + uint32 mode, + time_t date, + BOOL uc) +{ char *p; - pstring mask2; + char *mask2 = talloc_strdup(ctx, mask); - pstrcpy(mask2,mask); + if (!mask2) { + return False; + } - if ((mode & aDIR) != 0) + if ((mode & aDIR) != 0) { size = 0; + } memset(buf+1,' ',11); if ((p = strchr_m(mask2,'.')) != NULL) { @@ -88,8 +99,9 @@ void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T si push_ascii(buf+1,mask2,8, 0); push_ascii(buf+9,p+1,3, 0); *p = '.'; - } else + } else { push_ascii(buf+1,mask2,11, 0); + } memset(buf+21,'\0',DIR_STRUCT_SIZE-21); SCVAL(buf,21,mode); @@ -100,6 +112,7 @@ void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T si Strange, but verified on W2K3. Needed for OS/2. JRA. */ push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0); DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname)); + return True; } /**************************************************************************** @@ -238,7 +251,7 @@ static void dptr_close_internal(struct dptr_struct *dptr) DLIST_REMOVE(dirptrs, dptr); - /* + /* * Free the dnum in the bitmap. Remember the dnum value is always * biased by one with respect to the bitmap. */ @@ -563,7 +576,10 @@ static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffs Return the next visible file name, skipping veto'd and invisible files. ****************************************************************************/ -const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) +const char *dptr_ReadDirName(TALLOC_CTX *ctx, + struct dptr_struct *dptr, + long *poffset, + SMB_STRUCT_STAT *pst) { SET_STAT_INVALID(*pst); @@ -578,7 +594,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT } if (!dptr->did_stat) { - pstring pathreal; + char *pathreal = NULL; /* We know the stored wcard contains no wildcard characters. See if we can match with a stat call. If we can't, then set did_stat to true to @@ -602,14 +618,19 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT return dptr->wcard; } - pstrcpy(pathreal,dptr->path); - pstrcat(pathreal,"/"); - pstrcat(pathreal,dptr->wcard); + pathreal = talloc_asprintf(ctx, + "%s/%s", + dptr->path, + dptr->wcard); + if (!pathreal) { + return NULL; + } if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { /* We need to set the underlying dir_hnd offset to -1 also as this function is usually called with the output from TellDir. */ dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; + TALLOC_FREE(pathreal); return dptr->wcard; } else { /* If we get any other error than ENOENT or ENOTDIR @@ -618,10 +639,13 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT /* We need to set the underlying dir_hdn offset to -1 also as this function is usually called with the output from TellDir. */ dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; + TALLOC_FREE(pathreal); return dptr->wcard; } } + TALLOC_FREE(pathreal); + /* In case sensitive mode we don't search - we know if it doesn't exist with a stat we will fail. */ @@ -768,35 +792,43 @@ static BOOL mangle_mask_match(connection_struct *conn, Get an 8.3 directory entry. ****************************************************************************/ -BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname, - SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend) +BOOL get_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + const char *mask, + uint32 dirtype, + char **pp_fname_out, + SMB_OFF_T *size, + uint32 *mode, + time_t *date, + BOOL check_descend) { - const char *dname; + const char *dname = NULL; BOOL found = False; SMB_STRUCT_STAT sbuf; - pstring path; - pstring pathreal; - pstring filename; + char *pathreal = NULL; + const char *filename = NULL; BOOL needslash; - *path = *pathreal = *filename = 0; + *pp_fname_out = NULL; needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - if (!conn->dirptr) + if (!conn->dirptr) { return(False); + } while (!found) { long curoff = dptr_TellDir(conn->dirptr); - dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf); + dname = dptr_ReadDirName(ctx, conn->dirptr, &curoff, &sbuf); DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd))); - if (dname == NULL) + if (dname == NULL) { return(False); + } - pstrcpy(filename,dname); + filename = dname; /* notice the special *.* handling. This appears to be the only difference between the wildcard handling in this routine and in the trans2 routines. @@ -805,44 +837,65 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn if ((strcmp(mask,"*.*") == 0) || mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { + char mname[13]; if (!mangle_is_8_3(filename, False, conn->params)) { - char mname[13]; if (!name_to_8_3(filename,mname,False, conn->params)) { continue; } - pstrcpy(filename,mname); + filename = mname; + } + + if (needslash) { + pathreal = talloc_asprintf(ctx, + "%s/%s", + conn->dirpath, + dname); + } else { + pathreal = talloc_asprintf(ctx, + "%s%s", + conn->dirpath, + dname); + } + if (!pathreal) { + return False; } - pstrcpy(fname,filename); - *path = 0; - pstrcpy(path,conn->dirpath); - if(needslash) - pstrcat(path,"/"); - pstrcpy(pathreal,path); - pstrcat(path,fname); - pstrcat(pathreal,dname); if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) { - DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); + DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n", + pathreal, strerror(errno) )); + TALLOC_FREE(pathreal); continue; } - + *mode = dos_mode(conn,pathreal,&sbuf); if (!dir_check_ftype(conn,*mode,dirtype)) { DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype)); + TALLOC_FREE(pathreal); continue; } *size = sbuf.st_size; *date = sbuf.st_mtime; - DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); + DEBUG(3,("get_dir_entry mask=[%s] found %s " + "fname=%s (%s)\n", + mask, + pathreal, + dname, + filename)); found = True; + *pp_fname_out = talloc_strdup(ctx, filename); + if (!*pp_fname_out) { + return False; + } + DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff); + TALLOC_FREE(pathreal); } } @@ -1198,7 +1251,7 @@ void SeekDir(struct smb_Dir *dirp, long offset) if (offset != dirp->offset) { if (offset == START_OF_DIRECTORY_OFFSET) { RewindDir(dirp, &offset); - /* + /* * Ok we should really set the file number here * to 1 to enable ".." to be returned next. Trouble * is I'm worried about callers using SeekDir(dirp,0) diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 61490c444e..4c00f6d14a 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -135,6 +135,8 @@ BOOL name_to_8_3(const char *in, BOOL cache83, const struct share_params *p) { + memset(out,'\0',13); + /* name mangling can be disabled for speed, in which case we just truncate the string */ if (!lp_manglednames(p)) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7886ee86ce..c40fbc763c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2050,16 +2050,18 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) switch(rename_type) { case RENAME_FLAG_RENAME: - status = rename_internals(conn, req, oldname, newname, - attrs, False, src_has_wcard, - dest_has_wcard); + status = rename_internals(ctx, conn, req, oldname, + newname, attrs, False, src_has_wcard, + dest_has_wcard); break; case RENAME_FLAG_HARD_LINK: if (src_has_wcard || dest_has_wcard) { /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { - status = hardlink_internals(conn, oldname, newname); + status = hardlink_internals(conn, + oldname, + newname); } break; case RENAME_FLAG_COPY: @@ -2235,8 +2237,15 @@ static void call_nt_transact_rename(connection_struct *conn, return; } - status = rename_internals(conn, req, fsp->fsp_name, - new_name, 0, replace_if_exists, False, dest_has_wcard); + status = rename_internals(ctx, + conn, + req, + fsp->fsp_name, + new_name, + 0, + replace_if_exists, + False, + dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -2252,7 +2261,7 @@ static void call_nt_transact_rename(connection_struct *conn, */ send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); - DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", + DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); return; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 691599ca97..8e1068e708 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -117,22 +117,26 @@ static void change_file_owner_to_parent(connection_struct *conn, (unsigned int)parent_st.st_uid )); } -static void change_dir_owner_to_parent(connection_struct *conn, +static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, const char *inherit_from_dir, const char *fname, SMB_STRUCT_STAT *psbuf) { - pstring saved_dir; + char *saved_dir = NULL; SMB_STRUCT_STAT sbuf; SMB_STRUCT_STAT parent_st; + TALLOC_CTX *ctx = talloc_stackframe(); + NTSTATUS status = NT_STATUS_OK; int ret; ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", inherit_from_dir, strerror(errno) )); - return; + TALLOC_FREE(ctx); + return status; } /* We've already done an lstat into psbuf, and we know it's a @@ -142,14 +146,19 @@ static void change_dir_owner_to_parent(connection_struct *conn, should work on any UNIX (thanks tridge :-). JRA. */ - if (!vfs_GetWd(conn,saved_dir)) { + saved_dir = vfs_GetWd(ctx,conn); + if (!saved_dir) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to get " - "current working directory\n")); - return; + "current working directory. Error was %s\n", + strerror(errno))); + TALLOC_FREE(ctx); + return status; } /* Chdir into the new path. */ if (vfs_ChDir(conn, fname) == -1) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to change " "current working directory to %s. Error " "was %s\n", fname, strerror(errno) )); @@ -157,6 +166,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, } if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to stat " "directory '.' (%s) Error was %s\n", fname, strerror(errno))); @@ -170,6 +180,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, DEBUG(0,("change_dir_owner_to_parent: " "device/inode/mode on directory %s changed. " "Refusing to chown !\n", fname )); + status = NT_STATUS_ACCESS_DENIED; goto out; } @@ -177,6 +188,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { + status = map_nt_error_from_unix(errno); DEBUG(10,("change_dir_owner_to_parent: failed to chown " "directory %s to parent directory uid %u. " "Error was %s\n", fname, @@ -190,7 +202,9 @@ static void change_dir_owner_to_parent(connection_struct *conn, out: + TALLOC_FREE(ctx); vfs_ChDir(conn,saved_dir); + return status; } /**************************************************************************** @@ -500,9 +514,10 @@ static void validate_my_share_entries(int num, if (is_deferred_open_entry(share_entry) && !open_was_deferred(share_entry->op_mid)) { - pstring str; - pstr_sprintf(str, "Got a deferred entry without a request: " - "PANIC: %s\n", share_mode_str(num, share_entry)); + char *str = talloc_asprintf(talloc_tos(), + "Got a deferred entry without a request: " + "PANIC: %s\n", + share_mode_str(num, share_entry)); smb_panic(str); } @@ -539,11 +554,12 @@ static void validate_my_share_entries(int num, panic: { - pstring str; + char *str; DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); - slprintf(str, sizeof(str)-1, "validate_my_share_entries: " - "file %s, oplock_type = 0x%x, op_type = 0x%x\n", + str = talloc_asprintf(talloc_tos(), + "validate_my_share_entries: " + "file %s, oplock_type = 0x%x, op_type = 0x%x\n", fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); smb_panic(str); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 64051d23b1..f7cadeec3e 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -79,9 +79,9 @@ typedef struct canon_ace { struct pai_entry { struct pai_entry *next, *prev; enum ace_owner owner_type; - posix_id unix_ug; + posix_id unix_ug; }; - + struct pai_val { BOOL pai_protected; unsigned int num_entries; @@ -1001,7 +1001,7 @@ NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_i Ensure the enforced permissions for this share apply. ****************************************************************************/ -static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type) +static void apply_default_perms(const files_struct *fsp, canon_ace *pace, mode_t type) { int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; @@ -1047,7 +1047,7 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type) static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) { - fstring u_name; + const char *u_name = NULL; /* "Everyone" always matches every uid. */ @@ -1059,7 +1059,11 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) if (uid_ace->unix_ug.uid == current_user.ut.uid && group_ace->unix_ug.gid == current_user.ut.gid) return True; - fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); + /* u_name talloc'ed off tos. */ + u_name = uidtoname(uid_ace->unix_ug.uid); + if (!u_name) { + return False; + } return user_in_group_sid(u_name, &group_ace->trustee); } @@ -1074,7 +1078,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) ****************************************************************************/ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, - files_struct *fsp, + const files_struct *fsp, const DOM_SID *pfile_owner_sid, const DOM_SID *pfile_grp_sid, SMB_STRUCT_STAT *pst, @@ -2106,7 +2110,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) Create a linked list of canonical ACE entries. ****************************************************************************/ -static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, +static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { connection_struct *conn = fsp->conn; @@ -4416,8 +4420,9 @@ static int check_posix_acl_group_access(connection_struct *conn, const char *fna BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) { - SMB_STRUCT_STAT sbuf; - pstring dname; + SMB_STRUCT_STAT sbuf; + TALLOC_CTX *ctx = talloc_tos(); + char *dname = NULL; int ret; if (!CAN_WRITE(conn)) { @@ -4425,7 +4430,12 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) } /* Get the parent directory permission mask and owners. */ - pstrcpy(dname, parent_dirname(fname)); + if (!parent_dirname_talloc(ctx, + fname, + &dname, + NULL)) { + return False; + } if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) { return False; } @@ -4445,7 +4455,7 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) #ifdef S_ISVTX /* sticky bit means delete only by owner or root. */ if (sbuf.st_mode & S_ISVTX) { - SMB_STRUCT_STAT sbuf_file; + SMB_STRUCT_STAT sbuf_file; if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { if (errno == ENOENT) { /* If the file doesn't already exist then @@ -4563,21 +4573,19 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST descriptor via TALLOC_FREE(). This is designed for dealing with user space access checks in smbd outside of the VFS. For example, checking access rights in OpenEventlog(). - + Assume we are dealing with files (for now) ********************************************************************/ -SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) +SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) { SEC_DESC *psd, *ret_sd; connection_struct conn; files_struct finfo; struct fd_handle fh; - pstring path; - pstring filename; - + ZERO_STRUCT( conn ); - + if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) { DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); return NULL; @@ -4590,35 +4598,33 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) } conn.params->service = -1; - - pstrcpy( path, "/" ); - set_conn_connectpath(&conn, path); - + + set_conn_connectpath(&conn, "/"); + if (!smbd_vfs_init(&conn)) { DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n")); conn_free_internal( &conn ); return NULL; } - + ZERO_STRUCT( finfo ); ZERO_STRUCT( fh ); - + finfo.fnum = -1; finfo.conn = &conn; finfo.fh = &fh; finfo.fh->fd = -1; - pstrcpy( filename, fname ); - finfo.fsp_name = filename; - + finfo.fsp_name = CONST_DISCARD(char *,fname); + if (get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ) == 0) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); conn_free_internal( &conn ); return NULL; } - + ret_sd = dup_sec_desc( ctx, psd ); - + conn_free_internal( &conn ); - + return ret_sd; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8b3e85f4b4..29b942de81 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1227,7 +1227,7 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(const char *inbuf, char *outbuf) { set_message(inbuf,outbuf,0,0,False); - + SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); SIVAL(outbuf,smb_rcls,0); SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7ac6c4699f..b94c91fe8e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1193,9 +1193,9 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req) void reply_search(connection_struct *conn, struct smb_request *req) { - pstring mask; + char *mask = NULL; char *directory = NULL; - pstring fname; + char *fname = NULL; SMB_OFF_T size; uint32 mode; time_t date; @@ -1229,8 +1229,6 @@ void reply_search(connection_struct *conn, struct smb_request *req) return; } - *mask = *fname = 0; - /* If we were called as SMBffirst then we must expect close. */ if(CVAL(req->inbuf,smb_com) == SMBffirst) { expect_close = True; @@ -1297,8 +1295,8 @@ void reply_search(connection_struct *conn, struct smb_request *req) p = strrchr_m(directory,'/'); if (!p) { - pstrcpy(mask,directory); - directory = talloc_strdup(talloc_tos(),"."); + mask = directory; + directory = talloc_strdup(ctx,"."); if (!directory) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBsearch); @@ -1306,11 +1304,11 @@ void reply_search(connection_struct *conn, struct smb_request *req) } } else { *p = 0; - pstrcpy(mask,p+1); + mask = p+1; } if (*directory == '\0') { - directory = talloc_strdup(talloc_tos(),"."); + directory = talloc_strdup(ctx,"."); if (!directory) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBsearch); @@ -1349,7 +1347,10 @@ void reply_search(connection_struct *conn, struct smb_request *req) goto SearchEmpty; } string_set(&conn->dirpath,dptr_path(dptr_num)); - pstrcpy(mask, dptr_wcard(dptr_num)); + mask = dptr_wcard(dptr_num); + if (!mask) { + goto SearchEmpty; + } /* * For a 'continue' search we have no string. So * check from the initial saved string. @@ -1363,8 +1364,12 @@ void reply_search(connection_struct *conn, struct smb_request *req) if ((dirtype&0x1F) == aVOLID) { char buf[DIR_STRUCT_SIZE]; memcpy(buf,status,21); - make_dir_struct(buf,"???????????",volume_label(SNUM(conn)), - 0,aVOLID,0,!allow_long_path_components); + if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)), + 0,aVOLID,0,!allow_long_path_components)) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsearch); + return; + } dptr_fill(buf+12,dptr_num); if (dptr_zero(buf+12) && (status_len==0)) { numentries = 1; @@ -1393,12 +1398,23 @@ void reply_search(connection_struct *conn, struct smb_request *req) } for (i=numentries;(iparams)) { char *new_mask = NULL; - mangle_lookup_name_from_8_3(talloc_tos(), + mangle_lookup_name_from_8_3(ctx, mask, &new_mask, conn->params ); if (new_mask) { - pstrcpy(mask, new_mask); + mask = new_mask; } } if (!has_wild) { - pstrcat(directory,"/"); - pstrcat(directory,mask); + directory = talloc_asprintf(ctx, + "%s/%s", + directory, + mask); + if (!directory) { + return NT_STATUS_NO_MEMORY; + } if (dirtype == 0) { dirtype = FILE_ATTRIBUTE_NORMAL; } @@ -2435,7 +2460,8 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, } if (strequal(mask,"????????.???")) { - pstrcpy(mask,"*"); + mask[0] = '*'; + mask[1] = '\0'; } status = check_name(conn, directory); @@ -2447,35 +2473,37 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, if (dir_hnd == NULL) { return map_nt_error_from_unix(errno); } - + /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name We don't implement this yet XXXX */ - + status = NT_STATUS_NO_SUCH_FILE; while ((dname = ReadDirName(dir_hnd, &offset))) { SMB_STRUCT_STAT st; - pstring fname; - pstrcpy(fname,dname); + char *fname = NULL; if (!is_visible_file(conn, directory, dname, &st, True)) { continue; } /* Quick check for "." and ".." */ - if (fname[0] == '.') { - if (!fname[1] || (fname[1] == '.' && !fname[2])) { - continue; - } + if (ISDOT(dname) || ISDOTDOT(dname)) { + continue; } - if(!mask_match(fname, mask, conn->case_sensitive)) { + if(!mask_match(dname, mask, conn->case_sensitive)) { continue; } - - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); + + fname = talloc_asprintf(ctx, "%s/%s", + directory, + dname); + if (!fname) { + return NT_STATUS_NO_MEMORY; + } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { @@ -2485,16 +2513,19 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, status = do_unlink(conn, req, fname, dirtype); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(fname); continue; } count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n", fname)); + + TALLOC_FREE(fname); } CloseDir(dir_hnd); } - + if (count == 0 && NT_STATUS_IS_OK(status)) { status = map_nt_error_from_unix(errno); } @@ -2577,9 +2608,12 @@ void reply_unlink(connection_struct *conn, struct smb_request *req) static void fail_readraw(void) { - pstring errstr; - slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)", - strerror(errno) ); + const char *errstr = talloc_asprintf(talloc_tos(), + "FAIL ! reply_readbraw: socket write fail (%s)", + strerror(errno)); + if (!errstr) { + errstr = ""; + } exit_server_cleanly(errstr); } @@ -3097,12 +3131,14 @@ static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf, False); data = smb_buf(outbuf); + memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */ + + SCVAL(outbuf,smb_vwv0,0xFF); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,smb_maxcnt); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16)); SSVAL(smb_buf(outbuf),-2,smb_maxcnt); - SCVAL(outbuf,smb_vwv0,0xFF); /* Reset the outgoing length, set_message truncates at 0x1FFFF. */ _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4)); return outsize; @@ -3136,7 +3172,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, #if defined(WITH_SENDFILE) /* - * We can only use sendfile on a non-chained packet + * We can only use sendfile on a non-chained packet * but we can use on a non-oplocked file. tridge proved this * on a train in Germany :-). JRA. */ @@ -3146,7 +3182,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, uint8 headerbuf[smb_size + 12 * 2]; DATA_BLOB header; - /* + /* * Set up the packet header before send. We * assume here the sendfile will work (get the * correct amount of data). @@ -4790,7 +4826,9 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) tree recursively. Return True on ok, False on fail. ****************************************************************************/ -static BOOL recursive_rmdir(connection_struct *conn, char *directory) +static BOOL recursive_rmdir(TALLOC_CTX *ctx, + connection_struct *conn, + char *directory) { const char *dname = NULL; BOOL ret = True; @@ -4801,33 +4839,35 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) return False; while((dname = ReadDirName(dir_hnd, &offset))) { - pstring fullname; + char *fullname = NULL; SMB_STRUCT_STAT st; - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + if (ISDOT(dname) || ISDOTDOT(dname)) { continue; + } - if (!is_visible_file(conn, directory, dname, &st, False)) + if (!is_visible_file(conn, directory, dname, &st, False)) { continue; + } /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { + fullname = talloc_asprintf(ctx, + "%s/%s", + directory, + dname); + if (!fullname) { errno = ENOMEM; ret = False; break; } - pstrcpy(fullname, directory); - pstrcat(fullname, "/"); - pstrcat(fullname, dname); - if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) { ret = False; break; } if(st.st_mode & S_IFDIR) { - if(!recursive_rmdir(conn, fullname)) { + if(!recursive_rmdir(ctx, conn, fullname)) { ret = False; break; } @@ -4839,6 +4879,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) ret = False; break; } + TALLOC_FREE(fullname); } CloseDir(dir_hnd); return ret; @@ -4848,7 +4889,9 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) The internals of the rmdir code - called elsewhere. ****************************************************************************/ -NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) +NTSTATUS rmdir_internals(TALLOC_CTX *ctx, + connection_struct *conn, + const char *directory) { int ret; SMB_STRUCT_STAT st; @@ -4878,7 +4921,7 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) } if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { - /* + /* * Check to see if the only thing in this directory are * vetoed files/directories. If so then delete them and * retry. If we fail to delete any of them (and we *don't* @@ -4909,34 +4952,40 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory) RewindDir(dir_hnd,&dirpos); while ((dname = ReadDirName(dir_hnd,&dirpos))) { - pstring fullname; + char *fullname = NULL; - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + if (ISDOT(dname) || ISDOTDOT(dname)) { continue; - if (!is_visible_file(conn, directory, dname, &st, False)) + } + if (!is_visible_file(conn, directory, dname, &st, False)) { continue; + } + + fullname = talloc_asprintf(ctx, + "%s/%s", + directory, + dname); - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { + if(!fullname) { errno = ENOMEM; break; } - pstrcpy(fullname, directory); - pstrcat(fullname, "/"); - pstrcat(fullname, dname); - - if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) + if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) { break; + } if(st.st_mode & S_IFDIR) { if(lp_recursive_veto_delete(SNUM(conn))) { - if(!recursive_rmdir(conn, fullname)) + if(!recursive_rmdir(ctx, conn, fullname)) break; } - if(SMB_VFS_RMDIR(conn,fullname) != 0) + if(SMB_VFS_RMDIR(conn,fullname) != 0) { break; - } else if(SMB_VFS_UNLINK(conn,fullname) != 0) + } + } else if(SMB_VFS_UNLINK(conn,fullname) != 0) { break; + } + TALLOC_FREE(fullname); } CloseDir(dir_hnd); /* Retry the rmdir */ @@ -5012,17 +5061,17 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) } dptr_closepath(directory, req->smbpid); - status = rmdir_internals(conn, directory); + status = rmdir_internals(ctx, conn, directory); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBrmdir); return; } - + reply_outbuf(req, 0, 0); - + DEBUG( 3, ( "rmdir %s\n", directory ) ); - + END_PROFILE(SMBrmdir); return; } @@ -5451,19 +5500,21 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, /**************************************************************************** The guts of the rename command, split out so it may be called by the NT SMB - code. + code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, - const char *name_in, - const char *newname_in, - uint32 attrs, - BOOL replace_if_exists, - BOOL src_has_wild, - BOOL dest_has_wild) +NTSTATUS rename_internals(TALLOC_CTX *ctx, + connection_struct *conn, + struct smb_request *req, + const char *name_in, + const char *newname_in, + uint32 attrs, + BOOL replace_if_exists, + BOOL src_has_wild, + BOOL dest_has_wild) { - pstring directory; - pstring mask; + char *directory = NULL; + char *mask = NULL; char *last_component_src = NULL; char *last_component_dest = NULL; char *name = NULL; @@ -5475,9 +5526,6 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, struct smb_Dir *dir_hnd = NULL; const char *dname; long offset = 0; - pstring destname; - - *directory = *mask = 0; ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); @@ -5496,8 +5544,8 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, /* * Split the old name into directory and last component - * strings. Note that unix_convert may have stripped off a - * leading ./ from both name and newname if the rename is + * strings. Note that unix_convert may have stripped off a + * leading ./ from both name and newname if the rename is * at the root of the share. We need to make sure either both * name and newname contain a / character or neither of them do * as this is checked in resolve_wildcards(). @@ -5505,12 +5553,18 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, p = strrchr_m(name,'/'); if (!p) { - pstrcpy(directory,"."); - pstrcpy(mask,name); + directory = talloc_strdup(ctx, "."); + if (!directory) { + return NT_STATUS_NO_MEMORY; + } + mask = name; } else { *p = 0; - pstrcpy(directory,name); - pstrcpy(mask,p+1); + directory = talloc_strdup(ctx, name); + if (!directory) { + return NT_STATUS_NO_MEMORY; + } + mask = p+1; *p = '/'; /* Replace needed for exceptional test below. */ } @@ -5525,12 +5579,12 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) { char *new_mask = NULL; - mangle_lookup_name_from_8_3(talloc_tos(), + mangle_lookup_name_from_8_3(ctx, mask, &new_mask, conn->params ); if (new_mask) { - pstrcpy(mask, new_mask); + mask = new_mask; } } @@ -5543,12 +5597,16 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, BOOL is_short_name = mangle_is_8_3(name, True, conn->params); /* Add a terminating '/' to the directory name. */ - pstrcat(directory,"/"); - pstrcat(directory,mask); + directory = talloc_asprintf_append(directory, + "/%s", + mask); + if (!directory) { + return NT_STATUS_NO_MEMORY; + } /* Ensure newname contains a '/' also */ if(strrchr_m(newname,'/') == 0) { - newname = talloc_asprintf(talloc_tos(), + newname = talloc_asprintf(ctx, "./%s", newname); if (!newname) { @@ -5559,23 +5617,25 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, DEBUG(3, ("rename_internals: case_sensitive = %d, " "case_preserve = %d, short case preserve = %d, " "directory = %s, newname = %s, " - "last_component_dest = %s, is_8_3 = %d\n", + "last_component_dest = %s, is_8_3 = %d\n", conn->case_sensitive, conn->case_preserve, - conn->short_case_preserve, directory, + conn->short_case_preserve, directory, newname, last_component_dest, is_short_name)); /* The dest name still may have wildcards. */ if (dest_has_wild) { char *mod_newname = NULL; - if (!resolve_wildcards(talloc_tos(), + if (!resolve_wildcards(ctx, directory,newname,&mod_newname)) { - DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", - directory,newname)); + DEBUG(6, ("rename_internals: resolve_wildcards " + "%s %s failed\n", + directory, + newname)); return NT_STATUS_NO_MEMORY; } newname = mod_newname; } - + ZERO_STRUCT(sbuf1); SMB_VFS_STAT(conn, directory, &sbuf1); @@ -5613,41 +5673,38 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, * Wildcards - process each file that matches. */ if (strequal(mask,"????????.???")) { - pstrcpy(mask,"*"); + mask[0] = '*'; + mask[1] = '\0'; } - + status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { return status; } - + dir_hnd = OpenDir(conn, directory, mask, attrs); if (dir_hnd == NULL) { return map_nt_error_from_unix(errno); } - + status = NT_STATUS_NO_SUCH_FILE; /* * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; * - gentest fix. JRA */ - + while ((dname = ReadDirName(dir_hnd, &offset))) { - files_struct *fsp; - pstring fname; + files_struct *fsp = NULL; + char *fname = NULL; + char *destname = NULL; BOOL sysdir_entry = False; - char *mod_destname = NULL; - pstrcpy(fname,dname); - /* Quick check for "." and ".." */ - if (fname[0] == '.') { - if (!fname[1] || (fname[1] == '.' && !fname[2])) { - if (attrs & aDIR) { - sysdir_entry = True; - } else { - continue; - } + if (ISDOT(dname) || ISDOTDOT(dname)) { + if (attrs & aDIR) { + sysdir_entry = True; + } else { + continue; } } @@ -5655,27 +5712,34 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, continue; } - if(!mask_match(fname, mask, conn->case_sensitive)) { + if(!mask_match(dname, mask, conn->case_sensitive)) { continue; } - + if (sysdir_entry) { status = NT_STATUS_OBJECT_NAME_INVALID; break; } - slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname); + fname = talloc_asprintf(ctx, + "%s/%s", + directory, + dname); + if (!fname) { + return NT_STATUS_NO_MEMORY; + } - pstrcpy(destname,newname); - - if (!resolve_wildcards(talloc_tos(), - fname,destname,&mod_destname)) { - DEBUG(6, ("resolve_wildcards %s %s failed\n", + if (!resolve_wildcards(ctx, + fname,newname,&destname)) { + DEBUG(6, ("resolve_wildcards %s %s failed\n", fname, destname)); + TALLOC_FREE(fname); continue; } - pstrcpy(destname,mod_destname); - + if (!destname) { + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCT(sbuf1); SMB_VFS_STAT(conn, fname, &sbuf1); @@ -5714,13 +5778,16 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req, DEBUG(3,("rename_internals: doing rename on %s -> " "%s\n",fname,destname)); + + TALLOC_FREE(fname); + TALLOC_FREE(destname); } CloseDir(dir_hnd); if (count == 0 && NT_STATUS_IS_OK(status)) { status = map_nt_error_from_unix(errno); } - + return status; } @@ -5804,7 +5871,7 @@ void reply_mv(connection_struct *conn, struct smb_request *req) DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - status = rename_internals(conn, req, name, newname, attrs, False, + status = rename_internals(ctx, conn, req, name, newname, attrs, False, src_has_wcard, dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -5831,9 +5898,10 @@ void reply_mv(connection_struct *conn, struct smb_request *req) * TODO: check error codes on all callers */ -NTSTATUS copy_file(connection_struct *conn, - char *src, - char *dest1, +NTSTATUS copy_file(TALLOC_CTX *ctx, + connection_struct *conn, + const char *src, + const char *dest1, int ofun, int count, BOOL target_is_directory) @@ -5841,24 +5909,32 @@ NTSTATUS copy_file(connection_struct *conn, SMB_STRUCT_STAT src_sbuf, sbuf2; SMB_OFF_T ret=-1; files_struct *fsp1,*fsp2; - pstring dest; + char *dest = NULL; uint32 dosattrs; uint32 new_create_disposition; NTSTATUS status; - - pstrcpy(dest,dest1); + + dest = talloc_strdup(ctx, dest1); + if (!dest) { + return NT_STATUS_NO_MEMORY; + } if (target_is_directory) { - char *p = strrchr_m(src,'/'); + const char *p = strrchr_m(src,'/'); if (p) { p++; } else { p = src; } - pstrcat(dest,"/"); - pstrcat(dest,p); + dest = talloc_asprintf_append(dest, + "/%s", + p); + if (!dest) { + return NT_STATUS_NO_MEMORY; + } } if (!vfs_file_exist(conn,src,&src_sbuf)) { + TALLOC_FREE(dest); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -5867,6 +5943,7 @@ NTSTATUS copy_file(connection_struct *conn, } else { if (!map_open_params_to_ntcreate(dest1,0,ofun, NULL, NULL, &new_create_disposition, NULL)) { + TALLOC_FREE(dest); return NT_STATUS_INVALID_PARAMETER; } } @@ -5881,6 +5958,7 @@ NTSTATUS copy_file(connection_struct *conn, NULL, &fsp1); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(dest); return status; } @@ -5898,6 +5976,8 @@ NTSTATUS copy_file(connection_struct *conn, INTERNAL_OPEN_ONLY, NULL, &fsp2); + TALLOC_FREE(dest); + if (!NT_STATUS_IS_OK(status)) { close_file(fsp1,ERROR_CLOSE); return status; @@ -5913,7 +5993,7 @@ NTSTATUS copy_file(connection_struct *conn, src_sbuf.st_size = 0; } } - + if (src_sbuf.st_size) { ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); } @@ -5950,8 +6030,8 @@ void reply_copy(connection_struct *conn, struct smb_request *req) { char *name = NULL; char *newname = NULL; - pstring directory; - pstring mask; + char *directory = NULL; + char *mask = NULL; char *p; int count=0; int error = ERRnoaccess; @@ -5978,8 +6058,6 @@ void reply_copy(connection_struct *conn, struct smb_request *req) ofun = SVAL(req->inbuf,smb_vwv1); flags = SVAL(req->inbuf,smb_vwv2); - *directory = *mask = 0; - p = smb_buf(req->inbuf); p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p, 0, STR_TERMINATE, &status, @@ -6080,12 +6158,22 @@ void reply_copy(connection_struct *conn, struct smb_request *req) p = strrchr_m(name,'/'); if (!p) { - pstrcpy(directory,"./"); - pstrcpy(mask,name); + directory = talloc_strdup(ctx, "./"); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBcopy); + return; + } + mask = name; } else { *p = 0; - pstrcpy(directory,name); - pstrcpy(mask,p+1); + directory = talloc_strdup(ctx, name); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBcopy); + return; + } + mask = p+1; } /* @@ -6099,21 +6187,22 @@ void reply_copy(connection_struct *conn, struct smb_request *req) if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) { char *new_mask = NULL; - mangle_lookup_name_from_8_3( talloc_tos(), + mangle_lookup_name_from_8_3(ctx, mask, &new_mask, conn->params ); if (new_mask) { - pstrcpy(mask, new_mask); + mask = new_mask; } } if (!source_has_wild) { - pstrcat(directory,"/"); - pstrcat(directory,mask); + directory = talloc_asprintf_append(directory, + "/%s", + mask); if (dest_has_wild) { char *mod_newname = NULL; - if (!resolve_wildcards(talloc_tos(), + if (!resolve_wildcards(ctx, directory,newname,&mod_newname)) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBcopy); @@ -6135,9 +6224,9 @@ void reply_copy(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBcopy); return; } - - status = copy_file(conn,directory,newname,ofun, - count,target_is_directory); + + status = copy_file(ctx,conn,directory,newname,ofun, + count,target_is_directory); if(!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -6148,12 +6237,13 @@ void reply_copy(connection_struct *conn, struct smb_request *req) } } else { struct smb_Dir *dir_hnd = NULL; - const char *dname; + const char *dname = NULL; long offset = 0; - pstring destname; - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); + if (strequal(mask,"????????.???")) { + mask[0] = '*'; + mask[1] = '\0'; + } status = check_name(conn, directory); if (!NT_STATUS_IS_OK(status)) { @@ -6161,7 +6251,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBcopy); return; } - + dir_hnd = OpenDir(conn, directory, mask, 0); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); @@ -6173,26 +6263,41 @@ void reply_copy(connection_struct *conn, struct smb_request *req) error = ERRbadfile; while ((dname = ReadDirName(dir_hnd, &offset))) { - char *mod_destname = NULL; - pstring fname; - pstrcpy(fname,dname); - + char *destname = NULL; + char *fname = NULL; + + if (ISDOT(dname) || ISDOTDOT(dname)) { + continue; + } + if (!is_visible_file(conn, directory, dname, &sbuf1, False)) { continue; } - if(!mask_match(fname, mask, conn->case_sensitive)) { + if(!mask_match(dname, mask, conn->case_sensitive)) { continue; } error = ERRnoaccess; - slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); - pstrcpy(destname,newname); - if (!resolve_wildcards(talloc_tos(), - fname,destname,&mod_destname)) { + fname = talloc_asprintf(ctx, + "%s/%s", + directory, + dname); + if (!fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBcopy); + return; + } + + if (!resolve_wildcards(ctx, + fname,newname,&destname)) { continue; } - pstrcpy(destname,mod_destname); + if (!destname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBcopy); + return; + } status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { @@ -6200,25 +6305,27 @@ void reply_copy(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBcopy); return; } - + status = check_name(conn, destname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); return; } - + DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname)); - status = copy_file(conn,fname,destname,ofun, + status = copy_file(ctx,conn,fname,destname,ofun, count,target_is_directory); if (NT_STATUS_IS_OK(status)) { count++; } + TALLOC_FREE(fname); + TALLOC_FREE(destname); } CloseDir(dir_hnd); } - + if (count == 0) { if(err) { /* Error on close... */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index aeb0e0f31d..4daa2924a2 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -52,7 +52,7 @@ static BOOL canonicalize_path(connection_struct *conn, pstring path) Observent people will notice a similarity between this and check_path_syntax :-). ****************************************************************************/ -void set_conn_connectpath(connection_struct *conn, const pstring connectpath) +void set_conn_connectpath(connection_struct *conn, const char *connectpath) { pstring destname; char *d = destname; @@ -1117,27 +1117,31 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, strerror(errno) )); } change_to_root_user(); - /* Call VFS disconnect hook */ + /* Call VFS disconnect hook */ SMB_VFS_DISCONNECT(conn); yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } - + string_set(&conn->origpath,conn->connectpath); - + #if SOFTLINK_OPTIMISATION /* resolve any soft links early if possible */ if (vfs_ChDir(conn,conn->connectpath) == 0) { - pstring s; - pstrcpy(s,conn->connectpath); - vfs_GetWd(conn,s); + TALLOC_CTX *ctx = talloc_stackframe(); + char *s = vfs_GetWd(ctx,s); + if (!s) { + *status = map_nt_error_from_unix(errno); + return NULL; + } set_conn_connectpath(conn,s); vfs_ChDir(conn,conn->connectpath); + TALLOC_FREE(ctx); } #endif - + /* * Print out the 'connected as' stuff here as we need * to know the effective uid and gid we will be using @@ -1153,7 +1157,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)sys_getpid() ); } - + /* we've finished with the user stuff - go back to root */ change_to_root_user(); return(conn); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8e03094aef..63dcb06f5d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. SMB transaction2 handling Copyright (C) Jeremy Allison 1994-2007 @@ -13,12 +13,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 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, see . */ @@ -211,7 +211,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str if (strnequal(p, "system.", 7) || samba_private_attr_name(p)) continue; - + listp = TALLOC_P(mem_ctx, struct ea_list); if (!listp) return NULL; @@ -1008,7 +1008,9 @@ static void call_trans2open(connection_struct *conn, Case can be significant or not. **********************************************************/ -static BOOL exact_match(connection_struct *conn, char *str, char *mask) +static BOOL exact_match(connection_struct *conn, + const char *str, + const char *mask) { if (mask[0] == '.' && mask[1] == 0) return False; @@ -1134,21 +1136,29 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn, Get a level dependent lanman2 dir entry. ****************************************************************************/ -static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, - char *path_mask,uint32 dirtype,int info_level, - int requires_resume_key, - BOOL dont_descend,char **ppdata, - char *base_data, char *end_data, - int space_remaining, - BOOL *out_of_space, BOOL *got_exact_match, - int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx) +static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + uint16 flags2, + const char *path_mask, + uint32 dirtype, + int info_level, + int requires_resume_key, + BOOL dont_descend, + char **ppdata, + char *base_data, + char *end_data, + int space_remaining, + BOOL *out_of_space, + BOOL *got_exact_match, + int *last_entry_off, + struct ea_list *name_list) { const char *dname; BOOL found = False; SMB_STRUCT_STAT sbuf; - pstring mask; - pstring pathreal; - pstring fname; + const char *mask = NULL; + char *pathreal = NULL; + const char *fname = NULL; char *p, *q, *pdata = *ppdata; uint32 reskey=0; long prev_dirpos=0; @@ -1166,7 +1176,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, BOOL check_mangled_names = lp_manglednames(conn->params); char mangled_name[13]; /* mangled 8.3 name. */ - *fname = 0; *out_of_space = False; *got_exact_match = False; @@ -1174,18 +1183,20 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, ZERO_STRUCT(adate_ts); ZERO_STRUCT(create_date_ts); - if (!conn->dirptr) + if (!conn->dirptr) { return(False); + } p = strrchr_m(path_mask,'/'); if(p != NULL) { - if(p[1] == '\0') - pstrcpy(mask,"*.*"); - else - pstrcpy(mask, p+1); - } else - pstrcpy(mask, path_mask); - + if(p[1] == '\0') { + mask = talloc_strdup(ctx,"*.*"); + } else { + mask = p+1; + } + } else { + mask = path_mask; + } while (!found) { BOOL got_match; @@ -1193,7 +1204,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, /* Needed if we run out of space */ long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr); - dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf); + dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf); /* * Due to bugs in NT client redirectors we are not using @@ -1206,7 +1217,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n", (long)conn->dirptr,curr_dirpos)); - + if (!dname) { return(False); } @@ -1217,14 +1228,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, * pathreal which is composed from dname. */ - pstrcpy(fname,dname); + pathreal = NULL; + fname = dname; /* Mangle fname if it's an illegal name. */ - if (mangle_must_mangle(fname,conn->params)) { - if (!name_to_8_3(fname,mangled_name,True,conn->params)) { + if (mangle_must_mangle(dname,conn->params)) { + if (!name_to_8_3(dname,mangled_name,True,conn->params)) { continue; /* Error - couldn't mangle. */ } - pstrcpy(fname,mangled_name); + fname = mangled_name; } if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) { @@ -1250,21 +1262,34 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, } if (got_match) { - BOOL isdots = (strequal(dname,"..") || strequal(dname,".")); + BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname)); + if (dont_descend && !isdots) { continue; } - - pstrcpy(pathreal,conn->dirpath); - if(needslash) { - pstrcat(pathreal,"/"); + + if (needslash) { + pathreal = NULL; + pathreal = talloc_asprintf(ctx, + "%s/%s", + conn->dirpath, + dname); + } else { + pathreal = talloc_asprintf(ctx, + "%s%s", + conn->dirpath, + dname); + } + + if (!pathreal) { + return False; } - pstrcat(pathreal,dname); if (INFO_LEVEL_IS_UNIX(info_level)) { if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n", pathreal,strerror(errno))); + TALLOC_FREE(pathreal); continue; } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { @@ -1283,6 +1308,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", pathreal,strerror(errno))); + TALLOC_FREE(pathreal); continue; } } @@ -1295,6 +1321,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, if (!dir_check_ftype(conn,mode,dirtype)) { DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype)); + TALLOC_FREE(pathreal); continue; } @@ -1316,9 +1343,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, create_date = convert_timespec_to_time_t(create_date_ts); mdate = convert_timespec_to_time_t(mdate_ts); adate = convert_timespec_to_time_t(adate_ts); - + DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname)); - + found = True; dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos); @@ -1425,7 +1452,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, SSVAL(p,20,mode); p += 22; /* p now points to the EA area. */ - file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len); + file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len); name_list = ea_list_union(name_list, file_list, &ea_len); /* We need to determine if this entry will fit in the space available. */ @@ -1439,7 +1466,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, } /* Push the ea_data followed by the name. */ - p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list); + p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); nameptr = p; len = srvstr_push(base_data, flags2, p + 1, fname, PTR_DIFF(end_data, p), @@ -1537,7 +1564,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, SIVAL(pdata,0,len); p = pdata + len; break; - + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); p += 4; @@ -1713,7 +1740,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2, break; - default: + default: return(False); } @@ -1760,7 +1787,7 @@ static void call_trans2findfirst(connection_struct *conn, BOOL requires_resume_key; int info_level; char *directory = NULL; - pstring mask; + const char *mask = NULL; char *p; int last_entry_off=0; int dptr_num = -1; @@ -1772,7 +1799,6 @@ static void call_trans2findfirst(connection_struct *conn, int space_remaining; BOOL mask_contains_wcard = False; SMB_STRUCT_STAT sbuf; - TALLOC_CTX *ea_ctx = NULL; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; TALLOC_CTX *ctx = talloc_tos(); @@ -1790,8 +1816,6 @@ static void call_trans2findfirst(connection_struct *conn, requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); info_level = SVAL(params,6); - *mask = 0; - DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, @@ -1864,10 +1888,10 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", if(p == NULL) { /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */ if((directory[0] == '.') && (directory[1] == '\0')) { - pstrcpy(mask,"*"); + mask = "*"; mask_contains_wcard = True; } else { - pstrcpy(mask,directory); + mask = directory; } directory = talloc_strdup(talloc_tos(), "./"); if (!directory) { @@ -1875,7 +1899,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return; } } else { - pstrcpy(mask,p+1); + mask = p+1; *p = 0; } @@ -1901,16 +1925,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd reply_doserror(req, ERRDOS, ERReasnotsupported); return; } - - if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } /* Pull out the list of names. */ - ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); + ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4); if (!ea_list) { - talloc_destroy(ea_ctx); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } @@ -1919,7 +1937,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *ppdata = (char *)SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(*ppdata == NULL ) { - talloc_destroy(ea_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -1929,7 +1946,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Realloc the params space */ *pparams = (char *)SMB_REALLOC(*pparams, 10); if (*pparams == NULL) { - talloc_destroy(ea_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -1949,7 +1965,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd &conn->dirptr); if (!NT_STATUS_IS_OK(ntstatus)) { - talloc_destroy(ea_ctx); reply_nterror(req, ntstatus); return; } @@ -1957,13 +1972,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd dptr_num = dptr_dnum(conn->dirptr); DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype)); - /* We don't need to check for VOL here as this is returned by + /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ - + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn)))); if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; - + p = pdata; space_remaining = max_data_bytes; out_of_space = False; @@ -1977,14 +1992,19 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd out_of_space = True; finished = False; } else { - finished = !get_lanman2_dir_entry(conn, + TALLOC_CTX *sub_ctx = talloc_stackframe(); + + finished = !get_lanman2_dir_entry(sub_ctx, + conn, req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,data_end, space_remaining, &out_of_space, &got_exact_match, - &last_entry_off, ea_list, ea_ctx); + &last_entry_off, ea_list); + + TALLOC_FREE(sub_ctx); } if (finished && out_of_space) @@ -2005,8 +2025,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd space_remaining = max_data_bytes - PTR_DIFF(p,pdata); } - - talloc_destroy(ea_ctx); /* Check if we can close the dirptr */ if(close_after_first || (finished && close_if_end)) { @@ -2014,8 +2032,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd dptr_close(&dptr_num); } - /* - * If there are no matching entries we must return ERRDOS/ERRbadfile - + /* + * If there are no matching entries we must return ERRDOS/ERRbadfile - * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if * the protocol level is less than NT1. Tested with smbclient. JRA. * This should fix the OS/2 client bug #2335. @@ -2101,9 +2119,9 @@ static void call_trans2findnext(connection_struct *conn, BOOL continue_bit; BOOL mask_contains_wcard = False; char *resume_name = NULL; - pstring mask; - pstring directory; - char *p; + const char *mask = NULL; + const char *directory = NULL; + char *p = NULL; uint16 dirtype; int numentries = 0; int i, last_entry_off=0; @@ -2111,7 +2129,6 @@ static void call_trans2findnext(connection_struct *conn, BOOL dont_descend = False; BOOL out_of_space = False; int space_remaining; - TALLOC_CTX *ea_ctx = NULL; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; TALLOC_CTX *ctx = talloc_tos(); @@ -2131,8 +2148,6 @@ static void call_trans2findnext(connection_struct *conn, requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); - *mask = *directory = 0; - srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name, params+12, total_params - 12, STR_TERMINATE, &ntstatus, @@ -2202,21 +2217,15 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } - + if (!lp_ea_support(SNUM(conn))) { reply_doserror(req, ERRDOS, ERReasnotsupported); return; } - - if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } /* Pull out the list of names. */ - ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); + ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4); if (!ea_list) { - talloc_destroy(ea_ctx); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } @@ -2225,7 +2234,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *ppdata = (char *)SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(*ppdata == NULL) { - talloc_destroy(ea_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -2236,7 +2244,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Realloc the params space */ *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD); if(*pparams == NULL ) { - talloc_destroy(ea_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -2245,7 +2252,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Check that the dptr is valid */ if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { - talloc_destroy(ea_ctx); reply_doserror(req, ERRDOS, ERRnofiles); return; } @@ -2255,34 +2261,33 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Get the wildcard mask from the dptr */ if((p = dptr_wcard(dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); - talloc_destroy(ea_ctx); reply_doserror(req, ERRDOS, ERRnofiles); return; } - pstrcpy(mask, p); - pstrcpy(directory,conn->dirpath); + mask = p; + directory = conn->dirpath; /* Get the attr mask from the dptr */ dirtype = dptr_attr(dptr_num); DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n", - dptr_num, mask, dirtype, + dptr_num, mask, dirtype, (long)conn->dirptr, dptr_TellDir(conn->dirptr))); - /* We don't need to check for VOL here as this is returned by + /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn)))); if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; - + p = pdata; space_remaining = max_data_bytes; out_of_space = False; - /* + /* * Seek to the correct position. We no longer use the resume key but * depend on the last file name instead. */ @@ -2299,12 +2304,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (mangle_is_mangled(resume_name, conn->params)) { char *new_resume_name = NULL; - mangle_lookup_name_from_8_3(talloc_tos(), + mangle_lookup_name_from_8_3(ctx, resume_name, &new_resume_name, conn->params); if (new_resume_name) { - pstrcpy(resume_name, new_resume_name); + resume_name = new_resume_name; } } @@ -2329,14 +2334,19 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd out_of_space = True; finished = False; } else { - finished = !get_lanman2_dir_entry(conn, + TALLOC_CTX *sub_ctx = talloc_stackframe(); + + finished = !get_lanman2_dir_entry(sub_ctx, + conn, req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,data_end, space_remaining, &out_of_space, &got_exact_match, - &last_entry_off, ea_list, ea_ctx); + &last_entry_off, ea_list); + + TALLOC_FREE(sub_ctx); } if (finished && out_of_space) @@ -2357,8 +2367,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd space_remaining = max_data_bytes - PTR_DIFF(p,pdata); } - - talloc_destroy(ea_ctx); + + DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", + smb_fn_name(CVAL(req->inbuf,smb_com)), + mask, directory, dirtype, numentries ) ); /* Check if we can close the dirptr */ if(close_after_request || (finished && close_if_end)) { @@ -2375,13 +2387,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes); - if ((! *directory) && dptr_path(dptr_num)) - slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); - - DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", - smb_fn_name(CVAL(req->inbuf,smb_com)), - mask, directory, dirtype, numentries ) ); - return; } @@ -3511,7 +3516,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, unsigned int data_size = 0; unsigned int param_size = 2; SMB_STRUCT_STAT sbuf; - pstring dos_fname; + char *dos_fname = NULL; char *fname = NULL; char *fullpathname; char *base_name; @@ -3523,7 +3528,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, struct timespec create_time_ts, mtime_ts, atime_ts; files_struct *fsp = NULL; struct file_id fileid; - TALLOC_CTX *data_ctx = NULL; struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ char *lock_data = NULL; @@ -3712,7 +3716,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n", fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data)); - p = strrchr_m(fname,'/'); + p = strrchr_m(fname,'/'); if (!p) base_name = fname; else @@ -3754,15 +3758,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return; } - if ((data_ctx = talloc_init("ea_list")) == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - /* Pull out the list of names. */ - ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4); + ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4); if (!ea_list) { - talloc_destroy(data_ctx); reply_nterror( req, NT_STATUS_INVALID_PARAMETER); return; @@ -3783,16 +3781,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return; } - if ((data_ctx = talloc_init("lock_request")) == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - /* Copy the lock range data. */ lock_data = (char *)TALLOC_MEMDUP( - data_ctx, pdata, total_data); + ctx, pdata, total_data); if (!lock_data) { - talloc_destroy(data_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -3803,7 +3795,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *pparams = (char *)SMB_REALLOC(*pparams,2); if (*pparams == NULL) { - talloc_destroy(data_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -3812,7 +3803,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); if (*ppdata == NULL ) { - talloc_destroy(data_ctx); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -3857,10 +3847,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* NT expects the name to be in an exact form of the *full* filename. See the trans2 torture test */ - if (strequal(base_name,".")) { - pstrcpy(dos_fname, "\\"); + if (ISDOT(base_name)) { + dos_fname = talloc_strdup(ctx, "\\"); + if (!dos_fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } } else { - pstr_sprintf(dos_fname, "\\%s", fname); + dos_fname = talloc_asprintf(ctx, + "\\%s", + fname); + if (!dos_fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } string_replace(dos_fname, '/', '\\'); } @@ -3894,14 +3894,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_INFO_IS_NAME_VALID: DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n")); if (tran_call == TRANSACT2_QFILEINFO) { - /* os/2 needs this ? really ?*/ + /* os/2 needs this ? really ?*/ reply_doserror(req, ERRDOS, ERRbadfunc); return; } data_size = 0; param_size = 0; break; - + case SMB_INFO_QUERY_EAS_FROM_LIST: { size_t total_ea_len = 0; @@ -3909,18 +3909,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); - ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len); + ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len); ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len); if (!ea_list || (total_ea_len > data_size)) { - talloc_destroy(data_ctx); data_size = 4; SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ break; } - data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list); - talloc_destroy(data_ctx); + data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list); break; } @@ -3931,22 +3929,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); - data_ctx = talloc_init("ea_ctx"); - if (!data_ctx) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len); + ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len); if (!ea_list || (total_ea_len > data_size)) { - talloc_destroy(data_ctx); data_size = 4; SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ break; } - data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list); - talloc_destroy(data_ctx); + data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list); break; } @@ -4219,7 +4209,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_UNIX_LINK: { - pstring buffer; + char *buffer = TALLOC_SIZE(ctx, 1024); + + if (!buffer) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK @@ -4232,7 +4227,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd reply_unixerror(req, ERRDOS, ERRbadlink); return; #endif - len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ + len = SMB_VFS_READLINK(conn,fullpathname, + buffer, 1023); if (len == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); @@ -4364,7 +4360,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case POSIX_LOCK_TYPE_UNLOCK: default: /* There's no point in asking for an unlock... */ - talloc_destroy(data_ctx); reply_nterror( req, NT_STATUS_INVALID_PARAMETER); @@ -4860,21 +4855,32 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, /* !widelinks forces the target path to be within the share. */ /* This means we can interpret the target as a pathname. */ if (!lp_widelinks(SNUM(conn))) { - pstring rel_name; + char *rel_name = NULL; char *last_dirp = NULL; if (*link_target == '/') { /* No absolute paths allowed. */ return NT_STATUS_ACCESS_DENIED; } - pstrcpy(rel_name, newname); + rel_name = talloc_strdup(ctx,newname); + if (!rel_name) { + return NT_STATUS_NO_MEMORY; + } last_dirp = strrchr_m(rel_name, '/'); if (last_dirp) { last_dirp[1] = '\0'; } else { - pstrcpy(rel_name, "./"); + rel_name = talloc_strdup(ctx,"./"); + if (!rel_name) { + return NT_STATUS_NO_MEMORY; + } + } + rel_name = talloc_asprintf_append(ctx, + "%s", + link_target); + if (!rel_name) { + return NT_STATUS_NO_MEMORY; } - pstrcat(rel_name, link_target); status = check_name(conn, rel_name); if (!NT_STATUS_IS_OK(status)) { @@ -4945,7 +4951,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, uint32 root_fid; uint32 len; char *newname = NULL; - pstring base_name; + char *base_name = NULL; BOOL dest_has_wcard = False; NTSTATUS status = NT_STATUS_OK; char *p; @@ -4988,15 +4994,26 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, } /* Create the base directory. */ - pstrcpy(base_name, fname); + base_name = talloc_strdup(ctx, fname); + if (!base_name) { + return NT_STATUS_NO_MEMORY; + } p = strrchr_m(base_name, '/'); if (p) { p[1] = '\0'; } else { - pstrcpy(base_name, "./"); + base_name = talloc_strdup(ctx, "./"); + if (!base_name) { + return NT_STATUS_NO_MEMORY; + } } /* Append the new name. */ - pstrcat(base_name, newname); + base_name = talloc_asprintf_append(base_name, + "%s", + newname); + if (!base_name) { + return NT_STATUS_NO_MEMORY; + } if (fsp) { SMB_STRUCT_STAT sbuf; @@ -5026,7 +5043,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, } else { DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, base_name )); - status = rename_internals(conn, req, fname, base_name, 0, + status = rename_internals(ctx, conn, req, fname, base_name, 0, overwrite, False, dest_has_wcard); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f9a5ba5ed6..d9c772d6b1 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -653,7 +653,11 @@ char *vfs_readdirname(connection_struct *conn, void *p) int vfs_ChDir(connection_struct *conn, const char *path) { int res; - static pstring LastDir=""; + static char *LastDir = NULL; + + if (!LastDir) { + LastDir = SMB_STRDUP(""); + } if (strcsequal(path,".")) return(0); @@ -664,8 +668,10 @@ int vfs_ChDir(connection_struct *conn, const char *path) DEBUG(4,("vfs_ChDir to %s\n",path)); res = SMB_VFS_CHDIR(conn,path); - if (!res) - pstrcpy(LastDir,path); + if (!res) { + SAFE_FREE(LastDir); + LastDir = SMB_STRDUP(path); + } return(res); } @@ -675,7 +681,7 @@ int vfs_ChDir(connection_struct *conn, const char *path) static 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 *dos_path; /* The pathname in DOS format. */ + char *path; /* The pathname. */ BOOL valid; } ino_list[MAX_GETWDCACHE]; @@ -710,23 +716,36 @@ static void array_promote(char *array,int elsize,int element) format. Note this can be called with conn == NULL. ********************************************************************/ -char *vfs_GetWd(connection_struct *conn, char *path) +char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) { +#ifdef PATH_MAX + char s[PATH_MAX+1]; +#else pstring s; +#endif static BOOL getwd_cache_init = False; SMB_STRUCT_STAT st, st2; int i; + char *ret = NULL; *s = 0; - if (!use_getwd_cache) - return(SMB_VFS_GETWD(conn,path)); + if (!use_getwd_cache) { + nocache: + ret = SMB_VFS_GETWD(conn,s); + if (!ret) { + DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, " + "errno %s\n",strerror(errno))); + return NULL; + } + return talloc_strdup(ctx, ret); + } /* init the cache */ if (!getwd_cache_init) { getwd_cache_init = True; for (i=0;i University of Geneva */ - + #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; -- cgit From d5c9d87946263b5f3e3c072aa99e8ac6a6c728b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Sep 2007 23:50:21 +0000 Subject: r25118: More pstring elimination. Jeremy. (This used to be commit 7632f8fb4003657591778d2b55f546d1737859d1) --- source3/smbd/close.c | 103 +++++++++++++++++++++++++++++---------------------- source3/smbd/dfree.c | 14 +++++-- source3/smbd/pipes.c | 16 +++++--- 3 files changed, 80 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 40db9f9b7f..aee1c92f7b 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -1,20 +1,20 @@ -/* +/* Unix SMB/CIFS implementation. file closing Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1992-2007. Copyright (C) Volker Lendecke 2005 - + 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 3 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, see . */ @@ -29,60 +29,73 @@ extern struct current_user current_user; static void check_magic(files_struct *fsp,connection_struct *conn) { - if (!*lp_magicscript(SNUM(conn))) + int ret; + const char *magic_output = NULL; + SMB_STRUCT_STAT st; + int tmp_fd, outfd; + TALLOC_CTX *ctx = NULL; + const char *p; + + if (!*lp_magicscript(SNUM(conn))) { return; + } DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); - { - char *p; - if (!(p = strrchr_m(fsp->fsp_name,'/'))) - p = fsp->fsp_name; - else - p++; + if (!(p = strrchr_m(fsp->fsp_name,'/'))) { + p = fsp->fsp_name; + } else { + p++; + } - if (!strequal(lp_magicscript(SNUM(conn)),p)) - return; + if (!strequal(lp_magicscript(SNUM(conn)),p)) { + return; } - { - int ret; - pstring magic_output; - pstring fname; - SMB_STRUCT_STAT st; - int tmp_fd, outfd; - - pstrcpy(fname,fsp->fsp_name); - if (*lp_magicoutput(SNUM(conn))) - pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); - else - slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); - - chmod(fname,0755); - ret = smbrun(fname,&tmp_fd); - DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); - unlink(fname); - if (ret != 0 || tmp_fd == -1) { - if (tmp_fd != -1) - close(tmp_fd); - return; - } - outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); - if (outfd == -1) { - close(tmp_fd); - return; - } + ctx = talloc_stackframe(); + + if (*lp_magicoutput(SNUM(conn))) { + magic_output = lp_magicoutput(SNUM(conn)); + } else { + magic_output = talloc_asprintf(ctx, + "%s.out", + fsp->fsp_name); + } + if (!magic_output) { + TALLOC_FREE(ctx); + return; + } - if (sys_fstat(tmp_fd,&st) == -1) { + chmod(fsp->fsp_name,0755); + ret = smbrun(fsp->fsp_name,&tmp_fd); + DEBUG(3,("Invoking magic command %s gave %d\n", + fsp->fsp_name,ret)); + + unlink(fsp->fsp_name); + if (ret != 0 || tmp_fd == -1) { + if (tmp_fd != -1) { close(tmp_fd); - close(outfd); - return; } + TALLOC_FREE(ctx); + return; + } + outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); + if (outfd == -1) { + close(tmp_fd); + TALLOC_FREE(ctx); + return; + } - transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size); + if (sys_fstat(tmp_fd,&st) == -1) { close(tmp_fd); close(outfd); + return; } + + transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size); + close(tmp_fd); + close(outfd); + TALLOC_FREE(ctx); } /**************************************************************************** @@ -90,7 +103,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn) ****************************************************************************/ static NTSTATUS close_filestruct(files_struct *fsp) -{ +{ NTSTATUS status = NT_STATUS_OK; connection_struct *conn = fsp->conn; diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 2290558f0a..9439468600 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -81,10 +81,18 @@ SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small dfree_command = lp_dfree_command(SNUM(conn)); if (dfree_command && *dfree_command) { const char *p; - char **lines; - pstring syscmd; + char **lines = NULL; + char *syscmd = NULL; + + syscmd = talloc_asprintf(talloc_tos(), + "%s %s", + dfree_command, + path); + + if (!syscmd) { + return (SMB_BIG_UINT)-1; + } - slprintf(syscmd, sizeof(syscmd)-1, "%s %s", dfree_command, path); DEBUG (3, ("disk_free: Running command %s\n", syscmd)); lines = file_lines_pload(syscmd, NULL); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index f43e243453..9906bfb45b 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -55,15 +55,21 @@ extern struct pipe_id_info pipe_names[]; void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) { - pstring fname; - pstring pipe_name; + const char *fname = NULL; + char *pipe_name = NULL; smb_np_struct *p; int size=0,fmode=0,mtime=0,rmode=0; int i; + TALLOC_CTX *ctx = talloc_tos(); /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull_buf(req->inbuf, req->flags2, pipe_name, - smb_buf(req->inbuf), sizeof(pipe_name), STR_TERMINATE); + srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &pipe_name, + smb_buf(req->inbuf), STR_TERMINATE); + if (!pipe_name) { + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpipe); + return; + } /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ @@ -89,7 +95,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) } /* Strip \PIPE\ off the name. */ - pstrcpy(fname, pipe_name + PIPELEN); + fname = pipe_name + PIPELEN; #if 0 /* -- cgit From 1a292def316a3d464dd4ad66dc23aa7cbde33b20 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 13 Sep 2007 16:48:46 +0000 Subject: r25135: Remove one END_PROFILE(SMBntcreateX) from call_nt_transact_create() which appears to be a leftover. Should fix the build with profiling enabled. Jeremy, please check. Guenther (This used to be commit 98f2e10e3f7a86b1b30619a25ee15a489ad10d43) --- source3/smbd/nttrans.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c40fbc763c..452533629c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1396,7 +1396,6 @@ static void call_nt_transact_create(connection_struct *conn, if (!fname) { reply_nterror( req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBntcreateX); return; } memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); -- cgit From eacd3140573d1122a3785823e4003bfc6352c431 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Sep 2007 22:08:59 +0000 Subject: r25138: More pstring elimination. Add a TALLOC_CTX parameter to unix_convert(). Jeremy. (This used to be commit 39c211a702e91c34c1a5a689e1b0c4530ea8a1ac) --- source3/smbd/filename.c | 4 ++-- source3/smbd/lanman.c | 2 +- source3/smbd/msdfs.c | 2 +- source3/smbd/nttrans.c | 24 +++++++++++++----------- source3/smbd/reply.c | 37 ++++++++++++++++++++----------------- source3/smbd/trans2.c | 22 ++++++++++++---------- 6 files changed, 49 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 27f17f9628..f15c107711 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -107,7 +107,8 @@ stat struct will be filled with zeros (and this can be detected by checking for nlinks = 0, which can never be true for any file). ****************************************************************************/ -NTSTATUS unix_convert(connection_struct *conn, +NTSTATUS unix_convert(TALLOC_CTX *ctx, + connection_struct *conn, const char *orig_path, BOOL allow_wcard_last_component, char **pp_conv_path, @@ -121,7 +122,6 @@ NTSTATUS unix_convert(connection_struct *conn, BOOL component_was_mangled = False; BOOL name_has_wildcard = False; NTSTATUS result; - TALLOC_CTX *ctx = talloc_tos(); SET_STAT_INVALID(*pst); *pp_conv_path = NULL; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 37fcc658db..87cbc9183e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -415,7 +415,7 @@ static void PackDriverData(struct pack_desc* desc) SIVAL(drivdata,0,sizeof drivdata); /* cb */ SIVAL(drivdata,4,1000); /* lVersion */ memset(drivdata+8,0,32); /* szDeviceName */ - push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE); + push_ascii(drivdata+8,"NULL",32, STR_TERMINATE); PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 5cbe8c68ac..1917eb4d10 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -476,7 +476,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, * think this is needed. JRA. */ - status = unix_convert(conn, pdp->reqpath, search_flag, &localpath, + status = unix_convert(ctx, conn, pdp->reqpath, search_flag, &localpath, NULL, &sbuf); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 452533629c..14a11c3fe3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -745,7 +745,7 @@ void reply_ntcreate_and_X(connection_struct *conn, file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); reply_nterror(req, status); @@ -1479,7 +1479,7 @@ static void call_nt_transact_create(connection_struct *conn, return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); reply_nterror(req, status); @@ -1817,11 +1817,12 @@ void reply_ntcancel(connection_struct *conn, struct smb_request *req) Copy a file. ****************************************************************************/ -static NTSTATUS copy_internals(connection_struct *conn, - struct smb_request *req, - const char *oldname_in, - const char *newname_in, - uint32 attrs) +static NTSTATUS copy_internals(TALLOC_CTX *ctx, + connection_struct *conn, + struct smb_request *req, + const char *oldname_in, + const char *newname_in, + uint32 attrs) { SMB_STRUCT_STAT sbuf1, sbuf2; char *oldname = NULL; @@ -1841,7 +1842,7 @@ static NTSTATUS copy_internals(connection_struct *conn, return NT_STATUS_MEDIA_WRITE_PROTECTED; } - status = unix_convert(conn, oldname_in, False, &oldname, + status = unix_convert(ctx, conn, oldname_in, False, &oldname, &last_component_oldname, &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; @@ -1862,7 +1863,7 @@ static NTSTATUS copy_internals(connection_struct *conn, return NT_STATUS_NO_SUCH_FILE; } - status = unix_convert(conn, newname_in, False, &newname, + status = unix_convert(ctx, conn, newname_in, False, &newname, &last_component_newname, &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; @@ -2058,7 +2059,8 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { - status = hardlink_internals(conn, + status = hardlink_internals(ctx, + conn, oldname, newname); } @@ -2068,7 +2070,7 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { - status = copy_internals(conn, req, oldname, + status = copy_internals(ctx, conn, req, oldname, newname, attrs); } break; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b94c91fe8e..d6813bef80 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -879,7 +879,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0))); - status = unix_convert(conn, name, False, &name, NULL, &sbuf); + status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { goto path_err; } @@ -986,7 +986,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) size = 0; mtime = 0; } else { - status = unix_convert(conn, fname, False, &fname, NULL,&sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBgetatr); @@ -1081,7 +1081,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBsetatr); @@ -1107,7 +1107,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) mode = SVAL(req->inbuf,smb_vwv0); mtime = srv_make_unix_date3(req->inbuf+smb_vwv1); - + if (mode != FILE_ATTRIBUTE_NORMAL) { if (VALID_STAT_OF_DIR(sbuf)) mode |= aDIR; @@ -1279,7 +1279,8 @@ void reply_search(connection_struct *conn, struct smb_request *req) if (status_len == 0) { SMB_STRUCT_STAT sbuf; - nt_status = unix_convert(conn, path, True, &directory, NULL, &sbuf); + nt_status = unix_convert(ctx, conn, path, True, + &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); END_PROFILE(SMBsearch); @@ -1612,13 +1613,13 @@ void reply_open(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopen); return; } - + status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1776,7 +1777,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopenX); @@ -1996,7 +1997,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcreate); @@ -2132,7 +2133,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); @@ -2389,7 +2390,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, SMB_STRUCT_STAT sbuf; TALLOC_CTX *ctx = talloc_tos(); - status = unix_convert(conn, name_in, has_wild, &name, NULL, &sbuf); + status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4777,7 +4778,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, directory, False, &directory, NULL, &sbuf); + status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBmkdir); @@ -5045,7 +5046,7 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, directory, False, &directory, + status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -5530,13 +5531,13 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - status = unix_convert(conn, name_in, src_has_wild, &name, + status = unix_convert(ctx, conn, name_in, src_has_wild, &name, &last_component_src, &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; } - status = unix_convert(conn, newname_in, dest_has_wild, &newname, + status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname, &last_component_dest, &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; @@ -6120,14 +6121,16 @@ void reply_copy(connection_struct *conn, struct smb_request *req) return; } - status = unix_convert(conn, name, source_has_wild, &name, NULL, &sbuf1); + status = unix_convert(ctx, conn, name, source_has_wild, + &name, NULL, &sbuf1); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); return; } - status = unix_convert(conn, newname, dest_has_wild, &newname, NULL, &sbuf2); + status = unix_convert(ctx, conn, newname, dest_has_wild, + &newname, NULL, &sbuf2); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 63dcb06f5d..7af4bcee60 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -844,7 +844,7 @@ static void call_trans2open(connection_struct *conn, /* XXXX we need to handle passed times, sattr and flags */ - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -1872,7 +1872,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return; } - ntstatus = unix_convert(conn, directory, True, &directory, NULL, &sbuf); + ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); return; @@ -3664,7 +3664,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -4430,7 +4430,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd code. ****************************************************************************/ -NTSTATUS hardlink_internals(connection_struct *conn, +NTSTATUS hardlink_internals(TALLOC_CTX *ctx, + connection_struct *conn, const char *oldname_in, const char *newname_in) { @@ -4444,7 +4445,7 @@ NTSTATUS hardlink_internals(connection_struct *conn, ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); - status = unix_convert(conn, oldname_in, False, &oldname, + status = unix_convert(ctx, conn, oldname_in, False, &oldname, &last_component_oldname, &sbuf1); if (!NT_STATUS_IS_OK(status)) { return status; @@ -4460,7 +4461,7 @@ NTSTATUS hardlink_internals(connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - status = unix_convert(conn, newname_in, False, &newname, + status = unix_convert(ctx, conn, newname_in, False, &newname, &last_component_newname, &sbuf2); if (!NT_STATUS_IS_OK(status)) { return status; @@ -4933,7 +4934,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, oldname)); - return hardlink_internals(conn, oldname, fname); + return hardlink_internals(ctx, conn, oldname, fname); } /**************************************************************************** @@ -5021,7 +5022,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, ZERO_STRUCT(sbuf); - status = unix_convert(conn, newname, False, + status = unix_convert(ctx, conn, newname, False, &newname, &newname_last_component, &sbuf); @@ -6317,7 +6318,8 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - status = unix_convert(conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(ctx, conn, fname, False, + &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; @@ -6665,7 +6667,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - status = unix_convert(conn, directory, False, &directory, NULL, &sbuf); + status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); return; -- cgit From dd16ae2506abe46093118e2a33d9d0cae6455d07 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 01:07:57 +0000 Subject: r25141: More pstring removal. Jeremy. (This used to be commit cfcf7cf03e1be34e6839c1a659c4e8c1b5358c37) --- source3/smbd/oplock_irix.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index dde32fa288..9f81a960f5 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -33,17 +33,25 @@ static BOOL irix_oplocks_available(void) { int fd; int pfd[2]; - pstring tmpname; + TALLOC_CTX *ctx = talloc_stackframe(); + char *tmpname = NULL; set_effective_capability(KERNEL_OPLOCK_CAPABILITY); - slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), - (int)sys_getpid()); + tmpname = talloc_asprintf(ctx, + "%s/koplock.%d", + lp_lockdir(), + (int)sys_getpid()); + if (!tmpname) { + TALLOC_FREE(ctx); + return False; + } if(pipe(pfd) != 0) { DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error " "was %s\n", strerror(errno) )); + TALLOC_FREE(ctx); return False; } @@ -54,11 +62,14 @@ static BOOL irix_oplocks_available(void) unlink( tmpname ); close(pfd[0]); close(pfd[1]); + TALLOC_FREE(ctx); return False; } unlink(tmpname); + TALLOC_FREE(ctx); + if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) { DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not " "available on this machine. Disabling kernel oplock " -- cgit From 45a2713b475e66a880b4c6f019dc22119444dc7b Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 14 Sep 2007 04:17:17 +0000 Subject: r25142: Panic if setting the group list fails while switching security contexts. Patch from Tim Prouty . (This used to be commit a136de663f122603e8d34e06027896ff39b35e11) --- source3/smbd/sec_ctx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 67b15dc014..108d1794c7 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -239,7 +239,9 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou /* Start context switch */ gain_root(); #ifdef HAVE_SETGROUPS - sys_setgroups(gid, ngroups, groups); + if (sys_setgroups(gid, ngroups, groups) != 0) { + smb_panic("sys_setgroups failed"); + } #endif become_id(uid, gid); /* end context switch */ @@ -282,6 +284,7 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou DEBUG(0, ("WARNING: failed to set group list " "(%d groups) for UID %ld: %s\n", ngroups, uid, strerror(errno))); + smb_panic("sys_setgroups failed"); } become_uid(uid); -- cgit From 8b6366b301d3020223fbd6ac3dad42b1476b37f9 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 14 Sep 2007 15:08:07 +0000 Subject: r25161: Don't panic if setgroups fails in non-root mode. (This used to be commit ea226c5ed97d47649833546d5499213093d1925e) --- source3/smbd/sec_ctx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 108d1794c7..08d522cdd7 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -239,7 +239,7 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou /* Start context switch */ gain_root(); #ifdef HAVE_SETGROUPS - if (sys_setgroups(gid, ngroups, groups) != 0) { + if (sys_setgroups(gid, ngroups, groups) != 0 && !non_root_mode()) { smb_panic("sys_setgroups failed"); } #endif @@ -280,7 +280,7 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou if (syscall(SYS_initgroups, (ngroups > max) ? max : ngroups, - groups, uid) == 1) { + groups, uid) == -1 && !non_root_mode()) { DEBUG(0, ("WARNING: failed to set group list " "(%d groups) for UID %ld: %s\n", ngroups, uid, strerror(errno))); -- cgit From 539635cd94dd21dbc72f070fbd8a54c726091f5a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 16:50:54 +0000 Subject: r25163: Fix wrong ctx passed to talloc_asprintf_append(). Found by Metze's code review (thanks Metze !). Jeremy. (This used to be commit a7370eea6be29c0e2adf5ae62aa6182b9165e744) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7af4bcee60..478f60d094 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4876,7 +4876,7 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, return NT_STATUS_NO_MEMORY; } } - rel_name = talloc_asprintf_append(ctx, + rel_name = talloc_asprintf_append(rel_name, "%s", link_target); if (!rel_name) { -- cgit From b91b78530697556aec7764de9ef16735cdd22902 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 18:24:31 +0000 Subject: r25167: Fix breakage from mangling rewrite. Use the new name if unmangling succeeded, not if it failed. Jerry - please re-test, this should fix your bug. Jeremy. (This used to be commit c215d6e84929b70e4472e19f32ec4f1db7449d90) --- source3/smbd/filename.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f15c107711..fb8ed07ee8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -755,7 +755,8 @@ static BOOL scan_directory(connection_struct *conn, const char *path, name, &unmangled_name, conn->params); - if (mangled) { + if (!mangled) { + /* Name is now unmangled. */ name = unmangled_name; } } -- cgit From bb4773e30f6c524fc2c403111238d61a92474aed Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 22:27:27 +0000 Subject: r25173: Use the append_buffer version in a loop. Jeremy. (This used to be commit 37cf2c272751065245dd46708af0a78f1f0c47df) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1917eb4d10..56089fbe95 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1309,11 +1309,11 @@ BOOL create_msdfs_link(const struct junction_map *jucn, continue; } if (i > 0 && insert_comma) { - msdfs_link = talloc_asprintf_append(msdfs_link, + msdfs_link = talloc_asprintf_append_buffer(msdfs_link, ",%s", refpath); } else { - msdfs_link = talloc_asprintf_append(msdfs_link, + msdfs_link = talloc_asprintf_append_buffer(msdfs_link, "%s", refpath); } -- cgit From ad97bcf813d5f06df4711896eefc99c0c32651cc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Sep 2007 20:24:35 +0000 Subject: r25184: Fix some C++ warnings and an uninitialized variable (This used to be commit b64df8a3c504ab7749c21ffb26e4771a9a0a328f) --- source3/smbd/msdfs.c | 2 +- source3/smbd/nttrans.c | 4 ++-- source3/smbd/trans2.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 56089fbe95..69612dc571 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1549,7 +1549,7 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) { struct junction_map *jn = NULL; int i=0; - size_t jn_count; + size_t jn_count = 0; int sharecount = 0; *p_num_jn = 0; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 14a11c3fe3..dce0d6188d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -634,7 +634,7 @@ void reply_ntcreate_and_X(connection_struct *conn, */ dir_name_len = strlen(dir_fsp->fsp_name); - fname = TALLOC_SIZE(ctx, dir_name_len+2); + fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); if (!fname) { reply_nterror( req, NT_STATUS_NO_MEMORY); @@ -1392,7 +1392,7 @@ static void call_nt_transact_create(connection_struct *conn, */ dir_name_len = strlen(dir_fsp->fsp_name); - fname = TALLOC_SIZE(ctx, dir_name_len+2); + fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); if (!fname) { reply_nterror( req, NT_STATUS_NO_MEMORY); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 478f60d094..ada4868bf8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4209,7 +4209,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_UNIX_LINK: { - char *buffer = TALLOC_SIZE(ctx, 1024); + char *buffer = TALLOC_ARRAY(ctx, char, 1024); if (!buffer) { reply_nterror(req, NT_STATUS_NO_MEMORY); -- cgit From 30fc6400578a55ff4fad1ee9d292cbeb54aee744 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 21 Sep 2007 11:58:25 +0000 Subject: r25286: Fix one more caller of unistr2_to_ascii() that passed in -1 for maxlen. Michael (This used to be commit cd3d652d0d7609fc369ed0743c1fc54c87558438) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 520835bef7..20021ec7f7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -400,7 +400,7 @@ static void reply_spnego_kerberos(connection_struct *conn, if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, - -1); + sizeof(netbios_domain_name)); domain = netbios_domain_name; DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); -- cgit From e6228e2541669c297dd4206c2795560ddc80854c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Sep 2007 19:11:42 +0000 Subject: r25309: Volker's fix for bug #4984 - samba4 torture test to follow. Ensure we don't prepend "./" as a root directory - this is an invalid pathname for unix_convert(). Jeremy. (This used to be commit f70ac2e25847e41ecf54ae9d66e3247e1996b152) --- source3/smbd/nttrans.c | 112 +++++++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 41 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index dce0d6188d..e69fd86995 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -586,7 +586,6 @@ void reply_ntcreate_and_X(connection_struct *conn, char *rel_fname = NULL; files_struct *dir_fsp = file_fsp( SVAL(req->inbuf, smb_ntcreate_RootDirectoryFid)); - size_t dir_name_len; if(!dir_fsp) { reply_doserror(req, ERRDOS, ERRbadfid); @@ -629,29 +628,46 @@ void reply_ntcreate_and_X(connection_struct *conn, return; } - /* - * Copy in the base directory name. - */ + if (ISDOT(dir_fsp->fsp_name)) { + /* + * We're at the toplevel dir, the final file name + * must not contain ./, as this is filtered out + * normally by srvstr_get_path and unix_convert + * explicitly rejects paths containing ./. + */ + fname = talloc_strdup(ctx,""); + if (!fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBntcreateX); + return; + } + } else { + size_t dir_name_len = strlen(dir_fsp->fsp_name); - dir_name_len = strlen(dir_fsp->fsp_name); - fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); - if (!fname) { - reply_nterror( - req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBntcreateX); - return; - } - memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); + /* + * Copy in the base directory name. + */ - /* - * Ensure it ends in a '/'. - * We used TALLOC_SIZE +2 to add space for the '/'. - */ + fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); + if (!fname) { + reply_nterror( + req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBntcreateX); + return; + } + memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); + + /* + * Ensure it ends in a '/'. + * We used TALLOC_SIZE +2 to add space for the '/'. + */ - if(dir_name_len && (fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { - fname[dir_name_len] = '/'; - fname[dir_name_len+1] = '\0'; - dir_name_len++; + if(dir_name_len && + (fname[dir_name_len-1] != '\\') && + (fname[dir_name_len-1] != '/')) { + fname[dir_name_len] = '/'; + fname[dir_name_len+1] = '\0'; + } } srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &rel_fname, @@ -1356,7 +1372,6 @@ static void call_nt_transact_create(connection_struct *conn, */ char *tmpname = NULL; files_struct *dir_fsp = file_fsp(SVAL(params,4)); - size_t dir_name_len; if(!dir_fsp) { reply_doserror(req, ERRDOS, ERRbadfid); @@ -1387,28 +1402,43 @@ static void call_nt_transact_create(connection_struct *conn, return; } - /* - * Copy in the base directory name. - */ + if (ISDOT(dir_fsp->fsp_name)) { + /* + * We're at the toplevel dir, the final file name + * must not contain ./, as this is filtered out + * normally by srvstr_get_path and unix_convert + * explicitly rejects paths containing ./. + */ + fname = talloc_strdup(ctx,""); + if (!fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + } else { + size_t dir_name_len = strlen(dir_fsp->fsp_name); - dir_name_len = strlen(dir_fsp->fsp_name); - fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); - if (!fname) { - reply_nterror( - req, NT_STATUS_NO_MEMORY); - return; - } - memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); + /* + * Copy in the base directory name. + */ - /* - * Ensure it ends in a '/'. - * We used TALLOC_SIZE +2 to add space for the '/'. - */ + fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); + if (!fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); + + /* + * Ensure it ends in a '/'. + * We used TALLOC_SIZE +2 to add space for the '/'. + */ - if(dir_name_len && (fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) { - fname[dir_name_len] = '/'; - fname[dir_name_len+1] = '\0'; - dir_name_len++; + if(dir_name_len && + (fname[dir_name_len-1] != '\\') && + (fname[dir_name_len-1] != '/')) { + fname[dir_name_len] = '/'; + fname[dir_name_len+1] = '\0'; + } } srvstr_get_path(ctx, params, req->flags2, &tmpname, -- cgit From fb7ee0804c9d4e91a14c03651fc4907115d594e7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 24 Sep 2007 21:43:54 +0000 Subject: r25311: Patch from Heinrich Mislik to fix AIX quotas. Heinrich, I trust you on that, I don't even have compiled this :-) Volker (This used to be commit a8312a1d7b7e3ad00265279dd0640261beaa287d) --- source3/smbd/quotas.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 1f30acef33..cb31763a9f 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -1236,6 +1236,9 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB D.dqb_curblocks = user_quota.bused; D.dqb_bsoftlimit = user_quota.bsoft; D.dqb_bhardlimit = user_quota.bhard; + D.dqb_curfiles = user_quota.iused; + D.dqb_fsoftlimit = user_quota.isoft; + D.dqb_fhardlimit = user_quota.ihard; } else if(statbuf.f_vfstype == MNT_JFS) { -- cgit From e0402fa870ccf99c6ff6dc19a5005743cfe4b8d2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Sep 2007 21:41:39 +0000 Subject: r25324: Fix "msdfs proxy" Jeremy, please check! (This used to be commit d4eddf88d20b09c450d4358d2ef1bc35736501ff) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 69612dc571..a2d7b778ca 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -771,7 +771,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, } } - if (!lp_msdfs_root(snum)) { + if (!lp_msdfs_root(snum) && (*lp_msdfs_proxy(snum) == '\0')) { DEBUG(3,("get_referred_path: |%s| in dfs path %s is not " "a dfs root.\n", pdp->servicename, dfs_path)); -- cgit From aea0d4b9a0540e31392712bfeeb2185975919c42 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Sep 2007 23:26:05 +0000 Subject: r25327: Normalize the path we return for 'msdfs proxy' We now accept both \\server\tmp and \server\tmp. There are other places where this might be necessary, but at least the functionality is a bit easier now. (This used to be commit 25cc27df97e9eecb470f99ea934de12f2a0f4df9) --- source3/smbd/msdfs.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a2d7b778ca..ff55904b81 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -788,6 +788,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, */ if (pdp->reqpath[0] == '\0') { + char *tmp; struct referral *ref; if (*lp_msdfs_proxy(snum) == '\0') { @@ -810,7 +811,16 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - ref->alternate_path = talloc_strdup(ctx, lp_msdfs_proxy(snum)); + if (!(tmp = talloc_strdup(ctx, lp_msdfs_proxy(snum)))) { + TALLOC_FREE(pdp); + return NT_STATUS_NO_MEMORY; + } + + trim_string(tmp, "\\", 0); + + ref->alternate_path = talloc_asprintf(ctx, "\\%s", tmp); + TALLOC_FREE(tmp); + if (!ref->alternate_path) { TALLOC_FREE(pdp); return NT_STATUS_NO_MEMORY; -- cgit From 152a1f4a7d462ca118169cb99a407c245f5c2504 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Sep 2007 23:28:35 +0000 Subject: r25391: Fix bug #4978 : Store DOS Attributes fails when copying folders. Jeremy. (This used to be commit 713277391ae7f81f8545723c919865ff8c07ed86) --- source3/smbd/open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8e1068e708..6c2b5a4907 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1983,6 +1983,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, char *parent_dir; const char *dirname; NTSTATUS status; + bool posix_open = false; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -2001,6 +2002,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, } if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + posix_open = true; mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); } else { mode = unix_mode(conn, aDIR, name, parent_dir); @@ -2025,6 +2027,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } + if (lp_store_dos_attributes(SNUM(conn))) { + if (!posix_open) { + file_set_dosmode(conn, name, + file_attributes | aDIR, NULL, + parent_dir); + } + } + if (lp_inherit_perms(SNUM(conn))) { inherit_access_acl(conn, parent_dir, name, mode); } -- cgit From 0d87820380416955a132d565a479b4234f78c113 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 Oct 2007 20:43:55 +0000 Subject: r25492: Start adding IPv6 compatible code to lib/util_sock.c and deal with the ripple effects this causes. utmp has to change etc. Remove some global varables and store address/port in the unexpected db. Jeremy. (This used to be commit 18c6a2211d9e25233d01715b3f78977edcd6d869) --- source3/smbd/session.c | 25 +++++++------------- source3/smbd/sockinit.c | 63 +++++++++++++++++++++++++++++-------------------- source3/smbd/utmp.c | 63 ++++++++++++++++++++++++++++++------------------- 3 files changed, 85 insertions(+), 66 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 3cc93c1a7f..c7cdf41fb5 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -62,8 +62,6 @@ BOOL session_claim(user_struct *vuser) { TDB_DATA key, data; int i = 0; - struct sockaddr sa; - struct in_addr *client_ip; struct sessionid sessionid; struct server_id pid = procid_self(); fstring keystr; @@ -124,7 +122,7 @@ BOOL session_claim(user_struct *vuser) TALLOC_FREE(rec); } - + if (i == MAX_SESSION_ID) { SMB_ASSERT(rec == NULL); DEBUG(1,("session_claim: out of session IDs " @@ -147,16 +145,16 @@ BOOL session_claim(user_struct *vuser) return False; } - snprintf(sessionid.id_str, sizeof(sessionid.id_str), - SESSION_TEMPLATE, (long unsigned int)sys_getpid(), + snprintf(sessionid.id_str, sizeof(sessionid.id_str), + SESSION_TEMPLATE, (long unsigned int)sys_getpid(), vuser->vuid); } SMB_ASSERT(rec != NULL); /* If 'hostname lookup' == yes, then do the DNS lookup. This is - needed because utmp and PAM both expect DNS names - + needed because utmp and PAM both expect DNS names + client_name() handles this case internally. */ @@ -172,11 +170,9 @@ BOOL session_claim(user_struct *vuser) sessionid.uid = vuser->uid; sessionid.gid = vuser->gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); - fstrcpy(sessionid.ip_addr, client_addr()); + fstrcpy(sessionid.ip_addr_str, client_addr()); sessionid.connect_start = time(NULL); - client_ip = client_inaddr(&sa); - if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", @@ -200,8 +196,8 @@ BOOL session_claim(user_struct *vuser) } if (lp_utmp()) { - sys_utmp_claim(sessionid.username, sessionid.hostname, - client_ip, + sys_utmp_claim(sessionid.username, sessionid.hostname, + sessionid.ip_addr_str, sessionid.id_str, sessionid.id_num); } @@ -224,7 +220,6 @@ void session_yield(user_struct *vuser) { TDB_DATA key; struct sessionid sessionid; - struct in_addr *client_ip; struct db_context *ctx; struct db_record *rec; @@ -245,11 +240,9 @@ void session_yield(user_struct *vuser) memcpy(&sessionid, rec->value.dptr, sizeof(sessionid)); - client_ip = interpret_addr2(sessionid.ip_addr); - if (lp_utmp()) { sys_utmp_yield(sessionid.username, sessionid.hostname, - client_ip, + sessionid.ip_addr_str, sessionid.id_str, sessionid.id_num); } diff --git a/source3/smbd/sockinit.c b/source3/smbd/sockinit.c index c526a181d3..598bbd1bda 100644 --- a/source3/smbd/sockinit.c +++ b/source3/smbd/sockinit.c @@ -1,19 +1,19 @@ -/* +/* Unix SMB/CIFS implementation. Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) James Peach 2007 - + 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 3 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, see . */ @@ -43,11 +43,11 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) } if (lp_interfaces() && lp_bind_interfaces_only()) { - /* We have been given an interfaces line, and been + /* We have been given an interfaces line, and been told to only bind to those interfaces. Create a socket per interface and bind to only these. */ - + /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { @@ -56,35 +56,45 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) const char *ptr; if(ifip == NULL) { - DEBUG(0,("init_sockets_smbd: interface %d has NULL IP address !\n", i)); + DEBUG(0,("init_sockets_smbd: interface %d has " + "NULL IP address !\n", i)); continue; } - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + for (ptr=ports; next_token(&ptr, tok, " \t,", + sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0 || port > 0xffff) { continue; } - s = listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + s = listenset[num_sockets] = + open_socket_in(SOCK_STREAM, + port, + 0, + ifip->s_addr, + True); if(s == -1) return 0; /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - + + /* Set server socket to non-blocking + * for the accept. */ + set_blocking(s,False); + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("listen: %s\n",strerror(errno))); + DEBUG(0,("listen: %s\n", + strerror(errno))); close(s); return 0; } num_sockets++; if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + DEBUG(0,("init_sockets_smbd: " + "Too many sockets to bind to\n")); return 0; } } @@ -97,23 +107,24 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) const char *ptr; num_interfaces = 1; - + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0 || port > 0xffff) continue; /* open an incoming socket */ s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()),True); + interpret_addr(lp_socket_address()), + True); if (s == -1) return 0; - + /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); - + /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - + set_blocking(s,False); + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { DEBUG(0,("init_sockets_smbd: listen: %s\n", strerror(errno))); @@ -125,11 +136,12 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) num_sockets++; if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + DEBUG(0,("init_sockets_smbd: " + "Too many sockets to bind to\n")); return 0; } } - } + } SAFE_FREE(ports); return num_sockets; @@ -197,4 +209,3 @@ int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE], return num_sockets; } - diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index eb2152dac2..52174c4d83 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -112,14 +112,14 @@ Notes: * Not WITH_UTMP? Simply supply dummy routines. */ -void sys_utmp_claim(const char *username, const char *hostname, - struct in_addr *ipaddr, - const char *id_str, int id_num) +void sys_utmp_claim(const char *username, const char *hostname, + const char *ip_addr_str, + const char *id_str, int id_num) {} -void sys_utmp_yield(const char *username, const char *hostname, - struct in_addr *ipaddr, - const char *id_str, int id_num) +void sys_utmp_yield(const char *username, const char *hostname, + const char *ip_addr_str, + const char *id_str, int id_num) {} #else /* WITH_UTMP */ @@ -448,7 +448,7 @@ static int ut_id_encode(int i, char *fourbyte) { int nbase; const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - + fourbyte[0] = 'S'; fourbyte[1] = 'M'; @@ -470,13 +470,13 @@ static int ut_id_encode(int i, char *fourbyte) /* - fill a system utmp structure given all the info we can gather + fill a system utmp structure given all the info we can gather */ static BOOL sys_utmp_fill(struct utmp *u, - const char *username, const char *hostname, - struct in_addr *ipaddr, - const char *id_str, int id_num) -{ + const char *username, const char *hostname, + const char *ip_addr_str, + const char *id_str, int id_num) +{ struct timeval timeval; /* @@ -507,7 +507,7 @@ static BOOL sys_utmp_fill(struct utmp *u, #endif /* - * ut_time, ut_tv: + * ut_time, ut_tv: * Some have one, some the other. Many have both, but defined (aliased). * It is easier and clearer simply to let the following take its course. * But note that we do the more precise ut_tv as the final assignment. @@ -525,9 +525,22 @@ static BOOL sys_utmp_fill(struct utmp *u, #if defined(HAVE_UT_UT_HOST) utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host)); #endif -#if defined(HAVE_UT_UT_ADDR) - if (ipaddr) - u->ut_addr = ipaddr->s_addr; +#if defined(AF_INET6) && defined(HAVE_UT_UT_ADDR_V6) + memset(&u->ut_addr_v6, '\0', sizeof(u->ut_addr_v6)); + if (ip_addr_str) { + struct in6_addr addr; + if (inet_pton(AF_INET6, ip_addr_str, &addr) > 0) { + memcpy(&u->ut_addr_v6, &addr, sizeof(addr)); + } + } +#elif defined(HAVE_UT_UT_ADDR) + memset(&u->ut_addr, '\0', sizeof(u->ut_addr)); + if (ip_addr_str) { + struct in_addr addr; + if (inet_pton(AF_INET, ip_addr_str, &addr) > 0) { + memcpy(&u->ut_addr, &addr, sizeof(addr)); + } + } /* * "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20. * Volunteer to implement, please ... @@ -548,9 +561,9 @@ static BOOL sys_utmp_fill(struct utmp *u, Close a connection. ****************************************************************************/ -void sys_utmp_yield(const char *username, const char *hostname, - struct in_addr *ipaddr, - const char *id_str, int id_num) +void sys_utmp_yield(const char *username, const char *hostname, + const char *ip_addr_str, + const char *id_str, int id_num) { struct utmp u; @@ -565,7 +578,8 @@ void sys_utmp_yield(const char *username, const char *hostname, u.ut_type = DEAD_PROCESS; #endif - if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return; + if (!sys_utmp_fill(&u, username, hostname, ip_addr_str, id_str, id_num)) + return; sys_utmp_update(&u, NULL, False); } @@ -574,9 +588,9 @@ void sys_utmp_yield(const char *username, const char *hostname, Claim a entry in whatever utmp system the OS uses. ****************************************************************************/ -void sys_utmp_claim(const char *username, const char *hostname, - struct in_addr *ipaddr, - const char *id_str, int id_num) +void sys_utmp_claim(const char *username, const char *hostname, + const char *ip_addr_str, + const char *id_str, int id_num) { struct utmp u; @@ -586,7 +600,8 @@ void sys_utmp_claim(const char *username, const char *hostname, u.ut_type = USER_PROCESS; #endif - if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return; + if (!sys_utmp_fill(&u, username, hostname, ip_addr_str, id_str, id_num)) + return; sys_utmp_update(&u, hostname, True); } -- cgit From bb9f1e514620dde7defdb46edacdfc6f84d26d9d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 3 Oct 2007 22:23:37 +0000 Subject: r25498: Remove checks that are always true. (This used to be commit 2f2bdfa0df758104a9a2fcafe49d6215d8753536) --- source3/smbd/utmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 52174c4d83..7f43740754 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -220,13 +220,13 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau } /* For u-files and non-explicit w-dir, look for "utmp dir" */ - if (dirname == 0 || strlen(dirname) == 0) { + if (strlen(dirname) == 0) { pstrcpy(dirname,lp_utmpdir()); trim_char(dirname,'\0','/'); } /* If explicit directory above, use it */ - if (dirname != 0 && strlen(dirname) != 0) { + if (strlen(dirname) != 0) { pstrcpy(fname, dirname); pstrcat(fname, "/"); pstrcat(fname, uw_name); -- cgit From 4b21570812bfb070d4f4cc287780460c6bc50cca Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 4 Oct 2007 13:13:16 +0000 Subject: r25502: Fix bug 5006 Thanks to Joerg.Bernau at web.de (This used to be commit 492977016fa66ce0e98a5bdd1c0f00eacdf13f0c) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d6813bef80..e27272f0dd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3923,7 +3923,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) if(IVAL(req->inbuf,smb_vwv12) != 0) { DEBUG(0,("reply_write_and_X - large offset (%x << 32) " "used and we don't support 64 bit offsets.\n", - (unsigned int)IVAL(inbuf,smb_vwv12) )); + (unsigned int)IVAL(req->inbuf,smb_vwv12) )); reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBwriteX); return; -- cgit From 0ebab65706e7e2ef82d8af81225db05a5f78b5c4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Oct 2007 21:41:17 +0000 Subject: r25534: Apply some const Why? It moves these structs from the data into the text segment, so they will never been copy-on-write copied. Not much, but as in German you say "Kleinvieh macht auch Mist...." (This used to be commit 0141e64ad4972232de867137064d0dae62da22ee) --- source3/smbd/open.c | 2 +- source3/smbd/posix_acls.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6c2b5a4907..c2d7807158 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -21,7 +21,7 @@ #include "includes.h" -extern struct generic_mapping file_generic_mapping; +extern const struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; extern BOOL global_client_failed_oplock_break; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f7cadeec3e..116917d7eb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -21,7 +21,7 @@ #include "includes.h" extern struct current_user current_user; -extern struct generic_mapping file_generic_mapping; +extern const struct generic_mapping file_generic_mapping; #undef DBGC_CLASS #define DBGC_CLASS DBGC_ACLS -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/smbd/aio.c | 181 ++++++++++-- source3/smbd/close.c | 20 +- source3/smbd/conn.c | 1 + source3/smbd/connection.c | 32 +-- source3/smbd/error.c | 8 +- source3/smbd/files.c | 1 + source3/smbd/notify.c | 7 +- source3/smbd/open.c | 4 + source3/smbd/oplock.c | 2 +- source3/smbd/pipes.c | 2 +- source3/smbd/process.c | 29 +- source3/smbd/reply.c | 28 +- source3/smbd/seal.c | 703 ---------------------------------------------- source3/smbd/server.c | 246 ++++++++++------ source3/smbd/service.c | 18 +- source3/smbd/session.c | 5 +- source3/smbd/sockinit.c | 211 -------------- source3/smbd/srvstr.c | 2 +- source3/smbd/trans2.c | 49 +--- source3/smbd/utmp.c | 4 +- 20 files changed, 389 insertions(+), 1164 deletions(-) delete mode 100644 source3/smbd/seal.c delete mode 100644 source3/smbd/sockinit.c (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 49855796b7..6ee0fe16e1 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -48,10 +48,8 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, - size_t buflen, - uint16 mid, - const uint8 *inbuf) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, + uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -67,14 +65,6 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, SAFE_FREE(aio_ex); return NULL; } - /* Save the first 8 bytes of inbuf for possible enc data. */ - aio_ex->inbuf = SMB_MALLOC_ARRAY(char, 8); - if (!aio_ex->inbuf) { - SAFE_FREE(aio_ex->outbuf); - SAFE_FREE(aio_ex); - return NULL; - } - memcpy(aio_ex->inbuf, inbuf, 8); DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; aio_ex->read_req = True; @@ -240,14 +230,13 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, bufsize = smb_size + 12 * 2 + smb_maxcnt; - if (!(aio_ex = create_aio_ex_read(fsp, bufsize, req->mid, - req->inbuf))) { + if ((aio_ex = create_aio_ex_read(fsp, bufsize, req->mid)) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - set_message((char *)req->inbuf, aio_ex->outbuf, 12, 0, True); + set_message(aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -292,6 +281,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; size_t inbufsize, outbufsize; + BOOL write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { @@ -359,7 +349,22 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - srv_defer_sign_response(aio_ex->mid); + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) + && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the + * write. */ + SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); + SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); + show_msg(aio_ex->outbuf); + if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { + exit_server_cleanly("handle_aio_write: send_smb " + "failed."); + } + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " + "behind for file %s\n", fsp->fsp_name )); + } else { + srv_defer_sign_response(aio_ex->mid); + } outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " @@ -382,7 +387,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -406,7 +410,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; } else { - outsize = set_message(inbuf,outbuf,12,nread,False); + outsize = set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -419,7 +423,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(inbuf,outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -444,10 +448,34 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); + if (fsp->aio_write_behind) { + if (nwritten != numtowrite) { + if (nwritten == -1) { + DEBUG(5,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); + ret = errno; + } else { + DEBUG(0,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Wanted %u bytes but " + "only wrote %d\n", fsp->fsp_name, + (unsigned int)numtowrite, + (int)nwritten )); + ret = EIO; + } + } else { + DEBUG(10,("handle_aio_write_complete: " + "aio_write_behind completed for file %s\n", + fsp->fsp_name )); + } + return 0; + } + /* We don't need outsize or set_message here as we've already set the fixed size length when we set up the aio call. */ @@ -589,6 +617,115 @@ int process_aio_queue(void) return ret; } +/**************************************************************************** + We're doing write behind and the client closed the file. Wait up to 30 + seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes + completed, errno to return if not. +*****************************************************************************/ + +#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 + +int wait_for_aio_completion(files_struct *fsp) +{ + struct aio_extra *aio_ex; + const SMB_STRUCT_AIOCB **aiocb_list; + int aio_completion_count = 0; + time_t start_time = time(NULL); + int seconds_left; + + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; + seconds_left >= 0;) { + int err = 0; + int i; + struct timespec ts; + + aio_completion_count = 0; + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aio_completion_count++; + } + } + + if (!aio_completion_count) { + return 0; + } + + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " + "to complete.\n", aio_completion_count )); + + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, + aio_completion_count); + if (!aiocb_list) { + return ENOMEM; + } + + for( i = 0, aio_ex = aio_list_head; + aio_ex; + aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aiocb_list[i++] = &aio_ex->acb; + } + } + + /* Now wait up to seconds_left for completion. */ + ts.tv_sec = seconds_left; + ts.tv_nsec = 0; + + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " + "of %d seconds.\n", + aio_completion_count, seconds_left )); + + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, + aio_completion_count, &ts); + + DEBUG(10,("wait_for_aio_completion: returned err = %d, " + "errno = %s\n", err, strerror(errno) )); + + if (err == -1 && errno == EAGAIN) { + DEBUG(0,("wait_for_aio_completion: aio_suspend timed " + "out waiting for %d events after a wait of " + "%d seconds\n", aio_completion_count, + seconds_left)); + /* Timeout. */ + cancel_aio_by_fsp(fsp); + SAFE_FREE(aiocb_list); + return EIO; + } + + /* One or more events might have completed - process them if + * so. */ + for( i = 0; i < aio_completion_count; i++) { + uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; + + aio_ex = find_aio_ex(mid); + + if (!aio_ex) { + DEBUG(0, ("wait_for_aio_completion: mid %u " + "doesn't match an aio record\n", + (unsigned int)mid )); + continue; + } + + if (!handle_aio_completed(aio_ex, &err)) { + continue; + } + delete_aio_ex(aio_ex); + } + + SAFE_FREE(aiocb_list); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT + - (time(NULL) - start_time); + } + + /* We timed out - we don't know why. Return ret if already an error, + * else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " + "for %d events\n", + aio_completion_count)); + + return EIO; +} + /**************************************************************************** Cancel any outstanding aio requests. The client doesn't care about the reply. *****************************************************************************/ @@ -645,4 +782,8 @@ void cancel_aio_by_fsp(files_struct *fsp) { } +BOOL wait_for_aio_completion(files_struct *fsp) +{ + return True; +} #endif diff --git a/source3/smbd/close.c b/source3/smbd/close.c index aee1c92f7b..ae45aaa6da 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -345,16 +345,28 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ NTSTATUS status = NT_STATUS_OK; NTSTATUS saved_status1 = NT_STATUS_OK; NTSTATUS saved_status2 = NT_STATUS_OK; + NTSTATUS saved_status3 = NT_STATUS_OK; connection_struct *conn = fsp->conn; - cancel_aio_by_fsp(fsp); + if (fsp->aio_write_behind) { + /* + * If we're finishing write behind on a close we can get a write + * error here, we must remember this. + */ + int ret = wait_for_aio_completion(fsp); + if (ret) { + saved_status1 = map_nt_error_from_unix(ret); + } + } else { + cancel_aio_by_fsp(fsp); + } /* * If we're flushing on a close we can get a write * error here, we must remember this. */ - saved_status1 = close_filestruct(fsp); + saved_status2 = close_filestruct(fsp); if (fsp->print_file) { print_fsp_end(fsp, close_type); @@ -368,7 +380,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ if (fsp->fh->ref_count == 1) { /* Should we return on error here... ? */ - saved_status2 = close_remove_share_mode(fsp, close_type); + saved_status3 = close_remove_share_mode(fsp, close_type); } if(fsp->oplock_type) { @@ -399,6 +411,8 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ status = saved_status1; } else if (!NT_STATUS_IS_OK(saved_status2)) { status = saved_status2; + } else if (!NT_STATUS_IS_OK(saved_status3)) { + status = saved_status3; } } diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index f9befb84d2..50a71edf9d 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -285,6 +285,7 @@ void conn_free_internal(connection_struct *conn) free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); + free_namearray(conn->aio_write_behind_list); string_free(&conn->user); string_free(&conn->dirpath); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 4b807f7b90..65b7c352c5 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -83,19 +83,9 @@ static int count_fn(struct db_record *rec, } return 0; } - - if (cs->name) { - /* We are counting all the connections to a given share. */ - if (strequal(crec->servicename, cs->name)) { - cs->curr_connections++; - } - } else { - /* We are counting all the connections. Static registrations - * like the lpq backgroud process and the smbd daemon process - * have a cnum of -1, so won't be counted here. - */ + + if (strequal(crec->servicename, cs->name)) cs->curr_connections++; - } return 0; } @@ -121,28 +111,12 @@ int count_current_connections( const char *sharename, BOOL clear ) if (connections_forall(count_fn, &cs) == -1) { DEBUG(0,("count_current_connections: traverse of " "connections.tdb failed\n")); - DEBUGADD(0, ("count_current_connections: connection count of %d might not be accurate", - cs.curr_connections)); + return False; } - /* If the traverse failed part-way through, we at least return - * as many connections as we had already counted. If it failed - * right at the start, we will return 0, which is about all we - * can do anywway. - */ - return cs.curr_connections; } -/**************************************************************************** - Count the number of connections open across all shares. -****************************************************************************/ - -int count_all_current_connections(void) -{ - return count_current_connections(NULL, True /* clear stale entries */); -} - /**************************************************************************** Claim an entry in the connections database. ****************************************************************************/ diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 143417dce3..6cb63f0c49 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -28,7 +28,7 @@ extern uint32 global_client_caps; Create an error packet from errno. ****************************************************************************/ -int unix_error_packet(const char *inbuf,char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) +int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) { int eclass=def_class; int ecode=def_code; @@ -49,7 +49,7 @@ int unix_error_packet(const char *inbuf,char *outbuf,int def_class,uint32 def_co } } - return error_packet(inbuf,outbuf,eclass,ecode,ntstatus,line,file); + return error_packet(outbuf,eclass,ecode,ntstatus,line,file); } BOOL use_nt_status(void) @@ -109,9 +109,9 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu } } -int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { - int outsize = set_message(inbuf,outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,True); error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index f3740da328..179963dae9 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -558,6 +558,7 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->modified = fsp->modified; dup_fsp->is_directory = fsp->is_directory; dup_fsp->is_stat = fsp->is_stat; + dup_fsp->aio_write_behind = fsp->aio_write_behind; string_set(&dup_fsp->fsp_name,fsp->fsp_name); *result = dup_fsp; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index da80c25407..b8c5085b41 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -131,11 +131,10 @@ static BOOL notify_marshall_changes(int num_changes, static void change_notify_reply_packet(const uint8 *request_buf, NTSTATUS error_code) { - const char *inbuf = (char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common((char *)request_buf, outbuf); ERROR_NT(error_code); @@ -143,7 +142,7 @@ static void change_notify_reply_packet(const uint8 *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - set_message(inbuf,outbuf,18,0,False); + set_message(outbuf,18,0,False); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) @@ -187,7 +186,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, * We're only interested in the header fields here */ - smb_setlen(NULL, (char *)tmp_request, smb_size); + smb_setlen((char *)tmp_request, smb_size); SCVAL(tmp_request, smb_wct, 0); init_smb_request(req, tmp_request); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c2d7807158..fbc6f9ab64 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -387,6 +387,10 @@ static NTSTATUS open_file(files_struct *fsp, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; + if (conn->aio_write_behind_list && + is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) { + fsp->aio_write_behind = True; + } string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index a5f74b89d0..9ac9d76284 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -253,7 +253,7 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx, } memset(result,'\0',smb_size); - set_message(NULL,result,8,0,True); + set_message(result,8,0,True); SCVAL(result,smb_com,SMBlockingX); SSVAL(result,smb_tid,fsp->conn->cnum); SSVAL(result,smb_pid,0xFFFF); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 9906bfb45b..da43a29767 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -291,7 +291,7 @@ void reply_pipe_read_and_X(struct smb_request *req) return; } - set_message(NULL, (char *)req->outbuf, 12, nread, False); + set_message((char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 29b942de81..7faf26af25 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -91,8 +91,8 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) static struct pending_message_list *deferred_open_queue; /**************************************************************************** - Function to push a message onto the tail of a linked list of smb messages - ready for processing. + Function to push a message onto the tail of a linked list of smb messages ready + for processing. ****************************************************************************/ static BOOL push_queued_message(struct smb_request *req, @@ -148,7 +148,7 @@ void remove_deferred_open_smb_message(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { - DEBUG(10,("remove_deferred_open_smb_message: " + DEBUG(10,("remove_sharing_violation_open_smb_message: " "deleting mid %u len %u\n", (unsigned int)mid, (unsigned int)pml->buf.length )); @@ -171,11 +171,11 @@ void schedule_deferred_open_smb_message(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { uint16 msg_mid = SVAL(pml->buf.data,smb_mid); - DEBUG(10, ("schedule_deferred_open_smb_message: [%d] " - "msg_mid = %u\n", i++, (unsigned int)msg_mid )); + DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++, + (unsigned int)msg_mid )); if (mid == msg_mid) { - DEBUG(10, ("schedule_deferred_open_smb_message: " - "scheduling mid %u\n", mid)); + DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n", + mid )); pml->end_time.tv_sec = 0; pml->end_time.tv_usec = 0; DLIST_PROMOTE(deferred_open_queue, pml); @@ -183,8 +183,8 @@ void schedule_deferred_open_smb_message(uint16 mid) } } - DEBUG(10, ("schedule_deferred_open_smb_message: failed to find " - "message mid %u\n", mid )); + DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n", + mid )); } /**************************************************************************** @@ -932,8 +932,7 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) } construct_reply_common((char *)req->inbuf, (char *)req->outbuf); - set_message((char *)req->inbuf, (char *)req->outbuf, - num_words, num_bytes, False); + set_message((char *)req->outbuf, num_words, num_bytes, False); /* * Zero out the word area, the caller has to take care of the bcc area * himself @@ -1226,8 +1225,8 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(const char *inbuf, char *outbuf) { - set_message(inbuf,outbuf,0,0,False); - + set_message(outbuf,0,0,False); + SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); SIVAL(outbuf,smb_rcls,0); SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); @@ -1341,7 +1340,7 @@ void chain_reply(struct smb_request *req) } /* And set it in the header. */ - smb_setlen(inbuf, inbuf2, new_size - 4); + smb_setlen(inbuf2, new_size - 4); DEBUG(3,("Chained message\n")); show_msg(inbuf2); @@ -1428,7 +1427,7 @@ void chain_reply(struct smb_request *req) memset(outbuf + outsize, 0, outsize_padded - outsize); } - smb_setlen(NULL, outbuf, outsize2 + chain_size - 4); + smb_setlen(outbuf, outsize2 + chain_size - 4); /* * restore the saved data, being careful not to overwrite any data diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e27272f0dd..7c44216aea 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -402,7 +402,7 @@ void reply_special(char *inbuf) memset(outbuf, '\0', sizeof(outbuf)); - smb_setlen(inbuf,outbuf,0); + smb_setlen(outbuf,0); switch (msg_type) { case 0x81: /* session request */ @@ -1645,8 +1645,8 @@ void reply_open(connection_struct *conn, struct smb_request *req) if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { - END_PROFILE(SMBopen); /* We have re-scheduled this call. */ + END_PROFILE(SMBopen); return; } reply_openerror(req, status); @@ -2040,7 +2040,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) /* We have re-scheduled this call. */ return; } - reply_nterror(req, status); + reply_openerror(req, status); return; } @@ -3017,7 +3017,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - set_message(NULL, (char *)req->outbuf, 5, nread+3, False); + set_message((char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3104,7 +3104,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - set_message(NULL, (char *)req->outbuf, 5, nread+3, False); + set_message((char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3122,14 +3122,12 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Setup readX header. ****************************************************************************/ -static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf, - size_t smb_maxcnt) +static int setup_readX_header(char *outbuf, size_t smb_maxcnt) { int outsize; char *data; - outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt, - False); + outsize = set_message(outbuf,12,smb_maxcnt,False); data = smb_buf(outbuf); memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */ @@ -3192,7 +3190,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, header = data_blob_const(headerbuf, sizeof(headerbuf)); construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header(req->inbuf, headerbuf, smb_maxcnt); + setup_readX_header((char *)headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ @@ -3243,7 +3241,7 @@ normal_read: uint8 headerbuf[smb_size + 2*12]; construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header(req->inbuf, headerbuf, smb_maxcnt); + setup_readX_header((char *)headerbuf, smb_maxcnt); /* Send out the header. */ if (write_data(smbd_server_fd(), (char *)headerbuf, @@ -3270,7 +3268,7 @@ normal_read: return; } - setup_readX_header(req->inbuf, req->outbuf, nread); + setup_readX_header((char *)req->outbuf, nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); @@ -3334,8 +3332,8 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBreadX); return; } - /* We currently don't do this on signed or sealed data. */ - if (srv_is_signing_active() || srv_encryption_on()) { + /* We currently don't do this on signed data. */ + if (srv_is_signing_active()) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBreadX); return; @@ -3526,7 +3524,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) * it to send more bytes */ memcpy(buf, req->inbuf, smb_size); - outsize = set_message(NULL,buf, + outsize = set_message(buf, Protocol>PROTOCOL_COREPLUS?1:0,0,True); SCVAL(buf,smb_com,SMBwritebraw); SSVALS(buf,smb_vwv0,0xFFFF); diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c deleted file mode 100644 index 0276e34002..0000000000 --- a/source3/smbd/seal.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB Transport encryption (sealing) code - server code. - Copyright (C) Jeremy Allison 2007. - - 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 3 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, see . -*/ - -#include "includes.h" - -/****************************************************************************** - Server side encryption. -******************************************************************************/ - -/****************************************************************************** - Global server state. -******************************************************************************/ - -struct smb_srv_trans_enc_ctx { - struct smb_trans_enc_state *es; - AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ -}; - -static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; -static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; - -/****************************************************************************** - Is server encryption on ? -******************************************************************************/ - -BOOL srv_encryption_on(void) -{ - if (srv_trans_enc_ctx) { - return common_encryption_on(srv_trans_enc_ctx->es); - } - return False; -} - -/****************************************************************************** - Create an auth_ntlmssp_state and ensure pointer copy is correct. -******************************************************************************/ - -static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) -{ - NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - - /* - * We must remember to update the pointer copy for the common - * functions after any auth_ntlmssp_start/auth_ntlmssp_end. - */ - ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; - return status; -} - -/****************************************************************************** - Destroy an auth_ntlmssp_state and ensure pointer copy is correct. -******************************************************************************/ - -static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) -{ - /* - * We must remember to update the pointer copy for the common - * functions after any auth_ntlmssp_start/auth_ntlmssp_end. - */ - - if (ec->auth_ntlmssp_state) { - auth_ntlmssp_end(&ec->auth_ntlmssp_state); - /* The auth_ntlmssp_end killed this already. */ - ec->es->s.ntlmssp_state = NULL; - } -} - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - -/****************************************************************************** - Import a name. -******************************************************************************/ - -static NTSTATUS get_srv_gss_creds(const char *service, - const char *name, - gss_cred_usage_t cred_type, - gss_cred_id_t *p_srv_cred) -{ - OM_uint32 ret; - OM_uint32 min; - gss_name_t srv_name; - gss_buffer_desc input_name; - char *host_princ_s = NULL; - NTSTATUS status = NT_STATUS_OK; - - gss_OID_desc nt_hostbased_service = - {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; - - asprintf(&host_princ_s, "%s@%s", service, name); - if (host_princ_s == NULL) { - return NT_STATUS_NO_MEMORY; - } - - input_name.value = host_princ_s; - input_name.length = strlen(host_princ_s) + 1; - - ret = gss_import_name(&min, - &input_name, - &nt_hostbased_service, - &srv_name); - - DEBUG(10,("get_srv_gss_creds: imported name %s\n", - host_princ_s )); - - if (ret != GSS_S_COMPLETE) { - SAFE_FREE(host_princ_s); - return map_nt_error_from_gss(ret, min); - } - - /* - * We're accessing the krb5.keytab file here. - * ensure we have permissions to do so. - */ - become_root(); - - ret = gss_acquire_cred(&min, - srv_name, - GSS_C_INDEFINITE, - GSS_C_NULL_OID_SET, - cred_type, - p_srv_cred, - NULL, - NULL); - unbecome_root(); - - if (ret != GSS_S_COMPLETE) { - ADS_STATUS adss = ADS_ERROR_GSS(ret, min); - DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", - ads_errstr(adss))); - status = map_nt_error_from_gss(ret, min); - } - - SAFE_FREE(host_princ_s); - gss_release_name(&min, &srv_name); - return status; -} - -/****************************************************************************** - Create a gss state. - Try and get the cifs/server@realm principal first, then fall back to - host/server@realm. -******************************************************************************/ - -static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) -{ - NTSTATUS status; - gss_cred_id_t srv_cred; - fstring fqdn; - - name_to_fqdn(fqdn, global_myname()); - strlower_m(fqdn); - - status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); - if (!NT_STATUS_IS_OK(status)) { - status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - } - - ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); - if (!ec->es->s.gss_state) { - OM_uint32 min; - gss_release_cred(&min, &srv_cred); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(ec->es->s.gss_state); - ec->es->s.gss_state->creds = srv_cred; - - /* No context yet. */ - ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; - - return NT_STATUS_OK; -} -#endif - -/****************************************************************************** - Shutdown a server encryption context. -******************************************************************************/ - -static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) -{ - struct smb_srv_trans_enc_ctx *ec = *pp_ec; - - if (!ec) { - return; - } - - if (ec->es) { - switch (ec->es->smb_enc_type) { - case SMB_TRANS_ENC_NTLM: - destroy_auth_ntlmssp(ec); - break; -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - case SMB_TRANS_ENC_GSS: - break; -#endif - } - common_free_encryption_state(&ec->es); - } - - SAFE_FREE(ec); - *pp_ec = NULL; -} - -/****************************************************************************** - Create a server encryption context. -******************************************************************************/ - -static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) -{ - struct smb_srv_trans_enc_ctx *ec; - - *pp_ec = NULL; - - ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); - if (!ec) { - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(partial_srv_trans_enc_ctx); - ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); - if (!ec->es) { - SAFE_FREE(ec); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(ec->es); - ec->es->smb_enc_type = smb_enc_type; - switch (smb_enc_type) { - case SMB_TRANS_ENC_NTLM: - { - NTSTATUS status = make_auth_ntlmssp(ec); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&ec); - return status; - } - } - break; - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - case SMB_TRANS_ENC_GSS: - /* Acquire our credentials by calling gss_acquire_cred here. */ - { - NTSTATUS status = make_auth_gss(ec); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&ec); - return status; - } - } - break; -#endif - default: - srv_free_encryption_context(&ec); - return NT_STATUS_INVALID_PARAMETER; - } - *pp_ec = ec; - return NT_STATUS_OK; -} - -/****************************************************************************** - Free an encryption-allocated buffer. -******************************************************************************/ - -void srv_free_enc_buffer(char *buf) -{ - /* We know this is an smb buffer, and we - * didn't malloc, only copy, for a keepalive, - * so ignore session keepalives. */ - - if(CVAL(buf,0) == SMBkeepalive) { - return; - } - - if (srv_trans_enc_ctx) { - common_free_enc_buffer(srv_trans_enc_ctx->es, buf); - } -} - -/****************************************************************************** - Decrypt an incoming buffer. -******************************************************************************/ - -NTSTATUS srv_decrypt_buffer(char *buf) -{ - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { - return NT_STATUS_OK; - } - - if (srv_trans_enc_ctx) { - return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); - } - - return NT_STATUS_OK; -} - -/****************************************************************************** - Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. -******************************************************************************/ - -NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) -{ - *buf_out = buf; - - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { - return NT_STATUS_OK; - } - - if (srv_trans_enc_ctx) { - return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); - } - /* Not encrypting. */ - return NT_STATUS_OK; -} - -/****************************************************************************** - Do the gss encryption negotiation. Parameters are in/out. - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) -{ - OM_uint32 ret; - OM_uint32 min; - OM_uint32 flags = 0; - gss_buffer_desc in_buf, out_buf; - struct smb_tran_enc_state_gss *gss_state; - DATA_BLOB auth_reply = data_blob_null; - DATA_BLOB response = data_blob_null; - NTSTATUS status; - - if (!partial_srv_trans_enc_ctx) { - status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } - - gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; - - in_buf.value = secblob.data; - in_buf.length = secblob.length; - - out_buf.value = NULL; - out_buf.length = 0; - - become_root(); - - ret = gss_accept_sec_context(&min, - &gss_state->gss_ctx, - gss_state->creds, - &in_buf, - GSS_C_NO_CHANNEL_BINDINGS, - NULL, - NULL, /* Ignore oids. */ - &out_buf, /* To return. */ - &flags, - NULL, /* Ingore time. */ - NULL); /* Ignore delegated creds. */ - unbecome_root(); - - status = gss_err_to_ntstatus(ret, min); - if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - return status; - } - - /* Ensure we've got sign+seal available. */ - if (ret == GSS_S_COMPLETE) { - if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != - (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { - DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " - "for SMB sealing.\n")); - gss_release_buffer(&min, &out_buf); - return NT_STATUS_ACCESS_DENIED; - } - } - - auth_reply = data_blob(out_buf.value, out_buf.length); - gss_release_buffer(&min, &out_buf); - - /* Wrap in SPNEGO. */ - response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); - data_blob_free(&auth_reply); - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - - return status; -} -#endif - -/****************************************************************************** - Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap) -{ - NTSTATUS status; - DATA_BLOB chal = data_blob_null; - DATA_BLOB response = data_blob_null; - - status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); - - /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED - * for success ... */ - - if (spnego_wrap) { - response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); - data_blob_free(&chal); - } else { - /* Return the raw blob. */ - response = chal; - } - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Do the SPNEGO encryption negotiation. Parameters are in/out. - Based off code in smbd/sesssionsetup.c - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - DATA_BLOB secblob = data_blob_null; - BOOL got_kerberos_mechanism = False; - - blob = data_blob_const(*ppdata, *p_data_size); - - status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - - /* We should have no partial context at this point. */ - - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { - status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); - } else -#endif - { - status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, True); - } - - data_blob_free(&secblob); - - if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); - } - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); - *p_param_size = 2; - } - - return status; -} - -/****************************************************************************** - Complete a SPNEGO encryption negotiation. Parameters are in/out. - We only get this for a NTLM auth second stage. -******************************************************************************/ - -static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - DATA_BLOB auth = data_blob_null; - DATA_BLOB auth_reply = data_blob_null; - DATA_BLOB response = data_blob_null; - struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; - - /* We must have a partial context here. */ - - if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - blob = data_blob_const(*ppdata, *p_data_size); - if (!spnego_parse_auth(blob, &auth)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); - data_blob_free(&auth); - - response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); - data_blob_free(&auth_reply); - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,ec->es->enc_ctx_num); - *p_param_size = 2; - } - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Raw NTLM encryption negotiation. Parameters are in/out. - This function does both steps. -******************************************************************************/ - -static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); - DATA_BLOB response = data_blob_null; - struct smb_srv_trans_enc_ctx *ec; - - if (!partial_srv_trans_enc_ctx) { - /* This is the initial step. */ - status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False); - if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); - } - return status; - } - - ec = partial_srv_trans_enc_ctx; - if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - /* Second step. */ - status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,ec->es->enc_ctx_num); - *p_param_size = 2; - } - - /* Return the raw blob. */ - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Do the SPNEGO encryption negotiation. Parameters are in/out. -******************************************************************************/ - -NTSTATUS srv_request_encryption_setup(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - unsigned char *pdata = *ppdata; - - SAFE_FREE(*pparam); - *p_param_size = 0; - - if (*p_data_size < 1) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (pdata[0] == ASN1_APPLICATION(0)) { - /* its a negTokenTarg packet */ - return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); - } - - if (pdata[0] == ASN1_CONTEXT(1)) { - /* It's an auth packet */ - return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); - } - - /* Maybe it's a raw unwrapped auth ? */ - if (*p_data_size < 7) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { - return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); - } - - DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); - - return NT_STATUS_LOGON_FAILURE; -} - -/****************************************************************************** - Negotiation was successful - turn on server-side encryption. -******************************************************************************/ - -static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) -{ - if (!ec || !ec->es) { - return NT_STATUS_LOGON_FAILURE; - } - - if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != - (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { - return NT_STATUS_INVALID_PARAMETER; - } - } - /* Todo - check gssapi case. */ - - return NT_STATUS_OK; -} - -/****************************************************************************** - Negotiation was successful - turn on server-side encryption. -******************************************************************************/ - -NTSTATUS srv_encryption_start(connection_struct *conn) -{ - NTSTATUS status; - - /* Check that we are really doing sign+seal. */ - status = check_enc_good(partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* Throw away the context we're using currently (if any). */ - srv_free_encryption_context(&srv_trans_enc_ctx); - - /* Steal the partial pointer. Deliberate shallow copy. */ - srv_trans_enc_ctx = partial_srv_trans_enc_ctx; - srv_trans_enc_ctx->es->enc_on = True; - - partial_srv_trans_enc_ctx = NULL; - return NT_STATUS_OK; -} - -/****************************************************************************** - Shutdown all server contexts. -******************************************************************************/ - -void server_encryption_shutdown(void) -{ - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - srv_free_encryption_context(&srv_trans_enc_ctx); -} diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 72eeb7ee6a..0f47a550e9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4,7 +4,6 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 Copyright (C) Jelmer Vernooij 2002-2003 - Copyright (C) James Peach 2007 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 @@ -293,34 +292,26 @@ static BOOL allowable_number_of_smbd_processes(void) return num_children < max_processes; } -/**************************************************************************** - Are we idle enough that we could safely exit? -****************************************************************************/ - -static BOOL smbd_is_idle(void) -{ - /* Currently we define "idle" as having no client connections. */ - return count_all_current_connections() == 0; -} - /**************************************************************************** Open the socket communication. ****************************************************************************/ -static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ports) +static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) { + int num_interfaces = iface_count(); int num_sockets = 0; int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; int maxfd = 0; int i; - struct timeval idle_timeout = timeval_zero(); + char *ports; - if (server_mode == SERVER_MODE_INETD) { + if (!is_daemon) { return open_sockets_inetd(); } + #ifdef HAVE_ATEXIT { static int atexit_set; @@ -333,21 +324,116 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ /* Stop zombies */ CatchSignal(SIGCLD, sig_cld); - + FD_ZERO(&listen_set); - /* At this point, it doesn't matter what daemon mode we are in, we - * need some sockets to listen on. - */ - num_sockets = smbd_sockinit(smb_ports, fd_listenset, &idle_timeout); - if (num_sockets == 0) { - return False; + /* use a reasonable default set of ports - listing on 445 and 139 */ + if (!smb_ports) { + ports = lp_smb_ports(); + if (!ports || !*ports) { + ports = smb_xstrdup(SMB_PORTS); + } else { + ports = smb_xstrdup(ports); + } + } else { + ports = smb_xstrdup(smb_ports); } - for (i = 0; i < num_sockets; ++i) { - FD_SET(fd_listenset[i], &listen_set); - maxfd = MAX(maxfd, fd_listenset[i]); - } + if (lp_interfaces() && lp_bind_interfaces_only()) { + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + + /* Now open a listen socket for each of the + interfaces. */ + for(i = 0; i < num_interfaces; i++) { + struct in_addr *ifip = iface_n_ip(i); + fstring tok; + const char *ptr; + + if(ifip == NULL) { + DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); + continue; + } + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0 || port > 0xffff) { + continue; + } + s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + if(s == -1) + return False; + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } + FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); + + num_sockets++; + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } + } + } + } else { + /* Just bind to 0.0.0.0 - accept connections + from anywhere. */ + + fstring tok; + const char *ptr; + + num_interfaces = 1; + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0 || port > 0xffff) continue; + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address()),True); + if (s == -1) + return(False); + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("open_sockets_smbd: listen: %s\n", + strerror(errno))); + close(s); + return False; + } + + fd_listenset[num_sockets] = s; + FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); + + num_sockets++; + + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } + } + } + + SAFE_FREE(ports); /* Setup the main smbd so that we can get messages. Note that @@ -380,7 +466,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ for each incoming connection */ DEBUG(2,("waiting for a connection\n")); while (1) { - struct timeval now; + struct timeval now, idle_timeout; fd_set r_fds, w_fds; int num; @@ -396,6 +482,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ } } + idle_timeout = timeval_zero(); + memcpy((char *)&r_fds, (char *)&listen_set, sizeof(listen_set)); FD_ZERO(&w_fds); @@ -405,21 +493,9 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ &r_fds, &w_fds, &idle_timeout, &maxfd); - if (timeval_is_zero(&idle_timeout)) { - num = sys_select(maxfd + 1, &r_fds, &w_fds, - NULL, NULL); - } else { - num = sys_select(maxfd + 1, &r_fds, &w_fds, - NULL, &idle_timeout); - - /* If the idle timeout fired and we are idle, exit - * gracefully. We expect to be running under a process - * controller that will restart us if necessry. - */ - if (num == 0 && smbd_is_idle()) { - exit_server_cleanly("idle timeout"); - } - } + num = sys_select(maxfd+1,&r_fds,&w_fds,NULL, + timeval_is_zero(&idle_timeout) ? + NULL : &idle_timeout); if (num == -1 && errno == EINTR) { if (got_sig_term) { @@ -436,7 +512,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ continue; } - + if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { continue; } @@ -476,13 +552,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ /* Ensure child is set to blocking mode */ set_blocking(smbd_server_fd(),True); - /* In interactive mode, return with a connected socket. - * Foreground and daemon modes should fork worker - * processes. - */ - if (server_mode == SERVER_MODE_INTERACTIVE) { + if (smbd_server_fd() != -1 && interactive) return True; - } if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && @@ -694,8 +765,6 @@ static void exit_server_common(enum server_exit_reason how, locking_end(); printing_end(); - server_encryption_shutdown(); - if (how != SERVER_EXIT_NORMAL) { int oldlevel = DEBUGLEVEL; @@ -804,26 +873,23 @@ extern void build_options(BOOL screen); int main(int argc,const char *argv[]) { /* shall I run as a daemon */ - BOOL no_process_group = False; - BOOL log_stdout = False; - const char *ports = NULL; - const char *profile_level = NULL; + static BOOL is_daemon = False; + static BOOL interactive = False; + static BOOL Fork = True; + static BOOL no_process_group = False; + static BOOL log_stdout = False; + static char *ports = NULL; + static char *profile_level = NULL; int opt; poptContext pc; BOOL print_build_options = False; - enum smb_server_mode server_mode = SERVER_MODE_DAEMON; - struct poptOption long_options[] = { POPT_AUTOHELP - {"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON, - "Become a daemon (default)" }, - {"interactive", 'i', POPT_ARG_VAL, &server_mode, SERVER_MODE_INTERACTIVE, - "Run interactive (not a daemon)"}, - {"foreground", 'F', POPT_ARG_VAL, &server_mode, SERVER_MODE_FOREGROUND, - "Run daemon in foreground (for daemontools, etc.)" }, - {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, - "Don't create a new process group" }, + {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, + {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, + {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" }, + {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, @@ -870,14 +936,16 @@ extern void build_options(BOOL screen); set_remote_machine_name("smbd", False); - if (server_mode == SERVER_MODE_INTERACTIVE) { + if (interactive) { + Fork = False; log_stdout = True; - if (DEBUGLEVEL >= 9) { - talloc_enable_leak_report(); - } } - if (log_stdout && server_mode == SERVER_MODE_DAEMON) { + if (interactive && (DEBUGLEVEL >= 9)) { + talloc_enable_leak_report(); + } + + if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } @@ -967,19 +1035,21 @@ extern void build_options(BOOL screen); DEBUG(3,( "loaded services\n")); - if (is_a_socket(0)) { - if (server_mode == SERVER_MODE_DAEMON) { - DEBUG(0,("standard input is a socket, " - "assuming -F option\n")); - } - server_mode = SERVER_MODE_INETD; + if (!is_daemon && !is_a_socket(0)) { + if (!interactive) + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + + /* + * Setting is_daemon here prevents us from eventually calling + * the open_sockets_inetd() + */ + + is_daemon = True; } - if (server_mode == SERVER_MODE_DAEMON) { + if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(True, no_process_group); - } else if (server_mode == SERVER_MODE_FOREGROUND) { - become_daemon(False, no_process_group); + become_daemon(Fork, no_process_group); } #if HAVE_SETPGID @@ -987,18 +1057,15 @@ extern void build_options(BOOL screen); * If we're interactive we want to set our own process group for * signal management. */ - if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) { + if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); - } #endif if (!directory_exist(lp_lockdir(), NULL)) mkdir(lp_lockdir(), 0755); - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + if (is_daemon) pidfile_create("smbd"); - } /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ @@ -1052,10 +1119,9 @@ extern void build_options(BOOL screen); running as a daemon -- bad things will happen if smbd is launched via inetd and we fork a copy of ourselves here */ - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + + if ( is_daemon && !interactive ) start_background_queue(); - } /* Always attempt to initialize DMAPI. We will only use it later if * lp_dmapi_support is set on the share, but we need a single global @@ -1063,9 +1129,8 @@ extern void build_options(BOOL screen); */ dmapi_init_session(); - if (!open_sockets_smbd(server_mode, ports)) { + if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); - } /* * everything after this point is run after the fork() @@ -1078,8 +1143,7 @@ extern void build_options(BOOL screen); /* Possibly reload the services file. Only worth doing in * daemon mode. In inetd mode, we know we only just loaded this. */ - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + if (is_daemon) { reload_services(True); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4daa2924a2..1c46e3776c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -312,14 +312,7 @@ static int load_registry_service(const char *servicename) TALLOC_FREE(value); } - if (!service_ok(res)) { - /* this is actually never reached, since - * service_ok only returns False if the service - * entry does not have a service name, and we _know_ - * we do have a service name here... */ - res = -1; - } - + res = 0; error: TALLOC_FREE(key); @@ -409,6 +402,10 @@ int find_service(fstring service) if (iService < 0) { } + if (iService < 0) { + iService = load_registry_service(service); + } + /* Is it a usershare service ? */ if (iService < 0 && *lp_usershare_path()) { /* Ensure the name is canonicalized. */ @@ -444,10 +441,6 @@ int find_service(fstring service) } } - if (iService < 0) { - iService = load_registry_service(service); - } - if (iService >= 0) { if (!VALID_SNUM(iService)) { DEBUG(0,("Invalid snum %d for %s\n",iService, service)); @@ -789,6 +782,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->veto_list = NULL; conn->hide_list = NULL; conn->veto_oplock_list = NULL; + conn->aio_write_behind_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index c7cdf41fb5..8dd321fad7 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -201,12 +201,9 @@ BOOL session_claim(user_struct *vuser) sessionid.id_str, sessionid.id_num); } - TALLOC_FREE(rec); - vuser->session_keystr = talloc_strdup(vuser, keystr); if (!vuser->session_keystr) { - DEBUG(0, ("session_claim: talloc_strdup() failed for " - "session_keystr\n")); + DEBUG(0, ("session_claim: talloc_strdup() failed for session_keystr\n")); return False; } return True; diff --git a/source3/smbd/sockinit.c b/source3/smbd/sockinit.c deleted file mode 100644 index 598bbd1bda..0000000000 --- a/source3/smbd/sockinit.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) James Peach 2007 - - 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 3 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, see . -*/ - -#include "includes.h" -#include "smb_launchd.h" - -extern pstring user_socket_options; - -static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) -{ - int num_interfaces = iface_count(); - char * ports; - int num_sockets = 0; - int i, s; - - /* use a reasonable default set of ports - listing on 445 and 139 */ - if (!smb_ports) { - ports = lp_smb_ports(); - if (!ports || !*ports) { - ports = smb_xstrdup(SMB_PORTS); - } else { - ports = smb_xstrdup(ports); - } - } else { - ports = smb_xstrdup(smb_ports); - } - - if (lp_interfaces() && lp_bind_interfaces_only()) { - /* We have been given an interfaces line, and been - told to only bind to those interfaces. Create a - socket per interface and bind to only these. - */ - - /* Now open a listen socket for each of the - interfaces. */ - for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); - fstring tok; - const char *ptr; - - if(ifip == NULL) { - DEBUG(0,("init_sockets_smbd: interface %d has " - "NULL IP address !\n", i)); - continue; - } - - for (ptr=ports; next_token(&ptr, tok, " \t,", - sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0 || port > 0xffff) { - continue; - } - s = listenset[num_sockets] = - open_socket_in(SOCK_STREAM, - port, - 0, - ifip->s_addr, - True); - if(s == -1) - return 0; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking - * for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("listen: %s\n", - strerror(errno))); - close(s); - return 0; - } - - num_sockets++; - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: " - "Too many sockets to bind to\n")); - return 0; - } - } - } - } else { - /* Just bind to 0.0.0.0 - accept connections - from anywhere. */ - - fstring tok; - const char *ptr; - - num_interfaces = 1; - - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0 || port > 0xffff) continue; - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()), - True); - if (s == -1) - return 0; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("init_sockets_smbd: listen: %s\n", - strerror(errno))); - close(s); - return 0; - } - - listenset[num_sockets] = s; - num_sockets++; - - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: " - "Too many sockets to bind to\n")); - return 0; - } - } - } - - SAFE_FREE(ports); - return num_sockets; -} - -static int init_sockets_launchd(const struct smb_launch_info *linfo, - const char * smb_ports, - int listenset[FD_SETSIZE]) -{ - int num_sockets; - int i; - - /* The launchd service configuration does not have to provide sockets, - * even though it's basically useless without it. - */ - if (!linfo->num_sockets) { - return init_sockets_smbd(smb_ports, listenset); - } - - /* Make sure we don't get more sockets than we can handle. */ - num_sockets = MIN(FD_SETSIZE, linfo->num_sockets); - memcpy(listenset, linfo->socket_list, num_sockets * sizeof(int)); - - /* Get the sockets ready. This could be hoisted into - * open_sockets_smbd(), but the order of socket operations might - * matter for some platforms, so this approach seems less risky. - * --jpeach - */ - for (i = 0; i < num_sockets; ++i) { - set_socket_options(listenset[i], "SO_KEEPALIVE"); - set_socket_options(listenset[i], user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(listenset[i], False); - } - - return num_sockets; -} - -/* This function is responsible for opening (or retrieving) all the sockets we - * smbd will be listening on. It should apply all the configured socket options - * and return the number of valid sockets in listenset. - */ -int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE], - struct timeval *idle) -{ - int num_sockets; - struct smb_launch_info linfo; - - ZERO_STRUCTP(idle); - - if (smb_launchd_checkin(&linfo)) { - /* We are running under launchd and launchd has - * opened some sockets for us. - */ - num_sockets = init_sockets_launchd(&linfo, - cmdline_ports, - listenset); - idle->tv_sec = linfo.idle_timeout_secs; - smb_launchd_checkout(&linfo); - } else { - num_sockets = init_sockets_smbd(cmdline_ports, - listenset); - } - - return num_sockets; -} diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index fbcf249ffb..68e61033ae 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -79,7 +79,7 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags) DEBUG(0, ("srvstr_push failed\n")); return -1; } - set_message_bcc(NULL, (char *)tmp, smb_buflen(tmp) + result); + set_message_bcc((char *)tmp, smb_buflen(tmp) + result); *outbuf = tmp; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ada4868bf8..7392271b48 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2733,9 +2733,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_FCNTL_LOCKS_CAP| CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| - /* Ensure we don't do this on signed or sealed data. */ - (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP) - ))); + CIFS_UNIX_LARGE_READ_CAP))); break; case SMB_QUERY_POSIX_FS_INFO: @@ -2986,51 +2984,6 @@ cap_low = 0x%x, cap_high = 0x%x\n", } break; } - case SMB_REQUEST_TRANSPORT_ENCRYPTION: - { - NTSTATUS status; - size_t param_len = 0; - size_t data_len = total_data; - - if (!lp_unix_extensions()) { - reply_nterror( - req, NT_STATUS_INVALID_LEVEL); - return; - } - - DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n")); - - status = srv_request_encryption_setup(conn, - (unsigned char **)ppdata, - &data_len, - (unsigned char **)pparams, - ¶m_len - ); - - if (!NT_STATUS_IS_OK(status)) { - /* - * TODO: Check - * MORE_PROCESSING_REQUIRED, this used - * to have special handling here. - */ - reply_nterror(req, status); - return; - } - - send_trans2_replies(req, - *pparams, param_len, - *ppdata, data_len, - max_data_bytes); - - if (NT_STATUS_IS_OK(status)) { - /* Server-side transport encryption is now *on*. */ - status = srv_encryption_start(conn); - if (!NT_STATUS_IS_OK(status)) { - exit_server_cleanly("Failure in setting up encrypted transport"); - } - } - return; - } case SMB_FS_QUOTA_INFORMATION: { files_struct *fsp = NULL; diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 7f43740754..52174c4d83 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -220,13 +220,13 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau } /* For u-files and non-explicit w-dir, look for "utmp dir" */ - if (strlen(dirname) == 0) { + if (dirname == 0 || strlen(dirname) == 0) { pstrcpy(dirname,lp_utmpdir()); trim_char(dirname,'\0','/'); } /* If explicit directory above, use it */ - if (strlen(dirname) != 0) { + if (dirname != 0 && strlen(dirname) != 0) { pstrcpy(fname, dirname); pstrcat(fname, "/"); pstrcat(fname, uw_name); -- cgit From 39d30c54995b93c095dd8e367cff756c8a4b6e7f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Oct 2007 17:24:44 -0700 Subject: Fix valgrind-found memory overwrite. (This used to be commit 183df4754b5f18419f4d8fca2c0fa19919174556) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7392271b48..ce038e719a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1469,7 +1469,7 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx, p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); nameptr = p; len = srvstr_push(base_data, flags2, - p + 1, fname, PTR_DIFF(end_data, p), + p + 1, fname, PTR_DIFF(end_data, p+1), STR_TERMINATE | STR_NOALIGN); if (flags2 & FLAGS2_UNICODE_STRINGS) { if (len > 2) { @@ -1554,7 +1554,7 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx, SOFF_T(p,0,allocation_size); p += 8; SIVAL(p,0,nt_extmode); p += 4; len = srvstr_push(base_data, flags2, - p + 4, fname, PTR_DIFF(end_data, p), + p + 4, fname, PTR_DIFF(end_data, p+4), STR_TERMINATE_ASCII); SIVAL(p,0,len); p += 4 + len; -- cgit From 8e54530b52fd256137740107e9fdf000f00a7a30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Oct 2007 18:25:16 -0700 Subject: Add start of IPv6 implementation. Currently most of this is avoiding IPv6 in winbindd, but moves most of the socket functions that were wrongly in lib/util.c into lib/util_sock.c and provides generic IPv4/6 independent versions of most things. Still lots of work to do, but now I can see how I'll fix the access check code. Nasty part that remains is the name resolution code which is used to returning arrays of in_addr structs. Jeremy. (This used to be commit 3f6bd0e1ec5cc6670f3d08f76fc2cd94c9cd1a08) --- source3/smbd/server.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0f47a550e9..8c92c91577 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -348,15 +348,24 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); + const struct sockaddr_storage *ifss = + iface_n_sockaddr_storage(i); + const struct in_addr *ifip; fstring tok; const char *ptr; - if(ifip == NULL) { + if (ifss == NULL) { DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); continue; } + /* For now only deal with IPv4. */ + if (ifss->ss_family != AF_INET) { + continue; + } + + ifip = &((const struct sockaddr_in *)ifss)->sin_addr; + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0 || port > 0xffff) { -- cgit From cb5436bcc3b55e0c221fb6b3fa3133f149a64384 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Oct 2007 15:36:13 -0700 Subject: Add const to the get_peer_addr() and get_socket_addr() calls. Use the IPv6 varient for get_peer_addr(). Jeremy. (This used to be commit baf1f52e34ae2465a7a34be1065da29ed97e7bea) --- source3/smbd/session.c | 2 +- source3/smbd/sesssetup.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 8dd321fad7..54d2ddf721 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -65,7 +65,7 @@ BOOL session_claim(user_struct *vuser) struct sessionid sessionid; struct server_id pid = procid_self(); fstring keystr; - char * hostname; + const char * hostname; struct db_context *ctx; struct db_record *rec; NTSTATUS status; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 20021ec7f7..a2f24c66d2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1314,7 +1314,8 @@ static void setup_new_vc_session(void) invalidate_all_vuids(); #endif if (lp_reset_on_zero_vc()) { - connections_forall(shutdown_other_smbds, client_addr()); + connections_forall(shutdown_other_smbds, + CONST_DISCARD(void *,client_addr())); } } -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/aio.c | 24 +++++----- source3/smbd/blocking.c | 30 ++++++------ source3/smbd/chgpasswd.c | 40 ++++++++-------- source3/smbd/close.c | 8 ++-- source3/smbd/conn.c | 4 +- source3/smbd/connection.c | 18 ++++---- source3/smbd/dfree.c | 6 +-- source3/smbd/dir.c | 54 +++++++++++----------- source3/smbd/dmapi.c | 4 +- source3/smbd/dosmode.c | 8 ++-- source3/smbd/error.c | 6 +-- source3/smbd/fileio.c | 10 ++-- source3/smbd/filename.c | 20 ++++---- source3/smbd/ipc.c | 6 +-- source3/smbd/lanman.c | 100 ++++++++++++++++++++-------------------- source3/smbd/mangle.c | 14 +++--- source3/smbd/mangle_hash.c | 28 ++++++------ source3/smbd/mangle_hash2.c | 38 +++++++-------- source3/smbd/map_username.c | 8 ++-- source3/smbd/msdfs.c | 56 +++++++++++------------ source3/smbd/negprot.c | 8 ++-- source3/smbd/noquotas.c | 2 +- source3/smbd/notify.c | 8 ++-- source3/smbd/notify_inotify.c | 2 +- source3/smbd/ntquotas.c | 2 +- source3/smbd/nttrans.c | 28 ++++++------ source3/smbd/open.c | 42 ++++++++--------- source3/smbd/oplock.c | 24 +++++----- source3/smbd/oplock_irix.c | 6 +-- source3/smbd/oplock_linux.c | 6 +-- source3/smbd/password.c | 16 +++---- source3/smbd/pipes.c | 4 +- source3/smbd/posix_acls.c | 102 ++++++++++++++++++++--------------------- source3/smbd/process.c | 18 ++++---- source3/smbd/quotas.c | 34 +++++++------- source3/smbd/reply.c | 104 +++++++++++++++++++++--------------------- source3/smbd/sec_ctx.c | 10 ++-- source3/smbd/server.c | 30 ++++++------ source3/smbd/service.c | 18 ++++---- source3/smbd/session.c | 6 +-- source3/smbd/sesssetup.c | 34 +++++++------- source3/smbd/share_access.c | 12 ++--- source3/smbd/statcache.c | 8 ++-- source3/smbd/trans2.c | 90 ++++++++++++++++++------------------ source3/smbd/uid.c | 20 ++++---- source3/smbd/utmp.c | 10 ++-- source3/smbd/vfs.c | 22 ++++----- 47 files changed, 574 insertions(+), 574 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 6ee0fe16e1..994b10d6a8 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -35,7 +35,7 @@ struct aio_extra { struct aio_extra *next, *prev; SMB_STRUCT_AIOCB acb; files_struct *fsp; - BOOL read_req; + bool read_req; uint16 mid; char *inbuf; char *outbuf; @@ -163,7 +163,7 @@ static void signal_handler(int sig, siginfo_t *info, void *unused) Is there a signal waiting ? *****************************************************************************/ -BOOL aio_finished(void) +bool aio_finished(void) { return (signals_received != 0); } @@ -192,7 +192,7 @@ void initialize_async_io_handler(void) Set up an aio request from a SMBreadX call. *****************************************************************************/ -BOOL schedule_aio_read_and_X(connection_struct *conn, +bool schedule_aio_read_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) @@ -272,7 +272,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, Set up an aio request from a SMBwriteX call. *****************************************************************************/ -BOOL schedule_aio_write_and_X(connection_struct *conn, +bool schedule_aio_write_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, char *data, SMB_OFF_T startpos, @@ -281,7 +281,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; size_t inbufsize, outbufsize; - BOOL write_through = BITSETW(req->inbuf+smb_vwv7,0); + bool write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { @@ -495,7 +495,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) UNIXERROR(ERRHRD,ERRdiskfull); ret = errno; } else { - BOOL write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); + bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); NTSTATUS status; SSVAL(outbuf,smb_vwv2,nwritten); @@ -534,7 +534,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) was non-zero), False if not. *****************************************************************************/ -static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) +static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) { int err; @@ -747,7 +747,7 @@ void cancel_aio_by_fsp(files_struct *fsp) } #else -BOOL aio_finished(void) +bool aio_finished(void) { return False; } @@ -761,7 +761,7 @@ int process_aio_queue(void) return False; } -BOOL schedule_aio_read_and_X(connection_struct *conn, +bool schedule_aio_read_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) @@ -769,7 +769,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, return False; } -BOOL schedule_aio_write_and_X(connection_struct *conn, +bool schedule_aio_write_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, char *data, SMB_OFF_T startpos, @@ -782,8 +782,8 @@ void cancel_aio_by_fsp(files_struct *fsp) { } -BOOL wait_for_aio_completion(files_struct *fsp) +int wait_for_aio_completion(files_struct *fsp) { - return True; + return ENOSYS; } #endif diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ef70829f74..66a61449a1 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -66,7 +66,7 @@ static void free_blocking_lock_record(blocking_lock_record *blr) Determine if this is a secondary element of a chained SMB. **************************************************************************/ -static BOOL in_chained_smb(void) +static bool in_chained_smb(void) { return (chain_size != 0); } @@ -97,7 +97,7 @@ static void brl_timeout_fn(struct event_context *event_ctx, next processing. ****************************************************************************/ -static BOOL recalc_brl_timeout(void) +static bool recalc_brl_timeout(void) { blocking_lock_record *brl; struct timeval next_timeout; @@ -148,7 +148,7 @@ static BOOL recalc_brl_timeout(void) Function to push a blocking lock request onto the lock queue. ****************************************************************************/ -BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, +bool push_blocking_lock_request( struct byte_range_lock *br_lck, const char *inbuf, int length, files_struct *fsp, int lock_timeout, @@ -160,7 +160,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, SMB_BIG_UINT count, uint32 blocking_pid) { - static BOOL set_lock_msg; + static bool set_lock_msg; blocking_lock_record *blr; NTSTATUS status; @@ -327,7 +327,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; uint32 lock_pid; unsigned char locktype = CVAL(inbuf,smb_vwv3); - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); + bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; int i; @@ -345,7 +345,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) */ for(i = blr->lock_num - 1; i >= 0; i--) { - BOOL err; + bool err; lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); @@ -404,7 +404,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status Returns True if we want to be removed from the list. *****************************************************************************/ -static BOOL process_lockingX(blocking_lock_record *blr) +static bool process_lockingX(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); @@ -413,7 +413,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; uint32 lock_pid; - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); + bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; NTSTATUS status = NT_STATUS_OK; @@ -426,7 +426,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) for(; blr->lock_num < num_locks; blr->lock_num++) { struct byte_range_lock *br_lck = NULL; - BOOL err; + bool err; lock_pid = get_lock_pid( data, blr->lock_num, large_file_format); count = get_lock_count( data, blr->lock_num, large_file_format); @@ -494,7 +494,7 @@ Waiting....\n", Returns True if we want to be removed from the list. *****************************************************************************/ -static BOOL process_trans2(blocking_lock_record *blr) +static bool process_trans2(blocking_lock_record *blr) { struct smb_request *req; char params[2]; @@ -546,7 +546,7 @@ static BOOL process_trans2(blocking_lock_record *blr) Returns True if we want to be removed from the list. *****************************************************************************/ -static BOOL blocking_lock_record_process(blocking_lock_record *blr) +static bool blocking_lock_record_process(blocking_lock_record *blr) { switch(blr->com_type) { case SMBlockingX: @@ -639,7 +639,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); Is this mid a blocking lock request on the queue ? *****************************************************************************/ -BOOL blocking_lock_was_deferred(int mid) +bool blocking_lock_was_deferred(int mid) { blocking_lock_record *blr, *next = NULL; @@ -674,7 +674,7 @@ static void process_blocking_lock_queue(void) { struct timeval tv_curr = timeval_current(); blocking_lock_record *blr, *next = NULL; - BOOL recalc_timeout = False; + bool recalc_timeout = False; /* * Go through the queue and see if we can get any of the locks. @@ -861,7 +861,7 @@ static void process_blocking_lock_cancel_message(struct messaging_context *ctx, Send ourselves a blocking lock cancelled message. Handled asynchronously above. *****************************************************************************/ -BOOL blocking_lock_cancel(files_struct *fsp, +bool blocking_lock_cancel(files_struct *fsp, uint32 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count, @@ -869,7 +869,7 @@ BOOL blocking_lock_cancel(files_struct *fsp, unsigned char locktype, NTSTATUS err) { - static BOOL initialized; + static bool initialized; char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE]; blocking_lock_record *blr; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 242f0e0753..fb6e6c0f09 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -119,7 +119,7 @@ static int findpty(char **slave) } static int dochild(int master, const char *slavedev, const struct passwd *pass, - const char *passwordprogram, BOOL as_root) + const char *passwordprogram, bool as_root) { int slave; struct termios stermios; @@ -233,7 +233,7 @@ static int expect(int master, char *issue, char *expected) { pstring buffer; int attempts, timeout, nread, len; - BOOL match = False; + bool match = False; for (attempts = 0; attempts < 2; attempts++) { if (!strequal(issue, ".")) { @@ -331,14 +331,14 @@ static int talktochild(int master, const char *seq) return (count > 0); } -static BOOL chat_with_program(char *passwordprogram, const struct passwd *pass, - char *chatsequence, BOOL as_root) +static bool chat_with_program(char *passwordprogram, const struct passwd *pass, + char *chatsequence, bool as_root) { char *slavedev; int master; pid_t pid, wpid; int wstat; - BOOL chstat = False; + bool chstat = False; if (pass == NULL) { DEBUG(0, ("chat_with_program: user doesn't exist in the UNIX password database.\n")); @@ -446,8 +446,8 @@ while we were waiting\n", WTERMSIG(wstat))); return (chstat); } -BOOL chgpasswd(const char *name, const struct passwd *pass, - const char *oldpass, const char *newpass, BOOL as_root) +bool chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, bool as_root) { pstring passwordprogram; pstring chatsequence; @@ -496,7 +496,7 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, #ifdef WITH_PAM if (lp_pam_password_change()) { - BOOL ret; + bool ret; if (as_root) become_root(); @@ -557,8 +557,8 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(const char *name, const struct passwd *pass, - const char *oldpass, const char *newpass, BOOL as_root) +bool chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, bool as_root) { DEBUG(0, ("chgpasswd: Unix Password changing not compiled in (user=%s)\n", name)); return (False); @@ -569,7 +569,7 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, Code to check the lanman hashed password. ************************************************************/ -BOOL check_lanman_password(char *user, uchar * pass1, +bool check_lanman_password(char *user, uchar * pass1, uchar * pass2, struct samu **hnd) { uchar unenc_new_pw[16]; @@ -577,7 +577,7 @@ BOOL check_lanman_password(char *user, uchar * pass1, struct samu *sampass = NULL; uint32 acct_ctrl; const uint8 *lanman_pw; - BOOL ret; + bool ret; if ( !(sampass = samu_new(NULL)) ) { DEBUG(0, ("samu_new() failed!\n")); @@ -641,11 +641,11 @@ BOOL check_lanman_password(char *user, uchar * pass1, is correct before calling. JRA. ************************************************************/ -BOOL change_lanman_password(struct samu *sampass, uchar *pass2) +bool change_lanman_password(struct samu *sampass, uchar *pass2) { static uchar null_pw[16]; uchar unenc_new_pw[16]; - BOOL ret; + bool ret; uint32 acct_ctrl; const uint8 *pwd; @@ -766,10 +766,10 @@ static NTSTATUS check_oem_password(const char *user, uchar new_lm_hash[16]; uchar verifier[16]; char no_pw[2]; - BOOL ret; + bool ret; - BOOL nt_pass_set = (password_encrypted_with_nt_hash && old_nt_hash_encrypted); - BOOL lm_pass_set = (password_encrypted_with_lm_hash && old_lm_hash_encrypted); + bool nt_pass_set = (password_encrypted_with_nt_hash && old_nt_hash_encrypted); + bool lm_pass_set = (password_encrypted_with_lm_hash && old_lm_hash_encrypted); *hnd = NULL; @@ -948,13 +948,13 @@ static NTSTATUS check_oem_password(const char *user, found in the history list. ************************************************************/ -static BOOL check_passwd_history(struct samu *sampass, const char *plaintext) +static bool check_passwd_history(struct samu *sampass, const char *plaintext) { uchar new_nt_p16[NT_HASH_LEN]; uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN]; const uint8 *nt_pw; const uint8 *pwhistory; - BOOL found = False; + bool found = False; int i; uint32 pwHisLen, curr_pwHisLen; @@ -1015,7 +1015,7 @@ static BOOL check_passwd_history(struct samu *sampass, const char *plaintext) is correct before calling. JRA. ************************************************************/ -NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason) +NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, bool as_root, uint32 *samr_reject_reason) { uint32 min_len; uint32 refuse; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index ae45aaa6da..d2ee73d09d 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -162,7 +162,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, enum file_close_type close_type) { connection_struct *conn = fsp->conn; - BOOL delete_file = False; + bool delete_file = False; struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; @@ -189,7 +189,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) { - BOOL became_user = False; + bool became_user = False; /* Initial delete on close was set and no one else * wrote a real delete on close. */ @@ -432,7 +432,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type) { struct share_mode_lock *lck = 0; - BOOL delete_dir = False; + bool delete_dir = False; NTSTATUS status = NT_STATUS_OK; /* @@ -452,7 +452,7 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty } if (fsp->initial_delete_on_close) { - BOOL became_user = False; + bool became_user = False; /* Initial delete on close was set - for * directories we don't care if anyone else diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 50a71edf9d..5aedadc56b 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -52,7 +52,7 @@ int conn_num_open(void) /**************************************************************************** check if a snum is in use ****************************************************************************/ -BOOL conn_snum_used(int snum) +bool conn_snum_used(int snum) { connection_struct *conn; for (conn=Connections;conn;conn=conn->next) { @@ -186,7 +186,7 @@ void conn_close_all(void) Idle inactive connections. ****************************************************************************/ -BOOL conn_idle_all(time_t t) +bool conn_idle_all(time_t t) { int deadtime = lp_deadtime()*60; pipes_struct *plist = NULL; diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 65b7c352c5..e9f1b82fbf 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -23,7 +23,7 @@ Delete a connection record. ****************************************************************************/ -BOOL yield_connection(connection_struct *conn, const char *name) +bool yield_connection(connection_struct *conn, const char *name) { struct db_record *rec; NTSTATUS status; @@ -50,7 +50,7 @@ struct count_stat { pid_t mypid; int curr_connections; const char *name; - BOOL Clear; + bool Clear; }; /**************************************************************************** @@ -94,7 +94,7 @@ static int count_fn(struct db_record *rec, Claim an entry in the connections database. ****************************************************************************/ -int count_current_connections( const char *sharename, BOOL clear ) +int count_current_connections( const char *sharename, bool clear ) { struct count_stat cs; @@ -121,7 +121,7 @@ int count_current_connections( const char *sharename, BOOL clear ) Claim an entry in the connections database. ****************************************************************************/ -BOOL claim_connection(connection_struct *conn, const char *name, +bool claim_connection(connection_struct *conn, const char *name, uint32 msg_flags) { struct db_record *rec; @@ -170,7 +170,7 @@ BOOL claim_connection(connection_struct *conn, const char *name, return True; } -BOOL register_message_flags(BOOL doreg, uint32 msg_flags) +bool register_message_flags(bool doreg, uint32 msg_flags) { struct db_record *rec; struct connections_data *pcrec; @@ -255,13 +255,13 @@ static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p ) /********************************************************************* *********************************************************************/ -BOOL store_pipe_opendb( smb_np_struct *p ) +bool store_pipe_opendb( smb_np_struct *p ) { struct db_record *dbrec; struct pipe_open_rec *prec; TDB_DATA *key; TDB_DATA data; - BOOL ret = False; + bool ret = False; if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { DEBUG(0,("store_pipe_opendb: talloc failed!\n")); @@ -291,12 +291,12 @@ done: /********************************************************************* *********************************************************************/ -BOOL delete_pipe_opendb( smb_np_struct *p ) +bool delete_pipe_opendb( smb_np_struct *p ) { struct db_record *dbrec; struct pipe_open_rec *prec; TDB_DATA *key; - BOOL ret = False; + bool ret = False; if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { DEBUG(0,("store_pipe_opendb: talloc failed!\n")); diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 9439468600..31eb9fbd60 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -23,7 +23,7 @@ Normalise for DOS usage. ****************************************************************************/ -static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +static void disk_norm(bool small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { /* check if the disk is beyond the max disk size */ SMB_BIG_UINT maxdisksize = lp_maxdisksize(); @@ -62,7 +62,7 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree, Return number of 1K blocks available on a path and total number. ****************************************************************************/ -SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small_query, +SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, bool small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { SMB_BIG_UINT dfree_retval; @@ -176,7 +176,7 @@ SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small SMB_BIG_UINT get_dfree_info(connection_struct *conn, const char *path, - BOOL small_query, + bool small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index a7b1b020b8..f6a8b27ab4 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -55,12 +55,12 @@ struct dptr_struct { uint16 spid; struct connection_struct *conn; struct smb_Dir *dir_hnd; - BOOL expect_close; + bool expect_close; char *wcard; uint32 attr; char *path; - BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ - BOOL did_stat; /* Optimisation for non-wcard searches. */ + bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ + bool did_stat; /* Optimisation for non-wcard searches. */ }; static struct bitmap *dptr_bmap; @@ -73,14 +73,14 @@ static int dirhandles_open = 0; Make a dir struct. ****************************************************************************/ -BOOL make_dir_struct(TALLOC_CTX *ctx, +bool make_dir_struct(TALLOC_CTX *ctx, char *buf, const char *mask, const char *fname, SMB_OFF_T size, uint32 mode, time_t date, - BOOL uc) + bool uc) { char *p; char *mask2 = talloc_strdup(ctx, mask); @@ -121,7 +121,7 @@ BOOL make_dir_struct(TALLOC_CTX *ctx, void init_dptrs(void) { - static BOOL dptrs_init=False; + static bool dptrs_init=False; if (dptrs_init) return; @@ -182,7 +182,7 @@ static void dptr_idleoldest(void) Get the struct dptr_struct for a dir index. ****************************************************************************/ -static struct dptr_struct *dptr_get(int key, BOOL forclose) +static struct dptr_struct *dptr_get(int key, bool forclose) { struct dptr_struct *dptr; @@ -354,7 +354,7 @@ void dptr_closepath(char *path,uint16 spid) finished with that one. ****************************************************************************/ -static void dptr_close_oldest(BOOL old) +static void dptr_close_oldest(bool old) { struct dptr_struct *dptr; @@ -393,8 +393,8 @@ static void dptr_close_oldest(BOOL old) wcard must not be zero. ****************************************************************************/ -NTSTATUS dptr_create(connection_struct *conn, const char *path, BOOL old_handle, BOOL expect_close,uint16 spid, - const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret) +NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, bool expect_close,uint16 spid, + const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret) { struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; @@ -546,7 +546,7 @@ long dptr_TellDir(struct dptr_struct *dptr) return TellDir(dptr->dir_hnd); } -BOOL dptr_has_wild(struct dptr_struct *dptr) +bool dptr_has_wild(struct dptr_struct *dptr) { return dptr->has_wild; } @@ -663,7 +663,7 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx, Search for a file by name, skipping veto'ed and not visible files. ****************************************************************************/ -BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) +bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) { SET_STAT_INVALID(*pst); @@ -689,7 +689,7 @@ void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset) Fill the 5 byte server reserved dptr field. ****************************************************************************/ -BOOL dptr_fill(char *buf1,unsigned int key) +bool dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; struct dptr_struct *dptr = dptr_get(key, False); @@ -754,7 +754,7 @@ struct dptr_struct *dptr_fetch_lanman2(int dptr_num) Check that a file matches a particular file type. ****************************************************************************/ -BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) +bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) { uint32 mask; @@ -776,7 +776,7 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) return True; } -static BOOL mangle_mask_match(connection_struct *conn, +static bool mangle_mask_match(connection_struct *conn, const char *filename, const char *mask) { @@ -792,7 +792,7 @@ static BOOL mangle_mask_match(connection_struct *conn, Get an 8.3 directory entry. ****************************************************************************/ -BOOL get_dir_entry(TALLOC_CTX *ctx, +bool get_dir_entry(TALLOC_CTX *ctx, connection_struct *conn, const char *mask, uint32 dirtype, @@ -800,14 +800,14 @@ BOOL get_dir_entry(TALLOC_CTX *ctx, SMB_OFF_T *size, uint32 *mode, time_t *date, - BOOL check_descend) + bool check_descend) { const char *dname = NULL; - BOOL found = False; + bool found = False; SMB_STRUCT_STAT sbuf; char *pathreal = NULL; const char *filename = NULL; - BOOL needslash; + bool needslash; *pp_fname_out = NULL; @@ -908,7 +908,7 @@ BOOL get_dir_entry(TALLOC_CTX *ctx, use it for anything security sensitive. ********************************************************************/ -static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) +static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { SEC_DESC *psd = NULL; size_t sd_size; @@ -971,7 +971,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S use it for anything security sensitive. ********************************************************************/ -static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) +static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { SEC_DESC *psd = NULL; size_t sd_size; @@ -1030,7 +1030,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ Is a file a "special" type ? ********************************************************************/ -static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) +static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { /* * If user is a member of the Admin group @@ -1054,11 +1054,11 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT Should the file be seen by the client ? ********************************************************************/ -BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto) +bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto) { - BOOL hide_unreadable = lp_hideunreadable(SNUM(conn)); - BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); - BOOL hide_special = lp_hide_special_files(SNUM(conn)); + bool hide_unreadable = lp_hideunreadable(SNUM(conn)); + bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); + bool hide_special = lp_hide_special_files(SNUM(conn)); SET_STAT_INVALID(*pst); @@ -1309,7 +1309,7 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) Don't check for veto or invisible files. ********************************************************************/ -BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) +bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) { int i; const char *entry; diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 127d1627cf..05e9138ea9 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -27,7 +27,7 @@ int dmapi_init_session(void) { return -1; } uint32 dmapi_file_flags(const char * const path) { return 0; } -BOOL dmapi_have_session(void) { return False; } +bool dmapi_have_session(void) { return False; } #else /* USE_DMAPI */ @@ -73,7 +73,7 @@ static int init_dmapi_service(void) return 0; } -BOOL dmapi_have_session(void) +bool dmapi_have_session(void) { return dmapi_session != DM_NO_SESSION; } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index b4ab0ca226..ed622d3730 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -200,7 +200,7 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_ Get DOS attributes from an EA. ****************************************************************************/ -static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr) +static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr) { ssize_t sizeret; fstring attrstr; @@ -256,11 +256,11 @@ static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S Set DOS attributes in an EA. ****************************************************************************/ -static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode) +static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode) { fstring attrstr; files_struct *fsp = NULL; - BOOL ret = False; + bool ret = False; if (!lp_store_dos_attributes(SNUM(conn))) { return False; @@ -587,7 +587,7 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -BOOL set_filetime(connection_struct *conn, const char *fname, +bool set_filetime(connection_struct *conn, const char *fname, const struct timespec mtime) { struct timespec ts[2]; diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 6cb63f0c49..12eff42023 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -52,7 +52,7 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s return error_packet(outbuf,eclass,ecode,ntstatus,line,file); } -BOOL use_nt_status(void) +bool use_nt_status(void) { return lp_nt_status_support() && (global_client_caps & CAP_STATUS32); } @@ -66,8 +66,8 @@ BOOL use_nt_status(void) void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { - BOOL force_nt_status = False; - BOOL force_dos_status = False; + bool force_nt_status = False; + bool force_dos_status = False; if (eclass == (uint8)-1) { force_nt_status = True; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 76b29ec998..14056ddc80 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -21,13 +21,13 @@ #include "includes.h" -static BOOL setup_write_cache(files_struct *, SMB_OFF_T); +static bool setup_write_cache(files_struct *, SMB_OFF_T); /**************************************************************************** Read from write cache if we can. ****************************************************************************/ -static BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) +static bool read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { write_cache *wcp = fsp->wcp; @@ -297,7 +297,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", */ if (wcp->data_size) { - BOOL cache_flush_needed = False; + bool cache_flush_needed = False; if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) { @@ -739,7 +739,7 @@ void delete_write_cache(files_struct *fsp) Setup the write cache structure. ****************************************************************************/ -static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) +static bool setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) { ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); write_cache *wcp; @@ -845,7 +845,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) sync a file ********************************************************************/ -NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, BOOL write_through) +NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_through) { if (fsp->fh->fd == -1) return NT_STATUS_INVALID_HANDLE; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index fb8ed07ee8..dc733d4568 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -26,14 +26,14 @@ #include "includes.h" -static BOOL scan_directory(connection_struct *conn, const char *path, +static bool scan_directory(connection_struct *conn, const char *path, char *name, char **found_name); /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(const char *name1, +static bool mangled_equal(const char *name1, const char *name2, const struct share_params *p) { @@ -50,7 +50,7 @@ static BOOL mangled_equal(const char *name1, ****************************************************************************/ static NTSTATUS determine_path_error(const char *name, - BOOL allow_wcard_last_component) + bool allow_wcard_last_component) { const char *p; @@ -110,7 +110,7 @@ for nlinks = 0, which can never be true for any file). NTSTATUS unix_convert(TALLOC_CTX *ctx, connection_struct *conn, const char *orig_path, - BOOL allow_wcard_last_component, + bool allow_wcard_last_component, char **pp_conv_path, char **pp_saved_last_component, SMB_STRUCT_STAT *pst) @@ -119,8 +119,8 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, char *start, *end; char *dirpath = NULL; char *name = NULL; - BOOL component_was_mangled = False; - BOOL name_has_wildcard = False; + bool component_was_mangled = False; + bool name_has_wildcard = False; NTSTATUS result; SET_STAT_INVALID(*pst); @@ -702,8 +702,8 @@ NTSTATUS check_name(connection_struct *conn, const char *name) This needs to be careful about whether we are case sensitive. ****************************************************************************/ -static BOOL fname_equal(const char *name1, const char *name2, - BOOL case_sensitive) +static bool fname_equal(const char *name1, const char *name2, + bool case_sensitive) { /* Normal filename handling */ if (case_sensitive) { @@ -718,12 +718,12 @@ static BOOL fname_equal(const char *name1, const char *name2, If the name looks like a mangled name then try via the mangling functions ****************************************************************************/ -static BOOL scan_directory(connection_struct *conn, const char *path, +static bool scan_directory(connection_struct *conn, const char *path, char *name, char **found_name) { struct smb_Dir *cur_dir; const char *dname; - BOOL mangled; + bool mangled; char *unmangled_name = NULL; long curpos; TALLOC_CTX *ctx = talloc_tos(); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0709acc756..0360417c56 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -84,7 +84,7 @@ static void copy_trans_params_and_data(char *outbuf, int align, void send_trans_reply(struct smb_request *req, char *rparam, int rparam_len, char *rdata, int rdata_len, - BOOL buffer_too_large) + bool buffer_too_large) { int this_ldata,this_lparam; int tot_data_sent = 0; @@ -190,7 +190,7 @@ void send_trans_reply(struct smb_request *req, static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p) { - BOOL is_data_outstanding; + bool is_data_outstanding; char *rdata = (char *)SMB_MALLOC(p->max_trans_reply); int data_len; @@ -294,7 +294,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, int suwcnt, int tdscnt, int tpscnt, int mdrcnt, int mprcnt) { - BOOL reply = False; + bool reply = False; smb_np_struct *p = NULL; int pnum; int subcommand; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 87cbc9183e..440b928ef0 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -64,14 +64,14 @@ static char *smb_realloc_limit(void *ptr, size_t size) return val; } -static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, +static bool api_Unsupported(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len); -static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data, +static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len); @@ -146,7 +146,7 @@ static char *Expand(connection_struct *conn, int snum, char *s) Check a API string for validity when we only need to check the prefix. ******************************************************************/ -static BOOL prefix_ok(const char *str, const char *prefix) +static bool prefix_ok(const char *str, const char *prefix) { return(strncmp(str,prefix,strlen(prefix)) == 0); } @@ -221,7 +221,7 @@ static int getlen(const char *p) return n; } -static BOOL init_package(struct pack_desc *p, int count, int subcount) +static bool init_package(struct pack_desc *p, int count, int subcount) { int n = p->buflen; int i; @@ -572,10 +572,10 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, Returns True if from tdb, False otherwise. ********************************************************************/ -static BOOL get_driver_name(int snum, pstring drivername) +static bool get_driver_name(int snum, pstring drivername) { NT_PRINTER_INFO_LEVEL *info = NULL; - BOOL in_tdb = False; + bool in_tdb = False; get_a_printer (NULL, &info, 2, lp_servicename(snum)); if (info != NULL) { @@ -787,7 +787,7 @@ static int get_printerdrivernumber(int snum) return result; } -static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, +static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -915,7 +915,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, View list of all print jobs on all queues. ****************************************************************************/ -static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, +static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt, int mprcnt, @@ -1060,7 +1060,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, Get info level for a server list query. ****************************************************************************/ -static BOOL check_server_info(int uLevel, char* id) +static bool check_server_info(int uLevel, char* id) { switch( uLevel ) { case 0: @@ -1084,7 +1084,7 @@ struct srv_info_struct { uint32 type; fstring comment; fstring domain; - BOOL server_added; + bool server_added; }; /******************************************************************* @@ -1099,7 +1099,7 @@ static int get_server_info(uint32 servertype, int count=0; int alloced=0; char **lines; - BOOL local_list_only; + bool local_list_only; int i; lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0); @@ -1121,7 +1121,7 @@ static int get_server_info(uint32 servertype, fstring stype; struct srv_info_struct *s; const char *ptr = lines[i]; - BOOL ok = True; + bool ok = True; if (!*ptr) { continue; @@ -1280,7 +1280,7 @@ static int fill_srv_info(struct srv_info_struct *service, } -static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) +static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) { return(strcmp(s1->name,s2->name)); } @@ -1290,7 +1290,7 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) extracted from lists saved by nmbd on the local host. ****************************************************************************/ -static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, +static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt, int mprcnt, char **rdata, @@ -1309,8 +1309,8 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, int counted=0,total=0; int i,missed; fstring domain; - BOOL domain_request; - BOOL local_request; + bool domain_request; + bool local_request; if (!str1 || !str2 || !p) { return False; @@ -1445,7 +1445,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, command 0x34 - suspected of being a "Lookup Names" stub api ****************************************************************************/ -static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, +static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt, int mprcnt, char **rdata, @@ -1490,7 +1490,7 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, get info about a share ****************************************************************************/ -static BOOL check_share_info(int uLevel, char* id) +static bool check_share_info(int uLevel, char* id) { switch( uLevel ) { case 0: @@ -1634,7 +1634,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, return len; } -static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, +static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -1697,7 +1697,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, Share names longer than 12 bytes must be skipped. ****************************************************************************/ -static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, +static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt, @@ -1715,7 +1715,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, char *p2; int count = 0; int total=0,counted=0; - BOOL missed = False; + bool missed = False; int i; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; @@ -1804,7 +1804,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, Add a share ****************************************************************************/ -static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, +static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -1942,7 +1942,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, view list of groups available ****************************************************************************/ -static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, +static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2048,7 +2048,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, Get groups that a user is a member of. ******************************************************************/ -static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, +static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2063,7 +2063,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, const char *level_string; int count=0; struct samu *sampw = NULL; - BOOL ret = False; + bool ret = False; DOM_SID *sids; gid_t *gids; size_t num_groups; @@ -2188,7 +2188,7 @@ done: Get all users. ******************************************************************/ -static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, +static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2292,7 +2292,7 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, Get the time of day info. ****************************************************************************/ -static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, +static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2350,7 +2350,7 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, Set the user password. *****************************************************************************/ -static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, +static bool api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2461,7 +2461,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, Set the user password (SamOEM version - gets plaintext). ****************************************************************************/ -static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, +static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2539,7 +2539,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, Form: <> ****************************************************************************/ -static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, +static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2622,7 +2622,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, Purge a print queue - or pause or resume it. ****************************************************************************/ -static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, +static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2714,7 +2714,7 @@ static int check_printjob_info(struct pack_desc* desc, return True; } -static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, +static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2802,7 +2802,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, Get info about the server. ****************************************************************************/ -static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, +static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -2943,7 +2943,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, Get info about the server. ****************************************************************************/ -static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, +static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3211,7 +3211,7 @@ There is no auxiliary data in the response. #define AF_OP_ACCOUNTS 3 -static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, +static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3431,7 +3431,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, return(True); } -static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, +static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3534,7 +3534,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, api_WAccessGetUserPerms ****************************************************************************/ -static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, +static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3579,7 +3579,7 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, api_WPrintJobEnumerate ****************************************************************************/ -static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, +static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3678,7 +3678,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, return True; } -static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, +static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3835,7 +3835,7 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, } } -static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, +static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3915,7 +3915,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, return True; } -static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, +static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -3996,7 +3996,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, return True; } -static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, +static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -4059,7 +4059,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, return True; } -static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, +static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -4122,7 +4122,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, return True; } -static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, +static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -4191,7 +4191,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, List open sessions ****************************************************************************/ -static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, +static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt,int mprcnt, @@ -4276,7 +4276,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, The buffer was too small. ****************************************************************************/ -static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data, +static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, int *rdata_len, int *rparam_len) @@ -4300,7 +4300,7 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char The request is not supported. ****************************************************************************/ -static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, +static bool api_Unsupported(connection_struct *conn, uint16 vuid, char *param, int tpscnt, char *data, int tdscnt, int mdrcnt, int mprcnt, @@ -4326,11 +4326,11 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, static const struct { const char *name; int id; - BOOL (*fn)(connection_struct *, uint16, + bool (*fn)(connection_struct *, uint16, char *, int, char *, int, int,int,char **,char **,int *,int *); - BOOL auth_user; /* Deny anonymous access? */ + bool auth_user; /* Deny anonymous access? */ } api_commands[] = { {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True}, {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo}, @@ -4390,7 +4390,7 @@ void api_reply(connection_struct *conn, uint16 vuid, const char *name2 = NULL; int rdata_len = 0; int rparam_len = 0; - BOOL reply=False; + bool reply=False; int i; if (!params) { diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 4c00f6d14a..360692c546 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -80,7 +80,7 @@ void mangle_change_to_posix(void) /* see if a filename has come out of our mangling code */ -BOOL mangle_is_mangled(const char *s, const struct share_params *p) +bool mangle_is_mangled(const char *s, const struct share_params *p) { return mangle_fns->is_mangled(s, p); } @@ -88,19 +88,19 @@ BOOL mangle_is_mangled(const char *s, const struct share_params *p) /* see if a filename matches the rules of a 8.3 filename */ -BOOL mangle_is_8_3(const char *fname, BOOL check_case, +bool mangle_is_8_3(const char *fname, bool check_case, const struct share_params *p) { return mangle_fns->is_8_3(fname, check_case, False, p); } -BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, +bool mangle_is_8_3_wildcards(const char *fname, bool check_case, const struct share_params *p) { return mangle_fns->is_8_3(fname, check_case, True, p); } -BOOL mangle_must_mangle(const char *fname, +bool mangle_must_mangle(const char *fname, const struct share_params *p) { if (!lp_manglednames(p)) { @@ -115,7 +115,7 @@ BOOL mangle_must_mangle(const char *fname, looking for a matching name if it doesn't. It should succeed most of the time or there will be a huge performance penalty */ -BOOL mangle_lookup_name_from_8_3(TALLOC_CTX *ctx, +bool mangle_lookup_name_from_8_3(TALLOC_CTX *ctx, const char *in, char **out, /* talloced on the given context. */ const struct share_params *p) @@ -130,9 +130,9 @@ BOOL mangle_lookup_name_from_8_3(TALLOC_CTX *ctx, JRA. */ -BOOL name_to_8_3(const char *in, +bool name_to_8_3(const char *in, char out[13], - BOOL cache83, + bool cache83, const struct share_params *p) { memset(out,'\0',13); diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index d63a980cfb..44fbe8a9e8 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -58,7 +58,7 @@ static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; #define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) static unsigned char chartest[256] = { 0 }; -static BOOL ct_initialized = False; +static bool ct_initialized = False; #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) #define BASECHAR_MASK 0xf0 @@ -68,7 +68,7 @@ static TDB_CONTEXT *tdb_mangled_cache; /* -------------------------------------------------------------------- */ -static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, BOOL allow_wildcards) +static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, bool allow_wildcards) { if (!*s) { return NT_STATUS_INVALID_PARAMETER; @@ -88,7 +88,7 @@ static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, BOOL allow_wildcards) return NT_STATUS_OK; } -static NTSTATUS has_illegal_chars(const smb_ucs2_t *s, BOOL allow_wildcards) +static NTSTATUS has_illegal_chars(const smb_ucs2_t *s, bool allow_wildcards) { if (!allow_wildcards && ms_has_wild_w(s)) { return NT_STATUS_UNSUCCESSFUL; @@ -117,7 +117,7 @@ static NTSTATUS has_illegal_chars(const smb_ucs2_t *s, BOOL allow_wildcards) */ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, - smb_ucs2_t **extension, BOOL allow_wildcards) + smb_ucs2_t **extension, bool allow_wildcards) { size_t ext_len; smb_ucs2_t *p; @@ -155,7 +155,7 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr * ************************************************************************** ** */ -static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOOL only_8_3) +static NTSTATUS is_valid_name(const smb_ucs2_t *fname, bool allow_wildcards, bool only_8_3) { smb_ucs2_t *str, *p; size_t num_ucs2_chars; @@ -234,7 +234,7 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOO return ret; } -static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards) +static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, bool allow_wildcards) { smb_ucs2_t *pref = 0, *ext = 0; size_t plen; @@ -275,7 +275,7 @@ done: return ret; } -static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, +static bool is_8_3(const char *fname, bool check_case, bool allow_wildcards, const struct share_params *p) { const char *f; @@ -361,7 +361,7 @@ static void init_chartest( void ) * ************************************************************************** ** */ -static BOOL is_mangled(const char *s, const struct share_params *p) +static bool is_mangled(const char *s, const struct share_params *p) { char *magic; @@ -461,7 +461,7 @@ static void cache_mangled_name( const char mangled_name[13], * ************************************************************************** ** */ -static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, +static bool lookup_name_from_8_3(TALLOC_CTX *ctx, const char *in, char **out, /* talloced on the given context. */ const struct share_params *p) @@ -526,7 +526,7 @@ static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, Do the actual mangling to 8.3 format. *****************************************************************************/ -static BOOL to_8_3(const char *in, char out[13], int default_case) +static bool to_8_3(const char *in, char out[13], int default_case) { int csum; char *p; @@ -545,7 +545,7 @@ static BOOL to_8_3(const char *in, char out[13], int default_case) p = strrchr(s,'.'); if( p && (strlen(p+1) < (size_t)4) ) { - BOOL all_normal = ( strisnormal(p+1, default_case) ); /* XXXXXXXXX */ + bool all_normal = ( strisnormal(p+1, default_case) ); /* XXXXXXXXX */ if( all_normal && p[1] != 0 ) { *p = 0; @@ -599,7 +599,7 @@ static BOOL to_8_3(const char *in, char out[13], int default_case) return True; } -static BOOL must_mangle(const char *name, +static bool must_mangle(const char *name, const struct share_params *p) { smb_ucs2_t *name_ucs2 = NULL; @@ -630,9 +630,9 @@ static BOOL must_mangle(const char *name, * **************************************************************************** */ -static BOOL hash_name_to_8_3(const char *in, +static bool hash_name_to_8_3(const char *in, char out[13], - BOOL cache83, + bool cache83, int default_case, const struct share_params *p) { diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 73f81fe9ae..7066c2a4e5 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -150,7 +150,7 @@ static unsigned int mangle_hash(const char *key, unsigned int length) /* initialise (ie. allocate) the prefix cache */ -static BOOL cache_init(void) +static bool cache_init(void) { if (prefix_cache) { return True; @@ -208,7 +208,7 @@ static const char *cache_lookup(unsigned int hash) In this algorithm, mangled names use only pure ascii characters (no multi-byte) so we can avoid doing a UCS2 conversion */ -static BOOL is_mangled_component(const char *name, size_t len) +static bool is_mangled_component(const char *name, size_t len) { unsigned int i; @@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len) directory separators. It should return true if any component is mangled */ -static BOOL is_mangled(const char *name, const struct share_params *parm) +static bool is_mangled(const char *name, const struct share_params *parm) { const char *p; const char *s; @@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name, const struct share_params *parm) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) +static bool is_8_3(const char *name, bool check_case, bool allow_wildcards, const struct share_params *p) { int len, i; char *dot_p; @@ -370,7 +370,7 @@ static void mangle_reset(void) try to find a 8.3 name in the cache, and if found then replace the string with the original long name. */ -static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, +static bool lookup_name_from_8_3(TALLOC_CTX *ctx, const char *name, char **pp_out, /* talloced on the given context. */ const struct share_params *p) @@ -432,7 +432,7 @@ static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, /* look for a DOS reserved name */ -static BOOL is_reserved_name(const char *name) +static bool is_reserved_name(const char *name) { if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) && FLAG_CHECK(name[1], FLAG_POSSIBLE2) && @@ -459,10 +459,10 @@ static BOOL is_reserved_name(const char *name) A filename ending in ' ' is not legal either. See bug id #2769. */ -static BOOL is_legal_name(const char *name) +static bool is_legal_name(const char *name) { const char *dot_pos = NULL; - BOOL alldots = True; + bool alldots = True; size_t numdots = 0; while (*name) { @@ -510,7 +510,7 @@ static BOOL is_legal_name(const char *name) return True; } -static BOOL must_mangle(const char *name, +static bool must_mangle(const char *name, const struct share_params *p) { if (is_reserved_name(name)) { @@ -526,9 +526,9 @@ static BOOL must_mangle(const char *name, if cache83 is not set then we don't cache the result */ -static BOOL hash2_name_to_8_3(const char *name, +static bool hash2_name_to_8_3(const char *name, char new_name[13], - BOOL cache83, + bool cache83, int default_case, const struct share_params *p) { @@ -738,25 +738,25 @@ struct mangle_fns *mangle_hash2_init(void) static void posix_mangle_reset(void) {;} -static BOOL posix_is_mangled(const char *s, const struct share_params *p) +static bool posix_is_mangled(const char *s, const struct share_params *p) { return False; } -static BOOL posix_must_mangle(const char *s, const struct share_params *p) +static bool posix_must_mangle(const char *s, const struct share_params *p) { return False; } -static BOOL posix_is_8_3(const char *fname, - BOOL check_case, - BOOL allow_wildcards, +static bool posix_is_8_3(const char *fname, + bool check_case, + bool allow_wildcards, const struct share_params *p) { return False; } -static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx, +static bool posix_lookup_name_from_8_3(TALLOC_CTX *ctx, const char *in, char **out, /* talloced on the given context. */ const struct share_params *p) @@ -764,9 +764,9 @@ static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx, return False; } -static BOOL posix_name_to_8_3(const char *in, +static bool posix_name_to_8_3(const char *in, char out[13], - BOOL cache83, + bool cache83, int default_case, const struct share_params *p) { diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index 38881b3b2d..d9ad81a3e1 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -32,15 +32,15 @@ Returns True if username was changed, false otherwise. ********************************************************************/ -BOOL map_username(fstring user) +bool map_username(fstring user) { - static BOOL initialised=False; + static bool initialised=False; static fstring last_from,last_to; XFILE *f; char *mapfile = lp_username_map(); char *s; pstring buf; - BOOL mapped_user = False; + bool mapped_user = False; char *cmd = lp_username_map_script(); if (!*user) @@ -113,7 +113,7 @@ BOOL map_username(fstring user) char *unixname = s; char *dosname = strchr_m(unixname,'='); char **dosuserlist; - BOOL return_if_mapped = False; + bool return_if_mapped = False; if (!dosname) continue; diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index ff55904b81..cca1e0a428 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -43,9 +43,9 @@ extern uint32 global_client_caps; **********************************************************************/ static NTSTATUS parse_dfs_path(const char *pathname, - BOOL allow_wcards, + bool allow_wcards, struct dfs_path *pdp, /* MUST BE TALLOCED */ - BOOL *ppath_contains_wcard) + bool *ppath_contains_wcard) { char *pathname_local; char *p,*temp; @@ -268,7 +268,7 @@ static NTSTATUS create_conn_struct(connection_struct *conn, server we're referring to understands posix paths. **********************************************************************/ -static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, +static bool parse_msdfs_symlink(TALLOC_CTX *ctx, const char *target, struct referral **preflist, int *refcount) @@ -349,7 +349,7 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, returns the target string from inside the link. **********************************************************************/ -static BOOL is_msdfs_link_internal(TALLOC_CTX *ctx, +static bool is_msdfs_link_internal(TALLOC_CTX *ctx, connection_struct *conn, const char *path, char **pp_link_target, @@ -418,7 +418,7 @@ static BOOL is_msdfs_link_internal(TALLOC_CTX *ctx, Returns true if the unix path is a valid msdfs symlink. **********************************************************************/ -BOOL is_msdfs_link(connection_struct *conn, +bool is_msdfs_link(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbufp) { @@ -449,7 +449,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, const char *dfspath, /* Incoming complete dfs path */ const struct dfs_path *pdp, /* Parsed out server+share+extrapath. */ - BOOL search_flag, /* Called from a findfirst ? */ + bool search_flag, /* Called from a findfirst ? */ int *consumedcntp, char **pp_targetpath) { @@ -587,9 +587,9 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, connection_struct *conn, const char *path_in, - BOOL search_wcard_flag, + bool search_wcard_flag, char **pp_path_out, - BOOL *ppath_contains_wcard) + bool *ppath_contains_wcard) { NTSTATUS status; struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); @@ -687,7 +687,7 @@ static NTSTATUS self_ref(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, - BOOL *self_referralp) + bool *self_referralp) { struct referral *ref; @@ -718,14 +718,14 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, - BOOL *self_referralp) + bool *self_referralp) { struct connection_struct conns; struct connection_struct *conn = &conns; char *targetpath = NULL; int snum; NTSTATUS status = NT_STATUS_NOT_FOUND; - BOOL dummy; + bool dummy; struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); if (!pdp) { @@ -884,7 +884,7 @@ static int setup_ver2_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, int consumedcnt, - BOOL self_referral) + bool self_referral) { char* pdata = *ppdata; @@ -993,7 +993,7 @@ static int setup_ver3_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, int consumedcnt, - BOOL self_referral) + bool self_referral) { char *pdata = *ppdata; @@ -1095,7 +1095,7 @@ int setup_dfs_referral(connection_struct *orig_conn, { struct junction_map *junction = NULL; int consumedcnt = 0; - BOOL self_referral = False; + bool self_referral = False; int reply_size = 0; char *pathnamep = NULL; char *local_dfs_path = NULL; @@ -1209,12 +1209,12 @@ int setup_dfs_referral(connection_struct *orig_conn, Creates a junction structure from a DFS pathname **********************************************************************/ -BOOL create_junction(TALLOC_CTX *ctx, +bool create_junction(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn) { int snum; - BOOL dummy; + bool dummy; struct dfs_path *pdp = TALLOC_P(ctx,struct dfs_path); NTSTATUS status; @@ -1260,7 +1260,7 @@ BOOL create_junction(TALLOC_CTX *ctx, Forms a valid Unix pathname from the junction **********************************************************************/ -static BOOL junction_to_local_path(const struct junction_map *jucn, +static bool junction_to_local_path(const struct junction_map *jucn, char **pp_path_out, connection_struct *conn_out) { @@ -1285,16 +1285,16 @@ static BOOL junction_to_local_path(const struct junction_map *jucn, return True; } -BOOL create_msdfs_link(const struct junction_map *jucn, - BOOL exists) +bool create_msdfs_link(const struct junction_map *jucn, + bool exists) { char *path = NULL; char *msdfs_link = NULL; connection_struct conns; connection_struct *conn = &conns; int i=0; - BOOL insert_comma = False; - BOOL ret = False; + bool insert_comma = False; + bool ret = False; ZERO_STRUCT(conns); @@ -1360,12 +1360,12 @@ out: return ret; } -BOOL remove_msdfs_link(const struct junction_map *jucn) +bool remove_msdfs_link(const struct junction_map *jucn) { char *path = NULL; connection_struct conns; connection_struct *conn = &conns; - BOOL ret = False; + bool ret = False; ZERO_STRUCT(conns); @@ -1604,12 +1604,12 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) NTSTATUS resolve_dfspath(TALLOC_CTX *ctx, connection_struct *conn, - BOOL dfs_pathnames, + bool dfs_pathnames, const char *name_in, char **pp_name_out) { NTSTATUS status = NT_STATUS_OK; - BOOL dummy; + bool dummy; if (dfs_pathnames) { status = dfs_redirect(ctx, conn, @@ -1630,17 +1630,17 @@ NTSTATUS resolve_dfspath(TALLOC_CTX *ctx, /****************************************************************************** Core function to resolve a dfs pathname possibly containing a wildcard. - This function is identical to the above except for the BOOL param to + This function is identical to the above except for the bool param to dfs_redirect but I need this to be separate so it's really clear when we're allowing wildcards and when we're not. JRA. ******************************************************************************/ NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx, connection_struct *conn, - BOOL dfs_pathnames, + bool dfs_pathnames, const char *name_in, char **pp_name_out, - BOOL *ppath_contains_wcard) + bool *ppath_contains_wcard) { NTSTATUS status = NT_STATUS_OK; if (dfs_pathnames) { diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 98109a2149..02f752fd67 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -24,8 +24,8 @@ extern fstring remote_proto; extern enum protocol_types Protocol; extern int max_recv; -BOOL global_encrypted_passwords_negotiated = False; -BOOL global_spnego_negotiated = False; +bool global_encrypted_passwords_negotiated = False; +bool global_spnego_negotiated = False; struct auth_context *negprot_global_auth_context = NULL; static void get_challenge(uint8 buff[8]) @@ -252,7 +252,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice) int secword=0; char *p, *q; - BOOL negotiate_spnego = False; + bool negotiate_spnego = False; time_t t = time(NULL); ssize_t ret; @@ -517,7 +517,7 @@ void reply_negprot(connection_struct *conn, struct smb_request *req) char **cliprotos; int i; - static BOOL done_negprot = False; + static bool done_negprot = False; START_PROFILE(SMBnegprot); diff --git a/source3/smbd/noquotas.c b/source3/smbd/noquotas.c index 0c23bb6f06..c8ff8edf62 100644 --- a/source3/smbd/noquotas.c +++ b/source3/smbd/noquotas.c @@ -23,7 +23,7 @@ * Needed for auto generation of proto.h. */ -BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { (*bsize) = 512; /* This value should be ignored */ diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b8c5085b41..ecb7d9dce8 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -46,7 +46,7 @@ struct notify_mid_map { uint16 mid; }; -static BOOL notify_change_record_identical(struct notify_change *c1, +static bool notify_change_record_identical(struct notify_change *c1, struct notify_change *c2) { /* Note this is deliberately case sensitive. */ @@ -57,7 +57,7 @@ static BOOL notify_change_record_identical(struct notify_change *c1, return False; } -static BOOL notify_marshall_changes(int num_changes, +static bool notify_marshall_changes(int num_changes, uint32 max_offset, struct notify_change *changes, prs_struct *ps) @@ -210,7 +210,7 @@ static void notify_callback(void *private_data, const struct notify_event *e) } NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, - BOOL recursive) + bool recursive) { char *fullpath; struct notify_entry e; @@ -243,7 +243,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, } NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, - uint32 filter, BOOL recursive, + uint32 filter, bool recursive, struct files_struct *fsp) { struct notify_change_request *request = NULL; diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index f332e4b3d2..73cee440d4 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -95,7 +95,7 @@ static int inotify_destructor(struct inotify_private *in) see if a particular event from inotify really does match a requested notify event in SMB */ -static BOOL filter_match(struct inotify_watch_context *w, +static bool filter_match(struct inotify_watch_context *w, struct inotify_event *e) { DEBUG(10, ("filter_match: e->mask=%x, w->mask=%x, w->filter=%x\n", diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 4fbf0384a4..96ca2bc656 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -140,7 +140,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, return ret; } -static BOOL allready_in_quota_list(SMB_NTQUOTA_LIST *qt_list, uid_t uid) +static bool allready_in_quota_list(SMB_NTQUOTA_LIST *qt_list, uid_t uid) { SMB_NTQUOTA_LIST *tmp_list = NULL; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e69fd86995..bbbde06619 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -271,7 +271,7 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, Is it an NTFS stream name ? ****************************************************************************/ -BOOL is_ntfs_stream_name(const char *fname) +bool is_ntfs_stream_name(const char *fname) { if (lp_posix_pathnames()) { return False; @@ -281,9 +281,9 @@ BOOL is_ntfs_stream_name(const char *fname) struct case_semantics_state { connection_struct *conn; - BOOL case_sensitive; - BOOL case_preserve; - BOOL short_case_preserve; + bool case_sensitive; + bool case_preserve; + bool short_case_preserve; }; /**************************************************************************** @@ -516,7 +516,7 @@ void reply_ntcreate_and_X(connection_struct *conn, struct timespec c_timespec; struct timespec a_timespec; struct timespec m_timespec; - BOOL extended_oplock_granted = False; + bool extended_oplock_granted = False; NTSTATUS status; struct case_semantics_state *case_state = NULL; TALLOC_CTX *ctx = talloc_tos(); @@ -1271,7 +1271,7 @@ static void call_nt_transact_create(connection_struct *conn, int info = 0; files_struct *fsp = NULL; char *p = NULL; - BOOL extended_oplock_granted = False; + bool extended_oplock_granted = False; uint32 flags; uint32 access_mask; uint32 file_attributes; @@ -1994,8 +1994,8 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req) char *newname = NULL; char *p; NTSTATUS status; - BOOL src_has_wcard = False; - BOOL dest_has_wcard = False; + bool src_has_wcard = False; + bool dest_has_wcard = False; uint32 attrs; uint16 rename_type; TALLOC_CTX *ctx = talloc_tos(); @@ -2149,7 +2149,7 @@ static void call_nt_transact_notify_change(connection_struct *conn, files_struct *fsp; uint32 filter; NTSTATUS status; - BOOL recursive; + bool recursive; if(setup_count < 6) { reply_doserror(req, ERRDOS, ERRbadfunc); @@ -2245,8 +2245,8 @@ static void call_nt_transact_rename(connection_struct *conn, char *params = *ppparams; char *new_name = NULL; files_struct *fsp = NULL; - BOOL replace_if_exists = False; - BOOL dest_has_wcard = False; + bool replace_if_exists = False; + bool dest_has_wcard = False; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); @@ -2514,7 +2514,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, files_struct *fsp; uint8 isFSctl; uint8 compfilter; - static BOOL logged_message; + static bool logged_message; char *pdata = *ppdata; if (setup_count != 8) { @@ -2606,7 +2606,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, */ SHADOW_COPY_DATA *shadow_data = NULL; TALLOC_CTX *shadow_mem_ctx = NULL; - BOOL labels = False; + bool labels = False; uint32 labels_data_count = 0; uint32 i; char *cur_pdata; @@ -2810,7 +2810,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, uint16 level = 0; size_t sid_len; DOM_SID sid; - BOOL start_enum = True; + bool start_enum = True; SMB_NTQUOTA_STRUCT qt; SMB_NTQUOTA_LIST *tmp_list; SMB_NTQUOTA_HANDLE *qt_handle = NULL; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fbc6f9ab64..4ed3a70411 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -24,10 +24,10 @@ extern const struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; -extern BOOL global_client_failed_oplock_break; +extern bool global_client_failed_oplock_break; struct deferred_open_record { - BOOL delayed_for_oplocks; + bool delayed_for_oplocks; struct file_id id; }; @@ -226,7 +226,7 @@ static NTSTATUS open_file(files_struct *fsp, NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); int local_flags = flags; - BOOL file_existed = VALID_STAT(*psbuf); + bool file_existed = VALID_STAT(*psbuf); fsp->fh->fd = -1; errno = EPERM; @@ -409,7 +409,7 @@ static NTSTATUS open_file(files_struct *fsp, Return True if the filename is one of the special executable types. ********************************************************************/ -static BOOL is_executable(const char *fname) +static bool is_executable(const char *fname) { if ((fname = strrchr_m(fname,'.'))) { if (strequal(fname,".com") || @@ -427,7 +427,7 @@ static BOOL is_executable(const char *fname) Returns True if conflict, False if not. ****************************************************************************/ -static BOOL share_conflict(struct share_mode_entry *entry, +static bool share_conflict(struct share_mode_entry *entry, uint32 access_mask, uint32 share_access) { @@ -571,7 +571,7 @@ static void validate_my_share_entries(int num, } #endif -static BOOL is_stat_open(uint32 access_mask) +static bool is_stat_open(uint32 access_mask) { return (access_mask && ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| @@ -592,7 +592,7 @@ static NTSTATUS open_mode_check(connection_struct *conn, uint32 access_mask, uint32 share_access, uint32 create_options, - BOOL *file_existed) + bool *file_existed) { int i; @@ -646,7 +646,7 @@ static NTSTATUS open_mode_check(connection_struct *conn, return NT_STATUS_OK; } -static BOOL is_delete_request(files_struct *fsp) { +static bool is_delete_request(files_struct *fsp) { return ((fsp->access_mask == DELETE_ACCESS) && (fsp->oplock_type == NO_OPLOCK)); } @@ -661,7 +661,7 @@ static BOOL is_delete_request(files_struct *fsp) { * 3) Only level2 around: Grant level2 and do nothing else. */ -static BOOL delay_for_oplocks(struct share_mode_lock *lck, +static bool delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, uint16 mid, int pass_number, @@ -669,9 +669,9 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, { int i; struct share_mode_entry *exclusive = NULL; - BOOL valid_entry = False; - BOOL delay_it = False; - BOOL have_level2 = False; + bool valid_entry = False; + bool delay_it = False; + bool have_level2 = False; NTSTATUS status; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; @@ -772,7 +772,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, return True; } -static BOOL request_timed_out(struct timeval request_time, +static bool request_timed_out(struct timeval request_time, struct timeval timeout) { struct timeval now, end_time; @@ -838,7 +838,7 @@ static void defer_open(struct share_mode_lock *lck, On overwrite open ensure that the attributes match. ****************************************************************************/ -static BOOL open_match_attributes(connection_struct *conn, +static bool open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_attr, uint32 new_dos_attr, @@ -950,7 +950,7 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, Open a file with a share mode - old openX method - map into NTCreate. ****************************************************************************/ -BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, +bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, uint32 *paccess_mask, uint32 *pshare_mode, uint32 *pcreate_disposition, @@ -1142,10 +1142,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, { int flags=0; int flags2=0; - BOOL file_existed = VALID_STAT(*psbuf); - BOOL def_acl = False; - BOOL posix_open = False; - BOOL new_file_created = False; + bool file_existed = VALID_STAT(*psbuf); + bool def_acl = False; + bool posix_open = False; + bool new_file_created = False; struct file_id id; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; @@ -1504,7 +1504,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { uint32 can_access_mask; - BOOL can_access = True; + bool can_access = True; SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); @@ -2084,7 +2084,7 @@ NTSTATUS open_directory(connection_struct *conn, files_struct **result) { files_struct *fsp = NULL; - BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; + bool dir_existed = VALID_STAT(*psbuf) ? True : False; struct share_mode_lock *lck = NULL; NTSTATUS status; int info = 0; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 9ac9d76284..a84a9dbcb9 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -25,7 +25,7 @@ /* Current number of oplocks we have outstanding. */ static int32 exclusive_oplocks_open = 0; static int32 level_II_oplocks_open = 0; -BOOL global_client_failed_oplock_break = False; +bool global_client_failed_oplock_break = False; extern uint32 global_client_caps; extern int smb_read_error; @@ -45,7 +45,7 @@ int32 get_number_of_exclusive_open_oplocks(void) Return True if an oplock message is pending. ****************************************************************************/ -BOOL oplock_message_waiting(fd_set *fds) +bool oplock_message_waiting(fd_set *fds) { if (koplocks && koplocks->msg_waiting(fds)) { return True; @@ -103,7 +103,7 @@ void process_kernel_oplocks(struct messaging_context *msg_ctx, fd_set *pfds) disabled (just sets flags). Returns True if oplock set. ****************************************************************************/ -BOOL set_file_oplock(files_struct *fsp, int oplock_type) +bool set_file_oplock(files_struct *fsp, int oplock_type) { if (koplocks && !koplocks->set_oplock(fsp, oplock_type)) { return False; @@ -176,9 +176,9 @@ static void downgrade_file_oplock(files_struct *fsp) to none even if a "break-to-level II" was sent. ****************************************************************************/ -BOOL remove_oplock(files_struct *fsp) +bool remove_oplock(files_struct *fsp) { - BOOL ret; + bool ret; struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ @@ -202,9 +202,9 @@ BOOL remove_oplock(files_struct *fsp) /* * Deal with a reply when a break-to-level II was sent. */ -BOOL downgrade_oplock(files_struct *fsp) +bool downgrade_oplock(files_struct *fsp) { - BOOL ret; + bool ret; struct share_mode_lock *lck; lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); @@ -389,7 +389,7 @@ static void process_oplock_async_level2_break_message(struct messaging_context * struct share_mode_entry msg; files_struct *fsp; char *break_msg; - BOOL sign_state; + bool sign_state; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -476,8 +476,8 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, struct share_mode_entry msg; files_struct *fsp; char *break_msg; - BOOL break_to_level2 = False; - BOOL sign_state; + bool break_to_level2 = False; + bool sign_state; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -588,7 +588,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, unsigned long file_id; files_struct *fsp; char *break_msg; - BOOL sign_state; + bool sign_state; if (data->data == NULL) { DEBUG(0, ("Got NULL buffer\n")); @@ -862,7 +862,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) Setup oplocks for this process. ****************************************************************************/ -BOOL init_oplocks(struct messaging_context *msg_ctx) +bool init_oplocks(struct messaging_context *msg_ctx) { DEBUG(3,("init_oplocks: initializing messages.\n")); diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 9f81a960f5..8dd4e27973 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -29,7 +29,7 @@ static int oplock_pipe_read = -1; Test to see if IRIX kernel oplocks work. ****************************************************************************/ -static BOOL irix_oplocks_available(void) +static bool irix_oplocks_available(void) { int fd; int pfd[2]; @@ -175,7 +175,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) Attempt to set an kernel oplock on a file. ****************************************************************************/ -static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) +static bool irix_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) { if(errno != EAGAIN) { @@ -244,7 +244,7 @@ static void irix_release_kernel_oplock(files_struct *fsp) Note that fds MAY BE NULL ! If so we must do our own select. ****************************************************************************/ -static BOOL irix_oplock_msg_waiting(fd_set *fds) +static bool irix_oplock_msg_waiting(fd_set *fds) { int selrtn; fd_set myfds; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index b07c2644a9..086f105b89 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -162,7 +162,7 @@ static files_struct *linux_oplock_receive_message(fd_set *fds) Attempt to set an kernel oplock on a file. ****************************************************************************/ -static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) +static bool linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " @@ -218,7 +218,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) See if a oplock message is waiting. ****************************************************************************/ -static BOOL linux_oplock_msg_waiting(fd_set *fds) +static bool linux_oplock_msg_waiting(fd_set *fds) { return signals_received != 0; } @@ -227,7 +227,7 @@ static BOOL linux_oplock_msg_waiting(fd_set *fds) See if the kernel supports oplocks. ****************************************************************************/ -static BOOL linux_oplocks_available(void) +static bool linux_oplocks_available(void) { int fd, ret; fd = open("/dev/null", O_RDONLY); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a1590f2a58..995abbf663 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -81,7 +81,7 @@ user_struct *get_valid_user_struct(uint16 vuid) SERVER_ALLOCATED_REQUIRED_YES); } -BOOL is_partial_auth_vuid(uint16 vuid) +bool is_partial_auth_vuid(uint16 vuid) { if (vuid == UID_FIELD_INVALID) { return False; @@ -453,7 +453,7 @@ const char *get_session_workgroup(void) try lower case. ****************************************************************************/ -BOOL user_in_netgroup(const char *user, const char *ngname) +bool user_in_netgroup(const char *user, const char *ngname) { #ifdef HAVE_NETGROUP static char *mydomain = NULL; @@ -500,7 +500,7 @@ BOOL user_in_netgroup(const char *user, const char *ngname) and netgroup lists. ****************************************************************************/ -BOOL user_in_list(const char *user,const char **list) +bool user_in_list(const char *user,const char **list) { if (!list || !*list) return False; @@ -581,10 +581,10 @@ BOOL user_in_list(const char *user,const char **list) Check if a username is valid. ****************************************************************************/ -static BOOL user_ok(const char *user, int snum) +static bool user_ok(const char *user, int snum) { char **valid, **invalid; - BOOL ret; + bool ret; valid = invalid = NULL; ret = True; @@ -730,10 +730,10 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) Note this is *NOT* used when logging on using sessionsetup_and_X. ****************************************************************************/ -BOOL authorise_login(int snum, fstring user, DATA_BLOB password, - BOOL *guest) +bool authorise_login(int snum, fstring user, DATA_BLOB password, + bool *guest) { - BOOL ok = False; + bool ok = False; #ifdef DEBUG_PASSWORD DEBUG(100,("authorise_login: checking authorisation on " diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index da43a29767..0ddc00c767 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -196,7 +196,7 @@ void reply_pipe_write_and_X(struct smb_request *req) size_t numtowrite = SVAL(req->inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(req->inbuf, smb_vwv11); - BOOL pipe_start_message_raw = + bool pipe_start_message_raw = ((SVAL(req->inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); @@ -266,7 +266,7 @@ void reply_pipe_read_and_X(struct smb_request *req) int smb_mincnt = SVAL(req->inbuf,smb_vwv6); int nread = -1; char *data; - BOOL unused; + bool unused; /* we don't use the offset given to use for pipe reads. This is deliberate, instead we always return the next lump of diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 116917d7eb..b8afbb8710 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -47,7 +47,7 @@ typedef struct canon_ace { enum ace_owner owner_type; enum ace_attribute attr; posix_id unix_ug; - BOOL inherited; + bool inherited; } canon_ace; #define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR) @@ -83,7 +83,7 @@ struct pai_entry { }; struct pai_val { - BOOL pai_protected; + bool pai_protected; unsigned int num_entries; struct pai_entry *entry_list; unsigned int num_def_entries; @@ -148,7 +148,7 @@ static unsigned int num_inherited_entries(canon_ace *ace_list) Create the on-disk format. Caller must free. ************************************************************************/ -static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL pai_protected, size_t *store_size) +static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, bool pai_protected, size_t *store_size) { char *pai_buf = NULL; canon_ace *ace_list = NULL; @@ -212,7 +212,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B ************************************************************************/ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list, - canon_ace *dir_ace_list, BOOL pai_protected) + canon_ace *dir_ace_list, bool pai_protected) { int ret; size_t store_size; @@ -275,7 +275,7 @@ static void free_inherited_info(struct pai_val *pal) Was this ACL protected ? ************************************************************************/ -static BOOL get_protected_flag(struct pai_val *pal) +static bool get_protected_flag(struct pai_val *pal) { if (!pal) return False; @@ -286,7 +286,7 @@ static BOOL get_protected_flag(struct pai_val *pal) Was this ACE inherited ? ************************************************************************/ -static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL default_ace) +static bool get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, bool default_ace) { struct pai_entry *paie; @@ -306,7 +306,7 @@ static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL d Ensure an attribute just read is valid. ************************************************************************/ -static BOOL check_pai_ok(char *pai_buf, size_t pai_buf_data_size) +static bool check_pai_ok(char *pai_buf, size_t pai_buf_data_size) { uint16 num_entries; uint16 num_def_entries; @@ -672,7 +672,7 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI Is the identity in two ACEs equal ? Check both SID and uid/gid. ****************************************************************************/ -static BOOL identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2) +static bool identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2) { if (sid_equal(&ace1->trustee, &ace2->trustee)) { return True; @@ -807,7 +807,7 @@ static void merge_aces( canon_ace **pp_list_head ) Check if we need to return NT4.x compatible ACL entries. ****************************************************************************/ -static BOOL nt4_compatible_acls(void) +static bool nt4_compatible_acls(void) { int compat = lp_acl_compatibility(); @@ -830,7 +830,7 @@ static BOOL nt4_compatible_acls(void) static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, mode_t perms, - BOOL directory_ace) + bool directory_ace) { SEC_ACCESS sa; uint32 nt_mask = 0; @@ -1045,7 +1045,7 @@ static void apply_default_perms(const files_struct *fsp, canon_ace *pace, mode_t expensive and will need optimisation. A *lot* of optimisation :-). JRA. ****************************************************************************/ -static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) +static bool uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) { const char *u_name = NULL; @@ -1077,17 +1077,17 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) type. ****************************************************************************/ -static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, +static bool ensure_canon_entry_valid(canon_ace **pp_ace, const files_struct *fsp, const DOM_SID *pfile_owner_sid, const DOM_SID *pfile_grp_sid, SMB_STRUCT_STAT *pst, - BOOL setting_acl) + bool setting_acl) { canon_ace *pace; - BOOL got_user = False; - BOOL got_grp = False; - BOOL got_other = False; + bool got_user = False; + bool got_grp = False; + bool got_other = False; canon_ace *pace_other = NULL; for (pace = *pp_ace; pace; pace = pace->next) { @@ -1137,7 +1137,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, /* See if the owning user is in any of the other groups in the ACE. If so, OR in the permissions from that group. */ - BOOL group_matched = False; + bool group_matched = False; canon_ace *pace_iter; for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) { @@ -1223,7 +1223,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid) { - BOOL got_user_obj, got_group_obj; + bool got_user_obj, got_group_obj; canon_ace *current_ace; int i, entries; @@ -1264,18 +1264,18 @@ static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID Unpack a SEC_DESC into two canonical ace lists. ****************************************************************************/ -static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, +static bool create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, canon_ace **ppfile_ace, canon_ace **ppdir_ace, SEC_ACL *dacl) { - BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); + bool all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; canon_ace *current_ace = NULL; - BOOL got_dir_allow = False; - BOOL got_file_allow = False; + bool got_dir_allow = False; + bool got_file_allow = False; int i, j; *ppfile_ace = NULL; @@ -1905,7 +1905,7 @@ static void process_deny_list( canon_ace **pp_ace_list ) no user/group/world entries. ****************************************************************************/ -static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) +static mode_t create_default_mode(files_struct *fsp, bool interitable_mode) { int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; @@ -1939,7 +1939,7 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) succeeding. ****************************************************************************/ -static BOOL unpack_canon_ace(files_struct *fsp, +static bool unpack_canon_ace(files_struct *fsp, SMB_STRUCT_STAT *pst, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, @@ -2270,7 +2270,7 @@ static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl Check if the current user group list contains a given group. ****************************************************************************/ -static BOOL current_user_in_group(gid_t gid) +static bool current_user_in_group(gid_t gid) { int i; @@ -2288,7 +2288,7 @@ static BOOL current_user_in_group(gid_t gid) and 'dos filemode' ****************************************************************************/ -static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid) +static bool acl_group_override(connection_struct *conn, gid_t prim_gid) { if ( (errno == EACCES || errno == EPERM) && (lp_acl_group_control(SNUM(conn)) || lp_dos_filemode(SNUM(conn))) @@ -2304,18 +2304,18 @@ static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid) Attempt to apply an ACL to a file or directory. ****************************************************************************/ -static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, gid_t prim_gid, BOOL *pacl_set_support) +static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool default_ace, gid_t prim_gid, bool *pacl_set_support) { connection_struct *conn = fsp->conn; - BOOL ret = False; + bool ret = False; SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1); canon_ace *p_ace; int i; SMB_ACL_ENTRY_T mask_entry; - BOOL got_mask_entry = False; + bool got_mask_entry = False; SMB_ACL_PERMSET_T mask_permset; SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS); - BOOL needs_mask = False; + bool needs_mask = False; mode_t mask_perms = 0; #if defined(POSIX_ACL_NEEDS_MASK) @@ -2586,7 +2586,7 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl) #define MAP_PERM(p,mask,result) (((p) & (mask)) ? (result) : 0 ) -static BOOL convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms) +static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms) { int snum = SNUM(fsp->conn); size_t ace_count = count_canon_ace_list(file_ace_list); @@ -2670,8 +2670,8 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) for (j = i+1; j < num_aces; j++) { uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE); uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE); - BOOL i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; - BOOL j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; + bool i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; + bool j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; /* We know the lower number ACE's are file entries. */ if ((nt_ace_list[i].type == nt_ace_list[j].type) && @@ -3059,9 +3059,9 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) /* Case (2) / (3) */ if (lp_enable_privileges()) { - BOOL has_take_ownership_priv = user_has_privileges(current_user.nt_user_token, + bool has_take_ownership_priv = user_has_privileges(current_user.nt_user_token, &se_take_ownership); - BOOL has_restore_priv = user_has_privileges(current_user.nt_user_token, + bool has_restore_priv = user_has_privileges(current_user.nt_user_token, &se_restore); /* Case (2) */ @@ -3316,7 +3316,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DOM_SID file_grp_sid; canon_ace *file_ace_list = NULL; canon_ace *dir_ace_list = NULL; - BOOL acl_perms = False; + bool acl_perms = False; mode_t orig_mode = (mode_t)0; NTSTATUS status; @@ -3428,8 +3428,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) { - BOOL acl_set_support = False; - BOOL ret = False; + bool acl_set_support = False; + bool ret = False; /* * Try using the POSIX ACL set first. Fall back to chmod if @@ -3732,10 +3732,10 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) Check for an existing default POSIX ACL on a directory. ****************************************************************************/ -BOOL directory_has_default_acl(connection_struct *conn, const char *fname) +bool directory_has_default_acl(connection_struct *conn, const char *fname) { SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); - BOOL has_acl = False; + bool has_acl = False; SMB_ACL_ENTRY_T entry; if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { @@ -3752,7 +3752,7 @@ BOOL directory_has_default_acl(connection_struct *conn, const char *fname) Map from wire type to permset. ****************************************************************************/ -static BOOL unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset) +static bool unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset) { if (wire_perm & ~(SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE)) { return False; @@ -3784,7 +3784,7 @@ static BOOL unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_ Map from wire type to tagtype. ****************************************************************************/ -static BOOL unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt) +static bool unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt) { switch (wire_tt) { case SMB_POSIX_ACL_USER_OBJ: @@ -3907,7 +3907,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_ on the directory. ****************************************************************************/ -BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, +bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint16 num_def_acls, const char *pdata) { SMB_ACL_T def_acl = NULL; @@ -3952,12 +3952,12 @@ BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_ FIXME ! How does the share mask/mode fit into this.... ? ****************************************************************************/ -static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname) +static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname) { SMB_ACL_T file_acl = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; - BOOL ret = False; + bool ret = False; /* Create a new ACL with only 3 entries, u/g/w. */ SMB_ACL_T new_file_acl = SMB_VFS_SYS_ACL_INIT(conn, 3); SMB_ACL_ENTRY_T user_ent = NULL; @@ -4090,7 +4090,7 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER. ****************************************************************************/ -BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata) +bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata) { SMB_ACL_T file_acl = NULL; @@ -4136,8 +4136,8 @@ static int check_posix_acl_group_access(connection_struct *conn, const char *fna int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; int i; - BOOL seen_mask = False; - BOOL seen_owning_group = False; + bool seen_mask = False; + bool seen_owning_group = False; int ret = -1; gid_t cu_gid; @@ -4418,7 +4418,7 @@ static int check_posix_acl_group_access(connection_struct *conn, const char *fna this to successfully return ACCESS_DENIED on a file open for delete access. ****************************************************************************/ -BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) +bool can_delete_file_in_directory(connection_struct *conn, const char *fname) { SMB_STRUCT_STAT sbuf; TALLOC_CTX *ctx = talloc_tos(); @@ -4491,7 +4491,7 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) Note this doesn't take into account share write permissions. ****************************************************************************/ -BOOL can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) +bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) { int ret; @@ -4562,7 +4562,7 @@ BOOL can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT Note this doesn't take into account share write permissions. ****************************************************************************/ -BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7faf26af25..ed1bf762e9 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -41,7 +41,7 @@ extern int last_message; extern int smb_read_error; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; -extern BOOL global_machine_password_needs_changing; +extern bool global_machine_password_needs_changing; extern int max_send; /* @@ -95,7 +95,7 @@ static struct pending_message_list *deferred_open_queue; for processing. ****************************************************************************/ -static BOOL push_queued_message(struct smb_request *req, +static bool push_queued_message(struct smb_request *req, struct timeval request_time, struct timeval end_time, char *private_data, size_t private_len) @@ -191,7 +191,7 @@ void schedule_deferred_open_smb_message(uint16 mid) Return true if this mid is on the deferred queue. ****************************************************************************/ -BOOL open_was_deferred(uint16 mid) +bool open_was_deferred(uint16 mid) { struct pending_message_list *pml; @@ -224,7 +224,7 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) messages ready for processing. ****************************************************************************/ -BOOL push_deferred_smb_message(struct smb_request *req, +bool push_deferred_smb_message(struct smb_request *req, struct timeval request_time, struct timeval timeout, char *private_data, size_t priv_len) @@ -247,7 +247,7 @@ struct idle_event { struct timed_event *te; struct timeval interval; char *name; - BOOL (*handler)(const struct timeval *now, void *private_data); + bool (*handler)(const struct timeval *now, void *private_data); void *private_data; }; @@ -280,7 +280,7 @@ struct idle_event *event_add_idle(struct event_context *event_ctx, TALLOC_CTX *mem_ctx, struct timeval interval, const char *name, - BOOL (*handler)(const struct timeval *now, + bool (*handler)(const struct timeval *now, void *private_data), void *private_data) { @@ -382,7 +382,7 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds) The timeout is in milliseconds ****************************************************************************/ -static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, +static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, size_t *buffer_len, int timeout) { fd_set r_fds, w_fds; @@ -415,7 +415,7 @@ static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, * and it's time to schedule. */ if(deferred_open_queue != NULL) { - BOOL pop_message = False; + bool pop_message = False; struct pending_message_list *msg = deferred_open_queue; if (timeval_is_zero(&msg->end_time)) { @@ -1515,7 +1515,7 @@ void check_reload(time_t t) Process any timeout housekeeping. Return False if the caller should exit. ****************************************************************************/ -static BOOL timeout_processing(int *select_timeout, +static bool timeout_processing(int *select_timeout, time_t *last_timeout_processing_time) { time_t t; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index cb31763a9f..ac6ad9d470 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -45,7 +45,7 @@ * Declare here, define at end: reduces likely "include" interaction problems. * David Lee */ -BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); +bool disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); #endif /* VXFS_QUOTA */ @@ -205,7 +205,7 @@ static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LI Try to get the disk space from disk quotas (LINUX version). ****************************************************************************/ -BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { int r; SMB_STRUCT_STAT S; @@ -306,7 +306,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB try to get the disk space from disk quotas (CRAY VERSION) ****************************************************************************/ -BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { struct mntent *mnt; FILE *fd; @@ -467,7 +467,7 @@ static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) } /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ -static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +static bool nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t uid = euser_id; struct dqblk D; @@ -479,7 +479,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B int len; static struct timeval timeout = {2,0}; enum clnt_stat clnt_stat; - BOOL ret = True; + bool ret = True; *bsize = *dfree = *dsize = (SMB_BIG_UINT)0; @@ -587,7 +587,7 @@ try to get the disk space from disk quotas (SunOS & Solaris2 version) Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). ****************************************************************************/ -BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t euser_id; int ret; @@ -670,7 +670,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #if defined(SUNOS5) if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) { - BOOL retval; + bool retval; DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); unbecome_root(); @@ -702,7 +702,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB set_effective_uid(euser_id); DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { - BOOL retval; + bool retval; retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize); return(retval); } @@ -748,7 +748,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB try to get the disk space from disk quotas - OSF1 version ****************************************************************************/ -BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { int r, save_errno; struct dqblk D; @@ -814,7 +814,7 @@ try to get the disk space from disk quotas (IRIX 6.2 version) #include #include -BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t euser_id; int r; @@ -1007,7 +1007,7 @@ static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) } /* Works on FreeBSD, too. :-) */ -static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +static bool nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t uid = euser_id; struct dqblk D; @@ -1019,7 +1019,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B int len; static struct timeval timeout = {2,0}; enum clnt_stat clnt_stat; - BOOL ret = True; + bool ret = True; *bsize = *dfree = *dsize = (SMB_BIG_UINT)0; @@ -1132,7 +1132,7 @@ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B try to get the disk space from disk quotas - default version ****************************************************************************/ -BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { int r; struct dqblk D; @@ -1199,7 +1199,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #if defined(__FreeBSD__) || defined(__DragonFly__) if (strcmp(mnts[i].f_fstypename,"nfs") == 0) { - BOOL retval; + bool retval; retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize); unbecome_root(); return retval; @@ -1351,7 +1351,7 @@ Hints for porting: #include #include -BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t user_id, euser_id; int ret; @@ -1432,7 +1432,7 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B #else /* WITH_QUOTAS */ -BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { (*bsize) = 512; /* This value should be ignored */ @@ -1450,7 +1450,7 @@ BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BI /* wrapper to the new sys_quota interface this file should be removed later */ -BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { int r; SMB_DISK_QUOTA D; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 7c44216aea..38ce797eeb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -33,7 +33,7 @@ unsigned int smb_echo_count = 0; extern uint32 global_client_caps; extern struct current_user current_user; -extern BOOL global_encrypted_passwords_negotiated; +extern bool global_encrypted_passwords_negotiated; /**************************************************************************** Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext @@ -47,13 +47,13 @@ extern BOOL global_encrypted_passwords_negotiated; #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\')) static NTSTATUS check_path_syntax_internal(char *path, - BOOL posix_path, - BOOL *p_last_component_contains_wcard) + bool posix_path, + bool *p_last_component_contains_wcard) { char *d = path; const char *s = path; NTSTATUS ret = NT_STATUS_OK; - BOOL start_of_name_component = True; + bool start_of_name_component = True; *p_last_component_contains_wcard = False; @@ -177,7 +177,7 @@ static NTSTATUS check_path_syntax_internal(char *path, NTSTATUS check_path_syntax(char *path) { - BOOL ignore; + bool ignore; return check_path_syntax_internal(path, False, &ignore); } @@ -187,7 +187,7 @@ NTSTATUS check_path_syntax(char *path) a wildcard. ****************************************************************************/ -NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard) +NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard) { return check_path_syntax_internal(path, False, p_contains_wcard); } @@ -200,7 +200,7 @@ NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard) NTSTATUS check_path_syntax_posix(char *path) { - BOOL ignore; + bool ignore; return check_path_syntax_internal(path, True, &ignore); } @@ -216,7 +216,7 @@ size_t srvstr_get_path_wcard(TALLOC_CTX *ctx, size_t src_len, int flags, NTSTATUS *err, - BOOL *contains_wcard) + bool *contains_wcard) { size_t ret; @@ -325,7 +325,7 @@ size_t srvstr_get_path(TALLOC_CTX *ctx, Check if we have a correct fsp pointing to a file. Basic check for open fsp. ****************************************************************************/ -BOOL check_fsp_open(connection_struct *conn, struct smb_request *req, +bool check_fsp_open(connection_struct *conn, struct smb_request *req, files_struct *fsp, struct current_user *user) { if (!(fsp) || !(conn)) { @@ -344,7 +344,7 @@ BOOL check_fsp_open(connection_struct *conn, struct smb_request *req, CHECK_FSP macro. ****************************************************************************/ -BOOL check_fsp(connection_struct *conn, struct smb_request *req, +bool check_fsp(connection_struct *conn, struct smb_request *req, files_struct *fsp, struct current_user *user) { if (!check_fsp_open(conn, req, fsp, user)) { @@ -366,7 +366,7 @@ BOOL check_fsp(connection_struct *conn, struct smb_request *req, Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro ****************************************************************************/ -BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req, +bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req, files_struct *fsp, struct current_user *user) { if ((fsp) && (conn) && ((conn)==(fsp)->conn) @@ -396,7 +396,7 @@ void reply_special(char *inbuf) */ char outbuf[smb_size]; - static BOOL already_got_session = False; + static bool already_got_session = False; *name1 = *name2 = 0; @@ -1202,17 +1202,17 @@ void reply_search(connection_struct *conn, struct smb_request *req) uint32 dirtype; unsigned int numentries = 0; unsigned int maxentries = 0; - BOOL finished = False; + bool finished = False; char *p; int status_len; char *path = NULL; char status[21]; int dptr_num= -1; - BOOL check_descend = False; - BOOL expect_close = False; + bool check_descend = False; + bool expect_close = False; NTSTATUS nt_status; - BOOL mask_contains_wcard = False; - BOOL allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; + bool mask_contains_wcard = False; + bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBsearch); @@ -1501,7 +1501,7 @@ void reply_fclose(connection_struct *conn, struct smb_request *req) char *p; char *path = NULL; NTSTATUS err; - BOOL path_contains_wcard = False; + bool path_contains_wcard = False; TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBfclose); @@ -2379,7 +2379,7 @@ static NTSTATUS do_unlink(connection_struct *conn, ****************************************************************************/ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, - uint32 dirtype, const char *name_in, BOOL has_wild) + uint32 dirtype, const char *name_in, bool has_wild) { const char *directory = NULL; char *mask = NULL; @@ -2543,7 +2543,7 @@ void reply_unlink(connection_struct *conn, struct smb_request *req) char *name = NULL; uint32 dirtype; NTSTATUS status; - BOOL path_contains_wcard = False; + bool path_contains_wcard = False; TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBunlink); @@ -3288,7 +3288,7 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) files_struct *fsp; SMB_OFF_T startpos; size_t smb_maxcnt; - BOOL big_readX = False; + bool big_readX = False; #if 0 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6); #endif @@ -3422,7 +3422,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) size_t tcount; SMB_OFF_T startpos; char *data=NULL; - BOOL write_through; + bool write_through; files_struct *fsp; NTSTATUS status; @@ -3849,12 +3849,12 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) files_struct *fsp; SMB_OFF_T startpos; size_t numtowrite; - BOOL write_through; + bool write_through; ssize_t nwritten; unsigned int smb_doff; unsigned int smblen; char *data; - BOOL large_writeX; + bool large_writeX; NTSTATUS status; START_PROFILE(SMBwriteX); @@ -4825,12 +4825,12 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) tree recursively. Return True on ok, False on fail. ****************************************************************************/ -static BOOL recursive_rmdir(TALLOC_CTX *ctx, +static bool recursive_rmdir(TALLOC_CTX *ctx, connection_struct *conn, char *directory) { const char *dname = NULL; - BOOL ret = True; + bool ret = True; long offset = 0; struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); @@ -5079,7 +5079,7 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req) Resolve wildcards in a filename rename. ********************************************************************/ -static BOOL resolve_wildcards(TALLOC_CTX *ctx, +static bool resolve_wildcards(TALLOC_CTX *ctx, const char *name1, const char *name2, char **pp_newname) @@ -5212,7 +5212,7 @@ static void rename_open_files(connection_struct *conn, const char *newname) { files_struct *fsp; - BOOL did_rename = False; + bool did_rename = False; for(fsp = file_find_di_first(lck->id); fsp; fsp = file_find_di_next(fsp)) { @@ -5251,7 +5251,7 @@ static void rename_open_files(connection_struct *conn, report from . ****************************************************************************/ -static BOOL rename_path_prefix_equal(const char *src, const char *dest) +static bool rename_path_prefix_equal(const char *src, const char *dest) { const char *psrc = src; const char *pdst = dest; @@ -5273,7 +5273,7 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest) * Do the notify calls from a rename */ -static void notify_rename(connection_struct *conn, BOOL is_dir, +static void notify_rename(connection_struct *conn, bool is_dir, const char *oldpath, const char *newpath) { char *olddir, *newdir; @@ -5320,13 +5320,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, char *newname, const char *newname_last_component, uint32 attrs, - BOOL replace_if_exists) + bool replace_if_exists) { TALLOC_CTX *ctx = talloc_tos(); SMB_STRUCT_STAT sbuf, sbuf1; NTSTATUS status = NT_STATUS_OK; struct share_mode_lock *lck = NULL; - BOOL dst_exists; + bool dst_exists; ZERO_STRUCT(sbuf); @@ -5508,9 +5508,9 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, const char *name_in, const char *newname_in, uint32 attrs, - BOOL replace_if_exists, - BOOL src_has_wild, - BOOL dest_has_wild) + bool replace_if_exists, + bool src_has_wild, + bool dest_has_wild) { char *directory = NULL; char *mask = NULL; @@ -5593,7 +5593,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, /* * No wildcards - just process the one file. */ - BOOL is_short_name = mangle_is_8_3(name, True, conn->params); + bool is_short_name = mangle_is_8_3(name, True, conn->params); /* Add a terminating '/' to the directory name. */ directory = talloc_asprintf_append(directory, @@ -5696,7 +5696,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, files_struct *fsp = NULL; char *fname = NULL; char *destname = NULL; - BOOL sysdir_entry = False; + bool sysdir_entry = False; /* Quick check for "." and ".." */ if (ISDOT(dname) || ISDOTDOT(dname)) { @@ -5801,8 +5801,8 @@ void reply_mv(connection_struct *conn, struct smb_request *req) char *p; uint32 attrs; NTSTATUS status; - BOOL src_has_wcard = False; - BOOL dest_has_wcard = False; + bool src_has_wcard = False; + bool dest_has_wcard = False; TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBmv); @@ -5903,7 +5903,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, const char *dest1, int ofun, int count, - BOOL target_is_directory) + bool target_is_directory) { SMB_STRUCT_STAT src_sbuf, sbuf2; SMB_OFF_T ret=-1; @@ -6038,9 +6038,9 @@ void reply_copy(connection_struct *conn, struct smb_request *req) int tid2; int ofun; int flags; - BOOL target_is_directory=False; - BOOL source_has_wild = False; - BOOL dest_has_wild = False; + bool target_is_directory=False; + bool source_has_wild = False; + bool dest_has_wild = False; SMB_STRUCT_STAT sbuf1, sbuf2; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); @@ -6355,7 +6355,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req) Get a lock pid, dealing with large count requests. ****************************************************************************/ -uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format) +uint32 get_lock_pid( char *data, int data_offset, bool large_file_format) { if(!large_file_format) return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset)); @@ -6367,7 +6367,7 @@ uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format) Get a lock count, dealing with large count requests. ****************************************************************************/ -SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format) +SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format) { SMB_BIG_UINT count = 0; @@ -6439,7 +6439,7 @@ static uint32 map_lock_offset(uint32 high, uint32 low) Get a lock offset, dealing with large offset requests. ****************************************************************************/ -SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err) +SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err) { SMB_BIG_UINT offset = 0; @@ -6500,8 +6500,8 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) int32 lock_timeout; int i; char *data; - BOOL large_file_format; - BOOL err; + bool large_file_format; + bool err; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; START_PROFILE(SMBlockingX); @@ -6541,8 +6541,8 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) */ if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { /* Client can insist on breaking to none. */ - BOOL break_to_none = (oplocklevel == 0); - BOOL result; + bool break_to_none = (oplocklevel == 0); + bool result; DEBUG(5,("reply_lockingX: oplock break reply (%u) from client " "for fnum = %d\n", (unsigned int)oplocklevel, @@ -6720,8 +6720,8 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) offset, WINDOWS_LOCK); } else { - BOOL blocking_lock = lock_timeout ? True : False; - BOOL defer_lock = False; + bool blocking_lock = lock_timeout ? True : False; + bool defer_lock = False; struct byte_range_lock *br_lck; uint32 block_smbpid; diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 08d522cdd7..6edcc36764 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -36,7 +36,7 @@ static int sec_ctx_stack_ndx; Become the specified uid. ****************************************************************************/ -static BOOL become_uid(uid_t uid) +static bool become_uid(uid_t uid) { /* Check for dodgy uid values */ @@ -63,7 +63,7 @@ static BOOL become_uid(uid_t uid) Become the specified gid. ****************************************************************************/ -static BOOL become_gid(gid_t gid) +static bool become_gid(gid_t gid) { /* Check for dodgy gid values */ @@ -88,7 +88,7 @@ static BOOL become_gid(gid_t gid) Become the specified uid and gid. ****************************************************************************/ -static BOOL become_id(uid_t uid, gid_t gid) +static bool become_id(uid_t uid, gid_t gid) { return become_gid(gid) && become_uid(uid); } @@ -183,7 +183,7 @@ fail: one. User changes are done using the set_sec_ctx() function. ****************************************************************************/ -BOOL push_sec_ctx(void) +bool push_sec_ctx(void) { struct sec_ctx *ctx_p; @@ -367,7 +367,7 @@ void set_root_sec_ctx(void) Pop a security context from the stack. ****************************************************************************/ -BOOL pop_sec_ctx(void) +bool pop_sec_ctx(void) { struct sec_ctx *ctx_p; struct sec_ctx *prev_ctx_p; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8c92c91577..05bb3504c7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -169,7 +169,7 @@ static void msg_sam_sync(struct messaging_context *msg, Open the socket communication - inetd. ****************************************************************************/ -static BOOL open_sockets_inetd(void) +static bool open_sockets_inetd(void) { /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system @@ -282,7 +282,7 @@ static void remove_child_pid(pid_t pid) Have we reached the process limit ? ****************************************************************************/ -static BOOL allowable_number_of_smbd_processes(void) +static bool allowable_number_of_smbd_processes(void) { int max_processes = lp_max_smbd_processes(); @@ -296,7 +296,7 @@ static BOOL allowable_number_of_smbd_processes(void) Open the socket communication. ****************************************************************************/ -static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) +static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ports) { int num_interfaces = iface_count(); int num_sockets = 0; @@ -681,9 +681,9 @@ void reload_printers(void) Reload the services file. **************************************************************************/ -BOOL reload_services(BOOL test) +bool reload_services(bool test) { - BOOL ret; + bool ret; if (lp_loaded()) { pstring fname; @@ -816,7 +816,7 @@ void exit_server_fault(void) Initialise connect, service and file structs. ****************************************************************************/ -static BOOL init_structs(void ) +static bool init_structs(void ) { /* * Set the machine NETBIOS name if not already @@ -843,7 +843,7 @@ static BOOL init_structs(void ) /* * Send keepalive packets to our client */ -static BOOL keepalive_fn(const struct timeval *now, void *private_data) +static bool keepalive_fn(const struct timeval *now, void *private_data) { if (!send_keepalive(smbd_server_fd())) { DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); @@ -855,7 +855,7 @@ static BOOL keepalive_fn(const struct timeval *now, void *private_data) /* * Do the recurring check if we're idle */ -static BOOL deadtime_fn(const struct timeval *now, void *private_data) +static bool deadtime_fn(const struct timeval *now, void *private_data) { if ((conn_num_open() == 0) || (conn_idle_all(now->tv_sec))) { @@ -877,21 +877,21 @@ static BOOL deadtime_fn(const struct timeval *now, void *private_data) mkproto.h. Mixing $(builddir) and $(srcdir) source files in the current prototype generation system is too complicated. */ -extern void build_options(BOOL screen); +extern void build_options(bool screen); int main(int argc,const char *argv[]) { /* shall I run as a daemon */ - static BOOL is_daemon = False; - static BOOL interactive = False; - static BOOL Fork = True; - static BOOL no_process_group = False; - static BOOL log_stdout = False; + static bool is_daemon = False; + static bool interactive = False; + static bool Fork = True; + static bool no_process_group = False; + static bool log_stdout = False; static char *ports = NULL; static char *profile_level = NULL; int opt; poptContext pc; - BOOL print_build_options = False; + bool print_build_options = False; struct poptOption long_options[] = { POPT_AUTOHELP diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1c46e3776c..bb279b701f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -21,7 +21,7 @@ extern userdom_struct current_user_info; -static BOOL canonicalize_path(connection_struct *conn, pstring path) +static bool canonicalize_path(connection_struct *conn, pstring path) { #ifdef REALPATH_TAKES_NULL char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL); @@ -57,7 +57,7 @@ void set_conn_connectpath(connection_struct *conn, const char *connectpath) pstring destname; char *d = destname; const char *s = connectpath; - BOOL start_of_name_component = True; + bool start_of_name_component = True; *d++ = '/'; /* Always start with root. */ @@ -161,7 +161,7 @@ void set_conn_connectpath(connection_struct *conn, const char *connectpath) Load parameters specific to a connection/service. ****************************************************************************/ -BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir) +bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir) { static connection_struct *last_conn; static uint16 last_flags; @@ -503,7 +503,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } -static NTSTATUS find_forced_user(connection_struct *conn, BOOL vuser_is_guest, fstring username) +static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username) { int snum = conn->params->service; char *fuser, *found_username; @@ -535,7 +535,7 @@ static NTSTATUS find_forced_user(connection_struct *conn, BOOL vuser_is_guest, f * one found. */ -static NTSTATUS find_forced_group(BOOL force_user, +static NTSTATUS find_forced_group(bool force_user, int snum, const char *username, DOM_SID *pgroup_sid, gid_t *pgid) @@ -545,7 +545,7 @@ static NTSTATUS find_forced_group(BOOL force_user, DOM_SID group_sid; enum lsa_SidType type; char *groupname; - BOOL user_must_be_member = False; + bool user_must_be_member = False; gid_t gid; ZERO_STRUCTP(pgroup_sid); @@ -636,7 +636,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, NTSTATUS *status) { struct passwd *pass = NULL; - BOOL guest = False; + bool guest = False; connection_struct *conn; SMB_STRUCT_STAT st; fstring user; @@ -773,7 +773,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * insensitive for now. */ conn->case_sensitive = False; } else { - conn->case_sensitive = (BOOL)lp_casesensitive(snum); + conn->case_sensitive = (bool)lp_casesensitive(snum); } conn->case_preserve = lp_preservecase(snum); @@ -908,7 +908,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ { - BOOL can_write = False; + bool can_write = False; NT_USER_TOKEN *token = conn->nt_user_token ? conn->nt_user_token : (vuser ? vuser->nt_user_token : NULL); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 54d2ddf721..ebbb40eb5a 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -44,7 +44,7 @@ static struct db_context *session_db_ctx(void) return ctx; } -BOOL session_init(void) +bool session_init(void) { if (session_db_ctx() == NULL) { DEBUG(1,("session_init: failed to open sessionid tdb\n")); @@ -58,7 +58,7 @@ BOOL session_init(void) called when a session is created ********************************************************************/ -BOOL session_claim(user_struct *vuser) +bool session_claim(user_struct *vuser) { TDB_DATA key, data; int i = 0; @@ -254,7 +254,7 @@ void session_yield(user_struct *vuser) /******************************************************************** ********************************************************************/ -static BOOL session_traverse(int (*fn)(struct db_record *db, +static bool session_traverse(int (*fn)(struct db_record *db, void *private_data), void *private_data) { diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a2f24c66d2..bc298d11f7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -25,8 +25,8 @@ #include "includes.h" extern struct auth_context *negprot_global_auth_context; -extern BOOL global_encrypted_passwords_negotiated; -extern BOOL global_spnego_negotiated; +extern bool global_encrypted_passwords_negotiated; +extern bool global_spnego_negotiated; extern enum protocol_types Protocol; extern int max_send; @@ -186,14 +186,14 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) Cerate a clock skew error blob for a Windows client. ****************************************************************************/ -static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out) +static bool make_krb5_skew_error(DATA_BLOB *pblob_out) { krb5_context context = NULL; krb5_error_code kerr = 0; krb5_data reply; krb5_principal host_princ = NULL; char *host_princ_s = NULL; - BOOL ret = False; + bool ret = False; *pblob_out = data_blob_null; @@ -251,7 +251,7 @@ static void reply_spnego_kerberos(connection_struct *conn, struct smb_request *req, DATA_BLOB *secblob, uint16 vuid, - BOOL *p_invalidate_vuid) + bool *p_invalidate_vuid) { TALLOC_CTX *mem_ctx; DATA_BLOB ticket; @@ -268,8 +268,8 @@ static void reply_spnego_kerberos(connection_struct *conn, uint8 tok_id[2]; DATA_BLOB nullblob = data_blob_null; fstring real_username; - BOOL map_domainuser_to_guest = False; - BOOL username_was_mapped; + bool map_domainuser_to_guest = False; + bool username_was_mapped; PAC_LOGON_INFO *logon_info = NULL; ZERO_STRUCT(ticket); @@ -316,7 +316,7 @@ static void reply_spnego_kerberos(connection_struct *conn, * -- Looks like this only happens with a KDC. JRA. */ - BOOL ok = make_krb5_skew_error(&ap_rep); + bool ok = make_krb5_skew_error(&ap_rep); if (!ok) { talloc_destroy(mem_ctx); return ERROR_NT(nt_status_squash( @@ -628,7 +628,7 @@ static void reply_spnego_ntlmssp(connection_struct *conn, uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, - BOOL wrap) + bool wrap) { DATA_BLOB response; struct auth_serversupplied_info *server_info = NULL; @@ -716,7 +716,7 @@ static void reply_spnego_ntlmssp(connection_struct *conn, ****************************************************************************/ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, - BOOL *p_is_krb5) + bool *p_is_krb5) { char *OIDs[ASN1_MAX_OIDS]; int i; @@ -764,7 +764,7 @@ static void reply_spnego_negotiate(connection_struct *conn, { DATA_BLOB secblob; DATA_BLOB chal; - BOOL got_kerberos_mechanism = False; + bool got_kerberos_mechanism = False; NTSTATUS status; status = parse_spnego_mechanisms(blob1, &secblob, @@ -782,7 +782,7 @@ static void reply_spnego_negotiate(connection_struct *conn, #ifdef HAVE_KRB5 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { - BOOL destroy_vuid = True; + bool destroy_vuid = True; reply_spnego_kerberos(conn, req, &secblob, vuid, &destroy_vuid); data_blob_free(&secblob); @@ -850,7 +850,7 @@ static void reply_spnego_auth(connection_struct *conn, if (auth.data[0] == ASN1_APPLICATION(0)) { /* Might be a second negTokenTarg packet */ - BOOL got_krb5_mechanism = False; + bool got_krb5_mechanism = False; status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism); if (NT_STATUS_IS_OK(status)) { @@ -859,7 +859,7 @@ static void reply_spnego_auth(connection_struct *conn, #ifdef HAVE_KRB5 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { - BOOL destroy_vuid = True; + bool destroy_vuid = True; reply_spnego_kerberos(conn, req, &secblob, vuid, &destroy_vuid); data_blob_free(&secblob); @@ -1336,14 +1336,14 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) fstring native_os; fstring native_lanman; fstring primary_domain; - static BOOL done_sesssetup = False; + static bool done_sesssetup = False; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; uint16 smb_flag2 = req->flags2; NTSTATUS nt_status; - BOOL doencrypt = global_encrypted_passwords_negotiated; + bool doencrypt = global_encrypted_passwords_negotiated; DATA_BLOB session_key; @@ -1489,7 +1489,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) nt_resp = data_blob(p+passlen1, passlen2); } else { pstring pass; - BOOL unic= smb_flag2 & FLAGS2_UNICODE_STRINGS; + bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS; #if 0 /* This was the previous fix. Not sure if it's still diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index a5e0988b0f..512126254a 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -29,7 +29,7 @@ extern userdom_struct current_user_info; -static BOOL do_group_checks(const char **name, const char **pattern) +static bool do_group_checks(const char **name, const char **pattern) { if ((*name)[0] == '@') { *pattern = "&+"; @@ -64,7 +64,7 @@ static BOOL do_group_checks(const char **name, const char **pattern) return False; } -static BOOL token_contains_name(TALLOC_CTX *mem_ctx, +static bool token_contains_name(TALLOC_CTX *mem_ctx, const char *username, const char *sharename, const struct nt_user_token *token, @@ -151,7 +151,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, * The other use is the netgroup check when using @group or &group. */ -BOOL token_contains_name_in_list(const char *username, +bool token_contains_name_in_list(const char *username, const char *sharename, const struct nt_user_token *token, const char **list) @@ -191,7 +191,7 @@ BOOL token_contains_name_in_list(const char *username, * The other use is the netgroup check when using @group or &group. */ -BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum) +bool user_ok_token(const char *username, struct nt_user_token *token, int snum) { if (lp_invalid_users(snum) != NULL) { if (token_contains_name_in_list(username, lp_servicename(snum), @@ -247,10 +247,10 @@ BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum) * The other use is the netgroup check when using @group or &group. */ -BOOL is_share_read_only_for_token(const char *username, +bool is_share_read_only_for_token(const char *username, struct nt_user_token *token, int snum) { - BOOL result = lp_readonly(snum); + bool result = lp_readonly(snum); if (lp_readlist(snum) != NULL) { if (token_contains_name_in_list(username, diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index a066091b52..8f1e008985 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -42,7 +42,7 @@ static TDB_CONTEXT *tdb_stat_cache; void stat_cache_add( const char *full_orig_name, char *translated_path, - BOOL case_sensitive) + bool case_sensitive) { size_t translated_path_length; TDB_DATA data_val; @@ -174,7 +174,7 @@ void stat_cache_add( const char *full_orig_name, * */ -BOOL stat_cache_lookup(connection_struct *conn, +bool stat_cache_lookup(connection_struct *conn, char **pp_name, char **pp_dirpath, char **pp_start, @@ -182,7 +182,7 @@ BOOL stat_cache_lookup(connection_struct *conn, { char *chk_name; size_t namelen; - BOOL sizechanged = False; + bool sizechanged = False; unsigned int num_components = 0; char *translated_path; size_t translated_path_length; @@ -390,7 +390,7 @@ unsigned int fast_string_hash(TDB_DATA *key) Initializes or clears the stat cache. **************************************************************************/ -BOOL reset_stat_cache( void ) +bool reset_stat_cache( void ) { if (!lp_stat_cache()) return True; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ce038e719a..7f38d5caa8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -94,7 +94,7 @@ SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, con Refuse to allow clients to overwrite our private xattrs. ****************************************************************************/ -static BOOL samba_private_attr_name(const char *unix_ea_name) +static bool samba_private_attr_name(const char *unix_ea_name) { static const char *prohibited_ea_names[] = { SAMBA_POSIX_INHERITANCE_EA_NAME, @@ -115,7 +115,7 @@ static BOOL samba_private_attr_name(const char *unix_ea_name) Get one EA value. Fill in a struct ea_struct. ****************************************************************************/ -static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, +static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, char *ea_name, struct ea_struct *pea) { /* Get the value of this xattr. Max size is 64k. */ @@ -597,7 +597,7 @@ void send_trans2_replies(struct smb_request *req, int params_sent_thistime, data_sent_thistime, total_sent_thistime; int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */ int data_alignment_offset = 0; - BOOL overflow = False; + bool overflow = False; /* Modify the data_to_send and datasize and set the error if we're trying to send more than max_data_bytes. We still send @@ -774,9 +774,9 @@ static void call_trans2open(connection_struct *conn, char *pdata = *ppdata; int deny_mode; int32 open_attr; - BOOL oplock_request; + bool oplock_request; #if 0 - BOOL return_additional_info; + bool return_additional_info; int16 open_sattr; time_t open_time; #endif @@ -1008,7 +1008,7 @@ static void call_trans2open(connection_struct *conn, Case can be significant or not. **********************************************************/ -static BOOL exact_match(connection_struct *conn, +static bool exact_match(connection_struct *conn, const char *str, const char *mask) { @@ -1136,25 +1136,25 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn, Get a level dependent lanman2 dir entry. ****************************************************************************/ -static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx, +static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, connection_struct *conn, uint16 flags2, const char *path_mask, uint32 dirtype, int info_level, int requires_resume_key, - BOOL dont_descend, + bool dont_descend, char **ppdata, char *base_data, char *end_data, int space_remaining, - BOOL *out_of_space, - BOOL *got_exact_match, + bool *out_of_space, + bool *got_exact_match, int *last_entry_off, struct ea_list *name_list) { const char *dname; - BOOL found = False; + bool found = False; SMB_STRUCT_STAT sbuf; const char *mask = NULL; char *pathreal = NULL; @@ -1170,10 +1170,10 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx, time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0; char *nameptr; char *last_entry_ptr; - BOOL was_8_3; + bool was_8_3; uint32 nt_extmode; /* Used for NT connections instead of mode */ - BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - BOOL check_mangled_names = lp_manglednames(conn->params); + bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); + bool check_mangled_names = lp_manglednames(conn->params); char mangled_name[13]; /* mangled 8.3 name. */ *out_of_space = False; @@ -1199,8 +1199,8 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx, } while (!found) { - BOOL got_match; - BOOL ms_dfs_link = False; + bool got_match; + bool ms_dfs_link = False; /* Needed if we run out of space */ long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr); @@ -1262,7 +1262,7 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx, } if (got_match) { - BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname)); + bool isdots = (ISDOT(dname) || ISDOTDOT(dname)); if (dont_descend && !isdots) { continue; @@ -1782,9 +1782,9 @@ static void call_trans2findfirst(connection_struct *conn, uint32 dirtype; int maxentries; uint16 findfirst_flags; - BOOL close_after_first; - BOOL close_if_end; - BOOL requires_resume_key; + bool close_after_first; + bool close_if_end; + bool requires_resume_key; int info_level; char *directory = NULL; const char *mask = NULL; @@ -1793,11 +1793,11 @@ static void call_trans2findfirst(connection_struct *conn, int dptr_num = -1; int numentries = 0; int i; - BOOL finished = False; - BOOL dont_descend = False; - BOOL out_of_space = False; + bool finished = False; + bool dont_descend = False; + bool out_of_space = False; int space_remaining; - BOOL mask_contains_wcard = False; + bool mask_contains_wcard = False; SMB_STRUCT_STAT sbuf; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; @@ -1984,7 +1984,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd out_of_space = False; for (i=0;(ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { @@ -146,14 +146,14 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) stack, but modify the current_user entries. ****************************************************************************/ -BOOL change_to_user(connection_struct *conn, uint16 vuid) +bool change_to_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; gid_t gid; uid_t uid; char group_c; - BOOL must_free_token = False; + bool must_free_token = False; NT_USER_TOKEN *token = NULL; int num_groups = 0; gid_t *group_list = NULL; @@ -279,7 +279,7 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) but modify the current_user entries. ****************************************************************************/ -BOOL change_to_root_user(void) +bool change_to_root_user(void) { set_root_sec_ctx(); @@ -298,7 +298,7 @@ BOOL change_to_root_user(void) user. Doesn't modify current_user. ****************************************************************************/ -BOOL become_authenticated_pipe_user(pipes_struct *p) +bool become_authenticated_pipe_user(pipes_struct *p) { if (!push_sec_ctx()) return False; @@ -317,7 +317,7 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) current_user. ****************************************************************************/ -BOOL unbecome_authenticated_pipe_user(void) +bool unbecome_authenticated_pipe_user(void) { return pop_sec_ctx(); } @@ -405,7 +405,7 @@ void unbecome_root(void) Saves and restores the connection context. ****************************************************************************/ -BOOL become_user(connection_struct *conn, uint16 vuid) +bool become_user(connection_struct *conn, uint16 vuid) { if (!push_sec_ctx()) return False; @@ -421,7 +421,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) return True; } -BOOL unbecome_user(void) +bool unbecome_user(void) { pop_sec_ctx(); pop_conn_ctx(); diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 52174c4d83..e36e2aa042 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -249,7 +249,7 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau Update utmp file directly. No subroutine interface: probably a BSD system. ****************************************************************************/ -static void pututline_my(pstring uname, struct utmp *u, BOOL claim) +static void pututline_my(pstring uname, struct utmp *u, bool claim) { DEBUG(1,("pututline_my: not yet implemented\n")); /* BSD implementor: may want to consider (or not) adjusting "lastlog" */ @@ -263,7 +263,7 @@ static void pututline_my(pstring uname, struct utmp *u, BOOL claim) Credit: Michail Vidiassov ****************************************************************************/ -static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) +static void updwtmp_my(pstring wname, struct utmp *u, bool claim) { int fd; struct stat buf; @@ -306,7 +306,7 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) Update via utmp/wtmp (not utmpx/wtmpx). ****************************************************************************/ -static void utmp_nox_update(struct utmp *u, BOOL claim) +static void utmp_nox_update(struct utmp *u, bool claim) { pstring uname, wname; #if defined(PUTUTLINE_RETURNS_UTMP) @@ -384,7 +384,7 @@ static void utmp_strcpy(char *dest, const char *src, size_t n) Update via utmpx/wtmpx (preferred) or via utmp/wtmp. ****************************************************************************/ -static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) +static void sys_utmp_update(struct utmp *u, const char *hostname, bool claim) { #if !defined(HAVE_UTMPX_H) /* No utmpx stuff. Drop to non-x stuff */ @@ -472,7 +472,7 @@ static int ut_id_encode(int i, char *fourbyte) /* fill a system utmp structure given all the info we can gather */ -static BOOL sys_utmp_fill(struct utmp *u, +static bool sys_utmp_fill(struct utmp *u, const char *username, const char *hostname, const char *ip_addr_str, const char *id_str, int id_num) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index d9c772d6b1..b43f37e716 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -106,7 +106,7 @@ static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which, ((void **)(void *)&vfs->ops)[which] = op; } -BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) +bool vfs_init_custom(connection_struct *conn, const char *vfs_object) { vfs_op_tuple *ops; char *module_name = NULL; @@ -256,7 +256,7 @@ void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) Generic VFS init. ******************************************************************/ -BOOL smbd_vfs_init(connection_struct *conn) +bool smbd_vfs_init(connection_struct *conn) { const char **vfs_objects; unsigned int i = 0; @@ -287,10 +287,10 @@ BOOL smbd_vfs_init(connection_struct *conn) Check if directory exists. ********************************************************************/ -BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st) +bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st) { SMB_STRUCT_STAT st2; - BOOL ret; + bool ret; if (!st) st = &st2; @@ -309,7 +309,7 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ Check if an object exists in the vfs. ********************************************************************/ -BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf) +bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_STAT st; @@ -327,7 +327,7 @@ BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT Check if a file exists in the vfs. ********************************************************************/ -BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf) +bool vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_STAT st; @@ -682,10 +682,10 @@ static 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 *path; /* The pathname. */ - BOOL valid; + bool valid; } ino_list[MAX_GETWDCACHE]; -extern BOOL use_getwd_cache; +extern bool use_getwd_cache; /**************************************************************************** Prompte a ptr (to make it recently used) @@ -723,7 +723,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) #else pstring s; #endif - static BOOL getwd_cache_init = False; + static bool getwd_cache_init = False; SMB_STRUCT_STAT st, st2; int i; char *ret = NULL; @@ -835,14 +835,14 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) { #ifdef REALPATH_TAKES_NULL - BOOL free_resolved_name = True; + bool free_resolved_name = True; #else #ifdef PATH_MAX char resolved_name_buf[PATH_MAX+1]; #else pstring resolved_name_buf; #endif - BOOL free_resolved_name = False; + bool free_resolved_name = False; #endif char *resolved_name = NULL; size_t con_path_len = strlen(conn->connectpath); -- cgit From 7f82fbad50906866bbb6c0950795644f1c18b099 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 19 Oct 2007 10:34:06 +0200 Subject: fix startup of smbd, nmbd, winbindd jra: POPT_ARG_VAL arguments need int values. I assume there're more places like this in the cmdline tools. Please fix this properly, as my commit is just a hack to get make test working again. in samba4 we have a workaround for this see smbd/server.c metze (This used to be commit 9cb1937fe8601e526b5c924930500e0a3b52abd5) --- source3/smbd/server.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 05bb3504c7..1ae2c71ddd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -882,11 +882,11 @@ extern void build_options(bool screen); int main(int argc,const char *argv[]) { /* shall I run as a daemon */ - static bool is_daemon = False; - static bool interactive = False; - static bool Fork = True; - static bool no_process_group = False; - static bool log_stdout = False; + static int is_daemon = False; + static int interactive = False; + static int Fork = True; + static int no_process_group = False; + static int log_stdout = False; static char *ports = NULL; static char *profile_level = NULL; int opt; -- cgit From 9a85533914119fb995fb61555c9f6e0018d4d181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2007 11:38:36 -0700 Subject: Fix the popt / bool issues. Some places we used BOOL where we meant int. Fix this. Thanks to metze for pointing this out. Jeremy. (This used to be commit 793a9d24a163cb6cf5a3a0aa5ae30e9f8cf4744a) --- source3/smbd/server.c | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1ae2c71ddd..e52c2b3fba 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -882,24 +882,30 @@ extern void build_options(bool screen); int main(int argc,const char *argv[]) { /* shall I run as a daemon */ - static int is_daemon = False; - static int interactive = False; - static int Fork = True; - static int no_process_group = False; - static int log_stdout = False; + static bool is_daemon = False; + static bool interactive = False; + static bool Fork = True; + static bool no_process_group = False; + static bool log_stdout = False; static char *ports = NULL; static char *profile_level = NULL; int opt; poptContext pc; bool print_build_options = False; - + enum { + OPT_DAEMON = 1000, + OPT_INTERACTIVE, + OPT_FORK, + OPT_NO_PROCESS_GROUP, + OPT_LOG_STDOUT + }; struct poptOption long_options[] = { POPT_AUTOHELP - {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, - {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, - {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" }, - {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, - {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, + {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" }, + {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)"}, + {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools, etc.)" }, + {"no-process-group", '\0', POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" }, + {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"}, @@ -919,6 +925,21 @@ extern void build_options(bool screen); pc = poptGetContext("smbd", argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { + case OPT_DAEMON: + is_daemon = true; + break; + case OPT_INTERACTIVE: + interactive = true; + break; + case OPT_FORK: + Fork = false; + break; + case OPT_NO_PROCESS_GROUP: + no_process_group = true; + break; + case OPT_LOG_STDOUT: + log_stdout = true; + break; case 'b': print_build_options = True; break; -- cgit From 80b7bcb5fbc98964014b5c8082a626aef24c5feb Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Fri, 19 Oct 2007 08:14:12 -0500 Subject: Add test for "struct in6_addr" to the HAVE_IPV6 configure test. Also make use of "if defined(HAVE_IPV6)" rather than testing for AF_INET6 since this is not sufficient on HP-UX 11.11 to ensure a working IPv6 implementation. (This used to be commit 620785df4e57b72471ff0315e22e0d2f28a2b1a5) --- source3/smbd/utmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index e36e2aa042..c2908e33cc 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -525,7 +525,7 @@ static bool sys_utmp_fill(struct utmp *u, #if defined(HAVE_UT_UT_HOST) utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host)); #endif -#if defined(AF_INET6) && defined(HAVE_UT_UT_ADDR_V6) +#if defined(HAVE_IPV6) && defined(HAVE_UT_UT_ADDR_V6) memset(&u->ut_addr_v6, '\0', sizeof(u->ut_addr_v6)); if (ip_addr_str) { struct in6_addr addr; -- cgit From f88b7a076be74a29a3bf876b4e2705f4a1ecf42b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Oct 2007 14:16:54 -0700 Subject: This is a large patch (sorry). Migrate from struct in_addr to struct sockaddr_storage in most places that matter (ie. not the nmbd and NetBIOS lookups). This passes make test on an IPv4 box, but I'll have to do more work/testing on IPv6 enabled boxes. This should now give us a framework for testing and finishing the IPv6 migration. It's at the state where someone with a working IPv6 setup should (theorecically) be able to type : smbclient //ipv6-address/share and have it work. Jeremy. (This used to be commit 98e154c3125d5732c37a72d74b0eb5cd7b6155fd) --- source3/smbd/change_trust_pw.c | 6 +- source3/smbd/server.c | 169 ++++++++++++++++++++++++----------------- 2 files changed, 101 insertions(+), 74 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index eb26e56ac5..8ed0975781 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -30,7 +30,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct in_addr pdc_ip; + struct sockaddr_storage pdc_ss; fstring dc_name; struct cli_state *cli = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; @@ -41,12 +41,12 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m if (remote_machine == NULL || !strcmp(remote_machine, "*")) { /* Use the PDC *only* for this */ - if ( !get_pdc_ip(domain, &pdc_ip) ) { + if ( !get_pdc_ip(domain, &pdc_ss) ) { DEBUG(0,("Can't get IP for PDC for domain %s\n", domain)); goto failed; } - if ( !name_status_find( domain, 0x1b, 0x20, pdc_ip, dc_name) ) + if ( !name_status_find( domain, 0x1b, 0x20, &pdc_ss, dc_name) ) goto failed; } else { /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e52c2b3fba..61e20ce274 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -311,7 +311,6 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ return open_sockets_inetd(); } - #ifdef HAVE_ATEXIT { static int atexit_set; @@ -324,7 +323,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* Stop zombies */ CatchSignal(SIGCLD, sig_cld); - + FD_ZERO(&listen_set); /* use a reasonable default set of ports - listing on 445 and 139 */ @@ -340,50 +339,50 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ } if (lp_interfaces() && lp_bind_interfaces_only()) { - /* We have been given an interfaces line, and been + /* We have been given an interfaces line, and been told to only bind to those interfaces. Create a socket per interface and bind to only these. */ - + /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { const struct sockaddr_storage *ifss = iface_n_sockaddr_storage(i); - const struct in_addr *ifip; fstring tok; const char *ptr; if (ifss == NULL) { - DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); + DEBUG(0,("open_sockets_smbd: " + "interface %d has NULL IP address !\n", + i)); continue; } - /* For now only deal with IPv4. */ - if (ifss->ss_family != AF_INET) { - continue; - } - - ifip = &((const struct sockaddr_in *)ifss)->sin_addr; - - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + for (ptr=ports; next_token(&ptr, tok, " \t,", + sizeof(tok)); ) { unsigned port = atoi(tok); if (port == 0 || port > 0xffff) { continue; } - s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); - if(s == -1) - return False; + s = fd_listenset[num_sockets] = + open_socket_in(SOCK_STREAM, port, 0, + ifss, True); + if(s == -1) { + return false; + } /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,"SO_KEEPALIVE"); set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - + + /* Set server socket to + * non-blocking for the accept. */ + set_blocking(s,False); + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("listen: %s\n",strerror(errno))); + DEBUG(0,("open_sockets_smbd: listen: " + "%s\n", strerror(errno))); close(s); return False; } @@ -392,7 +391,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ num_sockets++; if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + DEBUG(0,("open_sockets_smbd: Too " + "many sockets to bind to\n")); return False; } } @@ -403,44 +403,71 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ fstring tok; const char *ptr; + const char *sock_addr = lp_socket_address(); + fstring sock_tok; + const char *sock_ptr; + + if (strequal(sock_addr, "0.0.0.0") || + strequal(sock_addr, "::")) { +#if HAVE_IPV6 + sock_addr = "::,0.0.0.0"; +#else + sock_addr = "0.0.0.0"; +#endif + } - num_interfaces = 1; - - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0 || port > 0xffff) continue; - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()),True); - if (s == -1) - return(False); - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("open_sockets_smbd: listen: %s\n", - strerror(errno))); - close(s); - return False; - } + for (sock_ptr=sock_addr; next_token(&sock_ptr, sock_tok, " \t,", + sizeof(sock_tok)); ) { + for (ptr=ports; next_token(&ptr, tok, " \t,", + sizeof(tok)); ) { + struct sockaddr_storage ss; + + unsigned port = atoi(tok); + if (port == 0 || port > 0xffff) { + continue; + } + /* open an incoming socket */ + if (!interpret_string_addr(&ss, sock_tok, + AI_NUMERICHOST|AI_PASSIVE)) { + return false; + } - fd_listenset[num_sockets] = s; - FD_SET(s,&listen_set); - maxfd = MAX( maxfd, s); + s = open_socket_in(SOCK_STREAM, port, 0, + &ss, true); + if (s == -1) { + return false; + } + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); - num_sockets++; + /* Set server socket to non-blocking + * for the accept. */ + set_blocking(s,False); - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); - return False; + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("open_sockets_smbd: " + "listen: %s\n", + strerror(errno))); + close(s); + return False; + } + + fd_listenset[num_sockets] = s; + FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); + + num_sockets++; + + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too " + "many sockets to bind to\n")); + return False; + } } } - } + } SAFE_FREE(ports); @@ -461,7 +488,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ messaging_register(smbd_messaging_context(), NULL, MSG_SMB_FILE_RENAME, msg_file_was_renamed); messaging_register(smbd_messaging_context(), NULL, - MSG_SMB_CONF_UPDATED, smb_conf_updated); + MSG_SMB_CONF_UPDATED, smb_conf_updated); messaging_register(smbd_messaging_context(), NULL, MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete); brl_register_msgs(smbd_messaging_context()); @@ -478,7 +505,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ struct timeval now, idle_timeout; fd_set r_fds, w_fds; int num; - + /* Ensure we respond to PING and DEBUG messages from the main smbd. */ message_dispatch(smbd_messaging_context()); @@ -493,7 +520,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ idle_timeout = timeval_zero(); - memcpy((char *)&r_fds, (char *)&listen_set, + memcpy((char *)&r_fds, (char *)&listen_set, sizeof(listen_set)); FD_ZERO(&w_fds); GetTimeOfDay(&now); @@ -521,7 +548,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; } - + if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { continue; } @@ -548,10 +575,10 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ } smbd_set_server_fd(accept(s,&addr,&in_addrlen)); - + if (smbd_server_fd() == -1 && errno == EINTR) continue; - + if (smbd_server_fd() == -1) { DEBUG(0,("open_sockets_smbd: accept: %s\n", strerror(errno))); @@ -563,7 +590,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ if (smbd_server_fd() != -1 && interactive) return True; - + if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && ((child = sys_fork())==0)) { @@ -572,24 +599,24 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* Stop zombies, the parent explicitly handles * them, counting worker smbds. */ CatchChild(); - + /* close the listening socket(s) */ for(i = 0; i < num_sockets; i++) close(fd_listenset[i]); - + /* close our standard file descriptors */ close_low_fds(False); am_parent = 0; - + set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); set_socket_options(smbd_server_fd(),user_socket_options); - + /* this is needed so that we get decent entries in smbstatus for port 445 connects */ set_remote_machine_name(get_peer_addr(smbd_server_fd()), False); - + /* Reset the state of the random * number generation system, so * children do not get the same random @@ -603,10 +630,10 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ smb_panic("tdb_reopen_all failed"); } - return True; + return True; } /* The parent doesn't need this socket */ - close(smbd_server_fd()); + close(smbd_server_fd()); /* Sun May 6 18:56:14 2001 ackley@cs.unm.edu: Clear the closed fd info out of server_fd -- @@ -637,7 +664,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ * (ca. 100kb). * */ force_check_log_size(); - + } /* end for num */ } /* end while 1 */ -- cgit From fac788d6e2fc7e214fc1371cd613d216178aaa80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Oct 2007 16:11:01 -0700 Subject: Don't terminate on an invalid address family. Jeremy. (This used to be commit d04a8a6cdcc505e0244882a9abb7174eadbf81a7) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 61e20ce274..0a292bc616 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -429,7 +429,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* open an incoming socket */ if (!interpret_string_addr(&ss, sock_tok, AI_NUMERICHOST|AI_PASSIVE)) { - return false; + continue; } s = open_socket_in(SOCK_STREAM, port, 0, -- cgit From 38c34ffd6bcd14314330fd5f2e2a401dbf9cd061 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 25 Oct 2007 14:11:35 -0700 Subject: Ensure we don't terminate if we fail to bind to a socket, only fail if we can't bind to any socket. Jeremy. (This used to be commit 2ec6224b552ef86fa1739c9e396c39c7ec6c76c6) --- source3/smbd/server.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0a292bc616..abad0efc3d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -435,7 +435,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ s = open_socket_in(SOCK_STREAM, port, 0, &ss, true); if (s == -1) { - return false; + continue; } /* ready to listen */ @@ -471,6 +471,11 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ SAFE_FREE(ports); + if (num_sockets == 0) { + DEBUG(0,("open_sockets_smbd: No " + "sockets available to bind to.\n")); + return false; + } /* Setup the main smbd so that we can get messages. Note that do this after starting listening. This is needed as when in -- cgit From a97b33baad5bbce7e8004346aa3a812ec4f91f0e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 Oct 2007 21:15:07 +0200 Subject: Two patches Hi! Can you check and push them? Thanks, Volker From b488af5905e2dee12a1a72a3b40801ae5c26f24f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 Oct 2007 14:20:09 +0200 Subject: [PATCH] Fix some warnings and errors (This used to be commit e17d3e10e860c96b6d5208e5fe51e43b8e58c174) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index abad0efc3d..bcf997f2d2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -369,7 +369,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ open_socket_in(SOCK_STREAM, port, 0, ifss, True); if(s == -1) { - return false; + continue; } /* ready to listen */ -- cgit From 6ca0d8124c26edec1d9232d7380c4b66a2915cad Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 28 Oct 2007 11:58:26 +0100 Subject: Enable vfs objects = /full/path/to/object.so Right now I'm testing a vfs object. I can't right now in make test, because "vfs objects" assumes the .so files to be in $libdir/vfs. This patch parses the module name out of the object name in case it starts with "/". The module name is assumed to be the last path component's basename. (This used to be commit 95cc019af775a6ab28ea602ad767fa54d7c86197) --- source3/smbd/vfs.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b43f37e716..e862710b6c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -44,6 +44,8 @@ static struct vfs_init_function_entry *backends = NULL; static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) { struct vfs_init_function_entry *entry = backends; + + DEBUG(10, ("vfs_find_backend_entry called for %s\n", name)); while(entry) { if (strcmp(entry->name, name)==0) return entry; @@ -109,6 +111,7 @@ static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which, bool vfs_init_custom(connection_struct *conn, const char *vfs_object) { vfs_op_tuple *ops; + char *module_path = NULL; char *module_name = NULL; char *module_param = NULL, *p; int i; @@ -126,9 +129,9 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object)); - module_name = smb_xstrdup(vfs_object); + module_path = smb_xstrdup(vfs_object); - p = strchr_m(module_name, ':'); + p = strchr_m(module_path, ':'); if (p) { *p = 0; @@ -136,31 +139,48 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) trim_char(module_param, ' ', ' '); } - trim_char(module_name, ' ', ' '); + trim_char(module_path, ' ', ' '); + + module_name = smb_xstrdup(module_path); + + if ((module_name[0] == '/') && + (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) { + + /* + * Extract the module name from the path. Just use the base + * name of the last path component. + */ + + SAFE_FREE(module_name); + module_name = smb_xstrdup(strrchr_m(module_path, '/')+1); + + p = strchr_m(module_name, '.'); + + if (p != NULL) { + *p = '\0'; + } + } /* First, try to load the module with the new module system */ if((entry = vfs_find_backend_entry(module_name)) || - (NT_STATUS_IS_OK(smb_probe_module("vfs", module_name)) && + (NT_STATUS_IS_OK(smb_probe_module("vfs", module_path)) && (entry = vfs_find_backend_entry(module_name)))) { DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object)); if ((ops = entry->vfs_op_tuples) == NULL) { DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object)); - SAFE_FREE(module_name); - return False; + goto fail; } } else { DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object)); - SAFE_FREE(module_name); - return False; + goto fail; } handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct); if (!handle) { DEBUG(0,("TALLOC_ZERO() failed!\n")); - SAFE_FREE(module_name); - return False; + goto fail; } memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops)); handle->conn = conn; @@ -183,8 +203,14 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) vfs_set_operation(&conn->vfs, ops[i].type, handle, ops[i].op); } + SAFE_FREE(module_path); SAFE_FREE(module_name); return True; + + fail: + SAFE_FREE(module_path); + SAFE_FREE(module_name); + return False; } /***************************************************************** -- cgit From 851ef9e22f5f58202b0c5594b4432941afb0e130 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 30 Oct 2007 15:44:27 +0100 Subject: start smbd, nmbd and winbindd with the same startup message at debug level 0. metze (This used to be commit 95f76ae7a52c6b22db22d03fed6b0848d2a61bee) --- source3/smbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bcf997f2d2..b9ab7ef7ac 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1057,8 +1057,8 @@ extern void build_options(bool screen); reopen_logs(); - DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING)); - DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) ); + DEBUG(0,("smbd version %s started.\n", SAMBA_VERSION_STRING)); + DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); -- cgit From c3250149e12338fac5093991b385ad2807c92d1f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Oct 2007 16:22:24 -0700 Subject: Add new parameter, "min receivefile size" (by default set to zero). If non-zero, writeX calls greater than this value will be left in the socket buffer for later handling with recvfile (or userspace equivalent). Definition of recvfile for your system is left as an exercise for the reader (I'm working on getting splice working :-). Jeremy. (This used to be commit 11c03b75ddbcb6e36b231bb40a1773d1c550621c) --- source3/smbd/blocking.c | 4 +- source3/smbd/fileio.c | 41 +++++-- source3/smbd/notify.c | 2 +- source3/smbd/process.c | 62 +++++++--- source3/smbd/reply.c | 95 ++++++++++++--- source3/smbd/server.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++- source3/smbd/vfs.c | 32 +++++- 7 files changed, 482 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 66a61449a1..0078bb7d13 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -259,7 +259,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) smb_panic("Could not allocate smb_request"); } - init_smb_request(req, (uint8 *)blr->inbuf); + init_smb_request(req, (uint8 *)blr->inbuf, 0); reply_outbuf(req, 2, 0); /* @@ -531,7 +531,7 @@ static bool process_trans2(blocking_lock_record *blr) return True; } - init_smb_request(req, (uint8 *)blr->inbuf); + init_smb_request(req, (uint8 *)blr->inbuf, 0); SCVAL(req->inbuf, smb_com, SMBtrans2); SSVAL(params,0,0); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 14056ddc80..9e296f2204 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -116,12 +116,16 @@ static unsigned int allocated_write_caches; *Really* write to a file. ****************************************************************************/ -static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos, size_t n) +static ssize_t real_write_file(struct smb_request *req, + files_struct *fsp, + const char *data, + SMB_OFF_T pos, + size_t n) { ssize_t ret; if (pos == -1) { - ret = vfs_write_data(fsp, data, n); + ret = vfs_write_data(req, fsp, data, n); } else { fsp->fh->pos = pos; if (pos && lp_strict_allocate(SNUM(fsp->conn))) { @@ -129,7 +133,7 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos return -1; } } - ret = vfs_pwrite_data(fsp, data, n, pos); + ret = vfs_pwrite_data(req, fsp, data, n, pos); } DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", @@ -191,11 +195,15 @@ static int wcp_file_size_change(files_struct *fsp) Write to a file. ****************************************************************************/ -ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) +ssize_t write_file(struct smb_request *req, + files_struct *fsp, + const char *data, + SMB_OFF_T pos, + size_t n) { write_cache *wcp = fsp->wcp; ssize_t total_written = 0; - int write_path = -1; + int write_path = -1; if (fsp->print_file) { fstring sharename; @@ -234,8 +242,8 @@ ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { setup_write_cache(fsp, st.st_size); wcp = fsp->wcp; - } - } + } + } } #ifdef WITH_PROFILE @@ -280,9 +288,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", } #endif + if (wcp && req->unread_bytes) { + /* If we're using receivefile don't + * deal with a write cache. + */ + flush_write_cache(fsp, WRITE_FLUSH); + delete_write_cache(fsp); + wcp = NULL; + } + if(!wcp) { DO_PROFILE_INC(writecache_direct_writes); - total_written = real_write_file(fsp, data, pos, n); + total_written = real_write_file(req, fsp, data, pos, n); return total_written; } @@ -291,7 +308,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", fsp->fh->pos = pos + n; - /* + /* * If we have active cache and it isn't contiguous then we flush. * NOTE: There is a small problem with running out of disk .... */ @@ -610,7 +627,7 @@ len = %u\n",fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (uns if ( n <= wcp->alloc_size && n > wcp->data_size) { cache_flush_needed = True; } else { - ssize_t ret = real_write_file(fsp, data, pos, n); + ssize_t ret = real_write_file(NULL,fsp, data, pos, n); /* * If the write overlaps the entire cache, then @@ -657,7 +674,7 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", */ if (n > wcp->alloc_size ) { - ssize_t ret = real_write_file(fsp, data, pos, n); + ssize_t ret = real_write_file(NULL,fsp, data, pos, n); if (ret == -1) { return -1; } @@ -828,7 +845,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) } #endif - ret = real_write_file(fsp, wcp->data, wcp->offset, data_size); + ret = real_write_file(NULL, fsp, wcp->data, wcp->offset, data_size); /* * Ensure file size if kept up to date if write extends file. diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ecb7d9dce8..0dd7fbb20e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -189,7 +189,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, smb_setlen((char *)tmp_request, smb_size); SCVAL(tmp_request, smb_wct, 0); - init_smb_request(req, tmp_request); + init_smb_request(req, tmp_request,0); send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ed1bf762e9..1c8d8a6e76 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -25,7 +25,7 @@ extern int smb_echo_count; const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); -/* +/* * Size of data we can send to client. Set * by the client for all protocols above CORE. * Set by us for CORE protocol. @@ -48,7 +48,9 @@ extern int max_send; * Initialize a struct smb_request from an inbuf */ -void init_smb_request(struct smb_request *req, const uint8 *inbuf) +void init_smb_request(struct smb_request *req, + const uint8 *inbuf, + size_t unread_bytes) { size_t req_size = smb_len(inbuf) + 4; /* Ensure we have at least smb_size bytes. */ @@ -63,6 +65,8 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) req->vuid = SVAL(inbuf, smb_uid); req->tid = SVAL(inbuf, smb_tid); req->wct = CVAL(inbuf, smb_wct); + req->unread_bytes = unread_bytes; + /* Ensure we have at least wct words and 2 bytes of bcc. */ if (smb_size + req->wct*2 > req_size) { DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n", @@ -231,6 +235,14 @@ bool push_deferred_smb_message(struct smb_request *req, { struct timeval end_time; + if (req->unread_bytes) { + DEBUG(0,("push_deferred_smb_message: logic error ! " + "unread_bytes = %u\n", + (unsigned int)req->unread_bytes )); + smb_panic("push_deferred_smb_message: " + "logic error unread_bytes != 0" ); + } + end_time = timeval_sum(&request_time, &timeout); DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u " @@ -382,8 +394,11 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds) The timeout is in milliseconds ****************************************************************************/ -static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, - size_t *buffer_len, int timeout) +static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, + char **buffer, + size_t *buffer_len, + int timeout, + size_t *p_unread) { fd_set r_fds, w_fds; int selrtn; @@ -391,6 +406,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, int maxfd = 0; ssize_t len; + *p_unread = 0; smb_read_error = 0; again: @@ -565,7 +581,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, goto again; } - len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0); + len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, p_unread); if (len == -1) { return False; @@ -1115,7 +1131,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size) Construct a reply to the incoming packet. ****************************************************************************/ -static void construct_reply(char *inbuf, int size) +static void construct_reply(char *inbuf, int size, size_t unread_bytes) { uint8 type = CVAL(inbuf,smb_com); struct smb_request *req; @@ -1127,10 +1143,19 @@ static void construct_reply(char *inbuf, int size) if (!(req = talloc(talloc_tos(), struct smb_request))) { smb_panic("could not allocate smb_request"); } - init_smb_request(req, (uint8 *)inbuf); + init_smb_request(req, (uint8 *)inbuf, unread_bytes); switch_message(type, req, size); + if (req->unread_bytes) { + /* writeX failed. drain socket. */ + if (drain_socket(smbd_server_fd(), req->unread_bytes) != + req->unread_bytes) { + smb_panic("failed to drain pending bytes"); + } + req->unread_bytes = 0; + } + if (req->outbuf == NULL) { return; } @@ -1152,7 +1177,7 @@ static void construct_reply(char *inbuf, int size) Process an smb from the client ****************************************************************************/ -static void process_smb(char *inbuf, size_t nread) +static void process_smb(char *inbuf, size_t nread, size_t unread_bytes) { static int trans_num; int msg_type = CVAL(inbuf,0); @@ -1176,7 +1201,9 @@ static void process_smb(char *inbuf, size_t nread) DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, smb_len(inbuf) ) ); - DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, (int)nread ) ); + DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num, + (int)nread, + (unsigned int)unread_bytes )); if (msg_type != 0) { /* @@ -1188,8 +1215,8 @@ static void process_smb(char *inbuf, size_t nread) show_msg(inbuf); - construct_reply(inbuf,nread); - + construct_reply(inbuf,nread,unread_bytes); + trans_num++; } @@ -1348,7 +1375,7 @@ void chain_reply(struct smb_request *req) if (!(req2 = talloc(talloc_tos(), struct smb_request))) { smb_panic("could not allocate smb_request"); } - init_smb_request(req2, (uint8 *)inbuf2); + init_smb_request(req2, (uint8 *)inbuf2,0); /* process the request */ switch_message(smb_com2, req2, new_size); @@ -1625,6 +1652,7 @@ void smbd_process(void) { time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; + size_t unread_bytes = 0; max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); @@ -1635,8 +1663,8 @@ void smbd_process(void) size_t inbuf_len; TALLOC_CTX *frame = talloc_stackframe(); - errno = 0; - + errno = 0; + /* Did someone ask for immediate checks on things like blocking locks ? */ if (select_timeout == 0) { if(!timeout_processing(&select_timeout, @@ -1648,7 +1676,7 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len, - select_timeout)) { + select_timeout, &unread_bytes)) { if(!timeout_processing(&select_timeout, &last_timeout_processing_time)) return; @@ -1664,10 +1692,10 @@ void smbd_process(void) * faster than the select timeout, thus starving out the * essential processing (change notify, blocking locks) that * the timeout code does. JRA. - */ + */ num_echos = smb_echo_count; - process_smb(inbuf, inbuf_len); + process_smb(inbuf, inbuf_len, unread_bytes); TALLOC_FREE(inbuf); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 38ce797eeb..4c1ed56d4f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3494,7 +3494,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) } if (numtowrite>0) { - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); } DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d " @@ -3572,7 +3572,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) exit_server_cleanly("secondary writebraw failed"); } - nwritten = write_file(fsp,buf+4,startpos+nwritten,numtowrite); + nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite); if (nwritten == -1) { TALLOC_FREE(buf); reply_unixerror(req, ERRHRD, ERRdiskfull); @@ -3686,7 +3686,7 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req) if(numtowrite == 0) { nwritten = 0; } else { - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); } status = sync_file(conn, fsp, False /* write through */); @@ -3808,7 +3808,7 @@ void reply_write(connection_struct *conn, struct smb_request *req) return; } } else - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); status = sync_file(conn, fsp, False); if (!NT_STATUS_IS_OK(status)) { @@ -3840,6 +3840,64 @@ void reply_write(connection_struct *conn, struct smb_request *req) return; } +/**************************************************************************** + Ensure a buffer is a valid writeX for recvfile purposes. +****************************************************************************/ + +#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \ + (2*14) + /* word count (including bcc) */ \ + 1 /* pad byte */) + +bool is_valid_writeX_buffer(char *inbuf) +{ + size_t numtowrite; + connection_struct *conn = NULL; + unsigned int doff = 0; + size_t len = smb_len(inbuf); + + if (CVAL(inbuf,smb_com) != SMBwriteX || + CVAL(inbuf,smb_vwv0) != 0xFF || + CVAL(inbuf,smb_wct) != 14) { + return false; + } + conn = conn_find(SVAL(inbuf, smb_tid)); + if (conn == NULL) { + return false; + } + if (IS_IPC(conn)) { + return false; + } + numtowrite = SVAL(inbuf,smb_vwv10); + numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); + if (numtowrite == 0) { + return false; + } + /* Ensure the sizes match up. */ + doff = SVAL(inbuf,smb_vwv11); + + if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) { + /* no pad byte...old smbclient :-( */ + return false; + } + + if (len - doff != numtowrite) { + DEBUG(10,("is_valid_writeX_buffer: doff mismatch " + "len = %u, doff = %u, numtowrite = %u\n", + (unsigned int)len, + (unsigned int)doff, + (unsigned int)numtowrite )); + return false; + } + + DEBUG(10,("is_valid_writeX_buffer: true " + "len = %u, doff = %u, numtowrite = %u\n", + (unsigned int)len, + (unsigned int)doff, + (unsigned int)numtowrite )); + + return true; +} + /**************************************************************************** Reply to a write and X. ****************************************************************************/ @@ -3875,10 +3933,18 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16); } - if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { - reply_doserror(req, ERRDOS, ERRbadmem); - END_PROFILE(SMBwriteX); - return; + if (req->unread_bytes) { + if (numtowrite != req->unread_bytes) { + reply_doserror(req, ERRDOS, ERRbadmem); + END_PROFILE(SMBwriteX); + return; + } + } else { + if (smb_doff > smblen || smb_doff + numtowrite > smblen) { + reply_doserror(req, ERRDOS, ERRbadmem); + END_PROFILE(SMBwriteX); + return; + } } /* If it's an IPC, pass off the pipe handler. */ @@ -3947,15 +4013,16 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) nwritten = 0; } else { - if (schedule_aio_write_and_X(conn, req, fsp, data, startpos, - numtowrite)) { + if (req->unread_bytes == 0 && + schedule_aio_write_and_X(conn, req, fsp, data, + startpos, numtowrite)) { END_PROFILE(SMBwriteX); return; } - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); } - + if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBwriteX); @@ -4264,7 +4331,7 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req) return; } - nwritten = write_file(fsp,data,startpos,numtowrite); + nwritten = write_file(req,fsp,data,startpos,numtowrite); set_filetime(conn, fsp->fsp_name, mtime); @@ -4726,7 +4793,7 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req) data = smb_buf(req->inbuf) + 3; - if (write_file(fsp,data,-1,numtowrite) != numtowrite) { + if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) { reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBsplwr); return; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b9ab7ef7ac..25e2d2cb5e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1,20 +1,22 @@ -/* +/* Unix SMB/CIFS implementation. Main SMB server routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 Copyright (C) Jelmer Vernooij 2002-2003 - + Copyright (C) Volker Lendecke 1993-2007 + Copyright (C) Jeremy Allison 1993-2007 + 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 3 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, see . */ @@ -37,6 +39,8 @@ extern SIG_ATOMIC_T got_sig_term; extern SIG_ATOMIC_T reload_after_sighup; static SIG_ATOMIC_T got_sig_cld; +extern int smb_read_error; + #ifdef WITH_DFS extern int dcelogin_atmost_once; #endif /* WITH_DFS */ @@ -60,6 +64,293 @@ static void smbd_set_server_fd(int fd) client_setfd(fd); } +/* Socket functions for smbd packet processing. */ + +static bool valid_packet_size(len) +{ + /* + * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes + * of header. Don't print the error if this fits.... JRA. + */ + + if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) { + DEBUG(0,("Invalid packet length! (%lu bytes).\n", + (unsigned long)len)); + if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) { + + /* + * Correct fix. smb_read_error may have already been + * set. Only set it here if not already set. Global + * variables still suck :-). JRA. + */ + + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return false; + } + } + return true; +} + +static ssize_t read_packet_remainder(int fd, + char *buffer, + unsigned int timeout, + ssize_t len) +{ + ssize_t ret; + + if(len <= 0) { + return len; + } + + if (timeout > 0) { + ret = read_socket_with_timeout(fd, + buffer, + len, + len, + timeout); + } else { + ret = read_data(fd, buffer, len); + } + + if (ret != len) { + if (smb_read_error == 0) { + smb_read_error = READ_ERROR; + } + return -1; + } + + return len; +} + +/**************************************************************************** + Attempt a zerocopy writeX read. We know here that len > smb_size-4 +****************************************************************************/ + +/* + * Unfortunately, earlier versions of smbclient/libsmbclient + * don't send this "standard" writeX header. I've fixed this + * for 3.2 but we'll use the old method with earlier versions. + * Windows and CIFSFS at least use this standard size. Not + * sure about MacOSX. + */ + +#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \ + (2*14) + /* word count (including bcc) */ \ + 1 /* pad byte */) + +ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, + const char lenbuf[4], + int fd, + char **buffer, + unsigned int timeout, + size_t *p_unread) +{ + /* Size of a WRITEX call (+4 byte len). */ + char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE]; + ssize_t len = smb_len(lenbuf); + ssize_t toread; + ssize_t ret; + + memcpy(writeX_header, lenbuf, sizeof(lenbuf)); + + if (timeout > 0) { + ret = read_socket_with_timeout(fd, + writeX_header + 4, + STANDARD_WRITE_AND_X_HEADER_SIZE, + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout); + } else { + ret = read_data(fd, + writeX_header+4, + STANDARD_WRITE_AND_X_HEADER_SIZE); + } + + if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { + if (smb_read_error == 0) { + smb_read_error = READ_ERROR; + } + return -1; + } + + /* + * Ok - now try and see if this is a possible + * valid writeX call. + */ + + if (is_valid_writeX_buffer(writeX_header)) { + /* + * If the data offset is beyond what + * we've read, drain the extra bytes. + */ + uint16_t doff = SVAL(writeX_header,smb_vwv11); + ssize_t newlen; + + if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) { + size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE; + if (drain_socket(smbd_server_fd(), drain) != drain) { + smb_panic("receive_smb_raw_talloc_partial_read:" + " failed to drain pending bytes"); + } + } else { + doff = STANDARD_WRITE_AND_X_HEADER_SIZE; + } + + /* Spoof down the length and null out the bcc. */ + set_message_bcc(writeX_header, 0); + newlen = smb_len(writeX_header); + + /* Copy the header we've written. */ + + *buffer = TALLOC_MEMDUP(mem_ctx, + writeX_header, + sizeof(writeX_header)); + + if (*buffer == NULL) { + DEBUG(0, ("Could not allocate inbuf of length %d\n", + (int)sizeof(writeX_header))); + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + /* Work out the remaining bytes. */ + *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; + + return newlen + 4; + } + + if (!valid_packet_size(len)) { + return -1; + } + + /* + * Not a valid writeX call. Just do the standard + * talloc and return. + */ + + *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); + + if (*buffer == NULL) { + DEBUG(0, ("Could not allocate inbuf of length %d\n", + (int)len+4)); + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + /* Copy in what we already read. */ + memcpy(*buffer, + writeX_header, + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE); + toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; + + if(toread > 0) { + ret = read_packet_remainder(fd, + (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout, + toread); + if (ret != toread) { + return -1; + } + } + + return len + 4; +} + +static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, + int fd, + char **buffer, + unsigned int timeout, + size_t *p_unread) +{ + char lenbuf[4]; + ssize_t len,ret; + int min_recv_size = lp_min_receive_file_size(); + + smb_read_error = 0; + *p_unread = 0; + + len = read_smb_length_return_keepalive(fd, lenbuf, timeout); + if (len < 0) { + DEBUG(10,("receive_smb_raw: length < 0!\n")); + + /* + * Correct fix. smb_read_error may have already been + * set. Only set it here if not already set. Global + * variables still suck :-). JRA. + */ + + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + if (CVAL(lenbuf,0) != SMBkeepalive && + min_recv_size && + len > min_recv_size && + !srv_is_signing_active()) { + + return receive_smb_raw_talloc_partial_read(mem_ctx, + lenbuf, + fd, + buffer, + timeout, + p_unread); + } + + if (!valid_packet_size(len)) { + return -1; + } + + /* + * The +4 here can't wrap, we've checked the length above already. + */ + + *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); + + if (*buffer == NULL) { + DEBUG(0, ("Could not allocate inbuf of length %d\n", + (int)len+4)); + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + memcpy(*buffer, lenbuf, sizeof(lenbuf)); + + ret = read_packet_remainder(fd, (*buffer)+4, timeout, len); + if (ret != len) { + return -1; + } + + return len + 4; +} + +ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, + unsigned int timeout, size_t *p_unread) +{ + ssize_t len; + + len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread); + + if (len < 0) { + return -1; + } + + /* Check the incoming SMB signature. */ + if (!srv_check_sign_mac(*buffer, true)) { + DEBUG(0, ("receive_smb: SMB Signature verification failed on " + "incoming packet!\n")); + if (smb_read_error == 0) { + smb_read_error = READ_BAD_SIG; + } + return -1; + } + + return len; +} + struct event_context *smbd_event_context(void) { static struct event_context *ctx; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index e862710b6c..c1c1939153 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -418,11 +418,24 @@ ssize_t vfs_pread_data(files_struct *fsp, char *buf, Write data to a fd on the vfs. ****************************************************************************/ -ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) +ssize_t vfs_write_data(struct smb_request *req, + files_struct *fsp, + const char *buffer, + size_t N) { size_t total=0; ssize_t ret; + if (req && req->unread_bytes) { + SMB_ASSERT(req->unread_bytes == N); + req->unread_bytes = 0; + return SMB_VFS_RECVFILE(smbd_server_fd(), + fsp, + fsp->fh->fd, + (SMB_OFF_T)-1, + N); + } + while (total < N) { ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total); @@ -436,12 +449,25 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) return (ssize_t)total; } -ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer, - size_t N, SMB_OFF_T offset) +ssize_t vfs_pwrite_data(struct smb_request *req, + files_struct *fsp, + const char *buffer, + size_t N, + SMB_OFF_T offset) { size_t total=0; ssize_t ret; + if (req && req->unread_bytes) { + SMB_ASSERT(req->unread_bytes == N); + req->unread_bytes = 0; + return SMB_VFS_RECVFILE(smbd_server_fd(), + fsp, + fsp->fh->fd, + offset, + N); + } + while (total < N) { ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total, N - total, offset + total); -- cgit From 360c02328faf6fd64edebc8f3d499cee54753aeb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Oct 2007 17:42:02 -0700 Subject: Ensure we don't prematurely clean out the bytes read. Jeremy. (This used to be commit 247675695dfbff503b5792de62f8bb1567ea2327) --- source3/smbd/vfs.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index c1c1939153..21a12ae766 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -428,12 +428,15 @@ ssize_t vfs_write_data(struct smb_request *req, if (req && req->unread_bytes) { SMB_ASSERT(req->unread_bytes == N); - req->unread_bytes = 0; - return SMB_VFS_RECVFILE(smbd_server_fd(), + ret = SMB_VFS_RECVFILE(smbd_server_fd(), fsp, fsp->fh->fd, (SMB_OFF_T)-1, N); + if (ret != -1) { + req->unread_bytes = 0; + } + return ret; } while (total < N) { @@ -460,12 +463,15 @@ ssize_t vfs_pwrite_data(struct smb_request *req, if (req && req->unread_bytes) { SMB_ASSERT(req->unread_bytes == N); - req->unread_bytes = 0; - return SMB_VFS_RECVFILE(smbd_server_fd(), + ret = SMB_VFS_RECVFILE(smbd_server_fd(), fsp, fsp->fh->fd, offset, N); + if (ret != -1) { + req->unread_bytes = 0; + } + return ret; } while (total < N) { -- cgit From ff82c0a037b7c7ce69d87ab70284acc71df5e1a7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Oct 2007 18:18:40 -0700 Subject: Handle the disk full error case correctly. Jeremy. (This used to be commit b7088bb9c2a00d4717b9a7efa4bddc0c005f4efb) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4c1ed56d4f..531e71fe73 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3698,7 +3698,7 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req) return; } - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { + if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) { reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBwriteunlock); return; -- cgit From 133fad90b5f9cef26f9c78cc5b302358c9c4da6a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Oct 2007 14:01:35 -0700 Subject: Make explicit draining the socket on RECVFILE. Add capability for large UNIX write if not signing and recvfile set. Cope with large UNIX write length on incoming processing. Stevef - we can now test 1-16Mb writes from CIFFS. Jeremy. (This used to be commit 8cf78776b0a44bd026cef3d74eb11cfb415f8303) --- source3/smbd/server.c | 2 +- source3/smbd/trans2.c | 9 ++++++++- source3/smbd/vfs.c | 18 ++++++++---------- 3 files changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 25e2d2cb5e..bac2d48ad6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -148,7 +148,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, { /* Size of a WRITEX call (+4 byte len). */ char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE]; - ssize_t len = smb_len(lenbuf); + ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */ ssize_t toread; ssize_t ret; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7f38d5caa8..d75f6a29fd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2719,6 +2719,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned */ case SMB_QUERY_CIFS_UNIX_INFO: + { + bool large_write = lp_min_receive_file_size() && + !srv_is_signing_active(); + if (!lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; @@ -2733,8 +2737,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_FCNTL_LOCKS_CAP| CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| - CIFS_UNIX_LARGE_READ_CAP))); + CIFS_UNIX_LARGE_READ_CAP| + large_write ? + CIFS_UNIX_LARGE_WRITE_CAP : 0))); break; + } case SMB_QUERY_POSIX_FS_INFO: { diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 21a12ae766..78939881d3 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -428,15 +428,14 @@ ssize_t vfs_write_data(struct smb_request *req, if (req && req->unread_bytes) { SMB_ASSERT(req->unread_bytes == N); - ret = SMB_VFS_RECVFILE(smbd_server_fd(), + /* VFS_RECVFILE must drain the socket + * before returning. */ + req->unread_bytes = 0; + return SMB_VFS_RECVFILE(smbd_server_fd(), fsp, fsp->fh->fd, (SMB_OFF_T)-1, N); - if (ret != -1) { - req->unread_bytes = 0; - } - return ret; } while (total < N) { @@ -463,15 +462,14 @@ ssize_t vfs_pwrite_data(struct smb_request *req, if (req && req->unread_bytes) { SMB_ASSERT(req->unread_bytes == N); - ret = SMB_VFS_RECVFILE(smbd_server_fd(), + /* VFS_RECVFILE must drain the socket + * before returning. */ + req->unread_bytes = 0; + return SMB_VFS_RECVFILE(smbd_server_fd(), fsp, fsp->fh->fd, offset, N); - if (ret != -1) { - req->unread_bytes = 0; - } - return ret; } while (total < N) { -- cgit From 695c4a7a741f1a8a00a4dc867cc3ef731bfc093f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Oct 2007 14:24:52 -0700 Subject: Fix vfstest link - move socket calls into smbd/process.c not smbd/server.c Jeremy (This used to be commit 8fbefe18a2dc23adb0ebe488cfb37ab4a382207d) --- source3/smbd/process.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 288 ------------------------------------------------- 2 files changed, 288 insertions(+), 288 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1c8d8a6e76..eca51a74a3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -22,6 +22,7 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; +extern int smb_read_error; const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); @@ -44,6 +45,293 @@ SIG_ATOMIC_T got_sig_term = 0; extern bool global_machine_password_needs_changing; extern int max_send; +/* Socket functions for smbd packet processing. */ + +static bool valid_packet_size(len) +{ + /* + * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes + * of header. Don't print the error if this fits.... JRA. + */ + + if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) { + DEBUG(0,("Invalid packet length! (%lu bytes).\n", + (unsigned long)len)); + if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) { + + /* + * Correct fix. smb_read_error may have already been + * set. Only set it here if not already set. Global + * variables still suck :-). JRA. + */ + + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return false; + } + } + return true; +} + +static ssize_t read_packet_remainder(int fd, + char *buffer, + unsigned int timeout, + ssize_t len) +{ + ssize_t ret; + + if(len <= 0) { + return len; + } + + if (timeout > 0) { + ret = read_socket_with_timeout(fd, + buffer, + len, + len, + timeout); + } else { + ret = read_data(fd, buffer, len); + } + + if (ret != len) { + if (smb_read_error == 0) { + smb_read_error = READ_ERROR; + } + return -1; + } + + return len; +} + +/**************************************************************************** + Attempt a zerocopy writeX read. We know here that len > smb_size-4 +****************************************************************************/ + +/* + * Unfortunately, earlier versions of smbclient/libsmbclient + * don't send this "standard" writeX header. I've fixed this + * for 3.2 but we'll use the old method with earlier versions. + * Windows and CIFSFS at least use this standard size. Not + * sure about MacOSX. + */ + +#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \ + (2*14) + /* word count (including bcc) */ \ + 1 /* pad byte */) + +ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, + const char lenbuf[4], + int fd, + char **buffer, + unsigned int timeout, + size_t *p_unread) +{ + /* Size of a WRITEX call (+4 byte len). */ + char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE]; + ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */ + ssize_t toread; + ssize_t ret; + + memcpy(writeX_header, lenbuf, sizeof(lenbuf)); + + if (timeout > 0) { + ret = read_socket_with_timeout(fd, + writeX_header + 4, + STANDARD_WRITE_AND_X_HEADER_SIZE, + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout); + } else { + ret = read_data(fd, + writeX_header+4, + STANDARD_WRITE_AND_X_HEADER_SIZE); + } + + if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { + if (smb_read_error == 0) { + smb_read_error = READ_ERROR; + } + return -1; + } + + /* + * Ok - now try and see if this is a possible + * valid writeX call. + */ + + if (is_valid_writeX_buffer(writeX_header)) { + /* + * If the data offset is beyond what + * we've read, drain the extra bytes. + */ + uint16_t doff = SVAL(writeX_header,smb_vwv11); + ssize_t newlen; + + if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) { + size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE; + if (drain_socket(smbd_server_fd(), drain) != drain) { + smb_panic("receive_smb_raw_talloc_partial_read:" + " failed to drain pending bytes"); + } + } else { + doff = STANDARD_WRITE_AND_X_HEADER_SIZE; + } + + /* Spoof down the length and null out the bcc. */ + set_message_bcc(writeX_header, 0); + newlen = smb_len(writeX_header); + + /* Copy the header we've written. */ + + *buffer = TALLOC_MEMDUP(mem_ctx, + writeX_header, + sizeof(writeX_header)); + + if (*buffer == NULL) { + DEBUG(0, ("Could not allocate inbuf of length %d\n", + (int)sizeof(writeX_header))); + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + /* Work out the remaining bytes. */ + *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; + + return newlen + 4; + } + + if (!valid_packet_size(len)) { + return -1; + } + + /* + * Not a valid writeX call. Just do the standard + * talloc and return. + */ + + *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); + + if (*buffer == NULL) { + DEBUG(0, ("Could not allocate inbuf of length %d\n", + (int)len+4)); + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + /* Copy in what we already read. */ + memcpy(*buffer, + writeX_header, + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE); + toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; + + if(toread > 0) { + ret = read_packet_remainder(fd, + (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout, + toread); + if (ret != toread) { + return -1; + } + } + + return len + 4; +} + +static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, + int fd, + char **buffer, + unsigned int timeout, + size_t *p_unread) +{ + char lenbuf[4]; + ssize_t len,ret; + int min_recv_size = lp_min_receive_file_size(); + + smb_read_error = 0; + *p_unread = 0; + + len = read_smb_length_return_keepalive(fd, lenbuf, timeout); + if (len < 0) { + DEBUG(10,("receive_smb_raw: length < 0!\n")); + + /* + * Correct fix. smb_read_error may have already been + * set. Only set it here if not already set. Global + * variables still suck :-). JRA. + */ + + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + if (CVAL(lenbuf,0) != SMBkeepalive && + min_recv_size && + len > min_recv_size && + !srv_is_signing_active()) { + + return receive_smb_raw_talloc_partial_read(mem_ctx, + lenbuf, + fd, + buffer, + timeout, + p_unread); + } + + if (!valid_packet_size(len)) { + return -1; + } + + /* + * The +4 here can't wrap, we've checked the length above already. + */ + + *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); + + if (*buffer == NULL) { + DEBUG(0, ("Could not allocate inbuf of length %d\n", + (int)len+4)); + if (smb_read_error == 0) + smb_read_error = READ_ERROR; + return -1; + } + + memcpy(*buffer, lenbuf, sizeof(lenbuf)); + + ret = read_packet_remainder(fd, (*buffer)+4, timeout, len); + if (ret != len) { + return -1; + } + + return len + 4; +} + +ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, + unsigned int timeout, size_t *p_unread) +{ + ssize_t len; + + len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread); + + if (len < 0) { + return -1; + } + + /* Check the incoming SMB signature. */ + if (!srv_check_sign_mac(*buffer, true)) { + DEBUG(0, ("receive_smb: SMB Signature verification failed on " + "incoming packet!\n")); + if (smb_read_error == 0) { + smb_read_error = READ_BAD_SIG; + } + return -1; + } + + return len; +} + /* * Initialize a struct smb_request from an inbuf */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bac2d48ad6..fa8e163081 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -39,8 +39,6 @@ extern SIG_ATOMIC_T got_sig_term; extern SIG_ATOMIC_T reload_after_sighup; static SIG_ATOMIC_T got_sig_cld; -extern int smb_read_error; - #ifdef WITH_DFS extern int dcelogin_atmost_once; #endif /* WITH_DFS */ @@ -64,292 +62,6 @@ static void smbd_set_server_fd(int fd) client_setfd(fd); } -/* Socket functions for smbd packet processing. */ - -static bool valid_packet_size(len) -{ - /* - * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes - * of header. Don't print the error if this fits.... JRA. - */ - - if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) { - DEBUG(0,("Invalid packet length! (%lu bytes).\n", - (unsigned long)len)); - if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) { - - /* - * Correct fix. smb_read_error may have already been - * set. Only set it here if not already set. Global - * variables still suck :-). JRA. - */ - - if (smb_read_error == 0) - smb_read_error = READ_ERROR; - return false; - } - } - return true; -} - -static ssize_t read_packet_remainder(int fd, - char *buffer, - unsigned int timeout, - ssize_t len) -{ - ssize_t ret; - - if(len <= 0) { - return len; - } - - if (timeout > 0) { - ret = read_socket_with_timeout(fd, - buffer, - len, - len, - timeout); - } else { - ret = read_data(fd, buffer, len); - } - - if (ret != len) { - if (smb_read_error == 0) { - smb_read_error = READ_ERROR; - } - return -1; - } - - return len; -} - -/**************************************************************************** - Attempt a zerocopy writeX read. We know here that len > smb_size-4 -****************************************************************************/ - -/* - * Unfortunately, earlier versions of smbclient/libsmbclient - * don't send this "standard" writeX header. I've fixed this - * for 3.2 but we'll use the old method with earlier versions. - * Windows and CIFSFS at least use this standard size. Not - * sure about MacOSX. - */ - -#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \ - (2*14) + /* word count (including bcc) */ \ - 1 /* pad byte */) - -ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, - const char lenbuf[4], - int fd, - char **buffer, - unsigned int timeout, - size_t *p_unread) -{ - /* Size of a WRITEX call (+4 byte len). */ - char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE]; - ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */ - ssize_t toread; - ssize_t ret; - - memcpy(writeX_header, lenbuf, sizeof(lenbuf)); - - if (timeout > 0) { - ret = read_socket_with_timeout(fd, - writeX_header + 4, - STANDARD_WRITE_AND_X_HEADER_SIZE, - STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout); - } else { - ret = read_data(fd, - writeX_header+4, - STANDARD_WRITE_AND_X_HEADER_SIZE); - } - - if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { - if (smb_read_error == 0) { - smb_read_error = READ_ERROR; - } - return -1; - } - - /* - * Ok - now try and see if this is a possible - * valid writeX call. - */ - - if (is_valid_writeX_buffer(writeX_header)) { - /* - * If the data offset is beyond what - * we've read, drain the extra bytes. - */ - uint16_t doff = SVAL(writeX_header,smb_vwv11); - ssize_t newlen; - - if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) { - size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE; - if (drain_socket(smbd_server_fd(), drain) != drain) { - smb_panic("receive_smb_raw_talloc_partial_read:" - " failed to drain pending bytes"); - } - } else { - doff = STANDARD_WRITE_AND_X_HEADER_SIZE; - } - - /* Spoof down the length and null out the bcc. */ - set_message_bcc(writeX_header, 0); - newlen = smb_len(writeX_header); - - /* Copy the header we've written. */ - - *buffer = TALLOC_MEMDUP(mem_ctx, - writeX_header, - sizeof(writeX_header)); - - if (*buffer == NULL) { - DEBUG(0, ("Could not allocate inbuf of length %d\n", - (int)sizeof(writeX_header))); - if (smb_read_error == 0) - smb_read_error = READ_ERROR; - return -1; - } - - /* Work out the remaining bytes. */ - *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; - - return newlen + 4; - } - - if (!valid_packet_size(len)) { - return -1; - } - - /* - * Not a valid writeX call. Just do the standard - * talloc and return. - */ - - *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); - - if (*buffer == NULL) { - DEBUG(0, ("Could not allocate inbuf of length %d\n", - (int)len+4)); - if (smb_read_error == 0) - smb_read_error = READ_ERROR; - return -1; - } - - /* Copy in what we already read. */ - memcpy(*buffer, - writeX_header, - 4 + STANDARD_WRITE_AND_X_HEADER_SIZE); - toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; - - if(toread > 0) { - ret = read_packet_remainder(fd, - (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout, - toread); - if (ret != toread) { - return -1; - } - } - - return len + 4; -} - -static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, - int fd, - char **buffer, - unsigned int timeout, - size_t *p_unread) -{ - char lenbuf[4]; - ssize_t len,ret; - int min_recv_size = lp_min_receive_file_size(); - - smb_read_error = 0; - *p_unread = 0; - - len = read_smb_length_return_keepalive(fd, lenbuf, timeout); - if (len < 0) { - DEBUG(10,("receive_smb_raw: length < 0!\n")); - - /* - * Correct fix. smb_read_error may have already been - * set. Only set it here if not already set. Global - * variables still suck :-). JRA. - */ - - if (smb_read_error == 0) - smb_read_error = READ_ERROR; - return -1; - } - - if (CVAL(lenbuf,0) != SMBkeepalive && - min_recv_size && - len > min_recv_size && - !srv_is_signing_active()) { - - return receive_smb_raw_talloc_partial_read(mem_ctx, - lenbuf, - fd, - buffer, - timeout, - p_unread); - } - - if (!valid_packet_size(len)) { - return -1; - } - - /* - * The +4 here can't wrap, we've checked the length above already. - */ - - *buffer = TALLOC_ARRAY(mem_ctx, char, len+4); - - if (*buffer == NULL) { - DEBUG(0, ("Could not allocate inbuf of length %d\n", - (int)len+4)); - if (smb_read_error == 0) - smb_read_error = READ_ERROR; - return -1; - } - - memcpy(*buffer, lenbuf, sizeof(lenbuf)); - - ret = read_packet_remainder(fd, (*buffer)+4, timeout, len); - if (ret != len) { - return -1; - } - - return len + 4; -} - -ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, - unsigned int timeout, size_t *p_unread) -{ - ssize_t len; - - len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread); - - if (len < 0) { - return -1; - } - - /* Check the incoming SMB signature. */ - if (!srv_check_sign_mac(*buffer, true)) { - DEBUG(0, ("receive_smb: SMB Signature verification failed on " - "incoming packet!\n")); - if (smb_read_error == 0) { - smb_read_error = READ_BAD_SIG; - } - return -1; - } - - return len; -} struct event_context *smbd_event_context(void) { -- cgit From 8f1f2f04c796a8659d93bafadefca4a98fee00f0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Oct 2007 15:45:45 -0700 Subject: Fix some cases where file_set_dosmode was being passed False instead of NULL. Fix more of the notifications to be correct for Samba4 RAW-NOTIFY torture (we had missed one when calling set_ea_dos_attribute(). Jeremy. (This used to be commit 39d265375cf55eedddef2c4faa65398df73d5ed2) --- source3/smbd/dosmode.c | 19 ++++++++++++++----- source3/smbd/fileio.c | 9 +++++++-- source3/smbd/nttrans.c | 2 +- source3/smbd/open.c | 6 ++++-- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 2 +- 6 files changed, 28 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ed622d3730..18e6439be4 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -425,7 +425,8 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, - const char *parent_dir) + const char *parent_dir, + bool newfile) { SMB_STRUCT_STAT st1; int mask=0; @@ -455,6 +456,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname, /* Store the DOS attributes in an EA by preference. */ if (set_ea_dos_attribute(conn, fname, st, dosmode)) { + if (!newfile) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + } return 0; } @@ -491,8 +496,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname, } if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + if (!newfile) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + } return 0; } @@ -523,8 +530,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname, ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + if (!newfile) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + } } return( ret ); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 9e296f2204..74f2c6774f 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -230,8 +230,13 @@ ssize_t write_file(struct smb_request *req, if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); - if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { - file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st, False); + if ((lp_store_dos_attributes(SNUM(fsp->conn)) || + MAP_ARCHIVE(fsp->conn)) && + !IS_DOS_ARCHIVE(dosmode)) { + file_set_dosmode(fsp->conn,fsp->fsp_name, + dosmode | aARCH,&st, + NULL, + false); } /* diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bbbde06619..da926d1bce 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1971,7 +1971,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, creates the file. This isn't the correct thing to do in the copy case. JRA */ file_set_dosmode(conn, newname, fattr, &sbuf2, - parent_dirname(newname)); + parent_dirname(newname),false); if (ret < (SMB_OFF_T)sbuf1.st_size) { return NT_STATUS_DISK_FULL; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4ed3a70411..53fc1be586 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1866,7 +1866,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (!posix_open) { file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, - parent_dir); + parent_dir, + true); } } } @@ -2035,7 +2036,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, if (!posix_open) { file_set_dosmode(conn, name, file_attributes | aDIR, NULL, - parent_dir); + parent_dir, + true); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 531e71fe73..d2aa6c6929 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1114,7 +1114,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) else mode &= ~aDIR; - if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) { + if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) { reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetatr); return; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d75f6a29fd..58d44a856b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4563,7 +4563,7 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n", fname, (unsigned int)dosmode )); - if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) { + if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) { DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n", fname, strerror(errno))); return map_nt_error_from_unix(errno); -- cgit From 0bb1a6ec2d963c2001230142692de8335c540434 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Oct 2007 16:32:48 -0700 Subject: Note when we're setting change time, not write time, and send message accordingly. Apart from not supporting create time we now pass the S4 RAW-NOTIFY torture. Jeremy. (This used to be commit 8a77f520fa03afa60eac2aaeab4babe7dd8db4f0) --- source3/smbd/dosmode.c | 11 ++++++----- source3/smbd/fileio.c | 3 ++- source3/smbd/trans2.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 32 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 18e6439be4..8e3c9b4c91 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -591,7 +591,7 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe return ret; } - + /******************************************************************* Change a filetime - possibly allowing DOS semantics. *******************************************************************/ @@ -609,12 +609,13 @@ bool set_filetime(connection_struct *conn, const char *fname, ts[0] = ts[1]; /* atime. */ if (file_ntimes(conn, fname, ts)) { - DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); + DEBUG(4,("set_filetime(%s) failed: %s\n", + fname,strerror(errno))); return False; } notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_LAST_WRITE, fname); - - return True; + FILE_NOTIFY_CHANGE_LAST_WRITE, fname); + + return true; } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 74f2c6774f..8037510d80 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -153,7 +153,8 @@ static ssize_t real_write_file(struct smb_request *req, */ if (!null_timespec(fsp->pending_modtime)) { - set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime); + set_filetime(fsp->conn, fsp->fsp_name, + fsp->pending_modtime); /* If we didn't get the "set modtime" call ourselves, we must store the last write time to restore on close. JRA. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 58d44a856b..09a8fcc876 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4467,13 +4467,13 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, const char *fname, const SMB_STRUCT_STAT *psbuf, - struct timespec ts[2]) + struct timespec ts[2], + bool setting_write_time) { uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS |FILE_NOTIFY_CHANGE_LAST_WRITE; - if (!VALID_STAT(*psbuf)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -4489,6 +4489,11 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } + if (!setting_write_time) { + /* ts[1] comes from change time, not write time. */ + action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; + } + DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) )); DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) )); @@ -4528,9 +4533,8 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, if(file_ntimes(conn, fname, ts)!=0) { return map_nt_error_from_unix(errno); } - if (action != 0) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname); - } + notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname); + return NT_STATUS_OK; } @@ -5226,7 +5230,8 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, fsp, fname, psbuf, - ts); + ts, + true); } /**************************************************************************** @@ -5246,6 +5251,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, uint32 dosmode = 0; struct timespec ts[2]; NTSTATUS status = NT_STATUS_OK; + bool setting_write_time = true; if (total_data < 36) { return NT_STATUS_INVALID_PARAMETER; @@ -5278,7 +5284,12 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, /* Prefer a defined time to an undefined one. */ if (null_timespec(ts[1])) { - ts[1] = null_timespec(write_time) ? changed_time : write_time; + if (null_timespec(write_time)) { + ts[1] = changed_time; + setting_write_time = false; + } else { + ts[1] = write_time; + } } DEBUG(10,("smb_set_file_basic_info: file %s\n", @@ -5288,7 +5299,8 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, fsp, fname, psbuf, - ts); + ts, + setting_write_time); } /**************************************************************************** @@ -5349,7 +5361,8 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, * This is equivalent to a write. Ensure it's seen immediately * if there are no pending writes. */ - set_filetime(fsp->conn, fsp->fsp_name, timespec_current()); + set_filetime(fsp->conn, fsp->fsp_name, + timespec_current()); } return NT_STATUS_OK; } @@ -5682,7 +5695,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", fsp, fname, psbuf, - ts); + ts, + true); } /**************************************************************************** -- cgit From 8bad80efb016dbd1aa392bbbc2b954d4dc9e3906 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Nov 2007 18:30:02 -0700 Subject: Add brackets so as not to break the POSIX caps return. Jeremy. (This used to be commit 47dbddcb5361caa30ee60cf4e15bb50d557d1191) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 09a8fcc876..c9ea02969b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2738,8 +2738,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| CIFS_UNIX_LARGE_READ_CAP| - large_write ? - CIFS_UNIX_LARGE_WRITE_CAP : 0))); + (large_write ? + CIFS_UNIX_LARGE_WRITE_CAP : 0)))); break; } -- cgit From c94b2898cd5d1174181add198a462ab232f5aba6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Nov 2007 21:51:45 -0700 Subject: Ensure we detect a large writeX when using recvfile. More changes needed to make the UNIX_LARGE_WRITEX_CAP writes work (I'll add these tomorrow). Jeremy. (This used to be commit 1c71546b6152d2930b98f766311bbd161ee0ee4e) --- source3/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d2aa6c6929..d4f3f1f255 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3926,7 +3926,8 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) numtowrite = SVAL(req->inbuf,smb_vwv10); smb_doff = SVAL(req->inbuf,smb_vwv11); smblen = smb_len(req->inbuf); - large_writeX = ((req->wct == 14) && (smblen > 0xFFFF)); + large_writeX = (req->wct == 14 && + (smblen > 0xFFFF || req->unread_bytes > 0xFFFF)); /* Deal with possible LARGE_WRITEX */ if (large_writeX) { -- cgit From bece9609cd633d69c2c8dc72fcb6c26c4f11f9f2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Nov 2007 22:24:39 -0700 Subject: Be careful and take care of the correct lengths in large writeX calls. Jeremy. (This used to be commit 2d3ff9c502105f92720131355b41e48be8d656c2) --- source3/smbd/reply.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d4f3f1f255..c83066d41e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3912,7 +3912,6 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) unsigned int smb_doff; unsigned int smblen; char *data; - bool large_writeX; NTSTATUS status; START_PROFILE(SMBwriteX); @@ -3926,12 +3925,11 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) numtowrite = SVAL(req->inbuf,smb_vwv10); smb_doff = SVAL(req->inbuf,smb_vwv11); smblen = smb_len(req->inbuf); - large_writeX = (req->wct == 14 && - (smblen > 0xFFFF || req->unread_bytes > 0xFFFF)); - /* Deal with possible LARGE_WRITEX */ - if (large_writeX) { - numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16); + if (req->unread_bytes > 0xFFFF || + (smblen > smb_doff + 4 && + smblen - smb_doff + 4 > 0xFFFF)) { + numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16); } if (req->unread_bytes) { @@ -3941,7 +3939,8 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) return; } } else { - if (smb_doff > smblen || smb_doff + numtowrite > smblen) { + if (smb_doff + 4 > smblen || smb_doff + 4 + numtowrite < numtowrite || + smb_doff + 4 + numtowrite > smblen) { reply_doserror(req, ERRDOS, ERRbadmem); END_PROFILE(SMBwriteX); return; @@ -4032,8 +4031,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) reply_outbuf(req, 6, 0); SSVAL(req->outbuf,smb_vwv2,nwritten); - if (large_writeX) - SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1); + SSVAL(req->outbuf,smb_vwv4,nwritten>>16); if (nwritten < (ssize_t)numtowrite) { SCVAL(req->outbuf,smb_rcls,ERRHRD); -- cgit From 10500184bf7aac4c1036a807ad4f57d2016d7bd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 Nov 2007 22:42:21 -0700 Subject: Ensure we can't accidently do a pipe write with unread bytes in the socket buffer. Jeremy (This used to be commit 84d22f7747126608b9460f9591bb5967d871b82d) --- source3/smbd/reply.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c83066d41e..de0e852e2a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3949,6 +3949,11 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { + if (req->unread_bytes) { + reply_doserror(req, ERRDOS, ERRbadmem); + END_PROFILE(SMBwriteX); + return; + } reply_pipe_write_and_X(req); END_PROFILE(SMBwriteX); return; -- cgit From 414ab2ce46dd62d0119f03eca93783bc489af896 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Nov 2007 10:35:10 -0700 Subject: Argggh. smblen doesn't include the +4, so my smb_doff calculations shouldn't either :-). Jeremy. (This used to be commit c3de44b6b063e126095b30536fdcb643c70e395e) --- source3/smbd/reply.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index de0e852e2a..84c1892560 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3927,8 +3927,8 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) smblen = smb_len(req->inbuf); if (req->unread_bytes > 0xFFFF || - (smblen > smb_doff + 4 && - smblen - smb_doff + 4 > 0xFFFF)) { + (smblen > smb_doff && + smblen - smb_doff > 0xFFFF)) { numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16); } @@ -3939,8 +3939,8 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) return; } } else { - if (smb_doff + 4 > smblen || smb_doff + 4 + numtowrite < numtowrite || - smb_doff + 4 + numtowrite > smblen) { + if (smb_doff > smblen || smb_doff + numtowrite < numtowrite || + smb_doff + numtowrite > smblen) { reply_doserror(req, ERRDOS, ERRbadmem); END_PROFILE(SMBwriteX); return; -- cgit From 329365684bca99bf9020b6638a1357df65c1d938 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Nov 2007 12:21:34 -0700 Subject: Change the client library to write directly out of the incoming buffer in the non-signed case. Speeds up writes by over 10% or so. Complete the server recvfile implementation. Jeremy. (This used to be commit 81ca5853b2475f123faab3b550f0a7b24ae3c208) --- source3/smbd/reply.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 84c1892560..a7fa67df22 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3848,12 +3848,12 @@ void reply_write(connection_struct *conn, struct smb_request *req) (2*14) + /* word count (including bcc) */ \ 1 /* pad byte */) -bool is_valid_writeX_buffer(char *inbuf) +bool is_valid_writeX_buffer(const char *inbuf) { size_t numtowrite; connection_struct *conn = NULL; unsigned int doff = 0; - size_t len = smb_len(inbuf); + size_t len = smb_len_large(inbuf); if (CVAL(inbuf,smb_com) != SMBwriteX || CVAL(inbuf,smb_vwv0) != 0xFF || @@ -3867,14 +3867,19 @@ bool is_valid_writeX_buffer(char *inbuf) if (IS_IPC(conn)) { return false; } + doff = SVAL(inbuf,smb_vwv11); + numtowrite = SVAL(inbuf,smb_vwv10); - numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); + + if (len > doff && len - doff > 0xFFFF) { + numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16); + } + if (numtowrite == 0) { return false; } - /* Ensure the sizes match up. */ - doff = SVAL(inbuf,smb_vwv11); + /* Ensure the sizes match up. */ if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) { /* no pad byte...old smbclient :-( */ return false; -- cgit From 73d407968002587eadd0ff13eb413ddf07c78771 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Nov 2007 15:12:42 -0700 Subject: Remove the smb_read_error global variable and replace it with accessor functions. "One global or pstring a day...." :-). Jeremy. (This used to be commit d50d14c300abc83b7015718ec48acc8b3227a273) --- source3/smbd/nttrans.c | 1 - source3/smbd/oplock.c | 1 - source3/smbd/oplock_irix.c | 5 ++--- source3/smbd/process.c | 51 +++++++++++++++++----------------------------- source3/smbd/trans2.c | 1 - 5 files changed, 21 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index da926d1bce..4bd4571171 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -22,7 +22,6 @@ extern int max_send; extern enum protocol_types Protocol; -extern int smb_read_error; extern struct current_user current_user; static const char *known_nt_pipes[] = { diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index a84a9dbcb9..961abd277b 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -28,7 +28,6 @@ static int32 level_II_oplocks_open = 0; bool global_client_failed_oplock_break = False; extern uint32 global_client_caps; -extern int smb_read_error; static struct kernel_oplocks *koplocks; diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 8dd4e27973..b8d49f03a1 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -104,7 +104,6 @@ static bool irix_oplocks_available(void) static files_struct *irix_oplock_receive_message(fd_set *fds) { - extern int smb_read_error; oplock_stat_t os; char dummy; struct file_id fileid; @@ -122,7 +121,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) DEBUG(0,("irix_oplock_receive_message: read of kernel " "notification failed. Error was %s.\n", strerror(errno) )); - smb_read_error = READ_ERROR; + set_smb_read_error(SMB_READ_ERROR); return NULL; } @@ -142,7 +141,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) */ return NULL; } - smb_read_error = READ_ERROR; + set_smb_read_error(SMB_READ_ERROR); return NULL; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index eca51a74a3..11fdb03d72 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -22,7 +22,6 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; -extern int smb_read_error; const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); @@ -39,7 +38,6 @@ int max_send = BUFFER_SIZE; int max_recv = BUFFER_SIZE; extern int last_message; -extern int smb_read_error; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; extern bool global_machine_password_needs_changing; @@ -65,8 +63,7 @@ static bool valid_packet_size(len) * variables still suck :-). JRA. */ - if (smb_read_error == 0) - smb_read_error = READ_ERROR; + cond_set_smb_read_error(SMB_READ_ERROR); return false; } } @@ -95,9 +92,7 @@ static ssize_t read_packet_remainder(int fd, } if (ret != len) { - if (smb_read_error == 0) { - smb_read_error = READ_ERROR; - } + cond_set_smb_read_error(SMB_READ_ERROR); return -1; } @@ -148,9 +143,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, } if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { - if (smb_read_error == 0) { - smb_read_error = READ_ERROR; - } + cond_set_smb_read_error(SMB_READ_ERROR); return -1; } @@ -190,8 +183,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)sizeof(writeX_header))); - if (smb_read_error == 0) - smb_read_error = READ_ERROR; + cond_set_smb_read_error(SMB_READ_ERROR); return -1; } @@ -215,8 +207,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - if (smb_read_error == 0) - smb_read_error = READ_ERROR; + cond_set_smb_read_error(SMB_READ_ERROR); return -1; } @@ -249,7 +240,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, ssize_t len,ret; int min_recv_size = lp_min_receive_file_size(); - smb_read_error = 0; + set_smb_read_error(SMB_READ_OK); *p_unread = 0; len = read_smb_length_return_keepalive(fd, lenbuf, timeout); @@ -262,8 +253,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, * variables still suck :-). JRA. */ - if (smb_read_error == 0) - smb_read_error = READ_ERROR; + cond_set_smb_read_error(SMB_READ_ERROR); return -1; } @@ -293,8 +283,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - if (smb_read_error == 0) - smb_read_error = READ_ERROR; + cond_set_smb_read_error(SMB_READ_ERROR); return -1; } @@ -323,9 +312,7 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, if (!srv_check_sign_mac(*buffer, true)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " "incoming packet!\n")); - if (smb_read_error == 0) { - smb_read_error = READ_BAD_SIG; - } + cond_set_smb_read_error(SMB_READ_BAD_SIG); return -1; } @@ -695,7 +682,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, ssize_t len; *p_unread = 0; - smb_read_error = 0; + set_smb_read_error(SMB_READ_OK); again: @@ -749,7 +736,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, msg->buf.length); if (*buffer == NULL) { DEBUG(0, ("talloc failed\n")); - smb_read_error = READ_ERROR; + set_smb_read_error(SMB_READ_ERROR); return False; } *buffer_len = msg->buf.length; @@ -843,13 +830,13 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, /* Check if error */ if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; + set_smb_read_error(SMB_READ_ERROR); return False; } /* Did we timeout ? */ if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; + set_smb_read_error(SMB_READ_TIMEOUT); return False; } @@ -1835,20 +1822,20 @@ static bool timeout_processing(int *select_timeout, { time_t t; - if (smb_read_error == READ_EOF) { + if (get_smb_read_error() == SMB_READ_EOF) { DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); - return False; + return false; } - if (smb_read_error == READ_ERROR) { + if (get_smb_read_error() == SMB_READ_ERROR) { DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", strerror(errno))); - return False; + return false; } - if (smb_read_error == READ_BAD_SIG) { + if (get_smb_read_error() == SMB_READ_BAD_SIG) { DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); - return False; + return false; } *last_timeout_processing_time = t = time(NULL); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c9ea02969b..dfd926ace9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -27,7 +27,6 @@ extern int max_send; extern enum protocol_types Protocol; -extern int smb_read_error; extern uint32 global_client_caps; extern struct current_user current_user; -- cgit From 6658165d5e9cd186fea74e1581091233e8990e9b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Nov 2007 18:15:45 -0700 Subject: Stop get_peer_addr() and client_addr() from using global statics. Part of my library cleanups. Jeremy. (This used to be commit e848506c858bd16706c1d7f6b4b032005512b8ac) --- source3/smbd/connection.c | 3 ++- source3/smbd/process.c | 5 ++++- source3/smbd/server.c | 4 +++- source3/smbd/service.c | 6 ++++-- source3/smbd/session.c | 5 +++-- source3/smbd/sesssetup.c | 4 +++- 6 files changed, 19 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index e9f1b82fbf..4b89668640 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -128,6 +128,7 @@ bool claim_connection(connection_struct *conn, const char *name, struct connections_data crec; TDB_DATA dbuf; NTSTATUS status; + char addr[INET6_ADDRSTRLEN]; DEBUG(5,("claiming [%s]\n", name)); @@ -151,7 +152,7 @@ bool claim_connection(connection_struct *conn, const char *name, crec.bcast_msg_flags = msg_flags; strlcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)); - strlcpy(crec.addr,conn?conn->client_address:client_addr(), + strlcpy(crec.addr,conn?conn->client_address:client_addr(addr), sizeof(crec.addr)); dbuf.dptr = (uint8 *)&crec; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 11fdb03d72..f35e7054d7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1460,15 +1460,18 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes) DO_PROFILE_INC(smb_count); if (trans_num == 0) { + char addr[INET6_ADDRSTRLEN]; + /* on the first packet, check the global hosts allow/ hosts deny parameters before doing any parsing of the packet passed to us by the client. This prevents attacks on our parsing code from hosts not in the hosts allow list */ + if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { /* send a negative session response "not listening on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) ); + DEBUG( 1, ( "Connection denied from %s\n", client_addr(addr) ) ); (void)send_smb(smbd_server_fd(),(char *)buf); exit_server_cleanly("connection denied"); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index fa8e163081..34b3d4a32a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -602,6 +602,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && ((child = sys_fork())==0)) { + char remaddr[INET6_ADDRSTRLEN]; + /* Child code ... */ /* Stop zombies, the parent explicitly handles @@ -622,7 +624,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* this is needed so that we get decent entries in smbstatus for port 445 connects */ - set_remote_machine_name(get_peer_addr(smbd_server_fd()), + set_remote_machine_name(get_peer_addr(smbd_server_fd(),remaddr), False); /* Reset the state of the random diff --git a/source3/smbd/service.c b/source3/smbd/service.c index bb279b701f..2901cd3417 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -642,6 +642,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, fstring user; fstring dev; int ret; + char addr[INET6_ADDRSTRLEN]; *user = 0; fstrcpy(dev, pdev); @@ -757,7 +758,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, add_session_user(user); - safe_strcpy(conn->client_address, client_addr(), + safe_strcpy(conn->client_address, client_addr(addr), sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = conn->lastused_count = time(NULL); @@ -1204,6 +1205,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstring service; fstring dev; int snum = -1; + char addr[INET6_ADDRSTRLEN]; fstrcpy(dev, pdev); @@ -1300,7 +1302,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } DEBUG(0,("%s (%s) couldn't find service %s\n", - get_remote_machine_name(), client_addr(), service)); + get_remote_machine_name(), client_addr(addr), service)); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index ebbb40eb5a..15154162b9 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -69,6 +69,7 @@ bool session_claim(user_struct *vuser) struct db_context *ctx; struct db_record *rec; NTSTATUS status; + char addr[INET6_ADDRSTRLEN]; vuser->session_keystr = NULL; @@ -160,7 +161,7 @@ bool session_claim(user_struct *vuser) hostname = client_name(); if (strcmp(hostname, "UNKNOWN") == 0) { - hostname = client_addr(); + hostname = client_addr(addr); } fstrcpy(sessionid.username, vuser->user.unix_name); @@ -170,7 +171,7 @@ bool session_claim(user_struct *vuser) sessionid.uid = vuser->uid; sessionid.gid = vuser->gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); - fstrcpy(sessionid.ip_addr_str, client_addr()); + fstrcpy(sessionid.ip_addr_str, client_addr(addr)); sessionid.connect_start = time(NULL); if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index bc298d11f7..35efbc009f 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1307,6 +1307,8 @@ static int shutdown_other_smbds(struct db_record *rec, static void setup_new_vc_session(void) { + char addr[INET6_ADDRSTRLEN]; + DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x " "compatible we would close all old resources.\n")); #if 0 @@ -1315,7 +1317,7 @@ static void setup_new_vc_session(void) #endif if (lp_reset_on_zero_vc()) { connections_forall(shutdown_other_smbds, - CONST_DISCARD(void *,client_addr())); + CONST_DISCARD(void *,client_addr(addr))); } } -- cgit From 25074433f412c4dd2531fd268d51be8753ddc11b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Nov 2007 18:41:26 -0700 Subject: I can't get away without a 'length' arg. :-). Jeremy. (This used to be commit 95d01279a5def709d0a5d5ae7224d6286006d120) --- source3/smbd/connection.c | 2 +- source3/smbd/process.c | 3 ++- source3/smbd/server.c | 6 ++++-- source3/smbd/service.c | 6 ++++-- source3/smbd/session.c | 4 ++-- source3/smbd/sesssetup.c | 3 ++- 6 files changed, 15 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 4b89668640..f041513820 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -152,7 +152,7 @@ bool claim_connection(connection_struct *conn, const char *name, crec.bcast_msg_flags = msg_flags; strlcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)); - strlcpy(crec.addr,conn?conn->client_address:client_addr(addr), + strlcpy(crec.addr,conn?conn->client_address:client_addr(addr,sizeof(addr)), sizeof(crec.addr)); dbuf.dptr = (uint8 *)&crec; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f35e7054d7..24feac4630 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1471,7 +1471,8 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes) lp_hostsdeny(-1))) { /* send a negative session response "not listening on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG( 1, ( "Connection denied from %s\n", client_addr(addr) ) ); + DEBUG( 1, ( "Connection denied from %s\n", + client_addr(addr,sizeof(addr)) ) ); (void)send_smb(smbd_server_fd(),(char *)buf); exit_server_cleanly("connection denied"); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 34b3d4a32a..e77573b9c6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -624,8 +624,10 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* this is needed so that we get decent entries in smbstatus for port 445 connects */ - set_remote_machine_name(get_peer_addr(smbd_server_fd(),remaddr), - False); + set_remote_machine_name(get_peer_addr(smbd_server_fd(), + remaddr, + sizeof(remaddr)), + false); /* Reset the state of the random * number generation system, so diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2901cd3417..502fadedc7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -758,7 +758,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, add_session_user(user); - safe_strcpy(conn->client_address, client_addr(addr), + safe_strcpy(conn->client_address, client_addr(addr,sizeof(addr)), sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = conn->lastused_count = time(NULL); @@ -1302,7 +1302,9 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } DEBUG(0,("%s (%s) couldn't find service %s\n", - get_remote_machine_name(), client_addr(addr), service)); + get_remote_machine_name(), + client_addr(addr,sizeof(addr)), + service)); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 15154162b9..69f4a37c85 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -161,7 +161,7 @@ bool session_claim(user_struct *vuser) hostname = client_name(); if (strcmp(hostname, "UNKNOWN") == 0) { - hostname = client_addr(addr); + hostname = client_addr(addr,sizeof(addr)); } fstrcpy(sessionid.username, vuser->user.unix_name); @@ -171,7 +171,7 @@ bool session_claim(user_struct *vuser) sessionid.uid = vuser->uid; sessionid.gid = vuser->gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); - fstrcpy(sessionid.ip_addr_str, client_addr(addr)); + fstrcpy(sessionid.ip_addr_str, client_addr(addr,sizeof(addr))); sessionid.connect_start = time(NULL); if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 35efbc009f..87cb3b435b 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1317,7 +1317,8 @@ static void setup_new_vc_session(void) #endif if (lp_reset_on_zero_vc()) { connections_forall(shutdown_other_smbds, - CONST_DISCARD(void *,client_addr(addr))); + CONST_DISCARD(void *, + client_addr(addr,sizeof(addr)))); } } -- cgit From 5b0b4f23ef5fec3d1ad518237f973d4e014b5766 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 3 Nov 2007 23:20:10 -0700 Subject: Remove most of the remaining globals out of lib/util_sock.c. I have a plan for dealing with the remaining..... Watch this space. Jeremy. (This used to be commit 963fc7685212689f02b3adcc05b4273ee5c382d4) --- source3/smbd/connection.c | 3 ++- source3/smbd/process.c | 2 +- source3/smbd/server.c | 5 ++++- source3/smbd/service.c | 7 ++++--- source3/smbd/session.c | 7 ++++--- source3/smbd/sesssetup.c | 4 ++-- 6 files changed, 17 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index f041513820..95e45a6990 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -152,7 +152,8 @@ bool claim_connection(connection_struct *conn, const char *name, crec.bcast_msg_flags = msg_flags; strlcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)); - strlcpy(crec.addr,conn?conn->client_address:client_addr(addr,sizeof(addr)), + strlcpy(crec.addr,conn?conn->client_address: + client_addr(get_client_fd(),addr,sizeof(addr)), sizeof(crec.addr)); dbuf.dptr = (uint8 *)&crec; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 24feac4630..aa39b01258 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1472,7 +1472,7 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes) /* send a negative session response "not listening on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", - client_addr(addr,sizeof(addr)) ) ); + client_addr(get_client_fd(),addr,sizeof(addr)) ) ); (void)send_smb(smbd_server_fd(),(char *)buf); exit_server_cleanly("connection denied"); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e77573b9c6..fbf886ee67 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -59,9 +59,12 @@ int smbd_server_fd(void) static void smbd_set_server_fd(int fd) { server_fd = fd; - client_setfd(fd); } +int get_client_fd(void) +{ + return server_fd; +} struct event_context *smbd_event_context(void) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 502fadedc7..2402be3aed 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -758,8 +758,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, add_session_user(user); - safe_strcpy(conn->client_address, client_addr(addr,sizeof(addr)), - sizeof(conn->client_address)-1); + safe_strcpy(conn->client_address, + client_addr(get_client_fd(),addr,sizeof(addr)), + sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = conn->lastused_count = time(NULL); conn->used = True; @@ -1303,7 +1304,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, DEBUG(0,("%s (%s) couldn't find service %s\n", get_remote_machine_name(), - client_addr(addr,sizeof(addr)), + client_addr(get_client_fd(),addr,sizeof(addr)), service)); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 69f4a37c85..000b2f5d9c 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -159,9 +159,9 @@ bool session_claim(user_struct *vuser) client_name() handles this case internally. */ - hostname = client_name(); + hostname = client_name(get_client_fd()); if (strcmp(hostname, "UNKNOWN") == 0) { - hostname = client_addr(addr,sizeof(addr)); + hostname = client_addr(get_client_fd(),addr,sizeof(addr)); } fstrcpy(sessionid.username, vuser->user.unix_name); @@ -171,7 +171,8 @@ bool session_claim(user_struct *vuser) sessionid.uid = vuser->uid; sessionid.gid = vuser->gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); - fstrcpy(sessionid.ip_addr_str, client_addr(addr,sizeof(addr))); + fstrcpy(sessionid.ip_addr_str, + client_addr(get_client_fd(),addr,sizeof(addr))); sessionid.connect_start = time(NULL); if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 87cb3b435b..0e8483c81e 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1317,8 +1317,8 @@ static void setup_new_vc_session(void) #endif if (lp_reset_on_zero_vc()) { connections_forall(shutdown_other_smbds, - CONST_DISCARD(void *, - client_addr(addr,sizeof(addr)))); + CONST_DISCARD(void *, + client_addr(get_client_fd(),addr,sizeof(addr)))); } } -- cgit From 4721050df5dd268fbb99199c17071c2b05c61e1f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 4 Nov 2007 15:38:43 -0800 Subject: Don't believe len returned from read_smb_length_return_keepalive(), it may be a UNIX large writeX (which wraps len in that case). Stevef this should fix your 128k write bug. Jeremy. (This used to be commit de2ebffa3c99ed28a3868fd956ef45629ca855b6) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index aa39b01258..659b7b55e9 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -259,7 +259,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, if (CVAL(lenbuf,0) != SMBkeepalive && min_recv_size && - len > min_recv_size && + smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */ !srv_is_signing_active()) { return receive_smb_raw_talloc_partial_read(mem_ctx, -- cgit From 58fbb512cc7a26471a2aae88425de4d337258e3a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 4 Nov 2007 17:15:35 -0800 Subject: Forgot arg type. Jeremy. (This used to be commit 46f3b04ddea4c63c6b37c7038d4bbd2ee1c9ca0c) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 659b7b55e9..7d6455621f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -45,7 +45,7 @@ extern int max_send; /* Socket functions for smbd packet processing. */ -static bool valid_packet_size(len) +static bool valid_packet_size(size_t len) { /* * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes -- cgit From ec1ecd92c914048a72a61b373a1c6d8507d0e92f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Nov 2007 15:03:26 +0100 Subject: Make load_registry_service return the share number (This used to be commit 934964c90f39d588d2399f10e3738ab1b4e01290) --- source3/smbd/service.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2402be3aed..2cd3363cf6 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -312,7 +312,6 @@ static int load_registry_service(const char *servicename) TALLOC_FREE(value); } - res = 0; error: TALLOC_FREE(key); -- cgit From 082da3d287558dcebcb1e3468ad05eeb7c75ef8c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 30 Oct 2007 22:58:09 +0100 Subject: Fix a debug message (This used to be commit a86849e4f9512b680f26010c297cec14251dafdd) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dfd926ace9..3abc0d065c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -144,7 +144,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str return False; } - DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret)); + DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret)); dump_data(10, (uint8 *)val, sizeret); pea->flags = 0; -- cgit From 36441da4240f3e3a296eed65f0796b25b7b05a3a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Nov 2007 11:12:56 -0800 Subject: Remove the horror that was the global smb_rw_error. Each cli struct has it's own local copy of this variable, so use that in client code. In the smbd server, add one static to smbd/proccess.c and use that inside smbd. Fix a bunch of places where smb_rw_error could be set by calling read_data() in places where we weren't reading from the SMB client socket (ie. winbindd). Jeremy. (This used to be commit 255c2adf7b6ef30932b5bb9f142ccef4a5d3d0db) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/process.c | 59 +++++++++++++++++++++++++++++++----------------- source3/smbd/reply.c | 5 ++-- 3 files changed, 42 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fb6e6c0f09..d89442150f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -256,7 +256,7 @@ static int expect(int master, char *issue, char *expected) while ((len = read_socket_with_timeout(master, buffer + nread, 1, sizeof(buffer) - nread - 1, - timeout)) > 0) { + timeout, NULL)) > 0) { nread += len; buffer[nread] = 0; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7d6455621f..24497de69a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -24,6 +24,7 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); +static enum smb_read_errors smb_read_error = SMB_READ_OK; /* * Size of data we can send to client. Set @@ -43,6 +44,13 @@ SIG_ATOMIC_T got_sig_term = 0; extern bool global_machine_password_needs_changing; extern int max_send; +/* Accessor function for smb_read_error for smbd functions. */ + +enum smb_read_errors *get_srv_read_error(void) +{ + return &smb_read_error; +} + /* Socket functions for smbd packet processing. */ static bool valid_packet_size(size_t len) @@ -63,7 +71,8 @@ static bool valid_packet_size(size_t len) * variables still suck :-). JRA. */ - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return false; } } @@ -86,13 +95,15 @@ static ssize_t read_packet_remainder(int fd, buffer, len, len, - timeout); + timeout, + get_srv_read_error()); } else { - ret = read_data(fd, buffer, len); + ret = read_data(fd, buffer, len, get_srv_read_error()); } if (ret != len) { - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -135,15 +146,18 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, writeX_header + 4, STANDARD_WRITE_AND_X_HEADER_SIZE, STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout); + timeout, + get_srv_read_error()); } else { ret = read_data(fd, writeX_header+4, - STANDARD_WRITE_AND_X_HEADER_SIZE); + STANDARD_WRITE_AND_X_HEADER_SIZE, + get_srv_read_error()); } if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -183,7 +197,8 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)sizeof(writeX_header))); - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -207,7 +222,8 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -240,10 +256,11 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, ssize_t len,ret; int min_recv_size = lp_min_receive_file_size(); - set_smb_read_error(SMB_READ_OK); + set_smb_read_error(get_srv_read_error(),SMB_READ_OK); *p_unread = 0; - len = read_smb_length_return_keepalive(fd, lenbuf, timeout); + len = read_smb_length_return_keepalive(fd, lenbuf, + timeout, get_srv_read_error()); if (len < 0) { DEBUG(10,("receive_smb_raw: length < 0!\n")); @@ -253,7 +270,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, * variables still suck :-). JRA. */ - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return -1; } @@ -283,7 +300,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return -1; } @@ -312,7 +329,7 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, if (!srv_check_sign_mac(*buffer, true)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " "incoming packet!\n")); - cond_set_smb_read_error(SMB_READ_BAD_SIG); + cond_set_smb_read_error(get_srv_read_error(),SMB_READ_BAD_SIG); return -1; } @@ -682,7 +699,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, ssize_t len; *p_unread = 0; - set_smb_read_error(SMB_READ_OK); + set_smb_read_error(get_srv_read_error(),SMB_READ_OK); again: @@ -736,7 +753,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, msg->buf.length); if (*buffer == NULL) { DEBUG(0, ("talloc failed\n")); - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return False; } *buffer_len = msg->buf.length; @@ -830,13 +847,13 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, /* Check if error */ if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return False; } /* Did we timeout ? */ if (selrtn == 0) { - set_smb_read_error(SMB_READ_TIMEOUT); + set_smb_read_error(get_srv_read_error(),SMB_READ_TIMEOUT); return False; } @@ -1826,18 +1843,18 @@ static bool timeout_processing(int *select_timeout, { time_t t; - if (get_smb_read_error() == SMB_READ_EOF) { + if (*get_srv_read_error() == SMB_READ_EOF) { DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); return false; } - if (get_smb_read_error() == SMB_READ_ERROR) { + if (*get_srv_read_error() == SMB_READ_ERROR) { DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", strerror(errno))); return false; } - if (get_smb_read_error() == SMB_READ_BAD_SIG) { + if (*get_srv_read_error() == SMB_READ_BAD_SIG) { DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); return false; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a7fa67df22..1b36fb1e44 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3535,7 +3535,8 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) } /* Now read the raw data into the buffer and write it */ - if (read_smb_length(smbd_server_fd(),buf,SMB_SECONDARY_WAIT) == -1) { + if (read_smb_length(smbd_server_fd(),buf, + SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) { exit_server_cleanly("secondary writebraw failed"); } @@ -3564,7 +3565,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) (int)tcount,(int)nwritten,(int)numtowrite)); } - if (read_data(smbd_server_fd(), buf+4, numtowrite) + if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error()) != numtowrite ) { DEBUG(0,("reply_writebraw: Oversize secondary write " "raw read failed (%s). Terminating\n", -- cgit From 3fd2d4ed856bc4fa053e1c03926ca71bb4ab1a9f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 5 Nov 2007 23:23:05 +0100 Subject: Add two const's. Michael (This used to be commit bf23c4ddff617dd3cd1e2d5cedb1b5c023356dc3) --- source3/smbd/posix_acls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b8afbb8710..7f03d7ebc5 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1081,7 +1081,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, const files_struct *fsp, const DOM_SID *pfile_owner_sid, const DOM_SID *pfile_grp_sid, - SMB_STRUCT_STAT *pst, + const SMB_STRUCT_STAT *pst, bool setting_acl) { canon_ace *pace; @@ -2066,7 +2066,7 @@ static bool unpack_canon_ace(files_struct *fsp, But NT cannot display this in their ACL editor ! ********************************************************************************/ -static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) +static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head) { canon_ace *list_head = *pp_list_head; canon_ace *owner_ace = NULL; -- cgit From 1fd78e226b503a1bce412ad6adbadc4c30a5f6e6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 6 Nov 2007 06:31:24 +0100 Subject: Add a const. Michael (This used to be commit 7b582af2107bed3b864bb408b5c9bcce4b8e4c72) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7f03d7ebc5..6422badf63 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -662,7 +662,7 @@ static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_AC Function to create owner and group SIDs from a SMB_STRUCT_STAT. ****************************************************************************/ -static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) +static void create_file_sids(const SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) { uid_to_sid( powner_sid, psbuf->st_uid ); gid_to_sid( pgroup_sid, psbuf->st_gid ); -- cgit From dbfee4efbf12802986f2ed3daad300ee6cfa982e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 20 Oct 2007 02:17:07 +0200 Subject: This is a proposed patch for Bug #5023. The three can_* access check functions in smbd/posix_acls.c that are used in smbd/open.c and smbd/nttrans.c explicitly called check_posix_acl_group_access() This lead to errors with nfsv4 acls (ZFS and GPFS). This changes the can_* functions to get the nt_acl via VFS layer and call se_access_check on that. It also removes check_posix_acl_group_access() which has no more callers. NOTE: The can_* functions should really not be in smbd/posix_acls.c but in a separate file (I propose smbd/access.c). Michael (This used to be commit 6f961a23de745aba5dcd4585b731e651b8cbeef4) --- source3/smbd/posix_acls.c | 370 +++++++++------------------------------------- 1 file changed, 70 insertions(+), 300 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6422badf63..e319a55249 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4126,291 +4126,82 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * } /**************************************************************************** - Check for POSIX group ACLs. If none use stat entry. - Return -1 if no match, 0 if match and denied, 1 if match and allowed. + Helper function that gets a security descriptor by connection and + file name. + NOTE: This is transitional, in the sense that SMB_VFS_GET_NT_ACL really + should *not* get a files_struct pointer but a connection_struct ptr + (automatic by the vfs handle) and the file name and _use_ that! ****************************************************************************/ - -static int check_posix_acl_group_access(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) +static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, + struct connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **psd) { - SMB_ACL_T posix_acl = NULL; - int entry_id = SMB_ACL_FIRST_ENTRY; - SMB_ACL_ENTRY_T entry; - int i; - bool seen_mask = False; - bool seen_owning_group = False; - int ret = -1; - gid_t cu_gid; - - DEBUG(10,("check_posix_acl_group_access: requesting 0x%x on file %s\n", - (unsigned int)access_mask, fname )); - - if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS)) == NULL) { - goto check_stat; - } - - /* First ensure the group mask allows group access. */ - /* Also check any user entries (these take preference over group). */ - - while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { - SMB_ACL_TAG_T tagtype; - SMB_ACL_PERMSET_T permset; - int have_write = -1; - int have_read = -1; - - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; - - if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) { - goto check_stat; - } - - if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { - goto check_stat; - } - - have_read = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ); - if (have_read == -1) { - goto check_stat; - } + NTSTATUS status; + struct files_struct *fsp = NULL; + struct security_descriptor *secdesc = NULL; + size_t secdesc_size; - have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE); - if (have_write == -1) { - goto check_stat; + if (!VALID_STAT(*psbuf)) { + if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { + return map_nt_error_from_unix(errno); } + } - /* - * Solaris returns 2 for this if write is available. - * canonicalize to 0 or 1. - */ - have_write = (have_write ? 1 : 0); - have_read = (have_read ? 1 : 0); + /* fake a files_struct ptr: */ - switch(tagtype) { - case SMB_ACL_MASK: - seen_mask = True; - switch (access_mask) { - case FILE_READ_DATA: - if (!have_read) { - ret = -1; - DEBUG(10,("check_posix_acl_group_access: file %s " - "refusing read due to mask.\n", fname)); - goto done; - } - break; - case FILE_WRITE_DATA: - if (!have_write) { - ret = -1; - DEBUG(10,("check_posix_acl_group_access: file %s " - "refusing write due to mask.\n", fname)); - goto done; - } - break; - default: /* FILE_READ_DATA|FILE_WRITE_DATA */ - if (!have_write || !have_read) { - ret = -1; - DEBUG(10,("check_posix_acl_group_access: file %s " - "refusing read/write due to mask.\n", fname)); - goto done; - } - break; - } - break; - case SMB_ACL_USER: - { - /* Check against current_user.ut.uid. */ - uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); - if (puid == NULL) { - goto check_stat; - } - if (current_user.ut.uid == *puid) { - /* We have a uid match but we must ensure we have seen the acl mask. */ - switch (access_mask) { - case FILE_READ_DATA: - ret = have_read; - break; - case FILE_WRITE_DATA: - ret = have_write; - break; - default: /* FILE_READ_DATA|FILE_WRITE_DATA */ - ret = (have_write & have_read); - break; - } - DEBUG(10,("check_posix_acl_group_access: file %s " - "match on user %u -> %s.\n", - fname, (unsigned int)*puid, - ret ? "can access" : "cannot access")); - if (seen_mask) { - goto done; - } - } - break; - } - default: - continue; - } + status = open_file_stat(conn, NULL, fname, psbuf, &fsp); + /* Perhaps it is a directory */ + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + status = open_directory(conn, NULL, fname, psbuf, + READ_CONTROL_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_DIRECTORY, + NULL, &fsp); } - - /* If ret is anything other than -1 we matched on a user entry. */ - if (ret != -1) { - goto done; + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Unable to open file %s: %s\n", fname, + nt_errstr(status))); + return status; } - /* Next check all group entries. */ - entry_id = SMB_ACL_FIRST_ENTRY; - while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { - SMB_ACL_TAG_T tagtype; - SMB_ACL_PERMSET_T permset; - int have_write = -1; - int have_read = -1; - - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; - - if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) { - goto check_stat; - } - - if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) { - goto check_stat; - } - - have_read = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ); - if (have_read == -1) { - goto check_stat; - } - - have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE); - if (have_write == -1) { - goto check_stat; - } - - /* - * Solaris returns 2 for this if write is available. - * canonicalize to 0 or 1. - */ - have_write = (have_write ? 1 : 0); - have_read = (have_read ? 1 : 0); - - switch(tagtype) { - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - { - gid_t *pgid = NULL; - - if (tagtype == SMB_ACL_GROUP) { - pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); - } else { - seen_owning_group = True; - pgid = &psbuf->st_gid; - } - if (pgid == NULL) { - goto check_stat; - } - - /* - * Does it match the current effective group - * or supplementary groups ? - */ - for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; - cu_gid = get_current_user_gid_next(&i)) { - if (cu_gid == *pgid) { - switch (access_mask) { - case FILE_READ_DATA: - ret = have_read; - break; - case FILE_WRITE_DATA: - ret = have_write; - break; - default: /* FILE_READ_DATA|FILE_WRITE_DATA */ - ret = (have_write & have_read); - break; - } - - DEBUG(10,("check_posix_acl_group_access: file %s " - "match on group %u -> can access.\n", - fname, (unsigned int)cu_gid )); - - /* If we don't have access permission this entry doesn't - terminate the enumeration of the entries. */ - if (ret) { - goto done; - } - /* But does terminate the group iteration. */ - break; - } - } - break; - } - default: - continue; - } + secdesc_size = SMB_VFS_GET_NT_ACL(fsp, fname, + (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION), + &secdesc); + if (secdesc_size == 0) { + DEBUG(5, ("Unable to get NT ACL for file %s\n", fname)); + return NT_STATUS_ACCESS_DENIED; } - /* If ret is -1 here we didn't match on the user entry or - supplemental group entries. */ - - DEBUG(10,("check_posix_acl_group_access: ret = %d before check_stat:\n", ret)); - - check_stat: - - /* - * We only check the S_I[RW]GRP permissions if we haven't already - * seen an owning group SMB_ACL_GROUP_OBJ ace entry. If there is an - * SMB_ACL_GROUP_OBJ ace entry then the group bits in st_gid are - * the same as the SMB_ACL_MASK bits, not the SMB_ACL_GROUP_OBJ - * bits. Thanks to Marc Cousin for pointing - * this out. JRA. - */ - - if (!seen_owning_group) { - /* Do we match on the owning group entry ? */ - /* - * Does it match the current effective group - * or supplementary groups ? - */ - for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; - cu_gid = get_current_user_gid_next(&i)) { - if (cu_gid == psbuf->st_gid) { - switch (access_mask) { - case FILE_READ_DATA: - ret = (psbuf->st_mode & S_IRGRP) ? 1 : 0; - break; - case FILE_WRITE_DATA: - ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; - break; - default: /* FILE_READ_DATA|FILE_WRITE_DATA */ - if ((psbuf->st_mode & (S_IWGRP|S_IRGRP)) == (S_IWGRP|S_IRGRP)) { - ret = 1; - } else { - ret = 0; - } - break; - } - DEBUG(10,("check_posix_acl_group_access: file %s " - "match on owning group %u -> %s.\n", - fname, (unsigned int)psbuf->st_gid, - ret ? "can access" : "cannot access")); - break; - } - } - - if (cu_gid == (gid_t)-1) { - DEBUG(10,("check_posix_acl_group_access: file %s " - "failed to match on user or group in token (ret = %d).\n", - fname, ret )); - } - } + *psd = talloc_move(mem_ctx, &secdesc); + close_file(fsp, NORMAL_CLOSE); + return NT_STATUS_OK; +} - done: +static bool can_access_file_acl(struct connection_struct *conn, + const char * fname, SMB_STRUCT_STAT *psbuf, + uint32_t access_mask) +{ + bool result; + NTSTATUS status; + uint32_t access_granted; + struct security_descriptor *secdesc = NULL; - if (posix_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); + status = conn_get_nt_acl(talloc_tos(), conn, fname, psbuf, &secdesc); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status))); + return false; } - DEBUG(10,("check_posix_acl_group_access: file %s returning (ret = %d).\n", fname, ret )); - return ret; + result = se_access_check(secdesc, current_user.nt_user_token, + access_mask, &access_granted, &status); + TALLOC_FREE(secdesc); + return result; } /**************************************************************************** @@ -4423,7 +4214,6 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) SMB_STRUCT_STAT sbuf; TALLOC_CTX *ctx = talloc_tos(); char *dname = NULL; - int ret; if (!CAN_WRITE(conn)) { return False; @@ -4439,6 +4229,9 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) { return False; } + + /* fast paths first */ + if (!S_ISDIR(sbuf.st_mode)) { return False; } @@ -4475,14 +4268,9 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) } #endif - /* Check group or explicit user acl entry write access. */ - ret = check_posix_acl_group_access(conn, dname, &sbuf, FILE_WRITE_DATA); - if (ret == 0 || ret == 1) { - return ret ? True : False; - } + /* now for ACL checks */ - /* Finally check other write access. */ - return (sbuf.st_mode & S_IWOTH) ? True : False; + return can_access_file(conn, dname, &sbuf, FILE_WRITE_DATA); } /**************************************************************************** @@ -4493,13 +4281,13 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) { - int ret; - if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) { return False; } access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA); + /* some fast paths first */ + DEBUG(10,("can_access_file: requesting 0x%x on file %s\n", (unsigned int)access_mask, fname )); @@ -4534,27 +4322,9 @@ bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT } } - /* Check group or explicit user acl entry access. */ - ret = check_posix_acl_group_access(conn, fname, psbuf, access_mask); - if (ret == 0 || ret == 1) { - return ret ? True : False; - } - - /* Finally check other access. */ - switch (access_mask) { - case FILE_READ_DATA: - return (psbuf->st_mode & S_IROTH) ? True : False; - - case FILE_WRITE_DATA: - return (psbuf->st_mode & S_IWOTH) ? True : False; - - default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + /* now for ACL checks */ - if ((psbuf->st_mode & (S_IWOTH|S_IROTH)) == (S_IWOTH|S_IROTH)) { - return True; - } - } - return False; + return can_access_file_acl(conn, fname, psbuf, access_mask); } /**************************************************************************** -- cgit From 754159ed9b28976f50adc4aa210cbfcac5217ce1 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 25 Oct 2007 13:32:56 +0200 Subject: Don't repeat fast-pathing... Michael (This used to be commit c61b4222d30288add216fac4da3cfaa537f5cd01) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index e319a55249..c29d56f524 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4270,7 +4270,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) /* now for ACL checks */ - return can_access_file(conn, dname, &sbuf, FILE_WRITE_DATA); + return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA); } /**************************************************************************** -- cgit From 7d899b5e7b7cd26d33fb1e9c9c8a63efabc4b093 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 26 Oct 2007 19:50:55 +0200 Subject: Move some access check functions that are not posix-acl specific to a new source file of their own. Michael (This used to be commit 9dd18bb534bca6b5de6cad9580b48681b36c0832) --- source3/smbd/file_access.c | 239 +++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/posix_acls.c | 212 ---------------------------------------- 2 files changed, 239 insertions(+), 212 deletions(-) create mode 100644 source3/smbd/file_access.c (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c new file mode 100644 index 0000000000..189fcbbce1 --- /dev/null +++ b/source3/smbd/file_access.c @@ -0,0 +1,239 @@ +/* + Unix SMB/CIFS implementation. + Check access to files based on security descriptors. + Copyright (C) Jeremy Allison 2005-2006. + Copyright (C) Michael Adam 2007. + + 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 3 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, see . +*/ + +#include "includes.h" + +extern struct current_user current_user; + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ACLS + +/**************************************************************************** + Helper function that gets a security descriptor by connection and + file name. + NOTE: This is transitional, in the sense that SMB_VFS_GET_NT_ACL really + should *not* get a files_struct pointer but a connection_struct ptr + (automatic by the vfs handle) and the file name and _use_ that! +****************************************************************************/ +static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, + struct connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor **psd) +{ + NTSTATUS status; + struct files_struct *fsp = NULL; + struct security_descriptor *secdesc = NULL; + size_t secdesc_size; + + if (!VALID_STAT(*psbuf)) { + if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { + return map_nt_error_from_unix(errno); + } + } + + /* fake a files_struct ptr: */ + + status = open_file_stat(conn, NULL, fname, psbuf, &fsp); + /* Perhaps it is a directory */ + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + status = open_directory(conn, NULL, fname, psbuf, + READ_CONTROL_ACCESS, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + FILE_ATTRIBUTE_DIRECTORY, + NULL, &fsp); + } + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Unable to open file %s: %s\n", fname, + nt_errstr(status))); + return status; + } + + secdesc_size = SMB_VFS_GET_NT_ACL(fsp, fname, + (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION), + &secdesc); + if (secdesc_size == 0) { + DEBUG(5, ("Unable to get NT ACL for file %s\n", fname)); + return NT_STATUS_ACCESS_DENIED; + } + + *psd = talloc_move(mem_ctx, &secdesc); + close_file(fsp, NORMAL_CLOSE); + return NT_STATUS_OK; +} + +static bool can_access_file_acl(struct connection_struct *conn, + const char * fname, SMB_STRUCT_STAT *psbuf, + uint32_t access_mask) +{ + bool result; + NTSTATUS status; + uint32_t access_granted; + struct security_descriptor *secdesc = NULL; + + status = conn_get_nt_acl(talloc_tos(), conn, fname, psbuf, &secdesc); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status))); + return false; + } + + result = se_access_check(secdesc, current_user.nt_user_token, + access_mask, &access_granted, &status); + TALLOC_FREE(secdesc); + return result; +} + +/**************************************************************************** + Actually emulate the in-kernel access checking for delete access. We need + this to successfully return ACCESS_DENIED on a file open for delete access. +****************************************************************************/ + +bool can_delete_file_in_directory(connection_struct *conn, const char *fname) +{ + SMB_STRUCT_STAT sbuf; + TALLOC_CTX *ctx = talloc_tos(); + char *dname = NULL; + + if (!CAN_WRITE(conn)) { + return False; + } + + /* Get the parent directory permission mask and owners. */ + if (!parent_dirname_talloc(ctx, + fname, + &dname, + NULL)) { + return False; + } + if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) { + return False; + } + + /* fast paths first */ + + if (!S_ISDIR(sbuf.st_mode)) { + return False; + } + if (current_user.ut.uid == 0 || conn->admin_user) { + /* I'm sorry sir, I didn't know you were root... */ + return True; + } + + /* Check primary owner write access. */ + if (current_user.ut.uid == sbuf.st_uid) { + return (sbuf.st_mode & S_IWUSR) ? True : False; + } + +#ifdef S_ISVTX + /* sticky bit means delete only by owner or root. */ + if (sbuf.st_mode & S_ISVTX) { + SMB_STRUCT_STAT sbuf_file; + if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { + if (errno == ENOENT) { + /* If the file doesn't already exist then + * yes we'll be able to delete it. */ + return True; + } + return False; + } + /* + * Patch from SATOH Fumiyasu + * for bug #3348. Don't assume owning sticky bit + * directory means write access allowed. + */ + if (current_user.ut.uid != sbuf_file.st_uid) { + return False; + } + } +#endif + + /* now for ACL checks */ + + return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA); +} + +/**************************************************************************** + Actually emulate the in-kernel access checking for read/write access. We need + this to successfully check for ability to write for dos filetimes. + Note this doesn't take into account share write permissions. +****************************************************************************/ + +bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) +{ + if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) { + return False; + } + access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA); + + /* some fast paths first */ + + DEBUG(10,("can_access_file: requesting 0x%x on file %s\n", + (unsigned int)access_mask, fname )); + + if (current_user.ut.uid == 0 || conn->admin_user) { + /* I'm sorry sir, I didn't know you were root... */ + return True; + } + + if (!VALID_STAT(*psbuf)) { + /* Get the file permission mask and owners. */ + if(SMB_VFS_STAT(conn, fname, psbuf) != 0) { + return False; + } + } + + /* Check primary owner access. */ + if (current_user.ut.uid == psbuf->st_uid) { + switch (access_mask) { + case FILE_READ_DATA: + return (psbuf->st_mode & S_IRUSR) ? True : False; + + case FILE_WRITE_DATA: + return (psbuf->st_mode & S_IWUSR) ? True : False; + + default: /* FILE_READ_DATA|FILE_WRITE_DATA */ + + if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) { + return True; + } else { + return False; + } + } + } + + /* now for ACL checks */ + + return can_access_file_acl(conn, fname, psbuf, access_mask); +} + +/**************************************************************************** + Userspace check for write access. + Note this doesn't take into account share write permissions. +****************************************************************************/ + +bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +{ + return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA); +} + diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c29d56f524..6e7dae4892 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4125,218 +4125,6 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * return True; } -/**************************************************************************** - Helper function that gets a security descriptor by connection and - file name. - NOTE: This is transitional, in the sense that SMB_VFS_GET_NT_ACL really - should *not* get a files_struct pointer but a connection_struct ptr - (automatic by the vfs handle) and the file name and _use_ that! -****************************************************************************/ -static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, - struct connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - struct security_descriptor **psd) -{ - NTSTATUS status; - struct files_struct *fsp = NULL; - struct security_descriptor *secdesc = NULL; - size_t secdesc_size; - - if (!VALID_STAT(*psbuf)) { - if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { - return map_nt_error_from_unix(errno); - } - } - - /* fake a files_struct ptr: */ - - status = open_file_stat(conn, NULL, fname, psbuf, &fsp); - /* Perhaps it is a directory */ - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - status = open_directory(conn, NULL, fname, psbuf, - READ_CONTROL_ACCESS, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_DIRECTORY, - NULL, &fsp); - } - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Unable to open file %s: %s\n", fname, - nt_errstr(status))); - return status; - } - - secdesc_size = SMB_VFS_GET_NT_ACL(fsp, fname, - (OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION), - &secdesc); - if (secdesc_size == 0) { - DEBUG(5, ("Unable to get NT ACL for file %s\n", fname)); - return NT_STATUS_ACCESS_DENIED; - } - - *psd = talloc_move(mem_ctx, &secdesc); - close_file(fsp, NORMAL_CLOSE); - return NT_STATUS_OK; -} - -static bool can_access_file_acl(struct connection_struct *conn, - const char * fname, SMB_STRUCT_STAT *psbuf, - uint32_t access_mask) -{ - bool result; - NTSTATUS status; - uint32_t access_granted; - struct security_descriptor *secdesc = NULL; - - status = conn_get_nt_acl(talloc_tos(), conn, fname, psbuf, &secdesc); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status))); - return false; - } - - result = se_access_check(secdesc, current_user.nt_user_token, - access_mask, &access_granted, &status); - TALLOC_FREE(secdesc); - return result; -} - -/**************************************************************************** - Actually emulate the in-kernel access checking for delete access. We need - this to successfully return ACCESS_DENIED on a file open for delete access. -****************************************************************************/ - -bool can_delete_file_in_directory(connection_struct *conn, const char *fname) -{ - SMB_STRUCT_STAT sbuf; - TALLOC_CTX *ctx = talloc_tos(); - char *dname = NULL; - - if (!CAN_WRITE(conn)) { - return False; - } - - /* Get the parent directory permission mask and owners. */ - if (!parent_dirname_talloc(ctx, - fname, - &dname, - NULL)) { - return False; - } - if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) { - return False; - } - - /* fast paths first */ - - if (!S_ISDIR(sbuf.st_mode)) { - return False; - } - if (current_user.ut.uid == 0 || conn->admin_user) { - /* I'm sorry sir, I didn't know you were root... */ - return True; - } - - /* Check primary owner write access. */ - if (current_user.ut.uid == sbuf.st_uid) { - return (sbuf.st_mode & S_IWUSR) ? True : False; - } - -#ifdef S_ISVTX - /* sticky bit means delete only by owner or root. */ - if (sbuf.st_mode & S_ISVTX) { - SMB_STRUCT_STAT sbuf_file; - if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { - if (errno == ENOENT) { - /* If the file doesn't already exist then - * yes we'll be able to delete it. */ - return True; - } - return False; - } - /* - * Patch from SATOH Fumiyasu - * for bug #3348. Don't assume owning sticky bit - * directory means write access allowed. - */ - if (current_user.ut.uid != sbuf_file.st_uid) { - return False; - } - } -#endif - - /* now for ACL checks */ - - return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA); -} - -/**************************************************************************** - Actually emulate the in-kernel access checking for read/write access. We need - this to successfully check for ability to write for dos filetimes. - Note this doesn't take into account share write permissions. -****************************************************************************/ - -bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) -{ - if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) { - return False; - } - access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA); - - /* some fast paths first */ - - DEBUG(10,("can_access_file: requesting 0x%x on file %s\n", - (unsigned int)access_mask, fname )); - - if (current_user.ut.uid == 0 || conn->admin_user) { - /* I'm sorry sir, I didn't know you were root... */ - return True; - } - - if (!VALID_STAT(*psbuf)) { - /* Get the file permission mask and owners. */ - if(SMB_VFS_STAT(conn, fname, psbuf) != 0) { - return False; - } - } - - /* Check primary owner access. */ - if (current_user.ut.uid == psbuf->st_uid) { - switch (access_mask) { - case FILE_READ_DATA: - return (psbuf->st_mode & S_IRUSR) ? True : False; - - case FILE_WRITE_DATA: - return (psbuf->st_mode & S_IWUSR) ? True : False; - - default: /* FILE_READ_DATA|FILE_WRITE_DATA */ - - if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) { - return True; - } else { - return False; - } - } - } - - /* now for ACL checks */ - - return can_access_file_acl(conn, fname, psbuf, access_mask); -} - -/**************************************************************************** - Userspace check for write access. - Note this doesn't take into account share write permissions. -****************************************************************************/ - -bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) -{ - return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA); -} - /******************************************************************** Pull the NT ACL from a file on disk or the OpenEventlog() access check. Caller is responsible for freeing the returned security -- cgit From 30a48a5c6c22484c6c06830e404242c1caa47d88 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 7 Nov 2007 22:28:26 +0100 Subject: Try to fix the build on irix. There were two callers of set_smb_read_error() in irix_oplocks.c not converted to the new prototype. Michael (This used to be commit e398a8d7b60127001d309c2fd0b1f13337f9b46d) --- source3/smbd/oplock_irix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index b8d49f03a1..a4ea63bc0a 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -121,7 +121,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) DEBUG(0,("irix_oplock_receive_message: read of kernel " "notification failed. Error was %s.\n", strerror(errno) )); - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); return NULL; } @@ -141,7 +141,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) */ return NULL; } - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); return NULL; } -- cgit From ae74aa9993863be8f75f203201b338e98824ce06 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Nov 2007 21:47:00 -0800 Subject: Constrain "min receivefile size" to max of BUFFER_SIZE (128k). Add debug error messages so we can see why writeX large is denied. Ensure we don't allow recvfile writes on IPC$. Jeremy. (This used to be commit 6bf053a6a17749a3bc73c8cc5fd490aa5f93b763) --- source3/smbd/reply.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1b36fb1e44..45081808e1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3856,16 +3856,24 @@ bool is_valid_writeX_buffer(const char *inbuf) unsigned int doff = 0; size_t len = smb_len_large(inbuf); - if (CVAL(inbuf,smb_com) != SMBwriteX || - CVAL(inbuf,smb_vwv0) != 0xFF || + if (CVAL(inbuf,smb_com) != SMBwriteX) { + return false; + } + + if (CVAL(inbuf,smb_vwv0) != 0xFF || CVAL(inbuf,smb_wct) != 14) { + DEBUG(10,("is_valid_writeX_buffer: chained or " + "invalid word length.\n")); return false; } + conn = conn_find(SVAL(inbuf, smb_tid)); if (conn == NULL) { + DEBUG(10,("is_valid_writeX_buffer: bad tid\n")); return false; } if (IS_IPC(conn)) { + DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n")); return false; } doff = SVAL(inbuf,smb_vwv11); @@ -3877,12 +3885,16 @@ bool is_valid_writeX_buffer(const char *inbuf) } if (numtowrite == 0) { + DEBUG(10,("is_valid_writeX_buffer: zero write\n")); return false; } /* Ensure the sizes match up. */ if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) { /* no pad byte...old smbclient :-( */ + DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n", + (unsigned int)doff, + (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE)); return false; } @@ -3939,6 +3951,12 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) } if (req->unread_bytes) { + /* Can't do a recvfile write on IPC$ */ + if (IS_IPC(conn)) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBwriteX); + return; + } if (numtowrite != req->unread_bytes) { reply_doserror(req, ERRDOS, ERRbadmem); END_PROFILE(SMBwriteX); -- cgit From e63bcdd720d801df278ef84063c46144df087793 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Nov 2007 18:13:00 +0100 Subject: Remove the silly "user_socket_options" global variable This is better done with a 'lp_do_parameter(-1, "socket options", ..); (This used to be commit 814bed029efa391e664ac432d0d68dfeab26381f) --- source3/smbd/server.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index fbf886ee67..547e9c6e81 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -34,7 +34,6 @@ int last_message = -1; #define LAST_MESSAGE() smb_fn_name(last_message) extern struct auth_context *negprot_global_auth_context; -extern pstring user_socket_options; extern SIG_ATOMIC_T got_sig_term; extern SIG_ATOMIC_T reload_after_sighup; static SIG_ATOMIC_T got_sig_cld; @@ -186,7 +185,7 @@ static bool open_sockets_inetd(void) close_low_fds(False); /* Don't close stderr */ set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), user_socket_options); + set_socket_options(smbd_server_fd(), lp_socket_options()); return True; } @@ -380,7 +379,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); + set_socket_options(smbd_server_fd(), + lp_socket_options()); /* Set server socket to * non-blocking for the accept. */ @@ -446,7 +446,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); + set_socket_options(smbd_server_fd(), + lp_socket_options()); /* Set server socket to non-blocking * for the accept. */ @@ -623,7 +624,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ am_parent = 0; set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(),user_socket_options); + set_socket_options(smbd_server_fd(), + lp_socket_options()); /* this is needed so that we get decent entries in smbstatus for port 445 connects */ @@ -758,7 +760,7 @@ bool reload_services(bool test) if (smbd_server_fd() != -1) { set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), user_socket_options); + set_socket_options(smbd_server_fd(), lp_socket_options()); } mangle_reset_cache(); -- cgit From 637f9d9bf0947600e612057ddcd9caf137b9698e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 9 Nov 2007 14:23:16 +0100 Subject: Fix some warnings (This used to be commit 0a1f524e8cce9bbe4fd10467c1f64f7a8862d298) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 24497de69a..5601a7fb6e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -190,7 +190,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, /* Copy the header we've written. */ - *buffer = TALLOC_MEMDUP(mem_ctx, + *buffer = (char *)TALLOC_MEMDUP(mem_ctx, writeX_header, sizeof(writeX_header)); -- cgit From 1c87d791991c4a8adb839923361e9dfbe50f0603 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2007 21:20:46 +0100 Subject: prepare changes in ndr code metze (This used to be commit 9ba00e7c167fb871a3d9acbd9fc5ce4e935d92c2) --- source3/smbd/notify_internal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 48ca572a25..2a2afe376b 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -163,9 +163,8 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec blob.data = (uint8 *)dbuf.dptr; blob.length = dbuf.dsize; - if (blob.length == 0) { - status = NT_STATUS_OK; - } else { + status = NT_STATUS_OK; + if (blob.length > 0) { status = ndr_pull_struct_blob(&blob, notify->array, notify->array, (ndr_pull_flags_fn_t)ndr_pull_notify_array); } -- cgit From f9578af966c1c1b5b5df4acac9977472d2896bea Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2007 14:39:45 +0100 Subject: ndr: change NTSTAUS into enum ndr_err_code (samba3 callers) lib/messages_local.c rpc_client/ndr.c smbd/notify_internal.c utils/net_rpc_registry.c metze (This used to be commit c2645d2164c05976a98bafed980b6029baf89977) --- source3/smbd/notify_internal.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 2a2afe376b..84b8e1098e 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -165,8 +165,12 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec status = NT_STATUS_OK; if (blob.length > 0) { - status = ndr_pull_struct_blob(&blob, notify->array, notify->array, - (ndr_pull_flags_fn_t)ndr_pull_notify_array); + enum ndr_err_code ndr_err; + ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->array, + (ndr_pull_flags_fn_t)ndr_pull_notify_array); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + } } if (DEBUGLEVEL >= 10) { @@ -199,6 +203,7 @@ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec TDB_DATA dbuf; DATA_BLOB blob; NTSTATUS status; + enum ndr_err_code ndr_err; TALLOC_CTX *tmp_ctx; /* if possible, remove some depth arrays */ @@ -215,11 +220,11 @@ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec tmp_ctx = talloc_new(notify); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); - status = ndr_push_struct_blob(&blob, tmp_ctx, notify->array, + ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->array, (ndr_push_flags_fn_t)ndr_push_notify_array); - if (!NT_STATUS_IS_OK(status)) { + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); - return status; + return ndr_map_error2ntstatus(ndr_err); } if (DEBUGLEVEL >= 10) { @@ -244,7 +249,7 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) { struct notify_context *notify = talloc_get_type(private_data, struct notify_context); - NTSTATUS status; + enum ndr_err_code ndr_err; struct notify_event ev; TALLOC_CTX *tmp_ctx = talloc_new(notify); struct notify_list *listel; @@ -253,9 +258,9 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data return; } - status = ndr_pull_struct_blob(data, tmp_ctx, &ev, - (ndr_pull_flags_fn_t)ndr_pull_notify_event); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_pull_struct_blob(data, tmp_ctx, &ev, + (ndr_pull_flags_fn_t)ndr_pull_notify_event); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); return; } @@ -547,6 +552,7 @@ static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry * struct notify_event ev; DATA_BLOB data; NTSTATUS status; + enum ndr_err_code ndr_err; TALLOC_CTX *tmp_ctx; ev.action = action; @@ -555,11 +561,11 @@ static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry * tmp_ctx = talloc_new(notify); - status = ndr_push_struct_blob(&data, tmp_ctx, &ev, - (ndr_push_flags_fn_t)ndr_push_notify_event); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_push_struct_blob(&data, tmp_ctx, &ev, + (ndr_push_flags_fn_t)ndr_push_notify_event); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); - return status; + return ndr_map_error2ntstatus(ndr_err); } status = messaging_send(notify->messaging_ctx, e->server, -- cgit From 6c25260ec12552653eabed25451866e370108c37 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Nov 2007 15:09:16 -0800 Subject: Remove more static fstring/pstrings. Fix socket option set on wrong fd (-1). Jeremy. (This used to be commit 52fe04df8e8c08126afe61d509fc1d3cb676e327) --- source3/smbd/server.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 547e9c6e81..e89a94599e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -379,8 +379,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), - lp_socket_options()); + set_socket_options(s,lp_socket_options()); /* Set server socket to * non-blocking for the accept. */ @@ -446,8 +445,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* ready to listen */ set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(smbd_server_fd(), - lp_socket_options()); + set_socket_options(s,lp_socket_options()); /* Set server socket to non-blocking * for the accept. */ -- cgit From acc0218f1396de2aad521dff722ada43631d92f9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Nov 2007 14:43:39 -0800 Subject: Remove pstring from service.c. Jeremy. (This used to be commit cdd9e5cc8366cf0be4dc31f793fc0e5be6f63c3e) --- source3/smbd/service.c | 180 ++++++++++++++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 71 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2cd3363cf6..dd09a6955e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -21,16 +21,17 @@ extern userdom_struct current_user_info; -static bool canonicalize_path(connection_struct *conn, pstring path) +static bool canonicalize_connect_path(connection_struct *conn) { #ifdef REALPATH_TAKES_NULL - char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL); + bool ret; + char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,NULL); if (!resolved_name) { - return False; + return false; } - pstrcpy(path, resolved_name); + ret = set_conn_connectpath(conn,resolved_name); SAFE_FREE(resolved_name); - return True; + return ret; #else #ifdef PATH_MAX char resolved_name_buf[PATH_MAX+1]; @@ -39,10 +40,9 @@ static bool canonicalize_path(connection_struct *conn, pstring path) #endif char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf); if (!resolved_name) { - return False; + return false; } - pstrcpy(path, resolved_name); - return True; + return set_conn_connectpath(conn,resolved_name); #endif /* REALPATH_TAKES_NULL */ } @@ -52,12 +52,18 @@ static bool canonicalize_path(connection_struct *conn, pstring path) Observent people will notice a similarity between this and check_path_syntax :-). ****************************************************************************/ -void set_conn_connectpath(connection_struct *conn, const char *connectpath) +bool set_conn_connectpath(connection_struct *conn, const char *connectpath) { - pstring destname; - char *d = destname; + char *destname; + char *d; const char *s = connectpath; - bool start_of_name_component = True; + bool start_of_name_component = true; + + destname = SMB_STRDUP(connectpath); + if (!destname) { + return false; + } + d = destname; *d++ = '/'; /* Always start with root. */ @@ -142,7 +148,7 @@ void set_conn_connectpath(connection_struct *conn, const char *connectpath) break; } } - start_of_name_component = False; + start_of_name_component = false; } *d = '\0'; @@ -155,6 +161,8 @@ void set_conn_connectpath(connection_struct *conn, const char *connectpath) lp_servicename(SNUM(conn)), destname )); string_set(&conn->connectpath, destname); + SAFE_FREE(destname); + return true; } /**************************************************************************** @@ -422,13 +430,17 @@ int find_service(fstring service) * could get overwritten by the recursive find_service() call * below. Fix from Josef Hinteregger . */ - pstring defservice; - pstrcpy(defservice, pdefservice); + char *defservice = SMB_STRDUP(pdefservice); + + if (!defservice) { + goto fail; + } /* Disallow anything except explicit share names. */ if (strequal(defservice,HOMES_NAME) || strequal(defservice, PRINTERS_NAME) || strequal(defservice, "IPC$")) { + SAFE_FREE(defservice); goto fail; } @@ -437,6 +449,7 @@ int find_service(fstring service) all_string_sub(service, "_","/",0); iService = lp_add_service(service, iService); } + SAFE_FREE(defservice); } } @@ -642,6 +655,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, fstring dev; int ret; char addr[INET6_ADDRSTRLEN]; + bool on_err_call_dis_hook = false; *user = 0; fstrcpy(dev, pdev); @@ -889,16 +903,27 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } { - pstring s; - pstrcpy(s,lp_pathname(snum)); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - s, sizeof(s)); - set_conn_connectpath(conn,s); + char *s = talloc_sub_advanced(talloc_tos(), + lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + lp_pathname(snum)); + if (!s) { + conn_free(conn); + *status = NT_STATUS_NO_MEMORY; + return NULL; + } + + if (!set_conn_connectpath(conn,s)) { + TALLOC_FREE(s); + conn_free(conn); + *status = NT_STATUS_NO_MEMORY; + return NULL; + } DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); + TALLOC_FREE(s); } /* @@ -969,10 +994,15 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * depend on the realpath() pointer in the vfs table. JRA. */ if (!lp_widelinks(snum)) { - pstring s; - pstrcpy(s,conn->connectpath); - canonicalize_path(conn, s); - set_conn_connectpath(conn,s); + if (!canonicalize_connect_path(conn)) { + DEBUG(0, ("canonicalize_connect_path failed " + "for service %s, path %s\n", + lp_servicename(snum), + conn->connectpath)); + conn_free(conn); + *status = NT_STATUS_BAD_NETWORK_NAME; + return NULL; + } } if ((!conn->printer) && (!conn->ipc)) { @@ -1012,15 +1042,15 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * to below */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(snum)) { - pstring cmd; - pstrcpy(cmd,lp_rootpreexec(snum)); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - cmd, sizeof(cmd)); + char *cmd = talloc_sub_advanced(talloc_tos(), + lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + lp_rootpreexec(snum)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); + TALLOC_FREE(cmd); if (ret != 0 && lp_rootpreexec_close(snum)) { DEBUG(1,("root preexec gave %d - failing " "connection\n", ret)); @@ -1049,22 +1079,19 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* execute any "preexec = " line */ if (*lp_preexec(snum)) { - pstring cmd; - pstrcpy(cmd,lp_preexec(snum)); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - cmd, sizeof(cmd)); + char *cmd = talloc_sub_advanced(talloc_tos(), + lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + lp_preexec(snum)); ret = smbrun(cmd,NULL); + TALLOC_FREE(cmd); if (ret != 0 && lp_preexec_close(snum)) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); - change_to_root_user(); - yield_connection(conn, lp_servicename(snum)); - conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; - return NULL; + goto err_root_exit; } } @@ -1087,13 +1114,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); - change_to_root_user(); - yield_connection(conn, lp_servicename(snum)); - conn_free(conn); *status = NT_STATUS_UNSUCCESSFUL; - return NULL; + goto err_root_exit; } + /* Any error exit after here needs to call the disconnect hook. */ + on_err_call_dis_hook = true; + /* win2000 does not check the permissions on the directory during the tree connect, instead relying on permission check during individual operations. To match this behaviour @@ -1111,13 +1138,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->connectpath, lp_servicename(snum), strerror(errno) )); } - change_to_root_user(); - /* Call VFS disconnect hook */ - SMB_VFS_DISCONNECT(conn); - yield_connection(conn, lp_servicename(snum)); - conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; - return NULL; + goto err_root_exit; } string_set(&conn->origpath,conn->connectpath); @@ -1129,9 +1151,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, char *s = vfs_GetWd(ctx,s); if (!s) { *status = map_nt_error_from_unix(errno); - return NULL; + TALLOC_FREE(ctx); + goto err_root_exit; + } + if (!set_conn_connectpath(conn,s)) { + *status = NT_STATUS_NO_MEMORY; + TALLOC_FREE(ctx); + goto err_root_exit; } - set_conn_connectpath(conn,s); vfs_ChDir(conn,conn->connectpath); TALLOC_FREE(ctx); } @@ -1156,6 +1183,17 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* we've finished with the user stuff - go back to root */ change_to_root_user(); return(conn); + + err_root_exit: + + change_to_root_user(); + if (on_err_call_dis_hook) { + /* Call VFS disconnect hook */ + SMB_VFS_DISCONNECT(conn); + } + yield_connection(conn, lp_servicename(snum)); + conn_free(conn); + return NULL; } /*************************************************************************************** @@ -1356,28 +1394,28 @@ void close_cnum(connection_struct *conn, uint16 vuid) /* execute any "postexec = " line */ if (*lp_postexec(SNUM(conn)) && change_to_user(conn, vuid)) { - pstring cmd; - pstrcpy(cmd,lp_postexec(SNUM(conn))); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - cmd, sizeof(cmd)); + char *cmd = talloc_sub_advanced(talloc_tos(), + lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + lp_postexec(SNUM(conn))); smbrun(cmd,NULL); + TALLOC_FREE(cmd); change_to_root_user(); } change_to_root_user(); /* execute any "root postexec = " line */ if (*lp_rootpostexec(SNUM(conn))) { - pstring cmd; - pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - cmd, sizeof(cmd)); + char *cmd = talloc_sub_advanced(talloc_tos(), + lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + lp_rootpostexec(SNUM(conn))); smbrun(cmd,NULL); + TALLOC_FREE(cmd); } conn_free(conn); -- cgit From 54d65bfb9a3200943afa14e314a3d620f6fa32b3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Nov 2007 15:02:08 -0800 Subject: Fix the build when realpath doesn't take null as a last arg. Jeremy. (This used to be commit 63125225383f512f43002b9a92569d4b8f1b63bd) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index dd09a6955e..c3972391f3 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -38,7 +38,7 @@ static bool canonicalize_connect_path(connection_struct *conn) #else pstring resolved_name_buf; #endif - char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf); + char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf); if (!resolved_name) { return false; } -- cgit From 41ae2a0a17d3f67252e81a6db730f87ce26fb939 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Nov 2007 15:36:47 -0800 Subject: Remove last pstring from sesssetup.c Jeremy. (This used to be commit 9ed12bfc48fe7f9b1863a9dd88e881974083053c) --- source3/smbd/sesssetup.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0e8483c81e..8ca012ff24 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1491,30 +1491,32 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) lm_resp = data_blob(p, passlen1); nt_resp = data_blob(p+passlen1, passlen2); } else { - pstring pass; + char *pass = NULL; bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS; -#if 0 - /* This was the previous fix. Not sure if it's still - * valid. JRA. */ - if ((ra_type == RA_WINNT) && (passlen2 == 0) - && unic && passlen1) { - /* NT4.0 stuffs up plaintext unicode password - * lengths... */ - srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1, - sizeof(pass), passlen1, STR_TERMINATE); -#endif - if (unic && (passlen2 == 0) && passlen1) { /* Only a ascii plaintext password was sent. */ - srvstr_pull(req->inbuf, req->flags2, pass, - smb_buf(req->inbuf), sizeof(pass), - passlen1, STR_TERMINATE|STR_ASCII); + (void)srvstr_pull_talloc(talloc_tos(), + req->inbuf, + req->flags2, + &pass, + smb_buf(req->inbuf), + passlen1, + STR_TERMINATE|STR_ASCII); } else { - srvstr_pull(req->inbuf, req->flags2, pass, - smb_buf(req->inbuf), sizeof(pass), - unic ? passlen2 : passlen1, - STR_TERMINATE); + (void)srvstr_pull_talloc(talloc_tos(), + req->inbuf, + req->flags2, + &pass, + smb_buf(req->inbuf), + unic ? passlen2 : passlen1, + STR_TERMINATE); + } + if (!pass) { + reply_nterror(req, nt_status_squash( + NT_STATUS_INVALID_PARAMETER)); + END_PROFILE(SMBsesssetupX); + return; } plaintext_password = data_blob(pass, strlen(pass)+1); } -- cgit From 2b3c44e4fb980335c22abcc07a88f32b13e5918f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Nov 2007 22:31:34 -0800 Subject: Always define PATH_MAX. Makes code simpler (removes a bunch of #defines). Remove pstring from msdfs.c. Jeremy. (This used to be commit e203ba22275320808bc11b17361ad1f2d5b0b897) --- source3/smbd/msdfs.c | 62 +++++++++++++++++++++++++++++++++----------------- source3/smbd/service.c | 4 ---- source3/smbd/vfs.c | 12 ---------- 3 files changed, 41 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index cca1e0a428..98a41e4ec3 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -196,16 +196,26 @@ static NTSTATUS parse_dfs_path(const char *pathname, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static NTSTATUS create_conn_struct(connection_struct *conn, +static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, + connection_struct *conn, int snum, const char *path) { - pstring connpath; + char *connpath; ZERO_STRUCTP(conn); - pstrcpy(connpath, path); - pstring_sub(connpath , "%S", lp_servicename(snum)); + connpath = talloc_strdup(ctx, path); + if (!connpath) { + return NT_STATUS_NO_MEMORY; + } + connpath = talloc_string_sub(ctx, + connpath, + "%S", + lp_servicename(snum)); + if (!connpath) { + return NT_STATUS_NO_MEMORY; + } /* needed for smbd_vfs_init() */ @@ -844,7 +854,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_OK; } - status = create_conn_struct(conn, snum, lp_pathname(snum)); + status = create_conn_struct(ctx, conn, snum, lp_pathname(snum)); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -888,7 +898,7 @@ static int setup_ver2_dfs_referral(const char *pathname, { char* pdata = *ppdata; - unsigned char uni_requestedpath[sizeof(pstring)]; + smb_ucs2_t *uni_requestedpath = NULL; int uni_reqpathoffset1,uni_reqpathoffset2; int uni_curroffset; int requestedpathlen=0; @@ -898,12 +908,15 @@ static int setup_ver2_dfs_referral(const char *pathname, DEBUG(10,("Setting up version2 referral\nRequested path:\n")); - requestedpathlen = rpcstr_push(uni_requestedpath, - pathname, sizeof(pstring), - STR_TERMINATE); + requestedpathlen = rpcstr_push_talloc(talloc_tos(), + &uni_requestedpath, pathname); + if (uni_requestedpath == NULL || requestedpathlen == 0) { + return -1; + } if (DEBUGLVL(10)) { - dump_data(0, uni_requestedpath,requestedpathlen); + dump_data(0, (unsigned char *)uni_requestedpath, + requestedpathlen); } DEBUG(10,("ref count = %u\n",junction->referral_count)); @@ -976,8 +989,10 @@ static int setup_ver2_dfs_referral(const char *pathname, SSVAL(pdata,offset+16,uni_reqpathoffset1-offset); SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); /* copy referred path into current offset */ - unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, - sizeof(pstring), STR_UNICODE); + unilen = rpcstr_push(pdata+uni_curroffset, + ref->alternate_path, + reply_size - uni_curroffset, + STR_UNICODE); SSVAL(pdata,offset+20,uni_curroffset-offset); @@ -997,7 +1012,7 @@ static int setup_ver3_dfs_referral(const char *pathname, { char *pdata = *ppdata; - unsigned char uni_reqpath[sizeof(pstring)]; + smb_ucs2_t *uni_reqpath = NULL; int uni_reqpathoffset1, uni_reqpathoffset2; int uni_curroffset; int reply_size = 0; @@ -1007,11 +1022,14 @@ static int setup_ver3_dfs_referral(const char *pathname, DEBUG(10,("setting up version3 referral\n")); - reqpathlen = rpcstr_push(uni_reqpath, pathname, - sizeof(pstring), STR_TERMINATE); + reqpathlen = rpcstr_push_talloc(talloc_tos(), &uni_reqpath, pathname); + if (uni_reqpath == NULL || reqpathlen == 0) { + return -1; + } if (DEBUGLVL(10)) { - dump_data(0, uni_reqpath,reqpathlen); + dump_data(0, (unsigned char *)uni_reqpath, + reqpathlen); } uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + @@ -1069,8 +1087,8 @@ static int setup_ver3_dfs_referral(const char *pathname, SSVAL(pdata,offset+14,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset,ref->alternate_path, - sizeof(pstring), - STR_UNICODE | STR_TERMINATE); + reply_size - uni_curroffset, + STR_UNICODE | STR_TERMINATE); SSVAL(pdata,offset+16,uni_curroffset-offset); /* copy 0x10 bytes of 00's in the ServiceSite GUID */ memset(pdata+offset+18,'\0',16); @@ -1270,7 +1288,8 @@ static bool junction_to_local_path(const struct junction_map *jucn, if(snum < 0) { return False; } - if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, + if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), + conn_out, snum, lp_pathname(snum)))) { return False; } @@ -1402,7 +1421,8 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { + if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), + &conn, snum, connect_path))) { return 0; } @@ -1467,7 +1487,7 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { + if (!NT_STATUS_IS_OK(create_conn_struct(ctx, &conn, snum, connect_path))) { return 0; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c3972391f3..e98ce0f8c2 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -33,11 +33,7 @@ static bool canonicalize_connect_path(connection_struct *conn) SAFE_FREE(resolved_name); return ret; #else -#ifdef PATH_MAX char resolved_name_buf[PATH_MAX+1]; -#else - pstring resolved_name_buf; -#endif char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf); if (!resolved_name) { return false; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 78939881d3..628d2eec4b 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -774,11 +774,7 @@ static void array_promote(char *array,int elsize,int element) char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) { -#ifdef PATH_MAX char s[PATH_MAX+1]; -#else - pstring s; -#endif static bool getwd_cache_init = False; SMB_STRUCT_STAT st, st2; int i; @@ -893,11 +889,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) #ifdef REALPATH_TAKES_NULL bool free_resolved_name = True; #else -#ifdef PATH_MAX char resolved_name_buf[PATH_MAX+1]; -#else - pstring resolved_name_buf; -#endif bool free_resolved_name = False; #endif char *resolved_name = NULL; @@ -969,11 +961,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) return NT_STATUS_NO_MEMORY; } #else -#ifdef PATH_MAX safe_strcpy(resolved_name_buf, tmp_fname, PATH_MAX); -#else - pstrcpy(resolved_name_buf, tmp_fname); -#endif resolved_name = resolved_name_buf; #endif TALLOC_FREE(tmp_ctx); -- cgit From 7e9d639ed1584c2f7cd3556ce3e93974851f74c6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Nov 2007 12:49:42 +0100 Subject: Cosmetic fix Do directory vs file open before entering open_file_stat (This used to be commit cd62122916defbfb57468c3b82a60b766fc4652e) --- source3/smbd/file_access.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 189fcbbce1..121e7f79a9 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -51,9 +51,7 @@ static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, /* fake a files_struct ptr: */ - status = open_file_stat(conn, NULL, fname, psbuf, &fsp); - /* Perhaps it is a directory */ - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + if (S_ISDIR(psbuf->st_mode)) { status = open_directory(conn, NULL, fname, psbuf, READ_CONTROL_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, @@ -62,6 +60,10 @@ static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, FILE_ATTRIBUTE_DIRECTORY, NULL, &fsp); } + else { + status = open_file_stat(conn, NULL, fname, psbuf, &fsp); + } + if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Unable to open file %s: %s\n", fname, nt_errstr(status))); -- cgit From d068bc64b6f16bc0b4a8170b56f6aadd487d7203 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Nov 2007 21:46:52 -0800 Subject: Three more pstring removals. Jeremy. (This used to be commit c15819b75751a1e15cfed2ef94dae10ee72d769c) --- source3/smbd/chgpasswd.c | 10 +++++++--- source3/smbd/process.c | 12 +++++++++--- source3/smbd/server.c | 3 +-- 3 files changed, 17 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index d89442150f..6e7ef208c1 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -262,14 +262,18 @@ static int expect(int master, char *issue, char *expected) { /* Eat leading/trailing whitespace before match. */ - pstring str; - pstrcpy( str, buffer); - trim_char( str, ' ', ' '); + char *str = SMB_STRDUP(buffer); + if (!str) { + DEBUG(2,("expect: ENOMEM\n")); + return False; + } + trim_char(str, ' ', ' '); if ((match = unix_wild_match(expected, str)) == True) { /* Now data has started to return, lower timeout. */ timeout = lp_passwd_chat_timeout() * 100; } + SAFE_FREE(str); } } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5601a7fb6e..ffc9e106f6 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1260,13 +1260,18 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) static void smb_dump(const char *name, int type, const char *data, ssize_t len) { int fd, i; - pstring fname; - if (DEBUGLEVEL < 50) return; + char *fname = NULL; + if (DEBUGLEVEL < 50) { + return; + } if (len < 4) len = smb_len(data)+4; for (i=1;i<100;i++) { - slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i, + asprintf(&fname, "/tmp/%s.%d.%s", name, i, type ? "req" : "resp"); + if (!fname) { + return; + } fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644); if (fd != -1 || errno != EEXIST) break; } @@ -1277,6 +1282,7 @@ static void smb_dump(const char *name, int type, const char *data, ssize_t len) close(fd); DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len)); } + SAFE_FREE(fname); } /**************************************************************************** diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e89a94599e..028dacc27e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -728,8 +728,7 @@ bool reload_services(bool test) bool ret; if (lp_loaded()) { - pstring fname; - pstrcpy(fname,lp_configfile()); + char *fname = lp_configfile(); if (file_exist(fname, NULL) && !strcsequal(fname, dyn_CONFIGFILE)) { pstrcpy(dyn_CONFIGFILE, fname); -- cgit From 86558e0376558f730ba1a650af2f8b545ad96b4d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Nov 2007 11:39:35 -0800 Subject: Fix bug #5073. Allow "delete readonly = yes" to correctly override deletion of a file. Fix from David Shaw Jeremy. (This used to be commit 5d1d650d192d4782421b5c3c2be1b632d4318279) --- source3/smbd/nttrans.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4bd4571171..f07d64eded 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -788,7 +788,8 @@ void reply_ntcreate_and_X(connection_struct *conn, && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS)) { - if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || + if (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) + && !lp_delete_readonly(SNUM(conn))) || !can_delete_file_in_directory(conn, fname)) { TALLOC_FREE(case_state); reply_nterror(req, NT_STATUS_ACCESS_DENIED); -- cgit From 79266500cd3f84c74b2f89ceeb15c23cedacc2b5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Nov 2007 15:02:50 -0800 Subject: Remove all pstrings from smbd/chgpasswd.c. Jeremy. (This used to be commit eaf14c701b08e9eff5b94bf57af68cb29142d7fc) --- source3/smbd/chgpasswd.c | 157 +++++++++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 67 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 6e7ef208c1..aef5adb72f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -25,7 +25,7 @@ * user who is attempting to change the password. */ -/* +/* * This code was copied/borrowed and stolen from various sources. * The primary source was the poppasswd.c from the authors of POPMail. This software * was included as a client to change passwords using the 'passwd' program @@ -50,12 +50,12 @@ extern struct passdb_ops pdb_ops; static NTSTATUS check_oem_password(const char *user, - uchar password_encrypted_with_lm_hash[516], + uchar password_encrypted_with_lm_hash[516], const uchar old_lm_hash_encrypted[16], - uchar password_encrypted_with_nt_hash[516], + uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], - struct samu **hnd, char *new_passwd, - int new_passwd_size); + struct samu **hnd, + char **pp_new_passwd); #if ALLOW_CHANGE_PASSWORD @@ -231,7 +231,7 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, static int expect(int master, char *issue, char *expected) { - pstring buffer; + char buffer[1024]; int attempts, timeout, nread, len; bool match = False; @@ -450,13 +450,14 @@ while we were waiting\n", WTERMSIG(wstat))); return (chstat); } -bool chgpasswd(const char *name, const struct passwd *pass, +bool chgpasswd(const char *name, const struct passwd *pass, const char *oldpass, const char *newpass, bool as_root) { - pstring passwordprogram; - pstring chatsequence; + char *passwordprogram = NULL; + char *chatsequence = NULL; size_t i; size_t len; + TALLOC_CTX *ctx = talloc_tos(); if (!oldpass) { oldpass = ""; @@ -477,7 +478,7 @@ bool chgpasswd(const char *name, const struct passwd *pass, return (False); /* inform the user */ } - /* + /* * Check the old and new passwords don't contain any control * characters. */ @@ -497,7 +498,7 @@ bool chgpasswd(const char *name, const struct passwd *pass, return False; } } - + #ifdef WITH_PAM if (lp_pam_password_change()) { bool ret; @@ -510,7 +511,7 @@ bool chgpasswd(const char *name, const struct passwd *pass, } else { ret = smb_pam_passchange(name, oldpass, newpass); } - + if (as_root) unbecome_root(); @@ -522,20 +523,18 @@ bool chgpasswd(const char *name, const struct passwd *pass, if (pass == NULL) { DEBUG(0, ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", name)); - return False; + return false; } - pstrcpy(passwordprogram, lp_passwd_program()); - pstrcpy(chatsequence, lp_passwd_chat()); - - if (!*chatsequence) { - DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n")); - return (False); - } - - if (!*passwordprogram) { + passwordprogram = talloc_strdup(ctx, lp_passwd_program()); + if (!passwordprogram || !*passwordprogram) { DEBUG(2, ("chgpasswd: Null password program - no password changing\n")); - return (False); + return false; + } + chatsequence = talloc_strdup(ctx, lp_passwd_chat()); + if (!chatsequence || !*chatsequence) { + DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n")); + return false; } if (as_root) { @@ -543,20 +542,38 @@ bool chgpasswd(const char *name, const struct passwd *pass, if (strstr_m(passwordprogram, "%u") == NULL) { DEBUG(0,("chgpasswd: Running as root the 'passwd program' parameter *MUST* contain \ the string %%u, and the given string %s does not.\n", passwordprogram )); - return False; + return false; } } - pstring_sub(passwordprogram, "%u", name); + passwordprogram = talloc_string_sub(ctx, passwordprogram, "%u", name); + if (!passwordprogram) { + return false; + } + /* note that we do NOT substitute the %o and %n in the password program as this would open up a security hole where the user could use a new password containing shell escape characters */ - pstring_sub(chatsequence, "%u", name); - all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring)); - all_string_sub(chatsequence, "%n", newpass, sizeof(pstring)); - return (chat_with_program - (passwordprogram, pass, chatsequence, as_root)); + chatsequence = talloc_string_sub(ctx, chatsequence, "%u", name); + if (!chatsequence) { + return false; + } + chatsequence = talloc_all_string_sub(ctx, + chatsequence, + "%o", + oldpass); + if (!chatsequence) { + return false; + } + chatsequence = talloc_all_string_sub(ctx, + chatsequence, + "%n", + newpass); + return chat_with_program(passwordprogram, + pass, + chatsequence, + as_root); } #else /* ALLOW_CHANGE_PASSWORD */ @@ -695,9 +712,9 @@ bool change_lanman_password(struct samu *sampass, uchar *pass2) if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) { TALLOC_FREE(sampass); /* Not quite sure what this one qualifies as, but this will do */ - return False; + return False; } - + /* Now flush the sam_passwd struct to persistent storage */ ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass)); @@ -709,29 +726,32 @@ bool change_lanman_password(struct samu *sampass, uchar *pass2) ************************************************************/ NTSTATUS pass_oem_change(char *user, - uchar password_encrypted_with_lm_hash[516], + uchar password_encrypted_with_lm_hash[516], const uchar old_lm_hash_encrypted[16], - uchar password_encrypted_with_nt_hash[516], + uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], uint32 *reject_reason) { - pstring new_passwd; + char *new_passwd = NULL; struct samu *sampass = NULL; - NTSTATUS nt_status = check_oem_password(user, password_encrypted_with_lm_hash, - old_lm_hash_encrypted, - password_encrypted_with_nt_hash, + NTSTATUS nt_status = check_oem_password(user, + password_encrypted_with_lm_hash, + old_lm_hash_encrypted, + password_encrypted_with_nt_hash, old_nt_hash_encrypted, - &sampass, new_passwd, sizeof(new_passwd)); - - if (!NT_STATUS_IS_OK(nt_status)) + &sampass, + &new_passwd); + + if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; + } /* We've already checked the old password here.... */ become_root(); nt_status = change_oem_password(sampass, NULL, new_passwd, True, reject_reason); unbecome_root(); - memset(new_passwd, 0, sizeof(new_passwd)); + memset(new_passwd, 0, strlen(new_passwd)); TALLOC_FREE(sampass); @@ -739,24 +759,24 @@ NTSTATUS pass_oem_change(char *user, } /*********************************************************** - Decrypt and verify a user password change. + Decrypt and verify a user password change. - The 516 byte long buffers are encrypted with the old NT and - old LM passwords, and if the NT passwords are present, both + The 516 byte long buffers are encrypted with the old NT and + old LM passwords, and if the NT passwords are present, both buffers contain a unicode string. After decrypting the buffers, check the password is correct by matching the old hashed passwords with the passwords in the passdb. - + ************************************************************/ static NTSTATUS check_oem_password(const char *user, - uchar password_encrypted_with_lm_hash[516], + uchar password_encrypted_with_lm_hash[516], const uchar old_lm_hash_encrypted[16], - uchar password_encrypted_with_nt_hash[516], + uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], - struct samu **hnd, char *new_passwd, - int new_passwd_size) + struct samu **hnd, + char **pp_new_passwd) { static uchar null_pw[16]; static uchar null_ntpw[16]; @@ -788,11 +808,11 @@ static NTSTATUS check_oem_password(const char *user, if (ret == False) { DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n")); TALLOC_FREE(sampass); - return NT_STATUS_NO_SUCH_USER; + return NT_STATUS_NO_SUCH_USER; } acct_ctrl = pdb_get_acct_ctrl(sampass); - + if (acct_ctrl & ACB_DISABLED) { DEBUG(2,("check_lanman_password: account %s disabled.\n", user)); TALLOC_FREE(sampass); @@ -819,7 +839,7 @@ static NTSTATUS check_oem_password(const char *user, if (nt_pw && nt_pass_set) { /* IDEAL Case: passwords are in unicode, and we can - * read use the password encrypted with the NT hash + * read use the password encrypted with the NT hash */ password_encrypted = password_encrypted_with_nt_hash; encryption_key = nt_pw; @@ -831,7 +851,7 @@ static NTSTATUS check_oem_password(const char *user, DEBUG(1, ("NT password change supplied for user %s, but we have no NT password to check it with\n", user)); TALLOC_FREE(sampass); - return NT_STATUS_WRONG_PASSWORD; + return NT_STATUS_WRONG_PASSWORD; } else if (lm_pass_set) { if (lp_lanman_auth()) { DEBUG(1, ("LM password change supplied for user %s, but we have no LanMan password to check it with\n", @@ -849,13 +869,16 @@ static NTSTATUS check_oem_password(const char *user, return NT_STATUS_WRONG_PASSWORD; } - /* - * Decrypt the password with the key + /* + * Decrypt the password with the key */ SamOEMhash( password_encrypted, encryption_key, 516); - if ( !decode_pw_buffer(password_encrypted, new_passwd, new_passwd_size, &new_pw_len, - nt_pass_set ? STR_UNICODE : STR_ASCII)) { + if (!decode_pw_buffer(talloc_tos(), + password_encrypted, + pp_new_passwd, + &new_pw_len, + nt_pass_set ? STR_UNICODE : STR_ASCII)) { TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } @@ -867,10 +890,10 @@ static NTSTATUS check_oem_password(const char *user, if (nt_pass_set) { /* NT passwords, verify the NT hash. */ - + /* Calculate the MD4 hash (NT compatible) of the password */ memset(new_nt_hash, '\0', 16); - E_md4hash(new_passwd, new_nt_hash); + E_md4hash(*pp_new_passwd, new_nt_hash); if (nt_pw) { /* @@ -882,7 +905,7 @@ static NTSTATUS check_oem_password(const char *user, TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } - + /* We could check the LM password here, but there is * little point, we already know the password is * correct, and the LM password might not even be @@ -894,12 +917,12 @@ static NTSTATUS check_oem_password(const char *user, * change */ #ifdef DEBUG_PASSWORD DEBUG(100, - ("check_oem_password: password %s ok\n", new_passwd)); + ("check_oem_password: password %s ok\n", *pp_new_passwd)); #endif *hnd = sampass; return NT_STATUS_OK; } - + if (lanman_pw) { /* * check the lm verifier @@ -912,7 +935,7 @@ static NTSTATUS check_oem_password(const char *user, } #ifdef DEBUG_PASSWORD DEBUG(100, - ("check_oem_password: password %s ok\n", new_passwd)); + ("check_oem_password: password %s ok\n", *pp_new_passwd)); #endif *hnd = sampass; return NT_STATUS_OK; @@ -921,7 +944,7 @@ static NTSTATUS check_oem_password(const char *user, if (lanman_pw && lm_pass_set) { - E_deshash(new_passwd, new_lm_hash); + E_deshash(*pp_new_passwd, new_lm_hash); /* * check the lm verifier @@ -932,10 +955,10 @@ static NTSTATUS check_oem_password(const char *user, TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } - + #ifdef DEBUG_PASSWORD DEBUG(100, - ("check_oem_password: password %s ok\n", new_passwd)); + ("check_oem_password: password %s ok\n", *pp_new_passwd)); #endif *hnd = sampass; return NT_STATUS_OK; -- cgit From d5791deefaa8ef67ee0573cd41f5eb22b37261a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Nov 2007 17:59:18 -0800 Subject: Remove pstrings from lanman.c Jeremy. (This used to be commit 7bfd25c75602e25da73710261a54da8e0feea133) --- source3/smbd/lanman.c | 202 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 148 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 440b928ef0..4bd59a7aa6 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -77,26 +77,43 @@ static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char int *rdata_len, int *rparam_len); -static int CopyExpanded(connection_struct *conn, - int snum, char **dst, char *src, int *n) +static int CopyExpanded(connection_struct *conn, + int snum, char **dst, char *src, int *p_space_remaining) { - pstring buf; + TALLOC_CTX *ctx = talloc_tos(); + char *buf = NULL; int l; - if (!src || !dst || !n || !(*dst)) { + if (!src || !dst || !p_space_remaining || !(*dst) || + *p_space_remaining <= 0) { return 0; } - StrnCpy(buf,src,sizeof(buf)/2); - pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - buf, sizeof(buf)); - l = push_ascii(*dst,buf,*n, STR_TERMINATE); + buf = talloc_strdup(ctx, src); + if (!buf) { + *p_space_remaining = 0; + return 0; + } + buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum)); + if (!buf) { + *p_space_remaining = 0; + return 0; + } + buf = talloc_sub_advanced(ctx, + lp_servicename(SNUM(conn)), + conn->user, + conn->connectpath, + conn->gid, + get_current_username(), + current_user_info.domain, + buf); + if (!buf) { + *p_space_remaining = 0; + return 0; + } + l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE); (*dst) += l; - (*n) -= l; + (*p_space_remaining) -= l; return l; } @@ -114,32 +131,57 @@ static int CopyAndAdvance(char **dst, char *src, int *n) static int StrlenExpanded(connection_struct *conn, int snum, char *s) { - pstring buf; + TALLOC_CTX *ctx = talloc_tos(); + char *buf = NULL; if (!s) { return 0; } - StrnCpy(buf,s,sizeof(buf)/2); - pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - buf, sizeof(buf)); + buf = talloc_strdup(ctx,s); + if (!buf) { + return 0; + } + buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum)); + if (!buf) { + return 0; + } + buf = talloc_sub_advanced(ctx, + lp_servicename(SNUM(conn)), + conn->user, + conn->connectpath, + conn->gid, + get_current_username(), + current_user_info.domain, + buf); + if (!buf) { + return 0; + } return strlen(buf) + 1; } static char *Expand(connection_struct *conn, int snum, char *s) { - pstring buf; + TALLOC_CTX *ctx = talloc_tos(); + char *buf = NULL; + if (!s) { return NULL; } - StrnCpy(buf,s,sizeof(buf)/2); - pstring_sub(buf,"%S",lp_servicename(snum)); - return talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)), - conn->user, conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, buf); + buf = talloc_strdup(ctx,s); + if (!buf) { + return 0; + } + buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum)); + if (!buf) { + return 0; + } + return talloc_sub_advanced(ctx, + lp_servicename(SNUM(conn)), + conn->user, + conn->connectpath, + conn->gid, + get_current_username(), + current_user_info.domain, + buf); } /******************************************************************* @@ -572,16 +614,20 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, Returns True if from tdb, False otherwise. ********************************************************************/ -static bool get_driver_name(int snum, pstring drivername) +static bool get_driver_name(int snum, char **pp_drivername) { NT_PRINTER_INFO_LEVEL *info = NULL; - bool in_tdb = False; + bool in_tdb = false; get_a_printer (NULL, &info, 2, lp_servicename(snum)); if (info != NULL) { - pstrcpy( drivername, info->info_2->drivername); - in_tdb = True; + *pp_drivername = talloc_strdup(talloc_tos(), + info->info_2->drivername); + in_tdb = true; free_a_printer(&info, 2); + if (!*pp_drivername) { + return false; + } } return in_tdb; @@ -716,7 +762,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, } if (uLevel == 3 || uLevel == 4) { - pstring drivername; + char *drivername = NULL; PACKI(desc,"W",5); /* uPriority */ PACKI(desc,"W",0); /* uStarttime */ @@ -726,7 +772,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z","WinPrint"); /* pszPrProc */ PACKS(desc,"z",NULL); /* pszParms */ PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */ - /* "don't ask" that it's done this way to fix corrupted + /* "don't ask" that it's done this way to fix corrupted Win9X/ME printer comments. */ if (!status) { PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ @@ -735,7 +781,10 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, } PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - get_driver_name(snum,drivername); + get_driver_name(snum,&drivername); + if (!drivername) { + return; + } PACKS(desc,"z",drivername); /* pszDriverName */ PackDriverData(desc); /* pDriverData */ } @@ -1817,12 +1866,12 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); fstring sharename; fstring comment; - pstring pathname; + char *pathname = NULL; char *command, *cmdname; unsigned int offset; int snum; int res = ERRunsup; - + if (!str1 || !str2 || !p) { return False; } @@ -1881,7 +1930,11 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, if (skip_string(data,mdrcnt,data+offset) == NULL) { return False; } - pull_ascii_pstring(pathname, offset? (data+offset) : ""); + + pull_ascii_talloc(talloc_tos(), &pathname, offset? (data+offset) : ""); + if (!pathname) { + return false; + } string_replace(sharename, '"', ' '); string_replace(pathname, '"', ' '); @@ -2884,16 +2937,25 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, if (uLevel > 0) { struct srv_info_struct *servers=NULL; int i,count; - pstring comment; + char *comment = NULL; + TALLOC_CTX *ctx = talloc_tos(); uint32 servertype= lp_default_server_announce(); - push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE); + comment = talloc_strdup(ctx,lp_serverstring()); + if (!comment) { + return false; + } if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;iuser, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, - comment, sizeof(comment)); - StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); + comment = talloc_sub_advanced(ctx, + lp_servicename(SNUM(conn)), + conn->user, + conn->connectpath, + conn->gid, + get_current_username(), + current_user_info.domain, + comment); + if (comment) { + return false; + } + if (mdrcnt - struct_len <= 0) { + return false; + } + push_ascii(p2, + comment, + MIN(mdrcnt - struct_len, + MAX_SERVER_STRING_LENGTH), + STR_TERMINATE); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3231,7 +3306,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); if(vuser != NULL) { - DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->user.unix_name)); } @@ -3246,7 +3321,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, } DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); - + /* check it's a supported variant */ if (strcmp(str1,"zWrLh") != 0) { return False; @@ -3279,7 +3354,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, return False; } - memset(p,0,21); + memset(p,0,21); fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ if (uLevel > 0) { @@ -3410,10 +3485,29 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SSVALS(p,104,-1); /* num_logons */ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ { - pstring tmp; - pstrcpy(tmp, "\\\\%L"); - standard_sub_basic("", "", tmp, sizeof(tmp)); - pstrcpy(p2, tmp); + TALLOC_CTX *ctx = talloc_tos(); + int space_rem = *rdata_len - (p2 - *rdata); + char *tmp; + + if (space_rem <= 0) { + return false; + } + tmp = talloc_strdup(ctx, "\\\\%L"); + if (!tmp) { + return false; + } + tmp = talloc_sub_basic(ctx, + "", + "", + tmp); + if (!tmp) { + return false; + } + + push_ascii(p2, + tmp, + space_rem, + STR_TERMINATE); } p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { -- cgit From 9441d1ba87313e0ecc6e6971a25e7ad0c280fdd7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Nov 2007 18:12:26 -0800 Subject: More pstring removal from smbd/*.c Jeremy. (This used to be commit 01663c2312467ceebeb2e2fb1aa432ad96c626e5) --- source3/smbd/map_username.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index d9ad81a3e1..c04e0f1ae2 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -39,30 +39,36 @@ bool map_username(fstring user) XFILE *f; char *mapfile = lp_username_map(); char *s; - pstring buf; + char buf[512]; bool mapped_user = False; char *cmd = lp_username_map_script(); - + if (!*user) - return False; - + return false; + if (strequal(user,last_to)) - return False; + return false; if (strequal(user,last_from)) { DEBUG(3,("Mapped user %s to %s\n",user,last_to)); fstrcpy(user,last_to); - return True; + return true; } - + /* first try the username map script */ - + if ( *cmd ) { char **qlines; - pstring command; + char *command = NULL; int numlines, ret, fd; - pstr_sprintf( command, "%s \"%s\"", cmd, user ); + command = talloc_asprintf(talloc_tos(), + "%s \"%s\"", + cmd, + user); + if (!command) { + return false; + } DEBUG(10,("Running [%s]\n", command)); ret = smbrun(command, &fd); @@ -87,7 +93,7 @@ bool map_username(fstring user) } file_lines_free(qlines); - + return numlines != 0; } -- cgit From 15953b82eb3b49d736b4b835b1d0d3cf0da0bff8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 13 Oct 2007 21:06:49 +0200 Subject: Make [f]get_nt_acl return NTSTATUS (This used to be commit dcbe1bf942d017a3cd5084c6ef605a13912f795b) --- source3/smbd/dir.c | 11 +++++------ source3/smbd/file_access.c | 15 +++++++-------- source3/smbd/nttrans.c | 18 +++++++++++------- source3/smbd/posix_acls.c | 20 ++++++++++---------- 4 files changed, 33 insertions(+), 31 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f6a8b27ab4..05679ee0ee 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -911,7 +911,6 @@ bool get_dir_entry(TALLOC_CTX *ctx, static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { SEC_DESC *psd = NULL; - size_t sd_size; files_struct *fsp; NTSTATUS status; uint32 access_granted; @@ -951,12 +950,12 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S } /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, + status = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, NORMAL_CLOSE); /* No access if SD get failed. */ - if (!sd_size) { + if (!NT_STATUS_IS_OK(status)) { return False; } @@ -974,7 +973,6 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { SEC_DESC *psd = NULL; - size_t sd_size; files_struct *fsp; int info; NTSTATUS status; @@ -1014,13 +1012,14 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ } /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, + status = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, NORMAL_CLOSE); /* No access if SD get failed. */ - if (!sd_size) + if (!NT_STATUS_IS_OK(status)) { return False; + } return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA, &access_granted, &status); diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 121e7f79a9..46472665e5 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -41,7 +41,6 @@ static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, NTSTATUS status; struct files_struct *fsp = NULL; struct security_descriptor *secdesc = NULL; - size_t secdesc_size; if (!VALID_STAT(*psbuf)) { if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { @@ -70,14 +69,14 @@ static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, return status; } - secdesc_size = SMB_VFS_GET_NT_ACL(fsp, fname, - (OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION), - &secdesc); - if (secdesc_size == 0) { + status = SMB_VFS_GET_NT_ACL(fsp, fname, + (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION), + &secdesc); + if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("Unable to get NT ACL for file %s\n", fname)); - return NT_STATUS_ACCESS_DENIED; + return status; } *psd = talloc_move(mem_ctx, &secdesc); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f07d64eded..d03abaeadb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2302,17 +2302,17 @@ static void call_nt_transact_rename(connection_struct *conn, Fake up a completely empty SD. *******************************************************************************/ -static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) +static NTSTATUS get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) { size_t sd_size; *ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size); if(!*ppsd) { DEBUG(0,("get_null_nt_acl: Unable to malloc space for security descriptor.\n")); - sd_size = 0; + return NT_STATUS_NO_MEMORY; } - return sd_size; + return NT_STATUS_OK; } /**************************************************************************** @@ -2337,6 +2337,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, uint32 security_info_wanted; TALLOC_CTX *mem_ctx; files_struct *fsp = NULL; + NTSTATUS status; if(parameter_count < 8) { reply_doserror(req, ERRDOS, ERRbadfunc); @@ -2371,17 +2372,20 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, */ if (!lp_nt_acl_support(SNUM(conn))) { - sd_size = get_null_nt_acl(mem_ctx, &psd); + status = get_null_nt_acl(mem_ctx, &psd); } else { - sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, security_info_wanted, &psd); + status = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, + security_info_wanted, &psd); } - if (sd_size == 0) { + if (!NT_STATUS_IS_OK(status)) { talloc_destroy(mem_ctx); - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, status); return; } + sd_size = sec_desc_size(psd); + DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); SIVAL(params,0,(uint32)sd_size); diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6e7dae4892..27953a2051 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2728,7 +2728,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) the UNIX style get ACL. ****************************************************************************/ -size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) +NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) { connection_struct *conn = fsp->conn; SMB_STRUCT_STAT sbuf; @@ -2756,7 +2756,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) /* Get the stat struct for the owner info. */ if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { - return 0; + return map_nt_error_from_unix(errno); } /* * Get the ACL from the path. @@ -2777,7 +2777,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) /* Get the stat struct for the owner info. */ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { - return 0; + return map_nt_error_from_unix(errno); } /* * Get the ACL from the fd. @@ -3027,7 +3027,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) free_inherited_info(pal); SAFE_FREE(nt_ace_list); - return sd_size; + return NT_STATUS_OK; } /**************************************************************************** @@ -3174,7 +3174,6 @@ static NTSTATUS append_parent_acl(files_struct *fsp, SMB_STRUCT_STAT sbuf; NTSTATUS status; int info; - size_t sd_size; unsigned int i, j; mode_t unx_mode; @@ -3213,13 +3212,13 @@ static NTSTATUS append_parent_acl(files_struct *fsp, return status; } - sd_size = SMB_VFS_GET_NT_ACL(parent_fsp, parent_fsp->fsp_name, - DACL_SECURITY_INFORMATION, &parent_sd ); + status = SMB_VFS_GET_NT_ACL(parent_fsp, parent_fsp->fsp_name, + DACL_SECURITY_INFORMATION, &parent_sd ); close_file(parent_fsp, NORMAL_CLOSE); - if (!sd_size) { - return NT_STATUS_ACCESS_DENIED; + if (!NT_STATUS_IS_OK(status)) { + return status; } /* @@ -4174,7 +4173,8 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) finfo.fh->fd = -1; finfo.fsp_name = CONST_DISCARD(char *,fname); - if (get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ) == 0) { + if (!NT_STATUS_IS_OK(get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, + &psd ))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); conn_free_internal( &conn ); return NULL; -- cgit From 052efa9a33d7a9a3b9ae9b038f6b3943c85c4bfc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Nov 2007 12:51:31 -0800 Subject: Remove last pstring from smbd/*.c Jeremy. (This used to be commit f1680bada913af4eaf5c0d686983018d6c8b3e5f) --- source3/smbd/message.c | 51 +++++-- source3/smbd/password.c | 70 ++++++---- source3/smbd/quotas.c | 365 ++++++++++++++++++++++++------------------------ source3/smbd/utmp.c | 64 +++++---- 4 files changed, 310 insertions(+), 240 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index b044b6f92d..12a4bc0d54 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -38,7 +38,8 @@ static fstring msgto; static void msg_deliver(void) { - pstring name; + TALLOC_CTX *ctx = talloc_tos(); + char *name = NULL; int i; int fd; char *msg; @@ -52,7 +53,10 @@ static void msg_deliver(void) } /* put it in a temporary file */ - slprintf(name,sizeof(name)-1, "%s/msg.XXXXXX",tmpdir()); + name = talloc_asprintf(ctx, "%s/msg.XXXXXX",tmpdir()); + if (!name) { + return; + } fd = smb_mkstemp(name); if (fd == -1) { @@ -63,7 +67,7 @@ static void msg_deliver(void) /* * Incoming message is in DOS codepage format. Convert to UNIX. */ - + if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **)(void *)&msg, True)) < 0 || !msg) { DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); for (i = 0; i < msgpos;) { @@ -95,14 +99,39 @@ static void msg_deliver(void) if (*lp_msg_command()) { fstring alpha_msgfrom; fstring alpha_msgto; - pstring s; - - pstrcpy(s,lp_msg_command()); - pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); - pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); - standard_sub_basic(current_user_info.smb_name, - current_user_info.domain, s, sizeof(s)); - pstring_sub(s,"%s",name); + char *s = talloc_strdup(ctx, + lp_msg_command()); + + if (!s) { + return; + } + s = talloc_string_sub(ctx, s, "%f", + alpha_strcpy(alpha_msgfrom, + msgfrom, + NULL, + sizeof(alpha_msgfrom))); + if (!s) { + return; + } + s = talloc_string_sub(ctx, s, "%t", + alpha_strcpy(alpha_msgto, + msgto, + NULL, + sizeof(alpha_msgto))); + if (!s) { + return; + } + s = talloc_sub_basic(ctx, + current_user_info.smb_name, + current_user_info.domain, + s); + if (!s) { + return; + } + s = talloc_string_sub(ctx, s, "%s",name); + if (!s) { + return; + } smbrun(s,NULL); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 995abbf663..80b541584d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -669,46 +669,51 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) /* * As user_ok can recurse doing a getgrent(), we must - * copy the member list into a pstring on the stack before + * copy the member list onto the heap before * use. Bug pointed out by leon@eatworms.swmed.edu. */ if (gptr) { - pstring member_list; + char *member_list = NULL; + size_t list_len = 0; char *member; - size_t copied_len = 0; int i; + for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) { + list_len += strlen(gptr->gr_mem[i])+1; + } + list_len++; + + member_list = SMB_MALLOC(list_len); + if (!member_list) { + endgrent(); + return NULL; + } + *member_list = '\0'; member = member_list; for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) { size_t member_len = strlen(gptr->gr_mem[i])+1; - if(copied_len+member_len < sizeof(pstring)) { - - DEBUG(10,("validate_group: = gr_mem = " - "%s\n", gptr->gr_mem[i])); - - safe_strcpy(member, gptr->gr_mem[i], - sizeof(pstring) - - copied_len - 1); - copied_len += member_len; - member += copied_len; - } else { - *member = '\0'; - } + + DEBUG(10,("validate_group: = gr_mem = " + "%s\n", gptr->gr_mem[i])); + + safe_strcpy(member, gptr->gr_mem[i], + list_len - (member-member_list)); + member += member_len; } endgrent(); member = member_list; while (*member) { - static fstring name; - fstrcpy(name,member); - if (user_ok(name,snum) && - password_ok(name,password)) { - endgrent(); - return(&name[0]); + if (user_ok(member,snum) && + password_ok(member,password)) { + char *name = talloc_strdup(talloc_tos(), + member); + SAFE_FREE(member_list); + return name; } DEBUG(10,("validate_group = member = %s\n", @@ -716,6 +721,8 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) member += strlen(member) + 1; } + + SAFE_FREE(member_list); } else { endgrent(); return NULL; @@ -790,11 +797,22 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password, /* check the user= fields and the given password */ if (!ok && lp_username(snum)) { + TALLOC_CTX *ctx = talloc_tos(); char *auser; - pstring user_list; - pstrcpy(user_list,lp_username(snum)); + char *user_list = talloc_strdup(ctx, lp_username(snum)); + + if (!user_list) { + goto check_guest; + } - pstring_sub(user_list,"%S",lp_servicename(snum)); + user_list = talloc_string_sub(ctx, + user_list, + "%S", + lp_servicename(snum)); + + if (!user_list) { + goto check_guest; + } for (auser=strtok(user_list,LIST_SEP); auser && !ok; auser = strtok(NULL,LIST_SEP)) { @@ -823,6 +841,8 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password, } } + check_guest: + /* check for a normal guest connection */ if (!ok && GUEST_OK(snum)) { fstring guestname; diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index ac6ad9d470..f47e89bd22 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -45,7 +45,7 @@ * Declare here, define at end: reduces likely "include" interaction problems. * David Lee */ -bool disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); +bool disk_quotas_vxfs(const char *name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); #endif /* VXFS_QUOTA */ @@ -223,17 +223,17 @@ bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB egrp_id = getegid(); /* find the block device file */ - + if ( sys_stat(path, &S) == -1 ) return(False) ; devno = S.st_dev ; - + if ((fp = setmntent(MOUNTED,"r")) == NULL) return(False) ; found = False ; - + while ((mnt = getmntent(fp))) { if ( sys_stat(mnt->mnt_dir,&S) == -1 ) continue ; @@ -245,7 +245,7 @@ bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB } endmntent(fp) ; - + if (!found) return(False); @@ -308,94 +308,81 @@ try to get the disk space from disk quotas (CRAY VERSION) bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { - struct mntent *mnt; - FILE *fd; - SMB_STRUCT_STAT sbuf; - SMB_DEV_T devno ; - static SMB_DEV_T devno_cached = 0 ; - static pstring name; - struct q_request request ; - struct qf_header header ; - static int quota_default = 0 ; - int found ; - - if ( sys_stat(path,&sbuf) == -1 ) - return(False) ; - - devno = sbuf.st_dev ; - - if ( devno != devno_cached ) { - - devno_cached = devno ; - - if ((fd = setmntent(KMTAB)) == NULL) - return(False) ; - - found = False ; - - while ((mnt = getmntent(fd)) != NULL) { - - if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - - if (sbuf.st_dev == devno) { - - found = True ; - break ; - - } - - } - - pstrcpy(name,mnt->mnt_dir) ; - endmntent(fd) ; - - if ( ! found ) - return(False) ; - } - - request.qf_magic = QF_MAGIC ; - request.qf_entry.id = geteuid() ; - - if (quotactl(name, Q_GETQUOTA, &request) == -1) - return(False) ; - - if ( ! request.user ) - return(False) ; - - if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) { - - if ( ! quota_default ) { - - if ( quotactl(name, Q_GETHEADER, &header) == -1 ) - return(False) ; - else - quota_default = header.user_h.def_fq ; - } - - *dfree = quota_default ; - - }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) { - - *dfree = 0 ; - - }else{ - - *dfree = request.qf_entry.user_q.f_quota ; - - } - - *dsize = request.qf_entry.user_q.f_use ; - - if ( *dfree < *dsize ) - *dfree = 0 ; - else - *dfree -= *dsize ; - - *bsize = 4096 ; /* Cray blocksize */ - - return(True) ; - + struct mntent *mnt; + FILE *fd; + SMB_STRUCT_STAT sbuf; + SMB_DEV_T devno ; + struct q_request request ; + struct qf_header header ; + int quota_default = 0 ; + bool found = false; + + if (sys_stat(path,&sbuf) == -1) { + return false; + } + + devno = sbuf.st_dev ; + + if ((fd = setmntent(KMTAB)) == NULL) { + return false; + } + + while ((mnt = getmntent(fd)) != NULL) { + if (sys_stat(mnt->mnt_dir,&sbuf) == -1) { + continue; + } + if (sbuf.st_dev == devno) { + found = frue ; + break; + } + } + + name = talloc_strdup(talloc_tos(), mnt->mnt_dir); + endmntent(fd); + if (!found) { + return false; + } + + if (!name) { + return false; + } + + request.qf_magic = QF_MAGIC ; + request.qf_entry.id = geteuid() ; + + if (quotactl(name, Q_GETQUOTA, &request) == -1) { + return false; + } + + if (!request.user) { + return False; + } + + if (request.qf_entry.user_q.f_quota == QFV_DEFAULT) { + if (!quota_default) { + if (quotactl(name, Q_GETHEADER, &header) == -1) { + return false; + } else { + quota_default = header.user_h.def_fq; + } + } + *dfree = quota_default; + } else if (request.qf_entry.user_q.f_quota == QFV_PREVENT) { + *dfree = 0; + } else { + *dfree = request.qf_entry.user_q.f_quota; + } + + *dsize = request.qf_entry.user_q.f_use; + + if (*dfree < *dsize) { + *dfree = 0; + } else { + *dfree -= *dsize; + } + + *bsize = 4096 ; /* Cray blocksize */ + return true; } @@ -466,7 +453,7 @@ static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) return (1); } -/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ +/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ static bool nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t uid = euser_id; @@ -515,11 +502,11 @@ static bool nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_B goto out; } - /* + /* * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is * no quota set, and 3 if no permission to get the quota. If 0 or 3 return * something sensible. - */ + */ switch ( quotastat ) { case 0: @@ -587,7 +574,10 @@ try to get the disk space from disk quotas (SunOS & Solaris2 version) Quota code by Peter Urbanec (amiga@cse.unsw.edu.au). ****************************************************************************/ -bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas(const char *path, + SMB_BIG_UINT *bsize, + SMB_BIG_UINT *dfree, + SMB_BIG_UINT *dsize) { uid_t euser_id; int ret; @@ -595,84 +585,90 @@ bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB #if defined(SUNOS5) struct quotctl command; int file; - static struct mnttab mnt; - static pstring name; + struct mnttab mnt; #else /* SunOS4 */ struct mntent *mnt; - static pstring name; #endif + char *name = NULL; FILE *fd; SMB_STRUCT_STAT sbuf; - SMB_DEV_T devno ; - static SMB_DEV_T devno_cached = 0 ; - static int found ; + SMB_DEV_T devno; + bool found = false; euser_id = geteuid(); - - if ( sys_stat(path,&sbuf) == -1 ) - return(False) ; - + + if (sys_stat(path,&sbuf) == -1) { + return false; + } + devno = sbuf.st_dev ; DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path, (unsigned int)devno)); - if ( devno != devno_cached ) { - devno_cached = devno ; #if defined(SUNOS5) - if ((fd = sys_fopen(MNTTAB, "r")) == NULL) - return(False) ; - - found = False ; - - while (getmntent(fd, &mnt) == 0) { - if (sys_stat(mnt.mnt_mountp, &sbuf) == -1) - continue; - - DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", - mnt.mnt_mountp, (unsigned int)devno)); - - /* quotas are only on vxfs, UFS or NFS */ - if ( (sbuf.st_dev == devno) && ( - strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || - strcmp( mnt.mnt_fstype, "nfs" ) == 0 || - strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) { - found = True ; - break; - } + if ((fd = sys_fopen(MNTTAB, "r")) == NULL) { + return false; + } + + while (getmntent(fd, &mnt) == 0) { + if (sys_stat(mnt.mnt_mountp, &sbuf) == -1) { + continue; } - - pstrcpy(name,mnt.mnt_mountp) ; - pstrcat(name,"/quotas") ; - fclose(fd) ; -#else /* SunOS4 */ - if ((fd = setmntent(MOUNTED, "r")) == NULL) - return(False) ; - - found = False ; - while ((mnt = getmntent(fd)) != NULL) { - if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev)); - if (sbuf.st_dev == devno) { - found = True ; + + DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", + mnt.mnt_mountp, (unsigned int)devno)); + + /* quotas are only on vxfs, UFS or NFS */ + if ((sbuf.st_dev == devno) && ( + strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || + strcmp( mnt.mnt_fstype, "nfs" ) == 0 || + strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) { + found = true; + name = talloc_asprintf(talloc_tos(), + "%s/quotas", + mnt.mnt_mountp); break; - } } - - pstrcpy(name,mnt->mnt_fsname) ; - endmntent(fd) ; -#endif } - if ( ! found ) - return(False) ; + fclose(fd); +#else /* SunOS4 */ + if ((fd = setmntent(MOUNTED, "r")) == NULL) { + return false; + } + + while ((mnt = getmntent(fd)) != NULL) { + if (sys_stat(mnt->mnt_dir,&sbuf) == -1) { + continue; + } + DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", + mnt->mnt_dir, + (unsigned int)sbuf.st_dev)); + if (sbuf.st_dev == devno) { + found = true; + name = talloc_strdup(talloc_tos(), + mnt->mnt_fsname); + break; + } + } + endmntent(fd); +#endif + if (!found) { + return false; + } + + if (!name) { + return false; + } become_root(); #if defined(SUNOS5) - if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) { + if (strcmp(mnt.mnt_fstype, "nfs") == 0) { bool retval; - DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special)); - retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); + DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", + mnt.mnt_special)); + retval = nfs_quotas(mnt.mnt_special, + euser_id, bsize, dfree, dsize); unbecome_root(); return retval; } @@ -680,7 +676,7 @@ bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); if((file=sys_open(name, O_RDONLY,0))<0) { unbecome_root(); - return(False); + return false; } command.op = Q_GETQUOTA; command.uid = euser_id; @@ -695,7 +691,8 @@ bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB unbecome_root(); if (ret < 0) { - DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) )); + DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", + strerror(errno) )); #if defined(SUNOS5) && defined(VXFS_QUOTA) /* If normal quotactl() fails, try vxfs private calls */ @@ -703,24 +700,27 @@ bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype)); if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) { bool retval; - retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize); - return(retval); + retval = disk_quotas_vxfs(name, path, + bsize, dfree, dsize); + return retval; } #else - return(False); + return false; #endif } /* If softlimit is zero, set it equal to hardlimit. */ - - if (D.dqb_bsoftlimit==0) + + if (D.dqb_bsoftlimit==0) { D.dqb_bsoftlimit = D.dqb_bhardlimit; + } - /* Use softlimit to determine disk space. A user exceeding the quota is told - * that there's no space left. Writes might actually work for a bit if the - * hardlimit is set higher than softlimit. Effectively the disk becomes - * made of rubber latex and begins to expand to accommodate the user :-) + /* Use softlimit to determine disk space. A user exceeding the quota + * is told that there's no space left. Writes might actually work for + * a bit if the hardlimit is set higher than softlimit. Effectively + * the disk becomes made of rubber latex and begins to expand to + * accommodate the user :-) */ if (D.dqb_bsoftlimit==0) @@ -731,13 +731,15 @@ bool disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB if (D.dqb_curblocks > D.dqb_bsoftlimit) { *dfree = 0; *dsize = D.dqb_curblocks; - } else + } else { *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - - DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", + } + + DEBUG(5,("disk_quotas for path \"%s\" returning " + "bsize %.0f, dfree %.0f, dsize %.0f\n", path,(double)*bsize,(double)*dfree,(double)*dsize)); - return(True); + return true; } @@ -1351,14 +1353,14 @@ Hints for porting: #include #include -bool disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +bool disk_quotas_vxfs(const char *name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t user_id, euser_id; int ret; struct vx_dqblk D; struct vx_quotctl quotabuf; struct vx_genioctl genbuf; - pstring qfname; + char *qfname; int file; /* @@ -1367,7 +1369,10 @@ bool disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B * it might be easier to examine and adjust it here. * Fortunately, VxFS seems not to mind at present. */ - pstrcpy(qfname, name) ; + qfname = talloc_strdup(talloc_tos(), name); + if (!qfname) { + return false; + } /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */ euser_id = geteuid(); @@ -1434,20 +1439,20 @@ bool disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B bool disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) { - (*bsize) = 512; /* This value should be ignored */ + (*bsize) = 512; /* This value should be ignored */ - /* And just to be sure we set some values that hopefully */ - /* will be larger that any possible real-world value */ - (*dfree) = (SMB_BIG_UINT)-1; - (*dsize) = (SMB_BIG_UINT)-1; + /* And just to be sure we set some values that hopefully */ + /* will be larger that any possible real-world value */ + (*dfree) = (SMB_BIG_UINT)-1; + (*dsize) = (SMB_BIG_UINT)-1; - /* As we have select not to use quotas, allways fail */ - return False; + /* As we have select not to use quotas, allways fail */ + return false; } #endif /* WITH_QUOTAS */ #else /* HAVE_SYS_QUOTAS */ -/* wrapper to the new sys_quota interface +/* wrapper to the new sys_quota interface this file should be removed later */ bool disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index c2908e33cc..e82bbea3b3 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -207,30 +207,36 @@ static const char *ll_pathname = * utmp{,x}: try "utmp dir", then default (a define) * wtmp{,x}: try "wtmp dir", then "utmp dir", then default (a define) */ -static void uw_pathname(pstring fname, const char *uw_name, const char *uw_default) +static char *uw_pathname(TALLOC_CTX *ctx, + const char *uw_name, + const char *uw_default) { - pstring dirname; - - pstrcpy(dirname, ""); + char *dirname = NULL; /* For w-files, first look for explicit "wtmp dir" */ if (uw_name[0] == 'w') { - pstrcpy(dirname,lp_wtmpdir()); + dirname = talloc_strdup(ctx, lp_wtmpdir()); + if (!dirname) { + return NULL; + } trim_char(dirname,'\0','/'); } /* For u-files and non-explicit w-dir, look for "utmp dir" */ - if (dirname == 0 || strlen(dirname) == 0) { - pstrcpy(dirname,lp_utmpdir()); + if (!dirname == 0 || strlen(dirname) == 0) { + dirname = talloc_strdup(ctx, lp_utmpdir()); + if (!dirname) { + return NULL; + } trim_char(dirname,'\0','/'); } /* If explicit directory above, use it */ - if (dirname != 0 && strlen(dirname) != 0) { - pstrcpy(fname, dirname); - pstrcat(fname, "/"); - pstrcat(fname, uw_name); - return; + if (dirname && strlen(dirname) != 0) { + return talloc_asprintf(ctx, + "%s/%s", + dirname, + uw_name); } /* No explicit directory: attempt to use default paths */ @@ -240,16 +246,15 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau */ DEBUG(2,("uw_pathname: unable to determine pathname\n")); } - pstrcpy(fname, uw_default); + return talloc_strdup(ctx, uw_default); } #ifndef HAVE_PUTUTLINE - /**************************************************************************** Update utmp file directly. No subroutine interface: probably a BSD system. ****************************************************************************/ -static void pututline_my(pstring uname, struct utmp *u, bool claim) +static void pututline_my(const char *uname, struct utmp *u, bool claim) { DEBUG(1,("pututline_my: not yet implemented\n")); /* BSD implementor: may want to consider (or not) adjusting "lastlog" */ @@ -263,7 +268,7 @@ static void pututline_my(pstring uname, struct utmp *u, bool claim) Credit: Michail Vidiassov ****************************************************************************/ -static void updwtmp_my(pstring wname, struct utmp *u, bool claim) +static void updwtmp_my(const char *wname, struct utmp *u, bool claim) { int fd; struct stat buf; @@ -308,12 +313,16 @@ static void updwtmp_my(pstring wname, struct utmp *u, bool claim) static void utmp_nox_update(struct utmp *u, bool claim) { - pstring uname, wname; + char *uname = NULL; + char *wname = NULL; #if defined(PUTUTLINE_RETURNS_UTMP) struct utmp *urc; #endif /* PUTUTLINE_RETURNS_UTMP */ - uw_pathname(uname, "utmp", ut_pathname); + uname = uw_pathname(talloc_tos(), "utmp", ut_pathname); + if (!uname) { + return; + } DEBUG(2,("utmp_nox_update: uname:%s\n", uname)); #ifdef HAVE_PUTUTLINE @@ -341,7 +350,10 @@ static void utmp_nox_update(struct utmp *u, bool claim) } #endif /* HAVE_PUTUTLINE */ - uw_pathname(wname, "wtmp", wt_pathname); + wname = uw_pathname(talloc_tos(), "wtmp", wt_pathname); + if (!wname) { + return; + } DEBUG(2,("utmp_nox_update: wname:%s\n", wname)); if (strlen(wname) != 0) { #ifdef HAVE_UPDWTMP @@ -398,7 +410,8 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, bool claim) DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n")); utmp_nox_update(u, claim); #else - pstring uname, wname; + char *uname = NULL; + char *wname = NULL; struct utmpx ux, *uxrc; getutmpx(u, &ux); @@ -413,9 +426,12 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, bool claim) utmp_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)); #endif - uw_pathname(uname, "utmpx", ux_pathname); - uw_pathname(wname, "wtmpx", wx_pathname); - DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname)); + uname = uw_pathname(talloc_tos(), "utmpx", ux_pathname); + wname = uw_pathname(talloc_tos(), "wtmpx", wx_pathname); + if (uname && wname) { + DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname)); + } + /* * Check for either uname or wname being empty. * Some systems, such as Redhat 6, have a "utmpx.h" which doesn't @@ -423,7 +439,7 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, bool claim) * Also, our local installation has not provided an override. * Drop to non-x method. (E.g. RH6 has good defaults in "utmp.h".) */ - if ((strlen(uname) == 0) || (strlen(wname) == 0)) { + if (!uname || !wname || (strlen(uname) == 0) || (strlen(wname) == 0)) { utmp_nox_update(u, claim); } else { utmpxname(uname); -- cgit From 8ab992524abf765f4cf18286d98e2ccd7bcae6af Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 13 Nov 2007 23:26:38 +0100 Subject: Fix potential orphaned open files. Calling can_access_file could lead to orphaned open files when SMB_VFS_GET_NT_ACL returned ENOSYS (not implemented). Michael (This used to be commit f4f700cf0c1657c36e801fab20fe7b1a4efcb714) --- source3/smbd/file_access.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 46472665e5..a58bcdd891 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -76,12 +76,14 @@ static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, &secdesc); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("Unable to get NT ACL for file %s\n", fname)); - return status; + goto done; } *psd = talloc_move(mem_ctx, &secdesc); + +done: close_file(fsp, NORMAL_CLOSE); - return NT_STATUS_OK; + return status; } static bool can_access_file_acl(struct connection_struct *conn, -- cgit From 68be9a820059ee96dd26c527efd7c14e679d3f2c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Nov 2007 14:19:52 -0800 Subject: More pstring removal. This one was tricky. I had to add one horror (pstring_clean_name()) which will have to remain until I've removed all pstrings from the client code. Jeremy. (This used to be commit 1ea3ac80146b83c2522b69e7747c823366a2b47d) --- source3/smbd/server.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 028dacc27e..aa85aca77e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -954,6 +954,7 @@ extern void build_options(bool screen); POPT_COMMON_DYNCONFIG POPT_TABLEEND }; + TALLOC_CTX *frame = talloc_stackframe(); /* Setup tos. */ load_case_tables(); @@ -1231,7 +1232,7 @@ extern void build_options(bool screen); /* Setup oplocks */ if (!init_oplocks(smbd_messaging_context())) exit(1); - + /* Setup aio signal handler. */ initialize_async_io_handler(); @@ -1262,6 +1263,8 @@ extern void build_options(bool screen); exit(1); } + TALLOC_FREE(frame); + smbd_process(); namecache_shutdown(); -- cgit From 3f437f681aa130438774cc5f4b8f16d00b43b377 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 16 Nov 2007 00:34:37 +0100 Subject: Fix an implicit cast warning. Michael (This used to be commit 4ab3b23a630e822e3fdf1ab4d08330625b0e4fb6) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 80b541584d..7bba458218 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -684,7 +684,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum) } list_len++; - member_list = SMB_MALLOC(list_len); + member_list = (char *)SMB_MALLOC(list_len); if (!member_list) { endgrent(); return NULL; -- cgit From acb829ecc3b9af3f141425ecac032a7c722a1815 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Nov 2007 18:27:26 -0800 Subject: Add MAX_DNS_NAME_LENGTH, remove more pstrings. Jeremy. (This used to be commit a1725f4ff7ed375808c78ac661b539557748d0a5) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 53fc1be586..6dc979cf3b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -521,7 +521,7 @@ static void validate_my_share_entries(int num, char *str = talloc_asprintf(talloc_tos(), "Got a deferred entry without a request: " "PANIC: %s\n", - share_mode_str(num, share_entry)); + share_mode_str(talloc_tos(), num, share_entry)); smb_panic(str); } @@ -533,7 +533,7 @@ static void validate_my_share_entries(int num, share_entry->share_file_id); if (!fsp) { DEBUG(0,("validate_my_share_entries: PANIC : %s\n", - share_mode_str(num, share_entry) )); + share_mode_str(talloc_tos(), num, share_entry) )); smb_panic("validate_my_share_entries: Cannot match a " "share entry with an open file\n"); } @@ -560,7 +560,7 @@ static void validate_my_share_entries(int num, { char *str; DEBUG(0,("validate_my_share_entries: PANIC : %s\n", - share_mode_str(num, share_entry) )); + share_mode_str(talloc_tos(), num, share_entry) )); str = talloc_asprintf(talloc_tos(), "validate_my_share_entries: " "file %s, oplock_type = 0x%x, op_type = 0x%x\n", -- cgit From 6ff701e695e847414afb0320a6701fe252d3f311 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Nov 2007 13:14:24 -0800 Subject: Match the 3.0.27a version of this function. Jeremy. (This used to be commit 629406cbe77a5d56a258ac414ab47f3e89183e52) --- source3/smbd/srvstr.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index 68e61033ae..bae77d5d4b 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -23,24 +23,14 @@ extern int max_send; /* Make sure we can't write a string past the end of the buffer */ -size_t srvstr_push_fn(const char *function, unsigned int line, +size_t srvstr_push_fn(const char *function, unsigned int line, const char *base_ptr, uint16 smb_flags2, void *dest, const char *src, int dest_len, int flags) { - size_t buf_used = PTR_DIFF(dest, base_ptr); - if (dest_len == -1) { - if (((ptrdiff_t)dest < (ptrdiff_t)base_ptr) || (buf_used > (size_t)max_send)) { -#if 0 - DEBUG(0, ("Pushing string of 'unlimited' length into non-SMB buffer!\n")); -#endif - return push_string_fn(function, line, base_ptr, - smb_flags2, dest, src, -1, - flags); - } - return push_string_fn(function, line, base_ptr, smb_flags2, - dest, src, max_send - buf_used, flags); + if (dest_len < 0) { + return 0; } - + /* 'normal' push into size-specified buffer */ return push_string_fn(function, line, base_ptr, smb_flags2, dest, src, dest_len, flags); -- cgit From b059e2cbf1d6190c996a1ff6b8f426a493ae937c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Nov 2007 17:06:57 -0800 Subject: Ensure we use PATH_MAX for symlinks. Jeremy. (This used to be commit a90ef69350c5efcf8dcf95d4853cbe3c662d1ba3) --- source3/smbd/trans2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3abc0d065c..bb24db9ee1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4168,7 +4168,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_UNIX_LINK: { - char *buffer = TALLOC_ARRAY(ctx, char, 1024); + char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1); if (!buffer) { reply_nterror(req, NT_STATUS_NO_MEMORY); @@ -4187,7 +4187,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return; #endif len = SMB_VFS_READLINK(conn,fullpathname, - buffer, 1023); + buffer, PATH_MAX); if (len == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); -- cgit From cae4c742a896c6adb02b3e7a3c091d02aebb7339 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 Nov 2007 17:43:28 -0800 Subject: Always check return from push_ascii. Jeremy. (This used to be commit 9c3d10521e691169cfbb8b728f123911c3c970ae) --- source3/smbd/lanman.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4bd59a7aa6..b2e435e97f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -112,6 +112,9 @@ static int CopyExpanded(connection_struct *conn, return 0; } l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE); + if (l == -1) { + return 0; + } (*dst) += l; (*p_space_remaining) -= l; return l; @@ -124,6 +127,9 @@ static int CopyAndAdvance(char **dst, char *src, int *n) return 0; } l = push_ascii(*dst,src,*n, STR_TERMINATE); + if (l == -1) { + return 0; + } (*dst) += l; (*n) -= l; return l; -- cgit From 61b37c73eeff8548c63df76e7d650c27746ca720 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Nov 2007 15:31:18 -0800 Subject: Paranoia check that space_remaining never goes -ve. Jeremy. (This used to be commit 76f9c0b2dccffbff7cbf98aa63f50b48ad7cb9cb) --- source3/smbd/trans2.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bb24db9ee1..323d78cde1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1371,7 +1371,9 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, SSVAL(p,20,mode); p += 23; nameptr = p; - p += align_string(pdata, p, 0); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + p += ucs2_align(base_data, p, 0); + } len = srvstr_push(base_data, flags2, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE); @@ -2022,7 +2024,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if(got_exact_match) finished = True; - space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + /* Ensure space_remaining never goes -ve. */ + if (PTR_DIFF(p,pdata) > max_data_bytes) { + space_remaining = 0; + out_of_space = true; + } else { + space_remaining = max_data_bytes - PTR_DIFF(p,pdata); + } } /* Check if we can close the dirptr */ -- cgit From c20077e825f55ca669cb89bbb206bfd3ad2a6307 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 Nov 2007 16:41:12 +0100 Subject: smbd: close_stat() should be static metze (This used to be commit e186b60afacfb609968b581a6d32757e1885a319) --- source3/smbd/close.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d2ee73d09d..eb610f7d1a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -541,7 +541,7 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty Close a 'stat file' opened internally. ****************************************************************************/ -NTSTATUS close_stat(files_struct *fsp) +static NTSTATUS close_stat(files_struct *fsp) { /* * Do the code common to files and directories. -- cgit From d4bfafa29c62c69b002b1ca9f527c51c00fd3fd6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 26 Nov 2007 15:28:13 +0100 Subject: Fix bug 5055 (This used to be commit 8bcd2df841bae63e7d58c35d4728b7d853471697) --- source3/smbd/lanman.c | 2 +- source3/smbd/trans2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b2e435e97f..17ab891c64 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1380,7 +1380,7 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid, } /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set - any other bit (they may just set this bit on it's own) they + any other bit (they may just set this bit on its own) they want all the locally seen servers. However this bit can be set on its own so set the requested servers to be ALL - DOMAIN_ENUM. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 323d78cde1..e37f6ffbfd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3279,7 +3279,7 @@ static char *store_file_unix_basic(connection_struct *conn, * * XXX: this really should be behind the VFS interface. To do this, we would * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field. - * Each VFS module could then implement it's own mapping as appropriate for the + * Each VFS module could then implement its own mapping as appropriate for the * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS. */ static const struct {unsigned stat_fflag; unsigned smb_fflag;} -- cgit From d2cf97aeba14a4d336fb57b01f19bd5a08dcb003 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Nov 2007 13:24:54 -0800 Subject: Remove the explicit TALLOC_CTX * from cli_struct. Make us very explicit about how long a talloc ctx should last. Jeremy. (This used to be commit ba9e2be2b5a59684e854609f9d82ea1633448c62) --- source3/smbd/change_trust_pw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 8ed0975781..fc58e97ea7 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -82,7 +82,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m goto failed; } - nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain); + nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, netlogon_pipe->mem_ctx, domain); cli_shutdown(cli); cli = NULL; -- cgit From f692694b99319ef1f534ea29f001922656402cdf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Nov 2007 17:25:41 -0800 Subject: Remove PSTRING_LEN from smbd/ nmbd/. Remove pstring from libsmb/clidfs.c except for a nasty hack (that will be removed when pstrings are gone from client/). Jeremy. (This used to be commit cc257b71d13daa47e6f2315d0f07a60eb4aaeca6) --- source3/smbd/password.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 7bba458218..75f05dea67 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -402,14 +402,14 @@ void add_session_user(const char *user) len_session_userlist) ) { char *newlist; - if (len_session_userlist > 128 * PSTRING_LEN) { + if (len_session_userlist > 128 * 1024) { DEBUG(3,("add_session_user: session userlist already " "too large.\n")); return; } newlist = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR( session_userlist, - len_session_userlist + PSTRING_LEN ); + len_session_userlist + 1024 ); if( newlist == NULL ) { DEBUG(1,("Unable to resize session_userlist\n")); return; @@ -418,7 +418,7 @@ void add_session_user(const char *user) *newlist = '\0'; } session_userlist = newlist; - len_session_userlist += PSTRING_LEN; + len_session_userlist += 1024; } safe_strcat(session_userlist," ",len_session_userlist-1); -- cgit From 5066f7c878001522baf66fd3b73871df188827cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 15:01:01 +0100 Subject: In nttransact_create, we also need to check for delete readonly (This used to be commit f4cc9cab518e97c1049aaad7516aba212ae15c95) --- source3/smbd/nttrans.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d03abaeadb..9ff1cac140 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1535,7 +1535,8 @@ static void call_nt_transact_create(connection_struct *conn, && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS)) { - if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) || + if (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) + && !lp_delete_readonly(SNUM(conn))) || !can_delete_file_in_directory(conn, fname)) { TALLOC_FREE(case_state); reply_nterror(req, NT_STATUS_ACCESS_DENIED); -- cgit From a2366187ad4e1308c8885ee6f928c747596a6c67 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 12:54:11 +0100 Subject: Bump up debug level Fix bug 5115 (This used to be commit d3c839c22edeca2de68574a8f5dd328080577f3a) --- source3/smbd/fake_file.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index e4f71193e1..31fe030f46 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -111,8 +111,9 @@ NTSTATUS open_fake_file(connection_struct *conn, /* access check */ if (current_user.ut.uid != 0) { - DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n", - lp_servicename(SNUM(conn)),fname,conn->user)); + DEBUG(3, ("open_fake_file_shared: access_denied to " + "service[%s] file[%s] user[%s]\n", + lp_servicename(SNUM(conn)),fname,conn->user)); return NT_STATUS_ACCESS_DENIED; } -- cgit From b9342eaaa6bf61f559e4173d7ea58acc1a0a9705 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 3 Dec 2007 15:19:22 -0800 Subject: Remove unused wpstring and macros. Stop using pstrcpy in smbd/*.c Jeremy. (This used to be commit e72bce5b62fb0a9d0ff4a3d76490219994f303cf) --- source3/smbd/lanman.c | 60 +++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 26 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 17ab891c64..b194fc6231 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2130,6 +2130,7 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid, NTSTATUS result; DOM_SID user_sid; enum lsa_SidType type; + char *endp = NULL; TALLOC_CTX *mem_ctx; if (!str1 || !str2 || !UserName || !p) { @@ -2168,6 +2169,7 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid, SSVAL(*rparam,2,0); /* converter word */ p = *rdata; + endp = *rdata + *rdata_len; mem_ctx = talloc_new(NULL); if (mem_ctx == NULL) { @@ -2181,7 +2183,7 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid, return False; } - /* Lookup the user information; This should only be one of + /* Lookup the user information; This should only be one of our accounts (not remote domains) */ become_root(); /* ROOT BLOCK */ @@ -2218,12 +2220,11 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid, } for (i=0; i return parameter number of entries * h -> return parameter total number of users */ - + resume_context = get_safe_SVAL(param,tpscnt,p,0,-1); cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0); DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", @@ -2301,6 +2303,7 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid, } p = *rdata; + endp = *rdata + *rdata_len; become_root(); search = pdb_search_users(ACB_NORMAL); @@ -2319,13 +2322,13 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid, for (i=0; i= 10) { SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ - pstrcpy(p2,"Comment"); + strlcpy(p2,"Comment",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ - pstrcpy(p2,"UserComment"); + strlcpy(p2,"UserComment",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3385,7 +3393,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); + strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3398,13 +3406,13 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); + strlcpy(p2, vuser && vuser->homedir ? vuser->homedir : "",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ - pstrcpy(p2,""); + strlcpy(p2,"",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3414,7 +3422,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ SSVALS(p,usri11_num_logons,-1); /* num logons */ SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ - pstrcpy(p2,"\\\\*"); + strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3422,7 +3430,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SSVAL(p,usri11_country_code,0); /* country code */ SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ - pstrcpy(p2,""); + strlcpy(p2,"",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3449,7 +3457,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, SSVAL(p,42, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); + strlcpy(p2, vuser && vuser->homedir ? vuser->homedir : "",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3458,7 +3466,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, *p2++ = 0; SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ - pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); + strlcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3466,14 +3474,14 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, if (uLevel == 2) { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); + strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; } SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ - pstrcpy(p2,""); + strlcpy(p2,"",PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; -- cgit From 0e9a1c24a067832b2d3962e851001767973643d8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Dec 2007 12:53:21 -0800 Subject: Fix crash bug with vl's new trans handling in old transs calls. Make this look like the (working) transs2 handling (replace inbuf, not write to outbuf - outbuf isn't allocated yet so you get a null deref). Jeremy. (This used to be commit f04e37a630f8e7538d670d34db4ea7fc7c0b50a3) --- source3/smbd/ipc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0360417c56..eed293d50d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -752,7 +752,7 @@ void reply_transs(connection_struct *conn, struct smb_request *req) goto bad_param; memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, - dcnt); + dcnt); } if ((state->received_param < state->total_param) || @@ -761,10 +761,11 @@ void reply_transs(connection_struct *conn, struct smb_request *req) return; } - /* construct_reply_common has done us the favor to pre-fill the - * command field with SMBtranss which is wrong :-) - */ - SCVAL(req->outbuf,smb_com,SMBtrans); + /* + * construct_reply_common will copy smb_com from inbuf to + * outbuf. SMBtranss is wrong here. + */ + SCVAL(req->inbuf,smb_com,SMBtrans); handle_trans(conn, req, state); -- cgit From 80287d65d0ac9f88b01f8dbc926cd71ea49df29f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 29 Nov 2007 15:15:33 +0100 Subject: tiny refactoring (This used to be commit 7f15a9f5a281052d2bed13a622b2fc9a24c62096) --- source3/smbd/nttrans.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9ff1cac140..d5abb372cf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1289,6 +1289,7 @@ static void call_nt_transact_create(connection_struct *conn, NTSTATUS status; size_t param_len; struct case_semantics_state *case_state = NULL; + SMB_BIG_UINT allocation_size; TALLOC_CTX *ctx = talloc_tos(); DEBUG(5,("call_nt_transact_create\n")); @@ -1330,6 +1331,10 @@ static void call_nt_transact_create(connection_struct *conn, sd_len = IVAL(params,36); ea_len = IVAL(params,40); root_dir_fid = (uint16)IVAL(params,4); + allocation_size = (SMB_BIG_UINT)IVAL(params,12); +#ifdef LARGE_SMB_OFF_T + allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); +#endif /* Ensure the data_len is correct for the sd and ea values given. */ if ((ea_len + sd_len > data_count) || @@ -1700,10 +1705,6 @@ static void call_nt_transact_create(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12); -#ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); -#endif if (allocation_size && (allocation_size > file_len)) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { -- cgit From c6cb3ed323f2762746b1cd83b468418aca652907 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 29 Nov 2007 15:38:00 +0100 Subject: Tiny refactoring (This used to be commit b79b16d637d41a356c036c6aac932e4504d2d7b0) --- source3/smbd/nttrans.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d5abb372cf..353cfcd339 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -583,8 +583,7 @@ void reply_ntcreate_and_X(connection_struct *conn, * This filename is relative to a directory fid. */ char *rel_fname = NULL; - files_struct *dir_fsp = file_fsp( - SVAL(req->inbuf, smb_ntcreate_RootDirectoryFid)); + files_struct *dir_fsp = file_fsp(root_dir_fid); if(!dir_fsp) { reply_doserror(req, ERRDOS, ERRbadfid); @@ -1376,7 +1375,7 @@ static void call_nt_transact_create(connection_struct *conn, * This filename is relative to a directory fid. */ char *tmpname = NULL; - files_struct *dir_fsp = file_fsp(SVAL(params,4)); + files_struct *dir_fsp = file_fsp(root_dir_fid); if(!dir_fsp) { reply_doserror(req, ERRDOS, ERRbadfid); -- cgit From 692725d9741b4602bc9ce16006eb84e546067445 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 29 Nov 2007 15:45:53 +0100 Subject: consolidate srvstr_get_path in ntcreate_and_X (This used to be commit 4a2d502903934f4c3dc6b31595fe77a2013dbc21) --- source3/smbd/nttrans.c | 148 ++++++++++++++++++++----------------------------- 1 file changed, 59 insertions(+), 89 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 353cfcd339..4d5e107ca6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -540,17 +540,27 @@ void reply_ntcreate_and_X(connection_struct *conn, allocation_size |= (((SMB_BIG_UINT)IVAL(req->inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf), 0, STR_TERMINATE, &status); + + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + END_PROFILE(SMBntcreateX); + return; + } + DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " "file_attributes = 0x%x, share_access = 0x%x, " "create_disposition = 0x%x create_options = 0x%x " - "root_dir_fid = 0x%x\n", + "root_dir_fid = 0x%x, fname = %s\n", (unsigned int)flags, (unsigned int)access_mask, (unsigned int)file_attributes, (unsigned int)share_access, (unsigned int)create_disposition, (unsigned int)create_options, - (unsigned int)root_dir_fid )); + (unsigned int)root_dir_fid, + fname)); /* * If it's an IPC, use the pipe handler. @@ -578,11 +588,11 @@ void reply_ntcreate_and_X(connection_struct *conn, * Get the file name. */ - if(root_dir_fid != 0) { + if (root_dir_fid != 0) { /* * This filename is relative to a directory fid. */ - char *rel_fname = NULL; + char *parent_fname = NULL; files_struct *dir_fsp = file_fsp(root_dir_fid); if(!dir_fsp) { @@ -593,16 +603,6 @@ void reply_ntcreate_and_X(connection_struct *conn, if(!dir_fsp->is_directory) { - srvstr_get_path(ctx, (char *)req->inbuf, - req->flags2, &fname, - smb_buf(req->inbuf), 0, - STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; - } - /* * Check to see if this is a mac fork of some kind. */ @@ -633,8 +633,8 @@ void reply_ntcreate_and_X(connection_struct *conn, * normally by srvstr_get_path and unix_convert * explicitly rejects paths containing ./. */ - fname = talloc_strdup(ctx,""); - if (!fname) { + parent_fname = talloc_strdup(ctx,""); + if (!parent_fname) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBntcreateX); return; @@ -646,55 +646,35 @@ void reply_ntcreate_and_X(connection_struct *conn, * Copy in the base directory name. */ - fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); - if (!fname) { - reply_nterror( - req, NT_STATUS_NO_MEMORY); + parent_fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); + if (!parent_fname) { + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBntcreateX); return; } - memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); + memcpy(parent_fname, dir_fsp->fsp_name, + dir_name_len+1); /* * Ensure it ends in a '/'. * We used TALLOC_SIZE +2 to add space for the '/'. */ - if(dir_name_len && - (fname[dir_name_len-1] != '\\') && - (fname[dir_name_len-1] != '/')) { - fname[dir_name_len] = '/'; - fname[dir_name_len+1] = '\0'; + if(dir_name_len + && (parent_fname[dir_name_len-1] != '\\') + && (parent_fname[dir_name_len-1] != '/')) { + parent_fname[dir_name_len] = '/'; + parent_fname[dir_name_len+1] = '\0'; } } - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &rel_fname, - smb_buf(req->inbuf), 0, - STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; - } - fname = talloc_asprintf(ctx, "%s%s", - fname, - rel_fname); - if (!fname) { - reply_nterror( - req, NT_STATUS_NO_MEMORY); + fname = talloc_asprintf(ctx, "%s%s", parent_fname, fname); + if (fname == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBntcreateX); return; } } else { - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf), 0, - STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; - } - /* * Check to see if this is a mac fork of some kind. */ @@ -1361,6 +1341,14 @@ static void call_nt_transact_create(connection_struct *conn, } } + srvstr_get_path(ctx, params, req->flags2, &fname, + params+53, parameter_count-53, + STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + if (create_options & FILE_OPEN_BY_FILE_ID) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); return; @@ -1374,7 +1362,7 @@ static void call_nt_transact_create(connection_struct *conn, /* * This filename is relative to a directory fid. */ - char *tmpname = NULL; + char *parent_fname = NULL; files_struct *dir_fsp = file_fsp(root_dir_fid); if(!dir_fsp) { @@ -1383,14 +1371,6 @@ static void call_nt_transact_create(connection_struct *conn, } if(!dir_fsp->is_directory) { - srvstr_get_path(ctx, params, req->flags2, &fname, - params+53, - parameter_count-53, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } /* * Check to see if this is a mac fork of some kind. @@ -1402,6 +1382,13 @@ static void call_nt_transact_create(connection_struct *conn, return; } + /* + we need to handle the case when we get a + relative open relative to a file and the + pathname is blank - this is a reopen! + (hint from demyn plantenberg) + */ + reply_doserror(req, ERRDOS, ERRbadfid); return; } @@ -1413,8 +1400,8 @@ static void call_nt_transact_create(connection_struct *conn, * normally by srvstr_get_path and unix_convert * explicitly rejects paths containing ./. */ - fname = talloc_strdup(ctx,""); - if (!fname) { + parent_fname = talloc_strdup(ctx,""); + if (!parent_fname) { reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -1425,51 +1412,34 @@ static void call_nt_transact_create(connection_struct *conn, * Copy in the base directory name. */ - fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); + parent_fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); if (!fname) { reply_nterror(req, NT_STATUS_NO_MEMORY); return; } - memcpy(fname, dir_fsp->fsp_name, dir_name_len+1); + memcpy(parent_fname, dir_fsp->fsp_name, + dir_name_len+1); /* * Ensure it ends in a '/'. * We used TALLOC_SIZE +2 to add space for the '/'. */ - if(dir_name_len && - (fname[dir_name_len-1] != '\\') && - (fname[dir_name_len-1] != '/')) { - fname[dir_name_len] = '/'; - fname[dir_name_len+1] = '\0'; + if(dir_name_len + && (parent_fname[dir_name_len-1] != '\\') + && (parent_fname[dir_name_len-1] != '/')) { + parent_fname[dir_name_len] = '/'; + parent_fname[dir_name_len+1] = '\0'; } } - srvstr_get_path(ctx, params, req->flags2, &tmpname, - params+53, - parameter_count-53, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - fname = talloc_asprintf(ctx, "%s%s", - fname, - tmpname); - if (!fname) { - reply_nterror( - req, NT_STATUS_NO_MEMORY); + fname = talloc_asprintf(ctx, "%s%s", parent_fname, fname); + if (fname == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBntcreateX); return; } } else { - srvstr_get_path(ctx, params, req->flags2, &fname, params+53, - parameter_count-53, - STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - /* * Check to see if this is a mac fork of some kind. */ -- cgit From cb7706cf2c078d09f013b74685aa658af37cf5ba Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 14:38:19 +0100 Subject: TALLOC_FREE early (This used to be commit 4b1f0d1d93d1e7bd0b4fa641d4e9629af8234d71) --- source3/smbd/nttrans.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4d5e107ca6..12709f9e02 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -593,6 +593,7 @@ void reply_ntcreate_and_X(connection_struct *conn, * This filename is relative to a directory fid. */ char *parent_fname = NULL; + char *tmp; files_struct *dir_fsp = file_fsp(root_dir_fid); if(!dir_fsp) { @@ -668,12 +669,14 @@ void reply_ntcreate_and_X(connection_struct *conn, } } - fname = talloc_asprintf(ctx, "%s%s", parent_fname, fname); - if (fname == NULL) { + tmp = talloc_asprintf(ctx, "%s%s", parent_fname, fname); + if (tmp == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBntcreateX); return; } + TALLOC_FREE(fname); + fname = tmp; } else { /* * Check to see if this is a mac fork of some kind. @@ -1363,6 +1366,7 @@ static void call_nt_transact_create(connection_struct *conn, * This filename is relative to a directory fid. */ char *parent_fname = NULL; + char *tmp; files_struct *dir_fsp = file_fsp(root_dir_fid); if(!dir_fsp) { @@ -1433,12 +1437,14 @@ static void call_nt_transact_create(connection_struct *conn, } } - fname = talloc_asprintf(ctx, "%s%s", parent_fname, fname); - if (fname == NULL) { + tmp = talloc_asprintf(ctx, "%s%s", parent_fname, fname); + if (tmp == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBntcreateX); return; } + TALLOC_FREE(fname); + fname = tmp; } else { /* * Check to see if this is a mac fork of some kind. -- cgit From acaea7ece8b56db47885fb5263e46bee17f83051 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 14:49:58 +0100 Subject: Tiny refactoring (This used to be commit 481e35eba8e130041848887ec5fb6212e331eb14) --- source3/smbd/nttrans.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 12709f9e02..68eb9f0985 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -716,10 +716,10 @@ void reply_ntcreate_and_X(connection_struct *conn, if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); + END_PROFILE(SMBntcreateX); + return; } - else { - reply_nterror(req, status); - } + reply_nterror(req, status); END_PROFILE(SMBntcreateX); return; } -- cgit From 96a1fb4b5da12666ac3164e65b76051dcbd77512 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 14:52:25 +0100 Subject: Tiny refactoring Reformatting, consolidate oplock calculation to the same place in both routines (This used to be commit a855808f4851a800055bfee5df39ca72057e55f9) --- source3/smbd/nttrans.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 68eb9f0985..aaf4a408e6 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -704,6 +704,12 @@ void reply_ntcreate_and_X(connection_struct *conn, } } + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) + ? BATCH_OPLOCK : 0; + } + /* * Now contruct the smb_open_mode value from the filename, * desired access and the share access. @@ -724,11 +730,6 @@ void reply_ntcreate_and_X(connection_struct *conn, return; } - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - if (oplock_request) { - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - } - /* * Ordinary file or directory. */ @@ -1458,7 +1459,8 @@ static void call_nt_transact_create(connection_struct *conn, oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; if (oplock_request) { - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) + ? BATCH_OPLOCK : 0; } /* -- cgit From 629278abdf580796ad79a7e03fedb31b49489631 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 14:55:56 +0100 Subject: Put posix semantic calculation in the same place in both routines (This used to be commit f6d62226a33cdff41ad7881996d856b7130ef15c) --- source3/smbd/nttrans.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index aaf4a408e6..9e6b933b64 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1467,15 +1467,6 @@ static void call_nt_transact_create(connection_struct *conn, * Ordinary file or directory. */ - /* - * Check if POSIX semantics are wanted. - */ - - if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { - case_state = set_posix_case_semantics(NULL, conn); - file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; - } - status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, @@ -1491,6 +1482,15 @@ static void call_nt_transact_create(connection_struct *conn, return; } + /* + * Check if POSIX semantics are wanted. + */ + + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + case_state = set_posix_case_semantics(NULL, conn); + file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; + } + status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(case_state); -- cgit From adb8d1b17911b5c7009e292917ccc209961fdde2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 14:57:46 +0100 Subject: Reformatting (This used to be commit fb900184feeda37691cf9bd57c029988648de9f8) --- source3/smbd/nttrans.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9e6b933b64..aed237fc65 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -759,11 +759,12 @@ void reply_ntcreate_and_X(connection_struct *conn, return; } - /* This is the correct thing to do (check every time) but can_delete is - expensive (it may have to read the parent directory permissions). So - for now we're not doing it unless we have a strong hint the client - is really going to delete this file. If the client is forcing FILE_CREATE - let the filesystem take care of the permissions. */ + /* This is the correct thing to do (check every time) but can_delete + * is expensive (it may have to read the parent directory + * permissions). So for now we're not doing it unless we have a strong + * hint the client is really going to delete this file. If the client + * is forcing FILE_CREATE let the filesystem take care of the + * permissions. */ /* Setting FILE_SHARE_DELETE is the hint. */ @@ -1505,11 +1506,12 @@ static void call_nt_transact_create(connection_struct *conn, return; } - /* This is the correct thing to do (check every time) but can_delete is - expensive (it may have to read the parent directory permissions). So - for now we're not doing it unless we have a strong hint the client - is really going to delete this file. If the client is forcing FILE_CREATE - let the filesystem take care of the permissions. */ + /* This is the correct thing to do (check every time) but can_delete + * is expensive (it may have to read the parent directory + * permissions). So for now we're not doing it unless we have a strong + * hint the client is really going to delete this file. If the client + * is forcing FILE_CREATE let the filesystem take care of the + * permissions. */ /* Setting FILE_SHARE_DELETE is the hint. */ -- cgit From 177bf9a877b8ed20d9abe8ada32b8d82ff9a6149 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 15:05:18 +0100 Subject: Move pulling the ea list out of the way (This used to be commit 753e640f49125c319d7b8f2db262e273a1727691) --- source3/smbd/nttrans.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index aed237fc65..c19ba6519f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1269,7 +1269,6 @@ static void call_nt_transact_create(connection_struct *conn, struct timespec a_timespec; struct timespec m_timespec; struct ea_list *ea_list = NULL; - char *pdata = NULL; NTSTATUS status; size_t param_len; struct case_semantics_state *case_state = NULL; @@ -1344,6 +1343,14 @@ static void call_nt_transact_create(connection_struct *conn, reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } + + /* We have already checked that ea_len <= data_count here. */ + ea_list = read_nttrans_ea_list(talloc_tos(), data + sd_len, + ea_len); + if (ea_list == NULL) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } } srvstr_get_path(ctx, params, req->flags2, &fname, @@ -1539,19 +1546,6 @@ static void call_nt_transact_create(connection_struct *conn, } #endif - if (ea_len) { - pdata = data + sd_len; - - /* We have already checked that ea_len <= data_count here. */ - ea_list = read_nttrans_ea_list(talloc_tos(), pdata, - ea_len); - if (!ea_list ) { - TALLOC_FREE(case_state); - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - } - /* * If it's a request for a directory open, deal with it separately. */ -- cgit From 222cd323cae37e87ab60dec5fa3ac2a3da7d36aa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 15:07:58 +0100 Subject: Align formatting, one TALLOC_FREE is enough (This used to be commit 5bf4647dea71305d9a92875a751b24c8a2e4a916) --- source3/smbd/nttrans.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c19ba6519f..bf29a2341d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -872,8 +872,9 @@ void reply_ntcreate_and_X(connection_struct *conn, if (create_options & FILE_NON_DIRECTORY_FILE) { TALLOC_FREE(case_state); - reply_force_nterror(req, - NT_STATUS_FILE_IS_A_DIRECTORY); + reply_force_nterror( + req, + NT_STATUS_FILE_IS_A_DIRECTORY); END_PROFILE(SMBntcreateX); return; } @@ -1591,7 +1592,8 @@ static void call_nt_transact_create(connection_struct *conn, if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { /* - * Fail the open if it was explicitly a non-directory file. + * Fail the open if it was explicitly a non-directory + * file. */ if (create_options & FILE_NON_DIRECTORY_FILE) { @@ -1663,8 +1665,6 @@ static void call_nt_transact_create(connection_struct *conn, } } - TALLOC_FREE(case_state); - file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); if(fattr == 0) { -- cgit From 825dddff8fe42d6f460ec06ad81374e382f0a4fc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 19:03:25 +0100 Subject: Reformatting (This used to be commit 719941605333a453c4219aed45780862c94a5c7c) --- source3/smbd/nttrans.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bf29a2341d..139163cb87 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1321,26 +1321,29 @@ static void call_nt_transact_create(connection_struct *conn, #endif /* Ensure the data_len is correct for the sd and ea values given. */ - if ((ea_len + sd_len > data_count) || - (ea_len > data_count) || (sd_len > data_count) || - (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) { - DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n", - (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count )); + if ((ea_len + sd_len > data_count) + || (ea_len > data_count) || (sd_len > data_count) + || (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) { + DEBUG(10, ("call_nt_transact_create - ea_len = %u, sd_len = " + "%u, data_count = %u\n", (unsigned int)ea_len, + (unsigned int)sd_len, (unsigned int)data_count)); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } if (ea_len) { if (!lp_ea_support(SNUM(conn))) { - DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n", - (unsigned int)ea_len )); + DEBUG(10, ("call_nt_transact_create - ea_len = %u but " + "EA's not supported.\n", + (unsigned int)ea_len)); reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); return; } if (ea_len < 10) { - DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n", - (unsigned int)ea_len )); + DEBUG(10,("call_nt_transact_create - ea_len = %u - " + "too small (should be more than 10)\n", + (unsigned int)ea_len )); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } -- cgit From ffeb5aaaa42c7a779609c1bcd745e9e403f32a67 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 19:16:52 +0100 Subject: Split out sd parsing (This used to be commit 5a9d147e41b260cb620f026291786eeb95ebc64f) --- source3/smbd/nttrans.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 139163cb87..38cda65eb1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1264,6 +1264,7 @@ static void call_nt_transact_create(connection_struct *conn, uint32 create_disposition; uint32 create_options; uint32 sd_len; + struct security_descriptor *sd; uint32 ea_len; uint16 root_dir_fid; struct timespec c_timespec; @@ -1331,6 +1332,18 @@ static void call_nt_transact_create(connection_struct *conn, return; } + if (sd_len) { + status = unmarshall_sec_desc(ctx, (uint8_t *)data, sd_len, + &sd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("call_nt_transact_create: " + "unmarshall_sec_desc failed: %s\n", + nt_errstr(status))); + reply_nterror(req, status); + return; + } + } + if (ea_len) { if (!lp_ea_support(SNUM(conn))) { DEBUG(10, ("call_nt_transact_create - ea_len = %u but " @@ -1641,14 +1654,29 @@ static void call_nt_transact_create(connection_struct *conn, * Patch for bug #2242 from Tom Lackemann . */ - if (lp_nt_acl_support(SNUM(conn)) && sd_len && info == FILE_WAS_CREATED) { - uint32 saved_access_mask = fsp->access_mask; - - /* We have already checked that sd_len <= data_count here. */ + if (lp_nt_acl_support(SNUM(conn)) && (info == FILE_WAS_CREATED) + && (sd != NULL)) { + uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; + uint32_t saved_access_mask = fsp->access_mask; fsp->access_mask = FILE_GENERIC_ALL; - status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION); + if (sd->owner_sid==0) { + sec_info_sent &= ~OWNER_SECURITY_INFORMATION; + } + if (sd->group_sid==0) { + sec_info_sent &= ~GROUP_SECURITY_INFORMATION; + } + if (sd->sacl==0) { + sec_info_sent &= ~SACL_SECURITY_INFORMATION; + } + if (sd->dacl==0) { + sec_info_sent &= ~DACL_SECURITY_INFORMATION; + } + + status = SMB_VFS_FSET_NT_ACL( + fsp, fsp->fh->fd, sec_info_sent, sd); + if (!NT_STATUS_IS_OK(status)) { close_file(fsp,ERROR_CLOSE); TALLOC_FREE(case_state); -- cgit From db1a23586a59e1b008c6c69cbf9d1f589a246ed2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 20:03:47 +0100 Subject: Tiny refactorings (This used to be commit f3421c3b86aece4f8303e864c5df97485db77f88) --- source3/smbd/nttrans.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 38cda65eb1..397b634f13 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -710,10 +710,6 @@ void reply_ntcreate_and_X(connection_struct *conn, ? BATCH_OPLOCK : 0; } - /* - * Now contruct the smb_open_mode value from the filename, - * desired access and the share access. - */ status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, @@ -918,8 +914,10 @@ void reply_ntcreate_and_X(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (allocation_size + && (allocation_size > (SMB_BIG_UINT)file_len)) { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,ERROR_CLOSE); /* Can't set allocation size on a directory. */ @@ -1387,7 +1385,7 @@ static void call_nt_transact_create(connection_struct *conn, * Get the file name. */ - if(root_dir_fid != 0) { + if (root_dir_fid != 0) { /* * This filename is relative to a directory fid. */ @@ -1407,8 +1405,8 @@ static void call_nt_transact_create(connection_struct *conn, */ if( is_ntfs_stream_name(fname)) { - reply_nterror(req, - NT_STATUS_OBJECT_PATH_NOT_FOUND); + reply_nterror( + req, NT_STATUS_OBJECT_PATH_NOT_FOUND); return; } @@ -1443,7 +1441,7 @@ static void call_nt_transact_create(connection_struct *conn, */ parent_fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); - if (!fname) { + if (!parent_fname) { reply_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -1488,16 +1486,11 @@ static void call_nt_transact_create(connection_struct *conn, ? BATCH_OPLOCK : 0; } - /* - * Ordinary file or directory. - */ - status = resolve_dfspath(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, &fname); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); @@ -1709,8 +1702,10 @@ static void call_nt_transact_create(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - if (allocation_size && (allocation_size > file_len)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (allocation_size + && (allocation_size > (SMB_BIG_UINT)file_len)) { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,ERROR_CLOSE); /* Can't set allocation size on a directory. */ -- cgit From 727746b8fb46a012e2ea901cffa5b91aec772f8d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 21:31:52 +0100 Subject: Reformatting, also allow quotas for transact_create (This used to be commit 956aae7a57364debf724a7ef0bd0074119a24d24) --- source3/smbd/nttrans.c | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 397b634f13..8ea8e09433 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -682,23 +682,29 @@ void reply_ntcreate_and_X(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname)) { - enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname); + if (is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type; + + fake_file_type = is_fake_file(fname); + if (fake_file_type!=FAKE_FILE_TYPE_NONE) { /* - * Here we go! support for changing the disk quotas --metze + * Here we go! support for changing the disk + * quotas --metze * - * We need to fake up to open this MAGIC QUOTA file - * and return a valid FID. + * We need to fake up to open this MAGIC QUOTA + * file and return a valid FID. * - * w2k close this file directly after openening - * xp also tries a QUERY_FILE_INFO on the file and then close it + * w2k close this file directly after + * openening xp also tries a QUERY_FILE_INFO + * on the file and then close it */ - reply_ntcreate_and_X_quota(conn, req, - fake_file_type, fname); - } else { - reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); + reply_ntcreate_and_X_quota( + conn, req, fake_file_type, fname); + END_PROFILE(SMBntcreateX); + return; } + reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); END_PROFILE(SMBntcreateX); return; } @@ -1474,7 +1480,27 @@ static void call_nt_transact_create(connection_struct *conn, * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname)) { + if (is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type; + + fake_file_type = is_fake_file(fname); + + if (fake_file_type!=FAKE_FILE_TYPE_NONE) { + /* + * Here we go! support for changing the disk + * quotas --metze + * + * We need to fake up to open this MAGIC QUOTA + * file and return a valid FID. + * + * w2k close this file directly after + * openening xp also tries a QUERY_FILE_INFO + * on the file and then close it + */ + reply_ntcreate_and_X_quota( + conn, req, fake_file_type, fname); + return; + } reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); return; } -- cgit From 3f1ed0fc1918d357b103f401a725b5477cd61b60 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Dec 2007 22:36:17 +0100 Subject: Implement create_file() Rip out the cores of reply_ntcreate_and_X and call_nt_transact_create Volker (This used to be commit 8cd27e4a7a1a2df0ff686ebe0b1a779511effd27) --- source3/smbd/nttrans.c | 1095 ++++++++++++++++-------------------------------- 1 file changed, 368 insertions(+), 727 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8ea8e09433..1ba2a335bf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -452,136 +452,42 @@ static void do_ntcreate_pipe_open(connection_struct *conn, chain_reply(req); } -/**************************************************************************** - Reply to an NT create and X call for a quota file. -****************************************************************************/ - -static void reply_ntcreate_and_X_quota(connection_struct *conn, - struct smb_request *req, - enum FAKE_FILE_TYPE fake_file_type, - const char *fname) -{ - char *p; - uint32 desired_access = IVAL(req->inbuf,smb_ntcreate_DesiredAccess); - files_struct *fsp; - NTSTATUS status; - - status = open_fake_file(conn, fake_file_type, fname, desired_access, - &fsp); - - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - reply_outbuf(req, 34, 0); - - p = (char *)req->outbuf + smb_vwv2; - - /* SCVAL(p,0,NO_OPLOCK_RETURN); */ - p++; - SSVAL(p,0,fsp->fnum); - - DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - - chain_reply(req); -} - -/**************************************************************************** - Reply to an NT create and X call. -****************************************************************************/ - -void reply_ntcreate_and_X(connection_struct *conn, - struct smb_request *req) +static NTSTATUS create_file(connection_struct *conn, + struct smb_request *req, + uint16_t root_dir_fid, + char *fname, + uint32_t flags, + uint32_t access_mask, + uint32_t file_attributes, + uint32_t share_access, + uint32_t create_disposition, + uint32_t create_options, + int oplock_request, + SMB_BIG_UINT allocation_size, + struct security_descriptor *sd, + struct ea_list *ea_list, + + files_struct **result, + int *pinfo, + uint8_t *poplock_granted, + SMB_STRUCT_STAT *psbuf, + SMB_OFF_T *pfile_len) { - char *fname = NULL; - uint32 flags; - uint32 access_mask; - uint32 file_attributes; - uint32 share_access; - uint32 create_disposition; - uint32 create_options; - uint16 root_dir_fid; - SMB_BIG_UINT allocation_size; - /* Breakout the oplock request bits so we can set the - reply bits separately. */ - int oplock_request = 0; - uint32 fattr=0; + TALLOC_CTX *frame = talloc_stackframe(); + struct case_semantics_state *case_state = NULL; + uint32_t fattr; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; - int info = 0; + int info = FILE_WAS_OPENED; files_struct *fsp = NULL; - char *p = NULL; - struct timespec c_timespec; - struct timespec a_timespec; - struct timespec m_timespec; - bool extended_oplock_granted = False; + uint8_t oplock_granted = NO_OPLOCK_RETURN; NTSTATUS status; - struct case_semantics_state *case_state = NULL; - TALLOC_CTX *ctx = talloc_tos(); - - START_PROFILE(SMBntcreateX); - - if (req->wct < 24) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - flags = IVAL(req->inbuf,smb_ntcreate_Flags); - access_mask = IVAL(req->inbuf,smb_ntcreate_DesiredAccess); - file_attributes = IVAL(req->inbuf,smb_ntcreate_FileAttributes); - share_access = IVAL(req->inbuf,smb_ntcreate_ShareAccess); - create_disposition = IVAL(req->inbuf,smb_ntcreate_CreateDisposition); - create_options = IVAL(req->inbuf,smb_ntcreate_CreateOptions); - root_dir_fid = (uint16)IVAL(req->inbuf,smb_ntcreate_RootDirectoryFid); - - allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_ntcreate_AllocationSize); -#ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(req->inbuf,smb_ntcreate_AllocationSize + 4)) << 32); -#endif - - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf), 0, STR_TERMINATE, &status); - - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; - } - - DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " - "file_attributes = 0x%x, share_access = 0x%x, " - "create_disposition = 0x%x create_options = 0x%x " - "root_dir_fid = 0x%x, fname = %s\n", - (unsigned int)flags, - (unsigned int)access_mask, - (unsigned int)file_attributes, - (unsigned int)share_access, - (unsigned int)create_disposition, - (unsigned int)create_options, - (unsigned int)root_dir_fid, - fname)); - - /* - * If it's an IPC, use the pipe handler. - */ - if (IS_IPC(conn)) { - if (lp_nt_pipe_support()) { - do_ntcreate_pipe_open(conn, req); - END_PROFILE(SMBntcreateX); - return; - } else { - reply_doserror(req, ERRDOS, ERRnoaccess); - END_PROFILE(SMBntcreateX); - return; - } - } + SET_STAT_INVALID(sbuf); if (create_options & FILE_OPEN_BY_FILE_ID) { - reply_nterror(req, NT_STATUS_NOT_SUPPORTED); - END_PROFILE(SMBntcreateX); - return; + status = NT_STATUS_NOT_SUPPORTED; + goto fail; } /* @@ -593,26 +499,22 @@ void reply_ntcreate_and_X(connection_struct *conn, * This filename is relative to a directory fid. */ char *parent_fname = NULL; - char *tmp; files_struct *dir_fsp = file_fsp(root_dir_fid); - if(!dir_fsp) { - reply_doserror(req, ERRDOS, ERRbadfid); - END_PROFILE(SMBntcreateX); - return; + if (dir_fsp == NULL) { + status = NT_STATUS_INVALID_HANDLE; + goto fail; } - if(!dir_fsp->is_directory) { + if (!dir_fsp->is_directory) { /* * Check to see if this is a mac fork of some kind. */ - if( is_ntfs_stream_name(fname)) { - reply_nterror( - req, NT_STATUS_OBJECT_PATH_NOT_FOUND); - END_PROFILE(SMBntcreateX); - return; + if (is_ntfs_stream_name(fname)) { + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; } /* @@ -622,9 +524,8 @@ void reply_ntcreate_and_X(connection_struct *conn, (hint from demyn plantenberg) */ - reply_doserror(req, ERRDOS, ERRbadfid); - END_PROFILE(SMBntcreateX); - return; + status = NT_STATUS_INVALID_HANDLE; + goto fail; } if (ISDOT(dir_fsp->fsp_name)) { @@ -634,11 +535,10 @@ void reply_ntcreate_and_X(connection_struct *conn, * normally by srvstr_get_path and unix_convert * explicitly rejects paths containing ./. */ - parent_fname = talloc_strdup(ctx,""); - if (!parent_fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBntcreateX); - return; + parent_fname = talloc_strdup(talloc_tos(), ""); + if (parent_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; } } else { size_t dir_name_len = strlen(dir_fsp->fsp_name); @@ -647,11 +547,11 @@ void reply_ntcreate_and_X(connection_struct *conn, * Copy in the base directory name. */ - parent_fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); - if (!parent_fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBntcreateX); - return; + parent_fname = TALLOC_ARRAY(talloc_tos(), char, + dir_name_len+2); + if (parent_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; } memcpy(parent_fname, dir_fsp->fsp_name, dir_name_len+1); @@ -669,14 +569,12 @@ void reply_ntcreate_and_X(connection_struct *conn, } } - tmp = talloc_asprintf(ctx, "%s%s", parent_fname, fname); - if (tmp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBntcreateX); - return; + fname = talloc_asprintf(talloc_tos(), "%s%s", parent_fname, + fname); + if (fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; } - TALLOC_FREE(fname); - fname = tmp; } else { /* * Check to see if this is a mac fork of some kind. @@ -687,26 +585,28 @@ void reply_ntcreate_and_X(connection_struct *conn, fake_file_type = is_fake_file(fname); - if (fake_file_type!=FAKE_FILE_TYPE_NONE) { - /* - * Here we go! support for changing the disk - * quotas --metze - * - * We need to fake up to open this MAGIC QUOTA - * file and return a valid FID. - * - * w2k close this file directly after - * openening xp also tries a QUERY_FILE_INFO - * on the file and then close it - */ - reply_ntcreate_and_X_quota( - conn, req, fake_file_type, fname); - END_PROFILE(SMBntcreateX); - return; + if (fake_file_type == FAKE_FILE_TYPE_NONE) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); - END_PROFILE(SMBntcreateX); - return; + + /* + * Here we go! support for changing the disk quotas + * --metze + * + * We need to fake up to open this MAGIC QUOTA file + * and return a valid FID. + * + * w2k close this file directly after openening xp + * also tries a QUERY_FILE_INFO on the file and then + * close it + */ + status = open_fake_file(conn, fake_file_type, fname, + access_mask, &fsp); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + goto done; } } @@ -716,20 +616,18 @@ void reply_ntcreate_and_X(connection_struct *conn, ? BATCH_OPLOCK : 0; } - status = resolve_dfspath(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, - &fname); + status = resolve_dfspath( + talloc_tos(), conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname, &fname); + if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - END_PROFILE(SMBntcreateX); - return; - } - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; + /* + * For PATH_NOT_COVERED we had + * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + * ERRSRV, ERRbadpath); + * Need to fix in callers + */ + goto fail; } /* @@ -741,24 +639,21 @@ void reply_ntcreate_and_X(connection_struct *conn, */ if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { - case_state = set_posix_case_semantics(NULL, conn); + case_state = set_posix_case_semantics(talloc_tos(), conn); file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); + status = unix_convert(talloc_tos(), conn, fname, False, &fname, NULL, + &sbuf); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; + goto fail; } + /* All file access must go through check_name() */ + status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); - reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; + goto fail; } /* This is the correct thing to do (check every time) but can_delete @@ -773,15 +668,12 @@ void reply_ntcreate_and_X(connection_struct *conn, if (lp_acl_check_permissions(SNUM(conn)) && (create_disposition != FILE_CREATE) && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS)) { - if (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) - && !lp_delete_readonly(SNUM(conn))) || - !can_delete_file_in_directory(conn, fname)) { - TALLOC_FREE(case_state); - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - END_PROFILE(SMBntcreateX); - return; - } + && (access_mask & DELETE_ACCESS) + && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) + && !lp_delete_readonly(SNUM(conn))) + || !can_delete_file_in_directory(conn, fname))) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; } #if 0 @@ -789,9 +681,8 @@ void reply_ntcreate_and_X(connection_struct *conn, if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && !user_has_privileges(current_user.nt_user_token, &se_security)) { - TALLOC_FREE(case_state); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD); + status = NT_STATUS_PRIVILEGE_NOT_HELD; + goto fail; } #endif @@ -799,71 +690,35 @@ void reply_ntcreate_and_X(connection_struct *conn, * If it's a request for a directory open, deal with it separately. */ - if(create_options & FILE_DIRECTORY_FILE) { + if (create_options & FILE_DIRECTORY_FILE) { /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - TALLOC_FREE(case_state); - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBntcreateX); - return; + status = NT_STATUS_INVALID_PARAMETER; + goto fail; } - oplock_request = 0; - status = open_directory(conn, req, fname, &sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - &info, &fsp); + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + &info, &fsp); } else { /* * Ordinary file case. */ - /* NB. We have a potential bug here. If we - * cause an oplock break to ourselves, then we - * could end up processing filename related - * SMB requests whilst we await the oplock - * break response. As we may have changed the - * filename case semantics to be POSIX-like, - * this could mean a filename request could - * fail when it should succeed. This is a rare - * condition, but eventually we must arrange - * to restore the correct case semantics - * before issuing an oplock break request to - * our client. JRA. */ - - status = open_file_ntcreate(conn, req, fname, &sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - oplock_request, - &info, &fsp); - - /* We cheat here. There are two cases we - * care about. One is a directory rename, - * where the NT client will attempt to - * open the source directory for - * DELETE access. Note that when the - * NT client does this it does *not* - * set the directory bit in the - * request packet. This is translated - * into a read/write open - * request. POSIX states that any open - * for write request on a directory - * will generate an EISDIR error, so - * we can catch this here and open a - * pseudo handle that is flagged as a - * directory. The second is an open - * for a permissions read only, which - * we handle in the open_file_stat case. JRA. - */ + status = open_file_ntcreate( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, &info, &fsp); if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { @@ -873,37 +728,72 @@ void reply_ntcreate_and_X(connection_struct *conn, */ if (create_options & FILE_NON_DIRECTORY_FILE) { - TALLOC_FREE(case_state); - reply_force_nterror( - req, - NT_STATUS_FILE_IS_A_DIRECTORY); - END_PROFILE(SMBntcreateX); - return; + status = NT_STATUS_FILE_IS_A_DIRECTORY; + goto fail; } oplock_request = 0; - status = open_directory(conn, req, fname, - &sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - &info, &fsp); + status = open_directory( + conn, req, fname, &sbuf, access_mask, + share_access, create_disposition, + create_options, file_attributes, + &info, &fsp); } } TALLOC_FREE(case_state); if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(req->mid)) { - /* We have re-scheduled this call. */ - END_PROFILE(SMBntcreateX); - return; + goto fail; + } + + /* + * According to the MS documentation, the only time the security + * descriptor is applied to the opened file is iff we *created* the + * file; an existing file stays the same. + * + * Also, it seems (from observation) that you can open the file with + * any access mask but you can still write the sd. We need to override + * the granted access before we call set_sd + * Patch for bug #2242 from Tom Lackemann . + */ + + if ((sd != NULL) && (info == FILE_WAS_CREATED) + && lp_nt_acl_support(SNUM(conn))) { + + uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; + uint32_t saved_access_mask = fsp->access_mask; + + if (sd->owner_sid==0) { + sec_info_sent &= ~OWNER_SECURITY_INFORMATION; + } + if (sd->group_sid==0) { + sec_info_sent &= ~GROUP_SECURITY_INFORMATION; + } + if (sd->sacl==0) { + sec_info_sent &= ~SACL_SECURITY_INFORMATION; + } + if (sd->dacl==0) { + sec_info_sent &= ~DACL_SECURITY_INFORMATION; + } + + fsp->access_mask = FILE_GENERIC_ALL; + + status = SMB_VFS_FSET_NT_ACL( + fsp, fsp->fh->fd, sec_info_sent, sd); + + fsp->access_mask = saved_access_mask; + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { + status = set_ea(conn, fsp, fname, ea_list); + if (!NT_STATUS_IS_OK(status)) { + goto fail; } - reply_openerror(req, status); - END_PROFILE(SMBntcreateX); - return; } file_len = sbuf.st_size; @@ -912,10 +802,8 @@ void reply_ntcreate_and_X(connection_struct *conn, fattr = FILE_ATTRIBUTE_NORMAL; } if (!fsp->is_directory && (fattr & aDIR)) { - close_file(fsp,ERROR_CLOSE); - reply_doserror(req, ERRDOS, ERRnoaccess); - END_PROFILE(SMBntcreateX); - return; + status = NT_STATUS_ACCESS_DENIED; + goto fail; } /* Save the requested allocation size. */ @@ -925,17 +813,14 @@ void reply_ntcreate_and_X(connection_struct *conn, fsp->initial_allocation_size = smb_roundup( fsp->conn, allocation_size); if (fsp->is_directory) { - close_file(fsp,ERROR_CLOSE); /* Can't set allocation size on a directory. */ - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - END_PROFILE(SMBntcreateX); - return; + status = NT_STATUS_ACCESS_DENIED; + goto fail; } - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,ERROR_CLOSE); - reply_nterror(req, NT_STATUS_DISK_FULL); - END_PROFILE(SMBntcreateX); - return; + if (vfs_allocate_file_space( + fsp, fsp->initial_allocation_size) == -1) { + status = NT_STATUS_DISK_FULL; + goto fail; } } else { fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); @@ -948,59 +833,186 @@ void reply_ntcreate_and_X(connection_struct *conn, * correct bit for extended oplock reply. */ - if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - extended_oplock_granted = True; - } - - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - extended_oplock_granted = True; - } - - if (flags & EXTENDED_RESPONSE_REQUIRED) { - /* This is very strange. We - * return 50 words, but only set - * the wcnt to 42 ? It's definately - * what happens on the wire.... - */ - reply_outbuf(req, 50, 0); - SCVAL(req->outbuf,smb_wct,42); - } else { - reply_outbuf(req, 34, 0); - } - - p = (char *)req->outbuf + smb_vwv2; + if (oplock_request && + (lp_fake_oplocks(SNUM(conn)) + || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { - /* - * Currently as we don't support level II oplocks we just report - * exclusive & batch here. - */ + /* + * Exclusive oplock granted + */ - if (extended_oplock_granted) { if (flags & REQUEST_BATCH_OPLOCK) { - SCVAL(p,0, BATCH_OPLOCK_RETURN); + oplock_granted = BATCH_OPLOCK_RETURN; } else { - SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN); + oplock_granted = EXCLUSIVE_OPLOCK_RETURN; } } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { - SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); + oplock_granted = LEVEL_II_OPLOCK_RETURN; } else { - SCVAL(p,0,NO_OPLOCK_RETURN); + oplock_granted = NO_OPLOCK_RETURN; } - p++; - SSVAL(p,0,fsp->fnum); - p += 2; - if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) { - SIVAL(p,0,FILE_WAS_SUPERSEDED); - } else { - SIVAL(p,0,info); - } - p += 4; + done: + *result = fsp; + *pinfo = info; + *poplock_granted = oplock_granted; + *psbuf = sbuf; + *pfile_len = file_len; + TALLOC_FREE(frame); + return NT_STATUS_OK; - /* Create time. */ - c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - a_timespec = get_atimespec(&sbuf); - m_timespec = get_mtimespec(&sbuf); + fail: + if (fsp != NULL) { + close_file(fsp, ERROR_CLOSE); + fsp = NULL; + } + TALLOC_FREE(frame); + return status; +} + +/**************************************************************************** + Reply to an NT create and X call. +****************************************************************************/ + +void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) +{ + char *fname = NULL; + uint32 flags; + uint32 access_mask; + uint32 file_attributes; + uint32 share_access; + uint32 create_disposition; + uint32 create_options; + uint16 root_dir_fid; + SMB_BIG_UINT allocation_size; + /* Breakout the oplock request bits so we can set the + reply bits separately. */ + int oplock_request = 0; + uint32 fattr=0; + SMB_OFF_T file_len = 0; + SMB_STRUCT_STAT sbuf; + int info = 0; + files_struct *fsp = NULL; + char *p = NULL; + struct timespec c_timespec; + struct timespec a_timespec; + struct timespec m_timespec; + NTSTATUS status; + uint8_t oplock_granted = NO_OPLOCK_RETURN; + TALLOC_CTX *ctx = talloc_tos(); + + START_PROFILE(SMBntcreateX); + + if (req->wct < 24) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + flags = IVAL(req->inbuf,smb_ntcreate_Flags); + access_mask = IVAL(req->inbuf,smb_ntcreate_DesiredAccess); + file_attributes = IVAL(req->inbuf,smb_ntcreate_FileAttributes); + share_access = IVAL(req->inbuf,smb_ntcreate_ShareAccess); + create_disposition = IVAL(req->inbuf,smb_ntcreate_CreateDisposition); + create_options = IVAL(req->inbuf,smb_ntcreate_CreateOptions); + root_dir_fid = (uint16)IVAL(req->inbuf,smb_ntcreate_RootDirectoryFid); + + allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf, + smb_ntcreate_AllocationSize); +#ifdef LARGE_SMB_OFF_T + allocation_size |= (((SMB_BIG_UINT)IVAL( + req->inbuf, + smb_ntcreate_AllocationSize + 4)) << 32); +#endif + + srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, + smb_buf(req->inbuf), 0, STR_TERMINATE, &status); + + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + END_PROFILE(SMBntcreateX); + return; + } + + DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " + "file_attributes = 0x%x, share_access = 0x%x, " + "create_disposition = 0x%x create_options = 0x%x " + "root_dir_fid = 0x%x, fname = %s\n", + (unsigned int)flags, + (unsigned int)access_mask, + (unsigned int)file_attributes, + (unsigned int)share_access, + (unsigned int)create_disposition, + (unsigned int)create_options, + (unsigned int)root_dir_fid, + fname)); + + /* + * If it's an IPC, use the pipe handler. + */ + + if (IS_IPC(conn)) { + if (lp_nt_pipe_support()) { + do_ntcreate_pipe_open(conn, req); + END_PROFILE(SMBntcreateX); + return; + } else { + reply_doserror(req, ERRDOS, ERRnoaccess); + END_PROFILE(SMBntcreateX); + return; + } + } + + status = create_file(conn, req, root_dir_fid, fname, flags, + access_mask, file_attributes, share_access, + create_disposition, create_options, + oplock_request, allocation_size, NULL, NULL, + &fsp, &info, &oplock_granted, &sbuf, &file_len); + + if (!NT_STATUS_IS_OK(status)) { + if (open_was_deferred(req->mid)) { + /* We have re-scheduled this call, no error. */ + END_PROFILE(SMBntcreateX); + return; + } + reply_nterror(req, status); + END_PROFILE(SMBntcreateX); + return; + } + + DEBUG(10, ("create_file returned fsp %p\n", fsp)); + + if (flags & EXTENDED_RESPONSE_REQUIRED) { + /* This is very strange. We + * return 50 words, but only set + * the wcnt to 42 ? It's definately + * what happens on the wire.... + */ + reply_outbuf(req, 50, 0); + SCVAL(req->outbuf,smb_wct,42); + } else { + reply_outbuf(req, 34, 0); + } + + p = (char *)req->outbuf + smb_vwv2; + + SCVAL(p, 0, oplock_granted); + + p++; + SSVAL(p,0,fsp->fnum); + p += 2; + if ((create_disposition == FILE_SUPERSEDE) + && (info == FILE_WAS_OVERWRITTEN)) { + SIVAL(p,0,FILE_WAS_SUPERSEDED); + } else { + SIVAL(p,0,info); + } + p += 4; + + /* Create time. */ + c_timespec = get_create_timespec( + &sbuf,lp_fake_dir_create_times(SNUM(conn))); + a_timespec = get_atimespec(&sbuf); + m_timespec = get_mtimespec(&sbuf); if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&c_timespec); @@ -1031,7 +1043,8 @@ void reply_ntcreate_and_X(connection_struct *conn, if (flags & EXTENDED_RESPONSE_REQUIRED) { uint32 perms = 0; p += 25; - if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) { + if (fsp->is_directory + || can_write_to_file(conn, fname, &sbuf)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; @@ -1039,7 +1052,8 @@ void reply_ntcreate_and_X(connection_struct *conn, SIVAL(p,0,perms); } - DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); + DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", + fsp->fnum, fsp->fsp_name)); chain_reply(req); END_PROFILE(SMBntcreateX); @@ -1260,7 +1274,6 @@ static void call_nt_transact_create(connection_struct *conn, int info = 0; files_struct *fsp = NULL; char *p = NULL; - bool extended_oplock_granted = False; uint32 flags; uint32 access_mask; uint32 file_attributes; @@ -1277,8 +1290,8 @@ static void call_nt_transact_create(connection_struct *conn, struct ea_list *ea_list = NULL; NTSTATUS status; size_t param_len; - struct case_semantics_state *case_state = NULL; SMB_BIG_UINT allocation_size; + uint8_t oplock_granted; TALLOC_CTX *ctx = talloc_tos(); DEBUG(5,("call_nt_transact_create\n")); @@ -1382,386 +1395,21 @@ static void call_nt_transact_create(connection_struct *conn, return; } - if (create_options & FILE_OPEN_BY_FILE_ID) { - reply_nterror(req, NT_STATUS_NOT_SUPPORTED); - return; - } - - /* - * Get the file name. - */ - - if (root_dir_fid != 0) { - /* - * This filename is relative to a directory fid. - */ - char *parent_fname = NULL; - char *tmp; - files_struct *dir_fsp = file_fsp(root_dir_fid); - - if(!dir_fsp) { - reply_doserror(req, ERRDOS, ERRbadfid); - return; - } - - if(!dir_fsp->is_directory) { - - /* - * Check to see if this is a mac fork of some kind. - */ - - if( is_ntfs_stream_name(fname)) { - reply_nterror( - req, NT_STATUS_OBJECT_PATH_NOT_FOUND); - return; - } - - /* - we need to handle the case when we get a - relative open relative to a file and the - pathname is blank - this is a reopen! - (hint from demyn plantenberg) - */ - - reply_doserror(req, ERRDOS, ERRbadfid); - return; - } - - if (ISDOT(dir_fsp->fsp_name)) { - /* - * We're at the toplevel dir, the final file name - * must not contain ./, as this is filtered out - * normally by srvstr_get_path and unix_convert - * explicitly rejects paths containing ./. - */ - parent_fname = talloc_strdup(ctx,""); - if (!parent_fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - } else { - size_t dir_name_len = strlen(dir_fsp->fsp_name); - - /* - * Copy in the base directory name. - */ - - parent_fname = TALLOC_ARRAY(ctx, char, dir_name_len+2); - if (!parent_fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - memcpy(parent_fname, dir_fsp->fsp_name, - dir_name_len+1); - - /* - * Ensure it ends in a '/'. - * We used TALLOC_SIZE +2 to add space for the '/'. - */ - - if(dir_name_len - && (parent_fname[dir_name_len-1] != '\\') - && (parent_fname[dir_name_len-1] != '/')) { - parent_fname[dir_name_len] = '/'; - parent_fname[dir_name_len+1] = '\0'; - } - } - - tmp = talloc_asprintf(ctx, "%s%s", parent_fname, fname); - if (tmp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBntcreateX); - return; - } - TALLOC_FREE(fname); - fname = tmp; - } else { - /* - * Check to see if this is a mac fork of some kind. - */ - - if (is_ntfs_stream_name(fname)) { - enum FAKE_FILE_TYPE fake_file_type; - - fake_file_type = is_fake_file(fname); - - if (fake_file_type!=FAKE_FILE_TYPE_NONE) { - /* - * Here we go! support for changing the disk - * quotas --metze - * - * We need to fake up to open this MAGIC QUOTA - * file and return a valid FID. - * - * w2k close this file directly after - * openening xp also tries a QUERY_FILE_INFO - * on the file and then close it - */ - reply_ntcreate_and_X_quota( - conn, req, fake_file_type, fname); - return; - } - reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); - return; - } - } - - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - if (oplock_request) { - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) - ? BATCH_OPLOCK : 0; - } - - status = resolve_dfspath(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - return; - } - reply_nterror(req, status); - return; - } - - /* - * Check if POSIX semantics are wanted. - */ - - if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { - case_state = set_posix_case_semantics(NULL, conn); - file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; - } - - status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); - reply_nterror(req, status); - return; - } - /* All file access must go through check_name() */ - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(case_state); - reply_nterror(req, status); - return; - } - - /* This is the correct thing to do (check every time) but can_delete - * is expensive (it may have to read the parent directory - * permissions). So for now we're not doing it unless we have a strong - * hint the client is really going to delete this file. If the client - * is forcing FILE_CREATE let the filesystem take care of the - * permissions. */ - - /* Setting FILE_SHARE_DELETE is the hint. */ - - if (lp_acl_check_permissions(SNUM(conn)) - && (create_disposition != FILE_CREATE) - && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS)) { - if (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) - && !lp_delete_readonly(SNUM(conn))) || - !can_delete_file_in_directory(conn, fname)) { - TALLOC_FREE(case_state); - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - } - -#if 0 - /* We need to support SeSecurityPrivilege for this. */ - if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && - !user_has_privileges(current_user.nt_user_token, - &se_security)) { - TALLOC_FREE(case_state); - reply_nterror(req, NT_STATUS_PRIVILEGE_NOT_HELD); - return; - } -#endif - - /* - * If it's a request for a directory open, deal with it separately. - */ - - if(create_options & FILE_DIRECTORY_FILE) { - - /* Can't open a temp directory. IFS kit test. */ - if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - TALLOC_FREE(case_state); - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - /* - * We will get a create directory here if the Win32 - * app specified a security descriptor in the - * CreateDirectory() call. - */ - - oplock_request = 0; - status = open_directory(conn, req, fname, &sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - &info, &fsp); - } else { - - /* - * Ordinary file case. - */ - - status = open_file_ntcreate(conn,req,fname,&sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - oplock_request, - &info, &fsp); - - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - - /* - * Fail the open if it was explicitly a non-directory - * file. - */ - - if (create_options & FILE_NON_DIRECTORY_FILE) { - TALLOC_FREE(case_state); - reply_force_nterror( - req, - NT_STATUS_FILE_IS_A_DIRECTORY); - return; - } - - oplock_request = 0; - status = open_directory(conn, req, fname, - &sbuf, - access_mask, - share_access, - create_disposition, - create_options, - file_attributes, - &info, &fsp); - } - } - - TALLOC_FREE(case_state); + status = create_file(conn, req, root_dir_fid, fname, flags, + access_mask, file_attributes, share_access, + create_disposition, create_options, + oplock_request, allocation_size, sd, ea_list, + &fsp, &info, &oplock_granted, &sbuf, &file_len); if(!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { - /* We have re-scheduled this call. */ - return; - } - reply_openerror(req, status); - return; - } - - /* - * According to the MS documentation, the only time the security - * descriptor is applied to the opened file is iff we *created* the - * file; an existing file stays the same. - * - * Also, it seems (from observation) that you can open the file with - * any access mask but you can still write the sd. We need to override - * the granted access before we call set_sd - * Patch for bug #2242 from Tom Lackemann . - */ - - if (lp_nt_acl_support(SNUM(conn)) && (info == FILE_WAS_CREATED) - && (sd != NULL)) { - uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; - uint32_t saved_access_mask = fsp->access_mask; - - fsp->access_mask = FILE_GENERIC_ALL; - - if (sd->owner_sid==0) { - sec_info_sent &= ~OWNER_SECURITY_INFORMATION; - } - if (sd->group_sid==0) { - sec_info_sent &= ~GROUP_SECURITY_INFORMATION; - } - if (sd->sacl==0) { - sec_info_sent &= ~SACL_SECURITY_INFORMATION; - } - if (sd->dacl==0) { - sec_info_sent &= ~DACL_SECURITY_INFORMATION; - } - - status = SMB_VFS_FSET_NT_ACL( - fsp, fsp->fh->fd, sec_info_sent, sd); - - if (!NT_STATUS_IS_OK(status)) { - close_file(fsp,ERROR_CLOSE); - TALLOC_FREE(case_state); - reply_nterror(req, status); + /* We have re-scheduled this call, no error. */ return; } - fsp->access_mask = saved_access_mask; - } - - if (ea_len && (info == FILE_WAS_CREATED)) { - status = set_ea(conn, fsp, fname, ea_list); - if (!NT_STATUS_IS_OK(status)) { - close_file(fsp,ERROR_CLOSE); - TALLOC_FREE(case_state); - reply_nterror(req, status); - return; - } - } - - file_len = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); - if(fattr == 0) { - fattr = FILE_ATTRIBUTE_NORMAL; - } - if (!fsp->is_directory && (fattr & aDIR)) { - close_file(fsp,ERROR_CLOSE); - reply_doserror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, status); return; } - /* Save the requested allocation size. */ - if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - if (allocation_size - && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = smb_roundup( - fsp->conn, allocation_size); - if (fsp->is_directory) { - close_file(fsp,ERROR_CLOSE); - /* Can't set allocation size on a directory. */ - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,ERROR_CLOSE); - reply_nterror(req, NT_STATUS_DISK_FULL); - return; - } - } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); - } - } - - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ - - if (oplock_request && lp_fake_oplocks(SNUM(conn))) { - extended_oplock_granted = True; - } - - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - extended_oplock_granted = True; - } - /* Realloc the size of parameters and data we will return */ if (flags & EXTENDED_RESPONSE_REQUIRED) { /* Extended response is 32 more byyes. */ @@ -1776,22 +1424,13 @@ static void call_nt_transact_create(connection_struct *conn, } p = params; - if (extended_oplock_granted) { - if (flags & REQUEST_BATCH_OPLOCK) { - SCVAL(p,0, BATCH_OPLOCK_RETURN); - } else { - SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN); - } - } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { - SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); - } else { - SCVAL(p,0,NO_OPLOCK_RETURN); - } + SCVAL(p, 0, oplock_granted); p += 2; SSVAL(p,0,fsp->fnum); p += 2; - if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) { + if ((create_disposition == FILE_SUPERSEDE) + && (info == FILE_WAS_OVERWRITTEN)) { SIVAL(p,0,FILE_WAS_SUPERSEDED); } else { SIVAL(p,0,info); @@ -1799,7 +1438,8 @@ static void call_nt_transact_create(connection_struct *conn, p += 8; /* Create time. */ - c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + c_timespec = get_create_timespec( + &sbuf,lp_fake_dir_create_times(SNUM(conn))); a_timespec = get_atimespec(&sbuf); m_timespec = get_mtimespec(&sbuf); @@ -1832,7 +1472,8 @@ static void call_nt_transact_create(connection_struct *conn, if (flags & EXTENDED_RESPONSE_REQUIRED) { uint32 perms = 0; p += 25; - if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) { + if (fsp->is_directory + || can_write_to_file(conn, fname, &sbuf)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; -- cgit From 72ca4a68de371baabf36d90179f5bc442d146057 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 13:34:27 +0100 Subject: Fix debugs (This used to be commit 77b31ef44a9f7c1c9b80d90653a49affee8e0372) --- source3/smbd/nttrans.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1ba2a335bf..c9bc3f45a0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -483,6 +483,19 @@ static NTSTATUS create_file(connection_struct *conn, uint8_t oplock_granted = NO_OPLOCK_RETURN; NTSTATUS status; + DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " + "file_attributes = 0x%x, share_access = 0x%x, " + "create_disposition = 0x%x create_options = 0x%x " + "root_dir_fid = 0x%x, fname = %s\n", + (unsigned int)flags, + (unsigned int)access_mask, + (unsigned int)file_attributes, + (unsigned int)share_access, + (unsigned int)create_disposition, + (unsigned int)create_options, + (unsigned int)root_dir_fid, + fname)); + SET_STAT_INVALID(sbuf); if (create_options & FILE_OPEN_BY_FILE_ID) { @@ -853,6 +866,9 @@ static NTSTATUS create_file(connection_struct *conn, } done: + DEBUG(10, ("create_file: info=%d, oplock_granted=%d, file_len=%lu\n", + info, (int)oplock_granted, (unsigned long)file_len)); + *result = fsp; *pinfo = info; *poplock_granted = oplock_granted; @@ -862,6 +878,8 @@ static NTSTATUS create_file(connection_struct *conn, return NT_STATUS_OK; fail: + DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + if (fsp != NULL) { close_file(fsp, ERROR_CLOSE); fsp = NULL; @@ -979,8 +997,6 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) return; } - DEBUG(10, ("create_file returned fsp %p\n", fsp)); - if (flags & EXTENDED_RESPONSE_REQUIRED) { /* This is very strange. We * return 50 words, but only set -- cgit From aa6f0a01513b91ead65069734a896eb9700b6c5b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 13:34:59 +0100 Subject: Fix error returns (This used to be commit f5cdaacd1784d3801d638fa9984b52c57dad6ebd) --- source3/smbd/nttrans.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c9bc3f45a0..739bf01ef9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -992,7 +992,12 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBntcreateX); return; } - reply_nterror(req, status); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + reply_botherror(req, status, ERRDOS, ERRfilexists); + } + else { + reply_nterror(req, status); + } END_PROFILE(SMBntcreateX); return; } @@ -1422,7 +1427,12 @@ static void call_nt_transact_create(connection_struct *conn, /* We have re-scheduled this call, no error. */ return; } - reply_nterror(req, status); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + reply_botherror(req, status, ERRDOS, ERRfilexists); + } + else { + reply_nterror(req, status); + } return; } -- cgit From bef09af7579e376dac76c617750883d915ddb3c7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 14:37:44 +0100 Subject: Fix attribute calculation for ntcreate&x (This used to be commit 9ef81cb14952cad96c71409c04a2cc6579e3311c) --- source3/smbd/nttrans.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 739bf01ef9..15a05b5e83 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -470,13 +470,10 @@ static NTSTATUS create_file(connection_struct *conn, files_struct **result, int *pinfo, uint8_t *poplock_granted, - SMB_STRUCT_STAT *psbuf, - SMB_OFF_T *pfile_len) + SMB_STRUCT_STAT *psbuf) { TALLOC_CTX *frame = talloc_stackframe(); struct case_semantics_state *case_state = NULL; - uint32_t fattr; - SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; files_struct *fsp = NULL; @@ -809,12 +806,7 @@ static NTSTATUS create_file(connection_struct *conn, } } - file_len = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); - if(fattr == 0) { - fattr = FILE_ATTRIBUTE_NORMAL; - } - if (!fsp->is_directory && (fattr & aDIR)) { + if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { status = NT_STATUS_ACCESS_DENIED; goto fail; } @@ -822,7 +814,7 @@ static NTSTATUS create_file(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { if (allocation_size - && (allocation_size > (SMB_BIG_UINT)file_len)) { + && (allocation_size > sbuf.st_size)) { fsp->initial_allocation_size = smb_roundup( fsp->conn, allocation_size); if (fsp->is_directory) { @@ -836,7 +828,8 @@ static NTSTATUS create_file(connection_struct *conn, goto fail; } } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); + fsp->initial_allocation_size = smb_roundup( + fsp->conn, (SMB_BIG_UINT)sbuf.st_size); } } @@ -866,14 +859,13 @@ static NTSTATUS create_file(connection_struct *conn, } done: - DEBUG(10, ("create_file: info=%d, oplock_granted=%d, file_len=%lu\n", - info, (int)oplock_granted, (unsigned long)file_len)); + DEBUG(10, ("create_file: info=%d, oplock_granted=%d\n", + info, (int)oplock_granted)); *result = fsp; *pinfo = info; *poplock_granted = oplock_granted; *psbuf = sbuf; - *pfile_len = file_len; TALLOC_FREE(frame); return NT_STATUS_OK; @@ -984,7 +976,7 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) access_mask, file_attributes, share_access, create_disposition, create_options, oplock_request, allocation_size, NULL, NULL, - &fsp, &info, &oplock_granted, &sbuf, &file_len); + &fsp, &info, &oplock_granted, &sbuf); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -1002,6 +994,12 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) return; } + file_len = sbuf.st_size; + fattr = dos_mode(conn,fname,&sbuf); + if (fattr == 0) { + fattr = FILE_ATTRIBUTE_NORMAL; + } + if (flags & EXTENDED_RESPONSE_REQUIRED) { /* This is very strange. We * return 50 words, but only set @@ -1420,7 +1418,7 @@ static void call_nt_transact_create(connection_struct *conn, access_mask, file_attributes, share_access, create_disposition, create_options, oplock_request, allocation_size, sd, ea_list, - &fsp, &info, &oplock_granted, &sbuf, &file_len); + &fsp, &info, &oplock_granted, &sbuf); if(!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -1436,6 +1434,12 @@ static void call_nt_transact_create(connection_struct *conn, return; } + file_len = sbuf.st_size; + fattr = dos_mode(conn,fname,&sbuf); + if (fattr == 0) { + fattr = FILE_ATTRIBUTE_NORMAL; + } + /* Realloc the size of parameters and data we will return */ if (flags & EXTENDED_RESPONSE_REQUIRED) { /* Extended response is 32 more byyes. */ -- cgit From 14d1bd25066506e047244f87ca362ee221a3e57c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 14:56:57 +0100 Subject: Fix debug (This used to be commit c268be54ee3bdd59980a6217a0e8e59dd3ec5ce2) --- source3/smbd/nttrans.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 15a05b5e83..669ffa1f13 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -480,10 +480,11 @@ static NTSTATUS create_file(connection_struct *conn, uint8_t oplock_granted = NO_OPLOCK_RETURN; NTSTATUS status; - DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " + DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " "file_attributes = 0x%x, share_access = 0x%x, " "create_disposition = 0x%x create_options = 0x%x " - "root_dir_fid = 0x%x, fname = %s\n", + "root_dir_fid = 0x%x, ea_list = 0x%x, sd = 0x%x, " + "fname = %s\n", (unsigned int)flags, (unsigned int)access_mask, (unsigned int)file_attributes, @@ -491,6 +492,8 @@ static NTSTATUS create_file(connection_struct *conn, (unsigned int)create_disposition, (unsigned int)create_options, (unsigned int)root_dir_fid, + (unsigned int)ea_list, + (unsigned int)sd, fname)); SET_STAT_INVALID(sbuf); @@ -1369,6 +1372,9 @@ static void call_nt_transact_create(connection_struct *conn, } if (sd_len) { + DEBUG(10, ("call_nt_transact_create - sd_len = %d\n", + sd_len)); + status = unmarshall_sec_desc(ctx, (uint8_t *)data, sd_len, &sd); if (!NT_STATUS_IS_OK(status)) { -- cgit From 756ce14d4956aece62eab12f468fa47a521b1c4a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 14:55:01 +0100 Subject: Fix an uninitialized variable (This used to be commit ca3add2d65a242029f08482f3b82ea56b7059538) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 669ffa1f13..15306ee590 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1303,7 +1303,7 @@ static void call_nt_transact_create(connection_struct *conn, uint32 create_disposition; uint32 create_options; uint32 sd_len; - struct security_descriptor *sd; + struct security_descriptor *sd = NULL; uint32 ea_len; uint16 root_dir_fid; struct timespec c_timespec; -- cgit From 188daba1a7eaa7201bc29bfa1a958fe7a20fc790 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 15:35:22 +0100 Subject: Move create_file to open.c I'm checking in this long sequence of micro-checkins for review, the overall patch from 3b057022a5 to this is not too large. (This used to be commit 51db8d09a4652d626c093f7bacf075c1c168fc33) --- source3/smbd/nttrans.c | 477 ------------------------------------------------- source3/smbd/open.c | 475 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 475 insertions(+), 477 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 15306ee590..8a177c8e76 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -278,52 +278,6 @@ bool is_ntfs_stream_name(const char *fname) return (strchr_m(fname, ':') != NULL) ? True : False; } -struct case_semantics_state { - connection_struct *conn; - bool case_sensitive; - bool case_preserve; - bool short_case_preserve; -}; - -/**************************************************************************** - Restore case semantics. -****************************************************************************/ -static int restore_case_semantics(struct case_semantics_state *state) -{ - state->conn->case_sensitive = state->case_sensitive; - state->conn->case_preserve = state->case_preserve; - state->conn->short_case_preserve = state->short_case_preserve; - return 0; -} - -/**************************************************************************** - Save case semantics. -****************************************************************************/ -static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx, - connection_struct *conn) -{ - struct case_semantics_state *result; - - if (!(result = talloc(mem_ctx, struct case_semantics_state))) { - DEBUG(0, ("talloc failed\n")); - return NULL; - } - - result->conn = conn; - result->case_sensitive = conn->case_sensitive; - result->case_preserve = conn->case_preserve; - result->short_case_preserve = conn->short_case_preserve; - - /* Set to POSIX. */ - conn->case_sensitive = True; - conn->case_preserve = True; - conn->short_case_preserve = True; - - talloc_set_destructor(result, restore_case_semantics); - - return result; -} - /**************************************************************************** Reply to an NT create and X call on a pipe ****************************************************************************/ @@ -452,437 +406,6 @@ static void do_ntcreate_pipe_open(connection_struct *conn, chain_reply(req); } -static NTSTATUS create_file(connection_struct *conn, - struct smb_request *req, - uint16_t root_dir_fid, - char *fname, - uint32_t flags, - uint32_t access_mask, - uint32_t file_attributes, - uint32_t share_access, - uint32_t create_disposition, - uint32_t create_options, - int oplock_request, - SMB_BIG_UINT allocation_size, - struct security_descriptor *sd, - struct ea_list *ea_list, - - files_struct **result, - int *pinfo, - uint8_t *poplock_granted, - SMB_STRUCT_STAT *psbuf) -{ - TALLOC_CTX *frame = talloc_stackframe(); - struct case_semantics_state *case_state = NULL; - SMB_STRUCT_STAT sbuf; - int info = FILE_WAS_OPENED; - files_struct *fsp = NULL; - uint8_t oplock_granted = NO_OPLOCK_RETURN; - NTSTATUS status; - - DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " - "file_attributes = 0x%x, share_access = 0x%x, " - "create_disposition = 0x%x create_options = 0x%x " - "root_dir_fid = 0x%x, ea_list = 0x%x, sd = 0x%x, " - "fname = %s\n", - (unsigned int)flags, - (unsigned int)access_mask, - (unsigned int)file_attributes, - (unsigned int)share_access, - (unsigned int)create_disposition, - (unsigned int)create_options, - (unsigned int)root_dir_fid, - (unsigned int)ea_list, - (unsigned int)sd, - fname)); - - SET_STAT_INVALID(sbuf); - - if (create_options & FILE_OPEN_BY_FILE_ID) { - status = NT_STATUS_NOT_SUPPORTED; - goto fail; - } - - /* - * Get the file name. - */ - - if (root_dir_fid != 0) { - /* - * This filename is relative to a directory fid. - */ - char *parent_fname = NULL; - files_struct *dir_fsp = file_fsp(root_dir_fid); - - if (dir_fsp == NULL) { - status = NT_STATUS_INVALID_HANDLE; - goto fail; - } - - if (!dir_fsp->is_directory) { - - /* - * Check to see if this is a mac fork of some kind. - */ - - if (is_ntfs_stream_name(fname)) { - status = NT_STATUS_OBJECT_PATH_NOT_FOUND; - goto fail; - } - - /* - we need to handle the case when we get a - relative open relative to a file and the - pathname is blank - this is a reopen! - (hint from demyn plantenberg) - */ - - status = NT_STATUS_INVALID_HANDLE; - goto fail; - } - - if (ISDOT(dir_fsp->fsp_name)) { - /* - * We're at the toplevel dir, the final file name - * must not contain ./, as this is filtered out - * normally by srvstr_get_path and unix_convert - * explicitly rejects paths containing ./. - */ - parent_fname = talloc_strdup(talloc_tos(), ""); - if (parent_fname == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; - } - } else { - size_t dir_name_len = strlen(dir_fsp->fsp_name); - - /* - * Copy in the base directory name. - */ - - parent_fname = TALLOC_ARRAY(talloc_tos(), char, - dir_name_len+2); - if (parent_fname == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; - } - memcpy(parent_fname, dir_fsp->fsp_name, - dir_name_len+1); - - /* - * Ensure it ends in a '/'. - * We used TALLOC_SIZE +2 to add space for the '/'. - */ - - if(dir_name_len - && (parent_fname[dir_name_len-1] != '\\') - && (parent_fname[dir_name_len-1] != '/')) { - parent_fname[dir_name_len] = '/'; - parent_fname[dir_name_len+1] = '\0'; - } - } - - fname = talloc_asprintf(talloc_tos(), "%s%s", parent_fname, - fname); - if (fname == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; - } - } else { - /* - * Check to see if this is a mac fork of some kind. - */ - - if (is_ntfs_stream_name(fname)) { - enum FAKE_FILE_TYPE fake_file_type; - - fake_file_type = is_fake_file(fname); - - if (fake_file_type == FAKE_FILE_TYPE_NONE) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - - /* - * Here we go! support for changing the disk quotas - * --metze - * - * We need to fake up to open this MAGIC QUOTA file - * and return a valid FID. - * - * w2k close this file directly after openening xp - * also tries a QUERY_FILE_INFO on the file and then - * close it - */ - status = open_fake_file(conn, fake_file_type, fname, - access_mask, &fsp); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - - goto done; - } - } - - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - if (oplock_request) { - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) - ? BATCH_OPLOCK : 0; - } - - status = resolve_dfspath( - talloc_tos(), conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, &fname); - - if (!NT_STATUS_IS_OK(status)) { - /* - * For PATH_NOT_COVERED we had - * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - * ERRSRV, ERRbadpath); - * Need to fix in callers - */ - goto fail; - } - - /* - * Ordinary file or directory. - */ - - /* - * Check if POSIX semantics are wanted. - */ - - if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { - case_state = set_posix_case_semantics(talloc_tos(), conn); - file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; - } - - status = unix_convert(talloc_tos(), conn, fname, False, &fname, NULL, - &sbuf); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - - /* All file access must go through check_name() */ - - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - - /* This is the correct thing to do (check every time) but can_delete - * is expensive (it may have to read the parent directory - * permissions). So for now we're not doing it unless we have a strong - * hint the client is really going to delete this file. If the client - * is forcing FILE_CREATE let the filesystem take care of the - * permissions. */ - - /* Setting FILE_SHARE_DELETE is the hint. */ - - if (lp_acl_check_permissions(SNUM(conn)) - && (create_disposition != FILE_CREATE) - && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS) - && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) - && !lp_delete_readonly(SNUM(conn))) - || !can_delete_file_in_directory(conn, fname))) { - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - -#if 0 - /* We need to support SeSecurityPrivilege for this. */ - if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && - !user_has_privileges(current_user.nt_user_token, - &se_security)) { - status = NT_STATUS_PRIVILEGE_NOT_HELD; - goto fail; - } -#endif - - /* - * If it's a request for a directory open, deal with it separately. - */ - - if (create_options & FILE_DIRECTORY_FILE) { - - /* Can't open a temp directory. IFS kit test. */ - if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - status = NT_STATUS_INVALID_PARAMETER; - goto fail; - } - - /* - * We will get a create directory here if the Win32 - * app specified a security descriptor in the - * CreateDirectory() call. - */ - - oplock_request = 0; - status = open_directory( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - &info, &fsp); - } else { - - /* - * Ordinary file case. - */ - - status = open_file_ntcreate( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - oplock_request, &info, &fsp); - - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - - /* - * Fail the open if it was explicitly a non-directory - * file. - */ - - if (create_options & FILE_NON_DIRECTORY_FILE) { - status = NT_STATUS_FILE_IS_A_DIRECTORY; - goto fail; - } - - oplock_request = 0; - status = open_directory( - conn, req, fname, &sbuf, access_mask, - share_access, create_disposition, - create_options, file_attributes, - &info, &fsp); - } - } - - TALLOC_FREE(case_state); - - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - - /* - * According to the MS documentation, the only time the security - * descriptor is applied to the opened file is iff we *created* the - * file; an existing file stays the same. - * - * Also, it seems (from observation) that you can open the file with - * any access mask but you can still write the sd. We need to override - * the granted access before we call set_sd - * Patch for bug #2242 from Tom Lackemann . - */ - - if ((sd != NULL) && (info == FILE_WAS_CREATED) - && lp_nt_acl_support(SNUM(conn))) { - - uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; - uint32_t saved_access_mask = fsp->access_mask; - - if (sd->owner_sid==0) { - sec_info_sent &= ~OWNER_SECURITY_INFORMATION; - } - if (sd->group_sid==0) { - sec_info_sent &= ~GROUP_SECURITY_INFORMATION; - } - if (sd->sacl==0) { - sec_info_sent &= ~SACL_SECURITY_INFORMATION; - } - if (sd->dacl==0) { - sec_info_sent &= ~DACL_SECURITY_INFORMATION; - } - - fsp->access_mask = FILE_GENERIC_ALL; - - status = SMB_VFS_FSET_NT_ACL( - fsp, fsp->fh->fd, sec_info_sent, sd); - - fsp->access_mask = saved_access_mask; - - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - } - - if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { - status = set_ea(conn, fsp, fname, ea_list); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - } - - if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - - /* Save the requested allocation size. */ - if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - if (allocation_size - && (allocation_size > sbuf.st_size)) { - fsp->initial_allocation_size = smb_roundup( - fsp->conn, allocation_size); - if (fsp->is_directory) { - /* Can't set allocation size on a directory. */ - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - if (vfs_allocate_file_space( - fsp, fsp->initial_allocation_size) == -1) { - status = NT_STATUS_DISK_FULL; - goto fail; - } - } else { - fsp->initial_allocation_size = smb_roundup( - fsp->conn, (SMB_BIG_UINT)sbuf.st_size); - } - } - - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ - - if (oplock_request && - (lp_fake_oplocks(SNUM(conn)) - || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { - - /* - * Exclusive oplock granted - */ - - if (flags & REQUEST_BATCH_OPLOCK) { - oplock_granted = BATCH_OPLOCK_RETURN; - } else { - oplock_granted = EXCLUSIVE_OPLOCK_RETURN; - } - } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { - oplock_granted = LEVEL_II_OPLOCK_RETURN; - } else { - oplock_granted = NO_OPLOCK_RETURN; - } - - done: - DEBUG(10, ("create_file: info=%d, oplock_granted=%d\n", - info, (int)oplock_granted)); - - *result = fsp; - *pinfo = info; - *poplock_granted = oplock_granted; - *psbuf = sbuf; - TALLOC_FREE(frame); - return NT_STATUS_OK; - - fail: - DEBUG(10, ("create_file: %s\n", nt_errstr(status))); - - if (fsp != NULL) { - close_file(fsp, ERROR_CLOSE); - fsp = NULL; - } - TALLOC_FREE(frame); - return status; -} - /**************************************************************************** Reply to an NT create and X call. ****************************************************************************/ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6dc979cf3b..0a142cd416 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2393,3 +2393,478 @@ void msg_file_was_renamed(struct messaging_context *msg, } } } + +struct case_semantics_state { + connection_struct *conn; + bool case_sensitive; + bool case_preserve; + bool short_case_preserve; +}; + +/**************************************************************************** + Restore case semantics. +****************************************************************************/ +static int restore_case_semantics(struct case_semantics_state *state) +{ + state->conn->case_sensitive = state->case_sensitive; + state->conn->case_preserve = state->case_preserve; + state->conn->short_case_preserve = state->short_case_preserve; + return 0; +} + +/**************************************************************************** + Save case semantics. +****************************************************************************/ +static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx, + connection_struct *conn) +{ + struct case_semantics_state *result; + + if (!(result = talloc(mem_ctx, struct case_semantics_state))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + result->conn = conn; + result->case_sensitive = conn->case_sensitive; + result->case_preserve = conn->case_preserve; + result->short_case_preserve = conn->short_case_preserve; + + /* Set to POSIX. */ + conn->case_sensitive = True; + conn->case_preserve = True; + conn->short_case_preserve = True; + + talloc_set_destructor(result, restore_case_semantics); + + return result; +} + +/* + * Wrapper around open_file_ntcreate and open_directory + */ + +NTSTATUS create_file(connection_struct *conn, + struct smb_request *req, + uint16_t root_dir_fid, + char *fname, + uint32_t flags, + uint32_t access_mask, + uint32_t file_attributes, + uint32_t share_access, + uint32_t create_disposition, + uint32_t create_options, + int oplock_request, + SMB_BIG_UINT allocation_size, + struct security_descriptor *sd, + struct ea_list *ea_list, + + files_struct **result, + int *pinfo, + uint8_t *poplock_granted, + SMB_STRUCT_STAT *psbuf) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct case_semantics_state *case_state = NULL; + SMB_STRUCT_STAT sbuf; + int info = FILE_WAS_OPENED; + files_struct *fsp = NULL; + uint8_t oplock_granted = NO_OPLOCK_RETURN; + NTSTATUS status; + + DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " + "file_attributes = 0x%x, share_access = 0x%x, " + "create_disposition = 0x%x create_options = 0x%x " + "root_dir_fid = 0x%x, ea_list = 0x%p, sd = 0x%p, " + "fname = %s\n", + (unsigned int)flags, + (unsigned int)access_mask, + (unsigned int)file_attributes, + (unsigned int)share_access, + (unsigned int)create_disposition, + (unsigned int)create_options, + (unsigned int)root_dir_fid, + ea_list, sd, fname)); + + SET_STAT_INVALID(sbuf); + + if (create_options & FILE_OPEN_BY_FILE_ID) { + status = NT_STATUS_NOT_SUPPORTED; + goto fail; + } + + /* + * Get the file name. + */ + + if (root_dir_fid != 0) { + /* + * This filename is relative to a directory fid. + */ + char *parent_fname = NULL; + files_struct *dir_fsp = file_fsp(root_dir_fid); + + if (dir_fsp == NULL) { + status = NT_STATUS_INVALID_HANDLE; + goto fail; + } + + if (!dir_fsp->is_directory) { + + /* + * Check to see if this is a mac fork of some kind. + */ + + if (is_ntfs_stream_name(fname)) { + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; + } + + /* + we need to handle the case when we get a + relative open relative to a file and the + pathname is blank - this is a reopen! + (hint from demyn plantenberg) + */ + + status = NT_STATUS_INVALID_HANDLE; + goto fail; + } + + if (ISDOT(dir_fsp->fsp_name)) { + /* + * We're at the toplevel dir, the final file name + * must not contain ./, as this is filtered out + * normally by srvstr_get_path and unix_convert + * explicitly rejects paths containing ./. + */ + parent_fname = talloc_strdup(talloc_tos(), ""); + if (parent_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + } else { + size_t dir_name_len = strlen(dir_fsp->fsp_name); + + /* + * Copy in the base directory name. + */ + + parent_fname = TALLOC_ARRAY(talloc_tos(), char, + dir_name_len+2); + if (parent_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + memcpy(parent_fname, dir_fsp->fsp_name, + dir_name_len+1); + + /* + * Ensure it ends in a '/'. + * We used TALLOC_SIZE +2 to add space for the '/'. + */ + + if(dir_name_len + && (parent_fname[dir_name_len-1] != '\\') + && (parent_fname[dir_name_len-1] != '/')) { + parent_fname[dir_name_len] = '/'; + parent_fname[dir_name_len+1] = '\0'; + } + } + + fname = talloc_asprintf(talloc_tos(), "%s%s", parent_fname, + fname); + if (fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + } else { + /* + * Check to see if this is a mac fork of some kind. + */ + + if (is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type; + + fake_file_type = is_fake_file(fname); + + if (fake_file_type == FAKE_FILE_TYPE_NONE) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* + * Here we go! support for changing the disk quotas + * --metze + * + * We need to fake up to open this MAGIC QUOTA file + * and return a valid FID. + * + * w2k close this file directly after openening xp + * also tries a QUERY_FILE_INFO on the file and then + * close it + */ + status = open_fake_file(conn, fake_file_type, fname, + access_mask, &fsp); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + goto done; + } + } + + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) + ? BATCH_OPLOCK : 0; + } + + status = resolve_dfspath( + talloc_tos(), conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname, &fname); + + if (!NT_STATUS_IS_OK(status)) { + /* + * For PATH_NOT_COVERED we had + * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + * ERRSRV, ERRbadpath); + * Need to fix in callers + */ + goto fail; + } + + /* + * Check if POSIX semantics are wanted. + */ + + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + case_state = set_posix_case_semantics(talloc_tos(), conn); + file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; + } + + status = unix_convert(talloc_tos(), conn, fname, False, &fname, NULL, + &sbuf); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* All file access must go through check_name() */ + + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* This is the correct thing to do (check every time) but can_delete + * is expensive (it may have to read the parent directory + * permissions). So for now we're not doing it unless we have a strong + * hint the client is really going to delete this file. If the client + * is forcing FILE_CREATE let the filesystem take care of the + * permissions. */ + + /* Setting FILE_SHARE_DELETE is the hint. */ + + if (lp_acl_check_permissions(SNUM(conn)) + && (create_disposition != FILE_CREATE) + && (share_access & FILE_SHARE_DELETE) + && (access_mask & DELETE_ACCESS) + && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) + && !lp_delete_readonly(SNUM(conn))) + || !can_delete_file_in_directory(conn, fname))) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + +#if 0 + /* We need to support SeSecurityPrivilege for this. */ + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && + !user_has_privileges(current_user.nt_user_token, + &se_security)) { + status = NT_STATUS_PRIVILEGE_NOT_HELD; + goto fail; + } +#endif + + /* + * If it's a request for a directory open, deal with it separately. + */ + + if (create_options & FILE_DIRECTORY_FILE) { + + /* Can't open a temp directory. IFS kit test. */ + if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + &info, &fsp); + } else { + + /* + * Ordinary file case. + */ + + status = open_file_ntcreate( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, &info, &fsp); + + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + + /* + * Fail the open if it was explicitly a non-directory + * file. + */ + + if (create_options & FILE_NON_DIRECTORY_FILE) { + status = NT_STATUS_FILE_IS_A_DIRECTORY; + goto fail; + } + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, + share_access, create_disposition, + create_options, file_attributes, + &info, &fsp); + } + } + + TALLOC_FREE(case_state); + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* + * According to the MS documentation, the only time the security + * descriptor is applied to the opened file is iff we *created* the + * file; an existing file stays the same. + * + * Also, it seems (from observation) that you can open the file with + * any access mask but you can still write the sd. We need to override + * the granted access before we call set_sd + * Patch for bug #2242 from Tom Lackemann . + */ + + if ((sd != NULL) && (info == FILE_WAS_CREATED) + && lp_nt_acl_support(SNUM(conn))) { + + uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; + uint32_t saved_access_mask = fsp->access_mask; + + if (sd->owner_sid==0) { + sec_info_sent &= ~OWNER_SECURITY_INFORMATION; + } + if (sd->group_sid==0) { + sec_info_sent &= ~GROUP_SECURITY_INFORMATION; + } + if (sd->sacl==0) { + sec_info_sent &= ~SACL_SECURITY_INFORMATION; + } + if (sd->dacl==0) { + sec_info_sent &= ~DACL_SECURITY_INFORMATION; + } + + fsp->access_mask = FILE_GENERIC_ALL; + + status = SMB_VFS_FSET_NT_ACL( + fsp, fsp->fh->fd, sec_info_sent, sd); + + fsp->access_mask = saved_access_mask; + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { + status = set_ea(conn, fsp, fname, ea_list); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + + /* Save the requested allocation size. */ + if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { + if (allocation_size + && (allocation_size > sbuf.st_size)) { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, allocation_size); + if (fsp->is_directory) { + /* Can't set allocation size on a directory. */ + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + if (vfs_allocate_file_space( + fsp, fsp->initial_allocation_size) == -1) { + status = NT_STATUS_DISK_FULL; + goto fail; + } + } else { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, (SMB_BIG_UINT)sbuf.st_size); + } + } + + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && + (lp_fake_oplocks(SNUM(conn)) + || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { + + /* + * Exclusive oplock granted + */ + + if (flags & REQUEST_BATCH_OPLOCK) { + oplock_granted = BATCH_OPLOCK_RETURN; + } else { + oplock_granted = EXCLUSIVE_OPLOCK_RETURN; + } + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { + oplock_granted = LEVEL_II_OPLOCK_RETURN; + } else { + oplock_granted = NO_OPLOCK_RETURN; + } + + done: + DEBUG(10, ("create_file: info=%d, oplock_granted=%d\n", + info, (int)oplock_granted)); + + *result = fsp; + *pinfo = info; + *poplock_granted = oplock_granted; + *psbuf = sbuf; + TALLOC_FREE(frame); + return NT_STATUS_OK; + + fail: + DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + + if (fsp != NULL) { + close_file(fsp, ERROR_CLOSE); + fsp = NULL; + } + TALLOC_FREE(frame); + return status; +} -- cgit From b2ca9253e9a1e394a5fc1c550d1b30e4853dc43b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 15:34:07 +0100 Subject: There's no point in passing down a 0 (This used to be commit 525a6887afcae8d8e740cf194a412c21da899649) --- source3/smbd/nttrans.c | 6 ++---- source3/smbd/open.c | 40 +++++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8a177c8e76..fb85a67d0a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -423,7 +423,6 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) SMB_BIG_UINT allocation_size; /* Breakout the oplock request bits so we can set the reply bits separately. */ - int oplock_request = 0; uint32 fattr=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; @@ -501,7 +500,7 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) status = create_file(conn, req, root_dir_fid, fname, flags, access_mask, file_attributes, share_access, create_disposition, create_options, - oplock_request, allocation_size, NULL, NULL, + allocation_size, NULL, NULL, &fsp, &info, &oplock_granted, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -812,7 +811,6 @@ static void call_nt_transact_create(connection_struct *conn, char *params = *ppparams; char *data = *ppdata; /* Breakout the oplock request bits so we can set the reply bits separately. */ - int oplock_request = 0; uint32 fattr=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; @@ -946,7 +944,7 @@ static void call_nt_transact_create(connection_struct *conn, status = create_file(conn, req, root_dir_fid, fname, flags, access_mask, file_attributes, share_access, create_disposition, create_options, - oplock_request, allocation_size, sd, ea_list, + allocation_size, sd, ea_list, &fsp, &info, &oplock_granted, &sbuf); if(!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0a142cd416..66ceb8dac7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2454,7 +2454,6 @@ NTSTATUS create_file(connection_struct *conn, uint32_t share_access, uint32_t create_disposition, uint32_t create_options, - int oplock_request, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, @@ -2470,6 +2469,7 @@ NTSTATUS create_file(connection_struct *conn, int info = FILE_WAS_OPENED; files_struct *fsp = NULL; uint8_t oplock_granted = NO_OPLOCK_RETURN; + int oplock_request; NTSTATUS status; DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " @@ -2619,18 +2619,22 @@ NTSTATUS create_file(connection_struct *conn, ? BATCH_OPLOCK : 0; } - status = resolve_dfspath( - talloc_tos(), conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, &fname); + if (req == NULL) { + oplock_request |= INTERNAL_OPEN_ONLY; + } - if (!NT_STATUS_IS_OK(status)) { - /* - * For PATH_NOT_COVERED we had - * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - * ERRSRV, ERRbadpath); - * Need to fix in callers - */ - goto fail; + if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { + status = resolve_dfspath(talloc_tos(), conn, true, fname, &fname); + + if (!NT_STATUS_IS_OK(status)) { + /* + * For PATH_NOT_COVERED we had + * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + * ERRSRV, ERRbadpath); + * Need to fix in callers + */ + goto fail; + } } /* @@ -2852,9 +2856,15 @@ NTSTATUS create_file(connection_struct *conn, info, (int)oplock_granted)); *result = fsp; - *pinfo = info; - *poplock_granted = oplock_granted; - *psbuf = sbuf; + if (pinfo != NULL) { + *pinfo = info; + } + if (poplock_granted != NULL) { + *poplock_granted = oplock_granted; + } + if (psbuf != NULL) { + *psbuf = sbuf; + } TALLOC_FREE(frame); return NT_STATUS_OK; -- cgit From 30d31a3f85399042cd7f337c85a261352dd31b09 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 10:46:11 +0100 Subject: Make fname arg to create_file a "const char *" (This used to be commit da94b5f9e37f38880e8ca4c2c7f8de6838864321) --- source3/smbd/open.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 66ceb8dac7..f4c3791b43 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2447,7 +2447,7 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx NTSTATUS create_file(connection_struct *conn, struct smb_request *req, uint16_t root_dir_fid, - char *fname, + const char *fname, uint32_t flags, uint32_t access_mask, uint32_t file_attributes, @@ -2624,7 +2624,10 @@ NTSTATUS create_file(connection_struct *conn, } if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { - status = resolve_dfspath(talloc_tos(), conn, true, fname, &fname); + char *resolved_fname; + + status = resolve_dfspath(talloc_tos(), conn, true, fname, + &resolved_fname); if (!NT_STATUS_IS_OK(status)) { /* @@ -2635,6 +2638,7 @@ NTSTATUS create_file(connection_struct *conn, */ goto fail; } + fname = resolved_fname; } /* @@ -2646,10 +2650,15 @@ NTSTATUS create_file(connection_struct *conn, file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - status = unix_convert(talloc_tos(), conn, fname, False, &fname, NULL, - &sbuf); - if (!NT_STATUS_IS_OK(status)) { - goto fail; + { + char *converted_fname; + + status = unix_convert(talloc_tos(), conn, fname, False, + &converted_fname, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + fname = converted_fname; } /* All file access must go through check_name() */ -- cgit From c55e44b6a7c8ca569010ddd7596ba05239c4d673 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 11:58:40 +0100 Subject: Re-arrange create_file() parameters This changes them to be a bit closer to open_file_ntcreate and thus provides less surprises to developers (This used to be commit d000258b96b9bb714efdfe982947370a6dfb5d55) --- source3/smbd/nttrans.c | 8 ++++---- source3/smbd/open.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index fb85a67d0a..01ac1abeb0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -498,8 +498,8 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) } status = create_file(conn, req, root_dir_fid, fname, flags, - access_mask, file_attributes, share_access, - create_disposition, create_options, + access_mask, share_access, create_disposition, + create_options, file_attributes, allocation_size, NULL, NULL, &fsp, &info, &oplock_granted, &sbuf); @@ -942,8 +942,8 @@ static void call_nt_transact_create(connection_struct *conn, } status = create_file(conn, req, root_dir_fid, fname, flags, - access_mask, file_attributes, share_access, - create_disposition, create_options, + access_mask, share_access, create_disposition, + create_options, file_attributes, allocation_size, sd, ea_list, &fsp, &info, &oplock_granted, &sbuf); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f4c3791b43..f555aeccb3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2450,10 +2450,10 @@ NTSTATUS create_file(connection_struct *conn, const char *fname, uint32_t flags, uint32_t access_mask, - uint32_t file_attributes, uint32_t share_access, uint32_t create_disposition, uint32_t create_options, + uint32_t file_attributes, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, -- cgit From ce535b4dd8c410d91f9c0fa2d1d973b4326af64d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 12:39:30 +0100 Subject: More parameter shuffling (This used to be commit 8f70f691ffa3e171a73d04a1c867aa6fca4d4583) --- source3/smbd/nttrans.c | 8 ++++---- source3/smbd/open.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 01ac1abeb0..a8afd580b3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -497,9 +497,9 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) } } - status = create_file(conn, req, root_dir_fid, fname, flags, + status = create_file(conn, req, root_dir_fid, fname, access_mask, share_access, create_disposition, - create_options, file_attributes, + create_options, file_attributes, flags, allocation_size, NULL, NULL, &fsp, &info, &oplock_granted, &sbuf); @@ -941,9 +941,9 @@ static void call_nt_transact_create(connection_struct *conn, return; } - status = create_file(conn, req, root_dir_fid, fname, flags, + status = create_file(conn, req, root_dir_fid, fname, access_mask, share_access, create_disposition, - create_options, file_attributes, + create_options, file_attributes, flags, allocation_size, sd, ea_list, &fsp, &info, &oplock_granted, &sbuf); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f555aeccb3..11dff4dfe5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2448,12 +2448,12 @@ NTSTATUS create_file(connection_struct *conn, struct smb_request *req, uint16_t root_dir_fid, const char *fname, - uint32_t flags, uint32_t access_mask, uint32_t share_access, uint32_t create_disposition, uint32_t create_options, uint32_t file_attributes, + uint32_t flags, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, -- cgit From ca4eee5bbe477af2abcdbed542c5e8f7ef5eb610 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 12:57:11 +0100 Subject: Pass only internal oplock request values to create_file Other callers (e.g. reply_open_and_X) might have other ideas of the bit shuffling (This used to be commit 6a58d823e51ccc8efd6682005e367c9096abc993) --- source3/smbd/nttrans.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/open.c | 47 ++++----------------------------- 2 files changed, 71 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a8afd580b3..716f682c1a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -433,6 +433,7 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) struct timespec a_timespec; struct timespec m_timespec; NTSTATUS status; + int oplock_request; uint8_t oplock_granted = NO_OPLOCK_RETURN; TALLOC_CTX *ctx = talloc_tos(); @@ -497,11 +498,16 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) } } + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) + ? BATCH_OPLOCK : 0; + } + status = create_file(conn, req, root_dir_fid, fname, access_mask, share_access, create_disposition, create_options, file_attributes, flags, - allocation_size, NULL, NULL, - &fsp, &info, &oplock_granted, &sbuf); + allocation_size, NULL, NULL, &fsp, &info, &sbuf); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -519,6 +525,31 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) return; } + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && + (lp_fake_oplocks(SNUM(conn)) + || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { + + /* + * Exclusive oplock granted + */ + + if (flags & REQUEST_BATCH_OPLOCK) { + oplock_granted = BATCH_OPLOCK_RETURN; + } else { + oplock_granted = EXCLUSIVE_OPLOCK_RETURN; + } + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { + oplock_granted = LEVEL_II_OPLOCK_RETURN; + } else { + oplock_granted = NO_OPLOCK_RETURN; + } + file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); if (fattr == 0) { @@ -834,6 +865,7 @@ static void call_nt_transact_create(connection_struct *conn, NTSTATUS status; size_t param_len; SMB_BIG_UINT allocation_size; + int oplock_request; uint8_t oplock_granted; TALLOC_CTX *ctx = talloc_tos(); @@ -941,11 +973,16 @@ static void call_nt_transact_create(connection_struct *conn, return; } + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) + ? BATCH_OPLOCK : 0; + } + status = create_file(conn, req, root_dir_fid, fname, access_mask, share_access, create_disposition, create_options, file_attributes, flags, - allocation_size, sd, ea_list, - &fsp, &info, &oplock_granted, &sbuf); + allocation_size, sd, ea_list, &fsp, &info, &sbuf); if(!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -961,6 +998,31 @@ static void call_nt_transact_create(connection_struct *conn, return; } + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && + (lp_fake_oplocks(SNUM(conn)) + || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { + + /* + * Exclusive oplock granted + */ + + if (flags & REQUEST_BATCH_OPLOCK) { + oplock_granted = BATCH_OPLOCK_RETURN; + } else { + oplock_granted = EXCLUSIVE_OPLOCK_RETURN; + } + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { + oplock_granted = LEVEL_II_OPLOCK_RETURN; + } else { + oplock_granted = NO_OPLOCK_RETURN; + } + file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); if (fattr == 0) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 11dff4dfe5..b156dbbce1 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2453,14 +2453,13 @@ NTSTATUS create_file(connection_struct *conn, uint32_t create_disposition, uint32_t create_options, uint32_t file_attributes, - uint32_t flags, + uint32_t oplock_request, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, int *pinfo, - uint8_t *poplock_granted, SMB_STRUCT_STAT *psbuf) { TALLOC_CTX *frame = talloc_stackframe(); @@ -2468,21 +2467,20 @@ NTSTATUS create_file(connection_struct *conn, SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; files_struct *fsp = NULL; - uint8_t oplock_granted = NO_OPLOCK_RETURN; - int oplock_request; NTSTATUS status; - DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " + DEBUG(10,("create_file: access_mask = 0x%x " "file_attributes = 0x%x, share_access = 0x%x, " "create_disposition = 0x%x create_options = 0x%x " + "oplock_request = 0x%x " "root_dir_fid = 0x%x, ea_list = 0x%p, sd = 0x%p, " "fname = %s\n", - (unsigned int)flags, (unsigned int)access_mask, (unsigned int)file_attributes, (unsigned int)share_access, (unsigned int)create_disposition, (unsigned int)create_options, + (unsigned int)oplock_request, (unsigned int)root_dir_fid, ea_list, sd, fname)); @@ -2613,12 +2611,6 @@ NTSTATUS create_file(connection_struct *conn, } } - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - if (oplock_request) { - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) - ? BATCH_OPLOCK : 0; - } - if (req == NULL) { oplock_request |= INTERNAL_OPEN_ONLY; } @@ -2835,42 +2827,13 @@ NTSTATUS create_file(connection_struct *conn, } } - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ - - if (oplock_request && - (lp_fake_oplocks(SNUM(conn)) - || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { - - /* - * Exclusive oplock granted - */ - - if (flags & REQUEST_BATCH_OPLOCK) { - oplock_granted = BATCH_OPLOCK_RETURN; - } else { - oplock_granted = EXCLUSIVE_OPLOCK_RETURN; - } - } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { - oplock_granted = LEVEL_II_OPLOCK_RETURN; - } else { - oplock_granted = NO_OPLOCK_RETURN; - } - done: - DEBUG(10, ("create_file: info=%d, oplock_granted=%d\n", - info, (int)oplock_granted)); + DEBUG(10, ("create_file: info=%d\n", info)); *result = fsp; if (pinfo != NULL) { *pinfo = info; } - if (poplock_granted != NULL) { - *poplock_granted = oplock_granted; - } if (psbuf != NULL) { *psbuf = sbuf; } -- cgit From a23d09081fdb089c776e568418cba75c2c2e8271 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 15:55:57 +0100 Subject: Attempt to fix make test :-) (This used to be commit de3a3e3745e58cbfa777ae426e38bad3d74230d4) --- source3/smbd/nttrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 716f682c1a..99b2bf65bb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -506,7 +506,7 @@ void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) status = create_file(conn, req, root_dir_fid, fname, access_mask, share_access, create_disposition, - create_options, file_attributes, flags, + create_options, file_attributes, oplock_request, allocation_size, NULL, NULL, &fsp, &info, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -981,7 +981,7 @@ static void call_nt_transact_create(connection_struct *conn, status = create_file(conn, req, root_dir_fid, fname, access_mask, share_access, create_disposition, - create_options, file_attributes, flags, + create_options, file_attributes, oplock_request, allocation_size, sd, ea_list, &fsp, &info, &sbuf); if(!NT_STATUS_IS_OK(status)) { -- cgit From acf15ae730c95443681404c76b67ccfca0253d8b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Dec 2007 12:26:32 -0800 Subject: Don't build rpctorture anymore - not maintained. Just remove. Remove all vestiges of pstring (except for smbctool as noted in previous commit). Jeremy (This used to be commit 4c32a22ac50ada3275d2ffba3c1aa08bee7d1549) --- source3/smbd/msdfs.c | 2 +- source3/smbd/server.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 98a41e4ec3..4ae735633b 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -481,7 +481,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, * unix_convert later in the codepath. * If we needed to remember what we'd resolved in * dp->reqpath (as the original code did) we'd - * pstrcpy(localhost, dp->reqpath) on any code + * copy (localhost, dp->reqpath) on any code * path below that returns True - but I don't * think this is needed. JRA. */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index aa85aca77e..328993f6b0 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -726,12 +726,12 @@ void reload_printers(void) bool reload_services(bool test) { bool ret; - + if (lp_loaded()) { char *fname = lp_configfile(); if (file_exist(fname, NULL) && !strcsequal(fname, dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE, fname); + strlcpy(dyn_CONFIGFILE, fname,sizeof(dyn_CONFIGFILE)); test = False; } } @@ -755,7 +755,7 @@ bool reload_services(bool test) load_interfaces(); - if (smbd_server_fd() != -1) { + if (smbd_server_fd() != -1) { set_socket_options(smbd_server_fd(),"SO_KEEPALIVE"); set_socket_options(smbd_server_fd(), lp_socket_options()); } -- cgit From 42cfffae80480eae4381902fff3f7c61f858a933 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Dec 2007 17:32:32 -0800 Subject: Remove next_token - all uses must now be next_token_talloc. No more temptations to use static length strings. Jeremy. (This used to be commit ec003f39369910dee852b7cafb883ddaa321c2de) --- source3/smbd/chgpasswd.c | 42 +++++++++++++++++++++++++++------------ source3/smbd/lanman.c | 51 +++++++++++++++++++++++++++++++++--------------- source3/smbd/server.c | 26 +++++++++++++++--------- 3 files changed, 81 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index aef5adb72f..5a1d71d2af 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -304,34 +304,50 @@ static void pwd_sub(char *buf) static int talktochild(int master, const char *seq) { + TALLOC_CTX *frame = talloc_stackframe(); int count = 0; - fstring issue, expected; + char *issue; + char *expected; - fstrcpy(issue, "."); + issue = talloc_strdup(frame, "."); + if (!issue) { + TALLOC_FREE(frame); + return false; + } - while (next_token(&seq, expected, NULL, sizeof(expected))) - { + while (next_token_talloc(frame, &seq, &expected, NULL)) { pwd_sub(expected); count++; - if (!expect(master, issue, expected)) - { + if (!expect(master, issue, expected)) { DEBUG(3, ("Response %d incorrect\n", count)); - return False; + TALLOC_FREE(frame); + return false; } - if (!next_token(&seq, issue, NULL, sizeof(issue))) - fstrcpy(issue, "."); - + if (!next_token_talloc(frame, &seq, &issue, NULL)) { + issue = talloc_strdup(frame, "."); + if (!issue) { + TALLOC_FREE(frame); + return false; + } + } pwd_sub(issue); } + if (!strequal(issue, ".")) { /* we have one final issue to send */ - fstrcpy(expected, "."); - if (!expect(master, issue, expected)) + expected = talloc_strdup(frame, "."); + if (!expected) { + TALLOC_FREE(frame); + return false; + } + if (!expect(master, issue, expected)) { + TALLOC_FREE(frame); return False; + } } - + TALLOC_FREE(frame); return (count > 0); } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index b194fc6231..feb5fa4b05 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1177,11 +1177,13 @@ static int get_server_info(uint32 servertype, struct srv_info_struct *s; const char *ptr = lines[i]; bool ok = True; + TALLOC_CTX *frame = NULL; + char *p; if (!*ptr) { continue; } - + if (count == alloced) { alloced += 10; *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); @@ -1193,26 +1195,43 @@ static int get_server_info(uint32 servertype, memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); } s = &(*servers)[count]; - - if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) { + + frame = talloc_stackframe(); + s->name[0] = '\0'; + if (!next_token_talloc(frame,&ptr,&p, NULL)) { + TALLOC_FREE(frame); continue; } - if (!next_token(&ptr,stype, NULL, sizeof(stype))) { + fstrcpy(s->name, p); + + stype[0] = '\0'; + if (!next_token_talloc(frame,&ptr, &p, NULL)) { + TALLOC_FREE(frame); continue; } - if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) { + fstrcpy(stype, p); + + s->comment[0] = '\0'; + if (!next_token_talloc(frame,&ptr, &p, NULL)) { + TALLOC_FREE(frame); continue; } - if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) { + fstrcpy(s->comment, p); + + s->domain[0] = '\0'; + if (!next_token_talloc(frame,&ptr,&p, NULL)) { /* this allows us to cope with an old nmbd */ - fstrcpy(s->domain,lp_workgroup()); + fstrcpy(s->domain,lp_workgroup()); + } else { + fstrcpy(s->domain, p); } - - if (sscanf(stype,"%X",&s->type) != 1) { - DEBUG(4,("r:host file ")); - ok = False; + TALLOC_FREE(frame); + + if (sscanf(stype,"%X",&s->type) != 1) { + DEBUG(4,("r:host file ")); + ok = False; } - + /* Filter the servers/domains we return based on what was asked for. */ /* Check to see if we are being asked for a local list only. */ @@ -1222,11 +1241,11 @@ static int get_server_info(uint32 servertype, } /* doesn't match up: don't want it */ - if (!(servertype & s->type)) { - DEBUG(4,("r:serv type ")); - ok = False; + 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: dom mismatch ")); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 328993f6b0..6b1ab6ff17 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -352,9 +352,10 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ /* Now open a listen socket for each of the interfaces. */ for(i = 0; i < num_interfaces; i++) { + TALLOC_CTX *frame = NULL; const struct sockaddr_storage *ifss = iface_n_sockaddr_storage(i); - fstring tok; + char *tok; const char *ptr; if (ifss == NULL) { @@ -364,8 +365,9 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; } - for (ptr=ports; next_token(&ptr, tok, " \t,", - sizeof(tok)); ) { + frame = talloc_stackframe(); + for (ptr=ports; + next_token_talloc(frame,&ptr, &tok, " \t,");) { unsigned port = atoi(tok); if (port == 0 || port > 0xffff) { continue; @@ -389,6 +391,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ DEBUG(0,("open_sockets_smbd: listen: " "%s\n", strerror(errno))); close(s); + TALLOC_FREE(frame); return False; } FD_SET(s,&listen_set); @@ -398,18 +401,21 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ if (num_sockets >= FD_SETSIZE) { DEBUG(0,("open_sockets_smbd: Too " "many sockets to bind to\n")); + TALLOC_FREE(frame); return False; } } + TALLOC_FREE(frame); } } else { /* Just bind to 0.0.0.0 - accept connections from anywhere. */ - fstring tok; + TALLOC_CTX *frame = talloc_stackframe(); + char *tok; const char *ptr; const char *sock_addr = lp_socket_address(); - fstring sock_tok; + char *sock_tok; const char *sock_ptr; if (strequal(sock_addr, "0.0.0.0") || @@ -421,10 +427,9 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ #endif } - for (sock_ptr=sock_addr; next_token(&sock_ptr, sock_tok, " \t,", - sizeof(sock_tok)); ) { - for (ptr=ports; next_token(&ptr, tok, " \t,", - sizeof(tok)); ) { + for (sock_ptr=sock_addr; + next_token_talloc(frame, &sock_ptr, &sock_tok, " \t,"); ) { + for (ptr=ports; next_token_talloc(frame, &ptr, &tok, " \t,"); ) { struct sockaddr_storage ss; unsigned port = atoi(tok); @@ -456,6 +461,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ "listen: %s\n", strerror(errno))); close(s); + TALLOC_FREE(frame); return False; } @@ -468,10 +474,12 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ if (num_sockets >= FD_SETSIZE) { DEBUG(0,("open_sockets_smbd: Too " "many sockets to bind to\n")); + TALLOC_FREE(frame); return False; } } } + TALLOC_FREE(frame); } SAFE_FREE(ports); -- cgit From 22e329d37fe7ce2cbb8545c83560a4698bca4a4b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 9 Dec 2007 13:45:10 +0100 Subject: Get rid of the msgbuf[1600] (This used to be commit af228007915cc8bb65fa7968da25a1a36004bc22) --- source3/smbd/message.c | 230 ++++++++++++++++++++++++++++--------------------- 1 file changed, 132 insertions(+), 98 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 12a4bc0d54..d0b524da0e 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -26,116 +26,110 @@ extern userdom_struct current_user_info; -/* look in server.c for some explanation of these variables */ -static char msgbuf[1600]; -static int msgpos; -static fstring msgfrom; -static fstring msgto; +struct msg_state { + char *from; + char *to; + char *msg; +}; + +static struct msg_state *smbd_msg_state; /**************************************************************************** Deliver the message. ****************************************************************************/ -static void msg_deliver(void) +static void msg_deliver(struct msg_state *state) { - TALLOC_CTX *ctx = talloc_tos(); + TALLOC_CTX *frame = talloc_stackframe(); char *name = NULL; int i; int fd; char *msg; int len; ssize_t sz; + fstring alpha_buf; + char *s; if (! (*lp_msg_command())) { DEBUG(1,("no messaging command specified\n")); - msgpos = 0; - return; + goto done; } /* put it in a temporary file */ - name = talloc_asprintf(ctx, "%s/msg.XXXXXX",tmpdir()); + name = talloc_asprintf(talloc_tos(), "%s/msg.XXXXXX", tmpdir()); if (!name) { - return; + goto done; } fd = smb_mkstemp(name); if (fd == -1) { - DEBUG(1,("can't open message file %s\n",name)); - return; + DEBUG(1, ("can't open message file %s: %s\n", name, + strerror(errno))); + goto done; } /* * Incoming message is in DOS codepage format. Convert to UNIX. */ - if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **)(void *)&msg, True)) < 0 || !msg) { - DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); - for (i = 0; i < msgpos;) { - if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { - i++; - continue; - } - sz = write(fd, &msgbuf[i++], 1); - if ( sz != 1 ) { - DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); - } + len = convert_string_talloc( + talloc_tos(), CH_DOS, CH_UNIX, state->msg, + talloc_get_size(state->msg), (void *)&msg, true); + + if (len == -1) { + DEBUG(3, ("Conversion failed, delivering message in DOS " + "codepage format\n")); + msg = state->msg; + } + + for (i = 0; i < len; i++) { + if ((msg[i] == '\r') && (i < (len-1)) && (msg[i+1] == '\n')) { + continue; } - } else { - for (i = 0; i < len;) { - if (msg[i] == '\r' && i < (len-1) && msg[i+1] == '\n') { - i++; - continue; - } - sz = write(fd, &msg[i++],1); - if ( sz != 1 ) { - DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); - } + sz = write(fd, &msg[i], 1); + if ( sz != 1 ) { + DEBUG(0, ("Write error to fd %d: %ld(%s)\n", fd, + (long)sz, strerror(errno))); } - SAFE_FREE(msg); } + close(fd); /* run the command */ - if (*lp_msg_command()) { - fstring alpha_msgfrom; - fstring alpha_msgto; - char *s = talloc_strdup(ctx, - lp_msg_command()); - - if (!s) { - return; - } - s = talloc_string_sub(ctx, s, "%f", - alpha_strcpy(alpha_msgfrom, - msgfrom, - NULL, - sizeof(alpha_msgfrom))); - if (!s) { - return; - } - s = talloc_string_sub(ctx, s, "%t", - alpha_strcpy(alpha_msgto, - msgto, - NULL, - sizeof(alpha_msgto))); - if (!s) { - return; - } - s = talloc_sub_basic(ctx, - current_user_info.smb_name, - current_user_info.domain, - s); - if (!s) { - return; - } - s = talloc_string_sub(ctx, s, "%s",name); - if (!s) { - return; - } - smbrun(s,NULL); + s = talloc_strdup(talloc_tos(), lp_msg_command()); + if (s == NULL) { + goto done; + } + + alpha_strcpy(alpha_buf, state->from, NULL, sizeof(alpha_buf)); + + s = talloc_string_sub(talloc_tos(), s, "%f", alpha_buf); + if (s == NULL) { + goto done; + } + + alpha_strcpy(alpha_buf, state->to, NULL, sizeof(alpha_buf)); + + s = talloc_string_sub(talloc_tos(), s, "%t", alpha_buf); + if (s == NULL) { + goto done; } - msgpos = 0; + s = talloc_sub_basic(talloc_tos(), current_user_info.smb_name, + current_user_info.domain, s); + if (s == NULL) { + goto done; + } + + s = talloc_string_sub(talloc_tos(), s, "%s", name); + if (s == NULL) { + goto done; + } + smbrun(s,NULL); + + done: + TALLOC_FREE(frame); + return; } /**************************************************************************** @@ -145,37 +139,45 @@ static void msg_deliver(void) void reply_sends(connection_struct *conn, struct smb_request *req) { + struct msg_state *state; int len; char *msg; char *p; START_PROFILE(SMBsends); - msgpos = 0; - - if (! (*lp_msg_command())) { + if (!(*lp_msg_command())) { reply_doserror(req, ERRSRV, ERRmsgoff); END_PROFILE(SMBsends); return; } + state = talloc(talloc_tos(), struct msg_state); + p = smb_buf(req->inbuf)+1; - p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgfrom, p, - sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgto, p, - sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf_talloc( + state, (char *)req->inbuf, req->flags2, &state->from, p, + STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf_talloc( + state, (char *)req->inbuf, req->flags2, &state->to, p, + STR_ASCII|STR_TERMINATE) + 1; msg = p; len = SVAL(msg,0); - len = MIN(len,sizeof(msgbuf)-msgpos); + len = MIN(len, smb_bufrem(req->inbuf, msg+2)); - memset(msgbuf,'\0',sizeof(msgbuf)); + state->msg = talloc_array(state, char, len); - memcpy(&msgbuf[msgpos],msg+2,len); - msgpos += len; + if (state->msg == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsends); + return; + } + + memcpy(state->msg, msg+2, len); - msg_deliver(); + msg_deliver(state); reply_outbuf(req, 0, 0); @@ -194,22 +196,32 @@ void reply_sendstrt(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBsendstrt); - if (! (*lp_msg_command())) { + if (!(*lp_msg_command())) { reply_doserror(req, ERRSRV, ERRmsgoff); END_PROFILE(SMBsendstrt); return; } - memset(msgbuf,'\0',sizeof(msgbuf)); - msgpos = 0; + TALLOC_FREE(smbd_msg_state); + + smbd_msg_state = TALLOC_ZERO_P(NULL, struct msg_state); + + if (smbd_msg_state == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsendstrt); + return; + } p = smb_buf(req->inbuf)+1; - p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgfrom, p, - sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf((char *)req->inbuf, req->flags2, msgto, p, - sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf_talloc( + smbd_msg_state, (char *)req->inbuf, req->flags2, + &smbd_msg_state->from, p, STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf_talloc( + smbd_msg_state, (char *)req->inbuf, req->flags2, + &smbd_msg_state->to, p, STR_ASCII|STR_TERMINATE) + 1; - DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); + DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", smbd_msg_state->from, + smbd_msg_state->to ) ); reply_outbuf(req, 0, 0); @@ -226,6 +238,9 @@ void reply_sendtxt(connection_struct *conn, struct smb_request *req) { int len; char *msg; + char *tmp; + size_t old_len; + START_PROFILE(SMBsendtxt); if (! (*lp_msg_command())) { @@ -234,13 +249,30 @@ void reply_sendtxt(connection_struct *conn, struct smb_request *req) return; } + if (smbd_msg_state == NULL) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsendtxt); + return; + } + msg = smb_buf(req->inbuf) + 1; - len = SVAL(msg,0); - len = MIN(len,sizeof(msgbuf)-msgpos); + old_len = talloc_get_size(smbd_msg_state->msg); + + len = MIN(SVAL(msg, 0), smb_bufrem(req->inbuf, msg+2)); - memcpy(&msgbuf[msgpos],msg+2,len); - msgpos += len; + tmp = TALLOC_REALLOC_ARRAY(smbd_msg_state, smbd_msg_state->msg, + char, old_len + len); + + if (tmp == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsendtxt); + return; + } + + smbd_msg_state->msg = tmp; + + memcpy(&smbd_msg_state->msg[old_len], msg+2, len); DEBUG( 3, ( "SMBsendtxt\n" ) ); @@ -267,7 +299,9 @@ void reply_sendend(connection_struct *conn, struct smb_request *req) DEBUG(3,("SMBsendend\n")); - msg_deliver(); + msg_deliver(smbd_msg_state); + + TALLOC_FREE(smbd_msg_state); reply_outbuf(req, 0, 0); -- cgit From d60fac2a5a789680b6dd9f05ab15a3033ec2887c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 20:53:22 +0100 Subject: Tiny simplifications locking.c:open_read_only was unused don't export the silly boolean flag locking_init(bool read_only) (This used to be commit 2f3c865707010bc7c463a02782dbee3dc2479da1) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6b1ab6ff17..7d0dff0480 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1174,7 +1174,7 @@ extern void build_options(bool screen); if (!connections_init(True)) exit(1); - if (!locking_init(0)) + if (!locking_init()) exit(1); namecache_enable(); -- cgit From e9e33adc7c959e5ccfd605dcc0456265e0cffc1d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 20:58:25 +0100 Subject: int->bool (This used to be commit 874258195278bc8c6bb3011c153c5d646fff9e75) --- source3/smbd/dfree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 31eb9fbd60..9e7f18a130 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -150,10 +150,10 @@ SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, bool small } if ((*dsize)<1) { - static int done; + static bool done = false; if (!done) { DEBUG(0,("WARNING: dfree is broken on this system\n")); - done=1; + done=true; } *dsize = 20*1024*1024/(*bsize); *dfree = MAX(1,*dfree); -- cgit From cc1664416ddc33d7d949e1f391f47a01cd3de27b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 21:09:57 +0100 Subject: Move stuff from data to text (This used to be commit 49f06a2fa70e469bcb5fe17852af011dac32994b) --- source3/smbd/mangle_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 44fbe8a9e8..c369f6eda4 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -52,9 +52,9 @@ * */ -char magic_char = '~'; +static char magic_char = '~'; -static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; +static const char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; #define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) static unsigned char chartest[256] = { 0 }; -- cgit From 3a9576c724460381782f6e39126f353c054699af Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 10:45:33 +0100 Subject: Increase debug level (This used to be commit 4e6df5547167fc235971498cb296a5f74dec8b8b) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b156dbbce1..0e73ba964e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2102,7 +2102,7 @@ NTSTATUS open_directory(connection_struct *conn, (unsigned int)file_attributes)); if (is_ntfs_stream_name(fname)) { - DEBUG(0,("open_directory: %s is a stream name!\n", fname )); + DEBUG(2, ("open_directory: %s is a stream name!\n", fname)); return NT_STATUS_NOT_A_DIRECTORY; } -- cgit From 2585232054934bc60e1384f2bdb93bc43f75c7da Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 9 Dec 2007 19:03:49 +0100 Subject: Simplify add_session_user (This used to be commit f98082ccf048a2de6fea8d922264879305b3d2c8) --- source3/smbd/password.c | 58 +++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 75f05dea67..b3005ba082 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -22,7 +22,6 @@ /* users from session setup */ static char *session_userlist = NULL; -static int len_session_userlist = 0; /* workgroup from session setup. */ static char *session_workgroup = NULL; @@ -383,46 +382,39 @@ int register_existing_vuid(uint16 vuid, void add_session_user(const char *user) { - fstring suser; - struct passwd *passwd; + struct passwd *pw; + char *tmp; - if (!(passwd = Get_Pwnam(user))) - return; - - fstrcpy(suser,passwd->pw_name); + pw = Get_Pwnam_alloc(talloc_tos(), user); - if(!*suser) + if (pw == NULL) { return; + } - if( session_userlist && in_list(suser,session_userlist,False) ) - return; + if (session_userlist == NULL) { + session_userlist = SMB_STRDUP(pw->pw_name); + goto done; + } - if( !session_userlist || - (strlen(suser) + strlen(session_userlist) + 2 >= - len_session_userlist) ) { - char *newlist; + if (in_list(pw->pw_name,session_userlist,False) ) { + goto done; + } - if (len_session_userlist > 128 * 1024) { - DEBUG(3,("add_session_user: session userlist already " - "too large.\n")); - return; - } - newlist = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR( - session_userlist, - len_session_userlist + 1024 ); - if( newlist == NULL ) { - DEBUG(1,("Unable to resize session_userlist\n")); - return; - } - if (!session_userlist) { - *newlist = '\0'; - } - session_userlist = newlist; - len_session_userlist += 1024; + if (strlen(session_userlist) > 128 * 1024) { + DEBUG(3,("add_session_user: session userlist already " + "too large.\n")); + goto done; + } + + if (asprintf(&tmp, "%s %s", session_userlist, pw->pw_name) == -1) { + DEBUG(3, ("asprintf failed\n")); + goto done; } - safe_strcat(session_userlist," ",len_session_userlist-1); - safe_strcat(session_userlist,suser,len_session_userlist-1); + SAFE_FREE(session_userlist); + session_userlist = tmp; + done: + TALLOC_FREE(pw); } /**************************************************************************** -- cgit From 7faee02d0d351c5c039e8f1be7e82ce3a93cbe96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Dec 2007 11:30:37 -0800 Subject: Remove the char[1024] strings from dynconfig. Replace them with malloc'ing accessor functions. Should save a lot of static space :-). Jeremy. (This used to be commit 52dc5eaef2106015b3a8b659e818bdb15ad94b05) --- source3/smbd/lanman.c | 2 +- source3/smbd/server.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index feb5fa4b05..7df7de36dc 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1972,7 +1972,7 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, } asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", - lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment); + lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename, pathname, comment); if (command) { DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7d0dff0480..0aa8dac18d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -738,8 +738,8 @@ bool reload_services(bool test) if (lp_loaded()) { char *fname = lp_configfile(); if (file_exist(fname, NULL) && - !strcsequal(fname, dyn_CONFIGFILE)) { - strlcpy(dyn_CONFIGFILE, fname,sizeof(dyn_CONFIGFILE)); + !strcsequal(fname, get_dyn_CONFIGFILE())) { + set_dyn_CONFIGFILE(fname); test = False; } } @@ -751,7 +751,7 @@ bool reload_services(bool test) lp_killunused(conn_snum_used); - ret = lp_load(dyn_CONFIGFILE, False, False, True, True); + ret = lp_load(get_dyn_CONFIGFILE(), False, False, True, True); reload_printers(); -- cgit From 09fcb233a30e65b4b42f36ce38f70ddd0dfc4746 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 10 Dec 2007 15:31:05 -0800 Subject: Don't need an fstring here, we can talloc. Jeremy. (This used to be commit 3f6cc826378729c9157ea68e7cf5c7b584bbb585) --- source3/smbd/ipc.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index eed293d50d..f28016ccb3 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -374,7 +374,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, static void named_pipe(connection_struct *conn, uint16 vuid, struct smb_request *req, - char *name, uint16 *setup, + const char *name, uint16 *setup, char *data, char *params, int suwcnt, int tdscnt,int tpscnt, int msrcnt, int mdrcnt, int mprcnt) @@ -452,7 +452,7 @@ static void handle_trans(connection_struct *conn, struct smb_request *req, reply_nterror(req, NT_STATUS_NOT_SUPPORTED); return; } - + name_offset += strlen("\\PIPE"); /* Win9x weirdness. When talking to a unicode server Win9x @@ -538,12 +538,11 @@ void reply_trans(connection_struct *conn, struct smb_request *req) state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0); state->one_way = BITSETW(req->inbuf+smb_vwv5,1); - memset(state->name, '\0',sizeof(state->name)); - srvstr_pull_buf(req->inbuf, req->flags2, state->name, - smb_buf(req->inbuf), sizeof(state->name), - STR_TERMINATE); - - if ((dscnt > state->total_data) || (pscnt > state->total_param)) + srvstr_pull_buf_talloc(state, req->inbuf, req->flags2, &state->name, + smb_buf(req->inbuf), STR_TERMINATE); + + if ((dscnt > state->total_data) || (pscnt > state->total_param) || + !state->name) goto bad_param; if (state->total_data) { @@ -557,7 +556,7 @@ void reply_trans(connection_struct *conn, struct smb_request *req) reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans); return; - } + } /* null-terminate the slack space */ memset(&state->data[state->total_data], 0, 100); if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) -- cgit From 0ac113e5a2c1de27a9a33f75821c4fac94ff8731 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Dec 2007 10:36:59 +0100 Subject: Move INTERNAL_OPEN_ONLY calculation out of the way (This used to be commit 0e96549b56e288c596ed8772197f97ffa5ade300) --- source3/smbd/open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0e73ba964e..4798563721 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2611,10 +2611,6 @@ NTSTATUS create_file(connection_struct *conn, } } - if (req == NULL) { - oplock_request |= INTERNAL_OPEN_ONLY; - } - if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { char *resolved_fname; @@ -2660,6 +2656,10 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } + if (req == NULL) { + oplock_request |= INTERNAL_OPEN_ONLY; + } + /* This is the correct thing to do (check every time) but can_delete * is expensive (it may have to read the parent directory * permissions). So for now we're not doing it unless we have a strong -- cgit From 3063f85a72e77d0b7dab66882cf08a45e1db539d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Dec 2007 10:49:26 +0100 Subject: Move more stuff out of the way (This used to be commit ae422fce01cd7520d6dd72e08719a5cd003cb640) --- source3/smbd/open.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4798563721..007b64abf2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2484,13 +2484,6 @@ NTSTATUS create_file(connection_struct *conn, (unsigned int)root_dir_fid, ea_list, sd, fname)); - SET_STAT_INVALID(sbuf); - - if (create_options & FILE_OPEN_BY_FILE_ID) { - status = NT_STATUS_NOT_SUPPORTED; - goto fail; - } - /* * Get the file name. */ @@ -2641,6 +2634,8 @@ NTSTATUS create_file(connection_struct *conn, { char *converted_fname; + SET_STAT_INVALID(sbuf); + status = unix_convert(talloc_tos(), conn, fname, False, &converted_fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -2656,6 +2651,11 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } + if (create_options & FILE_OPEN_BY_FILE_ID) { + status = NT_STATUS_NOT_SUPPORTED; + goto fail; + } + if (req == NULL) { oplock_request |= INTERNAL_OPEN_ONLY; } -- cgit From 39ea0edbbede873986a4dd333c3ec70ab1b5410c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Dec 2007 11:14:30 +0100 Subject: separate out create_file_unixpath() (This used to be commit deaacf971e0fbffd0e5fe24f225ebf645a77e133) --- source3/smbd/open.c | 413 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 242 insertions(+), 171 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 007b64abf2..b83d6844d6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2444,6 +2444,243 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx * Wrapper around open_file_ntcreate and open_directory */ +NTSTATUS create_file_unixpath(connection_struct *conn, + struct smb_request *req, + const char *fname, + uint32_t access_mask, + uint32_t share_access, + uint32_t create_disposition, + uint32_t create_options, + uint32_t file_attributes, + uint32_t oplock_request, + SMB_BIG_UINT allocation_size, + struct security_descriptor *sd, + struct ea_list *ea_list, + + files_struct **result, + int *pinfo, + SMB_STRUCT_STAT *psbuf) +{ + SMB_STRUCT_STAT sbuf; + int info = FILE_WAS_OPENED; + files_struct *fsp = NULL; + NTSTATUS status; + + DEBUG(10,("create_file_unixpath: access_mask = 0x%x " + "file_attributes = 0x%x, share_access = 0x%x, " + "create_disposition = 0x%x create_options = 0x%x " + "oplock_request = 0x%x ea_list = 0x%p, sd = 0x%p, " + "fname = %s\n", + (unsigned int)access_mask, + (unsigned int)file_attributes, + (unsigned int)share_access, + (unsigned int)create_disposition, + (unsigned int)create_options, + (unsigned int)oplock_request, + ea_list, sd, fname)); + + if (create_options & FILE_OPEN_BY_FILE_ID) { + status = NT_STATUS_NOT_SUPPORTED; + goto fail; + } + + if (req == NULL) { + oplock_request |= INTERNAL_OPEN_ONLY; + } + + if (psbuf != NULL) { + sbuf = *psbuf; + } + else { + SET_STAT_INVALID(sbuf); + } + + /* This is the correct thing to do (check every time) but can_delete + * is expensive (it may have to read the parent directory + * permissions). So for now we're not doing it unless we have a strong + * hint the client is really going to delete this file. If the client + * is forcing FILE_CREATE let the filesystem take care of the + * permissions. */ + + /* Setting FILE_SHARE_DELETE is the hint. */ + + if (lp_acl_check_permissions(SNUM(conn)) + && (create_disposition != FILE_CREATE) + && (share_access & FILE_SHARE_DELETE) + && (access_mask & DELETE_ACCESS) + && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) + && !lp_delete_readonly(SNUM(conn))) + || !can_delete_file_in_directory(conn, fname))) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + +#if 0 + /* We need to support SeSecurityPrivilege for this. */ + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && + !user_has_privileges(current_user.nt_user_token, + &se_security)) { + status = NT_STATUS_PRIVILEGE_NOT_HELD; + goto fail; + } +#endif + + /* + * If it's a request for a directory open, deal with it separately. + */ + + if (create_options & FILE_DIRECTORY_FILE) { + + /* Can't open a temp directory. IFS kit test. */ + if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + &info, &fsp); + } else { + + /* + * Ordinary file case. + */ + + status = open_file_ntcreate( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, &info, &fsp); + + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + + /* + * Fail the open if it was explicitly a non-directory + * file. + */ + + if (create_options & FILE_NON_DIRECTORY_FILE) { + status = NT_STATUS_FILE_IS_A_DIRECTORY; + goto fail; + } + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, + share_access, create_disposition, + create_options, file_attributes, + &info, &fsp); + } + } + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* + * According to the MS documentation, the only time the security + * descriptor is applied to the opened file is iff we *created* the + * file; an existing file stays the same. + * + * Also, it seems (from observation) that you can open the file with + * any access mask but you can still write the sd. We need to override + * the granted access before we call set_sd + * Patch for bug #2242 from Tom Lackemann . + */ + + if ((sd != NULL) && (info == FILE_WAS_CREATED) + && lp_nt_acl_support(SNUM(conn))) { + + uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; + uint32_t saved_access_mask = fsp->access_mask; + + if (sd->owner_sid==0) { + sec_info_sent &= ~OWNER_SECURITY_INFORMATION; + } + if (sd->group_sid==0) { + sec_info_sent &= ~GROUP_SECURITY_INFORMATION; + } + if (sd->sacl==0) { + sec_info_sent &= ~SACL_SECURITY_INFORMATION; + } + if (sd->dacl==0) { + sec_info_sent &= ~DACL_SECURITY_INFORMATION; + } + + fsp->access_mask = FILE_GENERIC_ALL; + + status = SMB_VFS_FSET_NT_ACL( + fsp, fsp->fh->fd, sec_info_sent, sd); + + fsp->access_mask = saved_access_mask; + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { + status = set_ea(conn, fsp, fname, ea_list); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + + /* Save the requested allocation size. */ + if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { + if (allocation_size + && (allocation_size > sbuf.st_size)) { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, allocation_size); + if (fsp->is_directory) { + /* Can't set allocation size on a directory. */ + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + if (vfs_allocate_file_space( + fsp, fsp->initial_allocation_size) == -1) { + status = NT_STATUS_DISK_FULL; + goto fail; + } + } else { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, (SMB_BIG_UINT)sbuf.st_size); + } + } + + DEBUG(10, ("create_file: info=%d\n", info)); + + *result = fsp; + if (pinfo != NULL) { + *pinfo = info; + } + if (psbuf != NULL) { + *psbuf = sbuf; + } + return NT_STATUS_OK; + + fail: + DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + + if (fsp != NULL) { + close_file(fsp, ERROR_CLOSE); + fsp = NULL; + } + return status; +} + NTSTATUS create_file(connection_struct *conn, struct smb_request *req, uint16_t root_dir_fid, @@ -2651,182 +2888,16 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } - if (create_options & FILE_OPEN_BY_FILE_ID) { - status = NT_STATUS_NOT_SUPPORTED; - goto fail; - } - - if (req == NULL) { - oplock_request |= INTERNAL_OPEN_ONLY; - } - - /* This is the correct thing to do (check every time) but can_delete - * is expensive (it may have to read the parent directory - * permissions). So for now we're not doing it unless we have a strong - * hint the client is really going to delete this file. If the client - * is forcing FILE_CREATE let the filesystem take care of the - * permissions. */ - - /* Setting FILE_SHARE_DELETE is the hint. */ - - if (lp_acl_check_permissions(SNUM(conn)) - && (create_disposition != FILE_CREATE) - && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS) - && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) - && !lp_delete_readonly(SNUM(conn))) - || !can_delete_file_in_directory(conn, fname))) { - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - -#if 0 - /* We need to support SeSecurityPrivilege for this. */ - if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && - !user_has_privileges(current_user.nt_user_token, - &se_security)) { - status = NT_STATUS_PRIVILEGE_NOT_HELD; - goto fail; - } -#endif - - /* - * If it's a request for a directory open, deal with it separately. - */ - - if (create_options & FILE_DIRECTORY_FILE) { - - /* Can't open a temp directory. IFS kit test. */ - if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - status = NT_STATUS_INVALID_PARAMETER; - goto fail; - } - - /* - * We will get a create directory here if the Win32 - * app specified a security descriptor in the - * CreateDirectory() call. - */ - - oplock_request = 0; - status = open_directory( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - &info, &fsp); - } else { - - /* - * Ordinary file case. - */ - - status = open_file_ntcreate( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - oplock_request, &info, &fsp); - - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - - /* - * Fail the open if it was explicitly a non-directory - * file. - */ - - if (create_options & FILE_NON_DIRECTORY_FILE) { - status = NT_STATUS_FILE_IS_A_DIRECTORY; - goto fail; - } - - oplock_request = 0; - status = open_directory( - conn, req, fname, &sbuf, access_mask, - share_access, create_disposition, - create_options, file_attributes, - &info, &fsp); - } - } - - TALLOC_FREE(case_state); + status = create_file_unixpath( + conn, req, fname, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, allocation_size, sd, ea_list, + &fsp, &info, &sbuf); if (!NT_STATUS_IS_OK(status)) { goto fail; } - /* - * According to the MS documentation, the only time the security - * descriptor is applied to the opened file is iff we *created* the - * file; an existing file stays the same. - * - * Also, it seems (from observation) that you can open the file with - * any access mask but you can still write the sd. We need to override - * the granted access before we call set_sd - * Patch for bug #2242 from Tom Lackemann . - */ - - if ((sd != NULL) && (info == FILE_WAS_CREATED) - && lp_nt_acl_support(SNUM(conn))) { - - uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; - uint32_t saved_access_mask = fsp->access_mask; - - if (sd->owner_sid==0) { - sec_info_sent &= ~OWNER_SECURITY_INFORMATION; - } - if (sd->group_sid==0) { - sec_info_sent &= ~GROUP_SECURITY_INFORMATION; - } - if (sd->sacl==0) { - sec_info_sent &= ~SACL_SECURITY_INFORMATION; - } - if (sd->dacl==0) { - sec_info_sent &= ~DACL_SECURITY_INFORMATION; - } - - fsp->access_mask = FILE_GENERIC_ALL; - - status = SMB_VFS_FSET_NT_ACL( - fsp, fsp->fh->fd, sec_info_sent, sd); - - fsp->access_mask = saved_access_mask; - - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - } - - if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { - status = set_ea(conn, fsp, fname, ea_list); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - } - - if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - - /* Save the requested allocation size. */ - if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - if (allocation_size - && (allocation_size > sbuf.st_size)) { - fsp->initial_allocation_size = smb_roundup( - fsp->conn, allocation_size); - if (fsp->is_directory) { - /* Can't set allocation size on a directory. */ - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - if (vfs_allocate_file_space( - fsp, fsp->initial_allocation_size) == -1) { - status = NT_STATUS_DISK_FULL; - goto fail; - } - } else { - fsp->initial_allocation_size = smb_roundup( - fsp->conn, (SMB_BIG_UINT)sbuf.st_size); - } - } - done: DEBUG(10, ("create_file: info=%d\n", info)); -- cgit From 12ac4c3119b3b7712e670d95d61413d97ecafaef Mon Sep 17 00:00:00 2001 From: Rishi Srivatsavai Date: Thu, 13 Dec 2007 20:56:29 -0800 Subject: Register the smb service with mDNS if mSDN is supported. If mDNS is supported, attempt to register the first port we are listening on for the _smb._tcp service. This provides more reliable service discovery than NetBIOS browsing. (This used to be commit 1e7241517d1f55d60af22570e0c9feb280e3fdb5) --- source3/smbd/dnsregister.c | 212 +++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 50 +++++++++-- 2 files changed, 253 insertions(+), 9 deletions(-) create mode 100644 source3/smbd/dnsregister.c (limited to 'source3/smbd') diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c new file mode 100644 index 0000000000..fcd97b5dab --- /dev/null +++ b/source3/smbd/dnsregister.c @@ -0,0 +1,212 @@ +/* + Unix SMB/CIFS implementation. + DNS-SD registration + Copyright (C) Rishi Srivatsavai 2007 + + 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 3 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, see . +*/ + +#include +#include + +/* Uses DNS service discovery (libdns_sd) to + * register the SMB service. SMB service is registered + * on ".local" domain via Multicast DNS & any + * other unicast DNS domains available. + * + * Users use the smbclient -B (Browse) option to + * browse for advertised SMB services. + */ + +#define DNS_REG_RETRY_INTERVAL (5*60) /* in seconds */ + +struct dns_reg_state { + DNSServiceRef srv_ref; + struct timed_event *retry_handler; +}; + +#ifdef WITH_DNSSD_SUPPORT + +void dns_register_close(struct dns_reg_state **dns_state_ptr) +{ + int mdnsd_conn_fd; + struct dns_reg_state *dns_state = *dns_state_ptr; + + if (dns_state == NULL) { + return; + } + + if (dns_state->srv_ref != NULL) { + /* Close connection to the mDNS daemon */ + DNSServiceRefDeallocate(dns_state->srv_ref); + dns_state->srv_ref = NULL; + } + + /* Clear event handler */ + if (dns_state->retry_handler != NULL) { + TALLOC_FREE(dns_state->retry_handler); + dns_state->retry_handler = NULL; + } + + talloc_free(dns_state); + *dns_state_ptr = NULL; +} + +static void dns_register_smbd_retry(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct dns_reg_state *dns_state = (struct dns_reg_state *)private_data; + + /* Clear previous registration state to force new + * registration attempt. Clears event handler. + */ + dns_register_close(dns_state); +} + +static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state, + struct timeval *timeout) +{ + struct timed_event * event; + + dns_state->srv_ref = NULL; + event= event_add_timed(smbd_event_context(), + NULL, + timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0), + "DNS registration handler", + dns_register_smbd_retry, + dns_state); + + dns_state->retry_handler = event; + get_timed_events_timeout(smbd_event_context(), timeout); +} + +/* Kick off a mDNS request to register the "_smb._tcp" on the specified port. + * We really ought to register on all the ports we are listening on. This will + * have to be an exercise for some-one who knows the DNS registration API a bit + * better. + */ +void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, + unsigned port, + int *maxfd, + fd_set *listen_set, + struct timeval *timeout) +{ + int mdnsd_conn_fd; + DNSServiceErrorType err; + struct dns_reg_state *dns_state = *dns_state_ptr; + + if (dns_state == NULL) { + *dns_state_ptr = dns_state = talloc(NULL, struct dns_reg_state); + if (dns_state == NULL) { + return; + } + } + + /* Quit if a re-try attempt has been scheduled. */ + if (dns_state->retry_handler != NULL) { + return; + } + + /* If a registration is active add conn + * fd to select listen_set and return + */ + if (dns_state->srv_ref != NULL) { + mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); + FD_SET(mdnsd_conn_fd, listen_set); + return; + } + + DEBUG(6, ("registering _smb._tcp service on port %d\n", port)); + + /* Register service with DNS. Connects with the mDNS + * daemon running on the local system to perform DNS + * service registration. + */ + err = DNSServiceRegister(&dns_state->srv_ref, 0 /* flags */, + kDNSServiceInterfaceIndexAny, + NULL /* service name */, + "_smb._tcp" /* service type */, + NULL /* domain */, + "" /* SRV target host name */, + htons(port), + 0 /* TXT record len */, + NULL /* TXT record data */, + NULL /* callback func */, + NULL /* callback context */); + + if (err != kDNSServiceErr_NoError) { + /* Failed to register service. Schedule a re-try attempt. + */ + DEBUG(3, ("unable to register with mDNS (err %d)\n", err)); + schedule_dns_register_smbd_retry(dns_state, timeout); + return; + } + + mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); + FD_SET(mdnsd_conn_fd, listen_set); + *maxfd = MAX(*maxfd, mdnsd_conn_fd); + *timeout = timeval_zero(); + +} + +/* Processes reply from mDNS daemon. Returns true if a reply was received */ +bool dns_register_smbd_reply(struct dns_reg_state *dns_state, + fd_set *lfds, struct timeval *timeout) +{ + int mdnsd_conn_fd = -1; + + if (dns_state->srv_ref == NULL) { + return false; + } + + mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); + + /* Process reply from daemon. Handles any errors. */ + if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) { + DNSServiceErrorType err; + + err = DNSServiceProcessResult(dns_state->srv_ref); + if (err != kDNSServiceErr_NoError) { + DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n", + err)); + schedule_dns_register_smbd_retry(dns_state, timeout); + } + + return true; + } + + return false; +} + +#else /* WITH_DNSSD_SUPPORT */ + + void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, + unsigned port, + int *maxfd, + fd_set *listen_set, + struct timeval *timeout) +{} + + void dns_register_close(struct dns_reg_state ** dns_state_ptr) +{} + + bool dns_register_smbd_reply(struct dns_reg_state *dns_state, + fd_set *lfds, struct timeval *timeout) +{ + return false; +} + +#endif /* WITH_DNSSD_SUPPORT */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0aa8dac18d..41d036a8b9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -311,6 +311,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ int maxfd = 0; int i; char *ports; + struct dns_reg_state * dns_reg = NULL; + unsigned dns_port = 0; if (!is_daemon) { return open_sockets_inetd(); @@ -372,6 +374,14 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ if (port == 0 || port > 0xffff) { continue; } + + /* Keep the first port for mDNS service + * registration. + */ + if (dns_port == 0) { + dns_port = port; + } + s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifss, True); @@ -436,6 +446,14 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ if (port == 0 || port > 0xffff) { continue; } + + /* Keep the first port for mDNS service + * registration. + */ + if (dns_port == 0) { + dns_port = port; + } + /* open an incoming socket */ if (!interpret_string_addr(&ss, sock_tok, AI_NUMERICHOST|AI_PASSIVE)) { @@ -543,6 +561,12 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ FD_ZERO(&w_fds); GetTimeOfDay(&now); + /* Kick off our mDNS registration. */ + if (dns_port != 0) { + dns_register_smbd(&dns_reg, dns_port, &maxfd, + &r_fds, &idle_timeout); + } + event_add_to_select_args(smbd_event_context(), &now, &r_fds, &w_fds, &idle_timeout, &maxfd); @@ -567,6 +591,11 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; } + /* process pending nDNS responses */ + if (dns_register_smbd_reply(dns_reg, &r_fds, &idle_timeout)) { + --num; + } + if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { continue; } @@ -624,6 +653,9 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ for(i = 0; i < num_sockets; i++) close(fd_listenset[i]); + /* close our mDNS daemon handle */ + dns_register_close(&dns_reg); + /* close our standard file descriptors */ close_low_fds(False); @@ -964,8 +996,6 @@ extern void build_options(bool screen); }; TALLOC_CTX *frame = talloc_stackframe(); /* Setup tos. */ - load_case_tables(); - TimeInit(); #ifdef HAVE_SET_AUTH_PARAMETERS @@ -1002,11 +1032,20 @@ extern void build_options(bool screen); } poptFreeContext(pc); + if (interactive) { + Fork = False; + log_stdout = True; + } + + setup_logging(argv[0],log_stdout); + if (print_build_options) { build_options(True); /* Display output to screen as well as debug */ exit(0); } + load_case_tables(); + #ifdef HAVE_SETLUID /* needed for SecureWare on SCO */ setluid(0); @@ -1016,11 +1055,6 @@ extern void build_options(bool screen); set_remote_machine_name("smbd", False); - if (interactive) { - Fork = False; - log_stdout = True; - } - if (interactive && (DEBUGLEVEL >= 9)) { talloc_enable_leak_report(); } @@ -1030,8 +1064,6 @@ extern void build_options(bool screen); exit(1); } - setup_logging(argv[0],log_stdout); - /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ generate_random_buffer(NULL, 0); -- cgit From 40889dccdfec1148481a542c3afc518c11b0642c Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 13 Dec 2007 22:12:21 -0800 Subject: Move dns_sd.h include to fix the build. (This used to be commit cf221a94bd8794add508a2b9305b8c0d40c3346a) --- source3/smbd/dnsregister.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c index fcd97b5dab..44bd39f64e 100644 --- a/source3/smbd/dnsregister.c +++ b/source3/smbd/dnsregister.c @@ -18,7 +18,6 @@ */ #include -#include /* Uses DNS service discovery (libdns_sd) to * register the SMB service. SMB service is registered @@ -31,13 +30,15 @@ #define DNS_REG_RETRY_INTERVAL (5*60) /* in seconds */ +#ifdef WITH_DNSSD_SUPPORT + +#include + struct dns_reg_state { DNSServiceRef srv_ref; struct timed_event *retry_handler; }; -#ifdef WITH_DNSSD_SUPPORT - void dns_register_close(struct dns_reg_state **dns_state_ptr) { int mdnsd_conn_fd; -- cgit From 3cdd8da3ca8466f19e440f0e46e52b53dae6dd45 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Dec 2007 17:02:50 -0800 Subject: Fix for bug #5082 from Mathias Gug , Steve Langasek . Recent versions of Linux-PAM support localization of user prompts, so Samba must use the C locale when invoking PAM (directly or via /usr/bin/passwd) to ensure that password chat values match the prompts in a locale-invariant fashion. Jeremy. (This used to be commit bc13e939546a5bcb78925a6b117e89fde20f6451) --- source3/smbd/chgpasswd.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5a1d71d2af..58b67a58cd 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -125,6 +125,7 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, struct termios stermios; gid_t gid; uid_t uid; + char * const eptrs[1] = { NULL }; if (pass == NULL) { @@ -221,7 +222,7 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, passwordprogram)); /* execl() password-change application */ - if (execl("/bin/sh", "sh", "-c", passwordprogram, NULL) < 0) + if (execle("/bin/sh", "sh", "-c", passwordprogram, NULL, eptrs) < 0) { DEBUG(3, ("Bad status returned from %s\n", passwordprogram)); return (False); @@ -518,6 +519,9 @@ bool chgpasswd(const char *name, const struct passwd *pass, #ifdef WITH_PAM if (lp_pam_password_change()) { bool ret; +#ifdef HAVE_SETLOCALE + const char *prevlocale = setlocale(LC_MESSAGES, "C"); +#endif if (as_root) become_root(); @@ -531,6 +535,10 @@ bool chgpasswd(const char *name, const struct passwd *pass, if (as_root) unbecome_root(); +#ifdef HAVE_SETLOCALE + setlocale(LC_MESSAGES, prevlocale); +#endif + return ret; } #endif -- cgit From 900288a2b86abd247f9eb4cd15dc5617a17cfef1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 21:11:36 +0100 Subject: Replace sid_string_static by sid_string_dbg in DEBUGs (This used to be commit bb35e794ec129805e874ceba882bcc1e84791a09) --- source3/smbd/lanman.c | 2 +- source3/smbd/ntquotas.c | 9 +++++---- source3/smbd/nttrans.c | 7 ++++--- source3/smbd/posix_acls.c | 18 ++++++++---------- source3/smbd/service.c | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7df7de36dc..3ab216c062 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2221,7 +2221,7 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid, if ( !pdb_getsampwsid(sampw, &user_sid) ) { DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n", - sid_string_static(&user_sid), UserName)); + sid_string_dbg(&user_sid), UserName)); goto done; } diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 96ca2bc656..fcccf9d9fc 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -88,7 +88,7 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, if (psid && !sid_to_uid(psid, &id.uid)) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", - sid_string_static(psid))); + sid_string_dbg(psid))); } ret = SMB_VFS_GET_QUOTA(fsp->conn, qtype, id, &D); @@ -132,7 +132,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, if (psid && !sid_to_uid(psid, &id.uid)) { DEBUG(0,("sid_to_uid: failed, SID[%s]\n", - sid_string_static(psid))); + sid_string_dbg(psid))); } ret = SMB_VFS_SET_QUOTA(fsp->conn, qtype, id, &D); @@ -188,12 +188,13 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) { DEBUG(5,("no quota entry for sid[%s] path[%s]\n", - sid_string_static(&sid),fsp->conn->connectpath)); + sid_string_dbg(&sid), + fsp->conn->connectpath)); continue; } DEBUG(15,("quota entry for id[%s] path[%s]\n", - sid_string_static(&sid),fsp->conn->connectpath)); + sid_string_dbg(&sid), fsp->conn->connectpath)); if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 99b2bf65bb..641670c484 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2033,11 +2033,12 @@ static void call_nt_transact_ioctl(connection_struct *conn, /*unknown = IVAL(pdata,0);*/ sid_parse(pdata+4,sid_len,&sid); - DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid))); + DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid))); if (!sid_to_uid(&sid, &uid)) { DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n", - sid_string_static(&sid),(unsigned long)sid_len)); + sid_string_dbg(&sid), + (unsigned long)sid_len)); uid = (-1); } @@ -2466,7 +2467,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, #endif /* LARGE_SMB_OFF_T */ sid_parse(pdata+40,sid_len,&sid); - DEBUGADD(8,("SID: %s\n",sid_string_static(&sid))); + DEBUGADD(8,("SID: %s\n", sid_string_dbg(&sid))); /* 44 unknown bytes left... */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 27953a2051..ccfed69721 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -546,10 +546,8 @@ static canon_ace *dup_canon_ace( canon_ace *src_ace) static void print_canon_ace(canon_ace *pace, int num) { - fstring str; - dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" ); - dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); + dbgtext( "SID = %s ", sid_string_dbg(&pace->trustee)); if (pace->owner_type == UID_ACE) { const char *u_name = uidtoname(pace->unix_ug.uid); dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name ); @@ -962,7 +960,7 @@ NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_i } else { DEBUG(3,("unpack_nt_owners: unable to validate" " owner sid for %s\n", - sid_string_static(&owner_sid))); + sid_string_dbg(&owner_sid))); return NT_STATUS_INVALID_OWNER; } } @@ -1414,23 +1412,23 @@ static bool create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, current_ace->owner_type = GID_ACE; current_ace->type = SMB_ACL_GROUP; } else { - fstring str; - /* * Silently ignore map failures in non-mappable SIDs (NT Authority, BUILTIN etc). */ if (non_mappable_sid(&psa->trustee)) { - DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n", - sid_to_string(str, &psa->trustee) )); + DEBUG(10, ("create_canon_ace_lists: ignoring " + "non-mappable SID %s\n", + sid_string_dbg(&psa->trustee))); SAFE_FREE(current_ace); continue; } free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); - DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n", - sid_to_string(str, ¤t_ace->trustee) )); + DEBUG(0, ("create_canon_ace_lists: unable to map SID " + "%s to uid or gid.\n", + sid_string_dbg(¤t_ace->trustee))); SAFE_FREE(current_ace); return False; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e98ce0f8c2..88ab9f0048 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -597,7 +597,7 @@ static NTSTATUS find_forced_group(bool force_user, if (!sid_to_gid(&group_sid, &gid)) { DEBUG(10, ("sid_to_gid(%s) for %s failed\n", - sid_string_static(&group_sid), groupname)); + sid_string_dbg(&group_sid), groupname)); goto done; } @@ -885,7 +885,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (!sid_to_gid(sid, &gid)) { DEBUG(10, ("Could not convert SID %s to gid, " "ignoring it\n", - sid_string_static(sid))); + sid_string_dbg(sid))); continue; } if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups, -- cgit From d76b086cc9edf0b9e0b3ac759d0b66e0515d62e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Dec 2007 22:28:38 -0800 Subject: More work on bug #5082, use LC_ALL as this takes precedence. Jeremy. (This used to be commit 446ebae76d6796b30e4c71ff7190337c28637be6) --- source3/smbd/chgpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 58b67a58cd..a277e729bf 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -520,7 +520,7 @@ bool chgpasswd(const char *name, const struct passwd *pass, if (lp_pam_password_change()) { bool ret; #ifdef HAVE_SETLOCALE - const char *prevlocale = setlocale(LC_MESSAGES, "C"); + const char *prevlocale = setlocale(LC_ALL, "C"); #endif if (as_root) @@ -536,7 +536,7 @@ bool chgpasswd(const char *name, const struct passwd *pass, unbecome_root(); #ifdef HAVE_SETLOCALE - setlocale(LC_MESSAGES, prevlocale); + setlocale(LC_ALL, prevlocale); #endif return ret; -- cgit From 8c6e781c3cd878ee30601560f8bac3a45471a0bf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 25 Nov 2007 18:26:52 +0100 Subject: make use of [un]marshall_sec_desc, allow for fd==-1 in get/set_secdesc (This used to be commit 585f5f8831f13260808a82611656fc6ca5caee81) --- source3/smbd/nttrans.c | 133 +++++++++++++++++-------------------------------- 1 file changed, 46 insertions(+), 87 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 641670c484..1fbb681c72 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -735,46 +735,20 @@ static void do_nt_transact_create_pipe(connection_struct *conn, Internal fn to set security descriptors. ****************************************************************************/ -static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent) +static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, + uint32 security_info_sent) { - prs_struct pd; SEC_DESC *psd = NULL; - TALLOC_CTX *mem_ctx; NTSTATUS status; if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) { return NT_STATUS_OK; } - /* - * Init the parse struct we will unmarshall from. - */ - - if ((mem_ctx = talloc_init("set_sd")) == NULL) { - DEBUG(0,("set_sd: talloc_init failed.\n")); - return NT_STATUS_NO_MEMORY; - } - - prs_init(&pd, 0, mem_ctx, UNMARSHALL); + status = unmarshall_sec_desc(talloc_tos(), data, sd_len, &psd); - /* - * Setup the prs_struct to point at the memory we just - * allocated. - */ - - prs_give_memory( &pd, data, sd_len, False); - - /* - * Finally, unmarshall from the data buffer. - */ - - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n")); - /* - * Return access denied for want of a better error message.. - */ - talloc_destroy(mem_ctx); - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(status)) { + return status; } if (psd->owner_sid==0) { @@ -790,9 +764,17 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu security_info_sent &= ~DACL_SECURITY_INFORMATION; } - status = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd); + if (fsp->fh->fd != -1) { + status = SMB_VFS_FSET_NT_ACL(fsp, fsp->fh->fd, + security_info_sent, psd); + } + else { + status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, + security_info_sent, psd); + } + + TALLOC_FREE(psd); - talloc_destroy(mem_ctx); return status; } @@ -989,12 +971,7 @@ static void call_nt_transact_create(connection_struct *conn, /* We have re-scheduled this call, no error. */ return; } - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - reply_botherror(req, status, ERRDOS, ERRfilexists); - } - else { - reply_nterror(req, status); - } + reply_openerror(req, status); return; } @@ -1618,13 +1595,13 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, { char *params = *ppparams; char *data = *ppdata; - prs_struct pd; SEC_DESC *psd = NULL; size_t sd_size; uint32 security_info_wanted; - TALLOC_CTX *mem_ctx; + TALLOC_CTX *frame; files_struct *fsp = NULL; NTSTATUS status; + DATA_BLOB blob; if(parameter_count < 8) { reply_doserror(req, ERRDOS, ERRbadfunc); @@ -1648,25 +1625,27 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, return; } - if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) { - DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - reply_doserror(req, ERRDOS, ERRnomem); - return; - } + frame = talloc_stackframe(); /* * Get the permissions to return. */ if (!lp_nt_acl_support(SNUM(conn))) { - status = get_null_nt_acl(mem_ctx, &psd); + status = get_null_nt_acl(talloc_tos(), &psd); } else { - status = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, - security_info_wanted, &psd); + if (fsp->fh->fd != -1) { + status = SMB_VFS_FGET_NT_ACL( + fsp, fsp->fh->fd, security_info_wanted, &psd); + } + else { + status = SMB_VFS_GET_NT_ACL( + fsp, fsp->fsp_name, security_info_wanted, &psd); + } } if (!NT_STATUS_IS_OK(status)) { - talloc_destroy(mem_ctx); + TALLOC_FREE(frame); reply_nterror(req, status); return; } @@ -1677,11 +1656,10 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, SIVAL(params,0,(uint32)sd_size); - if(max_data_count < sd_size) { - + if (max_data_count < sd_size) { send_nt_replies(req, NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); - talloc_destroy(mem_ctx); + TALLOC_FREE(frame); return; } @@ -1691,46 +1669,26 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, data = nttrans_realloc(ppdata, sd_size); if(data == NULL) { - talloc_destroy(mem_ctx); + TALLOC_FREE(frame); reply_doserror(req, ERRDOS, ERRnomem); return; } - /* - * Init the parse struct we will marshall into. - */ - - prs_init(&pd, 0, mem_ctx, MARSHALL); - - /* - * Setup the prs_struct to point at the memory we just - * allocated. - */ - - prs_give_memory( &pd, data, (uint32)sd_size, False); - - /* - * Finally, linearize into the outgoing buffer. - */ + status = marshall_sec_desc(talloc_tos(), psd, + &blob.data, &blob.length); - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ -security descriptor.\n")); - /* - * Return access denied for want of a better error message.. - */ - talloc_destroy(mem_ctx); - reply_unixerror(req, ERRDOS, ERRnoaccess); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + reply_nterror(req, status); return; } - /* - * Now we can delete the security descriptor. - */ - - talloc_destroy(mem_ctx); + SMB_ASSERT(sd_size == blob.length); + memcpy(data, blob.data, sd_size); send_nt_replies(req, NT_STATUS_OK, params, 4, data, (int)sd_size); + + TALLOC_FREE(frame); return; } @@ -1752,7 +1710,7 @@ static void call_nt_transact_set_security_desc(connection_struct *conn, char *data = *ppdata; files_struct *fsp = NULL; uint32 security_info_sent = 0; - NTSTATUS nt_status; + NTSTATUS status; if(parameter_count < 8) { reply_doserror(req, ERRDOS, ERRbadfunc); @@ -1778,13 +1736,14 @@ static void call_nt_transact_set_security_desc(connection_struct *conn, return; } - if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) { - reply_nterror(req, nt_status); + status = set_sd(fsp, (uint8 *)data, data_count, security_info_sent); + + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); return; } done: - send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); return; } -- cgit From bd1172d106cff332b642e02c144922ed55508be4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 16 Dec 2007 18:02:32 -0800 Subject: Remove a static fstring. Jeremy. (This used to be commit 898c56c0ead6331721de9645ce55608cbe7cf34d) --- source3/smbd/chgpasswd.c | 50 +++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index a277e729bf..5ccf3ed9da 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -61,28 +61,30 @@ static NTSTATUS check_oem_password(const char *user, static int findpty(char **slave) { - int master; - static fstring line; - SMB_STRUCT_DIR *dirp; + int master = -1; + char *line = NULL; + SMB_STRUCT_DIR *dirp = NULL; const char *dpname; + *slave = NULL; + #if defined(HAVE_GRANTPT) /* Try to open /dev/ptmx. If that fails, fall through to old method. */ - if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0) - { + if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0) { grantpt(master); unlockpt(master); - *slave = (char *)ptsname(master); - if (*slave == NULL) - { + line = (char *)ptsname(master); + if (line) { + *slave = SMB_STRDUP(line); + } + + if (*slave == NULL) { DEBUG(0, ("findpty: Unable to create master/slave pty pair.\n")); /* Stop fd leak on error. */ close(master); return -1; - } - else - { + } else { DEBUG(10, ("findpty: Allocated slave pty %s\n", *slave)); return (master); @@ -90,22 +92,25 @@ static int findpty(char **slave) } #endif /* HAVE_GRANTPT */ - fstrcpy(line, "/dev/ptyXX"); + line = SMB_STRDUP("/dev/ptyXX"); + if (!line) { + return (-1); + } dirp = sys_opendir("/dev"); - if (!dirp) + if (!dirp) { + SAFE_FREE(line); return (-1); - while ((dpname = readdirname(dirp)) != NULL) - { - if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) - { + } + + while ((dpname = readdirname(dirp)) != NULL) { + if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { DEBUG(3, ("pty: try to open %s, line was %s\n", dpname, line)); line[8] = dpname[3]; line[9] = dpname[4]; - if ((master = sys_open(line, O_RDWR, 0)) >= 0) - { + if ((master = sys_open(line, O_RDWR, 0)) >= 0) { DEBUG(3, ("pty: opened %s\n", line)); line[5] = 't'; *slave = line; @@ -115,6 +120,7 @@ static int findpty(char **slave) } } sys_closedir(dirp); + SAFE_FREE(line); return (-1); } @@ -355,7 +361,7 @@ static int talktochild(int master, const char *seq) static bool chat_with_program(char *passwordprogram, const struct passwd *pass, char *chatsequence, bool as_root) { - char *slavedev; + char *slavedev = NULL; int master; pid_t pid, wpid; int wstat; @@ -381,6 +387,7 @@ static bool chat_with_program(char *passwordprogram, const struct passwd *pass, if ((pid = sys_fork()) < 0) { DEBUG(3, ("chat_with_program: Cannot fork() child for password change: %s\n", pass->pw_name)); + SAFE_FREE(slavedev); close(master); CatchChild(); return (False); @@ -388,6 +395,9 @@ static bool chat_with_program(char *passwordprogram, const struct passwd *pass, /* we now have a pty */ if (pid > 0) { /* This is the parent process */ + /* Don't need this anymore in parent. */ + SAFE_FREE(slavedev); + if ((chstat = talktochild(master, chatsequence)) == False) { DEBUG(3, ("chat_with_program: Child failed to change password: %s\n", pass->pw_name)); kill(pid, SIGKILL); /* be sure to end this process */ -- cgit From 8f28bda7f8c18de597d345126c9ee03e99776e55 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Dec 2007 10:44:09 -0800 Subject: Fix bug #5121 (unix passwd sync not working on a streams based system). Jeremy. (This used to be commit 545cd2139cfc9484b733693814d4724d37125942) --- source3/smbd/chgpasswd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5ccf3ed9da..e478122e9b 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -159,19 +159,19 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, DEBUG(3, ("More weirdness, could not open %s\n", slavedev)); return (False); } -#if defined(I_PUSH) && defined(I_FIND) +#if defined(TIOCSCTTY) + if (ioctl(slave, TIOCSCTTY, 0) < 0) + { + DEBUG(3, ("Error in ioctl call for slave pty\n")); + /* return(False); */ + } +#elif defined(I_PUSH) && defined(I_FIND) if (ioctl(slave, I_FIND, "ptem") == 0) { ioctl(slave, I_PUSH, "ptem"); } if (ioctl(slave, I_FIND, "ldterm") == 0) { ioctl(slave, I_PUSH, "ldterm"); } -#elif defined(TIOCSCTTY) - if (ioctl(slave, TIOCSCTTY, 0) < 0) - { - DEBUG(3, ("Error in ioctl call for slave pty\n")); - /* return(False); */ - } #endif /* Close master. */ -- cgit From 192aae0564c641fa06f90a064c033fa52d8cf549 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 Dec 2007 17:27:29 -0800 Subject: Remove more static fstrings (yes this little cache should be in the rbtree....). Jeremy. (This used to be commit 97cfdae4052d46a35040d4c1a4ade8bf2c41dbc7) --- source3/smbd/map_username.c | 68 ++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index c04e0f1ae2..bde755eff6 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -32,10 +32,45 @@ Returns True if username was changed, false otherwise. ********************************************************************/ +static char *last_from, *last_to; + +static const char *get_last_from(void) +{ + if (!last_from) { + return ""; + } + return last_from; +} + +static const char *get_last_to(void) +{ + if (!last_to) { + return ""; + } + return last_to; +} + +static bool set_last_from_to(const char *from, const char *to) +{ + char *orig_from = last_from; + char *orig_to = last_to; + + last_from = SMB_STRDUP(from); + last_to = SMB_STRDUP(to); + + SAFE_FREE(orig_from); + SAFE_FREE(orig_to); + + if (!last_from || !last_to) { + SAFE_FREE(last_from); + SAFE_FREE(last_to); + return false; + } + return true; +} + bool map_username(fstring user) { - static bool initialised=False; - static fstring last_from,last_to; XFILE *f; char *mapfile = lp_username_map(); char *s; @@ -46,12 +81,12 @@ bool map_username(fstring user) if (!*user) return false; - if (strequal(user,last_to)) + if (strequal(user,get_last_to())) return false; - if (strequal(user,last_from)) { - DEBUG(3,("Mapped user %s to %s\n",user,last_to)); - fstrcpy(user,last_to); + if (strequal(user,get_last_from())) { + DEBUG(3,("Mapped user %s to %s\n",user,get_last_to())); + fstrcpy(user,get_last_to()); return true; } @@ -98,15 +133,9 @@ bool map_username(fstring user) } /* ok. let's try the mapfile */ - if (!*mapfile) return False; - if (!initialised) { - *last_from = *last_to = 0; - initialised = True; - } - f = x_fopen(mapfile,O_RDONLY, 0); if (!f) { DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) )); @@ -135,7 +164,7 @@ bool map_username(fstring user) while (*unixname && isspace((int)*unixname)) unixname++; } - + if (!*unixname || strchr_m("#;",*unixname)) continue; @@ -159,27 +188,28 @@ bool map_username(fstring user) user_in_list(user, (const char **)dosuserlist)) { DEBUG(3,("Mapped user %s to %s\n",user,unixname)); mapped_user = True; - fstrcpy( last_from,user ); + + set_last_from_to(user, unixname); fstrcpy( user, unixname ); - fstrcpy( last_to,user ); + if ( return_if_mapped ) { str_list_free (&dosuserlist); x_fclose(f); return True; } } - + str_list_free (&dosuserlist); } x_fclose(f); /* - * Setup the last_from and last_to as an optimization so + * Setup the last_from and last_to as an optimization so * that we don't scan the file again for the same user. */ - fstrcpy(last_from,user); - fstrcpy(last_to,user); + + set_last_from_to(user, user); return mapped_user; } -- cgit From f427d4ce65659419c8989d87acd97d00b4db41e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 18 Dec 2007 09:41:03 +0100 Subject: Add a in-memory cache This is a more general API that caches data with a LRU scheme. See include/cache.h. No comments yet, I'm still working on it. But Jeremy has given me a hint in one of his checkins that he would like to make use of this now. The idea is that we get rid of all our silly little caches and merge them all into one cache that we can then very easily trim, for example even with a smbcontrol message if someone decides memory is tight. The main user is the stat cache, this patch also converts the getwd cache. More caches to come. (This used to be commit 7a911b35713538d82001a3c9f34152e293fe1943) --- source3/smbd/mangle_hash2.c | 67 +++++------------- source3/smbd/server.c | 13 ++++ source3/smbd/statcache.c | 64 ++++++----------- source3/smbd/vfs.c | 168 +++++++++++++++----------------------------- 4 files changed, 112 insertions(+), 200 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 7066c2a4e5..9643506aea 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -93,15 +93,6 @@ static unsigned char char_flags[256]; */ static unsigned mangle_prefix; -/* we will use a very simple direct mapped prefix cache. The big - advantage of this cache structure is speed and low memory usage - - The cache is indexed by the low-order bits of the hash, and confirmed by - hashing the resulting cache entry to match the known hash -*/ -static char **prefix_cache; -static unsigned int *prefix_cache_hashes; - /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static unsigned char base_reverse[256]; @@ -147,57 +138,39 @@ static unsigned int mangle_hash(const char *key, unsigned int length) return value & ~0x80000000; } -/* - initialise (ie. allocate) the prefix cache - */ -static bool cache_init(void) -{ - if (prefix_cache) { - return True; - } - - prefix_cache = SMB_CALLOC_ARRAY(char *,MANGLE_CACHE_SIZE); - if (!prefix_cache) { - return False; - } - - prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); - if (!prefix_cache_hashes) { - SAFE_FREE(prefix_cache); - return False; - } - - return True; -} - /* insert an entry into the prefix cache. The string might not be null terminated */ static void cache_insert(const char *prefix, int length, unsigned int hash) { - int i = hash % MANGLE_CACHE_SIZE; + char *str = SMB_STRNDUP(prefix, length); - if (prefix_cache[i]) { - free(prefix_cache[i]); + if (str == NULL) { + return; } - prefix_cache[i] = SMB_STRNDUP(prefix, length); - prefix_cache_hashes[i] = hash; + memcache_add(smbd_memcache(), MANGLE_HASH2_CACHE, + data_blob_const(&hash, sizeof(hash)), + data_blob_const(str, length+1)); + SAFE_FREE(str); } /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(unsigned int hash) +static char *cache_lookup(TALLOC_CTX *mem_ctx, unsigned int hash) { - int i = hash % MANGLE_CACHE_SIZE; + DATA_BLOB value; - if (!prefix_cache[i] || hash != prefix_cache_hashes[i]) { + if (!memcache_lookup(smbd_memcache(), MANGLE_HASH2_CACHE, + data_blob_const(&hash, sizeof(hash)), &value)) { return NULL; } - /* yep, it matched */ - return prefix_cache[i]; + SMB_ASSERT((value.length > 0) + && (value.data[value.length-1] == '\0')); + + return talloc_strdup(mem_ctx, (char *)value.data); } @@ -377,7 +350,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, { unsigned int hash, multiplier; unsigned int i; - const char *prefix; + char *prefix; char extension[4]; *pp_out = NULL; @@ -397,7 +370,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, } /* now look in the prefix cache for that hash */ - prefix = cache_lookup(hash); + prefix = cache_lookup(ctx, hash); if (!prefix) { M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n", name, hash)); @@ -421,6 +394,8 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, *pp_out = talloc_strdup(ctx, prefix); } + TALLOC_FREE(prefix); + if (!pp_out) { M_DEBUG(0,("talloc_fail")); return False; @@ -728,10 +703,6 @@ struct mangle_fns *mangle_hash2_init(void) init_tables(); mangle_reset(); - if (!cache_init()) { - return NULL; - } - return &mangle_fns; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 41d036a8b9..574197d711 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -86,6 +86,19 @@ struct messaging_context *smbd_messaging_context(void) return ctx; } +struct memcache *smbd_memcache(void) +{ + static struct memcache *cache; + + if (!cache + && !(cache = memcache_init(NULL, + lp_max_stat_cache_size()*1024))) { + + smb_panic("Could not init smbd memcache"); + } + return cache; +} + /******************************************************************* What to do when smb.conf is updated. ********************************************************************/ diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8f1e008985..72fed008a2 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -26,8 +26,6 @@ Stat cache code used in unix_convert. *****************************************************************************/ -static TDB_CONTEXT *tdb_stat_cache; - /** * Add an entry into the stat cache. * @@ -45,10 +43,8 @@ void stat_cache_add( const char *full_orig_name, bool case_sensitive) { size_t translated_path_length; - TDB_DATA data_val; char *original_path; size_t original_path_length; - size_t sc_size = lp_max_stat_cache_size(); char saved_char; TALLOC_CTX *ctx = talloc_tos(); @@ -56,12 +52,6 @@ void stat_cache_add( const char *full_orig_name, return; } - if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { - reset_stat_cache(); - } - - ZERO_STRUCT(data_val); - /* * Don't cache trivial valid directory entries such as . and .. */ @@ -132,24 +122,20 @@ void stat_cache_add( const char *full_orig_name, saved_char = translated_path[translated_path_length]; translated_path[translated_path_length] = '\0'; - data_val.dsize = translated_path_length + 1; - data_val.dptr = (uint8 *)translated_path; - /* * New entry or replace old entry. */ - if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, - TDB_REPLACE) != 0) { - DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", - original_path, translated_path)); - } else { - DEBUG(5,("stat_cache_add: Added entry (%lx:size%x) %s -> %s\n", - (unsigned long)data_val.dptr, - (unsigned int)data_val.dsize, - original_path, - translated_path)); - } + memcache_add( + smbd_memcache(), STAT_CACHE, + data_blob_const(original_path, original_path_length), + data_blob_const(translated_path, translated_path_length + 1)); + + DEBUG(5,("stat_cache_add: Added entry (%lx:size %x) %s -> %s\n", + (unsigned long)translated_path, + (unsigned int)translated_path_length, + original_path, + translated_path)); translated_path[translated_path_length] = saved_char; TALLOC_FREE(original_path); @@ -186,7 +172,7 @@ bool stat_cache_lookup(connection_struct *conn, unsigned int num_components = 0; char *translated_path; size_t translated_path_length; - TDB_DATA data_val; + DATA_BLOB data_val; char *name; TALLOC_CTX *ctx = talloc_tos(); @@ -236,9 +222,12 @@ bool stat_cache_lookup(connection_struct *conn, while (1) { char *sp; - data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name); + data_val = data_blob_null; - if (data_val.dptr != NULL && data_val.dsize != 0) { + if (memcache_lookup( + smbd_memcache(), STAT_CACHE, + data_blob_const(chk_name, strlen(chk_name)), + &data_val)) { break; } @@ -275,12 +264,11 @@ bool stat_cache_lookup(connection_struct *conn, } } - translated_path = talloc_strdup(ctx,(char *)data_val.dptr); + translated_path = talloc_strdup(ctx,(char *)data_val.data); if (!translated_path) { smb_panic("talloc failed"); } - translated_path_length = data_val.dsize - 1; - SAFE_FREE(data_val.dptr); + translated_path_length = data_val.length - 1; DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " "-> [%s]\n", chk_name, translated_path )); @@ -288,7 +276,8 @@ bool stat_cache_lookup(connection_struct *conn, if (SMB_VFS_STAT(conn, translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ - tdb_delete_bystring(tdb_stat_cache, chk_name); + memcache_delete(smbd_memcache(), STAT_CACHE, + data_blob_const(chk_name, strlen(chk_name))); TALLOC_FREE(chk_name); TALLOC_FREE(translated_path); return False; @@ -366,7 +355,8 @@ void stat_cache_delete(const char *name) DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n", lname, name )); - tdb_delete_bystring(tdb_stat_cache, lname); + memcache_delete(smbd_memcache(), STAT_CACHE, + data_blob_const(lname, talloc_get_size(lname)-1)); TALLOC_FREE(lname); } @@ -395,15 +385,7 @@ bool reset_stat_cache( void ) if (!lp_stat_cache()) return True; - if (tdb_stat_cache) { - tdb_close(tdb_stat_cache); - } + memcache_flush(smbd_memcache(), STAT_CACHE); - /* Create the in-memory tdb using our custom hash function. */ - tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL, - (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); - - if (!tdb_stat_cache) - return False; return True; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 628d2eec4b..45d0788117 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -731,152 +731,98 @@ int vfs_ChDir(connection_struct *conn, const char *path) return(res); } -/* number of list structures for a caching GetWd function. */ -#define MAX_GETWDCACHE (50) - -static 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 *path; /* The pathname. */ - bool valid; -} ino_list[MAX_GETWDCACHE]; - -extern bool use_getwd_cache; - -/**************************************************************************** - Prompte a ptr (to make it recently used) -****************************************************************************/ - -static void array_promote(char *array,int elsize,int element) -{ - char *p; - if (element == 0) - return; - - p = (char *)SMB_MALLOC(elsize); - - if (!p) { - DEBUG(5,("array_promote: malloc fail\n")); - return; - } - - memcpy(p,array + element * elsize, elsize); - memmove(array + elsize,array,elsize*element); - memcpy(array,p,elsize); - SAFE_FREE(p); -} - /******************************************************************* Return the absolute current directory path - given a UNIX pathname. Note that this path is returned in DOS format, not UNIX format. Note this can be called with conn == NULL. ********************************************************************/ +struct getwd_cache_key { + SMB_DEV_T dev; + SMB_INO_T ino; +}; + char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) { char s[PATH_MAX+1]; - static bool getwd_cache_init = False; SMB_STRUCT_STAT st, st2; - int i; - char *ret = NULL; + char *result; + DATA_BLOB cache_value; + struct getwd_cache_key key; *s = 0; - if (!use_getwd_cache) { - nocache: - ret = SMB_VFS_GETWD(conn,s); - if (!ret) { - DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, " - "errno %s\n",strerror(errno))); - return NULL; - } - return talloc_strdup(ctx, ret); - } - - /* init the cache */ - if (!getwd_cache_init) { - getwd_cache_init = True; - for (i=0;i 0) + && (cache_value.data[cache_value.length-1] == '\0')); - /* promote it for future use */ - array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); - if (ret == NULL) { - errno = ENOMEM; - } - return ret; - } else { - /* If the inode is different then something's changed, - scrub the entry and start from scratch. */ - ino_list[i].valid = False; - } - } - } + if ((SMB_VFS_STAT(conn, (char *)cache_value.data, &st2) == 0) + && (st.st_dev == st2.st_dev) && (st.st_ino == st2.st_ino) + && (S_ISDIR(st.st_mode))) { + /* + * Ok, we're done + */ + result = talloc_strdup(ctx, (char *)cache_value.data); + if (result == NULL) { + errno = ENOMEM; } + return result; } - /* 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. */ + nocache: + + /* + * 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 (!SMB_VFS_GETWD(conn,s)) { - DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n", - strerror(errno))); - return (NULL); + DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n", + strerror(errno))); + return NULL; } - ret = talloc_strdup(ctx,s); - - DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n", - s,(double)st.st_ino,(double)st.st_dev)); - - /* add it to the cache */ - i = MAX_GETWDCACHE - 1; - string_set(&ino_list[i].path,s); - ino_list[i].dev = st.st_dev; - ino_list[i].inode = st.st_ino; - ino_list[i].valid = True; + if (lp_getwd_cache() && VALID_STAT(st)) { + ZERO_STRUCT(key); /* unlikely, but possible padding */ + key.dev = st.st_dev; + key.ino = st.st_ino; - /* put it at the top of the list */ - array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); + memcache_add(smbd_memcache(), GETWD_CACHE, + data_blob_const(&key, sizeof(key)), + data_blob_const(s, strlen(s)+1)); + } - if (ret == NULL) { + result = talloc_strdup(ctx, s); + if (result == NULL) { errno = ENOMEM; } - return ret; + return result; } /******************************************************************* -- cgit From a34c6cd0e7046c1127b05bf3b5d5819f1d500cbc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Dec 2007 18:10:09 -0800 Subject: Remove last_message completely as it's no longer used. Jeremy. (This used to be commit c378c3edc1197d46c5d6eb2bcabbf9e774c03ffc) --- source3/smbd/process.c | 3 --- source3/smbd/server.c | 6 ------ 2 files changed, 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ffc9e106f6..ee76f90bf5 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -38,7 +38,6 @@ int max_send = BUFFER_SIZE; */ int max_recv = BUFFER_SIZE; -extern int last_message; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; extern bool global_machine_password_needs_changing; @@ -1308,8 +1307,6 @@ static void switch_message(uint8 type, struct smb_request *req, int size) errno = 0; - last_message = type; - /* Make sure this is an SMB packet. smb_size contains NetBIOS header * so subtract 4 from it. */ if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0) diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 574197d711..40037074f6 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -27,12 +27,6 @@ static_decl_rpc; static int am_parent = 1; -/* the last message the was processed */ -int last_message = -1; - -/* a useful macro to debug the last message processed */ -#define LAST_MESSAGE() smb_fn_name(last_message) - extern struct auth_context *negprot_global_auth_context; extern SIG_ATOMIC_T got_sig_term; extern SIG_ATOMIC_T reload_after_sighup; -- cgit From e518e19bc0000019f131354f55e9f5b55f6a2c5e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Dec 2007 15:02:59 +0100 Subject: Remove Get_Pwnam and its associated static variable All callers are replaced by Get_Pwnam_alloc (This used to be commit 735f59315497113aebadcf9ad387e3dbfffa284a) --- source3/smbd/chgpasswd.c | 6 +++++- source3/smbd/map_username.c | 2 +- source3/smbd/password.c | 5 ++++- source3/smbd/service.c | 11 ++++++++--- 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e478122e9b..fb228f9e2a 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1142,7 +1142,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw return NT_STATUS_PASSWORD_RESTRICTION; } - pass = Get_Pwnam(username); + pass = Get_Pwnam_alloc(talloc_tos(), username); if (!pass) { DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username)); return NT_STATUS_ACCESS_DENIED; @@ -1160,6 +1160,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw if (samr_reject_reason) { *samr_reject_reason = REJECT_REASON_NOT_COMPLEX; } + TALLOC_FREE(pass); return NT_STATUS_PASSWORD_RESTRICTION; } } @@ -1178,9 +1179,12 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw if(lp_unix_password_sync() && !chgpasswd(username, pass, old_passwd, new_passwd, as_root)) { + TALLOC_FREE(pass); return NT_STATUS_ACCESS_DENIED; } + TALLOC_FREE(pass); + if (!pdb_set_plaintext_passwd (hnd, new_passwd)) { return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index bde755eff6..7290f70547 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -28,7 +28,7 @@ any incoming or new username - in order to canonicalize the name. This is being done to de-couple the case conversions from the user mapping function. Previously, the map_username was being called - every time Get_Pwnam was called. + every time Get_Pwnam_alloc was called. Returns True if username was changed, false otherwise. ********************************************************************/ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b3005ba082..6b517c3d86 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -837,9 +837,11 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password, /* check for a normal guest connection */ if (!ok && GUEST_OK(snum)) { + struct passwd *guest_pw; fstring guestname; fstrcpy(guestname,lp_guestaccount()); - if (Get_Pwnam(guestname)) { + guest_pw = Get_Pwnam_alloc(talloc_tos(), guestname); + if (guest_pw != NULL) { fstrcpy(user,guestname); ok = True; DEBUG(3,("authorise_login: ACCEPTED: guest account " @@ -848,6 +850,7 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password, DEBUG(0,("authorise_login: Invalid guest account " "%s??\n",guestname)); } + TALLOC_FREE(guest_pw); *guest = True; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 88ab9f0048..ed43528c76 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -357,6 +357,7 @@ void load_registry_shares(void) int find_service(fstring service) { int iService; + TALLOC_CTX *frame = talloc_stackframe(); all_string_sub(service,"\\","/",0); @@ -364,7 +365,7 @@ int find_service(fstring service) /* now handle the special case of a home directory */ if (iService < 0) { - char *phome_dir = get_user_home_dir(service); + char *phome_dir = get_user_home_dir(talloc_tos(), service); if(!phome_dir) { /* @@ -372,7 +373,8 @@ int find_service(fstring service) * be a Windows to unix mapped user name. */ if(map_username(service)) - phome_dir = get_user_home_dir(service); + phome_dir = get_user_home_dir( + talloc_tos(), service); } DEBUG(3,("checking for home directory %s gave %s\n",service, @@ -461,6 +463,8 @@ int find_service(fstring service) if (iService < 0) DEBUG(3,("find_service() failed to find service %s\n", service)); + TALLOC_FREE(frame); + return (iService); } @@ -744,11 +748,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *status = NT_STATUS_WRONG_PASSWORD; return NULL; } - pass = Get_Pwnam(user); + pass = Get_Pwnam_alloc(talloc_tos(), user); status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, &conn->uid, &conn->gid, &found_username, &conn->nt_user_token); + TALLOC_FREE(pass); if (!NT_STATUS_IS_OK(status2)) { conn_free(conn); *status = status2; -- cgit From bb89f8cb94802bb2f9b43c1c63fd55ee2de9b09e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 28 Oct 2007 01:14:51 +0200 Subject: Change apply_default_perms() to not take an fsp. This is a first change in a series: Pass what is needed instead of files_struct pointers to some functions. This is in preparation of introducing two variants of get_nt_acl - one for fname (which does not need an fsp), one for file descriptor. This changes apply_default_perms to take share_params (rather thatn snum) and an is_directory flag instead of an fsp. Michael (This used to be commit d7e2e93758f6598a0459db3255300558618f066e) --- source3/smbd/posix_acls.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ccfed69721..ca83d85399 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -999,20 +999,21 @@ NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_i Ensure the enforced permissions for this share apply. ****************************************************************************/ -static void apply_default_perms(const files_struct *fsp, canon_ace *pace, mode_t type) +static void apply_default_perms(const struct share_params *params, + const bool is_directory, canon_ace *pace, + mode_t type) { - int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; mode_t or_bits = (mode_t)0; /* Get the initial bits to apply. */ - if (fsp->is_directory) { - and_bits = lp_dir_security_mask(snum); - or_bits = lp_force_dir_security_mode(snum); + if (is_directory) { + and_bits = lp_dir_security_mask(params->service); + or_bits = lp_force_dir_security_mode(params->service); } else { - and_bits = lp_security_mask(snum); - or_bits = lp_force_security_mode(snum); + and_bits = lp_security_mask(params->service); + or_bits = lp_force_security_mode(params->service); } /* Now bounce them into the S_USR space. */ @@ -1020,7 +1021,7 @@ static void apply_default_perms(const files_struct *fsp, canon_ace *pace, mode_t case S_IRUSR: /* Ensure owner has read access. */ pace->perms |= S_IRUSR; - if (fsp->is_directory) + if (is_directory) pace->perms |= (S_IWUSR|S_IXUSR); and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR); or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR); @@ -1092,7 +1093,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, if (pace->type == SMB_ACL_USER_OBJ) { if (setting_acl) - apply_default_perms(fsp, pace, S_IRUSR); + apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRUSR); got_user = True; } else if (pace->type == SMB_ACL_GROUP_OBJ) { @@ -1102,7 +1103,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, */ if (setting_acl) - apply_default_perms(fsp, pace, S_IRGRP); + apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRGRP); got_grp = True; } else if (pace->type == SMB_ACL_OTHER) { @@ -1112,7 +1113,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, */ if (setting_acl) - apply_default_perms(fsp, pace, S_IROTH); + apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IROTH); got_other = True; pace_other = pace; } @@ -1155,7 +1156,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->perms = 0; } - apply_default_perms(fsp, pace, S_IRUSR); + apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRUSR); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); } @@ -1181,7 +1182,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->perms = pace_other->perms; else pace->perms = 0; - apply_default_perms(fsp, pace, S_IRGRP); + apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRGRP); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); } @@ -1203,7 +1204,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->attr = ALLOW_ACE; if (setting_acl) { pace->perms = 0; - apply_default_perms(fsp, pace, S_IROTH); + apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IROTH); } else pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); -- cgit From c5d21d1a651aa02c7b3e2fbaa89b8364bdfbfa68 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 28 Oct 2007 01:24:41 +0200 Subject: Change ensure_canon_entry_valid() to not take and fsp. Convert ensure_canon_entry_valid() to take share_params and an is_directory flag instead of an files_struct pointer. Michael (This used to be commit bdb208124bd703edee03ac4d2a4ec45ecdfc135e) --- source3/smbd/posix_acls.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ca83d85399..7be4ee1c80 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1077,7 +1077,8 @@ static bool uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) ****************************************************************************/ static bool ensure_canon_entry_valid(canon_ace **pp_ace, - const files_struct *fsp, + const struct share_params *params, + const bool is_directory, const DOM_SID *pfile_owner_sid, const DOM_SID *pfile_grp_sid, const SMB_STRUCT_STAT *pst, @@ -1093,7 +1094,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, if (pace->type == SMB_ACL_USER_OBJ) { if (setting_acl) - apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRUSR); + apply_default_perms(params, is_directory, pace, S_IRUSR); got_user = True; } else if (pace->type == SMB_ACL_GROUP_OBJ) { @@ -1103,7 +1104,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, */ if (setting_acl) - apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRGRP); + apply_default_perms(params, is_directory, pace, S_IRGRP); got_grp = True; } else if (pace->type == SMB_ACL_OTHER) { @@ -1113,7 +1114,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, */ if (setting_acl) - apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IROTH); + apply_default_perms(params, is_directory, pace, S_IROTH); got_other = True; pace_other = pace; } @@ -1156,7 +1157,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->perms = 0; } - apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRUSR); + apply_default_perms(params, is_directory, pace, S_IRUSR); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); } @@ -1182,7 +1183,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->perms = pace_other->perms; else pace->perms = 0; - apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IRGRP); + apply_default_perms(params, is_directory, pace, S_IRGRP); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); } @@ -1204,7 +1205,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->attr = ALLOW_ACE; if (setting_acl) { pace->perms = 0; - apply_default_perms(fsp->conn->params, fsp->is_directory, pace, S_IROTH); + apply_default_perms(params, is_directory, pace, S_IROTH); } else pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); @@ -2015,7 +2016,7 @@ static bool unpack_canon_ace(files_struct *fsp, pst->st_mode = create_default_mode(fsp, False); - if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { + if (!ensure_canon_entry_valid(&file_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -2031,7 +2032,7 @@ static bool unpack_canon_ace(files_struct *fsp, pst->st_mode = create_default_mode(fsp, True); - if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) { + if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -2227,7 +2228,7 @@ static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl * This next call will ensure we have at least a user/group/world set. */ - if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf, False)) + if (!ensure_canon_entry_valid(&list_head, fsp->conn->params, fsp->is_directory, powner, pgroup, psbuf, False)) goto fail; /* -- cgit From 13e0788714c1a5a3ce62597d04d3034ca14d031e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 28 Oct 2007 01:38:59 +0200 Subject: Change canonicalise_acl() to not take an fsp. Convert canonicalise_acl() to take connection_struct, is_directory and file name instead of files_struct pointer. Michael (This used to be commit d579a7f84fd47a3f00215725cecd65b21a5ff2e0) --- source3/smbd/posix_acls.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 7be4ee1c80..1b91823ea2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2110,10 +2110,11 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head) Create a linked list of canonical ACE entries. ****************************************************************************/ -static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, +static canon_ace *canonicalise_acl(const struct connection_struct *conn, + const bool is_directory, const char *fname, + SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { - connection_struct *conn = fsp->conn; mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); canon_ace *list_head = NULL; canon_ace *ace = NULL; @@ -2228,7 +2229,7 @@ static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl * This next call will ensure we have at least a user/group/world set. */ - if (!ensure_canon_entry_valid(&list_head, fsp->conn->params, fsp->is_directory, powner, pgroup, psbuf, False)) + if (!ensure_canon_entry_valid(&list_head, conn->params, is_directory, powner, pgroup, psbuf, False)) goto fail; /* @@ -2254,7 +2255,7 @@ static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl } } - arrange_posix_perms(fsp->fsp_name,&list_head ); + arrange_posix_perms(fname,&list_head ); print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head ); @@ -2816,7 +2817,10 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) */ /* Create the canon_ace lists. */ - file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS ); + file_ace = canonicalise_acl(fsp->conn, fsp->is_directory, + fsp->fsp_name, posix_acl, &sbuf, + &owner_sid, &group_sid, pal, + SMB_ACL_TYPE_ACCESS); /* We must have *some* ACLS. */ @@ -2826,9 +2830,12 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } if (fsp->is_directory && def_acl) { - dir_ace = canonicalise_acl(fsp, def_acl, &sbuf, - &global_sid_Creator_Owner, - &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT ); + dir_ace = canonicalise_acl(fsp->conn, fsp->is_directory, + fsp->fsp_name, def_acl, + &sbuf, + &global_sid_Creator_Owner, + &global_sid_Creator_Group, + pal, SMB_ACL_TYPE_DEFAULT); } /* -- cgit From a7e15d41c66e811777e52fbfa19df817d8617d5a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 6 Nov 2007 06:20:51 +0100 Subject: Remove the "is_directory" parameter from canonicalise_acl(): It can be retrieved from the stat buffer. Michael (This used to be commit b0ae830bf57dcaec00b2a2eabfec7221a3b7f791) --- source3/smbd/posix_acls.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 1b91823ea2..57a3ff9766 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2110,10 +2110,10 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head) Create a linked list of canonical ACE entries. ****************************************************************************/ -static canon_ace *canonicalise_acl(const struct connection_struct *conn, - const bool is_directory, const char *fname, - SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, - const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) +static canon_ace *canonicalise_acl(struct connection_struct *conn, + const char *fname, SMB_ACL_T posix_acl, + const SMB_STRUCT_STAT *psbuf, + const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); canon_ace *list_head = NULL; @@ -2229,7 +2229,9 @@ static canon_ace *canonicalise_acl(const struct connection_struct *conn, * This next call will ensure we have at least a user/group/world set. */ - if (!ensure_canon_entry_valid(&list_head, conn->params, is_directory, powner, pgroup, psbuf, False)) + if (!ensure_canon_entry_valid(&list_head, conn->params, + S_ISDIR(psbuf->st_mode), powner, pgroup, + psbuf, False)) goto fail; /* @@ -2817,7 +2819,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) */ /* Create the canon_ace lists. */ - file_ace = canonicalise_acl(fsp->conn, fsp->is_directory, + file_ace = canonicalise_acl(fsp->conn, fsp->fsp_name, posix_acl, &sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS); @@ -2830,7 +2832,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } if (fsp->is_directory && def_acl) { - dir_ace = canonicalise_acl(fsp->conn, fsp->is_directory, + dir_ace = canonicalise_acl(fsp->conn, fsp->fsp_name, def_acl, &sbuf, &global_sid_Creator_Owner, -- cgit From 8e2323e391e312e0f0284c918e2bb8567c035e20 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 6 Nov 2007 08:01:31 +0100 Subject: Split get_nt_acl() into two functions: fsp- and non-fsp variant. Replace smbd/posix_acls.c:get_nt_acl() by two funcions: posix_get_nt_acl() and posix_fget_nt_acl(). The first takes a connection struct and a file name instead of a files_struct pointer. This is in preparation of changing the vfs api for SMB_VFS_GET_NT_ACL. Michael (This used to be commit 50c82cc1456736fa634fb656e63555319742f725) --- source3/smbd/posix_acls.c | 211 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 148 insertions(+), 63 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 57a3ff9766..d9782cfdb8 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -430,7 +430,7 @@ static struct pai_val *create_pai_val(char *buf, size_t size) Load the user.SAMBA_PAI attribute. ************************************************************************/ -static struct pai_val *load_inherited_info(files_struct *fsp) +static struct pai_val *fload_inherited_info(files_struct *fsp) { char *pai_buf; size_t pai_buf_size = 1024; @@ -490,6 +490,71 @@ static struct pai_val *load_inherited_info(files_struct *fsp) return paiv; } +/************************************************************************ + Load the user.SAMBA_PAI attribute. +************************************************************************/ + +static struct pai_val *load_inherited_info(const struct connection_struct *conn, + const char *fname) +{ + char *pai_buf; + size_t pai_buf_size = 1024; + struct pai_val *paiv = NULL; + ssize_t ret; + + if (!lp_map_acl_inherit(SNUM(conn))) { + return NULL; + } + + if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) { + return NULL; + } + + do { + ret = SMB_VFS_GETXATTR(conn, fname, + SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, pai_buf_size); + + if (ret == -1) { + if (errno != ERANGE) { + break; + } + /* Buffer too small - enlarge it. */ + pai_buf_size *= 2; + SAFE_FREE(pai_buf); + if (pai_buf_size > 1024*1024) { + return NULL; /* Limit malloc to 1mb. */ + } + if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) + return NULL; + } + } while (ret == -1); + + DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fname)); + + if (ret == -1) { + /* No attribute or not supported. */ +#if defined(ENOATTR) + if (errno != ENOATTR) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#else + if (errno != ENOSYS) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#endif + SAFE_FREE(pai_buf); + return NULL; + } + + paiv = create_pai_val(pai_buf, ret); + + if (paiv && paiv->pai_protected) { + DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fname)); + } + + SAFE_FREE(pai_buf); + return paiv; +} + /**************************************************************************** Functions to manipulate the internal ACE format. ****************************************************************************/ @@ -2724,6 +2789,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) return num_aces; } + /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns the size needed to return the @@ -2731,11 +2797,15 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) the UNIX style get ACL. ****************************************************************************/ -NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) +static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, + const char *name, + const SMB_STRUCT_STAT *sbuf, + struct pai_val *pal, + SMB_ACL_T posix_acl, + SMB_ACL_T def_acl, + uint32_t security_info, + SEC_DESC **ppdesc) { - connection_struct *conn = fsp->conn; - SMB_STRUCT_STAT sbuf; - SEC_ACE *nt_ace_list = NULL; DOM_SID owner_sid; DOM_SID group_sid; size_t sd_size = 0; @@ -2743,57 +2813,12 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) size_t num_acls = 0; size_t num_def_acls = 0; size_t num_aces = 0; - SMB_ACL_T posix_acl = NULL; - SMB_ACL_T def_acl = NULL; canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; + SEC_ACE *nt_ace_list = NULL; size_t num_profile_acls = 0; - struct pai_val *pal = NULL; SEC_DESC *psd = NULL; - *ppdesc = NULL; - - DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name )); - - if(fsp->is_directory || fsp->fh->fd == -1) { - - /* Get the stat struct for the owner info. */ - if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { - return map_nt_error_from_unix(errno); - } - /* - * Get the ACL from the path. - */ - - posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); - - /* - * If it's a directory get the default POSIX ACL. - */ - - if(fsp->is_directory) { - def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); - def_acl = free_empty_sys_acl(conn, def_acl); - } - - } else { - - /* Get the stat struct for the owner info. */ - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { - return map_nt_error_from_unix(errno); - } - /* - * Get the ACL from the fd. - */ - posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); - } - - DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", - posix_acl ? "present" : "absent", - def_acl ? "present" : "absent" )); - - pal = load_inherited_info(fsp); - /* * Get the owner, group and world SIDs. */ @@ -2804,7 +2829,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) sid_copy(&group_sid, &global_sid_Builtin_Users); num_profile_acls = 2; } else { - create_file_sids(&sbuf, &owner_sid, &group_sid); + create_file_sids(sbuf, &owner_sid, &group_sid); } if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) { @@ -2819,22 +2844,20 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) */ /* Create the canon_ace lists. */ - file_ace = canonicalise_acl(fsp->conn, - fsp->fsp_name, posix_acl, &sbuf, + file_ace = canonicalise_acl(conn, name, posix_acl, sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS); /* We must have *some* ACLS. */ if (count_canon_ace_list(file_ace) == 0) { - DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); + DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", name)); goto done; } - if (fsp->is_directory && def_acl) { - dir_ace = canonicalise_acl(fsp->conn, - fsp->fsp_name, def_acl, - &sbuf, + if (S_ISDIR(sbuf->st_mode) && def_acl) { + dir_ace = canonicalise_acl(conn, name, def_acl, + sbuf, &global_sid_Creator_Owner, &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT); @@ -2921,7 +2944,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, ace->perms, - fsp->is_directory); + S_ISDIR(sbuf->st_mode)); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, @@ -2950,7 +2973,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, ace->perms, - fsp->is_directory); + S_ISDIR(sbuf->st_mode)); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, @@ -3039,6 +3062,69 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) return NT_STATUS_OK; } +NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, + SEC_DESC **ppdesc) +{ + SMB_STRUCT_STAT sbuf; + SMB_ACL_T posix_acl = NULL; + struct pai_val *pal; + + *ppdesc = NULL; + + DEBUG(10,("posix_fget_nt_acl: called for file %s\n", fsp->fsp_name )); + + /* can it happen that fsp_name == NULL ? */ + if (fsp->is_directory || fsp->fh->fd == -1) { + return posix_get_nt_acl(fsp->conn, fsp->fsp_name, + security_info, ppdesc); + } + + /* Get the stat struct for the owner info. */ + if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { + return map_nt_error_from_unix(errno); + } + + /* Get the ACL from the fd. */ + posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); + + pal = fload_inherited_info(fsp); + + return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name, &sbuf, pal, + posix_acl, NULL, security_info, ppdesc); +} + +NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, + uint32_t security_info, SEC_DESC **ppdesc) +{ + SMB_STRUCT_STAT sbuf; + SMB_ACL_T posix_acl = NULL; + SMB_ACL_T def_acl = NULL; + struct pai_val *pal; + + *ppdesc = NULL; + + DEBUG(10,("posix_get_nt_acl: called for file %s\n", name )); + + /* Get the stat struct for the owner info. */ + if(SMB_VFS_STAT(conn, name, &sbuf) != 0) { + return map_nt_error_from_unix(errno); + } + + /* Get the ACL from the path. */ + posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_ACCESS); + + /* If it's a directory get the default POSIX ACL. */ + if(S_ISDIR(sbuf.st_mode)) { + def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_DEFAULT); + def_acl = free_empty_sys_acl(conn, def_acl); + } + + pal = load_inherited_info(conn, name); + + return posix_get_nt_acl_common(conn, name, &sbuf, pal, posix_acl, + def_acl, security_info, ppdesc); +} + /**************************************************************************** Try to chown a file. We will be able to chown it under the following conditions. @@ -4182,8 +4268,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) finfo.fh->fd = -1; finfo.fsp_name = CONST_DISCARD(char *,fname); - if (!NT_STATUS_IS_OK(get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, - &psd ))) { + if (!NT_STATUS_IS_OK(posix_fget_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); conn_free_internal( &conn ); return NULL; -- cgit From 233eb0e560acb26f8706fd3ab96d4c6379458414 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 5 Dec 2007 09:53:10 +0100 Subject: Change the prototype of the vfs function get_nt_acl(). Up to now, get_nt_acl() took a files_struct pointer (fsp) and a file name. All the underlying functions should need and now do need (after the previous preparatory work), is a connection_struct and a file name. The connection_struct is already there in the vfs_handle passed to the vfs functions. So the files_struct argument can be eliminated. This eliminates the need of calling open_file_stat in a couple of places to produce the fsp needed. Michael (This used to be commit b5f600fab53c9d159a958c59795db3ba4a8acc63) --- source3/smbd/file_access.c | 67 ++++------------------------------------------ source3/smbd/nttrans.c | 2 +- source3/smbd/posix_acls.c | 2 +- 3 files changed, 7 insertions(+), 64 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index a58bcdd891..964d1af258 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -25,67 +25,6 @@ extern struct current_user current_user; #undef DBGC_CLASS #define DBGC_CLASS DBGC_ACLS -/**************************************************************************** - Helper function that gets a security descriptor by connection and - file name. - NOTE: This is transitional, in the sense that SMB_VFS_GET_NT_ACL really - should *not* get a files_struct pointer but a connection_struct ptr - (automatic by the vfs handle) and the file name and _use_ that! -****************************************************************************/ -static NTSTATUS conn_get_nt_acl(TALLOC_CTX *mem_ctx, - struct connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - struct security_descriptor **psd) -{ - NTSTATUS status; - struct files_struct *fsp = NULL; - struct security_descriptor *secdesc = NULL; - - if (!VALID_STAT(*psbuf)) { - if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { - return map_nt_error_from_unix(errno); - } - } - - /* fake a files_struct ptr: */ - - if (S_ISDIR(psbuf->st_mode)) { - status = open_directory(conn, NULL, fname, psbuf, - READ_CONTROL_ACCESS, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_DIRECTORY, - NULL, &fsp); - } - else { - status = open_file_stat(conn, NULL, fname, psbuf, &fsp); - } - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Unable to open file %s: %s\n", fname, - nt_errstr(status))); - return status; - } - - status = SMB_VFS_GET_NT_ACL(fsp, fname, - (OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION), - &secdesc); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(5, ("Unable to get NT ACL for file %s\n", fname)); - goto done; - } - - *psd = talloc_move(mem_ctx, &secdesc); - -done: - close_file(fsp, NORMAL_CLOSE); - return status; -} - static bool can_access_file_acl(struct connection_struct *conn, const char * fname, SMB_STRUCT_STAT *psbuf, uint32_t access_mask) @@ -95,7 +34,11 @@ static bool can_access_file_acl(struct connection_struct *conn, uint32_t access_granted; struct security_descriptor *secdesc = NULL; - status = conn_get_nt_acl(talloc_tos(), conn, fname, psbuf, &secdesc); + status = SMB_VFS_GET_NT_ACL(conn, fname, + (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION), + &secdesc); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status))); return false; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1fbb681c72..cb98a8139c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1640,7 +1640,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, } else { status = SMB_VFS_GET_NT_ACL( - fsp, fsp->fsp_name, security_info_wanted, &psd); + conn, fsp->fsp_name, security_info_wanted, &psd); } } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d9782cfdb8..d8794e2114 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3307,7 +3307,7 @@ static NTSTATUS append_parent_acl(files_struct *fsp, return status; } - status = SMB_VFS_GET_NT_ACL(parent_fsp, parent_fsp->fsp_name, + status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, parent_fsp->fsp_name, DACL_SECURITY_INFORMATION, &parent_sd ); close_file(parent_fsp, NORMAL_CLOSE); -- cgit From d2a9630a8b239118e7fc4b9dcedd860e6b7574f1 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 15 Oct 2007 13:59:37 -0700 Subject: Release per-fsp data on file closure. (This used to be commit 9fead46b54519b3df78a869dbc99207046587d6a) --- source3/smbd/files.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 179963dae9..95f01b88ce 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -460,6 +460,11 @@ void file_free(files_struct *fsp) ZERO_STRUCT(fsp_fi_cache); } + /* Drop all remaining extensions. */ + while (fsp->vfs_extension) { + vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp); + } + SAFE_FREE(fsp); } -- cgit From 26b75f2d833d7a4ba588e66b5cf6cf3ed8e0b236 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 15 Oct 2007 14:01:12 -0700 Subject: Expose per-fsp extension talloc context. This patch supplements the fsp extension API with an operation to retrieve the malloc zone pointer for that fsp. (This used to be commit d5d9e4084cfb3db3bebff0334b93f376022ef5d3) --- source3/smbd/vfs.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 45d0788117..96d71da8d9 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -263,19 +263,31 @@ void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) } } -void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) { struct vfs_fsp_data *head; for (head = fsp->vfs_extension; head; head = head->next) { if (head->owner == handle) { - return EXT_DATA_AREA(head); + return head; } } return NULL; } +void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +{ + struct vfs_fsp_data *head; + + head = vfs_memctx_fsp_extension(handle, fsp); + if (head != NULL) { + return EXT_DATA_AREA(head); + } + + return NULL; +} + #undef EXT_DATA_AREA /***************************************************************** -- cgit From 2403b319a76c3b425d618a3ff937e7ff05d211b4 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 15 Oct 2007 14:03:40 -0700 Subject: Add filesystem capabilities bitmask to statfs info. This patch adds Darwin support for the Samba statfs VFS call. It also adds a filesystem capabilities bitmask to the information returned by the call. (This used to be commit 555173eb3f6511e88798d6ef3d1fed0c219a9921) --- source3/smbd/statvfs.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/statvfs.c b/source3/smbd/statvfs.c index f6663208ea..5fc0afdd79 100644 --- a/source3/smbd/statvfs.c +++ b/source3/smbd/statvfs.c @@ -3,6 +3,7 @@ VFS API's statvfs abstraction Copyright (C) Alexander Bokovoy 2005 Copyright (C) Steve French 2005 + Copyright (C) James Peach 2006 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 @@ -37,11 +38,93 @@ static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) statbuf->TotalFileNodes = statvfs_buf.f_files; statbuf->FreeFileNodes = statvfs_buf.f_ffree; statbuf->FsIdentifier = statvfs_buf.f_fsid; + + /* Good defaults for Linux filesystems are case sensitive + * and case preserving. + */ + statbuf->FsCapabilities = + FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVING_NAMES; } return result; } #endif +#if defined(DARWINOS) + +#include + +static int darwin_fs_capabilities(const char * path) +{ + int caps = 0; + vol_capabilities_attr_t *vcaps; + struct attrlist attrlist; + char attrbuf[sizeof(u_int32_t) + sizeof(vol_capabilities_attr_t)]; + +#define FORMAT_CAP(vinfo, cap) \ + ( ((vinfo)->valid[VOL_CAPABILITIES_FORMAT] & (cap)) && \ + ((vinfo)->capabilities[VOL_CAPABILITIES_FORMAT] & (cap)) ) + +#define INTERFACE_CAP(vinfo, cap) \ + ( ((vinfo)->valid[VOL_CAPABILITIES_INTERFACES] & (cap)) && \ + ((vinfo)->capabilities[VOL_CAPABILITIES_INTERFACES] & (cap)) ) + + ZERO_STRUCT(attrlist); + attrlist.bitmapcount = ATTR_BIT_MAP_COUNT; + attrlist.volattr = ATTR_VOL_CAPABILITIES; + + if (getattrlist(path, &attrlist, attrbuf, sizeof(attrbuf), 0) != 0) { + DEBUG(0, ("getattrlist for %s capabilities failed: %s\n", + path, strerror(errno))); + /* Return no capabilities on failure. */ + return 0; + } + + vcaps = + (vol_capabilities_attr_t *)(attrbuf + sizeof(u_int32_t)); + + if (FORMAT_CAP(vcaps, VOL_CAP_FMT_SPARSE_FILES)) { + caps |= FILE_SUPPORTS_SPARSE_FILES; + } + + if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_SENSITIVE)) { + caps |= FILE_CASE_SENSITIVE_SEARCH; + } + + if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_PRESERVING)) { + caps |= FILE_CASE_PRESERVED_NAMES; + } + + if (INTERFACE_CAP(vcaps, VOL_CAP_INT_EXTENDED_SECURITY)) { + caps |= FILE_PERSISTENT_ACLS; + } + + return caps; +} + +static int darwin_statvfs(const char *path, vfs_statvfs_struct *statbuf) +{ + struct statfs sbuf; + int ret; + + ret = statfs(path, &sbuf); + if (ret != 0) { + return ret; + } + + statbuf->OptimalTransferSize = sbuf.f_iosize; + statbuf->BlockSize = sbuf.f_bsize; + statbuf->TotalBlocks = sbuf.f_blocks; + statbuf->BlocksAvail = sbuf.f_bfree; + statbuf->UserBlocksAvail = sbuf.f_bavail; + statbuf->TotalFileNodes = sbuf.f_files; + statbuf->FreeFileNodes = sbuf.f_ffree; + statbuf->FsIdentifier = *(SMB_BIG_UINT *)(&sbuf.f_fsid); /* Ick. */ + statbuf->FsCapabilities = darwin_fs_capabilities(sbuf.f_mntonname); + + return 0; +} +#endif + /* sys_statvfs() is an abstraction layer over system-dependent statvfs()/statfs() for particular POSIX systems. Due to controversy of what is considered more important @@ -52,6 +135,8 @@ int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf) { #if defined(LINUX) && defined(HAVE_FSID_INT) return linux_statvfs(path, statbuf); +#elif defined(DARWINOS) + return darwin_statvfs(path, statbuf); #else /* BB change this to return invalid level */ #ifdef EOPNOTSUPP -- cgit From 2ee96c7ee30ece5eeec97b545ac0f98fc3c00060 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 19 Dec 2007 22:33:43 -0800 Subject: Fix a couple of warnings in mDNS registration. One of these is an actual bug where we pass a pointer instead of a pointer to a pointer. (This used to be commit 36db6755103f01cb74bf4194fc81ca6d4b5320e4) --- source3/smbd/dnsregister.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c index 44bd39f64e..2319097ca5 100644 --- a/source3/smbd/dnsregister.c +++ b/source3/smbd/dnsregister.c @@ -41,7 +41,6 @@ struct dns_reg_state { void dns_register_close(struct dns_reg_state **dns_state_ptr) { - int mdnsd_conn_fd; struct dns_reg_state *dns_state = *dns_state_ptr; if (dns_state == NULL) { @@ -74,7 +73,7 @@ static void dns_register_smbd_retry(struct event_context *ctx, /* Clear previous registration state to force new * registration attempt. Clears event handler. */ - dns_register_close(dns_state); + dns_register_close(&dns_state); } static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state, -- cgit From 8804f5bdd7cbc0bc8166c7a4a9a09fbcb4402afd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 20 Dec 2007 10:33:13 +0100 Subject: Attempt to fix the build James, at least on my Linux system neither FILE_CASE_SENSITIVE_SEARCH nor FILE_CASE_PRESERVING_NAMES seem to be defined anywhere. Is it possible that this is a MacOS/X specific thing? If so, could you add configure tests for this? Thanks, Volker (This used to be commit 465fd4385013c95f9778d710d70796feae4eb858) --- source3/smbd/statvfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/statvfs.c b/source3/smbd/statvfs.c index 5fc0afdd79..431489032c 100644 --- a/source3/smbd/statvfs.c +++ b/source3/smbd/statvfs.c @@ -39,11 +39,13 @@ static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) statbuf->FreeFileNodes = statvfs_buf.f_ffree; statbuf->FsIdentifier = statvfs_buf.f_fsid; +#if defined(FILE_CASE_SENSITIVE_SEARCH) && defined(FILE_CASE_PRESERVING_NAMES) /* Good defaults for Linux filesystems are case sensitive * and case preserving. */ statbuf->FsCapabilities = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVING_NAMES; +#endif } return result; } -- cgit From 4c3c483fbfd870335f77ab610eb7230639d3d258 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 20 Dec 2007 08:31:27 -0800 Subject: Fix typo in filesystem capabilities bits. (This used to be commit 08fee0d28a20648d74c6b03d120eaf628f4de70c) --- source3/smbd/statvfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/statvfs.c b/source3/smbd/statvfs.c index 431489032c..0e9a2c2ebe 100644 --- a/source3/smbd/statvfs.c +++ b/source3/smbd/statvfs.c @@ -39,13 +39,11 @@ static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) statbuf->FreeFileNodes = statvfs_buf.f_ffree; statbuf->FsIdentifier = statvfs_buf.f_fsid; -#if defined(FILE_CASE_SENSITIVE_SEARCH) && defined(FILE_CASE_PRESERVING_NAMES) /* Good defaults for Linux filesystems are case sensitive * and case preserving. */ statbuf->FsCapabilities = - FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVING_NAMES; -#endif + FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; } return result; } -- cgit From cc48010f41684b5ef8c2e8a5511528cc426d300f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 20 Dec 2007 10:55:45 +0100 Subject: Add a global cache It hurts, but I think this global variable is necessary for transition, and it has the potential to remove quite a few other global variables without messing with APIs too much. (This used to be commit c131d0dc52ec09c9227eff3d68877369c37aaed5) --- source3/smbd/server.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 40037074f6..43a6d62a28 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1191,6 +1191,12 @@ extern void build_options(bool screen); if (smbd_messaging_context() == NULL) exit(1); + if (smbd_memcache() == NULL) { + exit(1); + } + + memcache_set_global(smbd_memcache()); + /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ -- cgit From dea7d2223d0d7e5db44cb8df7bf8d6b2ad1eb91f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 20 Dec 2007 20:59:44 +0100 Subject: Fix a C++ warning (This used to be commit 7e1d9b561f6df233b8c7eaec83d1e4207b5a2fb0) --- source3/smbd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 96d71da8d9..fefae38932 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -280,7 +280,7 @@ void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) { struct vfs_fsp_data *head; - head = vfs_memctx_fsp_extension(handle, fsp); + head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp); if (head != NULL) { return EXT_DATA_AREA(head); } -- cgit From addf598cde41d17ad4cf497a64b9a2b27e4028c5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 20 Dec 2007 22:17:16 +0100 Subject: Some C++ warnings (This used to be commit 5ab82d4f574f2a2e2761e9e414c66a70aeffb05d) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 45081808e1..575ca13ff6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1163,8 +1163,8 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req) total_space = dsize * (double)bsize; free_space = dfree * (double)bsize; - dsize = (total_space+63*512) / (64*512); - dfree = (free_space+63*512) / (64*512); + dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512)); + dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512)); if (dsize > 0xFFFF) dsize = 0xFFFF; if (dfree > 0xFFFF) dfree = 0xFFFF; -- cgit From 99b86e4a266b99634f6a65015f6df115c421d3e5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 20 Dec 2007 22:27:01 +0100 Subject: Some C++ fixes (This used to be commit 5c392c4c6e277a24d0d477902dc7856b2b46ee53) --- source3/smbd/posix_acls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d8794e2114..2810b5e587 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -891,7 +891,7 @@ static bool nt4_compatible_acls(void) ****************************************************************************/ static SEC_ACCESS map_canon_ace_perms(int snum, - int *pacl_type, + enum security_ace_type *pacl_type, mode_t perms, bool directory_ace) { @@ -2869,7 +2869,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, { canon_ace *ace; - int nt_acl_type; + enum security_ace_type nt_acl_type; int i; if (nt4_compatible_acls() && dir_ace) { @@ -3210,7 +3210,7 @@ static NTSTATUS append_ugw_ace(files_struct *fsp, { mode_t perms; SEC_ACCESS acc; - int nt_acl_type; + enum security_ace_type nt_acl_type; DOM_SID trustee; switch (ugw) { -- cgit From 4773973300d9b4c6d46bdeefd57d200378f6cec3 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 22 Dec 2007 01:49:29 +0100 Subject: Remove redundant connection_struct from fd_close_posix() parameter list. Michael (This used to be commit f3365b74ac016eaee1e82eef769dd618af5df201) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b83d6844d6..743f040911 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -78,7 +78,7 @@ NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp) if (fsp->fh->ref_count > 1) { return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } - return fd_close_posix(conn, fsp); + return fd_close_posix(fsp); } /**************************************************************************** -- cgit From e47520f2221ea34a2264a3cc03fe1c5fcc5bf5c5 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 22 Dec 2007 02:01:26 +0100 Subject: Remove redundant connection_struct from fd_close() parameter list. Michael (This used to be commit 3611cc8561cf837adea83fc7c16ca7535f188466) --- source3/smbd/close.c | 2 +- source3/smbd/open.c | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index eb610f7d1a..ff96c99712 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -389,7 +389,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ locking_close_file(smbd_messaging_context(), fsp); - status = fd_close(conn, fsp); + status = fd_close(fsp); /* check for magic scripts */ if (close_type == NORMAL_CLOSE) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 743f040911..9428b47b6a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -70,7 +70,7 @@ static NTSTATUS fd_open(struct connection_struct *conn, Close the file associated with a fsp. ****************************************************************************/ -NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp) +NTSTATUS fd_close(files_struct *fsp) { if (fsp->fh->fd == -1) { return NT_STATUS_OK; /* What we used to call a stat open. */ @@ -353,7 +353,7 @@ static NTSTATUS open_file(files_struct *fsp, /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { status = map_nt_error_from_unix(errno); - fd_close(conn, fsp); + fd_close(fsp); return status; } } @@ -365,7 +365,7 @@ static NTSTATUS open_file(files_struct *fsp, */ if(S_ISDIR(psbuf->st_mode)) { - fd_close(conn, fsp); + fd_close(fsp); errno = EISDIR; return NT_STATUS_FILE_IS_A_DIRECTORY; } @@ -1688,7 +1688,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share " "mode lock for %s\n", fname)); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1699,7 +1699,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, oplock_request)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1718,7 +1718,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, oplock_request)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1727,7 +1727,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); state.delayed_for_oplocks = False; @@ -1768,7 +1768,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if(ret_flock == -1 ){ TALLOC_FREE(lck); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1793,7 +1793,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); - fd_close(conn,fsp); + fd_close(fsp); file_free(fsp); return status; } @@ -1850,7 +1850,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); TALLOC_FREE(lck); - fd_close(conn,fsp); + fd_close(fsp); file_free(fsp); return status; } @@ -1974,7 +1974,7 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, NTSTATUS close_file_fchmod(files_struct *fsp) { - NTSTATUS status = fd_close(fsp->conn, fsp); + NTSTATUS status = fd_close(fsp); file_free(fsp); return status; } -- cgit From a000fa4ee5491ae32c60881b28b3536e88e82e27 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 22 Dec 2007 02:13:02 +0100 Subject: Remove redundant connection_struct from check_magic() parameter list. Michael (This used to be commit cebaa483e62910ac3f87cd135b2aff18dc880416) --- source3/smbd/close.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index ff96c99712..5d30e467d0 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -27,7 +27,7 @@ extern struct current_user current_user; Run a file if it is a magic script. ****************************************************************************/ -static void check_magic(files_struct *fsp,connection_struct *conn) +static void check_magic(struct files_struct *fsp) { int ret; const char *magic_output = NULL; @@ -35,6 +35,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn) int tmp_fd, outfd; TALLOC_CTX *ctx = NULL; const char *p; + struct connection_struct *conn = fsp->conn; if (!*lp_magicscript(SNUM(conn))) { return; @@ -393,7 +394,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ /* check for magic scripts */ if (close_type == NORMAL_CLOSE) { - check_magic(fsp,conn); + check_magic(fsp); } /* -- cgit From 1176e04c76e28d9ee9ab355c5e9edcd1b627ac03 Mon Sep 17 00:00:00 2001 From: James Peach Date: Sat, 22 Dec 2007 14:01:25 -0800 Subject: Cache the underlying filesystem capabilities at connection time. This change alters the Samba connection code to cache the filesystem capabilities when a new client connects. This can be used to enable filesystem specific optimisations is a general manner. (This used to be commit de3c5b808a941ac8e9ebe7169536d8290067eef5) --- source3/smbd/service.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ed43528c76..8e69a3b381 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1165,6 +1165,21 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #endif + /* Figure out the characteristics of the underlying filesystem. This + * assumes that all the filesystem mounted withing a share path have + * the same characteristics, which is likely but not guaranteed. + */ + { + vfs_statvfs_struct svfs; + + conn->fs_capabilities = + FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; + + if (SMB_VFS_STATVFS(conn, conn->connectpath, &svfs) == 0) { + conn->fs_capabilities = svfs.FsCapabilities; + } + } + /* * Print out the 'connected as' stuff here as we need * to know the effective uid and gid we will be using -- cgit From 596018455af0d80add90215689a80d336157429c Mon Sep 17 00:00:00 2001 From: James Peach Date: Sat, 22 Dec 2007 14:55:37 -0800 Subject: Use filesystem capabilities to support case-insensitive filesystems. If we know the underlying filesystem is case-insensitive, then we know that it won't help to search for case variations of the requested name. Jeremy, please review (and revert if you disagree). (This used to be commit 9e8b8f8c16612d8a08b55802f4fd9afca5498a7c) --- source3/smbd/dir.c | 38 +++++++++++++++++++++----------------- source3/smbd/filename.c | 9 +++++++++ 2 files changed, 30 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 05679ee0ee..ccf91fe57d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -646,10 +646,13 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx, TALLOC_FREE(pathreal); - /* In case sensitive mode we don't search - we know if it doesn't exist - with a stat we will fail. */ + /* Stat failed. We know this is authoratiative if we are + * providing case sensitive semantics or the underlying + * filesystem is case sensitive. + */ - if (dptr->conn->case_sensitive) { + if (dptr->conn->case_sensitive || + !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) { /* We need to set the underlying dir_hnd offset to -1 also as this function is usually called with the output from TellDir. */ dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET; @@ -924,12 +927,7 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return True; } - /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) { - DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n", - name, strerror(errno) )); - return False; - } + SMB_ASSERT(VALID_STAT(*pst)); /* Pseudo-open the file (note - no fd's created). */ @@ -987,10 +985,7 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return True; } - /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) { - return False; - } + SMB_ASSERT(VALID_STAT(*pst)); /* Pseudo-open the file */ @@ -1039,9 +1034,7 @@ static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT if (conn->admin_user) return False; - /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) - return True; + SMB_ASSERT(VALID_STAT(*pst)); if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) return False; @@ -1050,7 +1043,9 @@ static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT } /******************************************************************* - Should the file be seen by the client ? + Should the file be seen by the client ? NOTE: A successful return + is no guarantee of the file's existence ... you also have to check + whether pst is valid. ********************************************************************/ bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto) @@ -1086,6 +1081,15 @@ bool is_visible_file(connection_struct *conn, const char *dir_path, const char * return True; } + /* If the file name does not exist, there's no point checking + * the configuration options. We succeed, on the basis that the + * checks *might* have passed if the file was present. + */ + if (SMB_VFS_STAT(conn, entry, pst) != 0) { + SAFE_FREE(entry); + return True; + } + /* Honour _hide unreadable_ option */ if (hide_unreadable && !user_can_read_file(conn, entry, pst)) { DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry )); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index dc733d4568..f0d036b82b 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -735,6 +735,15 @@ static bool scan_directory(connection_struct *conn, const char *path, path = "."; } + /* If we have a case-sensitive filesystem, it doesn't do us any + * good to search for a name. If a case variation of the name was + * there, then the original stat(2) would have found it. + */ + if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) { + errno = ENOENT; + return False; + } + /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) -- cgit From f980d3ea14c020869102d8cd90fb69ecc2f78416 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Dec 2007 17:38:18 -0800 Subject: If we detect a case insensitive filesystem make sure we don't search directories on name misses for non-mangled names. Jeremy (This used to be commit 120048d2f40cf1a0ace2ecde205cbc694d263d69) --- source3/smbd/filename.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index f0d036b82b..5ae193fb46 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -222,8 +222,14 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, start = name; - if(!conn->case_sensitive - && stat_cache_lookup(conn, &name, &dirpath, &start, &st)) { + /* If we're providing case insentive semantics or + * the underlying filesystem is case insensitive, + * then a case-normalized hit in the stat-cache is + * authoratitive. JRA. + */ + + if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) && + stat_cache_lookup(conn, &name, &dirpath, &start, &st)) { *pst = st; goto done; } @@ -269,10 +275,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, /* * A special case - if we don't have any mangling chars and are case - * sensitive then searching won't help. + * sensitive or the underlying filesystem is case insentive then searching + * won't help. */ - if (conn->case_sensitive && + if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) && !mangle_is_mangled(name, conn->params)) { goto done; } -- cgit From 250c57ccfbae343e8d713c768d0288f73a0a5013 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 26 Dec 2007 14:18:11 +0100 Subject: We need to return the correct atime On systems with nanosecond atime we need to re-stat after messing with the fd, at least Solaris 10 updates atime after we stat(2)ed the file. (This used to be commit 6e6ec0a563f8b7e3d4618ce60e776bcce53f40c4) --- source3/smbd/open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9428b47b6a..f30808b30a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2667,7 +2667,12 @@ NTSTATUS create_file_unixpath(connection_struct *conn, *pinfo = info; } if (psbuf != NULL) { - *psbuf = sbuf; + if ((fsp->fh == NULL) || (fsp->fh->fd == -1)) { + *psbuf = sbuf; + } + else { + SMB_VFS_FSTAT(fsp, fsp->fh->fd, psbuf); + } } return NT_STATUS_OK; -- cgit From afc93255d183eefb68e45b8ec6275f6a62cf9795 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Dec 2007 17:12:36 -0800 Subject: Add SMB encryption. Still fixing client decrypt but negotiation works. Jeremy. (This used to be commit d78045601af787731f0737b8627450018902b104) --- source3/smbd/aio.c | 17 +- source3/smbd/error.c | 71 ++--- source3/smbd/notify.c | 3 +- source3/smbd/oplock.c | 6 +- source3/smbd/pipes.c | 3 +- source3/smbd/process.c | 56 +++- source3/smbd/reply.c | 35 ++- source3/smbd/seal.c | 703 +++++++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/trans2.c | 49 ++++ 9 files changed, 869 insertions(+), 74 deletions(-) create mode 100644 source3/smbd/seal.c (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 994b10d6a8..f13393b764 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -236,7 +236,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - set_message(aio_ex->outbuf, 12, 0, True); + srv_set_message((const char *)req->inbuf, aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -387,6 +387,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; + const char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -407,10 +408,11 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) "Error = %s\n", aio_ex->fsp->fsp_name, strerror(errno) )); - outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; + ERROR_NT(map_nt_error_from_unix(ret)); + outsize = srv_set_message(inbuf,outbuf,0,0,true); } else { - outsize = set_message(outbuf,12,nread,False); + outsize = srv_set_message(inbuf, outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -423,7 +425,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(outbuf,outsize - 4); + _smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -448,6 +450,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; + const char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); @@ -492,8 +495,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) return 0; } - UNIXERROR(ERRHRD,ERRdiskfull); ret = errno; + ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + srv_set_message(inbuf,outbuf,0,0,true); } else { bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); NTSTATUS status; @@ -509,8 +513,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) fsp->fnum, (int)numtowrite, (int)nwritten)); status = sync_file(fsp->conn,fsp, write_through); if (!NT_STATUS_IS_OK(status)) { - UNIXERROR(ERRHRD,ERRdiskfull); ret = errno; + ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + srv_set_message(inbuf,outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); } diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 12eff42023..c669e74146 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -24,34 +24,6 @@ extern struct unix_error_map unix_dos_nt_errmap[]; extern uint32 global_client_caps; -/**************************************************************************** - Create an error packet from errno. -****************************************************************************/ - -int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) -{ - int eclass=def_class; - int ecode=def_code; - NTSTATUS ntstatus = def_status; - int i=0; - - if (errno != 0) { - DEBUG(3,("unix_error_packet: error string = %s\n",strerror(errno))); - - while (unix_dos_nt_errmap[i].dos_class != 0) { - if (unix_dos_nt_errmap[i].unix_error == errno) { - eclass = unix_dos_nt_errmap[i].dos_class; - ecode = unix_dos_nt_errmap[i].dos_code; - ntstatus = unix_dos_nt_errmap[i].nt_error; - break; - } - i++; - } - } - - return error_packet(outbuf,eclass,ecode,ntstatus,line,file); -} - bool use_nt_status(void) { return lp_nt_status_support() && (global_client_caps & CAP_STATUS32); @@ -109,9 +81,9 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu } } -int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { - int outsize = set_message(outbuf,0,0,True); + int outsize = srv_set_message(inbuf, outbuf,0,0,True); error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } @@ -150,8 +122,24 @@ void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode, line, file); } +void reply_openerror(struct smb_request *req, NTSTATUS status) +{ + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + /* + * We hit an existing file, and if we're returning DOS + * error codes OBJECT_NAME_COLLISION would map to + * ERRDOS/183, we need to return ERRDOS/80, see bug + * 4852. + */ + reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERRfilexists); + } else { + reply_nterror(req, status); + } +} + void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode, - NTSTATUS defstatus, int line, const char *file) + NTSTATUS defstatus, int line, const char *file) { int eclass=defclass; int ecode=defcode; @@ -163,7 +151,7 @@ void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode, if (errno != 0) { DEBUG(3,("unix_error_packet: error string = %s\n", - strerror(errno))); + strerror(errno))); while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { @@ -177,22 +165,5 @@ void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode, } error_packet_set((char *)req->outbuf, eclass, ecode, ntstatus, - line, file); + line, file); } - -void reply_openerror(struct smb_request *req, NTSTATUS status) -{ - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - /* - * We hit an existing file, and if we're returning DOS - * error codes OBJECT_NAME_COLLISION would map to - * ERRDOS/183, we need to return ERRDOS/80, see bug - * 4852. - */ - reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION, - ERRDOS, ERRfilexists); - } else { - reply_nterror(req, status); - } -} - diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 0dd7fbb20e..baab48f77e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -131,6 +131,7 @@ static bool notify_marshall_changes(int num_changes, static void change_notify_reply_packet(const uint8 *request_buf, NTSTATUS error_code) { + const char *inbuf = (const char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); @@ -142,7 +143,7 @@ static void change_notify_reply_packet(const uint8 *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - set_message(outbuf,18,0,False); + srv_set_message((const char *)request_buf, outbuf,18,0,False); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 961abd277b..2c3313606a 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -252,7 +252,11 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx, } memset(result,'\0',smb_size); - set_message(result,8,0,True); + /* We use cli_set_message here as this is an + * asynchronous message that doesn't belong in + * the stream. + */ + cli_set_message(result,8,0,True); SCVAL(result,smb_com,SMBlockingX); SSVAL(result,smb_tid,fsp->conn->cnum); SSVAL(result,smb_pid,0xFFFF); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 0ddc00c767..88b67c03e5 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -291,7 +291,8 @@ void reply_pipe_read_and_X(struct smb_request *req) return; } - set_message((char *)req->outbuf, 12, nread, False); + srv_set_message((const char *)req->inbuf, + (char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ee76f90bf5..1260d52c77 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -50,6 +50,43 @@ enum smb_read_errors *get_srv_read_error(void) return &smb_read_error; } +/******************************************************************* + Setup the word count and byte count for a smb message. + copying the '0xFF X X X' bytes from incoming + buffer (so we copy any encryption context). +********************************************************************/ + +int srv_set_message(const char *frombuf, + char *buf, + int num_words, + int num_bytes, + bool zero) +{ + if (zero && (num_words || num_bytes)) { + memset(buf + smb_size,'\0',num_words*2 + num_bytes); + } + SCVAL(buf,smb_wct,num_words); + SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); + _smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4)); + if (buf != frombuf) { + memcpy(buf+4, frombuf+4, 4); + } + return (smb_size + num_words*2 + num_bytes); +} + +static bool valid_smb_header(const char *inbuf) +{ + if (srv_encryption_on()) { + uint16_t enc_num; + NTSTATUS status = get_enc_ctx_num(inbuf, &enc_num); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + return (enc_num == 0); + } + return (strncmp(smb_base(inbuf),"\377SMB",4) == 0); +} + /* Socket functions for smbd packet processing. */ static bool valid_packet_size(size_t len) @@ -324,6 +361,18 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, return -1; } + if (srv_encryption_on()) { + NTSTATUS status = srv_decrypt_buffer(*buffer); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("receive_smb_talloc: SMB decryption failed on " + "incoming packet! Error %s\n", + nt_errstr(status) )); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_BAD_DECRYPT); + return -1; + } + } + /* Check the incoming SMB signature. */ if (!srv_check_sign_mac(*buffer, true)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " @@ -1239,7 +1288,8 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) } construct_reply_common((char *)req->inbuf, (char *)req->outbuf); - set_message((char *)req->outbuf, num_words, num_bytes, False); + srv_set_message((const char *)req->inbuf, + (char *)req->outbuf, num_words, num_bytes, false); /* * Zero out the word area, the caller has to take care of the bcc area * himself @@ -1309,7 +1359,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size) /* Make sure this is an SMB packet. smb_size contains NetBIOS header * so subtract 4 from it. */ - if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0) + if (!valid_smb_header((const char *)req->inbuf) || (size < (smb_size - 4))) { DEBUG(2,("Non-SMB packet of length %d. Terminating server\n", smb_len(req->inbuf))); @@ -1551,7 +1601,7 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(const char *inbuf, char *outbuf) { - set_message(outbuf,0,0,False); + srv_set_message(inbuf,outbuf,0,0,false); SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); SIVAL(outbuf,smb_rcls,0); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 575ca13ff6..2707aee9c8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2791,8 +2791,8 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBreadbraw); - if (srv_is_signing_active()) { - exit_server_cleanly("reply_readbraw: SMB signing is active - " + if (srv_is_signing_active() || srv_encryption_on()) { + exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - " "raw reads/writes are disallowed."); } @@ -3017,7 +3017,8 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - set_message((char *)req->outbuf, 5, nread+3, False); + srv_set_message((const char *)req->inbuf, + (char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3104,7 +3105,8 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - set_message((char *)req->outbuf, 5, nread+3, False); + srv_set_message((const char *)req->inbuf, + (char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3122,12 +3124,12 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Setup readX header. ****************************************************************************/ -static int setup_readX_header(char *outbuf, size_t smb_maxcnt) +static int setup_readX_header(const char *inbuf, char *outbuf, size_t smb_maxcnt) { int outsize; char *data; - outsize = set_message(outbuf,12,smb_maxcnt,False); + outsize = srv_set_message(inbuf, outbuf,12,smb_maxcnt,False); data = smb_buf(outbuf); memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */ @@ -3190,7 +3192,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, header = data_blob_const(headerbuf, sizeof(headerbuf)); construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header((char *)headerbuf, smb_maxcnt); + setup_readX_header((const char *)req->inbuf, + (char *)headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ @@ -3241,7 +3244,8 @@ normal_read: uint8 headerbuf[smb_size + 2*12]; construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header((char *)headerbuf, smb_maxcnt); + setup_readX_header((const char *)req->inbuf, + (char *)headerbuf, smb_maxcnt); /* Send out the header. */ if (write_data(smbd_server_fd(), (char *)headerbuf, @@ -3268,7 +3272,8 @@ normal_read: return; } - setup_readX_header((char *)req->outbuf, nread); + setup_readX_header((const char *)req->inbuf, + (char *)req->outbuf, nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); @@ -3332,8 +3337,8 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBreadX); return; } - /* We currently don't do this on signed data. */ - if (srv_is_signing_active()) { + /* We currently don't do this on signed or sealed data. */ + if (srv_is_signing_active() || srv_encryption_on()) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBreadX); return; @@ -3524,7 +3529,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) * it to send more bytes */ memcpy(buf, req->inbuf, smb_size); - outsize = set_message(buf, + outsize = srv_set_message((const char *)req->inbuf, buf, Protocol>PROTOCOL_COREPLUS?1:0,0,True); SCVAL(buf,smb_com,SMBwritebraw); SSVALS(buf,smb_vwv0,0xFFFF); @@ -3856,6 +3861,12 @@ bool is_valid_writeX_buffer(const char *inbuf) unsigned int doff = 0; size_t len = smb_len_large(inbuf); + if (srv_encryption_on()) { + /* Can't do this on encrypted + * connections. */ + return false; + } + if (CVAL(inbuf,smb_com) != SMBwriteX) { return false; } diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c new file mode 100644 index 0000000000..14a427bb9c --- /dev/null +++ b/source3/smbd/seal.c @@ -0,0 +1,703 @@ +/* + Unix SMB/CIFS implementation. + SMB Transport encryption (sealing) code - server code. + Copyright (C) Jeremy Allison 2007. + + 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 3 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, see . +*/ + +#include "includes.h" + +/****************************************************************************** + Server side encryption. +******************************************************************************/ + +/****************************************************************************** + Global server state. +******************************************************************************/ + +struct smb_srv_trans_enc_ctx { + struct smb_trans_enc_state *es; + AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ +}; + +static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; +static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; + +/****************************************************************************** + Is server encryption on ? +******************************************************************************/ + +bool srv_encryption_on(void) +{ + if (srv_trans_enc_ctx) { + return common_encryption_on(srv_trans_enc_ctx->es); + } + return false; +} + +/****************************************************************************** + Create an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; + return status; +} + +/****************************************************************************** + Destroy an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + + if (ec->auth_ntlmssp_state) { + auth_ntlmssp_end(&ec->auth_ntlmssp_state); + /* The auth_ntlmssp_end killed this already. */ + ec->es->s.ntlmssp_state = NULL; + } +} + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + +/****************************************************************************** + Import a name. +******************************************************************************/ + +static NTSTATUS get_srv_gss_creds(const char *service, + const char *name, + gss_cred_usage_t cred_type, + gss_cred_id_t *p_srv_cred) +{ + OM_uint32 ret; + OM_uint32 min; + gss_name_t srv_name; + gss_buffer_desc input_name; + char *host_princ_s = NULL; + NTSTATUS status = NT_STATUS_OK; + + gss_OID_desc nt_hostbased_service = + {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; + + asprintf(&host_princ_s, "%s@%s", service, name); + if (host_princ_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + input_name.value = host_princ_s; + input_name.length = strlen(host_princ_s) + 1; + + ret = gss_import_name(&min, + &input_name, + &nt_hostbased_service, + &srv_name); + + DEBUG(10,("get_srv_gss_creds: imported name %s\n", + host_princ_s )); + + if (ret != GSS_S_COMPLETE) { + SAFE_FREE(host_princ_s); + return map_nt_error_from_gss(ret, min); + } + + /* + * We're accessing the krb5.keytab file here. + * ensure we have permissions to do so. + */ + become_root(); + + ret = gss_acquire_cred(&min, + srv_name, + GSS_C_INDEFINITE, + GSS_C_NULL_OID_SET, + cred_type, + p_srv_cred, + NULL, + NULL); + unbecome_root(); + + if (ret != GSS_S_COMPLETE) { + ADS_STATUS adss = ADS_ERROR_GSS(ret, min); + DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", + ads_errstr(adss))); + status = map_nt_error_from_gss(ret, min); + } + + SAFE_FREE(host_princ_s); + gss_release_name(&min, &srv_name); + return status; +} + +/****************************************************************************** + Create a gss state. + Try and get the cifs/server@realm principal first, then fall back to + host/server@realm. +******************************************************************************/ + +static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status; + gss_cred_id_t srv_cred; + fstring fqdn; + + name_to_fqdn(fqdn, global_myname()); + strlower_m(fqdn); + + status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + } + + ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); + if (!ec->es->s.gss_state) { + OM_uint32 min; + gss_release_cred(&min, &srv_cred); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(ec->es->s.gss_state); + ec->es->s.gss_state->creds = srv_cred; + + /* No context yet. */ + ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; + + return NT_STATUS_OK; +} +#endif + +/****************************************************************************** + Shutdown a server encryption context. +******************************************************************************/ + +static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) +{ + struct smb_srv_trans_enc_ctx *ec = *pp_ec; + + if (!ec) { + return; + } + + if (ec->es) { + switch (ec->es->smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + destroy_auth_ntlmssp(ec); + break; +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + break; +#endif + } + common_free_encryption_state(&ec->es); + } + + SAFE_FREE(ec); + *pp_ec = NULL; +} + +/****************************************************************************** + Create a server encryption context. +******************************************************************************/ + +static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) +{ + struct smb_srv_trans_enc_ctx *ec; + + *pp_ec = NULL; + + ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); + if (!ec) { + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(partial_srv_trans_enc_ctx); + ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); + if (!ec->es) { + SAFE_FREE(ec); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(ec->es); + ec->es->smb_enc_type = smb_enc_type; + switch (smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + { + NTSTATUS status = make_auth_ntlmssp(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return status; + } + } + break; + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + /* Acquire our credentials by calling gss_acquire_cred here. */ + { + NTSTATUS status = make_auth_gss(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return status; + } + } + break; +#endif + default: + srv_free_encryption_context(&ec); + return NT_STATUS_INVALID_PARAMETER; + } + *pp_ec = ec; + return NT_STATUS_OK; +} + +/****************************************************************************** + Free an encryption-allocated buffer. +******************************************************************************/ + +void srv_free_enc_buffer(char *buf) +{ + /* We know this is an smb buffer, and we + * didn't malloc, only copy, for a keepalive, + * so ignore session keepalives. */ + + if(CVAL(buf,0) == SMBkeepalive) { + return; + } + + if (srv_trans_enc_ctx) { + common_free_enc_buffer(srv_trans_enc_ctx->es, buf); + } +} + +/****************************************************************************** + Decrypt an incoming buffer. +******************************************************************************/ + +NTSTATUS srv_decrypt_buffer(char *buf) +{ + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + + if (srv_trans_enc_ctx) { + return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); + } + + return NT_STATUS_OK; +} + +/****************************************************************************** + Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. +******************************************************************************/ + +NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) +{ + *buf_out = buf; + + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + + if (srv_trans_enc_ctx) { + return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); + } + /* Not encrypting. */ + return NT_STATUS_OK; +} + +/****************************************************************************** + Do the gss encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) +static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +{ + OM_uint32 ret; + OM_uint32 min; + OM_uint32 flags = 0; + gss_buffer_desc in_buf, out_buf; + struct smb_tran_enc_state_gss *gss_state; + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; + NTSTATUS status; + + if (!partial_srv_trans_enc_ctx) { + status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; + + in_buf.value = secblob.data; + in_buf.length = secblob.length; + + out_buf.value = NULL; + out_buf.length = 0; + + become_root(); + + ret = gss_accept_sec_context(&min, + &gss_state->gss_ctx, + gss_state->creds, + &in_buf, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, /* Ignore oids. */ + &out_buf, /* To return. */ + &flags, + NULL, /* Ingore time. */ + NULL); /* Ignore delegated creds. */ + unbecome_root(); + + status = gss_err_to_ntstatus(ret, min); + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + return status; + } + + /* Ensure we've got sign+seal available. */ + if (ret == GSS_S_COMPLETE) { + if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != + (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { + DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " + "for SMB sealing.\n")); + gss_release_buffer(&min, &out_buf); + return NT_STATUS_ACCESS_DENIED; + } + } + + auth_reply = data_blob(out_buf.value, out_buf.length); + gss_release_buffer(&min, &out_buf); + + /* Wrap in SPNEGO. */ + response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); + data_blob_free(&auth_reply); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + + return status; +} +#endif + +/****************************************************************************** + Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, bool spnego_wrap) +{ + NTSTATUS status; + DATA_BLOB chal = data_blob_null; + DATA_BLOB response = data_blob_null; + + status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); + + /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED + * for success ... */ + + if (spnego_wrap) { + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + } else { + /* Return the raw blob. */ + response = chal; + } + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. + Based off code in smbd/sesssionsetup.c + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_null; + DATA_BLOB secblob = data_blob_null; + bool got_kerberos_mechanism = false; + + blob = data_blob_const(*ppdata, *p_data_size); + + status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* We should have no partial context at this point. */ + + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { + status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); + } else +#endif + { + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true); + } + + data_blob_free(&secblob); + + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); + *p_param_size = 2; + } + + return status; +} + +/****************************************************************************** + Complete a SPNEGO encryption negotiation. Parameters are in/out. + We only get this for a NTLM auth second stage. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_null; + DATA_BLOB auth = data_blob_null; + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; + struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; + + /* We must have a partial context here. */ + + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + blob = data_blob_const(*ppdata, *p_data_size); + if (!spnego_parse_auth(blob, &auth)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); + data_blob_free(&auth); + + response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); + data_blob_free(&auth_reply); + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + +/****************************************************************************** + Raw NTLM encryption negotiation. Parameters are in/out. + This function does both steps. +******************************************************************************/ + +static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); + DATA_BLOB response = data_blob_null; + struct smb_srv_trans_enc_ctx *ec; + + if (!partial_srv_trans_enc_ctx) { + /* This is the initial step. */ + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, false); + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + return status; + } + + ec = partial_srv_trans_enc_ctx; + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + /* Second step. */ + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + + /* Return the raw blob. */ + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. +******************************************************************************/ + +NTSTATUS srv_request_encryption_setup(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + unsigned char *pdata = *ppdata; + + SAFE_FREE(*pparam); + *p_param_size = 0; + + if (*p_data_size < 1) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (pdata[0] == ASN1_APPLICATION(0)) { + /* its a negTokenTarg packet */ + return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); + } + + if (pdata[0] == ASN1_CONTEXT(1)) { + /* It's an auth packet */ + return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); + } + + /* Maybe it's a raw unwrapped auth ? */ + if (*p_data_size < 7) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { + return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); + } + + DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); + + return NT_STATUS_LOGON_FAILURE; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) +{ + if (!ec || !ec->es) { + return NT_STATUS_LOGON_FAILURE; + } + + if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { + if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != + (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { + return NT_STATUS_INVALID_PARAMETER; + } + } + /* Todo - check gssapi case. */ + + return NT_STATUS_OK; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +NTSTATUS srv_encryption_start(connection_struct *conn) +{ + NTSTATUS status; + + /* Check that we are really doing sign+seal. */ + status = check_enc_good(partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Throw away the context we're using currently (if any). */ + srv_free_encryption_context(&srv_trans_enc_ctx); + + /* Steal the partial pointer. Deliberate shallow copy. */ + srv_trans_enc_ctx = partial_srv_trans_enc_ctx; + srv_trans_enc_ctx->es->enc_on = true; + + partial_srv_trans_enc_ctx = NULL; + return NT_STATUS_OK; +} + +/****************************************************************************** + Shutdown all server contexts. +******************************************************************************/ + +void server_encryption_shutdown(void) +{ + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + srv_free_encryption_context(&srv_trans_enc_ctx); +} diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e37f6ffbfd..0e34284443 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2998,6 +2998,55 @@ cap_low = 0x%x, cap_high = 0x%x\n", } break; } + + case SMB_REQUEST_TRANSPORT_ENCRYPTION: + { + NTSTATUS status; + size_t param_len = 0; + size_t data_len = total_data; + + if (!lp_unix_extensions()) { + reply_nterror( + req, + NT_STATUS_INVALID_LEVEL); + return; + } + + DEBUG( 4,("call_trans2setfsinfo: " + "request transport encrption.\n")); + + status = srv_request_encryption_setup(conn, + (unsigned char **)ppdata, + &data_len, + (unsigned char **)pparams, + ¶m_len); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && + !NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + send_trans2_replies(req, + *pparams, + param_len, + *ppdata, + data_len, + max_data_bytes); + + if (NT_STATUS_IS_OK(status)) { + /* Server-side transport + * encryption is now *on*. */ + status = srv_encryption_start(conn); + if (!NT_STATUS_IS_OK(status)) { + exit_server_cleanly( + "Failure in setting " + "up encrypted transport"); + } + } + return; + } + case SMB_FS_QUOTA_INFORMATION: { files_struct *fsp = NULL; -- cgit From 5413ad4aca69245c575b621db33b61eae5db4a35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Dec 2007 10:18:22 -0800 Subject: Add CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP capability to our reported caps. Jeremy. (This used to be commit e86d027823c85173c64e7b85406e98f6f7345b10) --- source3/smbd/trans2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0e34284443..5a8fe41d27 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2737,7 +2737,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned data_len = 12; SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); - /* We have POSIX ACLs, pathname and locking capability. */ + + /* We have POSIX ACLs, pathname, encryption, + * large read/write, and locking capability. */ + SBIG_UINT(pdata,4,((SMB_BIG_UINT)( CIFS_UNIX_POSIX_ACLS_CAP| CIFS_UNIX_POSIX_PATHNAMES_CAP| @@ -2745,6 +2748,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| CIFS_UNIX_LARGE_READ_CAP| + CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP| (large_write ? CIFS_UNIX_LARGE_WRITE_CAP : 0)))); break; -- cgit From bd7fc51f2d26ba238b68db83106883bfa1fe1d7b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 27 Dec 2007 19:56:44 +0100 Subject: Fix the build (This used to be commit 7fb858b350856d626fed6f062029fcf09b8251e2) --- source3/smbd/aio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index f13393b764..a439c3a4f0 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -496,7 +496,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) } ret = errno; - ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); srv_set_message(inbuf,outbuf,0,0,true); } else { bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); @@ -514,7 +514,8 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) status = sync_file(fsp->conn,fsp, write_through); if (!NT_STATUS_IS_OK(status)) { ret = errno; - ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + ERROR_BOTH(map_nt_error_from_unix(ret), + ERRHRD, ERRdiskfull); srv_set_message(inbuf,outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); -- cgit From 675f41dc144fc0c150b44d931a9242f1ac1ebe5f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Dec 2007 16:54:07 -0800 Subject: Add "smb encrypt" parameter. Can be set to "no, yes, required". Currently if set required this is not enforced. I'll be adding that soon. Jeremy. (This used to be commit df7e447623ac03d81bec384f5cfe83c3976cf7b2) --- source3/smbd/trans2.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5a8fe41d27..ee4787199e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2729,11 +2729,27 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { bool large_write = lp_min_receive_file_size() && !srv_is_signing_active(); + int encrypt_caps = 0; if (!lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; } + + switch (lp_smb_encrypt(SNUM(conn))) { + case 0: + encrypt_caps = 0; + break; + case 1: + case Auto: + encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP; + break; + case Required: + encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP| + CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP; + break; + } + data_len = 12; SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); @@ -2748,7 +2764,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| CIFS_UNIX_LARGE_READ_CAP| - CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP| + encrypt_caps| (large_write ? CIFS_UNIX_LARGE_WRITE_CAP : 0)))); break; @@ -3016,6 +3032,13 @@ cap_low = 0x%x, cap_high = 0x%x\n", return; } + if (lp_smb_encrypt(SNUM(conn)) == false) { + reply_nterror( + req, + NT_STATUS_NOT_SUPPORTED); + return; + } + DEBUG( 4,("call_trans2setfsinfo: " "request transport encrption.\n")); -- cgit From 33f01360e0a40f6d1fa03035979d816ff9198d85 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 27 Dec 2007 21:31:08 +0100 Subject: Fix setting the initial permission bits This fixes a make test failure on Solaris. When creating a new file, file_set_dosmode() called from open_file_ntcreate calculates a new permission mask, very likely different from what had been calculated in open_file_ntcreate. Further down we overwrote the newly calculated value with SMB_FCHMOD_ACL, ignoring what file_set_dosmode had calculated. Why did Linux not see this? fchmod_acl on a newly created file without acls would not retrieve an acl at all, whereas under Solaris acl(2) returns something even for files with just posix permissions returns something. Jeremy, given that we have very similar code in 3.0.28 this might also explain some of the bug reports that people have concerning ACLs on new files. Volker P.S: This one took a while to find... (This used to be commit 2135dfe91bf1ae114a18c15286b535662200677d) --- source3/smbd/dosmode.c | 18 ++++++++++++++++-- source3/smbd/open.c | 13 +++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 8e3c9b4c91..a96f80ee0e 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -438,12 +438,19 @@ int file_set_dosmode(connection_struct *conn, const char *fname, dosmode &= SAMBA_ATTRIBUTES_MASK; DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname)); - if (!st || (st && !VALID_STAT(*st))) { + + if (st == NULL) { + SET_STAT_INVALID(st1); st = &st1; + } + + if (!VALID_STAT(*st)) { if (SMB_VFS_STAT(conn,fname,st)) return(-1); } + unixmode = st->st_mode; + get_acl_group_bits(conn, fname, &st->st_mode); if (S_ISDIR(st->st_mode)) @@ -451,8 +458,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname, else dosmode &= ~aDIR; - if (dos_mode(conn,fname,st) == dosmode) + if (dos_mode(conn,fname,st) == dosmode) { + st->st_mode = unixmode; return(0); + } /* Store the DOS attributes in an EA by preference. */ if (set_ea_dos_attribute(conn, fname, st, dosmode)) { @@ -460,6 +469,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } + st->st_mode = unixmode; return 0; } @@ -500,6 +510,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } + st->st_mode = unixmode; return 0; } @@ -534,6 +545,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname, notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } + if (ret == 0) { + st->st_mode = unixmode; + } } return( ret ); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f30808b30a..d3ba9e076c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1864,10 +1864,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if (!posix_open) { - file_set_dosmode(conn, fname, - new_dos_attributes | aARCH, NULL, - parent_dir, - true); + SMB_STRUCT_STAT tmp_sbuf; + SET_STAT_INVALID(tmp_sbuf); + if (file_set_dosmode( + conn, fname, + new_dos_attributes | aARCH, + &tmp_sbuf, parent_dir, + true) == 0) { + unx_mode = tmp_sbuf.st_mode; + } } } } -- cgit From afce2b245a8ff137a4ecea547c3cfb65ab58dc15 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Dec 2007 23:51:03 -0800 Subject: Add the capability to set "smb encrypt = required" on a share (or global) and have the server reply with ACCESS_DENIED for all non-encrypted traffic (except that used to query encryption requirements and set encryption state). Jeremy. (This used to be commit d241bfa57729bb934ada6beabf842a2ca7b4f8a2) --- source3/smbd/process.c | 10 ++++++++++ source3/smbd/service.c | 2 ++ source3/smbd/trans2.c | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1260d52c77..48a6d18bc9 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1457,6 +1457,16 @@ static void switch_message(uint8 type, struct smb_request *req, int size) reply_doserror(req, ERRSRV, ERRaccess); return; } + + if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { + /* An encrypted packet has 0xFF 'E' at offset 4 + * which is little endian 0x45FF */ + uint8 com = CVAL(req->inbuf,smb_com); + if (com != SMBtrans2 && com != SMBtranss2) { + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + } conn->num_smb_operations++; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8e69a3b381..65fc818144 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -795,6 +795,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->case_preserve = lp_preservecase(snum); conn->short_case_preserve = lp_shortpreservecase(snum); + conn->encrypt_level = lp_smb_encrypt(snum); + conn->veto_list = NULL; conn->hide_list = NULL; conn->veto_oplock_list = NULL; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ee4787199e..7625eaed7d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2430,6 +2430,16 @@ static void call_trans2qfsinfo(connection_struct *conn, info_level = SVAL(params,0); + if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { + if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { + DEBUG(0,("call_trans2qfsinfo: encryption required " + "and info level 0x%x sent.\n", + (unsigned int)info_level)); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + } + DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); if(SMB_VFS_STAT(conn,".",&st)!=0) { @@ -2736,7 +2746,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return; } - switch (lp_smb_encrypt(SNUM(conn))) { + switch (conn->encrypt_level) { case 0: encrypt_caps = 0; break; @@ -2968,6 +2978,16 @@ static void call_trans2setfsinfo(connection_struct *conn, info_level = SVAL(params,2); + if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { + if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) { + DEBUG(0,("call_trans2setfsinfo: encryption required " + "and info level 0x%x sent.\n", + (unsigned int)info_level)); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + } + switch(info_level) { case SMB_SET_CIFS_UNIX_INFO: { @@ -7060,6 +7080,17 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req, SSVAL(req->inbuf,smb_flg2,req->flags2); } + if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { + if (state->call != TRANSACT2_QFSINFO && + state->call != TRANSACT2_SETFSINFO) { + DEBUG(0,("handle_trans2: encryption required " + "with call 0x%x\n", + (unsigned int)state->call)); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + } + /* Now we must call the relevant TRANS2 function */ switch(state->call) { case TRANSACT2_OPEN: -- cgit From 38369ba74190259b437e9a875ac75a33d3ff3c24 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Dec 2007 00:02:13 -0800 Subject: Ensure we turn off POSIX large read/write if encryption is mandatory or signing is on. Jeremy. (This used to be commit 5088b704791be2f36641fa0ec59dff7f289ae868) --- source3/smbd/trans2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7625eaed7d..b1f57a9b3e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2739,6 +2739,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { bool large_write = lp_min_receive_file_size() && !srv_is_signing_active(); + bool large_read = !srv_is_signing_active(); int encrypt_caps = 0; if (!lp_unix_extensions()) { @@ -2757,6 +2758,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned case Required: encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP| CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP; + large_write = false; + large_read = false; break; } @@ -2773,8 +2776,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_FCNTL_LOCKS_CAP| CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| - CIFS_UNIX_LARGE_READ_CAP| encrypt_caps| + (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) | (large_write ? CIFS_UNIX_LARGE_WRITE_CAP : 0)))); break; -- cgit From 4cdce5b50e286aab457611d2c634cb79990795fd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 28 Dec 2007 17:02:07 +0100 Subject: Remove a static array This might be worth it, mangle_hash is hardly used these days (This used to be commit 44775ea38bc320ac8e2208769a8cde2c6f44f640) --- source3/smbd/mangle_hash.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index c369f6eda4..1dc9c67dcc 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -57,8 +57,7 @@ static char magic_char = '~'; static const char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; #define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1) -static unsigned char chartest[256] = { 0 }; -static bool ct_initialized = False; +static unsigned char *chartest; #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) #define BASECHAR_MASK 0xf0 @@ -334,13 +333,13 @@ static void init_chartest( void ) { const unsigned char *s; - memset( (char *)chartest, '\0', 256 ); + chartest = SMB_MALLOC_ARRAY(unsigned char, 256); + + SMB_ASSERT(chartest != NULL); for( s = (const unsigned char *)basechars; *s; s++ ) { chartest[*s] |= BASECHAR_MASK; } - - ct_initialized = True; } /* ************************************************************************** ** @@ -367,8 +366,9 @@ static bool is_mangled(const char *s, const struct share_params *p) magic_char = lp_magicchar(p); - if( !ct_initialized ) + if (chartest == NULL) { init_chartest(); + } magic = strchr_m( s, magic_char ); while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */ -- cgit From a60867b67e53d8a0f08de402e160478efc089a72 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 27 Dec 2007 20:00:13 +0100 Subject: Apply some const (This used to be commit 241b72141e3d9e31e30977517f871a97d74bbf7d) --- source3/smbd/vfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index fefae38932..ed0406211d 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -31,7 +31,7 @@ static_decl_vfs; struct vfs_init_function_entry { char *name; - vfs_op_tuple *vfs_op_tuples; + const vfs_op_tuple *vfs_op_tuples; struct vfs_init_function_entry *prev, *next; }; @@ -55,7 +55,7 @@ static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) return NULL; } -NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples) +NTSTATUS smb_register_vfs(int version, const char *name, const vfs_op_tuple *vfs_op_tuples) { struct vfs_init_function_entry *entry = backends; @@ -110,13 +110,13 @@ static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which, bool vfs_init_custom(connection_struct *conn, const char *vfs_object) { - vfs_op_tuple *ops; + const vfs_op_tuple *ops; char *module_path = NULL; char *module_name = NULL; char *module_param = NULL, *p; int i; vfs_handle_struct *handle; - struct vfs_init_function_entry *entry; + const struct vfs_init_function_entry *entry; if (!conn||!vfs_object||!vfs_object[0]) { DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n")); -- cgit From a59280792cab616f5b269960ab68bc44ccc1fd38 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 29 Dec 2007 22:16:31 +0100 Subject: Remove tiny code duplication sid_size did the same as ndr_size_dom_sid (This used to be commit 8aec5d09ba023413bd8ecbdfbc7d23904df94389) --- source3/smbd/nttrans.c | 3 ++- source3/smbd/trans2.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index cb98a8139c..eb29e65935 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2174,7 +2174,8 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, for (;((tmp_list!=NULL)&&((qt_len +40+SID_MAX_SIZE)next,entry+=entry_len,qt_len+=entry_len) { - sid_len = sid_size(&tmp_list->quotas->sid); + sid_len = ndr_size_dom_sid( + &tmp_list->quotas->sid, 0); entry_len = 40 + sid_len; /* nextoffset entry 4 bytes */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b1f57a9b3e..21bde12056 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2897,8 +2897,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned */ for (i = 0, sid_bytes = 0; i < current_user.nt_user_token->num_sids; ++i) { - sid_bytes += - sid_size(¤t_user.nt_user_token->user_sids[i]); + sid_bytes += ndr_size_dom_sid( + ¤t_user.nt_user_token->user_sids[i], 0); } /* SID list byte count */ @@ -2918,8 +2918,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned /* SID list */ for (i = 0; i < current_user.nt_user_token->num_sids; ++i) { - int sid_len = - sid_size(¤t_user.nt_user_token->user_sids[i]); + int sid_len = ndr_size_dom_sid( + ¤t_user.nt_user_token->user_sids[i], 0); sid_linearize(pdata + data_len, sid_len, ¤t_user.nt_user_token->user_sids[i]); -- cgit From 7cbdb48475b0340154fad60cb4b7cc53dc2bbcfd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 29 Dec 2007 23:00:49 +0100 Subject: Remove tiny code duplication ndr_size_security_descriptor does the same as sec_desc_size (This used to be commit bc3bd7a8e7c6e9e27acb195c86abb92c0f53112f) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index eb29e65935..69772b6bec 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1650,7 +1650,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, return; } - sd_size = sec_desc_size(psd); + sd_size = ndr_size_security_descriptor(psd, 0); DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); -- cgit From bd3521457ce9d899d42fdea32993a42c906070c7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 29 Dec 2007 22:36:49 -0800 Subject: Allow encryption context setup on IPC$. Jeremy. (This used to be commit 5d424cb3060af89bde50bc7fe2989e3c1b8e91b2) --- source3/smbd/trans2.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 21bde12056..656925502b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2430,7 +2430,8 @@ static void call_trans2qfsinfo(connection_struct *conn, info_level = SVAL(params,0); - if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { + if (IS_IPC(conn) || + (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF )) { if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { DEBUG(0,("call_trans2qfsinfo: encryption required " "and info level 0x%x sent.\n", @@ -2981,6 +2982,17 @@ static void call_trans2setfsinfo(connection_struct *conn, info_level = SVAL(params,2); + if (IS_IPC(conn)) { + if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION && + info_level != SMB_SET_CIFS_UNIX_INFO) { + DEBUG(0,("call_trans2setfsinfo: not an allowed " + "info level (0x%x) on IPC$.\n", + (unsigned int)info_level)); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + } + if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) { DEBUG(0,("call_trans2setfsinfo: encryption required " @@ -7276,12 +7288,20 @@ void reply_trans2(connection_struct *conn, struct smb_request *req) return; } - if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) - && (tran_call != TRANSACT2_GET_DFS_REFERRAL) - && (tran_call != TRANSACT2_QFILEINFO)) { - reply_doserror(req, ERRSRV, ERRaccess); - END_PROFILE(SMBtrans2); - return; + if (IS_IPC(conn)) { + switch (tran_call) { + /* List the allowed trans2 calls on IPC$ */ + case TRANSACT2_OPEN: + case TRANSACT2_GET_DFS_REFERRAL: + case TRANSACT2_QFILEINFO: + case TRANSACT2_QFSINFO: + case TRANSACT2_SETFSINFO: + break; + default: + reply_doserror(req, ERRSRV, ERRaccess); + END_PROFILE(SMBtrans2); + return; + } } if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { -- cgit From c6646f115ebca2fe8b05c898d3529832b3599056 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 30 Dec 2007 13:10:29 -0800 Subject: As the encryption is stream based there's no reason oplock breaks can't be encrypted. If we have multiple contexts I should probably attach them to the connection struct, but for now use the global context number. Jeremy. (This used to be commit 5b4b335ed0d1dc738f1f099e5c638361f3aede07) --- source3/smbd/oplock.c | 12 +++++++----- source3/smbd/seal.c | 9 +++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 2c3313606a..8a5b1f4ecd 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -252,11 +252,13 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx, } memset(result,'\0',smb_size); - /* We use cli_set_message here as this is an - * asynchronous message that doesn't belong in - * the stream. - */ - cli_set_message(result,8,0,True); + if (!srv_encryption_on()) { + cli_set_message(result,8,0,true); + } else { + char inbuf[8]; + smb_set_enclen(inbuf,4,srv_enc_ctx()); + srv_set_message(inbuf,result,8,0,true); + } SCVAL(result,smb_com,SMBlockingX); SSVAL(result,smb_tid,fsp->conn->cnum); SSVAL(result,smb_pid,0xFFFF); diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 14a427bb9c..24ecb77fd5 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -47,6 +47,15 @@ bool srv_encryption_on(void) return false; } +/****************************************************************************** + Return global enc context - this must change if we ever do multiple contexts. +******************************************************************************/ + +uint16 srv_enc_ctx(void) +{ + return srv_trans_enc_ctx->es->enc_ctx_num; +} + /****************************************************************************** Create an auth_ntlmssp_state and ensure pointer copy is correct. ******************************************************************************/ -- cgit From 31d3f5726a0f4ae23243c82645506cb257d57b53 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 1 Jan 2008 12:55:29 +0100 Subject: Use NULL instead of 0 "struct security_descriptor" has pointers, not integers inside (This used to be commit 13158014e3b05e44eea897fbcf470957301c5c97) --- source3/smbd/open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d3ba9e076c..b6e6adde8a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2606,16 +2606,16 @@ NTSTATUS create_file_unixpath(connection_struct *conn, uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; uint32_t saved_access_mask = fsp->access_mask; - if (sd->owner_sid==0) { + if (sd->owner_sid == NULL) { sec_info_sent &= ~OWNER_SECURITY_INFORMATION; } - if (sd->group_sid==0) { + if (sd->group_sid == NULL) { sec_info_sent &= ~GROUP_SECURITY_INFORMATION; } - if (sd->sacl==0) { + if (sd->sacl == NULL) { sec_info_sent &= ~SACL_SECURITY_INFORMATION; } - if (sd->dacl==0) { + if (sd->dacl == NULL) { sec_info_sent &= ~DACL_SECURITY_INFORMATION; } -- cgit From c1328242652e4d61348cf00ba66e52485f4bbcaf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 14:19:07 +0100 Subject: Convert reply_open to create_file (This used to be commit 209c696ab8490564ec9e30f6f07b9c72af3ed2e1) --- source3/smbd/reply.c | 59 +++++++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 40 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2707aee9c8..452b803f9c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1597,51 +1597,30 @@ void reply_open(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - END_PROFILE(SMBopen); - return; - } - reply_nterror(req, status); - END_PROFILE(SMBopen); - return; - } - - status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBopen); - return; - } - - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBopen); - return; - } - - if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, - &access_mask, &share_mode, &create_disposition, &create_options)) { + if (!map_open_params_to_ntcreate( + fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask, + &share_mode, &create_disposition, &create_options)) { reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); END_PROFILE(SMBopen); return; } - status = open_file_ntcreate(conn, req, fname, &sbuf, - access_mask, - share_mode, - create_disposition, - create_options, - dos_attr, - oplock_request, - &info, &fsp); + status = create_file(conn, /* conn */ + req, /* req */ + 0, /* root_dir_fid */ + fname, /* fname */ + access_mask, /* access_mask */ + share_mode, /* share_access */ + create_disposition, /* create_disposition*/ + create_options, /* create_options */ + dos_attr, /* file_attributes */ + oplock_request, /* oplock_request */ + 0, /* allocation_size */ + NULL, /* sd */ + NULL, /* ea_list */ + &fsp, /* result */ + &info, /* pinfo */ + &sbuf); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { -- cgit From cc322c708c3ba3e73b9788ca27a233873effb88b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 14:23:10 +0100 Subject: Convert reply_open_and_X to create_file (This used to be commit fa09b9ab26657af9bd6dcf3fcc7311d5983a591d) --- source3/smbd/reply.c | 61 ++++++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 452b803f9c..4b873037b5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1741,53 +1741,30 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBopenX); - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - return; - } - reply_nterror(req, status); - return; - } - - status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBopenX); - return; - } - - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBopenX); - return; - } - - if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun, - &access_mask, - &share_mode, - &create_disposition, - &create_options)) { + if (!map_open_params_to_ntcreate( + fname, deny_mode, smb_ofun, &access_mask, + &share_mode, &create_disposition, &create_options)) { reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); END_PROFILE(SMBopenX); return; } - status = open_file_ntcreate(conn, req, fname, &sbuf, - access_mask, - share_mode, - create_disposition, - create_options, - smb_attr, - oplock_request, - &smb_action, &fsp); + status = create_file(conn, /* conn */ + req, /* req */ + 0, /* root_dir_fid */ + fname, /* fname */ + access_mask, /* access_mask */ + share_mode, /* share_access */ + create_disposition, /* create_disposition*/ + create_options, /* create_options */ + smb_attr, /* file_attributes */ + oplock_request, /* oplock_request */ + 0, /* allocation_size */ + NULL, /* sd */ + NULL, /* ea_list */ + &fsp, /* result */ + &smb_action, /* pinfo */ + &sbuf); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); -- cgit From 8ad3db1d2be41f8afca66f1db52560d026ea3845 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Dec 2007 12:05:41 +0100 Subject: Convert reply_mknew to create_file (This used to be commit 1b1cea9ef04a85a2fdd3c8574f7c4db559b7d9b6) --- source3/smbd/reply.c | 54 ++++++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4b873037b5..c859efd370 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1938,35 +1938,6 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) return; } - status = resolve_dfspath(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBcreate); - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - return; - } - reply_nterror(req, status); - return; - } - - status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBcreate); - return; - } - - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBcreate); - return; - } - if (fattr & aVOLID) { DEBUG(0,("Attempt to create file (%s) with volid set - " "please report this\n", fname)); @@ -1980,15 +1951,22 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) create_disposition = FILE_OVERWRITE_IF; } - /* Open file using ntcreate. */ - status = open_file_ntcreate(conn, req, fname, &sbuf, - access_mask, - share_mode, - create_disposition, - create_options, - fattr, - oplock_request, - NULL, &fsp); + status = create_file(conn, /* conn */ + req, /* req */ + 0, /* root_dir_fid */ + fname, /* fname */ + access_mask, /* access_mask */ + share_mode, /* share_access */ + create_disposition, /* create_disposition*/ + create_options, /* create_options */ + fattr, /* file_attributes */ + oplock_request, /* oplock_request */ + 0, /* allocation_size */ + NULL, /* sd */ + NULL, /* ea_list */ + &fsp, /* result */ + NULL, /* pinfo */ + &sbuf); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); -- cgit From 523dbf801b019b16ea5ec9ca1e8e3dfcc2dc50ac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Dec 2007 12:29:09 +0100 Subject: Convert call_trans2open to create_file() (This used to be commit 22138572bd2b9ae379b01098566e38e132653968) --- source3/smbd/trans2.c | 73 +++++++++++---------------------------------------- 1 file changed, 16 insertions(+), 57 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 656925502b..eba8cb50f0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -841,20 +841,6 @@ static void call_trans2open(connection_struct *conn, fname, (unsigned int)deny_mode, (unsigned int)open_attr, (unsigned int)open_ofun, open_size)); - /* XXXX we need to handle passed times, sattr and flags */ - - status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - status = check_name(conn, fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - if (open_ofun == 0) { reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION); return; @@ -899,14 +885,22 @@ static void call_trans2open(connection_struct *conn, return; } - status = open_file_ntcreate(conn, req, fname, &sbuf, - access_mask, - share_mode, - create_disposition, - create_options, - open_attr, - oplock_request, - &smb_action, &fsp); + status = create_file(conn, /* conn */ + req, /* req */ + 0, /* root_dir_fid */ + fname, /* fname */ + access_mask, /* access_mask */ + share_mode, /* share_access */ + create_disposition, /* create_disposition*/ + create_options, /* create_options */ + open_attr, /* file_attributes */ + oplock_request, /* oplock_request */ + open_size, /* allocation_size */ + NULL, /* sd */ + ea_list, /* ea_list */ + &fsp, /* result */ + &smb_action, /* pinfo */ + &sbuf); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -927,41 +921,6 @@ static void call_trans2open(connection_struct *conn, return; } - /* Save the requested allocation size. */ - /* Allocate space for the file if a size hint is supplied */ - if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { - SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size; - if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); - if (fsp->is_directory) { - close_file(fsp,ERROR_CLOSE); - /* Can't set allocation size on a directory. */ - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,ERROR_CLOSE); - reply_nterror(req, NT_STATUS_DISK_FULL); - return; - } - - /* Adjust size here to return the right size in the reply. - Windows does it this way. */ - size = fsp->initial_allocation_size; - } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size); - } - } - - if (ea_list && smb_action == FILE_WAS_CREATED) { - status = set_ea(conn, fsp, fname, ea_list); - if (!NT_STATUS_IS_OK(status)) { - close_file(fsp,ERROR_CLOSE); - reply_nterror(req, status); - return; - } - } - /* Realloc the size of parameters and data we will return */ *pparams = (char *)SMB_REALLOC(*pparams, 30); if(*pparams == NULL ) { -- cgit From 9254bb4ef1c3c3a52ea8e935edb0e7a86ec3ea7a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 12:56:23 -0800 Subject: Refactor the crypto code after a very helpful conversation with Volker. Mostly making sure we have data on the incoming packet type, not stored in the smb header. Jeremy. (This used to be commit c4e5a505043965eec77b5bb9bc60957e8f3b97c8) --- source3/smbd/aio.c | 27 ++++---- source3/smbd/blocking.c | 34 ++++++---- source3/smbd/error.c | 4 +- source3/smbd/ipc.c | 53 ++++++++------- source3/smbd/lanman.c | 2 +- source3/smbd/notify.c | 46 +++++++------ source3/smbd/nttrans.c | 39 ++++++----- source3/smbd/open.c | 4 +- source3/smbd/oplock.c | 26 +++---- source3/smbd/pipes.c | 3 +- source3/smbd/process.c | 173 +++++++++++++++++++++++++++++++---------------- source3/smbd/reply.c | 55 ++++++++------- source3/smbd/seal.c | 44 ++++++++---- source3/smbd/sesssetup.c | 2 +- source3/smbd/trans2.c | 69 +++++++++++-------- 15 files changed, 345 insertions(+), 236 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index a439c3a4f0..bc1761b0fd 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -236,7 +236,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - srv_set_message((const char *)req->inbuf, aio_ex->outbuf, 12, 0, True); + srv_set_message(aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -356,8 +356,9 @@ bool schedule_aio_write_and_X(connection_struct *conn, SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); show_msg(aio_ex->outbuf); - if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb " + if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf, + IS_CONN_ENCRYPTED(fsp->conn))) { + exit_server_cleanly("handle_aio_write: srv_send_smb " "failed."); } DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " @@ -387,7 +388,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; - const char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -410,9 +410,9 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) ret = errno; ERROR_NT(map_nt_error_from_unix(ret)); - outsize = srv_set_message(inbuf,outbuf,0,0,true); + outsize = srv_set_message(outbuf,0,0,true); } else { - outsize = srv_set_message(inbuf, outbuf,12,nread,False); + outsize = srv_set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -425,10 +425,11 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - _smb_setlen(outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4); show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("handle_aio_read_complete: send_smb " + if (!srv_send_smb(smbd_server_fd(),outbuf, + IS_CONN_ENCRYPTED(aio_ex->fsp->conn))) { + exit_server_cleanly("handle_aio_read_complete: srv_send_smb " "failed."); } @@ -497,7 +498,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ret = errno; ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); - srv_set_message(inbuf,outbuf,0,0,true); + srv_set_message(outbuf,0,0,true); } else { bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); NTSTATUS status; @@ -516,15 +517,15 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ret = errno; ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); - srv_set_message(inbuf,outbuf,0,0,true); + srv_set_message(outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); } } show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn))) { + exit_server_cleanly("handle_aio_write: srv_send_smb failed."); } DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed " diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 0078bb7d13..c56f635dde 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -41,6 +41,7 @@ typedef struct _blocking_lock_record { enum brl_type lock_type; char *inbuf; int length; + bool encrypted; } blocking_lock_record; /* dlink list we store pending lock records on. */ @@ -149,7 +150,7 @@ static bool recalc_brl_timeout(void) ****************************************************************************/ bool push_blocking_lock_request( struct byte_range_lock *br_lck, - const char *inbuf, int length, + const struct smb_request *req, files_struct *fsp, int lock_timeout, int lock_num, @@ -161,6 +162,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, uint32 blocking_pid) { static bool set_lock_msg; + size_t length = smb_len(req->inbuf)+4; blocking_lock_record *blr; NTSTATUS status; @@ -188,7 +190,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, return False; } - blr->com_type = CVAL(inbuf,smb_com); + blr->com_type = CVAL(req->inbuf,smb_com); blr->fsp = fsp; if (lock_timeout == -1) { blr->expire_time.tv_sec = 0; @@ -204,8 +206,9 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, blr->lock_type = lock_type; blr->offset = offset; blr->count = count; - memcpy(blr->inbuf, inbuf, length); + memcpy(blr->inbuf, req->inbuf, length); blr->length = length; + blr->encrypted = req->encrypted; /* Add a pending lock record for this. */ status = brl_lock(smbd_messaging_context(), br_lck, @@ -242,7 +245,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(req->inbuf,smb_mid)); return True; } @@ -259,7 +262,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) smb_panic("Could not allocate smb_request"); } - init_smb_request(req, (uint8 *)blr->inbuf, 0); + init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted); reply_outbuf(req, 2, 0); /* @@ -272,8 +275,10 @@ static void reply_lockingX_success(blocking_lock_record *blr) chain_reply(req); - if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) { - exit_server_cleanly("send_blocking_reply: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + IS_CONN_ENCRYPTED(blr->fsp->conn))) { + exit_server_cleanly("send_blocking_reply: srv_send_smb failed."); } } @@ -309,8 +314,9 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat } ERROR_NT(status); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("generic_blocking_lock_error: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(),outbuf, + IS_CONN_ENCRYPTED(blr->fsp->conn))) { + exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed."); } } @@ -388,8 +394,10 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status */ SCVAL(outbuf,smb_com,SMBtrans2); ERROR_NT(status); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("blocking_lock_reply_error: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + outbuf, + IS_CONN_ENCRYPTED(blr->fsp->conn))) { + exit_server_cleanly("blocking_lock_reply_error: srv_send_smb failed."); } break; } @@ -531,12 +539,12 @@ static bool process_trans2(blocking_lock_record *blr) return True; } - init_smb_request(req, (uint8 *)blr->inbuf, 0); + init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted); SCVAL(req->inbuf, smb_com, SMBtrans2); SSVAL(params,0,0); /* Fake up max_data_bytes here - we know it fits. */ - send_trans2_replies(req, params, 2, NULL, 0, 0xffff); + send_trans2_replies(blr->fsp->conn, req, params, 2, NULL, 0, 0xffff); return True; } diff --git a/source3/smbd/error.c b/source3/smbd/error.c index c669e74146..de2de088ec 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -81,9 +81,9 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu } } -int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { - int outsize = srv_set_message(inbuf, outbuf,0,0,True); + int outsize = srv_set_message(outbuf,0,0,True); error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index f28016ccb3..a89f5cbbfe 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -30,7 +30,7 @@ extern int max_send; #define NERR_notsupported 50 -static void api_no_reply(struct smb_request *req); +static void api_no_reply(connection_struct *conn, struct smb_request *req); /******************************************************************* copies parameters and data, as needed, into the smb buffer @@ -81,7 +81,8 @@ static void copy_trans_params_and_data(char *outbuf, int align, Send a trans reply. ****************************************************************************/ -void send_trans_reply(struct smb_request *req, +void send_trans_reply(connection_struct *conn, + struct smb_request *req, char *rparam, int rparam_len, char *rdata, int rdata_len, bool buffer_too_large) @@ -129,8 +130,10 @@ void send_trans_reply(struct smb_request *req, } show_msg((char *)req->outbuf); - if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) - exit_server_cleanly("send_trans_reply: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + IS_CONN_ENCRYPTED(conn))) + exit_server_cleanly("send_trans_reply: srv_send_smb failed."); TALLOC_FREE(req->outbuf); @@ -175,8 +178,10 @@ void send_trans_reply(struct smb_request *req, } show_msg((char *)req->outbuf); - if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) - exit_server_cleanly("send_trans_reply: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + IS_CONN_ENCRYPTED(conn))) + exit_server_cleanly("send_trans_reply: srv_send_smb failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; @@ -188,7 +193,7 @@ void send_trans_reply(struct smb_request *req, Start the first part of an RPC reply which began with an SMBtrans request. ****************************************************************************/ -static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p) +static void api_rpc_trans_reply(connection_struct *conn, struct smb_request *req, smb_np_struct *p) { bool is_data_outstanding; char *rdata = (char *)SMB_MALLOC(p->max_trans_reply); @@ -203,11 +208,11 @@ static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p) if((data_len = read_from_pipe( p, rdata, p->max_trans_reply, &is_data_outstanding)) < 0) { SAFE_FREE(rdata); - api_no_reply(req); + api_no_reply(conn,req); return; } - send_trans_reply(req, NULL, 0, rdata, data_len, is_data_outstanding); + send_trans_reply(conn, req, NULL, 0, rdata, data_len, is_data_outstanding); SAFE_FREE(rdata); return; } @@ -216,7 +221,7 @@ static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p) WaitNamedPipeHandleState ****************************************************************************/ -static void api_WNPHS(struct smb_request *req, smb_np_struct *p, +static void api_WNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p, char *param, int param_len) { uint16 priority; @@ -231,10 +236,10 @@ static void api_WNPHS(struct smb_request *req, smb_np_struct *p, if (wait_rpc_pipe_hnd_state(p, priority)) { /* now send the reply */ - send_trans_reply(req, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req, NULL, 0, NULL, 0, False); return; } - api_no_reply(req); + api_no_reply(conn,req); } @@ -242,7 +247,7 @@ static void api_WNPHS(struct smb_request *req, smb_np_struct *p, SetNamedPipeHandleState ****************************************************************************/ -static void api_SNPHS(struct smb_request *req, smb_np_struct *p, +static void api_SNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p, char *param, int param_len) { uint16 id; @@ -257,10 +262,10 @@ static void api_SNPHS(struct smb_request *req, smb_np_struct *p, if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply(req, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req, NULL, 0, NULL, 0, False); return; } - api_no_reply(req); + api_no_reply(conn,req); } @@ -268,7 +273,7 @@ static void api_SNPHS(struct smb_request *req, smb_np_struct *p, When no reply is generated, indicate unsupported. ****************************************************************************/ -static void api_no_reply(struct smb_request *req) +static void api_no_reply(connection_struct *conn, struct smb_request *req) { char rparam[4]; @@ -279,7 +284,7 @@ static void api_no_reply(struct smb_request *req) DEBUG(3,("Unsupported API fd command\n")); /* now send the reply */ - send_trans_reply(req, rparam, 4, NULL, 0, False); + send_trans_reply(conn, req, rparam, 4, NULL, 0, False); return; } @@ -321,7 +326,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, /* Win9x does this call with a unicode pipe name, not a pnum. */ /* Just return success for now... */ DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n")); - send_trans_reply(req, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req, NULL, 0, NULL, 0, False); return; } @@ -349,18 +354,18 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, /* dce/rpc command */ reply = write_to_pipe(p, data, tdscnt); if (!reply) { - api_no_reply(req); + api_no_reply(conn, req); return; } - api_rpc_trans_reply(req, p); + api_rpc_trans_reply(conn, req, p); break; case TRANSACT_WAITNAMEDPIPEHANDLESTATE: /* Wait Named Pipe Handle state */ - api_WNPHS(req, p, params, tpscnt); + api_WNPHS(conn, req, p, params, tpscnt); break; case TRANSACT_SETNAMEDPIPEHANDLESTATE: /* Set Named Pipe Handle state */ - api_SNPHS(req, p, params, tpscnt); + api_SNPHS(conn, req, p, params, tpscnt); break; default: reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -472,8 +477,10 @@ static void handle_trans(connection_struct *conn, struct smb_request *req, state->max_data_return, state->max_param_return); - if (state->close_on_completion) + if (state->close_on_completion) { close_cnum(conn,state->vuid); + req->conn = NULL; + } return; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 3ab216c062..5a6df1f139 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4605,7 +4605,7 @@ void api_reply(connection_struct *conn, uint16 vuid, /* If api_Unsupported returns false we can't return anything. */ if (reply) { - send_trans_reply(req, rparam, rparam_len, + send_trans_reply(conn, req, rparam, rparam_len, rdata, rdata_len, False); } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index baab48f77e..7287210802 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -128,10 +128,10 @@ static bool notify_marshall_changes(int num_changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(const uint8 *request_buf, +static void change_notify_reply_packet(connection_struct *conn, + const uint8 *request_buf, NTSTATUS error_code) { - const char *inbuf = (const char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); @@ -143,15 +143,18 @@ static void change_notify_reply_packet(const uint8 *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - srv_set_message((const char *)request_buf, outbuf,18,0,False); + srv_set_message(outbuf,18,0,False); show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("change_notify_reply_packet: send_smb " + if (!srv_send_smb(smbd_server_fd(), + outbuf, + IS_CONN_ENCRYPTED(conn))) + exit_server_cleanly("change_notify_reply_packet: srv_send_smb " "failed."); } -void change_notify_reply(const uint8 *request_buf, uint32 max_param, +void change_notify_reply(connection_struct *conn, + const uint8 *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { prs_struct ps; @@ -159,7 +162,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, uint8 tmp_request[smb_size]; if (notify_buf->num_changes == -1) { - change_notify_reply_packet(request_buf, NT_STATUS_OK); + change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); notify_buf->num_changes = 0; return; } @@ -172,12 +175,12 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, * We exceed what the client is willing to accept. Send * nothing. */ - change_notify_reply_packet(request_buf, NT_STATUS_OK); + change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); goto done; } if (!(req = talloc(talloc_tos(), struct smb_request))) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); + change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY); goto done; } @@ -190,9 +193,9 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, smb_setlen((char *)tmp_request, smb_size); SCVAL(tmp_request, smb_wct, 0); - init_smb_request(req, tmp_request,0); + init_smb_request(req, tmp_request,0, conn->encrypted_tid); - send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), + send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); done: @@ -243,9 +246,10 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, - uint32 filter, bool recursive, - struct files_struct *fsp) +NTSTATUS change_notify_add_request(const struct smb_request *req, + uint32 max_param, + uint32 filter, bool recursive, + struct files_struct *fsp) { struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; @@ -259,7 +263,7 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, request->mid_map = map; map->req = request; - memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); + memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf)); request->max_param = max_param; request->filter = filter; request->fsp = fsp; @@ -268,11 +272,11 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); - map->mid = SVAL(inbuf, smb_mid); + map->mid = SVAL(req->inbuf, smb_mid); DLIST_ADD(notify_changes_by_mid, map); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(req->inbuf,smb_mid)); return NT_STATUS_OK; } @@ -325,7 +329,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid) return; } - change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_reply_packet(map->req->fsp->conn, + map->req->request_buf, NT_STATUS_CANCELLED); change_notify_remove_request(map->req); } @@ -341,7 +346,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } while (fsp->notify->requests != NULL) { - change_notify_reply_packet( + change_notify_reply_packet(fsp->conn, fsp->notify->requests->request_buf, status); change_notify_remove_request(fsp->notify->requests); } @@ -435,7 +440,8 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) * TODO: do we have to walk the lists of requests pending? */ - change_notify_reply(fsp->notify->requests->request_buf, + change_notify_reply(fsp->conn, + fsp->notify->requests->request_buf, fsp->notify->requests->max_param, fsp->notify); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 69772b6bec..8ac0217dcd 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -66,7 +66,8 @@ static char *nttrans_realloc(char **ptr, size_t size) HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, +void send_nt_replies(connection_struct *conn, + struct smb_request *req, NTSTATUS nt_error, char *params, int paramsize, char *pdata, int datasize) { @@ -242,8 +243,10 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error, /* Send the packet */ show_msg((char *)req->outbuf); - if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) { - exit_server_cleanly("send_nt_replies: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + IS_CONN_ENCRYPTED(conn))) { + exit_server_cleanly("send_nt_replies: srv_send_smb failed."); } TALLOC_FREE(req->outbuf); @@ -726,7 +729,7 @@ static void do_nt_transact_create_pipe(connection_struct *conn, DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0); return; } @@ -1080,7 +1083,7 @@ static void call_nt_transact_create(connection_struct *conn, DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ - send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0); + send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0); return; } @@ -1474,7 +1477,7 @@ static void call_nt_transact_notify_change(connection_struct *conn, * here. */ - change_notify_reply(req->inbuf, max_param_count, fsp->notify); + change_notify_reply(fsp->conn, req->inbuf, max_param_count, fsp->notify); /* * change_notify_reply() above has independently sent its @@ -1487,7 +1490,9 @@ static void call_nt_transact_notify_change(connection_struct *conn, * No changes pending, queue the request */ - status = change_notify_add_request(req->inbuf, max_param_count, filter, + status = change_notify_add_request(req, + max_param_count, + filter, recursive, fsp); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -1554,7 +1559,7 @@ static void call_nt_transact_rename(connection_struct *conn, /* * Rename was successful. */ - send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", fsp->fsp_name, new_name)); @@ -1657,7 +1662,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, SIVAL(params,0,(uint32)sd_size); if (max_data_count < sd_size) { - send_nt_replies(req, NT_STATUS_BUFFER_TOO_SMALL, + send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); TALLOC_FREE(frame); return; @@ -1686,7 +1691,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, SMB_ASSERT(sd_size == blob.length); memcpy(data, blob.data, sd_size); - send_nt_replies(req, NT_STATUS_OK, params, 4, data, (int)sd_size); + send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size); TALLOC_FREE(frame); return; @@ -1744,7 +1749,7 @@ static void call_nt_transact_set_security_desc(connection_struct *conn, } done: - send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); return; } @@ -1793,7 +1798,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, so we can know if we need to pre-allocate or not */ DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); - send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); return; case FSCTL_CREATE_OR_GET_OBJECT_ID: @@ -1819,7 +1824,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, push_file_id_16(pdata, &fsp->file_id); memcpy(pdata+16,create_volume_objectid(conn,objid),16); push_file_id_16(pdata+32, &fsp->file_id); - send_nt_replies(req, NT_STATUS_OK, NULL, 0, + send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, pdata, data_count); return; } @@ -1964,7 +1969,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, talloc_destroy(shadow_data->mem_ctx); - send_nt_replies(req, NT_STATUS_OK, NULL, 0, + send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, pdata, data_count); return; @@ -2020,7 +2025,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, */ /* this works for now... */ - send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0); + send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); return; } default: @@ -2306,7 +2311,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, break; } - send_nt_replies(req, nt_status, params, param_len, + send_nt_replies(conn, req, nt_status, params, param_len, pdata, data_len); } @@ -2436,7 +2441,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, return; } - send_nt_replies(req, NT_STATUS_OK, params, param_len, + send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, pdata, data_len); } #endif /* HAVE_SYS_QUOTAS */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b6e6adde8a..e3fae02b83 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2267,7 +2267,7 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_OK; } -NTSTATUS create_directory(connection_struct *conn, const char *directory) +NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory) { NTSTATUS status; SMB_STRUCT_STAT sbuf; @@ -2275,7 +2275,7 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) SET_STAT_INVALID(sbuf); - status = open_directory(conn, NULL, directory, &sbuf, + status = open_directory(conn, req, directory, &sbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ FILE_CREATE, diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8a5b1f4ecd..277e07c178 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -252,13 +252,7 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx, } memset(result,'\0',smb_size); - if (!srv_encryption_on()) { - cli_set_message(result,8,0,true); - } else { - char inbuf[8]; - smb_set_enclen(inbuf,4,srv_enc_ctx()); - srv_set_message(inbuf,result,8,0,true); - } + srv_set_message(result,8,0,true); SCVAL(result,smb_com,SMBlockingX); SSVAL(result,smb_tid,fsp->conn->cnum); SSVAL(result,smb_pid,0xFFFF); @@ -455,8 +449,10 @@ static void process_oplock_async_level2_break_message(struct messaging_context * sign_state = srv_oplock_set_signing(False); show_msg(break_msg); - if (!send_smb(smbd_server_fd(), break_msg)) { - exit_server_cleanly("oplock_break: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + break_msg, + IS_CONN_ENCRYPTED(fsp->conn))) { + exit_server_cleanly("oplock_break: srv_send_smb failed."); } /* Restore the sign state to what it was. */ @@ -560,8 +556,10 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, sign_state = srv_oplock_set_signing(False); show_msg(break_msg); - if (!send_smb(smbd_server_fd(), break_msg)) { - exit_server_cleanly("oplock_break: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + break_msg, + IS_CONN_ENCRYPTED(fsp->conn))) { + exit_server_cleanly("oplock_break: srv_send_smb failed."); } /* Restore the sign state to what it was. */ @@ -637,8 +635,10 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, sign_state = srv_oplock_set_signing(False); show_msg(break_msg); - if (!send_smb(smbd_server_fd(), break_msg)) { - exit_server_cleanly("oplock_break: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + break_msg, + IS_CONN_ENCRYPTED(fsp->conn))) { + exit_server_cleanly("oplock_break: srv_send_smb failed."); } /* Restore the sign state to what it was. */ diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 88b67c03e5..6b4b83d97d 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -291,8 +291,7 @@ void reply_pipe_read_and_X(struct smb_request *req) return; } - srv_set_message((const char *)req->inbuf, - (char *)req->outbuf, 12, nread, False); + srv_set_message((char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 48a6d18bc9..32d1d058e3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -50,14 +50,52 @@ enum smb_read_errors *get_srv_read_error(void) return &smb_read_error; } +/**************************************************************************** + Send an smb to a fd. +****************************************************************************/ + +bool srv_send_smb(int fd, char *buffer, bool do_encrypt) +{ + size_t len; + size_t nwritten=0; + ssize_t ret; + char *buf_out = buffer; + + /* Sign the outgoing packet if required. */ + srv_calculate_sign_mac(buf_out); + + if (do_encrypt) { + NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("send_smb: SMB encryption failed " + "on outgoing packet! Error %s\n", + nt_errstr(status) )); + return false; + } + } + + len = smb_len(buf_out) + 4; + + while (nwritten < len) { + ret = write_data(fd,buf_out+nwritten,len - nwritten); + if (ret <= 0) { + DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n", + (int)len,(int)ret, strerror(errno) )); + srv_free_enc_buffer(buf_out); + return false; + } + nwritten += ret; + } + + srv_free_enc_buffer(buf_out); + return true; +} + /******************************************************************* Setup the word count and byte count for a smb message. - copying the '0xFF X X X' bytes from incoming - buffer (so we copy any encryption context). ********************************************************************/ -int srv_set_message(const char *frombuf, - char *buf, +int srv_set_message(char *buf, int num_words, int num_bytes, bool zero) @@ -67,22 +105,14 @@ int srv_set_message(const char *frombuf, } SCVAL(buf,smb_wct,num_words); SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); - _smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4)); - if (buf != frombuf) { - memcpy(buf+4, frombuf+4, 4); - } + smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4)); return (smb_size + num_words*2 + num_bytes); } -static bool valid_smb_header(const char *inbuf) +static bool valid_smb_header(const uint8_t *inbuf) { - if (srv_encryption_on()) { - uint16_t enc_num; - NTSTATUS status = get_enc_ctx_num(inbuf, &enc_num); - if (!NT_STATUS_IS_OK(status)) { - return false; - } - return (enc_num == 0); + if (is_encrypted_packet(inbuf)) { + return true; } return (strncmp(smb_base(inbuf),"\377SMB",4) == 0); } @@ -162,7 +192,7 @@ static ssize_t read_packet_remainder(int fd, (2*14) + /* word count (including bcc) */ \ 1 /* pad byte */) -ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, +static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, const char lenbuf[4], int fd, char **buffer, @@ -202,7 +232,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, * valid writeX call. */ - if (is_valid_writeX_buffer(writeX_header)) { + if (is_valid_writeX_buffer((uint8_t *)writeX_header)) { /* * If the data offset is beyond what * we've read, drain the extra bytes. @@ -310,7 +340,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, return -1; } - if (CVAL(lenbuf,0) != SMBkeepalive && + if (CVAL(lenbuf,0) == 0 && min_recv_size && smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */ !srv_is_signing_active()) { @@ -350,18 +380,24 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, return len + 4; } -ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, - unsigned int timeout, size_t *p_unread) +static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, + int fd, + char **buffer, + unsigned int timeout, + size_t *p_unread, + bool *p_encrypted) { ssize_t len; + *p_encrypted = false; + len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread); if (len < 0) { return -1; } - if (srv_encryption_on()) { + if (is_encrypted_packet((uint8_t *)*buffer)) { NTSTATUS status = srv_decrypt_buffer(*buffer); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("receive_smb_talloc: SMB decryption failed on " @@ -371,6 +407,7 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, SMB_READ_BAD_DECRYPT); return -1; } + *p_encrypted = true; } /* Check the incoming SMB signature. */ @@ -390,7 +427,8 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, void init_smb_request(struct smb_request *req, const uint8 *inbuf, - size_t unread_bytes) + size_t unread_bytes, + bool encrypted) { size_t req_size = smb_len(inbuf) + 4; /* Ensure we have at least smb_size bytes. */ @@ -406,6 +444,8 @@ void init_smb_request(struct smb_request *req, req->tid = SVAL(inbuf, smb_tid); req->wct = CVAL(inbuf, smb_wct); req->unread_bytes = unread_bytes; + req->encrypted = encrypted; + req->conn = conn_find(req->tid); /* Ensure we have at least wct words and 2 bytes of bcc. */ if (smb_size + req->wct*2 > req_size) { @@ -463,6 +503,7 @@ static bool push_queued_message(struct smb_request *req, msg->request_time = request_time; msg->end_time = end_time; + msg->encrypted = req->encrypted; if (private_data) { msg->private_data = data_blob_talloc(msg, private_data, @@ -738,7 +779,8 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, size_t *buffer_len, int timeout, - size_t *p_unread) + size_t *p_unread, + bool *p_encrypted) { fd_set r_fds, w_fds; int selrtn; @@ -805,6 +847,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, return False; } *buffer_len = msg->buf.length; + *p_encrypted = msg->encrypted; /* We leave this message on the queue so the open code can know this is a retry. */ @@ -921,7 +964,8 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, goto again; } - len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, p_unread); + len = receive_smb_talloc(mem_ctx, smbd_server_fd(), + buffer, 0, p_unread, p_encrypted); if (len == -1) { return False; @@ -1288,8 +1332,7 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) } construct_reply_common((char *)req->inbuf, (char *)req->outbuf); - srv_set_message((const char *)req->inbuf, - (char *)req->outbuf, num_words, num_bytes, false); + srv_set_message((char *)req->outbuf, num_words, num_bytes, false); /* * Zero out the word area, the caller has to take care of the bcc area * himself @@ -1347,11 +1390,11 @@ static void smb_dump(const char *name, int type, const char *data, ssize_t len) find. ****************************************************************************/ -static void switch_message(uint8 type, struct smb_request *req, int size) +static connection_struct *switch_message(uint8 type, struct smb_request *req, int size) { int flags; uint16 session_tag; - connection_struct *conn; + connection_struct *conn = NULL; static uint16 last_session_tag = UID_FIELD_INVALID; @@ -1359,7 +1402,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size) /* Make sure this is an SMB packet. smb_size contains NetBIOS header * so subtract 4 from it. */ - if (!valid_smb_header((const char *)req->inbuf) + if (!valid_smb_header(req->inbuf) || (size < (smb_size - 4))) { DEBUG(2,("Non-SMB packet of length %d. Terminating server\n", smb_len(req->inbuf))); @@ -1370,7 +1413,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size) DEBUG(0,("Unknown message type %d!\n",type)); smb_dump("Unknown", 1, (char *)req->inbuf, size); reply_unknown_new(req, type); - return; + return NULL; } flags = smb_messages[type].flags; @@ -1378,7 +1421,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size) /* In share mode security we must ignore the vuid. */ session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : req->vuid; - conn = conn_find(req->tid); + conn = req->conn; DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type), (int)sys_getpid(), (unsigned long)conn)); @@ -1423,12 +1466,12 @@ static void switch_message(uint8 type, struct smb_request *req, int size) } else { reply_doserror(req, ERRSRV, ERRinvnid); } - return; + return NULL; } if (!change_to_user(conn,session_tag)) { reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); - return; + return conn; } /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ @@ -1436,13 +1479,13 @@ static void switch_message(uint8 type, struct smb_request *req, int size) /* Does it need write permission? */ if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED); - return; + return conn; } /* IPC services are limited */ if (IS_IPC(conn) && !(flags & CAN_IPC)) { reply_doserror(req, ERRSRV,ERRaccess); - return; + return conn; } } else { /* This call needs to be run as root */ @@ -1451,21 +1494,24 @@ static void switch_message(uint8 type, struct smb_request *req, int size) /* load service specific parameters */ if (conn) { + if (req->encrypted) { + conn->encrypted_tid = true; + /* encrypted required from now on. */ + conn->encrypt_level = Required; + } else if (ENCRYPTION_REQUIRED(conn)) { + uint8 com = CVAL(req->inbuf,smb_com); + if (com != SMBtrans2 && com != SMBtranss2) { + exit_server_cleanly("encryption required " + "on connection"); + return conn; + } + } + if (!set_current_service(conn,SVAL(req->inbuf,smb_flg), (flags & (AS_USER|DO_CHDIR) ?True:False))) { reply_doserror(req, ERRSRV, ERRaccess); - return; - } - - if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { - /* An encrypted packet has 0xFF 'E' at offset 4 - * which is little endian 0x45FF */ - uint8 com = CVAL(req->inbuf,smb_com); - if (com != SMBtrans2 && com != SMBtranss2) { - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } + return conn; } conn->num_smb_operations++; } @@ -1476,19 +1522,21 @@ static void switch_message(uint8 type, struct smb_request *req, int size) !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { reply_doserror(req, ERRSRV, ERRaccess); - return; + return conn; } smb_messages[type].fn_new(conn, req); + return req->conn; } /**************************************************************************** Construct a reply to the incoming packet. ****************************************************************************/ -static void construct_reply(char *inbuf, int size, size_t unread_bytes) +static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted) { uint8 type = CVAL(inbuf,smb_com); + connection_struct *conn; struct smb_request *req; chain_size = 0; @@ -1498,9 +1546,9 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes) if (!(req = talloc(talloc_tos(), struct smb_request))) { smb_panic("could not allocate smb_request"); } - init_smb_request(req, (uint8 *)inbuf, unread_bytes); + init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted); - switch_message(type, req, size); + conn = switch_message(type, req, size); if (req->unread_bytes) { /* writeX failed. drain socket. */ @@ -1519,8 +1567,10 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes) show_msg((char *)req->outbuf); } - if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) { - exit_server_cleanly("construct_reply: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + IS_CONN_ENCRYPTED(conn)||req->encrypted)) { + exit_server_cleanly("construct_reply: srv_send_smb failed."); } TALLOC_FREE(req); @@ -1532,7 +1582,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes) Process an smb from the client ****************************************************************************/ -static void process_smb(char *inbuf, size_t nread, size_t unread_bytes) +static void process_smb(char *inbuf, size_t nread, size_t unread_bytes, bool encrypted) { static int trans_num; int msg_type = CVAL(inbuf,0); @@ -1553,7 +1603,7 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes) static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", client_addr(get_client_fd(),addr,sizeof(addr)) ) ); - (void)send_smb(smbd_server_fd(),(char *)buf); + (void)srv_send_smb(smbd_server_fd(),(char *)buf,false); exit_server_cleanly("connection denied"); } } @@ -1574,7 +1624,7 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes) show_msg(inbuf); - construct_reply(inbuf,nread,unread_bytes); + construct_reply(inbuf,nread,unread_bytes,encrypted); trans_num++; } @@ -1611,7 +1661,7 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(const char *inbuf, char *outbuf) { - srv_set_message(inbuf,outbuf,0,0,false); + srv_set_message(outbuf,0,0,false); SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); SIVAL(outbuf,smb_rcls,0); @@ -1734,7 +1784,7 @@ void chain_reply(struct smb_request *req) if (!(req2 = talloc(talloc_tos(), struct smb_request))) { smb_panic("could not allocate smb_request"); } - init_smb_request(req2, (uint8 *)inbuf2,0); + init_smb_request(req2, (uint8 *)inbuf2,0, req->encrypted); /* process the request */ switch_message(smb_com2, req2, new_size); @@ -2020,6 +2070,7 @@ void smbd_process(void) int num_echos; char *inbuf; size_t inbuf_len; + bool encrypted = false; TALLOC_CTX *frame = talloc_stackframe(); errno = 0; @@ -2035,7 +2086,9 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len, - select_timeout, &unread_bytes)) { + select_timeout, + &unread_bytes, + &encrypted)) { if(!timeout_processing(&select_timeout, &last_timeout_processing_time)) return; @@ -2054,7 +2107,7 @@ void smbd_process(void) */ num_echos = smb_echo_count; - process_smb(inbuf, inbuf_len, unread_bytes); + process_smb(inbuf, inbuf_len, unread_bytes, encrypted); TALLOC_FREE(inbuf); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c859efd370..b6efccdb15 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -391,7 +391,7 @@ void reply_special(char *inbuf) /* * We only really use 4 bytes of the outbuf, but for the smb_setlen - * calculation & friends (send_smb uses that) we need the full smb + * calculation & friends (srv_send_smb uses that) we need the full smb * header. */ char outbuf[smb_size]; @@ -470,7 +470,7 @@ void reply_special(char *inbuf) DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n", msg_type, msg_flags)); - send_smb(smbd_server_fd(), outbuf); + srv_send_smb(smbd_server_fd(), outbuf, false); return; } @@ -523,6 +523,7 @@ void reply_tcon(connection_struct *conn, struct smb_request *req) password_blob = data_blob(password, pwlen+1); conn = make_connection(service,password_blob,dev,req->vuid,&nt_status); + req->conn = conn; data_blob_clear_free(&password_blob); @@ -578,6 +579,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) /* we might have to close an old one */ if ((tcon_flags & 0x1) && conn) { close_cnum(conn,req->vuid); + req->conn = NULL; } if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) { @@ -646,6 +648,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) conn = make_connection(service, password, client_devicetype, req->vuid, &nt_status); + req->conn =conn; data_blob_clear_free(&password); @@ -2725,7 +2728,7 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req) START_PROFILE(SMBreadbraw); - if (srv_is_signing_active() || srv_encryption_on()) { + if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) { exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - " "raw reads/writes are disallowed."); } @@ -2951,8 +2954,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - srv_set_message((const char *)req->inbuf, - (char *)req->outbuf, 5, nread+3, False); + srv_set_message((char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3039,8 +3041,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - srv_set_message((const char *)req->inbuf, - (char *)req->outbuf, 5, nread+3, False); + srv_set_message((char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3058,12 +3059,12 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Setup readX header. ****************************************************************************/ -static int setup_readX_header(const char *inbuf, char *outbuf, size_t smb_maxcnt) +static int setup_readX_header(char *outbuf, size_t smb_maxcnt) { int outsize; char *data; - outsize = srv_set_message(inbuf, outbuf,12,smb_maxcnt,False); + outsize = srv_set_message(outbuf,12,smb_maxcnt,False); data = smb_buf(outbuf); memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */ @@ -3113,6 +3114,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, */ if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) && + !is_encrypted_packet(req->inbuf) && lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { uint8 headerbuf[smb_size + 12 * 2]; DATA_BLOB header; @@ -3126,8 +3128,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, header = data_blob_const(headerbuf, sizeof(headerbuf)); construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header((const char *)req->inbuf, - (char *)headerbuf, smb_maxcnt); + setup_readX_header((char *)headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ @@ -3178,8 +3179,7 @@ normal_read: uint8 headerbuf[smb_size + 2*12]; construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header((const char *)req->inbuf, - (char *)headerbuf, smb_maxcnt); + setup_readX_header((char *)headerbuf, smb_maxcnt); /* Send out the header. */ if (write_data(smbd_server_fd(), (char *)headerbuf, @@ -3206,8 +3206,7 @@ normal_read: return; } - setup_readX_header((const char *)req->inbuf, - (char *)req->outbuf, nread); + setup_readX_header((char *)req->outbuf, nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); @@ -3272,7 +3271,7 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) return; } /* We currently don't do this on signed or sealed data. */ - if (srv_is_signing_active() || srv_encryption_on()) { + if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBreadX); return; @@ -3463,13 +3462,15 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) * it to send more bytes */ memcpy(buf, req->inbuf, smb_size); - outsize = srv_set_message((const char *)req->inbuf, buf, + outsize = srv_set_message(buf, Protocol>PROTOCOL_COREPLUS?1:0,0,True); SCVAL(buf,smb_com,SMBwritebraw); SSVALS(buf,smb_vwv0,0xFFFF); show_msg(buf); - if (!send_smb(smbd_server_fd(),buf)) { - exit_server_cleanly("reply_writebraw: send_smb " + if (!srv_send_smb(smbd_server_fd(), + buf, + IS_CONN_ENCRYPTED(conn))) { + exit_server_cleanly("reply_writebraw: srv_send_smb " "failed."); } @@ -3788,14 +3789,14 @@ void reply_write(connection_struct *conn, struct smb_request *req) (2*14) + /* word count (including bcc) */ \ 1 /* pad byte */) -bool is_valid_writeX_buffer(const char *inbuf) +bool is_valid_writeX_buffer(const uint8_t *inbuf) { size_t numtowrite; connection_struct *conn = NULL; unsigned int doff = 0; size_t len = smb_len_large(inbuf); - if (srv_encryption_on()) { + if (is_encrypted_packet(inbuf)) { /* Can't do this on encrypted * connections. */ return false; @@ -4476,6 +4477,7 @@ void reply_tdis(connection_struct *conn, struct smb_request *req) conn->used = False; close_cnum(conn,req->vuid); + req->conn = NULL; reply_outbuf(req, 0, 0); END_PROFILE(SMBtdis); @@ -4526,8 +4528,10 @@ void reply_echo(connection_struct *conn, struct smb_request *req) SSVAL(req->outbuf,smb_vwv0,seq_num); show_msg((char *)req->outbuf); - if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) - exit_server_cleanly("reply_echo: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + IS_CONN_ENCRYPTED(conn)||req->encrypted)) + exit_server_cleanly("reply_echo: srv_send_smb failed."); } DEBUG(3,("echo %d times\n", smb_reverb)); @@ -4830,7 +4834,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req) return; } - status = create_directory(conn, directory); + status = create_directory(conn, req, directory); DEBUG(5, ("create_directory returned %s\n", nt_errstr(status))); @@ -6803,8 +6807,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) * onto the blocking lock queue. */ if(push_blocking_lock_request(br_lck, - (char *)req->inbuf, - smb_len(req->inbuf)+4, + req, fsp, lock_timeout, i, diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 24ecb77fd5..21fca73fea 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -36,24 +36,37 @@ static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; /****************************************************************************** - Is server encryption on ? + Return global enc context - this must change if we ever do multiple contexts. ******************************************************************************/ -bool srv_encryption_on(void) +uint16_t srv_enc_ctx(void) { - if (srv_trans_enc_ctx) { - return common_encryption_on(srv_trans_enc_ctx->es); - } - return false; + return srv_trans_enc_ctx->es->enc_ctx_num; } /****************************************************************************** - Return global enc context - this must change if we ever do multiple contexts. + Is this an incoming encrypted packet ? ******************************************************************************/ -uint16 srv_enc_ctx(void) +bool is_encrypted_packet(const uint8_t *inbuf) { - return srv_trans_enc_ctx->es->enc_ctx_num; + NTSTATUS status; + uint16_t enc_num; + + /* Ignore non-session messages. */ + if(CVAL(inbuf,0)) { + return false; + } + + status = get_enc_ctx_num(inbuf, &enc_num); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) { + return true; + } + return false; } /****************************************************************************** @@ -292,9 +305,9 @@ void srv_free_enc_buffer(char *buf) { /* We know this is an smb buffer, and we * didn't malloc, only copy, for a keepalive, - * so ignore session keepalives. */ + * so ignore non-session messages. */ - if(CVAL(buf,0) == SMBkeepalive) { + if(CVAL(buf,0)) { return; } @@ -309,8 +322,8 @@ void srv_free_enc_buffer(char *buf) NTSTATUS srv_decrypt_buffer(char *buf) { - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { + /* Ignore non-session messages. */ + if(CVAL(buf,0)) { return NT_STATUS_OK; } @@ -329,8 +342,8 @@ NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) { *buf_out = buf; - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { + /* Ignore non-session messages. */ + if(CVAL(buf,0)) { return NT_STATUS_OK; } @@ -698,6 +711,7 @@ NTSTATUS srv_encryption_start(connection_struct *conn) srv_trans_enc_ctx->es->enc_on = true; partial_srv_trans_enc_ctx = NULL; + return NT_STATUS_OK; } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 8ca012ff24..e44a540554 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -139,7 +139,7 @@ static void reply_sesssetup_blob(connection_struct *conn, } show_msg((char *)req->outbuf); - send_smb(smbd_server_fd(),(char *)req->outbuf); + srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted); TALLOC_FREE(req->outbuf); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index eba8cb50f0..1e421a70b6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -575,7 +575,8 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list * HACK ! Always assumes smb_setup field is zero. ****************************************************************************/ -void send_trans2_replies(struct smb_request *req, +void send_trans2_replies(connection_struct *conn, + struct smb_request *req, const char *params, int paramsize, const char *pdata, @@ -737,8 +738,10 @@ void send_trans2_replies(struct smb_request *req, /* Send the packet */ show_msg((char *)req->outbuf); - if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) - exit_server_cleanly("send_trans2_replies: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(), + (char *)req->outbuf, + IS_CONN_ENCRYPTED(conn))) + exit_server_cleanly("send_trans2_replies: srv_send_smb failed."); TALLOC_FREE(req->outbuf); @@ -956,7 +959,7 @@ static void call_trans2open(connection_struct *conn, } /* Send the required number of replies */ - send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes); + send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes); } /********************************************************* @@ -2026,7 +2029,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,6,0); /* Never an EA error */ SSVAL(params,8,last_entry_off); - send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata), + send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); if ((! *directory) && dptr_path(dptr_num)) { @@ -2350,7 +2353,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd SSVAL(params,4,0); /* Never an EA error */ SSVAL(params,6,last_entry_off); - send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata), + send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes); return; @@ -2389,13 +2392,23 @@ static void call_trans2qfsinfo(connection_struct *conn, info_level = SVAL(params,0); - if (IS_IPC(conn) || - (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF )) { + if (IS_IPC(conn)) { + if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { + DEBUG(0,("call_trans2qfsinfo: not an allowed " + "info level (0x%x) on IPC$.\n", + (unsigned int)info_level)); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + } + + if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) { if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { DEBUG(0,("call_trans2qfsinfo: encryption required " "and info level 0x%x sent.\n", (unsigned int)info_level)); - reply_nterror(req, NT_STATUS_ACCESS_DENIED); + exit_server_cleanly("encryption required " + "on connection"); return; } } @@ -2906,7 +2919,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } - send_trans2_replies(req, params, 0, pdata, data_len, + send_trans2_replies(conn, req, params, 0, pdata, data_len, max_data_bytes); DEBUG( 4, ( "%s info_level = %d\n", @@ -2952,12 +2965,13 @@ static void call_trans2setfsinfo(connection_struct *conn, } } - if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { + if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) { if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) { DEBUG(0,("call_trans2setfsinfo: encryption required " "and info level 0x%x sent.\n", (unsigned int)info_level)); - reply_nterror(req, NT_STATUS_ACCESS_DENIED); + exit_server_cleanly("encryption required " + "on connection"); return; } } @@ -3048,7 +3062,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", return; } - send_trans2_replies(req, + send_trans2_replies(conn, req, *pparams, param_len, *ppdata, @@ -3524,7 +3538,7 @@ static void call_trans2qpipeinfo(connection_struct *conn, return; } - send_trans2_replies(req, params, param_size, *ppdata, data_size, + send_trans2_replies(conn, req, params, param_size, *ppdata, data_size, max_data_bytes); return; @@ -4456,7 +4470,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return; } - send_trans2_replies(req, params, param_size, *ppdata, data_size, + send_trans2_replies(conn, req, params, param_size, *ppdata, data_size, max_data_bytes); return; @@ -5160,8 +5174,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_posix_lock(connection_struct *conn, - const uint8 *inbuf, - int length, + const struct smb_request *req, const char *pdata, int total_data, files_struct *fsp) @@ -5171,6 +5184,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, uint32 lock_pid; bool blocking_lock = False; enum brl_type lock_type; + NTSTATUS status = NT_STATUS_OK; if (fsp == NULL || fsp->fh->fd == -1) { @@ -5258,7 +5272,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, * onto the blocking lock queue. */ if(push_blocking_lock_request(br_lck, - (char *)inbuf, length, + req, fsp, -1, /* infinite timeout. */ 0, @@ -6316,7 +6330,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); SSVAL(params,0,0); - send_trans2_replies(req, params, 2, + send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes); return; @@ -6606,8 +6620,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; } - status = smb_set_posix_lock(conn, req->inbuf, - smb_len(req->inbuf) + 4, + status = smb_set_posix_lock(conn, req, pdata, total_data, fsp); break; } @@ -6675,7 +6688,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } SSVAL(params,0,0); - send_trans2_replies(req, params, 2, *ppdata, data_return_size, + send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size, max_data_bytes); return; @@ -6767,7 +6780,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, return; } - status = create_directory(conn, directory); + status = create_directory(conn, req, directory); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -6793,7 +6806,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, SSVAL(params,0,0); - send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes); + send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes); return; } @@ -6847,7 +6860,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn, if(fnf_handle == 0) fnf_handle = 257; - send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes); + send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes); return; } @@ -6878,7 +6891,7 @@ static void call_trans2findnotifynext(connection_struct *conn, SSVAL(params,0,0); /* No changes */ SSVAL(params,2,0); /* No EA errors */ - send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes); + send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes); return; } @@ -6928,7 +6941,7 @@ static void call_trans2getdfsreferral(connection_struct *conn, SSVAL(req->inbuf, smb_flg2, SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); - send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes); + send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes); return; } @@ -6975,7 +6988,7 @@ static void call_trans2ioctl(connection_struct *conn, srvstr_push(pdata, req->flags2, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */ - send_trans2_replies(req, *pparams, 0, *ppdata, 32, + send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32, max_data_bytes); return; } -- cgit From 6503c7338e2c46bf3c660759c078ff51835a40e9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 13:59:26 -0800 Subject: Fix interesting bug found with make valgrindtest. When cancelling a lock due to file closure make sure we null out the fsp pointer so it isn't dangling. This is an old bug (not related to the new changes). Jeremy. (This used to be commit b5ee972b0c04b4d119573d95ac458a3b6be30c5c) --- source3/smbd/blocking.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index c56f635dde..41963166f7 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -303,19 +303,20 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat /* Store the last lock error. */ files_struct *fsp = blr->fsp; - fsp->last_lock_failure.context.smbpid = blr->lock_pid; - fsp->last_lock_failure.context.tid = fsp->conn->cnum; - fsp->last_lock_failure.context.pid = procid_self(); - fsp->last_lock_failure.start = blr->offset; - fsp->last_lock_failure.size = blr->count; - fsp->last_lock_failure.fnum = fsp->fnum; - fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */ - fsp->last_lock_failure.lock_flav = blr->lock_flav; + if (fsp) { + fsp->last_lock_failure.context.smbpid = blr->lock_pid; + fsp->last_lock_failure.context.tid = fsp->conn->cnum; + fsp->last_lock_failure.context.pid = procid_self(); + fsp->last_lock_failure.start = blr->offset; + fsp->last_lock_failure.size = blr->count; + fsp->last_lock_failure.fnum = fsp->fnum; + fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */ + fsp->last_lock_failure.lock_flav = blr->lock_flav; + } } ERROR_NT(status); - if (!srv_send_smb(smbd_server_fd(),outbuf, - IS_CONN_ENCRYPTED(blr->fsp->conn))) { + if (!srv_send_smb(smbd_server_fd(),outbuf, blr->encrypted)) { exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed."); } } @@ -605,6 +606,9 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); locktype, NT_STATUS_RANGE_NOT_LOCKED); } + /* We're closing the file fsp here, so ensure + * we don't have a dangling pointer. */ + blr->fsp = NULL; } } } -- cgit From 9394916e49d124461299af8d3e13e97d2c935d14 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 14:43:43 -0800 Subject: We dont' modify the smb header for crypto anymore. Jeremy. (This used to be commit f5b6b6dac66b4ecc113985a7e7db1855b324c465) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1e421a70b6..4e2cceca36 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7067,7 +7067,7 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req, SSVAL(req->inbuf,smb_flg2,req->flags2); } - if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) { + if (conn->encrypt_level == Required && !req->encrypted) { if (state->call != TRANSACT2_QFSINFO && state->call != TRANSACT2_SETFSINFO) { DEBUG(0,("handle_trans2: encryption required " -- cgit From 29562987c393ef7e908aa02ee7ba00a83f3db520 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 15:37:24 -0800 Subject: Now conn is part of smb_request, we don't need it as an extra parameter. This cleans up quite a few places we were passing it around without needing it. Jeremy. (This used to be commit 8f36def18e9f980e8db522e1de41e80cfd5f466e) --- source3/smbd/ipc.c | 6 +- source3/smbd/message.c | 8 +-- source3/smbd/negprot.c | 2 +- source3/smbd/nttrans.c | 14 +++-- source3/smbd/process.c | 4 +- source3/smbd/reply.c | 147 ++++++++++++++++++++++++++++------------------- source3/smbd/sesssetup.c | 40 ++++++------- source3/smbd/trans2.c | 10 ++-- 8 files changed, 131 insertions(+), 100 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a89f5cbbfe..68a13d692f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -489,8 +489,9 @@ static void handle_trans(connection_struct *conn, struct smb_request *req, Reply to a SMBtrans. ****************************************************************************/ -void reply_trans(connection_struct *conn, struct smb_request *req) +void reply_trans(struct smb_request *req) { + connection_struct *conn = req->conn; unsigned int dsoff; unsigned int dscnt; unsigned int psoff; @@ -669,8 +670,9 @@ void reply_trans(connection_struct *conn, struct smb_request *req) Reply to a secondary SMBtrans. ****************************************************************************/ -void reply_transs(connection_struct *conn, struct smb_request *req) +void reply_transs(struct smb_request *req) { + connection_struct *conn = req->conn; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; int size; diff --git a/source3/smbd/message.c b/source3/smbd/message.c index d0b524da0e..a870f03df9 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -137,7 +137,7 @@ static void msg_deliver(struct msg_state *state) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_sends(connection_struct *conn, struct smb_request *req) +void reply_sends(struct smb_request *req) { struct msg_state *state; int len; @@ -190,7 +190,7 @@ void reply_sends(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_sendstrt(connection_struct *conn, struct smb_request *req) +void reply_sendstrt(struct smb_request *req) { char *p; @@ -234,7 +234,7 @@ void reply_sendstrt(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_sendtxt(connection_struct *conn, struct smb_request *req) +void reply_sendtxt(struct smb_request *req) { int len; char *msg; @@ -287,7 +287,7 @@ void reply_sendtxt(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_sendend(connection_struct *conn, struct smb_request *req) +void reply_sendend(struct smb_request *req) { START_PROFILE(SMBsendend); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 02f752fd67..9f56949eeb 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -505,7 +505,7 @@ static const struct { conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_negprot(connection_struct *conn, struct smb_request *req) +void reply_negprot(struct smb_request *req) { size_t size = smb_len(req->inbuf) + 4; int choice= -1; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8ac0217dcd..a51f3afd82 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -413,8 +413,9 @@ static void do_ntcreate_pipe_open(connection_struct *conn, Reply to an NT create and X call. ****************************************************************************/ -void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req) +void reply_ntcreate_and_X(struct smb_request *req) { + connection_struct *conn = req->conn; char *fname = NULL; uint32 flags; uint32 access_mask; @@ -1093,7 +1094,7 @@ static void call_nt_transact_create(connection_struct *conn, conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_ntcancel(connection_struct *conn, struct smb_request *req) +void reply_ntcancel(struct smb_request *req) { /* * Go through and cancel any pending change notifies. @@ -1255,8 +1256,9 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, Reply to a NT rename request. ****************************************************************************/ -void reply_ntrename(connection_struct *conn, struct smb_request *req) +void reply_ntrename(struct smb_request *req) { + connection_struct *conn = req->conn; char *oldname = NULL; char *newname = NULL; char *p; @@ -2578,8 +2580,9 @@ static void handle_nttrans(connection_struct *conn, Reply to a SMBNTtrans. ****************************************************************************/ -void reply_nttrans(connection_struct *conn, struct smb_request *req) +void reply_nttrans(struct smb_request *req) { + connection_struct *conn = req->conn; uint32 pscnt; uint32 psoff; uint32 dscnt; @@ -2769,8 +2772,9 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req) Reply to a SMBnttranss ****************************************************************************/ -void reply_nttranss(connection_struct *conn, struct smb_request *req) +void reply_nttranss(struct smb_request *req) { + connection_struct *conn = req->conn; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 32d1d058e3..fe32d57ff7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1045,7 +1045,7 @@ force write permissions on print services. */ static const struct smb_message_struct { const char *name; - void (*fn_new)(connection_struct *conn, struct smb_request *req); + void (*fn_new)(struct smb_request *req); int flags; } smb_messages[256] = { @@ -1525,7 +1525,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in return conn; } - smb_messages[type].fn_new(conn, req); + smb_messages[type].fn_new(req); return req->conn; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b6efccdb15..d5e683ca3c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -479,8 +479,9 @@ void reply_special(char *inbuf) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_tcon(connection_struct *conn, struct smb_request *req) +void reply_tcon(struct smb_request *req) { + connection_struct *conn = req->conn; const char *service; char *service_buf = NULL; char *password = NULL; @@ -550,8 +551,9 @@ void reply_tcon(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) +void reply_tcon_and_X(struct smb_request *req) { + connection_struct *conn = req->conn; char *service = NULL; DATA_BLOB password; TALLOC_CTX *ctx = talloc_tos(); @@ -580,6 +582,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) if ((tcon_flags & 0x1) && conn) { close_cnum(conn,req->vuid); req->conn = NULL; + conn = NULL; } if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) { @@ -734,17 +737,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req) Reply to an unknown type. ****************************************************************************/ -int reply_unknown(char *inbuf,char *outbuf) -{ - int type; - type = CVAL(inbuf,smb_com); - - DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n", - smb_fn_name(type), type, type)); - - return(ERROR_DOS(ERRSRV,ERRunknownsmb)); -} - void reply_unknown_new(struct smb_request *req, uint8 type) { DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n", @@ -758,8 +750,9 @@ void reply_unknown_new(struct smb_request *req, uint8 type) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_ioctl(connection_struct *conn, struct smb_request *req) +void reply_ioctl(struct smb_request *req) { + connection_struct *conn = req->conn; uint16 device; uint16 function; uint32 ioctl_code; @@ -847,8 +840,9 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status) Reply to a checkpath. ****************************************************************************/ -void reply_checkpath(connection_struct *conn, struct smb_request *req) +void reply_checkpath(struct smb_request *req) { + connection_struct *conn = req->conn; char *name = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; @@ -941,8 +935,9 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req) Reply to a getatr. ****************************************************************************/ -void reply_getatr(connection_struct *conn, struct smb_request *req) +void reply_getatr(struct smb_request *req) { + connection_struct *conn = req->conn; char *fname = NULL; SMB_STRUCT_STAT sbuf; int mode=0; @@ -1042,8 +1037,9 @@ void reply_getatr(connection_struct *conn, struct smb_request *req) Reply to a setatr. ****************************************************************************/ -void reply_setatr(connection_struct *conn, struct smb_request *req) +void reply_setatr(struct smb_request *req) { + connection_struct *conn = req->conn; char *fname = NULL; int mode; time_t mtime; @@ -1142,8 +1138,9 @@ void reply_setatr(connection_struct *conn, struct smb_request *req) Reply to a dskattr. ****************************************************************************/ -void reply_dskattr(connection_struct *conn, struct smb_request *req) +void reply_dskattr(struct smb_request *req) { + connection_struct *conn = req->conn; SMB_BIG_UINT dfree,dsize,bsize; START_PROFILE(SMBdskattr); @@ -1194,8 +1191,9 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req) Can be called from SMBsearch, SMBffirst or SMBfunique. ****************************************************************************/ -void reply_search(connection_struct *conn, struct smb_request *req) +void reply_search(struct smb_request *req) { + connection_struct *conn = req->conn; char *mask = NULL; char *directory = NULL; char *fname = NULL; @@ -1496,7 +1494,7 @@ void reply_search(connection_struct *conn, struct smb_request *req) Reply to a fclose (stop directory search). ****************************************************************************/ -void reply_fclose(connection_struct *conn, struct smb_request *req) +void reply_fclose(struct smb_request *req) { int status_len; char status[21]; @@ -1560,8 +1558,9 @@ void reply_fclose(connection_struct *conn, struct smb_request *req) Reply to an open. ****************************************************************************/ -void reply_open(connection_struct *conn, struct smb_request *req) +void reply_open(struct smb_request *req) { + connection_struct *conn = req->conn; char *fname = NULL; uint32 fattr=0; SMB_OFF_T size = 0; @@ -1676,8 +1675,9 @@ void reply_open(connection_struct *conn, struct smb_request *req) Reply to an open and X. ****************************************************************************/ -void reply_open_and_X(connection_struct *conn, struct smb_request *req) +void reply_open_and_X(struct smb_request *req) { + connection_struct *conn = req->conn; char *fname = NULL; uint16 open_flags; int deny_mode; @@ -1864,10 +1864,9 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req) /**************************************************************************** Reply to a SMBulogoffX. - conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_ulogoffX(connection_struct *conn, struct smb_request *req) +void reply_ulogoffX(struct smb_request *req) { user_struct *vuser; @@ -1900,8 +1899,9 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req) Reply to a mknew or a create. ****************************************************************************/ -void reply_mknew(connection_struct *conn, struct smb_request *req) +void reply_mknew(struct smb_request *req) { + connection_struct *conn = req->conn; char *fname = NULL; int com; uint32 fattr = 0; @@ -2009,8 +2009,9 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) Reply to a create temporary file. ****************************************************************************/ -void reply_ctemp(connection_struct *conn, struct smb_request *req) +void reply_ctemp(struct smb_request *req) { + connection_struct *conn = req->conn; char *fname = NULL; uint32 fattr; files_struct *fsp; @@ -2475,8 +2476,9 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, Reply to a unlink ****************************************************************************/ -void reply_unlink(connection_struct *conn, struct smb_request *req) +void reply_unlink(struct smb_request *req) { + connection_struct *conn = req->conn; char *name = NULL; uint32 dirtype; NTSTATUS status; @@ -2717,8 +2719,9 @@ normal_readbraw: Reply to a readbraw (core+ protocol). ****************************************************************************/ -void reply_readbraw(connection_struct *conn, struct smb_request *req) +void reply_readbraw(struct smb_request *req) { + connection_struct *conn = req->conn; ssize_t maxcount,mincount; size_t nread = 0; SMB_OFF_T startpos; @@ -2867,8 +2870,9 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req) Reply to a lockread (core+ protocol). ****************************************************************************/ -void reply_lockread(connection_struct *conn, struct smb_request *req) +void reply_lockread(struct smb_request *req) { + connection_struct *conn = req->conn; ssize_t nread = -1; char *data; SMB_OFF_T startpos; @@ -2976,8 +2980,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Reply to a read. ****************************************************************************/ -void reply_read(connection_struct *conn, struct smb_request *req) +void reply_read(struct smb_request *req) { + connection_struct *conn = req->conn; size_t numtoread; ssize_t nread = 0; char *data; @@ -3221,8 +3226,9 @@ normal_read: Reply to a read and X. ****************************************************************************/ -void reply_read_and_X(connection_struct *conn, struct smb_request *req) +void reply_read_and_X(struct smb_request *req) { + connection_struct *conn = req->conn; files_struct *fsp; SMB_OFF_T startpos; size_t smb_maxcnt; @@ -3350,8 +3356,9 @@ void error_to_writebrawerr(struct smb_request *req) Reply to a writebraw (core+ or LANMAN1.0 protocol). ****************************************************************************/ -void reply_writebraw(connection_struct *conn, struct smb_request *req) +void reply_writebraw(struct smb_request *req) { + connection_struct *conn = req->conn; int outsize = 0; char *buf = NULL; ssize_t nwritten=0; @@ -3579,8 +3586,9 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) Reply to a writeunlock (core+). ****************************************************************************/ -void reply_writeunlock(connection_struct *conn, struct smb_request *req) +void reply_writeunlock(struct smb_request *req) { + connection_struct *conn = req->conn; ssize_t nwritten = -1; size_t numtowrite; SMB_OFF_T startpos; @@ -3678,8 +3686,9 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req) Reply to a write. ****************************************************************************/ -void reply_write(connection_struct *conn, struct smb_request *req) +void reply_write(struct smb_request *req) { + connection_struct *conn = req->conn; size_t numtowrite; ssize_t nwritten = -1; SMB_OFF_T startpos; @@ -3866,8 +3875,9 @@ bool is_valid_writeX_buffer(const uint8_t *inbuf) Reply to a write and X. ****************************************************************************/ -void reply_write_and_X(connection_struct *conn, struct smb_request *req) +void reply_write_and_X(struct smb_request *req) { + connection_struct *conn = req->conn; files_struct *fsp; SMB_OFF_T startpos; size_t numtowrite; @@ -4034,8 +4044,9 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req) Reply to a lseek. ****************************************************************************/ -void reply_lseek(connection_struct *conn, struct smb_request *req) +void reply_lseek(struct smb_request *req) { + connection_struct *conn = req->conn; SMB_OFF_T startpos; SMB_OFF_T res= -1; int mode,umode; @@ -4121,8 +4132,9 @@ void reply_lseek(connection_struct *conn, struct smb_request *req) Reply to a flush. ****************************************************************************/ -void reply_flush(connection_struct *conn, struct smb_request *req) +void reply_flush(struct smb_request *req) { + connection_struct *conn = req->conn; uint16 fnum; files_struct *fsp; @@ -4165,7 +4177,7 @@ void reply_flush(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_exit(connection_struct *conn, struct smb_request *req) +void reply_exit(struct smb_request *req) { START_PROFILE(SMBexit); @@ -4183,8 +4195,9 @@ void reply_exit(connection_struct *conn, struct smb_request *req) Reply to a close - has to deal with closing a directory opened by NT SMB's. ****************************************************************************/ -void reply_close(connection_struct *conn, struct smb_request *req) +void reply_close(struct smb_request *req) { + connection_struct *conn = req->conn; NTSTATUS status = NT_STATUS_OK; files_struct *fsp = NULL; START_PROFILE(SMBclose); @@ -4261,8 +4274,9 @@ void reply_close(connection_struct *conn, struct smb_request *req) Reply to a writeclose (Core+ protocol). ****************************************************************************/ -void reply_writeclose(connection_struct *conn, struct smb_request *req) +void reply_writeclose(struct smb_request *req) { + connection_struct *conn = req->conn; size_t numtowrite; ssize_t nwritten = -1; NTSTATUS close_status = NT_STATUS_OK; @@ -4350,8 +4364,9 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req) Reply to a lock. ****************************************************************************/ -void reply_lock(connection_struct *conn, struct smb_request *req) +void reply_lock(struct smb_request *req) { + connection_struct *conn = req->conn; SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp; @@ -4409,8 +4424,9 @@ void reply_lock(connection_struct *conn, struct smb_request *req) Reply to a unlock. ****************************************************************************/ -void reply_unlock(connection_struct *conn, struct smb_request *req) +void reply_unlock(struct smb_request *req) { + connection_struct *conn = req->conn; SMB_BIG_UINT count,offset; NTSTATUS status; files_struct *fsp; @@ -4463,8 +4479,9 @@ void reply_unlock(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_tdis(connection_struct *conn, struct smb_request *req) +void reply_tdis(struct smb_request *req) { + connection_struct *conn = req->conn; START_PROFILE(SMBtdis); if (!conn) { @@ -4489,8 +4506,9 @@ void reply_tdis(connection_struct *conn, struct smb_request *req) conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -void reply_echo(connection_struct *conn, struct smb_request *req) +void reply_echo(struct smb_request *req) { + connection_struct *conn = req->conn; int smb_reverb; int seq_num; unsigned int data_len = smb_buflen(req->inbuf); @@ -4548,8 +4566,9 @@ void reply_echo(connection_struct *conn, struct smb_request *req) Reply to a printopen. ****************************************************************************/ -void reply_printopen(connection_struct *conn, struct smb_request *req) +void reply_printopen(struct smb_request *req) { + connection_struct *conn = req->conn; files_struct *fsp; NTSTATUS status; @@ -4590,8 +4609,9 @@ void reply_printopen(connection_struct *conn, struct smb_request *req) Reply to a printclose. ****************************************************************************/ -void reply_printclose(connection_struct *conn, struct smb_request *req) +void reply_printclose(struct smb_request *req) { + connection_struct *conn = req->conn; files_struct *fsp; NTSTATUS status; @@ -4635,8 +4655,9 @@ void reply_printclose(connection_struct *conn, struct smb_request *req) Reply to a printqueue. ****************************************************************************/ -void reply_printqueue(connection_struct *conn, struct smb_request *req) +void reply_printqueue(struct smb_request *req) { + connection_struct *conn = req->conn; int max_count; int start_index; @@ -4727,8 +4748,9 @@ void reply_printqueue(connection_struct *conn, struct smb_request *req) Reply to a printwrite. ****************************************************************************/ -void reply_printwrite(connection_struct *conn, struct smb_request *req) +void reply_printwrite(struct smb_request *req) { + connection_struct *conn = req->conn; int numtowrite; char *data; files_struct *fsp; @@ -4786,8 +4808,9 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req) Reply to a mkdir. ****************************************************************************/ -void reply_mkdir(connection_struct *conn, struct smb_request *req) +void reply_mkdir(struct smb_request *req) { + connection_struct *conn = req->conn; char *directory = NULL; NTSTATUS status; SMB_STRUCT_STAT sbuf; @@ -5054,8 +5077,9 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, Reply to a rmdir. ****************************************************************************/ -void reply_rmdir(connection_struct *conn, struct smb_request *req) +void reply_rmdir(struct smb_request *req) { + connection_struct *conn = req->conn; char *directory = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; @@ -5838,8 +5862,9 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, Reply to a mv. ****************************************************************************/ -void reply_mv(connection_struct *conn, struct smb_request *req) +void reply_mv(struct smb_request *req) { + connection_struct *conn = req->conn; char *name = NULL; char *newname = NULL; char *p; @@ -6069,8 +6094,9 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, Reply to a file copy. ****************************************************************************/ -void reply_copy(connection_struct *conn, struct smb_request *req) +void reply_copy(struct smb_request *req) { + connection_struct *conn = req->conn; char *name = NULL; char *newname = NULL; char *directory = NULL; @@ -6532,8 +6558,9 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_forma Reply to a lockingX request. ****************************************************************************/ -void reply_lockingX(connection_struct *conn, struct smb_request *req) +void reply_lockingX(struct smb_request *req) { + connection_struct *conn = req->conn; files_struct *fsp; unsigned char locktype; unsigned char oplocklevel; @@ -6890,7 +6917,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req) please contact vl@samba.org ****************************************************************************/ -void reply_readbmpx(connection_struct *conn, struct smb_request *req) +void reply_readbmpx(struct smb_request *req) { START_PROFILE(SMBreadBmpx); reply_doserror(req, ERRSRV, ERRuseSTD); @@ -6904,7 +6931,7 @@ void reply_readbmpx(connection_struct *conn, struct smb_request *req) please contact vl@samba.org ****************************************************************************/ -void reply_readbs(connection_struct *conn, struct smb_request *req) +void reply_readbs(struct smb_request *req) { START_PROFILE(SMBreadBs); reply_doserror(req, ERRSRV, ERRuseSTD); @@ -6916,8 +6943,9 @@ void reply_readbs(connection_struct *conn, struct smb_request *req) Reply to a SMBsetattrE. ****************************************************************************/ -void reply_setattrE(connection_struct *conn, struct smb_request *req) +void reply_setattrE(struct smb_request *req) { + connection_struct *conn = req->conn; struct timespec ts[2]; files_struct *fsp; @@ -6994,7 +7022,7 @@ void reply_setattrE(connection_struct *conn, struct smb_request *req) please contact vl@samba.org ****************************************************************************/ -void reply_writebmpx(connection_struct *conn, struct smb_request *req) +void reply_writebmpx(struct smb_request *req) { START_PROFILE(SMBwriteBmpx); reply_doserror(req, ERRSRV, ERRuseSTD); @@ -7008,7 +7036,7 @@ void reply_writebmpx(connection_struct *conn, struct smb_request *req) please contact vl@samba.org ****************************************************************************/ -void reply_writebs(connection_struct *conn, struct smb_request *req) +void reply_writebs(struct smb_request *req) { START_PROFILE(SMBwriteBs); reply_doserror(req, ERRSRV, ERRuseSTD); @@ -7020,8 +7048,9 @@ void reply_writebs(connection_struct *conn, struct smb_request *req) Reply to a SMBgetattrE. ****************************************************************************/ -void reply_getattrE(connection_struct *conn, struct smb_request *req) +void reply_getattrE(struct smb_request *req) { + connection_struct *conn = req->conn; SMB_STRUCT_STAT sbuf; int mode; files_struct *fsp; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e44a540554..167682ede2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -118,8 +118,7 @@ static void sessionsetup_start_signing_engine( Send a security blob via a session setup reply. ****************************************************************************/ -static void reply_sesssetup_blob(connection_struct *conn, - struct smb_request *req, +static void reply_sesssetup_blob(struct smb_request *req, DATA_BLOB blob, NTSTATUS nt_status) { @@ -247,8 +246,7 @@ static bool make_krb5_skew_error(DATA_BLOB *pblob_out) Reply to a session setup spnego negotiate packet for kerberos. ****************************************************************************/ -static void reply_spnego_kerberos(connection_struct *conn, - struct smb_request *req, +static void reply_spnego_kerberos(struct smb_request *req, DATA_BLOB *secblob, uint16 vuid, bool *p_invalidate_vuid) @@ -605,7 +603,7 @@ static void reply_spnego_kerberos(connection_struct *conn, } response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); - reply_sesssetup_blob(conn, req, response, ret); + reply_sesssetup_blob(req, response, ret); data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); @@ -623,8 +621,7 @@ static void reply_spnego_kerberos(connection_struct *conn, leg of the NTLM auth steps. ***************************************************************************/ -static void reply_spnego_ntlmssp(connection_struct *conn, - struct smb_request *req, +static void reply_spnego_ntlmssp(struct smb_request *req, uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, @@ -693,7 +690,7 @@ static void reply_spnego_ntlmssp(connection_struct *conn, response = *ntlmssp_blob; } - reply_sesssetup_blob(conn, req, response, nt_status); + reply_sesssetup_blob(req, response, nt_status); if (wrap) { data_blob_free(&response); } @@ -756,8 +753,7 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, Reply to a session setup spnego negotiate packet. ****************************************************************************/ -static void reply_spnego_negotiate(connection_struct *conn, - struct smb_request *req, +static void reply_spnego_negotiate(struct smb_request *req, uint16 vuid, DATA_BLOB blob1, AUTH_NTLMSSP_STATE **auth_ntlmssp_state) @@ -783,7 +779,7 @@ static void reply_spnego_negotiate(connection_struct *conn, if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { bool destroy_vuid = True; - reply_spnego_kerberos(conn, req, &secblob, vuid, + reply_spnego_kerberos(req, &secblob, vuid, &destroy_vuid); data_blob_free(&secblob); if (destroy_vuid) { @@ -811,7 +807,7 @@ static void reply_spnego_negotiate(connection_struct *conn, data_blob_free(&secblob); - reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state, + reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state, &chal, status, True); data_blob_free(&chal); @@ -824,8 +820,7 @@ static void reply_spnego_negotiate(connection_struct *conn, Reply to a session setup spnego auth packet. ****************************************************************************/ -static void reply_spnego_auth(connection_struct *conn, - struct smb_request *req, +static void reply_spnego_auth(struct smb_request *req, uint16 vuid, DATA_BLOB blob1, AUTH_NTLMSSP_STATE **auth_ntlmssp_state) @@ -860,7 +855,7 @@ static void reply_spnego_auth(connection_struct *conn, if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { bool destroy_vuid = True; - reply_spnego_kerberos(conn, req, &secblob, + reply_spnego_kerberos(req, &secblob, vuid, &destroy_vuid); data_blob_free(&secblob); data_blob_free(&auth); @@ -892,7 +887,7 @@ static void reply_spnego_auth(connection_struct *conn, data_blob_free(&auth); - reply_spnego_ntlmssp(conn, req, vuid, + reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state, &auth_reply, status, True); @@ -1104,8 +1099,7 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, conn POINTER CAN BE NULL HERE ! ****************************************************************************/ -static void reply_sesssetup_and_X_spnego(connection_struct *conn, - struct smb_request *req) +static void reply_sesssetup_and_X_spnego(struct smb_request *req) { uint8 *p; DATA_BLOB blob1; @@ -1225,7 +1219,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, /* its a negTokenTarg packet */ - reply_spnego_negotiate(conn, req, vuid, blob1, + reply_spnego_negotiate(req, vuid, blob1, &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return; @@ -1235,7 +1229,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, /* its a auth packet */ - reply_spnego_auth(conn, req, vuid, blob1, + reply_spnego_auth(req, vuid, blob1, &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return; @@ -1260,7 +1254,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn, data_blob_free(&blob1); - reply_spnego_ntlmssp(conn, req, vuid, + reply_spnego_ntlmssp(req, vuid, &vuser->auth_ntlmssp_state, &chal, status, False); data_blob_free(&chal); @@ -1326,7 +1320,7 @@ static void setup_new_vc_session(void) Reply to a session setup command. ****************************************************************************/ -void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) +void reply_sesssetup_and_X(struct smb_request *req) { int sess_vuid; int smb_bufsize; @@ -1377,7 +1371,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req) setup_new_vc_session(); } - reply_sesssetup_and_X_spnego(conn, req); + reply_sesssetup_and_X_spnego(req); END_PROFILE(SMBsesssetupX); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4e2cceca36..c3b5f9fa2f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7001,7 +7001,7 @@ static void call_trans2ioctl(connection_struct *conn, Reply to a SMBfindclose (stop trans2 directory search). ****************************************************************************/ -void reply_findclose(connection_struct *conn, struct smb_request *req) +void reply_findclose(struct smb_request *req) { int dptr_num; @@ -7031,7 +7031,7 @@ void reply_findclose(connection_struct *conn, struct smb_request *req) Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search). ****************************************************************************/ -void reply_findnclose(connection_struct *conn, struct smb_request *req) +void reply_findnclose(struct smb_request *req) { int dptr_num; @@ -7225,8 +7225,9 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req, Reply to a SMBtrans2. ****************************************************************************/ -void reply_trans2(connection_struct *conn, struct smb_request *req) +void reply_trans2(struct smb_request *req) { + connection_struct *conn = req->conn; unsigned int dsoff; unsigned int dscnt; unsigned int psoff; @@ -7414,8 +7415,9 @@ void reply_trans2(connection_struct *conn, struct smb_request *req) Reply to a SMBtranss2 ****************************************************************************/ -void reply_transs2(connection_struct *conn, struct smb_request *req) +void reply_transs2(struct smb_request *req) { + connection_struct *conn = req->conn; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; int size; -- cgit From d5bd2e7000592b8256b837415c40e20f319fb07b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 22:56:06 -0800 Subject: Can't use logical operations on boolean values. Jeremy. (This used to be commit 34cd9b5b51a4209b4d970eb90bf1db0eb24a60bb) --- source3/smbd/sesssetup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 167682ede2..bc1d26faca 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -537,7 +537,9 @@ static void reply_spnego_kerberos(struct smb_request *req, } } - server_info->was_mapped |= username_was_mapped; + if (username_was_mapped) { + server_info->was_mapped = username_was_mapped; + } /* we need to build the token for the user. make_server_info_guest() already does this */ -- cgit From c6a2292724036340f766d774e64d6738d702478d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 23:17:38 -0800 Subject: Using a bool with a logical operation. IBM checker caught. Jeremy. (This used to be commit 7f9fe7da1e25bcc730f4c4226bf77f6d39b5ace4) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e3fae02b83..f178102fdd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1405,7 +1405,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } #endif /* O_SYNC */ - if (posix_open & (access_mask & FILE_APPEND_DATA)) { + if (posix_open && (access_mask & FILE_APPEND_DATA)) { flags2 |= O_APPEND; } -- cgit From 4a413e4bd177402a1697cffac43d35e94cc55102 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 5 Jan 2008 01:17:33 -0800 Subject: Fix %d / size_t printf arg missmatch. Jeremy. (This used to be commit 3e3205309b75edf7d29633525adfdceb5f8856eb) --- source3/smbd/blocking.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 41963166f7..4e0d5289f8 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -238,9 +238,9 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, set_lock_msg = True; } - DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with " + DEBUG(3,("push_blocking_lock_request: lock request length=%u blocked with " "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n", - length, (unsigned int)blr->expire_time.tv_sec, + (unsigned int)length, (unsigned int)blr->expire_time.tv_sec, (unsigned int)blr->expire_time.tv_usec, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); -- cgit From ee24c629a68e13764f78064121a6aea3d0e9240c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 5 Jan 2008 02:16:15 +0100 Subject: Remove superfluous fd parameter from SMB_VFS_FGET_NT_ACL(). Michael (This used to be commit c0c7c1223da29c68359dac64a340c1c710d5f3d2) --- source3/smbd/dir.c | 4 ++-- source3/smbd/nttrans.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ccf91fe57d..ab6e12f20f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -948,7 +948,7 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S } /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - status = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, + status = SMB_VFS_FGET_NT_ACL(fsp, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, NORMAL_CLOSE); @@ -1007,7 +1007,7 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ } /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - status = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, + status = SMB_VFS_FGET_NT_ACL(fsp, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, NORMAL_CLOSE); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a51f3afd82..e7f9f0d36c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1643,7 +1643,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, } else { if (fsp->fh->fd != -1) { status = SMB_VFS_FGET_NT_ACL( - fsp, fsp->fh->fd, security_info_wanted, &psd); + fsp, security_info_wanted, &psd); } else { status = SMB_VFS_GET_NT_ACL( -- cgit From 05352cf2cb7f9710444d340f3f14ac6917fb0416 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 6 Jan 2008 18:48:02 +0100 Subject: Remove superfluous parameter fd from SMB_VFS_FSET_NT_ACL(). Michael (This used to be commit 4f2d139a186048f08180378a877b69d2f80ad51f) --- source3/smbd/nttrans.c | 3 +-- source3/smbd/open.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e7f9f0d36c..ae64c06215 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -769,8 +769,7 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, } if (fsp->fh->fd != -1) { - status = SMB_VFS_FSET_NT_ACL(fsp, fsp->fh->fd, - security_info_sent, psd); + status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd); } else { status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f178102fdd..23d0223446 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2621,8 +2621,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, fsp->access_mask = FILE_GENERIC_ALL; - status = SMB_VFS_FSET_NT_ACL( - fsp, fsp->fh->fd, sec_info_sent, sd); + status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd); fsp->access_mask = saved_access_mask; -- cgit From ca275e254985727c50b1b988c958a3743a7bc8ce Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 00:14:19 +0100 Subject: Remove unneeded parameter fd from SMB_VFS_PREAD(). Michael (This used to be commit 73e28806ce87d829ea7c38ed3440020845bb13bf) --- source3/smbd/fileio.c | 4 ++-- source3/smbd/vfs.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 8037510d80..a648326f89 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -77,7 +77,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #ifdef DMF_FIX int numretries = 3; tryagain: - readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos); + readret = SMB_VFS_PREAD(fsp,data,n,pos); if (readret == -1) { if ((errno == EAGAIN) && numretries) { @@ -89,7 +89,7 @@ tryagain: return -1; } #else /* NO DMF fix. */ - readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos); + readret = SMB_VFS_PREAD(fsp,data,n,pos); if (readret == -1) { return -1; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index ed0406211d..bc272914c7 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -411,7 +411,7 @@ ssize_t vfs_pread_data(files_struct *fsp, char *buf, while (total < byte_count) { - ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fh->fd, buf + total, + ssize_t ret = SMB_VFS_PREAD(fsp, buf + total, byte_count - total, offset + total); if (ret == 0) return total; -- cgit From a56b417809805f8872c1e3238cce5d006d6189e4 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 09:23:04 +0100 Subject: Remove redundant parameter fd from SMB_VFS_PWRITE(). Michael (This used to be commit 8c4901a19ae2fd3ee085f9499f33aa7db016d182) --- source3/smbd/vfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index bc272914c7..aa914797d1 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -485,8 +485,8 @@ ssize_t vfs_pwrite_data(struct smb_request *req, } while (total < N) { - ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total, - N - total, offset + total); + ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total, + offset + total); if (ret == -1) return -1; @@ -641,7 +641,7 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) while (total < num_to_write) { size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total)); - pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, sparse_buf, curr_write_size, offset + total); + pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total); if (pwrite_ret == -1) { DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n", fsp->fsp_name, strerror(errno) )); -- cgit From 6f657c873efa4779e762a8f9ede97e19da6fb7ec Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 10:15:08 +0100 Subject: Remove redundant parameter fd from SMB_VFS_LSEEK(). Michael (This used to be commit df929796f2698698d2875227bda8500589cca2df) --- source3/smbd/reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d5e683ca3c..910e3a27a6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4091,7 +4091,7 @@ void reply_lseek(struct smb_request *req) } if (umode == SEEK_END) { - if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) { + if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) { if(errno == EINVAL) { SMB_OFF_T current_pos = startpos; SMB_STRUCT_STAT sbuf; @@ -4105,7 +4105,7 @@ void reply_lseek(struct smb_request *req) current_pos += sbuf.st_size; if(current_pos < 0) - res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET); + res = SMB_VFS_LSEEK(fsp,0,SEEK_SET); } } @@ -6052,7 +6052,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, } if ((ofun&3) == 1) { - if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) { + if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); /* * Stop the copy from occurring. -- cgit From 8dcce0d236b2102ca94fbcb7aa7126fe6733f2e7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 12:49:02 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FSYNC(). Michael (This used to be commit 8f83c9a7b245dbfef28195f9a7f33047a8ba95a0) --- source3/smbd/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index a648326f89..5a4263739b 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -879,7 +879,7 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug if (ret == -1) { return map_nt_error_from_unix(errno); } - ret = SMB_VFS_FSYNC(fsp,fsp->fh->fd); + ret = SMB_VFS_FSYNC(fsp); if (ret == -1) { return map_nt_error_from_unix(errno); } -- cgit From 87a684f7fcfa8d9fabc42e33981299d0b33eeeb7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 13:21:26 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FSTAT(). Michael (This used to be commit 0b86c420be94d295f6917a220b5d699f65b46711) --- source3/smbd/fileio.c | 4 ++-- source3/smbd/open.c | 6 +++--- source3/smbd/posix_acls.c | 6 +++--- source3/smbd/reply.c | 8 ++++---- source3/smbd/trans2.c | 4 ++-- source3/smbd/vfs.c | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 5a4263739b..1258b73cad 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -229,7 +229,7 @@ ssize_t write_file(struct smb_request *req, SMB_STRUCT_STAT st; fsp->modified = True; - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { + if (SMB_VFS_FSTAT(fsp, &st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && @@ -896,6 +896,6 @@ int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) if (fsp->fh->fd == -1) { return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst); } else { - return SMB_VFS_FSTAT(fsp,fsp->fh->fd, pst); + return SMB_VFS_FSTAT(fsp, pst); } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 23d0223446..d870374835 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -342,7 +342,7 @@ static NTSTATUS open_file(files_struct *fsp, if (fsp->fh->fd == -1) { ret = SMB_VFS_STAT(conn, path, psbuf); } else { - ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf); + ret = SMB_VFS_FSTAT(fsp, psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) { DEBUG(0,("Error doing fstat on open file %s " @@ -1790,7 +1790,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * struct.. */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || - (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { + (SMB_VFS_FSTAT(fsp, psbuf)==-1)) { status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); fd_close(fsp); @@ -2675,7 +2675,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, *psbuf = sbuf; } else { - SMB_VFS_FSTAT(fsp, fsp->fh->fd, psbuf); + SMB_VFS_FSTAT(fsp, psbuf); } } return NT_STATUS_OK; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2810b5e587..f11aa69e08 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3080,7 +3080,7 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, } /* Get the stat struct for the owner info. */ - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { + if(SMB_VFS_FSTAT(fsp, &sbuf) != 0) { return map_nt_error_from_unix(errno); } @@ -3429,7 +3429,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) return map_nt_error_from_unix(errno); } else { - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) + if(SMB_VFS_FSTAT(fsp, &sbuf) != 0) return map_nt_error_from_unix(errno); } @@ -3479,7 +3479,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(fsp->fh->fd == -1) ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf); else - ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf); + ret = SMB_VFS_FSTAT(fsp, &sbuf); if(ret != 0) return map_nt_error_from_unix(errno); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 910e3a27a6..27f380a627 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2835,7 +2835,7 @@ void reply_readbraw(struct smb_request *req) return; } - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { + if (SMB_VFS_FSTAT(fsp, &st) == 0) { size = st.st_size; } @@ -3096,7 +3096,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, SMB_STRUCT_STAT sbuf; ssize_t nread = -1; - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { + if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); return; } @@ -4096,7 +4096,7 @@ void reply_lseek(struct smb_request *req) SMB_OFF_T current_pos = startpos; SMB_STRUCT_STAT sbuf; - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) { + if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBlseek); @@ -5485,7 +5485,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, /* Ensure we have a valid stat struct for the source. */ if (fsp->fh->fd != -1) { - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) { + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { return map_nt_error_from_unix(errno); } } else { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c3b5f9fa2f..ab6706aec7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3663,7 +3663,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); reply_unixerror(req, ERRDOS, ERRbadfid); return; @@ -6346,7 +6346,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); reply_unixerror(req, ERRDOS, ERRbadfid); return; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index aa914797d1..c7edac7b7a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -525,7 +525,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) return -1; } - ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st); + ret = SMB_VFS_FSTAT(fsp, &st); if (ret == -1) return ret; @@ -612,7 +612,7 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) ssize_t pwrite_ret; release_level_2_oplocks_on_change(fsp); - ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st); + ret = SMB_VFS_FSTAT(fsp, &st); if (ret == -1) { return ret; } -- cgit From e614dec27f33c932c6c29c806d567fd6015cd5e6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 13:44:37 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FCHMOD(). Michael (This used to be commit a54d5604da556d1250ca9948d4acc4a187a9fede) --- source3/smbd/dosmode.c | 2 +- source3/smbd/open.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index a96f80ee0e..d3813f9b41 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -538,7 +538,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp))) return -1; become_root(); - ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); + ret = SMB_VFS_FCHMOD(fsp, unixmode); unbecome_root(); close_file_fchmod(fsp); if (!newfile) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d870374835..c7b053d531 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1915,7 +1915,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if ((ret == -1) && - (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) + (SMB_VFS_FCHMOD(fsp, new_unx_mode) == -1)) DEBUG(5, ("open_file_ntcreate: failed to reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); -- cgit From 670909cb07e38a06bf5db12342b3b1189f0e1ab7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 14:26:00 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FCHOWN(). Michael (This used to be commit fbb193db3e0dc51cb000ae406a68bc547f31d9ab) --- source3/smbd/open.c | 2 +- source3/smbd/posix_acls.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c7b053d531..036e3e12a2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -102,7 +102,7 @@ static void change_file_owner_to_parent(connection_struct *conn, } become_root(); - ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { DEBUG(0,("change_file_owner_to_parent: failed to fchown " diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f11aa69e08..1aa3001923 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3194,7 +3194,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) become_root(); /* Keep the current file gid the same. */ - ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1); unbecome_root(); close_file_fchmod(fsp); -- cgit From b457b94bb86897b7020c6f300cd19a3d8e192610 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 15:55:09 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FTRUNCATE(). Michael (This used to be commit 2ad66050a0452b8e7e08b1e7a01efa00c72fd451) --- source3/smbd/fileio.c | 2 +- source3/smbd/open.c | 2 +- source3/smbd/vfs.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 1258b73cad..8cea4989f5 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -184,7 +184,7 @@ static int wcp_file_size_change(files_struct *fsp) write_cache *wcp = fsp->wcp; wcp->file_size = wcp->offset + wcp->data_size; - ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, wcp->file_size); + ret = SMB_VFS_FTRUNCATE(fsp, wcp->file_size); if (ret == -1) { DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f error %s\n", fsp->fsp_name, (double)wcp->file_size, strerror(errno) )); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 036e3e12a2..cc62e020da 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1789,7 +1789,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * We are modifing the file after open - update the stat * struct.. */ - if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || + if ((SMB_VFS_FTRUNCATE(fsp, 0) == -1) || (SMB_VFS_FSTAT(fsp, psbuf)==-1)) { status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index c7edac7b7a..9a5e0aff60 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -539,7 +539,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) fsp->fsp_name, (double)st.st_size )); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, (SMB_OFF_T)len)) != -1) { + if ((ret = SMB_VFS_FTRUNCATE(fsp, (SMB_OFF_T)len)) != -1) { set_filelen_write_cache(fsp, len); } return ret; @@ -581,7 +581,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1) { + if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) { set_filelen_write_cache(fsp, len); notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_SIZE -- cgit From 327cc04da587fa54f28dafb00267fde79b858349 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 17:14:20 +0100 Subject: Remove redundant parameter fd from SMB_VFS_KERNEL_FLOCK(). Michael (This used to be commit 195c519377c2fdc655e25760b52bc0694b8dda81) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cc62e020da..b618092a32 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1764,7 +1764,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, the kernel refuses the operations then the kernel is wrong. note that GPFS supports it as well - jmcd */ - ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); if(ret_flock == -1 ){ TALLOC_FREE(lck); -- cgit From 26169410cd3fa90be5740a913f027802488eca8d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 21:47:53 +0100 Subject: Remove redundant parameter fd from SMB_VFS_LINUX_SETLEASE(). Michael (This used to be commit 8880eb82f16d561a4023ec8426f8ea35c579a7a6) --- source3/smbd/oplock_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 086f105b89..05021b6c74 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -164,7 +164,7 @@ static files_struct *linux_oplock_receive_message(fd_set *fds) static bool linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { - if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_WRLCK) == -1) { + if ( SMB_VFS_LINUX_SETLEASE(fsp, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " "fd = %d, file_id = %s. (%s)\n", fsp->fsp_name, fsp->fh->fd, @@ -202,7 +202,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) /* * Remove the kernel oplock on this file. */ - if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_UNLCK) == -1) { + if ( SMB_VFS_LINUX_SETLEASE(fsp, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when " "removing kernel oplock on file " ); -- cgit From 62e9d503d82d645cf29af643732ad97c0eb8b340 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 23:53:34 +0100 Subject: Remove redundant parameter fd from SMB_VFS_SYS_ACL_GET_FD(). Michael (This used to be commit 42663e8736e1a3dfb57e0aafdcbf5fec880da779) --- source3/smbd/posix_acls.c | 8 ++++---- source3/smbd/trans2.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 1aa3001923..b07033b8ac 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3085,7 +3085,7 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, } /* Get the ACL from the fd. */ - posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); + posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp); pal = fload_inherited_info(fsp); @@ -3808,13 +3808,13 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fd)) == NULL) + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = SMB_VFS_SYS_ACL_SET_FD(fsp, fd, posix_acl); + ret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, posix_acl); done: @@ -4099,7 +4099,7 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c /* Get the current file ACL. */ if (fsp && fsp->fh->fd != -1) { - file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); + file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp); } else { file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ab6706aec7..611f803210 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4305,7 +4305,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd uint16 num_def_acls = 0; if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) { - file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); + file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp); } else { file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS); } -- cgit From b2182c11eab0e1b2f0acb5d82aec86d4598573eb Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 01:14:24 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FCHMOD_ACL(). Michael (This used to be commit 7b201c177b3668f54751ba17d6a0b53ed913e7f7) --- source3/smbd/open.c | 5 ++--- source3/smbd/posix_acls.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b618092a32..4abe017380 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1887,7 +1887,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ - if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 && + if (SMB_VFS_FCHMOD_ACL(fsp, unx_mode) == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } @@ -1901,8 +1901,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, { int saved_errno = errno; /* We might get ENOSYS in the * next call.. */ - ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, - new_unx_mode); + ret = SMB_VFS_FCHMOD_ACL(fsp, new_unx_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b07033b8ac..23a246fea7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3802,7 +3802,7 @@ int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir, and set the mask to rwx. Needed to preserve complex ACLs set by NT. ****************************************************************************/ -int fchmod_acl(files_struct *fsp, int fd, mode_t mode) +int fchmod_acl(files_struct *fsp, mode_t mode) { connection_struct *conn = fsp->conn; SMB_ACL_T posix_acl = NULL; -- cgit From 5921607f2647cec20a6bcebd17c5a0c53449c1ba Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 01:54:19 +0100 Subject: Remove redundant parameter fd from SMB_VFS_SYS_ACL_SET_FD(). Michael (This used to be commit 9296e93588c0e795cae770765050247ac1474a74) --- source3/smbd/posix_acls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 23a246fea7..b6cb1d2e54 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2573,7 +2573,7 @@ static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool defau } } } else { - if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2589,7 +2589,7 @@ static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool defau fsp->fsp_name )); become_root(); - sret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl); + sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl); unbecome_root(); if (sret == 0) { ret = True; @@ -3814,7 +3814,7 @@ int fchmod_acl(files_struct *fsp, mode_t mode) if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, posix_acl); + ret = SMB_VFS_SYS_ACL_SET_FD(fsp, posix_acl); done: @@ -4152,7 +4152,7 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c /* Set the new empty file ACL. */ if (fsp && fsp->fh->fd != -1) { - if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, new_file_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, new_file_acl) == -1) { DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n", fname, strerror(errno) )); goto done; @@ -4199,7 +4199,7 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * if (fsp && fsp->fh->fd != -1) { /* The preferred way - use an open fd. */ - if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, file_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, file_acl) == -1) { DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n", fname, strerror(errno) )); SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); -- cgit From 50ee744fa445b74136a8f2cef36c2b48ba7ee5f6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 10:00:47 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FGETXATTR(). Michael (This used to be commit 2cb739a82dc6bb194d60718cc74b26ee7c1c46a7) --- source3/smbd/posix_acls.c | 2 +- source3/smbd/trans2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b6cb1d2e54..be05ebd2ab 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -445,7 +445,7 @@ static struct pai_val *fload_inherited_info(files_struct *fsp) do { if (fsp->fh->fd != -1) - ret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, pai_buf_size); else ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 611f803210..42914298fa 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -130,7 +130,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str } if (fsp && fsp->fh->fd != -1) { - sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size); + sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size); } else { sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size); } -- cgit From 9f691df852581b1ae4fab7cb9907606f4dcab291 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 10:51:40 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FLISTXATTR(). Michael (This used to be commit 167649b3b8bc293f8434ffc9fb5f80463e4e75be) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 42914298fa..2958985b02 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -187,7 +187,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str } if (fsp && fsp->fh->fd != -1) { - sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size); + sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, ea_namelist_size); } else { sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size); } -- cgit From 1590dd32cfccd9ce73cd798330b5207bcc48bfaf Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 11:29:09 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FREMOVEXATTR(). Michael (This used to be commit bfc3b5a27f707d3e4b8d5d66192891e22365fbb3) --- source3/smbd/posix_acls.c | 2 +- source3/smbd/trans2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index be05ebd2ab..120e82c4b0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -229,7 +229,7 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) { /* Instead just remove the attribute if it exists. */ if (fsp->fh->fd != -1) - SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME); + SMB_VFS_FREMOVEXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME); else SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME); return; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2958985b02..c20d930433 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -355,7 +355,7 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s if (fsp && (fsp->fh->fd != -1)) { DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name); + ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name); } else { DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", unix_ea_name, fname)); -- cgit From aab6704ce803a738ba125895b20a31f242fe2885 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 11:47:33 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FSETXATTR(). Michael (This used to be commit 0bd2643463a9160c8a1c7e1c2f8cca7b89060e09) --- source3/smbd/posix_acls.c | 2 +- source3/smbd/trans2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 120e82c4b0..5f18615f66 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -238,7 +238,7 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_ pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size); if (fsp->fh->fd != -1) - ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, store_size, 0); else ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c20d930433..485513c734 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -373,7 +373,7 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s if (fsp && (fsp->fh->fd != -1)) { DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name, + ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name, ea_list->ea.value.data, ea_list->ea.value.length, 0); } else { DEBUG(10,("set_ea: setting ea name %s on file %s.\n", -- cgit From 4a056e127ac35d640d899cd8a4735b927aa8d005 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 12:20:51 +0100 Subject: Remove redundant parameter fd from SMB_VFS_AIO_CANCEL(). Michael (This used to be commit 3c997ae0002d4c50e8899600c17ddf74ac61f6f0) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index bc1761b0fd..c8175f77ac 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -746,7 +746,7 @@ void cancel_aio_by_fsp(files_struct *fsp) /* Don't delete the aio_extra record as we may have completed and don't yet know it. Just do the aio_cancel call and return. */ - SMB_VFS_AIO_CANCEL(fsp,fsp->fh->fd, &aio_ex->acb); + SMB_VFS_AIO_CANCEL(fsp, &aio_ex->acb); aio_ex->fsp = NULL; /* fsp will be closed when we * return. */ } -- cgit From 35c256226f7cbf1125ad7b6370eecdf09b3cfbc6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 8 Jan 2008 21:45:21 +0100 Subject: Allocate dirp->name_cache on demand only (This used to be commit 1a15778331393f9ece9aac9450828e799b20a058) --- source3/smbd/dir.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ab6e12f20f..04e3167e77 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1139,16 +1139,6 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *m goto fail; } - if (dirp->name_cache_size) { - dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, - dirp->name_cache_size); - if (!dirp->name_cache) { - goto fail; - } - } else { - dirp->name_cache = NULL; - } - dirhandles_open++; return dirp; @@ -1295,10 +1285,19 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) { struct name_cache_entry *e; - if (!dirp->name_cache_size || !dirp->name_cache) { + if (dirp->name_cache_size == 0) { return; } + if (dirp->name_cache == NULL) { + dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, + dirp->name_cache_size); + + if (dirp->name_cache == NULL) { + return; + } + } + dirp->name_cache_index = (dirp->name_cache_index+1) % dirp->name_cache_size; e = &dirp->name_cache[dirp->name_cache_index]; -- cgit From 80158198eee90cf05396989df068f77f8bb7e064 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jan 2008 15:57:08 -0800 Subject: Correctly identify enc/non-enc packets. Jeremy. (This used to be commit 647f13d0f1a270a68263b3b0403436f9d6cf1a0e) --- source3/smbd/seal.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 21fca73fea..51a5f23f03 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -53,8 +53,8 @@ bool is_encrypted_packet(const uint8_t *inbuf) NTSTATUS status; uint16_t enc_num; - /* Ignore non-session messages. */ - if(CVAL(inbuf,0)) { + /* Ignore non-session messages or 0xFF'SMB' messages. */ + if(CVAL(inbuf,0) || IVAL(inbuf,4) == 0x424d53ff) { return false; } @@ -63,7 +63,9 @@ bool is_encrypted_packet(const uint8_t *inbuf) return false; } - if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) { + if (SVAL(inbuf,4) == 0x45FF && + srv_trans_enc_ctx && + enc_num == srv_enc_ctx()) { return true; } return false; -- cgit From 7febec3c58bebb20d7866ea98c43bb41f0c09db4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jan 2008 16:08:39 -0800 Subject: Simplify... plus add a debug message. Jeremy. (This used to be commit bedc493874adaf783362ba7b821e2a6d985b96ea) --- source3/smbd/seal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 51a5f23f03..ea017e08d8 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -53,8 +53,8 @@ bool is_encrypted_packet(const uint8_t *inbuf) NTSTATUS status; uint16_t enc_num; - /* Ignore non-session messages or 0xFF'SMB' messages. */ - if(CVAL(inbuf,0) || IVAL(inbuf,4) == 0x424d53ff) { + /* Ignore non-session messages or non 0xFF'E' messages. */ + if(CVAL(inbuf,0) || !(inbuf[4] == 0xFF && inbuf[5] == 'E')) { return false; } @@ -63,9 +63,8 @@ bool is_encrypted_packet(const uint8_t *inbuf) return false; } - if (SVAL(inbuf,4) == 0x45FF && - srv_trans_enc_ctx && - enc_num == srv_enc_ctx()) { + /* Encrypted messages are 0xFF'E' */ + if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) { return true; } return false; @@ -714,6 +713,7 @@ NTSTATUS srv_encryption_start(connection_struct *conn) partial_srv_trans_enc_ctx = NULL; + DEBUG(1,("srv_encryption_start: context negotiated\n")); return NT_STATUS_OK; } -- cgit From 2371d31f64e8b1238e86d86c5b6f20ac5a842799 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jan 2008 18:44:19 -0800 Subject: Fix resource leak found by coverity (CID 521). Jeremy. (This used to be commit acfb233acc7324b8d431d5cb777a1933d173b3dc) --- source3/smbd/reply.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 27f380a627..a796a3193b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -6355,6 +6355,7 @@ void reply_copy(struct smb_request *req) directory, dname); if (!fname) { + CloseDir(dir_hnd); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBcopy); return; @@ -6365,6 +6366,7 @@ void reply_copy(struct smb_request *req) continue; } if (!destname) { + CloseDir(dir_hnd); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBcopy); return; @@ -6372,6 +6374,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + CloseDir(dir_hnd); reply_nterror(req, status); END_PROFILE(SMBcopy); return; @@ -6379,6 +6382,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, destname); if (!NT_STATUS_IS_OK(status)) { + CloseDir(dir_hnd); reply_nterror(req, status); END_PROFILE(SMBcopy); return; -- cgit From cb3c3ccd63bc5647b76964ed9569737719eefc7c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 9 Jan 2008 07:59:12 +0100 Subject: ensure uni_name.buffer is initialised merge from http://samba.org/~tridge/3_0-ctdb (This used to be commit 2938e74dea1695c813d6220a839b248dbc3b1d8f) --- source3/smbd/notify.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 7287210802..5c26cac219 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -65,6 +65,8 @@ static bool notify_marshall_changes(int num_changes, int i; UNISTR uni_name; + uni_name.buffer = NULL; + for (i=0; i Date: Wed, 9 Jan 2008 10:29:34 +0100 Subject: Replace an uninitialized variable Reported by the IBM checker (This used to be commit 48f61e4b9fce5ea4f4bc3cf55530bb757c0def07) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4abe017380..6aef99ff0e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2845,6 +2845,8 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } + SET_STAT_INVALID(sbuf); + goto done; } } -- cgit From 253fbf1a6ece5c8dc9759e3535b7f9fa46883c1b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jan 2008 17:11:04 -0800 Subject: Make use of talloc_pool in the main codepaths. Remove the sub-contexts. Jeremy. (This used to be commit bc932b8ad4396f76b71c43efe9a6346f89c3632c) --- source3/smbd/nttrans.c | 8 -------- source3/smbd/open.c | 8 +------- source3/smbd/process.c | 2 +- source3/smbd/service.c | 8 +------- source3/smbd/trans2.c | 25 +++++-------------------- source3/smbd/vfs.c | 13 ++++--------- 6 files changed, 12 insertions(+), 52 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ae64c06215..e8df732ea2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1604,7 +1604,6 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, SEC_DESC *psd = NULL; size_t sd_size; uint32 security_info_wanted; - TALLOC_CTX *frame; files_struct *fsp = NULL; NTSTATUS status; DATA_BLOB blob; @@ -1631,8 +1630,6 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, return; } - frame = talloc_stackframe(); - /* * Get the permissions to return. */ @@ -1651,7 +1648,6 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, } if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(frame); reply_nterror(req, status); return; } @@ -1665,7 +1661,6 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, if (max_data_count < sd_size) { send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); - TALLOC_FREE(frame); return; } @@ -1675,7 +1670,6 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, data = nttrans_realloc(ppdata, sd_size); if(data == NULL) { - TALLOC_FREE(frame); reply_doserror(req, ERRDOS, ERRnomem); return; } @@ -1684,7 +1678,6 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, &blob.data, &blob.length); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(frame); reply_nterror(req, status); return; } @@ -1694,7 +1687,6 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size); - TALLOC_FREE(frame); return; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6aef99ff0e..037ab633e3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -125,7 +125,7 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, char *saved_dir = NULL; SMB_STRUCT_STAT sbuf; SMB_STRUCT_STAT parent_st; - TALLOC_CTX *ctx = talloc_stackframe(); + TALLOC_CTX *ctx = talloc_tos(); NTSTATUS status = NT_STATUS_OK; int ret; @@ -135,7 +135,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", inherit_from_dir, strerror(errno) )); - TALLOC_FREE(ctx); return status; } @@ -152,7 +151,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, DEBUG(0,("change_dir_owner_to_parent: failed to get " "current working directory. Error was %s\n", strerror(errno))); - TALLOC_FREE(ctx); return status; } @@ -202,7 +200,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, out: - TALLOC_FREE(ctx); vfs_ChDir(conn,saved_dir); return status; } @@ -2707,7 +2704,6 @@ NTSTATUS create_file(connection_struct *conn, int *pinfo, SMB_STRUCT_STAT *psbuf) { - TALLOC_CTX *frame = talloc_stackframe(); struct case_semantics_state *case_state = NULL; SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; @@ -2918,7 +2914,6 @@ NTSTATUS create_file(connection_struct *conn, if (psbuf != NULL) { *psbuf = sbuf; } - TALLOC_FREE(frame); return NT_STATUS_OK; fail: @@ -2928,6 +2923,5 @@ NTSTATUS create_file(connection_struct *conn, close_file(fsp, ERROR_CLOSE); fsp = NULL; } - TALLOC_FREE(frame); return status; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index fe32d57ff7..2d3cf7fbd8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2071,7 +2071,7 @@ void smbd_process(void) char *inbuf; size_t inbuf_len; bool encrypted = false; - TALLOC_CTX *frame = talloc_stackframe(); + TALLOC_CTX *frame = talloc_stackframe_pool(8192); errno = 0; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 65fc818144..2588a66b8b 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -357,7 +357,6 @@ void load_registry_shares(void) int find_service(fstring service) { int iService; - TALLOC_CTX *frame = talloc_stackframe(); all_string_sub(service,"\\","/",0); @@ -463,8 +462,6 @@ int find_service(fstring service) if (iService < 0) DEBUG(3,("find_service() failed to find service %s\n", service)); - TALLOC_FREE(frame); - return (iService); } @@ -1150,20 +1147,17 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, #if SOFTLINK_OPTIMISATION /* resolve any soft links early if possible */ if (vfs_ChDir(conn,conn->connectpath) == 0) { - TALLOC_CTX *ctx = talloc_stackframe(); + TALLOC_CTX *ctx = talloc_tos(); char *s = vfs_GetWd(ctx,s); if (!s) { *status = map_nt_error_from_unix(errno); - TALLOC_FREE(ctx); goto err_root_exit; } if (!set_conn_connectpath(conn,s)) { *status = NT_STATUS_NO_MEMORY; - TALLOC_FREE(ctx); goto err_root_exit; } vfs_ChDir(conn,conn->connectpath); - TALLOC_FREE(ctx); } #endif diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 485513c734..ce0b239c4e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -297,9 +297,8 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, if (!lp_ea_support(SNUM(conn))) { return 0; } - mem_ctx = talloc_init("estimate_ea_size"); + mem_ctx = talloc_tos(); (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); - talloc_destroy(mem_ctx); return total_ea_len; } @@ -310,7 +309,7 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name) { size_t total_ea_len; - TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name"); + TALLOC_CTX *mem_ctx = talloc_tos(); struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); for (; ea_list; ea_list = ea_list->next) { @@ -321,7 +320,6 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con break; } } - talloc_destroy(mem_ctx); } /**************************************************************************** @@ -1955,9 +1953,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd out_of_space = True; finished = False; } else { - TALLOC_CTX *sub_ctx = talloc_stackframe(); - - finished = !get_lanman2_dir_entry(sub_ctx, + finished = !get_lanman2_dir_entry(ctx, conn, req->flags2, mask,dirtype,info_level, @@ -1966,8 +1962,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd space_remaining, &out_of_space, &got_exact_match, &last_entry_off, ea_list); - - TALLOC_FREE(sub_ctx); } if (finished && out_of_space) @@ -2303,9 +2297,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd out_of_space = True; finished = False; } else { - TALLOC_CTX *sub_ctx = talloc_stackframe(); - - finished = !get_lanman2_dir_entry(sub_ctx, + finished = !get_lanman2_dir_entry(ctx, conn, req->flags2, mask,dirtype,info_level, @@ -2314,8 +2306,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd space_remaining, &out_of_space, &got_exact_match, &last_entry_off, ea_list); - - TALLOC_FREE(sub_ctx); } if (finished && out_of_space) @@ -4759,17 +4749,12 @@ static NTSTATUS smb_info_set_ea(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - ctx = talloc_init("SMB_INFO_SET_EA"); - if (!ctx) { - return NT_STATUS_NO_MEMORY; - } + ctx = talloc_tos(); ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); if (!ea_list) { - talloc_destroy(ctx); return NT_STATUS_INVALID_PARAMETER; } status = set_ea(conn, fsp, fname, ea_list); - talloc_destroy(ctx); return status; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9a5e0aff60..bb4e77ed31 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -869,14 +869,13 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) return map_nt_error_from_unix(errno); case ENOENT: { - TALLOC_CTX *tmp_ctx = talloc_stackframe(); + TALLOC_CTX *ctx = talloc_tos(); char *tmp_fname = NULL; char *last_component = NULL; /* Last component didn't exist. Remove it and try and canonicalise the directory. */ - tmp_fname = talloc_strdup(tmp_ctx, fname); + tmp_fname = talloc_strdup(ctx, fname); if (!tmp_fname) { - TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } p = strrchr_m(tmp_fname, '/'); @@ -885,10 +884,9 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) last_component = p; } else { last_component = tmp_fname; - tmp_fname = talloc_strdup(tmp_ctx, + tmp_fname = talloc_strdup(ctx, "."); if (!tmp_fname) { - TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } } @@ -900,15 +898,13 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) #endif if (!resolved_name) { DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname)); - TALLOC_FREE(tmp_ctx); return map_nt_error_from_unix(errno); } - tmp_fname = talloc_asprintf(tmp_ctx, + tmp_fname = talloc_asprintf(ctx, "%s/%s", resolved_name, last_component); if (!tmp_fname) { - TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } #ifdef REALPATH_TAKES_NULL @@ -922,7 +918,6 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) safe_strcpy(resolved_name_buf, tmp_fname, PATH_MAX); resolved_name = resolved_name_buf; #endif - TALLOC_FREE(tmp_ctx); break; } default: -- cgit From 3cc3b9e1879d3d9714ac2914364418a140e8389c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 Jan 2008 14:21:25 +0100 Subject: use talloc_tos in a few more places (This used to be commit 65dd869bea351010c67f02046ae4134bdada1a4c) --- source3/smbd/close.c | 4 ++-- source3/smbd/connection.c | 2 +- source3/smbd/open.c | 8 ++++---- source3/smbd/oplock.c | 6 +++--- source3/smbd/reply.c | 8 +++++--- source3/smbd/trans2.c | 2 +- 6 files changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 5d30e467d0..c74e13348e 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -176,7 +176,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, * This prevents race conditions with the file being created. JRA. */ - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_remove_share_mode: Could not get share mode " @@ -441,7 +441,7 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty * reference to a directory also. */ - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 95e45a6990..016c8adb1b 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -132,7 +132,7 @@ bool claim_connection(connection_struct *conn, const char *name, DEBUG(5,("claiming [%s]\n", name)); - if (!(rec = connections_fetch_entry(NULL, conn, name))) { + if (!(rec = connections_fetch_entry(talloc_tos(), conn, name))) { DEBUG(0, ("connections_fetch_entry failed\n")); return False; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 037ab633e3..59699dfbd0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1221,7 +1221,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, request_time = pml->request_time; /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1451,7 +1451,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (file_existed) { id = vfs_file_id_from_sbuf(conn, psbuf); - lck = get_share_mode_lock(NULL, id, + lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, fname); @@ -1678,7 +1678,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, id = fsp->file_id; - lck = get_share_mode_lock(NULL, id, + lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, fname); @@ -2212,7 +2212,7 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->file_id, + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, conn->connectpath, fname); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 277e07c178..420aa94fe6 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -181,7 +181,7 @@ bool remove_oplock(files_struct *fsp) struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -206,7 +206,7 @@ bool downgrade_oplock(files_struct *fsp) bool ret; struct share_mode_lock *lck; - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -757,7 +757,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " "share mode entry for file %s.\n", fsp->fsp_name )); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a796a3193b..79c0176e64 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -592,7 +592,8 @@ void reply_tcon_and_X(struct smb_request *req) } if (global_encrypted_passwords_negotiated) { - password = data_blob(smb_buf(req->inbuf),passlen); + password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf), + passlen); if (lp_security() == SEC_SHARE) { /* * Security = share always has a pad byte @@ -603,7 +604,8 @@ void reply_tcon_and_X(struct smb_request *req) p = smb_buf(req->inbuf) + passlen; } } else { - password = data_blob(smb_buf(req->inbuf),passlen+1); + password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf), + passlen+1); /* Ensure correct termination */ password.data[passlen]=0; p = smb_buf(req->inbuf) + passlen + 1; @@ -5508,7 +5510,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); /* * We have the file open ourselves, so not being able to get the diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ce0b239c4e..bf6802f2a6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6193,7 +6193,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, * non-POSIX opens return SHARING_VIOLATION. */ - lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("smb_posix_unlink: Could not get share mode " "lock for file %s\n", fsp->fsp_name)); -- cgit From 5ddb2abf7611a93960056075ea56f992329c3678 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 Jan 2008 16:15:45 +0100 Subject: Some more talloc_tos() (This used to be commit 444e35e7df1f13fc285183da8fb41b30ad99a3fa) --- source3/smbd/blocking.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 4e0d5289f8..479361a8c1 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -625,7 +625,7 @@ void remove_pending_lock_requests_by_mid(int mid) next = blr->next; if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ @@ -715,7 +715,7 @@ static void process_blocking_lock_queue(void) fsp->fnum, fsp->fsp_name )); if(!change_to_user(conn,vuid)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); /* * Remove the entry and return an error to the client. @@ -741,7 +741,7 @@ static void process_blocking_lock_queue(void) } if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); /* * Remove the entry and return an error to the client. @@ -773,7 +773,7 @@ static void process_blocking_lock_queue(void) */ if(blocking_lock_record_process(blr)) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); if (br_lck) { brl_lock_cancel(br_lck, @@ -800,7 +800,7 @@ static void process_blocking_lock_queue(void) */ if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { - struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); /* * Lock expired - throw away all previously -- cgit From 5661ac6a389620ac543a384832de9ee9b64893c7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 10 Jan 2008 13:30:43 +0100 Subject: Correctly abstract the transfer_file mechanism with callbacks and void ptrs. This removes the in_fsp and out_fsp global variables hack from smbd/vfs.c. Michael (This used to be commit b2e7cdc6e899ca3c16edbb6c8786ff9aa999fa6e) --- source3/smbd/vfs.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index bb4e77ed31..b6b6b1c0f1 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -662,25 +662,23 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) Transfer some data (n bytes) between two file_struct's. ****************************************************************************/ -static files_struct *in_fsp; -static files_struct *out_fsp; - -static ssize_t read_fn(int fd, void *buf, size_t len) +static ssize_t vfs_read_fn(void *file, void *buf, size_t len) { - return SMB_VFS_READ(in_fsp, fd, buf, len); + struct files_struct *fsp = (struct files_struct *)file; + + return SMB_VFS_READ(fsp, fsp->fh->fd, buf, len); } -static ssize_t write_fn(int fd, const void *buf, size_t len) +static ssize_t vfs_write_fn(void *file, const void *buf, size_t len) { - return SMB_VFS_WRITE(out_fsp, fd, buf, len); + struct files_struct *fsp = (struct files_struct *)file; + + return SMB_VFS_WRITE(fsp, fsp->fh->fd, buf, len); } SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) { - in_fsp = in; - out_fsp = out; - - return transfer_file_internal(in_fsp->fh->fd, out_fsp->fh->fd, n, read_fn, write_fn); + return transfer_file_internal(in, out, n, vfs_read_fn, vfs_write_fn); } /******************************************************************* -- cgit From 10da70325b899bfbebf5a6eeef69838fe9d346bb Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 10 Jan 2008 13:55:16 +0100 Subject: Make casts to (void *) explicit to remove compiler warnings. Michael (This used to be commit cbbfbd7a63fe0fc479a1b63b4552c713633dd6be) --- source3/smbd/vfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index b6b6b1c0f1..a57dcddade 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -678,7 +678,8 @@ static ssize_t vfs_write_fn(void *file, const void *buf, size_t len) SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) { - return transfer_file_internal(in, out, n, vfs_read_fn, vfs_write_fn); + return transfer_file_internal((void *)in, (void *)out, n, + vfs_read_fn, vfs_write_fn); } /******************************************************************* -- cgit From 1d66f4d58b5fdd9c4e0c022cd2724e05d144510b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 10 Jan 2008 15:33:51 +0100 Subject: Remove redundant parameter fd from SMB_VFS_READ(). Michael (This used to be commit a8fc2ddad8d5f7c6c00cb36c74a32a02d69d1d04) --- source3/smbd/vfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a57dcddade..53a0001515 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -389,8 +389,8 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) while (total < byte_count) { - ssize_t ret = SMB_VFS_READ(fsp, fsp->fh->fd, buf + total, - byte_count - total); + ssize_t ret = SMB_VFS_READ(fsp, buf + total, + byte_count - total); if (ret == 0) return total; if (ret == -1) { @@ -666,7 +666,7 @@ static ssize_t vfs_read_fn(void *file, void *buf, size_t len) { struct files_struct *fsp = (struct files_struct *)file; - return SMB_VFS_READ(fsp, fsp->fh->fd, buf, len); + return SMB_VFS_READ(fsp, buf, len); } static ssize_t vfs_write_fn(void *file, const void *buf, size_t len) -- cgit From e9a3a62e7448bef72d9c17c90ff2b404082f067c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 10 Jan 2008 15:49:35 +0100 Subject: Remove redundant parameter fd from SMB_VFS_WRITE(). Michael (This used to be commit c8ae7d095a2a6a7eac920a68ca7244e3a423e1b1) --- source3/smbd/vfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 53a0001515..1e71da742c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -451,7 +451,7 @@ ssize_t vfs_write_data(struct smb_request *req, } while (total < N) { - ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total); + ret = SMB_VFS_WRITE(fsp, buffer + total, N - total); if (ret == -1) return -1; @@ -673,7 +673,7 @@ static ssize_t vfs_write_fn(void *file, const void *buf, size_t len) { struct files_struct *fsp = (struct files_struct *)file; - return SMB_VFS_WRITE(fsp, fsp->fh->fd, buf, len); + return SMB_VFS_WRITE(fsp, buf, len); } SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) -- cgit From 13785d5c62093540139094f6dfcf808100790939 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Jan 2008 15:15:01 -0800 Subject: Don't print out debug messages at level 0 if we can't bind to a socket if we've already bound to one (this prevents : bind failed on port 445 socket_addr = 0.0.0.0. Error = Address already in use bind failed on port 139 socket_addr = 0.0.0.0. Error = Address already in use messages when trying to bind to an IPv4 address when we've already bound to the IPv6 equivalent. Jeremy. (This used to be commit 3936de735a7bb548df8ce7f06f2cc8f7ffdf56cd) --- source3/smbd/server.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 43a6d62a28..8371d17f10 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -390,8 +390,11 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ } s = fd_listenset[num_sockets] = - open_socket_in(SOCK_STREAM, port, 0, - ifss, True); + open_socket_in(SOCK_STREAM, + port, + num_sockets == 0 ? 0 : 2, + ifss, + true); if(s == -1) { continue; } @@ -467,8 +470,11 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; } - s = open_socket_in(SOCK_STREAM, port, 0, - &ss, true); + s = open_socket_in(SOCK_STREAM, + port, + num_sockets == 0 ? 0 : 2, + &ss, + true); if (s == -1) { continue; } -- cgit From 4caab9ca25e1163378714de825d835e79e27dd4f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 00:51:19 +0100 Subject: Combine fsp and fromfd to fromfsp in SMB_VFS_SENDFILE(). Michael (This used to be commit a52cfb7d777157c93c9dc26c67f457be592dd537) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 79c0176e64..8149f5aeb6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2654,7 +2654,7 @@ void send_file_readbraw(connection_struct *conn, _smb_setlen(header,nread); header_blob = data_blob_const(header, 4); - if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, + if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header_blob, startpos, nread) == -1) { /* Returning ENOSYS means no data at all was sent. * Do this as a normal read. */ @@ -3137,7 +3137,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, construct_reply_common((char *)req->inbuf, (char *)headerbuf); setup_readX_header((char *)headerbuf, smb_maxcnt); - if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { + if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ if (errno == ENOSYS) { goto normal_read; -- cgit From fef9cf00e1e110ff5872f1c368d080fe4f7939d6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 01:26:54 +0100 Subject: Combine fsp and tofd to tofsp in SMB_VFS_RECVFILE(). Michael (This used to be commit 3958abffaf2866c69ad9e13ec345364fde5c78bb) --- source3/smbd/vfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 1e71da742c..33a3a43aa4 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -445,7 +445,6 @@ ssize_t vfs_write_data(struct smb_request *req, req->unread_bytes = 0; return SMB_VFS_RECVFILE(smbd_server_fd(), fsp, - fsp->fh->fd, (SMB_OFF_T)-1, N); } @@ -479,7 +478,6 @@ ssize_t vfs_pwrite_data(struct smb_request *req, req->unread_bytes = 0; return SMB_VFS_RECVFILE(smbd_server_fd(), fsp, - fsp->fh->fd, offset, N); } -- cgit From f33f4ef4a24fcbf09eeba0d51e7db74e9b13b432 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 10 Jan 2008 16:35:54 -0800 Subject: Don't switch user contexts unless you have to. Saves a bunch of syscalls on close. Noticed by Volker. Jeremy. (This used to be commit 3caeeaea162e2083a087c242b850c107a3be1bf9) --- source3/smbd/close.c | 39 +++++++++++++++++++++++++-------------- source3/smbd/sec_ctx.c | 17 +++++++++++++++++ 2 files changed, 42 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c74e13348e..f67a4ad668 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -163,7 +163,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, enum file_close_type close_type) { connection_struct *conn = fsp->conn; - bool delete_file = False; + bool delete_file = false; + bool changed_user = false; struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; @@ -246,18 +247,26 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " "- deleting file.\n", fsp->fsp_name)); - /* Become the user who requested the delete. */ + if (!unix_token_equal(lck->delete_token, ¤t_user.ut)) { + /* Become the user who requested the delete. */ - if (!push_sec_ctx()) { - smb_panic("close_remove_share_mode: file %s. failed to push " - "sec_ctx.\n"); - } + DEBUG(5,("close_remove_share_mode: file %s. " + "Change user to uid %u\n", + (unsigned int)lck->delete_token->uid)); - set_sec_ctx(lck->delete_token->uid, - lck->delete_token->gid, - lck->delete_token->ngroups, - lck->delete_token->groups, - NULL); + if (!push_sec_ctx()) { + smb_panic("close_remove_share_mode: file %s. failed to push " + "sec_ctx.\n"); + } + + set_sec_ctx(lck->delete_token->uid, + lck->delete_token->gid, + lck->delete_token->ngroups, + lck->delete_token->groups, + NULL); + + changed_user = true; + } /* We can only delete the file if the name we have is still valid and hasn't been renamed. */ @@ -326,9 +335,11 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, done: - /* unbecome user. */ - pop_sec_ctx(); - + if (changed_user) { + /* unbecome user. */ + pop_sec_ctx(); + } + TALLOC_FREE(lck); return status; } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 6edcc36764..0f307f6a64 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -32,6 +32,23 @@ struct sec_ctx { static struct sec_ctx sec_ctx_stack[MAX_SEC_CTX_DEPTH + 1]; static int sec_ctx_stack_ndx; +/**************************************************************************** + Are two UNIX tokens equal ? +****************************************************************************/ + +bool unix_token_equal(const UNIX_USER_TOKEN *t1, const UNIX_USER_TOKEN *t2) +{ + if (t1->uid != t2->uid || t1->gid != t2->gid || + t1->ngroups != t2->ngroups) { + return false; + } + if (memcmp(t1->groups, t2->groups, + t1->ngroups*sizeof(gid_t)) != 0) { + return false; + } + return true; +} + /**************************************************************************** Become the specified uid. ****************************************************************************/ -- cgit From 2539cf073915c481ae449e2eb11f501c29276688 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 11 Jan 2008 18:46:41 +0100 Subject: Fix a build warning. Guenther (This used to be commit 88874a501d0c086f796e4838af8c9399d3cccc1f) --- source3/smbd/close.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index f67a4ad668..4c385d7611 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -252,6 +252,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. " "Change user to uid %u\n", + fsp->fsp_name, (unsigned int)lck->delete_token->uid)); if (!push_sec_ctx()) { -- cgit From 915647da9cb1227378f53a5a386df69e9348754b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jan 2008 22:50:13 -0800 Subject: Fix CID 523 - wrong null deref check. Jeremy. (This used to be commit 05cadffeab38ca9df7ffd46785b536266c4438c4) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 9643506aea..a9b94aabc3 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -396,7 +396,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, TALLOC_FREE(prefix); - if (!pp_out) { + if (!*pp_out) { M_DEBUG(0,("talloc_fail")); return False; } -- cgit From 9f750996571c75b0be53fdf13705b95bf6126102 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jan 2008 23:17:23 -0800 Subject: Fix CID 505 - don't copy uninitialized memory. Jeremy. (This used to be commit 0d2c77e8d3a83f2c5e78fa076f22919ef9d124b9) --- source3/smbd/notify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5c26cac219..55009ce0b1 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -235,6 +235,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return NT_STATUS_NO_MEMORY; } + ZERO_STRUCT(e); e.path = fullpath; e.filter = filter; e.subdir_filter = 0; -- cgit From 43717a16e2fca8b196d4a89e33b05fefc0cb02d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jan 2008 23:53:27 -0800 Subject: Fix CID 476. Ensure a valid pac_data pointer is always passed to ads_verify_ticket as it's always derefed. Jeremy. (This used to be commit 0599d57efff0f417f75510e8b08c3cb7b4bcfcd8) --- source3/smbd/sesssetup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index bc1d26faca..aee8e498e9 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -259,7 +259,7 @@ static void reply_spnego_kerberos(struct smb_request *req, fstring user; int sess_vuid = req->vuid; NTSTATUS ret = NT_STATUS_OK; - PAC_DATA *pac_data; + PAC_DATA *pac_data = NULL; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob_null; @@ -271,7 +271,6 @@ static void reply_spnego_kerberos(struct smb_request *req, PAC_LOGON_INFO *logon_info = NULL; ZERO_STRUCT(ticket); - ZERO_STRUCT(pac_data); ZERO_STRUCT(ap_rep); ZERO_STRUCT(ap_rep_wrapped); ZERO_STRUCT(response); -- cgit From 4c0ca860515a799ddcda3804fe4c2080d1df9b80 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jan 2008 21:53:29 +0100 Subject: There's no point in calling FLOCK on a non-existing fd (This used to be commit 9ff79f231f1206631662b5c521ecddf5df9141c0) --- source3/smbd/open.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 59699dfbd0..d1679209bb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1761,14 +1761,16 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, the kernel refuses the operations then the kernel is wrong. note that GPFS supports it as well - jmcd */ - ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); - if(ret_flock == -1 ){ + if (fsp->fh->fd != -1) { + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); + if(ret_flock == -1 ){ - TALLOC_FREE(lck); - fd_close(fsp); - file_free(fsp); - - return NT_STATUS_SHARING_VIOLATION; + TALLOC_FREE(lck); + fd_close(fsp); + file_free(fsp); + + return NT_STATUS_SHARING_VIOLATION; + } } /* -- cgit From b36a78837f2bb16725c39e42296015c61f1c5910 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jan 2008 12:35:04 +0100 Subject: delete on close even prevents stat opens (This used to be commit 85fe7f3f6ed4aae76e5cf31ab689b2dfacfd74de) --- source3/smbd/open.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d1679209bb..9d48bcc98b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -598,12 +598,6 @@ static NTSTATUS open_mode_check(connection_struct *conn, } *file_existed = True; - - if (is_stat_open(access_mask)) { - /* Stat open that doesn't trigger oplock breaks or share mode - * checks... ! JRA. */ - return NT_STATUS_OK; - } /* A delete on close prohibits everything */ @@ -611,6 +605,12 @@ static NTSTATUS open_mode_check(connection_struct *conn, return NT_STATUS_DELETE_PENDING; } + if (is_stat_open(access_mask)) { + /* Stat open that doesn't trigger oplock breaks or share mode + * checks... ! JRA. */ + return NT_STATUS_OK; + } + /* * Check if the share modes will give us access. */ -- cgit From ec412b60ea6d6a4e0fd2e03ca9299b4264483c0c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 12 Jan 2008 17:08:04 +0100 Subject: Convert OpenDir to talloc, use talloc_tos() This cuts some mallocs on NtCreate&X (This used to be commit 8e64107b7846d8f9cce71aabc95b28b7488d01ce) --- source3/smbd/dir.c | 96 ++++++++++++++++++++----------------------------- source3/smbd/filename.c | 6 ++-- source3/smbd/reply.c | 35 +++++++++--------- 3 files changed, 61 insertions(+), 76 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 04e3167e77..ca6f8bfd8d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -142,8 +142,7 @@ static void dptr_idle(struct dptr_struct *dptr) { if (dptr->dir_hnd) { DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); - CloseDir(dptr->dir_hnd); - dptr->dir_hnd = NULL; + TALLOC_FREE(dptr->dir_hnd); } } @@ -192,7 +191,9 @@ static struct dptr_struct *dptr_get(int key, bool forclose) if (dirhandles_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); - if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, dptr->wcard, dptr->attr))) { + if (!(dptr->dir_hnd = OpenDir( + NULL, dptr->conn, dptr->path, + dptr->wcard, dptr->attr))) { DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, strerror(errno))); return False; @@ -263,9 +264,7 @@ static void dptr_close_internal(struct dptr_struct *dptr) bitmap_clear(dptr_bmap, dptr->dnum - 1); - if (dptr->dir_hnd) { - CloseDir(dptr->dir_hnd); - } + TALLOC_FREE(dptr->dir_hnd); /* Lanman 2 specific code */ SAFE_FREE(dptr->wcard); @@ -411,7 +410,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, return status; } - dir_hnd = OpenDir(conn, path, wcard, attr); + dir_hnd = OpenDir(NULL, conn, path, wcard, attr); if (!dir_hnd) { return map_nt_error_from_unix(errno); } @@ -425,7 +424,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, dptr = SMB_MALLOC_P(struct dptr_struct); if(!dptr) { DEBUG(0,("malloc fail in dptr_create.\n")); - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); return NT_STATUS_NO_MEMORY; } @@ -455,7 +454,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, if(dptr->dnum == -1 || dptr->dnum > 254) { DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); return NT_STATUS_TOO_MANY_OPENED_FILES; } } @@ -485,7 +484,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, if(dptr->dnum == -1 || dptr->dnum < 255) { DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); return NT_STATUS_TOO_MANY_OPENED_FILES; } } @@ -504,7 +503,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, if (!dptr->wcard) { bitmap_clear(dptr_bmap, dptr->dnum - 1); SAFE_FREE(dptr); - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); return NT_STATUS_NO_MEMORY; } if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { @@ -533,7 +532,8 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, int dptr_CloseDir(struct dptr_struct *dptr) { DLIST_REMOVE(dirptrs, dptr); - return CloseDir(dptr->dir_hnd); + TALLOC_FREE(dptr->dir_hnd); + return 0; } void dptr_SeekDir(struct dptr_struct *dptr, long offset) @@ -1113,72 +1113,53 @@ bool is_visible_file(connection_struct *conn, const char *dir_path, const char * return True; } +static int smb_Dir_destructor(struct smb_Dir *dirp) +{ + if (dirp->dir) { + SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); + } + dirhandles_open--; + return 0; +} + /******************************************************************* Open a directory. ********************************************************************/ -struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr) +struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, + const char *name, const char *mask, uint32 attr) { - struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir); + struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir); if (!dirp) { return NULL; } - ZERO_STRUCTP(dirp); dirp->conn = conn; dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); - dirp->dir_path = SMB_STRDUP(name); + dirp->dir_path = talloc_strdup(dirp, name); if (!dirp->dir_path) { goto fail; } + + dirhandles_open++; + talloc_set_destructor(dirp, smb_Dir_destructor); + dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); if (!dirp->dir) { - DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); + DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, + strerror(errno) )); goto fail; } - dirhandles_open++; return dirp; fail: - - if (dirp) { - if (dirp->dir) { - SMB_VFS_CLOSEDIR(conn,dirp->dir); - } - SAFE_FREE(dirp->dir_path); - SAFE_FREE(dirp->name_cache); - SAFE_FREE(dirp); - } + TALLOC_FREE(dirp); return NULL; } - -/******************************************************************* - Close a directory. -********************************************************************/ - -int CloseDir(struct smb_Dir *dirp) -{ - int i, ret = 0; - - if (dirp->dir) { - ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); - } - SAFE_FREE(dirp->dir_path); - if (dirp->name_cache) { - for (i = 0; i < dirp->name_cache_size; i++) { - SAFE_FREE(dirp->name_cache[i].name); - } - } - SAFE_FREE(dirp->name_cache); - SAFE_FREE(dirp); - dirhandles_open--; - return ret; -} - /******************************************************************* Read from a directory. Also return current offset. Don't check for veto or invisible files. @@ -1290,8 +1271,8 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) } if (dirp->name_cache == NULL) { - dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, - dirp->name_cache_size); + dirp->name_cache = TALLOC_ZERO_ARRAY( + dirp, struct name_cache_entry, dirp->name_cache_size); if (dirp->name_cache == NULL) { return; @@ -1301,8 +1282,8 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) dirp->name_cache_index = (dirp->name_cache_index+1) % dirp->name_cache_size; e = &dirp->name_cache[dirp->name_cache_index]; - SAFE_FREE(e->name); - e->name = SMB_STRDUP(name); + TALLOC_FREE(e->name); + e->name = talloc_strdup(dirp, name); e->offset = offset; } @@ -1359,7 +1340,8 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, NTSTATUS status = NT_STATUS_OK; long dirpos = 0; const char *dname; - struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0); + struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname, + NULL, 0); if (!dir_hnd) { return map_nt_error_from_unix(errno); @@ -1383,7 +1365,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, status = NT_STATUS_DIRECTORY_NOT_EMPTY; break; } - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); return status; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 5ae193fb46..be4960cab8 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -778,7 +778,7 @@ static bool scan_directory(connection_struct *conn, const char *path, } /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { + if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); TALLOC_FREE(unmangled_name); return(False); @@ -809,7 +809,7 @@ static bool scan_directory(connection_struct *conn, const char *path, /* we've found the file, change it's name and return */ *found_name = talloc_strdup(ctx,dname); TALLOC_FREE(unmangled_name); - CloseDir(cur_dir); + TALLOC_FREE(cur_dir); if (!*found_name) { errno = ENOMEM; return False; @@ -819,7 +819,7 @@ static bool scan_directory(connection_struct *conn, const char *path, } TALLOC_FREE(unmangled_name); - CloseDir(cur_dir); + TALLOC_FREE(cur_dir); errno = ENOENT; return False; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8149f5aeb6..e2316ef120 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2410,7 +2410,8 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, return status; } - dir_hnd = OpenDir(conn, directory, mask, dirtype); + dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, + dirtype); if (dir_hnd == NULL) { return map_nt_error_from_unix(errno); } @@ -2448,7 +2449,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); return status; } @@ -2464,7 +2465,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, TALLOC_FREE(fname); } - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); } if (count == 0 && NT_STATUS_IS_OK(status)) { @@ -4901,7 +4902,8 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, const char *dname = NULL; bool ret = True; long offset = 0; - struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); + struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory, + NULL, 0); if(dir_hnd == NULL) return False; @@ -4949,7 +4951,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, } TALLOC_FREE(fullname); } - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); return ret; } @@ -4997,7 +4999,8 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, */ const char *dname; long dirpos = 0; - struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); + struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, + directory, NULL, 0); if(dir_hnd == NULL) { errno = ENOTEMPTY; @@ -5010,7 +5013,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, if (!is_visible_file(conn, directory, dname, &st, False)) continue; if(!IS_VETO_PATH(conn, dname)) { - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); errno = ENOTEMPTY; goto err; } @@ -5055,7 +5058,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, } TALLOC_FREE(fullname); } - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); /* Retry the rmdir */ ret = SMB_VFS_RMDIR(conn,directory); } @@ -5751,7 +5754,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, return status; } - dir_hnd = OpenDir(conn, directory, mask, attrs); + dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs); if (dir_hnd == NULL) { return map_nt_error_from_unix(errno); } @@ -5851,7 +5854,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, TALLOC_FREE(fname); TALLOC_FREE(destname); } - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); if (count == 0 && NT_STATUS_IS_OK(status)) { status = map_nt_error_from_unix(errno); @@ -6325,7 +6328,7 @@ void reply_copy(struct smb_request *req) return; } - dir_hnd = OpenDir(conn, directory, mask, 0); + dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0); if (dir_hnd == NULL) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); @@ -6357,7 +6360,7 @@ void reply_copy(struct smb_request *req) directory, dname); if (!fname) { - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBcopy); return; @@ -6368,7 +6371,7 @@ void reply_copy(struct smb_request *req) continue; } if (!destname) { - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBcopy); return; @@ -6376,7 +6379,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); reply_nterror(req, status); END_PROFILE(SMBcopy); return; @@ -6384,7 +6387,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, destname); if (!NT_STATUS_IS_OK(status)) { - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); reply_nterror(req, status); END_PROFILE(SMBcopy); return; @@ -6400,7 +6403,7 @@ void reply_copy(struct smb_request *req) TALLOC_FREE(fname); TALLOC_FREE(destname); } - CloseDir(dir_hnd); + TALLOC_FREE(dir_hnd); } if (count == 0) { -- cgit From 18083f1d88f3cfade68587f9289fa709c229e1d0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 12 Jan 2008 21:09:43 +0100 Subject: Get the inbuf on talloc_tos() (This used to be commit 883f7415769ad1e714f636e9d6fbd1f075e69d1e) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2d3cf7fbd8..a5bdb96650 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2085,7 +2085,7 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); - while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len, + while (!receive_message_or_smb(talloc_tos(), &inbuf, &inbuf_len, select_timeout, &unread_bytes, &encrypted)) { -- cgit From bb2c52ad43b12c30315189ebbd722ae3125e457b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 12 Jan 2008 19:12:30 +0100 Subject: Remove an unused variable (This used to be commit 24e719a1d432d5de022ab903457df0dd67c24b85) --- source3/smbd/aio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index c8175f77ac..9c25f69c97 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -451,7 +451,6 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; - const char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); -- cgit From 68694369fc96354452979b07425f3f48c4f73bbe Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 12:09:48 +0300 Subject: Merge CTDB-related fixes from samba-ctdb 3.0 branch (http://samba.org/~tridge/3_0-ctdb) Signed-off-by: Alexander Bokovoy (This used to be commit 0c8e23afbbb2d081fc23908bafcad04650bfacea) --- source3/smbd/connection.c | 9 ++++++ source3/smbd/oplock_linux.c | 22 +++++++++++---- source3/smbd/server.c | 67 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 016c8adb1b..d7063c9989 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -117,6 +117,15 @@ int count_current_connections( const char *sharename, bool clear ) return cs.curr_connections; } +/**************************************************************************** + Count the number of connections open across all shares. +****************************************************************************/ + +int count_all_current_connections(void) +{ + return count_current_connections(NULL, True /* clear stale entries */); +} + /**************************************************************************** Claim an entry in the connections database. ****************************************************************************/ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 05021b6c74..fa7cb42bc6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -93,17 +93,27 @@ static void set_capability(unsigned capability) return; } - data.effective |= (1< 0) { - remove_child_pid(pid); + while ((pid = sys_waitpid(-1, &status, WNOHANG)) > 0) { + bool unclean_shutdown = False; + + /* If the child terminated normally, assume + it was an unclean shutdown unless the + status is 0 + */ + if (WIFEXITED(status)) { + unclean_shutdown = WEXITSTATUS(status); + } + /* If the child terminated due to a signal + we always assume it was unclean. + */ + if (WIFSIGNALED(status)) { + unclean_shutdown = True; + } + remove_child_pid(pid, unclean_shutdown); } } @@ -603,6 +630,15 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; } + + + /* If the idle timeout fired and we don't have any connected + * users, exit gracefully. We should be running under a process + * controller that will restart us if necessry. + */ + if (num == 0 && count_all_current_connections() == 0) { + exit_server_cleanly("idle timeout"); + } /* process pending nDNS responses */ if (dns_register_smbd_reply(dns_reg, &r_fds, &idle_timeout)) { @@ -906,6 +942,29 @@ void exit_server_fault(void) exit_server("critical server fault"); } + +/**************************************************************************** +received when we should release a specific IP +****************************************************************************/ +static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data, + uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) +{ + const char *ip = (const char *)data->data; + char addr[INET6_ADDRSTRLEN]; + + if (strcmp(client_socket_addr(get_client_fd(),addr,sizeof(addr)), ip) == 0) { + /* we can't afford to do a clean exit - that involves + database writes, which would potentially mean we + are still running after the failover has finished - + we have to get rid of this process ID straight + away */ + DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n", + ip)); + _exit(0); + } +} + + /**************************************************************************** Initialise connect, service and file structs. ****************************************************************************/ @@ -1305,6 +1364,8 @@ extern void build_options(bool screen); /* register our message handlers */ messaging_register(smbd_messaging_context(), NULL, MSG_SMB_FORCE_TDIS, msg_force_tdis); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_RELEASE_IP, msg_release_ip); if ((lp_keepalive() != 0) && !(event_add_idle(smbd_event_context(), NULL, -- cgit From d86fc3ec8c99aaa5ffaa14a97525154507c39df7 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 12:17:03 +0300 Subject: Add support for offline files support, remote storage, and Async I/O force operations to VFS Offline files support and remote storage are for allowing communication with backup and archiving tools that mark files moved to a tape library as offline. We translate this info into corresponding CIFS offline file attribute and mark an exported volume as remote storage. Async I/O force is to allow selective redirection of I/O operations to asynchronous processing in case it is viable at VFS module discretion. It is needed for proper handling of offline files as performing regular I/O on offline file will block smbd. Signed-off-by: Alexander Bokovoy (This used to be commit 875208724e39564fe81385dfe36e6c963e79e101) --- source3/smbd/dmapi.c | 71 ++++++++++++++++++++++++++++---------------------- source3/smbd/dosmode.c | 44 +++++++++++++++---------------- source3/smbd/reply.c | 19 +++++++++----- source3/smbd/trans2.c | 23 ++++++++++------ 4 files changed, 89 insertions(+), 68 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 05e9138ea9..620baf199e 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -46,7 +46,7 @@ bool dmapi_have_session(void) { return False; } #define DMAPI_SESSION_NAME "samba" #define DMAPI_TRACE 10 -static dm_sessid_t dmapi_session = DM_NO_SESSION; +static dm_sessid_t samba_dmapi_session = DM_NO_SESSION; /* Initialise the DMAPI interface. Make sure that we only end up initialising * once per process to avoid resource leaks across different DMAPI @@ -75,7 +75,7 @@ static int init_dmapi_service(void) bool dmapi_have_session(void) { - return dmapi_session != DM_NO_SESSION; + return samba_dmapi_session != DM_NO_SESSION; } static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) @@ -110,7 +110,7 @@ int dmapi_init_session(void) */ SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; if (init_dmapi_service() < 0) { return -1; } @@ -139,7 +139,7 @@ retry: err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); buf[sizeof(buf) - 1] = '\0'; if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { - dmapi_session = sessions[i]; + samba_dmapi_session = sessions[i]; DEBUGADD(DMAPI_TRACE, ("attached to existing DMAPI session " "named '%s'\n", buf)); @@ -150,16 +150,15 @@ retry: TALLOC_FREE(sessions); /* No session already defined. */ - if (dmapi_session == DM_NO_SESSION) { - err = dm_create_session(DM_NO_SESSION, - CONST_DISCARD(char *, - DMAPI_SESSION_NAME), - &dmapi_session); + if (samba_dmapi_session == DM_NO_SESSION) { + err = dm_create_session(DM_NO_SESSION, + CONST_DISCARD(char *, DMAPI_SESSION_NAME), + &samba_dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, ("failed to create new DMAPI session: %s\n", strerror(errno))); - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; return -1; } @@ -185,22 +184,22 @@ static int reattach_dmapi_session(void) char buf[DM_SESSION_INFO_LEN]; size_t buflen; - if (dmapi_session != DM_NO_SESSION ) { + if (samba_dmapi_session != DM_NO_SESSION ) { become_root(); /* NOTE: On Linux, this call opens /dev/dmapi, costing us a * file descriptor. Ideally, we would close this when we fork. */ if (init_dmapi_service() < 0) { - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; unbecome_root(); return -1; } - if (dm_query_session(dmapi_session, sizeof(buf), + if (dm_query_session(samba_dmapi_session, sizeof(buf), buf, &buflen) < 0) { /* Session is stale. Disable DMAPI. */ - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; unbecome_root(); return -1; } @@ -214,33 +213,42 @@ static int reattach_dmapi_session(void) return 0; } -uint32 dmapi_file_flags(const char * const path) +/* If a DMAPI session has been initialised, then we need to make sure + * we are attached to it and have the correct privileges. This is + * necessary to be able to do DMAPI operations across a fork(2). If + * it fails, there is no likelihood of that failure being transient. + * + * Note that this use of the static attached flag relies on the fact + * that dmapi_file_flags() is never called prior to forking the + * per-client server process. + */ +const void * dmapi_get_current_session(void) { static int attached = 0; + if (dmapi_have_session() && !attached) { + attached++; + if (reattach_dmapi_session() < 0) { + return DM_NO_SESSION; + } + } + return &samba_dmapi_session; +} +uint32 dmapi_file_flags(const char * const path) +{ + dm_sessid_t dmapi_session; int err; dm_eventset_t events = {0}; uint nevents; - void *dm_handle; - size_t dm_handle_len; + void *dm_handle = NULL; + size_t dm_handle_len = 0; uint32 flags = 0; - /* If a DMAPI session has been initialised, then we need to make sure - * we are attached to it and have the correct privileges. This is - * necessary to be able to do DMAPI operations across a fork(2). If - * it fails, there is no liklihood of that failure being transient. - * - * Note that this use of the static attached flag relies on the fact - * that dmapi_file_flags() is never called prior to forking the - * per-client server process. - */ - if (dmapi_have_session() && !attached) { - attached++; - if (reattach_dmapi_session() < 0) { - return 0; - } + dmapi_session = *(dm_sessid_t*) dmapi_get_current_session(); + if (dmapi_session == DM_NO_SESSION) { + return 0; } /* AIX has DMAPI but no POSIX capablities support. In this case, @@ -313,4 +321,5 @@ done: return flags; } + #endif /* USE_DMAPI */ diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index d3813f9b41..2021621dfa 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -30,23 +30,6 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf) return 0; } -/**************************************************************************** - Work out whether this file is offline -****************************************************************************/ - -static uint32 set_offline_flag(connection_struct *conn, const char *const path) -{ - if (ISDOT(path) || ISDOTDOT(path)) { - return 0; - } - - if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) { - return 0; - } - - return dmapi_file_flags(path); -} - /**************************************************************************** Change a dos mode to a unix mode. Base permission for files: @@ -366,6 +349,8 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) { uint32 result = 0; + bool offline; + int ret; DEBUG(8,("dos_mode: %s\n", path)); @@ -395,8 +380,10 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) result |= dos_mode_from_sbuf(conn, path, sbuf); } - if (S_ISREG(sbuf->st_mode)) { - result |= set_offline_flag(conn, path); + + ret = SMB_VFS_IS_OFFLINE(conn, path, sbuf, &offline); + if (S_ISREG(sbuf->st_mode) && (ret == 0) && offline) { + result |= FILE_ATTRIBUTE_OFFLINE; } /* Optimization : Only call is_hidden_path if it's not already @@ -432,7 +419,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, int mask=0; mode_t tmp; mode_t unixmode; - int ret = -1; + int ret = -1, lret = -1; /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */ dosmode &= SAMBA_ATTRIBUTES_MASK; @@ -505,10 +492,21 @@ int file_set_dosmode(connection_struct *conn, const char *fname, unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) { - if (!newfile) { + if (dosmode & FILE_ATTRIBUTE_OFFLINE) { + lret = SMB_VFS_SET_OFFLINE(conn, fname); + if (lret == -1) { + DEBUG(0, ("set_dos_mode: client has asked to set " + "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was " + "an error while setting it or it is not supported.\n", + parent_dir, fname)); + } + } + + ret = SMB_VFS_CHMOD(conn, fname, unixmode); + if (ret == 0) { + if(!newfile || (lret != -1)) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } st->st_mode = unixmode; return 0; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e2316ef120..381ddfe151 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3329,8 +3329,12 @@ void reply_read_and_X(struct smb_request *req) return; } - if (!big_readX - && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) { + /* It is possible for VFS modules to selectively decide whether Async I/O should be used + for the file or not. + */ + if ((SMB_VFS_AIO_FORCE(fsp)) && + !big_readX && + schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) { END_PROFILE(SMBreadX); return; } @@ -4001,13 +4005,16 @@ void reply_write_and_X(struct smb_request *req) nwritten = 0; } else { - if (req->unread_bytes == 0 && - schedule_aio_write_and_X(conn, req, fsp, data, - startpos, numtowrite)) { + /* It is possible for VFS modules to selectively decide whether Async I/O + should be used for the file or not. + */ + if ((SMB_VFS_AIO_FORCE(fsp)) && (req->unread_bytes == 0) && + schedule_aio_write_and_X(conn, req, fsp, data, startpos, + numtowrite)) { END_PROFILE(SMBwriteX); return; } - + nwritten = write_file(req,fsp,data,startpos,numtowrite); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bf6802f2a6..5729ab5349 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2373,8 +2373,8 @@ static void call_trans2qfsinfo(connection_struct *conn, const char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); - int quota_flag = 0; - + uint32 additional_flags = 0; + if (total_params < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; @@ -2487,16 +2487,23 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi case SMB_QUERY_FS_ATTRIBUTE_INFO: case SMB_FS_ATTRIBUTE_INFORMATION: - + additional_flags = 0; #if defined(HAVE_SYS_QUOTAS) - quota_flag = FILE_VOLUME_QUOTAS; + additional_flags |= FILE_VOLUME_QUOTAS; #endif + if(lp_nt_acl_support(SNUM(conn))) { + additional_flags |= FILE_PERSISTENT_ACLS; + } + + if(SMB_VFS_IS_REMOTESTORAGE(conn, lp_pathname(SNUM(conn)))) { + additional_flags |= FILE_SUPPORTS_REMOTE_STORAGE; + additional_flags |= FILE_SUPPORTS_REPARSE_POINTS; + } + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| - FILE_SUPPORTS_OBJECT_IDS| - FILE_UNICODE_ON_DISK| - quota_flag); /* FS ATTRIBUTES */ + FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK| + additional_flags); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it -- cgit From 313f7d10b884d083ef9488db739465c54c3f6515 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 12:18:57 +0300 Subject: Merge latest fixes to vfs_gpfs and NFS4 ACLs from Samba 3.0 CTDB branch (from http://samba.org/~tridge/3_0-ctdb) Signed-off-by: Alexander Bokovoy (This used to be commit 1daad835cbfb4615a8fe7a241f4d578f7e69f214) --- source3/smbd/posix_acls.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 5f18615f66..6cec39f9c0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3413,6 +3413,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) bool acl_perms = False; mode_t orig_mode = (mode_t)0; NTSTATUS status; + uid_t orig_uid; + gid_t orig_gid; + bool need_chown = False; DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -3435,6 +3438,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) /* Save the original elements we check against. */ orig_mode = sbuf.st_mode; + orig_uid = sbuf.st_uid; + orig_gid = sbuf.st_gid; /* * Unpack the user/group/world id's. @@ -3449,7 +3454,11 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * Do we need to chown ? */ - if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) { + if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) { + need_chown = True; + } + + if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); @@ -3487,6 +3496,11 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) /* Save the original elements we check against. */ orig_mode = sbuf.st_mode; + orig_uid = sbuf.st_uid; + orig_gid = sbuf.st_gid; + + /* We did chown already, drop the flag */ + need_chown = False; } create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); @@ -3630,6 +3644,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) free_canon_ace_list(dir_ace_list); } + /* Any chown pending? */ + if (need_chown) { + DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); + + if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { + DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); + if (errno == EPERM) { + return NT_STATUS_INVALID_OWNER; + } + return map_nt_error_from_unix(errno); + } + } + return NT_STATUS_OK; } -- cgit From b92c3e281c66127dbd2b16b7c71e2cba4e0c1de9 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 16 Jan 2008 16:40:59 +0100 Subject: Add handling of [homes] and [printers] via registry shares. Now homes and printers shares can be accessed through the registry meachanism on demand in pure registry configurations with "config backend = registry" without the need to have a special handler for these two. Michael (This used to be commit eec3248ef90fbfe6e048394c875173b164a8b439) --- source3/smbd/service.c | 84 +++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 39 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2588a66b8b..ed8061e2f7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -219,44 +219,6 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir) return(True); } -/**************************************************************************** - Add a home service. Returns the new service number or -1 if fail. -****************************************************************************/ - -int add_home_service(const char *service, const char *username, const char *homedir) -{ - int iHomeService; - - if (!service || !homedir) - return -1; - - if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) - return -1; - - /* - * If this is a winbindd provided username, remove - * the domain component before adding the service. - * Log a warning if the "path=" parameter does not - * include any macros. - */ - - { - const char *p = strchr(service,*lp_winbind_separator()); - - /* We only want the 'user' part of the string */ - if (p) { - service = p + 1; - } - } - - if (!lp_add_home(service, iHomeService, username, homedir)) { - return -1; - } - - return lp_servicenumber(service); - -} - static int load_registry_service(const char *servicename) { struct registry_key *key; @@ -348,6 +310,47 @@ void load_registry_shares(void) return; } +/**************************************************************************** + Add a home service. Returns the new service number or -1 if fail. +****************************************************************************/ + +int add_home_service(const char *service, const char *username, const char *homedir) +{ + int iHomeService; + + if (!service || !homedir) + return -1; + + if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) { + if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) { + return -1; + } + } + + /* + * If this is a winbindd provided username, remove + * the domain component before adding the service. + * Log a warning if the "path=" parameter does not + * include any macros. + */ + + { + const char *p = strchr(service,*lp_winbind_separator()); + + /* We only want the 'user' part of the string */ + if (p) { + service = p + 1; + } + } + + if (!lp_add_home(service, iHomeService, username, homedir)) { + return -1; + } + + return lp_servicenumber(service); + +} + /** * Find a service entry. * @@ -386,7 +389,10 @@ int find_service(fstring service) if (iService < 0) { int iPrinterService; - if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) { + if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) { + iPrinterService = load_registry_service(PRINTERS_NAME); + } + if (iPrinterService) { DEBUG(3,("checking whether %s is a valid printer name...\n", service)); if (pcap_printername_ok(service)) { DEBUG(3,("%s is a valid printer name\n", service)); -- cgit From 026a66abecea3e3a54cdbfb97129d5e65608e5df Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 17 Jan 2008 14:57:35 +0300 Subject: Rework of VFS is_offline() function to only return boolean offline/online result for a file. This makes sense as upper levels are only taking returned result of 0 (no error) into consideration when deciding whether to mark file offline/online as returned from is_offline. That means that we simply can move the decision down to VFS module and clean up upper levels so that they always see only file status. If there is an error when trying to identify file status, then VFS module could decide what to return (offline or online) by itself -- after all, it ought to have system-specific knowledge anyway. (This used to be commit 75cc08661473cce62756fa062071bb2bc1fb39ec) --- source3/smbd/dosmode.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 2021621dfa..eb18f65fca 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -350,7 +350,6 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) { uint32 result = 0; bool offline; - int ret; DEBUG(8,("dos_mode: %s\n", path)); @@ -381,8 +380,8 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) } - ret = SMB_VFS_IS_OFFLINE(conn, path, sbuf, &offline); - if (S_ISREG(sbuf->st_mode) && (ret == 0) && offline) { + offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf); + if (S_ISREG(sbuf->st_mode) && offline) { result |= FILE_ATTRIBUTE_OFFLINE; } -- cgit From 03387a0f5886d449eda359a5acecd830f3bd35bc Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 17 Jan 2008 16:51:14 +0300 Subject: Remove is_remotestorage() call from VFS. We already have statvfs() there to handle FS capabilities. As discussed with Volker, it is better to calculate FS capabilities at connection time. We already do this with help of VFS statvfs() call which allows to fill-in system-specific attributes including FS capabilities. So just re-use it if you want to represent additional capabilities in your modules. The only caution is that you need to call underlying statvfs() call to actually get system-specific capabilities (and other fields) added. Then add module-specific ones. (This used to be commit e342ca0d931f9a5c8ec9e472dc9c63f1fe012b3a) --- source3/smbd/trans2.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5729ab5349..23d6f12996 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2495,12 +2495,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi if(lp_nt_acl_support(SNUM(conn))) { additional_flags |= FILE_PERSISTENT_ACLS; } - - if(SMB_VFS_IS_REMOTESTORAGE(conn, lp_pathname(SNUM(conn)))) { - additional_flags |= FILE_SUPPORTS_REMOTE_STORAGE; - additional_flags |= FILE_SUPPORTS_REPARSE_POINTS; - } - + + /* Capabilities are filled in at connection time through STATVFS call */ + additional_flags |= conn->fs_capabilities; + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK| additional_flags); /* FS ATTRIBUTES */ -- cgit From a92eb76688600efbf4a4056c2543f348e2fee8aa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 17 Jan 2008 10:24:34 +0100 Subject: Finally enable pidl generated SAMR & NETLOGON headers and clients. Guenther (This used to be commit f7100156a7df7ac3ae84e45a47153b38d9375215) --- source3/smbd/chgpasswd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fb228f9e2a..668c8e2095 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1092,7 +1092,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw if (!pdb_get_pass_can_change(hnd)) { DEBUG(1, ("user %s does not have permissions to change password\n", username)); if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_OTHER; + *samr_reject_reason = SAMR_REJECT_OTHER; } return NT_STATUS_ACCOUNT_RESTRICTION; } @@ -1106,7 +1106,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw "denied by Refuse Machine Password Change policy\n", username)); if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_OTHER; + *samr_reject_reason = SAMR_REJECT_OTHER; } return NT_STATUS_ACCOUNT_RESTRICTION; } @@ -1119,7 +1119,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw "wait until %s\n", username, http_timestring(can_change_time))); if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_OTHER; + *samr_reject_reason = SAMR_REJECT_OTHER; } return NT_STATUS_ACCOUNT_RESTRICTION; } @@ -1129,7 +1129,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_TOO_SHORT; + *samr_reject_reason = SAMR_REJECT_TOO_SHORT; } return NT_STATUS_PASSWORD_RESTRICTION; /* return NT_STATUS_PWD_TOO_SHORT; */ @@ -1137,7 +1137,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw if (check_passwd_history(hnd,new_passwd)) { if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_IN_HISTORY; + *samr_reject_reason = SAMR_REJECT_IN_HISTORY; } return NT_STATUS_PASSWORD_RESTRICTION; } @@ -1158,7 +1158,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw if (check_ret != 0) { DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n")); if (samr_reject_reason) { - *samr_reject_reason = REJECT_REASON_NOT_COMPLEX; + *samr_reject_reason = SAMR_REJECT_COMPLEXITY; } TALLOC_FREE(pass); return NT_STATUS_PASSWORD_RESTRICTION; -- cgit From c17c64530ec479334f88679ef780691e06ccd65a Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Fri, 18 Jan 2008 17:34:21 +0300 Subject: Merge DMAPI fixes from CTDB Samba (This used to be commit cf1f90ad7a79dbe5926018790bb50d4e3b36cc7b) --- source3/smbd/dmapi.c | 205 +++++++++++++++++++------------------------------- source3/smbd/server.c | 6 -- 2 files changed, 78 insertions(+), 133 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 620baf199e..a410748ccf 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -25,9 +25,9 @@ #ifndef USE_DMAPI -int dmapi_init_session(void) { return -1; } uint32 dmapi_file_flags(const char * const path) { return 0; } bool dmapi_have_session(void) { return False; } +const void * dmapi_get_current_session(void) { return NULL; } #else /* USE_DMAPI */ @@ -48,90 +48,48 @@ bool dmapi_have_session(void) { return False; } static dm_sessid_t samba_dmapi_session = DM_NO_SESSION; -/* Initialise the DMAPI interface. Make sure that we only end up initialising - * once per process to avoid resource leaks across different DMAPI - * implementations. - */ -static int init_dmapi_service(void) -{ - static pid_t lastpid; - - pid_t mypid; - - mypid = sys_getpid(); - if (mypid != lastpid) { - char *version; - - lastpid = mypid; - if (dm_init_service(&version) < 0) { - return -1; - } - - DEBUG(0, ("Initializing DMAPI: %s\n", version)); - } - - return 0; -} - -bool dmapi_have_session(void) -{ - return samba_dmapi_session != DM_NO_SESSION; -} - -static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) -{ - dm_sessid_t *nsessions; - - nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); - if (nsessions == NULL) { - TALLOC_FREE(sessions); - return NULL; - } - return nsessions; -} - -/* Initialise DMAPI session. The session is persistant kernel state, so it - * might already exist, in which case we merely want to reconnect to it. This - * function should be called as root. - */ -int dmapi_init_session(void) +/* + Initialise DMAPI session. The session is persistant kernel state, + so it might already exist, in which case we merely want to + reconnect to it. This function should be called as root. +*/ +static int dmapi_init_session(void) { char buf[DM_SESSION_INFO_LEN]; size_t buflen; - - uint nsessions = 10; + uint nsessions = 5; dm_sessid_t *sessions = NULL; + char *version; int i, err; - /* If we aren't root, something in the following will fail due to lack - * of privileges. Aborting seems a little extreme. - */ - SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); - - samba_dmapi_session = DM_NO_SESSION; - if (init_dmapi_service() < 0) { + if (dm_init_service(&version) < 0) { + DEBUG(0, ("dm_init_service failed - disabling DMAPI\n")); return -1; } -retry: + ZERO_STRUCT(buf); - if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { - return -1; - } - - err = dm_getall_sessions(nsessions, sessions, &nsessions); - if (err < 0) { - if (errno == E2BIG) { - nsessions *= 2; - goto retry; + do { + dm_sessid_t *new_sessions; + nsessions *= 2; + new_sessions = TALLOC_REALLOC_ARRAY(NULL, sessions, + dm_sessid_t, nsessions); + if (new_sessions == NULL) { + talloc_free(sessions); + return -1; } + sessions = new_sessions; + err = dm_getall_sessions(nsessions, sessions, &nsessions); + } while (err == -1 && errno == E2BIG); + + if (err == -1) { DEBUGADD(DMAPI_TRACE, ("failed to retrieve DMAPI sessions: %s\n", strerror(errno))); - TALLOC_FREE(sessions); + talloc_free(sessions); return -1; } @@ -147,7 +105,7 @@ retry: } } - TALLOC_FREE(sessions); + talloc_free(sessions); /* No session already defined. */ if (samba_dmapi_session == DM_NO_SESSION) { @@ -162,91 +120,84 @@ retry: return -1; } - DEBUGADD(DMAPI_TRACE, - ("created new DMAPI session named '%s'\n", - DMAPI_SESSION_NAME)); + DEBUG(0, ("created new DMAPI session named '%s' for %s\n", + DMAPI_SESSION_NAME, version)); + } + + if (samba_dmapi_session != DM_NO_SESSION) { + set_effective_capability(DMAPI_ACCESS_CAPABILITY); } - /* Note that we never end the DMAPI session. This enables child - * processes to continue to use the session after we exit. It also lets - * you run a second Samba server on different ports without any - * conflict. + /* + Note that we never end the DMAPI session. It gets re-used if possiblie. + DMAPI session is a kernel resource that is usually lives until server reboot + and doesn't get destroed when an application finishes. */ return 0; } -/* Reattach to an existing dmapi session. Called from service processes that - * might not be running as root. - */ -static int reattach_dmapi_session(void) +/* + Return a pointer to our DMAPI session, if available. + This assumes that you have called dmapi_have_session() first. +*/ +const void *dmapi_get_current_session(void) { - char buf[DM_SESSION_INFO_LEN]; - size_t buflen; - - if (samba_dmapi_session != DM_NO_SESSION ) { - become_root(); - - /* NOTE: On Linux, this call opens /dev/dmapi, costing us a - * file descriptor. Ideally, we would close this when we fork. - */ - if (init_dmapi_service() < 0) { - samba_dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - if (dm_query_session(samba_dmapi_session, sizeof(buf), - buf, &buflen) < 0) { - /* Session is stale. Disable DMAPI. */ - samba_dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - set_effective_capability(DMAPI_ACCESS_CAPABILITY); - - DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); - unbecome_root(); + if (samba_dmapi_session == DM_NO_SESSION) { + return NULL; } - return 0; + return (void *)&samba_dmapi_session; } + +/* + dmapi_have_session() must be the first DMAPI call you make in Samba. It will + initialize DMAPI, if available, and tell you if you can get a DMAPI session. + This should be called in the client-specific child process. +*/ -/* If a DMAPI session has been initialised, then we need to make sure - * we are attached to it and have the correct privileges. This is - * necessary to be able to do DMAPI operations across a fork(2). If - * it fails, there is no likelihood of that failure being transient. - * - * Note that this use of the static attached flag relies on the fact - * that dmapi_file_flags() is never called prior to forking the - * per-client server process. - */ -const void * dmapi_get_current_session(void) +bool dmapi_have_session(void) { - static int attached = 0; - if (dmapi_have_session() && !attached) { - attached++; - if (reattach_dmapi_session() < 0) { - return DM_NO_SESSION; - } + static bool initialized; + if (!initialized) { + initialized = true; + + become_root(); + dmapi_init_session(); + unbecome_root(); + } - return &samba_dmapi_session; + + return samba_dmapi_session != DM_NO_SESSION; } +/* + This is default implementation of dmapi_file_flags() that is + called from VFS is_offline() call to know whether file is offline. + For GPFS-specific version see modules/vfs_tsmsm.c. It might be + that approach on quering existence of a specific attribute that + is used in vfs_tsmsm.c will work with other DMAPI-based HSM + implementations as well. +*/ uint32 dmapi_file_flags(const char * const path) { - dm_sessid_t dmapi_session; int err; dm_eventset_t events = {0}; uint nevents; + dm_sessid_t dmapi_session; + void *dmapi_session_ptr; void *dm_handle = NULL; size_t dm_handle_len = 0; uint32 flags = 0; - dmapi_session = *(dm_sessid_t*) dmapi_get_current_session(); + dmapi_session_ptr = dmapi_get_current_session(); + if (dmapi_session_ptr == NULL) { + return 0; + } + + dmapi_session = *(dm_sessid_t *)dmapi_session_ptr; if (dmapi_session == DM_NO_SESSION) { return 0; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index db241103ed..7116027adf 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1313,12 +1313,6 @@ extern void build_options(bool screen); if ( is_daemon && !interactive ) start_background_queue(); - /* Always attempt to initialize DMAPI. We will only use it later if - * lp_dmapi_support is set on the share, but we need a single global - * session to work with. - */ - dmapi_init_session(); - if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); -- cgit From 145ab107b2670b3d645c6757d0a3930eaff6c4d0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 17 Jan 2008 17:48:33 +0100 Subject: Always return nlink=1 for directories I did not test it, but it should not affect cifsfs, there are special posix calls that also return the stat information unfiltered. (This used to be commit e96cf1309e45628f4c27d03f77a4eef5e00602df) --- source3/smbd/trans2.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 23d6f12996..763b6480e3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3745,11 +3745,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, nlink = sbuf.st_nlink; - if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) { - /* NTFS does not seem to count ".." */ - nlink -= 1; - } - if ((nlink > 0) && delete_pending) { nlink -= 1; } @@ -4018,7 +4013,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,nlink); + SIVAL(pdata,16,(mode&aDIR)?1:nlink); SCVAL(pdata,20,delete_pending?1:0); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); /* Padding. */ @@ -4096,7 +4091,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,nlink); + SIVAL(pdata,16,(mode&aDIR)?1:nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); -- cgit From ca6cf1fe94f096aac846d0111b39006bdd40b7e3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Jan 2008 18:39:27 -0800 Subject: Actually test vl's new code and make it work to fix the build farm :-). Jeremy. (This used to be commit 63defd3e9d4ba3f02f36ec5ad7b73463f31962a1) --- source3/smbd/trans2.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 763b6480e3..935a881607 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3743,12 +3743,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } } - nlink = sbuf.st_nlink; - - if ((nlink > 0) && delete_pending) { - nlink -= 1; - } - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; @@ -3767,6 +3761,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn, if (!mode) mode = FILE_ATTRIBUTE_NORMAL; + nlink = sbuf.st_nlink; + + if (nlink && (mode&aDIR)) { + nlink = 1; + } + + if ((nlink > 0) && delete_pending) { + nlink -= 1; + } + fullpathname = fname; if (!(mode & aDIR)) file_size = get_file_size(sbuf); @@ -4013,7 +4017,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,(mode&aDIR)?1:nlink); + SIVAL(pdata,16,nlink); SCVAL(pdata,20,delete_pending?1:0); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); /* Padding. */ @@ -4091,7 +4095,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,(mode&aDIR)?1:nlink); + SIVAL(pdata,16,nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); -- cgit From 6d7eb2e6ecec5920fe347c5d75d8596bd289eecf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 15 Jan 2008 13:22:39 +0100 Subject: Make get_ea_value public (This used to be commit 0aa406bbba8699063ea3758b19dca24cf42ff15a) --- source3/smbd/trans2.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 935a881607..12b0f20879 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -114,8 +114,9 @@ static bool samba_private_attr_name(const char *unix_ea_name) Get one EA value. Fill in a struct ea_struct. ****************************************************************************/ -static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, - const char *fname, char *ea_name, struct ea_struct *pea) +NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, + files_struct *fsp, const char *fname, + const char *ea_name, struct ea_struct *pea) { /* Get the value of this xattr. Max size is 64k. */ size_t attr_size = 256; @@ -126,7 +127,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size); if (!val) { - return False; + return NT_STATUS_NO_MEMORY; } if (fsp && fsp->fh->fd != -1) { @@ -141,7 +142,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str } if (sizeret == -1) { - return False; + return map_nt_error_from_unix(errno); } DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret)); @@ -149,13 +150,17 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str pea->flags = 0; if (strnequal(ea_name, "user.", 5)) { - pea->name = &ea_name[5]; + pea->name = talloc_strdup(mem_ctx, &ea_name[5]); } else { - pea->name = ea_name; + pea->name = talloc_strdup(mem_ctx, ea_name); + } + if (pea->name == NULL) { + TALLOC_FREE(val); + return NT_STATUS_NO_MEMORY; } pea->value.data = (unsigned char *)val; pea->value.length = (size_t)sizeret; - return True; + return NT_STATUS_OK; } /**************************************************************************** @@ -215,7 +220,9 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str if (!listp) return NULL; - if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) { + if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp, + fname, p, + &listp->ea))) { return NULL; } -- cgit From 84518f1fc74437c61b79080671f3adfd809b2c32 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 16:07:56 +0100 Subject: Add get_ea_names_from_file to sanely list posix xattrs Refactor get_ea_list_from_file to use that. (This used to be commit aec357a456798050abe565d2a744ed5f17ad5901) --- source3/smbd/trans2.c | 191 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 142 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 12b0f20879..53eff65b54 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -163,86 +163,179 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, return NT_STATUS_OK; } -/**************************************************************************** - Return a linked list of the total EA's. Plus the total size -****************************************************************************/ - -static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, - const char *fname, size_t *pea_total_len) +NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, + files_struct *fsp, const char *fname, + char ***pnames, size_t *pnum_names) { /* Get a list of all xattrs. Max namesize is 64k. */ size_t ea_namelist_size = 1024; - char *ea_namelist; + char *ea_namelist = NULL; + char *p; + char **names, **tmp; + size_t num_names; ssize_t sizeret; - int i; - struct ea_list *ea_list_head = NULL; - - *pea_total_len = 0; if (!lp_ea_support(SNUM(conn))) { - return NULL; + *pnames = NULL; + *pnum_names = 0; + return NT_STATUS_OK; } - for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6; - ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { + /* + * TALLOC the result early to get the talloc hierarchy right. + */ - if (!ea_namelist) { - return NULL; + names = TALLOC_ARRAY(mem_ctx, char *, 1); + if (names == NULL) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + while (ea_namelist_size <= 65536) { + + ea_namelist = TALLOC_REALLOC_ARRAY( + names, ea_namelist, char, ea_namelist_size); + if (ea_namelist == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(names); + return NT_STATUS_NO_MEMORY; } if (fsp && fsp->fh->fd != -1) { - sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, ea_namelist_size); + sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, + ea_namelist_size); } else { - sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size); + sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, + ea_namelist_size); } - if (sizeret == -1 && errno == ERANGE) { + if ((sizeret == -1) && (errno = ERANGE)) { ea_namelist_size *= 2; - } else { + } + else { break; } } - if (sizeret == -1) - return NULL; + if (sizeret == -1) { + TALLOC_FREE(names); + return map_nt_error_from_unix(errno); + } - DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret )); + DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n", + (unsigned int)sizeret)); - if (sizeret) { - for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { - struct ea_list *listp; + if (sizeret == 0) { + TALLOC_FREE(names); + *pnames = NULL; + *pnum_names = 0; + return NT_STATUS_OK; + } - if (strnequal(p, "system.", 7) || samba_private_attr_name(p)) - continue; + /* + * Ensure the result is 0-terminated + */ - listp = TALLOC_P(mem_ctx, struct ea_list); - if (!listp) - return NULL; + if (ea_namelist[sizeret-1] != '\0') { + TALLOC_FREE(names); + return NT_STATUS_INTERNAL_ERROR; + } - if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp, - fname, p, - &listp->ea))) { - return NULL; - } + /* + * count the names + */ + num_names = 0; - { - fstring dos_ea_name; - push_ascii_fstring(dos_ea_name, listp->ea.name); - *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; - DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n", - (unsigned int)*pea_total_len, dos_ea_name, - (unsigned int)listp->ea.value.length )); - } - DLIST_ADD_END(ea_list_head, listp, struct ea_list *); + for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) { + num_names += 1; + } + + tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names); + if (tmp == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(names); + return NT_STATUS_NO_MEMORY; + } + + names = tmp; + num_names = 0; + + for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) { + names[num_names++] = p; + } + + *pnames = names; + *pnum_names = num_names; + return NT_STATUS_OK; +} + +/**************************************************************************** + Return a linked list of the total EA's. Plus the total size +****************************************************************************/ + +static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, + const char *fname, size_t *pea_total_len) +{ + /* Get a list of all xattrs. Max namesize is 64k. */ + size_t i, num_names; + char **names; + struct ea_list *ea_list_head = NULL; + NTSTATUS status; + + *pea_total_len = 0; + + if (!lp_ea_support(SNUM(conn))) { + return NULL; + } + + status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname, + &names, &num_names); + + if (!NT_STATUS_IS_OK(status) || (num_names == 0)) { + return NULL; + } + + for (i=0; iea))) { + return NULL; } + + push_ascii_fstring(dos_ea_name, listp->ea.name); + + *pea_total_len += + 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; + + DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len " + "= %u\n", (unsigned int)*pea_total_len, dos_ea_name, + (unsigned int)listp->ea.value.length)); + + DLIST_ADD_END(ea_list_head, listp, struct ea_list *); + } - DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len)); + /* Add on 4 for total length. */ + if (*pea_total_len) { + *pea_total_len += 4; + } + + DEBUG(10, ("get_ea_list_from_file: total_len = %u\n", + (unsigned int)*pea_total_len)); + return ea_list_head; } -- cgit From 1b976d51928dd6fa923272d277e13e5267188869 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 20:41:15 +0100 Subject: Add the STREAMINFO vfs call Based on jpeach's work, modified the streaminfo prototype Make use of it in trans2.c together with marshall_stream_info() (This used to be commit c34d729c7c0600a8f11bf7e489a634a4e37fe88e) --- source3/smbd/trans2.c | 112 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 53eff65b54..d56a0dab09 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5,7 +5,7 @@ Copyright (C) Stefan (metze) Metzmacher 2003 Copyright (C) Volker Lendecke 2005-2007 Copyright (C) Steve French 2005 - Copyright (C) James Peach 2007 + Copyright (C) James Peach 2006-2007 Extensively modified by Andrew Tridgell, 1995 @@ -3568,6 +3568,72 @@ static char *store_file_unix_basic_info2(connection_struct *conn, return pdata; } +static NTSTATUS marshall_stream_info(unsigned int num_streams, + const struct stream_struct *streams, + char *data, + unsigned int max_data_bytes, + unsigned int *data_size) +{ + unsigned int i; + unsigned int ofs = 0; + + for (i=0; i max_data_bytes) { + TALLOC_FREE(namebuf); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + SIVAL(data, ofs+4, namelen); + SOFF_T(data, ofs+8, streams[i].size); + SOFF_T(data, ofs+16, streams[i].alloc_size); + memcpy(data+ofs+24, namebuf, namelen); + TALLOC_FREE(namebuf); + + next_offset = ofs + 24 + namelen; + + if (i == num_streams-1) { + SIVAL(data, ofs, 0); + } + else { + unsigned int align = ndr_align_size(next_offset, 8); + + if (next_offset + align > max_data_bytes) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + memset(data+next_offset, 0, align); + next_offset += align; + + SIVAL(data, ofs, next_offset - ofs); + ofs = next_offset; + } + + ofs = next_offset; + } + + *data_size = ofs; + + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a TRANSACT2_QFILEINFO on a PIPE ! ****************************************************************************/ @@ -4273,20 +4339,40 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd */ case SMB_QUERY_FILE_STREAM_INFO: #endif - case SMB_FILE_STREAM_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n")); - if (mode & aDIR) { - data_size = 0; - } else { - size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False); - SIVAL(pdata,0,0); /* ??? */ - SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ - SOFF_T(pdata,8,file_size); - SOFF_T(pdata,16,allocation_size); - data_size = 24 + byte_len; + case SMB_FILE_STREAM_INFORMATION: { + unsigned int num_streams; + struct stream_struct *streams; + NTSTATUS status; + + DEBUG(10,("call_trans2qfilepathinfo: " + "SMB_FILE_STREAM_INFORMATION\n")); + + status = SMB_VFS_STREAMINFO( + conn, fsp, fname, talloc_tos(), + &num_streams, &streams); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("could not get stream info: %s\n", + nt_errstr(status))); + reply_nterror(req, status); + return; } - break; + status = marshall_stream_info(num_streams, streams, + pdata, max_data_bytes, + &data_size); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("marshall_stream_info failed: %s\n", + nt_errstr(status))); + reply_nterror(req, status); + return; + } + + TALLOC_FREE(streams); + + break; + } case SMB_QUERY_COMPRESSION_INFO: case SMB_FILE_COMPRESSION_INFORMATION: DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n")); -- cgit From 2411c6cb90e485bd289b8b654db1c632556bfb2d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 23:10:09 +0100 Subject: Add "split_ntfs_stream_name()" together with a torture test (This used to be commit d813bd9e02d9baf916eb96c478be89f0c435e07c) --- source3/smbd/nttrans.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e8df732ea2..9381174af0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -271,6 +271,9 @@ void send_nt_replies(connection_struct *conn, /**************************************************************************** Is it an NTFS stream name ? + An NTFS file name is .:: + $DATA can be used as both a stream name and a stream type. A missing stream + name or type implies $DATA. ****************************************************************************/ bool is_ntfs_stream_name(const char *fname) -- cgit From 1069cfe4ade88a032164c1242c9480a544584655 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 23:25:36 +0100 Subject: Add streams support This is the core of the streams support. The main change is that in files_struct there is now a base_fsp pointer that holds the main file open while a stream is open. This is necessary to get the rather strange delete semantics right: You can't delete the main file while a stream is open without FILE_SHARE_DELETE, and while a stream is open a successful unlink of the main file leads to DELETE_PENDING for all further access on the main file or any stream. (This used to be commit 6022873cc155bdbbd3fb620689715f07a24d6ed1) --- source3/smbd/close.c | 115 +++++++++++++++++++++++++- source3/smbd/filename.c | 121 +++++++++++++++++++++++++++ source3/smbd/open.c | 214 +++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/reply.c | 28 +++++-- 4 files changed, 454 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4c385d7611..4bd23a35fc 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -155,6 +155,75 @@ static void notify_deferred_opens(struct share_mode_lock *lck) } } +/**************************************************************************** + Delete all streams +****************************************************************************/ + +static NTSTATUS delete_all_streams(connection_struct *conn, const char *fname) +{ + struct stream_struct *stream_info; + int i; + unsigned int num_streams; + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + + status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), + &num_streams, &stream_info); + + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + DEBUG(10, ("no streams around\n")); + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n", + nt_errstr(status))); + goto fail; + } + + DEBUG(10, ("delete_all_streams found %d streams\n", + num_streams)); + + if (num_streams == 0) { + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + for (i=0; ifs_capabilities & FILE_NAMED_STREAMS) + && !is_ntfs_stream_name(fsp->fsp_name)) { + + status = delete_all_streams(conn, fsp->fsp_name); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5, ("delete_all_streams failed: %s\n", + nt_errstr(status))); + goto done; + } + } + + if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { /* * This call can potentially fail as another smbd may @@ -570,12 +652,37 @@ static NTSTATUS close_stat(files_struct *fsp) NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type) { + NTSTATUS status; + struct files_struct *base_fsp = fsp->base_fsp; + if(fsp->is_directory) { - return close_directory(fsp, close_type); + status = close_directory(fsp, close_type); } else if (fsp->is_stat) { - return close_stat(fsp); + status = close_stat(fsp); } else if (fsp->fake_file_handle != NULL) { - return close_fake_file(fsp); + status = close_fake_file(fsp); + } else { + status = close_normal_file(fsp, close_type); + } + + if (!NT_STATUS_IS_OK(status)) { + return status; } - return close_normal_file(fsp, close_type); + + if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) { + + /* + * fsp was a stream, the base fsp can't be a stream as well + * + * For SHUTDOWN_CLOSE this is not possible here, because + * SHUTDOWN_CLOSE only happens from files.c which walks the + * complete list of files. If we mess with more than one fsp + * those loops will become confused. + */ + + SMB_ASSERT(base_fsp->base_fsp == NULL); + close_file(base_fsp, close_type); + } + + return status; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index be4960cab8..1d44c7498e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -28,6 +28,13 @@ static bool scan_directory(connection_struct *conn, const char *path, char *name, char **found_name); +static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, + connection_struct *conn, + const char *orig_path, + const char *basepath, + const char *streamname, + SMB_STRUCT_STAT *pst, + char **path); /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. @@ -119,6 +126,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, char *start, *end; char *dirpath = NULL; char *name = NULL; + char *stream = NULL; bool component_was_mangled = False; bool name_has_wildcard = False; NTSTATUS result; @@ -206,6 +214,18 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } + stream = strchr_m(name, ':'); + + if (stream != NULL) { + char *tmp = talloc_strdup(ctx, stream); + if (tmp == NULL) { + TALLOC_FREE(name); + return NT_STATUS_NO_MEMORY; + } + *stream = '\0'; + stream = tmp; + } + /* * Large directory fix normalization. If we're case sensitive, and * the case preserving parameters are set to "no", normalize the case of @@ -653,6 +673,20 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); done: + if (stream != NULL) { + char *tmp = NULL; + + result = build_stream_path(ctx, conn, orig_path, name, stream, + pst, &tmp); + if (!NT_STATUS_IS_OK(result)) { + goto fail; + } + + DEBUG(10, ("build_stream_path returned %s\n", tmp)); + + TALLOC_FREE(name); + name = tmp; + } *pp_conv_path = name; TALLOC_FREE(dirpath); return NT_STATUS_OK; @@ -823,3 +857,90 @@ static bool scan_directory(connection_struct *conn, const char *path, errno = ENOENT; return False; } + +static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, + connection_struct *conn, + const char *orig_path, + const char *basepath, + const char *streamname, + SMB_STRUCT_STAT *pst, + char **path) +{ + SMB_STRUCT_STAT st; + char *result = NULL; + NTSTATUS status; + unsigned int i, num_streams; + struct stream_struct *streams = NULL; + + result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (SMB_VFS_STAT(conn, result, &st) == 0) { + *pst = st; + *path = result; + return NT_STATUS_OK; + } + + if (errno != ENOENT) { + status = map_nt_error_from_unix(errno); + DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status))); + goto fail; + } + + status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx, + &num_streams, &streams); + + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + SET_STAT_INVALID(*pst); + *path = result; + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status))); + goto fail; + } + + for (i=0; icase_sensitive)) { + DEBUGADD(10, ("equal\n")); + break; + } + DEBUGADD(10, ("not equal\n")); + } + + if (i == num_streams) { + SET_STAT_INVALID(*pst); + *path = result; + TALLOC_FREE(streams); + return NT_STATUS_OK; + } + + TALLOC_FREE(result); + + result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name); + if (result == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + SET_STAT_INVALID(*pst); + + if (SMB_VFS_STAT(conn, result, pst) == 0) { + stat_cache_add(orig_path, result, conn->case_sensitive); + } + + *path = result; + TALLOC_FREE(streams); + return NT_STATUS_OK; + + fail: + TALLOC_FREE(result); + TALLOC_FREE(streams); + return status; +} diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9d48bcc98b..0d6e07a032 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1842,7 +1842,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); /* Handle strange delete on close create semantics. */ - if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) { + if ((create_options & FILE_DELETE_ON_CLOSE) + && (is_ntfs_stream_name(fname) + || can_set_initial_delete_on_close(lck))) { status = can_set_delete_on_close(fsp, True, new_dos_attributes); if (!NT_STATUS_IS_OK(status)) { @@ -2443,6 +2445,115 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx return result; } +/* + * If a main file is opened for delete, all streams need to be checked for + * !FILE_SHARE_DELETE. Do this by opening with DELETE_ACCESS. + * If that works, delete them all by setting the delete on close and close. + */ + +static NTSTATUS open_streams_for_delete(connection_struct *conn, + const char *fname) +{ + struct stream_struct *stream_info; + files_struct **streams; + int i; + unsigned int num_streams; + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + + status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), + &num_streams, &stream_info); + + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + DEBUG(10, ("no streams around\n")); + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n", + nt_errstr(status))); + goto fail; + } + + DEBUG(10, ("open_streams_for_delete found %d streams\n", + num_streams)); + + if (num_streams == 0) { + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + streams = TALLOC_ARRAY(talloc_tos(), files_struct *, num_streams); + if (streams == NULL) { + DEBUG(0, ("talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + for (i=0; i= 0; i--) { + if (streams[i] == NULL) { + continue; + } + + DEBUG(10, ("Closing stream # %d, %s\n", i, + streams[i]->fsp_name)); + close_file(streams[i], NORMAL_CLOSE); + } + + fail: + TALLOC_FREE(frame); + return status; +} + /* * Wrapper around open_file_ntcreate and open_directory */ @@ -2466,6 +2577,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, { SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; + files_struct *base_fsp = NULL; files_struct *fsp = NULL; NTSTATUS status; @@ -2495,7 +2607,23 @@ NTSTATUS create_file_unixpath(connection_struct *conn, sbuf = *psbuf; } else { - SET_STAT_INVALID(sbuf); + if (SMB_VFS_STAT(conn, fname, &sbuf) == -1) { + SET_STAT_INVALID(sbuf); + } + } + + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && (access_mask & DELETE_ACCESS) + && !is_ntfs_stream_name(fname)) { + /* + * We can't open a file with DELETE access if any of the + * streams is open without FILE_SHARE_DELETE + */ + status = open_streams_for_delete(conn, fname); + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } } /* This is the correct thing to do (check every time) but can_delete @@ -2528,12 +2656,61 @@ NTSTATUS create_file_unixpath(connection_struct *conn, } #endif + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && is_ntfs_stream_name(fname) + && (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) { + char *base; + uint32 base_create_disposition; + + if (create_options & FILE_DIRECTORY_FILE) { + status = NT_STATUS_NOT_A_DIRECTORY; + goto fail; + } + + status = split_ntfs_stream_name(talloc_tos(), fname, + &base, NULL); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("split_ntfs_stream_name failed: %s\n", + nt_errstr(status))); + goto fail; + } + + SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */ + + switch (create_disposition) { + case FILE_OPEN: + base_create_disposition = FILE_OPEN; + break; + default: + base_create_disposition = FILE_OPEN_IF; + break; + } + + status = create_file_unixpath(conn, NULL, base, 0, + FILE_SHARE_READ + | FILE_SHARE_WRITE + | FILE_SHARE_DELETE, + base_create_disposition, + 0, 0, 0, 0, NULL, NULL, + &base_fsp, NULL, NULL); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("create_file_unixpath for base %s failed: " + "%s\n", base, nt_errstr(status))); + goto fail; + } + } + /* * If it's a request for a directory open, deal with it separately. */ if (create_options & FILE_DIRECTORY_FILE) { + if (create_options & FILE_NON_DIRECTORY_FILE) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { status = NT_STATUS_INVALID_PARAMETER; @@ -2664,6 +2841,16 @@ NTSTATUS create_file_unixpath(connection_struct *conn, DEBUG(10, ("create_file: info=%d\n", info)); + /* + * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In + * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would + * also close fsp->base_fsp which we have to also do explicitly in + * this routine here, as not in all "goto fail:" we have the fsp set + * up already to be initialized with the base_fsp. + */ + + fsp->base_fsp = base_fsp; + *result = fsp; if (pinfo != NULL) { *pinfo = info; @@ -2685,6 +2872,10 @@ NTSTATUS create_file_unixpath(connection_struct *conn, close_file(fsp, ERROR_CLOSE); fsp = NULL; } + if (base_fsp != NULL) { + close_file(base_fsp, ERROR_CLOSE); + base_fsp = NULL; + } return status; } @@ -2812,19 +3003,18 @@ NTSTATUS create_file(connection_struct *conn, status = NT_STATUS_NO_MEMORY; goto fail; } - } else { - /* - * Check to see if this is a mac fork of some kind. - */ + } + + /* + * Check to see if this is a mac fork of some kind. + */ - if (is_ntfs_stream_name(fname)) { - enum FAKE_FILE_TYPE fake_file_type; + if (is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type; - fake_file_type = is_fake_file(fname); + fake_file_type = is_fake_file(fname); - if (fake_file_type == FAKE_FILE_TYPE_NONE) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } + if (fake_file_type != FAKE_FILE_TYPE_NONE) { /* * Here we go! support for changing the disk quotas diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 381ddfe151..61ec611b6b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -167,6 +167,10 @@ static NTSTATUS check_path_syntax_internal(char *path, } *d = '\0'; + + if (NT_STATUS_IS_OK(ret) && !posix_path) { + ret = split_ntfs_stream_name(NULL, path, NULL, NULL); + } return ret; } @@ -2289,14 +2293,22 @@ static NTSTATUS do_unlink(connection_struct *conn, /* On open checks the open itself will check the share mode, so don't do it here as we'll get it wrong. */ - status = open_file_ntcreate(conn, req, fname, &sbuf, - DELETE_ACCESS, - FILE_SHARE_NONE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - req != NULL ? 0 : INTERNAL_OPEN_ONLY, - NULL, &fsp); + status = create_file_unixpath + (conn, /* conn */ + req, /* req */ + fname, /* fname */ + DELETE_ACCESS, /* access_mask */ + FILE_SHARE_NONE, /* share_access */ + FILE_OPEN, /* create_disposition*/ + FILE_NON_DIRECTORY_FILE, /* create_options */ + FILE_ATTRIBUTE_NORMAL, /* file_attributes */ + 0, /* oplock_request */ + 0, /* allocation_size */ + NULL, /* sd */ + NULL, /* ea_list */ + &fsp, /* result */ + NULL, /* pinfo */ + &sbuf); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("open_file_ntcreate failed: %s\n", -- cgit From 0bb6fb7b6f8ea1c039e710f55bba779363716f2d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Jan 2008 21:53:49 -0800 Subject: Couple of minor fixes for POSIX pathname processing in the new stream code. (1) In smbd/filename, don't split the name at ':' if we know it's a posix path (this should be parameterized....). (2). When calling posix_mkdir, we get the flag FILE_FLAG_POSIX_SEMANTICS passed to open_directory(). I know for a posix client lp_posix_pathnames should be true (which is checked for in is_ntfs_stream_name() but we have an explicit flag here, so let's use it. Jeremy. (This used to be commit 7bb7a0def6518784befa75e5303289d2b4d36dd4) --- source3/smbd/filename.c | 18 ++++++++++-------- source3/smbd/open.c | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1d44c7498e..10e9583049 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -214,16 +214,18 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - stream = strchr_m(name, ':'); + if (!lp_posix_pathnames()) { + stream = strchr_m(name, ':'); - if (stream != NULL) { - char *tmp = talloc_strdup(ctx, stream); - if (tmp == NULL) { - TALLOC_FREE(name); - return NT_STATUS_NO_MEMORY; + if (stream != NULL) { + char *tmp = talloc_strdup(ctx, stream); + if (tmp == NULL) { + TALLOC_FREE(name); + return NT_STATUS_NO_MEMORY; + } + *stream = '\0'; + stream = tmp; } - *stream = '\0'; - stream = tmp; } /* diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d6e07a032..ad221c3227 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2106,7 +2106,7 @@ NTSTATUS open_directory(connection_struct *conn, (unsigned int)create_disposition, (unsigned int)file_attributes)); - if (is_ntfs_stream_name(fname)) { + if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) && is_ntfs_stream_name(fname)) { DEBUG(2, ("open_directory: %s is a stream name!\n", fname)); return NT_STATUS_NOT_A_DIRECTORY; } -- cgit From f87d08f6222f3e86b771c9c8ef669c1872118f6b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 14:43:30 +0100 Subject: Don't test split_ntfs_stream_name This is a hot code path, and if it has a :, the name will be split later on anyway. (This used to be commit 9f7f6b812d89decea1456ccdc37978e645d11a63) --- source3/smbd/reply.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 61ec611b6b..5a5eb1e190 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -168,9 +168,6 @@ static NTSTATUS check_path_syntax_internal(char *path, *d = '\0'; - if (NT_STATUS_IS_OK(ret) && !posix_path) { - ret = split_ntfs_stream_name(NULL, path, NULL, NULL); - } return ret; } -- cgit From 896ec681816b38d85e3dfbb45e9df8993de42899 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 14:44:07 +0100 Subject: NT_STATUS_OBJECT_NAME_NOT_FOUND also means "no streams around :-)" (This used to be commit 96b9a7b3eb92c9f133a3f43ffc4d57d0212e4ebd) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ad221c3227..f55728665f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2464,7 +2464,8 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn, status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), &num_streams, &stream_info); - if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) + || NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { DEBUG(10, ("no streams around\n")); TALLOC_FREE(frame); return NT_STATUS_OK; -- cgit From 043a7e177476d4c281b74d6ce997219f3009744a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 15:59:31 +0100 Subject: Activate SMB_QUERY_FILE_STREAM_INFO gcolley was right, my nt4 does not blue screen with it (This used to be commit 9f2b5dc1865ca109e1e34c91548479ad9b26f450) --- source3/smbd/trans2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d56a0dab09..9c48cdfbba 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4331,14 +4331,15 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 4; break; -#if 0 /* - * NT4 server just returns "invalid query" to this - if we try to answer - * it then NTws gets a BSOD! (tridge). - * W2K seems to want this. JRA. + * NT4 server just returns "invalid query" to this - if we try + * to answer it then NTws gets a BSOD! (tridge). W2K seems to + * want this. JRA. + */ + /* The first statement above is false - verified using Thursby + * client against NT4 -- gcolley. */ case SMB_QUERY_FILE_STREAM_INFO: -#endif case SMB_FILE_STREAM_INFORMATION: { unsigned int num_streams; struct stream_struct *streams; -- cgit From b1017bb551fd28d2f9562acb1ff7f0dde933417a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 17:32:19 +0100 Subject: Free case_state earlier Found by a "set but never used" warning. Thanks to talloc_tos() this was not really a bug, but this way the code becomes much clearer. (This used to be commit b326f11dc39a8ce20d957aac976be0cf7108ba9d) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f55728665f..9fca38e3ed 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3080,6 +3080,8 @@ NTSTATUS create_file(connection_struct *conn, fname = converted_fname; } + TALLOC_FREE(case_state); + /* All file access must go through check_name() */ status = check_name(conn, fname); -- cgit From 33f3eeaa00974860dfc45962d5fd34cf05396c76 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 17:35:25 +0100 Subject: Fix some "set but never used" warnings (This used to be commit 4a6dadc5178f4861e9c032321939db3b639734b5) --- source3/smbd/reply.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5a5eb1e190..4ea81a3819 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3375,7 +3375,6 @@ void error_to_writebrawerr(struct smb_request *req) void reply_writebraw(struct smb_request *req) { connection_struct *conn = req->conn; - int outsize = 0; char *buf = NULL; ssize_t nwritten=0; ssize_t total_written=0; @@ -3485,8 +3484,7 @@ void reply_writebraw(struct smb_request *req) * it to send more bytes */ memcpy(buf, req->inbuf, smb_size); - outsize = srv_set_message(buf, - Protocol>PROTOCOL_COREPLUS?1:0,0,True); + srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); SCVAL(buf,smb_com,SMBwritebraw); SSVALS(buf,smb_vwv0,0xFFFF); show_msg(buf); -- cgit From 9a226532221b88369b913bc9f9d6ec335620349f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 21 Jan 2008 15:10:44 +0100 Subject: Add SMB_VFS_FS_CAPABILITIES It turns out that this is a necessary operation, separate from statvfs. statvfs can fail during tcon, so conn->fs_capabilities would never see that we support streams on a particular share. James, can you check that I got the darwin variant right? Thanks! (This used to be commit 3ad798d803b3b023533bb48e6993885f22b96095) --- source3/smbd/service.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ed8061e2f7..a8aa25405a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1171,16 +1171,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * assumes that all the filesystem mounted withing a share path have * the same characteristics, which is likely but not guaranteed. */ - { - vfs_statvfs_struct svfs; - - conn->fs_capabilities = - FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; - if (SMB_VFS_STATVFS(conn, conn->connectpath, &svfs) == 0) { - conn->fs_capabilities = svfs.FsCapabilities; - } - } + conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn); /* * Print out the 'connected as' stuff here as we need -- cgit From 597b28b86ed99acfb488afb86b11fe48538cf169 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 09:13:25 +0100 Subject: Fix a segfault Found by the IBM checker. Jeremy, you changed this from 'dirname == 0' which does not make sense at all in the old code to '!dirname == 0' which from my point of view makes even less sense, because the precedence of ! is according to Harbison/Steele higher than the precedence of ==. Please check that the code now actually does what it's supposed to do. Thanks! (This used to be commit c8def5564739c4c754001f84fcfb77f1093b96c3) --- source3/smbd/utmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index e82bbea3b3..5931b2b1d0 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -223,7 +223,7 @@ static char *uw_pathname(TALLOC_CTX *ctx, } /* For u-files and non-explicit w-dir, look for "utmp dir" */ - if (!dirname == 0 || strlen(dirname) == 0) { + if ((dirname == NULL) || (strlen(dirname) == 0)) { dirname = talloc_strdup(ctx, lp_utmpdir()); if (!dirname) { return NULL; -- cgit From 6a69bc3ef99349edf78b5dec9a029366985f23b9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 09:18:40 +0100 Subject: Fix get_ea_names_from_file for many EAs Found by the IBM checker (This used to be commit 8741a9b37496e78b28d59d844aaba12f269171e0) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9c48cdfbba..896d2dee14 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -210,7 +210,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, ea_namelist_size); } - if ((sizeret == -1) && (errno = ERANGE)) { + if ((sizeret == -1) && (errno == ERANGE)) { ea_namelist_size *= 2; } else { -- cgit From 2a78eb9c0d5f82b9d893509dff3932bde9799adf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 09:22:14 +0100 Subject: Fix a ton of IBM checker uninitialized variable warnings SET_STAT_INVALID only sets nlink, not the other fields We might consider to change SET_STAT_INVALID to always do ZERO_STRUCT (This used to be commit 8cf8c5b2034fe093b5db7f069bc6be8d328399bf) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9fca38e3ed..aa4bc48f3d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3034,8 +3034,7 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } - SET_STAT_INVALID(sbuf); - + ZERO_STRUCT(sbuf); goto done; } } -- cgit From a4c2b04a2b46fd308e98cc83c26de8307f5196a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 21 Jan 2008 20:24:23 +0100 Subject: Hide streams from the EA API (This used to be commit e9bb3d5067b74a29beb778f85687829778e42b5b) --- source3/smbd/trans2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 896d2dee14..b5b3ea751b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -105,9 +105,13 @@ static bool samba_private_attr_name(const char *unix_ea_name) for (i = 0; prohibited_ea_names[i]; i++) { if (strequal( prohibited_ea_names[i], unix_ea_name)) - return True; + return true; } - return False; + if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX, + strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) { + return true; + } + return false; } /**************************************************************************** -- cgit From 559603ad693ede382c566cb8bbd8e6bd8d5750a6 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 22 Jan 2008 11:33:17 +0100 Subject: Get Samba version or capability information from Windows On Jan 21 16:18, Danilo Almeida wrote: > Corina wrote: > > > + time_t samba_gitcommitdate; > > And: > > > + SIVAL(pdata,28,extended_info.samba_gitcommitdate); > > + memcpy(pdata+32,extended_info.samba_version_string,32); > > Note that you are dropping bits on a system w/64-bit time_t, and that this has the 2038 problem. Right. I changed samba_gitcommitdate from time_t to NTTIME and shortened samba_version_string to 28 bytes. New patch below. Thanks, Corinna (This used to be commit 28aa1c199d3a22cda34afcaab49c0561eeb0abcb) --- source3/smbd/trans2.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b5b3ea751b..1243bdd9d2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2797,7 +2797,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned case SMB_FS_OBJECTID_INFORMATION: { unsigned char objid[16]; + struct smb_extended_info extended_info; memcpy(pdata,create_volume_objectid(conn, objid),16); + samba_extended_info_version (&extended_info); + SIVAL(pdata,16,extended_info.samba_magic); + SIVAL(pdata,20,extended_info.samba_version); + SIVAL(pdata,24,extended_info.samba_subversion); + SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate); + memcpy(pdata+36,extended_info.samba_version_string,28); data_len = 64; break; } -- cgit From d4d962f691d13f36226157c38f706ee4d10b9150 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 13:00:22 +0100 Subject: Move samba_extended_info_version to smbd/trans2.c This is right now only used there, and in version.c it gave linker errors because some binaries (e.g. smbmnt) don't link in time.o (This used to be commit 1f0eaaa5911f893c822465a26fe49ab65afb0730) --- source3/smbd/trans2.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1243bdd9d2..8b999cd8f5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2459,6 +2459,38 @@ unsigned char *create_volume_objectid(connection_struct *conn, unsigned char obj return objid; } +static void samba_extended_info_version(struct smb_extended_info *extended_info) +{ + SMB_ASSERT(extended_info != NULL); + + extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC; + extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24) + | ((SAMBA_VERSION_MINOR & 0xff) << 16) + | ((SAMBA_VERSION_RELEASE & 0xff) << 8); +#ifdef SAMBA_VERSION_REVISION + extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff; +#endif +#ifdef SAMBA_VERSION_RC_RELEASE + extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24; +#else +#ifdef SAMBA_VERSION_PRE_RELEASE + extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16; +#endif +#endif +#ifdef SAMBA_VERSION_VENDOR_PATCH + extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff); +#endif + /* FIXME: samba_gitcommitdate should contain the git commit date. */ + unix_to_nt_time(&extended_info->samba_gitcommitdate, time(NULL)); + + memset(extended_info->samba_version_string, 0, + sizeof(extended_info->samba_version_string)); + + snprintf (extended_info->samba_version_string, + sizeof(extended_info->samba_version_string), + "%s", samba_version_string()); +} + /**************************************************************************** Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ -- cgit From 9051199e40dec27d3532fbec7f5744033def1874 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 22 Jan 2008 16:38:00 +0100 Subject: Get Samba version or capability information from Windows On Jan 22 13:31, Volker Lendecke wrote: > On Tue, Jan 22, 2008 at 11:33:17AM +0100, Corinna Vinschen wrote: > > Right. I changed samba_gitcommitdate from time_t to NTTIME and shortened > > samba_version_string to 28 bytes. New patch below. > > Ok, pushed with some modifications. You might want to review > that. Reviewed and tested. Looks good, thank you! Below you'll find a tiny patch to add the git commit date. It seems I simply missed its existence in version.h :( Tested on Windows XP. Thanks, Corinna * source/smbd/trans2.c (samba_extended_info_version): Fill out samba_gitcommitdate member with GIT commit timestamp. (This used to be commit a33d0797585b5cdd304ac1eb6966b9c7c799bab6) --- source3/smbd/trans2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8b999cd8f5..fb845220cd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2481,7 +2481,9 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info) extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff); #endif /* FIXME: samba_gitcommitdate should contain the git commit date. */ - unix_to_nt_time(&extended_info->samba_gitcommitdate, time(NULL)); +#ifdef SAMBA_VERSION_GIT_COMMIT_TIME + unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME); +#endif memset(extended_info->samba_version_string, 0, sizeof(extended_info->samba_version_string)); -- cgit From 5b35ecd930dc6267821c7a3d8b3a90c680ab71b1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Jan 2008 10:33:36 +0100 Subject: Remove two unused variables (This used to be commit f12ac1ecedd6634d8ccc54d8fce8382514e3322f) --- source3/smbd/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a5bdb96650..6fd4d17d88 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -23,7 +23,6 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; -const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); static enum smb_read_errors smb_read_error = SMB_READ_OK; /* -- cgit From 587cf54c61c9f1f7bcae431a82035fd942716c32 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Jan 2008 11:04:10 +0100 Subject: strtok -> strtok_r (This used to be commit fd34ce437057bb34cdc37f4b066e424000d36789) --- source3/smbd/msdfs.c | 5 +++-- source3/smbd/password.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4ae735633b..8ffa0f7751 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -288,12 +288,13 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, char **alt_path = NULL; int count = 0, i; struct referral *reflist; + char *saveptr; temp = talloc_strdup(ctx, target); if (!temp) { return False; } - prot = strtok(temp,":"); + prot = strtok_r(temp, ":", &saveptr); if (!prot) { DEBUG(0,("parse_msdfs_symlink: invalid path !\n")); return False; @@ -306,7 +307,7 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, /* parse out the alternate paths */ while((count Date: Wed, 23 Jan 2008 16:42:31 +0100 Subject: read_socket_with_timeout has timeout=0 handling (This used to be commit 7101026061c470ed962267b43ac0aa67cc761a64) --- source3/smbd/process.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6fd4d17d88..d961f98cc0 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -155,16 +155,8 @@ static ssize_t read_packet_remainder(int fd, return len; } - if (timeout > 0) { - ret = read_socket_with_timeout(fd, - buffer, - len, - len, - timeout, - get_srv_read_error()); - } else { - ret = read_data(fd, buffer, len, get_srv_read_error()); - } + ret = read_socket_with_timeout(fd, buffer, len, len, timeout, + get_srv_read_error()); if (ret != len) { cond_set_smb_read_error(get_srv_read_error(), @@ -206,19 +198,10 @@ static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, memcpy(writeX_header, lenbuf, sizeof(lenbuf)); - if (timeout > 0) { - ret = read_socket_with_timeout(fd, - writeX_header + 4, - STANDARD_WRITE_AND_X_HEADER_SIZE, - STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout, - get_srv_read_error()); - } else { - ret = read_data(fd, - writeX_header+4, - STANDARD_WRITE_AND_X_HEADER_SIZE, - get_srv_read_error()); - } + ret = read_socket_with_timeout(fd, writeX_header + 4, + STANDARD_WRITE_AND_X_HEADER_SIZE, + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout, get_srv_read_error()); if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { cond_set_smb_read_error(get_srv_read_error(), -- cgit From 70e1ce640370eddb3c3e4f16cb6ae86c9d8e3a5e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jan 2008 12:59:08 -0800 Subject: First part of fix for bug #4929 - worked out by jmcd. Cope with protected ACL set correctly. Jeremy. (This used to be commit f5e50f42e7c79b4f8857602457db5b97886bd19e) --- source3/smbd/posix_acls.c | 109 ++++++++++++---------------------------------- 1 file changed, 29 insertions(+), 80 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6cec39f9c0..323d6cadb2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3202,57 +3202,8 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) return ret; } -static NTSTATUS append_ugw_ace(files_struct *fsp, - SMB_STRUCT_STAT *psbuf, - mode_t unx_mode, - int ugw, - SEC_ACE *se) -{ - mode_t perms; - SEC_ACCESS acc; - enum security_ace_type nt_acl_type; - DOM_SID trustee; - - switch (ugw) { - case S_IRUSR: - perms = unix_perms_to_acl_perms(unx_mode, - S_IRUSR, - S_IWUSR, - S_IXUSR); - uid_to_sid(&trustee, psbuf->st_uid ); - break; - case S_IRGRP: - perms = unix_perms_to_acl_perms(unx_mode, - S_IRGRP, - S_IWGRP, - S_IXGRP); - gid_to_sid(&trustee, psbuf->st_gid ); - break; - case S_IROTH: - perms = unix_perms_to_acl_perms(unx_mode, - S_IROTH, - S_IWOTH, - S_IXOTH); - sid_copy(&trustee, &global_sid_World); - break; - default: - return NT_STATUS_INVALID_PARAMETER; - } - acc = map_canon_ace_perms(SNUM(fsp->conn), - &nt_acl_type, - perms, - fsp->is_directory); - - init_sec_ace(se, - &trustee, - nt_acl_type, - acc, - 0); - return NT_STATUS_OK; -} - /**************************************************************************** - If this is an + Take care of parent ACL inheritance. ****************************************************************************/ static NTSTATUS append_parent_acl(files_struct *fsp, @@ -3270,7 +3221,7 @@ static NTSTATUS append_parent_acl(files_struct *fsp, NTSTATUS status; int info; unsigned int i, j; - mode_t unx_mode; + bool is_dacl_protected = (psd->type & SE_DESC_DACL_PROTECTED); ZERO_STRUCT(sbuf); @@ -3285,12 +3236,6 @@ static NTSTATUS append_parent_acl(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - /* Create a default mode for u/g/w. */ - unx_mode = unix_mode(fsp->conn, - aARCH | (fsp->is_directory ? aDIR : 0), - fsp->fsp_name, - parent_name); - status = open_directory(fsp->conn, NULL, parent_name, @@ -3318,20 +3263,23 @@ static NTSTATUS append_parent_acl(files_struct *fsp, /* * Make room for potentially all the ACLs from - * the parent, plus the user/group/other triple. + * the parent. We used to add the ugw triple here, + * as we knew we were dealing with POSIX ACLs. + * We no longer need to do so as we can guarentee + * that a default ACL from the parent directory will + * be well formed for POSIX ACLs if it came from a + * POSIX ACL source, and if we're not writing to a + * POSIX ACL sink then we don't care if it's not well + * formed. JRA. */ - num_aces += parent_sd->dacl->num_aces + 3; + num_aces += parent_sd->dacl->num_aces; if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, SEC_ACE, num_aces)) == NULL) { return NT_STATUS_NO_MEMORY; } - DEBUG(10,("append_parent_acl: parent ACL has %u entries. New " - "ACL has %u entries\n", - parent_sd->dacl->num_aces, num_aces )); - /* Start by copying in all the given ACE entries. */ for (i = 0; i < psd->dacl->num_aces; i++) { sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]); @@ -3342,23 +3290,6 @@ static NTSTATUS append_parent_acl(files_struct *fsp, * as that really only applies to newly created files. JRA. */ - /* - * Append u/g/w. - */ - - status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRUSR, &new_ace[i++]); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRGRP, &new_ace[i++]); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = append_ugw_ace(fsp, psbuf, unx_mode, S_IROTH, &new_ace[i++]); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* Finally append any inherited ACEs. */ for (j = 0; j < parent_sd->dacl->num_aces; j++) { SEC_ACE *se = &parent_sd->dacl->aces[j]; @@ -3379,6 +3310,24 @@ static NTSTATUS append_parent_acl(files_struct *fsp, continue; } } + + if (is_dacl_protected) { + /* If the DACL is protected it means we must + * not overwrite an existing ACE entry with the + * same SID. This is order N^2. Ouch :-(. JRA. */ + unsigned int k; + for (k = 0; k < psd->dacl->num_aces; k++) { + if (sid_equal(&psd->dacl->aces[k].trustee, + &se->trustee)) { + break; + } + } + if (k < psd->dacl->num_aces) { + /* SID matched. Ignore. */ + continue; + } + } + sec_ace_copy(&new_ace[i], se); if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT); -- cgit From 47a8e77513686bbc492bbfdebbbd0bfb7f786063 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jan 2008 13:06:11 -0800 Subject: The checks for OI and CI were just wrong.... Fix them. Thanks to Jim for testing this. Jeremy. (This used to be commit e898789e0d819df05b14bcedfa1d230c7a983440) --- source3/smbd/posix_acls.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 323d6cadb2..40979cd6a2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3293,20 +3293,15 @@ static NTSTATUS append_parent_acl(files_struct *fsp, /* Finally append any inherited ACEs. */ for (j = 0; j < parent_sd->dacl->num_aces; j++) { SEC_ACE *se = &parent_sd->dacl->aces[j]; - uint32 i_flags = se->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| - SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY); if (fsp->is_directory) { - if (i_flags == SEC_ACE_FLAG_OBJECT_INHERIT) { - /* Should only apply to a file - ignore. */ + if (!(se->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) { + /* Doesn't apply to a directory - ignore. */ continue; } } else { - if ((i_flags & (SEC_ACE_FLAG_OBJECT_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY)) != - SEC_ACE_FLAG_OBJECT_INHERIT) { - /* Should not apply to a file - ignore. */ + if (!(se->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) { + /* Doesn't apply to a file - ignore. */ continue; } } -- cgit From 85a44396a794ae456d4998a9d9dd5ceb37312999 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jan 2008 13:27:00 -0800 Subject: Add debug messages to trace this if needed. Jeremy. (This used to be commit b628269b3260661cb4eeeab8c533b3129827ba62) --- source3/smbd/posix_acls.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 40979cd6a2..dee5d8e7c9 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3297,11 +3297,21 @@ static NTSTATUS append_parent_acl(files_struct *fsp, if (fsp->is_directory) { if (!(se->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) { /* Doesn't apply to a directory - ignore. */ + DEBUG(10,("append_parent_acl: directory %s " + "ignoring non container " + "inherit flags %u\n", + fsp->fsp_name, + (unsigned int)se->flags )); continue; } } else { if (!(se->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) { /* Doesn't apply to a file - ignore. */ + DEBUG(10,("append_parent_acl: file %s " + "ignoring non object " + "inherit flags %u\n", + fsp->fsp_name, + (unsigned int)se->flags )); continue; } } @@ -3319,6 +3329,10 @@ static NTSTATUS append_parent_acl(files_struct *fsp, } if (k < psd->dacl->num_aces) { /* SID matched. Ignore. */ + DEBUG(10,("append_parent_acl: path %s " + "ignoring protected sid %s\n", + fsp->fsp_name, + sid_string_dbg(&se->trustee))); continue; } } -- cgit From 50c7e98a46a1c97011f37c78db8caddc634d6994 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jan 2008 16:13:53 -0800 Subject: Make explicit in debug we're ignoring flags from the parent SD. Jeremy (This used to be commit 58cfa4b1bdc1ce30cc3befb342cc98ac0e283585) --- source3/smbd/posix_acls.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index dee5d8e7c9..12e611f9cb 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3299,9 +3299,10 @@ static NTSTATUS append_parent_acl(files_struct *fsp, /* Doesn't apply to a directory - ignore. */ DEBUG(10,("append_parent_acl: directory %s " "ignoring non container " - "inherit flags %u\n", + "inherit flags %u from parent %s\n", fsp->fsp_name, - (unsigned int)se->flags )); + (unsigned int)se->flags, + parent_name)); continue; } } else { @@ -3309,9 +3310,10 @@ static NTSTATUS append_parent_acl(files_struct *fsp, /* Doesn't apply to a file - ignore. */ DEBUG(10,("append_parent_acl: file %s " "ignoring non object " - "inherit flags %u\n", + "inherit flags %u from parent %s\n", fsp->fsp_name, - (unsigned int)se->flags )); + (unsigned int)se->flags, + parent_name)); continue; } } @@ -3330,9 +3332,11 @@ static NTSTATUS append_parent_acl(files_struct *fsp, if (k < psd->dacl->num_aces) { /* SID matched. Ignore. */ DEBUG(10,("append_parent_acl: path %s " - "ignoring protected sid %s\n", + "ignoring protected sid %s " + "from parent %s\n", fsp->fsp_name, - sid_string_dbg(&se->trustee))); + sid_string_dbg(&se->trustee), + parent_name)); continue; } } -- cgit From dd67913a999323188f4d8c877ab761ce9d53883d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jan 2008 17:50:07 -0800 Subject: Correctly set flags in ACE's inherited from parent. Still one bug left to find then I'll back-port to 3.0.28. Jeremy. (This used to be commit 3df2f7ca782e418703d82f7a1f3c035a365f9589) --- source3/smbd/posix_acls.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 12e611f9cb..347064362d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3299,9 +3299,11 @@ static NTSTATUS append_parent_acl(files_struct *fsp, /* Doesn't apply to a directory - ignore. */ DEBUG(10,("append_parent_acl: directory %s " "ignoring non container " - "inherit flags %u from parent %s\n", + "inherit flags %u on ACE with sid %s " + "from parent %s\n", fsp->fsp_name, (unsigned int)se->flags, + sid_string_dbg(&se->trustee), parent_name)); continue; } @@ -3310,9 +3312,11 @@ static NTSTATUS append_parent_acl(files_struct *fsp, /* Doesn't apply to a file - ignore. */ DEBUG(10,("append_parent_acl: file %s " "ignoring non object " - "inherit flags %u from parent %s\n", + "inherit flags %u on ACE with sid %s " + "from parent %s\n", fsp->fsp_name, (unsigned int)se->flags, + sid_string_dbg(&se->trustee), parent_name)); continue; } @@ -3332,7 +3336,7 @@ static NTSTATUS append_parent_acl(files_struct *fsp, if (k < psd->dacl->num_aces) { /* SID matched. Ignore. */ DEBUG(10,("append_parent_acl: path %s " - "ignoring protected sid %s " + "ignoring ACE with protected sid %s " "from parent %s\n", fsp->fsp_name, sid_string_dbg(&se->trustee), @@ -3346,7 +3350,35 @@ static NTSTATUS append_parent_acl(files_struct *fsp, new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT); } new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE; + + if (fsp->is_directory) { + /* + * Strip off any inherit only. It's applied. + */ + new_ace[i].flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY); + if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { + /* No further inheritance. */ + new_ace[i].flags &= + ~(SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_OBJECT_INHERIT); + } + } else { + /* + * Strip off any container or inherit + * flags, they can't apply to objects. + */ + new_ace[i].flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY| + SEC_ACE_FLAG_NO_PROPAGATE_INHERIT); + } i++; + + DEBUG(10,("append_parent_acl: path %s " + "inheriting ACE with sid %s " + "from parent %s\n", + fsp->fsp_name, + sid_string_dbg(&se->trustee), + parent_name)); } parent_sd->dacl->aces = new_ace; -- cgit From fccae57310dcd9b625c4f41be9548d2ed6d81427 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jan 2008 18:13:22 -0800 Subject: Fix a really subtle old, old bug :-). When canonicalizing the NT ACL into a POSIX one, if the group being set is the primary group of the file, map it into a SMB_ACL_GROUP_OBJ, not a SMB_ACL_GROUP. Otherwise we get an extra bogus group entry in the POSIX ACL. Jeremy. (This used to be commit 4d302254fdfce2c267cf6b21f662d5aa2dc9c72c) --- source3/smbd/posix_acls.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 347064362d..9c015261b5 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1408,12 +1408,12 @@ static bool create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)); psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT); - + } else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) { psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)); psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT); - + } } } @@ -1477,7 +1477,13 @@ static bool create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, current_ace->type = SMB_ACL_USER; } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid)) { current_ace->owner_type = GID_ACE; - current_ace->type = SMB_ACL_GROUP; + /* If it's the primary group, this is a group_obj, not + * a group. */ + if (current_ace->unix_ug.gid == pst->st_gid) { + current_ace->type = SMB_ACL_GROUP_OBJ; + } else { + current_ace->type = SMB_ACL_GROUP; + } } else { /* * Silently ignore map failures in non-mappable SIDs (NT Authority, BUILTIN etc). -- cgit From 51f62beabd91c94374bcadf70ee1bcad20fd60ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jan 2008 18:22:43 -0800 Subject: Fix the same bug with user -> user_obj. Jeremy. (This used to be commit c5edf7456955471b8590c2cfa67c7f47a387cdf0) --- source3/smbd/posix_acls.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9c015261b5..f60329a039 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1474,7 +1474,13 @@ static bool create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid)) { current_ace->owner_type = UID_ACE; - current_ace->type = SMB_ACL_USER; + /* If it's the owning user, this is a user_obj, not + * a user. */ + if (current_ace->unix_ug.uid == pst->st_uid) { + current_ace->type = SMB_ACL_USER_OBJ; + } else { + current_ace->type = SMB_ACL_USER; + } } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid)) { current_ace->owner_type = GID_ACE; /* If it's the primary group, this is a group_obj, not -- cgit From 5398dd641cd296a3bc4762b6b6a00cc241c2d2a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 26 Jan 2008 21:29:18 +0100 Subject: Fix uninitialized variables Thanks to Corinna Vinschen (This used to be commit aba8c17599f0be82cff33229bb107814d88faafe) --- source3/smbd/trans2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index fb845220cd..1f7af82670 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2470,6 +2470,7 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info) #ifdef SAMBA_VERSION_REVISION extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff; #endif + extended_info->samba_subversion = 0; #ifdef SAMBA_VERSION_RC_RELEASE extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24; #else @@ -2480,7 +2481,7 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info) #ifdef SAMBA_VERSION_VENDOR_PATCH extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff); #endif - /* FIXME: samba_gitcommitdate should contain the git commit date. */ + extended_info->samba_gitcommitdate = 0; #ifdef SAMBA_VERSION_GIT_COMMIT_TIME unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME); #endif -- cgit From 47e1251f721cfbc45ab26b15d5bdbc523c55d6e9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 Jan 2008 00:35:14 +0100 Subject: Remove an unused external reference (This used to be commit 147033b9dff7160ff324fa52aba1f054f962961b) --- source3/smbd/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d961f98cc0..4672510d8d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -20,7 +20,6 @@ #include "includes.h" -extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; static enum smb_read_errors smb_read_error = SMB_READ_OK; -- cgit From 28b27bfd40d1bfbebaa9f8026efdf169d7bc6b29 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 29 Jan 2008 17:43:49 +0300 Subject: Merge DMAPI fixes from Tridge Support cases when existing DMAPI session is stale. In this case we are creating another one. The code differs from 3-0_ctdb branch in that we fail when it is not possible to create more sessions and pretend that file is offline. This allows to escape endless loop in vfs_tsmsm.c. (This used to be commit 5efb57d904e25e68b09a567e260292439ad9c095) --- source3/smbd/dmapi.c | 72 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index a410748ccf..8d43e0a9d1 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -47,7 +47,7 @@ const void * dmapi_get_current_session(void) { return NULL; } #define DMAPI_TRACE 10 static dm_sessid_t samba_dmapi_session = DM_NO_SESSION; - +static unsigned session_num; /* Initialise DMAPI session. The session is persistant kernel state, @@ -61,23 +61,41 @@ static int dmapi_init_session(void) uint nsessions = 5; dm_sessid_t *sessions = NULL; char *version; + char *session_name; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); int i, err; + if (session_num == 0) { + session_name = DMAPI_SESSION_NAME; + } else { + session_name = talloc_asprintf(tmp_ctx, "%s%u", DMAPI_SESSION_NAME, + session_num); + } + + if (session_name == NULL) { + DEBUG(0,("Out of memory in dmapi_init_session\n")); + talloc_free(tmp_ctx); + return -1; + } + + if (dm_init_service(&version) < 0) { DEBUG(0, ("dm_init_service failed - disabling DMAPI\n")); + talloc_free(tmp_ctx); return -1; } ZERO_STRUCT(buf); + /* Fetch kernel DMAPI sessions until we get any of them */ do { dm_sessid_t *new_sessions; nsessions *= 2; - new_sessions = TALLOC_REALLOC_ARRAY(NULL, sessions, + new_sessions = TALLOC_REALLOC_ARRAY(tmp_ctx, sessions, dm_sessid_t, nsessions); if (new_sessions == NULL) { - talloc_free(sessions); + talloc_free(tmp_ctx); return -1; } @@ -89,14 +107,15 @@ static int dmapi_init_session(void) DEBUGADD(DMAPI_TRACE, ("failed to retrieve DMAPI sessions: %s\n", strerror(errno))); - talloc_free(sessions); + talloc_free(tmp_ctx); return -1; } + /* Look through existing kernel DMAPI sessions to find out ours */ for (i = 0; i < nsessions; ++i) { err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); buf[sizeof(buf) - 1] = '\0'; - if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { + if (err == 0 && strcmp(session_name, buf) == 0) { samba_dmapi_session = sessions[i]; DEBUGADD(DMAPI_TRACE, ("attached to existing DMAPI session " @@ -105,23 +124,22 @@ static int dmapi_init_session(void) } } - talloc_free(sessions); - /* No session already defined. */ if (samba_dmapi_session == DM_NO_SESSION) { err = dm_create_session(DM_NO_SESSION, - CONST_DISCARD(char *, DMAPI_SESSION_NAME), + session_name, &samba_dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, ("failed to create new DMAPI session: %s\n", strerror(errno))); samba_dmapi_session = DM_NO_SESSION; + talloc_free(tmp_ctx); return -1; } DEBUG(0, ("created new DMAPI session named '%s' for %s\n", - DMAPI_SESSION_NAME, version)); + session_name, version)); } if (samba_dmapi_session != DM_NO_SESSION) { @@ -132,8 +150,12 @@ static int dmapi_init_session(void) Note that we never end the DMAPI session. It gets re-used if possiblie. DMAPI session is a kernel resource that is usually lives until server reboot and doesn't get destroed when an application finishes. + + However, we free list of references to DMAPI sessions we've got from the kernel + as it is not needed anymore once we have found (or created) our session. */ + talloc_free(tmp_ctx); return 0; } @@ -171,6 +193,25 @@ bool dmapi_have_session(void) return samba_dmapi_session != DM_NO_SESSION; } +/* + only call this when you get back an EINVAL error indicating that the + session you are using is invalid. This destroys the existing session + and creates a new one. + */ +BOOL dmapi_new_session(void) +{ + if (dmapi_have_session()) { + /* try to destroy the old one - this may not succeed */ + dm_destroy_session(samba_dmapi_session); + } + samba_dmapi_session = DM_NO_SESSION; + become_root(); + session_num++; + dmapi_init_session(); + unbecome_root(); + return samba_dmapi_session != DM_NO_SESSION; +} + /* This is default implementation of dmapi_file_flags() that is called from VFS is_offline() call to know whether file is offline. @@ -185,12 +226,12 @@ uint32 dmapi_file_flags(const char * const path) dm_eventset_t events = {0}; uint nevents; - dm_sessid_t dmapi_session; - void *dmapi_session_ptr; - void *dm_handle = NULL; - size_t dm_handle_len = 0; + dm_sessid_t dmapi_session; + const void *dmapi_session_ptr; + void *dm_handle = NULL; + size_t dm_handle_len = 0; - uint32 flags = 0; + uint32 flags = 0; dmapi_session_ptr = dmapi_get_current_session(); if (dmapi_session_ptr == NULL) { @@ -251,8 +292,7 @@ uint32 dmapi_file_flags(const char * const path) * interested in trapping read events is that part of the file is * offline. */ - DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", - path, events)); + DEBUG(DMAPI_TRACE, ("DMAPI event list for %s\n", path)); if (DMEV_ISSET(DM_EVENT_READ, events)) { flags = FILE_ATTRIBUTE_OFFLINE; } -- cgit From 52c16c95e6e6fa17a7e440b77afdccfd9a7295c9 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 29 Jan 2008 18:01:23 +0300 Subject: Fix BOOL introduced by last commit (This used to be commit 8afb7133e956ec963ac55720fb297b4d5b44702c) --- source3/smbd/dmapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 8d43e0a9d1..fab0d5f9ef 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -198,7 +198,7 @@ bool dmapi_have_session(void) session you are using is invalid. This destroys the existing session and creates a new one. */ -BOOL dmapi_new_session(void) +bool dmapi_new_session(void) { if (dmapi_have_session()) { /* try to destroy the old one - this may not succeed */ -- cgit From 34a92c6285513acff08c7c9ad67474243559fd2f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 30 Jan 2008 11:11:27 +0100 Subject: Re-enable async I/O for non-TSM systems The logic was wrong: A "SMB_VFS_AIO_FORCE()==False" disabled async I/O, whereas a "SMB_VFS_AIO_FORCE()==True" should enforce it regardless of other settings. Alexander, please check! (This used to be commit 46882ad9927c95caadeb7fb03c1d7491bbe1fb22) --- source3/smbd/aio.c | 6 ++++-- source3/smbd/reply.c | 11 ++--------- 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 9c25f69c97..86fdfe31b7 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -202,7 +202,8 @@ bool schedule_aio_read_and_X(connection_struct *conn, size_t bufsize; size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); - if (!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) { + if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) + && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a read for aio request. */ DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small " "for minimum aio_read of %u\n", @@ -284,7 +285,8 @@ bool schedule_aio_write_and_X(connection_struct *conn, bool write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); - if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { + if ((!min_aio_write_size || (numtowrite < min_aio_write_size)) + && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a write for aio request. */ DEBUG(10,("schedule_aio_write_and_X: write size (%u) too " "small for minimum aio_write of %u\n", diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4ea81a3819..18376031ec 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3338,11 +3338,7 @@ void reply_read_and_X(struct smb_request *req) return; } - /* It is possible for VFS modules to selectively decide whether Async I/O should be used - for the file or not. - */ - if ((SMB_VFS_AIO_FORCE(fsp)) && - !big_readX && + if (!big_readX && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) { END_PROFILE(SMBreadX); return; @@ -4012,10 +4008,7 @@ void reply_write_and_X(struct smb_request *req) nwritten = 0; } else { - /* It is possible for VFS modules to selectively decide whether Async I/O - should be used for the file or not. - */ - if ((SMB_VFS_AIO_FORCE(fsp)) && (req->unread_bytes == 0) && + if ((req->unread_bytes == 0) && schedule_aio_write_and_X(conn, req, fsp, data, startpos, numtowrite)) { END_PROFILE(SMBwriteX); -- cgit From 0afbfa4284db8204a3696f4fea6cff96965e6074 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 21:24:48 +0100 Subject: Convert read_smb_length_return_keepalive to return NTSTATUS (This used to be commit 73a79a957a33a8761acf54598ce71e3604ecf3c5) --- source3/smbd/process.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4672510d8d..d6301d0d00 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -300,24 +300,30 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, size_t *p_unread) { char lenbuf[4]; - ssize_t len,ret; + size_t len; + ssize_t ret; int min_recv_size = lp_min_receive_file_size(); + NTSTATUS status; set_smb_read_error(get_srv_read_error(),SMB_READ_OK); *p_unread = 0; - len = read_smb_length_return_keepalive(fd, lenbuf, - timeout, get_srv_read_error()); - if (len < 0) { - DEBUG(10,("receive_smb_raw: length < 0!\n")); + status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status))); - /* - * Correct fix. smb_read_error may have already been - * set. Only set it here if not already set. Global - * variables still suck :-). JRA. - */ + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); + return -1; + } - cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + return -1; + } + + set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); return -1; } -- cgit From 9f6e983d0b67b64daf27dab130348d3491bad4ac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 21:31:40 +0100 Subject: Convert read_smb_length to return NTSTATUS (This used to be commit 5750c3a51b4ddac635a98195d1621b24f91bad3f) --- source3/smbd/reply.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 18376031ec..46c14d158e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3492,18 +3492,12 @@ void reply_writebraw(struct smb_request *req) } /* Now read the raw data into the buffer and write it */ - if (read_smb_length(smbd_server_fd(),buf, - SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) { + status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT, + &numtowrite); + if (!NT_STATUS_IS_OK(status)) { exit_server_cleanly("secondary writebraw failed"); } - /* - * Even though this is not an smb message, - * smb_len returns the generic length of a packet. - */ - - numtowrite = smb_len(buf); - /* Set up outbuf to return the correct size */ reply_outbuf(req, 1, 0); -- cgit From 48b1ee61db5f513321b7f3360eb17f94ef339872 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 22:21:38 +0100 Subject: Convert read_packet_remainder to use read_socket_with_timeout_ntstatus (This used to be commit fff31f8f35ad26d67e78b9a71cfd35670aa9ac5f) --- source3/smbd/process.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index d6301d0d00..02b190f003 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -148,22 +148,34 @@ static ssize_t read_packet_remainder(int fd, unsigned int timeout, ssize_t len) { - ssize_t ret; + NTSTATUS status; - if(len <= 0) { + if (len <= 0) { return len; } - ret = read_socket_with_timeout(fd, buffer, len, len, timeout, - get_srv_read_error()); + set_smb_read_error(get_srv_read_error(), SMB_READ_OK); - if (ret != len) { - cond_set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); + status = read_socket_with_timeout_ntstatus(fd, buffer, len, len, + timeout, NULL); + + if (NT_STATUS_IS_OK(status)) { + return len; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); return -1; } - return len; + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + return -1; + } + + set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); + return -1; } /**************************************************************************** -- cgit From e604e137e21af52efdbabc28863a5ea76d8d620d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 22:27:59 +0100 Subject: Convert read_packet_remainder to return NTSTATUS (This used to be commit 667864d442ea7e1faed7b032315db8856fa91481) --- source3/smbd/process.c | 81 +++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 02b190f003..4d9a90a840 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -143,39 +143,15 @@ static bool valid_packet_size(size_t len) return true; } -static ssize_t read_packet_remainder(int fd, - char *buffer, - unsigned int timeout, - ssize_t len) +static NTSTATUS read_packet_remainder(int fd, char *buffer, + unsigned int timeout, ssize_t len) { - NTSTATUS status; - if (len <= 0) { - return len; - } - - set_smb_read_error(get_srv_read_error(), SMB_READ_OK); - - status = read_socket_with_timeout_ntstatus(fd, buffer, len, len, - timeout, NULL); - - if (NT_STATUS_IS_OK(status)) { - return len; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); - return -1; + return NT_STATUS_OK; } - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - return -1; - } - - set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); - return -1; + return read_socket_with_timeout_ntstatus(fd, buffer, len, len, + timeout, NULL); } /**************************************************************************** @@ -293,11 +269,29 @@ static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; if(toread > 0) { - ret = read_packet_remainder(fd, - (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout, - toread); - if (ret != toread) { + NTSTATUS status; + + set_smb_read_error(get_srv_read_error(), SMB_READ_OK); + + status = read_packet_remainder( + fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout, toread); + + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_EOF); + return -1; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + return -1; + } + + set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } } @@ -313,7 +307,6 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, { char lenbuf[4]; size_t len; - ssize_t ret; int min_recv_size = lp_min_receive_file_size(); NTSTATUS status; @@ -371,8 +364,22 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, memcpy(*buffer, lenbuf, sizeof(lenbuf)); - ret = read_packet_remainder(fd, (*buffer)+4, timeout, len); - if (ret != len) { + status = read_packet_remainder(fd, (*buffer)+4, timeout, len); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_EOF); + return -1; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + return -1; + } + + set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } -- cgit From 250b2b6464521fa4e2b5c737164e1ce68755677f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:12:04 +0100 Subject: Convert receive_smb_raw_talloc_partial_read to NTSTATUS (This used to be commit 9a82350ba92bf5fc4f2968d5130bcb2118e7a981) --- source3/smbd/process.c | 106 ++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 59 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4d9a90a840..10ef67c2b2 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -128,15 +128,6 @@ static bool valid_packet_size(size_t len) DEBUG(0,("Invalid packet length! (%lu bytes).\n", (unsigned long)len)); if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) { - - /* - * Correct fix. smb_read_error may have already been - * set. Only set it here if not already set. Global - * variables still suck :-). JRA. - */ - - cond_set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); return false; } } @@ -170,30 +161,29 @@ static NTSTATUS read_packet_remainder(int fd, char *buffer, (2*14) + /* word count (including bcc) */ \ 1 /* pad byte */) -static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, - const char lenbuf[4], - int fd, - char **buffer, - unsigned int timeout, - size_t *p_unread) +static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, + const char lenbuf[4], + int fd, char **buffer, + unsigned int timeout, + size_t *p_unread, + size_t *len_ret) { /* Size of a WRITEX call (+4 byte len). */ char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE]; ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */ ssize_t toread; - ssize_t ret; + NTSTATUS status; memcpy(writeX_header, lenbuf, sizeof(lenbuf)); - ret = read_socket_with_timeout(fd, writeX_header + 4, - STANDARD_WRITE_AND_X_HEADER_SIZE, - STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout, get_srv_read_error()); + status = read_socket_with_timeout_ntstatus( + fd, writeX_header + 4, + STANDARD_WRITE_AND_X_HEADER_SIZE, + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout, NULL); - if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { - cond_set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); - return -1; + if (!NT_STATUS_IS_OK(status)) { + return status; } /* @@ -232,19 +222,17 @@ static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)sizeof(writeX_header))); - cond_set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); - return -1; + return NT_STATUS_NO_MEMORY; } /* Work out the remaining bytes. */ *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; - - return newlen + 4; + *len_ret = newlen + 4; + return NT_STATUS_OK; } if (!valid_packet_size(len)) { - return -1; + return NT_STATUS_INVALID_PARAMETER; } /* @@ -257,9 +245,7 @@ static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - cond_set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); - return -1; + return NT_STATUS_NO_MEMORY; } /* Copy in what we already read. */ @@ -269,34 +255,17 @@ static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE; if(toread > 0) { - NTSTATUS status; - - set_smb_read_error(get_srv_read_error(), SMB_READ_OK); - status = read_packet_remainder( fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE, timeout, toread); if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_EOF); - return -1; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - return -1; - } - - set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); - return -1; + return status; } } - return len + 4; + *len_ret = len + 4; + return NT_STATUS_OK; } static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, @@ -337,15 +306,34 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */ !srv_is_signing_active()) { - return receive_smb_raw_talloc_partial_read(mem_ctx, - lenbuf, - fd, - buffer, - timeout, - p_unread); + status = receive_smb_raw_talloc_partial_read( + mem_ctx, lenbuf, fd, buffer, timeout, p_unread, &len); + + if (!NT_STATUS_IS_OK(status)) { + + DEBUG(10, ("receive_smb_raw: %s\n", + nt_errstr(status))); + + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_EOF); + return -1; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + return -1; + } + + set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); + return -1; + } } if (!valid_packet_size(len)) { + cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return -1; } -- cgit From 9fe66ddd15b3c5b5d9a30fc79d6ed6cdb31cae12 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:18:56 +0100 Subject: Convert receive_smb_raw_talloc to NTSTATUS (This used to be commit 187707591ffa2668aecd4857cb2ef2cd20bd6b08) --- source3/smbd/process.c | 90 ++++++++++++++++---------------------------------- 1 file changed, 29 insertions(+), 61 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 10ef67c2b2..cb7d12a0c3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -268,37 +268,21 @@ static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, - int fd, - char **buffer, - unsigned int timeout, - size_t *p_unread) +static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd, + char **buffer, unsigned int timeout, + size_t *p_unread, size_t *plen) { char lenbuf[4]; size_t len; int min_recv_size = lp_min_receive_file_size(); NTSTATUS status; - set_smb_read_error(get_srv_read_error(),SMB_READ_OK); *p_unread = 0; status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status))); - - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); - return -1; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - return -1; - } - - set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); - return -1; + return status; } if (CVAL(lenbuf,0) == 0 && @@ -310,31 +294,14 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, mem_ctx, lenbuf, fd, buffer, timeout, p_unread, &len); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status))); - - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_EOF); - return -1; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - return -1; - } - - set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); - return -1; + return status; } } if (!valid_packet_size(len)) { - cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); - return -1; + return NT_STATUS_INVALID_PARAMETER; } /* @@ -346,32 +313,18 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); - return -1; + return NT_STATUS_NO_MEMORY; } memcpy(*buffer, lenbuf, sizeof(lenbuf)); status = read_packet_remainder(fd, (*buffer)+4, timeout, len); if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_EOF); - return -1; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - return -1; - } - - set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); - return -1; + return status; } - return len + 4; + *plen = len + 4; + return NT_STATUS_OK; } static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, @@ -381,18 +334,33 @@ static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, size_t *p_unread, bool *p_encrypted) { - ssize_t len; + size_t len; + NTSTATUS status; *p_encrypted = false; - len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread); + set_smb_read_error(get_srv_read_error(), SMB_READ_OK); + + status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, + p_unread, &len); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); + return -1; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + return -1; + } - if (len < 0) { + set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); return -1; } if (is_encrypted_packet((uint8_t *)*buffer)) { - NTSTATUS status = srv_decrypt_buffer(*buffer); + status = srv_decrypt_buffer(*buffer); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("receive_smb_talloc: SMB decryption failed on " "incoming packet! Error %s\n", -- cgit From e514cd0af56031cd0396e716e9e77edf897420e9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:28:22 +0100 Subject: Convert receive_smb_talloc to NTSTATUS (This used to be commit ddbdd11a49fba9ec4834807dec385cdf3120ce00) --- source3/smbd/process.c | 61 +++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cb7d12a0c3..e21229109d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -327,36 +327,20 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd, return NT_STATUS_OK; } -static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, - int fd, - char **buffer, - unsigned int timeout, - size_t *p_unread, - bool *p_encrypted) +static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, + char **buffer, unsigned int timeout, + size_t *p_unread, bool *p_encrypted, + size_t *p_len) { size_t len; NTSTATUS status; *p_encrypted = false; - set_smb_read_error(get_srv_read_error(), SMB_READ_OK); - status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread, &len); if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); - return -1; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - return -1; - } - - set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); - return -1; + return status; } if (is_encrypted_packet((uint8_t *)*buffer)) { @@ -365,9 +349,7 @@ static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, DEBUG(0, ("receive_smb_talloc: SMB decryption failed on " "incoming packet! Error %s\n", nt_errstr(status) )); - cond_set_smb_read_error(get_srv_read_error(), - SMB_READ_BAD_DECRYPT); - return -1; + return status; } *p_encrypted = true; } @@ -376,11 +358,11 @@ static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, if (!srv_check_sign_mac(*buffer, true)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " "incoming packet!\n")); - cond_set_smb_read_error(get_srv_read_error(),SMB_READ_BAD_SIG); - return -1; + return NT_STATUS_INVALID_NETWORK_RESPONSE; } - return len; + *p_len = len; + return NT_STATUS_OK; } /* @@ -748,7 +730,8 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, int selrtn; struct timeval to; int maxfd = 0; - ssize_t len; + size_t len; + NTSTATUS status; *p_unread = 0; set_smb_read_error(get_srv_read_error(),SMB_READ_OK); @@ -926,14 +909,26 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, goto again; } - len = receive_smb_talloc(mem_ctx, smbd_server_fd(), - buffer, 0, p_unread, p_encrypted); + status = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, + p_unread, p_encrypted, &len); - if (len == -1) { - return False; + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + return false; + } + + set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); + return false; } - *buffer_len = (size_t)len; + *buffer_len = len; return True; } -- cgit From 5e43eeb1b6eef7ea7a88ffc51a0a0535e9bd8023 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:41:48 +0100 Subject: Get rid of read_socket_with_timeout (This used to be commit f9c8ac83ff42137d2101d3bb17e5dcc3c3d70a8f) --- source3/smbd/chgpasswd.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 668c8e2095..bd5ff1f523 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -239,7 +239,8 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, static int expect(int master, char *issue, char *expected) { char buffer[1024]; - int attempts, timeout, nread, len; + int attempts, timeout, nread; + size_t len; bool match = False; for (attempts = 0; attempts < 2; attempts++) { @@ -248,7 +249,8 @@ static int expect(int master, char *issue, char *expected) DEBUG(100, ("expect: sending [%s]\n", issue)); if ((len = sys_write(master, issue, strlen(issue))) != strlen(issue)) { - DEBUG(2,("expect: (short) write returned %d\n", len )); + DEBUG(2,("expect: (short) write returned %d\n", + (int)len )); return False; } } @@ -261,9 +263,16 @@ static int expect(int master, char *issue, char *expected) nread = 0; buffer[nread] = 0; - while ((len = read_socket_with_timeout(master, buffer + nread, 1, - sizeof(buffer) - nread - 1, - timeout, NULL)) > 0) { + while (True) { + NTSTATUS status; + status = read_socket_with_timeout_ntstatus( + master, buffer + nread, 1, + sizeof(buffer) - nread - 1, + timeout, &len); + + if (!NT_STATUS_IS_OK(status)) { + break; + } nread += len; buffer[nread] = 0; -- cgit From 6ddfa6ae7734ffdd26ac38478c27cc9d646ddadd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:43:50 +0100 Subject: read_socket_with_timeout_ntstatus->read_socket_with_timeout (This used to be commit 90554799afa42855c3e7b87dc632e67f0952f988) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/process.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index bd5ff1f523..e7ab60d22f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -265,7 +265,7 @@ static int expect(int master, char *issue, char *expected) while (True) { NTSTATUS status; - status = read_socket_with_timeout_ntstatus( + status = read_socket_with_timeout( master, buffer + nread, 1, sizeof(buffer) - nread - 1, timeout, &len); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e21229109d..83e51e3892 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -141,8 +141,7 @@ static NTSTATUS read_packet_remainder(int fd, char *buffer, return NT_STATUS_OK; } - return read_socket_with_timeout_ntstatus(fd, buffer, len, len, - timeout, NULL); + return read_socket_with_timeout(fd, buffer, len, len, timeout, NULL); } /**************************************************************************** @@ -176,7 +175,7 @@ static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, memcpy(writeX_header, lenbuf, sizeof(lenbuf)); - status = read_socket_with_timeout_ntstatus( + status = read_socket_with_timeout( fd, writeX_header + 4, STANDARD_WRITE_AND_X_HEADER_SIZE, STANDARD_WRITE_AND_X_HEADER_SIZE, -- cgit From 88c27f83d449fa20cba47cbf0a5dbaedc99859d8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:54:22 +0100 Subject: Convert receive_smb_raw to NTSTATUS (This used to be commit ba771bd858602452a9e58c3aab1336f2ac8a25ef) --- source3/smbd/oplock_irix.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index a4ea63bc0a..788cd04c17 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -121,7 +121,6 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) DEBUG(0,("irix_oplock_receive_message: read of kernel " "notification failed. Error was %s.\n", strerror(errno) )); - set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); return NULL; } @@ -141,7 +140,6 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) */ return NULL; } - set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); return NULL; } -- cgit From 21e7344d2f45416ea996f88be72de1a923c0ee9c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:57:20 +0100 Subject: Make get_srv_read_error static to process.c (This used to be commit 9e2947039ef70cab8bbd6027182d9c721eac3194) --- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 83e51e3892..f5a3186e5e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -43,7 +43,7 @@ extern int max_send; /* Accessor function for smb_read_error for smbd functions. */ -enum smb_read_errors *get_srv_read_error(void) +static enum smb_read_errors *get_srv_read_error(void) { return &smb_read_error; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 46c14d158e..f371dde705 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3516,8 +3516,8 @@ void reply_writebraw(struct smb_request *req) (int)tcount,(int)nwritten,(int)numtowrite)); } - if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error()) - != numtowrite ) { + if (read_data(smbd_server_fd(), buf+4, numtowrite, NULL) + != numtowrite ) { DEBUG(0,("reply_writebraw: Oversize secondary write " "raw read failed (%s). Terminating\n", strerror(errno) )); -- cgit From b42a5d68a3ffd88fd60c64b6a75fe2d687d9c92d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 26 Jan 2008 10:39:21 +0100 Subject: Convert read_data() to NTSTATUS (This used to be commit af40b71023f8c4a2133d996ea698c72b97624043) --- source3/smbd/reply.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f371dde705..bced8ed984 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3516,11 +3516,12 @@ void reply_writebraw(struct smb_request *req) (int)tcount,(int)nwritten,(int)numtowrite)); } - if (read_data(smbd_server_fd(), buf+4, numtowrite, NULL) - != numtowrite ) { + status = read_data(smbd_server_fd(), buf+4, numtowrite); + + if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reply_writebraw: Oversize secondary write " - "raw read failed (%s). Terminating\n", - strerror(errno) )); + "raw read failed (%s). Terminating\n", + nt_errstr(status))); exit_server_cleanly("secondary writebraw failed"); } -- cgit From eaf7621c51629f058b85ce4593a2338b9b2d06ed Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 26 Jan 2008 15:18:33 +0100 Subject: Convert receive_message_or_smb to NTSTATUS (This used to be commit 0f7d360a01baf02e251846118cb36e6a1cdcbeb9) --- source3/smbd/process.c | 79 +++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 36 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f5a3186e5e..4fa1248e3b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -718,12 +718,9 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds) The timeout is in milliseconds ****************************************************************************/ -static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, - char **buffer, - size_t *buffer_len, - int timeout, - size_t *p_unread, - bool *p_encrypted) +static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, + size_t *buffer_len, int timeout, + size_t *p_unread, bool *p_encrypted) { fd_set r_fds, w_fds; int selrtn; @@ -733,7 +730,6 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, NTSTATUS status; *p_unread = 0; - set_smb_read_error(get_srv_read_error(),SMB_READ_OK); again: @@ -787,8 +783,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, msg->buf.length); if (*buffer == NULL) { DEBUG(0, ("talloc failed\n")); - set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); - return False; + return NT_STATUS_NO_MEMORY; } *buffer_len = msg->buf.length; *p_encrypted = msg->encrypted; @@ -796,7 +791,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, /* We leave this message on the queue so the open code can know this is a retry. */ DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n")); - return True; + return NT_STATUS_OK; } } @@ -882,14 +877,12 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, /* Check if error */ if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ - set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); - return False; + return map_nt_error_from_unix(errno); } /* Did we timeout ? */ if (selrtn == 0) { - set_smb_read_error(get_srv_read_error(),SMB_READ_TIMEOUT); - return False; + return NT_STATUS_IO_TIMEOUT; } /* @@ -912,24 +905,12 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, p_unread, p_encrypted, &len); if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), SMB_READ_EOF); - return false; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - return false; - } - - set_smb_read_error(get_srv_read_error(), SMB_READ_ERROR); - return false; + return status; } *buffer_len = len; - return True; + return NT_STATUS_OK; } /* @@ -2024,8 +2005,8 @@ void smbd_process(void) while (True) { int select_timeout = setup_select_timeout(); int num_echos; - char *inbuf; - size_t inbuf_len; + char *inbuf = NULL; + size_t inbuf_len = 0; bool encrypted = false; TALLOC_CTX *frame = talloc_stackframe_pool(8192); @@ -2041,13 +2022,39 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); - while (!receive_message_or_smb(talloc_tos(), &inbuf, &inbuf_len, - select_timeout, - &unread_bytes, - &encrypted)) { - if(!timeout_processing(&select_timeout, - &last_timeout_processing_time)) + while (True) { + NTSTATUS status; + + set_smb_read_error(get_srv_read_error(), SMB_READ_OK); + + status = receive_message_or_smb( + talloc_tos(), &inbuf, &inbuf_len, + select_timeout, &unread_bytes, &encrypted); + + if (NT_STATUS_IS_OK(status)) { + break; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_EOF); + } + else if (NT_STATUS_EQUAL(status, + NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(get_srv_read_error(), + SMB_READ_TIMEOUT); + } + else { + set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); + } + + if (!timeout_processing( + &select_timeout, + &last_timeout_processing_time)) { return; + } + num_smbs = 0; /* Reset smb counter. */ } -- cgit From 9e5a5d49dee83335f6990c4ec5d3b11f1f69e2e7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 26 Jan 2008 15:33:40 +0100 Subject: Remove dependency on get_srv_read_error() from main loop (This used to be commit fad87968921eca0b5144760c412c5f599f9066f3) --- source3/smbd/process.c | 69 +++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 4fa1248e3b..3cb1331054 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1888,27 +1888,11 @@ void check_reload(time_t t) Process any timeout housekeeping. Return False if the caller should exit. ****************************************************************************/ -static bool timeout_processing(int *select_timeout, +static void timeout_processing(int *select_timeout, time_t *last_timeout_processing_time) { time_t t; - if (*get_srv_read_error() == SMB_READ_EOF) { - DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); - return false; - } - - if (*get_srv_read_error() == SMB_READ_ERROR) { - DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", - strerror(errno))); - return false; - } - - if (*get_srv_read_error() == SMB_READ_BAD_SIG) { - DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); - return false; - } - *last_timeout_processing_time = t = time(NULL); /* become root again if waiting */ @@ -1938,14 +1922,14 @@ static bool timeout_processing(int *select_timeout, if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { DEBUG(0,("process: unable to lock the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); - return True; + return; } if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) { DEBUG(0,("process: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup())); secrets_lock_trust_account_password(lp_workgroup(), False); - return True; + return; } /* @@ -1955,7 +1939,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); if(t < lct + lp_machine_password_timeout()) { global_machine_password_needs_changing = False; secrets_lock_trust_account_password(lp_workgroup(), False); - return True; + return; } /* always just contact the PDC here */ @@ -1987,7 +1971,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); *select_timeout = setup_select_timeout(); - return True; + return; } /**************************************************************************** @@ -2014,9 +1998,8 @@ void smbd_process(void) /* Did someone ask for immediate checks on things like blocking locks ? */ if (select_timeout == 0) { - if(!timeout_processing(&select_timeout, - &last_timeout_processing_time)) - return; + timeout_processing(&select_timeout, + &last_timeout_processing_time); num_smbs = 0; /* Reset smb counter. */ } @@ -2025,8 +2008,6 @@ void smbd_process(void) while (True) { NTSTATUS status; - set_smb_read_error(get_srv_read_error(), SMB_READ_OK); - status = receive_message_or_smb( talloc_tos(), &inbuf, &inbuf_len, select_timeout, &unread_bytes, &encrypted); @@ -2035,25 +2016,16 @@ void smbd_process(void) break; } - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_EOF); - } - else if (NT_STATUS_EQUAL(status, - NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(get_srv_read_error(), - SMB_READ_TIMEOUT); - } - else { - set_smb_read_error(get_srv_read_error(), - SMB_READ_ERROR); + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + timeout_processing( + &select_timeout, + &last_timeout_processing_time); + continue; } - if (!timeout_processing( - &select_timeout, - &last_timeout_processing_time)) { - return; - } + DEBUG(3, ("receive_message_or_smb failed: %s, " + "exiting\n", nt_errstr(status))); + return; num_smbs = 0; /* Reset smb counter. */ } @@ -2075,8 +2047,8 @@ void smbd_process(void) TALLOC_FREE(inbuf); if (smb_echo_count != num_echos) { - if(!timeout_processing( &select_timeout, &last_timeout_processing_time)) - return; + timeout_processing(&select_timeout, + &last_timeout_processing_time); num_smbs = 0; /* Reset smb counter. */ } @@ -2092,10 +2064,9 @@ void smbd_process(void) if ((num_smbs % 200) == 0) { time_t new_check_time = time(NULL); if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) { - if(!timeout_processing( - &select_timeout, - &last_timeout_processing_time)) - return; + timeout_processing( + &select_timeout, + &last_timeout_processing_time); num_smbs = 0; /* Reset smb counter. */ last_timeout_processing_time = new_check_time; /* Reset time. */ } -- cgit From e8f1edb9cd0d2014c05cdb2aba4f4deef48efedf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 26 Jan 2008 15:36:00 +0100 Subject: Remove smb_read_error global YESS :-) (This used to be commit 26771bdca0e6837db267f4db7907e489acd92fc6) --- source3/smbd/process.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3cb1331054..2a643864fa 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -22,8 +22,6 @@ extern int smb_echo_count; -static enum smb_read_errors smb_read_error = SMB_READ_OK; - /* * Size of data we can send to client. Set * by the client for all protocols above CORE. @@ -43,11 +41,6 @@ extern int max_send; /* Accessor function for smb_read_error for smbd functions. */ -static enum smb_read_errors *get_srv_read_error(void) -{ - return &smb_read_error; -} - /**************************************************************************** Send an smb to a fd. ****************************************************************************/ -- cgit From 2762b9a97582b9b28fd5985ba8e3d0299126820e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 4 Feb 2008 20:57:35 +0100 Subject: Always pass a TALLOC_CTX to str_list_make and str_list_copy (This used to be commit e2c9fc4cf5f0ff725330fa44f53782db65fca37e) --- source3/smbd/map_username.c | 6 +++--- source3/smbd/password.c | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index 7290f70547..7536758bcb 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -178,7 +178,7 @@ bool map_username(fstring user) /* skip lines like 'user = ' */ - dosuserlist = str_list_make(dosname, NULL); + dosuserlist = str_list_make(talloc_tos(), dosname, NULL); if (!dosuserlist) { DEBUG(0,("Bad username map entry. Unable to build user list. Ignoring.\n")); continue; @@ -193,13 +193,13 @@ bool map_username(fstring user) fstrcpy( user, unixname ); if ( return_if_mapped ) { - str_list_free (&dosuserlist); + TALLOC_FREE(dosuserlist); x_fclose(f); return True; } } - str_list_free (&dosuserlist); + TALLOC_FREE(dosuserlist); } x_fclose(f); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 85e1ccf0a7..913c3c35da 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -582,7 +582,7 @@ static bool user_ok(const char *user, int snum) ret = True; if (lp_invalid_users(snum)) { - str_list_copy(&invalid, lp_invalid_users(snum)); + str_list_copy(talloc_tos(), &invalid, lp_invalid_users(snum)); if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { @@ -599,7 +599,7 @@ static bool user_ok(const char *user, int snum) str_list_free (&invalid); if (ret && lp_valid_users(snum)) { - str_list_copy(&valid, lp_valid_users(snum)); + str_list_copy(talloc_tos(), &valid, lp_valid_users(snum)); if ( valid && str_list_substitute(valid, "%S", lp_servicename(snum)) ) { @@ -615,13 +615,14 @@ static bool user_ok(const char *user, int snum) str_list_free (&valid); if (ret && lp_onlyuser(snum)) { - char **user_list = str_list_make (lp_username(snum), NULL); + char **user_list = str_list_make( + talloc_tos(), lp_username(snum), NULL); if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) { ret = user_in_list(user, (const char **)user_list); } - if (user_list) str_list_free (&user_list); + TALLOC_FREE(user_list); } return(ret); -- cgit From b361956942618ec2f7c2efc60cb190858adbc516 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 4 Feb 2008 21:05:41 +0100 Subject: str_list_free is not needed anymore (This used to be commit feddc1447d585fd108d22a36bccc576fa81197ef) --- source3/smbd/password.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 913c3c35da..687b67950a 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -595,8 +595,7 @@ static bool user_ok(const char *user, int snum) } } } - if (invalid) - str_list_free (&invalid); + TALLOC_FREE(invalid); if (ret && lp_valid_users(snum)) { str_list_copy(talloc_tos(), &valid, lp_valid_users(snum)); @@ -611,8 +610,7 @@ static bool user_ok(const char *user, int snum) } } } - if (valid) - str_list_free (&valid); + TALLOC_FREE(valid); if (ret && lp_onlyuser(snum)) { char **user_list = str_list_make( -- cgit From 55af880341226f8ecd864cbe046af8434a961278 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 5 Feb 2008 15:32:14 +0100 Subject: Fix typo. Karolin (This used to be commit 3745e398b1cc4d1b76a7cb4ee9c998ff16b454b9) --- source3/smbd/lanman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 5a6df1f139..18e6bf9f7b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3175,7 +3175,7 @@ static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, where: - usri11_name specifies the user name for which information is retireved + usri11_name specifies the user name for which information is retrieved usri11_pad aligns the next data structure element to a word boundary -- cgit From 47666c93a78dc7a9c18212bfe7be3e6487313226 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Feb 2008 13:36:17 -0800 Subject: Fix a couple of "might be used uninitialized" warnings. Jeremy. (This used to be commit b3ac8073a23afbba19d045302aa0700197c58bd5) --- source3/smbd/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2a643864fa..68bec7830a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -324,7 +324,7 @@ static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, size_t *p_unread, bool *p_encrypted, size_t *p_len) { - size_t len; + size_t len = 0; NTSTATUS status; *p_encrypted = false; @@ -719,7 +719,7 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, int selrtn; struct timeval to; int maxfd = 0; - size_t len; + size_t len = 0; NTSTATUS status; *p_unread = 0; -- cgit From 1ae0f2d02ea5909fbb8cfa7c0d78291048699b9c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 6 Feb 2008 09:09:23 +0300 Subject: Allow actual call to set file offline Dos mode calculation was masking out FILE_ATTRIBUTE_OFFLINE so that code to set file offline was never called before. Merge from Tridge's v3-0-ctdb git tree. (This used to be commit 9827d5ff416479408b19a8964c2321ea2517aa74) --- source3/smbd/dosmode.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index eb18f65fca..f068f1f655 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -419,9 +419,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname, mode_t tmp; mode_t unixmode; int ret = -1, lret = -1; + uint32_t old_mode; /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */ - dosmode &= SAMBA_ATTRIBUTES_MASK; + dosmode &= SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE; DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname)); @@ -444,7 +445,24 @@ int file_set_dosmode(connection_struct *conn, const char *fname, else dosmode &= ~aDIR; - if (dos_mode(conn,fname,st) == dosmode) { + old_mode = dos_mode(conn,fname,st); + + if (dosmode & FILE_ATTRIBUTE_OFFLINE) { + if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) { + lret = SMB_VFS_SET_OFFLINE(conn, fname); + if (lret == -1) { + DEBUG(0, ("set_dos_mode: client has asked to set " + "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was " + "an error while setting it or it is not supported.\n", + parent_dir, fname)); + } + } + } + + dosmode &= ~FILE_ATTRIBUTE_OFFLINE; + old_mode &= ~FILE_ATTRIBUTE_OFFLINE; + + if (old_mode == dosmode) { st->st_mode = unixmode; return(0); } @@ -491,16 +509,6 @@ int file_set_dosmode(connection_struct *conn, const char *fname, unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if (dosmode & FILE_ATTRIBUTE_OFFLINE) { - lret = SMB_VFS_SET_OFFLINE(conn, fname); - if (lret == -1) { - DEBUG(0, ("set_dos_mode: client has asked to set " - "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was " - "an error while setting it or it is not supported.\n", - parent_dir, fname)); - } - } - ret = SMB_VFS_CHMOD(conn, fname, unixmode); if (ret == 0) { if(!newfile || (lret != -1)) { -- cgit From a4436154b8ce446e84e6c07bd9c69edfafe1b68c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 6 Feb 2008 09:10:50 +0300 Subject: Change the file time before we change the file mode. This doesn't matter for most applications, but for offline files it matters as it allows you to set files offline from windows clients even with HSM systems that refuse to offline newly created files. Merge from Tridge's v3-0-ctdb tree. (This used to be commit 7da6c675440b0253ab37ee6097f769a2e45c7b7b) --- source3/smbd/reply.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bced8ed984..baebff83de 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1110,6 +1110,12 @@ void reply_setatr(struct smb_request *req) mode = SVAL(req->inbuf,smb_vwv0); mtime = srv_make_unix_date3(req->inbuf+smb_vwv1); + if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) { + reply_unixerror(req, ERRDOS, ERRnoaccess); + END_PROFILE(SMBsetatr); + return; + } + if (mode != FILE_ATTRIBUTE_NORMAL) { if (VALID_STAT_OF_DIR(sbuf)) mode |= aDIR; @@ -1123,12 +1129,6 @@ void reply_setatr(struct smb_request *req) } } - if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) { - reply_unixerror(req, ERRDOS, ERRnoaccess); - END_PROFILE(SMBsetatr); - return; - } - reply_outbuf(req, 0, 0); DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); -- cgit From a33236f4aa2d90ca7293c627d9e34d855fea65e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Feb 2008 10:31:22 -0800 Subject: Make operator precedence very clear. Jeremy. (This used to be commit 4f125110cfe25b499eb628b5b08fdb610a5d972c) --- source3/smbd/dosmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index f068f1f655..a2e617c117 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -422,7 +422,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32_t old_mode; /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */ - dosmode &= SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE; + dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE); DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname)); -- cgit From 2a6a2288c5fae908f431bd79332554e0a23dbeed Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 8 Feb 2008 09:28:57 +0100 Subject: Fix some typos. Karolin (This used to be commit 2bec0a1fb7857e6fb8ec15e5f597b2d4125f105b) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index baebff83de..669dad2e3a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2469,7 +2469,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, } count++; - DEBUG(3,("unlink_internals: succesful unlink [%s]\n", + DEBUG(3,("unlink_internals: successful unlink [%s]\n", fname)); TALLOC_FREE(fname); -- cgit From de48cd925a11414063cae7ead89fa060c280352a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 4 Feb 2008 13:47:15 +0100 Subject: smbd: use make usage of wbcDomainInfo() metze (This used to be commit 9d6b43ea106df188b51060a8055fe5168220c314) --- source3/smbd/sesssetup.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index aee8e498e9..1e4e208951 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -410,30 +410,24 @@ static void reply_spnego_kerberos(struct smb_request *req, name. And even w2k3 does use ntlmssp if you for example connect to an ip address. */ - struct winbindd_request wb_request; - struct winbindd_response wb_response; - NSS_STATUS wb_result; - - ZERO_STRUCT(wb_request); - ZERO_STRUCT(wb_response); + wbcErr wbc_status; + struct wbcDomainInfo *info = NULL; DEBUG(10, ("Mapping [%s] to short name\n", domain)); - fstrcpy(wb_request.domain_name, domain); - - wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO, - &wb_request, &wb_response); + wbc_status = wbcDomainInfo(domain, &info); - if (wb_result == NSS_STATUS_SUCCESS) { + if (WBC_ERROR_IS_OK(wbc_status)) { fstrcpy(netbios_domain_name, - wb_response.data.domain_info.name); - domain = netbios_domain_name; + info->short_name); + wbcFreeMemory(info); + domain = netbios_domain_name; DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain)); } else { - DEBUG(3, ("Could not find short name -- winbind " - "not running?\n")); + DEBUG(3, ("Could not find short name: %s\n", + wbcErrorString(wbc_status))); } } -- cgit From 0a89940df5255a3921f81721a627610967fe2698 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2008 18:06:16 -0800 Subject: Ensure invalidate_vuid() deletes any ntlmssp state. Jeremy. (This used to be commit b41799c351c72b268ef094047a51766747671280) --- source3/smbd/password.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 687b67950a..80eba562c5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -121,6 +121,10 @@ void invalidate_vuid(uint16 vuid) data_blob_free(&vuser->session_key); + if (vuser->auth_ntlmssp_state) { + auth_ntlmssp_end(&vuser->auth_ntlmssp_state); + } + DLIST_REMOVE(validated_users, vuser); /* clear the vuid from the 'cache' on each connection, and -- cgit From 81d6133b0363be3736e60d8336a90129d67d7e4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2008 18:07:27 -0800 Subject: Currently we don't SPNEGO negotiate back to NTLMSSP. Note this. Jeremy. (This used to be commit 8cd04b948bfba3896d40c9e314a197f60ad76833) --- source3/smbd/seal.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index ea017e08d8..d4394e5bca 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -496,12 +496,15 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, srv_free_encryption_context(&partial_srv_trans_enc_ctx); + if (got_kerberos_mechanism) { #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); - } else +#else + /* Currently we don't SPNEGO negotiate + * back to NTLMSSP as we do in sessionsetupX. We should... */ + return NT_STATUS_LOGON_FAILURE; #endif - { + } else { status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true); } @@ -558,7 +561,16 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); data_blob_free(&auth); - response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); + /* From RFC4178. + * + * supportedMech + * + * This field SHALL only be present in the first reply from the + * target. + * So set mechOID to NULL here. + */ + + response = spnego_gen_auth_response(&auth_reply, status, NULL); data_blob_free(&auth_reply); if (NT_STATUS_IS_OK(status)) { -- cgit From 4754c2bafe0ac5dc176c1e1d371bbc15165a7447 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2008 18:10:50 -0800 Subject: Correctly use SPNEGO to negotiate down from krb5 to NTLMSSP. Previously we didn't implement the 'NEGO' part of SPNEGO :-). Jeremy. (This used to be commit 8767a0dab95c544878b4187157e494e740974bb8) --- source3/smbd/sesssetup.c | 109 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 28 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1e4e208951..3e04da35df 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -620,6 +620,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req, uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, + const char *OID, bool wrap) { DATA_BLOB response; @@ -680,7 +681,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req, if (wrap) { response = spnego_gen_auth_response(ntlmssp_blob, - nt_status, OID_NTLMSSP); + nt_status, OID); } else { response = *ntlmssp_blob; } @@ -744,6 +745,28 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, return NT_STATUS_OK; } +/**************************************************************************** + Fall back from krb5 to NTLMSSP. +****************************************************************************/ + +static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req, + uint16 vuid) +{ + DATA_BLOB response; + + reply_outbuf(req, 4, 0); + SSVAL(req->outbuf,smb_uid,vuid); + + DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO " + "but set to downgrade to NTLMSSP\n")); + + response = spnego_gen_auth_response(NULL, + NT_STATUS_MORE_PROCESSING_REQUIRED, + OID_NTLMSSP); + reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED); + data_blob_free(&response); +} + /**************************************************************************** Reply to a session setup spnego negotiate packet. ****************************************************************************/ @@ -789,6 +812,15 @@ static void reply_spnego_negotiate(struct smb_request *req, auth_ntlmssp_end(auth_ntlmssp_state); } + if (got_kerberos_mechanism) { + data_blob_free(&secblob); + /* The mechtoken is a krb5 ticket, but + * we need to fall back to NTLM. */ + reply_spnego_downgrade_to_ntlmssp(req, + vuid); + return; + } + status = auth_ntlmssp_start(auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ @@ -803,7 +835,7 @@ static void reply_spnego_negotiate(struct smb_request *req, data_blob_free(&secblob); reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state, - &chal, status, True); + &chal, status, OID_NTLMSSP, true); data_blob_free(&chal); @@ -823,7 +855,7 @@ static void reply_spnego_auth(struct smb_request *req, DATA_BLOB auth = data_blob_null; DATA_BLOB auth_reply = data_blob_null; DATA_BLOB secblob = data_blob_null; - NTSTATUS status = NT_STATUS_INVALID_PARAMETER; + NTSTATUS status = NT_STATUS_LOGON_FAILURE; if (!spnego_parse_auth(blob1, &auth)) { #if 0 @@ -833,7 +865,7 @@ static void reply_spnego_auth(struct smb_request *req, invalidate_vuid(vuid); reply_nterror(req, nt_status_squash( - NT_STATUS_INVALID_PARAMETER)); + NT_STATUS_LOGON_FAILURE)); return; } @@ -843,24 +875,43 @@ static void reply_spnego_auth(struct smb_request *req, bool got_krb5_mechanism = False; status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism); - if (NT_STATUS_IS_OK(status)) { - DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", - (unsigned long)secblob.length)); + + if (!NT_STATUS_IS_OK(status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + reply_nterror(req, nt_status_squash(status)); + return; + } + + DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", + (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || - lp_use_kerberos_keytab()) ) { - bool destroy_vuid = True; - reply_spnego_kerberos(req, &secblob, - vuid, &destroy_vuid); - data_blob_free(&secblob); - data_blob_free(&auth); - if (destroy_vuid) { - /* Kill the intermediate vuid */ - invalidate_vuid(vuid); - } - return; + if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || + lp_use_kerberos_keytab()) ) { + bool destroy_vuid = True; + reply_spnego_kerberos(req, &secblob, + vuid, &destroy_vuid); + data_blob_free(&secblob); + data_blob_free(&auth); + if (destroy_vuid) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); } + return; + } #endif + /* Can't blunder into NTLMSSP auth if we have + * a krb5 ticket. */ + + if (got_krb5_mechanism) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + DEBUG(3,("reply_spnego_auth: network " + "misconfiguration, client sent us a " + "krb5 ticket and kerberos security " + "not enabled")); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); } } @@ -868,13 +919,13 @@ static void reply_spnego_auth(struct smb_request *req, data_blob_free(&secblob); if (!*auth_ntlmssp_state) { - /* Kill the intermediate vuid */ - invalidate_vuid(vuid); - - /* auth before negotiatiate? */ - reply_nterror(req, nt_status_squash( - NT_STATUS_INVALID_PARAMETER)); - return; + status = auth_ntlmssp_start(auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + reply_nterror(req, nt_status_squash(status)); + return; + } } status = auth_ntlmssp_update(*auth_ntlmssp_state, @@ -882,9 +933,11 @@ static void reply_spnego_auth(struct smb_request *req, data_blob_free(&auth); + /* Don't send the mechid as we've already sent this (RFC4178). */ + reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state, - &auth_reply, status, True); + &auth_reply, status, NULL, true); data_blob_free(&auth_reply); @@ -1251,7 +1304,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) reply_spnego_ntlmssp(req, vuid, &vuser->auth_ntlmssp_state, - &chal, status, False); + &chal, status, OID_NTLMSSP, false); data_blob_free(&chal); return; } -- cgit From 65fc3ae0701dba3d8c336abd236716413b1f634d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 16 Feb 2008 18:55:08 +0100 Subject: Use new structs in reply_spnego_kerberos(). Guenther (This used to be commit c55160f8e866d9b24a4dad234af78ae46c236a37) --- source3/smbd/sesssetup.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3e04da35df..9baa02977a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -259,7 +259,7 @@ static void reply_spnego_kerberos(struct smb_request *req, fstring user; int sess_vuid = req->vuid; NTSTATUS ret = NT_STATUS_OK; - PAC_DATA *pac_data = NULL; + struct PAC_DATA *pac_data = NULL; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob_null; @@ -268,7 +268,7 @@ static void reply_spnego_kerberos(struct smb_request *req, fstring real_username; bool map_domainuser_to_guest = False; bool username_was_mapped; - PAC_LOGON_INFO *logon_info = NULL; + struct PAC_LOGON_INFO *logon_info = NULL; ZERO_STRUCT(ticket); ZERO_STRUCT(ap_rep); @@ -394,10 +394,9 @@ static void reply_spnego_kerberos(struct smb_request *req, domain = p+1; - if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { - unistr2_to_ascii(netbios_domain_name, - &logon_info->info3.uni_logon_dom, - sizeof(netbios_domain_name)); + if (logon_info && logon_info->info3.base.domain.string) { + fstrcpy(netbios_domain_name, + logon_info->info3.base.domain.string); domain = netbios_domain_name; DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); -- cgit From a8fbb92146ddfe0b774f8385dfdea672447a1c46 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 18 Feb 2008 10:21:50 +1100 Subject: Check return code of secrets_init() function. (This used to be commit 2b1eead269e95142576d0c8c259874324ba83502) --- source3/smbd/server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7116027adf..7bf11abfbd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -988,7 +988,8 @@ static bool init_structs(void ) init_dptrs(); - secrets_init(); + if (!secrets_init()) + return False; return True; } -- cgit From e12cd305dd9d383058d5bdfa805078735c8018e3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Feb 2008 15:53:57 +0100 Subject: Inform level II oplock holders when we write using AIO Jeremy, please check! (This used to be commit 81d823e026fb332a88b6e1f15030fe49719f2522) --- source3/smbd/aio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 86fdfe31b7..5515582eec 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -351,6 +351,8 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } + release_level_2_oplocks_on_change(fsp); + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) { /* Lie to the client and immediately claim we finished the -- cgit From 4c4c1bfb798aafa5a338a821456bae75e4753da1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Feb 2008 13:27:08 +0100 Subject: Update position information also for AIO Necessary to survive RAW-SEEK with AIO enabled. Jeremy, please check! (This used to be commit e2ca12c2345c0e3916dd09d097b2ba1ce2989fa8) --- source3/smbd/aio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 5515582eec..8c6eaf1498 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -423,6 +423,9 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,nread); + aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread; + aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos; + DEBUG( 3, ( "handle_aio_read_complete file %s max=%d " "nread=%d\n", aio_ex->fsp->fsp_name, @@ -524,6 +527,8 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); } + + aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten; } show_msg(outbuf); -- cgit From 14aa57a9e3368fed5b8b7d1ac0f6e94b9b1ac20e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 22 Feb 2008 16:17:10 +0100 Subject: Don't use fname after create_file has been called create_file calls unix_convert internally, so modifies fname. So we can't use "fname" after create_file has returned. Use fsp->fsp_name instead. Found during a lengthy debugging session with Karolin testing the xattr_tdb module... (This used to be commit 183fe570469963923864b732817a87f8660341ed) --- source3/smbd/nttrans.c | 10 +++++----- source3/smbd/reply.c | 22 +++++++++++----------- source3/smbd/trans2.c | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9381174af0..5293ca5347 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -558,7 +558,7 @@ void reply_ntcreate_and_X(struct smb_request *req) } file_len = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -626,7 +626,7 @@ void reply_ntcreate_and_X(struct smb_request *req) uint32 perms = 0; p += 25; if (fsp->is_directory - || can_write_to_file(conn, fname, &sbuf)) { + || can_write_to_file(conn, fsp->fsp_name, &sbuf)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; @@ -1007,7 +1007,7 @@ static void call_nt_transact_create(connection_struct *conn, } file_len = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -1075,7 +1075,7 @@ static void call_nt_transact_create(connection_struct *conn, uint32 perms = 0; p += 25; if (fsp->is_directory - || can_write_to_file(conn, fname, &sbuf)) { + || can_write_to_file(conn, fsp->fsp_name, &sbuf)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; @@ -1083,7 +1083,7 @@ static void call_nt_transact_create(connection_struct *conn, SIVAL(p,0,perms); } - DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); + DEBUG(5,("call_nt_transact_create: open name = %s\n", fsp->fsp_name)); /* Send the required number of replies */ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 669dad2e3a..818ff319e4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1639,11 +1639,11 @@ void reply_open(struct smb_request *req) } size = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); mtime = sbuf.st_mtime; if (fattr & aDIR) { - DEBUG(3,("attempt to open a directory %s\n",fname)); + DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name)); close_file(fsp,ERROR_CLOSE); reply_doserror(req, ERRDOS,ERRnoaccess); END_PROFILE(SMBopen); @@ -1802,7 +1802,7 @@ void reply_open_and_X(struct smb_request *req) sbuf.st_size = get_allocation_size(conn,fsp,&sbuf); } - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); mtime = sbuf.st_mtime; if (fattr & aDIR) { close_file(fsp,ERROR_CLOSE); @@ -1985,7 +1985,7 @@ void reply_mknew(struct smb_request *req) } ts[0] = get_atimespec(&sbuf); /* atime. */ - file_ntimes(conn, fname, ts); + file_ntimes(conn, fsp->fsp_name, ts); reply_outbuf(req, 1, 0); SSVAL(req->outbuf,smb_vwv0,fsp->fnum); @@ -2000,9 +2000,9 @@ void reply_mknew(struct smb_request *req) CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - DEBUG( 2, ( "reply_mknew: file %s\n", fname ) ); + DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) ); DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", - fname, fsp->fh->fd, (unsigned int)fattr ) ); + fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) ); END_PROFILE(SMBcreate); return; @@ -2125,9 +2125,9 @@ void reply_ctemp(struct smb_request *req) SSVAL(req->outbuf,smb_vwv0,fsp->fnum); /* the returned filename is relative to the directory */ - s = strrchr_m(fname, '/'); + s = strrchr_m(fsp->fsp_name, '/'); if (!s) { - s = fname; + s = fsp->fsp_name; } else { s++; } @@ -2154,9 +2154,9 @@ void reply_ctemp(struct smb_request *req) CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) ); - DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd, - (unsigned int)sbuf.st_mode ) ); + DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) ); + DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name, + fsp->fh->fd, (unsigned int)sbuf.st_mode ) ); END_PROFILE(SMBctemp); return; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1f7af82670..dc908846b3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1017,7 +1017,7 @@ static void call_trans2open(connection_struct *conn, } size = get_file_size(sbuf); - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fattr & aDIR) { @@ -1054,7 +1054,7 @@ static void call_trans2open(connection_struct *conn, SIVAL(params,20,inode); SSVAL(params,24,0); /* Padding. */ if (flags & 8) { - uint32 ea_size = estimate_ea_size(conn, fsp, fname); + uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name); SIVAL(params, 26, ea_size); } else { SIVAL(params, 26, 0); -- cgit From 6cdd527fed86476f9fc86b11cd5d2e7f1067d2e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Feb 2008 16:12:57 -0800 Subject: Fix debug messages. Jeremy. (This used to be commit d265cedb55b07c6b8a13b9632fbdf8a05fbba886) --- source3/smbd/open.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aa4bc48f3d..cc78503379 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2671,8 +2671,9 @@ NTSTATUS create_file_unixpath(connection_struct *conn, status = split_ntfs_stream_name(talloc_tos(), fname, &base, NULL); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("split_ntfs_stream_name failed: %s\n", - nt_errstr(status))); + DEBUG(10, ("create_file_unixpath: " + "split_ntfs_stream_name failed: %s\n", + nt_errstr(status))); goto fail; } @@ -2840,7 +2841,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, } } - DEBUG(10, ("create_file: info=%d\n", info)); + DEBUG(10, ("create_file_unixpath: info=%d\n", info)); /* * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In @@ -2867,7 +2868,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, return NT_STATUS_OK; fail: - DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + DEBUG(10, ("create_file_unixpath: %s\n", nt_errstr(status))); if (fsp != NULL) { close_file(fsp, ERROR_CLOSE); -- cgit From db9db9cef9b1ec04952ff7f0079cdff1e6ea8016 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Feb 2008 00:01:07 +0100 Subject: AIO on streams does not work (yet...) (This used to be commit 1ba223f202a070a695581e0d7161473a3ebf4332) --- source3/smbd/aio.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 8c6eaf1498..59dd9a9568 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -202,6 +202,12 @@ bool schedule_aio_read_and_X(connection_struct *conn, size_t bufsize; size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); + if (fsp->base_fsp != NULL) { + /* No AIO on streams yet */ + DEBUG(10, ("AIO on streams not yet supported\n")); + return false; + } + if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a read for aio request. */ @@ -285,6 +291,12 @@ bool schedule_aio_write_and_X(connection_struct *conn, bool write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); + if (fsp->base_fsp != NULL) { + /* No AIO on streams yet */ + DEBUG(10, ("AIO on streams not yet supported\n")); + return false; + } + if ((!min_aio_write_size || (numtowrite < min_aio_write_size)) && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a write for aio request. */ -- cgit From 21b6a036780ae0c020e199043c25c63fbbf8fa95 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Feb 2008 11:39:57 +0100 Subject: Export aio_request_done() This is for external modules implementing the Posix AIO API that not necessarily depend on the signal mechanism to indicate completion. (This used to be commit 9a069d306bb6f8a2cd51b8ba87b433884942d13f) --- source3/smbd/aio.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 59dd9a9568..78189d32f7 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -150,12 +150,18 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE]; Signal handler when an aio request completes. *****************************************************************************/ -static void signal_handler(int sig, siginfo_t *info, void *unused) +void aio_request_done(uint16_t mid) { if (signals_received < AIO_PENDING_SIZE) { - aio_pending_array[signals_received] = info->si_value.sival_int; + aio_pending_array[signals_received] = mid; signals_received++; - } /* Else signal is lost. */ + } + /* Else signal is lost. */ +} + +static void signal_handler(int sig, siginfo_t *info, void *unused) +{ + aio_request_done(info->si_value.sival_int); sys_select_signal(RT_SIGNAL_AIO); } -- cgit From fcee8fee63fc907f106477a55d651b5a1be692bf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Feb 2008 11:32:22 +0100 Subject: Allow "max mux" async i/o requests In the negprot reply, we allowed the client to issued "max mux" concurrent requests. The OS might allow less, for example AFAIK AIX has a configurable limit of concurrent AIO requests. We will fall back to sync operation for the requests that are too many when aio_read/aio_write return an error. Jeremy, please check! (This used to be commit 8f86f7f25c4eb71bbdfcc6bf2d12eaaae9a8d9ec) --- source3/smbd/aio.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 78189d32f7..2889e3c13f 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -141,10 +141,10 @@ static struct aio_extra *find_aio_ex(uint16 mid) We can have these many aio buffers in flight. *****************************************************************************/ -#define AIO_PENDING_SIZE 10 +static int aio_pending_size; static sig_atomic_t signals_received; static int outstanding_aio_calls; -static uint16 aio_pending_array[AIO_PENDING_SIZE]; +static uint16 *aio_pending_array; /**************************************************************************** Signal handler when an aio request completes. @@ -152,7 +152,7 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE]; void aio_request_done(uint16_t mid) { - if (signals_received < AIO_PENDING_SIZE) { + if (signals_received < aio_pending_size) { aio_pending_array[signals_received] = mid; signals_received++; } @@ -182,6 +182,10 @@ void initialize_async_io_handler(void) { struct sigaction act; + aio_pending_size = lp_maxmux(); + aio_pending_array = SMB_MALLOC_ARRAY(uint16, aio_pending_size); + SMB_ASSERT(aio_pending_array != NULL); + ZERO_STRUCT(act); act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; @@ -231,7 +235,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, return False; } - if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + if (outstanding_aio_calls >= aio_pending_size) { DEBUG(10,("schedule_aio_read_and_X: Already have %d aio " "activities outstanding.\n", outstanding_aio_calls )); @@ -320,7 +324,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } - if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + if (outstanding_aio_calls >= aio_pending_size) { DEBUG(3,("schedule_aio_write_and_X: Already have %d aio " "activities outstanding.\n", outstanding_aio_calls )); -- cgit From 43491db17c8f0b62f5bfdcb68a92feef651ed5d4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Feb 2008 12:52:55 +0100 Subject: Fix inotify detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug 5271 -- thanks to Tiziano Müller (This used to be commit 4a1a138b0fe0f2200e5a37a0609481e4340a896c) --- source3/smbd/notify_inotify.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 73cee440d4..fa0f0ed51d 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -29,10 +29,12 @@ #include #endif +#ifndef HAVE_INOTIFY_INIT + #include #include -#ifndef HAVE_INOTIFY_INIT + /* glibc doesn't define these functions yet (as of March 2006) */ @@ -50,6 +52,10 @@ static int inotify_rm_watch(int fd, int wd) { return syscall(__NR_inotify_rm_watch, fd, wd); } +#else + +#include + #endif -- cgit From 23cd8e5ea7f2aac6cfdcb52666ba4e925740f63f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 6 Mar 2008 12:24:37 +0100 Subject: Be more verbose why create local token has failed during NTLMSSP and Kerberos session setup Guenther (This used to be commit 18b8c2c19e50aee8fc900c7507244cb95014a4fa) --- source3/smbd/sesssetup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9baa02977a..5578dafd85 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -539,6 +539,8 @@ static void reply_spnego_kerberos(struct smb_request *req, if ( !server_info->ptok ) { ret = create_local_token( server_info ); if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(10,("failed to create local token: %s\n", + nt_errstr(ret))); SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); -- cgit From 6a2dbea79433465518a47a275f3ed5fbaa887c1e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Mar 2008 19:54:17 +0100 Subject: Fix some typos (This used to be commit cfa1b838144800c0758969921b8904fd62e46c07) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dc908846b3..008ffed5a1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3189,7 +3189,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", } DEBUG( 4,("call_trans2setfsinfo: " - "request transport encrption.\n")); + "request transport encryption.\n")); status = srv_request_encryption_setup(conn, (unsigned char **)ppdata, -- cgit From d634ab06b34990b6eecee751435f2436ff76ec44 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 10 Mar 2008 15:48:04 +0100 Subject: Convert secrets_lock_trust_account_password to talloc This is preparing the conversion of secrets.c to ctdb (This used to be commit 1307f0130c47b8d740d2b7afe7a5d8d1a655e2a2) --- source3/smbd/process.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 68bec7830a..9c01bbaa4a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1901,6 +1901,7 @@ static void timeout_processing(int *select_timeout, unsigned char trust_passwd_hash[16]; time_t lct; + void *lock; /* * We're in domain level security, and the code that @@ -1912,7 +1913,9 @@ static void timeout_processing(int *select_timeout, * First, open the machine password file with an exclusive lock. */ - if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { + lock = secrets_get_trust_account_lock(NULL, lp_workgroup()); + + if (lock == NULL) { DEBUG(0,("process: unable to lock the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); return; @@ -1921,7 +1924,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) { DEBUG(0,("process: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup())); - secrets_lock_trust_account_password(lp_workgroup(), False); + TALLOC_FREE(lock); return; } @@ -1931,7 +1934,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); if(t < lct + lp_machine_password_timeout()) { global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); + TALLOC_FREE(lock); return; } @@ -1939,7 +1942,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); change_trust_account_password( lp_workgroup(), NULL); global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); + TALLOC_FREE(lock); } /* update printer queue caches if necessary */ -- cgit From 67536eddc34e225562e31e500cf64c03d63ad1cc Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Mar 2008 02:02:27 +0100 Subject: registry shares: prevent creating regular share called "global". This is a first quick fix. Registry shares should be rewritten to use libnet_conf. Michael (This used to be commit 71bd0bd0ea018e8c5033bbf904333c596330855a) --- source3/smbd/service.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a8aa25405a..8b73f68364 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -235,6 +235,10 @@ static int load_registry_service(const char *servicename) return -1; } + if (strequal(servicename, GLOBAL_NAME)) { + return -2; + } + if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) { return -1; } -- cgit From 380fcfa60047e0f886ce9fdf35f304427891a7d8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2008 12:37:01 -0700 Subject: Fix S3 to pass the test_raw_oplock_exclusive3 test. Jeremy. (This used to be commit 028302fac53083d66c969b876db1d831e53b8e35) --- source3/smbd/open.c | 5 +++-- source3/smbd/trans2.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cc78503379..0cc48c4f1c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1366,7 +1366,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, se_map_generic(&access_mask, &file_generic_mapping); open_access_mask = access_mask; - if (flags2 & O_TRUNC) { + if ((flags2 & O_TRUNC) || (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) { open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ } @@ -1378,7 +1378,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * mean the same thing under DOS and Unix. */ - if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { + if ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) || + (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) { /* DENY_DOS opens are always underlying read-write on the file handle, no matter what the requested access mask says. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 008ffed5a1..716f94f661 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4930,7 +4930,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, } status = open_file_ntcreate(conn, req, fname, psbuf, - FILE_WRITE_DATA, + FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, -- cgit From bac7b5b19e1c9a21a8de6b7b09cd4b06faf43f09 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2008 13:27:33 -0700 Subject: Try and fix bug #5315, as well as S4 torture tests RAW-OPLOCK BATCH19, BATCH20 and RAW-RENAME. Jeremy. (This used to be commit 9065792d4bc42522f12f9732de3c0ad82c72a2d3) --- source3/smbd/nttrans.c | 5 +++-- source3/smbd/reply.c | 15 ++++++++------- source3/smbd/trans2.c | 3 ++- 3 files changed, 13 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5293ca5347..f67ddd3b31 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1353,7 +1353,7 @@ void reply_ntrename(struct smb_request *req) case RENAME_FLAG_RENAME: status = rename_internals(ctx, conn, req, oldname, newname, attrs, False, src_has_wcard, - dest_has_wcard); + dest_has_wcard, DELETE_ACCESS); break; case RENAME_FLAG_HARD_LINK: if (src_has_wcard || dest_has_wcard) { @@ -1549,7 +1549,8 @@ static void call_nt_transact_rename(connection_struct *conn, 0, replace_if_exists, False, - dest_has_wcard); + dest_has_wcard, + DELETE_ACCESS); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 818ff319e4..d3b5dfac64 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2184,7 +2184,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, return NT_STATUS_OK; } - if (fsp->access_mask & DELETE_ACCESS) { + if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) { return NT_STATUS_OK; } @@ -5585,7 +5585,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, uint32 attrs, bool replace_if_exists, bool src_has_wild, - bool dest_has_wild) + bool dest_has_wild, + uint32_t access_mask) { char *directory = NULL; char *mask = NULL; @@ -5715,12 +5716,12 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, status = S_ISDIR(sbuf1.st_mode) ? open_directory(conn, req, directory, &sbuf1, - DELETE_ACCESS, + access_mask, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, NULL, &fsp) : open_file_ntcreate(conn, req, directory, &sbuf1, - DELETE_ACCESS, + access_mask, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, 0, NULL, &fsp); @@ -5819,12 +5820,12 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, status = S_ISDIR(sbuf1.st_mode) ? open_directory(conn, req, fname, &sbuf1, - DELETE_ACCESS, + access_mask, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, NULL, &fsp) : open_file_ntcreate(conn, req, fname, &sbuf1, - DELETE_ACCESS, + access_mask, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, 0, NULL, &fsp); @@ -5947,7 +5948,7 @@ void reply_mv(struct smb_request *req) DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); status = rename_internals(ctx, conn, req, name, newname, attrs, False, - src_has_wcard, dest_has_wcard); + src_has_wcard, dest_has_wcard, DELETE_ACCESS); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 716f94f661..85a7cdb613 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5322,7 +5322,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", fname, base_name )); status = rename_internals(ctx, conn, req, fname, base_name, 0, - overwrite, False, dest_has_wcard); + overwrite, False, dest_has_wcard, + FILE_WRITE_ATTRIBUTES); } return status; -- cgit From b7a014a6ee1d71beae14a0f90460aa5fdfb5d07c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2008 13:38:25 -0700 Subject: Allow us to pass RAW-RENAME by testing that the connection struct connection paths are equal, not just the conn structs themselves. Jeremy. (This used to be commit 632f3fe66fbcbe3cc25d070c3885177264f5ad65) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d3b5dfac64..91d5f25a27 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5295,7 +5295,7 @@ static void rename_open_files(connection_struct *conn, sharepaths we need to manipulate relative paths. */ /* TODO - create the absolute path and manipulate the newname relative to the sharepath. */ - if (fsp->conn != conn) { + if (!strequal(fsp->conn->connectpath, conn->connectpath)) { continue; } DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n", -- cgit From 792c9725388a8d1fd91df49f520705fcc7ffcea1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2008 13:59:04 -0700 Subject: Metze pointed out this we don't need FILE_ATTRIBUTE_READ here. Jeremy. (This used to be commit 923aa9f330cb370221af6b66cf0f237a9bd06f8e) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 85a7cdb613..d7a0f6eff8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4930,7 +4930,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, } status = open_file_ntcreate(conn, req, fname, psbuf, - FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES, + FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, -- cgit From 7d2c9c67fd5e4ebcedc5774fb8a24bee985b8fc8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2008 15:26:02 -0700 Subject: Using Metze's S4 nttrans rename test, the nttrans rename behaves the same as the trans2 one. Jeremy. (This used to be commit c4fa4917dad97c5047f7336c6675739b44da256b) --- source3/smbd/nttrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f67ddd3b31..bc93d19af3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1550,7 +1550,7 @@ static void call_nt_transact_rename(connection_struct *conn, replace_if_exists, False, dest_has_wcard, - DELETE_ACCESS); + FILE_WRITE_ATTRIBUTES); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { -- cgit From 6476313b6d4ad8b33e63f8b7bf9bf6a7384d23ec Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 12 Mar 2008 02:07:37 +0100 Subject: Add a debug message. Michael (This used to be commit a39807044879ad9df7614e010db6ea16b51000a0) --- source3/smbd/service.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8b73f68364..33b2cb26c1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -295,6 +295,7 @@ void load_registry_shares(void) WERROR err; int i; + DEBUG(8, ("load_registry_shares()\n")); if (!lp_registry_shares()) { return; } -- cgit From e06aa46b9fab1e107fea8f6453fb13deffa91e96 Mon Sep 17 00:00:00 2001 From: Marc VanHeyningen Date: Fri, 14 Mar 2008 14:26:28 -0800 Subject: Coverity fixes (This used to be commit 3fc85d22590550f0539215d020e4411bf5b14363) --- source3/smbd/notify.c | 2 +- source3/smbd/uid.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 55009ce0b1..ffdf1c22e7 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -169,7 +169,7 @@ void change_notify_reply(connection_struct *conn, return; } - prs_init(&ps, 0, NULL, MARSHALL); + prs_init_empty(&ps, NULL, MARSHALL); if (!notify_marshall_changes(notify_buf->num_changes, max_param, notify_buf->changes, &ps)) { diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index dceea450e6..1a3b7383c9 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -387,7 +387,12 @@ static void pop_conn_ctx(void) void become_root(void) { - push_sec_ctx(); + /* + * no good way to handle push_sec_ctx() failing without changing + * the prototype of become_root() + */ + if (!push_sec_ctx()) + return; push_conn_ctx(); set_root_sec_ctx(); } -- cgit From c5356479c1953b15fee8097d5d3436204fc7a4ce Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Mar 2008 21:00:16 +0100 Subject: Some simplifications (This used to be commit b59b436997fba47afd02ffb6f1194dfaef229d44) --- source3/smbd/uid.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 1a3b7383c9..ffa643a8f5 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -391,8 +391,9 @@ void become_root(void) * no good way to handle push_sec_ctx() failing without changing * the prototype of become_root() */ - if (!push_sec_ctx()) - return; + if (!push_sec_ctx()) { + smb_panic("become_root: push_sec_ctx failed"); + } push_conn_ctx(); set_root_sec_ctx(); } -- cgit From f152fe2103750301b7f8b2cda06baeed19c800f7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Jun 2007 15:38:09 +1000 Subject: [samba-3-0-ctdb.tridge @ tridge@samba.org-20070602053809-kpw5kjkcyjs8yjbl] suppress that darn message (cherry picked from commit 542e46a21898f6fcc8a0aeb63925607a60e0b99f) (This used to be commit 5e8c624c9c9775f255632717e6898d5f190ba51b) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7bf11abfbd..50c84f9da9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -676,7 +676,7 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ continue; if (smbd_server_fd() == -1) { - DEBUG(0,("open_sockets_smbd: accept: %s\n", + DEBUG(2,("open_sockets_smbd: accept: %s\n", strerror(errno))); continue; } -- cgit From 3d2ec806937b3f8e3c30b4a32d4f97fed6dfdd74 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 20 Mar 2008 15:59:37 +0100 Subject: Port 3c1f1f0797e from 3-0-ctdb We need to inform ctdb about the client's TCP connection so that after a fail over ctdbd can trigger the client to reconnect very quickly (This used to be commit ddc989886deff173b8a2a2a753a896770efe7545) --- source3/smbd/server.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 50c84f9da9..179d480f43 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -59,6 +59,23 @@ int get_client_fd(void) return server_fd; } +int client_get_tcp_info(struct sockaddr_in *server, struct sockaddr_in *client) +{ + socklen_t length; + if (server_fd == -1) { + return -1; + } + length = sizeof(*server); + if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) { + return -1; + } + length = sizeof(*client); + if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) { + return -1; + } + return 0; +} + struct event_context *smbd_event_context(void) { static struct event_context *ctx; @@ -946,10 +963,8 @@ void exit_server_fault(void) /**************************************************************************** received when we should release a specific IP ****************************************************************************/ -static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data, - uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) +static void release_ip(const char *ip, void *priv) { - const char *ip = (const char *)data->data; char addr[INET6_ADDRSTRLEN]; if (strcmp(client_socket_addr(get_client_fd(),addr,sizeof(addr)), ip) == 0) { @@ -964,6 +979,11 @@ static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data } } +static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data, + uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) +{ + release_ip((char *)data->data, NULL); +} /**************************************************************************** Initialise connect, service and file structs. @@ -1378,6 +1398,40 @@ extern void build_options(bool screen); exit(1); } +#ifdef CLUSTER_SUPPORT + + if (lp_clustering()) { + /* + * We need to tell ctdb about our client's TCP + * connection, so that for failover ctdbd can send + * tickle acks, triggering a reconnection by the + * client. + */ + + struct sockaddr_in srv, clnt; + + if (client_get_tcp_info(&srv, &clnt) == 0) { + + NTSTATUS status; + + status = ctdbd_register_ips( + messaging_ctdbd_connection(), + &srv, &clnt, release_ip, NULL); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("ctdbd_register_ips failed: %s\n", + nt_errstr(status))); + } + } else + { + DEBUG(0,("Unable to get tcp info for " + "CTDB_CONTROL_TCP_CLIENT: %s\n", + strerror(errno))); + } + } + +#endif + TALLOC_FREE(frame); smbd_process(); -- cgit From be2fab1fefa5cc2f0b6d0f880215e09405e0bb29 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 20 Mar 2008 16:50:52 +0100 Subject: smbd: fix session setup with security = share. Broken by pstring removal in 9ed12bfc48fe7f9b1863a9dd88e881974083053c. Jeremy, please check. Thanks to Yannick Bergeron for noting this. Michael (This used to be commit 008c4bdbe5de064b4469fc1f7c7173290f35b3ef) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 5578dafd85..cf90c7183a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1533,7 +1533,7 @@ void reply_sesssetup_and_X(struct smb_request *req) if (doencrypt) { lm_resp = data_blob(p, passlen1); nt_resp = data_blob(p+passlen1, passlen2); - } else { + } else if (lp_security() != SEC_SHARE) { char *pass = NULL; bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS; -- cgit From 2c5c3a0ba980ab97450cb97e1e575b23898ccc1f Mon Sep 17 00:00:00 2001 From: Eric Cronin Date: Mon, 24 Mar 2008 12:33:04 -0700 Subject: Missing HAVE_UPDWTMPX check before using updwtmpx(). In 10.5 Mac OS X added enough utmpx support to make it past the first two preprocessor checks around line 390 of src/smbd/utmp.c and on to the utmpx block which uses updwtmpx(). Unfortunately, as ./configure correctly surmised, 10.5 doesn't have that. https://bugzilla.samba.org/show_bug.cgi?id=5184 (This used to be commit f19d1e3d93d0d9dfe80372c6c5635f1047f9aa88) --- source3/smbd/utmp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 5931b2b1d0..de6d707eaf 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -409,6 +409,10 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, bool claim) /* Odd. Have utmpx.h but no "getutmpx()". Drop to non-x stuff */ DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n")); utmp_nox_update(u, claim); +#elif !defined(HAVE_UPDWTMPX) + /* Have utmpx.h but no "updwtmpx()". Drop to non-x stuff */ + DEBUG(1,("utmp_update: have utmpx.h but no updwtmpx() function\n")); + utmp_nox_update(u, claim); #else char *uname = NULL; char *wname = NULL; -- cgit From 3c213a1f8d7da283a48574eabcd3f81b46ea7b74 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 27 Mar 2008 10:09:24 +0100 Subject: posix_acls: clarify loop condition code, removing unneeded counter variable. Coverity ID 545 falsely classified this as a NULL dereferencing bug. By putting the loop of walking the list of aces more naturely not using additional counters, it becomes much more obvious that it is not entered when dir_ace == NULL. The same modifications are done for the file_ace loop. Michael (This used to be commit 6dab6cf0647d7db01e5e472f8b5cf21395b7dbf0) --- source3/smbd/posix_acls.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f60329a039..c3c9d2e60c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2882,7 +2882,6 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, { canon_ace *ace; enum security_ace_type nt_acl_type; - int i; if (nt4_compatible_acls() && dir_ace) { /* @@ -2948,9 +2947,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, * Create the NT ACE list from the canonical ace lists. */ - ace = file_ace; - - for (i = 0; i < num_acls; i++, ace = ace->next) { + for (ace = file_ace; ace != NULL; ace = ace->next) { SEC_ACCESS acc; acc = map_canon_ace_perms(SNUM(conn), @@ -2977,9 +2974,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, acc, 0); } - ace = dir_ace; - - for (i = 0; i < num_def_acls; i++, ace = ace->next) { + for (ace = dir_ace; ace != NULL; ace = ace->next) { SEC_ACCESS acc; acc = map_canon_ace_perms(SNUM(conn), -- cgit From 7752494cf199d6edcce021baa81f2148e3c7ba4d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Mar 2008 16:08:39 -0700 Subject: Fix up the comments on security=share to explain we're ignoring passwords. Jeremy. (This used to be commit e7b6ea46532a26611dfd9d9e2727d52ba6a9cf50) --- source3/smbd/sesssetup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index cf90c7183a..e0739ef992 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1534,6 +1534,10 @@ void reply_sesssetup_and_X(struct smb_request *req) lm_resp = data_blob(p, passlen1); nt_resp = data_blob(p+passlen1, passlen2); } else if (lp_security() != SEC_SHARE) { + /* + * In share level we should ignore any passwords, so + * only read them if we're not. + */ char *pass = NULL; bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS; @@ -1636,7 +1640,7 @@ void reply_sesssetup_and_X(struct smb_request *req) reload_services(True); if (lp_security() == SEC_SHARE) { - /* in share level we should ignore any passwords */ + /* In share level we should ignore any passwords */ data_blob_free(&lm_resp); data_blob_free(&nt_resp); -- cgit From afa682943c1799f02b6a86f8f872fd2ce2d62da5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 26 Mar 2008 18:33:38 +0100 Subject: printclose has only 1 vwv (This used to be commit 99d980125054cbfef8ec85a31e83aa18a6e0bce3) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 91d5f25a27..bababfecac 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4622,7 +4622,7 @@ void reply_printclose(struct smb_request *req) START_PROFILE(SMBsplclose); - if (req->wct < 3) { + if (req->wct < 1) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBsplclose); return; -- cgit From 9644b6cb50ec01c04a0d6ab17a8e39054fd8b0f8 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 28 Mar 2008 15:49:13 +0100 Subject: Add a talloc context parameter to current_timestring() to fix memleaks. current_timestring used to return a string talloced to talloc_tos(). When called by DEBUG from a TALLOC_FREE, this produced messages "no talloc stackframe around, leaking memory". For example when used from net conf. This also adds a temporary talloc context to alloc_sub_basic(). For this purpose, the exit strategy is slightly altered: a common exit point is used for success and failure. Michael (This used to be commit 16b5800d4e3a8b88bac67b2550d14e0aaaa302a9) --- source3/smbd/change_trust_pw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index fc58e97ea7..4773eeff86 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -90,7 +90,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m failed: if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", - current_timestring(False), domain)); + current_timestring(debug_ctx(), False), domain)); } else DEBUG(5,("change_trust_account_password: sucess!\n")); -- cgit From e00bfc509219cce65168f9ef4532eeff09e6f5fb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Mar 2008 17:31:06 -0700 Subject: Only allow sendfile on non-stream fsp's. Should fix make test for streams as sendfile isn't implemented in the streams vfs modules yet. Jeremy. (This used to be commit eef53e9603d4f3d892ffe00b061def5d717ca481) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bababfecac..eb8e5ff915 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2656,7 +2656,7 @@ void send_file_readbraw(connection_struct *conn, * reply_readbraw has already checked the length. */ - if ( (chain_size == 0) && (nread > 0) && + if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) { char header[4]; DATA_BLOB header_blob; @@ -3131,7 +3131,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, */ if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) && - !is_encrypted_packet(req->inbuf) && + !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) && lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { uint8 headerbuf[smb_size + 12 * 2]; DATA_BLOB header; -- cgit From 43fdd1748c8e7d0432f5f960687df74870df60de Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Mar 2008 17:32:52 -0700 Subject: Fix missing '&&'. Jeremy. (This used to be commit 251df53811e4272b629575a4b50c29a99715ccf9) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index eb8e5ff915..972f30dbbd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2656,7 +2656,7 @@ void send_file_readbraw(connection_struct *conn, * reply_readbraw has already checked the length. */ - if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) + if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) && (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) { char header[4]; DATA_BLOB header_blob; -- cgit From e11cd466e1b6beae82fa0117c300669b8eff7f0a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Mar 2008 16:46:20 -0700 Subject: Reduce the race condition in Samba4 in RAW-RENAME test. We rename a file using trans2 setfileinfo on one connection, and then check the file name has changed on the other. In Samba we achieve this by sending a local message to the other process. This change causes us to re-scan for incoming messages after we've woken up from the select (which is cheap if there are no pending messages). This reduces the race significantly. Volker please review. Jeremy. (This used to be commit a7499e994aef743ea9c443f9a1618b262f6eda93) --- source3/smbd/process.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9c01bbaa4a..03216a0700 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -853,6 +853,15 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, goto again; } + /* + * We've just woken up from a protentially long select sleep. + * Ensure we process local messages as we need to synchronously + * process any messages from other smbd's to avoid file rename race + * conditions. This call is cheap if there are no messages waiting. + * JRA. + */ + message_dispatch(smbd_messaging_context()); + /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but is the best we can do until the oplock code knows more about -- cgit From 6913f1013456be8938bb71b3d8968170e50933e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Mar 2008 16:56:21 -0700 Subject: Move the message_dispatch() call after the check for errno on the select return. We don't want the call to message_dispatch to mess up the errno value. Jeremy. (This used to be commit 26a74d01bb2b53ffa5d296ff1c7d8b2b0d17831a) --- source3/smbd/process.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 03216a0700..9aa775d0f6 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -853,15 +853,6 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, goto again; } - /* - * We've just woken up from a protentially long select sleep. - * Ensure we process local messages as we need to synchronously - * process any messages from other smbd's to avoid file rename race - * conditions. This call is cheap if there are no messages waiting. - * JRA. - */ - message_dispatch(smbd_messaging_context()); - /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but is the best we can do until the oplock code knows more about @@ -880,8 +871,17 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ return map_nt_error_from_unix(errno); - } - + } + + /* + * We've just woken up from a protentially long select sleep. + * Ensure we process local messages as we need to synchronously + * process any messages from other smbd's to avoid file rename race + * conditions. This call is cheap if there are no messages waiting. + * JRA. + */ + message_dispatch(smbd_messaging_context()); + /* Did we timeout ? */ if (selrtn == 0) { return NT_STATUS_IO_TIMEOUT; -- cgit From 8b04a3350092bf482e4b1c3339ccf95449848bf7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Mar 2008 17:01:27 -0700 Subject: Ok, final move of this code :-). I think I've found the correct place for it now where it will cause minimal disruption (only call the extra message_dispatch just before reading the next smb off the wire). Jeremy. (This used to be commit da2c19c481d0041872b4ce2f5105052077f3d3b8) --- source3/smbd/process.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9aa775d0f6..88684315cc 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -873,15 +873,6 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, return map_nt_error_from_unix(errno); } - /* - * We've just woken up from a protentially long select sleep. - * Ensure we process local messages as we need to synchronously - * process any messages from other smbd's to avoid file rename race - * conditions. This call is cheap if there are no messages waiting. - * JRA. - */ - message_dispatch(smbd_messaging_context()); - /* Did we timeout ? */ if (selrtn == 0) { return NT_STATUS_IO_TIMEOUT; @@ -903,6 +894,15 @@ static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, goto again; } + /* + * We've just woken up from a protentially long select sleep. + * Ensure we process local messages as we need to synchronously + * process any messages from other smbd's to avoid file rename race + * conditions. This call is cheap if there are no messages waiting. + * JRA. + */ + message_dispatch(smbd_messaging_context()); + status = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, p_unread, p_encrypted, &len); -- cgit From dc83b956b9600b4577983e327745445b35f481c0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Apr 2008 12:29:12 +0200 Subject: smbd: ignore nttrans renames as w2k3 does This lets us pass the RAW-RENAME test. metze Signed-off-by: Michael Adam (This used to be commit 2d50a1fef022023588e9963131951f8f3e4c7c23) --- source3/smbd/nttrans.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bc93d19af3..60e546450b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1518,7 +1518,6 @@ static void call_nt_transact_rename(connection_struct *conn, char *params = *ppparams; char *new_name = NULL; files_struct *fsp = NULL; - bool replace_if_exists = False; bool dest_has_wcard = False; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); @@ -1529,7 +1528,6 @@ static void call_nt_transact_rename(connection_struct *conn, } fsp = file_fsp(SVAL(params, 0)); - replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; if (!check_fsp(conn, req, fsp, ¤t_user)) { return; } @@ -1541,32 +1539,13 @@ static void call_nt_transact_rename(connection_struct *conn, return; } - status = rename_internals(ctx, - conn, - req, - fsp->fsp_name, - new_name, - 0, - replace_if_exists, - False, - dest_has_wcard, - FILE_WRITE_ATTRIBUTES); - - if (!NT_STATUS_IS_OK(status)) { - if (open_was_deferred(req->mid)) { - /* We have re-scheduled this call. */ - return; - } - reply_nterror(req, status); - return; - } - /* - * Rename was successful. + * W2K3 ignores this request as the RAW-RENAME test + * demonstrates, so we do. */ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); - DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", + DEBUG(3,("nt transact rename from = %s, to = %s ignored!\n", fsp->fsp_name, new_name)); return; -- cgit From 5b07337cc5e853d0f02554593f4eb842191d67e5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Apr 2008 18:18:38 +0200 Subject: smbd: always close the base_fsp even if the real close returned an error Otherwise we may end up with share mode entry without an open file. Volker, Jeremy: please check... metze (This used to be commit 547eacf6058d2bc5b41b266b70f8f4747aca4eae) --- source3/smbd/close.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4bd23a35fc..b06c0d1e9c 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -665,10 +665,6 @@ NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type) status = close_normal_file(fsp, close_type); } - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) { /* -- cgit From 3ebb6be00d88aeb27cfe7d2cc931b14d4993a94b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Apr 2008 11:23:36 -0700 Subject: Fix MSDFS bug noticed by Ofir Azoulay . There is no reason to ensure the target host is ourselves, and this breaks MS clients in some cases. Jeremy. (This used to be commit c19fdf43d16ce9fba3e8e12e6192bac31837715e) --- source3/smbd/msdfs.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 8ffa0f7751..fb757a5f74 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -127,28 +127,6 @@ static NTSTATUS parse_dfs_path(const char *pathname, DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); - /* If we got a hostname, is it ours (or an IP address) ? */ - if (!is_myname_or_ipaddr(pdp->hostname)) { - /* Repair path. */ - *p = sepchar; - DEBUG(10,("parse_dfs_path: hostname %s isn't ours. " - "Try local path from path %s\n", - pdp->hostname, temp)); - /* - * Possibly client sent a local path by mistake. - * Try and convert to a local path. - */ - - pdp->hostname = eos_ptr; /* "" */ - pdp->servicename = eos_ptr; /* "" */ - - p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s " - "to a local path\n", - temp)); - goto local_path; - } - /* Parse out servicename. */ temp = p+1; p = strchr_m(temp,sepchar); @@ -751,14 +729,6 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return status; } - /* Verify hostname in path */ - if (!is_myname_or_ipaddr(pdp->hostname)) { - DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - pdp->hostname, dfs_path)); - TALLOC_FREE(pdp); - return NT_STATUS_NOT_FOUND; - } - jucn->service_name = talloc_strdup(ctx, pdp->servicename); jucn->volume_name = talloc_strdup(ctx, pdp->reqpath); if (!jucn->service_name || !jucn->volume_name) { -- cgit From 2ccf50256e31bd7b9da0f7a7c223bebca5bca062 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Mar 2008 15:32:47 +0100 Subject: locking: store the write time in the locking.tdb This is needed to implement the strange write time update logic later. We need to store 2 time timestamps to distinguish between the time the file system had before the first client opened the file and a forced timestamp update. metze (This used to be commit 6aaa2ce0eeb46f6735ec984a2e7aadde7a7f456d) --- source3/smbd/close.c | 6 ++++-- source3/smbd/open.c | 15 ++++++++++----- source3/smbd/oplock.c | 9 ++++++--- source3/smbd/reply.c | 3 ++- source3/smbd/trans2.c | 3 ++- 5 files changed, 24 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index b06c0d1e9c..8a5c82cc93 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -246,7 +246,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, * This prevents race conditions with the file being created. JRA. */ - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0, ("close_remove_share_mode: Could not get share mode " @@ -535,7 +536,8 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty * reference to a directory also. */ - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0cc48c4f1c..f3ed234c87 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1221,7 +1221,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, request_time = pml->request_time; /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1450,11 +1451,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { + struct timespec old_write_time = get_mtimespec(psbuf); id = vfs_file_id_from_sbuf(conn, psbuf); lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname); + fname, &old_write_time); if (lck == NULL) { file_free(fsp); @@ -1661,7 +1663,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (!file_existed) { - + struct timespec old_write_time = get_mtimespec(psbuf); /* * Deal with the race condition where two smbd's detect the * file doesn't exist and do the create at the same time. One @@ -1681,7 +1683,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname); + fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share " @@ -2095,6 +2097,7 @@ NTSTATUS open_directory(connection_struct *conn, bool dir_existed = VALID_STAT(*psbuf) ? True : False; struct share_mode_lock *lck = NULL; NTSTATUS status; + struct timespec mtimespec; int info = 0; DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " @@ -2217,9 +2220,11 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); + mtimespec = get_mtimespec(psbuf); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, conn->connectpath, - fname); + fname, &mtimespec); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 420aa94fe6..c3409547fe 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -181,7 +181,8 @@ bool remove_oplock(files_struct *fsp) struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -206,7 +207,8 @@ bool downgrade_oplock(files_struct *fsp) bool ret; struct share_mode_lock *lck; - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -757,7 +759,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " "share mode entry for file %s.\n", fsp->fsp_name )); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 972f30dbbd..b300c09f4f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5515,7 +5515,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); /* * We have the file open ourselves, so not being able to get the diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d7a0f6eff8..308ba271b8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6431,7 +6431,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, * non-POSIX opens return SHARING_VIOLATION. */ - lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0, ("smb_posix_unlink: Could not get share mode " "lock for file %s\n", fsp->fsp_name)); -- cgit From d03453864ab1bc5fd3b4a3abaf96176a006c102b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Mar 2008 15:39:38 +0100 Subject: smbd: implement the strange write time update logic We now never call file_ntimes() directly, every update is done via smb_set_file_time(). This let samba3 pass the BASE-DELAYWRITE test. The write time is only updated 2 seconds after the first write() on any open handle to the current time (not the time of the first write). Each handle which had write requests updates the write time to the current time on close(). If the write time is set explicit via setfileinfo or setpathinfo the write time is visible directly and a following close on the same handle doesn't update the write time. metze (This used to be commit 2eab212ea2e1bfd8fa716c2c89b2c042f7ba12ea) --- source3/smbd/close.c | 78 ++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/dir.c | 8 +++++ source3/smbd/dosmode.c | 42 ++++++++++++++++--------- source3/smbd/fileio.c | 60 ++++++++++++++++++++++------------- source3/smbd/files.c | 29 ++--------------- source3/smbd/nttrans.c | 2 +- source3/smbd/reply.c | 61 +++++++++++++++++++++++------------- source3/smbd/trans2.c | 85 ++++++++++++++++++++++++++------------------------ 8 files changed, 235 insertions(+), 130 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 8a5c82cc93..3afc037f69 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -255,6 +255,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, return NT_STATUS_INVALID_PARAMETER; } + if (fsp->write_time_forced) { + set_close_write_time(fsp, lck->changed_write_time); + } + if (!del_share_mode(lck, fsp)) { DEBUG(0, ("close_remove_share_mode: Could not delete share " "entry for file %s\n", fsp->fsp_name)); @@ -317,6 +321,11 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " "- deleting file.\n", fsp->fsp_name)); + /* + * Don't try to update the write time when we delete the file + */ + fsp->update_write_time_on_close = false; + if (!unix_token_equal(lck->delete_token, ¤t_user.ut)) { /* Become the user who requested the delete. */ @@ -428,6 +437,66 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, return status; } +void set_close_write_time(struct files_struct *fsp, struct timespec ts) +{ + DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts)))); + + if (null_timespec(ts)) { + return; + } + /* + * if the write time on close is explict set, then don't + * need to fix it up to the value in the locking db + */ + fsp->write_time_forced = false; + + fsp->update_write_time_on_close = true; + fsp->close_write_time = ts; +} + +static NTSTATUS update_write_time_on_close(struct files_struct *fsp) +{ + SMB_STRUCT_STAT sbuf; + struct timespec ts[2]; + NTSTATUS status; + + ZERO_STRUCT(sbuf); + ZERO_STRUCT(ts); + + if (!fsp->update_write_time_on_close) { + return NT_STATUS_OK; + } + + if (null_timespec(fsp->close_write_time)) { + fsp->close_write_time = timespec_current(); + } + + /* Ensure we have a valid stat struct for the source. */ + if (fsp->fh->fd != -1) { + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return map_nt_error_from_unix(errno); + } + } else { + if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) { + return map_nt_error_from_unix(errno); + } + } + + if (!VALID_STAT(sbuf)) { + /* if it doesn't seem to be a real file */ + return NT_STATUS_OK; + } + + ts[1] = fsp->close_write_time; + status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, + &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + /**************************************************************************** Close a file. @@ -442,6 +511,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ NTSTATUS saved_status1 = NT_STATUS_OK; NTSTATUS saved_status2 = NT_STATUS_OK; NTSTATUS saved_status3 = NT_STATUS_OK; + NTSTATUS saved_status4 = NT_STATUS_OK; connection_struct *conn = fsp->conn; if (fsp->aio_write_behind) { @@ -496,11 +566,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ * Ensure pending modtime is set after close. */ - if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) { - set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); - } else if (!null_timespec(fsp->last_write_time)) { - set_filetime(conn, fsp->fsp_name, fsp->last_write_time); - } + saved_status4 = update_write_time_on_close(fsp); if (NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(saved_status1)) { @@ -509,6 +575,8 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ status = saved_status2; } else if (!NT_STATUS_IS_OK(saved_status3)) { status = saved_status3; + } else if (!NT_STATUS_IS_OK(saved_status4)) { + status = saved_status4; } } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ca6f8bfd8d..8531d6250d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -841,6 +841,8 @@ bool get_dir_entry(TALLOC_CTX *ctx, mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { char mname[13]; + struct timespec write_time_ts; + struct file_id fileid; if (!mangle_is_8_3(filename, False, conn->params)) { if (!name_to_8_3(filename,mname,False, @@ -883,6 +885,12 @@ bool get_dir_entry(TALLOC_CTX *ctx, *size = sbuf.st_size; *date = sbuf.st_mtime; + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + write_time_ts = get_write_time(fileid); + if (!null_timespec(write_time_ts)) { + *date = convert_timespec_to_time_t(write_time_ts); + } + DEBUG(3,("get_dir_entry mask=[%s] found %s " "fname=%s (%s)\n", mask, diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index a2e617c117..0ac3873275 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -571,6 +571,11 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe errno = 0; ZERO_STRUCT(sbuf); + DEBUG(6, ("file_ntime: actime: %s", + time_to_asc(convert_timespec_to_time_t(ts[0])))); + DEBUG(6, ("file_ntime: modtime: %s", + time_to_asc(convert_timespec_to_time_t(ts[1])))); + /* Don't update the time on read-only shares */ /* We need this as set_filetime (which can be called on close and other paths) can end up calling this function @@ -615,26 +620,35 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -bool set_filetime(connection_struct *conn, const char *fname, - const struct timespec mtime) +bool set_write_time_path(connection_struct *conn, const char *fname, + struct file_id fileid, const struct timespec mtime, + bool overwrite) { - struct timespec ts[2]; - if (null_timespec(mtime)) { - return(True); + return true; } - ts[1] = mtime; /* mtime. */ - ts[0] = ts[1]; /* atime. */ - - if (file_ntimes(conn, fname, ts)) { - DEBUG(4,("set_filetime(%s) failed: %s\n", - fname,strerror(errno))); - return False; + if (!set_write_time(fileid, mtime, overwrite)) { + return false; } - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_LAST_WRITE, fname); + /* in the overwrite case the caller should trigger the notify */ + if (!overwrite) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_LAST_WRITE, fname); + } return true; } + +bool set_write_time_fsp(struct files_struct *fsp, const struct timespec mtime, + bool overwrite) +{ + if (overwrite) { + fsp->write_time_forced = true; + TALLOC_FREE(fsp->update_write_time_event); + } + + return set_write_time_path(fsp->conn, fsp->fsp_name, fsp->file_id, + mtime, overwrite); +} diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 8cea4989f5..93a303f6c8 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -142,27 +142,6 @@ static ssize_t real_write_file(struct smb_request *req, if (ret != -1) { fsp->fh->pos += ret; - /* - * It turns out that setting the last write time from a Windows - * client stops any subsequent writes from updating the write time. - * Doing this after the write gives a race condition here where - * a stat may see the changed write time before we reset it here, - * but it's cheaper than having to store the write time in shared - * memory and look it up using dev/inode across all running smbd's. - * The 99% solution will hopefully be good enough in this case. JRA. - */ - - if (!null_timespec(fsp->pending_modtime)) { - set_filetime(fsp->conn, fsp->fsp_name, - fsp->pending_modtime); - - /* If we didn't get the "set modtime" call ourselves, we must - store the last write time to restore on close. JRA. */ - if (!fsp->pending_modtime_owner) { - fsp->last_write_time = timespec_current(); - } - } - /* Yes - this is correct - writes don't update this. JRA. */ /* Found by Samba4 tests. */ #if 0 @@ -192,6 +171,41 @@ static int wcp_file_size_change(files_struct *fsp) return ret; } +static void update_write_time_handler(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + files_struct *fsp = (files_struct *)private_data; + + /* Remove the timed event handler. */ + TALLOC_FREE(fsp->update_write_time_event); + DEBUG(5, ("Update write time on %s\n", fsp->fsp_name)); + + /* change the write time if not already changed by someoneelse */ + set_write_time_fsp(fsp, timespec_current(), false); +} + +void trigger_write_time_update(struct files_struct *fsp) +{ + if (fsp->write_time_forced) { + return; + } + + if (fsp->update_write_time_triggered) { + return; + } + fsp->update_write_time_triggered = true; + + /* trigger the update 2 seconds later */ + fsp->update_write_time_on_close = true; + fsp->update_write_time_event = + event_add_timed(smbd_event_context(), NULL, + timeval_current_ofs(2, 0), + "update_write_time_handler", + update_write_time_handler, fsp); +} + /**************************************************************************** Write to a file. ****************************************************************************/ @@ -230,7 +244,9 @@ ssize_t write_file(struct smb_request *req, fsp->modified = True; if (SMB_VFS_FSTAT(fsp, &st) == 0) { - int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); + int dosmode; + trigger_write_time_update(fsp); + dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 95f01b88ce..d6e91c67be 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -374,29 +374,6 @@ files_struct *file_find_print(void) return NULL; } -/**************************************************************************** - Set a pending modtime across all files with a given dev/ino pair. - Record the owner of that modtime. -****************************************************************************/ - -void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod) -{ - files_struct *fsp; - - if (null_timespec(mod)) { - return; - } - - for (fsp = Files;fsp;fsp=fsp->next) { - if ( fsp->fh->fd != -1 && file_id_equal(&fsp->file_id, &tfsp->file_id)) { - fsp->pending_modtime = mod; - fsp->pending_modtime_owner = False; - } - } - - tfsp->pending_modtime_owner = True; -} - /**************************************************************************** Sync open files on a connection. ****************************************************************************/ @@ -441,6 +418,9 @@ void file_free(files_struct *fsp) /* Ensure this event will never fire. */ TALLOC_FREE(fsp->oplock_timeout); + /* Ensure this event will never fire. */ + TALLOC_FREE(fsp->update_write_time_event); + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; @@ -548,9 +528,6 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->open_time = fsp->open_time; dup_fsp->access_mask = access_mask; dup_fsp->share_access = share_access; - dup_fsp->pending_modtime_owner = fsp->pending_modtime_owner; - dup_fsp->pending_modtime = fsp->pending_modtime; - dup_fsp->last_write_time = fsp->last_write_time; dup_fsp->oplock_type = fsp->oplock_type; dup_fsp->can_lock = fsp->can_lock; dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 60e546450b..05c0957e4f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1233,7 +1233,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1)); + set_close_write_time(fsp2, get_mtimespec(&sbuf1)); status = close_file(fsp2,NORMAL_CLOSE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b300c09f4f..411eb98ac5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1042,6 +1042,7 @@ void reply_getatr(struct smb_request *req) void reply_setatr(struct smb_request *req) { + struct timespec ts[2]; connection_struct *conn = req->conn; char *fname = NULL; int mode; @@ -1053,6 +1054,8 @@ void reply_setatr(struct smb_request *req) START_PROFILE(SMBsetatr); + ZERO_STRUCT(ts); + if (req->wct < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; @@ -1110,7 +1113,10 @@ void reply_setatr(struct smb_request *req) mode = SVAL(req->inbuf,smb_vwv0); mtime = srv_make_unix_date3(req->inbuf+smb_vwv1); - if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) { + ts[1] = convert_time_t_to_timespec(mtime); + status = smb_set_file_time(conn, NULL, fname, + &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetatr); return; @@ -1985,7 +1991,12 @@ void reply_mknew(struct smb_request *req) } ts[0] = get_atimespec(&sbuf); /* atime. */ - file_ntimes(conn, fsp->fsp_name, ts); + status = smb_set_file_time(conn, fsp, fname, &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcreate); + reply_openerror(req, status); + return; + } reply_outbuf(req, 1, 0); SSVAL(req->outbuf,smb_vwv0,fsp->fnum); @@ -4239,6 +4250,7 @@ void reply_close(struct smb_request *req) DEBUG(3,("close directory fnum=%d\n", fsp->fnum)); status = close_file(fsp,NORMAL_CLOSE); } else { + time_t t; /* * Close ordinary file. */ @@ -4251,9 +4263,8 @@ void reply_close(struct smb_request *req) * Take care of any time sent in the close. */ - fsp_set_pending_modtime(fsp, convert_time_t_to_timespec( - srv_make_unix_date3( - req->inbuf+smb_vwv1))); + t = srv_make_unix_date3(req->inbuf+smb_vwv1); + set_close_write_time(fsp, convert_time_t_to_timespec(t)); /* * close_file() returns the unix errno if an error @@ -4326,8 +4337,8 @@ void reply_writeclose(struct smb_request *req) nwritten = write_file(req,fsp,data,startpos,numtowrite); - set_filetime(conn, fsp->fsp_name, mtime); - + set_close_write_time(fsp, mtime); + /* * More insanity. W2K only closes the file if writelen > 0. * JRA. @@ -6078,7 +6089,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf)); + set_close_write_time(fsp2, get_mtimespec(&src_sbuf)); /* * As we are opening fsp1 read-only we only expect @@ -6961,6 +6972,8 @@ void reply_setattrE(struct smb_request *req) connection_struct *conn = req->conn; struct timespec ts[2]; files_struct *fsp; + SMB_STRUCT_STAT sbuf; + NTSTATUS status; START_PROFILE(SMBsetattrE); @@ -6996,23 +7009,27 @@ void reply_setattrE(struct smb_request *req) * Sometimes times are sent as zero - ignore them. */ - if (null_timespec(ts[0]) && null_timespec(ts[1])) { - /* Ignore request */ - if( DEBUGLVL( 3 ) ) { - dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); - dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); + /* Ensure we have a valid stat struct for the source. */ + if (fsp->fh->fd != -1) { + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + status = map_nt_error_from_unix(errno); + reply_nterror(req, status); + END_PROFILE(SMBsetattrE); + return; + } + } else { + if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) { + status = map_nt_error_from_unix(errno); + reply_nterror(req, status) + END_PROFILE(SMBsetattrE); + return; } - END_PROFILE(SMBsetattrE); - return; - } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) { - /* set modify time = to access time if modify time was unset */ - ts[1] = ts[0]; } - /* Set the date on this file */ - /* Should we set pending modtime here ? JRA */ - if(file_ntimes(conn, fsp->fsp_name, ts)) { - reply_doserror(req, ERRDOS, ERRnoaccess); + status = smb_set_file_time(conn, fsp, fsp->fsp_name, + &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { + reply_doserror(req, ERRDOS, ERRnoaccess) END_PROFILE(SMBsetattrE); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 308ba271b8..06bb31622f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1238,6 +1238,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); bool check_mangled_names = lp_manglednames(conn->params); char mangled_name[13]; /* mangled 8.3 name. */ + struct timespec write_time_ts; *out_of_space = False; *got_exact_match = False; @@ -1397,6 +1398,12 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, adate_ts = get_atimespec(&sbuf); create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + write_time_ts = get_write_time( + vfs_file_id_from_sbuf(conn, &sbuf)); + if (!null_timespec(write_time_ts)) { + mdate_ts = write_time_ts; + } + if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_date_ts); dos_filetime_timespec(&mdate_ts); @@ -3784,6 +3791,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, int len; time_t create_time, mtime, atime; struct timespec create_time_ts, mtime_ts, atime_ts; + struct timespec write_time_ts; files_struct *fsp = NULL; struct file_id fileid; struct ea_list *ea_list = NULL; @@ -3797,6 +3805,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } ZERO_STRUCT(sbuf); + ZERO_STRUCT(write_time_ts); if (tran_call == TRANSACT2_QFILEINFO) { if (total_params < 4) { @@ -3862,6 +3871,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, fileid = vfs_file_id_from_sbuf(conn, &sbuf); delete_pending = get_delete_on_close_flag(fileid); + write_time_ts = get_write_time(fileid); } else { /* * Original code - this is an open file. @@ -3878,6 +3888,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, pos = fsp->fh->position_information; fileid = vfs_file_id_from_sbuf(conn, &sbuf); delete_pending = get_delete_on_close_flag(fileid); + write_time_ts = get_write_time(fileid); access_mask = fsp->access_mask; } @@ -3953,6 +3964,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, reply_nterror(req, NT_STATUS_DELETE_PENDING); return; } + write_time_ts = get_write_time(fileid); } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { @@ -4073,25 +4085,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd allocation_size = get_allocation_size(conn,fsp,&sbuf); - if (fsp) { - if (!null_timespec(fsp->pending_modtime)) { - /* the pending modtime overrides the current modtime */ - mtime_ts = fsp->pending_modtime; - } - } else { - files_struct *fsp1; + if (!fsp) { /* Do we have this path open ? */ + files_struct *fsp1; fileid = vfs_file_id_from_sbuf(conn, &sbuf); fsp1 = file_find_di_first(fileid); - if (fsp1 && !null_timespec(fsp1->pending_modtime)) { - /* the pending modtime overrides the current modtime */ - mtime_ts = fsp1->pending_modtime; - } if (fsp1 && fsp1->initial_allocation_size) { allocation_size = get_allocation_size(conn, fsp1, &sbuf); } } + if (!null_timespec(write_time_ts)) { + mtime_ts = write_time_ts; + } + if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_time_ts); dos_filetime_timespec(&mtime_ts); @@ -4781,12 +4788,12 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, Deal with setting the time from any of the setfilepathinfo functions. ****************************************************************************/ -static NTSTATUS smb_set_file_time(connection_struct *conn, - files_struct *fsp, - const char *fname, - const SMB_STRUCT_STAT *psbuf, - struct timespec ts[2], - bool setting_write_time) +NTSTATUS smb_set_file_time(connection_struct *conn, + files_struct *fsp, + const char *fname, + const SMB_STRUCT_STAT *psbuf, + struct timespec ts[2], + bool setting_write_time) { uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS @@ -4828,7 +4835,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, } } - if(fsp != NULL) { + if (setting_write_time) { /* * This was a setfileinfo on an open file. * NT does this a lot. We also need to @@ -4839,13 +4846,18 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, * away and will set it on file close and after a write. JRA. */ - if (!null_timespec(ts[1])) { - DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", - time_to_asc(convert_timespec_to_time_t(ts[1])) )); - fsp_set_pending_modtime(fsp, ts[1]); - } + DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", + time_to_asc(convert_timespec_to_time_t(ts[1])) )); + if (fsp != NULL) { + set_write_time_fsp(fsp, ts[1], true); + } else { + set_write_time_path(conn, fname, + vfs_file_id_from_sbuf(conn, psbuf), + ts[1], true); + } } + DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); if(file_ntimes(conn, fname, ts)!=0) { @@ -5670,14 +5682,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, } } /* But always update the time. */ - if (null_timespec(fsp->pending_modtime)) { - /* - * This is equivalent to a write. Ensure it's seen immediately - * if there are no pending writes. - */ - set_filetime(fsp->conn, fsp->fsp_name, - timespec_current()); - } + /* + * This is equivalent to a write. Ensure it's seen immediately + * if there are no pending writes. + */ + trigger_write_time_update(fsp); return NT_STATUS_OK; } @@ -5707,10 +5716,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, } /* Changing the allocation size should set the last mod time. */ - /* Don't need to call set_filetime as this will be flushed on - * close. */ - - fsp_set_pending_modtime(new_fsp, timespec_current()); + /* + * This is equivalent to a write. Ensure it's seen immediately + * if there are no pending writes. + */ + trigger_write_time_update(new_fsp); close_file(new_fsp,NORMAL_CLOSE); return NT_STATUS_OK; @@ -6658,11 +6668,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn, SSVAL(params,0,0); - if (fsp && !null_timespec(fsp->pending_modtime)) { - /* the pending modtime overrides the current modtime */ - set_mtimespec(&sbuf, fsp->pending_modtime); - } - switch (info_level) { case SMB_INFO_STANDARD: -- cgit From 851cadba51b00b326c5f040f23f95932aec53105 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Apr 2008 11:40:23 +0200 Subject: locking: combine get_delete_on_close_flag() and get_write_time() into get_file_infos() This means we need to fetch the record only once. metze (This used to be commit 4130b873291d39e363184fe4e38dc1f24ebe5056) --- source3/smbd/dir.c | 2 +- source3/smbd/filename.c | 18 +++++++++++++----- source3/smbd/trans2.c | 13 +++++-------- 3 files changed, 19 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 8531d6250d..5fc2e3719e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -886,7 +886,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, *date = sbuf.st_mtime; fileid = vfs_file_id_from_sbuf(conn, &sbuf); - write_time_ts = get_write_time(fileid); + get_file_infos(fileid, NULL, &write_time_ts); if (!null_timespec(write_time_ts)) { *date = convert_timespec_to_time_t(write_time_ts); } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 10e9583049..4323e843d2 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -611,11 +611,19 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } /* end else */ #ifdef DEVELOPER - if (VALID_STAT(st) && - get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, - &st))) { - result = NT_STATUS_DELETE_PENDING; - goto fail; + /* + * This sucks! + * We should never provide different behaviors + * depending on DEVELOPER!!! + */ + if (VALID_STAT(st)) { + bool delete_pending; + get_file_infos(vfs_file_id_from_sbuf(conn, &st), + &delete_pending, NULL); + if (delete_pending) { + result = NT_STATUS_DELETE_PENDING; + goto fail; + } } #endif diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 06bb31622f..9e56434d5c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1398,8 +1398,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, adate_ts = get_atimespec(&sbuf); create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - write_time_ts = get_write_time( - vfs_file_id_from_sbuf(conn, &sbuf)); + get_file_infos(vfs_file_id_from_sbuf(conn, &sbuf), + NULL, &write_time_ts); if (!null_timespec(write_time_ts)) { mdate_ts = write_time_ts; } @@ -3870,8 +3870,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } fileid = vfs_file_id_from_sbuf(conn, &sbuf); - delete_pending = get_delete_on_close_flag(fileid); - write_time_ts = get_write_time(fileid); + get_file_infos(fileid, &delete_pending, &write_time_ts); } else { /* * Original code - this is an open file. @@ -3887,8 +3886,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } pos = fsp->fh->position_information; fileid = vfs_file_id_from_sbuf(conn, &sbuf); - delete_pending = get_delete_on_close_flag(fileid); - write_time_ts = get_write_time(fileid); + get_file_infos(fileid, &delete_pending, &write_time_ts); access_mask = fsp->access_mask; } @@ -3959,12 +3957,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } fileid = vfs_file_id_from_sbuf(conn, &sbuf); - delete_pending = get_delete_on_close_flag(fileid); + get_file_infos(fileid, &delete_pending, &write_time_ts); if (delete_pending) { reply_nterror(req, NT_STATUS_DELETE_PENDING); return; } - write_time_ts = get_write_time(fileid); } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { -- cgit From 19f49de92e176495f3e0640502d4a330eacbf59e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 7 Apr 2008 09:21:19 +0200 Subject: smbd: make it possible to disable get_file_infos() on searches metze (This used to be commit 404a865a34c3a7c67131b3f99e92c11b2abe3e39) --- source3/smbd/dir.c | 18 +++++++++++------- source3/smbd/reply.c | 13 +++++++++++-- source3/smbd/trans2.c | 19 ++++++++++++++----- 3 files changed, 36 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5fc2e3719e..6e02401e25 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -803,7 +803,8 @@ bool get_dir_entry(TALLOC_CTX *ctx, SMB_OFF_T *size, uint32 *mode, time_t *date, - bool check_descend) + bool check_descend, + bool ask_sharemode) { const char *dname = NULL; bool found = False; @@ -841,8 +842,6 @@ bool get_dir_entry(TALLOC_CTX *ctx, mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { char mname[13]; - struct timespec write_time_ts; - struct file_id fileid; if (!mangle_is_8_3(filename, False, conn->params)) { if (!name_to_8_3(filename,mname,False, @@ -885,10 +884,15 @@ bool get_dir_entry(TALLOC_CTX *ctx, *size = sbuf.st_size; *date = sbuf.st_mtime; - fileid = vfs_file_id_from_sbuf(conn, &sbuf); - get_file_infos(fileid, NULL, &write_time_ts); - if (!null_timespec(write_time_ts)) { - *date = convert_timespec_to_time_t(write_time_ts); + if (ask_sharemode) { + struct timespec write_time_ts; + struct file_id fileid; + + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + get_file_infos(fileid, NULL, &write_time_ts); + if (!null_timespec(write_time_ts)) { + *date = convert_timespec_to_time_t(write_time_ts); + } } DEBUG(3,("get_dir_entry mask=[%s] found %s " diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 411eb98ac5..ab77de06f8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1224,6 +1224,7 @@ void reply_search(struct smb_request *req) bool mask_contains_wcard = False; bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; TALLOC_CTX *ctx = talloc_tos(); + bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); START_PROFILE(SMBsearch); @@ -1409,8 +1410,16 @@ void reply_search(struct smb_request *req) } for (i=numentries;(idirpath[strlen(conn->dirpath) -1] != '/'); bool check_mangled_names = lp_manglednames(conn->params); char mangled_name[13]; /* mangled 8.3 name. */ - struct timespec write_time_ts; *out_of_space = False; *got_exact_match = False; @@ -1398,10 +1398,15 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, adate_ts = get_atimespec(&sbuf); create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - get_file_infos(vfs_file_id_from_sbuf(conn, &sbuf), - NULL, &write_time_ts); - if (!null_timespec(write_time_ts)) { - mdate_ts = write_time_ts; + if (ask_sharemode) { + struct timespec write_time_ts; + struct file_id fileid; + + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + get_file_infos(fileid, NULL, &write_time_ts); + if (!null_timespec(write_time_ts)) { + mdate_ts = write_time_ts; + } } if (lp_dos_filetime_resolution(SNUM(conn))) { @@ -1873,6 +1878,7 @@ static void call_trans2findfirst(connection_struct *conn, SMB_STRUCT_STAT sbuf; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; + bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); if (total_params < 13) { @@ -2069,6 +2075,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, + ask_sharemode, &p,pdata,data_end, space_remaining, &out_of_space, &got_exact_match, @@ -2205,6 +2212,7 @@ static void call_trans2findnext(connection_struct *conn, int space_remaining; struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; + bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); if (total_params < 13) { @@ -2413,6 +2421,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, + ask_sharemode, &p,pdata,data_end, space_remaining, &out_of_space, &got_exact_match, -- cgit From 206e7eeb6fb5491155ac4b54e13b7b81ae6c29a0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 7 Apr 2008 09:27:22 +0200 Subject: smbd: make it possible to change the write time delay for testing metze (This used to be commit df8c100c2b53575a0d425a2daf52e2d59904746a) --- source3/smbd/fileio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 93a303f6c8..64cea7f7ce 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -188,6 +188,8 @@ static void update_write_time_handler(struct event_context *ctx, void trigger_write_time_update(struct files_struct *fsp) { + int delay; + if (fsp->write_time_forced) { return; } @@ -197,11 +199,15 @@ void trigger_write_time_update(struct files_struct *fsp) } fsp->update_write_time_triggered = true; + delay = lp_parm_int(SNUM(fsp->conn), + "smbd", "writetimeupdatedelay", + WRITE_TIME_UPDATE_USEC_DELAY); + /* trigger the update 2 seconds later */ fsp->update_write_time_on_close = true; fsp->update_write_time_event = event_add_timed(smbd_event_context(), NULL, - timeval_current_ofs(2, 0), + timeval_current_ofs(0, delay), "update_write_time_handler", update_write_time_handler, fsp); } -- cgit From f700ee6418c7b861efdb0f8eaa61b99ad598b7c3 Mon Sep 17 00:00:00 2001 From: Bill Ricker Date: Mon, 7 Apr 2008 15:02:56 -0700 Subject: Fix Kerberos interop with Mac OS X 10.5 clients. Ignore optional req_flags. Use the Kerberos mechanism OID negotiated with the client rather than hardcoding OID_KERBEROS5_OLD. (This used to be commit 59a2bcf30fef14ecc826271862b645dd3a61cb48) --- source3/smbd/seal.c | 7 +++++-- source3/smbd/sesssetup.c | 49 +++++++++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index d4394e5bca..955ca471bc 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -484,10 +484,11 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, DATA_BLOB blob = data_blob_null; DATA_BLOB secblob = data_blob_null; bool got_kerberos_mechanism = false; + char *kerb_mech = NULL; blob = data_blob_const(*ppdata, *p_data_size); - status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); + status = parse_spnego_mechanisms(blob, &secblob, &kerb_mech); if (!NT_STATUS_IS_OK(status)) { return nt_status_squash(status); } @@ -496,7 +497,9 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, srv_free_encryption_context(&partial_srv_trans_enc_ctx); - if (got_kerberos_mechanism) { + if (kerb_mech) { + SAFE_FREE(kerb_mech); + #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); #else diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index e0739ef992..33a54dd0de 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -248,6 +248,7 @@ static bool make_krb5_skew_error(DATA_BLOB *pblob_out) static void reply_spnego_kerberos(struct smb_request *req, DATA_BLOB *secblob, + const char *mechOID, uint16 vuid, bool *p_invalidate_vuid) { @@ -598,7 +599,7 @@ static void reply_spnego_kerberos(struct smb_request *req, ap_rep_wrapped = data_blob_null; } response = spnego_gen_auth_response(&ap_rep_wrapped, ret, - OID_KERBEROS5_OLD); + mechOID); reply_sesssetup_blob(req, response, ret); data_blob_free(&ap_rep); @@ -709,13 +710,15 @@ static void reply_spnego_ntlmssp(struct smb_request *req, Is this a krb5 mechanism ? ****************************************************************************/ -NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, - bool *p_is_krb5) +NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, + DATA_BLOB *pblob_out, + char **kerb_mechOID) { char *OIDs[ASN1_MAX_OIDS]; int i; + NTSTATUS ret = NT_STATUS_OK; - *p_is_krb5 = False; + *kerb_mechOID = NULL; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) { @@ -735,7 +738,10 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, #ifdef HAVE_KRB5 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { - *p_is_krb5 = True; + *kerb_mechOID = SMB_STRDUP(OIDs[0]); + if (*kerb_mechOID == NULL) { + ret = NT_STATUS_NO_MEMORY; + } } #endif @@ -743,7 +749,7 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i])); free(OIDs[i]); } - return NT_STATUS_OK; + return ret; } /**************************************************************************** @@ -779,11 +785,10 @@ static void reply_spnego_negotiate(struct smb_request *req, { DATA_BLOB secblob; DATA_BLOB chal; - bool got_kerberos_mechanism = False; + char *kerb_mech = NULL; NTSTATUS status; - status = parse_spnego_mechanisms(blob1, &secblob, - &got_kerberos_mechanism); + status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); @@ -795,16 +800,17 @@ static void reply_spnego_negotiate(struct smb_request *req, (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || + if (kerb_mech && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { bool destroy_vuid = True; - reply_spnego_kerberos(req, &secblob, vuid, - &destroy_vuid); + reply_spnego_kerberos(req, &secblob, kerb_mech, + vuid, &destroy_vuid); data_blob_free(&secblob); if (destroy_vuid) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); } + SAFE_FREE(kerb_mech); return; } #endif @@ -813,12 +819,12 @@ static void reply_spnego_negotiate(struct smb_request *req, auth_ntlmssp_end(auth_ntlmssp_state); } - if (got_kerberos_mechanism) { + if (kerb_mech) { data_blob_free(&secblob); /* The mechtoken is a krb5 ticket, but * we need to fall back to NTLM. */ - reply_spnego_downgrade_to_ntlmssp(req, - vuid); + reply_spnego_downgrade_to_ntlmssp(req, vuid); + SAFE_FREE(kerb_mech); return; } @@ -872,10 +878,9 @@ static void reply_spnego_auth(struct smb_request *req, if (auth.data[0] == ASN1_APPLICATION(0)) { /* Might be a second negTokenTarg packet */ + char *kerb_mech = NULL; - bool got_krb5_mechanism = False; - status = parse_spnego_mechanisms(auth, &secblob, - &got_krb5_mechanism); + status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ @@ -887,10 +892,10 @@ static void reply_spnego_auth(struct smb_request *req, DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || + if (kerb_mech && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { bool destroy_vuid = True; - reply_spnego_kerberos(req, &secblob, + reply_spnego_kerberos(req, &secblob, kerb_mech, vuid, &destroy_vuid); data_blob_free(&secblob); data_blob_free(&auth); @@ -898,13 +903,14 @@ static void reply_spnego_auth(struct smb_request *req, /* Kill the intermediate vuid */ invalidate_vuid(vuid); } + SAFE_FREE(kerb_mech); return; } #endif /* Can't blunder into NTLMSSP auth if we have * a krb5 ticket. */ - if (got_krb5_mechanism) { + if (kerb_mech) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); DEBUG(3,("reply_spnego_auth: network " @@ -913,6 +919,7 @@ static void reply_spnego_auth(struct smb_request *req, "not enabled")); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); + SAFE_FREE(kerb_mech); } } -- cgit From f863cb2ef45a19e092d72b93427b5b3c4e0c0a42 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 7 Apr 2008 15:28:10 -0700 Subject: Remove unused variable. (This used to be commit 3ed2c65bde0c2e5ad10cf777dae8a2d3e626a42c) --- source3/smbd/seal.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 955ca471bc..e9dc46aa3c 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -483,7 +483,6 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, NTSTATUS status; DATA_BLOB blob = data_blob_null; DATA_BLOB secblob = data_blob_null; - bool got_kerberos_mechanism = false; char *kerb_mech = NULL; blob = data_blob_const(*ppdata, *p_data_size); -- cgit From 86e59c50f1c92c9dc8dd6ab35c5b5436c29151dc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Apr 2008 21:11:16 -0700 Subject: Rewrite the wrap checks to deal with gcc 4.x optimisations. Karolin, please pull once Volker has reviewed. Thanks. Jeremy. (This used to be commit 09852899cadc48abe2f2651ecbceaf881198e648) --- source3/smbd/ipc.c | 78 ++++++++++++++++++++++++------------------- source3/smbd/nttrans.c | 89 +++++++++++++++++++++++++++++--------------------- source3/smbd/trans2.c | 76 +++++++++++++++++++++++++----------------- 3 files changed, 142 insertions(+), 101 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 68a13d692f..6961a5caf1 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -498,7 +498,8 @@ void reply_trans(struct smb_request *req) unsigned int pscnt; struct trans_state *state; NTSTATUS result; - int size; + unsigned int size; + unsigned int av_size; START_PROFILE(SMBtrans); @@ -509,6 +510,7 @@ void reply_trans(struct smb_request *req) } size = smb_len(req->inbuf) + 4; + av_size = smb_len(req->inbuf); dsoff = SVAL(req->inbuf, smb_dsoff); dscnt = SVAL(req->inbuf, smb_dscnt); psoff = SVAL(req->inbuf, smb_psoff); @@ -567,12 +569,17 @@ void reply_trans(struct smb_request *req) } /* null-terminate the slack space */ memset(&state->data[state->total_data], 0, 100); - if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) + + if (dscnt > state->total_data || + dsoff+dscnt < dsoff) { goto bad_param; - if ((smb_base(req->inbuf)+dsoff+dscnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf))) + } + + if (dsoff > av_size || + dscnt > av_size || + dsoff+dscnt > av_size) { goto bad_param; + } memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } @@ -592,12 +599,17 @@ void reply_trans(struct smb_request *req) } /* null-terminate the slack space */ memset(&state->param[state->total_param], 0, 100); - if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) + + if (pscnt > state->total_param || + psoff+pscnt < psoff) { goto bad_param; - if ((smb_base(req->inbuf)+psoff+pscnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf))) + } + + if (psoff > av_size || + pscnt > av_size || + psoff+pscnt > av_size) { goto bad_param; + } memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } @@ -675,7 +687,7 @@ void reply_transs(struct smb_request *req) connection_struct *conn = req->conn; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - int size; + unsigned int av_size; START_PROFILE(SMBtranss); @@ -708,7 +720,7 @@ void reply_transs(struct smb_request *req) if (SVAL(req->inbuf, smb_vwv1) < state->total_data) state->total_data = SVAL(req->inbuf,smb_vwv1); - size = smb_len(req->inbuf) + 4; + av_size = smb_len(req->inbuf); pcnt = SVAL(req->inbuf, smb_spscnt); poff = SVAL(req->inbuf, smb_spsoff); @@ -726,38 +738,38 @@ void reply_transs(struct smb_request *req) goto bad_param; if (pcnt) { - if (pdisp+pcnt > state->total_param) - goto bad_param; - if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) - goto bad_param; - if (pdisp > state->total_param) + if (pdisp > state->total_param || + pcnt > state->total_param || + pdisp+pcnt > state->total_param || + pdisp+pcnt < pdisp) { goto bad_param; - if ((smb_base(req->inbuf) + poff + pcnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf) + poff + pcnt - < smb_base(req->inbuf))) - goto bad_param; - if (state->param + pdisp < state->param) + } + + if (poff > av_size || + pcnt > av_size || + poff+pcnt > av_size || + poff+pcnt < poff) { goto bad_param; + } memcpy(state->param+pdisp,smb_base(req->inbuf)+poff, pcnt); } if (dcnt) { - if (ddisp+dcnt > state->total_data) - goto bad_param; - if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) + if (ddisp > state->total_data || + dcnt > state->total_data || + ddisp+dcnt > state->total_data || + ddisp+dcnt < ddisp) { goto bad_param; - if (ddisp > state->total_data) - goto bad_param; - if ((smb_base(req->inbuf) + doff + dcnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf) + doff + dcnt - < smb_base(req->inbuf))) - goto bad_param; - if (state->data + ddisp < state->data) + } + + if (ddisp > av_size || + dcnt > av_size || + ddisp+dcnt > av_size || + ddisp+dcnt < ddisp) { goto bad_param; + } memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, dcnt); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 05c0957e4f..e8dae705b0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2557,14 +2557,15 @@ static void handle_nttrans(connection_struct *conn, void reply_nttrans(struct smb_request *req) { connection_struct *conn = req->conn; - uint32 pscnt; - uint32 psoff; - uint32 dscnt; - uint32 dsoff; + uint32_t pscnt; + uint32_t psoff; + uint32_t dscnt; + uint32_t dsoff; uint16 function_code; NTSTATUS result; struct trans_state *state; - int size; + uint32_t size; + uint32_t av_size; START_PROFILE(SMBnttrans); @@ -2575,6 +2576,7 @@ void reply_nttrans(struct smb_request *req) } size = smb_len(req->inbuf) + 4; + av_size = smb_len(req->inbuf); pscnt = IVAL(req->inbuf,smb_nt_ParameterCount); psoff = IVAL(req->inbuf,smb_nt_ParameterOffset); dscnt = IVAL(req->inbuf,smb_nt_DataCount); @@ -2650,12 +2652,17 @@ void reply_nttrans(struct smb_request *req) END_PROFILE(SMBnttrans); return; } - if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) + + if (dscnt > state->total_data || + dsoff+dscnt < dsoff) { goto bad_param; - if ((smb_base(req->inbuf)+dsoff+dscnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf))) + } + + if (dsoff > av_size || + dscnt > av_size || + dsoff+dscnt > av_size) { goto bad_param; + } memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } @@ -2672,12 +2679,17 @@ void reply_nttrans(struct smb_request *req) END_PROFILE(SMBnttrans); return; } - if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) + + if (pscnt > state->total_param || + psoff+pscnt < psoff) { goto bad_param; - if ((smb_base(req->inbuf)+psoff+pscnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf))) + } + + if (psoff > av_size || + pscnt > av_size || + psoff+pscnt > av_size) { goto bad_param; + } memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } @@ -2749,10 +2761,10 @@ void reply_nttrans(struct smb_request *req) void reply_nttranss(struct smb_request *req) { connection_struct *conn = req->conn; - unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; + uint32_t pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - - int size; + uint32_t av_size; + uint32_t size; START_PROFILE(SMBnttranss); @@ -2789,6 +2801,7 @@ void reply_nttranss(struct smb_request *req) } size = smb_len(req->inbuf) + 4; + av_size = smb_len(req->inbuf); pcnt = IVAL(req->inbuf,smb_nts_ParameterCount); poff = IVAL(req->inbuf, smb_nts_ParameterOffset); @@ -2806,38 +2819,38 @@ void reply_nttranss(struct smb_request *req) goto bad_param; if (pcnt) { - if (pdisp+pcnt > state->total_param) - goto bad_param; - if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) - goto bad_param; - if (pdisp > state->total_param) + if (pdisp > state->total_param || + pcnt > state->total_param || + pdisp+pcnt > state->total_param || + pdisp+pcnt < pdisp) { goto bad_param; - if ((smb_base(req->inbuf) + poff + pcnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf) + poff + pcnt - < smb_base(req->inbuf))) - goto bad_param; - if (state->param + pdisp < state->param) + } + + if (poff > av_size || + pcnt > av_size || + poff+pcnt > av_size || + poff+pcnt < poff) { goto bad_param; + } memcpy(state->param+pdisp, smb_base(req->inbuf)+poff, pcnt); } if (dcnt) { - if (ddisp+dcnt > state->total_data) - goto bad_param; - if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) + if (ddisp > state->total_data || + dcnt > state->total_data || + ddisp+dcnt > state->total_data || + ddisp+dcnt < ddisp) { goto bad_param; - if (ddisp > state->total_data) - goto bad_param; - if ((smb_base(req->inbuf) + doff + dcnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf) + doff + dcnt - < smb_base(req->inbuf))) - goto bad_param; - if (state->data + ddisp < state->data) + } + + if (ddisp > av_size || + dcnt > av_size || + ddisp+dcnt > av_size || + ddisp+dcnt < ddisp) { goto bad_param; + } memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, dcnt); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 05e8375d05..709eb39dd8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7468,7 +7468,8 @@ void reply_trans2(struct smb_request *req) unsigned int psoff; unsigned int pscnt; unsigned int tran_call; - int size; + unsigned int size; + unsigned int av_size; struct trans_state *state; NTSTATUS result; @@ -7486,6 +7487,7 @@ void reply_trans2(struct smb_request *req) pscnt = SVAL(req->inbuf, smb_pscnt); tran_call = SVAL(req->inbuf, smb_setup0); size = smb_len(req->inbuf) + 4; + av_size = smb_len(req->inbuf); result = allow_new_trans(conn->pending_trans, req->mid); if (!NT_STATUS_IS_OK(result)) { @@ -7578,12 +7580,17 @@ void reply_trans2(struct smb_request *req) END_PROFILE(SMBtrans2); return; } - if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt)) + + if (dscnt > state->total_data || + dsoff+dscnt < dsoff) { goto bad_param; - if ((smb_base(req->inbuf)+dsoff+dscnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf))) + } + + if (dsoff > av_size || + dscnt > av_size || + dsoff+dscnt > av_size) { goto bad_param; + } memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt); } @@ -7601,12 +7608,17 @@ void reply_trans2(struct smb_request *req) END_PROFILE(SMBtrans2); return; } - if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt)) + + if (pscnt > state->total_param || + psoff+pscnt < psoff) { goto bad_param; - if ((smb_base(req->inbuf)+psoff+pscnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf))) + } + + if (psoff > av_size || + pscnt > av_size || + psoff+pscnt > av_size) { goto bad_param; + } memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt); } @@ -7655,7 +7667,8 @@ void reply_transs2(struct smb_request *req) connection_struct *conn = req->conn; unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp; struct trans_state *state; - int size; + unsigned int size; + unsigned int av_size; START_PROFILE(SMBtranss2); @@ -7668,6 +7681,7 @@ void reply_transs2(struct smb_request *req) } size = smb_len(req->inbuf)+4; + av_size = smb_len(req->inbuf); for (state = conn->pending_trans; state != NULL; state = state->next) { @@ -7706,36 +7720,38 @@ void reply_transs2(struct smb_request *req) goto bad_param; if (pcnt) { - if (pdisp+pcnt > state->total_param) - goto bad_param; - if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt)) - goto bad_param; - if (pdisp > state->total_param) + if (pdisp > state->total_param || + pcnt > state->total_param || + pdisp+pcnt > state->total_param || + pdisp+pcnt < pdisp) { goto bad_param; - if ((smb_base(req->inbuf) + poff + pcnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf))) - goto bad_param; - if (state->param + pdisp < state->param) + } + + if (poff > av_size || + pcnt > av_size || + poff+pcnt > av_size || + poff+pcnt < poff) { goto bad_param; + } memcpy(state->param+pdisp,smb_base(req->inbuf)+poff, pcnt); } if (dcnt) { - if (ddisp+dcnt > state->total_data) - goto bad_param; - if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt)) + if (ddisp > state->total_data || + dcnt > state->total_data || + ddisp+dcnt > state->total_data || + ddisp+dcnt < ddisp) { goto bad_param; - if (ddisp > state->total_data) - goto bad_param; - if ((smb_base(req->inbuf) + doff + dcnt - > (char *)req->inbuf + size) || - (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf))) - goto bad_param; - if (state->data + ddisp < state->data) + } + + if (ddisp > av_size || + dcnt > av_size || + ddisp+dcnt > av_size || + ddisp+dcnt < ddisp) { goto bad_param; + } memcpy(state->data+ddisp, smb_base(req->inbuf)+doff, dcnt); -- cgit From c2bb4b51c1e660a675197063781323fe65c97135 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 8 Apr 2008 15:19:01 +0400 Subject: Destroy DMAPI session when main smbd daemon exits. DMAPI session is precious resource maintained at kernel level. We open one of them and use across multiple smbd daemons but once last of them exits, DMAPI session needs to be destroyed. There are some HSM implementations which fail to shutdown when opened DMAPI sessions left. Ensure we shutdown our session when it is really not needed anymore. This is what recommended by DMAPI specification anyway. (This used to be commit a0cefd44009d414fa00ec6e08c70d21b74acdbcb) --- source3/smbd/dmapi.c | 24 ++++++++++++++++++++++++ source3/smbd/server.c | 9 +++++++++ 2 files changed, 33 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index fab0d5f9ef..fd252e980a 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -212,6 +212,30 @@ bool dmapi_new_session(void) return samba_dmapi_session != DM_NO_SESSION; } +/* + only call this when exiting from master smbd process. DMAPI sessions + are long-lived kernel resources we ought to share across smbd processes. + However, we must free them when all smbd processes are finished to + allow other subsystems clean up properly. Not freeing DMAPI session + blocks certain HSM implementations from proper shutdown. +*/ +bool dmapi_destroy_session(void) +{ + if (samba_dmapi_session != DM_NO_SESSION) { + become_root(); + if (!dm_destroy_session(samba_dmapi_session)) { + session_num--; + samba_dmapi_session = DM_NO_SESSION; + } else { + DEBUG(0,("Couldn't destroy DMAPI session: %s\n", + strerror(errno))); + } + unbecome_root(); + } + return samba_dmapi_session == DM_NO_SESSION; +} + + /* This is default implementation of dmapi_file_flags() that is called from VFS is_offline() call to know whether file is offline. diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 179d480f43..7a6e17135f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -918,6 +918,15 @@ static void exit_server_common(enum server_exit_reason how, } #endif +#ifdef USE_DMAPI + /* Destroy Samba DMAPI session only if we are master smbd process */ + if (am_parent) { + if (!dmapi_destroy_session()) { + DEBUG(0,("Unable to close Samba DMAPI session\n")); + } + } +#endif + locking_end(); printing_end(); -- cgit From ee8dffbca635abce6c1c79b81a8dfa624871fda9 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 8 Apr 2008 21:41:16 +0200 Subject: Fix the build of reply_setattrE(). How ever could this compile ? Guenther (This used to be commit 02f5f35e5ed3b061cfd020d0b13014c72fced5f4) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ab77de06f8..2506ff97e9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -7029,7 +7029,7 @@ void reply_setattrE(struct smb_request *req) } else { if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) { status = map_nt_error_from_unix(errno); - reply_nterror(req, status) + reply_nterror(req, status); END_PROFILE(SMBsetattrE); return; } @@ -7038,7 +7038,7 @@ void reply_setattrE(struct smb_request *req) status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true); if (!NT_STATUS_IS_OK(status)) { - reply_doserror(req, ERRDOS, ERRnoaccess) + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetattrE); return; } -- cgit From 245ebca937d1a98007ad8a85fbf7cdc812ba6316 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Apr 2008 11:34:33 +0200 Subject: Fix bug 5366 (This used to be commit 448a8fe6c15bc4e85149d1ae821f0ebc2e3edde5) --- source3/smbd/chgpasswd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e7ab60d22f..b2b082363f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -159,7 +159,12 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, DEBUG(3, ("More weirdness, could not open %s\n", slavedev)); return (False); } -#if defined(TIOCSCTTY) +#if defined(TIOCSCTTY) && !defined(SUNOS5) + /* + * On patched Solaris 10 TIOCSCTTY is defined but seems not to work, + * see the discussion under + * https://bugzilla.samba.org/show_bug.cgi?id=5366. + */ if (ioctl(slave, TIOCSCTTY, 0) < 0) { DEBUG(3, ("Error in ioctl call for slave pty\n")); -- cgit From bb869741ddc3d82da02c96bef592dab6074ff142 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Mon, 3 Mar 2008 13:32:54 -0800 Subject: Cleanup size_t return values in convert_string_allocate This patch is the first iteration of an inside-out conversion to cleanup functions in charcnv.c returning size_t == -1 to indicate failure. (This used to be commit 59124382d2894a1b194b48dd82bc5f956959eb48) --- source3/smbd/notify.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ffdf1c22e7..eb3384d9a4 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -82,10 +82,9 @@ static bool notify_marshall_changes(int num_changes, c = &changes[i]; - namelen = convert_string_allocate( - NULL, CH_UNIX, CH_UTF16LE, c->name, strlen(c->name)+1, - &uni_name.buffer, True); - if ((namelen == -1) || (uni_name.buffer == NULL)) { + if (!convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, + c->name, strlen(c->name)+1, &uni_name.buffer, + &namelen, True) || (uni_name.buffer == NULL)) { goto fail; } -- cgit From e21b283d6713794fb0a415a9313943867812884d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Apr 2008 14:01:28 +0200 Subject: dbwrap: wait for tdb2 change notifies in smbd, nmbd and winbindd metze (This used to be commit 64450cc1e441355aa8925b7183e90872eeab20b1) --- source3/smbd/server.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7a6e17135f..bc0d4b70a3 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -553,7 +553,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ clustered mode, ctdb won't allow us to start doing database operations until it has gone thru a full startup, which includes checking to see that smbd is listening. */ - claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD); + claim_connection(NULL,"", + FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_DBWRAP); /* Listen to messages */ @@ -574,6 +575,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ MSG_SMB_INJECT_FAULT, msg_inject_fault); #endif + db_tdb2_setup_messaging(smbd_messaging_context(), true); + /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); @@ -1226,6 +1229,7 @@ extern void build_options(bool screen); /* * Do this before reload_services. */ + db_tdb2_setup_messaging(NULL, false); if (!reload_services(False)) return(-1); -- cgit From 281e610ff31edff43dabe4ee9eb3e7b840fad204 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 13 Apr 2008 15:31:02 +0200 Subject: registry: change init_registry() to return WERROR instead of bool. Michael (This used to be commit 0b196095dbbc29c796cb0742fe6e57a421e9596b) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bc0d4b70a3..9754fab534 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1323,7 +1323,7 @@ extern void build_options(bool screen); namecache_enable(); - if (!init_registry()) + if (!W_ERROR_IS_OK(init_registry())) exit(1); #if 0 -- cgit From a9ff941f41b9ddc28dfaa855773d80055eccae96 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 13 Apr 2008 15:33:12 +0200 Subject: registry: rename init_registry() to registry_init_full() for consistency. Michael (This used to be commit 14d82708d4499b48830d3dd25a0133f00a39d030) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 9754fab534..b71d6271f2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1323,7 +1323,7 @@ extern void build_options(bool screen); namecache_enable(); - if (!W_ERROR_IS_OK(init_registry())) + if (!W_ERROR_IS_OK(registry_init_full())) exit(1); #if 0 -- cgit From 09c5d892201a94c8d24bc5b593942a869ece2f34 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 14 Apr 2008 13:56:36 +0400 Subject: Use more error-prone form of testing dm_destroy_session() return code after discussing with Tridge (This used to be commit 4abdbad52e456764bca1b17ead04edee1e2a2a64) --- source3/smbd/dmapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index fd252e980a..1049c95a39 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -223,7 +223,7 @@ bool dmapi_destroy_session(void) { if (samba_dmapi_session != DM_NO_SESSION) { become_root(); - if (!dm_destroy_session(samba_dmapi_session)) { + if (0 == dm_destroy_session(samba_dmapi_session)) { session_num--; samba_dmapi_session = DM_NO_SESSION; } else { -- cgit From a4c0812af0132476dfd542ca212304de898fa7c7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Apr 2008 15:54:49 +0200 Subject: Fix some "ignoring asprintf result" warnings (This used to be commit 155d62ddfd3584d44a493c2aa1ea7f096bcff432) --- source3/smbd/lanman.c | 30 +++++++++++++++--------------- source3/smbd/process.c | 11 ++++++----- 2 files changed, 21 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 18e6bf9f7b..6fa4f9698d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1971,24 +1971,24 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, return False; } - asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", - lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename, pathname, comment); + if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", + lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename, + pathname, comment) == -1) { + return false; + } - if (command) { - DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); + DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); - if ((res = smbrun(command, NULL)) != 0) { - DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); - SAFE_FREE(command); - res = ERRnoaccess; - goto error_exit; - } else { - SAFE_FREE(command); - message_send_all(smbd_messaging_context(), - MSG_SMB_CONF_UPDATED, NULL, 0, NULL); - } + if ((res = smbrun(command, NULL)) != 0) { + DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", + command, res )); + SAFE_FREE(command); + res = ERRnoaccess; + goto error_exit; } else { - return False; + SAFE_FREE(command); + message_send_all(smbd_messaging_context(), + MSG_SMB_CONF_UPDATED, NULL, 0, NULL); } *rparam_len = 6; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 88684315cc..5946989ae7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1259,8 +1259,10 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) if ((num_bytes > 0xffffff) || ((num_bytes + smb_size + num_words*2) > 0xffffff)) { char *msg; - asprintf(&msg, "num_bytes too large: %u", - (unsigned)num_bytes); + if (asprintf(&msg, "num_bytes too large: %u", + (unsigned)num_bytes) == -1) { + msg = CONST_DISCARD(char *, "num_bytes too large"); + } smb_panic(msg); } @@ -1298,9 +1300,8 @@ static void smb_dump(const char *name, int type, const char *data, ssize_t len) if (len < 4) len = smb_len(data)+4; for (i=1;i<100;i++) { - asprintf(&fname, "/tmp/%s.%d.%s", name, i, - type ? "req" : "resp"); - if (!fname) { + if (asprintf(&fname, "/tmp/%s.%d.%s", name, i, + type ? "req" : "resp") == -1) { return; } fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644); -- cgit From ae4159f0f7160ffd4ebcc0a2a79681d873e3e4f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 30 Mar 2008 22:08:17 +0200 Subject: Remove two pointless else branches (This used to be commit ed343114cd0844a7fd14b45f95c0f43a6d172a42) --- source3/smbd/nttrans.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e8dae705b0..ae7bd8b7b7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -498,11 +498,10 @@ void reply_ntcreate_and_X(struct smb_request *req) do_ntcreate_pipe_open(conn, req); END_PROFILE(SMBntcreateX); return; - } else { - reply_doserror(req, ERRDOS, ERRnoaccess); - END_PROFILE(SMBntcreateX); - return; } + reply_doserror(req, ERRDOS, ERRnoaccess); + END_PROFILE(SMBntcreateX); + return; } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -871,10 +870,9 @@ static void call_nt_transact_create(connection_struct *conn, ppparams, parameter_count, ppdata, data_count); return; - } else { - reply_doserror(req, ERRDOS, ERRnoaccess); - return; } + reply_doserror(req, ERRDOS, ERRnoaccess); + return; } /* -- cgit From b7a141f8a72512302bd118ad5d4b9cf8c4c57564 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Apr 2008 01:50:13 +0200 Subject: smbd: merge "smbd:backgroundqueue=no" option from the v3-0-ctdb tree metze (This used to be commit 16d295d466eb18e3bccce6fb26d53012d5f2c3e8) --- source3/smbd/server.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b71d6271f2..108a55033c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1344,8 +1344,10 @@ extern void build_options(bool screen); smbd is launched via inetd and we fork a copy of ourselves here */ - if ( is_daemon && !interactive ) - start_background_queue(); + if (is_daemon && !interactive + && lp_parm_bool(-1, "smbd", "backgroundqueue", true)) { + start_background_queue(); + } if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); -- cgit From f2067658df3c272c2e8c6f2d00bcc5687050ee1d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Apr 2008 01:01:59 +0200 Subject: smbd: call reinit_after_fork() in the needed places metze (This used to be commit 425b3513a45cf98b53235470a3536be86d56d1c2) --- source3/smbd/server.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 108a55033c..337026a8ca 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -741,17 +741,9 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ sizeof(remaddr)), false); - /* Reset the state of the random - * number generation system, so - * children do not get the same random - * numbers as each other */ - - set_need_random_reseed(); - /* tdb needs special fork handling - remove - * CLEAR_IF_FIRST flags */ - if (tdb_reopen_all(1) == -1) { - DEBUG(0,("tdb_reopen_all failed.\n")); - smb_panic("tdb_reopen_all failed"); + if (!reinit_after_fork(smbd_messaging_context())) { + DEBUG(0,("reinit_after_fork() failed\n")); + smb_panic("reinit_after_fork() failed"); } return True; @@ -1384,12 +1376,10 @@ extern void build_options(bool screen); /* Setup aio signal handler. */ initialize_async_io_handler(); - /* - * For clustering, we need to re-init our ctdbd connection after the - * fork - */ - if (!NT_STATUS_IS_OK(messaging_reinit(smbd_messaging_context()))) + if (!reinit_after_fork(smbd_messaging_context())) { + DEBUG(0,("reinit_after_fork() failed\n")); exit(1); + } /* register our message handlers */ messaging_register(smbd_messaging_context(), NULL, -- cgit From 2df0ade13afc1690c2e6d80e087aa281c815e678 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Apr 2008 10:57:45 +0200 Subject: smbd: create the messaging conntext earlier metze (This used to be commit 658d8475336c4397e0dad341f216baf9e1eb6aaf) --- source3/smbd/server.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 337026a8ca..59bbfdbc17 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -575,8 +575,6 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ MSG_SMB_INJECT_FAULT, msg_inject_fault); #endif - db_tdb2_setup_messaging(smbd_messaging_context(), true); - /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); @@ -1095,6 +1093,8 @@ extern void build_options(bool screen); TimeInit(); + db_tdb2_setup_messaging(NULL, false); + #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif @@ -1218,10 +1218,18 @@ extern void build_options(bool screen); exit(1); } + if (!lp_load_initial_only(get_dyn_CONFIGFILE())) { + DEBUG(0, ("error opening config file\n")); + exit(1); + } + + if (smbd_messaging_context() == NULL) + exit(1); + /* * Do this before reload_services. */ - db_tdb2_setup_messaging(NULL, false); + db_tdb2_setup_messaging(smbd_messaging_context(), true); if (!reload_services(False)) return(-1); @@ -1277,10 +1285,12 @@ extern void build_options(bool screen); if (is_daemon) pidfile_create("smbd"); - /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ - - if (smbd_messaging_context() == NULL) + if (!reinit_after_fork(smbd_messaging_context())) { + DEBUG(0,("reinit_after_fork() failed\n")); exit(1); + } + + /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (smbd_memcache() == NULL) { exit(1); @@ -1376,11 +1386,6 @@ extern void build_options(bool screen); /* Setup aio signal handler. */ initialize_async_io_handler(); - if (!reinit_after_fork(smbd_messaging_context())) { - DEBUG(0,("reinit_after_fork() failed\n")); - exit(1); - } - /* register our message handlers */ messaging_register(smbd_messaging_context(), NULL, MSG_SMB_FORCE_TDIS, msg_force_tdis); -- cgit From c071b941e6090a2b107a8a42835e6da772161425 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Apr 2008 13:08:14 +0200 Subject: Fix bug 5398 Thanks to Jason Mader for sending the compiler output :-) Volker (This used to be commit 7a57c2da1a6cc0fcea0b4d949c696219f1822694) --- source3/smbd/chgpasswd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index b2b082363f..2596e73380 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -249,6 +249,7 @@ static int expect(int master, char *issue, char *expected) bool match = False; for (attempts = 0; attempts < 2; attempts++) { + NTSTATUS status; if (!strequal(issue, ".")) { if (lp_passwd_chat_debug()) DEBUG(100, ("expect: sending [%s]\n", issue)); @@ -269,7 +270,6 @@ static int expect(int master, char *issue, char *expected) buffer[nread] = 0; while (True) { - NTSTATUS status; status = read_socket_with_timeout( master, buffer + nread, 1, sizeof(buffer) - nread - 1, @@ -305,8 +305,8 @@ static int expect(int master, char *issue, char *expected) if (match) break; - if (len < 0) { - DEBUG(2, ("expect: %s\n", strerror(errno))); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2, ("expect: %s\n", nt_errstr(status))); return False; } } -- cgit From b46d340fd5d7e88684ac77000e17c1899ff608b2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Apr 2008 18:17:13 +0200 Subject: Refactoring: Make struct rpc_pipe_client its own talloc parent (This used to be commit a6d74a5a562b54f0b36934965f545fdeb1e8b34a) --- source3/smbd/change_trust_pw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 4773eeff86..227b2d6899 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -82,7 +82,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m goto failed; } - nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, netlogon_pipe->mem_ctx, domain); + nt_status = trust_pw_find_change_and_store_it( + netlogon_pipe, netlogon_pipe, domain); cli_shutdown(cli); cli = NULL; -- cgit From 3756467db6a661be91f4aeb484000e993e4a9a4c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 12:18:33 +0100 Subject: Move the posix pending close functionality down into the VFS layer. This hides the pending close fds from the outside. Call order of SMB_VFS_CLOSE is reversed. Originally, it was: fd_close -> fd_close_posix -> SMB_VFS_CLOSE -> close And now it is: fd_close -> SMB_VFS_CLOSE -> fd_close_posix -> close This is in preparation of removing the fd parameter from the SMB_VFS_CLOSE function. But it is also the right place for the pending close calls anyways. Michael (This used to be commit 3cf56b124a2886c6260455bba4bf77d08e9a4f77) --- source3/smbd/open.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f3ed234c87..7a13b3ae38 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -72,13 +72,21 @@ static NTSTATUS fd_open(struct connection_struct *conn, NTSTATUS fd_close(files_struct *fsp) { + int ret; + if (fsp->fh->fd == -1) { return NT_STATUS_OK; /* What we used to call a stat open. */ } if (fsp->fh->ref_count > 1) { return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } - return fd_close_posix(fsp); + + ret = SMB_VFS_CLOSE(fsp, fsp->fh->fd); + fsp->fh->fd = -1; + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; } /**************************************************************************** -- cgit From 0db7aba8af80a01150d1061a4192ab814e4234b7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 14:19:28 +0100 Subject: Remove redundant parameter fd from SMB_VFS_CLOSE(). Now all those redundant fd's have vanished from the VFS API. Michael (This used to be commit 14294535512a7f191c5008e622b6708e417854ae) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7a13b3ae38..0d1dd31cd6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -81,7 +81,7 @@ NTSTATUS fd_close(files_struct *fsp) return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } - ret = SMB_VFS_CLOSE(fsp, fsp->fh->fd); + ret = SMB_VFS_CLOSE(fsp); fsp->fh->fd = -1; if (ret == -1) { return map_nt_error_from_unix(errno); -- cgit From 0c4093a234dfaca6d363a6e1358f2fbf421dcd3c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Apr 2008 17:13:50 +0200 Subject: Fix CLEAR_IF_FIRST handling of messages.tdb We now open messages.tdb even before we do the become_daemon. become_daemon() involves a fork and an immediate exit of the parent, thus the parent_is_longlived argument must be set to false in this case. The parent is not really long lived :-) (This used to be commit 4f4781c6d17fe2db34dd5945fec52a7685448aec) --- source3/smbd/server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 59bbfdbc17..cf02589864 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -739,7 +739,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ sizeof(remaddr)), false); - if (!reinit_after_fork(smbd_messaging_context())) { + if (!reinit_after_fork( + smbd_messaging_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } @@ -1285,7 +1286,7 @@ extern void build_options(bool screen); if (is_daemon) pidfile_create("smbd"); - if (!reinit_after_fork(smbd_messaging_context())) { + if (!reinit_after_fork(smbd_messaging_context(), false)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } -- cgit From 0173eeb3b5c0e67a58c43089d5b152bfd307de80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Apr 2008 15:06:08 -0700 Subject: Fix bug found by Igor Mammedov where we are not returning a directory value for a QPATHINFO on a msdfs link with a non-dfs path. Windows does this. Jeremy. (This used to be commit fbd99071f99cadd21aa2b8971f745a323a9cda13) --- source3/smbd/trans2.c | 56 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 709eb39dd8..41f2a15cb8 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1195,6 +1195,32 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn, return NT_STATUS_OK; } +/**************************************************************************** + Needed to show the msdfs symlinks as directories. Modifies psbuf + to be a directory if it's a msdfs link. +****************************************************************************/ + +static bool check_msdfs_link(connection_struct *conn, + const char *pathname, + SMB_STRUCT_STAT *psbuf) +{ + int saved_errno = errno; + if(lp_host_msdfs() && + lp_msdfs_root(SNUM(conn)) && + is_msdfs_link(conn, pathname, psbuf)) { + + DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s " + "as a directory\n", + pathname)); + psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR; + errno = saved_errno; + return true; + } + errno = saved_errno; + return false; +} + + /**************************************************************************** Get a level dependent lanman2 dir entry. ****************************************************************************/ @@ -1360,16 +1386,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, /* Needed to show the msdfs symlinks as * directories */ - if(lp_host_msdfs() && - lp_msdfs_root(SNUM(conn)) && - ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) { - DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s " - "as a directory\n", - pathreal)); - sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR; - - } else { - + ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf); + if (!ms_dfs_link) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", pathreal,strerror(errno))); TALLOC_FREE(pathreal); @@ -3806,6 +3824,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ char *lock_data = NULL; + bool ms_dfs_link = false; TALLOC_CTX *ctx = talloc_tos(); if (!params) { @@ -3959,10 +3978,15 @@ static void call_trans2qfilepathinfo(connection_struct *conn, reply_unixerror(req, ERRDOS, ERRbadpath); return; } + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) { - DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - reply_unixerror(req, ERRDOS, ERRbadpath); - return; + ms_dfs_link = check_msdfs_link(conn,fname,&sbuf); + + if (!ms_dfs_link) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); + reply_unixerror(req, ERRDOS, ERRbadpath); + return; + } } fileid = vfs_file_id_from_sbuf(conn, &sbuf); @@ -3987,7 +4011,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn, else base_name = p+1; - mode = dos_mode(conn,fname,&sbuf); + if (ms_dfs_link) { + mode = dos_mode_msdfs(conn,fname,&sbuf); + } else { + mode = dos_mode(conn,fname,&sbuf); + } if (!mode) mode = FILE_ATTRIBUTE_NORMAL; -- cgit From 6f19a1fddaa614ea8d64eb70c08dffeb650e5b54 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 May 2008 17:01:37 -0700 Subject: Start to ensure we use the NT ACL interface, keep the POSIX ACL interface inside the VFS modules. Will help when moving to storing NT ACLs. Jeremy. (This used to be commit b08ea48f883d1b000f6364c1ff8f62bc25741244) --- source3/smbd/posix_acls.c | 67 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c3c9d2e60c..d422746a3c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3813,6 +3813,26 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode) return copy_access_acl(conn, name, name, mode); } +/**************************************************************************** + Check for an existing default POSIX ACL on a directory. +****************************************************************************/ + +static bool directory_has_default_posix_acl(connection_struct *conn, const char *fname) +{ + SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); + bool has_acl = False; + SMB_ACL_ENTRY_T entry; + + if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { + has_acl = True; + } + + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); + } + return has_acl; +} + /**************************************************************************** If the parent directory has no default ACL but it does have an Access ACL, inherit this Access ACL to file name. @@ -3821,7 +3841,7 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode) int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir, const char *name, mode_t mode) { - if (directory_has_default_acl(conn, inherit_from_dir)) + if (directory_has_default_posix_acl(conn, inherit_from_dir)) return 0; return copy_access_acl(conn, inherit_from_dir, name, mode); @@ -3852,26 +3872,6 @@ int fchmod_acl(files_struct *fsp, mode_t mode) return ret; } -/**************************************************************************** - Check for an existing default POSIX ACL on a directory. -****************************************************************************/ - -bool directory_has_default_acl(connection_struct *conn, const char *fname) -{ - SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); - bool has_acl = False; - SMB_ACL_ENTRY_T entry; - - if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { - has_acl = True; - } - - if (def_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); - } - return has_acl; -} - /**************************************************************************** Map from wire type to permset. ****************************************************************************/ @@ -4310,3 +4310,28 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) return ret_sd; } + +/**************************************************************************** + Check for an existing default Windows ACL on a directory. +****************************************************************************/ + +bool directory_has_default_acl(connection_struct *conn, const char *fname) +{ + SEC_DESC *psd = NULL; /* returns talloced off tos. */ + unsigned int i; + NTSTATUS status = SMB_VFS_GET_NT_ACL(conn, fname, + DACL_SECURITY_INFORMATION, &psd); + + if (!NT_STATUS_IS_OK(status) || psd == NULL) { + return false; + } + + for (i = 0; i < psd->dacl->num_aces; i++) { + SEC_ACE *psa = &psd->dacl->aces[i]; + if (psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT)) { + return true; + } + } + return false; +} -- cgit From 96e969c9eb60cf1d96ba9aeeb4c991d2acf4c095 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 May 2008 10:09:00 -0700 Subject: Move directory_has_default_acl() to file_access.c, belongs there as it no longer uses explicit POSIX ACL calls. Jeremy. (This used to be commit ac1eac9b0d07b7b3d341c06ef1a8fd8f3c05a618) --- source3/smbd/file_access.c | 27 +++++++++++++++++++++++++++ source3/smbd/posix_acls.c | 25 ------------------------- 2 files changed, 27 insertions(+), 25 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 964d1af258..4c07bc5a61 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -183,3 +183,30 @@ bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA); } +/**************************************************************************** + Check for an existing default Windows ACL on a directory. +****************************************************************************/ + +bool directory_has_default_acl(connection_struct *conn, const char *fname) +{ + /* returns talloced off tos. */ + struct security_descriptor *secdesc = NULL; + unsigned int i; + NTSTATUS status = SMB_VFS_GET_NT_ACL(conn, fname, + DACL_SECURITY_INFORMATION, &secdesc); + + if (!NT_STATUS_IS_OK(status) || secdesc == NULL) { + return false; + } + + for (i = 0; i < secdesc->dacl->num_aces; i++) { + struct security_ace *psa = &secdesc->dacl->aces[i]; + if (psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT)) { + TALLOC_FREE(secdesc); + return true; + } + } + TALLOC_FREE(secdesc); + return false; +} diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d422746a3c..61ee5b4352 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4310,28 +4310,3 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) return ret_sd; } - -/**************************************************************************** - Check for an existing default Windows ACL on a directory. -****************************************************************************/ - -bool directory_has_default_acl(connection_struct *conn, const char *fname) -{ - SEC_DESC *psd = NULL; /* returns talloced off tos. */ - unsigned int i; - NTSTATUS status = SMB_VFS_GET_NT_ACL(conn, fname, - DACL_SECURITY_INFORMATION, &psd); - - if (!NT_STATUS_IS_OK(status) || psd == NULL) { - return false; - } - - for (i = 0; i < psd->dacl->num_aces; i++) { - SEC_ACE *psa = &psd->dacl->aces[i]; - if (psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| - SEC_ACE_FLAG_CONTAINER_INHERIT)) { - return true; - } - } - return false; -} -- cgit From 85dc0ad7beb50dbab6d98a22b114f20537425268 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 May 2008 12:54:53 -0700 Subject: Rename inherit_access_acl() -> inherit_access_posix_acl() to make use clear. Jeremy. (This used to be commit b739c7f1cdb2b19a380b06681b00dcf490d788a9) --- source3/smbd/open.c | 4 ++-- source3/smbd/posix_acls.c | 8 ++++---- source3/smbd/trans2.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d1dd31cd6..dd518b90de 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -323,7 +323,7 @@ static NTSTATUS open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, parent_dir, path, + inherit_access_posix_acl(conn, parent_dir, path, unx_mode); } @@ -2058,7 +2058,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, } if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, parent_dir, name, mode); + inherit_access_posix_acl(conn, parent_dir, name, mode); } if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 61ee5b4352..732199e0e9 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3783,7 +3783,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo resulting ACL on TO. Note that name is in UNIX character set. ****************************************************************************/ -static int copy_access_acl(connection_struct *conn, const char *from, const char *to, mode_t mode) +static int copy_access_posix_acl(connection_struct *conn, const char *from, const char *to, mode_t mode) { SMB_ACL_T posix_acl = NULL; int ret = -1; @@ -3810,7 +3810,7 @@ static int copy_access_acl(connection_struct *conn, const char *from, const char int chmod_acl(connection_struct *conn, const char *name, mode_t mode) { - return copy_access_acl(conn, name, name, mode); + return copy_access_posix_acl(conn, name, name, mode); } /**************************************************************************** @@ -3838,13 +3838,13 @@ static bool directory_has_default_posix_acl(connection_struct *conn, const char inherit this Access ACL to file name. ****************************************************************************/ -int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir, +int inherit_access_posix_acl(connection_struct *conn, const char *inherit_from_dir, const char *name, mode_t mode) { if (directory_has_default_posix_acl(conn, inherit_from_dir)) return 0; - return copy_access_acl(conn, inherit_from_dir, name, mode); + return copy_access_posix_acl(conn, inherit_from_dir, name, mode); } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 41f2a15cb8..e7157d02ec 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5868,7 +5868,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn, */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl( + inherit_access_posix_acl( conn, parent_dirname(fname), fname, unixmode); } -- cgit From b430b382202858a6c52c1cacbb91910b2dd7e16c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 May 2008 17:22:10 -0700 Subject: Remove the "stat_open()" function, flag, and all associated code. It was only being (correctly) used in the can_read/can_write checks for hide unreadable/unwritable and this is more properly done using the functions in smbd/file_access.c. Preparing to do NT access checks on all file access. Jeremy. (This used to be commit 6bfb06ad95963ae2acb67c4694a98282d3b29faa) --- source3/smbd/close.c | 16 ----------- source3/smbd/dir.c | 68 ++-------------------------------------------- source3/smbd/file_access.c | 8 +++--- source3/smbd/files.c | 1 - source3/smbd/open.c | 56 +------------------------------------- 5 files changed, 7 insertions(+), 142 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 3afc037f69..e27d5c44fa 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -702,20 +702,6 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty return status; } -/**************************************************************************** - Close a 'stat file' opened internally. -****************************************************************************/ - -static NTSTATUS close_stat(files_struct *fsp) -{ - /* - * Do the code common to files and directories. - */ - close_filestruct(fsp); - file_free(fsp); - return NT_STATUS_OK; -} - /**************************************************************************** Close a files_struct. ****************************************************************************/ @@ -727,8 +713,6 @@ NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type) if(fsp->is_directory) { status = close_directory(fsp, close_type); - } else if (fsp->is_stat) { - status = close_stat(fsp); } else if (fsp->fake_file_handle != NULL) { status = close_fake_file(fsp); } else { diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 6e02401e25..7d584977df 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -925,11 +925,6 @@ bool get_dir_entry(TALLOC_CTX *ctx, static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { - SEC_DESC *psd = NULL; - files_struct *fsp; - NTSTATUS status; - uint32 access_granted; - /* * If user is a member of the Admin group * we never hide files from them. @@ -941,36 +936,7 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S SMB_ASSERT(VALID_STAT(*pst)); - /* Pseudo-open the file (note - no fd's created). */ - - if(S_ISDIR(pst->st_mode)) { - status = open_directory(conn, NULL, name, pst, - READ_CONTROL_ACCESS, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, - 0, /* no create options. */ - FILE_ATTRIBUTE_DIRECTORY, - NULL, &fsp); - } else { - status = open_file_stat(conn, NULL, name, pst, &fsp); - } - - if (!NT_STATUS_IS_OK(status)) { - return False; - } - - /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - status = SMB_VFS_FGET_NT_ACL(fsp, - (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); - close_file(fsp, NORMAL_CLOSE); - - /* No access if SD get failed. */ - if (!NT_STATUS_IS_OK(status)) { - return False; - } - - return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, - &access_granted, &status); + return can_access_file_acl(conn, name, pst, FILE_READ_DATA); } /******************************************************************* @@ -982,12 +948,6 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { - SEC_DESC *psd = NULL; - files_struct *fsp; - int info; - NTSTATUS status; - uint32 access_granted; - /* * If user is a member of the Admin group * we never hide files from them. @@ -1003,33 +963,9 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ if(S_ISDIR(pst->st_mode)) { return True; - } else { - status = open_file_ntcreate(conn, NULL, name, pst, - FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - INTERNAL_OPEN_ONLY, - &info, &fsp); - } - - if (!NT_STATUS_IS_OK(status)) { - return False; - } - - /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - status = SMB_VFS_FGET_NT_ACL(fsp, - (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); - close_file(fsp, NORMAL_CLOSE); - - /* No access if SD get failed. */ - if (!NT_STATUS_IS_OK(status)) { - return False; } - return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA, - &access_granted, &status); + return can_write_to_file(conn, name, pst); } /******************************************************************* diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 4c07bc5a61..71f3291b9b 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -25,7 +25,7 @@ extern struct current_user current_user; #undef DBGC_CLASS #define DBGC_CLASS DBGC_ACLS -static bool can_access_file_acl(struct connection_struct *conn, +bool can_access_file_acl(struct connection_struct *conn, const char * fname, SMB_STRUCT_STAT *psbuf, uint32_t access_mask) { @@ -125,7 +125,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) Note this doesn't take into account share write permissions. ****************************************************************************/ -bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) +bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) { if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) { return False; @@ -134,7 +134,7 @@ bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT /* some fast paths first */ - DEBUG(10,("can_access_file: requesting 0x%x on file %s\n", + DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n", (unsigned int)access_mask, fname )); if (current_user.ut.uid == 0 || conn->admin_user) { @@ -180,7 +180,7 @@ bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA); + return can_access_file_data(conn, fname, psbuf, FILE_WRITE_DATA); } /**************************************************************************** diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d6e91c67be..17c473f028 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -539,7 +539,6 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->print_file = fsp->print_file; dup_fsp->modified = fsp->modified; dup_fsp->is_directory = fsp->is_directory; - dup_fsp->is_stat = fsp->is_stat; dup_fsp->aio_write_behind = fsp->aio_write_behind; string_set(&dup_fsp->fsp_name,fsp->fsp_name); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd518b90de..5c860f891d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -391,7 +391,6 @@ static NTSTATUS open_file(files_struct *fsp, fsp->modified = False; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; - fsp->is_stat = False; if (conn->aio_write_behind_list && is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) { fsp->aio_write_behind = True; @@ -1571,7 +1570,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) || - !can_access_file(conn,fname,psbuf,can_access_mask)) { + !can_access_file_data(conn,fname,psbuf,can_access_mask)) { can_access = False; } @@ -2223,7 +2222,6 @@ NTSTATUS open_directory(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; - fsp->is_stat = False; fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False; string_set(&fsp->fsp_name,fname); @@ -2305,58 +2303,6 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, cons return status; } -/**************************************************************************** - Open a pseudo-file (no locking checks - a 'stat' open). -****************************************************************************/ - -NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req, - const char *fname, SMB_STRUCT_STAT *psbuf, - files_struct **result) -{ - files_struct *fsp = NULL; - NTSTATUS status; - - if (!VALID_STAT(*psbuf)) { - return NT_STATUS_INVALID_PARAMETER; - } - - /* Can't 'stat' open directories. */ - if(S_ISDIR(psbuf->st_mode)) { - return NT_STATUS_FILE_IS_A_DIRECTORY; - } - - status = file_new(conn, &fsp); - if(!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); - - /* - * Setup the files_struct for it. - */ - - fsp->mode = psbuf->st_mode; - fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); - fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; - fsp->file_pid = req ? req->smbpid : 0; - fsp->can_lock = False; - fsp->can_read = False; - fsp->can_write = False; - fsp->print_file = False; - fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->is_directory = False; - fsp->is_stat = True; - string_set(&fsp->fsp_name,fname); - - conn->num_files_open++; - - *result = fsp; - return NT_STATUS_OK; -} - /**************************************************************************** Receive notification that one of our open files has been renamed by another smbd process. -- cgit From d62563342e8c83d67dbcfb0c4b8e2ed886742006 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 Apr 2008 10:31:49 +0200 Subject: Remove connection_struct->mem_ctx, connection_struct is its own parent (This used to be commit 559180f7d30606d1999399d954ceedc798c669a4) --- source3/smbd/conn.c | 17 +++------- source3/smbd/dfree.c | 2 +- source3/smbd/ipc.c | 2 +- source3/smbd/msdfs.c | 81 +++++++++++++++++++++-------------------------- source3/smbd/nttrans.c | 2 +- source3/smbd/posix_acls.c | 27 ++++++++-------- source3/smbd/service.c | 12 +++---- source3/smbd/trans2.c | 2 +- source3/smbd/vfs.c | 6 ++-- 9 files changed, 66 insertions(+), 85 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 5aedadc56b..af18e905c0 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -92,7 +92,6 @@ thinking the server is still available. ****************************************************************************/ connection_struct *conn_new(void) { - TALLOC_CTX *mem_ctx; connection_struct *conn; int i; int find_offset = 1; @@ -140,18 +139,12 @@ find_again: return NULL; } - if ((mem_ctx=talloc_init("connection_struct"))==NULL) { - DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return NULL; - } - - if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) || - !(conn->params = TALLOC_P(mem_ctx, struct share_params))) { + if (!(conn=TALLOC_ZERO_P(NULL, connection_struct)) || + !(conn->params = TALLOC_P(conn, struct share_params))) { DEBUG(0,("TALLOC_ZERO() failed!\n")); - TALLOC_FREE(mem_ctx); + TALLOC_FREE(conn); return NULL; } - conn->mem_ctx = mem_ctx; conn->cnum = i; bitmap_set(bmap, i); @@ -262,7 +255,6 @@ void conn_clear_vuid_cache(uint16 vuid) void conn_free_internal(connection_struct *conn) { vfs_handle_struct *handle = NULL, *thandle = NULL; - TALLOC_CTX *mem_ctx = NULL; struct trans_state *state = NULL; /* Free vfs_connection_struct */ @@ -292,9 +284,8 @@ void conn_free_internal(connection_struct *conn) string_free(&conn->connectpath); string_free(&conn->origpath); - mem_ctx = conn->mem_ctx; ZERO_STRUCTP(conn); - talloc_destroy(mem_ctx); + talloc_destroy(conn); } /**************************************************************************** diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 9e7f18a130..1ddcd48d40 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -206,7 +206,7 @@ SMB_BIG_UINT get_dfree_info(connection_struct *conn, /* No cached info or time to refresh. */ if (!dfc) { - dfc = TALLOC_P(conn->mem_ctx, struct dfree_cached_info); + dfc = TALLOC_P(conn, struct dfree_cached_info); if (!dfc) { return dfree_ret; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6961a5caf1..59a5dfdd3f 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -525,7 +525,7 @@ void reply_trans(struct smb_request *req) return; } - if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { + if ((state = TALLOC_P(conn, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans); diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index fb757a5f74..14062e129d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -175,36 +175,37 @@ static NTSTATUS parse_dfs_path(const char *pathname, *********************************************************/ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, - connection_struct *conn, + connection_struct **pconn, int snum, const char *path) { + connection_struct *conn; char *connpath; - ZERO_STRUCTP(conn); + conn = TALLOC_ZERO_P(ctx, connection_struct); + if (conn == NULL) { + return NT_STATUS_NO_MEMORY; + } - connpath = talloc_strdup(ctx, path); + connpath = talloc_strdup(conn, path); if (!connpath) { + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } - connpath = talloc_string_sub(ctx, + connpath = talloc_string_sub(conn, connpath, "%S", lp_servicename(snum)); if (!connpath) { + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } /* needed for smbd_vfs_init() */ - if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { - DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, - struct share_params))) { + if (!(conn->params = TALLOC_ZERO_P(conn, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } @@ -234,6 +235,8 @@ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, return status; } + *pconn = conn; + return NT_STATUS_OK; } @@ -709,8 +712,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, int *consumedcntp, bool *self_referralp) { - struct connection_struct conns; - struct connection_struct *conn = &conns; + struct connection_struct *conn; char *targetpath = NULL; int snum; NTSTATUS status = NT_STATUS_NOT_FOUND; @@ -721,7 +723,6 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - ZERO_STRUCT(conns); *self_referralp = False; status = parse_dfs_path(dfs_path, False, pdp, &dummy); @@ -825,7 +826,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_OK; } - status = create_conn_struct(ctx, conn, snum, lp_pathname(snum)); + status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum)); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -1251,7 +1252,7 @@ bool create_junction(TALLOC_CTX *ctx, static bool junction_to_local_path(const struct junction_map *jucn, char **pp_path_out, - connection_struct *conn_out) + connection_struct **conn_out) { int snum; @@ -1265,7 +1266,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, return False; } - *pp_path_out = talloc_asprintf(conn_out->mem_ctx, + *pp_path_out = talloc_asprintf(conn_out, "%s/%s", lp_pathname(snum), jucn->volume_name); @@ -1280,20 +1281,17 @@ bool create_msdfs_link(const struct junction_map *jucn, { char *path = NULL; char *msdfs_link = NULL; - connection_struct conns; - connection_struct *conn = &conns; + connection_struct *conn; int i=0; bool insert_comma = False; bool ret = False; - ZERO_STRUCT(conns); - - if(!junction_to_local_path(jucn, &path, conn)) { + if(!junction_to_local_path(jucn, &path, &conn)) { return False; } /* Form the msdfs_link contents */ - msdfs_link = talloc_strdup(conn->mem_ctx, "msdfs:"); + msdfs_link = talloc_strdup(conn, "msdfs:"); if (!msdfs_link) { goto out; } @@ -1353,13 +1351,10 @@ out: bool remove_msdfs_link(const struct junction_map *jucn) { char *path = NULL; - connection_struct conns; - connection_struct *conn = &conns; + connection_struct *conn; bool ret = False; - ZERO_STRUCT(conns); - - if( junction_to_local_path(jucn, &path, conn) ) { + if( junction_to_local_path(jucn, &path, &conn) ) { if( SMB_VFS_UNLINK(conn, path) == 0 ) { ret = True; } @@ -1380,9 +1375,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) char *dname = NULL; const char *connect_path = lp_pathname(snum); const char *msdfs_proxy = lp_msdfs_proxy(snum); - connection_struct conn; - - ZERO_STRUCT(conn); + connection_struct *conn; if(*connect_path == '\0') { return 0; @@ -1406,24 +1399,24 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) } /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) { goto out; } - while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { - if (is_msdfs_link(&conn, + while ((dname = vfs_readdirname(conn, dirp)) != NULL) { + if (is_msdfs_link(conn, dname, NULL)) { cnt++; } } - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); out: - conn_free_internal(&conn); + conn_free_internal(conn); return cnt; } @@ -1441,11 +1434,9 @@ static int form_junctions(TALLOC_CTX *ctx, const char *connect_path = lp_pathname(snum); char *service_name = lp_servicename(snum); const char *msdfs_proxy = lp_msdfs_proxy(snum); - connection_struct conn; + connection_struct *conn; struct referral *ref = NULL; - ZERO_STRUCT(conn); - if (jn_remain == 0) { return 0; } @@ -1501,21 +1492,21 @@ static int form_junctions(TALLOC_CTX *ctx, } /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) { goto out; } - while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + while ((dname = vfs_readdirname(conn, dirp)) != NULL) { char *link_target = NULL; if (cnt >= jn_remain) { - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); goto out; } if (is_msdfs_link_internal(ctx, - &conn, + conn, dname, &link_target, NULL)) { if (parse_msdfs_symlink(ctx, @@ -1539,10 +1530,10 @@ static int form_junctions(TALLOC_CTX *ctx, out: if (dirp) { - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); } - conn_free_internal(&conn); + conn_free_internal(conn); return cnt; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ae7bd8b7b7..ec4126c1f7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2595,7 +2595,7 @@ void reply_nttrans(struct smb_request *req) return; } - if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { + if ((state = TALLOC_P(conn, struct trans_state)) == NULL) { reply_doserror(req, ERRSRV, ERRaccess); END_PROFILE(SMBnttrans); return; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 732199e0e9..33042faf56 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4262,30 +4262,29 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) { SEC_DESC *psd, *ret_sd; - connection_struct conn; + connection_struct *conn; files_struct finfo; struct fd_handle fh; - ZERO_STRUCT( conn ); - - if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) { - DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); + conn = TALLOC_ZERO_P(ctx, connection_struct); + if (conn == NULL) { + DEBUG(0, ("talloc failed\n")); return NULL; } - if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) { + if (!(conn->params = TALLOC_P(conn, struct share_params))) { DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); - TALLOC_FREE(conn.mem_ctx); + TALLOC_FREE(conn); return NULL; } - conn.params->service = -1; + conn->params->service = -1; - set_conn_connectpath(&conn, "/"); + set_conn_connectpath(conn, "/"); - if (!smbd_vfs_init(&conn)) { + if (!smbd_vfs_init(conn)) { DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n")); - conn_free_internal( &conn ); + conn_free_internal( conn ); return NULL; } @@ -4293,20 +4292,20 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) ZERO_STRUCT( fh ); finfo.fnum = -1; - finfo.conn = &conn; + finfo.conn = conn; finfo.fh = &fh; finfo.fh->fd = -1; finfo.fsp_name = CONST_DISCARD(char *,fname); if (!NT_STATUS_IS_OK(posix_fget_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); - conn_free_internal( &conn ); + conn_free_internal( conn ); return NULL; } ret_sd = dup_sec_desc( ctx, psd ); - conn_free_internal( &conn ); + conn_free_internal( conn ); return ret_sd; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 33b2cb26c1..a405ffc9bc 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -529,12 +529,12 @@ static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, f char *fuser, *found_username; NTSTATUS result; - if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S", + if (!(fuser = talloc_string_sub(conn, lp_force_user(snum), "%S", lp_servicename(snum)))) { return NT_STATUS_NO_MEMORY; } - result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest, + result = create_token_from_username(conn, fuser, vuser_is_guest, &conn->uid, &conn->gid, &found_username, &conn->nt_user_token); if (!NT_STATUS_IS_OK(result)) { @@ -697,7 +697,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *status = NT_STATUS_NO_SUCH_USER; return NULL; } - status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, + status2 = create_token_from_username(conn, pass->pw_name, True, &conn->uid, &conn->gid, &found_username, &conn->nt_user_token); @@ -757,7 +757,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } pass = Get_Pwnam_alloc(talloc_tos(), user); - status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, + status2 = create_token_from_username(conn, pass->pw_name, True, &conn->uid, &conn->gid, &found_username, &conn->nt_user_token); @@ -903,7 +903,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, sid_string_dbg(sid))); continue; } - if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups, + if (!add_gid_to_array_unique(conn, gid, &conn->groups, &conn->ngroups)) { DEBUG(0, ("add_gid_to_array_unique failed\n")); conn_free(conn); @@ -1017,7 +1017,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } if ((!conn->printer) && (!conn->ipc)) { - conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(), + conn->notify_ctx = notify_init(conn, server_id_self(), smbd_messaging_context(), smbd_event_context(), conn); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e7157d02ec..4d60eecda9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7542,7 +7542,7 @@ void reply_trans2(struct smb_request *req) } } - if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) { + if ((state = TALLOC_P(conn, struct trans_state)) == NULL) { DEBUG(0, ("talloc failed\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtrans2); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 33a3a43aa4..1e137dd908 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -177,7 +177,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) goto fail; } - handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct); + handle = TALLOC_ZERO_P(conn, vfs_handle_struct); if (!handle) { DEBUG(0,("TALLOC_ZERO() failed!\n")); goto fail; @@ -185,7 +185,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops)); handle->conn = conn; if (module_param) { - handle->param = talloc_strdup(conn->mem_ctx, module_param); + handle->param = talloc_strdup(conn, module_param); } DLIST_ADD(conn->vfs_handles, handle); @@ -232,7 +232,7 @@ void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, } ext = (struct vfs_fsp_data *)TALLOC_ZERO( - handle->conn->mem_ctx, sizeof(struct vfs_fsp_data) + ext_size); + handle->conn, sizeof(struct vfs_fsp_data) + ext_size); if (ext == NULL) { return NULL; } -- cgit From 768c0d6b22f85ff9fe34922e30a822c69e1d5bd7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 May 2008 12:45:12 +0200 Subject: Fix dfs_Enum: In form_junctions, correctly check for malloc failure (This used to be commit 1b1614c3261e1e93a2cad1f1063e28cbbb13f434) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 14062e129d..e321a8c8e4 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1459,7 +1459,7 @@ static int form_junctions(TALLOC_CTX *ctx, */ jucn[cnt].service_name = talloc_strdup(ctx,service_name); jucn[cnt].volume_name = talloc_strdup(ctx, ""); - if (!jucn[cnt].service_name || jucn[cnt].volume_name) { + if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { goto out; } jucn[cnt].referral_count = 1; -- cgit From 8dd53811d57da9a079f81e1f742f803131239b09 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 May 2008 14:43:57 +0200 Subject: Fix allocation of conn->vuid_cache entries With the old code, if more than VUID_CACHE_SIZE elements were used all new entries ended up in slot 0. With this checkin we do cycle. Jeremy, please revert if the old behaviour was intentional (This used to be commit 50c891d3dfb75c9f607f7ad2a578aa3ba5d91988) --- source3/smbd/uid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index ffa643a8f5..343a0cf490 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -123,9 +123,9 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) return False; } - i = conn->vuid_cache.entries % VUID_CACHE_SIZE; - if (conn->vuid_cache.entries < VUID_CACHE_SIZE) - conn->vuid_cache.entries++; + i = conn->vuid_cache.entries; + conn->vuid_cache.entries = + (conn->vuid_cache.entries + 1) % VUID_CACHE_SIZE; ent = &conn->vuid_cache.array[i]; ent->vuid = vuser->vuid; -- cgit From a529b2e1c3d5bc51dc0b17331bdc1c14481a12de Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 May 2008 14:53:49 +0200 Subject: Second half of 50c891d3: Correctly clear the vuid cache (This used to be commit 0aea404b0a83736ba2884cc7cf00cd797aab1f56) --- source3/smbd/conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index af18e905c0..ce0705377f 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -237,7 +237,7 @@ void conn_clear_vuid_cache(uint16 vuid) conn->vuid = UID_FIELD_INVALID; } - for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { + for (i=0; ivuid_cache.array[i].vuid == vuid) { struct vuid_cache_entry *ent = &conn->vuid_cache.array[i]; ent->vuid = UID_FIELD_INVALID; -- cgit From 58c54eb91f0490096c980a4f7aec323953813d64 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 May 2008 15:06:30 +0200 Subject: Revert "Second half of 50c891d3: Correctly clear the vuid cache" This reverts commit 0aea404b0a83736ba2884cc7cf00cd797aab1f56. (This used to be commit fa39f47f5fc2df0f1a59705e30a799518c353b45) --- source3/smbd/conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index ce0705377f..af18e905c0 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -237,7 +237,7 @@ void conn_clear_vuid_cache(uint16 vuid) conn->vuid = UID_FIELD_INVALID; } - for (i=0; ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { if (conn->vuid_cache.array[i].vuid == vuid) { struct vuid_cache_entry *ent = &conn->vuid_cache.array[i]; ent->vuid = UID_FIELD_INVALID; -- cgit From 1a3f50559e06c9dc45556c2c52d68a23c05d7e41 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 May 2008 15:06:39 +0200 Subject: Revert "Fix allocation of conn->vuid_cache entries" This reverts commit 50c891d3dfb75c9f607f7ad2a578aa3ba5d91988. There's more to this code -- sorry for the spam (This used to be commit 6e0e0cb8dd6f57de36c041e2ba4b82feeb357ce8) --- source3/smbd/uid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 343a0cf490..ffa643a8f5 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -123,9 +123,9 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) return False; } - i = conn->vuid_cache.entries; - conn->vuid_cache.entries = - (conn->vuid_cache.entries + 1) % VUID_CACHE_SIZE; + i = conn->vuid_cache.entries % VUID_CACHE_SIZE; + if (conn->vuid_cache.entries < VUID_CACHE_SIZE) + conn->vuid_cache.entries++; ent = &conn->vuid_cache.array[i]; ent->vuid = vuser->vuid; -- cgit From 1b2bf00fb98417434f653ce869226887d97aaeb2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Apr 2008 12:47:55 +0200 Subject: Remove "homedir" from "struct user_struct" (This used to be commit 41f9afd62d8cc6067582d452f3d53a5c67253b69) --- source3/smbd/lanman.c | 14 ++++++++++++-- source3/smbd/password.c | 6 ------ 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 6fa4f9698d..be8aa58e7f 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3420,12 +3420,17 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, } if (uLevel == 11) { + const char *homedir = ""; + if (vuser != NULL) { + homedir = pdb_get_homedir( + vuser->server_info->sam_account); + } /* modelled after NTAS 3.51 reply */ SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - strlcpy(p2, vuser && vuser->homedir ? vuser->homedir : "",PTR_DIFF(endp,p2)); + strlcpy(p2, homedir, PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3471,12 +3476,17 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, } if (uLevel == 1 || uLevel == 2) { + const char *homedir = ""; + if (vuser != NULL) { + homedir = pdb_get_homedir( + vuser->server_info->sam_account); + } memset(p+22,' ',16); /* password */ SIVALS(p,38,-1); /* password age */ SSVAL(p,42, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - strlcpy(p2, vuser && vuser->homedir ? vuser->homedir : "",PTR_DIFF(endp,p2)); + strlcpy(p2, homedir, PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 80eba562c5..a7e462a0ca 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -268,9 +268,6 @@ int register_existing_vuid(uint16 vuid, pdb_get_fullname(server_info->sam_account)); { - /* Keep the homedir handy */ - const char *homedir = - pdb_get_homedir(server_info->sam_account); const char *logon_script = pdb_get_logon_script(server_info->sam_account); @@ -294,9 +291,6 @@ int register_existing_vuid(uint16 vuid, } } - if (homedir) { - vuser->homedir = homedir; - } if (logon_script) { vuser->logon_script = logon_script; } -- cgit From 2b3d03d6f16e4110d0000cbb10a087cef2ce9e44 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Apr 2008 13:23:47 +0200 Subject: Remove unix_homedir from struct user_struct This makes pdb_get_unix_homedir unused. I wonder if that was ever really used... (This used to be commit 36bfd32f1ff878e827db91e9bf233719ecca5b01) --- source3/smbd/password.c | 72 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a7e462a0ca..74fa645c13 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -201,6 +201,37 @@ int register_initial_vuid(void) return vuser->vuid; } +static int register_homes_share(const char *username) +{ + int result; + struct passwd *pwd; + + result = lp_servicenumber(username); + if (result != -1) { + DEBUG(3, ("Using static (or previously created) service for " + "user '%s'; path = '%s'\n", username, + lp_pathname(result))); + return result; + } + + pwd = getpwnam_alloc(talloc_tos(), username); + + if ((pwd == NULL) || (pwd->pw_dir[0] == '\0')) { + DEBUG(3, ("No home directory defined for user '%s'\n", + username)); + TALLOC_FREE(pwd); + return -1; + } + + DEBUG(3, ("Adding homes service for user '%s' using home directory: " + "'%s'\n", username, pwd->pw_dir)); + + result = add_home_service(username, username, pwd->pw_dir); + + TALLOC_FREE(pwd); + return result; +} + /** * register that a valid login has been performed, establish 'session'. * @param server_info The token returned from the authentication process. @@ -271,26 +302,6 @@ int register_existing_vuid(uint16 vuid, const char *logon_script = pdb_get_logon_script(server_info->sam_account); - if (!IS_SAM_DEFAULT(server_info->sam_account, - PDB_UNIXHOMEDIR)) { - const char *unix_homedir = - pdb_get_unix_homedir(server_info->sam_account); - if (unix_homedir) { - vuser->unix_homedir = unix_homedir; - } - } else { - struct passwd *passwd = - getpwnam_alloc(vuser, vuser->user.unix_name); - if (passwd) { - vuser->unix_homedir = passwd->pw_dir; - /* Ensure that the unix_homedir now - * belongs to vuser, so it goes away - * with it, not with passwd below: */ - talloc_steal(vuser, vuser->unix_homedir); - TALLOC_FREE(passwd); - } - } - if (logon_script) { vuser->logon_script = logon_script; } @@ -336,23 +347,10 @@ int register_existing_vuid(uint16 vuid, If a share exists by this name (autoloaded or not) reuse it . */ vuser->homes_snum = -1; - if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { - int servicenumber = lp_servicenumber(vuser->user.unix_name); - if ( servicenumber == -1 ) { - DEBUG(3, ("Adding homes service for user '%s' using " - "home directory: '%s'\n", - vuser->user.unix_name, vuser->unix_homedir)); - vuser->homes_snum = - add_home_service(vuser->user.unix_name, - vuser->user.unix_name, - vuser->unix_homedir); - } else { - DEBUG(3, ("Using static (or previously created) " - "service for user '%s'; path = '%s'\n", - vuser->user.unix_name, - lp_pathname(servicenumber) )); - vuser->homes_snum = servicenumber; - } + + if (!vuser->guest) { + vuser->homes_snum = register_homes_share( + vuser->user.unix_name); } if (srv_is_signing_negotiated() && !vuser->guest && -- cgit From faa5e8e12c58376db0323a4e4855454ed53dcc00 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Apr 2008 13:28:40 +0200 Subject: Remove "logon_script" from "struct user_struct" (This used to be commit b36fd84186a656f86e4cfb9166fc0ecbffb422cb) --- source3/smbd/lanman.c | 16 ++++++++-------- source3/smbd/password.c | 8 -------- 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index be8aa58e7f..39d49334e0 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3476,17 +3476,14 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, } if (uLevel == 1 || uLevel == 2) { - const char *homedir = ""; - if (vuser != NULL) { - homedir = pdb_get_homedir( - vuser->server_info->sam_account); - } memset(p+22,' ',16); /* password */ SIVALS(p,38,-1); /* password age */ SSVAL(p,42, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - strlcpy(p2, homedir, PTR_DIFF(endp,p2)); + strlcpy(p2, vuser ? pdb_get_homedir( + vuser->server_info->sam_account) : "", + PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3495,7 +3492,9 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, *p2++ = 0; SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ - strlcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "",PTR_DIFF(endp,p2)); + strlcpy(p2, vuser ? pdb_get_logon_script( + vuser->server_info->sam_account) : "", + PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3648,7 +3647,8 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, } PACKS(&desc,"z",lp_workgroup());/* domain */ - PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */ + PACKS(&desc,"z", vuser ? pdb_get_logon_script( + vuser->server_info->sam_account) : ""); /* script path */ PACKI(&desc,"D",0x00000000); /* reserved */ } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 74fa645c13..124bc315fa 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -298,14 +298,6 @@ int register_existing_vuid(uint16 vuid, fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); - { - const char *logon_script = - pdb_get_logon_script(server_info->sam_account); - - if (logon_script) { - vuser->logon_script = logon_script; - } - } vuser->session_key = session_key; DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", -- cgit From bb3755968f5e953340edfb0b71997dddc11badb9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Apr 2008 13:35:00 +0200 Subject: Remove "nt_user_token" from "struct user_struct" (This used to be commit 51d5d512f28eadc74eced43e5e7f4e5bdff3ff69) --- source3/smbd/password.c | 4 +--- source3/smbd/service.c | 6 +++--- source3/smbd/uid.c | 14 +++++++------- 3 files changed, 11 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 124bc315fa..2636438d5d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -310,9 +310,7 @@ int register_existing_vuid(uint16 vuid, "Real name: %s\n", vuser->user.unix_name, vuser->user.full_name)); - if (server_info->ptok) { - vuser->nt_user_token = dup_nt_token(vuser, server_info->ptok); - } else { + if (!server_info->ptok) { DEBUG(1, ("register_existing_vuid: server_info does not " "contain a user_token - cannot continue\n")); goto fail; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a405ffc9bc..a286e561c7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -725,7 +725,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } } else { if (!user_ok_token(vuser->user.unix_name, - vuser->nt_user_token, snum)) { + vuser->server_info->ptok, snum)) { DEBUG(2, ("user '%s' (from session setup) not " "permitted to access this share " "(%s)\n", vuser->user.unix_name, @@ -861,7 +861,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * group. vuser has a token to copy */ conn->nt_user_token = dup_nt_token( - NULL, vuser->nt_user_token); + NULL, vuser->server_info->ptok); if (conn->nt_user_token == NULL) { DEBUG(0, ("dup_nt_token failed\n")); conn_free(conn); @@ -948,7 +948,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, bool can_write = False; NT_USER_TOKEN *token = conn->nt_user_token ? conn->nt_user_token : - (vuser ? vuser->nt_user_token : NULL); + (vuser ? vuser->server_info->ptok : NULL); /* * I don't believe this can happen. But the diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index ffa643a8f5..866f954436 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -97,15 +97,15 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) } } - if (!user_ok_token(vuser->user.unix_name, vuser->nt_user_token, snum)) + if (!user_ok_token(vuser->user.unix_name, vuser->server_info->ptok, + snum)) return(False); - readonly_share = is_share_read_only_for_token(vuser->user.unix_name, - vuser->nt_user_token, - SNUM(conn)); + readonly_share = is_share_read_only_for_token( + vuser->user.unix_name, vuser->server_info->ptok, SNUM(conn)); token = conn->nt_user_token ? - conn->nt_user_token : vuser->nt_user_token; + conn->nt_user_token : vuser->server_info->ptok; if (!readonly_share && !share_access_check(token, lp_servicename(snum), @@ -132,7 +132,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->read_only = readonly_share; ent->admin_user = token_contains_name_in_list( - vuser->user.unix_name, NULL, vuser->nt_user_token, + vuser->user.unix_name, NULL, vuser->server_info->ptok, lp_admin_users(SNUM(conn))); conn->read_only = ent->read_only; @@ -204,7 +204,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) gid = vuser->gid; num_groups = vuser->n_groups; group_list = vuser->groups; - token = vuser->nt_user_token; + token = vuser->server_info->ptok; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " "share %s.\n",vuid, lp_servicename(snum) )); -- cgit From c6d209f8342d56adc52a6c8ab99a4a2e17d409b2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Apr 2008 13:43:10 +0200 Subject: Remove the unix token info from "struct user_struct" (This used to be commit aa2299d42adf4d27e707ac755e07be70d0af1bb4) --- source3/smbd/lanman.c | 10 ++++++---- source3/smbd/password.c | 26 ++++---------------------- source3/smbd/service.c | 4 ++-- source3/smbd/session.c | 4 ++-- source3/smbd/uid.c | 10 +++++----- 5 files changed, 19 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 39d49334e0..7ba4b64477 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3338,8 +3338,9 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); if(vuser != NULL) { - DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, - vuser->user.unix_name)); + DEBUG(3,(" Username of UID %d is %s\n", + (int)vuser->server_info->uid, + vuser->user.unix_name)); } if (!str1 || !str2 || !UserName || !p) { @@ -3589,8 +3590,9 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, } if(vuser != NULL) { - DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, - vuser->user.unix_name)); + DEBUG(3,(" Username of UID %d is %s\n", + (int)vuser->server_info->uid, + vuser->user.unix_name)); } uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2636438d5d..c5c0245444 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -269,24 +269,6 @@ int register_existing_vuid(uint16 vuid, talloc_steal(vuser, vuser->server_info); - /* the next functions should be done by a SID mapping system (SMS) as - * the new real sam db won't have reference to unix uids or gids - */ - - vuser->uid = server_info->uid; - vuser->gid = server_info->gid; - - vuser->n_groups = server_info->n_groups; - if (vuser->n_groups) { - if (!(vuser->groups = (gid_t *)talloc_memdup(vuser, - server_info->groups, - sizeof(gid_t)*vuser->n_groups))) { - DEBUG(0,("register_existing_vuid: " - "failed to talloc_memdup vuser->groups\n")); - goto fail; - } - } - vuser->guest = server_info->guest; fstrcpy(vuser->user.unix_name, server_info->unix_name); @@ -301,8 +283,8 @@ int register_existing_vuid(uint16 vuid, vuser->session_key = session_key; DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", - (unsigned int)vuser->uid, - (unsigned int)vuser->gid, + (unsigned int)vuser->server_info->uid, + (unsigned int)vuser->server_info->gid, vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest )); @@ -317,8 +299,8 @@ int register_existing_vuid(uint16 vuid, } DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, " - "and will be vuid %u\n", - (int)vuser->uid,vuser->user.unix_name, vuser->vuid)); + "and will be vuid %u\n", (int)vuser->server_info->uid, + vuser->user.unix_name, vuser->vuid)); next_vuid++; num_validated_vuids++; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a286e561c7..43f8699e29 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -736,8 +736,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } } conn->vuid = vuser->vuid; - conn->uid = vuser->uid; - conn->gid = vuser->gid; + conn->uid = vuser->server_info->uid; + conn->gid = vuser->server_info->gid; string_set(&conn->user,vuser->user.unix_name); fstrcpy(user,vuser->user.unix_name); guest = vuser->guest; diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 000b2f5d9c..adfc4e300f 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -168,8 +168,8 @@ bool session_claim(user_struct *vuser) fstrcpy(sessionid.hostname, hostname); sessionid.id_num = i; /* Only valid for utmp sessions */ sessionid.pid = pid; - sessionid.uid = vuser->uid; - sessionid.gid = vuser->gid; + sessionid.uid = vuser->server_info->uid; + sessionid.gid = vuser->server_info->gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); fstrcpy(sessionid.ip_addr_str, client_addr(get_client_fd(),addr,sizeof(addr))); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 866f954436..0b87b93636 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -177,7 +177,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) return(True); } else if ((current_user.conn == conn) && (vuser != 0) && (current_user.vuid == vuid) && - (current_user.ut.uid == vuser->uid)) { + (current_user.ut.uid == vuser->server_info->uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); return(True); @@ -200,10 +200,10 @@ bool change_to_user(connection_struct *conn, uint16 vuid) num_groups = conn->ngroups; token = conn->nt_user_token; } else if (vuser) { - uid = conn->admin_user ? 0 : vuser->uid; - gid = vuser->gid; - num_groups = vuser->n_groups; - group_list = vuser->groups; + uid = conn->admin_user ? 0 : vuser->server_info->uid; + gid = vuser->server_info->gid; + num_groups = vuser->server_info->n_groups; + group_list = vuser->server_info->groups; token = vuser->server_info->ptok; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " -- cgit From 71ff1ba2deddf8fa12b034518e92e0a461871388 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 Apr 2008 13:45:58 +0200 Subject: Remove "guest" from "struct user_struct" (This used to be commit 570a6b80feb5b0dc23213ba936c721e766cd4818) --- source3/smbd/lanman.c | 2 +- source3/smbd/password.c | 7 +++---- source3/smbd/service.c | 6 +++--- source3/smbd/session.c | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7ba4b64477..a3687451d5 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4572,7 +4572,7 @@ void api_reply(connection_struct *conn, uint16 vuid, if (api_commands[i].auth_user && lp_restrict_anonymous()) { user_struct *user = get_valid_user_struct(vuid); - if (!user || user->guest) { + if (!user || user->server_info->guest) { reply_nterror(req, NT_STATUS_ACCESS_DENIED); return; } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index c5c0245444..6305180e6f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -269,7 +269,6 @@ int register_existing_vuid(uint16 vuid, talloc_steal(vuser, vuser->server_info); - vuser->guest = server_info->guest; fstrcpy(vuser->user.unix_name, server_info->unix_name); /* This is a potentially untrusted username */ @@ -286,7 +285,7 @@ int register_existing_vuid(uint16 vuid, (unsigned int)vuser->server_info->uid, (unsigned int)vuser->server_info->gid, vuser->user.unix_name, vuser->user.smb_name, - vuser->user.domain, vuser->guest )); + vuser->user.domain, vuser->server_info->guest )); DEBUG(3, ("register_existing_vuid: User name: %s\t" "Real name: %s\n", vuser->user.unix_name, @@ -320,12 +319,12 @@ int register_existing_vuid(uint16 vuid, vuser->homes_snum = -1; - if (!vuser->guest) { + if (!vuser->server_info->guest) { vuser->homes_snum = register_homes_share( vuser->user.unix_name); } - if (srv_is_signing_negotiated() && !vuser->guest && + if (srv_is_signing_negotiated() && !vuser->server_info->guest && !srv_signing_started()) { /* Try and turn on server signing on the first non-guest * sessionsetup. */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 43f8699e29..7b0fdc8976 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -714,7 +714,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, TALLOC_FREE(pass); DEBUG(3,("Guest only user %s\n",user)); } else if (vuser) { - if (vuser->guest) { + if (vuser->server_info->guest) { if (!lp_guest_ok(snum)) { DEBUG(2, ("guest user (from session setup) " "not permitted to access this share " @@ -740,7 +740,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->gid = vuser->server_info->gid; string_set(&conn->user,vuser->user.unix_name); fstrcpy(user,vuser->user.unix_name); - guest = vuser->guest; + guest = vuser->server_info->guest; } else if (lp_security() == SEC_SHARE) { NTSTATUS status2; char *found_username = NULL; @@ -825,7 +825,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, NTSTATUS status2; status2 = find_forced_user(conn, - (vuser != NULL) && vuser->guest, + (vuser != NULL) && vuser->server_info->guest, user); if (!NT_STATUS_IS_OK(status2)) { conn_free(conn); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index adfc4e300f..2b964d828f 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -75,7 +75,7 @@ bool session_claim(user_struct *vuser) /* don't register sessions for the guest user - its just too expensive to go through pam session code for browsing etc */ - if (vuser->guest) { + if (vuser->server_info->guest) { return True; } -- cgit From 82d2f07dae5d69fc1635a4ed326a2af6632d8a97 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 30 Apr 2008 14:26:16 +0200 Subject: Remove "session_key" from "struct user_struct" This one took a bit -- I hope I covered all data paths (This used to be commit 74c88a44422f88d6e2f2cdbfdfa0bafe0dbe06c4) --- source3/smbd/password.c | 7 +------ source3/smbd/sesssetup.c | 31 +++++++++++++------------------ 2 files changed, 14 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 6305180e6f..5e2e713d43 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -119,8 +119,6 @@ void invalidate_vuid(uint16 vuid) session_yield(vuser); - data_blob_free(&vuser->session_key); - if (vuser->auth_ntlmssp_state) { auth_ntlmssp_end(&vuser->auth_ntlmssp_state); } @@ -252,7 +250,6 @@ static int register_homes_share(const char *username) int register_existing_vuid(uint16 vuid, auth_serversupplied_info *server_info, - DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name) { @@ -279,8 +276,6 @@ int register_existing_vuid(uint16 vuid, fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); - vuser->session_key = session_key; - DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->server_info->uid, (unsigned int)vuser->server_info->gid, @@ -328,7 +323,7 @@ int register_existing_vuid(uint16 vuid, !srv_signing_started()) { /* Try and turn on server signing on the first non-guest * sessionsetup. */ - srv_set_signing(vuser->session_key, response_blob); + srv_set_signing(vuser->server_info->user_session_key, response_blob); } /* fill in the current_user_info struct */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 33a54dd0de..99bf0dcbb9 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -560,9 +560,13 @@ static void reply_spnego_kerberos(struct smb_request *req, if (!is_partial_auth_vuid(sess_vuid)) { sess_vuid = register_initial_vuid(); } + + data_blob_free(&server_info->user_session_key); + server_info->user_session_key = session_key; + session_key = data_blob_null; + sess_vuid = register_existing_vuid(sess_vuid, server_info, - session_key, nullblob, client); @@ -573,7 +577,6 @@ static void reply_spnego_kerberos(struct smb_request *req, if (sess_vuid == UID_FIELD_INVALID ) { ret = NT_STATUS_LOGON_FAILURE; - data_blob_free(&session_key); } else { /* current_user_info is changed on new vuid */ reload_services( True ); @@ -649,14 +652,19 @@ static void reply_spnego_ntlmssp(struct smb_request *req, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); if (!is_partial_auth_vuid(vuid)) { - data_blob_free(&session_key); nt_status = NT_STATUS_LOGON_FAILURE; goto out; } + + data_blob_free(&server_info->user_session_key); + server_info->user_session_key = + data_blob( + (*auth_ntlmssp_state)->ntlmssp_state->session_key.data, + (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); + /* register_existing_vuid keeps the server info */ if (register_existing_vuid(vuid, - server_info, - session_key, nullblob, + server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user) != vuid) { data_blob_free(&session_key); @@ -1398,8 +1406,6 @@ void reply_sesssetup_and_X(struct smb_request *req) bool doencrypt = global_encrypted_passwords_negotiated; - DATA_BLOB session_key; - START_PROFILE(SMBsesssetupX); ZERO_STRUCT(lm_resp); @@ -1747,13 +1753,6 @@ void reply_sesssetup_and_X(struct smb_request *req) return; } - if (server_info->user_session_key.data) { - session_key = data_blob(server_info->user_session_key.data, - server_info->user_session_key.length); - } else { - session_key = data_blob_null; - } - data_blob_clear_free(&plaintext_password); /* it's ok - setup a reply */ @@ -1772,7 +1771,6 @@ void reply_sesssetup_and_X(struct smb_request *req) if (lp_security() == SEC_SHARE) { sess_vuid = UID_FIELD_INVALID; - data_blob_free(&session_key); TALLOC_FREE(server_info); } else { /* Ignore the initial vuid. */ @@ -1780,7 +1778,6 @@ void reply_sesssetup_and_X(struct smb_request *req) if (sess_vuid == UID_FIELD_INVALID) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); - data_blob_free(&session_key); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); END_PROFILE(SMBsesssetupX); @@ -1789,13 +1786,11 @@ void reply_sesssetup_and_X(struct smb_request *req) /* register_existing_vuid keeps the server info */ sess_vuid = register_existing_vuid(sess_vuid, server_info, - session_key, nt_resp.data ? nt_resp : lm_resp, sub_user); if (sess_vuid == UID_FIELD_INVALID) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); - data_blob_free(&session_key); reply_nterror(req, nt_status_squash( NT_STATUS_LOGON_FAILURE)); END_PROFILE(SMBsesssetupX); -- cgit From 0636236eec5e73b08b28511ea6dc27d20aa35629 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 30 Apr 2008 12:58:40 +0200 Subject: Fix typo (This used to be commit 8047a1991a09191fec254815f3bfc85a2c36674a) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 99bf0dcbb9..b9219ab302 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -442,7 +442,7 @@ static void reply_spnego_kerberos(struct smb_request *req, if (pw) { /* if a real user check pam account restrictions */ /* only really perfomed if "obey pam restriction" is true */ - /* do this before an eventual mappign to guest occurs */ + /* do this before an eventual mapping to guest occurs */ ret = smb_pam_accountcheck(pw->pw_name); if ( !NT_STATUS_IS_OK(ret)) { DEBUG(1,("PAM account restriction " -- cgit From bec1dfab27be3db888eeb451b4547f16e08e93c3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 30 Apr 2008 17:42:39 +0200 Subject: Remove "userdom_struct user" from "struct user_struct" (This used to be commit 420de035237bb08bc470c9eb820f3da2edaa6805) --- source3/smbd/lanman.c | 12 ++++++++---- source3/smbd/password.c | 49 +++++++++++++++++++++++++------------------------ source3/smbd/process.c | 8 +++++++- source3/smbd/service.c | 9 +++++---- source3/smbd/session.c | 2 +- source3/smbd/uid.c | 11 +++++++---- 6 files changed, 53 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a3687451d5..a233893482 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3340,7 +3340,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->server_info->uid, - vuser->user.unix_name)); + vuser->server_info->unix_name)); } if (!str1 || !str2 || !UserName || !p) { @@ -3413,7 +3413,9 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2)); + strlcpy(p2,((vuser != NULL) + ? pdb_get_fullname(vuser->server_info->sam_account) + : UserName),PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3503,7 +3505,9 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, if (uLevel == 2) { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2)); + strlcpy(p2,((vuser != NULL) + ? pdb_get_fullname(vuser->server_info->sam_account) + : UserName),PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3592,7 +3596,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->server_info->uid, - vuser->user.unix_name)); + vuser->server_info->unix_name)); } uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 5e2e713d43..a872ea2b48 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -253,40 +253,36 @@ int register_existing_vuid(uint16 vuid, DATA_BLOB response_blob, const char *smb_name) { - user_struct *vuser = get_partial_auth_user_struct(vuid); + fstring tmp; + user_struct *vuser; + + vuser = get_partial_auth_user_struct(vuid); if (!vuser) { goto fail; } /* Use this to keep tabs on all our info from the authentication */ - vuser->server_info = server_info; - - /* Ensure that the server_info will disappear with - * the vuser it is now attached to */ - - talloc_steal(vuser, vuser->server_info); - - fstrcpy(vuser->user.unix_name, server_info->unix_name); + vuser->server_info = talloc_move(vuser, &server_info); /* This is a potentially untrusted username */ - alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", - sizeof(vuser->user.smb_name)); + alpha_strcpy(tmp, smb_name, ". _-$", sizeof(tmp)); - fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); - fstrcpy(vuser->user.full_name, - pdb_get_fullname(server_info->sam_account)); + vuser->server_info->sanitized_username = talloc_strdup( + server_info, tmp); DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", - (unsigned int)vuser->server_info->uid, - (unsigned int)vuser->server_info->gid, - vuser->user.unix_name, vuser->user.smb_name, - vuser->user.domain, vuser->server_info->guest )); + (unsigned int)vuser->server_info->uid, + (unsigned int)vuser->server_info->gid, + vuser->server_info->unix_name, + vuser->server_info->sanitized_username, + pdb_get_domain(vuser->server_info->sam_account), + vuser->server_info->guest )); DEBUG(3, ("register_existing_vuid: User name: %s\t" - "Real name: %s\n", vuser->user.unix_name, - vuser->user.full_name)); + "Real name: %s\n", vuser->server_info->unix_name, + pdb_get_fullname(vuser->server_info->sam_account))); - if (!server_info->ptok) { + if (!vuser->server_info->ptok) { DEBUG(1, ("register_existing_vuid: server_info does not " "contain a user_token - cannot continue\n")); goto fail; @@ -294,7 +290,7 @@ int register_existing_vuid(uint16 vuid, DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, " "and will be vuid %u\n", (int)vuser->server_info->uid, - vuser->user.unix_name, vuser->vuid)); + vuser->server_info->unix_name, vuser->vuid)); next_vuid++; num_validated_vuids++; @@ -316,7 +312,7 @@ int register_existing_vuid(uint16 vuid, if (!vuser->server_info->guest) { vuser->homes_snum = register_homes_share( - vuser->user.unix_name); + vuser->server_info->unix_name); } if (srv_is_signing_negotiated() && !vuser->server_info->guest && @@ -327,7 +323,12 @@ int register_existing_vuid(uint16 vuid, } /* fill in the current_user_info struct */ - set_current_user_info( &vuser->user ); + set_current_user_info( + vuser->server_info->sanitized_username, + vuser->server_info->unix_name, + pdb_get_fullname(vuser->server_info->sam_account), + pdb_get_domain(vuser->server_info->sam_account)); + return vuser->vuid; fail: diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5946989ae7..ab737a89a7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1387,7 +1387,13 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in if(session_tag != UID_FIELD_INVALID) { vuser = get_valid_user_struct(session_tag); if (vuser) { - set_current_user_info(&vuser->user); + set_current_user_info( + vuser->server_info->sanitized_username, + vuser->server_info->unix_name, + pdb_get_fullname(vuser->server_info + ->sam_account), + pdb_get_domain(vuser->server_info + ->sam_account)); } } } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 7b0fdc8976..ff69fc4029 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -724,11 +724,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } } else { - if (!user_ok_token(vuser->user.unix_name, + if (!user_ok_token(vuser->server_info->unix_name, vuser->server_info->ptok, snum)) { DEBUG(2, ("user '%s' (from session setup) not " "permitted to access this share " - "(%s)\n", vuser->user.unix_name, + "(%s)\n", + vuser->server_info->unix_name, lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -738,8 +739,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->vuid = vuser->vuid; conn->uid = vuser->server_info->uid; conn->gid = vuser->server_info->gid; - string_set(&conn->user,vuser->user.unix_name); - fstrcpy(user,vuser->user.unix_name); + string_set(&conn->user,vuser->server_info->unix_name); + fstrcpy(user,vuser->server_info->unix_name); guest = vuser->server_info->guest; } else if (lp_security() == SEC_SHARE) { NTSTATUS status2; diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 2b964d828f..5e5a184efa 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -164,7 +164,7 @@ bool session_claim(user_struct *vuser) hostname = client_addr(get_client_fd(),addr,sizeof(addr)); } - fstrcpy(sessionid.username, vuser->user.unix_name); + fstrcpy(sessionid.username, vuser->server_info->unix_name); fstrcpy(sessionid.hostname, hostname); sessionid.id_num = i; /* Only valid for utmp sessions */ sessionid.pid = pid; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 0b87b93636..3779c3f608 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -97,12 +97,14 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) } } - if (!user_ok_token(vuser->user.unix_name, vuser->server_info->ptok, + if (!user_ok_token(vuser->server_info->unix_name, + vuser->server_info->ptok, snum)) return(False); readonly_share = is_share_read_only_for_token( - vuser->user.unix_name, vuser->server_info->ptok, SNUM(conn)); + vuser->server_info->unix_name, vuser->server_info->ptok, + SNUM(conn)); token = conn->nt_user_token ? conn->nt_user_token : vuser->server_info->ptok; @@ -132,7 +134,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->read_only = readonly_share; ent->admin_user = token_contains_name_in_list( - vuser->user.unix_name, NULL, vuser->server_info->ptok, + vuser->server_info->unix_name, NULL, vuser->server_info->ptok, lp_admin_users(SNUM(conn))); conn->read_only = ent->read_only; @@ -188,7 +190,8 @@ bool change_to_user(connection_struct *conn, uint16 vuid) if ((vuser) && !check_user_ok(conn, vuser, snum)) { DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) " "not permitted access to share %s.\n", - vuser->user.smb_name, vuser->user.unix_name, vuid, + vuser->server_info->sanitized_username, + vuser->server_info->unix_name, vuid, lp_servicename(snum))); return False; } -- cgit From 89ac43d49859ef9169283341f2917e9100820bb4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 14:16:06 +0200 Subject: Remove some unused code (This used to be commit 87383a4605ab99d32fccae7793dc5292b8f3e25b) --- source3/smbd/uid.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 3779c3f608..78dff8ffee 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -22,29 +22,6 @@ /* what user is current? */ extern struct current_user current_user; -/**************************************************************************** - Iterator functions for getting all gid's from current_user. -****************************************************************************/ - -gid_t get_current_user_gid_first(int *piterator) -{ - *piterator = 0; - return current_user.ut.gid; -} - -gid_t get_current_user_gid_next(int *piterator) -{ - gid_t ret; - - if (!current_user.ut.groups || *piterator >= current_user.ut.ngroups) { - return (gid_t)-1; - } - - ret = current_user.ut.groups[*piterator]; - (*piterator) += 1; - return ret; -} - /**************************************************************************** Become the guest user without changing the security context stack. ****************************************************************************/ -- cgit From 53802412512f77082f22c279636c9a943afc77eb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 15:41:20 +0200 Subject: Fix a memleak introduced after refactoring "struct user_struct" (This used to be commit e70b5b762234f1733f150bdfbda7b208a8139990) --- source3/smbd/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a872ea2b48..673a1a01c1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -268,7 +268,7 @@ int register_existing_vuid(uint16 vuid, alpha_strcpy(tmp, smb_name, ". _-$", sizeof(tmp)); vuser->server_info->sanitized_username = talloc_strdup( - server_info, tmp); + vuser->server_info, tmp); DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->server_info->uid, -- cgit From 193b63f326d31907bdc4486fadec4a7f4dcb0bac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 14:20:15 +0200 Subject: Use talloc_stackframe() in find_forced_group (This used to be commit 27a9bbc645416265eebdfc866925855021bd407c) --- source3/smbd/service.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ff69fc4029..d57156762f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -561,7 +561,7 @@ static NTSTATUS find_forced_group(bool force_user, gid_t *pgid) { NTSTATUS result = NT_STATUS_NO_SUCH_GROUP; - TALLOC_CTX *mem_ctx; + TALLOC_CTX *frame = talloc_stackframe(); DOM_SID group_sid; enum lsa_SidType type; char *groupname; @@ -571,13 +571,7 @@ static NTSTATUS find_forced_group(bool force_user, ZERO_STRUCTP(pgroup_sid); *pgid = (gid_t)-1; - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { - DEBUG(0, ("talloc_new failed\n")); - return NT_STATUS_NO_MEMORY; - } - - groupname = talloc_strdup(mem_ctx, lp_force_group(snum)); + groupname = talloc_strdup(talloc_tos(), lp_force_group(snum)); if (groupname == NULL) { DEBUG(1, ("talloc_strdup failed\n")); result = NT_STATUS_NO_MEMORY; @@ -589,10 +583,10 @@ static NTSTATUS find_forced_group(bool force_user, groupname += 1; } - groupname = talloc_string_sub(mem_ctx, groupname, + groupname = talloc_string_sub(talloc_tos(), groupname, "%S", lp_servicename(snum)); - if (!lookup_name_smbconf(mem_ctx, groupname, + if (!lookup_name_smbconf(talloc_tos(), groupname, LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, NULL, NULL, &group_sid, &type)) { DEBUG(10, ("lookup_name_smbconf(%s) failed\n", @@ -641,7 +635,7 @@ static NTSTATUS find_forced_group(bool force_user, result = NT_STATUS_OK; done: - TALLOC_FREE(mem_ctx); + TALLOC_FREE(frame); return result; } -- cgit From 4f731150bdc4e7257e1fc87e6ea6944d33cb1e34 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 15:16:45 +0200 Subject: Use talloc_tos() for a temporary getpwnam_alloc in make_connection_snum (This used to be commit 1843ea64ab1df5ced5926aedbeb27c8320b0c70b) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d57156762f..f589f0644b 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -683,7 +683,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, char *found_username = NULL; guest = True; - pass = getpwnam_alloc(NULL, guestname); + pass = getpwnam_alloc(talloc_tos(), guestname); if (!pass) { DEBUG(0,("make_connection_snum: Invalid guest " "account %s??\n",guestname)); -- cgit From 64ddd381b74ca94e8ff8ae62d8f019a9b5290a80 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 17:37:00 +0200 Subject: Rename server_info->was_mapped to server_info->nss_token "nss_token" from my point of view much better reflects what this flag actually represents (This used to be commit b121a5acb2ef0bb3067d953b028696175432f10d) --- source3/smbd/sesssetup.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b9219ab302..9076949a81 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -530,9 +530,7 @@ static void reply_spnego_kerberos(struct smb_request *req, } } - if (username_was_mapped) { - server_info->was_mapped = username_was_mapped; - } + server_info->nss_token |= username_was_mapped; /* we need to build the token for the user. make_server_info_guest() already does this */ -- cgit From 00b2cdf75e9bea25034440054b4acd91a179c86d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 May 2008 18:09:07 -0700 Subject: Yay ! Remove a VFS entry. Removed the set_nt_acl() call, this can only be done via fset_nt_acl() using an open file/directory handle. I'd like to do the same with get_nt_acl() but am concerned about efficiency problems with "hide unreadable/hide unwritable" when doing a directory listing (this would mean opening every file in the dir on list). Moving closer to rationalizing the ACL model and maybe moving the POSIX calls into a posix_acl VFS module rather than having them as first class citizens of the VFS. Jeremy. (This used to be commit f487f742cb903a06fbf2be006ddc9ce9063339ed) --- source3/smbd/nttrans.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ec4126c1f7..362823d78a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -770,13 +770,7 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, security_info_sent &= ~DACL_SECURITY_INFORMATION; } - if (fsp->fh->fd != -1) { - status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd); - } - else { - status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, - security_info_sent, psd); - } + status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd); TALLOC_FREE(psd); -- cgit From 3f76504d92e0bde89472e569acd64494729778a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 May 2008 11:14:45 -0700 Subject: Remove a couple of uses of SMB_VFS_GET_NT_ACL(), use SMB_VFS_FGET_NT_ACL instead. I'd like to ultimately remove SMB_VFS_GET_NT_ACL. Jeremy. (This used to be commit 4221937b68e2414295279b27c5f12a80f826ed4b) --- source3/smbd/nttrans.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 362823d78a..bd34b5a361 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1612,14 +1612,8 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, if (!lp_nt_acl_support(SNUM(conn))) { status = get_null_nt_acl(talloc_tos(), &psd); } else { - if (fsp->fh->fd != -1) { - status = SMB_VFS_FGET_NT_ACL( - fsp, security_info_wanted, &psd); - } - else { - status = SMB_VFS_GET_NT_ACL( - conn, fsp->fsp_name, security_info_wanted, &psd); - } + status = SMB_VFS_FGET_NT_ACL( + fsp, security_info_wanted, &psd); } if (!NT_STATUS_IS_OK(status)) { -- cgit From 0283e95a7c20bb0aeedbdd0b657a1293e449a62d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 17:26:49 +0200 Subject: Add a mem_ctx argument to make_server_info_guest() (This used to be commit e4a9492967f3d2b64f27943f99414608e0c03d21) --- source3/smbd/sesssetup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9076949a81..0f0a0d5f31 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -45,7 +45,7 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { DEBUG(3,("No such user %s [%s] - using guest account\n", user, domain)); - status = make_server_info_guest(server_info); + status = make_server_info_guest(NULL, server_info); } } @@ -53,7 +53,7 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { DEBUG(3,("Registered username %s for guest access\n", user)); - status = make_server_info_guest(server_info); + status = make_server_info_guest(NULL, server_info); } } @@ -488,7 +488,7 @@ static void reply_spnego_kerberos(struct smb_request *req, reload_services(True); if ( map_domainuser_to_guest ) { - make_server_info_guest(&server_info); + make_server_info_guest(NULL, &server_info); } else if (logon_info) { /* pass the unmapped username here since map_username() will be called again from inside make_server_info_info3() */ -- cgit From 270a3f2a6f6674c0a854b513b756500a9edb3d21 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 17:48:22 +0200 Subject: Add create_connection_server_info() -- not used yet (This used to be commit 50bf075f7556fd09e0081175c31a5020a8eaf4d6) --- source3/smbd/service.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index f589f0644b..35a415b0ac 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -639,6 +639,82 @@ static NTSTATUS find_forced_group(bool force_user, return result; } +/**************************************************************************** + Create an auth_serversupplied_info structure for a connection_struct +****************************************************************************/ + +static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum, + struct auth_serversupplied_info *vuid_serverinfo, + DATA_BLOB password, + struct auth_serversupplied_info **presult) +{ + if (lp_guest_only(snum)) { + return make_server_info_guest(mem_ctx, presult); + } + + if (vuid_serverinfo != NULL) { + + struct auth_serversupplied_info *result; + + /* + * This is the normal security != share case where we have a + * valid vuid from the session setup. */ + + if (vuid_serverinfo->guest) { + if (!lp_guest_ok(snum)) { + DEBUG(2, ("guest user (from session setup) " + "not permitted to access this share " + "(%s)\n", lp_servicename(snum))); + return NT_STATUS_ACCESS_DENIED; + } + } else { + if (!user_ok_token(vuid_serverinfo->unix_name, + vuid_serverinfo->ptok, snum)) { + DEBUG(2, ("user '%s' (from session setup) not " + "permitted to access this share " + "(%s)\n", + vuid_serverinfo->unix_name, + lp_servicename(snum))); + return NT_STATUS_ACCESS_DENIED; + } + } + + result = copy_serverinfo(mem_ctx, vuid_serverinfo); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + + *presult = result; + return NT_STATUS_OK; + } + + if (lp_security() == SEC_SHARE) { + + fstring user; + bool guest; + + /* add the sharename as a possible user name if we + are in share mode security */ + + add_session_user(lp_servicename(snum)); + + /* shall we let them in? */ + + if (!authorise_login(snum,user,password,&guest)) { + DEBUG( 2, ( "Invalid username/password for [%s]\n", + lp_servicename(snum)) ); + return NT_STATUS_WRONG_PASSWORD; + } + + return make_serverinfo_from_username(mem_ctx, user, guest, + presult); + } + + DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); + return NT_STATUS_ACCESS_DENIED; +} + + /**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the connecting user if appropriate. -- cgit From 39a318aee4ca4114ce7cbb2f1af001a6035bf783 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 21:50:08 +0200 Subject: "status" -> "pstatus" in make_connection_snum (This used to be commit 3ce395e61e931a77c5d2f52f39c7e3f71a9605a9) --- source3/smbd/service.c | 80 ++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 42 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 35a415b0ac..40863fc55d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -723,7 +723,7 @@ static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum, static connection_struct *make_connection_snum(int snum, user_struct *vuser, DATA_BLOB password, const char *pdev, - NTSTATUS *status) + NTSTATUS *pstatus) { struct passwd *pass = NULL; bool guest = False; @@ -734,19 +734,20 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, int ret; char addr[INET6_ADDRSTRLEN]; bool on_err_call_dis_hook = false; + NTSTATUS status; *user = 0; fstrcpy(dev, pdev); SET_STAT_INVALID(st); - if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { + if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) { return NULL; } conn = conn_new(); if (!conn) { DEBUG(0,("Couldn't find free connection.\n")); - *status = NT_STATUS_INSUFFICIENT_RESOURCES; + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } @@ -755,7 +756,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (lp_guest_only(snum)) { const char *guestname = lp_guestaccount(); - NTSTATUS status2; char *found_username = NULL; guest = True; @@ -764,17 +764,17 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(0,("make_connection_snum: Invalid guest " "account %s??\n",guestname)); conn_free(conn); - *status = NT_STATUS_NO_SUCH_USER; + *pstatus = NT_STATUS_NO_SUCH_USER; return NULL; } - status2 = create_token_from_username(conn, pass->pw_name, True, - &conn->uid, &conn->gid, - &found_username, - &conn->nt_user_token); - if (!NT_STATUS_IS_OK(status2)) { + status = create_token_from_username(conn, pass->pw_name, True, + &conn->uid, &conn->gid, + &found_username, + &conn->nt_user_token); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pass); conn_free(conn); - *status = status2; + *pstatus = status; return NULL; } fstrcpy(user, found_username); @@ -790,7 +790,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, "not permitted to access this share " "(%s)\n", lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } } else { @@ -802,7 +802,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, vuser->server_info->unix_name, lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } } @@ -824,7 +824,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG( 2, ( "Invalid username/password for [%s]\n", lp_servicename(snum)) ); conn_free(conn); - *status = NT_STATUS_WRONG_PASSWORD; + *pstatus = NT_STATUS_WRONG_PASSWORD; return NULL; } pass = Get_Pwnam_alloc(talloc_tos(), user); @@ -835,7 +835,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, TALLOC_FREE(pass); if (!NT_STATUS_IS_OK(status2)) { conn_free(conn); - *status = status2; + *pstatus = status2; return NULL; } fstrcpy(user, found_username); @@ -845,7 +845,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } else { DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } @@ -893,14 +893,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if (*lp_force_user(snum)) { - NTSTATUS status2; - - status2 = find_forced_user(conn, + status = find_forced_user(conn, (vuser != NULL) && vuser->server_info->guest, user); - if (!NT_STATUS_IS_OK(status2)) { + if (!NT_STATUS_IS_OK(status)) { conn_free(conn); - *status = status2; + *pstatus = status; return NULL; } string_set(&conn->user,user); @@ -914,15 +912,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if (*lp_force_group(snum)) { - NTSTATUS status2; DOM_SID group_sid; - status2 = find_forced_group(conn->force_user, - snum, user, - &group_sid, &conn->gid); - if (!NT_STATUS_IS_OK(status2)) { + status = find_forced_group(conn->force_user, snum, user, + &group_sid, &conn->gid); + if (!NT_STATUS_IS_OK(status)) { conn_free(conn); - *status = status2; + *pstatus = status; return NULL; } @@ -936,7 +932,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (conn->nt_user_token == NULL) { DEBUG(0, ("dup_nt_token failed\n")); conn_free(conn); - *status = NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; return NULL; } } @@ -978,7 +974,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, &conn->ngroups)) { DEBUG(0, ("add_gid_to_array_unique failed\n")); conn_free(conn); - *status = NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; return NULL; } } @@ -993,14 +989,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, lp_pathname(snum)); if (!s) { conn_free(conn); - *status = NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; return NULL; } if (!set_conn_connectpath(conn,s)) { TALLOC_FREE(s); conn_free(conn); - *status = NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; return NULL; } DEBUG(3,("Connect path is '%s' for service [%s]\n",s, @@ -1033,7 +1029,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, "NT token.\n", lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } @@ -1051,7 +1047,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, "descriptor.\n", lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } else { conn->read_only = True; @@ -1064,7 +1060,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; + *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -1082,7 +1078,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, lp_servicename(snum), conn->connectpath)); conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; + *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } } @@ -1106,7 +1102,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(1, ("Max connections (%d) exceeded for %s\n", lp_max_connections(snum), lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_INSUFFICIENT_RESOURCES; + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } @@ -1116,7 +1112,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (!claim_connection(conn, lp_servicename(snum), 0)) { DEBUG(1, ("Could not store connections entry\n")); conn_free(conn); - *status = NT_STATUS_INTERNAL_DB_ERROR; + *pstatus = NT_STATUS_INTERNAL_DB_ERROR; return NULL; } @@ -1138,7 +1134,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, "connection\n", ret)); yield_connection(conn, lp_servicename(snum)); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } } @@ -1149,7 +1145,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(0,("Can't become connected user!\n")); yield_connection(conn, lp_servicename(snum)); conn_free(conn); - *status = NT_STATUS_LOGON_FAILURE; + *pstatus = NT_STATUS_LOGON_FAILURE; return NULL; } @@ -1172,7 +1168,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (ret != 0 && lp_preexec_close(snum)) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; goto err_root_exit; } } @@ -1196,7 +1192,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); - *status = NT_STATUS_UNSUCCESSFUL; + *pstatus = NT_STATUS_UNSUCCESSFUL; goto err_root_exit; } @@ -1220,7 +1216,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->connectpath, lp_servicename(snum), strerror(errno) )); } - *status = NT_STATUS_BAD_NETWORK_NAME; + *pstatus = NT_STATUS_BAD_NETWORK_NAME; goto err_root_exit; } -- cgit From f93e232535eb14d8f3862fff965adc544e70819f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 6 May 2008 22:12:04 +0200 Subject: Remove unused "force_group" from connection_struct (This used to be commit 03944f8d8934cff74e19fc036f7611c1491e0d57) --- source3/smbd/service.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 40863fc55d..e2715fa6d8 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -947,7 +947,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, &group_sid); } - conn->force_group = True; } if (conn->nt_user_token != NULL) { -- cgit From 90995202c0f64d2c379be26760d3bf8c122199b5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 12:20:18 +0200 Subject: Add "server_info" to connection_struct This will replace all the user identity stuff in connection_struct, for now it is just a source where the other fields in connection_struct are filled from. (This used to be commit 0f53f9e7db9f99f239c4d0950452d0e2cde2ae8b) --- source3/smbd/service.c | 120 ++++++++++--------------------------------------- 1 file changed, 23 insertions(+), 97 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e2715fa6d8..974af83932 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -725,18 +725,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, const char *pdev, NTSTATUS *pstatus) { - struct passwd *pass = NULL; - bool guest = False; connection_struct *conn; SMB_STRUCT_STAT st; - fstring user; fstring dev; int ret; char addr[INET6_ADDRSTRLEN]; bool on_err_call_dis_hook = false; NTSTATUS status; - *user = 0; fstrcpy(dev, pdev); SET_STAT_INVALID(st); @@ -754,102 +750,33 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->params->service = snum; conn->nt_user_token = NULL; + status = create_connection_server_info( + conn, snum, vuser ? vuser->server_info : NULL, password, + &conn->server_info); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("create_connection_server_info failed: %s\n", + nt_errstr(status))); + *pstatus = status; + conn_free(conn); + return NULL; + } + if (lp_guest_only(snum)) { - const char *guestname = lp_guestaccount(); - char *found_username = NULL; - - guest = True; - pass = getpwnam_alloc(talloc_tos(), guestname); - if (!pass) { - DEBUG(0,("make_connection_snum: Invalid guest " - "account %s??\n",guestname)); - conn_free(conn); - *pstatus = NT_STATUS_NO_SUCH_USER; - return NULL; - } - status = create_token_from_username(conn, pass->pw_name, True, - &conn->uid, &conn->gid, - &found_username, - &conn->nt_user_token); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(pass); - conn_free(conn); - *pstatus = status; - return NULL; - } - fstrcpy(user, found_username); - string_set(&conn->user,user); - conn->force_user = True; - TALLOC_FREE(found_username); - TALLOC_FREE(pass); - DEBUG(3,("Guest only user %s\n",user)); + string_set(&conn->user, conn->server_info->unix_name); + conn->force_user = true; + DEBUG(3,("Guest only user %s\n", conn->user)); } else if (vuser) { - if (vuser->server_info->guest) { - if (!lp_guest_ok(snum)) { - DEBUG(2, ("guest user (from session setup) " - "not permitted to access this share " - "(%s)\n", lp_servicename(snum))); - conn_free(conn); - *pstatus = NT_STATUS_ACCESS_DENIED; - return NULL; - } - } else { - if (!user_ok_token(vuser->server_info->unix_name, - vuser->server_info->ptok, snum)) { - DEBUG(2, ("user '%s' (from session setup) not " - "permitted to access this share " - "(%s)\n", - vuser->server_info->unix_name, - lp_servicename(snum))); - conn_free(conn); - *pstatus = NT_STATUS_ACCESS_DENIED; - return NULL; - } - } conn->vuid = vuser->vuid; conn->uid = vuser->server_info->uid; conn->gid = vuser->server_info->gid; string_set(&conn->user,vuser->server_info->unix_name); - fstrcpy(user,vuser->server_info->unix_name); - guest = vuser->server_info->guest; } else if (lp_security() == SEC_SHARE) { - NTSTATUS status2; - char *found_username = NULL; - - /* add it as a possible user name if we - are in share mode security */ - add_session_user(lp_servicename(snum)); - /* shall we let them in? */ - if (!authorise_login(snum,user,password,&guest)) { - DEBUG( 2, ( "Invalid username/password for [%s]\n", - lp_servicename(snum)) ); - conn_free(conn); - *pstatus = NT_STATUS_WRONG_PASSWORD; - return NULL; - } - pass = Get_Pwnam_alloc(talloc_tos(), user); - status2 = create_token_from_username(conn, pass->pw_name, True, - &conn->uid, &conn->gid, - &found_username, - &conn->nt_user_token); - TALLOC_FREE(pass); - if (!NT_STATUS_IS_OK(status2)) { - conn_free(conn); - *pstatus = status2; - return NULL; - } - fstrcpy(user, found_username); - string_set(&conn->user,user); - TALLOC_FREE(found_username); + string_set(&conn->user, conn->server_info->unix_name); conn->force_user = True; - } else { - DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); - conn_free(conn); - *pstatus = NT_STATUS_ACCESS_DENIED; - return NULL; } - add_session_user(user); + add_session_user(conn->user); safe_strcpy(conn->client_address, client_addr(get_client_fd(),addr,sizeof(addr)), @@ -881,7 +808,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->veto_oplock_list = NULL; conn->aio_write_behind_list = NULL; string_set(&conn->dirpath,""); - string_set(&conn->user,user); conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; @@ -895,15 +821,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_force_user(snum)) { status = find_forced_user(conn, (vuser != NULL) && vuser->server_info->guest, - user); + conn->user); if (!NT_STATUS_IS_OK(status)) { conn_free(conn); *pstatus = status; return NULL; } - string_set(&conn->user,user); conn->force_user = True; - DEBUG(3,("Forced user %s\n",user)); + DEBUG(3,("Forced user %s\n",conn->user)); } /* @@ -914,7 +839,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_force_group(snum)) { DOM_SID group_sid; - status = find_forced_group(conn->force_user, snum, user, + status = find_forced_group(conn->force_user, snum, + conn->user, &group_sid, &conn->gid); if (!NT_STATUS_IS_OK(status)) { conn_free(conn); @@ -1189,7 +1115,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, to allow any filesystems needing user credentials to initialize themselves. */ - if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), conn->user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); *pstatus = NT_STATUS_UNSUCCESSFUL; goto err_root_exit; @@ -1256,7 +1182,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->client_address ); dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(snum) ); - dbgtext( "initially as user %s ", user ); + dbgtext( "initially as user %s ", conn->user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)sys_getpid() ); } -- cgit From ca2580028744c8c9301487ffee87befdd94be383 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 12:42:36 +0200 Subject: Simplify make_connection_snum: Copy connection_struct info from server_info (This used to be commit 5aa3cdf355c179d89c2703f528919194ab084337) --- source3/smbd/service.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 974af83932..a95f756132 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -762,20 +762,16 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - if (lp_guest_only(snum)) { - string_set(&conn->user, conn->server_info->unix_name); + if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) { conn->force_user = true; - DEBUG(3,("Guest only user %s\n", conn->user)); - } else if (vuser) { - conn->vuid = vuser->vuid; - conn->uid = vuser->server_info->uid; - conn->gid = vuser->server_info->gid; - string_set(&conn->user,vuser->server_info->unix_name); - } else if (lp_security() == SEC_SHARE) { - string_set(&conn->user, conn->server_info->unix_name); - conn->force_user = True; } + conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; + + conn->uid = conn->server_info->uid; + conn->gid = conn->server_info->gid; + string_set(&conn->user, conn->server_info->unix_name); + add_session_user(conn->user); safe_strcpy(conn->client_address, @@ -819,16 +815,18 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if (*lp_force_user(snum)) { + fstring tmp; + fstrcpy(tmp, conn->user); status = find_forced_user(conn, (vuser != NULL) && vuser->server_info->guest, - conn->user); + tmp); if (!NT_STATUS_IS_OK(status)) { conn_free(conn); *pstatus = status; return NULL; } conn->force_user = True; - DEBUG(3,("Forced user %s\n",conn->user)); + DEBUG(3,("Forced user %s\n",tmp)); } /* -- cgit From ddcea20947fb3ca5ccd9e2a1e024ac8296dc4055 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 13:16:20 +0200 Subject: Replace find_forced_user by a direct call to make_serverinfo_from_username (This used to be commit 7991e6764b4187ba86802569dfdc5816e6137f78) --- source3/smbd/service.c | 63 +++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 37 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a95f756132..e3635d45db 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -523,31 +523,6 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } -static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username) -{ - int snum = conn->params->service; - char *fuser, *found_username; - NTSTATUS result; - - if (!(fuser = talloc_string_sub(conn, lp_force_user(snum), "%S", - lp_servicename(snum)))) { - return NT_STATUS_NO_MEMORY; - } - - result = create_token_from_username(conn, fuser, vuser_is_guest, - &conn->uid, &conn->gid, &found_username, - &conn->nt_user_token); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - fstrcpy(username, found_username); - - TALLOC_FREE(fuser); - TALLOC_FREE(found_username); - return NT_STATUS_OK; -} - /* * Go through lookup_name etc to find the force'd group. * @@ -766,13 +741,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->force_user = true; } - conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; - - conn->uid = conn->server_info->uid; - conn->gid = conn->server_info->gid; - string_set(&conn->user, conn->server_info->unix_name); - add_session_user(conn->user); + add_session_user(conn->server_info->unix_name); safe_strcpy(conn->client_address, client_addr(get_client_fd(),addr,sizeof(addr)), @@ -815,20 +785,39 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if (*lp_force_user(snum)) { - fstring tmp; - fstrcpy(tmp, conn->user); - status = find_forced_user(conn, - (vuser != NULL) && vuser->server_info->guest, - tmp); + char *fuser; + struct auth_serversupplied_info *forced_serverinfo; + + fuser = talloc_string_sub(conn, lp_force_user(snum), "%S", + lp_servicename(snum)); + if (fuser == NULL) { + conn_free(conn); + *pstatus = NT_STATUS_NO_MEMORY; + return NULL; + } + + status = make_serverinfo_from_username( + conn, fuser, conn->server_info->guest, + &forced_serverinfo); if (!NT_STATUS_IS_OK(status)) { conn_free(conn); *pstatus = status; return NULL; } + + TALLOC_FREE(conn->server_info); + conn->server_info = forced_serverinfo; + conn->force_user = True; - DEBUG(3,("Forced user %s\n",tmp)); + DEBUG(3,("Forced user %s\n", fuser)); } + conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; + + conn->uid = conn->server_info->uid; + conn->gid = conn->server_info->gid; + string_set(&conn->user, conn->server_info->unix_name); + /* * If force group is true, then override * any groupid stored for the connecting user. -- cgit From 39bd6a95959e9015262b7b4250d3fcd58be44fc9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 14:25:47 +0200 Subject: Do not unnecessarily mess with the results in find_forced_group() (This used to be commit 6d9860d09b54c61625f011c2d56d710aa59d7686) --- source3/smbd/service.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e3635d45db..60d962f3fd 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -543,9 +543,6 @@ static NTSTATUS find_forced_group(bool force_user, bool user_must_be_member = False; gid_t gid; - ZERO_STRUCTP(pgroup_sid); - *pgid = (gid_t)-1; - groupname = talloc_strdup(talloc_tos(), lp_force_group(snum)); if (groupname == NULL) { DEBUG(1, ("talloc_strdup failed\n")); -- cgit From d2157f13422da4991ffcc007c7bc3c07e1f42912 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 14:28:23 +0200 Subject: Add an error return in find_forced_group() (This used to be commit 93ce0705c14f222bda3e6204f4b54ba1893f33e1) --- source3/smbd/service.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 60d962f3fd..30e48018e9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -557,6 +557,11 @@ static NTSTATUS find_forced_group(bool force_user, groupname = talloc_string_sub(talloc_tos(), groupname, "%S", lp_servicename(snum)); + if (groupname == NULL) { + DEBUG(1, ("talloc_string_sub failed\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } if (!lookup_name_smbconf(talloc_tos(), groupname, LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, -- cgit From 322896f8dd9e7d92fe677178bd131fcfc09319f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 14:36:15 +0200 Subject: find_forced_group can directly change the token in server_info Now that we have a token that is correctly set up with gids already, this saves manual translation of the SIDs to GIDs. (This used to be commit 6136a6d9d7301c65f37e2bf485681138cddd8bd2) --- source3/smbd/service.c | 88 +++++++++----------------------------------------- 1 file changed, 16 insertions(+), 72 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 30e48018e9..267ca3c29f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -743,7 +743,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->force_user = true; } - add_session_user(conn->server_info->unix_name); safe_strcpy(conn->client_address, @@ -780,13 +779,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; - /* - * If force user is true, then store the given userid and the gid of - * the user we're forcing. - * For auxiliary groups see below. - */ - if (*lp_force_user(snum)) { + + /* + * Replace conn->server_info with a completely faked up one + * from the username we are forced into :-) + */ + char *fuser; struct auth_serversupplied_info *forced_serverinfo; @@ -814,85 +813,30 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(3,("Forced user %s\n", fuser)); } - conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; - - conn->uid = conn->server_info->uid; - conn->gid = conn->server_info->gid; - string_set(&conn->user, conn->server_info->unix_name); - /* * If force group is true, then override * any groupid stored for the connecting user. */ - + if (*lp_force_group(snum)) { - DOM_SID group_sid; - status = find_forced_group(conn->force_user, snum, - conn->user, - &group_sid, &conn->gid); + status = find_forced_group( + conn->force_user, snum, conn->user, + &conn->server_info->ptok->user_sids[1], + &conn->server_info->gid); + if (!NT_STATUS_IS_OK(status)) { conn_free(conn); *pstatus = status; return NULL; } - - if ((conn->nt_user_token == NULL) && (vuser != NULL)) { - - /* Not force user and not security=share, but force - * group. vuser has a token to copy */ - - conn->nt_user_token = dup_nt_token( - NULL, vuser->server_info->ptok); - if (conn->nt_user_token == NULL) { - DEBUG(0, ("dup_nt_token failed\n")); - conn_free(conn); - *pstatus = NT_STATUS_NO_MEMORY; - return NULL; - } - } - - /* If conn->nt_user_token is still NULL, we have - * security=share. This means ignore the SID, as we had no - * vuser to copy from */ - - if (conn->nt_user_token != NULL) { - /* Overwrite the primary group sid */ - sid_copy(&conn->nt_user_token->user_sids[1], - &group_sid); - - } } - if (conn->nt_user_token != NULL) { - size_t i; - - /* We have a share-specific token from force [user|group]. - * This means we have to create the list of unix groups from - * the list of sids. */ - - conn->ngroups = 0; - conn->groups = NULL; - - for (i=0; int_user_token->num_sids; i++) { - gid_t gid; - DOM_SID *sid = &conn->nt_user_token->user_sids[i]; + conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; - if (!sid_to_gid(sid, &gid)) { - DEBUG(10, ("Could not convert SID %s to gid, " - "ignoring it\n", - sid_string_dbg(sid))); - continue; - } - if (!add_gid_to_array_unique(conn, gid, &conn->groups, - &conn->ngroups)) { - DEBUG(0, ("add_gid_to_array_unique failed\n")); - conn_free(conn); - *pstatus = NT_STATUS_NO_MEMORY; - return NULL; - } - } - } + conn->uid = conn->server_info->uid; + conn->gid = conn->server_info->gid; + string_set(&conn->user, conn->server_info->unix_name); { char *s = talloc_sub_advanced(talloc_tos(), -- cgit From c881c866d656bacb30180b574f3634db26deb37a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 7 May 2008 15:51:42 +0200 Subject: Next try at making the vuid cache circular Jeremy, please check! (This used to be commit a34f73521712e3820d417f0d9ed811723b7681d6) --- source3/smbd/conn.c | 9 ++++++--- source3/smbd/uid.c | 14 +++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index af18e905c0..3baf0cfaab 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -237,9 +237,12 @@ void conn_clear_vuid_cache(uint16 vuid) conn->vuid = UID_FIELD_INVALID; } - for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { - if (conn->vuid_cache.array[i].vuid == vuid) { - struct vuid_cache_entry *ent = &conn->vuid_cache.array[i]; + for (i=0; ivuid_cache.array[i]; + + if (ent->vuid == vuid) { ent->vuid = UID_FIELD_INVALID; ent->read_only = False; ent->admin_user = False; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 78dff8ffee..ce8aaa33ea 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -65,9 +65,9 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) bool readonly_share; NT_USER_TOKEN *token; - for (i=0;ivuid_cache.entries && i< VUID_CACHE_SIZE;i++) { - if (conn->vuid_cache.array[i].vuid == vuser->vuid) { - ent = &conn->vuid_cache.array[i]; + for (i=0; ivuid_cache.array[i]; + if (ent->vuid == vuser->vuid) { conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; return(True); @@ -102,11 +102,11 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) return False; } - i = conn->vuid_cache.entries % VUID_CACHE_SIZE; - if (conn->vuid_cache.entries < VUID_CACHE_SIZE) - conn->vuid_cache.entries++; + ent = &conn->vuid_cache.array[conn->vuid_cache.next_entry]; + + conn->vuid_cache.next_entry = + (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE; - ent = &conn->vuid_cache.array[i]; ent->vuid = vuser->vuid; ent->read_only = readonly_share; -- cgit From e2b9ac714b0f7aeece4ebe8772b7f8380356818d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 May 2008 11:47:43 +0200 Subject: Make use of talloc_tos() in change_to_user() (This used to be commit c4bed3a48b86d44ad641250add2fc189af7e72f5) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index ce8aaa33ea..288ce50139 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -199,7 +199,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) if((group_c = *lp_force_group(snum))) { - token = dup_nt_token(NULL, token); + token = dup_nt_token(talloc_tos(), token); if (token == NULL) { DEBUG(0, ("dup_nt_token failed\n")); return False; -- cgit From 0c2bf9521efcf066268016bdab5d7a30bf879e26 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 May 2008 12:14:43 +0200 Subject: Empty some nonempty blank lines (This used to be commit 1a406def02bf171b223467d6b76317586d6205fc) --- source3/smbd/uid.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 288ce50139..2335bff9fd 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -2,17 +2,17 @@ Unix SMB/CIFS implementation. uid/user handling Copyright (C) Andrew Tridgell 1992-1998 - + 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 3 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, see . */ @@ -36,21 +36,21 @@ bool change_to_guest(void) if (!pass) return(False); } - + #ifdef AIX /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before setting IDs */ initgroups(pass->pw_name, pass->pw_gid); #endif - + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); - + current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; TALLOC_FREE(pass); pass = NULL; - + return True; } @@ -136,7 +136,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) NT_USER_TOKEN *token = NULL; int num_groups = 0; gid_t *group_list = NULL; - + if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); return(False); @@ -228,7 +228,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) gid_to_sid(&token->user_sids[1], gid); } } - + /* Now set current_user since we will immediately also call set_sec_ctx() */ @@ -250,7 +250,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - + return(True); } @@ -310,29 +310,29 @@ struct conn_ctx { connection_struct *conn; uint16 vuid; }; - + /* A stack of current_user connection contexts. */ - + static struct conn_ctx conn_ctx_stack[MAX_SEC_CTX_DEPTH]; static int conn_ctx_stack_ndx; static void push_conn_ctx(void) { struct conn_ctx *ctx_p; - + /* Check we don't overflow our stack */ - + if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) { DEBUG(0, ("Connection context stack overflow!\n")); smb_panic("Connection context stack overflow!\n"); } - + /* Store previous user context */ ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx]; - + ctx_p->conn = current_user.conn; ctx_p->vuid = current_user.vuid; - + DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n", (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx )); @@ -342,7 +342,7 @@ static void push_conn_ctx(void) static void pop_conn_ctx(void) { struct conn_ctx *ctx_p; - + /* Check for stack underflow. */ if (conn_ctx_stack_ndx == 0) { -- cgit From 776caa081bc36aac0ab7cc826836740f5bf0bf24 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 May 2008 15:09:02 +0200 Subject: Replace nt_user_token with server_info in connection_struct (This used to be commit a3738aef59e97d4533010b048534d937d36c0950) --- source3/smbd/conn.c | 1 + source3/smbd/service.c | 28 ++++-------------------- source3/smbd/uid.c | 58 ++++++++++++++++++++++++-------------------------- 3 files changed, 33 insertions(+), 54 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 3baf0cfaab..ce3512c4ec 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -244,6 +244,7 @@ void conn_clear_vuid_cache(uint16 vuid) if (ent->vuid == vuid) { ent->vuid = UID_FIELD_INVALID; + TALLOC_FREE(ent->server_info); ent->read_only = False; ent->admin_user = False; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 267ca3c29f..77ed320e07 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -725,7 +725,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } conn->params->service = snum; - conn->nt_user_token = NULL; status = create_connection_server_info( conn, snum, vuser ? vuser->server_info : NULL, password, @@ -871,32 +870,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, { bool can_write = False; - NT_USER_TOKEN *token = conn->nt_user_token ? - conn->nt_user_token : - (vuser ? vuser->server_info->ptok : NULL); - /* - * I don't believe this can happen. But the - * logic above is convoluted enough to confuse - * automated checkers, so be sure. JRA. - */ - - if (token == NULL) { - DEBUG(0,("make_connection: connection to %s " - "denied due to missing " - "NT token.\n", - lp_servicename(snum))); - conn_free(conn); - *pstatus = NT_STATUS_ACCESS_DENIED; - return NULL; - } - - can_write = share_access_check(token, - lp_servicename(snum), - FILE_WRITE_DATA); + can_write = share_access_check(conn->server_info->ptok, + lp_servicename(snum), + FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(token, + if (!share_access_check(conn->server_info->ptok, lp_servicename(snum), FILE_READ_DATA)) { /* No access, read or write. */ diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 2335bff9fd..8a4a54f867 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -56,6 +56,9 @@ bool change_to_guest(void) /******************************************************************* Check if a username is OK. + + This sets up conn->server_info with a copy related to this vuser that + later code can then mess with. ********************************************************************/ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) @@ -63,11 +66,11 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) unsigned int i; struct vuid_cache_entry *ent = NULL; bool readonly_share; - NT_USER_TOKEN *token; for (i=0; ivuid_cache.array[i]; if (ent->vuid == vuser->vuid) { + conn->server_info = ent->server_info; conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; return(True); @@ -83,11 +86,8 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) vuser->server_info->unix_name, vuser->server_info->ptok, SNUM(conn)); - token = conn->nt_user_token ? - conn->nt_user_token : vuser->server_info->ptok; - if (!readonly_share && - !share_access_check(token, lp_servicename(snum), + !share_access_check(vuser->server_info->ptok, lp_servicename(snum), FILE_WRITE_DATA)) { /* smb.conf allows r/w, but the security descriptor denies * write. Fall back to looking at readonly. */ @@ -96,7 +96,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) "security descriptor\n")); } - if (!share_access_check(token, lp_servicename(snum), + if (!share_access_check(vuser->server_info->ptok, lp_servicename(snum), readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { return False; @@ -107,6 +107,14 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) conn->vuid_cache.next_entry = (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE; + TALLOC_FREE(ent->server_info); + + ent->server_info = copy_serverinfo(conn, vuser->server_info); + if (ent->server_info == NULL) { + ent->vuid = UID_FIELD_INVALID; + return false; + } + ent->vuid = vuser->vuid; ent->read_only = readonly_share; @@ -116,6 +124,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; + conn->server_info = ent->server_info; return(True); } @@ -132,8 +141,6 @@ bool change_to_user(connection_struct *conn, uint16 vuid) gid_t gid; uid_t uid; char group_c; - bool must_free_token = False; - NT_USER_TOKEN *token = NULL; int num_groups = 0; gid_t *group_list = NULL; @@ -173,18 +180,21 @@ bool change_to_user(connection_struct *conn, uint16 vuid) return False; } + /* + * conn->server_info is now correctly set up with a copy we can mess + * with for force_group etc. + */ + if (conn->force_user) /* security = share sets this too */ { uid = conn->uid; gid = conn->gid; group_list = conn->groups; num_groups = conn->ngroups; - token = conn->nt_user_token; } else if (vuser) { uid = conn->admin_user ? 0 : vuser->server_info->uid; - gid = vuser->server_info->gid; - num_groups = vuser->server_info->n_groups; - group_list = vuser->server_info->groups; - token = vuser->server_info->ptok; + gid = conn->server_info->gid; + num_groups = conn->server_info->n_groups; + group_list = conn->server_info->groups; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " "share %s.\n",vuid, lp_servicename(snum) )); @@ -199,13 +209,6 @@ bool change_to_user(connection_struct *conn, uint16 vuid) if((group_c = *lp_force_group(snum))) { - token = dup_nt_token(talloc_tos(), token); - if (token == NULL) { - DEBUG(0, ("dup_nt_token failed\n")); - return False; - } - must_free_token = True; - if(group_c == '+') { /* @@ -219,13 +222,15 @@ bool change_to_user(connection_struct *conn, uint16 vuid) for (i = 0; i < num_groups; i++) { if (group_list[i] == conn->gid) { gid = conn->gid; - gid_to_sid(&token->user_sids[1], gid); + gid_to_sid(&conn->server_info->ptok + ->user_sids[1], gid); break; } } } else { gid = conn->gid; - gid_to_sid(&token->user_sids[1], gid); + gid_to_sid(&conn->server_info->ptok->user_sids[1], + gid); } } @@ -236,14 +241,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) current_user.ut.groups = group_list; set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, - token); - - /* - * Free the new token (as set_sec_ctx copies it). - */ - - if (must_free_token) - TALLOC_FREE(token); + conn->server_info->ptok); current_user.conn = conn; current_user.vuid = vuid; -- cgit From 53a623d8a69b5dd7fbd964013032878e09032375 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 May 2008 15:53:55 +0200 Subject: Remove the unix token info from connection_struct (This used to be commit 2834dacc8d49f77fe55fb5d7e3eb2dda431d1d3d) --- source3/smbd/connection.c | 4 ++-- source3/smbd/lanman.c | 8 ++++---- source3/smbd/service.c | 17 ++++++++++------- source3/smbd/uid.c | 16 ++++++++-------- 4 files changed, 24 insertions(+), 21 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index d7063c9989..97f36971c8 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -152,8 +152,8 @@ bool claim_connection(connection_struct *conn, const char *name, crec.pid = procid_self(); crec.cnum = conn?conn->cnum:-1; if (conn) { - crec.uid = conn->uid; - crec.gid = conn->gid; + crec.uid = conn->server_info->uid; + crec.gid = conn->server_info->gid; strlcpy(crec.servicename, lp_servicename(SNUM(conn)), sizeof(crec.servicename)); } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a233893482..4309622b26 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -103,7 +103,7 @@ static int CopyExpanded(connection_struct *conn, lp_servicename(SNUM(conn)), conn->user, conn->connectpath, - conn->gid, + conn->server_info->gid, get_current_username(), current_user_info.domain, buf); @@ -154,7 +154,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) lp_servicename(SNUM(conn)), conn->user, conn->connectpath, - conn->gid, + conn->server_info->gid, get_current_username(), current_user_info.domain, buf); @@ -184,7 +184,7 @@ static char *Expand(connection_struct *conn, int snum, char *s) lp_servicename(SNUM(conn)), conn->user, conn->connectpath, - conn->gid, + conn->server_info->gid, get_current_username(), current_user_info.domain, buf); @@ -3002,7 +3002,7 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, lp_servicename(SNUM(conn)), conn->user, conn->connectpath, - conn->gid, + conn->server_info->gid, get_current_username(), current_user_info.domain, comment); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 77ed320e07..fd072135e8 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -833,14 +833,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; - conn->uid = conn->server_info->uid; - conn->gid = conn->server_info->gid; string_set(&conn->user, conn->server_info->unix_name); { char *s = talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, + conn->connectpath, + conn->server_info->gid, get_current_username(), current_user_info.domain, lp_pathname(snum)); @@ -960,7 +959,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_rootpreexec(snum)) { char *cmd = talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, + conn->connectpath, + conn->server_info->gid, get_current_username(), current_user_info.domain, lp_rootpreexec(snum)); @@ -997,7 +997,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_preexec(snum)) { char *cmd = talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, + conn->connectpath, + conn->server_info->gid, get_current_username(), current_user_info.domain, lp_preexec(snum)); @@ -1316,7 +1317,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_user(conn, vuid)) { char *cmd = talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, + conn->connectpath, + conn->server_info->gid, get_current_username(), current_user_info.domain, lp_postexec(SNUM(conn))); @@ -1330,7 +1332,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) if (*lp_rootpostexec(SNUM(conn))) { char *cmd = talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, + conn->connectpath, + conn->server_info->gid, get_current_username(), current_user_info.domain, lp_rootpostexec(SNUM(conn))); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8a4a54f867..004e48a44f 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -157,7 +157,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) */ if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && - (current_user.ut.uid == conn->uid)) { + (current_user.ut.uid == conn->server_info->uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); return(True); @@ -186,10 +186,10 @@ bool change_to_user(connection_struct *conn, uint16 vuid) */ if (conn->force_user) /* security = share sets this too */ { - uid = conn->uid; - gid = conn->gid; - group_list = conn->groups; - num_groups = conn->ngroups; + uid = conn->server_info->uid; + gid = conn->server_info->gid; + group_list = conn->server_info->groups; + num_groups = conn->server_info->n_groups; } else if (vuser) { uid = conn->admin_user ? 0 : vuser->server_info->uid; gid = conn->server_info->gid; @@ -220,15 +220,15 @@ bool change_to_user(connection_struct *conn, uint16 vuid) int i; for (i = 0; i < num_groups; i++) { - if (group_list[i] == conn->gid) { - gid = conn->gid; + if (group_list[i] == conn->server_info->gid) { + gid = conn->server_info->gid; gid_to_sid(&conn->server_info->ptok ->user_sids[1], gid); break; } } } else { - gid = conn->gid; + gid = conn->server_info->gid; gid_to_sid(&conn->server_info->ptok->user_sids[1], gid); } -- cgit From 5bda9a8af02c7889e15e580a5620689aa312a16a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 May 2008 16:06:42 +0200 Subject: Remove "user" from connection_struct (This used to be commit 368454a27cb53a408ec416cbf37235b304592fb5) --- source3/smbd/close.c | 2 +- source3/smbd/conn.c | 2 -- source3/smbd/fake_file.c | 3 ++- source3/smbd/lanman.c | 8 ++++---- source3/smbd/nttrans.c | 10 ++++++---- source3/smbd/open.c | 5 +++-- source3/smbd/service.c | 25 +++++++++++++++---------- source3/smbd/trans2.c | 9 ++++++--- 8 files changed, 37 insertions(+), 27 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index e27d5c44fa..df188bafe1 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -581,7 +581,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ } DEBUG(2,("%s closed file %s (numopen=%d) %s\n", - conn->user,fsp->fsp_name, + conn->server_info->unix_name,fsp->fsp_name, conn->num_files_open, nt_errstr(status) )); diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index ce3512c4ec..e899af1319 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -151,7 +151,6 @@ find_again: num_open++; - string_set(&conn->user,""); string_set(&conn->dirpath,""); string_set(&conn->connectpath,""); string_set(&conn->origpath,""); @@ -283,7 +282,6 @@ void conn_free_internal(connection_struct *conn) free_namearray(conn->veto_oplock_list); free_namearray(conn->aio_write_behind_list); - string_free(&conn->user); string_free(&conn->dirpath); string_free(&conn->connectpath); string_free(&conn->origpath); diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 31fe030f46..0a54c85cd0 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -113,7 +113,8 @@ NTSTATUS open_fake_file(connection_struct *conn, if (current_user.ut.uid != 0) { DEBUG(3, ("open_fake_file_shared: access_denied to " "service[%s] file[%s] user[%s]\n", - lp_servicename(SNUM(conn)),fname,conn->user)); + lp_servicename(SNUM(conn)), fname, + conn->server_info->unix_name)); return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4309622b26..413b916f7b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -101,7 +101,7 @@ static int CopyExpanded(connection_struct *conn, } buf = talloc_sub_advanced(ctx, lp_servicename(SNUM(conn)), - conn->user, + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), @@ -152,7 +152,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) } buf = talloc_sub_advanced(ctx, lp_servicename(SNUM(conn)), - conn->user, + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), @@ -182,7 +182,7 @@ static char *Expand(connection_struct *conn, int snum, char *s) } return talloc_sub_advanced(ctx, lp_servicename(SNUM(conn)), - conn->user, + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), @@ -3000,7 +3000,7 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, SIVAL(p,6,PTR_DIFF(p2,*rdata)); comment = talloc_sub_advanced(ctx, lp_servicename(SNUM(conn)), - conn->user, + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bd34b5a361..b5546ea1e1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2037,8 +2037,9 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, /* access check */ if (current_user.ut.uid != 0) { - DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n", - lp_servicename(SNUM(conn)),conn->user)); + DEBUG(1,("get_user_quota: access_denied service [%s] user " + "[%s]\n", lp_servicename(SNUM(conn)), + conn->server_info->unix_name)); reply_doserror(req, ERRDOS, ERRnoaccess); return; } @@ -2303,8 +2304,9 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, /* access check */ if (current_user.ut.uid != 0) { - DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", - lp_servicename(SNUM(conn)),conn->user)); + DEBUG(1,("set_user_quota: access_denied service [%s] user " + "[%s]\n", lp_servicename(SNUM(conn)), + conn->server_info->unix_name)); reply_doserror(req, ERRDOS, ERRnoaccess); return; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5c860f891d..546128c0e5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -400,8 +400,9 @@ static NTSTATUS open_file(files_struct *fsp, fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *current_user_info.smb_name ? - current_user_info.smb_name : conn->user,fsp->fsp_name, + *current_user_info.smb_name + ? current_user_info.smb_name : conn->server_info->unix_name, + fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index fd072135e8..c90d4d16bc 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -820,7 +820,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_force_group(snum)) { status = find_forced_group( - conn->force_user, snum, conn->user, + conn->force_user, snum, conn->server_info->unix_name, &conn->server_info->ptok->user_sids[1], &conn->server_info->gid); @@ -833,11 +833,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; - string_set(&conn->user, conn->server_info->unix_name); - { char *s = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), @@ -958,7 +957,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* execute any "root preexec = " line */ if (*lp_rootpreexec(snum)) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), @@ -996,7 +996,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* execute any "preexec = " line */ if (*lp_preexec(snum)) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), @@ -1029,7 +1030,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, to allow any filesystems needing user credentials to initialize themselves. */ - if (SMB_VFS_CONNECT(conn, lp_servicename(snum), conn->user) < 0) { + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), + conn->server_info->unix_name) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); *pstatus = NT_STATUS_UNSUCCESSFUL; goto err_root_exit; @@ -1096,7 +1098,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->client_address ); dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(snum) ); - dbgtext( "initially as user %s ", conn->user ); + dbgtext( "initially as user %s ", + conn->server_info->unix_name ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)sys_getpid() ); } @@ -1316,7 +1319,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) if (*lp_postexec(SNUM(conn)) && change_to_user(conn, vuid)) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), @@ -1331,7 +1335,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) /* execute any "root postexec = " line */ if (*lp_rootpostexec(SNUM(conn))) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, get_current_username(), diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4d60eecda9..d5435533f9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2826,8 +2826,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned /* access check */ if (current_user.ut.uid != 0) { - DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", - lp_servicename(SNUM(conn)),conn->user)); + DEBUG(0,("set_user_quota: access_denied " + "service [%s] user [%s]\n", + lp_servicename(SNUM(conn)), + conn->server_info->unix_name)); reply_doserror(req, ERRDOS, ERRnoaccess); return; } @@ -3267,7 +3269,8 @@ cap_low = 0x%x, cap_high = 0x%x\n", /* access check */ if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", - lp_servicename(SNUM(conn)),conn->user)); + lp_servicename(SNUM(conn)), + conn->server_info->unix_name)); reply_doserror(req, ERRSRV, ERRaccess); return; } -- cgit From 4f9b325fb2e9872e4c306791306cd08eb7ac6ef6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 10 May 2008 23:27:21 +0200 Subject: Fix a memleak (This used to be commit 9891c7c30858a3bea9adbea1c5bfa5c6b1b85221) --- source3/smbd/sesssetup.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 0f0a0d5f31..7cff422507 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -644,10 +644,6 @@ static void reply_spnego_ntlmssp(struct smb_request *req, if (NT_STATUS_IS_OK(nt_status)) { DATA_BLOB nullblob = data_blob_null; - DATA_BLOB session_key = - data_blob( - (*auth_ntlmssp_state)->ntlmssp_state->session_key.data, - (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); if (!is_partial_auth_vuid(vuid)) { nt_status = NT_STATUS_LOGON_FAILURE; @@ -665,7 +661,6 @@ static void reply_spnego_ntlmssp(struct smb_request *req, server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user) != vuid) { - data_blob_free(&session_key); nt_status = NT_STATUS_LOGON_FAILURE; goto out; } -- cgit From 6b6bb484a8049c5acf88b94f9106e40d96bf56ae Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 May 2008 00:23:01 +0200 Subject: Fix a memleak in new auth_serversupplied code (This used to be commit f23e970848b6e6655453fa65f6f160f624acfcff) --- source3/smbd/sesssetup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7cff422507..5b00403140 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -652,7 +652,8 @@ static void reply_spnego_ntlmssp(struct smb_request *req, data_blob_free(&server_info->user_session_key); server_info->user_session_key = - data_blob( + data_blob_talloc( + server_info, (*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); -- cgit From aac9e7d1cafc7be5abdbc73a238b7585cdba4708 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 May 2008 00:25:27 +0200 Subject: With force user, we have the same base token for all vuids (This used to be commit 0f19bc3f65bfc132aea1de1e76fcb4ee625a050f) --- source3/smbd/uid.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 004e48a44f..310ad4d23a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -109,7 +109,15 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) TALLOC_FREE(ent->server_info); - ent->server_info = copy_serverinfo(conn, vuser->server_info); + /* + * If force_user was set, all server_info's are based on the same + * username-based faked one. + */ + + ent->server_info = copy_serverinfo( + conn, + conn->force_user ? conn->server_info : vuser->server_info); + if (ent->server_info == NULL) { ent->vuid = UID_FIELD_INVALID; return false; -- cgit From bafe8d22fde97755bf35e8abf389d52b8993a551 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 14:01:19 -0700 Subject: Fix bug #5460. The problem is RHEL5.0 shipped a CIFS client that sets the DFS bit on pathnames but doesn't send DFS paths. This causes lookups to fail as the smbd/msdfs.c code now just eats the first two parts of the pathname and uses the rest as the local path. The previous hostname check used to protect us from that as we knew that when the hostname was invalid it was a local path (and a broken client). I didn't want to put that check back in, but came up with another idea - even though the hostname can be a different one, the sharename must be valid on this machine. So we can check for a valid sharename instead. Jeremy. (This used to be commit e1cda82f6f7de3306a653af920756c1640057f2d) --- source3/smbd/conn.c | 25 +++++++++++++++++++++++-- source3/smbd/msdfs.c | 10 ++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index e899af1319..125277be21 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -63,10 +63,10 @@ bool conn_snum_used(int snum) return(False); } - /**************************************************************************** -find a conn given a cnum + Find a conn given a cnum. ****************************************************************************/ + connection_struct *conn_find(unsigned cnum) { int count=0; @@ -84,6 +84,27 @@ connection_struct *conn_find(unsigned cnum) return NULL; } +/**************************************************************************** + Find a conn given a service name. +****************************************************************************/ + +connection_struct *conn_find_byname(const char *service) +{ + int count=0; + connection_struct *conn; + + for (conn=Connections;conn;conn=conn->next,count++) { + if (strequal(lp_servicename(SNUM(conn)),service)) { + if (count > 10) { + DLIST_PROMOTE(Connections, conn); + } + return conn; + } + } + + return NULL; +} + /**************************************************************************** find first available connection slot, starting from a random position. diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e321a8c8e4..6306745574 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -133,6 +133,16 @@ static NTSTATUS parse_dfs_path(const char *pathname, if(p == NULL) { pdp->servicename = temp; pdp->reqpath = eos_ptr; /* "" */ + /* Is this really our servicename ? */ + if (NULL == conn_find_byname(pdp->servicename)) { + DEBUG(10,("parse_dfs_path: %s is not our servicename\n", + pdp->servicename)); + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", + temp)); + goto local_path; + } return NT_STATUS_OK; } *p = '\0'; -- cgit From b833615721d6d2e328908afeb1cb965ab5d38284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 15:02:11 -0700 Subject: Second part of patch for bug #5460. Cope with pathnames that don't look like \xxx\yyy, cope with arbitrary length. Jeremy. (This used to be commit 635035d999fcd8e06b70c8cb1137127c289dc9e6) --- source3/smbd/msdfs.c | 54 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6306745574..4e673d8000 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -49,6 +49,7 @@ static NTSTATUS parse_dfs_path(const char *pathname, { char *pathname_local; char *p,*temp; + char *servicename; char *eos_ptr; NTSTATUS status = NT_STATUS_OK; char sepchar; @@ -128,25 +129,48 @@ static NTSTATUS parse_dfs_path(const char *pathname, DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); /* Parse out servicename. */ - temp = p+1; - p = strchr_m(temp,sepchar); + servicename = p+1; + p = strchr_m(servicename,sepchar); + if (p) { + *p = '\0'; + } + + /* Is this really our servicename ? */ + if (NULL == conn_find_byname(servicename)) { + DEBUG(10,("parse_dfs_path: %s is not our servicename\n", + servicename)); + + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ + + pdp->hostname = eos_ptr; /* "" */ + pdp->servicename = eos_ptr; /* "" */ + + /* Repair the path - replace the sepchar's + we nulled out */ + servicename--; + *servicename = sepchar; + if (p) { + *p = sepchar; + } + + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", + temp)); + goto local_path; + } + + pdp->servicename = servicename; + if(p == NULL) { - pdp->servicename = temp; + /* Client sent self referral \server\share. */ pdp->reqpath = eos_ptr; /* "" */ - /* Is this really our servicename ? */ - if (NULL == conn_find_byname(pdp->servicename)) { - DEBUG(10,("parse_dfs_path: %s is not our servicename\n", - pdp->servicename)); - p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s " - "to a local path\n", - temp)); - goto local_path; - } return NT_STATUS_OK; } - *p = '\0'; - pdp->servicename = temp; + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); p++; -- cgit From b8398d19af01cbdaec3af6c264e4d073fa85f78d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 15:25:26 -0700 Subject: Fix debug message. Jeremy. (This used to be commit 08d168f0e5b8fb07e95a5118a839e0da53e9d363) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4e673d8000..04b9b7deaa 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -165,14 +165,14 @@ static NTSTATUS parse_dfs_path(const char *pathname, pdp->servicename = servicename; + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + if(p == NULL) { /* Client sent self referral \server\share. */ pdp->reqpath = eos_ptr; /* "" */ return NT_STATUS_OK; } - DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); - p++; local_path: -- cgit From 96ef630ba33f23125b2d7c6c2fa74b524f285c1e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 May 2008 14:10:05 -0700 Subject: Ensure we don't keep searching for sharename if it's not the start of the list. Jeremy. (This used to be commit 15857534b76bc66ad122510100aa224f17250465) --- source3/smbd/conn.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 125277be21..159b232b5f 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -90,12 +90,12 @@ connection_struct *conn_find(unsigned cnum) connection_struct *conn_find_byname(const char *service) { - int count=0; connection_struct *conn; - for (conn=Connections;conn;conn=conn->next,count++) { + for (conn=Connections;conn;conn=conn->next) { if (strequal(lp_servicename(SNUM(conn)),service)) { - if (count > 10) { + if (conn != Connections) { + /* Promote if not first. */ DLIST_PROMOTE(Connections, conn); } return conn; -- cgit From e58729f0eaefb5659396f7f0ecb6239806ee275f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 29 Mar 2008 18:19:31 +0100 Subject: Simplify fake_file logic (This used to be commit 93111ea0a1191e8547ad6cf112e2699d3bb3799b) --- source3/smbd/fake_file.c | 68 ++++++++++++++++++++++-------------------------- source3/smbd/ntquotas.c | 29 +++++++-------------- source3/smbd/nttrans.c | 2 +- 3 files changed, 41 insertions(+), 58 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 0a54c85cd0..565b557dd3 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -21,52 +21,52 @@ extern struct current_user current_user; -static FAKE_FILE fake_files[] = { +struct fake_file_type { + const char *name; + enum FAKE_FILE_TYPE type; + void *(*init_pd)(TALLOC_CTX *mem_ctx); +}; + +static struct fake_file_type fake_files[] = { #ifdef WITH_QUOTAS - {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle}, + {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle}, #endif /* WITH_QUOTAS */ - {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL } + {NULL, FAKE_FILE_TYPE_NONE, NULL} }; /**************************************************************************** Create a fake file handle ****************************************************************************/ -static struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) +static struct fake_file_handle *init_fake_file_handle(enum FAKE_FILE_TYPE type) { - TALLOC_CTX *mem_ctx = NULL; - FAKE_FILE_HANDLE *fh = NULL; + struct fake_file_handle *fh = NULL; int i; - for (i=0;fake_files[i].name!=NULL;i++) { + for (i=0; fake_files[i].name!=NULL; i++) { if (fake_files[i].type==type) { - DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name)); - - if ((mem_ctx=talloc_init("fake_file_handle"))==NULL) { - DEBUG(0,("talloc_init(fake_file_handle) failed.\n")); - return NULL; - } + break; + } + } - if ((fh =TALLOC_ZERO_P(mem_ctx, FAKE_FILE_HANDLE))==NULL) { - DEBUG(0,("TALLOC_ZERO() failed.\n")); - talloc_destroy(mem_ctx); - return NULL; - } + if (fake_files[i].name == NULL) { + return NULL; + } - fh->type = type; - fh->mem_ctx = mem_ctx; + DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name)); - if (fake_files[i].init_pd) { - fh->pd = fake_files[i].init_pd(fh->mem_ctx); - } + fh = talloc(NULL, struct fake_file_handle); + if (fh == NULL) { + DEBUG(0,("TALLOC_ZERO() failed.\n")); + return NULL; + } - fh->free_pd = fake_files[i].free_pd; + fh->type = type; - return fh; - } + if (fake_files[i].init_pd) { + fh->private_data = fake_files[i].init_pd(fh); } - - return NULL; + return fh; } /**************************************************************************** @@ -147,18 +147,12 @@ NTSTATUS open_fake_file(connection_struct *conn, return NT_STATUS_OK; } -void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) +void destroy_fake_file_handle(struct fake_file_handle **fh) { - if (!fh||!(*fh)) { + if (!fh) { return; } - - if ((*fh)->free_pd) { - (*fh)->free_pd(&(*fh)->pd); - } - - talloc_destroy((*fh)->mem_ctx); - (*fh) = NULL; + TALLOC_FREE(*fh); } NTSTATUS close_fake_file(files_struct *fsp) diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index fcccf9d9fc..c616c494dc 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -222,6 +222,13 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) return 0; } +static int quota_handle_destructor(SMB_NTQUOTA_HANDLE *handle) +{ + if (handle->quota_list) + free_ntquota_list(&handle->quota_list); + return 0; +} + void *init_quota_handle(TALLOC_CTX *mem_ctx) { SMB_NTQUOTA_HANDLE *qt_handle; @@ -235,24 +242,6 @@ void *init_quota_handle(TALLOC_CTX *mem_ctx) return NULL; } - return (void *)qt_handle; -} - -void destroy_quota_handle(void **pqt_handle) -{ - SMB_NTQUOTA_HANDLE *qt_handle = NULL; - if (!pqt_handle||!(*pqt_handle)) - return; - - qt_handle = (SMB_NTQUOTA_HANDLE *)(*pqt_handle); - - - if (qt_handle->quota_list) - free_ntquota_list(&qt_handle->quota_list); - - qt_handle->quota_list = NULL; - qt_handle->tmp_list = NULL; - qt_handle = NULL; - - return; + talloc_set_destructor(qt_handle, quota_handle_destructor); + return (void *)qt_handle; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b5546ea1e1..cbe1299cf7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2065,7 +2065,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, /* the NULL pointer checking for fsp->fake_file_handle->pd * is done by CHECK_NTQUOTA_HANDLE_OK() */ - qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd; + qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data; level = SVAL(params,2); -- cgit From c7f5d24d813097a5bdb29c68bd30f4d117e083be Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 May 2008 13:11:00 -0700 Subject: Restructuring of code to fix #5460. Remove search by name code from conn, we were already doing the same check in the dfs_redirect() function, so move it into parse_dfs_path() instead. Jeremy. (This used to be commit 8a7c6df122c5e4a1d0f74ab0f1bc9376a0a8bcb1) --- source3/smbd/conn.c | 22 ---------------------- source3/smbd/msdfs.c | 28 ++++++++++++---------------- 2 files changed, 12 insertions(+), 38 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 159b232b5f..5c75ed719e 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -84,28 +84,6 @@ connection_struct *conn_find(unsigned cnum) return NULL; } -/**************************************************************************** - Find a conn given a service name. -****************************************************************************/ - -connection_struct *conn_find_byname(const char *service) -{ - connection_struct *conn; - - for (conn=Connections;conn;conn=conn->next) { - if (strequal(lp_servicename(SNUM(conn)),service)) { - if (conn != Connections) { - /* Promote if not first. */ - DLIST_PROMOTE(Connections, conn); - } - return conn; - } - } - - return NULL; -} - - /**************************************************************************** find first available connection slot, starting from a random position. The randomisation stops problems with the server dieing and clients diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 04b9b7deaa..e4760ec461 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -36,13 +36,17 @@ extern uint32 global_client_caps; SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then send a local path, we have to cope with that too.... + If conn != NULL then ensure the provided service is + the one pointed to by the connection. + This version does everything using pointers within one copy of the pathname string, talloced on the struct dfs_path pointer (which must be talloced). This may be too clever to live.... JRA. **********************************************************************/ -static NTSTATUS parse_dfs_path(const char *pathname, +static NTSTATUS parse_dfs_path(connection_struct *conn, + const char *pathname, bool allow_wcards, struct dfs_path *pdp, /* MUST BE TALLOCED */ bool *ppath_contains_wcard) @@ -136,7 +140,10 @@ static NTSTATUS parse_dfs_path(const char *pathname, } /* Is this really our servicename ? */ - if (NULL == conn_find_byname(servicename)) { + if (conn && !( strequal(servicename, lp_servicename(SNUM(conn))) + || (strequal(servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), + get_current_username()) )) ) { DEBUG(10,("parse_dfs_path: %s is not our servicename\n", servicename)); @@ -624,7 +631,7 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - status = parse_dfs_path(path_in, search_wcard_flag, pdp, + status = parse_dfs_path(conn, path_in, search_wcard_flag, pdp, ppath_contains_wcard); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); @@ -665,17 +672,6 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, return NT_STATUS_OK; } - if (!( strequal(pdp->servicename, lp_servicename(SNUM(conn))) - || (strequal(pdp->servicename, HOMES_NAME) - && strequal(lp_servicename(SNUM(conn)), - get_current_username()) )) ) { - - /* The given sharename doesn't match this connection. */ - TALLOC_FREE(pdp); - - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } - status = dfs_path_lookup(ctx, conn, path_in, pdp, search_wcard_flag, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { @@ -759,7 +755,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, *self_referralp = False; - status = parse_dfs_path(dfs_path, False, pdp, &dummy); + status = parse_dfs_path(NULL, dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1245,7 +1241,7 @@ bool create_junction(TALLOC_CTX *ctx, if (!pdp) { return False; } - status = parse_dfs_path(dfs_path, False, pdp, &dummy); + status = parse_dfs_path(NULL, dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return False; } -- cgit From bdcc7ddc1ec692a9c8420426b8b2413bf0f7e1a2 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 20 May 2008 11:09:06 +0200 Subject: sesssetup.c: Add debug message. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Log when we kill other smbd sessions like when we hit the VC == 0 case. This one fixes BUG #5476. Initial patch from Björn Jacke . Karolin (This used to be commit 1429f3b7cf293994b334052428fcdadcee162dea) --- source3/smbd/sesssetup.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 5b00403140..f6aec7dddc 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1352,6 +1352,9 @@ static int shutdown_other_smbds(struct db_record *rec, return 0; } + DEBUG(0,("shutdown_other_smbds: shutting down pid %d " + "(IP %s)\n", crec->pid, ip)); + messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN, &data_blob_null); return 0; -- cgit From 8ca459e067c3d4f3495e0a6dafea7296e3dfb2ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 May 2008 12:09:48 -0700 Subject: Fix bug #5477 - recvfile code was broken. Jeremy. (This used to be commit 830337f054a6c0646d85df33d9958e99283e727a) --- source3/smbd/process.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ab737a89a7..c8ad19dd15 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -252,6 +252,8 @@ static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, timeout, toread); if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n", + nt_errstr(status))); return status; } } @@ -282,14 +284,8 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd, smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */ !srv_is_signing_active()) { - status = receive_smb_raw_talloc_partial_read( - mem_ctx, lenbuf, fd, buffer, timeout, p_unread, &len); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("receive_smb_raw: %s\n", - nt_errstr(status))); - return status; - } + return receive_smb_raw_talloc_partial_read( + mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen); } if (!valid_packet_size(len)) { -- cgit From fb37f156009611af0dd454a0fb0829a09cd638ac Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Tue, 29 Apr 2008 14:36:24 -0700 Subject: Cleanup size_t return values in callers of convert_string_allocate This patch is the second iteration of an inside-out conversion to cleanup functions in charcnv.c returning size_t == -1 to indicate failure. (This used to be commit 6b189dabc562d86dcaa685419d0cb6ea276f100d) --- source3/smbd/lanman.c | 9 ++++++++- source3/smbd/mangle_hash.c | 11 +++++++---- source3/smbd/message.c | 13 ++++++------- source3/smbd/negprot.c | 5 +++-- source3/smbd/trans2.c | 24 ++++++++++++++++-------- 5 files changed, 40 insertions(+), 22 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 413b916f7b..d6c76c54c1 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1896,6 +1896,7 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, unsigned int offset; int snum; int res = ERRunsup; + size_t converted_size; if (!str1 || !str2 || !p) { return False; @@ -1956,7 +1957,13 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid, return False; } - pull_ascii_talloc(talloc_tos(), &pathname, offset? (data+offset) : ""); + if (!pull_ascii_talloc(talloc_tos(), &pathname, + offset ? (data+offset) : "", &converted_size)) + { + DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s", + strerror(errno))); + } + if (!pathname) { return false; } diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 1dc9c67dcc..69ecf77834 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -294,8 +294,7 @@ static bool is_8_3(const char *fname, bool check_case, bool allow_wildcards, if (strlen(f) > 12) return False; - size = push_ucs2_allocate(&ucs2name, f); - if (size == (size_t)-1) { + if (!push_ucs2_allocate(&ucs2name, f, &size)) { DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n")); goto done; } @@ -604,9 +603,11 @@ static bool must_mangle(const char *name, { smb_ucs2_t *name_ucs2 = NULL; NTSTATUS status; + size_t converted_size; + magic_char = lp_magicchar(p); - if (push_ucs2_allocate(&name_ucs2, name) == (size_t)-1) { + if (!push_ucs2_allocate(&name_ucs2, name, &converted_size)) { DEBUG(0, ("push_ucs2_allocate failed!\n")); return False; } @@ -637,12 +638,14 @@ static bool hash_name_to_8_3(const char *in, const struct share_params *p) { smb_ucs2_t *in_ucs2 = NULL; + size_t converted_size; + magic_char = lp_magicchar(p); DEBUG(5,("hash_name_to_8_3( %s, cache83 = %s)\n", in, cache83 ? "True" : "False")); - if (push_ucs2_allocate(&in_ucs2, in) == (size_t)-1) { + if (!push_ucs2_allocate(&in_ucs2, in, &converted_size)) { DEBUG(0, ("push_ucs2_allocate failed!\n")); return False; } diff --git a/source3/smbd/message.c b/source3/smbd/message.c index a870f03df9..62df5c37eb 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -45,7 +45,7 @@ static void msg_deliver(struct msg_state *state) int i; int fd; char *msg; - int len; + size_t len; ssize_t sz; fstring alpha_buf; char *s; @@ -72,18 +72,17 @@ static void msg_deliver(struct msg_state *state) * Incoming message is in DOS codepage format. Convert to UNIX. */ - len = convert_string_talloc( - talloc_tos(), CH_DOS, CH_UNIX, state->msg, - talloc_get_size(state->msg), (void *)&msg, true); - - if (len == -1) { + if (!convert_string_talloc(talloc_tos(), CH_DOS, CH_UNIX, state->msg, + talloc_get_size(state->msg), (void *)&msg, + &len, true)) { DEBUG(3, ("Conversion failed, delivering message in DOS " "codepage format\n")); msg = state->msg; } for (i = 0; i < len; i++) { - if ((msg[i] == '\r') && (i < (len-1)) && (msg[i+1] == '\n')) { + if ((msg[i] == '\r') && + (i < (len-1)) && (msg[i+1] == '\n')) { continue; } sz = write(fd, &msg[i], 1); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 9f56949eeb..84f111fb02 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -516,6 +516,7 @@ void reply_negprot(struct smb_request *req) int num_cliprotos; char **cliprotos; int i; + size_t converted_size; static bool done_negprot = False; @@ -555,8 +556,8 @@ void reply_negprot(struct smb_request *req) cliprotos = tmp; - if (pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p) - == (size_t)-1) { + if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p, + &converted_size)) { DEBUG(0, ("pull_ascii_talloc failed\n")); TALLOC_FREE(cliprotos); reply_nterror(req, NT_STATUS_NO_MEMORY); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d5435533f9..72688bbd66 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -178,7 +178,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, char *p; char **names, **tmp; size_t num_names; - ssize_t sizeret; + ssize_t sizeret = -1; if (!lp_ea_support(SNUM(conn))) { *pnames = NULL; @@ -504,7 +504,7 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) { struct ea_list *ea_list_head = NULL; - size_t offset = 0; + size_t converted_size, offset = 0; while (offset + 2 < data_size) { struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); @@ -522,7 +522,11 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz if (pdata[offset + namelen] != '\0') { return NULL; } - pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]); + if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset], + &converted_size)) { + DEBUG(0,("read_ea_name_list: pull_ascii_talloc " + "failed: %s", strerror(errno))); + } if (!eal->ea.name) { return NULL; } @@ -544,6 +548,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); uint16 val_len; unsigned int namelen; + size_t converted_size; if (!eal) { return NULL; @@ -565,7 +570,10 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da if (pdata[namelen + 4] != '\0') { return NULL; } - pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4); + if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) { + DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s", + strerror(errno))); + } if (!eal->ea.name) { return NULL; } @@ -3665,10 +3673,10 @@ static NTSTATUS marshall_stream_info(unsigned int num_streams, size_t namelen; smb_ucs2_t *namebuf; - namelen = push_ucs2_talloc(talloc_tos(), &namebuf, - streams[i].name); - - if ((namelen == (size_t)-1) || (namelen <= 2)) { + if (!push_ucs2_talloc(talloc_tos(), &namebuf, + streams[i].name, &namelen) || + namelen <= 2) + { return NT_STATUS_INVALID_PARAMETER; } -- cgit From c38a1e06b5ada7325ba0fcebd7254475ae84a4de Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 20 May 2008 23:08:42 +0200 Subject: Fix type error in debug message (This used to be commit eb281532b1721ded39c39bb00c26202080dcd735) --- source3/smbd/sesssetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index f6aec7dddc..041596b953 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1353,7 +1353,7 @@ static int shutdown_other_smbds(struct db_record *rec, } DEBUG(0,("shutdown_other_smbds: shutting down pid %d " - "(IP %s)\n", crec->pid, ip)); + "(IP %s)\n", procid_to_pid(&crec->pid), ip)); messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN, &data_blob_null); -- cgit From f4d8141174cf75984978e80b6a040b98423089f6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 May 2008 01:02:52 +0200 Subject: Remove reference to current_user_info from lanman.c (This used to be commit f52d7c3faba4aa815d95883775f4859251406161) --- source3/smbd/lanman.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d6c76c54c1..fce58d069b 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -28,7 +28,6 @@ #include "includes.h" extern struct current_user current_user; -extern userdom_struct current_user_info; #ifdef CHECK_TYPES #undef CHECK_TYPES @@ -105,7 +104,7 @@ static int CopyExpanded(connection_struct *conn, conn->connectpath, conn->server_info->gid, get_current_username(), - current_user_info.domain, + pdb_get_domain(conn->server_info->sam_account), buf); if (!buf) { *p_space_remaining = 0; @@ -156,7 +155,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) conn->connectpath, conn->server_info->gid, get_current_username(), - current_user_info.domain, + pdb_get_domain(conn->server_info->sam_account), buf); if (!buf) { return 0; @@ -186,7 +185,7 @@ static char *Expand(connection_struct *conn, int snum, char *s) conn->connectpath, conn->server_info->gid, get_current_username(), - current_user_info.domain, + pdb_get_domain(conn->server_info->sam_account), buf); } @@ -3005,14 +3004,15 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, SIVAL(p,6,0); } else { SIVAL(p,6,PTR_DIFF(p2,*rdata)); - comment = talloc_sub_advanced(ctx, - lp_servicename(SNUM(conn)), - conn->server_info->unix_name, - conn->connectpath, - conn->server_info->gid, - get_current_username(), - current_user_info.domain, - comment); + comment = talloc_sub_advanced( + ctx, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, + conn->connectpath, + conn->server_info->gid, + get_current_username(), + pdb_get_domain(conn->server_info->sam_account), + comment); if (comment) { return false; } @@ -3111,7 +3111,7 @@ static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strlcpy(p2,current_user_info.smb_name,PTR_DIFF(endp,p2)); + strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; -- cgit From 320fadd8fc600262d26ea417a92d395aeb16ef57 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 May 2008 01:03:45 +0200 Subject: Remove the reference to current_user_info from share_access.c This required to pass around the domain a bit (This used to be commit 17b0db20d28d1b737c5e86b78106657e8ca5ce9c) --- source3/smbd/service.c | 1 + source3/smbd/share_access.c | 26 +++++++++++++++----------- source3/smbd/uid.c | 9 +++++++-- 3 files changed, 23 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c90d4d16bc..4092928de1 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -646,6 +646,7 @@ static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum, } } else { if (!user_ok_token(vuid_serverinfo->unix_name, + pdb_get_domain(vuid_serverinfo->sam_account), vuid_serverinfo->ptok, snum)) { DEBUG(2, ("user '%s' (from session setup) not " "permitted to access this share " diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index 512126254a..f5f79c86e5 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -27,8 +27,6 @@ * + and & may be combined */ -extern userdom_struct current_user_info; - static bool do_group_checks(const char **name, const char **pattern) { if ((*name)[0] == '@') { @@ -66,6 +64,7 @@ static bool do_group_checks(const char **name, const char **pattern) static bool token_contains_name(TALLOC_CTX *mem_ctx, const char *username, + const char *domain, const char *sharename, const struct nt_user_token *token, const char *name) @@ -75,8 +74,7 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx, enum lsa_SidType type; if (username != NULL) { - name = talloc_sub_basic(mem_ctx, username, - current_user_info.domain, name); + name = talloc_sub_basic(mem_ctx, username, domain, name); } if (sharename != NULL) { name = talloc_string_sub(mem_ctx, name, "%S", sharename); @@ -152,6 +150,7 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx, */ bool token_contains_name_in_list(const char *username, + const char *domain, const char *sharename, const struct nt_user_token *token, const char **list) @@ -167,7 +166,8 @@ bool token_contains_name_in_list(const char *username, } while (*list != NULL) { - if (token_contains_name(mem_ctx, username, sharename,token, *list)) { + if (token_contains_name(mem_ctx, username, domain, sharename, + token, *list)) { TALLOC_FREE(mem_ctx); return True; } @@ -191,10 +191,12 @@ bool token_contains_name_in_list(const char *username, * The other use is the netgroup check when using @group or &group. */ -bool user_ok_token(const char *username, struct nt_user_token *token, int snum) +bool user_ok_token(const char *username, const char *domain, + struct nt_user_token *token, int snum) { if (lp_invalid_users(snum) != NULL) { - if (token_contains_name_in_list(username, lp_servicename(snum), + if (token_contains_name_in_list(username, domain, + lp_servicename(snum), token, lp_invalid_users(snum))) { DEBUG(10, ("User %s in 'invalid users'\n", username)); @@ -203,7 +205,7 @@ bool user_ok_token(const char *username, struct nt_user_token *token, int snum) } if (lp_valid_users(snum) != NULL) { - if (!token_contains_name_in_list(username, + if (!token_contains_name_in_list(username, domain, lp_servicename(snum), token, lp_valid_users(snum))) { DEBUG(10, ("User %s not in 'valid users'\n", @@ -220,7 +222,8 @@ bool user_ok_token(const char *username, struct nt_user_token *token, int snum) DEBUG(0, ("'only user = yes' and no 'username ='\n")); return False; } - if (!token_contains_name_in_list(NULL, lp_servicename(snum), + if (!token_contains_name_in_list(NULL, domain, + lp_servicename(snum), token, list)) { DEBUG(10, ("%s != 'username'\n", username)); return False; @@ -248,12 +251,13 @@ bool user_ok_token(const char *username, struct nt_user_token *token, int snum) */ bool is_share_read_only_for_token(const char *username, + const char *domain, struct nt_user_token *token, int snum) { bool result = lp_readonly(snum); if (lp_readlist(snum) != NULL) { - if (token_contains_name_in_list(username, + if (token_contains_name_in_list(username, domain, lp_servicename(snum), token, lp_readlist(snum))) { result = True; @@ -261,7 +265,7 @@ bool is_share_read_only_for_token(const char *username, } if (lp_writelist(snum) != NULL) { - if (token_contains_name_in_list(username, + if (token_contains_name_in_list(username, domain, lp_servicename(snum), token, lp_writelist(snum))) { result = False; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 310ad4d23a..b0f8cb224b 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -78,12 +78,15 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) } if (!user_ok_token(vuser->server_info->unix_name, + pdb_get_domain(vuser->server_info->sam_account), vuser->server_info->ptok, snum)) return(False); readonly_share = is_share_read_only_for_token( - vuser->server_info->unix_name, vuser->server_info->ptok, + vuser->server_info->unix_name, + pdb_get_domain(vuser->server_info->sam_account), + vuser->server_info->ptok, SNUM(conn)); if (!readonly_share && @@ -127,7 +130,9 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->read_only = readonly_share; ent->admin_user = token_contains_name_in_list( - vuser->server_info->unix_name, NULL, vuser->server_info->ptok, + vuser->server_info->unix_name, + pdb_get_domain(vuser->server_info->sam_account), + NULL, vuser->server_info->ptok, lp_admin_users(SNUM(conn))); conn->read_only = ent->read_only; -- cgit From 50ab871813d8281760e0c70d454cba996e0b67d8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 May 2008 11:26:33 +0200 Subject: Remove some references to get_current_username() and current_user_info (This used to be commit 344d69f95e217d16213eaa6b53141af6ab459708) --- source3/smbd/lanman.c | 8 ++++---- source3/smbd/msdfs.c | 11 +++++++++++ source3/smbd/service.c | 20 ++++++++++---------- 3 files changed, 25 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index fce58d069b..31d4a39842 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -103,7 +103,7 @@ static int CopyExpanded(connection_struct *conn, conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), + conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), buf); if (!buf) { @@ -154,7 +154,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), + conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), buf); if (!buf) { @@ -184,7 +184,7 @@ static char *Expand(connection_struct *conn, int snum, char *s) conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), + conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), buf); } @@ -3010,7 +3010,7 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), + conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), comment); if (comment) { diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e4760ec461..de57d8def2 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -672,6 +672,17 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, return NT_STATUS_OK; } + if (!( strequal(pdp->servicename, lp_servicename(SNUM(conn))) + || (strequal(pdp->servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), + conn->server_info->sanitized_username) )) ) { + + /* The given sharename doesn't match this connection. */ + TALLOC_FREE(pdp); + + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + status = dfs_path_lookup(ctx, conn, path_in, pdp, search_wcard_flag, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4092928de1..fbce22e975 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -840,8 +840,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), - current_user_info.domain, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_pathname(snum)); if (!s) { conn_free(conn); @@ -962,8 +962,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), - current_user_info.domain, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_rootpreexec(snum)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); @@ -1001,8 +1001,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), - current_user_info.domain, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_preexec(snum)); ret = smbrun(cmd,NULL); TALLOC_FREE(cmd); @@ -1324,8 +1324,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), - current_user_info.domain, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_postexec(SNUM(conn))); smbrun(cmd,NULL); TALLOC_FREE(cmd); @@ -1340,8 +1340,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) conn->server_info->unix_name, conn->connectpath, conn->server_info->gid, - get_current_username(), - current_user_info.domain, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_rootpostexec(SNUM(conn))); smbrun(cmd,NULL); TALLOC_FREE(cmd); -- cgit From ae5135310737499dfe801df48fe554e5ba53a834 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 May 2008 21:13:05 -0700 Subject: Re-enable the evil "aio write behind" parameter. Jeremy. (This used to be commit 5d22ca00bcdf49dcb35468400ac8cc3c57808d0d) --- source3/smbd/service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index fbce22e975..ac233a97b7 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1025,6 +1025,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, set_namearray( &conn->veto_list, lp_veto_files(snum)); set_namearray( &conn->hide_list, lp_hide_files(snum)); set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); + set_namearray( &conn->aio_write_behind_list, + lp_aio_write_behind(snum)); } /* Invoke VFS make connection hook - do this before the VFS_STAT call -- cgit From 6811dc3fc236e62f042e43efa500cc55346c29d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 May 2008 11:23:59 -0700 Subject: Allow server manager to close open files selected by id. Jeremy. (This used to be commit 7eeed8bb41059ec2bddedb6a71deddeec7f33af2) --- source3/smbd/close.c | 34 ++++++++++++++++++++++++++++++++++ source3/smbd/oplock.c | 2 +- source3/smbd/server.c | 2 ++ 3 files changed, 37 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index df188bafe1..818b4c70a8 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -736,3 +736,37 @@ NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type) return status; } + +/**************************************************************************** + Deal with an (authorized) message to close a file given the share mode + entry. +****************************************************************************/ + +void msg_close_file(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + files_struct *fsp = NULL; + struct share_mode_entry e; + + message_to_share_mode_entry(&e, (char *)data->data); + + if(DEBUGLVL(10)) { + char *sm_str = share_mode_str(NULL, 0, &e); + if (!sm_str) { + smb_panic("talloc failed"); + } + DEBUG(10,("msg_close_file: got request to close share mode " + "entry %s\n", sm_str)); + TALLOC_FREE(sm_str); + } + + fsp = file_find_dif(e.id, e.share_file_id); + if (!fsp) { + DEBUG(10,("msg_close_file: failed to find file.\n")); + return; + } + close_file(fsp, NORMAL_CLOSE); +} diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c3409547fe..23411294df 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -824,7 +824,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) Linearize a share mode entry struct to an internal oplock break message. ****************************************************************************/ -void share_mode_entry_to_message(char *msg, struct share_mode_entry *e) +void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e) { SIVAL(msg,0,(uint32)e->pid.pid); SSVAL(msg,4,e->op_mid); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index cf02589864..035469cd62 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1392,6 +1392,8 @@ extern void build_options(bool screen); MSG_SMB_FORCE_TDIS, msg_force_tdis); messaging_register(smbd_messaging_context(), NULL, MSG_SMB_RELEASE_IP, msg_release_ip); + messaging_register(smbd_messaging_context(), NULL, + MSG_SMB_CLOSE_FILE, msg_close_file); if ((lp_keepalive() != 0) && !(event_add_idle(smbd_event_context(), NULL, -- cgit From 611072fc1cd94e6c9d56ce910fd13f007f6ecb84 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 28 May 2008 13:20:16 +0200 Subject: Fix Bug #5285. (libcap header mismatch) Can someone with gpfs available test this ? The only codepath using this function is the modules/gpfs.c module. The fix resolves at least the build issues Samba has with recent kernel / libcap versions by using the portable cap_get_proc()/cap_set_proc() interface (instead of using capget/capset). Guenther (This used to be commit 177955141247a4eb56ba0d82dc1add7f52175c40) --- source3/smbd/oplock_linux.c | 48 ++------------------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index fa7cb42bc6..08df228f8f 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -22,22 +22,6 @@ #if HAVE_KERNEL_OPLOCKS_LINUX -/* these can be removed when they are in glibc headers */ -struct cap_user_header { - uint32 version; - int pid; -} header; -struct cap_user_data { - uint32 effective; - uint32 permitted; - uint32 inheritable; -} data; - -extern int capget(struct cap_user_header * hdrp, - struct cap_user_data * datap); -extern int capset(struct cap_user_header * hdrp, - const struct cap_user_data * datap); - static SIG_ATOMIC_T signals_received; #define FD_PENDING_SIZE 100 static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; @@ -75,40 +59,12 @@ static void signal_handler(int sig, siginfo_t *info, void *unused) sys_select_signal(RT_SIGNAL_LEASE); } -/**************************************************************************** - Try to gain a linux capability. -****************************************************************************/ - -static void set_capability(unsigned capability) -{ -#ifndef _LINUX_CAPABILITY_VERSION -#define _LINUX_CAPABILITY_VERSION 0x19980330 -#endif - header.version = _LINUX_CAPABILITY_VERSION; - header.pid = 0; - - if (capget(&header, &data) == -1) { - DEBUG(3,("Unable to get kernel capabilities (%s)\n", - strerror(errno))); - return; - } - - if (0 == (data.effective & (1< Date: Wed, 28 May 2008 09:31:42 -0700 Subject: Security fix for CVE-2008-1105: Boundary failure when parsing SMB responses can result in a buffer overrun. Jeremy. (This used to be commit 23b825e9d2c74c5b940cf4d3aa56c18692259972) --- source3/smbd/process.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c8ad19dd15..71e38634b7 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -120,9 +120,7 @@ static bool valid_packet_size(size_t len) if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) { DEBUG(0,("Invalid packet length! (%lu bytes).\n", (unsigned long)len)); - if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) { - return false; - } + return false; } return true; } -- cgit From ad538bf0ab4ae10ff10ea71898875d2d35e25dea Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 14 Jun 2008 16:35:22 +0200 Subject: Compare the pointer "vuser" to NULL, not 0 (This used to be commit 5c916549f002d5e4e06f24d396a2bdca73d384c7) --- source3/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index b0f8cb224b..04796418bc 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -175,7 +175,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) "user\n")); return(True); } else if ((current_user.conn == conn) && - (vuser != 0) && (current_user.vuid == vuid) && + (vuser != NULL) && (current_user.vuid == vuid) && (current_user.ut.uid == vuser->server_info->uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); -- cgit From b935f4a2dca62d197195573ed868abe657a71993 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 14 Jun 2008 16:43:03 +0200 Subject: Consistently use snum in check_user_ok Most already used it, these two still used SNUM(conn), where the only caller of this routine (change_to_user) had set snum = SNUM(conn). (This used to be commit b14e59bfdbfb62494002e22d0665c4d420484245) --- source3/smbd/uid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 04796418bc..af992d7aee 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -87,7 +87,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) vuser->server_info->unix_name, pdb_get_domain(vuser->server_info->sam_account), vuser->server_info->ptok, - SNUM(conn)); + snum); if (!readonly_share && !share_access_check(vuser->server_info->ptok, lp_servicename(snum), @@ -133,7 +133,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) vuser->server_info->unix_name, pdb_get_domain(vuser->server_info->sam_account), NULL, vuser->server_info->ptok, - lp_admin_users(SNUM(conn))); + lp_admin_users(snum)); conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; -- cgit From ee6ee96af2cf6a5bf2b825883a9cb5f2ff64de5b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 14 Jun 2008 16:46:25 +0200 Subject: Group the access checks together in check_user_ok() (This used to be commit 45662b5e8b3c7bc39cb33c5d7deb7e9a91f30a8b) --- source3/smbd/uid.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index af992d7aee..54caca9405 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -66,6 +66,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) unsigned int i; struct vuid_cache_entry *ent = NULL; bool readonly_share; + bool admin_user; for (i=0; ivuid_cache.array[i]; @@ -105,6 +106,12 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) return False; } + admin_user = token_contains_name_in_list( + vuser->server_info->unix_name, + pdb_get_domain(vuser->server_info->sam_account), + NULL, vuser->server_info->ptok, + lp_admin_users(snum)); + ent = &conn->vuid_cache.array[conn->vuid_cache.next_entry]; conn->vuid_cache.next_entry = @@ -128,12 +135,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->vuid = vuser->vuid; ent->read_only = readonly_share; - - ent->admin_user = token_contains_name_in_list( - vuser->server_info->unix_name, - pdb_get_domain(vuser->server_info->sam_account), - NULL, vuser->server_info->ptok, - lp_admin_users(snum)); + ent->admin_user = admin_user; conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; -- cgit From 82d4806ce62a78b0eecc4805b7ecf7f77b196864 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 14 Jun 2008 16:55:02 +0200 Subject: Slight refactoring for check_user_ok: It only needs vuid and server_info (This used to be commit 68944ea1ea7a0a63b08cbfc703f5ee29d2627696) --- source3/smbd/uid.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 54caca9405..bded780c49 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -61,7 +61,9 @@ bool change_to_guest(void) later code can then mess with. ********************************************************************/ -static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) +static bool check_user_ok(connection_struct *conn, uint16_t vuid, + struct auth_serversupplied_info *server_info, + int snum) { unsigned int i; struct vuid_cache_entry *ent = NULL; @@ -70,7 +72,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) for (i=0; ivuid_cache.array[i]; - if (ent->vuid == vuser->vuid) { + if (ent->vuid == vuid) { conn->server_info = ent->server_info; conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; @@ -78,20 +80,18 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) } } - if (!user_ok_token(vuser->server_info->unix_name, - pdb_get_domain(vuser->server_info->sam_account), - vuser->server_info->ptok, - snum)) + if (!user_ok_token(server_info->unix_name, + pdb_get_domain(server_info->sam_account), + server_info->ptok, snum)) return(False); readonly_share = is_share_read_only_for_token( - vuser->server_info->unix_name, - pdb_get_domain(vuser->server_info->sam_account), - vuser->server_info->ptok, - snum); + server_info->unix_name, + pdb_get_domain(server_info->sam_account), + server_info->ptok, snum); if (!readonly_share && - !share_access_check(vuser->server_info->ptok, lp_servicename(snum), + !share_access_check(server_info->ptok, lp_servicename(snum), FILE_WRITE_DATA)) { /* smb.conf allows r/w, but the security descriptor denies * write. Fall back to looking at readonly. */ @@ -100,17 +100,16 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) "security descriptor\n")); } - if (!share_access_check(vuser->server_info->ptok, lp_servicename(snum), + if (!share_access_check(server_info->ptok, lp_servicename(snum), readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { return False; } admin_user = token_contains_name_in_list( - vuser->server_info->unix_name, - pdb_get_domain(vuser->server_info->sam_account), - NULL, vuser->server_info->ptok, - lp_admin_users(snum)); + server_info->unix_name, + pdb_get_domain(server_info->sam_account), + NULL, server_info->ptok, lp_admin_users(snum)); ent = &conn->vuid_cache.array[conn->vuid_cache.next_entry]; @@ -125,15 +124,14 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) */ ent->server_info = copy_serverinfo( - conn, - conn->force_user ? conn->server_info : vuser->server_info); + conn, conn->force_user ? conn->server_info : server_info); if (ent->server_info == NULL) { ent->vuid = UID_FIELD_INVALID; return false; } - ent->vuid = vuser->vuid; + ent->vuid = vuid; ent->read_only = readonly_share; ent->admin_user = admin_user; @@ -186,7 +184,7 @@ bool change_to_user(connection_struct *conn, uint16 vuid) snum = SNUM(conn); - if ((vuser) && !check_user_ok(conn, vuser, snum)) { + if ((vuser) && !check_user_ok(conn, vuid, vuser->server_info, snum)) { DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) " "not permitted access to share %s.\n", vuser->server_info->sanitized_username, -- cgit From 101162257c14338eb2df7f331b18bca41813bff7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 14 Jun 2008 16:59:07 +0200 Subject: Move connection-specific vuid cache clear to uid.c (This used to be commit 1025f687910ce40283c7344ed67ebd5bf31217b7) --- source3/smbd/conn.c | 17 ++--------------- source3/smbd/password.c | 2 +- source3/smbd/uid.c | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 16 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 5c75ed719e..1a67ac9b32 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -225,28 +225,15 @@ bool conn_idle_all(time_t t) Clear a vuid out of the validity cache, and as the 'owner' of a connection. ****************************************************************************/ -void conn_clear_vuid_cache(uint16 vuid) +void conn_clear_vuid_caches(uint16_t vuid) { connection_struct *conn; - unsigned int i; for (conn=Connections;conn;conn=conn->next) { if (conn->vuid == vuid) { conn->vuid = UID_FIELD_INVALID; } - - for (i=0; ivuid_cache.array[i]; - - if (ent->vuid == vuid) { - ent->vuid = UID_FIELD_INVALID; - TALLOC_FREE(ent->server_info); - ent->read_only = False; - ent->admin_user = False; - } - } + conn_clear_vuid_cache(conn, vuid); } } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 673a1a01c1..ebc72350b5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -127,7 +127,7 @@ void invalidate_vuid(uint16 vuid) /* clear the vuid from the 'cache' on each connection, and from the vuid 'owner' of connections */ - conn_clear_vuid_cache(vuid); + conn_clear_vuid_caches(vuid); TALLOC_FREE(vuser); num_validated_vuids--; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index bded780c49..2bc5595661 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -142,6 +142,28 @@ static bool check_user_ok(connection_struct *conn, uint16_t vuid, return(True); } +/**************************************************************************** + Clear a vuid out of the connection's vuid cache +****************************************************************************/ + +void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid) +{ + int i; + + for (i=0; ivuid_cache.array[i]; + + if (ent->vuid == vuid) { + ent->vuid = UID_FIELD_INVALID; + TALLOC_FREE(ent->server_info); + ent->read_only = False; + ent->admin_user = False; + } + } +} + /**************************************************************************** Become the user of a connection number without changing the security context stack, but modify the current_user entries. -- cgit From 704c99f34022170d613e17262c842cd8989049ee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jun 2008 11:39:31 +0200 Subject: Remove the reference to current_user from file_access.c conn holds the current user info (This used to be commit 093bc5f2b33ebf90e04bc17e51b1695b1b932bf2) --- source3/smbd/file_access.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 71f3291b9b..f72d6d1292 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -20,8 +20,6 @@ #include "includes.h" -extern struct current_user current_user; - #undef DBGC_CLASS #define DBGC_CLASS DBGC_ACLS @@ -44,7 +42,7 @@ bool can_access_file_acl(struct connection_struct *conn, return false; } - result = se_access_check(secdesc, current_user.nt_user_token, + result = se_access_check(secdesc, conn->server_info->ptok, access_mask, &access_granted, &status); TALLOC_FREE(secdesc); return result; @@ -81,13 +79,13 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) if (!S_ISDIR(sbuf.st_mode)) { return False; } - if (current_user.ut.uid == 0 || conn->admin_user) { + if (conn->server_info->uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; } /* Check primary owner write access. */ - if (current_user.ut.uid == sbuf.st_uid) { + if (conn->server_info->uid == sbuf.st_uid) { return (sbuf.st_mode & S_IWUSR) ? True : False; } @@ -108,7 +106,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) * for bug #3348. Don't assume owning sticky bit * directory means write access allowed. */ - if (current_user.ut.uid != sbuf_file.st_uid) { + if (conn->server_info->uid != sbuf_file.st_uid) { return False; } } @@ -137,7 +135,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n", (unsigned int)access_mask, fname )); - if (current_user.ut.uid == 0 || conn->admin_user) { + if (conn->server_info->uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; } @@ -150,7 +148,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT } /* Check primary owner access. */ - if (current_user.ut.uid == psbuf->st_uid) { + if (conn->server_info->uid == psbuf->st_uid) { switch (access_mask) { case FILE_READ_DATA: return (psbuf->st_mode & S_IRUSR) ? True : False; -- cgit From 3a5e1cacf1495a37143b15725c5d226088b2473a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jun 2008 11:40:33 +0200 Subject: Remove unused "extern struct current_user" from dir.c (This used to be commit b92cfd19b459caad34229dfe941cf15fd14a5ce0) --- source3/smbd/dir.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 7d584977df..caa1c41a4f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -24,8 +24,6 @@ This module implements directory related functions for Samba. */ -extern struct current_user current_user; - /* "Special" directory offsets. */ #define END_OF_DIRECTORY_OFFSET ((long)-1) #define START_OF_DIRECTORY_OFFSET ((long)0) -- cgit From d49de28f1154140f63670cfbf5093cdee6f16eb0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jun 2008 13:37:53 +0200 Subject: Remove the current_user reference from fake_file.c The current vuid is not only available there, it is also in the current smb_request structure. (This used to be commit c8fd5eef32a86888c7a28317f0fdf717a26b7d4c) --- source3/smbd/fake_file.c | 7 +++---- source3/smbd/open.c | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 565b557dd3..47982d4f00 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -19,8 +19,6 @@ #include "includes.h" -extern struct current_user current_user; - struct fake_file_type { const char *name; enum FAKE_FILE_TYPE type; @@ -101,6 +99,7 @@ enum FAKE_FILE_TYPE is_fake_file(const char *fname) ****************************************************************************/ NTSTATUS open_fake_file(connection_struct *conn, + uint16_t current_vuid, enum FAKE_FILE_TYPE fake_file_type, const char *fname, uint32 access_mask, @@ -110,7 +109,7 @@ NTSTATUS open_fake_file(connection_struct *conn, NTSTATUS status; /* access check */ - if (current_user.ut.uid != 0) { + if (conn->server_info->uid != 0) { DEBUG(3, ("open_fake_file_shared: access_denied to " "service[%s] file[%s] user[%s]\n", lp_servicename(SNUM(conn)), fname, @@ -129,7 +128,7 @@ NTSTATUS open_fake_file(connection_struct *conn, fsp->conn = conn; fsp->fh->fd = -1; - fsp->vuid = current_user.vuid; + fsp->vuid = current_vuid; fsp->fh->pos = -1; fsp->can_lock = False; /* Should this be true ? - No, JRA */ fsp->access_mask = access_mask; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 546128c0e5..9b847ec877 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2990,7 +2990,8 @@ NTSTATUS create_file(connection_struct *conn, * also tries a QUERY_FILE_INFO on the file and then * close it */ - status = open_fake_file(conn, fake_file_type, fname, + status = open_fake_file(conn, req->vuid, + fake_file_type, fname, access_mask, &fsp); if (!NT_STATUS_IS_OK(status)) { goto fail; -- cgit From b6c125e4e0201498e67405fe9065415d6f45abef Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jun 2008 13:41:16 +0200 Subject: Remove the current_user references from open.c current_user_info was "only" used in a debug msg, and current_user.ut.uid is also available via conn->server_info (This used to be commit d0386914ff0f7b0f1edc3302fdc6a25f211712fa) --- source3/smbd/open.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9b847ec877..5a1af42638 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -22,8 +22,6 @@ #include "includes.h" extern const struct generic_mapping file_generic_mapping; -extern struct current_user current_user; -extern userdom_struct current_user_info; extern bool global_client_failed_oplock_break; struct deferred_open_record { @@ -400,8 +398,7 @@ static NTSTATUS open_file(files_struct *fsp, fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *current_user_info.smb_name - ? current_user_info.smb_name : conn->server_info->unix_name, + conn->server_info->unix_name, fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); @@ -1850,7 +1847,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, new_file_created = True; } - set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); + set_share_mode(lck, fsp, conn->server_info->uid, 0, fsp->oplock_type, + new_file_created); /* Handle strange delete on close create semantics. */ if ((create_options & FILE_DELETE_ON_CLOSE) @@ -2249,7 +2247,7 @@ NTSTATUS open_directory(connection_struct *conn, return status; } - set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK, True); + set_share_mode(lck, fsp, conn->server_info->uid, 0, NO_OPLOCK, True); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ -- cgit From d314f7eab5d6fd5c14849abc553c43642b26cf54 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 17 Jun 2008 10:46:20 +0200 Subject: Add some debug to notify (This used to be commit 4394235378f85ccb911d662d95f1545a14240bdf) --- source3/smbd/notify.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index eb3384d9a4..139dfe7d5b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -114,6 +114,9 @@ static bool notify_marshall_changes(int num_changes, if (prs_offset(ps) > max_offset) { /* Too much data for client. */ + DEBUG(10, ("Client only wanted %d bytes, trying to " + "marshall %d bytes\n", (int)max_offset, + (int)prs_offset(ps))); return False; } } @@ -256,6 +259,9 @@ NTSTATUS change_notify_add_request(const struct smb_request *req, struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; + DEBUG(10, ("change_notify_add_request: Adding request for %s: " + "max_param = %d\n", fsp->fsp_name, (int)max_param)); + if (!(request = SMB_MALLOC_P(struct notify_change_request)) || !(map = SMB_MALLOC_P(struct notify_mid_map))) { SAFE_FREE(request); -- cgit From b172eb1d478aef1f1e6c8ea40486fe9895b0f9de Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 17 Jun 2008 23:58:49 +0200 Subject: file_access: remove unneeded stat buf parameter from can_access_file_acl(). This is a security descriptor level function only. Michael (This used to be commit 5931540fa1681f026fed42df387d17e43c493c47) --- source3/smbd/dir.c | 2 +- source3/smbd/file_access.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index caa1c41a4f..2d9e7e7527 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -934,7 +934,7 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S SMB_ASSERT(VALID_STAT(*pst)); - return can_access_file_acl(conn, name, pst, FILE_READ_DATA); + return can_access_file_acl(conn, name, FILE_READ_DATA); } /******************************************************************* diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index f72d6d1292..aaa114b950 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -24,7 +24,7 @@ #define DBGC_CLASS DBGC_ACLS bool can_access_file_acl(struct connection_struct *conn, - const char * fname, SMB_STRUCT_STAT *psbuf, + const char * fname, uint32_t access_mask) { bool result; @@ -114,7 +114,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) /* now for ACL checks */ - return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA); + return can_access_file_acl(conn, dname, FILE_WRITE_DATA); } /**************************************************************************** @@ -168,7 +168,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT /* now for ACL checks */ - return can_access_file_acl(conn, fname, psbuf, access_mask); + return can_access_file_acl(conn, fname, access_mask); } /**************************************************************************** -- cgit From 24e7f40687b9542543533e1a4820b8f3f0016f07 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 18 Jun 2008 00:02:28 +0200 Subject: smbd/dir.c: remove unneeded stat buf parameter from user_can_read_file() This is not needed anymore since user_can_access_file_acl() ist used. Michael (This used to be commit 3c349f773a52e3de693d3bb79f5060c9f1e01e41) --- source3/smbd/dir.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 2d9e7e7527..74cd63ddda 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -921,7 +921,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, use it for anything security sensitive. ********************************************************************/ -static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) +static bool user_can_read_file(connection_struct *conn, char *name) { /* * If user is a member of the Admin group @@ -932,8 +932,6 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return True; } - SMB_ASSERT(VALID_STAT(*pst)); - return can_access_file_acl(conn, name, FILE_READ_DATA); } @@ -1037,7 +1035,7 @@ bool is_visible_file(connection_struct *conn, const char *dir_path, const char * } /* Honour _hide unreadable_ option */ - if (hide_unreadable && !user_can_read_file(conn, entry, pst)) { + if (hide_unreadable && !user_can_read_file(conn, entry)) { DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry )); SAFE_FREE(entry); return False; -- cgit From aedce263a81a2ff167f25fa7ac865ac858a5cb90 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 18 Jun 2008 00:06:46 +0200 Subject: file_access: add a function header comment for can_access_file_acl(). Michael (This used to be commit 7d5fb873bde0a84de522650945effeaf602c759e) --- source3/smbd/file_access.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index aaa114b950..0552a16b50 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -23,6 +23,9 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_ACLS +/** + * Security descriptor / NT Token level access check function. + */ bool can_access_file_acl(struct connection_struct *conn, const char * fname, uint32_t access_mask) -- cgit From 7df309c339602d2d67e146441958818f626a0f6b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 12:03:31 +0200 Subject: Remove some code Did not measure it, but I think a single write is better than a read and a conditional branch (This used to be commit abe1bed665ad8d1dbf9177dcbb9344b25df9594c) --- source3/smbd/posix_acls.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 33042faf56..b83e3b692a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2207,9 +2207,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, posix_id unix_ug; enum ace_owner owner_type; - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; + entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) @@ -3684,9 +3682,7 @@ int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; + entry_id = SMB_ACL_NEXT_ENTRY; if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1) break; @@ -3724,9 +3720,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo SMB_ACL_PERMSET_T permset; mode_t perms; - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; + entry_id = SMB_ACL_NEXT_ENTRY; if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) return -1; @@ -4146,9 +4140,7 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; + entry_id = SMB_ACL_NEXT_ENTRY; if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) { DEBUG(5,("remove_posix_acl: failed to get tagtype from ACL on file %s (%s).\n", -- cgit From 066f6c856fccc791009f85492289276267e24bcf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 14:53:46 +0200 Subject: Fix checks in can_delete_file_in_directory() With at least NFSv4 ACLs around the write permission for the owner is a bogus check if we can delete a file in a directory. Like in Windows, there are two ways which can grant us such: First, the DELETE permission on the file itself, or if that does not help, the DELETE_CHILD permission on the directory. It might be a bit more code that runs, but essentially we should end up with the same set of syscalls in the non-acl case. (This used to be commit daa9b056645a45edfb3a70e3536011ebe5678970) --- source3/smbd/file_access.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 0552a16b50..e61a8c3a5a 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -87,11 +87,6 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) return True; } - /* Check primary owner write access. */ - if (conn->server_info->uid == sbuf.st_uid) { - return (sbuf.st_mode & S_IWUSR) ? True : False; - } - #ifdef S_ISVTX /* sticky bit means delete only by owner or root. */ if (sbuf.st_mode & S_ISVTX) { @@ -117,7 +112,21 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) /* now for ACL checks */ - return can_access_file_acl(conn, dname, FILE_WRITE_DATA); + /* + * There's two ways to get the permission to delete a file: First by + * having the DELETE bit on the file itself and second if that does + * not help, by the DELETE_CHILD bit on the containing directory. + * + * Here we check the other way round because with just posix + * permissions looking at the file itself will never grant DELETE, so + * by looking at the directory first we save one get_acl call. + */ + + if (can_access_file_acl(conn, dname, FILE_DELETE_CHILD)) { + return true; + } + + return can_access_file_acl(conn, fname, DELETE_ACCESS); } /**************************************************************************** -- cgit From 156cd09899c7328c164b55159c17b1947d97f9d8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 17 Jun 2008 16:22:43 +0200 Subject: RWX on a file does not imply DELETE access Without this the changed checks in can_delete_file_in_directory give DELETE access where there is none. So we can end up granting the ntcreate&x preparing the unlink where we should not, which leads to a NT_STATUS_ACCESS_DENIED at close time later, which in turn does *not* give the access denied error message in the Windows GUI. can_delete_file_in_directory will grant access now by looking at the directory permissions. (This used to be commit 51b5364c2afb3a18df4bec2bc1624760ccc01676) --- source3/smbd/posix_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b83e3b692a..e92a263ca0 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -904,7 +904,7 @@ static SEC_ACCESS map_canon_ace_perms(int snum, if (directory_ace) { nt_mask = UNIX_DIRECTORY_ACCESS_RWX; } else { - nt_mask = UNIX_ACCESS_RWX; + nt_mask = (UNIX_ACCESS_RWX & ~DELETE_ACCESS); } } else if ((perms & ALL_ACE_PERMS) == (mode_t)0) { /* -- cgit From 49ca8efa9199ba21e3a41cbe4abbea1ca4974d0e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 16:31:59 +0200 Subject: Remove the "current_user" arg from check_fsp check_fsp only used the vuid struct member anyway, and this is available in the smb_request structure as well. (This used to be commit 8d364c4c3311b406847158fc37e9208d298cf8ba) --- source3/smbd/nttrans.c | 2 +- source3/smbd/reply.c | 38 +++++++++++++++++++------------------- source3/smbd/trans2.c | 8 ++++---- 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index cbe1299cf7..61562b2de2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1520,7 +1520,7 @@ static void call_nt_transact_rename(connection_struct *conn, } fsp = file_fsp(SVAL(params, 0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { return; } srvstr_get_path_wcard(ctx, params, req->flags2, &new_name, params+4, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2506ff97e9..4427ba2ebd 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -327,13 +327,13 @@ size_t srvstr_get_path(TALLOC_CTX *ctx, ****************************************************************************/ bool check_fsp_open(connection_struct *conn, struct smb_request *req, - files_struct *fsp, struct current_user *user) + files_struct *fsp) { if (!(fsp) || !(conn)) { reply_nterror(req, NT_STATUS_INVALID_HANDLE); return False; } - if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) { + if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) { reply_nterror(req, NT_STATUS_INVALID_HANDLE); return False; } @@ -346,9 +346,9 @@ bool check_fsp_open(connection_struct *conn, struct smb_request *req, ****************************************************************************/ bool check_fsp(connection_struct *conn, struct smb_request *req, - files_struct *fsp, struct current_user *user) + files_struct *fsp) { - if (!check_fsp_open(conn, req, fsp, user)) { + if (!check_fsp_open(conn, req, fsp)) { return False; } if ((fsp)->is_directory) { @@ -2924,7 +2924,7 @@ void reply_lockread(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBlockread); return; } @@ -3032,7 +3032,7 @@ void reply_read(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBread); return; } @@ -3287,7 +3287,7 @@ void reply_read_and_X(struct smb_request *req) return; } - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBreadX); return; } @@ -3425,7 +3425,7 @@ void reply_writebraw(struct smb_request *req) } fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { error_to_writebrawerr(req); END_PROFILE(SMBwritebraw); return; @@ -3631,7 +3631,7 @@ void reply_writeunlock(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwriteunlock); return; } @@ -3738,7 +3738,7 @@ void reply_write(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwrite); return; } @@ -3968,7 +3968,7 @@ void reply_write_and_X(struct smb_request *req) startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); write_through = BITSETW(req->inbuf+smb_vwv7,0); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwriteX); return; } @@ -4087,7 +4087,7 @@ void reply_lseek(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { return; } @@ -4173,7 +4173,7 @@ void reply_flush(struct smb_request *req) fnum = SVAL(req->inbuf,smb_vwv0); fsp = file_fsp(fnum); - if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, ¤t_user)) { + if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) { return; } @@ -4320,7 +4320,7 @@ void reply_writeclose(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwriteclose); return; } @@ -4407,7 +4407,7 @@ void reply_lock(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBlock); return; } @@ -4466,7 +4466,7 @@ void reply_unlock(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBunlock); return; } @@ -4650,7 +4650,7 @@ void reply_printclose(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBsplclose); return; } @@ -4790,7 +4790,7 @@ void reply_printwrite(struct smb_request *req) fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBsplwr); return; } @@ -6624,7 +6624,7 @@ void reply_lockingX(struct smb_request *req) lock_timeout = IVAL(req->inbuf,smb_vwv4); large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBlockingX); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 72688bbd66..3a59be115e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3871,7 +3871,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } /* Initial check for valid fsp ptr. */ - if (!check_fsp_open(conn, req, fsp, ¤t_user)) { + if (!check_fsp_open(conn, req, fsp)) { return; } @@ -3914,7 +3914,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, /* * Original code - this is an open file. */ - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { return; } @@ -6568,7 +6568,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, fsp = file_fsp(SVAL(params,0)); /* Basic check for non-null fsp. */ - if (!check_fsp_open(conn, req, fsp, ¤t_user)) { + if (!check_fsp_open(conn, req, fsp)) { return; } info_level = SVAL(params,2); @@ -6621,7 +6621,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, /* * Original code - this is an open file. */ - if (!check_fsp(conn, req, fsp, ¤t_user)) { + if (!check_fsp(conn, req, fsp)) { return; } -- cgit From e40b6e296a91f87e0a238323fe1dbf76149487e0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 16:31:59 +0200 Subject: Remove the "current_user" arg from fsp_belongs_conn fsp_belongs_conn only used the vuid struct member anyway, and this is available in the smb_request structure as well. (This used to be commit 64e9372ab997739d46669c0cc4a4c6edb11d5e64) --- source3/smbd/nttrans.c | 6 +++--- source3/smbd/reply.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 61562b2de2..8e55d6b8e9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1773,7 +1773,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum)); - if (!fsp_belongs_conn(conn, req, fsp, ¤t_user)) { + if (!fsp_belongs_conn(conn, req, fsp)) { return; } @@ -1828,7 +1828,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, uint32 i; char *cur_pdata; - if (!fsp_belongs_conn(conn, req, fsp, ¤t_user)) { + if (!fsp_belongs_conn(conn, req, fsp)) { return; } @@ -1951,7 +1951,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum)); - if (!fsp_belongs_conn(conn, req, fsp, ¤t_user)) { + if (!fsp_belongs_conn(conn, req, fsp)) { return; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4427ba2ebd..f36c5c4d31 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -368,10 +368,10 @@ bool check_fsp(connection_struct *conn, struct smb_request *req, ****************************************************************************/ bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req, - files_struct *fsp, struct current_user *user) + files_struct *fsp) { if ((fsp) && (conn) && ((conn)==(fsp)->conn) - && (current_user.vuid==(fsp)->vuid)) { + && (req->vuid == (fsp)->vuid)) { return True; } -- cgit From 40f5eab5eb515937e1b23cf6762b77c194d29b9d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 16:54:12 +0200 Subject: Wrap the unix token info in a unix_user_token in auth_serversupplied_info No functional change, this is a preparation for more current_user ref removal (This used to be commit dcaedf345e62ab74ea87f0a3fa1e3199c75c5445) --- source3/smbd/connection.c | 4 ++-- source3/smbd/fake_file.c | 2 +- source3/smbd/file_access.c | 8 ++++---- source3/smbd/lanman.c | 12 ++++++------ source3/smbd/open.c | 7 ++++--- source3/smbd/password.c | 6 +++--- source3/smbd/sec_ctx.c | 2 +- source3/smbd/service.c | 12 ++++++------ source3/smbd/session.c | 4 ++-- source3/smbd/uid.c | 27 ++++++++++++++------------- 10 files changed, 43 insertions(+), 41 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 97f36971c8..8dd5964f5f 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -152,8 +152,8 @@ bool claim_connection(connection_struct *conn, const char *name, crec.pid = procid_self(); crec.cnum = conn?conn->cnum:-1; if (conn) { - crec.uid = conn->server_info->uid; - crec.gid = conn->server_info->gid; + crec.uid = conn->server_info->utok.uid; + crec.gid = conn->server_info->utok.gid; strlcpy(crec.servicename, lp_servicename(SNUM(conn)), sizeof(crec.servicename)); } diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index 47982d4f00..8dd9abee1a 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -109,7 +109,7 @@ NTSTATUS open_fake_file(connection_struct *conn, NTSTATUS status; /* access check */ - if (conn->server_info->uid != 0) { + if (conn->server_info->utok.uid != 0) { DEBUG(3, ("open_fake_file_shared: access_denied to " "service[%s] file[%s] user[%s]\n", lp_servicename(SNUM(conn)), fname, diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index e61a8c3a5a..84c993d06b 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -82,7 +82,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) if (!S_ISDIR(sbuf.st_mode)) { return False; } - if (conn->server_info->uid == 0 || conn->admin_user) { + if (conn->server_info->utok.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; } @@ -104,7 +104,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) * for bug #3348. Don't assume owning sticky bit * directory means write access allowed. */ - if (conn->server_info->uid != sbuf_file.st_uid) { + if (conn->server_info->utok.uid != sbuf_file.st_uid) { return False; } } @@ -147,7 +147,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n", (unsigned int)access_mask, fname )); - if (conn->server_info->uid == 0 || conn->admin_user) { + if (conn->server_info->utok.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return True; } @@ -160,7 +160,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT } /* Check primary owner access. */ - if (conn->server_info->uid == psbuf->st_uid) { + if (conn->server_info->utok.uid == psbuf->st_uid) { switch (access_mask) { case FILE_READ_DATA: return (psbuf->st_mode & S_IRUSR) ? True : False; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 31d4a39842..226e0d5789 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -102,7 +102,7 @@ static int CopyExpanded(connection_struct *conn, lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), buf); @@ -153,7 +153,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), buf); @@ -183,7 +183,7 @@ static char *Expand(connection_struct *conn, int snum, char *s) lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), buf); @@ -3009,7 +3009,7 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), comment); @@ -3346,7 +3346,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, user_struct *vuser = get_valid_user_struct(vuid); if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", - (int)vuser->server_info->uid, + (int)vuser->server_info->utok.uid, vuser->server_info->unix_name)); } @@ -3602,7 +3602,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", - (int)vuser->server_info->uid, + (int)vuser->server_info->utok.uid, vuser->server_info->unix_name)); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5a1af42638..3cec80c6df 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1847,8 +1847,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, new_file_created = True; } - set_share_mode(lck, fsp, conn->server_info->uid, 0, fsp->oplock_type, - new_file_created); + set_share_mode(lck, fsp, conn->server_info->utok.uid, 0, + fsp->oplock_type, new_file_created); /* Handle strange delete on close create semantics. */ if ((create_options & FILE_DELETE_ON_CLOSE) @@ -2247,7 +2247,8 @@ NTSTATUS open_directory(connection_struct *conn, return status; } - set_share_mode(lck, fsp, conn->server_info->uid, 0, NO_OPLOCK, True); + set_share_mode(lck, fsp, conn->server_info->utok.uid, 0, NO_OPLOCK, + True); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ebc72350b5..1d3514429f 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -271,8 +271,8 @@ int register_existing_vuid(uint16 vuid, vuser->server_info, tmp); DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", - (unsigned int)vuser->server_info->uid, - (unsigned int)vuser->server_info->gid, + (unsigned int)vuser->server_info->utok.uid, + (unsigned int)vuser->server_info->utok.gid, vuser->server_info->unix_name, vuser->server_info->sanitized_username, pdb_get_domain(vuser->server_info->sam_account), @@ -289,7 +289,7 @@ int register_existing_vuid(uint16 vuid, } DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, " - "and will be vuid %u\n", (int)vuser->server_info->uid, + "and will be vuid %u\n", (int)vuser->server_info->utok.uid, vuser->server_info->unix_name, vuser->vuid)); next_vuid++; diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 0f307f6a64..a618f06e6b 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -145,7 +145,7 @@ static void gain_root(void) Get the list of current groups. ****************************************************************************/ -static int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups) +static int get_current_groups(gid_t gid, size_t *p_ngroups, gid_t **p_groups) { int i; gid_t grp; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ac233a97b7..1ad48451ff 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -823,7 +823,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, status = find_forced_group( conn->force_user, snum, conn->server_info->unix_name, &conn->server_info->ptok->user_sids[1], - &conn->server_info->gid); + &conn->server_info->utok.gid); if (!NT_STATUS_IS_OK(status)) { conn_free(conn); @@ -839,7 +839,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), lp_pathname(snum)); @@ -961,7 +961,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), lp_rootpreexec(snum)); @@ -1000,7 +1000,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), lp_preexec(snum)); @@ -1325,7 +1325,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), lp_postexec(SNUM(conn))); @@ -1341,7 +1341,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, - conn->server_info->gid, + conn->server_info->utok.gid, conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), lp_rootpostexec(SNUM(conn))); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 5e5a184efa..3b431a19be 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -168,8 +168,8 @@ bool session_claim(user_struct *vuser) fstrcpy(sessionid.hostname, hostname); sessionid.id_num = i; /* Only valid for utmp sessions */ sessionid.pid = pid; - sessionid.uid = vuser->server_info->uid; - sessionid.gid = vuser->server_info->gid; + sessionid.uid = vuser->server_info->utok.uid; + sessionid.gid = vuser->server_info->utok.gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); fstrcpy(sessionid.ip_addr_str, client_addr(get_client_fd(),addr,sizeof(addr))); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 2bc5595661..8998f6a371 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -192,13 +192,13 @@ bool change_to_user(connection_struct *conn, uint16 vuid) */ if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && - (current_user.ut.uid == conn->server_info->uid)) { + (current_user.ut.uid == conn->server_info->utok.uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); return(True); } else if ((current_user.conn == conn) && (vuser != NULL) && (current_user.vuid == vuid) && - (current_user.ut.uid == vuser->server_info->uid)) { + (current_user.ut.uid == vuser->server_info->utok.uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); return(True); @@ -221,15 +221,15 @@ bool change_to_user(connection_struct *conn, uint16 vuid) */ if (conn->force_user) /* security = share sets this too */ { - uid = conn->server_info->uid; - gid = conn->server_info->gid; - group_list = conn->server_info->groups; - num_groups = conn->server_info->n_groups; + uid = conn->server_info->utok.uid; + gid = conn->server_info->utok.gid; + group_list = conn->server_info->utok.groups; + num_groups = conn->server_info->utok.ngroups; } else if (vuser) { - uid = conn->admin_user ? 0 : vuser->server_info->uid; - gid = conn->server_info->gid; - num_groups = conn->server_info->n_groups; - group_list = conn->server_info->groups; + uid = conn->admin_user ? 0 : vuser->server_info->utok.uid; + gid = conn->server_info->utok.gid; + num_groups = conn->server_info->utok.ngroups; + group_list = conn->server_info->utok.groups; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " "share %s.\n",vuid, lp_servicename(snum) )); @@ -255,15 +255,16 @@ bool change_to_user(connection_struct *conn, uint16 vuid) int i; for (i = 0; i < num_groups; i++) { - if (group_list[i] == conn->server_info->gid) { - gid = conn->server_info->gid; + if (group_list[i] + == conn->server_info->utok.gid) { + gid = conn->server_info->utok.gid; gid_to_sid(&conn->server_info->ptok ->user_sids[1], gid); break; } } } else { - gid = conn->server_info->gid; + gid = conn->server_info->utok.gid; gid_to_sid(&conn->server_info->ptok->user_sids[1], gid); } -- cgit From f1cd0bdbccd36e202f69ffa2dbbc9d9bdb060db0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 18:21:41 +0200 Subject: Remove reference to current_user from reply.c (This used to be commit e895e44cc7d675d128430fb53c138e5e8736e59f) --- source3/smbd/reply.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f36c5c4d31..f12dbdc8f3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -32,7 +32,6 @@ extern int max_recv; unsigned int smb_echo_count = 0; extern uint32 global_client_caps; -extern struct current_user current_user; extern bool global_encrypted_passwords_negotiated; /**************************************************************************** @@ -2334,7 +2333,7 @@ static NTSTATUS do_unlink(connection_struct *conn, } /* The set is across all open files on this dev/inode pair. */ - if (!set_delete_on_close(fsp, True, ¤t_user.ut)) { + if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) { close_file(fsp, NORMAL_CLOSE); return NT_STATUS_ACCESS_DENIED; } @@ -2789,7 +2788,7 @@ void reply_readbraw(struct smb_request *req) */ if (!fsp || !conn || conn != fsp->conn || - current_user.vuid != fsp->vuid || + req->vuid != fsp->vuid || fsp->is_directory || fsp->fh->fd == -1) { /* * fsp could be NULL here so use the value from the packet. JRA. @@ -4246,7 +4245,7 @@ void reply_close(struct smb_request *req) * We can only use CHECK_FSP if we know it's not a directory. */ - if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) { + if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) { reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBclose); return; -- cgit From e901466061bbbbe0c7b5dc9856346a308d80506b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 18:36:54 +0200 Subject: Remove some current_user references from trans2.c (This used to be commit 4c31cc0b62f532eafdc44398b29b773ad8cb0646) --- source3/smbd/trans2.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3a59be115e..ee966ad8cd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2833,7 +2833,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned fsp.fnum = -1; /* access check */ - if (current_user.ut.uid != 0) { + if (conn->server_info->utok.uid != 0) { DEBUG(0,("set_user_quota: access_denied " "service [%s] user [%s]\n", lp_servicename(SNUM(conn)), @@ -2997,7 +2997,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned * in our list of SIDs. */ if (nt_token_check_sid(&global_sid_Builtin_Guests, - current_user.nt_user_token)) { + conn->server_info->ptok)) { flags |= SMB_WHOAMI_GUEST; } @@ -3005,7 +3005,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned * is in our list of SIDs. */ if (nt_token_check_sid(&global_sid_Authenticated_Users, - current_user.nt_user_token)) { + conn->server_info->ptok)) { flags &= ~SMB_WHOAMI_GUEST; } @@ -3021,16 +3021,18 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned + 4 /* num_sids */ + 4 /* SID bytes */ + 4 /* pad/reserved */ - + (current_user.ut.ngroups * 8) + + (conn->server_info->utok.ngroups * 8) /* groups list */ - + (current_user.nt_user_token->num_sids * + + (conn->server_info->ptok->num_sids * SID_MAX_SIZE) /* SID list */; SIVAL(pdata, 0, flags); SIVAL(pdata, 4, SMB_WHOAMI_MASK); - SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid); - SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid); + SBIG_UINT(pdata, 8, + (SMB_BIG_UINT)conn->server_info->utok.uid); + SBIG_UINT(pdata, 16, + (SMB_BIG_UINT)conn->server_info->utok.gid); if (data_len >= max_data_bytes) { @@ -3045,18 +3047,18 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned break; } - SIVAL(pdata, 24, current_user.ut.ngroups); - SIVAL(pdata, 28, - current_user.nt_user_token->num_sids); + SIVAL(pdata, 24, conn->server_info->utok.ngroups); + SIVAL(pdata, 28, conn->server_info->num_sids); /* We walk the SID list twice, but this call is fairly * infrequent, and I don't expect that it's performance * sensitive -- jpeach */ for (i = 0, sid_bytes = 0; - i < current_user.nt_user_token->num_sids; ++i) { + i < conn->server_info->ptok->num_sids; ++i) { sid_bytes += ndr_size_dom_sid( - ¤t_user.nt_user_token->user_sids[i], 0); + &conn->server_info->ptok->user_sids[i], + 0); } /* SID list byte count */ @@ -3067,20 +3069,21 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned data_len = 40; /* GID list */ - for (i = 0; i < current_user.ut.ngroups; ++i) { + for (i = 0; i < conn->server_info->utok.ngroups; ++i) { SBIG_UINT(pdata, data_len, - (SMB_BIG_UINT)current_user.ut.groups[i]); + (SMB_BIG_UINT)conn->server_info->utok.groups[i]); data_len += 8; } /* SID list */ for (i = 0; - i < current_user.nt_user_token->num_sids; ++i) { + i < conn->server_info->ptok->num_sids; ++i) { int sid_len = ndr_size_dom_sid( - ¤t_user.nt_user_token->user_sids[i], 0); + &conn->server_info->ptok->user_sids[i], + 0); sid_linearize(pdata + data_len, sid_len, - ¤t_user.nt_user_token->user_sids[i]); + &conn->server_info->ptok->user_sids[i]); data_len += sid_len; } @@ -3275,7 +3278,8 @@ cap_low = 0x%x, cap_high = 0x%x\n", ZERO_STRUCT(quotas); /* access check */ - if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) { + if ((conn->server_info->utok.uid != 0) + ||!CAN_WRITE(conn)) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)), conn->server_info->unix_name)); @@ -3288,6 +3292,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", * --metze */ fsp = file_fsp(SVAL(params,0)); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); reply_nterror( @@ -5092,7 +5097,8 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, } /* The set is across all open files on this dev/inode pair. */ - if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) { + if (!set_delete_on_close(fsp, delete_on_close, + &conn->server_info->utok)) { return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK; -- cgit From 52664f62ba84719a9ea6eb8f9c01f1f3a9bd1b24 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 18:46:57 +0200 Subject: Remove current_user references from trans2.c This involved replacing the CHECK_NTQUOTA_HANDLE_OK macro by a function. (This used to be commit 5595cdf837edb82db69a3e57bcf3108be7feeeb8) --- source3/smbd/nttrans.c | 4 ++-- source3/smbd/reply.c | 31 +++++++++++++++++++++++++++++++ source3/smbd/trans2.c | 4 ++-- 3 files changed, 35 insertions(+), 4 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8e55d6b8e9..ad5db7a3e7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2056,7 +2056,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, /* maybe we can check the quota_fnum */ fsp = file_fsp(SVAL(params,0)); - if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + if (!check_fsp_ntquota_handle(conn, req, fsp)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); reply_nterror(req, NT_STATUS_INVALID_HANDLE); return; @@ -2323,7 +2323,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, /* maybe we can check the quota_fnum */ fsp = file_fsp(SVAL(params,0)); - if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + if (!check_fsp_ntquota_handle(conn, req, fsp)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); reply_nterror(req, NT_STATUS_INVALID_HANDLE); return; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f12dbdc8f3..aaa284dc39 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -362,6 +362,37 @@ bool check_fsp(connection_struct *conn, struct smb_request *req, return True; } +/**************************************************************************** + Check if we have a correct fsp pointing to a quota fake file. Replacement for + the CHECK_NTQUOTA_HANDLE_OK macro. +****************************************************************************/ + +bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req, + files_struct *fsp) +{ + if (!check_fsp_open(conn, req, fsp)) { + return false; + } + + if (fsp->is_directory) { + return false; + } + + if (fsp->fake_file_handle == NULL) { + return false; + } + + if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) { + return false; + } + + if (fsp->fake_file_handle->private_data == NULL) { + return false; + } + + return true; +} + /**************************************************************************** Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ee966ad8cd..881b29c6f0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -28,7 +28,6 @@ extern int max_send; extern enum protocol_types Protocol; extern uint32 global_client_caps; -extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) #define DIR_ENTRY_SAFETY_MARGIN 4096 @@ -3293,7 +3292,8 @@ cap_low = 0x%x, cap_high = 0x%x\n", */ fsp = file_fsp(SVAL(params,0)); - if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + if (!check_fsp_ntquota_handle(conn, req, + fsp)) { DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); reply_nterror( req, NT_STATUS_INVALID_HANDLE); -- cgit From be5dc4f3c82210860661954cad81bcb37d495db7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 18:48:10 +0200 Subject: Remove current_user references from nttrans.c (This used to be commit 5f8a5e68ea166fbeda3af6e5ec381ec09d06f0f6) --- source3/smbd/nttrans.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ad5db7a3e7..12f4da627b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -22,7 +22,6 @@ extern int max_send; extern enum protocol_types Protocol; -extern struct current_user current_user; static const char *known_nt_pipes[] = { "\\LANMAN", @@ -2036,7 +2035,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn, ZERO_STRUCT(qt); /* access check */ - if (current_user.ut.uid != 0) { + if (conn->server_info->utok.uid != 0) { DEBUG(1,("get_user_quota: access_denied service [%s] user " "[%s]\n", lp_servicename(SNUM(conn)), conn->server_info->unix_name)); @@ -2303,7 +2302,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn, ZERO_STRUCT(qt); /* access check */ - if (current_user.ut.uid != 0) { + if (conn->server_info->utok.uid != 0) { DEBUG(1,("set_user_quota: access_denied service [%s] user " "[%s]\n", lp_servicename(SNUM(conn)), conn->server_info->unix_name)); -- cgit From a8ae3bc317c9fb0c77798b361e54efff6cdb8a9b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 21 Jun 2008 16:39:05 +0200 Subject: Fix a double-closedir() in form_junctions() (This used to be commit 1d7ad0dea7ebf7a46af6e695797e5132264307d6) --- source3/smbd/msdfs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index de57d8def2..25b22f4cc0 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1541,7 +1541,6 @@ static int form_junctions(TALLOC_CTX *ctx, while ((dname = vfs_readdirname(conn, dirp)) != NULL) { char *link_target = NULL; if (cnt >= jn_remain) { - SMB_VFS_CLOSEDIR(conn,dirp); DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); goto out; -- cgit From 62f69165f6b66e149055ba431a48aab1a67c4215 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 12:50:30 +0200 Subject: Fix an uninitialized variable access in callers of parse_msdfs_symlink At least form_junctions() does not initialize refcount, and I don't see it in get_referred_path(). For the latters, the callers might initialize it. But even if they did, I think parse_msdfs_symlink() should unconditionally return the number of referrals it found. I don't think it makes sense to count them up from somewhere else. (This used to be commit 73172113484a2c6c9af014f59e84707716c61a7d) --- source3/smbd/msdfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 25b22f4cc0..bdcdc92df2 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -370,9 +370,10 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, reflist[i].ttl = REFERRAL_TTL; DEBUG(10, ("parse_msdfs_symlink: Created alt path: %s\n", reflist[i].alternate_path)); - *refcount += 1; } + *refcount = count; + TALLOC_FREE(alt_path); return True; } -- cgit From 65f7457583e7074ab5c07aa23f1281289fe66359 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 13:06:35 +0200 Subject: Fix a crash in _dfs_Enum (cherry picked from commit 4a996476297963d4cb300b4d45c23e83a493c339) (This used to be commit 86cae83a7db87063ecd6e58eaa15f11441c45040) --- source3/smbd/msdfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index bdcdc92df2..84ee282372 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1504,6 +1504,7 @@ static int form_junctions(TALLOC_CTX *ctx, if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { goto out; } + jucn[cnt].comment = ""; jucn[cnt].referral_count = 1; ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral); @@ -1563,6 +1564,7 @@ static int form_junctions(TALLOC_CTX *ctx, !jucn[cnt].volume_name) { goto out; } + jucn[cnt].comment = ""; cnt++; } } -- cgit From b4587a7c78fc8452f87f114b07b574180a3ea159 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 18:36:37 +0200 Subject: Fix an abort in junction_to_local_path (This used to be commit 587bd636cb70d09600111ced040adaa55af35d0f) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 84ee282372..df30257fcc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1308,7 +1308,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, return False; } - *pp_path_out = talloc_asprintf(conn_out, + *pp_path_out = talloc_asprintf(*conn_out, "%s/%s", lp_pathname(snum), jucn->volume_name); -- cgit From a7e284c62d4b961780130a3ae8594094f1fb841d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 11:28:57 +0200 Subject: Reduce memory usage in form_junctions() a little bit (This used to be commit d031e6d8cabe2dd0b29e90d173d45843e145176a) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index df30257fcc..bc7cd81337 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1567,6 +1567,7 @@ static int form_junctions(TALLOC_CTX *ctx, jucn[cnt].comment = ""; cnt++; } + TALLOC_FREE(link_target); } } -- cgit From 13ebf889b39e0b71f1f98198b0d003f5461d42a6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 20:33:28 +0200 Subject: Remove the "exists" parameter from create_msdfs_link Jeremy, setting "exists" to True in _dfs_Add prevented the initial creation of a new symlink for me, because the SMB_VFS_UNLINK failed. This also exists in 3.2. I only check it into 3.3 as I would like you to look at it first. Thanks, Volker (This used to be commit f58b098a4172949018e84c4d0c722d6eb9bba514) --- source3/smbd/msdfs.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index bc7cd81337..062ab804cc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1318,8 +1318,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, return True; } -bool create_msdfs_link(const struct junction_map *jucn, - bool exists) +bool create_msdfs_link(const struct junction_map *jucn) { char *path = NULL; char *msdfs_link = NULL; @@ -1369,19 +1368,20 @@ bool create_msdfs_link(const struct junction_map *jucn, DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); - if(exists) { - if(SMB_VFS_UNLINK(conn,path)!=0) { + if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { + if (errno == EEXIST) { + if(SMB_VFS_UNLINK(conn,path)!=0) { + goto out; + } + } + if (SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { + DEBUG(1,("create_msdfs_link: symlink failed " + "%s -> %s\nError: %s\n", + path, msdfs_link, strerror(errno))); goto out; } } - if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { - DEBUG(1,("create_msdfs_link: symlink failed " - "%s -> %s\nError: %s\n", - path, msdfs_link, strerror(errno))); - goto out; - } - ret = True; out: -- cgit From 344941bb49d91e6b382196c347e5259e133f506d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 22:19:10 +0200 Subject: Move the responsibility to keep the cwd from srv_dfs_nt to msdfs.c (This used to be commit 7db382588ac90fe250b72cf4cd07afb39fcae7c0) --- source3/smbd/msdfs.c | 70 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 17 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 062ab804cc..8e83a6c17e 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -218,10 +218,12 @@ static NTSTATUS parse_dfs_path(connection_struct *conn, static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, connection_struct **pconn, int snum, - const char *path) + const char *path, + char **poldcwd) { connection_struct *conn; char *connpath; + char *oldcwd; conn = TALLOC_ZERO_P(ctx, connection_struct); if (conn == NULL) { @@ -267,6 +269,14 @@ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, * user we will fail.... WTF ? JRA. */ + oldcwd = vfs_GetWd(ctx, conn); + if (oldcwd == NULL) { + NTSTATUS status = map_nt_error_from_unix(errno); + DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno))); + conn_free_internal(conn); + return status; + } + if (vfs_ChDir(conn,conn->connectpath) != 0) { NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. " @@ -277,6 +287,7 @@ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, } *pconn = conn; + *poldcwd = oldcwd; return NT_STATUS_OK; } @@ -760,6 +771,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, NTSTATUS status = NT_STATUS_NOT_FOUND; bool dummy; struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); + char *oldpath; if (!pdp) { return NT_STATUS_NO_MEMORY; @@ -868,7 +880,8 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_OK; } - status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum)); + status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum), + &oldpath); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -883,6 +896,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); + vfs_ChDir(conn, oldpath); conn_free_internal(conn); TALLOC_FREE(pdp); return status; @@ -894,11 +908,13 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, &jucn->referral_count)) { DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); + vfs_ChDir(conn, oldpath); conn_free_internal(conn); TALLOC_FREE(pdp); return NT_STATUS_NOT_FOUND; } + vfs_ChDir(conn, oldpath); conn_free_internal(conn); TALLOC_FREE(pdp); return NT_STATUS_OK; @@ -1293,18 +1309,20 @@ bool create_junction(TALLOC_CTX *ctx, **********************************************************************/ static bool junction_to_local_path(const struct junction_map *jucn, - char **pp_path_out, - connection_struct **conn_out) + char **pp_path_out, + connection_struct **conn_out, + char **oldpath) { int snum; + NTSTATUS status; snum = lp_servicenumber(jucn->service_name); if(snum < 0) { return False; } - if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), - conn_out, snum, - lp_pathname(snum)))) { + status = create_conn_struct(talloc_tos(), conn_out, snum, + lp_pathname(snum), oldpath); + if (!NT_STATUS_IS_OK(status)) { return False; } @@ -1313,6 +1331,8 @@ static bool junction_to_local_path(const struct junction_map *jucn, lp_pathname(snum), jucn->volume_name); if (!*pp_path_out) { + vfs_ChDir(*conn_out, *oldpath); + conn_free_internal(*conn_out); return False; } return True; @@ -1321,13 +1341,14 @@ static bool junction_to_local_path(const struct junction_map *jucn, bool create_msdfs_link(const struct junction_map *jucn) { char *path = NULL; + char *cwd; char *msdfs_link = NULL; connection_struct *conn; int i=0; bool insert_comma = False; bool ret = False; - if(!junction_to_local_path(jucn, &path, &conn)) { + if(!junction_to_local_path(jucn, &path, &conn, &cwd)) { return False; } @@ -1385,7 +1406,7 @@ bool create_msdfs_link(const struct junction_map *jucn) ret = True; out: - + vfs_ChDir(conn, cwd); conn_free_internal(conn); return ret; } @@ -1393,15 +1414,19 @@ out: bool remove_msdfs_link(const struct junction_map *jucn) { char *path = NULL; + char *cwd; connection_struct *conn; bool ret = False; - if( junction_to_local_path(jucn, &path, &conn) ) { - if( SMB_VFS_UNLINK(conn, path) == 0 ) { - ret = True; - } + if (!junction_to_local_path(jucn, &path, &conn, &cwd)) { + return false; + } + + if( SMB_VFS_UNLINK(conn, path) == 0 ) { + ret = True; } + vfs_ChDir(conn, cwd); conn_free_internal(conn); return ret; } @@ -1418,6 +1443,8 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) const char *connect_path = lp_pathname(snum); const char *msdfs_proxy = lp_msdfs_proxy(snum); connection_struct *conn; + NTSTATUS status; + char *cwd; if(*connect_path == '\0') { return 0; @@ -1427,8 +1454,11 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), - &conn, snum, connect_path))) { + status = create_conn_struct(talloc_tos(), &conn, snum, connect_path, + &cwd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("create_conn_struct failed: %s\n", + nt_errstr(status))); return 0; } @@ -1457,7 +1487,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) SMB_VFS_CLOSEDIR(conn,dirp); out: - + vfs_ChDir(conn, cwd); conn_free_internal(conn); return cnt; } @@ -1478,6 +1508,8 @@ static int form_junctions(TALLOC_CTX *ctx, const char *msdfs_proxy = lp_msdfs_proxy(snum); connection_struct *conn; struct referral *ref = NULL; + char *cwd; + NTSTATUS status; if (jn_remain == 0) { return 0; @@ -1491,7 +1523,10 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(ctx, &conn, snum, connect_path))) { + status = create_conn_struct(ctx, &conn, snum, connect_path, &cwd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("create_conn_struct failed: %s\n", + nt_errstr(status))); return 0; } @@ -1577,6 +1612,7 @@ out: SMB_VFS_CLOSEDIR(conn,dirp); } + vfs_ChDir(conn, cwd); conn_free_internal(conn); return cnt; } -- cgit From 8b6d41b3b083dd5876e8fbfdce4afed191b8da0f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 23 Jun 2008 17:32:32 +0200 Subject: smbd: don't panic if messaging_init() fails but return NULL leaving panic or more appropriate action to callers. This can for instance happen in a clustered setup, when ctdb is not running. This allows for a more defined behaviour, reducing chicken-egg-problems. Michael (This used to be commit 3b6541ff483d5fea4fd30bb6a01a560c05028d4e) --- source3/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 035469cd62..ed07e5c02b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -92,7 +92,7 @@ struct messaging_context *smbd_messaging_context(void) if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), smbd_event_context()))) { - smb_panic("Could not init smbd messaging context"); + DEBUG(0, ("Could not init smbd messaging context.\n")); } return ctx; } -- cgit From 59634c91ec08c1f1f0f3d1c5af985b7b381cb1ac Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 23 Jun 2008 17:35:08 +0200 Subject: smbd: untangle logic in smbd_messaging_context() slightly. Michael (This used to be commit fae4c21b14b9d288e06f6b4b4e1527e2c6d58dca) --- source3/smbd/server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index ed07e5c02b..4a0e60a8d7 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -90,8 +90,11 @@ struct messaging_context *smbd_messaging_context(void) { static struct messaging_context *ctx; - if (!ctx && !(ctx = messaging_init(NULL, server_id_self(), - smbd_event_context()))) { + if (ctx == NULL) { + ctx = messaging_init(NULL, server_id_self(), + smbd_event_context()); + } + if (ctx == NULL) { DEBUG(0, ("Could not init smbd messaging context.\n")); } return ctx; -- cgit From a3c0be63256b7db6325d8dcb599497e8e7905f08 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 24 Jun 2008 16:03:28 +0200 Subject: Change print_access_check to take auth_serversupplied_info instead of current_user Reason: This is the main user of p->current_user which I would like to remove (This used to be commit fd43059b3dfa8cdac9814de1c76f963ba5de9bcb) --- source3/smbd/lanman.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 226e0d5789..29703ffd1e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -2682,15 +2682,15 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, switch (function) { case 81: /* delete */ - if (print_job_delete(¤t_user, snum, jobid, &werr)) + if (print_job_delete(conn->server_info, snum, jobid, &werr)) errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(¤t_user, snum, jobid, &werr)) + if (print_job_pause(conn->server_info, snum, jobid, &werr)) errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(¤t_user, snum, jobid, &werr)) + if (print_job_resume(conn->server_info, snum, jobid, &werr)) errcode = NERR_Success; break; } @@ -2751,13 +2751,19 @@ static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, switch (function) { case 74: /* Pause queue */ - if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success; + if (print_queue_pause(conn->server_info, snum, &werr)) { + errcode = NERR_Success; + } break; case 75: /* Resume queue */ - if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success; + if (print_queue_resume(conn->server_info, snum, &werr)) { + errcode = NERR_Success; + } break; case 103: /* Purge */ - if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success; + if (print_queue_purge(conn->server_info, snum, &werr)) { + errcode = NERR_Success; + } break; } -- cgit From e2585b73e975e8a434533019fbab1b8bd045ca70 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 24 Jun 2008 16:58:12 +0200 Subject: remove unused extern current_user from lanman.c (This used to be commit e2009c0b8dc229faf98ce189d2a906e58d3e1e63) --- source3/smbd/lanman.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 29703ffd1e..03a48f5e61 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -27,8 +27,6 @@ #include "includes.h" -extern struct current_user current_user; - #ifdef CHECK_TYPES #undef CHECK_TYPES #endif -- cgit From c885ae01ebbf2b2f5c75799c4e8b1b0c68b2d34e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 24 Jun 2008 16:58:29 +0200 Subject: Remove current_user reference from printfsp.c (This used to be commit 510f45d01a19ce1c226755ac42a328241098b2e0) --- source3/smbd/open.c | 2 +- source3/smbd/reply.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3cec80c6df..aa3bbdf685 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1178,7 +1178,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(conn, fname, result); + return print_fsp_open(conn, fname, req->vuid, result); } if (!parent_dirname_talloc(talloc_tos(), fname, &parent_dir, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index aaa284dc39..ee646aa7c3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4642,7 +4642,7 @@ void reply_printopen(struct smb_request *req) } /* Open for exclusive use, write only. */ - status = print_fsp_open(conn, NULL, &fsp); + status = print_fsp_open(conn, NULL, req->vuid, &fsp); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); -- cgit From 3c516937e80bcac5dd453dd9e6f83ccb67c5a22b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 26 Jun 2008 13:32:11 +0200 Subject: Fix a debug message (This used to be commit 8dd94d448bc5ad067024c56c6ef498bc88a396b2) --- source3/smbd/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 1ad48451ff..0b851f1e48 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1143,7 +1143,7 @@ connection_struct *make_connection_with_chdir(const char *service_in, */ if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { - DEBUG(0,("move_driver_to_download_area: Can't change " + DEBUG(0,("make_connection_with_chdir: Can't change " "directory to %s for [print$] (%s)\n", conn->connectpath,strerror(errno))); yield_connection(conn, lp_servicename(SNUM(conn))); -- cgit From 5cd8a42720b09c50109052b4fea253b2653525d5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Apr 2008 15:34:29 +0200 Subject: Factor out create_outbuf, creating an outbuf just given an inbuf (This used to be commit 50427cbf6345d3f671e9ea321089c4b4244df972) --- source3/smbd/process.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 71e38634b7..da1165219b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1245,7 +1245,8 @@ static const struct smb_message_struct { allocate and initialize a reply packet ********************************************************************/ -void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) +bool create_outbuf(TALLOC_CTX *mem_ctx, const char *inbuf, char **outbuf, + uint8_t num_words, uint32_t num_bytes) { /* * Protect against integer wrap @@ -1260,23 +1261,33 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) smb_panic(msg); } - if (!(req->outbuf = TALLOC_ARRAY( - req, uint8, - smb_size + num_words*2 + num_bytes))) { - smb_panic("could not allocate output buffer\n"); + *outbuf = TALLOC_ARRAY(mem_ctx, char, + smb_size + num_words*2 + num_bytes); + if (*outbuf == NULL) { + return false; } - construct_reply_common((char *)req->inbuf, (char *)req->outbuf); - srv_set_message((char *)req->outbuf, num_words, num_bytes, false); + construct_reply_common(inbuf, *outbuf); + srv_set_message(*outbuf, num_words, num_bytes, false); /* * Zero out the word area, the caller has to take care of the bcc area * himself */ if (num_words != 0) { - memset(req->outbuf + smb_vwv0, 0, num_words*2); + memset(*outbuf + smb_vwv0, 0, num_words*2); } - return; + return true; +} + +void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) +{ + char *outbuf; + if (!create_outbuf(req, (char *)req->inbuf, &outbuf, num_words, + num_bytes)) { + smb_panic("could not allocate output buffer\n"); + } + req->outbuf = (uint8_t *)outbuf; } -- cgit From cf9665016f70aff9a5d6ec7ab427e469f43dbfc6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 2 Apr 2008 15:55:10 +0200 Subject: Let send_trans_reply work on only the inbuf It does not really need the whole smb_request (This used to be commit d3facf4cbdb2915168e91d64c2d8320f67524df8) --- source3/smbd/ipc.c | 107 ++++++++++++++++++++++++++------------------------ source3/smbd/lanman.c | 2 +- 2 files changed, 56 insertions(+), 53 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 59a5dfdd3f..f4c45999ba 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -81,8 +81,7 @@ static void copy_trans_params_and_data(char *outbuf, int align, Send a trans reply. ****************************************************************************/ -void send_trans_reply(connection_struct *conn, - struct smb_request *req, +void send_trans_reply(connection_struct *conn, const uint8_t *inbuf, char *rparam, int rparam_len, char *rdata, int rdata_len, bool buffer_too_large) @@ -91,6 +90,7 @@ void send_trans_reply(connection_struct *conn, int tot_data_sent = 0; int tot_param_sent = 0; int align; + char *outbuf; int ldata = rdata ? rdata_len : 0; int lparam = rparam ? rparam_len : 0; @@ -103,47 +103,48 @@ void send_trans_reply(connection_struct *conn, align = ((this_lparam)%4); - reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); + if (!create_outbuf(talloc_tos(), (char *)inbuf, &outbuf, + 10, 1+align+this_ldata+this_lparam)) { + smb_panic("could not allocate outbuf"); + } - copy_trans_params_and_data((char *)req->outbuf, align, + copy_trans_params_and_data(outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(req->outbuf,smb_vwv0,lparam); - SSVAL(req->outbuf,smb_vwv1,ldata); - SSVAL(req->outbuf,smb_vwv3,this_lparam); - SSVAL(req->outbuf,smb_vwv4,smb_offset(smb_buf(req->outbuf)+1, - req->outbuf)); - SSVAL(req->outbuf,smb_vwv5,0); - SSVAL(req->outbuf,smb_vwv6,this_ldata); - SSVAL(req->outbuf,smb_vwv7,smb_offset(smb_buf(req->outbuf)+1+ - this_lparam+align, - req->outbuf)); - SSVAL(req->outbuf,smb_vwv8,0); - SSVAL(req->outbuf,smb_vwv9,0); + SSVAL(outbuf,smb_vwv0,lparam); + SSVAL(outbuf,smb_vwv1,ldata); + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); + SSVAL(outbuf,smb_vwv5,0); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align, + outbuf)); + SSVAL(outbuf,smb_vwv8,0); + SSVAL(outbuf,smb_vwv9,0); if (buffer_too_large) { - error_packet_set((char *)req->outbuf, - ERRDOS, ERRmoredata, - STATUS_BUFFER_OVERFLOW, - __LINE__, __FILE__); + error_packet_set((char *)outbuf, ERRDOS, ERRmoredata, + STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } - show_msg((char *)req->outbuf); - if (!srv_send_smb(smbd_server_fd(), - (char *)req->outbuf, - IS_CONN_ENCRYPTED(conn))) + show_msg(outbuf); + if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, + IS_CONN_ENCRYPTED(conn))) { exit_server_cleanly("send_trans_reply: srv_send_smb failed."); + } - TALLOC_FREE(req->outbuf); + TALLOC_FREE(outbuf); tot_data_sent = this_ldata; tot_param_sent = this_lparam; while (tot_data_sent < ldata || tot_param_sent < lparam) { - this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */ - this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam)); + this_lparam = MIN(lparam-tot_param_sent, + max_send - 500); /* hack */ + this_ldata = MIN(ldata -tot_data_sent, + max_send - (500+this_lparam)); if(this_lparam < 0) this_lparam = 0; @@ -153,39 +154,39 @@ void send_trans_reply(connection_struct *conn, align = (this_lparam%4); - reply_outbuf(req, 10, 1+this_ldata+this_lparam+align); + if (!create_outbuf(talloc_tos(), (char *)inbuf, &outbuf, + 10, 1+align+this_ldata+this_lparam)) { + smb_panic("could not allocate outbuf"); + } - copy_trans_params_and_data((char *)req->outbuf, align, + copy_trans_params_and_data(outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(req->outbuf,smb_vwv3,this_lparam); - SSVAL(req->outbuf,smb_vwv4,smb_offset(smb_buf(req->outbuf)+1, - req->outbuf)); - SSVAL(req->outbuf,smb_vwv5,tot_param_sent); - SSVAL(req->outbuf,smb_vwv6,this_ldata); - SSVAL(req->outbuf,smb_vwv7,smb_offset(smb_buf(req->outbuf)+1+ - this_lparam+align, - req->outbuf)); - SSVAL(req->outbuf,smb_vwv8,tot_data_sent); - SSVAL(req->outbuf,smb_vwv9,0); + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); + SSVAL(outbuf,smb_vwv5,tot_param_sent); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7, + smb_offset(smb_buf(outbuf)+1+this_lparam+align, outbuf)); + SSVAL(outbuf,smb_vwv8,tot_data_sent); + SSVAL(outbuf,smb_vwv9,0); if (buffer_too_large) { - error_packet_set((char *)req->outbuf, - ERRDOS, ERRmoredata, + error_packet_set(outbuf, ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } - show_msg((char *)req->outbuf); - if (!srv_send_smb(smbd_server_fd(), - (char *)req->outbuf, - IS_CONN_ENCRYPTED(conn))) - exit_server_cleanly("send_trans_reply: srv_send_smb failed."); + show_msg(outbuf); + if (!srv_send_smb(smbd_server_fd(), outbuf, + IS_CONN_ENCRYPTED(conn))) + exit_server_cleanly("send_trans_reply: srv_send_smb " + "failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; - TALLOC_FREE(req->outbuf); + TALLOC_FREE(outbuf); } } @@ -212,7 +213,8 @@ static void api_rpc_trans_reply(connection_struct *conn, struct smb_request *req return; } - send_trans_reply(conn, req, NULL, 0, rdata, data_len, is_data_outstanding); + send_trans_reply(conn, req->inbuf, NULL, 0, rdata, data_len, + is_data_outstanding); SAFE_FREE(rdata); return; } @@ -236,7 +238,7 @@ static void api_WNPHS(connection_struct *conn, struct smb_request *req, smb_np_s if (wait_rpc_pipe_hnd_state(p, priority)) { /* now send the reply */ - send_trans_reply(conn, req, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0, False); return; } api_no_reply(conn,req); @@ -262,7 +264,7 @@ static void api_SNPHS(connection_struct *conn, struct smb_request *req, smb_np_s if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply(conn, req, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0, False); return; } api_no_reply(conn,req); @@ -284,7 +286,7 @@ static void api_no_reply(connection_struct *conn, struct smb_request *req) DEBUG(3,("Unsupported API fd command\n")); /* now send the reply */ - send_trans_reply(conn, req, rparam, 4, NULL, 0, False); + send_trans_reply(conn, req->inbuf, rparam, 4, NULL, 0, False); return; } @@ -326,7 +328,8 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, /* Win9x does this call with a unicode pipe name, not a pnum. */ /* Just return success for now... */ DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n")); - send_trans_reply(conn, req, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0, + False); return; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 03a48f5e61..fe1d766b9d 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4632,7 +4632,7 @@ void api_reply(connection_struct *conn, uint16 vuid, /* If api_Unsupported returns false we can't return anything. */ if (reply) { - send_trans_reply(conn, req, rparam, rparam_len, + send_trans_reply(conn, req->inbuf, rparam, rparam_len, rdata, rdata_len, False); } -- cgit From 4a09c5a09f791738453947f07abe8d0f100fe53d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Jul 2008 15:39:41 -0700 Subject: Two more fixes from Jim Brown for SGI compiler warnings. Jeremy. (This used to be commit d85cbdbe296ec6de5bdbd66a90ca41345f55c837) --- source3/smbd/oplock_irix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 788cd04c17..8c287c9836 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -184,7 +184,7 @@ static bool irix_set_kernel_oplock(files_struct *fsp, int oplock_type) strerror(errno) )); } else { DEBUG(5,("irix_set_kernel_oplock: Refused oplock on " - "file %s, fd = %d, file_id = 5s, " + "file %s, fd = %d, file_id = %s, " "gen_id = %ul. Another process had the file " "open.\n", fsp->fsp_name, fsp->fh->fd, -- cgit From 1fb1c67fb9392364887ba8963f18d10b27d1cfa0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Jul 2008 10:24:12 -0700 Subject: Patch from SATOH Fumiyasu for bug #5202. Re-activate "acl group control" parameter and make it only apply to owning group. Also added man page fix. Jeremy. (This used to be commit e98e080bad2c8b9f038a8f2dffcfeba1d5f392ce) --- source3/smbd/posix_acls.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index e92a263ca0..427cfc9a0d 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2362,20 +2362,32 @@ static bool current_user_in_group(gid_t gid) } /**************************************************************************** - Should we override a deny ? Check deprecated 'acl group control' - and 'dos filemode' + Should we override a deny ? Check 'acl group control' and 'dos filemode'. ****************************************************************************/ -static bool acl_group_override(connection_struct *conn, gid_t prim_gid) +static bool acl_group_override(connection_struct *conn, + gid_t prim_gid, + const char *fname) { - if ( (errno == EACCES || errno == EPERM) - && (lp_acl_group_control(SNUM(conn)) || lp_dos_filemode(SNUM(conn))) - && current_user_in_group(prim_gid)) - { - return True; - } + SMB_STRUCT_STAT sbuf; - return False; + if ((errno != EPERM) && (errno != EACCES)) { + return false; + } + + /* file primary group == user primary or supplementary group */ + if (lp_acl_group_control(SNUM(conn)) && + current_user_in_group(prim_gid)) { + return true; + } + + /* user has writeable permission */ + if (lp_dos_filemode(SNUM(conn)) && + can_write_to_file(conn, fname, &sbuf)) { + return true; + } + + return false; } /**************************************************************************** @@ -2561,7 +2573,7 @@ static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool defau *pacl_set_support = False; } - if (acl_group_override(conn, prim_gid)) { + if (acl_group_override(conn, prim_gid, fsp->fsp_name)) { int sret; DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", @@ -2592,7 +2604,7 @@ static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool defau *pacl_set_support = False; } - if (acl_group_override(conn, prim_gid)) { + if (acl_group_override(conn, prim_gid, fsp->fsp_name)) { int sret; DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", @@ -3570,7 +3582,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) { int sret = -1; - if (acl_group_override(conn, sbuf.st_gid)) { + if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) { DEBUG(5,("set_nt_acl: acl group control on and " "current user in file %s primary group. Override delete_def_acl\n", fsp->fsp_name )); @@ -3617,7 +3629,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) if(SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) { int sret = -1; - if (acl_group_override(conn, sbuf.st_gid)) { + if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) { DEBUG(5,("set_nt_acl: acl group control on and " "current user in file %s primary group. Override chmod\n", fsp->fsp_name )); -- cgit From 2e7cb1a5ccf8ae513a432cef9ccebfcebe4241ac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jul 2008 20:27:56 +0200 Subject: Introduce is_known_pipename This scans the list of pipes registered via rpc_pipe_register_commands instead of using static tables. (This used to be commit 283e6039989adea1c8921b3600b410cb67b6492a) --- source3/smbd/nttrans.c | 36 +----------------------------------- source3/smbd/pipes.c | 12 +----------- 2 files changed, 2 insertions(+), 46 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 12f4da627b..149e6ecbd9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -23,27 +23,6 @@ extern int max_send; extern enum protocol_types Protocol; -static const char *known_nt_pipes[] = { - "\\LANMAN", - "\\srvsvc", - "\\samr", - "\\wkssvc", - "\\NETLOGON", - "\\ntlsa", - "\\ntsvcs", - "\\lsass", - "\\lsarpc", - "\\winreg", - "\\initshutdown", - "\\spoolss", - "\\netdfs", - "\\rpcecho", - "\\svcctl", - "\\eventlog", - "\\unixinfo", - NULL -}; - static char *nttrans_realloc(char **ptr, size_t size) { if (ptr==NULL) { @@ -291,25 +270,12 @@ static void nt_open_pipe(char *fname, connection_struct *conn, struct smb_request *req, int *ppnum) { smb_np_struct *p = NULL; - int i; DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); /* See if it is one we want to handle. */ - if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) { - reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, - ERRDOS, ERRbadpipe); - return; - } - - for( i = 0; known_nt_pipes[i]; i++ ) { - if( strequal(fname,known_nt_pipes[i])) { - break; - } - } - - if ( known_nt_pipes[i] == NULL ) { + if (!is_known_pipename(fname)) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERRbadpipe); return; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 6b4b83d97d..4fdcdcc557 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -44,9 +44,6 @@ struct pipe_dbrec { fstring user; }; - -extern struct pipe_id_info pipe_names[]; - /**************************************************************************** Reply to an open and X on a named pipe. This code is basically stolen from reply_open_and_X with some @@ -59,7 +56,6 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) char *pipe_name = NULL; smb_np_struct *p; int size=0,fmode=0,mtime=0,rmode=0; - int i; TALLOC_CTX *ctx = talloc_tos(); /* XXXX we need to handle passed times, sattr and flags */ @@ -82,13 +78,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) DEBUG(4,("Opening pipe %s.\n", pipe_name)); /* See if it is one we want to handle. */ - for( i = 0; pipe_names[i].client_pipe ; i++ ) { - if( strequal(pipe_name,pipe_names[i].client_pipe)) { - break; - } - } - - if (pipe_names[i].client_pipe == NULL) { + if (!is_known_pipename(pipe_name)) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERRbadpipe); return; -- cgit From 1335da2a7cc639310e5d389e8e8dbe67c4e7ca25 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jul 2008 11:04:31 +0200 Subject: Refactoring: Change calling conventions for cli_rpc_pipe_open_noauth Pass in ndr_syntax_id instead of pipe_idx, return NTSTATUS (This used to be commit 9abc9dc4dc13bd3e42f98eff64eacf24b51f5779) --- source3/smbd/change_trust_pw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 227b2d6899..72a72a78b5 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -73,8 +73,9 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m /* Shouldn't we open this with schannel ? JRA. */ - netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &nt_status); - if (!netlogon_pipe) { + nt_status = cli_rpc_pipe_open_noauth( + cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", dc_name, nt_errstr(nt_status))); cli_shutdown(cli); -- cgit From 06d0790c0799112b89534a646e78d0cb38b06e20 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Thu, 3 Jul 2008 22:53:42 -0700 Subject: Fix various build warnings This fixes various build warnings on our platform. I'm sure I haven't caught them all, but it's a start. (This used to be commit 6b73f259cb67d9dda9127907d706f9244a871fa3) --- source3/smbd/utmp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index de6d707eaf..af947ef462 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -189,7 +189,7 @@ static const char *wt_pathname = # endif /* BSD-like systems might want "lastlog" support. */ -/* *** Not yet implemented */ +#if 0 /* *** Not yet implemented */ #ifndef HAVE_PUTUTLINE /* see "pututline_my()" */ static const char *ll_pathname = # if defined (_PATH_LASTLOG) /* what other names (if any?) */ @@ -198,6 +198,7 @@ static const char *ll_pathname = "" ; # endif /* _PATH_LASTLOG */ #endif /* HAVE_PUTUTLINE */ +#endif /* * Get name of {u,w}tmp{,x} file. -- cgit From f9223a7139e7cc43cb3337a5c66d0262b9e03d54 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2008 18:12:12 -0700 Subject: If we're not allowing streams on this conn ptr, then don't allow create_file() to call down to create_file_unixpath() with a stream name. Jeremy. (This used to be commit 167d611b525db6d103a7f83fd5a19792be4e7745) --- source3/smbd/open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aa3bbdf685..03efd09f06 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2999,6 +2999,11 @@ NTSTATUS create_file(connection_struct *conn, ZERO_STRUCT(sbuf); goto done; } + + if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) { + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; + } } if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { -- cgit From ee49e0391fda564f165f582a3119b832555e4952 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Jul 2008 13:16:18 -0700 Subject: Fix bug creating files using DOS clients with mixed case files. Reported by Daniel Johnson . The smb_set_file_time() call to set the filetimes is failing because it's using the unmodified name passed in by the client, not the modified name (matching case on the disk) that comes out from create_file(). Jeremy. (This used to be commit 1706a33e78347d14a8b09fd21b87d57bad543bcd) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ee646aa7c3..ddc5dd06a5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2030,7 +2030,7 @@ void reply_mknew(struct smb_request *req) } ts[0] = get_atimespec(&sbuf); /* atime. */ - status = smb_set_file_time(conn, fsp, fname, &sbuf, ts, true); + status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); reply_openerror(req, status); -- cgit From 49403ee82f5b4a40f4feacd441b2e27f23e6c156 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 Jul 2008 17:56:48 +0200 Subject: Make create_conn_struct() public (This used to be commit e115e2582256c34e6905afc8c2929efd6ea61088) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 8e83a6c17e..32240ff0d5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -215,7 +215,7 @@ static NTSTATUS parse_dfs_path(connection_struct *conn, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, +NTSTATUS create_conn_struct(TALLOC_CTX *ctx, connection_struct **pconn, int snum, const char *path, -- cgit From b117e1039451e10c8c86b867d1a53781957f451e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 Jul 2008 18:37:00 +0200 Subject: Remove a pointless CONST_DISCARD (This used to be commit c63cb78b4c8a283c0eebe37ff2f60ddbfbfaac4a) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ddc5dd06a5..897024c4d8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2131,7 +2131,7 @@ void reply_ctemp(struct smb_request *req) return; } - status = check_name(conn, CONST_DISCARD(char *,fname)); + status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); -- cgit From a235676dd1159d93d6fac7374918c1f33eaf0120 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 Jul 2008 18:41:19 +0200 Subject: Fix a debug message (This used to be commit 1970eed1b79a5d9dc45eb96098d653ad62a20871) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 897024c4d8..80afd582f6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2358,7 +2358,7 @@ static NTSTATUS do_unlink(connection_struct *conn, &sbuf); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("open_file_ntcreate failed: %s\n", + DEBUG(10, ("create_file_unixpath failed: %s\n", nt_errstr(status))); return status; } -- cgit From 12b6c1f57db772679cfb4b640a3f3dba259c9c72 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 10 Aug 2008 17:37:08 +0200 Subject: Fix andx offset calculation for more than 2 chained requests Untested code is broken code.... Test follows later, it's quite an intrusive change to libsmb/ (This used to be commit 0ff16e8573f3c312f10fc723648319fa1f514ac0) --- source3/smbd/process.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index da1165219b..a1d2d88b3d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1696,7 +1696,7 @@ void chain_reply(struct smb_request *req) * remember how much the caller added to the chain, only counting * stuff after the parameter words */ - chain_size += outsize_padded - smb_wct; + chain_size += (outsize_padded - smb_wct); /* * work out pointers into the original packets. The @@ -1825,6 +1825,12 @@ void chain_reply(struct smb_request *req) SAFE_FREE(caller_output); TALLOC_FREE(req2); + /* + * Reset the chain_size for our caller's offset calculations + */ + + chain_size -= (outsize_padded - smb_wct); + return; } -- cgit From 1a7b6fe34d6d7d29256fe3b5432593fa07d74838 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 10 Aug 2008 17:53:35 +0200 Subject: fix smb_len calculation for chained requests I think chain_reply() is one of the most tricky parts of Samba. This recursion needs to go away, we need to sequentially walk the chain list. (This used to be commit af2b01d85188d2301580643f7e862e3e3988aadc) --- source3/smbd/process.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a1d2d88b3d..332a2e4da3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1653,6 +1653,7 @@ void chain_reply(struct smb_request *req) char *outbuf = (char *)req->outbuf; size_t outsize = smb_len(outbuf) + 4; size_t outsize_padded; + size_t padding; size_t ofs, to_move; struct smb_request *req2; @@ -1691,6 +1692,7 @@ void chain_reply(struct smb_request *req) */ outsize_padded = (outsize + 3) & ~3; + padding = outsize_padded - outsize; /* * remember how much the caller added to the chain, only counting @@ -1804,17 +1806,17 @@ void chain_reply(struct smb_request *req) SCVAL(outbuf, smb_vwv0, smb_com2); SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4); - if (outsize_padded > outsize) { + if (padding != 0) { /* * Due to padding we have some uninitialized bytes after the * caller's output */ - memset(outbuf + outsize, 0, outsize_padded - outsize); + memset(outbuf + outsize, 0, padding); } - smb_setlen(outbuf, outsize2 + chain_size - 4); + smb_setlen(outbuf, outsize2 + caller_outputlen + padding - 4); /* * restore the saved data, being careful not to overwrite any data -- cgit From 8b25ce06ceb4ad57fa585e76c1a6be12a4c7d3d2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Aug 2008 10:43:36 +1000 Subject: I found lots of places where we assume error will be set when calling one of our virtualised functions, such as db_open(), but error is only set when a system call fails, and it is not uncommon for us to fail a function internally without ever making a system call. That led to us passing back success when a function had in fact failed. I found two places where we relied on map_nt_error_from_unix() returning success when errno==0, but lots and lots of places where we relied on the reverse, so I fixed those two places. map_nt_error_from_unix() will now always return an error, returning NT_STATUS_UNSUCCESSFUL if errno is 0 (cherry picked from commit 69d40ca4c1af925d4b0e59ddc69ef8c26e6501d1) (This used to be commit 834684a524a24bb4eb46b4af583d39947dc87d95) --- source3/smbd/reply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 80afd582f6..d32d998da8 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2527,7 +2527,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, TALLOC_FREE(dir_hnd); } - if (count == 0 && NT_STATUS_IS_OK(status)) { + if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) { status = map_nt_error_from_unix(errno); } @@ -5910,7 +5910,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } TALLOC_FREE(dir_hnd); - if (count == 0 && NT_STATUS_IS_OK(status)) { + if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) { status = map_nt_error_from_unix(errno); } -- cgit From ac9f55b9102574085ae6c7364c794a386d4981a1 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 12 Aug 2008 14:59:59 +0200 Subject: Fix unix_convert() for "*" after changing map_nt_error_from_unix(). map_nt_error_from_unix() now assumes that it is called in an error path and returns an error even for a given errno == 0. The original behaviour of unix_convert() used the mapping of errno == 0 ==> NT_STATUS_OK to return success through an error path. I think this must have been an oversight, and unix_convert() worked only by coincidence (or because explicitly using the knowledge of the conceptually wrong working of map_nt_error_from_unix(). This patch puts this straight by not interpreting errno == 0 as an error condition and proceeding in that case. Jeremy - please check! Michael (This used to be commit ec5956ab0df1b3f567470b2481b73da9c3c67371) --- source3/smbd/filename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 4323e843d2..41a0b9296a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -477,7 +477,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } /* ENOENT is the only valid error here. */ - if (errno != ENOENT) { + if ((errno != 0) && (errno != ENOENT)) { /* * ENOTDIR and ELOOP both map to * NT_STATUS_OBJECT_PATH_NOT_FOUND -- cgit From 743d6f707a7dcd31f8d0cf1685275d179c0d5169 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 12 Aug 2008 15:19:17 +0200 Subject: Make sure to always set errno on error path in OpenDir (and hence scan_directory). Michael (This used to be commit 15fc2427f91da697e0e91f7f34b0f0c6e230a9a5) --- source3/smbd/dir.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 74cd63ddda..c2735c032a 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1084,6 +1084,7 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, dirp->dir_path = talloc_strdup(dirp, name); if (!dirp->dir_path) { + errno = ENOMEM; goto fail; } -- cgit From 0f41961e4ffaa602a5b19a1e0899bffa491c886f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 7 Aug 2008 16:20:05 +1000 Subject: first cut at adding full transactions for ctdb to samba3 (This used to be commit f91a3e0f7b7737c1d0667cd961ea950e2b93e592) --- source3/smbd/server.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4a0e60a8d7..05f11f6753 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1097,8 +1097,6 @@ extern void build_options(bool screen); TimeInit(); - db_tdb2_setup_messaging(NULL, false); - #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif @@ -1230,11 +1228,6 @@ extern void build_options(bool screen); if (smbd_messaging_context() == NULL) exit(1); - /* - * Do this before reload_services. - */ - db_tdb2_setup_messaging(smbd_messaging_context(), true); - if (!reload_services(False)) return(-1); -- cgit From 2f09edb492834e149fd8d70a0965edab481c80db Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 8 Aug 2008 20:31:03 +1000 Subject: register the ctdbd reconfigure message (This used to be commit 9d3217bb28765e107c230fb90b578dcc6f5d4375) --- source3/smbd/server.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 05f11f6753..d083fec494 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -573,6 +573,10 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete); brl_register_msgs(smbd_messaging_context()); +#ifdef CLUSTER_SUPPORT + ctdbd_register_reconfigure(messaging_ctdbd_connection()); +#endif + #ifdef DEVELOPER messaging_register(smbd_messaging_context(), NULL, MSG_SMB_INJECT_FAULT, msg_inject_fault); -- cgit From 4b2399d5c065f17e6885f8c53cfd8310d03235ed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 8 Aug 2008 21:00:42 +1000 Subject: log unclean shutdowns (This used to be commit 30b83245a22ebd5e4fa4739dd2aa1805373a7eb2) --- source3/smbd/server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d083fec494..df6b6ae41d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -296,6 +296,7 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown) /* a child terminated uncleanly so tickle all processes to see if they can grab any of the pending locks */ + DEBUG(0,(__location__ " Unclean shutdown of pid %u\n", pid)); messaging_send_buf(smbd_messaging_context(), procid_self(), MSG_SMB_BRL_VALIDATE, NULL, 0); message_send_all(smbd_messaging_context(), -- cgit From b5f4373be5ac0de57dffd8721f41fa1ff1e96182 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 8 Aug 2008 21:11:56 +1000 Subject: fixed child exit handling and IP release handling (This used to be commit 6fe27d296c389473c24e8c627a61bd56b364ad9f) --- source3/smbd/server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index df6b6ae41d..265d4927f5 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -986,7 +986,9 @@ static void release_ip(const char *ip, void *priv) away */ DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n", ip)); - _exit(0); + /* note we must exit with non-zero status so the unclean handler gets + called in the parent, so that the brl database is tickled */ + _exit(1); } } -- cgit From 416fa081ab9d0a5338a11924d7b85c8e159a5109 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 8 Aug 2008 22:34:59 +1000 Subject: ensure we exit with non-zero status on EOF on socket, so the parent can trigger a brlock db cleanup (This used to be commit bbd49f9e1c4b50c4a596fb991f3306e1e90c0177) --- source3/smbd/conn.c | 7 +++++-- source3/smbd/server.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 1a67ac9b32..b9433bb965 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -161,16 +161,19 @@ find_again: /**************************************************************************** Close all conn structures. +return true if any were closed ****************************************************************************/ - -void conn_close_all(void) +bool conn_close_all(void) { connection_struct *conn, *next; + bool ret = false; for (conn=Connections;conn;conn=next) { next=conn->next; set_current_service(conn, 0, True); close_cnum(conn, conn->vuid); + ret = true; } + return ret; } /**************************************************************************** diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 265d4927f5..c7bf1daf68 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -296,7 +296,7 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown) /* a child terminated uncleanly so tickle all processes to see if they can grab any of the pending locks */ - DEBUG(0,(__location__ " Unclean shutdown of pid %u\n", pid)); + DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", pid)); messaging_send_buf(smbd_messaging_context(), procid_self(), MSG_SMB_BRL_VALIDATE, NULL, 0); message_send_all(smbd_messaging_context(), @@ -891,6 +891,7 @@ static void exit_server_common(enum server_exit_reason how, const char *const reason) { static int firsttime=1; + bool had_open_conn; if (!firsttime) exit(0); @@ -902,7 +903,7 @@ static void exit_server_common(enum server_exit_reason how, (negprot_global_auth_context->free)(&negprot_global_auth_context); } - conn_close_all(); + had_open_conn = conn_close_all(); invalidate_all_vuids(); @@ -952,7 +953,11 @@ static void exit_server_common(enum server_exit_reason how, (reason ? reason : "normal exit"))); } - exit(0); + if (had_open_conn) { + exit(1); + } else { + exit(0); + } } void exit_server(const char *const explanation) -- cgit From 1a4e299c7033cb3d61ccf024b2eeb7409a32b31b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 8 Aug 2008 22:47:04 +1000 Subject: added a explanatory comment on tcon check (This used to be commit f2ab2cebb9b81453dc0b6370288b85909182ae49) --- source3/smbd/server.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c7bf1daf68..3e816ee62d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -953,6 +953,10 @@ static void exit_server_common(enum server_exit_reason how, (reason ? reason : "normal exit"))); } + /* if we had any open SMB connections when we exited then we + need to tell the parent smbd so that it can trigger a retry + of any locks we may have been holding or open files we were + blocking */ if (had_open_conn) { exit(1); } else { -- cgit From f284cde4b94062edf01608c7f937fa548575fedf Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 11 Aug 2008 16:30:36 +0200 Subject: smbd: prevent smbd from panicing with "clustering = no" but --with-cluster-support Michael (This used to be commit a687949d19ba9690f96e7869aa22e4d87840640e) --- source3/smbd/server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 3e816ee62d..0d855f876f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -575,7 +575,9 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ brl_register_msgs(smbd_messaging_context()); #ifdef CLUSTER_SUPPORT - ctdbd_register_reconfigure(messaging_ctdbd_connection()); + if (lp_clustering()) { + ctdbd_register_reconfigure(messaging_ctdbd_connection()); + } #endif #ifdef DEVELOPER -- cgit From a5cf8b9fb5711dce8baf509e27396269e711dd07 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Aug 2008 15:46:35 -0700 Subject: Fix for bug #5617, reported and patched by Bartosz Antosik antosik@gmail.com. xp/2003 explorer freezes browsing shares on samba ipv6 hosts. Caused by missing reply packet to SMB printclose packet. Jeremy (This used to be commit ecf2b906f476e4a764d0e53eed84b9b75a2062c0) --- source3/smbd/reply.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d32d998da8..b3d691fbe7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4702,6 +4702,8 @@ void reply_printclose(struct smb_request *req) return; } + reply_outbuf(req, 0, 0); + END_PROFILE(SMBsplclose); return; } -- cgit From 0595ecb3a6c1719a12f443b40650aaf642617b00 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 13 Aug 2008 16:45:34 -0700 Subject: Fix for bug #5688 from SATOH Fumiyasu . LPQ process is orphaned if socket address parameter is invalid. If the "socket address" parameter is a null string that is an invalid value for Samba 3.2 but valid for Samba 3.0. Jeremy. (This used to be commit c65726d418601cdc86202c0371615e4f7f3d843c) --- source3/smbd/server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 0d855f876f..53116f3d98 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -469,7 +469,8 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ char *sock_tok; const char *sock_ptr; - if (strequal(sock_addr, "0.0.0.0") || + if (sock_addr[0] == '\0' || + strequal(sock_addr, "0.0.0.0") || strequal(sock_addr, "::")) { #if HAVE_IPV6 sock_addr = "::,0.0.0.0"; -- cgit From eb8dd6a81181c3dab9cbe6b934ceb4f3ba1ba2af Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 19 Aug 2008 16:34:50 +0200 Subject: smbd: fix the handling of create_options to pass RAW-OPEN Some of the bits generate INVALID_PARAMETER and some bits are ignored when they come from a client, that's why we need to use bits from the ignored range for our internal usage. metze (This used to be commit 7b4c8a4e39f310eb450918fa841b0ea1b4af19f7) --- source3/smbd/nttrans.c | 12 ++++++++++++ source3/smbd/open.c | 5 +++++ 2 files changed, 17 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 149e6ecbd9..b6951272d7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -454,6 +454,12 @@ void reply_ntcreate_and_X(struct smb_request *req) (unsigned int)root_dir_fid, fname)); + /* + * we need to remove ignored bits when they come directly from the client + * because we reuse some of them for internal stuff + */ + create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK; + /* * If it's an IPC, use the pipe handler. */ @@ -858,6 +864,12 @@ static void call_nt_transact_create(connection_struct *conn, allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif + /* + * we need to remove ignored bits when they come directly from the client + * because we reuse some of them for internal stuff + */ + create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK; + /* Ensure the data_len is correct for the sd and ea values given. */ if ((ea_len + sd_len > data_count) || (ea_len > data_count) || (sd_len > data_count) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 03efd09f06..8b32907a4b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2560,6 +2560,11 @@ NTSTATUS create_file_unixpath(connection_struct *conn, goto fail; } + if (create_options & NTCREATEX_OPTIONS_INVALID_PARAM_MASK) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + if (req == NULL) { oplock_request |= INTERNAL_OPEN_ONLY; } -- cgit From 4a5ccfb91f8d427fe9fa83cab992587fe6ce70c7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Aug 2008 13:49:46 -0700 Subject: Don't re-initialize a token when we already have one. This fixes the build farm failures when winbindd connects as guest. This one took a *lot* of tracking down :-). Jeremy. (This used to be commit dca827791276906436452c650062164eb819dfe0) --- source3/smbd/sesssetup.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 041596b953..9c9d0a97bc 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1738,16 +1738,19 @@ void reply_sesssetup_and_X(struct smb_request *req) return; } - nt_status = create_local_token(server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(10, ("create_local_token failed: %s\n", - nt_errstr(nt_status))); - data_blob_free(&nt_resp); - data_blob_free(&lm_resp); - data_blob_clear_free(&plaintext_password); - reply_nterror(req, nt_status_squash(nt_status)); - END_PROFILE(SMBsesssetupX); - return; + if (!server_info->ptok) { + nt_status = create_local_token(server_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(10, ("create_local_token failed: %s\n", + nt_errstr(nt_status))); + data_blob_free(&nt_resp); + data_blob_free(&lm_resp); + data_blob_clear_free(&plaintext_password); + reply_nterror(req, nt_status_squash(nt_status)); + END_PROFILE(SMBsesssetupX); + return; + } } data_blob_clear_free(&plaintext_password); -- cgit From 563a7ccdd9d23ffbd3195c8def82cd4d8d4cb0dc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Aug 2008 13:58:05 +1000 Subject: become root for AIO operations We need to become root for AIO read and write to allow the AIO thread to send a completion signal to the parent process when the IO completes (This used to be commit c548e5c69f9d8bc85a654f4d29d64c735a5e780b) --- source3/smbd/aio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 2889e3c13f..74275368bd 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -268,12 +268,15 @@ bool schedule_aio_read_and_X(connection_struct *conn, a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; + become_root(); if (SMB_VFS_AIO_READ(fsp,a) == -1) { DEBUG(0,("schedule_aio_read_and_X: aio_read failed. " "Error %s\n", strerror(errno) )); delete_aio_ex(aio_ex); + unbecome_root(); return False; } + unbecome_root(); DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, " "offset %.0f, len = %u (mid = %u)\n", @@ -366,13 +369,16 @@ bool schedule_aio_write_and_X(connection_struct *conn, a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; + become_root(); if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. " "Error %s\n", strerror(errno) )); delete_aio_ex(aio_ex); + unbecome_root(); return False; } - + unbecome_root(); + release_level_2_oplocks_on_change(fsp); if (!write_through && !lp_syncalways(SNUM(fsp->conn)) -- cgit From 39697d57451d05585063dc05c4fd6c5ae646a0a5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Aug 2008 14:06:42 +1000 Subject: EINVAL is also a valid error return, meaning "this filesystem cannot do sendfile for this file" (This used to be commit 737f664604b28f230be63bfc2f3d516fd9eb1c63) --- source3/smbd/reply.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b3d691fbe7..06aa835cb0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3198,8 +3198,9 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, setup_readX_header((char *)headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) { - /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ - if (errno == ENOSYS) { + /* Returning ENOSYS or EINVAL means no data at all was sent. + Do this as a normal read. */ + if (errno == ENOSYS || errno == EINVAL) { goto normal_read; } -- cgit From 1cae2ac905cc3e4b6e4c92ec4d64c582cfad8fea Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2008 15:06:14 -0700 Subject: Add st_birthtime and friends for accurate create times on systems that support it (*BSD and MacOSX). Should have done this ages ago, sorry. Jeremy. (This used to be commit 4c3a9558906f213948c3bdc081be73f8fed148cb) --- source3/smbd/reply.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 06aa835cb0..ff38ac88cf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -7126,6 +7126,7 @@ void reply_getattrE(struct smb_request *req) SMB_STRUCT_STAT sbuf; int mode; files_struct *fsp; + struct timespec create_ts; START_PROFILE(SMBgetattrE); @@ -7160,9 +7161,9 @@ void reply_getattrE(struct smb_request *req) reply_outbuf(req, 11, 0); - srv_put_dos_date2((char *)req->outbuf, smb_vwv0, - get_create_time(&sbuf, - lp_fake_dir_create_times(SNUM(conn)))); + create_ts = get_create_timespec(&sbuf, + lp_fake_dir_create_times(SNUM(conn))); + srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec); srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime); /* Should we check pending modtime here ? JRA */ srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime); -- cgit From 227718cd1a2143cd3c9585fc76f335ec7b5a24a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Sep 2008 13:46:27 +0200 Subject: Fix Coverity ID 587 The following test program prints "8" on 64-bit :-) static void print_size(const char lenbuf[4]) { printf("sizeof(lenbuf) = %d\n", (int)sizeof(lenbuf)); } int main(void) { const char lenbuf[4]; print_size(lenbuf); return 0; } Jeremy, please check :-) Volker (This used to be commit 9daea0ccfdda58450be3c9a9a94c016f5900c319) --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 332a2e4da3..b2d19e11e3 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -164,7 +164,7 @@ static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, ssize_t toread; NTSTATUS status; - memcpy(writeX_header, lenbuf, sizeof(lenbuf)); + memcpy(writeX_header, lenbuf, 4); status = read_socket_with_timeout( fd, writeX_header + 4, -- cgit From edd16eaa90df96f58ba1c224ca9316ccc0e2210d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Sep 2008 18:42:44 +0200 Subject: Slightly simplify logic: remove an else branch (This used to be commit 56ecec50130aa948a431427285aed4b28a5647e8) --- source3/smbd/reply.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ff38ac88cf..16f8a5b177 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3264,25 +3264,22 @@ normal_read: } TALLOC_FREE(req->outbuf); return; - } else { - reply_outbuf(req, 12, smb_maxcnt); + } - nread = read_file(fsp, smb_buf(req->outbuf), startpos, - smb_maxcnt); - if (nread < 0) { - reply_unixerror(req, ERRDOS, ERRnoaccess); - return; - } + reply_outbuf(req, 12, smb_maxcnt); - setup_readX_header((char *)req->outbuf, nread); + nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt); + if (nread < 0) { + reply_unixerror(req, ERRDOS, ERRnoaccess); + return; + } - DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", - fsp->fnum, (int)smb_maxcnt, (int)nread ) ); + setup_readX_header((char *)req->outbuf, nread); - chain_reply(req); + DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", + fsp->fnum, (int)smb_maxcnt, (int)nread ) ); - return; - } + chain_reply(req); } /**************************************************************************** -- cgit From 405b072431db3f3f8f16e4e0d2f2b1b2f1c71286 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2008 19:00:48 -0700 Subject: Write times code update. Ok, here's the fix for the write times breakage with the new tests in S4 smbtorture. The key is keeping in the share mode struct the "old_file_time" as the real write time, set by all the write and allocation calls, and the "changed_write_time" as the "sticky" write time - set by the SET_FILE_TIME calls. We can set them independently (although I kept the optimization of not setting the "old_file_time" is a "changed_write_time" was already set, as we'll never see it. This allows us to update the write time immediately on the SMBwrite truncate case, SET_END_OF_FILE and SET_ALLOCATION_SIZE calls, whilst still have the 2 second delay on the "normal" SMBwrite, SMBwriteX calls. I think in a subsequent patch I'd like to change the name of these from "old_file_time" to "write_time" and "changed_write_time" to "sticky_write_time" to make this clearer. I think I also fixed a bug in Metze's original code in that once a write timestamp had been set from a "normal" SMBwriteX call the fsp->update_write_time_triggered variable was set and then never reset - thus meaning the write timestamp would never get updated again on subsequent SMBwriteX's. The new code checks the update_write_time_event event instead, and doesn't update is there's an event already scheduled. Metze especially, please check this over for your understanding. Jeremy. (This used to be commit 6f20585419046c4aca1f7d6c863cf79eb6ae53b0) --- source3/smbd/dosmode.c | 52 +++++++++++++++++++++++++++++++------------------- source3/smbd/fileio.c | 47 +++++++++++++++++++++++++++++++++++++-------- source3/smbd/reply.c | 6 ++++-- source3/smbd/trans2.c | 12 +++++++----- 4 files changed, 82 insertions(+), 35 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 0ac3873275..88c6a51770 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -616,39 +616,51 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe return ret; } -/******************************************************************* - Change a filetime - possibly allowing DOS semantics. -*******************************************************************/ +/****************************************************************** + Force a "sticky" write time on a pathname. This will always be + returned on all future write time queries and set on close. +******************************************************************/ -bool set_write_time_path(connection_struct *conn, const char *fname, - struct file_id fileid, const struct timespec mtime, - bool overwrite) +bool set_sticky_write_time_path(connection_struct *conn, const char *fname, + struct file_id fileid, const struct timespec mtime) { if (null_timespec(mtime)) { return true; } - if (!set_write_time(fileid, mtime, overwrite)) { + if (!set_sticky_write_time(fileid, mtime)) { return false; } - /* in the overwrite case the caller should trigger the notify */ - if (!overwrite) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_LAST_WRITE, fname); - } - return true; } -bool set_write_time_fsp(struct files_struct *fsp, const struct timespec mtime, - bool overwrite) +/****************************************************************** + Force a "sticky" write time on an fsp. This will always be + returned on all future write time queries and set on close. +******************************************************************/ + +bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime) { - if (overwrite) { - fsp->write_time_forced = true; - TALLOC_FREE(fsp->update_write_time_event); + fsp->write_time_forced = true; + TALLOC_FREE(fsp->update_write_time_event); + + return set_sticky_write_time_path(fsp->conn, fsp->fsp_name, + fsp->file_id, mtime); +} + +/****************************************************************** + Update a write time immediately, without the 2 second delay. +******************************************************************/ + +bool update_write_time(struct files_struct *fsp) +{ + if (!set_write_time(fsp->file_id, timespec_current())) { + return false; } - return set_write_time_path(fsp->conn, fsp->fsp_name, fsp->file_id, - mtime, overwrite); + notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name); + + return true; } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 64cea7f7ce..63850f24eb 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -176,28 +176,38 @@ static void update_write_time_handler(struct event_context *ctx, const struct timeval *now, void *private_data) { - files_struct *fsp = (files_struct *)private_data; + files_struct *fsp = (files_struct *)private_data; - /* Remove the timed event handler. */ - TALLOC_FREE(fsp->update_write_time_event); - DEBUG(5, ("Update write time on %s\n", fsp->fsp_name)); + /* Remove the timed event handler. */ + TALLOC_FREE(fsp->update_write_time_event); + DEBUG(5, ("Update write time on %s\n", fsp->fsp_name)); - /* change the write time if not already changed by someoneelse */ - set_write_time_fsp(fsp, timespec_current(), false); + /* change the write time if not already changed by someone else */ + update_write_time(fsp); } +/********************************************************* + Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY + in the future. +*********************************************************/ + void trigger_write_time_update(struct files_struct *fsp) { int delay; if (fsp->write_time_forced) { + /* No point - "sticky" write times + * in effect. + */ return; } - if (fsp->update_write_time_triggered) { + if (fsp->update_write_time_event) { + /* + * No point - an event is already scheduled. + */ return; } - fsp->update_write_time_triggered = true; delay = lp_parm_int(SNUM(fsp->conn), "smbd", "writetimeupdatedelay", @@ -212,6 +222,27 @@ void trigger_write_time_update(struct files_struct *fsp) update_write_time_handler, fsp); } +void trigger_write_time_update_immediate(struct files_struct *fsp) +{ + if (fsp->write_time_forced) { + /* + * No point - "sticky" write times + * in effect. + */ + return; + } + + if (fsp->update_write_time_event) { + /* + * No point - an event is already scheduled. + */ + return; + } + + fsp->update_write_time_on_close = true; + update_write_time(fsp); +} + /**************************************************************************** Write to a file. ****************************************************************************/ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 16f8a5b177..6933533672 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3810,9 +3810,11 @@ void reply_write(struct smb_request *req) END_PROFILE(SMBwrite); return; } - } else + trigger_write_time_update_immediate(fsp); + } else { nwritten = write_file(req,fsp,data,startpos,numtowrite); - + } + status = sync_file(conn, fsp, False); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_write: sync_file for %s returned %s\n", diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 881b29c6f0..8d839b66b3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4900,11 +4900,11 @@ NTSTATUS smb_set_file_time(connection_struct *conn, time_to_asc(convert_timespec_to_time_t(ts[1])) )); if (fsp != NULL) { - set_write_time_fsp(fsp, ts[1], true); + set_sticky_write_time_fsp(fsp, ts[1]); } else { - set_write_time_path(conn, fname, + set_sticky_write_time_path(conn, fname, vfs_file_id_from_sbuf(conn, psbuf), - ts[1], true); + ts[1]); } } @@ -4988,6 +4988,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, if (vfs_set_filelen(fsp, size) == -1) { return map_nt_error_from_unix(errno); } + trigger_write_time_update_immediate(fsp); return NT_STATUS_OK; } @@ -5011,6 +5012,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, return status; } + trigger_write_time_update_immediate(new_fsp); close_file(new_fsp,NORMAL_CLOSE); return NT_STATUS_OK; } @@ -5737,7 +5739,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, * This is equivalent to a write. Ensure it's seen immediately * if there are no pending writes. */ - trigger_write_time_update(fsp); + trigger_write_time_update_immediate(fsp); return NT_STATUS_OK; } @@ -5771,7 +5773,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, * This is equivalent to a write. Ensure it's seen immediately * if there are no pending writes. */ - trigger_write_time_update(new_fsp); + trigger_write_time_update_immediate(new_fsp); close_file(new_fsp,NORMAL_CLOSE); return NT_STATUS_OK; -- cgit From c9fb96146cdae56a2711e176f07620d33ea0e18c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 8 Sep 2008 15:12:24 +0200 Subject: smbd: some write time fixes - only the first non truncating write causes the write time update with 2 seconds delay. It's not enough to check for an existing update event as it will be NULL after the event was triggered. - SMBwrite truncates always update the write time unless the sticky write time is set. - SMBwrite truncates don't trigger a write time update on close. metze (This used to be commit 3d17089b6dc773303c8c553f3f6140e60e348fb7) --- source3/smbd/fileio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 63850f24eb..095841825a 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -202,12 +202,13 @@ void trigger_write_time_update(struct files_struct *fsp) return; } - if (fsp->update_write_time_event) { + if (fsp->update_write_time_triggered) { /* * No point - an event is already scheduled. */ return; } + fsp->update_write_time_triggered = true; delay = lp_parm_int(SNUM(fsp->conn), "smbd", "writetimeupdatedelay", @@ -232,14 +233,12 @@ void trigger_write_time_update_immediate(struct files_struct *fsp) return; } - if (fsp->update_write_time_event) { - /* - * No point - an event is already scheduled. - */ - return; - } + TALLOC_FREE(fsp->update_write_time_event); + DEBUG(5, ("Update write time immediate on %s\n", fsp->fsp_name)); + + fsp->update_write_time_triggered = true; - fsp->update_write_time_on_close = true; + fsp->update_write_time_on_close = false; update_write_time(fsp); } -- cgit From d39e9e05ed485f93bb2709ec2494dd2c42ea1300 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Sep 2008 22:53:50 +0200 Subject: Fix calculation of useable_space for trans2 and nttrans replies When alignment was in place, we pretended to send more data/params according to the param_offset/param_length and data_offset/data_length parameters than would actually fit into the SMB according to the NBSS length field. (This used to be commit ef3c132b8455c6fe4d0bb9f0be881040a806a4ed) --- source3/smbd/nttrans.c | 22 ++++++++++------------ source3/smbd/trans2.c | 15 +++++++++------ 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b6951272d7..567c428bb8 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -91,14 +91,11 @@ void send_nt_replies(connection_struct *conn, + alignment_offset + data_alignment_offset); - /* - * useable_space can never be more than max_send minus the - * alignment offset. - */ - - useable_space = MIN(useable_space, - max_send - (alignment_offset+data_alignment_offset)); - + if (useable_space < 0) { + DEBUG(0, ("send_nt_replies failed sanity useable_space " + "= %d!!!", useable_space)); + exit_server_cleanly("send_nt_replies: srv_send_smb failed."); + } while (params_to_send || data_to_send) { @@ -106,8 +103,7 @@ void send_nt_replies(connection_struct *conn, * Calculate whether we will totally or partially fill this packet. */ - total_sent_thistime = params_to_send + data_to_send + - alignment_offset + data_alignment_offset; + total_sent_thistime = params_to_send + data_to_send; /* * We can never send more than useable_space. @@ -115,7 +111,9 @@ void send_nt_replies(connection_struct *conn, total_sent_thistime = MIN(total_sent_thistime, useable_space); - reply_outbuf(req, 18, total_sent_thistime); + reply_outbuf(req, 18, + total_sent_thistime + alignment_offset + + data_alignment_offset); /* * Set total params and data to be sent. @@ -242,7 +240,7 @@ void send_nt_replies(connection_struct *conn, if(params_to_send < 0 || data_to_send < 0) { DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!", params_to_send, data_to_send)); - return; + exit_server_cleanly("send_nt_replies: internal error"); } } } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8d839b66b3..3c1753354b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -744,14 +744,16 @@ void send_trans2_replies(connection_struct *conn, + alignment_offset + data_alignment_offset); - /* useable_space can never be more than max_send minus the alignment offset. */ - - useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset)); + if (useable_space < 0) { + DEBUG(0, ("send_trans2_replies failed sanity useable_space " + "= %d!!!", useable_space)); + exit_server_cleanly("send_trans2_replies: Not enough space"); + } while (params_to_send || data_to_send) { /* Calculate whether we will totally or partially fill this packet */ - total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset; + total_sent_thistime = params_to_send + data_to_send; /* We can never send more than useable_space */ /* @@ -761,9 +763,10 @@ void send_trans2_replies(connection_struct *conn, * are sent here. Fix from Marc_Jacobsen@hp.com. */ - total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset); + total_sent_thistime = MIN(total_sent_thistime, useable_space); - reply_outbuf(req, 10, total_sent_thistime); + reply_outbuf(req, 10, total_sent_thistime + alignment_offset + + data_alignment_offset); /* Set total params and data to be sent */ SSVAL(req->outbuf,smb_tprcnt,paramsize); -- cgit From 0b31c97e8267c70b6fa812d5d2783eb966b6bdca Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Sep 2008 14:43:20 +0200 Subject: Add some debug to reply_nttrans (This used to be commit 23e9fed28cf9998534b3c55f4b20a562da507552) --- source3/smbd/nttrans.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 567c428bb8..584399c86c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2582,6 +2582,17 @@ void reply_nttrans(struct smb_request *req) state->setup = NULL; state->call = function_code; + DEBUG(10, ("num_setup=%u, " + "param_total=%u, this_param=%u, max_param=%u, " + "data_total=%u, this_data=%u, max_data=%u, " + "param_offset=%u, data_offset=%u\n", + (unsigned)state->setup_count, + (unsigned)state->total_param, (unsigned)pscnt, + (unsigned)state->max_param_return, + (unsigned)state->total_data, (unsigned)dscnt, + (unsigned)state->max_data_return, + (unsigned)psoff, (unsigned)dsoff)); + /* * All nttrans messages we handle have smb_wct == 19 + * state->setup_count. Ensure this is so as a sanity check. -- cgit From cb40b1ae83cf689e95e03f2d2d3fccc666dc4472 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Sep 2008 14:54:25 -0700 Subject: When requesting UNIX info levels on findfirst/findnext, don't play games with write time, just return what the underlying filesystem says. Trying not to confuse UNIX apps any more than necessary. Jeremy. (This used to be commit b81a4dd003957a611ea190979d828b75d07a1f80) --- source3/smbd/trans2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 3c1753354b..2e2da5cc71 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1945,6 +1945,8 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", break; case SMB_FIND_FILE_UNIX: case SMB_FIND_FILE_UNIX_INFO2: + /* Always use filesystem for UNIX mtime query. */ + ask_sharemode = false; if (!lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; @@ -2302,6 +2304,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", break; case SMB_FIND_FILE_UNIX: case SMB_FIND_FILE_UNIX_INFO2: + /* Always use filesystem for UNIX mtime query. */ + ask_sharemode = false; if (!lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; @@ -4148,7 +4152,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } - if (!null_timespec(write_time_ts)) { + if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) { mtime_ts = write_time_ts; } -- cgit From 5f3160ce274cbe1832155012caaa90ccc77459f6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 10 Sep 2008 16:22:51 -0700 Subject: Fix bug #5052 - not work cancel inheritance on share. We were using the parent security descriptor type and flags instead of using the passed in SD. Jeremy. (This used to be commit 0d824d7188518aaa7b4e890885e6bc42e94397c5) --- source3/smbd/posix_acls.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 427cfc9a0d..7479aea076 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3398,10 +3398,17 @@ static NTSTATUS append_parent_acl(files_struct *fsp, parent_name)); } - parent_sd->dacl->aces = new_ace; - parent_sd->dacl->num_aces = i; + /* This sucks. psd should be const and we should + * be doing a deep-copy here. We're getting away + * with is as we know parent_sd is talloced off + * talloc_tos() as well as psd. JRA. */ - *pp_new_sd = parent_sd; + psd->dacl->aces = new_ace; + psd->dacl->num_aces = i; + psd->type &= ~(SE_DESC_DACL_AUTO_INHERITED| + SE_DESC_DACL_AUTO_INHERIT_REQ); + + *pp_new_sd = psd; return status; } -- cgit From c7b75de96269e55f07a3e788e5c99067e291e069 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Sep 2008 15:03:05 -0700 Subject: Modify a comment to make things clearer. Jeremy. (This used to be commit 9d55ca85ffc73e3fa5fb9895fbcb1ee22f4e320d) --- source3/smbd/fileio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 095841825a..60aeeef1e2 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -204,7 +204,9 @@ void trigger_write_time_update(struct files_struct *fsp) if (fsp->update_write_time_triggered) { /* - * No point - an event is already scheduled. + * We only update the write time + * on the first write. After that + * no other writes affect this. */ return; } -- cgit